diff -druNp linux-libre-2.6.37-gnu1/arch/alpha/include/asm/ioctls.h linux-libre-2.6.38-gnu1/arch/alpha/include/asm/ioctls.h
--- linux-libre-2.6.37-gnu1/arch/alpha/include/asm/ioctls.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/alpha/include/asm/ioctls.h	2011-03-14 21:20:32.000000000 -0400
@@ -92,6 +92,7 @@
 #define TIOCGSID	0x5429  /* Return the session ID of FD */
 #define TIOCGPTN	_IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
 #define TIOCSPTLCK	_IOW('T',0x31, int)  /* Lock/unlock Pty */
+#define TIOCGDEV	_IOR('T',0x32, unsigned int) /* Get primary device node of /dev/console */
 #define TIOCSIG		_IOW('T',0x36, int)  /* Generate signal on Pty slave */
 
 #define TIOCSERCONFIG	0x5453
diff -druNp linux-libre-2.6.37-gnu1/arch/alpha/include/asm/io.h linux-libre-2.6.38-gnu1/arch/alpha/include/asm/io.h
--- linux-libre-2.6.37-gnu1/arch/alpha/include/asm/io.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/alpha/include/asm/io.h	2011-03-14 21:20:32.000000000 -0400
@@ -37,8 +37,9 @@
  */
 extern inline void __set_hae(unsigned long new_hae)
 {
-	unsigned long flags;
-	local_irq_save(flags);
+	unsigned long flags = swpipl(IPL_MAX);
+
+	barrier();
 
 	alpha_mv.hae_cache = new_hae;
 	*alpha_mv.hae_register = new_hae;
@@ -46,7 +47,8 @@ extern inline void __set_hae(unsigned lo
 	/* Re-read to make sure it was written.  */
 	new_hae = *alpha_mv.hae_register;
 
-	local_irq_restore(flags);
+	setipl(flags);
+	barrier();
 }
 
 extern inline void set_hae(unsigned long new_hae)
diff -druNp linux-libre-2.6.37-gnu1/arch/alpha/include/asm/mman.h linux-libre-2.6.38-gnu1/arch/alpha/include/asm/mman.h
--- linux-libre-2.6.37-gnu1/arch/alpha/include/asm/mman.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/alpha/include/asm/mman.h	2011-03-14 21:20:32.000000000 -0400
@@ -53,6 +53,9 @@
 #define MADV_MERGEABLE   12		/* KSM may merge identical pages */
 #define MADV_UNMERGEABLE 13		/* KSM may not merge identical pages */
 
+#define MADV_HUGEPAGE	14		/* Worth backing with hugepages */
+#define MADV_NOHUGEPAGE	15		/* Not worth backing with hugepages */
+
 /* compatibility flags */
 #define MAP_FILE	0
 
diff -druNp linux-libre-2.6.37-gnu1/arch/alpha/include/asm/perf_event.h linux-libre-2.6.38-gnu1/arch/alpha/include/asm/perf_event.h
--- linux-libre-2.6.37-gnu1/arch/alpha/include/asm/perf_event.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/alpha/include/asm/perf_event.h	2011-03-14 21:20:32.000000000 -0400
@@ -1,10 +1,4 @@
 #ifndef __ASM_ALPHA_PERF_EVENT_H
 #define __ASM_ALPHA_PERF_EVENT_H
 
-#ifdef CONFIG_PERF_EVENTS
-extern void init_hw_perf_events(void);
-#else
-static inline void init_hw_perf_events(void)    { }
-#endif
-
 #endif /* __ASM_ALPHA_PERF_EVENT_H */
diff -druNp linux-libre-2.6.37-gnu1/arch/alpha/Kconfig linux-libre-2.6.38-gnu1/arch/alpha/Kconfig
--- linux-libre-2.6.37-gnu1/arch/alpha/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/alpha/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -8,6 +8,10 @@ config ALPHA
 	select HAVE_IRQ_WORK
 	select HAVE_PERF_EVENTS
 	select HAVE_DMA_ATTRS
+	select HAVE_GENERIC_HARDIRQS
+	select GENERIC_IRQ_PROBE
+	select AUTO_IRQ_AFFINITY if SMP
+	select GENERIC_HARDIRQS_NO_DEPRECATED
 	help
 	  The Alpha is a 64-bit general-purpose processor designed and
 	  marketed by the Digital Equipment Corporation of blessed memory,
@@ -68,19 +72,6 @@ config GENERIC_IOMAP
 	bool
 	default n
 
-config GENERIC_HARDIRQS
-	bool
-	default y
-
-config GENERIC_IRQ_PROBE
-	bool
-	default y
-
-config AUTO_IRQ_AFFINITY
-	bool
-	depends on SMP
-	default y
-
 source "init/Kconfig"
 source "kernel/Kconfig.freezer"
 
diff -druNp linux-libre-2.6.37-gnu1/arch/alpha/kernel/irq_alpha.c linux-libre-2.6.38-gnu1/arch/alpha/kernel/irq_alpha.c
--- linux-libre-2.6.37-gnu1/arch/alpha/kernel/irq_alpha.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/alpha/kernel/irq_alpha.c	2011-03-14 21:20:32.000000000 -0400
@@ -112,8 +112,6 @@ init_IRQ(void)
 	wrent(entInt, 0);
 
 	alpha_mv.init_irq();
-
-	init_hw_perf_events();
 }
 
 /*
@@ -221,30 +219,17 @@ process_mcheck_info(unsigned long vector
  * processed by PALcode, and comes in via entInt vector 1.
  */
 
-static void rtc_enable_disable(unsigned int irq) { }
-static unsigned int rtc_startup(unsigned int irq) { return 0; }
-
 struct irqaction timer_irqaction = {
 	.handler	= timer_interrupt,
 	.flags		= IRQF_DISABLED,
 	.name		= "timer",
 };
 
-static struct irq_chip rtc_irq_type = {
-	.name		= "RTC",
-	.startup	= rtc_startup,
-	.shutdown	= rtc_enable_disable,
-	.enable		= rtc_enable_disable,
-	.disable	= rtc_enable_disable,
-	.ack		= rtc_enable_disable,
-	.end		= rtc_enable_disable,
-};
-
 void __init
 init_rtc_irq(void)
 {
-	irq_desc[RTC_IRQ].status = IRQ_DISABLED;
-	irq_desc[RTC_IRQ].chip = &rtc_irq_type;
+	set_irq_chip_and_handler_name(RTC_IRQ, &no_irq_chip,
+				      handle_simple_irq, "RTC");
 	setup_irq(RTC_IRQ, &timer_irqaction);
 }
 
diff -druNp linux-libre-2.6.37-gnu1/arch/alpha/kernel/irq.c linux-libre-2.6.38-gnu1/arch/alpha/kernel/irq.c
--- linux-libre-2.6.37-gnu1/arch/alpha/kernel/irq.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/alpha/kernel/irq.c	2011-03-14 21:20:32.000000000 -0400
@@ -44,10 +44,16 @@ static char irq_user_affinity[NR_IRQS];
 
 int irq_select_affinity(unsigned int irq)
 {
+	struct irq_data *data = irq_get_irq_data(irq);
+	struct irq_chip *chip;
 	static int last_cpu;
 	int cpu = last_cpu + 1;
 
-	if (!irq_desc[irq].chip->set_affinity || irq_user_affinity[irq])
+	if (!data)
+		return 1;
+	chip = irq_data_get_irq_chip(data);
+
+	if (!chip->irq_set_affinity || irq_user_affinity[irq])
 		return 1;
 
 	while (!cpu_possible(cpu) ||
@@ -55,8 +61,8 @@ int irq_select_affinity(unsigned int irq
 		cpu = (cpu < (NR_CPUS-1) ? cpu + 1 : 0);
 	last_cpu = cpu;
 
-	cpumask_copy(irq_desc[irq].affinity, cpumask_of(cpu));
-	irq_desc[irq].chip->set_affinity(irq, cpumask_of(cpu));
+	cpumask_copy(data->affinity, cpumask_of(cpu));
+	chip->irq_set_affinity(data, cpumask_of(cpu), false);
 	return 0;
 }
 #endif /* CONFIG_SMP */
@@ -67,6 +73,7 @@ show_interrupts(struct seq_file *p, void
 	int j;
 	int irq = *(loff_t *) v;
 	struct irqaction * action;
+	struct irq_desc *desc;
 	unsigned long flags;
 
 #ifdef CONFIG_SMP
@@ -79,8 +86,13 @@ show_interrupts(struct seq_file *p, void
 #endif
 
 	if (irq < ACTUAL_NR_IRQS) {
-		raw_spin_lock_irqsave(&irq_desc[irq].lock, flags);
-		action = irq_desc[irq].action;
+		desc = irq_to_desc(irq);
+
+		if (!desc)
+			return 0;
+
+		raw_spin_lock_irqsave(&desc->lock, flags);
+		action = desc->action;
 		if (!action) 
 			goto unlock;
 		seq_printf(p, "%3d: ", irq);
@@ -90,7 +102,7 @@ show_interrupts(struct seq_file *p, void
 		for_each_online_cpu(j)
 			seq_printf(p, "%10u ", kstat_irqs_cpu(irq, j));
 #endif
-		seq_printf(p, " %14s", irq_desc[irq].chip->name);
+		seq_printf(p, " %14s", get_irq_desc_chip(desc)->name);
 		seq_printf(p, "  %c%s",
 			(action->flags & IRQF_DISABLED)?'+':' ',
 			action->name);
@@ -103,7 +115,7 @@ show_interrupts(struct seq_file *p, void
 
 		seq_putc(p, '\n');
 unlock:
-		raw_spin_unlock_irqrestore(&irq_desc[irq].lock, flags);
+		raw_spin_unlock_irqrestore(&desc->lock, flags);
 	} else if (irq == ACTUAL_NR_IRQS) {
 #ifdef CONFIG_SMP
 		seq_puts(p, "IPI: ");
@@ -142,8 +154,10 @@ handle_irq(int irq)
 	 * handled by some other CPU. (or is disabled)
 	 */
 	static unsigned int illegal_count=0;
+	struct irq_desc *desc = irq_to_desc(irq);
 	
-	if ((unsigned) irq > ACTUAL_NR_IRQS && illegal_count < MAX_ILLEGAL_IRQS ) {
+	if (!desc || ((unsigned) irq > ACTUAL_NR_IRQS &&
+	    illegal_count < MAX_ILLEGAL_IRQS)) {
 		irq_err_count++;
 		illegal_count++;
 		printk(KERN_CRIT "device_interrupt: invalid interrupt %d\n",
@@ -151,14 +165,14 @@ handle_irq(int irq)
 		return;
 	}
 
-	irq_enter();
 	/*
-	 * __do_IRQ() must be called with IPL_MAX. Note that we do not
+	 * From here we must proceed with IPL_MAX. Note that we do not
 	 * explicitly enable interrupts afterwards - some MILO PALcode
 	 * (namely LX164 one) seems to have severe problems with RTI
 	 * at IPL 0.
 	 */
 	local_irq_disable();
-	__do_IRQ(irq);
+	irq_enter();
+	generic_handle_irq_desc(irq, desc);
 	irq_exit();
 }
diff -druNp linux-libre-2.6.37-gnu1/arch/alpha/kernel/irq_i8259.c linux-libre-2.6.38-gnu1/arch/alpha/kernel/irq_i8259.c
--- linux-libre-2.6.37-gnu1/arch/alpha/kernel/irq_i8259.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/alpha/kernel/irq_i8259.c	2011-03-14 21:20:32.000000000 -0400
@@ -33,10 +33,10 @@ i8259_update_irq_hw(unsigned int irq, un
 }
 
 inline void
-i8259a_enable_irq(unsigned int irq)
+i8259a_enable_irq(struct irq_data *d)
 {
 	spin_lock(&i8259_irq_lock);
-	i8259_update_irq_hw(irq, cached_irq_mask &= ~(1 << irq));
+	i8259_update_irq_hw(d->irq, cached_irq_mask &= ~(1 << d->irq));
 	spin_unlock(&i8259_irq_lock);
 }
 
@@ -47,16 +47,18 @@ __i8259a_disable_irq(unsigned int irq)
 }
 
 void
-i8259a_disable_irq(unsigned int irq)
+i8259a_disable_irq(struct irq_data *d)
 {
 	spin_lock(&i8259_irq_lock);
-	__i8259a_disable_irq(irq);
+	__i8259a_disable_irq(d->irq);
 	spin_unlock(&i8259_irq_lock);
 }
 
 void
-i8259a_mask_and_ack_irq(unsigned int irq)
+i8259a_mask_and_ack_irq(struct irq_data *d)
 {
+	unsigned int irq = d->irq;
+
 	spin_lock(&i8259_irq_lock);
 	__i8259a_disable_irq(irq);
 
@@ -69,28 +71,11 @@ i8259a_mask_and_ack_irq(unsigned int irq
 	spin_unlock(&i8259_irq_lock);
 }
 
-unsigned int
-i8259a_startup_irq(unsigned int irq)
-{
-	i8259a_enable_irq(irq);
-	return 0; /* never anything pending */
-}
-
-void
-i8259a_end_irq(unsigned int irq)
-{
-	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
-		i8259a_enable_irq(irq);
-}
-
 struct irq_chip i8259a_irq_type = {
 	.name		= "XT-PIC",
-	.startup	= i8259a_startup_irq,
-	.shutdown	= i8259a_disable_irq,
-	.enable		= i8259a_enable_irq,
-	.disable	= i8259a_disable_irq,
-	.ack		= i8259a_mask_and_ack_irq,
-	.end		= i8259a_end_irq,
+	.irq_unmask	= i8259a_enable_irq,
+	.irq_mask	= i8259a_disable_irq,
+	.irq_mask_ack	= i8259a_mask_and_ack_irq,
 };
 
 void __init
@@ -107,8 +92,7 @@ init_i8259a_irqs(void)
 	outb(0xff, 0xA1);	/* mask all of 8259A-2 */
 
 	for (i = 0; i < 16; i++) {
-		irq_desc[i].status = IRQ_DISABLED;
-		irq_desc[i].chip = &i8259a_irq_type;
+		set_irq_chip_and_handler(i, &i8259a_irq_type, handle_level_irq);
 	}
 
 	setup_irq(2, &cascade);
diff -druNp linux-libre-2.6.37-gnu1/arch/alpha/kernel/irq_impl.h linux-libre-2.6.38-gnu1/arch/alpha/kernel/irq_impl.h
--- linux-libre-2.6.37-gnu1/arch/alpha/kernel/irq_impl.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/alpha/kernel/irq_impl.h	2011-03-14 21:20:32.000000000 -0400
@@ -31,11 +31,9 @@ extern void init_rtc_irq(void);
 
 extern void common_init_isa_dma(void);
 
-extern void i8259a_enable_irq(unsigned int);
-extern void i8259a_disable_irq(unsigned int);
-extern void i8259a_mask_and_ack_irq(unsigned int);
-extern unsigned int i8259a_startup_irq(unsigned int);
-extern void i8259a_end_irq(unsigned int);
+extern void i8259a_enable_irq(struct irq_data *d);
+extern void i8259a_disable_irq(struct irq_data *d);
+extern void i8259a_mask_and_ack_irq(struct irq_data *d);
 extern struct irq_chip i8259a_irq_type;
 extern void init_i8259a_irqs(void);
 
diff -druNp linux-libre-2.6.37-gnu1/arch/alpha/kernel/irq_pyxis.c linux-libre-2.6.38-gnu1/arch/alpha/kernel/irq_pyxis.c
--- linux-libre-2.6.37-gnu1/arch/alpha/kernel/irq_pyxis.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/alpha/kernel/irq_pyxis.c	2011-03-14 21:20:32.000000000 -0400
@@ -29,35 +29,21 @@ pyxis_update_irq_hw(unsigned long mask)
 }
 
 static inline void
-pyxis_enable_irq(unsigned int irq)
-{
-	pyxis_update_irq_hw(cached_irq_mask |= 1UL << (irq - 16));
-}
-
-static void
-pyxis_disable_irq(unsigned int irq)
-{
-	pyxis_update_irq_hw(cached_irq_mask &= ~(1UL << (irq - 16)));
-}
-
-static unsigned int
-pyxis_startup_irq(unsigned int irq)
+pyxis_enable_irq(struct irq_data *d)
 {
-	pyxis_enable_irq(irq);
-	return 0;
+	pyxis_update_irq_hw(cached_irq_mask |= 1UL << (d->irq - 16));
 }
 
 static void
-pyxis_end_irq(unsigned int irq)
+pyxis_disable_irq(struct irq_data *d)
 {
-	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
-		pyxis_enable_irq(irq);
+	pyxis_update_irq_hw(cached_irq_mask &= ~(1UL << (d->irq - 16)));
 }
 
 static void
-pyxis_mask_and_ack_irq(unsigned int irq)
+pyxis_mask_and_ack_irq(struct irq_data *d)
 {
-	unsigned long bit = 1UL << (irq - 16);
+	unsigned long bit = 1UL << (d->irq - 16);
 	unsigned long mask = cached_irq_mask &= ~bit;
 
 	/* Disable the interrupt.  */
@@ -72,12 +58,9 @@ pyxis_mask_and_ack_irq(unsigned int irq)
 
 static struct irq_chip pyxis_irq_type = {
 	.name		= "PYXIS",
-	.startup	= pyxis_startup_irq,
-	.shutdown	= pyxis_disable_irq,
-	.enable		= pyxis_enable_irq,
-	.disable	= pyxis_disable_irq,
-	.ack		= pyxis_mask_and_ack_irq,
-	.end		= pyxis_end_irq,
+	.irq_mask_ack	= pyxis_mask_and_ack_irq,
+	.irq_mask	= pyxis_disable_irq,
+	.irq_unmask	= pyxis_enable_irq,
 };
 
 void 
@@ -119,8 +102,8 @@ init_pyxis_irqs(unsigned long ignore_mas
 	for (i = 16; i < 48; ++i) {
 		if ((ignore_mask >> i) & 1)
 			continue;
-		irq_desc[i].status = IRQ_DISABLED | IRQ_LEVEL;
-		irq_desc[i].chip = &pyxis_irq_type;
+		set_irq_chip_and_handler(i, &pyxis_irq_type, handle_level_irq);
+		irq_set_status_flags(i, IRQ_LEVEL);
 	}
 
 	setup_irq(16+7, &isa_cascade_irqaction);
diff -druNp linux-libre-2.6.37-gnu1/arch/alpha/kernel/irq_srm.c linux-libre-2.6.38-gnu1/arch/alpha/kernel/irq_srm.c
--- linux-libre-2.6.37-gnu1/arch/alpha/kernel/irq_srm.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/alpha/kernel/irq_srm.c	2011-03-14 21:20:32.000000000 -0400
@@ -18,44 +18,27 @@
 DEFINE_SPINLOCK(srm_irq_lock);
 
 static inline void
-srm_enable_irq(unsigned int irq)
+srm_enable_irq(struct irq_data *d)
 {
 	spin_lock(&srm_irq_lock);
-	cserve_ena(irq - 16);
+	cserve_ena(d->irq - 16);
 	spin_unlock(&srm_irq_lock);
 }
 
 static void
-srm_disable_irq(unsigned int irq)
+srm_disable_irq(struct irq_data *d)
 {
 	spin_lock(&srm_irq_lock);
-	cserve_dis(irq - 16);
+	cserve_dis(d->irq - 16);
 	spin_unlock(&srm_irq_lock);
 }
 
-static unsigned int
-srm_startup_irq(unsigned int irq)
-{
-	srm_enable_irq(irq);
-	return 0;
-}
-
-static void
-srm_end_irq(unsigned int irq)
-{
-	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
-		srm_enable_irq(irq);
-}
-
 /* Handle interrupts from the SRM, assuming no additional weirdness.  */
 static struct irq_chip srm_irq_type = {
 	.name		= "SRM",
-	.startup	= srm_startup_irq,
-	.shutdown	= srm_disable_irq,
-	.enable		= srm_enable_irq,
-	.disable	= srm_disable_irq,
-	.ack		= srm_disable_irq,
-	.end		= srm_end_irq,
+	.irq_unmask	= srm_enable_irq,
+	.irq_mask	= srm_disable_irq,
+	.irq_mask_ack	= srm_disable_irq,
 };
 
 void __init
@@ -68,8 +51,8 @@ init_srm_irqs(long max, unsigned long ig
 	for (i = 16; i < max; ++i) {
 		if (i < 64 && ((ignore_mask >> i) & 1))
 			continue;
-		irq_desc[i].status = IRQ_DISABLED | IRQ_LEVEL;
-		irq_desc[i].chip = &srm_irq_type;
+		set_irq_chip_and_handler(i, &srm_irq_type, handle_level_irq);
+		irq_set_status_flags(i, IRQ_LEVEL);
 	}
 }
 
diff -druNp linux-libre-2.6.37-gnu1/arch/alpha/kernel/Makefile linux-libre-2.6.38-gnu1/arch/alpha/kernel/Makefile
--- linux-libre-2.6.37-gnu1/arch/alpha/kernel/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/alpha/kernel/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -3,8 +3,8 @@
 #
 
 extra-y		:= head.o vmlinux.lds
-EXTRA_AFLAGS	:= $(KBUILD_CFLAGS)
-EXTRA_CFLAGS	:= -Werror -Wno-sign-compare
+asflags-y	:= $(KBUILD_CFLAGS)
+ccflags-y	:= -Werror -Wno-sign-compare
 
 obj-y    := entry.o traps.o process.o init_task.o osf_sys.o irq.o \
 	    irq_alpha.o signal.o setup.o ptrace.o time.o \
diff -druNp linux-libre-2.6.37-gnu1/arch/alpha/kernel/osf_sys.c linux-libre-2.6.38-gnu1/arch/alpha/kernel/osf_sys.c
--- linux-libre-2.6.37-gnu1/arch/alpha/kernel/osf_sys.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/alpha/kernel/osf_sys.c	2011-03-14 21:20:32.000000000 -0400
@@ -951,9 +951,6 @@ SYSCALL_DEFINE2(osf_utimes, const char _
 	return do_utimes(AT_FDCWD, filename, tvs ? tv : NULL, 0);
 }
 
-#define MAX_SELECT_SECONDS \
-	((unsigned long) (MAX_SCHEDULE_TIMEOUT / HZ)-1)
-
 SYSCALL_DEFINE5(osf_select, int, n, fd_set __user *, inp, fd_set __user *, outp,
 		fd_set __user *, exp, struct timeval32 __user *, tvp)
 {
diff -druNp linux-libre-2.6.37-gnu1/arch/alpha/kernel/perf_event.c linux-libre-2.6.38-gnu1/arch/alpha/kernel/perf_event.c
--- linux-libre-2.6.37-gnu1/arch/alpha/kernel/perf_event.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/alpha/kernel/perf_event.c	2011-03-14 21:20:32.000000000 -0400
@@ -14,6 +14,7 @@
 #include <linux/kernel.h>
 #include <linux/kdebug.h>
 #include <linux/mutex.h>
+#include <linux/init.h>
 
 #include <asm/hwrpb.h>
 #include <asm/atomic.h>
@@ -863,13 +864,13 @@ static void alpha_perf_event_irq_handler
 /*
  * Init call to initialise performance events at kernel startup.
  */
-void __init init_hw_perf_events(void)
+int __init init_hw_perf_events(void)
 {
 	pr_info("Performance events: ");
 
 	if (!supported_cpu()) {
 		pr_cont("No support for your CPU.\n");
-		return;
+		return 0;
 	}
 
 	pr_cont("Supported CPU type!\n");
@@ -881,6 +882,8 @@ void __init init_hw_perf_events(void)
 	/* And set up PMU specification */
 	alpha_pmu = &ev67_pmu;
 
-	perf_pmu_register(&pmu);
-}
+	perf_pmu_register(&pmu, "cpu", PERF_TYPE_RAW);
 
+	return 0;
+}
+early_initcall(init_hw_perf_events);
diff -druNp linux-libre-2.6.37-gnu1/arch/alpha/kernel/sys_alcor.c linux-libre-2.6.38-gnu1/arch/alpha/kernel/sys_alcor.c
--- linux-libre-2.6.37-gnu1/arch/alpha/kernel/sys_alcor.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/alpha/kernel/sys_alcor.c	2011-03-14 21:20:32.000000000 -0400
@@ -44,59 +44,42 @@ alcor_update_irq_hw(unsigned long mask)
 }
 
 static inline void
-alcor_enable_irq(unsigned int irq)
+alcor_enable_irq(struct irq_data *d)
 {
-	alcor_update_irq_hw(cached_irq_mask |= 1UL << (irq - 16));
+	alcor_update_irq_hw(cached_irq_mask |= 1UL << (d->irq - 16));
 }
 
 static void
-alcor_disable_irq(unsigned int irq)
+alcor_disable_irq(struct irq_data *d)
 {
-	alcor_update_irq_hw(cached_irq_mask &= ~(1UL << (irq - 16)));
+	alcor_update_irq_hw(cached_irq_mask &= ~(1UL << (d->irq - 16)));
 }
 
 static void
-alcor_mask_and_ack_irq(unsigned int irq)
+alcor_mask_and_ack_irq(struct irq_data *d)
 {
-	alcor_disable_irq(irq);
+	alcor_disable_irq(d);
 
 	/* On ALCOR/XLT, need to dismiss interrupt via GRU. */
-	*(vuip)GRU_INT_CLEAR = 1 << (irq - 16); mb();
+	*(vuip)GRU_INT_CLEAR = 1 << (d->irq - 16); mb();
 	*(vuip)GRU_INT_CLEAR = 0; mb();
 }
 
-static unsigned int
-alcor_startup_irq(unsigned int irq)
-{
-	alcor_enable_irq(irq);
-	return 0;
-}
-
 static void
-alcor_isa_mask_and_ack_irq(unsigned int irq)
+alcor_isa_mask_and_ack_irq(struct irq_data *d)
 {
-	i8259a_mask_and_ack_irq(irq);
+	i8259a_mask_and_ack_irq(d);
 
 	/* On ALCOR/XLT, need to dismiss interrupt via GRU. */
 	*(vuip)GRU_INT_CLEAR = 0x80000000; mb();
 	*(vuip)GRU_INT_CLEAR = 0; mb();
 }
 
-static void
-alcor_end_irq(unsigned int irq)
-{
-	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
-		alcor_enable_irq(irq);
-}
-
 static struct irq_chip alcor_irq_type = {
 	.name		= "ALCOR",
-	.startup	= alcor_startup_irq,
-	.shutdown	= alcor_disable_irq,
-	.enable		= alcor_enable_irq,
-	.disable	= alcor_disable_irq,
-	.ack		= alcor_mask_and_ack_irq,
-	.end		= alcor_end_irq,
+	.irq_unmask	= alcor_enable_irq,
+	.irq_mask	= alcor_disable_irq,
+	.irq_mask_ack	= alcor_mask_and_ack_irq,
 };
 
 static void
@@ -142,10 +125,10 @@ alcor_init_irq(void)
 		   on while IRQ probing.  */
 		if (i >= 16+20 && i <= 16+30)
 			continue;
-		irq_desc[i].status = IRQ_DISABLED | IRQ_LEVEL;
-		irq_desc[i].chip = &alcor_irq_type;
+		set_irq_chip_and_handler(i, &alcor_irq_type, handle_level_irq);
+		irq_set_status_flags(i, IRQ_LEVEL);
 	}
-	i8259a_irq_type.ack = alcor_isa_mask_and_ack_irq;
+	i8259a_irq_type.irq_ack = alcor_isa_mask_and_ack_irq;
 
 	init_i8259a_irqs();
 	common_init_isa_dma();
diff -druNp linux-libre-2.6.37-gnu1/arch/alpha/kernel/sys_cabriolet.c linux-libre-2.6.38-gnu1/arch/alpha/kernel/sys_cabriolet.c
--- linux-libre-2.6.37-gnu1/arch/alpha/kernel/sys_cabriolet.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/alpha/kernel/sys_cabriolet.c	2011-03-14 21:20:32.000000000 -0400
@@ -46,39 +46,22 @@ cabriolet_update_irq_hw(unsigned int irq
 }
 
 static inline void
-cabriolet_enable_irq(unsigned int irq)
+cabriolet_enable_irq(struct irq_data *d)
 {
-	cabriolet_update_irq_hw(irq, cached_irq_mask &= ~(1UL << irq));
+	cabriolet_update_irq_hw(d->irq, cached_irq_mask &= ~(1UL << d->irq));
 }
 
 static void
-cabriolet_disable_irq(unsigned int irq)
+cabriolet_disable_irq(struct irq_data *d)
 {
-	cabriolet_update_irq_hw(irq, cached_irq_mask |= 1UL << irq);
-}
-
-static unsigned int
-cabriolet_startup_irq(unsigned int irq)
-{ 
-	cabriolet_enable_irq(irq);
-	return 0; /* never anything pending */
-}
-
-static void
-cabriolet_end_irq(unsigned int irq)
-{ 
-	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
-		cabriolet_enable_irq(irq);
+	cabriolet_update_irq_hw(d->irq, cached_irq_mask |= 1UL << d->irq);
 }
 
 static struct irq_chip cabriolet_irq_type = {
 	.name		= "CABRIOLET",
-	.startup	= cabriolet_startup_irq,
-	.shutdown	= cabriolet_disable_irq,
-	.enable		= cabriolet_enable_irq,
-	.disable	= cabriolet_disable_irq,
-	.ack		= cabriolet_disable_irq,
-	.end		= cabriolet_end_irq,
+	.irq_unmask	= cabriolet_enable_irq,
+	.irq_mask	= cabriolet_disable_irq,
+	.irq_mask_ack	= cabriolet_disable_irq,
 };
 
 static void 
@@ -122,8 +105,9 @@ common_init_irq(void (*srm_dev_int)(unsi
 		outb(0xff, 0x806);
 
 		for (i = 16; i < 35; ++i) {
-			irq_desc[i].status = IRQ_DISABLED | IRQ_LEVEL;
-			irq_desc[i].chip = &cabriolet_irq_type;
+			set_irq_chip_and_handler(i, &cabriolet_irq_type,
+				handle_level_irq);
+			irq_set_status_flags(i, IRQ_LEVEL);
 		}
 	}
 
diff -druNp linux-libre-2.6.37-gnu1/arch/alpha/kernel/sys_dp264.c linux-libre-2.6.38-gnu1/arch/alpha/kernel/sys_dp264.c
--- linux-libre-2.6.37-gnu1/arch/alpha/kernel/sys_dp264.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/alpha/kernel/sys_dp264.c	2011-03-14 21:20:32.000000000 -0400
@@ -98,69 +98,41 @@ tsunami_update_irq_hw(unsigned long mask
 }
 
 static void
-dp264_enable_irq(unsigned int irq)
+dp264_enable_irq(struct irq_data *d)
 {
 	spin_lock(&dp264_irq_lock);
-	cached_irq_mask |= 1UL << irq;
+	cached_irq_mask |= 1UL << d->irq;
 	tsunami_update_irq_hw(cached_irq_mask);
 	spin_unlock(&dp264_irq_lock);
 }
 
 static void
-dp264_disable_irq(unsigned int irq)
+dp264_disable_irq(struct irq_data *d)
 {
 	spin_lock(&dp264_irq_lock);
-	cached_irq_mask &= ~(1UL << irq);
+	cached_irq_mask &= ~(1UL << d->irq);
 	tsunami_update_irq_hw(cached_irq_mask);
 	spin_unlock(&dp264_irq_lock);
 }
 
-static unsigned int
-dp264_startup_irq(unsigned int irq)
-{ 
-	dp264_enable_irq(irq);
-	return 0; /* never anything pending */
-}
-
-static void
-dp264_end_irq(unsigned int irq)
-{ 
-	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
-		dp264_enable_irq(irq);
-}
-
 static void
-clipper_enable_irq(unsigned int irq)
+clipper_enable_irq(struct irq_data *d)
 {
 	spin_lock(&dp264_irq_lock);
-	cached_irq_mask |= 1UL << (irq - 16);
+	cached_irq_mask |= 1UL << (d->irq - 16);
 	tsunami_update_irq_hw(cached_irq_mask);
 	spin_unlock(&dp264_irq_lock);
 }
 
 static void
-clipper_disable_irq(unsigned int irq)
+clipper_disable_irq(struct irq_data *d)
 {
 	spin_lock(&dp264_irq_lock);
-	cached_irq_mask &= ~(1UL << (irq - 16));
+	cached_irq_mask &= ~(1UL << (d->irq - 16));
 	tsunami_update_irq_hw(cached_irq_mask);
 	spin_unlock(&dp264_irq_lock);
 }
 
-static unsigned int
-clipper_startup_irq(unsigned int irq)
-{ 
-	clipper_enable_irq(irq);
-	return 0; /* never anything pending */
-}
-
-static void
-clipper_end_irq(unsigned int irq)
-{ 
-	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
-		clipper_enable_irq(irq);
-}
-
 static void
 cpu_set_irq_affinity(unsigned int irq, cpumask_t affinity)
 {
@@ -177,10 +149,11 @@ cpu_set_irq_affinity(unsigned int irq, c
 }
 
 static int
-dp264_set_affinity(unsigned int irq, const struct cpumask *affinity)
-{ 
+dp264_set_affinity(struct irq_data *d, const struct cpumask *affinity,
+		   bool force)
+{
 	spin_lock(&dp264_irq_lock);
-	cpu_set_irq_affinity(irq, *affinity);
+	cpu_set_irq_affinity(d->irq, *affinity);
 	tsunami_update_irq_hw(cached_irq_mask);
 	spin_unlock(&dp264_irq_lock);
 
@@ -188,10 +161,11 @@ dp264_set_affinity(unsigned int irq, con
 }
 
 static int
-clipper_set_affinity(unsigned int irq, const struct cpumask *affinity)
-{ 
+clipper_set_affinity(struct irq_data *d, const struct cpumask *affinity,
+		     bool force)
+{
 	spin_lock(&dp264_irq_lock);
-	cpu_set_irq_affinity(irq - 16, *affinity);
+	cpu_set_irq_affinity(d->irq - 16, *affinity);
 	tsunami_update_irq_hw(cached_irq_mask);
 	spin_unlock(&dp264_irq_lock);
 
@@ -199,25 +173,19 @@ clipper_set_affinity(unsigned int irq, c
 }
 
 static struct irq_chip dp264_irq_type = {
-	.name		= "DP264",
-	.startup	= dp264_startup_irq,
-	.shutdown	= dp264_disable_irq,
-	.enable		= dp264_enable_irq,
-	.disable	= dp264_disable_irq,
-	.ack		= dp264_disable_irq,
-	.end		= dp264_end_irq,
-	.set_affinity	= dp264_set_affinity,
+	.name			= "DP264",
+	.irq_unmask		= dp264_enable_irq,
+	.irq_mask		= dp264_disable_irq,
+	.irq_mask_ack		= dp264_disable_irq,
+	.irq_set_affinity	= dp264_set_affinity,
 };
 
 static struct irq_chip clipper_irq_type = {
-	.name		= "CLIPPER",
-	.startup	= clipper_startup_irq,
-	.shutdown	= clipper_disable_irq,
-	.enable		= clipper_enable_irq,
-	.disable	= clipper_disable_irq,
-	.ack		= clipper_disable_irq,
-	.end		= clipper_end_irq,
-	.set_affinity	= clipper_set_affinity,
+	.name			= "CLIPPER",
+	.irq_unmask		= clipper_enable_irq,
+	.irq_mask		= clipper_disable_irq,
+	.irq_mask_ack		= clipper_disable_irq,
+	.irq_set_affinity	= clipper_set_affinity,
 };
 
 static void
@@ -302,8 +270,8 @@ init_tsunami_irqs(struct irq_chip * ops,
 {
 	long i;
 	for (i = imin; i <= imax; ++i) {
-		irq_desc[i].status = IRQ_DISABLED | IRQ_LEVEL;
-		irq_desc[i].chip = ops;
+		set_irq_chip_and_handler(i, ops, handle_level_irq);
+		irq_set_status_flags(i, IRQ_LEVEL);
 	}
 }
 
diff -druNp linux-libre-2.6.37-gnu1/arch/alpha/kernel/sys_eb64p.c linux-libre-2.6.38-gnu1/arch/alpha/kernel/sys_eb64p.c
--- linux-libre-2.6.37-gnu1/arch/alpha/kernel/sys_eb64p.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/alpha/kernel/sys_eb64p.c	2011-03-14 21:20:32.000000000 -0400
@@ -44,39 +44,22 @@ eb64p_update_irq_hw(unsigned int irq, un
 }
 
 static inline void
-eb64p_enable_irq(unsigned int irq)
-{
-	eb64p_update_irq_hw(irq, cached_irq_mask &= ~(1 << irq));
-}
-
-static void
-eb64p_disable_irq(unsigned int irq)
-{
-	eb64p_update_irq_hw(irq, cached_irq_mask |= 1 << irq);
-}
-
-static unsigned int
-eb64p_startup_irq(unsigned int irq)
+eb64p_enable_irq(struct irq_data *d)
 {
-	eb64p_enable_irq(irq);
-	return 0; /* never anything pending */
+	eb64p_update_irq_hw(d->irq, cached_irq_mask &= ~(1 << d->irq));
 }
 
 static void
-eb64p_end_irq(unsigned int irq)
+eb64p_disable_irq(struct irq_data *d)
 {
-	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
-		eb64p_enable_irq(irq);
+	eb64p_update_irq_hw(d->irq, cached_irq_mask |= 1 << d->irq);
 }
 
 static struct irq_chip eb64p_irq_type = {
 	.name		= "EB64P",
-	.startup	= eb64p_startup_irq,
-	.shutdown	= eb64p_disable_irq,
-	.enable		= eb64p_enable_irq,
-	.disable	= eb64p_disable_irq,
-	.ack		= eb64p_disable_irq,
-	.end		= eb64p_end_irq,
+	.irq_unmask	= eb64p_enable_irq,
+	.irq_mask	= eb64p_disable_irq,
+	.irq_mask_ack	= eb64p_disable_irq,
 };
 
 static void 
@@ -135,9 +118,9 @@ eb64p_init_irq(void)
 	init_i8259a_irqs();
 
 	for (i = 16; i < 32; ++i) {
-		irq_desc[i].status = IRQ_DISABLED | IRQ_LEVEL;
-		irq_desc[i].chip = &eb64p_irq_type;
-	}		
+		set_irq_chip_and_handler(i, &eb64p_irq_type, handle_level_irq);
+		irq_set_status_flags(i, IRQ_LEVEL);
+	}
 
 	common_init_isa_dma();
 	setup_irq(16+5, &isa_cascade_irqaction);
diff -druNp linux-libre-2.6.37-gnu1/arch/alpha/kernel/sys_eiger.c linux-libre-2.6.38-gnu1/arch/alpha/kernel/sys_eiger.c
--- linux-libre-2.6.37-gnu1/arch/alpha/kernel/sys_eiger.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/alpha/kernel/sys_eiger.c	2011-03-14 21:20:32.000000000 -0400
@@ -51,43 +51,28 @@ eiger_update_irq_hw(unsigned long irq, u
 }
 
 static inline void
-eiger_enable_irq(unsigned int irq)
+eiger_enable_irq(struct irq_data *d)
 {
+	unsigned int irq = d->irq;
 	unsigned long mask;
 	mask = (cached_irq_mask[irq >= 64] &= ~(1UL << (irq & 63)));
 	eiger_update_irq_hw(irq, mask);
 }
 
 static void
-eiger_disable_irq(unsigned int irq)
+eiger_disable_irq(struct irq_data *d)
 {
+	unsigned int irq = d->irq;
 	unsigned long mask;
 	mask = (cached_irq_mask[irq >= 64] |= 1UL << (irq & 63));
 	eiger_update_irq_hw(irq, mask);
 }
 
-static unsigned int
-eiger_startup_irq(unsigned int irq)
-{
-	eiger_enable_irq(irq);
-	return 0; /* never anything pending */
-}
-
-static void
-eiger_end_irq(unsigned int irq)
-{
-	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
-		eiger_enable_irq(irq);
-}
-
 static struct irq_chip eiger_irq_type = {
 	.name		= "EIGER",
-	.startup	= eiger_startup_irq,
-	.shutdown	= eiger_disable_irq,
-	.enable		= eiger_enable_irq,
-	.disable	= eiger_disable_irq,
-	.ack		= eiger_disable_irq,
-	.end		= eiger_end_irq,
+	.irq_unmask	= eiger_enable_irq,
+	.irq_mask	= eiger_disable_irq,
+	.irq_mask_ack	= eiger_disable_irq,
 };
 
 static void
@@ -153,8 +138,8 @@ eiger_init_irq(void)
 	init_i8259a_irqs();
 
 	for (i = 16; i < 128; ++i) {
-		irq_desc[i].status = IRQ_DISABLED | IRQ_LEVEL;
-		irq_desc[i].chip = &eiger_irq_type;
+		set_irq_chip_and_handler(i, &eiger_irq_type, handle_level_irq);
+		irq_set_status_flags(i, IRQ_LEVEL);
 	}
 }
 
diff -druNp linux-libre-2.6.37-gnu1/arch/alpha/kernel/sys_jensen.c linux-libre-2.6.38-gnu1/arch/alpha/kernel/sys_jensen.c
--- linux-libre-2.6.37-gnu1/arch/alpha/kernel/sys_jensen.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/alpha/kernel/sys_jensen.c	2011-03-14 21:20:32.000000000 -0400
@@ -62,70 +62,35 @@
  * world.
  */
 
-static unsigned int
-jensen_local_startup(unsigned int irq)
-{
-	/* the parport is really hw IRQ 1, silly Jensen.  */
-	if (irq == 7)
-		i8259a_startup_irq(1);
-	else
-		/*
-		 * For all true local interrupts, set the flag that prevents
-		 * the IPL from being dropped during handler processing.
-		 */
-		if (irq_desc[irq].action)
-			irq_desc[irq].action->flags |= IRQF_DISABLED;
-	return 0;
-}
-
-static void
-jensen_local_shutdown(unsigned int irq)
-{
-	/* the parport is really hw IRQ 1, silly Jensen.  */
-	if (irq == 7)
-		i8259a_disable_irq(1);
-}
-
-static void
-jensen_local_enable(unsigned int irq)
-{
-	/* the parport is really hw IRQ 1, silly Jensen.  */
-	if (irq == 7)
-		i8259a_enable_irq(1);
-}
-
 static void
-jensen_local_disable(unsigned int irq)
+jensen_local_enable(struct irq_data *d)
 {
 	/* the parport is really hw IRQ 1, silly Jensen.  */
-	if (irq == 7)
-		i8259a_disable_irq(1);
+	if (d->irq == 7)
+		i8259a_enable_irq(d);
 }
 
 static void
-jensen_local_ack(unsigned int irq)
+jensen_local_disable(struct irq_data *d)
 {
 	/* the parport is really hw IRQ 1, silly Jensen.  */
-	if (irq == 7)
-		i8259a_mask_and_ack_irq(1);
+	if (d->irq == 7)
+		i8259a_disable_irq(d);
 }
 
 static void
-jensen_local_end(unsigned int irq)
+jensen_local_mask_ack(struct irq_data *d)
 {
 	/* the parport is really hw IRQ 1, silly Jensen.  */
-	if (irq == 7)
-		i8259a_end_irq(1);
+	if (d->irq == 7)
+		i8259a_mask_and_ack_irq(d);
 }
 
 static struct irq_chip jensen_local_irq_type = {
 	.name		= "LOCAL",
-	.startup	= jensen_local_startup,
-	.shutdown	= jensen_local_shutdown,
-	.enable		= jensen_local_enable,
-	.disable	= jensen_local_disable,
-	.ack		= jensen_local_ack,
-	.end		= jensen_local_end,
+	.irq_unmask	= jensen_local_enable,
+	.irq_mask	= jensen_local_disable,
+	.irq_mask_ack	= jensen_local_mask_ack,
 };
 
 static void 
@@ -158,7 +123,7 @@ jensen_device_interrupt(unsigned long ve
 	}
 
 	/* If there is no handler yet... */
-	if (irq_desc[irq].action == NULL) {
+	if (!irq_has_action(irq)) {
 	    /* If it is a local interrupt that cannot be masked... */
 	    if (vector >= 0x900)
 	    {
@@ -206,11 +171,11 @@ jensen_init_irq(void)
 {
 	init_i8259a_irqs();
 
-	irq_desc[1].chip = &jensen_local_irq_type;
-	irq_desc[4].chip = &jensen_local_irq_type;
-	irq_desc[3].chip = &jensen_local_irq_type;
-	irq_desc[7].chip = &jensen_local_irq_type;
-	irq_desc[9].chip = &jensen_local_irq_type;
+	set_irq_chip_and_handler(1, &jensen_local_irq_type, handle_level_irq);
+	set_irq_chip_and_handler(4, &jensen_local_irq_type, handle_level_irq);
+	set_irq_chip_and_handler(3, &jensen_local_irq_type, handle_level_irq);
+	set_irq_chip_and_handler(7, &jensen_local_irq_type, handle_level_irq);
+	set_irq_chip_and_handler(9, &jensen_local_irq_type, handle_level_irq);
 
 	common_init_isa_dma();
 }
diff -druNp linux-libre-2.6.37-gnu1/arch/alpha/kernel/sys_marvel.c linux-libre-2.6.38-gnu1/arch/alpha/kernel/sys_marvel.c
--- linux-libre-2.6.37-gnu1/arch/alpha/kernel/sys_marvel.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/alpha/kernel/sys_marvel.c	2011-03-14 21:20:32.000000000 -0400
@@ -104,9 +104,10 @@ io7_get_irq_ctl(unsigned int irq, struct
 }
 
 static void
-io7_enable_irq(unsigned int irq)
+io7_enable_irq(struct irq_data *d)
 {
 	volatile unsigned long *ctl;
+	unsigned int irq = d->irq;
 	struct io7 *io7;
 
 	ctl = io7_get_irq_ctl(irq, &io7);
@@ -115,7 +116,7 @@ io7_enable_irq(unsigned int irq)
 		       __func__, irq);
 		return;
 	}
-		
+
 	spin_lock(&io7->irq_lock);
 	*ctl |= 1UL << 24;
 	mb();
@@ -124,9 +125,10 @@ io7_enable_irq(unsigned int irq)
 }
 
 static void
-io7_disable_irq(unsigned int irq)
+io7_disable_irq(struct irq_data *d)
 {
 	volatile unsigned long *ctl;
+	unsigned int irq = d->irq;
 	struct io7 *io7;
 
 	ctl = io7_get_irq_ctl(irq, &io7);
@@ -135,7 +137,7 @@ io7_disable_irq(unsigned int irq)
 		       __func__, irq);
 		return;
 	}
-		
+
 	spin_lock(&io7->irq_lock);
 	*ctl &= ~(1UL << 24);
 	mb();
@@ -143,60 +145,30 @@ io7_disable_irq(unsigned int irq)
 	spin_unlock(&io7->irq_lock);
 }
 
-static unsigned int
-io7_startup_irq(unsigned int irq)
-{
-	io7_enable_irq(irq);
-	return 0;	/* never anything pending */
-}
-
 static void
-io7_end_irq(unsigned int irq)
+marvel_irq_noop(struct irq_data *d)
 {
-	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
-		io7_enable_irq(irq);
-}
-
-static void
-marvel_irq_noop(unsigned int irq) 
-{ 
-	return; 
-}
-
-static unsigned int
-marvel_irq_noop_return(unsigned int irq) 
-{ 
-	return 0; 
+	return;
 }
 
 static struct irq_chip marvel_legacy_irq_type = {
 	.name		= "LEGACY",
-	.startup	= marvel_irq_noop_return,
-	.shutdown	= marvel_irq_noop,
-	.enable		= marvel_irq_noop,
-	.disable	= marvel_irq_noop,
-	.ack		= marvel_irq_noop,
-	.end		= marvel_irq_noop,
+	.irq_mask	= marvel_irq_noop,
+	.irq_unmask	= marvel_irq_noop,
 };
 
 static struct irq_chip io7_lsi_irq_type = {
 	.name		= "LSI",
-	.startup	= io7_startup_irq,
-	.shutdown	= io7_disable_irq,
-	.enable		= io7_enable_irq,
-	.disable	= io7_disable_irq,
-	.ack		= io7_disable_irq,
-	.end		= io7_end_irq,
+	.irq_unmask	= io7_enable_irq,
+	.irq_mask	= io7_disable_irq,
+	.irq_mask_ack	= io7_disable_irq,
 };
 
 static struct irq_chip io7_msi_irq_type = {
 	.name		= "MSI",
-	.startup	= io7_startup_irq,
-	.shutdown	= io7_disable_irq,
-	.enable		= io7_enable_irq,
-	.disable	= io7_disable_irq,
-	.ack		= marvel_irq_noop,
-	.end		= io7_end_irq,
+	.irq_unmask	= io7_enable_irq,
+	.irq_mask	= io7_disable_irq,
+	.irq_ack	= marvel_irq_noop,
 };
 
 static void
@@ -304,8 +276,8 @@ init_io7_irqs(struct io7 *io7,
 
 	/* Set up the lsi irqs.  */
 	for (i = 0; i < 128; ++i) {
-		irq_desc[base + i].status = IRQ_DISABLED | IRQ_LEVEL;
-		irq_desc[base + i].chip = lsi_ops;
+		set_irq_chip_and_handler(base + i, lsi_ops, handle_level_irq);
+		irq_set_status_flags(i, IRQ_LEVEL);
 	}
 
 	/* Disable the implemented irqs in hardware.  */
@@ -318,8 +290,8 @@ init_io7_irqs(struct io7 *io7,
 
 	/* Set up the msi irqs.  */
 	for (i = 128; i < (128 + 512); ++i) {
-		irq_desc[base + i].status = IRQ_DISABLED | IRQ_LEVEL;
-		irq_desc[base + i].chip = msi_ops;
+		set_irq_chip_and_handler(base + i, msi_ops, handle_level_irq);
+		irq_set_status_flags(i, IRQ_LEVEL);
 	}
 
 	for (i = 0; i < 16; ++i)
@@ -336,8 +308,8 @@ marvel_init_irq(void)
 
 	/* Reserve the legacy irqs.  */
 	for (i = 0; i < 16; ++i) {
-		irq_desc[i].status = IRQ_DISABLED;
-		irq_desc[i].chip = &marvel_legacy_irq_type;
+		set_irq_chip_and_handler(i, &marvel_legacy_irq_type,
+			handle_level_irq);
 	}
 
 	/* Init the io7 irqs.  */
diff -druNp linux-libre-2.6.37-gnu1/arch/alpha/kernel/sys_mikasa.c linux-libre-2.6.38-gnu1/arch/alpha/kernel/sys_mikasa.c
--- linux-libre-2.6.37-gnu1/arch/alpha/kernel/sys_mikasa.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/alpha/kernel/sys_mikasa.c	2011-03-14 21:20:32.000000000 -0400
@@ -43,39 +43,22 @@ mikasa_update_irq_hw(int mask)
 }
 
 static inline void
-mikasa_enable_irq(unsigned int irq)
-{
-	mikasa_update_irq_hw(cached_irq_mask |= 1 << (irq - 16));
-}
-
-static void
-mikasa_disable_irq(unsigned int irq)
-{
-	mikasa_update_irq_hw(cached_irq_mask &= ~(1 << (irq - 16)));
-}
-
-static unsigned int
-mikasa_startup_irq(unsigned int irq)
+mikasa_enable_irq(struct irq_data *d)
 {
-	mikasa_enable_irq(irq);
-	return 0;
+	mikasa_update_irq_hw(cached_irq_mask |= 1 << (d->irq - 16));
 }
 
 static void
-mikasa_end_irq(unsigned int irq)
+mikasa_disable_irq(struct irq_data *d)
 {
-	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
-		mikasa_enable_irq(irq);
+	mikasa_update_irq_hw(cached_irq_mask &= ~(1 << (d->irq - 16)));
 }
 
 static struct irq_chip mikasa_irq_type = {
 	.name		= "MIKASA",
-	.startup	= mikasa_startup_irq,
-	.shutdown	= mikasa_disable_irq,
-	.enable		= mikasa_enable_irq,
-	.disable	= mikasa_disable_irq,
-	.ack		= mikasa_disable_irq,
-	.end		= mikasa_end_irq,
+	.irq_unmask	= mikasa_enable_irq,
+	.irq_mask	= mikasa_disable_irq,
+	.irq_mask_ack	= mikasa_disable_irq,
 };
 
 static void 
@@ -115,8 +98,8 @@ mikasa_init_irq(void)
 	mikasa_update_irq_hw(0);
 
 	for (i = 16; i < 32; ++i) {
-		irq_desc[i].status = IRQ_DISABLED | IRQ_LEVEL;
-		irq_desc[i].chip = &mikasa_irq_type;
+		set_irq_chip_and_handler(i, &mikasa_irq_type, handle_level_irq);
+		irq_set_status_flags(i, IRQ_LEVEL);
 	}
 
 	init_i8259a_irqs();
diff -druNp linux-libre-2.6.37-gnu1/arch/alpha/kernel/sys_noritake.c linux-libre-2.6.38-gnu1/arch/alpha/kernel/sys_noritake.c
--- linux-libre-2.6.37-gnu1/arch/alpha/kernel/sys_noritake.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/alpha/kernel/sys_noritake.c	2011-03-14 21:20:32.000000000 -0400
@@ -48,39 +48,22 @@ noritake_update_irq_hw(int irq, int mask
 }
 
 static void
-noritake_enable_irq(unsigned int irq)
-{
-	noritake_update_irq_hw(irq, cached_irq_mask |= 1 << (irq - 16));
-}
-
-static void
-noritake_disable_irq(unsigned int irq)
-{
-	noritake_update_irq_hw(irq, cached_irq_mask &= ~(1 << (irq - 16)));
-}
-
-static unsigned int
-noritake_startup_irq(unsigned int irq)
+noritake_enable_irq(struct irq_data *d)
 {
-	noritake_enable_irq(irq);
-	return 0;
+	noritake_update_irq_hw(d->irq, cached_irq_mask |= 1 << (d->irq - 16));
 }
 
 static void
-noritake_end_irq(unsigned int irq)
+noritake_disable_irq(struct irq_data *d)
 {
-        if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
-                noritake_enable_irq(irq);
+	noritake_update_irq_hw(d->irq, cached_irq_mask &= ~(1 << (d->irq - 16)));
 }
 
 static struct irq_chip noritake_irq_type = {
 	.name		= "NORITAKE",
-	.startup	= noritake_startup_irq,
-	.shutdown	= noritake_disable_irq,
-	.enable		= noritake_enable_irq,
-	.disable	= noritake_disable_irq,
-	.ack		= noritake_disable_irq,
-	.end		= noritake_end_irq,
+	.irq_unmask	= noritake_enable_irq,
+	.irq_mask	= noritake_disable_irq,
+	.irq_mask_ack	= noritake_disable_irq,
 };
 
 static void 
@@ -144,8 +127,8 @@ noritake_init_irq(void)
 	outw(0, 0x54c);
 
 	for (i = 16; i < 48; ++i) {
-		irq_desc[i].status = IRQ_DISABLED | IRQ_LEVEL;
-		irq_desc[i].chip = &noritake_irq_type;
+		set_irq_chip_and_handler(i, &noritake_irq_type, handle_level_irq);
+		irq_set_status_flags(i, IRQ_LEVEL);
 	}
 
 	init_i8259a_irqs();
diff -druNp linux-libre-2.6.37-gnu1/arch/alpha/kernel/sys_rawhide.c linux-libre-2.6.38-gnu1/arch/alpha/kernel/sys_rawhide.c
--- linux-libre-2.6.37-gnu1/arch/alpha/kernel/sys_rawhide.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/alpha/kernel/sys_rawhide.c	2011-03-14 21:20:32.000000000 -0400
@@ -56,9 +56,10 @@ rawhide_update_irq_hw(int hose, int mask
   (((h) < MCPCIA_MAX_HOSES) && (cached_irq_masks[(h)] != 0))
 
 static inline void 
-rawhide_enable_irq(unsigned int irq)
+rawhide_enable_irq(struct irq_data *d)
 {
 	unsigned int mask, hose;
+	unsigned int irq = d->irq;
 
 	irq -= 16;
 	hose = irq / 24;
@@ -76,9 +77,10 @@ rawhide_enable_irq(unsigned int irq)
 }
 
 static void 
-rawhide_disable_irq(unsigned int irq)
+rawhide_disable_irq(struct irq_data *d)
 {
 	unsigned int mask, hose;
+	unsigned int irq = d->irq;
 
 	irq -= 16;
 	hose = irq / 24;
@@ -96,9 +98,10 @@ rawhide_disable_irq(unsigned int irq)
 }
 
 static void
-rawhide_mask_and_ack_irq(unsigned int irq)
+rawhide_mask_and_ack_irq(struct irq_data *d)
 {
 	unsigned int mask, mask1, hose;
+	unsigned int irq = d->irq;
 
 	irq -= 16;
 	hose = irq / 24;
@@ -121,28 +124,11 @@ rawhide_mask_and_ack_irq(unsigned int ir
 	spin_unlock(&rawhide_irq_lock);
 }
 
-static unsigned int
-rawhide_startup_irq(unsigned int irq)
-{
-	rawhide_enable_irq(irq);
-	return 0;
-}
-
-static void
-rawhide_end_irq(unsigned int irq)
-{
-	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
-		rawhide_enable_irq(irq);
-}
-
 static struct irq_chip rawhide_irq_type = {
 	.name		= "RAWHIDE",
-	.startup	= rawhide_startup_irq,
-	.shutdown	= rawhide_disable_irq,
-	.enable		= rawhide_enable_irq,
-	.disable	= rawhide_disable_irq,
-	.ack		= rawhide_mask_and_ack_irq,
-	.end		= rawhide_end_irq,
+	.irq_unmask	= rawhide_enable_irq,
+	.irq_mask	= rawhide_disable_irq,
+	.irq_mask_ack	= rawhide_mask_and_ack_irq,
 };
 
 static void 
@@ -194,8 +180,8 @@ rawhide_init_irq(void)
 	}
 
 	for (i = 16; i < 128; ++i) {
-		irq_desc[i].status = IRQ_DISABLED | IRQ_LEVEL;
-		irq_desc[i].chip = &rawhide_irq_type;
+		set_irq_chip_and_handler(i, &rawhide_irq_type, handle_level_irq);
+		irq_set_status_flags(i, IRQ_LEVEL);
 	}
 
 	init_i8259a_irqs();
diff -druNp linux-libre-2.6.37-gnu1/arch/alpha/kernel/sys_rx164.c linux-libre-2.6.38-gnu1/arch/alpha/kernel/sys_rx164.c
--- linux-libre-2.6.37-gnu1/arch/alpha/kernel/sys_rx164.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/alpha/kernel/sys_rx164.c	2011-03-14 21:20:32.000000000 -0400
@@ -47,39 +47,22 @@ rx164_update_irq_hw(unsigned long mask)
 }
 
 static inline void
-rx164_enable_irq(unsigned int irq)
-{
-	rx164_update_irq_hw(cached_irq_mask |= 1UL << (irq - 16));
-}
-
-static void
-rx164_disable_irq(unsigned int irq)
-{
-	rx164_update_irq_hw(cached_irq_mask &= ~(1UL << (irq - 16)));
-}
-
-static unsigned int
-rx164_startup_irq(unsigned int irq)
+rx164_enable_irq(struct irq_data *d)
 {
-	rx164_enable_irq(irq);
-	return 0;
+	rx164_update_irq_hw(cached_irq_mask |= 1UL << (d->irq - 16));
 }
 
 static void
-rx164_end_irq(unsigned int irq)
+rx164_disable_irq(struct irq_data *d)
 {
-	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
-		rx164_enable_irq(irq);
+	rx164_update_irq_hw(cached_irq_mask &= ~(1UL << (d->irq - 16)));
 }
 
 static struct irq_chip rx164_irq_type = {
 	.name		= "RX164",
-	.startup	= rx164_startup_irq,
-	.shutdown	= rx164_disable_irq,
-	.enable		= rx164_enable_irq,
-	.disable	= rx164_disable_irq,
-	.ack		= rx164_disable_irq,
-	.end		= rx164_end_irq,
+	.irq_unmask	= rx164_enable_irq,
+	.irq_mask	= rx164_disable_irq,
+	.irq_mask_ack	= rx164_disable_irq,
 };
 
 static void 
@@ -116,8 +99,8 @@ rx164_init_irq(void)
 
 	rx164_update_irq_hw(0);
 	for (i = 16; i < 40; ++i) {
-		irq_desc[i].status = IRQ_DISABLED | IRQ_LEVEL;
-		irq_desc[i].chip = &rx164_irq_type;
+		set_irq_chip_and_handler(i, &rx164_irq_type, handle_level_irq);
+		irq_set_status_flags(i, IRQ_LEVEL);
 	}
 
 	init_i8259a_irqs();
diff -druNp linux-libre-2.6.37-gnu1/arch/alpha/kernel/sys_sable.c linux-libre-2.6.38-gnu1/arch/alpha/kernel/sys_sable.c
--- linux-libre-2.6.37-gnu1/arch/alpha/kernel/sys_sable.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/alpha/kernel/sys_sable.c	2011-03-14 21:20:32.000000000 -0400
@@ -443,11 +443,11 @@ lynx_swizzle(struct pci_dev *dev, u8 *pi
 /* GENERIC irq routines */
 
 static inline void
-sable_lynx_enable_irq(unsigned int irq)
+sable_lynx_enable_irq(struct irq_data *d)
 {
 	unsigned long bit, mask;
 
-	bit = sable_lynx_irq_swizzle->irq_to_mask[irq];
+	bit = sable_lynx_irq_swizzle->irq_to_mask[d->irq];
 	spin_lock(&sable_lynx_irq_lock);
 	mask = sable_lynx_irq_swizzle->shadow_mask &= ~(1UL << bit);
 	sable_lynx_irq_swizzle->update_irq_hw(bit, mask);
@@ -459,11 +459,11 @@ sable_lynx_enable_irq(unsigned int irq)
 }
 
 static void
-sable_lynx_disable_irq(unsigned int irq)
+sable_lynx_disable_irq(struct irq_data *d)
 {
 	unsigned long bit, mask;
 
-	bit = sable_lynx_irq_swizzle->irq_to_mask[irq];
+	bit = sable_lynx_irq_swizzle->irq_to_mask[d->irq];
 	spin_lock(&sable_lynx_irq_lock);
 	mask = sable_lynx_irq_swizzle->shadow_mask |= 1UL << bit;
 	sable_lynx_irq_swizzle->update_irq_hw(bit, mask);
@@ -474,26 +474,12 @@ sable_lynx_disable_irq(unsigned int irq)
 #endif
 }
 
-static unsigned int
-sable_lynx_startup_irq(unsigned int irq)
-{
-	sable_lynx_enable_irq(irq);
-	return 0;
-}
-
-static void
-sable_lynx_end_irq(unsigned int irq)
-{
-	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
-		sable_lynx_enable_irq(irq);
-}
-
 static void
-sable_lynx_mask_and_ack_irq(unsigned int irq)
+sable_lynx_mask_and_ack_irq(struct irq_data *d)
 {
 	unsigned long bit, mask;
 
-	bit = sable_lynx_irq_swizzle->irq_to_mask[irq];
+	bit = sable_lynx_irq_swizzle->irq_to_mask[d->irq];
 	spin_lock(&sable_lynx_irq_lock);
 	mask = sable_lynx_irq_swizzle->shadow_mask |= 1UL << bit;
 	sable_lynx_irq_swizzle->update_irq_hw(bit, mask);
@@ -503,12 +489,9 @@ sable_lynx_mask_and_ack_irq(unsigned int
 
 static struct irq_chip sable_lynx_irq_type = {
 	.name		= "SABLE/LYNX",
-	.startup	= sable_lynx_startup_irq,
-	.shutdown	= sable_lynx_disable_irq,
-	.enable		= sable_lynx_enable_irq,
-	.disable	= sable_lynx_disable_irq,
-	.ack		= sable_lynx_mask_and_ack_irq,
-	.end		= sable_lynx_end_irq,
+	.irq_unmask	= sable_lynx_enable_irq,
+	.irq_mask	= sable_lynx_disable_irq,
+	.irq_mask_ack	= sable_lynx_mask_and_ack_irq,
 };
 
 static void 
@@ -535,8 +518,9 @@ sable_lynx_init_irq(int nr_of_irqs)
 	long i;
 
 	for (i = 0; i < nr_of_irqs; ++i) {
-		irq_desc[i].status = IRQ_DISABLED | IRQ_LEVEL;
-		irq_desc[i].chip = &sable_lynx_irq_type;
+		set_irq_chip_and_handler(i, &sable_lynx_irq_type,
+			handle_level_irq);
+		irq_set_status_flags(i, IRQ_LEVEL);
 	}
 
 	common_init_isa_dma();
diff -druNp linux-libre-2.6.37-gnu1/arch/alpha/kernel/sys_takara.c linux-libre-2.6.38-gnu1/arch/alpha/kernel/sys_takara.c
--- linux-libre-2.6.37-gnu1/arch/alpha/kernel/sys_takara.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/alpha/kernel/sys_takara.c	2011-03-14 21:20:32.000000000 -0400
@@ -45,43 +45,28 @@ takara_update_irq_hw(unsigned long irq,
 }
 
 static inline void
-takara_enable_irq(unsigned int irq)
+takara_enable_irq(struct irq_data *d)
 {
+	unsigned int irq = d->irq;
 	unsigned long mask;
 	mask = (cached_irq_mask[irq >= 64] &= ~(1UL << (irq & 63)));
 	takara_update_irq_hw(irq, mask);
 }
 
 static void
-takara_disable_irq(unsigned int irq)
+takara_disable_irq(struct irq_data *d)
 {
+	unsigned int irq = d->irq;
 	unsigned long mask;
 	mask = (cached_irq_mask[irq >= 64] |= 1UL << (irq & 63));
 	takara_update_irq_hw(irq, mask);
 }
 
-static unsigned int
-takara_startup_irq(unsigned int irq)
-{
-	takara_enable_irq(irq);
-	return 0; /* never anything pending */
-}
-
-static void
-takara_end_irq(unsigned int irq)
-{
-	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
-		takara_enable_irq(irq);
-}
-
 static struct irq_chip takara_irq_type = {
 	.name		= "TAKARA",
-	.startup	= takara_startup_irq,
-	.shutdown	= takara_disable_irq,
-	.enable		= takara_enable_irq,
-	.disable	= takara_disable_irq,
-	.ack		= takara_disable_irq,
-	.end		= takara_end_irq,
+	.irq_unmask	= takara_enable_irq,
+	.irq_mask	= takara_disable_irq,
+	.irq_mask_ack	= takara_disable_irq,
 };
 
 static void
@@ -153,8 +138,8 @@ takara_init_irq(void)
 		takara_update_irq_hw(i, -1);
 
 	for (i = 16; i < 128; ++i) {
-		irq_desc[i].status = IRQ_DISABLED | IRQ_LEVEL;
-		irq_desc[i].chip = &takara_irq_type;
+		set_irq_chip_and_handler(i, &takara_irq_type, handle_level_irq);
+		irq_set_status_flags(i, IRQ_LEVEL);
 	}
 
 	common_init_isa_dma();
diff -druNp linux-libre-2.6.37-gnu1/arch/alpha/kernel/sys_titan.c linux-libre-2.6.38-gnu1/arch/alpha/kernel/sys_titan.c
--- linux-libre-2.6.37-gnu1/arch/alpha/kernel/sys_titan.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/alpha/kernel/sys_titan.c	2011-03-14 21:20:32.000000000 -0400
@@ -112,8 +112,9 @@ titan_update_irq_hw(unsigned long mask)
 }
 
 static inline void
-titan_enable_irq(unsigned int irq)
+titan_enable_irq(struct irq_data *d)
 {
+	unsigned int irq = d->irq;
 	spin_lock(&titan_irq_lock);
 	titan_cached_irq_mask |= 1UL << (irq - 16);
 	titan_update_irq_hw(titan_cached_irq_mask);
@@ -121,28 +122,15 @@ titan_enable_irq(unsigned int irq)
 }
 
 static inline void
-titan_disable_irq(unsigned int irq)
+titan_disable_irq(struct irq_data *d)
 {
+	unsigned int irq = d->irq;
 	spin_lock(&titan_irq_lock);
 	titan_cached_irq_mask &= ~(1UL << (irq - 16));
 	titan_update_irq_hw(titan_cached_irq_mask);
 	spin_unlock(&titan_irq_lock);
 }
 
-static unsigned int
-titan_startup_irq(unsigned int irq)
-{
-	titan_enable_irq(irq);
-	return 0;	/* never anything pending */
-}
-
-static void
-titan_end_irq(unsigned int irq)
-{
-	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
-		titan_enable_irq(irq);
-}
-
 static void
 titan_cpu_set_irq_affinity(unsigned int irq, cpumask_t affinity)
 {
@@ -158,8 +146,10 @@ titan_cpu_set_irq_affinity(unsigned int
 }
 
 static int
-titan_set_irq_affinity(unsigned int irq, const struct cpumask *affinity)
+titan_set_irq_affinity(struct irq_data *d, const struct cpumask *affinity,
+		       bool force)
 { 
+	unsigned int irq = d->irq;
 	spin_lock(&titan_irq_lock);
 	titan_cpu_set_irq_affinity(irq - 16, *affinity);
 	titan_update_irq_hw(titan_cached_irq_mask);
@@ -189,20 +179,17 @@ init_titan_irqs(struct irq_chip * ops, i
 {
 	long i;
 	for (i = imin; i <= imax; ++i) {
-		irq_desc[i].status = IRQ_DISABLED | IRQ_LEVEL;
-		irq_desc[i].chip = ops;
+		set_irq_chip_and_handler(i, ops, handle_level_irq);
+		irq_set_status_flags(i, IRQ_LEVEL);
 	}
 }
 
 static struct irq_chip titan_irq_type = {
-       .name	       = "TITAN",
-       .startup        = titan_startup_irq,
-       .shutdown       = titan_disable_irq,
-       .enable         = titan_enable_irq,
-       .disable        = titan_disable_irq,
-       .ack            = titan_disable_irq,
-       .end            = titan_end_irq,
-       .set_affinity   = titan_set_irq_affinity,
+       .name			= "TITAN",
+       .irq_unmask		= titan_enable_irq,
+       .irq_mask		= titan_disable_irq,
+       .irq_mask_ack		= titan_disable_irq,
+       .irq_set_affinity	= titan_set_irq_affinity,
 };
 
 static irqreturn_t
diff -druNp linux-libre-2.6.37-gnu1/arch/alpha/kernel/sys_wildfire.c linux-libre-2.6.38-gnu1/arch/alpha/kernel/sys_wildfire.c
--- linux-libre-2.6.37-gnu1/arch/alpha/kernel/sys_wildfire.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/alpha/kernel/sys_wildfire.c	2011-03-14 21:20:32.000000000 -0400
@@ -104,10 +104,12 @@ wildfire_init_irq_hw(void)
 }
 
 static void
-wildfire_enable_irq(unsigned int irq)
+wildfire_enable_irq(struct irq_data *d)
 {
+	unsigned int irq = d->irq;
+
 	if (irq < 16)
-		i8259a_enable_irq(irq);
+		i8259a_enable_irq(d);
 
 	spin_lock(&wildfire_irq_lock);
 	set_bit(irq, &cached_irq_mask);
@@ -116,10 +118,12 @@ wildfire_enable_irq(unsigned int irq)
 }
 
 static void
-wildfire_disable_irq(unsigned int irq)
+wildfire_disable_irq(struct irq_data *d)
 {
+	unsigned int irq = d->irq;
+
 	if (irq < 16)
-		i8259a_disable_irq(irq);
+		i8259a_disable_irq(d);
 
 	spin_lock(&wildfire_irq_lock);
 	clear_bit(irq, &cached_irq_mask);
@@ -128,10 +132,12 @@ wildfire_disable_irq(unsigned int irq)
 }
 
 static void
-wildfire_mask_and_ack_irq(unsigned int irq)
+wildfire_mask_and_ack_irq(struct irq_data *d)
 {
+	unsigned int irq = d->irq;
+
 	if (irq < 16)
-		i8259a_mask_and_ack_irq(irq);
+		i8259a_mask_and_ack_irq(d);
 
 	spin_lock(&wildfire_irq_lock);
 	clear_bit(irq, &cached_irq_mask);
@@ -139,32 +145,11 @@ wildfire_mask_and_ack_irq(unsigned int i
 	spin_unlock(&wildfire_irq_lock);
 }
 
-static unsigned int
-wildfire_startup_irq(unsigned int irq)
-{ 
-	wildfire_enable_irq(irq);
-	return 0; /* never anything pending */
-}
-
-static void
-wildfire_end_irq(unsigned int irq)
-{ 
-#if 0
-	if (!irq_desc[irq].action)
-		printk("got irq %d\n", irq);
-#endif
-	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
-		wildfire_enable_irq(irq);
-}
-
 static struct irq_chip wildfire_irq_type = {
 	.name		= "WILDFIRE",
-	.startup	= wildfire_startup_irq,
-	.shutdown	= wildfire_disable_irq,
-	.enable		= wildfire_enable_irq,
-	.disable	= wildfire_disable_irq,
-	.ack		= wildfire_mask_and_ack_irq,
-	.end		= wildfire_end_irq,
+	.irq_unmask	= wildfire_enable_irq,
+	.irq_mask	= wildfire_disable_irq,
+	.irq_mask_ack	= wildfire_mask_and_ack_irq,
 };
 
 static void __init
@@ -198,18 +183,21 @@ wildfire_init_irq_per_pca(int qbbno, int
 	for (i = 0; i < 16; ++i) {
 		if (i == 2)
 			continue;
-		irq_desc[i+irq_bias].status = IRQ_DISABLED | IRQ_LEVEL;
-		irq_desc[i+irq_bias].chip = &wildfire_irq_type;
+		set_irq_chip_and_handler(i+irq_bias, &wildfire_irq_type,
+			handle_level_irq);
+		irq_set_status_flags(i + irq_bias, IRQ_LEVEL);
 	}
 
-	irq_desc[36+irq_bias].status = IRQ_DISABLED | IRQ_LEVEL;
-	irq_desc[36+irq_bias].chip = &wildfire_irq_type;
+	set_irq_chip_and_handler(36+irq_bias, &wildfire_irq_type,
+		handle_level_irq);
+	irq_set_status_flags(36 + irq_bias, IRQ_LEVEL);
 	for (i = 40; i < 64; ++i) {
-		irq_desc[i+irq_bias].status = IRQ_DISABLED | IRQ_LEVEL;
-		irq_desc[i+irq_bias].chip = &wildfire_irq_type;
+		set_irq_chip_and_handler(i+irq_bias, &wildfire_irq_type,
+			handle_level_irq);
+		irq_set_status_flags(i + irq_bias, IRQ_LEVEL);
 	}
 
-	setup_irq(32+irq_bias, &isa_enable);	
+	setup_irq(32+irq_bias, &isa_enable);
 }
 
 static void __init
diff -druNp linux-libre-2.6.37-gnu1/arch/alpha/kernel/time.c linux-libre-2.6.38-gnu1/arch/alpha/kernel/time.c
--- linux-libre-2.6.37-gnu1/arch/alpha/kernel/time.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/alpha/kernel/time.c	2011-03-14 21:20:32.000000000 -0400
@@ -506,7 +506,7 @@ set_rtc_mmss(unsigned long nowtime)
 		CMOS_WRITE(real_seconds,RTC_SECONDS);
 		CMOS_WRITE(real_minutes,RTC_MINUTES);
 	} else {
-		printk(KERN_WARNING
+		printk_once(KERN_NOTICE
 		       "set_rtc_mmss: can't update from %d to %d\n",
 		       cmos_minutes, real_minutes);
  		retval = -1;
diff -druNp linux-libre-2.6.37-gnu1/arch/alpha/lib/Makefile linux-libre-2.6.38-gnu1/arch/alpha/lib/Makefile
--- linux-libre-2.6.37-gnu1/arch/alpha/lib/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/alpha/lib/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -2,8 +2,8 @@
 # Makefile for alpha-specific library files..
 #
 
-EXTRA_AFLAGS := $(KBUILD_CFLAGS)
-EXTRA_CFLAGS := -Werror
+asflags-y := $(KBUILD_CFLAGS)
+ccflags-y := -Werror
 
 # Many of these routines have implementations tuned for ev6.
 # Choose them iff we're targeting ev6 specifically.
diff -druNp linux-libre-2.6.37-gnu1/arch/alpha/math-emu/Makefile linux-libre-2.6.38-gnu1/arch/alpha/math-emu/Makefile
--- linux-libre-2.6.37-gnu1/arch/alpha/math-emu/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/alpha/math-emu/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -2,7 +2,7 @@
 # Makefile for the FPU instruction emulation.
 #
 
-EXTRA_CFLAGS := -w
+ccflags-y := -w
 
 obj-$(CONFIG_MATHEMU) += math-emu.o
 
diff -druNp linux-libre-2.6.37-gnu1/arch/alpha/mm/Makefile linux-libre-2.6.38-gnu1/arch/alpha/mm/Makefile
--- linux-libre-2.6.37-gnu1/arch/alpha/mm/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/alpha/mm/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -2,7 +2,7 @@
 # Makefile for the linux alpha-specific parts of the memory manager.
 #
 
-EXTRA_CFLAGS := -Werror
+ccflags-y := -Werror
 
 obj-y	:= init.o fault.o extable.o
 
diff -druNp linux-libre-2.6.37-gnu1/arch/alpha/oprofile/Makefile linux-libre-2.6.38-gnu1/arch/alpha/oprofile/Makefile
--- linux-libre-2.6.37-gnu1/arch/alpha/oprofile/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/alpha/oprofile/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -1,4 +1,4 @@
-EXTRA_CFLAGS := -Werror -Wno-sign-compare
+ccflags-y := -Werror -Wno-sign-compare
 
 obj-$(CONFIG_OPROFILE) += oprofile.o
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/boot/compressed/.gitignore linux-libre-2.6.38-gnu1/arch/arm/boot/compressed/.gitignore
--- linux-libre-2.6.37-gnu1/arch/arm/boot/compressed/.gitignore	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/boot/compressed/.gitignore	2011-03-14 21:20:32.000000000 -0400
@@ -1,3 +1,7 @@
 font.c
-piggy.gz
+lib1funcs.S
+piggy.gzip
+piggy.lzo
+piggy.lzma
+vmlinux
 vmlinux.lds
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/boot/compressed/head-shmobile.S linux-libre-2.6.38-gnu1/arch/arm/boot/compressed/head-shmobile.S
--- linux-libre-2.6.37-gnu1/arch/arm/boot/compressed/head-shmobile.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/boot/compressed/head-shmobile.S	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,53 @@
+/*
+ * The head-file for SH-Mobile ARM platforms
+ *
+ * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+ * Simon Horman <horms@verge.net.au>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifdef CONFIG_ZBOOT_ROM
+
+	.section	".start", "ax"
+
+	/* load board-specific initialization code */
+#include <mach/zboot.h>
+
+	b	1f
+__atags:@ tag #1
+	.long	12			@ tag->hdr.size = tag_size(tag_core);
+	.long	0x54410001		@ tag->hdr.tag = ATAG_CORE;
+	.long   0			@ tag->u.core.flags = 0;
+	.long	0			@ tag->u.core.pagesize = 0;
+	.long	0			@ tag->u.core.rootdev = 0;
+	@ tag #2
+	.long	8			@ tag->hdr.size = tag_size(tag_mem32);
+	.long	0x54410002		@ tag->hdr.tag = ATAG_MEM;
+	.long	CONFIG_MEMORY_SIZE	@ tag->u.mem.size = CONFIG_MEMORY_SIZE;
+	.long	CONFIG_MEMORY_START	@ @ tag->u.mem.start = CONFIG_MEMORY_START;
+	@ tag #3
+	.long	0			@ tag->hdr.size = 0
+	.long	0			@ tag->hdr.tag = ATAG_NONE;
+1:
+
+	/* Set board ID necessary for boot */
+	ldr	r7, 1f				@ Set machine type register
+	adr	r8, __atags			@ Set atag register
+	b	2f
+
+1 :	.long MACH_TYPE
+2 :
+
+#endif /* CONFIG_ZBOOT_ROM */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/boot/compressed/Makefile linux-libre-2.6.38-gnu1/arch/arm/boot/compressed/Makefile
--- linux-libre-2.6.37-gnu1/arch/arm/boot/compressed/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/boot/compressed/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -45,6 +45,10 @@ else
 endif
 endif
 
+ifeq ($(CONFIG_ARCH_SHMOBILE),y)
+OBJS		+= head-shmobile.o
+endif
+
 #
 # We now have a PIC decompressor implementation.  Decompressors running
 # from RAM should not define ZTEXTADDR.  Decompressors running directly
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/common/clkdev.c linux-libre-2.6.38-gnu1/arch/arm/common/clkdev.c
--- linux-libre-2.6.37-gnu1/arch/arm/common/clkdev.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/common/clkdev.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,179 +0,0 @@
-/*
- *  arch/arm/common/clkdev.c
- *
- *  Copyright (C) 2008 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.
- *
- * Helper for the clk API to assist looking up a struct clk.
- */
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/device.h>
-#include <linux/list.h>
-#include <linux/errno.h>
-#include <linux/err.h>
-#include <linux/string.h>
-#include <linux/mutex.h>
-#include <linux/clk.h>
-#include <linux/slab.h>
-
-#include <asm/clkdev.h>
-#include <mach/clkdev.h>
-
-static LIST_HEAD(clocks);
-static DEFINE_MUTEX(clocks_mutex);
-
-/*
- * Find the correct struct clk for the device and connection ID.
- * We do slightly fuzzy matching here:
- *  An entry with a NULL ID is assumed to be a wildcard.
- *  If an entry has a device ID, it must match
- *  If an entry has a connection ID, it must match
- * Then we take the most specific entry - with the following
- * order of precedence: dev+con > dev only > con only.
- */
-static struct clk *clk_find(const char *dev_id, const char *con_id)
-{
-	struct clk_lookup *p;
-	struct clk *clk = NULL;
-	int match, best = 0;
-
-	list_for_each_entry(p, &clocks, node) {
-		match = 0;
-		if (p->dev_id) {
-			if (!dev_id || strcmp(p->dev_id, dev_id))
-				continue;
-			match += 2;
-		}
-		if (p->con_id) {
-			if (!con_id || strcmp(p->con_id, con_id))
-				continue;
-			match += 1;
-		}
-
-		if (match > best) {
-			clk = p->clk;
-			if (match != 3)
-				best = match;
-			else
-				break;
-		}
-	}
-	return clk;
-}
-
-struct clk *clk_get_sys(const char *dev_id, const char *con_id)
-{
-	struct clk *clk;
-
-	mutex_lock(&clocks_mutex);
-	clk = clk_find(dev_id, con_id);
-	if (clk && !__clk_get(clk))
-		clk = NULL;
-	mutex_unlock(&clocks_mutex);
-
-	return clk ? clk : ERR_PTR(-ENOENT);
-}
-EXPORT_SYMBOL(clk_get_sys);
-
-struct clk *clk_get(struct device *dev, const char *con_id)
-{
-	const char *dev_id = dev ? dev_name(dev) : NULL;
-
-	return clk_get_sys(dev_id, con_id);
-}
-EXPORT_SYMBOL(clk_get);
-
-void clk_put(struct clk *clk)
-{
-	__clk_put(clk);
-}
-EXPORT_SYMBOL(clk_put);
-
-void clkdev_add(struct clk_lookup *cl)
-{
-	mutex_lock(&clocks_mutex);
-	list_add_tail(&cl->node, &clocks);
-	mutex_unlock(&clocks_mutex);
-}
-EXPORT_SYMBOL(clkdev_add);
-
-void __init clkdev_add_table(struct clk_lookup *cl, size_t num)
-{
-	mutex_lock(&clocks_mutex);
-	while (num--) {
-		list_add_tail(&cl->node, &clocks);
-		cl++;
-	}
-	mutex_unlock(&clocks_mutex);
-}
-
-#define MAX_DEV_ID	20
-#define MAX_CON_ID	16
-
-struct clk_lookup_alloc {
-	struct clk_lookup cl;
-	char	dev_id[MAX_DEV_ID];
-	char	con_id[MAX_CON_ID];
-};
-
-struct clk_lookup *clkdev_alloc(struct clk *clk, const char *con_id,
-	const char *dev_fmt, ...)
-{
-	struct clk_lookup_alloc *cla;
-
-	cla = kzalloc(sizeof(*cla), GFP_KERNEL);
-	if (!cla)
-		return NULL;
-
-	cla->cl.clk = clk;
-	if (con_id) {
-		strlcpy(cla->con_id, con_id, sizeof(cla->con_id));
-		cla->cl.con_id = cla->con_id;
-	}
-
-	if (dev_fmt) {
-		va_list ap;
-
-		va_start(ap, dev_fmt);
-		vscnprintf(cla->dev_id, sizeof(cla->dev_id), dev_fmt, ap);
-		cla->cl.dev_id = cla->dev_id;
-		va_end(ap);
-	}
-
-	return &cla->cl;
-}
-EXPORT_SYMBOL(clkdev_alloc);
-
-int clk_add_alias(const char *alias, const char *alias_dev_name, char *id,
-	struct device *dev)
-{
-	struct clk *r = clk_get(dev, id);
-	struct clk_lookup *l;
-
-	if (IS_ERR(r))
-		return PTR_ERR(r);
-
-	l = clkdev_alloc(r, alias, alias_dev_name);
-	clk_put(r);
-	if (!l)
-		return -ENODEV;
-	clkdev_add(l);
-	return 0;
-}
-EXPORT_SYMBOL(clk_add_alias);
-
-/*
- * clkdev_drop - remove a clock dynamically allocated
- */
-void clkdev_drop(struct clk_lookup *cl)
-{
-	mutex_lock(&clocks_mutex);
-	list_del(&cl->node);
-	mutex_unlock(&clocks_mutex);
-	kfree(cl);
-}
-EXPORT_SYMBOL(clkdev_drop);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/common/dmabounce.c linux-libre-2.6.38-gnu1/arch/arm/common/dmabounce.c
--- linux-libre-2.6.37-gnu1/arch/arm/common/dmabounce.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/common/dmabounce.c	2011-03-14 21:20:32.000000000 -0400
@@ -328,7 +328,7 @@ static inline void unmap_single(struct d
  * substitute the safe buffer for the unsafe one.
  * (basically move the buffer from an unsafe area to a safe one)
  */
-dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size,
+dma_addr_t __dma_map_single(struct device *dev, void *ptr, size_t size,
 		enum dma_data_direction dir)
 {
 	dev_dbg(dev, "%s(ptr=%p,size=%d,dir=%x)\n",
@@ -338,7 +338,7 @@ dma_addr_t dma_map_single(struct device
 
 	return map_single(dev, ptr, size, dir);
 }
-EXPORT_SYMBOL(dma_map_single);
+EXPORT_SYMBOL(__dma_map_single);
 
 /*
  * see if a mapped address was really a "safe" buffer and if so, copy
@@ -346,7 +346,7 @@ EXPORT_SYMBOL(dma_map_single);
  * the safe buffer.  (basically return things back to the way they
  * should be)
  */
-void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
+void __dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
 		enum dma_data_direction dir)
 {
 	dev_dbg(dev, "%s(ptr=%p,size=%d,dir=%x)\n",
@@ -354,9 +354,9 @@ void dma_unmap_single(struct device *dev
 
 	unmap_single(dev, dma_addr, size, dir);
 }
-EXPORT_SYMBOL(dma_unmap_single);
+EXPORT_SYMBOL(__dma_unmap_single);
 
-dma_addr_t dma_map_page(struct device *dev, struct page *page,
+dma_addr_t __dma_map_page(struct device *dev, struct page *page,
 		unsigned long offset, size_t size, enum dma_data_direction dir)
 {
 	dev_dbg(dev, "%s(page=%p,off=%#lx,size=%zx,dir=%x)\n",
@@ -372,7 +372,7 @@ dma_addr_t dma_map_page(struct device *d
 
 	return map_single(dev, page_address(page) + offset, size, dir);
 }
-EXPORT_SYMBOL(dma_map_page);
+EXPORT_SYMBOL(__dma_map_page);
 
 /*
  * see if a mapped address was really a "safe" buffer and if so, copy
@@ -380,7 +380,7 @@ EXPORT_SYMBOL(dma_map_page);
  * the safe buffer.  (basically return things back to the way they
  * should be)
  */
-void dma_unmap_page(struct device *dev, dma_addr_t dma_addr, size_t size,
+void __dma_unmap_page(struct device *dev, dma_addr_t dma_addr, size_t size,
 		enum dma_data_direction dir)
 {
 	dev_dbg(dev, "%s(ptr=%p,size=%d,dir=%x)\n",
@@ -388,7 +388,7 @@ void dma_unmap_page(struct device *dev,
 
 	unmap_single(dev, dma_addr, size, dir);
 }
-EXPORT_SYMBOL(dma_unmap_page);
+EXPORT_SYMBOL(__dma_unmap_page);
 
 int dmabounce_sync_for_cpu(struct device *dev, dma_addr_t addr,
 		unsigned long off, size_t sz, enum dma_data_direction dir)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/common/gic.c linux-libre-2.6.38-gnu1/arch/arm/common/gic.c
--- linux-libre-2.6.37-gnu1/arch/arm/common/gic.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/common/gic.c	2011-03-14 21:20:32.000000000 -0400
@@ -35,6 +35,9 @@
 
 static DEFINE_SPINLOCK(irq_controller_lock);
 
+/* Address of GIC 0 CPU interface */
+void __iomem *gic_cpu_base_addr __read_mostly;
+
 struct gic_chip_data {
 	unsigned int irq_offset;
 	void __iomem *dist_base;
@@ -45,59 +48,58 @@ struct gic_chip_data {
 #define MAX_GIC_NR	1
 #endif
 
-static struct gic_chip_data gic_data[MAX_GIC_NR];
+static struct gic_chip_data gic_data[MAX_GIC_NR] __read_mostly;
 
-static inline void __iomem *gic_dist_base(unsigned int irq)
+static inline void __iomem *gic_dist_base(struct irq_data *d)
 {
-	struct gic_chip_data *gic_data = get_irq_chip_data(irq);
+	struct gic_chip_data *gic_data = irq_data_get_irq_chip_data(d);
 	return gic_data->dist_base;
 }
 
-static inline void __iomem *gic_cpu_base(unsigned int irq)
+static inline void __iomem *gic_cpu_base(struct irq_data *d)
 {
-	struct gic_chip_data *gic_data = get_irq_chip_data(irq);
+	struct gic_chip_data *gic_data = irq_data_get_irq_chip_data(d);
 	return gic_data->cpu_base;
 }
 
-static inline unsigned int gic_irq(unsigned int irq)
+static inline unsigned int gic_irq(struct irq_data *d)
 {
-	struct gic_chip_data *gic_data = get_irq_chip_data(irq);
-	return irq - gic_data->irq_offset;
+	struct gic_chip_data *gic_data = irq_data_get_irq_chip_data(d);
+	return d->irq - gic_data->irq_offset;
 }
 
 /*
  * Routines to acknowledge, disable and enable interrupts
  */
-static void gic_ack_irq(unsigned int irq)
+static void gic_ack_irq(struct irq_data *d)
 {
-
 	spin_lock(&irq_controller_lock);
-	writel(gic_irq(irq), gic_cpu_base(irq) + GIC_CPU_EOI);
+	writel(gic_irq(d), gic_cpu_base(d) + GIC_CPU_EOI);
 	spin_unlock(&irq_controller_lock);
 }
 
-static void gic_mask_irq(unsigned int irq)
+static void gic_mask_irq(struct irq_data *d)
 {
-	u32 mask = 1 << (irq % 32);
+	u32 mask = 1 << (d->irq % 32);
 
 	spin_lock(&irq_controller_lock);
-	writel(mask, gic_dist_base(irq) + GIC_DIST_ENABLE_CLEAR + (gic_irq(irq) / 32) * 4);
+	writel(mask, gic_dist_base(d) + GIC_DIST_ENABLE_CLEAR + (gic_irq(d) / 32) * 4);
 	spin_unlock(&irq_controller_lock);
 }
 
-static void gic_unmask_irq(unsigned int irq)
+static void gic_unmask_irq(struct irq_data *d)
 {
-	u32 mask = 1 << (irq % 32);
+	u32 mask = 1 << (d->irq % 32);
 
 	spin_lock(&irq_controller_lock);
-	writel(mask, gic_dist_base(irq) + GIC_DIST_ENABLE_SET + (gic_irq(irq) / 32) * 4);
+	writel(mask, gic_dist_base(d) + GIC_DIST_ENABLE_SET + (gic_irq(d) / 32) * 4);
 	spin_unlock(&irq_controller_lock);
 }
 
-static int gic_set_type(unsigned int irq, unsigned int type)
+static int gic_set_type(struct irq_data *d, unsigned int type)
 {
-	void __iomem *base = gic_dist_base(irq);
-	unsigned int gicirq = gic_irq(irq);
+	void __iomem *base = gic_dist_base(d);
+	unsigned int gicirq = gic_irq(d);
 	u32 enablemask = 1 << (gicirq % 32);
 	u32 enableoff = (gicirq / 32) * 4;
 	u32 confmask = 0x2 << ((gicirq % 16) * 2);
@@ -140,21 +142,22 @@ static int gic_set_type(unsigned int irq
 }
 
 #ifdef CONFIG_SMP
-static int gic_set_cpu(unsigned int irq, const struct cpumask *mask_val)
+static int
+gic_set_cpu(struct irq_data *d, const struct cpumask *mask_val, bool force)
 {
-	void __iomem *reg = gic_dist_base(irq) + GIC_DIST_TARGET + (gic_irq(irq) & ~3);
-	unsigned int shift = (irq % 4) * 8;
+	void __iomem *reg = gic_dist_base(d) + GIC_DIST_TARGET + (gic_irq(d) & ~3);
+	unsigned int shift = (d->irq % 4) * 8;
 	unsigned int cpu = cpumask_first(mask_val);
 	u32 val;
 	struct irq_desc *desc;
 
 	spin_lock(&irq_controller_lock);
-	desc = irq_to_desc(irq);
+	desc = irq_to_desc(d->irq);
 	if (desc == NULL) {
 		spin_unlock(&irq_controller_lock);
 		return -EINVAL;
 	}
-	desc->node = cpu;
+	d->node = cpu;
 	val = readl(reg) & ~(0xff << shift);
 	val |= 1 << (cpu + shift);
 	writel(val, reg);
@@ -172,7 +175,7 @@ static void gic_handle_cascade_irq(unsig
 	unsigned long status;
 
 	/* primary controller ack'ing */
-	chip->ack(irq);
+	chip->irq_ack(&desc->irq_data);
 
 	spin_lock(&irq_controller_lock);
 	status = readl(chip_data->cpu_base + GIC_CPU_INTACK);
@@ -190,17 +193,17 @@ static void gic_handle_cascade_irq(unsig
 
  out:
 	/* primary controller unmasking */
-	chip->unmask(irq);
+	chip->irq_unmask(&desc->irq_data);
 }
 
 static struct irq_chip gic_chip = {
-	.name		= "GIC",
-	.ack		= gic_ack_irq,
-	.mask		= gic_mask_irq,
-	.unmask		= gic_unmask_irq,
-	.set_type	= gic_set_type,
+	.name			= "GIC",
+	.irq_ack		= gic_ack_irq,
+	.irq_mask		= gic_mask_irq,
+	.irq_unmask		= gic_unmask_irq,
+	.irq_set_type		= gic_set_type,
 #ifdef CONFIG_SMP
-	.set_affinity	= gic_set_cpu,
+	.irq_set_affinity	= gic_set_cpu,
 #endif
 };
 
@@ -213,21 +216,16 @@ void __init gic_cascade_irq(unsigned int
 	set_irq_chained_handler(irq, gic_handle_cascade_irq);
 }
 
-void __init gic_dist_init(unsigned int gic_nr, void __iomem *base,
-			  unsigned int irq_start)
+static void __init gic_dist_init(struct gic_chip_data *gic,
+	unsigned int irq_start)
 {
 	unsigned int gic_irqs, irq_limit, i;
+	void __iomem *base = gic->dist_base;
 	u32 cpumask = 1 << smp_processor_id();
 
-	if (gic_nr >= MAX_GIC_NR)
-		BUG();
-
 	cpumask |= cpumask << 8;
 	cpumask |= cpumask << 16;
 
-	gic_data[gic_nr].dist_base = base;
-	gic_data[gic_nr].irq_offset = (irq_start - 1) & ~31;
-
 	writel(0, base + GIC_DIST_CTRL);
 
 	/*
@@ -267,7 +265,7 @@ void __init gic_dist_init(unsigned int g
 	/*
 	 * Limit number of interrupts registered to the platform maximum
 	 */
-	irq_limit = gic_data[gic_nr].irq_offset + gic_irqs;
+	irq_limit = gic->irq_offset + gic_irqs;
 	if (WARN_ON(irq_limit > NR_IRQS))
 		irq_limit = NR_IRQS;
 
@@ -276,7 +274,7 @@ void __init gic_dist_init(unsigned int g
 	 */
 	for (i = irq_start; i < irq_limit; i++) {
 		set_irq_chip(i, &gic_chip);
-		set_irq_chip_data(i, &gic_data[gic_nr]);
+		set_irq_chip_data(i, gic);
 		set_irq_handler(i, handle_level_irq);
 		set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
 	}
@@ -284,19 +282,12 @@ void __init gic_dist_init(unsigned int g
 	writel(1, base + GIC_DIST_CTRL);
 }
 
-void __cpuinit gic_cpu_init(unsigned int gic_nr, void __iomem *base)
+static void __cpuinit gic_cpu_init(struct gic_chip_data *gic)
 {
-	void __iomem *dist_base;
+	void __iomem *dist_base = gic->dist_base;
+	void __iomem *base = gic->cpu_base;
 	int i;
 
-	if (gic_nr >= MAX_GIC_NR)
-		BUG();
-
-	dist_base = gic_data[gic_nr].dist_base;
-	BUG_ON(!dist_base);
-
-	gic_data[gic_nr].cpu_base = base;
-
 	/*
 	 * Deal with the banked PPI and SGI interrupts - disable all
 	 * PPI interrupts, ensure all SGI interrupts are enabled.
@@ -314,6 +305,42 @@ void __cpuinit gic_cpu_init(unsigned int
 	writel(1, base + GIC_CPU_CTRL);
 }
 
+void __init gic_init(unsigned int gic_nr, unsigned int irq_start,
+	void __iomem *dist_base, void __iomem *cpu_base)
+{
+	struct gic_chip_data *gic;
+
+	BUG_ON(gic_nr >= MAX_GIC_NR);
+
+	gic = &gic_data[gic_nr];
+	gic->dist_base = dist_base;
+	gic->cpu_base = cpu_base;
+	gic->irq_offset = (irq_start - 1) & ~31;
+
+	if (gic_nr == 0)
+		gic_cpu_base_addr = cpu_base;
+
+	gic_dist_init(gic, irq_start);
+	gic_cpu_init(gic);
+}
+
+void __cpuinit gic_secondary_init(unsigned int gic_nr)
+{
+	BUG_ON(gic_nr >= MAX_GIC_NR);
+
+	gic_cpu_init(&gic_data[gic_nr]);
+}
+
+void __cpuinit gic_enable_ppi(unsigned int irq)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+	irq_to_desc(irq)->status |= IRQ_NOPROBE;
+	gic_unmask_irq(irq_get_irq_data(irq));
+	local_irq_restore(flags);
+}
+
 #ifdef CONFIG_SMP
 void gic_raise_softirq(const struct cpumask *mask, unsigned int irq)
 {
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/common/it8152.c linux-libre-2.6.38-gnu1/arch/arm/common/it8152.c
--- linux-libre-2.6.37-gnu1/arch/arm/common/it8152.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/common/it8152.c	2011-03-14 21:20:32.000000000 -0400
@@ -31,8 +31,10 @@
 
 #define MAX_SLOTS		21
 
-static void it8152_mask_irq(unsigned int irq)
+static void it8152_mask_irq(struct irq_data *d)
 {
+	unsigned int irq = d->irq;
+
        if (irq >= IT8152_LD_IRQ(0)) {
 	       __raw_writel((__raw_readl(IT8152_INTC_LDCNIMR) |
 			    (1 << (irq - IT8152_LD_IRQ(0)))),
@@ -48,8 +50,10 @@ static void it8152_mask_irq(unsigned int
        }
 }
 
-static void it8152_unmask_irq(unsigned int irq)
+static void it8152_unmask_irq(struct irq_data *d)
 {
+	unsigned int irq = d->irq;
+
        if (irq >= IT8152_LD_IRQ(0)) {
 	       __raw_writel((__raw_readl(IT8152_INTC_LDCNIMR) &
 			     ~(1 << (irq - IT8152_LD_IRQ(0)))),
@@ -67,9 +71,9 @@ static void it8152_unmask_irq(unsigned i
 
 static struct irq_chip it8152_irq_chip = {
 	.name		= "it8152",
-	.ack		= it8152_mask_irq,
-	.mask		= it8152_mask_irq,
-	.unmask		= it8152_unmask_irq,
+	.irq_ack	= it8152_mask_irq,
+	.irq_mask	= it8152_mask_irq,
+	.irq_unmask	= it8152_unmask_irq,
 };
 
 void it8152_init_irq(void)
@@ -236,7 +240,7 @@ static struct resource it8152_mem = {
 
 /*
  * The following functions are needed for DMA bouncing.
- * ITE8152 chip can addrees up to 64MByte, so all the devices
+ * ITE8152 chip can address up to 64MByte, so all the devices
  * connected to ITE8152 (PCI and USB) should have limited DMA window
  */
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/common/Kconfig linux-libre-2.6.38-gnu1/arch/arm/common/Kconfig
--- linux-libre-2.6.37-gnu1/arch/arm/common/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/common/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -6,6 +6,8 @@ config ARM_VIC
 
 config ARM_VIC_NR
 	int
+	default 4 if ARCH_S5PV210
+	default 3 if ARCH_S5P6442 || ARCH_S5PC100
 	default 2
 	depends on ARM_VIC
 	help
@@ -37,7 +39,3 @@ config SHARP_PARAM
 
 config SHARP_SCOOP
 	bool
-
-config COMMON_CLKDEV
-	bool
-	select HAVE_CLK
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/common/locomo.c linux-libre-2.6.38-gnu1/arch/arm/common/locomo.c
--- linux-libre-2.6.37-gnu1/arch/arm/common/locomo.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/common/locomo.c	2011-03-14 21:20:32.000000000 -0400
@@ -144,7 +144,7 @@ static void locomo_handler(unsigned int
 	int req, i;
 
 	/* Acknowledge the parent IRQ */
-	desc->chip->ack(irq);
+	desc->irq_data.chip->irq_ack(&desc->irq_data);
 
 	/* check why this interrupt was generated */
 	req = locomo_readl(lchip->base + LOCOMO_ICR) & 0x0f00;
@@ -161,33 +161,33 @@ static void locomo_handler(unsigned int
 	}
 }
 
-static void locomo_ack_irq(unsigned int irq)
+static void locomo_ack_irq(struct irq_data *d)
 {
 }
 
-static void locomo_mask_irq(unsigned int irq)
+static void locomo_mask_irq(struct irq_data *d)
 {
-	struct locomo *lchip = get_irq_chip_data(irq);
+	struct locomo *lchip = irq_data_get_irq_chip_data(d);
 	unsigned int r;
 	r = locomo_readl(lchip->base + LOCOMO_ICR);
-	r &= ~(0x0010 << (irq - lchip->irq_base));
+	r &= ~(0x0010 << (d->irq - lchip->irq_base));
 	locomo_writel(r, lchip->base + LOCOMO_ICR);
 }
 
-static void locomo_unmask_irq(unsigned int irq)
+static void locomo_unmask_irq(struct irq_data *d)
 {
-	struct locomo *lchip = get_irq_chip_data(irq);
+	struct locomo *lchip = irq_data_get_irq_chip_data(d);
 	unsigned int r;
 	r = locomo_readl(lchip->base + LOCOMO_ICR);
-	r |= (0x0010 << (irq - lchip->irq_base));
+	r |= (0x0010 << (d->irq - lchip->irq_base));
 	locomo_writel(r, lchip->base + LOCOMO_ICR);
 }
 
 static struct irq_chip locomo_chip = {
-	.name	= "LOCOMO",
-	.ack	= locomo_ack_irq,
-	.mask	= locomo_mask_irq,
-	.unmask	= locomo_unmask_irq,
+	.name		= "LOCOMO",
+	.irq_ack	= locomo_ack_irq,
+	.irq_mask	= locomo_mask_irq,
+	.irq_unmask	= locomo_unmask_irq,
 };
 
 static void locomo_setup_irq(struct locomo *lchip)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/common/Makefile linux-libre-2.6.38-gnu1/arch/arm/common/Makefile
--- linux-libre-2.6.37-gnu1/arch/arm/common/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/common/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -17,3 +17,4 @@ obj-$(CONFIG_ARCH_IXP2000)	+= uengine.o
 obj-$(CONFIG_ARCH_IXP23XX)	+= uengine.o
 obj-$(CONFIG_PCI_HOST_ITE8152)  += it8152.o
 obj-$(CONFIG_COMMON_CLKDEV)	+= clkdev.o
+obj-$(CONFIG_ARM_TIMER_SP804)	+= timer-sp.o
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/common/sa1111.c linux-libre-2.6.38-gnu1/arch/arm/common/sa1111.c
--- linux-libre-2.6.37-gnu1/arch/arm/common/sa1111.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/common/sa1111.c	2011-03-14 21:20:32.000000000 -0400
@@ -210,7 +210,7 @@ sa1111_irq_handler(unsigned int irq, str
 
 	sa1111_writel(stat0, mapbase + SA1111_INTSTATCLR0);
 
-	desc->chip->ack(irq);
+	desc->irq_data.chip->irq_ack(&desc->irq_data);
 
 	sa1111_writel(stat1, mapbase + SA1111_INTSTATCLR1);
 
@@ -228,35 +228,35 @@ sa1111_irq_handler(unsigned int irq, str
 			generic_handle_irq(i + sachip->irq_base);
 
 	/* For level-based interrupts */
-	desc->chip->unmask(irq);
+	desc->irq_data.chip->irq_unmask(&desc->irq_data);
 }
 
 #define SA1111_IRQMASK_LO(x)	(1 << (x - sachip->irq_base))
 #define SA1111_IRQMASK_HI(x)	(1 << (x - sachip->irq_base - 32))
 
-static void sa1111_ack_irq(unsigned int irq)
+static void sa1111_ack_irq(struct irq_data *d)
 {
 }
 
-static void sa1111_mask_lowirq(unsigned int irq)
+static void sa1111_mask_lowirq(struct irq_data *d)
 {
-	struct sa1111 *sachip = get_irq_chip_data(irq);
+	struct sa1111 *sachip = irq_data_get_irq_chip_data(d);
 	void __iomem *mapbase = sachip->base + SA1111_INTC;
 	unsigned long ie0;
 
 	ie0 = sa1111_readl(mapbase + SA1111_INTEN0);
-	ie0 &= ~SA1111_IRQMASK_LO(irq);
+	ie0 &= ~SA1111_IRQMASK_LO(d->irq);
 	writel(ie0, mapbase + SA1111_INTEN0);
 }
 
-static void sa1111_unmask_lowirq(unsigned int irq)
+static void sa1111_unmask_lowirq(struct irq_data *d)
 {
-	struct sa1111 *sachip = get_irq_chip_data(irq);
+	struct sa1111 *sachip = irq_data_get_irq_chip_data(d);
 	void __iomem *mapbase = sachip->base + SA1111_INTC;
 	unsigned long ie0;
 
 	ie0 = sa1111_readl(mapbase + SA1111_INTEN0);
-	ie0 |= SA1111_IRQMASK_LO(irq);
+	ie0 |= SA1111_IRQMASK_LO(d->irq);
 	sa1111_writel(ie0, mapbase + SA1111_INTEN0);
 }
 
@@ -267,11 +267,11 @@ static void sa1111_unmask_lowirq(unsigne
  * be triggered.  In fact, its very difficult, if not impossible to get
  * INTSET to re-trigger the interrupt.
  */
-static int sa1111_retrigger_lowirq(unsigned int irq)
+static int sa1111_retrigger_lowirq(struct irq_data *d)
 {
-	struct sa1111 *sachip = get_irq_chip_data(irq);
+	struct sa1111 *sachip = irq_data_get_irq_chip_data(d);
 	void __iomem *mapbase = sachip->base + SA1111_INTC;
-	unsigned int mask = SA1111_IRQMASK_LO(irq);
+	unsigned int mask = SA1111_IRQMASK_LO(d->irq);
 	unsigned long ip0;
 	int i;
 
@@ -279,21 +279,21 @@ static int sa1111_retrigger_lowirq(unsig
 	for (i = 0; i < 8; i++) {
 		sa1111_writel(ip0 ^ mask, mapbase + SA1111_INTPOL0);
 		sa1111_writel(ip0, mapbase + SA1111_INTPOL0);
-		if (sa1111_readl(mapbase + SA1111_INTSTATCLR1) & mask)
+		if (sa1111_readl(mapbase + SA1111_INTSTATCLR0) & mask)
 			break;
 	}
 
 	if (i == 8)
 		printk(KERN_ERR "Danger Will Robinson: failed to "
-			"re-trigger IRQ%d\n", irq);
+			"re-trigger IRQ%d\n", d->irq);
 	return i == 8 ? -1 : 0;
 }
 
-static int sa1111_type_lowirq(unsigned int irq, unsigned int flags)
+static int sa1111_type_lowirq(struct irq_data *d, unsigned int flags)
 {
-	struct sa1111 *sachip = get_irq_chip_data(irq);
+	struct sa1111 *sachip = irq_data_get_irq_chip_data(d);
 	void __iomem *mapbase = sachip->base + SA1111_INTC;
-	unsigned int mask = SA1111_IRQMASK_LO(irq);
+	unsigned int mask = SA1111_IRQMASK_LO(d->irq);
 	unsigned long ip0;
 
 	if (flags == IRQ_TYPE_PROBE)
@@ -313,11 +313,11 @@ static int sa1111_type_lowirq(unsigned i
 	return 0;
 }
 
-static int sa1111_wake_lowirq(unsigned int irq, unsigned int on)
+static int sa1111_wake_lowirq(struct irq_data *d, unsigned int on)
 {
-	struct sa1111 *sachip = get_irq_chip_data(irq);
+	struct sa1111 *sachip = irq_data_get_irq_chip_data(d);
 	void __iomem *mapbase = sachip->base + SA1111_INTC;
-	unsigned int mask = SA1111_IRQMASK_LO(irq);
+	unsigned int mask = SA1111_IRQMASK_LO(d->irq);
 	unsigned long we0;
 
 	we0 = sa1111_readl(mapbase + SA1111_WAKEEN0);
@@ -332,33 +332,33 @@ static int sa1111_wake_lowirq(unsigned i
 
 static struct irq_chip sa1111_low_chip = {
 	.name		= "SA1111-l",
-	.ack		= sa1111_ack_irq,
-	.mask		= sa1111_mask_lowirq,
-	.unmask		= sa1111_unmask_lowirq,
-	.retrigger	= sa1111_retrigger_lowirq,
-	.set_type	= sa1111_type_lowirq,
-	.set_wake	= sa1111_wake_lowirq,
+	.irq_ack	= sa1111_ack_irq,
+	.irq_mask	= sa1111_mask_lowirq,
+	.irq_unmask	= sa1111_unmask_lowirq,
+	.irq_retrigger	= sa1111_retrigger_lowirq,
+	.irq_set_type	= sa1111_type_lowirq,
+	.irq_set_wake	= sa1111_wake_lowirq,
 };
 
-static void sa1111_mask_highirq(unsigned int irq)
+static void sa1111_mask_highirq(struct irq_data *d)
 {
-	struct sa1111 *sachip = get_irq_chip_data(irq);
+	struct sa1111 *sachip = irq_data_get_irq_chip_data(d);
 	void __iomem *mapbase = sachip->base + SA1111_INTC;
 	unsigned long ie1;
 
 	ie1 = sa1111_readl(mapbase + SA1111_INTEN1);
-	ie1 &= ~SA1111_IRQMASK_HI(irq);
+	ie1 &= ~SA1111_IRQMASK_HI(d->irq);
 	sa1111_writel(ie1, mapbase + SA1111_INTEN1);
 }
 
-static void sa1111_unmask_highirq(unsigned int irq)
+static void sa1111_unmask_highirq(struct irq_data *d)
 {
-	struct sa1111 *sachip = get_irq_chip_data(irq);
+	struct sa1111 *sachip = irq_data_get_irq_chip_data(d);
 	void __iomem *mapbase = sachip->base + SA1111_INTC;
 	unsigned long ie1;
 
 	ie1 = sa1111_readl(mapbase + SA1111_INTEN1);
-	ie1 |= SA1111_IRQMASK_HI(irq);
+	ie1 |= SA1111_IRQMASK_HI(d->irq);
 	sa1111_writel(ie1, mapbase + SA1111_INTEN1);
 }
 
@@ -369,11 +369,11 @@ static void sa1111_unmask_highirq(unsign
  * be triggered.  In fact, its very difficult, if not impossible to get
  * INTSET to re-trigger the interrupt.
  */
-static int sa1111_retrigger_highirq(unsigned int irq)
+static int sa1111_retrigger_highirq(struct irq_data *d)
 {
-	struct sa1111 *sachip = get_irq_chip_data(irq);
+	struct sa1111 *sachip = irq_data_get_irq_chip_data(d);
 	void __iomem *mapbase = sachip->base + SA1111_INTC;
-	unsigned int mask = SA1111_IRQMASK_HI(irq);
+	unsigned int mask = SA1111_IRQMASK_HI(d->irq);
 	unsigned long ip1;
 	int i;
 
@@ -387,15 +387,15 @@ static int sa1111_retrigger_highirq(unsi
 
 	if (i == 8)
 		printk(KERN_ERR "Danger Will Robinson: failed to "
-			"re-trigger IRQ%d\n", irq);
+			"re-trigger IRQ%d\n", d->irq);
 	return i == 8 ? -1 : 0;
 }
 
-static int sa1111_type_highirq(unsigned int irq, unsigned int flags)
+static int sa1111_type_highirq(struct irq_data *d, unsigned int flags)
 {
-	struct sa1111 *sachip = get_irq_chip_data(irq);
+	struct sa1111 *sachip = irq_data_get_irq_chip_data(d);
 	void __iomem *mapbase = sachip->base + SA1111_INTC;
-	unsigned int mask = SA1111_IRQMASK_HI(irq);
+	unsigned int mask = SA1111_IRQMASK_HI(d->irq);
 	unsigned long ip1;
 
 	if (flags == IRQ_TYPE_PROBE)
@@ -415,11 +415,11 @@ static int sa1111_type_highirq(unsigned
 	return 0;
 }
 
-static int sa1111_wake_highirq(unsigned int irq, unsigned int on)
+static int sa1111_wake_highirq(struct irq_data *d, unsigned int on)
 {
-	struct sa1111 *sachip = get_irq_chip_data(irq);
+	struct sa1111 *sachip = irq_data_get_irq_chip_data(d);
 	void __iomem *mapbase = sachip->base + SA1111_INTC;
-	unsigned int mask = SA1111_IRQMASK_HI(irq);
+	unsigned int mask = SA1111_IRQMASK_HI(d->irq);
 	unsigned long we1;
 
 	we1 = sa1111_readl(mapbase + SA1111_WAKEEN1);
@@ -434,12 +434,12 @@ static int sa1111_wake_highirq(unsigned
 
 static struct irq_chip sa1111_high_chip = {
 	.name		= "SA1111-h",
-	.ack		= sa1111_ack_irq,
-	.mask		= sa1111_mask_highirq,
-	.unmask		= sa1111_unmask_highirq,
-	.retrigger	= sa1111_retrigger_highirq,
-	.set_type	= sa1111_type_highirq,
-	.set_wake	= sa1111_wake_highirq,
+	.irq_ack	= sa1111_ack_irq,
+	.irq_mask	= sa1111_mask_highirq,
+	.irq_unmask	= sa1111_unmask_highirq,
+	.irq_retrigger	= sa1111_retrigger_highirq,
+	.irq_set_type	= sa1111_type_highirq,
+	.irq_set_wake	= sa1111_wake_highirq,
 };
 
 static void sa1111_setup_irq(struct sa1111 *sachip)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/common/timer-sp.c linux-libre-2.6.38-gnu1/arch/arm/common/timer-sp.c
--- linux-libre-2.6.37-gnu1/arch/arm/common/timer-sp.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/common/timer-sp.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,152 @@
+/*
+ *  linux/arch/arm/common/timer-sp.c
+ *
+ *  Copyright (C) 1999 - 2003 ARM Limited
+ *  Copyright (C) 2000 Deep Blue Solutions 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <linux/clocksource.h>
+#include <linux/clockchips.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+
+#include <asm/hardware/arm_timer.h>
+
+/*
+ * These timers are currently always setup to be clocked at 1MHz.
+ */
+#define TIMER_FREQ_KHZ	(1000)
+#define TIMER_RELOAD	(TIMER_FREQ_KHZ * 1000 / HZ)
+
+static void __iomem *clksrc_base;
+
+static cycle_t sp804_read(struct clocksource *cs)
+{
+	return ~readl(clksrc_base + TIMER_VALUE);
+}
+
+static struct clocksource clocksource_sp804 = {
+	.name		= "timer3",
+	.rating		= 200,
+	.read		= sp804_read,
+	.mask		= CLOCKSOURCE_MASK(32),
+	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+void __init sp804_clocksource_init(void __iomem *base)
+{
+	struct clocksource *cs = &clocksource_sp804;
+
+	clksrc_base = base;
+
+	/* setup timer 0 as free-running clocksource */
+	writel(0, clksrc_base + TIMER_CTRL);
+	writel(0xffffffff, clksrc_base + TIMER_LOAD);
+	writel(0xffffffff, clksrc_base + TIMER_VALUE);
+	writel(TIMER_CTRL_32BIT | TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC,
+		clksrc_base + TIMER_CTRL);
+
+	clocksource_register_khz(cs, TIMER_FREQ_KHZ);
+}
+
+
+static void __iomem *clkevt_base;
+
+/*
+ * IRQ handler for the timer
+ */
+static irqreturn_t sp804_timer_interrupt(int irq, void *dev_id)
+{
+	struct clock_event_device *evt = dev_id;
+
+	/* clear the interrupt */
+	writel(1, clkevt_base + TIMER_INTCLR);
+
+	evt->event_handler(evt);
+
+	return IRQ_HANDLED;
+}
+
+static void sp804_set_mode(enum clock_event_mode mode,
+	struct clock_event_device *evt)
+{
+	unsigned long ctrl = TIMER_CTRL_32BIT | TIMER_CTRL_IE;
+
+	writel(ctrl, clkevt_base + TIMER_CTRL);
+
+	switch (mode) {
+	case CLOCK_EVT_MODE_PERIODIC:
+		writel(TIMER_RELOAD, clkevt_base + TIMER_LOAD);
+		ctrl |= TIMER_CTRL_PERIODIC | TIMER_CTRL_ENABLE;
+		break;
+
+	case CLOCK_EVT_MODE_ONESHOT:
+		/* period set, and timer enabled in 'next_event' hook */
+		ctrl |= TIMER_CTRL_ONESHOT;
+		break;
+
+	case CLOCK_EVT_MODE_UNUSED:
+	case CLOCK_EVT_MODE_SHUTDOWN:
+	default:
+		break;
+	}
+
+	writel(ctrl, clkevt_base + TIMER_CTRL);
+}
+
+static int sp804_set_next_event(unsigned long next,
+	struct clock_event_device *evt)
+{
+	unsigned long ctrl = readl(clkevt_base + TIMER_CTRL);
+
+	writel(next, clkevt_base + TIMER_LOAD);
+	writel(ctrl | TIMER_CTRL_ENABLE, clkevt_base + TIMER_CTRL);
+
+	return 0;
+}
+
+static struct clock_event_device sp804_clockevent = {
+	.name		= "timer0",
+	.shift		= 32,
+	.features       = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
+	.set_mode	= sp804_set_mode,
+	.set_next_event	= sp804_set_next_event,
+	.rating		= 300,
+	.cpumask	= cpu_all_mask,
+};
+
+static struct irqaction sp804_timer_irq = {
+	.name		= "timer",
+	.flags		= IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
+	.handler	= sp804_timer_interrupt,
+	.dev_id		= &sp804_clockevent,
+};
+
+void __init sp804_clockevents_init(void __iomem *base, unsigned int timer_irq)
+{
+	struct clock_event_device *evt = &sp804_clockevent;
+
+	clkevt_base = base;
+
+	evt->irq = timer_irq;
+	evt->mult = div_sc(TIMER_FREQ_KHZ, NSEC_PER_MSEC, evt->shift);
+	evt->max_delta_ns = clockevent_delta2ns(0xffffffff, evt);
+	evt->min_delta_ns = clockevent_delta2ns(0xf, evt);
+
+	setup_irq(timer_irq, &sp804_timer_irq);
+	clockevents_register_device(evt);
+}
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/common/vic.c linux-libre-2.6.38-gnu1/arch/arm/common/vic.c
--- linux-libre-2.6.37-gnu1/arch/arm/common/vic.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/common/vic.c	2011-03-14 21:20:32.000000000 -0400
@@ -70,7 +70,7 @@ static inline struct vic_device *to_vic(
  * vic_init2 - common initialisation code
  * @base: Base of the VIC.
  *
- * Common initialisation code for registeration
+ * Common initialisation code for registration
  * and resume.
 */
 static void vic_init2(void __iomem *base)
@@ -204,26 +204,26 @@ static void __init vic_pm_register(void
 static inline void vic_pm_register(void __iomem *base, unsigned int irq, u32 arg1) { }
 #endif /* CONFIG_PM */
 
-static void vic_ack_irq(unsigned int irq)
+static void vic_ack_irq(struct irq_data *d)
 {
-	void __iomem *base = get_irq_chip_data(irq);
-	irq &= 31;
+	void __iomem *base = irq_data_get_irq_chip_data(d);
+	unsigned int irq = d->irq & 31;
 	writel(1 << irq, base + VIC_INT_ENABLE_CLEAR);
 	/* moreover, clear the soft-triggered, in case it was the reason */
 	writel(1 << irq, base + VIC_INT_SOFT_CLEAR);
 }
 
-static void vic_mask_irq(unsigned int irq)
+static void vic_mask_irq(struct irq_data *d)
 {
-	void __iomem *base = get_irq_chip_data(irq);
-	irq &= 31;
+	void __iomem *base = irq_data_get_irq_chip_data(d);
+	unsigned int irq = d->irq & 31;
 	writel(1 << irq, base + VIC_INT_ENABLE_CLEAR);
 }
 
-static void vic_unmask_irq(unsigned int irq)
+static void vic_unmask_irq(struct irq_data *d)
 {
-	void __iomem *base = get_irq_chip_data(irq);
-	irq &= 31;
+	void __iomem *base = irq_data_get_irq_chip_data(d);
+	unsigned int irq = d->irq & 31;
 	writel(1 << irq, base + VIC_INT_ENABLE);
 }
 
@@ -242,10 +242,10 @@ static struct vic_device *vic_from_irq(u
 	return NULL;
 }
 
-static int vic_set_wake(unsigned int irq, unsigned int on)
+static int vic_set_wake(struct irq_data *d, unsigned int on)
 {
-	struct vic_device *v = vic_from_irq(irq);
-	unsigned int off = irq & 31;
+	struct vic_device *v = vic_from_irq(d->irq);
+	unsigned int off = d->irq & 31;
 	u32 bit = 1 << off;
 
 	if (!v)
@@ -267,10 +267,10 @@ static int vic_set_wake(unsigned int irq
 
 static struct irq_chip vic_chip = {
 	.name		= "VIC",
-	.ack		= vic_ack_irq,
-	.mask		= vic_mask_irq,
-	.unmask		= vic_unmask_irq,
-	.set_wake	= vic_set_wake,
+	.irq_ack	= vic_ack_irq,
+	.irq_mask	= vic_mask_irq,
+	.irq_unmask	= vic_unmask_irq,
+	.irq_set_wake	= vic_set_wake,
 };
 
 static void __init vic_disable(void __iomem *base)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/configs/ag5evm_defconfig linux-libre-2.6.38-gnu1/arch/arm/configs/ag5evm_defconfig
--- linux-libre-2.6.37-gnu1/arch/arm/configs/ag5evm_defconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/configs/ag5evm_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,83 @@
+CONFIG_EXPERIMENTAL=y
+CONFIG_SYSVIPC=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=16
+CONFIG_NAMESPACES=y
+# CONFIG_UTS_NS is not set
+# CONFIG_IPC_NS is not set
+# CONFIG_USER_NS is not set
+# CONFIG_PID_NS is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_EXPERT=y
+CONFIG_SLAB=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+CONFIG_ARCH_SHMOBILE=y
+CONFIG_ARCH_SH73A0=y
+CONFIG_MACH_AG5EVM=y
+CONFIG_MEMORY_SIZE=0x10000000
+CONFIG_CPU_BPREDICT_DISABLE=y
+CONFIG_ARM_ERRATA_430973=y
+CONFIG_ARM_ERRATA_458693=y
+CONFIG_NO_HZ=y
+CONFIG_AEABI=y
+# CONFIG_OABI_COMPAT is not set
+CONFIG_HIGHMEM=y
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="console=tty0 console=ttySC2,115200 earlyprintk=sh-sci.2,115200 ignore_loglevel"
+CONFIG_CMDLINE_FORCE=y
+CONFIG_KEXEC=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_PM=y
+# CONFIG_SUSPEND is not set
+CONFIG_PM_RUNTIME=y
+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_WIRELESS is not set
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+# CONFIG_BLK_DEV is not set
+CONFIG_NETDEVICES=y
+CONFIG_NET_ETHERNET=y
+CONFIG_SMSC911X=y
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+# CONFIG_WLAN is not set
+CONFIG_INPUT_SPARSEKMAP=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_SERIAL_SH_SCI=y
+CONFIG_SERIAL_SH_SCI_NR_UARTS=9
+CONFIG_SERIAL_SH_SCI_CONSOLE=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_HW_RANDOM is not set
+CONFIG_I2C=y
+CONFIG_I2C_SH_MOBILE=y
+# CONFIG_HWMON is not set
+# CONFIG_MFD_SUPPORT is not set
+CONFIG_FB=y
+CONFIG_FB_SH_MOBILE_LCDC=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
+# CONFIG_HID_SUPPORT is not set
+# CONFIG_USB_SUPPORT is not set
+# CONFIG_DNOTIFY is not set
+# CONFIG_INOTIFY_USER is not set
+CONFIG_TMPFS=y
+# CONFIG_MISC_FILESYSTEMS is not set
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_FTRACE is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/configs/am200epdkit_defconfig linux-libre-2.6.38-gnu1/arch/arm/configs/am200epdkit_defconfig
--- linux-libre-2.6.37-gnu1/arch/arm/configs/am200epdkit_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/configs/am200epdkit_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -3,7 +3,7 @@ CONFIG_LOCALVERSION="gum"
 # CONFIG_SWAP is not set
 CONFIG_SYSVIPC=y
 CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_SYSCTL_SYSCALL is not set
 # CONFIG_EPOLL is not set
 # CONFIG_SHMEM is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/configs/ams_delta_defconfig linux-libre-2.6.38-gnu1/arch/arm/configs/ams_delta_defconfig
--- linux-libre-2.6.37-gnu1/arch/arm/configs/ams_delta_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/configs/ams_delta_defconfig	1969-12-31 19:00:00.000000000 -0500
@@ -1,121 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-# CONFIG_SWAP is not set
-CONFIG_SYSVIPC=y
-CONFIG_TREE_PREEMPT_RCU=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_EMBEDDED=y
-# CONFIG_KALLSYMS is not set
-CONFIG_SLAB=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-CONFIG_MODULE_FORCE_UNLOAD=y
-# CONFIG_LBDAF is not set
-CONFIG_ARCH_OMAP=y
-CONFIG_ARCH_OMAP1=y
-CONFIG_OMAP_MBOX_FWK=m
-CONFIG_MACH_AMS_DELTA=y
-CONFIG_OMAP_ARM_150MHZ=y
-# CONFIG_OMAP_ARM_60MHZ is not set
-CONFIG_PREEMPT=y
-CONFIG_AEABI=y
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="mem=32M console=ttyS0,115200n8 root=/dev/ram0 initrd=0x11c00000,4M"
-CONFIG_FPE_NWFPE=y
-CONFIG_PM=y
-# CONFIG_SUSPEND is not set
-CONFIG_PM_RUNTIME=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-CONFIG_IPV6=y
-# CONFIG_FW_LOADER is not set
-CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLOCK=y
-CONFIG_MTD_NAND=y
-CONFIG_MTD_NAND_AMS_DELTA=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_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_USB_CATC=y
-CONFIG_USB_KAWETH=y
-CONFIG_USB_PEGASUS=y
-CONFIG_USB_RTL8150=y
-CONFIG_USB_USBNET=y
-CONFIG_PPP=y
-CONFIG_PPP_MULTILINK=y
-CONFIG_INPUT_EVDEV=y
-CONFIG_KEYBOARD_OMAP=y
-# CONFIG_INPUT_MOUSE is not set
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-# CONFIG_LEGACY_PTYS is not set
-CONFIG_HW_RANDOM=y
-CONFIG_I2C=y
-CONFIG_I2C_CHARDEV=y
-CONFIG_I2C_OMAP=y
-CONFIG_GPIO_SYSFS=y
-# CONFIG_HWMON is not set
-CONFIG_FB=y
-CONFIG_FIRMWARE_EDID=y
-CONFIG_FB_OMAP=y
-CONFIG_BACKLIGHT_LCD_SUPPORT=y
-CONFIG_LCD_CLASS_DEVICE=y
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_FRAMEBUFFER_CONSOLE=y
-CONFIG_FONTS=y
-CONFIG_FONT_6x11=y
-CONFIG_LOGO=y
-# CONFIG_LOGO_LINUX_MONO is not set
-# CONFIG_LOGO_LINUX_VGA16 is not set
-CONFIG_SOUND=y
-CONFIG_SND=y
-CONFIG_SND_MIXER_OSS=y
-CONFIG_SND_PCM_OSS=y
-CONFIG_SND_SOC=y
-CONFIG_SND_OMAP_SOC=y
-CONFIG_SND_OMAP_SOC_AMS_DELTA=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_NEW_LEDS=y
-CONFIG_LEDS_CLASS=y
-CONFIG_LEDS_AMS_DELTA=y
-CONFIG_LEDS_TRIGGERS=y
-CONFIG_LEDS_TRIGGER_TIMER=y
-CONFIG_LEDS_TRIGGER_HEARTBEAT=y
-CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
-CONFIG_RTC_CLASS=y
-CONFIG_RTC_DRV_OMAP=y
-CONFIG_EXT2_FS=y
-CONFIG_EXT3_FS=y
-CONFIG_INOTIFY=y
-CONFIG_AUTOFS_FS=y
-CONFIG_AUTOFS4_FS=y
-CONFIG_MSDOS_FS=y
-CONFIG_VFAT_FS=y
-CONFIG_TMPFS=y
-CONFIG_JFFS2_FS=y
-CONFIG_JFFS2_SUMMARY=y
-CONFIG_NFS_FS=y
-CONFIG_PARTITION_ADVANCED=y
-CONFIG_NLS_CODEPAGE_437=y
-CONFIG_NLS_CODEPAGE_850=y
-CONFIG_NLS_CODEPAGE_852=y
-CONFIG_NLS_ISO8859_1=y
-CONFIG_NLS_ISO8859_2=y
-CONFIG_MAGIC_SYSRQ=y
-CONFIG_DEBUG_KERNEL=y
-# CONFIG_DEBUG_BUGVERBOSE is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/configs/at572d940hfek_defconfig linux-libre-2.6.38-gnu1/arch/arm/configs/at572d940hfek_defconfig
--- linux-libre-2.6.37-gnu1/arch/arm/configs/at572d940hfek_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/configs/at572d940hfek_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -17,7 +17,7 @@ CONFIG_SYSFS_DEPRECATED_V2=y
 CONFIG_RELAY=y
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 CONFIG_SLAB=y
 CONFIG_PROFILING=y
 CONFIG_OPROFILE=m
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/configs/badge4_defconfig linux-libre-2.6.38-gnu1/arch/arm/configs/badge4_defconfig
--- linux-libre-2.6.37-gnu1/arch/arm/configs/badge4_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/configs/badge4_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -1,6 +1,6 @@
 CONFIG_EXPERIMENTAL=y
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 CONFIG_MODULES=y
 CONFIG_MODVERSIONS=y
 CONFIG_ARCH_SA1100=y
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/configs/bcmring_defconfig linux-libre-2.6.38-gnu1/arch/arm/configs/bcmring_defconfig
--- linux-libre-2.6.37-gnu1/arch/arm/configs/bcmring_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/configs/bcmring_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -2,7 +2,7 @@ CONFIG_EXPERIMENTAL=y
 # CONFIG_LOCALVERSION_AUTO is not set
 # CONFIG_SWAP is not set
 CONFIG_SYSVIPC=y
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 CONFIG_KALLSYMS_EXTRA_PASS=y
 # CONFIG_HOTPLUG is not set
 # CONFIG_ELF_CORE is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/configs/cm_x2xx_defconfig linux-libre-2.6.38-gnu1/arch/arm/configs/cm_x2xx_defconfig
--- linux-libre-2.6.37-gnu1/arch/arm/configs/cm_x2xx_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/configs/cm_x2xx_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -6,7 +6,7 @@ CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_SYSFS_DEPRECATED_V2=y
 CONFIG_BLK_DEV_INITRD=y
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_VM_EVENT_COUNTERS is not set
 # CONFIG_SLUB_DEBUG is not set
 # CONFIG_COMPAT_BRK is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/configs/colibri_pxa270_defconfig linux-libre-2.6.38-gnu1/arch/arm/configs/colibri_pxa270_defconfig
--- linux-libre-2.6.37-gnu1/arch/arm/configs/colibri_pxa270_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/configs/colibri_pxa270_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -8,7 +8,7 @@ CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_SYSFS_DEPRECATED_V2=y
 CONFIG_BLK_DEV_INITRD=y
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 CONFIG_KALLSYMS_EXTRA_PASS=y
 CONFIG_SLAB=y
 CONFIG_MODULES=y
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/configs/collie_defconfig linux-libre-2.6.38-gnu1/arch/arm/configs/collie_defconfig
--- linux-libre-2.6.37-gnu1/arch/arm/configs/collie_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/configs/collie_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -4,7 +4,7 @@ CONFIG_SYSVIPC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_BASE_FULL is not set
 # CONFIG_EPOLL is not set
 CONFIG_SLOB=y
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/configs/corgi_defconfig linux-libre-2.6.38-gnu1/arch/arm/configs/corgi_defconfig
--- linux-libre-2.6.37-gnu1/arch/arm/configs/corgi_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/configs/corgi_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -4,7 +4,7 @@ CONFIG_BSD_PROCESS_ACCT=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_SYSFS_DEPRECATED_V2=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 CONFIG_PROFILING=y
 CONFIG_OPROFILE=m
 CONFIG_MODULES=y
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/configs/da8xx_omapl_defconfig linux-libre-2.6.38-gnu1/arch/arm/configs/da8xx_omapl_defconfig
--- linux-libre-2.6.37-gnu1/arch/arm/configs/da8xx_omapl_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/configs/da8xx_omapl_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -6,7 +6,7 @@ CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 CONFIG_MODULE_FORCE_UNLOAD=y
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/configs/davinci_all_defconfig linux-libre-2.6.38-gnu1/arch/arm/configs/davinci_all_defconfig
--- linux-libre-2.6.37-gnu1/arch/arm/configs/davinci_all_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/configs/davinci_all_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -6,7 +6,7 @@ CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 CONFIG_MODULE_FORCE_UNLOAD=y
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/configs/dove_defconfig linux-libre-2.6.38-gnu1/arch/arm/configs/dove_defconfig
--- linux-libre-2.6.37-gnu1/arch/arm/configs/dove_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/configs/dove_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -1,7 +1,7 @@
 CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 CONFIG_SLAB=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/configs/ebsa110_defconfig linux-libre-2.6.38-gnu1/arch/arm/configs/ebsa110_defconfig
--- linux-libre-2.6.37-gnu1/arch/arm/configs/ebsa110_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/configs/ebsa110_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -2,7 +2,7 @@ CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
 CONFIG_BSD_PROCESS_ACCT=y
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 CONFIG_MODULES=y
 CONFIG_ARCH_EBSA110=y
 CONFIG_PCCARD=m
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/configs/edb7211_defconfig linux-libre-2.6.38-gnu1/arch/arm/configs/edb7211_defconfig
--- linux-libre-2.6.37-gnu1/arch/arm/configs/edb7211_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/configs/edb7211_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -2,7 +2,7 @@ CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_HOTPLUG is not set
 CONFIG_ARCH_CLPS711X=y
 CONFIG_ARCH_EDB7211=y
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/configs/em_x270_defconfig linux-libre-2.6.38-gnu1/arch/arm/configs/em_x270_defconfig
--- linux-libre-2.6.37-gnu1/arch/arm/configs/em_x270_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/configs/em_x270_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -6,7 +6,7 @@ CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_SYSFS_DEPRECATED_V2=y
 CONFIG_BLK_DEV_INITRD=y
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_VM_EVENT_COUNTERS is not set
 # CONFIG_SLUB_DEBUG is not set
 # CONFIG_COMPAT_BRK is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/configs/ep93xx_defconfig linux-libre-2.6.38-gnu1/arch/arm/configs/ep93xx_defconfig
--- linux-libre-2.6.37-gnu1/arch/arm/configs/ep93xx_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/configs/ep93xx_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -4,7 +4,7 @@ CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 CONFIG_SLAB=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/configs/eseries_pxa_defconfig linux-libre-2.6.38-gnu1/arch/arm/configs/eseries_pxa_defconfig
--- linux-libre-2.6.37-gnu1/arch/arm/configs/eseries_pxa_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/configs/eseries_pxa_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -2,7 +2,7 @@ CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_KALLSYMS is not set
 # CONFIG_COMPAT_BRK is not set
 CONFIG_SLAB=y
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/configs/ezx_defconfig linux-libre-2.6.38-gnu1/arch/arm/configs/ezx_defconfig
--- linux-libre-2.6.37-gnu1/arch/arm/configs/ezx_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/configs/ezx_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -7,7 +7,7 @@ CONFIG_SYSFS_DEPRECATED_V2=y
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_RD_BZIP2=y
 CONFIG_RD_LZMA=y
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_COMPAT_BRK is not set
 CONFIG_SLAB=y
 CONFIG_MODULES=y
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/configs/footbridge_defconfig linux-libre-2.6.38-gnu1/arch/arm/configs/footbridge_defconfig
--- linux-libre-2.6.37-gnu1/arch/arm/configs/footbridge_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/configs/footbridge_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -3,7 +3,7 @@ CONFIG_SYSVIPC=y
 CONFIG_BSD_PROCESS_ACCT=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_HOTPLUG is not set
 CONFIG_MODULES=y
 CONFIG_ARCH_FOOTBRIDGE=y
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/configs/fortunet_defconfig linux-libre-2.6.38-gnu1/arch/arm/configs/fortunet_defconfig
--- linux-libre-2.6.37-gnu1/arch/arm/configs/fortunet_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/configs/fortunet_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -2,7 +2,7 @@ CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_HOTPLUG is not set
 CONFIG_ARCH_CLPS711X=y
 CONFIG_ARCH_FORTUNET=y
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/configs/h5000_defconfig linux-libre-2.6.38-gnu1/arch/arm/configs/h5000_defconfig
--- linux-libre-2.6.37-gnu1/arch/arm/configs/h5000_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/configs/h5000_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -4,7 +4,7 @@ CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=16
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_UID16 is not set
 CONFIG_SLAB=y
 CONFIG_MODULES=y
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/configs/htcherald_defconfig linux-libre-2.6.38-gnu1/arch/arm/configs/htcherald_defconfig
--- linux-libre-2.6.37-gnu1/arch/arm/configs/htcherald_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/configs/htcherald_defconfig	1969-12-31 19:00:00.000000000 -0500
@@ -1,73 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-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_ARCH_OMAP=y
-CONFIG_ARCH_OMAP1=y
-CONFIG_ARCH_OMAP850=y
-# CONFIG_ARCH_OMAP15XX is not set
-CONFIG_MACH_HERALD=y
-CONFIG_OMAP_ARM_195MHZ=y
-# CONFIG_OMAP_ARM_60MHZ is not set
-CONFIG_CPU_ARM925T=y
-CONFIG_PREEMPT=y
-CONFIG_AEABI=y
-CONFIG_LEDS=y
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="mem=32M console=ttyS0,115200 ip=dhcp"
-CONFIG_FPE_NWFPE=y
-CONFIG_PM=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_IP_PNP_BOOTP=y
-# CONFIG_IPV6 is not set
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-CONFIG_BLK_DEV_LOOP=y
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=8192
-CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_SMC91X=y
-# CONFIG_KEYBOARD_ATKBD is not set
-CONFIG_KEYBOARD_OMAP=y
-# CONFIG_INPUT_MOUSE is not set
-CONFIG_SERIAL_8250=m
-# CONFIG_LEGACY_PTYS is not set
-CONFIG_VIDEO_OUTPUT_CONTROL=m
-CONFIG_FB=y
-CONFIG_FB_MODE_HELPERS=y
-CONFIG_FB_OMAP=y
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_FRAMEBUFFER_CONSOLE=y
-CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
-CONFIG_FONTS=y
-CONFIG_FONT_MINI_4x6=y
-CONFIG_USB_GADGET=y
-CONFIG_USB_ETH=m
-# CONFIG_USB_ETH_RNDIS is not set
-CONFIG_MMC=y
-CONFIG_MMC_SDHCI=y
-CONFIG_MMC_SDHCI_PLTFM=y
-CONFIG_MMC_OMAP=y
-CONFIG_RTC_CLASS=y
-CONFIG_EXT2_FS=y
-CONFIG_EXT3_FS=y
-CONFIG_INOTIFY=y
-CONFIG_TMPFS=y
-CONFIG_NFS_FS=y
-CONFIG_ROOT_NFS=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
-CONFIG_CRYPTO_DEFLATE=y
-CONFIG_CRYPTO_ZLIB=y
-CONFIG_CRYPTO_LZO=y
-# CONFIG_CRYPTO_ANSI_CPRNG is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/configs/imote2_defconfig linux-libre-2.6.38-gnu1/arch/arm/configs/imote2_defconfig
--- linux-libre-2.6.37-gnu1/arch/arm/configs/imote2_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/configs/imote2_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -6,7 +6,7 @@ CONFIG_SYSFS_DEPRECATED_V2=y
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_RD_BZIP2=y
 CONFIG_RD_LZMA=y
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_COMPAT_BRK is not set
 CONFIG_SLAB=y
 CONFIG_MODULES=y
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/configs/ixp2000_defconfig linux-libre-2.6.38-gnu1/arch/arm/configs/ixp2000_defconfig
--- linux-libre-2.6.37-gnu1/arch/arm/configs/ixp2000_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/configs/ixp2000_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -3,7 +3,7 @@ CONFIG_SYSVIPC=y
 CONFIG_BSD_PROCESS_ACCT=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_HOTPLUG is not set
 CONFIG_SLAB=y
 CONFIG_MODULES=y
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/configs/ixp23xx_defconfig linux-libre-2.6.38-gnu1/arch/arm/configs/ixp23xx_defconfig
--- linux-libre-2.6.37-gnu1/arch/arm/configs/ixp23xx_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/configs/ixp23xx_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -3,7 +3,7 @@ CONFIG_SYSVIPC=y
 CONFIG_BSD_PROCESS_ACCT=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 CONFIG_SLAB=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/configs/ixp4xx_defconfig linux-libre-2.6.38-gnu1/arch/arm/configs/ixp4xx_defconfig
--- linux-libre-2.6.37-gnu1/arch/arm/configs/ixp4xx_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/configs/ixp4xx_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -3,7 +3,7 @@ CONFIG_SYSVIPC=y
 CONFIG_BSD_PROCESS_ACCT=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 CONFIG_MODULES=y
 CONFIG_MODVERSIONS=y
 # CONFIG_BLK_DEV_BSG is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/configs/loki_defconfig linux-libre-2.6.38-gnu1/arch/arm/configs/loki_defconfig
--- linux-libre-2.6.37-gnu1/arch/arm/configs/loki_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/configs/loki_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -1,7 +1,7 @@
 CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 CONFIG_SLAB=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/configs/lpd7a400_defconfig linux-libre-2.6.38-gnu1/arch/arm/configs/lpd7a400_defconfig
--- linux-libre-2.6.37-gnu1/arch/arm/configs/lpd7a400_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/configs/lpd7a400_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -3,7 +3,7 @@ CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
 CONFIG_IKCONFIG=y
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_HOTPLUG is not set
 # CONFIG_EPOLL is not set
 # CONFIG_IOSCHED_DEADLINE is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/configs/lpd7a404_defconfig linux-libre-2.6.38-gnu1/arch/arm/configs/lpd7a404_defconfig
--- linux-libre-2.6.37-gnu1/arch/arm/configs/lpd7a404_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/configs/lpd7a404_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -3,7 +3,7 @@ CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
 CONFIG_IKCONFIG=y
 CONFIG_LOG_BUF_SHIFT=16
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_HOTPLUG is not set
 # CONFIG_EPOLL is not set
 CONFIG_SLAB=y
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/configs/mackerel_defconfig linux-libre-2.6.38-gnu1/arch/arm/configs/mackerel_defconfig
--- linux-libre-2.6.37-gnu1/arch/arm/configs/mackerel_defconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/configs/mackerel_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,138 @@
+CONFIG_EXPERIMENTAL=y
+CONFIG_SYSVIPC=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=16
+# CONFIG_UTS_NS is not set
+# CONFIG_IPC_NS is not set
+# CONFIG_USER_NS is not set
+# CONFIG_PID_NS is not set
+# CONFIG_NET_NS is not set
+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_SHMOBILE=y
+CONFIG_ARCH_SH7372=y
+CONFIG_MACH_MACKEREL=y
+CONFIG_MEMORY_SIZE=0x10000000
+CONFIG_AEABI=y
+# CONFIG_OABI_COMPAT is not set
+CONFIG_FORCE_MAX_ZONEORDER=15
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="console=tty0, console=ttySC0,115200 earlyprintk=sh-sci.0,115200 root=/dev/nfs nfsroot=,tcp,v3 ip=dhcp memchunk.vpu=64m memchunk.veu0=8m memchunk.spu0=2m mem=240m"
+CONFIG_KEXEC=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_PM=y
+CONFIG_PM_RUNTIME=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_IPV6 is not set
+# CONFIG_WIRELESS is not set
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+# CONFIG_FIRMWARE_IN_KERNEL is not set
+CONFIG_MTD=y
+CONFIG_MTD_CONCAT=y
+CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_CFI=y
+CONFIG_MTD_CFI_ADV_OPTIONS=y
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_ARM_INTEGRATOR=y
+CONFIG_MTD_BLOCK2MTD=y
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+# CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_NETDEVICES=y
+CONFIG_NET_ETHERNET=y
+CONFIG_SMSC911X=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_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_SERIAL_SH_SCI=y
+CONFIG_SERIAL_SH_SCI_NR_UARTS=8
+CONFIG_SERIAL_SH_SCI_CONSOLE=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_HWMON is not set
+# CONFIG_MFD_SUPPORT is not set
+CONFIG_FB=y
+CONFIG_FB_MODE_HELPERS=y
+CONFIG_FB_SH_MOBILE_LCDC=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_CLUT224 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_EXT2_FS_XIP=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_DNOTIFY is not set
+# CONFIG_INOTIFY_USER is not set
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+# CONFIG_MISC_FILESYSTEMS is not set
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_NFS_V4_1=y
+CONFIG_ROOT_NFS=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_737=y
+CONFIG_NLS_CODEPAGE_775=y
+CONFIG_NLS_CODEPAGE_850=y
+CONFIG_NLS_CODEPAGE_852=y
+CONFIG_NLS_CODEPAGE_855=y
+CONFIG_NLS_CODEPAGE_857=y
+CONFIG_NLS_CODEPAGE_860=y
+CONFIG_NLS_CODEPAGE_861=y
+CONFIG_NLS_CODEPAGE_862=y
+CONFIG_NLS_CODEPAGE_863=y
+CONFIG_NLS_CODEPAGE_864=y
+CONFIG_NLS_CODEPAGE_865=y
+CONFIG_NLS_CODEPAGE_866=y
+CONFIG_NLS_CODEPAGE_869=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_ISO8859_2=y
+CONFIG_NLS_ISO8859_3=y
+CONFIG_NLS_ISO8859_4=y
+CONFIG_NLS_ISO8859_5=y
+CONFIG_NLS_ISO8859_6=y
+CONFIG_NLS_ISO8859_7=y
+CONFIG_NLS_ISO8859_9=y
+CONFIG_NLS_ISO8859_13=y
+CONFIG_NLS_ISO8859_14=y
+CONFIG_NLS_ISO8859_15=y
+CONFIG_NLS_KOI8_R=y
+CONFIG_NLS_KOI8_U=y
+CONFIG_NLS_UTF8=y
+# CONFIG_ENABLE_WARN_DEPRECATED is not set
+# CONFIG_ENABLE_MUST_CHECK is not set
+# CONFIG_ARM_UNWIND is not set
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ANSI_CPRNG=y
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/configs/magician_defconfig linux-libre-2.6.38-gnu1/arch/arm/configs/magician_defconfig
--- linux-libre-2.6.37-gnu1/arch/arm/configs/magician_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/configs/magician_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -4,7 +4,7 @@ CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=16
 CONFIG_BLK_DEV_INITRD=y
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_UID16 is not set
 CONFIG_SLAB=y
 CONFIG_MODULES=y
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/configs/mv78xx0_defconfig linux-libre-2.6.38-gnu1/arch/arm/configs/mv78xx0_defconfig
--- linux-libre-2.6.37-gnu1/arch/arm/configs/mv78xx0_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/configs/mv78xx0_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -2,7 +2,7 @@ CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 CONFIG_KALLSYMS_ALL=y
 # CONFIG_SLUB_DEBUG is not set
 CONFIG_PROFILING=y
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/configs/mx1_defconfig linux-libre-2.6.38-gnu1/arch/arm/configs/mx1_defconfig
--- linux-libre-2.6.37-gnu1/arch/arm/configs/mx1_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/configs/mx1_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -4,7 +4,7 @@ CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 CONFIG_SLAB=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/configs/mx21_defconfig linux-libre-2.6.38-gnu1/arch/arm/configs/mx21_defconfig
--- linux-libre-2.6.37-gnu1/arch/arm/configs/mx21_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/configs/mx21_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -4,7 +4,7 @@ CONFIG_SYSVIPC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_SYSFS_DEPRECATED_V2=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 CONFIG_KALLSYMS_EXTRA_PASS=y
 CONFIG_SLAB=y
 CONFIG_MODULES=y
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/configs/mx27_defconfig linux-libre-2.6.38-gnu1/arch/arm/configs/mx27_defconfig
--- linux-libre-2.6.37-gnu1/arch/arm/configs/mx27_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/configs/mx27_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -4,7 +4,7 @@ CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 CONFIG_KALLSYMS_EXTRA_PASS=y
 # CONFIG_COMPAT_BRK is not set
 CONFIG_SLAB=y
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/configs/mx3_defconfig linux-libre-2.6.38-gnu1/arch/arm/configs/mx3_defconfig
--- linux-libre-2.6.37-gnu1/arch/arm/configs/mx3_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/configs/mx3_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -4,7 +4,7 @@ CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 CONFIG_SLAB=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
@@ -84,6 +84,7 @@ CONFIG_SERIAL_IMX_CONSOLE=y
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
 CONFIG_I2C_IMX=y
+CONFIG_SPI=y
 CONFIG_W1=y
 CONFIG_W1_MASTER_MXC=y
 CONFIG_W1_SLAVE_THERM=y
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/configs/mx51_defconfig linux-libre-2.6.38-gnu1/arch/arm/configs/mx51_defconfig
--- linux-libre-2.6.37-gnu1/arch/arm/configs/mx51_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/configs/mx51_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -3,7 +3,7 @@ CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
 CONFIG_LOG_BUF_SHIFT=18
 CONFIG_RELAY=y
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_SLUB_DEBUG is not set
 # CONFIG_COMPAT_BRK is not set
 CONFIG_MODULES=y
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/configs/n770_defconfig linux-libre-2.6.38-gnu1/arch/arm/configs/n770_defconfig
--- linux-libre-2.6.37-gnu1/arch/arm/configs/n770_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/configs/n770_defconfig	1969-12-31 19:00:00.000000000 -0500
@@ -1,138 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-CONFIG_SYSVIPC=y
-CONFIG_POSIX_MQUEUE=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SLAB=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_BLK_DEV_BSG is not set
-# CONFIG_IOSCHED_DEADLINE is not set
-CONFIG_ARCH_OMAP=y
-CONFIG_ARCH_OMAP1=y
-CONFIG_OMAP_RESET_CLOCKS=y
-# CONFIG_OMAP_MUX is not set
-CONFIG_OMAP_MBOX_FWK=y
-CONFIG_OMAP_32K_TIMER=y
-CONFIG_OMAP_DM_TIMER=y
-# CONFIG_ARCH_OMAP15XX is not set
-CONFIG_ARCH_OMAP16XX=y
-CONFIG_MACH_NOKIA770=y
-CONFIG_OMAP_CLOCKS_SET_BY_BOOTLOADER=y
-CONFIG_OMAP_ARM_216MHZ=y
-# CONFIG_OMAP_ARM_60MHZ is not set
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="root=1f03 rootfstype=jffs2 time"
-CONFIG_FPE_NWFPE=y
-CONFIG_PM=y
-CONFIG_PM_RUNTIME=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_IP_PNP_BOOTP=y
-# CONFIG_INET_LRO is not set
-# CONFIG_INET_DIAG is not set
-# CONFIG_IPV6 is not set
-CONFIG_NETFILTER=y
-CONFIG_BT=y
-CONFIG_BT_L2CAP=y
-CONFIG_BT_SCO=y
-CONFIG_BT_RFCOMM=y
-CONFIG_BT_RFCOMM_TTY=y
-CONFIG_BT_BNEP=y
-CONFIG_BT_HIDP=y
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-CONFIG_CONNECTOR=y
-# CONFIG_PROC_EVENTS is not set
-CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
-CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLOCK=y
-CONFIG_MTD_NAND=y
-CONFIG_BLK_DEV_LOOP=y
-CONFIG_SCSI=y
-# CONFIG_SCSI_PROC_FS is not set
-CONFIG_BLK_DEV_SD=y
-CONFIG_NETDEVICES=y
-CONFIG_TUN=y
-CONFIG_NET_ETHERNET=y
-CONFIG_USB_USBNET=y
-# CONFIG_USB_NET_AX8817X is not set
-# CONFIG_USB_NET_CDC_SUBSET is not set
-CONFIG_PPP=y
-CONFIG_PPP_FILTER=y
-CONFIG_PPP_ASYNC=y
-CONFIG_PPP_DEFLATE=y
-CONFIG_PPP_BSDCOMP=y
-# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
-CONFIG_INPUT_EVDEV=y
-# CONFIG_KEYBOARD_ATKBD is not set
-CONFIG_KEYBOARD_OMAP=y
-# CONFIG_INPUT_MOUSE is not set
-CONFIG_INPUT_TOUCHSCREEN=y
-CONFIG_TOUCHSCREEN_ADS7846=y
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-# CONFIG_LEGACY_PTYS is not set
-CONFIG_I2C=y
-CONFIG_I2C_OMAP=y
-CONFIG_SPI=y
-CONFIG_SPI_OMAP_UWIRE=y
-# CONFIG_HWMON is not set
-CONFIG_WATCHDOG=y
-CONFIG_WATCHDOG_NOWAYOUT=y
-CONFIG_OMAP_WATCHDOG=y
-CONFIG_FB=y
-CONFIG_FB_OMAP=y
-CONFIG_FB_OMAP_LCDC_EXTERNAL=y
-CONFIG_FB_OMAP_LCDC_HWA742=y
-CONFIG_FB_OMAP_MANUAL_UPDATE=y
-CONFIG_FB_OMAP_LCD_MIPID=y
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_SOUND=y
-CONFIG_SND=y
-# CONFIG_SND_SUPPORT_OLD_API is not set
-CONFIG_SND_DUMMY=y
-CONFIG_SND_USB_AUDIO=y
-CONFIG_USB=y
-CONFIG_USB_DEVICEFS=y
-CONFIG_USB_SUSPEND=y
-CONFIG_USB_OTG=y
-# CONFIG_USB_OTG_WHITELIST is not set
-CONFIG_USB_OHCI_HCD=y
-CONFIG_USB_STORAGE=y
-CONFIG_USB_SERIAL=y
-CONFIG_USB_SERIAL_CONSOLE=y
-CONFIG_USB_SERIAL_PL2303=y
-CONFIG_USB_GADGET=y
-CONFIG_USB_ETH=m
-CONFIG_USB_FILE_STORAGE=m
-CONFIG_USB_FILE_STORAGE_TEST=y
-CONFIG_MMC=y
-CONFIG_MMC_OMAP=y
-CONFIG_EXT2_FS=y
-CONFIG_EXT3_FS=y
-CONFIG_MSDOS_FS=y
-CONFIG_VFAT_FS=y
-CONFIG_TMPFS=y
-CONFIG_JFFS2_FS=y
-CONFIG_JFFS2_SUMMARY=y
-CONFIG_JFFS2_COMPRESSION_OPTIONS=y
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-CONFIG_PARTITION_ADVANCED=y
-CONFIG_NLS_CODEPAGE_437=y
-CONFIG_NLS_CODEPAGE_852=y
-CONFIG_NLS_ISO8859_1=y
-CONFIG_NLS_ISO8859_15=y
-CONFIG_NLS_UTF8=y
-CONFIG_MAGIC_SYSRQ=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_DEBUG_MUTEXES=y
-CONFIG_DEBUG_ERRORS=y
-CONFIG_SECURITY=y
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/configs/nhk8815_defconfig linux-libre-2.6.38-gnu1/arch/arm/configs/nhk8815_defconfig
--- linux-libre-2.6.37-gnu1/arch/arm/configs/nhk8815_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/configs/nhk8815_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -7,7 +7,7 @@ CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_SYSFS_DEPRECATED_V2=y
 CONFIG_BLK_DEV_INITRD=y
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 CONFIG_KALLSYMS_ALL=y
 CONFIG_SLAB=y
 CONFIG_MODULES=y
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/configs/omap1_defconfig linux-libre-2.6.38-gnu1/arch/arm/configs/omap1_defconfig
--- linux-libre-2.6.37-gnu1/arch/arm/configs/omap1_defconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/configs/omap1_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,286 @@
+CONFIG_EXPERIMENTAL=y
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_IKCONFIG=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_EXPERT=y
+# CONFIG_KALLSYMS is not set
+# CONFIG_ELF_CORE is not set
+# CONFIG_BASE_FULL is not set
+# CONFIG_SHMEM is not set
+# CONFIG_VM_EVENT_COUNTERS is not set
+CONFIG_SLOB=y
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_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_OMAP=y
+CONFIG_ARCH_OMAP1=y
+CONFIG_OMAP_RESET_CLOCKS=y
+# CONFIG_OMAP_MUX is not set
+CONFIG_OMAP_MBOX_FWK=y
+CONFIG_OMAP_32K_TIMER=y
+CONFIG_OMAP_DM_TIMER=y
+CONFIG_ARCH_OMAP730=y
+CONFIG_ARCH_OMAP850=y
+CONFIG_ARCH_OMAP16XX=y
+CONFIG_MACH_OMAP_INNOVATOR=y
+CONFIG_MACH_OMAP_H2=y
+CONFIG_MACH_OMAP_H3=y
+CONFIG_MACH_OMAP_HTCWIZARD=y
+CONFIG_MACH_HERALD=y
+CONFIG_MACH_OMAP_OSK=y
+CONFIG_MACH_OMAP_PERSEUS2=y
+CONFIG_MACH_OMAP_FSAMPLE=y
+CONFIG_MACH_VOICEBLUE=y
+CONFIG_MACH_OMAP_PALMTE=y
+CONFIG_MACH_OMAP_PALMZ71=y
+CONFIG_MACH_OMAP_PALMTT=y
+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
+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="root=1f03 rootfstype=jffs2"
+CONFIG_FPE_NWFPE=y
+CONFIG_BINFMT_MISC=y
+CONFIG_PM=y
+# CONFIG_SUSPEND is not set
+CONFIG_PM_RUNTIME=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=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_INET_DIAG is not set
+CONFIG_IPV6=y
+CONFIG_NETFILTER=y
+CONFIG_BT=y
+CONFIG_BT_L2CAP=y
+CONFIG_BT_SCO=y
+CONFIG_BT_RFCOMM=y
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=y
+CONFIG_BT_HIDP=y
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+# CONFIG_STANDALONE is not set
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+CONFIG_CONNECTOR=y
+# CONFIG_PROC_EVENTS is not set
+CONFIG_MTD=y
+CONFIG_MTD_DEBUG=y
+CONFIG_MTD_DEBUG_VERBOSE=3
+CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_CFI=y
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_NAND=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=2
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_IDE=m
+CONFIG_BLK_DEV_IDECS=m
+CONFIG_SCSI=y
+# CONFIG_SCSI_PROC_FS is not set
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_ST=y
+CONFIG_BLK_DEV_SR=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_NETDEVICES=y
+CONFIG_TUN=y
+CONFIG_PHYLIB=y
+CONFIG_NET_ETHERNET=y
+CONFIG_SMC91X=y
+CONFIG_USB_CATC=y
+CONFIG_USB_KAWETH=y
+CONFIG_USB_PEGASUS=y
+CONFIG_USB_RTL8150=y
+CONFIG_USB_USBNET=y
+# CONFIG_USB_NET_AX8817X is not set
+# CONFIG_USB_NET_CDC_SUBSET is not set
+CONFIG_PPP=y
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_ASYNC=y
+CONFIG_PPP_DEFLATE=y
+CONFIG_PPP_BSDCOMP=y
+CONFIG_SLIP=y
+CONFIG_SLIP_COMPRESSED=y
+# CONFIG_INPUT_MOUSEDEV is not set
+CONFIG_INPUT_EVDEV=y
+CONFIG_INPUT_EVBUG=y
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_ADS7846=y
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_UINPUT=y
+# CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=3
+CONFIG_SERIAL_8250_RUNTIME_UARTS=3
+# CONFIG_LEGACY_PTYS is not set
+CONFIG_HW_RANDOM=y
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_SPI=y
+CONFIG_SPI_OMAP_UWIRE=y
+# CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_NOWAYOUT=y
+CONFIG_OMAP_WATCHDOG=y
+CONFIG_VIDEO_OUTPUT_CONTROL=y
+CONFIG_FB=y
+CONFIG_FIRMWARE_EDID=y
+CONFIG_FB_MODE_HELPERS=y
+CONFIG_FB_VIRTUAL=y
+CONFIG_FB_OMAP=y
+CONFIG_FB_OMAP_LCDC_EXTERNAL=y
+CONFIG_FB_OMAP_LCDC_HWA742=y
+CONFIG_FB_OMAP_MANUAL_UPDATE=y
+CONFIG_FB_OMAP_LCD_MIPID=y
+CONFIG_FB_OMAP_BOOTLOADER_INIT=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_LCD_CLASS_DEVICE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
+CONFIG_FONTS=y
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+CONFIG_FONT_6x11=y
+CONFIG_FONT_MINI_4x6=y
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_SOUND=y
+CONFIG_SND=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_DUMMY=y
+CONFIG_SND_USB_AUDIO=y
+CONFIG_SND_SOC=y
+CONFIG_SND_OMAP_SOC=y
+# CONFIG_USB_HID is not set
+CONFIG_USB=y
+CONFIG_USB_DEBUG=y
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_DEVICE_CLASS is not set
+CONFIG_USB_SUSPEND=y
+CONFIG_USB_MON=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_STORAGE_DATAFAB=y
+CONFIG_USB_STORAGE_FREECOM=y
+CONFIG_USB_STORAGE_SDDR09=y
+CONFIG_USB_STORAGE_SDDR55=y
+CONFIG_USB_STORAGE_JUMPSHOT=y
+CONFIG_USB_SERIAL=y
+CONFIG_USB_SERIAL_CONSOLE=y
+CONFIG_USB_SERIAL_PL2303=y
+CONFIG_USB_TEST=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_ETH=m
+# CONFIG_USB_ETH_RNDIS is not set
+CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_FILE_STORAGE_TEST=y
+CONFIG_MMC=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_PLTFM=y
+CONFIG_MMC_OMAP=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_OMAP=y
+CONFIG_EXT2_FS=y
+CONFIG_EXT3_FS=y
+# CONFIG_DNOTIFY is not set
+CONFIG_AUTOFS4_FS=y
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=866
+CONFIG_FAT_DEFAULT_IOCHARSET="koi8-r"
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_SUMMARY=y
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_CRAMFS=y
+CONFIG_ROMFS_FS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_NFS_V4=y
+CONFIG_ROOT_NFS=y
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_850=y
+CONFIG_NLS_CODEPAGE_852=y
+CONFIG_NLS_CODEPAGE_866=y
+CONFIG_NLS_CODEPAGE_1251=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_ISO8859_2=y
+CONFIG_NLS_ISO8859_5=y
+CONFIG_NLS_ISO8859_15=y
+CONFIG_NLS_KOI8_R=y
+CONFIG_NLS_UTF8=y
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_DEBUG_SPINLOCK=y
+CONFIG_DEBUG_MUTEXES=y
+# CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_DEBUG_INFO=y
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+CONFIG_DEBUG_USER=y
+CONFIG_DEBUG_ERRORS=y
+CONFIG_SECURITY=y
+CONFIG_CRYPTO_ECB=y
+CONFIG_CRYPTO_PCBC=y
+CONFIG_CRYPTO_DEFLATE=y
+CONFIG_CRYPTO_ZLIB=y
+CONFIG_CRYPTO_LZO=y
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_LIBCRC32C=y
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/configs/omap2plus_defconfig linux-libre-2.6.38-gnu1/arch/arm/configs/omap2plus_defconfig
--- linux-libre-2.6.37-gnu1/arch/arm/configs/omap2plus_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/configs/omap2plus_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -6,7 +6,7 @@ CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=16
 CONFIG_BLK_DEV_INITRD=y
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_SYSCTL_SYSCALL is not set
 CONFIG_KALLSYMS_EXTRA_PASS=y
 CONFIG_SLAB=y
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/configs/omap_generic_1510_defconfig linux-libre-2.6.38-gnu1/arch/arm/configs/omap_generic_1510_defconfig
--- linux-libre-2.6.37-gnu1/arch/arm/configs/omap_generic_1510_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/configs/omap_generic_1510_defconfig	1969-12-31 19:00:00.000000000 -0500
@@ -1,84 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-CONFIG_SYSVIPC=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_SLAB=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-CONFIG_MODULE_FORCE_UNLOAD=y
-# CONFIG_BLK_DEV_BSG is not set
-CONFIG_ARCH_OMAP=y
-CONFIG_ARCH_OMAP1=y
-CONFIG_MACH_OMAP_GENERIC=y
-CONFIG_OMAP_ARM_168MHZ=y
-# CONFIG_OMAP_ARM_60MHZ is not set
-# CONFIG_ARM_THUMB is not set
-CONFIG_PREEMPT=y
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="mem=64M console=ttyS2,115200 root=0803 ro init=/bin/sh"
-CONFIG_FPE_NWFPE=y
-CONFIG_PM=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_IP_PNP_BOOTP=y
-# CONFIG_IPV6 is not set
-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_BLK_DEV_SR=y
-CONFIG_CHR_DEV_SG=y
-CONFIG_SCSI_MULTI_LUN=y
-CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_USB_RTL8150=y
-CONFIG_USB_USBNET=y
-CONFIG_USB_AN2720=y
-CONFIG_USB_EPSON2888=y
-CONFIG_PPP=y
-CONFIG_PPP_MULTILINK=y
-CONFIG_KEYBOARD_OMAP=y
-# CONFIG_INPUT_MOUSE is not set
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-# CONFIG_LEGACY_PTYS is not set
-CONFIG_I2C=y
-CONFIG_I2C_CHARDEV=y
-CONFIG_VIDEO_OUTPUT_CONTROL=m
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_USB=y
-CONFIG_USB_DEBUG=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_STORAGE_DATAFAB=y
-CONFIG_USB_STORAGE_FREECOM=y
-CONFIG_USB_STORAGE_SDDR09=y
-CONFIG_USB_STORAGE_SDDR55=y
-CONFIG_USB_STORAGE_JUMPSHOT=y
-CONFIG_MMC=y
-CONFIG_MMC_OMAP=y
-CONFIG_RTC_CLASS=y
-CONFIG_RTC_DRV_OMAP=y
-CONFIG_EXT2_FS=y
-CONFIG_EXT3_FS=y
-CONFIG_INOTIFY=y
-CONFIG_AUTOFS_FS=y
-CONFIG_AUTOFS4_FS=y
-CONFIG_ISO9660_FS=y
-CONFIG_JOLIET=y
-CONFIG_MSDOS_FS=m
-CONFIG_VFAT_FS=m
-CONFIG_NFS_FS=y
-CONFIG_PARTITION_ADVANCED=y
-CONFIG_MAGIC_SYSRQ=y
-CONFIG_DEBUG_KERNEL=y
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/configs/omap_generic_1610_defconfig linux-libre-2.6.38-gnu1/arch/arm/configs/omap_generic_1610_defconfig
--- linux-libre-2.6.37-gnu1/arch/arm/configs/omap_generic_1610_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/configs/omap_generic_1610_defconfig	1969-12-31 19:00:00.000000000 -0500
@@ -1,87 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-CONFIG_SYSVIPC=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_SLAB=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-CONFIG_MODULE_FORCE_UNLOAD=y
-# CONFIG_BLK_DEV_BSG is not set
-CONFIG_ARCH_OMAP=y
-CONFIG_ARCH_OMAP1=y
-# CONFIG_ARCH_OMAP15XX is not set
-CONFIG_ARCH_OMAP16XX=y
-CONFIG_MACH_OMAP_GENERIC=y
-CONFIG_OMAP_ARM_192MHZ=y
-# CONFIG_OMAP_ARM_60MHZ is not set
-# CONFIG_ARM_THUMB is not set
-CONFIG_PREEMPT=y
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="mem=64M console=ttyS2,115200 root=0803 ro init=/bin/sh"
-CONFIG_FPE_NWFPE=y
-CONFIG_PM=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_IP_PNP_BOOTP=y
-# CONFIG_IPV6 is not set
-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_BLK_DEV_SR=y
-CONFIG_CHR_DEV_SG=y
-CONFIG_SCSI_MULTI_LUN=y
-CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_USB_RTL8150=y
-CONFIG_USB_USBNET=y
-CONFIG_USB_ALI_M5632=y
-CONFIG_USB_AN2720=y
-CONFIG_USB_EPSON2888=y
-CONFIG_PPP=y
-CONFIG_PPP_MULTILINK=y
-CONFIG_KEYBOARD_OMAP=y
-# CONFIG_INPUT_MOUSE is not set
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-# CONFIG_LEGACY_PTYS is not set
-CONFIG_I2C=y
-CONFIG_I2C_CHARDEV=y
-CONFIG_VIDEO_OUTPUT_CONTROL=m
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_USB=y
-CONFIG_USB_DEBUG=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_STORAGE_DATAFAB=y
-CONFIG_USB_STORAGE_FREECOM=y
-CONFIG_USB_STORAGE_SDDR09=y
-CONFIG_USB_STORAGE_SDDR55=y
-CONFIG_USB_STORAGE_JUMPSHOT=y
-CONFIG_MMC=y
-CONFIG_MMC_OMAP=y
-CONFIG_RTC_CLASS=y
-CONFIG_RTC_DRV_OMAP=y
-CONFIG_EXT2_FS=y
-CONFIG_EXT3_FS=y
-CONFIG_INOTIFY=y
-CONFIG_AUTOFS_FS=y
-CONFIG_AUTOFS4_FS=y
-CONFIG_ISO9660_FS=y
-CONFIG_JOLIET=y
-CONFIG_MSDOS_FS=m
-CONFIG_VFAT_FS=m
-CONFIG_NFS_FS=y
-CONFIG_PARTITION_ADVANCED=y
-CONFIG_MAGIC_SYSRQ=y
-CONFIG_DEBUG_KERNEL=y
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/configs/omap_generic_1710_defconfig linux-libre-2.6.38-gnu1/arch/arm/configs/omap_generic_1710_defconfig
--- linux-libre-2.6.37-gnu1/arch/arm/configs/omap_generic_1710_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/configs/omap_generic_1710_defconfig	1969-12-31 19:00:00.000000000 -0500
@@ -1,75 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-CONFIG_SYSVIPC=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_BLK_DEV_INITRD=y
-# CONFIG_BLK_DEV_BSG is not set
-CONFIG_ARCH_OMAP=y
-CONFIG_ARCH_OMAP1=y
-# CONFIG_OMAP_MUX is not set
-# CONFIG_ARCH_OMAP15XX is not set
-CONFIG_ARCH_OMAP16XX=y
-CONFIG_MACH_OMAP_GENERIC=y
-CONFIG_OMAP_ARM_192MHZ=y
-# CONFIG_OMAP_ARM_60MHZ is not set
-# CONFIG_ARM_THUMB is not set
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="mem=64M console=tty0 console=ttyS2,115200 root=0801"
-CONFIG_FPE_NWFPE=y
-CONFIG_ARTHUR=y
-CONFIG_PM=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_IP_PNP_BOOTP=y
-# CONFIG_IPV6 is not set
-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_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_USB_USBNET=y
-CONFIG_USB_ALI_M5632=y
-# CONFIG_USB_BELKIN is not set
-# CONFIG_USB_ARMLINUX is not set
-CONFIG_PPP=y
-CONFIG_INPUT_EVDEV=y
-CONFIG_KEYBOARD_OMAP=y
-# CONFIG_INPUT_MOUSE is not set
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_VIDEO_OUTPUT_CONTROL=y
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_USB=y
-CONFIG_USB_DEBUG=y
-CONFIG_USB_DEVICEFS=y
-CONFIG_USB_MON=y
-CONFIG_USB_OHCI_HCD=y
-CONFIG_USB_STORAGE=y
-CONFIG_MMC=y
-CONFIG_MMC_OMAP=y
-CONFIG_EXT2_FS=y
-CONFIG_EXT3_FS=y
-CONFIG_INOTIFY=y
-CONFIG_TMPFS=y
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-CONFIG_NFS_V4=y
-CONFIG_PARTITION_ADVANCED=y
-CONFIG_NLS_CODEPAGE_437=y
-CONFIG_NLS_CODEPAGE_852=y
-CONFIG_NLS_ISO8859_1=y
-CONFIG_NLS_ISO8859_15=y
-CONFIG_MAGIC_SYSRQ=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_DEBUG_SPINLOCK=y
-CONFIG_DEBUG_ERRORS=y
-CONFIG_SECURITY=y
-CONFIG_CRYPTO_ECB=y
-CONFIG_CRYPTO_PCBC=y
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/configs/omap_h2_1610_defconfig linux-libre-2.6.38-gnu1/arch/arm/configs/omap_h2_1610_defconfig
--- linux-libre-2.6.37-gnu1/arch/arm/configs/omap_h2_1610_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/configs/omap_h2_1610_defconfig	1969-12-31 19:00:00.000000000 -0500
@@ -1,109 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-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_ARCH_OMAP=y
-CONFIG_ARCH_OMAP1=y
-CONFIG_OMAP_MUX_DEBUG=y
-CONFIG_OMAP_32K_TIMER=y
-CONFIG_OMAP_DM_TIMER=y
-# CONFIG_ARCH_OMAP15XX is not set
-CONFIG_ARCH_OMAP16XX=y
-CONFIG_MACH_OMAP_H2=y
-CONFIG_NO_HZ=y
-CONFIG_HIGH_RES_TIMERS=y
-CONFIG_LEDS=y
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="mem=32M console=ttyS0,115200n8 root=/dev/ram0 rw initrd=0x10600000,8M ramdisk_size=8192"
-CONFIG_FPE_NWFPE=y
-CONFIG_PM=y
-CONFIG_PM_RUNTIME=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_LRO is not set
-# CONFIG_IPV6 is not set
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-CONFIG_DEBUG_DRIVER=y
-CONFIG_MTD=y
-CONFIG_MTD_DEBUG=y
-CONFIG_MTD_DEBUG_VERBOSE=3
-CONFIG_MTD_PARTITIONS=y
-CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLOCK=y
-CONFIG_MTD_CFI=y
-CONFIG_MTD_CFI_INTELEXT=y
-CONFIG_BLK_DEV_LOOP=y
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=8192
-CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_SMC91X=y
-CONFIG_PPP=y
-CONFIG_SLIP=y
-CONFIG_SLIP_COMPRESSED=y
-CONFIG_INPUT_EVDEV=y
-CONFIG_INPUT_EVBUG=y
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-CONFIG_INPUT_MISC=y
-CONFIG_INPUT_UINPUT=y
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-# CONFIG_LEGACY_PTYS is not set
-CONFIG_I2C=y
-CONFIG_I2C_OMAP=y
-CONFIG_SPI=y
-CONFIG_SPI_OMAP_UWIRE=y
-CONFIG_WATCHDOG=y
-CONFIG_WATCHDOG_NOWAYOUT=y
-CONFIG_VIDEO_OUTPUT_CONTROL=m
-CONFIG_FB=y
-CONFIG_FIRMWARE_EDID=y
-CONFIG_FB_MODE_HELPERS=y
-CONFIG_FB_OMAP=y
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_FRAMEBUFFER_CONSOLE=y
-CONFIG_LOGO=y
-# CONFIG_LOGO_LINUX_MONO is not set
-# CONFIG_LOGO_LINUX_VGA16 is not set
-# CONFIG_USB_HID is not set
-CONFIG_USB=y
-CONFIG_USB_DEVICEFS=y
-# CONFIG_USB_DEVICE_CLASS is not set
-CONFIG_USB_SUSPEND=y
-CONFIG_USB_OTG=y
-CONFIG_USB_MON=y
-CONFIG_USB_OHCI_HCD=y
-CONFIG_USB_TEST=y
-CONFIG_USB_GADGET=y
-CONFIG_USB_ETH=m
-CONFIG_MMC=y
-CONFIG_MMC_OMAP=y
-CONFIG_RTC_CLASS=y
-CONFIG_RTC_DRV_OMAP=y
-CONFIG_EXT2_FS=y
-CONFIG_INOTIFY=y
-CONFIG_MSDOS_FS=y
-CONFIG_VFAT_FS=y
-CONFIG_JFFS2_FS=y
-CONFIG_CRAMFS=y
-CONFIG_ROMFS_FS=y
-CONFIG_NFS_FS=y
-CONFIG_ROOT_NFS=y
-CONFIG_NLS_CODEPAGE_437=y
-CONFIG_NLS_ISO8859_1=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_DEBUG_INFO=y
-CONFIG_DEBUG_USER=y
-CONFIG_DEBUG_ERRORS=y
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/configs/omap_innovator_1510_defconfig linux-libre-2.6.38-gnu1/arch/arm/configs/omap_innovator_1510_defconfig
--- linux-libre-2.6.37-gnu1/arch/arm/configs/omap_innovator_1510_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/configs/omap_innovator_1510_defconfig	1969-12-31 19:00:00.000000000 -0500
@@ -1,102 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-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_ARCH_OMAP=y
-CONFIG_ARCH_OMAP1=y
-CONFIG_MACH_OMAP_INNOVATOR=y
-CONFIG_OMAP_ARM_168MHZ=y
-# CONFIG_OMAP_ARM_60MHZ is not set
-CONFIG_PREEMPT=y
-CONFIG_LEDS=y
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="console=ttyS0,115200n8 root=/dev/nfs ip=bootp noinitrd"
-CONFIG_FPE_NWFPE=y
-CONFIG_PM=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_IP_PNP_BOOTP=y
-# CONFIG_IPV6 is not set
-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_CHR_DEV_ST=y
-CONFIG_BLK_DEV_SR=y
-CONFIG_CHR_DEV_SG=y
-CONFIG_SCSI_MULTI_LUN=y
-CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_SMC91X=y
-CONFIG_USB_RTL8150=y
-CONFIG_USB_USBNET=y
-# CONFIG_USB_NET_CDC_SUBSET is not set
-CONFIG_PPP=y
-CONFIG_PPP_MULTILINK=y
-CONFIG_PPP_ASYNC=y
-CONFIG_PPP_DEFLATE=y
-CONFIG_PPP_BSDCOMP=y
-CONFIG_INPUT_MOUSEDEV_SCREEN_X=240
-CONFIG_INPUT_MOUSEDEV_SCREEN_Y=320
-# CONFIG_KEYBOARD_ATKBD is not set
-CONFIG_KEYBOARD_OMAP=y
-# CONFIG_INPUT_MOUSE is not set
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-# CONFIG_LEGACY_PTYS is not set
-CONFIG_I2C=y
-CONFIG_VIDEO_OUTPUT_CONTROL=m
-CONFIG_FB=y
-CONFIG_FB_OMAP=y
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_FRAMEBUFFER_CONSOLE=y
-CONFIG_FONTS=y
-CONFIG_FONT_8x8=y
-CONFIG_FONT_8x16=y
-CONFIG_LOGO=y
-CONFIG_USB=y
-CONFIG_USB_DEBUG=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_STORAGE_DATAFAB=y
-CONFIG_USB_STORAGE_FREECOM=y
-CONFIG_USB_STORAGE_SDDR09=y
-CONFIG_USB_STORAGE_SDDR55=y
-CONFIG_USB_STORAGE_JUMPSHOT=y
-CONFIG_MMC=y
-CONFIG_MMC_OMAP=y
-CONFIG_RTC_CLASS=y
-CONFIG_RTC_DRV_OMAP=y
-CONFIG_EXT2_FS=y
-CONFIG_EXT3_FS=y
-CONFIG_INOTIFY=y
-CONFIG_AUTOFS_FS=y
-CONFIG_AUTOFS4_FS=y
-CONFIG_ISO9660_FS=y
-CONFIG_JOLIET=y
-CONFIG_MSDOS_FS=m
-CONFIG_VFAT_FS=m
-CONFIG_TMPFS=y
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-CONFIG_NFS_V4=y
-CONFIG_ROOT_NFS=y
-CONFIG_PARTITION_ADVANCED=y
-CONFIG_MAGIC_SYSRQ=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_CRYPTO_ECB=m
-CONFIG_CRYPTO_PCBC=m
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/configs/omap_innovator_1610_defconfig linux-libre-2.6.38-gnu1/arch/arm/configs/omap_innovator_1610_defconfig
--- linux-libre-2.6.37-gnu1/arch/arm/configs/omap_innovator_1610_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/configs/omap_innovator_1610_defconfig	1969-12-31 19:00:00.000000000 -0500
@@ -1,58 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-CONFIG_SYSVIPC=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_BLK_DEV_BSG is not set
-CONFIG_ARCH_OMAP=y
-CONFIG_ARCH_OMAP1=y
-# CONFIG_ARCH_OMAP15XX is not set
-CONFIG_ARCH_OMAP16XX=y
-CONFIG_MACH_OMAP_INNOVATOR=y
-CONFIG_OMAP_ARM_192MHZ=y
-# CONFIG_OMAP_ARM_60MHZ is not set
-# CONFIG_ARM_THUMB is not set
-CONFIG_CPU_DCACHE_WRITETHROUGH=y
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="mem=32M console=tty0 console=ttyS0,115200 initrd=0x10200000,8M root=/dev/ram0 rw"
-CONFIG_FPE_NWFPE=y
-CONFIG_NET=y
-CONFIG_PACKET=m
-CONFIG_UNIX=y
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_IPV6 is not set
-CONFIG_BLK_DEV_LOOP=y
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=8192
-CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_SMC91X=y
-CONFIG_PPP=y
-CONFIG_PPP_MULTILINK=y
-# CONFIG_KEYBOARD_ATKBD is not set
-CONFIG_KEYBOARD_OMAP=y
-# CONFIG_INPUT_MOUSE is not set
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_VIDEO_OUTPUT_CONTROL=m
-CONFIG_FB=y
-CONFIG_FB_MODE_HELPERS=y
-CONFIG_FB_OMAP=y
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_FRAMEBUFFER_CONSOLE=y
-CONFIG_FONTS=y
-CONFIG_FONT_8x8=y
-CONFIG_FONT_8x16=y
-CONFIG_LOGO=y
-CONFIG_EXT2_FS=y
-CONFIG_INOTIFY=y
-CONFIG_AUTOFS_FS=y
-CONFIG_AUTOFS4_FS=y
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/configs/omap_osk_5912_defconfig linux-libre-2.6.38-gnu1/arch/arm/configs/omap_osk_5912_defconfig
--- linux-libre-2.6.37-gnu1/arch/arm/configs/omap_osk_5912_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/configs/omap_osk_5912_defconfig	1969-12-31 19:00:00.000000000 -0500
@@ -1,87 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-CONFIG_SYSVIPC=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_BLK_DEV_BSG is not set
-CONFIG_ARCH_OMAP=y
-CONFIG_ARCH_OMAP1=y
-CONFIG_OMAP_RESET_CLOCKS=y
-CONFIG_OMAP_32K_TIMER=y
-# CONFIG_ARCH_OMAP15XX is not set
-CONFIG_ARCH_OMAP16XX=y
-CONFIG_MACH_OMAP_OSK=y
-CONFIG_OMAP_ARM_192MHZ=y
-# CONFIG_OMAP_ARM_60MHZ is not set
-# CONFIG_ARM_THUMB is not set
-CONFIG_PCCARD=y
-CONFIG_OMAP_CF=y
-CONFIG_NO_HZ=y
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="mem=32M console=ttyS0,115200 initrd=0x10400000,8M root=/dev/ram0 rw"
-CONFIG_FPE_NWFPE=y
-CONFIG_PM=y
-CONFIG_NET=y
-CONFIG_PACKET=m
-CONFIG_UNIX=y
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_INET_LRO 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_INTELEXT=y
-CONFIG_BLK_DEV_LOOP=y
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=8192
-CONFIG_IDE=m
-CONFIG_BLK_DEV_IDECS=m
-CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_SMC91X=y
-CONFIG_PPP=y
-CONFIG_PPP_MULTILINK=y
-# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
-CONFIG_INPUT_EVDEV=y
-# CONFIG_KEYBOARD_ATKBD is not set
-CONFIG_KEYBOARD_OMAP=y
-# CONFIG_INPUT_MOUSE is not set
-CONFIG_INPUT_TOUCHSCREEN=y
-# CONFIG_SERIO is not set
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_I2C=y
-CONFIG_I2C_CHARDEV=y
-CONFIG_VIDEO_OUTPUT_CONTROL=m
-CONFIG_FB=y
-CONFIG_FB_MODE_HELPERS=y
-CONFIG_FB_OMAP=y
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_FRAMEBUFFER_CONSOLE=y
-CONFIG_FONTS=y
-CONFIG_FONT_8x8=y
-CONFIG_LOGO=y
-# CONFIG_LOGO_LINUX_MONO is not set
-# CONFIG_LOGO_LINUX_VGA16 is not set
-CONFIG_EXT2_FS=y
-CONFIG_INOTIFY=y
-CONFIG_AUTOFS_FS=y
-CONFIG_AUTOFS4_FS=y
-CONFIG_MSDOS_FS=m
-CONFIG_VFAT_FS=m
-CONFIG_JFFS2_FS=y
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-CONFIG_ROOT_NFS=y
-CONFIG_NLS_CODEPAGE_437=m
-CONFIG_NLS_ISO8859_1=m
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/configs/omap_perseus2_730_defconfig linux-libre-2.6.38-gnu1/arch/arm/configs/omap_perseus2_730_defconfig
--- linux-libre-2.6.37-gnu1/arch/arm/configs/omap_perseus2_730_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/configs/omap_perseus2_730_defconfig	1969-12-31 19:00:00.000000000 -0500
@@ -1,65 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-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_ARCH_OMAP=y
-CONFIG_ARCH_OMAP1=y
-CONFIG_ARCH_OMAP730=y
-# CONFIG_ARCH_OMAP15XX is not set
-CONFIG_MACH_OMAP_PERSEUS2=y
-CONFIG_OMAP_ARM_182MHZ=y
-# CONFIG_OMAP_ARM_60MHZ is not set
-# CONFIG_ARM_THUMB is not set
-CONFIG_PREEMPT=y
-CONFIG_LEDS=y
-CONFIG_LEDS_CPU=y
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="mem=32M console=ttyS0,115200 ip=dhcp"
-CONFIG_FPE_NWFPE=y
-CONFIG_PM=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_IP_PNP_BOOTP=y
-# CONFIG_IPV6 is not set
-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_INTELEXT=y
-CONFIG_MTD_NAND=y
-CONFIG_BLK_DEV_LOOP=y
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=8192
-CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_SMC91X=y
-# CONFIG_KEYBOARD_ATKBD is not set
-CONFIG_KEYBOARD_OMAP=y
-# CONFIG_INPUT_MOUSE is not set
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-# CONFIG_LEGACY_PTYS is not set
-CONFIG_VIDEO_OUTPUT_CONTROL=m
-CONFIG_FB=y
-CONFIG_FB_MODE_HELPERS=y
-CONFIG_FB_VIRTUAL=y
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_RTC_CLASS=y
-CONFIG_RTC_DRV_OMAP=y
-CONFIG_EXT2_FS=y
-CONFIG_INOTIFY=y
-CONFIG_JFFS2_FS=y
-CONFIG_NFS_FS=y
-CONFIG_ROOT_NFS=y
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/configs/orion5x_defconfig linux-libre-2.6.38-gnu1/arch/arm/configs/orion5x_defconfig
--- linux-libre-2.6.37-gnu1/arch/arm/configs/orion5x_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/configs/orion5x_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -2,7 +2,7 @@ CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_SLUB_DEBUG is not set
 CONFIG_PROFILING=y
 CONFIG_OPROFILE=y
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/configs/palmte_defconfig linux-libre-2.6.38-gnu1/arch/arm/configs/palmte_defconfig
--- linux-libre-2.6.37-gnu1/arch/arm/configs/palmte_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/configs/palmte_defconfig	1969-12-31 19:00:00.000000000 -0500
@@ -1,48 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-# CONFIG_SWAP is not set
-CONFIG_SYSVIPC=y
-CONFIG_BSD_PROCESS_ACCT=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SLAB=y
-# CONFIG_IOSCHED_DEADLINE is not set
-# CONFIG_IOSCHED_CFQ is not set
-CONFIG_ARCH_OMAP=y
-CONFIG_ARCH_OMAP1=y
-CONFIG_MACH_OMAP_PALMTE=y
-CONFIG_OMAP_CLOCKS_SET_BY_BOOTLOADER=y
-# CONFIG_OMAP_ARM_60MHZ is not set
-# CONFIG_ARM_THUMB is not set
-# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_FPE_NWFPE=y
-# CONFIG_STANDALONE is not set
-# CONFIG_PREVENT_FIRMWARE_BUILD is not set
-# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
-CONFIG_INPUT_MOUSEDEV_SCREEN_X=320
-CONFIG_INPUT_MOUSEDEV_SCREEN_Y=320
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_SERIO is not set
-# CONFIG_LEGACY_PTYS is not set
-# CONFIG_HWMON is not set
-CONFIG_FB=y
-CONFIG_FB_OMAP=y
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_FRAMEBUFFER_CONSOLE=y
-CONFIG_LOGO=y
-# CONFIG_LOGO_LINUX_MONO is not set
-# CONFIG_LOGO_LINUX_VGA16 is not set
-CONFIG_USB_GADGET=y
-CONFIG_MMC=y
-CONFIG_MMC_OMAP=y
-CONFIG_EXT2_FS=y
-CONFIG_MSDOS_FS=y
-CONFIG_VFAT_FS=y
-CONFIG_FAT_DEFAULT_CODEPAGE=850
-CONFIG_TMPFS=y
-CONFIG_CRAMFS=y
-CONFIG_PARTITION_ADVANCED=y
-CONFIG_NLS_CODEPAGE_850=y
-CONFIG_NLS_ISO8859_1=y
-CONFIG_CRC_CCITT=y
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/configs/palmtt_defconfig linux-libre-2.6.38-gnu1/arch/arm/configs/palmtt_defconfig
--- linux-libre-2.6.37-gnu1/arch/arm/configs/palmtt_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/configs/palmtt_defconfig	1969-12-31 19:00:00.000000000 -0500
@@ -1,56 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-CONFIG_SYSVIPC=y
-CONFIG_BSD_PROCESS_ACCT=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SLAB=y
-# CONFIG_IOSCHED_DEADLINE is not set
-# CONFIG_IOSCHED_CFQ is not set
-CONFIG_ARCH_OMAP=y
-CONFIG_ARCH_OMAP1=y
-CONFIG_MACH_OMAP_PALMTT=y
-CONFIG_OMAP_CLOCKS_SET_BY_BOOTLOADER=y
-# CONFIG_OMAP_ARM_60MHZ is not set
-# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="root=/dev/mmcblk0p2 rw init=/init"
-CONFIG_FPE_NWFPE=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_NET_KEY=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_DIAG is not set
-# CONFIG_IPV6 is not set
-CONFIG_INPUT_MOUSEDEV_SCREEN_X=320
-CONFIG_INPUT_MOUSEDEV_SCREEN_Y=320
-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_SPI=y
-CONFIG_SPI_OMAP_UWIRE=y
-CONFIG_FB=y
-CONFIG_FIRMWARE_EDID=y
-CONFIG_FB_OMAP=y
-CONFIG_BACKLIGHT_LCD_SUPPORT=y
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_FRAMEBUFFER_CONSOLE=y
-CONFIG_NEW_LEDS=y
-CONFIG_LEDS_CLASS=y
-CONFIG_LEDS_TRIGGERS=y
-CONFIG_LEDS_TRIGGER_TIMER=y
-CONFIG_LEDS_TRIGGER_HEARTBEAT=y
-CONFIG_RTC_CLASS=y
-CONFIG_RTC_DRV_OMAP=y
-CONFIG_EXT2_FS=y
-CONFIG_PARTITION_ADVANCED=y
-# CONFIG_ENABLE_MUST_CHECK is not set
-CONFIG_CRC_CCITT=y
-CONFIG_CRC16=y
-CONFIG_LIBCRC32C=y
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/configs/palmz71_defconfig linux-libre-2.6.38-gnu1/arch/arm/configs/palmz71_defconfig
--- linux-libre-2.6.37-gnu1/arch/arm/configs/palmz71_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/configs/palmz71_defconfig	1969-12-31 19:00:00.000000000 -0500
@@ -1,53 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-CONFIG_LOCALVERSION="-z71"
-CONFIG_SYSVIPC=y
-CONFIG_BSD_PROCESS_ACCT=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SLAB=y
-# CONFIG_IOSCHED_DEADLINE is not set
-# CONFIG_IOSCHED_CFQ is not set
-CONFIG_ARCH_OMAP=y
-CONFIG_ARCH_OMAP1=y
-CONFIG_MACH_OMAP_PALMZ71=y
-CONFIG_OMAP_CLOCKS_SET_BY_BOOTLOADER=y
-# CONFIG_OMAP_ARM_60MHZ is not set
-# CONFIG_ARM_THUMB is not set
-# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_FPE_NWFPE=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_NET_KEY=y
-CONFIG_INET=y
-# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
-# CONFIG_INET_DIAG is not set
-# CONFIG_IPV6 is not set
-CONFIG_INPUT_MOUSEDEV_SCREEN_X=320
-CONFIG_INPUT_MOUSEDEV_SCREEN_Y=320
-# 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_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_LEGACY_PTY_COUNT=16
-CONFIG_SPI=y
-CONFIG_SPI_OMAP_UWIRE=y
-CONFIG_FB=y
-CONFIG_FIRMWARE_EDID=y
-CONFIG_FB_OMAP=y
-CONFIG_BACKLIGHT_LCD_SUPPORT=y
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_FRAMEBUFFER_CONSOLE=y
-CONFIG_MMC=y
-CONFIG_MMC_OMAP=y
-CONFIG_RTC_CLASS=y
-CONFIG_RTC_DRV_OMAP=y
-CONFIG_EXT2_FS=y
-CONFIG_CRC_CCITT=y
-CONFIG_CRC16=y
-CONFIG_LIBCRC32C=y
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/configs/pcm027_defconfig linux-libre-2.6.38-gnu1/arch/arm/configs/pcm027_defconfig
--- linux-libre-2.6.37-gnu1/arch/arm/configs/pcm027_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/configs/pcm027_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -7,7 +7,7 @@ CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_KALLSYMS is not set
 CONFIG_SLAB=y
 CONFIG_MODULES=y
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/configs/pcontrol_g20_defconfig linux-libre-2.6.38-gnu1/arch/arm/configs/pcontrol_g20_defconfig
--- linux-libre-2.6.37-gnu1/arch/arm/configs/pcontrol_g20_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/configs/pcontrol_g20_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -10,7 +10,7 @@ CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_NAMESPACES=y
 CONFIG_BLK_DEV_INITRD=y
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_SYSCTL_SYSCALL is not set
 # CONFIG_KALLSYMS is not set
 # CONFIG_VM_EVENT_COUNTERS is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/configs/pleb_defconfig linux-libre-2.6.38-gnu1/arch/arm/configs/pleb_defconfig
--- linux-libre-2.6.37-gnu1/arch/arm/configs/pleb_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/configs/pleb_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -3,7 +3,7 @@ CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_HOTPLUG is not set
 # CONFIG_SHMEM is not set
 CONFIG_MODULES=y
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/configs/pnx4008_defconfig linux-libre-2.6.38-gnu1/arch/arm/configs/pnx4008_defconfig
--- linux-libre-2.6.37-gnu1/arch/arm/configs/pnx4008_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/configs/pnx4008_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@ CONFIG_BSD_PROCESS_ACCT=y
 CONFIG_AUDIT=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 CONFIG_SLAB=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/configs/simpad_defconfig linux-libre-2.6.38-gnu1/arch/arm/configs/simpad_defconfig
--- linux-libre-2.6.37-gnu1/arch/arm/configs/simpad_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/configs/simpad_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -2,7 +2,7 @@ CONFIG_EXPERIMENTAL=y
 CONFIG_LOCALVERSION="oe1"
 CONFIG_SYSVIPC=y
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 CONFIG_KALLSYMS_ALL=y
 CONFIG_KALLSYMS_EXTRA_PASS=y
 CONFIG_MODULES=y
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/configs/spitz_defconfig linux-libre-2.6.38-gnu1/arch/arm/configs/spitz_defconfig
--- linux-libre-2.6.37-gnu1/arch/arm/configs/spitz_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/configs/spitz_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -4,7 +4,7 @@ CONFIG_BSD_PROCESS_ACCT=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_SYSFS_DEPRECATED_V2=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 CONFIG_PROFILING=y
 CONFIG_OPROFILE=m
 CONFIG_MODULES=y
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/configs/stmp378x_defconfig linux-libre-2.6.38-gnu1/arch/arm/configs/stmp378x_defconfig
--- linux-libre-2.6.37-gnu1/arch/arm/configs/stmp378x_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/configs/stmp378x_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@ CONFIG_POSIX_MQUEUE=y
 CONFIG_BSD_PROCESS_ACCT=y
 CONFIG_SYSFS_DEPRECATED_V2=y
 CONFIG_BLK_DEV_INITRD=y
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 CONFIG_SLAB=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/configs/stmp37xx_defconfig linux-libre-2.6.38-gnu1/arch/arm/configs/stmp37xx_defconfig
--- linux-libre-2.6.37-gnu1/arch/arm/configs/stmp37xx_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/configs/stmp37xx_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@ CONFIG_POSIX_MQUEUE=y
 CONFIG_BSD_PROCESS_ACCT=y
 CONFIG_SYSFS_DEPRECATED_V2=y
 CONFIG_BLK_DEV_INITRD=y
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 CONFIG_SLAB=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/configs/sx1_defconfig linux-libre-2.6.38-gnu1/arch/arm/configs/sx1_defconfig
--- linux-libre-2.6.37-gnu1/arch/arm/configs/sx1_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/configs/sx1_defconfig	1969-12-31 19:00:00.000000000 -0500
@@ -1,110 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-CONFIG_SYSVIPC=y
-CONFIG_POSIX_MQUEUE=y
-CONFIG_IKCONFIG=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_EMBEDDED=y
-# CONFIG_KALLSYMS is not set
-# CONFIG_ELF_CORE is not set
-# CONFIG_BASE_FULL is not set
-# CONFIG_SHMEM is not set
-# CONFIG_VM_EVENT_COUNTERS is not set
-CONFIG_SLOB=y
-CONFIG_PROFILING=y
-CONFIG_OPROFILE=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_IOSCHED_CFQ is not set
-CONFIG_ARCH_OMAP=y
-CONFIG_ARCH_OMAP1=y
-CONFIG_OMAP_MBOX_FWK=y
-CONFIG_MACH_SX1=y
-CONFIG_OMAP_ARM_168MHZ=y
-# CONFIG_OMAP_ARM_60MHZ is not set
-# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
-CONFIG_PREEMPT=y
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_FPE_NWFPE=y
-CONFIG_BINFMT_MISC=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-CONFIG_IP_PNP=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 is not set
-# CONFIG_FW_LOADER is not set
-CONFIG_CONNECTOR=y
-# CONFIG_PROC_EVENTS is not set
-CONFIG_BLK_DEV_LOOP=m
-CONFIG_BLK_DEV_RAM=m
-CONFIG_BLK_DEV_RAM_COUNT=2
-CONFIG_NETDEVICES=y
-CONFIG_PHYLIB=y
-CONFIG_NET_ETHERNET=y
-CONFIG_MII=y
-# CONFIG_INPUT_MOUSEDEV is not set
-CONFIG_INPUT_EVDEV=y
-# CONFIG_KEYBOARD_ATKBD is not set
-CONFIG_KEYBOARD_OMAP=y
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_SERIO is not set
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_NR_UARTS=3
-# CONFIG_LEGACY_PTYS is not set
-# CONFIG_HW_RANDOM is not set
-CONFIG_I2C=y
-CONFIG_I2C_CHARDEV=y
-CONFIG_I2C_OMAP=y
-# CONFIG_HWMON is not set
-CONFIG_FB=y
-CONFIG_FB_OMAP=y
-CONFIG_FB_OMAP_BOOTLOADER_INIT=y
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_FRAMEBUFFER_CONSOLE=y
-CONFIG_FONTS=y
-CONFIG_FONT_MINI_4x6=y
-CONFIG_LOGO=y
-# CONFIG_LOGO_LINUX_MONO is not set
-# CONFIG_LOGO_LINUX_VGA16 is not set
-CONFIG_SOUND=y
-CONFIG_SND=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_USB_GADGET=y
-CONFIG_USB_ETH=m
-CONFIG_MMC=y
-CONFIG_MMC_OMAP=y
-CONFIG_RTC_CLASS=y
-CONFIG_RTC_DRV_OMAP=y
-CONFIG_EXT2_FS=y
-# CONFIG_DNOTIFY is not set
-CONFIG_INOTIFY=y
-CONFIG_MSDOS_FS=y
-CONFIG_VFAT_FS=y
-CONFIG_FAT_DEFAULT_CODEPAGE=866
-CONFIG_FAT_DEFAULT_IOCHARSET="koi8-r"
-CONFIG_CRAMFS=y
-CONFIG_NFS_FS=y
-CONFIG_ROOT_NFS=y
-CONFIG_PARTITION_ADVANCED=y
-CONFIG_NLS_CODEPAGE_437=y
-CONFIG_NLS_CODEPAGE_866=y
-CONFIG_NLS_CODEPAGE_1251=y
-CONFIG_NLS_ISO8859_1=y
-CONFIG_NLS_ISO8859_5=y
-CONFIG_NLS_KOI8_R=y
-CONFIG_NLS_UTF8=y
-# CONFIG_ENABLE_MUST_CHECK is not set
-CONFIG_DEBUG_KERNEL=y
-# CONFIG_DETECT_SOFTLOCKUP is not set
-# CONFIG_DEBUG_BUGVERBOSE is not set
-CONFIG_CRC_CCITT=y
-CONFIG_CRC16=y
-CONFIG_LIBCRC32C=y
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/configs/tct_hammer_defconfig linux-libre-2.6.38-gnu1/arch/arm/configs/tct_hammer_defconfig
--- linux-libre-2.6.37-gnu1/arch/arm/configs/tct_hammer_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/configs/tct_hammer_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@ CONFIG_SYSVIPC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_SYSFS_DEPRECATED_V2=y
 CONFIG_BLK_DEV_INITRD=y
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_KALLSYMS is not set
 # CONFIG_BUG is not set
 # CONFIG_ELF_CORE is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/configs/trizeps4_defconfig linux-libre-2.6.38-gnu1/arch/arm/configs/trizeps4_defconfig
--- linux-libre-2.6.37-gnu1/arch/arm/configs/trizeps4_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/configs/trizeps4_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -7,7 +7,7 @@ CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 CONFIG_KALLSYMS_EXTRA_PASS=y
 CONFIG_SLAB=y
 CONFIG_MODULES=y
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/configs/u300_defconfig linux-libre-2.6.38-gnu1/arch/arm/configs/u300_defconfig
--- linux-libre-2.6.37-gnu1/arch/arm/configs/u300_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/configs/u300_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -3,7 +3,7 @@ CONFIG_EXPERIMENTAL=y
 # CONFIG_SWAP is not set
 CONFIG_SYSVIPC=y
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_AIO is not set
 # CONFIG_VM_EVENT_COUNTERS is not set
 CONFIG_MODULES=y
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/configs/u8500_defconfig linux-libre-2.6.38-gnu1/arch/arm/configs/u8500_defconfig
--- linux-libre-2.6.37-gnu1/arch/arm/configs/u8500_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/configs/u8500_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -9,6 +9,10 @@ CONFIG_MODULE_UNLOAD=y
 # CONFIG_LBDAF is not set
 # CONFIG_BLK_DEV_BSG is not set
 CONFIG_ARCH_U8500=y
+CONFIG_UX500_SOC_DB5500=y
+CONFIG_UX500_SOC_DB8500=y
+CONFIG_MACH_U8500=y
+CONFIG_MACH_U5500=y
 CONFIG_SMP=y
 CONFIG_NR_CPUS=2
 CONFIG_PREEMPT=y
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/configs/viper_defconfig linux-libre-2.6.38-gnu1/arch/arm/configs/viper_defconfig
--- linux-libre-2.6.37-gnu1/arch/arm/configs/viper_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/configs/viper_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -3,7 +3,7 @@ CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
 CONFIG_LOG_BUF_SHIFT=13
 CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_ELF_CORE is not set
 # CONFIG_SHMEM is not set
 CONFIG_SLAB=y
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/configs/xcep_defconfig linux-libre-2.6.38-gnu1/arch/arm/configs/xcep_defconfig
--- linux-libre-2.6.37-gnu1/arch/arm/configs/xcep_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/configs/xcep_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -8,7 +8,7 @@ CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=16
 CONFIG_SYSFS_DEPRECATED_V2=y
 CONFIG_BLK_DEV_INITRD=y
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_UID16 is not set
 # CONFIG_SHMEM is not set
 # CONFIG_VM_EVENT_COUNTERS is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/include/asm/assembler.h linux-libre-2.6.38-gnu1/arch/arm/include/asm/assembler.h
--- linux-libre-2.6.37-gnu1/arch/arm/include/asm/assembler.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/include/asm/assembler.h	2011-03-14 21:20:32.000000000 -0400
@@ -18,6 +18,7 @@
 #endif
 
 #include <asm/ptrace.h>
+#include <asm/domain.h>
 
 /*
  * Endian independent macros for shifting bytes within registers.
@@ -157,16 +158,24 @@
 #ifdef CONFIG_SMP
 #define ALT_SMP(instr...)					\
 9998:	instr
+/*
+ * Note: if you get assembler errors from ALT_UP() when building with
+ * CONFIG_THUMB2_KERNEL, you almost certainly need to use
+ * ALT_SMP( W(instr) ... )
+ */
 #define ALT_UP(instr...)					\
 	.pushsection ".alt.smp.init", "a"			;\
 	.long	9998b						;\
-	instr							;\
+9997:	instr							;\
+	.if . - 9997b != 4					;\
+		.error "ALT_UP() content must assemble to exactly 4 bytes";\
+	.endif							;\
 	.popsection
 #define ALT_UP_B(label)					\
 	.equ	up_b_offset, label - 9998b			;\
 	.pushsection ".alt.smp.init", "a"			;\
 	.long	9998b						;\
-	b	. + up_b_offset					;\
+	W(b)	. + up_b_offset					;\
 	.popsection
 #else
 #define ALT_SMP(instr...)
@@ -177,16 +186,24 @@
 /*
  * SMP data memory barrier
  */
-	.macro	smp_dmb
+	.macro	smp_dmb mode
 #ifdef CONFIG_SMP
 #if __LINUX_ARM_ARCH__ >= 7
+	.ifeqs "\mode","arm"
 	ALT_SMP(dmb)
+	.else
+	ALT_SMP(W(dmb))
+	.endif
 #elif __LINUX_ARM_ARCH__ == 6
 	ALT_SMP(mcr	p15, 0, r0, c7, c10, 5)	@ dmb
 #else
 #error Incompatible SMP platform
 #endif
+	.ifeqs "\mode","arm"
 	ALT_UP(nop)
+	.else
+	ALT_UP(W(nop))
+	.endif
 #endif
 	.endm
 
@@ -206,12 +223,12 @@
  */
 #ifdef CONFIG_THUMB2_KERNEL
 
-	.macro	usraccoff, instr, reg, ptr, inc, off, cond, abort
+	.macro	usraccoff, instr, reg, ptr, inc, off, cond, abort, t=T()
 9999:
 	.if	\inc == 1
-	\instr\cond\()bt \reg, [\ptr, #\off]
+	\instr\cond\()b\()\t\().w \reg, [\ptr, #\off]
 	.elseif	\inc == 4
-	\instr\cond\()t \reg, [\ptr, #\off]
+	\instr\cond\()\t\().w \reg, [\ptr, #\off]
 	.else
 	.error	"Unsupported inc macro argument"
 	.endif
@@ -246,13 +263,13 @@
 
 #else	/* !CONFIG_THUMB2_KERNEL */
 
-	.macro	usracc, instr, reg, ptr, inc, cond, rept, abort
+	.macro	usracc, instr, reg, ptr, inc, cond, rept, abort, t=T()
 	.rept	\rept
 9999:
 	.if	\inc == 1
-	\instr\cond\()bt \reg, [\ptr], #\inc
+	\instr\cond\()b\()\t \reg, [\ptr], #\inc
 	.elseif	\inc == 4
-	\instr\cond\()t \reg, [\ptr], #\inc
+	\instr\cond\()\t \reg, [\ptr], #\inc
 	.else
 	.error	"Unsupported inc macro argument"
 	.endif
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/include/asm/bitops.h linux-libre-2.6.38-gnu1/arch/arm/include/asm/bitops.h
--- linux-libre-2.6.37-gnu1/arch/arm/include/asm/bitops.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/include/asm/bitops.h	2011-03-14 21:20:32.000000000 -0400
@@ -285,7 +285,7 @@ static inline int fls(int x)
 	if (__builtin_constant_p(x))
 	       return constant_fls(x);
 
-	asm("clz\t%0, %1" : "=r" (ret) : "r" (x) : "cc");
+	asm("clz\t%0, %1" : "=r" (ret) : "r" (x));
        	ret = 32 - ret;
 	return ret;
 }
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/include/asm/cache.h linux-libre-2.6.38-gnu1/arch/arm/include/asm/cache.h
--- linux-libre-2.6.37-gnu1/arch/arm/include/asm/cache.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/include/asm/cache.h	2011-03-14 21:20:32.000000000 -0400
@@ -23,4 +23,6 @@
 #define ARCH_SLAB_MINALIGN 8
 #endif
 
+#define __read_mostly __attribute__((__section__(".data..read_mostly")))
+
 #endif
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/include/asm/clkdev.h linux-libre-2.6.38-gnu1/arch/arm/include/asm/clkdev.h
--- linux-libre-2.6.37-gnu1/arch/arm/include/asm/clkdev.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/include/asm/clkdev.h	2011-03-14 21:20:32.000000000 -0400
@@ -12,23 +12,13 @@
 #ifndef __ASM_CLKDEV_H
 #define __ASM_CLKDEV_H
 
-struct clk;
-struct device;
-
-struct clk_lookup {
-	struct list_head	node;
-	const char		*dev_id;
-	const char		*con_id;
-	struct clk		*clk;
-};
-
-struct clk_lookup *clkdev_alloc(struct clk *clk, const char *con_id,
-	const char *dev_fmt, ...);
+#include <linux/slab.h>
 
-void clkdev_add(struct clk_lookup *cl);
-void clkdev_drop(struct clk_lookup *cl);
+#include <mach/clkdev.h>
 
-void clkdev_add_table(struct clk_lookup *, size_t);
-int clk_add_alias(const char *, const char *, char *, struct device *);
+static inline struct clk_lookup_alloc *__clkdev_alloc(size_t size)
+{
+	return kzalloc(size, GFP_KERNEL);
+}
 
 #endif
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/include/asm/dma-mapping.h linux-libre-2.6.38-gnu1/arch/arm/include/asm/dma-mapping.h
--- linux-libre-2.6.37-gnu1/arch/arm/include/asm/dma-mapping.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/include/asm/dma-mapping.h	2011-03-14 21:20:32.000000000 -0400
@@ -5,24 +5,29 @@
 
 #include <linux/mm_types.h>
 #include <linux/scatterlist.h>
+#include <linux/dma-debug.h>
 
 #include <asm-generic/dma-coherent.h>
 #include <asm/memory.h>
 
+#ifdef __arch_page_to_dma
+#error Please update to __arch_pfn_to_dma
+#endif
+
 /*
- * page_to_dma/dma_to_virt/virt_to_dma are architecture private functions
- * used internally by the DMA-mapping API to provide DMA addresses. They
- * must not be used by drivers.
+ * dma_to_pfn/pfn_to_dma/dma_to_virt/virt_to_dma are architecture private
+ * functions used internally by the DMA-mapping API to provide DMA
+ * addresses. They must not be used by drivers.
  */
-#ifndef __arch_page_to_dma
-static inline dma_addr_t page_to_dma(struct device *dev, struct page *page)
+#ifndef __arch_pfn_to_dma
+static inline dma_addr_t pfn_to_dma(struct device *dev, unsigned long pfn)
 {
-	return (dma_addr_t)__pfn_to_bus(page_to_pfn(page));
+	return (dma_addr_t)__pfn_to_bus(pfn);
 }
 
-static inline struct page *dma_to_page(struct device *dev, dma_addr_t addr)
+static inline unsigned long dma_to_pfn(struct device *dev, dma_addr_t addr)
 {
-	return pfn_to_page(__bus_to_pfn(addr));
+	return __bus_to_pfn(addr);
 }
 
 static inline void *dma_to_virt(struct device *dev, dma_addr_t addr)
@@ -35,14 +40,14 @@ static inline dma_addr_t virt_to_dma(str
 	return (dma_addr_t)__virt_to_bus((unsigned long)(addr));
 }
 #else
-static inline dma_addr_t page_to_dma(struct device *dev, struct page *page)
+static inline dma_addr_t pfn_to_dma(struct device *dev, unsigned long pfn)
 {
-	return __arch_page_to_dma(dev, page);
+	return __arch_pfn_to_dma(dev, pfn);
 }
 
-static inline struct page *dma_to_page(struct device *dev, dma_addr_t addr)
+static inline unsigned long dma_to_pfn(struct device *dev, dma_addr_t addr)
 {
-	return __arch_dma_to_page(dev, addr);
+	return __arch_dma_to_pfn(dev, addr);
 }
 
 static inline void *dma_to_virt(struct device *dev, dma_addr_t addr)
@@ -293,13 +298,13 @@ extern int dma_needs_bounce(struct devic
 /*
  * The DMA API, implemented by dmabounce.c.  See below for descriptions.
  */
-extern dma_addr_t dma_map_single(struct device *, void *, size_t,
+extern dma_addr_t __dma_map_single(struct device *, void *, size_t,
 		enum dma_data_direction);
-extern void dma_unmap_single(struct device *, dma_addr_t, size_t,
+extern void __dma_unmap_single(struct device *, dma_addr_t, size_t,
 		enum dma_data_direction);
-extern dma_addr_t dma_map_page(struct device *, struct page *,
+extern dma_addr_t __dma_map_page(struct device *, struct page *,
 		unsigned long, size_t, enum dma_data_direction);
-extern void dma_unmap_page(struct device *, dma_addr_t, size_t,
+extern void __dma_unmap_page(struct device *, dma_addr_t, size_t,
 		enum dma_data_direction);
 
 /*
@@ -323,6 +328,34 @@ static inline int dmabounce_sync_for_dev
 }
 
 
+static inline dma_addr_t __dma_map_single(struct device *dev, void *cpu_addr,
+		size_t size, enum dma_data_direction dir)
+{
+	__dma_single_cpu_to_dev(cpu_addr, size, dir);
+	return virt_to_dma(dev, cpu_addr);
+}
+
+static inline dma_addr_t __dma_map_page(struct device *dev, struct page *page,
+	     unsigned long offset, size_t size, enum dma_data_direction dir)
+{
+	__dma_page_cpu_to_dev(page, offset, size, dir);
+	return pfn_to_dma(dev, page_to_pfn(page)) + offset;
+}
+
+static inline void __dma_unmap_single(struct device *dev, dma_addr_t handle,
+		size_t size, enum dma_data_direction dir)
+{
+	__dma_single_dev_to_cpu(dma_to_virt(dev, handle), size, dir);
+}
+
+static inline void __dma_unmap_page(struct device *dev, dma_addr_t handle,
+		size_t size, enum dma_data_direction dir)
+{
+	__dma_page_dev_to_cpu(pfn_to_page(dma_to_pfn(dev, handle)),
+		handle & ~PAGE_MASK, size, dir);
+}
+#endif /* CONFIG_DMABOUNCE */
+
 /**
  * dma_map_single - map a single buffer for streaming DMA
  * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
@@ -340,11 +373,16 @@ static inline int dmabounce_sync_for_dev
 static inline dma_addr_t dma_map_single(struct device *dev, void *cpu_addr,
 		size_t size, enum dma_data_direction dir)
 {
+	dma_addr_t addr;
+
 	BUG_ON(!valid_dma_direction(dir));
 
-	__dma_single_cpu_to_dev(cpu_addr, size, dir);
+	addr = __dma_map_single(dev, cpu_addr, size, dir);
+	debug_dma_map_page(dev, virt_to_page(cpu_addr),
+			(unsigned long)cpu_addr & ~PAGE_MASK, size,
+			dir, addr, true);
 
-	return virt_to_dma(dev, cpu_addr);
+	return addr;
 }
 
 /**
@@ -364,11 +402,14 @@ static inline dma_addr_t dma_map_single(
 static inline dma_addr_t dma_map_page(struct device *dev, struct page *page,
 	     unsigned long offset, size_t size, enum dma_data_direction dir)
 {
+	dma_addr_t addr;
+
 	BUG_ON(!valid_dma_direction(dir));
 
-	__dma_page_cpu_to_dev(page, offset, size, dir);
+	addr = __dma_map_page(dev, page, offset, size, dir);
+	debug_dma_map_page(dev, page, offset, size, dir, addr, false);
 
-	return page_to_dma(dev, page) + offset;
+	return addr;
 }
 
 /**
@@ -388,7 +429,8 @@ static inline dma_addr_t dma_map_page(st
 static inline void dma_unmap_single(struct device *dev, dma_addr_t handle,
 		size_t size, enum dma_data_direction dir)
 {
-	__dma_single_dev_to_cpu(dma_to_virt(dev, handle), size, dir);
+	debug_dma_unmap_page(dev, handle, size, dir, true);
+	__dma_unmap_single(dev, handle, size, dir);
 }
 
 /**
@@ -408,10 +450,9 @@ static inline void dma_unmap_single(stru
 static inline void dma_unmap_page(struct device *dev, dma_addr_t handle,
 		size_t size, enum dma_data_direction dir)
 {
-	__dma_page_dev_to_cpu(dma_to_page(dev, handle), handle & ~PAGE_MASK,
-		size, dir);
+	debug_dma_unmap_page(dev, handle, size, dir, false);
+	__dma_unmap_page(dev, handle, size, dir);
 }
-#endif /* CONFIG_DMABOUNCE */
 
 /**
  * dma_sync_single_range_for_cpu
@@ -437,6 +478,8 @@ static inline void dma_sync_single_range
 {
 	BUG_ON(!valid_dma_direction(dir));
 
+	debug_dma_sync_single_for_cpu(dev, handle + offset, size, dir);
+
 	if (!dmabounce_sync_for_cpu(dev, handle, offset, size, dir))
 		return;
 
@@ -449,6 +492,8 @@ static inline void dma_sync_single_range
 {
 	BUG_ON(!valid_dma_direction(dir));
 
+	debug_dma_sync_single_for_device(dev, handle + offset, size, dir);
+
 	if (!dmabounce_sync_for_device(dev, handle, offset, size, dir))
 		return;
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/include/asm/domain.h linux-libre-2.6.38-gnu1/arch/arm/include/asm/domain.h
--- linux-libre-2.6.37-gnu1/arch/arm/include/asm/domain.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/include/asm/domain.h	2011-03-14 21:20:32.000000000 -0400
@@ -45,13 +45,17 @@
  */
 #define DOMAIN_NOACCESS	0
 #define DOMAIN_CLIENT	1
+#ifdef CONFIG_CPU_USE_DOMAINS
 #define DOMAIN_MANAGER	3
+#else
+#define DOMAIN_MANAGER	1
+#endif
 
 #define domain_val(dom,type)	((type) << (2*(dom)))
 
 #ifndef __ASSEMBLY__
 
-#ifdef CONFIG_MMU
+#ifdef CONFIG_CPU_USE_DOMAINS
 #define set_domain(x)					\
 	do {						\
 	__asm__ __volatile__(				\
@@ -74,5 +78,28 @@
 #define modify_domain(dom,type)	do { } while (0)
 #endif
 
+/*
+ * Generate the T (user) versions of the LDR/STR and related
+ * instructions (inline assembly)
+ */
+#ifdef CONFIG_CPU_USE_DOMAINS
+#define T(instr)	#instr "t"
+#else
+#define T(instr)	#instr
 #endif
-#endif /* !__ASSEMBLY__ */
+
+#else /* __ASSEMBLY__ */
+
+/*
+ * Generate the T (user) versions of the LDR/STR and related
+ * instructions
+ */
+#ifdef CONFIG_CPU_USE_DOMAINS
+#define T(instr)	instr ## t
+#else
+#define T(instr)	instr
+#endif
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* !__ASM_PROC_DOMAIN_H */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/include/asm/elf.h linux-libre-2.6.38-gnu1/arch/arm/include/asm/elf.h
--- linux-libre-2.6.37-gnu1/arch/arm/include/asm/elf.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/include/asm/elf.h	2011-03-14 21:20:32.000000000 -0400
@@ -99,6 +99,8 @@ struct elf32_hdr;
 extern int elf_check_arch(const struct elf32_hdr *);
 #define elf_check_arch elf_check_arch
 
+#define vmcore_elf64_check_arch(x) (0)
+
 extern int arm_elf_read_implies_exec(const struct elf32_hdr *, int);
 #define elf_read_implies_exec(ex,stk) arm_elf_read_implies_exec(&(ex), stk)
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/include/asm/entry-macro-multi.S linux-libre-2.6.38-gnu1/arch/arm/include/asm/entry-macro-multi.S
--- linux-libre-2.6.37-gnu1/arch/arm/include/asm/entry-macro-multi.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/include/asm/entry-macro-multi.S	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,44 @@
+/*
+ * Interrupt handling.  Preserves r7, r8, r9
+ */
+	.macro	arch_irq_handler_default
+	get_irqnr_preamble r5, lr
+1:	get_irqnr_and_base r0, r6, r5, lr
+	movne	r1, sp
+	@
+	@ routine called with r0 = irq number, r1 = struct pt_regs *
+	@
+	adrne	lr, BSYM(1b)
+	bne	asm_do_IRQ
+
+#ifdef CONFIG_SMP
+	/*
+	 * XXX
+	 *
+	 * this macro assumes that irqstat (r6) and base (r5) are
+	 * preserved from get_irqnr_and_base above
+	 */
+	ALT_SMP(test_for_ipi r0, r6, r5, lr)
+	ALT_UP_B(9997f)
+	movne	r1, sp
+	adrne	lr, BSYM(1b)
+	bne	do_IPI
+
+#ifdef CONFIG_LOCAL_TIMERS
+	test_for_ltirq r0, r6, r5, lr
+	movne	r0, sp
+	adrne	lr, BSYM(1b)
+	bne	do_local_timer
+#endif
+#endif
+9997:
+	.endm
+
+	.macro	arch_irq_handler, symbol_name
+	.align	5
+	.global \symbol_name
+\symbol_name:
+	mov	r4, lr
+	arch_irq_handler_default
+	mov     pc, r4
+	.endm
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/include/asm/futex.h linux-libre-2.6.38-gnu1/arch/arm/include/asm/futex.h
--- linux-libre-2.6.37-gnu1/arch/arm/include/asm/futex.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/include/asm/futex.h	2011-03-14 21:20:32.000000000 -0400
@@ -13,12 +13,13 @@
 #include <linux/preempt.h>
 #include <linux/uaccess.h>
 #include <asm/errno.h>
+#include <asm/domain.h>
 
 #define __futex_atomic_op(insn, ret, oldval, uaddr, oparg)	\
 	__asm__ __volatile__(					\
-	"1:	ldrt	%1, [%2]\n"				\
+	"1:	" T(ldr) "	%1, [%2]\n"			\
 	"	" insn "\n"					\
-	"2:	strt	%0, [%2]\n"				\
+	"2:	" T(str) "	%0, [%2]\n"			\
 	"	mov	%0, #0\n"				\
 	"3:\n"							\
 	"	.pushsection __ex_table,\"a\"\n"		\
@@ -97,10 +98,10 @@ futex_atomic_cmpxchg_inatomic(int __user
 	pagefault_disable();	/* implies preempt_disable() */
 
 	__asm__ __volatile__("@futex_atomic_cmpxchg_inatomic\n"
-	"1:	ldrt	%0, [%3]\n"
+	"1:	" T(ldr) "	%0, [%3]\n"
 	"	teq	%0, %1\n"
 	"	it	eq	@ explicit IT needed for the 2b label\n"
-	"2:	streqt	%2, [%3]\n"
+	"2:	" T(streq) "	%2, [%3]\n"
 	"3:\n"
 	"	.pushsection __ex_table,\"a\"\n"
 	"	.align	3\n"
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/include/asm/hardirq.h linux-libre-2.6.38-gnu1/arch/arm/include/asm/hardirq.h
--- linux-libre-2.6.37-gnu1/arch/arm/include/asm/hardirq.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/include/asm/hardirq.h	2011-03-14 21:20:32.000000000 -0400
@@ -5,13 +5,31 @@
 #include <linux/threads.h>
 #include <asm/irq.h>
 
+#define NR_IPI	5
+
 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
 } ____cacheline_aligned irq_cpustat_t;
 
 #include <linux/irq_cpustat.h>	/* Standard mappings for irq_cpustat_t above */
 
+#define __inc_irq_stat(cpu, member)	__IRQ_STAT(cpu, member)++
+#define __get_irq_stat(cpu, member)	__IRQ_STAT(cpu, member)
+
+#ifdef CONFIG_SMP
+u64 smp_irq_stat_cpu(unsigned int cpu);
+#else
+#define smp_irq_stat_cpu(cpu)	0
+#endif
+
+#define arch_irq_stat_cpu	smp_irq_stat_cpu
+
 #if NR_IRQS > 512
 #define HARDIRQ_BITS	10
 #elif NR_IRQS > 256
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/include/asm/hardware/cache-l2x0.h linux-libre-2.6.38-gnu1/arch/arm/include/asm/hardware/cache-l2x0.h
--- linux-libre-2.6.37-gnu1/arch/arm/include/asm/hardware/cache-l2x0.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/include/asm/hardware/cache-l2x0.h	2011-03-14 21:20:32.000000000 -0400
@@ -36,6 +36,7 @@
 #define L2X0_RAW_INTR_STAT		0x21C
 #define L2X0_INTR_CLEAR			0x220
 #define L2X0_CACHE_SYNC			0x730
+#define L2X0_DUMMY_REG			0x740
 #define L2X0_INV_LINE_PA		0x770
 #define L2X0_INV_WAY			0x77C
 #define L2X0_CLEAN_LINE_PA		0x7B0
@@ -59,7 +60,17 @@
 #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_AUX_CTRL_WAY_SIZE_MASK	(0x3 << 17)
+
+#define L2X0_AUX_CTRL_MASK			0xc0000fff
+#define L2X0_AUX_CTRL_ASSOCIATIVITY_SHIFT	16
+#define L2X0_AUX_CTRL_WAY_SIZE_SHIFT		17
+#define L2X0_AUX_CTRL_WAY_SIZE_MASK		(0x3 << 17)
+#define L2X0_AUX_CTRL_SHARE_OVERRIDE_SHIFT	22
+#define L2X0_AUX_CTRL_NS_LOCKDOWN_SHIFT		26
+#define L2X0_AUX_CTRL_NS_INT_CTRL_SHIFT		27
+#define L2X0_AUX_CTRL_DATA_PREFETCH_SHIFT	28
+#define L2X0_AUX_CTRL_INSTR_PREFETCH_SHIFT	29
+#define L2X0_AUX_CTRL_EARLY_BRESP_SHIFT		30
 
 #ifndef __ASSEMBLY__
 extern void __init l2x0_init(void __iomem *base, __u32 aux_val, __u32 aux_mask);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/include/asm/hardware/entry-macro-gic.S linux-libre-2.6.38-gnu1/arch/arm/include/asm/hardware/entry-macro-gic.S
--- linux-libre-2.6.37-gnu1/arch/arm/include/asm/hardware/entry-macro-gic.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/include/asm/hardware/entry-macro-gic.S	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,75 @@
+/*
+ * arch/arm/include/asm/hardware/entry-macro-gic.S
+ *
+ * Low-level IRQ helper macros for GIC
+ *
+ * This file is licensed under  the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <asm/hardware/gic.h>
+
+#ifndef HAVE_GET_IRQNR_PREAMBLE
+	.macro	get_irqnr_preamble, base, tmp
+	ldr	\base, =gic_cpu_base_addr
+	ldr	\base, [\base]
+	.endm
+#endif
+
+/*
+ * The interrupt numbering scheme is defined in the
+ * interrupt controller spec.  To wit:
+ *
+ * Interrupts 0-15 are IPI
+ * 16-28 are reserved
+ * 29-31 are local.  We allow 30 to be used for the watchdog.
+ * 32-1020 are global
+ * 1021-1022 are reserved
+ * 1023 is "spurious" (no interrupt)
+ *
+ * For now, we ignore all local interrupts so only return an interrupt if it's
+ * between 30 and 1020.  The test_for_ipi routine below will pick up on IPIs.
+ *
+ * A simple read from the controller will tell us the number of the highest
+ * priority enabled interrupt.  We then just need to check whether it is in the
+ * valid range for an IRQ (30-1020 inclusive).
+ */
+
+	.macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
+
+	ldr     \irqstat, [\base, #GIC_CPU_INTACK]
+	/* bits 12-10 = src CPU, 9-0 = int # */
+
+	ldr	\tmp, =1021
+	bic     \irqnr, \irqstat, #0x1c00
+	cmp     \irqnr, #29
+	cmpcc	\irqnr, \irqnr
+	cmpne	\irqnr, \tmp
+	cmpcs	\irqnr, \irqnr
+	.endm
+
+/* We assume that irqstat (the raw value of the IRQ acknowledge
+ * register) is preserved from the macro above.
+ * If there is an IPI, we immediately signal end of interrupt on the
+ * controller, since this requires the original irqstat value which
+ * we won't easily be able to recreate later.
+ */
+
+	.macro test_for_ipi, irqnr, irqstat, base, tmp
+	bic	\irqnr, \irqstat, #0x1c00
+	cmp	\irqnr, #16
+	strcc	\irqstat, [\base, #GIC_CPU_EOI]
+	cmpcs	\irqnr, \irqnr
+	.endm
+
+/* As above, this assumes that irqstat and base are preserved.. */
+
+	.macro test_for_ltirq, irqnr, irqstat, base, tmp
+	bic	\irqnr, \irqstat, #0x1c00
+	mov 	\tmp, #0
+	cmp	\irqnr, #29
+	moveq	\tmp, #1
+	streq	\irqstat, [\base, #GIC_CPU_EOI]
+	cmp	\tmp, #0
+	.endm
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/include/asm/hardware/gic.h linux-libre-2.6.38-gnu1/arch/arm/include/asm/hardware/gic.h
--- linux-libre-2.6.37-gnu1/arch/arm/include/asm/hardware/gic.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/include/asm/hardware/gic.h	2011-03-14 21:20:32.000000000 -0400
@@ -33,10 +33,13 @@
 #define GIC_DIST_SOFTINT		0xf00
 
 #ifndef __ASSEMBLY__
-void gic_dist_init(unsigned int gic_nr, void __iomem *base, unsigned int irq_start);
-void gic_cpu_init(unsigned int gic_nr, void __iomem *base);
+extern void __iomem *gic_cpu_base_addr;
+
+void gic_init(unsigned int, unsigned int, void __iomem *, void __iomem *);
+void gic_secondary_init(unsigned int);
 void gic_cascade_irq(unsigned int gic_nr, unsigned int irq);
 void gic_raise_softirq(const struct cpumask *mask, unsigned int irq);
+void gic_enable_ppi(unsigned int);
 #endif
 
 #endif
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/include/asm/hardware/sp810.h linux-libre-2.6.38-gnu1/arch/arm/include/asm/hardware/sp810.h
--- linux-libre-2.6.37-gnu1/arch/arm/include/asm/hardware/sp810.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/include/asm/hardware/sp810.h	2011-03-14 21:20:32.000000000 -0400
@@ -50,8 +50,17 @@
 #define SCPCELLID2		0xFF8
 #define SCPCELLID3		0xFFC
 
+#define SCCTRL_TIMEREN0SEL_REFCLK	(0 << 15)
+#define SCCTRL_TIMEREN0SEL_TIMCLK	(1 << 15)
+
+#define SCCTRL_TIMEREN1SEL_REFCLK	(0 << 17)
+#define SCCTRL_TIMEREN1SEL_TIMCLK	(1 << 17)
+
 static inline void sysctl_soft_reset(void __iomem *base)
 {
+	/* switch to slow mode */
+	writel(0x2, base + SCCTRL);
+
 	/* writing any value to SCSYSSTAT reg will reset system */
 	writel(0, base + SCSYSSTAT);
 }
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/include/asm/hardware/timer-sp.h linux-libre-2.6.38-gnu1/arch/arm/include/asm/hardware/timer-sp.h
--- linux-libre-2.6.37-gnu1/arch/arm/include/asm/hardware/timer-sp.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/include/asm/hardware/timer-sp.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,2 @@
+void sp804_clocksource_init(void __iomem *);
+void sp804_clockevents_init(void __iomem *, unsigned int);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/include/asm/hw_breakpoint.h linux-libre-2.6.38-gnu1/arch/arm/include/asm/hw_breakpoint.h
--- linux-libre-2.6.37-gnu1/arch/arm/include/asm/hw_breakpoint.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/include/asm/hw_breakpoint.h	2011-03-14 21:20:32.000000000 -0400
@@ -20,8 +20,8 @@ struct arch_hw_breakpoint_ctrl {
 struct arch_hw_breakpoint {
 	u32	address;
 	u32	trigger;
-	struct perf_event *suspended_wp;
-	struct arch_hw_breakpoint_ctrl ctrl;
+	struct	arch_hw_breakpoint_ctrl step_ctrl;
+	struct	arch_hw_breakpoint_ctrl ctrl;
 };
 
 static inline u32 encode_ctrl_reg(struct arch_hw_breakpoint_ctrl ctrl)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/include/asm/io.h linux-libre-2.6.38-gnu1/arch/arm/include/asm/io.h
--- linux-libre-2.6.37-gnu1/arch/arm/include/asm/io.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/include/asm/io.h	2011-03-14 21:20:32.000000000 -0400
@@ -95,6 +95,15 @@ static inline void __iomem *__typesafe_i
 	return (void __iomem *)addr;
 }
 
+/* IO barriers */
+#ifdef CONFIG_ARM_DMA_MEM_BUFFERABLE
+#define __iormb()		rmb()
+#define __iowmb()		wmb()
+#else
+#define __iormb()		do { } while (0)
+#define __iowmb()		do { } while (0)
+#endif
+
 /*
  * Now, pick up the machine-defined IO definitions
  */
@@ -125,17 +134,17 @@ static inline void __iomem *__typesafe_i
  * The {in,out}[bwl] macros are for emulating x86-style PCI/ISA IO space.
  */
 #ifdef __io
-#define outb(v,p)		__raw_writeb(v,__io(p))
-#define outw(v,p)		__raw_writew((__force __u16) \
-					cpu_to_le16(v),__io(p))
-#define outl(v,p)		__raw_writel((__force __u32) \
-					cpu_to_le32(v),__io(p))
+#define outb(v,p)	({ __iowmb(); __raw_writeb(v,__io(p)); })
+#define outw(v,p)	({ __iowmb(); __raw_writew((__force __u16) \
+					cpu_to_le16(v),__io(p)); })
+#define outl(v,p)	({ __iowmb(); __raw_writel((__force __u32) \
+					cpu_to_le32(v),__io(p)); })
 
-#define inb(p)	({ __u8 __v = __raw_readb(__io(p)); __v; })
+#define inb(p)	({ __u8 __v = __raw_readb(__io(p)); __iormb(); __v; })
 #define inw(p)	({ __u16 __v = le16_to_cpu((__force __le16) \
-			__raw_readw(__io(p))); __v; })
+			__raw_readw(__io(p))); __iormb(); __v; })
 #define inl(p)	({ __u32 __v = le32_to_cpu((__force __le32) \
-			__raw_readl(__io(p))); __v; })
+			__raw_readl(__io(p))); __iormb(); __v; })
 
 #define outsb(p,d,l)		__raw_writesb(__io(p),d,l)
 #define outsw(p,d,l)		__raw_writesw(__io(p),d,l)
@@ -192,14 +201,6 @@ extern void _memset_io(volatile void __i
 #define writel_relaxed(v,c)	((void)__raw_writel((__force u32) \
 					cpu_to_le32(v),__mem_pci(c)))
 
-#ifdef CONFIG_ARM_DMA_MEM_BUFFERABLE
-#define __iormb()		rmb()
-#define __iowmb()		wmb()
-#else
-#define __iormb()		do { } while (0)
-#define __iowmb()		do { } while (0)
-#endif
-
 #define readb(c)		({ u8  __v = readb_relaxed(c); __iormb(); __v; })
 #define readw(c)		({ u16 __v = readw_relaxed(c); __iormb(); __v; })
 #define readl(c)		({ u32 __v = readl_relaxed(c); __iormb(); __v; })
@@ -241,18 +242,15 @@ extern void _memset_io(volatile void __i
  *
  */
 #ifndef __arch_ioremap
-#define ioremap(cookie,size)		__arm_ioremap(cookie, size, MT_DEVICE)
-#define ioremap_nocache(cookie,size)	__arm_ioremap(cookie, size, MT_DEVICE)
-#define ioremap_cached(cookie,size)	__arm_ioremap(cookie, size, MT_DEVICE_CACHED)
-#define ioremap_wc(cookie,size)		__arm_ioremap(cookie, size, MT_DEVICE_WC)
-#define iounmap(cookie)			__iounmap(cookie)
-#else
+#define __arch_ioremap			__arm_ioremap
+#define __arch_iounmap			__iounmap
+#endif
+
 #define ioremap(cookie,size)		__arch_ioremap((cookie), (size), MT_DEVICE)
 #define ioremap_nocache(cookie,size)	__arch_ioremap((cookie), (size), MT_DEVICE)
 #define ioremap_cached(cookie,size)	__arch_ioremap((cookie), (size), MT_DEVICE_CACHED)
 #define ioremap_wc(cookie,size)		__arch_ioremap((cookie), (size), MT_DEVICE_WC)
-#define iounmap(cookie)			__arch_iounmap(cookie)
-#endif
+#define iounmap				__arch_iounmap
 
 /*
  * io{read,write}{8,16,32} macros
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/include/asm/kexec.h linux-libre-2.6.38-gnu1/arch/arm/include/asm/kexec.h
--- linux-libre-2.6.37-gnu1/arch/arm/include/asm/kexec.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/include/asm/kexec.h	2011-03-14 21:20:32.000000000 -0400
@@ -33,10 +33,20 @@ static inline void crash_setup_regs(stru
 	if (oldregs) {
 		memcpy(newregs, oldregs, sizeof(*newregs));
 	} else {
-		__asm__ __volatile__ ("stmia %0, {r0 - r15}"
-				      : : "r" (&newregs->ARM_r0));
-		__asm__ __volatile__ ("mrs %0, cpsr"
-				      : "=r" (newregs->ARM_cpsr));
+		__asm__ __volatile__ (
+			"stmia	%[regs_base], {r0-r12}\n\t"
+			"mov	%[_ARM_sp], sp\n\t"
+			"str	lr, %[_ARM_lr]\n\t"
+			"adr	%[_ARM_pc], 1f\n\t"
+			"mrs	%[_ARM_cpsr], cpsr\n\t"
+		"1:"
+			: [_ARM_pc] "=r" (newregs->ARM_pc),
+			  [_ARM_cpsr] "=r" (newregs->ARM_cpsr),
+			  [_ARM_sp] "=r" (newregs->ARM_sp),
+			  [_ARM_lr] "=o" (newregs->ARM_lr)
+			: [regs_base] "r" (&newregs->ARM_r0)
+			: "memory"
+		);
 	}
 }
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/include/asm/localtimer.h linux-libre-2.6.38-gnu1/arch/arm/include/asm/localtimer.h
--- linux-libre-2.6.37-gnu1/arch/arm/include/asm/localtimer.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/include/asm/localtimer.h	2011-03-14 21:20:32.000000000 -0400
@@ -30,7 +30,6 @@ asmlinkage void do_local_timer(struct pt
 #include "smp_twd.h"
 
 #define local_timer_ack()	twd_timer_ack()
-#define local_timer_stop()	twd_timer_stop()
 
 #else
 
@@ -40,11 +39,6 @@ asmlinkage void do_local_timer(struct pt
  */
 int local_timer_ack(void);
 
-/*
- * Stop a local timer interrupt.
- */
-void local_timer_stop(void);
-
 #endif
 
 /*
@@ -52,12 +46,6 @@ void local_timer_stop(void);
  */
 void local_timer_setup(struct clock_event_device *);
 
-#else
-
-static inline void local_timer_stop(void)
-{
-}
-
 #endif
 
 #endif
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/include/asm/mach/arch.h linux-libre-2.6.38-gnu1/arch/arm/include/asm/mach/arch.h
--- linux-libre-2.6.37-gnu1/arch/arm/include/asm/mach/arch.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/include/asm/mach/arch.h	2011-03-14 21:20:32.000000000 -0400
@@ -15,10 +15,6 @@ struct meminfo;
 struct sys_timer;
 
 struct machine_desc {
-	/*
-	 * Note! The first two elements are used
-	 * by assembler code in head.S, head-common.S
-	 */
 	unsigned int		nr;		/* architecture number	*/
 	const char		*name;		/* architecture name	*/
 	unsigned long		boot_params;	/* tagged list		*/
@@ -37,12 +33,21 @@ struct machine_desc {
 					 struct meminfo *);
 	void			(*reserve)(void);/* reserve mem blocks	*/
 	void			(*map_io)(void);/* IO mapping function	*/
+	void			(*init_early)(void);
 	void			(*init_irq)(void);
 	struct sys_timer	*timer;		/* system tick timer	*/
 	void			(*init_machine)(void);
+#ifdef CONFIG_MULTI_IRQ_HANDLER
+	void			(*handle_irq)(struct pt_regs *);
+#endif
 };
 
 /*
+ * Current machine - only accessible during boot.
+ */
+extern struct machine_desc *machine_desc;
+
+/*
  * Set of macros to define architecture features.  This is built into
  * a table by the linker.
  */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/include/asm/mach/irq.h linux-libre-2.6.38-gnu1/arch/arm/include/asm/mach/irq.h
--- linux-libre-2.6.37-gnu1/arch/arm/include/asm/mach/irq.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/include/asm/mach/irq.h	2011-03-14 21:20:32.000000000 -0400
@@ -17,10 +17,12 @@ struct seq_file;
 /*
  * This is internal.  Do not use it.
  */
-extern unsigned int arch_nr_irqs;
-extern void (*init_arch_irq)(void);
 extern void init_FIQ(void);
-extern int show_fiq_list(struct seq_file *, void *);
+extern int show_fiq_list(struct seq_file *, int);
+
+#ifdef CONFIG_MULTI_IRQ_HANDLER
+extern void (*handle_arch_irq)(struct pt_regs *);
+#endif
 
 /*
  * This is for easy migration, but should be changed in the source
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/include/asm/mach/time.h linux-libre-2.6.38-gnu1/arch/arm/include/asm/mach/time.h
--- linux-libre-2.6.37-gnu1/arch/arm/include/asm/mach/time.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/include/asm/mach/time.h	2011-03-14 21:20:32.000000000 -0400
@@ -43,7 +43,6 @@ struct sys_timer {
 #endif
 };
 
-extern struct sys_timer *system_timer;
 extern void timer_tick(void);
 
 #endif
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/include/asm/memory.h linux-libre-2.6.38-gnu1/arch/arm/include/asm/memory.h
--- linux-libre-2.6.37-gnu1/arch/arm/include/asm/memory.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/include/asm/memory.h	2011-03-14 21:20:32.000000000 -0400
@@ -188,7 +188,7 @@
  * translation for translating DMA addresses.  Use the driver
  * DMA support - see dma-mapping.h.
  */
-static inline unsigned long virt_to_phys(void *x)
+static inline unsigned long virt_to_phys(const volatile void *x)
 {
 	return __virt_to_phys((unsigned long)(x));
 }
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/include/asm/module.h linux-libre-2.6.38-gnu1/arch/arm/include/asm/module.h
--- linux-libre-2.6.37-gnu1/arch/arm/include/asm/module.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/include/asm/module.h	2011-03-14 21:20:32.000000000 -0400
@@ -8,11 +8,6 @@
 struct unwind_table;
 
 #ifdef CONFIG_ARM_UNWIND
-struct arm_unwind_mapping {
-	Elf_Shdr *unw_sec;
-	Elf_Shdr *sec_text;
-	struct unwind_table *unwind;
-};
 enum {
 	ARM_SEC_INIT,
 	ARM_SEC_DEVINIT,
@@ -21,13 +16,13 @@ enum {
 	ARM_SEC_DEVEXIT,
 	ARM_SEC_MAX,
 };
+#endif
+
 struct mod_arch_specific {
-	struct arm_unwind_mapping map[ARM_SEC_MAX];
-};
-#else
-struct mod_arch_specific {
-};
+#ifdef CONFIG_ARM_UNWIND
+	struct unwind_table *unwind[ARM_SEC_MAX];
 #endif
+};
 
 /*
  * Include the ARM architecture version.
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/include/asm/page.h linux-libre-2.6.38-gnu1/arch/arm/include/asm/page.h
--- linux-libre-2.6.37-gnu1/arch/arm/include/asm/page.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/include/asm/page.h	2011-03-14 21:20:32.000000000 -0400
@@ -151,13 +151,15 @@ 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 { unsigned long pte; } pte_t;
+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;
@@ -175,7 +177,7 @@ typedef struct { unsigned long pgprot; }
 /*
  * .. while these make it easier on the compiler
  */
-typedef unsigned long pte_t;
+typedef pteval_t pte_t;
 typedef unsigned long pmd_t;
 typedef unsigned long pgd_t[2];
 typedef unsigned long pgprot_t;
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/include/asm/pgalloc.h linux-libre-2.6.38-gnu1/arch/arm/include/asm/pgalloc.h
--- linux-libre-2.6.37-gnu1/arch/arm/include/asm/pgalloc.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/include/asm/pgalloc.h	2011-03-14 21:20:32.000000000 -0400
@@ -10,6 +10,8 @@
 #ifndef _ASMARM_PGALLOC_H
 #define _ASMARM_PGALLOC_H
 
+#include <linux/pagemap.h>
+
 #include <asm/domain.h>
 #include <asm/pgtable-hwdef.h>
 #include <asm/processor.h>
@@ -30,14 +32,16 @@
 #define pmd_free(mm, pmd)		do { } while (0)
 #define pgd_populate(mm,pmd,pte)	BUG()
 
-extern pgd_t *get_pgd_slow(struct mm_struct *mm);
-extern void free_pgd_slow(struct mm_struct *mm, pgd_t *pgd);
-
-#define pgd_alloc(mm)			get_pgd_slow(mm)
-#define pgd_free(mm, pgd)		free_pgd_slow(mm, pgd)
+extern pgd_t *pgd_alloc(struct mm_struct *mm);
+extern void pgd_free(struct mm_struct *mm, pgd_t *pgd);
 
 #define PGALLOC_GFP	(GFP_KERNEL | __GFP_NOTRACK | __GFP_REPEAT | __GFP_ZERO)
 
+static inline void clean_pte_table(pte_t *pte)
+{
+	clean_dcache_area(pte + PTE_HWTABLE_PTRS, PTE_HWTABLE_SIZE);
+}
+
 /*
  * Allocate one PTE table.
  *
@@ -45,14 +49,14 @@ extern void free_pgd_slow(struct mm_stru
  * into one table thus:
  *
  *  +------------+
- *  |  h/w pt 0  |
- *  +------------+
- *  |  h/w pt 1  |
- *  +------------+
  *  | Linux pt 0 |
  *  +------------+
  *  | Linux pt 1 |
  *  +------------+
+ *  |  h/w pt 0  |
+ *  +------------+
+ *  |  h/w pt 1  |
+ *  +------------+
  */
 static inline pte_t *
 pte_alloc_one_kernel(struct mm_struct *mm, unsigned long addr)
@@ -60,10 +64,8 @@ pte_alloc_one_kernel(struct mm_struct *m
 	pte_t *pte;
 
 	pte = (pte_t *)__get_free_page(PGALLOC_GFP);
-	if (pte) {
-		clean_dcache_area(pte, sizeof(pte_t) * PTRS_PER_PTE);
-		pte += PTRS_PER_PTE;
-	}
+	if (pte)
+		clean_pte_table(pte);
 
 	return pte;
 }
@@ -79,10 +81,8 @@ pte_alloc_one(struct mm_struct *mm, unsi
 	pte = alloc_pages(PGALLOC_GFP, 0);
 #endif
 	if (pte) {
-		if (!PageHighMem(pte)) {
-			void *page = page_address(pte);
-			clean_dcache_area(page, sizeof(pte_t) * PTRS_PER_PTE);
-		}
+		if (!PageHighMem(pte))
+			clean_pte_table(page_address(pte));
 		pgtable_page_ctor(pte);
 	}
 
@@ -94,10 +94,8 @@ pte_alloc_one(struct mm_struct *mm, unsi
  */
 static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
 {
-	if (pte) {
-		pte -= PTRS_PER_PTE;
+	if (pte)
 		free_page((unsigned long)pte);
-	}
 }
 
 static inline void pte_free(struct mm_struct *mm, pgtable_t pte)
@@ -106,8 +104,10 @@ static inline void pte_free(struct mm_st
 	__free_page(pte);
 }
 
-static inline void __pmd_populate(pmd_t *pmdp, unsigned long pmdval)
+static inline void __pmd_populate(pmd_t *pmdp, phys_addr_t pte,
+	unsigned long prot)
 {
+	unsigned long pmdval = (pte + PTE_HWTABLE_OFF) | prot;
 	pmdp[0] = __pmd(pmdval);
 	pmdp[1] = __pmd(pmdval + 256 * sizeof(pte_t));
 	flush_pmd_entry(pmdp);
@@ -122,20 +122,16 @@ static inline void __pmd_populate(pmd_t
 static inline void
 pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmdp, pte_t *ptep)
 {
-	unsigned long pte_ptr = (unsigned long)ptep;
-
 	/*
-	 * The pmd must be loaded with the physical
-	 * address of the PTE table
+	 * The pmd must be loaded with the physical address of the PTE table
 	 */
-	pte_ptr -= PTRS_PER_PTE * sizeof(void *);
-	__pmd_populate(pmdp, __pa(pte_ptr) | _PAGE_KERNEL_TABLE);
+	__pmd_populate(pmdp, __pa(ptep), _PAGE_KERNEL_TABLE);
 }
 
 static inline void
 pmd_populate(struct mm_struct *mm, pmd_t *pmdp, pgtable_t ptep)
 {
-	__pmd_populate(pmdp, page_to_pfn(ptep) << PAGE_SHIFT | _PAGE_USER_TABLE);
+	__pmd_populate(pmdp, page_to_phys(ptep), _PAGE_USER_TABLE);
 }
 #define pmd_pgtable(pmd) pmd_page(pmd)
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/include/asm/pgtable.h linux-libre-2.6.38-gnu1/arch/arm/include/asm/pgtable.h
--- linux-libre-2.6.37-gnu1/arch/arm/include/asm/pgtable.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/include/asm/pgtable.h	2011-03-14 21:20:32.000000000 -0400
@@ -10,6 +10,7 @@
 #ifndef _ASMARM_PGTABLE_H
 #define _ASMARM_PGTABLE_H
 
+#include <linux/const.h>
 #include <asm-generic/4level-fixup.h>
 #include <asm/proc-fns.h>
 
@@ -54,7 +55,7 @@
  * 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, followed by Linux versions
+ * 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.
  *
@@ -62,15 +63,15 @@
  *
  *    pgd             pte
  * |        |
- * +--------+ +0
- * |        |-----> +------------+ +0
+ * +--------+
+ * |        |       +------------+ +0
+ * +- - - - +       | Linux pt 0 |
+ * |        |       +------------+ +1024
+ * +--------+ +0    | Linux pt 1 |
+ * |        |-----> +------------+ +2048
  * +- - - - + +4    |  h/w pt 0  |
- * |        |-----> +------------+ +1024
+ * |        |-----> +------------+ +3072
  * +--------+ +8    |  h/w pt 1  |
- * |        |       +------------+ +2048
- * +- - - - +       | Linux pt 0 |
- * |        |       +------------+ +3072
- * +--------+       | Linux pt 1 |
  * |        |       +------------+ +4096
  *
  * See L_PTE_xxx below for definitions of bits in the "Linux pt", and
@@ -102,6 +103,10 @@
 #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
@@ -112,13 +117,13 @@
 #define LIBRARY_TEXT_START	0x0c000000
 
 #ifndef __ASSEMBLY__
-extern void __pte_error(const char *file, int line, unsigned long val);
-extern void __pmd_error(const char *file, int line, unsigned long val);
-extern void __pgd_error(const char *file, int line, unsigned long val);
+extern void __pte_error(const char *file, int line, pte_t);
+extern void __pmd_error(const char *file, int line, pmd_t);
+extern void __pgd_error(const char *file, int line, pgd_t);
 
-#define pte_ERROR(pte)		__pte_error(__FILE__, __LINE__, pte_val(pte))
-#define pmd_ERROR(pmd)		__pmd_error(__FILE__, __LINE__, pmd_val(pmd))
-#define pgd_ERROR(pgd)		__pgd_error(__FILE__, __LINE__, pgd_val(pgd))
+#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)
@@ -133,8 +138,7 @@ extern void __pgd_error(const char *file
  */
 #define FIRST_USER_ADDRESS	PAGE_SIZE
 
-#define FIRST_USER_PGD_NR	1
-#define USER_PTRS_PER_PGD	((TASK_SIZE/PGDIR_SIZE) - FIRST_USER_PGD_NR)
+#define USER_PTRS_PER_PGD	(TASK_SIZE / PGDIR_SIZE)
 
 /*
  * section address mask and size definitions.
@@ -161,30 +165,30 @@ extern void __pgd_error(const char *file
  * The PTE table pointer refers to the hardware entries; the "Linux"
  * entries are stored 1024 bytes below.
  */
-#define L_PTE_PRESENT		(1 << 0)
-#define L_PTE_YOUNG		(1 << 1)
-#define L_PTE_FILE		(1 << 2)	/* only when !PRESENT */
-#define L_PTE_DIRTY		(1 << 6)
-#define L_PTE_WRITE		(1 << 7)
-#define L_PTE_USER		(1 << 8)
-#define L_PTE_EXEC		(1 << 9)
-#define L_PTE_SHARED		(1 << 10)	/* shared(v6), coherent(xsc3) */
+#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	(0x00 << 2)	/* 0000 */
-#define L_PTE_MT_BUFFERABLE	(0x01 << 2)	/* 0001 */
-#define L_PTE_MT_WRITETHROUGH	(0x02 << 2)	/* 0010 */
-#define L_PTE_MT_WRITEBACK	(0x03 << 2)	/* 0011 */
-#define L_PTE_MT_MINICACHE	(0x06 << 2)	/* 0110 (sa1100, xscale) */
-#define L_PTE_MT_WRITEALLOC	(0x07 << 2)	/* 0111 */
-#define L_PTE_MT_DEV_SHARED	(0x04 << 2)	/* 0100 */
-#define L_PTE_MT_DEV_NONSHARED	(0x0c << 2)	/* 1100 */
-#define L_PTE_MT_DEV_WC		(0x09 << 2)	/* 1001 */
-#define L_PTE_MT_DEV_CACHED	(0x0b << 2)	/* 1011 */
-#define L_PTE_MT_MASK		(0x0f << 2)
+#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__
 
@@ -201,23 +205,44 @@ extern pgprot_t		pgprot_kernel;
 
 #define _MOD_PROT(p, b)	__pgprot(pgprot_val(p) | (b))
 
-#define PAGE_NONE		pgprot_user
-#define PAGE_SHARED		_MOD_PROT(pgprot_user, L_PTE_USER | L_PTE_WRITE)
-#define PAGE_SHARED_EXEC	_MOD_PROT(pgprot_user, L_PTE_USER | L_PTE_WRITE | L_PTE_EXEC)
-#define PAGE_COPY		_MOD_PROT(pgprot_user, L_PTE_USER)
-#define PAGE_COPY_EXEC		_MOD_PROT(pgprot_user, L_PTE_USER | L_PTE_EXEC)
-#define PAGE_READONLY		_MOD_PROT(pgprot_user, L_PTE_USER)
-#define PAGE_READONLY_EXEC	_MOD_PROT(pgprot_user, L_PTE_USER | L_PTE_EXEC)
-#define PAGE_KERNEL		pgprot_kernel
-#define PAGE_KERNEL_EXEC	_MOD_PROT(pgprot_kernel, L_PTE_EXEC)
+#define PAGE_NONE		_MOD_PROT(pgprot_user, L_PTE_XN | L_PTE_RDONLY)
+#define PAGE_SHARED		_MOD_PROT(pgprot_user, L_PTE_USER | L_PTE_XN)
+#define PAGE_SHARED_EXEC	_MOD_PROT(pgprot_user, L_PTE_USER)
+#define PAGE_COPY		_MOD_PROT(pgprot_user, L_PTE_USER | L_PTE_RDONLY | L_PTE_XN)
+#define PAGE_COPY_EXEC		_MOD_PROT(pgprot_user, L_PTE_USER | L_PTE_RDONLY)
+#define PAGE_READONLY		_MOD_PROT(pgprot_user, L_PTE_USER | L_PTE_RDONLY | L_PTE_XN)
+#define PAGE_READONLY_EXEC	_MOD_PROT(pgprot_user, L_PTE_USER | L_PTE_RDONLY)
+#define PAGE_KERNEL		_MOD_PROT(pgprot_kernel, L_PTE_XN)
+#define PAGE_KERNEL_EXEC	pgprot_kernel
 
-#define __PAGE_NONE		__pgprot(_L_PTE_DEFAULT)
-#define __PAGE_SHARED		__pgprot(_L_PTE_DEFAULT | L_PTE_USER | L_PTE_WRITE)
-#define __PAGE_SHARED_EXEC	__pgprot(_L_PTE_DEFAULT | L_PTE_USER | L_PTE_WRITE | L_PTE_EXEC)
-#define __PAGE_COPY		__pgprot(_L_PTE_DEFAULT | L_PTE_USER)
-#define __PAGE_COPY_EXEC	__pgprot(_L_PTE_DEFAULT | L_PTE_USER | L_PTE_EXEC)
-#define __PAGE_READONLY		__pgprot(_L_PTE_DEFAULT | L_PTE_USER)
-#define __PAGE_READONLY_EXEC	__pgprot(_L_PTE_DEFAULT | L_PTE_USER | L_PTE_EXEC)
+#define __PAGE_NONE		__pgprot(_L_PTE_DEFAULT | L_PTE_RDONLY | L_PTE_XN)
+#define __PAGE_SHARED		__pgprot(_L_PTE_DEFAULT | L_PTE_USER | L_PTE_XN)
+#define __PAGE_SHARED_EXEC	__pgprot(_L_PTE_DEFAULT | L_PTE_USER)
+#define __PAGE_COPY		__pgprot(_L_PTE_DEFAULT | L_PTE_USER | L_PTE_RDONLY | L_PTE_XN)
+#define __PAGE_COPY_EXEC	__pgprot(_L_PTE_DEFAULT | L_PTE_USER | L_PTE_RDONLY)
+#define __PAGE_READONLY		__pgprot(_L_PTE_DEFAULT | L_PTE_USER | L_PTE_RDONLY | L_PTE_XN)
+#define __PAGE_READONLY_EXEC	__pgprot(_L_PTE_DEFAULT | L_PTE_USER | L_PTE_RDONLY)
+
+#define __pgprot_modify(prot,mask,bits)		\
+	__pgprot((pgprot_val(prot) & ~(mask)) | (bits))
+
+#define pgprot_noncached(prot) \
+	__pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_UNCACHED)
+
+#define pgprot_writecombine(prot) \
+	__pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_BUFFERABLE)
+
+#ifdef CONFIG_ARM_DMA_MEM_BUFFERABLE
+#define pgprot_dmacoherent(prot) \
+	__pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_BUFFERABLE | L_PTE_XN)
+#define __HAVE_PHYS_MEM_ACCESS_PROT
+struct file;
+extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
+				     unsigned long size, pgprot_t vma_prot);
+#else
+#define pgprot_dmacoherent(prot) \
+	__pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_UNCACHED | L_PTE_XN)
+#endif
 
 #endif /* __ASSEMBLY__ */
 
@@ -255,26 +280,84 @@ extern pgprot_t		pgprot_kernel;
 extern struct page *empty_zero_page;
 #define ZERO_PAGE(vaddr)	(empty_zero_page)
 
-#define pte_pfn(pte)		(pte_val(pte) >> PAGE_SHIFT)
-#define pfn_pte(pfn,prot)	(__pte(((pfn) << PAGE_SHIFT) | pgprot_val(prot)))
 
-#define pte_none(pte)		(!pte_val(pte))
-#define pte_clear(mm,addr,ptep)	set_pte_ext(ptep, __pte(0), 0)
-#define pte_page(pte)		(pfn_to_page(pte_pfn(pte)))
-#define pte_offset_kernel(dir,addr)	(pmd_page_vaddr(*(dir)) + __pte_index(addr))
+extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
+
+/* to find an entry in a page-table-directory */
+#define pgd_index(addr)		((addr) >> PGDIR_SHIFT)
+
+#define pgd_offset(mm, addr)	((mm)->pgd + pgd_index(addr))
+
+/* to find an entry in a kernel page-table-directory */
+#define pgd_offset_k(addr)	pgd_offset(&init_mm, addr)
+
+/*
+ * The "pgd_xxx()" functions here are trivial for a folded two-level
+ * setup: the pgd is never bad, and a pmd always exists (as it's folded
+ * into the pgd entry)
+ */
+#define pgd_none(pgd)		(0)
+#define pgd_bad(pgd)		(0)
+#define pgd_present(pgd)	(1)
+#define pgd_clear(pgdp)		do { } while (0)
+#define set_pgd(pgd,pgdp)	do { } while (0)
+
+
+/* Find an entry in the second-level page table.. */
+#define pmd_offset(dir, addr)	((pmd_t *)(dir))
+
+#define pmd_none(pmd)		(!pmd_val(pmd))
+#define pmd_present(pmd)	(pmd_val(pmd))
+#define pmd_bad(pmd)		(pmd_val(pmd) & 2)
+
+#define copy_pmd(pmdpd,pmdps)		\
+	do {				\
+		pmdpd[0] = pmdps[0];	\
+		pmdpd[1] = pmdps[1];	\
+		flush_pmd_entry(pmdpd);	\
+	} while (0)
+
+#define pmd_clear(pmdp)			\
+	do {				\
+		pmdp[0] = __pmd(0);	\
+		pmdp[1] = __pmd(0);	\
+		clean_pmd_entry(pmdp);	\
+	} while (0)
+
+static inline pte_t *pmd_page_vaddr(pmd_t pmd)
+{
+	return __va(pmd_val(pmd) & PAGE_MASK);
+}
+
+#define pmd_page(pmd)		pfn_to_page(__phys_to_pfn(pmd_val(pmd)))
+
+/* we don't need complex calculations here as the pmd is folded into the pgd */
+#define pmd_addr_end(addr,end)	(end)
 
-#define pte_offset_map(dir,addr)	(__pte_map(dir) + __pte_index(addr))
-#define pte_unmap(pte)			__pte_unmap(pte)
 
 #ifndef CONFIG_HIGHPTE
-#define __pte_map(dir)		pmd_page_vaddr(*(dir))
+#define __pte_map(pmd)		pmd_page_vaddr(*(pmd))
 #define __pte_unmap(pte)	do { } while (0)
 #else
-#define __pte_map(dir)		((pte_t *)kmap_atomic(pmd_page(*(dir))) + PTRS_PER_PTE)
-#define __pte_unmap(pte)	kunmap_atomic((pte - PTRS_PER_PTE))
+#define __pte_map(pmd)		(pte_t *)kmap_atomic(pmd_page(*(pmd)))
+#define __pte_unmap(pte)	kunmap_atomic(pte)
 #endif
 
+#define pte_index(addr)		(((addr) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
+
+#define pte_offset_kernel(pmd,addr)	(pmd_page_vaddr(*(pmd)) + pte_index(addr))
+
+#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 pfn_pte(pfn,prot)	__pte(((pfn) << PAGE_SHIFT) | pgprot_val(prot))
+
+#define pte_page(pte)		pfn_to_page(pte_pfn(pte))
+#define mk_pte(page,prot)	pfn_pte(page_to_pfn(page), prot)
+
 #define set_pte_ext(ptep,pte,ext) cpu_set_pte_ext(ptep,pte,ext)
+#define pte_clear(mm,addr,ptep)	set_pte_ext(ptep, __pte(0), 0)
 
 #if __LINUX_ARM_ARCH__ < 6
 static inline void __sync_icache_dcache(pte_t pteval)
@@ -295,15 +378,12 @@ static inline void set_pte_at(struct mm_
 	}
 }
 
-/*
- * The following only work if pte_present() is true.
- * Undefined behaviour if not..
- */
+#define pte_none(pte)		(!pte_val(pte))
 #define pte_present(pte)	(pte_val(pte) & L_PTE_PRESENT)
-#define pte_write(pte)		(pte_val(pte) & L_PTE_WRITE)
+#define pte_write(pte)		(!(pte_val(pte) & L_PTE_RDONLY))
 #define pte_dirty(pte)		(pte_val(pte) & L_PTE_DIRTY)
 #define pte_young(pte)		(pte_val(pte) & L_PTE_YOUNG)
-#define pte_exec(pte)		(pte_val(pte) & L_PTE_EXEC)
+#define pte_exec(pte)		(!(pte_val(pte) & L_PTE_XN))
 #define pte_special(pte)	(0)
 
 #define pte_present_user(pte) \
@@ -313,8 +393,8 @@ static inline void set_pte_at(struct mm_
 #define PTE_BIT_FUNC(fn,op) \
 static inline pte_t pte_##fn(pte_t pte) { pte_val(pte) op; return pte; }
 
-PTE_BIT_FUNC(wrprotect, &= ~L_PTE_WRITE);
-PTE_BIT_FUNC(mkwrite,   |= L_PTE_WRITE);
+PTE_BIT_FUNC(wrprotect, |= L_PTE_RDONLY);
+PTE_BIT_FUNC(mkwrite,   &= ~L_PTE_RDONLY);
 PTE_BIT_FUNC(mkclean,   &= ~L_PTE_DIRTY);
 PTE_BIT_FUNC(mkdirty,   |= L_PTE_DIRTY);
 PTE_BIT_FUNC(mkold,     &= ~L_PTE_YOUNG);
@@ -322,101 +402,13 @@ PTE_BIT_FUNC(mkyoung,   |= L_PTE_YOUNG);
 
 static inline pte_t pte_mkspecial(pte_t pte) { return pte; }
 
-#define __pgprot_modify(prot,mask,bits)		\
-	__pgprot((pgprot_val(prot) & ~(mask)) | (bits))
-
-/*
- * Mark the prot value as uncacheable and unbufferable.
- */
-#define pgprot_noncached(prot) \
-	__pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_UNCACHED)
-#define pgprot_writecombine(prot) \
-	__pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_BUFFERABLE)
-#ifdef CONFIG_ARM_DMA_MEM_BUFFERABLE
-#define pgprot_dmacoherent(prot) \
-	__pgprot_modify(prot, L_PTE_MT_MASK|L_PTE_EXEC, L_PTE_MT_BUFFERABLE)
-#define __HAVE_PHYS_MEM_ACCESS_PROT
-struct file;
-extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
-				     unsigned long size, pgprot_t vma_prot);
-#else
-#define pgprot_dmacoherent(prot) \
-	__pgprot_modify(prot, L_PTE_MT_MASK|L_PTE_EXEC, L_PTE_MT_UNCACHED)
-#endif
-
-#define pmd_none(pmd)		(!pmd_val(pmd))
-#define pmd_present(pmd)	(pmd_val(pmd))
-#define pmd_bad(pmd)		(pmd_val(pmd) & 2)
-
-#define copy_pmd(pmdpd,pmdps)		\
-	do {				\
-		pmdpd[0] = pmdps[0];	\
-		pmdpd[1] = pmdps[1];	\
-		flush_pmd_entry(pmdpd);	\
-	} while (0)
-
-#define pmd_clear(pmdp)			\
-	do {				\
-		pmdp[0] = __pmd(0);	\
-		pmdp[1] = __pmd(0);	\
-		clean_pmd_entry(pmdp);	\
-	} while (0)
-
-static inline pte_t *pmd_page_vaddr(pmd_t pmd)
-{
-	unsigned long ptr;
-
-	ptr = pmd_val(pmd) & ~(PTRS_PER_PTE * sizeof(void *) - 1);
-	ptr += PTRS_PER_PTE * sizeof(void *);
-
-	return __va(ptr);
-}
-
-#define pmd_page(pmd)		pfn_to_page(__phys_to_pfn(pmd_val(pmd)))
-
-/* we don't need complex calculations here as the pmd is folded into the pgd */
-#define pmd_addr_end(addr,end)	(end)
-
-/*
- * Conversion functions: convert a page and protection to a page entry,
- * and a page entry and page directory to the page they refer to.
- */
-#define mk_pte(page,prot)	pfn_pte(page_to_pfn(page),prot)
-
-/*
- * The "pgd_xxx()" functions here are trivial for a folded two-level
- * setup: the pgd is never bad, and a pmd always exists (as it's folded
- * into the pgd entry)
- */
-#define pgd_none(pgd)		(0)
-#define pgd_bad(pgd)		(0)
-#define pgd_present(pgd)	(1)
-#define pgd_clear(pgdp)		do { } while (0)
-#define set_pgd(pgd,pgdp)	do { } while (0)
-
-/* to find an entry in a page-table-directory */
-#define pgd_index(addr)		((addr) >> PGDIR_SHIFT)
-
-#define pgd_offset(mm, addr)	((mm)->pgd+pgd_index(addr))
-
-/* to find an entry in a kernel page-table-directory */
-#define pgd_offset_k(addr)	pgd_offset(&init_mm, addr)
-
-/* Find an entry in the second-level page table.. */
-#define pmd_offset(dir, addr)	((pmd_t *)(dir))
-
-/* Find an entry in the third-level page table.. */
-#define __pte_index(addr)	(((addr) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
-
 static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
 {
-	const unsigned long mask = L_PTE_EXEC | L_PTE_WRITE | L_PTE_USER;
+	const pteval_t mask = L_PTE_XN | L_PTE_RDONLY | L_PTE_USER;
 	pte_val(pte) = (pte_val(pte) & ~mask) | (pgprot_val(newprot) & mask);
 	return pte;
 }
 
-extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
-
 /*
  * Encode and decode a swap entry.  Swap entries are stored in the Linux
  * page tables as follows:
@@ -481,6 +473,9 @@ extern pgd_t swapper_pg_dir[PTRS_PER_PGD
 
 #define pgtable_cache_init() do { } while (0)
 
+void identity_mapping_add(pgd_t *, unsigned long, unsigned long);
+void identity_mapping_del(pgd_t *, unsigned long, unsigned long);
+
 #endif /* !__ASSEMBLY__ */
 
 #endif /* CONFIG_MMU */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/include/asm/sched_clock.h linux-libre-2.6.38-gnu1/arch/arm/include/asm/sched_clock.h
--- linux-libre-2.6.37-gnu1/arch/arm/include/asm/sched_clock.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/include/asm/sched_clock.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,120 @@
+/*
+ * sched_clock.h: support for extending counters to full 64-bit ns counter
+ *
+ * This program is free software; you can 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_SCHED_CLOCK
+#define ASM_SCHED_CLOCK
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+
+struct clock_data {
+	u64 epoch_ns;
+	u32 epoch_cyc;
+	u32 epoch_cyc_copy;
+	u32 mult;
+	u32 shift;
+};
+
+#define DEFINE_CLOCK_DATA(name)	struct clock_data name
+
+static inline u64 cyc_to_ns(u64 cyc, u32 mult, u32 shift)
+{
+	return (cyc * mult) >> shift;
+}
+
+/*
+ * Atomically update the sched_clock epoch.  Your update callback will
+ * be called from a timer before the counter wraps - read the current
+ * counter value, and call this function to safely move the epochs
+ * forward.  Only use this from the update callback.
+ */
+static inline void update_sched_clock(struct clock_data *cd, u32 cyc, u32 mask)
+{
+	unsigned long flags;
+	u64 ns = cd->epoch_ns +
+		cyc_to_ns((cyc - cd->epoch_cyc) & mask, cd->mult, cd->shift);
+
+	/*
+	 * Write epoch_cyc and epoch_ns in a way that the update is
+	 * detectable in cyc_to_fixed_sched_clock().
+	 */
+	raw_local_irq_save(flags);
+	cd->epoch_cyc = cyc;
+	smp_wmb();
+	cd->epoch_ns = ns;
+	smp_wmb();
+	cd->epoch_cyc_copy = cyc;
+	raw_local_irq_restore(flags);
+}
+
+/*
+ * If your clock rate is known at compile time, using this will allow
+ * you to optimize the mult/shift loads away.  This is paired with
+ * init_fixed_sched_clock() to ensure that your mult/shift are correct.
+ */
+static inline unsigned long long cyc_to_fixed_sched_clock(struct clock_data *cd,
+	u32 cyc, u32 mask, u32 mult, u32 shift)
+{
+	u64 epoch_ns;
+	u32 epoch_cyc;
+
+	/*
+	 * Load the epoch_cyc and epoch_ns atomically.  We do this by
+	 * ensuring that we always write epoch_cyc, epoch_ns and
+	 * epoch_cyc_copy in strict order, and read them in strict order.
+	 * If epoch_cyc and epoch_cyc_copy are not equal, then we're in
+	 * the middle of an update, and we should repeat the load.
+	 */
+	do {
+		epoch_cyc = cd->epoch_cyc;
+		smp_rmb();
+		epoch_ns = cd->epoch_ns;
+		smp_rmb();
+	} while (epoch_cyc != cd->epoch_cyc_copy);
+
+	return epoch_ns + cyc_to_ns((cyc - epoch_cyc) & mask, mult, shift);
+}
+
+/*
+ * Otherwise, you need to use this, which will obtain the mult/shift
+ * from the clock_data structure.  Use init_sched_clock() with this.
+ */
+static inline unsigned long long cyc_to_sched_clock(struct clock_data *cd,
+	u32 cyc, u32 mask)
+{
+	return cyc_to_fixed_sched_clock(cd, cyc, mask, cd->mult, cd->shift);
+}
+
+/*
+ * Initialize the clock data - calculate the appropriate multiplier
+ * and shift.  Also setup a timer to ensure that the epoch is refreshed
+ * at the appropriate time interval, which will call your update
+ * handler.
+ */
+void init_sched_clock(struct clock_data *, void (*)(void),
+	unsigned int, unsigned long);
+
+/*
+ * Use this initialization function rather than init_sched_clock() if
+ * you're using cyc_to_fixed_sched_clock, which will warn if your
+ * constants are incorrect.
+ */
+static inline void init_fixed_sched_clock(struct clock_data *cd,
+	void (*update)(void), unsigned int bits, unsigned long rate,
+	u32 mult, u32 shift)
+{
+	init_sched_clock(cd, update, bits, rate);
+	if (cd->mult != mult || cd->shift != shift) {
+		pr_crit("sched_clock: wrong multiply/shift: %u>>%u vs calculated %u>>%u\n"
+			"sched_clock: fix multiply/shift to avoid scheduler hiccups\n",
+			mult, shift, cd->mult, cd->shift);
+	}
+}
+
+extern void sched_clock_postinit(void);
+
+#endif
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/include/asm/smp.h linux-libre-2.6.38-gnu1/arch/arm/include/asm/smp.h
--- linux-libre-2.6.37-gnu1/arch/arm/include/asm/smp.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/include/asm/smp.h	2011-03-14 21:20:32.000000000 -0400
@@ -33,27 +33,23 @@ struct seq_file;
 /*
  * generate IPI list text
  */
-extern void show_ipi_list(struct seq_file *p);
+extern void show_ipi_list(struct seq_file *, int);
 
 /*
  * Called from assembly code, this handles an IPI.
  */
-asmlinkage void do_IPI(struct pt_regs *regs);
+asmlinkage void do_IPI(int ipinr, struct pt_regs *regs);
 
 /*
  * Setup the set of possible CPUs (via set_cpu_possible)
  */
 extern void smp_init_cpus(void);
 
-/*
- * Move global data into per-processor storage.
- */
-extern void smp_store_cpu_info(unsigned int cpuid);
 
 /*
  * Raise an IPI cross call on CPUs in callmap.
  */
-extern void smp_cross_call(const struct cpumask *mask);
+extern void smp_cross_call(const struct cpumask *mask, int ipi);
 
 /*
  * Boot a secondary CPU, and assign it the specified idle task.
@@ -73,6 +69,11 @@ asmlinkage void secondary_start_kernel(v
 extern void platform_secondary_init(unsigned int cpu);
 
 /*
+ * Initialize cpu_possible map, and enable coherency
+ */
+extern void platform_smp_prepare_cpus(unsigned int);
+
+/*
  * Initial data for bringing up a secondary CPU.
  */
 struct secondary_data {
@@ -97,6 +98,6 @@ extern void arch_send_call_function_ipi_
 /*
  * show local interrupt info
  */
-extern void show_local_irqs(struct seq_file *);
+extern void show_local_irqs(struct seq_file *, int);
 
 #endif /* ifndef __ASM_ARM_SMP_H */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/include/asm/smp_mpidr.h linux-libre-2.6.38-gnu1/arch/arm/include/asm/smp_mpidr.h
--- linux-libre-2.6.37-gnu1/arch/arm/include/asm/smp_mpidr.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/include/asm/smp_mpidr.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,17 +0,0 @@
-#ifndef ASMARM_SMP_MIDR_H
-#define ASMARM_SMP_MIDR_H
-
-#define hard_smp_processor_id()						\
-	({								\
-		unsigned int cpunum;					\
-		__asm__("\n"						\
-			"1:	mrc p15, 0, %0, c0, c0, 5\n"		\
-			"	.pushsection \".alt.smp.init\", \"a\"\n"\
-			"	.long	1b\n"				\
-			"	mov	%0, #0\n"			\
-			"	.popsection"				\
-			: "=r" (cpunum));				\
-		cpunum &= 0x0F;						\
-	})
-
-#endif
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/include/asm/smp_twd.h linux-libre-2.6.38-gnu1/arch/arm/include/asm/smp_twd.h
--- linux-libre-2.6.37-gnu1/arch/arm/include/asm/smp_twd.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/include/asm/smp_twd.h	2011-03-14 21:20:32.000000000 -0400
@@ -22,7 +22,6 @@ struct clock_event_device;
 
 extern void __iomem *twd_base;
 
-void twd_timer_stop(void);
 int twd_timer_ack(void);
 void twd_timer_setup(struct clock_event_device *);
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/include/asm/system.h linux-libre-2.6.38-gnu1/arch/arm/include/asm/system.h
--- linux-libre-2.6.37-gnu1/arch/arm/include/asm/system.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/include/asm/system.h	2011-03-14 21:20:32.000000000 -0400
@@ -63,6 +63,11 @@
 #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;
@@ -119,6 +124,13 @@ extern unsigned int user_debug;
 #define vectors_high()	(0)
 #endif
 
+#if __LINUX_ARM_ARCH__ >= 7 ||		\
+	(__LINUX_ARM_ARCH__ == 6 && defined(CONFIG_CPU_32v6K))
+#define sev()	__asm__ __volatile__ ("sev" : : : "memory")
+#define wfe()	__asm__ __volatile__ ("wfe" : : : "memory")
+#define wfi()	__asm__ __volatile__ ("wfi" : : : "memory")
+#endif
+
 #if __LINUX_ARM_ARCH__ >= 7
 #define isb() __asm__ __volatile__ ("isb" : : : "memory")
 #define dsb() __asm__ __volatile__ ("dsb" : : : "memory")
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/include/asm/tlbflush.h linux-libre-2.6.38-gnu1/arch/arm/include/asm/tlbflush.h
--- linux-libre-2.6.37-gnu1/arch/arm/include/asm/tlbflush.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/include/asm/tlbflush.h	2011-03-14 21:20:32.000000000 -0400
@@ -10,12 +10,7 @@
 #ifndef _ASMARM_TLBFLUSH_H
 #define _ASMARM_TLBFLUSH_H
 
-
-#ifndef CONFIG_MMU
-
-#define tlb_flush(tlb)	((void) tlb)
-
-#else /* CONFIG_MMU */
+#ifdef CONFIG_MMU
 
 #include <asm/glue.h>
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/include/asm/tlb.h linux-libre-2.6.38-gnu1/arch/arm/include/asm/tlb.h
--- linux-libre-2.6.37-gnu1/arch/arm/include/asm/tlb.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/include/asm/tlb.h	2011-03-14 21:20:32.000000000 -0400
@@ -18,16 +18,34 @@
 #define __ASMARM_TLB_H
 
 #include <asm/cacheflush.h>
-#include <asm/tlbflush.h>
 
 #ifndef CONFIG_MMU
 
 #include <linux/pagemap.h>
+
+#define tlb_flush(tlb)	((void) tlb)
+
 #include <asm-generic/tlb.h>
 
 #else /* !CONFIG_MMU */
 
+#include <linux/swap.h>
 #include <asm/pgalloc.h>
+#include <asm/tlbflush.h>
+
+/*
+ * We need to delay page freeing for SMP as other CPUs can access pages
+ * which have been removed but not yet had their TLB entries invalidated.
+ * Also, as ARMv7 speculative prefetch can drag new entries into the TLB,
+ * we need to apply this same delaying tactic to ensure correct operation.
+ */
+#if defined(CONFIG_SMP) || defined(CONFIG_CPU_32v7)
+#define tlb_fast_mode(tlb)	0
+#define FREE_PTE_NR		500
+#else
+#define tlb_fast_mode(tlb)	1
+#define FREE_PTE_NR		0
+#endif
 
 /*
  * TLB handling.  This allows us to remove pages from the page
@@ -36,12 +54,58 @@
 struct mmu_gather {
 	struct mm_struct	*mm;
 	unsigned int		fullmm;
+	struct vm_area_struct	*vma;
 	unsigned long		range_start;
 	unsigned long		range_end;
+	unsigned int		nr;
+	struct page		*pages[FREE_PTE_NR];
 };
 
 DECLARE_PER_CPU(struct mmu_gather, mmu_gathers);
 
+/*
+ * This is unnecessarily complex.  There's three ways the TLB shootdown
+ * code is used:
+ *  1. Unmapping a range of vmas.  See zap_page_range(), unmap_region().
+ *     tlb->fullmm = 0, and tlb_start_vma/tlb_end_vma will be called.
+ *     tlb->vma will be non-NULL.
+ *  2. Unmapping all vmas.  See exit_mmap().
+ *     tlb->fullmm = 1, and tlb_start_vma/tlb_end_vma will be called.
+ *     tlb->vma will be non-NULL.  Additionally, page tables will be freed.
+ *  3. Unmapping argument pages.  See shift_arg_pages().
+ *     tlb->fullmm = 0, but tlb_start_vma/tlb_end_vma will not be called.
+ *     tlb->vma will be NULL.
+ */
+static inline void tlb_flush(struct mmu_gather *tlb)
+{
+	if (tlb->fullmm || !tlb->vma)
+		flush_tlb_mm(tlb->mm);
+	else if (tlb->range_end > 0) {
+		flush_tlb_range(tlb->vma, tlb->range_start, tlb->range_end);
+		tlb->range_start = TASK_SIZE;
+		tlb->range_end = 0;
+	}
+}
+
+static inline void tlb_add_flush(struct mmu_gather *tlb, unsigned long addr)
+{
+	if (!tlb->fullmm) {
+		if (addr < tlb->range_start)
+			tlb->range_start = addr;
+		if (addr + PAGE_SIZE > tlb->range_end)
+			tlb->range_end = addr + PAGE_SIZE;
+	}
+}
+
+static inline void tlb_flush_mmu(struct mmu_gather *tlb)
+{
+	tlb_flush(tlb);
+	if (!tlb_fast_mode(tlb)) {
+		free_pages_and_swap_cache(tlb->pages, tlb->nr);
+		tlb->nr = 0;
+	}
+}
+
 static inline struct mmu_gather *
 tlb_gather_mmu(struct mm_struct *mm, unsigned int full_mm_flush)
 {
@@ -49,6 +113,8 @@ tlb_gather_mmu(struct mm_struct *mm, uns
 
 	tlb->mm = mm;
 	tlb->fullmm = full_mm_flush;
+	tlb->vma = NULL;
+	tlb->nr = 0;
 
 	return tlb;
 }
@@ -56,8 +122,7 @@ tlb_gather_mmu(struct mm_struct *mm, uns
 static inline void
 tlb_finish_mmu(struct mmu_gather *tlb, unsigned long start, unsigned long end)
 {
-	if (tlb->fullmm)
-		flush_tlb_mm(tlb->mm);
+	tlb_flush_mmu(tlb);
 
 	/* keep the page table cache within bounds */
 	check_pgt_cache();
@@ -71,12 +136,7 @@ tlb_finish_mmu(struct mmu_gather *tlb, u
 static inline void
 tlb_remove_tlb_entry(struct mmu_gather *tlb, pte_t *ptep, unsigned long addr)
 {
-	if (!tlb->fullmm) {
-		if (addr < tlb->range_start)
-			tlb->range_start = addr;
-		if (addr + PAGE_SIZE > tlb->range_end)
-			tlb->range_end = addr + PAGE_SIZE;
-	}
+	tlb_add_flush(tlb, addr);
 }
 
 /*
@@ -89,6 +149,7 @@ tlb_start_vma(struct mmu_gather *tlb, st
 {
 	if (!tlb->fullmm) {
 		flush_cache_range(vma, vma->vm_start, vma->vm_end);
+		tlb->vma = vma;
 		tlb->range_start = TASK_SIZE;
 		tlb->range_end = 0;
 	}
@@ -97,12 +158,30 @@ tlb_start_vma(struct mmu_gather *tlb, st
 static inline void
 tlb_end_vma(struct mmu_gather *tlb, struct vm_area_struct *vma)
 {
-	if (!tlb->fullmm && tlb->range_end > 0)
-		flush_tlb_range(vma, tlb->range_start, tlb->range_end);
+	if (!tlb->fullmm)
+		tlb_flush(tlb);
 }
 
-#define tlb_remove_page(tlb,page)	free_page_and_swap_cache(page)
-#define pte_free_tlb(tlb, ptep, addr)	pte_free((tlb)->mm, ptep)
+static inline void tlb_remove_page(struct mmu_gather *tlb, struct page *page)
+{
+	if (tlb_fast_mode(tlb)) {
+		free_page_and_swap_cache(page);
+	} else {
+		tlb->pages[tlb->nr++] = page;
+		if (tlb->nr >= FREE_PTE_NR)
+			tlb_flush_mmu(tlb);
+	}
+}
+
+static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t pte,
+	unsigned long addr)
+{
+	pgtable_page_dtor(pte);
+	tlb_add_flush(tlb, addr);
+	tlb_remove_page(tlb, pte);
+}
+
+#define pte_free_tlb(tlb, ptep, addr)	__pte_free_tlb(tlb, ptep, addr)
 #define pmd_free_tlb(tlb, pmdp, addr)	pmd_free((tlb)->mm, pmdp)
 
 #define tlb_migrate_finish(mm)		do { } while (0)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/include/asm/traps.h linux-libre-2.6.38-gnu1/arch/arm/include/asm/traps.h
--- linux-libre-2.6.37-gnu1/arch/arm/include/asm/traps.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/include/asm/traps.h	2011-03-14 21:20:32.000000000 -0400
@@ -15,16 +15,37 @@ struct undef_hook {
 void register_undef_hook(struct undef_hook *hook);
 void unregister_undef_hook(struct undef_hook *hook);
 
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+static inline int __in_irqentry_text(unsigned long ptr)
+{
+	extern char __irqentry_text_start[];
+	extern char __irqentry_text_end[];
+
+	return ptr >= (unsigned long)&__irqentry_text_start &&
+	       ptr < (unsigned long)&__irqentry_text_end;
+}
+#else
+static inline int __in_irqentry_text(unsigned long ptr)
+{
+	return 0;
+}
+#endif
+
 static inline int in_exception_text(unsigned long ptr)
 {
 	extern char __exception_text_start[];
 	extern char __exception_text_end[];
+	int in;
 
-	return ptr >= (unsigned long)&__exception_text_start &&
-	       ptr < (unsigned long)&__exception_text_end;
+	in = ptr >= (unsigned long)&__exception_text_start &&
+	     ptr < (unsigned long)&__exception_text_end;
+
+	return in ? : __in_irqentry_text(ptr);
 }
 
 extern void __init early_trap_init(void);
 extern void dump_backtrace_entry(unsigned long where, unsigned long from, unsigned long frame);
 
+extern void *vectors_page;
+
 #endif
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/include/asm/uaccess.h linux-libre-2.6.38-gnu1/arch/arm/include/asm/uaccess.h
--- linux-libre-2.6.37-gnu1/arch/arm/include/asm/uaccess.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/include/asm/uaccess.h	2011-03-14 21:20:32.000000000 -0400
@@ -227,7 +227,7 @@ do {									\
 
 #define __get_user_asm_byte(x,addr,err)				\
 	__asm__ __volatile__(					\
-	"1:	ldrbt	%1,[%2]\n"				\
+	"1:	" T(ldrb) "	%1,[%2],#0\n"			\
 	"2:\n"							\
 	"	.pushsection .fixup,\"ax\"\n"			\
 	"	.align	2\n"					\
@@ -263,7 +263,7 @@ do {									\
 
 #define __get_user_asm_word(x,addr,err)				\
 	__asm__ __volatile__(					\
-	"1:	ldrt	%1,[%2]\n"				\
+	"1:	" T(ldr) "	%1,[%2],#0\n"			\
 	"2:\n"							\
 	"	.pushsection .fixup,\"ax\"\n"			\
 	"	.align	2\n"					\
@@ -308,7 +308,7 @@ do {									\
 
 #define __put_user_asm_byte(x,__pu_addr,err)			\
 	__asm__ __volatile__(					\
-	"1:	strbt	%1,[%2]\n"				\
+	"1:	" T(strb) "	%1,[%2],#0\n"			\
 	"2:\n"							\
 	"	.pushsection .fixup,\"ax\"\n"			\
 	"	.align	2\n"					\
@@ -341,7 +341,7 @@ do {									\
 
 #define __put_user_asm_word(x,__pu_addr,err)			\
 	__asm__ __volatile__(					\
-	"1:	strt	%1,[%2]\n"				\
+	"1:	" T(str) "	%1,[%2],#0\n"			\
 	"2:\n"							\
 	"	.pushsection .fixup,\"ax\"\n"			\
 	"	.align	2\n"					\
@@ -366,10 +366,10 @@ do {									\
 
 #define __put_user_asm_dword(x,__pu_addr,err)			\
 	__asm__ __volatile__(					\
- ARM(	"1:	strt	" __reg_oper1 ", [%1], #4\n"	)	\
- ARM(	"2:	strt	" __reg_oper0 ", [%1]\n"	)	\
- THUMB(	"1:	strt	" __reg_oper1 ", [%1]\n"	)	\
- THUMB(	"2:	strt	" __reg_oper0 ", [%1, #4]\n"	)	\
+ ARM(	"1:	" T(str) "	" __reg_oper1 ", [%1], #4\n"	)	\
+ ARM(	"2:	" T(str) "	" __reg_oper0 ", [%1]\n"	)	\
+ THUMB(	"1:	" T(str) "	" __reg_oper1 ", [%1]\n"	)	\
+ THUMB(	"2:	" T(str) "	" __reg_oper0 ", [%1, #4]\n"	)	\
 	"3:\n"							\
 	"	.pushsection .fixup,\"ax\"\n"			\
 	"	.align	2\n"					\
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/Kconfig linux-libre-2.6.38-gnu1/arch/arm/Kconfig
--- linux-libre-2.6.37-gnu1/arch/arm/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -2,6 +2,7 @@ config ARM
 	bool
 	default y
 	select HAVE_AOUT
+	select HAVE_DMA_API_DEBUG
 	select HAVE_IDE
 	select HAVE_MEMBLOCK
 	select RTC_LIB
@@ -14,6 +15,7 @@ config ARM
 	select HAVE_FUNCTION_TRACER if (!XIP_KERNEL)
 	select HAVE_FTRACE_MCOUNT_RECORD if (!XIP_KERNEL)
 	select HAVE_DYNAMIC_FTRACE if (!XIP_KERNEL)
+	select HAVE_FUNCTION_GRAPH_TRACER if (!THUMB2_KERNEL)
 	select HAVE_GENERIC_DMA_COHERENT
 	select HAVE_KERNEL_GZIP
 	select HAVE_KERNEL_LZO
@@ -23,6 +25,9 @@ config ARM
 	select PERF_USE_VMALLOC
 	select HAVE_REGS_AND_STACK_ACCESS_API
 	select HAVE_HW_BREAKPOINT if (PERF_EVENTS && (CPU_V6 || CPU_V7))
+	select HAVE_C_RECORDMCOUNT
+	select HAVE_GENERIC_HARDIRQS
+	select HAVE_SPARSE_IRQ
 	help
 	  The ARM series is a line of low-power-consumption RISC chip designs
 	  licensed by ARM Ltd and targeted at embedded applications and
@@ -34,9 +39,15 @@ config ARM
 config HAVE_PWM
 	bool
 
+config MIGHT_HAVE_PCI
+	bool
+
 config SYS_SUPPORTS_APM_EMULATION
 	bool
 
+config HAVE_SCHED_CLOCK
+	bool
+
 config GENERIC_GPIO
 	bool
 
@@ -88,10 +99,6 @@ config MCA
 	  <file:Documentation/mca.txt> (and especially the web page given
 	  there) before attempting to build an MCA bus kernel.
 
-config GENERIC_HARDIRQS
-	bool
-	default y
-
 config STACKTRACE_SUPPORT
 	bool
 	default y
@@ -171,9 +178,6 @@ config FIQ
 config ARCH_MTD_XIP
 	bool
 
-config GENERIC_HARDIRQS_NO__DO_IRQ
-	def_bool y
-
 config ARM_L1_CACHE_SHIFT_6
 	bool
 	help
@@ -221,7 +225,7 @@ config ARCH_INTEGRATOR
 	bool "ARM Ltd. Integrator family"
 	select ARM_AMBA
 	select ARCH_HAS_CPUFREQ
-	select COMMON_CLKDEV
+	select CLKDEV_LOOKUP
 	select ICST
 	select GENERIC_CLOCKEVENTS
 	select PLAT_VERSATILE
@@ -231,7 +235,8 @@ config ARCH_INTEGRATOR
 config ARCH_REALVIEW
 	bool "ARM Ltd. RealView family"
 	select ARM_AMBA
-	select COMMON_CLKDEV
+	select CLKDEV_LOOKUP
+	select HAVE_SCHED_CLOCK
 	select ICST
 	select GENERIC_CLOCKEVENTS
 	select ARCH_WANT_OPTIONAL_GPIOLIB
@@ -245,7 +250,8 @@ config ARCH_VERSATILE
 	bool "ARM Ltd. Versatile family"
 	select ARM_AMBA
 	select ARM_VIC
-	select COMMON_CLKDEV
+	select CLKDEV_LOOKUP
+	select HAVE_SCHED_CLOCK
 	select ICST
 	select GENERIC_CLOCKEVENTS
 	select ARCH_WANT_OPTIONAL_GPIOLIB
@@ -259,9 +265,10 @@ config ARCH_VEXPRESS
 	select ARCH_WANT_OPTIONAL_GPIOLIB
 	select ARM_AMBA
 	select ARM_TIMER_SP804
-	select COMMON_CLKDEV
+	select CLKDEV_LOOKUP
 	select GENERIC_CLOCKEVENTS
 	select HAVE_CLK
+	select HAVE_SCHED_CLOCK
 	select ICST
 	select PLAT_VERSATILE
 	help
@@ -280,7 +287,7 @@ config ARCH_BCMRING
 	depends on MMU
 	select CPU_V6
 	select ARM_AMBA
-	select COMMON_CLKDEV
+	select CLKDEV_LOOKUP
 	select GENERIC_CLOCKEVENTS
 	select ARCH_WANT_OPTIONAL_GPIOLIB
 	help
@@ -298,6 +305,7 @@ config ARCH_CNS3XXX
 	select CPU_V6
 	select GENERIC_CLOCKEVENTS
 	select ARM_GIC
+	select MIGHT_HAVE_PCI
 	select PCI_DOMAINS if PCI
 	help
 	  Support for Cavium Networks CNS3XXX platform.
@@ -327,7 +335,7 @@ config ARCH_EP93XX
 	select CPU_ARM920T
 	select ARM_AMBA
 	select ARM_VIC
-	select COMMON_CLKDEV
+	select CLKDEV_LOOKUP
 	select ARCH_REQUIRE_GPIOLIB
 	select ARCH_HAS_HOLES_MEMORYMODEL
 	select ARCH_USES_GETTIMEOFFSET
@@ -347,14 +355,22 @@ config ARCH_MXC
 	bool "Freescale MXC/iMX-based"
 	select GENERIC_CLOCKEVENTS
 	select ARCH_REQUIRE_GPIOLIB
-	select COMMON_CLKDEV
+	select CLKDEV_LOOKUP
 	help
 	  Support for Freescale MXC/iMX-based family of processors
 
+config ARCH_MXS
+	bool "Freescale MXS-based"
+	select GENERIC_CLOCKEVENTS
+	select ARCH_REQUIRE_GPIOLIB
+	select CLKDEV_LOOKUP
+	help
+	  Support for Freescale MXS-based family of processors
+
 config ARCH_STMP3XXX
 	bool "Freescale STMP3xxx"
 	select CPU_ARM926T
-	select COMMON_CLKDEV
+	select CLKDEV_LOOKUP
 	select ARCH_REQUIRE_GPIOLIB
 	select GENERIC_CLOCKEVENTS
 	select USB_ARCH_HAS_EHCI
@@ -433,6 +449,8 @@ config ARCH_IXP4XX
 	select CPU_XSCALE
 	select GENERIC_GPIO
 	select GENERIC_CLOCKEVENTS
+	select HAVE_SCHED_CLOCK
+	select MIGHT_HAVE_PCI
 	select DMABOUNCE if PCI
 	help
 	  Support for Intel's IXP4XX (XScale) family of processors.
@@ -472,7 +490,7 @@ config ARCH_LPC32XX
 	select HAVE_IDE
 	select ARM_AMBA
 	select USB_ARCH_HAS_OHCI
-	select COMMON_CLKDEV
+	select CLKDEV_LOOKUP
 	select GENERIC_TIME
 	select GENERIC_CLOCKEVENTS
 	help
@@ -506,8 +524,9 @@ config ARCH_MMP
 	bool "Marvell PXA168/910/MMP2"
 	depends on MMU
 	select ARCH_REQUIRE_GPIOLIB
-	select COMMON_CLKDEV
+	select CLKDEV_LOOKUP
 	select GENERIC_CLOCKEVENTS
+	select HAVE_SCHED_CLOCK
 	select TICK_ONESHOT
 	select PLAT_PXA
 	select SPARSE_IRQ
@@ -539,7 +558,7 @@ config ARCH_W90X900
 	bool "Nuvoton W90X900 CPU"
 	select CPU_ARM926T
 	select ARCH_REQUIRE_GPIOLIB
-	select COMMON_CLKDEV
+	select CLKDEV_LOOKUP
 	select GENERIC_CLOCKEVENTS
 	help
 	  Support for Nuvoton (Winbond logic dept.) ARM9 processor,
@@ -553,18 +572,19 @@ config ARCH_W90X900
 config ARCH_NUC93X
 	bool "Nuvoton NUC93X CPU"
 	select CPU_ARM926T
-	select COMMON_CLKDEV
+	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 GENERIC_TIME
 	select GENERIC_CLOCKEVENTS
 	select GENERIC_GPIO
 	select HAVE_CLK
-	select COMMON_CLKDEV
+	select HAVE_SCHED_CLOCK
 	select ARCH_HAS_BARRIERS if CACHE_L2X0
 	select ARCH_HAS_CPUFREQ
 	help
@@ -574,7 +594,7 @@ config ARCH_TEGRA
 config ARCH_PNX4008
 	bool "Philips Nexperia PNX4008 Mobile"
 	select CPU_ARM926T
-	select COMMON_CLKDEV
+	select CLKDEV_LOOKUP
 	select ARCH_USES_GETTIMEOFFSET
 	help
 	  This enables support for Philips PNX4008 mobile platform.
@@ -584,9 +604,10 @@ config ARCH_PXA
 	depends on MMU
 	select ARCH_MTD_XIP
 	select ARCH_HAS_CPUFREQ
-	select COMMON_CLKDEV
+	select CLKDEV_LOOKUP
 	select ARCH_REQUIRE_GPIOLIB
 	select GENERIC_CLOCKEVENTS
+	select HAVE_SCHED_CLOCK
 	select TICK_ONESHOT
 	select PLAT_PXA
 	select SPARSE_IRQ
@@ -606,9 +627,15 @@ config ARCH_MSM
 	  (clock and power control, etc).
 
 config ARCH_SHMOBILE
-	bool "Renesas SH-Mobile"
+	bool "Renesas SH-Mobile / R-Mobile"
+	select HAVE_CLK
+	select CLKDEV_LOOKUP
+	select GENERIC_CLOCKEVENTS
+	select NO_IOPORT
+	select SPARSE_IRQ
+	select MULTI_IRQ_HANDLER
 	help
-	  Support for Renesas's SH-Mobile ARM platforms
+	  Support for Renesas's SH-Mobile and R-Mobile ARM platforms.
 
 config ARCH_RPC
 	bool "RiscPC"
@@ -635,6 +662,7 @@ config ARCH_SA1100
 	select CPU_FREQ
 	select GENERIC_CLOCKEVENTS
 	select HAVE_CLK
+	select HAVE_SCHED_CLOCK
 	select TICK_ONESHOT
 	select ARCH_REQUIRE_GPIOLIB
 	help
@@ -738,6 +766,7 @@ config ARCH_S5PV310
 	select ARCH_SPARSEMEM_ENABLE
 	select GENERIC_GPIO
 	select HAVE_CLK
+	select ARCH_HAS_CPUFREQ
 	select GENERIC_CLOCKEVENTS
 	select HAVE_S3C_RTC if RTC_CLASS
 	select HAVE_S3C2410_I2C if I2C
@@ -761,7 +790,7 @@ config ARCH_TCC_926
 	bool "Telechips TCC ARM926-based systems"
 	select CPU_ARM926T
 	select HAVE_CLK
-	select COMMON_CLKDEV
+	select CLKDEV_LOOKUP
 	select GENERIC_CLOCKEVENTS
 	help
 	  Support for Telechips TCC ARM926-based systems.
@@ -781,11 +810,12 @@ config ARCH_U300
 	bool "ST-Ericsson U300 Series"
 	depends on MMU
 	select CPU_ARM926T
+	select HAVE_SCHED_CLOCK
 	select HAVE_TCM
 	select ARM_AMBA
 	select ARM_VIC
 	select GENERIC_CLOCKEVENTS
-	select COMMON_CLKDEV
+	select CLKDEV_LOOKUP
 	select GENERIC_GPIO
 	help
 	  Support for ST-Ericsson U300 series mobile platforms.
@@ -795,8 +825,9 @@ config ARCH_U8500
 	select CPU_V7
 	select ARM_AMBA
 	select GENERIC_CLOCKEVENTS
-	select COMMON_CLKDEV
+	select CLKDEV_LOOKUP
 	select ARCH_REQUIRE_GPIOLIB
+	select ARCH_HAS_CPUFREQ
 	help
 	  Support for ST-Ericsson's Ux500 architecture
 
@@ -805,7 +836,7 @@ config ARCH_NOMADIK
 	select ARM_AMBA
 	select ARM_VIC
 	select CPU_ARM926T
-	select COMMON_CLKDEV
+	select CLKDEV_LOOKUP
 	select GENERIC_CLOCKEVENTS
 	select ARCH_REQUIRE_GPIOLIB
 	help
@@ -817,7 +848,7 @@ config ARCH_DAVINCI
 	select ARCH_REQUIRE_GPIOLIB
 	select ZONE_DMA
 	select HAVE_IDE
-	select COMMON_CLKDEV
+	select CLKDEV_LOOKUP
 	select GENERIC_ALLOCATOR
 	select ARCH_HAS_HOLES_MEMORYMODEL
 	help
@@ -829,6 +860,7 @@ config ARCH_OMAP
 	select ARCH_REQUIRE_GPIOLIB
 	select ARCH_HAS_CPUFREQ
 	select GENERIC_CLOCKEVENTS
+	select HAVE_SCHED_CLOCK
 	select ARCH_HAS_HOLES_MEMORYMODEL
 	help
 	  Support for TI's OMAP platform (OMAP1/2/3/4).
@@ -837,7 +869,7 @@ config PLAT_SPEAR
 	bool "ST SPEAr"
 	select ARM_AMBA
 	select ARCH_REQUIRE_GPIOLIB
-	select COMMON_CLKDEV
+	select CLKDEV_LOOKUP
 	select GENERIC_CLOCKEVENTS
 	select HAVE_CLK
 	help
@@ -902,6 +934,8 @@ source "arch/arm/mach-mv78xx0/Kconfig"
 
 source "arch/arm/plat-mxc/Kconfig"
 
+source "arch/arm/mach-mxs/Kconfig"
+
 source "arch/arm/mach-netx/Kconfig"
 
 source "arch/arm/mach-nomadik/Kconfig"
@@ -982,9 +1016,11 @@ config ARCH_ACORN
 config PLAT_IOP
 	bool
 	select GENERIC_CLOCKEVENTS
+	select HAVE_SCHED_CLOCK
 
 config PLAT_ORION
 	bool
+	select HAVE_SCHED_CLOCK
 
 config PLAT_PXA
 	bool
@@ -999,8 +1035,8 @@ source arch/arm/mm/Kconfig
 
 config IWMMXT
 	bool "Enable iWMMXt support"
-	depends on CPU_XSCALE || CPU_XSC3 || CPU_MOHAWK
-	default y if PXA27x || PXA3xx || ARCH_MMP
+	depends on CPU_XSCALE || CPU_XSC3 || CPU_MOHAWK || CPU_PJ4
+	default y if PXA27x || PXA3xx || PXA95x || ARCH_MMP
 	help
 	  Enable support for iWMMXt context switching at run time if
 	  running on a CPU that supports it.
@@ -1017,6 +1053,11 @@ config CPU_HAS_PMU
 	default y
 	bool
 
+config MULTI_IRQ_HANDLER
+	bool
+	help
+	  Allow each machine to specify it's own IRQ handler at run time.
+
 if !MMU
 source "arch/arm/Kconfig-nommu"
 endif
@@ -1136,6 +1177,31 @@ config ARM_ERRATA_743622
 	  visible impact on the overall performance or power consumption of the
 	  processor.
 
+config ARM_ERRATA_751472
+	bool "ARM errata: Interrupted ICIALLUIS may prevent completion of broadcasted operation"
+	depends on CPU_V7 && SMP
+	help
+	  This option enables the workaround for the 751472 Cortex-A9 (prior
+	  to r3p0) erratum. An interrupted ICIALLUIS operation may prevent the
+	  completion of a following broadcasted operation if the second
+	  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"
+	depends on CACHE_PL310
+	help
+	  This option enables the workaround for the 753970 PL310 (r3p0) erratum.
+
+	  Under some condition the effect of cache sync operation on
+	  the store buffer still remains when the operation completes.
+	  This means that the store buffer is always asked to drain and
+	  this prevents it from merging any further writes. The workaround
+	  is to replace the normal offset of cache sync operation (0x730)
+	  by another offset targeting an unmapped PL310 register 0x740.
+	  This has the same effect as the cache sync operation: store buffer
+	  drain and waiting for all buffers empty.
+
 endmenu
 
 source "arch/arm/common/Kconfig"
@@ -1164,7 +1230,7 @@ config ISA_DMA_API
 	bool
 
 config PCI
-	bool "PCI support" if ARCH_INTEGRATOR_AP || ARCH_VERSATILE_PB || ARCH_IXP4XX || ARCH_KS8695 || MACH_ARMCORE || ARCH_CNS3XXX
+	bool "PCI support" if MIGHT_HAVE_PCI
 	help
 	  Find out whether you have a PCI motherboard. PCI is the name of a
 	  bus system, i.e. the way the CPU talks to the other stuff inside
@@ -1175,6 +1241,12 @@ config PCI_DOMAINS
 	bool
 	depends on PCI
 
+config PCI_NANOENGINE
+	bool "BSE nanoEngine PCI support"
+	depends on SA1100_NANOENGINE
+	help
+	  Enable PCI on the BSE nanoEngine board.
+
 config PCI_SYSCALL
 	def_bool PCI
 
@@ -1205,10 +1277,11 @@ config SMP
 	depends on EXPERIMENTAL
 	depends on GENERIC_CLOCKEVENTS
 	depends on REALVIEW_EB_ARM11MP || REALVIEW_EB_A9MP || \
-		 MACH_REALVIEW_PB11MP || MACH_REALVIEW_PBX || ARCH_OMAP4 ||\
-		 ARCH_S5PV310 || ARCH_TEGRA || ARCH_U8500 || ARCH_VEXPRESS_CA9X4
+		 MACH_REALVIEW_PB11MP || MACH_REALVIEW_PBX || ARCH_OMAP4 || \
+		 ARCH_S5PV310 || ARCH_TEGRA || ARCH_U8500 || ARCH_VEXPRESS_CA9X4 || \
+		 ARCH_MSM_SCORPIONMP || ARCH_SHMOBILE
 	select USE_GENERIC_SMP_HELPERS
-	select HAVE_ARM_SCU
+	select HAVE_ARM_SCU if !ARCH_MSM_SCORPIONMP
 	help
 	  This enables support for systems with more than one CPU. If you have
 	  a system with only one CPU, like most personal computers, say N. If
@@ -1229,7 +1302,7 @@ config SMP
 config SMP_ON_UP
 	bool "Allow booting SMP kernel on uniprocessor systems (EXPERIMENTAL)"
 	depends on EXPERIMENTAL
-	depends on SMP && !XIP && !THUMB2_KERNEL
+	depends on SMP && !XIP_KERNEL
 	default y
 	help
 	  SMP kernels contain instructions which fail on non-SMP processors.
@@ -1248,6 +1321,7 @@ config HAVE_ARM_SCU
 config HAVE_ARM_TWD
 	bool
 	depends on SMP
+	select TICK_ONESHOT
 	help
 	  This options enables support for the ARM timer and watchdog unit
 
@@ -1283,6 +1357,7 @@ config NR_CPUS
 config HOTPLUG_CPU
 	bool "Support for hot-pluggable CPUs (EXPERIMENTAL)"
 	depends on SMP && HOTPLUG && EXPERIMENTAL
+	depends on !ARCH_MSM
 	help
 	  Say Y here to experiment with turning CPUs off and on.  CPUs
 	  can be controlled through /sys/devices/system/cpu.
@@ -1291,7 +1366,7 @@ config LOCAL_TIMERS
 	bool "Use local timer interrupts"
 	depends on SMP
 	default y
-	select HAVE_ARM_TWD
+	select HAVE_ARM_TWD if !ARCH_MSM_SCORPIONMP
 	help
 	  Enable support for local timers on SMP platforms, rather then the
 	  legacy IPI broadcast method.  Local timers allows the system
@@ -1310,7 +1385,7 @@ config HZ
 	default 100
 
 config THUMB2_KERNEL
-	bool "Compile the kernel in Thumb-2 mode"
+	bool "Compile the kernel in Thumb-2 mode (EXPERIMENTAL)"
 	depends on CPU_V7 && !CPU_V6 && EXPERIMENTAL
 	select AEABI
 	select ARM_ASM_UNIFIED
@@ -1341,7 +1416,7 @@ config AEABI
 
 config OABI_COMPAT
 	bool "Allow old ABI binaries to run with this kernel (EXPERIMENTAL)"
-	depends on AEABI && EXPERIMENTAL
+	depends on AEABI && EXPERIMENTAL && !THUMB2_KERNEL
 	default y
 	help
 	  This option preserves the old syscall interface along with the
@@ -1398,15 +1473,6 @@ config HW_PERF_EVENTS
 	  Enable hardware performance counter support for perf events. If
 	  disabled, perf events will use software events only.
 
-config SPARSE_IRQ
-	def_bool n
-	help
-	  This enables support for sparse irqs. This is useful in general
-	  as most CPUs have a fairly sparse array of IRQ vectors, which
-	  the irq_desc then maps directly on to. Systems with a high
-	  number of off-chip IRQs will want to treat this as
-	  experimental until they have been independently verified.
-
 source "mm/Kconfig"
 
 config FORCE_MAX_ZONEORDER
@@ -1524,6 +1590,7 @@ config SECCOMP
 
 config CC_STACKPROTECTOR
 	bool "Enable -fstack-protector buffer overflow detection (EXPERIMENTAL)"
+	depends on EXPERIMENTAL
 	help
 	  This option turns on the -fstack-protector GCC feature. This
 	  feature puts, at the beginning of functions, a canary value on
@@ -1650,6 +1717,19 @@ config ATAGS_PROC
 	  Should the atags used to boot the kernel be exported in an "atags"
 	  file in procfs. Useful with kexec.
 
+config CRASH_DUMP
+	bool "Build kdump crash kernel (EXPERIMENTAL)"
+	depends on EXPERIMENTAL
+	help
+	  Generate crash dump after being started by kexec. This should
+	  be normally only set in special crash dump kernels which are
+	  loaded in the main kernel with kexec-tools into a specially
+	  reserved region and then later executed after a crash by
+	  kdump/kexec. The crash dump kernel must be compiled to a
+	  memory address not used by the main kernel
+
+	  For more details see Documentation/kdump/kdump.txt
+
 config AUTO_ZRELADDR
 	bool "Auto calculation of the decompressed kernel image address"
 	depends on !ZBOOT_ROM && !ARCH_U300
@@ -1707,7 +1787,7 @@ config CPU_FREQ_S3C
 	  Internal configuration node for common cpufreq on Samsung SoC
 
 config CPU_FREQ_S3C24XX
-	bool "CPUfreq driver for Samsung S3C24XX series CPUs"
+	bool "CPUfreq driver for Samsung S3C24XX series CPUs (EXPERIMENTAL)"
 	depends on ARCH_S3C2410 && CPU_FREQ && EXPERIMENTAL
 	select CPU_FREQ_S3C
 	help
@@ -1719,7 +1799,7 @@ config CPU_FREQ_S3C24XX
 	  If in doubt, say N.
 
 config CPU_FREQ_S3C24XX_PLL
-	bool "Support CPUfreq changing of PLL frequency"
+	bool "Support CPUfreq changing of PLL frequency (EXPERIMENTAL)"
 	depends on CPU_FREQ_S3C24XX && EXPERIMENTAL
 	help
 	  Compile in support for changing the PLL frequency from the
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/Kconfig.debug linux-libre-2.6.38-gnu1/arch/arm/Kconfig.debug
--- linux-libre-2.6.37-gnu1/arch/arm/Kconfig.debug	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/Kconfig.debug	2011-03-14 21:20:32.000000000 -0400
@@ -23,7 +23,7 @@ config STRICT_DEVMEM
 config FRAME_POINTER
 	bool
 	depends on !THUMB2_KERNEL
-	default y if !ARM_UNWIND
+	default y if !ARM_UNWIND || FUNCTION_GRAPH_TRACER
 	help
 	  If you say N here, the resulting kernel will be slightly smaller and
 	  faster. However, if neither FRAME_POINTER nor ARM_UNWIND are enabled,
@@ -31,7 +31,7 @@ config FRAME_POINTER
 	  reported is severely limited.
 
 config ARM_UNWIND
-	bool "Enable stack unwinding support"
+	bool "Enable stack unwinding support (EXPERIMENTAL)"
 	depends on AEABI && EXPERIMENTAL
 	default y
 	help
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/kernel/ecard.c linux-libre-2.6.38-gnu1/arch/arm/kernel/ecard.c
--- linux-libre-2.6.37-gnu1/arch/arm/kernel/ecard.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/kernel/ecard.c	2011-03-14 21:20:32.000000000 -0400
@@ -443,40 +443,40 @@ static expansioncard_ops_t ecard_default
  *
  * They are not meant to be called directly, but via enable/disable_irq.
  */
-static void ecard_irq_unmask(unsigned int irqnr)
+static void ecard_irq_unmask(struct irq_data *d)
 {
-	ecard_t *ec = slot_to_ecard(irqnr - 32);
+	ecard_t *ec = slot_to_ecard(d->irq - 32);
 
 	if (ec) {
 		if (!ec->ops)
 			ec->ops = &ecard_default_ops;
 
 		if (ec->claimed && ec->ops->irqenable)
-			ec->ops->irqenable(ec, irqnr);
+			ec->ops->irqenable(ec, d->irq);
 		else
 			printk(KERN_ERR "ecard: rejecting request to "
-				"enable IRQs for %d\n", irqnr);
+				"enable IRQs for %d\n", d->irq);
 	}
 }
 
-static void ecard_irq_mask(unsigned int irqnr)
+static void ecard_irq_mask(struct irq_data *d)
 {
-	ecard_t *ec = slot_to_ecard(irqnr - 32);
+	ecard_t *ec = slot_to_ecard(d->irq - 32);
 
 	if (ec) {
 		if (!ec->ops)
 			ec->ops = &ecard_default_ops;
 
 		if (ec->ops && ec->ops->irqdisable)
-			ec->ops->irqdisable(ec, irqnr);
+			ec->ops->irqdisable(ec, d->irq);
 	}
 }
 
 static struct irq_chip ecard_chip = {
-	.name	= "ECARD",
-	.ack	= ecard_irq_mask,
-	.mask	= ecard_irq_mask,
-	.unmask = ecard_irq_unmask,
+	.name		= "ECARD",
+	.irq_ack	= ecard_irq_mask,
+	.irq_mask	= ecard_irq_mask,
+	.irq_unmask	= ecard_irq_unmask,
 };
 
 void ecard_enablefiq(unsigned int fiqnr)
@@ -551,7 +551,7 @@ static void ecard_check_lockup(struct ir
 			printk(KERN_ERR "\nInterrupt lockup detected - "
 			       "disabling all expansion card interrupts\n");
 
-			desc->chip->mask(IRQ_EXPANSIONCARD);
+			desc->irq_data.chip->irq_mask(&desc->irq_data);
 			ecard_dump_irq_state();
 		}
 	} else
@@ -574,7 +574,7 @@ ecard_irq_handler(unsigned int irq, stru
 	ecard_t *ec;
 	int called = 0;
 
-	desc->chip->mask(irq);
+	desc->irq_data.chip->irq_mask(&desc->irq_data);
 	for (ec = cards; ec; ec = ec->next) {
 		int pending;
 
@@ -591,7 +591,7 @@ ecard_irq_handler(unsigned int irq, stru
 			called ++;
 		}
 	}
-	desc->chip->unmask(irq);
+	desc->irq_data.chip->irq_unmask(&desc->irq_data);
 
 	if (called == 0)
 		ecard_check_lockup(desc);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/kernel/entry-armv.S linux-libre-2.6.38-gnu1/arch/arm/kernel/entry-armv.S
--- linux-libre-2.6.37-gnu1/arch/arm/kernel/entry-armv.S	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/kernel/entry-armv.S	2011-03-14 21:20:32.000000000 -0400
@@ -25,42 +25,22 @@
 #include <asm/tls.h>
 
 #include "entry-header.S"
+#include <asm/entry-macro-multi.S>
 
 /*
  * Interrupt handling.  Preserves r7, r8, r9
  */
 	.macro	irq_handler
-	get_irqnr_preamble r5, lr
-1:	get_irqnr_and_base r0, r6, r5, lr
-	movne	r1, sp
-	@
-	@ routine called with r0 = irq number, r1 = struct pt_regs *
-	@
-	adrne	lr, BSYM(1b)
-	bne	asm_do_IRQ
-
-#ifdef CONFIG_SMP
-	/*
-	 * XXX
-	 *
-	 * this macro assumes that irqstat (r6) and base (r5) are
-	 * preserved from get_irqnr_and_base above
-	 */
-	ALT_SMP(test_for_ipi r0, r6, r5, lr)
-	ALT_UP_B(9997f)
-	movne	r0, sp
-	adrne	lr, BSYM(1b)
-	bne	do_IPI
-
-#ifdef CONFIG_LOCAL_TIMERS
-	test_for_ltirq r0, r6, r5, lr
-	movne	r0, sp
-	adrne	lr, BSYM(1b)
-	bne	do_local_timer
+#ifdef CONFIG_MULTI_IRQ_HANDLER
+	ldr	r5, =handle_arch_irq
+	mov	r0, sp
+	ldr	r5, [r5]
+	adr	lr, BSYM(9997f)
+	teq	r5, #0
+	movne	pc, r5
 #endif
+	arch_irq_handler_default
 9997:
-#endif
-
 	.endm
 
 #ifdef CONFIG_KPROBES
@@ -198,6 +178,7 @@ __dabt_svc:
 	@
 	@ set desired IRQ state, then call main handler
 	@
+	debug_entry r1
 	msr	cpsr_c, r9
 	mov	r2, sp
 	bl	do_DataAbort
@@ -324,6 +305,7 @@ __pabt_svc:
 #else
 	bl	CPU_PABORT_HANDLER
 #endif
+	debug_entry r1
 	msr	cpsr_c, r9			@ Maybe enable interrupts
 	mov	r2, sp				@ regs
 	bl	do_PrefetchAbort		@ call abort handler
@@ -439,6 +421,7 @@ __dabt_usr:
 	@
 	@ IRQs on, then call the main handler
 	@
+	debug_entry r1
 	enable_irq
 	mov	r2, sp
 	adr	lr, BSYM(ret_from_exception)
@@ -703,6 +686,7 @@ __pabt_usr:
 #else
 	bl	CPU_PABORT_HANDLER
 #endif
+	debug_entry r1
 	enable_irq				@ Enable interrupts
 	mov	r2, sp				@ regs
 	bl	do_PrefetchAbort		@ call abort handler
@@ -735,7 +719,7 @@ ENTRY(__switch_to)
  THUMB(	stmia	ip!, {r4 - sl, fp}	   )	@ Store most regs on stack
  THUMB(	str	sp, [ip], #4		   )
  THUMB(	str	lr, [ip], #4		   )
-#ifdef CONFIG_MMU
+#ifdef CONFIG_CPU_USE_DOMAINS
 	ldr	r6, [r2, #TI_CPU_DOMAIN]
 #endif
 	set_tls	r3, r4, r5
@@ -744,7 +728,7 @@ ENTRY(__switch_to)
 	ldr	r8, =__stack_chk_guard
 	ldr	r7, [r7, #TSK_STACK_CANARY]
 #endif
-#ifdef CONFIG_MMU
+#ifdef CONFIG_CPU_USE_DOMAINS
 	mcr	p15, 0, r6, c3, c0, 0		@ Set domain register
 #endif
 	mov	r5, r0
@@ -842,7 +826,7 @@ __kuser_helper_start:
  */
 
 __kuser_memory_barrier:				@ 0xffff0fa0
-	smp_dmb
+	smp_dmb	arm
 	usr_ret	lr
 
 	.align	5
@@ -959,7 +943,7 @@ kuser_cmpxchg_fixup:
 
 #else
 
-	smp_dmb
+	smp_dmb	arm
 1:	ldrex	r3, [r2]
 	subs	r3, r3, r0
 	strexeq	r3, r1, [r2]
@@ -1245,3 +1229,9 @@ cr_alignment:
 	.space	4
 cr_no_alignment:
 	.space	4
+
+#ifdef CONFIG_MULTI_IRQ_HANDLER
+	.globl	handle_arch_irq
+handle_arch_irq:
+	.space	4
+#endif
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/kernel/entry-common.S linux-libre-2.6.38-gnu1/arch/arm/kernel/entry-common.S
--- linux-libre-2.6.37-gnu1/arch/arm/kernel/entry-common.S	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/kernel/entry-common.S	2011-03-14 21:20:32.000000000 -0400
@@ -147,98 +147,170 @@ ENDPROC(ret_from_fork)
 #endif
 #endif
 
-#ifdef CONFIG_DYNAMIC_FTRACE
-ENTRY(__gnu_mcount_nc)
-	mov	ip, lr
-	ldmia	sp!, {lr}
-	mov	pc, ip
-ENDPROC(__gnu_mcount_nc)
+.macro __mcount suffix
+	mcount_enter
+	ldr	r0, =ftrace_trace_function
+	ldr	r2, [r0]
+	adr	r0, .Lftrace_stub
+	cmp	r0, r2
+	bne	1f
 
-ENTRY(ftrace_caller)
-	stmdb	sp!, {r0-r3, lr}
-	mov	r0, lr
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+	ldr     r1, =ftrace_graph_return
+	ldr     r2, [r1]
+	cmp     r0, r2
+	bne     ftrace_graph_caller\suffix
+
+	ldr     r1, =ftrace_graph_entry
+	ldr     r2, [r1]
+	ldr     r0, =ftrace_graph_entry_stub
+	cmp     r0, r2
+	bne     ftrace_graph_caller\suffix
+#endif
+
+	mcount_exit
+
+1: 	mcount_get_lr	r1			@ lr of instrumented func
+	mov	r0, lr				@ instrumented function
 	sub	r0, r0, #MCOUNT_INSN_SIZE
-	ldr	r1, [sp, #20]
+	adr	lr, BSYM(2f)
+	mov	pc, r2
+2:	mcount_exit
+.endm
 
-	.global	ftrace_call
-ftrace_call:
+.macro __ftrace_caller suffix
+	mcount_enter
+
+	mcount_get_lr	r1			@ lr of instrumented func
+	mov	r0, lr				@ instrumented function
+	sub	r0, r0, #MCOUNT_INSN_SIZE
+
+	.globl ftrace_call\suffix
+ftrace_call\suffix:
 	bl	ftrace_stub
-	ldmia	sp!, {r0-r3, ip, lr}
-	mov	pc, ip
-ENDPROC(ftrace_caller)
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+	.globl ftrace_graph_call\suffix
+ftrace_graph_call\suffix:
+	mov	r0, r0
+#endif
+
+	mcount_exit
+.endm
+
+.macro __ftrace_graph_caller
+	sub	r0, fp, #4		@ &lr of instrumented routine (&parent)
+#ifdef CONFIG_DYNAMIC_FTRACE
+	@ called from __ftrace_caller, saved in mcount_enter
+	ldr	r1, [sp, #16]		@ instrumented routine (func)
+#else
+	@ called from __mcount, untouched in lr
+	mov	r1, lr			@ instrumented routine (func)
+#endif
+	sub	r1, r1, #MCOUNT_INSN_SIZE
+	mov	r2, fp			@ frame pointer
+	bl	prepare_ftrace_return
+	mcount_exit
+.endm
 
 #ifdef CONFIG_OLD_MCOUNT
+/*
+ * mcount
+ */
+
+.macro mcount_enter
+	stmdb	sp!, {r0-r3, lr}
+.endm
+
+.macro mcount_get_lr reg
+	ldr	\reg, [fp, #-4]
+.endm
+
+.macro mcount_exit
+	ldr	lr, [fp, #-4]
+	ldmia	sp!, {r0-r3, pc}
+.endm
+
 ENTRY(mcount)
+#ifdef CONFIG_DYNAMIC_FTRACE
 	stmdb	sp!, {lr}
 	ldr	lr, [fp, #-4]
 	ldmia	sp!, {pc}
+#else
+	__mcount _old
+#endif
 ENDPROC(mcount)
 
+#ifdef CONFIG_DYNAMIC_FTRACE
 ENTRY(ftrace_caller_old)
-	stmdb	sp!, {r0-r3, lr}
-	ldr	r1, [fp, #-4]
-	mov	r0, lr
-	sub	r0, r0, #MCOUNT_INSN_SIZE
-
-	.globl ftrace_call_old
-ftrace_call_old:
-	bl	ftrace_stub
-	ldr	lr, [fp, #-4]			@ restore lr
-	ldmia	sp!, {r0-r3, pc}
+	__ftrace_caller _old
 ENDPROC(ftrace_caller_old)
 #endif
 
-#else
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+ENTRY(ftrace_graph_caller_old)
+	__ftrace_graph_caller
+ENDPROC(ftrace_graph_caller_old)
+#endif
 
-ENTRY(__gnu_mcount_nc)
+.purgem mcount_enter
+.purgem mcount_get_lr
+.purgem mcount_exit
+#endif
+
+/*
+ * __gnu_mcount_nc
+ */
+
+.macro mcount_enter
 	stmdb	sp!, {r0-r3, lr}
-	ldr	r0, =ftrace_trace_function
-	ldr	r2, [r0]
-	adr	r0, .Lftrace_stub
-	cmp	r0, r2
-	bne	gnu_trace
+.endm
+
+.macro mcount_get_lr reg
+	ldr	\reg, [sp, #20]
+.endm
+
+.macro mcount_exit
 	ldmia	sp!, {r0-r3, ip, lr}
 	mov	pc, ip
+.endm
 
-gnu_trace:
-	ldr	r1, [sp, #20]			@ lr of instrumented routine
-	mov	r0, lr
-	sub	r0, r0, #MCOUNT_INSN_SIZE
-	adr	lr, BSYM(1f)
-	mov	pc, r2
-1:
-	ldmia	sp!, {r0-r3, ip, lr}
+ENTRY(__gnu_mcount_nc)
+#ifdef CONFIG_DYNAMIC_FTRACE
+	mov	ip, lr
+	ldmia	sp!, {lr}
 	mov	pc, ip
+#else
+	__mcount
+#endif
 ENDPROC(__gnu_mcount_nc)
 
-#ifdef CONFIG_OLD_MCOUNT
-/*
- * This is under an ifdef in order to force link-time errors for people trying
- * to build with !FRAME_POINTER with a GCC which doesn't use the new-style
- * mcount.
- */
-ENTRY(mcount)
-	stmdb	sp!, {r0-r3, lr}
-	ldr	r0, =ftrace_trace_function
-	ldr	r2, [r0]
-	adr	r0, ftrace_stub
-	cmp	r0, r2
-	bne	trace
-	ldr	lr, [fp, #-4]			@ restore lr
-	ldmia	sp!, {r0-r3, pc}
+#ifdef CONFIG_DYNAMIC_FTRACE
+ENTRY(ftrace_caller)
+	__ftrace_caller
+ENDPROC(ftrace_caller)
+#endif
 
-trace:
-	ldr	r1, [fp, #-4]			@ lr of instrumented routine
-	mov	r0, lr
-	sub	r0, r0, #MCOUNT_INSN_SIZE
-	mov	lr, pc
-	mov	pc, r2
-	ldr	lr, [fp, #-4]			@ restore lr
-	ldmia	sp!, {r0-r3, pc}
-ENDPROC(mcount)
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+ENTRY(ftrace_graph_caller)
+	__ftrace_graph_caller
+ENDPROC(ftrace_graph_caller)
 #endif
 
-#endif /* CONFIG_DYNAMIC_FTRACE */
+.purgem mcount_enter
+.purgem mcount_get_lr
+.purgem mcount_exit
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+	.globl return_to_handler
+return_to_handler:
+	stmdb	sp!, {r0-r3}
+	mov	r0, fp			@ frame pointer
+	bl	ftrace_return_to_handler
+	mov	lr, r0			@ r0 has real ret addr
+	ldmia	sp!, {r0-r3}
+	mov	pc, lr
+#endif
 
 ENTRY(ftrace_stub)
 .Lftrace_stub:
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/kernel/entry-header.S linux-libre-2.6.38-gnu1/arch/arm/kernel/entry-header.S
--- linux-libre-2.6.37-gnu1/arch/arm/kernel/entry-header.S	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/kernel/entry-header.S	2011-03-14 21:20:32.000000000 -0400
@@ -165,6 +165,25 @@
 	.endm
 #endif	/* !CONFIG_THUMB2_KERNEL */
 
+	@
+	@ Debug exceptions are taken as prefetch or data aborts.
+	@ We must disable preemption during the handler so that
+	@ we can access the debug registers safely.
+	@
+	.macro	debug_entry, fsr
+#if defined(CONFIG_HAVE_HW_BREAKPOINT) && defined(CONFIG_PREEMPT)
+	ldr	r4, =0x40f		@ mask out fsr.fs
+	and	r5, r4, \fsr
+	cmp	r5, #2			@ debug exception
+	bne	1f
+	get_thread_info r10
+	ldr	r6, [r10, #TI_PREEMPT]	@ get preempt count
+	add	r11, r6, #1		@ increment it
+	str	r11, [r10, #TI_PREEMPT]
+1:
+#endif
+	.endm
+
 /*
  * These are the registers used in the syscall handler, and allow us to
  * have in theory up to 7 arguments to a function - r0 to r6.
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/kernel/fiq.c linux-libre-2.6.38-gnu1/arch/arm/kernel/fiq.c
--- linux-libre-2.6.37-gnu1/arch/arm/kernel/fiq.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/kernel/fiq.c	2011-03-14 21:20:32.000000000 -0400
@@ -45,6 +45,7 @@
 #include <asm/fiq.h>
 #include <asm/irq.h>
 #include <asm/system.h>
+#include <asm/traps.h>
 
 static unsigned long no_fiq_insn;
 
@@ -67,17 +68,22 @@ static struct fiq_handler default_owner
 
 static struct fiq_handler *current_fiq = &default_owner;
 
-int show_fiq_list(struct seq_file *p, void *v)
+int show_fiq_list(struct seq_file *p, int prec)
 {
 	if (current_fiq != &default_owner)
-		seq_printf(p, "FIQ:              %s\n", current_fiq->name);
+		seq_printf(p, "%*s:              %s\n", prec, "FIQ",
+			current_fiq->name);
 
 	return 0;
 }
 
 void set_fiq_handler(void *start, unsigned int length)
 {
+#if defined(CONFIG_CPU_USE_DOMAINS)
 	memcpy((void *)0xffff001c, start, length);
+#else
+	memcpy(vectors_page + 0x1c, start, length);
+#endif
 	flush_icache_range(0xffff001c, 0xffff001c + length);
 	if (!vectors_high())
 		flush_icache_range(0x1c, 0x1c + length);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/kernel/ftrace.c linux-libre-2.6.38-gnu1/arch/arm/kernel/ftrace.c
--- linux-libre-2.6.37-gnu1/arch/arm/kernel/ftrace.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/kernel/ftrace.c	2011-03-14 21:20:32.000000000 -0400
@@ -24,6 +24,7 @@
 #define	NOP		0xe8bd4000	/* pop {lr} */
 #endif
 
+#ifdef CONFIG_DYNAMIC_FTRACE
 #ifdef CONFIG_OLD_MCOUNT
 #define OLD_MCOUNT_ADDR	((unsigned long) mcount)
 #define OLD_FTRACE_ADDR ((unsigned long) ftrace_caller_old)
@@ -59,9 +60,9 @@ static unsigned long adjust_address(stru
 }
 #endif
 
-/* construct a branch (BL) instruction to addr */
 #ifdef CONFIG_THUMB2_KERNEL
-static unsigned long ftrace_call_replace(unsigned long pc, unsigned long addr)
+static unsigned long ftrace_gen_branch(unsigned long pc, unsigned long addr,
+				       bool link)
 {
 	unsigned long s, j1, j2, i1, i2, imm10, imm11;
 	unsigned long first, second;
@@ -83,15 +84,22 @@ static unsigned long ftrace_call_replace
 	j2 = (!i2) ^ s;
 
 	first = 0xf000 | (s << 10) | imm10;
-	second = 0xd000 | (j1 << 13) | (j2 << 11) | imm11;
+	second = 0x9000 | (j1 << 13) | (j2 << 11) | imm11;
+	if (link)
+		second |= 1 << 14;
 
 	return (second << 16) | first;
 }
 #else
-static unsigned long ftrace_call_replace(unsigned long pc, unsigned long addr)
+static unsigned long ftrace_gen_branch(unsigned long pc, unsigned long addr,
+				       bool link)
 {
+	unsigned long opcode = 0xea000000;
 	long offset;
 
+	if (link)
+		opcode |= 1 << 24;
+
 	offset = (long)addr - (long)(pc + 8);
 	if (unlikely(offset < -33554432 || offset > 33554428)) {
 		/* Can't generate branches that far (from ARM ARM). Ftrace
@@ -103,10 +111,15 @@ static unsigned long ftrace_call_replace
 
 	offset = (offset >> 2) & 0x00ffffff;
 
-	return 0xeb000000 | offset;
+	return opcode | offset;
 }
 #endif
 
+static unsigned long ftrace_call_replace(unsigned long pc, unsigned long addr)
+{
+	return ftrace_gen_branch(pc, addr, true);
+}
+
 static int ftrace_modify_code(unsigned long pc, unsigned long old,
 			      unsigned long new)
 {
@@ -193,3 +206,83 @@ int __init ftrace_dyn_arch_init(void *da
 
 	return 0;
 }
+#endif /* CONFIG_DYNAMIC_FTRACE */
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
+			   unsigned long frame_pointer)
+{
+	unsigned long return_hooker = (unsigned long) &return_to_handler;
+	struct ftrace_graph_ent trace;
+	unsigned long old;
+	int err;
+
+	if (unlikely(atomic_read(&current->tracing_graph_pause)))
+		return;
+
+	old = *parent;
+	*parent = return_hooker;
+
+	err = ftrace_push_return_trace(old, self_addr, &trace.depth,
+				       frame_pointer);
+	if (err == -EBUSY) {
+		*parent = old;
+		return;
+	}
+
+	trace.func = self_addr;
+
+	/* Only trace if the calling function expects to */
+	if (!ftrace_graph_entry(&trace)) {
+		current->curr_ret_stack--;
+		*parent = old;
+	}
+}
+
+#ifdef CONFIG_DYNAMIC_FTRACE
+extern unsigned long ftrace_graph_call;
+extern unsigned long ftrace_graph_call_old;
+extern void ftrace_graph_caller_old(void);
+
+static int __ftrace_modify_caller(unsigned long *callsite,
+				  void (*func) (void), bool enable)
+{
+	unsigned long caller_fn = (unsigned long) func;
+	unsigned long pc = (unsigned long) callsite;
+	unsigned long branch = ftrace_gen_branch(pc, caller_fn, false);
+	unsigned long nop = 0xe1a00000;	/* mov r0, r0 */
+	unsigned long old = enable ? nop : branch;
+	unsigned long new = enable ? branch : nop;
+
+	return ftrace_modify_code(pc, old, new);
+}
+
+static int ftrace_modify_graph_caller(bool enable)
+{
+	int ret;
+
+	ret = __ftrace_modify_caller(&ftrace_graph_call,
+				     ftrace_graph_caller,
+				     enable);
+
+#ifdef CONFIG_OLD_MCOUNT
+	if (!ret)
+		ret = __ftrace_modify_caller(&ftrace_graph_call_old,
+					     ftrace_graph_caller_old,
+					     enable);
+#endif
+
+	return ret;
+}
+
+int ftrace_enable_ftrace_graph_caller(void)
+{
+	return ftrace_modify_graph_caller(true);
+}
+
+int ftrace_disable_ftrace_graph_caller(void)
+{
+	return ftrace_modify_graph_caller(false);
+}
+#endif /* CONFIG_DYNAMIC_FTRACE */
+#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/kernel/head-common.S linux-libre-2.6.38-gnu1/arch/arm/kernel/head-common.S
--- linux-libre-2.6.37-gnu1/arch/arm/kernel/head-common.S	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/kernel/head-common.S	2011-03-14 21:20:32.000000000 -0400
@@ -60,6 +60,8 @@ str_a1:	.asciz	"\nError: unrecognized/un
 str_a2:	.asciz	").\n\nAvailable machine support:\n\nID (hex)\tNAME\n"
 str_a3:	.asciz	"\nPlease check your kernel config and/or bootloader.\n"
 	.align
+#else
+	b	__error
 #endif
 
 /*
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/kernel/head.S linux-libre-2.6.38-gnu1/arch/arm/kernel/head.S
--- linux-libre-2.6.37-gnu1/arch/arm/kernel/head.S	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/kernel/head.S	2011-03-14 21:20:32.000000000 -0400
@@ -91,6 +91,11 @@ ENTRY(stext)
 	movs	r8, r5				@ invalid machine (r5=0)?
  THUMB( it	eq )		@ force fixup-able long branch encoding
 	beq	__error_a			@ yes, error 'a'
+
+	/*
+	 * r1 = machine no, r2 = atags,
+	 * r8 = machinfo, r9 = cpuid, r10 = procinfo
+	 */
 	bl	__vet_atags
 #ifdef CONFIG_SMP_ON_UP
 	bl	__fixup_smp
@@ -386,37 +391,32 @@ ENDPROC(__turn_mmu_on)
 
 
 #ifdef CONFIG_SMP_ON_UP
+	__INIT
 __fixup_smp:
-	mov	r7, #0x00070000
-	orr	r6, r7, #0xff000000	@ mask 0xff070000
-	orr	r7, r7, #0x41000000	@ val 0x41070000
-	and	r0, r9, r6
-	teq	r0, r7			@ ARM CPU and ARMv6/v7?
+	and	r3, r9, #0x000f0000	@ architecture version
+	teq	r3, #0x000f0000		@ CPU ID supported?
 	bne	__fixup_smp_on_up	@ no, assume UP
 
-	orr	r6, r6, #0x0000ff00
-	orr	r6, r6, #0x000000f0	@ mask 0xff07fff0
-	orr	r7, r7, #0x0000b000
-	orr	r7, r7, #0x00000020	@ val 0x4107b020
-	and	r0, r9, r6
-	teq	r0, r7			@ ARM 11MPCore?
+	bic	r3, r9, #0x00ff0000
+	bic	r3, r3, #0x0000000f	@ mask 0xff00fff0
+	mov	r4, #0x41000000
+	orr	r4, r4, #0x0000b000
+	orr	r4, r4, #0x00000020	@ val 0x4100b020
+	teq	r3, r4			@ ARM 11MPCore?
 	moveq	pc, lr			@ yes, assume SMP
 
 	mrc	p15, 0, r0, c0, c0, 5	@ read MPIDR
-	tst	r0, #1 << 31
-	movne	pc, lr			@ bit 31 => SMP
+	and	r0, r0, #0xc0000000	@ multiprocessing extensions and
+	teq	r0, #0x80000000		@ not part of a uniprocessor system?
+	moveq	pc, lr			@ yes, assume SMP
 
 __fixup_smp_on_up:
 	adr	r0, 1f
-	ldmia	r0, {r3, r6, r7}
+	ldmia	r0, {r3 - r5}
 	sub	r3, r0, r3
-	add	r6, r6, r3
-	add	r7, r7, r3
-2:	cmp	r6, r7
-	ldmia	r6!, {r0, r4}
-	strlo	r4, [r0, r3]
-	blo	2b
-	mov	pc, lr
+	add	r4, r4, r3
+	add	r5, r5, r3
+	b	__do_fixup_smp_on_up
 ENDPROC(__fixup_smp)
 
 	.align
@@ -430,7 +430,31 @@ smp_on_up:
 	ALT_SMP(.long	1)
 	ALT_UP(.long	0)
 	.popsection
+#endif
 
+	.text
+__do_fixup_smp_on_up:
+	cmp	r4, r5
+	movhs	pc, lr
+	ldmia	r4!, {r0, r6}
+ ARM(	str	r6, [r0, r3]	)
+ THUMB(	add	r0, r0, r3	)
+#ifdef __ARMEB__
+ THUMB(	mov	r6, r6, ror #16	)	@ Convert word order for big-endian.
 #endif
+ THUMB(	strh	r6, [r0], #2	)	@ For Thumb-2, store as two halfwords
+ THUMB(	mov	r6, r6, lsr #16	)	@ to be robust against misaligned r3.
+ THUMB(	strh	r6, [r0]	)
+	b	__do_fixup_smp_on_up
+ENDPROC(__do_fixup_smp_on_up)
+
+ENTRY(fixup_smp)
+	stmfd	sp!, {r4 - r6, lr}
+	mov	r4, r0
+	add	r5, r0, r1
+	mov	r3, #0
+	bl	__do_fixup_smp_on_up
+	ldmfd	sp!, {r4 - r6, pc}
+ENDPROC(fixup_smp)
 
 #include "head-common.S"
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/kernel/hw_breakpoint.c linux-libre-2.6.38-gnu1/arch/arm/kernel/hw_breakpoint.c
--- linux-libre-2.6.37-gnu1/arch/arm/kernel/hw_breakpoint.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/kernel/hw_breakpoint.c	2011-03-14 21:20:32.000000000 -0400
@@ -24,6 +24,7 @@
 #define pr_fmt(fmt) "hw-breakpoint: " fmt
 
 #include <linux/errno.h>
+#include <linux/hardirq.h>
 #include <linux/perf_event.h>
 #include <linux/hw_breakpoint.h>
 #include <linux/smp.h>
@@ -44,6 +45,7 @@ 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. */
@@ -52,87 +54,6 @@ static u8 debug_arch;
 /* Maximum supported watchpoint length. */
 static u8 max_watchpoint_len;
 
-/* Determine number of BRP registers available. */
-static int get_num_brps(void)
-{
-	u32 didr;
-	ARM_DBG_READ(c0, 0, didr);
-	return ((didr >> 24) & 0xf) + 1;
-}
-
-/* Determine number of WRP registers available. */
-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.
-	 *
-	 * Furthermore, we can only do this if the watchpoint was precise
-	 * since imprecise watchpoints prevent us from calculating register
-	 * based addresses.
-	 *
-	 * For the time being, we only report 1 watchpoint register so we
-	 * always know which watchpoint fired. In the future we can either
-	 * add a disassembler and address generation emulator, or we can
-	 * insert a check to see if the DFAR is set on watchpoint exception
-	 * entry [the ARM ARM states that the DFAR is UNKNOWN, but
-	 * experience shows that it is set on some implementations].
-	 */
-
-#if 0
-	u32 didr, wrps;
-	ARM_DBG_READ(c0, 0, didr);
-	return ((didr >> 28) & 0xf) + 1;
-#endif
-
-	return 1;
-}
-
-int hw_breakpoint_slots(int type)
-{
-	/*
-	 * We can be called early, so don't rely on
-	 * our static variables being initialised.
-	 */
-	switch (type) {
-	case TYPE_INST:
-		return get_num_brps();
-	case TYPE_DATA:
-		return get_num_wrps();
-	default:
-		pr_warning("unknown slot type: %d\n", type);
-		return 0;
-	}
-}
-
-/* Determine debug architecture. */
-static u8 get_debug_arch(void)
-{
-	u32 didr;
-
-	/* Do we implement the extended CPUID interface? */
-	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;
-}
-
-/* Does this core support mismatch breakpoints? */
-static int core_has_mismatch_bps(void)
-{
-	return debug_arch >= ARM_DEBUG_ARCH_V7_ECP14 && core_num_brps > 1;
-}
-
-u8 arch_get_debug_arch(void)
-{
-	return debug_arch;
-}
-
 #define READ_WB_REG_CASE(OP2, M, VAL)		\
 	case ((OP2 << 4) + M):			\
 		ARM_DBG_READ(c ## M, OP2, VAL); \
@@ -210,6 +131,99 @@ static void write_wb_reg(int n, u32 val)
 	isb();
 }
 
+/* Determine debug architecture. */
+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"))
+		return ARM_DEBUG_ARCH_V6;
+
+	ARM_DBG_READ(c0, 0, didr);
+	return (didr >> 16) & 0xf;
+}
+
+u8 arch_get_debug_arch(void)
+{
+	return debug_arch;
+}
+
+static int debug_arch_supported(void)
+{
+	u8 arch = get_debug_arch();
+	return arch >= ARM_DEBUG_ARCH_V6 && arch <= ARM_DEBUG_ARCH_V7_ECP14;
+}
+
+/* Determine number of BRP register available. */
+static int get_num_brp_resources(void)
+{
+	u32 didr;
+	ARM_DBG_READ(c0, 0, didr);
+	return ((didr >> 24) & 0xf) + 1;
+}
+
+/* Does this core support mismatch breakpoints? */
+static int core_has_mismatch_brps(void)
+{
+	return (get_debug_arch() >= ARM_DEBUG_ARCH_V7_ECP14 &&
+		get_num_brp_resources() > 1);
+}
+
+/* Determine number of usable WRPs available. */
+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.
+	 *
+	 * Furthermore, we can only do this if the watchpoint was precise
+	 * since imprecise watchpoints prevent us from calculating register
+	 * based addresses.
+	 *
+	 * Providing we have more than 1 breakpoint register, we only report
+	 * a single watchpoint register for the time being. This way, we always
+	 * know which watchpoint fired. In the future we can either add a
+	 * disassembler and address generation emulator, or we can insert a
+	 * check to see if the DFAR is set on watchpoint exception entry
+	 * [the ARM ARM states that the DFAR is UNKNOWN, but experience shows
+	 * that it is set on some implementations].
+	 */
+
+#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;
+}
+
+/* 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;
+}
+
 /*
  * In order to access the breakpoint/watchpoint control registers,
  * we must be running in debug monitor mode. Unfortunately, we can
@@ -230,8 +244,12 @@ static int enable_monitor_mode(void)
 		goto out;
 	}
 
+	/* If monitor mode is already enabled, just return. */
+	if (dscr & ARM_DSCR_MDBGEN)
+		goto out;
+
 	/* Write to the corresponding DSCR. */
-	switch (debug_arch) {
+	switch (get_debug_arch()) {
 	case ARM_DEBUG_ARCH_V6:
 	case ARM_DEBUG_ARCH_V6_1:
 		ARM_DBG_WRITE(c1, 0, (dscr | ARM_DSCR_MDBGEN));
@@ -246,15 +264,33 @@ static int enable_monitor_mode(void)
 
 	/* Check that the write made it through. */
 	ARM_DBG_READ(c1, 0, dscr);
-	if (WARN_ONCE(!(dscr & ARM_DSCR_MDBGEN),
-				"failed to enable monitor mode.")) {
+	if (!(dscr & ARM_DSCR_MDBGEN))
 		ret = -EPERM;
-	}
 
 out:
 	return ret;
 }
 
+int hw_breakpoint_slots(int type)
+{
+	if (!debug_arch_supported())
+		return 0;
+
+	/*
+	 * We can be called early, so don't rely on
+	 * our static variables being initialised.
+	 */
+	switch (type) {
+	case TYPE_INST:
+		return get_num_brps();
+	case TYPE_DATA:
+		return get_num_wrps();
+	default:
+		pr_warning("unknown slot type: %d\n", type);
+		return 0;
+	}
+}
+
 /*
  * Check if 8-bit byte-address select is available.
  * This clobbers WRP 0.
@@ -268,9 +304,6 @@ static u8 get_max_wp_len(void)
 	if (debug_arch < ARM_DEBUG_ARCH_V7_ECP14)
 		goto out;
 
-	if (enable_monitor_mode())
-		goto out;
-
 	memset(&ctrl, 0, sizeof(ctrl));
 	ctrl.len = ARM_BREAKPOINT_LEN_8;
 	ctrl_reg = encode_ctrl_reg(ctrl);
@@ -290,23 +323,6 @@ u8 arch_get_max_wp_len(void)
 }
 
 /*
- * Handler for reactivating a suspended watchpoint when the single
- * step `mismatch' breakpoint is triggered.
- */
-static void wp_single_step_handler(struct perf_event *bp, int unused,
-				   struct perf_sample_data *data,
-				   struct pt_regs *regs)
-{
-	perf_event_enable(counter_arch_bp(bp)->suspended_wp);
-	unregister_hw_breakpoint(bp);
-}
-
-static int bp_is_single_step(struct perf_event *bp)
-{
-	return bp->overflow_handler == wp_single_step_handler;
-}
-
-/*
  * Install a perf counter breakpoint.
  */
 int arch_install_hw_breakpoint(struct perf_event *bp)
@@ -314,30 +330,41 @@ int arch_install_hw_breakpoint(struct pe
 	struct arch_hw_breakpoint *info = counter_arch_bp(bp);
 	struct perf_event **slot, **slots;
 	int i, max_slots, ctrl_base, val_base, ret = 0;
+	u32 addr, ctrl;
 
 	/* Ensure that we are in monitor mode and halting mode is disabled. */
 	ret = enable_monitor_mode();
 	if (ret)
 		goto out;
 
+	addr = info->address;
+	ctrl = encode_ctrl_reg(info->ctrl) | 0x1;
+
 	if (info->ctrl.type == ARM_BREAKPOINT_EXECUTE) {
 		/* Breakpoint */
 		ctrl_base = ARM_BASE_BCR;
 		val_base = ARM_BASE_BVR;
-		slots = __get_cpu_var(bp_on_reg);
-		max_slots = core_num_brps - 1;
-
-		if (bp_is_single_step(bp)) {
-			info->ctrl.mismatch = 1;
-			i = max_slots;
-			slots[i] = bp;
-			goto setup;
+		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 */
-		ctrl_base = ARM_BASE_WCR;
-		val_base = ARM_BASE_WVR;
-		slots = __get_cpu_var(wp_on_reg);
+		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;
+		}
+		slots = (struct perf_event **)__get_cpu_var(wp_on_reg);
 		max_slots = core_num_wrps;
 	}
 
@@ -355,12 +382,11 @@ int arch_install_hw_breakpoint(struct pe
 		goto out;
 	}
 
-setup:
 	/* Setup the address register. */
-	write_wb_reg(val_base + i, info->address);
+	write_wb_reg(val_base + i, addr);
 
 	/* Setup the control register. */
-	write_wb_reg(ctrl_base + i, encode_ctrl_reg(info->ctrl) | 0x1);
+	write_wb_reg(ctrl_base + i, ctrl);
 
 out:
 	return ret;
@@ -375,18 +401,15 @@ void arch_uninstall_hw_breakpoint(struct
 	if (info->ctrl.type == ARM_BREAKPOINT_EXECUTE) {
 		/* Breakpoint */
 		base = ARM_BASE_BCR;
-		slots = __get_cpu_var(bp_on_reg);
-		max_slots = core_num_brps - 1;
-
-		if (bp_is_single_step(bp)) {
-			i = max_slots;
-			slots[i] = NULL;
-			goto reset;
-		}
+		slots = (struct perf_event **)__get_cpu_var(bp_on_reg);
+		max_slots = core_num_brps;
 	} else {
 		/* Watchpoint */
-		base = ARM_BASE_WCR;
-		slots = __get_cpu_var(wp_on_reg);
+		if (info->step_ctrl.enabled)
+			base = ARM_BASE_BCR + core_num_brps;
+		else
+			base = ARM_BASE_WCR;
+		slots = (struct perf_event **)__get_cpu_var(wp_on_reg);
 		max_slots = core_num_wrps;
 	}
 
@@ -403,7 +426,6 @@ void arch_uninstall_hw_breakpoint(struct
 	if (WARN_ONCE(i == max_slots, "Can't find any breakpoint slot"))
 		return;
 
-reset:
 	/* Reset the control register. */
 	write_wb_reg(base + i, 0);
 }
@@ -537,12 +559,23 @@ static int arch_build_bp_info(struct per
 		return -EINVAL;
 	}
 
+	/*
+	 * Breakpoints must be of length 2 (thumb) or 4 (ARM) bytes.
+	 * Watchpoints can be of length 1, 2, 4 or 8 bytes if supported
+	 * by the hardware and must be aligned to the appropriate number of
+	 * bytes.
+	 */
+	if (info->ctrl.type == ARM_BREAKPOINT_EXECUTE &&
+	    info->ctrl.len != ARM_BREAKPOINT_LEN_2 &&
+	    info->ctrl.len != ARM_BREAKPOINT_LEN_4)
+		return -EINVAL;
+
 	/* Address */
 	info->address = bp->attr.bp_addr;
 
 	/* Privilege */
 	info->ctrl.privilege = ARM_BREAKPOINT_USER;
-	if (arch_check_bp_in_kernelspace(bp) && !bp_is_single_step(bp))
+	if (arch_check_bp_in_kernelspace(bp))
 		info->ctrl.privilege |= ARM_BREAKPOINT_PRIV;
 
 	/* Enabled? */
@@ -561,7 +594,7 @@ int arch_validate_hwbkpt_settings(struct
 {
 	struct arch_hw_breakpoint *info = counter_arch_bp(bp);
 	int ret = 0;
-	u32 bytelen, max_len, offset, alignment_mask = 0x3;
+	u32 offset, alignment_mask = 0x3;
 
 	/* Build the arch_hw_breakpoint. */
 	ret = arch_build_bp_info(bp);
@@ -571,84 +604,85 @@ int arch_validate_hwbkpt_settings(struct
 	/* Check address alignment. */
 	if (info->ctrl.len == ARM_BREAKPOINT_LEN_8)
 		alignment_mask = 0x7;
-	if (info->address & alignment_mask) {
-		/*
-		 * Try to fix the alignment. This may result in a length
-		 * that is too large, so we must check for that.
-		 */
-		bytelen = get_hbp_len(info->ctrl.len);
-		max_len = info->ctrl.type == ARM_BREAKPOINT_EXECUTE ? 4 :
-				max_watchpoint_len;
-
-		if (max_len >= 8)
-			offset = info->address & 0x7;
-		else
-			offset = info->address & 0x3;
-
-		if (bytelen > (1 << ((max_len - (offset + 1)) >> 1))) {
-			ret = -EFBIG;
-			goto out;
-		}
-
-		info->ctrl.len <<= offset;
-		info->address &= ~offset;
-
-		pr_debug("breakpoint alignment fixup: length = 0x%x, "
-			"address = 0x%x\n", info->ctrl.len, info->address);
+	offset = info->address & alignment_mask;
+	switch (offset) {
+	case 0:
+		/* Aligned */
+		break;
+	case 1:
+		/* Allow single byte watchpoint. */
+		if (info->ctrl.len == ARM_BREAKPOINT_LEN_1)
+			break;
+	case 2:
+		/* Allow halfword watchpoints and breakpoints. */
+		if (info->ctrl.len == ARM_BREAKPOINT_LEN_2)
+			break;
+	default:
+		ret = -EINVAL;
+		goto out;
 	}
 
+	info->address &= ~alignment_mask;
+	info->ctrl.len <<= offset;
+
 	/*
 	 * Currently we rely on an overflow handler to take
 	 * care of single-stepping the breakpoint when it fires.
 	 * In the case of userspace breakpoints on a core with V7 debug,
-	 * we can use the mismatch feature as a poor-man's hardware single-step.
+	 * 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_bps()),
+		(arch_check_bp_in_kernelspace(bp) || !core_has_mismatch_brps()
+		 || !bp->hw.bp_target),
 			"overflow handler required but none found")) {
 		ret = -EINVAL;
-		goto out;
 	}
 out:
 	return ret;
 }
 
-static void update_mismatch_flag(int idx, int flag)
+/*
+ * Enable/disable single-stepping over the breakpoint bp at address addr.
+ */
+static void enable_single_step(struct perf_event *bp, u32 addr)
 {
-	struct perf_event *bp = __get_cpu_var(bp_on_reg[idx]);
-	struct arch_hw_breakpoint *info;
-
-	if (bp == NULL)
-		return;
+	struct arch_hw_breakpoint *info = counter_arch_bp(bp);
 
-	info = counter_arch_bp(bp);
+	arch_uninstall_hw_breakpoint(bp);
+	info->step_ctrl.mismatch  = 1;
+	info->step_ctrl.len	  = ARM_BREAKPOINT_LEN_4;
+	info->step_ctrl.type	  = ARM_BREAKPOINT_EXECUTE;
+	info->step_ctrl.privilege = info->ctrl.privilege;
+	info->step_ctrl.enabled	  = 1;
+	info->trigger		  = addr;
+	arch_install_hw_breakpoint(bp);
+}
 
-	/* Update the mismatch field to enter/exit `single-step' mode */
-	if (!bp->overflow_handler && info->ctrl.mismatch != flag) {
-		info->ctrl.mismatch = flag;
-		write_wb_reg(ARM_BASE_BCR + idx, encode_ctrl_reg(info->ctrl) | 0x1);
-	}
+static void disable_single_step(struct perf_event *bp)
+{
+	arch_uninstall_hw_breakpoint(bp);
+	counter_arch_bp(bp)->step_ctrl.enabled = 0;
+	arch_install_hw_breakpoint(bp);
 }
 
 static void watchpoint_handler(unsigned long unknown, struct pt_regs *regs)
 {
 	int i;
-	struct perf_event *bp, **slots = __get_cpu_var(wp_on_reg);
+	struct perf_event *wp, **slots;
 	struct arch_hw_breakpoint *info;
-	struct perf_event_attr attr;
+
+	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);
 
-	hw_breakpoint_init(&attr);
-	attr.bp_addr	= regs->ARM_pc & ~0x3;
-	attr.bp_len	= HW_BREAKPOINT_LEN_4;
-	attr.bp_type	= HW_BREAKPOINT_X;
-
 	for (i = 0; i < core_num_wrps; ++i) {
 		rcu_read_lock();
 
-		if (slots[i] == NULL) {
+		wp = slots[i];
+
+		if (wp == NULL) {
 			rcu_read_unlock();
 			continue;
 		}
@@ -658,24 +692,51 @@ static void watchpoint_handler(unsigned
 		 * single watchpoint, we can set the trigger to the lowest
 		 * possible faulting address.
 		 */
-		info = counter_arch_bp(slots[i]);
-		info->trigger = slots[i]->attr.bp_addr;
+		info = counter_arch_bp(wp);
+		info->trigger = wp->attr.bp_addr;
 		pr_debug("watchpoint fired: address = 0x%x\n", info->trigger);
-		perf_bp_event(slots[i], regs);
+		perf_bp_event(wp, regs);
 
 		/*
 		 * If no overflow handler is present, insert a temporary
 		 * mismatch breakpoint so we can single-step over the
 		 * watchpoint trigger.
 		 */
-		if (!slots[i]->overflow_handler) {
-			bp = register_user_hw_breakpoint(&attr,
-							 wp_single_step_handler,
-							 current);
-			counter_arch_bp(bp)->suspended_wp = slots[i];
-			perf_event_disable(slots[i]);
-		}
+		if (!wp->overflow_handler)
+			enable_single_step(wp, instruction_pointer(regs));
+
+		rcu_read_unlock();
+	}
+}
+
+static void watchpoint_single_step_handler(unsigned long pc)
+{
+	int i;
+	struct perf_event *wp, **slots;
+	struct arch_hw_breakpoint *info;
+
+	slots = (struct perf_event **)__get_cpu_var(wp_on_reg);
+
+	for (i = 0; i < core_num_reserved_brps; ++i) {
+		rcu_read_lock();
+
+		wp = slots[i];
+
+		if (wp == NULL)
+			goto unlock;
+
+		info = counter_arch_bp(wp);
+		if (!info->step_ctrl.enabled)
+			goto unlock;
+
+		/*
+		 * Restore the original watchpoint if we've completed the
+		 * single-step.
+		 */
+		if (info->trigger != pc)
+			disable_single_step(wp);
 
+unlock:
 		rcu_read_unlock();
 	}
 }
@@ -683,62 +744,69 @@ static void watchpoint_handler(unsigned
 static void breakpoint_handler(unsigned long unknown, struct pt_regs *regs)
 {
 	int i;
-	int mismatch;
 	u32 ctrl_reg, val, addr;
-	struct perf_event *bp, **slots = __get_cpu_var(bp_on_reg);
+	struct perf_event *bp, **slots;
 	struct arch_hw_breakpoint *info;
 	struct arch_hw_breakpoint_ctrl ctrl;
 
+	slots = (struct perf_event **)__get_cpu_var(bp_on_reg);
+
 	/* The exception entry code places the amended lr in the PC. */
 	addr = regs->ARM_pc;
 
+	/* Check the currently installed breakpoints first. */
 	for (i = 0; i < core_num_brps; ++i) {
 		rcu_read_lock();
 
 		bp = slots[i];
 
-		if (bp == NULL) {
-			rcu_read_unlock();
-			continue;
-		}
+		if (bp == NULL)
+			goto unlock;
 
-		mismatch = 0;
+		info = counter_arch_bp(bp);
 
 		/* Check if the breakpoint value matches. */
 		val = read_wb_reg(ARM_BASE_BVR + i);
 		if (val != (addr & ~0x3))
-			goto unlock;
+			goto mismatch;
 
 		/* Possible match, check the byte address select to confirm. */
 		ctrl_reg = read_wb_reg(ARM_BASE_BCR + i);
 		decode_ctrl_reg(ctrl_reg, &ctrl);
 		if ((1 << (addr & 0x3)) & ctrl.len) {
-			mismatch = 1;
-			info = counter_arch_bp(bp);
 			info->trigger = addr;
-		}
-
-unlock:
-		if ((mismatch && !info->ctrl.mismatch) || bp_is_single_step(bp)) {
 			pr_debug("breakpoint fired: address = 0x%x\n", addr);
 			perf_bp_event(bp, regs);
+			if (!bp->overflow_handler)
+				enable_single_step(bp, addr);
+			goto unlock;
 		}
 
-		update_mismatch_flag(i, mismatch);
+mismatch:
+		/* If we're stepping a breakpoint, it can now be restored. */
+		if (info->step_ctrl.enabled)
+			disable_single_step(bp);
+unlock:
 		rcu_read_unlock();
 	}
+
+	/* Handle any pending watchpoint single-step breakpoints. */
+	watchpoint_single_step_handler(addr);
 }
 
 /*
  * Called from either the Data Abort Handler [watchpoint] or the
- * Prefetch Abort Handler [breakpoint].
+ * Prefetch Abort Handler [breakpoint] with preemption disabled.
  */
 static int hw_breakpoint_pending(unsigned long addr, unsigned int fsr,
 				 struct pt_regs *regs)
 {
-	int ret = 1; /* Unhandled fault. */
+	int ret = 0;
 	u32 dscr;
 
+	/* We must be called with preemption disabled. */
+	WARN_ON(preemptible());
+
 	/* We only handle watchpoints and hardware breakpoints. */
 	ARM_DBG_READ(c1, 0, dscr);
 
@@ -753,25 +821,60 @@ static int hw_breakpoint_pending(unsigne
 		watchpoint_handler(addr, regs);
 		break;
 	default:
-		goto out;
+		ret = 1; /* Unhandled fault. */
 	}
 
-	ret = 0;
-out:
+	/*
+	 * Re-enable preemption after it was disabled in the
+	 * low-level exception handling code.
+	 */
+	preempt_enable();
+
 	return ret;
 }
 
 /*
  * One-time initialisation.
  */
-static void __init reset_ctrl_regs(void *unused)
+static void reset_ctrl_regs(void *info)
 {
-	int i;
+	int i, cpu = smp_processor_id();
+	u32 dbg_power;
+	cpumask_t *cpumask = info;
+
+	/*
+	 * v7 debug contains save and restore registers so that debug state
+	 * can be maintained across low-power modes without leaving the debug
+	 * logic powered up. It is IMPLEMENTATION DEFINED whether we can access
+	 * the debug registers out of reset, so we must unlock the OS Lock
+	 * Access Register to avoid taking undefined instruction exceptions
+	 * later on.
+	 */
+	if (debug_arch >= 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;
+		}
+
+		/*
+		 * 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();
+	}
 
 	if (enable_monitor_mode())
 		return;
 
-	for (i = 0; i < core_num_brps; ++i) {
+	/* We must also reset any reserved registers. */
+	for (i = 0; i < core_num_brps + core_num_reserved_brps; ++i) {
 		write_wb_reg(ARM_BASE_BCR + i, 0UL);
 		write_wb_reg(ARM_BASE_BVR + i, 0UL);
 	}
@@ -782,45 +885,64 @@ static void __init reset_ctrl_regs(void
 	}
 }
 
+static int __cpuinit dbg_reset_notify(struct notifier_block *self,
+				      unsigned long action, void *cpu)
+{
+	if (action == CPU_ONLINE)
+		smp_call_function_single((int)cpu, reset_ctrl_regs, NULL, 1);
+	return NOTIFY_OK;
+}
+
+static struct notifier_block __cpuinitdata dbg_reset_nb = {
+	.notifier_call = dbg_reset_notify,
+};
+
 static int __init arch_hw_breakpoint_init(void)
 {
-	int ret = 0;
 	u32 dscr;
+	cpumask_t cpumask = { CPU_BITS_NONE };
 
 	debug_arch = get_debug_arch();
 
-	if (debug_arch > ARM_DEBUG_ARCH_V7_ECP14) {
+	if (!debug_arch_supported()) {
 		pr_info("debug architecture 0x%x unsupported.\n", debug_arch);
-		ret = -ENODEV;
-		goto out;
+		return 0;
 	}
 
 	/* 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_wrps);
+		core_num_brps + core_num_reserved_brps, core_num_wrps);
 
-	if (core_has_mismatch_bps())
-		pr_info("1 breakpoint reserved for watchpoint single-step.\n");
+	if (core_num_reserved_brps)
+		pr_info("%d breakpoint(s) reserved for watchpoint "
+				"single-step.\n", core_num_reserved_brps);
+
+	/*
+	 * 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)) {
+		core_num_brps = 0;
+		core_num_reserved_brps = 0;
+		core_num_wrps = 0;
+		return 0;
+	}
 
 	ARM_DBG_READ(c1, 0, dscr);
 	if (dscr & ARM_DSCR_HDBGEN) {
+		max_watchpoint_len = 4;
 		pr_warning("halting debug mode enabled. Assuming maximum "
-				"watchpoint size of 4 bytes.");
+			   "watchpoint size of %u bytes.", max_watchpoint_len);
 	} else {
 		/* Work out the maximum supported watchpoint length. */
 		max_watchpoint_len = get_max_wp_len();
 		pr_info("maximum watchpoint size is %u bytes.\n",
 				max_watchpoint_len);
-
-		/*
-		 * Reset the breakpoint resources. We assume that a halting
-		 * debugger will leave the world in a nice state for us.
-		 */
-		smp_call_function(reset_ctrl_regs, NULL, 1);
-		reset_ctrl_regs(NULL);
 	}
 
 	/* Register debug fault handler. */
@@ -829,8 +951,9 @@ static int __init arch_hw_breakpoint_ini
 	hook_ifault_code(2, hw_breakpoint_pending, SIGTRAP, TRAP_HWBKPT,
 			"breakpoint debug exception");
 
-out:
-	return ret;
+	/* Register hotplug notifier. */
+	register_cpu_notifier(&dbg_reset_nb);
+	return 0;
 }
 arch_initcall(arch_hw_breakpoint_init);
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/kernel/irq.c linux-libre-2.6.38-gnu1/arch/arm/kernel/irq.c
--- linux-libre-2.6.37-gnu1/arch/arm/kernel/irq.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/kernel/irq.c	2011-03-14 21:20:32.000000000 -0400
@@ -35,8 +35,10 @@
 #include <linux/list.h>
 #include <linux/kallsyms.h>
 #include <linux/proc_fs.h>
+#include <linux/ftrace.h>
 
 #include <asm/system.h>
+#include <asm/mach/arch.h>
 #include <asm/mach/irq.h>
 #include <asm/mach/time.h>
 
@@ -47,8 +49,6 @@
 #define irq_finish(irq) do { } while (0)
 #endif
 
-unsigned int arch_nr_irqs;
-void (*init_arch_irq)(void) __initdata = NULL;
 unsigned long irq_err_count;
 
 int show_interrupts(struct seq_file *p, void *v)
@@ -57,11 +57,20 @@ int show_interrupts(struct seq_file *p,
 	struct irq_desc *desc;
 	struct irqaction * action;
 	unsigned long flags;
+	int prec, n;
+
+	for (prec = 3, n = 1000; prec < 10 && n <= nr_irqs; prec++)
+		n *= 10;
+
+#ifdef CONFIG_SMP
+	if (prec < 4)
+		prec = 4;
+#endif
 
 	if (i == 0) {
 		char cpuname[12];
 
-		seq_printf(p, "    ");
+		seq_printf(p, "%*s ", prec, "");
 		for_each_present_cpu(cpu) {
 			sprintf(cpuname, "CPU%d", cpu);
 			seq_printf(p, " %10s", cpuname);
@@ -76,10 +85,10 @@ int show_interrupts(struct seq_file *p,
 		if (!action)
 			goto unlock;
 
-		seq_printf(p, "%3d: ", i);
+		seq_printf(p, "%*d: ", prec, i);
 		for_each_present_cpu(cpu)
 			seq_printf(p, "%10u ", kstat_irqs_cpu(i, cpu));
-		seq_printf(p, " %10s", desc->chip->name ? : "-");
+		seq_printf(p, " %10s", desc->irq_data.chip->name ? : "-");
 		seq_printf(p, "  %s", action->name);
 		for (action = action->next; action; action = action->next)
 			seq_printf(p, ", %s", action->name);
@@ -89,13 +98,15 @@ unlock:
 		raw_spin_unlock_irqrestore(&desc->lock, flags);
 	} else if (i == nr_irqs) {
 #ifdef CONFIG_FIQ
-		show_fiq_list(p, v);
+		show_fiq_list(p, prec);
 #endif
 #ifdef CONFIG_SMP
-		show_ipi_list(p);
-		show_local_irqs(p);
+		show_ipi_list(p, prec);
 #endif
-		seq_printf(p, "Err: %10lu\n", irq_err_count);
+#ifdef CONFIG_LOCAL_TIMERS
+		show_local_irqs(p, prec);
+#endif
+		seq_printf(p, "%*s: %10lu\n", prec, "Err", irq_err_count);
 	}
 	return 0;
 }
@@ -105,7 +116,8 @@ unlock:
  * come via this function.  Instead, they should provide their
  * own 'handler'
  */
-asmlinkage void __exception asm_do_IRQ(unsigned int irq, struct pt_regs *regs)
+asmlinkage void __exception_irq_entry
+asm_do_IRQ(unsigned int irq, struct pt_regs *regs)
 {
 	struct pt_regs *old_regs = set_irq_regs(regs);
 
@@ -154,13 +166,13 @@ void set_irq_flags(unsigned int irq, uns
 
 void __init init_IRQ(void)
 {
-	init_arch_irq();
+	machine_desc->init_irq();
 }
 
 #ifdef CONFIG_SPARSE_IRQ
 int __init arch_probe_nr_irqs(void)
 {
-	nr_irqs = arch_nr_irqs ? arch_nr_irqs : NR_IRQS;
+	nr_irqs = machine_desc->nr_irqs ? machine_desc->nr_irqs : NR_IRQS;
 	return nr_irqs;
 }
 #endif
@@ -169,10 +181,11 @@ int __init arch_probe_nr_irqs(void)
 
 static void route_irq(struct irq_desc *desc, unsigned int irq, unsigned int cpu)
 {
-	pr_debug("IRQ%u: moving from cpu%u to cpu%u\n", irq, desc->node, cpu);
+	pr_debug("IRQ%u: moving from cpu%u to cpu%u\n", irq, desc->irq_data.node, cpu);
 
 	raw_spin_lock_irq(&desc->lock);
-	desc->chip->set_affinity(irq, cpumask_of(cpu));
+	desc->irq_data.chip->irq_set_affinity(&desc->irq_data,
+					      cpumask_of(cpu), false);
 	raw_spin_unlock_irq(&desc->lock);
 }
 
@@ -187,16 +200,18 @@ void migrate_irqs(void)
 	struct irq_desc *desc;
 
 	for_each_irq_desc(i, desc) {
-		if (desc->node == cpu) {
-			unsigned int newcpu = cpumask_any_and(desc->affinity,
+		struct irq_data *d = &desc->irq_data;
+
+		if (d->node == cpu) {
+			unsigned int newcpu = cpumask_any_and(d->affinity,
 							      cpu_online_mask);
 			if (newcpu >= nr_cpu_ids) {
 				if (printk_ratelimit())
 					printk(KERN_INFO "IRQ%u no longer affine to CPU%u\n",
 					       i, cpu);
 
-				cpumask_setall(desc->affinity);
-				newcpu = cpumask_any_and(desc->affinity,
+				cpumask_setall(d->affinity);
+				newcpu = cpumask_any_and(d->affinity,
 							 cpu_online_mask);
 			}
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/kernel/iwmmxt.S linux-libre-2.6.38-gnu1/arch/arm/kernel/iwmmxt.S
--- linux-libre-2.6.37-gnu1/arch/arm/kernel/iwmmxt.S	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/kernel/iwmmxt.S	2011-03-14 21:20:32.000000000 -0400
@@ -19,6 +19,14 @@
 #include <asm/thread_info.h>
 #include <asm/asm-offsets.h>
 
+#if defined(CONFIG_CPU_PJ4)
+#define PJ4(code...)		code
+#define XSC(code...)
+#else
+#define PJ4(code...)
+#define XSC(code...)		code
+#endif
+
 #define MMX_WR0		 	(0x00)
 #define MMX_WR1		 	(0x08)
 #define MMX_WR2		 	(0x10)
@@ -58,11 +66,17 @@
 
 ENTRY(iwmmxt_task_enable)
 
-	mrc	p15, 0, r2, c15, c1, 0
-	tst	r2, #0x3			@ CP0 and CP1 accessible?
+	XSC(mrc	p15, 0, r2, c15, c1, 0)
+	PJ4(mrc p15, 0, r2, c1, c0, 2)
+	@ CP0 and CP1 accessible?
+	XSC(tst	r2, #0x3)
+	PJ4(tst	r2, #0xf)
 	movne	pc, lr				@ if so no business here
-	orr	r2, r2, #0x3			@ enable access to CP0 and CP1
-	mcr	p15, 0, r2, c15, c1, 0
+	@ enable access to CP0 and CP1
+	XSC(orr	r2, r2, #0x3)
+	XSC(mcr	p15, 0, r2, c15, c1, 0)
+	PJ4(orr	r2, r2, #0xf)
+	PJ4(mcr	p15, 0, r2, c1, c0, 2)
 
 	ldr	r3, =concan_owner
 	add	r0, r10, #TI_IWMMXT_STATE	@ get task Concan save area
@@ -179,17 +193,26 @@ ENTRY(iwmmxt_task_disable)
 	teqne	r1, r2				@ or specified one?
 	bne	1f				@ no: quit
 
-	mrc	p15, 0, r4, c15, c1, 0
-	orr	r4, r4, #0x3			@ enable access to CP0 and CP1
-	mcr	p15, 0, r4, c15, c1, 0
+	@ enable access to CP0 and CP1
+	XSC(mrc	p15, 0, r4, c15, c1, 0)
+	XSC(orr	r4, r4, #0xf)
+	XSC(mcr	p15, 0, r4, c15, c1, 0)
+	PJ4(mrc p15, 0, r4, c1, c0, 2)
+	PJ4(orr	r4, r4, #0x3)
+	PJ4(mcr	p15, 0, r4, c1, c0, 2)
+
 	mov	r0, #0				@ nothing to load
 	str	r0, [r3]			@ no more current owner
 	mrc	p15, 0, r2, c2, c0, 0
 	mov	r2, r2				@ cpwait
 	bl	concan_save
 
-	bic	r4, r4, #0x3			@ disable access to CP0 and CP1
-	mcr	p15, 0, r4, c15, c1, 0
+	@ disable access to CP0 and CP1
+	XSC(bic	r4, r4, #0x3)
+	XSC(mcr	p15, 0, r4, c15, c1, 0)
+	PJ4(bic	r4, r4, #0xf)
+	PJ4(mcr	p15, 0, r4, c1, c0, 2)
+
 	mrc	p15, 0, r2, c2, c0, 0
 	mov	r2, r2				@ cpwait
 
@@ -277,8 +300,11 @@ ENTRY(iwmmxt_task_restore)
  */
 ENTRY(iwmmxt_task_switch)
 
-	mrc	p15, 0, r1, c15, c1, 0
-	tst	r1, #0x3			@ CP0 and CP1 accessible?
+	XSC(mrc	p15, 0, r1, c15, c1, 0)
+	PJ4(mrc	p15, 0, r1, c1, c0, 2)
+	@ CP0 and CP1 accessible?
+	XSC(tst	r1, #0x3)
+	PJ4(tst	r1, #0xf)
 	bne	1f				@ yes: block them for next task
 
 	ldr	r2, =concan_owner
@@ -287,8 +313,11 @@ ENTRY(iwmmxt_task_switch)
 	teq	r2, r3				@ next task owns it?
 	movne	pc, lr				@ no: leave Concan disabled
 
-1:	eor	r1, r1, #3			@ flip Concan access
-	mcr	p15, 0, r1, c15, c1, 0
+1:	@ flip Conan access
+	XSC(eor	r1, r1, #0x3)
+	XSC(mcr	p15, 0, r1, c15, c1, 0)
+	PJ4(eor r1, r1, #0xf)
+	PJ4(mcr	p15, 0, r1, c1, c0, 2)
 
 	mrc	p15, 0, r1, c2, c0, 0
 	sub	pc, lr, r1, lsr #32		@ cpwait and return
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/kernel/kprobes-decode.c linux-libre-2.6.38-gnu1/arch/arm/kernel/kprobes-decode.c
--- linux-libre-2.6.37-gnu1/arch/arm/kernel/kprobes-decode.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/kernel/kprobes-decode.c	2011-03-14 21:20:32.000000000 -0400
@@ -1437,7 +1437,7 @@ arm_kprobe_decode_insn(kprobe_opcode_t i
 
 		return space_cccc_1100_010x(insn, asi);
 
-	} else if ((insn & 0x0e000000) == 0x0c400000) {
+	} else if ((insn & 0x0e000000) == 0x0c000000) {
 
 		return space_cccc_110x(insn, asi);
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/kernel/machine_kexec.c linux-libre-2.6.38-gnu1/arch/arm/kernel/machine_kexec.c
--- linux-libre-2.6.37-gnu1/arch/arm/kernel/machine_kexec.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/kernel/machine_kexec.c	2011-03-14 21:20:32.000000000 -0400
@@ -23,6 +23,8 @@ extern unsigned long kexec_indirection_p
 extern unsigned long kexec_mach_type;
 extern unsigned long kexec_boot_atags;
 
+static atomic_t waiting_for_crash_ipi;
+
 /*
  * Provide a dummy crash_notes definition while crash dump arrives to arm.
  * This prevents breakage of crash_notes attribute in kernel/ksysfs.c.
@@ -37,9 +39,37 @@ void machine_kexec_cleanup(struct kimage
 {
 }
 
+void machine_crash_nonpanic_core(void *unused)
+{
+	struct pt_regs regs;
+
+	crash_setup_regs(&regs, NULL);
+	printk(KERN_DEBUG "CPU %u will stop doing anything useful since another CPU has crashed\n",
+	       smp_processor_id());
+	crash_save_cpu(&regs, smp_processor_id());
+	flush_cache_all();
+
+	atomic_dec(&waiting_for_crash_ipi);
+	while (1)
+		cpu_relax();
+}
+
 void machine_crash_shutdown(struct pt_regs *regs)
 {
+	unsigned long msecs;
+
 	local_irq_disable();
+
+	atomic_set(&waiting_for_crash_ipi, num_online_cpus() - 1);
+	smp_call_function(machine_crash_nonpanic_core, NULL, false);
+	msecs = 1000; /* Wait at most a second for the other cpus to stop */
+	while ((atomic_read(&waiting_for_crash_ipi) > 0) && msecs) {
+		mdelay(1);
+		msecs--;
+	}
+	if (atomic_read(&waiting_for_crash_ipi) > 0)
+		printk(KERN_WARNING "Non-crashing CPUs did not react to IPI\n");
+
 	crash_save_cpu(regs, smp_processor_id());
 
 	printk(KERN_INFO "Loading crashdump kernel...\n");
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/kernel/Makefile linux-libre-2.6.38-gnu1/arch/arm/kernel/Makefile
--- linux-libre-2.6.37-gnu1/arch/arm/kernel/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/kernel/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
 CPPFLAGS_vmlinux.lds := -DTEXT_OFFSET=$(TEXT_OFFSET)
 AFLAGS_head.o        := -DTEXT_OFFSET=$(TEXT_OFFSET)
 
-ifdef CONFIG_DYNAMIC_FTRACE
+ifdef CONFIG_FUNCTION_TRACER
 CFLAGS_REMOVE_ftrace.o = -pg
 endif
 
@@ -29,10 +29,12 @@ 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_SMP)		+= smp.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
 obj-$(CONFIG_HAVE_ARM_TWD)	+= smp_twd.o
 obj-$(CONFIG_DYNAMIC_FTRACE)	+= ftrace.o
+obj-$(CONFIG_FUNCTION_GRAPH_TRACER)	+= ftrace.o
 obj-$(CONFIG_KEXEC)		+= machine_kexec.o relocate_kernel.o
 obj-$(CONFIG_KPROBES)		+= kprobes.o kprobes-decode.o
 obj-$(CONFIG_ATAGS_PROC)	+= atags.o
@@ -42,6 +44,8 @@ obj-$(CONFIG_KGDB)		+= kgdb.o
 obj-$(CONFIG_ARM_UNWIND)	+= unwind.o
 obj-$(CONFIG_HAVE_TCM)		+= tcm.o
 obj-$(CONFIG_CRASH_DUMP)	+= crash_dump.o
+obj-$(CONFIG_SWP_EMULATE)	+= swp_emulate.o
+CFLAGS_swp_emulate.o		:= -Wa,-march=armv7-a
 obj-$(CONFIG_HAVE_HW_BREAKPOINT)	+= hw_breakpoint.o
 
 obj-$(CONFIG_CRUNCH)		+= crunch.o crunch-bits.o
@@ -50,6 +54,7 @@ AFLAGS_crunch-bits.o		:= -Wa,-mcpu=ep931
 obj-$(CONFIG_CPU_XSCALE)	+= xscale-cp0.o
 obj-$(CONFIG_CPU_XSC3)		+= xscale-cp0.o
 obj-$(CONFIG_CPU_MOHAWK)	+= xscale-cp0.o
+obj-$(CONFIG_CPU_PJ4)		+= pj4-cp0.o
 obj-$(CONFIG_IWMMXT)		+= iwmmxt.o
 obj-$(CONFIG_CPU_HAS_PMU)	+= pmu.o
 obj-$(CONFIG_HW_PERF_EVENTS)	+= perf_event.o
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/kernel/module.c linux-libre-2.6.38-gnu1/arch/arm/kernel/module.c
--- linux-libre-2.6.37-gnu1/arch/arm/kernel/module.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/kernel/module.c	2011-03-14 21:20:32.000000000 -0400
@@ -22,6 +22,7 @@
 
 #include <asm/pgtable.h>
 #include <asm/sections.h>
+#include <asm/smp_plat.h>
 #include <asm/unwind.h>
 
 #ifdef CONFIG_XIP_KERNEL
@@ -38,17 +39,9 @@
 #ifdef CONFIG_MMU
 void *module_alloc(unsigned long size)
 {
-	struct vm_struct *area;
-
-	size = PAGE_ALIGN(size);
-	if (!size)
-		return NULL;
-
-	area = __get_vm_area(size, VM_ALLOC, MODULES_VADDR, MODULES_END);
-	if (!area)
-		return NULL;
-
-	return __vmalloc_area(area, GFP_KERNEL, PAGE_KERNEL_EXEC);
+	return __vmalloc_node_range(size, 1, MODULES_VADDR, MODULES_END,
+				GFP_KERNEL, PAGE_KERNEL_EXEC, -1,
+				__builtin_return_address(0));
 }
 #else /* CONFIG_MMU */
 void *module_alloc(unsigned long size)
@@ -67,35 +60,6 @@ int module_frob_arch_sections(Elf_Ehdr *
 			      char *secstrings,
 			      struct module *mod)
 {
-#ifdef CONFIG_ARM_UNWIND
-	Elf_Shdr *s, *sechdrs_end = sechdrs + hdr->e_shnum;
-	struct arm_unwind_mapping *maps = mod->arch.map;
-
-	for (s = sechdrs; s < sechdrs_end; s++) {
-		char const *secname = secstrings + s->sh_name;
-
-		if (strcmp(".ARM.exidx.init.text", secname) == 0)
-			maps[ARM_SEC_INIT].unw_sec = s;
-		else if (strcmp(".ARM.exidx.devinit.text", secname) == 0)
-			maps[ARM_SEC_DEVINIT].unw_sec = s;
-		else if (strcmp(".ARM.exidx", secname) == 0)
-			maps[ARM_SEC_CORE].unw_sec = s;
-		else if (strcmp(".ARM.exidx.exit.text", secname) == 0)
-			maps[ARM_SEC_EXIT].unw_sec = s;
-		else if (strcmp(".ARM.exidx.devexit.text", secname) == 0)
-			maps[ARM_SEC_DEVEXIT].unw_sec = s;
-		else if (strcmp(".init.text", secname) == 0)
-			maps[ARM_SEC_INIT].sec_text = s;
-		else if (strcmp(".devinit.text", secname) == 0)
-			maps[ARM_SEC_DEVINIT].sec_text = s;
-		else if (strcmp(".text", secname) == 0)
-			maps[ARM_SEC_CORE].sec_text = s;
-		else if (strcmp(".exit.text", secname) == 0)
-			maps[ARM_SEC_EXIT].sec_text = s;
-		else if (strcmp(".devexit.text", secname) == 0)
-			maps[ARM_SEC_DEVEXIT].sec_text = s;
-	}
-#endif
 	return 0;
 }
 
@@ -300,41 +264,88 @@ apply_relocate_add(Elf32_Shdr *sechdrs,
 	return -ENOEXEC;
 }
 
-#ifdef CONFIG_ARM_UNWIND
-static void register_unwind_tables(struct module *mod)
-{
-	int i;
-	for (i = 0; i < ARM_SEC_MAX; ++i) {
-		struct arm_unwind_mapping *map = &mod->arch.map[i];
-		if (map->unw_sec && map->sec_text)
-			map->unwind = unwind_table_add(map->unw_sec->sh_addr,
-						       map->unw_sec->sh_size,
-						       map->sec_text->sh_addr,
-						       map->sec_text->sh_size);
-	}
-}
+struct mod_unwind_map {
+	const Elf_Shdr *unw_sec;
+	const Elf_Shdr *txt_sec;
+};
 
-static void unregister_unwind_tables(struct module *mod)
+static const Elf_Shdr *find_mod_section(const Elf32_Ehdr *hdr,
+	const Elf_Shdr *sechdrs, const char *name)
 {
-	int i = ARM_SEC_MAX;
-	while (--i >= 0)
-		unwind_table_del(mod->arch.map[i].unwind);
+	const Elf_Shdr *s, *se;
+	const char *secstrs = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
+
+	for (s = sechdrs, se = sechdrs + hdr->e_shnum; s < se; s++)
+		if (strcmp(name, secstrs + s->sh_name) == 0)
+			return s;
+
+	return NULL;
 }
-#else
-static inline void register_unwind_tables(struct module *mod) { }
-static inline void unregister_unwind_tables(struct module *mod) { }
-#endif
 
-int
-module_finalize(const Elf32_Ehdr *hdr, const Elf_Shdr *sechdrs,
-		struct module *module)
+extern void fixup_smp(const void *, unsigned long);
+
+int module_finalize(const Elf32_Ehdr *hdr, const Elf_Shdr *sechdrs,
+		    struct module *mod)
 {
-	register_unwind_tables(module);
+	const Elf_Shdr * __maybe_unused s = NULL;
+#ifdef CONFIG_ARM_UNWIND
+	const char *secstrs = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
+	const Elf_Shdr *sechdrs_end = sechdrs + hdr->e_shnum;
+	struct mod_unwind_map maps[ARM_SEC_MAX];
+	int i;
+
+	memset(maps, 0, sizeof(maps));
+
+	for (s = sechdrs; s < sechdrs_end; s++) {
+		const char *secname = secstrs + s->sh_name;
+
+		if (!(s->sh_flags & SHF_ALLOC))
+			continue;
+
+		if (strcmp(".ARM.exidx.init.text", secname) == 0)
+			maps[ARM_SEC_INIT].unw_sec = s;
+		else if (strcmp(".ARM.exidx.devinit.text", secname) == 0)
+			maps[ARM_SEC_DEVINIT].unw_sec = s;
+		else if (strcmp(".ARM.exidx", secname) == 0)
+			maps[ARM_SEC_CORE].unw_sec = s;
+		else if (strcmp(".ARM.exidx.exit.text", secname) == 0)
+			maps[ARM_SEC_EXIT].unw_sec = s;
+		else if (strcmp(".ARM.exidx.devexit.text", secname) == 0)
+			maps[ARM_SEC_DEVEXIT].unw_sec = s;
+		else if (strcmp(".init.text", secname) == 0)
+			maps[ARM_SEC_INIT].txt_sec = s;
+		else if (strcmp(".devinit.text", secname) == 0)
+			maps[ARM_SEC_DEVINIT].txt_sec = s;
+		else if (strcmp(".text", secname) == 0)
+			maps[ARM_SEC_CORE].txt_sec = s;
+		else if (strcmp(".exit.text", secname) == 0)
+			maps[ARM_SEC_EXIT].txt_sec = s;
+		else if (strcmp(".devexit.text", secname) == 0)
+			maps[ARM_SEC_DEVEXIT].txt_sec = s;
+	}
+
+	for (i = 0; i < ARM_SEC_MAX; i++)
+		if (maps[i].unw_sec && maps[i].txt_sec)
+			mod->arch.unwind[i] =
+				unwind_table_add(maps[i].unw_sec->sh_addr,
+					         maps[i].unw_sec->sh_size,
+					         maps[i].txt_sec->sh_addr,
+					         maps[i].txt_sec->sh_size);
+#endif
+	s = find_mod_section(hdr, sechdrs, ".alt.smp.init");
+	if (s && !is_smp())
+		fixup_smp((void *)s->sh_addr, s->sh_size);
 	return 0;
 }
 
 void
 module_arch_cleanup(struct module *mod)
 {
-	unregister_unwind_tables(mod);
+#ifdef CONFIG_ARM_UNWIND
+	int i;
+
+	for (i = 0; i < ARM_SEC_MAX; i++)
+		if (mod->arch.unwind[i])
+			unwind_table_del(mod->arch.unwind[i]);
+#endif
 }
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/kernel/perf_event.c linux-libre-2.6.38-gnu1/arch/arm/kernel/perf_event.c
--- linux-libre-2.6.37-gnu1/arch/arm/kernel/perf_event.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/kernel/perf_event.c	2011-03-14 21:20:32.000000000 -0400
@@ -4,9 +4,7 @@
  * ARM performance counter support.
  *
  * Copyright (C) 2009 picoChip Designs, Ltd., Jamie Iles
- *
- * ARMv7 support: Jean Pihet <jpihet@mvista.com>
- * 2010 (c) MontaVista Software, LLC.
+ * Copyright (C) 2010 ARM Ltd., Will Deacon <will.deacon@arm.com>
  *
  * This code is based on the sparc64 perf event code, which is in turn based
  * on the x86 code. Callchain code is based on the ARM OProfile backtrace
@@ -34,7 +32,7 @@ static struct platform_device *pmu_devic
  * Hardware lock to serialize accesses to PMU registers. Needed for the
  * read/modify/write sequences.
  */
-DEFINE_SPINLOCK(pmu_lock);
+static DEFINE_RAW_SPINLOCK(pmu_lock);
 
 /*
  * ARMv6 supports a maximum of 3 events, starting from index 1. If we add
@@ -67,31 +65,25 @@ struct cpu_hw_events {
 	 */
 	unsigned long		active_mask[BITS_TO_LONGS(ARMPMU_MAX_HWEVENTS)];
 };
-DEFINE_PER_CPU(struct cpu_hw_events, cpu_hw_events);
-
-/* PMU names. */
-static const char *arm_pmu_names[] = {
-	[ARM_PERF_PMU_ID_XSCALE1] = "xscale1",
-	[ARM_PERF_PMU_ID_XSCALE2] = "xscale2",
-	[ARM_PERF_PMU_ID_V6]	  = "v6",
-	[ARM_PERF_PMU_ID_V6MP]	  = "v6mpcore",
-	[ARM_PERF_PMU_ID_CA8]	  = "ARMv7 Cortex-A8",
-	[ARM_PERF_PMU_ID_CA9]	  = "ARMv7 Cortex-A9",
-};
+static DEFINE_PER_CPU(struct cpu_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		(*event_map)(int evt);
-	u64		(*raw_event)(u64);
 	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);
+	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;
 };
@@ -136,10 +128,6 @@ EXPORT_SYMBOL_GPL(perf_num_counters);
 
 #define CACHE_OP_UNSUPPORTED		0xFFFF
 
-static unsigned armpmu_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
-				     [PERF_COUNT_HW_CACHE_OP_MAX]
-				     [PERF_COUNT_HW_CACHE_RESULT_MAX];
-
 static int
 armpmu_map_cache_event(u64 config)
 {
@@ -157,7 +145,7 @@ armpmu_map_cache_event(u64 config)
 	if (cache_result >= PERF_COUNT_HW_CACHE_RESULT_MAX)
 		return -EINVAL;
 
-	ret = (int)armpmu_perf_cache_map[cache_type][cache_op][cache_result];
+	ret = (int)(*armpmu->cache_map)[cache_type][cache_op][cache_result];
 
 	if (ret == CACHE_OP_UNSUPPORTED)
 		return -ENOENT;
@@ -166,6 +154,19 @@ armpmu_map_cache_event(u64 config)
 }
 
 static int
+armpmu_map_event(u64 config)
+{
+	int mapping = (*armpmu->event_map)[config];
+	return mapping == HW_OP_UNSUPPORTED ? -EOPNOTSUPP : mapping;
+}
+
+static int
+armpmu_map_raw_event(u64 config)
+{
+	return (int)(config & armpmu->raw_event_mask);
+}
+
+static int
 armpmu_event_set_period(struct perf_event *event,
 			struct hw_perf_event *hwc,
 			int idx)
@@ -458,11 +459,11 @@ __hw_perf_event_init(struct perf_event *
 
 	/* Decode the generic type into an ARM event identifier. */
 	if (PERF_TYPE_HARDWARE == event->attr.type) {
-		mapping = armpmu->event_map(event->attr.config);
+		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->raw_event(event->attr.config);
+		mapping = armpmu_map_raw_event(event->attr.config);
 	} else {
 		pr_debug("event type %x not supported\n", event->attr.type);
 		return -EOPNOTSUPP;
@@ -603,2366 +604,10 @@ static struct pmu pmu = {
 	.read		= armpmu_read,
 };
 
-/*
- * ARMv6 Performance counter handling code.
- *
- * ARMv6 has 2 configurable performance counters and a single cycle counter.
- * They all share a single reset bit but can be written to zero so we can use
- * that for a reset.
- *
- * The counters can't be individually enabled or disabled so when we remove
- * one event and replace it with another we could get spurious counts from the
- * wrong event. However, we can take advantage of the fact that the
- * performance counters can export events to the event bus, and the event bus
- * itself can be monitored. This requires that we *don't* export the events to
- * the event bus. The procedure for disabling a configurable counter is:
- *	- change the counter to count the ETMEXTOUT[0] signal (0x20). This
- *	  effectively stops the counter from counting.
- *	- disable the counter's interrupt generation (each counter has it's
- *	  own interrupt enable bit).
- * Once stopped, the counter value can be written as 0 to reset.
- *
- * To enable a counter:
- *	- enable the counter's interrupt generation.
- *	- set the new event type.
- *
- * Note: the dedicated cycle counter only counts cycles and can't be
- * enabled/disabled independently of the others. When we want to disable the
- * cycle counter, we have to just disable the interrupt reporting and start
- * ignoring that counter. When re-enabling, we have to reset the value and
- * enable the interrupt.
- */
-
-enum armv6_perf_types {
-	ARMV6_PERFCTR_ICACHE_MISS	    = 0x0,
-	ARMV6_PERFCTR_IBUF_STALL	    = 0x1,
-	ARMV6_PERFCTR_DDEP_STALL	    = 0x2,
-	ARMV6_PERFCTR_ITLB_MISS		    = 0x3,
-	ARMV6_PERFCTR_DTLB_MISS		    = 0x4,
-	ARMV6_PERFCTR_BR_EXEC		    = 0x5,
-	ARMV6_PERFCTR_BR_MISPREDICT	    = 0x6,
-	ARMV6_PERFCTR_INSTR_EXEC	    = 0x7,
-	ARMV6_PERFCTR_DCACHE_HIT	    = 0x9,
-	ARMV6_PERFCTR_DCACHE_ACCESS	    = 0xA,
-	ARMV6_PERFCTR_DCACHE_MISS	    = 0xB,
-	ARMV6_PERFCTR_DCACHE_WBACK	    = 0xC,
-	ARMV6_PERFCTR_SW_PC_CHANGE	    = 0xD,
-	ARMV6_PERFCTR_MAIN_TLB_MISS	    = 0xF,
-	ARMV6_PERFCTR_EXPL_D_ACCESS	    = 0x10,
-	ARMV6_PERFCTR_LSU_FULL_STALL	    = 0x11,
-	ARMV6_PERFCTR_WBUF_DRAINED	    = 0x12,
-	ARMV6_PERFCTR_CPU_CYCLES	    = 0xFF,
-	ARMV6_PERFCTR_NOP		    = 0x20,
-};
-
-enum armv6_counters {
-	ARMV6_CYCLE_COUNTER = 1,
-	ARMV6_COUNTER0,
-	ARMV6_COUNTER1,
-};
-
-/*
- * The hardware events that we support. We do support cache operations but
- * we have harvard caches and no way to combine instruction and data
- * accesses/misses in hardware.
- */
-static const unsigned armv6_perf_map[PERF_COUNT_HW_MAX] = {
-	[PERF_COUNT_HW_CPU_CYCLES]	    = ARMV6_PERFCTR_CPU_CYCLES,
-	[PERF_COUNT_HW_INSTRUCTIONS]	    = ARMV6_PERFCTR_INSTR_EXEC,
-	[PERF_COUNT_HW_CACHE_REFERENCES]    = HW_OP_UNSUPPORTED,
-	[PERF_COUNT_HW_CACHE_MISSES]	    = HW_OP_UNSUPPORTED,
-	[PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = ARMV6_PERFCTR_BR_EXEC,
-	[PERF_COUNT_HW_BRANCH_MISSES]	    = ARMV6_PERFCTR_BR_MISPREDICT,
-	[PERF_COUNT_HW_BUS_CYCLES]	    = HW_OP_UNSUPPORTED,
-};
-
-static const unsigned armv6_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
-					  [PERF_COUNT_HW_CACHE_OP_MAX]
-					  [PERF_COUNT_HW_CACHE_RESULT_MAX] = {
-	[C(L1D)] = {
-		/*
-		 * The performance counters don't differentiate between read
-		 * and write accesses/misses so this isn't strictly correct,
-		 * but it's the best we can do. Writes and reads get
-		 * combined.
-		 */
-		[C(OP_READ)] = {
-			[C(RESULT_ACCESS)]	= ARMV6_PERFCTR_DCACHE_ACCESS,
-			[C(RESULT_MISS)]	= ARMV6_PERFCTR_DCACHE_MISS,
-		},
-		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]	= ARMV6_PERFCTR_DCACHE_ACCESS,
-			[C(RESULT_MISS)]	= ARMV6_PERFCTR_DCACHE_MISS,
-		},
-		[C(OP_PREFETCH)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-	},
-	[C(L1I)] = {
-		[C(OP_READ)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= ARMV6_PERFCTR_ICACHE_MISS,
-		},
-		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= ARMV6_PERFCTR_ICACHE_MISS,
-		},
-		[C(OP_PREFETCH)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-	},
-	[C(LL)] = {
-		[C(OP_READ)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-		[C(OP_PREFETCH)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-	},
-	[C(DTLB)] = {
-		/*
-		 * The ARM performance counters can count micro DTLB misses,
-		 * micro ITLB misses and main TLB misses. There isn't an event
-		 * for TLB misses, so use the micro misses here and if users
-		 * want the main TLB misses they can use a raw counter.
-		 */
-		[C(OP_READ)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= ARMV6_PERFCTR_DTLB_MISS,
-		},
-		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= ARMV6_PERFCTR_DTLB_MISS,
-		},
-		[C(OP_PREFETCH)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-	},
-	[C(ITLB)] = {
-		[C(OP_READ)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= ARMV6_PERFCTR_ITLB_MISS,
-		},
-		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= ARMV6_PERFCTR_ITLB_MISS,
-		},
-		[C(OP_PREFETCH)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-	},
-	[C(BPU)] = {
-		[C(OP_READ)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-		[C(OP_PREFETCH)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-	},
-};
-
-enum armv6mpcore_perf_types {
-	ARMV6MPCORE_PERFCTR_ICACHE_MISS	    = 0x0,
-	ARMV6MPCORE_PERFCTR_IBUF_STALL	    = 0x1,
-	ARMV6MPCORE_PERFCTR_DDEP_STALL	    = 0x2,
-	ARMV6MPCORE_PERFCTR_ITLB_MISS	    = 0x3,
-	ARMV6MPCORE_PERFCTR_DTLB_MISS	    = 0x4,
-	ARMV6MPCORE_PERFCTR_BR_EXEC	    = 0x5,
-	ARMV6MPCORE_PERFCTR_BR_NOTPREDICT   = 0x6,
-	ARMV6MPCORE_PERFCTR_BR_MISPREDICT   = 0x7,
-	ARMV6MPCORE_PERFCTR_INSTR_EXEC	    = 0x8,
-	ARMV6MPCORE_PERFCTR_DCACHE_RDACCESS = 0xA,
-	ARMV6MPCORE_PERFCTR_DCACHE_RDMISS   = 0xB,
-	ARMV6MPCORE_PERFCTR_DCACHE_WRACCESS = 0xC,
-	ARMV6MPCORE_PERFCTR_DCACHE_WRMISS   = 0xD,
-	ARMV6MPCORE_PERFCTR_DCACHE_EVICTION = 0xE,
-	ARMV6MPCORE_PERFCTR_SW_PC_CHANGE    = 0xF,
-	ARMV6MPCORE_PERFCTR_MAIN_TLB_MISS   = 0x10,
-	ARMV6MPCORE_PERFCTR_EXPL_MEM_ACCESS = 0x11,
-	ARMV6MPCORE_PERFCTR_LSU_FULL_STALL  = 0x12,
-	ARMV6MPCORE_PERFCTR_WBUF_DRAINED    = 0x13,
-	ARMV6MPCORE_PERFCTR_CPU_CYCLES	    = 0xFF,
-};
-
-/*
- * The hardware events that we support. We do support cache operations but
- * we have harvard caches and no way to combine instruction and data
- * accesses/misses in hardware.
- */
-static const unsigned armv6mpcore_perf_map[PERF_COUNT_HW_MAX] = {
-	[PERF_COUNT_HW_CPU_CYCLES]	    = ARMV6MPCORE_PERFCTR_CPU_CYCLES,
-	[PERF_COUNT_HW_INSTRUCTIONS]	    = ARMV6MPCORE_PERFCTR_INSTR_EXEC,
-	[PERF_COUNT_HW_CACHE_REFERENCES]    = HW_OP_UNSUPPORTED,
-	[PERF_COUNT_HW_CACHE_MISSES]	    = HW_OP_UNSUPPORTED,
-	[PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = ARMV6MPCORE_PERFCTR_BR_EXEC,
-	[PERF_COUNT_HW_BRANCH_MISSES]	    = ARMV6MPCORE_PERFCTR_BR_MISPREDICT,
-	[PERF_COUNT_HW_BUS_CYCLES]	    = HW_OP_UNSUPPORTED,
-};
-
-static const unsigned armv6mpcore_perf_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)]  =
-				ARMV6MPCORE_PERFCTR_DCACHE_RDACCESS,
-			[C(RESULT_MISS)]    =
-				ARMV6MPCORE_PERFCTR_DCACHE_RDMISS,
-		},
-		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]  =
-				ARMV6MPCORE_PERFCTR_DCACHE_WRACCESS,
-			[C(RESULT_MISS)]    =
-				ARMV6MPCORE_PERFCTR_DCACHE_WRMISS,
-		},
-		[C(OP_PREFETCH)] = {
-			[C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]    = CACHE_OP_UNSUPPORTED,
-		},
-	},
-	[C(L1I)] = {
-		[C(OP_READ)] = {
-			[C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]    = ARMV6MPCORE_PERFCTR_ICACHE_MISS,
-		},
-		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]    = ARMV6MPCORE_PERFCTR_ICACHE_MISS,
-		},
-		[C(OP_PREFETCH)] = {
-			[C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]    = CACHE_OP_UNSUPPORTED,
-		},
-	},
-	[C(LL)] = {
-		[C(OP_READ)] = {
-			[C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]    = CACHE_OP_UNSUPPORTED,
-		},
-		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]    = CACHE_OP_UNSUPPORTED,
-		},
-		[C(OP_PREFETCH)] = {
-			[C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]    = CACHE_OP_UNSUPPORTED,
-		},
-	},
-	[C(DTLB)] = {
-		/*
-		 * The ARM performance counters can count micro DTLB misses,
-		 * micro ITLB misses and main TLB misses. There isn't an event
-		 * for TLB misses, so use the micro misses here and if users
-		 * want the main TLB misses they can use a raw counter.
-		 */
-		[C(OP_READ)] = {
-			[C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]    = ARMV6MPCORE_PERFCTR_DTLB_MISS,
-		},
-		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]    = ARMV6MPCORE_PERFCTR_DTLB_MISS,
-		},
-		[C(OP_PREFETCH)] = {
-			[C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]    = CACHE_OP_UNSUPPORTED,
-		},
-	},
-	[C(ITLB)] = {
-		[C(OP_READ)] = {
-			[C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]    = ARMV6MPCORE_PERFCTR_ITLB_MISS,
-		},
-		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]    = ARMV6MPCORE_PERFCTR_ITLB_MISS,
-		},
-		[C(OP_PREFETCH)] = {
-			[C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]    = CACHE_OP_UNSUPPORTED,
-		},
-	},
-	[C(BPU)] = {
-		[C(OP_READ)] = {
-			[C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]    = CACHE_OP_UNSUPPORTED,
-		},
-		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]    = CACHE_OP_UNSUPPORTED,
-		},
-		[C(OP_PREFETCH)] = {
-			[C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]    = CACHE_OP_UNSUPPORTED,
-		},
-	},
-};
-
-static inline unsigned long
-armv6_pmcr_read(void)
-{
-	u32 val;
-	asm volatile("mrc   p15, 0, %0, c15, c12, 0" : "=r"(val));
-	return val;
-}
-
-static inline void
-armv6_pmcr_write(unsigned long val)
-{
-	asm volatile("mcr   p15, 0, %0, c15, c12, 0" : : "r"(val));
-}
-
-#define ARMV6_PMCR_ENABLE		(1 << 0)
-#define ARMV6_PMCR_CTR01_RESET		(1 << 1)
-#define ARMV6_PMCR_CCOUNT_RESET		(1 << 2)
-#define ARMV6_PMCR_CCOUNT_DIV		(1 << 3)
-#define ARMV6_PMCR_COUNT0_IEN		(1 << 4)
-#define ARMV6_PMCR_COUNT1_IEN		(1 << 5)
-#define ARMV6_PMCR_CCOUNT_IEN		(1 << 6)
-#define ARMV6_PMCR_COUNT0_OVERFLOW	(1 << 8)
-#define ARMV6_PMCR_COUNT1_OVERFLOW	(1 << 9)
-#define ARMV6_PMCR_CCOUNT_OVERFLOW	(1 << 10)
-#define ARMV6_PMCR_EVT_COUNT0_SHIFT	20
-#define ARMV6_PMCR_EVT_COUNT0_MASK	(0xFF << ARMV6_PMCR_EVT_COUNT0_SHIFT)
-#define ARMV6_PMCR_EVT_COUNT1_SHIFT	12
-#define ARMV6_PMCR_EVT_COUNT1_MASK	(0xFF << ARMV6_PMCR_EVT_COUNT1_SHIFT)
-
-#define ARMV6_PMCR_OVERFLOWED_MASK \
-	(ARMV6_PMCR_COUNT0_OVERFLOW | ARMV6_PMCR_COUNT1_OVERFLOW | \
-	 ARMV6_PMCR_CCOUNT_OVERFLOW)
-
-static inline int
-armv6_pmcr_has_overflowed(unsigned long pmcr)
-{
-	return (pmcr & ARMV6_PMCR_OVERFLOWED_MASK);
-}
-
-static inline int
-armv6_pmcr_counter_has_overflowed(unsigned long pmcr,
-				  enum armv6_counters counter)
-{
-	int ret = 0;
-
-	if (ARMV6_CYCLE_COUNTER == counter)
-		ret = pmcr & ARMV6_PMCR_CCOUNT_OVERFLOW;
-	else if (ARMV6_COUNTER0 == counter)
-		ret = pmcr & ARMV6_PMCR_COUNT0_OVERFLOW;
-	else if (ARMV6_COUNTER1 == counter)
-		ret = pmcr & ARMV6_PMCR_COUNT1_OVERFLOW;
-	else
-		WARN_ONCE(1, "invalid counter number (%d)\n", counter);
-
-	return ret;
-}
-
-static inline u32
-armv6pmu_read_counter(int counter)
-{
-	unsigned long value = 0;
-
-	if (ARMV6_CYCLE_COUNTER == counter)
-		asm volatile("mrc   p15, 0, %0, c15, c12, 1" : "=r"(value));
-	else if (ARMV6_COUNTER0 == counter)
-		asm volatile("mrc   p15, 0, %0, c15, c12, 2" : "=r"(value));
-	else if (ARMV6_COUNTER1 == counter)
-		asm volatile("mrc   p15, 0, %0, c15, c12, 3" : "=r"(value));
-	else
-		WARN_ONCE(1, "invalid counter number (%d)\n", counter);
-
-	return value;
-}
-
-static inline void
-armv6pmu_write_counter(int counter,
-		       u32 value)
-{
-	if (ARMV6_CYCLE_COUNTER == counter)
-		asm volatile("mcr   p15, 0, %0, c15, c12, 1" : : "r"(value));
-	else if (ARMV6_COUNTER0 == counter)
-		asm volatile("mcr   p15, 0, %0, c15, c12, 2" : : "r"(value));
-	else if (ARMV6_COUNTER1 == counter)
-		asm volatile("mcr   p15, 0, %0, c15, c12, 3" : : "r"(value));
-	else
-		WARN_ONCE(1, "invalid counter number (%d)\n", counter);
-}
-
-void
-armv6pmu_enable_event(struct hw_perf_event *hwc,
-		      int idx)
-{
-	unsigned long val, mask, evt, flags;
-
-	if (ARMV6_CYCLE_COUNTER == idx) {
-		mask	= 0;
-		evt	= ARMV6_PMCR_CCOUNT_IEN;
-	} else if (ARMV6_COUNTER0 == idx) {
-		mask	= ARMV6_PMCR_EVT_COUNT0_MASK;
-		evt	= (hwc->config_base << ARMV6_PMCR_EVT_COUNT0_SHIFT) |
-			  ARMV6_PMCR_COUNT0_IEN;
-	} else if (ARMV6_COUNTER1 == idx) {
-		mask	= ARMV6_PMCR_EVT_COUNT1_MASK;
-		evt	= (hwc->config_base << ARMV6_PMCR_EVT_COUNT1_SHIFT) |
-			  ARMV6_PMCR_COUNT1_IEN;
-	} else {
-		WARN_ONCE(1, "invalid counter number (%d)\n", idx);
-		return;
-	}
-
-	/*
-	 * Mask out the current event and set the counter to count the event
-	 * that we're interested in.
-	 */
-	spin_lock_irqsave(&pmu_lock, flags);
-	val = armv6_pmcr_read();
-	val &= ~mask;
-	val |= evt;
-	armv6_pmcr_write(val);
-	spin_unlock_irqrestore(&pmu_lock, flags);
-}
-
-static irqreturn_t
-armv6pmu_handle_irq(int irq_num,
-		    void *dev)
-{
-	unsigned long pmcr = armv6_pmcr_read();
-	struct perf_sample_data data;
-	struct cpu_hw_events *cpuc;
-	struct pt_regs *regs;
-	int idx;
-
-	if (!armv6_pmcr_has_overflowed(pmcr))
-		return IRQ_NONE;
-
-	regs = get_irq_regs();
-
-	/*
-	 * The interrupts are cleared by writing the overflow flags back to
-	 * the control register. All of the other bits don't have any effect
-	 * if they are rewritten, so write the whole value back.
-	 */
-	armv6_pmcr_write(pmcr);
-
-	perf_sample_data_init(&data, 0);
-
-	cpuc = &__get_cpu_var(cpu_hw_events);
-	for (idx = 0; idx <= armpmu->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.
-		 */
-		if (!armv6_pmcr_counter_has_overflowed(pmcr, idx))
-			continue;
-
-		hwc = &event->hw;
-		armpmu_event_update(event, hwc, idx);
-		data.period = event->hw.last_period;
-		if (!armpmu_event_set_period(event, hwc, idx))
-			continue;
-
-		if (perf_event_overflow(event, 0, &data, regs))
-			armpmu->disable(hwc, idx);
-	}
-
-	/*
-	 * Handle the pending perf events.
-	 *
-	 * Note: this call *must* be run with interrupts disabled. For
-	 * platforms that can have the PMU interrupts raised as an NMI, this
-	 * will not work.
-	 */
-	irq_work_run();
-
-	return IRQ_HANDLED;
-}
-
-static void
-armv6pmu_start(void)
-{
-	unsigned long flags, val;
-
-	spin_lock_irqsave(&pmu_lock, flags);
-	val = armv6_pmcr_read();
-	val |= ARMV6_PMCR_ENABLE;
-	armv6_pmcr_write(val);
-	spin_unlock_irqrestore(&pmu_lock, flags);
-}
-
-void
-armv6pmu_stop(void)
-{
-	unsigned long flags, val;
-
-	spin_lock_irqsave(&pmu_lock, flags);
-	val = armv6_pmcr_read();
-	val &= ~ARMV6_PMCR_ENABLE;
-	armv6_pmcr_write(val);
-	spin_unlock_irqrestore(&pmu_lock, flags);
-}
-
-static inline int
-armv6pmu_event_map(int config)
-{
-	int mapping = armv6_perf_map[config];
-	if (HW_OP_UNSUPPORTED == mapping)
-		mapping = -EOPNOTSUPP;
-	return mapping;
-}
-
-static inline int
-armv6mpcore_pmu_event_map(int config)
-{
-	int mapping = armv6mpcore_perf_map[config];
-	if (HW_OP_UNSUPPORTED == mapping)
-		mapping = -EOPNOTSUPP;
-	return mapping;
-}
-
-static u64
-armv6pmu_raw_event(u64 config)
-{
-	return config & 0xff;
-}
-
-static int
-armv6pmu_get_event_idx(struct cpu_hw_events *cpuc,
-		       struct hw_perf_event *event)
-{
-	/* Always place a cycle counter into the cycle counter. */
-	if (ARMV6_PERFCTR_CPU_CYCLES == event->config_base) {
-		if (test_and_set_bit(ARMV6_CYCLE_COUNTER, cpuc->used_mask))
-			return -EAGAIN;
-
-		return ARMV6_CYCLE_COUNTER;
-	} else {
-		/*
-		 * For anything other than a cycle counter, try and use
-		 * counter0 and counter1.
-		 */
-		if (!test_and_set_bit(ARMV6_COUNTER1, cpuc->used_mask)) {
-			return ARMV6_COUNTER1;
-		}
-
-		if (!test_and_set_bit(ARMV6_COUNTER0, cpuc->used_mask)) {
-			return ARMV6_COUNTER0;
-		}
-
-		/* The counters are all in use. */
-		return -EAGAIN;
-	}
-}
-
-static void
-armv6pmu_disable_event(struct hw_perf_event *hwc,
-		       int idx)
-{
-	unsigned long val, mask, evt, flags;
-
-	if (ARMV6_CYCLE_COUNTER == idx) {
-		mask	= ARMV6_PMCR_CCOUNT_IEN;
-		evt	= 0;
-	} else if (ARMV6_COUNTER0 == idx) {
-		mask	= ARMV6_PMCR_COUNT0_IEN | ARMV6_PMCR_EVT_COUNT0_MASK;
-		evt	= ARMV6_PERFCTR_NOP << ARMV6_PMCR_EVT_COUNT0_SHIFT;
-	} else if (ARMV6_COUNTER1 == idx) {
-		mask	= ARMV6_PMCR_COUNT1_IEN | ARMV6_PMCR_EVT_COUNT1_MASK;
-		evt	= ARMV6_PERFCTR_NOP << ARMV6_PMCR_EVT_COUNT1_SHIFT;
-	} else {
-		WARN_ONCE(1, "invalid counter number (%d)\n", idx);
-		return;
-	}
-
-	/*
-	 * Mask out the current event and set the counter to count the number
-	 * of ETM bus signal assertion cycles. The external reporting should
-	 * be disabled and so this should never increment.
-	 */
-	spin_lock_irqsave(&pmu_lock, flags);
-	val = armv6_pmcr_read();
-	val &= ~mask;
-	val |= evt;
-	armv6_pmcr_write(val);
-	spin_unlock_irqrestore(&pmu_lock, flags);
-}
-
-static void
-armv6mpcore_pmu_disable_event(struct hw_perf_event *hwc,
-			      int idx)
-{
-	unsigned long val, mask, flags, evt = 0;
-
-	if (ARMV6_CYCLE_COUNTER == idx) {
-		mask	= ARMV6_PMCR_CCOUNT_IEN;
-	} else if (ARMV6_COUNTER0 == idx) {
-		mask	= ARMV6_PMCR_COUNT0_IEN;
-	} else if (ARMV6_COUNTER1 == idx) {
-		mask	= ARMV6_PMCR_COUNT1_IEN;
-	} else {
-		WARN_ONCE(1, "invalid counter number (%d)\n", idx);
-		return;
-	}
-
-	/*
-	 * Unlike UP ARMv6, we don't have a way of stopping the counters. We
-	 * simply disable the interrupt reporting.
-	 */
-	spin_lock_irqsave(&pmu_lock, flags);
-	val = armv6_pmcr_read();
-	val &= ~mask;
-	val |= evt;
-	armv6_pmcr_write(val);
-	spin_unlock_irqrestore(&pmu_lock, flags);
-}
-
-static const struct arm_pmu armv6pmu = {
-	.id			= ARM_PERF_PMU_ID_V6,
-	.handle_irq		= armv6pmu_handle_irq,
-	.enable			= armv6pmu_enable_event,
-	.disable		= armv6pmu_disable_event,
-	.event_map		= armv6pmu_event_map,
-	.raw_event		= armv6pmu_raw_event,
-	.read_counter		= armv6pmu_read_counter,
-	.write_counter		= armv6pmu_write_counter,
-	.get_event_idx		= armv6pmu_get_event_idx,
-	.start			= armv6pmu_start,
-	.stop			= armv6pmu_stop,
-	.num_events		= 3,
-	.max_period		= (1LLU << 32) - 1,
-};
-
-/*
- * ARMv6mpcore is almost identical to single core ARMv6 with the exception
- * that some of the events have different enumerations and that there is no
- * *hack* to stop the programmable counters. To stop the counters we simply
- * 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 = {
-	.id			= ARM_PERF_PMU_ID_V6MP,
-	.handle_irq		= armv6pmu_handle_irq,
-	.enable			= armv6pmu_enable_event,
-	.disable		= armv6mpcore_pmu_disable_event,
-	.event_map		= armv6mpcore_pmu_event_map,
-	.raw_event		= armv6pmu_raw_event,
-	.read_counter		= armv6pmu_read_counter,
-	.write_counter		= armv6pmu_write_counter,
-	.get_event_idx		= armv6pmu_get_event_idx,
-	.start			= armv6pmu_start,
-	.stop			= armv6pmu_stop,
-	.num_events		= 3,
-	.max_period		= (1LLU << 32) - 1,
-};
-
-/*
- * ARMv7 Cortex-A8 and Cortex-A9 Performance Events handling code.
- *
- * Copied from ARMv6 code, with the low level code inspired
- *  by the ARMv7 Oprofile code.
- *
- * Cortex-A8 has up to 4 configurable performance counters and
- *  a single cycle counter.
- * Cortex-A9 has up to 31 configurable performance counters and
- *  a single cycle counter.
- *
- * All counters can be enabled/disabled and IRQ masked separately. The cycle
- *  counter and all 4 performance counters together can be reset separately.
- */
-
-/* Common ARMv7 event types */
-enum armv7_perf_types {
-	ARMV7_PERFCTR_PMNC_SW_INCR		= 0x00,
-	ARMV7_PERFCTR_IFETCH_MISS		= 0x01,
-	ARMV7_PERFCTR_ITLB_MISS			= 0x02,
-	ARMV7_PERFCTR_DCACHE_REFILL		= 0x03,
-	ARMV7_PERFCTR_DCACHE_ACCESS		= 0x04,
-	ARMV7_PERFCTR_DTLB_REFILL		= 0x05,
-	ARMV7_PERFCTR_DREAD			= 0x06,
-	ARMV7_PERFCTR_DWRITE			= 0x07,
-
-	ARMV7_PERFCTR_EXC_TAKEN			= 0x09,
-	ARMV7_PERFCTR_EXC_EXECUTED		= 0x0A,
-	ARMV7_PERFCTR_CID_WRITE			= 0x0B,
-	/* ARMV7_PERFCTR_PC_WRITE is equivalent to HW_BRANCH_INSTRUCTIONS.
-	 * It counts:
-	 *  - all branch instructions,
-	 *  - instructions that explicitly write the PC,
-	 *  - exception generating instructions.
-	 */
-	ARMV7_PERFCTR_PC_WRITE			= 0x0C,
-	ARMV7_PERFCTR_PC_IMM_BRANCH		= 0x0D,
-	ARMV7_PERFCTR_UNALIGNED_ACCESS		= 0x0F,
-	ARMV7_PERFCTR_PC_BRANCH_MIS_PRED	= 0x10,
-	ARMV7_PERFCTR_CLOCK_CYCLES		= 0x11,
-
-	ARMV7_PERFCTR_PC_BRANCH_MIS_USED	= 0x12,
-
-	ARMV7_PERFCTR_CPU_CYCLES		= 0xFF
-};
-
-/* ARMv7 Cortex-A8 specific event types */
-enum armv7_a8_perf_types {
-	ARMV7_PERFCTR_INSTR_EXECUTED		= 0x08,
-
-	ARMV7_PERFCTR_PC_PROC_RETURN		= 0x0E,
-
-	ARMV7_PERFCTR_WRITE_BUFFER_FULL		= 0x40,
-	ARMV7_PERFCTR_L2_STORE_MERGED		= 0x41,
-	ARMV7_PERFCTR_L2_STORE_BUFF		= 0x42,
-	ARMV7_PERFCTR_L2_ACCESS			= 0x43,
-	ARMV7_PERFCTR_L2_CACH_MISS		= 0x44,
-	ARMV7_PERFCTR_AXI_READ_CYCLES		= 0x45,
-	ARMV7_PERFCTR_AXI_WRITE_CYCLES		= 0x46,
-	ARMV7_PERFCTR_MEMORY_REPLAY		= 0x47,
-	ARMV7_PERFCTR_UNALIGNED_ACCESS_REPLAY	= 0x48,
-	ARMV7_PERFCTR_L1_DATA_MISS		= 0x49,
-	ARMV7_PERFCTR_L1_INST_MISS		= 0x4A,
-	ARMV7_PERFCTR_L1_DATA_COLORING		= 0x4B,
-	ARMV7_PERFCTR_L1_NEON_DATA		= 0x4C,
-	ARMV7_PERFCTR_L1_NEON_CACH_DATA		= 0x4D,
-	ARMV7_PERFCTR_L2_NEON			= 0x4E,
-	ARMV7_PERFCTR_L2_NEON_HIT		= 0x4F,
-	ARMV7_PERFCTR_L1_INST			= 0x50,
-	ARMV7_PERFCTR_PC_RETURN_MIS_PRED	= 0x51,
-	ARMV7_PERFCTR_PC_BRANCH_FAILED		= 0x52,
-	ARMV7_PERFCTR_PC_BRANCH_TAKEN		= 0x53,
-	ARMV7_PERFCTR_PC_BRANCH_EXECUTED	= 0x54,
-	ARMV7_PERFCTR_OP_EXECUTED		= 0x55,
-	ARMV7_PERFCTR_CYCLES_INST_STALL		= 0x56,
-	ARMV7_PERFCTR_CYCLES_INST		= 0x57,
-	ARMV7_PERFCTR_CYCLES_NEON_DATA_STALL	= 0x58,
-	ARMV7_PERFCTR_CYCLES_NEON_INST_STALL	= 0x59,
-	ARMV7_PERFCTR_NEON_CYCLES		= 0x5A,
-
-	ARMV7_PERFCTR_PMU0_EVENTS		= 0x70,
-	ARMV7_PERFCTR_PMU1_EVENTS		= 0x71,
-	ARMV7_PERFCTR_PMU_EVENTS		= 0x72,
-};
-
-/* ARMv7 Cortex-A9 specific event types */
-enum armv7_a9_perf_types {
-	ARMV7_PERFCTR_JAVA_HW_BYTECODE_EXEC	= 0x40,
-	ARMV7_PERFCTR_JAVA_SW_BYTECODE_EXEC	= 0x41,
-	ARMV7_PERFCTR_JAZELLE_BRANCH_EXEC	= 0x42,
-
-	ARMV7_PERFCTR_COHERENT_LINE_MISS	= 0x50,
-	ARMV7_PERFCTR_COHERENT_LINE_HIT		= 0x51,
-
-	ARMV7_PERFCTR_ICACHE_DEP_STALL_CYCLES	= 0x60,
-	ARMV7_PERFCTR_DCACHE_DEP_STALL_CYCLES	= 0x61,
-	ARMV7_PERFCTR_TLB_MISS_DEP_STALL_CYCLES	= 0x62,
-	ARMV7_PERFCTR_STREX_EXECUTED_PASSED	= 0x63,
-	ARMV7_PERFCTR_STREX_EXECUTED_FAILED	= 0x64,
-	ARMV7_PERFCTR_DATA_EVICTION		= 0x65,
-	ARMV7_PERFCTR_ISSUE_STAGE_NO_INST	= 0x66,
-	ARMV7_PERFCTR_ISSUE_STAGE_EMPTY		= 0x67,
-	ARMV7_PERFCTR_INST_OUT_OF_RENAME_STAGE	= 0x68,
-
-	ARMV7_PERFCTR_PREDICTABLE_FUNCT_RETURNS	= 0x6E,
-
-	ARMV7_PERFCTR_MAIN_UNIT_EXECUTED_INST	= 0x70,
-	ARMV7_PERFCTR_SECOND_UNIT_EXECUTED_INST	= 0x71,
-	ARMV7_PERFCTR_LD_ST_UNIT_EXECUTED_INST	= 0x72,
-	ARMV7_PERFCTR_FP_EXECUTED_INST		= 0x73,
-	ARMV7_PERFCTR_NEON_EXECUTED_INST	= 0x74,
-
-	ARMV7_PERFCTR_PLD_FULL_DEP_STALL_CYCLES	= 0x80,
-	ARMV7_PERFCTR_DATA_WR_DEP_STALL_CYCLES	= 0x81,
-	ARMV7_PERFCTR_ITLB_MISS_DEP_STALL_CYCLES	= 0x82,
-	ARMV7_PERFCTR_DTLB_MISS_DEP_STALL_CYCLES	= 0x83,
-	ARMV7_PERFCTR_MICRO_ITLB_MISS_DEP_STALL_CYCLES	= 0x84,
-	ARMV7_PERFCTR_MICRO_DTLB_MISS_DEP_STALL_CYCLES 	= 0x85,
-	ARMV7_PERFCTR_DMB_DEP_STALL_CYCLES	= 0x86,
-
-	ARMV7_PERFCTR_INTGR_CLK_ENABLED_CYCLES	= 0x8A,
-	ARMV7_PERFCTR_DATA_ENGINE_CLK_EN_CYCLES	= 0x8B,
-
-	ARMV7_PERFCTR_ISB_INST			= 0x90,
-	ARMV7_PERFCTR_DSB_INST			= 0x91,
-	ARMV7_PERFCTR_DMB_INST			= 0x92,
-	ARMV7_PERFCTR_EXT_INTERRUPTS		= 0x93,
-
-	ARMV7_PERFCTR_PLE_CACHE_LINE_RQST_COMPLETED	= 0xA0,
-	ARMV7_PERFCTR_PLE_CACHE_LINE_RQST_SKIPPED	= 0xA1,
-	ARMV7_PERFCTR_PLE_FIFO_FLUSH		= 0xA2,
-	ARMV7_PERFCTR_PLE_RQST_COMPLETED	= 0xA3,
-	ARMV7_PERFCTR_PLE_FIFO_OVERFLOW		= 0xA4,
-	ARMV7_PERFCTR_PLE_RQST_PROG		= 0xA5
-};
-
-/*
- * Cortex-A8 HW events mapping
- *
- * The hardware events that we support. We do support cache operations but
- * we have harvard caches and no way to combine instruction and data
- * accesses/misses in hardware.
- */
-static const unsigned armv7_a8_perf_map[PERF_COUNT_HW_MAX] = {
-	[PERF_COUNT_HW_CPU_CYCLES]	    = ARMV7_PERFCTR_CPU_CYCLES,
-	[PERF_COUNT_HW_INSTRUCTIONS]	    = ARMV7_PERFCTR_INSTR_EXECUTED,
-	[PERF_COUNT_HW_CACHE_REFERENCES]    = HW_OP_UNSUPPORTED,
-	[PERF_COUNT_HW_CACHE_MISSES]	    = HW_OP_UNSUPPORTED,
-	[PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = ARMV7_PERFCTR_PC_WRITE,
-	[PERF_COUNT_HW_BRANCH_MISSES]	    = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
-	[PERF_COUNT_HW_BUS_CYCLES]	    = ARMV7_PERFCTR_CLOCK_CYCLES,
-};
-
-static const unsigned armv7_a8_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
-					  [PERF_COUNT_HW_CACHE_OP_MAX]
-					  [PERF_COUNT_HW_CACHE_RESULT_MAX] = {
-	[C(L1D)] = {
-		/*
-		 * The performance counters don't differentiate between read
-		 * and write accesses/misses so this isn't strictly correct,
-		 * but it's the best we can do. Writes and reads get
-		 * combined.
-		 */
-		[C(OP_READ)] = {
-			[C(RESULT_ACCESS)]	= ARMV7_PERFCTR_DCACHE_ACCESS,
-			[C(RESULT_MISS)]	= ARMV7_PERFCTR_DCACHE_REFILL,
-		},
-		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]	= ARMV7_PERFCTR_DCACHE_ACCESS,
-			[C(RESULT_MISS)]	= ARMV7_PERFCTR_DCACHE_REFILL,
-		},
-		[C(OP_PREFETCH)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-	},
-	[C(L1I)] = {
-		[C(OP_READ)] = {
-			[C(RESULT_ACCESS)]	= ARMV7_PERFCTR_L1_INST,
-			[C(RESULT_MISS)]	= ARMV7_PERFCTR_L1_INST_MISS,
-		},
-		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]	= ARMV7_PERFCTR_L1_INST,
-			[C(RESULT_MISS)]	= ARMV7_PERFCTR_L1_INST_MISS,
-		},
-		[C(OP_PREFETCH)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-	},
-	[C(LL)] = {
-		[C(OP_READ)] = {
-			[C(RESULT_ACCESS)]	= ARMV7_PERFCTR_L2_ACCESS,
-			[C(RESULT_MISS)]	= ARMV7_PERFCTR_L2_CACH_MISS,
-		},
-		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]	= ARMV7_PERFCTR_L2_ACCESS,
-			[C(RESULT_MISS)]	= ARMV7_PERFCTR_L2_CACH_MISS,
-		},
-		[C(OP_PREFETCH)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-	},
-	[C(DTLB)] = {
-		/*
-		 * Only ITLB misses and DTLB refills are supported.
-		 * If users want the DTLB refills misses a raw counter
-		 * must be used.
-		 */
-		[C(OP_READ)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= ARMV7_PERFCTR_DTLB_REFILL,
-		},
-		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= ARMV7_PERFCTR_DTLB_REFILL,
-		},
-		[C(OP_PREFETCH)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-	},
-	[C(ITLB)] = {
-		[C(OP_READ)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= ARMV7_PERFCTR_ITLB_MISS,
-		},
-		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= ARMV7_PERFCTR_ITLB_MISS,
-		},
-		[C(OP_PREFETCH)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-	},
-	[C(BPU)] = {
-		[C(OP_READ)] = {
-			[C(RESULT_ACCESS)]	= ARMV7_PERFCTR_PC_WRITE,
-			[C(RESULT_MISS)]
-					= ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
-		},
-		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]	= ARMV7_PERFCTR_PC_WRITE,
-			[C(RESULT_MISS)]
-					= ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
-		},
-		[C(OP_PREFETCH)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-	},
-};
-
-/*
- * Cortex-A9 HW events mapping
- */
-static const unsigned armv7_a9_perf_map[PERF_COUNT_HW_MAX] = {
-	[PERF_COUNT_HW_CPU_CYCLES]	    = ARMV7_PERFCTR_CPU_CYCLES,
-	[PERF_COUNT_HW_INSTRUCTIONS]	    =
-					ARMV7_PERFCTR_INST_OUT_OF_RENAME_STAGE,
-	[PERF_COUNT_HW_CACHE_REFERENCES]    = ARMV7_PERFCTR_COHERENT_LINE_HIT,
-	[PERF_COUNT_HW_CACHE_MISSES]	    = ARMV7_PERFCTR_COHERENT_LINE_MISS,
-	[PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = ARMV7_PERFCTR_PC_WRITE,
-	[PERF_COUNT_HW_BRANCH_MISSES]	    = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
-	[PERF_COUNT_HW_BUS_CYCLES]	    = ARMV7_PERFCTR_CLOCK_CYCLES,
-};
-
-static const unsigned armv7_a9_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
-					  [PERF_COUNT_HW_CACHE_OP_MAX]
-					  [PERF_COUNT_HW_CACHE_RESULT_MAX] = {
-	[C(L1D)] = {
-		/*
-		 * The performance counters don't differentiate between read
-		 * and write accesses/misses so this isn't strictly correct,
-		 * but it's the best we can do. Writes and reads get
-		 * combined.
-		 */
-		[C(OP_READ)] = {
-			[C(RESULT_ACCESS)]	= ARMV7_PERFCTR_DCACHE_ACCESS,
-			[C(RESULT_MISS)]	= ARMV7_PERFCTR_DCACHE_REFILL,
-		},
-		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]	= ARMV7_PERFCTR_DCACHE_ACCESS,
-			[C(RESULT_MISS)]	= ARMV7_PERFCTR_DCACHE_REFILL,
-		},
-		[C(OP_PREFETCH)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-	},
-	[C(L1I)] = {
-		[C(OP_READ)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= ARMV7_PERFCTR_IFETCH_MISS,
-		},
-		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= ARMV7_PERFCTR_IFETCH_MISS,
-		},
-		[C(OP_PREFETCH)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-	},
-	[C(LL)] = {
-		[C(OP_READ)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-		[C(OP_PREFETCH)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-	},
-	[C(DTLB)] = {
-		/*
-		 * Only ITLB misses and DTLB refills are supported.
-		 * If users want the DTLB refills misses a raw counter
-		 * must be used.
-		 */
-		[C(OP_READ)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= ARMV7_PERFCTR_DTLB_REFILL,
-		},
-		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= ARMV7_PERFCTR_DTLB_REFILL,
-		},
-		[C(OP_PREFETCH)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-	},
-	[C(ITLB)] = {
-		[C(OP_READ)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= ARMV7_PERFCTR_ITLB_MISS,
-		},
-		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= ARMV7_PERFCTR_ITLB_MISS,
-		},
-		[C(OP_PREFETCH)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-	},
-	[C(BPU)] = {
-		[C(OP_READ)] = {
-			[C(RESULT_ACCESS)]	= ARMV7_PERFCTR_PC_WRITE,
-			[C(RESULT_MISS)]
-					= ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
-		},
-		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]	= ARMV7_PERFCTR_PC_WRITE,
-			[C(RESULT_MISS)]
-					= ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
-		},
-		[C(OP_PREFETCH)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-	},
-};
-
-/*
- * Perf Events counters
- */
-enum armv7_counters {
-	ARMV7_CYCLE_COUNTER 		= 1,	/* Cycle counter */
-	ARMV7_COUNTER0			= 2,	/* First event counter */
-};
-
-/*
- * 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).
- */
-#define	ARMV7_COUNTER_LAST	(ARMV7_COUNTER0 + armpmu->num_events - 1)
-
-/*
- * ARMv7 low level PMNC access
- */
-
-/*
- * Per-CPU PMNC: config reg
- */
-#define ARMV7_PMNC_E		(1 << 0) /* Enable all counters */
-#define ARMV7_PMNC_P		(1 << 1) /* Reset all counters */
-#define ARMV7_PMNC_C		(1 << 2) /* Cycle counter reset */
-#define ARMV7_PMNC_D		(1 << 3) /* CCNT counts every 64th cpu cycle */
-#define ARMV7_PMNC_X		(1 << 4) /* Export to ETM */
-#define ARMV7_PMNC_DP		(1 << 5) /* Disable CCNT if non-invasive debug*/
-#define	ARMV7_PMNC_N_SHIFT	11	 /* Number of counters supported */
-#define	ARMV7_PMNC_N_MASK	0x1f
-#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
- */
-#define	ARMV7_EVTSEL_MASK	0xff		/* Mask for writable bits */
-
-/*
- * SELECT: Counter selection reg
- */
-#define	ARMV7_SELECT_MASK	0x1f		/* Mask for writable bits */
-
-/*
- * FLAG: counters overflow flag status reg
- */
-#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
-
-static inline unsigned long 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)
-{
-	val &= ARMV7_PMNC_MASK;
-	asm volatile("mcr p15, 0, %0, c9, c12, 0" : : "r"(val));
-}
-
-static inline int armv7_pmnc_has_overflowed(unsigned long pmnc)
-{
-	return pmnc & ARMV7_OVERFLOWED_MASK;
-}
-
-static inline int armv7_pmnc_counter_has_overflowed(unsigned long pmnc,
-					enum armv7_counters counter)
-{
-	int ret = 0;
-
-	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
-		pr_err("CPU%u checking wrong counter %d overflow status\n",
-			smp_processor_id(), counter);
-
-	return ret;
-}
-
-static inline int armv7_pmnc_select_counter(unsigned int idx)
-{
-	u32 val;
-
-	if ((idx < ARMV7_COUNTER0) || (idx > ARMV7_COUNTER_LAST)) {
-		pr_err("CPU%u selecting wrong PMNC counter"
-			" %d\n", smp_processor_id(), idx);
-		return -1;
-	}
-
-	val = (idx - ARMV7_EVENT_CNT_TO_CNTx) & ARMV7_SELECT_MASK;
-	asm volatile("mcr p15, 0, %0, c9, c12, 5" : : "r" (val));
-
-	return idx;
-}
-
-static inline u32 armv7pmu_read_counter(int idx)
-{
-	unsigned long 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
-		pr_err("CPU%u reading wrong counter %d\n",
-			smp_processor_id(), idx);
-
-	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
-		pr_err("CPU%u writing wrong counter %d\n",
-			smp_processor_id(), idx);
-}
-
-static inline void armv7_pmnc_write_evtsel(unsigned int idx, u32 val)
-{
-	if (armv7_pmnc_select_counter(idx) == idx) {
-		val &= ARMV7_EVTSEL_MASK;
-		asm volatile("mcr p15, 0, %0, c9, c13, 1" : : "r" (val));
-	}
-}
-
-static inline u32 armv7_pmnc_enable_counter(unsigned int idx)
-{
-	u32 val;
-
-	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 (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));
-
-	return idx;
-}
-
-static inline u32 armv7_pmnc_disable_counter(unsigned int idx)
-{
-	u32 val;
-
-
-	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 (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));
-
-	return idx;
-}
-
-static inline u32 armv7_pmnc_enable_intens(unsigned int idx)
-{
-	u32 val;
-
-	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 (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));
-
-	return idx;
-}
-
-static inline u32 armv7_pmnc_disable_intens(unsigned int idx)
-{
-	u32 val;
-
-	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 (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));
-
-	return idx;
-}
-
-static inline u32 armv7_pmnc_getreset_flags(void)
-{
-	u32 val;
-
-	/* Read */
-	asm volatile("mrc p15, 0, %0, c9, c12, 3" : "=r" (val));
-
-	/* Write to clear flags */
-	val &= ARMV7_FLAG_MASK;
-	asm volatile("mcr p15, 0, %0, c9, c12, 3" : : "r" (val));
-
-	return val;
-}
-
-#ifdef DEBUG
-static void armv7_pmnc_dump_regs(void)
-{
-	u32 val;
-	unsigned int cnt;
-
-	printk(KERN_INFO "PMNC registers dump:\n");
-
-	asm volatile("mrc p15, 0, %0, c9, c12, 0" : "=r" (val));
-	printk(KERN_INFO "PMNC  =0x%08x\n", val);
-
-	asm volatile("mrc p15, 0, %0, c9, c12, 1" : "=r" (val));
-	printk(KERN_INFO "CNTENS=0x%08x\n", val);
-
-	asm volatile("mrc p15, 0, %0, c9, c14, 1" : "=r" (val));
-	printk(KERN_INFO "INTENS=0x%08x\n", val);
-
-	asm volatile("mrc p15, 0, %0, c9, c12, 3" : "=r" (val));
-	printk(KERN_INFO "FLAGS =0x%08x\n", val);
-
-	asm volatile("mrc p15, 0, %0, c9, c12, 5" : "=r" (val));
-	printk(KERN_INFO "SELECT=0x%08x\n", val);
-
-	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++) {
-		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);
-		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);
-	}
-}
-#endif
-
-void armv7pmu_enable_event(struct hw_perf_event *hwc, int idx)
-{
-	unsigned long flags;
-
-	/*
-	 * Enable counter and interrupt, and set the counter to count
-	 * the event that we're interested in.
-	 */
-	spin_lock_irqsave(&pmu_lock, flags);
-
-	/*
-	 * Disable counter
-	 */
-	armv7_pmnc_disable_counter(idx);
-
-	/*
-	 * Set event (if destined for PMNx counters)
-	 * We don't need to set the event if it's a cycle count
-	 */
-	if (idx != ARMV7_CYCLE_COUNTER)
-		armv7_pmnc_write_evtsel(idx, hwc->config_base);
-
-	/*
-	 * Enable interrupt for this counter
-	 */
-	armv7_pmnc_enable_intens(idx);
-
-	/*
-	 * Enable counter
-	 */
-	armv7_pmnc_enable_counter(idx);
-
-	spin_unlock_irqrestore(&pmu_lock, flags);
-}
-
-static void armv7pmu_disable_event(struct hw_perf_event *hwc, int idx)
-{
-	unsigned long flags;
-
-	/*
-	 * Disable counter and interrupt
-	 */
-	spin_lock_irqsave(&pmu_lock, flags);
-
-	/*
-	 * Disable counter
-	 */
-	armv7_pmnc_disable_counter(idx);
-
-	/*
-	 * Disable interrupt for this counter
-	 */
-	armv7_pmnc_disable_intens(idx);
-
-	spin_unlock_irqrestore(&pmu_lock, flags);
-}
-
-static irqreturn_t armv7pmu_handle_irq(int irq_num, void *dev)
-{
-	unsigned long pmnc;
-	struct perf_sample_data data;
-	struct cpu_hw_events *cpuc;
-	struct pt_regs *regs;
-	int idx;
-
-	/*
-	 * Get and reset the IRQ flags
-	 */
-	pmnc = armv7_pmnc_getreset_flags();
-
-	/*
-	 * Did an overflow occur?
-	 */
-	if (!armv7_pmnc_has_overflowed(pmnc))
-		return IRQ_NONE;
-
-	/*
-	 * Handle the counter(s) overflow(s)
-	 */
-	regs = get_irq_regs();
-
-	perf_sample_data_init(&data, 0);
-
-	cpuc = &__get_cpu_var(cpu_hw_events);
-	for (idx = 0; idx <= armpmu->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.
-		 */
-		if (!armv7_pmnc_counter_has_overflowed(pmnc, idx))
-			continue;
-
-		hwc = &event->hw;
-		armpmu_event_update(event, hwc, idx);
-		data.period = event->hw.last_period;
-		if (!armpmu_event_set_period(event, hwc, idx))
-			continue;
-
-		if (perf_event_overflow(event, 0, &data, regs))
-			armpmu->disable(hwc, idx);
-	}
-
-	/*
-	 * Handle the pending perf events.
-	 *
-	 * Note: this call *must* be run with interrupts disabled. For
-	 * platforms that can have the PMU interrupts raised as an NMI, this
-	 * will not work.
-	 */
-	irq_work_run();
-
-	return IRQ_HANDLED;
-}
-
-static void armv7pmu_start(void)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&pmu_lock, flags);
-	/* Enable all counters */
-	armv7_pmnc_write(armv7_pmnc_read() | ARMV7_PMNC_E);
-	spin_unlock_irqrestore(&pmu_lock, flags);
-}
-
-static void armv7pmu_stop(void)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&pmu_lock, flags);
-	/* Disable all counters */
-	armv7_pmnc_write(armv7_pmnc_read() & ~ARMV7_PMNC_E);
-	spin_unlock_irqrestore(&pmu_lock, flags);
-}
-
-static inline int armv7_a8_pmu_event_map(int config)
-{
-	int mapping = armv7_a8_perf_map[config];
-	if (HW_OP_UNSUPPORTED == mapping)
-		mapping = -EOPNOTSUPP;
-	return mapping;
-}
-
-static inline int armv7_a9_pmu_event_map(int config)
-{
-	int mapping = armv7_a9_perf_map[config];
-	if (HW_OP_UNSUPPORTED == mapping)
-		mapping = -EOPNOTSUPP;
-	return mapping;
-}
-
-static u64 armv7pmu_raw_event(u64 config)
-{
-	return config & 0xff;
-}
-
-static int armv7pmu_get_event_idx(struct cpu_hw_events *cpuc,
-				  struct hw_perf_event *event)
-{
-	int idx;
-
-	/* 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))
-			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;
-		}
-
-		/* The counters are all in use. */
-		return -EAGAIN;
-	}
-}
-
-static struct arm_pmu armv7pmu = {
-	.handle_irq		= armv7pmu_handle_irq,
-	.enable			= armv7pmu_enable_event,
-	.disable		= armv7pmu_disable_event,
-	.raw_event		= armv7pmu_raw_event,
-	.read_counter		= armv7pmu_read_counter,
-	.write_counter		= armv7pmu_write_counter,
-	.get_event_idx		= armv7pmu_get_event_idx,
-	.start			= armv7pmu_start,
-	.stop			= armv7pmu_stop,
-	.max_period		= (1LLU << 32) - 1,
-};
-
-static u32 __init armv7_reset_read_pmnc(void)
-{
-	u32 nb_cnt;
-
-	/* Initialize & Reset PMNC: C and P bits */
-	armv7_pmnc_write(ARMV7_PMNC_P | ARMV7_PMNC_C);
-
-	/* Read the nb of CNTx counters supported from PMNC */
-	nb_cnt = (armv7_pmnc_read() >> ARMV7_PMNC_N_SHIFT) & ARMV7_PMNC_N_MASK;
-
-	/* Add the CPU cycles counter and return */
-	return nb_cnt + 1;
-}
-
-/*
- * ARMv5 [xscale] Performance counter handling code.
- *
- * Based on xscale OProfile code.
- *
- * There are two variants of the xscale PMU that we support:
- * 	- xscale1pmu: 2 event counters and a cycle counter
- * 	- xscale2pmu: 4 event counters and a cycle counter
- * The two variants share event definitions, but have different
- * PMU structures.
- */
-
-enum xscale_perf_types {
-	XSCALE_PERFCTR_ICACHE_MISS		= 0x00,
-	XSCALE_PERFCTR_ICACHE_NO_DELIVER	= 0x01,
-	XSCALE_PERFCTR_DATA_STALL		= 0x02,
-	XSCALE_PERFCTR_ITLB_MISS		= 0x03,
-	XSCALE_PERFCTR_DTLB_MISS		= 0x04,
-	XSCALE_PERFCTR_BRANCH			= 0x05,
-	XSCALE_PERFCTR_BRANCH_MISS		= 0x06,
-	XSCALE_PERFCTR_INSTRUCTION		= 0x07,
-	XSCALE_PERFCTR_DCACHE_FULL_STALL	= 0x08,
-	XSCALE_PERFCTR_DCACHE_FULL_STALL_CONTIG	= 0x09,
-	XSCALE_PERFCTR_DCACHE_ACCESS		= 0x0A,
-	XSCALE_PERFCTR_DCACHE_MISS		= 0x0B,
-	XSCALE_PERFCTR_DCACHE_WRITE_BACK	= 0x0C,
-	XSCALE_PERFCTR_PC_CHANGED		= 0x0D,
-	XSCALE_PERFCTR_BCU_REQUEST		= 0x10,
-	XSCALE_PERFCTR_BCU_FULL			= 0x11,
-	XSCALE_PERFCTR_BCU_DRAIN		= 0x12,
-	XSCALE_PERFCTR_BCU_ECC_NO_ELOG		= 0x14,
-	XSCALE_PERFCTR_BCU_1_BIT_ERR		= 0x15,
-	XSCALE_PERFCTR_RMW			= 0x16,
-	/* XSCALE_PERFCTR_CCNT is not hardware defined */
-	XSCALE_PERFCTR_CCNT			= 0xFE,
-	XSCALE_PERFCTR_UNUSED			= 0xFF,
-};
-
-enum xscale_counters {
-	XSCALE_CYCLE_COUNTER	= 1,
-	XSCALE_COUNTER0,
-	XSCALE_COUNTER1,
-	XSCALE_COUNTER2,
-	XSCALE_COUNTER3,
-};
-
-static const unsigned xscale_perf_map[PERF_COUNT_HW_MAX] = {
-	[PERF_COUNT_HW_CPU_CYCLES]	    = XSCALE_PERFCTR_CCNT,
-	[PERF_COUNT_HW_INSTRUCTIONS]	    = XSCALE_PERFCTR_INSTRUCTION,
-	[PERF_COUNT_HW_CACHE_REFERENCES]    = HW_OP_UNSUPPORTED,
-	[PERF_COUNT_HW_CACHE_MISSES]	    = HW_OP_UNSUPPORTED,
-	[PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = XSCALE_PERFCTR_BRANCH,
-	[PERF_COUNT_HW_BRANCH_MISSES]	    = XSCALE_PERFCTR_BRANCH_MISS,
-	[PERF_COUNT_HW_BUS_CYCLES]	    = HW_OP_UNSUPPORTED,
-};
-
-static const unsigned xscale_perf_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)]	= XSCALE_PERFCTR_DCACHE_ACCESS,
-			[C(RESULT_MISS)]	= XSCALE_PERFCTR_DCACHE_MISS,
-		},
-		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]	= XSCALE_PERFCTR_DCACHE_ACCESS,
-			[C(RESULT_MISS)]	= XSCALE_PERFCTR_DCACHE_MISS,
-		},
-		[C(OP_PREFETCH)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-	},
-	[C(L1I)] = {
-		[C(OP_READ)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= XSCALE_PERFCTR_ICACHE_MISS,
-		},
-		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= XSCALE_PERFCTR_ICACHE_MISS,
-		},
-		[C(OP_PREFETCH)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-	},
-	[C(LL)] = {
-		[C(OP_READ)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-		[C(OP_PREFETCH)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-	},
-	[C(DTLB)] = {
-		[C(OP_READ)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= XSCALE_PERFCTR_DTLB_MISS,
-		},
-		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= XSCALE_PERFCTR_DTLB_MISS,
-		},
-		[C(OP_PREFETCH)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-	},
-	[C(ITLB)] = {
-		[C(OP_READ)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= XSCALE_PERFCTR_ITLB_MISS,
-		},
-		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= XSCALE_PERFCTR_ITLB_MISS,
-		},
-		[C(OP_PREFETCH)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-	},
-	[C(BPU)] = {
-		[C(OP_READ)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-		[C(OP_PREFETCH)] = {
-			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
-		},
-	},
-};
-
-#define	XSCALE_PMU_ENABLE	0x001
-#define XSCALE_PMN_RESET	0x002
-#define	XSCALE_CCNT_RESET	0x004
-#define	XSCALE_PMU_RESET	(CCNT_RESET | PMN_RESET)
-#define XSCALE_PMU_CNT64	0x008
-
-static inline int
-xscalepmu_event_map(int config)
-{
-	int mapping = xscale_perf_map[config];
-	if (HW_OP_UNSUPPORTED == mapping)
-		mapping = -EOPNOTSUPP;
-	return mapping;
-}
-
-static u64
-xscalepmu_raw_event(u64 config)
-{
-	return config & 0xff;
-}
-
-#define XSCALE1_OVERFLOWED_MASK	0x700
-#define XSCALE1_CCOUNT_OVERFLOW	0x400
-#define XSCALE1_COUNT0_OVERFLOW	0x100
-#define XSCALE1_COUNT1_OVERFLOW	0x200
-#define XSCALE1_CCOUNT_INT_EN	0x040
-#define XSCALE1_COUNT0_INT_EN	0x010
-#define XSCALE1_COUNT1_INT_EN	0x020
-#define XSCALE1_COUNT0_EVT_SHFT	12
-#define XSCALE1_COUNT0_EVT_MASK	(0xff << XSCALE1_COUNT0_EVT_SHFT)
-#define XSCALE1_COUNT1_EVT_SHFT	20
-#define XSCALE1_COUNT1_EVT_MASK	(0xff << XSCALE1_COUNT1_EVT_SHFT)
-
-static inline u32
-xscale1pmu_read_pmnc(void)
-{
-	u32 val;
-	asm volatile("mrc p14, 0, %0, c0, c0, 0" : "=r" (val));
-	return val;
-}
-
-static inline void
-xscale1pmu_write_pmnc(u32 val)
-{
-	/* upper 4bits and 7, 11 are write-as-0 */
-	val &= 0xffff77f;
-	asm volatile("mcr p14, 0, %0, c0, c0, 0" : : "r" (val));
-}
-
-static inline int
-xscale1_pmnc_counter_has_overflowed(unsigned long pmnc,
-					enum xscale_counters counter)
-{
-	int ret = 0;
-
-	switch (counter) {
-	case XSCALE_CYCLE_COUNTER:
-		ret = pmnc & XSCALE1_CCOUNT_OVERFLOW;
-		break;
-	case XSCALE_COUNTER0:
-		ret = pmnc & XSCALE1_COUNT0_OVERFLOW;
-		break;
-	case XSCALE_COUNTER1:
-		ret = pmnc & XSCALE1_COUNT1_OVERFLOW;
-		break;
-	default:
-		WARN_ONCE(1, "invalid counter number (%d)\n", counter);
-	}
-
-	return ret;
-}
-
-static irqreturn_t
-xscale1pmu_handle_irq(int irq_num, void *dev)
-{
-	unsigned long pmnc;
-	struct perf_sample_data data;
-	struct cpu_hw_events *cpuc;
-	struct pt_regs *regs;
-	int idx;
-
-	/*
-	 * NOTE: there's an A stepping erratum that states if an overflow
-	 *       bit already exists and another occurs, the previous
-	 *       Overflow bit gets cleared. There's no workaround.
-	 *	 Fixed in B stepping or later.
-	 */
-	pmnc = xscale1pmu_read_pmnc();
-
-	/*
-	 * Write the value back to clear the overflow flags. Overflow
-	 * flags remain in pmnc for use below. We also disable the PMU
-	 * while we process the interrupt.
-	 */
-	xscale1pmu_write_pmnc(pmnc & ~XSCALE_PMU_ENABLE);
-
-	if (!(pmnc & XSCALE1_OVERFLOWED_MASK))
-		return IRQ_NONE;
-
-	regs = get_irq_regs();
-
-	perf_sample_data_init(&data, 0);
-
-	cpuc = &__get_cpu_var(cpu_hw_events);
-	for (idx = 0; idx <= armpmu->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;
-
-		hwc = &event->hw;
-		armpmu_event_update(event, hwc, idx);
-		data.period = event->hw.last_period;
-		if (!armpmu_event_set_period(event, hwc, idx))
-			continue;
-
-		if (perf_event_overflow(event, 0, &data, regs))
-			armpmu->disable(hwc, idx);
-	}
-
-	irq_work_run();
-
-	/*
-	 * Re-enable the PMU.
-	 */
-	pmnc = xscale1pmu_read_pmnc() | XSCALE_PMU_ENABLE;
-	xscale1pmu_write_pmnc(pmnc);
-
-	return IRQ_HANDLED;
-}
-
-static void
-xscale1pmu_enable_event(struct hw_perf_event *hwc, int idx)
-{
-	unsigned long val, mask, evt, flags;
-
-	switch (idx) {
-	case XSCALE_CYCLE_COUNTER:
-		mask = 0;
-		evt = XSCALE1_CCOUNT_INT_EN;
-		break;
-	case XSCALE_COUNTER0:
-		mask = XSCALE1_COUNT0_EVT_MASK;
-		evt = (hwc->config_base << XSCALE1_COUNT0_EVT_SHFT) |
-			XSCALE1_COUNT0_INT_EN;
-		break;
-	case XSCALE_COUNTER1:
-		mask = XSCALE1_COUNT1_EVT_MASK;
-		evt = (hwc->config_base << XSCALE1_COUNT1_EVT_SHFT) |
-			XSCALE1_COUNT1_INT_EN;
-		break;
-	default:
-		WARN_ONCE(1, "invalid counter number (%d)\n", idx);
-		return;
-	}
-
-	spin_lock_irqsave(&pmu_lock, flags);
-	val = xscale1pmu_read_pmnc();
-	val &= ~mask;
-	val |= evt;
-	xscale1pmu_write_pmnc(val);
-	spin_unlock_irqrestore(&pmu_lock, flags);
-}
-
-static void
-xscale1pmu_disable_event(struct hw_perf_event *hwc, int idx)
-{
-	unsigned long val, mask, evt, flags;
-
-	switch (idx) {
-	case XSCALE_CYCLE_COUNTER:
-		mask = XSCALE1_CCOUNT_INT_EN;
-		evt = 0;
-		break;
-	case XSCALE_COUNTER0:
-		mask = XSCALE1_COUNT0_INT_EN | XSCALE1_COUNT0_EVT_MASK;
-		evt = XSCALE_PERFCTR_UNUSED << XSCALE1_COUNT0_EVT_SHFT;
-		break;
-	case XSCALE_COUNTER1:
-		mask = XSCALE1_COUNT1_INT_EN | XSCALE1_COUNT1_EVT_MASK;
-		evt = XSCALE_PERFCTR_UNUSED << XSCALE1_COUNT1_EVT_SHFT;
-		break;
-	default:
-		WARN_ONCE(1, "invalid counter number (%d)\n", idx);
-		return;
-	}
-
-	spin_lock_irqsave(&pmu_lock, flags);
-	val = xscale1pmu_read_pmnc();
-	val &= ~mask;
-	val |= evt;
-	xscale1pmu_write_pmnc(val);
-	spin_unlock_irqrestore(&pmu_lock, flags);
-}
-
-static int
-xscale1pmu_get_event_idx(struct cpu_hw_events *cpuc,
-			struct hw_perf_event *event)
-{
-	if (XSCALE_PERFCTR_CCNT == event->config_base) {
-		if (test_and_set_bit(XSCALE_CYCLE_COUNTER, cpuc->used_mask))
-			return -EAGAIN;
-
-		return XSCALE_CYCLE_COUNTER;
-	} else {
-		if (!test_and_set_bit(XSCALE_COUNTER1, cpuc->used_mask)) {
-			return XSCALE_COUNTER1;
-		}
-
-		if (!test_and_set_bit(XSCALE_COUNTER0, cpuc->used_mask)) {
-			return XSCALE_COUNTER0;
-		}
-
-		return -EAGAIN;
-	}
-}
-
-static void
-xscale1pmu_start(void)
-{
-	unsigned long flags, val;
-
-	spin_lock_irqsave(&pmu_lock, flags);
-	val = xscale1pmu_read_pmnc();
-	val |= XSCALE_PMU_ENABLE;
-	xscale1pmu_write_pmnc(val);
-	spin_unlock_irqrestore(&pmu_lock, flags);
-}
-
-static void
-xscale1pmu_stop(void)
-{
-	unsigned long flags, val;
-
-	spin_lock_irqsave(&pmu_lock, flags);
-	val = xscale1pmu_read_pmnc();
-	val &= ~XSCALE_PMU_ENABLE;
-	xscale1pmu_write_pmnc(val);
-	spin_unlock_irqrestore(&pmu_lock, flags);
-}
-
-static inline u32
-xscale1pmu_read_counter(int counter)
-{
-	u32 val = 0;
-
-	switch (counter) {
-	case XSCALE_CYCLE_COUNTER:
-		asm volatile("mrc p14, 0, %0, c1, c0, 0" : "=r" (val));
-		break;
-	case XSCALE_COUNTER0:
-		asm volatile("mrc p14, 0, %0, c2, c0, 0" : "=r" (val));
-		break;
-	case XSCALE_COUNTER1:
-		asm volatile("mrc p14, 0, %0, c3, c0, 0" : "=r" (val));
-		break;
-	}
-
-	return val;
-}
-
-static inline void
-xscale1pmu_write_counter(int counter, u32 val)
-{
-	switch (counter) {
-	case XSCALE_CYCLE_COUNTER:
-		asm volatile("mcr p14, 0, %0, c1, c0, 0" : : "r" (val));
-		break;
-	case XSCALE_COUNTER0:
-		asm volatile("mcr p14, 0, %0, c2, c0, 0" : : "r" (val));
-		break;
-	case XSCALE_COUNTER1:
-		asm volatile("mcr p14, 0, %0, c3, c0, 0" : : "r" (val));
-		break;
-	}
-}
-
-static const struct arm_pmu xscale1pmu = {
-	.id		= ARM_PERF_PMU_ID_XSCALE1,
-	.handle_irq	= xscale1pmu_handle_irq,
-	.enable		= xscale1pmu_enable_event,
-	.disable	= xscale1pmu_disable_event,
-	.event_map	= xscalepmu_event_map,
-	.raw_event	= xscalepmu_raw_event,
-	.read_counter	= xscale1pmu_read_counter,
-	.write_counter	= xscale1pmu_write_counter,
-	.get_event_idx	= xscale1pmu_get_event_idx,
-	.start		= xscale1pmu_start,
-	.stop		= xscale1pmu_stop,
-	.num_events	= 3,
-	.max_period	= (1LLU << 32) - 1,
-};
-
-#define XSCALE2_OVERFLOWED_MASK	0x01f
-#define XSCALE2_CCOUNT_OVERFLOW	0x001
-#define XSCALE2_COUNT0_OVERFLOW	0x002
-#define XSCALE2_COUNT1_OVERFLOW	0x004
-#define XSCALE2_COUNT2_OVERFLOW	0x008
-#define XSCALE2_COUNT3_OVERFLOW	0x010
-#define XSCALE2_CCOUNT_INT_EN	0x001
-#define XSCALE2_COUNT0_INT_EN	0x002
-#define XSCALE2_COUNT1_INT_EN	0x004
-#define XSCALE2_COUNT2_INT_EN	0x008
-#define XSCALE2_COUNT3_INT_EN	0x010
-#define XSCALE2_COUNT0_EVT_SHFT	0
-#define XSCALE2_COUNT0_EVT_MASK	(0xff << XSCALE2_COUNT0_EVT_SHFT)
-#define XSCALE2_COUNT1_EVT_SHFT	8
-#define XSCALE2_COUNT1_EVT_MASK	(0xff << XSCALE2_COUNT1_EVT_SHFT)
-#define XSCALE2_COUNT2_EVT_SHFT	16
-#define XSCALE2_COUNT2_EVT_MASK	(0xff << XSCALE2_COUNT2_EVT_SHFT)
-#define XSCALE2_COUNT3_EVT_SHFT	24
-#define XSCALE2_COUNT3_EVT_MASK	(0xff << XSCALE2_COUNT3_EVT_SHFT)
-
-static inline u32
-xscale2pmu_read_pmnc(void)
-{
-	u32 val;
-	asm volatile("mrc p14, 0, %0, c0, c1, 0" : "=r" (val));
-	/* bits 1-2 and 4-23 are read-unpredictable */
-	return val & 0xff000009;
-}
-
-static inline void
-xscale2pmu_write_pmnc(u32 val)
-{
-	/* bits 4-23 are write-as-0, 24-31 are write ignored */
-	val &= 0xf;
-	asm volatile("mcr p14, 0, %0, c0, c1, 0" : : "r" (val));
-}
-
-static inline u32
-xscale2pmu_read_overflow_flags(void)
-{
-	u32 val;
-	asm volatile("mrc p14, 0, %0, c5, c1, 0" : "=r" (val));
-	return val;
-}
-
-static inline void
-xscale2pmu_write_overflow_flags(u32 val)
-{
-	asm volatile("mcr p14, 0, %0, c5, c1, 0" : : "r" (val));
-}
-
-static inline u32
-xscale2pmu_read_event_select(void)
-{
-	u32 val;
-	asm volatile("mrc p14, 0, %0, c8, c1, 0" : "=r" (val));
-	return val;
-}
-
-static inline void
-xscale2pmu_write_event_select(u32 val)
-{
-	asm volatile("mcr p14, 0, %0, c8, c1, 0" : : "r"(val));
-}
-
-static inline u32
-xscale2pmu_read_int_enable(void)
-{
-	u32 val;
-	asm volatile("mrc p14, 0, %0, c4, c1, 0" : "=r" (val));
-	return val;
-}
-
-static void
-xscale2pmu_write_int_enable(u32 val)
-{
-	asm volatile("mcr p14, 0, %0, c4, c1, 0" : : "r" (val));
-}
-
-static inline int
-xscale2_pmnc_counter_has_overflowed(unsigned long of_flags,
-					enum xscale_counters counter)
-{
-	int ret = 0;
-
-	switch (counter) {
-	case XSCALE_CYCLE_COUNTER:
-		ret = of_flags & XSCALE2_CCOUNT_OVERFLOW;
-		break;
-	case XSCALE_COUNTER0:
-		ret = of_flags & XSCALE2_COUNT0_OVERFLOW;
-		break;
-	case XSCALE_COUNTER1:
-		ret = of_flags & XSCALE2_COUNT1_OVERFLOW;
-		break;
-	case XSCALE_COUNTER2:
-		ret = of_flags & XSCALE2_COUNT2_OVERFLOW;
-		break;
-	case XSCALE_COUNTER3:
-		ret = of_flags & XSCALE2_COUNT3_OVERFLOW;
-		break;
-	default:
-		WARN_ONCE(1, "invalid counter number (%d)\n", counter);
-	}
-
-	return ret;
-}
-
-static irqreturn_t
-xscale2pmu_handle_irq(int irq_num, void *dev)
-{
-	unsigned long pmnc, of_flags;
-	struct perf_sample_data data;
-	struct cpu_hw_events *cpuc;
-	struct pt_regs *regs;
-	int idx;
-
-	/* Disable the PMU. */
-	pmnc = xscale2pmu_read_pmnc();
-	xscale2pmu_write_pmnc(pmnc & ~XSCALE_PMU_ENABLE);
-
-	/* Check the overflow flag register. */
-	of_flags = xscale2pmu_read_overflow_flags();
-	if (!(of_flags & XSCALE2_OVERFLOWED_MASK))
-		return IRQ_NONE;
-
-	/* Clear the overflow bits. */
-	xscale2pmu_write_overflow_flags(of_flags);
-
-	regs = get_irq_regs();
-
-	perf_sample_data_init(&data, 0);
-
-	cpuc = &__get_cpu_var(cpu_hw_events);
-	for (idx = 0; idx <= armpmu->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;
-
-		hwc = &event->hw;
-		armpmu_event_update(event, hwc, idx);
-		data.period = event->hw.last_period;
-		if (!armpmu_event_set_period(event, hwc, idx))
-			continue;
-
-		if (perf_event_overflow(event, 0, &data, regs))
-			armpmu->disable(hwc, idx);
-	}
-
-	irq_work_run();
-
-	/*
-	 * Re-enable the PMU.
-	 */
-	pmnc = xscale2pmu_read_pmnc() | XSCALE_PMU_ENABLE;
-	xscale2pmu_write_pmnc(pmnc);
-
-	return IRQ_HANDLED;
-}
-
-static void
-xscale2pmu_enable_event(struct hw_perf_event *hwc, int idx)
-{
-	unsigned long flags, ien, evtsel;
-
-	ien = xscale2pmu_read_int_enable();
-	evtsel = xscale2pmu_read_event_select();
-
-	switch (idx) {
-	case XSCALE_CYCLE_COUNTER:
-		ien |= XSCALE2_CCOUNT_INT_EN;
-		break;
-	case XSCALE_COUNTER0:
-		ien |= XSCALE2_COUNT0_INT_EN;
-		evtsel &= ~XSCALE2_COUNT0_EVT_MASK;
-		evtsel |= hwc->config_base << XSCALE2_COUNT0_EVT_SHFT;
-		break;
-	case XSCALE_COUNTER1:
-		ien |= XSCALE2_COUNT1_INT_EN;
-		evtsel &= ~XSCALE2_COUNT1_EVT_MASK;
-		evtsel |= hwc->config_base << XSCALE2_COUNT1_EVT_SHFT;
-		break;
-	case XSCALE_COUNTER2:
-		ien |= XSCALE2_COUNT2_INT_EN;
-		evtsel &= ~XSCALE2_COUNT2_EVT_MASK;
-		evtsel |= hwc->config_base << XSCALE2_COUNT2_EVT_SHFT;
-		break;
-	case XSCALE_COUNTER3:
-		ien |= XSCALE2_COUNT3_INT_EN;
-		evtsel &= ~XSCALE2_COUNT3_EVT_MASK;
-		evtsel |= hwc->config_base << XSCALE2_COUNT3_EVT_SHFT;
-		break;
-	default:
-		WARN_ONCE(1, "invalid counter number (%d)\n", idx);
-		return;
-	}
-
-	spin_lock_irqsave(&pmu_lock, flags);
-	xscale2pmu_write_event_select(evtsel);
-	xscale2pmu_write_int_enable(ien);
-	spin_unlock_irqrestore(&pmu_lock, flags);
-}
-
-static void
-xscale2pmu_disable_event(struct hw_perf_event *hwc, int idx)
-{
-	unsigned long flags, ien, evtsel;
-
-	ien = xscale2pmu_read_int_enable();
-	evtsel = xscale2pmu_read_event_select();
-
-	switch (idx) {
-	case XSCALE_CYCLE_COUNTER:
-		ien &= ~XSCALE2_CCOUNT_INT_EN;
-		break;
-	case XSCALE_COUNTER0:
-		ien &= ~XSCALE2_COUNT0_INT_EN;
-		evtsel &= ~XSCALE2_COUNT0_EVT_MASK;
-		evtsel |= XSCALE_PERFCTR_UNUSED << XSCALE2_COUNT0_EVT_SHFT;
-		break;
-	case XSCALE_COUNTER1:
-		ien &= ~XSCALE2_COUNT1_INT_EN;
-		evtsel &= ~XSCALE2_COUNT1_EVT_MASK;
-		evtsel |= XSCALE_PERFCTR_UNUSED << XSCALE2_COUNT1_EVT_SHFT;
-		break;
-	case XSCALE_COUNTER2:
-		ien &= ~XSCALE2_COUNT2_INT_EN;
-		evtsel &= ~XSCALE2_COUNT2_EVT_MASK;
-		evtsel |= XSCALE_PERFCTR_UNUSED << XSCALE2_COUNT2_EVT_SHFT;
-		break;
-	case XSCALE_COUNTER3:
-		ien &= ~XSCALE2_COUNT3_INT_EN;
-		evtsel &= ~XSCALE2_COUNT3_EVT_MASK;
-		evtsel |= XSCALE_PERFCTR_UNUSED << XSCALE2_COUNT3_EVT_SHFT;
-		break;
-	default:
-		WARN_ONCE(1, "invalid counter number (%d)\n", idx);
-		return;
-	}
-
-	spin_lock_irqsave(&pmu_lock, flags);
-	xscale2pmu_write_event_select(evtsel);
-	xscale2pmu_write_int_enable(ien);
-	spin_unlock_irqrestore(&pmu_lock, flags);
-}
-
-static int
-xscale2pmu_get_event_idx(struct cpu_hw_events *cpuc,
-			struct hw_perf_event *event)
-{
-	int idx = xscale1pmu_get_event_idx(cpuc, event);
-	if (idx >= 0)
-		goto out;
-
-	if (!test_and_set_bit(XSCALE_COUNTER3, cpuc->used_mask))
-		idx = XSCALE_COUNTER3;
-	else if (!test_and_set_bit(XSCALE_COUNTER2, cpuc->used_mask))
-		idx = XSCALE_COUNTER2;
-out:
-	return idx;
-}
-
-static void
-xscale2pmu_start(void)
-{
-	unsigned long flags, val;
-
-	spin_lock_irqsave(&pmu_lock, flags);
-	val = xscale2pmu_read_pmnc() & ~XSCALE_PMU_CNT64;
-	val |= XSCALE_PMU_ENABLE;
-	xscale2pmu_write_pmnc(val);
-	spin_unlock_irqrestore(&pmu_lock, flags);
-}
-
-static void
-xscale2pmu_stop(void)
-{
-	unsigned long flags, val;
-
-	spin_lock_irqsave(&pmu_lock, flags);
-	val = xscale2pmu_read_pmnc();
-	val &= ~XSCALE_PMU_ENABLE;
-	xscale2pmu_write_pmnc(val);
-	spin_unlock_irqrestore(&pmu_lock, flags);
-}
-
-static inline u32
-xscale2pmu_read_counter(int counter)
-{
-	u32 val = 0;
-
-	switch (counter) {
-	case XSCALE_CYCLE_COUNTER:
-		asm volatile("mrc p14, 0, %0, c1, c1, 0" : "=r" (val));
-		break;
-	case XSCALE_COUNTER0:
-		asm volatile("mrc p14, 0, %0, c0, c2, 0" : "=r" (val));
-		break;
-	case XSCALE_COUNTER1:
-		asm volatile("mrc p14, 0, %0, c1, c2, 0" : "=r" (val));
-		break;
-	case XSCALE_COUNTER2:
-		asm volatile("mrc p14, 0, %0, c2, c2, 0" : "=r" (val));
-		break;
-	case XSCALE_COUNTER3:
-		asm volatile("mrc p14, 0, %0, c3, c2, 0" : "=r" (val));
-		break;
-	}
-
-	return val;
-}
-
-static inline void
-xscale2pmu_write_counter(int counter, u32 val)
-{
-	switch (counter) {
-	case XSCALE_CYCLE_COUNTER:
-		asm volatile("mcr p14, 0, %0, c1, c1, 0" : : "r" (val));
-		break;
-	case XSCALE_COUNTER0:
-		asm volatile("mcr p14, 0, %0, c0, c2, 0" : : "r" (val));
-		break;
-	case XSCALE_COUNTER1:
-		asm volatile("mcr p14, 0, %0, c1, c2, 0" : : "r" (val));
-		break;
-	case XSCALE_COUNTER2:
-		asm volatile("mcr p14, 0, %0, c2, c2, 0" : : "r" (val));
-		break;
-	case XSCALE_COUNTER3:
-		asm volatile("mcr p14, 0, %0, c3, c2, 0" : : "r" (val));
-		break;
-	}
-}
-
-static const struct arm_pmu xscale2pmu = {
-	.id		= ARM_PERF_PMU_ID_XSCALE2,
-	.handle_irq	= xscale2pmu_handle_irq,
-	.enable		= xscale2pmu_enable_event,
-	.disable	= xscale2pmu_disable_event,
-	.event_map	= xscalepmu_event_map,
-	.raw_event	= xscalepmu_raw_event,
-	.read_counter	= xscale2pmu_read_counter,
-	.write_counter	= xscale2pmu_write_counter,
-	.get_event_idx	= xscale2pmu_get_event_idx,
-	.start		= xscale2pmu_start,
-	.stop		= xscale2pmu_stop,
-	.num_events	= 5,
-	.max_period	= (1LLU << 32) - 1,
-};
+/* Include the PMU-specific implementations. */
+#include "perf_event_xscale.c"
+#include "perf_event_v6.c"
+#include "perf_event_v7.c"
 
 static int __init
 init_hw_perf_events(void)
@@ -2977,37 +622,16 @@ init_hw_perf_events(void)
 		case 0xB360:	/* ARM1136 */
 		case 0xB560:	/* ARM1156 */
 		case 0xB760:	/* ARM1176 */
-			armpmu = &armv6pmu;
-			memcpy(armpmu_perf_cache_map, armv6_perf_cache_map,
-					sizeof(armv6_perf_cache_map));
+			armpmu = armv6pmu_init();
 			break;
 		case 0xB020:	/* ARM11mpcore */
-			armpmu = &armv6mpcore_pmu;
-			memcpy(armpmu_perf_cache_map,
-			       armv6mpcore_perf_cache_map,
-			       sizeof(armv6mpcore_perf_cache_map));
+			armpmu = armv6mpcore_pmu_init();
 			break;
 		case 0xC080:	/* Cortex-A8 */
-			armv7pmu.id = ARM_PERF_PMU_ID_CA8;
-			memcpy(armpmu_perf_cache_map, armv7_a8_perf_cache_map,
-				sizeof(armv7_a8_perf_cache_map));
-			armv7pmu.event_map = armv7_a8_pmu_event_map;
-			armpmu = &armv7pmu;
-
-			/* Reset PMNC and read the nb of CNTx counters
-			    supported */
-			armv7pmu.num_events = armv7_reset_read_pmnc();
+			armpmu = armv7_a8_pmu_init();
 			break;
 		case 0xC090:	/* Cortex-A9 */
-			armv7pmu.id = ARM_PERF_PMU_ID_CA9;
-			memcpy(armpmu_perf_cache_map, armv7_a9_perf_cache_map,
-				sizeof(armv7_a9_perf_cache_map));
-			armv7pmu.event_map = armv7_a9_pmu_event_map;
-			armpmu = &armv7pmu;
-
-			/* Reset PMNC and read the nb of CNTx counters
-			    supported */
-			armv7pmu.num_events = armv7_reset_read_pmnc();
+			armpmu = armv7_a9_pmu_init();
 			break;
 		}
 	/* Intel CPUs [xscale]. */
@@ -3015,30 +639,26 @@ init_hw_perf_events(void)
 		part_number = (cpuid >> 13) & 0x7;
 		switch (part_number) {
 		case 1:
-			armpmu = &xscale1pmu;
-			memcpy(armpmu_perf_cache_map, xscale_perf_cache_map,
-					sizeof(xscale_perf_cache_map));
+			armpmu = xscale1pmu_init();
 			break;
 		case 2:
-			armpmu = &xscale2pmu;
-			memcpy(armpmu_perf_cache_map, xscale_perf_cache_map,
-					sizeof(xscale_perf_cache_map));
+			armpmu = xscale2pmu_init();
 			break;
 		}
 	}
 
 	if (armpmu) {
 		pr_info("enabled with %s PMU driver, %d counters available\n",
-				arm_pmu_names[armpmu->id], armpmu->num_events);
+			armpmu->name, armpmu->num_events);
 	} else {
 		pr_info("no hardware support available\n");
 	}
 
-	perf_pmu_register(&pmu);
+	perf_pmu_register(&pmu, "cpu", PERF_TYPE_RAW);
 
 	return 0;
 }
-arch_initcall(init_hw_perf_events);
+early_initcall(init_hw_perf_events);
 
 /*
  * Callchain handling code.
@@ -3053,17 +673,17 @@ arch_initcall(init_hw_perf_events);
  * This code has been adapted from the ARM OProfile support.
  */
 struct frame_tail {
-	struct frame_tail   *fp;
-	unsigned long	    sp;
-	unsigned long	    lr;
+	struct frame_tail __user *fp;
+	unsigned long sp;
+	unsigned long lr;
 } __attribute__((packed));
 
 /*
  * Get the return address for a single stackframe and return a pointer to the
  * next frame tail.
  */
-static struct frame_tail *
-user_backtrace(struct frame_tail *tail,
+static struct frame_tail __user *
+user_backtrace(struct frame_tail __user *tail,
 	       struct perf_callchain_entry *entry)
 {
 	struct frame_tail buftail;
@@ -3080,7 +700,7 @@ user_backtrace(struct frame_tail *tail,
 	 * Frame pointers should strictly progress back up the stack
 	 * (towards higher addresses).
 	 */
-	if (tail >= buftail.fp)
+	if (tail + 1 >= buftail.fp)
 		return NULL;
 
 	return buftail.fp - 1;
@@ -3089,10 +709,10 @@ user_backtrace(struct frame_tail *tail,
 void
 perf_callchain_user(struct perf_callchain_entry *entry, struct pt_regs *regs)
 {
-	struct frame_tail *tail;
+	struct frame_tail __user *tail;
 
 
-	tail = (struct frame_tail *)regs->ARM_fp - 1;
+	tail = (struct frame_tail __user *)regs->ARM_fp - 1;
 
 	while (tail && !((unsigned long)tail & 0x3))
 		tail = user_backtrace(tail, entry);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/kernel/perf_event_v6.c linux-libre-2.6.38-gnu1/arch/arm/kernel/perf_event_v6.c
--- linux-libre-2.6.37-gnu1/arch/arm/kernel/perf_event_v6.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/kernel/perf_event_v6.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,672 @@
+/*
+ * ARMv6 Performance counter handling code.
+ *
+ * Copyright (C) 2009 picoChip Designs, Ltd., Jamie Iles
+ *
+ * ARMv6 has 2 configurable performance counters and a single cycle counter.
+ * They all share a single reset bit but can be written to zero so we can use
+ * that for a reset.
+ *
+ * The counters can't be individually enabled or disabled so when we remove
+ * one event and replace it with another we could get spurious counts from the
+ * wrong event. However, we can take advantage of the fact that the
+ * performance counters can export events to the event bus, and the event bus
+ * itself can be monitored. This requires that we *don't* export the events to
+ * the event bus. The procedure for disabling a configurable counter is:
+ *	- change the counter to count the ETMEXTOUT[0] signal (0x20). This
+ *	  effectively stops the counter from counting.
+ *	- disable the counter's interrupt generation (each counter has it's
+ *	  own interrupt enable bit).
+ * Once stopped, the counter value can be written as 0 to reset.
+ *
+ * To enable a counter:
+ *	- enable the counter's interrupt generation.
+ *	- set the new event type.
+ *
+ * Note: the dedicated cycle counter only counts cycles and can't be
+ * enabled/disabled independently of the others. When we want to disable the
+ * cycle counter, we have to just disable the interrupt reporting and start
+ * ignoring that counter. When re-enabling, we have to reset the value and
+ * enable the interrupt.
+ */
+
+#ifdef CONFIG_CPU_V6
+enum armv6_perf_types {
+	ARMV6_PERFCTR_ICACHE_MISS	    = 0x0,
+	ARMV6_PERFCTR_IBUF_STALL	    = 0x1,
+	ARMV6_PERFCTR_DDEP_STALL	    = 0x2,
+	ARMV6_PERFCTR_ITLB_MISS		    = 0x3,
+	ARMV6_PERFCTR_DTLB_MISS		    = 0x4,
+	ARMV6_PERFCTR_BR_EXEC		    = 0x5,
+	ARMV6_PERFCTR_BR_MISPREDICT	    = 0x6,
+	ARMV6_PERFCTR_INSTR_EXEC	    = 0x7,
+	ARMV6_PERFCTR_DCACHE_HIT	    = 0x9,
+	ARMV6_PERFCTR_DCACHE_ACCESS	    = 0xA,
+	ARMV6_PERFCTR_DCACHE_MISS	    = 0xB,
+	ARMV6_PERFCTR_DCACHE_WBACK	    = 0xC,
+	ARMV6_PERFCTR_SW_PC_CHANGE	    = 0xD,
+	ARMV6_PERFCTR_MAIN_TLB_MISS	    = 0xF,
+	ARMV6_PERFCTR_EXPL_D_ACCESS	    = 0x10,
+	ARMV6_PERFCTR_LSU_FULL_STALL	    = 0x11,
+	ARMV6_PERFCTR_WBUF_DRAINED	    = 0x12,
+	ARMV6_PERFCTR_CPU_CYCLES	    = 0xFF,
+	ARMV6_PERFCTR_NOP		    = 0x20,
+};
+
+enum armv6_counters {
+	ARMV6_CYCLE_COUNTER = 1,
+	ARMV6_COUNTER0,
+	ARMV6_COUNTER1,
+};
+
+/*
+ * The hardware events that we support. We do support cache operations but
+ * we have harvard caches and no way to combine instruction and data
+ * accesses/misses in hardware.
+ */
+static const unsigned armv6_perf_map[PERF_COUNT_HW_MAX] = {
+	[PERF_COUNT_HW_CPU_CYCLES]	    = ARMV6_PERFCTR_CPU_CYCLES,
+	[PERF_COUNT_HW_INSTRUCTIONS]	    = ARMV6_PERFCTR_INSTR_EXEC,
+	[PERF_COUNT_HW_CACHE_REFERENCES]    = HW_OP_UNSUPPORTED,
+	[PERF_COUNT_HW_CACHE_MISSES]	    = HW_OP_UNSUPPORTED,
+	[PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = ARMV6_PERFCTR_BR_EXEC,
+	[PERF_COUNT_HW_BRANCH_MISSES]	    = ARMV6_PERFCTR_BR_MISPREDICT,
+	[PERF_COUNT_HW_BUS_CYCLES]	    = HW_OP_UNSUPPORTED,
+};
+
+static const unsigned armv6_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
+					  [PERF_COUNT_HW_CACHE_OP_MAX]
+					  [PERF_COUNT_HW_CACHE_RESULT_MAX] = {
+	[C(L1D)] = {
+		/*
+		 * The performance counters don't differentiate between read
+		 * and write accesses/misses so this isn't strictly correct,
+		 * but it's the best we can do. Writes and reads get
+		 * combined.
+		 */
+		[C(OP_READ)] = {
+			[C(RESULT_ACCESS)]	= ARMV6_PERFCTR_DCACHE_ACCESS,
+			[C(RESULT_MISS)]	= ARMV6_PERFCTR_DCACHE_MISS,
+		},
+		[C(OP_WRITE)] = {
+			[C(RESULT_ACCESS)]	= ARMV6_PERFCTR_DCACHE_ACCESS,
+			[C(RESULT_MISS)]	= ARMV6_PERFCTR_DCACHE_MISS,
+		},
+		[C(OP_PREFETCH)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+	},
+	[C(L1I)] = {
+		[C(OP_READ)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= ARMV6_PERFCTR_ICACHE_MISS,
+		},
+		[C(OP_WRITE)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= ARMV6_PERFCTR_ICACHE_MISS,
+		},
+		[C(OP_PREFETCH)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+	},
+	[C(LL)] = {
+		[C(OP_READ)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+		[C(OP_WRITE)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+		[C(OP_PREFETCH)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+	},
+	[C(DTLB)] = {
+		/*
+		 * The ARM performance counters can count micro DTLB misses,
+		 * micro ITLB misses and main TLB misses. There isn't an event
+		 * for TLB misses, so use the micro misses here and if users
+		 * want the main TLB misses they can use a raw counter.
+		 */
+		[C(OP_READ)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= ARMV6_PERFCTR_DTLB_MISS,
+		},
+		[C(OP_WRITE)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= ARMV6_PERFCTR_DTLB_MISS,
+		},
+		[C(OP_PREFETCH)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+	},
+	[C(ITLB)] = {
+		[C(OP_READ)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= ARMV6_PERFCTR_ITLB_MISS,
+		},
+		[C(OP_WRITE)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= ARMV6_PERFCTR_ITLB_MISS,
+		},
+		[C(OP_PREFETCH)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+	},
+	[C(BPU)] = {
+		[C(OP_READ)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+		[C(OP_WRITE)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+		[C(OP_PREFETCH)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+	},
+};
+
+enum armv6mpcore_perf_types {
+	ARMV6MPCORE_PERFCTR_ICACHE_MISS	    = 0x0,
+	ARMV6MPCORE_PERFCTR_IBUF_STALL	    = 0x1,
+	ARMV6MPCORE_PERFCTR_DDEP_STALL	    = 0x2,
+	ARMV6MPCORE_PERFCTR_ITLB_MISS	    = 0x3,
+	ARMV6MPCORE_PERFCTR_DTLB_MISS	    = 0x4,
+	ARMV6MPCORE_PERFCTR_BR_EXEC	    = 0x5,
+	ARMV6MPCORE_PERFCTR_BR_NOTPREDICT   = 0x6,
+	ARMV6MPCORE_PERFCTR_BR_MISPREDICT   = 0x7,
+	ARMV6MPCORE_PERFCTR_INSTR_EXEC	    = 0x8,
+	ARMV6MPCORE_PERFCTR_DCACHE_RDACCESS = 0xA,
+	ARMV6MPCORE_PERFCTR_DCACHE_RDMISS   = 0xB,
+	ARMV6MPCORE_PERFCTR_DCACHE_WRACCESS = 0xC,
+	ARMV6MPCORE_PERFCTR_DCACHE_WRMISS   = 0xD,
+	ARMV6MPCORE_PERFCTR_DCACHE_EVICTION = 0xE,
+	ARMV6MPCORE_PERFCTR_SW_PC_CHANGE    = 0xF,
+	ARMV6MPCORE_PERFCTR_MAIN_TLB_MISS   = 0x10,
+	ARMV6MPCORE_PERFCTR_EXPL_MEM_ACCESS = 0x11,
+	ARMV6MPCORE_PERFCTR_LSU_FULL_STALL  = 0x12,
+	ARMV6MPCORE_PERFCTR_WBUF_DRAINED    = 0x13,
+	ARMV6MPCORE_PERFCTR_CPU_CYCLES	    = 0xFF,
+};
+
+/*
+ * The hardware events that we support. We do support cache operations but
+ * we have harvard caches and no way to combine instruction and data
+ * accesses/misses in hardware.
+ */
+static const unsigned armv6mpcore_perf_map[PERF_COUNT_HW_MAX] = {
+	[PERF_COUNT_HW_CPU_CYCLES]	    = ARMV6MPCORE_PERFCTR_CPU_CYCLES,
+	[PERF_COUNT_HW_INSTRUCTIONS]	    = ARMV6MPCORE_PERFCTR_INSTR_EXEC,
+	[PERF_COUNT_HW_CACHE_REFERENCES]    = HW_OP_UNSUPPORTED,
+	[PERF_COUNT_HW_CACHE_MISSES]	    = HW_OP_UNSUPPORTED,
+	[PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = ARMV6MPCORE_PERFCTR_BR_EXEC,
+	[PERF_COUNT_HW_BRANCH_MISSES]	    = ARMV6MPCORE_PERFCTR_BR_MISPREDICT,
+	[PERF_COUNT_HW_BUS_CYCLES]	    = HW_OP_UNSUPPORTED,
+};
+
+static const unsigned armv6mpcore_perf_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)]  =
+				ARMV6MPCORE_PERFCTR_DCACHE_RDACCESS,
+			[C(RESULT_MISS)]    =
+				ARMV6MPCORE_PERFCTR_DCACHE_RDMISS,
+		},
+		[C(OP_WRITE)] = {
+			[C(RESULT_ACCESS)]  =
+				ARMV6MPCORE_PERFCTR_DCACHE_WRACCESS,
+			[C(RESULT_MISS)]    =
+				ARMV6MPCORE_PERFCTR_DCACHE_WRMISS,
+		},
+		[C(OP_PREFETCH)] = {
+			[C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]    = CACHE_OP_UNSUPPORTED,
+		},
+	},
+	[C(L1I)] = {
+		[C(OP_READ)] = {
+			[C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]    = ARMV6MPCORE_PERFCTR_ICACHE_MISS,
+		},
+		[C(OP_WRITE)] = {
+			[C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]    = ARMV6MPCORE_PERFCTR_ICACHE_MISS,
+		},
+		[C(OP_PREFETCH)] = {
+			[C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]    = CACHE_OP_UNSUPPORTED,
+		},
+	},
+	[C(LL)] = {
+		[C(OP_READ)] = {
+			[C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]    = CACHE_OP_UNSUPPORTED,
+		},
+		[C(OP_WRITE)] = {
+			[C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]    = CACHE_OP_UNSUPPORTED,
+		},
+		[C(OP_PREFETCH)] = {
+			[C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]    = CACHE_OP_UNSUPPORTED,
+		},
+	},
+	[C(DTLB)] = {
+		/*
+		 * The ARM performance counters can count micro DTLB misses,
+		 * micro ITLB misses and main TLB misses. There isn't an event
+		 * for TLB misses, so use the micro misses here and if users
+		 * want the main TLB misses they can use a raw counter.
+		 */
+		[C(OP_READ)] = {
+			[C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]    = ARMV6MPCORE_PERFCTR_DTLB_MISS,
+		},
+		[C(OP_WRITE)] = {
+			[C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]    = ARMV6MPCORE_PERFCTR_DTLB_MISS,
+		},
+		[C(OP_PREFETCH)] = {
+			[C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]    = CACHE_OP_UNSUPPORTED,
+		},
+	},
+	[C(ITLB)] = {
+		[C(OP_READ)] = {
+			[C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]    = ARMV6MPCORE_PERFCTR_ITLB_MISS,
+		},
+		[C(OP_WRITE)] = {
+			[C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]    = ARMV6MPCORE_PERFCTR_ITLB_MISS,
+		},
+		[C(OP_PREFETCH)] = {
+			[C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]    = CACHE_OP_UNSUPPORTED,
+		},
+	},
+	[C(BPU)] = {
+		[C(OP_READ)] = {
+			[C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]    = CACHE_OP_UNSUPPORTED,
+		},
+		[C(OP_WRITE)] = {
+			[C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]    = CACHE_OP_UNSUPPORTED,
+		},
+		[C(OP_PREFETCH)] = {
+			[C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]    = CACHE_OP_UNSUPPORTED,
+		},
+	},
+};
+
+static inline unsigned long
+armv6_pmcr_read(void)
+{
+	u32 val;
+	asm volatile("mrc   p15, 0, %0, c15, c12, 0" : "=r"(val));
+	return val;
+}
+
+static inline void
+armv6_pmcr_write(unsigned long val)
+{
+	asm volatile("mcr   p15, 0, %0, c15, c12, 0" : : "r"(val));
+}
+
+#define ARMV6_PMCR_ENABLE		(1 << 0)
+#define ARMV6_PMCR_CTR01_RESET		(1 << 1)
+#define ARMV6_PMCR_CCOUNT_RESET		(1 << 2)
+#define ARMV6_PMCR_CCOUNT_DIV		(1 << 3)
+#define ARMV6_PMCR_COUNT0_IEN		(1 << 4)
+#define ARMV6_PMCR_COUNT1_IEN		(1 << 5)
+#define ARMV6_PMCR_CCOUNT_IEN		(1 << 6)
+#define ARMV6_PMCR_COUNT0_OVERFLOW	(1 << 8)
+#define ARMV6_PMCR_COUNT1_OVERFLOW	(1 << 9)
+#define ARMV6_PMCR_CCOUNT_OVERFLOW	(1 << 10)
+#define ARMV6_PMCR_EVT_COUNT0_SHIFT	20
+#define ARMV6_PMCR_EVT_COUNT0_MASK	(0xFF << ARMV6_PMCR_EVT_COUNT0_SHIFT)
+#define ARMV6_PMCR_EVT_COUNT1_SHIFT	12
+#define ARMV6_PMCR_EVT_COUNT1_MASK	(0xFF << ARMV6_PMCR_EVT_COUNT1_SHIFT)
+
+#define ARMV6_PMCR_OVERFLOWED_MASK \
+	(ARMV6_PMCR_COUNT0_OVERFLOW | ARMV6_PMCR_COUNT1_OVERFLOW | \
+	 ARMV6_PMCR_CCOUNT_OVERFLOW)
+
+static inline int
+armv6_pmcr_has_overflowed(unsigned long pmcr)
+{
+	return pmcr & ARMV6_PMCR_OVERFLOWED_MASK;
+}
+
+static inline int
+armv6_pmcr_counter_has_overflowed(unsigned long pmcr,
+				  enum armv6_counters counter)
+{
+	int ret = 0;
+
+	if (ARMV6_CYCLE_COUNTER == counter)
+		ret = pmcr & ARMV6_PMCR_CCOUNT_OVERFLOW;
+	else if (ARMV6_COUNTER0 == counter)
+		ret = pmcr & ARMV6_PMCR_COUNT0_OVERFLOW;
+	else if (ARMV6_COUNTER1 == counter)
+		ret = pmcr & ARMV6_PMCR_COUNT1_OVERFLOW;
+	else
+		WARN_ONCE(1, "invalid counter number (%d)\n", counter);
+
+	return ret;
+}
+
+static inline u32
+armv6pmu_read_counter(int counter)
+{
+	unsigned long value = 0;
+
+	if (ARMV6_CYCLE_COUNTER == counter)
+		asm volatile("mrc   p15, 0, %0, c15, c12, 1" : "=r"(value));
+	else if (ARMV6_COUNTER0 == counter)
+		asm volatile("mrc   p15, 0, %0, c15, c12, 2" : "=r"(value));
+	else if (ARMV6_COUNTER1 == counter)
+		asm volatile("mrc   p15, 0, %0, c15, c12, 3" : "=r"(value));
+	else
+		WARN_ONCE(1, "invalid counter number (%d)\n", counter);
+
+	return value;
+}
+
+static inline void
+armv6pmu_write_counter(int counter,
+		       u32 value)
+{
+	if (ARMV6_CYCLE_COUNTER == counter)
+		asm volatile("mcr   p15, 0, %0, c15, c12, 1" : : "r"(value));
+	else if (ARMV6_COUNTER0 == counter)
+		asm volatile("mcr   p15, 0, %0, c15, c12, 2" : : "r"(value));
+	else if (ARMV6_COUNTER1 == counter)
+		asm volatile("mcr   p15, 0, %0, c15, c12, 3" : : "r"(value));
+	else
+		WARN_ONCE(1, "invalid counter number (%d)\n", counter);
+}
+
+static void
+armv6pmu_enable_event(struct hw_perf_event *hwc,
+		      int idx)
+{
+	unsigned long val, mask, evt, flags;
+
+	if (ARMV6_CYCLE_COUNTER == idx) {
+		mask	= 0;
+		evt	= ARMV6_PMCR_CCOUNT_IEN;
+	} else if (ARMV6_COUNTER0 == idx) {
+		mask	= ARMV6_PMCR_EVT_COUNT0_MASK;
+		evt	= (hwc->config_base << ARMV6_PMCR_EVT_COUNT0_SHIFT) |
+			  ARMV6_PMCR_COUNT0_IEN;
+	} else if (ARMV6_COUNTER1 == idx) {
+		mask	= ARMV6_PMCR_EVT_COUNT1_MASK;
+		evt	= (hwc->config_base << ARMV6_PMCR_EVT_COUNT1_SHIFT) |
+			  ARMV6_PMCR_COUNT1_IEN;
+	} else {
+		WARN_ONCE(1, "invalid counter number (%d)\n", idx);
+		return;
+	}
+
+	/*
+	 * 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);
+	val = armv6_pmcr_read();
+	val &= ~mask;
+	val |= evt;
+	armv6_pmcr_write(val);
+	raw_spin_unlock_irqrestore(&pmu_lock, flags);
+}
+
+static irqreturn_t
+armv6pmu_handle_irq(int irq_num,
+		    void *dev)
+{
+	unsigned long pmcr = armv6_pmcr_read();
+	struct perf_sample_data data;
+	struct cpu_hw_events *cpuc;
+	struct pt_regs *regs;
+	int idx;
+
+	if (!armv6_pmcr_has_overflowed(pmcr))
+		return IRQ_NONE;
+
+	regs = get_irq_regs();
+
+	/*
+	 * The interrupts are cleared by writing the overflow flags back to
+	 * the control register. All of the other bits don't have any effect
+	 * if they are rewritten, so write the whole value back.
+	 */
+	armv6_pmcr_write(pmcr);
+
+	perf_sample_data_init(&data, 0);
+
+	cpuc = &__get_cpu_var(cpu_hw_events);
+	for (idx = 0; idx <= armpmu->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.
+		 */
+		if (!armv6_pmcr_counter_has_overflowed(pmcr, idx))
+			continue;
+
+		hwc = &event->hw;
+		armpmu_event_update(event, hwc, idx);
+		data.period = event->hw.last_period;
+		if (!armpmu_event_set_period(event, hwc, idx))
+			continue;
+
+		if (perf_event_overflow(event, 0, &data, regs))
+			armpmu->disable(hwc, idx);
+	}
+
+	/*
+	 * Handle the pending perf events.
+	 *
+	 * Note: this call *must* be run with interrupts disabled. For
+	 * platforms that can have the PMU interrupts raised as an NMI, this
+	 * will not work.
+	 */
+	irq_work_run();
+
+	return IRQ_HANDLED;
+}
+
+static void
+armv6pmu_start(void)
+{
+	unsigned long flags, val;
+
+	raw_spin_lock_irqsave(&pmu_lock, flags);
+	val = armv6_pmcr_read();
+	val |= ARMV6_PMCR_ENABLE;
+	armv6_pmcr_write(val);
+	raw_spin_unlock_irqrestore(&pmu_lock, flags);
+}
+
+static void
+armv6pmu_stop(void)
+{
+	unsigned long flags, val;
+
+	raw_spin_lock_irqsave(&pmu_lock, flags);
+	val = armv6_pmcr_read();
+	val &= ~ARMV6_PMCR_ENABLE;
+	armv6_pmcr_write(val);
+	raw_spin_unlock_irqrestore(&pmu_lock, flags);
+}
+
+static int
+armv6pmu_get_event_idx(struct cpu_hw_events *cpuc,
+		       struct hw_perf_event *event)
+{
+	/* Always place a cycle counter into the cycle counter. */
+	if (ARMV6_PERFCTR_CPU_CYCLES == event->config_base) {
+		if (test_and_set_bit(ARMV6_CYCLE_COUNTER, cpuc->used_mask))
+			return -EAGAIN;
+
+		return ARMV6_CYCLE_COUNTER;
+	} else {
+		/*
+		 * For anything other than a cycle counter, try and use
+		 * counter0 and counter1.
+		 */
+		if (!test_and_set_bit(ARMV6_COUNTER1, cpuc->used_mask))
+			return ARMV6_COUNTER1;
+
+		if (!test_and_set_bit(ARMV6_COUNTER0, cpuc->used_mask))
+			return ARMV6_COUNTER0;
+
+		/* The counters are all in use. */
+		return -EAGAIN;
+	}
+}
+
+static void
+armv6pmu_disable_event(struct hw_perf_event *hwc,
+		       int idx)
+{
+	unsigned long val, mask, evt, flags;
+
+	if (ARMV6_CYCLE_COUNTER == idx) {
+		mask	= ARMV6_PMCR_CCOUNT_IEN;
+		evt	= 0;
+	} else if (ARMV6_COUNTER0 == idx) {
+		mask	= ARMV6_PMCR_COUNT0_IEN | ARMV6_PMCR_EVT_COUNT0_MASK;
+		evt	= ARMV6_PERFCTR_NOP << ARMV6_PMCR_EVT_COUNT0_SHIFT;
+	} else if (ARMV6_COUNTER1 == idx) {
+		mask	= ARMV6_PMCR_COUNT1_IEN | ARMV6_PMCR_EVT_COUNT1_MASK;
+		evt	= ARMV6_PERFCTR_NOP << ARMV6_PMCR_EVT_COUNT1_SHIFT;
+	} else {
+		WARN_ONCE(1, "invalid counter number (%d)\n", idx);
+		return;
+	}
+
+	/*
+	 * Mask out the current event and set the counter to count the number
+	 * 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);
+	val = armv6_pmcr_read();
+	val &= ~mask;
+	val |= evt;
+	armv6_pmcr_write(val);
+	raw_spin_unlock_irqrestore(&pmu_lock, flags);
+}
+
+static void
+armv6mpcore_pmu_disable_event(struct hw_perf_event *hwc,
+			      int idx)
+{
+	unsigned long val, mask, flags, evt = 0;
+
+	if (ARMV6_CYCLE_COUNTER == idx) {
+		mask	= ARMV6_PMCR_CCOUNT_IEN;
+	} else if (ARMV6_COUNTER0 == idx) {
+		mask	= ARMV6_PMCR_COUNT0_IEN;
+	} else if (ARMV6_COUNTER1 == idx) {
+		mask	= ARMV6_PMCR_COUNT1_IEN;
+	} else {
+		WARN_ONCE(1, "invalid counter number (%d)\n", idx);
+		return;
+	}
+
+	/*
+	 * 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);
+	val = armv6_pmcr_read();
+	val &= ~mask;
+	val |= evt;
+	armv6_pmcr_write(val);
+	raw_spin_unlock_irqrestore(&pmu_lock, flags);
+}
+
+static const struct arm_pmu armv6pmu = {
+	.id			= ARM_PERF_PMU_ID_V6,
+	.name			= "v6",
+	.handle_irq		= armv6pmu_handle_irq,
+	.enable			= armv6pmu_enable_event,
+	.disable		= armv6pmu_disable_event,
+	.read_counter		= armv6pmu_read_counter,
+	.write_counter		= armv6pmu_write_counter,
+	.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,
+	.num_events		= 3,
+	.max_period		= (1LLU << 32) - 1,
+};
+
+static const struct arm_pmu *__init armv6pmu_init(void)
+{
+	return &armv6pmu;
+}
+
+/*
+ * ARMv6mpcore is almost identical to single core ARMv6 with the exception
+ * that some of the events have different enumerations and that there is no
+ * *hack* to stop the programmable counters. To stop the counters we simply
+ * 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 = {
+	.id			= ARM_PERF_PMU_ID_V6MP,
+	.name			= "v6mpcore",
+	.handle_irq		= armv6pmu_handle_irq,
+	.enable			= armv6pmu_enable_event,
+	.disable		= armv6mpcore_pmu_disable_event,
+	.read_counter		= armv6pmu_read_counter,
+	.write_counter		= armv6pmu_write_counter,
+	.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,
+	.num_events		= 3,
+	.max_period		= (1LLU << 32) - 1,
+};
+
+static const struct arm_pmu *__init armv6mpcore_pmu_init(void)
+{
+	return &armv6mpcore_pmu;
+}
+#else
+static const struct arm_pmu *__init armv6pmu_init(void)
+{
+	return NULL;
+}
+
+static const struct arm_pmu *__init armv6mpcore_pmu_init(void)
+{
+	return NULL;
+}
+#endif	/* CONFIG_CPU_V6 */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/kernel/perf_event_v7.c linux-libre-2.6.38-gnu1/arch/arm/kernel/perf_event_v7.c
--- linux-libre-2.6.37-gnu1/arch/arm/kernel/perf_event_v7.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/kernel/perf_event_v7.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,906 @@
+/*
+ * ARMv7 Cortex-A8 and Cortex-A9 Performance Events handling code.
+ *
+ * ARMv7 support: Jean Pihet <jpihet@mvista.com>
+ * 2010 (c) MontaVista Software, LLC.
+ *
+ * Copied from ARMv6 code, with the low level code inspired
+ *  by the ARMv7 Oprofile code.
+ *
+ * Cortex-A8 has up to 4 configurable performance counters and
+ *  a single cycle counter.
+ * Cortex-A9 has up to 31 configurable performance counters and
+ *  a single cycle counter.
+ *
+ * All counters can be enabled/disabled and IRQ masked separately. The cycle
+ *  counter and all 4 performance counters together can be reset separately.
+ */
+
+#ifdef CONFIG_CPU_V7
+/* Common ARMv7 event types */
+enum armv7_perf_types {
+	ARMV7_PERFCTR_PMNC_SW_INCR		= 0x00,
+	ARMV7_PERFCTR_IFETCH_MISS		= 0x01,
+	ARMV7_PERFCTR_ITLB_MISS			= 0x02,
+	ARMV7_PERFCTR_DCACHE_REFILL		= 0x03,
+	ARMV7_PERFCTR_DCACHE_ACCESS		= 0x04,
+	ARMV7_PERFCTR_DTLB_REFILL		= 0x05,
+	ARMV7_PERFCTR_DREAD			= 0x06,
+	ARMV7_PERFCTR_DWRITE			= 0x07,
+
+	ARMV7_PERFCTR_EXC_TAKEN			= 0x09,
+	ARMV7_PERFCTR_EXC_EXECUTED		= 0x0A,
+	ARMV7_PERFCTR_CID_WRITE			= 0x0B,
+	/* ARMV7_PERFCTR_PC_WRITE is equivalent to HW_BRANCH_INSTRUCTIONS.
+	 * It counts:
+	 *  - all branch instructions,
+	 *  - instructions that explicitly write the PC,
+	 *  - exception generating instructions.
+	 */
+	ARMV7_PERFCTR_PC_WRITE			= 0x0C,
+	ARMV7_PERFCTR_PC_IMM_BRANCH		= 0x0D,
+	ARMV7_PERFCTR_UNALIGNED_ACCESS		= 0x0F,
+	ARMV7_PERFCTR_PC_BRANCH_MIS_PRED	= 0x10,
+	ARMV7_PERFCTR_CLOCK_CYCLES		= 0x11,
+
+	ARMV7_PERFCTR_PC_BRANCH_MIS_USED	= 0x12,
+
+	ARMV7_PERFCTR_CPU_CYCLES		= 0xFF
+};
+
+/* ARMv7 Cortex-A8 specific event types */
+enum armv7_a8_perf_types {
+	ARMV7_PERFCTR_INSTR_EXECUTED		= 0x08,
+
+	ARMV7_PERFCTR_PC_PROC_RETURN		= 0x0E,
+
+	ARMV7_PERFCTR_WRITE_BUFFER_FULL		= 0x40,
+	ARMV7_PERFCTR_L2_STORE_MERGED		= 0x41,
+	ARMV7_PERFCTR_L2_STORE_BUFF		= 0x42,
+	ARMV7_PERFCTR_L2_ACCESS			= 0x43,
+	ARMV7_PERFCTR_L2_CACH_MISS		= 0x44,
+	ARMV7_PERFCTR_AXI_READ_CYCLES		= 0x45,
+	ARMV7_PERFCTR_AXI_WRITE_CYCLES		= 0x46,
+	ARMV7_PERFCTR_MEMORY_REPLAY		= 0x47,
+	ARMV7_PERFCTR_UNALIGNED_ACCESS_REPLAY	= 0x48,
+	ARMV7_PERFCTR_L1_DATA_MISS		= 0x49,
+	ARMV7_PERFCTR_L1_INST_MISS		= 0x4A,
+	ARMV7_PERFCTR_L1_DATA_COLORING		= 0x4B,
+	ARMV7_PERFCTR_L1_NEON_DATA		= 0x4C,
+	ARMV7_PERFCTR_L1_NEON_CACH_DATA		= 0x4D,
+	ARMV7_PERFCTR_L2_NEON			= 0x4E,
+	ARMV7_PERFCTR_L2_NEON_HIT		= 0x4F,
+	ARMV7_PERFCTR_L1_INST			= 0x50,
+	ARMV7_PERFCTR_PC_RETURN_MIS_PRED	= 0x51,
+	ARMV7_PERFCTR_PC_BRANCH_FAILED		= 0x52,
+	ARMV7_PERFCTR_PC_BRANCH_TAKEN		= 0x53,
+	ARMV7_PERFCTR_PC_BRANCH_EXECUTED	= 0x54,
+	ARMV7_PERFCTR_OP_EXECUTED		= 0x55,
+	ARMV7_PERFCTR_CYCLES_INST_STALL		= 0x56,
+	ARMV7_PERFCTR_CYCLES_INST		= 0x57,
+	ARMV7_PERFCTR_CYCLES_NEON_DATA_STALL	= 0x58,
+	ARMV7_PERFCTR_CYCLES_NEON_INST_STALL	= 0x59,
+	ARMV7_PERFCTR_NEON_CYCLES		= 0x5A,
+
+	ARMV7_PERFCTR_PMU0_EVENTS		= 0x70,
+	ARMV7_PERFCTR_PMU1_EVENTS		= 0x71,
+	ARMV7_PERFCTR_PMU_EVENTS		= 0x72,
+};
+
+/* ARMv7 Cortex-A9 specific event types */
+enum armv7_a9_perf_types {
+	ARMV7_PERFCTR_JAVA_HW_BYTECODE_EXEC	= 0x40,
+	ARMV7_PERFCTR_JAVA_SW_BYTECODE_EXEC	= 0x41,
+	ARMV7_PERFCTR_JAZELLE_BRANCH_EXEC	= 0x42,
+
+	ARMV7_PERFCTR_COHERENT_LINE_MISS	= 0x50,
+	ARMV7_PERFCTR_COHERENT_LINE_HIT		= 0x51,
+
+	ARMV7_PERFCTR_ICACHE_DEP_STALL_CYCLES	= 0x60,
+	ARMV7_PERFCTR_DCACHE_DEP_STALL_CYCLES	= 0x61,
+	ARMV7_PERFCTR_TLB_MISS_DEP_STALL_CYCLES	= 0x62,
+	ARMV7_PERFCTR_STREX_EXECUTED_PASSED	= 0x63,
+	ARMV7_PERFCTR_STREX_EXECUTED_FAILED	= 0x64,
+	ARMV7_PERFCTR_DATA_EVICTION		= 0x65,
+	ARMV7_PERFCTR_ISSUE_STAGE_NO_INST	= 0x66,
+	ARMV7_PERFCTR_ISSUE_STAGE_EMPTY		= 0x67,
+	ARMV7_PERFCTR_INST_OUT_OF_RENAME_STAGE	= 0x68,
+
+	ARMV7_PERFCTR_PREDICTABLE_FUNCT_RETURNS	= 0x6E,
+
+	ARMV7_PERFCTR_MAIN_UNIT_EXECUTED_INST	= 0x70,
+	ARMV7_PERFCTR_SECOND_UNIT_EXECUTED_INST	= 0x71,
+	ARMV7_PERFCTR_LD_ST_UNIT_EXECUTED_INST	= 0x72,
+	ARMV7_PERFCTR_FP_EXECUTED_INST		= 0x73,
+	ARMV7_PERFCTR_NEON_EXECUTED_INST	= 0x74,
+
+	ARMV7_PERFCTR_PLD_FULL_DEP_STALL_CYCLES	= 0x80,
+	ARMV7_PERFCTR_DATA_WR_DEP_STALL_CYCLES	= 0x81,
+	ARMV7_PERFCTR_ITLB_MISS_DEP_STALL_CYCLES	= 0x82,
+	ARMV7_PERFCTR_DTLB_MISS_DEP_STALL_CYCLES	= 0x83,
+	ARMV7_PERFCTR_MICRO_ITLB_MISS_DEP_STALL_CYCLES	= 0x84,
+	ARMV7_PERFCTR_MICRO_DTLB_MISS_DEP_STALL_CYCLES	= 0x85,
+	ARMV7_PERFCTR_DMB_DEP_STALL_CYCLES	= 0x86,
+
+	ARMV7_PERFCTR_INTGR_CLK_ENABLED_CYCLES	= 0x8A,
+	ARMV7_PERFCTR_DATA_ENGINE_CLK_EN_CYCLES	= 0x8B,
+
+	ARMV7_PERFCTR_ISB_INST			= 0x90,
+	ARMV7_PERFCTR_DSB_INST			= 0x91,
+	ARMV7_PERFCTR_DMB_INST			= 0x92,
+	ARMV7_PERFCTR_EXT_INTERRUPTS		= 0x93,
+
+	ARMV7_PERFCTR_PLE_CACHE_LINE_RQST_COMPLETED	= 0xA0,
+	ARMV7_PERFCTR_PLE_CACHE_LINE_RQST_SKIPPED	= 0xA1,
+	ARMV7_PERFCTR_PLE_FIFO_FLUSH		= 0xA2,
+	ARMV7_PERFCTR_PLE_RQST_COMPLETED	= 0xA3,
+	ARMV7_PERFCTR_PLE_FIFO_OVERFLOW		= 0xA4,
+	ARMV7_PERFCTR_PLE_RQST_PROG		= 0xA5
+};
+
+/*
+ * Cortex-A8 HW events mapping
+ *
+ * The hardware events that we support. We do support cache operations but
+ * we have harvard caches and no way to combine instruction and data
+ * accesses/misses in hardware.
+ */
+static const unsigned armv7_a8_perf_map[PERF_COUNT_HW_MAX] = {
+	[PERF_COUNT_HW_CPU_CYCLES]	    = ARMV7_PERFCTR_CPU_CYCLES,
+	[PERF_COUNT_HW_INSTRUCTIONS]	    = ARMV7_PERFCTR_INSTR_EXECUTED,
+	[PERF_COUNT_HW_CACHE_REFERENCES]    = HW_OP_UNSUPPORTED,
+	[PERF_COUNT_HW_CACHE_MISSES]	    = HW_OP_UNSUPPORTED,
+	[PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = ARMV7_PERFCTR_PC_WRITE,
+	[PERF_COUNT_HW_BRANCH_MISSES]	    = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
+	[PERF_COUNT_HW_BUS_CYCLES]	    = ARMV7_PERFCTR_CLOCK_CYCLES,
+};
+
+static const unsigned armv7_a8_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
+					  [PERF_COUNT_HW_CACHE_OP_MAX]
+					  [PERF_COUNT_HW_CACHE_RESULT_MAX] = {
+	[C(L1D)] = {
+		/*
+		 * The performance counters don't differentiate between read
+		 * and write accesses/misses so this isn't strictly correct,
+		 * but it's the best we can do. Writes and reads get
+		 * combined.
+		 */
+		[C(OP_READ)] = {
+			[C(RESULT_ACCESS)]	= ARMV7_PERFCTR_DCACHE_ACCESS,
+			[C(RESULT_MISS)]	= ARMV7_PERFCTR_DCACHE_REFILL,
+		},
+		[C(OP_WRITE)] = {
+			[C(RESULT_ACCESS)]	= ARMV7_PERFCTR_DCACHE_ACCESS,
+			[C(RESULT_MISS)]	= ARMV7_PERFCTR_DCACHE_REFILL,
+		},
+		[C(OP_PREFETCH)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+	},
+	[C(L1I)] = {
+		[C(OP_READ)] = {
+			[C(RESULT_ACCESS)]	= ARMV7_PERFCTR_L1_INST,
+			[C(RESULT_MISS)]	= ARMV7_PERFCTR_L1_INST_MISS,
+		},
+		[C(OP_WRITE)] = {
+			[C(RESULT_ACCESS)]	= ARMV7_PERFCTR_L1_INST,
+			[C(RESULT_MISS)]	= ARMV7_PERFCTR_L1_INST_MISS,
+		},
+		[C(OP_PREFETCH)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+	},
+	[C(LL)] = {
+		[C(OP_READ)] = {
+			[C(RESULT_ACCESS)]	= ARMV7_PERFCTR_L2_ACCESS,
+			[C(RESULT_MISS)]	= ARMV7_PERFCTR_L2_CACH_MISS,
+		},
+		[C(OP_WRITE)] = {
+			[C(RESULT_ACCESS)]	= ARMV7_PERFCTR_L2_ACCESS,
+			[C(RESULT_MISS)]	= ARMV7_PERFCTR_L2_CACH_MISS,
+		},
+		[C(OP_PREFETCH)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+	},
+	[C(DTLB)] = {
+		/*
+		 * Only ITLB misses and DTLB refills are supported.
+		 * If users want the DTLB refills misses a raw counter
+		 * must be used.
+		 */
+		[C(OP_READ)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= ARMV7_PERFCTR_DTLB_REFILL,
+		},
+		[C(OP_WRITE)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= ARMV7_PERFCTR_DTLB_REFILL,
+		},
+		[C(OP_PREFETCH)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+	},
+	[C(ITLB)] = {
+		[C(OP_READ)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= ARMV7_PERFCTR_ITLB_MISS,
+		},
+		[C(OP_WRITE)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= ARMV7_PERFCTR_ITLB_MISS,
+		},
+		[C(OP_PREFETCH)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+	},
+	[C(BPU)] = {
+		[C(OP_READ)] = {
+			[C(RESULT_ACCESS)]	= ARMV7_PERFCTR_PC_WRITE,
+			[C(RESULT_MISS)]
+					= ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
+		},
+		[C(OP_WRITE)] = {
+			[C(RESULT_ACCESS)]	= ARMV7_PERFCTR_PC_WRITE,
+			[C(RESULT_MISS)]
+					= ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
+		},
+		[C(OP_PREFETCH)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+	},
+};
+
+/*
+ * Cortex-A9 HW events mapping
+ */
+static const unsigned armv7_a9_perf_map[PERF_COUNT_HW_MAX] = {
+	[PERF_COUNT_HW_CPU_CYCLES]	    = ARMV7_PERFCTR_CPU_CYCLES,
+	[PERF_COUNT_HW_INSTRUCTIONS]	    =
+					ARMV7_PERFCTR_INST_OUT_OF_RENAME_STAGE,
+	[PERF_COUNT_HW_CACHE_REFERENCES]    = ARMV7_PERFCTR_COHERENT_LINE_HIT,
+	[PERF_COUNT_HW_CACHE_MISSES]	    = ARMV7_PERFCTR_COHERENT_LINE_MISS,
+	[PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = ARMV7_PERFCTR_PC_WRITE,
+	[PERF_COUNT_HW_BRANCH_MISSES]	    = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
+	[PERF_COUNT_HW_BUS_CYCLES]	    = ARMV7_PERFCTR_CLOCK_CYCLES,
+};
+
+static const unsigned armv7_a9_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
+					  [PERF_COUNT_HW_CACHE_OP_MAX]
+					  [PERF_COUNT_HW_CACHE_RESULT_MAX] = {
+	[C(L1D)] = {
+		/*
+		 * The performance counters don't differentiate between read
+		 * and write accesses/misses so this isn't strictly correct,
+		 * but it's the best we can do. Writes and reads get
+		 * combined.
+		 */
+		[C(OP_READ)] = {
+			[C(RESULT_ACCESS)]	= ARMV7_PERFCTR_DCACHE_ACCESS,
+			[C(RESULT_MISS)]	= ARMV7_PERFCTR_DCACHE_REFILL,
+		},
+		[C(OP_WRITE)] = {
+			[C(RESULT_ACCESS)]	= ARMV7_PERFCTR_DCACHE_ACCESS,
+			[C(RESULT_MISS)]	= ARMV7_PERFCTR_DCACHE_REFILL,
+		},
+		[C(OP_PREFETCH)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+	},
+	[C(L1I)] = {
+		[C(OP_READ)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= ARMV7_PERFCTR_IFETCH_MISS,
+		},
+		[C(OP_WRITE)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= ARMV7_PERFCTR_IFETCH_MISS,
+		},
+		[C(OP_PREFETCH)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+	},
+	[C(LL)] = {
+		[C(OP_READ)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+		[C(OP_WRITE)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+		[C(OP_PREFETCH)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+	},
+	[C(DTLB)] = {
+		/*
+		 * Only ITLB misses and DTLB refills are supported.
+		 * If users want the DTLB refills misses a raw counter
+		 * must be used.
+		 */
+		[C(OP_READ)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= ARMV7_PERFCTR_DTLB_REFILL,
+		},
+		[C(OP_WRITE)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= ARMV7_PERFCTR_DTLB_REFILL,
+		},
+		[C(OP_PREFETCH)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+	},
+	[C(ITLB)] = {
+		[C(OP_READ)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= ARMV7_PERFCTR_ITLB_MISS,
+		},
+		[C(OP_WRITE)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= ARMV7_PERFCTR_ITLB_MISS,
+		},
+		[C(OP_PREFETCH)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+	},
+	[C(BPU)] = {
+		[C(OP_READ)] = {
+			[C(RESULT_ACCESS)]	= ARMV7_PERFCTR_PC_WRITE,
+			[C(RESULT_MISS)]
+					= ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
+		},
+		[C(OP_WRITE)] = {
+			[C(RESULT_ACCESS)]	= ARMV7_PERFCTR_PC_WRITE,
+			[C(RESULT_MISS)]
+					= ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
+		},
+		[C(OP_PREFETCH)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+	},
+};
+
+/*
+ * Perf Events counters
+ */
+enum armv7_counters {
+	ARMV7_CYCLE_COUNTER		= 1,	/* Cycle counter */
+	ARMV7_COUNTER0			= 2,	/* First event counter */
+};
+
+/*
+ * 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).
+ */
+#define	ARMV7_COUNTER_LAST	(ARMV7_COUNTER0 + armpmu->num_events - 1)
+
+/*
+ * ARMv7 low level PMNC access
+ */
+
+/*
+ * Per-CPU PMNC: config reg
+ */
+#define ARMV7_PMNC_E		(1 << 0) /* Enable all counters */
+#define ARMV7_PMNC_P		(1 << 1) /* Reset all counters */
+#define ARMV7_PMNC_C		(1 << 2) /* Cycle counter reset */
+#define ARMV7_PMNC_D		(1 << 3) /* CCNT counts every 64th cpu cycle */
+#define ARMV7_PMNC_X		(1 << 4) /* Export to ETM */
+#define ARMV7_PMNC_DP		(1 << 5) /* Disable CCNT if non-invasive debug*/
+#define	ARMV7_PMNC_N_SHIFT	11	 /* Number of counters supported */
+#define	ARMV7_PMNC_N_MASK	0x1f
+#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
+ */
+#define	ARMV7_EVTSEL_MASK	0xff		/* Mask for writable bits */
+
+/*
+ * SELECT: Counter selection reg
+ */
+#define	ARMV7_SELECT_MASK	0x1f		/* Mask for writable bits */
+
+/*
+ * FLAG: counters overflow flag status reg
+ */
+#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
+
+static inline unsigned long 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)
+{
+	val &= ARMV7_PMNC_MASK;
+	asm volatile("mcr p15, 0, %0, c9, c12, 0" : : "r"(val));
+}
+
+static inline int armv7_pmnc_has_overflowed(unsigned long pmnc)
+{
+	return pmnc & ARMV7_OVERFLOWED_MASK;
+}
+
+static inline int armv7_pmnc_counter_has_overflowed(unsigned long pmnc,
+					enum armv7_counters counter)
+{
+	int ret = 0;
+
+	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
+		pr_err("CPU%u checking wrong counter %d overflow status\n",
+			smp_processor_id(), counter);
+
+	return ret;
+}
+
+static inline int armv7_pmnc_select_counter(unsigned int idx)
+{
+	u32 val;
+
+	if ((idx < ARMV7_COUNTER0) || (idx > ARMV7_COUNTER_LAST)) {
+		pr_err("CPU%u selecting wrong PMNC counter"
+			" %d\n", smp_processor_id(), idx);
+		return -1;
+	}
+
+	val = (idx - ARMV7_EVENT_CNT_TO_CNTx) & ARMV7_SELECT_MASK;
+	asm volatile("mcr p15, 0, %0, c9, c12, 5" : : "r" (val));
+
+	return idx;
+}
+
+static inline u32 armv7pmu_read_counter(int idx)
+{
+	unsigned long 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
+		pr_err("CPU%u reading wrong counter %d\n",
+			smp_processor_id(), idx);
+
+	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
+		pr_err("CPU%u writing wrong counter %d\n",
+			smp_processor_id(), idx);
+}
+
+static inline void armv7_pmnc_write_evtsel(unsigned int idx, u32 val)
+{
+	if (armv7_pmnc_select_counter(idx) == idx) {
+		val &= ARMV7_EVTSEL_MASK;
+		asm volatile("mcr p15, 0, %0, c9, c13, 1" : : "r" (val));
+	}
+}
+
+static inline u32 armv7_pmnc_enable_counter(unsigned int idx)
+{
+	u32 val;
+
+	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 (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));
+
+	return idx;
+}
+
+static inline u32 armv7_pmnc_disable_counter(unsigned int idx)
+{
+	u32 val;
+
+
+	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 (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));
+
+	return idx;
+}
+
+static inline u32 armv7_pmnc_enable_intens(unsigned int idx)
+{
+	u32 val;
+
+	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 (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));
+
+	return idx;
+}
+
+static inline u32 armv7_pmnc_disable_intens(unsigned int idx)
+{
+	u32 val;
+
+	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 (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));
+
+	return idx;
+}
+
+static inline u32 armv7_pmnc_getreset_flags(void)
+{
+	u32 val;
+
+	/* Read */
+	asm volatile("mrc p15, 0, %0, c9, c12, 3" : "=r" (val));
+
+	/* Write to clear flags */
+	val &= ARMV7_FLAG_MASK;
+	asm volatile("mcr p15, 0, %0, c9, c12, 3" : : "r" (val));
+
+	return val;
+}
+
+#ifdef DEBUG
+static void armv7_pmnc_dump_regs(void)
+{
+	u32 val;
+	unsigned int cnt;
+
+	printk(KERN_INFO "PMNC registers dump:\n");
+
+	asm volatile("mrc p15, 0, %0, c9, c12, 0" : "=r" (val));
+	printk(KERN_INFO "PMNC  =0x%08x\n", val);
+
+	asm volatile("mrc p15, 0, %0, c9, c12, 1" : "=r" (val));
+	printk(KERN_INFO "CNTENS=0x%08x\n", val);
+
+	asm volatile("mrc p15, 0, %0, c9, c14, 1" : "=r" (val));
+	printk(KERN_INFO "INTENS=0x%08x\n", val);
+
+	asm volatile("mrc p15, 0, %0, c9, c12, 3" : "=r" (val));
+	printk(KERN_INFO "FLAGS =0x%08x\n", val);
+
+	asm volatile("mrc p15, 0, %0, c9, c12, 5" : "=r" (val));
+	printk(KERN_INFO "SELECT=0x%08x\n", val);
+
+	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++) {
+		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);
+		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);
+	}
+}
+#endif
+
+static void armv7pmu_enable_event(struct hw_perf_event *hwc, int idx)
+{
+	unsigned long flags;
+
+	/*
+	 * Enable counter and interrupt, and set the counter to count
+	 * the event that we're interested in.
+	 */
+	raw_spin_lock_irqsave(&pmu_lock, flags);
+
+	/*
+	 * Disable counter
+	 */
+	armv7_pmnc_disable_counter(idx);
+
+	/*
+	 * Set event (if destined for PMNx counters)
+	 * We don't need to set the event if it's a cycle count
+	 */
+	if (idx != ARMV7_CYCLE_COUNTER)
+		armv7_pmnc_write_evtsel(idx, hwc->config_base);
+
+	/*
+	 * Enable interrupt for this counter
+	 */
+	armv7_pmnc_enable_intens(idx);
+
+	/*
+	 * Enable counter
+	 */
+	armv7_pmnc_enable_counter(idx);
+
+	raw_spin_unlock_irqrestore(&pmu_lock, flags);
+}
+
+static void armv7pmu_disable_event(struct hw_perf_event *hwc, int idx)
+{
+	unsigned long flags;
+
+	/*
+	 * Disable counter and interrupt
+	 */
+	raw_spin_lock_irqsave(&pmu_lock, flags);
+
+	/*
+	 * Disable counter
+	 */
+	armv7_pmnc_disable_counter(idx);
+
+	/*
+	 * Disable interrupt for this counter
+	 */
+	armv7_pmnc_disable_intens(idx);
+
+	raw_spin_unlock_irqrestore(&pmu_lock, flags);
+}
+
+static irqreturn_t armv7pmu_handle_irq(int irq_num, void *dev)
+{
+	unsigned long pmnc;
+	struct perf_sample_data data;
+	struct cpu_hw_events *cpuc;
+	struct pt_regs *regs;
+	int idx;
+
+	/*
+	 * Get and reset the IRQ flags
+	 */
+	pmnc = armv7_pmnc_getreset_flags();
+
+	/*
+	 * Did an overflow occur?
+	 */
+	if (!armv7_pmnc_has_overflowed(pmnc))
+		return IRQ_NONE;
+
+	/*
+	 * Handle the counter(s) overflow(s)
+	 */
+	regs = get_irq_regs();
+
+	perf_sample_data_init(&data, 0);
+
+	cpuc = &__get_cpu_var(cpu_hw_events);
+	for (idx = 0; idx <= armpmu->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.
+		 */
+		if (!armv7_pmnc_counter_has_overflowed(pmnc, idx))
+			continue;
+
+		hwc = &event->hw;
+		armpmu_event_update(event, hwc, idx);
+		data.period = event->hw.last_period;
+		if (!armpmu_event_set_period(event, hwc, idx))
+			continue;
+
+		if (perf_event_overflow(event, 0, &data, regs))
+			armpmu->disable(hwc, idx);
+	}
+
+	/*
+	 * Handle the pending perf events.
+	 *
+	 * Note: this call *must* be run with interrupts disabled. For
+	 * platforms that can have the PMU interrupts raised as an NMI, this
+	 * will not work.
+	 */
+	irq_work_run();
+
+	return IRQ_HANDLED;
+}
+
+static void armv7pmu_start(void)
+{
+	unsigned long flags;
+
+	raw_spin_lock_irqsave(&pmu_lock, flags);
+	/* Enable all counters */
+	armv7_pmnc_write(armv7_pmnc_read() | ARMV7_PMNC_E);
+	raw_spin_unlock_irqrestore(&pmu_lock, flags);
+}
+
+static void armv7pmu_stop(void)
+{
+	unsigned long flags;
+
+	raw_spin_lock_irqsave(&pmu_lock, flags);
+	/* Disable all counters */
+	armv7_pmnc_write(armv7_pmnc_read() & ~ARMV7_PMNC_E);
+	raw_spin_unlock_irqrestore(&pmu_lock, flags);
+}
+
+static int armv7pmu_get_event_idx(struct cpu_hw_events *cpuc,
+				  struct hw_perf_event *event)
+{
+	int idx;
+
+	/* 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))
+			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;
+		}
+
+		/* The counters are all in use. */
+		return -EAGAIN;
+	}
+}
+
+static struct arm_pmu armv7pmu = {
+	.handle_irq		= armv7pmu_handle_irq,
+	.enable			= armv7pmu_enable_event,
+	.disable		= armv7pmu_disable_event,
+	.read_counter		= armv7pmu_read_counter,
+	.write_counter		= armv7pmu_write_counter,
+	.get_event_idx		= armv7pmu_get_event_idx,
+	.start			= armv7pmu_start,
+	.stop			= armv7pmu_stop,
+	.raw_event_mask		= 0xFF,
+	.max_period		= (1LLU << 32) - 1,
+};
+
+static u32 __init armv7_reset_read_pmnc(void)
+{
+	u32 nb_cnt;
+
+	/* Initialize & Reset PMNC: C and P bits */
+	armv7_pmnc_write(ARMV7_PMNC_P | ARMV7_PMNC_C);
+
+	/* Read the nb of CNTx counters supported from PMNC */
+	nb_cnt = (armv7_pmnc_read() >> ARMV7_PMNC_N_SHIFT) & ARMV7_PMNC_N_MASK;
+
+	/* Add the CPU cycles counter and return */
+	return nb_cnt + 1;
+}
+
+static const 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.num_events	= armv7_reset_read_pmnc();
+	return &armv7pmu;
+}
+
+static const 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.num_events	= armv7_reset_read_pmnc();
+	return &armv7pmu;
+}
+#else
+static const struct arm_pmu *__init armv7_a8_pmu_init(void)
+{
+	return NULL;
+}
+
+static const struct arm_pmu *__init armv7_a9_pmu_init(void)
+{
+	return NULL;
+}
+#endif	/* CONFIG_CPU_V7 */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/kernel/perf_event_xscale.c linux-libre-2.6.38-gnu1/arch/arm/kernel/perf_event_xscale.c
--- linux-libre-2.6.37-gnu1/arch/arm/kernel/perf_event_xscale.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/kernel/perf_event_xscale.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,807 @@
+/*
+ * ARMv5 [xscale] Performance counter handling code.
+ *
+ * Copyright (C) 2010, ARM Ltd., Will Deacon <will.deacon@arm.com>
+ *
+ * Based on the previous xscale OProfile code.
+ *
+ * There are two variants of the xscale PMU that we support:
+ * 	- xscale1pmu: 2 event counters and a cycle counter
+ * 	- xscale2pmu: 4 event counters and a cycle counter
+ * The two variants share event definitions, but have different
+ * PMU structures.
+ */
+
+#ifdef CONFIG_CPU_XSCALE
+enum xscale_perf_types {
+	XSCALE_PERFCTR_ICACHE_MISS		= 0x00,
+	XSCALE_PERFCTR_ICACHE_NO_DELIVER	= 0x01,
+	XSCALE_PERFCTR_DATA_STALL		= 0x02,
+	XSCALE_PERFCTR_ITLB_MISS		= 0x03,
+	XSCALE_PERFCTR_DTLB_MISS		= 0x04,
+	XSCALE_PERFCTR_BRANCH			= 0x05,
+	XSCALE_PERFCTR_BRANCH_MISS		= 0x06,
+	XSCALE_PERFCTR_INSTRUCTION		= 0x07,
+	XSCALE_PERFCTR_DCACHE_FULL_STALL	= 0x08,
+	XSCALE_PERFCTR_DCACHE_FULL_STALL_CONTIG	= 0x09,
+	XSCALE_PERFCTR_DCACHE_ACCESS		= 0x0A,
+	XSCALE_PERFCTR_DCACHE_MISS		= 0x0B,
+	XSCALE_PERFCTR_DCACHE_WRITE_BACK	= 0x0C,
+	XSCALE_PERFCTR_PC_CHANGED		= 0x0D,
+	XSCALE_PERFCTR_BCU_REQUEST		= 0x10,
+	XSCALE_PERFCTR_BCU_FULL			= 0x11,
+	XSCALE_PERFCTR_BCU_DRAIN		= 0x12,
+	XSCALE_PERFCTR_BCU_ECC_NO_ELOG		= 0x14,
+	XSCALE_PERFCTR_BCU_1_BIT_ERR		= 0x15,
+	XSCALE_PERFCTR_RMW			= 0x16,
+	/* XSCALE_PERFCTR_CCNT is not hardware defined */
+	XSCALE_PERFCTR_CCNT			= 0xFE,
+	XSCALE_PERFCTR_UNUSED			= 0xFF,
+};
+
+enum xscale_counters {
+	XSCALE_CYCLE_COUNTER	= 1,
+	XSCALE_COUNTER0,
+	XSCALE_COUNTER1,
+	XSCALE_COUNTER2,
+	XSCALE_COUNTER3,
+};
+
+static const unsigned xscale_perf_map[PERF_COUNT_HW_MAX] = {
+	[PERF_COUNT_HW_CPU_CYCLES]	    = XSCALE_PERFCTR_CCNT,
+	[PERF_COUNT_HW_INSTRUCTIONS]	    = XSCALE_PERFCTR_INSTRUCTION,
+	[PERF_COUNT_HW_CACHE_REFERENCES]    = HW_OP_UNSUPPORTED,
+	[PERF_COUNT_HW_CACHE_MISSES]	    = HW_OP_UNSUPPORTED,
+	[PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = XSCALE_PERFCTR_BRANCH,
+	[PERF_COUNT_HW_BRANCH_MISSES]	    = XSCALE_PERFCTR_BRANCH_MISS,
+	[PERF_COUNT_HW_BUS_CYCLES]	    = HW_OP_UNSUPPORTED,
+};
+
+static const unsigned xscale_perf_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)]	= XSCALE_PERFCTR_DCACHE_ACCESS,
+			[C(RESULT_MISS)]	= XSCALE_PERFCTR_DCACHE_MISS,
+		},
+		[C(OP_WRITE)] = {
+			[C(RESULT_ACCESS)]	= XSCALE_PERFCTR_DCACHE_ACCESS,
+			[C(RESULT_MISS)]	= XSCALE_PERFCTR_DCACHE_MISS,
+		},
+		[C(OP_PREFETCH)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+	},
+	[C(L1I)] = {
+		[C(OP_READ)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= XSCALE_PERFCTR_ICACHE_MISS,
+		},
+		[C(OP_WRITE)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= XSCALE_PERFCTR_ICACHE_MISS,
+		},
+		[C(OP_PREFETCH)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+	},
+	[C(LL)] = {
+		[C(OP_READ)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+		[C(OP_WRITE)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+		[C(OP_PREFETCH)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+	},
+	[C(DTLB)] = {
+		[C(OP_READ)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= XSCALE_PERFCTR_DTLB_MISS,
+		},
+		[C(OP_WRITE)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= XSCALE_PERFCTR_DTLB_MISS,
+		},
+		[C(OP_PREFETCH)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+	},
+	[C(ITLB)] = {
+		[C(OP_READ)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= XSCALE_PERFCTR_ITLB_MISS,
+		},
+		[C(OP_WRITE)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= XSCALE_PERFCTR_ITLB_MISS,
+		},
+		[C(OP_PREFETCH)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+	},
+	[C(BPU)] = {
+		[C(OP_READ)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+		[C(OP_WRITE)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+		[C(OP_PREFETCH)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+	},
+};
+
+#define	XSCALE_PMU_ENABLE	0x001
+#define XSCALE_PMN_RESET	0x002
+#define	XSCALE_CCNT_RESET	0x004
+#define	XSCALE_PMU_RESET	(CCNT_RESET | PMN_RESET)
+#define XSCALE_PMU_CNT64	0x008
+
+#define XSCALE1_OVERFLOWED_MASK	0x700
+#define XSCALE1_CCOUNT_OVERFLOW	0x400
+#define XSCALE1_COUNT0_OVERFLOW	0x100
+#define XSCALE1_COUNT1_OVERFLOW	0x200
+#define XSCALE1_CCOUNT_INT_EN	0x040
+#define XSCALE1_COUNT0_INT_EN	0x010
+#define XSCALE1_COUNT1_INT_EN	0x020
+#define XSCALE1_COUNT0_EVT_SHFT	12
+#define XSCALE1_COUNT0_EVT_MASK	(0xff << XSCALE1_COUNT0_EVT_SHFT)
+#define XSCALE1_COUNT1_EVT_SHFT	20
+#define XSCALE1_COUNT1_EVT_MASK	(0xff << XSCALE1_COUNT1_EVT_SHFT)
+
+static inline u32
+xscale1pmu_read_pmnc(void)
+{
+	u32 val;
+	asm volatile("mrc p14, 0, %0, c0, c0, 0" : "=r" (val));
+	return val;
+}
+
+static inline void
+xscale1pmu_write_pmnc(u32 val)
+{
+	/* upper 4bits and 7, 11 are write-as-0 */
+	val &= 0xffff77f;
+	asm volatile("mcr p14, 0, %0, c0, c0, 0" : : "r" (val));
+}
+
+static inline int
+xscale1_pmnc_counter_has_overflowed(unsigned long pmnc,
+					enum xscale_counters counter)
+{
+	int ret = 0;
+
+	switch (counter) {
+	case XSCALE_CYCLE_COUNTER:
+		ret = pmnc & XSCALE1_CCOUNT_OVERFLOW;
+		break;
+	case XSCALE_COUNTER0:
+		ret = pmnc & XSCALE1_COUNT0_OVERFLOW;
+		break;
+	case XSCALE_COUNTER1:
+		ret = pmnc & XSCALE1_COUNT1_OVERFLOW;
+		break;
+	default:
+		WARN_ONCE(1, "invalid counter number (%d)\n", counter);
+	}
+
+	return ret;
+}
+
+static irqreturn_t
+xscale1pmu_handle_irq(int irq_num, void *dev)
+{
+	unsigned long pmnc;
+	struct perf_sample_data data;
+	struct cpu_hw_events *cpuc;
+	struct pt_regs *regs;
+	int idx;
+
+	/*
+	 * NOTE: there's an A stepping erratum that states if an overflow
+	 *       bit already exists and another occurs, the previous
+	 *       Overflow bit gets cleared. There's no workaround.
+	 *	 Fixed in B stepping or later.
+	 */
+	pmnc = xscale1pmu_read_pmnc();
+
+	/*
+	 * Write the value back to clear the overflow flags. Overflow
+	 * flags remain in pmnc for use below. We also disable the PMU
+	 * while we process the interrupt.
+	 */
+	xscale1pmu_write_pmnc(pmnc & ~XSCALE_PMU_ENABLE);
+
+	if (!(pmnc & XSCALE1_OVERFLOWED_MASK))
+		return IRQ_NONE;
+
+	regs = get_irq_regs();
+
+	perf_sample_data_init(&data, 0);
+
+	cpuc = &__get_cpu_var(cpu_hw_events);
+	for (idx = 0; idx <= armpmu->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;
+
+		hwc = &event->hw;
+		armpmu_event_update(event, hwc, idx);
+		data.period = event->hw.last_period;
+		if (!armpmu_event_set_period(event, hwc, idx))
+			continue;
+
+		if (perf_event_overflow(event, 0, &data, regs))
+			armpmu->disable(hwc, idx);
+	}
+
+	irq_work_run();
+
+	/*
+	 * Re-enable the PMU.
+	 */
+	pmnc = xscale1pmu_read_pmnc() | XSCALE_PMU_ENABLE;
+	xscale1pmu_write_pmnc(pmnc);
+
+	return IRQ_HANDLED;
+}
+
+static void
+xscale1pmu_enable_event(struct hw_perf_event *hwc, int idx)
+{
+	unsigned long val, mask, evt, flags;
+
+	switch (idx) {
+	case XSCALE_CYCLE_COUNTER:
+		mask = 0;
+		evt = XSCALE1_CCOUNT_INT_EN;
+		break;
+	case XSCALE_COUNTER0:
+		mask = XSCALE1_COUNT0_EVT_MASK;
+		evt = (hwc->config_base << XSCALE1_COUNT0_EVT_SHFT) |
+			XSCALE1_COUNT0_INT_EN;
+		break;
+	case XSCALE_COUNTER1:
+		mask = XSCALE1_COUNT1_EVT_MASK;
+		evt = (hwc->config_base << XSCALE1_COUNT1_EVT_SHFT) |
+			XSCALE1_COUNT1_INT_EN;
+		break;
+	default:
+		WARN_ONCE(1, "invalid counter number (%d)\n", idx);
+		return;
+	}
+
+	raw_spin_lock_irqsave(&pmu_lock, flags);
+	val = xscale1pmu_read_pmnc();
+	val &= ~mask;
+	val |= evt;
+	xscale1pmu_write_pmnc(val);
+	raw_spin_unlock_irqrestore(&pmu_lock, flags);
+}
+
+static void
+xscale1pmu_disable_event(struct hw_perf_event *hwc, int idx)
+{
+	unsigned long val, mask, evt, flags;
+
+	switch (idx) {
+	case XSCALE_CYCLE_COUNTER:
+		mask = XSCALE1_CCOUNT_INT_EN;
+		evt = 0;
+		break;
+	case XSCALE_COUNTER0:
+		mask = XSCALE1_COUNT0_INT_EN | XSCALE1_COUNT0_EVT_MASK;
+		evt = XSCALE_PERFCTR_UNUSED << XSCALE1_COUNT0_EVT_SHFT;
+		break;
+	case XSCALE_COUNTER1:
+		mask = XSCALE1_COUNT1_INT_EN | XSCALE1_COUNT1_EVT_MASK;
+		evt = XSCALE_PERFCTR_UNUSED << XSCALE1_COUNT1_EVT_SHFT;
+		break;
+	default:
+		WARN_ONCE(1, "invalid counter number (%d)\n", idx);
+		return;
+	}
+
+	raw_spin_lock_irqsave(&pmu_lock, flags);
+	val = xscale1pmu_read_pmnc();
+	val &= ~mask;
+	val |= evt;
+	xscale1pmu_write_pmnc(val);
+	raw_spin_unlock_irqrestore(&pmu_lock, flags);
+}
+
+static int
+xscale1pmu_get_event_idx(struct cpu_hw_events *cpuc,
+			struct hw_perf_event *event)
+{
+	if (XSCALE_PERFCTR_CCNT == event->config_base) {
+		if (test_and_set_bit(XSCALE_CYCLE_COUNTER, cpuc->used_mask))
+			return -EAGAIN;
+
+		return XSCALE_CYCLE_COUNTER;
+	} else {
+		if (!test_and_set_bit(XSCALE_COUNTER1, cpuc->used_mask))
+			return XSCALE_COUNTER1;
+
+		if (!test_and_set_bit(XSCALE_COUNTER0, cpuc->used_mask))
+			return XSCALE_COUNTER0;
+
+		return -EAGAIN;
+	}
+}
+
+static void
+xscale1pmu_start(void)
+{
+	unsigned long flags, val;
+
+	raw_spin_lock_irqsave(&pmu_lock, flags);
+	val = xscale1pmu_read_pmnc();
+	val |= XSCALE_PMU_ENABLE;
+	xscale1pmu_write_pmnc(val);
+	raw_spin_unlock_irqrestore(&pmu_lock, flags);
+}
+
+static void
+xscale1pmu_stop(void)
+{
+	unsigned long flags, val;
+
+	raw_spin_lock_irqsave(&pmu_lock, flags);
+	val = xscale1pmu_read_pmnc();
+	val &= ~XSCALE_PMU_ENABLE;
+	xscale1pmu_write_pmnc(val);
+	raw_spin_unlock_irqrestore(&pmu_lock, flags);
+}
+
+static inline u32
+xscale1pmu_read_counter(int counter)
+{
+	u32 val = 0;
+
+	switch (counter) {
+	case XSCALE_CYCLE_COUNTER:
+		asm volatile("mrc p14, 0, %0, c1, c0, 0" : "=r" (val));
+		break;
+	case XSCALE_COUNTER0:
+		asm volatile("mrc p14, 0, %0, c2, c0, 0" : "=r" (val));
+		break;
+	case XSCALE_COUNTER1:
+		asm volatile("mrc p14, 0, %0, c3, c0, 0" : "=r" (val));
+		break;
+	}
+
+	return val;
+}
+
+static inline void
+xscale1pmu_write_counter(int counter, u32 val)
+{
+	switch (counter) {
+	case XSCALE_CYCLE_COUNTER:
+		asm volatile("mcr p14, 0, %0, c1, c0, 0" : : "r" (val));
+		break;
+	case XSCALE_COUNTER0:
+		asm volatile("mcr p14, 0, %0, c2, c0, 0" : : "r" (val));
+		break;
+	case XSCALE_COUNTER1:
+		asm volatile("mcr p14, 0, %0, c3, c0, 0" : : "r" (val));
+		break;
+	}
+}
+
+static const struct arm_pmu xscale1pmu = {
+	.id		= ARM_PERF_PMU_ID_XSCALE1,
+	.name		= "xscale1",
+	.handle_irq	= xscale1pmu_handle_irq,
+	.enable		= xscale1pmu_enable_event,
+	.disable	= xscale1pmu_disable_event,
+	.read_counter	= xscale1pmu_read_counter,
+	.write_counter	= xscale1pmu_write_counter,
+	.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,
+	.num_events	= 3,
+	.max_period	= (1LLU << 32) - 1,
+};
+
+static const struct arm_pmu *__init xscale1pmu_init(void)
+{
+	return &xscale1pmu;
+}
+
+#define XSCALE2_OVERFLOWED_MASK	0x01f
+#define XSCALE2_CCOUNT_OVERFLOW	0x001
+#define XSCALE2_COUNT0_OVERFLOW	0x002
+#define XSCALE2_COUNT1_OVERFLOW	0x004
+#define XSCALE2_COUNT2_OVERFLOW	0x008
+#define XSCALE2_COUNT3_OVERFLOW	0x010
+#define XSCALE2_CCOUNT_INT_EN	0x001
+#define XSCALE2_COUNT0_INT_EN	0x002
+#define XSCALE2_COUNT1_INT_EN	0x004
+#define XSCALE2_COUNT2_INT_EN	0x008
+#define XSCALE2_COUNT3_INT_EN	0x010
+#define XSCALE2_COUNT0_EVT_SHFT	0
+#define XSCALE2_COUNT0_EVT_MASK	(0xff << XSCALE2_COUNT0_EVT_SHFT)
+#define XSCALE2_COUNT1_EVT_SHFT	8
+#define XSCALE2_COUNT1_EVT_MASK	(0xff << XSCALE2_COUNT1_EVT_SHFT)
+#define XSCALE2_COUNT2_EVT_SHFT	16
+#define XSCALE2_COUNT2_EVT_MASK	(0xff << XSCALE2_COUNT2_EVT_SHFT)
+#define XSCALE2_COUNT3_EVT_SHFT	24
+#define XSCALE2_COUNT3_EVT_MASK	(0xff << XSCALE2_COUNT3_EVT_SHFT)
+
+static inline u32
+xscale2pmu_read_pmnc(void)
+{
+	u32 val;
+	asm volatile("mrc p14, 0, %0, c0, c1, 0" : "=r" (val));
+	/* bits 1-2 and 4-23 are read-unpredictable */
+	return val & 0xff000009;
+}
+
+static inline void
+xscale2pmu_write_pmnc(u32 val)
+{
+	/* bits 4-23 are write-as-0, 24-31 are write ignored */
+	val &= 0xf;
+	asm volatile("mcr p14, 0, %0, c0, c1, 0" : : "r" (val));
+}
+
+static inline u32
+xscale2pmu_read_overflow_flags(void)
+{
+	u32 val;
+	asm volatile("mrc p14, 0, %0, c5, c1, 0" : "=r" (val));
+	return val;
+}
+
+static inline void
+xscale2pmu_write_overflow_flags(u32 val)
+{
+	asm volatile("mcr p14, 0, %0, c5, c1, 0" : : "r" (val));
+}
+
+static inline u32
+xscale2pmu_read_event_select(void)
+{
+	u32 val;
+	asm volatile("mrc p14, 0, %0, c8, c1, 0" : "=r" (val));
+	return val;
+}
+
+static inline void
+xscale2pmu_write_event_select(u32 val)
+{
+	asm volatile("mcr p14, 0, %0, c8, c1, 0" : : "r"(val));
+}
+
+static inline u32
+xscale2pmu_read_int_enable(void)
+{
+	u32 val;
+	asm volatile("mrc p14, 0, %0, c4, c1, 0" : "=r" (val));
+	return val;
+}
+
+static void
+xscale2pmu_write_int_enable(u32 val)
+{
+	asm volatile("mcr p14, 0, %0, c4, c1, 0" : : "r" (val));
+}
+
+static inline int
+xscale2_pmnc_counter_has_overflowed(unsigned long of_flags,
+					enum xscale_counters counter)
+{
+	int ret = 0;
+
+	switch (counter) {
+	case XSCALE_CYCLE_COUNTER:
+		ret = of_flags & XSCALE2_CCOUNT_OVERFLOW;
+		break;
+	case XSCALE_COUNTER0:
+		ret = of_flags & XSCALE2_COUNT0_OVERFLOW;
+		break;
+	case XSCALE_COUNTER1:
+		ret = of_flags & XSCALE2_COUNT1_OVERFLOW;
+		break;
+	case XSCALE_COUNTER2:
+		ret = of_flags & XSCALE2_COUNT2_OVERFLOW;
+		break;
+	case XSCALE_COUNTER3:
+		ret = of_flags & XSCALE2_COUNT3_OVERFLOW;
+		break;
+	default:
+		WARN_ONCE(1, "invalid counter number (%d)\n", counter);
+	}
+
+	return ret;
+}
+
+static irqreturn_t
+xscale2pmu_handle_irq(int irq_num, void *dev)
+{
+	unsigned long pmnc, of_flags;
+	struct perf_sample_data data;
+	struct cpu_hw_events *cpuc;
+	struct pt_regs *regs;
+	int idx;
+
+	/* Disable the PMU. */
+	pmnc = xscale2pmu_read_pmnc();
+	xscale2pmu_write_pmnc(pmnc & ~XSCALE_PMU_ENABLE);
+
+	/* Check the overflow flag register. */
+	of_flags = xscale2pmu_read_overflow_flags();
+	if (!(of_flags & XSCALE2_OVERFLOWED_MASK))
+		return IRQ_NONE;
+
+	/* Clear the overflow bits. */
+	xscale2pmu_write_overflow_flags(of_flags);
+
+	regs = get_irq_regs();
+
+	perf_sample_data_init(&data, 0);
+
+	cpuc = &__get_cpu_var(cpu_hw_events);
+	for (idx = 0; idx <= armpmu->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;
+
+		hwc = &event->hw;
+		armpmu_event_update(event, hwc, idx);
+		data.period = event->hw.last_period;
+		if (!armpmu_event_set_period(event, hwc, idx))
+			continue;
+
+		if (perf_event_overflow(event, 0, &data, regs))
+			armpmu->disable(hwc, idx);
+	}
+
+	irq_work_run();
+
+	/*
+	 * Re-enable the PMU.
+	 */
+	pmnc = xscale2pmu_read_pmnc() | XSCALE_PMU_ENABLE;
+	xscale2pmu_write_pmnc(pmnc);
+
+	return IRQ_HANDLED;
+}
+
+static void
+xscale2pmu_enable_event(struct hw_perf_event *hwc, int idx)
+{
+	unsigned long flags, ien, evtsel;
+
+	ien = xscale2pmu_read_int_enable();
+	evtsel = xscale2pmu_read_event_select();
+
+	switch (idx) {
+	case XSCALE_CYCLE_COUNTER:
+		ien |= XSCALE2_CCOUNT_INT_EN;
+		break;
+	case XSCALE_COUNTER0:
+		ien |= XSCALE2_COUNT0_INT_EN;
+		evtsel &= ~XSCALE2_COUNT0_EVT_MASK;
+		evtsel |= hwc->config_base << XSCALE2_COUNT0_EVT_SHFT;
+		break;
+	case XSCALE_COUNTER1:
+		ien |= XSCALE2_COUNT1_INT_EN;
+		evtsel &= ~XSCALE2_COUNT1_EVT_MASK;
+		evtsel |= hwc->config_base << XSCALE2_COUNT1_EVT_SHFT;
+		break;
+	case XSCALE_COUNTER2:
+		ien |= XSCALE2_COUNT2_INT_EN;
+		evtsel &= ~XSCALE2_COUNT2_EVT_MASK;
+		evtsel |= hwc->config_base << XSCALE2_COUNT2_EVT_SHFT;
+		break;
+	case XSCALE_COUNTER3:
+		ien |= XSCALE2_COUNT3_INT_EN;
+		evtsel &= ~XSCALE2_COUNT3_EVT_MASK;
+		evtsel |= hwc->config_base << XSCALE2_COUNT3_EVT_SHFT;
+		break;
+	default:
+		WARN_ONCE(1, "invalid counter number (%d)\n", idx);
+		return;
+	}
+
+	raw_spin_lock_irqsave(&pmu_lock, flags);
+	xscale2pmu_write_event_select(evtsel);
+	xscale2pmu_write_int_enable(ien);
+	raw_spin_unlock_irqrestore(&pmu_lock, flags);
+}
+
+static void
+xscale2pmu_disable_event(struct hw_perf_event *hwc, int idx)
+{
+	unsigned long flags, ien, evtsel;
+
+	ien = xscale2pmu_read_int_enable();
+	evtsel = xscale2pmu_read_event_select();
+
+	switch (idx) {
+	case XSCALE_CYCLE_COUNTER:
+		ien &= ~XSCALE2_CCOUNT_INT_EN;
+		break;
+	case XSCALE_COUNTER0:
+		ien &= ~XSCALE2_COUNT0_INT_EN;
+		evtsel &= ~XSCALE2_COUNT0_EVT_MASK;
+		evtsel |= XSCALE_PERFCTR_UNUSED << XSCALE2_COUNT0_EVT_SHFT;
+		break;
+	case XSCALE_COUNTER1:
+		ien &= ~XSCALE2_COUNT1_INT_EN;
+		evtsel &= ~XSCALE2_COUNT1_EVT_MASK;
+		evtsel |= XSCALE_PERFCTR_UNUSED << XSCALE2_COUNT1_EVT_SHFT;
+		break;
+	case XSCALE_COUNTER2:
+		ien &= ~XSCALE2_COUNT2_INT_EN;
+		evtsel &= ~XSCALE2_COUNT2_EVT_MASK;
+		evtsel |= XSCALE_PERFCTR_UNUSED << XSCALE2_COUNT2_EVT_SHFT;
+		break;
+	case XSCALE_COUNTER3:
+		ien &= ~XSCALE2_COUNT3_INT_EN;
+		evtsel &= ~XSCALE2_COUNT3_EVT_MASK;
+		evtsel |= XSCALE_PERFCTR_UNUSED << XSCALE2_COUNT3_EVT_SHFT;
+		break;
+	default:
+		WARN_ONCE(1, "invalid counter number (%d)\n", idx);
+		return;
+	}
+
+	raw_spin_lock_irqsave(&pmu_lock, flags);
+	xscale2pmu_write_event_select(evtsel);
+	xscale2pmu_write_int_enable(ien);
+	raw_spin_unlock_irqrestore(&pmu_lock, flags);
+}
+
+static int
+xscale2pmu_get_event_idx(struct cpu_hw_events *cpuc,
+			struct hw_perf_event *event)
+{
+	int idx = xscale1pmu_get_event_idx(cpuc, event);
+	if (idx >= 0)
+		goto out;
+
+	if (!test_and_set_bit(XSCALE_COUNTER3, cpuc->used_mask))
+		idx = XSCALE_COUNTER3;
+	else if (!test_and_set_bit(XSCALE_COUNTER2, cpuc->used_mask))
+		idx = XSCALE_COUNTER2;
+out:
+	return idx;
+}
+
+static void
+xscale2pmu_start(void)
+{
+	unsigned long flags, val;
+
+	raw_spin_lock_irqsave(&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);
+}
+
+static void
+xscale2pmu_stop(void)
+{
+	unsigned long flags, val;
+
+	raw_spin_lock_irqsave(&pmu_lock, flags);
+	val = xscale2pmu_read_pmnc();
+	val &= ~XSCALE_PMU_ENABLE;
+	xscale2pmu_write_pmnc(val);
+	raw_spin_unlock_irqrestore(&pmu_lock, flags);
+}
+
+static inline u32
+xscale2pmu_read_counter(int counter)
+{
+	u32 val = 0;
+
+	switch (counter) {
+	case XSCALE_CYCLE_COUNTER:
+		asm volatile("mrc p14, 0, %0, c1, c1, 0" : "=r" (val));
+		break;
+	case XSCALE_COUNTER0:
+		asm volatile("mrc p14, 0, %0, c0, c2, 0" : "=r" (val));
+		break;
+	case XSCALE_COUNTER1:
+		asm volatile("mrc p14, 0, %0, c1, c2, 0" : "=r" (val));
+		break;
+	case XSCALE_COUNTER2:
+		asm volatile("mrc p14, 0, %0, c2, c2, 0" : "=r" (val));
+		break;
+	case XSCALE_COUNTER3:
+		asm volatile("mrc p14, 0, %0, c3, c2, 0" : "=r" (val));
+		break;
+	}
+
+	return val;
+}
+
+static inline void
+xscale2pmu_write_counter(int counter, u32 val)
+{
+	switch (counter) {
+	case XSCALE_CYCLE_COUNTER:
+		asm volatile("mcr p14, 0, %0, c1, c1, 0" : : "r" (val));
+		break;
+	case XSCALE_COUNTER0:
+		asm volatile("mcr p14, 0, %0, c0, c2, 0" : : "r" (val));
+		break;
+	case XSCALE_COUNTER1:
+		asm volatile("mcr p14, 0, %0, c1, c2, 0" : : "r" (val));
+		break;
+	case XSCALE_COUNTER2:
+		asm volatile("mcr p14, 0, %0, c2, c2, 0" : : "r" (val));
+		break;
+	case XSCALE_COUNTER3:
+		asm volatile("mcr p14, 0, %0, c3, c2, 0" : : "r" (val));
+		break;
+	}
+}
+
+static const struct arm_pmu xscale2pmu = {
+	.id		= ARM_PERF_PMU_ID_XSCALE2,
+	.name		= "xscale2",
+	.handle_irq	= xscale2pmu_handle_irq,
+	.enable		= xscale2pmu_enable_event,
+	.disable	= xscale2pmu_disable_event,
+	.read_counter	= xscale2pmu_read_counter,
+	.write_counter	= xscale2pmu_write_counter,
+	.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,
+	.num_events	= 5,
+	.max_period	= (1LLU << 32) - 1,
+};
+
+static const struct arm_pmu *__init xscale2pmu_init(void)
+{
+	return &xscale2pmu;
+}
+#else
+static const struct arm_pmu *__init xscale1pmu_init(void)
+{
+	return NULL;
+}
+
+static const struct arm_pmu *__init xscale2pmu_init(void)
+{
+	return NULL;
+}
+#endif	/* CONFIG_CPU_XSCALE */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/kernel/pj4-cp0.c linux-libre-2.6.38-gnu1/arch/arm/kernel/pj4-cp0.c
--- linux-libre-2.6.37-gnu1/arch/arm/kernel/pj4-cp0.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/kernel/pj4-cp0.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,94 @@
+/*
+ * linux/arch/arm/kernel/pj4-cp0.c
+ *
+ * PJ4 iWMMXt coprocessor context switching and handling
+ *
+ * Copyright (c) 2010 Marvell International 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/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <asm/thread_notify.h>
+
+static int iwmmxt_do(struct notifier_block *self, unsigned long cmd, void *t)
+{
+	struct thread_info *thread = t;
+
+	switch (cmd) {
+	case THREAD_NOTIFY_FLUSH:
+		/*
+		 * flush_thread() zeroes thread->fpstate, so no need
+		 * to do anything here.
+		 *
+		 * FALLTHROUGH: Ensure we don't try to overwrite our newly
+		 * initialised state information on the first fault.
+		 */
+
+	case THREAD_NOTIFY_EXIT:
+		iwmmxt_task_release(thread);
+		break;
+
+	case THREAD_NOTIFY_SWITCH:
+		iwmmxt_task_switch(thread);
+		break;
+	}
+
+	return NOTIFY_DONE;
+}
+
+static struct notifier_block iwmmxt_notifier_block = {
+	.notifier_call	= iwmmxt_do,
+};
+
+
+static u32 __init pj4_cp_access_read(void)
+{
+	u32 value;
+
+	__asm__ __volatile__ (
+		"mrc	p15, 0, %0, c1, c0, 2\n\t"
+		: "=r" (value));
+	return value;
+}
+
+static void __init pj4_cp_access_write(u32 value)
+{
+	u32 temp;
+
+	__asm__ __volatile__ (
+		"mcr	p15, 0, %1, c1, c0, 2\n\t"
+		"mrc	p15, 0, %0, c1, c0, 2\n\t"
+		"mov	%0, %0\n\t"
+		"sub	pc, pc, #4\n\t"
+		: "=r" (temp) : "r" (value));
+}
+
+
+/*
+ * Disable CP0/CP1 on boot, and let call_fpe() and the iWMMXt lazy
+ * switch code handle iWMMXt context switching.
+ */
+static int __init pj4_cp0_init(void)
+{
+	u32 cp_access;
+
+	cp_access = pj4_cp_access_read() & ~0xf;
+	pj4_cp_access_write(cp_access);
+
+	printk(KERN_INFO "PJ4 iWMMXt coprocessor enabled.\n");
+	elf_hwcap |= HWCAP_IWMMXT;
+	thread_register_notifier(&iwmmxt_notifier_block);
+
+	return 0;
+}
+
+late_initcall(pj4_cp0_init);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/kernel/pmu.c linux-libre-2.6.38-gnu1/arch/arm/kernel/pmu.c
--- linux-libre-2.6.37-gnu1/arch/arm/kernel/pmu.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/kernel/pmu.c	2011-03-14 21:20:32.000000000 -0400
@@ -97,28 +97,34 @@ set_irq_affinity(int irq,
 			   irq, cpu);
 	return err;
 #else
-	return 0;
+	return -EINVAL;
 #endif
 }
 
 static int
 init_cpu_pmu(void)
 {
-	int i, err = 0;
+	int i, irqs, err = 0;
 	struct platform_device *pdev = pmu_devices[ARM_PMU_DEVICE_CPU];
 
-	if (!pdev) {
-		err = -ENODEV;
-		goto out;
-	}
+	if (!pdev)
+		return -ENODEV;
 
-	for (i = 0; i < pdev->num_resources; ++i) {
+	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;
 	}
 
-out:
 	return err;
 }
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/kernel/process.c linux-libre-2.6.38-gnu1/arch/arm/kernel/process.c
--- linux-libre-2.6.37-gnu1/arch/arm/kernel/process.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/kernel/process.c	2011-03-14 21:20:32.000000000 -0400
@@ -483,6 +483,7 @@ unsigned long arch_randomize_brk(struct
 	return randomize_range(mm->brk, range_end, 0) ? : mm->brk;
 }
 
+#ifdef CONFIG_MMU
 /*
  * The vectors page is always readable from user space for the
  * atomic helpers and the signal restart code.  Let's declare a mapping
@@ -503,3 +504,4 @@ const char *arch_vma_name(struct vm_area
 {
 	return (vma->vm_start == 0xffff0000) ? "[vectors]" : NULL;
 }
+#endif
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/kernel/ptrace.c linux-libre-2.6.38-gnu1/arch/arm/kernel/ptrace.c
--- linux-libre-2.6.37-gnu1/arch/arm/kernel/ptrace.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/kernel/ptrace.c	2011-03-14 21:20:32.000000000 -0400
@@ -996,10 +996,10 @@ static int ptrace_gethbpregs(struct task
 		while (!(arch_ctrl.len & 0x1))
 			arch_ctrl.len >>= 1;
 
-		if (idx & 0x1)
-			reg = encode_ctrl_reg(arch_ctrl);
-		else
+		if (num & 0x1)
 			reg = bp->attr.bp_addr;
+		else
+			reg = encode_ctrl_reg(arch_ctrl);
 	}
 
 put:
@@ -1060,8 +1060,8 @@ static int ptrace_sethbpregs(struct task
 			goto out;
 
 		if ((gen_type & implied_type) != gen_type) {
-				ret = -EINVAL;
-				goto out;
+			ret = -EINVAL;
+			goto out;
 		}
 
 		attr.bp_len	= gen_len;
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/kernel/sched_clock.c linux-libre-2.6.38-gnu1/arch/arm/kernel/sched_clock.c
--- linux-libre-2.6.37-gnu1/arch/arm/kernel/sched_clock.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/kernel/sched_clock.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,74 @@
+/*
+ * sched_clock.c: support for extending counters to full 64-bit ns counter
+ *
+ * This program is free software; you can 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/clocksource.h>
+#include <linux/init.h>
+#include <linux/jiffies.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/timer.h>
+
+#include <asm/sched_clock.h>
+
+static void sched_clock_poll(unsigned long wrap_ticks);
+static DEFINE_TIMER(sched_clock_timer, sched_clock_poll, 0, 0);
+static void (*sched_clock_update_fn)(void);
+
+static void sched_clock_poll(unsigned long wrap_ticks)
+{
+	mod_timer(&sched_clock_timer, round_jiffies(jiffies + wrap_ticks));
+	sched_clock_update_fn();
+}
+
+void __init init_sched_clock(struct clock_data *cd, void (*update)(void),
+	unsigned int clock_bits, unsigned long rate)
+{
+	unsigned long r, w;
+	u64 res, wrap;
+	char r_unit;
+
+	sched_clock_update_fn = update;
+
+	/* calculate the mult/shift to convert counter ticks to ns. */
+	clocks_calc_mult_shift(&cd->mult, &cd->shift, rate, NSEC_PER_SEC, 0);
+
+	r = rate;
+	if (r >= 4000000) {
+		r /= 1000000;
+		r_unit = 'M';
+	} else {
+		r /= 1000;
+		r_unit = 'k';
+	}
+
+	/* calculate how many ns until we wrap */
+	wrap = cyc_to_ns((1ULL << clock_bits) - 1, cd->mult, cd->shift);
+	do_div(wrap, NSEC_PER_MSEC);
+	w = wrap;
+
+	/* calculate the ns resolution of this counter */
+	res = cyc_to_ns(1ULL, cd->mult, cd->shift);
+	pr_info("sched_clock: %u bits at %lu%cHz, resolution %lluns, wraps every %lums\n",
+		clock_bits, r, r_unit, res, w);
+
+	/*
+	 * Start the timer to keep sched_clock() properly updated and
+	 * sets the initial epoch.
+	 */
+	sched_clock_timer.data = msecs_to_jiffies(w - (w / 10));
+	update();
+
+	/*
+	 * Ensure that sched_clock() starts off at 0ns
+	 */
+	cd->epoch_ns = 0;
+}
+
+void __init sched_clock_postinit(void)
+{
+	sched_clock_poll(sched_clock_timer.data);
+}
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/kernel/setup.c linux-libre-2.6.38-gnu1/arch/arm/kernel/setup.c
--- linux-libre-2.6.37-gnu1/arch/arm/kernel/setup.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/kernel/setup.c	2011-03-14 21:20:32.000000000 -0400
@@ -75,9 +75,9 @@ extern void reboot_setup(char *str);
 
 unsigned int processor_id;
 EXPORT_SYMBOL(processor_id);
-unsigned int __machine_arch_type;
+unsigned int __machine_arch_type __read_mostly;
 EXPORT_SYMBOL(__machine_arch_type);
-unsigned int cacheid;
+unsigned int cacheid __read_mostly;
 EXPORT_SYMBOL(cacheid);
 
 unsigned int __atags_pointer __initdata;
@@ -91,24 +91,24 @@ EXPORT_SYMBOL(system_serial_low);
 unsigned int system_serial_high;
 EXPORT_SYMBOL(system_serial_high);
 
-unsigned int elf_hwcap;
+unsigned int elf_hwcap __read_mostly;
 EXPORT_SYMBOL(elf_hwcap);
 
 
 #ifdef MULTI_CPU
-struct processor processor;
+struct processor processor __read_mostly;
 #endif
 #ifdef MULTI_TLB
-struct cpu_tlb_fns cpu_tlb;
+struct cpu_tlb_fns cpu_tlb __read_mostly;
 #endif
 #ifdef MULTI_USER
-struct cpu_user_fns cpu_user;
+struct cpu_user_fns cpu_user __read_mostly;
 #endif
 #ifdef MULTI_CACHE
-struct cpu_cache_fns cpu_cache;
+struct cpu_cache_fns cpu_cache __read_mostly;
 #endif
 #ifdef CONFIG_OUTER_CACHE
-struct outer_cache_fns outer_cache;
+struct outer_cache_fns outer_cache __read_mostly;
 EXPORT_SYMBOL(outer_cache);
 #endif
 
@@ -126,6 +126,7 @@ EXPORT_SYMBOL(elf_platform);
 static const char *cpu_name;
 static const char *machine_name;
 static char __initdata cmd_line[COMMAND_LINE_SIZE];
+struct machine_desc *machine_desc __initdata;
 
 static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE;
 static union { char c[4]; unsigned long l; } endian_test __initdata = { { 'l', '?', '?', 'b' } };
@@ -225,8 +226,8 @@ int cpu_architecture(void)
 		 * Register 0 and check for VMSAv7 or PMSAv7 */
 		asm("mrc	p15, 0, %0, c0, c1, 4"
 		    : "=r" (mmfr0));
-		if ((mmfr0 & 0x0000000f) == 0x00000003 ||
-		    (mmfr0 & 0x000000f0) == 0x00000030)
+		if ((mmfr0 & 0x0000000f) >= 0x00000003 ||
+		    (mmfr0 & 0x000000f0) >= 0x00000030)
 			cpu_arch = CPU_ARCH_ARMv7;
 		else if ((mmfr0 & 0x0000000f) == 0x00000002 ||
 			 (mmfr0 & 0x000000f0) == 0x00000020)
@@ -517,25 +518,21 @@ setup_ramdisk(int doload, int prompt, in
 #endif
 }
 
-static void __init
-request_standard_resources(struct meminfo *mi, struct machine_desc *mdesc)
+static void __init request_standard_resources(struct machine_desc *mdesc)
 {
+	struct memblock_region *region;
 	struct resource *res;
-	int i;
 
 	kernel_code.start   = virt_to_phys(_text);
 	kernel_code.end     = virt_to_phys(_etext - 1);
 	kernel_data.start   = virt_to_phys(_sdata);
 	kernel_data.end     = virt_to_phys(_end - 1);
 
-	for (i = 0; i < mi->nr_banks; i++) {
-		if (mi->bank[i].size == 0)
-			continue;
-
+	for_each_memblock(memory, region) {
 		res = alloc_bootmem_low(sizeof(*res));
 		res->name  = "System RAM";
-		res->start = mi->bank[i].start;
-		res->end   = mi->bank[i].start + mi->bank[i].size - 1;
+		res->start = __pfn_to_phys(memblock_region_memory_base_pfn(region));
+		res->end = __pfn_to_phys(memblock_region_memory_end_pfn(region)) - 1;
 		res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
 
 		request_resource(&iomem_resource, res);
@@ -649,15 +646,17 @@ static int __init parse_tag_revision(con
 
 __tagtable(ATAG_REVISION, parse_tag_revision);
 
-#ifndef CONFIG_CMDLINE_FORCE
 static int __init parse_tag_cmdline(const struct tag *tag)
 {
+#ifndef CONFIG_CMDLINE_FORCE
 	strlcpy(default_command_line, tag->u.cmdline.cmdline, COMMAND_LINE_SIZE);
+#else
+	pr_warning("Ignoring tag cmdline (using the default kernel command line)\n");
+#endif /* CONFIG_CMDLINE_FORCE */
 	return 0;
 }
 
 __tagtable(ATAG_CMDLINE, parse_tag_cmdline);
-#endif /* CONFIG_CMDLINE_FORCE */
 
 /*
  * Scan the tag table for this tag, and call its parse function.
@@ -708,13 +707,11 @@ static struct init_tags {
 	{ 0, ATAG_NONE }
 };
 
-static void (*init_machine)(void) __initdata;
-
 static int __init customize_machine(void)
 {
 	/* customizes platform devices, or adds new ones */
-	if (init_machine)
-		init_machine();
+	if (machine_desc->init_machine)
+		machine_desc->init_machine();
 	return 0;
 }
 arch_initcall(customize_machine);
@@ -809,6 +806,7 @@ void __init setup_arch(char **cmdline_p)
 
 	setup_processor();
 	mdesc = setup_machine(machine_arch_type);
+	machine_desc = mdesc;
 	machine_name = mdesc->name;
 
 	if (mdesc->soft_reboot)
@@ -857,7 +855,7 @@ void __init setup_arch(char **cmdline_p)
 	arm_memblock_init(&meminfo, mdesc);
 
 	paging_init(mdesc);
-	request_standard_resources(&meminfo, mdesc);
+	request_standard_resources(mdesc);
 
 #ifdef CONFIG_SMP
 	if (is_smp())
@@ -868,13 +866,9 @@ void __init setup_arch(char **cmdline_p)
 	cpu_init();
 	tcm_init();
 
-	/*
-	 * Set up various architecture-specific pointers
-	 */
-	arch_nr_irqs = mdesc->nr_irqs;
-	init_arch_irq = mdesc->init_irq;
-	system_timer = mdesc->timer;
-	init_machine = mdesc->init_machine;
+#ifdef CONFIG_MULTI_IRQ_HANDLER
+	handle_arch_irq = mdesc->handle_irq;
+#endif
 
 #ifdef CONFIG_VT
 #if defined(CONFIG_VGA_CONSOLE)
@@ -884,6 +878,9 @@ void __init setup_arch(char **cmdline_p)
 #endif
 #endif
 	early_trap_init();
+
+	if (mdesc->init_early)
+		mdesc->init_early();
 }
 
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/kernel/signal.c linux-libre-2.6.38-gnu1/arch/arm/kernel/signal.c
--- linux-libre-2.6.37-gnu1/arch/arm/kernel/signal.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/kernel/signal.c	2011-03-14 21:20:32.000000000 -0400
@@ -474,7 +474,9 @@ setup_return(struct pt_regs *regs, struc
 	unsigned long handler = (unsigned long)ka->sa.sa_handler;
 	unsigned long retcode;
 	int thumb = 0;
-	unsigned long cpsr = regs->ARM_cpsr & ~PSR_f;
+	unsigned long cpsr = regs->ARM_cpsr & ~(PSR_f | PSR_E_BIT);
+
+	cpsr |= PSR_ENDSTATE;
 
 	/*
 	 * Maybe we need to deliver a 32-bit signal to a 26-bit task.
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/kernel/smp.c linux-libre-2.6.38-gnu1/arch/arm/kernel/smp.c
--- linux-libre-2.6.37-gnu1/arch/arm/kernel/smp.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/kernel/smp.c	2011-03-14 21:20:32.000000000 -0400
@@ -16,6 +16,7 @@
 #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>
@@ -24,6 +25,7 @@
 #include <linux/irq.h>
 #include <linux/percpu.h>
 #include <linux/clockchips.h>
+#include <linux/completion.h>
 
 #include <asm/atomic.h>
 #include <asm/cacheflush.h>
@@ -37,7 +39,6 @@
 #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
@@ -46,64 +47,14 @@
  */
 struct secondary_data secondary_data;
 
-/*
- * structures for inter-processor calls
- * - A collection of single bit ipi messages.
- */
-struct ipi_data {
-	spinlock_t lock;
-	unsigned long ipi_count;
-	unsigned long bits;
-};
-
-static DEFINE_PER_CPU(struct ipi_data, ipi_data) = {
-	.lock	= SPIN_LOCK_UNLOCKED,
-};
-
 enum ipi_msg_type {
-	IPI_TIMER,
+	IPI_TIMER = 2,
 	IPI_RESCHEDULE,
 	IPI_CALL_FUNC,
 	IPI_CALL_FUNC_SINGLE,
 	IPI_CPU_STOP,
 };
 
-static inline void identity_mapping_add(pgd_t *pgd, unsigned long start,
-	unsigned long end)
-{
-	unsigned long addr, prot;
-	pmd_t *pmd;
-
-	prot = PMD_TYPE_SECT | PMD_SECT_AP_WRITE;
-	if (cpu_architecture() <= CPU_ARCH_ARMv5TEJ && !cpu_is_xscale())
-		prot |= PMD_BIT4;
-
-	for (addr = start & PGDIR_MASK; addr < end;) {
-		pmd = pmd_offset(pgd + pgd_index(addr), addr);
-		pmd[0] = __pmd(addr | prot);
-		addr += SECTION_SIZE;
-		pmd[1] = __pmd(addr | prot);
-		addr += SECTION_SIZE;
-		flush_pmd_entry(pmd);
-		outer_clean_range(__pa(pmd), __pa(pmd + 1));
-	}
-}
-
-static inline void identity_mapping_del(pgd_t *pgd, unsigned long start,
-	unsigned long end)
-{
-	unsigned long addr;
-	pmd_t *pmd;
-
-	for (addr = start & PGDIR_MASK; addr < end; addr += PGDIR_SIZE) {
-		pmd = pmd_offset(pgd + pgd_index(addr), addr);
-		pmd[0] = __pmd(0);
-		pmd[1] = __pmd(0);
-		clean_pmd_entry(pmd);
-		outer_clean_range(__pa(pmd), __pa(pmd + 1));
-	}
-}
-
 int __cpuinit __cpu_up(unsigned int cpu)
 {
 	struct cpuinfo_arm *ci = &per_cpu(cpu_data, cpu);
@@ -177,8 +128,12 @@ int __cpuinit __cpu_up(unsigned int cpu)
 			barrier();
 		}
 
-		if (!cpu_online(cpu))
+		if (!cpu_online(cpu)) {
+			pr_crit("CPU%u: failed to come online\n", cpu);
 			ret = -EIO;
+		}
+	} else {
+		pr_err("CPU%u: failed to boot: %d\n", cpu, ret);
 	}
 
 	secondary_data.stack = NULL;
@@ -194,18 +149,12 @@ int __cpuinit __cpu_up(unsigned int cpu)
 
 	pgd_free(&init_mm, pgd);
 
-	if (ret) {
-		printk(KERN_CRIT "CPU%u: processor failed to boot\n", cpu);
-
-		/*
-		 * FIXME: We need to clean up the new idle thread. --rmk
-		 */
-	}
-
 	return ret;
 }
 
 #ifdef CONFIG_HOTPLUG_CPU
+static void percpu_timer_stop(void);
+
 /*
  * __cpu_disable runs on the processor to be shutdown.
  */
@@ -233,7 +182,7 @@ int __cpu_disable(void)
 	/*
 	 * Stop the local timer for this CPU.
 	 */
-	local_timer_stop();
+	percpu_timer_stop();
 
 	/*
 	 * Flush user cache and TLB mappings, and then remove this CPU
@@ -252,12 +201,20 @@ int __cpu_disable(void)
 	return 0;
 }
 
+static DECLARE_COMPLETION(cpu_died);
+
 /*
  * called on the thread which is asking for a CPU to be shutdown -
  * waits until shutdown has completed, or it is timed out.
  */
 void __cpu_die(unsigned int cpu)
 {
+	if (!wait_for_completion_timeout(&cpu_died, msecs_to_jiffies(5000))) {
+		pr_err("CPU%u: cpu didn't die\n", cpu);
+		return;
+	}
+	printk(KERN_NOTICE "CPU%u: shutdown\n", cpu);
+
 	if (!platform_cpu_kill(cpu))
 		printk("CPU%u: unable to kill\n", cpu);
 }
@@ -274,12 +231,17 @@ void __ref cpu_die(void)
 {
 	unsigned int cpu = smp_processor_id();
 
-	local_irq_disable();
 	idle_task_exit();
 
+	local_irq_disable();
+	mb();
+
+	/* Tell __cpu_die() that this CPU is now safe to dispose of */
+	complete(&cpu_died);
+
 	/*
 	 * actual CPU shutdown procedure is at least platform (if not
-	 * CPU) specific
+	 * CPU) specific.
 	 */
 	platform_cpu_die(cpu);
 
@@ -289,6 +251,7 @@ void __ref cpu_die(void)
 	 * to be repeated to undo the effects of taking the CPU offline.
 	 */
 	__asm__("mov	sp, %0\n"
+	"	mov	fp, #0\n"
 	"	b	secondary_start_kernel"
 		:
 		: "r" (task_stack_page(current) + THREAD_SIZE - 8));
@@ -296,6 +259,17 @@ void __ref cpu_die(void)
 #endif /* CONFIG_HOTPLUG_CPU */
 
 /*
+ * Called by both boot and secondaries to move global data into
+ * per-processor storage.
+ */
+static void __cpuinit smp_store_cpu_info(unsigned int cpuid)
+{
+	struct cpuinfo_arm *cpu_info = &per_cpu(cpu_data, cpuid);
+
+	cpu_info->loops_per_jiffy = loops_per_jiffy;
+}
+
+/*
  * This is the secondary CPU boot entry.  We're using this CPUs
  * idle thread stack, but a set of temporary page tables.
  */
@@ -319,6 +293,7 @@ asmlinkage void __cpuinit secondary_star
 
 	cpu_init();
 	preempt_disable();
+	trace_hardirqs_off();
 
 	/*
 	 * Give the platform a chance to do its own initialisation.
@@ -352,17 +327,6 @@ asmlinkage void __cpuinit secondary_star
 	cpu_idle();
 }
 
-/*
- * Called by both boot and secondaries to move global data into
- * per-processor storage.
- */
-void __cpuinit smp_store_cpu_info(unsigned int cpuid)
-{
-	struct cpuinfo_arm *cpu_info = &per_cpu(cpu_data, cpuid);
-
-	cpu_info->loops_per_jiffy = loops_per_jiffy;
-}
-
 void __init smp_cpus_done(unsigned int max_cpus)
 {
 	int cpu;
@@ -385,61 +349,80 @@ void __init smp_prepare_boot_cpu(void)
 	per_cpu(cpu_data, cpu).idle = current;
 }
 
-static void send_ipi_message(const struct cpumask *mask, enum ipi_msg_type msg)
+void __init smp_prepare_cpus(unsigned int max_cpus)
 {
-	unsigned long flags;
-	unsigned int cpu;
-
-	local_irq_save(flags);
-
-	for_each_cpu(cpu, mask) {
-		struct ipi_data *ipi = &per_cpu(ipi_data, cpu);
+	unsigned int ncores = num_possible_cpus();
 
-		spin_lock(&ipi->lock);
-		ipi->bits |= 1 << msg;
-		spin_unlock(&ipi->lock);
-	}
+	smp_store_cpu_info(smp_processor_id());
 
 	/*
-	 * Call the platform specific cross-CPU call function.
+	 * are we trying to boot more cores than exist?
 	 */
-	smp_cross_call(mask);
+	if (max_cpus > ncores)
+		max_cpus = ncores;
 
-	local_irq_restore(flags);
+	if (max_cpus > 1) {
+		/*
+		 * Enable the local timer or broadcast device for the
+		 * boot CPU, but only if we have more than one CPU.
+		 */
+		percpu_timer_setup();
+
+		/*
+		 * Initialise the SCU if there are more than one CPU
+		 * and let them know where to start.
+		 */
+		platform_smp_prepare_cpus(max_cpus);
+	}
 }
 
 void arch_send_call_function_ipi_mask(const struct cpumask *mask)
 {
-	send_ipi_message(mask, IPI_CALL_FUNC);
+	smp_cross_call(mask, IPI_CALL_FUNC);
 }
 
 void arch_send_call_function_single_ipi(int cpu)
 {
-	send_ipi_message(cpumask_of(cpu), IPI_CALL_FUNC_SINGLE);
+	smp_cross_call(cpumask_of(cpu), IPI_CALL_FUNC_SINGLE);
 }
 
-void show_ipi_list(struct seq_file *p)
+static const char *ipi_types[NR_IPI] = {
+#define S(x,s)	[x - IPI_TIMER] = s
+	S(IPI_TIMER, "Timer broadcast interrupts"),
+	S(IPI_RESCHEDULE, "Rescheduling interrupts"),
+	S(IPI_CALL_FUNC, "Function call interrupts"),
+	S(IPI_CALL_FUNC_SINGLE, "Single function call interrupts"),
+	S(IPI_CPU_STOP, "CPU stop interrupts"),
+};
+
+void show_ipi_list(struct seq_file *p, int prec)
 {
-	unsigned int cpu;
+	unsigned int cpu, i;
 
-	seq_puts(p, "IPI:");
+	for (i = 0; i < NR_IPI; i++) {
+		seq_printf(p, "%*s%u: ", prec - 1, "IPI", i);
 
-	for_each_present_cpu(cpu)
-		seq_printf(p, " %10lu", per_cpu(ipi_data, cpu).ipi_count);
+		for_each_present_cpu(cpu)
+			seq_printf(p, "%10u ",
+				   __get_irq_stat(cpu, ipi_irqs[i]));
 
-	seq_putc(p, '\n');
+		seq_printf(p, " %s\n", ipi_types[i]);
+	}
 }
 
-void show_local_irqs(struct seq_file *p)
+u64 smp_irq_stat_cpu(unsigned int cpu)
 {
-	unsigned int cpu;
+	u64 sum = 0;
+	int i;
 
-	seq_printf(p, "LOC: ");
+	for (i = 0; i < NR_IPI; i++)
+		sum += __get_irq_stat(cpu, ipi_irqs[i]);
 
-	for_each_present_cpu(cpu)
-		seq_printf(p, "%10u ", irq_stat[cpu].local_timer_irqs);
+#ifdef CONFIG_LOCAL_TIMERS
+	sum += __get_irq_stat(cpu, local_timer_irqs);
+#endif
 
-	seq_putc(p, '\n');
+	return sum;
 }
 
 /*
@@ -456,24 +439,36 @@ static void ipi_timer(void)
 }
 
 #ifdef CONFIG_LOCAL_TIMERS
-asmlinkage void __exception do_local_timer(struct pt_regs *regs)
+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()) {
-		irq_stat[cpu].local_timer_irqs++;
+		__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)
 {
-	send_ipi_message(mask, IPI_TIMER);
+	smp_cross_call(mask, IPI_TIMER);
 }
 #else
 #define smp_timer_broadcast	NULL
@@ -510,6 +505,21 @@ void __cpuinit percpu_timer_setup(void)
 	local_timer_setup(evt);
 }
 
+#ifdef CONFIG_HOTPLUG_CPU
+/*
+ * The generic clock events code purposely does not stop the local timer
+ * on CPU_DEAD/CPU_DEAD_FROZEN hotplug events, so we have to do it
+ * manually here.
+ */
+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);
+}
+#endif
+
 static DEFINE_SPINLOCK(stop_lock);
 
 /*
@@ -536,216 +546,76 @@ static void ipi_cpu_stop(unsigned int cp
 
 /*
  * Main handler for inter-processor interrupts
- *
- * For ARM, the ipimask now only identifies a single
- * category of IPI (Bit 1 IPIs have been replaced by a
- * different mechanism):
- *
- *  Bit 0 - Inter-processor function call
  */
-asmlinkage void __exception do_IPI(struct pt_regs *regs)
+asmlinkage void __exception_irq_entry do_IPI(int ipinr, struct pt_regs *regs)
 {
 	unsigned int cpu = smp_processor_id();
-	struct ipi_data *ipi = &per_cpu(ipi_data, cpu);
 	struct pt_regs *old_regs = set_irq_regs(regs);
 
-	ipi->ipi_count++;
-
-	for (;;) {
-		unsigned long msgs;
-
-		spin_lock(&ipi->lock);
-		msgs = ipi->bits;
-		ipi->bits = 0;
-		spin_unlock(&ipi->lock);
-
-		if (!msgs)
-			break;
-
-		do {
-			unsigned nextmsg;
-
-			nextmsg = msgs & -msgs;
-			msgs &= ~nextmsg;
-			nextmsg = ffz(~nextmsg);
+	if (ipinr >= IPI_TIMER && ipinr < IPI_TIMER + NR_IPI)
+		__inc_irq_stat(cpu, ipi_irqs[ipinr - IPI_TIMER]);
 
-			switch (nextmsg) {
-			case IPI_TIMER:
-				ipi_timer();
-				break;
+	switch (ipinr) {
+	case IPI_TIMER:
+		ipi_timer();
+		break;
 
-			case IPI_RESCHEDULE:
-				/*
-				 * nothing more to do - eveything is
-				 * done on the interrupt return path
-				 */
-				break;
+	case IPI_RESCHEDULE:
+		/*
+		 * nothing more to do - eveything is
+		 * done on the interrupt return path
+		 */
+		break;
 
-			case IPI_CALL_FUNC:
-				generic_smp_call_function_interrupt();
-				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_CALL_FUNC_SINGLE:
+		generic_smp_call_function_single_interrupt();
+		break;
 
-			case IPI_CPU_STOP:
-				ipi_cpu_stop(cpu);
-				break;
+	case IPI_CPU_STOP:
+		ipi_cpu_stop(cpu);
+		break;
 
-			default:
-				printk(KERN_CRIT "CPU%u: Unknown IPI message 0x%x\n",
-				       cpu, nextmsg);
-				break;
-			}
-		} while (msgs);
+	default:
+		printk(KERN_CRIT "CPU%u: Unknown IPI message 0x%x\n",
+		       cpu, ipinr);
+		break;
 	}
-
 	set_irq_regs(old_regs);
 }
 
 void smp_send_reschedule(int cpu)
 {
-	send_ipi_message(cpumask_of(cpu), IPI_RESCHEDULE);
+	smp_cross_call(cpumask_of(cpu), IPI_RESCHEDULE);
 }
 
 void smp_send_stop(void)
 {
-	cpumask_t mask = cpu_online_map;
-	cpu_clear(smp_processor_id(), mask);
-	if (!cpus_empty(mask))
-		send_ipi_message(&mask, IPI_CPU_STOP);
-}
+	unsigned long timeout;
 
-/*
- * not supported here
- */
-int setup_profiling_timer(unsigned int multiplier)
-{
-	return -EINVAL;
-}
+	if (num_online_cpus() > 1) {
+		cpumask_t mask = cpu_online_map;
+		cpu_clear(smp_processor_id(), mask);
 
-static void
-on_each_cpu_mask(void (*func)(void *), void *info, int wait,
-		const struct cpumask *mask)
-{
-	preempt_disable();
+		smp_cross_call(&mask, IPI_CPU_STOP);
+	}
 
-	smp_call_function_many(mask, func, info, wait);
-	if (cpumask_test_cpu(smp_processor_id(), mask))
-		func(info);
+	/* Wait up to one second for other CPUs to stop */
+	timeout = USEC_PER_SEC;
+	while (num_online_cpus() > 1 && timeout--)
+		udelay(1);
 
-	preempt_enable();
+	if (num_online_cpus() > 1)
+		pr_warning("SMP: failed to stop secondary CPUs\n");
 }
 
-/**********************************************************************/
-
 /*
- * TLB operations
+ * not supported here
  */
-struct tlb_args {
-	struct vm_area_struct *ta_vma;
-	unsigned long ta_start;
-	unsigned long ta_end;
-};
-
-static inline void ipi_flush_tlb_all(void *ignored)
-{
-	local_flush_tlb_all();
-}
-
-static inline void ipi_flush_tlb_mm(void *arg)
-{
-	struct mm_struct *mm = (struct mm_struct *)arg;
-
-	local_flush_tlb_mm(mm);
-}
-
-static inline void ipi_flush_tlb_page(void *arg)
-{
-	struct tlb_args *ta = (struct tlb_args *)arg;
-
-	local_flush_tlb_page(ta->ta_vma, ta->ta_start);
-}
-
-static inline void ipi_flush_tlb_kernel_page(void *arg)
-{
-	struct tlb_args *ta = (struct tlb_args *)arg;
-
-	local_flush_tlb_kernel_page(ta->ta_start);
-}
-
-static inline void ipi_flush_tlb_range(void *arg)
-{
-	struct tlb_args *ta = (struct tlb_args *)arg;
-
-	local_flush_tlb_range(ta->ta_vma, ta->ta_start, ta->ta_end);
-}
-
-static inline void ipi_flush_tlb_kernel_range(void *arg)
-{
-	struct tlb_args *ta = (struct tlb_args *)arg;
-
-	local_flush_tlb_kernel_range(ta->ta_start, ta->ta_end);
-}
-
-void flush_tlb_all(void)
-{
-	if (tlb_ops_need_broadcast())
-		on_each_cpu(ipi_flush_tlb_all, NULL, 1);
-	else
-		local_flush_tlb_all();
-}
-
-void flush_tlb_mm(struct mm_struct *mm)
-{
-	if (tlb_ops_need_broadcast())
-		on_each_cpu_mask(ipi_flush_tlb_mm, mm, 1, mm_cpumask(mm));
-	else
-		local_flush_tlb_mm(mm);
-}
-
-void flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr)
-{
-	if (tlb_ops_need_broadcast()) {
-		struct tlb_args ta;
-		ta.ta_vma = vma;
-		ta.ta_start = uaddr;
-		on_each_cpu_mask(ipi_flush_tlb_page, &ta, 1, mm_cpumask(vma->vm_mm));
-	} else
-		local_flush_tlb_page(vma, uaddr);
-}
-
-void flush_tlb_kernel_page(unsigned long kaddr)
-{
-	if (tlb_ops_need_broadcast()) {
-		struct tlb_args ta;
-		ta.ta_start = kaddr;
-		on_each_cpu(ipi_flush_tlb_kernel_page, &ta, 1);
-	} else
-		local_flush_tlb_kernel_page(kaddr);
-}
-
-void flush_tlb_range(struct vm_area_struct *vma,
-                     unsigned long start, unsigned long end)
-{
-	if (tlb_ops_need_broadcast()) {
-		struct tlb_args ta;
-		ta.ta_vma = vma;
-		ta.ta_start = start;
-		ta.ta_end = end;
-		on_each_cpu_mask(ipi_flush_tlb_range, &ta, 1, mm_cpumask(vma->vm_mm));
-	} else
-		local_flush_tlb_range(vma, start, end);
-}
-
-void flush_tlb_kernel_range(unsigned long start, unsigned long end)
+int setup_profiling_timer(unsigned int multiplier)
 {
-	if (tlb_ops_need_broadcast()) {
-		struct tlb_args ta;
-		ta.ta_start = start;
-		ta.ta_end = end;
-		on_each_cpu(ipi_flush_tlb_kernel_range, &ta, 1);
-	} else
-		local_flush_tlb_kernel_range(start, end);
+	return -EINVAL;
 }
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/kernel/smp_tlb.c linux-libre-2.6.38-gnu1/arch/arm/kernel/smp_tlb.c
--- linux-libre-2.6.37-gnu1/arch/arm/kernel/smp_tlb.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/kernel/smp_tlb.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,139 @@
+/*
+ *  linux/arch/arm/kernel/smp_tlb.c
+ *
+ *  Copyright (C) 2002 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/preempt.h>
+#include <linux/smp.h>
+
+#include <asm/smp_plat.h>
+#include <asm/tlbflush.h>
+
+static void on_each_cpu_mask(void (*func)(void *), void *info, int wait,
+	const struct cpumask *mask)
+{
+	preempt_disable();
+
+	smp_call_function_many(mask, func, info, wait);
+	if (cpumask_test_cpu(smp_processor_id(), mask))
+		func(info);
+
+	preempt_enable();
+}
+
+/**********************************************************************/
+
+/*
+ * TLB operations
+ */
+struct tlb_args {
+	struct vm_area_struct *ta_vma;
+	unsigned long ta_start;
+	unsigned long ta_end;
+};
+
+static inline void ipi_flush_tlb_all(void *ignored)
+{
+	local_flush_tlb_all();
+}
+
+static inline void ipi_flush_tlb_mm(void *arg)
+{
+	struct mm_struct *mm = (struct mm_struct *)arg;
+
+	local_flush_tlb_mm(mm);
+}
+
+static inline void ipi_flush_tlb_page(void *arg)
+{
+	struct tlb_args *ta = (struct tlb_args *)arg;
+
+	local_flush_tlb_page(ta->ta_vma, ta->ta_start);
+}
+
+static inline void ipi_flush_tlb_kernel_page(void *arg)
+{
+	struct tlb_args *ta = (struct tlb_args *)arg;
+
+	local_flush_tlb_kernel_page(ta->ta_start);
+}
+
+static inline void ipi_flush_tlb_range(void *arg)
+{
+	struct tlb_args *ta = (struct tlb_args *)arg;
+
+	local_flush_tlb_range(ta->ta_vma, ta->ta_start, ta->ta_end);
+}
+
+static inline void ipi_flush_tlb_kernel_range(void *arg)
+{
+	struct tlb_args *ta = (struct tlb_args *)arg;
+
+	local_flush_tlb_kernel_range(ta->ta_start, ta->ta_end);
+}
+
+void flush_tlb_all(void)
+{
+	if (tlb_ops_need_broadcast())
+		on_each_cpu(ipi_flush_tlb_all, NULL, 1);
+	else
+		local_flush_tlb_all();
+}
+
+void flush_tlb_mm(struct mm_struct *mm)
+{
+	if (tlb_ops_need_broadcast())
+		on_each_cpu_mask(ipi_flush_tlb_mm, mm, 1, mm_cpumask(mm));
+	else
+		local_flush_tlb_mm(mm);
+}
+
+void flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr)
+{
+	if (tlb_ops_need_broadcast()) {
+		struct tlb_args ta;
+		ta.ta_vma = vma;
+		ta.ta_start = uaddr;
+		on_each_cpu_mask(ipi_flush_tlb_page, &ta, 1, mm_cpumask(vma->vm_mm));
+	} else
+		local_flush_tlb_page(vma, uaddr);
+}
+
+void flush_tlb_kernel_page(unsigned long kaddr)
+{
+	if (tlb_ops_need_broadcast()) {
+		struct tlb_args ta;
+		ta.ta_start = kaddr;
+		on_each_cpu(ipi_flush_tlb_kernel_page, &ta, 1);
+	} else
+		local_flush_tlb_kernel_page(kaddr);
+}
+
+void flush_tlb_range(struct vm_area_struct *vma,
+                     unsigned long start, unsigned long end)
+{
+	if (tlb_ops_need_broadcast()) {
+		struct tlb_args ta;
+		ta.ta_vma = vma;
+		ta.ta_start = start;
+		ta.ta_end = end;
+		on_each_cpu_mask(ipi_flush_tlb_range, &ta, 1, mm_cpumask(vma->vm_mm));
+	} else
+		local_flush_tlb_range(vma, start, end);
+}
+
+void flush_tlb_kernel_range(unsigned long start, unsigned long end)
+{
+	if (tlb_ops_need_broadcast()) {
+		struct tlb_args ta;
+		ta.ta_start = start;
+		ta.ta_end = end;
+		on_each_cpu(ipi_flush_tlb_kernel_range, &ta, 1);
+	} else
+		local_flush_tlb_kernel_range(start, end);
+}
+
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/kernel/smp_twd.c linux-libre-2.6.38-gnu1/arch/arm/kernel/smp_twd.c
--- linux-libre-2.6.37-gnu1/arch/arm/kernel/smp_twd.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/kernel/smp_twd.c	2011-03-14 21:20:32.000000000 -0400
@@ -36,6 +36,7 @@ static void twd_set_mode(enum clock_even
 		/* timer load already set up */
 		ctrl = TWD_TIMER_CONTROL_ENABLE | TWD_TIMER_CONTROL_IT_ENABLE
 			| TWD_TIMER_CONTROL_PERIODIC;
+		__raw_writel(twd_timer_rate / HZ, twd_base + TWD_TIMER_LOAD);
 		break;
 	case CLOCK_EVT_MODE_ONESHOT:
 		/* period set, and timer enabled in 'next_event' hook */
@@ -81,7 +82,7 @@ int twd_timer_ack(void)
 
 static void __cpuinit twd_calibrate_rate(void)
 {
-	unsigned long load, count;
+	unsigned long count;
 	u64 waitjiffies;
 
 	/*
@@ -114,12 +115,8 @@ static void __cpuinit twd_calibrate_rate
 		twd_timer_rate = (0xFFFFFFFFU - count) * (HZ / 5);
 
 		printk("%lu.%02luMHz.\n", twd_timer_rate / 1000000,
-			(twd_timer_rate / 100000) % 100);
+			(twd_timer_rate / 1000000) % 100);
 	}
-
-	load = twd_timer_rate / HZ;
-
-	__raw_writel(load, twd_base + TWD_TIMER_LOAD);
 }
 
 /*
@@ -127,8 +124,6 @@ static void __cpuinit twd_calibrate_rate
  */
 void __cpuinit twd_timer_setup(struct clock_event_device *clk)
 {
-	unsigned long flags;
-
 	twd_calibrate_rate();
 
 	clk->name = "local_timer";
@@ -143,20 +138,7 @@ void __cpuinit twd_timer_setup(struct cl
 	clk->min_delta_ns = clockevent_delta2ns(0xf, clk);
 
 	/* Make sure our local interrupt controller has this enabled */
-	local_irq_save(flags);
-	irq_to_desc(clk->irq)->status |= IRQ_NOPROBE;
-	get_irq_chip(clk->irq)->unmask(clk->irq);
-	local_irq_restore(flags);
+	gic_enable_ppi(clk->irq);
 
 	clockevents_register_device(clk);
 }
-
-#ifdef CONFIG_HOTPLUG_CPU
-/*
- * take a local timer down
- */
-void twd_timer_stop(void)
-{
-	__raw_writel(0, twd_base + TWD_TIMER_CONTROL);
-}
-#endif
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/kernel/stacktrace.c linux-libre-2.6.38-gnu1/arch/arm/kernel/stacktrace.c
--- linux-libre-2.6.37-gnu1/arch/arm/kernel/stacktrace.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/kernel/stacktrace.c	2011-03-14 21:20:32.000000000 -0400
@@ -94,10 +94,13 @@ void save_stack_trace_tsk(struct task_st
 	if (tsk != current) {
 #ifdef CONFIG_SMP
 		/*
-		 * What guarantees do we have here that 'tsk'
-		 * is not running on another CPU?
+		 * What guarantees do we have here that 'tsk' is not
+		 * running on another CPU?  For now, ignore it as we
+		 * can't guarantee we won't explode.
 		 */
-		BUG();
+		if (trace->nr_entries < trace->max_entries)
+			trace->entries[trace->nr_entries++] = ULONG_MAX;
+		return;
 #else
 		data.no_sched_functions = 1;
 		frame.fp = thread_saved_fp(tsk);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/kernel/swp_emulate.c linux-libre-2.6.38-gnu1/arch/arm/kernel/swp_emulate.c
--- linux-libre-2.6.37-gnu1/arch/arm/kernel/swp_emulate.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/kernel/swp_emulate.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,267 @@
+/*
+ *  linux/arch/arm/kernel/swp_emulate.c
+ *
+ *  Copyright (C) 2009 ARM Limited
+ *  __user_* functions adapted from include/asm/uaccess.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.
+ *
+ *  Implements emulation of the SWP/SWPB instructions using load-exclusive and
+ *  store-exclusive for processors that have them disabled (or future ones that
+ *  might not implement them).
+ *
+ *  Syntax of SWP{B} instruction: SWP{B}<c> <Rt>, <Rt2>, [<Rn>]
+ *  Where: Rt  = destination
+ *	   Rt2 = source
+ *	   Rn  = address
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/proc_fs.h>
+#include <linux/sched.h>
+#include <linux/syscalls.h>
+#include <linux/perf_event.h>
+
+#include <asm/traps.h>
+#include <asm/uaccess.h>
+
+/*
+ * Error-checking SWP macros implemented using ldrex{b}/strex{b}
+ */
+#define __user_swpX_asm(data, addr, res, temp, B)		\
+	__asm__ __volatile__(					\
+	"	mov		%2, %1\n"			\
+	"0:	ldrex"B"	%1, [%3]\n"			\
+	"1:	strex"B"	%0, %2, [%3]\n"			\
+	"	cmp		%0, #0\n"			\
+	"	movne		%0, %4\n"			\
+	"2:\n"							\
+	"	.section	 .fixup,\"ax\"\n"		\
+	"	.align		2\n"				\
+	"3:	mov		%0, %5\n"			\
+	"	b		2b\n"				\
+	"	.previous\n"					\
+	"	.section	 __ex_table,\"a\"\n"		\
+	"	.align		3\n"				\
+	"	.long		0b, 3b\n"			\
+	"	.long		1b, 3b\n"			\
+	"	.previous"					\
+	: "=&r" (res), "+r" (data), "=&r" (temp)		\
+	: "r" (addr), "i" (-EAGAIN), "i" (-EFAULT)		\
+	: "cc", "memory")
+
+#define __user_swp_asm(data, addr, res, temp) \
+	__user_swpX_asm(data, addr, res, temp, "")
+#define __user_swpb_asm(data, addr, res, temp) \
+	__user_swpX_asm(data, addr, res, temp, "b")
+
+/*
+ * Macros/defines for extracting register numbers from instruction.
+ */
+#define EXTRACT_REG_NUM(instruction, offset) \
+	(((instruction) & (0xf << (offset))) >> (offset))
+#define RN_OFFSET  16
+#define RT_OFFSET  12
+#define RT2_OFFSET  0
+/*
+ * Bit 22 of the instruction encoding distinguishes between
+ * the SWP and SWPB variants (bit set means SWPB).
+ */
+#define TYPE_SWPB (1 << 22)
+
+static unsigned long swpcounter;
+static unsigned long swpbcounter;
+static unsigned long abtcounter;
+static pid_t         previous_pid;
+
+#ifdef CONFIG_PROC_FS
+static int proc_read_status(char *page, char **start, off_t off, int count,
+			    int *eof, void *data)
+{
+	char *p = page;
+	int len;
+
+	p += sprintf(p, "Emulated SWP:\t\t%lu\n", swpcounter);
+	p += sprintf(p, "Emulated SWPB:\t\t%lu\n", swpbcounter);
+	p += sprintf(p, "Aborted SWP{B}:\t\t%lu\n", abtcounter);
+	if (previous_pid != 0)
+		p += sprintf(p, "Last process:\t\t%d\n", previous_pid);
+
+	len = (p - page) - off;
+	if (len < 0)
+		len = 0;
+
+	*eof = (len <= count) ? 1 : 0;
+	*start = page + off;
+
+	return len;
+}
+#endif
+
+/*
+ * Set up process info to signal segmentation fault - called on access error.
+ */
+static void set_segfault(struct pt_regs *regs, unsigned long addr)
+{
+	siginfo_t info;
+
+	if (find_vma(current->mm, addr) == NULL)
+		info.si_code = SEGV_MAPERR;
+	else
+		info.si_code = SEGV_ACCERR;
+
+	info.si_signo = SIGSEGV;
+	info.si_errno = 0;
+	info.si_addr  = (void *) instruction_pointer(regs);
+
+	pr_debug("SWP{B} emulation: access caused memory abort!\n");
+	arm_notify_die("Illegal memory access", regs, &info, 0, 0);
+
+	abtcounter++;
+}
+
+static int emulate_swpX(unsigned int address, unsigned int *data,
+			unsigned int type)
+{
+	unsigned int res = 0;
+
+	if ((type != TYPE_SWPB) && (address & 0x3)) {
+		/* SWP to unaligned address not permitted */
+		pr_debug("SWP instruction on unaligned pointer!\n");
+		return -EFAULT;
+	}
+
+	while (1) {
+		unsigned long temp;
+
+		/*
+		 * Barrier required between accessing protected resource and
+		 * releasing a lock for it. Legacy code might not have done
+		 * this, and we cannot determine that this is not the case
+		 * being emulated, so insert always.
+		 */
+		smp_mb();
+
+		if (type == TYPE_SWPB)
+			__user_swpb_asm(*data, address, res, temp);
+		else
+			__user_swp_asm(*data, address, res, temp);
+
+		if (likely(res != -EAGAIN) || signal_pending(current))
+			break;
+
+		cond_resched();
+	}
+
+	if (res == 0) {
+		/*
+		 * Barrier also required between aquiring a lock for a
+		 * protected resource and accessing the resource. Inserted for
+		 * same reason as above.
+		 */
+		smp_mb();
+
+		if (type == TYPE_SWPB)
+			swpbcounter++;
+		else
+			swpcounter++;
+	}
+
+	return res;
+}
+
+/*
+ * swp_handler logs the id of calling process, dissects the instruction, sanity
+ * checks the memory location, calls emulate_swpX for the actual operation and
+ * deals with fixup/error handling before returning
+ */
+static int swp_handler(struct pt_regs *regs, unsigned int instr)
+{
+	unsigned int address, destreg, data, type;
+	unsigned int res = 0;
+
+	perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, 0, regs, regs->ARM_pc);
+
+	if (current->pid != previous_pid) {
+		pr_debug("\"%s\" (%ld) uses deprecated SWP{B} instruction\n",
+			 current->comm, (unsigned long)current->pid);
+		previous_pid = current->pid;
+	}
+
+	address = regs->uregs[EXTRACT_REG_NUM(instr, RN_OFFSET)];
+	data	= regs->uregs[EXTRACT_REG_NUM(instr, RT2_OFFSET)];
+	destreg = EXTRACT_REG_NUM(instr, RT_OFFSET);
+
+	type = instr & TYPE_SWPB;
+
+	pr_debug("addr in r%d->0x%08x, dest is r%d, source in r%d->0x%08x)\n",
+		 EXTRACT_REG_NUM(instr, RN_OFFSET), address,
+		 destreg, EXTRACT_REG_NUM(instr, RT2_OFFSET), data);
+
+	/* Check access in reasonable access range for both SWP and SWPB */
+	if (!access_ok(VERIFY_WRITE, (address & ~3), 4)) {
+		pr_debug("SWP{B} emulation: access to %p not allowed!\n",
+			 (void *)address);
+		res = -EFAULT;
+	} else {
+		res = emulate_swpX(address, &data, type);
+	}
+
+	if (res == 0) {
+		/*
+		 * On successful emulation, revert the adjustment to the PC
+		 * made in kernel/traps.c in order to resume execution at the
+		 * instruction following the SWP{B}.
+		 */
+		regs->ARM_pc += 4;
+		regs->uregs[destreg] = data;
+	} else if (res == -EFAULT) {
+		/*
+		 * Memory errors do not mean emulation failed.
+		 * Set up signal info to return SEGV, then return OK
+		 */
+		set_segfault(regs, address);
+	}
+
+	return 0;
+}
+
+/*
+ * Only emulate SWP/SWPB executed in ARM state/User mode.
+ * The kernel must be SWP free and SWP{B} does not exist in Thumb/ThumbEE.
+ */
+static struct undef_hook swp_hook = {
+	.instr_mask = 0x0fb00ff0,
+	.instr_val  = 0x01000090,
+	.cpsr_mask  = MODE_MASK | PSR_T_BIT | PSR_J_BIT,
+	.cpsr_val   = USR_MODE,
+	.fn	    = swp_handler
+};
+
+/*
+ * Register handler and create status file in /proc/cpu
+ * Invoked as late_initcall, since not needed before init spawned.
+ */
+static int __init swp_emulation_init(void)
+{
+#ifdef CONFIG_PROC_FS
+	struct proc_dir_entry *res;
+
+	res = create_proc_entry("cpu/swp_emulation", S_IRUGO, NULL);
+
+	if (!res)
+		return -ENOMEM;
+
+	res->read_proc = proc_read_status;
+#endif /* CONFIG_PROC_FS */
+
+	printk(KERN_NOTICE "Registering SWP/SWPB emulation handler\n");
+	register_undef_hook(&swp_hook);
+
+	return 0;
+}
+
+late_initcall(swp_emulation_init);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/kernel/time.c linux-libre-2.6.38-gnu1/arch/arm/kernel/time.c
--- linux-libre-2.6.37-gnu1/arch/arm/kernel/time.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/kernel/time.c	2011-03-14 21:20:32.000000000 -0400
@@ -29,13 +29,15 @@
 
 #include <asm/leds.h>
 #include <asm/thread_info.h>
+#include <asm/sched_clock.h>
 #include <asm/stacktrace.h>
+#include <asm/mach/arch.h>
 #include <asm/mach/time.h>
 
 /*
  * Our system timer.
  */
-struct sys_timer *system_timer;
+static struct sys_timer *system_timer;
 
 #if defined(CONFIG_RTC_DRV_CMOS) || defined(CONFIG_RTC_DRV_CMOS_MODULE)
 /* this needs a better home */
@@ -160,6 +162,10 @@ device_initcall(timer_init_sysfs);
 
 void __init time_init(void)
 {
+	system_timer = machine_desc->timer;
 	system_timer->init();
+#ifdef CONFIG_HAVE_SCHED_CLOCK
+	sched_clock_postinit();
+#endif
 }
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/kernel/traps.c linux-libre-2.6.38-gnu1/arch/arm/kernel/traps.c
--- linux-libre-2.6.37-gnu1/arch/arm/kernel/traps.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/kernel/traps.c	2011-03-14 21:20:32.000000000 -0400
@@ -37,6 +37,8 @@
 
 static const char *handler[]= { "prefetch abort", "data abort", "address exception", "interrupt" };
 
+void *vectors_page;
+
 #ifdef CONFIG_DEBUG_USER
 unsigned int user_debug;
 
@@ -708,19 +710,19 @@ void __readwrite_bug(const char *fn)
 }
 EXPORT_SYMBOL(__readwrite_bug);
 
-void __pte_error(const char *file, int line, unsigned long val)
+void __pte_error(const char *file, int line, pte_t pte)
 {
-	printk("%s:%d: bad pte %08lx.\n", file, line, val);
+	printk("%s:%d: bad pte %08lx.\n", file, line, pte_val(pte));
 }
 
-void __pmd_error(const char *file, int line, unsigned long val)
+void __pmd_error(const char *file, int line, pmd_t pmd)
 {
-	printk("%s:%d: bad pmd %08lx.\n", file, line, val);
+	printk("%s:%d: bad pmd %08lx.\n", file, line, pmd_val(pmd));
 }
 
-void __pgd_error(const char *file, int line, unsigned long val)
+void __pgd_error(const char *file, int line, pgd_t pgd)
 {
-	printk("%s:%d: bad pgd %08lx.\n", file, line, val);
+	printk("%s:%d: bad pgd %08lx.\n", file, line, pgd_val(pgd));
 }
 
 asmlinkage void __div0(void)
@@ -756,7 +758,11 @@ static void __init kuser_get_tls_init(un
 
 void __init early_trap_init(void)
 {
+#if defined(CONFIG_CPU_USE_DOMAINS)
 	unsigned long vectors = CONFIG_VECTORS_BASE;
+#else
+	unsigned long vectors = (unsigned long)vectors_page;
+#endif
 	extern char __stubs_start[], __stubs_end[];
 	extern char __vectors_start[], __vectors_end[];
 	extern char __kuser_helper_start[], __kuser_helper_end[];
@@ -780,10 +786,10 @@ void __init early_trap_init(void)
 	 * Copy signal return handlers into the vector page, and
 	 * set sigreturn to be a pointer to these.
 	 */
-	memcpy((void *)KERN_SIGRETURN_CODE, sigreturn_codes,
-	       sizeof(sigreturn_codes));
-	memcpy((void *)KERN_RESTART_CODE, syscall_restart_code,
-	       sizeof(syscall_restart_code));
+	memcpy((void *)(vectors + KERN_SIGRETURN_CODE - CONFIG_VECTORS_BASE),
+	       sigreturn_codes, sizeof(sigreturn_codes));
+	memcpy((void *)(vectors + KERN_RESTART_CODE - CONFIG_VECTORS_BASE),
+	       syscall_restart_code, sizeof(syscall_restart_code));
 
 	flush_icache_range(vectors, vectors + PAGE_SIZE);
 	modify_domain(DOMAIN_USER, DOMAIN_CLIENT);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/kernel/vmlinux.lds.S linux-libre-2.6.38-gnu1/arch/arm/kernel/vmlinux.lds.S
--- linux-libre-2.6.37-gnu1/arch/arm/kernel/vmlinux.lds.S	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/kernel/vmlinux.lds.S	2011-03-14 21:20:32.000000000 -0400
@@ -21,6 +21,12 @@
 #define ARM_CPU_KEEP(x)
 #endif
 
+#if defined(CONFIG_SMP_ON_UP) && !defined(CONFIG_DEBUG_SPINLOCK)
+#define ARM_EXIT_KEEP(x)	x
+#else
+#define ARM_EXIT_KEEP(x)
+#endif
+
 OUTPUT_ARCH(arm)
 ENTRY(stext)
 
@@ -43,6 +49,7 @@ SECTIONS
 		_sinittext = .;
 			HEAD_TEXT
 			INIT_TEXT
+			ARM_EXIT_KEEP(EXIT_TEXT)
 		_einittext = .;
 		ARM_CPU_DISCARD(PROC_INFO)
 		__arch_info_begin = .;
@@ -67,6 +74,7 @@ SECTIONS
 #ifndef CONFIG_XIP_KERNEL
 		__init_begin = _stext;
 		INIT_DATA
+		ARM_EXIT_KEEP(EXIT_DATA)
 #endif
 	}
 
@@ -101,6 +109,7 @@ SECTIONS
 			__exception_text_start = .;
 			*(.exception.text)
 			__exception_text_end = .;
+			IRQENTRY_TEXT
 			TEXT_TEXT
 			SCHED_TEXT
 			LOCK_TEXT
@@ -161,12 +170,14 @@ SECTIONS
 		. = ALIGN(PAGE_SIZE);
 		__init_begin = .;
 		INIT_DATA
+		ARM_EXIT_KEEP(EXIT_DATA)
 		. = ALIGN(PAGE_SIZE);
 		__init_end = .;
 #endif
 
 		NOSAVE_DATA
 		CACHELINE_ALIGNED_DATA(32)
+		READ_MOSTLY_DATA(32)
 
 		/*
 		 * The exception fixup table (might need resorting at runtime)
@@ -245,6 +256,8 @@ SECTIONS
 	}
 #endif
 
+	NOTES
+
 	BSS_SECTION(0, 0, 0)
 	_end = .;
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/lib/delay.S linux-libre-2.6.38-gnu1/arch/arm/lib/delay.S
--- linux-libre-2.6.37-gnu1/arch/arm/lib/delay.S	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/lib/delay.S	2011-03-14 21:20:32.000000000 -0400
@@ -25,11 +25,15 @@ ENTRY(__udelay)
 		ldr	r2, .LC1
 		mul	r0, r2, r0
 ENTRY(__const_udelay)				@ 0 <= r0 <= 0x7fffff06
+		mov	r1, #-1
 		ldr	r2, .LC0
 		ldr	r2, [r2]		@ max = 0x01ffffff
+		add	r0, r0, r1, lsr #32-14
 		mov	r0, r0, lsr #14		@ max = 0x0001ffff
+		add	r2, r2, r1, lsr #32-10
 		mov	r2, r2, lsr #10		@ max = 0x00007fff
 		mul	r0, r2, r0		@ max = 2^32-1
+		add	r0, r0, r1, lsr #32-6
 		movs	r0, r0, lsr #6
 		moveq	pc, lr
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/lib/getuser.S linux-libre-2.6.38-gnu1/arch/arm/lib/getuser.S
--- linux-libre-2.6.37-gnu1/arch/arm/lib/getuser.S	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/lib/getuser.S	2011-03-14 21:20:32.000000000 -0400
@@ -28,20 +28,21 @@
  */
 #include <linux/linkage.h>
 #include <asm/errno.h>
+#include <asm/domain.h>
 
 ENTRY(__get_user_1)
-1:	ldrbt	r2, [r0]
+1:	T(ldrb)	r2, [r0]
 	mov	r0, #0
 	mov	pc, lr
 ENDPROC(__get_user_1)
 
 ENTRY(__get_user_2)
 #ifdef CONFIG_THUMB2_KERNEL
-2:	ldrbt	r2, [r0]
-3:	ldrbt	r3, [r0, #1]
+2:	T(ldrb)	r2, [r0]
+3:	T(ldrb)	r3, [r0, #1]
 #else
-2:	ldrbt	r2, [r0], #1
-3:	ldrbt	r3, [r0]
+2:	T(ldrb)	r2, [r0], #1
+3:	T(ldrb)	r3, [r0]
 #endif
 #ifndef __ARMEB__
 	orr	r2, r2, r3, lsl #8
@@ -53,7 +54,7 @@ ENTRY(__get_user_2)
 ENDPROC(__get_user_2)
 
 ENTRY(__get_user_4)
-4:	ldrt	r2, [r0]
+4:	T(ldr)	r2, [r0]
 	mov	r0, #0
 	mov	pc, lr
 ENDPROC(__get_user_4)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/lib/putuser.S linux-libre-2.6.38-gnu1/arch/arm/lib/putuser.S
--- linux-libre-2.6.37-gnu1/arch/arm/lib/putuser.S	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/lib/putuser.S	2011-03-14 21:20:32.000000000 -0400
@@ -28,9 +28,10 @@
  */
 #include <linux/linkage.h>
 #include <asm/errno.h>
+#include <asm/domain.h>
 
 ENTRY(__put_user_1)
-1:	strbt	r2, [r0]
+1:	T(strb)	r2, [r0]
 	mov	r0, #0
 	mov	pc, lr
 ENDPROC(__put_user_1)
@@ -39,19 +40,19 @@ ENTRY(__put_user_2)
 	mov	ip, r2, lsr #8
 #ifdef CONFIG_THUMB2_KERNEL
 #ifndef __ARMEB__
-2:	strbt	r2, [r0]
-3:	strbt	ip, [r0, #1]
+2:	T(strb)	r2, [r0]
+3:	T(strb)	ip, [r0, #1]
 #else
-2:	strbt	ip, [r0]
-3:	strbt	r2, [r0, #1]
+2:	T(strb)	ip, [r0]
+3:	T(strb)	r2, [r0, #1]
 #endif
 #else	/* !CONFIG_THUMB2_KERNEL */
 #ifndef __ARMEB__
-2:	strbt	r2, [r0], #1
-3:	strbt	ip, [r0]
+2:	T(strb)	r2, [r0], #1
+3:	T(strb)	ip, [r0]
 #else
-2:	strbt	ip, [r0], #1
-3:	strbt	r2, [r0]
+2:	T(strb)	ip, [r0], #1
+3:	T(strb)	r2, [r0]
 #endif
 #endif	/* CONFIG_THUMB2_KERNEL */
 	mov	r0, #0
@@ -59,18 +60,18 @@ ENTRY(__put_user_2)
 ENDPROC(__put_user_2)
 
 ENTRY(__put_user_4)
-4:	strt	r2, [r0]
+4:	T(str)	r2, [r0]
 	mov	r0, #0
 	mov	pc, lr
 ENDPROC(__put_user_4)
 
 ENTRY(__put_user_8)
 #ifdef CONFIG_THUMB2_KERNEL
-5:	strt	r2, [r0]
-6:	strt	r3, [r0, #4]
+5:	T(str)	r2, [r0]
+6:	T(str)	r3, [r0, #4]
 #else
-5:	strt	r2, [r0], #4
-6:	strt	r3, [r0]
+5:	T(str)	r2, [r0], #4
+6:	T(str)	r3, [r0]
 #endif
 	mov	r0, #0
 	mov	pc, lr
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/lib/uaccess.S linux-libre-2.6.38-gnu1/arch/arm/lib/uaccess.S
--- linux-libre-2.6.37-gnu1/arch/arm/lib/uaccess.S	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/lib/uaccess.S	2011-03-14 21:20:32.000000000 -0400
@@ -14,6 +14,7 @@
 #include <linux/linkage.h>
 #include <asm/assembler.h>
 #include <asm/errno.h>
+#include <asm/domain.h>
 
 		.text
 
@@ -31,11 +32,11 @@
 		rsb	ip, ip, #4
 		cmp	ip, #2
 		ldrb	r3, [r1], #1
-USER(		strbt	r3, [r0], #1)			@ May fault
+USER(		T(strb)	r3, [r0], #1)			@ May fault
 		ldrgeb	r3, [r1], #1
-USER(		strgebt	r3, [r0], #1)			@ May fault
+USER(		T(strgeb) r3, [r0], #1)			@ May fault
 		ldrgtb	r3, [r1], #1
-USER(		strgtbt	r3, [r0], #1)			@ May fault
+USER(		T(strgtb) r3, [r0], #1)			@ May fault
 		sub	r2, r2, ip
 		b	.Lc2u_dest_aligned
 
@@ -58,7 +59,7 @@ ENTRY(__copy_to_user)
 		addmi	ip, r2, #4
 		bmi	.Lc2u_0nowords
 		ldr	r3, [r1], #4
-USER(		strt	r3, [r0], #4)			@ May fault
+USER(		T(str)	r3, [r0], #4)			@ May fault
 		mov	ip, r0, lsl #32 - PAGE_SHIFT	@ On each page, use a ld/st??t instruction
 		rsb	ip, ip, #0
 		movs	ip, ip, lsr #32 - PAGE_SHIFT
@@ -87,18 +88,18 @@ USER(		strt	r3, [r0], #4)			@ May fault
 		stmneia	r0!, {r3 - r4}			@ Shouldnt fault
 		tst	ip, #4
 		ldrne	r3, [r1], #4
-		strnet	r3, [r0], #4			@ Shouldnt fault
+		T(strne) r3, [r0], #4			@ Shouldnt fault
 		ands	ip, ip, #3
 		beq	.Lc2u_0fupi
 .Lc2u_0nowords:	teq	ip, #0
 		beq	.Lc2u_finished
 .Lc2u_nowords:	cmp	ip, #2
 		ldrb	r3, [r1], #1
-USER(		strbt	r3, [r0], #1)			@ May fault
+USER(		T(strb)	r3, [r0], #1)			@ May fault
 		ldrgeb	r3, [r1], #1
-USER(		strgebt	r3, [r0], #1)			@ May fault
+USER(		T(strgeb) r3, [r0], #1)			@ May fault
 		ldrgtb	r3, [r1], #1
-USER(		strgtbt	r3, [r0], #1)			@ May fault
+USER(		T(strgtb) r3, [r0], #1)			@ May fault
 		b	.Lc2u_finished
 
 .Lc2u_not_enough:
@@ -119,7 +120,7 @@ USER(		strgtbt	r3, [r0], #1)			@ May fau
 		mov	r3, r7, pull #8
 		ldr	r7, [r1], #4
 		orr	r3, r3, r7, push #24
-USER(		strt	r3, [r0], #4)			@ May fault
+USER(		T(str)	r3, [r0], #4)			@ May fault
 		mov	ip, r0, lsl #32 - PAGE_SHIFT
 		rsb	ip, ip, #0
 		movs	ip, ip, lsr #32 - PAGE_SHIFT
@@ -154,18 +155,18 @@ USER(		strt	r3, [r0], #4)			@ May fault
 		movne	r3, r7, pull #8
 		ldrne	r7, [r1], #4
 		orrne	r3, r3, r7, push #24
-		strnet	r3, [r0], #4			@ Shouldnt fault
+		T(strne) r3, [r0], #4			@ Shouldnt fault
 		ands	ip, ip, #3
 		beq	.Lc2u_1fupi
 .Lc2u_1nowords:	mov	r3, r7, get_byte_1
 		teq	ip, #0
 		beq	.Lc2u_finished
 		cmp	ip, #2
-USER(		strbt	r3, [r0], #1)			@ May fault
+USER(		T(strb)	r3, [r0], #1)			@ May fault
 		movge	r3, r7, get_byte_2
-USER(		strgebt	r3, [r0], #1)			@ May fault
+USER(		T(strgeb) r3, [r0], #1)			@ May fault
 		movgt	r3, r7, get_byte_3
-USER(		strgtbt	r3, [r0], #1)			@ May fault
+USER(		T(strgtb) r3, [r0], #1)			@ May fault
 		b	.Lc2u_finished
 
 .Lc2u_2fupi:	subs	r2, r2, #4
@@ -174,7 +175,7 @@ USER(		strgtbt	r3, [r0], #1)			@ May fau
 		mov	r3, r7, pull #16
 		ldr	r7, [r1], #4
 		orr	r3, r3, r7, push #16
-USER(		strt	r3, [r0], #4)			@ May fault
+USER(		T(str)	r3, [r0], #4)			@ May fault
 		mov	ip, r0, lsl #32 - PAGE_SHIFT
 		rsb	ip, ip, #0
 		movs	ip, ip, lsr #32 - PAGE_SHIFT
@@ -209,18 +210,18 @@ USER(		strt	r3, [r0], #4)			@ May fault
 		movne	r3, r7, pull #16
 		ldrne	r7, [r1], #4
 		orrne	r3, r3, r7, push #16
-		strnet	r3, [r0], #4			@ Shouldnt fault
+		T(strne) r3, [r0], #4			@ Shouldnt fault
 		ands	ip, ip, #3
 		beq	.Lc2u_2fupi
 .Lc2u_2nowords:	mov	r3, r7, get_byte_2
 		teq	ip, #0
 		beq	.Lc2u_finished
 		cmp	ip, #2
-USER(		strbt	r3, [r0], #1)			@ May fault
+USER(		T(strb)	r3, [r0], #1)			@ May fault
 		movge	r3, r7, get_byte_3
-USER(		strgebt	r3, [r0], #1)			@ May fault
+USER(		T(strgeb) r3, [r0], #1)			@ May fault
 		ldrgtb	r3, [r1], #0
-USER(		strgtbt	r3, [r0], #1)			@ May fault
+USER(		T(strgtb) r3, [r0], #1)			@ May fault
 		b	.Lc2u_finished
 
 .Lc2u_3fupi:	subs	r2, r2, #4
@@ -229,7 +230,7 @@ USER(		strgtbt	r3, [r0], #1)			@ May fau
 		mov	r3, r7, pull #24
 		ldr	r7, [r1], #4
 		orr	r3, r3, r7, push #8
-USER(		strt	r3, [r0], #4)			@ May fault
+USER(		T(str)	r3, [r0], #4)			@ May fault
 		mov	ip, r0, lsl #32 - PAGE_SHIFT
 		rsb	ip, ip, #0
 		movs	ip, ip, lsr #32 - PAGE_SHIFT
@@ -264,18 +265,18 @@ USER(		strt	r3, [r0], #4)			@ May fault
 		movne	r3, r7, pull #24
 		ldrne	r7, [r1], #4
 		orrne	r3, r3, r7, push #8
-		strnet	r3, [r0], #4			@ Shouldnt fault
+		T(strne) r3, [r0], #4			@ Shouldnt fault
 		ands	ip, ip, #3
 		beq	.Lc2u_3fupi
 .Lc2u_3nowords:	mov	r3, r7, get_byte_3
 		teq	ip, #0
 		beq	.Lc2u_finished
 		cmp	ip, #2
-USER(		strbt	r3, [r0], #1)			@ May fault
+USER(		T(strb)	r3, [r0], #1)			@ May fault
 		ldrgeb	r3, [r1], #1
-USER(		strgebt	r3, [r0], #1)			@ May fault
+USER(		T(strgeb) r3, [r0], #1)			@ May fault
 		ldrgtb	r3, [r1], #0
-USER(		strgtbt	r3, [r0], #1)			@ May fault
+USER(		T(strgtb) r3, [r0], #1)			@ May fault
 		b	.Lc2u_finished
 ENDPROC(__copy_to_user)
 
@@ -294,11 +295,11 @@ ENDPROC(__copy_to_user)
 .Lcfu_dest_not_aligned:
 		rsb	ip, ip, #4
 		cmp	ip, #2
-USER(		ldrbt	r3, [r1], #1)			@ May fault
+USER(		T(ldrb)	r3, [r1], #1)			@ May fault
 		strb	r3, [r0], #1
-USER(		ldrgebt	r3, [r1], #1)			@ May fault
+USER(		T(ldrgeb) r3, [r1], #1)			@ May fault
 		strgeb	r3, [r0], #1
-USER(		ldrgtbt	r3, [r1], #1)			@ May fault
+USER(		T(ldrgtb) r3, [r1], #1)			@ May fault
 		strgtb	r3, [r0], #1
 		sub	r2, r2, ip
 		b	.Lcfu_dest_aligned
@@ -321,7 +322,7 @@ ENTRY(__copy_from_user)
 .Lcfu_0fupi:	subs	r2, r2, #4
 		addmi	ip, r2, #4
 		bmi	.Lcfu_0nowords
-USER(		ldrt	r3, [r1], #4)
+USER(		T(ldr)	r3, [r1], #4)
 		str	r3, [r0], #4
 		mov	ip, r1, lsl #32 - PAGE_SHIFT	@ On each page, use a ld/st??t instruction
 		rsb	ip, ip, #0
@@ -350,18 +351,18 @@ USER(		ldrt	r3, [r1], #4)
 		ldmneia	r1!, {r3 - r4}			@ Shouldnt fault
 		stmneia	r0!, {r3 - r4}
 		tst	ip, #4
-		ldrnet	r3, [r1], #4			@ Shouldnt fault
+		T(ldrne) r3, [r1], #4			@ Shouldnt fault
 		strne	r3, [r0], #4
 		ands	ip, ip, #3
 		beq	.Lcfu_0fupi
 .Lcfu_0nowords:	teq	ip, #0
 		beq	.Lcfu_finished
 .Lcfu_nowords:	cmp	ip, #2
-USER(		ldrbt	r3, [r1], #1)			@ May fault
+USER(		T(ldrb)	r3, [r1], #1)			@ May fault
 		strb	r3, [r0], #1
-USER(		ldrgebt	r3, [r1], #1)			@ May fault
+USER(		T(ldrgeb) r3, [r1], #1)			@ May fault
 		strgeb	r3, [r0], #1
-USER(		ldrgtbt	r3, [r1], #1)			@ May fault
+USER(		T(ldrgtb) r3, [r1], #1)			@ May fault
 		strgtb	r3, [r0], #1
 		b	.Lcfu_finished
 
@@ -374,7 +375,7 @@ USER(		ldrgtbt	r3, [r1], #1)			@ May fau
 
 .Lcfu_src_not_aligned:
 		bic	r1, r1, #3
-USER(		ldrt	r7, [r1], #4)			@ May fault
+USER(		T(ldr)	r7, [r1], #4)			@ May fault
 		cmp	ip, #2
 		bgt	.Lcfu_3fupi
 		beq	.Lcfu_2fupi
@@ -382,7 +383,7 @@ USER(		ldrt	r7, [r1], #4)			@ May fault
 		addmi	ip, r2, #4
 		bmi	.Lcfu_1nowords
 		mov	r3, r7, pull #8
-USER(		ldrt	r7, [r1], #4)			@ May fault
+USER(		T(ldr)	r7, [r1], #4)			@ May fault
 		orr	r3, r3, r7, push #24
 		str	r3, [r0], #4
 		mov	ip, r1, lsl #32 - PAGE_SHIFT
@@ -417,7 +418,7 @@ USER(		ldrt	r7, [r1], #4)			@ May fault
 		stmneia	r0!, {r3 - r4}
 		tst	ip, #4
 		movne	r3, r7, pull #8
-USER(		ldrnet	r7, [r1], #4)			@ May fault
+USER(		T(ldrne) r7, [r1], #4)			@ May fault
 		orrne	r3, r3, r7, push #24
 		strne	r3, [r0], #4
 		ands	ip, ip, #3
@@ -437,7 +438,7 @@ USER(		ldrnet	r7, [r1], #4)			@ May faul
 		addmi	ip, r2, #4
 		bmi	.Lcfu_2nowords
 		mov	r3, r7, pull #16
-USER(		ldrt	r7, [r1], #4)			@ May fault
+USER(		T(ldr)	r7, [r1], #4)			@ May fault
 		orr	r3, r3, r7, push #16
 		str	r3, [r0], #4
 		mov	ip, r1, lsl #32 - PAGE_SHIFT
@@ -473,7 +474,7 @@ USER(		ldrt	r7, [r1], #4)			@ May fault
 		stmneia	r0!, {r3 - r4}
 		tst	ip, #4
 		movne	r3, r7, pull #16
-USER(		ldrnet	r7, [r1], #4)			@ May fault
+USER(		T(ldrne) r7, [r1], #4)			@ May fault
 		orrne	r3, r3, r7, push #16
 		strne	r3, [r0], #4
 		ands	ip, ip, #3
@@ -485,7 +486,7 @@ USER(		ldrnet	r7, [r1], #4)			@ May faul
 		strb	r3, [r0], #1
 		movge	r3, r7, get_byte_3
 		strgeb	r3, [r0], #1
-USER(		ldrgtbt	r3, [r1], #0)			@ May fault
+USER(		T(ldrgtb) r3, [r1], #0)			@ May fault
 		strgtb	r3, [r0], #1
 		b	.Lcfu_finished
 
@@ -493,7 +494,7 @@ USER(		ldrgtbt	r3, [r1], #0)			@ May fau
 		addmi	ip, r2, #4
 		bmi	.Lcfu_3nowords
 		mov	r3, r7, pull #24
-USER(		ldrt	r7, [r1], #4)			@ May fault
+USER(		T(ldr)	r7, [r1], #4)			@ May fault
 		orr	r3, r3, r7, push #8
 		str	r3, [r0], #4
 		mov	ip, r1, lsl #32 - PAGE_SHIFT
@@ -528,7 +529,7 @@ USER(		ldrt	r7, [r1], #4)			@ May fault
 		stmneia	r0!, {r3 - r4}
 		tst	ip, #4
 		movne	r3, r7, pull #24
-USER(		ldrnet	r7, [r1], #4)			@ May fault
+USER(		T(ldrne) r7, [r1], #4)			@ May fault
 		orrne	r3, r3, r7, push #8
 		strne	r3, [r0], #4
 		ands	ip, ip, #3
@@ -538,9 +539,9 @@ USER(		ldrnet	r7, [r1], #4)			@ May faul
 		beq	.Lcfu_finished
 		cmp	ip, #2
 		strb	r3, [r0], #1
-USER(		ldrgebt	r3, [r1], #1)			@ May fault
+USER(		T(ldrgeb) r3, [r1], #1)			@ May fault
 		strgeb	r3, [r0], #1
-USER(		ldrgtbt	r3, [r1], #1)			@ May fault
+USER(		T(ldrgtb) r3, [r1], #1)			@ May fault
 		strgtb	r3, [r0], #1
 		b	.Lcfu_finished
 ENDPROC(__copy_from_user)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-aaec2000/core.c linux-libre-2.6.38-gnu1/arch/arm/mach-aaec2000/core.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-aaec2000/core.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-aaec2000/core.c	2011-03-14 21:20:32.000000000 -0400
@@ -68,25 +68,25 @@ void __init aaec2000_map_io(void)
 /*
  * Interrupt handling routines
  */
-static void aaec2000_int_ack(unsigned int irq)
+static void aaec2000_int_ack(struct irq_data *d)
 {
-	IRQ_INTSR = 1 << irq;
+	IRQ_INTSR = 1 << d->irq;
 }
 
-static void aaec2000_int_mask(unsigned int irq)
+static void aaec2000_int_mask(struct irq_data *d)
 {
-	IRQ_INTENC |= (1 << irq);
+	IRQ_INTENC |= (1 << d->irq);
 }
 
-static void aaec2000_int_unmask(unsigned int irq)
+static void aaec2000_int_unmask(struct irq_data *d)
 {
-	IRQ_INTENS |= (1 << irq);
+	IRQ_INTENS |= (1 << d->irq);
 }
 
 static struct irq_chip aaec2000_irq_chip = {
-	.ack	= aaec2000_int_ack,
-	.mask	= aaec2000_int_mask,
-	.unmask	= aaec2000_int_unmask,
+	.irq_ack	= aaec2000_int_ack,
+	.irq_mask	= aaec2000_int_mask,
+	.irq_unmask	= aaec2000_int_unmask,
 };
 
 void __init aaec2000_init_irq(void)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-at91/at91rm9200_time.c linux-libre-2.6.38-gnu1/arch/arm/mach-at91/at91rm9200_time.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-at91/at91rm9200_time.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-at91/at91rm9200_time.c	2011-03-14 21:20:32.000000000 -0400
@@ -101,7 +101,6 @@ static struct clocksource clk32k = {
 	.rating		= 150,
 	.read		= read_clk32k,
 	.mask		= CLOCKSOURCE_MASK(20),
-	.shift		= 10,
 	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
@@ -201,8 +200,7 @@ void __init at91rm9200_timer_init(void)
 	clockevents_register_device(&clkevt);
 
 	/* register clocksource */
-	clk32k.mult = clocksource_hz2mult(AT91_SLOW_CLOCK, clk32k.shift);
-	clocksource_register(&clk32k);
+	clocksource_register_hz(&clk32k, AT91_SLOW_CLOCK);
 }
 
 struct sys_timer at91rm9200_timer = {
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-at91/at91sam926x_time.c linux-libre-2.6.38-gnu1/arch/arm/mach-at91/at91sam926x_time.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-at91/at91sam926x_time.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-at91/at91sam926x_time.c	2011-03-14 21:20:32.000000000 -0400
@@ -51,7 +51,6 @@ static struct clocksource pit_clk = {
 	.name		= "pit",
 	.rating		= 175,
 	.read		= read_pit_clk,
-	.shift		= 20,
 	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
@@ -163,10 +162,9 @@ static void __init at91sam926x_pit_init(
 	 * Register clocksource.  The high order bits of PIV are unused,
 	 * so this isn't a 32-bit counter unless we get clockevent irqs.
 	 */
-	pit_clk.mult = clocksource_hz2mult(pit_rate, pit_clk.shift);
 	bits = 12 /* PICNT */ + ilog2(pit_cycle) /* PIV */;
 	pit_clk.mask = CLOCKSOURCE_MASK(bits);
-	clocksource_register(&pit_clk);
+	clocksource_register_hz(&pit_clk, pit_rate);
 
 	/* Set up irq handler */
 	setup_irq(AT91_ID_SYS, &at91sam926x_pit_irq);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-at91/board-ecbat91.c linux-libre-2.6.38-gnu1/arch/arm/mach-at91/board-ecbat91.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-at91/board-ecbat91.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-at91/board-ecbat91.c	2011-03-14 21:20:32.000000000 -0400
@@ -128,17 +128,17 @@ static struct spi_board_info __initdata
 		.platform_data	= &my_flash0_platform,
 #endif
 	},
-	{	/* User accessable spi - cs1 (250KHz) */
+	{	/* User accessible spi - cs1 (250KHz) */
 		.modalias	= "spi-cs1",
 		.chip_select	= 1,
 		.max_speed_hz	= 250 * 1000,
 	},
-	{	/* User accessable spi - cs2 (1MHz) */
+	{	/* User accessible spi - cs2 (1MHz) */
 		.modalias	= "spi-cs2",
 		.chip_select	= 2,
 		.max_speed_hz	= 1 * 1000 * 1000,
 	},
-	{	/* User accessable spi - cs3 (10MHz) */
+	{	/* User accessible spi - cs3 (10MHz) */
 		.modalias	= "spi-cs3",
 		.chip_select	= 3,
 		.max_speed_hz	= 10 * 1000 * 1000,
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-at91/board-foxg20.c linux-libre-2.6.38-gnu1/arch/arm/mach-at91/board-foxg20.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-at91/board-foxg20.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-at91/board-foxg20.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,274 @@
+/*
+ *  Copyright (C) 2005 SAN People
+ *  Copyright (C) 2008 Atmel
+ *  Copyright (C) 2010 Lee McLoughlin - lee@lmmrtech.com
+ *  Copyright (C) 2010 Sergio Tanzilli - tanzilli@acmesystems.it
+ *
+ * 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/spi/at73c213.h>
+#include <linux/gpio.h>
+#include <linux/gpio_keys.h>
+#include <linux/input.h>
+#include <linux/clk.h>
+#include <linux/w1-gpio.h>
+
+#include <mach/hardware.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/board.h>
+#include <mach/at91sam9_smc.h>
+
+#include "sam9_smc.h"
+#include "generic.h"
+
+/*
+ * The FOX Board G20 hardware comes as the "Netus G20" board with
+ * just the cpu, ram, dataflash and two header connectors.
+ * This is plugged into the FOX Board which provides the ethernet,
+ * usb, rtc, leds, switch, ...
+ *
+ * For more info visit: http://www.acmesystems.it/foxg20
+ */
+
+
+static void __init foxg20_map_io(void)
+{
+	/* Initialize processor: 18.432 MHz crystal */
+	at91sam9260_initialize(18432000);
+
+	/* DBGU on ttyS0. (Rx & Tx only) */
+	at91_register_uart(0, 0, 0);
+
+	/* USART0 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
+	at91_register_uart(AT91SAM9260_ID_US0, 1,
+				ATMEL_UART_CTS
+				| ATMEL_UART_RTS
+				| ATMEL_UART_DTR
+				| ATMEL_UART_DSR
+				| ATMEL_UART_DCD
+				| ATMEL_UART_RI);
+
+	/* USART1 on ttyS2. (Rx, Tx, RTS, CTS) */
+	at91_register_uart(AT91SAM9260_ID_US1, 2,
+		ATMEL_UART_CTS
+		| ATMEL_UART_RTS);
+
+	/* USART2 on ttyS3. (Rx & Tx only) */
+	at91_register_uart(AT91SAM9260_ID_US2, 3, 0);
+
+	/* USART3 on ttyS4. (Rx, Tx, RTS, CTS) */
+	at91_register_uart(AT91SAM9260_ID_US3, 4,
+		ATMEL_UART_CTS
+		| ATMEL_UART_RTS);
+
+	/* USART4 on ttyS5. (Rx & Tx only) */
+	at91_register_uart(AT91SAM9260_ID_US4, 5, 0);
+
+	/* USART5 on ttyS6. (Rx & Tx only) */
+	at91_register_uart(AT91SAM9260_ID_US5, 6, 0);
+
+	/* set serial console to ttyS0 (ie, DBGU) */
+	at91_set_serial_console(0);
+
+	/* Set the internal pull-up resistor on DRXD */
+	at91_set_A_periph(AT91_PIN_PB14, 1);
+
+}
+
+static void __init foxg20_init_irq(void)
+{
+	at91sam9260_init_interrupts(NULL);
+}
+
+
+/*
+ * USB Host port
+ */
+static struct at91_usbh_data __initdata foxg20_usbh_data = {
+	.ports		= 2,
+};
+
+/*
+ * USB Device port
+ */
+static struct at91_udc_data __initdata foxg20_udc_data = {
+	.vbus_pin	= AT91_PIN_PC6,
+	.pullup_pin	= 0,		/* pull-up driven by UDC */
+};
+
+
+/*
+ * SPI devices.
+ */
+static struct spi_board_info foxg20_spi_devices[] = {
+#if !defined(CONFIG_MMC_AT91)
+	{
+		.modalias	= "mtd_dataflash",
+		.chip_select	= 1,
+		.max_speed_hz	= 15 * 1000 * 1000,
+		.bus_num	= 0,
+	},
+#endif
+};
+
+
+/*
+ * MACB Ethernet device
+ */
+static struct at91_eth_data __initdata foxg20_macb_data = {
+	.phy_irq_pin	= AT91_PIN_PA7,
+	.is_rmii	= 1,
+};
+
+/*
+ * MCI (SD/MMC)
+ * det_pin, wp_pin and vcc_pin are not connected
+ */
+static struct at91_mmc_data __initdata foxg20_mmc_data = {
+	.slot_b		= 1,
+	.wire4		= 1,
+};
+
+
+/*
+ * LEDs
+ */
+static struct gpio_led foxg20_leds[] = {
+	{	/* user led, red */
+		.name			= "user_led",
+		.gpio			= AT91_PIN_PC7,
+		.active_low		= 0,
+		.default_trigger	= "heartbeat",
+	},
+};
+
+
+/*
+ * GPIO Buttons
+ */
+#if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE)
+static struct gpio_keys_button foxg20_buttons[] = {
+	{
+		.gpio		= AT91_PIN_PC4,
+		.code		= BTN_1,
+		.desc		= "Button 1",
+		.active_low	= 1,
+		.wakeup		= 1,
+	},
+};
+
+static struct gpio_keys_platform_data foxg20_button_data = {
+	.buttons	= foxg20_buttons,
+	.nbuttons	= ARRAY_SIZE(foxg20_buttons),
+};
+
+static struct platform_device foxg20_button_device = {
+	.name		= "gpio-keys",
+	.id		= -1,
+	.num_resources	= 0,
+	.dev		= {
+		.platform_data	= &foxg20_button_data,
+	}
+};
+
+static void __init foxg20_add_device_buttons(void)
+{
+	at91_set_gpio_input(AT91_PIN_PC4, 1);	/* btn1 */
+	at91_set_deglitch(AT91_PIN_PC4, 1);
+
+	platform_device_register(&foxg20_button_device);
+}
+#else
+static void __init foxg20_add_device_buttons(void) {}
+#endif
+
+
+#if defined(CONFIG_W1_MASTER_GPIO) || defined(CONFIG_W1_MASTER_GPIO_MODULE)
+static struct w1_gpio_platform_data w1_gpio_pdata = {
+	/* If you choose to use a pin other than PB16 it needs to be 3.3V */
+	.pin		= AT91_PIN_PB16,
+	.is_open_drain  = 1,
+};
+
+static struct platform_device w1_device = {
+	.name			= "w1-gpio",
+	.id			= -1,
+	.dev.platform_data	= &w1_gpio_pdata,
+};
+
+static void __init at91_add_device_w1(void)
+{
+	at91_set_GPIO_periph(w1_gpio_pdata.pin, 1);
+	at91_set_multi_drive(w1_gpio_pdata.pin, 1);
+	platform_device_register(&w1_device);
+}
+
+#endif
+
+
+static struct i2c_board_info __initdata foxg20_i2c_devices[] = {
+	{
+		I2C_BOARD_INFO("24c512", 0x50),
+	},
+};
+
+
+static void __init foxg20_board_init(void)
+{
+	/* Serial */
+	at91_add_device_serial();
+	/* USB Host */
+	at91_add_device_usbh(&foxg20_usbh_data);
+	/* USB Device */
+	at91_add_device_udc(&foxg20_udc_data);
+	/* SPI */
+	at91_add_device_spi(foxg20_spi_devices, ARRAY_SIZE(foxg20_spi_devices));
+	/* Ethernet */
+	at91_add_device_eth(&foxg20_macb_data);
+	/* MMC */
+	at91_add_device_mmc(0, &foxg20_mmc_data);
+	/* I2C */
+	at91_add_device_i2c(foxg20_i2c_devices, ARRAY_SIZE(foxg20_i2c_devices));
+	/* LEDs */
+	at91_gpio_leds(foxg20_leds, ARRAY_SIZE(foxg20_leds));
+	/* Push Buttons */
+	foxg20_add_device_buttons();
+#if defined(CONFIG_W1_MASTER_GPIO) || defined(CONFIG_W1_MASTER_GPIO_MODULE)
+	at91_add_device_w1();
+#endif
+}
+
+MACHINE_START(ACMENETUSFOXG20, "Acme Systems srl FOX Board G20")
+	/* Maintainer: Sergio Tanzilli */
+	.boot_params	= AT91_SDRAM_BASE + 0x100,
+	.timer		= &at91sam926x_timer,
+	.map_io		= foxg20_map_io,
+	.init_irq	= foxg20_init_irq,
+	.init_machine	= foxg20_board_init,
+MACHINE_END
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-at91/board-gsia18s.c linux-libre-2.6.38-gnu1/arch/arm/mach-at91/board-gsia18s.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-at91/board-gsia18s.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-at91/board-gsia18s.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,584 @@
+/*
+ *  Copyright (C) 2010 Christian Glindkamp <christian.glindkamp@taskit.de>
+ *                     taskit GmbH
+ *                2010 Igor Plyatov <plyatov@gmail.com>
+ *                     GeoSIG 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/w1-gpio.h>
+#include <linux/i2c.h>
+#include <linux/i2c/pcf857x.h>
+#include <linux/gpio_keys.h>
+#include <linux/input.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+
+#include <mach/board.h>
+#include <mach/at91sam9_smc.h>
+#include <mach/gsia18s.h>
+#include <mach/stamp9g20.h>
+
+#include "sam9_smc.h"
+#include "generic.h"
+
+static void __init gsia18s_map_io(void)
+{
+	stamp9g20_map_io();
+
+	/*
+	 * USART0 on ttyS1 (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI).
+	 * Used for Internal Analog Modem.
+	 */
+	at91_register_uart(AT91SAM9260_ID_US0, 1,
+				ATMEL_UART_CTS | ATMEL_UART_RTS |
+				ATMEL_UART_DTR | ATMEL_UART_DSR |
+				ATMEL_UART_DCD | ATMEL_UART_RI);
+	/*
+	 * USART1 on ttyS2 (Rx, Tx, CTS, RTS).
+	 * Used for GPS or WiFi or Data stream.
+	 */
+	at91_register_uart(AT91SAM9260_ID_US1, 2,
+				ATMEL_UART_CTS | ATMEL_UART_RTS);
+	/*
+	 * USART2 on ttyS3 (Rx, Tx, CTS, RTS).
+	 * Used for External Modem.
+	 */
+	at91_register_uart(AT91SAM9260_ID_US2, 3,
+				ATMEL_UART_CTS | ATMEL_UART_RTS);
+	/*
+	 * USART3 on ttyS4 (Rx, Tx, RTS).
+	 * Used for RS-485.
+	 */
+	at91_register_uart(AT91SAM9260_ID_US3, 4, ATMEL_UART_RTS);
+
+	/*
+	 * USART4 on ttyS5 (Rx, Tx).
+	 * Used for TRX433 Radio Module.
+	 */
+	at91_register_uart(AT91SAM9260_ID_US4, 5, 0);
+}
+
+static void __init init_irq(void)
+{
+	at91sam9260_init_interrupts(NULL);
+}
+
+/*
+ * Two USB Host ports
+ */
+static struct at91_usbh_data __initdata usbh_data = {
+	.ports		= 2,
+};
+
+/*
+ * USB Device port
+ */
+static struct at91_udc_data __initdata udc_data = {
+	.vbus_pin	= AT91_PIN_PA22,
+	.pullup_pin	= 0,		/* pull-up driven by UDC */
+};
+
+/*
+ * MACB Ethernet device
+ */
+static struct at91_eth_data __initdata macb_data = {
+	.phy_irq_pin	= AT91_PIN_PA28,
+	.is_rmii	= 1,
+};
+
+/*
+ * LEDs and GPOs
+ */
+static struct gpio_led gpio_leds[] = {
+	{
+		.name			= "gpo:spi1reset",
+		.gpio			= AT91_PIN_PC1,
+		.active_low		= 0,
+		.default_trigger	= "none",
+		.default_state		= LEDS_GPIO_DEFSTATE_OFF,
+	},
+	{
+		.name			= "gpo:trig_net_out",
+		.gpio			= AT91_PIN_PB20,
+		.active_low		= 0,
+		.default_trigger	= "none",
+		.default_state		= LEDS_GPIO_DEFSTATE_OFF,
+	},
+	{
+		.name			= "gpo:trig_net_dir",
+		.gpio			= AT91_PIN_PB19,
+		.active_low		= 0,
+		.default_trigger	= "none",
+		.default_state		= LEDS_GPIO_DEFSTATE_OFF,
+	},
+	{
+		.name			= "gpo:charge_dis",
+		.gpio			= AT91_PIN_PC2,
+		.active_low		= 0,
+		.default_trigger	= "none",
+		.default_state		= LEDS_GPIO_DEFSTATE_OFF,
+	},
+	{
+		.name			= "led:event",
+		.gpio			= AT91_PIN_PB17,
+		.active_low		= 1,
+		.default_trigger	= "none",
+		.default_state		= LEDS_GPIO_DEFSTATE_OFF,
+	},
+	{
+		.name			= "led:lan",
+		.gpio			= AT91_PIN_PB18,
+		.active_low		= 1,
+		.default_trigger	= "none",
+		.default_state		= LEDS_GPIO_DEFSTATE_OFF,
+	},
+	{
+		.name			= "led:error",
+		.gpio			= AT91_PIN_PB16,
+		.active_low		= 1,
+		.default_trigger	= "none",
+		.default_state		= LEDS_GPIO_DEFSTATE_ON,
+	}
+};
+
+static struct gpio_led_platform_data gpio_led_info = {
+	.leds		= gpio_leds,
+	.num_leds	= ARRAY_SIZE(gpio_leds),
+};
+
+static struct platform_device leds = {
+	.name	= "leds-gpio",
+	.id	= 0,
+	.dev	= {
+		.platform_data	= &gpio_led_info,
+	}
+};
+
+static void __init gsia18s_leds_init(void)
+{
+	platform_device_register(&leds);
+}
+
+/* PCF8574 0x20 GPIO - U1 on the GS_IA18-CB_V3 board */
+static struct gpio_led pcf_gpio_leds1[] = {
+	{ /* bit 0 */
+		.name			= "gpo:hdc_power",
+		.gpio			= PCF_GPIO_HDC_POWER,
+		.active_low		= 0,
+		.default_trigger	= "none",
+		.default_state		= LEDS_GPIO_DEFSTATE_OFF,
+	},
+	{ /* bit 1 */
+		.name			= "gpo:wifi_setup",
+		.gpio			= PCF_GPIO_WIFI_SETUP,
+		.active_low		= 1,
+		.default_trigger	= "none",
+		.default_state		= LEDS_GPIO_DEFSTATE_OFF,
+	},
+	{ /* bit 2 */
+		.name			= "gpo:wifi_enable",
+		.gpio			= PCF_GPIO_WIFI_ENABLE,
+		.active_low		= 1,
+		.default_trigger	= "none",
+		.default_state		= LEDS_GPIO_DEFSTATE_OFF,
+	},
+	{ /* bit 3	*/
+		.name			= "gpo:wifi_reset",
+		.gpio			= PCF_GPIO_WIFI_RESET,
+		.active_low		= 1,
+		.default_trigger	= "none",
+		.default_state		= LEDS_GPIO_DEFSTATE_ON,
+	},
+	/* bit 4 used as GPI	*/
+	{ /* bit 5 */
+		.name			= "gpo:gps_setup",
+		.gpio			= PCF_GPIO_GPS_SETUP,
+		.active_low		= 1,
+		.default_trigger	= "none",
+		.default_state		= LEDS_GPIO_DEFSTATE_OFF,
+	},
+	{ /* bit 6 */
+		.name			= "gpo:gps_standby",
+		.gpio			= PCF_GPIO_GPS_STANDBY,
+		.active_low		= 0,
+		.default_trigger	= "none",
+		.default_state		= LEDS_GPIO_DEFSTATE_ON,
+	},
+	{ /* bit 7 */
+		.name			= "gpo:gps_power",
+		.gpio			= PCF_GPIO_GPS_POWER,
+		.active_low		= 0,
+		.default_trigger	= "none",
+		.default_state		= LEDS_GPIO_DEFSTATE_OFF,
+	}
+};
+
+static struct gpio_led_platform_data pcf_gpio_led_info1 = {
+	.leds		= pcf_gpio_leds1,
+	.num_leds	= ARRAY_SIZE(pcf_gpio_leds1),
+};
+
+static struct platform_device pcf_leds1 = {
+	.name	= "leds-gpio", /* GS_IA18-CB_board */
+	.id	= 1,
+	.dev	= {
+		.platform_data	= &pcf_gpio_led_info1,
+	}
+};
+
+/* PCF8574 0x22 GPIO - U1 on the GS_2G_OPT1-A_V0 board (Alarm) */
+static struct gpio_led pcf_gpio_leds2[] = {
+	{ /* bit 0 */
+		.name			= "gpo:alarm_1",
+		.gpio			= PCF_GPIO_ALARM1,
+		.active_low		= 1,
+		.default_trigger	= "none",
+		.default_state		= LEDS_GPIO_DEFSTATE_OFF,
+	},
+	{ /* bit 1 */
+		.name			= "gpo:alarm_2",
+		.gpio			= PCF_GPIO_ALARM2,
+		.active_low		= 1,
+		.default_trigger	= "none",
+		.default_state		= LEDS_GPIO_DEFSTATE_OFF,
+	},
+	{ /* bit 2 */
+		.name			= "gpo:alarm_3",
+		.gpio			= PCF_GPIO_ALARM3,
+		.active_low		= 1,
+		.default_trigger	= "none",
+		.default_state		= LEDS_GPIO_DEFSTATE_OFF,
+	},
+	{ /* bit 3 */
+		.name			= "gpo:alarm_4",
+		.gpio			= PCF_GPIO_ALARM4,
+		.active_low		= 1,
+		.default_trigger	= "none",
+		.default_state		= LEDS_GPIO_DEFSTATE_OFF,
+	},
+	/* bits 4, 5, 6 not used */
+	{ /* bit 7 */
+		.name			= "gpo:alarm_v_relay_on",
+		.gpio			= PCF_GPIO_ALARM_V_RELAY_ON,
+		.active_low		= 0,
+		.default_trigger	= "none",
+		.default_state		= LEDS_GPIO_DEFSTATE_OFF,
+	},
+};
+
+static struct gpio_led_platform_data pcf_gpio_led_info2 = {
+	.leds		= pcf_gpio_leds2,
+	.num_leds	= ARRAY_SIZE(pcf_gpio_leds2),
+};
+
+static struct platform_device pcf_leds2 = {
+	.name	= "leds-gpio",
+	.id	= 2,
+	.dev	= {
+		.platform_data	= &pcf_gpio_led_info2,
+	}
+};
+
+/* PCF8574 0x24 GPIO U1 on the GS_2G-OPT23-A_V0 board (Modem) */
+static struct gpio_led pcf_gpio_leds3[] = {
+	{ /* bit 0 */
+		.name			= "gpo:modem_power",
+		.gpio			= PCF_GPIO_MODEM_POWER,
+		.active_low		= 1,
+		.default_trigger	= "none",
+		.default_state		= LEDS_GPIO_DEFSTATE_OFF,
+	},
+		/* bits 1 and 2 not used */
+	{ /* bit 3 */
+		.name			= "gpo:modem_reset",
+		.gpio			= PCF_GPIO_MODEM_RESET,
+		.active_low		= 1,
+		.default_trigger	= "none",
+		.default_state		= LEDS_GPIO_DEFSTATE_ON,
+	},
+		/* bits 4, 5 and 6 not used */
+	{ /* bit 7 */
+		.name			= "gpo:trx_reset",
+		.gpio			= PCF_GPIO_TRX_RESET,
+		.active_low		= 1,
+		.default_trigger	= "none",
+		.default_state		= LEDS_GPIO_DEFSTATE_ON,
+	}
+};
+
+static struct gpio_led_platform_data pcf_gpio_led_info3 = {
+	.leds		= pcf_gpio_leds3,
+	.num_leds	= ARRAY_SIZE(pcf_gpio_leds3),
+};
+
+static struct platform_device pcf_leds3 = {
+	.name	= "leds-gpio",
+	.id	= 3,
+	.dev	= {
+		.platform_data	= &pcf_gpio_led_info3,
+	}
+};
+
+static void __init gsia18s_pcf_leds_init(void)
+{
+	platform_device_register(&pcf_leds1);
+	platform_device_register(&pcf_leds2);
+	platform_device_register(&pcf_leds3);
+}
+
+/*
+ * SPI busses.
+ */
+static struct spi_board_info gsia18s_spi_devices[] = {
+	{ /* User accessible spi0, cs0 used for communication with MSP RTC */
+		.modalias	= "spidev",
+		.bus_num	= 0,
+		.chip_select	= 0,
+		.max_speed_hz	= 580000,
+		.mode		= SPI_MODE_1,
+	},
+	{ /* User accessible spi1, cs0 used for communication with int. DSP */
+		.modalias	= "spidev",
+		.bus_num	= 1,
+		.chip_select	= 0,
+		.max_speed_hz	= 5600000,
+		.mode		= SPI_MODE_0,
+	},
+	{ /* User accessible spi1, cs1 used for communication with ext. DSP */
+		.modalias	= "spidev",
+		.bus_num	= 1,
+		.chip_select	= 1,
+		.max_speed_hz	= 5600000,
+		.mode		= SPI_MODE_0,
+	},
+	{ /* User accessible spi1, cs2 used for communication with ext. DSP */
+		.modalias	= "spidev",
+		.bus_num	= 1,
+		.chip_select	= 2,
+		.max_speed_hz	= 5600000,
+		.mode		= SPI_MODE_0,
+	},
+	{ /* User accessible spi1, cs3 used for communication with ext. DSP */
+		.modalias	= "spidev",
+		.bus_num	= 1,
+		.chip_select	= 3,
+		.max_speed_hz	= 5600000,
+		.mode		= SPI_MODE_0,
+	}
+};
+
+/*
+ * GPI Buttons
+ */
+static struct gpio_keys_button buttons[] = {
+	{
+		.gpio		= GPIO_TRIG_NET_IN,
+		.code		= BTN_1,
+		.desc		= "TRIG_NET_IN",
+		.type		= EV_KEY,
+		.active_low	= 0,
+		.wakeup		= 1,
+	},
+	{ /* SW80 on the GS_IA18_S-MN board*/
+		.gpio		= GPIO_CARD_UNMOUNT_0,
+		.code		= BTN_2,
+		.desc		= "Card umount 0",
+		.type		= EV_KEY,
+		.active_low	= 1,
+		.wakeup		= 1,
+	},
+	{ /* SW79 on the GS_IA18_S-MN board*/
+		.gpio		= GPIO_CARD_UNMOUNT_1,
+		.code		= BTN_3,
+		.desc		= "Card umount 1",
+		.type		= EV_KEY,
+		.active_low	= 1,
+		.wakeup		= 1,
+	},
+	{ /* SW280 on the GS_IA18-CB board*/
+		.gpio		= GPIO_KEY_POWER,
+		.code		= KEY_POWER,
+		.desc		= "Power Off Button",
+		.type		= EV_KEY,
+		.active_low	= 0,
+		.wakeup		= 1,
+	}
+};
+
+static struct gpio_keys_platform_data button_data = {
+	.buttons	= buttons,
+	.nbuttons	= ARRAY_SIZE(buttons),
+};
+
+static struct platform_device button_device = {
+	.name		= "gpio-keys",
+	.id		= -1,
+	.num_resources	= 0,
+	.dev		= {
+		.platform_data	= &button_data,
+	}
+};
+
+static void __init gsia18s_add_device_buttons(void)
+{
+	at91_set_gpio_input(GPIO_TRIG_NET_IN, 1);
+	at91_set_deglitch(GPIO_TRIG_NET_IN, 1);
+	at91_set_gpio_input(GPIO_CARD_UNMOUNT_0, 1);
+	at91_set_deglitch(GPIO_CARD_UNMOUNT_0, 1);
+	at91_set_gpio_input(GPIO_CARD_UNMOUNT_1, 1);
+	at91_set_deglitch(GPIO_CARD_UNMOUNT_1, 1);
+	at91_set_gpio_input(GPIO_KEY_POWER, 0);
+	at91_set_deglitch(GPIO_KEY_POWER, 1);
+
+	platform_device_register(&button_device);
+}
+
+/*
+ * I2C
+ */
+static int pcf8574x_0x20_setup(struct i2c_client *client, int gpio,
+				unsigned int ngpio, void *context)
+{
+	int status;
+
+	status = gpio_request(gpio + PCF_GPIO_ETH_DETECT, "eth_det");
+	if (status < 0) {
+		pr_err("error: can't request GPIO%d\n",
+			gpio + PCF_GPIO_ETH_DETECT);
+		return status;
+	}
+	status = gpio_direction_input(gpio + PCF_GPIO_ETH_DETECT);
+	if (status < 0) {
+		pr_err("error: can't setup GPIO%d as input\n",
+			gpio + PCF_GPIO_ETH_DETECT);
+		return status;
+	}
+	status = gpio_export(gpio + PCF_GPIO_ETH_DETECT, false);
+	if (status < 0) {
+		pr_err("error: can't export GPIO%d\n",
+			gpio + PCF_GPIO_ETH_DETECT);
+		return status;
+	}
+	status = gpio_sysfs_set_active_low(gpio + PCF_GPIO_ETH_DETECT, 1);
+	if (status < 0) {
+		pr_err("error: gpio_sysfs_set active_low(GPIO%d, 1)\n",
+			gpio + PCF_GPIO_ETH_DETECT);
+		return status;
+	}
+
+	return 0;
+}
+
+static int pcf8574x_0x20_teardown(struct i2c_client *client, int gpio,
+					unsigned ngpio, void *context)
+{
+	gpio_free(gpio + PCF_GPIO_ETH_DETECT);
+	return 0;
+}
+
+static struct pcf857x_platform_data pcf20_pdata = {
+	.gpio_base	= GS_IA18_S_PCF_GPIO_BASE0,
+	.n_latch	= (1 << 4),
+	.setup		= pcf8574x_0x20_setup,
+	.teardown	= pcf8574x_0x20_teardown,
+};
+
+static struct pcf857x_platform_data pcf22_pdata = {
+	.gpio_base	= GS_IA18_S_PCF_GPIO_BASE1,
+};
+
+static struct pcf857x_platform_data pcf24_pdata = {
+	.gpio_base	= GS_IA18_S_PCF_GPIO_BASE2,
+};
+
+static struct i2c_board_info __initdata gsia18s_i2c_devices[] = {
+	{ /* U1 on the GS_IA18-CB_V3 board */
+		I2C_BOARD_INFO("pcf8574", 0x20),
+		.platform_data = &pcf20_pdata,
+	},
+	{ /* U1 on the GS_2G_OPT1-A_V0 board (Alarm) */
+		I2C_BOARD_INFO("pcf8574", 0x22),
+		.platform_data = &pcf22_pdata,
+	},
+	{ /* U1 on the GS_2G-OPT23-A_V0 board (Modem) */
+		I2C_BOARD_INFO("pcf8574", 0x24),
+		.platform_data = &pcf24_pdata,
+	},
+	{ /* U161 on the GS_IA18_S-MN board */
+		I2C_BOARD_INFO("24c1024", 0x50),
+	},
+	{ /* U162 on the GS_IA18_S-MN board */
+		I2C_BOARD_INFO("24c01", 0x53),
+	},
+};
+
+/*
+ * Compact Flash
+ */
+static struct at91_cf_data __initdata gsia18s_cf1_data = {
+	.irq_pin	= AT91_PIN_PA27,
+	.det_pin	= AT91_PIN_PB30,
+	.rst_pin	= AT91_PIN_PB31,
+	.chipselect	= 5,
+	.flags		= AT91_CF_TRUE_IDE,
+};
+
+/* Power Off by RTC */
+static void gsia18s_power_off(void)
+{
+	pr_notice("Power supply will be switched off automatically now or after 60 seconds without ArmDAS.\n");
+	at91_set_gpio_output(AT91_PIN_PA25, 1);
+	/* Spin to death... */
+	while (1)
+		;
+}
+
+static int __init gsia18s_power_off_init(void)
+{
+	pm_power_off = gsia18s_power_off;
+	return 0;
+}
+
+/* ---------------------------------------------------------------------------*/
+
+static void __init gsia18s_board_init(void)
+{
+	stamp9g20_board_init();
+	at91_add_device_usbh(&usbh_data);
+	at91_add_device_udc(&udc_data);
+	at91_add_device_eth(&macb_data);
+	gsia18s_leds_init();
+	gsia18s_pcf_leds_init();
+	gsia18s_add_device_buttons();
+	at91_add_device_i2c(gsia18s_i2c_devices,
+				ARRAY_SIZE(gsia18s_i2c_devices));
+	at91_add_device_cf(&gsia18s_cf1_data);
+	at91_add_device_spi(gsia18s_spi_devices,
+				ARRAY_SIZE(gsia18s_spi_devices));
+	gsia18s_power_off_init();
+}
+
+MACHINE_START(GSIA18S, "GS_IA18_S")
+	.boot_params	= AT91_SDRAM_BASE + 0x100,
+	.timer		= &at91sam926x_timer,
+	.map_io		= gsia18s_map_io,
+	.init_irq	= init_irq,
+	.init_machine	= gsia18s_board_init,
+MACHINE_END
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-at91/board-sam9m10g45ek.c linux-libre-2.6.38-gnu1/arch/arm/mach-at91/board-sam9m10g45ek.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-at91/board-sam9m10g45ek.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-at91/board-sam9m10g45ek.c	2011-03-14 21:20:32.000000000 -0400
@@ -37,7 +37,6 @@
 #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>
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-at91/gpio.c linux-libre-2.6.38-gnu1/arch/arm/mach-at91/gpio.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-at91/gpio.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-at91/gpio.c	2011-03-14 21:20:32.000000000 -0400
@@ -274,10 +274,10 @@ EXPORT_SYMBOL(at91_get_gpio_value);
 static u32 wakeups[MAX_GPIO_BANKS];
 static u32 backups[MAX_GPIO_BANKS];
 
-static int gpio_irq_set_wake(unsigned pin, unsigned state)
+static int gpio_irq_set_wake(struct irq_data *d, unsigned state)
 {
-	unsigned	mask = pin_to_mask(pin);
-	unsigned	bank = (pin - PIN_BASE) / 32;
+	unsigned	mask = pin_to_mask(d->irq);
+	unsigned	bank = (d->irq - PIN_BASE) / 32;
 
 	if (unlikely(bank >= MAX_GPIO_BANKS))
 		return -EINVAL;
@@ -344,25 +344,25 @@ void at91_gpio_resume(void)
  * IRQ0..IRQ6 should be configurable, e.g. level vs edge triggering.
  */
 
-static void gpio_irq_mask(unsigned pin)
+static void gpio_irq_mask(struct irq_data *d)
 {
-	void __iomem	*pio = pin_to_controller(pin);
-	unsigned	mask = pin_to_mask(pin);
+	void __iomem	*pio = pin_to_controller(d->irq);
+	unsigned	mask = pin_to_mask(d->irq);
 
 	if (pio)
 		__raw_writel(mask, pio + PIO_IDR);
 }
 
-static void gpio_irq_unmask(unsigned pin)
+static void gpio_irq_unmask(struct irq_data *d)
 {
-	void __iomem	*pio = pin_to_controller(pin);
-	unsigned	mask = pin_to_mask(pin);
+	void __iomem	*pio = pin_to_controller(d->irq);
+	unsigned	mask = pin_to_mask(d->irq);
 
 	if (pio)
 		__raw_writel(mask, pio + PIO_IER);
 }
 
-static int gpio_irq_type(unsigned pin, unsigned type)
+static int gpio_irq_type(struct irq_data *d, unsigned type)
 {
 	switch (type) {
 	case IRQ_TYPE_NONE:
@@ -375,10 +375,10 @@ static int gpio_irq_type(unsigned pin, u
 
 static struct irq_chip gpio_irqchip = {
 	.name		= "GPIO",
-	.mask		= gpio_irq_mask,
-	.unmask		= gpio_irq_unmask,
-	.set_type	= gpio_irq_type,
-	.set_wake	= gpio_irq_set_wake,
+	.irq_mask	= gpio_irq_mask,
+	.irq_unmask	= gpio_irq_unmask,
+	.irq_set_type	= gpio_irq_type,
+	.irq_set_wake	= gpio_irq_set_wake,
 };
 
 static void gpio_irq_handler(unsigned irq, struct irq_desc *desc)
@@ -393,7 +393,7 @@ static void gpio_irq_handler(unsigned ir
 	pio = at91_gpio->regbase;
 
 	/* temporarily mask (level sensitive) parent IRQ */
-	desc->chip->ack(irq);
+	desc->irq_data.chip->irq_ack(&desc->irq_data);
 	for (;;) {
 		/* Reading ISR acks pending (edge triggered) GPIO interrupts.
 		 * When there none are pending, we're finished unless we need
@@ -419,7 +419,7 @@ static void gpio_irq_handler(unsigned ir
 					 * another IRQ must be generated before it actually gets
 					 * here to be disabled on the GPIO controller.
 					 */
-					gpio_irq_mask(pin);
+					gpio_irq_mask(irq_get_irq_data(pin));
 				}
 				else
 					generic_handle_irq(pin);
@@ -429,7 +429,7 @@ static void gpio_irq_handler(unsigned ir
 			isr >>= 1;
 		}
 	}
-	desc->chip->unmask(irq);
+	desc->irq_data.chip->irq_unmask(&desc->irq_data);
 	/* now it may re-trigger */
 }
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-at91/include/mach/gsia18s.h linux-libre-2.6.38-gnu1/arch/arm/mach-at91/include/mach/gsia18s.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-at91/include/mach/gsia18s.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-at91/include/mach/gsia18s.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,33 @@
+/* Buttons */
+#define GPIO_TRIG_NET_IN		AT91_PIN_PB21
+#define GPIO_CARD_UNMOUNT_0		AT91_PIN_PB13
+#define GPIO_CARD_UNMOUNT_1		AT91_PIN_PB12
+#define GPIO_KEY_POWER			AT91_PIN_PA25
+
+/* PCF8574 0x20 GPIO - U1 on the GS_IA18-CB_V3 board */
+#define GS_IA18_S_PCF_GPIO_BASE0	NR_BUILTIN_GPIO
+#define PCF_GPIO_HDC_POWER		(GS_IA18_S_PCF_GPIO_BASE0 + 0)
+#define PCF_GPIO_WIFI_SETUP		(GS_IA18_S_PCF_GPIO_BASE0 + 1)
+#define PCF_GPIO_WIFI_ENABLE		(GS_IA18_S_PCF_GPIO_BASE0 + 2)
+#define PCF_GPIO_WIFI_RESET		(GS_IA18_S_PCF_GPIO_BASE0 + 3)
+#define PCF_GPIO_ETH_DETECT		4 /* this is a GPI */
+#define PCF_GPIO_GPS_SETUP		(GS_IA18_S_PCF_GPIO_BASE0 + 5)
+#define PCF_GPIO_GPS_STANDBY		(GS_IA18_S_PCF_GPIO_BASE0 + 6)
+#define PCF_GPIO_GPS_POWER		(GS_IA18_S_PCF_GPIO_BASE0 + 7)
+
+/* PCF8574 0x22 GPIO - U1 on the GS_2G_OPT1-A_V0 board (Alarm) */
+#define GS_IA18_S_PCF_GPIO_BASE1	(GS_IA18_S_PCF_GPIO_BASE0 + 8)
+#define PCF_GPIO_ALARM1			(GS_IA18_S_PCF_GPIO_BASE1 + 0)
+#define PCF_GPIO_ALARM2			(GS_IA18_S_PCF_GPIO_BASE1 + 1)
+#define PCF_GPIO_ALARM3			(GS_IA18_S_PCF_GPIO_BASE1 + 2)
+#define PCF_GPIO_ALARM4			(GS_IA18_S_PCF_GPIO_BASE1 + 3)
+/* bits 4, 5, 6 not used */
+#define PCF_GPIO_ALARM_V_RELAY_ON	(GS_IA18_S_PCF_GPIO_BASE1 + 7)
+
+/* PCF8574 0x24 GPIO U1 on the GS_2G-OPT23-A_V0 board (Modem) */
+#define GS_IA18_S_PCF_GPIO_BASE2	(GS_IA18_S_PCF_GPIO_BASE1 + 8)
+#define PCF_GPIO_MODEM_POWER		(GS_IA18_S_PCF_GPIO_BASE2 + 0)
+#define PCF_GPIO_MODEM_RESET		(GS_IA18_S_PCF_GPIO_BASE2 + 3)
+/* bits 1, 2, 4, 5 not used */
+#define PCF_GPIO_TRX_RESET		(GS_IA18_S_PCF_GPIO_BASE2 + 6)
+/* bit 7 not used */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-at91/irq.c linux-libre-2.6.38-gnu1/arch/arm/mach-at91/irq.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-at91/irq.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-at91/irq.c	2011-03-14 21:20:32.000000000 -0400
@@ -34,23 +34,23 @@
 #include <asm/mach/map.h>
 
 
-static void at91_aic_mask_irq(unsigned int irq)
+static void at91_aic_mask_irq(struct irq_data *d)
 {
 	/* Disable interrupt on AIC */
-	at91_sys_write(AT91_AIC_IDCR, 1 << irq);
+	at91_sys_write(AT91_AIC_IDCR, 1 << d->irq);
 }
 
-static void at91_aic_unmask_irq(unsigned int irq)
+static void at91_aic_unmask_irq(struct irq_data *d)
 {
 	/* Enable interrupt on AIC */
-	at91_sys_write(AT91_AIC_IECR, 1 << irq);
+	at91_sys_write(AT91_AIC_IECR, 1 << d->irq);
 }
 
 unsigned int at91_extern_irq;
 
 #define is_extern_irq(irq) ((1 << (irq)) & at91_extern_irq)
 
-static int at91_aic_set_type(unsigned irq, unsigned type)
+static int at91_aic_set_type(struct irq_data *d, unsigned type)
 {
 	unsigned int smr, srctype;
 
@@ -62,13 +62,13 @@ static int at91_aic_set_type(unsigned ir
 		srctype = AT91_AIC_SRCTYPE_RISING;
 		break;
 	case IRQ_TYPE_LEVEL_LOW:
-		if ((irq == AT91_ID_FIQ) || is_extern_irq(irq))		/* only supported on external interrupts */
+		if ((d->irq == AT91_ID_FIQ) || is_extern_irq(d->irq))		/* only supported on external interrupts */
 			srctype = AT91_AIC_SRCTYPE_LOW;
 		else
 			return -EINVAL;
 		break;
 	case IRQ_TYPE_EDGE_FALLING:
-		if ((irq == AT91_ID_FIQ) || is_extern_irq(irq))		/* only supported on external interrupts */
+		if ((d->irq == AT91_ID_FIQ) || is_extern_irq(d->irq))		/* only supported on external interrupts */
 			srctype = AT91_AIC_SRCTYPE_FALLING;
 		else
 			return -EINVAL;
@@ -77,8 +77,8 @@ static int at91_aic_set_type(unsigned ir
 		return -EINVAL;
 	}
 
-	smr = at91_sys_read(AT91_AIC_SMR(irq)) & ~AT91_AIC_SRCTYPE;
-	at91_sys_write(AT91_AIC_SMR(irq), smr | srctype);
+	smr = at91_sys_read(AT91_AIC_SMR(d->irq)) & ~AT91_AIC_SRCTYPE;
+	at91_sys_write(AT91_AIC_SMR(d->irq), smr | srctype);
 	return 0;
 }
 
@@ -87,15 +87,15 @@ static int at91_aic_set_type(unsigned ir
 static u32 wakeups;
 static u32 backups;
 
-static int at91_aic_set_wake(unsigned irq, unsigned value)
+static int at91_aic_set_wake(struct irq_data *d, unsigned value)
 {
-	if (unlikely(irq >= 32))
+	if (unlikely(d->irq >= 32))
 		return -EINVAL;
 
 	if (value)
-		wakeups |= (1 << irq);
+		wakeups |= (1 << d->irq);
 	else
-		wakeups &= ~(1 << irq);
+		wakeups &= ~(1 << d->irq);
 
 	return 0;
 }
@@ -119,11 +119,11 @@ void at91_irq_resume(void)
 
 static struct irq_chip at91_aic_chip = {
 	.name		= "AIC",
-	.ack		= at91_aic_mask_irq,
-	.mask		= at91_aic_mask_irq,
-	.unmask		= at91_aic_unmask_irq,
-	.set_type	= at91_aic_set_type,
-	.set_wake	= at91_aic_set_wake,
+	.irq_ack	= at91_aic_mask_irq,
+	.irq_mask	= at91_aic_mask_irq,
+	.irq_unmask	= at91_aic_unmask_irq,
+	.irq_set_type	= at91_aic_set_type,
+	.irq_set_wake	= at91_aic_set_wake,
 };
 
 /*
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-at91/Kconfig linux-libre-2.6.38-gnu1/arch/arm/mach-at91/Kconfig
--- linux-libre-2.6.37-gnu1/arch/arm/mach-at91/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-at91/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -362,6 +362,12 @@ config MACH_CPU9G20
 	  Select this if you are using a Eukrea Electromatique's
 	  CPU9G20 Board <http://www.eukrea.com/>
 
+config MACH_ACMENETUSFOXG20
+	bool "Acme Systems srl FOX Board G20"
+	help
+	  Select this if you are using Acme Systems
+	  FOX Board G20 <http://www.acmesystems.it>
+
 config MACH_PORTUXG20
 	bool "taskit PortuxG20"
 	help
@@ -381,6 +387,13 @@ config MACH_PCONTROL_G20
 	  Select this if you are using taskit's Stamp9G20 CPU module on this
 	  carrier board, beeing the decentralized unit of a building automation
 	  system; featuring nvram, eth-switch, iso-rs485, display, io
+
+config MACH_GSIA18S
+	bool "GS_IA18_S board"
+	help
+	  This enables support for the GS_IA18_S board
+	  produced by GeoSIG Ltd company. This is an internet accelerograph.
+	  <http://www.geosig.com>
 endif
 
 if (ARCH_AT91SAM9260 || ARCH_AT91SAM9G20)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-at91/Makefile linux-libre-2.6.38-gnu1/arch/arm/mach-at91/Makefile
--- linux-libre-2.6.37-gnu1/arch/arm/mach-at91/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-at91/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -63,9 +63,11 @@ obj-$(CONFIG_MACH_AT91SAM9RLEK)	+= board
 # AT91SAM9G20 board-specific support
 obj-$(CONFIG_MACH_AT91SAM9G20EK) += board-sam9g20ek.o
 obj-$(CONFIG_MACH_CPU9G20)	+= board-cpu9krea.o
+obj-$(CONFIG_MACH_ACMENETUSFOXG20) += board-foxg20.o
 obj-$(CONFIG_MACH_STAMP9G20)	+= board-stamp9g20.o
 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
 
 # AT91SAM9260/AT91SAM9G20 board-specific support
 obj-$(CONFIG_MACH_SNAPPER_9260)	+= board-snapper9260.o
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-at91/pm.c linux-libre-2.6.38-gnu1/arch/arm/mach-at91/pm.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-at91/pm.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-at91/pm.c	2011-03-14 21:20:32.000000000 -0400
@@ -301,7 +301,7 @@ static void at91_pm_end(void)
 }
 
 
-static struct platform_suspend_ops at91_pm_ops ={
+static const struct platform_suspend_ops at91_pm_ops = {
 	.valid	= at91_pm_valid_state,
 	.begin	= at91_pm_begin,
 	.enter	= at91_pm_enter,
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-bcmring/clock.c linux-libre-2.6.38-gnu1/arch/arm/mach-bcmring/clock.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-bcmring/clock.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-bcmring/clock.c	2011-03-14 21:20:32.000000000 -0400
@@ -21,13 +21,12 @@
 #include <linux/string.h>
 #include <linux/clk.h>
 #include <linux/spinlock.h>
+#include <linux/clkdev.h>
 #include <mach/csp/hw_cfg.h>
 #include <mach/csp/chipcHw_def.h>
 #include <mach/csp/chipcHw_reg.h>
 #include <mach/csp/chipcHw_inline.h>
 
-#include <asm/clkdev.h>
-
 #include "clock.h"
 
 #define clk_is_primary(x)       ((x)->type & CLK_TYPE_PRIMARY)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-bcmring/core.c linux-libre-2.6.38-gnu1/arch/arm/mach-bcmring/core.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-bcmring/core.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-bcmring/core.c	2011-03-14 21:20:32.000000000 -0400
@@ -30,10 +30,10 @@
 #include <linux/amba/bus.h>
 #include <linux/clocksource.h>
 #include <linux/clockchips.h>
+#include <linux/clkdev.h>
 
 #include <mach/csp/mm_addr.h>
 #include <mach/hardware.h>
-#include <asm/clkdev.h>
 #include <linux/io.h>
 #include <asm/irq.h>
 #include <asm/hardware/arm_timer.h>
@@ -294,7 +294,6 @@ static struct clocksource clocksource_bc
 	.rating = 200,
 	.read = bcmring_get_cycles_timer1,
 	.mask = CLOCKSOURCE_MASK(32),
-	.shift = 20,
 	.flags = CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
@@ -303,7 +302,6 @@ static struct clocksource clocksource_bc
 	.rating = 100,
 	.read = bcmring_get_cycles_timer3,
 	.mask = CLOCKSOURCE_MASK(32),
-	.shift = 20,
 	.flags = CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
@@ -316,10 +314,8 @@ static int __init bcmring_clocksource_in
 	writel(TIMER_CTRL_32BIT | TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC,
 	       TIMER1_VA_BASE + TIMER_CTRL);
 
-	clocksource_bcmring_timer1.mult =
-	    clocksource_khz2mult(TIMER1_FREQUENCY_MHZ * 1000,
-				 clocksource_bcmring_timer1.shift);
-	clocksource_register(&clocksource_bcmring_timer1);
+	clocksource_register_khz(&clocksource_bcmring_timer1,
+				 TIMER1_FREQUENCY_MHZ * 1000);
 
 	/* setup timer3 as free-running clocksource */
 	writel(0, TIMER3_VA_BASE + TIMER_CTRL);
@@ -328,10 +324,8 @@ static int __init bcmring_clocksource_in
 	writel(TIMER_CTRL_32BIT | TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC,
 	       TIMER3_VA_BASE + TIMER_CTRL);
 
-	clocksource_bcmring_timer3.mult =
-	    clocksource_khz2mult(TIMER3_FREQUENCY_KHZ,
-				 clocksource_bcmring_timer3.shift);
-	clocksource_register(&clocksource_bcmring_timer3);
+	clocksource_register_khz(&clocksource_bcmring_timer3,
+				 TIMER3_FREQUENCY_KHZ);
 
 	return 0;
 }
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-bcmring/csp/chipc/chipcHw.c linux-libre-2.6.38-gnu1/arch/arm/mach-bcmring/csp/chipc/chipcHw.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-bcmring/csp/chipc/chipcHw.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-bcmring/csp/chipc/chipcHw.c	2011-03-14 21:20:32.000000000 -0400
@@ -757,7 +757,7 @@ static int chipcHw_divide(int num, int d
 		t = t << 1;
 	}
 
-	/* Intialize the result */
+	/* Initialize the result */
 	r = 0;
 
 	do {
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-bcmring/csp/dmac/dmacHw.c linux-libre-2.6.38-gnu1/arch/arm/mach-bcmring/csp/dmac/dmacHw.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-bcmring/csp/dmac/dmacHw.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-bcmring/csp/dmac/dmacHw.c	2011-03-14 21:20:32.000000000 -0400
@@ -893,7 +893,7 @@ int dmacHw_setDataDescriptor(dmacHw_CONF
 */
 /****************************************************************************/
 uint32_t dmacHw_getDmaControllerAttribute(dmacHw_HANDLE_t handle,	/*  [ IN ]  DMA Channel handle */
-					  dmacHw_CONTROLLER_ATTRIB_e attr	/*  [ IN ]  DMA Controler attribute of type  dmacHw_CONTROLLER_ATTRIB_e */
+					  dmacHw_CONTROLLER_ATTRIB_e attr	/*  [ IN ]  DMA Controller attribute of type  dmacHw_CONTROLLER_ATTRIB_e */
     ) {
 	dmacHw_CBLK_t *pCblk = dmacHw_HANDLE_TO_CBLK(handle);
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-bcmring/csp/dmac/dmacHw_extra.c linux-libre-2.6.38-gnu1/arch/arm/mach-bcmring/csp/dmac/dmacHw_extra.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-bcmring/csp/dmac/dmacHw_extra.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-bcmring/csp/dmac/dmacHw_extra.c	2011-03-14 21:20:32.000000000 -0400
@@ -316,7 +316,7 @@ static void DisplayDescRing(void *pDescr
 /**
 *  @brief   Check if DMA channel is the flow controller
 *
-*  @return  1 : If DMA is a flow controler
+*  @return  1 : If DMA is a flow controller
 *           0 : Peripheral is the flow controller
 *
 *  @note
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-bcmring/csp/tmr/tmrHw.c linux-libre-2.6.38-gnu1/arch/arm/mach-bcmring/csp/tmr/tmrHw.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-bcmring/csp/tmr/tmrHw.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-bcmring/csp/tmr/tmrHw.c	2011-03-14 21:20:32.000000000 -0400
@@ -558,7 +558,7 @@ static int tmrHw_divide(int num, int den
 		t = t << 1;
 	}
 
-	/* Intialize the result */
+	/* Initialize the result */
 	r = 0;
 
 	do {
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-bcmring/dma.c linux-libre-2.6.38-gnu1/arch/arm/mach-bcmring/dma.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-bcmring/dma.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-bcmring/dma.c	2011-03-14 21:20:32.000000000 -0400
@@ -671,7 +671,7 @@ static int ConfigChannel(DMA_Handle_t ha
 
 /****************************************************************************/
 /**
-*   Intializes all of the data structures associated with the DMA.
+*   Initializes all of the data structures associated with the DMA.
 *   @return
 *       >= 0    - Initialization was successfull.
 *
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-bcmring/include/csp/dmacHw.h linux-libre-2.6.38-gnu1/arch/arm/mach-bcmring/include/csp/dmacHw.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-bcmring/include/csp/dmacHw.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-bcmring/include/csp/dmacHw.h	2011-03-14 21:20:32.000000000 -0400
@@ -590,7 +590,7 @@ void dmacHw_printDebugInfo(dmacHw_HANDLE
 */
 /****************************************************************************/
 uint32_t dmacHw_getDmaControllerAttribute(dmacHw_HANDLE_t handle,	/*  [ IN ]  DMA Channel handle  */
-					  dmacHw_CONTROLLER_ATTRIB_e attr	/*  [ IN ]  DMA Controler attribute of type  dmacHw_CONTROLLER_ATTRIB_e */
+					  dmacHw_CONTROLLER_ATTRIB_e attr	/*  [ IN ]  DMA Controller attribute of type  dmacHw_CONTROLLER_ATTRIB_e */
     );
 
 #endif /* _DMACHW_H */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-bcmring/include/csp/tmrHw.h linux-libre-2.6.38-gnu1/arch/arm/mach-bcmring/include/csp/tmrHw.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-bcmring/include/csp/tmrHw.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-bcmring/include/csp/tmrHw.h	2011-03-14 21:20:32.000000000 -0400
@@ -76,7 +76,7 @@ tmrHw_RATE_t tmrHw_setPeriodicTimerRate(
 *           certain time interval
 *
 *  This function initializes a periodic timer to generate timer interrupt
-*  after every time interval in milisecond
+*  after every time interval in millisecond
 *
 *  @return   On success: Effective interval set in mili-second
 *            On failure: 0
@@ -93,7 +93,7 @@ tmrHw_INTERVAL_t tmrHw_setPeriodicTimerI
 *           after certain time interval
 *
 *  This function initializes a periodic timer to generate a single ticks after
-*  certain time interval in milisecond
+*  certain time interval in millisecond
 *
 *  @return   On success: Effective interval set in mili-second
 *            On failure: 0
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-bcmring/include/mach/csp/dmacHw_priv.h linux-libre-2.6.38-gnu1/arch/arm/mach-bcmring/include/mach/csp/dmacHw_priv.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-bcmring/include/mach/csp/dmacHw_priv.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-bcmring/include/mach/csp/dmacHw_priv.h	2011-03-14 21:20:32.000000000 -0400
@@ -28,7 +28,7 @@
 
 /* Data type for DMA Link List Item */
 typedef struct {
-	uint32_t sar;		/* Source Adress Register.
+	uint32_t sar;		/* Source Address Register.
 				   Address must be aligned to CTLx.SRC_TR_WIDTH.             */
 	uint32_t dar;		/* Destination Address Register.
 				   Address must be aligned to CTLx.DST_TR_WIDTH.             */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-bcmring/include/mach/csp/dmacHw_reg.h linux-libre-2.6.38-gnu1/arch/arm/mach-bcmring/include/mach/csp/dmacHw_reg.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-bcmring/include/mach/csp/dmacHw_reg.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-bcmring/include/mach/csp/dmacHw_reg.h	2011-03-14 21:20:32.000000000 -0400
@@ -35,7 +35,7 @@ typedef struct {
 
 /* Data type representing DMA channel registers */
 typedef struct {
-	dmacHw_REG64_t ChannelSar;	/*  Source Adress Register. 64 bits (upper 32 bits are reserved)
+	dmacHw_REG64_t ChannelSar;	/*  Source Address Register. 64 bits (upper 32 bits are reserved)
 					   Address must be aligned to CTLx.SRC_TR_WIDTH.
 					 */
 	dmacHw_REG64_t ChannelDar;	/*  Destination Address Register.64 bits (upper 32 bits are reserved)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-bcmring/irq.c linux-libre-2.6.38-gnu1/arch/arm/mach-bcmring/irq.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-bcmring/irq.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-bcmring/irq.c	2011-03-14 21:20:32.000000000 -0400
@@ -30,61 +30,61 @@
 #include <mach/csp/intcHw_reg.h>
 #include <mach/csp/mm_io.h>
 
-static void bcmring_mask_irq0(unsigned int irq)
+static void bcmring_mask_irq0(struct irq_data *d)
 {
-	writel(1 << (irq - IRQ_INTC0_START),
+	writel(1 << (d->irq - IRQ_INTC0_START),
 	       MM_IO_BASE_INTC0 + INTCHW_INTENCLEAR);
 }
 
-static void bcmring_unmask_irq0(unsigned int irq)
+static void bcmring_unmask_irq0(struct irq_data *d)
 {
-	writel(1 << (irq - IRQ_INTC0_START),
+	writel(1 << (d->irq - IRQ_INTC0_START),
 	       MM_IO_BASE_INTC0 + INTCHW_INTENABLE);
 }
 
-static void bcmring_mask_irq1(unsigned int irq)
+static void bcmring_mask_irq1(struct irq_data *d)
 {
-	writel(1 << (irq - IRQ_INTC1_START),
+	writel(1 << (d->irq - IRQ_INTC1_START),
 	       MM_IO_BASE_INTC1 + INTCHW_INTENCLEAR);
 }
 
-static void bcmring_unmask_irq1(unsigned int irq)
+static void bcmring_unmask_irq1(struct irq_data *d)
 {
-	writel(1 << (irq - IRQ_INTC1_START),
+	writel(1 << (d->irq - IRQ_INTC1_START),
 	       MM_IO_BASE_INTC1 + INTCHW_INTENABLE);
 }
 
-static void bcmring_mask_irq2(unsigned int irq)
+static void bcmring_mask_irq2(struct irq_data *d)
 {
-	writel(1 << (irq - IRQ_SINTC_START),
+	writel(1 << (d->irq - IRQ_SINTC_START),
 	       MM_IO_BASE_SINTC + INTCHW_INTENCLEAR);
 }
 
-static void bcmring_unmask_irq2(unsigned int irq)
+static void bcmring_unmask_irq2(struct irq_data *d)
 {
-	writel(1 << (irq - IRQ_SINTC_START),
+	writel(1 << (d->irq - IRQ_SINTC_START),
 	       MM_IO_BASE_SINTC + INTCHW_INTENABLE);
 }
 
 static struct irq_chip bcmring_irq0_chip = {
 	.name = "ARM-INTC0",
-	.ack = bcmring_mask_irq0,
-	.mask = bcmring_mask_irq0,	/* mask a specific interrupt, blocking its delivery. */
-	.unmask = bcmring_unmask_irq0,	/* unmaks an interrupt */
+	.irq_ack = bcmring_mask_irq0,
+	.irq_mask = bcmring_mask_irq0,	/* mask a specific interrupt, blocking its delivery. */
+	.irq_unmask = bcmring_unmask_irq0,	/* unmaks an interrupt */
 };
 
 static struct irq_chip bcmring_irq1_chip = {
 	.name = "ARM-INTC1",
-	.ack = bcmring_mask_irq1,
-	.mask = bcmring_mask_irq1,
-	.unmask = bcmring_unmask_irq1,
+	.irq_ack = bcmring_mask_irq1,
+	.irq_mask = bcmring_mask_irq1,
+	.irq_unmask = bcmring_unmask_irq1,
 };
 
 static struct irq_chip bcmring_irq2_chip = {
 	.name = "ARM-SINTC",
-	.ack = bcmring_mask_irq2,
-	.mask = bcmring_mask_irq2,
-	.unmask = bcmring_unmask_irq2,
+	.irq_ack = bcmring_mask_irq2,
+	.irq_mask = bcmring_mask_irq2,
+	.irq_unmask = bcmring_unmask_irq2,
 };
 
 static void vic_init(void __iomem *base, struct irq_chip *chip,
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-clps711x/irq.c linux-libre-2.6.38-gnu1/arch/arm/mach-clps711x/irq.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-clps711x/irq.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-clps711x/irq.c	2011-03-14 21:20:32.000000000 -0400
@@ -27,24 +27,24 @@
 
 #include <asm/hardware/clps7111.h>
 
-static void int1_mask(unsigned int irq)
+static void int1_mask(struct irq_data *d)
 {
 	u32 intmr1;
 
 	intmr1 = clps_readl(INTMR1);
-	intmr1 &= ~(1 << irq);
+	intmr1 &= ~(1 << d->irq);
 	clps_writel(intmr1, INTMR1);
 }
 
-static void int1_ack(unsigned int irq)
+static void int1_ack(struct irq_data *d)
 {
 	u32 intmr1;
 
 	intmr1 = clps_readl(INTMR1);
-	intmr1 &= ~(1 << irq);
+	intmr1 &= ~(1 << d->irq);
 	clps_writel(intmr1, INTMR1);
 
-	switch (irq) {
+	switch (d->irq) {
 	case IRQ_CSINT:  clps_writel(0, COEOI);  break;
 	case IRQ_TC1OI:  clps_writel(0, TC1EOI); break;
 	case IRQ_TC2OI:  clps_writel(0, TC2EOI); break;
@@ -54,56 +54,56 @@ static void int1_ack(unsigned int irq)
 	}
 }
 
-static void int1_unmask(unsigned int irq)
+static void int1_unmask(struct irq_data *d)
 {
 	u32 intmr1;
 
 	intmr1 = clps_readl(INTMR1);
-	intmr1 |= 1 << irq;
+	intmr1 |= 1 << d->irq;
 	clps_writel(intmr1, INTMR1);
 }
 
 static struct irq_chip int1_chip = {
-	.ack	= int1_ack,
-	.mask	= int1_mask,
-	.unmask = int1_unmask,
+	.irq_ack	= int1_ack,
+	.irq_mask	= int1_mask,
+	.irq_unmask	= int1_unmask,
 };
 
-static void int2_mask(unsigned int irq)
+static void int2_mask(struct irq_data *d)
 {
 	u32 intmr2;
 
 	intmr2 = clps_readl(INTMR2);
-	intmr2 &= ~(1 << (irq - 16));
+	intmr2 &= ~(1 << (d->irq - 16));
 	clps_writel(intmr2, INTMR2);
 }
 
-static void int2_ack(unsigned int irq)
+static void int2_ack(struct irq_data *d)
 {
 	u32 intmr2;
 
 	intmr2 = clps_readl(INTMR2);
-	intmr2 &= ~(1 << (irq - 16));
+	intmr2 &= ~(1 << (d->irq - 16));
 	clps_writel(intmr2, INTMR2);
 
-	switch (irq) {
+	switch (d->irq) {
 	case IRQ_KBDINT: clps_writel(0, KBDEOI); break;
 	}
 }
 
-static void int2_unmask(unsigned int irq)
+static void int2_unmask(struct irq_data *d)
 {
 	u32 intmr2;
 
 	intmr2 = clps_readl(INTMR2);
-	intmr2 |= 1 << (irq - 16);
+	intmr2 |= 1 << (d->irq - 16);
 	clps_writel(intmr2, INTMR2);
 }
 
 static struct irq_chip int2_chip = {
-	.ack	= int2_ack,
-	.mask	= int2_mask,
-	.unmask = int2_unmask,
+	.irq_ack	= int2_ack,
+	.irq_mask	= int2_mask,
+	.irq_unmask	= int2_unmask,
 };
 
 void __init clps711x_init_irq(void)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-cns3xxx/cns3420vb.c linux-libre-2.6.38-gnu1/arch/arm/mach-cns3xxx/cns3420vb.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-cns3xxx/cns3420vb.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-cns3xxx/cns3420vb.c	2011-03-14 21:20:32.000000000 -0400
@@ -17,6 +17,7 @@
 #include <linux/kernel.h>
 #include <linux/compiler.h>
 #include <linux/io.h>
+#include <linux/dma-mapping.h>
 #include <linux/serial_core.h>
 #include <linux/serial_8250.h>
 #include <linux/platform_device.h>
@@ -108,10 +109,63 @@ static void __init cns3420_early_serial_
 }
 
 /*
+ * USB
+ */
+static struct resource cns3xxx_usb_ehci_resources[] = {
+	[0] = {
+		.start = CNS3XXX_USB_BASE,
+		.end   = CNS3XXX_USB_BASE + SZ_16M - 1,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = IRQ_CNS3XXX_USB_EHCI,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+static u64 cns3xxx_usb_ehci_dma_mask = DMA_BIT_MASK(32);
+
+static struct platform_device cns3xxx_usb_ehci_device = {
+	.name          = "cns3xxx-ehci",
+	.num_resources = ARRAY_SIZE(cns3xxx_usb_ehci_resources),
+	.resource      = cns3xxx_usb_ehci_resources,
+	.dev           = {
+		.dma_mask          = &cns3xxx_usb_ehci_dma_mask,
+		.coherent_dma_mask = DMA_BIT_MASK(32),
+	},
+};
+
+static struct resource cns3xxx_usb_ohci_resources[] = {
+	[0] = {
+		.start = CNS3XXX_USB_OHCI_BASE,
+		.end   = CNS3XXX_USB_OHCI_BASE + SZ_16M - 1,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = IRQ_CNS3XXX_USB_OHCI,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+static u64 cns3xxx_usb_ohci_dma_mask = DMA_BIT_MASK(32);
+
+static struct platform_device cns3xxx_usb_ohci_device = {
+	.name          = "cns3xxx-ohci",
+	.num_resources = ARRAY_SIZE(cns3xxx_usb_ohci_resources),
+	.resource      = cns3xxx_usb_ohci_resources,
+	.dev           = {
+		.dma_mask          = &cns3xxx_usb_ohci_dma_mask,
+		.coherent_dma_mask = DMA_BIT_MASK(32),
+	},
+};
+
+/*
  * Initialization
  */
 static struct platform_device *cns3420_pdevs[] __initdata = {
 	&cns3420_nor_pdev,
+	&cns3xxx_usb_ehci_device,
+	&cns3xxx_usb_ohci_device,
 };
 
 static void __init cns3420_init(void)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-cns3xxx/core.c linux-libre-2.6.38-gnu1/arch/arm/mach-cns3xxx/core.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-cns3xxx/core.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-cns3xxx/core.c	2011-03-14 21:20:32.000000000 -0400
@@ -69,13 +69,10 @@ void __init cns3xxx_map_io(void)
 }
 
 /* used by entry-macro.S */
-void __iomem *gic_cpu_base_addr;
-
 void __init cns3xxx_init_irq(void)
 {
-	gic_cpu_base_addr = __io(CNS3XXX_TC11MP_GIC_CPU_BASE_VIRT);
-	gic_dist_init(0, __io(CNS3XXX_TC11MP_GIC_DIST_BASE_VIRT), 29);
-	gic_cpu_init(0, gic_cpu_base_addr);
+	gic_init(0, 29, __io(CNS3XXX_TC11MP_GIC_DIST_BASE_VIRT),
+		 __io(CNS3XXX_TC11MP_GIC_CPU_BASE_VIRT));
 }
 
 void cns3xxx_power_off(void)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-cns3xxx/core.h linux-libre-2.6.38-gnu1/arch/arm/mach-cns3xxx/core.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-cns3xxx/core.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-cns3xxx/core.h	2011-03-14 21:20:32.000000000 -0400
@@ -11,13 +11,10 @@
 #ifndef __CNS3XXX_CORE_H
 #define __CNS3XXX_CORE_H
 
-extern void __iomem *gic_cpu_base_addr;
 extern struct sys_timer cns3xxx_timer;
 
 void __init cns3xxx_map_io(void);
 void __init cns3xxx_init_irq(void);
 void cns3xxx_power_off(void);
-void cns3xxx_pwr_power_up(unsigned int block);
-void cns3xxx_pwr_power_down(unsigned int block);
 
 #endif /* __CNS3XXX_CORE_H */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-cns3xxx/devices.c linux-libre-2.6.38-gnu1/arch/arm/mach-cns3xxx/devices.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-cns3xxx/devices.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-cns3xxx/devices.c	2011-03-14 21:20:32.000000000 -0400
@@ -18,6 +18,7 @@
 #include <linux/platform_device.h>
 #include <mach/cns3xxx.h>
 #include <mach/irqs.h>
+#include <mach/pm.h>
 #include "core.h"
 #include "devices.h"
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-cns3xxx/include/mach/cns3xxx.h linux-libre-2.6.38-gnu1/arch/arm/mach-cns3xxx/include/mach/cns3xxx.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-cns3xxx/include/mach/cns3xxx.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-cns3xxx/include/mach/cns3xxx.h	2011-03-14 21:20:32.000000000 -0400
@@ -165,7 +165,6 @@
 #define CNS3XXX_USBOTG_BASE_VIRT		0xFFF15000
 
 #define CNS3XXX_USB_BASE			0x82000000	/* USB Host Control */
-#define CNS3XXX_USB_BASE_VIRT			0xFFF16000
 
 #define CNS3XXX_SATA2_BASE			0x83000000	/* SATA */
 #define CNS3XXX_SATA2_SIZE			SZ_16M
@@ -184,7 +183,6 @@
 #define CNS3XXX_2DG_BASE_VIRT			0xFFF1B000
 
 #define CNS3XXX_USB_OHCI_BASE			0x88000000	/* USB OHCI */
-#define CNS3XXX_USB_OHCI_BASE_VIRT		0xFFF1C000
 
 #define CNS3XXX_L2C_BASE			0x92000000	/* L2 Cache Control */
 #define CNS3XXX_L2C_BASE_VIRT			0xFFF27000
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-cns3xxx/include/mach/entry-macro.S linux-libre-2.6.38-gnu1/arch/arm/mach-cns3xxx/include/mach/entry-macro.S
--- linux-libre-2.6.37-gnu1/arch/arm/mach-cns3xxx/include/mach/entry-macro.S	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-cns3xxx/include/mach/entry-macro.S	2011-03-14 21:20:32.000000000 -0400
@@ -9,74 +9,10 @@
  */
 
 #include <mach/hardware.h>
-#include <asm/hardware/gic.h>
+#include <asm/hardware/entry-macro-gic.S>
 
 		.macro	disable_fiq
 		.endm
 
-		.macro  get_irqnr_preamble, base, tmp
-		ldr	\base, =gic_cpu_base_addr
-		ldr	\base, [\base]
-		.endm
-
 		.macro  arch_ret_to_user, tmp1, tmp2
 		.endm
-
-		/*
-		 * The interrupt numbering scheme is defined in the
-		 * interrupt controller spec.  To wit:
-		 *
-		 * Interrupts 0-15 are IPI
-		 * 16-28 are reserved
-		 * 29-31 are local.  We allow 30 to be used for the watchdog.
-		 * 32-1020 are global
-		 * 1021-1022 are reserved
-		 * 1023 is "spurious" (no interrupt)
-		 *
-		 * For now, we ignore all local interrupts so only return an interrupt if it's
-		 * between 30 and 1020.  The test_for_ipi routine below will pick up on IPIs.
-		 *
-		 * A simple read from the controller will tell us the number of the highest
-                 * priority enabled interrupt.  We then just need to check whether it is in the
-		 * valid range for an IRQ (30-1020 inclusive).
-		 */
-
-		.macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
-
-		ldr     \irqstat, [\base, #GIC_CPU_INTACK] /* bits 12-10 = src CPU, 9-0 = int # */
-
-		ldr	\tmp, =1021
-
-		bic     \irqnr, \irqstat, #0x1c00
-
-		cmp     \irqnr, #29
-		cmpcc	\irqnr, \irqnr
-		cmpne	\irqnr, \tmp
-		cmpcs	\irqnr, \irqnr
-
-		.endm
-
-		/* We assume that irqstat (the raw value of the IRQ acknowledge
-		 * register) is preserved from the macro above.
-		 * If there is an IPI, we immediately signal end of interrupt on the
-		 * controller, since this requires the original irqstat value which
-		 * we won't easily be able to recreate later.
-		 */
-
-		.macro test_for_ipi, irqnr, irqstat, base, tmp
-		bic	\irqnr, \irqstat, #0x1c00
-		cmp	\irqnr, #16
-		strcc	\irqstat, [\base, #GIC_CPU_EOI]
-		cmpcs	\irqnr, \irqnr
-		.endm
-
-		/* As above, this assumes that irqstat and base are preserved.. */
-
-		.macro test_for_ltirq, irqnr, irqstat, base, tmp
-		bic	\irqnr, \irqstat, #0x1c00
-		mov 	\tmp, #0
-		cmp	\irqnr, #29
-		moveq	\tmp, #1
-		streq	\irqstat, [\base, #GIC_CPU_EOI]
-		cmp	\tmp, #0
-		.endm
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-cns3xxx/include/mach/pm.h linux-libre-2.6.38-gnu1/arch/arm/mach-cns3xxx/include/mach/pm.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-cns3xxx/include/mach/pm.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-cns3xxx/include/mach/pm.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2000 Deep Blue Solutions Ltd
+ * Copyright 2004 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 __CNS3XXX_PM_H
+#define __CNS3XXX_PM_H
+
+#include <asm/atomic.h>
+
+void cns3xxx_pwr_clk_en(unsigned int block);
+void cns3xxx_pwr_clk_dis(unsigned int block);
+void cns3xxx_pwr_power_up(unsigned int block);
+void cns3xxx_pwr_power_down(unsigned int block);
+
+extern atomic_t usb_pwr_ref;
+
+#endif /* __CNS3XXX_PM_H */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-cns3xxx/Kconfig linux-libre-2.6.38-gnu1/arch/arm/mach-cns3xxx/Kconfig
--- linux-libre-2.6.37-gnu1/arch/arm/mach-cns3xxx/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-cns3xxx/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -3,6 +3,7 @@ menu "CNS3XXX platform type"
 
 config MACH_CNS3420VB
 	bool "Support for CNS3420 Validation Board"
+	select MIGHT_HAVE_PCI
 	help
 	  Include support for the Cavium Networks CNS3420 MPCore Platform
 	  Baseboard.
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-cns3xxx/pm.c linux-libre-2.6.38-gnu1/arch/arm/mach-cns3xxx/pm.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-cns3xxx/pm.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-cns3xxx/pm.c	2011-03-14 21:20:32.000000000 -0400
@@ -6,10 +6,14 @@
  * published by the Free Software Foundation.
  */
 
+#include <linux/init.h>
+#include <linux/module.h>
 #include <linux/io.h>
 #include <linux/delay.h>
+#include <asm/atomic.h>
 #include <mach/system.h>
 #include <mach/cns3xxx.h>
+#include <mach/pm.h>
 
 void cns3xxx_pwr_clk_en(unsigned int block)
 {
@@ -18,6 +22,16 @@ void cns3xxx_pwr_clk_en(unsigned int blo
 	reg |= (block & PM_CLK_GATE_REG_MASK);
 	__raw_writel(reg, PM_CLK_GATE_REG);
 }
+EXPORT_SYMBOL(cns3xxx_pwr_clk_en);
+
+void cns3xxx_pwr_clk_dis(unsigned int block)
+{
+	u32 reg = __raw_readl(PM_CLK_GATE_REG);
+
+	reg &= ~(block & PM_CLK_GATE_REG_MASK);
+	__raw_writel(reg, PM_CLK_GATE_REG);
+}
+EXPORT_SYMBOL(cns3xxx_pwr_clk_dis);
 
 void cns3xxx_pwr_power_up(unsigned int block)
 {
@@ -29,6 +43,7 @@ void cns3xxx_pwr_power_up(unsigned int b
 	/* Wait for 300us for the PLL output clock locked. */
 	udelay(300);
 };
+EXPORT_SYMBOL(cns3xxx_pwr_power_up);
 
 void cns3xxx_pwr_power_down(unsigned int block)
 {
@@ -38,6 +53,7 @@ void cns3xxx_pwr_power_down(unsigned int
 	reg |= (block & CNS3XXX_PWR_PLL_ALL);
 	__raw_writel(reg, PM_PLL_HM_PD_CTRL_REG);
 };
+EXPORT_SYMBOL(cns3xxx_pwr_power_down);
 
 static void cns3xxx_pwr_soft_rst_force(unsigned int block)
 {
@@ -51,11 +67,13 @@ static void cns3xxx_pwr_soft_rst_force(u
 		reg &= ~(block & PM_SOFT_RST_REG_MASK);
 	} else {
 		reg &= ~(block & PM_SOFT_RST_REG_MASK);
+		__raw_writel(reg, PM_SOFT_RST_REG);
 		reg |= (block & PM_SOFT_RST_REG_MASK);
 	}
 
 	__raw_writel(reg, PM_SOFT_RST_REG);
 }
+EXPORT_SYMBOL(cns3xxx_pwr_soft_rst_force);
 
 void cns3xxx_pwr_soft_rst(unsigned int block)
 {
@@ -69,6 +87,7 @@ void cns3xxx_pwr_soft_rst(unsigned int b
 	}
 	cns3xxx_pwr_soft_rst_force(block);
 }
+EXPORT_SYMBOL(cns3xxx_pwr_soft_rst);
 
 void arch_reset(char mode, const char *cmd)
 {
@@ -99,3 +118,7 @@ int cns3xxx_cpu_clock(void)
 
 	return cpu;
 }
+EXPORT_SYMBOL(cns3xxx_cpu_clock);
+
+atomic_t usb_pwr_ref = ATOMIC_INIT(0);
+EXPORT_SYMBOL(usb_pwr_ref);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-davinci/aemif.c linux-libre-2.6.38-gnu1/arch/arm/mach-davinci/aemif.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-davinci/aemif.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-davinci/aemif.c	2011-03-14 21:20:32.000000000 -0400
@@ -90,7 +90,7 @@ int davinci_aemif_setup_timing(struct da
 					void __iomem *base, unsigned cs)
 {
 	unsigned set, val;
-	unsigned ta, rhold, rstrobe, rsetup, whold, wstrobe, wsetup;
+	int ta, rhold, rstrobe, rsetup, whold, wstrobe, wsetup;
 	unsigned offset = A1CR_OFFSET + cs * 4;
 	struct clk *aemif_clk;
 	unsigned long clkrate;
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-davinci/board-da850-evm.c linux-libre-2.6.38-gnu1/arch/arm/mach-davinci/board-da850-evm.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-davinci/board-da850-evm.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-davinci/board-da850-evm.c	2011-03-14 21:20:32.000000000 -0400
@@ -17,8 +17,10 @@
 #include <linux/i2c.h>
 #include <linux/i2c/at24.h>
 #include <linux/i2c/pca953x.h>
+#include <linux/input.h>
 #include <linux/mfd/tps6507x.h>
 #include <linux/gpio.h>
+#include <linux/gpio_keys.h>
 #include <linux/platform_device.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/nand.h>
@@ -266,34 +268,115 @@ static inline void da850_evm_setup_emac_
 	struct davinci_soc_info *soc_info = &davinci_soc_info;
 
 	soc_info->emac_pdata->rmii_en = 1;
-	gpio_set_value(rmii_sel, 0);
+	gpio_set_value_cansleep(rmii_sel, 0);
 }
 #else
 static inline void da850_evm_setup_emac_rmii(int rmii_sel) { }
 #endif
 
+
+#define DA850_KEYS_DEBOUNCE_MS	10
+/*
+ * At 200ms polling interval it is possible to miss an
+ * event by tapping very lightly on the push button but most
+ * pushes do result in an event; longer intervals require the
+ * user to hold the button whereas shorter intervals require
+ * more CPU time for polling.
+ */
+#define DA850_GPIO_KEYS_POLL_MS	200
+
+enum da850_evm_ui_exp_pins {
+	DA850_EVM_UI_EXP_SEL_C = 5,
+	DA850_EVM_UI_EXP_SEL_B,
+	DA850_EVM_UI_EXP_SEL_A,
+	DA850_EVM_UI_EXP_PB8,
+	DA850_EVM_UI_EXP_PB7,
+	DA850_EVM_UI_EXP_PB6,
+	DA850_EVM_UI_EXP_PB5,
+	DA850_EVM_UI_EXP_PB4,
+	DA850_EVM_UI_EXP_PB3,
+	DA850_EVM_UI_EXP_PB2,
+	DA850_EVM_UI_EXP_PB1,
+};
+
+static const char const *da850_evm_ui_exp[] = {
+	[DA850_EVM_UI_EXP_SEL_C]        = "sel_c",
+	[DA850_EVM_UI_EXP_SEL_B]        = "sel_b",
+	[DA850_EVM_UI_EXP_SEL_A]        = "sel_a",
+	[DA850_EVM_UI_EXP_PB8]          = "pb8",
+	[DA850_EVM_UI_EXP_PB7]          = "pb7",
+	[DA850_EVM_UI_EXP_PB6]          = "pb6",
+	[DA850_EVM_UI_EXP_PB5]          = "pb5",
+	[DA850_EVM_UI_EXP_PB4]          = "pb4",
+	[DA850_EVM_UI_EXP_PB3]          = "pb3",
+	[DA850_EVM_UI_EXP_PB2]          = "pb2",
+	[DA850_EVM_UI_EXP_PB1]          = "pb1",
+};
+
+#define DA850_N_UI_PB		8
+
+static struct gpio_keys_button da850_evm_ui_keys[] = {
+	[0 ... DA850_N_UI_PB - 1] = {
+		.type			= EV_KEY,
+		.active_low		= 1,
+		.wakeup			= 0,
+		.debounce_interval	= DA850_KEYS_DEBOUNCE_MS,
+		.code			= -1, /* assigned at runtime */
+		.gpio			= -1, /* assigned at runtime */
+		.desc			= NULL, /* assigned at runtime */
+	},
+};
+
+static struct gpio_keys_platform_data da850_evm_ui_keys_pdata = {
+	.buttons = da850_evm_ui_keys,
+	.nbuttons = ARRAY_SIZE(da850_evm_ui_keys),
+	.poll_interval = DA850_GPIO_KEYS_POLL_MS,
+};
+
+static struct platform_device da850_evm_ui_keys_device = {
+	.name = "gpio-keys-polled",
+	.id = 0,
+	.dev = {
+		.platform_data = &da850_evm_ui_keys_pdata
+	},
+};
+
+static void da850_evm_ui_keys_init(unsigned gpio)
+{
+	int i;
+	struct gpio_keys_button *button;
+
+	for (i = 0; i < DA850_N_UI_PB; i++) {
+		button = &da850_evm_ui_keys[i];
+		button->code = KEY_F8 - i;
+		button->desc = (char *)
+				da850_evm_ui_exp[DA850_EVM_UI_EXP_PB8 + i];
+		button->gpio = gpio + DA850_EVM_UI_EXP_PB8 + i;
+	}
+}
+
 static int da850_evm_ui_expander_setup(struct i2c_client *client, unsigned gpio,
 						unsigned ngpio, void *c)
 {
 	int sel_a, sel_b, sel_c, ret;
 
-	sel_a = gpio + 7;
-	sel_b = gpio + 6;
-	sel_c = gpio + 5;
+	sel_a = gpio + DA850_EVM_UI_EXP_SEL_A;
+	sel_b = gpio + DA850_EVM_UI_EXP_SEL_B;
+	sel_c = gpio + DA850_EVM_UI_EXP_SEL_C;
 
-	ret = gpio_request(sel_a, "sel_a");
+	ret = gpio_request(sel_a, da850_evm_ui_exp[DA850_EVM_UI_EXP_SEL_A]);
 	if (ret) {
 		pr_warning("Cannot open UI expander pin %d\n", sel_a);
 		goto exp_setup_sela_fail;
 	}
 
-	ret = gpio_request(sel_b, "sel_b");
+	ret = gpio_request(sel_b, da850_evm_ui_exp[DA850_EVM_UI_EXP_SEL_B]);
 	if (ret) {
 		pr_warning("Cannot open UI expander pin %d\n", sel_b);
 		goto exp_setup_selb_fail;
 	}
 
-	ret = gpio_request(sel_c, "sel_c");
+	ret = gpio_request(sel_c, da850_evm_ui_exp[DA850_EVM_UI_EXP_SEL_C]);
 	if (ret) {
 		pr_warning("Cannot open UI expander pin %d\n", sel_c);
 		goto exp_setup_selc_fail;
@@ -304,6 +387,13 @@ static int da850_evm_ui_expander_setup(s
 	gpio_direction_output(sel_b, 1);
 	gpio_direction_output(sel_c, 1);
 
+	da850_evm_ui_keys_init(gpio);
+	ret = platform_device_register(&da850_evm_ui_keys_device);
+	if (ret) {
+		pr_warning("Could not register UI GPIO expander push-buttons");
+		goto exp_setup_keys_fail;
+	}
+
 	ui_card_detected = 1;
 	pr_info("DA850/OMAP-L138 EVM UI card detected\n");
 
@@ -313,6 +403,8 @@ static int da850_evm_ui_expander_setup(s
 
 	return 0;
 
+exp_setup_keys_fail:
+	gpio_free(sel_c);
 exp_setup_selc_fail:
 	gpio_free(sel_b);
 exp_setup_selb_fail:
@@ -324,14 +416,192 @@ exp_setup_sela_fail:
 static int da850_evm_ui_expander_teardown(struct i2c_client *client,
 					unsigned gpio, unsigned ngpio, void *c)
 {
+	platform_device_unregister(&da850_evm_ui_keys_device);
+
 	/* deselect all functionalities */
-	gpio_set_value(gpio + 5, 1);
-	gpio_set_value(gpio + 6, 1);
-	gpio_set_value(gpio + 7, 1);
+	gpio_set_value_cansleep(gpio + DA850_EVM_UI_EXP_SEL_C, 1);
+	gpio_set_value_cansleep(gpio + DA850_EVM_UI_EXP_SEL_B, 1);
+	gpio_set_value_cansleep(gpio + DA850_EVM_UI_EXP_SEL_A, 1);
 
-	gpio_free(gpio + 5);
-	gpio_free(gpio + 6);
-	gpio_free(gpio + 7);
+	gpio_free(gpio + DA850_EVM_UI_EXP_SEL_C);
+	gpio_free(gpio + DA850_EVM_UI_EXP_SEL_B);
+	gpio_free(gpio + DA850_EVM_UI_EXP_SEL_A);
+
+	return 0;
+}
+
+/* assign the baseboard expander's GPIOs after the UI board's */
+#define DA850_UI_EXPANDER_N_GPIOS ARRAY_SIZE(da850_evm_ui_exp)
+#define DA850_BB_EXPANDER_GPIO_BASE (DAVINCI_N_GPIO + DA850_UI_EXPANDER_N_GPIOS)
+
+enum da850_evm_bb_exp_pins {
+	DA850_EVM_BB_EXP_DEEP_SLEEP_EN = 0,
+	DA850_EVM_BB_EXP_SW_RST,
+	DA850_EVM_BB_EXP_TP_23,
+	DA850_EVM_BB_EXP_TP_22,
+	DA850_EVM_BB_EXP_TP_21,
+	DA850_EVM_BB_EXP_USER_PB1,
+	DA850_EVM_BB_EXP_USER_LED2,
+	DA850_EVM_BB_EXP_USER_LED1,
+	DA850_EVM_BB_EXP_USER_SW1,
+	DA850_EVM_BB_EXP_USER_SW2,
+	DA850_EVM_BB_EXP_USER_SW3,
+	DA850_EVM_BB_EXP_USER_SW4,
+	DA850_EVM_BB_EXP_USER_SW5,
+	DA850_EVM_BB_EXP_USER_SW6,
+	DA850_EVM_BB_EXP_USER_SW7,
+	DA850_EVM_BB_EXP_USER_SW8
+};
+
+static const char const *da850_evm_bb_exp[] = {
+	[DA850_EVM_BB_EXP_DEEP_SLEEP_EN]	= "deep_sleep_en",
+	[DA850_EVM_BB_EXP_SW_RST]		= "sw_rst",
+	[DA850_EVM_BB_EXP_TP_23]		= "tp_23",
+	[DA850_EVM_BB_EXP_TP_22]		= "tp_22",
+	[DA850_EVM_BB_EXP_TP_21]		= "tp_21",
+	[DA850_EVM_BB_EXP_USER_PB1]		= "user_pb1",
+	[DA850_EVM_BB_EXP_USER_LED2]		= "user_led2",
+	[DA850_EVM_BB_EXP_USER_LED1]		= "user_led1",
+	[DA850_EVM_BB_EXP_USER_SW1]		= "user_sw1",
+	[DA850_EVM_BB_EXP_USER_SW2]		= "user_sw2",
+	[DA850_EVM_BB_EXP_USER_SW3]		= "user_sw3",
+	[DA850_EVM_BB_EXP_USER_SW4]		= "user_sw4",
+	[DA850_EVM_BB_EXP_USER_SW5]		= "user_sw5",
+	[DA850_EVM_BB_EXP_USER_SW6]		= "user_sw6",
+	[DA850_EVM_BB_EXP_USER_SW7]		= "user_sw7",
+	[DA850_EVM_BB_EXP_USER_SW8]		= "user_sw8",
+};
+
+#define DA850_N_BB_USER_SW	8
+
+static struct gpio_keys_button da850_evm_bb_keys[] = {
+	[0] = {
+		.type			= EV_KEY,
+		.active_low		= 1,
+		.wakeup			= 0,
+		.debounce_interval	= DA850_KEYS_DEBOUNCE_MS,
+		.code			= KEY_PROG1,
+		.desc			= NULL, /* assigned at runtime */
+		.gpio			= -1, /* assigned at runtime */
+	},
+	[1 ... DA850_N_BB_USER_SW] = {
+		.type			= EV_SW,
+		.active_low		= 1,
+		.wakeup			= 0,
+		.debounce_interval	= DA850_KEYS_DEBOUNCE_MS,
+		.code			= -1, /* assigned at runtime */
+		.desc			= NULL, /* assigned at runtime */
+		.gpio			= -1, /* assigned at runtime */
+	},
+};
+
+static struct gpio_keys_platform_data da850_evm_bb_keys_pdata = {
+	.buttons = da850_evm_bb_keys,
+	.nbuttons = ARRAY_SIZE(da850_evm_bb_keys),
+	.poll_interval = DA850_GPIO_KEYS_POLL_MS,
+};
+
+static struct platform_device da850_evm_bb_keys_device = {
+	.name = "gpio-keys-polled",
+	.id = 1,
+	.dev = {
+		.platform_data = &da850_evm_bb_keys_pdata
+	},
+};
+
+static void da850_evm_bb_keys_init(unsigned gpio)
+{
+	int i;
+	struct gpio_keys_button *button;
+
+	button = &da850_evm_bb_keys[0];
+	button->desc = (char *)
+		da850_evm_bb_exp[DA850_EVM_BB_EXP_USER_PB1];
+	button->gpio = gpio + DA850_EVM_BB_EXP_USER_PB1;
+
+	for (i = 0; i < DA850_N_BB_USER_SW; i++) {
+		button = &da850_evm_bb_keys[i + 1];
+		button->code = SW_LID + i;
+		button->desc = (char *)
+				da850_evm_bb_exp[DA850_EVM_BB_EXP_USER_SW1 + i];
+		button->gpio = gpio + DA850_EVM_BB_EXP_USER_SW1 + i;
+	}
+}
+
+#define DA850_N_BB_USER_LED	2
+
+static struct gpio_led da850_evm_bb_leds[] = {
+	[0 ... DA850_N_BB_USER_LED - 1] = {
+		.active_low = 1,
+		.gpio = -1, /* assigned at runtime */
+		.name = NULL, /* assigned at runtime */
+	},
+};
+
+static struct gpio_led_platform_data da850_evm_bb_leds_pdata = {
+	.leds = da850_evm_bb_leds,
+	.num_leds = ARRAY_SIZE(da850_evm_bb_leds),
+};
+
+static struct platform_device da850_evm_bb_leds_device = {
+	.name		= "leds-gpio",
+	.id		= -1,
+	.dev = {
+		.platform_data = &da850_evm_bb_leds_pdata
+	}
+};
+
+static void da850_evm_bb_leds_init(unsigned gpio)
+{
+	int i;
+	struct gpio_led *led;
+
+	for (i = 0; i < DA850_N_BB_USER_LED; i++) {
+		led = &da850_evm_bb_leds[i];
+
+		led->gpio = gpio + DA850_EVM_BB_EXP_USER_LED2 + i;
+		led->name =
+			da850_evm_bb_exp[DA850_EVM_BB_EXP_USER_LED2 + i];
+	}
+}
+
+static int da850_evm_bb_expander_setup(struct i2c_client *client,
+						unsigned gpio, unsigned ngpio,
+						void *c)
+{
+	int ret;
+
+	/*
+	 * Register the switches and pushbutton on the baseboard as a gpio-keys
+	 * device.
+	 */
+	da850_evm_bb_keys_init(gpio);
+	ret = platform_device_register(&da850_evm_bb_keys_device);
+	if (ret) {
+		pr_warning("Could not register baseboard GPIO expander keys");
+		goto io_exp_setup_sw_fail;
+	}
+
+	da850_evm_bb_leds_init(gpio);
+	ret = platform_device_register(&da850_evm_bb_leds_device);
+	if (ret) {
+		pr_warning("Could not register baseboard GPIO expander LEDS");
+		goto io_exp_setup_leds_fail;
+	}
+
+	return 0;
+
+io_exp_setup_leds_fail:
+	platform_device_unregister(&da850_evm_bb_keys_device);
+io_exp_setup_sw_fail:
+	return ret;
+}
+
+static int da850_evm_bb_expander_teardown(struct i2c_client *client,
+					unsigned gpio, unsigned ngpio, void *c)
+{
+	platform_device_unregister(&da850_evm_bb_leds_device);
+	platform_device_unregister(&da850_evm_bb_keys_device);
 
 	return 0;
 }
@@ -340,6 +610,14 @@ static struct pca953x_platform_data da85
 	.gpio_base	= DAVINCI_N_GPIO,
 	.setup		= da850_evm_ui_expander_setup,
 	.teardown	= da850_evm_ui_expander_teardown,
+	.names		= da850_evm_ui_exp,
+};
+
+static struct pca953x_platform_data da850_evm_bb_expander_info = {
+	.gpio_base	= DA850_BB_EXPANDER_GPIO_BASE,
+	.setup		= da850_evm_bb_expander_setup,
+	.teardown	= da850_evm_bb_expander_teardown,
+	.names		= da850_evm_bb_exp,
 };
 
 static struct i2c_board_info __initdata da850_evm_i2c_devices[] = {
@@ -350,6 +628,10 @@ static struct i2c_board_info __initdata
 		I2C_BOARD_INFO("tca6416", 0x20),
 		.platform_data = &da850_evm_ui_expander_info,
 	},
+	{
+		I2C_BOARD_INFO("tca6416", 0x21),
+		.platform_data = &da850_evm_bb_expander_info,
+	},
 };
 
 static struct davinci_i2c_platform_data da850_evm_i2c_0_pdata = {
@@ -540,7 +822,7 @@ static struct regulator_init_data tps650
 	{
 		.constraints = {
 			.min_uV = 950000,
-			.max_uV = 1320000,
+			.max_uV = 1350000,
 			.valid_ops_mask = (REGULATOR_CHANGE_VOLTAGE |
 				REGULATOR_CHANGE_STATUS),
 			.boot_on = 1,
@@ -591,7 +873,7 @@ static struct tps6507x_board tps_board =
 	.tps6507x_ts_init_data = &tps6507x_touchscreen_data,
 };
 
-static struct i2c_board_info __initdata da850evm_tps65070_info[] = {
+static struct i2c_board_info __initdata da850_evm_tps65070_info[] = {
 	{
 		I2C_BOARD_INFO("tps6507x", 0x48),
 		.platform_data = &tps_board,
@@ -600,8 +882,8 @@ static struct i2c_board_info __initdata
 
 static int __init pmic_tps65070_init(void)
 {
-	return i2c_register_board_info(1, da850evm_tps65070_info,
-					ARRAY_SIZE(da850evm_tps65070_info));
+	return i2c_register_board_info(1, da850_evm_tps65070_info,
+					ARRAY_SIZE(da850_evm_tps65070_info));
 }
 
 static const short da850_evm_lcdc_pins[] = {
@@ -736,6 +1018,27 @@ static struct edma_rsv_info *da850_edma_
 	&da850_edma_cc1_rsv,
 };
 
+#ifdef CONFIG_CPU_FREQ
+static __init int da850_evm_init_cpufreq(void)
+{
+	switch (system_rev & 0xF) {
+	case 3:
+		da850_max_speed = 456000;
+		break;
+	case 2:
+		da850_max_speed = 408000;
+		break;
+	case 1:
+		da850_max_speed = 372000;
+		break;
+	}
+
+	return da850_register_cpufreq("pll0_sysclk3");
+}
+#else
+static __init int da850_evm_init_cpufreq(void) { return 0; }
+#endif
+
 static __init void da850_evm_init(void)
 {
 	int ret;
@@ -836,7 +1139,7 @@ static __init void da850_evm_init(void)
 	if (ret)
 		pr_warning("da850_evm_init: rtc setup failed: %d\n", ret);
 
-	ret = da850_register_cpufreq("pll0_sysclk3");
+	ret = da850_evm_init_cpufreq();
 	if (ret)
 		pr_warning("da850_evm_init: cpufreq registration failed: %d\n",
 				ret);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-davinci/clock.c linux-libre-2.6.38-gnu1/arch/arm/mach-davinci/clock.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-davinci/clock.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-davinci/clock.c	2011-03-14 21:20:32.000000000 -0400
@@ -336,7 +336,7 @@ int davinci_set_sysclk_rate(struct clk *
 		ratio--;
 	}
 
-	if (ratio > PLLDIV_RATIO_MASK)
+	if (ratio > pll->div_ratio_mask)
 		return -EINVAL;
 
 	do {
@@ -344,7 +344,7 @@ int davinci_set_sysclk_rate(struct clk *
 	} while (v & PLLSTAT_GOSTAT);
 
 	v = __raw_readl(pll->base + clk->div_reg);
-	v &= ~PLLDIV_RATIO_MASK;
+	v &= ~pll->div_ratio_mask;
 	v |= ratio | PLLDIV_EN;
 	__raw_writel(v, pll->base + clk->div_reg);
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-davinci/clock.h linux-libre-2.6.38-gnu1/arch/arm/mach-davinci/clock.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-davinci/clock.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-davinci/clock.h	2011-03-14 21:20:32.000000000 -0400
@@ -68,7 +68,7 @@
 #ifndef __ASSEMBLER__
 
 #include <linux/list.h>
-#include <asm/clkdev.h>
+#include <linux/clkdev.h>
 
 #define PLLSTAT_GOSTAT	BIT(0)
 #define PLLCMD_GOSET	BIT(0)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-davinci/cp_intc.c linux-libre-2.6.38-gnu1/arch/arm/mach-davinci/cp_intc.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-davinci/cp_intc.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-davinci/cp_intc.c	2011-03-14 21:20:32.000000000 -0400
@@ -26,30 +26,30 @@ static inline void cp_intc_write(unsigne
 	__raw_writel(value, davinci_intc_base + offset);
 }
 
-static void cp_intc_ack_irq(unsigned int irq)
+static void cp_intc_ack_irq(struct irq_data *d)
 {
-	cp_intc_write(irq, CP_INTC_SYS_STAT_IDX_CLR);
+	cp_intc_write(d->irq, CP_INTC_SYS_STAT_IDX_CLR);
 }
 
 /* Disable interrupt */
-static void cp_intc_mask_irq(unsigned int irq)
+static void cp_intc_mask_irq(struct irq_data *d)
 {
 	/* XXX don't know why we need to disable nIRQ here... */
 	cp_intc_write(1, CP_INTC_HOST_ENABLE_IDX_CLR);
-	cp_intc_write(irq, CP_INTC_SYS_ENABLE_IDX_CLR);
+	cp_intc_write(d->irq, CP_INTC_SYS_ENABLE_IDX_CLR);
 	cp_intc_write(1, CP_INTC_HOST_ENABLE_IDX_SET);
 }
 
 /* Enable interrupt */
-static void cp_intc_unmask_irq(unsigned int irq)
+static void cp_intc_unmask_irq(struct irq_data *d)
 {
-	cp_intc_write(irq, CP_INTC_SYS_ENABLE_IDX_SET);
+	cp_intc_write(d->irq, CP_INTC_SYS_ENABLE_IDX_SET);
 }
 
-static int cp_intc_set_irq_type(unsigned int irq, unsigned int flow_type)
+static int cp_intc_set_irq_type(struct irq_data *d, unsigned int flow_type)
 {
-	unsigned reg		= BIT_WORD(irq);
-	unsigned mask		= BIT_MASK(irq);
+	unsigned reg		= BIT_WORD(d->irq);
+	unsigned mask		= BIT_MASK(d->irq);
 	unsigned polarity	= cp_intc_read(CP_INTC_SYS_POLARITY(reg));
 	unsigned type		= cp_intc_read(CP_INTC_SYS_TYPE(reg));
 
@@ -85,18 +85,18 @@ static int cp_intc_set_irq_type(unsigned
  * generic drivers which call {enable|disable}_irq_wake for
  * wake up interrupt sources (eg RTC on DA850).
  */
-static int cp_intc_set_wake(unsigned int irq, unsigned int on)
+static int cp_intc_set_wake(struct irq_data *d, unsigned int on)
 {
 	return 0;
 }
 
 static struct irq_chip cp_intc_irq_chip = {
 	.name		= "cp_intc",
-	.ack		= cp_intc_ack_irq,
-	.mask		= cp_intc_mask_irq,
-	.unmask		= cp_intc_unmask_irq,
-	.set_type	= cp_intc_set_irq_type,
-	.set_wake	= cp_intc_set_wake,
+	.irq_ack	= cp_intc_ack_irq,
+	.irq_mask	= cp_intc_mask_irq,
+	.irq_unmask	= cp_intc_unmask_irq,
+	.irq_set_type	= cp_intc_set_irq_type,
+	.irq_set_wake	= cp_intc_set_wake,
 };
 
 void __init cp_intc_init(void)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-davinci/cpufreq.c linux-libre-2.6.38-gnu1/arch/arm/mach-davinci/cpufreq.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-davinci/cpufreq.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-davinci/cpufreq.c	2011-03-14 21:20:32.000000000 -0400
@@ -132,7 +132,7 @@ out:
 	return ret;
 }
 
-static int __init davinci_cpu_init(struct cpufreq_policy *policy)
+static int davinci_cpu_init(struct cpufreq_policy *policy)
 {
 	int result = 0;
 	struct davinci_cpufreq_config *pdata = cpufreq.dev->platform_data;
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-davinci/da850.c linux-libre-2.6.38-gnu1/arch/arm/mach-davinci/da850.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-davinci/da850.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-davinci/da850.c	2011-03-14 21:20:32.000000000 -0400
@@ -830,8 +830,7 @@ static void da850_set_async3_src(int pll
  * According to the TRM, minimum PLLM results in maximum power savings.
  * The OPP definitions below should keep the PLLM as low as possible.
  *
- * The output of the PLLM must be between 400 to 600 MHz.
- * This rules out prediv of anything but divide-by-one for 24Mhz OSC input.
+ * The output of the PLLM must be between 300 to 600 MHz.
  */
 struct da850_opp {
 	unsigned int	freq;	/* in KHz */
@@ -842,6 +841,33 @@ struct da850_opp {
 	unsigned int	cvdd_max; /* in uV */
 };
 
+static const struct da850_opp da850_opp_456 = {
+	.freq		= 456000,
+	.prediv		= 1,
+	.mult		= 19,
+	.postdiv	= 1,
+	.cvdd_min	= 1300000,
+	.cvdd_max	= 1350000,
+};
+
+static const struct da850_opp da850_opp_408 = {
+	.freq		= 408000,
+	.prediv		= 1,
+	.mult		= 17,
+	.postdiv	= 1,
+	.cvdd_min	= 1300000,
+	.cvdd_max	= 1350000,
+};
+
+static const struct da850_opp da850_opp_372 = {
+	.freq		= 372000,
+	.prediv		= 2,
+	.mult		= 31,
+	.postdiv	= 1,
+	.cvdd_min	= 1200000,
+	.cvdd_max	= 1320000,
+};
+
 static const struct da850_opp da850_opp_300 = {
 	.freq		= 300000,
 	.prediv		= 1,
@@ -876,6 +902,9 @@ static const struct da850_opp da850_opp_
 	}
 
 static struct cpufreq_frequency_table da850_freq_table[] = {
+	OPP(456),
+	OPP(408),
+	OPP(372),
 	OPP(300),
 	OPP(200),
 	OPP(96),
@@ -886,6 +915,19 @@ static struct cpufreq_frequency_table da
 };
 
 #ifdef CONFIG_REGULATOR
+static int da850_set_voltage(unsigned int index);
+static int da850_regulator_init(void);
+#endif
+
+static struct davinci_cpufreq_config cpufreq_info = {
+	.freq_table = da850_freq_table,
+#ifdef CONFIG_REGULATOR
+	.init = da850_regulator_init,
+	.set_voltage = da850_set_voltage,
+#endif
+};
+
+#ifdef CONFIG_REGULATOR
 static struct regulator *cvdd;
 
 static int da850_set_voltage(unsigned int index)
@@ -895,7 +937,7 @@ static int da850_set_voltage(unsigned in
 	if (!cvdd)
 		return -ENODEV;
 
-	opp = (struct da850_opp *) da850_freq_table[index].index;
+	opp = (struct da850_opp *) cpufreq_info.freq_table[index].index;
 
 	return regulator_set_voltage(cvdd, opp->cvdd_min, opp->cvdd_max);
 }
@@ -912,14 +954,6 @@ static int da850_regulator_init(void)
 }
 #endif
 
-static struct davinci_cpufreq_config cpufreq_info = {
-	.freq_table = &da850_freq_table[0],
-#ifdef CONFIG_REGULATOR
-	.init = da850_regulator_init,
-	.set_voltage = da850_set_voltage,
-#endif
-};
-
 static struct platform_device da850_cpufreq_device = {
 	.name			= "cpufreq-davinci",
 	.dev = {
@@ -928,12 +962,22 @@ static struct platform_device da850_cpuf
 	.id = -1,
 };
 
+unsigned int da850_max_speed = 300000;
+
 int __init da850_register_cpufreq(char *async_clk)
 {
+	int i;
+
 	/* cpufreq driver can help keep an "async" clock constant */
 	if (async_clk)
 		clk_add_alias("async", da850_cpufreq_device.name,
 							async_clk, NULL);
+	for (i = 0; i < ARRAY_SIZE(da850_freq_table); i++) {
+		if (da850_freq_table[i].frequency <= da850_max_speed) {
+			cpufreq_info.freq_table = &da850_freq_table[i];
+			break;
+		}
+	}
 
 	return platform_device_register(&da850_cpufreq_device);
 }
@@ -942,17 +986,18 @@ static int da850_round_armrate(struct cl
 {
 	int i, ret = 0, diff;
 	unsigned int best = (unsigned int) -1;
+	struct cpufreq_frequency_table *table = cpufreq_info.freq_table;
 
 	rate /= 1000; /* convert to kHz */
 
-	for (i = 0; da850_freq_table[i].frequency != CPUFREQ_TABLE_END; i++) {
-		diff = da850_freq_table[i].frequency - rate;
+	for (i = 0; table[i].frequency != CPUFREQ_TABLE_END; i++) {
+		diff = table[i].frequency - rate;
 		if (diff < 0)
 			diff = -diff;
 
 		if (diff < best) {
 			best = diff;
-			ret = da850_freq_table[i].frequency;
+			ret = table[i].frequency;
 		}
 	}
 
@@ -973,7 +1018,7 @@ static int da850_set_pll0rate(struct clk
 	struct pll_data *pll = clk->pll_data;
 	int ret;
 
-	opp = (struct da850_opp *) da850_freq_table[index].index;
+	opp = (struct da850_opp *) cpufreq_info.freq_table[index].index;
 	prediv = opp->prediv;
 	mult = opp->mult;
 	postdiv = opp->postdiv;
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-davinci/devices-da8xx.c linux-libre-2.6.38-gnu1/arch/arm/mach-davinci/devices-da8xx.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-davinci/devices-da8xx.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-davinci/devices-da8xx.c	2011-03-14 21:20:32.000000000 -0400
@@ -480,8 +480,15 @@ static struct platform_device da850_mcas
 	.resource	= da850_mcasp_resources,
 };
 
+struct platform_device davinci_pcm_device = {
+	.name	= "davinci-pcm-audio",
+	.id	= -1,
+};
+
 void __init da8xx_register_mcasp(int id, struct snd_platform_data *pdata)
 {
+	platform_device_register(&davinci_pcm_device);
+
 	/* DA830/OMAP-L137 has 3 instances of McASP */
 	if (cpu_is_davinci_da830() && id == 1) {
 		da830_mcasp1_device.dev.platform_data = pdata;
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-davinci/devices-tnetv107x.c linux-libre-2.6.38-gnu1/arch/arm/mach-davinci/devices-tnetv107x.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-davinci/devices-tnetv107x.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-davinci/devices-tnetv107x.c	2011-03-14 21:20:32.000000000 -0400
@@ -344,7 +344,20 @@ static struct platform_device tsc_device
 
 void __init tnetv107x_devices_init(struct tnetv107x_device_info *info)
 {
-	int i;
+	int i, error;
+	struct clk *tsc_clk;
+
+	/*
+	 * The reset defaults for tnetv107x tsc clock divider is set too high.
+	 * This forces the clock down to a range that allows the ADC to
+	 * complete sample conversion in time.
+	 */
+	tsc_clk = clk_get(NULL, "sys_tsc_clk");
+	if (tsc_clk) {
+		error = clk_set_rate(tsc_clk, 5000000);
+		WARN_ON(error < 0);
+		clk_put(tsc_clk);
+	}
 
 	platform_device_register(&edma_device);
 	platform_device_register(&tnetv107x_wdt_device);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-davinci/dm355.c linux-libre-2.6.38-gnu1/arch/arm/mach-davinci/dm355.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-davinci/dm355.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-davinci/dm355.c	2011-03-14 21:20:32.000000000 -0400
@@ -412,12 +412,7 @@ static struct resource dm355_spi0_resour
 static struct davinci_spi_platform_data dm355_spi0_pdata = {
 	.version 	= SPI_VERSION_1,
 	.num_chipselect = 2,
-	.clk_internal	= 1,
-	.cs_hold	= 1,
-	.intr_level	= 0,
-	.poll_mode	= 1,	/* 0 -> interrupt mode 1-> polling mode */
-	.c2tdelay	= 0,
-	.t2cdelay	= 0,
+	.cshold_bug	= true,
 };
 static struct platform_device dm355_spi0_device = {
 	.name = "spi_davinci",
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-davinci/dm365.c linux-libre-2.6.38-gnu1/arch/arm/mach-davinci/dm365.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-davinci/dm365.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-davinci/dm365.c	2011-03-14 21:20:32.000000000 -0400
@@ -625,12 +625,6 @@ static u64 dm365_spi0_dma_mask = DMA_BIT
 static struct davinci_spi_platform_data dm365_spi0_pdata = {
 	.version 	= SPI_VERSION_1,
 	.num_chipselect = 2,
-	.clk_internal	= 1,
-	.cs_hold	= 1,
-	.intr_level	= 0,
-	.poll_mode	= 1,	/* 0 -> interrupt mode 1-> polling mode */
-	.c2tdelay	= 0,
-	.t2cdelay	= 0,
 };
 
 static struct resource dm365_spi0_resources[] = {
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-davinci/gpio.c linux-libre-2.6.38-gnu1/arch/arm/mach-davinci/gpio.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-davinci/gpio.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-davinci/gpio.c	2011-03-14 21:20:32.000000000 -0400
@@ -205,20 +205,20 @@ pure_initcall(davinci_gpio_setup);
  * serve as EDMA event triggers.
  */
 
-static void gpio_irq_disable(unsigned irq)
+static void gpio_irq_disable(struct irq_data *d)
 {
-	struct davinci_gpio_regs __iomem *g = irq2regs(irq);
-	u32 mask = (u32) get_irq_data(irq);
+	struct davinci_gpio_regs __iomem *g = irq2regs(d->irq);
+	u32 mask = (u32) irq_data_get_irq_data(d);
 
 	__raw_writel(mask, &g->clr_falling);
 	__raw_writel(mask, &g->clr_rising);
 }
 
-static void gpio_irq_enable(unsigned irq)
+static void gpio_irq_enable(struct irq_data *d)
 {
-	struct davinci_gpio_regs __iomem *g = irq2regs(irq);
-	u32 mask = (u32) get_irq_data(irq);
-	unsigned status = irq_desc[irq].status;
+	struct davinci_gpio_regs __iomem *g = irq2regs(d->irq);
+	u32 mask = (u32) irq_data_get_irq_data(d);
+	unsigned status = irq_desc[d->irq].status;
 
 	status &= IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING;
 	if (!status)
@@ -230,19 +230,19 @@ static void gpio_irq_enable(unsigned irq
 		__raw_writel(mask, &g->set_rising);
 }
 
-static int gpio_irq_type(unsigned irq, unsigned trigger)
+static int gpio_irq_type(struct irq_data *d, unsigned trigger)
 {
-	struct davinci_gpio_regs __iomem *g = irq2regs(irq);
-	u32 mask = (u32) get_irq_data(irq);
+	struct davinci_gpio_regs __iomem *g = irq2regs(d->irq);
+	u32 mask = (u32) irq_data_get_irq_data(d);
 
 	if (trigger & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
 		return -EINVAL;
 
-	irq_desc[irq].status &= ~IRQ_TYPE_SENSE_MASK;
-	irq_desc[irq].status |= trigger;
+	irq_desc[d->irq].status &= ~IRQ_TYPE_SENSE_MASK;
+	irq_desc[d->irq].status |= trigger;
 
 	/* don't enable the IRQ if it's currently disabled */
-	if (irq_desc[irq].depth == 0) {
+	if (irq_desc[d->irq].depth == 0) {
 		__raw_writel(mask, (trigger & IRQ_TYPE_EDGE_FALLING)
 			     ? &g->set_falling : &g->clr_falling);
 		__raw_writel(mask, (trigger & IRQ_TYPE_EDGE_RISING)
@@ -253,9 +253,9 @@ static int gpio_irq_type(unsigned irq, u
 
 static struct irq_chip gpio_irqchip = {
 	.name		= "GPIO",
-	.enable		= gpio_irq_enable,
-	.disable	= gpio_irq_disable,
-	.set_type	= gpio_irq_type,
+	.irq_enable	= gpio_irq_enable,
+	.irq_disable	= gpio_irq_disable,
+	.irq_set_type	= gpio_irq_type,
 };
 
 static void
@@ -269,8 +269,8 @@ gpio_irq_handler(unsigned irq, struct ir
 		mask <<= 16;
 
 	/* temporarily mask (level sensitive) parent IRQ */
-	desc->chip->mask(irq);
-	desc->chip->ack(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;
@@ -293,7 +293,7 @@ gpio_irq_handler(unsigned irq, struct ir
 			status >>= res;
 		}
 	}
-	desc->chip->unmask(irq);
+	desc->irq_data.chip->irq_unmask(&desc->irq_data);
 	/* now it may re-trigger */
 }
 
@@ -320,10 +320,10 @@ static int gpio_to_irq_unbanked(struct g
 		return -ENODEV;
 }
 
-static int gpio_irq_type_unbanked(unsigned irq, unsigned trigger)
+static int gpio_irq_type_unbanked(struct irq_data *d, unsigned trigger)
 {
-	struct davinci_gpio_regs __iomem *g = irq2regs(irq);
-	u32 mask = (u32) get_irq_data(irq);
+	struct davinci_gpio_regs __iomem *g = irq2regs(d->irq);
+	u32 mask = (u32) irq_data_get_irq_data(d);
 
 	if (trigger & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
 		return -EINVAL;
@@ -397,7 +397,7 @@ static int __init davinci_gpio_irq_setup
 		irq = bank_irq;
 		gpio_irqchip_unbanked = *get_irq_desc_chip(irq_to_desc(irq));
 		gpio_irqchip_unbanked.name = "GPIO-AINTC";
-		gpio_irqchip_unbanked.set_type = gpio_irq_type_unbanked;
+		gpio_irqchip_unbanked.irq_set_type = gpio_irq_type_unbanked;
 
 		/* default trigger: both edges */
 		g = gpio2regs(0);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-davinci/gpio-tnetv107x.c linux-libre-2.6.38-gnu1/arch/arm/mach-davinci/gpio-tnetv107x.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-davinci/gpio-tnetv107x.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-davinci/gpio-tnetv107x.c	2011-03-14 21:20:32.000000000 -0400
@@ -58,7 +58,7 @@ static int tnetv107x_gpio_request(struct
 
 	spin_lock_irqsave(&ctlr->lock, flags);
 
-	gpio_reg_set_bit(&regs->enable, gpio);
+	gpio_reg_set_bit(regs->enable, gpio);
 
 	spin_unlock_irqrestore(&ctlr->lock, flags);
 
@@ -74,7 +74,7 @@ static void tnetv107x_gpio_free(struct g
 
 	spin_lock_irqsave(&ctlr->lock, flags);
 
-	gpio_reg_clear_bit(&regs->enable, gpio);
+	gpio_reg_clear_bit(regs->enable, gpio);
 
 	spin_unlock_irqrestore(&ctlr->lock, flags);
 }
@@ -88,7 +88,7 @@ static int tnetv107x_gpio_dir_in(struct
 
 	spin_lock_irqsave(&ctlr->lock, flags);
 
-	gpio_reg_set_bit(&regs->direction, gpio);
+	gpio_reg_set_bit(regs->direction, gpio);
 
 	spin_unlock_irqrestore(&ctlr->lock, flags);
 
@@ -106,11 +106,11 @@ static int tnetv107x_gpio_dir_out(struct
 	spin_lock_irqsave(&ctlr->lock, flags);
 
 	if (value)
-		gpio_reg_set_bit(&regs->data_out, gpio);
+		gpio_reg_set_bit(regs->data_out, gpio);
 	else
-		gpio_reg_clear_bit(&regs->data_out, gpio);
+		gpio_reg_clear_bit(regs->data_out, gpio);
 
-	gpio_reg_clear_bit(&regs->direction, gpio);
+	gpio_reg_clear_bit(regs->direction, gpio);
 
 	spin_unlock_irqrestore(&ctlr->lock, flags);
 
@@ -124,7 +124,7 @@ static int tnetv107x_gpio_get(struct gpi
 	unsigned gpio = chip->base + offset;
 	int ret;
 
-	ret = gpio_reg_get_bit(&regs->data_in, gpio);
+	ret = gpio_reg_get_bit(regs->data_in, gpio);
 
 	return ret ? 1 : 0;
 }
@@ -140,9 +140,9 @@ static void tnetv107x_gpio_set(struct gp
 	spin_lock_irqsave(&ctlr->lock, flags);
 
 	if (value)
-		gpio_reg_set_bit(&regs->data_out, gpio);
+		gpio_reg_set_bit(regs->data_out, gpio);
 	else
-		gpio_reg_clear_bit(&regs->data_out, gpio);
+		gpio_reg_clear_bit(regs->data_out, gpio);
 
 	spin_unlock_irqrestore(&ctlr->lock, flags);
 }
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-davinci/include/mach/clkdev.h linux-libre-2.6.38-gnu1/arch/arm/mach-davinci/include/mach/clkdev.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-davinci/include/mach/clkdev.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-davinci/include/mach/clkdev.h	2011-03-14 21:20:32.000000000 -0400
@@ -1,6 +1,8 @@
 #ifndef __MACH_CLKDEV_H
 #define __MACH_CLKDEV_H
 
+struct clk;
+
 static inline int __clk_get(struct clk *clk)
 {
 	return 1;
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-davinci/include/mach/da8xx.h linux-libre-2.6.38-gnu1/arch/arm/mach-davinci/include/mach/da8xx.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-davinci/include/mach/da8xx.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-davinci/include/mach/da8xx.h	2011-03-14 21:20:32.000000000 -0400
@@ -28,6 +28,13 @@ extern void __iomem *da8xx_syscfg0_base;
 extern void __iomem *da8xx_syscfg1_base;
 
 /*
+ * If the DA850/OMAP-L138/AM18x SoC on board is of a higher speed grade
+ * (than the regular 300Mhz variant), the board code should set this up
+ * with the supported speed before calling da850_register_cpufreq().
+ */
+extern unsigned int da850_max_speed;
+
+/*
  * The cp_intc interrupt controller for the da8xx isn't in the same
  * chunk of physical memory space as the other registers (like it is
  * on the davincis) so it needs to be mapped separately.  It will be
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-davinci/include/mach/io.h linux-libre-2.6.38-gnu1/arch/arm/mach-davinci/include/mach/io.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-davinci/include/mach/io.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-davinci/include/mach/io.h	2011-03-14 21:20:32.000000000 -0400
@@ -22,8 +22,8 @@
 #define __mem_isa(a)		(a)
 
 #ifndef __ASSEMBLER__
-#define __arch_ioremap(p, s, t)	davinci_ioremap(p, s, t)
-#define __arch_iounmap(v)	davinci_iounmap(v)
+#define __arch_ioremap		davinci_ioremap
+#define __arch_iounmap		davinci_iounmap
 
 void __iomem *davinci_ioremap(unsigned long phys, size_t size,
 			      unsigned int type);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-davinci/include/mach/spi.h linux-libre-2.6.38-gnu1/arch/arm/mach-davinci/include/mach/spi.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-davinci/include/mach/spi.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-davinci/include/mach/spi.h	2011-03-14 21:20:32.000000000 -0400
@@ -19,26 +19,66 @@
 #ifndef __ARCH_ARM_DAVINCI_SPI_H
 #define __ARCH_ARM_DAVINCI_SPI_H
 
+#define SPI_INTERN_CS	0xFF
+
 enum {
 	SPI_VERSION_1, /* For DM355/DM365/DM6467 */
 	SPI_VERSION_2, /* For DA8xx */
 };
 
+/**
+ * davinci_spi_platform_data - Platform data for SPI master device on DaVinci
+ *
+ * @version:	version of the SPI IP. Different DaVinci devices have slightly
+ *		varying versions of the same IP.
+ * @num_chipselect: number of chipselects supported by this SPI master
+ * @intr_line:	interrupt line used to connect the SPI IP to the ARM interrupt
+ *		controller withn the SoC. Possible values are 0 and 1.
+ * @chip_sel:	list of GPIOs which can act as chip-selects for the SPI.
+ *		SPI_INTERN_CS denotes internal SPI chip-select. Not necessary
+ *		to populate if all chip-selects are internal.
+ * @cshold_bug:	set this to true if the SPI controller on your chip requires
+ *		a write to CSHOLD bit in between transfers (like in DM355).
+ */
 struct davinci_spi_platform_data {
 	u8	version;
 	u8	num_chipselect;
+	u8	intr_line;
+	u8	*chip_sel;
+	bool	cshold_bug;
+};
+
+/**
+ * davinci_spi_config - Per-chip-select configuration for SPI slave devices
+ *
+ * @wdelay:	amount of delay between transmissions. Measured in number of
+ *		SPI module clocks.
+ * @odd_parity:	polarity of parity flag at the end of transmit data stream.
+ *		0 - odd parity, 1 - even parity.
+ * @parity_enable: enable transmission of parity at end of each transmit
+ *		data stream.
+ * @io_type:	type of IO transfer. Choose between polled, interrupt and DMA.
+ * @timer_disable: disable chip-select timers (setup and hold)
+ * @c2tdelay:	chip-select setup time. Measured in number of SPI module clocks.
+ * @t2cdelay:	chip-select hold time. Measured in number of SPI module clocks.
+ * @t2edelay:	transmit data finished to SPI ENAn pin inactive time. Measured
+ *		in number of SPI clocks.
+ * @c2edelay:	chip-select active to SPI ENAn signal active time. Measured in
+ *		number of SPI clocks.
+ */
+struct davinci_spi_config {
 	u8	wdelay;
 	u8	odd_parity;
 	u8	parity_enable;
-	u8	wait_enable;
+#define SPI_IO_TYPE_INTR	0
+#define SPI_IO_TYPE_POLL	1
+#define SPI_IO_TYPE_DMA		2
+	u8	io_type;
 	u8	timer_disable;
-	u8	clk_internal;
-	u8	cs_hold;
-	u8	intr_level;
-	u8	poll_mode;
-	u8	use_dma;
 	u8	c2tdelay;
 	u8	t2cdelay;
+	u8	t2edelay;
+	u8	c2edelay;
 };
 
 #endif	/* __ARCH_ARM_DAVINCI_SPI_H */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-davinci/irq.c linux-libre-2.6.38-gnu1/arch/arm/mach-davinci/irq.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-davinci/irq.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-davinci/irq.c	2011-03-14 21:20:32.000000000 -0400
@@ -53,14 +53,14 @@ static inline void davinci_irq_writel(un
 }
 
 /* Disable interrupt */
-static void davinci_mask_irq(unsigned int irq)
+static void davinci_mask_irq(struct irq_data *d)
 {
 	unsigned int mask;
 	u32 l;
 
-	mask = 1 << IRQ_BIT(irq);
+	mask = 1 << IRQ_BIT(d->irq);
 
-	if (irq > 31) {
+	if (d->irq > 31) {
 		l = davinci_irq_readl(IRQ_ENT_REG1_OFFSET);
 		l &= ~mask;
 		davinci_irq_writel(l, IRQ_ENT_REG1_OFFSET);
@@ -72,14 +72,14 @@ static void davinci_mask_irq(unsigned in
 }
 
 /* Enable interrupt */
-static void davinci_unmask_irq(unsigned int irq)
+static void davinci_unmask_irq(struct irq_data *d)
 {
 	unsigned int mask;
 	u32 l;
 
-	mask = 1 << IRQ_BIT(irq);
+	mask = 1 << IRQ_BIT(d->irq);
 
-	if (irq > 31) {
+	if (d->irq > 31) {
 		l = davinci_irq_readl(IRQ_ENT_REG1_OFFSET);
 		l |= mask;
 		davinci_irq_writel(l, IRQ_ENT_REG1_OFFSET);
@@ -91,23 +91,23 @@ static void davinci_unmask_irq(unsigned
 }
 
 /* EOI interrupt */
-static void davinci_ack_irq(unsigned int irq)
+static void davinci_ack_irq(struct irq_data *d)
 {
 	unsigned int mask;
 
-	mask = 1 << IRQ_BIT(irq);
+	mask = 1 << IRQ_BIT(d->irq);
 
-	if (irq > 31)
+	if (d->irq > 31)
 		davinci_irq_writel(mask, IRQ_REG1_OFFSET);
 	else
 		davinci_irq_writel(mask, IRQ_REG0_OFFSET);
 }
 
 static struct irq_chip davinci_irq_chip_0 = {
-	.name	= "AINTC",
-	.ack	= davinci_ack_irq,
-	.mask	= davinci_mask_irq,
-	.unmask = davinci_unmask_irq,
+	.name		= "AINTC",
+	.irq_ack	= davinci_ack_irq,
+	.irq_mask	= davinci_mask_irq,
+	.irq_unmask	= davinci_unmask_irq,
 };
 
 /* ARM Interrupt Controller Initialization */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-davinci/Kconfig linux-libre-2.6.38-gnu1/arch/arm/mach-davinci/Kconfig
--- linux-libre-2.6.37-gnu1/arch/arm/mach-davinci/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-davinci/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -61,6 +61,8 @@ config MACH_DAVINCI_EVM
 	bool "TI DM644x EVM"
 	default ARCH_DAVINCI_DM644x
 	depends on ARCH_DAVINCI_DM644x
+	select MISC_DEVICES
+	select EEPROM_AT24
 	help
 	  Configure this option to specify the whether the board used
 	  for development is a DM644x EVM
@@ -68,6 +70,8 @@ config MACH_DAVINCI_EVM
 config MACH_SFFSDR
 	bool "Lyrtech SFFSDR"
 	depends on ARCH_DAVINCI_DM644x
+	select MISC_DEVICES
+	select EEPROM_AT24
 	help
 	  Say Y here to select the Lyrtech Small Form Factor
 	  Software Defined Radio (SFFSDR) board.
@@ -99,6 +103,8 @@ config MACH_DAVINCI_DM6467_EVM
 	default ARCH_DAVINCI_DM646x
 	depends on ARCH_DAVINCI_DM646x
 	select MACH_DAVINCI_DM6467TEVM
+	select MISC_DEVICES
+	select EEPROM_AT24
 	help
 	  Configure this option to specify the whether the board used
 	  for development is a DM6467 EVM
@@ -110,6 +116,8 @@ config MACH_DAVINCI_DM365_EVM
 	bool "TI DM365 EVM"
 	default ARCH_DAVINCI_DM365
 	depends on ARCH_DAVINCI_DM365
+	select MISC_DEVICES
+	select EEPROM_AT24
 	help
 	  Configure this option to specify whether the board used
 	  for development is a DM365 EVM
@@ -119,6 +127,8 @@ config MACH_DAVINCI_DA830_EVM
 	default ARCH_DAVINCI_DA830
 	depends on ARCH_DAVINCI_DA830
 	select GPIO_PCF857X
+	select MISC_DEVICES
+	select EEPROM_AT24
 	help
 	  Say Y here to select the TI DA830/OMAP-L137/AM17x Evaluation Module.
 
@@ -148,7 +158,6 @@ config MACH_DAVINCI_DA850_EVM
 	bool "TI DA850/OMAP-L138/AM18x Reference Platform"
 	default ARCH_DAVINCI_DA850
 	depends on ARCH_DAVINCI_DA850
-	select GPIO_PCA953X
 	help
 	  Say Y here to select the TI DA850/OMAP-L138/AM18x Evaluation Module.
 
@@ -178,6 +187,12 @@ config DA850_UI_RMII
 
 endchoice
 
+config GPIO_PCA953X
+	default MACH_DAVINCI_DA850_EVM
+
+config KEYBOARD_GPIO_POLLED
+	default MACH_DAVINCI_DA850_EVM
+
 config MACH_TNETV107X
 	bool "TI TNETV107X Reference Platform"
 	default ARCH_DAVINCI_TNETV107X
@@ -188,6 +203,8 @@ config MACH_TNETV107X
 config MACH_MITYOMAPL138
 	bool "Critical Link MityDSP-L138/MityARM-1808 SoM"
 	depends on ARCH_DAVINCI_DA850
+	select MISC_DEVICES
+	select EEPROM_AT24
 	help
 	  Say Y here to select the Critical Link MityDSP-L138/MityARM-1808
 	  System on Module.  Information on this SoM may be found at
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-davinci/pm.c linux-libre-2.6.38-gnu1/arch/arm/mach-davinci/pm.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-davinci/pm.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-davinci/pm.c	2011-03-14 21:20:32.000000000 -0400
@@ -110,7 +110,7 @@ static int davinci_pm_enter(suspend_stat
 	return ret;
 }
 
-static struct platform_suspend_ops davinci_pm_ops = {
+static const struct platform_suspend_ops davinci_pm_ops = {
 	.enter		= davinci_pm_enter,
 	.valid		= suspend_valid_only_mem,
 };
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-davinci/psc.c linux-libre-2.6.38-gnu1/arch/arm/mach-davinci/psc.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-davinci/psc.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-davinci/psc.c	2011-03-14 21:20:32.000000000 -0400
@@ -83,21 +83,16 @@ void davinci_psc_config(unsigned int dom
 		pdctl1 = __raw_readl(psc_base + PDCTL1);
 		pdctl1 |= 0x100;
 		__raw_writel(pdctl1, psc_base + PDCTL1);
-
-		do {
-			ptstat = __raw_readl(psc_base +
-					       PTSTAT);
-		} while (!(((ptstat >> domain) & 1) == 0));
 	} else {
 		ptcmd = 1 << domain;
 		__raw_writel(ptcmd, psc_base + PTCMD);
-
-		do {
-			ptstat = __raw_readl(psc_base + PTSTAT);
-		} while (!(((ptstat >> domain) & 1) == 0));
 	}
 
 	do {
+		ptstat = __raw_readl(psc_base + PTSTAT);
+	} while (!(((ptstat >> domain) & 1) == 0));
+
+	do {
 		mdstat = __raw_readl(psc_base + MDSTAT + 4 * id);
 	} while (!((mdstat & MDSTAT_STATE_MASK) == next_state));
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-davinci/time.c linux-libre-2.6.38-gnu1/arch/arm/mach-davinci/time.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-davinci/time.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-davinci/time.c	2011-03-14 21:20:32.000000000 -0400
@@ -272,15 +272,35 @@ static cycle_t read_cycles(struct clocks
 	return (cycles_t)timer32_read(t);
 }
 
+/*
+ * Kernel assumes that sched_clock can be called early but may not have
+ * things ready yet.
+ */
+static cycle_t read_dummy(struct clocksource *cs)
+{
+	return 0;
+}
+
+
 static struct clocksource clocksource_davinci = {
 	.rating		= 300,
-	.read		= read_cycles,
+	.read		= read_dummy,
 	.mask		= CLOCKSOURCE_MASK(32),
-	.shift		= 24,
 	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
 /*
+ * Overwrite weak default sched_clock with something more precise
+ */
+unsigned long long notrace sched_clock(void)
+{
+	const cycle_t cyc = clocksource_davinci.read(&clocksource_davinci);
+
+	return clocksource_cyc2ns(cyc, clocksource_davinci.mult,
+				clocksource_davinci.shift);
+}
+
+/*
  * clockevent
  */
 static int davinci_set_next_event(unsigned long cycles,
@@ -377,11 +397,10 @@ static void __init davinci_timer_init(vo
 	davinci_clock_tick_rate = clk_get_rate(timer_clk);
 
 	/* setup clocksource */
+	clocksource_davinci.read = read_cycles;
 	clocksource_davinci.name = id_to_name[clocksource_id];
-	clocksource_davinci.mult =
-		clocksource_khz2mult(davinci_clock_tick_rate/1000,
-				     clocksource_davinci.shift);
-	if (clocksource_register(&clocksource_davinci))
+	if (clocksource_register_hz(&clocksource_davinci,
+				    davinci_clock_tick_rate))
 		printk(err, clocksource_davinci.name);
 
 	/* setup clockevent */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-davinci/tnetv107x.c linux-libre-2.6.38-gnu1/arch/arm/mach-davinci/tnetv107x.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-davinci/tnetv107x.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-davinci/tnetv107x.c	2011-03-14 21:20:32.000000000 -0400
@@ -131,12 +131,13 @@ define_pll_clk(tdm, 1, 0x0ff, 0x200);
 define_pll_clk(eth, 2, 0x0ff, 0x400);
 
 /* Level 2 - divided outputs from the PLLs */
-#define define_pll_div_clk(pll, cname, div)		\
-	static struct clk pll##_##cname##_clk = {	\
-		.name		= #pll "_" #cname "_clk",\
-		.parent		= &pll_##pll##_clk,	\
-		.flags		= CLK_PLL,		\
-		.div_reg	= PLLDIV##div,		\
+#define define_pll_div_clk(pll, cname, div)			\
+	static struct clk pll##_##cname##_clk = {		\
+		.name		= #pll "_" #cname "_clk",	\
+		.parent		= &pll_##pll##_clk,		\
+		.flags		= CLK_PLL,			\
+		.div_reg	= PLLDIV##div,			\
+		.set_rate	= davinci_set_sysclk_rate,	\
 	}
 
 define_pll_div_clk(sys, arm1176,	1);
@@ -192,6 +193,7 @@ lpsc_clk_enabled(system,	sys_half_clk,	S
 lpsc_clk_enabled(ddr2_vrst,	sys_ddr_clk,	DDR2_EMIF1_VRST);
 lpsc_clk_enabled(ddr2_vctl_rst,	sys_ddr_clk,	DDR2_EMIF2_VCTL_RST);
 lpsc_clk_enabled(wdt_arm,	sys_half_clk,	WDT_ARM);
+lpsc_clk_enabled(timer1,	sys_half_clk,	TIMER1);
 
 lpsc_clk(mbx_lite,	sys_arm1176_clk,	MBX_LITE);
 lpsc_clk(ethss,		eth_125mhz_clk,		ETHSS);
@@ -205,16 +207,15 @@ lpsc_clk(mdio,		sys_half_clk,		MDIO);
 lpsc_clk(sdio0,		sys_half_clk,		SDIO0);
 lpsc_clk(sdio1,		sys_half_clk,		SDIO1);
 lpsc_clk(timer0,	sys_half_clk,		TIMER0);
-lpsc_clk(timer1,	sys_half_clk,		TIMER1);
 lpsc_clk(wdt_dsp,	sys_half_clk,		WDT_DSP);
 lpsc_clk(ssp,		sys_half_clk,		SSP);
 lpsc_clk(tdm0,		tdm_0_clk,		TDM0);
 lpsc_clk(tdm1,		tdm_1_clk,		TDM1);
 lpsc_clk(vlynq,		sys_vlynq_ref_clk,	VLYNQ);
 lpsc_clk(mcdma,		sys_half_clk,		MCDMA);
-lpsc_clk(usb0,		sys_half_clk,		USB0);
-lpsc_clk(usb1,		sys_half_clk,		USB1);
 lpsc_clk(usbss,		sys_half_clk,		USBSS);
+lpsc_clk(usb0,		clk_usbss,		USB0);
+lpsc_clk(usb1,		clk_usbss,		USB1);
 lpsc_clk(ethss_rgmii,	eth_250mhz_clk,		ETHSS_RGMII);
 lpsc_clk(imcop,		sys_dsp_clk,		IMCOP);
 lpsc_clk(spare,		sys_half_clk,		SPARE);
@@ -281,7 +282,9 @@ static struct clk_lookup clks[] = {
 	CLK(NULL,		"clk_tdm0",		&clk_tdm0),
 	CLK(NULL,		"clk_vlynq",		&clk_vlynq),
 	CLK(NULL,		"clk_mcdma",		&clk_mcdma),
+	CLK(NULL,		"clk_usbss",		&clk_usbss),
 	CLK(NULL,		"clk_usb0",		&clk_usb0),
+	CLK(NULL,		"clk_usb1",		&clk_usb1),
 	CLK(NULL,		"clk_tdm1",		&clk_tdm1),
 	CLK(NULL,		"clk_debugss",		&clk_debugss),
 	CLK(NULL,		"clk_ethss_rgmii",	&clk_ethss_rgmii),
@@ -289,8 +292,6 @@ static struct clk_lookup clks[] = {
 	CLK(NULL,		"clk_imcop",		&clk_imcop),
 	CLK(NULL,		"clk_spare",		&clk_spare),
 	CLK("davinci_mmc.1",	NULL,			&clk_sdio1),
-	CLK(NULL,		"clk_usb1",		&clk_usb1),
-	CLK(NULL,		"clk_usbss",		&clk_usbss),
 	CLK(NULL,		"clk_ddr2_vrst",	&clk_ddr2_vrst),
 	CLK(NULL,		"clk_ddr2_vctl_rst",	&clk_ddr2_vctl_rst),
 	CLK(NULL,		NULL,			NULL),
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-davinci/usb.c linux-libre-2.6.38-gnu1/arch/arm/mach-davinci/usb.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-davinci/usb.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-davinci/usb.c	2011-03-14 21:20:32.000000000 -0400
@@ -64,17 +64,19 @@ static struct resource usb_resources[] =
 	{
 		.start          = IRQ_USBINT,
 		.flags          = IORESOURCE_IRQ,
+		.name		= "mc"
 	},
 	{
 		/* placeholder for the dedicated CPPI IRQ */
 		.flags          = IORESOURCE_IRQ,
+		.name		= "dma"
 	},
 };
 
 static u64 usb_dmamask = DMA_BIT_MASK(32);
 
 static struct platform_device usb_dev = {
-	.name           = "musb_hdrc",
+	.name           = "musb-davinci",
 	.id             = -1,
 	.dev = {
 		.platform_data		= &usb_data,
@@ -110,6 +112,7 @@ static struct resource da8xx_usb20_resou
 	{
 		.start		= IRQ_DA8XX_USB_INT,
 		.flags		= IORESOURCE_IRQ,
+		.name		= "mc",
 	},
 };
 
@@ -121,6 +124,7 @@ int __init da8xx_register_usb20(unsigned
 
 	usb_dev.resource = da8xx_usb20_resources;
 	usb_dev.num_resources = ARRAY_SIZE(da8xx_usb20_resources);
+	usb_dev.name = "musb-da8xx";
 
 	return platform_device_register(&usb_dev);
 }
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-dove/cm-a510.c linux-libre-2.6.38-gnu1/arch/arm/mach-dove/cm-a510.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-dove/cm-a510.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-dove/cm-a510.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,95 @@
+/*
+ * arch/arm/mach-dove/cm-a510.c
+ *
+ * Copyright (C) 2010 CompuLab, Ltd.
+ * Konstantin Sinyuk <kostyas@compulab.co.il>
+ *
+ * Based on Marvell DB-MV88AP510-BP Development Board Setup
+ *
+ * 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/platform_device.h>
+#include <linux/ata_platform.h>
+#include <linux/mv643xx_eth.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/flash.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+
+#include <mach/dove.h>
+
+#include "common.h"
+
+static struct mv643xx_eth_platform_data cm_a510_ge00_data = {
+	.phy_addr	= MV643XX_ETH_PHY_ADDR_DEFAULT,
+};
+
+static struct mv_sata_platform_data cm_a510_sata_data = {
+	.n_ports        = 1,
+};
+
+/*
+ * SPI Devices:
+ * SPI0: 1M Flash Winbond w25q32bv
+ */
+static const struct flash_platform_data cm_a510_spi_flash_data = {
+	.type		= "w25q32bv",
+};
+
+static struct spi_board_info __initdata cm_a510_spi_flash_info[] = {
+	{
+		.modalias       = "m25p80",
+		.platform_data  = &cm_a510_spi_flash_data,
+		.irq            = -1,
+		.max_speed_hz   = 20000000,
+		.bus_num        = 0,
+		.chip_select    = 0,
+	},
+};
+
+static int __init cm_a510_pci_init(void)
+{
+	if (machine_is_cm_a510())
+		dove_pcie_init(1, 1);
+
+	return 0;
+}
+
+subsys_initcall(cm_a510_pci_init);
+
+/* Board Init */
+static void __init cm_a510_init(void)
+{
+	/*
+	 * Basic Dove setup. Needs to be called early.
+	 */
+	dove_init();
+
+	dove_ge00_init(&cm_a510_ge00_data);
+	dove_ehci0_init();
+	dove_ehci1_init();
+	dove_sata_init(&cm_a510_sata_data);
+	dove_sdio0_init();
+	dove_sdio1_init();
+	dove_spi0_init();
+	dove_spi1_init();
+	dove_uart0_init();
+	dove_uart1_init();
+	dove_i2c_init();
+	spi_register_board_info(cm_a510_spi_flash_info,
+				ARRAY_SIZE(cm_a510_spi_flash_info));
+}
+
+MACHINE_START(CM_A510, "Compulab CM-A510 Board")
+	.boot_params	= 0x00000100,
+	.init_machine	= cm_a510_init,
+	.map_io		= dove_map_io,
+	.init_irq	= dove_init_irq,
+	.timer		= &dove_timer,
+MACHINE_END
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-dove/common.c linux-libre-2.6.38-gnu1/arch/arm/mach-dove/common.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-dove/common.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-dove/common.c	2011-03-14 21:20:32.000000000 -0400
@@ -770,7 +770,7 @@ static struct resource dove_sdio0_resour
 };
 
 static struct platform_device dove_sdio0 = {
-	.name		= "sdhci-mv",
+	.name		= "sdhci-dove",
 	.id		= 0,
 	.dev		= {
 		.dma_mask		= &sdio_dmamask,
@@ -798,7 +798,7 @@ static struct resource dove_sdio1_resour
 };
 
 static struct platform_device dove_sdio1 = {
-	.name		= "sdhci-mv",
+	.name		= "sdhci-dove",
 	.id		= 1,
 	.dev		= {
 		.dma_mask		= &sdio_dmamask,
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-dove/include/mach/dove.h linux-libre-2.6.38-gnu1/arch/arm/mach-dove/include/mach/dove.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-dove/include/mach/dove.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-dove/include/mach/dove.h	2011-03-14 21:20:32.000000000 -0400
@@ -131,14 +131,21 @@
 #define DOVE_RESET_SAMPLE_LO	(DOVE_MPP_VIRT_BASE | 0x014)
 #define DOVE_RESET_SAMPLE_HI	(DOVE_MPP_VIRT_BASE | 0x018)
 #define DOVE_GPIO_VIRT_BASE	(DOVE_SB_REGS_VIRT_BASE | 0xd0400)
+#define DOVE_GPIO2_VIRT_BASE    (DOVE_SB_REGS_VIRT_BASE | 0xe8400)
 #define DOVE_MPP_GENERAL_VIRT_BASE	(DOVE_SB_REGS_VIRT_BASE | 0xe803c)
 #define  DOVE_AU1_SPDIFO_GPIO_EN	(1 << 1)
 #define  DOVE_NAND_GPIO_EN		(1 << 0)
 #define DOVE_MPP_CTRL4_VIRT_BASE	(DOVE_GPIO_VIRT_BASE + 0x40)
-
+#define  DOVE_SPI_GPIO_SEL		(1 << 5)
+#define  DOVE_UART1_GPIO_SEL		(1 << 4)
+#define  DOVE_AU1_GPIO_SEL		(1 << 3)
+#define  DOVE_CAM_GPIO_SEL		(1 << 2)
+#define  DOVE_SD1_GPIO_SEL		(1 << 1)
+#define  DOVE_SD0_GPIO_SEL		(1 << 0)
 
 /* Power Management */
 #define DOVE_PMU_VIRT_BASE	(DOVE_SB_REGS_VIRT_BASE | 0xd0000)
+#define DOVE_PMU_SIG_CTRL	(DOVE_PMU_VIRT_BASE + 0x802c)
 
 /* Real Time Clock */
 #define DOVE_RTC_PHYS_BASE	(DOVE_SB_REGS_PHYS_BASE | 0xd8500)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-dove/include/mach/gpio.h linux-libre-2.6.38-gnu1/arch/arm/mach-dove/include/mach/gpio.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-dove/include/mach/gpio.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-dove/include/mach/gpio.h	2011-03-14 21:20:32.000000000 -0400
@@ -14,12 +14,14 @@
 #include <plat/gpio.h>
 #include <asm-generic/gpio.h>		/* cansleep wrappers */
 
-#define GPIO_MAX	64
+#define GPIO_MAX	72
 
 #define GPIO_BASE_LO		(DOVE_GPIO_VIRT_BASE + 0x00)
 #define GPIO_BASE_HI		(DOVE_GPIO_VIRT_BASE + 0x20)
 
-#define GPIO_BASE(pin)		((pin < 32) ? GPIO_BASE_LO : GPIO_BASE_HI)
+#define GPIO_BASE(pin)		((pin < 32) ? GPIO_BASE_LO :		\
+				 ((pin < 64) ? GPIO_BASE_HI :		\
+				  DOVE_GPIO2_VIRT_BASE))
 
 #define GPIO_OUT(pin)		(GPIO_BASE(pin) + 0x00)
 #define GPIO_IO_CONF(pin)	(GPIO_BASE(pin) + 0x04)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-dove/irq.c linux-libre-2.6.38-gnu1/arch/arm/mach-dove/irq.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-dove/irq.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-dove/irq.c	2011-03-14 21:20:32.000000000 -0400
@@ -36,9 +36,9 @@ static void gpio_irq_handler(unsigned in
 	}
 }
 
-static void pmu_irq_mask(unsigned int irq)
+static void pmu_irq_mask(struct irq_data *d)
 {
-	int pin = irq_to_pmu(irq);
+	int pin = irq_to_pmu(d->irq);
 	u32 u;
 
 	u = readl(PMU_INTERRUPT_MASK);
@@ -46,9 +46,9 @@ static void pmu_irq_mask(unsigned int ir
 	writel(u, PMU_INTERRUPT_MASK);
 }
 
-static void pmu_irq_unmask(unsigned int irq)
+static void pmu_irq_unmask(struct irq_data *d)
 {
-	int pin = irq_to_pmu(irq);
+	int pin = irq_to_pmu(d->irq);
 	u32 u;
 
 	u = readl(PMU_INTERRUPT_MASK);
@@ -56,9 +56,9 @@ static void pmu_irq_unmask(unsigned int
 	writel(u, PMU_INTERRUPT_MASK);
 }
 
-static void pmu_irq_ack(unsigned int irq)
+static void pmu_irq_ack(struct irq_data *d)
 {
-	int pin = irq_to_pmu(irq);
+	int pin = irq_to_pmu(d->irq);
 	u32 u;
 
 	u = ~(1 << (pin & 31));
@@ -67,9 +67,9 @@ static void pmu_irq_ack(unsigned int irq
 
 static struct irq_chip pmu_irq_chip = {
 	.name		= "pmu_irq",
-	.mask		= pmu_irq_mask,
-	.unmask		= pmu_irq_unmask,
-	.ack		= pmu_irq_ack,
+	.irq_mask	= pmu_irq_mask,
+	.irq_unmask	= pmu_irq_unmask,
+	.irq_ack	= pmu_irq_ack,
 };
 
 static void pmu_irq_handler(unsigned int irq, struct irq_desc *desc)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-dove/Kconfig linux-libre-2.6.38-gnu1/arch/arm/mach-dove/Kconfig
--- linux-libre-2.6.37-gnu1/arch/arm/mach-dove/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-dove/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -9,6 +9,12 @@ config MACH_DOVE_DB
 	  Say 'Y' here if you want your kernel to support the
 	  Marvell DB-MV88AP510 Development Board.
 
+ config MACH_CM_A510
+	bool "CompuLab CM-A510 Board"
+	help
+	  Say 'Y' here if you want your kernel to support the
+	  CompuLab CM-A510 Board.
+
 endmenu
 
 endif
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-dove/Makefile linux-libre-2.6.38-gnu1/arch/arm/mach-dove/Makefile
--- linux-libre-2.6.37-gnu1/arch/arm/mach-dove/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-dove/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -1,3 +1,4 @@
-obj-y				+= common.o addr-map.o irq.o pcie.o
+obj-y				+= common.o addr-map.o irq.o pcie.o mpp.o
 
 obj-$(CONFIG_MACH_DOVE_DB)	+= dove-db-setup.o
+obj-$(CONFIG_MACH_CM_A510)	+= cm-a510.o
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-dove/mpp.c linux-libre-2.6.38-gnu1/arch/arm/mach-dove/mpp.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-dove/mpp.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-dove/mpp.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,212 @@
+/*
+ * arch/arm/mach-dove/mpp.c
+ *
+ * MPP functions for Marvell Dove SoCs
+ *
+ * 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/gpio.h>
+#include <linux/io.h>
+
+#include <mach/dove.h>
+
+#include "mpp.h"
+
+#define MPP_NR_REGS 4
+#define MPP_CTRL(i)	((i) == 3 ?				\
+			 DOVE_MPP_CTRL4_VIRT_BASE :		\
+			 DOVE_MPP_VIRT_BASE + (i) * 4)
+#define PMU_SIG_REGS 2
+#define PMU_SIG_CTRL(i)	(DOVE_PMU_SIG_CTRL + (i) * 4)
+
+struct dove_mpp_grp {
+	int start;
+	int end;
+};
+
+static struct dove_mpp_grp dove_mpp_grp[] = {
+	[MPP_24_39] = {
+		.start	= 24,
+		.end	= 39,
+	},
+	[MPP_40_45] = {
+		.start	= 40,
+		.end	= 45,
+	},
+	[MPP_46_51] = {
+		.start	= 40,
+		.end	= 45,
+	},
+	[MPP_58_61] = {
+		.start	= 58,
+		.end	= 61,
+	},
+	[MPP_62_63] = {
+		.start	= 62,
+		.end	= 63,
+	},
+};
+
+static void dove_mpp_gpio_mode(int start, int end, int gpio_mode)
+{
+	int i;
+
+	for (i = start; i <= end; i++)
+		orion_gpio_set_valid(i, gpio_mode);
+}
+
+static void dove_mpp_dump_regs(void)
+{
+#ifdef DEBUG
+	int i;
+
+	pr_debug("MPP_CTRL regs:");
+	for (i = 0; i < MPP_NR_REGS; i++)
+		printk(" %08x", readl(MPP_CTRL(i)));
+	printk("\n");
+
+	pr_debug("PMU_SIG_CTRL regs:");
+	for (i = 0; i < PMU_SIG_REGS; i++)
+		printk(" %08x", readl(PMU_SIG_CTRL(i)));
+	printk("\n");
+
+	pr_debug("PMU_MPP_GENERAL_CTRL: %08x\n", readl(DOVE_PMU_MPP_GENERAL_CTRL));
+	pr_debug("MPP_GENERAL: %08x\n", readl(DOVE_MPP_GENERAL_VIRT_BASE));
+#endif
+}
+
+static void dove_mpp_cfg_nfc(int sel)
+{
+	u32 mpp_gen_cfg = readl(DOVE_MPP_GENERAL_VIRT_BASE);
+
+	mpp_gen_cfg &= ~0x1;
+	mpp_gen_cfg |= sel;
+	writel(mpp_gen_cfg, DOVE_MPP_GENERAL_VIRT_BASE);
+
+	dove_mpp_gpio_mode(64, 71, GPIO_OUTPUT_OK);
+}
+
+static void dove_mpp_cfg_au1(int sel)
+{
+	u32 mpp_ctrl4		= readl(DOVE_MPP_CTRL4_VIRT_BASE);
+	u32 ssp_ctrl1 = readl(DOVE_SSP_CTRL_STATUS_1);
+	u32 mpp_gen_ctrl = readl(DOVE_MPP_GENERAL_VIRT_BASE);
+	u32 global_cfg_2 = readl(DOVE_GLOBAL_CONFIG_2);
+
+	mpp_ctrl4 &= ~(DOVE_AU1_GPIO_SEL);
+	ssp_ctrl1 &= ~(DOVE_SSP_ON_AU1);
+	mpp_gen_ctrl &= ~(DOVE_AU1_SPDIFO_GPIO_EN);
+	global_cfg_2 &= ~(DOVE_TWSI_OPTION3_GPIO);
+
+	if (!sel || sel == 0x2)
+		dove_mpp_gpio_mode(52, 57, 0);
+	else
+		dove_mpp_gpio_mode(52, 57, GPIO_OUTPUT_OK | GPIO_INPUT_OK);
+
+	if (sel & 0x1) {
+		global_cfg_2 |= DOVE_TWSI_OPTION3_GPIO;
+		dove_mpp_gpio_mode(56, 57, 0);
+	}
+	if (sel & 0x2) {
+		mpp_gen_ctrl |= DOVE_AU1_SPDIFO_GPIO_EN;
+		dove_mpp_gpio_mode(57, 57, GPIO_OUTPUT_OK | GPIO_INPUT_OK);
+	}
+	if (sel & 0x4) {
+		ssp_ctrl1 |= DOVE_SSP_ON_AU1;
+		dove_mpp_gpio_mode(52, 55, 0);
+	}
+	if (sel & 0x8)
+		mpp_ctrl4 |= DOVE_AU1_GPIO_SEL;
+
+	writel(mpp_ctrl4, DOVE_MPP_CTRL4_VIRT_BASE);
+	writel(ssp_ctrl1, DOVE_SSP_CTRL_STATUS_1);
+	writel(mpp_gen_ctrl, DOVE_MPP_GENERAL_VIRT_BASE);
+	writel(global_cfg_2, DOVE_GLOBAL_CONFIG_2);
+}
+
+static void dove_mpp_conf_grp(int num, int sel, u32 *mpp_ctrl)
+{
+	int start = dove_mpp_grp[num].start;
+	int end = dove_mpp_grp[num].end;
+	int gpio_mode = sel ? GPIO_OUTPUT_OK | GPIO_INPUT_OK : 0;
+
+	*mpp_ctrl &= ~(0x1 << num);
+	*mpp_ctrl |= sel << num;
+
+	dove_mpp_gpio_mode(start, end, gpio_mode);
+}
+
+void __init dove_mpp_conf(unsigned int *mpp_list)
+{
+	u32 mpp_ctrl[MPP_NR_REGS];
+	u32 pmu_mpp_ctrl = 0;
+	u32 pmu_sig_ctrl[PMU_SIG_REGS];
+	int i;
+
+	/* Initialize gpiolib. */
+	orion_gpio_init();
+
+	for (i = 0; i < MPP_NR_REGS; i++)
+		mpp_ctrl[i] = readl(MPP_CTRL(i));
+
+	for (i = 0; i < PMU_SIG_REGS; i++)
+		pmu_sig_ctrl[i] = readl(PMU_SIG_CTRL(i));
+
+	pmu_mpp_ctrl = readl(DOVE_PMU_MPP_GENERAL_CTRL);
+
+	dove_mpp_dump_regs();
+
+	for ( ; *mpp_list != MPP_END; mpp_list++) {
+		unsigned int num = MPP_NUM(*mpp_list);
+		unsigned int sel = MPP_SEL(*mpp_list);
+		int shift, gpio_mode;
+
+		if (num > MPP_MAX) {
+			pr_err("dove: invalid MPP number (%u)\n", num);
+			continue;
+		}
+
+		if (*mpp_list & MPP_NFC_MASK) {
+			dove_mpp_cfg_nfc(sel);
+			continue;
+		}
+
+		if (*mpp_list & MPP_AU1_MASK) {
+			dove_mpp_cfg_au1(sel);
+			continue;
+		}
+
+		if (*mpp_list & MPP_GRP_MASK) {
+			dove_mpp_conf_grp(num, sel, &mpp_ctrl[3]);
+			continue;
+		}
+
+		shift = (num & 7) << 2;
+		if (*mpp_list & MPP_PMU_MASK) {
+			pmu_mpp_ctrl |= (0x1 << num);
+			pmu_sig_ctrl[num / 8] &= ~(0xf << shift);
+			pmu_sig_ctrl[num / 8] |= 0xf << shift;
+			gpio_mode = 0;
+		} else {
+			mpp_ctrl[num / 8] &= ~(0xf << shift);
+			mpp_ctrl[num / 8] |= sel << shift;
+			gpio_mode = GPIO_OUTPUT_OK | GPIO_INPUT_OK;
+		}
+
+		orion_gpio_set_valid(num, gpio_mode);
+	}
+
+	for (i = 0; i < MPP_NR_REGS; i++)
+		writel(mpp_ctrl[i], MPP_CTRL(i));
+
+	for (i = 0; i < PMU_SIG_REGS; i++)
+		writel(pmu_sig_ctrl[i], PMU_SIG_CTRL(i));
+
+	writel(pmu_mpp_ctrl, DOVE_PMU_MPP_GENERAL_CTRL);
+
+	dove_mpp_dump_regs();
+}
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-dove/mpp.h linux-libre-2.6.38-gnu1/arch/arm/mach-dove/mpp.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-dove/mpp.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-dove/mpp.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,220 @@
+#ifndef __ARCH_DOVE_MPP_CODED_H
+#define __ARCH_DOVE_MPP_CODED_H
+
+#define MPP(_num, _mode, _pmu, _grp, _au1, _nfc) (	\
+/* MPP/group number */		((_num) & 0xff) |		\
+/* MPP select value */		(((_mode) & 0xf) << 8) |	\
+/* MPP PMU */			((!!(_pmu)) << 12) |		\
+/* group flag */		((!!(_grp)) << 13) |		\
+/* AU1 flag */			((!!(_au1)) << 14) |		\
+/* NFCE flag */			((!!(_nfc)) << 15))
+
+#define MPP_MAX	71
+
+#define MPP_NUM(x)    ((x) & 0xff)
+#define MPP_SEL(x)    (((x) >> 8) & 0xf)
+
+#define MPP_PMU_MASK		MPP(0, 0x0, 1, 0, 0, 0)
+#define MPP_GRP_MASK		MPP(0, 0x0, 0, 1, 0, 0)
+#define MPP_AU1_MASK		MPP(0, 0x0, 0, 0, 1, 0)
+#define MPP_NFC_MASK		MPP(0, 0x0, 0, 0, 0, 1)
+
+#define MPP_END			MPP(0xff, 0xf, 1, 1, 1, 1)
+
+#define MPP_PMU_DRIVE_0		0x1
+#define MPP_PMU_DRIVE_1		0x2
+#define MPP_PMU_SDI		0x3
+#define MPP_PMU_CPU_PWRDWN	0x4
+#define MPP_PMU_STBY_PWRDWN	0x5
+#define MPP_PMU_CORE_PWR_GOOD	0x8
+#define MPP_PMU_BAT_FAULT	0xa
+#define MPP_PMU_EXT0_WU		0xb
+#define MPP_PMU_EXT1_WU		0xc
+#define MPP_PMU_EXT2_WU		0xd
+#define MPP_PMU_BLINK		0xe
+#define MPP_PMU(_num, _mode)	MPP((_num), MPP_PMU_##_mode, 1, 0, 0, 0)
+
+#define MPP_PIN(_num, _mode)	MPP((_num), (_mode), 0, 0, 0, 0)
+#define MPP_GRP(_grp, _mode)	MPP((_grp), (_mode), 0, 1, 0, 0)
+#define MPP_GRP_AU1(_mode)	MPP(0, (_mode), 0, 0, 1, 0)
+#define MPP_GRP_NFC(_mode)	MPP(0, (_mode), 0, 0, 0, 1)
+
+#define MPP0_GPIO0		MPP_PIN(0, 0x0)
+#define MPP0_UA2_RTSn		MPP_PIN(0, 0x2)
+#define MPP0_SDIO0_CD		MPP_PIN(0, 0x3)
+#define MPP0_LCD0_PWM		MPP_PIN(0, 0xf)
+
+#define MPP1_GPIO1		MPP_PIN(1, 0x0)
+#define MPP1_UA2_CTSn		MPP_PIN(1, 0x2)
+#define MPP1_SDIO0_WP		MPP_PIN(1, 0x3)
+#define MPP1_LCD1_PWM		MPP_PIN(1, 0xf)
+
+#define MPP2_GPIO2		MPP_PIN(2, 0x0)
+#define MPP2_SATA_PRESENT	MPP_PIN(2, 0x1)
+#define MPP2_UA2_TXD		MPP_PIN(2, 0x2)
+#define MPP2_SDIO0_BUS_POWER	MPP_PIN(2, 0x3)
+#define MPP2_UA_RTSn1		MPP_PIN(2, 0x4)
+
+#define MPP3_GPIO3		MPP_PIN(3, 0x0)
+#define MPP3_SATA_ACT		MPP_PIN(3, 0x1)
+#define MPP3_UA2_RXD		MPP_PIN(3, 0x2)
+#define MPP3_SDIO0_LED_CTRL	MPP_PIN(3, 0x3)
+#define MPP3_UA_CTSn1		MPP_PIN(3, 0x4)
+#define MPP3_SPI_LCD_CS1	MPP_PIN(3, 0xf)
+
+#define MPP4_GPIO4		MPP_PIN(4, 0x0)
+#define MPP4_UA3_RTSn		MPP_PIN(4, 0x2)
+#define MPP4_SDIO1_CD		MPP_PIN(4, 0x3)
+#define MPP4_SPI_1_MISO		MPP_PIN(4, 0x4)
+
+#define MPP5_GPIO5		MPP_PIN(5, 0x0)
+#define MPP5_UA3_CTSn		MPP_PIN(5, 0x2)
+#define MPP5_SDIO1_WP		MPP_PIN(5, 0x3)
+#define MPP5_SPI_1_CS		MPP_PIN(5, 0x4)
+
+#define MPP6_GPIO6		MPP_PIN(6, 0x0)
+#define MPP6_UA3_TXD		MPP_PIN(6, 0x2)
+#define MPP6_SDIO1_BUS_POWER	MPP_PIN(6, 0x3)
+#define MPP6_SPI_1_MOSI		MPP_PIN(6, 0x4)
+
+#define MPP7_GPIO7		MPP_PIN(7, 0x0)
+#define MPP7_UA3_RXD		MPP_PIN(7, 0x2)
+#define MPP7_SDIO1_LED_CTRL	MPP_PIN(7, 0x3)
+#define MPP7_SPI_1_SCK		MPP_PIN(7, 0x4)
+
+#define MPP8_GPIO8		MPP_PIN(8, 0x0)
+#define MPP8_WD_RST_OUT		MPP_PIN(8, 0x1)
+
+#define MPP9_GPIO9		MPP_PIN(9, 0x0)
+#define MPP9_PEX1_CLKREQn	MPP_PIN(9, 0x5)
+
+#define MPP10_GPIO10		MPP_PIN(10, 0x0)
+#define MPP10_SSP_SCLK		MPP_PIN(10, 0x5)
+
+#define MPP11_GPIO11		MPP_PIN(11, 0x0)
+#define MPP11_SATA_PRESENT	MPP_PIN(11, 0x1)
+#define MPP11_SATA_ACT		MPP_PIN(11, 0x2)
+#define MPP11_SDIO0_LED_CTRL	MPP_PIN(11, 0x3)
+#define MPP11_SDIO1_LED_CTRL	MPP_PIN(11, 0x4)
+#define MPP11_PEX0_CLKREQn	MPP_PIN(11, 0x5)
+
+#define MPP12_GPIO12		MPP_PIN(12, 0x0)
+#define MPP12_SATA_ACT		MPP_PIN(12, 0x1)
+#define MPP12_UA2_RTSn		MPP_PIN(12, 0x2)
+#define MPP12_AD0_I2S_EXT_MCLK	MPP_PIN(12, 0x3)
+#define MPP12_SDIO1_CD		MPP_PIN(12, 0x4)
+
+#define MPP13_GPIO13		MPP_PIN(13, 0x0)
+#define MPP13_UA2_CTSn		MPP_PIN(13, 0x2)
+#define MPP13_AD1_I2S_EXT_MCLK	MPP_PIN(13, 0x3)
+#define MPP13_SDIO1WP		MPP_PIN(13, 0x4)
+#define MPP13_SSP_EXTCLK	MPP_PIN(13, 0x5)
+
+#define MPP14_GPIO14		MPP_PIN(14, 0x0)
+#define MPP14_UA2_TXD		MPP_PIN(14, 0x2)
+#define MPP14_SDIO1_BUS_POWER	MPP_PIN(14, 0x4)
+#define MPP14_SSP_RXD		MPP_PIN(14, 0x5)
+
+#define MPP15_GPIO15		MPP_PIN(15, 0x0)
+#define MPP15_UA2_RXD		MPP_PIN(15, 0x2)
+#define MPP15_SDIO1_LED_CTRL	MPP_PIN(15, 0x4)
+#define MPP15_SSP_SFRM		MPP_PIN(15, 0x5)
+
+#define MPP16_GPIO16		MPP_PIN(16, 0x0)
+#define MPP16_UA3_RTSn		MPP_PIN(16, 0x2)
+#define MPP16_SDIO0_CD		MPP_PIN(16, 0x3)
+#define MPP16_SPI_LCD_CS1	MPP_PIN(16, 0x4)
+#define MPP16_AC97_SDATA_IN1	MPP_PIN(16, 0x5)
+
+#define MPP17_GPIO17		MPP_PIN(17, 0x0)
+#define MPP17_AC97_SYSCLK_OUT	MPP_PIN(17, 0x1)
+#define MPP17_UA3_CTSn		MPP_PIN(17, 0x2)
+#define MPP17_SDIO0_WP		MPP_PIN(17, 0x3)
+#define MPP17_TW_SDA2		MPP_PIN(17, 0x4)
+#define MPP17_AC97_SDATA_IN2	MPP_PIN(17, 0x5)
+
+#define MPP18_GPIO18		MPP_PIN(18, 0x0)
+#define MPP18_UA3_TXD		MPP_PIN(18, 0x2)
+#define MPP18_SDIO0_BUS_POWER	MPP_PIN(18, 0x3)
+#define MPP18_LCD0_PWM		MPP_PIN(18, 0x4)
+#define MPP18_AC_SDATA_IN3	MPP_PIN(18, 0x5)
+
+#define MPP19_GPIO19		MPP_PIN(19, 0x0)
+#define MPP19_UA3_RXD		MPP_PIN(19, 0x2)
+#define MPP19_SDIO0_LED_CTRL	MPP_PIN(19, 0x3)
+#define MPP19_TW_SCK2		MPP_PIN(19, 0x4)
+
+#define MPP20_GPIO20		MPP_PIN(20, 0x0)
+#define MPP20_AC97_SYSCLK_OUT	MPP_PIN(20, 0x1)
+#define MPP20_SPI_LCD_MISO	MPP_PIN(20, 0x2)
+#define MPP20_SDIO1_CD		MPP_PIN(20, 0x3)
+#define MPP20_SDIO0_CD		MPP_PIN(20, 0x5)
+#define MPP20_SPI_1_MISO	MPP_PIN(20, 0x6)
+
+#define MPP21_GPIO21		MPP_PIN(21, 0x0)
+#define MPP21_UA1_RTSn		MPP_PIN(21, 0x1)
+#define MPP21_SPI_LCD_CS0	MPP_PIN(21, 0x2)
+#define MPP21_SDIO1_WP		MPP_PIN(21, 0x3)
+#define MPP21_SSP_SFRM		MPP_PIN(21, 0x4)
+#define MPP21_SDIO0_WP		MPP_PIN(21, 0x5)
+#define MPP21_SPI_1_CS		MPP_PIN(21, 0x6)
+
+#define MPP22_GPIO22		MPP_PIN(22, 0x0)
+#define MPP22_UA1_CTSn		MPP_PIN(22, 0x1)
+#define MPP22_SPI_LCD_MOSI	MPP_PIN(22, 0x2)
+#define MPP22_SDIO1_BUS_POWER	MPP_PIN(22, 0x3)
+#define MPP22_SSP_TXD		MPP_PIN(22, 0x4)
+#define MPP22_SDIO0_BUS_POWER	MPP_PIN(22, 0x5)
+#define MPP22_SPI_1_MOSI	MPP_PIN(22, 0x6)
+
+#define MPP23_GPIO23		MPP_PIN(23, 0x0)
+#define MPP23_SPI_LCD_SCK	MPP_PIN(23, 0x2)
+#define MPP23_SDIO1_LED_CTRL	MPP_PIN(23, 0x3)
+#define MPP23_SSP_SCLK		MPP_PIN(23, 0x4)
+#define MPP23_SDIO0_LED_CTRL	MPP_PIN(23, 0x5)
+#define MPP23_SPI_1_SCK		MPP_PIN(23, 0x6)
+
+/* for MPP groups _num is a group index */
+enum dove_mpp_grp_idx {
+	MPP_24_39 = 2,
+	MPP_40_45 = 0,
+	MPP_46_51 = 1,
+	MPP_58_61 = 5,
+	MPP_62_63 = 4,
+};
+
+#define MPP24_39_GPIO		MPP_GRP(MPP_24_39, 0x1)
+#define MPP24_39_CAM		MPP_GRP(MPP_24_39, 0x0)
+
+#define MPP40_45_GPIO		MPP_GRP(MPP_40_45, 0x1)
+#define MPP40_45_SD0		MPP_GRP(MPP_40_45, 0x0)
+
+#define MPP46_51_GPIO		MPP_GRP(MPP_46_51, 0x1)
+#define MPP46_51_SD1		MPP_GRP(MPP_46_51, 0x0)
+
+#define MPP58_61_GPIO		MPP_GRP(MPP_58_61, 0x1)
+#define MPP58_61_SPI		MPP_GRP(MPP_58_61, 0x0)
+
+#define MPP62_63_GPIO		MPP_GRP(MPP_62_63, 0x1)
+#define MPP62_63_UA1		MPP_GRP(MPP_62_63, 0x0)
+
+/* The MPP[64:71] control differs from other groups */
+#define MPP64_71_GPO		MPP_GRP_NFC(0x1)
+#define MPP64_71_NFC		MPP_GRP_NFC(0x0)
+
+/*
+ * The MPP[52:57] functionality is encoded by 4 bits in different
+ * registers. The _num field in this case encodes those bits in
+ * correspodence with Table 135 of 88AP510 Functional specification
+ */
+#define MPP52_57_AU1		MPP_GRP_AU1(0x0)
+#define MPP52_57_AU1_GPIO57	MPP_GRP_AU1(0x2)
+#define MPP52_57_GPIO		MPP_GRP_AU1(0xa)
+#define MPP52_57_TW_GPIO	MPP_GRP_AU1(0xb)
+#define MPP52_57_AU1_SSP	MPP_GRP_AU1(0xc)
+#define MPP52_57_SSP_GPIO	MPP_GRP_AU1(0xe)
+#define MPP52_57_SSP_TW		MPP_GRP_AU1(0xf)
+
+void dove_mpp_conf(unsigned int *mpp_list);
+
+#endif	/* __ARCH_DOVE_MPP_CODED_H */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-ebsa110/core.c linux-libre-2.6.38-gnu1/arch/arm/mach-ebsa110/core.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-ebsa110/core.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-ebsa110/core.c	2011-03-14 21:20:32.000000000 -0400
@@ -35,20 +35,20 @@
 #define IRQ_STAT		0xff000000	/* read */
 #define IRQ_MCLR		0xff000000	/* write */
 
-static void ebsa110_mask_irq(unsigned int irq)
+static void ebsa110_mask_irq(struct irq_data *d)
 {
-	__raw_writeb(1 << irq, IRQ_MCLR);
+	__raw_writeb(1 << d->irq, IRQ_MCLR);
 }
 
-static void ebsa110_unmask_irq(unsigned int irq)
+static void ebsa110_unmask_irq(struct irq_data *d)
 {
-	__raw_writeb(1 << irq, IRQ_MSET);
+	__raw_writeb(1 << d->irq, IRQ_MSET);
 }
 
 static struct irq_chip ebsa110_irq_chip = {
-	.ack	= ebsa110_mask_irq,
-	.mask	= ebsa110_mask_irq,
-	.unmask = ebsa110_unmask_irq,
+	.irq_ack	= ebsa110_mask_irq,
+	.irq_mask	= ebsa110_mask_irq,
+	.irq_unmask	= ebsa110_unmask_irq,
 };
  
 static void __init ebsa110_init_irq(void)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-ep93xx/clock.c linux-libre-2.6.38-gnu1/arch/arm/mach-ep93xx/clock.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-ep93xx/clock.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-ep93xx/clock.c	2011-03-14 21:20:32.000000000 -0400
@@ -19,10 +19,10 @@
 #include <linux/string.h>
 #include <linux/io.h>
 #include <linux/spinlock.h>
+#include <linux/clkdev.h>
 
 #include <mach/hardware.h>
 
-#include <asm/clkdev.h>
 #include <asm/div64.h>
 
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-ep93xx/core.c linux-libre-2.6.38-gnu1/arch/arm/mach-ep93xx/core.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-ep93xx/core.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-ep93xx/core.c	2011-03-14 21:20:32.000000000 -0400
@@ -838,7 +838,7 @@ EXPORT_SYMBOL(ep93xx_i2s_release);
 static struct resource ep93xx_ac97_resources[] = {
 	{
 		.start	= EP93XX_AAC_PHYS_BASE,
-		.end	= EP93XX_AAC_PHYS_BASE + 0xb0 - 1,
+		.end	= EP93XX_AAC_PHYS_BASE + 0xac - 1,
 		.flags	= IORESOURCE_MEM,
 	},
 	{
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-ep93xx/gpio.c linux-libre-2.6.38-gnu1/arch/arm/mach-ep93xx/gpio.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-ep93xx/gpio.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-ep93xx/gpio.c	2011-03-14 21:20:32.000000000 -0400
@@ -112,13 +112,13 @@ static void ep93xx_gpio_f_irq_handler(un
 	generic_handle_irq(gpio_irq);
 }
 
-static void ep93xx_gpio_irq_ack(unsigned int irq)
+static void ep93xx_gpio_irq_ack(struct irq_data *d)
 {
-	int line = irq_to_gpio(irq);
+	int line = irq_to_gpio(d->irq);
 	int port = line >> 3;
 	int port_mask = 1 << (line & 7);
 
-	if ((irq_desc[irq].status & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH) {
+	if ((irq_desc[d->irq].status & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH) {
 		gpio_int_type2[port] ^= port_mask; /* switch edge direction */
 		ep93xx_gpio_update_int_params(port);
 	}
@@ -126,13 +126,13 @@ static void ep93xx_gpio_irq_ack(unsigned
 	__raw_writeb(port_mask, EP93XX_GPIO_REG(eoi_register_offset[port]));
 }
 
-static void ep93xx_gpio_irq_mask_ack(unsigned int irq)
+static void ep93xx_gpio_irq_mask_ack(struct irq_data *d)
 {
-	int line = irq_to_gpio(irq);
+	int line = irq_to_gpio(d->irq);
 	int port = line >> 3;
 	int port_mask = 1 << (line & 7);
 
-	if ((irq_desc[irq].status & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH)
+	if ((irq_desc[d->irq].status & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH)
 		gpio_int_type2[port] ^= port_mask; /* switch edge direction */
 
 	gpio_int_unmasked[port] &= ~port_mask;
@@ -141,18 +141,18 @@ static void ep93xx_gpio_irq_mask_ack(uns
 	__raw_writeb(port_mask, EP93XX_GPIO_REG(eoi_register_offset[port]));
 }
 
-static void ep93xx_gpio_irq_mask(unsigned int irq)
+static void ep93xx_gpio_irq_mask(struct irq_data *d)
 {
-	int line = irq_to_gpio(irq);
+	int line = irq_to_gpio(d->irq);
 	int port = line >> 3;
 
 	gpio_int_unmasked[port] &= ~(1 << (line & 7));
 	ep93xx_gpio_update_int_params(port);
 }
 
-static void ep93xx_gpio_irq_unmask(unsigned int irq)
+static void ep93xx_gpio_irq_unmask(struct irq_data *d)
 {
-	int line = irq_to_gpio(irq);
+	int line = irq_to_gpio(d->irq);
 	int port = line >> 3;
 
 	gpio_int_unmasked[port] |= 1 << (line & 7);
@@ -164,10 +164,10 @@ static void ep93xx_gpio_irq_unmask(unsig
  * edge (1) triggered, while gpio_int_type2 controls whether it
  * triggers on low/falling (0) or high/rising (1).
  */
-static int ep93xx_gpio_irq_type(unsigned int irq, unsigned int type)
+static int ep93xx_gpio_irq_type(struct irq_data *d, unsigned int type)
 {
-	struct irq_desc *desc = irq_desc + irq;
-	const int gpio = irq_to_gpio(irq);
+	struct irq_desc *desc = irq_desc + d->irq;
+	const int gpio = irq_to_gpio(d->irq);
 	const int port = gpio >> 3;
 	const int port_mask = 1 << (gpio & 7);
 
@@ -220,11 +220,11 @@ static int ep93xx_gpio_irq_type(unsigned
 
 static struct irq_chip ep93xx_gpio_irq_chip = {
 	.name		= "GPIO",
-	.ack		= ep93xx_gpio_irq_ack,
-	.mask_ack	= ep93xx_gpio_irq_mask_ack,
-	.mask		= ep93xx_gpio_irq_mask,
-	.unmask		= ep93xx_gpio_irq_unmask,
-	.set_type	= ep93xx_gpio_irq_type,
+	.irq_ack	= ep93xx_gpio_irq_ack,
+	.irq_mask_ack	= ep93xx_gpio_irq_mask_ack,
+	.irq_mask	= ep93xx_gpio_irq_mask,
+	.irq_unmask	= ep93xx_gpio_irq_unmask,
+	.irq_set_type	= ep93xx_gpio_irq_type,
 };
 
 void __init ep93xx_gpio_init_irq(void)
@@ -427,6 +427,13 @@ void __init ep93xx_gpio_init(void)
 {
 	int i;
 
+	/* Set Ports C, D, E, G, and H for GPIO use */
+	ep93xx_devcfg_set_bits(EP93XX_SYSCON_DEVCFG_KEYS |
+				 EP93XX_SYSCON_DEVCFG_GONK |
+				 EP93XX_SYSCON_DEVCFG_EONIDE |
+				 EP93XX_SYSCON_DEVCFG_GONIDE |
+				 EP93XX_SYSCON_DEVCFG_HONIDE);
+
 	for (i = 0; i < ARRAY_SIZE(ep93xx_gpio_banks); i++)
 		gpiochip_add(&ep93xx_gpio_banks[i].chip);
 }
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-footbridge/common.c linux-libre-2.6.38-gnu1/arch/arm/mach-footbridge/common.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-footbridge/common.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-footbridge/common.c	2011-03-14 21:20:32.000000000 -0400
@@ -75,20 +75,20 @@ static const int fb_irq_mask[] = {
 	IRQ_MASK_PCI_PERR,	/* 19 */
 };
 
-static void fb_mask_irq(unsigned int irq)
+static void fb_mask_irq(struct irq_data *d)
 {
-	*CSR_IRQ_DISABLE = fb_irq_mask[_DC21285_INR(irq)];
+	*CSR_IRQ_DISABLE = fb_irq_mask[_DC21285_INR(d->irq)];
 }
 
-static void fb_unmask_irq(unsigned int irq)
+static void fb_unmask_irq(struct irq_data *d)
 {
-	*CSR_IRQ_ENABLE = fb_irq_mask[_DC21285_INR(irq)];
+	*CSR_IRQ_ENABLE = fb_irq_mask[_DC21285_INR(d->irq)];
 }
 
 static struct irq_chip fb_chip = {
-	.ack	= fb_mask_irq,
-	.mask	= fb_mask_irq,
-	.unmask = fb_unmask_irq,
+	.irq_ack	= fb_mask_irq,
+	.irq_mask	= fb_mask_irq,
+	.irq_unmask	= fb_unmask_irq,
 };
 
 static void __init __fb_init_irq(void)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-footbridge/include/mach/debug-macro.S linux-libre-2.6.38-gnu1/arch/arm/mach-footbridge/include/mach/debug-macro.S
--- linux-libre-2.6.37-gnu1/arch/arm/mach-footbridge/include/mach/debug-macro.S	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-footbridge/include/mach/debug-macro.S	2011-03-14 21:20:32.000000000 -0400
@@ -17,8 +17,8 @@
 	/* For NetWinder debugging */
 		.macro	addruart, rp, rv
 		mov	\rp, #0x000003f8
-		orr	\rv, \rp, #0x7c000000	@ physical
-		orr	\rp, \rp, #0xff000000	@ virtual
+		orr	\rv, \rp, #0xff000000	@ virtual
+		orr	\rp, \rp, #0x7c000000	@ physical
 		.endm
 
 #define UART_SHIFT	0
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-footbridge/isa-irq.c linux-libre-2.6.38-gnu1/arch/arm/mach-footbridge/isa-irq.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-footbridge/isa-irq.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-footbridge/isa-irq.c	2011-03-14 21:20:32.000000000 -0400
@@ -30,61 +30,61 @@
 
 #include "common.h"
 
-static void isa_mask_pic_lo_irq(unsigned int irq)
+static void isa_mask_pic_lo_irq(struct irq_data *d)
 {
-	unsigned int mask = 1 << (irq & 7);
+	unsigned int mask = 1 << (d->irq & 7);
 
 	outb(inb(PIC_MASK_LO) | mask, PIC_MASK_LO);
 }
 
-static void isa_ack_pic_lo_irq(unsigned int irq)
+static void isa_ack_pic_lo_irq(struct irq_data *d)
 {
-	unsigned int mask = 1 << (irq & 7);
+	unsigned int mask = 1 << (d->irq & 7);
 
 	outb(inb(PIC_MASK_LO) | mask, PIC_MASK_LO);
 	outb(0x20, PIC_LO);
 }
 
-static void isa_unmask_pic_lo_irq(unsigned int irq)
+static void isa_unmask_pic_lo_irq(struct irq_data *d)
 {
-	unsigned int mask = 1 << (irq & 7);
+	unsigned int mask = 1 << (d->irq & 7);
 
 	outb(inb(PIC_MASK_LO) & ~mask, PIC_MASK_LO);
 }
 
 static struct irq_chip isa_lo_chip = {
-	.ack	= isa_ack_pic_lo_irq,
-	.mask	= isa_mask_pic_lo_irq,
-	.unmask = isa_unmask_pic_lo_irq,
+	.irq_ack	= isa_ack_pic_lo_irq,
+	.irq_mask	= isa_mask_pic_lo_irq,
+	.irq_unmask	= isa_unmask_pic_lo_irq,
 };
 
-static void isa_mask_pic_hi_irq(unsigned int irq)
+static void isa_mask_pic_hi_irq(struct irq_data *d)
 {
-	unsigned int mask = 1 << (irq & 7);
+	unsigned int mask = 1 << (d->irq & 7);
 
 	outb(inb(PIC_MASK_HI) | mask, PIC_MASK_HI);
 }
 
-static void isa_ack_pic_hi_irq(unsigned int irq)
+static void isa_ack_pic_hi_irq(struct irq_data *d)
 {
-	unsigned int mask = 1 << (irq & 7);
+	unsigned int mask = 1 << (d->irq & 7);
 
 	outb(inb(PIC_MASK_HI) | mask, PIC_MASK_HI);
 	outb(0x62, PIC_LO);
 	outb(0x20, PIC_HI);
 }
 
-static void isa_unmask_pic_hi_irq(unsigned int irq)
+static void isa_unmask_pic_hi_irq(struct irq_data *d)
 {
-	unsigned int mask = 1 << (irq & 7);
+	unsigned int mask = 1 << (d->irq & 7);
 
 	outb(inb(PIC_MASK_HI) & ~mask, PIC_MASK_HI);
 }
 
 static struct irq_chip isa_hi_chip = {
-	.ack	= isa_ack_pic_hi_irq,
-	.mask	= isa_mask_pic_hi_irq,
-	.unmask = isa_unmask_pic_hi_irq,
+	.irq_ack	= isa_ack_pic_hi_irq,
+	.irq_mask	= isa_mask_pic_hi_irq,
+	.irq_unmask	= isa_unmask_pic_hi_irq,
 };
 
 static void
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-gemini/gpio.c linux-libre-2.6.38-gnu1/arch/arm/mach-gemini/gpio.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-gemini/gpio.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-gemini/gpio.c	2011-03-14 21:20:32.000000000 -0400
@@ -54,33 +54,33 @@ static void _set_gpio_irqenable(unsigned
 	__raw_writel(reg, base + GPIO_INT_EN);
 }
 
-static void gpio_ack_irq(unsigned int irq)
+static void gpio_ack_irq(struct irq_data *d)
 {
-	unsigned int gpio = irq_to_gpio(irq);
+	unsigned int gpio = irq_to_gpio(d->irq);
 	unsigned int base = GPIO_BASE(gpio / 32);
 
 	__raw_writel(1 << (gpio % 32), base + GPIO_INT_CLR);
 }
 
-static void gpio_mask_irq(unsigned int irq)
+static void gpio_mask_irq(struct irq_data *d)
 {
-	unsigned int gpio = irq_to_gpio(irq);
+	unsigned int gpio = irq_to_gpio(d->irq);
 	unsigned int base = GPIO_BASE(gpio / 32);
 
 	_set_gpio_irqenable(base, gpio % 32, 0);
 }
 
-static void gpio_unmask_irq(unsigned int irq)
+static void gpio_unmask_irq(struct irq_data *d)
 {
-	unsigned int gpio = irq_to_gpio(irq);
+	unsigned int gpio = irq_to_gpio(d->irq);
 	unsigned int base = GPIO_BASE(gpio / 32);
 
 	_set_gpio_irqenable(base, gpio % 32, 1);
 }
 
-static int gpio_set_irq_type(unsigned int irq, unsigned int type)
+static int gpio_set_irq_type(struct irq_data *d, unsigned int type)
 {
-	unsigned int gpio = irq_to_gpio(irq);
+	unsigned int gpio = irq_to_gpio(d->irq);
 	unsigned int gpio_mask = 1 << (gpio % 32);
 	unsigned int base = GPIO_BASE(gpio / 32);
 	unsigned int reg_both, reg_level, reg_type;
@@ -120,7 +120,7 @@ static int gpio_set_irq_type(unsigned in
 	__raw_writel(reg_level, base + GPIO_INT_LEVEL);
 	__raw_writel(reg_both, base + GPIO_INT_BOTH_EDGE);
 
-	gpio_ack_irq(irq);
+	gpio_ack_irq(d->irq);
 
 	return 0;
 }
@@ -146,10 +146,10 @@ static void gpio_irq_handler(unsigned in
 
 static struct irq_chip gpio_irq_chip = {
 	.name = "GPIO",
-	.ack = gpio_ack_irq,
-	.mask = gpio_mask_irq,
-	.unmask = gpio_unmask_irq,
-	.set_type = gpio_set_irq_type,
+	.irq_ack = gpio_ack_irq,
+	.irq_mask = gpio_mask_irq,
+	.irq_unmask = gpio_unmask_irq,
+	.irq_set_type = gpio_set_irq_type,
 };
 
 static void _set_gpio_direction(struct gpio_chip *chip, unsigned offset,
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-gemini/include/mach/hardware.h linux-libre-2.6.38-gnu1/arch/arm/mach-gemini/include/mach/hardware.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-gemini/include/mach/hardware.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-gemini/include/mach/hardware.h	2011-03-14 21:20:32.000000000 -0400
@@ -33,7 +33,7 @@
 #define GEMINI_LPC_HOST_BASE	0x47000000
 #define GEMINI_LPC_IO_BASE	0x47800000
 #define GEMINI_INTERRUPT_BASE	0x48000000
-/* TODO: Different interrupt controlers when SMP
+/* TODO: Different interrupt controllers when SMP
  * #define GEMINI_INTERRUPT0_BASE	0x48000000
  * #define GEMINI_INTERRUPT1_BASE	0x49000000
  */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-gemini/irq.c linux-libre-2.6.38-gnu1/arch/arm/mach-gemini/irq.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-gemini/irq.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-gemini/irq.c	2011-03-14 21:20:32.000000000 -0400
@@ -32,34 +32,34 @@
 #define FIQ_LEVEL(base_addr)	(base_addr + 0x30)
 #define FIQ_STATUS(base_addr)	(base_addr + 0x34)
 
-static void gemini_ack_irq(unsigned int irq)
+static void gemini_ack_irq(struct irq_data *d)
 {
-	__raw_writel(1 << irq, IRQ_CLEAR(IO_ADDRESS(GEMINI_INTERRUPT_BASE)));
+	__raw_writel(1 << d->irq, IRQ_CLEAR(IO_ADDRESS(GEMINI_INTERRUPT_BASE)));
 }
 
-static void gemini_mask_irq(unsigned int irq)
+static void gemini_mask_irq(struct irq_data *d)
 {
 	unsigned int mask;
 
 	mask = __raw_readl(IRQ_MASK(IO_ADDRESS(GEMINI_INTERRUPT_BASE)));
-	mask &= ~(1 << irq);
+	mask &= ~(1 << d->irq);
 	__raw_writel(mask, IRQ_MASK(IO_ADDRESS(GEMINI_INTERRUPT_BASE)));
 }
 
-static void gemini_unmask_irq(unsigned int irq)
+static void gemini_unmask_irq(struct irq_data *d)
 {
 	unsigned int mask;
 
 	mask = __raw_readl(IRQ_MASK(IO_ADDRESS(GEMINI_INTERRUPT_BASE)));
-	mask |= (1 << irq);
+	mask |= (1 << d->irq);
 	__raw_writel(mask, IRQ_MASK(IO_ADDRESS(GEMINI_INTERRUPT_BASE)));
 }
 
 static struct irq_chip gemini_irq_chip = {
-	.name	= "INTC",
-	.ack	= gemini_ack_irq,
-	.mask	= gemini_mask_irq,
-	.unmask	= gemini_unmask_irq,
+	.name		= "INTC",
+	.irq_ack	= gemini_ack_irq,
+	.irq_mask	= gemini_mask_irq,
+	.irq_unmask	= gemini_unmask_irq,
 };
 
 static struct resource irq_resource = {
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-h720x/common.c linux-libre-2.6.38-gnu1/arch/arm/mach-h720x/common.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-h720x/common.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-h720x/common.c	2011-03-14 21:20:32.000000000 -0400
@@ -52,17 +52,17 @@ unsigned long h720x_gettimeoffset(void)
 /*
  * mask Global irq's
  */
-static void mask_global_irq (unsigned int irq )
+static void mask_global_irq(struct irq_data *d)
 {
-	CPU_REG (IRQC_VIRT, IRQC_IER) &= ~(1 << irq);
+	CPU_REG (IRQC_VIRT, IRQC_IER) &= ~(1 << d->irq);
 }
 
 /*
  * unmask Global irq's
  */
-static void unmask_global_irq (unsigned int irq )
+static void unmask_global_irq(struct irq_data *d)
 {
-	CPU_REG (IRQC_VIRT, IRQC_IER) |= (1 << irq);
+	CPU_REG (IRQC_VIRT, IRQC_IER) |= (1 << d->irq);
 }
 
 
@@ -70,10 +70,10 @@ static void unmask_global_irq (unsigned
  * ack GPIO irq's
  * Ack only for edge triggered int's valid
  */
-static void inline ack_gpio_irq(u32 irq)
+static void inline ack_gpio_irq(struct irq_data *d)
 {
-	u32 reg_base = GPIO_VIRT(IRQ_TO_REGNO(irq));
-	u32 bit = IRQ_TO_BIT(irq);
+	u32 reg_base = GPIO_VIRT(IRQ_TO_REGNO(d->irq));
+	u32 bit = IRQ_TO_BIT(d->irq);
 	if ( (CPU_REG (reg_base, GPIO_EDGE) & bit))
 		CPU_REG (reg_base, GPIO_CLR) = bit;
 }
@@ -81,20 +81,20 @@ static void inline ack_gpio_irq(u32 irq)
 /*
  * mask GPIO irq's
  */
-static void inline mask_gpio_irq(u32 irq)
+static void inline mask_gpio_irq(struct irq_data *d)
 {
-	u32 reg_base = GPIO_VIRT(IRQ_TO_REGNO(irq));
-	u32 bit = IRQ_TO_BIT(irq);
+	u32 reg_base = GPIO_VIRT(IRQ_TO_REGNO(d->irq));
+	u32 bit = IRQ_TO_BIT(d->irq);
 	CPU_REG (reg_base, GPIO_MASK) &= ~bit;
 }
 
 /*
  * unmask GPIO irq's
  */
-static void inline unmask_gpio_irq(u32 irq)
+static void inline unmask_gpio_irq(struct irq_data *d)
 {
-	u32 reg_base = GPIO_VIRT(IRQ_TO_REGNO(irq));
-	u32 bit = IRQ_TO_BIT(irq);
+	u32 reg_base = GPIO_VIRT(IRQ_TO_REGNO(d->irq));
+	u32 bit = IRQ_TO_BIT(d->irq);
 	CPU_REG (reg_base, GPIO_MASK) |= bit;
 }
 
@@ -170,15 +170,15 @@ h720x_gpioe_demux_handler(unsigned int i
 #endif
 
 static struct irq_chip h720x_global_chip = {
-	.ack = mask_global_irq,
-	.mask = mask_global_irq,
-	.unmask = unmask_global_irq,
+	.irq_ack = mask_global_irq,
+	.irq_mask = mask_global_irq,
+	.irq_unmask = unmask_global_irq,
 };
 
 static struct irq_chip h720x_gpio_chip = {
-	.ack = ack_gpio_irq,
-	.mask = mask_gpio_irq,
-	.unmask = unmask_gpio_irq,
+	.irq_ack = ack_gpio_irq,
+	.irq_mask = mask_gpio_irq,
+	.irq_unmask = unmask_gpio_irq,
 };
 
 /*
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-h720x/cpu-h7202.c linux-libre-2.6.38-gnu1/arch/arm/mach-h720x/cpu-h7202.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-h720x/cpu-h7202.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-h720x/cpu-h7202.c	2011-03-14 21:20:32.000000000 -0400
@@ -141,27 +141,27 @@ h7202_timer_interrupt(int irq, void *dev
 /*
  * mask multiplexed timer IRQs
  */
-static void inline mask_timerx_irq (u32 irq)
+static void inline mask_timerx_irq(struct irq_data *d)
 {
 	unsigned int bit;
-	bit = 2 << ((irq == IRQ_TIMER64B) ? 4 : (irq - IRQ_TIMER1));
+	bit = 2 << ((d->irq == IRQ_TIMER64B) ? 4 : (d->irq - IRQ_TIMER1));
 	CPU_REG (TIMER_VIRT, TIMER_TOPCTRL) &= ~bit;
 }
 
 /*
  * unmask multiplexed timer IRQs
  */
-static void inline unmask_timerx_irq (u32 irq)
+static void inline unmask_timerx_irq(struct irq_data *d)
 {
 	unsigned int bit;
-	bit = 2 << ((irq == IRQ_TIMER64B) ? 4 : (irq - IRQ_TIMER1));
+	bit = 2 << ((d->irq == IRQ_TIMER64B) ? 4 : (d->irq - IRQ_TIMER1));
 	CPU_REG (TIMER_VIRT, TIMER_TOPCTRL) |= bit;
 }
 
 static struct irq_chip h7202_timerx_chip = {
-	.ack = mask_timerx_irq,
-	.mask = mask_timerx_irq,
-	.unmask = unmask_timerx_irq,
+	.irq_ack = mask_timerx_irq,
+	.irq_mask = mask_timerx_irq,
+	.irq_unmask = unmask_timerx_irq,
 };
 
 static struct irqaction h7202_timer_irq = {
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-h720x/h7201-eval.c linux-libre-2.6.38-gnu1/arch/arm/mach-h720x/h7201-eval.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-h720x/h7201-eval.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-h720x/h7201-eval.c	2011-03-14 21:20:32.000000000 -0400
@@ -23,7 +23,6 @@
 #include <asm/types.h>
 #include <asm/mach-types.h>
 #include <asm/page.h>
-#include <asm/pgtable.h>
 #include <asm/mach/arch.h>
 #include <mach/hardware.h>
 #include "common.h"
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-h720x/h7202-eval.c linux-libre-2.6.38-gnu1/arch/arm/mach-h720x/h7202-eval.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-h720x/h7202-eval.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-h720x/h7202-eval.c	2011-03-14 21:20:32.000000000 -0400
@@ -23,7 +23,6 @@
 #include <asm/types.h>
 #include <asm/mach-types.h>
 #include <asm/page.h>
-#include <asm/pgtable.h>
 #include <asm/mach/arch.h>
 #include <mach/irqs.h>
 #include <mach/hardware.h>
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-imx/clock-imx1.c linux-libre-2.6.38-gnu1/arch/arm/mach-imx/clock-imx1.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-imx/clock-imx1.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-imx/clock-imx1.c	2011-03-14 21:20:32.000000000 -0400
@@ -22,8 +22,7 @@
 #include <linux/err.h>
 #include <linux/clk.h>
 #include <linux/io.h>
-
-#include <asm/clkdev.h>
+#include <linux/clkdev.h>
 
 #include <mach/clock.h>
 #include <mach/hardware.h>
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-imx/clock-imx21.c linux-libre-2.6.38-gnu1/arch/arm/mach-imx/clock-imx21.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-imx/clock-imx21.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-imx/clock-imx21.c	2011-03-14 21:20:32.000000000 -0400
@@ -21,11 +21,11 @@
 #include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/module.h>
+#include <linux/clkdev.h>
 
 #include <mach/clock.h>
 #include <mach/hardware.h>
 #include <mach/common.h>
-#include <asm/clkdev.h>
 #include <asm/div64.h>
 
 #define IO_ADDR_CCM(off)	(MX21_IO_ADDRESS(MX21_CCM_BASE_ADDR + (off)))
@@ -1185,7 +1185,7 @@ static struct clk_lookup lookups[] = {
 	_REGISTER_CLOCK(NULL, "brom", brom_clk)
 	_REGISTER_CLOCK(NULL, "emma", emma_clk[0])
 	_REGISTER_CLOCK(NULL, "slcdc", slcdc_clk[0])
-	_REGISTER_CLOCK("imx-wdt.0", NULL, wdog_clk)
+	_REGISTER_CLOCK("imx2-wdt.0", NULL, wdog_clk)
 	_REGISTER_CLOCK(NULL, "gpio", gpio_clk)
 	_REGISTER_CLOCK("imx-i2c.0", NULL, i2c_clk)
 	_REGISTER_CLOCK("mxc-keypad", NULL, kpp_clk)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-imx/clock-imx25.c linux-libre-2.6.38-gnu1/arch/arm/mach-imx/clock-imx25.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-imx/clock-imx25.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-imx/clock-imx25.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,331 @@
+/*
+ * Copyright (C) 2009 by Sascha Hauer, Pengutronix
+ *
+ * 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/kernel.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/clkdev.h>
+
+#include <mach/clock.h>
+#include <mach/hardware.h>
+#include <mach/common.h>
+#include <mach/mx25.h>
+
+#define CRM_BASE	MX25_IO_ADDRESS(MX25_CRM_BASE_ADDR)
+
+#define CCM_MPCTL	0x00
+#define CCM_UPCTL	0x04
+#define CCM_CCTL	0x08
+#define CCM_CGCR0	0x0C
+#define CCM_CGCR1	0x10
+#define CCM_CGCR2	0x14
+#define CCM_PCDR0	0x18
+#define CCM_PCDR1	0x1C
+#define CCM_PCDR2	0x20
+#define CCM_PCDR3	0x24
+#define CCM_RCSR	0x28
+#define CCM_CRDR	0x2C
+#define CCM_DCVR0	0x30
+#define CCM_DCVR1	0x34
+#define CCM_DCVR2	0x38
+#define CCM_DCVR3	0x3c
+#define CCM_LTR0	0x40
+#define CCM_LTR1	0x44
+#define CCM_LTR2	0x48
+#define CCM_LTR3	0x4c
+
+static unsigned long get_rate_mpll(void)
+{
+	ulong mpctl = __raw_readl(CRM_BASE + CCM_MPCTL);
+
+	return mxc_decode_pll(mpctl, 24000000);
+}
+
+static unsigned long get_rate_upll(void)
+{
+	ulong mpctl = __raw_readl(CRM_BASE + CCM_UPCTL);
+
+	return mxc_decode_pll(mpctl, 24000000);
+}
+
+unsigned long get_rate_arm(struct clk *clk)
+{
+	unsigned long cctl = readl(CRM_BASE + CCM_CCTL);
+	unsigned long rate = get_rate_mpll();
+
+	if (cctl & (1 << 14))
+		rate = (rate * 3) >> 2;
+
+	return rate / ((cctl >> 30) + 1);
+}
+
+static unsigned long get_rate_ahb(struct clk *clk)
+{
+	unsigned long cctl = readl(CRM_BASE + CCM_CCTL);
+
+	return get_rate_arm(NULL) / (((cctl >> 28) & 0x3) + 1);
+}
+
+static unsigned long get_rate_ipg(struct clk *clk)
+{
+	return get_rate_ahb(NULL) >> 1;
+}
+
+static unsigned long get_rate_per(int per)
+{
+	unsigned long ofs = (per & 0x3) * 8;
+	unsigned long reg = per & ~0x3;
+	unsigned long val = (readl(CRM_BASE + CCM_PCDR0 + reg) >> ofs) & 0x3f;
+	unsigned long fref;
+
+	if (readl(CRM_BASE + 0x64) & (1 << per))
+		fref = get_rate_upll();
+	else
+		fref = get_rate_ahb(NULL);
+
+	return fref / (val + 1);
+}
+
+static unsigned long get_rate_uart(struct clk *clk)
+{
+	return get_rate_per(15);
+}
+
+static unsigned long get_rate_ssi2(struct clk *clk)
+{
+	return get_rate_per(14);
+}
+
+static unsigned long get_rate_ssi1(struct clk *clk)
+{
+	return get_rate_per(13);
+}
+
+static unsigned long get_rate_i2c(struct clk *clk)
+{
+	return get_rate_per(6);
+}
+
+static unsigned long get_rate_nfc(struct clk *clk)
+{
+	return get_rate_per(8);
+}
+
+static unsigned long get_rate_gpt(struct clk *clk)
+{
+	return get_rate_per(5);
+}
+
+static unsigned long get_rate_lcdc(struct clk *clk)
+{
+	return get_rate_per(7);
+}
+
+static unsigned long get_rate_esdhc1(struct clk *clk)
+{
+	return get_rate_per(3);
+}
+
+static unsigned long get_rate_esdhc2(struct clk *clk)
+{
+	return get_rate_per(4);
+}
+
+static unsigned long get_rate_csi(struct clk *clk)
+{
+	return get_rate_per(0);
+}
+
+static unsigned long get_rate_otg(struct clk *clk)
+{
+	unsigned long cctl = readl(CRM_BASE + CCM_CCTL);
+	unsigned long rate = get_rate_upll();
+
+	return (cctl & (1 << 23)) ? 0 : rate / ((0x3F & (cctl >> 16)) + 1);
+}
+
+static int clk_cgcr_enable(struct clk *clk)
+{
+	u32 reg;
+
+	reg = __raw_readl(clk->enable_reg);
+	reg |= 1 << clk->enable_shift;
+	__raw_writel(reg, clk->enable_reg);
+
+	return 0;
+}
+
+static void clk_cgcr_disable(struct clk *clk)
+{
+	u32 reg;
+
+	reg = __raw_readl(clk->enable_reg);
+	reg &= ~(1 << clk->enable_shift);
+	__raw_writel(reg, clk->enable_reg);
+}
+
+#define DEFINE_CLOCK(name, i, er, es, gr, sr, s)	\
+	static struct clk name = {			\
+		.id		= i,			\
+		.enable_reg	= CRM_BASE + er,	\
+		.enable_shift	= es,			\
+		.get_rate	= gr,			\
+		.set_rate	= sr,			\
+		.enable		= clk_cgcr_enable,	\
+		.disable	= clk_cgcr_disable,	\
+		.secondary	= s,			\
+	}
+
+/*
+ * Note: the following IPG clock gating bits are wrongly marked "Reserved" in
+ * the i.MX25 Reference Manual Rev 1, table 15-13. The information below is
+ * taken from the Freescale released BSP.
+ *
+ * bit	reg	offset	clock
+ *
+ * 0	CGCR1	0	AUDMUX
+ * 12	CGCR1	12	ESAI
+ * 16	CGCR1	16	GPIO1
+ * 17	CGCR1	17	GPIO2
+ * 18	CGCR1	18	GPIO3
+ * 23	CGCR1	23	I2C1
+ * 24	CGCR1	24	I2C2
+ * 25	CGCR1	25	I2C3
+ * 27	CGCR1	27	IOMUXC
+ * 28	CGCR1	28	KPP
+ * 30	CGCR1	30	OWIRE
+ * 36	CGCR2	4	RTIC
+ * 51	CGCR2	19	WDOG
+ */
+
+DEFINE_CLOCK(gpt_clk,    0, CCM_CGCR0,  5, get_rate_gpt, NULL, NULL);
+DEFINE_CLOCK(uart_per_clk, 0, CCM_CGCR0, 15, get_rate_uart, NULL, NULL);
+DEFINE_CLOCK(ssi1_per_clk, 0, CCM_CGCR0, 13, get_rate_ipg, NULL, NULL);
+DEFINE_CLOCK(ssi2_per_clk, 0, CCM_CGCR0, 14, get_rate_ipg, NULL, NULL);
+DEFINE_CLOCK(cspi1_clk,  0, CCM_CGCR1,  5, get_rate_ipg, NULL, NULL);
+DEFINE_CLOCK(cspi2_clk,  0, CCM_CGCR1,  6, get_rate_ipg, NULL, NULL);
+DEFINE_CLOCK(cspi3_clk,  0, CCM_CGCR1,  7, get_rate_ipg, NULL, NULL);
+DEFINE_CLOCK(esdhc1_ahb_clk, 0, CCM_CGCR0, 21, get_rate_esdhc1,	 NULL, NULL);
+DEFINE_CLOCK(esdhc1_per_clk, 0, CCM_CGCR0,  3, get_rate_esdhc1,	 NULL,
+		&esdhc1_ahb_clk);
+DEFINE_CLOCK(esdhc2_ahb_clk, 0, CCM_CGCR0, 22, get_rate_esdhc2,	 NULL, NULL);
+DEFINE_CLOCK(esdhc2_per_clk, 0, CCM_CGCR0,  4, get_rate_esdhc2,	 NULL,
+		&esdhc2_ahb_clk);
+DEFINE_CLOCK(fec_ahb_clk, 0, CCM_CGCR0, 23, NULL,	 NULL, NULL);
+DEFINE_CLOCK(lcdc_ahb_clk, 0, CCM_CGCR0, 24, NULL,	 NULL, NULL);
+DEFINE_CLOCK(lcdc_per_clk, 0, CCM_CGCR0,  7, NULL,	 NULL, &lcdc_ahb_clk);
+DEFINE_CLOCK(csi_ahb_clk, 0, CCM_CGCR0, 18, get_rate_csi, NULL, NULL);
+DEFINE_CLOCK(csi_per_clk, 0, CCM_CGCR0, 0, get_rate_csi, NULL, &csi_ahb_clk);
+DEFINE_CLOCK(uart1_clk,  0, CCM_CGCR2, 14, get_rate_uart, NULL, &uart_per_clk);
+DEFINE_CLOCK(uart2_clk,  0, CCM_CGCR2, 15, get_rate_uart, NULL, &uart_per_clk);
+DEFINE_CLOCK(uart3_clk,  0, CCM_CGCR2, 16, get_rate_uart, NULL, &uart_per_clk);
+DEFINE_CLOCK(uart4_clk,  0, CCM_CGCR2, 17, get_rate_uart, NULL, &uart_per_clk);
+DEFINE_CLOCK(uart5_clk,  0, CCM_CGCR2, 18, get_rate_uart, NULL, &uart_per_clk);
+DEFINE_CLOCK(nfc_clk,    0, CCM_CGCR0,  8, get_rate_nfc, NULL, NULL);
+DEFINE_CLOCK(usbotg_clk, 0, CCM_CGCR0, 28, get_rate_otg, NULL, NULL);
+DEFINE_CLOCK(pwm1_clk,	 0, CCM_CGCR1, 31, get_rate_ipg, NULL, NULL);
+DEFINE_CLOCK(pwm2_clk,	 0, CCM_CGCR2,  0, get_rate_ipg, NULL, NULL);
+DEFINE_CLOCK(pwm3_clk,	 0, CCM_CGCR2,  1, get_rate_ipg, NULL, NULL);
+DEFINE_CLOCK(pwm4_clk,	 0, CCM_CGCR2,  2, get_rate_ipg, NULL, NULL);
+DEFINE_CLOCK(kpp_clk,	 0, CCM_CGCR1, 28, get_rate_ipg, NULL, NULL);
+DEFINE_CLOCK(tsc_clk,	 0, CCM_CGCR2, 13, get_rate_ipg, NULL, NULL);
+DEFINE_CLOCK(i2c_clk,	 0, CCM_CGCR0,  6, get_rate_i2c, NULL, NULL);
+DEFINE_CLOCK(fec_clk,	 0, CCM_CGCR1, 15, get_rate_ipg, NULL, &fec_ahb_clk);
+DEFINE_CLOCK(dryice_clk, 0, CCM_CGCR1,  8, get_rate_ipg, NULL, NULL);
+DEFINE_CLOCK(lcdc_clk,	 0, CCM_CGCR1, 29, get_rate_lcdc, NULL, &lcdc_per_clk);
+DEFINE_CLOCK(wdt_clk,    0, CCM_CGCR2, 19, get_rate_ipg, NULL,  NULL);
+DEFINE_CLOCK(ssi1_clk,  0, CCM_CGCR2, 11, get_rate_ssi1, NULL, &ssi1_per_clk);
+DEFINE_CLOCK(ssi2_clk,  1, CCM_CGCR2, 12, get_rate_ssi2, NULL, &ssi2_per_clk);
+DEFINE_CLOCK(esdhc1_clk,  0, CCM_CGCR1, 13, get_rate_esdhc1, NULL,
+		&esdhc1_per_clk);
+DEFINE_CLOCK(esdhc2_clk,  1, CCM_CGCR1, 14, get_rate_esdhc2, NULL,
+		&esdhc2_per_clk);
+DEFINE_CLOCK(audmux_clk, 0, CCM_CGCR1, 0, NULL, NULL, NULL);
+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 _REGISTER_CLOCK(d, n, c)	\
+	{				\
+		.dev_id = d,		\
+		.con_id = n,		\
+		.clk = &c,		\
+	},
+
+static struct clk_lookup lookups[] = {
+	_REGISTER_CLOCK("imx-uart.0", NULL, uart1_clk)
+	_REGISTER_CLOCK("imx-uart.1", NULL, uart2_clk)
+	_REGISTER_CLOCK("imx-uart.2", NULL, uart3_clk)
+	_REGISTER_CLOCK("imx-uart.3", NULL, uart4_clk)
+	_REGISTER_CLOCK("imx-uart.4", NULL, uart5_clk)
+	_REGISTER_CLOCK("mxc-ehci.0", "usb", usbotg_clk)
+	_REGISTER_CLOCK("mxc-ehci.1", "usb", usbotg_clk)
+	_REGISTER_CLOCK("mxc-ehci.2", "usb", usbotg_clk)
+	_REGISTER_CLOCK("fsl-usb2-udc", "usb", usbotg_clk)
+	_REGISTER_CLOCK("mxc_nand.0", NULL, nfc_clk)
+	_REGISTER_CLOCK("imx25-cspi.0", NULL, cspi1_clk)
+	_REGISTER_CLOCK("imx25-cspi.1", NULL, cspi2_clk)
+	_REGISTER_CLOCK("imx25-cspi.2", NULL, cspi3_clk)
+	_REGISTER_CLOCK("mxc_pwm.0", NULL, pwm1_clk)
+	_REGISTER_CLOCK("mxc_pwm.1", NULL, pwm2_clk)
+	_REGISTER_CLOCK("mxc_pwm.2", NULL, pwm3_clk)
+	_REGISTER_CLOCK("mxc_pwm.3", NULL, pwm4_clk)
+	_REGISTER_CLOCK("imx-keypad", NULL, kpp_clk)
+	_REGISTER_CLOCK("mx25-adc", NULL, tsc_clk)
+	_REGISTER_CLOCK("imx-i2c.0", NULL, i2c_clk)
+	_REGISTER_CLOCK("imx-i2c.1", NULL, i2c_clk)
+	_REGISTER_CLOCK("imx-i2c.2", NULL, i2c_clk)
+	_REGISTER_CLOCK("fec.0", NULL, fec_clk)
+	_REGISTER_CLOCK("imxdi_rtc.0", NULL, dryice_clk)
+	_REGISTER_CLOCK("imx-fb.0", NULL, lcdc_clk)
+	_REGISTER_CLOCK("imx2-wdt.0", NULL, wdt_clk)
+	_REGISTER_CLOCK("imx-ssi.0", NULL, ssi1_clk)
+	_REGISTER_CLOCK("imx-ssi.1", NULL, ssi2_clk)
+	_REGISTER_CLOCK("sdhci-esdhc-imx.0", NULL, esdhc1_clk)
+	_REGISTER_CLOCK("sdhci-esdhc-imx.1", NULL, esdhc2_clk)
+	_REGISTER_CLOCK("mx2-camera.0", NULL, csi_clk)
+	_REGISTER_CLOCK(NULL, "audmux", audmux_clk)
+	_REGISTER_CLOCK("flexcan.0", NULL, can1_clk)
+	_REGISTER_CLOCK("flexcan.1", NULL, can2_clk)
+};
+
+int __init mx25_clocks_init(void)
+{
+	clkdev_add_table(lookups, ARRAY_SIZE(lookups));
+
+	/* Turn off all clocks except the ones we need to survive, namely:
+	 * EMI, GPIO1-3 (CCM_CGCR1[18:16]), GPT1, IOMUXC (CCM_CGCR1[27]), IIM,
+	 * SCC
+	 */
+	__raw_writel((1 << 19), CRM_BASE + CCM_CGCR0);
+	__raw_writel((0xf << 16) | (3 << 26), CRM_BASE + CCM_CGCR1);
+	__raw_writel((1 << 5), CRM_BASE + CCM_CGCR2);
+#if defined(CONFIG_DEBUG_LL) && !defined(CONFIG_DEBUG_ICEDCC)
+	clk_enable(&uart1_clk);
+#endif
+
+	/* Clock source for lcdc and csi is upll */
+	__raw_writel(__raw_readl(CRM_BASE+0x64) | (1 << 7) | (1 << 0),
+			CRM_BASE + 0x64);
+
+	mxc_timer_init(&gpt_clk, MX25_IO_ADDRESS(MX25_GPT1_BASE_ADDR), 54);
+
+	return 0;
+}
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-imx/clock-imx27.c linux-libre-2.6.38-gnu1/arch/arm/mach-imx/clock-imx27.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-imx/clock-imx27.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-imx/clock-imx27.c	2011-03-14 21:20:32.000000000 -0400
@@ -21,8 +21,8 @@
 #include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/module.h>
+#include <linux/clkdev.h>
 
-#include <asm/clkdev.h>
 #include <asm/div64.h>
 
 #include <mach/clock.h>
@@ -125,7 +125,7 @@ static int clk_cpu_set_parent(struct clk
 	if (clk->parent == parent)
 		return 0;
 
-	if (mx27_revision() >= CHIP_REV_2_0) {
+	if (mx27_revision() >= IMX_CHIP_REVISION_2_0) {
 		if (parent == &mpll_main1_clk) {
 			cscr |= CCM_CSCR_ARM_SRC;
 		} else {
@@ -174,7 +174,7 @@ static int set_rate_cpu(struct clk *clk,
 	div--;
 
 	reg = __raw_readl(CCM_CSCR);
-	if (mx27_revision() >= CHIP_REV_2_0) {
+	if (mx27_revision() >= IMX_CHIP_REVISION_2_0) {
 		reg &= ~(3 << 12);
 		reg |= div << 12;
 		reg &= ~(CCM_CSCR_FPM | CCM_CSCR_SPEN);
@@ -244,7 +244,7 @@ static unsigned long get_rate_ssix(struc
 
 	parent_rate = clk_get_rate(clk->parent);
 
-	if (mx27_revision() >= CHIP_REV_2_0)
+	if (mx27_revision() >= IMX_CHIP_REVISION_2_0)
 		pdf += 4;  /* MX27 TO2+ */
 	else
 		pdf = (pdf < 2) ? 124UL : pdf;  /* MX21 & MX27 TO1 */
@@ -269,7 +269,7 @@ static unsigned long get_rate_nfc(struct
 
 	parent_rate = clk_get_rate(clk->parent);
 
-	if (mx27_revision() >= CHIP_REV_2_0)
+	if (mx27_revision() >= IMX_CHIP_REVISION_2_0)
 		nfc_pdf = (__raw_readl(CCM_PCDR0) >> 6) & 0xf;
 	else
 		nfc_pdf = (__raw_readl(CCM_PCDR0) >> 12) & 0xf;
@@ -284,7 +284,7 @@ static unsigned long get_rate_vpu(struct
 
 	parent_rate = clk_get_rate(clk->parent);
 
-	if (mx27_revision() >= CHIP_REV_2_0) {
+	if (mx27_revision() >= IMX_CHIP_REVISION_2_0) {
 		vpu_pdf = (__raw_readl(CCM_PCDR0) >> 10) & 0x3f;
 		vpu_pdf += 4;
 	} else {
@@ -347,7 +347,7 @@ static unsigned long get_rate_mpll_main(
 	 * clk->id == 0: arm clock source path 1 which is from 2 * MPLL / 2
 	 * clk->id == 1: arm clock source path 2 which is from 2 * MPLL / 3
 	 */
-	if (mx27_revision() >= CHIP_REV_2_0 && clk->id == 1)
+	if (mx27_revision() >= IMX_CHIP_REVISION_2_0 && clk->id == 1)
 		return 2UL * parent_rate / 3UL;
 
 	return parent_rate;
@@ -365,7 +365,7 @@ static unsigned long get_rate_spll(struc
 	/* On TO2 we have to write the value back. Otherwise we
 	 * read 0 from this register the next time.
 	 */
-	if (mx27_revision() >= CHIP_REV_2_0)
+	if (mx27_revision() >= IMX_CHIP_REVISION_2_0)
 		__raw_writel(reg, CCM_SPCTL0);
 
 	return mxc_decode_pll(reg, rate);
@@ -376,7 +376,7 @@ static unsigned long get_rate_cpu(struct
 	u32 div;
 	unsigned long rate;
 
-	if (mx27_revision() >= CHIP_REV_2_0)
+	if (mx27_revision() >= IMX_CHIP_REVISION_2_0)
 		div = (__raw_readl(CCM_CSCR) >> 12) & 0x3;
 	else
 		div = (__raw_readl(CCM_CSCR) >> 13) & 0x7;
@@ -389,7 +389,7 @@ static unsigned long get_rate_ahb(struct
 {
 	unsigned long rate, bclk_pdf;
 
-	if (mx27_revision() >= CHIP_REV_2_0)
+	if (mx27_revision() >= IMX_CHIP_REVISION_2_0)
 		bclk_pdf = (__raw_readl(CCM_CSCR) >> 8) & 0x3;
 	else
 		bclk_pdf = (__raw_readl(CCM_CSCR) >> 9) & 0xf;
@@ -402,7 +402,7 @@ static unsigned long get_rate_ipg(struct
 {
 	unsigned long rate, ipg_pdf;
 
-	if (mx27_revision() >= CHIP_REV_2_0)
+	if (mx27_revision() >= IMX_CHIP_REVISION_2_0)
 		return clk_get_rate(clk->parent);
 	else
 		ipg_pdf = (__raw_readl(CCM_CSCR) >> 8) & 1;
@@ -667,7 +667,7 @@ static struct clk_lookup lookups[] = {
 	_REGISTER_CLOCK(NULL, "sahara2", sahara2_clk)
 	_REGISTER_CLOCK(NULL, "ata", ata_clk)
 	_REGISTER_CLOCK(NULL, "mstick", mstick_clk)
-	_REGISTER_CLOCK("imx-wdt.0", NULL, wdog_clk)
+	_REGISTER_CLOCK("imx2-wdt.0", NULL, wdog_clk)
 	_REGISTER_CLOCK(NULL, "gpio", gpio_clk)
 	_REGISTER_CLOCK("imx-i2c.0", NULL, i2c1_clk)
 	_REGISTER_CLOCK("imx-i2c.1", NULL, i2c2_clk)
@@ -683,7 +683,7 @@ static void __init to2_adjust_clocks(voi
 {
 	unsigned long cscr = __raw_readl(CCM_CSCR);
 
-	if (mx27_revision() >= CHIP_REV_2_0) {
+	if (mx27_revision() >= IMX_CHIP_REVISION_2_0) {
 		if (cscr & CCM_CSCR_ARM_SRC)
 			cpu_clk.parent = &mpll_main1_clk;
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-imx/cpu-imx27.c linux-libre-2.6.38-gnu1/arch/arm/mach-imx/cpu-imx27.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-imx/cpu-imx27.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-imx/cpu-imx27.c	2011-03-14 21:20:32.000000000 -0400
@@ -42,7 +42,19 @@ static void query_silicon_parameter(void
 	val = __raw_readl(MX27_IO_ADDRESS(MX27_SYSCTRL_BASE_ADDR
 				+ SYS_CHIP_ID));
 
-	cpu_silicon_rev = (int)(val >> 28);
+	switch (val >> 28) {
+	case 0:
+		cpu_silicon_rev = IMX_CHIP_REVISION_1_0;
+		break;
+	case 1:
+		cpu_silicon_rev = IMX_CHIP_REVISION_2_0;
+		break;
+	case 2:
+		cpu_silicon_rev = IMX_CHIP_REVISION_2_1;
+		break;
+	default:
+		cpu_silicon_rev = IMX_CHIP_REVISION_UNKNOWN;
+	}
 	cpu_partnumber = (int)((val >> 12) & 0xFFFF);
 }
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-imx/devices.c linux-libre-2.6.38-gnu1/arch/arm/mach-imx/devices.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-imx/devices.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-imx/devices.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,553 +0,0 @@
-/*
- * Author: MontaVista Software, Inc.
- *       <source@mvista.com>
- *
- * Based on the OMAP devices.c
- *
- * 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.
- *
- * Copyright 2006-2007 Freescale Semiconductor, Inc. All Rights Reserved.
- * Copyright 2008 Juergen Beisert, kernel@pengutronix.de
- * Copyright 2008 Sascha Hauer, kernel@pengutronix.de
- * Copyright (c) 2008 Paulius Zaleckas <paulius.zaleckas@teltonika.lt>
- * Copyright (c) 2008 Darius Augulis <darius.augulis@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.
- * 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 <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/gpio.h>
-#include <linux/dma-mapping.h>
-#include <linux/serial.h>
-
-#include <mach/irqs.h>
-#include <mach/hardware.h>
-#include <mach/common.h>
-#include <mach/mmc.h>
-
-#include "devices.h"
-
-#if defined(CONFIG_ARCH_MX1)
-static struct resource imx1_camera_resources[] = {
-	{
-		.start  = 0x00224000,
-		.end    = 0x00224010,
-		.flags  = IORESOURCE_MEM,
-	}, {
-		.start  = MX1_CSI_INT,
-		.end    = MX1_CSI_INT,
-		.flags  = IORESOURCE_IRQ,
-	},
-};
-
-static u64 imx1_camera_dmamask = DMA_BIT_MASK(32);
-
-struct platform_device imx1_camera_device = {
-	.name           = "mx1-camera",
-	.id             = 0, /* This is used to put cameras on this interface */
-	.dev		= {
-		.dma_mask = &imx1_camera_dmamask,
-		.coherent_dma_mask = DMA_BIT_MASK(32),
-	},
-	.resource       = imx1_camera_resources,
-	.num_resources  = ARRAY_SIZE(imx1_camera_resources),
-};
-
-static struct resource imx_rtc_resources[] = {
-	{
-		.start  = 0x00204000,
-		.end    = 0x00204024,
-		.flags  = IORESOURCE_MEM,
-	}, {
-		.start  = MX1_RTC_INT,
-		.end    = MX1_RTC_INT,
-		.flags  = IORESOURCE_IRQ,
-	}, {
-		.start  = MX1_RTC_SAMINT,
-		.end    = MX1_RTC_SAMINT,
-		.flags  = IORESOURCE_IRQ,
-	},
-};
-
-struct platform_device imx_rtc_device = {
-	.name           = "rtc-imx",
-	.id             = 0,
-	.resource       = imx_rtc_resources,
-	.num_resources  = ARRAY_SIZE(imx_rtc_resources),
-};
-
-static struct resource imx_wdt_resources[] = {
-	{
-		.start  = 0x00201000,
-		.end    = 0x00201008,
-		.flags  = IORESOURCE_MEM,
-	}, {
-		.start  = MX1_WDT_INT,
-		.end    = MX1_WDT_INT,
-		.flags  = IORESOURCE_IRQ,
-	},
-};
-
-struct platform_device imx_wdt_device = {
-	.name           = "imx-wdt",
-	.id             = 0,
-	.resource       = imx_wdt_resources,
-	.num_resources  = ARRAY_SIZE(imx_wdt_resources),
-};
-
-static struct resource imx_usb_resources[] = {
-	{
-		.start	= 0x00212000,
-		.end	= 0x00212148,
-		.flags	= IORESOURCE_MEM,
-	}, {
-		.start	= MX1_USBD_INT0,
-		.end	= MX1_USBD_INT0,
-		.flags	= IORESOURCE_IRQ,
-	}, {
-		.start	= MX1_USBD_INT1,
-		.end	= MX1_USBD_INT1,
-		.flags	= IORESOURCE_IRQ,
-	}, {
-		.start	= MX1_USBD_INT2,
-		.end	= MX1_USBD_INT2,
-		.flags	= IORESOURCE_IRQ,
-	}, {
-		.start	= MX1_USBD_INT3,
-		.end	= MX1_USBD_INT3,
-		.flags	= IORESOURCE_IRQ,
-	}, {
-		.start	= MX1_USBD_INT4,
-		.end	= MX1_USBD_INT4,
-		.flags	= IORESOURCE_IRQ,
-	}, {
-		.start	= MX1_USBD_INT5,
-		.end	= MX1_USBD_INT5,
-		.flags	= IORESOURCE_IRQ,
-	}, {
-		.start	= MX1_USBD_INT6,
-		.end	= MX1_USBD_INT6,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-struct platform_device imx_usb_device = {
-	.name		= "imx_udc",
-	.id		= 0,
-	.num_resources	= ARRAY_SIZE(imx_usb_resources),
-	.resource	= imx_usb_resources,
-};
-
-/* GPIO port description */
-static struct mxc_gpio_port imx_gpio_ports[] = {
-	{
-		.chip.label = "gpio-0",
-		.base = (void __iomem *)MX1_IO_ADDRESS(MX1_GPIO_BASE_ADDR),
-		.irq = MX1_GPIO_INT_PORTA,
-		.virtual_irq_start = MXC_GPIO_IRQ_START,
-	}, {
-		.chip.label = "gpio-1",
-		.base = (void __iomem *)MX1_IO_ADDRESS(MX1_GPIO_BASE_ADDR + 0x100),
-		.irq = MX1_GPIO_INT_PORTB,
-		.virtual_irq_start = MXC_GPIO_IRQ_START + 32,
-	}, {
-		.chip.label = "gpio-2",
-		.base = (void __iomem *)MX1_IO_ADDRESS(MX1_GPIO_BASE_ADDR + 0x200),
-		.irq = MX1_GPIO_INT_PORTC,
-		.virtual_irq_start = MXC_GPIO_IRQ_START + 64,
-	}, {
-		.chip.label = "gpio-3",
-		.base = (void __iomem *)MX1_IO_ADDRESS(MX1_GPIO_BASE_ADDR + 0x300),
-		.irq = MX1_GPIO_INT_PORTD,
-		.virtual_irq_start = MXC_GPIO_IRQ_START + 96,
-	}
-};
-
-int __init imx1_register_gpios(void)
-{
-	return mxc_gpio_init(imx_gpio_ports, ARRAY_SIZE(imx_gpio_ports));
-}
-#endif
-
-#if defined(CONFIG_MACH_MX21) || defined(CONFIG_MACH_MX27)
-
-#ifdef CONFIG_MACH_MX27
-static struct resource mx27_camera_resources[] = {
-	{
-	       .start = MX27_CSI_BASE_ADDR,
-	       .end = MX27_CSI_BASE_ADDR + 0x1f,
-	       .flags = IORESOURCE_MEM,
-	}, {
-	       .start = MX27_EMMA_PRP_BASE_ADDR,
-	       .end = MX27_EMMA_PRP_BASE_ADDR + 0x1f,
-	       .flags = IORESOURCE_MEM,
-	}, {
-	       .start = MX27_INT_CSI,
-	       .end = MX27_INT_CSI,
-	       .flags = IORESOURCE_IRQ,
-	},{
-	       .start = MX27_INT_EMMAPRP,
-	       .end = MX27_INT_EMMAPRP,
-	       .flags = IORESOURCE_IRQ,
-	},
-};
-struct platform_device mx27_camera_device = {
-	.name = "mx2-camera",
-	.id = 0,
-	.num_resources = ARRAY_SIZE(mx27_camera_resources),
-	.resource = mx27_camera_resources,
-	.dev = {
-		.coherent_dma_mask = 0xffffffff,
-	},
-};
-#endif
-
-/*
- * General Purpose Timer
- * - i.MX21: 3 timers
- * - i.MX27: 6 timers
- */
-#define DEFINE_IMX_GPT_DEVICE(n, baseaddr, irq)				\
-	static struct resource timer ## n ##_resources[] = {		\
-		{							\
-			.start = baseaddr,				\
-			.end = baseaddr + SZ_4K - 1,			\
-			.flags = IORESOURCE_MEM,			\
-		}, {							\
-			.start = irq,					\
-			.end = irq,					\
-			.flags = IORESOURCE_IRQ,			\
-		}							\
-	};								\
-									\
-	struct platform_device mxc_gpt ## n = {				\
-		.name = "imx_gpt",					\
-		.id = n,						\
-		.num_resources = ARRAY_SIZE(timer ## n ## _resources),	\
-		.resource = timer ## n ## _resources,			\
-	}
-
-/* We use gpt1 as system timer, so do not add a device for this one */
-DEFINE_IMX_GPT_DEVICE(1, MX2x_GPT2_BASE_ADDR, MX2x_INT_GPT2);
-DEFINE_IMX_GPT_DEVICE(2, MX2x_GPT3_BASE_ADDR, MX2x_INT_GPT3);
-
-#ifdef CONFIG_MACH_MX27
-DEFINE_IMX_GPT_DEVICE(3, MX27_GPT4_BASE_ADDR, MX27_INT_GPT4);
-DEFINE_IMX_GPT_DEVICE(4, MX27_GPT5_BASE_ADDR, MX27_INT_GPT5);
-DEFINE_IMX_GPT_DEVICE(5, MX27_GPT6_BASE_ADDR, MX27_INT_GPT6);
-#endif
-
-/* Watchdog: i.MX1 has seperate driver, i.MX21 and i.MX27 are equal */
-static struct resource mxc_wdt_resources[] = {
-	{
-		.start = MX2x_WDOG_BASE_ADDR,
-		.end = MX2x_WDOG_BASE_ADDR + SZ_4K - 1,
-		.flags = IORESOURCE_MEM,
-	},
-};
-
-struct platform_device mxc_wdt = {
-	.name = "imx2-wdt",
-	.id = 0,
-	.num_resources = ARRAY_SIZE(mxc_wdt_resources),
-	.resource = mxc_wdt_resources,
-};
-
-static struct resource mxc_w1_master_resources[] = {
-	{
-		.start = MX2x_OWIRE_BASE_ADDR,
-		.end = MX2x_OWIRE_BASE_ADDR + SZ_4K - 1,
-		.flags = IORESOURCE_MEM,
-	},
-};
-
-struct platform_device mxc_w1_master_device = {
-	.name = "mxc_w1",
-	.id = 0,
-	.num_resources = ARRAY_SIZE(mxc_w1_master_resources),
-	.resource = mxc_w1_master_resources,
-};
-
-/*
- * lcdc:
- * - i.MX1: the basic controller
- * - i.MX21: to be checked
- * - i.MX27: like i.MX1, with slightly variations
- */
-static struct resource mxc_fb[] = {
-	{
-		.start = MX2x_LCDC_BASE_ADDR,
-		.end = MX2x_LCDC_BASE_ADDR + SZ_4K - 1,
-		.flags = IORESOURCE_MEM,
-	}, {
-		.start = MX2x_INT_LCDC,
-		.end = MX2x_INT_LCDC,
-		.flags = IORESOURCE_IRQ,
-	}
-};
-
-/* mxc lcd driver */
-struct platform_device mxc_fb_device = {
-	.name = "imx-fb",
-	.id = 0,
-	.num_resources = ARRAY_SIZE(mxc_fb),
-	.resource = mxc_fb,
-	.dev = {
-		.coherent_dma_mask = DMA_BIT_MASK(32),
-	},
-};
-
-static struct resource mxc_pwm_resources[] = {
-	{
-		.start = MX2x_PWM_BASE_ADDR,
-		.end = MX2x_PWM_BASE_ADDR + SZ_4K - 1,
-		.flags = IORESOURCE_MEM,
-	}, {
-		.start = MX2x_INT_PWM,
-		.end = MX2x_INT_PWM,
-		.flags = IORESOURCE_IRQ,
-	}
-};
-
-struct platform_device mxc_pwm_device = {
-	.name = "mxc_pwm",
-	.id = 0,
-	.num_resources = ARRAY_SIZE(mxc_pwm_resources),
-	.resource = mxc_pwm_resources,
-};
-
-#define DEFINE_MXC_MMC_DEVICE(n, baseaddr, irq, dmareq)			\
-	static struct resource mxc_sdhc_resources ## n[] = {		\
-		{							\
-			.start = baseaddr,				\
-			.end = baseaddr + SZ_4K - 1,			\
-			.flags = IORESOURCE_MEM,			\
-		}, {							\
-			.start = irq,					\
-			.end = irq,					\
-			.flags = IORESOURCE_IRQ,			\
-		}, {							\
-			.start = dmareq,				\
-			.end = dmareq,					\
-			.flags = IORESOURCE_DMA,			\
-		},							\
-	};								\
-									\
-	static u64 mxc_sdhc ## n ## _dmamask = DMA_BIT_MASK(32);	\
-									\
-	struct platform_device mxc_sdhc_device ## n = {			\
-		.name = "mxc-mmc",					\
-		.id = n,						\
-		.dev = {						\
-			.dma_mask = &mxc_sdhc ## n ## _dmamask,		\
-			.coherent_dma_mask = DMA_BIT_MASK(32),		\
-		},							\
-		.num_resources = ARRAY_SIZE(mxc_sdhc_resources ## n),	\
-		.resource = mxc_sdhc_resources ## n,		\
-	}
-
-DEFINE_MXC_MMC_DEVICE(0, MX2x_SDHC1_BASE_ADDR, MX2x_INT_SDHC1, MX2x_DMA_REQ_SDHC1);
-DEFINE_MXC_MMC_DEVICE(1, MX2x_SDHC2_BASE_ADDR, MX2x_INT_SDHC2, MX2x_DMA_REQ_SDHC2);
-
-#ifdef CONFIG_MACH_MX27
-static struct resource otg_resources[] = {
-	{
-		.start = MX27_USBOTG_BASE_ADDR,
-		.end = MX27_USBOTG_BASE_ADDR + 0x1ff,
-		.flags = IORESOURCE_MEM,
-	}, {
-		.start = MX27_INT_USB3,
-		.end = MX27_INT_USB3,
-		.flags = IORESOURCE_IRQ,
-	},
-};
-
-static u64 otg_dmamask = DMA_BIT_MASK(32);
-
-/* OTG gadget device */
-struct platform_device mxc_otg_udc_device = {
-	.name		= "fsl-usb2-udc",
-	.id		= -1,
-	.dev		= {
-		.dma_mask		= &otg_dmamask,
-		.coherent_dma_mask	= DMA_BIT_MASK(32),
-	},
-	.resource	= otg_resources,
-	.num_resources	= ARRAY_SIZE(otg_resources),
-};
-
-/* OTG host */
-struct platform_device mxc_otg_host = {
-	.name = "mxc-ehci",
-	.id = 0,
-	.dev = {
-		.coherent_dma_mask = DMA_BIT_MASK(32),
-		.dma_mask = &otg_dmamask,
-	},
-	.resource = otg_resources,
-	.num_resources = ARRAY_SIZE(otg_resources),
-};
-
-/* USB host 1 */
-
-static u64 usbh1_dmamask = DMA_BIT_MASK(32);
-
-static struct resource mxc_usbh1_resources[] = {
-	{
-		.start = MX27_USBOTG_BASE_ADDR + 0x200,
-		.end = MX27_USBOTG_BASE_ADDR + 0x3ff,
-		.flags = IORESOURCE_MEM,
-	}, {
-		.start = MX27_INT_USB1,
-		.end = MX27_INT_USB1,
-		.flags = IORESOURCE_IRQ,
-	},
-};
-
-struct platform_device mxc_usbh1 = {
-	.name = "mxc-ehci",
-	.id = 1,
-	.dev = {
-		.coherent_dma_mask = DMA_BIT_MASK(32),
-		.dma_mask = &usbh1_dmamask,
-	},
-	.resource = mxc_usbh1_resources,
-	.num_resources = ARRAY_SIZE(mxc_usbh1_resources),
-};
-
-/* USB host 2 */
-static u64 usbh2_dmamask = DMA_BIT_MASK(32);
-
-static struct resource mxc_usbh2_resources[] = {
-	{
-		.start = MX27_USBOTG_BASE_ADDR + 0x400,
-		.end = MX27_USBOTG_BASE_ADDR + 0x5ff,
-		.flags = IORESOURCE_MEM,
-	}, {
-		.start = MX27_INT_USB2,
-		.end = MX27_INT_USB2,
-		.flags = IORESOURCE_IRQ,
-	},
-};
-
-struct platform_device mxc_usbh2 = {
-	.name = "mxc-ehci",
-	.id = 2,
-	.dev = {
-		.coherent_dma_mask = DMA_BIT_MASK(32),
-		.dma_mask = &usbh2_dmamask,
-	},
-	.resource = mxc_usbh2_resources,
-	.num_resources = ARRAY_SIZE(mxc_usbh2_resources),
-};
-#endif
-
-/* GPIO port description */
-#define DEFINE_MXC_GPIO_PORT_IRQ(SOC, n, _irq)				\
-	{								\
-		.chip.label = "gpio-" #n,				\
-		.irq = _irq,						\
-		.base = SOC ## _IO_ADDRESS(MX2x_GPIO_BASE_ADDR +	\
-				n * 0x100),				\
-		.virtual_irq_start = MXC_GPIO_IRQ_START + n * 32,	\
-	}
-
-#define DEFINE_MXC_GPIO_PORT(SOC, n)					\
-	{								\
-		.chip.label = "gpio-" #n,				\
-		.base = SOC ## _IO_ADDRESS(MX2x_GPIO_BASE_ADDR +	\
-				n * 0x100),				\
-		.virtual_irq_start = MXC_GPIO_IRQ_START + n * 32,	\
-	}
-
-#define DEFINE_MXC_GPIO_PORTS(SOC, pfx)					\
-	static struct mxc_gpio_port pfx ## _gpio_ports[] = {		\
-		DEFINE_MXC_GPIO_PORT_IRQ(SOC, 0, SOC ## _INT_GPIO),	\
-		DEFINE_MXC_GPIO_PORT(SOC, 1),				\
-		DEFINE_MXC_GPIO_PORT(SOC, 2),				\
-		DEFINE_MXC_GPIO_PORT(SOC, 3),				\
-		DEFINE_MXC_GPIO_PORT(SOC, 4),				\
-		DEFINE_MXC_GPIO_PORT(SOC, 5),				\
-	}
-
-#ifdef CONFIG_MACH_MX21
-DEFINE_MXC_GPIO_PORTS(MX21, imx21);
-
-int __init imx21_register_gpios(void)
-{
-	return mxc_gpio_init(imx21_gpio_ports, ARRAY_SIZE(imx21_gpio_ports));
-}
-#endif
-
-#ifdef CONFIG_MACH_MX27
-DEFINE_MXC_GPIO_PORTS(MX27, imx27);
-
-int __init imx27_register_gpios(void)
-{
-	return mxc_gpio_init(imx27_gpio_ports, ARRAY_SIZE(imx27_gpio_ports));
-}
-#endif
-
-#ifdef CONFIG_MACH_MX21
-static struct resource mx21_usbhc_resources[] = {
-	{
-		.start	= MX21_USBOTG_BASE_ADDR,
-		.end	= MX21_USBOTG_BASE_ADDR + SZ_8K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	{
-		.start		= MX21_INT_USBHOST,
-		.end		= MX21_INT_USBHOST,
-		.flags		= IORESOURCE_IRQ,
-	},
-};
-
-struct platform_device mx21_usbhc_device = {
-	.name		= "imx21-hcd",
-	.id		= 0,
-	.dev		= {
-		.dma_mask = &mx21_usbhc_device.dev.coherent_dma_mask,
-		.coherent_dma_mask = DMA_BIT_MASK(32),
-	},
-	.num_resources	= ARRAY_SIZE(mx21_usbhc_resources),
-	.resource	= mx21_usbhc_resources,
-};
-#endif
-
-static struct resource imx_kpp_resources[] = {
-	{
-		.start  = MX2x_KPP_BASE_ADDR,
-		.end    = MX2x_KPP_BASE_ADDR + 0xf,
-		.flags  = IORESOURCE_MEM
-	}, {
-		.start  = MX2x_INT_KPP,
-		.end    = MX2x_INT_KPP,
-		.flags  = IORESOURCE_IRQ,
-	},
-};
-
-struct platform_device imx_kpp_device = {
-	.name = "imx-keypad",
-	.id = -1,
-	.num_resources = ARRAY_SIZE(imx_kpp_resources),
-	.resource = imx_kpp_resources,
-};
-
-#endif
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-imx/devices.h linux-libre-2.6.38-gnu1/arch/arm/mach-imx/devices.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-imx/devices.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-imx/devices.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,29 +0,0 @@
-#ifdef CONFIG_ARCH_MX1
-extern struct platform_device imx1_camera_device;
-extern struct platform_device imx_rtc_device;
-extern struct platform_device imx_wdt_device;
-extern struct platform_device imx_usb_device;
-#endif
-
-#if defined(CONFIG_MACH_MX21) || defined(CONFIG_MACH_MX27)
-extern struct platform_device mxc_gpt1;
-extern struct platform_device mxc_gpt2;
-#ifdef CONFIG_MACH_MX27
-extern struct platform_device mxc_gpt3;
-extern struct platform_device mxc_gpt4;
-extern struct platform_device mxc_gpt5;
-#endif
-extern struct platform_device mxc_wdt;
-extern struct platform_device mxc_w1_master_device;
-extern struct platform_device mxc_fb_device;
-extern struct platform_device mxc_pwm_device;
-extern struct platform_device mxc_sdhc_device0;
-extern struct platform_device mxc_sdhc_device1;
-extern struct platform_device mxc_otg_udc_device;
-extern struct platform_device mx27_camera_device;
-extern struct platform_device mxc_otg_host;
-extern struct platform_device mxc_usbh1;
-extern struct platform_device mxc_usbh2;
-extern struct platform_device mx21_usbhc_device;
-extern struct platform_device imx_kpp_device;
-#endif
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-imx/devices-imx21.h linux-libre-2.6.38-gnu1/arch/arm/mach-imx/devices-imx21.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-imx/devices-imx21.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-imx/devices-imx21.h	2011-03-14 21:20:32.000000000 -0400
@@ -9,10 +9,26 @@
 #include <mach/mx21.h>
 #include <mach/devices-common.h>
 
+extern const struct imx_imx21_hcd_data imx21_imx21_hcd_data __initconst;
+#define imx21_add_imx21_hcd(pdata)	\
+	imx_add_imx21_hcd(&imx21_imx21_hcd_data, pdata)
+
+extern const struct imx_imx2_wdt_data imx21_imx2_wdt_data __initconst;
+#define imx21_add_imx2_wdt(pdata)	\
+	imx_add_imx2_wdt(&imx21_imx2_wdt_data)
+
+extern const struct imx_imx_fb_data imx21_imx_fb_data __initconst;
+#define imx21_add_imx_fb(pdata)	\
+	imx_add_imx_fb(&imx21_imx_fb_data, pdata)
+
 extern const struct imx_imx_i2c_data imx21_imx_i2c_data __initconst;
 #define imx21_add_imx_i2c(pdata)	\
 	imx_add_imx_i2c(&imx21_imx_i2c_data, pdata)
 
+extern const struct imx_imx_keypad_data imx21_imx_keypad_data __initconst;
+#define imx21_add_imx_keypad(pdata)	\
+	imx_add_imx_keypad(&imx21_imx_keypad_data, pdata)
+
 extern const struct imx_imx_ssi_data imx21_imx_ssi_data[] __initconst;
 #define imx21_add_imx_ssi(id, pdata)	\
 	imx_add_imx_ssi(&imx21_imx_ssi_data[id], pdata)
@@ -25,10 +41,18 @@ extern const struct imx_imx_uart_1irq_da
 #define imx21_add_imx_uart2(pdata)	imx21_add_imx_uart(2, pdata)
 #define imx21_add_imx_uart3(pdata)	imx21_add_imx_uart(3, pdata)
 
+extern const struct imx_mxc_mmc_data imx21_mxc_mmc_data[] __initconst;
+#define imx21_add_mxc_mmc(id, pdata)	\
+	imx_add_mxc_mmc(&imx21_mxc_mmc_data[id], pdata)
+
 extern const struct imx_mxc_nand_data imx21_mxc_nand_data __initconst;
 #define imx21_add_mxc_nand(pdata)	\
 	imx_add_mxc_nand(&imx21_mxc_nand_data, pdata)
 
+extern const struct imx_mxc_w1_data imx21_mxc_w1_data __initconst;
+#define imx21_add_mxc_w1(pdata)	\
+	imx_add_mxc_w1(&imx21_mxc_w1_data)
+
 extern const struct imx_spi_imx_data imx21_cspi_data[] __initconst;
 #define imx21_add_cspi(id, pdata)	\
 	imx_add_spi_imx(&imx21_cspi_data[id], pdata)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-imx/devices-imx25.h linux-libre-2.6.38-gnu1/arch/arm/mach-imx/devices-imx25.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-imx/devices-imx25.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-imx/devices-imx25.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2010 Pengutronix
+ * Uwe Kleine-Koenig <u.kleine-koenig@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 <mach/mx25.h>
+#include <mach/devices-common.h>
+
+extern const struct imx_fec_data imx25_fec_data __initconst;
+#define imx25_add_fec(pdata)	\
+	imx_add_fec(&imx25_fec_data, pdata)
+
+extern const struct imx_flexcan_data imx25_flexcan_data[] __initconst;
+#define imx25_add_flexcan(id, pdata)	\
+	imx_add_flexcan(&imx25_flexcan_data[id], pdata)
+#define imx25_add_flexcan0(pdata)	imx25_add_flexcan(0, pdata)
+#define imx25_add_flexcan1(pdata)	imx25_add_flexcan(1, pdata)
+
+extern const struct imx_fsl_usb2_udc_data imx25_fsl_usb2_udc_data __initconst;
+#define imx25_add_fsl_usb2_udc(pdata)	\
+	imx_add_fsl_usb2_udc(&imx25_fsl_usb2_udc_data, pdata)
+
+extern struct imx_imxdi_rtc_data imx25_imxdi_rtc_data __initconst;
+#define imx25_add_imxdi_rtc(pdata)	\
+	imx_add_imxdi_rtc(&imx25_imxdi_rtc_data)
+
+extern const struct imx_imx2_wdt_data imx25_imx2_wdt_data __initconst;
+#define imx25_add_imx2_wdt(pdata)	\
+	imx_add_imx2_wdt(&imx25_imx2_wdt_data)
+
+extern const struct imx_imx_fb_data imx25_imx_fb_data __initconst;
+#define imx25_add_imx_fb(pdata)	\
+	imx_add_imx_fb(&imx25_imx_fb_data, pdata)
+
+extern const struct imx_imx_i2c_data imx25_imx_i2c_data[] __initconst;
+#define imx25_add_imx_i2c(id, pdata)	\
+	imx_add_imx_i2c(&imx25_imx_i2c_data[id], pdata)
+#define imx25_add_imx_i2c0(pdata)	imx25_add_imx_i2c(0, pdata)
+#define imx25_add_imx_i2c1(pdata)	imx25_add_imx_i2c(1, pdata)
+#define imx25_add_imx_i2c2(pdata)	imx25_add_imx_i2c(2, pdata)
+
+extern const struct imx_imx_keypad_data imx25_imx_keypad_data __initconst;
+#define imx25_add_imx_keypad(pdata)	\
+	imx_add_imx_keypad(&imx25_imx_keypad_data, pdata)
+
+extern const struct imx_imx_ssi_data imx25_imx_ssi_data[] __initconst;
+#define imx25_add_imx_ssi(id, pdata)	\
+	imx_add_imx_ssi(&imx25_imx_ssi_data[id], pdata)
+
+extern const struct imx_imx_uart_1irq_data imx25_imx_uart_data[] __initconst;
+#define imx25_add_imx_uart(id, pdata)	\
+	imx_add_imx_uart_1irq(&imx25_imx_uart_data[id], pdata)
+#define imx25_add_imx_uart0(pdata)	imx25_add_imx_uart(0, pdata)
+#define imx25_add_imx_uart1(pdata)	imx25_add_imx_uart(1, pdata)
+#define imx25_add_imx_uart2(pdata)	imx25_add_imx_uart(2, pdata)
+#define imx25_add_imx_uart3(pdata)	imx25_add_imx_uart(3, pdata)
+#define imx25_add_imx_uart4(pdata)	imx25_add_imx_uart(4, pdata)
+
+extern const struct imx_mx2_camera_data imx25_mx2_camera_data __initconst;
+#define imx25_add_mx2_camera(pdata)	\
+	imx_add_mx2_camera(&imx25_mx2_camera_data, pdata)
+
+extern const struct imx_mxc_ehci_data imx25_mxc_ehci_otg_data __initconst;
+#define imx25_add_mxc_ehci_otg(pdata)	\
+	imx_add_mxc_ehci(&imx25_mxc_ehci_otg_data, pdata)
+extern const struct imx_mxc_ehci_data imx25_mxc_ehci_hs_data __initconst;
+#define imx25_add_mxc_ehci_hs(pdata)	\
+	imx_add_mxc_ehci(&imx25_mxc_ehci_hs_data, pdata)
+
+extern const struct imx_mxc_nand_data imx25_mxc_nand_data __initconst;
+#define imx25_add_mxc_nand(pdata)	\
+	imx_add_mxc_nand(&imx25_mxc_nand_data, pdata)
+
+extern const struct imx_sdhci_esdhc_imx_data
+imx25_sdhci_esdhc_imx_data[] __initconst;
+#define imx25_add_sdhci_esdhc_imx(id, pdata)	\
+	imx_add_sdhci_esdhc_imx(&imx25_sdhci_esdhc_imx_data[id], pdata)
+
+extern const struct imx_spi_imx_data imx25_cspi_data[] __initconst;
+#define imx25_add_spi_imx(id, pdata)	\
+	imx_add_spi_imx(&imx25_spi_imx_data[id], pdata)
+#define imx25_add_spi_imx0(pdata)	imx25_add_spi_imx(0, pdata)
+#define imx25_add_spi_imx1(pdata)	imx25_add_spi_imx(1, pdata)
+#define imx25_add_spi_imx2(pdata)	imx25_add_spi_imx(2, pdata)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-imx/devices-imx27.h linux-libre-2.6.38-gnu1/arch/arm/mach-imx/devices-imx27.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-imx/devices-imx27.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-imx/devices-imx27.h	2011-03-14 21:20:32.000000000 -0400
@@ -13,10 +13,26 @@ extern const struct imx_fec_data imx27_f
 #define imx27_add_fec(pdata)	\
 	imx_add_fec(&imx27_fec_data, pdata)
 
+extern const struct imx_fsl_usb2_udc_data imx27_fsl_usb2_udc_data __initconst;
+#define imx27_add_fsl_usb2_udc(pdata)	\
+	imx_add_fsl_usb2_udc(&imx27_fsl_usb2_udc_data, pdata)
+
+extern const struct imx_imx2_wdt_data imx27_imx2_wdt_data __initconst;
+#define imx27_add_imx2_wdt(pdata)	\
+	imx_add_imx2_wdt(&imx27_imx2_wdt_data)
+
+extern const struct imx_imx_fb_data imx27_imx_fb_data __initconst;
+#define imx27_add_imx_fb(pdata)	\
+	imx_add_imx_fb(&imx27_imx_fb_data, pdata)
+
 extern const struct imx_imx_i2c_data imx27_imx_i2c_data[] __initconst;
 #define imx27_add_imx_i2c(id, pdata)	\
 	imx_add_imx_i2c(&imx27_imx_i2c_data[id], pdata)
 
+extern const struct imx_imx_keypad_data imx27_imx_keypad_data __initconst;
+#define imx27_add_imx_keypad(pdata)	\
+	imx_add_imx_keypad(&imx27_imx_keypad_data, pdata)
+
 extern const struct imx_imx_ssi_data imx27_imx_ssi_data[] __initconst;
 #define imx27_add_imx_ssi(id, pdata)    \
 	imx_add_imx_ssi(&imx27_imx_ssi_data[id], pdata)
@@ -31,10 +47,29 @@ extern const struct imx_imx_uart_1irq_da
 #define imx27_add_imx_uart4(pdata)	imx27_add_imx_uart(4, pdata)
 #define imx27_add_imx_uart5(pdata)	imx27_add_imx_uart(5, pdata)
 
+extern const struct imx_mx2_camera_data imx27_mx2_camera_data __initconst;
+#define imx27_add_mx2_camera(pdata)	\
+	imx_add_mx2_camera(&imx27_mx2_camera_data, pdata)
+
+extern const struct imx_mxc_ehci_data imx27_mxc_ehci_otg_data __initconst;
+#define imx27_add_mxc_ehci_otg(pdata)	\
+	imx_add_mxc_ehci(&imx27_mxc_ehci_otg_data, pdata)
+extern const struct imx_mxc_ehci_data imx27_mxc_ehci_hs_data[] __initconst;
+#define imx27_add_mxc_ehci_hs(id, pdata)	\
+	imx_add_mxc_ehci(&imx27_mxc_ehci_hs_data[id - 1], pdata)
+
+extern const struct imx_mxc_mmc_data imx27_mxc_mmc_data[] __initconst;
+#define imx27_add_mxc_mmc(id, pdata)	\
+	imx_add_mxc_mmc(&imx27_mxc_mmc_data[id], pdata)
+
 extern const struct imx_mxc_nand_data imx27_mxc_nand_data __initconst;
 #define imx27_add_mxc_nand(pdata)	\
 	imx_add_mxc_nand(&imx27_mxc_nand_data, pdata)
 
+extern const struct imx_mxc_w1_data imx27_mxc_w1_data __initconst;
+#define imx27_add_mxc_w1(pdata)	\
+	imx_add_mxc_w1(&imx27_mxc_w1_data)
+
 extern const struct imx_spi_imx_data imx27_cspi_data[] __initconst;
 #define imx27_add_cspi(id, pdata)	\
 	imx_add_spi_imx(&imx27_cspi_data[id], pdata)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-imx/dma-v1.c linux-libre-2.6.38-gnu1/arch/arm/mach-imx/dma-v1.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-imx/dma-v1.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-imx/dma-v1.c	2011-03-14 21:20:32.000000000 -0400
@@ -818,9 +818,11 @@ static int __init imx_dma_init(void)
 		imx_dmav1_baseaddr = MX27_IO_ADDRESS(MX27_DMA_BASE_ADDR);
 	else
 #endif
-		BUG();
+		return 0;
 
 	dma_clk = clk_get(NULL, "dma");
+	if (IS_ERR(dma_clk))
+		return PTR_ERR(dma_clk);
 	clk_enable(dma_clk);
 
 	/* reset DMA module */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-imx/eukrea_mbimx27-baseboard.c linux-libre-2.6.38-gnu1/arch/arm/mach-imx/eukrea_mbimx27-baseboard.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-imx/eukrea_mbimx27-baseboard.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-imx/eukrea_mbimx27-baseboard.c	2011-03-14 21:20:32.000000000 -0400
@@ -26,20 +26,16 @@
 #include <linux/spi/ads7846.h>
 #include <linux/backlight.h>
 #include <video/platform_lcd.h>
-#include <linux/input/matrix_keypad.h>
 
 #include <asm/mach/arch.h>
 
 #include <mach/common.h>
 #include <mach/iomux-mx27.h>
-#include <mach/imxfb.h>
 #include <mach/hardware.h>
-#include <mach/mmc.h>
 #include <mach/spi.h>
 #include <mach/audmux.h>
 
 #include "devices-imx27.h"
-#include "devices.h"
 
 static const int eukrea_mbimx27_pins[] __initconst = {
 	/* UART2 */
@@ -111,7 +107,8 @@ static const uint32_t eukrea_mbimx27_key
 	KEY(1, 1, KEY_LEFT),
 };
 
-static struct matrix_keymap_data eukrea_mbimx27_keymap_data = {
+static const struct matrix_keymap_data
+eukrea_mbimx27_keymap_data __initconst = {
 	.keymap         = eukrea_mbimx27_keymap,
 	.keymap_size    = ARRAY_SIZE(eukrea_mbimx27_keymap),
 };
@@ -196,7 +193,7 @@ static struct imx_fb_videomode eukrea_mb
 	},
 };
 
-static struct imx_fb_platform_data eukrea_mbimx27_fb_data = {
+static const struct imx_fb_platform_data eukrea_mbimx27_fb_data __initconst = {
 	.mode = eukrea_mbimx27_modes,
 	.num_modes = ARRAY_SIZE(eukrea_mbimx27_modes),
 
@@ -300,7 +297,7 @@ static struct platform_device *platform_
 	&leds_gpio,
 };
 
-static struct imxmmc_platform_data sdhc_pdata = {
+static const struct imxmmc_platform_data sdhc_pdata __initconst = {
 	.dat3_card_detect = 1,
 };
 
@@ -345,8 +342,8 @@ void __init eukrea_mbimx27_baseboard_ini
 	imx27_add_imx_uart3(&uart_pdata);
 #endif
 
-	mxc_register_device(&mxc_fb_device, &eukrea_mbimx27_fb_data);
-	mxc_register_device(&mxc_sdhc_device0, &sdhc_pdata);
+	imx27_add_imx_fb(&eukrea_mbimx27_fb_data);
+	imx27_add_mxc_mmc(0, &sdhc_pdata);
 
 	i2c_register_board_info(0, eukrea_mbimx27_i2c_devices,
 				ARRAY_SIZE(eukrea_mbimx27_i2c_devices));
@@ -380,7 +377,7 @@ void __init eukrea_mbimx27_baseboard_ini
 	gpio_request(GPIO_PORTA | 25, "lcd_enable");
 	platform_device_register(&eukrea_mbimx27_lcd_powerdev);
 
-	mxc_register_device(&imx_kpp_device, &eukrea_mbimx27_keymap_data);
+	imx27_add_imx_keypad(&eukrea_mbimx27_keymap_data);
 
 	platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
 }
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c linux-libre-2.6.38-gnu1/arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,296 @@
+/*
+ * Copyright (C) 2010 Eric Benard - eric@eukrea.com
+ *
+ * Based on pcm970-baseboard.c which is :
+ * Copyright (C) 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.
+ */
+
+#include <linux/gpio.h>
+#include <linux/leds.h>
+#include <linux/platform_device.h>
+#include <linux/gpio_keys.h>
+#include <linux/input.h>
+#include <video/platform_lcd.h>
+
+#include <mach/hardware.h>
+#include <mach/iomux-mx25.h>
+#include <mach/common.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <mach/mx25.h>
+#include <mach/imx-uart.h>
+#include <mach/audmux.h>
+
+#include "devices-imx25.h"
+
+static iomux_v3_cfg_t eukrea_mbimxsd_pads[] = {
+	/* LCD */
+	MX25_PAD_LD0__LD0,
+	MX25_PAD_LD1__LD1,
+	MX25_PAD_LD2__LD2,
+	MX25_PAD_LD3__LD3,
+	MX25_PAD_LD4__LD4,
+	MX25_PAD_LD5__LD5,
+	MX25_PAD_LD6__LD6,
+	MX25_PAD_LD7__LD7,
+	MX25_PAD_LD8__LD8,
+	MX25_PAD_LD9__LD9,
+	MX25_PAD_LD10__LD10,
+	MX25_PAD_LD11__LD11,
+	MX25_PAD_LD12__LD12,
+	MX25_PAD_LD13__LD13,
+	MX25_PAD_LD14__LD14,
+	MX25_PAD_LD15__LD15,
+	MX25_PAD_GPIO_E__LD16,
+	MX25_PAD_GPIO_F__LD17,
+	MX25_PAD_HSYNC__HSYNC,
+	MX25_PAD_VSYNC__VSYNC,
+	MX25_PAD_LSCLK__LSCLK,
+	MX25_PAD_OE_ACD__OE_ACD,
+	MX25_PAD_CONTRAST__CONTRAST,
+	/* LCD_PWR */
+	MX25_PAD_PWM__GPIO_1_26,
+	/* LED */
+	MX25_PAD_POWER_FAIL__GPIO_3_19,
+	/* SWITCH */
+	MX25_PAD_VSTBY_ACK__GPIO_3_18,
+	/* UART2 */
+	MX25_PAD_UART2_RTS__UART2_RTS,
+	MX25_PAD_UART2_CTS__UART2_CTS,
+	MX25_PAD_UART2_TXD__UART2_TXD,
+	MX25_PAD_UART2_RXD__UART2_RXD,
+	/* SD1 */
+	MX25_PAD_SD1_CMD__SD1_CMD,
+	MX25_PAD_SD1_CLK__SD1_CLK,
+	MX25_PAD_SD1_DATA0__SD1_DATA0,
+	MX25_PAD_SD1_DATA1__SD1_DATA1,
+	MX25_PAD_SD1_DATA2__SD1_DATA2,
+	MX25_PAD_SD1_DATA3__SD1_DATA3,
+	/* SD1 CD */
+	MX25_PAD_DE_B__GPIO_2_20,
+	/* I2S */
+	MX25_PAD_KPP_COL3__AUD5_TXFS,
+	MX25_PAD_KPP_COL2__AUD5_TXC,
+	MX25_PAD_KPP_COL1__AUD5_RXD,
+	MX25_PAD_KPP_COL0__AUD5_TXD,
+	/* CAN */
+	MX25_PAD_GPIO_D__CAN2_RX,
+	MX25_PAD_GPIO_C__CAN2_TX,
+};
+
+#define GPIO_LED1	83
+#define GPIO_SWITCH1	82
+#define GPIO_SD1CD	52
+#define GPIO_LCDPWR	26
+
+static struct imx_fb_videomode eukrea_mximxsd_modes[] = {
+	{
+		.mode	= {
+			.name		= "CMO-QVGA",
+			.refresh	= 60,
+			.xres		= 320,
+			.yres		= 240,
+			.pixclock	= KHZ2PICOS(6500),
+			.left_margin	= 30,
+			.right_margin	= 38,
+			.upper_margin	= 20,
+			.lower_margin	= 3,
+			.hsync_len	= 15,
+			.vsync_len	= 4,
+		},
+		.bpp	= 16,
+		.pcr	= 0xCAD08B80,
+	}, {
+		.mode = {
+			.name		= "DVI-VGA",
+			.refresh	= 60,
+			.xres		= 640,
+			.yres		= 480,
+			.pixclock	= 32000,
+			.hsync_len	= 7,
+			.left_margin	= 100,
+			.right_margin	= 100,
+			.vsync_len	= 7,
+			.upper_margin	= 7,
+			.lower_margin	= 100,
+		},
+		.pcr		= 0xFA208B80,
+		.bpp		= 16,
+	}, {
+		.mode = {
+			.name		= "DVI-SVGA",
+			.refresh	= 60,
+			.xres		= 800,
+			.yres		= 600,
+			.pixclock	= 25000,
+			.hsync_len	= 7,
+			.left_margin	= 75,
+			.right_margin	= 75,
+			.vsync_len	= 7,
+			.upper_margin	= 7,
+			.lower_margin	= 75,
+		},
+		.pcr		= 0xFA208B80,
+		.bpp		= 16,
+	},
+};
+
+static const struct imx_fb_platform_data eukrea_mximxsd_fb_pdata __initconst = {
+	.mode		= eukrea_mximxsd_modes,
+	.num_modes	= ARRAY_SIZE(eukrea_mximxsd_modes),
+	.pwmr		= 0x00A903FF,
+	.lscr1		= 0x00120300,
+	.dmacr		= 0x00040060,
+};
+
+static void eukrea_mbimxsd_lcd_power_set(struct plat_lcd_data *pd,
+				   unsigned int power)
+{
+	if (power)
+		gpio_direction_output(GPIO_LCDPWR, 1);
+	else
+		gpio_direction_output(GPIO_LCDPWR, 0);
+}
+
+static struct plat_lcd_data eukrea_mbimxsd_lcd_power_data = {
+	.set_power		= eukrea_mbimxsd_lcd_power_set,
+};
+
+static struct platform_device eukrea_mbimxsd_lcd_powerdev = {
+	.name			= "platform-lcd",
+	.dev.platform_data	= &eukrea_mbimxsd_lcd_power_data,
+};
+
+static struct gpio_led eukrea_mbimxsd_leds[] = {
+	{
+		.name			= "led1",
+		.default_trigger	= "heartbeat",
+		.active_low		= 1,
+		.gpio			= GPIO_LED1,
+	},
+};
+
+static struct gpio_led_platform_data eukrea_mbimxsd_led_info = {
+	.leds		= eukrea_mbimxsd_leds,
+	.num_leds	= ARRAY_SIZE(eukrea_mbimxsd_leds),
+};
+
+static struct platform_device eukrea_mbimxsd_leds_gpio = {
+	.name	= "leds-gpio",
+	.id	= -1,
+	.dev	= {
+		.platform_data	= &eukrea_mbimxsd_led_info,
+	},
+};
+
+static struct gpio_keys_button eukrea_mbimxsd_gpio_buttons[] = {
+	{
+		.gpio		= GPIO_SWITCH1,
+		.code		= BTN_0,
+		.desc		= "BP1",
+		.active_low	= 1,
+		.wakeup		= 1,
+	},
+};
+
+static struct gpio_keys_platform_data eukrea_mbimxsd_button_data = {
+	.buttons	= eukrea_mbimxsd_gpio_buttons,
+	.nbuttons	= ARRAY_SIZE(eukrea_mbimxsd_gpio_buttons),
+};
+
+static struct platform_device eukrea_mbimxsd_button_device = {
+	.name		= "gpio-keys",
+	.id		= -1,
+	.num_resources	= 0,
+	.dev		= {
+		.platform_data	= &eukrea_mbimxsd_button_data,
+	}
+};
+
+static struct platform_device *platform_devices[] __initdata = {
+	&eukrea_mbimxsd_leds_gpio,
+	&eukrea_mbimxsd_button_device,
+	&eukrea_mbimxsd_lcd_powerdev,
+};
+
+static const struct imxuart_platform_data uart_pdata __initconst = {
+	.flags = IMXUART_HAVE_RTSCTS,
+};
+
+static struct i2c_board_info eukrea_mbimxsd_i2c_devices[] = {
+	{
+		I2C_BOARD_INFO("tlv320aic23", 0x1a),
+	},
+};
+
+static const
+struct imx_ssi_platform_data eukrea_mbimxsd_ssi_pdata __initconst = {
+	.flags = IMX_SSI_SYN | IMX_SSI_NET | IMX_SSI_USE_I2S_SLAVE,
+};
+
+/*
+ * system init for baseboard usage. Will be called by cpuimx25 init.
+ *
+ * Add platform devices present on this baseboard and init
+ * them from CPU side as far as required to use them later on
+ */
+void __init eukrea_mbimxsd25_baseboard_init(void)
+{
+	if (mxc_iomux_v3_setup_multiple_pads(eukrea_mbimxsd_pads,
+			ARRAY_SIZE(eukrea_mbimxsd_pads)))
+		printk(KERN_ERR "error setting mbimxsd pads !\n");
+
+#if defined(CONFIG_SND_SOC_EUKREA_TLV320)
+	/* SSI unit master I2S codec connected to SSI_AUD5*/
+	mxc_audmux_v2_configure_port(0,
+			MXC_AUDMUX_V2_PTCR_SYN |
+			MXC_AUDMUX_V2_PTCR_TFSDIR |
+			MXC_AUDMUX_V2_PTCR_TFSEL(4) |
+			MXC_AUDMUX_V2_PTCR_TCLKDIR |
+			MXC_AUDMUX_V2_PTCR_TCSEL(4),
+			MXC_AUDMUX_V2_PDCR_RXDSEL(4)
+	);
+	mxc_audmux_v2_configure_port(4,
+			MXC_AUDMUX_V2_PTCR_SYN,
+			MXC_AUDMUX_V2_PDCR_RXDSEL(0)
+	);
+#endif
+
+	imx25_add_imx_uart1(&uart_pdata);
+	imx25_add_imx_fb(&eukrea_mximxsd_fb_pdata);
+	imx25_add_imx_ssi(0, &eukrea_mbimxsd_ssi_pdata);
+
+	imx25_add_flexcan1(NULL);
+	imx25_add_sdhci_esdhc_imx(0, NULL);
+
+	gpio_request(GPIO_LED1, "LED1");
+	gpio_direction_output(GPIO_LED1, 1);
+	gpio_free(GPIO_LED1);
+
+	gpio_request(GPIO_SWITCH1, "SWITCH1");
+	gpio_direction_input(GPIO_SWITCH1);
+	gpio_free(GPIO_SWITCH1);
+
+	gpio_request(GPIO_LCDPWR, "LCDPWR");
+	gpio_direction_output(GPIO_LCDPWR, 1);
+	gpio_free(GPIO_SWITCH1);
+
+	i2c_register_board_info(0, eukrea_mbimxsd_i2c_devices,
+				ARRAY_SIZE(eukrea_mbimxsd_i2c_devices));
+
+	platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
+}
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-imx/Kconfig linux-libre-2.6.38-gnu1/arch/arm/mach-imx/Kconfig
--- linux-libre-2.6.37-gnu1/arch/arm/mach-imx/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-imx/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -1,13 +1,37 @@
 config IMX_HAVE_DMA_V1
 	bool
 
-if ARCH_MX1
-
 config SOC_IMX1
+	bool
 	select CPU_ARM920T
 	select IMX_HAVE_DMA_V1
 	select IMX_HAVE_IOMUX_V1
+	select MXC_AVIC
+
+config SOC_IMX21
+	bool
+	select CPU_ARM926T
+	select ARCH_MXC_AUDMUX_V1
+	select IMX_HAVE_DMA_V1
+	select IMX_HAVE_IOMUX_V1
+	select MXC_AVIC
+
+config SOC_IMX25
 	bool
+	select CPU_ARM926T
+	select ARCH_MXC_AUDMUX_V2
+	select ARCH_MXC_IOMUX_V3
+	select MXC_AVIC
+
+config SOC_IMX27
+	bool
+	select CPU_ARM926T
+	select ARCH_MXC_AUDMUX_V1
+	select IMX_HAVE_DMA_V1
+	select IMX_HAVE_IOMUX_V1
+	select MXC_AVIC
+
+if ARCH_MX1
 
 comment "MX1 platforms:"
 config MACH_MXLADS
@@ -31,33 +55,17 @@ endif
 
 if ARCH_MX2
 
-config SOC_IMX21
-	select CPU_ARM926T
-	select ARCH_MXC_AUDMUX_V1
-	select IMX_HAVE_DMA_V1
-	select IMX_HAVE_IOMUX_V1
-	bool
-
-config SOC_IMX27
-	select CPU_ARM926T
-	select ARCH_MXC_AUDMUX_V1
-	select IMX_HAVE_DMA_V1
-	select IMX_HAVE_IOMUX_V1
-	bool
-
 choice
 	prompt "CPUs:"
 	default MACH_MX21
 
 config MACH_MX21
 	bool "i.MX21 support"
-	select SOC_IMX21
 	help
 	  This enables support for Freescale's MX2 based i.MX21 processor.
 
 config MACH_MX27
 	bool "i.MX27 support"
-	select SOC_IMX27
 	help
 	  This enables support for Freescale's MX2 based i.MX27 processor.
 
@@ -71,7 +79,10 @@ comment "MX21 platforms:"
 
 config MACH_MX21ADS
 	bool "MX21ADS platform"
+	select SOC_IMX21
+	select IMX_HAVE_PLATFORM_IMX_FB
 	select IMX_HAVE_PLATFORM_IMX_UART
+	select IMX_HAVE_PLATFORM_MXC_MMC
 	select IMX_HAVE_PLATFORM_MXC_NAND
 	help
 	  Include support for MX21ADS platform. This includes specific
@@ -79,24 +90,79 @@ config MACH_MX21ADS
 
 endif
 
+if ARCH_MX25
+
+comment "MX25 platforms:"
+
+config MACH_MX25_3DS
+	bool "Support MX25PDK (3DS) Platform"
+	select SOC_IMX25
+	select IMX_HAVE_PLATFORM_FSL_USB2_UDC
+	select IMX_HAVE_PLATFORM_IMX2_WDT
+	select IMX_HAVE_PLATFORM_IMXDI_RTC
+	select IMX_HAVE_PLATFORM_IMX_FB
+	select IMX_HAVE_PLATFORM_IMX_KEYPAD
+	select IMX_HAVE_PLATFORM_IMX_UART
+	select IMX_HAVE_PLATFORM_MXC_EHCI
+	select IMX_HAVE_PLATFORM_MXC_NAND
+	select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
+
+config MACH_EUKREA_CPUIMX25
+	bool "Support Eukrea CPUIMX25 Platform"
+	select SOC_IMX25
+	select IMX_HAVE_PLATFORM_FLEXCAN
+	select IMX_HAVE_PLATFORM_FSL_USB2_UDC
+	select IMX_HAVE_PLATFORM_IMXDI_RTC
+	select IMX_HAVE_PLATFORM_IMX_FB
+	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_SDHCI_ESDHC_IMX
+	select MXC_ULPI if USB_ULPI
+
+choice
+	prompt "Baseboard"
+	depends on MACH_EUKREA_CPUIMX25
+	default MACH_EUKREA_MBIMXSD25_BASEBOARD
+
+config MACH_EUKREA_MBIMXSD25_BASEBOARD
+	bool "Eukrea MBIMXSD development board"
+	select IMX_HAVE_PLATFORM_IMX_SSI
+	help
+	  This adds board specific devices that can be found on Eukrea's
+	  MBIMXSD evaluation board.
+
+endchoice
+
+endif
+
 if MACH_MX27
 
 comment "MX27 platforms:"
 
 config MACH_MX27ADS
 	bool "MX27ADS platform"
+	select SOC_IMX27
+	select IMX_HAVE_PLATFORM_IMX_FB
 	select IMX_HAVE_PLATFORM_IMX_I2C
 	select IMX_HAVE_PLATFORM_IMX_UART
+	select IMX_HAVE_PLATFORM_MXC_MMC
 	select IMX_HAVE_PLATFORM_MXC_NAND
+	select IMX_HAVE_PLATFORM_MXC_W1
 	help
 	  Include support for MX27ADS platform. This includes specific
 	  configurations for the board and its peripherals.
 
 config MACH_PCM038
 	bool "Phytec phyCORE-i.MX27 CPU module (pcm038)"
+	select SOC_IMX27
+	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_MXC_NAND
+	select IMX_HAVE_PLATFORM_MXC_W1
 	select IMX_HAVE_PLATFORM_SPI_IMX
 	select MXC_ULPI if USB_ULPI
 	help
@@ -109,8 +175,9 @@ choice
 	default MACH_PCM970_BASEBOARD
 
 config MACH_PCM970_BASEBOARD
-	prompt "PHYTEC PCM970 development board"
-	bool
+	bool "PHYTEC PCM970 development board"
+	select IMX_HAVE_PLATFORM_IMX_FB
+	select IMX_HAVE_PLATFORM_MXC_MMC
 	help
 	  This adds board specific devices that can be found on Phytec's
 	  PCM970 evaluation board.
@@ -119,9 +186,14 @@ endchoice
 
 config MACH_CPUIMX27
 	bool "Eukrea CPUIMX27 module"
+	select SOC_IMX27
+	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_MXC_NAND
+	select IMX_HAVE_PLATFORM_MXC_W1
 	select MXC_ULPI if USB_ULPI
 	help
 	  Include support for Eukrea CPUIMX27 platform. This includes
@@ -130,6 +202,7 @@ config MACH_CPUIMX27
 config MACH_EUKREA_CPUIMX27_USESDHC2
 	bool "CPUIMX27 integrates SDHC2 module"
 	depends on MACH_CPUIMX27
+	select IMX_HAVE_PLATFORM_MXC_MMC
 	help
 	  This adds support for the internal SDHC2 used on CPUIMX27
 	  for wifi or eMMC.
@@ -148,8 +221,11 @@ choice
 
 config MACH_EUKREA_MBIMX27_BASEBOARD
 	bool "Eukrea MBIMX27 development board"
+	select IMX_HAVE_PLATFORM_IMX_FB
+	select IMX_HAVE_PLATFORM_IMX_KEYPAD
 	select IMX_HAVE_PLATFORM_IMX_SSI
 	select IMX_HAVE_PLATFORM_IMX_UART
+	select IMX_HAVE_PLATFORM_MXC_MMC
 	select IMX_HAVE_PLATFORM_SPI_IMX
 	help
 	  This adds board specific devices that can be found on Eukrea's
@@ -159,15 +235,27 @@ endchoice
 
 config MACH_MX27_3DS
 	bool "MX27PDK platform"
+	select SOC_IMX27
+	select IMX_HAVE_PLATFORM_FSL_USB2_UDC
+	select IMX_HAVE_PLATFORM_IMX2_WDT
+	select IMX_HAVE_PLATFORM_IMX_KEYPAD
 	select IMX_HAVE_PLATFORM_IMX_UART
+	select IMX_HAVE_PLATFORM_MXC_EHCI
+	select IMX_HAVE_PLATFORM_MXC_MMC
+	select IMX_HAVE_PLATFORM_SPI_IMX
+	select MXC_DEBUG_BOARD
+	select MXC_ULPI if USB_ULPI
 	help
 	  Include support for MX27PDK platform. This includes specific
 	  configurations for the board and its peripherals.
 
 config MACH_IMX27_VISSTRIM_M10
 	bool "Vista Silicon i.MX27 Visstrim_m10"
+	select SOC_IMX27
 	select IMX_HAVE_PLATFORM_IMX_I2C
 	select IMX_HAVE_PLATFORM_IMX_UART
+	select IMX_HAVE_PLATFORM_MXC_MMC
+	select IMX_HAVE_PLATFORM_MXC_EHCI
 	help
 	  Include support for Visstrim_m10 platform and its different variants.
 	  This includes specific configurations for the board and its
@@ -175,6 +263,7 @@ config MACH_IMX27_VISSTRIM_M10
 
 config MACH_IMX27LITE
 	bool "LogicPD MX27 LITEKIT platform"
+	select SOC_IMX27
 	select IMX_HAVE_PLATFORM_IMX_UART
 	help
 	  Include support for MX27 LITEKIT platform. This includes specific
@@ -182,10 +271,17 @@ config MACH_IMX27LITE
 
 config MACH_PCA100
 	bool "Phytec phyCARD-s (pca100)"
+	select SOC_IMX27
+	select IMX_HAVE_PLATFORM_FSL_USB2_UDC
+	select IMX_HAVE_PLATFORM_IMX2_WDT
+	select IMX_HAVE_PLATFORM_IMX_FB
 	select IMX_HAVE_PLATFORM_IMX_I2C
 	select IMX_HAVE_PLATFORM_IMX_SSI
 	select IMX_HAVE_PLATFORM_IMX_UART
+	select IMX_HAVE_PLATFORM_MXC_EHCI
+	select IMX_HAVE_PLATFORM_MXC_MMC
 	select IMX_HAVE_PLATFORM_MXC_NAND
+	select IMX_HAVE_PLATFORM_MXC_W1
 	select IMX_HAVE_PLATFORM_SPI_IMX
 	select MXC_ULPI if USB_ULPI
 	help
@@ -194,8 +290,11 @@ config MACH_PCA100
 
 config MACH_MXT_TD60
 	bool "Maxtrack i-MXT TD60"
+	select SOC_IMX27
+	select IMX_HAVE_PLATFORM_IMX_FB
 	select IMX_HAVE_PLATFORM_IMX_I2C
 	select IMX_HAVE_PLATFORM_IMX_UART
+	select IMX_HAVE_PLATFORM_MXC_MMC
 	select IMX_HAVE_PLATFORM_MXC_NAND
 	help
 	  Include support for i-MXT (aka td60) platform. This
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-imx/mach-cpuimx27.c linux-libre-2.6.38-gnu1/arch/arm/mach-imx/mach-cpuimx27.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-imx/mach-cpuimx27.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-imx/mach-cpuimx27.c	2011-03-14 21:20:32.000000000 -0400
@@ -28,7 +28,6 @@
 #include <linux/serial_8250.h>
 #include <linux/usb/otg.h>
 #include <linux/usb/ulpi.h>
-#include <linux/fsl_devices.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -40,11 +39,9 @@
 #include <mach/hardware.h>
 #include <mach/iomux-mx27.h>
 #include <mach/mxc_nand.h>
-#include <mach/mxc_ehci.h>
 #include <mach/ulpi.h>
 
 #include "devices-imx27.h"
-#include "devices.h"
 
 static const int eukrea_cpuimx27_pins[] __initconst = {
 	/* UART1 */
@@ -157,8 +154,6 @@ cpuimx27_nand_board_info __initconst = {
 
 static struct platform_device *platform_devices[] __initdata = {
 	&eukrea_cpuimx27_nor_mtd_device,
-	&mxc_wdt,
-	&mxc_w1_master_device,
 };
 
 static const struct imxi2c_platform_data cpuimx27_i2c1_data __initconst = {
@@ -215,18 +210,18 @@ static struct platform_device serial_dev
 #endif
 
 #if defined(CONFIG_USB_ULPI)
-static struct mxc_usbh_platform_data otg_pdata = {
+static struct mxc_usbh_platform_data otg_pdata __initdata = {
 	.portsc	= MXC_EHCI_MODE_ULPI,
 	.flags	= MXC_EHCI_INTERFACE_DIFF_UNI,
 };
 
-static struct mxc_usbh_platform_data usbh2_pdata = {
+static struct mxc_usbh_platform_data usbh2_pdata __initdata = {
 	.portsc	= MXC_EHCI_MODE_ULPI,
 	.flags	= MXC_EHCI_INTERFACE_DIFF_UNI,
 };
 #endif
 
-static struct fsl_usb2_platform_data otg_device_pdata = {
+static const struct fsl_usb2_platform_data otg_device_pdata __initconst = {
 	.operating_mode = FSL_USB2_DR_DEVICE,
 	.phy_mode       = FSL_USB2_PHY_ULPI,
 };
@@ -262,10 +257,12 @@ static void __init eukrea_cpuimx27_init(
 
 	imx27_add_fec(NULL);
 	platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
+	imx27_add_imx2_wdt(NULL);
+	imx27_add_mxc_w1(NULL);
 
 #if defined(CONFIG_MACH_EUKREA_CPUIMX27_USESDHC2)
 	/* SDHC2 can be used for Wifi */
-	mxc_register_device(&mxc_sdhc_device1, NULL);
+	imx27_add_mxc_mmc(1, NULL);
 #endif
 #if defined(MACH_EUKREA_CPUIMX27_USEUART4)
 	/* in which case UART4 is also used for Bluetooth */
@@ -281,16 +278,16 @@ static void __init eukrea_cpuimx27_init(
 		otg_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops,
 				ULPI_OTG_DRVVBUS | ULPI_OTG_DRVVBUS_EXT);
 
-		mxc_register_device(&mxc_otg_host, &otg_pdata);
+		imx27_add_mxc_ehci_otg(&otg_pdata);
 	}
 
 	usbh2_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops,
 				ULPI_OTG_DRVVBUS | ULPI_OTG_DRVVBUS_EXT);
 
-	mxc_register_device(&mxc_usbh2, &usbh2_pdata);
+	imx27_add_mxc_ehci_hs(2, &usbh2_pdata);
 #endif
 	if (!otg_mode_host)
-		mxc_register_device(&mxc_otg_udc_device, &otg_device_pdata);
+		imx27_add_fsl_usb2_udc(&otg_device_pdata);
 
 #ifdef CONFIG_MACH_EUKREA_MBIMX27_BASEBOARD
 	eukrea_mbimx27_baseboard_init();
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-imx/mach-eukrea_cpuimx25.c linux-libre-2.6.38-gnu1/arch/arm/mach-imx/mach-eukrea_cpuimx25.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-imx/mach-eukrea_cpuimx25.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-imx/mach-eukrea_cpuimx25.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,161 @@
+/*
+ * Copyright 2009 Sascha Hauer, <kernel@pengutronix.de>
+ * Copyright 2010 Eric Bénard - Eukréa Electromatique, <eric@eukrea.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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA  02110-1301, USA.
+ */
+
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/irq.h>
+#include <linux/gpio.h>
+#include <linux/platform_device.h>
+#include <linux/usb/otg.h>
+#include <linux/usb/ulpi.h>
+
+#include <mach/eukrea-baseboards.h>
+#include <mach/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include <asm/memory.h>
+#include <asm/mach/map.h>
+#include <mach/common.h>
+#include <mach/mx25.h>
+#include <mach/mxc_nand.h>
+#include <mach/imxfb.h>
+#include <mach/iomux-mx25.h>
+
+#include "devices-imx25.h"
+
+static const struct imxuart_platform_data uart_pdata __initconst = {
+	.flags = IMXUART_HAVE_RTSCTS,
+};
+
+static iomux_v3_cfg_t eukrea_cpuimx25_pads[] = {
+	/* FEC - RMII */
+	MX25_PAD_FEC_MDC__FEC_MDC,
+	MX25_PAD_FEC_MDIO__FEC_MDIO,
+	MX25_PAD_FEC_TDATA0__FEC_TDATA0,
+	MX25_PAD_FEC_TDATA1__FEC_TDATA1,
+	MX25_PAD_FEC_TX_EN__FEC_TX_EN,
+	MX25_PAD_FEC_RDATA0__FEC_RDATA0,
+	MX25_PAD_FEC_RDATA1__FEC_RDATA1,
+	MX25_PAD_FEC_RX_DV__FEC_RX_DV,
+	MX25_PAD_FEC_TX_CLK__FEC_TX_CLK,
+	/* I2C1 */
+	MX25_PAD_I2C1_CLK__I2C1_CLK,
+	MX25_PAD_I2C1_DAT__I2C1_DAT,
+};
+
+static const struct fec_platform_data mx25_fec_pdata __initconst = {
+	.phy	= PHY_INTERFACE_MODE_RMII,
+};
+
+static const struct mxc_nand_platform_data
+eukrea_cpuimx25_nand_board_info __initconst = {
+	.width		= 1,
+	.hw_ecc		= 1,
+	.flash_bbt	= 1,
+};
+
+static const struct imxi2c_platform_data
+eukrea_cpuimx25_i2c0_data __initconst = {
+	.bitrate = 100000,
+};
+
+static struct i2c_board_info eukrea_cpuimx25_i2c_devices[] = {
+	{
+		I2C_BOARD_INFO("pcf8563", 0x51),
+	},
+};
+
+static const struct mxc_usbh_platform_data otg_pdata __initconst = {
+	.portsc	= MXC_EHCI_MODE_UTMI,
+	.flags	= MXC_EHCI_INTERFACE_DIFF_UNI,
+};
+
+static const struct mxc_usbh_platform_data usbh2_pdata __initconst = {
+	.portsc	= MXC_EHCI_MODE_SERIAL,
+	.flags	= MXC_EHCI_INTERFACE_SINGLE_UNI | MXC_EHCI_INTERNAL_PHY |
+		  MXC_EHCI_IPPUE_DOWN,
+};
+
+static const struct fsl_usb2_platform_data otg_device_pdata __initconst = {
+	.operating_mode = FSL_USB2_DR_DEVICE,
+	.phy_mode       = FSL_USB2_PHY_UTMI,
+};
+
+static int otg_mode_host;
+
+static int __init eukrea_cpuimx25_otg_mode(char *options)
+{
+	if (!strcmp(options, "host"))
+		otg_mode_host = 1;
+	else if (!strcmp(options, "device"))
+		otg_mode_host = 0;
+	else
+		pr_info("otg_mode neither \"host\" nor \"device\". "
+			"Defaulting to device\n");
+	return 0;
+}
+__setup("otg_mode=", eukrea_cpuimx25_otg_mode);
+
+static void __init eukrea_cpuimx25_init(void)
+{
+	if (mxc_iomux_v3_setup_multiple_pads(eukrea_cpuimx25_pads,
+			ARRAY_SIZE(eukrea_cpuimx25_pads)))
+		printk(KERN_ERR "error setting cpuimx25 pads !\n");
+
+	imx25_add_imx_uart0(&uart_pdata);
+	imx25_add_mxc_nand(&eukrea_cpuimx25_nand_board_info);
+	imx25_add_imxdi_rtc(NULL);
+	imx25_add_fec(&mx25_fec_pdata);
+
+	i2c_register_board_info(0, eukrea_cpuimx25_i2c_devices,
+				ARRAY_SIZE(eukrea_cpuimx25_i2c_devices));
+	imx25_add_imx_i2c0(&eukrea_cpuimx25_i2c0_data);
+
+	if (otg_mode_host)
+		imx25_add_mxc_ehci_otg(&otg_pdata);
+	else
+		imx25_add_fsl_usb2_udc(&otg_device_pdata);
+
+	imx25_add_mxc_ehci_hs(&usbh2_pdata);
+
+#ifdef CONFIG_MACH_EUKREA_MBIMXSD25_BASEBOARD
+	eukrea_mbimxsd25_baseboard_init();
+#endif
+}
+
+static void __init eukrea_cpuimx25_timer_init(void)
+{
+	mx25_clocks_init();
+}
+
+static struct sys_timer eukrea_cpuimx25_timer = {
+	.init   = eukrea_cpuimx25_timer_init,
+};
+
+MACHINE_START(EUKREA_CPUIMX25, "Eukrea CPUIMX25")
+	/* Maintainer: Eukrea Electromatique */
+	.boot_params    = MX25_PHYS_OFFSET + 0x100,
+	.map_io         = mx25_map_io,
+	.init_irq       = mx25_init_irq,
+	.init_machine   = eukrea_cpuimx25_init,
+	.timer          = &eukrea_cpuimx25_timer,
+MACHINE_END
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-imx/mach-imx27lite.c linux-libre-2.6.38-gnu1/arch/arm/mach-imx/mach-imx27lite.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-imx/mach-imx27lite.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-imx/mach-imx27lite.c	2011-03-14 21:20:32.000000000 -0400
@@ -25,7 +25,6 @@
 #include <mach/iomux-mx27.h>
 
 #include "devices-imx27.h"
-#include "devices.h"
 
 static const int mx27lite_pins[] __initconst = {
 	/* UART1 */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-imx/mach-imx27_visstrim_m10.c linux-libre-2.6.38-gnu1/arch/arm/mach-imx/mach-imx27_visstrim_m10.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-imx/mach-imx27_visstrim_m10.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-imx/mach-imx27_visstrim_m10.c	2011-03-14 21:20:32.000000000 -0400
@@ -34,12 +34,9 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
 #include <mach/common.h>
-#include <mach/mmc.h>
 #include <mach/iomux.h>
-#include <mach/mxc_ehci.h>
 
 #include "devices-imx27.h"
-#include "devices.h"
 
 #define OTG_PHY_CS_GPIO (GPIO_PORTF + 17)
 #define SDHC1_IRQ IRQ_GPIOB(25)
@@ -156,7 +153,7 @@ static void visstrim_m10_sdhc1_exit(stru
 	free_irq(SDHC1_IRQ, data);
 }
 
-static struct imxmmc_platform_data visstrim_m10_sdhc_pdata = {
+static const struct imxmmc_platform_data visstrim_m10_sdhc_pdata __initconst = {
 	.init = visstrim_m10_sdhc1_init,
 	.exit = visstrim_m10_sdhc1_exit,
 };
@@ -216,7 +213,8 @@ static int otg_phy_init(struct platform_
 	return 0;
 }
 
-static struct mxc_usbh_platform_data visstrim_m10_usbotg_pdata = {
+static const struct mxc_usbh_platform_data
+visstrim_m10_usbotg_pdata __initconst = {
 	.init = otg_phy_init,
 	.portsc	= MXC_EHCI_MODE_ULPI | MXC_EHCI_UTMI_8BIT,
 	.flags	= MXC_EHCI_POWER_PINS_ENABLED,
@@ -237,8 +235,8 @@ static void __init visstrim_m10_board_in
 				ARRAY_SIZE(visstrim_m10_i2c_devices));
 	imx27_add_imx_i2c(0, &visstrim_m10_i2c_data);
 	imx27_add_imx_i2c(1, &visstrim_m10_i2c_data);
-	mxc_register_device(&mxc_sdhc_device0, &visstrim_m10_sdhc_pdata);
-	mxc_register_device(&mxc_otg_host, &visstrim_m10_usbotg_pdata);
+	imx27_add_mxc_mmc(0, &visstrim_m10_sdhc_pdata);
+	imx27_add_mxc_ehci_otg(&visstrim_m10_usbotg_pdata);
 	imx27_add_fec(NULL);
 	platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
 }
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-imx/mach-mx1ads.c linux-libre-2.6.38-gnu1/arch/arm/mach-imx/mach-mx1ads.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-imx/mach-mx1ads.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-imx/mach-mx1ads.c	2011-03-14 21:20:32.000000000 -0400
@@ -30,7 +30,6 @@
 #include <mach/irqs.h>
 
 #include "devices-imx1.h"
-#include "devices.h"
 
 static const int mx1ads_pins[] __initconst = {
 	/* UART1 */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-imx/mach-mx21ads.c linux-libre-2.6.38-gnu1/arch/arm/mach-imx/mach-mx21ads.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-imx/mach-mx21ads.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-imx/mach-mx21ads.c	2011-03-14 21:20:32.000000000 -0400
@@ -24,13 +24,10 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
 #include <asm/mach/map.h>
-#include <mach/imxfb.h>
 #include <mach/iomux-mx21.h>
 #include <mach/mxc_nand.h>
-#include <mach/mmc.h>
 
 #include "devices-imx21.h"
-#include "devices.h"
 
 /*
  * Memory-mapped I/O on MX21ADS base board
@@ -213,7 +210,7 @@ static struct imx_fb_videomode mx21ads_m
 	},
 };
 
-static struct imx_fb_platform_data mx21ads_fb_data = {
+static const struct imx_fb_platform_data mx21ads_fb_data __initconst = {
 	.mode = mx21ads_modes,
 	.num_modes = ARRAY_SIZE(mx21ads_modes),
 
@@ -233,15 +230,8 @@ static int mx21ads_sdhc_get_ro(struct de
 static int mx21ads_sdhc_init(struct device *dev, irq_handler_t detect_irq,
 	void *data)
 {
-	int ret;
-
-	ret = request_irq(IRQ_GPIOD(25), detect_irq,
+	return request_irq(IRQ_GPIOD(25), detect_irq,
 		IRQF_TRIGGER_FALLING, "mmc-detect", data);
-	if (ret)
-		goto out;
-	return 0;
-out:
-	return ret;
 }
 
 static void mx21ads_sdhc_exit(struct device *dev, void *data)
@@ -249,7 +239,7 @@ static void mx21ads_sdhc_exit(struct dev
 	free_irq(IRQ_GPIOD(25), data);
 }
 
-static struct imxmmc_platform_data mx21ads_sdhc_pdata = {
+static const struct imxmmc_platform_data mx21ads_sdhc_pdata __initconst = {
 	.ocr_avail = MMC_VDD_29_30 | MMC_VDD_30_31, /* 3.0V */
 	.get_ro = mx21ads_sdhc_get_ro,
 	.init = mx21ads_sdhc_init,
@@ -296,8 +286,8 @@ static void __init mx21ads_board_init(vo
 	imx21_add_imx_uart0(&uart_pdata_rts);
 	imx21_add_imx_uart2(&uart_pdata_norts);
 	imx21_add_imx_uart3(&uart_pdata_rts);
-	mxc_register_device(&mxc_fb_device, &mx21ads_fb_data);
-	mxc_register_device(&mxc_sdhc_device0, &mx21ads_sdhc_pdata);
+	imx21_add_imx_fb(&mx21ads_fb_data);
+	imx21_add_mxc_mmc(0, &mx21ads_sdhc_pdata);
 	imx21_add_mxc_nand(&mx21ads_nand_board_info);
 
 	platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-imx/mach-mx25_3ds.c linux-libre-2.6.38-gnu1/arch/arm/mach-imx/mach-mx25_3ds.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-imx/mach-mx25_3ds.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-imx/mach-mx25_3ds.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,235 @@
+/*
+ * Copyright 2009 Sascha Hauer, <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.
+ */
+
+/*
+ * This machine is known as:
+ *  - i.MX25 3-Stack Development System
+ *  - i.MX25 Platform Development Kit (i.MX25 PDK)
+ */
+
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/irq.h>
+#include <linux/gpio.h>
+#include <linux/platform_device.h>
+#include <linux/input/matrix_keypad.h>
+#include <linux/usb/otg.h>
+
+#include <mach/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include <asm/memory.h>
+#include <asm/mach/map.h>
+#include <mach/common.h>
+#include <mach/mx25.h>
+#include <mach/iomux-mx25.h>
+
+#include "devices-imx25.h"
+
+static const struct imxuart_platform_data uart_pdata __initconst = {
+	.flags = IMXUART_HAVE_RTSCTS,
+};
+
+static iomux_v3_cfg_t mx25pdk_pads[] = {
+	MX25_PAD_FEC_MDC__FEC_MDC,
+	MX25_PAD_FEC_MDIO__FEC_MDIO,
+	MX25_PAD_FEC_TDATA0__FEC_TDATA0,
+	MX25_PAD_FEC_TDATA1__FEC_TDATA1,
+	MX25_PAD_FEC_TX_EN__FEC_TX_EN,
+	MX25_PAD_FEC_RDATA0__FEC_RDATA0,
+	MX25_PAD_FEC_RDATA1__FEC_RDATA1,
+	MX25_PAD_FEC_RX_DV__FEC_RX_DV,
+	MX25_PAD_FEC_TX_CLK__FEC_TX_CLK,
+	MX25_PAD_A17__GPIO_2_3, /* FEC_EN, GPIO 35 */
+	MX25_PAD_D12__GPIO_4_8, /* FEC_RESET_B, GPIO 104 */
+
+	/* LCD */
+	MX25_PAD_LD0__LD0,
+	MX25_PAD_LD1__LD1,
+	MX25_PAD_LD2__LD2,
+	MX25_PAD_LD3__LD3,
+	MX25_PAD_LD4__LD4,
+	MX25_PAD_LD5__LD5,
+	MX25_PAD_LD6__LD6,
+	MX25_PAD_LD7__LD7,
+	MX25_PAD_LD8__LD8,
+	MX25_PAD_LD9__LD9,
+	MX25_PAD_LD10__LD10,
+	MX25_PAD_LD11__LD11,
+	MX25_PAD_LD12__LD12,
+	MX25_PAD_LD13__LD13,
+	MX25_PAD_LD14__LD14,
+	MX25_PAD_LD15__LD15,
+	MX25_PAD_GPIO_E__LD16,
+	MX25_PAD_GPIO_F__LD17,
+	MX25_PAD_HSYNC__HSYNC,
+	MX25_PAD_VSYNC__VSYNC,
+	MX25_PAD_LSCLK__LSCLK,
+	MX25_PAD_OE_ACD__OE_ACD,
+	MX25_PAD_CONTRAST__CONTRAST,
+
+	/* Keypad */
+	MX25_PAD_KPP_ROW0__KPP_ROW0,
+	MX25_PAD_KPP_ROW1__KPP_ROW1,
+	MX25_PAD_KPP_ROW2__KPP_ROW2,
+	MX25_PAD_KPP_ROW3__KPP_ROW3,
+	MX25_PAD_KPP_COL0__KPP_COL0,
+	MX25_PAD_KPP_COL1__KPP_COL1,
+	MX25_PAD_KPP_COL2__KPP_COL2,
+	MX25_PAD_KPP_COL3__KPP_COL3,
+
+	/* SD1 */
+	MX25_PAD_SD1_CMD__SD1_CMD,
+	MX25_PAD_SD1_CLK__SD1_CLK,
+	MX25_PAD_SD1_DATA0__SD1_DATA0,
+	MX25_PAD_SD1_DATA1__SD1_DATA1,
+	MX25_PAD_SD1_DATA2__SD1_DATA2,
+	MX25_PAD_SD1_DATA3__SD1_DATA3,
+};
+
+static const struct fec_platform_data mx25_fec_pdata __initconst = {
+	.phy    = PHY_INTERFACE_MODE_RMII,
+};
+
+#define FEC_ENABLE_GPIO		35
+#define FEC_RESET_B_GPIO	104
+
+static void __init mx25pdk_fec_reset(void)
+{
+	gpio_request(FEC_ENABLE_GPIO, "FEC PHY enable");
+	gpio_request(FEC_RESET_B_GPIO, "FEC PHY reset");
+
+	gpio_direction_output(FEC_ENABLE_GPIO, 0);  /* drop PHY power */
+	gpio_direction_output(FEC_RESET_B_GPIO, 0); /* assert reset */
+	udelay(2);
+
+	/* turn on PHY power and lift reset */
+	gpio_set_value(FEC_ENABLE_GPIO, 1);
+	gpio_set_value(FEC_RESET_B_GPIO, 1);
+}
+
+static const struct mxc_nand_platform_data
+mx25pdk_nand_board_info __initconst = {
+	.width		= 1,
+	.hw_ecc		= 1,
+	.flash_bbt	= 1,
+};
+
+static struct imx_fb_videomode mx25pdk_modes[] = {
+	{
+		.mode	= {
+			.name		= "CRT-VGA",
+			.refresh	= 60,
+			.xres		= 640,
+			.yres		= 480,
+			.pixclock	= 39683,
+			.left_margin	= 45,
+			.right_margin	= 114,
+			.upper_margin	= 33,
+			.lower_margin	= 11,
+			.hsync_len	= 1,
+			.vsync_len	= 1,
+		},
+		.bpp	= 16,
+		.pcr	= 0xFA208B80,
+	},
+};
+
+static const struct imx_fb_platform_data mx25pdk_fb_pdata __initconst = {
+	.mode		= mx25pdk_modes,
+	.num_modes	= ARRAY_SIZE(mx25pdk_modes),
+	.pwmr		= 0x00A903FF,
+	.lscr1		= 0x00120300,
+	.dmacr		= 0x00020010,
+};
+
+static const uint32_t mx25pdk_keymap[] = {
+	KEY(0, 0, KEY_UP),
+	KEY(0, 1, KEY_DOWN),
+	KEY(0, 2, KEY_VOLUMEDOWN),
+	KEY(0, 3, KEY_HOME),
+	KEY(1, 0, KEY_RIGHT),
+	KEY(1, 1, KEY_LEFT),
+	KEY(1, 2, KEY_ENTER),
+	KEY(1, 3, KEY_VOLUMEUP),
+	KEY(2, 0, KEY_F6),
+	KEY(2, 1, KEY_F8),
+	KEY(2, 2, KEY_F9),
+	KEY(2, 3, KEY_F10),
+	KEY(3, 0, KEY_F1),
+	KEY(3, 1, KEY_F2),
+	KEY(3, 2, KEY_F3),
+	KEY(3, 3, KEY_POWER),
+};
+
+static const struct matrix_keymap_data mx25pdk_keymap_data __initconst = {
+	.keymap		= mx25pdk_keymap,
+	.keymap_size	= ARRAY_SIZE(mx25pdk_keymap),
+};
+
+static const struct mxc_usbh_platform_data usbh2_pdata __initconst = {
+	.portsc	= MXC_EHCI_MODE_SERIAL,
+	.flags	= MXC_EHCI_INTERNAL_PHY,
+};
+
+static const struct fsl_usb2_platform_data otg_device_pdata __initconst = {
+	.operating_mode = FSL_USB2_DR_DEVICE,
+	.phy_mode       = FSL_USB2_PHY_UTMI,
+};
+
+static void __init mx25pdk_init(void)
+{
+	mxc_iomux_v3_setup_multiple_pads(mx25pdk_pads,
+			ARRAY_SIZE(mx25pdk_pads));
+
+	imx25_add_imx_uart0(&uart_pdata);
+	imx25_add_fsl_usb2_udc(&otg_device_pdata);
+	imx25_add_mxc_ehci_hs(&usbh2_pdata);
+	imx25_add_mxc_nand(&mx25pdk_nand_board_info);
+	imx25_add_imxdi_rtc(NULL);
+	imx25_add_imx_fb(&mx25pdk_fb_pdata);
+	imx25_add_imx2_wdt(NULL);
+
+	mx25pdk_fec_reset();
+	imx25_add_fec(&mx25_fec_pdata);
+	imx25_add_imx_keypad(&mx25pdk_keymap_data);
+
+	imx25_add_sdhci_esdhc_imx(0, NULL);
+}
+
+static void __init mx25pdk_timer_init(void)
+{
+	mx25_clocks_init();
+}
+
+static struct sys_timer mx25pdk_timer = {
+	.init   = mx25pdk_timer_init,
+};
+
+MACHINE_START(MX25_3DS, "Freescale MX25PDK (3DS)")
+	/* Maintainer: Freescale Semiconductor, Inc. */
+	.boot_params    = MX25_PHYS_OFFSET + 0x100,
+	.map_io         = mx25_map_io,
+	.init_irq       = mx25_init_irq,
+	.init_machine   = mx25pdk_init,
+	.timer          = &mx25pdk_timer,
+MACHINE_END
+
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-imx/mach-mx27_3ds.c linux-libre-2.6.38-gnu1/arch/arm/mach-imx/mach-mx27_3ds.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-imx/mach-mx27_3ds.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-imx/mach-mx27_3ds.c	2011-03-14 21:20:32.000000000 -0400
@@ -22,20 +22,30 @@
 
 #include <linux/platform_device.h>
 #include <linux/gpio.h>
-#include <linux/input/matrix_keypad.h>
 #include <linux/irq.h>
+#include <linux/usb/otg.h>
+#include <linux/usb/ulpi.h>
+#include <linux/delay.h>
+#include <linux/mfd/mc13783.h>
+#include <linux/spi/spi.h>
+#include <linux/regulator/machine.h>
+
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
 #include <mach/hardware.h>
 #include <mach/common.h>
 #include <mach/iomux-mx27.h>
-#include <mach/mmc.h>
+#include <mach/ulpi.h>
+#include <mach/irqs.h>
+#include <mach/3ds_debugboard.h>
 
 #include "devices-imx27.h"
-#include "devices.h"
 
 #define SD1_EN_GPIO (GPIO_PORTB + 25)
+#define OTG_PHY_RESET_GPIO (GPIO_PORTB + 23)
+#define SPI2_SS0 (GPIO_PORTD + 21)
+#define EXPIO_PARENT_INT	(MXC_INTERNAL_IRQS + GPIO_PORTC + 28)
 
 static const int mx27pdk_pins[] __initconst = {
 	/* UART1 */
@@ -70,6 +80,24 @@ static const int mx27pdk_pins[] __initco
 	PE22_PF_SD1_CMD,
 	PE23_PF_SD1_CLK,
 	SD1_EN_GPIO | GPIO_GPIO | GPIO_OUT,
+	/* OTG */
+	OTG_PHY_RESET_GPIO | GPIO_GPIO | GPIO_OUT,
+	PC7_PF_USBOTG_DATA5,
+	PC8_PF_USBOTG_DATA6,
+	PC9_PF_USBOTG_DATA0,
+	PC10_PF_USBOTG_DATA2,
+	PC11_PF_USBOTG_DATA1,
+	PC12_PF_USBOTG_DATA4,
+	PC13_PF_USBOTG_DATA3,
+	PE0_PF_USBOTG_NXT,
+	PE1_PF_USBOTG_STP,
+	PE2_PF_USBOTG_DIR,
+	PE24_PF_USBOTG_CLK,
+	PE25_PF_USBOTG_DATA7,
+	/* CSPI2 */
+	PD22_PF_CSPI2_SCLK,
+	PD23_PF_CSPI2_MISO,
+	PD24_PF_CSPI2_MOSI,
 };
 
 static const struct imxuart_platform_data uart_pdata __initconst = {
@@ -92,7 +120,7 @@ static const uint32_t mx27_3ds_keymap[]
 	KEY(2, 3, KEY_F10),
 };
 
-static struct matrix_keymap_data mx27_3ds_keymap_data = {
+static const struct matrix_keymap_data mx27_3ds_keymap_data __initconst = {
 	.keymap		= mx27_3ds_keymap,
 	.keymap_size	= ARRAY_SIZE(mx27_3ds_keymap),
 };
@@ -109,7 +137,7 @@ static void mx27_3ds_sdhc1_exit(struct d
 	free_irq(IRQ_GPIOB(26), data);
 }
 
-static struct imxmmc_platform_data sdhc1_pdata = {
+static const struct imxmmc_platform_data sdhc1_pdata __initconst = {
 	.init = mx27_3ds_sdhc1_init,
 	.exit = mx27_3ds_sdhc1_exit,
 };
@@ -121,6 +149,111 @@ static void mx27_3ds_sdhc1_enable_level_
 	gpio_direction_output(SD1_EN_GPIO, 1);
 }
 
+
+static int otg_phy_init(void)
+{
+	gpio_request(OTG_PHY_RESET_GPIO, "usb-otg-reset");
+	gpio_direction_output(OTG_PHY_RESET_GPIO, 0);
+	mdelay(1);
+	gpio_set_value(OTG_PHY_RESET_GPIO, 1);
+	return 0;
+}
+
+#if defined(CONFIG_USB_ULPI)
+
+static struct mxc_usbh_platform_data otg_pdata __initdata = {
+	.portsc	= MXC_EHCI_MODE_ULPI,
+	.flags	= MXC_EHCI_INTERFACE_DIFF_UNI,
+};
+#endif
+
+static const struct fsl_usb2_platform_data otg_device_pdata __initconst = {
+	.operating_mode = FSL_USB2_DR_DEVICE,
+	.phy_mode       = FSL_USB2_PHY_ULPI,
+};
+
+static int otg_mode_host;
+
+static int __init mx27_3ds_otg_mode(char *options)
+{
+	if (!strcmp(options, "host"))
+		otg_mode_host = 1;
+	else if (!strcmp(options, "device"))
+		otg_mode_host = 0;
+	else
+		pr_info("otg_mode neither \"host\" nor \"device\". "
+			"Defaulting to device\n");
+	return 0;
+}
+__setup("otg_mode=", mx27_3ds_otg_mode);
+
+/* Regulators */
+static struct regulator_consumer_supply vmmc1_consumers[] = {
+	REGULATOR_SUPPLY("lcd_2v8", NULL),
+};
+
+static struct regulator_init_data vmmc1_init = {
+	.constraints = {
+		.min_uV	= 2800000,
+		.max_uV = 2800000,
+		.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+	},
+	.num_consumer_supplies = ARRAY_SIZE(vmmc1_consumers),
+	.consumer_supplies = vmmc1_consumers,
+};
+
+static struct regulator_consumer_supply vgen_consumers[] = {
+	REGULATOR_SUPPLY("vdd_lcdio", NULL),
+};
+
+static struct regulator_init_data vgen_init = {
+	.constraints = {
+		.min_uV	= 1800000,
+		.max_uV = 1800000,
+		.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+	},
+	.num_consumer_supplies = ARRAY_SIZE(vgen_consumers),
+	.consumer_supplies = vgen_consumers,
+};
+
+static struct mc13783_regulator_init_data mx27_3ds_regulators[] = {
+	{
+		.id = MC13783_REG_VMMC1,
+		.init_data = &vmmc1_init,
+	}, {
+		.id = MC13783_REG_VGEN,
+		.init_data = &vgen_init,
+	},
+};
+
+/* MC13783 */
+static struct mc13783_platform_data mc13783_pdata __initdata = {
+	.regulators = mx27_3ds_regulators,
+	.num_regulators = ARRAY_SIZE(mx27_3ds_regulators),
+	.flags  = MC13783_USE_REGULATOR,
+};
+
+/* SPI */
+static int spi2_internal_chipselect[] = {SPI2_SS0};
+
+static const struct spi_imx_master spi2_pdata __initconst = {
+	.chipselect	= spi2_internal_chipselect,
+	.num_chipselect	= ARRAY_SIZE(spi2_internal_chipselect),
+};
+
+static struct spi_board_info mx27_3ds_spi_devs[] __initdata = {
+	{
+		.modalias	= "mc13783",
+		.max_speed_hz	= 1000000,
+		.bus_num	= 1,
+		.chip_select	= 0, /* SS0 */
+		.platform_data	= &mc13783_pdata,
+		.irq = IRQ_GPIOC(14),
+		.mode = SPI_CS_HIGH,
+	},
+};
+
+
 static void __init mx27pdk_init(void)
 {
 	mxc_gpio_setup_multiple_pins(mx27pdk_pins, ARRAY_SIZE(mx27pdk_pins),
@@ -128,8 +261,27 @@ static void __init mx27pdk_init(void)
 	mx27_3ds_sdhc1_enable_level_translator();
 	imx27_add_imx_uart0(&uart_pdata);
 	imx27_add_fec(NULL);
-	mxc_register_device(&imx_kpp_device, &mx27_3ds_keymap_data);
-	mxc_register_device(&mxc_sdhc_device0, &sdhc1_pdata);
+	imx27_add_imx_keypad(&mx27_3ds_keymap_data);
+	imx27_add_mxc_mmc(0, &sdhc1_pdata);
+	imx27_add_imx2_wdt(NULL);
+	otg_phy_init();
+#if defined(CONFIG_USB_ULPI)
+	if (otg_mode_host) {
+		otg_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops,
+				ULPI_OTG_DRVVBUS | ULPI_OTG_DRVVBUS_EXT);
+
+		imx27_add_mxc_ehci_otg(&otg_pdata);
+	}
+#endif
+	if (!otg_mode_host)
+		imx27_add_fsl_usb2_udc(&otg_device_pdata);
+
+	imx27_add_spi_imx1(&spi2_pdata);
+	spi_register_board_info(mx27_3ds_spi_devs,
+						ARRAY_SIZE(mx27_3ds_spi_devs));
+
+	if (mxc_expio_init(MX27_CS5_BASE_ADDR, EXPIO_PARENT_INT))
+		pr_warn("Init of the debugboard failed, all devices on the debugboard are unusable.\n");
 }
 
 static void __init mx27pdk_timer_init(void)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-imx/mach-mx27ads.c linux-libre-2.6.38-gnu1/arch/arm/mach-imx/mach-mx27ads.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-imx/mach-mx27ads.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-imx/mach-mx27ads.c	2011-03-14 21:20:32.000000000 -0400
@@ -30,11 +30,8 @@
 #include <mach/gpio.h>
 #include <mach/iomux-mx27.h>
 #include <mach/mxc_nand.h>
-#include <mach/imxfb.h>
-#include <mach/mmc.h>
 
 #include "devices-imx27.h"
-#include "devices.h"
 
 /*
  * Base address of PBC controller, CS4
@@ -228,7 +225,7 @@ static struct imx_fb_videomode mx27ads_m
 	},
 };
 
-static struct imx_fb_platform_data mx27ads_fb_data = {
+static const struct imx_fb_platform_data mx27ads_fb_data __initconst = {
 	.mode = mx27ads_modes,
 	.num_modes = ARRAY_SIZE(mx27ads_modes),
 
@@ -272,19 +269,18 @@ static void mx27ads_sdhc2_exit(struct de
 	free_irq(IRQ_GPIOB(7), data);
 }
 
-static struct imxmmc_platform_data sdhc1_pdata = {
+static const struct imxmmc_platform_data sdhc1_pdata __initconst = {
 	.init = mx27ads_sdhc1_init,
 	.exit = mx27ads_sdhc1_exit,
 };
 
-static struct imxmmc_platform_data sdhc2_pdata = {
+static const struct imxmmc_platform_data sdhc2_pdata __initconst = {
 	.init = mx27ads_sdhc2_init,
 	.exit = mx27ads_sdhc2_exit,
 };
 
 static struct platform_device *platform_devices[] __initdata = {
 	&mx27ads_nor_mtd_device,
-	&mxc_w1_master_device,
 };
 
 static const struct imxuart_platform_data uart_pdata __initconst = {
@@ -308,12 +304,13 @@ static void __init mx27ads_board_init(vo
 	i2c_register_board_info(1, mx27ads_i2c_devices,
 				ARRAY_SIZE(mx27ads_i2c_devices));
 	imx27_add_imx_i2c(1, &mx27ads_i2c1_data);
-	mxc_register_device(&mxc_fb_device, &mx27ads_fb_data);
-	mxc_register_device(&mxc_sdhc_device0, &sdhc1_pdata);
-	mxc_register_device(&mxc_sdhc_device1, &sdhc2_pdata);
+	imx27_add_imx_fb(&mx27ads_fb_data);
+	imx27_add_mxc_mmc(0, &sdhc1_pdata);
+	imx27_add_mxc_mmc(1, &sdhc2_pdata);
 
 	imx27_add_fec(NULL);
 	platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
+	imx27_add_mxc_w1(NULL);
 }
 
 static void __init mx27ads_timer_init(void)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-imx/mach-mxt_td60.c linux-libre-2.6.38-gnu1/arch/arm/mach-imx/mach-mxt_td60.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-imx/mach-mxt_td60.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-imx/mach-mxt_td60.c	2011-03-14 21:20:32.000000000 -0400
@@ -31,11 +31,8 @@
 #include <mach/iomux-mx27.h>
 #include <mach/mxc_nand.h>
 #include <linux/i2c/pca953x.h>
-#include <mach/imxfb.h>
-#include <mach/mmc.h>
 
 #include "devices-imx27.h"
-#include "devices.h"
 
 static const int mxt_td60_pins[] __initconst = {
 	/* UART0 */
@@ -196,7 +193,7 @@ static struct imx_fb_videomode mxt_td60_
 	},
 };
 
-static struct imx_fb_platform_data mxt_td60_fb_data = {
+static const struct imx_fb_platform_data mxt_td60_fb_data __initconst = {
 	.mode = mxt_td60_modes,
 	.num_modes = ARRAY_SIZE(mxt_td60_modes),
 
@@ -226,7 +223,7 @@ static void mxt_td60_sdhc1_exit(struct d
 	free_irq(IRQ_GPIOF(8), data);
 }
 
-static struct imxmmc_platform_data sdhc1_pdata = {
+static const struct imxmmc_platform_data sdhc1_pdata __initconst = {
 	.init = mxt_td60_sdhc1_init,
 	.exit = mxt_td60_sdhc1_exit,
 };
@@ -253,8 +250,8 @@ static void __init mxt_td60_board_init(v
 
 	imx27_add_imx_i2c(0, &mxt_td60_i2c0_data);
 	imx27_add_imx_i2c(1, &mxt_td60_i2c1_data);
-	mxc_register_device(&mxc_fb_device, &mxt_td60_fb_data);
-	mxc_register_device(&mxc_sdhc_device0, &sdhc1_pdata);
+	imx27_add_imx_fb(&mxt_td60_fb_data);
+	imx27_add_mxc_mmc(0, &sdhc1_pdata);
 	imx27_add_fec(NULL);
 }
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-imx/mach-pca100.c linux-libre-2.6.38-gnu1/arch/arm/mach-imx/mach-pca100.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-imx/mach-pca100.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-imx/mach-pca100.c	2011-03-14 21:20:32.000000000 -0400
@@ -29,7 +29,6 @@
 #include <linux/gpio.h>
 #include <linux/usb/otg.h>
 #include <linux/usb/ulpi.h>
-#include <linux/fsl_devices.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
@@ -40,13 +39,9 @@
 #include <mach/audmux.h>
 #include <mach/mxc_nand.h>
 #include <mach/irqs.h>
-#include <mach/mmc.h>
-#include <mach/mxc_ehci.h>
 #include <mach/ulpi.h>
-#include <mach/imxfb.h>
 
 #include "devices-imx27.h"
-#include "devices.h"
 
 #define OTG_PHY_CS_GPIO (GPIO_PORTB + 23)
 #define USBH2_PHY_CS_GPIO (GPIO_PORTB + 24)
@@ -171,11 +166,6 @@ pca100_nand_board_info __initconst = {
 	.hw_ecc = 1,
 };
 
-static struct platform_device *platform_devices[] __initdata = {
-	&mxc_w1_master_device,
-	&mxc_wdt,
-};
-
 static const struct imxi2c_platform_data pca100_i2c1_data __initconst = {
 	.bitrate = 100000,
 };
@@ -274,7 +264,7 @@ static void pca100_sdhc2_exit(struct dev
 	free_irq(IRQ_GPIOC(29), data);
 }
 
-static struct imxmmc_platform_data sdhc_pdata = {
+static const struct imxmmc_platform_data sdhc_pdata __initconst = {
 	.init = pca100_sdhc2_init,
 	.exit = pca100_sdhc2_exit,
 };
@@ -286,7 +276,7 @@ static int otg_phy_init(struct platform_
 	return 0;
 }
 
-static struct mxc_usbh_platform_data otg_pdata = {
+static struct mxc_usbh_platform_data otg_pdata __initdata = {
 	.init	= otg_phy_init,
 	.portsc	= MXC_EHCI_MODE_ULPI,
 	.flags	= MXC_EHCI_INTERFACE_DIFF_UNI,
@@ -298,14 +288,14 @@ static int usbh2_phy_init(struct platfor
 	return 0;
 }
 
-static struct mxc_usbh_platform_data usbh2_pdata = {
+static struct mxc_usbh_platform_data usbh2_pdata __initdata = {
 	.init	= usbh2_phy_init,
 	.portsc	= MXC_EHCI_MODE_ULPI,
 	.flags	= MXC_EHCI_INTERFACE_DIFF_UNI,
 };
 #endif
 
-static struct fsl_usb2_platform_data otg_device_pdata = {
+static const struct fsl_usb2_platform_data otg_device_pdata __initconst = {
 	.operating_mode = FSL_USB2_DR_DEVICE,
 	.phy_mode       = FSL_USB2_PHY_ULPI,
 };
@@ -355,7 +345,7 @@ static struct imx_fb_videomode pca100_fb
 	},
 };
 
-static struct imx_fb_platform_data pca100_fb_data = {
+static const struct imx_fb_platform_data pca100_fb_data __initconst = {
 	.mode = pca100_fb_modes,
 	.num_modes = ARRAY_SIZE(pca100_fb_modes),
 
@@ -389,7 +379,7 @@ static void __init pca100_init(void)
 
 	imx27_add_imx_uart0(&uart_pdata);
 
-	mxc_register_device(&mxc_sdhc_device1, &sdhc_pdata);
+	imx27_add_mxc_mmc(1, &sdhc_pdata);
 
 	imx27_add_mxc_nand(&pca100_nand_board_info);
 
@@ -417,23 +407,24 @@ static void __init pca100_init(void)
 		otg_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops,
 				ULPI_OTG_DRVVBUS | ULPI_OTG_DRVVBUS_EXT);
 
-		mxc_register_device(&mxc_otg_host, &otg_pdata);
+		imx27_add_mxc_ehci_otg(&otg_pdata);
 	}
 
 	usbh2_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops,
 				ULPI_OTG_DRVVBUS | ULPI_OTG_DRVVBUS_EXT);
 
-	mxc_register_device(&mxc_usbh2, &usbh2_pdata);
+	imx27_add_mxc_ehci_hs(2, &usbh2_pdata);
 #endif
 	if (!otg_mode_host) {
 		gpio_set_value(OTG_PHY_CS_GPIO, 0);
-		mxc_register_device(&mxc_otg_udc_device, &otg_device_pdata);
+		imx27_add_fsl_usb2_udc(&otg_device_pdata);
 	}
 
-	mxc_register_device(&mxc_fb_device, &pca100_fb_data);
+	imx27_add_imx_fb(&pca100_fb_data);
 
 	imx27_add_fec(NULL);
-	platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
+	imx27_add_imx2_wdt(NULL);
+	imx27_add_mxc_w1(NULL);
 }
 
 static void __init pca100_timer_init(void)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-imx/mach-pcm038.c linux-libre-2.6.38-gnu1/arch/arm/mach-imx/mach-pcm038.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-imx/mach-pcm038.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-imx/mach-pcm038.c	2011-03-14 21:20:32.000000000 -0400
@@ -37,11 +37,9 @@
 #include <mach/hardware.h>
 #include <mach/iomux-mx27.h>
 #include <mach/mxc_nand.h>
-#include <mach/mxc_ehci.h>
 #include <mach/ulpi.h>
 
 #include "devices-imx27.h"
-#include "devices.h"
 
 static const int pcm038_pins[] __initconst = {
 	/* UART1 */
@@ -172,9 +170,7 @@ pcm038_nand_board_info __initconst = {
 
 static struct platform_device *platform_devices[] __initdata = {
 	&pcm038_nor_mtd_device,
-	&mxc_w1_master_device,
 	&pcm038_sram_mtd_device,
-	&mxc_wdt,
 };
 
 /* On pcm038 there's a sram attached to CS1, we enable the chipselect here and
@@ -214,7 +210,7 @@ static const struct spi_imx_master pcm03
 
 static struct regulator_consumer_supply sdhc1_consumers[] = {
 	{
-		.dev	= &mxc_sdhc_device1.dev,
+		.dev_name = "mxc-mmc.1",
 		.supply	= "sdhc_vcc",
 	},
 };
@@ -258,10 +254,10 @@ static struct regulator_init_data cam_da
 
 static struct mc13783_regulator_init_data pcm038_regulators[] = {
 	{
-		.id = MC13783_REGU_VCAM,
+		.id = MC13783_REG_VCAM,
 		.init_data = &cam_data,
 	}, {
-		.id = MC13783_REGU_VMMC1,
+		.id = MC13783_REG_VMMC1,
 		.init_data = &sdhc1_data,
 	},
 };
@@ -285,7 +281,7 @@ static struct spi_board_info pcm038_spi_
 	}
 };
 
-static struct mxc_usbh_platform_data usbh2_pdata = {
+static const struct mxc_usbh_platform_data usbh2_pdata __initconst = {
 	.portsc	= MXC_EHCI_MODE_ULPI,
 	.flags	= MXC_EHCI_POWER_PINS_ENABLED | MXC_EHCI_INTERFACE_DIFF_UNI,
 };
@@ -322,10 +318,12 @@ static void __init pcm038_init(void)
 	spi_register_board_info(pcm038_spi_board_info,
 				ARRAY_SIZE(pcm038_spi_board_info));
 
-	mxc_register_device(&mxc_usbh2, &usbh2_pdata);
+	imx27_add_mxc_ehci_hs(2, &usbh2_pdata);
 
 	imx27_add_fec(NULL);
 	platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
+	imx27_add_imx2_wdt(NULL);
+	imx27_add_mxc_w1(NULL);
 
 #ifdef CONFIG_MACH_PCM970_BASEBOARD
 	pcm970_baseboard_init();
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-imx/mach-scb9328.c linux-libre-2.6.38-gnu1/arch/arm/mach-imx/mach-scb9328.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-imx/mach-scb9328.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-imx/mach-scb9328.c	2011-03-14 21:20:32.000000000 -0400
@@ -25,7 +25,6 @@
 #include <mach/iomux-mx1.h>
 
 #include "devices-imx1.h"
-#include "devices.h"
 
 /*
  * This scb9328 has a 32MiB flash
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-imx/Makefile linux-libre-2.6.38-gnu1/arch/arm/mach-imx/Makefile
--- linux-libre-2.6.37-gnu1/arch/arm/mach-imx/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-imx/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -4,13 +4,13 @@
 
 # Object file lists.
 
-obj-y	:=  devices.o
-
 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_ARCH_MX25) += clock-imx25.o mm-imx25.o
+
 obj-$(CONFIG_MACH_MX27) += cpu-imx27.o pm-imx27.o
 obj-$(CONFIG_MACH_MX27) += clock-imx27.o mm-imx27.o
 
@@ -22,6 +22,10 @@ obj-$(CONFIG_MACH_SCB9328) += mach-scb93
 
 obj-$(CONFIG_MACH_MX21ADS) += mach-mx21ads.o
 
+obj-$(CONFIG_MACH_MX25_3DS) += mach-mx25_3ds.o
+obj-$(CONFIG_MACH_EUKREA_CPUIMX25) += mach-eukrea_cpuimx25.o
+obj-$(CONFIG_MACH_EUKREA_MBIMXSD25_BASEBOARD) += eukrea_mbimxsd25-baseboard.o
+
 obj-$(CONFIG_MACH_MX27ADS) += mach-mx27ads.o
 obj-$(CONFIG_MACH_PCM038) += mach-pcm038.o
 obj-$(CONFIG_MACH_PCM970_BASEBOARD) += pcm970-baseboard.o
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-imx/Makefile.boot linux-libre-2.6.38-gnu1/arch/arm/mach-imx/Makefile.boot
--- linux-libre-2.6.37-gnu1/arch/arm/mach-imx/Makefile.boot	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-imx/Makefile.boot	2011-03-14 21:20:32.000000000 -0400
@@ -6,6 +6,10 @@ zreladdr-$(CONFIG_MACH_MX21)	:= 0xC00080
 params_phys-$(CONFIG_MACH_MX21)	:= 0xC0000100
 initrd_phys-$(CONFIG_MACH_MX21)	:= 0xC0800000
 
+zreladdr-$(CONFIG_ARCH_MX25)	:= 0x80008000
+params_phys-$(CONFIG_ARCH_MX25)	:= 0x80000100
+initrd_phys-$(CONFIG_ARCH_MX25)	:= 0x80800000
+
 zreladdr-$(CONFIG_MACH_MX27)	:= 0xA0008000
 params_phys-$(CONFIG_MACH_MX27)	:= 0xA0000100
 initrd_phys-$(CONFIG_MACH_MX27)	:= 0xA0800000
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-imx/mm-imx1.c linux-libre-2.6.38-gnu1/arch/arm/mach-imx/mm-imx1.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-imx/mm-imx1.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-imx/mm-imx1.c	2011-03-14 21:20:32.000000000 -0400
@@ -25,12 +25,7 @@
 #include <mach/hardware.h>
 
 static struct map_desc imx_io_desc[] __initdata = {
-	{
-		.virtual = MX1_IO_BASE_ADDR_VIRT,
-		.pfn = __phys_to_pfn(MX1_IO_BASE_ADDR),
-		.length = MX1_IO_SIZE,
-		.type = MT_DEVICE
-	}
+	imx_map_entry(MX1, IO, MT_DEVICE),
 };
 
 void __init mx1_map_io(void)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-imx/mm-imx21.c linux-libre-2.6.38-gnu1/arch/arm/mach-imx/mm-imx21.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-imx/mm-imx21.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-imx/mm-imx21.c	2011-03-14 21:20:32.000000000 -0400
@@ -35,33 +35,18 @@ static struct map_desc imx21_io_desc[] _
 	 * - ROM Patch
 	 * - and some reserved space
 	 */
-	{
-		.virtual = MX21_AIPI_BASE_ADDR_VIRT,
-		.pfn = __phys_to_pfn(MX21_AIPI_BASE_ADDR),
-		.length = MX21_AIPI_SIZE,
-		.type = MT_DEVICE
-	},
+	imx_map_entry(MX21, AIPI, MT_DEVICE),
 	/*
 	 * this fixed mapping covers:
 	 * - CSI
 	 * - ATA
 	 */
-	{
-		.virtual = MX21_SAHB1_BASE_ADDR_VIRT,
-		.pfn = __phys_to_pfn(MX21_SAHB1_BASE_ADDR),
-		.length = MX21_SAHB1_SIZE,
-		.type = MT_DEVICE
-	},
+	imx_map_entry(MX21, SAHB1, MT_DEVICE),
 	/*
 	 * this fixed mapping covers:
 	 * - EMI
 	 */
-	{
-		.virtual = MX21_X_MEMC_BASE_ADDR_VIRT,
-		.pfn = __phys_to_pfn(MX21_X_MEMC_BASE_ADDR),
-		.length = MX21_X_MEMC_SIZE,
-		.type = MT_DEVICE
-	},
+	imx_map_entry(MX21, X_MEMC, MT_DEVICE),
 };
 
 /*
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-imx/mm-imx25.c linux-libre-2.6.38-gnu1/arch/arm/mach-imx/mm-imx25.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-imx/mm-imx25.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-imx/mm-imx25.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,62 @@
+/*
+ *  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/hardware.h>
+#include <mach/mx25.h>
+#include <mach/iomux-v3.h>
+
+/*
+ * This table defines static virtual address mappings for I/O regions.
+ * These are the mappings common across all MX25 boards.
+ */
+static struct map_desc mx25_io_desc[] __initdata = {
+	imx_map_entry(MX25, AVIC, MT_DEVICE_NONSHARED),
+	imx_map_entry(MX25, AIPS1, MT_DEVICE_NONSHARED),
+	imx_map_entry(MX25, AIPS2, 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 mx25_map_io(void)
+{
+	mxc_set_cpu_type(MXC_CPU_MX25);
+	mxc_iomux_v3_init(MX25_IO_ADDRESS(MX25_IOMUXC_BASE_ADDR));
+	mxc_arch_reset_init(MX25_IO_ADDRESS(MX25_WDOG_BASE_ADDR));
+
+	iotable_init(mx25_io_desc, ARRAY_SIZE(mx25_io_desc));
+}
+
+int imx25_register_gpios(void);
+
+void __init mx25_init_irq(void)
+{
+	mxc_init_irq(MX25_IO_ADDRESS(MX25_AVIC_BASE_ADDR));
+	imx25_register_gpios();
+}
+
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-imx/mm-imx27.c linux-libre-2.6.38-gnu1/arch/arm/mach-imx/mm-imx27.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-imx/mm-imx27.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-imx/mm-imx27.c	2011-03-14 21:20:32.000000000 -0400
@@ -35,33 +35,18 @@ static struct map_desc imx27_io_desc[] _
 	 * - ROM Patch
 	 * - and some reserved space
 	 */
-	{
-		.virtual = MX27_AIPI_BASE_ADDR_VIRT,
-		.pfn = __phys_to_pfn(MX27_AIPI_BASE_ADDR),
-		.length = MX27_AIPI_SIZE,
-		.type = MT_DEVICE
-	},
+	imx_map_entry(MX27, AIPI, MT_DEVICE),
 	/*
 	 * this fixed mapping covers:
 	 * - CSI
 	 * - ATA
 	 */
-	{
-		.virtual = MX27_SAHB1_BASE_ADDR_VIRT,
-		.pfn = __phys_to_pfn(MX27_SAHB1_BASE_ADDR),
-		.length = MX27_SAHB1_SIZE,
-		.type = MT_DEVICE
-	},
+	imx_map_entry(MX27, SAHB1, MT_DEVICE),
 	/*
 	 * this fixed mapping covers:
 	 * - EMI
 	 */
-	{
-		.virtual = MX27_X_MEMC_BASE_ADDR_VIRT,
-		.pfn = __phys_to_pfn(MX27_X_MEMC_BASE_ADDR),
-		.length = MX27_X_MEMC_SIZE,
-		.type = MT_DEVICE
-	},
+	imx_map_entry(MX27, X_MEMC, MT_DEVICE),
 };
 
 /*
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-imx/pcm970-baseboard.c linux-libre-2.6.38-gnu1/arch/arm/mach-imx/pcm970-baseboard.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-imx/pcm970-baseboard.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-imx/pcm970-baseboard.c	2011-03-14 21:20:32.000000000 -0400
@@ -25,11 +25,9 @@
 
 #include <mach/common.h>
 #include <mach/iomux-mx27.h>
-#include <mach/imxfb.h>
 #include <mach/hardware.h>
-#include <mach/mmc.h>
 
-#include "devices.h"
+#include "devices-imx27.h"
 
 static const int pcm970_pins[] __initconst = {
 	/* SDHC */
@@ -119,7 +117,7 @@ static void pcm970_sdhc2_exit(struct dev
 	gpio_free(GPIO_PORTC + 28);
 }
 
-static struct imxmmc_platform_data sdhc_pdata = {
+static const struct imxmmc_platform_data sdhc_pdata __initconst = {
 	.get_ro = pcm970_sdhc2_get_ro,
 	.init = pcm970_sdhc2_init,
 	.exit = pcm970_sdhc2_exit,
@@ -179,7 +177,7 @@ static struct imx_fb_videomode pcm970_mo
 	},
 };
 
-static struct imx_fb_platform_data pcm038_fb_data = {
+static const struct imx_fb_platform_data pcm038_fb_data __initconst = {
 	.mode = pcm970_modes,
 	.num_modes = ARRAY_SIZE(pcm970_modes),
 
@@ -226,8 +224,8 @@ void __init pcm970_baseboard_init(void)
 	mxc_gpio_setup_multiple_pins(pcm970_pins, ARRAY_SIZE(pcm970_pins),
 			"PCM970");
 
-	mxc_register_device(&mxc_fb_device, &pcm038_fb_data);
+	imx27_add_imx_fb(&pcm038_fb_data);
 	mxc_gpio_mode(GPIO_PORTC | 28 | GPIO_GPIO | GPIO_IN);
-	mxc_register_device(&mxc_sdhc_device1, &sdhc_pdata);
+	imx27_add_mxc_mmc(1, &sdhc_pdata);
 	platform_device_register(&pcm970_sja1000);
 }
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-imx/pm-imx27.c linux-libre-2.6.38-gnu1/arch/arm/mach-imx/pm-imx27.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-imx/pm-imx27.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-imx/pm-imx27.c	2011-03-14 21:20:32.000000000 -0400
@@ -32,13 +32,16 @@ static int mx27_suspend_enter(suspend_st
 	return 0;
 }
 
-static struct platform_suspend_ops mx27_suspend_ops = {
+static const struct platform_suspend_ops mx27_suspend_ops = {
 	.enter = mx27_suspend_enter,
 	.valid = suspend_valid_only_mem,
 };
 
 static int __init mx27_pm_init(void)
 {
+	if (!cpu_is_mx27())
+		return 0;
+
 	suspend_set_ops(&mx27_suspend_ops);
 	return 0;
 }
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-integrator/core.c linux-libre-2.6.38-gnu1/arch/arm/mach-integrator/core.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-integrator/core.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-integrator/core.c	2011-03-14 21:20:32.000000000 -0400
@@ -21,9 +21,8 @@
 #include <linux/amba/bus.h>
 #include <linux/amba/serial.h>
 #include <linux/io.h>
+#include <linux/clkdev.h>
 
-#include <asm/clkdev.h>
-#include <mach/clkdev.h>
 #include <mach/hardware.h>
 #include <mach/platform.h>
 #include <asm/irq.h>
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-integrator/cpu.c linux-libre-2.6.38-gnu1/arch/arm/mach-integrator/cpu.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-integrator/cpu.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-integrator/cpu.c	2011-03-14 21:20:32.000000000 -0400
@@ -173,7 +173,7 @@ static unsigned int integrator_get(unsig
 
 	if (machine_is_integrator()) {
 		vco.s = (cm_osc >> 8) & 7;
-	} else if (machine_is_cintegrator()) {
+	} else {
 		vco.s = 1;
 	}
 	vco.v = cm_osc & 255;
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-integrator/impd1.c linux-libre-2.6.38-gnu1/arch/arm/mach-integrator/impd1.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-integrator/impd1.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-integrator/impd1.c	2011-03-14 21:20:32.000000000 -0400
@@ -22,9 +22,8 @@
 #include <linux/amba/clcd.h>
 #include <linux/io.h>
 #include <linux/slab.h>
+#include <linux/clkdev.h>
 
-#include <asm/clkdev.h>
-#include <mach/clkdev.h>
 #include <asm/hardware/icst.h>
 #include <mach/lm.h>
 #include <mach/impd1.h>
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-integrator/integrator_ap.c linux-libre-2.6.38-gnu1/arch/arm/mach-integrator/integrator_ap.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-integrator/integrator_ap.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-integrator/integrator_ap.c	2011-03-14 21:20:32.000000000 -0400
@@ -156,21 +156,21 @@ static void __init ap_map_io(void)
 
 #define INTEGRATOR_SC_VALID_INT	0x003fffff
 
-static void sc_mask_irq(unsigned int irq)
+static void sc_mask_irq(struct irq_data *d)
 {
-	writel(1 << irq, VA_IC_BASE + IRQ_ENABLE_CLEAR);
+	writel(1 << d->irq, VA_IC_BASE + IRQ_ENABLE_CLEAR);
 }
 
-static void sc_unmask_irq(unsigned int irq)
+static void sc_unmask_irq(struct irq_data *d)
 {
-	writel(1 << irq, VA_IC_BASE + IRQ_ENABLE_SET);
+	writel(1 << d->irq, VA_IC_BASE + IRQ_ENABLE_SET);
 }
 
 static struct irq_chip sc_chip = {
-	.name	= "SC",
-	.ack	= sc_mask_irq,
-	.mask	= sc_mask_irq,
-	.unmask = sc_unmask_irq,
+	.name		= "SC",
+	.irq_ack	= sc_mask_irq,
+	.irq_mask	= sc_mask_irq,
+	.irq_unmask	= sc_unmask_irq,
 };
 
 static void __init ap_init_irq(void)
@@ -372,7 +372,6 @@ static struct clocksource clocksource_ti
 	.rating		= 200,
 	.read		= timersp_read,
 	.mask		= CLOCKSOURCE_MASK(16),
-	.shift		= 16,
 	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
@@ -390,8 +389,7 @@ static void integrator_clocksource_init(
 	writel(ctrl, base + TIMER_CTRL);
 	writel(0xffff, base + TIMER_LOAD);
 
-	cs->mult = clocksource_khz2mult(khz, cs->shift);
-	clocksource_register(cs);
+	clocksource_register_khz(cs, khz);
 }
 
 static void __iomem * const clkevt_base = (void __iomem *)TIMER1_VA_BASE;
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-integrator/integrator_cp.c linux-libre-2.6.38-gnu1/arch/arm/mach-integrator/integrator_cp.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-integrator/integrator_cp.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-integrator/integrator_cp.c	2011-03-14 21:20:32.000000000 -0400
@@ -21,9 +21,8 @@
 #include <linux/amba/mmci.h>
 #include <linux/io.h>
 #include <linux/gfp.h>
+#include <linux/clkdev.h>
 
-#include <asm/clkdev.h>
-#include <mach/clkdev.h>
 #include <mach/hardware.h>
 #include <mach/platform.h>
 #include <asm/irq.h>
@@ -41,7 +40,7 @@
 #include <asm/mach/map.h>
 #include <asm/mach/time.h>
 
-#include <plat/timer-sp.h>
+#include <asm/hardware/timer-sp.h>
 
 #include "common.h"
 
@@ -147,61 +146,61 @@ static void __init intcp_map_io(void)
 #define sic_writel	__raw_writel
 #define sic_readl	__raw_readl
 
-static void cic_mask_irq(unsigned int irq)
+static void cic_mask_irq(struct irq_data *d)
 {
-	irq -= IRQ_CIC_START;
+	unsigned int irq = d->irq - IRQ_CIC_START;
 	cic_writel(1 << irq, INTCP_VA_CIC_BASE + IRQ_ENABLE_CLEAR);
 }
 
-static void cic_unmask_irq(unsigned int irq)
+static void cic_unmask_irq(struct irq_data *d)
 {
-	irq -= IRQ_CIC_START;
+	unsigned int irq = d->irq - IRQ_CIC_START;
 	cic_writel(1 << irq, INTCP_VA_CIC_BASE + IRQ_ENABLE_SET);
 }
 
 static struct irq_chip cic_chip = {
-	.name	= "CIC",
-	.ack	= cic_mask_irq,
-	.mask	= cic_mask_irq,
-	.unmask	= cic_unmask_irq,
+	.name		= "CIC",
+	.irq_ack	= cic_mask_irq,
+	.irq_mask	= cic_mask_irq,
+	.irq_unmask	= cic_unmask_irq,
 };
 
-static void pic_mask_irq(unsigned int irq)
+static void pic_mask_irq(struct irq_data *d)
 {
-	irq -= IRQ_PIC_START;
+	unsigned int irq = d->irq - IRQ_PIC_START;
 	pic_writel(1 << irq, INTCP_VA_PIC_BASE + IRQ_ENABLE_CLEAR);
 }
 
-static void pic_unmask_irq(unsigned int irq)
+static void pic_unmask_irq(struct irq_data *d)
 {
-	irq -= IRQ_PIC_START;
+	unsigned int irq = d->irq - IRQ_PIC_START;
 	pic_writel(1 << irq, INTCP_VA_PIC_BASE + IRQ_ENABLE_SET);
 }
 
 static struct irq_chip pic_chip = {
-	.name	= "PIC",
-	.ack	= pic_mask_irq,
-	.mask	= pic_mask_irq,
-	.unmask = pic_unmask_irq,
+	.name		= "PIC",
+	.irq_ack	= pic_mask_irq,
+	.irq_mask	= pic_mask_irq,
+	.irq_unmask	= pic_unmask_irq,
 };
 
-static void sic_mask_irq(unsigned int irq)
+static void sic_mask_irq(struct irq_data *d)
 {
-	irq -= IRQ_SIC_START;
+	unsigned int irq = d->irq - IRQ_SIC_START;
 	sic_writel(1 << irq, INTCP_VA_SIC_BASE + IRQ_ENABLE_CLEAR);
 }
 
-static void sic_unmask_irq(unsigned int irq)
+static void sic_unmask_irq(struct irq_data *d)
 {
-	irq -= IRQ_SIC_START;
+	unsigned int irq = d->irq - IRQ_SIC_START;
 	sic_writel(1 << irq, INTCP_VA_SIC_BASE + IRQ_ENABLE_SET);
 }
 
 static struct irq_chip sic_chip = {
-	.name	= "SIC",
-	.ack	= sic_mask_irq,
-	.mask	= sic_mask_irq,
-	.unmask	= sic_unmask_irq,
+	.name		= "SIC",
+	.irq_ack	= sic_mask_irq,
+	.irq_mask	= sic_mask_irq,
+	.irq_unmask	= sic_unmask_irq,
 };
 
 static void
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-integrator/Kconfig linux-libre-2.6.38-gnu1/arch/arm/mach-integrator/Kconfig
--- linux-libre-2.6.37-gnu1/arch/arm/mach-integrator/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-integrator/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -4,6 +4,7 @@ menu "Integrator Options"
 
 config ARCH_INTEGRATOR_AP
 	bool "Support Integrator/AP and Integrator/PP2 platforms"
+	select MIGHT_HAVE_PCI
 	help
 	  Include support for the ARM(R) Integrator/AP and
 	  Integrator/PP2 platforms.
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-iop13xx/include/mach/io.h linux-libre-2.6.38-gnu1/arch/arm/mach-iop13xx/include/mach/io.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-iop13xx/include/mach/io.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-iop13xx/include/mach/io.h	2011-03-14 21:20:32.000000000 -0400
@@ -35,7 +35,7 @@ extern u32 iop13xx_atux_mem_base;
 extern size_t iop13xx_atue_mem_size;
 extern size_t iop13xx_atux_mem_size;
 
-#define __arch_ioremap(a, s, f) __iop13xx_ioremap(a, s, f)
-#define __arch_iounmap(a)	 __iop13xx_iounmap(a)
+#define __arch_ioremap	__iop13xx_ioremap
+#define __arch_iounmap	__iop13xx_iounmap
 
 #endif
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-iop13xx/include/mach/memory.h linux-libre-2.6.38-gnu1/arch/arm/mach-iop13xx/include/mach/memory.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-iop13xx/include/mach/memory.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-iop13xx/include/mach/memory.h	2011-03-14 21:20:32.000000000 -0400
@@ -58,13 +58,13 @@ static inline unsigned long __lbus_to_vi
 		__dma;							\
 	})
 
-#define __arch_page_to_dma(dev, page)					\
+#define __arch_pfn_to_dma(dev, pfn)					\
 	({								\
 		/* __is_lbus_virt() can never be true for RAM pages */	\
-		(dma_addr_t)page_to_phys(page);				\
+		(dma_addr_t)__pfn_to_phys(pfn);				\
 	})
 
-#define __arch_dma_to_page(dev, addr)	phys_to_page(addr)
+#define __arch_dma_to_pfn(dev, addr)	__phys_to_pfn(addr)
 
 #endif /* CONFIG_ARCH_IOP13XX */
 #endif /* !ASSEMBLY */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-iop13xx/irq.c linux-libre-2.6.38-gnu1/arch/arm/mach-iop13xx/irq.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-iop13xx/irq.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-iop13xx/irq.c	2011-03-14 21:20:32.000000000 -0400
@@ -123,79 +123,79 @@ static void write_intsize(u32 val)
 
 /* 0 = Interrupt Masked and 1 = Interrupt not masked */
 static void
-iop13xx_irq_mask0 (unsigned int irq)
+iop13xx_irq_mask0 (struct irq_data *d)
 {
-	write_intctl_0(read_intctl_0() & ~(1 << (irq - 0)));
+	write_intctl_0(read_intctl_0() & ~(1 << (d->irq - 0)));
 }
 
 static void
-iop13xx_irq_mask1 (unsigned int irq)
+iop13xx_irq_mask1 (struct irq_data *d)
 {
-	write_intctl_1(read_intctl_1() & ~(1 << (irq - 32)));
+	write_intctl_1(read_intctl_1() & ~(1 << (d->irq - 32)));
 }
 
 static void
-iop13xx_irq_mask2 (unsigned int irq)
+iop13xx_irq_mask2 (struct irq_data *d)
 {
-	write_intctl_2(read_intctl_2() & ~(1 << (irq - 64)));
+	write_intctl_2(read_intctl_2() & ~(1 << (d->irq - 64)));
 }
 
 static void
-iop13xx_irq_mask3 (unsigned int irq)
+iop13xx_irq_mask3 (struct irq_data *d)
 {
-	write_intctl_3(read_intctl_3() & ~(1 << (irq - 96)));
+	write_intctl_3(read_intctl_3() & ~(1 << (d->irq - 96)));
 }
 
 static void
-iop13xx_irq_unmask0(unsigned int irq)
+iop13xx_irq_unmask0(struct irq_data *d)
 {
-	write_intctl_0(read_intctl_0() | (1 << (irq - 0)));
+	write_intctl_0(read_intctl_0() | (1 << (d->irq - 0)));
 }
 
 static void
-iop13xx_irq_unmask1(unsigned int irq)
+iop13xx_irq_unmask1(struct irq_data *d)
 {
-	write_intctl_1(read_intctl_1() | (1 << (irq - 32)));
+	write_intctl_1(read_intctl_1() | (1 << (d->irq - 32)));
 }
 
 static void
-iop13xx_irq_unmask2(unsigned int irq)
+iop13xx_irq_unmask2(struct irq_data *d)
 {
-	write_intctl_2(read_intctl_2() | (1 << (irq - 64)));
+	write_intctl_2(read_intctl_2() | (1 << (d->irq - 64)));
 }
 
 static void
-iop13xx_irq_unmask3(unsigned int irq)
+iop13xx_irq_unmask3(struct irq_data *d)
 {
-	write_intctl_3(read_intctl_3() | (1 << (irq - 96)));
+	write_intctl_3(read_intctl_3() | (1 << (d->irq - 96)));
 }
 
 static struct irq_chip iop13xx_irqchip1 = {
-	.name	= "IOP13xx-1",
-	.ack    = iop13xx_irq_mask0,
-	.mask   = iop13xx_irq_mask0,
-	.unmask = iop13xx_irq_unmask0,
+	.name       = "IOP13xx-1",
+	.irq_ack    = iop13xx_irq_mask0,
+	.irq_mask   = iop13xx_irq_mask0,
+	.irq_unmask = iop13xx_irq_unmask0,
 };
 
 static struct irq_chip iop13xx_irqchip2 = {
-	.name	= "IOP13xx-2",
-	.ack    = iop13xx_irq_mask1,
-	.mask   = iop13xx_irq_mask1,
-	.unmask = iop13xx_irq_unmask1,
+	.name       = "IOP13xx-2",
+	.irq_ack    = iop13xx_irq_mask1,
+	.irq_mask   = iop13xx_irq_mask1,
+	.irq_unmask = iop13xx_irq_unmask1,
 };
 
 static struct irq_chip iop13xx_irqchip3 = {
-	.name	= "IOP13xx-3",
-	.ack    = iop13xx_irq_mask2,
-	.mask   = iop13xx_irq_mask2,
-	.unmask = iop13xx_irq_unmask2,
+	.name       = "IOP13xx-3",
+	.irq_ack    = iop13xx_irq_mask2,
+	.irq_mask   = iop13xx_irq_mask2,
+	.irq_unmask = iop13xx_irq_unmask2,
 };
 
 static struct irq_chip iop13xx_irqchip4 = {
-	.name	= "IOP13xx-4",
-	.ack    = iop13xx_irq_mask3,
-	.mask   = iop13xx_irq_mask3,
-	.unmask = iop13xx_irq_unmask3,
+	.name       = "IOP13xx-4",
+	.irq_ack    = iop13xx_irq_mask3,
+	.irq_mask   = iop13xx_irq_mask3,
+	.irq_unmask = iop13xx_irq_unmask3,
 };
 
 extern void iop_init_cp6_handler(void);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-iop13xx/msi.c linux-libre-2.6.38-gnu1/arch/arm/mach-iop13xx/msi.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-iop13xx/msi.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-iop13xx/msi.c	2011-03-14 21:20:32.000000000 -0400
@@ -156,14 +156,14 @@ void arch_teardown_msi_irq(unsigned int
 	destroy_irq(irq);
 }
 
-static void iop13xx_msi_nop(unsigned int irq)
+static void iop13xx_msi_nop(struct irq_data *d)
 {
 	return;
 }
 
 static struct irq_chip iop13xx_msi_chip = {
 	.name = "PCI-MSI",
-	.ack = iop13xx_msi_nop,
+	.irq_ack = iop13xx_msi_nop,
 	.irq_enable = unmask_msi_irq,
 	.irq_disable = mask_msi_irq,
 	.irq_mask = mask_msi_irq,
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-iop32x/include/mach/io.h linux-libre-2.6.38-gnu1/arch/arm/mach-iop32x/include/mach/io.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-iop32x/include/mach/io.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-iop32x/include/mach/io.h	2011-03-14 21:20:32.000000000 -0400
@@ -21,7 +21,7 @@ extern void __iop3xx_iounmap(void __iome
 #define __io(p)		((void __iomem *)IOP3XX_PCI_IO_PHYS_TO_VIRT(p))
 #define __mem_pci(a)		(a)
 
-#define __arch_ioremap(a, s, f) __iop3xx_ioremap(a, s, f)
-#define __arch_iounmap(a)	 __iop3xx_iounmap(a)
+#define __arch_ioremap	__iop3xx_ioremap
+#define __arch_iounmap	__iop3xx_iounmap
 
 #endif
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-iop32x/irq.c linux-libre-2.6.38-gnu1/arch/arm/mach-iop32x/irq.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-iop32x/irq.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-iop32x/irq.c	2011-03-14 21:20:32.000000000 -0400
@@ -32,24 +32,24 @@ static void intstr_write(u32 val)
 }
 
 static void
-iop32x_irq_mask(unsigned int irq)
+iop32x_irq_mask(struct irq_data *d)
 {
-	iop32x_mask &= ~(1 << irq);
+	iop32x_mask &= ~(1 << d->irq);
 	intctl_write(iop32x_mask);
 }
 
 static void
-iop32x_irq_unmask(unsigned int irq)
+iop32x_irq_unmask(struct irq_data *d)
 {
-	iop32x_mask |= 1 << irq;
+	iop32x_mask |= 1 << d->irq;
 	intctl_write(iop32x_mask);
 }
 
 struct irq_chip ext_chip = {
-	.name	= "IOP32x",
-	.ack	= iop32x_irq_mask,
-	.mask	= iop32x_irq_mask,
-	.unmask	= iop32x_irq_unmask,
+	.name		= "IOP32x",
+	.irq_ack	= iop32x_irq_mask,
+	.irq_mask	= iop32x_irq_mask,
+	.irq_unmask	= iop32x_irq_unmask,
 };
 
 void __init iop32x_init_irq(void)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-iop33x/include/mach/io.h linux-libre-2.6.38-gnu1/arch/arm/mach-iop33x/include/mach/io.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-iop33x/include/mach/io.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-iop33x/include/mach/io.h	2011-03-14 21:20:32.000000000 -0400
@@ -21,7 +21,7 @@ extern void __iop3xx_iounmap(void __iome
 #define __io(p)		((void __iomem *)IOP3XX_PCI_IO_PHYS_TO_VIRT(p))
 #define __mem_pci(a)		(a)
 
-#define __arch_ioremap(a, s, f) __iop3xx_ioremap(a, s, f)
-#define __arch_iounmap(a)	 __iop3xx_iounmap(a)
+#define __arch_ioremap	__iop3xx_ioremap
+#define __arch_iounmap	__iop3xx_iounmap
 
 #endif
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-iop33x/irq.c linux-libre-2.6.38-gnu1/arch/arm/mach-iop33x/irq.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-iop33x/irq.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-iop33x/irq.c	2011-03-14 21:20:32.000000000 -0400
@@ -53,45 +53,45 @@ static void intsize_write(u32 val)
 }
 
 static void
-iop33x_irq_mask1 (unsigned int irq)
+iop33x_irq_mask1 (struct irq_data *d)
 {
-	iop33x_mask0 &= ~(1 << irq);
+	iop33x_mask0 &= ~(1 << d->irq);
 	intctl0_write(iop33x_mask0);
 }
 
 static void
-iop33x_irq_mask2 (unsigned int irq)
+iop33x_irq_mask2 (struct irq_data *d)
 {
-	iop33x_mask1 &= ~(1 << (irq - 32));
+	iop33x_mask1 &= ~(1 << (d->irq - 32));
 	intctl1_write(iop33x_mask1);
 }
 
 static void
-iop33x_irq_unmask1(unsigned int irq)
+iop33x_irq_unmask1(struct irq_data *d)
 {
-	iop33x_mask0 |= 1 << irq;
+	iop33x_mask0 |= 1 << d->irq;
 	intctl0_write(iop33x_mask0);
 }
 
 static void
-iop33x_irq_unmask2(unsigned int irq)
+iop33x_irq_unmask2(struct irq_data *d)
 {
-	iop33x_mask1 |= (1 << (irq - 32));
+	iop33x_mask1 |= (1 << (d->irq - 32));
 	intctl1_write(iop33x_mask1);
 }
 
 struct irq_chip iop33x_irqchip1 = {
-	.name	= "IOP33x-1",
-	.ack	= iop33x_irq_mask1,
-	.mask	= iop33x_irq_mask1,
-	.unmask	= iop33x_irq_unmask1,
+	.name		= "IOP33x-1",
+	.irq_ack	= iop33x_irq_mask1,
+	.irq_mask	= iop33x_irq_mask1,
+	.irq_unmask	= iop33x_irq_unmask1,
 };
 
 struct irq_chip iop33x_irqchip2 = {
-	.name	= "IOP33x-2",
-	.ack	= iop33x_irq_mask2,
-	.mask	= iop33x_irq_mask2,
-	.unmask	= iop33x_irq_unmask2,
+	.name		= "IOP33x-2",
+	.irq_ack	= iop33x_irq_mask2,
+	.irq_mask	= iop33x_irq_mask2,
+	.irq_unmask	= iop33x_irq_unmask2,
 };
 
 void __init iop33x_init_irq(void)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-ixp2000/core.c linux-libre-2.6.38-gnu1/arch/arm/mach-ixp2000/core.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-ixp2000/core.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-ixp2000/core.c	2011-03-14 21:20:32.000000000 -0400
@@ -309,9 +309,9 @@ static void ixp2000_GPIO_irq_handler(uns
 	}
 }
 
-static int ixp2000_GPIO_irq_type(unsigned int irq, unsigned int type)
+static int ixp2000_GPIO_irq_type(struct irq_data *d, unsigned int type)
 {
-	int line = irq - IRQ_IXP2000_GPIO0;
+	int line = d->irq - IRQ_IXP2000_GPIO0;
 
 	/*
 	 * First, configure this GPIO line as an input.
@@ -342,8 +342,10 @@ static int ixp2000_GPIO_irq_type(unsigne
 	return 0;
 }
 
-static void ixp2000_GPIO_irq_mask_ack(unsigned int irq)
+static void ixp2000_GPIO_irq_mask_ack(struct irq_data *d)
 {
+	unsigned int irq = d->irq;
+
 	ixp2000_reg_write(IXP2000_GPIO_INCR, (1 << (irq - IRQ_IXP2000_GPIO0)));
 
 	ixp2000_reg_write(IXP2000_GPIO_EDSR, (1 << (irq - IRQ_IXP2000_GPIO0)));
@@ -351,38 +353,42 @@ static void ixp2000_GPIO_irq_mask_ack(un
 	ixp2000_reg_wrb(IXP2000_GPIO_INST, (1 << (irq - IRQ_IXP2000_GPIO0)));
 }
 
-static void ixp2000_GPIO_irq_mask(unsigned int irq)
+static void ixp2000_GPIO_irq_mask(struct irq_data *d)
 {
+	unsigned int irq = d->irq;
+
 	ixp2000_reg_wrb(IXP2000_GPIO_INCR, (1 << (irq - IRQ_IXP2000_GPIO0)));
 }
 
-static void ixp2000_GPIO_irq_unmask(unsigned int irq)
+static void ixp2000_GPIO_irq_unmask(struct irq_data *d)
 {
+	unsigned int irq = d->irq;
+
 	ixp2000_reg_write(IXP2000_GPIO_INSR, (1 << (irq - IRQ_IXP2000_GPIO0)));
 }
 
 static struct irq_chip ixp2000_GPIO_irq_chip = {
-	.ack		= ixp2000_GPIO_irq_mask_ack,
-	.mask		= ixp2000_GPIO_irq_mask,
-	.unmask		= ixp2000_GPIO_irq_unmask,
-	.set_type	= ixp2000_GPIO_irq_type,
+	.irq_ack	= ixp2000_GPIO_irq_mask_ack,
+	.irq_mask	= ixp2000_GPIO_irq_mask,
+	.irq_unmask	= ixp2000_GPIO_irq_unmask,
+	.irq_set_type	= ixp2000_GPIO_irq_type,
 };
 
-static void ixp2000_pci_irq_mask(unsigned int irq)
+static void ixp2000_pci_irq_mask(struct irq_data *d)
 {
 	unsigned long temp = *IXP2000_PCI_XSCALE_INT_ENABLE;
-	if (irq == IRQ_IXP2000_PCIA)
+	if (d->irq == IRQ_IXP2000_PCIA)
 		ixp2000_reg_wrb(IXP2000_PCI_XSCALE_INT_ENABLE, (temp & ~(1 << 26)));
-	else if (irq == IRQ_IXP2000_PCIB)
+	else if (d->irq == IRQ_IXP2000_PCIB)
 		ixp2000_reg_wrb(IXP2000_PCI_XSCALE_INT_ENABLE, (temp & ~(1 << 27)));
 }
 
-static void ixp2000_pci_irq_unmask(unsigned int irq)
+static void ixp2000_pci_irq_unmask(struct irq_data *d)
 {
 	unsigned long temp = *IXP2000_PCI_XSCALE_INT_ENABLE;
-	if (irq == IRQ_IXP2000_PCIA)
+	if (d->irq == IRQ_IXP2000_PCIA)
 		ixp2000_reg_write(IXP2000_PCI_XSCALE_INT_ENABLE, (temp | (1 << 26)));
-	else if (irq == IRQ_IXP2000_PCIB)
+	else if (d->irq == IRQ_IXP2000_PCIB)
 		ixp2000_reg_write(IXP2000_PCI_XSCALE_INT_ENABLE, (temp | (1 << 27)));
 }
 
@@ -401,44 +407,44 @@ static void ixp2000_err_irq_handler(unsi
 	}
 }
 
-static void ixp2000_err_irq_mask(unsigned int irq)
+static void ixp2000_err_irq_mask(struct irq_data *d)
 {
 	ixp2000_reg_write(IXP2000_IRQ_ERR_ENABLE_CLR,
-			(1 << (irq - IRQ_IXP2000_DRAM0_MIN_ERR)));
+			(1 << (d->irq - IRQ_IXP2000_DRAM0_MIN_ERR)));
 }
 
-static void ixp2000_err_irq_unmask(unsigned int irq)
+static void ixp2000_err_irq_unmask(struct irq_data *d)
 {
 	ixp2000_reg_write(IXP2000_IRQ_ERR_ENABLE_SET,
-			(1 << (irq - IRQ_IXP2000_DRAM0_MIN_ERR)));
+			(1 << (d->irq - IRQ_IXP2000_DRAM0_MIN_ERR)));
 }
 
 static struct irq_chip ixp2000_err_irq_chip = {
-	.ack	= ixp2000_err_irq_mask,
-	.mask	= ixp2000_err_irq_mask,
-	.unmask	= ixp2000_err_irq_unmask
+	.irq_ack	= ixp2000_err_irq_mask,
+	.irq_mask	= ixp2000_err_irq_mask,
+	.irq_unmask	= ixp2000_err_irq_unmask
 };
 
 static struct irq_chip ixp2000_pci_irq_chip = {
-	.ack	= ixp2000_pci_irq_mask,
-	.mask	= ixp2000_pci_irq_mask,
-	.unmask	= ixp2000_pci_irq_unmask
+	.irq_ack	= ixp2000_pci_irq_mask,
+	.irq_mask	= ixp2000_pci_irq_mask,
+	.irq_unmask	= ixp2000_pci_irq_unmask
 };
 
-static void ixp2000_irq_mask(unsigned int irq)
+static void ixp2000_irq_mask(struct irq_data *d)
 {
-	ixp2000_reg_wrb(IXP2000_IRQ_ENABLE_CLR, (1 << irq));
+	ixp2000_reg_wrb(IXP2000_IRQ_ENABLE_CLR, (1 << d->irq));
 }
 
-static void ixp2000_irq_unmask(unsigned int irq)
+static void ixp2000_irq_unmask(struct irq_data *d)
 {
-	ixp2000_reg_write(IXP2000_IRQ_ENABLE_SET, (1 << irq));
+	ixp2000_reg_write(IXP2000_IRQ_ENABLE_SET, (1 << d->irq));
 }
 
 static struct irq_chip ixp2000_irq_chip = {
-	.ack	= ixp2000_irq_mask,
-	.mask	= ixp2000_irq_mask,
-	.unmask	= ixp2000_irq_unmask
+	.irq_ack	= ixp2000_irq_mask,
+	.irq_mask	= ixp2000_irq_mask,
+	.irq_unmask	= ixp2000_irq_unmask
 };
 
 void __init ixp2000_init_irq(void)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-ixp2000/ixdp2x00.c linux-libre-2.6.38-gnu1/arch/arm/mach-ixp2000/ixdp2x00.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-ixp2000/ixdp2x00.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-ixp2000/ixdp2x00.c	2011-03-14 21:20:32.000000000 -0400
@@ -63,7 +63,7 @@ static struct slowport_cfg slowport_cpld
 };
 #endif
 
-static void ixdp2x00_irq_mask(unsigned int irq)
+static void ixdp2x00_irq_mask(struct irq_data *d)
 {
 	unsigned long dummy;
 	static struct slowport_cfg old_cfg;
@@ -78,7 +78,7 @@ static void ixdp2x00_irq_mask(unsigned i
 #endif
 
 	dummy = *board_irq_mask;
-	dummy |=  IXP2000_BOARD_IRQ_MASK(irq);
+	dummy |=  IXP2000_BOARD_IRQ_MASK(d->irq);
 	ixp2000_reg_wrb(board_irq_mask, dummy);
 
 #ifdef CONFIG_ARCH_IXDP2400
@@ -87,7 +87,7 @@ static void ixdp2x00_irq_mask(unsigned i
 #endif
 }
 
-static void ixdp2x00_irq_unmask(unsigned int irq)
+static void ixdp2x00_irq_unmask(struct irq_data *d)
 {
 	unsigned long dummy;
 	static struct slowport_cfg old_cfg;
@@ -98,7 +98,7 @@ static void ixdp2x00_irq_unmask(unsigned
 #endif
 
 	dummy = *board_irq_mask;
-	dummy &=  ~IXP2000_BOARD_IRQ_MASK(irq);
+	dummy &=  ~IXP2000_BOARD_IRQ_MASK(d->irq);
 	ixp2000_reg_wrb(board_irq_mask, dummy);
 
 	if (machine_is_ixdp2400()) 
@@ -111,7 +111,7 @@ static void ixdp2x00_irq_handler(unsigne
 	static struct slowport_cfg old_cfg;
 	int i;
 
-	desc->chip->mask(irq);
+	desc->irq_data.chip->irq_mask(&desc->irq_data);
 
 #ifdef CONFIG_ARCH_IXDP2400
 	if (machine_is_ixdp2400())
@@ -133,13 +133,13 @@ static void ixdp2x00_irq_handler(unsigne
 		}
 	}
 
-	desc->chip->unmask(irq);
+	desc->irq_data.chip->irq_unmask(&desc->irq_data);
 }
 
 static struct irq_chip ixdp2x00_cpld_irq_chip = {
-	.ack	= ixdp2x00_irq_mask,
-	.mask	= ixdp2x00_irq_mask,
-	.unmask	= ixdp2x00_irq_unmask
+	.irq_ack	= ixdp2x00_irq_mask,
+	.irq_mask	= ixdp2x00_irq_mask,
+	.irq_unmask	= ixdp2x00_irq_unmask
 };
 
 void __init ixdp2x00_init_irq(volatile unsigned long *stat_reg, volatile unsigned long *mask_reg, unsigned long nr_of_irqs)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-ixp2000/ixdp2x01.c linux-libre-2.6.38-gnu1/arch/arm/mach-ixp2000/ixdp2x01.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-ixp2000/ixdp2x01.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-ixp2000/ixdp2x01.c	2011-03-14 21:20:32.000000000 -0400
@@ -48,16 +48,16 @@
 /*************************************************************************
  * IXDP2x01 IRQ Handling
  *************************************************************************/
-static void ixdp2x01_irq_mask(unsigned int irq)
+static void ixdp2x01_irq_mask(struct irq_data *d)
 {
 	ixp2000_reg_wrb(IXDP2X01_INT_MASK_SET_REG,
-				IXP2000_BOARD_IRQ_MASK(irq));
+				IXP2000_BOARD_IRQ_MASK(d->irq));
 }
 
-static void ixdp2x01_irq_unmask(unsigned int irq)
+static void ixdp2x01_irq_unmask(struct irq_data *d)
 {
 	ixp2000_reg_write(IXDP2X01_INT_MASK_CLR_REG,
-				IXP2000_BOARD_IRQ_MASK(irq));
+				IXP2000_BOARD_IRQ_MASK(d->irq));
 }
 
 static u32 valid_irq_mask;
@@ -67,7 +67,7 @@ static void ixdp2x01_irq_handler(unsigne
 	u32 ex_interrupt;
 	int i;
 
-	desc->chip->mask(irq);
+	desc->irq_data.chip->irq_mask(&desc->irq_data);
 
 	ex_interrupt = *IXDP2X01_INT_STAT_REG & valid_irq_mask;
 
@@ -83,13 +83,13 @@ static void ixdp2x01_irq_handler(unsigne
 		}
 	}
 
-	desc->chip->unmask(irq);
+	desc->irq_data.chip->irq_unmask(&desc->irq_data);
 }
 
 static struct irq_chip ixdp2x01_irq_chip = {
-	.mask	= ixdp2x01_irq_mask,
-	.ack	= ixdp2x01_irq_mask,
-	.unmask	= ixdp2x01_irq_unmask
+	.irq_mask	= ixdp2x01_irq_mask,
+	.irq_ack	= ixdp2x01_irq_mask,
+	.irq_unmask	= ixdp2x01_irq_unmask
 };
 
 /*
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-ixp23xx/core.c linux-libre-2.6.38-gnu1/arch/arm/mach-ixp23xx/core.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-ixp23xx/core.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-ixp23xx/core.c	2011-03-14 21:20:32.000000000 -0400
@@ -111,9 +111,9 @@ enum ixp23xx_irq_type {
 
 static void ixp23xx_config_irq(unsigned int, enum ixp23xx_irq_type);
 
-static int ixp23xx_irq_set_type(unsigned int irq, unsigned int type)
+static int ixp23xx_irq_set_type(struct irq_data *d, unsigned int type)
 {
-	int line = irq - IRQ_IXP23XX_GPIO6 + 6;
+	int line = d->irq - IRQ_IXP23XX_GPIO6 + 6;
 	u32 int_style;
 	enum ixp23xx_irq_type irq_type;
 	volatile u32 *int_reg;
@@ -149,7 +149,7 @@ static int ixp23xx_irq_set_type(unsigned
 		return -EINVAL;
 	}
 
-	ixp23xx_config_irq(irq, irq_type);
+	ixp23xx_config_irq(d->irq, irq_type);
 
 	if (line >= 8) {	/* pins 8-15 */
 		line -= 8;
@@ -173,9 +173,10 @@ static int ixp23xx_irq_set_type(unsigned
 	return 0;
 }
 
-static void ixp23xx_irq_mask(unsigned int irq)
+static void ixp23xx_irq_mask(struct irq_data *d)
 {
 	volatile unsigned long *intr_reg;
+	unsigned int irq = d->irq;
 
 	if (irq >= 56)
 		irq += 8;
@@ -184,9 +185,9 @@ static void ixp23xx_irq_mask(unsigned in
 	*intr_reg &= ~(1 << (irq % 32));
 }
 
-static void ixp23xx_irq_ack(unsigned int irq)
+static void ixp23xx_irq_ack(struct irq_data *d)
 {
-	int line = irq - IRQ_IXP23XX_GPIO6 + 6;
+	int line = d->irq - IRQ_IXP23XX_GPIO6 + 6;
 
 	if ((line < 6) || (line > 15))
 		return;
@@ -198,11 +199,12 @@ static void ixp23xx_irq_ack(unsigned int
  * Level triggered interrupts on GPIO lines can only be cleared when the
  * interrupt condition disappears.
  */
-static void ixp23xx_irq_level_unmask(unsigned int irq)
+static void ixp23xx_irq_level_unmask(struct irq_data *d)
 {
 	volatile unsigned long *intr_reg;
+	unsigned int irq = d->irq;
 
-	ixp23xx_irq_ack(irq);
+	ixp23xx_irq_ack(d);
 
 	if (irq >= 56)
 		irq += 8;
@@ -211,9 +213,10 @@ static void ixp23xx_irq_level_unmask(uns
 	*intr_reg |= (1 << (irq % 32));
 }
 
-static void ixp23xx_irq_edge_unmask(unsigned int irq)
+static void ixp23xx_irq_edge_unmask(struct irq_data *d)
 {
 	volatile unsigned long *intr_reg;
+	unsigned int irq = d->irq;
 
 	if (irq >= 56)
 		irq += 8;
@@ -223,26 +226,30 @@ static void ixp23xx_irq_edge_unmask(unsi
 }
 
 static struct irq_chip ixp23xx_irq_level_chip = {
-	.ack		= ixp23xx_irq_mask,
-	.mask		= ixp23xx_irq_mask,
-	.unmask		= ixp23xx_irq_level_unmask,
-	.set_type	= ixp23xx_irq_set_type
+	.irq_ack	= ixp23xx_irq_mask,
+	.irq_mask	= ixp23xx_irq_mask,
+	.irq_unmask	= ixp23xx_irq_level_unmask,
+	.irq_set_type	= ixp23xx_irq_set_type
 };
 
 static struct irq_chip ixp23xx_irq_edge_chip = {
-	.ack		= ixp23xx_irq_ack,
-	.mask		= ixp23xx_irq_mask,
-	.unmask		= ixp23xx_irq_edge_unmask,
-	.set_type	= ixp23xx_irq_set_type
+	.irq_ack	= ixp23xx_irq_ack,
+	.irq_mask	= ixp23xx_irq_mask,
+	.irq_unmask	= ixp23xx_irq_edge_unmask,
+	.irq_set_type	= ixp23xx_irq_set_type
 };
 
-static void ixp23xx_pci_irq_mask(unsigned int irq)
+static void ixp23xx_pci_irq_mask(struct irq_data *d)
 {
+	unsigned int irq = d->irq;
+
 	*IXP23XX_PCI_XSCALE_INT_ENABLE &= ~(1 << (IRQ_IXP23XX_INTA + 27 - irq));
 }
 
-static void ixp23xx_pci_irq_unmask(unsigned int irq)
+static void ixp23xx_pci_irq_unmask(struct irq_data *d)
 {
+	unsigned int irq = d->irq;
+
 	*IXP23XX_PCI_XSCALE_INT_ENABLE |= (1 << (IRQ_IXP23XX_INTA + 27 - irq));
 }
 
@@ -256,7 +263,7 @@ static void pci_handler(unsigned int irq
 
 	pci_interrupt = *IXP23XX_PCI_XSCALE_INT_STATUS;
 
-	desc->chip->ack(irq);
+	desc->irq_data.chip->irq_ack(&desc->irq_data);
 
 	/* See which PCI_INTA, or PCI_INTB interrupted */
 	if (pci_interrupt & (1 << 26)) {
@@ -269,13 +276,13 @@ static void pci_handler(unsigned int irq
 
 	generic_handle_irq(irqno);
 
-	desc->chip->unmask(irq);
+	desc->irq_data.chip->irq_unmask(&desc->irq_data);
 }
 
 static struct irq_chip ixp23xx_pci_irq_chip = {
-	.ack	= ixp23xx_pci_irq_mask,
-	.mask	= ixp23xx_pci_irq_mask,
-	.unmask	= ixp23xx_pci_irq_unmask
+	.irq_ack	= ixp23xx_pci_irq_mask,
+	.irq_mask	= ixp23xx_pci_irq_mask,
+	.irq_unmask	= ixp23xx_pci_irq_unmask
 };
 
 static void ixp23xx_config_irq(unsigned int irq, enum ixp23xx_irq_type type)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-ixp23xx/include/mach/io.h linux-libre-2.6.38-gnu1/arch/arm/mach-ixp23xx/include/mach/io.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-ixp23xx/include/mach/io.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-ixp23xx/include/mach/io.h	2011-03-14 21:20:32.000000000 -0400
@@ -45,8 +45,8 @@ ixp23xx_iounmap(void __iomem *addr)
 	__iounmap(addr);
 }
 
-#define __arch_ioremap(a,s,f)	ixp23xx_ioremap(a,s,f)
-#define __arch_iounmap(a)	ixp23xx_iounmap(a)
+#define __arch_ioremap	ixp23xx_ioremap
+#define __arch_iounmap	ixp23xx_iounmap
 
 
 #endif
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-ixp23xx/ixdp2351.c linux-libre-2.6.38-gnu1/arch/arm/mach-ixp23xx/ixdp2351.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-ixp23xx/ixdp2351.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-ixp23xx/ixdp2351.c	2011-03-14 21:20:32.000000000 -0400
@@ -48,14 +48,14 @@
 /*
  * IXDP2351 Interrupt Handling
  */
-static void ixdp2351_inta_mask(unsigned int irq)
+static void ixdp2351_inta_mask(struct irq_data *d)
 {
-	*IXDP2351_CPLD_INTA_MASK_SET_REG = IXDP2351_INTA_IRQ_MASK(irq);
+	*IXDP2351_CPLD_INTA_MASK_SET_REG = IXDP2351_INTA_IRQ_MASK(d->irq);
 }
 
-static void ixdp2351_inta_unmask(unsigned int irq)
+static void ixdp2351_inta_unmask(struct irq_data *d)
 {
-	*IXDP2351_CPLD_INTA_MASK_CLR_REG = IXDP2351_INTA_IRQ_MASK(irq);
+	*IXDP2351_CPLD_INTA_MASK_CLR_REG = IXDP2351_INTA_IRQ_MASK(d->irq);
 }
 
 static void ixdp2351_inta_handler(unsigned int irq, struct irq_desc *desc)
@@ -64,7 +64,7 @@ static void ixdp2351_inta_handler(unsign
 		*IXDP2351_CPLD_INTA_STAT_REG & IXDP2351_INTA_IRQ_VALID;
 	int i;
 
-	desc->chip->mask(irq);
+	desc->irq_data.chip->irq_mask(&desc->irq_data);
 
 	for (i = 0; i < IXDP2351_INTA_IRQ_NUM; i++) {
 		if (ex_interrupt & (1 << i)) {
@@ -74,23 +74,23 @@ static void ixdp2351_inta_handler(unsign
 		}
 	}
 
-	desc->chip->unmask(irq);
+	desc->irq_data.chip->irq_unmask(&desc->irq_data);
 }
 
 static struct irq_chip ixdp2351_inta_chip = {
-	.ack	= ixdp2351_inta_mask,
-	.mask	= ixdp2351_inta_mask,
-	.unmask	= ixdp2351_inta_unmask
+	.irq_ack	= ixdp2351_inta_mask,
+	.irq_mask	= ixdp2351_inta_mask,
+	.irq_unmask	= ixdp2351_inta_unmask
 };
 
-static void ixdp2351_intb_mask(unsigned int irq)
+static void ixdp2351_intb_mask(struct irq_data *d)
 {
-	*IXDP2351_CPLD_INTB_MASK_SET_REG = IXDP2351_INTB_IRQ_MASK(irq);
+	*IXDP2351_CPLD_INTB_MASK_SET_REG = IXDP2351_INTB_IRQ_MASK(d->irq);
 }
 
-static void ixdp2351_intb_unmask(unsigned int irq)
+static void ixdp2351_intb_unmask(struct irq_data *d)
 {
-	*IXDP2351_CPLD_INTB_MASK_CLR_REG = IXDP2351_INTB_IRQ_MASK(irq);
+	*IXDP2351_CPLD_INTB_MASK_CLR_REG = IXDP2351_INTB_IRQ_MASK(d->irq);
 }
 
 static void ixdp2351_intb_handler(unsigned int irq, struct irq_desc *desc)
@@ -99,7 +99,7 @@ static void ixdp2351_intb_handler(unsign
 		*IXDP2351_CPLD_INTB_STAT_REG & IXDP2351_INTB_IRQ_VALID;
 	int i;
 
-	desc->chip->ack(irq);
+	desc->irq_data.chip->irq_ack(&desc->irq_data);
 
 	for (i = 0; i < IXDP2351_INTB_IRQ_NUM; i++) {
 		if (ex_interrupt & (1 << i)) {
@@ -109,13 +109,13 @@ static void ixdp2351_intb_handler(unsign
 		}
 	}
 
-	desc->chip->unmask(irq);
+	desc->irq_data.chip->irq_unmask(&desc->irq_data);
 }
 
 static struct irq_chip ixdp2351_intb_chip = {
-	.ack	= ixdp2351_intb_mask,
-	.mask	= ixdp2351_intb_mask,
-	.unmask	= ixdp2351_intb_unmask
+	.irq_ack	= ixdp2351_intb_mask,
+	.irq_mask	= ixdp2351_intb_mask,
+	.irq_unmask	= ixdp2351_intb_unmask
 };
 
 void __init ixdp2351_init_irq(void)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-ixp4xx/common.c linux-libre-2.6.38-gnu1/arch/arm/mach-ixp4xx/common.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-ixp4xx/common.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-ixp4xx/common.c	2011-03-14 21:20:32.000000000 -0400
@@ -35,6 +35,7 @@
 #include <asm/pgtable.h>
 #include <asm/page.h>
 #include <asm/irq.h>
+#include <asm/sched_clock.h>
 
 #include <asm/mach/map.h>
 #include <asm/mach/irq.h>
@@ -127,9 +128,9 @@ int irq_to_gpio(unsigned int irq)
 }
 EXPORT_SYMBOL(irq_to_gpio);
 
-static int ixp4xx_set_irq_type(unsigned int irq, unsigned int type)
+static int ixp4xx_set_irq_type(struct irq_data *d, unsigned int type)
 {
-	int line = irq2gpio[irq];
+	int line = irq2gpio[d->irq];
 	u32 int_style;
 	enum ixp4xx_irq_type irq_type;
 	volatile u32 *int_reg;
@@ -166,9 +167,9 @@ static int ixp4xx_set_irq_type(unsigned
 	}
 
 	if (irq_type == IXP4XX_IRQ_EDGE)
-		ixp4xx_irq_edge |= (1 << irq);
+		ixp4xx_irq_edge |= (1 << d->irq);
 	else
-		ixp4xx_irq_edge &= ~(1 << irq);
+		ixp4xx_irq_edge &= ~(1 << d->irq);
 
 	if (line >= 8) {	/* pins 8-15 */
 		line -= 8;
@@ -187,22 +188,22 @@ static int ixp4xx_set_irq_type(unsigned
 	*int_reg |= (int_style << (line * IXP4XX_GPIO_STYLE_SIZE));
 
 	/* Configure the line as an input */
-	gpio_line_config(irq2gpio[irq], IXP4XX_GPIO_IN);
+	gpio_line_config(irq2gpio[d->irq], IXP4XX_GPIO_IN);
 
 	return 0;
 }
 
-static void ixp4xx_irq_mask(unsigned int irq)
+static void ixp4xx_irq_mask(struct irq_data *d)
 {
-	if ((cpu_is_ixp46x() || cpu_is_ixp43x()) && irq >= 32)
-		*IXP4XX_ICMR2 &= ~(1 << (irq - 32));
+	if ((cpu_is_ixp46x() || cpu_is_ixp43x()) && d->irq >= 32)
+		*IXP4XX_ICMR2 &= ~(1 << (d->irq - 32));
 	else
-		*IXP4XX_ICMR &= ~(1 << irq);
+		*IXP4XX_ICMR &= ~(1 << d->irq);
 }
 
-static void ixp4xx_irq_ack(unsigned int irq)
+static void ixp4xx_irq_ack(struct irq_data *d)
 {
-	int line = (irq < 32) ? irq2gpio[irq] : -1;
+	int line = (d->irq < 32) ? irq2gpio[d->irq] : -1;
 
 	if (line >= 0)
 		*IXP4XX_GPIO_GPISR = (1 << line);
@@ -212,23 +213,23 @@ static void ixp4xx_irq_ack(unsigned int
  * Level triggered interrupts on GPIO lines can only be cleared when the
  * interrupt condition disappears.
  */
-static void ixp4xx_irq_unmask(unsigned int irq)
+static void ixp4xx_irq_unmask(struct irq_data *d)
 {
-	if (!(ixp4xx_irq_edge & (1 << irq)))
-		ixp4xx_irq_ack(irq);
+	if (!(ixp4xx_irq_edge & (1 << d->irq)))
+		ixp4xx_irq_ack(d);
 
-	if ((cpu_is_ixp46x() || cpu_is_ixp43x()) && irq >= 32)
-		*IXP4XX_ICMR2 |= (1 << (irq - 32));
+	if ((cpu_is_ixp46x() || cpu_is_ixp43x()) && d->irq >= 32)
+		*IXP4XX_ICMR2 |= (1 << (d->irq - 32));
 	else
-		*IXP4XX_ICMR |= (1 << irq);
+		*IXP4XX_ICMR |= (1 << d->irq);
 }
 
 static struct irq_chip ixp4xx_irq_chip = {
 	.name		= "IXP4xx",
-	.ack		= ixp4xx_irq_ack,
-	.mask		= ixp4xx_irq_mask,
-	.unmask		= ixp4xx_irq_unmask,
-	.set_type	= ixp4xx_set_irq_type,
+	.irq_ack	= ixp4xx_irq_ack,
+	.irq_mask	= ixp4xx_irq_mask,
+	.irq_unmask	= ixp4xx_irq_unmask,
+	.irq_set_type	= ixp4xx_set_irq_type,
 };
 
 void __init ixp4xx_init_irq(void)
@@ -399,6 +400,23 @@ void __init ixp4xx_sys_init(void)
 }
 
 /*
+ * sched_clock()
+ */
+static DEFINE_CLOCK_DATA(cd);
+
+unsigned long long notrace sched_clock(void)
+{
+	u32 cyc = *IXP4XX_OSTS;
+	return cyc_to_sched_clock(&cd, cyc, (u32)~0);
+}
+
+static void notrace ixp4xx_update_sched_clock(void)
+{
+	u32 cyc = *IXP4XX_OSTS;
+	update_sched_clock(&cd, cyc, (u32)~0);
+}
+
+/*
  * clocksource
  */
 static cycle_t ixp4xx_get_cycles(struct clocksource *cs)
@@ -411,29 +429,16 @@ static struct clocksource clocksource_ix
 	.rating		= 200,
 	.read		= ixp4xx_get_cycles,
 	.mask		= CLOCKSOURCE_MASK(32),
-	.shift 		= 20,
 	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
-unsigned long ixp4xx_timer_freq = FREQ;
+unsigned long ixp4xx_timer_freq = IXP4XX_TIMER_FREQ;
 EXPORT_SYMBOL(ixp4xx_timer_freq);
 static void __init ixp4xx_clocksource_init(void)
 {
-	clocksource_ixp4xx.mult =
-		clocksource_hz2mult(ixp4xx_timer_freq,
-				    clocksource_ixp4xx.shift);
-	clocksource_register(&clocksource_ixp4xx);
-}
-
-/*
- * sched_clock()
- */
-unsigned long long sched_clock(void)
-{
-	cycle_t cyc = ixp4xx_get_cycles(NULL);
-	struct clocksource *cs = &clocksource_ixp4xx;
+	init_sched_clock(&cd, ixp4xx_update_sched_clock, 32, ixp4xx_timer_freq);
 
-	return clocksource_cyc2ns(cyc, cs->mult, cs->shift);
+	clocksource_register_hz(&clocksource_ixp4xx, ixp4xx_timer_freq);
 }
 
 /*
@@ -491,7 +496,7 @@ static struct clock_event_device clockev
 
 static void __init ixp4xx_clockevent_init(void)
 {
-	clockevent_ixp4xx.mult = div_sc(FREQ, NSEC_PER_SEC,
+	clockevent_ixp4xx.mult = div_sc(IXP4XX_TIMER_FREQ, NSEC_PER_SEC,
 					clockevent_ixp4xx.shift);
 	clockevent_ixp4xx.max_delta_ns =
 		clockevent_delta2ns(0xfffffffe, &clockevent_ixp4xx);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-ixp4xx/include/mach/io.h linux-libre-2.6.38-gnu1/arch/arm/mach-ixp4xx/include/mach/io.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-ixp4xx/include/mach/io.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-ixp4xx/include/mach/io.h	2011-03-14 21:20:32.000000000 -0400
@@ -74,8 +74,8 @@ static inline void __indirect_iounmap(vo
 		__iounmap(addr);
 }
 
-#define __arch_ioremap(a, s, f)		__indirect_ioremap(a, s, f)
-#define __arch_iounmap(a)		__indirect_iounmap(a)
+#define __arch_ioremap			__indirect_ioremap
+#define __arch_iounmap			__indirect_iounmap
 
 #define writeb(v, p)			__indirect_writeb(v, p)
 #define writew(v, p)			__indirect_writew(v, p)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-ixp4xx/include/mach/timex.h linux-libre-2.6.38-gnu1/arch/arm/mach-ixp4xx/include/mach/timex.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-ixp4xx/include/mach/timex.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-ixp4xx/include/mach/timex.h	2011-03-14 21:20:32.000000000 -0400
@@ -10,6 +10,7 @@
  * 66.66... MHz. We do a convulted calculation of CLOCK_TICK_RATE b/c the
  * timer register ignores the bottom 2 bits of the LATCH value.
  */
-#define FREQ 66666000
-#define CLOCK_TICK_RATE (((FREQ / HZ & ~IXP4XX_OST_RELOAD_MASK) + 1) * HZ)
+#define IXP4XX_TIMER_FREQ 66666000
+#define CLOCK_TICK_RATE \
+	(((IXP4XX_TIMER_FREQ / HZ & ~IXP4XX_OST_RELOAD_MASK) + 1) * HZ)
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-ixp4xx/ixp4xx_qmgr.c linux-libre-2.6.38-gnu1/arch/arm/mach-ixp4xx/ixp4xx_qmgr.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-ixp4xx/ixp4xx_qmgr.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-ixp4xx/ixp4xx_qmgr.c	2011-03-14 21:20:32.000000000 -0400
@@ -265,6 +265,11 @@ void qmgr_release_queue(unsigned int que
 	       qmgr_queue_descs[queue], queue);
 	qmgr_queue_descs[queue][0] = '\x0';
 #endif
+
+	while ((addr = qmgr_get_entry(queue)))
+		printk(KERN_ERR "qmgr: released queue %i not empty: 0x%08X\n",
+		       queue, addr);
+
 	__raw_writel(0, &qmgr_regs->sram[queue]);
 
 	used_sram_bitmap[0] &= ~mask[0];
@@ -275,10 +280,6 @@ void qmgr_release_queue(unsigned int que
 	spin_unlock_irq(&qmgr_lock);
 
 	module_put(THIS_MODULE);
-
-	while ((addr = qmgr_get_entry(queue)))
-		printk(KERN_ERR "qmgr: released queue %i not empty: 0x%08X\n",
-		       queue, addr);
 }
 
 static int qmgr_init(void)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-kirkwood/include/mach/io.h linux-libre-2.6.38-gnu1/arch/arm/mach-kirkwood/include/mach/io.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-kirkwood/include/mach/io.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-kirkwood/include/mach/io.h	2011-03-14 21:20:32.000000000 -0400
@@ -42,8 +42,8 @@ __arch_iounmap(void __iomem *addr)
 		__iounmap(addr);
 }
 
-#define __arch_ioremap(p, s, m)	__arch_ioremap(p, s, m)
-#define __arch_iounmap(a)	__arch_iounmap(a)
+#define __arch_ioremap		__arch_ioremap
+#define __arch_iounmap		__arch_iounmap
 #define __io(a)			__io(a)
 #define __mem_pci(a)		(a)
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-kirkwood/Kconfig linux-libre-2.6.38-gnu1/arch/arm/mach-kirkwood/Kconfig
--- linux-libre-2.6.37-gnu1/arch/arm/mach-kirkwood/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-kirkwood/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -45,18 +45,18 @@ config MACH_GURUPLUG
 	  Marvell GuruPlug Reference Board.
 
 config MACH_TS219
-	bool "QNAP TS-110, TS-119, TS-210, TS-219 and TS-219P Turbo NAS"
+	bool "QNAP TS-110, TS-119, TS-119P+, TS-210, TS-219, TS-219P and TS-219P+ Turbo NAS"
 	help
 	  Say 'Y' here if you want your kernel to support the
-	  QNAP TS-110, TS-119, TS-210, TS-219 and TS-219P Turbo NAS
-	  devices.
+	  QNAP TS-110, TS-119, TS-119P+, TS-210, TS-219, TS-219P and
+	  TS-219P+ Turbo NAS devices.
 
 config MACH_TS41X
-	bool "QNAP TS-410, TS-410U, TS-419P and TS-419U Turbo NAS"
+	bool "QNAP TS-410, TS-410U, TS-419P, TS-419P+ and TS-419U Turbo NAS"
 	help
 	  Say 'Y' here if you want your kernel to support the
-	  QNAP TS-410, TS-410U, TS-419P and TS-419U Turbo NAS
-	  devices.
+	  QNAP TS-410, TS-410U, TS-419P, TS-419P+ and TS-419U Turbo
+	  NAS devices.
 
 config MACH_DOCKSTAR
 	bool "Seagate FreeAgent DockStar"
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-kirkwood/openrd-setup.c linux-libre-2.6.38-gnu1/arch/arm/mach-kirkwood/openrd-setup.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-kirkwood/openrd-setup.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-kirkwood/openrd-setup.c	2011-03-14 21:20:32.000000000 -0400
@@ -171,7 +171,7 @@ static void __init openrd_init(void)
 
 	kirkwood_i2c_init();
 
-	if (machine_is_openrd_client()) {
+	if (machine_is_openrd_client() || machine_is_openrd_ultimate()) {
 		i2c_register_board_info(0, i2c_board_info,
 			ARRAY_SIZE(i2c_board_info));
 		kirkwood_audio_init();
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-kirkwood/ts219-setup.c linux-libre-2.6.38-gnu1/arch/arm/mach-kirkwood/ts219-setup.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-kirkwood/ts219-setup.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-kirkwood/ts219-setup.c	2011-03-14 21:20:32.000000000 -0400
@@ -80,15 +80,19 @@ static unsigned int qnap_ts219_mpp_confi
 	MPP11_UART0_RXD,
 	MPP13_UART1_TXD,	/* PIC controller */
 	MPP14_UART1_RXD,	/* PIC controller */
-	MPP15_GPIO,		/* USB Copy button */
-	MPP16_GPIO,		/* Reset button */
+	MPP15_GPIO,		/* USB Copy button (on devices with 88F6281) */
+	MPP16_GPIO,		/* Reset button (on devices with 88F6281) */
 	MPP36_GPIO,		/* RAM: 0: 256 MB, 1: 512 MB */
+	MPP37_GPIO,		/* Reset button (on devices with 88F6282) */
+	MPP43_GPIO,		/* USB Copy button (on devices with 88F6282) */
 	MPP44_GPIO,		/* Board ID: 0: TS-11x, 1: TS-21x */
 	0
 };
 
 static void __init qnap_ts219_init(void)
 {
+	u32 dev, rev;
+
 	/*
 	 * Basic setup. Needs to be called early.
 	 */
@@ -100,6 +104,14 @@ static void __init qnap_ts219_init(void)
 	qnap_tsx1x_register_flash();
 	kirkwood_i2c_init();
 	i2c_register_board_info(0, &qnap_ts219_i2c_rtc, 1);
+
+	kirkwood_pcie_id(&dev, &rev);
+	if (dev == MV88F6282_DEV_ID) {
+		qnap_ts219_buttons[0].gpio = 43; /* USB Copy button */
+		qnap_ts219_buttons[1].gpio = 37; /* Reset button */
+		qnap_ts219_ge00_data.phy_addr = MV643XX_ETH_PHY_ADDR(0);
+	}
+
 	kirkwood_ge00_init(&qnap_ts219_ge00_data);
 	kirkwood_sata_init(&qnap_ts219_sata_data);
 	kirkwood_ehci_init();
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-kirkwood/ts41x-setup.c linux-libre-2.6.38-gnu1/arch/arm/mach-kirkwood/ts41x-setup.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-kirkwood/ts41x-setup.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-kirkwood/ts41x-setup.c	2011-03-14 21:20:32.000000000 -0400
@@ -119,6 +119,8 @@ static unsigned int qnap_ts41x_mpp_confi
 
 static void __init qnap_ts41x_init(void)
 {
+	u32 dev, rev;
+
 	/*
 	 * Basic setup. Needs to be called early.
 	 */
@@ -130,8 +132,15 @@ static void __init qnap_ts41x_init(void)
 	qnap_tsx1x_register_flash();
 	kirkwood_i2c_init();
 	i2c_register_board_info(0, &qnap_ts41x_i2c_rtc, 1);
+
+	kirkwood_pcie_id(&dev, &rev);
+	if (dev == MV88F6282_DEV_ID) {
+		qnap_ts41x_ge00_data.phy_addr = MV643XX_ETH_PHY_ADDR(0);
+		qnap_ts41x_ge01_data.phy_addr = MV643XX_ETH_PHY_ADDR(1);
+	}
 	kirkwood_ge00_init(&qnap_ts41x_ge00_data);
 	kirkwood_ge01_init(&qnap_ts41x_ge01_data);
+
 	kirkwood_sata_init(&qnap_ts41x_sata_data);
 	kirkwood_ehci_init();
 	platform_device_register(&qnap_ts41x_button_device);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-ks8695/include/mach/memory.h linux-libre-2.6.38-gnu1/arch/arm/mach-ks8695/include/mach/memory.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-ks8695/include/mach/memory.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-ks8695/include/mach/memory.h	2011-03-14 21:20:32.000000000 -0400
@@ -35,17 +35,17 @@ extern struct bus_type platform_bus_type
 					__phys_to_virt(x) : __bus_to_virt(x)); })
 #define __arch_virt_to_dma(dev, x)	({ is_lbus_device(dev) ? \
 					(dma_addr_t)__virt_to_phys(x) : (dma_addr_t)__virt_to_bus(x); })
-#define __arch_page_to_dma(dev, x)	\
-	({ dma_addr_t __dma = page_to_phys(page); \
+#define __arch_pfn_to_dma(dev, pfn)	\
+	({ dma_addr_t __dma = __pfn_to_phys(pfn); \
 	   if (!is_lbus_device(dev)) \
 		__dma = __dma - PHYS_OFFSET + KS8695_PCIMEM_PA; \
 	   __dma; })
 
-#define __arch_dma_to_page(dev, x)	\
+#define __arch_dma_to_pfn(dev, x)	\
 	({ dma_addr_t __dma = x;				\
 	   if (!is_lbus_device(dev))				\
 		__dma += PHYS_OFFSET - KS8695_PCIMEM_PA;	\
-	   phys_to_page(__dma);					\
+	   __phys_to_pfn(__dma);				\
 	})
 
 #endif
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-ks8695/irq.c linux-libre-2.6.38-gnu1/arch/arm/mach-ks8695/irq.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-ks8695/irq.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-ks8695/irq.c	2011-03-14 21:20:32.000000000 -0400
@@ -34,29 +34,29 @@
 #include <mach/regs-irq.h>
 #include <mach/regs-gpio.h>
 
-static void ks8695_irq_mask(unsigned int irqno)
+static void ks8695_irq_mask(struct irq_data *d)
 {
 	unsigned long inten;
 
 	inten = __raw_readl(KS8695_IRQ_VA + KS8695_INTEN);
-	inten &= ~(1 << irqno);
+	inten &= ~(1 << d->irq);
 
 	__raw_writel(inten, KS8695_IRQ_VA + KS8695_INTEN);
 }
 
-static void ks8695_irq_unmask(unsigned int irqno)
+static void ks8695_irq_unmask(struct irq_data *d)
 {
 	unsigned long inten;
 
 	inten = __raw_readl(KS8695_IRQ_VA + KS8695_INTEN);
-	inten |= (1 << irqno);
+	inten |= (1 << d->irq);
 
 	__raw_writel(inten, KS8695_IRQ_VA + KS8695_INTEN);
 }
 
-static void ks8695_irq_ack(unsigned int irqno)
+static void ks8695_irq_ack(struct irq_data *d)
 {
-	__raw_writel((1 << irqno), KS8695_IRQ_VA + KS8695_INTST);
+	__raw_writel((1 << d->irq), KS8695_IRQ_VA + KS8695_INTST);
 }
 
 
@@ -64,7 +64,7 @@ static struct irq_chip ks8695_irq_level_
 static struct irq_chip ks8695_irq_edge_chip;
 
 
-static int ks8695_irq_set_type(unsigned int irqno, unsigned int type)
+static int ks8695_irq_set_type(struct irq_data *d, unsigned int type)
 {
 	unsigned long ctrl, mode;
 	unsigned short level_triggered = 0;
@@ -93,7 +93,7 @@ static int ks8695_irq_set_type(unsigned
 			return -EINVAL;
 	}
 
-	switch (irqno) {
+	switch (d->irq) {
 		case KS8695_IRQ_EXTERN0:
 			ctrl &= ~IOPC_IOEINT0TM;
 			ctrl |= IOPC_IOEINT0_MODE(mode);
@@ -115,12 +115,12 @@ static int ks8695_irq_set_type(unsigned
 	}
 
 	if (level_triggered) {
-		set_irq_chip(irqno, &ks8695_irq_level_chip);
-		set_irq_handler(irqno, handle_level_irq);
+		set_irq_chip(d->irq, &ks8695_irq_level_chip);
+		set_irq_handler(d->irq, handle_level_irq);
 	}
 	else {
-		set_irq_chip(irqno, &ks8695_irq_edge_chip);
-		set_irq_handler(irqno, handle_edge_irq);
+		set_irq_chip(d->irq, &ks8695_irq_edge_chip);
+		set_irq_handler(d->irq, handle_edge_irq);
 	}
 
 	__raw_writel(ctrl, KS8695_GPIO_VA + KS8695_IOPC);
@@ -128,17 +128,17 @@ static int ks8695_irq_set_type(unsigned
 }
 
 static struct irq_chip ks8695_irq_level_chip = {
-	.ack		= ks8695_irq_mask,
-	.mask		= ks8695_irq_mask,
-	.unmask		= ks8695_irq_unmask,
-	.set_type	= ks8695_irq_set_type,
+	.irq_ack	= ks8695_irq_mask,
+	.irq_mask	= ks8695_irq_mask,
+	.irq_unmask	= ks8695_irq_unmask,
+	.irq_set_type	= ks8695_irq_set_type,
 };
 
 static struct irq_chip ks8695_irq_edge_chip = {
-	.ack		= ks8695_irq_ack,
-	.mask		= ks8695_irq_mask,
-	.unmask		= ks8695_irq_unmask,
-	.set_type	= ks8695_irq_set_type,
+	.irq_ack	= ks8695_irq_ack,
+	.irq_mask	= ks8695_irq_mask,
+	.irq_unmask	= ks8695_irq_unmask,
+	.irq_set_type	= ks8695_irq_set_type,
 };
 
 void __init ks8695_init_irq(void)
@@ -164,7 +164,8 @@ void __init ks8695_init_irq(void)
 
 			/* Edge-triggered interrupts */
 			default:
-				ks8695_irq_ack(irq);	/* clear pending bit */
+				/* clear pending bit */
+				ks8695_irq_ack(irq_get_irq_data(irq));
 				set_irq_chip(irq, &ks8695_irq_edge_chip);
 				set_irq_handler(irq, handle_edge_irq);
 		}
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-ks8695/Kconfig linux-libre-2.6.38-gnu1/arch/arm/mach-ks8695/Kconfig
--- linux-libre-2.6.37-gnu1/arch/arm/mach-ks8695/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-ks8695/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -4,6 +4,7 @@ menu "Kendin/Micrel KS8695 Implementatio
 
 config MACH_KS8695
 	bool "KS8695 development board"
+	select MIGHT_HAVE_PCI
 	help
 	  Say 'Y' here if you want your kernel to run on the original
 	  Kendin-Micrel KS8695 development board.
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-lh7a40x/arch-kev7a400.c linux-libre-2.6.38-gnu1/arch/arm/mach-lh7a40x/arch-kev7a400.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-lh7a40x/arch-kev7a400.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-lh7a40x/arch-kev7a400.c	2011-03-14 21:20:32.000000000 -0400
@@ -46,28 +46,28 @@ void __init kev7a400_map_io(void)
 
 static u16 CPLD_IRQ_mask;	/* Mask for CPLD IRQs, 1 == unmasked */
 
-static void kev7a400_ack_cpld_irq (u32 irq)
+static void kev7a400_ack_cpld_irq(struct irq_data *d)
 {
-	CPLD_CL_INT = 1 << (irq - IRQ_KEV7A400_CPLD);
+	CPLD_CL_INT = 1 << (d->irq - IRQ_KEV7A400_CPLD);
 }
 
-static void kev7a400_mask_cpld_irq (u32 irq)
+static void kev7a400_mask_cpld_irq(struct irq_data *d)
 {
-	CPLD_IRQ_mask &= ~(1 << (irq - IRQ_KEV7A400_CPLD));
+	CPLD_IRQ_mask &= ~(1 << (d->irq - IRQ_KEV7A400_CPLD));
 	CPLD_WR_PB_INT_MASK = CPLD_IRQ_mask;
 }
 
-static void kev7a400_unmask_cpld_irq (u32 irq)
+static void kev7a400_unmask_cpld_irq(struct irq_data *d)
 {
-	CPLD_IRQ_mask |= 1 << (irq - IRQ_KEV7A400_CPLD);
+	CPLD_IRQ_mask |= 1 << (d->irq - IRQ_KEV7A400_CPLD);
 	CPLD_WR_PB_INT_MASK = CPLD_IRQ_mask;
 }
 
 static struct irq_chip kev7a400_cpld_chip = {
-	.name	= "CPLD",
-	.ack	= kev7a400_ack_cpld_irq,
-	.mask	= kev7a400_mask_cpld_irq,
-	.unmask	= kev7a400_unmask_cpld_irq,
+	.name		= "CPLD",
+	.irq_ack	= kev7a400_ack_cpld_irq,
+	.irq_mask	= kev7a400_mask_cpld_irq,
+	.irq_unmask	= kev7a400_unmask_cpld_irq,
 };
 
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-lh7a40x/arch-lpd7a40x.c linux-libre-2.6.38-gnu1/arch/arm/mach-lh7a40x/arch-lpd7a40x.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-lh7a40x/arch-lpd7a40x.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-lh7a40x/arch-lpd7a40x.c	2011-03-14 21:20:32.000000000 -0400
@@ -159,7 +159,7 @@ static void __init lpd7a40x_init (void)
 #endif
 }
 
-static void lh7a40x_ack_cpld_irq (u32 irq)
+static void lh7a40x_ack_cpld_irq(struct irq_data *d)
 {
 	/* CPLD doesn't have ack capability, but some devices may */
 
@@ -167,14 +167,14 @@ static void lh7a40x_ack_cpld_irq (u32 ir
 	/* The touch control *must* mask the interrupt because the
 	 * interrupt bit is read by the driver to determine if the pen
 	 * is still down. */
-	if (irq == IRQ_TOUCH)
+	if (d->irq == IRQ_TOUCH)
 		CPLD_INTERRUPTS |= CPLD_INTMASK_TOUCH;
 #endif
 }
 
-static void lh7a40x_mask_cpld_irq (u32 irq)
+static void lh7a40x_mask_cpld_irq(struct irq_data *d)
 {
-	switch (irq) {
+	switch (d->irq) {
 	case IRQ_LPD7A40X_ETH_INT:
 		CPLD_INTERRUPTS |= CPLD_INTMASK_ETHERNET;
 		break;
@@ -186,9 +186,9 @@ static void lh7a40x_mask_cpld_irq (u32 i
 	}
 }
 
-static void lh7a40x_unmask_cpld_irq (u32 irq)
+static void lh7a40x_unmask_cpld_irq(struct irq_data *d)
 {
-	switch (irq) {
+	switch (d->irq) {
 	case IRQ_LPD7A40X_ETH_INT:
 		CPLD_INTERRUPTS &= ~CPLD_INTMASK_ETHERNET;
 		break;
@@ -201,17 +201,17 @@ static void lh7a40x_unmask_cpld_irq (u32
 }
 
 static struct irq_chip lpd7a40x_cpld_chip = {
-	.name	= "CPLD",
-	.ack	= lh7a40x_ack_cpld_irq,
-	.mask	= lh7a40x_mask_cpld_irq,
-	.unmask	= lh7a40x_unmask_cpld_irq,
+	.name		= "CPLD",
+	.irq_ack	= lh7a40x_ack_cpld_irq,
+	.irq_mask	= lh7a40x_mask_cpld_irq,
+	.irq_unmask	= lh7a40x_unmask_cpld_irq,
 };
 
 static void lpd7a40x_cpld_handler (unsigned int irq, struct irq_desc *desc)
 {
 	unsigned int mask = CPLD_INTERRUPTS;
 
-	desc->chip->ack (irq);
+	desc->irq_data.chip->irq_ack(&desc->irq_data);
 
 	if ((mask & (1<<0)) == 0)	/* WLAN */
 		generic_handle_irq(IRQ_LPD7A40X_ETH_INT);
@@ -221,7 +221,8 @@ static void lpd7a40x_cpld_handler (unsig
 		generic_handle_irq(IRQ_TOUCH);
 #endif
 
-	desc->chip->unmask (irq); /* Level-triggered need this */
+	/* Level-triggered need this */
+	desc->irq_data.chip->irq_unmask(&desc->irq_data);
 }
 
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-lh7a40x/irq-lh7a400.c linux-libre-2.6.38-gnu1/arch/arm/mach-lh7a40x/irq-lh7a400.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-lh7a40x/irq-lh7a400.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-lh7a40x/irq-lh7a400.c	2011-03-14 21:20:32.000000000 -0400
@@ -21,34 +21,34 @@
 
   /* CPU IRQ handling */
 
-static void lh7a400_mask_irq (u32 irq)
+static void lh7a400_mask_irq(struct irq_data *d)
 {
-	INTC_INTENC = (1 << irq);
+	INTC_INTENC = (1 << d->irq);
 }
 
-static void lh7a400_unmask_irq (u32 irq)
+static void lh7a400_unmask_irq(struct irq_data *d)
 {
-	INTC_INTENS = (1 << irq);
+	INTC_INTENS = (1 << d->irq);
 }
 
-static void lh7a400_ack_gpio_irq (u32 irq)
+static void lh7a400_ack_gpio_irq(struct irq_data *d)
 {
-	GPIO_GPIOFEOI = (1 << IRQ_TO_GPIO (irq));
-	INTC_INTENC = (1 << irq);
+	GPIO_GPIOFEOI = (1 << IRQ_TO_GPIO (d->irq));
+	INTC_INTENC = (1 << d->irq);
 }
 
 static struct irq_chip lh7a400_internal_chip = {
-	.name	= "MPU",
-	.ack	= lh7a400_mask_irq, /* Level triggering -> mask is ack */
-	.mask	= lh7a400_mask_irq,
-	.unmask	= lh7a400_unmask_irq,
+	.name		= "MPU",
+	.irq_ack	= lh7a400_mask_irq, /* Level triggering -> mask is ack */
+	.irq_mask	= lh7a400_mask_irq,
+	.irq_unmask	= lh7a400_unmask_irq,
 };
 
 static struct irq_chip lh7a400_gpio_chip = {
-	.name	= "GPIO",
-	.ack	= lh7a400_ack_gpio_irq,
-	.mask	= lh7a400_mask_irq,
-	.unmask	= lh7a400_unmask_irq,
+	.name		= "GPIO",
+	.irq_ack	= lh7a400_ack_gpio_irq,
+	.irq_mask	= lh7a400_mask_irq,
+	.irq_unmask	= lh7a400_unmask_irq,
 };
 
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-lh7a40x/irq-lh7a404.c linux-libre-2.6.38-gnu1/arch/arm/mach-lh7a40x/irq-lh7a404.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-lh7a40x/irq-lh7a404.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-lh7a40x/irq-lh7a404.c	2011-03-14 21:20:32.000000000 -0400
@@ -43,64 +43,64 @@ static unsigned char irq_pri_vic2[] = {
 
   /* CPU IRQ handling */
 
-static void lh7a404_vic1_mask_irq (u32 irq)
+static void lh7a404_vic1_mask_irq(struct irq_data *d)
 {
-	VIC1_INTENCLR = (1 << irq);
+	VIC1_INTENCLR = (1 << d->irq);
 }
 
-static void lh7a404_vic1_unmask_irq (u32 irq)
+static void lh7a404_vic1_unmask_irq(struct irq_data *d)
 {
-	VIC1_INTEN = (1 << irq);
+	VIC1_INTEN = (1 << d->irq);
 }
 
-static void lh7a404_vic2_mask_irq (u32 irq)
+static void lh7a404_vic2_mask_irq(struct irq_data *d)
 {
-	VIC2_INTENCLR = (1 << (irq - 32));
+	VIC2_INTENCLR = (1 << (d->irq - 32));
 }
 
-static void lh7a404_vic2_unmask_irq (u32 irq)
+static void lh7a404_vic2_unmask_irq(struct irq_data *d)
 {
-	VIC2_INTEN = (1 << (irq - 32));
+	VIC2_INTEN = (1 << (d->irq - 32));
 }
 
-static void lh7a404_vic1_ack_gpio_irq (u32 irq)
+static void lh7a404_vic1_ack_gpio_irq(struct irq_data *d)
 {
-	GPIO_GPIOFEOI = (1 << IRQ_TO_GPIO (irq));
-	VIC1_INTENCLR = (1 << irq);
+	GPIO_GPIOFEOI = (1 << IRQ_TO_GPIO (d->irq));
+	VIC1_INTENCLR = (1 << d->irq);
 }
 
-static void lh7a404_vic2_ack_gpio_irq (u32 irq)
+static void lh7a404_vic2_ack_gpio_irq(struct irq_data *d)
 {
-	GPIO_GPIOFEOI = (1 << IRQ_TO_GPIO (irq));
-	VIC2_INTENCLR = (1 << irq);
+	GPIO_GPIOFEOI = (1 << IRQ_TO_GPIO (d->irq));
+	VIC2_INTENCLR = (1 << d->irq);
 }
 
 static struct irq_chip lh7a404_vic1_chip = {
-	.name	= "VIC1",
-	.ack	= lh7a404_vic1_mask_irq, /* Because level-triggered */
-	.mask	= lh7a404_vic1_mask_irq,
-	.unmask	= lh7a404_vic1_unmask_irq,
+	.name		= "VIC1",
+	.irq_ack	= lh7a404_vic1_mask_irq, /* Because level-triggered */
+	.irq_mask	= lh7a404_vic1_mask_irq,
+	.irq_unmask	= lh7a404_vic1_unmask_irq,
 };
 
 static struct irq_chip lh7a404_vic2_chip = {
-	.name	= "VIC2",
-	.ack	= lh7a404_vic2_mask_irq, /* Because level-triggered */
-	.mask	= lh7a404_vic2_mask_irq,
-	.unmask	= lh7a404_vic2_unmask_irq,
+	.name		= "VIC2",
+	.irq_ack	= lh7a404_vic2_mask_irq, /* Because level-triggered */
+	.irq_mask	= lh7a404_vic2_mask_irq,
+	.irq_unmask	= lh7a404_vic2_unmask_irq,
 };
 
 static struct irq_chip lh7a404_gpio_vic1_chip = {
-	.name	= "GPIO-VIC1",
-	.ack	= lh7a404_vic1_ack_gpio_irq,
-	.mask	= lh7a404_vic1_mask_irq,
-	.unmask	= lh7a404_vic1_unmask_irq,
+	.name		= "GPIO-VIC1",
+	.irq_ack	= lh7a404_vic1_ack_gpio_irq,
+	.irq_mask	= lh7a404_vic1_mask_irq,
+	.irq_unmask	= lh7a404_vic1_unmask_irq,
 };
 
 static struct irq_chip lh7a404_gpio_vic2_chip = {
-	.name	= "GPIO-VIC2",
-	.ack	= lh7a404_vic2_ack_gpio_irq,
-	.mask	= lh7a404_vic2_mask_irq,
-	.unmask	= lh7a404_vic2_unmask_irq,
+	.name		= "GPIO-VIC2",
+	.irq_ack	= lh7a404_vic2_ack_gpio_irq,
+	.irq_mask	= lh7a404_vic2_mask_irq,
+	.irq_unmask	= lh7a404_vic2_unmask_irq,
 };
 
   /* IRQ initialization */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-lh7a40x/irq-lpd7a40x.c linux-libre-2.6.38-gnu1/arch/arm/mach-lh7a40x/irq-lpd7a40x.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-lh7a40x/irq-lpd7a40x.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-lh7a40x/irq-lpd7a40x.c	2011-03-14 21:20:32.000000000 -0400
@@ -20,14 +20,14 @@
 
 #include "common.h"
 
-static void lh7a40x_ack_cpld_irq (u32 irq)
+static void lh7a40x_ack_cpld_irq(struct irq_data *d)
 {
 	/* CPLD doesn't have ack capability */
 }
 
-static void lh7a40x_mask_cpld_irq (u32 irq)
+static void lh7a40x_mask_cpld_irq(struct irq_data *d)
 {
-	switch (irq) {
+	switch (d->irq) {
 	case IRQ_LPD7A40X_ETH_INT:
 		CPLD_INTERRUPTS = CPLD_INTERRUPTS | 0x4;
 		break;
@@ -37,9 +37,9 @@ static void lh7a40x_mask_cpld_irq (u32 i
 	}
 }
 
-static void lh7a40x_unmask_cpld_irq (u32 irq)
+static void lh7a40x_unmask_cpld_irq(struct irq_data *d)
 {
-	switch (irq) {
+	switch (d->irq) {
 	case IRQ_LPD7A40X_ETH_INT:
 		CPLD_INTERRUPTS = CPLD_INTERRUPTS & ~ 0x4;
 		break;
@@ -50,17 +50,17 @@ static void lh7a40x_unmask_cpld_irq (u32
 }
 
 static struct irq_chip lh7a40x_cpld_chip = {
-	.name	= "CPLD",
-	.ack	= lh7a40x_ack_cpld_irq,
-	.mask	= lh7a40x_mask_cpld_irq,
-	.unmask	= lh7a40x_unmask_cpld_irq,
+	.name		= "CPLD",
+	.irq_ack	= lh7a40x_ack_cpld_irq,
+	.irq_mask	= lh7a40x_mask_cpld_irq,
+	.irq_unmask	= lh7a40x_unmask_cpld_irq,
 };
 
 static void lh7a40x_cpld_handler (unsigned int irq, struct irq_desc *desc)
 {
 	unsigned int mask = CPLD_INTERRUPTS;
 
-	desc->chip->ack (irq);
+	desc->irq_data.chip->ack (irq);
 
 	if ((mask & 0x1) == 0)	/* WLAN */
 		generic_handle_irq(IRQ_LPD7A40X_ETH_INT);
@@ -68,7 +68,7 @@ static void lh7a40x_cpld_handler (unsign
 	if ((mask & 0x2) == 0)	/* Touch */
 		generic_handle_irq(IRQ_LPD7A400_TS);
 
-	desc->chip->unmask (irq); /* Level-triggered need this */
+	desc->irq_data.chip->unmask (irq); /* Level-triggered need this */
 }
 
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-lpc32xx/clock.c linux-libre-2.6.38-gnu1/arch/arm/mach-lpc32xx/clock.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-lpc32xx/clock.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-lpc32xx/clock.c	2011-03-14 21:20:32.000000000 -0400
@@ -90,10 +90,9 @@
 #include <linux/clk.h>
 #include <linux/amba/bus.h>
 #include <linux/amba/clcd.h>
+#include <linux/clkdev.h>
 
 #include <mach/hardware.h>
-#include <asm/clkdev.h>
-#include <mach/clkdev.h>
 #include <mach/platform.h>
 #include "clock.h"
 #include "common.h"
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-lpc32xx/irq.c linux-libre-2.6.38-gnu1/arch/arm/mach-lpc32xx/irq.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-lpc32xx/irq.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-lpc32xx/irq.c	2011-03-14 21:20:32.000000000 -0400
@@ -191,38 +191,38 @@ static void get_controller(unsigned int
 	}
 }
 
-static void lpc32xx_mask_irq(unsigned int irq)
+static void lpc32xx_mask_irq(struct irq_data *d)
 {
 	unsigned int reg, ctrl, mask;
 
-	get_controller(irq, &ctrl, &mask);
+	get_controller(d->irq, &ctrl, &mask);
 
 	reg = __raw_readl(LPC32XX_INTC_MASK(ctrl)) & ~mask;
 	__raw_writel(reg, LPC32XX_INTC_MASK(ctrl));
 }
 
-static void lpc32xx_unmask_irq(unsigned int irq)
+static void lpc32xx_unmask_irq(struct irq_data *d)
 {
 	unsigned int reg, ctrl, mask;
 
-	get_controller(irq, &ctrl, &mask);
+	get_controller(d->irq, &ctrl, &mask);
 
 	reg = __raw_readl(LPC32XX_INTC_MASK(ctrl)) | mask;
 	__raw_writel(reg, LPC32XX_INTC_MASK(ctrl));
 }
 
-static void lpc32xx_ack_irq(unsigned int irq)
+static void lpc32xx_ack_irq(struct irq_data *d)
 {
 	unsigned int ctrl, mask;
 
-	get_controller(irq, &ctrl, &mask);
+	get_controller(d->irq, &ctrl, &mask);
 
 	__raw_writel(mask, LPC32XX_INTC_RAW_STAT(ctrl));
 
 	/* Also need to clear pending wake event */
-	if (lpc32xx_events[irq].mask != 0)
-		__raw_writel(lpc32xx_events[irq].mask,
-			lpc32xx_events[irq].event_group->rawstat_reg);
+	if (lpc32xx_events[d->irq].mask != 0)
+		__raw_writel(lpc32xx_events[d->irq].mask,
+			lpc32xx_events[d->irq].event_group->rawstat_reg);
 }
 
 static void __lpc32xx_set_irq_type(unsigned int irq, int use_high_level,
@@ -261,27 +261,27 @@ static void __lpc32xx_set_irq_type(unsig
 	}
 }
 
-static int lpc32xx_set_irq_type(unsigned int irq, unsigned int type)
+static int lpc32xx_set_irq_type(struct irq_data *d, unsigned int type)
 {
 	switch (type) {
 	case IRQ_TYPE_EDGE_RISING:
 		/* Rising edge sensitive */
-		__lpc32xx_set_irq_type(irq, 1, 1);
+		__lpc32xx_set_irq_type(d->irq, 1, 1);
 		break;
 
 	case IRQ_TYPE_EDGE_FALLING:
 		/* Falling edge sensitive */
-		__lpc32xx_set_irq_type(irq, 0, 1);
+		__lpc32xx_set_irq_type(d->irq, 0, 1);
 		break;
 
 	case IRQ_TYPE_LEVEL_LOW:
 		/* Low level sensitive */
-		__lpc32xx_set_irq_type(irq, 0, 0);
+		__lpc32xx_set_irq_type(d->irq, 0, 0);
 		break;
 
 	case IRQ_TYPE_LEVEL_HIGH:
 		/* High level sensitive */
-		__lpc32xx_set_irq_type(irq, 1, 0);
+		__lpc32xx_set_irq_type(d->irq, 1, 0);
 		break;
 
 	/* Other modes are not supported */
@@ -290,33 +290,33 @@ static int lpc32xx_set_irq_type(unsigned
 	}
 
 	/* Ok to use the level handler for all types */
-	set_irq_handler(irq, handle_level_irq);
+	set_irq_handler(d->irq, handle_level_irq);
 
 	return 0;
 }
 
-static int lpc32xx_irq_wake(unsigned int irqno, unsigned int state)
+static int lpc32xx_irq_wake(struct irq_data *d, unsigned int state)
 {
 	unsigned long eventreg;
 
-	if (lpc32xx_events[irqno].mask != 0) {
-		eventreg = __raw_readl(lpc32xx_events[irqno].
+	if (lpc32xx_events[d->irq].mask != 0) {
+		eventreg = __raw_readl(lpc32xx_events[d->irq].
 			event_group->enab_reg);
 
 		if (state)
-			eventreg |= lpc32xx_events[irqno].mask;
+			eventreg |= lpc32xx_events[d->irq].mask;
 		else
-			eventreg &= ~lpc32xx_events[irqno].mask;
+			eventreg &= ~lpc32xx_events[d->irq].mask;
 
 		__raw_writel(eventreg,
-			lpc32xx_events[irqno].event_group->enab_reg);
+			lpc32xx_events[d->irq].event_group->enab_reg);
 
 		return 0;
 	}
 
 	/* Clear event */
-	__raw_writel(lpc32xx_events[irqno].mask,
-		lpc32xx_events[irqno].event_group->rawstat_reg);
+	__raw_writel(lpc32xx_events[d->irq].mask,
+		lpc32xx_events[d->irq].event_group->rawstat_reg);
 
 	return -ENODEV;
 }
@@ -336,11 +336,11 @@ static void __init lpc32xx_set_default_m
 }
 
 static struct irq_chip lpc32xx_irq_chip = {
-	.ack = lpc32xx_ack_irq,
-	.mask = lpc32xx_mask_irq,
-	.unmask = lpc32xx_unmask_irq,
-	.set_type = lpc32xx_set_irq_type,
-	.set_wake = lpc32xx_irq_wake
+	.irq_ack = lpc32xx_ack_irq,
+	.irq_mask = lpc32xx_mask_irq,
+	.irq_unmask = lpc32xx_unmask_irq,
+	.irq_set_type = lpc32xx_set_irq_type,
+	.irq_set_wake = lpc32xx_irq_wake
 };
 
 static void lpc32xx_sic1_handler(unsigned int irq, struct irq_desc *desc)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-lpc32xx/pm.c linux-libre-2.6.38-gnu1/arch/arm/mach-lpc32xx/pm.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-lpc32xx/pm.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-lpc32xx/pm.c	2011-03-14 21:20:32.000000000 -0400
@@ -123,7 +123,7 @@ static int lpc32xx_pm_enter(suspend_stat
 	return 0;
 }
 
-static struct platform_suspend_ops lpc32xx_pm_ops = {
+static const struct platform_suspend_ops lpc32xx_pm_ops = {
 	.valid	= suspend_valid_only_mem,
 	.enter	= lpc32xx_pm_enter,
 };
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-lpc32xx/timer.c linux-libre-2.6.38-gnu1/arch/arm/mach-lpc32xx/timer.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-lpc32xx/timer.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-lpc32xx/timer.c	2011-03-14 21:20:32.000000000 -0400
@@ -38,7 +38,6 @@ static cycle_t lpc32xx_clksrc_read(struc
 
 static struct clocksource lpc32xx_clksrc = {
 	.name	= "lpc32xx_clksrc",
-	.shift	= 24,
 	.rating	= 300,
 	.read	= lpc32xx_clksrc_read,
 	.mask	= CLOCKSOURCE_MASK(32),
@@ -171,9 +170,7 @@ static void __init lpc32xx_timer_init(vo
 	__raw_writel(0, LCP32XX_TIMER_MCR(LPC32XX_TIMER1_BASE));
 	__raw_writel(LCP32XX_TIMER_CNTR_TCR_EN,
 		LCP32XX_TIMER_TCR(LPC32XX_TIMER1_BASE));
-	lpc32xx_clksrc.mult = clocksource_hz2mult(clkrate,
-		lpc32xx_clksrc.shift);
-	clocksource_register(&lpc32xx_clksrc);
+	clocksource_register_hz(&lpc32xx_clksrc, clkrate);
 }
 
 struct sys_timer lpc32xx_timer = {
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mmp/brownstone.c linux-libre-2.6.38-gnu1/arch/arm/mach-mmp/brownstone.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mmp/brownstone.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mmp/brownstone.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,204 @@
+/*
+ *  linux/arch/arm/mach-mmp/brownstone.c
+ *
+ *  Support for the Marvell Brownstone Development Platform.
+ *
+ *  Copyright (C) 2009-2010 Marvell International 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
+ *  publishhed by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#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>
+#include <linux/mfd/max8925.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <mach/addr-map.h>
+#include <mach/mfp-mmp2.h>
+#include <mach/mmp2.h>
+#include <mach/irqs.h>
+
+#include "common.h"
+
+#define BROWNSTONE_NR_IRQS	(IRQ_BOARD_START + 40)
+
+#define GPIO_5V_ENABLE		(89)
+
+static unsigned long brownstone_pin_config[] __initdata = {
+	/* UART1 */
+	GPIO29_UART1_RXD,
+	GPIO30_UART1_TXD,
+
+	/* UART3 */
+	GPIO51_UART3_RXD,
+	GPIO52_UART3_TXD,
+
+	/* DFI */
+	GPIO168_DFI_D0,
+	GPIO167_DFI_D1,
+	GPIO166_DFI_D2,
+	GPIO165_DFI_D3,
+	GPIO107_DFI_D4,
+	GPIO106_DFI_D5,
+	GPIO105_DFI_D6,
+	GPIO104_DFI_D7,
+	GPIO111_DFI_D8,
+	GPIO164_DFI_D9,
+	GPIO163_DFI_D10,
+	GPIO162_DFI_D11,
+	GPIO161_DFI_D12,
+	GPIO110_DFI_D13,
+	GPIO109_DFI_D14,
+	GPIO108_DFI_D15,
+	GPIO143_ND_nCS0,
+	GPIO144_ND_nCS1,
+	GPIO147_ND_nWE,
+	GPIO148_ND_nRE,
+	GPIO150_ND_ALE,
+	GPIO149_ND_CLE,
+	GPIO112_ND_RDY0,
+	GPIO160_ND_RDY1,
+
+	/* PMIC */
+	PMIC_PMIC_INT | MFP_LPM_EDGE_FALL,
+
+	/* MMC0 */
+	GPIO131_MMC1_DAT3 | MFP_PULL_HIGH,
+	GPIO132_MMC1_DAT2 | MFP_PULL_HIGH,
+	GPIO133_MMC1_DAT1 | MFP_PULL_HIGH,
+	GPIO134_MMC1_DAT0 | MFP_PULL_HIGH,
+	GPIO136_MMC1_CMD | MFP_PULL_HIGH,
+	GPIO139_MMC1_CLK,
+	GPIO140_MMC1_CD | MFP_PULL_LOW,
+	GPIO141_MMC1_WP | MFP_PULL_LOW,
+
+	/* MMC1 */
+	GPIO37_MMC2_DAT3 | MFP_PULL_HIGH,
+	GPIO38_MMC2_DAT2 | MFP_PULL_HIGH,
+	GPIO39_MMC2_DAT1 | MFP_PULL_HIGH,
+	GPIO40_MMC2_DAT0 | MFP_PULL_HIGH,
+	GPIO41_MMC2_CMD | MFP_PULL_HIGH,
+	GPIO42_MMC2_CLK,
+
+	/* MMC2 */
+	GPIO165_MMC3_DAT7 | MFP_PULL_HIGH,
+	GPIO162_MMC3_DAT6 | MFP_PULL_HIGH,
+	GPIO166_MMC3_DAT5 | MFP_PULL_HIGH,
+	GPIO163_MMC3_DAT4 | MFP_PULL_HIGH,
+	GPIO167_MMC3_DAT3 | MFP_PULL_HIGH,
+	GPIO164_MMC3_DAT2 | MFP_PULL_HIGH,
+	GPIO168_MMC3_DAT1 | MFP_PULL_HIGH,
+	GPIO111_MMC3_DAT0 | MFP_PULL_HIGH,
+	GPIO112_MMC3_CMD | MFP_PULL_HIGH,
+	GPIO151_MMC3_CLK,
+
+	/* 5V regulator */
+	GPIO89_GPIO,
+};
+
+static struct regulator_consumer_supply max8649_supply[] = {
+	REGULATOR_SUPPLY("vcc_core", NULL),
+};
+
+static struct regulator_init_data max8649_init_data = {
+	.constraints	= {
+		.name		= "vcc_core range",
+		.min_uV		= 1150000,
+		.max_uV		= 1280000,
+		.always_on	= 1,
+		.boot_on	= 1,
+		.valid_ops_mask	= REGULATOR_CHANGE_VOLTAGE,
+	},
+	.num_consumer_supplies	= 1,
+	.consumer_supplies	= &max8649_supply[0],
+};
+
+static struct max8649_platform_data brownstone_max8649_info = {
+	.mode		= 2,	/* VID1 = 1, VID0 = 0 */
+	.extclk		= 0,
+	.ramp_timing	= MAX8649_RAMP_32MV,
+	.regulator	= &max8649_init_data,
+};
+
+static struct regulator_consumer_supply brownstone_v_5vp_supplies[] = {
+	REGULATOR_SUPPLY("v_5vp", NULL),
+};
+
+static struct regulator_init_data brownstone_v_5vp_data = {
+	.constraints	= {
+		.valid_ops_mask		= REGULATOR_CHANGE_STATUS,
+	},
+	.num_consumer_supplies	= ARRAY_SIZE(brownstone_v_5vp_supplies),
+	.consumer_supplies	= brownstone_v_5vp_supplies,
+};
+
+static struct fixed_voltage_config brownstone_v_5vp = {
+	.supply_name		= "v_5vp",
+	.microvolts		= 5000000,
+	.gpio			= GPIO_5V_ENABLE,
+	.enable_high		= 1,
+	.enabled_at_boot	= 1,
+	.init_data		= &brownstone_v_5vp_data,
+};
+
+static struct platform_device brownstone_v_5vp_device = {
+	.name		= "reg-fixed-voltage",
+	.id		= 1,
+	.dev = {
+		.platform_data = &brownstone_v_5vp,
+	},
+};
+
+static struct max8925_platform_data brownstone_max8925_info = {
+	.irq_base		= IRQ_BOARD_START,
+};
+
+static struct i2c_board_info brownstone_twsi1_info[] = {
+	[0] = {
+		.type		= "max8649",
+		.addr		= 0x60,
+		.platform_data	= &brownstone_max8649_info,
+	},
+	[1] = {
+		.type		= "max8925",
+		.addr		= 0x3c,
+		.irq		= IRQ_MMP2_PMIC,
+		.platform_data	= &brownstone_max8925_info,
+	},
+};
+
+static struct sdhci_pxa_platdata mmp2_sdh_platdata_mmc0 = {
+	.max_speed	= 25000000,
+};
+
+static void __init brownstone_init(void)
+{
+	mfp_config(ARRAY_AND_SIZE(brownstone_pin_config));
+
+	/* on-chip devices */
+	mmp2_add_uart(1);
+	mmp2_add_uart(3);
+	mmp2_add_twsi(1, NULL, ARRAY_AND_SIZE(brownstone_twsi1_info));
+	mmp2_add_sdhost(0, &mmp2_sdh_platdata_mmc0); /* SD/MMC */
+
+	/* enable 5v regulator */
+	platform_device_register(&brownstone_v_5vp_device);
+}
+
+MACHINE_START(BROWNSTONE, "Brownstone Development Platform")
+	/* Maintainer: Haojian Zhuang <haojian.zhuang@marvell.com> */
+	.map_io		= mmp_map_io,
+	.nr_irqs	= BROWNSTONE_NR_IRQS,
+	.init_irq	= mmp2_init_irq,
+	.timer		= &mmp2_timer,
+	.init_machine	= brownstone_init,
+MACHINE_END
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mmp/clock.h linux-libre-2.6.38-gnu1/arch/arm/mach-mmp/clock.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mmp/clock.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mmp/clock.h	2011-03-14 21:20:32.000000000 -0400
@@ -6,7 +6,7 @@
  *  published by the Free Software Foundation.
  */
 
-#include <asm/clkdev.h>
+#include <linux/clkdev.h>
 
 struct clkops {
 	void			(*enable)(struct clk *);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mmp/flint.c linux-libre-2.6.38-gnu1/arch/arm/mach-mmp/flint.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mmp/flint.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mmp/flint.c	2011-03-14 21:20:32.000000000 -0400
@@ -47,7 +47,7 @@ static unsigned long flint_pin_config[]
 	GPIO113_SMC_RDY,
 
 	/*Ethernet*/
-	GPIO155_GPIO155,
+	GPIO155_GPIO,
 
 	/* DFI */
 	GPIO168_DFI_D0,
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mmp/include/mach/mfp-mmp2.h linux-libre-2.6.38-gnu1/arch/arm/mach-mmp/include/mach/mfp-mmp2.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mmp/include/mach/mfp-mmp2.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mmp/include/mach/mfp-mmp2.h	2011-03-14 21:20:32.000000000 -0400
@@ -6,178 +6,178 @@
 #define MFP_DRIVE_VERY_SLOW	(0x0 << 13)
 #define MFP_DRIVE_SLOW		(0x2 << 13)
 #define MFP_DRIVE_MEDIUM	(0x4 << 13)
-#define MFP_DRIVE_FAST		(0x8 << 13)
+#define MFP_DRIVE_FAST		(0x6 << 13)
 
 /* GPIO */
-#define GPIO0_GPIO0		MFP_CFG(GPIO0, AF0)
-#define GPIO1_GPIO1		MFP_CFG(GPIO1, AF0)
-#define GPIO2_GPIO2		MFP_CFG(GPIO2, AF0)
-#define GPIO3_GPIO3		MFP_CFG(GPIO3, AF0)
-#define GPIO4_GPIO4		MFP_CFG(GPIO4, AF0)
-#define GPIO5_GPIO5		MFP_CFG(GPIO5, AF0)
-#define GPIO6_GPIO6		MFP_CFG(GPIO6, AF0)
-#define GPIO7_GPIO7		MFP_CFG(GPIO7, AF0)
-#define GPIO8_GPIO8		MFP_CFG(GPIO8, AF0)
-#define GPIO9_GPIO9		MFP_CFG(GPIO9, AF0)
-#define GPIO10_GPIO10		MFP_CFG(GPIO10, AF0)
-#define GPIO11_GPIO11		MFP_CFG(GPIO11, AF0)
-#define GPIO12_GPIO12		MFP_CFG(GPIO12, AF0)
-#define GPIO13_GPIO13		MFP_CFG(GPIO13, AF0)
-#define GPIO14_GPIO14		MFP_CFG(GPIO14, AF0)
-#define GPIO15_GPIO15		MFP_CFG(GPIO15, AF0)
-#define GPIO16_GPIO16		MFP_CFG(GPIO16, AF0)
-#define GPIO17_GPIO17		MFP_CFG(GPIO17, AF0)
-#define GPIO18_GPIO18		MFP_CFG(GPIO18, AF0)
-#define GPIO19_GPIO19		MFP_CFG(GPIO19, AF0)
-#define GPIO20_GPIO20		MFP_CFG(GPIO20, AF0)
-#define GPIO21_GPIO21		MFP_CFG(GPIO21, AF0)
-#define GPIO22_GPIO22		MFP_CFG(GPIO22, AF0)
-#define GPIO23_GPIO23		MFP_CFG(GPIO23, AF0)
-#define GPIO24_GPIO24		MFP_CFG(GPIO24, AF0)
-#define GPIO25_GPIO25		MFP_CFG(GPIO25, AF0)
-#define GPIO26_GPIO26		MFP_CFG(GPIO26, AF0)
-#define GPIO27_GPIO27		MFP_CFG(GPIO27, AF0)
-#define GPIO28_GPIO28		MFP_CFG(GPIO28, AF0)
-#define GPIO29_GPIO29		MFP_CFG(GPIO29, AF0)
-#define GPIO30_GPIO30		MFP_CFG(GPIO30, AF0)
-#define GPIO31_GPIO31		MFP_CFG(GPIO31, AF0)
-#define GPIO32_GPIO32		MFP_CFG(GPIO32, AF0)
-#define GPIO33_GPIO33		MFP_CFG(GPIO33, AF0)
-#define GPIO34_GPIO34		MFP_CFG(GPIO34, AF0)
-#define GPIO35_GPIO35		MFP_CFG(GPIO35, AF0)
-#define GPIO36_GPIO36		MFP_CFG(GPIO36, AF0)
-#define GPIO37_GPIO37		MFP_CFG(GPIO37, AF0)
-#define GPIO38_GPIO38		MFP_CFG(GPIO38, AF0)
-#define GPIO39_GPIO39		MFP_CFG(GPIO39, AF0)
-#define GPIO40_GPIO40		MFP_CFG(GPIO40, AF0)
-#define GPIO41_GPIO41		MFP_CFG(GPIO41, AF0)
-#define GPIO42_GPIO42		MFP_CFG(GPIO42, AF0)
-#define GPIO43_GPIO43		MFP_CFG(GPIO43, AF0)
-#define GPIO44_GPIO44		MFP_CFG(GPIO44, AF0)
-#define GPIO45_GPIO45		MFP_CFG(GPIO45, AF0)
-#define GPIO46_GPIO46		MFP_CFG(GPIO46, AF0)
-#define GPIO47_GPIO47		MFP_CFG(GPIO47, AF0)
-#define GPIO48_GPIO48		MFP_CFG(GPIO48, AF0)
-#define GPIO49_GPIO49		MFP_CFG(GPIO49, AF0)
-#define GPIO50_GPIO50		MFP_CFG(GPIO50, AF0)
-#define GPIO51_GPIO51		MFP_CFG(GPIO51, AF0)
-#define GPIO52_GPIO52		MFP_CFG(GPIO52, AF0)
-#define GPIO53_GPIO53		MFP_CFG(GPIO53, AF0)
-#define GPIO54_GPIO54		MFP_CFG(GPIO54, AF0)
-#define GPIO55_GPIO55		MFP_CFG(GPIO55, AF0)
-#define GPIO56_GPIO56		MFP_CFG(GPIO56, AF0)
-#define GPIO57_GPIO57		MFP_CFG(GPIO57, AF0)
-#define GPIO58_GPIO58		MFP_CFG(GPIO58, AF0)
-#define GPIO59_GPIO59		MFP_CFG(GPIO59, AF0)
-#define GPIO60_GPIO60		MFP_CFG(GPIO60, AF0)
-#define GPIO61_GPIO61		MFP_CFG(GPIO61, AF0)
-#define GPIO62_GPIO62		MFP_CFG(GPIO62, AF0)
-#define GPIO63_GPIO63		MFP_CFG(GPIO63, AF0)
-#define GPIO64_GPIO64		MFP_CFG(GPIO64, AF0)
-#define GPIO65_GPIO65		MFP_CFG(GPIO65, AF0)
-#define GPIO66_GPIO66		MFP_CFG(GPIO66, AF0)
-#define GPIO67_GPIO67		MFP_CFG(GPIO67, AF0)
-#define GPIO68_GPIO68		MFP_CFG(GPIO68, AF0)
-#define GPIO69_GPIO69		MFP_CFG(GPIO69, AF0)
-#define GPIO70_GPIO70		MFP_CFG(GPIO70, AF0)
-#define GPIO71_GPIO71		MFP_CFG(GPIO71, AF0)
-#define GPIO72_GPIO72		MFP_CFG(GPIO72, AF0)
-#define GPIO73_GPIO73		MFP_CFG(GPIO73, AF0)
-#define GPIO74_GPIO74		MFP_CFG(GPIO74, AF0)
-#define GPIO75_GPIO75		MFP_CFG(GPIO75, AF0)
-#define GPIO76_GPIO76		MFP_CFG(GPIO76, AF0)
-#define GPIO77_GPIO77		MFP_CFG(GPIO77, AF0)
-#define GPIO78_GPIO78		MFP_CFG(GPIO78, AF0)
-#define GPIO79_GPIO79		MFP_CFG(GPIO79, AF0)
-#define GPIO80_GPIO80		MFP_CFG(GPIO80, AF0)
-#define GPIO81_GPIO81		MFP_CFG(GPIO81, AF0)
-#define GPIO82_GPIO82		MFP_CFG(GPIO82, AF0)
-#define GPIO83_GPIO83		MFP_CFG(GPIO83, AF0)
-#define GPIO84_GPIO84		MFP_CFG(GPIO84, AF0)
-#define GPIO85_GPIO85		MFP_CFG(GPIO85, AF0)
-#define GPIO86_GPIO86		MFP_CFG(GPIO86, AF0)
-#define GPIO87_GPIO87		MFP_CFG(GPIO87, AF0)
-#define GPIO88_GPIO88		MFP_CFG(GPIO88, AF0)
-#define GPIO89_GPIO89		MFP_CFG(GPIO89, AF0)
-#define GPIO90_GPIO90		MFP_CFG(GPIO90, AF0)
-#define GPIO91_GPIO91		MFP_CFG(GPIO91, AF0)
-#define GPIO92_GPIO92		MFP_CFG(GPIO92, AF0)
-#define GPIO93_GPIO93		MFP_CFG(GPIO93, AF0)
-#define GPIO94_GPIO94		MFP_CFG(GPIO94, AF0)
-#define GPIO95_GPIO95		MFP_CFG(GPIO95, AF0)
-#define GPIO96_GPIO96		MFP_CFG(GPIO96, AF0)
-#define GPIO97_GPIO97		MFP_CFG(GPIO97, AF0)
-#define GPIO98_GPIO98		MFP_CFG(GPIO98, AF0)
-#define GPIO99_GPIO99		MFP_CFG(GPIO99, AF0)
-#define GPIO100_GPIO100		MFP_CFG(GPIO100, AF0)
-#define GPIO101_GPIO101		MFP_CFG(GPIO101, AF0)
-#define GPIO102_GPIO102		MFP_CFG(GPIO102, AF1)
-#define GPIO103_GPIO103		MFP_CFG(GPIO103, AF1)
-#define GPIO104_GPIO104		MFP_CFG(GPIO104, AF1)
-#define GPIO105_GPIO105		MFP_CFG(GPIO105, AF1)
-#define GPIO106_GPIO106		MFP_CFG(GPIO106, AF1)
-#define GPIO107_GPIO107		MFP_CFG(GPIO107, AF1)
-#define GPIO108_GPIO108		MFP_CFG(GPIO108, AF1)
-#define GPIO109_GPIO109		MFP_CFG(GPIO109, AF1)
-#define GPIO110_GPIO110		MFP_CFG(GPIO110, AF1)
-#define GPIO111_GPIO111		MFP_CFG(GPIO111, AF1)
-#define GPIO112_GPIO112		MFP_CFG(GPIO112, AF1)
-#define GPIO113_GPIO113		MFP_CFG(GPIO113, AF1)
-#define GPIO114_GPIO114		MFP_CFG(GPIO114, AF0)
-#define GPIO115_GPIO115		MFP_CFG(GPIO115, AF0)
-#define GPIO116_GPIO116		MFP_CFG(GPIO116, AF0)
-#define GPIO117_GPIO117		MFP_CFG(GPIO117, AF0)
-#define GPIO118_GPIO118		MFP_CFG(GPIO118, AF0)
-#define GPIO119_GPIO119		MFP_CFG(GPIO119, AF0)
-#define GPIO120_GPIO120		MFP_CFG(GPIO120, AF0)
-#define GPIO121_GPIO121		MFP_CFG(GPIO121, AF0)
-#define GPIO122_GPIO122		MFP_CFG(GPIO122, AF0)
-#define GPIO123_GPIO123		MFP_CFG(GPIO123, AF0)
-#define GPIO124_GPIO124		MFP_CFG(GPIO124, AF0)
-#define GPIO125_GPIO125		MFP_CFG(GPIO125, AF0)
-#define GPIO126_GPIO126		MFP_CFG(GPIO126, AF0)
-#define GPIO127_GPIO127		MFP_CFG(GPIO127, AF0)
-#define GPIO128_GPIO128		MFP_CFG(GPIO128, AF0)
-#define GPIO129_GPIO129		MFP_CFG(GPIO129, AF0)
-#define GPIO130_GPIO130		MFP_CFG(GPIO130, AF0)
-#define GPIO131_GPIO131		MFP_CFG(GPIO131, AF0)
-#define GPIO132_GPIO132		MFP_CFG(GPIO132, AF0)
-#define GPIO133_GPIO133		MFP_CFG(GPIO133, AF0)
-#define GPIO134_GPIO134		MFP_CFG(GPIO134, AF0)
-#define GPIO135_GPIO135		MFP_CFG(GPIO135, AF0)
-#define GPIO136_GPIO136		MFP_CFG(GPIO136, AF0)
-#define GPIO137_GPIO137		MFP_CFG(GPIO137, AF0)
-#define GPIO138_GPIO138		MFP_CFG(GPIO138, AF0)
-#define GPIO139_GPIO139		MFP_CFG(GPIO139, AF0)
-#define GPIO140_GPIO140		MFP_CFG(GPIO140, AF0)
-#define GPIO141_GPIO141		MFP_CFG(GPIO141, AF0)
-#define GPIO142_GPIO142		MFP_CFG(GPIO142, AF1)
-#define GPIO143_GPIO143		MFP_CFG(GPIO143, AF1)
-#define GPIO144_GPIO144		MFP_CFG(GPIO144, AF1)
-#define GPIO145_GPIO145		MFP_CFG(GPIO145, AF1)
-#define GPIO146_GPIO146		MFP_CFG(GPIO146, AF1)
-#define GPIO147_GPIO147		MFP_CFG(GPIO147, AF1)
-#define GPIO148_GPIO148		MFP_CFG(GPIO148, AF1)
-#define GPIO149_GPIO149		MFP_CFG(GPIO149, AF1)
-#define GPIO150_GPIO150		MFP_CFG(GPIO150, AF1)
-#define GPIO151_GPIO151		MFP_CFG(GPIO151, AF1)
-#define GPIO152_GPIO152		MFP_CFG(GPIO152, AF1)
-#define GPIO153_GPIO153		MFP_CFG(GPIO153, AF1)
-#define GPIO154_GPIO154		MFP_CFG(GPIO154, AF1)
-#define GPIO155_GPIO155		MFP_CFG(GPIO155, AF1)
-#define GPIO156_GPIO156		MFP_CFG(GPIO156, AF1)
-#define GPIO157_GPIO157		MFP_CFG(GPIO157, AF1)
-#define GPIO158_GPIO158		MFP_CFG(GPIO158, AF1)
-#define GPIO159_GPIO159		MFP_CFG(GPIO159, AF1)
-#define GPIO160_GPIO160		MFP_CFG(GPIO160, AF1)
-#define GPIO161_GPIO161		MFP_CFG(GPIO161, AF1)
-#define GPIO162_GPIO162		MFP_CFG(GPIO162, AF1)
-#define GPIO163_GPIO163		MFP_CFG(GPIO163, AF1)
-#define GPIO164_GPIO164		MFP_CFG(GPIO164, AF1)
-#define GPIO165_GPIO165		MFP_CFG(GPIO165, AF1)
-#define GPIO166_GPIO166		MFP_CFG(GPIO166, AF1)
-#define GPIO167_GPIO167		MFP_CFG(GPIO167, AF1)
-#define GPIO168_GPIO168		MFP_CFG(GPIO168, AF1)
+#define GPIO0_GPIO	MFP_CFG(GPIO0, AF0)
+#define GPIO1_GPIO	MFP_CFG(GPIO1, AF0)
+#define GPIO2_GPIO	MFP_CFG(GPIO2, AF0)
+#define GPIO3_GPIO	MFP_CFG(GPIO3, AF0)
+#define GPIO4_GPIO	MFP_CFG(GPIO4, AF0)
+#define GPIO5_GPIO	MFP_CFG(GPIO5, AF0)
+#define GPIO6_GPIO	MFP_CFG(GPIO6, AF0)
+#define GPIO7_GPIO	MFP_CFG(GPIO7, AF0)
+#define GPIO8_GPIO	MFP_CFG(GPIO8, AF0)
+#define GPIO9_GPIO	MFP_CFG(GPIO9, AF0)
+#define GPIO10_GPIO	MFP_CFG(GPIO10, AF0)
+#define GPIO11_GPIO	MFP_CFG(GPIO11, AF0)
+#define GPIO12_GPIO	MFP_CFG(GPIO12, AF0)
+#define GPIO13_GPIO	MFP_CFG(GPIO13, AF0)
+#define GPIO14_GPIO	MFP_CFG(GPIO14, AF0)
+#define GPIO15_GPIO	MFP_CFG(GPIO15, AF0)
+#define GPIO16_GPIO	MFP_CFG(GPIO16, AF0)
+#define GPIO17_GPIO	MFP_CFG(GPIO17, AF0)
+#define GPIO18_GPIO	MFP_CFG(GPIO18, AF0)
+#define GPIO19_GPIO	MFP_CFG(GPIO19, AF0)
+#define GPIO20_GPIO	MFP_CFG(GPIO20, AF0)
+#define GPIO21_GPIO	MFP_CFG(GPIO21, AF0)
+#define GPIO22_GPIO	MFP_CFG(GPIO22, AF0)
+#define GPIO23_GPIO	MFP_CFG(GPIO23, AF0)
+#define GPIO24_GPIO	MFP_CFG(GPIO24, AF0)
+#define GPIO25_GPIO	MFP_CFG(GPIO25, AF0)
+#define GPIO26_GPIO	MFP_CFG(GPIO26, AF0)
+#define GPIO27_GPIO	MFP_CFG(GPIO27, AF0)
+#define GPIO28_GPIO	MFP_CFG(GPIO28, AF0)
+#define GPIO29_GPIO	MFP_CFG(GPIO29, AF0)
+#define GPIO30_GPIO	MFP_CFG(GPIO30, AF0)
+#define GPIO31_GPIO	MFP_CFG(GPIO31, AF0)
+#define GPIO32_GPIO	MFP_CFG(GPIO32, AF0)
+#define GPIO33_GPIO	MFP_CFG(GPIO33, AF0)
+#define GPIO34_GPIO	MFP_CFG(GPIO34, AF0)
+#define GPIO35_GPIO	MFP_CFG(GPIO35, AF0)
+#define GPIO36_GPIO	MFP_CFG(GPIO36, AF0)
+#define GPIO37_GPIO	MFP_CFG(GPIO37, AF0)
+#define GPIO38_GPIO	MFP_CFG(GPIO38, AF0)
+#define GPIO39_GPIO	MFP_CFG(GPIO39, AF0)
+#define GPIO40_GPIO	MFP_CFG(GPIO40, AF0)
+#define GPIO41_GPIO	MFP_CFG(GPIO41, AF0)
+#define GPIO42_GPIO	MFP_CFG(GPIO42, AF0)
+#define GPIO43_GPIO	MFP_CFG(GPIO43, AF0)
+#define GPIO44_GPIO	MFP_CFG(GPIO44, AF0)
+#define GPIO45_GPIO	MFP_CFG(GPIO45, AF0)
+#define GPIO46_GPIO	MFP_CFG(GPIO46, AF0)
+#define GPIO47_GPIO	MFP_CFG(GPIO47, AF0)
+#define GPIO48_GPIO	MFP_CFG(GPIO48, AF0)
+#define GPIO49_GPIO	MFP_CFG(GPIO49, AF0)
+#define GPIO50_GPIO	MFP_CFG(GPIO50, AF0)
+#define GPIO51_GPIO	MFP_CFG(GPIO51, AF0)
+#define GPIO52_GPIO	MFP_CFG(GPIO52, AF0)
+#define GPIO53_GPIO	MFP_CFG(GPIO53, AF0)
+#define GPIO54_GPIO	MFP_CFG(GPIO54, AF0)
+#define GPIO55_GPIO	MFP_CFG(GPIO55, AF0)
+#define GPIO56_GPIO	MFP_CFG(GPIO56, AF0)
+#define GPIO57_GPIO	MFP_CFG(GPIO57, AF0)
+#define GPIO58_GPIO	MFP_CFG(GPIO58, AF0)
+#define GPIO59_GPIO	MFP_CFG(GPIO59, AF0)
+#define GPIO60_GPIO	MFP_CFG(GPIO60, AF0)
+#define GPIO61_GPIO	MFP_CFG(GPIO61, AF0)
+#define GPIO62_GPIO	MFP_CFG(GPIO62, AF0)
+#define GPIO63_GPIO	MFP_CFG(GPIO63, AF0)
+#define GPIO64_GPIO	MFP_CFG(GPIO64, AF0)
+#define GPIO65_GPIO	MFP_CFG(GPIO65, AF0)
+#define GPIO66_GPIO	MFP_CFG(GPIO66, AF0)
+#define GPIO67_GPIO	MFP_CFG(GPIO67, AF0)
+#define GPIO68_GPIO	MFP_CFG(GPIO68, AF0)
+#define GPIO69_GPIO	MFP_CFG(GPIO69, AF0)
+#define GPIO70_GPIO	MFP_CFG(GPIO70, AF0)
+#define GPIO71_GPIO	MFP_CFG(GPIO71, AF0)
+#define GPIO72_GPIO	MFP_CFG(GPIO72, AF0)
+#define GPIO73_GPIO	MFP_CFG(GPIO73, AF0)
+#define GPIO74_GPIO	MFP_CFG(GPIO74, AF0)
+#define GPIO75_GPIO	MFP_CFG(GPIO75, AF0)
+#define GPIO76_GPIO	MFP_CFG(GPIO76, AF0)
+#define GPIO77_GPIO	MFP_CFG(GPIO77, AF0)
+#define GPIO78_GPIO	MFP_CFG(GPIO78, AF0)
+#define GPIO79_GPIO	MFP_CFG(GPIO79, AF0)
+#define GPIO80_GPIO	MFP_CFG(GPIO80, AF0)
+#define GPIO81_GPIO	MFP_CFG(GPIO81, AF0)
+#define GPIO82_GPIO	MFP_CFG(GPIO82, AF0)
+#define GPIO83_GPIO	MFP_CFG(GPIO83, AF0)
+#define GPIO84_GPIO	MFP_CFG(GPIO84, AF0)
+#define GPIO85_GPIO	MFP_CFG(GPIO85, AF0)
+#define GPIO86_GPIO	MFP_CFG(GPIO86, AF0)
+#define GPIO87_GPIO	MFP_CFG(GPIO87, AF0)
+#define GPIO88_GPIO	MFP_CFG(GPIO88, AF0)
+#define GPIO89_GPIO	MFP_CFG(GPIO89, AF0)
+#define GPIO90_GPIO	MFP_CFG(GPIO90, AF0)
+#define GPIO91_GPIO	MFP_CFG(GPIO91, AF0)
+#define GPIO92_GPIO	MFP_CFG(GPIO92, AF0)
+#define GPIO93_GPIO	MFP_CFG(GPIO93, AF0)
+#define GPIO94_GPIO	MFP_CFG(GPIO94, AF0)
+#define GPIO95_GPIO	MFP_CFG(GPIO95, AF0)
+#define GPIO96_GPIO	MFP_CFG(GPIO96, AF0)
+#define GPIO97_GPIO	MFP_CFG(GPIO97, AF0)
+#define GPIO98_GPIO	MFP_CFG(GPIO98, AF0)
+#define GPIO99_GPIO	MFP_CFG(GPIO99, AF0)
+#define GPIO100_GPIO	MFP_CFG(GPIO100, AF0)
+#define GPIO101_GPIO	MFP_CFG(GPIO101, AF0)
+#define GPIO102_GPIO	MFP_CFG(GPIO102, AF1)
+#define GPIO103_GPIO	MFP_CFG(GPIO103, AF1)
+#define GPIO104_GPIO	MFP_CFG(GPIO104, AF1)
+#define GPIO105_GPIO	MFP_CFG(GPIO105, AF1)
+#define GPIO106_GPIO	MFP_CFG(GPIO106, AF1)
+#define GPIO107_GPIO	MFP_CFG(GPIO107, AF1)
+#define GPIO108_GPIO	MFP_CFG(GPIO108, AF1)
+#define GPIO109_GPIO	MFP_CFG(GPIO109, AF1)
+#define GPIO110_GPIO	MFP_CFG(GPIO110, AF1)
+#define GPIO111_GPIO	MFP_CFG(GPIO111, AF1)
+#define GPIO112_GPIO	MFP_CFG(GPIO112, AF1)
+#define GPIO113_GPIO	MFP_CFG(GPIO113, AF1)
+#define GPIO114_GPIO	MFP_CFG(GPIO114, AF0)
+#define GPIO115_GPIO	MFP_CFG(GPIO115, AF0)
+#define GPIO116_GPIO	MFP_CFG(GPIO116, AF0)
+#define GPIO117_GPIO	MFP_CFG(GPIO117, AF0)
+#define GPIO118_GPIO	MFP_CFG(GPIO118, AF0)
+#define GPIO119_GPIO	MFP_CFG(GPIO119, AF0)
+#define GPIO120_GPIO	MFP_CFG(GPIO120, AF0)
+#define GPIO121_GPIO	MFP_CFG(GPIO121, AF0)
+#define GPIO122_GPIO	MFP_CFG(GPIO122, AF0)
+#define GPIO123_GPIO	MFP_CFG(GPIO123, AF0)
+#define GPIO124_GPIO	MFP_CFG(GPIO124, AF0)
+#define GPIO125_GPIO	MFP_CFG(GPIO125, AF0)
+#define GPIO126_GPIO	MFP_CFG(GPIO126, AF0)
+#define GPIO127_GPIO	MFP_CFG(GPIO127, AF0)
+#define GPIO128_GPIO	MFP_CFG(GPIO128, AF0)
+#define GPIO129_GPIO	MFP_CFG(GPIO129, AF0)
+#define GPIO130_GPIO	MFP_CFG(GPIO130, AF0)
+#define GPIO131_GPIO	MFP_CFG(GPIO131, AF0)
+#define GPIO132_GPIO	MFP_CFG(GPIO132, AF0)
+#define GPIO133_GPIO	MFP_CFG(GPIO133, AF0)
+#define GPIO134_GPIO	MFP_CFG(GPIO134, AF0)
+#define GPIO135_GPIO	MFP_CFG(GPIO135, AF0)
+#define GPIO136_GPIO	MFP_CFG(GPIO136, AF0)
+#define GPIO137_GPIO	MFP_CFG(GPIO137, AF0)
+#define GPIO138_GPIO	MFP_CFG(GPIO138, AF0)
+#define GPIO139_GPIO	MFP_CFG(GPIO139, AF0)
+#define GPIO140_GPIO	MFP_CFG(GPIO140, AF0)
+#define GPIO141_GPIO	MFP_CFG(GPIO141, AF0)
+#define GPIO142_GPIO	MFP_CFG(GPIO142, AF1)
+#define GPIO143_GPIO	MFP_CFG(GPIO143, AF1)
+#define GPIO144_GPIO	MFP_CFG(GPIO144, AF1)
+#define GPIO145_GPIO	MFP_CFG(GPIO145, AF1)
+#define GPIO146_GPIO	MFP_CFG(GPIO146, AF1)
+#define GPIO147_GPIO	MFP_CFG(GPIO147, AF1)
+#define GPIO148_GPIO	MFP_CFG(GPIO148, AF1)
+#define GPIO149_GPIO	MFP_CFG(GPIO149, AF1)
+#define GPIO150_GPIO	MFP_CFG(GPIO150, AF1)
+#define GPIO151_GPIO	MFP_CFG(GPIO151, AF1)
+#define GPIO152_GPIO	MFP_CFG(GPIO152, AF1)
+#define GPIO153_GPIO	MFP_CFG(GPIO153, AF1)
+#define GPIO154_GPIO	MFP_CFG(GPIO154, AF1)
+#define GPIO155_GPIO	MFP_CFG(GPIO155, AF1)
+#define GPIO156_GPIO	MFP_CFG(GPIO156, AF1)
+#define GPIO157_GPIO	MFP_CFG(GPIO157, AF1)
+#define GPIO158_GPIO	MFP_CFG(GPIO158, AF1)
+#define GPIO159_GPIO	MFP_CFG(GPIO159, AF1)
+#define GPIO160_GPIO	MFP_CFG(GPIO160, AF1)
+#define GPIO161_GPIO	MFP_CFG(GPIO161, AF1)
+#define GPIO162_GPIO	MFP_CFG(GPIO162, AF1)
+#define GPIO163_GPIO	MFP_CFG(GPIO163, AF1)
+#define GPIO164_GPIO	MFP_CFG(GPIO164, AF1)
+#define GPIO165_GPIO	MFP_CFG(GPIO165, AF1)
+#define GPIO166_GPIO	MFP_CFG(GPIO166, AF1)
+#define GPIO167_GPIO	MFP_CFG(GPIO167, AF1)
+#define GPIO168_GPIO	MFP_CFG(GPIO168, AF1)
 
 /* DFI */
 #define GPIO108_DFI_D15		MFP_CFG(GPIO108, AF0)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mmp/include/mach/mfp-pxa910.h linux-libre-2.6.38-gnu1/arch/arm/mach-mmp/include/mach/mfp-pxa910.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mmp/include/mach/mfp-pxa910.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mmp/include/mach/mfp-pxa910.h	2011-03-14 21:20:32.000000000 -0400
@@ -6,7 +6,7 @@
 #define MFP_DRIVE_VERY_SLOW	(0x0 << 13)
 #define MFP_DRIVE_SLOW		(0x2 << 13)
 #define MFP_DRIVE_MEDIUM	(0x4 << 13)
-#define MFP_DRIVE_FAST		(0x8 << 13)
+#define MFP_DRIVE_FAST		(0x6 << 13)
 
 /* UART2 */
 #define GPIO47_UART2_RXD	MFP_CFG(GPIO47, AF6)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mmp/include/mach/mmp2.h linux-libre-2.6.38-gnu1/arch/arm/mach-mmp/include/mach/mmp2.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mmp/include/mach/mmp2.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mmp/include/mach/mmp2.h	2011-03-14 21:20:32.000000000 -0400
@@ -1,6 +1,8 @@
 #ifndef __ASM_MACH_MMP2_H
 #define __ASM_MACH_MMP2_H
 
+#include <plat/sdhci.h>
+
 struct sys_timer;
 
 extern struct sys_timer mmp2_timer;
@@ -22,6 +24,10 @@ extern struct pxa_device_desc mmp2_devic
 extern struct pxa_device_desc mmp2_device_twsi4;
 extern struct pxa_device_desc mmp2_device_twsi5;
 extern struct pxa_device_desc mmp2_device_twsi6;
+extern struct pxa_device_desc mmp2_device_sdh0;
+extern struct pxa_device_desc mmp2_device_sdh1;
+extern struct pxa_device_desc mmp2_device_sdh2;
+extern struct pxa_device_desc mmp2_device_sdh3;
 
 static inline int mmp2_add_uart(int id)
 {
@@ -62,6 +68,22 @@ static inline int mmp2_add_twsi(int id,
 
 	return pxa_register_device(d, data, sizeof(*data));
 }
+
+static inline int mmp2_add_sdhost(int id, struct sdhci_pxa_platdata *data)
+{
+	struct pxa_device_desc *d = NULL;
+
+	switch (id) {
+	case 0: d = &mmp2_device_sdh0; break;
+	case 1: d = &mmp2_device_sdh1; break;
+	case 2: d = &mmp2_device_sdh2; break;
+	case 3: d = &mmp2_device_sdh3; break;
+	default:
+		return -EINVAL;
+	}
+
+	return pxa_register_device(d, data, sizeof(*data));
+}
 
 #endif /* __ASM_MACH_MMP2_H */
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mmp/include/mach/regs-apmu.h linux-libre-2.6.38-gnu1/arch/arm/mach-mmp/include/mach/regs-apmu.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mmp/include/mach/regs-apmu.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mmp/include/mach/regs-apmu.h	2011-03-14 21:20:32.000000000 -0400
@@ -27,6 +27,8 @@
 #define APMU_DMA	APMU_REG(0x064)
 #define APMU_GEU	APMU_REG(0x068)
 #define APMU_BUS	APMU_REG(0x06c)
+#define APMU_SDH2	APMU_REG(0x0e8)
+#define APMU_SDH3	APMU_REG(0x0ec)
 
 #define APMU_FNCLK_EN	(1 << 4)
 #define APMU_AXICLK_EN	(1 << 3)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mmp/irq-mmp2.c linux-libre-2.6.38-gnu1/arch/arm/mach-mmp/irq-mmp2.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mmp/irq-mmp2.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mmp/irq-mmp2.c	2011-03-14 21:20:32.000000000 -0400
@@ -20,48 +20,48 @@
 
 #include "common.h"
 
-static void icu_mask_irq(unsigned int irq)
+static void icu_mask_irq(struct irq_data *d)
 {
-	uint32_t r = __raw_readl(ICU_INT_CONF(irq));
+	uint32_t r = __raw_readl(ICU_INT_CONF(d->irq));
 
 	r &= ~ICU_INT_ROUTE_PJ4_IRQ;
-	__raw_writel(r, ICU_INT_CONF(irq));
+	__raw_writel(r, ICU_INT_CONF(d->irq));
 }
 
-static void icu_unmask_irq(unsigned int irq)
+static void icu_unmask_irq(struct irq_data *d)
 {
-	uint32_t r = __raw_readl(ICU_INT_CONF(irq));
+	uint32_t r = __raw_readl(ICU_INT_CONF(d->irq));
 
 	r |= ICU_INT_ROUTE_PJ4_IRQ;
-	__raw_writel(r, ICU_INT_CONF(irq));
+	__raw_writel(r, ICU_INT_CONF(d->irq));
 }
 
 static struct irq_chip icu_irq_chip = {
 	.name		= "icu_irq",
-	.mask		= icu_mask_irq,
-	.mask_ack	= icu_mask_irq,
-	.unmask		= icu_unmask_irq,
+	.irq_mask	= icu_mask_irq,
+	.irq_mask_ack	= icu_mask_irq,
+	.irq_unmask	= icu_unmask_irq,
 };
 
-static void pmic_irq_ack(unsigned int irq)
+static void pmic_irq_ack(struct irq_data *d)
 {
-	if (irq == IRQ_MMP2_PMIC)
+	if (d->irq == IRQ_MMP2_PMIC)
 		mmp2_clear_pmic_int();
 }
 
 #define SECOND_IRQ_MASK(_name_, irq_base, prefix)			\
-static void _name_##_mask_irq(unsigned int irq)				\
+static void _name_##_mask_irq(struct irq_data *d)			\
 {									\
 	uint32_t r;							\
-	r = __raw_readl(prefix##_MASK) | (1 << (irq - irq_base));	\
+	r = __raw_readl(prefix##_MASK) | (1 << (d->irq - irq_base));	\
 	__raw_writel(r, prefix##_MASK);					\
 }
 
 #define SECOND_IRQ_UNMASK(_name_, irq_base, prefix)			\
-static void _name_##_unmask_irq(unsigned int irq)			\
+static void _name_##_unmask_irq(struct irq_data *d)			\
 {									\
 	uint32_t r;							\
-	r = __raw_readl(prefix##_MASK) & ~(1 << (irq - irq_base));	\
+	r = __raw_readl(prefix##_MASK) & ~(1 << (d->irq - irq_base));	\
 	__raw_writel(r, prefix##_MASK);					\
 }
 
@@ -88,8 +88,8 @@ SECOND_IRQ_UNMASK(_name_, irq_base, pref
 SECOND_IRQ_DEMUX(_name_, irq_base, prefix)				\
 static struct irq_chip _name_##_irq_chip = {				\
 	.name		= #_name_,					\
-	.mask		= _name_##_mask_irq,				\
-	.unmask		= _name_##_unmask_irq,				\
+	.irq_mask	= _name_##_mask_irq,				\
+	.irq_unmask	= _name_##_unmask_irq,				\
 }
 
 SECOND_IRQ_CHIP(pmic, IRQ_MMP2_PMIC_BASE, MMP2_ICU_INT4);
@@ -103,10 +103,12 @@ static void init_mux_irq(struct irq_chip
 	int irq;
 
 	for (irq = start; num > 0; irq++, num--) {
+		struct irq_data *d = irq_get_irq_data(irq);
+
 		/* mask and clear the IRQ */
-		chip->mask(irq);
-		if (chip->ack)
-			chip->ack(irq);
+		chip->irq_mask(d);
+		if (chip->irq_ack)
+			chip->irq_ack(d);
 
 		set_irq_chip(irq, chip);
 		set_irq_flags(irq, IRQF_VALID);
@@ -119,7 +121,7 @@ void __init mmp2_init_icu(void)
 	int irq;
 
 	for (irq = 0; irq < IRQ_MMP2_MUX_BASE; irq++) {
-		icu_mask_irq(irq);
+		icu_mask_irq(irq_get_irq_data(irq));
 		set_irq_chip(irq, &icu_irq_chip);
 		set_irq_flags(irq, IRQF_VALID);
 
@@ -139,7 +141,7 @@ void __init mmp2_init_icu(void)
 	/* NOTE: IRQ_MMP2_PMIC requires the PMIC MFPR register
 	 * to be written to clear the interrupt
 	 */
-	pmic_irq_chip.ack = pmic_irq_ack;
+	pmic_irq_chip.irq_ack = pmic_irq_ack;
 
 	init_mux_irq(&pmic_irq_chip, IRQ_MMP2_PMIC_BASE, 2);
 	init_mux_irq(&rtc_irq_chip, IRQ_MMP2_RTC_BASE, 2);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mmp/irq-pxa168.c linux-libre-2.6.38-gnu1/arch/arm/mach-mmp/irq-pxa168.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mmp/irq-pxa168.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mmp/irq-pxa168.c	2011-03-14 21:20:32.000000000 -0400
@@ -25,21 +25,21 @@
 #define PRIORITY_DEFAULT	0x1
 #define PRIORITY_NONE		0x0	/* means IRQ disabled */
 
-static void icu_mask_irq(unsigned int irq)
+static void icu_mask_irq(struct irq_data *d)
 {
-	__raw_writel(PRIORITY_NONE, ICU_INT_CONF(irq));
+	__raw_writel(PRIORITY_NONE, ICU_INT_CONF(d->irq));
 }
 
-static void icu_unmask_irq(unsigned int irq)
+static void icu_unmask_irq(struct irq_data *d)
 {
-	__raw_writel(IRQ_ROUTE_TO_AP | PRIORITY_DEFAULT, ICU_INT_CONF(irq));
+	__raw_writel(IRQ_ROUTE_TO_AP | PRIORITY_DEFAULT, ICU_INT_CONF(d->irq));
 }
 
 static struct irq_chip icu_irq_chip = {
-	.name	= "icu_irq",
-	.ack	= icu_mask_irq,
-	.mask	= icu_mask_irq,
-	.unmask	= icu_unmask_irq,
+	.name		= "icu_irq",
+	.irq_ack	= icu_mask_irq,
+	.irq_mask	= icu_mask_irq,
+	.irq_unmask	= icu_unmask_irq,
 };
 
 void __init icu_init_irq(void)
@@ -47,7 +47,7 @@ void __init icu_init_irq(void)
 	int irq;
 
 	for (irq = 0; irq < 64; irq++) {
-		icu_mask_irq(irq);
+		icu_mask_irq(irq_get_irq_data(irq));
 		set_irq_chip(irq, &icu_irq_chip);
 		set_irq_handler(irq, handle_level_irq);
 		set_irq_flags(irq, IRQF_VALID);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mmp/jasper.c linux-libre-2.6.38-gnu1/arch/arm/mach-mmp/jasper.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mmp/jasper.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mmp/jasper.c	2011-03-14 21:20:32.000000000 -0400
@@ -67,6 +67,36 @@ static unsigned long jasper_pin_config[]
 
 	/* PMIC */
 	PMIC_PMIC_INT | MFP_LPM_EDGE_FALL,
+
+	/* MMC1 */
+	GPIO131_MMC1_DAT3,
+	GPIO132_MMC1_DAT2,
+	GPIO133_MMC1_DAT1,
+	GPIO134_MMC1_DAT0,
+	GPIO136_MMC1_CMD,
+	GPIO139_MMC1_CLK,
+	GPIO140_MMC1_CD,
+	GPIO141_MMC1_WP,
+
+	/* MMC2 */
+	GPIO37_MMC2_DAT3,
+	GPIO38_MMC2_DAT2,
+	GPIO39_MMC2_DAT1,
+	GPIO40_MMC2_DAT0,
+	GPIO41_MMC2_CMD,
+	GPIO42_MMC2_CLK,
+
+	/* MMC3 */
+	GPIO165_MMC3_DAT7,
+	GPIO162_MMC3_DAT6,
+	GPIO166_MMC3_DAT5,
+	GPIO163_MMC3_DAT4,
+	GPIO167_MMC3_DAT3,
+	GPIO164_MMC3_DAT2,
+	GPIO168_MMC3_DAT1,
+	GPIO111_MMC3_DAT0,
+	GPIO112_MMC3_CMD,
+	GPIO151_MMC3_CLK,
 };
 
 static struct regulator_consumer_supply max8649_supply[] = {
@@ -123,6 +153,10 @@ static struct i2c_board_info jasper_twsi
 	},
 };
 
+static struct sdhci_pxa_platdata mmp2_sdh_platdata_mmc0 = {
+	.max_speed	= 25000000,
+};
+
 static void __init jasper_init(void)
 {
 	mfp_config(ARRAY_AND_SIZE(jasper_pin_config));
@@ -131,6 +165,7 @@ static void __init jasper_init(void)
 	mmp2_add_uart(1);
 	mmp2_add_uart(3);
 	mmp2_add_twsi(1, NULL, ARRAY_AND_SIZE(jasper_twsi1_info));
+	mmp2_add_sdhost(0, &mmp2_sdh_platdata_mmc0); /* SD/MMC */
 
 	regulator_has_full_constraints();
 }
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mmp/Kconfig linux-libre-2.6.38-gnu1/arch/arm/mach-mmp/Kconfig
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mmp/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mmp/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -37,25 +37,38 @@ config MACH_TTC_DKB
 	  Say 'Y' here if you want to support the Marvell PXA910-based
 	  TTC_DKB Development Board.
 
+config MACH_BROWNSTONE
+	bool "Marvell's Brownstone Development Platform"
+	depends on !CPU_MOHAWK
+	select CPU_MMP2
+	help
+	  Say 'Y' here if you want to support the Marvell MMP2-based
+	  Brown Development Platform.
+	  MMP2-based board can't be co-existed with PXA168-based &
+	  PXA910-based development board. Since MMP2 is compatible to
+	  ARMv7 architecture.
+
 config MACH_FLINT
 	bool "Marvell's Flint Development Platform"
+	depends on !CPU_MOHAWK
 	select CPU_MMP2
 	help
 	  Say 'Y' here if you want to support the Marvell MMP2-based
 	  Flint Development Platform.
 	  MMP2-based board can't be co-existed with PXA168-based &
 	  PXA910-based development board. Since MMP2 is compatible to
-	  ARMv6 architecture.
+	  ARMv7 architecture.
 
 config MACH_MARVELL_JASPER
 	bool "Marvell's Jasper Development Platform"
+	depends on !CPU_MOHAWK
 	select CPU_MMP2
 	help
 	  Say 'Y' here if you want to support the Marvell MMP2-base
 	  Jasper Development Platform.
 	  MMP2-based board can't be co-existed with PXA168-based &
 	  PXA910-based development board. Since MMP2 is compatible to
-	  ARMv6 architecture.
+	  ARMv7 architecture.
 
 config MACH_TETON_BGA
 	bool "Marvell's PXA168 Teton BGA Development Board"
@@ -80,8 +93,7 @@ config CPU_PXA910
 
 config CPU_MMP2
 	bool
-	select CPU_V6
-	select CPU_32v6K
+	select CPU_PJ4
 	help
-	  Select code specific to MMP2. MMP2 is ARMv6 compatible.
+	  Select code specific to MMP2. MMP2 is ARMv7 compatible.
 endif
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mmp/Makefile linux-libre-2.6.38-gnu1/arch/arm/mach-mmp/Makefile
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mmp/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mmp/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -15,6 +15,7 @@ obj-$(CONFIG_MACH_ZYLONITE2)	+= aspenite
 obj-$(CONFIG_MACH_AVENGERS_LITE)+= avengers_lite.o
 obj-$(CONFIG_MACH_TAVOREVB)	+= tavorevb.o
 obj-$(CONFIG_MACH_TTC_DKB)	+= ttc_dkb.o
+obj-$(CONFIG_MACH_BROWNSTONE)	+= brownstone.o
 obj-$(CONFIG_MACH_FLINT)	+= flint.o
 obj-$(CONFIG_MACH_MARVELL_JASPER) += jasper.o
 obj-$(CONFIG_MACH_TETON_BGA)	+= teton_bga.o
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mmp/mmp2.c linux-libre-2.6.38-gnu1/arch/arm/mach-mmp/mmp2.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mmp/mmp2.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mmp/mmp2.c	2011-03-14 21:20:32.000000000 -0400
@@ -115,6 +115,29 @@ void __init mmp2_init_irq(void)
 	mmp2_init_gpio();
 }
 
+static void sdhc_clk_enable(struct clk *clk)
+{
+	uint32_t clk_rst;
+
+	clk_rst  =  __raw_readl(clk->clk_rst);
+	clk_rst |= clk->enable_val;
+	__raw_writel(clk_rst, clk->clk_rst);
+}
+
+static void sdhc_clk_disable(struct clk *clk)
+{
+	uint32_t clk_rst;
+
+	clk_rst  =  __raw_readl(clk->clk_rst);
+	clk_rst &= ~clk->enable_val;
+	__raw_writel(clk_rst, clk->clk_rst);
+}
+
+struct clkops sdhc_clk_ops = {
+	.enable		= sdhc_clk_enable,
+	.disable	= sdhc_clk_disable,
+};
+
 /* APB peripheral clocks */
 static APBC_CLK(uart1, MMP2_UART1, 1, 26000000);
 static APBC_CLK(uart2, MMP2_UART2, 1, 26000000);
@@ -128,6 +151,10 @@ static APBC_CLK(twsi5, MMP2_TWSI5, 0, 26
 static APBC_CLK(twsi6, MMP2_TWSI6, 0, 26000000);
 
 static APMU_CLK(nand, NAND, 0xbf, 100000000);
+static APMU_CLK_OPS(sdh0, SDH0, 0x1b, 200000000, &sdhc_clk_ops);
+static APMU_CLK_OPS(sdh1, SDH1, 0x1b, 200000000, &sdhc_clk_ops);
+static APMU_CLK_OPS(sdh2, SDH2, 0x1b, 200000000, &sdhc_clk_ops);
+static APMU_CLK_OPS(sdh3, SDH3, 0x1b, 200000000, &sdhc_clk_ops);
 
 static struct clk_lookup mmp2_clkregs[] = {
 	INIT_CLKREG(&clk_uart1, "pxa2xx-uart.0", NULL),
@@ -141,6 +168,10 @@ static struct clk_lookup mmp2_clkregs[]
 	INIT_CLKREG(&clk_twsi5, "pxa2xx-i2c.4", NULL),
 	INIT_CLKREG(&clk_twsi6, "pxa2xx-i2c.5", NULL),
 	INIT_CLKREG(&clk_nand, "pxa3xx-nand", NULL),
+	INIT_CLKREG(&clk_sdh0, "sdhci-pxa.0", "PXA-SDHCLK"),
+	INIT_CLKREG(&clk_sdh1, "sdhci-pxa.1", "PXA-SDHCLK"),
+	INIT_CLKREG(&clk_sdh2, "sdhci-pxa.2", "PXA-SDHCLK"),
+	INIT_CLKREG(&clk_sdh3, "sdhci-pxa.3", "PXA-SDHCLK"),
 };
 
 static int __init mmp2_init(void)
@@ -191,4 +222,8 @@ MMP2_DEVICE(twsi4, "pxa2xx-i2c", 3, TWSI
 MMP2_DEVICE(twsi5, "pxa2xx-i2c", 4, TWSI5, 0xd4033800, 0x70);
 MMP2_DEVICE(twsi6, "pxa2xx-i2c", 5, TWSI6, 0xd4034000, 0x70);
 MMP2_DEVICE(nand, "pxa3xx-nand", -1, NAND, 0xd4283000, 0x100, 28, 29);
+MMP2_DEVICE(sdh0, "sdhci-pxa", 0, MMC, 0xd4280000, 0x120);
+MMP2_DEVICE(sdh1, "sdhci-pxa", 1, MMC2, 0xd4280800, 0x120);
+MMP2_DEVICE(sdh2, "sdhci-pxa", 2, MMC3, 0xd4281000, 0x120);
+MMP2_DEVICE(sdh3, "sdhci-pxa", 3, MMC4, 0xd4281800, 0x120);
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mmp/pxa910.c linux-libre-2.6.38-gnu1/arch/arm/mach-mmp/pxa910.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mmp/pxa910.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mmp/pxa910.c	2011-03-14 21:20:32.000000000 -0400
@@ -111,6 +111,7 @@ static APBC_CLK(pwm3, PXA910_PWM3, 1, 13
 static APBC_CLK(pwm4, PXA910_PWM4, 1, 13000000);
 
 static APMU_CLK(nand, NAND, 0x01db, 208000000);
+static APMU_CLK(u2o, USB, 0x1b, 480000000);
 
 /* device and clock bindings */
 static struct clk_lookup pxa910_clkregs[] = {
@@ -123,6 +124,7 @@ static struct clk_lookup pxa910_clkregs[
 	INIT_CLKREG(&clk_pwm3, "pxa910-pwm.2", NULL),
 	INIT_CLKREG(&clk_pwm4, "pxa910-pwm.3", NULL),
 	INIT_CLKREG(&clk_nand, "pxa3xx-nand", NULL),
+	INIT_CLKREG(&clk_u2o, "pxa-u2o", "U2OCLK"),
 };
 
 static int __init pxa910_init(void)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mmp/time.c linux-libre-2.6.38-gnu1/arch/arm/mach-mmp/time.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mmp/time.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mmp/time.c	2011-03-14 21:20:32.000000000 -0400
@@ -26,8 +26,8 @@
 #include <linux/io.h>
 #include <linux/irq.h>
 #include <linux/sched.h>
-#include <linux/cnt32_to_63.h>
 
+#include <asm/sched_clock.h>
 #include <mach/addr-map.h>
 #include <mach/regs-timers.h>
 #include <mach/regs-apbc.h>
@@ -42,23 +42,7 @@
 #define MAX_DELTA		(0xfffffffe)
 #define MIN_DELTA		(16)
 
-#define TCR2NS_SCALE_FACTOR	10
-
-static unsigned long tcr2ns_scale;
-
-static void __init set_tcr2ns_scale(unsigned long tcr_rate)
-{
-	unsigned long long v = 1000000000ULL << TCR2NS_SCALE_FACTOR;
-	do_div(v, tcr_rate);
-	tcr2ns_scale = v;
-	/*
-	 * We want an even value to automatically clear the top bit
-	 * returned by cnt32_to_63() without an additional run time
-	 * instruction. So if the LSB is 1 then round it up.
-	 */
-	if (tcr2ns_scale & 1)
-		tcr2ns_scale++;
-}
+static DEFINE_CLOCK_DATA(cd);
 
 /*
  * FIXME: the timer needs some delay to stablize the counter capture
@@ -75,10 +59,16 @@ static inline uint32_t timer_read(void)
 	return __raw_readl(TIMERS_VIRT_BASE + TMR_CVWR(0));
 }
 
-unsigned long long sched_clock(void)
+unsigned long long notrace sched_clock(void)
 {
-	unsigned long long v = cnt32_to_63(timer_read());
-	return (v * tcr2ns_scale) >> TCR2NS_SCALE_FACTOR;
+	u32 cyc = timer_read();
+	return cyc_to_sched_clock(&cd, cyc, (u32)~0);
+}
+
+static void notrace mmp_update_sched_clock(void)
+{
+	u32 cyc = timer_read();
+	update_sched_clock(&cd, cyc, (u32)~0);
 }
 
 static irqreturn_t timer_interrupt(int irq, void *dev_id)
@@ -146,7 +136,6 @@ static cycle_t clksrc_read(struct clocks
 
 static struct clocksource cksrc = {
 	.name		= "clocksource",
-	.shift		= 20,
 	.rating		= 200,
 	.read		= clksrc_read,
 	.mask		= CLOCKSOURCE_MASK(32),
@@ -186,17 +175,15 @@ void __init timer_init(int irq)
 {
 	timer_config();
 
-	set_tcr2ns_scale(CLOCK_TICK_RATE);
+	init_sched_clock(&cd, mmp_update_sched_clock, 32, CLOCK_TICK_RATE);
 
 	ckevt.mult = div_sc(CLOCK_TICK_RATE, NSEC_PER_SEC, ckevt.shift);
 	ckevt.max_delta_ns = clockevent_delta2ns(MAX_DELTA, &ckevt);
 	ckevt.min_delta_ns = clockevent_delta2ns(MIN_DELTA, &ckevt);
 	ckevt.cpumask = cpumask_of(0);
 
-	cksrc.mult = clocksource_hz2mult(CLOCK_TICK_RATE, cksrc.shift);
-
 	setup_irq(irq, &timer_irq);
 
-	clocksource_register(&cksrc);
+	clocksource_register_hz(&cksrc, CLOCK_TICK_RATE);
 	clockevents_register_device(&ckevt);
 }
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-msm/board-msm7x30.c linux-libre-2.6.38-gnu1/arch/arm/mach-msm/board-msm7x30.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-msm/board-msm7x30.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-msm/board-msm7x30.c	2011-03-14 21:20:32.000000000 -0400
@@ -22,6 +22,7 @@
 #include <linux/delay.h>
 #include <linux/io.h>
 #include <linux/smsc911x.h>
+#include <linux/usb/msm_hsusb.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -39,11 +40,26 @@
 
 extern struct sys_timer msm_timer;
 
+static int hsusb_phy_init_seq[] = {
+	0x30, 0x32,	/* Enable and set Pre-Emphasis Depth to 20% */
+	0x02, 0x36,	/* Disable CDR Auto Reset feature */
+	-1
+};
+
+static struct msm_otg_platform_data msm_otg_pdata = {
+	.phy_init_seq		= hsusb_phy_init_seq,
+	.mode                   = USB_PERIPHERAL,
+	.otg_control		= OTG_PHY_CONTROL,
+};
+
 static struct platform_device *devices[] __initdata = {
 #if defined(CONFIG_SERIAL_MSM) || defined(CONFIG_MSM_SERIAL_DEBUGGER)
         &msm_device_uart2,
 #endif
 	&msm_device_smd,
+	&msm_device_otg,
+	&msm_device_hsusb,
+	&msm_device_hsusb_host,
 };
 
 static void __init msm7x30_init_irq(void)
@@ -53,6 +69,10 @@ static void __init msm7x30_init_irq(void
 
 static void __init msm7x30_init(void)
 {
+	msm_device_otg.dev.platform_data = &msm_otg_pdata;
+	msm_device_hsusb.dev.parent = &msm_device_otg.dev;
+	msm_device_hsusb_host.dev.parent = &msm_device_otg.dev;
+
 	platform_add_devices(devices, ARRAY_SIZE(devices));
 }
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-msm/board-msm8x60.c linux-libre-2.6.38-gnu1/arch/arm/mach-msm/board-msm8x60.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-msm/board-msm8x60.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-msm/board-msm8x60.c	2011-03-14 21:20:32.000000000 -0400
@@ -28,8 +28,6 @@
 #include <mach/board.h>
 #include <mach/msm_iomap.h>
 
-void __iomem *gic_cpu_base_addr;
-
 unsigned long clk_get_max_axi_khz(void)
 {
 	return 0;
@@ -44,9 +42,8 @@ static void __init msm8x60_init_irq(void
 {
 	unsigned int i;
 
-	gic_dist_init(0, MSM_QGIC_DIST_BASE, GIC_PPI_START);
-	gic_cpu_base_addr = (void *)MSM_QGIC_CPU_BASE;
-	gic_cpu_init(0, MSM_QGIC_CPU_BASE);
+	gic_init(0, GIC_PPI_START, MSM_QGIC_DIST_BASE,
+		 (void *)MSM_QGIC_CPU_BASE);
 
 	/* Edge trigger PPIs except AVS_SVICINT and AVS_SVICINTSWDONE */
 	writel(0xFFFFD7FF, MSM_QGIC_DIST_BASE + GIC_DIST_CONFIG + 4);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-msm/board-qsd8x50.c linux-libre-2.6.38-gnu1/arch/arm/mach-msm/board-qsd8x50.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-msm/board-qsd8x50.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-msm/board-qsd8x50.c	2011-03-14 21:20:32.000000000 -0400
@@ -20,6 +20,7 @@
 #include <linux/gpio.h>
 #include <linux/platform_device.h>
 #include <linux/delay.h>
+#include <linux/usb/msm_hsusb.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -42,7 +43,7 @@ static const unsigned        qsd8x50_sur
  * at run-time: they vary from board to board, and the true
  * configuration won't be known until boot.
  */
-static struct resource smc91x_resources[] __initdata = {
+static struct resource smc91x_resources[] = {
 	[0] = {
 		.flags = IORESOURCE_MEM,
 	},
@@ -51,7 +52,7 @@ static struct resource smc91x_resources[
 	},
 };
 
-static struct platform_device smc91x_device __initdata = {
+static struct platform_device smc91x_device = {
 	.name           = "smc91x",
 	.id             = 0,
 	.num_resources  = ARRAY_SIZE(smc91x_resources),
@@ -74,9 +75,24 @@ static int __init msm_init_smc91x(void)
 }
 module_init(msm_init_smc91x);
 
+static int hsusb_phy_init_seq[] = {
+	0x08, 0x31,	/* Increase HS Driver Amplitude */
+	0x20, 0x32,	/* Enable and set Pre-Emphasis Depth to 10% */
+	-1
+};
+
+static struct msm_otg_platform_data msm_otg_pdata = {
+	.phy_init_seq		= hsusb_phy_init_seq,
+	.mode                   = USB_PERIPHERAL,
+	.otg_control		= OTG_PHY_CONTROL,
+};
+
 static struct platform_device *devices[] __initdata = {
 	&msm_device_uart3,
 	&msm_device_smd,
+	&msm_device_otg,
+	&msm_device_hsusb,
+	&msm_device_hsusb_host,
 };
 
 static void __init qsd8x50_map_io(void)
@@ -93,6 +109,9 @@ static void __init qsd8x50_init_irq(void
 
 static void __init qsd8x50_init(void)
 {
+	msm_device_otg.dev.platform_data = &msm_otg_pdata;
+	msm_device_hsusb.dev.parent = &msm_device_otg.dev;
+	msm_device_hsusb_host.dev.parent = &msm_device_otg.dev;
 	platform_add_devices(devices, ARRAY_SIZE(devices));
 }
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-msm/board-trout-gpio.c linux-libre-2.6.38-gnu1/arch/arm/mach-msm/board-trout-gpio.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-msm/board-trout-gpio.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-msm/board-trout-gpio.c	2011-03-14 21:20:32.000000000 -0400
@@ -72,6 +72,13 @@ static int msm_gpiolib_direction_output(
 	return 0;
 }
 
+static int trout_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+	struct msm_gpio_chip *msm_gpio = to_msm_gpio_chip(chip);
+
+	return TROUT_GPIO_TO_INT(offset + chip->base);
+}
+
 #define TROUT_GPIO_BANK(name, reg_num, base_gpio, shadow_val)		\
 	{								\
 		.chip = {						\
@@ -80,6 +87,7 @@ static int msm_gpiolib_direction_output(
 			.direction_output = msm_gpiolib_direction_output, \
 			.get		  = msm_gpiolib_get,		\
 			.set		  = msm_gpiolib_set,		\
+			.to_irq		  = trout_gpio_to_irq,		\
 			.base		  = base_gpio,			\
 			.ngpio		  = 8,				\
 		},							\
@@ -105,52 +113,52 @@ static struct msm_gpio_chip msm_gpio_ban
 	TROUT_GPIO_BANK("VIRTUAL", 0x12, TROUT_GPIO_VIRTUAL_BASE, 0),
 };
 
-static void trout_gpio_irq_ack(unsigned int irq)
+static void trout_gpio_irq_ack(struct irq_data *d)
 {
-	int bank = TROUT_INT_TO_BANK(irq);
-	uint8_t mask = TROUT_INT_TO_MASK(irq);
+	int bank = TROUT_INT_TO_BANK(d->irq);
+	uint8_t mask = TROUT_INT_TO_MASK(d->irq);
 	int reg = TROUT_BANK_TO_STAT_REG(bank);
-	/*printk(KERN_INFO "trout_gpio_irq_ack irq %d\n", irq);*/
+	/*printk(KERN_INFO "trout_gpio_irq_ack irq %d\n", d->irq);*/
 	writeb(mask, TROUT_CPLD_BASE + reg);
 }
 
-static void trout_gpio_irq_mask(unsigned int irq)
+static void trout_gpio_irq_mask(struct irq_data *d)
 {
 	unsigned long flags;
 	uint8_t reg_val;
-	int bank = TROUT_INT_TO_BANK(irq);
-	uint8_t mask = TROUT_INT_TO_MASK(irq);
+	int bank = TROUT_INT_TO_BANK(d->irq);
+	uint8_t mask = TROUT_INT_TO_MASK(d->irq);
 	int reg = TROUT_BANK_TO_MASK_REG(bank);
 
 	local_irq_save(flags);
 	reg_val = trout_int_mask[bank] |= mask;
 	/*printk(KERN_INFO "trout_gpio_irq_mask irq %d => %d:%02x\n",
-	       irq, bank, reg_val);*/
+	       d->irq, bank, reg_val);*/
 	writeb(reg_val, TROUT_CPLD_BASE + reg);
 	local_irq_restore(flags);
 }
 
-static void trout_gpio_irq_unmask(unsigned int irq)
+static void trout_gpio_irq_unmask(struct irq_data *d)
 {
 	unsigned long flags;
 	uint8_t reg_val;
-	int bank = TROUT_INT_TO_BANK(irq);
-	uint8_t mask = TROUT_INT_TO_MASK(irq);
+	int bank = TROUT_INT_TO_BANK(d->irq);
+	uint8_t mask = TROUT_INT_TO_MASK(d->irq);
 	int reg = TROUT_BANK_TO_MASK_REG(bank);
 
 	local_irq_save(flags);
 	reg_val = trout_int_mask[bank] &= ~mask;
 	/*printk(KERN_INFO "trout_gpio_irq_unmask irq %d => %d:%02x\n",
-	       irq, bank, reg_val);*/
+	       d->irq, bank, reg_val);*/
 	writeb(reg_val, TROUT_CPLD_BASE + reg);
 	local_irq_restore(flags);
 }
 
-int trout_gpio_irq_set_wake(unsigned int irq, unsigned int on)
+int trout_gpio_irq_set_wake(struct irq_data *d, unsigned int on)
 {
 	unsigned long flags;
-	int bank = TROUT_INT_TO_BANK(irq);
-	uint8_t mask = TROUT_INT_TO_MASK(irq);
+	int bank = TROUT_INT_TO_BANK(d->irq);
+	uint8_t mask = TROUT_INT_TO_MASK(d->irq);
 
 	local_irq_save(flags);
 	if(on)
@@ -190,15 +198,15 @@ static void trout_gpio_irq_handler(unsig
 		}
 		int_base += TROUT_INT_BANK0_COUNT;
 	}
-	desc->chip->ack(irq);
+	desc->irq_data.chip->irq_ack(&desc->irq_data);
 }
 
 static struct irq_chip trout_gpio_irq_chip = {
-	.name      = "troutgpio",
-	.ack       = trout_gpio_irq_ack,
-	.mask      = trout_gpio_irq_mask,
-	.unmask    = trout_gpio_irq_unmask,
-	.set_wake  = trout_gpio_irq_set_wake,
+	.name          = "troutgpio",
+	.irq_ack       = trout_gpio_irq_ack,
+	.irq_mask      = trout_gpio_irq_mask,
+	.irq_unmask    = trout_gpio_irq_unmask,
+	.irq_set_wake  = trout_gpio_irq_set_wake,
 };
 
 /*
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-msm/board-trout-panel.c linux-libre-2.6.38-gnu1/arch/arm/mach-msm/board-trout-panel.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-msm/board-trout-panel.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-msm/board-trout-panel.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,297 @@
+/* linux/arch/arm/mach-msm/board-trout-mddi.c
+** Author: Brian Swetland <swetland@google.com>
+*/
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/leds.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+
+#include <asm/io.h>
+#include <asm/gpio.h>
+#include <asm/mach-types.h>
+
+#include <mach/msm_fb.h>
+#include <mach/vreg.h>
+
+#include "board-trout.h"
+#include "proc_comm.h"
+#include "devices.h"
+
+#define TROUT_DEFAULT_BACKLIGHT_BRIGHTNESS 255
+
+#define MDDI_CLIENT_CORE_BASE  0x108000
+#define LCD_CONTROL_BLOCK_BASE 0x110000
+#define SPI_BLOCK_BASE         0x120000
+#define I2C_BLOCK_BASE         0x130000
+#define PWM_BLOCK_BASE         0x140000
+#define GPIO_BLOCK_BASE        0x150000
+#define SYSTEM_BLOCK1_BASE     0x160000
+#define SYSTEM_BLOCK2_BASE     0x170000
+
+
+#define	DPSUS       (MDDI_CLIENT_CORE_BASE|0x24)
+#define	SYSCLKENA   (MDDI_CLIENT_CORE_BASE|0x2C)
+#define	PWM0OFF	      (PWM_BLOCK_BASE|0x1C)
+
+#define V_VDDE2E_VDD2_GPIO 0
+#define MDDI_RST_N 82
+
+#define	MDDICAP0    (MDDI_CLIENT_CORE_BASE|0x00)
+#define	MDDICAP1    (MDDI_CLIENT_CORE_BASE|0x04)
+#define	MDDICAP2    (MDDI_CLIENT_CORE_BASE|0x08)
+#define	MDDICAP3    (MDDI_CLIENT_CORE_BASE|0x0C)
+#define	MDCAPCHG    (MDDI_CLIENT_CORE_BASE|0x10)
+#define	MDCRCERC    (MDDI_CLIENT_CORE_BASE|0x14)
+#define	TTBUSSEL    (MDDI_CLIENT_CORE_BASE|0x18)
+#define	DPSET0      (MDDI_CLIENT_CORE_BASE|0x1C)
+#define	DPSET1      (MDDI_CLIENT_CORE_BASE|0x20)
+#define	DPSUS       (MDDI_CLIENT_CORE_BASE|0x24)
+#define	DPRUN       (MDDI_CLIENT_CORE_BASE|0x28)
+#define	SYSCKENA    (MDDI_CLIENT_CORE_BASE|0x2C)
+#define	TESTMODE    (MDDI_CLIENT_CORE_BASE|0x30)
+#define	FIFOMONI    (MDDI_CLIENT_CORE_BASE|0x34)
+#define	INTMONI     (MDDI_CLIENT_CORE_BASE|0x38)
+#define	MDIOBIST    (MDDI_CLIENT_CORE_BASE|0x3C)
+#define	MDIOPSET    (MDDI_CLIENT_CORE_BASE|0x40)
+#define	BITMAP0     (MDDI_CLIENT_CORE_BASE|0x44)
+#define	BITMAP1     (MDDI_CLIENT_CORE_BASE|0x48)
+#define	BITMAP2     (MDDI_CLIENT_CORE_BASE|0x4C)
+#define	BITMAP3     (MDDI_CLIENT_CORE_BASE|0x50)
+#define	BITMAP4     (MDDI_CLIENT_CORE_BASE|0x54)
+
+#define	SRST        (LCD_CONTROL_BLOCK_BASE|0x00)
+#define	PORT_ENB    (LCD_CONTROL_BLOCK_BASE|0x04)
+#define	START       (LCD_CONTROL_BLOCK_BASE|0x08)
+#define	PORT        (LCD_CONTROL_BLOCK_BASE|0x0C)
+#define	CMN         (LCD_CONTROL_BLOCK_BASE|0x10)
+#define	GAMMA       (LCD_CONTROL_BLOCK_BASE|0x14)
+#define	INTFLG      (LCD_CONTROL_BLOCK_BASE|0x18)
+#define	INTMSK      (LCD_CONTROL_BLOCK_BASE|0x1C)
+#define	MPLFBUF     (LCD_CONTROL_BLOCK_BASE|0x20)
+#define	HDE_LEFT    (LCD_CONTROL_BLOCK_BASE|0x24)
+#define	VDE_TOP     (LCD_CONTROL_BLOCK_BASE|0x28)
+#define	PXL         (LCD_CONTROL_BLOCK_BASE|0x30)
+#define	HCYCLE      (LCD_CONTROL_BLOCK_BASE|0x34)
+#define	HSW         (LCD_CONTROL_BLOCK_BASE|0x38)
+#define	HDE_START   (LCD_CONTROL_BLOCK_BASE|0x3C)
+#define	HDE_SIZE    (LCD_CONTROL_BLOCK_BASE|0x40)
+#define	VCYCLE      (LCD_CONTROL_BLOCK_BASE|0x44)
+#define	VSW         (LCD_CONTROL_BLOCK_BASE|0x48)
+#define	VDE_START   (LCD_CONTROL_BLOCK_BASE|0x4C)
+#define	VDE_SIZE    (LCD_CONTROL_BLOCK_BASE|0x50)
+#define	WAKEUP      (LCD_CONTROL_BLOCK_BASE|0x54)
+#define	WSYN_DLY    (LCD_CONTROL_BLOCK_BASE|0x58)
+#define	REGENB      (LCD_CONTROL_BLOCK_BASE|0x5C)
+#define	VSYNIF      (LCD_CONTROL_BLOCK_BASE|0x60)
+#define	WRSTB       (LCD_CONTROL_BLOCK_BASE|0x64)
+#define	RDSTB       (LCD_CONTROL_BLOCK_BASE|0x68)
+#define	ASY_DATA    (LCD_CONTROL_BLOCK_BASE|0x6C)
+#define	ASY_DATB    (LCD_CONTROL_BLOCK_BASE|0x70)
+#define	ASY_DATC    (LCD_CONTROL_BLOCK_BASE|0x74)
+#define	ASY_DATD    (LCD_CONTROL_BLOCK_BASE|0x78)
+#define	ASY_DATE    (LCD_CONTROL_BLOCK_BASE|0x7C)
+#define	ASY_DATF    (LCD_CONTROL_BLOCK_BASE|0x80)
+#define	ASY_DATG    (LCD_CONTROL_BLOCK_BASE|0x84)
+#define	ASY_DATH    (LCD_CONTROL_BLOCK_BASE|0x88)
+#define	ASY_CMDSET  (LCD_CONTROL_BLOCK_BASE|0x8C)
+
+#define	SSICTL      (SPI_BLOCK_BASE|0x00)
+#define	SSITIME     (SPI_BLOCK_BASE|0x04)
+#define	SSITX       (SPI_BLOCK_BASE|0x08)
+#define	SSIRX       (SPI_BLOCK_BASE|0x0C)
+#define	SSIINTC     (SPI_BLOCK_BASE|0x10)
+#define	SSIINTS     (SPI_BLOCK_BASE|0x14)
+#define	SSIDBG1     (SPI_BLOCK_BASE|0x18)
+#define	SSIDBG2     (SPI_BLOCK_BASE|0x1C)
+#define	SSIID       (SPI_BLOCK_BASE|0x20)
+
+#define	WKREQ       (SYSTEM_BLOCK1_BASE|0x00)
+#define	CLKENB      (SYSTEM_BLOCK1_BASE|0x04)
+#define	DRAMPWR     (SYSTEM_BLOCK1_BASE|0x08)
+#define	INTMASK     (SYSTEM_BLOCK1_BASE|0x0C)
+#define	GPIOSEL     (SYSTEM_BLOCK2_BASE|0x00)
+
+#define	GPIODATA    (GPIO_BLOCK_BASE|0x00)
+#define	GPIODIR     (GPIO_BLOCK_BASE|0x04)
+#define	GPIOIS      (GPIO_BLOCK_BASE|0x08)
+#define	GPIOIBE     (GPIO_BLOCK_BASE|0x0C)
+#define	GPIOIEV     (GPIO_BLOCK_BASE|0x10)
+#define	GPIOIE      (GPIO_BLOCK_BASE|0x14)
+#define	GPIORIS     (GPIO_BLOCK_BASE|0x18)
+#define	GPIOMIS     (GPIO_BLOCK_BASE|0x1C)
+#define	GPIOIC      (GPIO_BLOCK_BASE|0x20)
+#define	GPIOOMS     (GPIO_BLOCK_BASE|0x24)
+#define	GPIOPC      (GPIO_BLOCK_BASE|0x28)
+#define	GPIOID      (GPIO_BLOCK_BASE|0x30)
+
+#define SPI_WRITE(reg, val) \
+	{ SSITX,        0x00010000 | (((reg) & 0xff) << 8) | ((val) & 0xff) }, \
+	{ 0, 5 },
+
+#define SPI_WRITE1(reg) \
+	{ SSITX,        (reg) & 0xff }, \
+	{ 0, 5 },
+
+struct mddi_table {
+	uint32_t reg;
+	uint32_t value;
+};
+static struct mddi_table mddi_toshiba_init_table[] = {
+	{ DPSET0,       0x09e90046 },
+	{ DPSET1,       0x00000118 },
+	{ DPSUS,        0x00000000 },
+	{ DPRUN,        0x00000001 },
+	{ 1,            14         }, /* msleep 14 */
+	{ SYSCKENA,     0x00000001 },
+	{ CLKENB,       0x0000A1EF },  /*    # SYS.CLKENB  # Enable clocks for each module (without DCLK , i2cCLK) */
+
+	{ GPIODATA,     0x02000200 },  /*   # GPI .GPIODATA  # GPIO2(RESET_LCD_N) set to 0 , GPIO3(eDRAM_Power) set to 0 */
+	{ GPIODIR,      0x000030D  },  /* 24D   # GPI .GPIODIR  # Select direction of GPIO port (0,2,3,6,9 output) */
+	{ GPIOSEL,      0/*0x00000173*/},  /*   # SYS.GPIOSEL  # GPIO port multiplexing control */
+	{ GPIOPC,       0x03C300C0 },  /*   # GPI .GPIOPC  # GPIO2,3 PD cut */
+	{ WKREQ,        0x00000000 },  /*   # SYS.WKREQ  # Wake-up request event is VSYNC alignment */
+
+	{ GPIOIBE,      0x000003FF },
+	{ GPIOIS,       0x00000000 },
+	{ GPIOIC,       0x000003FF },
+	{ GPIOIE,       0x00000000 },
+
+	{ GPIODATA,     0x00040004 },  /*   # GPI .GPIODATA  # eDRAM VD supply */
+	{ 1,            1          }, /* msleep 1 */
+	{ GPIODATA,     0x02040004 },  /*   # GPI .GPIODATA  # eDRAM VD supply */
+	{ DRAMPWR,      0x00000001 }, /* eDRAM power */
+};
+
+#define GPIOSEL_VWAKEINT (1U << 0)
+#define INTMASK_VWAKEOUT (1U << 0)
+
+
+static struct clk *gp_clk;
+static int trout_new_backlight = 1;
+static struct vreg *vreg_mddi_1v5;
+static struct vreg *vreg_lcm_2v85;
+
+static void trout_process_mddi_table(struct msm_mddi_client_data *client_data,
+				     struct mddi_table *table, size_t count)
+{
+	int i;
+	for (i = 0; i < count; i++) {
+		uint32_t reg = table[i].reg;
+		uint32_t value = table[i].value;
+
+		if (reg == 0)
+			udelay(value);
+		else if (reg == 1)
+			msleep(value);
+		else
+			client_data->remote_write(client_data, value, reg);
+	}
+}
+
+static int trout_mddi_toshiba_client_init(
+	struct msm_mddi_bridge_platform_data *bridge_data,
+	struct msm_mddi_client_data *client_data)
+{
+	int panel_id;
+
+	client_data->auto_hibernate(client_data, 0);
+	trout_process_mddi_table(client_data, mddi_toshiba_init_table,
+				 ARRAY_SIZE(mddi_toshiba_init_table));
+	client_data->auto_hibernate(client_data, 1);
+	panel_id = (client_data->remote_read(client_data, GPIODATA) >> 4) & 3;
+	if (panel_id > 1) {
+		printk(KERN_WARNING "unknown panel id at mddi_enable\n");
+		return -1;
+	}
+	return 0;
+}
+
+static int trout_mddi_toshiba_client_uninit(
+	struct msm_mddi_bridge_platform_data *bridge_data,
+	struct msm_mddi_client_data *client_data)
+{
+	return 0;
+}
+
+static struct resource resources_msm_fb[] = {
+	{
+		.start = MSM_FB_BASE,
+		.end = MSM_FB_BASE + MSM_FB_SIZE,
+		.flags = IORESOURCE_MEM,
+	},
+};
+
+struct msm_mddi_bridge_platform_data toshiba_client_data = {
+	.init = trout_mddi_toshiba_client_init,
+	.uninit = trout_mddi_toshiba_client_uninit,
+	.fb_data = {
+		.xres = 320,
+		.yres = 480,
+		.width = 45,
+		.height = 67,
+		.output_format = 0,
+	},
+};
+
+static struct msm_mddi_platform_data mddi_pdata = {
+	.clk_rate = 122880000,
+	.fb_resource = resources_msm_fb,
+	.num_clients = 1,
+	.client_platform_data = {
+		{
+			.product_id = (0xd263 << 16 | 0),
+			.name = "mddi_c_d263_0000",
+			.id = 0,
+			.client_data = &toshiba_client_data,
+			.clk_rate = 0,
+		},
+	},
+};
+
+int __init trout_init_panel(void)
+{
+	int rc;
+
+	if (!machine_is_trout())
+		return 0;
+	vreg_mddi_1v5 = vreg_get(0, "gp2");
+	if (IS_ERR(vreg_mddi_1v5))
+		return PTR_ERR(vreg_mddi_1v5);
+	vreg_lcm_2v85 = vreg_get(0, "gp4");
+	if (IS_ERR(vreg_lcm_2v85))
+		return PTR_ERR(vreg_lcm_2v85);
+
+	trout_new_backlight = system_rev >= 5;
+	if (trout_new_backlight) {
+		uint32_t config = PCOM_GPIO_CFG(27, 0, GPIO_OUTPUT,
+						GPIO_NO_PULL, GPIO_8MA);
+		msm_proc_comm(PCOM_RPC_GPIO_TLMM_CONFIG_EX, &config, 0);
+	} else {
+		uint32_t config = PCOM_GPIO_CFG(27, 1, GPIO_OUTPUT,
+						GPIO_NO_PULL, GPIO_8MA);
+		msm_proc_comm(PCOM_RPC_GPIO_TLMM_CONFIG_EX, &config, 0);
+
+		gp_clk = clk_get(NULL, "gp_clk");
+		if (IS_ERR(gp_clk)) {
+			printk(KERN_ERR "trout_init_panel: could not get gp"
+			       "clock\n");
+			gp_clk = NULL;
+		}
+		rc = clk_set_rate(gp_clk, 19200000);
+		if (rc)
+			printk(KERN_ERR "trout_init_panel: set clock rate "
+			       "failed\n");
+	}
+
+	rc = platform_device_register(&msm_device_mdp);
+	if (rc)
+		return rc;
+	msm_device_mddi0.dev.platform_data = &mddi_pdata;
+	return platform_device_register(&msm_device_mddi0);
+}
+
+device_initcall(trout_init_panel);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-msm/clock.c linux-libre-2.6.38-gnu1/arch/arm/mach-msm/clock.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-msm/clock.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-msm/clock.c	2011-03-14 21:20:32.000000000 -0400
@@ -120,6 +120,21 @@ EXPORT_SYMBOL(clk_get_rate);
 
 int clk_set_rate(struct clk *clk, unsigned long rate)
 {
+	int ret;
+	if (clk->flags & CLKFLAG_MAX) {
+		ret = clk->ops->set_max_rate(clk->id, rate);
+		if (ret)
+			return ret;
+	}
+	if (clk->flags & CLKFLAG_MIN) {
+		ret = clk->ops->set_min_rate(clk->id, rate);
+		if (ret)
+			return ret;
+	}
+
+	if (clk->flags & CLKFLAG_MAX || clk->flags & CLKFLAG_MIN)
+		return ret;
+
 	return clk->ops->set_rate(clk->id, rate);
 }
 EXPORT_SYMBOL(clk_set_rate);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-msm/devices.h linux-libre-2.6.38-gnu1/arch/arm/mach-msm/devices.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-msm/devices.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-msm/devices.h	2011-03-14 21:20:32.000000000 -0400
@@ -28,6 +28,8 @@ extern struct platform_device msm_device
 extern struct platform_device msm_device_sdc4;
 
 extern struct platform_device msm_device_hsusb;
+extern struct platform_device msm_device_otg;
+extern struct platform_device msm_device_hsusb_host;
 
 extern struct platform_device msm_device_i2c;
 
@@ -35,6 +37,10 @@ extern struct platform_device msm_device
 
 extern struct platform_device msm_device_nand;
 
+extern struct platform_device msm_device_mddi0;
+extern struct platform_device msm_device_mddi1;
+extern struct platform_device msm_device_mdp;
+
 extern struct clk msm_clocks_7x01a[];
 extern unsigned msm_num_clocks_7x01a;
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-msm/devices-msm7x00.c linux-libre-2.6.38-gnu1/arch/arm/mach-msm/devices-msm7x00.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-msm/devices-msm7x00.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-msm/devices-msm7x00.c	2011-03-14 21:20:32.000000000 -0400
@@ -347,6 +347,73 @@ int __init msm_add_sdcc(unsigned int con
 	return platform_device_register(pdev);
 }
 
+static struct resource resources_mddi0[] = {
+	{
+		.start	= MSM_PMDH_PHYS,
+		.end	= MSM_PMDH_PHYS + MSM_PMDH_SIZE - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.start	= INT_MDDI_PRI,
+		.end	= INT_MDDI_PRI,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct resource resources_mddi1[] = {
+	{
+		.start	= MSM_EMDH_PHYS,
+		.end	= MSM_EMDH_PHYS + MSM_EMDH_SIZE - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.start	= INT_MDDI_EXT,
+		.end	= INT_MDDI_EXT,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+struct platform_device msm_device_mddi0 = {
+	.name = "msm_mddi",
+	.id = 0,
+	.num_resources = ARRAY_SIZE(resources_mddi0),
+	.resource = resources_mddi0,
+	.dev = {
+		.coherent_dma_mask      = 0xffffffff,
+	},
+};
+
+struct platform_device msm_device_mddi1 = {
+	.name = "msm_mddi",
+	.id = 1,
+	.num_resources = ARRAY_SIZE(resources_mddi1),
+	.resource = resources_mddi1,
+	.dev = {
+		.coherent_dma_mask      = 0xffffffff,
+	},
+};
+
+static struct resource resources_mdp[] = {
+	{
+		.start	= MSM_MDP_PHYS,
+		.end	= MSM_MDP_PHYS + MSM_MDP_SIZE - 1,
+		.name	= "mdp",
+		.flags	= IORESOURCE_MEM
+	},
+	{
+		.start	= INT_MDP,
+		.end	= INT_MDP,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+struct platform_device msm_device_mdp = {
+	.name = "msm_mdp",
+	.id = 0,
+	.num_resources = ARRAY_SIZE(resources_mdp),
+	.resource = resources_mdp,
+};
+
 struct clk msm_clocks_7x01a[] = {
 	CLK_PCOM("adm_clk",	ADM_CLK,	NULL, 0),
 	CLK_PCOM("adsp_clk",	ADSP_CLK,	NULL, 0),
@@ -364,7 +431,7 @@ struct clk msm_clocks_7x01a[] = {
 	CLK_PCOM("mdp_clk",	MDP_CLK,	NULL, OFF),
 	CLK_PCOM("pbus_clk",	PBUS_CLK,	NULL, 0),
 	CLK_PCOM("pcm_clk",	PCM_CLK,	NULL, 0),
-	CLK_PCOM("pmdh_clk",	PMDH_CLK,	NULL, OFF ),
+	CLK_PCOM("mddi_clk",	PMDH_CLK,	NULL, OFF | CLK_MINMAX),
 	CLK_PCOM("sdac_clk",	SDAC_CLK,	NULL, OFF),
 	CLK_PCOM("sdc_clk",	SDC1_CLK,	&msm_device_sdc1.dev, OFF),
 	CLK_PCOM("sdc_pclk",	SDC1_P_CLK,	&msm_device_sdc1.dev, OFF),
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-msm/devices-msm7x30.c linux-libre-2.6.38-gnu1/arch/arm/mach-msm/devices-msm7x30.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-msm/devices-msm7x30.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-msm/devices-msm7x30.c	2011-03-14 21:20:32.000000000 -0400
@@ -56,6 +56,77 @@ struct platform_device msm_device_smd =
 	.id     = -1,
 };
 
+static struct resource resources_otg[] = {
+	{
+		.start	= MSM_HSUSB_PHYS,
+		.end	= MSM_HSUSB_PHYS + MSM_HSUSB_SIZE,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.start	= INT_USB_HS,
+		.end	= INT_USB_HS,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+struct platform_device msm_device_otg = {
+	.name		= "msm_otg",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(resources_otg),
+	.resource	= resources_otg,
+	.dev		= {
+		.coherent_dma_mask	= 0xffffffff,
+	},
+};
+
+static struct resource resources_hsusb[] = {
+	{
+		.start	= MSM_HSUSB_PHYS,
+		.end	= MSM_HSUSB_PHYS + MSM_HSUSB_SIZE,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.start	= INT_USB_HS,
+		.end	= INT_USB_HS,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+struct platform_device msm_device_hsusb = {
+	.name		= "msm_hsusb",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(resources_hsusb),
+	.resource	= resources_hsusb,
+	.dev		= {
+		.coherent_dma_mask	= 0xffffffff,
+	},
+};
+
+static u64 dma_mask = 0xffffffffULL;
+static struct resource resources_hsusb_host[] = {
+	{
+		.start	= MSM_HSUSB_PHYS,
+		.end	= MSM_HSUSB_PHYS + MSM_HSUSB_SIZE,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.start	= INT_USB_HS,
+		.end	= INT_USB_HS,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+struct platform_device msm_device_hsusb_host = {
+	.name		= "msm_hsusb_host",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(resources_hsusb_host),
+	.resource	= resources_hsusb_host,
+	.dev		= {
+		.dma_mask               = &dma_mask,
+		.coherent_dma_mask      = 0xffffffffULL,
+	},
+};
+
 struct clk msm_clocks_7x30[] = {
 	CLK_PCOM("adm_clk",	ADM_CLK,	NULL, 0),
 	CLK_PCOM("adsp_clk",	ADSP_CLK,	NULL, 0),
@@ -107,6 +178,7 @@ struct clk msm_clocks_7x30[] = {
 	CLK_PCOM("tv_dac_clk",	TV_DAC_CLK,	NULL, 0),
 	CLK_PCOM("tv_enc_clk",	TV_ENC_CLK,	NULL, 0),
 	CLK_PCOM("uart_clk",	UART2_CLK,	&msm_device_uart2.dev, 0),
+	CLK_PCOM("usb_phy_clk",	USB_PHY_CLK,	NULL, 0),
 	CLK_PCOM("usb_hs_clk",		USB_HS_CLK,		NULL, OFF),
 	CLK_PCOM("usb_hs_pclk",		USB_HS_P_CLK,		NULL, OFF),
 	CLK_PCOM("usb_hs_core_clk",	USB_HS_CORE_CLK,	NULL, OFF),
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-msm/devices-msm8x60-iommu.c linux-libre-2.6.38-gnu1/arch/arm/mach-msm/devices-msm8x60-iommu.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-msm/devices-msm8x60-iommu.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-msm/devices-msm8x60-iommu.c	2011-03-14 21:20:32.000000000 -0400
@@ -254,60 +254,86 @@ static struct resource msm_iommu_gfx2d0_
 	},
 };
 
+static struct resource msm_iommu_gfx2d1_resources[] = {
+	{
+		.start = MSM_IOMMU_GFX2D1_PHYS,
+		.end   = MSM_IOMMU_GFX2D1_PHYS + MSM_IOMMU_GFX2D1_SIZE - 1,
+		.name  = "physbase",
+		.flags = IORESOURCE_MEM,
+	},
+	{
+		.name = "nonsecure_irq",
+		.start = SMMU_GFX2D1_CB_SC_NON_SECURE_IRQ,
+		.end   = SMMU_GFX2D1_CB_SC_NON_SECURE_IRQ,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
+		.name = "secure_irq",
+		.start = SMMU_GFX2D1_CB_SC_SECURE_IRQ,
+		.end   = SMMU_GFX2D1_CB_SC_SECURE_IRQ,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
 static struct platform_device msm_root_iommu_dev = {
 	.name = "msm_iommu",
 	.id = -1,
 };
 
-static struct msm_iommu_dev jpegd_smmu = {
+static struct msm_iommu_dev jpegd_iommu = {
 	.name = "jpegd",
 	.clk_rate = -1
 };
 
-static struct msm_iommu_dev vpe_smmu = {
+static struct msm_iommu_dev vpe_iommu = {
 	.name = "vpe"
 };
 
-static struct msm_iommu_dev mdp0_smmu = {
+static struct msm_iommu_dev mdp0_iommu = {
 	.name = "mdp0"
 };
 
-static struct msm_iommu_dev mdp1_smmu = {
+static struct msm_iommu_dev mdp1_iommu = {
 	.name = "mdp1"
 };
 
-static struct msm_iommu_dev rot_smmu = {
+static struct msm_iommu_dev rot_iommu = {
 	.name = "rot"
 };
 
-static struct msm_iommu_dev ijpeg_smmu = {
+static struct msm_iommu_dev ijpeg_iommu = {
 	.name = "ijpeg"
 };
 
-static struct msm_iommu_dev vfe_smmu = {
+static struct msm_iommu_dev vfe_iommu = {
 	.name = "vfe",
 	.clk_rate = -1
 };
 
-static struct msm_iommu_dev vcodec_a_smmu = {
+static struct msm_iommu_dev vcodec_a_iommu = {
 	.name = "vcodec_a"
 };
 
-static struct msm_iommu_dev vcodec_b_smmu = {
+static struct msm_iommu_dev vcodec_b_iommu = {
 	.name = "vcodec_b"
 };
 
-static struct msm_iommu_dev gfx3d_smmu = {
+static struct msm_iommu_dev gfx3d_iommu = {
 	.name = "gfx3d",
 	.clk_rate = 27000000
 };
 
-static struct msm_iommu_dev gfx2d0_smmu = {
+static struct msm_iommu_dev gfx2d0_iommu = {
 	.name = "gfx2d0",
 	.clk_rate = 27000000
 };
 
-static struct platform_device msm_device_smmu_jpegd = {
+static struct msm_iommu_dev gfx2d1_iommu = {
+	.name = "gfx2d1",
+	.clk_rate = 27000000
+};
+
+static struct platform_device msm_device_iommu_jpegd = {
 	.name = "msm_iommu",
 	.id = 0,
 	.dev = {
@@ -317,7 +343,7 @@ static struct platform_device msm_device
 	.resource = msm_iommu_jpegd_resources,
 };
 
-static struct platform_device msm_device_smmu_vpe = {
+static struct platform_device msm_device_iommu_vpe = {
 	.name = "msm_iommu",
 	.id = 1,
 	.dev = {
@@ -327,7 +353,7 @@ static struct platform_device msm_device
 	.resource = msm_iommu_vpe_resources,
 };
 
-static struct platform_device msm_device_smmu_mdp0 = {
+static struct platform_device msm_device_iommu_mdp0 = {
 	.name = "msm_iommu",
 	.id = 2,
 	.dev = {
@@ -337,7 +363,7 @@ static struct platform_device msm_device
 	.resource = msm_iommu_mdp0_resources,
 };
 
-static struct platform_device msm_device_smmu_mdp1 = {
+static struct platform_device msm_device_iommu_mdp1 = {
 	.name = "msm_iommu",
 	.id = 3,
 	.dev = {
@@ -347,7 +373,7 @@ static struct platform_device msm_device
 	.resource = msm_iommu_mdp1_resources,
 };
 
-static struct platform_device msm_device_smmu_rot = {
+static struct platform_device msm_device_iommu_rot = {
 	.name = "msm_iommu",
 	.id = 4,
 	.dev = {
@@ -357,7 +383,7 @@ static struct platform_device msm_device
 	.resource = msm_iommu_rot_resources,
 };
 
-static struct platform_device msm_device_smmu_ijpeg = {
+static struct platform_device msm_device_iommu_ijpeg = {
 	.name = "msm_iommu",
 	.id = 5,
 	.dev = {
@@ -367,7 +393,7 @@ static struct platform_device msm_device
 	.resource = msm_iommu_ijpeg_resources,
 };
 
-static struct platform_device msm_device_smmu_vfe = {
+static struct platform_device msm_device_iommu_vfe = {
 	.name = "msm_iommu",
 	.id = 6,
 	.dev = {
@@ -377,7 +403,7 @@ static struct platform_device msm_device
 	.resource = msm_iommu_vfe_resources,
 };
 
-static struct platform_device msm_device_smmu_vcodec_a = {
+static struct platform_device msm_device_iommu_vcodec_a = {
 	.name = "msm_iommu",
 	.id = 7,
 	.dev = {
@@ -387,7 +413,7 @@ static struct platform_device msm_device
 	.resource = msm_iommu_vcodec_a_resources,
 };
 
-static struct platform_device msm_device_smmu_vcodec_b = {
+static struct platform_device msm_device_iommu_vcodec_b = {
 	.name = "msm_iommu",
 	.id = 8,
 	.dev = {
@@ -397,7 +423,7 @@ static struct platform_device msm_device
 	.resource = msm_iommu_vcodec_b_resources,
 };
 
-static struct platform_device msm_device_smmu_gfx3d = {
+static struct platform_device msm_device_iommu_gfx3d = {
 	.name = "msm_iommu",
 	.id = 9,
 	.dev = {
@@ -407,7 +433,7 @@ static struct platform_device msm_device
 	.resource = msm_iommu_gfx3d_resources,
 };
 
-static struct platform_device msm_device_smmu_gfx2d0 = {
+static struct platform_device msm_device_iommu_gfx2d0 = {
 	.name = "msm_iommu",
 	.id = 10,
 	.dev = {
@@ -417,6 +443,16 @@ static struct platform_device msm_device
 	.resource = msm_iommu_gfx2d0_resources,
 };
 
+struct platform_device msm_device_iommu_gfx2d1 = {
+	.name = "msm_iommu",
+	.id = 11,
+	.dev = {
+		.parent = &msm_root_iommu_dev.dev,
+	},
+	.num_resources = ARRAY_SIZE(msm_iommu_gfx2d1_resources),
+	.resource = msm_iommu_gfx2d1_resources,
+};
+
 static struct msm_iommu_ctx_dev jpegd_src_ctx = {
 	.name = "jpegd_src",
 	.num = 0,
@@ -519,41 +555,36 @@ static struct msm_iommu_ctx_dev vcodec_b
 	.mids = {0, 1, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, -1}
 };
 
-static struct msm_iommu_ctx_dev gfx3d_rbpa_ctx = {
-	.name = "gfx3d_rbpa",
+static struct msm_iommu_ctx_dev gfx3d_user_ctx = {
+	.name = "gfx3d_user",
 	.num = 0,
-	.mids = {-1}
+	.mids = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, -1}
 };
 
-static struct msm_iommu_ctx_dev gfx3d_cpvgttc_ctx = {
-	.name = "gfx3d_cpvgttc",
+static struct msm_iommu_ctx_dev gfx3d_priv_ctx = {
+	.name = "gfx3d_priv",
 	.num = 1,
-	.mids = {0, 1, 2, 3, 4, 5, 6, 7, -1}
-};
-
-static struct msm_iommu_ctx_dev gfx3d_smmu_ctx = {
-	.name = "gfx3d_smmu",
-	.num = 2,
-	.mids = {8, 9, 10, 11, 12, -1}
+	.mids = {16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
+		 31, -1}
 };
 
-static struct msm_iommu_ctx_dev gfx2d0_pixv1_ctx = {
-	.name = "gfx2d0_pixv1_smmu",
+static struct msm_iommu_ctx_dev gfx2d0_2d0_ctx = {
+	.name = "gfx2d0_2d0",
 	.num = 0,
-	.mids = {0, 3, 4, -1}
+	.mids = {0, 1, 2, 3, 4, 5, 6, 7, -1}
 };
 
-static struct msm_iommu_ctx_dev gfx2d0_texv3_ctx = {
-	.name = "gfx2d0_texv3_smmu",
-	.num = 1,
-	.mids = {1, 6, 7, -1}
+static struct msm_iommu_ctx_dev gfx2d1_2d1_ctx = {
+	.name = "gfx2d1_2d1",
+	.num = 0,
+	.mids = {0, 1, 2, 3, 4, 5, 6, 7, -1}
 };
 
 static struct platform_device msm_device_jpegd_src_ctx = {
 	.name = "msm_iommu_ctx",
 	.id = 0,
 	.dev = {
-		.parent = &msm_device_smmu_jpegd.dev,
+		.parent = &msm_device_iommu_jpegd.dev,
 	},
 };
 
@@ -561,7 +592,7 @@ static struct platform_device msm_device
 	.name = "msm_iommu_ctx",
 	.id = 1,
 	.dev = {
-		.parent = &msm_device_smmu_jpegd.dev,
+		.parent = &msm_device_iommu_jpegd.dev,
 	},
 };
 
@@ -569,7 +600,7 @@ static struct platform_device msm_device
 	.name = "msm_iommu_ctx",
 	.id = 2,
 	.dev = {
-		.parent = &msm_device_smmu_vpe.dev,
+		.parent = &msm_device_iommu_vpe.dev,
 	},
 };
 
@@ -577,7 +608,7 @@ static struct platform_device msm_device
 	.name = "msm_iommu_ctx",
 	.id = 3,
 	.dev = {
-		.parent = &msm_device_smmu_vpe.dev,
+		.parent = &msm_device_iommu_vpe.dev,
 	},
 };
 
@@ -585,7 +616,7 @@ static struct platform_device msm_device
 	.name = "msm_iommu_ctx",
 	.id = 4,
 	.dev = {
-		.parent = &msm_device_smmu_mdp0.dev,
+		.parent = &msm_device_iommu_mdp0.dev,
 	},
 };
 
@@ -593,7 +624,7 @@ static struct platform_device msm_device
 	.name = "msm_iommu_ctx",
 	.id = 5,
 	.dev = {
-		.parent = &msm_device_smmu_mdp0.dev,
+		.parent = &msm_device_iommu_mdp0.dev,
 	},
 };
 
@@ -601,7 +632,7 @@ static struct platform_device msm_device
 	.name = "msm_iommu_ctx",
 	.id = 6,
 	.dev = {
-		.parent = &msm_device_smmu_mdp1.dev,
+		.parent = &msm_device_iommu_mdp1.dev,
 	},
 };
 
@@ -609,7 +640,7 @@ static struct platform_device msm_device
 	.name = "msm_iommu_ctx",
 	.id = 7,
 	.dev = {
-		.parent = &msm_device_smmu_mdp1.dev,
+		.parent = &msm_device_iommu_mdp1.dev,
 	},
 };
 
@@ -617,7 +648,7 @@ static struct platform_device msm_device
 	.name = "msm_iommu_ctx",
 	.id = 8,
 	.dev = {
-		.parent = &msm_device_smmu_rot.dev,
+		.parent = &msm_device_iommu_rot.dev,
 	},
 };
 
@@ -625,7 +656,7 @@ static struct platform_device msm_device
 	.name = "msm_iommu_ctx",
 	.id = 9,
 	.dev = {
-		.parent = &msm_device_smmu_rot.dev,
+		.parent = &msm_device_iommu_rot.dev,
 	},
 };
 
@@ -633,7 +664,7 @@ static struct platform_device msm_device
 	.name = "msm_iommu_ctx",
 	.id = 10,
 	.dev = {
-		.parent = &msm_device_smmu_ijpeg.dev,
+		.parent = &msm_device_iommu_ijpeg.dev,
 	},
 };
 
@@ -641,7 +672,7 @@ static struct platform_device msm_device
 	.name = "msm_iommu_ctx",
 	.id = 11,
 	.dev = {
-		.parent = &msm_device_smmu_ijpeg.dev,
+		.parent = &msm_device_iommu_ijpeg.dev,
 	},
 };
 
@@ -649,7 +680,7 @@ static struct platform_device msm_device
 	.name = "msm_iommu_ctx",
 	.id = 12,
 	.dev = {
-		.parent = &msm_device_smmu_vfe.dev,
+		.parent = &msm_device_iommu_vfe.dev,
 	},
 };
 
@@ -657,7 +688,7 @@ static struct platform_device msm_device
 	.name = "msm_iommu_ctx",
 	.id = 13,
 	.dev = {
-		.parent = &msm_device_smmu_vfe.dev,
+		.parent = &msm_device_iommu_vfe.dev,
 	},
 };
 
@@ -665,7 +696,7 @@ static struct platform_device msm_device
 	.name = "msm_iommu_ctx",
 	.id = 14,
 	.dev = {
-		.parent = &msm_device_smmu_vcodec_a.dev,
+		.parent = &msm_device_iommu_vcodec_a.dev,
 	},
 };
 
@@ -673,7 +704,7 @@ static struct platform_device msm_device
 	.name = "msm_iommu_ctx",
 	.id = 15,
 	.dev = {
-		.parent = &msm_device_smmu_vcodec_a.dev,
+		.parent = &msm_device_iommu_vcodec_a.dev,
 	},
 };
 
@@ -681,76 +712,70 @@ static struct platform_device msm_device
 	.name = "msm_iommu_ctx",
 	.id = 16,
 	.dev = {
-		.parent = &msm_device_smmu_vcodec_b.dev,
+		.parent = &msm_device_iommu_vcodec_b.dev,
 	},
 };
 
-static struct platform_device msm_device_gfx3d_rbpa_ctx = {
+static struct platform_device msm_device_gfx3d_user_ctx = {
 	.name = "msm_iommu_ctx",
 	.id = 17,
 	.dev = {
-		.parent = &msm_device_smmu_gfx3d.dev,
+		.parent = &msm_device_iommu_gfx3d.dev,
 	},
 };
 
-static struct platform_device msm_device_gfx3d_cpvgttc_ctx = {
+static struct platform_device msm_device_gfx3d_priv_ctx = {
 	.name = "msm_iommu_ctx",
 	.id = 18,
 	.dev = {
-		.parent = &msm_device_smmu_gfx3d.dev,
+		.parent = &msm_device_iommu_gfx3d.dev,
 	},
 };
 
-static struct platform_device msm_device_gfx3d_smmu_ctx = {
+static struct platform_device msm_device_gfx2d0_2d0_ctx = {
 	.name = "msm_iommu_ctx",
 	.id = 19,
 	.dev = {
-		.parent = &msm_device_smmu_gfx3d.dev,
+		.parent = &msm_device_iommu_gfx2d0.dev,
 	},
 };
 
-static struct platform_device msm_device_gfx2d0_pixv1_ctx = {
+static struct platform_device msm_device_gfx2d1_2d1_ctx = {
 	.name = "msm_iommu_ctx",
 	.id = 20,
 	.dev = {
-		.parent = &msm_device_smmu_gfx2d0.dev,
-	},
-};
-
-static struct platform_device msm_device_gfx2d0_texv3_ctx = {
-	.name = "msm_iommu_ctx",
-	.id = 21,
-	.dev = {
-		.parent = &msm_device_smmu_gfx2d0.dev,
+		.parent = &msm_device_iommu_gfx2d1.dev,
 	},
 };
 
 static struct platform_device *msm_iommu_devs[] = {
-	&msm_device_smmu_jpegd,
-	&msm_device_smmu_vpe,
-	&msm_device_smmu_mdp0,
-	&msm_device_smmu_mdp1,
-	&msm_device_smmu_rot,
-	&msm_device_smmu_ijpeg,
-	&msm_device_smmu_vfe,
-	&msm_device_smmu_vcodec_a,
-	&msm_device_smmu_vcodec_b,
-	&msm_device_smmu_gfx3d,
-	&msm_device_smmu_gfx2d0,
+	&msm_device_iommu_jpegd,
+	&msm_device_iommu_vpe,
+	&msm_device_iommu_mdp0,
+	&msm_device_iommu_mdp1,
+	&msm_device_iommu_rot,
+	&msm_device_iommu_ijpeg,
+	&msm_device_iommu_vfe,
+	&msm_device_iommu_vcodec_a,
+	&msm_device_iommu_vcodec_b,
+	&msm_device_iommu_gfx3d,
+	&msm_device_iommu_gfx2d0,
+	&msm_device_iommu_gfx2d1,
 };
 
 static struct msm_iommu_dev *msm_iommu_data[] = {
-	&jpegd_smmu,
-	&vpe_smmu,
-	&mdp0_smmu,
-	&mdp1_smmu,
-	&rot_smmu,
-	&ijpeg_smmu,
-	&vfe_smmu,
-	&vcodec_a_smmu,
-	&vcodec_b_smmu,
-	&gfx3d_smmu,
-	&gfx2d0_smmu,
+	&jpegd_iommu,
+	&vpe_iommu,
+	&mdp0_iommu,
+	&mdp1_iommu,
+	&rot_iommu,
+	&ijpeg_iommu,
+	&vfe_iommu,
+	&vcodec_a_iommu,
+	&vcodec_b_iommu,
+	&gfx3d_iommu,
+	&gfx2d0_iommu,
+	&gfx2d1_iommu,
 };
 
 static struct platform_device *msm_iommu_ctx_devs[] = {
@@ -771,11 +796,10 @@ static struct platform_device *msm_iommu
 	&msm_device_vcodec_a_stream_ctx,
 	&msm_device_vcodec_a_mm1_ctx,
 	&msm_device_vcodec_b_mm2_ctx,
-	&msm_device_gfx3d_rbpa_ctx,
-	&msm_device_gfx3d_cpvgttc_ctx,
-	&msm_device_gfx3d_smmu_ctx,
-	&msm_device_gfx2d0_pixv1_ctx,
-	&msm_device_gfx2d0_texv3_ctx,
+	&msm_device_gfx3d_user_ctx,
+	&msm_device_gfx3d_priv_ctx,
+	&msm_device_gfx2d0_2d0_ctx,
+	&msm_device_gfx2d1_2d1_ctx,
 };
 
 static struct msm_iommu_ctx_dev *msm_iommu_ctx_data[] = {
@@ -796,14 +820,13 @@ static struct msm_iommu_ctx_dev *msm_iom
 	&vcodec_a_stream_ctx,
 	&vcodec_a_mm1_ctx,
 	&vcodec_b_mm2_ctx,
-	&gfx3d_rbpa_ctx,
-	&gfx3d_cpvgttc_ctx,
-	&gfx3d_smmu_ctx,
-	&gfx2d0_pixv1_ctx,
-	&gfx2d0_texv3_ctx,
+	&gfx3d_user_ctx,
+	&gfx3d_priv_ctx,
+	&gfx2d0_2d0_ctx,
+	&gfx2d1_2d1_ctx,
 };
 
-static int msm8x60_iommu_init(void)
+static int __init msm8x60_iommu_init(void)
 {
 	int ret, i;
 
@@ -826,7 +849,7 @@ static int msm8x60_iommu_init(void)
 		ret = platform_device_register(msm_iommu_devs[i]);
 
 		if (ret != 0) {
-			pr_err("platform_device_register smmu failed, "
+			pr_err("platform_device_register iommu failed, "
 			       "i = %d\n", i);
 			goto failure_unwind;
 		}
@@ -837,7 +860,7 @@ static int msm8x60_iommu_init(void)
 					       msm_iommu_ctx_data[i],
 					       sizeof(*msm_iommu_ctx_devs[i]));
 		if (ret != 0) {
-			pr_err("platform_device_add_data smmu failed, "
+			pr_err("platform_device_add_data iommu failed, "
 			       "i = %d\n", i);
 			goto failure_unwind2;
 		}
@@ -863,7 +886,7 @@ failure:
 	return ret;
 }
 
-static void msm8x60_iommu_exit(void)
+static void __exit msm8x60_iommu_exit(void)
 {
 	int i;
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-msm/devices-qsd8x50.c linux-libre-2.6.38-gnu1/arch/arm/mach-msm/devices-qsd8x50.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-msm/devices-qsd8x50.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-msm/devices-qsd8x50.c	2011-03-14 21:20:32.000000000 -0400
@@ -53,6 +53,77 @@ struct platform_device msm_device_smd =
 	.id     = -1,
 };
 
+static struct resource resources_otg[] = {
+	{
+		.start	= MSM_HSUSB_PHYS,
+		.end	= MSM_HSUSB_PHYS + MSM_HSUSB_SIZE,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.start	= INT_USB_HS,
+		.end	= INT_USB_HS,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+struct platform_device msm_device_otg = {
+	.name		= "msm_otg",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(resources_otg),
+	.resource	= resources_otg,
+	.dev		= {
+		.coherent_dma_mask	= 0xffffffff,
+	},
+};
+
+static struct resource resources_hsusb[] = {
+	{
+		.start	= MSM_HSUSB_PHYS,
+		.end	= MSM_HSUSB_PHYS + MSM_HSUSB_SIZE,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.start	= INT_USB_HS,
+		.end	= INT_USB_HS,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+struct platform_device msm_device_hsusb = {
+	.name		= "msm_hsusb",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(resources_hsusb),
+	.resource	= resources_hsusb,
+	.dev		= {
+		.coherent_dma_mask	= 0xffffffff,
+	},
+};
+
+static u64 dma_mask = 0xffffffffULL;
+static struct resource resources_hsusb_host[] = {
+	{
+		.start	= MSM_HSUSB_PHYS,
+		.end	= MSM_HSUSB_PHYS + MSM_HSUSB_SIZE,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.start	= INT_USB_HS,
+		.end	= INT_USB_HS,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+struct platform_device msm_device_hsusb_host = {
+	.name		= "msm_hsusb_host",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(resources_hsusb_host),
+	.resource	= resources_hsusb_host,
+	.dev		= {
+		.dma_mask               = &dma_mask,
+		.coherent_dma_mask      = 0xffffffffULL,
+	},
+};
+
 struct clk msm_clocks_8x50[] = {
 	CLK_PCOM("adm_clk",	ADM_CLK,	NULL, 0),
 	CLK_PCOM("ebi1_clk",	EBI1_CLK,	NULL, CLK_MIN),
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-msm/gpio.c linux-libre-2.6.38-gnu1/arch/arm/mach-msm/gpio.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-msm/gpio.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-msm/gpio.c	2011-03-14 21:20:32.000000000 -0400
@@ -225,21 +225,21 @@ struct msm_gpio_chip msm_gpio_chips[] =
 #endif
 };
 
-static void msm_gpio_irq_ack(unsigned int irq)
+static void msm_gpio_irq_ack(struct irq_data *d)
 {
 	unsigned long irq_flags;
-	struct msm_gpio_chip *msm_chip = get_irq_chip_data(irq);
+	struct msm_gpio_chip *msm_chip = irq_data_get_irq_chip_data(d);
 	spin_lock_irqsave(&msm_chip->lock, irq_flags);
 	msm_gpio_clear_detect_status(msm_chip,
-				     irq - gpio_to_irq(msm_chip->chip.base));
+				     d->irq - gpio_to_irq(msm_chip->chip.base));
 	spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
 }
 
-static void msm_gpio_irq_mask(unsigned int irq)
+static void msm_gpio_irq_mask(struct irq_data *d)
 {
 	unsigned long irq_flags;
-	struct msm_gpio_chip *msm_chip = get_irq_chip_data(irq);
-	unsigned offset = irq - gpio_to_irq(msm_chip->chip.base);
+	struct msm_gpio_chip *msm_chip = irq_data_get_irq_chip_data(d);
+	unsigned offset = d->irq - gpio_to_irq(msm_chip->chip.base);
 
 	spin_lock_irqsave(&msm_chip->lock, irq_flags);
 	/* level triggered interrupts are also latched */
@@ -250,11 +250,11 @@ static void msm_gpio_irq_mask(unsigned i
 	spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
 }
 
-static void msm_gpio_irq_unmask(unsigned int irq)
+static void msm_gpio_irq_unmask(struct irq_data *d)
 {
 	unsigned long irq_flags;
-	struct msm_gpio_chip *msm_chip = get_irq_chip_data(irq);
-	unsigned offset = irq - gpio_to_irq(msm_chip->chip.base);
+	struct msm_gpio_chip *msm_chip = irq_data_get_irq_chip_data(d);
+	unsigned offset = d->irq - gpio_to_irq(msm_chip->chip.base);
 
 	spin_lock_irqsave(&msm_chip->lock, irq_flags);
 	/* level triggered interrupts are also latched */
@@ -265,11 +265,11 @@ static void msm_gpio_irq_unmask(unsigned
 	spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
 }
 
-static int msm_gpio_irq_set_wake(unsigned int irq, unsigned int on)
+static int msm_gpio_irq_set_wake(struct irq_data *d, unsigned int on)
 {
 	unsigned long irq_flags;
-	struct msm_gpio_chip *msm_chip = get_irq_chip_data(irq);
-	unsigned offset = irq - gpio_to_irq(msm_chip->chip.base);
+	struct msm_gpio_chip *msm_chip = irq_data_get_irq_chip_data(d);
+	unsigned offset = d->irq - gpio_to_irq(msm_chip->chip.base);
 
 	spin_lock_irqsave(&msm_chip->lock, irq_flags);
 
@@ -282,21 +282,21 @@ static int msm_gpio_irq_set_wake(unsigne
 	return 0;
 }
 
-static int msm_gpio_irq_set_type(unsigned int irq, unsigned int flow_type)
+static int msm_gpio_irq_set_type(struct irq_data *d, unsigned int flow_type)
 {
 	unsigned long irq_flags;
-	struct msm_gpio_chip *msm_chip = get_irq_chip_data(irq);
-	unsigned offset = irq - gpio_to_irq(msm_chip->chip.base);
+	struct msm_gpio_chip *msm_chip = irq_data_get_irq_chip_data(d);
+	unsigned offset = d->irq - gpio_to_irq(msm_chip->chip.base);
 	unsigned val, mask = BIT(offset);
 
 	spin_lock_irqsave(&msm_chip->lock, irq_flags);
 	val = readl(msm_chip->regs.int_edge);
 	if (flow_type & IRQ_TYPE_EDGE_BOTH) {
 		writel(val | mask, msm_chip->regs.int_edge);
-		irq_desc[irq].handle_irq = handle_edge_irq;
+		irq_desc[d->irq].handle_irq = handle_edge_irq;
 	} else {
 		writel(val & ~mask, msm_chip->regs.int_edge);
-		irq_desc[irq].handle_irq = handle_level_irq;
+		irq_desc[d->irq].handle_irq = handle_level_irq;
 	}
 	if ((flow_type & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH) {
 		msm_chip->both_edge_detect |= mask;
@@ -333,16 +333,16 @@ static void msm_gpio_irq_handler(unsigne
 					   msm_chip->chip.base + j);
 		}
 	}
-	desc->chip->ack(irq);
+	desc->irq_data.chip->irq_ack(&desc->irq_data);
 }
 
 static struct irq_chip msm_gpio_irq_chip = {
-	.name      = "msmgpio",
-	.ack       = msm_gpio_irq_ack,
-	.mask      = msm_gpio_irq_mask,
-	.unmask    = msm_gpio_irq_unmask,
-	.set_wake  = msm_gpio_irq_set_wake,
-	.set_type  = msm_gpio_irq_set_type,
+	.name          = "msmgpio",
+	.irq_ack       = msm_gpio_irq_ack,
+	.irq_mask      = msm_gpio_irq_mask,
+	.irq_unmask    = msm_gpio_irq_unmask,
+	.irq_set_wake  = msm_gpio_irq_set_wake,
+	.irq_set_type  = msm_gpio_irq_set_type,
 };
 
 static int __init msm_init_gpio(void)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-msm/gpio-v2.c linux-libre-2.6.38-gnu1/arch/arm/mach-msm/gpio-v2.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-msm/gpio-v2.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-msm/gpio-v2.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,426 @@
+/* Copyright (c) 2010, 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 pr_fmt(fmt) "%s: " fmt, __func__
+
+#include <linux/bitmap.h>
+#include <linux/bitops.h>
+#include <linux/gpio.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+#include <mach/msm_iomap.h>
+#include "gpiomux.h"
+
+/* Bits of interest in the GPIO_IN_OUT register.
+ */
+enum {
+	GPIO_IN  = 0,
+	GPIO_OUT = 1
+};
+
+/* Bits of interest in the GPIO_INTR_STATUS register.
+ */
+enum {
+	INTR_STATUS = 0,
+};
+
+/* Bits of interest in the GPIO_CFG register.
+ */
+enum {
+	GPIO_OE = 9,
+};
+
+/* Bits of interest in the GPIO_INTR_CFG register.
+ * When a GPIO triggers, two separate decisions are made, controlled
+ * by two separate flags.
+ *
+ * - First, INTR_RAW_STATUS_EN controls whether or not the GPIO_INTR_STATUS
+ * register for that GPIO will be updated to reflect the triggering of that
+ * gpio.  If this bit is 0, this register will not be updated.
+ * - Second, INTR_ENABLE controls whether an interrupt is triggered.
+ *
+ * If INTR_ENABLE is set and INTR_RAW_STATUS_EN is NOT set, an interrupt
+ * can be triggered but the status register will not reflect it.
+ */
+enum {
+	INTR_ENABLE        = 0,
+	INTR_POL_CTL       = 1,
+	INTR_DECT_CTL      = 2,
+	INTR_RAW_STATUS_EN = 3,
+};
+
+/* Codes of interest in GPIO_INTR_CFG_SU.
+ */
+enum {
+	TARGET_PROC_SCORPION = 4,
+	TARGET_PROC_NONE     = 7,
+};
+
+
+#define GPIO_INTR_CFG_SU(gpio)    (MSM_TLMM_BASE + 0x0400 + (0x04 * (gpio)))
+#define GPIO_CONFIG(gpio)         (MSM_TLMM_BASE + 0x1000 + (0x10 * (gpio)))
+#define GPIO_IN_OUT(gpio)         (MSM_TLMM_BASE + 0x1004 + (0x10 * (gpio)))
+#define GPIO_INTR_CFG(gpio)       (MSM_TLMM_BASE + 0x1008 + (0x10 * (gpio)))
+#define GPIO_INTR_STATUS(gpio)    (MSM_TLMM_BASE + 0x100c + (0x10 * (gpio)))
+
+/**
+ * struct msm_gpio_dev: the MSM8660 SoC GPIO device structure
+ *
+ * @enabled_irqs: a bitmap used to optimize the summary-irq handler.  By
+ * keeping track of which gpios are unmasked as irq sources, we avoid
+ * having to do readl calls on hundreds of iomapped registers each time
+ * the summary interrupt fires in order to locate the active interrupts.
+ *
+ * @wake_irqs: a bitmap for tracking which interrupt lines are enabled
+ * as wakeup sources.  When the device is suspended, interrupts which are
+ * not wakeup sources are disabled.
+ *
+ * @dual_edge_irqs: a bitmap used to track which irqs are configured
+ * as dual-edge, as this is not supported by the hardware and requires
+ * some special handling in the driver.
+ */
+struct msm_gpio_dev {
+	struct gpio_chip gpio_chip;
+	DECLARE_BITMAP(enabled_irqs, NR_GPIO_IRQS);
+	DECLARE_BITMAP(wake_irqs, NR_GPIO_IRQS);
+	DECLARE_BITMAP(dual_edge_irqs, NR_GPIO_IRQS);
+};
+
+static DEFINE_SPINLOCK(tlmm_lock);
+
+static inline struct msm_gpio_dev *to_msm_gpio_dev(struct gpio_chip *chip)
+{
+	return container_of(chip, struct msm_gpio_dev, gpio_chip);
+}
+
+static inline void set_gpio_bits(unsigned n, void __iomem *reg)
+{
+	writel(readl(reg) | n, reg);
+}
+
+static inline void clear_gpio_bits(unsigned n, void __iomem *reg)
+{
+	writel(readl(reg) & ~n, reg);
+}
+
+static int msm_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+	return readl(GPIO_IN_OUT(offset)) & BIT(GPIO_IN);
+}
+
+static void msm_gpio_set(struct gpio_chip *chip, unsigned offset, int val)
+{
+	writel(val ? BIT(GPIO_OUT) : 0, GPIO_IN_OUT(offset));
+}
+
+static int msm_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+	unsigned long irq_flags;
+
+	spin_lock_irqsave(&tlmm_lock, irq_flags);
+	clear_gpio_bits(BIT(GPIO_OE), GPIO_CONFIG(offset));
+	spin_unlock_irqrestore(&tlmm_lock, irq_flags);
+	return 0;
+}
+
+static int msm_gpio_direction_output(struct gpio_chip *chip,
+				unsigned offset,
+				int val)
+{
+	unsigned long irq_flags;
+
+	spin_lock_irqsave(&tlmm_lock, irq_flags);
+	msm_gpio_set(chip, offset, val);
+	set_gpio_bits(BIT(GPIO_OE), GPIO_CONFIG(offset));
+	spin_unlock_irqrestore(&tlmm_lock, irq_flags);
+	return 0;
+}
+
+static int msm_gpio_request(struct gpio_chip *chip, unsigned offset)
+{
+	return msm_gpiomux_get(chip->base + offset);
+}
+
+static void msm_gpio_free(struct gpio_chip *chip, unsigned offset)
+{
+	msm_gpiomux_put(chip->base + offset);
+}
+
+static int msm_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+	return MSM_GPIO_TO_INT(chip->base + offset);
+}
+
+static inline int msm_irq_to_gpio(struct gpio_chip *chip, unsigned irq)
+{
+	return irq - MSM_GPIO_TO_INT(chip->base);
+}
+
+static struct msm_gpio_dev msm_gpio = {
+	.gpio_chip = {
+		.base             = 0,
+		.ngpio            = NR_GPIO_IRQS,
+		.direction_input  = msm_gpio_direction_input,
+		.direction_output = msm_gpio_direction_output,
+		.get              = msm_gpio_get,
+		.set              = msm_gpio_set,
+		.to_irq           = msm_gpio_to_irq,
+		.request          = msm_gpio_request,
+		.free             = msm_gpio_free,
+	},
+};
+
+/* For dual-edge interrupts in software, since the hardware has no
+ * such support:
+ *
+ * At appropriate moments, this function may be called to flip the polarity
+ * settings of both-edge irq lines to try and catch the next edge.
+ *
+ * The attempt is considered successful if:
+ * - the status bit goes high, indicating that an edge was caught, or
+ * - the input value of the gpio doesn't change during the attempt.
+ * If the value changes twice during the process, that would cause the first
+ * test to fail but would force the second, as two opposite
+ * transitions would cause a detection no matter the polarity setting.
+ *
+ * The do-loop tries to sledge-hammer closed the timing hole between
+ * the initial value-read and the polarity-write - if the line value changes
+ * during that window, an interrupt is lost, the new polarity setting is
+ * incorrect, and the first success test will fail, causing a retry.
+ *
+ * Algorithm comes from Google's msmgpio driver, see mach-msm/gpio.c.
+ */
+static void msm_gpio_update_dual_edge_pos(unsigned gpio)
+{
+	int loop_limit = 100;
+	unsigned val, val2, intstat;
+
+	do {
+		val = readl(GPIO_IN_OUT(gpio)) & BIT(GPIO_IN);
+		if (val)
+			clear_gpio_bits(BIT(INTR_POL_CTL), GPIO_INTR_CFG(gpio));
+		else
+			set_gpio_bits(BIT(INTR_POL_CTL), GPIO_INTR_CFG(gpio));
+		val2 = readl(GPIO_IN_OUT(gpio)) & BIT(GPIO_IN);
+		intstat = readl(GPIO_INTR_STATUS(gpio)) & BIT(INTR_STATUS);
+		if (intstat || val == val2)
+			return;
+	} while (loop_limit-- > 0);
+	pr_err("dual-edge irq failed to stabilize, "
+	       "interrupts dropped. %#08x != %#08x\n",
+	       val, val2);
+}
+
+static void msm_gpio_irq_ack(unsigned int irq)
+{
+	int gpio = msm_irq_to_gpio(&msm_gpio.gpio_chip, irq);
+
+	writel(BIT(INTR_STATUS), GPIO_INTR_STATUS(gpio));
+	if (test_bit(gpio, msm_gpio.dual_edge_irqs))
+		msm_gpio_update_dual_edge_pos(gpio);
+}
+
+static void msm_gpio_irq_mask(unsigned int irq)
+{
+	int gpio = msm_irq_to_gpio(&msm_gpio.gpio_chip, irq);
+	unsigned long irq_flags;
+
+	spin_lock_irqsave(&tlmm_lock, irq_flags);
+	writel(TARGET_PROC_NONE, GPIO_INTR_CFG_SU(gpio));
+	clear_gpio_bits(INTR_RAW_STATUS_EN | INTR_ENABLE, GPIO_INTR_CFG(gpio));
+	__clear_bit(gpio, msm_gpio.enabled_irqs);
+	spin_unlock_irqrestore(&tlmm_lock, irq_flags);
+}
+
+static void msm_gpio_irq_unmask(unsigned int irq)
+{
+	int gpio = msm_irq_to_gpio(&msm_gpio.gpio_chip, irq);
+	unsigned long irq_flags;
+
+	spin_lock_irqsave(&tlmm_lock, irq_flags);
+	__set_bit(gpio, msm_gpio.enabled_irqs);
+	set_gpio_bits(INTR_RAW_STATUS_EN | INTR_ENABLE, GPIO_INTR_CFG(gpio));
+	writel(TARGET_PROC_SCORPION, GPIO_INTR_CFG_SU(gpio));
+	spin_unlock_irqrestore(&tlmm_lock, irq_flags);
+}
+
+static int msm_gpio_irq_set_type(unsigned int irq, unsigned int flow_type)
+{
+	int gpio = msm_irq_to_gpio(&msm_gpio.gpio_chip, irq);
+	unsigned long irq_flags;
+	uint32_t bits;
+
+	spin_lock_irqsave(&tlmm_lock, irq_flags);
+
+	bits = readl(GPIO_INTR_CFG(gpio));
+
+	if (flow_type & IRQ_TYPE_EDGE_BOTH) {
+		bits |= BIT(INTR_DECT_CTL);
+		irq_desc[irq].handle_irq = handle_edge_irq;
+		if ((flow_type & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH)
+			__set_bit(gpio, msm_gpio.dual_edge_irqs);
+		else
+			__clear_bit(gpio, msm_gpio.dual_edge_irqs);
+	} else {
+		bits &= ~BIT(INTR_DECT_CTL);
+		irq_desc[irq].handle_irq = handle_level_irq;
+		__clear_bit(gpio, msm_gpio.dual_edge_irqs);
+	}
+
+	if (flow_type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_LEVEL_HIGH))
+		bits |= BIT(INTR_POL_CTL);
+	else
+		bits &= ~BIT(INTR_POL_CTL);
+
+	writel(bits, GPIO_INTR_CFG(gpio));
+
+	if ((flow_type & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH)
+		msm_gpio_update_dual_edge_pos(gpio);
+
+	spin_unlock_irqrestore(&tlmm_lock, irq_flags);
+
+	return 0;
+}
+
+/*
+ * When the summary IRQ is raised, any number of GPIO lines may be high.
+ * It is the job of the summary handler to find all those GPIO lines
+ * which have been set as summary IRQ lines and which are triggered,
+ * and to call their interrupt handlers.
+ */
+static void msm_summary_irq_handler(unsigned int irq, struct irq_desc *desc)
+{
+	unsigned long i;
+
+	for (i = find_first_bit(msm_gpio.enabled_irqs, NR_GPIO_IRQS);
+	     i < NR_GPIO_IRQS;
+	     i = find_next_bit(msm_gpio.enabled_irqs, NR_GPIO_IRQS, i + 1)) {
+		if (readl(GPIO_INTR_STATUS(i)) & BIT(INTR_STATUS))
+			generic_handle_irq(msm_gpio_to_irq(&msm_gpio.gpio_chip,
+							   i));
+	}
+	desc->chip->ack(irq);
+}
+
+static int msm_gpio_irq_set_wake(unsigned int irq, unsigned int on)
+{
+	int gpio = msm_irq_to_gpio(&msm_gpio.gpio_chip, irq);
+
+	if (on) {
+		if (bitmap_empty(msm_gpio.wake_irqs, NR_GPIO_IRQS))
+			set_irq_wake(TLMM_SCSS_SUMMARY_IRQ, 1);
+		set_bit(gpio, msm_gpio.wake_irqs);
+	} else {
+		clear_bit(gpio, msm_gpio.wake_irqs);
+		if (bitmap_empty(msm_gpio.wake_irqs, NR_GPIO_IRQS))
+			set_irq_wake(TLMM_SCSS_SUMMARY_IRQ, 0);
+	}
+
+	return 0;
+}
+
+static struct irq_chip msm_gpio_irq_chip = {
+	.name		= "msmgpio",
+	.mask		= msm_gpio_irq_mask,
+	.unmask		= msm_gpio_irq_unmask,
+	.ack		= msm_gpio_irq_ack,
+	.set_type	= msm_gpio_irq_set_type,
+	.set_wake	= msm_gpio_irq_set_wake,
+};
+
+static int __devinit msm_gpio_probe(struct platform_device *dev)
+{
+	int i, irq, ret;
+
+	bitmap_zero(msm_gpio.enabled_irqs, NR_GPIO_IRQS);
+	bitmap_zero(msm_gpio.wake_irqs, NR_GPIO_IRQS);
+	bitmap_zero(msm_gpio.dual_edge_irqs, NR_GPIO_IRQS);
+	msm_gpio.gpio_chip.label = dev->name;
+	ret = gpiochip_add(&msm_gpio.gpio_chip);
+	if (ret < 0)
+		return ret;
+
+	for (i = 0; i < msm_gpio.gpio_chip.ngpio; ++i) {
+		irq = msm_gpio_to_irq(&msm_gpio.gpio_chip, i);
+		set_irq_chip(irq, &msm_gpio_irq_chip);
+		set_irq_handler(irq, handle_level_irq);
+		set_irq_flags(irq, IRQF_VALID);
+	}
+
+	set_irq_chained_handler(TLMM_SCSS_SUMMARY_IRQ,
+				msm_summary_irq_handler);
+	return 0;
+}
+
+static int __devexit msm_gpio_remove(struct platform_device *dev)
+{
+	int ret = gpiochip_remove(&msm_gpio.gpio_chip);
+
+	if (ret < 0)
+		return ret;
+
+	set_irq_handler(TLMM_SCSS_SUMMARY_IRQ, NULL);
+
+	return 0;
+}
+
+static struct platform_driver msm_gpio_driver = {
+	.probe = msm_gpio_probe,
+	.remove = __devexit_p(msm_gpio_remove),
+	.driver = {
+		.name = "msmgpio",
+		.owner = THIS_MODULE,
+	},
+};
+
+static struct platform_device msm_device_gpio = {
+	.name = "msmgpio",
+	.id   = -1,
+};
+
+static int __init msm_gpio_init(void)
+{
+	int rc;
+
+	rc = platform_driver_register(&msm_gpio_driver);
+	if (!rc) {
+		rc = platform_device_register(&msm_device_gpio);
+		if (rc)
+			platform_driver_unregister(&msm_gpio_driver);
+	}
+
+	return rc;
+}
+
+static void __exit msm_gpio_exit(void)
+{
+	platform_device_unregister(&msm_device_gpio);
+	platform_driver_unregister(&msm_gpio_driver);
+}
+
+postcore_initcall(msm_gpio_init);
+module_exit(msm_gpio_exit);
+
+MODULE_AUTHOR("Gregory Bean <gbean@codeaurora.org>");
+MODULE_DESCRIPTION("Driver for Qualcomm MSM TLMMv2 SoC GPIOs");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:msmgpio");
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-msm/headsmp.S linux-libre-2.6.38-gnu1/arch/arm/mach-msm/headsmp.S
--- linux-libre-2.6.37-gnu1/arch/arm/mach-msm/headsmp.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-msm/headsmp.S	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,40 @@
+/*
+ *  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>
+
+	__INIT
+
+/*
+ * MSM 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(msm_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
+
+	.align
+1:	.long	.
+	.long	pen_release
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-msm/hotplug.c linux-libre-2.6.38-gnu1/arch/arm/mach-msm/hotplug.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-msm/hotplug.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-msm/hotplug.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,91 @@
+/*
+ *  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 <asm/cacheflush.h>
+
+extern volatile int pen_release;
+
+static inline void cpu_enter_lowpower(void)
+{
+	/* Just flush the cache. Changing the coherency is not yet
+	 * available on msm. */
+	flush_cache_all();
+}
+
+static inline void cpu_leave_lowpower(void)
+{
+}
+
+static inline void platform_do_lowpower(unsigned int cpu)
+{
+	/* Just enter wfi for now. TODO: Properly shut off the cpu. */
+	for (;;) {
+		/*
+		 * here's the WFI
+		 */
+		asm("wfi"
+		    :
+		    :
+		    : "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
+		 *
+		 * The trouble is, letting people know about this is not really
+		 * possible, since we are currently running incoherently, and
+		 * therefore cannot safely call printk() or anything else
+		 */
+		pr_debug("CPU%u: spurious wakeup call\n", cpu);
+	}
+}
+
+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)
+{
+	/*
+	 * we're ready for shutdown now, so do it
+	 */
+	cpu_enter_lowpower();
+	platform_do_lowpower(cpu);
+
+	/*
+	 * bring this CPU back into the world of cache
+	 * coherency, and then restore interrupts
+	 */
+	cpu_leave_lowpower();
+}
+
+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-2.6.37-gnu1/arch/arm/mach-msm/include/mach/entry-macro-qgic.S linux-libre-2.6.38-gnu1/arch/arm/mach-msm/include/mach/entry-macro-qgic.S
--- linux-libre-2.6.37-gnu1/arch/arm/mach-msm/include/mach/entry-macro-qgic.S	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-msm/include/mach/entry-macro-qgic.S	2011-03-14 21:20:32.000000000 -0400
@@ -26,7 +26,7 @@
 	 * The interrupt numbering scheme is defined in the
 	 * interrupt controller spec.  To wit:
 	 *
-	 * Migrated the code from ARM MP port to be more consistant
+	 * 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
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-msm/include/mach/iommu.h linux-libre-2.6.38-gnu1/arch/arm/mach-msm/include/mach/iommu.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-msm/include/mach/iommu.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-msm/include/mach/iommu.h	2011-03-14 21:20:32.000000000 -0400
@@ -20,13 +20,26 @@
 
 #include <linux/interrupt.h>
 
+/* Sharability attributes of MSM IOMMU mappings */
+#define MSM_IOMMU_ATTR_NON_SH		0x0
+#define MSM_IOMMU_ATTR_SH		0x4
+
+/* Cacheability attributes of MSM IOMMU mappings */
+#define MSM_IOMMU_ATTR_NONCACHED	0x0
+#define MSM_IOMMU_ATTR_CACHED_WB_WA	0x1
+#define MSM_IOMMU_ATTR_CACHED_WB_NWA	0x2
+#define MSM_IOMMU_ATTR_CACHED_WT	0x3
+
+/* Mask for the cache policy attribute */
+#define MSM_IOMMU_CP_MASK		0x03
+
 /* Maximum number of Machine IDs that we are allowing to be mapped to the same
  * context bank. The number of MIDs mapped to the same CB does not affect
  * performance, but there is a practical limit on how many distinct MIDs may
  * be present. These mappings are typically determined at design time and are
  * not expected to change at run time.
  */
-#define MAX_NUM_MIDS	16
+#define MAX_NUM_MIDS	32
 
 /**
  * struct msm_iommu_dev - a single IOMMU hardware instance
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-msm/include/mach/iommu_hw-8xxx.h linux-libre-2.6.38-gnu1/arch/arm/mach-msm/include/mach/iommu_hw-8xxx.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-msm/include/mach/iommu_hw-8xxx.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-msm/include/mach/iommu_hw-8xxx.h	2011-03-14 21:20:32.000000000 -0400
@@ -54,6 +54,7 @@ do { \
 
 #define NUM_FL_PTE	4096
 #define NUM_SL_PTE	256
+#define NUM_TEX_CLASS	8
 
 /* First-level page table bits */
 #define FL_BASE_MASK		0xFFFFFC00
@@ -63,6 +64,9 @@ do { \
 #define FL_AP_WRITE		(1 << 10)
 #define FL_AP_READ		(1 << 11)
 #define FL_SHARED		(1 << 16)
+#define FL_BUFFERABLE		(1 << 2)
+#define FL_CACHEABLE		(1 << 3)
+#define FL_TEX0			(1 << 12)
 #define FL_OFFSET(va)		(((va) & 0xFFF00000) >> 20)
 
 /* Second-level page table bits */
@@ -73,8 +77,20 @@ do { \
 #define SL_AP0			(1 << 4)
 #define SL_AP1			(2 << 4)
 #define SL_SHARED		(1 << 10)
+#define SL_BUFFERABLE		(1 << 2)
+#define SL_CACHEABLE		(1 << 3)
+#define SL_TEX0			(1 << 6)
 #define SL_OFFSET(va)		(((va) & 0xFF000) >> 12)
 
+/* Memory type and cache policy attributes */
+#define MT_SO			0
+#define MT_DEV			1
+#define MT_NORMAL		2
+#define CP_NONCACHED		0
+#define CP_WB_WA		1
+#define CP_WT			2
+#define CP_WB_NWA		3
+
 /* Global register setters / getters */
 #define SET_M2VCBR_N(b, N, v)	 SET_GLOBAL_REG_N(M2VCBR_N, N, (b), (v))
 #define SET_CBACR_N(b, N, v)	 SET_GLOBAL_REG_N(CBACR_N, N, (b), (v))
@@ -706,7 +722,9 @@ do { \
 #define GET_OCPC5(b, c)		GET_CONTEXT_FIELD(b, c, NMRR, OCPC5)
 #define GET_OCPC6(b, c)		GET_CONTEXT_FIELD(b, c, NMRR, OCPC6)
 #define GET_OCPC7(b, c)		GET_CONTEXT_FIELD(b, c, NMRR, OCPC7)
-
+#define NMRR_ICP(nmrr, n)	(((nmrr) & (3 << ((n) * 2))) >> ((n) * 2))
+#define NMRR_OCP(nmrr, n)	(((nmrr) & (3 << ((n) * 2 + 16))) >> \
+								((n) * 2 + 16))
 
 /* PAR */
 #define GET_FAULT(b, c)		GET_CONTEXT_FIELD(b, c, PAR, FAULT)
@@ -750,6 +768,8 @@ do { \
 #define GET_NOS5(b, c)		GET_CONTEXT_FIELD(b, c, PRRR, NOS5)
 #define GET_NOS6(b, c)		GET_CONTEXT_FIELD(b, c, PRRR, NOS6)
 #define GET_NOS7(b, c)		GET_CONTEXT_FIELD(b, c, PRRR, NOS7)
+#define PRRR_NOS(prrr, n)	 ((prrr) & (1 << ((n) + 24)) ? 1 : 0)
+#define PRRR_MT(prrr, n)	 ((((prrr) & (3 << ((n) * 2))) >> ((n) * 2)))
 
 
 /* RESUME */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-msm/include/mach/irqs-8x60.h linux-libre-2.6.38-gnu1/arch/arm/mach-msm/include/mach/irqs-8x60.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-msm/include/mach/irqs-8x60.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-msm/include/mach/irqs-8x60.h	2011-03-14 21:20:32.000000000 -0400
@@ -237,7 +237,12 @@
 #define GSBI11_QUP_IRQ				(GIC_SPI_START + 194)
 #define INT_UART12DM_IRQ			(GIC_SPI_START + 195)
 #define GSBI12_QUP_IRQ				(GIC_SPI_START + 196)
-/*SPI 197 to 216 arent used in 8x60*/
+
+/*SPI 197 to 209 arent used in 8x60*/
+#define SMMU_GFX2D1_CB_SC_SECURE_IRQ            (GIC_SPI_START + 210)
+#define SMMU_GFX2D1_CB_SC_NON_SECURE_IRQ        (GIC_SPI_START + 211)
+
+/*SPI 212 to 216 arent used in 8x60*/
 #define SMPSS_SPARE_1				(GIC_SPI_START + 217)
 #define SMPSS_SPARE_2				(GIC_SPI_START + 218)
 #define SMPSS_SPARE_3				(GIC_SPI_START + 219)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-msm/include/mach/msm_iomap-7x30.h linux-libre-2.6.38-gnu1/arch/arm/mach-msm/include/mach/msm_iomap-7x30.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-msm/include/mach/msm_iomap-7x30.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-msm/include/mach/msm_iomap-7x30.h	2011-03-14 21:20:32.000000000 -0400
@@ -119,4 +119,7 @@
 #define MSM_AD5_PHYS          0xA7000000
 #define MSM_AD5_SIZE          (SZ_1M*13)
 
+#define MSM_HSUSB_PHYS        0xA3600000
+#define MSM_HSUSB_SIZE        SZ_1K
+
 #endif
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-msm/include/mach/msm_iomap-8x60.h linux-libre-2.6.38-gnu1/arch/arm/mach-msm/include/mach/msm_iomap-8x60.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-msm/include/mach/msm_iomap-8x60.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-msm/include/mach/msm_iomap-8x60.h	2011-03-14 21:20:32.000000000 -0400
@@ -60,7 +60,11 @@
 
 #define MSM_TMR_BASE		IOMEM(0xF0200000)
 #define MSM_TMR_PHYS		0x02000000
-#define MSM_TMR_SIZE		(SZ_1M)
+#define MSM_TMR_SIZE		SZ_4K
+
+#define MSM_TMR0_BASE		IOMEM(0xF0201000)
+#define MSM_TMR0_PHYS		0x02040000
+#define MSM_TMR0_SIZE		SZ_4K
 
 #define MSM_GPT_BASE		(MSM_TMR_BASE + 0x4)
 #define MSM_DGT_BASE		(MSM_TMR_BASE + 0x24)
@@ -98,4 +102,7 @@
 #define MSM_IOMMU_GFX2D0_PHYS	0x07D00000
 #define MSM_IOMMU_GFX2D0_SIZE	SZ_1M
 
+#define MSM_IOMMU_GFX2D1_PHYS	0x07E00000
+#define MSM_IOMMU_GFX2D1_SIZE	SZ_1M
+
 #endif
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-msm/include/mach/smp.h linux-libre-2.6.38-gnu1/arch/arm/mach-msm/include/mach/smp.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-msm/include/mach/smp.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-msm/include/mach/smp.h	2011-03-14 21:20:32.000000000 -0400
@@ -31,9 +31,9 @@
 
 #include <asm/hardware/gic.h>
 
-static inline void smp_cross_call(const struct cpumask *mask)
+static inline void smp_cross_call(const struct cpumask *mask, int ipi)
 {
-	gic_raise_softirq(mask, 1);
+	gic_raise_softirq(mask, ipi);
 }
 
 #endif
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-msm/io.c linux-libre-2.6.38-gnu1/arch/arm/mach-msm/io.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-msm/io.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-msm/io.c	2011-03-14 21:20:32.000000000 -0400
@@ -105,6 +105,7 @@ static struct map_desc msm8x60_io_desc[]
 	MSM_DEVICE(QGIC_DIST),
 	MSM_DEVICE(QGIC_CPU),
 	MSM_DEVICE(TMR),
+	MSM_DEVICE(TMR0),
 	MSM_DEVICE(ACC),
 	MSM_DEVICE(GCC),
 };
@@ -153,7 +154,7 @@ __msm_ioremap(unsigned long phys_addr, s
 {
 	if (mtype == MT_DEVICE) {
 		/* The peripherals in the 88000000 - D0000000 range
-		 * are only accessable by type MT_DEVICE_NONSHARED.
+		 * are only accessible by type MT_DEVICE_NONSHARED.
 		 * Adjust mtype as necessary to make this "just work."
 		 */
 		if ((phys_addr >= 0x88000000) && (phys_addr < 0xD0000000))
@@ -163,3 +164,4 @@ __msm_ioremap(unsigned long phys_addr, s
 	return __arm_ioremap_caller(phys_addr, size, mtype,
 		__builtin_return_address(0));
 }
+EXPORT_SYMBOL(__msm_ioremap);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-msm/iommu.c linux-libre-2.6.38-gnu1/arch/arm/mach-msm/iommu.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-msm/iommu.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-msm/iommu.c	2011-03-14 21:20:32.000000000 -0400
@@ -33,6 +33,16 @@
 #include <mach/iommu_hw-8xxx.h>
 #include <mach/iommu.h>
 
+#define MRC(reg, processor, op1, crn, crm, op2)				\
+__asm__ __volatile__ (							\
+"   mrc   "   #processor "," #op1 ", %0,"  #crn "," #crm "," #op2 "\n"  \
+: "=r" (reg))
+
+#define RCP15_PRRR(reg)		MRC(reg, p15, 0, c10, c2, 0)
+#define RCP15_NMRR(reg)		MRC(reg, p15, 0, c10, c2, 1)
+
+static int msm_iommu_tex_class[4];
+
 DEFINE_SPINLOCK(msm_iommu_lock);
 
 struct msm_priv {
@@ -40,23 +50,26 @@ struct msm_priv {
 	struct list_head list_attached;
 };
 
-static void __flush_iotlb(struct iommu_domain *domain)
+static int __flush_iotlb(struct iommu_domain *domain)
 {
 	struct msm_priv *priv = domain->priv;
 	struct msm_iommu_drvdata *iommu_drvdata;
 	struct msm_iommu_ctx_drvdata *ctx_drvdata;
-
+	int ret = 0;
 #ifndef CONFIG_IOMMU_PGTABLES_L2
 	unsigned long *fl_table = priv->pgtable;
 	int i;
 
-	dmac_flush_range(fl_table, fl_table + SZ_16K);
+	if (!list_empty(&priv->list_attached)) {
+		dmac_flush_range(fl_table, fl_table + SZ_16K);
 
-	for (i = 0; i < NUM_FL_PTE; i++)
-		if ((fl_table[i] & 0x03) == FL_TYPE_TABLE) {
-			void *sl_table = __va(fl_table[i] & FL_BASE_MASK);
-			dmac_flush_range(sl_table, sl_table + SZ_4K);
-		}
+		for (i = 0; i < NUM_FL_PTE; i++)
+			if ((fl_table[i] & 0x03) == FL_TYPE_TABLE) {
+				void *sl_table = __va(fl_table[i] &
+								FL_BASE_MASK);
+				dmac_flush_range(sl_table, sl_table + SZ_4K);
+			}
+	}
 #endif
 
 	list_for_each_entry(ctx_drvdata, &priv->list_attached, attached_elm) {
@@ -66,6 +79,8 @@ static void __flush_iotlb(struct iommu_d
 		iommu_drvdata = dev_get_drvdata(ctx_drvdata->pdev->dev.parent);
 		SET_CTX_TLBIALL(iommu_drvdata->base, ctx_drvdata->num, 0);
 	}
+
+	return ret;
 }
 
 static void __reset_context(void __iomem *base, int ctx)
@@ -95,6 +110,7 @@ static void __reset_context(void __iomem
 
 static void __program_context(void __iomem *base, int ctx, phys_addr_t pgtable)
 {
+	unsigned int prrr, nmrr;
 	__reset_context(base, ctx);
 
 	/* Set up HTW mode */
@@ -127,11 +143,11 @@ static void __program_context(void __iom
 	/* Turn on TEX Remap */
 	SET_TRE(base, ctx, 1);
 
-	/* Do not configure PRRR / NMRR on the IOMMU for now. We will assume
-	 * TEX class 0 for everything until attributes are properly worked out
-	 */
-	SET_PRRR(base, ctx, 0);
-	SET_NMRR(base, ctx, 0);
+	/* Set TEX remap attributes */
+	RCP15_PRRR(prrr);
+	RCP15_NMRR(nmrr);
+	SET_PRRR(base, ctx, prrr);
+	SET_NMRR(base, ctx, nmrr);
 
 	/* Turn on BFB prefetch */
 	SET_BFBDFE(base, ctx, 1);
@@ -238,6 +254,11 @@ static int msm_iommu_attach_dev(struct i
 		goto fail;
 	}
 
+	if (!list_empty(&ctx_drvdata->attached_elm)) {
+		ret = -EBUSY;
+		goto fail;
+	}
+
 	list_for_each_entry(tmp_drvdata, &priv->list_attached, attached_elm)
 		if (tmp_drvdata == ctx_drvdata) {
 			ret = -EBUSY;
@@ -248,7 +269,7 @@ static int msm_iommu_attach_dev(struct i
 			  __pa(priv->pgtable));
 
 	list_add(&(ctx_drvdata->attached_elm), &priv->list_attached);
-	__flush_iotlb(domain);
+	ret = __flush_iotlb(domain);
 
 fail:
 	spin_unlock_irqrestore(&msm_iommu_lock, flags);
@@ -263,6 +284,7 @@ static void msm_iommu_detach_dev(struct
 	struct msm_iommu_drvdata *iommu_drvdata;
 	struct msm_iommu_ctx_drvdata *ctx_drvdata;
 	unsigned long flags;
+	int ret;
 
 	spin_lock_irqsave(&msm_iommu_lock, flags);
 	priv = domain->priv;
@@ -277,7 +299,10 @@ static void msm_iommu_detach_dev(struct
 	if (!iommu_drvdata || !ctx_drvdata || !ctx_dev)
 		goto fail;
 
-	__flush_iotlb(domain);
+	ret = __flush_iotlb(domain);
+	if (ret)
+		goto fail;
+
 	__reset_context(iommu_drvdata->base, ctx_dev->num);
 	list_del_init(&ctx_drvdata->attached_elm);
 
@@ -296,12 +321,21 @@ static int msm_iommu_map(struct iommu_do
 	unsigned long *sl_table;
 	unsigned long *sl_pte;
 	unsigned long sl_offset;
+	unsigned int pgprot;
 	size_t len = 0x1000UL << order;
-	int ret = 0;
+	int ret = 0, tex, sh;
 
 	spin_lock_irqsave(&msm_iommu_lock, flags);
-	priv = domain->priv;
 
+	sh = (prot & MSM_IOMMU_ATTR_SH) ? 1 : 0;
+	tex = msm_iommu_tex_class[prot & MSM_IOMMU_CP_MASK];
+
+	if (tex < 0 || tex > NUM_TEX_CLASS - 1) {
+		ret = -EINVAL;
+		goto fail;
+	}
+
+	priv = domain->priv;
 	if (!priv) {
 		ret = -EINVAL;
 		goto fail;
@@ -322,6 +356,18 @@ static int msm_iommu_map(struct iommu_do
 		goto fail;
 	}
 
+	if (len == SZ_16M || len == SZ_1M) {
+		pgprot = sh ? FL_SHARED : 0;
+		pgprot |= tex & 0x01 ? FL_BUFFERABLE : 0;
+		pgprot |= tex & 0x02 ? FL_CACHEABLE : 0;
+		pgprot |= tex & 0x04 ? FL_TEX0 : 0;
+	} else	{
+		pgprot = sh ? SL_SHARED : 0;
+		pgprot |= tex & 0x01 ? SL_BUFFERABLE : 0;
+		pgprot |= tex & 0x02 ? SL_CACHEABLE : 0;
+		pgprot |= tex & 0x04 ? SL_TEX0 : 0;
+	}
+
 	fl_offset = FL_OFFSET(va);	/* Upper 12 bits */
 	fl_pte = fl_table + fl_offset;	/* int pointers, 4 bytes */
 
@@ -330,17 +376,17 @@ static int msm_iommu_map(struct iommu_do
 		for (i = 0; i < 16; i++)
 			*(fl_pte+i) = (pa & 0xFF000000) | FL_SUPERSECTION |
 				  FL_AP_READ | FL_AP_WRITE | FL_TYPE_SECT |
-				  FL_SHARED;
+				  FL_SHARED | pgprot;
 	}
 
 	if (len == SZ_1M)
 		*fl_pte = (pa & 0xFFF00000) | FL_AP_READ | FL_AP_WRITE |
-						FL_TYPE_SECT | FL_SHARED;
+					    FL_TYPE_SECT | FL_SHARED | pgprot;
 
 	/* Need a 2nd level table */
 	if ((len == SZ_4K || len == SZ_64K) && (*fl_pte) == 0) {
 		unsigned long *sl;
-		sl = (unsigned long *) __get_free_pages(GFP_KERNEL,
+		sl = (unsigned long *) __get_free_pages(GFP_ATOMIC,
 							get_order(SZ_4K));
 
 		if (!sl) {
@@ -360,17 +406,17 @@ static int msm_iommu_map(struct iommu_do
 
 	if (len == SZ_4K)
 		*sl_pte = (pa & SL_BASE_MASK_SMALL) | SL_AP0 | SL_AP1 |
-					  SL_SHARED | SL_TYPE_SMALL;
+					  SL_SHARED | SL_TYPE_SMALL | pgprot;
 
 	if (len == SZ_64K) {
 		int i;
 
 		for (i = 0; i < 16; i++)
 			*(sl_pte+i) = (pa & SL_BASE_MASK_LARGE) | SL_AP0 |
-					    SL_AP1 | SL_SHARED | SL_TYPE_LARGE;
+				SL_AP1 | SL_SHARED | SL_TYPE_LARGE | pgprot;
 	}
 
-	__flush_iotlb(domain);
+	ret = __flush_iotlb(domain);
 fail:
 	spin_unlock_irqrestore(&msm_iommu_lock, flags);
 	return ret;
@@ -455,7 +501,7 @@ static int msm_iommu_unmap(struct iommu_
 		}
 	}
 
-	__flush_iotlb(domain);
+	ret = __flush_iotlb(domain);
 fail:
 	spin_unlock_irqrestore(&msm_iommu_lock, flags);
 	return ret;
@@ -490,9 +536,6 @@ static phys_addr_t msm_iommu_iova_to_phy
 	SET_CTX_TLBIALL(base, ctx, 0);
 	SET_V2PPR_VA(base, ctx, va >> V2Pxx_VA_SHIFT);
 
-	if (GET_FAULT(base, ctx))
-		goto fail;
-
 	par = GET_PAR(base, ctx);
 
 	/* We are dealing with a supersection */
@@ -501,6 +544,9 @@ static phys_addr_t msm_iommu_iova_to_phy
 	else	/* Upper 20 bits from PAR, lower 12 from VA */
 		ret = (par & 0xFFFFF000) | (va & 0x00000FFF);
 
+	if (GET_FAULT(base, ctx))
+		ret = 0;
+
 fail:
 	spin_unlock_irqrestore(&msm_iommu_lock, flags);
 	return ret;
@@ -543,8 +589,8 @@ irqreturn_t msm_iommu_fault_handler(int
 {
 	struct msm_iommu_drvdata *drvdata = dev_id;
 	void __iomem *base;
-	unsigned int fsr = 0;
-	int ncb = 0, i = 0;
+	unsigned int fsr;
+	int ncb, i;
 
 	spin_lock(&msm_iommu_lock);
 
@@ -555,7 +601,6 @@ irqreturn_t msm_iommu_fault_handler(int
 
 	base = drvdata->base;
 
-	pr_err("===== WOAH! =====\n");
 	pr_err("Unexpected IOMMU page fault!\n");
 	pr_err("base = %08x\n", (unsigned int) base);
 
@@ -585,8 +630,47 @@ static struct iommu_ops msm_iommu_ops =
 	.domain_has_cap = msm_iommu_domain_has_cap
 };
 
-static int msm_iommu_init(void)
+static int __init get_tex_class(int icp, int ocp, int mt, int nos)
 {
+	int i = 0;
+	unsigned int prrr = 0;
+	unsigned int nmrr = 0;
+	int c_icp, c_ocp, c_mt, c_nos;
+
+	RCP15_PRRR(prrr);
+	RCP15_NMRR(nmrr);
+
+	for (i = 0; i < NUM_TEX_CLASS; i++) {
+		c_nos = PRRR_NOS(prrr, i);
+		c_mt = PRRR_MT(prrr, i);
+		c_icp = NMRR_ICP(nmrr, i);
+		c_ocp = NMRR_OCP(nmrr, i);
+
+		if (icp == c_icp && ocp == c_ocp && c_mt == mt && c_nos == nos)
+			return i;
+	}
+
+	return -ENODEV;
+}
+
+static void __init setup_iommu_tex_classes(void)
+{
+	msm_iommu_tex_class[MSM_IOMMU_ATTR_NONCACHED] =
+			get_tex_class(CP_NONCACHED, CP_NONCACHED, MT_NORMAL, 1);
+
+	msm_iommu_tex_class[MSM_IOMMU_ATTR_CACHED_WB_WA] =
+			get_tex_class(CP_WB_WA, CP_WB_WA, MT_NORMAL, 1);
+
+	msm_iommu_tex_class[MSM_IOMMU_ATTR_CACHED_WB_NWA] =
+			get_tex_class(CP_WB_NWA, CP_WB_NWA, MT_NORMAL, 1);
+
+	msm_iommu_tex_class[MSM_IOMMU_ATTR_CACHED_WT] =
+			get_tex_class(CP_WT, CP_WT, MT_NORMAL, 1);
+}
+
+static int __init msm_iommu_init(void)
+{
+	setup_iommu_tex_classes();
 	register_iommu(&msm_iommu_ops);
 	return 0;
 }
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-msm/iommu_dev.c linux-libre-2.6.38-gnu1/arch/arm/mach-msm/iommu_dev.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-msm/iommu_dev.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-msm/iommu_dev.c	2011-03-14 21:20:32.000000000 -0400
@@ -346,7 +346,7 @@ static struct platform_driver msm_iommu_
 	.remove		= msm_iommu_ctx_remove,
 };
 
-static int msm_iommu_driver_init(void)
+static int __init msm_iommu_driver_init(void)
 {
 	int ret;
 	ret = platform_driver_register(&msm_iommu_driver);
@@ -365,7 +365,7 @@ error:
 	return ret;
 }
 
-static void msm_iommu_driver_exit(void)
+static void __exit msm_iommu_driver_exit(void)
 {
 	platform_driver_unregister(&msm_iommu_ctx_driver);
 	platform_driver_unregister(&msm_iommu_driver);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-msm/irq.c linux-libre-2.6.38-gnu1/arch/arm/mach-msm/irq.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-msm/irq.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-msm/irq.c	2011-03-14 21:20:32.000000000 -0400
@@ -64,35 +64,34 @@
 #define VIC_VECTPRIORITY(n) VIC_REG(0x0200+((n) * 4))
 #define VIC_VECTADDR(n)     VIC_REG(0x0400+((n) * 4))
 
-static void msm_irq_ack(unsigned int irq)
+static void msm_irq_ack(struct irq_data *d)
 {
-	void __iomem *reg = VIC_INT_CLEAR0 + ((irq & 32) ? 4 : 0);
-	irq = 1 << (irq & 31);
-	writel(irq, reg);
+	void __iomem *reg = VIC_INT_CLEAR0 + ((d->irq & 32) ? 4 : 0);
+	writel(1 << (d->irq & 31), reg);
 }
 
-static void msm_irq_mask(unsigned int irq)
+static void msm_irq_mask(struct irq_data *d)
 {
-	void __iomem *reg = VIC_INT_ENCLEAR0 + ((irq & 32) ? 4 : 0);
-	writel(1 << (irq & 31), reg);
+	void __iomem *reg = VIC_INT_ENCLEAR0 + ((d->irq & 32) ? 4 : 0);
+	writel(1 << (d->irq & 31), reg);
 }
 
-static void msm_irq_unmask(unsigned int irq)
+static void msm_irq_unmask(struct irq_data *d)
 {
-	void __iomem *reg = VIC_INT_ENSET0 + ((irq & 32) ? 4 : 0);
-	writel(1 << (irq & 31), reg);
+	void __iomem *reg = VIC_INT_ENSET0 + ((d->irq & 32) ? 4 : 0);
+	writel(1 << (d->irq & 31), reg);
 }
 
-static int msm_irq_set_wake(unsigned int irq, unsigned int on)
+static int msm_irq_set_wake(struct irq_data *d, unsigned int on)
 {
 	return -EINVAL;
 }
 
-static int msm_irq_set_type(unsigned int irq, unsigned int flow_type)
+static int msm_irq_set_type(struct irq_data *d, unsigned int flow_type)
 {
-	void __iomem *treg = VIC_INT_TYPE0 + ((irq & 32) ? 4 : 0);
-	void __iomem *preg = VIC_INT_POLARITY0 + ((irq & 32) ? 4 : 0);
-	int b = 1 << (irq & 31);
+	void __iomem *treg = VIC_INT_TYPE0 + ((d->irq & 32) ? 4 : 0);
+	void __iomem *preg = VIC_INT_POLARITY0 + ((d->irq & 32) ? 4 : 0);
+	int b = 1 << (d->irq & 31);
 
 	if (flow_type & (IRQF_TRIGGER_FALLING | IRQF_TRIGGER_LOW))
 		writel(readl(preg) | b, preg);
@@ -101,22 +100,22 @@ static int msm_irq_set_type(unsigned int
 
 	if (flow_type & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)) {
 		writel(readl(treg) | b, treg);
-		irq_desc[irq].handle_irq = handle_edge_irq;
+		irq_desc[d->irq].handle_irq = handle_edge_irq;
 	}
 	if (flow_type & (IRQF_TRIGGER_HIGH | IRQF_TRIGGER_LOW)) {
 		writel(readl(treg) & (~b), treg);
-		irq_desc[irq].handle_irq = handle_level_irq;
+		irq_desc[d->irq].handle_irq = handle_level_irq;
 	}
 	return 0;
 }
 
 static struct irq_chip msm_irq_chip = {
-	.name      = "msm",
-	.ack       = msm_irq_ack,
-	.mask      = msm_irq_mask,
-	.unmask    = msm_irq_unmask,
-	.set_wake  = msm_irq_set_wake,
-	.set_type  = msm_irq_set_type,
+	.name          = "msm",
+	.irq_ack       = msm_irq_ack,
+	.irq_mask      = msm_irq_mask,
+	.irq_unmask    = msm_irq_unmask,
+	.irq_set_wake  = msm_irq_set_wake,
+	.irq_set_type  = msm_irq_set_type,
 };
 
 void __init msm_init_irq(void)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-msm/irq-vic.c linux-libre-2.6.38-gnu1/arch/arm/mach-msm/irq-vic.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-msm/irq-vic.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-msm/irq-vic.c	2011-03-14 21:20:32.000000000 -0400
@@ -226,19 +226,18 @@ static inline void msm_irq_write_all_reg
 		writel(val, base + (i * 4));
 }
 
-static void msm_irq_ack(unsigned int irq)
+static void msm_irq_ack(struct irq_data *d)
 {
-	void __iomem *reg = VIC_INT_TO_REG_ADDR(VIC_INT_CLEAR0, irq);
-	irq = 1 << (irq & 31);
-	writel(irq, reg);
+	void __iomem *reg = VIC_INT_TO_REG_ADDR(VIC_INT_CLEAR0, d->irq);
+	writel(1 << (d->irq & 31), reg);
 }
 
-static void msm_irq_mask(unsigned int irq)
+static void msm_irq_mask(struct irq_data *d)
 {
-	void __iomem *reg = VIC_INT_TO_REG_ADDR(VIC_INT_ENCLEAR0, irq);
-	unsigned index = VIC_INT_TO_REG_INDEX(irq);
-	uint32_t mask = 1UL << (irq & 31);
-	int smsm_irq = msm_irq_to_smsm[irq];
+	void __iomem *reg = VIC_INT_TO_REG_ADDR(VIC_INT_ENCLEAR0, d->irq);
+	unsigned index = VIC_INT_TO_REG_INDEX(d->irq);
+	uint32_t mask = 1UL << (d->irq & 31);
+	int smsm_irq = msm_irq_to_smsm[d->irq];
 
 	msm_irq_shadow_reg[index].int_en[0] &= ~mask;
 	writel(mask, reg);
@@ -250,12 +249,12 @@ static void msm_irq_mask(unsigned int ir
 	}
 }
 
-static void msm_irq_unmask(unsigned int irq)
+static void msm_irq_unmask(struct irq_data *d)
 {
-	void __iomem *reg = VIC_INT_TO_REG_ADDR(VIC_INT_ENSET0, irq);
-	unsigned index = VIC_INT_TO_REG_INDEX(irq);
-	uint32_t mask = 1UL << (irq & 31);
-	int smsm_irq = msm_irq_to_smsm[irq];
+	void __iomem *reg = VIC_INT_TO_REG_ADDR(VIC_INT_ENSET0, d->irq);
+	unsigned index = VIC_INT_TO_REG_INDEX(d->irq);
+	uint32_t mask = 1UL << (d->irq & 31);
+	int smsm_irq = msm_irq_to_smsm[d->irq];
 
 	msm_irq_shadow_reg[index].int_en[0] |= mask;
 	writel(mask, reg);
@@ -268,14 +267,14 @@ static void msm_irq_unmask(unsigned int
 	}
 }
 
-static int msm_irq_set_wake(unsigned int irq, unsigned int on)
+static int msm_irq_set_wake(struct irq_data *d, unsigned int on)
 {
-	unsigned index = VIC_INT_TO_REG_INDEX(irq);
-	uint32_t mask = 1UL << (irq & 31);
-	int smsm_irq = msm_irq_to_smsm[irq];
+	unsigned index = VIC_INT_TO_REG_INDEX(d->irq);
+	uint32_t mask = 1UL << (d->irq & 31);
+	int smsm_irq = msm_irq_to_smsm[d->irq];
 
 	if (smsm_irq == 0) {
-		printk(KERN_ERR "msm_irq_set_wake: bad wakeup irq %d\n", irq);
+		printk(KERN_ERR "msm_irq_set_wake: bad wakeup irq %d\n", d->irq);
 		return -EINVAL;
 	}
 	if (on)
@@ -294,12 +293,12 @@ static int msm_irq_set_wake(unsigned int
 	return 0;
 }
 
-static int msm_irq_set_type(unsigned int irq, unsigned int flow_type)
+static int msm_irq_set_type(struct irq_data *d, unsigned int flow_type)
 {
-	void __iomem *treg = VIC_INT_TO_REG_ADDR(VIC_INT_TYPE0, irq);
-	void __iomem *preg = VIC_INT_TO_REG_ADDR(VIC_INT_POLARITY0, irq);
-	unsigned index = VIC_INT_TO_REG_INDEX(irq);
-	int b = 1 << (irq & 31);
+	void __iomem *treg = VIC_INT_TO_REG_ADDR(VIC_INT_TYPE0, d->irq);
+	void __iomem *preg = VIC_INT_TO_REG_ADDR(VIC_INT_POLARITY0, d->irq);
+	unsigned index = VIC_INT_TO_REG_INDEX(d->irq);
+	int b = 1 << (d->irq & 31);
 	uint32_t polarity;
 	uint32_t type;
 
@@ -314,11 +313,11 @@ static int msm_irq_set_type(unsigned int
 	type = msm_irq_shadow_reg[index].int_type;
 	if (flow_type & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)) {
 		type |= b;
-		irq_desc[irq].handle_irq = handle_edge_irq;
+		irq_desc[d->irq].handle_irq = handle_edge_irq;
 	}
 	if (flow_type & (IRQF_TRIGGER_HIGH | IRQF_TRIGGER_LOW)) {
 		type &= ~b;
-		irq_desc[irq].handle_irq = handle_level_irq;
+		irq_desc[d->irq].handle_irq = handle_level_irq;
 	}
 	writel(type, treg);
 	msm_irq_shadow_reg[index].int_type = type;
@@ -326,13 +325,13 @@ static int msm_irq_set_type(unsigned int
 }
 
 static struct irq_chip msm_irq_chip = {
-	.name      = "msm",
-	.disable   = msm_irq_mask,
-	.ack       = msm_irq_ack,
-	.mask      = msm_irq_mask,
-	.unmask    = msm_irq_unmask,
-	.set_wake  = msm_irq_set_wake,
-	.set_type  = msm_irq_set_type,
+	.name          = "msm",
+	.irq_disable   = msm_irq_mask,
+	.irq_ack       = msm_irq_ack,
+	.irq_mask      = msm_irq_mask,
+	.irq_unmask    = msm_irq_unmask,
+	.irq_set_wake  = msm_irq_set_wake,
+	.irq_set_type  = msm_irq_set_type,
 };
 
 void __init msm_init_irq(void)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-msm/Kconfig linux-libre-2.6.38-gnu1/arch/arm/mach-msm/Kconfig
--- linux-libre-2.6.37-gnu1/arch/arm/mach-msm/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-msm/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -40,15 +40,20 @@ config ARCH_MSM8X60
 	bool "MSM8X60"
 	select MACH_MSM8X60_SURF if (!MACH_MSM8X60_RUMI3 && !MACH_MSM8X60_SIM \
 				  && !MACH_MSM8X60_FFA)
+	select ARCH_MSM_SCORPIONMP
 	select ARM_GIC
 	select CPU_V7
 	select MSM_V2_TLMM
 	select MSM_GPIOMUX
+	select IOMMU_API
+	select MSM_SCM if SMP
 
 endchoice
 
 config MSM_SOC_REV_A
 	bool
+config  ARCH_MSM_SCORPIONMP
+	bool
 
 config  ARCH_MSM_ARM11
 	bool
@@ -122,6 +127,10 @@ config MACH_MSM8X60_FFA
 
 endmenu
 
+config IOMMU_PGTABLES_L2
+	def_bool y
+	depends on ARCH_MSM8X60 && MMU && SMP && CPU_DCACHE_DISABLE=n
+
 config MSM_DEBUG_UART
 	int
 	default 1 if MSM_DEBUG_UART1
@@ -162,4 +171,10 @@ config MSM_GPIOMUX
 
 config MSM_V2_TLMM
 	bool
+
+config IOMMU_API
+	bool
+
+config MSM_SCM
+	bool
 endif
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-msm/Makefile linux-libre-2.6.38-gnu1/arch/arm/mach-msm/Makefile
--- linux-libre-2.6.37-gnu1/arch/arm/mach-msm/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-msm/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -18,8 +18,13 @@ obj-$(CONFIG_MSM_PROC_COMM) += clock.o
 obj-$(CONFIG_ARCH_QSD8X50) += sirc.o
 obj-$(CONFIG_MSM_SMD) += smd.o smd_debug.o
 obj-$(CONFIG_MSM_SMD) += last_radio_log.o
+obj-$(CONFIG_MSM_SCM) += scm.o scm-boot.o
+
+obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
+obj-$(CONFIG_SMP) += headsmp.o platsmp.o
 
 obj-$(CONFIG_MACH_TROUT) += board-trout.o board-trout-gpio.o board-trout-mmc.o devices-msm7x00.o
+obj-$(CONFIG_MACH_TROUT) += board-trout.o board-trout-gpio.o board-trout-mmc.o board-trout-panel.o devices-msm7x00.o
 obj-$(CONFIG_MACH_HALIBUT) += board-halibut.o devices-msm7x00.o
 obj-$(CONFIG_ARCH_MSM7X30) += board-msm7x30.o devices-msm7x30.o
 obj-$(CONFIG_ARCH_QSD8X50) += board-qsd8x50.o devices-qsd8x50.o
@@ -28,6 +33,8 @@ obj-$(CONFIG_ARCH_MSM8X60) += board-msm8
 obj-$(CONFIG_ARCH_MSM7X30) += gpiomux-7x30.o gpiomux-v1.o gpiomux.o
 obj-$(CONFIG_ARCH_QSD8X50) += gpiomux-8x50.o gpiomux-v1.o gpiomux.o
 obj-$(CONFIG_ARCH_MSM8X60) += gpiomux-8x60.o gpiomux-v2.o gpiomux.o
-ifndef CONFIG_MSM_V2_TLMM
+ifdef CONFIG_MSM_V2_TLMM
+obj-y	+= gpio-v2.o
+else
 obj-y	+= gpio.o
 endif
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-msm/platsmp.c linux-libre-2.6.38-gnu1/arch/arm/mach-msm/platsmp.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-msm/platsmp.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-msm/platsmp.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,166 @@
+/*
+ *  Copyright (C) 2002 ARM Ltd.
+ *  All Rights Reserved
+ *  Copyright (c) 2010, 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 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/hardware/gic.h>
+#include <asm/cacheflush.h>
+#include <asm/mach-types.h>
+
+#include <mach/msm_iomap.h>
+
+#include "scm-boot.h"
+
+#define VDD_SC1_ARRAY_CLAMP_GFS_CTL 0x15A0
+#define SCSS_CPU1CORE_RESET 0xD80
+#define SCSS_DBG_STATUS_CORE_PWRDUP 0xE64
+
+/* Mask for edge trigger PPIs except AVS_SVICINT and AVS_SVICINTSWDONE */
+#define GIC_PPI_EDGE_MASK 0xFFFFD7FF
+
+extern void msm_secondary_startup(void);
+/*
+ * control for which core is the next to come out of the secondary
+ * boot "holding pen".
+ */
+volatile int pen_release = -1;
+
+static DEFINE_SPINLOCK(boot_lock);
+
+void __cpuinit platform_secondary_init(unsigned int cpu)
+{
+	/* Configure edge-triggered PPIs */
+	writel(GIC_PPI_EDGE_MASK, MSM_QGIC_DIST_BASE + GIC_DIST_CONFIG + 4);
+
+	/*
+	 * 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);
+
+	/*
+	 * let the primary processor know we're out of the
+	 * pen, then head off into the C entry point
+	 */
+	pen_release = -1;
+	smp_wmb();
+
+	/*
+	 * Synchronise with the boot thread.
+	 */
+	spin_lock(&boot_lock);
+	spin_unlock(&boot_lock);
+}
+
+static __cpuinit void prepare_cold_cpu(unsigned int cpu)
+{
+	int ret;
+	ret = scm_set_boot_addr(virt_to_phys(msm_secondary_startup),
+				SCM_FLAG_COLDBOOT_CPU1);
+	if (ret == 0) {
+		void *sc1_base_ptr;
+		sc1_base_ptr = ioremap_nocache(0x00902000, SZ_4K*2);
+		if (sc1_base_ptr) {
+			writel(0, sc1_base_ptr + VDD_SC1_ARRAY_CLAMP_GFS_CTL);
+			writel(0, sc1_base_ptr + SCSS_CPU1CORE_RESET);
+			writel(3, sc1_base_ptr + SCSS_DBG_STATUS_CORE_PWRDUP);
+			iounmap(sc1_base_ptr);
+		}
+	} else
+		printk(KERN_DEBUG "Failed to set secondary core boot "
+				  "address\n");
+}
+
+int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
+{
+	unsigned long timeout;
+	static int cold_boot_done;
+
+	/* Only need to bring cpu out of reset this way once */
+	if (cold_boot_done == false) {
+		prepare_cold_cpu(cpu);
+		cold_boot_done = true;
+	}
+
+	/*
+	 * 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.
+	 */
+	pen_release = cpu;
+	__cpuc_flush_dcache_area((void *)&pen_release, sizeof(pen_release));
+	outer_clean_range(__pa(&pen_release), __pa(&pen_release + 1));
+
+	/*
+	 * 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.
+	 */
+	smp_cross_call(cpumask_of(cpu), 1);
+
+	timeout = jiffies + (1 * HZ);
+	while (time_before(jiffies, timeout)) {
+		smp_rmb();
+		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. The msm8x60
+ * does not support the ARM SCU, so just set the possible cpu mask to
+ * NR_CPUS.
+ */
+void __init smp_init_cpus(void)
+{
+	unsigned int i;
+
+	for (i = 0; i < NR_CPUS; i++)
+		set_cpu_possible(i, true);
+}
+
+void __init platform_smp_prepare_cpus(unsigned int max_cpus)
+{
+	int i;
+
+	/*
+	 * Initialise the present map, which describes the set of CPUs
+	 * actually populated at the present time.
+	 */
+	for (i = 0; i < max_cpus; i++)
+		set_cpu_present(i, true);
+}
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-msm/scm-boot.c linux-libre-2.6.38-gnu1/arch/arm/mach-msm/scm-boot.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-msm/scm-boot.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-msm/scm-boot.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,39 @@
+/* Copyright (c) 2010, 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/module.h>
+#include <linux/slab.h>
+
+#include "scm.h"
+#include "scm-boot.h"
+
+/*
+ * Set the cold/warm boot address for one of the CPU cores.
+ */
+int scm_set_boot_addr(phys_addr_t addr, int flags)
+{
+	struct {
+		unsigned int flags;
+		phys_addr_t  addr;
+	} cmd;
+
+	cmd.addr = addr;
+	cmd.flags = flags;
+	return scm_call(SCM_SVC_BOOT, SCM_BOOT_ADDR,
+			&cmd, sizeof(cmd), NULL, 0);
+}
+EXPORT_SYMBOL(scm_set_boot_addr);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-msm/scm-boot.h linux-libre-2.6.38-gnu1/arch/arm/mach-msm/scm-boot.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-msm/scm-boot.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-msm/scm-boot.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,38 @@
+/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ *
+ * 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 Code Aurora Forum, Inc. nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * 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.
+ */
+#ifndef __MACH_SCM_BOOT_H
+#define __MACH_SCM_BOOT_H
+
+#define SCM_BOOT_ADDR			0x1
+#define SCM_FLAG_COLDBOOT_CPU1		0x1
+#define SCM_FLAG_WARMBOOT_CPU1		0x2
+#define SCM_FLAG_WARMBOOT_CPU0		0x4
+
+int scm_set_boot_addr(phys_addr_t addr, int flags);
+
+#endif
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-msm/scm.c linux-libre-2.6.38-gnu1/arch/arm/mach-msm/scm.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-msm/scm.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-msm/scm.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,287 @@
+/* Copyright (c) 2010, 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/slab.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+
+#include <asm/cacheflush.h>
+
+#include "scm.h"
+
+/* Cache line size for msm8x60 */
+#define CACHELINESIZE 32
+
+#define SCM_ENOMEM		-5
+#define SCM_EOPNOTSUPP		-4
+#define SCM_EINVAL_ADDR		-3
+#define SCM_EINVAL_ARG		-2
+#define SCM_ERROR		-1
+#define SCM_INTERRUPTED		1
+
+static DEFINE_MUTEX(scm_lock);
+
+/**
+ * struct scm_command - one SCM command buffer
+ * @len: total available memory for command and response
+ * @buf_offset: start of command buffer
+ * @resp_hdr_offset: start of response buffer
+ * @id: command to be executed
+ * @buf: buffer returned from scm_get_command_buffer()
+ *
+ * An SCM command is layed out in memory as follows:
+ *
+ *	------------------- <--- struct scm_command
+ *	| command header  |
+ *	------------------- <--- scm_get_command_buffer()
+ *	| command buffer  |
+ *	------------------- <--- struct scm_response and
+ *	| response header |      scm_command_to_response()
+ *	------------------- <--- scm_get_response_buffer()
+ *	| response buffer |
+ *	-------------------
+ *
+ * There can be arbitrary padding between the headers and buffers so
+ * you should always use the appropriate scm_get_*_buffer() routines
+ * to access the buffers in a safe manner.
+ */
+struct scm_command {
+	u32	len;
+	u32	buf_offset;
+	u32	resp_hdr_offset;
+	u32	id;
+	u32	buf[0];
+};
+
+/**
+ * struct scm_response - one SCM response buffer
+ * @len: total available memory for response
+ * @buf_offset: start of response data relative to start of scm_response
+ * @is_complete: indicates if the command has finished processing
+ */
+struct scm_response {
+	u32	len;
+	u32	buf_offset;
+	u32	is_complete;
+};
+
+/**
+ * alloc_scm_command() - Allocate an SCM command
+ * @cmd_size: size of the command buffer
+ * @resp_size: size of the response buffer
+ *
+ * Allocate an SCM command, including enough room for the command
+ * and response headers as well as the command and response buffers.
+ *
+ * Returns a valid &scm_command on success or %NULL if the allocation fails.
+ */
+static struct scm_command *alloc_scm_command(size_t cmd_size, size_t resp_size)
+{
+	struct scm_command *cmd;
+	size_t len = sizeof(*cmd) + sizeof(struct scm_response) + cmd_size +
+		resp_size;
+
+	cmd = kzalloc(PAGE_ALIGN(len), GFP_KERNEL);
+	if (cmd) {
+		cmd->len = len;
+		cmd->buf_offset = offsetof(struct scm_command, buf);
+		cmd->resp_hdr_offset = cmd->buf_offset + cmd_size;
+	}
+	return cmd;
+}
+
+/**
+ * free_scm_command() - Free an SCM command
+ * @cmd: command to free
+ *
+ * Free an SCM command.
+ */
+static inline void free_scm_command(struct scm_command *cmd)
+{
+	kfree(cmd);
+}
+
+/**
+ * scm_command_to_response() - Get a pointer to a scm_response
+ * @cmd: command
+ *
+ * Returns a pointer to a response for a command.
+ */
+static inline struct scm_response *scm_command_to_response(
+		const struct scm_command *cmd)
+{
+	return (void *)cmd + cmd->resp_hdr_offset;
+}
+
+/**
+ * scm_get_command_buffer() - Get a pointer to a command buffer
+ * @cmd: command
+ *
+ * Returns a pointer to the command buffer of a command.
+ */
+static inline void *scm_get_command_buffer(const struct scm_command *cmd)
+{
+	return (void *)cmd->buf;
+}
+
+/**
+ * scm_get_response_buffer() - Get a pointer to a response buffer
+ * @rsp: response
+ *
+ * Returns a pointer to a response buffer of a response.
+ */
+static inline void *scm_get_response_buffer(const struct scm_response *rsp)
+{
+	return (void *)rsp + rsp->buf_offset;
+}
+
+static int scm_remap_error(int err)
+{
+	switch (err) {
+	case SCM_ERROR:
+		return -EIO;
+	case SCM_EINVAL_ADDR:
+	case SCM_EINVAL_ARG:
+		return -EINVAL;
+	case SCM_EOPNOTSUPP:
+		return -EOPNOTSUPP;
+	case SCM_ENOMEM:
+		return -ENOMEM;
+	}
+	return -EINVAL;
+}
+
+static u32 smc(u32 cmd_addr)
+{
+	int context_id;
+	register u32 r0 asm("r0") = 1;
+	register u32 r1 asm("r1") = (u32)&context_id;
+	register u32 r2 asm("r2") = cmd_addr;
+	asm(
+		__asmeq("%0", "r0")
+		__asmeq("%1", "r0")
+		__asmeq("%2", "r1")
+		__asmeq("%3", "r2")
+		"smc	#0	@ switch to secure world\n"
+		: "=r" (r0)
+		: "r" (r0), "r" (r1), "r" (r2)
+		: "r3");
+	return r0;
+}
+
+static int __scm_call(const struct scm_command *cmd)
+{
+	int ret;
+	u32 cmd_addr = virt_to_phys(cmd);
+
+	/*
+	 * Flush the entire cache here so callers don't have to remember
+	 * to flush the cache when passing physical addresses to the secure
+	 * side in the buffer.
+	 */
+	flush_cache_all();
+	do {
+		ret = smc(cmd_addr);
+		if (ret < 0) {
+			ret = scm_remap_error(ret);
+			break;
+		}
+	} while (ret == SCM_INTERRUPTED);
+
+	return ret;
+}
+
+/**
+ * scm_call() - Send an SCM command
+ * @svc_id: service identifier
+ * @cmd_id: command identifier
+ * @cmd_buf: command buffer
+ * @cmd_len: length of the command buffer
+ * @resp_buf: response buffer
+ * @resp_len: length of the response buffer
+ *
+ * Sends a command to the SCM and waits for the command to finish processing.
+ */
+int scm_call(u32 svc_id, u32 cmd_id, const void *cmd_buf, size_t cmd_len,
+		void *resp_buf, size_t resp_len)
+{
+	int ret;
+	struct scm_command *cmd;
+	struct scm_response *rsp;
+
+	cmd = alloc_scm_command(cmd_len, resp_len);
+	if (!cmd)
+		return -ENOMEM;
+
+	cmd->id = (svc_id << 10) | cmd_id;
+	if (cmd_buf)
+		memcpy(scm_get_command_buffer(cmd), cmd_buf, cmd_len);
+
+	mutex_lock(&scm_lock);
+	ret = __scm_call(cmd);
+	mutex_unlock(&scm_lock);
+	if (ret)
+		goto out;
+
+	rsp = scm_command_to_response(cmd);
+	do {
+		u32 start = (u32)rsp;
+		u32 end = (u32)scm_get_response_buffer(rsp) + resp_len;
+		start &= ~(CACHELINESIZE - 1);
+		while (start < end) {
+			asm ("mcr p15, 0, %0, c7, c6, 1" : : "r" (start)
+			     : "memory");
+			start += CACHELINESIZE;
+		}
+	} while (!rsp->is_complete);
+
+	if (resp_buf)
+		memcpy(resp_buf, scm_get_response_buffer(rsp), resp_len);
+out:
+	free_scm_command(cmd);
+	return ret;
+}
+EXPORT_SYMBOL(scm_call);
+
+u32 scm_get_version(void)
+{
+	int context_id;
+	static u32 version = -1;
+	register u32 r0 asm("r0") = 0x1 << 8;
+	register u32 r1 asm("r1") = (u32)&context_id;
+
+	if (version != -1)
+		return version;
+
+	mutex_lock(&scm_lock);
+	asm(
+		__asmeq("%0", "r1")
+		__asmeq("%1", "r0")
+		__asmeq("%2", "r1")
+		"smc	#0	@ switch to secure world\n"
+		: "=r" (r1)
+		: "r" (r0), "r" (r1)
+		: "r2", "r3");
+	version = r1;
+	mutex_unlock(&scm_lock);
+
+	return version;
+}
+EXPORT_SYMBOL(scm_get_version);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-msm/scm.h linux-libre-2.6.38-gnu1/arch/arm/mach-msm/scm.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-msm/scm.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-msm/scm.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,41 @@
+/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ *
+ * 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 Code Aurora Forum, Inc. nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * 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.
+ */
+#ifndef __MACH_SCM_H
+#define __MACH_SCM_H
+
+#define SCM_SVC_BOOT			0x1
+#define SCM_SVC_PIL			0x2
+
+extern int scm_call(u32 svc_id, u32 cmd_id, const void *cmd_buf, size_t cmd_len,
+		void *resp_buf, size_t resp_len);
+
+#define SCM_VERSION(major, minor) (((major) << 16) | ((minor) & 0xFF))
+
+extern u32 scm_get_version(void);
+
+#endif
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-msm/sirc.c linux-libre-2.6.38-gnu1/arch/arm/mach-msm/sirc.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-msm/sirc.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-msm/sirc.c	2011-03-14 21:20:32.000000000 -0400
@@ -40,17 +40,13 @@ static struct sirc_cascade_regs sirc_reg
 	}
 };
 
-static unsigned int save_type;
-static unsigned int save_polarity;
-
 /* Mask off the given interrupt. Keep the int_enable mask in sync with
    the enable reg, so it can be restored after power collapse. */
-static void sirc_irq_mask(unsigned int irq)
+static void sirc_irq_mask(struct irq_data *d)
 {
 	unsigned int mask;
 
-
-	mask = 1 << (irq - FIRST_SIRC_IRQ);
+	mask = 1 << (d->irq - FIRST_SIRC_IRQ);
 	writel(mask, sirc_regs.int_enable_clear);
 	int_enable &= ~mask;
 	return;
@@ -58,31 +54,31 @@ static void sirc_irq_mask(unsigned int i
 
 /* Unmask the given interrupt. Keep the int_enable mask in sync with
    the enable reg, so it can be restored after power collapse. */
-static void sirc_irq_unmask(unsigned int irq)
+static void sirc_irq_unmask(struct irq_data *d)
 {
 	unsigned int mask;
 
-	mask = 1 << (irq - FIRST_SIRC_IRQ);
+	mask = 1 << (d->irq - FIRST_SIRC_IRQ);
 	writel(mask, sirc_regs.int_enable_set);
 	int_enable |= mask;
 	return;
 }
 
-static void sirc_irq_ack(unsigned int irq)
+static void sirc_irq_ack(struct irq_data *d)
 {
 	unsigned int mask;
 
-	mask = 1 << (irq - FIRST_SIRC_IRQ);
+	mask = 1 << (d->irq - FIRST_SIRC_IRQ);
 	writel(mask, sirc_regs.int_clear);
 	return;
 }
 
-static int sirc_irq_set_wake(unsigned int irq, unsigned int on)
+static int sirc_irq_set_wake(struct irq_data *d, unsigned int on)
 {
 	unsigned int mask;
 
 	/* Used to set the interrupt enable mask during power collapse. */
-	mask = 1 << (irq - FIRST_SIRC_IRQ);
+	mask = 1 << (d->irq - FIRST_SIRC_IRQ);
 	if (on)
 		wake_enable |= mask;
 	else
@@ -91,12 +87,12 @@ static int sirc_irq_set_wake(unsigned in
 	return 0;
 }
 
-static int sirc_irq_set_type(unsigned int irq, unsigned int flow_type)
+static int sirc_irq_set_type(struct irq_data *d, unsigned int flow_type)
 {
 	unsigned int mask;
 	unsigned int val;
 
-	mask = 1 << (irq - FIRST_SIRC_IRQ);
+	mask = 1 << (d->irq - FIRST_SIRC_IRQ);
 	val = readl(sirc_regs.int_polarity);
 
 	if (flow_type & (IRQF_TRIGGER_LOW | IRQF_TRIGGER_FALLING))
@@ -109,10 +105,10 @@ static int sirc_irq_set_type(unsigned in
 	val = readl(sirc_regs.int_type);
 	if (flow_type & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)) {
 		val |= mask;
-		irq_desc[irq].handle_irq = handle_edge_irq;
+		irq_desc[d->irq].handle_irq = handle_edge_irq;
 	} else {
 		val &= ~mask;
-		irq_desc[irq].handle_irq = handle_level_irq;
+		irq_desc[d->irq].handle_irq = handle_level_irq;
 	}
 
 	writel(val, sirc_regs.int_type);
@@ -142,16 +138,16 @@ static void sirc_irq_handler(unsigned in
 		;
 	generic_handle_irq(sirq+FIRST_SIRC_IRQ);
 
-	desc->chip->ack(irq);
+	desc->irq_data.chip->irq_ack(&desc->irq_data);
 }
 
 static struct irq_chip sirc_irq_chip = {
-	.name      = "sirc",
-	.ack       = sirc_irq_ack,
-	.mask      = sirc_irq_mask,
-	.unmask    = sirc_irq_unmask,
-	.set_wake  = sirc_irq_set_wake,
-	.set_type  = sirc_irq_set_type,
+	.name          = "sirc",
+	.irq_ack       = sirc_irq_ack,
+	.irq_mask      = sirc_irq_mask,
+	.irq_unmask    = sirc_irq_unmask,
+	.irq_set_wake  = sirc_irq_set_wake,
+	.irq_set_type  = sirc_irq_set_type,
 };
 
 void __init msm_init_sirc(void)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-msm/smd.c linux-libre-2.6.38-gnu1/arch/arm/mach-msm/smd.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-msm/smd.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-msm/smd.c	2011-03-14 21:20:32.000000000 -0400
@@ -14,6 +14,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/platform_device.h>
 #include <linux/module.h>
 #include <linux/fs.h>
@@ -89,7 +91,7 @@ static void smd_diag(void)
 	x = smem_find(ID_DIAG_ERR_MSG, SZ_DIAG_ERR_MSG);
 	if (x != 0) {
 		x[SZ_DIAG_ERR_MSG - 1] = 0;
-		pr_info("smem: DIAG '%s'\n", x);
+		pr_debug("DIAG '%s'\n", x);
 	}
 }
 
@@ -312,7 +314,7 @@ static void smd_state_change(struct smd_
 {
 	ch->last_state = next;
 
-	pr_info("SMD: ch %d %d -> %d\n", ch->n, last, next);
+	pr_debug("ch %d %d -> %d\n", ch->n, last, next);
 
 	switch (next) {
 	case SMD_SS_OPENING:
@@ -601,7 +603,7 @@ static int smd_alloc_channel(const char
 	ch->pdev.name = ch->name;
 	ch->pdev.id = -1;
 
-	pr_info("smd_alloc_channel() cid=%02d size=%05d '%s'\n",
+	pr_debug("smd_alloc_channel() cid=%02d size=%05d '%s'\n",
 		ch->n, ch->fifo_size, ch->name);
 
 	mutex_lock(&smd_creation_mutex);
@@ -621,7 +623,7 @@ static void smd_channel_probe_worker(str
 
 	shared = smem_find(ID_CH_ALLOC_TBL, sizeof(*shared) * 64);
 	if (!shared) {
-		pr_err("smd: cannot find allocation table\n");
+		pr_err("cannot find allocation table\n");
 		return;
 	}
 	for (n = 0; n < 64; n++) {
@@ -725,8 +727,6 @@ int smd_close(smd_channel_t *ch)
 {
 	unsigned long flags;
 
-	pr_info("smd_close(%p)\n", ch);
-
 	if (ch == 0)
 		return -1;
 
@@ -939,7 +939,6 @@ int smsm_set_sleep_duration(uint32_t del
 int smd_core_init(void)
 {
 	int r;
-	pr_info("smd_core_init()\n");
 
 	/* wait for essential items to be initialized */
 	for (;;) {
@@ -992,15 +991,11 @@ int smd_core_init(void)
 	smsm_change_state(SMSM_STATE_APPS_DEM, ~0, 0);
 #endif
 
-	pr_info("smd_core_init() done\n");
-
 	return 0;
 }
 
 static int __devinit msm_smd_probe(struct platform_device *pdev)
 {
-	pr_info("smd_init()\n");
-
 	/*
 	 * If we haven't waited for the ARM9 to boot up till now,
 	 * then we need to wait here. Otherwise this should just
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-msm/smd_debug.c linux-libre-2.6.38-gnu1/arch/arm/mach-msm/smd_debug.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-msm/smd_debug.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-msm/smd_debug.c	2011-03-14 21:20:32.000000000 -0400
@@ -270,8 +270,10 @@ void smsm_print_sleep_info(void)
 {
 	unsigned long flags;
 	uint32_t *ptr;
+#ifndef CONFIG_ARCH_MSM_SCORPION
 	struct tramp_gpio_smem *gpio;
 	struct smsm_interrupt_info *int_info;
+#endif
 
 
 	spin_lock_irqsave(&smem_lock, flags);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-msm/timer.c linux-libre-2.6.38-gnu1/arch/arm/mach-msm/timer.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-msm/timer.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-msm/timer.c	2011-03-14 21:20:32.000000000 -0400
@@ -47,6 +47,19 @@ enum {
 
 #define GPT_HZ 32768
 
+enum timer_location {
+	LOCAL_TIMER = 0,
+	GLOBAL_TIMER = 1,
+};
+
+#ifdef MSM_TMR0_BASE
+#define MSM_TMR_GLOBAL		(MSM_TMR0_BASE - MSM_TMR_BASE)
+#else
+#define MSM_TMR_GLOBAL		0
+#endif
+
+#define MSM_GLOBAL_TIMER MSM_CLOCK_DGT
+
 #if defined(CONFIG_ARCH_QSD8X50)
 #define DGT_HZ (19200000 / 4) /* 19.2 MHz / 4 by default */
 #define MSM_DGT_SHIFT (0)
@@ -65,49 +78,67 @@ struct msm_clock {
 	void __iomem                *regbase;
 	uint32_t                    freq;
 	uint32_t                    shift;
+	void __iomem                *global_counter;
+	void __iomem                *local_counter;
 };
 
+enum {
+	MSM_CLOCK_GPT,
+	MSM_CLOCK_DGT,
+	NR_TIMERS,
+};
+
+
+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;
+	if (evt->event_handler == NULL)
+		return IRQ_HANDLED;
 	evt->event_handler(evt);
 	return IRQ_HANDLED;
 }
 
-static cycle_t msm_gpt_read(struct clocksource *cs)
+static cycle_t msm_read_timer_count(struct clocksource *cs)
 {
-	return readl(MSM_GPT_BASE + TIMER_COUNT_VAL);
+	struct msm_clock *clk = container_of(cs, struct msm_clock, clocksource);
+
+	return readl(clk->global_counter);
 }
 
-static cycle_t msm_dgt_read(struct clocksource *cs)
+static struct msm_clock *clockevent_to_clock(struct clock_event_device *evt)
 {
-	return readl(MSM_DGT_BASE + TIMER_COUNT_VAL) >> MSM_DGT_SHIFT;
+#ifdef CONFIG_SMP
+	int i;
+	for (i = 0; i < NR_TIMERS; i++)
+		if (evt == &(msm_clocks[i].clockevent))
+			return &msm_clocks[i];
+	return &msm_clocks[MSM_GLOBAL_TIMER];
+#else
+	return container_of(evt, struct msm_clock, clockevent);
+#endif
 }
 
 static int msm_timer_set_next_event(unsigned long cycles,
 				    struct clock_event_device *evt)
 {
-	struct msm_clock *clock = container_of(evt, struct msm_clock, clockevent);
-	uint32_t now = readl(clock->regbase + TIMER_COUNT_VAL);
+	struct msm_clock *clock = clockevent_to_clock(evt);
+	uint32_t now = readl(clock->local_counter);
 	uint32_t alarm = now + (cycles << clock->shift);
-	int late;
 
 	writel(alarm, clock->regbase + TIMER_MATCH_VAL);
-	now = readl(clock->regbase + TIMER_COUNT_VAL);
-	late = now - alarm;
-	if (late >= (-2 << clock->shift) && late < DGT_HZ*5) {
-		printk(KERN_NOTICE "msm_timer_set_next_event(%lu) clock %s, "
-		       "alarm already expired, now %x, alarm %x, late %d\n",
-		       cycles, clock->clockevent.name, now, alarm, late);
-		return -ETIME;
-	}
 	return 0;
 }
 
 static void msm_timer_set_mode(enum clock_event_mode mode,
 			      struct clock_event_device *evt)
 {
-	struct msm_clock *clock = container_of(evt, struct msm_clock, clockevent);
+	struct msm_clock *clock = clockevent_to_clock(evt);
+
 	switch (mode) {
 	case CLOCK_EVT_MODE_RESUME:
 	case CLOCK_EVT_MODE_PERIODIC:
@@ -123,7 +154,7 @@ static void msm_timer_set_mode(enum cloc
 }
 
 static struct msm_clock msm_clocks[] = {
-	{
+	[MSM_CLOCK_GPT] = {
 		.clockevent = {
 			.name           = "gp_timer",
 			.features       = CLOCK_EVT_FEAT_ONESHOT,
@@ -135,9 +166,8 @@ static struct msm_clock msm_clocks[] = {
 		.clocksource = {
 			.name           = "gp_timer",
 			.rating         = 200,
-			.read           = msm_gpt_read,
+			.read           = msm_read_timer_count,
 			.mask           = CLOCKSOURCE_MASK(32),
-			.shift          = 17,
 			.flags          = CLOCK_SOURCE_IS_CONTINUOUS,
 		},
 		.irq = {
@@ -148,9 +178,12 @@ static struct msm_clock msm_clocks[] = {
 			.irq     = INT_GP_TIMER_EXP
 		},
 		.regbase = MSM_GPT_BASE,
-		.freq = GPT_HZ
+		.freq = GPT_HZ,
+		.local_counter = MSM_GPT_BASE + TIMER_COUNT_VAL,
+		.global_counter = MSM_GPT_BASE + TIMER_COUNT_VAL +
+			MSM_TMR_GLOBAL,
 	},
-	{
+	[MSM_CLOCK_DGT] = {
 		.clockevent = {
 			.name           = "dg_timer",
 			.features       = CLOCK_EVT_FEAT_ONESHOT,
@@ -162,9 +195,8 @@ static struct msm_clock msm_clocks[] = {
 		.clocksource = {
 			.name           = "dg_timer",
 			.rating         = 300,
-			.read           = msm_dgt_read,
+			.read           = msm_read_timer_count,
 			.mask           = CLOCKSOURCE_MASK((32 - MSM_DGT_SHIFT)),
-			.shift          = 24 - MSM_DGT_SHIFT,
 			.flags          = CLOCK_SOURCE_IS_CONTINUOUS,
 		},
 		.irq = {
@@ -176,7 +208,10 @@ static struct msm_clock msm_clocks[] = {
 		},
 		.regbase = MSM_DGT_BASE,
 		.freq = DGT_HZ >> MSM_DGT_SHIFT,
-		.shift = MSM_DGT_SHIFT
+		.shift = MSM_DGT_SHIFT,
+		.local_counter = MSM_DGT_BASE + TIMER_COUNT_VAL,
+		.global_counter = MSM_DGT_BASE + TIMER_COUNT_VAL +
+			MSM_TMR_GLOBAL,
 	}
 };
 
@@ -185,7 +220,7 @@ static void __init msm_timer_init(void)
 	int i;
 	int res;
 
-#ifdef CONFIG_ARCH_MSM8X60
+#ifdef CONFIG_ARCH_MSM_SCORPIONMP
 	writel(DGT_CLK_CTL_DIV_4, MSM_TMR_BASE + DGT_CLK_CTL);
 #endif
 
@@ -205,8 +240,7 @@ static void __init msm_timer_init(void)
 		ce->min_delta_ns = clockevent_delta2ns(4, ce);
 		ce->cpumask = cpumask_of(0);
 
-		cs->mult = clocksource_hz2mult(clock->freq, cs->shift);
-		res = clocksource_register(cs);
+		res = clocksource_register_hz(cs, clock->freq);
 		if (res)
 			printk(KERN_ERR "msm_timer_init: clocksource_register "
 			       "failed for %s\n", cs->name);
@@ -220,6 +254,48 @@ static void __init msm_timer_init(void)
 	}
 }
 
+#ifdef CONFIG_SMP
+void __cpuinit local_timer_setup(struct clock_event_device *evt)
+{
+	struct msm_clock *clock = &msm_clocks[MSM_GLOBAL_TIMER];
+
+	/* Use existing clock_event for cpu 0 */
+	if (!smp_processor_id())
+		return;
+
+	writel(DGT_CLK_CTL_DIV_4, MSM_TMR_BASE + DGT_CLK_CTL);
+
+	if (!local_clock_event) {
+		writel(0, clock->regbase  + TIMER_ENABLE);
+		writel(0, clock->regbase + TIMER_CLEAR);
+		writel(~0, clock->regbase + TIMER_MATCH_VAL);
+	}
+	evt->irq = clock->irq.irq;
+	evt->name = "local_timer";
+	evt->features = CLOCK_EVT_FEAT_ONESHOT;
+	evt->rating = clock->clockevent.rating;
+	evt->set_mode = msm_timer_set_mode;
+	evt->set_next_event = msm_timer_set_next_event;
+	evt->shift = clock->clockevent.shift;
+	evt->mult = div_sc(clock->freq, NSEC_PER_SEC, evt->shift);
+	evt->max_delta_ns =
+		clockevent_delta2ns(0xf0000000 >> clock->shift, evt);
+	evt->min_delta_ns = clockevent_delta2ns(4, evt);
+
+	local_clock_event = evt;
+
+	gic_enable_ppi(clock->irq.irq);
+
+	clockevents_register_device(evt);
+}
+
+inline int local_timer_ack(void)
+{
+	return 1;
+}
+
+#endif
+
 struct sys_timer msm_timer = {
 	.init = msm_timer_init
 };
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mv78xx0/include/mach/mv78xx0.h linux-libre-2.6.38-gnu1/arch/arm/mach-mv78xx0/include/mach/mv78xx0.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mv78xx0/include/mach/mv78xx0.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mv78xx0/include/mach/mv78xx0.h	2011-03-14 21:20:32.000000000 -0400
@@ -65,7 +65,7 @@
  */
 #define DDR_VIRT_BASE		(MV78XX0_REGS_VIRT_BASE | 0x00000)
 #define  DDR_WINDOW_CPU0_BASE	(DDR_VIRT_BASE | 0x1500)
-#define  DDR_WINDOW_CPU1_BASE	(DDR_VIRT_BASE | 0x1700)
+#define  DDR_WINDOW_CPU1_BASE	(DDR_VIRT_BASE | 0x1570)
 
 #define DEV_BUS_PHYS_BASE	(MV78XX0_REGS_PHYS_BASE | 0x10000)
 #define DEV_BUS_VIRT_BASE	(MV78XX0_REGS_VIRT_BASE | 0x10000)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mx25/clock.c linux-libre-2.6.38-gnu1/arch/arm/mach-mx25/clock.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mx25/clock.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mx25/clock.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,332 +0,0 @@
-/*
- * Copyright (C) 2009 by Sascha Hauer, Pengutronix
- *
- * 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/kernel.h>
-#include <linux/init.h>
-#include <linux/list.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-
-#include <asm/clkdev.h>
-
-#include <mach/clock.h>
-#include <mach/hardware.h>
-#include <mach/common.h>
-#include <mach/mx25.h>
-
-#define CRM_BASE	MX25_IO_ADDRESS(MX25_CRM_BASE_ADDR)
-
-#define CCM_MPCTL	0x00
-#define CCM_UPCTL	0x04
-#define CCM_CCTL	0x08
-#define CCM_CGCR0	0x0C
-#define CCM_CGCR1	0x10
-#define CCM_CGCR2	0x14
-#define CCM_PCDR0	0x18
-#define CCM_PCDR1	0x1C
-#define CCM_PCDR2	0x20
-#define CCM_PCDR3	0x24
-#define CCM_RCSR	0x28
-#define CCM_CRDR	0x2C
-#define CCM_DCVR0	0x30
-#define CCM_DCVR1	0x34
-#define CCM_DCVR2	0x38
-#define CCM_DCVR3	0x3c
-#define CCM_LTR0	0x40
-#define CCM_LTR1	0x44
-#define CCM_LTR2	0x48
-#define CCM_LTR3	0x4c
-
-static unsigned long get_rate_mpll(void)
-{
-	ulong mpctl = __raw_readl(CRM_BASE + CCM_MPCTL);
-
-	return mxc_decode_pll(mpctl, 24000000);
-}
-
-static unsigned long get_rate_upll(void)
-{
-	ulong mpctl = __raw_readl(CRM_BASE + CCM_UPCTL);
-
-	return mxc_decode_pll(mpctl, 24000000);
-}
-
-unsigned long get_rate_arm(struct clk *clk)
-{
-	unsigned long cctl = readl(CRM_BASE + CCM_CCTL);
-	unsigned long rate = get_rate_mpll();
-
-	if (cctl & (1 << 14))
-		rate = (rate * 3) >> 2;
-
-	return rate / ((cctl >> 30) + 1);
-}
-
-static unsigned long get_rate_ahb(struct clk *clk)
-{
-	unsigned long cctl = readl(CRM_BASE + CCM_CCTL);
-
-	return get_rate_arm(NULL) / (((cctl >> 28) & 0x3) + 1);
-}
-
-static unsigned long get_rate_ipg(struct clk *clk)
-{
-	return get_rate_ahb(NULL) >> 1;
-}
-
-static unsigned long get_rate_per(int per)
-{
-	unsigned long ofs = (per & 0x3) * 8;
-	unsigned long reg = per & ~0x3;
-	unsigned long val = (readl(CRM_BASE + CCM_PCDR0 + reg) >> ofs) & 0x3f;
-	unsigned long fref;
-
-	if (readl(CRM_BASE + 0x64) & (1 << per))
-		fref = get_rate_upll();
-	else
-		fref = get_rate_ahb(NULL);
-
-	return fref / (val + 1);
-}
-
-static unsigned long get_rate_uart(struct clk *clk)
-{
-	return get_rate_per(15);
-}
-
-static unsigned long get_rate_ssi2(struct clk *clk)
-{
-	return get_rate_per(14);
-}
-
-static unsigned long get_rate_ssi1(struct clk *clk)
-{
-	return get_rate_per(13);
-}
-
-static unsigned long get_rate_i2c(struct clk *clk)
-{
-	return get_rate_per(6);
-}
-
-static unsigned long get_rate_nfc(struct clk *clk)
-{
-	return get_rate_per(8);
-}
-
-static unsigned long get_rate_gpt(struct clk *clk)
-{
-	return get_rate_per(5);
-}
-
-static unsigned long get_rate_lcdc(struct clk *clk)
-{
-	return get_rate_per(7);
-}
-
-static unsigned long get_rate_esdhc1(struct clk *clk)
-{
-	return get_rate_per(3);
-}
-
-static unsigned long get_rate_esdhc2(struct clk *clk)
-{
-	return get_rate_per(4);
-}
-
-static unsigned long get_rate_csi(struct clk *clk)
-{
-	return get_rate_per(0);
-}
-
-static unsigned long get_rate_otg(struct clk *clk)
-{
-	unsigned long cctl = readl(CRM_BASE + CCM_CCTL);
-	unsigned long rate = get_rate_upll();
-
-	return (cctl & (1 << 23)) ? 0 : rate / ((0x3F & (cctl >> 16)) + 1);
-}
-
-static int clk_cgcr_enable(struct clk *clk)
-{
-	u32 reg;
-
-	reg = __raw_readl(clk->enable_reg);
-	reg |= 1 << clk->enable_shift;
-	__raw_writel(reg, clk->enable_reg);
-
-	return 0;
-}
-
-static void clk_cgcr_disable(struct clk *clk)
-{
-	u32 reg;
-
-	reg = __raw_readl(clk->enable_reg);
-	reg &= ~(1 << clk->enable_shift);
-	__raw_writel(reg, clk->enable_reg);
-}
-
-#define DEFINE_CLOCK(name, i, er, es, gr, sr, s)	\
-	static struct clk name = {			\
-		.id		= i,			\
-		.enable_reg	= CRM_BASE + er,	\
-		.enable_shift	= es,			\
-		.get_rate	= gr,			\
-		.set_rate	= sr,			\
-		.enable		= clk_cgcr_enable,	\
-		.disable	= clk_cgcr_disable,	\
-		.secondary	= s,			\
-	}
-
-/*
- * Note: the following IPG clock gating bits are wrongly marked "Reserved" in
- * the i.MX25 Reference Manual Rev 1, table 15-13. The information below is
- * taken from the Freescale released BSP.
- *
- * bit	reg	offset	clock
- *
- * 0	CGCR1	0	AUDMUX
- * 12	CGCR1	12	ESAI
- * 16	CGCR1	16	GPIO1
- * 17	CGCR1	17	GPIO2
- * 18	CGCR1	18	GPIO3
- * 23	CGCR1	23	I2C1
- * 24	CGCR1	24	I2C2
- * 25	CGCR1	25	I2C3
- * 27	CGCR1	27	IOMUXC
- * 28	CGCR1	28	KPP
- * 30	CGCR1	30	OWIRE
- * 36	CGCR2	4	RTIC
- * 51	CGCR2	19	WDOG
- */
-
-DEFINE_CLOCK(gpt_clk,    0, CCM_CGCR0,  5, get_rate_gpt, NULL, NULL);
-DEFINE_CLOCK(uart_per_clk, 0, CCM_CGCR0, 15, get_rate_uart, NULL, NULL);
-DEFINE_CLOCK(ssi1_per_clk, 0, CCM_CGCR0, 13, get_rate_ipg, NULL, NULL);
-DEFINE_CLOCK(ssi2_per_clk, 0, CCM_CGCR0, 14, get_rate_ipg, NULL, NULL);
-DEFINE_CLOCK(cspi1_clk,  0, CCM_CGCR1,  5, get_rate_ipg, NULL, NULL);
-DEFINE_CLOCK(cspi2_clk,  0, CCM_CGCR1,  6, get_rate_ipg, NULL, NULL);
-DEFINE_CLOCK(cspi3_clk,  0, CCM_CGCR1,  7, get_rate_ipg, NULL, NULL);
-DEFINE_CLOCK(esdhc1_ahb_clk, 0, CCM_CGCR0, 21, get_rate_esdhc1,	 NULL, NULL);
-DEFINE_CLOCK(esdhc1_per_clk, 0, CCM_CGCR0,  3, get_rate_esdhc1,	 NULL,
-		&esdhc1_ahb_clk);
-DEFINE_CLOCK(esdhc2_ahb_clk, 0, CCM_CGCR0, 22, get_rate_esdhc2,	 NULL, NULL);
-DEFINE_CLOCK(esdhc2_per_clk, 0, CCM_CGCR0,  4, get_rate_esdhc2,	 NULL,
-		&esdhc2_ahb_clk);
-DEFINE_CLOCK(fec_ahb_clk, 0, CCM_CGCR0, 23, NULL,	 NULL, NULL);
-DEFINE_CLOCK(lcdc_ahb_clk, 0, CCM_CGCR0, 24, NULL,	 NULL, NULL);
-DEFINE_CLOCK(lcdc_per_clk, 0, CCM_CGCR0,  7, NULL,	 NULL, &lcdc_ahb_clk);
-DEFINE_CLOCK(csi_ahb_clk, 0, CCM_CGCR0, 18, get_rate_csi, NULL, NULL);
-DEFINE_CLOCK(csi_per_clk, 0, CCM_CGCR0, 0, get_rate_csi, NULL, &csi_ahb_clk);
-DEFINE_CLOCK(uart1_clk,  0, CCM_CGCR2, 14, get_rate_uart, NULL, &uart_per_clk);
-DEFINE_CLOCK(uart2_clk,  0, CCM_CGCR2, 15, get_rate_uart, NULL, &uart_per_clk);
-DEFINE_CLOCK(uart3_clk,  0, CCM_CGCR2, 16, get_rate_uart, NULL, &uart_per_clk);
-DEFINE_CLOCK(uart4_clk,  0, CCM_CGCR2, 17, get_rate_uart, NULL, &uart_per_clk);
-DEFINE_CLOCK(uart5_clk,  0, CCM_CGCR2, 18, get_rate_uart, NULL, &uart_per_clk);
-DEFINE_CLOCK(nfc_clk,    0, CCM_CGCR0,  8, get_rate_nfc, NULL, NULL);
-DEFINE_CLOCK(usbotg_clk, 0, CCM_CGCR0, 28, get_rate_otg, NULL, NULL);
-DEFINE_CLOCK(pwm1_clk,	 0, CCM_CGCR1, 31, get_rate_ipg, NULL, NULL);
-DEFINE_CLOCK(pwm2_clk,	 0, CCM_CGCR2,  0, get_rate_ipg, NULL, NULL);
-DEFINE_CLOCK(pwm3_clk,	 0, CCM_CGCR2,  1, get_rate_ipg, NULL, NULL);
-DEFINE_CLOCK(pwm4_clk,	 0, CCM_CGCR2,  2, get_rate_ipg, NULL, NULL);
-DEFINE_CLOCK(kpp_clk,	 0, CCM_CGCR1, 28, get_rate_ipg, NULL, NULL);
-DEFINE_CLOCK(tsc_clk,	 0, CCM_CGCR2, 13, get_rate_ipg, NULL, NULL);
-DEFINE_CLOCK(i2c_clk,	 0, CCM_CGCR0,  6, get_rate_i2c, NULL, NULL);
-DEFINE_CLOCK(fec_clk,	 0, CCM_CGCR1, 15, get_rate_ipg, NULL, &fec_ahb_clk);
-DEFINE_CLOCK(dryice_clk, 0, CCM_CGCR1,  8, get_rate_ipg, NULL, NULL);
-DEFINE_CLOCK(lcdc_clk,	 0, CCM_CGCR1, 29, get_rate_lcdc, NULL, &lcdc_per_clk);
-DEFINE_CLOCK(wdt_clk,    0, CCM_CGCR2, 19, get_rate_ipg, NULL,  NULL);
-DEFINE_CLOCK(ssi1_clk,  0, CCM_CGCR2, 11, get_rate_ssi1, NULL, &ssi1_per_clk);
-DEFINE_CLOCK(ssi2_clk,  1, CCM_CGCR2, 12, get_rate_ssi2, NULL, &ssi2_per_clk);
-DEFINE_CLOCK(esdhc1_clk,  0, CCM_CGCR1, 13, get_rate_esdhc1, NULL,
-		&esdhc1_per_clk);
-DEFINE_CLOCK(esdhc2_clk,  1, CCM_CGCR1, 14, get_rate_esdhc2, NULL,
-		&esdhc2_per_clk);
-DEFINE_CLOCK(audmux_clk, 0, CCM_CGCR1, 0, NULL, NULL, NULL);
-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 _REGISTER_CLOCK(d, n, c)	\
-	{				\
-		.dev_id = d,		\
-		.con_id = n,		\
-		.clk = &c,		\
-	},
-
-static struct clk_lookup lookups[] = {
-	_REGISTER_CLOCK("imx-uart.0", NULL, uart1_clk)
-	_REGISTER_CLOCK("imx-uart.1", NULL, uart2_clk)
-	_REGISTER_CLOCK("imx-uart.2", NULL, uart3_clk)
-	_REGISTER_CLOCK("imx-uart.3", NULL, uart4_clk)
-	_REGISTER_CLOCK("imx-uart.4", NULL, uart5_clk)
-	_REGISTER_CLOCK("mxc-ehci.0", "usb", usbotg_clk)
-	_REGISTER_CLOCK("mxc-ehci.1", "usb", usbotg_clk)
-	_REGISTER_CLOCK("mxc-ehci.2", "usb", usbotg_clk)
-	_REGISTER_CLOCK("fsl-usb2-udc", "usb", usbotg_clk)
-	_REGISTER_CLOCK("mxc_nand.0", NULL, nfc_clk)
-	_REGISTER_CLOCK("imx25-cspi.0", NULL, cspi1_clk)
-	_REGISTER_CLOCK("imx25-cspi.1", NULL, cspi2_clk)
-	_REGISTER_CLOCK("imx25-cspi.2", NULL, cspi3_clk)
-	_REGISTER_CLOCK("mxc_pwm.0", NULL, pwm1_clk)
-	_REGISTER_CLOCK("mxc_pwm.1", NULL, pwm2_clk)
-	_REGISTER_CLOCK("mxc_pwm.2", NULL, pwm3_clk)
-	_REGISTER_CLOCK("mxc_pwm.3", NULL, pwm4_clk)
-	_REGISTER_CLOCK("imx-keypad", NULL, kpp_clk)
-	_REGISTER_CLOCK("mx25-adc", NULL, tsc_clk)
-	_REGISTER_CLOCK("imx-i2c.0", NULL, i2c_clk)
-	_REGISTER_CLOCK("imx-i2c.1", NULL, i2c_clk)
-	_REGISTER_CLOCK("imx-i2c.2", NULL, i2c_clk)
-	_REGISTER_CLOCK("fec.0", NULL, fec_clk)
-	_REGISTER_CLOCK("imxdi_rtc.0", NULL, dryice_clk)
-	_REGISTER_CLOCK("imx-fb.0", NULL, lcdc_clk)
-	_REGISTER_CLOCK("imx-wdt.0", NULL, wdt_clk)
-	_REGISTER_CLOCK("imx-ssi.0", NULL, ssi1_clk)
-	_REGISTER_CLOCK("imx-ssi.1", NULL, ssi2_clk)
-	_REGISTER_CLOCK("sdhci-esdhc-imx.0", NULL, esdhc1_clk)
-	_REGISTER_CLOCK("sdhci-esdhc-imx.1", NULL, esdhc2_clk)
-	_REGISTER_CLOCK("mx2-camera.0", NULL, csi_clk)
-	_REGISTER_CLOCK(NULL, "audmux", audmux_clk)
-	_REGISTER_CLOCK("flexcan.0", NULL, can1_clk)
-	_REGISTER_CLOCK("flexcan.1", NULL, can2_clk)
-};
-
-int __init mx25_clocks_init(void)
-{
-	clkdev_add_table(lookups, ARRAY_SIZE(lookups));
-
-	/* Turn off all clocks except the ones we need to survive, namely:
-	 * EMI, GPIO1-3 (CCM_CGCR1[18:16]), GPT1, IOMUXC (CCM_CGCR1[27]), IIM,
-	 * SCC
-	 */
-	__raw_writel((1 << 19), CRM_BASE + CCM_CGCR0);
-	__raw_writel((0xf << 16) | (3 << 26), CRM_BASE + CCM_CGCR1);
-	__raw_writel((1 << 5), CRM_BASE + CCM_CGCR2);
-#if defined(CONFIG_DEBUG_LL) && !defined(CONFIG_DEBUG_ICEDCC)
-	clk_enable(&uart1_clk);
-#endif
-
-	/* Clock source for lcdc and csi is upll */
-	__raw_writel(__raw_readl(CRM_BASE+0x64) | (1 << 7) | (1 << 0),
-			CRM_BASE + 0x64);
-
-	mxc_timer_init(&gpt_clk, MX25_IO_ADDRESS(MX25_GPT1_BASE_ADDR), 54);
-
-	return 0;
-}
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mx25/devices.c linux-libre-2.6.38-gnu1/arch/arm/mach-mx25/devices.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mx25/devices.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mx25/devices.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,308 +0,0 @@
-/*
- * Copyright 2009 Sascha Hauer, <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.
- */
-
-#include <linux/platform_device.h>
-#include <linux/dma-mapping.h>
-#include <linux/gpio.h>
-#include <mach/mx25.h>
-#include <mach/irqs.h>
-
-static u64 otg_dmamask = DMA_BIT_MASK(32);
-
-static struct resource mxc_otg_resources[] = {
-	{
-		.start = MX25_OTG_BASE_ADDR,
-		.end = MX25_OTG_BASE_ADDR + 0x1ff,
-		.flags = IORESOURCE_MEM,
-	}, {
-		.start = 37,
-		.end = 37,
-		.flags = IORESOURCE_IRQ,
-	},
-};
-
-struct platform_device mxc_otg = {
-	.name = "mxc-ehci",
-	.id = 0,
-	.dev = {
-		.coherent_dma_mask = 0xffffffff,
-		.dma_mask = &otg_dmamask,
-	},
-	.resource = mxc_otg_resources,
-	.num_resources = ARRAY_SIZE(mxc_otg_resources),
-};
-
-/* OTG gadget device */
-struct platform_device otg_udc_device = {
-	.name = "fsl-usb2-udc",
-	.id   = -1,
-	.dev  = {
-		.dma_mask          = &otg_dmamask,
-		.coherent_dma_mask = 0xffffffff,
-	},
-	.resource = mxc_otg_resources,
-	.num_resources = ARRAY_SIZE(mxc_otg_resources),
-};
-
-static u64 usbh2_dmamask = DMA_BIT_MASK(32);
-
-static struct resource mxc_usbh2_resources[] = {
-	{
-		.start = MX25_OTG_BASE_ADDR + 0x400,
-		.end = MX25_OTG_BASE_ADDR + 0x5ff,
-		.flags = IORESOURCE_MEM,
-	}, {
-		.start = 35,
-		.end = 35,
-		.flags = IORESOURCE_IRQ,
-	},
-};
-
-struct platform_device mxc_usbh2 = {
-	.name = "mxc-ehci",
-	.id = 1,
-	.dev = {
-		.coherent_dma_mask = 0xffffffff,
-		.dma_mask = &usbh2_dmamask,
-	},
-	.resource = mxc_usbh2_resources,
-	.num_resources = ARRAY_SIZE(mxc_usbh2_resources),
-};
-
-static struct resource mxc_pwm_resources0[] = {
-	{
-		.start	= 0x53fe0000,
-		.end	= 0x53fe3fff,
-		.flags	= IORESOURCE_MEM,
-	}, {
-		.start   = 26,
-		.end     = 26,
-		.flags   = IORESOURCE_IRQ,
-	}
-};
-
-struct platform_device mxc_pwm_device0 = {
-	.name = "mxc_pwm",
-	.id = 0,
-	.num_resources = ARRAY_SIZE(mxc_pwm_resources0),
-	.resource = mxc_pwm_resources0,
-};
-
-static struct resource mxc_pwm_resources1[] = {
-	{
-		.start	= 0x53fa0000,
-		.end	= 0x53fa3fff,
-		.flags	= IORESOURCE_MEM,
-	}, {
-		.start   = 36,
-		.end     = 36,
-		.flags   = IORESOURCE_IRQ,
-	}
-};
-
-struct platform_device mxc_pwm_device1 = {
-	.name = "mxc_pwm",
-	.id = 1,
-	.num_resources = ARRAY_SIZE(mxc_pwm_resources1),
-	.resource = mxc_pwm_resources1,
-};
-
-static struct resource mxc_pwm_resources2[] = {
-	{
-		.start	= 0x53fa8000,
-		.end	= 0x53fabfff,
-		.flags	= IORESOURCE_MEM,
-	}, {
-		.start   = 41,
-		.end     = 41,
-		.flags   = IORESOURCE_IRQ,
-	}
-};
-
-struct platform_device mxc_pwm_device2 = {
-	.name = "mxc_pwm",
-	.id = 2,
-	.num_resources = ARRAY_SIZE(mxc_pwm_resources2),
-	.resource = mxc_pwm_resources2,
-};
-
-static struct resource mxc_keypad_resources[] = {
-	{
-		.start	= 0x43fa8000,
-		.end	= 0x43fabfff,
-		.flags	= IORESOURCE_MEM,
-	}, {
-		.start   = 24,
-		.end     = 24,
-		.flags   = IORESOURCE_IRQ,
-	}
-};
-
-struct platform_device mxc_keypad_device = {
-	.name = "mxc-keypad",
-	.id = -1,
-	.num_resources = ARRAY_SIZE(mxc_keypad_resources),
-	.resource = mxc_keypad_resources,
-};
-
-static struct resource mxc_pwm_resources3[] = {
-	{
-		.start	= 0x53fc8000,
-		.end	= 0x53fcbfff,
-		.flags	= IORESOURCE_MEM,
-	}, {
-		.start   = 42,
-		.end     = 42,
-		.flags   = IORESOURCE_IRQ,
-	}
-};
-
-struct platform_device mxc_pwm_device3 = {
-	.name = "mxc_pwm",
-	.id = 3,
-	.num_resources = ARRAY_SIZE(mxc_pwm_resources3),
-	.resource = mxc_pwm_resources3,
-};
-
-static struct mxc_gpio_port imx_gpio_ports[] = {
-	{
-		.chip.label = "gpio-0",
-		.base = (void __iomem *)MX25_GPIO1_BASE_ADDR_VIRT,
-		.irq = 52,
-		.virtual_irq_start = MXC_GPIO_IRQ_START,
-	}, {
-		.chip.label = "gpio-1",
-		.base = (void __iomem *)MX25_GPIO2_BASE_ADDR_VIRT,
-		.irq = 51,
-		.virtual_irq_start = MXC_GPIO_IRQ_START + 32,
-	}, {
-		.chip.label = "gpio-2",
-		.base = (void __iomem *)MX25_GPIO3_BASE_ADDR_VIRT,
-		.irq = 16,
-		.virtual_irq_start = MXC_GPIO_IRQ_START + 64,
-	}, {
-		.chip.label = "gpio-3",
-		.base = (void __iomem *)MX25_GPIO4_BASE_ADDR_VIRT,
-		.irq = 23,
-		.virtual_irq_start = MXC_GPIO_IRQ_START + 96,
-	}
-};
-
-int __init imx25_register_gpios(void)
-{
-	return mxc_gpio_init(imx_gpio_ports, ARRAY_SIZE(imx_gpio_ports));
-}
-
-static struct resource mx25_rtc_resources[] = {
-	{
-		.start	= MX25_DRYICE_BASE_ADDR,
-		.end	= MX25_DRYICE_BASE_ADDR + 0x40,
-		.flags	= IORESOURCE_MEM,
-	},
-	{
-		.start	= MX25_INT_DRYICE,
-		.flags	= IORESOURCE_IRQ
-	},
-};
-
-struct platform_device mx25_rtc_device = {
-	.name	= "imxdi_rtc",
-	.id	= 0,
-	.num_resources	= ARRAY_SIZE(mx25_rtc_resources),
-	.resource	= mx25_rtc_resources,
-};
-
-static struct resource mx25_fb_resources[] = {
-	{
-		.start	= MX25_LCDC_BASE_ADDR,
-		.end	= MX25_LCDC_BASE_ADDR + 0xfff,
-		.flags	= IORESOURCE_MEM,
-	},
-	{
-		.start	= MX25_INT_LCDC,
-		.end	= MX25_INT_LCDC,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-struct platform_device mx25_fb_device = {
-	.name		= "imx-fb",
-	.id		= 0,
-	.resource	= mx25_fb_resources,
-	.num_resources	= ARRAY_SIZE(mx25_fb_resources),
-	.dev		= {
-		.coherent_dma_mask = 0xFFFFFFFF,
-	},
-};
-
-static struct resource mxc_wdt_resources[] = {
-	{
-		.start = MX25_WDOG_BASE_ADDR,
-		.end = MX25_WDOG_BASE_ADDR + SZ_16K - 1,
-		.flags = IORESOURCE_MEM,
-	},
-};
-
-struct platform_device mxc_wdt = {
-	.name = "imx2-wdt",
-	.id = 0,
-	.num_resources = ARRAY_SIZE(mxc_wdt_resources),
-	.resource = mxc_wdt_resources,
-};
-
-static struct resource mx25_kpp_resources[] = {
-	{
-		.start	= MX25_KPP_BASE_ADDR,
-		.end	= MX25_KPP_BASE_ADDR + 0xf,
-		.flags	= IORESOURCE_MEM,
-	},
-	{
-		.start	= MX25_INT_KPP,
-		.end	= MX25_INT_KPP,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-struct platform_device mx25_kpp_device = {
-	.name	= "imx-keypad",
-	.id	= -1,
-	.num_resources	= ARRAY_SIZE(mx25_kpp_resources),
-	.resource	= mx25_kpp_resources,
-};
-
-static struct resource mx25_csi_resources[] = {
-	{
-		.start	= MX25_CSI_BASE_ADDR,
-		.end	= MX25_CSI_BASE_ADDR + 0xfff,
-		.flags	= IORESOURCE_MEM,
-	},
-	{
-		.start	= MX25_INT_CSI,
-		.flags	= IORESOURCE_IRQ
-	},
-};
-
-struct platform_device mx25_csi_device = {
-	.name	= "mx2-camera",
-	.id	= 0,
-	.num_resources	= ARRAY_SIZE(mx25_csi_resources),
-	.resource	= mx25_csi_resources,
-	.dev		= {
-		.coherent_dma_mask = 0xffffffff,
-	},
-};
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mx25/devices.h linux-libre-2.6.38-gnu1/arch/arm/mach-mx25/devices.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mx25/devices.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mx25/devices.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,13 +0,0 @@
-extern struct platform_device mxc_otg;
-extern struct platform_device otg_udc_device;
-extern struct platform_device mxc_usbh2;
-extern struct platform_device mxc_pwm_device0;
-extern struct platform_device mxc_pwm_device1;
-extern struct platform_device mxc_pwm_device2;
-extern struct platform_device mxc_pwm_device3;
-extern struct platform_device mxc_keypad_device;
-extern struct platform_device mx25_rtc_device;
-extern struct platform_device mx25_fb_device;
-extern struct platform_device mxc_wdt;
-extern struct platform_device mx25_kpp_device;
-extern struct platform_device mx25_csi_device;
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mx25/devices-imx25.h linux-libre-2.6.38-gnu1/arch/arm/mach-mx25/devices-imx25.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mx25/devices-imx25.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mx25/devices-imx25.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,54 +0,0 @@
-/*
- * Copyright (C) 2010 Pengutronix
- * Uwe Kleine-Koenig <u.kleine-koenig@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 <mach/mx25.h>
-#include <mach/devices-common.h>
-
-extern const struct imx_fec_data imx25_fec_data __initconst;
-#define imx25_add_fec(pdata)	\
-	imx_add_fec(&imx25_fec_data, pdata)
-
-#define imx25_add_flexcan0(pdata)	\
-	imx_add_flexcan(0, MX25_CAN1_BASE_ADDR, SZ_16K, MX25_INT_CAN1, pdata)
-#define imx25_add_flexcan1(pdata)	\
-	imx_add_flexcan(1, MX25_CAN2_BASE_ADDR, SZ_16K, MX25_INT_CAN2, pdata)
-
-extern const struct imx_imx_i2c_data imx25_imx_i2c_data[] __initconst;
-#define imx25_add_imx_i2c(id, pdata)	\
-	imx_add_imx_i2c(&imx25_imx_i2c_data[id], pdata)
-#define imx25_add_imx_i2c0(pdata)	imx25_add_imx_i2c(0, pdata)
-#define imx25_add_imx_i2c1(pdata)	imx25_add_imx_i2c(1, pdata)
-#define imx25_add_imx_i2c2(pdata)	imx25_add_imx_i2c(2, pdata)
-
-extern const struct imx_imx_ssi_data imx25_imx_ssi_data[] __initconst;
-#define imx25_add_imx_ssi(id, pdata)	\
-	imx_add_imx_ssi(&imx25_imx_ssi_data[id], pdata)
-
-extern const struct imx_imx_uart_1irq_data imx25_imx_uart_data[] __initconst;
-#define imx25_add_imx_uart(id, pdata)	\
-	imx_add_imx_uart_1irq(&imx25_imx_uart_data[id], pdata)
-#define imx25_add_imx_uart0(pdata)	imx25_add_imx_uart(0, pdata)
-#define imx25_add_imx_uart1(pdata)	imx25_add_imx_uart(1, pdata)
-#define imx25_add_imx_uart2(pdata)	imx25_add_imx_uart(2, pdata)
-#define imx25_add_imx_uart3(pdata)	imx25_add_imx_uart(3, pdata)
-#define imx25_add_imx_uart4(pdata)	imx25_add_imx_uart(4, pdata)
-
-extern const struct imx_mxc_nand_data imx25_mxc_nand_data __initconst;
-#define imx25_add_mxc_nand(pdata)	\
-	imx_add_mxc_nand(&imx25_mxc_nand_data, pdata)
-
-extern const struct imx_spi_imx_data imx25_cspi_data[] __initconst;
-#define imx25_add_spi_imx(id, pdata)	\
-	imx_add_spi_imx(&imx25_cspi_data[id], pdata)
-#define imx25_add_spi_imx0(pdata)	imx25_add_spi_imx(0, pdata)
-#define imx25_add_spi_imx1(pdata)	imx25_add_spi_imx(1, pdata)
-#define imx25_add_spi_imx2(pdata)	imx25_add_spi_imx(2, pdata)
-
-extern const struct imx_esdhc_imx_data imx25_esdhc_data[] __initconst;
-#define imx25_add_esdhc(id, pdata)	\
-	imx_add_esdhc(&imx25_esdhc_data[id], pdata)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mx25/eukrea_mbimxsd-baseboard.c linux-libre-2.6.38-gnu1/arch/arm/mach-mx25/eukrea_mbimxsd-baseboard.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mx25/eukrea_mbimxsd-baseboard.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mx25/eukrea_mbimxsd-baseboard.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,298 +0,0 @@
-/*
- * Copyright (C) 2010 Eric Benard - eric@eukrea.com
- *
- * Based on pcm970-baseboard.c which is :
- * Copyright (C) 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.
- */
-
-#include <linux/gpio.h>
-#include <linux/leds.h>
-#include <linux/platform_device.h>
-#include <linux/gpio_keys.h>
-#include <linux/input.h>
-#include <video/platform_lcd.h>
-
-#include <mach/hardware.h>
-#include <mach/iomux-mx25.h>
-#include <mach/common.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <mach/mx25.h>
-#include <mach/imx-uart.h>
-#include <mach/imxfb.h>
-#include <mach/audmux.h>
-
-#include "devices-imx25.h"
-#include "devices.h"
-
-static struct pad_desc eukrea_mbimxsd_pads[] = {
-	/* LCD */
-	MX25_PAD_LD0__LD0,
-	MX25_PAD_LD1__LD1,
-	MX25_PAD_LD2__LD2,
-	MX25_PAD_LD3__LD3,
-	MX25_PAD_LD4__LD4,
-	MX25_PAD_LD5__LD5,
-	MX25_PAD_LD6__LD6,
-	MX25_PAD_LD7__LD7,
-	MX25_PAD_LD8__LD8,
-	MX25_PAD_LD9__LD9,
-	MX25_PAD_LD10__LD10,
-	MX25_PAD_LD11__LD11,
-	MX25_PAD_LD12__LD12,
-	MX25_PAD_LD13__LD13,
-	MX25_PAD_LD14__LD14,
-	MX25_PAD_LD15__LD15,
-	MX25_PAD_GPIO_E__LD16,
-	MX25_PAD_GPIO_F__LD17,
-	MX25_PAD_HSYNC__HSYNC,
-	MX25_PAD_VSYNC__VSYNC,
-	MX25_PAD_LSCLK__LSCLK,
-	MX25_PAD_OE_ACD__OE_ACD,
-	MX25_PAD_CONTRAST__CONTRAST,
-	/* LCD_PWR */
-	MX25_PAD_PWM__GPIO_1_26,
-	/* LED */
-	MX25_PAD_POWER_FAIL__GPIO_3_19,
-	/* SWITCH */
-	MX25_PAD_VSTBY_ACK__GPIO_3_18,
-	/* UART2 */
-	MX25_PAD_UART2_RTS__UART2_RTS,
-	MX25_PAD_UART2_CTS__UART2_CTS,
-	MX25_PAD_UART2_TXD__UART2_TXD,
-	MX25_PAD_UART2_RXD__UART2_RXD,
-	/* SD1 */
-	MX25_PAD_SD1_CMD__SD1_CMD,
-	MX25_PAD_SD1_CLK__SD1_CLK,
-	MX25_PAD_SD1_DATA0__SD1_DATA0,
-	MX25_PAD_SD1_DATA1__SD1_DATA1,
-	MX25_PAD_SD1_DATA2__SD1_DATA2,
-	MX25_PAD_SD1_DATA3__SD1_DATA3,
-	/* SD1 CD */
-	MX25_PAD_DE_B__GPIO_2_20,
-	/* I2S */
-	MX25_PAD_KPP_COL3__AUD5_TXFS,
-	MX25_PAD_KPP_COL2__AUD5_TXC,
-	MX25_PAD_KPP_COL1__AUD5_RXD,
-	MX25_PAD_KPP_COL0__AUD5_TXD,
-	/* CAN */
-	MX25_PAD_GPIO_D__CAN2_RX,
-	MX25_PAD_GPIO_C__CAN2_TX,
-};
-
-#define GPIO_LED1	83
-#define GPIO_SWITCH1	82
-#define GPIO_SD1CD	52
-#define GPIO_LCDPWR	26
-
-static struct imx_fb_videomode eukrea_mximxsd_modes[] = {
-	{
-		.mode	= {
-			.name		= "CMO-QVGA",
-			.refresh	= 60,
-			.xres		= 320,
-			.yres		= 240,
-			.pixclock	= KHZ2PICOS(6500),
-			.left_margin	= 30,
-			.right_margin	= 38,
-			.upper_margin	= 20,
-			.lower_margin	= 3,
-			.hsync_len	= 15,
-			.vsync_len	= 4,
-		},
-		.bpp	= 16,
-		.pcr	= 0xCAD08B80,
-	}, {
-		.mode = {
-			.name		= "DVI-VGA",
-			.refresh	= 60,
-			.xres		= 640,
-			.yres		= 480,
-			.pixclock	= 32000,
-			.hsync_len	= 7,
-			.left_margin	= 100,
-			.right_margin	= 100,
-			.vsync_len	= 7,
-			.upper_margin	= 7,
-			.lower_margin	= 100,
-		},
-		.pcr		= 0xFA208B80,
-		.bpp		= 16,
-	}, {
-		.mode = {
-			.name		= "DVI-SVGA",
-			.refresh	= 60,
-			.xres		= 800,
-			.yres		= 600,
-			.pixclock	= 25000,
-			.hsync_len	= 7,
-			.left_margin	= 75,
-			.right_margin	= 75,
-			.vsync_len	= 7,
-			.upper_margin	= 7,
-			.lower_margin	= 75,
-		},
-		.pcr		= 0xFA208B80,
-		.bpp		= 16,
-	},
-};
-
-static struct imx_fb_platform_data eukrea_mximxsd_fb_pdata = {
-	.mode		= eukrea_mximxsd_modes,
-	.num_modes	= ARRAY_SIZE(eukrea_mximxsd_modes),
-	.pwmr		= 0x00A903FF,
-	.lscr1		= 0x00120300,
-	.dmacr		= 0x00040060,
-};
-
-static void eukrea_mbimxsd_lcd_power_set(struct plat_lcd_data *pd,
-				   unsigned int power)
-{
-	if (power)
-		gpio_direction_output(GPIO_LCDPWR, 1);
-	else
-		gpio_direction_output(GPIO_LCDPWR, 0);
-}
-
-static struct plat_lcd_data eukrea_mbimxsd_lcd_power_data = {
-	.set_power		= eukrea_mbimxsd_lcd_power_set,
-};
-
-static struct platform_device eukrea_mbimxsd_lcd_powerdev = {
-	.name			= "platform-lcd",
-	.dev.platform_data	= &eukrea_mbimxsd_lcd_power_data,
-};
-
-static struct gpio_led eukrea_mbimxsd_leds[] = {
-	{
-		.name			= "led1",
-		.default_trigger	= "heartbeat",
-		.active_low		= 1,
-		.gpio			= GPIO_LED1,
-	},
-};
-
-static struct gpio_led_platform_data eukrea_mbimxsd_led_info = {
-	.leds		= eukrea_mbimxsd_leds,
-	.num_leds	= ARRAY_SIZE(eukrea_mbimxsd_leds),
-};
-
-static struct platform_device eukrea_mbimxsd_leds_gpio = {
-	.name	= "leds-gpio",
-	.id	= -1,
-	.dev	= {
-		.platform_data	= &eukrea_mbimxsd_led_info,
-	},
-};
-
-static struct gpio_keys_button eukrea_mbimxsd_gpio_buttons[] = {
-	{
-		.gpio		= GPIO_SWITCH1,
-		.code		= BTN_0,
-		.desc		= "BP1",
-		.active_low	= 1,
-		.wakeup		= 1,
-	},
-};
-
-static struct gpio_keys_platform_data eukrea_mbimxsd_button_data = {
-	.buttons	= eukrea_mbimxsd_gpio_buttons,
-	.nbuttons	= ARRAY_SIZE(eukrea_mbimxsd_gpio_buttons),
-};
-
-static struct platform_device eukrea_mbimxsd_button_device = {
-	.name		= "gpio-keys",
-	.id		= -1,
-	.num_resources	= 0,
-	.dev		= {
-		.platform_data	= &eukrea_mbimxsd_button_data,
-	}
-};
-
-static struct platform_device *platform_devices[] __initdata = {
-	&eukrea_mbimxsd_leds_gpio,
-	&eukrea_mbimxsd_button_device,
-	&eukrea_mbimxsd_lcd_powerdev,
-};
-
-static const struct imxuart_platform_data uart_pdata __initconst = {
-	.flags = IMXUART_HAVE_RTSCTS,
-};
-
-static struct i2c_board_info eukrea_mbimxsd_i2c_devices[] = {
-	{
-		I2C_BOARD_INFO("tlv320aic23", 0x1a),
-	},
-};
-
-static const
-struct imx_ssi_platform_data eukrea_mbimxsd_ssi_pdata __initconst = {
-	.flags = IMX_SSI_SYN | IMX_SSI_NET | IMX_SSI_USE_I2S_SLAVE,
-};
-
-/*
- * system init for baseboard usage. Will be called by cpuimx25 init.
- *
- * Add platform devices present on this baseboard and init
- * them from CPU side as far as required to use them later on
- */
-void __init eukrea_mbimxsd25_baseboard_init(void)
-{
-	if (mxc_iomux_v3_setup_multiple_pads(eukrea_mbimxsd_pads,
-			ARRAY_SIZE(eukrea_mbimxsd_pads)))
-		printk(KERN_ERR "error setting mbimxsd pads !\n");
-
-#if defined(CONFIG_SND_SOC_EUKREA_TLV320)
-	/* SSI unit master I2S codec connected to SSI_AUD5*/
-	mxc_audmux_v2_configure_port(0,
-			MXC_AUDMUX_V2_PTCR_SYN |
-			MXC_AUDMUX_V2_PTCR_TFSDIR |
-			MXC_AUDMUX_V2_PTCR_TFSEL(4) |
-			MXC_AUDMUX_V2_PTCR_TCLKDIR |
-			MXC_AUDMUX_V2_PTCR_TCSEL(4),
-			MXC_AUDMUX_V2_PDCR_RXDSEL(4)
-	);
-	mxc_audmux_v2_configure_port(4,
-			MXC_AUDMUX_V2_PTCR_SYN,
-			MXC_AUDMUX_V2_PDCR_RXDSEL(0)
-	);
-#endif
-
-	imx25_add_imx_uart1(&uart_pdata);
-	mxc_register_device(&mx25_fb_device, &eukrea_mximxsd_fb_pdata);
-	imx25_add_imx_ssi(0, &eukrea_mbimxsd_ssi_pdata);
-
-	imx25_add_flexcan1(NULL);
-	imx25_add_esdhc(0, NULL);
-
-	gpio_request(GPIO_LED1, "LED1");
-	gpio_direction_output(GPIO_LED1, 1);
-	gpio_free(GPIO_LED1);
-
-	gpio_request(GPIO_SWITCH1, "SWITCH1");
-	gpio_direction_input(GPIO_SWITCH1);
-	gpio_free(GPIO_SWITCH1);
-
-	gpio_request(GPIO_LCDPWR, "LCDPWR");
-	gpio_direction_output(GPIO_LCDPWR, 1);
-	gpio_free(GPIO_SWITCH1);
-
-	i2c_register_board_info(0, eukrea_mbimxsd_i2c_devices,
-				ARRAY_SIZE(eukrea_mbimxsd_i2c_devices));
-
-	platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
-}
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mx25/Kconfig linux-libre-2.6.38-gnu1/arch/arm/mach-mx25/Kconfig
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mx25/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mx25/Kconfig	1969-12-31 19:00:00.000000000 -0500
@@ -1,34 +0,0 @@
-if ARCH_MX25
-
-comment "MX25 platforms:"
-
-config MACH_MX25_3DS
-	bool "Support MX25PDK (3DS) Platform"
-	select IMX_HAVE_PLATFORM_IMX_UART
-	select IMX_HAVE_PLATFORM_MXC_NAND
-	select IMX_HAVE_PLATFORM_ESDHC
-
-config MACH_EUKREA_CPUIMX25
-	bool "Support Eukrea CPUIMX25 Platform"
-	select IMX_HAVE_PLATFORM_IMX_I2C
-	select IMX_HAVE_PLATFORM_IMX_UART
-	select IMX_HAVE_PLATFORM_MXC_NAND
-	select IMX_HAVE_PLATFORM_FLEXCAN
-	select IMX_HAVE_PLATFORM_ESDHC
-	select MXC_ULPI if USB_ULPI
-
-choice
-	prompt "Baseboard"
-	depends on MACH_EUKREA_CPUIMX25
-	default MACH_EUKREA_MBIMXSD25_BASEBOARD
-
-config MACH_EUKREA_MBIMXSD25_BASEBOARD
-	bool "Eukrea MBIMXSD development board"
-	select IMX_HAVE_PLATFORM_IMX_SSI
-	help
-	  This adds board specific devices that can be found on Eukrea's
-	  MBIMXSD evaluation board.
-
-endchoice
-
-endif
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mx25/mach-cpuimx25.c linux-libre-2.6.38-gnu1/arch/arm/mach-mx25/mach-cpuimx25.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mx25/mach-cpuimx25.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mx25/mach-cpuimx25.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,164 +0,0 @@
-/*
- * Copyright 2009 Sascha Hauer, <kernel@pengutronix.de>
- * Copyright 2010 Eric Bénard - Eukréa Electromatique, <eric@eukrea.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., 51 Franklin Street, Fifth Floor,
- * Boston, MA  02110-1301, USA.
- */
-
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/clk.h>
-#include <linux/irq.h>
-#include <linux/gpio.h>
-#include <linux/platform_device.h>
-#include <linux/usb/otg.h>
-#include <linux/usb/ulpi.h>
-#include <linux/fsl_devices.h>
-
-#include <mach/eukrea-baseboards.h>
-#include <mach/hardware.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/time.h>
-#include <asm/memory.h>
-#include <asm/mach/map.h>
-#include <mach/common.h>
-#include <mach/mx25.h>
-#include <mach/mxc_nand.h>
-#include <mach/imxfb.h>
-#include <mach/mxc_ehci.h>
-#include <mach/iomux-mx25.h>
-
-#include "devices-imx25.h"
-#include "devices.h"
-
-static const struct imxuart_platform_data uart_pdata __initconst = {
-	.flags = IMXUART_HAVE_RTSCTS,
-};
-
-static struct pad_desc eukrea_cpuimx25_pads[] = {
-	/* FEC - RMII */
-	MX25_PAD_FEC_MDC__FEC_MDC,
-	MX25_PAD_FEC_MDIO__FEC_MDIO,
-	MX25_PAD_FEC_TDATA0__FEC_TDATA0,
-	MX25_PAD_FEC_TDATA1__FEC_TDATA1,
-	MX25_PAD_FEC_TX_EN__FEC_TX_EN,
-	MX25_PAD_FEC_RDATA0__FEC_RDATA0,
-	MX25_PAD_FEC_RDATA1__FEC_RDATA1,
-	MX25_PAD_FEC_RX_DV__FEC_RX_DV,
-	MX25_PAD_FEC_TX_CLK__FEC_TX_CLK,
-	/* I2C1 */
-	MX25_PAD_I2C1_CLK__I2C1_CLK,
-	MX25_PAD_I2C1_DAT__I2C1_DAT,
-};
-
-static const struct fec_platform_data mx25_fec_pdata __initconst = {
-	.phy	= PHY_INTERFACE_MODE_RMII,
-};
-
-static const struct mxc_nand_platform_data
-eukrea_cpuimx25_nand_board_info __initconst = {
-	.width		= 1,
-	.hw_ecc		= 1,
-	.flash_bbt	= 1,
-};
-
-static const struct imxi2c_platform_data
-eukrea_cpuimx25_i2c0_data __initconst = {
-	.bitrate = 100000,
-};
-
-static struct i2c_board_info eukrea_cpuimx25_i2c_devices[] = {
-	{
-		I2C_BOARD_INFO("pcf8563", 0x51),
-	},
-};
-
-static struct mxc_usbh_platform_data otg_pdata = {
-	.portsc	= MXC_EHCI_MODE_UTMI,
-	.flags	= MXC_EHCI_INTERFACE_DIFF_UNI,
-};
-
-static struct mxc_usbh_platform_data usbh2_pdata = {
-	.portsc	= MXC_EHCI_MODE_SERIAL,
-	.flags	= MXC_EHCI_INTERFACE_SINGLE_UNI | MXC_EHCI_INTERNAL_PHY |
-		  MXC_EHCI_IPPUE_DOWN,
-};
-
-static struct fsl_usb2_platform_data otg_device_pdata = {
-	.operating_mode = FSL_USB2_DR_DEVICE,
-	.phy_mode       = FSL_USB2_PHY_UTMI,
-};
-
-static int otg_mode_host;
-
-static int __init eukrea_cpuimx25_otg_mode(char *options)
-{
-	if (!strcmp(options, "host"))
-		otg_mode_host = 1;
-	else if (!strcmp(options, "device"))
-		otg_mode_host = 0;
-	else
-		pr_info("otg_mode neither \"host\" nor \"device\". "
-			"Defaulting to device\n");
-	return 0;
-}
-__setup("otg_mode=", eukrea_cpuimx25_otg_mode);
-
-static void __init eukrea_cpuimx25_init(void)
-{
-	if (mxc_iomux_v3_setup_multiple_pads(eukrea_cpuimx25_pads,
-			ARRAY_SIZE(eukrea_cpuimx25_pads)))
-		printk(KERN_ERR "error setting cpuimx25 pads !\n");
-
-	imx25_add_imx_uart0(&uart_pdata);
-	imx25_add_mxc_nand(&eukrea_cpuimx25_nand_board_info);
-	mxc_register_device(&mx25_rtc_device, NULL);
-	imx25_add_fec(&mx25_fec_pdata);
-
-	i2c_register_board_info(0, eukrea_cpuimx25_i2c_devices,
-				ARRAY_SIZE(eukrea_cpuimx25_i2c_devices));
-	imx25_add_imx_i2c0(&eukrea_cpuimx25_i2c0_data);
-
-	if (otg_mode_host)
-		mxc_register_device(&mxc_otg, &otg_pdata);
-	else
-		mxc_register_device(&otg_udc_device, &otg_device_pdata);
-
-	mxc_register_device(&mxc_usbh2, &usbh2_pdata);
-
-#ifdef CONFIG_MACH_EUKREA_MBIMXSD25_BASEBOARD
-	eukrea_mbimxsd25_baseboard_init();
-#endif
-}
-
-static void __init eukrea_cpuimx25_timer_init(void)
-{
-	mx25_clocks_init();
-}
-
-static struct sys_timer eukrea_cpuimx25_timer = {
-	.init   = eukrea_cpuimx25_timer_init,
-};
-
-MACHINE_START(EUKREA_CPUIMX25, "Eukrea CPUIMX25")
-	/* Maintainer: Eukrea Electromatique */
-	.boot_params    = MX25_PHYS_OFFSET + 0x100,
-	.map_io         = mx25_map_io,
-	.init_irq       = mx25_init_irq,
-	.init_machine   = eukrea_cpuimx25_init,
-	.timer          = &eukrea_cpuimx25_timer,
-MACHINE_END
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mx25/mach-mx25_3ds.c linux-libre-2.6.38-gnu1/arch/arm/mach-mx25/mach-mx25_3ds.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mx25/mach-mx25_3ds.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mx25/mach-mx25_3ds.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,225 +0,0 @@
-/*
- * Copyright 2009 Sascha Hauer, <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.
- */
-
-/*
- * This machine is known as:
- *  - i.MX25 3-Stack Development System
- *  - i.MX25 Platform Development Kit (i.MX25 PDK)
- */
-
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/clk.h>
-#include <linux/irq.h>
-#include <linux/gpio.h>
-#include <linux/platform_device.h>
-#include <linux/input/matrix_keypad.h>
-
-#include <mach/hardware.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/time.h>
-#include <asm/memory.h>
-#include <asm/mach/map.h>
-#include <mach/common.h>
-#include <mach/mx25.h>
-#include <mach/imxfb.h>
-#include <mach/iomux-mx25.h>
-
-#include "devices-imx25.h"
-#include "devices.h"
-
-static const struct imxuart_platform_data uart_pdata __initconst = {
-	.flags = IMXUART_HAVE_RTSCTS,
-};
-
-static struct pad_desc mx25pdk_pads[] = {
-	MX25_PAD_FEC_MDC__FEC_MDC,
-	MX25_PAD_FEC_MDIO__FEC_MDIO,
-	MX25_PAD_FEC_TDATA0__FEC_TDATA0,
-	MX25_PAD_FEC_TDATA1__FEC_TDATA1,
-	MX25_PAD_FEC_TX_EN__FEC_TX_EN,
-	MX25_PAD_FEC_RDATA0__FEC_RDATA0,
-	MX25_PAD_FEC_RDATA1__FEC_RDATA1,
-	MX25_PAD_FEC_RX_DV__FEC_RX_DV,
-	MX25_PAD_FEC_TX_CLK__FEC_TX_CLK,
-	MX25_PAD_A17__GPIO_2_3, /* FEC_EN, GPIO 35 */
-	MX25_PAD_D12__GPIO_4_8, /* FEC_RESET_B, GPIO 104 */
-
-	/* LCD */
-	MX25_PAD_LD0__LD0,
-	MX25_PAD_LD1__LD1,
-	MX25_PAD_LD2__LD2,
-	MX25_PAD_LD3__LD3,
-	MX25_PAD_LD4__LD4,
-	MX25_PAD_LD5__LD5,
-	MX25_PAD_LD6__LD6,
-	MX25_PAD_LD7__LD7,
-	MX25_PAD_LD8__LD8,
-	MX25_PAD_LD9__LD9,
-	MX25_PAD_LD10__LD10,
-	MX25_PAD_LD11__LD11,
-	MX25_PAD_LD12__LD12,
-	MX25_PAD_LD13__LD13,
-	MX25_PAD_LD14__LD14,
-	MX25_PAD_LD15__LD15,
-	MX25_PAD_GPIO_E__LD16,
-	MX25_PAD_GPIO_F__LD17,
-	MX25_PAD_HSYNC__HSYNC,
-	MX25_PAD_VSYNC__VSYNC,
-	MX25_PAD_LSCLK__LSCLK,
-	MX25_PAD_OE_ACD__OE_ACD,
-	MX25_PAD_CONTRAST__CONTRAST,
-
-	/* Keypad */
-	MX25_PAD_KPP_ROW0__KPP_ROW0,
-	MX25_PAD_KPP_ROW1__KPP_ROW1,
-	MX25_PAD_KPP_ROW2__KPP_ROW2,
-	MX25_PAD_KPP_ROW3__KPP_ROW3,
-	MX25_PAD_KPP_COL0__KPP_COL0,
-	MX25_PAD_KPP_COL1__KPP_COL1,
-	MX25_PAD_KPP_COL2__KPP_COL2,
-	MX25_PAD_KPP_COL3__KPP_COL3,
-
-	/* SD1 */
-	MX25_PAD_SD1_CMD__SD1_CMD,
-	MX25_PAD_SD1_CLK__SD1_CLK,
-	MX25_PAD_SD1_DATA0__SD1_DATA0,
-	MX25_PAD_SD1_DATA1__SD1_DATA1,
-	MX25_PAD_SD1_DATA2__SD1_DATA2,
-	MX25_PAD_SD1_DATA3__SD1_DATA3,
-};
-
-static const struct fec_platform_data mx25_fec_pdata __initconst = {
-        .phy    = PHY_INTERFACE_MODE_RMII,
-};
-
-#define FEC_ENABLE_GPIO		35
-#define FEC_RESET_B_GPIO	104
-
-static void __init mx25pdk_fec_reset(void)
-{
-	gpio_request(FEC_ENABLE_GPIO, "FEC PHY enable");
-	gpio_request(FEC_RESET_B_GPIO, "FEC PHY reset");
-
-	gpio_direction_output(FEC_ENABLE_GPIO, 0);  /* drop PHY power */
-	gpio_direction_output(FEC_RESET_B_GPIO, 0); /* assert reset */
-	udelay(2);
-
-	/* turn on PHY power and lift reset */
-	gpio_set_value(FEC_ENABLE_GPIO, 1);
-	gpio_set_value(FEC_RESET_B_GPIO, 1);
-}
-
-static const struct mxc_nand_platform_data
-mx25pdk_nand_board_info __initconst = {
-	.width		= 1,
-	.hw_ecc		= 1,
-	.flash_bbt	= 1,
-};
-
-static struct imx_fb_videomode mx25pdk_modes[] = {
-	{
-		.mode	= {
-			.name		= "CRT-VGA",
-			.refresh	= 60,
-			.xres		= 640,
-			.yres		= 480,
-			.pixclock	= 39683,
-			.left_margin	= 45,
-			.right_margin	= 114,
-			.upper_margin	= 33,
-			.lower_margin	= 11,
-			.hsync_len	= 1,
-			.vsync_len	= 1,
-		},
-		.bpp	= 16,
-		.pcr	= 0xFA208B80,
-	},
-};
-
-static struct imx_fb_platform_data mx25pdk_fb_pdata = {
-	.mode		= mx25pdk_modes,
-	.num_modes	= ARRAY_SIZE(mx25pdk_modes),
-	.pwmr		= 0x00A903FF,
-	.lscr1		= 0x00120300,
-	.dmacr		= 0x00020010,
-};
-
-static const uint32_t mx25pdk_keymap[] = {
-	KEY(0, 0, KEY_UP),
-	KEY(0, 1, KEY_DOWN),
-	KEY(0, 2, KEY_VOLUMEDOWN),
-	KEY(0, 3, KEY_HOME),
-	KEY(1, 0, KEY_RIGHT),
-	KEY(1, 1, KEY_LEFT),
-	KEY(1, 2, KEY_ENTER),
-	KEY(1, 3, KEY_VOLUMEUP),
-	KEY(2, 0, KEY_F6),
-	KEY(2, 1, KEY_F8),
-	KEY(2, 2, KEY_F9),
-	KEY(2, 3, KEY_F10),
-	KEY(3, 0, KEY_F1),
-	KEY(3, 1, KEY_F2),
-	KEY(3, 2, KEY_F3),
-	KEY(3, 3, KEY_POWER),
-};
-
-static struct matrix_keymap_data mx25pdk_keymap_data = {
-	.keymap		= mx25pdk_keymap,
-	.keymap_size	= ARRAY_SIZE(mx25pdk_keymap),
-};
-
-static void __init mx25pdk_init(void)
-{
-	mxc_iomux_v3_setup_multiple_pads(mx25pdk_pads,
-			ARRAY_SIZE(mx25pdk_pads));
-
-	imx25_add_imx_uart0(&uart_pdata);
-	mxc_register_device(&mxc_usbh2, NULL);
-	imx25_add_mxc_nand(&mx25pdk_nand_board_info);
-	mxc_register_device(&mx25_rtc_device, NULL);
-	mxc_register_device(&mx25_fb_device, &mx25pdk_fb_pdata);
-	mxc_register_device(&mxc_wdt, NULL);
-
-	mx25pdk_fec_reset();
-	imx25_add_fec(&mx25_fec_pdata);
-	mxc_register_device(&mx25_kpp_device, &mx25pdk_keymap_data);
-
-	imx25_add_esdhc(0, NULL);
-}
-
-static void __init mx25pdk_timer_init(void)
-{
-	mx25_clocks_init();
-}
-
-static struct sys_timer mx25pdk_timer = {
-	.init   = mx25pdk_timer_init,
-};
-
-MACHINE_START(MX25_3DS, "Freescale MX25PDK (3DS)")
-	/* Maintainer: Freescale Semiconductor, Inc. */
-	.boot_params    = MX25_PHYS_OFFSET + 0x100,
-	.map_io         = mx25_map_io,
-	.init_irq       = mx25_init_irq,
-	.init_machine   = mx25pdk_init,
-	.timer          = &mx25pdk_timer,
-MACHINE_END
-
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mx25/Makefile linux-libre-2.6.38-gnu1/arch/arm/mach-mx25/Makefile
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mx25/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mx25/Makefile	1969-12-31 19:00:00.000000000 -0500
@@ -1,5 +0,0 @@
-obj-y				:= mm.o devices.o
-obj-$(CONFIG_ARCH_MX25)		+= clock.o
-obj-$(CONFIG_MACH_MX25_3DS)	+= mach-mx25_3ds.o
-obj-$(CONFIG_MACH_EUKREA_CPUIMX25)		+= mach-cpuimx25.o
-obj-$(CONFIG_MACH_EUKREA_MBIMXSD25_BASEBOARD)	+= eukrea_mbimxsd-baseboard.o
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mx25/Makefile.boot linux-libre-2.6.38-gnu1/arch/arm/mach-mx25/Makefile.boot
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mx25/Makefile.boot	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mx25/Makefile.boot	1969-12-31 19:00:00.000000000 -0500
@@ -1,3 +0,0 @@
-   zreladdr-y	:= 0x80008000
-params_phys-y	:= 0x80000100
-initrd_phys-y	:= 0x80800000
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mx25/mm.c linux-libre-2.6.38-gnu1/arch/arm/mach-mx25/mm.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mx25/mm.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mx25/mm.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,75 +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/hardware.h>
-#include <mach/mx25.h>
-#include <mach/iomux-v3.h>
-
-/*
- * This table defines static virtual address mappings for I/O regions.
- * These are the mappings common across all MX3 boards.
- */
-static struct map_desc mxc_io_desc[] __initdata = {
-	{
-		.virtual	= MX25_AVIC_BASE_ADDR_VIRT,
-		.pfn		= __phys_to_pfn(MX25_AVIC_BASE_ADDR),
-		.length		= MX25_AVIC_SIZE,
-		.type		= MT_DEVICE_NONSHARED
-	}, {
-		.virtual	= MX25_AIPS1_BASE_ADDR_VIRT,
-		.pfn		= __phys_to_pfn(MX25_AIPS1_BASE_ADDR),
-		.length		= MX25_AIPS1_SIZE,
-		.type		= MT_DEVICE_NONSHARED
-	}, {
-		.virtual	= MX25_AIPS2_BASE_ADDR_VIRT,
-		.pfn		= __phys_to_pfn(MX25_AIPS2_BASE_ADDR),
-		.length		= MX25_AIPS2_SIZE,
-		.type		= 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 mx25_map_io(void)
-{
-	mxc_set_cpu_type(MXC_CPU_MX25);
-	mxc_iomux_v3_init(MX25_IO_ADDRESS(MX25_IOMUXC_BASE_ADDR));
-	mxc_arch_reset_init(MX25_IO_ADDRESS(MX25_WDOG_BASE_ADDR));
-
-	iotable_init(mxc_io_desc, ARRAY_SIZE(mxc_io_desc));
-}
-
-int imx25_register_gpios(void);
-
-void __init mx25_init_irq(void)
-{
-	mxc_init_irq((void __iomem *)MX25_AVIC_BASE_ADDR_VIRT);
-	imx25_register_gpios();
-}
-
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mx3/clock-imx31.c linux-libre-2.6.38-gnu1/arch/arm/mach-mx3/clock-imx31.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mx3/clock-imx31.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mx3/clock-imx31.c	2011-03-14 21:20:32.000000000 -0400
@@ -23,8 +23,8 @@
 #include <linux/clk.h>
 #include <linux/err.h>
 #include <linux/io.h>
+#include <linux/clkdev.h>
 
-#include <asm/clkdev.h>
 #include <asm/div64.h>
 
 #include <mach/clock.h>
@@ -530,7 +530,7 @@ static struct clk_lookup lookups[] = {
 	_REGISTER_CLOCK("imx31-cspi.2", NULL, cspi3_clk)
 	_REGISTER_CLOCK(NULL, "gpt", gpt_clk)
 	_REGISTER_CLOCK(NULL, "pwm", pwm_clk)
-	_REGISTER_CLOCK("imx-wdt.0", NULL, wdog_clk)
+	_REGISTER_CLOCK("imx2-wdt.0", NULL, wdog_clk)
 	_REGISTER_CLOCK(NULL, "rtc", rtc_clk)
 	_REGISTER_CLOCK(NULL, "epit", epit1_clk)
 	_REGISTER_CLOCK(NULL, "epit", epit2_clk)
@@ -615,7 +615,7 @@ int __init mx31_clocks_init(unsigned lon
 
 	mx31_read_cpu_rev();
 
-	if (mx31_revision() >= MX31_CHIP_REV_2_0) {
+	if (mx31_revision() >= IMX_CHIP_REVISION_2_0) {
 		reg = __raw_readl(MXC_CCM_PMCR1);
 		/* No PLL restart on DVFS switch; enable auto EMI handshake */
 		reg |= MXC_CCM_PMCR1_PLLRDIS | MXC_CCM_PMCR1_EMIRQ_EN;
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mx3/clock-imx35.c linux-libre-2.6.38-gnu1/arch/arm/mach-mx3/clock-imx35.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mx3/clock-imx35.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mx3/clock-imx35.c	2011-03-14 21:20:32.000000000 -0400
@@ -21,8 +21,7 @@
 #include <linux/list.h>
 #include <linux/clk.h>
 #include <linux/io.h>
-
-#include <asm/clkdev.h>
+#include <linux/clkdev.h>
 
 #include <mach/clock.h>
 #include <mach/hardware.h>
@@ -495,7 +494,7 @@ static struct clk_lookup lookups[] = {
 	_REGISTER_CLOCK("mxc-ehci.2", "usb", usbotg_clk)
 	_REGISTER_CLOCK("fsl-usb2-udc", "usb", usbotg_clk)
 	_REGISTER_CLOCK("fsl-usb2-udc", "usb_ahb", usbahb_clk)
-	_REGISTER_CLOCK("imx-wdt.0", NULL, wdog_clk)
+	_REGISTER_CLOCK("imx2-wdt.0", NULL, wdog_clk)
 	_REGISTER_CLOCK(NULL, "max", max_clk)
 	_REGISTER_CLOCK(NULL, "audmux", audmux_clk)
 	_REGISTER_CLOCK(NULL, "csi", csi_clk)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mx3/cpu.c linux-libre-2.6.38-gnu1/arch/arm/mach-mx3/cpu.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mx3/cpu.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mx3/cpu.c	2011-03-14 21:20:32.000000000 -0400
@@ -25,15 +25,15 @@ struct mx3_cpu_type {
 };
 
 static struct mx3_cpu_type mx31_cpu_type[] __initdata = {
-	{ .srev = 0x00, .name = "i.MX31(L)", .v = "1.0",  .rev = MX3x_CHIP_REV_1_0 },
-	{ .srev = 0x10, .name = "i.MX31",    .v = "1.1",  .rev = MX3x_CHIP_REV_1_1 },
-	{ .srev = 0x11, .name = "i.MX31L",   .v = "1.1",  .rev = MX3x_CHIP_REV_1_1 },
-	{ .srev = 0x12, .name = "i.MX31",    .v = "1.15", .rev = MX3x_CHIP_REV_1_1 },
-	{ .srev = 0x13, .name = "i.MX31L",   .v = "1.15", .rev = MX3x_CHIP_REV_1_1 },
-	{ .srev = 0x14, .name = "i.MX31",    .v = "1.2",  .rev = MX3x_CHIP_REV_1_2 },
-	{ .srev = 0x15, .name = "i.MX31L",   .v = "1.2",  .rev = MX3x_CHIP_REV_1_2 },
-	{ .srev = 0x28, .name = "i.MX31",    .v = "2.0",  .rev = MX3x_CHIP_REV_2_0 },
-	{ .srev = 0x29, .name = "i.MX31L",   .v = "2.0",  .rev = MX3x_CHIP_REV_2_0 },
+	{ .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	},
 };
 
 void __init mx31_read_cpu_rev(void)
@@ -53,6 +53,8 @@ void __init mx31_read_cpu_rev(void)
 			return;
 		}
 
+	mx31_cpu_rev = IMX_CHIP_REVISION_UNKNOWN;
+
 	printk(KERN_WARNING "Unknown CPU identifier. srev = %02x\n", srev);
 }
 
@@ -62,22 +64,25 @@ EXPORT_SYMBOL(mx35_cpu_rev);
 void __init mx35_read_cpu_rev(void)
 {
 	u32 rev;
-	char *srev = "unknown";
+	char *srev;
 
 	rev = __raw_readl(MX35_IO_ADDRESS(MX35_IIM_BASE_ADDR + MXC_IIMSREV));
 	switch (rev) {
 	case 0x00:
-		mx35_cpu_rev = MX3x_CHIP_REV_1_0;
+		mx35_cpu_rev = IMX_CHIP_REVISION_1_0;
 		srev = "1.0";
 		break;
 	case 0x10:
-		mx35_cpu_rev = MX3x_CHIP_REV_2_0;
+		mx35_cpu_rev = IMX_CHIP_REVISION_2_0;
 		srev = "2.0";
 		break;
 	case 0x11:
-		mx35_cpu_rev = MX3x_CHIP_REV_2_1;
+		mx35_cpu_rev = IMX_CHIP_REVISION_2_1;
 		srev = "2.1";
 		break;
+	default:
+		mx35_cpu_rev = IMX_CHIP_REVISION_UNKNOWN;
+		srev = "unknown";
 	}
 
 	printk(KERN_INFO "CPU identified as i.MX35, silicon rev %s\n", srev);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mx3/devices.c linux-libre-2.6.38-gnu1/arch/arm/mach-mx3/devices.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mx3/devices.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mx3/devices.c	2011-03-14 21:20:32.000000000 -0400
@@ -29,120 +29,25 @@
 
 #include "devices.h"
 
-/* GPIO port description */
-static struct mxc_gpio_port imx_gpio_ports[] = {
-	{
-		.chip.label = "gpio-0",
-		.base = IO_ADDRESS(GPIO1_BASE_ADDR),
-		.irq = MXC_INT_GPIO1,
-		.virtual_irq_start = MXC_GPIO_IRQ_START,
-	}, {
-		.chip.label = "gpio-1",
-		.base = IO_ADDRESS(GPIO2_BASE_ADDR),
-		.irq = MXC_INT_GPIO2,
-		.virtual_irq_start = MXC_GPIO_IRQ_START + 32,
-	}, {
-		.chip.label = "gpio-2",
-		.base = IO_ADDRESS(GPIO3_BASE_ADDR),
-		.irq = MXC_INT_GPIO3,
-		.virtual_irq_start = MXC_GPIO_IRQ_START + 64,
-	}
-};
-
-int __init imx3x_register_gpios(void)
-{
-	return mxc_gpio_init(imx_gpio_ports, ARRAY_SIZE(imx_gpio_ports));
-}
-
-static struct resource mxc_w1_master_resources[] = {
-	{
-		.start = OWIRE_BASE_ADDR,
-		.end   = OWIRE_BASE_ADDR + SZ_4K - 1,
-		.flags = IORESOURCE_MEM,
-	},
-};
-
-struct platform_device mxc_w1_master_device = {
-	.name = "mxc_w1",
-	.id = 0,
-	.num_resources = ARRAY_SIZE(mxc_w1_master_resources),
-	.resource = mxc_w1_master_resources,
-};
-
-#ifdef CONFIG_ARCH_MX31
-static struct resource mxcsdhc0_resources[] = {
-	{
-		.start = MX31_MMC_SDHC1_BASE_ADDR,
-		.end = MX31_MMC_SDHC1_BASE_ADDR + SZ_16K - 1,
-		.flags = IORESOURCE_MEM,
-	}, {
-		.start = MX31_INT_MMC_SDHC1,
-		.end = MX31_INT_MMC_SDHC1,
-		.flags = IORESOURCE_IRQ,
-	},
-};
-
-static struct resource mxcsdhc1_resources[] = {
-	{
-		.start = MX31_MMC_SDHC2_BASE_ADDR,
-		.end = MX31_MMC_SDHC2_BASE_ADDR + SZ_16K - 1,
-		.flags = IORESOURCE_MEM,
-	}, {
-		.start = MX31_INT_MMC_SDHC2,
-		.end = MX31_INT_MMC_SDHC2,
-		.flags = IORESOURCE_IRQ,
-	},
-};
-
-struct platform_device mxcsdhc_device0 = {
-	.name = "mxc-mmc",
-	.id = 0,
-	.num_resources = ARRAY_SIZE(mxcsdhc0_resources),
-	.resource = mxcsdhc0_resources,
-};
-
-struct platform_device mxcsdhc_device1 = {
-	.name = "mxc-mmc",
-	.id = 1,
-	.num_resources = ARRAY_SIZE(mxcsdhc1_resources),
-	.resource = mxcsdhc1_resources,
-};
-
-static struct resource rnga_resources[] = {
-	{
-		.start = RNGA_BASE_ADDR,
-		.end = RNGA_BASE_ADDR + 0x28,
-		.flags = IORESOURCE_MEM,
-	},
-};
-
-struct platform_device mxc_rnga_device = {
-	.name = "mxc_rnga",
-	.id = -1,
-	.num_resources = 1,
-	.resource = rnga_resources,
-};
-#endif /* CONFIG_ARCH_MX31 */
-
 /* i.MX31 Image Processing Unit */
 
 /* The resource order is important! */
 static struct resource mx3_ipu_rsrc[] = {
 	{
-		.start = IPU_CTRL_BASE_ADDR,
-		.end = IPU_CTRL_BASE_ADDR + 0x5F,
+		.start = MX3x_IPU_CTRL_BASE_ADDR,
+		.end = MX3x_IPU_CTRL_BASE_ADDR + 0x5F,
 		.flags = IORESOURCE_MEM,
 	}, {
-		.start = IPU_CTRL_BASE_ADDR + 0x88,
-		.end = IPU_CTRL_BASE_ADDR + 0xB3,
+		.start = MX3x_IPU_CTRL_BASE_ADDR + 0x88,
+		.end = MX3x_IPU_CTRL_BASE_ADDR + 0xB3,
 		.flags = IORESOURCE_MEM,
 	}, {
-		.start = MXC_INT_IPU_SYN,
-		.end = MXC_INT_IPU_SYN,
+		.start = MX3x_INT_IPU_SYN,
+		.end = MX3x_INT_IPU_SYN,
 		.flags = IORESOURCE_IRQ,
 	}, {
-		.start = MXC_INT_IPU_ERR,
-		.end = MXC_INT_IPU_ERR,
+		.start = MX3x_INT_IPU_ERR,
+		.end = MX3x_INT_IPU_ERR,
 		.flags = IORESOURCE_IRQ,
 	},
 };
@@ -156,8 +61,8 @@ struct platform_device mx3_ipu = {
 
 static struct resource fb_resources[] = {
 	{
-		.start	= IPU_CTRL_BASE_ADDR + 0xB4,
-		.end	= IPU_CTRL_BASE_ADDR + 0x1BF,
+		.start	= MX3x_IPU_CTRL_BASE_ADDR + 0xB4,
+		.end	= MX3x_IPU_CTRL_BASE_ADDR + 0x1BF,
 		.flags	= IORESOURCE_MEM,
 	},
 };
@@ -174,8 +79,8 @@ struct platform_device mx3_fb = {
 
 static struct resource camera_resources[] = {
 	{
-		.start	= IPU_CTRL_BASE_ADDR + 0x60,
-		.end	= IPU_CTRL_BASE_ADDR + 0x87,
+		.start	= MX3x_IPU_CTRL_BASE_ADDR + 0x60,
+		.end	= MX3x_IPU_CTRL_BASE_ADDR + 0x87,
 		.flags	= IORESOURCE_MEM,
 	},
 };
@@ -190,110 +95,6 @@ struct platform_device mx3_camera = {
 	},
 };
 
-static struct resource otg_resources[] = {
-	{
-		.start	= MX31_OTG_BASE_ADDR,
-		.end	= MX31_OTG_BASE_ADDR + 0x1ff,
-		.flags	= IORESOURCE_MEM,
-	}, {
-		.start	= MXC_INT_USB3,
-		.end	= MXC_INT_USB3,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static u64 otg_dmamask = DMA_BIT_MASK(32);
-
-/* OTG gadget device */
-struct platform_device mxc_otg_udc_device = {
-	.name		= "fsl-usb2-udc",
-	.id		= -1,
-	.dev		= {
-		.dma_mask		= &otg_dmamask,
-		.coherent_dma_mask	= DMA_BIT_MASK(32),
-	},
-	.resource	= otg_resources,
-	.num_resources	= ARRAY_SIZE(otg_resources),
-};
-
-/* OTG host */
-struct platform_device mxc_otg_host = {
-	.name = "mxc-ehci",
-	.id = 0,
-	.dev = {
-		.coherent_dma_mask = 0xffffffff,
-		.dma_mask = &otg_dmamask,
-	},
-	.resource = otg_resources,
-	.num_resources = ARRAY_SIZE(otg_resources),
-};
-
-/* USB host 1 */
-
-static u64 usbh1_dmamask = ~(u32)0;
-
-static struct resource mxc_usbh1_resources[] = {
-	{
-		.start = MX31_OTG_BASE_ADDR + 0x200,
-		.end = MX31_OTG_BASE_ADDR + 0x3ff,
-		.flags = IORESOURCE_MEM,
-	}, {
-		.start = MXC_INT_USB1,
-		.end = MXC_INT_USB1,
-		.flags = IORESOURCE_IRQ,
-	},
-};
-
-struct platform_device mxc_usbh1 = {
-	.name = "mxc-ehci",
-	.id = 1,
-	.dev = {
-		.coherent_dma_mask = 0xffffffff,
-		.dma_mask = &usbh1_dmamask,
-	},
-	.resource = mxc_usbh1_resources,
-	.num_resources = ARRAY_SIZE(mxc_usbh1_resources),
-};
-
-/* USB host 2 */
-static u64 usbh2_dmamask = ~(u32)0;
-
-static struct resource mxc_usbh2_resources[] = {
-	{
-		.start = MX31_OTG_BASE_ADDR + 0x400,
-		.end = MX31_OTG_BASE_ADDR + 0x5ff,
-		.flags = IORESOURCE_MEM,
-	}, {
-		.start = MXC_INT_USB2,
-		.end = MXC_INT_USB2,
-		.flags = IORESOURCE_IRQ,
-	},
-};
-
-struct platform_device mxc_usbh2 = {
-	.name = "mxc-ehci",
-	.id = 2,
-	.dev = {
-		.coherent_dma_mask = 0xffffffff,
-		.dma_mask = &usbh2_dmamask,
-	},
-	.resource = mxc_usbh2_resources,
-	.num_resources = ARRAY_SIZE(mxc_usbh2_resources),
-};
-
-static struct resource imx_wdt_resources[] = {
-	{
-		.flags = IORESOURCE_MEM,
-	},
-};
-
-struct platform_device imx_wdt_device0 = {
-	.name           = "imx2-wdt",
-	.id             = 0,
-	.num_resources  = ARRAY_SIZE(imx_wdt_resources),
-	.resource       = imx_wdt_resources,
-};
-
 static struct resource imx_rtc_resources[] = {
 	{
 		.start  = MX31_RTC_BASE_ADDR,
@@ -312,51 +113,3 @@ struct platform_device imx_rtc_device0 =
 	.num_resources  = ARRAY_SIZE(imx_rtc_resources),
 	.resource       = imx_rtc_resources,
 };
-
-static struct resource imx_kpp_resources[] = {
-	{
-		.start	= MX3x_KPP_BASE_ADDR,
-		.end	= MX3x_KPP_BASE_ADDR + 0xf,
-		.flags	= IORESOURCE_MEM
-	}, {
-		.start	= MX3x_INT_KPP,
-		.end	= MX3x_INT_KPP,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-struct platform_device imx_kpp_device = {
-	.name = "imx-keypad",
-	.id = -1,
-	.num_resources = ARRAY_SIZE(imx_kpp_resources),
-	.resource = imx_kpp_resources,
-};
-
-static int __init mx3_devices_init(void)
-{
-#if defined(CONFIG_ARCH_MX31)
-	if (cpu_is_mx31()) {
-		imx_wdt_resources[0].start = MX31_WDOG_BASE_ADDR;
-		imx_wdt_resources[0].end = MX31_WDOG_BASE_ADDR + 0x3fff;
-		mxc_register_device(&mxc_rnga_device, NULL);
-	}
-#endif
-#if defined(CONFIG_ARCH_MX35)
-	if (cpu_is_mx35()) {
-		otg_resources[0].start = MX35_OTG_BASE_ADDR;
-		otg_resources[0].end = MX35_OTG_BASE_ADDR + 0x1ff;
-		otg_resources[1].start = MXC_INT_USBOTG;
-		otg_resources[1].end = MXC_INT_USBOTG;
-		mxc_usbh1_resources[0].start = MX35_OTG_BASE_ADDR + 0x400;
-		mxc_usbh1_resources[0].end = MX35_OTG_BASE_ADDR + 0x5ff;
-		mxc_usbh1_resources[1].start = MXC_INT_USBHS;
-		mxc_usbh1_resources[1].end = MXC_INT_USBHS;
-		imx_wdt_resources[0].start = MX35_WDOG_BASE_ADDR;
-		imx_wdt_resources[0].end = MX35_WDOG_BASE_ADDR + 0x3fff;
-	}
-#endif
-
-	return 0;
-}
-
-subsys_initcall(mx3_devices_init);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mx3/devices.h linux-libre-2.6.38-gnu1/arch/arm/mach-mx3/devices.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mx3/devices.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mx3/devices.h	2011-03-14 21:20:32.000000000 -0400
@@ -1,14 +1,4 @@
-extern struct platform_device mxc_w1_master_device;
 extern struct platform_device mx3_ipu;
 extern struct platform_device mx3_fb;
 extern struct platform_device mx3_camera;
-extern struct platform_device mxcsdhc_device0;
-extern struct platform_device mxcsdhc_device1;
-extern struct platform_device mxc_otg_udc_device;
-extern struct platform_device mxc_otg_host;
-extern struct platform_device mxc_usbh1;
-extern struct platform_device mxc_usbh2;
-extern struct platform_device mxc_rnga_device;
-extern struct platform_device imx_wdt_device0;
 extern struct platform_device imx_rtc_device0;
-extern struct platform_device imx_kpp_device;
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mx3/devices-imx31.h linux-libre-2.6.38-gnu1/arch/arm/mach-mx3/devices-imx31.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mx3/devices-imx31.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mx3/devices-imx31.h	2011-03-14 21:20:32.000000000 -0400
@@ -9,6 +9,14 @@
 #include <mach/mx31.h>
 #include <mach/devices-common.h>
 
+extern const struct imx_fsl_usb2_udc_data imx31_fsl_usb2_udc_data __initconst;
+#define imx31_add_fsl_usb2_udc(pdata)	\
+	imx_add_fsl_usb2_udc(&imx31_fsl_usb2_udc_data, pdata)
+
+extern const struct imx_imx2_wdt_data imx31_imx2_wdt_data __initconst;
+#define imx31_add_imx2_wdt(pdata)       \
+	imx_add_imx2_wdt(&imx31_imx2_wdt_data)
+
 extern const struct imx_imx_i2c_data imx31_imx_i2c_data[] __initconst;
 #define imx31_add_imx_i2c(id, pdata)	\
 	imx_add_imx_i2c(&imx31_imx_i2c_data[id], pdata)
@@ -16,6 +24,10 @@ extern const struct imx_imx_i2c_data imx
 #define imx31_add_imx_i2c1(pdata)	imx31_add_imx_i2c(1, pdata)
 #define imx31_add_imx_i2c2(pdata)	imx31_add_imx_i2c(2, pdata)
 
+extern const struct imx_imx_keypad_data imx31_imx_keypad_data __initconst;
+#define imx31_add_imx_keypad(pdata)	\
+	imx_add_imx_keypad(&imx31_imx_keypad_data, pdata)
+
 extern const struct imx_imx_ssi_data imx31_imx_ssi_data[] __initconst;
 #define imx31_add_imx_ssi(id, pdata)    \
 	imx_add_imx_ssi(&imx31_imx_ssi_data[id], pdata)
@@ -29,10 +41,25 @@ extern const struct imx_imx_uart_1irq_da
 #define imx31_add_imx_uart3(pdata)	imx31_add_imx_uart(3, pdata)
 #define imx31_add_imx_uart4(pdata)	imx31_add_imx_uart(4, pdata)
 
+extern const struct imx_mxc_ehci_data imx31_mxc_ehci_otg_data __initconst;
+#define imx31_add_mxc_ehci_otg(pdata)	\
+	imx_add_mxc_ehci(&imx31_mxc_ehci_otg_data, pdata)
+extern const struct imx_mxc_ehci_data imx31_mxc_ehci_hs_data[] __initconst;
+#define imx31_add_mxc_ehci_hs(id, pdata)	\
+	imx_add_mxc_ehci(&imx31_mxc_ehci_hs_data[id - 1], pdata)
+
+extern const struct imx_mxc_mmc_data imx31_mxc_mmc_data[] __initconst;
+#define imx31_add_mxc_mmc(id, pdata)	\
+	imx_add_mxc_mmc(&imx31_mxc_mmc_data[id], pdata)
+
 extern const struct imx_mxc_nand_data imx31_mxc_nand_data __initconst;
 #define imx31_add_mxc_nand(pdata)	\
 	imx_add_mxc_nand(&imx31_mxc_nand_data, pdata)
 
+extern const struct imx_mxc_w1_data imx31_mxc_w1_data __initconst;
+#define imx31_add_mxc_w1(pdata)	\
+	imx_add_mxc_w1(&imx31_mxc_w1_data)
+
 extern const struct imx_spi_imx_data imx31_cspi_data[] __initconst;
 #define imx31_add_cspi(id, pdata)	\
 	imx_add_spi_imx(&imx31_cspi_data[id], pdata)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mx3/devices-imx35.h linux-libre-2.6.38-gnu1/arch/arm/mach-mx3/devices-imx35.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mx3/devices-imx35.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mx3/devices-imx35.h	2011-03-14 21:20:32.000000000 -0400
@@ -13,10 +13,19 @@ extern const struct imx_fec_data imx35_f
 #define imx35_add_fec(pdata)	\
 	imx_add_fec(&imx35_fec_data, pdata)
 
-#define imx35_add_flexcan0(pdata)	\
-	imx_add_flexcan(0, MX35_CAN1_BASE_ADDR, SZ_16K, MX35_INT_CAN1, pdata)
-#define imx35_add_flexcan1(pdata)	\
-	imx_add_flexcan(1, MX35_CAN2_BASE_ADDR, SZ_16K, MX35_INT_CAN2, pdata)
+extern const struct imx_fsl_usb2_udc_data imx35_fsl_usb2_udc_data __initconst;
+#define imx35_add_fsl_usb2_udc(pdata)	\
+	imx_add_fsl_usb2_udc(&imx35_fsl_usb2_udc_data, pdata)
+
+extern const struct imx_flexcan_data imx35_flexcan_data[] __initconst;
+#define imx35_add_flexcan(id, pdata)	\
+	imx_add_flexcan(&imx35_flexcan_data[id], pdata)
+#define imx35_add_flexcan0(pdata)	imx35_add_flexcan(0, pdata)
+#define imx35_add_flexcan1(pdata)	imx35_add_flexcan(1, pdata)
+
+extern const struct imx_imx2_wdt_data imx35_imx2_wdt_data __initconst;
+#define imx35_add_imx2_wdt(pdata)       \
+	imx_add_imx2_wdt(&imx35_imx2_wdt_data)
 
 extern const struct imx_imx_i2c_data imx35_imx_i2c_data[] __initconst;
 #define imx35_add_imx_i2c(id, pdata)	\
@@ -25,6 +34,10 @@ extern const struct imx_imx_i2c_data imx
 #define imx35_add_imx_i2c1(pdata)	imx35_add_imx_i2c(1, pdata)
 #define imx35_add_imx_i2c2(pdata)	imx35_add_imx_i2c(2, pdata)
 
+extern const struct imx_imx_keypad_data imx35_imx_keypad_data __initconst;
+#define imx31_add_imx_keypad(pdata)	\
+	imx_add_imx_keypad(&imx35_imx_keypad_data, pdata)
+
 extern const struct imx_imx_ssi_data imx35_imx_ssi_data[] __initconst;
 #define imx35_add_imx_ssi(id, pdata)    \
 	imx_add_imx_ssi(&imx35_imx_ssi_data[id], pdata)
@@ -36,16 +49,28 @@ extern const struct imx_imx_uart_1irq_da
 #define imx35_add_imx_uart1(pdata)	imx35_add_imx_uart(1, pdata)
 #define imx35_add_imx_uart2(pdata)	imx35_add_imx_uart(2, pdata)
 
+extern const struct imx_mxc_ehci_data imx35_mxc_ehci_otg_data __initconst;
+#define imx35_add_mxc_ehci_otg(pdata)	\
+	imx_add_mxc_ehci(&imx35_mxc_ehci_otg_data, pdata)
+extern const struct imx_mxc_ehci_data imx35_mxc_ehci_hs_data __initconst;
+#define imx35_add_mxc_ehci_hs(pdata)	\
+	imx_add_mxc_ehci(&imx35_mxc_ehci_hs_data, pdata)
+
 extern const struct imx_mxc_nand_data imx35_mxc_nand_data __initconst;
 #define imx35_add_mxc_nand(pdata)	\
 	imx_add_mxc_nand(&imx35_mxc_nand_data, pdata)
 
+extern const struct imx_mxc_w1_data imx35_mxc_w1_data __initconst;
+#define imx35_add_mxc_w1(pdata)	\
+	imx_add_mxc_w1(&imx35_mxc_w1_data)
+
+extern const struct imx_sdhci_esdhc_imx_data
+imx35_sdhci_esdhc_imx_data[] __initconst;
+#define imx35_add_sdhci_esdhc_imx(id, pdata)	\
+	imx_add_sdhci_esdhc_imx(&imx35_sdhci_esdhc_imx_data[id], pdata)
+
 extern const struct imx_spi_imx_data imx35_cspi_data[] __initconst;
 #define imx35_add_cspi(id, pdata)	\
 	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_esdhc_imx_data imx35_esdhc_data[] __initconst;
-#define imx35_add_esdhc(id, pdata)	\
-	imx_add_esdhc(&imx35_esdhc_data[id], pdata)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mx3/eukrea_mbimxsd-baseboard.c linux-libre-2.6.38-gnu1/arch/arm/mach-mx3/eukrea_mbimxsd-baseboard.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mx3/eukrea_mbimxsd-baseboard.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mx3/eukrea_mbimxsd-baseboard.c	2011-03-14 21:20:32.000000000 -0400
@@ -111,7 +111,7 @@ static struct mx3fb_platform_data mx3fb_
 	.num_modes	= ARRAY_SIZE(fb_modedb),
 };
 
-static struct pad_desc eukrea_mbimxsd_pads[] = {
+static iomux_v3_cfg_t eukrea_mbimxsd_pads[] = {
 	/* LCD */
 	MX35_PAD_LD0__IPU_DISPB_DAT_0,
 	MX35_PAD_LD1__IPU_DISPB_DAT_1,
@@ -289,7 +289,7 @@ void __init eukrea_mbimxsd35_baseboard_i
 	imx35_add_imx_ssi(0, &eukrea_mbimxsd_ssi_pdata);
 
 	imx35_add_flexcan1(NULL);
-	imx35_add_esdhc(0, NULL);
+	imx35_add_sdhci_esdhc_imx(0, NULL);
 
 	gpio_request(GPIO_LED1, "LED1");
 	gpio_direction_output(GPIO_LED1, 1);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mx3/Kconfig linux-libre-2.6.38-gnu1/arch/arm/mach-mx3/Kconfig
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mx3/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mx3/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -1,21 +1,35 @@
 if ARCH_MX3
 
+# 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
-	select ARCH_HAS_RNGA
-	select ARCH_MXC_AUDMUX_V2
 	bool
 
 config ARCH_MX35
 	bool
+
+config SOC_IMX31
+	bool
+	select IMX_HAVE_PLATFORM_MXC_RNGA
+	select ARCH_MXC_AUDMUX_V2
+	select ARCH_MX31
+	select MXC_AVIC
+
+config SOC_IMX35
+	bool
 	select ARCH_MXC_IOMUX_V3
 	select ARCH_MXC_AUDMUX_V2
 	select HAVE_EPIT
+	select ARCH_MX35
+	select MXC_AVIC
 
 comment "MX3 platforms:"
 
 config MACH_MX31ADS
 	bool "Support MX31ADS platforms"
-	select ARCH_MX31
+	select SOC_IMX31
 	select IMX_HAVE_PLATFORM_IMX_I2C
 	select IMX_HAVE_PLATFORM_IMX_SSI
 	select IMX_HAVE_PLATFORM_IMX_UART
@@ -37,10 +51,15 @@ config MACH_MX31ADS_WM1133_EV1
 
 config MACH_PCM037
 	bool "Support Phytec pcm037 (i.MX31) platforms"
-	select ARCH_MX31
+	select SOC_IMX31
+	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_MXC_MMC
 	select IMX_HAVE_PLATFORM_MXC_NAND
+	select IMX_HAVE_PLATFORM_MXC_W1
 	select MXC_ULPI if USB_ULPI
 	help
 	  Include support for Phytec pcm037 platform. This includes
@@ -57,9 +76,12 @@ config MACH_PCM037_EET
 
 config MACH_MX31LITE
 	bool "Support MX31 LITEKIT (LogicPD)"
-	select ARCH_MX31
+	select SOC_IMX31
 	select MXC_ULPI if USB_ULPI
+	select IMX_HAVE_PLATFORM_IMX2_WDT
 	select IMX_HAVE_PLATFORM_IMX_UART
+	select IMX_HAVE_PLATFORM_MXC_EHCI
+	select IMX_HAVE_PLATFORM_MXC_MMC
 	select IMX_HAVE_PLATFORM_MXC_NAND
 	select IMX_HAVE_PLATFORM_SPI_IMX
 	help
@@ -68,11 +90,16 @@ config MACH_MX31LITE
 
 config MACH_MX31_3DS
 	bool "Support MX31PDK (3DS)"
-	select ARCH_MX31
+	select SOC_IMX31
 	select MXC_DEBUG_BOARD
+	select IMX_HAVE_PLATFORM_FSL_USB2_UDC
+	select IMX_HAVE_PLATFORM_IMX2_WDT
+	select IMX_HAVE_PLATFORM_IMX_KEYPAD
 	select IMX_HAVE_PLATFORM_IMX_UART
+	select IMX_HAVE_PLATFORM_MXC_EHCI
 	select IMX_HAVE_PLATFORM_MXC_NAND
 	select IMX_HAVE_PLATFORM_SPI_IMX
+	select MXC_ULPI if USB_ULPI
 	help
 	  Include support for MX31PDK (3DS) platform. This includes specific
 	  configurations for the board and its peripherals.
@@ -88,9 +115,12 @@ config MACH_MX31_3DS_MXC_NAND_USE_BBT
 
 config MACH_MX31MOBOARD
 	bool "Support mx31moboard platforms (EPFL Mobots group)"
-	select ARCH_MX31
+	select SOC_IMX31
+	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_MMC
 	select IMX_HAVE_PLATFORM_SPI_IMX
 	select MXC_ULPI if USB_ULPI
 	help
@@ -99,8 +129,10 @@ config MACH_MX31MOBOARD
 
 config MACH_MX31LILLY
 	bool "Support MX31 LILLY-1131 platforms (INCO startec)"
-	select ARCH_MX31
+	select SOC_IMX31
 	select IMX_HAVE_PLATFORM_IMX_UART
+	select IMX_HAVE_PLATFORM_MXC_EHCI
+	select IMX_HAVE_PLATFORM_MXC_MMC
 	select IMX_HAVE_PLATFORM_SPI_IMX
 	select MXC_ULPI if USB_ULPI
 	help
@@ -109,7 +141,7 @@ config MACH_MX31LILLY
 
 config MACH_QONG
 	bool "Support Dave/DENX QongEVB-LITE platform"
-	select ARCH_MX31
+	select SOC_IMX31
 	select IMX_HAVE_PLATFORM_IMX_UART
 	help
 	  Include support for Dave/DENX QongEVB-LITE platform. This includes
@@ -117,13 +149,16 @@ config MACH_QONG
 
 config MACH_PCM043
 	bool "Support Phytec pcm043 (i.MX35) platforms"
-	select ARCH_MX35
+	select SOC_IMX35
+	select IMX_HAVE_PLATFORM_FLEXCAN
+	select IMX_HAVE_PLATFORM_FSL_USB2_UDC
+	select IMX_HAVE_PLATFORM_IMX2_WDT
 	select IMX_HAVE_PLATFORM_IMX_I2C
 	select IMX_HAVE_PLATFORM_IMX_SSI
 	select IMX_HAVE_PLATFORM_IMX_UART
+	select IMX_HAVE_PLATFORM_MXC_EHCI
 	select IMX_HAVE_PLATFORM_MXC_NAND
-	select IMX_HAVE_PLATFORM_FLEXCAN
-	select IMX_HAVE_PLATFORM_ESDHC
+	select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
 	select MXC_ULPI if USB_ULPI
 	help
 	  Include support for Phytec pcm043 platform. This includes
@@ -131,9 +166,11 @@ config MACH_PCM043
 
 config MACH_ARMADILLO5X0
 	bool "Support Atmark Armadillo-500 Development Base Board"
-	select ARCH_MX31
+	select SOC_IMX31
 	select IMX_HAVE_PLATFORM_IMX_I2C
 	select IMX_HAVE_PLATFORM_IMX_UART
+	select IMX_HAVE_PLATFORM_MXC_EHCI
+	select IMX_HAVE_PLATFORM_MXC_MMC
 	select IMX_HAVE_PLATFORM_MXC_NAND
 	select MXC_ULPI if USB_ULPI
 	help
@@ -142,19 +179,21 @@ config MACH_ARMADILLO5X0
 
 config MACH_MX35_3DS
 	bool "Support MX35PDK platform"
-	select ARCH_MX35
+	select SOC_IMX35
 	select MXC_DEBUG_BOARD
+	select IMX_HAVE_PLATFORM_FSL_USB2_UDC
+	select IMX_HAVE_PLATFORM_IMX2_WDT
 	select IMX_HAVE_PLATFORM_IMX_UART
+	select IMX_HAVE_PLATFORM_MXC_EHCI
 	select IMX_HAVE_PLATFORM_MXC_NAND
-	select IMX_HAVE_PLATFORM_ESDHC
-	default n
+	select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
 	help
 	  Include support for MX35PDK platform. This includes specific
 	  configurations for the board and its peripherals.
 
 config MACH_KZM_ARM11_01
 	bool "Support KZM-ARM11-01(Kyoto Microcomputer)"
-	select ARCH_MX31
+	select SOC_IMX31
 	select IMX_HAVE_PLATFORM_IMX_UART
 	help
 	  Include support for KZM-ARM11-01. This includes specific
@@ -162,12 +201,15 @@ config MACH_KZM_ARM11_01
 
 config MACH_EUKREA_CPUIMX35
 	bool "Support Eukrea CPUIMX35 Platform"
-	select ARCH_MX35
-	select IMX_HAVE_PLATFORM_IMX_UART
+	select SOC_IMX35
+	select IMX_HAVE_PLATFORM_FLEXCAN
+	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_MXC_NAND
-	select IMX_HAVE_PLATFORM_FLEXCAN
-	select IMX_HAVE_PLATFORM_ESDHC
+	select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
 	select MXC_ULPI if USB_ULPI
 	help
 	  Include support for Eukrea CPUIMX35 platform. This includes
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mx3/mach-armadillo5x0.c linux-libre-2.6.38-gnu1/arch/arm/mach-mx3/mach-armadillo5x0.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mx3/mach-armadillo5x0.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mx3/mach-armadillo5x0.c	2011-03-14 21:20:32.000000000 -0400
@@ -49,10 +49,8 @@
 
 #include <mach/common.h>
 #include <mach/iomux-mx3.h>
-#include <mach/mmc.h>
 #include <mach/ipu.h>
 #include <mach/mx3fb.h>
-#include <mach/mxc_ehci.h>
 #include <mach/ulpi.h>
 
 #include "devices-imx31.h"
@@ -245,13 +243,13 @@ h2_free_cs:
 	return err;
 }
 
-static struct mxc_usbh_platform_data usbotg_pdata = {
+static struct mxc_usbh_platform_data usbotg_pdata __initdata = {
 	.init	= usbotg_init,
 	.portsc	= MXC_EHCI_MODE_ULPI | MXC_EHCI_UTMI_8BIT,
 	.flags	= MXC_EHCI_POWER_PINS_ENABLED | MXC_EHCI_INTERFACE_DIFF_UNI,
 };
 
-static struct mxc_usbh_platform_data usbh2_pdata = {
+static struct mxc_usbh_platform_data usbh2_pdata __initdata = {
 	.init	= usbh2_init,
 	.portsc	= MXC_EHCI_MODE_ULPI | MXC_EHCI_UTMI_8BIT,
 	.flags	= MXC_EHCI_POWER_PINS_ENABLED | MXC_EHCI_INTERFACE_DIFF_UNI,
@@ -453,7 +451,7 @@ static void armadillo5x0_sdhc1_exit(stru
 	gpio_free(IOMUX_TO_GPIO(MX31_PIN_ATA_RESET_B));
 }
 
-static struct imxmmc_platform_data sdhc_pdata = {
+static const struct imxmmc_platform_data sdhc_pdata __initconst = {
 	.get_ro = armadillo5x0_sdhc1_get_ro,
 	.init = armadillo5x0_sdhc1_init,
 	.exit = armadillo5x0_sdhc1_exit,
@@ -520,7 +518,7 @@ static void __init armadillo5x0_init(voi
 	gpio_direction_input(MX31_PIN_GPIO1_0);
 
 	/* Register SDHC */
-	mxc_register_device(&mxcsdhc_device0, &sdhc_pdata);
+	imx31_add_mxc_mmc(0, &sdhc_pdata);
 
 	/* Register FB */
 	mxc_register_device(&mx3_ipu, &mx3_ipu_data);
@@ -555,8 +553,8 @@ static void __init armadillo5x0_init(voi
 	usbh2_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops,
 			ULPI_OTG_DRVVBUS | ULPI_OTG_DRVVBUS_EXT);
 
-	mxc_register_device(&mxc_otg_host, &usbotg_pdata);
-	mxc_register_device(&mxc_usbh2, &usbh2_pdata);
+	imx31_add_mxc_ehci_otg(&usbotg_pdata);
+	imx31_add_mxc_ehci_hs(2, &usbh2_pdata);
 #endif
 }
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mx3/mach-cpuimx35.c linux-libre-2.6.38-gnu1/arch/arm/mach-mx3/mach-cpuimx35.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mx3/mach-cpuimx35.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mx3/mach-cpuimx35.c	2011-03-14 21:20:32.000000000 -0400
@@ -30,7 +30,6 @@
 #include <linux/i2c/tsc2007.h>
 #include <linux/usb/otg.h>
 #include <linux/usb/ulpi.h>
-#include <linux/fsl_devices.h>
 #include <linux/i2c-gpio.h>
 
 #include <asm/mach-types.h>
@@ -43,7 +42,6 @@
 #include <mach/common.h>
 #include <mach/iomux-mx35.h>
 #include <mach/mxc_nand.h>
-#include <mach/mxc_ehci.h>
 
 #include "devices-imx35.h"
 #include "devices.h"
@@ -74,11 +72,7 @@ static struct i2c_board_info eukrea_cpui
 	},
 };
 
-static struct platform_device *devices[] __initdata = {
-	&imx_wdt_device0,
-};
-
-static struct pad_desc eukrea_cpuimx35_pads[] = {
+static iomux_v3_cfg_t eukrea_cpuimx35_pads[] = {
 	/* UART1 */
 	MX35_PAD_CTS1__UART1_CTS,
 	MX35_PAD_RTS1__UART1_RTS,
@@ -117,18 +111,18 @@ static const struct mxc_nand_platform_da
 	.flash_bbt	= 1,
 };
 
-static struct mxc_usbh_platform_data __maybe_unused otg_pdata = {
+static const struct mxc_usbh_platform_data otg_pdata __initconst = {
 	.portsc	= MXC_EHCI_MODE_UTMI,
 	.flags	= MXC_EHCI_INTERFACE_DIFF_UNI,
 };
 
-static struct mxc_usbh_platform_data __maybe_unused usbh1_pdata = {
+static const struct mxc_usbh_platform_data usbh1_pdata __initconst = {
 	.portsc	= MXC_EHCI_MODE_SERIAL,
 	.flags	= MXC_EHCI_INTERFACE_SINGLE_UNI | MXC_EHCI_INTERNAL_PHY |
 		  MXC_EHCI_IPPUE_DOWN,
 };
 
-static struct fsl_usb2_platform_data otg_device_pdata = {
+static const struct fsl_usb2_platform_data otg_device_pdata __initconst = {
 	.operating_mode	= FSL_USB2_DR_DEVICE,
 	.phy_mode	= FSL_USB2_PHY_UTMI,
 	.workaround	= FLS_USB2_WORKAROUND_ENGCM09152,
@@ -158,7 +152,7 @@ static void __init mxc_board_init(void)
 			ARRAY_SIZE(eukrea_cpuimx35_pads));
 
 	imx35_add_fec(NULL);
-	platform_add_devices(devices, ARRAY_SIZE(devices));
+	imx35_add_imx2_wdt(NULL);
 
 	imx35_add_imx_uart0(&uart_pdata);
 	imx35_add_mxc_nand(&eukrea_cpuimx35_nand_board_info);
@@ -168,11 +162,11 @@ static void __init mxc_board_init(void)
 	imx35_add_imx_i2c0(&eukrea_cpuimx35_i2c0_data);
 
 	if (otg_mode_host)
-		mxc_register_device(&mxc_otg_host, &otg_pdata);
+		imx35_add_mxc_ehci_otg(&otg_pdata);
 	else
-		mxc_register_device(&mxc_otg_udc_device, &otg_device_pdata);
+		imx35_add_fsl_usb2_udc(&otg_device_pdata);
 
-	mxc_register_device(&mxc_usbh1, &usbh1_pdata);
+	imx35_add_mxc_ehci_hs(&usbh1_pdata);
 
 #ifdef CONFIG_MACH_EUKREA_MBIMXSD35_BASEBOARD
 	eukrea_mbimxsd35_baseboard_init();
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mx3/mach-kzm_arm11_01.c linux-libre-2.6.38-gnu1/arch/arm/mach-mx3/mach-kzm_arm11_01.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mx3/mach-kzm_arm11_01.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mx3/mach-kzm_arm11_01.c	2011-03-14 21:20:32.000000000 -0400
@@ -41,9 +41,9 @@
 #include "devices-imx31.h"
 #include "devices.h"
 
-#define KZM_ARM11_IO_ADDRESS(x) (					\
-	IMX_IO_ADDRESS(x, MX31_CS4) ?:					\
-	IMX_IO_ADDRESS(x, MX31_CS5) ?:					\
+#define KZM_ARM11_IO_ADDRESS(x) (IOMEM(					\
+	IMX_IO_P2V_MODULE(x, MX31_CS4) ?:				\
+	IMX_IO_P2V_MODULE(x, MX31_CS5)) ?:				\
 	MX31_IO_ADDRESS(x))
 
 /*
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mx3/mach-mx31_3ds.c linux-libre-2.6.38-gnu1/arch/arm/mach-mx3/mach-mx31_3ds.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mx3/mach-mx31_3ds.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mx3/mach-mx31_3ds.c	2011-03-14 21:20:32.000000000 -0400
@@ -22,8 +22,8 @@
 #include <linux/mfd/mc13783.h>
 #include <linux/spi/spi.h>
 #include <linux/regulator/machine.h>
-#include <linux/fsl_devices.h>
-#include <linux/input/matrix_keypad.h>
+#include <linux/usb/otg.h>
+#include <linux/usb/ulpi.h>
 
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
@@ -34,6 +34,7 @@
 #include <mach/common.h>
 #include <mach/iomux-mx3.h>
 #include <mach/3ds_debugboard.h>
+#include <mach/ulpi.h>
 
 #include "devices-imx31.h"
 #include "devices.h"
@@ -84,6 +85,21 @@ static int mx31_3ds_pins[] = {
 	MX31_PIN_KEY_COL1_KEY_COL1,
 	MX31_PIN_KEY_COL2_KEY_COL2,
 	MX31_PIN_KEY_COL3_KEY_COL3,
+	/* USB Host 2 */
+	IOMUX_MODE(MX31_PIN_USBH2_CLK, IOMUX_CONFIG_FUNC),
+	IOMUX_MODE(MX31_PIN_USBH2_DIR, IOMUX_CONFIG_FUNC),
+	IOMUX_MODE(MX31_PIN_USBH2_NXT, IOMUX_CONFIG_FUNC),
+	IOMUX_MODE(MX31_PIN_USBH2_STP, IOMUX_CONFIG_FUNC),
+	IOMUX_MODE(MX31_PIN_USBH2_DATA0, IOMUX_CONFIG_FUNC),
+	IOMUX_MODE(MX31_PIN_USBH2_DATA1, IOMUX_CONFIG_FUNC),
+	IOMUX_MODE(MX31_PIN_PC_VS2, IOMUX_CONFIG_ALT1),
+	IOMUX_MODE(MX31_PIN_PC_BVD1, IOMUX_CONFIG_ALT1),
+	IOMUX_MODE(MX31_PIN_PC_BVD2, IOMUX_CONFIG_ALT1),
+	IOMUX_MODE(MX31_PIN_PC_RST, IOMUX_CONFIG_ALT1),
+	IOMUX_MODE(MX31_PIN_IOIS16, IOMUX_CONFIG_ALT1),
+	IOMUX_MODE(MX31_PIN_PC_RW_B, IOMUX_CONFIG_ALT1),
+	/* USB Host2 reset */
+	IOMUX_MODE(MX31_PIN_USB_BYP, IOMUX_CONFIG_GPIO),
 };
 
 /*
@@ -102,7 +118,7 @@ static const uint32_t mx31_3ds_keymap[]
 	KEY(2, 3, KEY_F10),
 };
 
-static struct matrix_keymap_data mx31_3ds_keymap_data = {
+static const struct matrix_keymap_data mx31_3ds_keymap_data __initconst = {
 	.keymap		= mx31_3ds_keymap,
 	.keymap_size	= ARRAY_SIZE(mx31_3ds_keymap),
 };
@@ -115,13 +131,27 @@ static struct regulator_init_data pwgtx_
 	},
 };
 
+static struct regulator_init_data gpo_init = {
+	.constraints = {
+		.boot_on = 1,
+		.always_on = 1,
+	}
+};
+
 static struct mc13783_regulator_init_data mx31_3ds_regulators[] = {
 	{
-		.id = MC13783_REGU_PWGT1SPI, /* Power Gate for ARM core. */
+		.id = MC13783_REG_PWGT1SPI, /* Power Gate for ARM core. */
 		.init_data = &pwgtx_init,
 	}, {
-		.id = MC13783_REGU_PWGT2SPI, /* Power Gate for L2 Cache. */
+		.id = MC13783_REG_PWGT2SPI, /* Power Gate for L2 Cache. */
 		.init_data = &pwgtx_init,
+	}, {
+
+		.id = MC13783_REG_GPO1, /* Turn on 1.8V */
+		.init_data = &gpo_init,
+	}, {
+		.id = MC13783_REG_GPO3, /* Turn on 3.3V */
+		.init_data = &gpo_init,
 	},
 };
 
@@ -129,7 +159,7 @@ static struct mc13783_regulator_init_dat
 static struct mc13783_platform_data mc13783_pdata __initdata = {
 	.regulators = mx31_3ds_regulators,
 	.num_regulators = ARRAY_SIZE(mx31_3ds_regulators),
-	.flags  = MC13783_USE_REGULATOR,
+	.flags  = MC13783_USE_REGULATOR | MC13783_USE_TOUCHSCREEN,
 };
 
 /* SPI */
@@ -175,6 +205,7 @@ mx31_3ds_nand_board_info __initconst = {
 		     PAD_CTL_ODE_CMOS | PAD_CTL_100K_PU)
 
 #define USBOTG_RST_B IOMUX_TO_GPIO(MX31_PIN_USB_PWR)
+#define USBH2_RST_B IOMUX_TO_GPIO(MX31_PIN_USB_BYP)
 
 static int mx31_3ds_usbotg_init(void)
 {
@@ -214,11 +245,77 @@ usbotg_free_reset:
 	return err;
 }
 
-static struct fsl_usb2_platform_data usbotg_pdata = {
+static int mx31_3ds_host2_init(struct platform_device *pdev)
+{
+	int err;
+
+	mxc_iomux_set_pad(MX31_PIN_USBH2_CLK, USB_PAD_CFG);
+	mxc_iomux_set_pad(MX31_PIN_USBH2_DIR, USB_PAD_CFG);
+	mxc_iomux_set_pad(MX31_PIN_USBH2_NXT, USB_PAD_CFG);
+	mxc_iomux_set_pad(MX31_PIN_USBH2_STP, USB_PAD_CFG);
+	mxc_iomux_set_pad(MX31_PIN_USBH2_DATA0, USB_PAD_CFG);
+	mxc_iomux_set_pad(MX31_PIN_USBH2_DATA1, USB_PAD_CFG);
+	mxc_iomux_set_pad(MX31_PIN_PC_VS2, USB_PAD_CFG);
+	mxc_iomux_set_pad(MX31_PIN_PC_BVD1, USB_PAD_CFG);
+	mxc_iomux_set_pad(MX31_PIN_PC_BVD2, USB_PAD_CFG);
+	mxc_iomux_set_pad(MX31_PIN_PC_RST, USB_PAD_CFG);
+	mxc_iomux_set_pad(MX31_PIN_IOIS16, USB_PAD_CFG);
+	mxc_iomux_set_pad(MX31_PIN_PC_RW_B, USB_PAD_CFG);
+
+	err = gpio_request(USBH2_RST_B, "usbh2-reset");
+	if (err) {
+		pr_err("Failed to request the USB Host 2 reset gpio\n");
+		return err;
+	}
+
+	err = gpio_direction_output(USBH2_RST_B, 0);
+	if (err) {
+		pr_err("Failed to drive the USB Host 2 reset gpio\n");
+		goto usbotg_free_reset;
+	}
+
+	mdelay(1);
+	gpio_set_value(USBH2_RST_B, 1);
+	return 0;
+
+usbotg_free_reset:
+	gpio_free(USBH2_RST_B);
+	return err;
+}
+
+#if defined(CONFIG_USB_ULPI)
+static struct mxc_usbh_platform_data otg_pdata __initdata = {
+	.portsc	= MXC_EHCI_MODE_ULPI,
+	.flags	= MXC_EHCI_POWER_PINS_ENABLED,
+};
+
+static struct mxc_usbh_platform_data usbh2_pdata __initdata = {
+	.init = mx31_3ds_host2_init,
+	.portsc	= MXC_EHCI_MODE_ULPI,
+	.flags	= MXC_EHCI_POWER_PINS_ENABLED,
+};
+#endif
+
+static const struct fsl_usb2_platform_data usbotg_pdata __initconst = {
 	.operating_mode = FSL_USB2_DR_DEVICE,
 	.phy_mode	= FSL_USB2_PHY_ULPI,
 };
 
+static int otg_mode_host;
+
+static int __init mx31_3ds_otg_mode(char *options)
+{
+	if (!strcmp(options, "host"))
+		otg_mode_host = 1;
+	else if (!strcmp(options, "device"))
+		otg_mode_host = 0;
+	else
+		pr_info("otg_mode neither \"host\" nor \"device\". "
+			"Defaulting to device\n");
+	return 0;
+}
+__setup("otg_mode=", mx31_3ds_otg_mode);
+
 static const struct imxuart_platform_data uart_pdata __initconst = {
 	.flags = IMXUART_HAVE_RTSCTS,
 };
@@ -246,14 +343,27 @@ static void __init mxc_board_init(void)
 	spi_register_board_info(mx31_3ds_spi_devs,
 						ARRAY_SIZE(mx31_3ds_spi_devs));
 
-	mxc_register_device(&imx_kpp_device, &mx31_3ds_keymap_data);
+	imx31_add_imx_keypad(&mx31_3ds_keymap_data);
 
 	mx31_3ds_usbotg_init();
-	mxc_register_device(&mxc_otg_udc_device, &usbotg_pdata);
+#if defined(CONFIG_USB_ULPI)
+	if (otg_mode_host) {
+		otg_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops,
+				ULPI_OTG_DRVVBUS | ULPI_OTG_DRVVBUS_EXT);
+
+		imx31_add_mxc_ehci_otg(&otg_pdata);
+	}
+	usbh2_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops,
+				ULPI_OTG_DRVVBUS | ULPI_OTG_DRVVBUS_EXT);
+	imx31_add_mxc_ehci_hs(2, &usbh2_pdata);
+#endif
+	if (!otg_mode_host)
+		imx31_add_fsl_usb2_udc(&usbotg_pdata);
 
 	if (mxc_expio_init(MX31_CS5_BASE_ADDR, EXPIO_PARENT_INT))
 		printk(KERN_WARNING "Init of the debug board failed, all "
 				    "devices on the debug board are unusable.\n");
+	imx31_add_imx2_wdt(NULL);
 }
 
 static void __init mx31_3ds_timer_init(void)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mx3/mach-mx31ads.c linux-libre-2.6.38-gnu1/arch/arm/mach-mx3/mach-mx31ads.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mx3/mach-mx31ads.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mx3/mach-mx31ads.c	2011-03-14 21:20:32.000000000 -0400
@@ -162,9 +162,9 @@ static void mx31ads_expio_irq_handler(u3
  * Disable an expio pin's interrupt by setting the bit in the imr.
  * @param irq           an expio virtual irq number
  */
-static void expio_mask_irq(u32 irq)
+static void expio_mask_irq(struct irq_data *d)
 {
-	u32 expio = MXC_IRQ_TO_EXPIO(irq);
+	u32 expio = MXC_IRQ_TO_EXPIO(d->irq);
 	/* mask the interrupt */
 	__raw_writew(1 << expio, PBC_INTMASK_CLEAR_REG);
 	__raw_readw(PBC_INTMASK_CLEAR_REG);
@@ -174,9 +174,9 @@ static void expio_mask_irq(u32 irq)
  * Acknowledge an expanded io pin's interrupt by clearing the bit in the isr.
  * @param irq           an expanded io virtual irq number
  */
-static void expio_ack_irq(u32 irq)
+static void expio_ack_irq(struct irq_data *d)
 {
-	u32 expio = MXC_IRQ_TO_EXPIO(irq);
+	u32 expio = MXC_IRQ_TO_EXPIO(d->irq);
 	/* clear the interrupt status */
 	__raw_writew(1 << expio, PBC_INTSTATUS_REG);
 }
@@ -185,18 +185,18 @@ static void expio_ack_irq(u32 irq)
  * Enable a expio pin's interrupt by clearing the bit in the imr.
  * @param irq           a expio virtual irq number
  */
-static void expio_unmask_irq(u32 irq)
+static void expio_unmask_irq(struct irq_data *d)
 {
-	u32 expio = MXC_IRQ_TO_EXPIO(irq);
+	u32 expio = MXC_IRQ_TO_EXPIO(d->irq);
 	/* unmask the interrupt */
 	__raw_writew(1 << expio, PBC_INTMASK_SET_REG);
 }
 
 static struct irq_chip expio_irq_chip = {
 	.name = "EXPIO(CPLD)",
-	.ack = expio_ack_irq,
-	.mask = expio_mask_irq,
-	.unmask = expio_unmask_irq,
+	.irq_ack = expio_ack_irq,
+	.irq_mask = expio_mask_irq,
+	.irq_unmask = expio_unmask_irq,
 };
 
 static void __init mx31ads_init_expio(void)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mx3/mach-mx31lilly.c linux-libre-2.6.38-gnu1/arch/arm/mach-mx3/mach-mx31lilly.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mx3/mach-mx31lilly.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mx3/mach-mx31lilly.c	2011-03-14 21:20:32.000000000 -0400
@@ -42,7 +42,6 @@
 #include <mach/common.h>
 #include <mach/iomux-mx3.h>
 #include <mach/board-mx31lilly.h>
-#include <mach/mxc_ehci.h>
 #include <mach/ulpi.h>
 
 #include "devices-imx31.h"
@@ -230,13 +229,13 @@ static struct mxc_usbh_platform_data usb
 	.flags	= MXC_EHCI_POWER_PINS_ENABLED,
 };
 
-static struct mxc_usbh_platform_data usbh1_pdata = {
+static const struct mxc_usbh_platform_data usbh1_pdata __initconst = {
 	.init	= usbh1_init,
 	.portsc	= MXC_EHCI_MODE_UTMI | MXC_EHCI_SERIAL,
 	.flags	= MXC_EHCI_POWER_PINS_ENABLED | MXC_EHCI_INTERFACE_SINGLE_UNI,
 };
 
-static struct mxc_usbh_platform_data usbh2_pdata = {
+static struct mxc_usbh_platform_data usbh2_pdata __initdata = {
 	.init	= usbh2_init,
 	.portsc	= MXC_EHCI_MODE_ULPI | MXC_EHCI_UTMI_8BIT,
 	.flags	= MXC_EHCI_POWER_PINS_ENABLED,
@@ -249,8 +248,8 @@ static void lilly1131_usb_init(void)
 	usbh2_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops,
 				ULPI_OTG_DRVVBUS | ULPI_OTG_DRVVBUS_EXT);
 
-	mxc_register_device(&mxc_usbh1, &usbh1_pdata);
-	mxc_register_device(&mxc_usbh2, &usbh2_pdata);
+	imx31_add_mxc_ehci_hs(1, &usbh1_pdata);
+	imx31_add_mxc_ehci_hs(2, &usbh2_pdata);
 }
 
 #else
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mx3/mach-mx31lite.c linux-libre-2.6.38-gnu1/arch/arm/mach-mx3/mach-mx31lite.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mx3/mach-mx31lite.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mx3/mach-mx31lite.c	2011-03-14 21:20:32.000000000 -0400
@@ -40,7 +40,6 @@
 #include <mach/board-mx31lite.h>
 #include <mach/iomux-mx3.h>
 #include <mach/irqs.h>
-#include <mach/mxc_ehci.h>
 #include <mach/ulpi.h>
 
 #include "devices-imx31.h"
@@ -171,7 +170,7 @@ static int usbh2_init(struct platform_de
 	return 0;
 }
 
-static struct mxc_usbh_platform_data usbh2_pdata = {
+static struct mxc_usbh_platform_data usbh2_pdata __initdata = {
 	.init   = usbh2_init,
 	.portsc = MXC_EHCI_MODE_ULPI | MXC_EHCI_UTMI_8BIT,
 	.flags  = MXC_EHCI_POWER_PINS_ENABLED,
@@ -258,7 +257,7 @@ static void __init mxc_board_init(void)
 	usbh2_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops,
 				ULPI_OTG_DRVVBUS | ULPI_OTG_DRVVBUS_EXT);
 
-	mxc_register_device(&mxc_usbh2, &usbh2_pdata);
+	imx31_add_mxc_ehci_hs(2, &usbh2_pdata);
 #endif
 
 	/* SMSC9117 IRQ pin */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mx3/mach-mx31moboard.c linux-libre-2.6.38-gnu1/arch/arm/mach-mx3/mach-mx31moboard.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mx3/mach-mx31moboard.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mx3/mach-mx31moboard.c	2011-03-14 21:20:32.000000000 -0400
@@ -40,8 +40,6 @@
 #include <mach/hardware.h>
 #include <mach/iomux-mx3.h>
 #include <mach/ipu.h>
-#include <mach/mmc.h>
-#include <mach/mxc_ehci.h>
 #include <mach/mx3_camera.h>
 #include <mach/spi.h>
 #include <mach/ulpi.h>
@@ -170,11 +168,11 @@ static const struct spi_imx_master moboa
 
 static struct regulator_consumer_supply sdhc_consumers[] = {
 	{
-		.dev	= &mxcsdhc_device0.dev,
+		.dev_name = "mxc-mmc.0",
 		.supply	= "sdhc0_vcc",
 	},
 	{
-		.dev	= &mxcsdhc_device1.dev,
+		.dev_name = "mxc-mmc.1",
 		.supply	= "sdhc1_vcc",
 	},
 };
@@ -218,11 +216,11 @@ static struct regulator_init_data cam_vr
 
 static struct mc13783_regulator_init_data moboard_regulators[] = {
 	{
-		.id = MC13783_REGU_VMMC1,
+		.id = MC13783_REG_VMMC1,
 		.init_data = &sdhc_vreg_data,
 	},
 	{
-		.id = MC13783_REGU_VCAM,
+		.id = MC13783_REG_VCAM,
 		.init_data = &cam_vreg_data,
 	},
 };
@@ -345,7 +343,7 @@ static void moboard_sdhc1_exit(struct de
 	gpio_free(SDHC1_CD);
 }
 
-static struct imxmmc_platform_data sdhc1_pdata = {
+static const struct imxmmc_platform_data sdhc1_pdata __initconst = {
 	.get_ro	= moboard_sdhc1_get_ro,
 	.init	= moboard_sdhc1_init,
 	.exit	= moboard_sdhc1_exit,
@@ -404,17 +402,23 @@ static void usb_xcvr_reset(void)
 
 #if defined(CONFIG_USB_ULPI)
 
-static struct mxc_usbh_platform_data usbh2_pdata = {
+static struct mxc_usbh_platform_data usbh2_pdata __initdata = {
 	.portsc	= MXC_EHCI_MODE_ULPI | MXC_EHCI_UTMI_8BIT,
 	.flags	= MXC_EHCI_POWER_PINS_ENABLED,
 };
 
 static int __init moboard_usbh2_init(void)
 {
+	struct platform_device *pdev;
+
 	usbh2_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops,
 			ULPI_OTG_DRVVBUS | ULPI_OTG_DRVVBUS_EXT);
 
-	return mxc_register_device(&mxc_usbh2, &usbh2_pdata);
+	pdev = imx31_add_mxc_ehci_hs(2, &usbh2_pdata);
+	if (IS_ERR(pdev))
+		return PTR_ERR(pdev);
+
+	return 0;
 }
 #else
 static inline int moboard_usbh2_init(void) { return 0; }
@@ -520,7 +524,7 @@ static void __init mxc_board_init(void)
 	spi_register_board_info(moboard_spi_board_info,
 		ARRAY_SIZE(moboard_spi_board_info));
 
-	mxc_register_device(&mxcsdhc_device0, &sdhc1_pdata);
+	imx31_add_mxc_mmc(0, &sdhc1_pdata);
 
 	mxc_register_device(&mx3_ipu, &mx3_ipu_data);
 	if (!mx31moboard_cam_alloc_dma(CAMERA_BUF_SIZE))
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mx3/mach-mx35_3ds.c linux-libre-2.6.38-gnu1/arch/arm/mach-mx3/mach-mx35_3ds.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mx3/mach-mx35_3ds.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mx3/mach-mx35_3ds.c	2011-03-14 21:20:32.000000000 -0400
@@ -26,7 +26,7 @@
 #include <linux/platform_device.h>
 #include <linux/memory.h>
 #include <linux/gpio.h>
-#include <linux/fsl_devices.h>
+#include <linux/usb/otg.h>
 
 #include <linux/mtd/physmap.h>
 
@@ -40,7 +40,6 @@
 #include <mach/iomux-mx35.h>
 #include <mach/irqs.h>
 #include <mach/3ds_debugboard.h>
-#include <mach/mxc_ehci.h>
 
 #include "devices-imx35.h"
 #include "devices.h"
@@ -81,7 +80,7 @@ static struct platform_device *devices[]
 	&mx35pdk_flash,
 };
 
-static struct pad_desc mx35pdk_pads[] = {
+static iomux_v3_cfg_t mx35pdk_pads[] = {
 	/* UART1 */
 	MX35_PAD_CTS1__UART1_CTS,
 	MX35_PAD_RTS1__UART1_RTS,
@@ -122,18 +121,38 @@ static struct pad_desc mx35pdk_pads[] =
 };
 
 /* OTG config */
-static struct fsl_usb2_platform_data usb_otg_pdata = {
+static const struct fsl_usb2_platform_data usb_otg_pdata __initconst = {
 	.operating_mode	= FSL_USB2_DR_DEVICE,
 	.phy_mode	= FSL_USB2_PHY_UTMI_WIDE,
 };
 
+static struct mxc_usbh_platform_data otg_pdata __initdata = {
+	.portsc	= MXC_EHCI_MODE_UTMI,
+	.flags	= MXC_EHCI_INTERNAL_PHY,
+};
+
 /* USB HOST config */
-static struct mxc_usbh_platform_data usb_host_pdata = {
+static const struct mxc_usbh_platform_data usb_host_pdata __initconst = {
 	.portsc		= MXC_EHCI_MODE_SERIAL,
 	.flags		= MXC_EHCI_INTERFACE_SINGLE_UNI |
 			  MXC_EHCI_INTERNAL_PHY,
 };
 
+static int otg_mode_host;
+
+static int __init mx35_3ds_otg_mode(char *options)
+{
+	if (!strcmp(options, "host"))
+		otg_mode_host = 1;
+	else if (!strcmp(options, "device"))
+		otg_mode_host = 0;
+	else
+		pr_info("otg_mode neither \"host\" nor \"device\". "
+			"Defaulting to device\n");
+	return 0;
+}
+__setup("otg_mode=", mx35_3ds_otg_mode);
+
 /*
  * Board specific initialization.
  */
@@ -142,16 +161,21 @@ static void __init mxc_board_init(void)
 	mxc_iomux_v3_setup_multiple_pads(mx35pdk_pads, ARRAY_SIZE(mx35pdk_pads));
 
 	imx35_add_fec(NULL);
+	imx35_add_imx2_wdt(NULL);
 	platform_add_devices(devices, ARRAY_SIZE(devices));
 
 	imx35_add_imx_uart0(&uart_pdata);
 
-	mxc_register_device(&mxc_otg_udc_device, &usb_otg_pdata);
+	if (otg_mode_host)
+		imx35_add_mxc_ehci_otg(&otg_pdata);
 
-	mxc_register_device(&mxc_usbh1, &usb_host_pdata);
+	imx35_add_mxc_ehci_hs(&usb_host_pdata);
+
+	if (!otg_mode_host)
+		imx35_add_fsl_usb2_udc(&usb_otg_pdata);
 
 	imx35_add_mxc_nand(&mx35pdk_nand_board_info);
-	imx35_add_esdhc(0, NULL);
+	imx35_add_sdhci_esdhc_imx(0, NULL);
 
 	if (mxc_expio_init(MX35_CS5_BASE_ADDR, EXPIO_PARENT_INT))
 		pr_warn("Init of the debugboard failed, all "
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mx3/mach-pcm037.c linux-libre-2.6.38-gnu1/arch/arm/mach-mx3/mach-pcm037.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mx3/mach-pcm037.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mx3/mach-pcm037.c	2011-03-14 21:20:32.000000000 -0400
@@ -27,7 +27,6 @@
 #include <linux/delay.h>
 #include <linux/spi/spi.h>
 #include <linux/irq.h>
-#include <linux/fsl_devices.h>
 #include <linux/can/platform/sja1000.h>
 #include <linux/usb/otg.h>
 #include <linux/usb/ulpi.h>
@@ -43,10 +42,8 @@
 #include <mach/hardware.h>
 #include <mach/iomux-mx3.h>
 #include <mach/ipu.h>
-#include <mach/mmc.h>
 #include <mach/mx3_camera.h>
 #include <mach/mx3fb.h>
-#include <mach/mxc_ehci.h>
 #include <mach/ulpi.h>
 
 #include "devices-imx31.h"
@@ -399,7 +396,7 @@ static void pcm970_sdhc1_exit(struct dev
 	gpio_free(SDHC1_GPIO_WP);
 }
 
-static struct imxmmc_platform_data sdhc_pdata = {
+static const struct imxmmc_platform_data sdhc_pdata __initconst = {
 #ifdef PCM970_SDHC_RW_SWITCH
 	.get_ro = pcm970_sdhc1_get_ro,
 #endif
@@ -441,7 +438,6 @@ static int __init pcm037_camera_alloc_dm
 static struct platform_device *devices[] __initdata = {
 	&pcm037_flash,
 	&pcm037_sram_device,
-	&imx_wdt_device0,
 	&pcm037_mt9t031,
 	&pcm037_mt9v022,
 };
@@ -538,18 +534,18 @@ static struct platform_device pcm970_sja
 };
 
 #if defined(CONFIG_USB_ULPI)
-static struct mxc_usbh_platform_data otg_pdata = {
+static struct mxc_usbh_platform_data otg_pdata __initdata = {
 	.portsc	= MXC_EHCI_MODE_ULPI,
 	.flags	= MXC_EHCI_INTERFACE_DIFF_UNI,
 };
 
-static struct mxc_usbh_platform_data usbh2_pdata = {
+static struct mxc_usbh_platform_data usbh2_pdata __initdata = {
 	.portsc	= MXC_EHCI_MODE_ULPI,
 	.flags	= MXC_EHCI_INTERFACE_DIFF_UNI,
 };
 #endif
 
-static struct fsl_usb2_platform_data otg_device_pdata = {
+static const struct fsl_usb2_platform_data otg_device_pdata __initconst = {
 	.operating_mode = FSL_USB2_DR_DEVICE,
 	.phy_mode       = FSL_USB2_PHY_ULPI,
 };
@@ -607,12 +603,13 @@ static void __init mxc_board_init(void)
 
 	platform_add_devices(devices, ARRAY_SIZE(devices));
 
+	imx31_add_imx2_wdt(NULL);
 	imx31_add_imx_uart0(&uart_pdata);
 	/* XXX: should't this have .flags = 0 (i.e. no RTSCTS) on PCM037_EET? */
 	imx31_add_imx_uart1(&uart_pdata);
 	imx31_add_imx_uart2(&uart_pdata);
 
-	mxc_register_device(&mxc_w1_master_device, NULL);
+	imx31_add_mxc_w1(NULL);
 
 	/* LAN9217 IRQ pin */
 	ret = gpio_request(IOMUX_TO_GPIO(MX31_PIN_GPIO3_1), "lan9217-irq");
@@ -632,7 +629,7 @@ static void __init mxc_board_init(void)
 	imx31_add_imx_i2c2(&pcm037_i2c2_data);
 
 	imx31_add_mxc_nand(&pcm037_nand_board_info);
-	mxc_register_device(&mxcsdhc_device0, &sdhc_pdata);
+	imx31_add_mxc_mmc(0, &sdhc_pdata);
 	mxc_register_device(&mx3_ipu, &mx3_ipu_data);
 	mxc_register_device(&mx3_fb, &mx3fb_pdata);
 
@@ -654,16 +651,16 @@ static void __init mxc_board_init(void)
 		otg_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops,
 				ULPI_OTG_DRVVBUS | ULPI_OTG_DRVVBUS_EXT);
 
-		mxc_register_device(&mxc_otg_host, &otg_pdata);
+		imx31_add_mxc_ehci_otg(&otg_pdata);
 	}
 
 	usbh2_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops,
 				ULPI_OTG_DRVVBUS | ULPI_OTG_DRVVBUS_EXT);
 
-	mxc_register_device(&mxc_usbh2, &usbh2_pdata);
+	imx31_add_mxc_ehci_hs(2, &usbh2_pdata);
 #endif
 	if (!otg_mode_host)
-		mxc_register_device(&mxc_otg_udc_device, &otg_device_pdata);
+		imx31_add_fsl_usb2_udc(&otg_device_pdata);
 
 }
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mx3/mach-pcm043.c linux-libre-2.6.38-gnu1/arch/arm/mach-mx3/mach-pcm043.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mx3/mach-pcm043.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mx3/mach-pcm043.c	2011-03-14 21:20:32.000000000 -0400
@@ -27,7 +27,6 @@
 #include <linux/i2c/at24.h>
 #include <linux/usb/otg.h>
 #include <linux/usb/ulpi.h>
-#include <linux/fsl_devices.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -39,7 +38,6 @@
 #include <mach/iomux-mx35.h>
 #include <mach/ipu.h>
 #include <mach/mx3fb.h>
-#include <mach/mxc_ehci.h>
 #include <mach/ulpi.h>
 #include <mach/audmux.h>
 
@@ -140,10 +138,9 @@ static struct i2c_board_info pcm043_i2c_
 
 static struct platform_device *devices[] __initdata = {
 	&pcm043_flash,
-	&imx_wdt_device0,
 };
 
-static struct pad_desc pcm043_pads[] = {
+static iomux_v3_cfg_t pcm043_pads[] = {
 	/* UART1 */
 	MX35_PAD_CTS1__UART1_CTS,
 	MX35_PAD_RTS1__UART1_RTS,
@@ -230,8 +227,8 @@ static struct pad_desc pcm043_pads[] = {
 
 static void pcm043_ac97_warm_reset(struct snd_ac97 *ac97)
 {
-	struct pad_desc txfs_gpio = MX35_PAD_STXFS4__GPIO2_31;
-	struct pad_desc txfs = MX35_PAD_STXFS4__AUDMUX_AUD4_TXFS;
+	iomux_v3_cfg_t txfs_gpio = MX35_PAD_STXFS4__GPIO2_31;
+	iomux_v3_cfg_t txfs = MX35_PAD_STXFS4__AUDMUX_AUD4_TXFS;
 	int ret;
 
 	ret = gpio_request(AC97_GPIO_TXFS, "SSI");
@@ -240,7 +237,7 @@ static void pcm043_ac97_warm_reset(struc
 		return;
 	}
 
-	mxc_iomux_v3_setup_pad(&txfs_gpio);
+	mxc_iomux_v3_setup_pad(txfs_gpio);
 
 	/* warm reset */
 	gpio_direction_output(AC97_GPIO_TXFS, 1);
@@ -248,16 +245,16 @@ static void pcm043_ac97_warm_reset(struc
 	gpio_set_value(AC97_GPIO_TXFS, 0);
 
 	gpio_free(AC97_GPIO_TXFS);
-	mxc_iomux_v3_setup_pad(&txfs);
+	mxc_iomux_v3_setup_pad(txfs);
 }
 
 static void pcm043_ac97_cold_reset(struct snd_ac97 *ac97)
 {
-	struct pad_desc txfs_gpio = MX35_PAD_STXFS4__GPIO2_31;
-	struct pad_desc txfs = MX35_PAD_STXFS4__AUDMUX_AUD4_TXFS;
-	struct pad_desc txd_gpio = MX35_PAD_STXD4__GPIO2_28;
-	struct pad_desc txd = MX35_PAD_STXD4__AUDMUX_AUD4_TXD;
-	struct pad_desc reset_gpio = MX35_PAD_SD2_CMD__GPIO2_0;
+	iomux_v3_cfg_t txfs_gpio = MX35_PAD_STXFS4__GPIO2_31;
+	iomux_v3_cfg_t txfs = MX35_PAD_STXFS4__AUDMUX_AUD4_TXFS;
+	iomux_v3_cfg_t txd_gpio = MX35_PAD_STXD4__GPIO2_28;
+	iomux_v3_cfg_t txd = MX35_PAD_STXD4__AUDMUX_AUD4_TXD;
+	iomux_v3_cfg_t reset_gpio = MX35_PAD_SD2_CMD__GPIO2_0;
 	int ret;
 
 	ret = gpio_request(AC97_GPIO_TXFS, "SSI");
@@ -272,9 +269,9 @@ static void pcm043_ac97_cold_reset(struc
 	if (ret)
 		goto err3;
 
-	mxc_iomux_v3_setup_pad(&txfs_gpio);
-	mxc_iomux_v3_setup_pad(&txd_gpio);
-	mxc_iomux_v3_setup_pad(&reset_gpio);
+	mxc_iomux_v3_setup_pad(txfs_gpio);
+	mxc_iomux_v3_setup_pad(txd_gpio);
+	mxc_iomux_v3_setup_pad(reset_gpio);
 
 	gpio_direction_output(AC97_GPIO_TXFS, 0);
 	gpio_direction_output(AC97_GPIO_TXD, 0);
@@ -284,8 +281,8 @@ static void pcm043_ac97_cold_reset(struc
 	udelay(10);
 	gpio_direction_output(AC97_GPIO_RESET, 1);
 
-	mxc_iomux_v3_setup_pad(&txd);
-	mxc_iomux_v3_setup_pad(&txfs);
+	mxc_iomux_v3_setup_pad(txd);
+	mxc_iomux_v3_setup_pad(txfs);
 
 	gpio_free(AC97_GPIO_RESET);
 err3:
@@ -311,19 +308,19 @@ pcm037_nand_board_info __initconst = {
 };
 
 #if defined(CONFIG_USB_ULPI)
-static struct mxc_usbh_platform_data otg_pdata = {
+static struct mxc_usbh_platform_data otg_pdata __initdata = {
 	.portsc	= MXC_EHCI_MODE_UTMI,
 	.flags	= MXC_EHCI_INTERFACE_DIFF_UNI,
 };
 
-static struct mxc_usbh_platform_data usbh1_pdata = {
+static const struct mxc_usbh_platform_data usbh1_pdata __initconst = {
 	.portsc	= MXC_EHCI_MODE_SERIAL,
 	.flags	= MXC_EHCI_INTERFACE_SINGLE_UNI | MXC_EHCI_INTERNAL_PHY |
 		  MXC_EHCI_IPPUE_DOWN,
 };
 #endif
 
-static struct fsl_usb2_platform_data otg_device_pdata = {
+static const struct fsl_usb2_platform_data otg_device_pdata __initconst = {
 	.operating_mode = FSL_USB2_DR_DEVICE,
 	.phy_mode       = FSL_USB2_PHY_UTMI,
 };
@@ -364,6 +361,7 @@ static void __init mxc_board_init(void)
 
 	imx35_add_fec(NULL);
 	platform_add_devices(devices, ARRAY_SIZE(devices));
+	imx35_add_imx2_wdt(NULL);
 
 	imx35_add_imx_uart0(&uart_pdata);
 	imx35_add_mxc_nand(&pcm037_nand_board_info);
@@ -386,16 +384,16 @@ static void __init mxc_board_init(void)
 		otg_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops,
 				ULPI_OTG_DRVVBUS | ULPI_OTG_DRVVBUS_EXT);
 
-		mxc_register_device(&mxc_otg_host, &otg_pdata);
+		imx35_add_mxc_ehci_otg(&otg_pdata);
 	}
 
-	mxc_register_device(&mxc_usbh1, &usbh1_pdata);
+	imx35_add_mxc_ehci_hs(&usbh1_pdata);
 #endif
 	if (!otg_mode_host)
-		mxc_register_device(&mxc_otg_udc_device, &otg_device_pdata);
+		imx35_add_fsl_usb2_udc(&otg_device_pdata);
 
 	imx35_add_flexcan1(NULL);
-	imx35_add_esdhc(0, NULL);
+	imx35_add_sdhci_esdhc_imx(0, NULL);
 }
 
 static void __init pcm043_timer_init(void)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mx3/Makefile linux-libre-2.6.38-gnu1/arch/arm/mach-mx3/Makefile
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mx3/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mx3/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -5,17 +5,14 @@
 # Object file lists.
 
 obj-y				:= mm.o devices.o cpu.o
-CFLAGS_mm.o = -DIMX_NEEDS_DEPRECATED_SYMBOLS
-CFLAGS_devices.o = -DIMX_NEEDS_DEPRECATED_SYMBOLS
-obj-$(CONFIG_ARCH_MX31)		+= clock-imx31.o iomux-imx31.o
-obj-$(CONFIG_ARCH_MX35)		+= clock-imx35.o
+obj-$(CONFIG_SOC_IMX31)		+= clock-imx31.o iomux-imx31.o
+obj-$(CONFIG_SOC_IMX35)		+= clock-imx35.o
 obj-$(CONFIG_MACH_MX31ADS)	+= mach-mx31ads.o
 obj-$(CONFIG_MACH_MX31LILLY)	+= mach-mx31lilly.o mx31lilly-db.o
 obj-$(CONFIG_MACH_MX31LITE)	+= mach-mx31lite.o mx31lite-db.o
 obj-$(CONFIG_MACH_PCM037)	+= mach-pcm037.o
 obj-$(CONFIG_MACH_PCM037_EET)	+= mach-pcm037_eet.o
 obj-$(CONFIG_MACH_MX31_3DS)	+= mach-mx31_3ds.o
-CFLAGS_mach-mx31_3ds.o = -DIMX_NEEDS_DEPRECATED_SYMBOLS
 obj-$(CONFIG_MACH_MX31MOBOARD)	+= mach-mx31moboard.o mx31moboard-devboard.o \
 				   mx31moboard-marxbot.o mx31moboard-smartbot.o
 obj-$(CONFIG_MACH_QONG)		+= mach-qong.o
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mx3/mm.c linux-libre-2.6.38-gnu1/arch/arm/mach-mx3/mm.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mx3/mm.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mx3/mm.c	2011-03-14 21:20:32.000000000 -0400
@@ -36,40 +36,16 @@
  * @ingroup Memory
  */
 
-/*!
- * This table defines static virtual address mappings for I/O regions.
- * These are the mappings common across all MX3 boards.
- */
-static struct map_desc mxc_io_desc[] __initdata = {
-	{
-		.virtual	= X_MEMC_BASE_ADDR_VIRT,
-		.pfn		= __phys_to_pfn(X_MEMC_BASE_ADDR),
-		.length		= X_MEMC_SIZE,
-		.type		= MT_DEVICE
-	}, {
-		.virtual	= AVIC_BASE_ADDR_VIRT,
-		.pfn		= __phys_to_pfn(AVIC_BASE_ADDR),
-		.length		= AVIC_SIZE,
-		.type		= MT_DEVICE_NONSHARED
-	}, {
-		.virtual	= AIPS1_BASE_ADDR_VIRT,
-		.pfn		= __phys_to_pfn(AIPS1_BASE_ADDR),
-		.length		= AIPS1_SIZE,
-		.type		= MT_DEVICE_NONSHARED
-	}, {
-		.virtual	= AIPS2_BASE_ADDR_VIRT,
-		.pfn		= __phys_to_pfn(AIPS2_BASE_ADDR),
-		.length		= AIPS2_SIZE,
-		.type		= MT_DEVICE_NONSHARED
-	}, {
-		.virtual = SPBA0_BASE_ADDR_VIRT,
-		.pfn = __phys_to_pfn(SPBA0_BASE_ADDR),
-		.length = SPBA0_SIZE,
-		.type = MT_DEVICE_NONSHARED
-	},
+#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.
@@ -77,34 +53,44 @@ static struct map_desc mxc_io_desc[] __i
 void __init mx31_map_io(void)
 {
 	mxc_set_cpu_type(MXC_CPU_MX31);
-	mxc_arch_reset_init(IO_ADDRESS(WDOG_BASE_ADDR));
+	mxc_arch_reset_init(MX31_IO_ADDRESS(MX31_WDOG_BASE_ADDR));
 
-	iotable_init(mxc_io_desc, ARRAY_SIZE(mxc_io_desc));
+	iotable_init(mx31_io_desc, ARRAY_SIZE(mx31_io_desc));
 }
 
-#ifdef CONFIG_ARCH_MX35
-void __init mx35_map_io(void)
+int imx31_register_gpios(void);
+void __init mx31_init_irq(void)
 {
-	mxc_set_cpu_type(MXC_CPU_MX35);
-	mxc_iomux_v3_init(IO_ADDRESS(IOMUXC_BASE_ADDR));
-	mxc_arch_reset_init(IO_ADDRESS(WDOG_BASE_ADDR));
-
-	iotable_init(mxc_io_desc, ARRAY_SIZE(mxc_io_desc));
+	mxc_init_irq(MX31_IO_ADDRESS(MX31_AVIC_BASE_ADDR));
+	imx31_register_gpios();
 }
-#endif
+#endif /* ifdef CONFIG_SOC_IMX31 */
 
-int imx3x_register_gpios(void);
+#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 mx31_init_irq(void)
+void __init mx35_map_io(void)
 {
-	mxc_init_irq(IO_ADDRESS(AVIC_BASE_ADDR));
-	imx3x_register_gpios();
+	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));
+
+	iotable_init(mx35_io_desc, ARRAY_SIZE(mx35_io_desc));
 }
 
+int imx35_register_gpios(void);
 void __init mx35_init_irq(void)
 {
-	mx31_init_irq();
+	mxc_init_irq(MX35_IO_ADDRESS(MX35_AVIC_BASE_ADDR));
+	imx35_register_gpios();
 }
+#endif /* ifdef CONFIG_SOC_IMX35 */
 
 #ifdef CONFIG_CACHE_L2X0
 static int mxc_init_l2x0(void)
@@ -129,7 +115,7 @@ static int mxc_init_l2x0(void)
 		pr_err("L2 cache: Cannot fix timing. Trying to continue without\n");
 	}
 
-	l2x0_base = ioremap(L2CC_BASE_ADDR, 4096);
+	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));
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mx3/mx31lilly-db.c linux-libre-2.6.38-gnu1/arch/arm/mach-mx3/mx31lilly-db.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mx3/mx31lilly-db.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mx3/mx31lilly-db.c	2011-03-14 21:20:32.000000000 -0400
@@ -34,7 +34,6 @@
 #include <mach/common.h>
 #include <mach/iomux-mx3.h>
 #include <mach/board-mx31lilly.h>
-#include <mach/mmc.h>
 #include <mach/mx3fb.h>
 #include <mach/ipu.h>
 
@@ -158,7 +157,7 @@ static void mxc_mmc1_exit(struct device
 	free_irq(IOMUX_TO_IRQ(MX31_PIN_GPIO1_1), data);
 }
 
-static struct imxmmc_platform_data mmc_pdata = {
+static const struct imxmmc_platform_data mmc_pdata __initconst = {
 	.get_ro	= mxc_mmc1_get_ro,
 	.init	= mxc_mmc1_init,
 	.exit	= mxc_mmc1_exit,
@@ -216,7 +215,7 @@ void __init mx31lilly_db_init(void)
 	imx31_add_imx_uart0(&uart_pdata);
 	imx31_add_imx_uart1(&uart_pdata);
 	imx31_add_imx_uart2(&uart_pdata);
-	mxc_register_device(&mxcsdhc_device0, &mmc_pdata);
+	imx31_add_mxc_mmc(0, &mmc_pdata);
 	mx31lilly_init_fb();
 }
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mx3/mx31lite-db.c linux-libre-2.6.38-gnu1/arch/arm/mach-mx3/mx31lite-db.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mx3/mx31lite-db.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mx3/mx31lite-db.c	2011-03-14 21:20:32.000000000 -0400
@@ -35,7 +35,6 @@
 #include <mach/common.h>
 #include <mach/iomux-mx3.h>
 #include <mach/board-mx31lite.h>
-#include <mach/mmc.h>
 
 #include "devices-imx31.h"
 #include "devices.h"
@@ -142,7 +141,7 @@ static void mxc_mmc1_exit(struct device
 	free_irq(IOMUX_TO_IRQ(MX31_PIN_DCD_DCE1), data);
 }
 
-static struct imxmmc_platform_data mmc_pdata = {
+static const struct imxmmc_platform_data mmc_pdata __initconst = {
 	.get_ro	 = mxc_mmc1_get_ro,
 	.init	   = mxc_mmc1_init,
 	.exit	   = mxc_mmc1_exit,
@@ -197,10 +196,9 @@ void __init mx31lite_db_init(void)
 					ARRAY_SIZE(litekit_db_board_pins),
 					"development board pins");
 	imx31_add_imx_uart0(&uart_pdata);
-	mxc_register_device(&mxcsdhc_device0, &mmc_pdata);
+	imx31_add_mxc_mmc(0, &mmc_pdata);
 	imx31_add_spi_imx0(&spi0_pdata);
 	platform_device_register(&litekit_led_device);
-	mxc_register_device(&imx_wdt_device0, NULL);
+	imx31_add_imx2_wdt(NULL);
 	mxc_register_device(&imx_rtc_device0, NULL);
 }
-
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mx3/mx31moboard-devboard.c linux-libre-2.6.38-gnu1/arch/arm/mach-mx3/mx31moboard-devboard.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mx3/mx31moboard-devboard.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mx3/mx31moboard-devboard.c	2011-03-14 21:20:32.000000000 -0400
@@ -18,15 +18,12 @@
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/types.h>
-#include <linux/fsl_devices.h>
 
 #include <linux/usb/otg.h>
 
 #include <mach/common.h>
 #include <mach/iomux-mx3.h>
 #include <mach/hardware.h>
-#include <mach/mmc.h>
-#include <mach/mxc_ehci.h>
 #include <mach/ulpi.h>
 
 #include "devices-imx31.h"
@@ -103,7 +100,7 @@ static void devboard_sdhc2_exit(struct d
 	gpio_free(SDHC2_CD);
 }
 
-static struct imxmmc_platform_data sdhc2_pdata = {
+static const struct imxmmc_platform_data sdhc2_pdata __initconst = {
 	.get_ro	= devboard_sdhc2_get_ro,
 	.init	= devboard_sdhc2_init,
 	.exit	= devboard_sdhc2_exit,
@@ -187,7 +184,7 @@ static int devboard_isp1105_set_vbus(str
 	return 0;
 }
 
-static struct mxc_usbh_platform_data usbh1_pdata = {
+static struct mxc_usbh_platform_data usbh1_pdata __initdata = {
 	.init	= devboard_usbh1_hw_init,
 	.portsc	= MXC_EHCI_MODE_UTMI | MXC_EHCI_SERIAL,
 	.flags	= MXC_EHCI_POWER_PINS_ENABLED | MXC_EHCI_INTERFACE_SINGLE_UNI,
@@ -196,6 +193,7 @@ static struct mxc_usbh_platform_data usb
 static int __init devboard_usbh1_init(void)
 {
 	struct otg_transceiver *otg;
+	struct platform_device *pdev;
 
 	otg = kzalloc(sizeof(*otg), GFP_KERNEL);
 	if (!otg)
@@ -207,11 +205,15 @@ static int __init devboard_usbh1_init(vo
 
 	usbh1_pdata.otg = otg;
 
-	return mxc_register_device(&mxc_usbh1, &usbh1_pdata);
+	pdev = imx31_add_mxc_ehci_hs(1, &usbh1_pdata);
+	if (IS_ERR(pdev))
+		return PTR_ERR(pdev);
+
+	return 0;
 }
 
 
-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_ULPI,
 };
@@ -228,11 +230,11 @@ void __init mx31moboard_devboard_init(vo
 
 	imx31_add_imx_uart1(&uart_pdata);
 
-	mxc_register_device(&mxcsdhc_device1, &sdhc2_pdata);
+	imx31_add_mxc_mmc(1, &sdhc2_pdata);
 
 	devboard_init_sel_gpios();
 
-	mxc_register_device(&mxc_otg_udc_device, &usb_pdata);
+	imx31_add_fsl_usb2_udc(&usb_pdata);
 
 	devboard_usbh1_init();
 }
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mx3/mx31moboard-marxbot.c linux-libre-2.6.38-gnu1/arch/arm/mach-mx3/mx31moboard-marxbot.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mx3/mx31moboard-marxbot.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mx3/mx31moboard-marxbot.c	2011-03-14 21:20:32.000000000 -0400
@@ -21,7 +21,6 @@
 #include <linux/slab.h>
 #include <linux/platform_device.h>
 #include <linux/types.h>
-#include <linux/fsl_devices.h>
 
 #include <linux/usb/otg.h>
 
@@ -29,12 +28,11 @@
 #include <mach/hardware.h>
 #include <mach/imx-uart.h>
 #include <mach/iomux-mx3.h>
-#include <mach/mmc.h>
-#include <mach/mxc_ehci.h>
 #include <mach/ulpi.h>
 
 #include <media/soc_camera.h>
 
+#include "devices-imx31.h"
 #include "devices.h"
 
 static unsigned int marxbot_pins[] = {
@@ -116,7 +114,7 @@ static void marxbot_sdhc2_exit(struct de
 	gpio_free(SDHC2_CD);
 }
 
-static struct imxmmc_platform_data sdhc2_pdata = {
+static const struct imxmmc_platform_data sdhc2_pdata __initconst = {
 	.get_ro	= marxbot_sdhc2_get_ro,
 	.init	= marxbot_sdhc2_init,
 	.exit	= marxbot_sdhc2_exit,
@@ -302,7 +300,7 @@ static int marxbot_isp1105_set_vbus(stru
 	return 0;
 }
 
-static struct mxc_usbh_platform_data usbh1_pdata = {
+static struct mxc_usbh_platform_data usbh1_pdata __initdata = {
 	.init	= marxbot_usbh1_hw_init,
 	.portsc	= MXC_EHCI_MODE_UTMI | MXC_EHCI_SERIAL,
 	.flags	= MXC_EHCI_POWER_PINS_ENABLED | MXC_EHCI_INTERFACE_SINGLE_UNI,
@@ -311,6 +309,7 @@ static struct mxc_usbh_platform_data usb
 static int __init marxbot_usbh1_init(void)
 {
 	struct otg_transceiver *otg;
+	struct platform_device *pdev;
 
 	otg = kzalloc(sizeof(*otg), GFP_KERNEL);
 	if (!otg)
@@ -322,10 +321,14 @@ static int __init marxbot_usbh1_init(voi
 
 	usbh1_pdata.otg = otg;
 
-	return mxc_register_device(&mxc_usbh1, &usbh1_pdata);
+	pdev = imx31_add_mxc_ehci_hs(1, &usbh1_pdata);
+	if (IS_ERR(pdev))
+		return PTR_ERR(pdev);
+
+	return 0;
 }
 
-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_ULPI,
 };
@@ -344,7 +347,7 @@ void __init mx31moboard_marxbot_init(voi
 
 	dspics_resets_init();
 
-	mxc_register_device(&mxcsdhc_device1, &sdhc2_pdata);
+	imx31_add_mxc_mmc(1, &sdhc2_pdata);
 
 	spi_register_board_info(marxbot_spi_board_info,
 		ARRAY_SIZE(marxbot_spi_board_info));
@@ -357,7 +360,7 @@ void __init mx31moboard_marxbot_init(voi
 	gpio_direction_input(IOMUX_TO_GPIO(MX31_PIN_LCS0));
 	gpio_export(IOMUX_TO_GPIO(MX31_PIN_LCS0), false);
 
-	mxc_register_device(&mxc_otg_udc_device, &usb_pdata);
+	imx31_add_fsl_usb2_udc(&usb_pdata);
 
 	marxbot_usbh1_init();
 }
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mx3/mx31moboard-smartbot.c linux-libre-2.6.38-gnu1/arch/arm/mach-mx3/mx31moboard-smartbot.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mx3/mx31moboard-smartbot.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mx3/mx31moboard-smartbot.c	2011-03-14 21:20:32.000000000 -0400
@@ -19,7 +19,6 @@
 #include <linux/i2c.h>
 #include <linux/platform_device.h>
 #include <linux/types.h>
-#include <linux/fsl_devices.h>
 
 #include <linux/usb/otg.h>
 #include <linux/usb/ulpi.h>
@@ -28,7 +27,6 @@
 #include <mach/hardware.h>
 #include <mach/iomux-mx3.h>
 #include <mach/board-mx31moboard.h>
-#include <mach/mxc_ehci.h>
 #include <mach/ulpi.h>
 
 #include <media/soc_camera.h>
@@ -118,24 +116,30 @@ static int __init smartbot_cam_init(void
 	return 0;
 }
 
-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_ULPI,
 };
 
 #if defined(CONFIG_USB_ULPI)
 
-static struct mxc_usbh_platform_data otg_host_pdata = {
+static struct mxc_usbh_platform_data otg_host_pdata __initdata = {
 	.portsc = MXC_EHCI_MODE_ULPI | MXC_EHCI_UTMI_8BIT,
 	.flags	= MXC_EHCI_POWER_PINS_ENABLED,
 };
 
 static int __init smartbot_otg_host_init(void)
 {
+	struct platform_device *pdev;
+
 	otg_host_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops,
 			ULPI_OTG_DRVVBUS | ULPI_OTG_DRVVBUS_EXT);
 
-	return mxc_register_device(&mxc_otg_host, &otg_host_pdata);
+	pdev = imx31_add_mxc_ehci_otg(&otg_host_pdata);
+	if (IS_ERR(pdev))
+		return PTR_ERR(pdev);
+
+	return 0;
 }
 #else
 static inline int smartbot_otg_host_init(void) { return 0; }
@@ -182,7 +186,7 @@ void __init mx31moboard_smartbot_init(in
 
 	switch (board) {
 	case MX31SMARTBOT:
-		mxc_register_device(&mxc_otg_udc_device, &usb_pdata);
+		imx31_add_fsl_usb2_udc(&usb_pdata);
 		break;
 	case MX31EYEBOT:
 		smartbot_otg_host_init();
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mx5/board-cpuimx51.c linux-libre-2.6.38-gnu1/arch/arm/mach-mx5/board-cpuimx51.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mx5/board-cpuimx51.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mx5/board-cpuimx51.c	2011-03-14 21:20:32.000000000 -0400
@@ -40,11 +40,11 @@
 #include "devices-imx51.h"
 #include "devices.h"
 
-#define CPUIMX51_USBH1_STP	(0*32 + 27)
-#define CPUIMX51_QUARTA_GPIO	(2*32 + 28)
-#define CPUIMX51_QUARTB_GPIO	(2*32 + 25)
-#define CPUIMX51_QUARTC_GPIO	(2*32 + 26)
-#define CPUIMX51_QUARTD_GPIO	(2*32 + 27)
+#define CPUIMX51_USBH1_STP	IMX_GPIO_NR(1, 27)
+#define CPUIMX51_QUARTA_GPIO	IMX_GPIO_NR(3, 28)
+#define CPUIMX51_QUARTB_GPIO	IMX_GPIO_NR(3, 25)
+#define CPUIMX51_QUARTC_GPIO	IMX_GPIO_NR(3, 26)
+#define CPUIMX51_QUARTD_GPIO	IMX_GPIO_NR(3, 27)
 #define CPUIMX51_QUARTA_IRQ	(MXC_INTERNAL_IRQS + CPUIMX51_QUARTA_GPIO)
 #define CPUIMX51_QUARTB_IRQ	(MXC_INTERNAL_IRQS + CPUIMX51_QUARTB_GPIO)
 #define CPUIMX51_QUARTC_IRQ	(MXC_INTERNAL_IRQS + CPUIMX51_QUARTC_GPIO)
@@ -113,7 +113,7 @@ static struct platform_device *devices[]
 #endif
 };
 
-static struct pad_desc eukrea_cpuimx51_pads[] = {
+static iomux_v3_cfg_t eukrea_cpuimx51_pads[] = {
 	/* UART1 */
 	MX51_PAD_UART1_RXD__UART1_RXD,
 	MX51_PAD_UART1_TXD__UART1_TXD,
@@ -121,15 +121,15 @@ static struct pad_desc eukrea_cpuimx51_p
 	MX51_PAD_UART1_CTS__UART1_CTS,
 
 	/* I2C2 */
-	MX51_PAD_GPIO_1_2__I2C2_SCL,
-	MX51_PAD_GPIO_1_3__I2C2_SDA,
-	MX51_PAD_NANDF_D10__GPIO_3_30,
+	MX51_PAD_GPIO1_2__I2C2_SCL,
+	MX51_PAD_GPIO1_3__I2C2_SDA,
+	MX51_PAD_NANDF_D10__GPIO3_30,
 
 	/* QUART IRQ */
-	MX51_PAD_NANDF_D15__GPIO_3_25,
-	MX51_PAD_NANDF_D14__GPIO_3_26,
-	MX51_PAD_NANDF_D13__GPIO_3_27,
-	MX51_PAD_NANDF_D12__GPIO_3_28,
+	MX51_PAD_NANDF_D15__GPIO3_25,
+	MX51_PAD_NANDF_D14__GPIO3_26,
+	MX51_PAD_NANDF_D13__GPIO3_27,
+	MX51_PAD_NANDF_D12__GPIO3_28,
 
 	/* USB HOST1 */
 	MX51_PAD_USBH1_CLK__USBH1_CLK,
@@ -178,6 +178,8 @@ static int initialize_otg_port(struct pl
 	void __iomem *usbother_base;
 
 	usb_base = ioremap(MX51_OTG_BASE_ADDR, SZ_4K);
+	if (!usb_base)
+		return -ENOMEM;
 	usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET;
 
 	/* Set the PHY clock to 19.2MHz */
@@ -196,6 +198,8 @@ static int initialize_usbh1_port(struct
 	void __iomem *usbother_base;
 
 	usb_base = ioremap(MX51_OTG_BASE_ADDR, SZ_4K);
+	if (!usb_base)
+		return -ENOMEM;
 	usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET;
 
 	/* The clock for the USBH1 ULPI port will come externally from the PHY. */
@@ -292,7 +296,7 @@ static struct sys_timer mxc_timer = {
 
 MACHINE_START(EUKREA_CPUIMX51, "Eukrea CPUIMX51 Module")
 	/* Maintainer: Eric Bénard <eric@eukrea.com> */
-	.boot_params = PHYS_OFFSET + 0x100,
+	.boot_params = MX51_PHYS_OFFSET + 0x100,
 	.map_io = mx51_map_io,
 	.init_irq = mx51_init_irq,
 	.init_machine = eukrea_cpuimx51_init,
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mx5/board-cpuimx51sd.c linux-libre-2.6.38-gnu1/arch/arm/mach-mx5/board-cpuimx51sd.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mx5/board-cpuimx51sd.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mx5/board-cpuimx51sd.c	2011-03-14 21:20:32.000000000 -0400
@@ -43,19 +43,19 @@
 #include "devices-imx51.h"
 #include "devices.h"
 
-#define USBH1_RST		(1*32 + 28)
-#define ETH_RST			(1*32 + 31)
-#define TSC2007_IRQGPIO		(2*32 + 12)
-#define CAN_IRQGPIO		(0*32 + 1)
-#define CAN_RST			(3*32 + 15)
-#define CAN_NCS			(3*32 + 24)
-#define CAN_RXOBF		(0*32 + 4)
-#define CAN_RX1BF		(0*32 + 6)
-#define CAN_TXORTS		(0*32 + 7)
-#define CAN_TX1RTS		(0*32 + 8)
-#define CAN_TX2RTS		(0*32 + 9)
-#define I2C_SCL			(3*32 + 16)
-#define I2C_SDA			(3*32 + 17)
+#define USBH1_RST		IMX_GPIO_NR(2, 28)
+#define ETH_RST			IMX_GPIO_NR(2, 31)
+#define TSC2007_IRQGPIO		IMX_GPIO_NR(3, 12)
+#define CAN_IRQGPIO		IMX_GPIO_NR(1, 1)
+#define CAN_RST			IMX_GPIO_NR(4, 15)
+#define CAN_NCS			IMX_GPIO_NR(4, 24)
+#define CAN_RXOBF		IMX_GPIO_NR(1, 4)
+#define CAN_RX1BF		IMX_GPIO_NR(1, 6)
+#define CAN_TXORTS		IMX_GPIO_NR(1, 7)
+#define CAN_TX1RTS		IMX_GPIO_NR(1, 8)
+#define CAN_TX2RTS		IMX_GPIO_NR(1, 9)
+#define I2C_SCL			IMX_GPIO_NR(4, 16)
+#define I2C_SDA			IMX_GPIO_NR(4, 17)
 
 /* USB_CTRL_1 */
 #define MX51_USB_CTRL_1_OFFSET		0x10
@@ -65,10 +65,7 @@
 #define	MX51_USB_PLL_DIV_19_2_MHZ	0x01
 #define	MX51_USB_PLL_DIV_24_MHZ		0x02
 
-#define CPUIMX51SD_GPIO_3_12 IOMUX_PAD(0x57C, 0x194, 3, 0x0, 0, \
-				MX51_PAD_CTRL_1 | PAD_CTL_PUS_22K_UP)
-
-static struct pad_desc eukrea_cpuimx51sd_pads[] = {
+static iomux_v3_cfg_t eukrea_cpuimx51sd_pads[] = {
 	/* UART1 */
 	MX51_PAD_UART1_RXD__UART1_RXD,
 	MX51_PAD_UART1_TXD__UART1_TXD,
@@ -88,30 +85,33 @@ static struct pad_desc eukrea_cpuimx51sd
 	MX51_PAD_USBH1_DATA6__USBH1_DATA6,
 	MX51_PAD_USBH1_DATA7__USBH1_DATA7,
 	MX51_PAD_USBH1_STP__USBH1_STP,
-	MX51_PAD_EIM_CS3__GPIO_2_28,		/* PHY nRESET */
+	MX51_PAD_EIM_CS3__GPIO2_28,		/* PHY nRESET */
 
 	/* FEC */
-	MX51_PAD_EIM_DTACK__GPIO_2_31,		/* PHY nRESET */
+	MX51_PAD_EIM_DTACK__GPIO2_31,		/* PHY nRESET */
 
 	/* HSI2C */
-	MX51_PAD_I2C1_CLK__GPIO_4_16,
-	MX51_PAD_I2C1_DAT__GPIO_4_17,
+	MX51_PAD_I2C1_CLK__GPIO4_16,
+	MX51_PAD_I2C1_DAT__GPIO4_17,
 
 	/* CAN */
 	MX51_PAD_CSPI1_MOSI__ECSPI1_MOSI,
 	MX51_PAD_CSPI1_MISO__ECSPI1_MISO,
 	MX51_PAD_CSPI1_SCLK__ECSPI1_SCLK,
-	MX51_PAD_CSPI1_SS0__GPIO_4_24,		/* nCS */
-	MX51_PAD_CSI2_PIXCLK__GPIO_4_15,	/* nReset */
-	MX51_PAD_GPIO_1_1__GPIO_1_1,		/* IRQ */
-	MX51_PAD_GPIO_1_4__GPIO_1_4,		/* Control signals */
-	MX51_PAD_GPIO_1_6__GPIO_1_6,
-	MX51_PAD_GPIO_1_7__GPIO_1_7,
-	MX51_PAD_GPIO_1_8__GPIO_1_8,
-	MX51_PAD_GPIO_1_9__GPIO_1_9,
+	MX51_PAD_CSPI1_SS0__GPIO4_24,		/* nCS */
+	MX51_PAD_CSI2_PIXCLK__GPIO4_15,		/* nReset */
+	MX51_PAD_GPIO1_1__GPIO1_1,		/* IRQ */
+	MX51_PAD_GPIO1_4__GPIO1_4,		/* Control signals */
+	MX51_PAD_GPIO1_6__GPIO1_6,
+	MX51_PAD_GPIO1_7__GPIO1_7,
+	MX51_PAD_GPIO1_8__GPIO1_8,
+	MX51_PAD_GPIO1_9__GPIO1_9,
 
 	/* Touchscreen */
-	CPUIMX51SD_GPIO_3_12,			/* IRQ */
+	/* IRQ */
+	_MX51_PAD_CSI1_D8__GPIO3_12 | 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),
 };
 
 static const struct imxuart_platform_data uart_pdata __initconst = {
@@ -157,6 +157,8 @@ static int initialize_otg_port(struct pl
 	void __iomem *usbother_base;
 
 	usb_base = ioremap(MX51_OTG_BASE_ADDR, SZ_4K);
+	if (!usb_base)
+		return -ENOMEM;
 	usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET;
 
 	/* Set the PHY clock to 19.2MHz */
@@ -175,6 +177,8 @@ static int initialize_usbh1_port(struct
 	void __iomem *usbother_base;
 
 	usb_base = ioremap(MX51_OTG_BASE_ADDR, SZ_4K);
+	if (!usb_base)
+		return -ENOMEM;
 	usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET;
 
 	/* The clock for the USBH1 ULPI port will come from the PHY. */
@@ -243,7 +247,7 @@ static struct spi_board_info cpuimx51sd_
 		.mode		= SPI_MODE_0,
 		.chip_select     = 0,
 		.platform_data   = &mcp251x_info,
-		.irq             = gpio_to_irq(0 * 32 + 1)
+		.irq             = gpio_to_irq(CAN_IRQGPIO)
 	},
 };
 
@@ -323,7 +327,7 @@ static struct sys_timer mxc_timer = {
 
 MACHINE_START(EUKREA_CPUIMX51SD, "Eukrea CPUIMX51SD")
 	/* Maintainer: Eric Bénard <eric@eukrea.com> */
-	.boot_params = PHYS_OFFSET + 0x100,
+	.boot_params = MX51_PHYS_OFFSET + 0x100,
 	.map_io = mx51_map_io,
 	.init_irq = mx51_init_irq,
 	.init_machine = eukrea_cpuimx51sd_init,
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mx5/board-mx50_rdp.c linux-libre-2.6.38-gnu1/arch/arm/mach-mx5/board-mx50_rdp.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mx5/board-mx50_rdp.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mx5/board-mx50_rdp.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,197 @@
+/*
+ * 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.
+ */
+
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/fsl_devices.h>
+
+#include <mach/common.h>
+#include <mach/hardware.h>
+#include <mach/iomux-mx50.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-mx50.h"
+
+static iomux_v3_cfg_t mx50_rdp_pads[] __initdata = {
+	/* SD1 */
+	MX50_PAD_ECSPI2_SS0__GPIO_4_19,
+	MX50_PAD_EIM_CRE__GPIO_1_27,
+	MX50_PAD_SD1_CMD__SD1_CMD,
+
+	MX50_PAD_SD1_CLK__SD1_CLK,
+	MX50_PAD_SD1_D0__SD1_D0,
+	MX50_PAD_SD1_D1__SD1_D1,
+	MX50_PAD_SD1_D2__SD1_D2,
+	MX50_PAD_SD1_D3__SD1_D3,
+
+	/* SD2 */
+	MX50_PAD_SD2_CD__GPIO_5_17,
+	MX50_PAD_SD2_WP__GPIO_5_16,
+	MX50_PAD_SD2_CMD__SD2_CMD,
+	MX50_PAD_SD2_CLK__SD2_CLK,
+	MX50_PAD_SD2_D0__SD2_D0,
+	MX50_PAD_SD2_D1__SD2_D1,
+	MX50_PAD_SD2_D2__SD2_D2,
+	MX50_PAD_SD2_D3__SD2_D3,
+	MX50_PAD_SD2_D4__SD2_D4,
+	MX50_PAD_SD2_D5__SD2_D5,
+	MX50_PAD_SD2_D6__SD2_D6,
+	MX50_PAD_SD2_D7__SD2_D7,
+
+	/* SD3 */
+	MX50_PAD_SD3_CMD__SD3_CMD,
+	MX50_PAD_SD3_CLK__SD3_CLK,
+	MX50_PAD_SD3_D0__SD3_D0,
+	MX50_PAD_SD3_D1__SD3_D1,
+	MX50_PAD_SD3_D2__SD3_D2,
+	MX50_PAD_SD3_D3__SD3_D3,
+	MX50_PAD_SD3_D4__SD3_D4,
+	MX50_PAD_SD3_D5__SD3_D5,
+	MX50_PAD_SD3_D6__SD3_D6,
+	MX50_PAD_SD3_D7__SD3_D7,
+
+	/* PWR_INT */
+	MX50_PAD_ECSPI2_MISO__GPIO_4_18,
+
+	/* UART pad setting */
+	MX50_PAD_UART1_TXD__UART1_TXD,
+	MX50_PAD_UART1_RXD__UART1_RXD,
+	MX50_PAD_UART1_RTS__UART1_RTS,
+	MX50_PAD_UART2_TXD__UART2_TXD,
+	MX50_PAD_UART2_RXD__UART2_RXD,
+	MX50_PAD_UART2_CTS__UART2_CTS,
+	MX50_PAD_UART2_RTS__UART2_RTS,
+
+	MX50_PAD_I2C1_SCL__I2C1_SCL,
+	MX50_PAD_I2C1_SDA__I2C1_SDA,
+	MX50_PAD_I2C2_SCL__I2C2_SCL,
+	MX50_PAD_I2C2_SDA__I2C2_SDA,
+
+	MX50_PAD_EPITO__USBH1_PWR,
+	/* Need to comment below line if
+	 * one needs to debug owire.
+	 */
+	MX50_PAD_OWIRE__USBH1_OC,
+	/* using gpio to control otg pwr */
+	MX50_PAD_PWM2__GPIO_6_25,
+	MX50_PAD_I2C3_SCL__USBOTG_OC,
+
+	MX50_PAD_SSI_RXC__FEC_MDIO,
+	MX50_PAD_SSI_RXC__FEC_MDIO,
+	MX50_PAD_DISP_D0__FEC_TXCLK,
+	MX50_PAD_DISP_D1__FEC_RX_ER,
+	MX50_PAD_DISP_D2__FEC_RX_DV,
+	MX50_PAD_DISP_D3__FEC_RXD1,
+	MX50_PAD_DISP_D4__FEC_RXD0,
+	MX50_PAD_DISP_D5__FEC_TX_EN,
+	MX50_PAD_DISP_D6__FEC_TXD1,
+	MX50_PAD_DISP_D7__FEC_TXD0,
+	MX50_PAD_SSI_RXFS__FEC_MDC,
+	MX50_PAD_I2C3_SDA__GPIO_6_23,
+	MX50_PAD_ECSPI1_SCLK__GPIO_4_12,
+
+	MX50_PAD_CSPI_SS0__CSPI_SS0,
+	MX50_PAD_ECSPI1_MOSI__CSPI_SS1,
+	MX50_PAD_CSPI_MOSI__CSPI_MOSI,
+	MX50_PAD_CSPI_MISO__CSPI_MISO,
+
+	/* SGTL500_OSC_EN */
+	MX50_PAD_UART1_CTS__GPIO_6_8,
+
+	/* SGTL_AMP_SHDN */
+	MX50_PAD_UART3_RXD__GPIO_6_15,
+
+	/* Keypad */
+	MX50_PAD_KEY_COL0__KEY_COL0,
+	MX50_PAD_KEY_ROW0__KEY_ROW0,
+	MX50_PAD_KEY_COL1__KEY_COL1,
+	MX50_PAD_KEY_ROW1__KEY_ROW1,
+	MX50_PAD_KEY_COL2__KEY_COL2,
+	MX50_PAD_KEY_ROW2__KEY_ROW2,
+	MX50_PAD_KEY_COL3__KEY_COL3,
+	MX50_PAD_KEY_ROW3__KEY_ROW3,
+	MX50_PAD_EIM_DA0__KEY_COL4,
+	MX50_PAD_EIM_DA1__KEY_ROW4,
+	MX50_PAD_EIM_DA2__KEY_COL5,
+	MX50_PAD_EIM_DA3__KEY_ROW5,
+	MX50_PAD_EIM_DA4__KEY_COL6,
+	MX50_PAD_EIM_DA5__KEY_ROW6,
+	MX50_PAD_EIM_DA6__KEY_COL7,
+	MX50_PAD_EIM_DA7__KEY_ROW7,
+	/*EIM pads */
+	MX50_PAD_EIM_DA8__GPIO_1_8,
+	MX50_PAD_EIM_DA9__GPIO_1_9,
+	MX50_PAD_EIM_DA10__GPIO_1_10,
+	MX50_PAD_EIM_DA11__GPIO_1_11,
+	MX50_PAD_EIM_DA12__GPIO_1_12,
+	MX50_PAD_EIM_DA13__GPIO_1_13,
+	MX50_PAD_EIM_DA14__GPIO_1_14,
+	MX50_PAD_EIM_DA15__GPIO_1_15,
+	MX50_PAD_EIM_CS2__GPIO_1_16,
+	MX50_PAD_EIM_CS1__GPIO_1_17,
+	MX50_PAD_EIM_CS0__GPIO_1_18,
+	MX50_PAD_EIM_EB0__GPIO_1_19,
+	MX50_PAD_EIM_EB1__GPIO_1_20,
+	MX50_PAD_EIM_WAIT__GPIO_1_21,
+	MX50_PAD_EIM_BCLK__GPIO_1_22,
+	MX50_PAD_EIM_RDY__GPIO_1_23,
+	MX50_PAD_EIM_OE__GPIO_1_24,
+};
+
+/* Serial ports */
+static const struct imxuart_platform_data uart_pdata __initconst = {
+	.flags = IMXUART_HAVE_RTSCTS,
+};
+
+/*
+ * Board specific initialization.
+ */
+static void __init mx50_rdp_board_init(void)
+{
+	mxc_iomux_v3_setup_multiple_pads(mx50_rdp_pads,
+					ARRAY_SIZE(mx50_rdp_pads));
+
+	imx50_add_imx_uart(0, &uart_pdata);
+	imx50_add_imx_uart(1, &uart_pdata);
+}
+
+static void __init mx50_rdp_timer_init(void)
+{
+	mx50_clocks_init(32768, 24000000, 22579200);
+}
+
+static struct sys_timer mx50_rdp_timer = {
+	.init	= mx50_rdp_timer_init,
+};
+
+MACHINE_START(MX50_RDP, "Freescale MX50 Reference Design Platform")
+	.map_io = mx50_map_io,
+	.init_irq = mx50_init_irq,
+	.init_machine = mx50_rdp_board_init,
+	.timer = &mx50_rdp_timer,
+MACHINE_END
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mx5/board-mx51_3ds.c linux-libre-2.6.38-gnu1/arch/arm/mach-mx5/board-mx51_3ds.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mx5/board-mx51_3ds.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mx5/board-mx51_3ds.c	2011-03-14 21:20:32.000000000 -0400
@@ -12,7 +12,6 @@
 
 #include <linux/irq.h>
 #include <linux/platform_device.h>
-#include <linux/input/matrix_keypad.h>
 #include <linux/spi/spi.h>
 
 #include <asm/mach-types.h>
@@ -30,7 +29,7 @@
 #define EXPIO_PARENT_INT	(MXC_INTERNAL_IRQS + GPIO_PORTA + 6)
 #define MX51_3DS_ECSPI2_CS	(GPIO_PORTC + 28)
 
-static struct pad_desc mx51_3ds_pads[] = {
+static iomux_v3_cfg_t mx51_3ds_pads[] = {
 	/* UART1 */
 	MX51_PAD_UART1_RXD__UART1_RXD,
 	MX51_PAD_UART1_TXD__UART1_TXD,
@@ -50,7 +49,7 @@ static struct pad_desc mx51_3ds_pads[] =
 	MX51_PAD_EIM_D27__UART3_RTS,
 
 	/* CPLD PARENT IRQ PIN */
-	MX51_PAD_GPIO_1_6__GPIO_1_6,
+	MX51_PAD_GPIO1_6__GPIO1_6,
 
 	/* KPP */
 	MX51_PAD_KEY_ROW0__KEY_ROW0,
@@ -68,7 +67,7 @@ static struct pad_desc mx51_3ds_pads[] =
 	MX51_PAD_NANDF_RB2__ECSPI2_SCLK,
 	MX51_PAD_NANDF_RB3__ECSPI2_MISO,
 	MX51_PAD_NANDF_D15__ECSPI2_MOSI,
-	MX51_PAD_NANDF_D12__GPIO_3_28,
+	MX51_PAD_NANDF_D12__GPIO3_28,
 };
 
 /* Serial ports */
@@ -120,14 +119,14 @@ static int mx51_3ds_board_keymap[] = {
 	KEY(3, 5, KEY_BACK)
 };
 
-static struct matrix_keymap_data mx51_3ds_map_data = {
+static const struct matrix_keymap_data mx51_3ds_map_data __initconst = {
 	.keymap		= mx51_3ds_board_keymap,
 	.keymap_size	= ARRAY_SIZE(mx51_3ds_board_keymap),
 };
 
 static void mxc_init_keypad(void)
 {
-	mxc_register_device(&mxc_keypad_device, &mx51_3ds_map_data);
+	imx51_add_imx_keypad(&mx51_3ds_map_data);
 }
 #else
 static inline void mxc_init_keypad(void)
@@ -172,6 +171,7 @@ static void __init mxc_board_init(void)
 		printk(KERN_WARNING "Init of the debugboard failed, all "
 				    "devices on the board are unusable.\n");
 
+	imx51_add_sdhci_esdhc_imx(0, NULL);
 	mxc_init_keypad();
 }
 
@@ -186,7 +186,7 @@ static struct sys_timer mxc_timer = {
 
 MACHINE_START(MX51_3DS, "Freescale MX51 3-Stack Board")
 	/* Maintainer: Freescale Semiconductor, Inc. */
-	.boot_params = PHYS_OFFSET + 0x100,
+	.boot_params = MX51_PHYS_OFFSET + 0x100,
 	.map_io = mx51_map_io,
 	.init_irq = mx51_init_irq,
 	.init_machine = mxc_board_init,
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mx5/board-mx51_babbage.c linux-libre-2.6.38-gnu1/arch/arm/mach-mx5/board-mx51_babbage.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mx5/board-mx51_babbage.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mx5/board-mx51_babbage.c	2011-03-14 21:20:32.000000000 -0400
@@ -20,6 +20,8 @@
 #include <linux/fec.h>
 #include <linux/gpio_keys.h>
 #include <linux/input.h>
+#include <linux/spi/flash.h>
+#include <linux/spi/spi.h>
 
 #include <mach/common.h>
 #include <mach/hardware.h>
@@ -36,11 +38,13 @@
 #include "devices.h"
 #include "cpu_op-mx51.h"
 
-#define BABBAGE_USB_HUB_RESET	(0*32 + 7)	/* GPIO_1_7 */
-#define BABBAGE_USBH1_STP	(0*32 + 27)	/* GPIO_1_27 */
-#define BABBAGE_PHY_RESET	(1*32 + 5)	/* GPIO_2_5 */
-#define BABBAGE_FEC_PHY_RESET	(1*32 + 14)	/* GPIO_2_14 */
-#define BABBAGE_POWER_KEY	(1*32 + 21)	/* GPIO_2_21 */
+#define BABBAGE_USB_HUB_RESET	IMX_GPIO_NR(1, 7)
+#define BABBAGE_USBH1_STP	IMX_GPIO_NR(1, 27)
+#define BABBAGE_PHY_RESET	IMX_GPIO_NR(2, 5)
+#define BABBAGE_FEC_PHY_RESET	IMX_GPIO_NR(2, 14)
+#define BABBAGE_POWER_KEY	IMX_GPIO_NR(2, 21)
+#define BABBAGE_ECSPI1_CS0	IMX_GPIO_NR(4, 24)
+#define BABBAGE_ECSPI1_CS1	IMX_GPIO_NR(4, 25)
 
 /* USB_CTRL_1 */
 #define MX51_USB_CTRL_1_OFFSET			0x10
@@ -65,7 +69,7 @@ static const struct gpio_keys_platform_d
 	.nbuttons	= ARRAY_SIZE(babbage_buttons),
 };
 
-static struct pad_desc mx51babbage_pads[] = {
+static iomux_v3_cfg_t mx51babbage_pads[] = {
 	/* UART1 */
 	MX51_PAD_UART1_RXD__UART1_RXD,
 	MX51_PAD_UART1_TXD__UART1_TXD,
@@ -91,8 +95,8 @@ static struct pad_desc mx51babbage_pads[
 	MX51_PAD_KEY_COL5__I2C2_SDA,
 
 	/* HSI2C */
-	MX51_PAD_I2C1_CLK__HSI2C_CLK,
-	MX51_PAD_I2C1_DAT__HSI2C_DAT,
+	MX51_PAD_I2C1_CLK__I2C1_CLK,
+	MX51_PAD_I2C1_DAT__I2C1_DAT,
 
 	/* USB HOST1 */
 	MX51_PAD_USBH1_CLK__USBH1_CLK,
@@ -108,29 +112,29 @@ static struct pad_desc mx51babbage_pads[
 	MX51_PAD_USBH1_DATA7__USBH1_DATA7,
 
 	/* USB HUB reset line*/
-	MX51_PAD_GPIO_1_7__GPIO_1_7,
+	MX51_PAD_GPIO1_7__GPIO1_7,
 
 	/* FEC */
 	MX51_PAD_EIM_EB2__FEC_MDIO,
-	MX51_PAD_EIM_EB3__FEC_RDAT1,
-	MX51_PAD_EIM_CS2__FEC_RDAT2,
-	MX51_PAD_EIM_CS3__FEC_RDAT3,
+	MX51_PAD_EIM_EB3__FEC_RDATA1,
+	MX51_PAD_EIM_CS2__FEC_RDATA2,
+	MX51_PAD_EIM_CS3__FEC_RDATA3,
 	MX51_PAD_EIM_CS4__FEC_RX_ER,
 	MX51_PAD_EIM_CS5__FEC_CRS,
 	MX51_PAD_NANDF_RB2__FEC_COL,
-	MX51_PAD_NANDF_RB3__FEC_RXCLK,
-	MX51_PAD_NANDF_RB6__FEC_RDAT0,
-	MX51_PAD_NANDF_RB7__FEC_TDAT0,
+	MX51_PAD_NANDF_RB3__FEC_RX_CLK,
+	MX51_PAD_NANDF_D9__FEC_RDATA0,
+	MX51_PAD_NANDF_D8__FEC_TDATA0,
 	MX51_PAD_NANDF_CS2__FEC_TX_ER,
 	MX51_PAD_NANDF_CS3__FEC_MDC,
-	MX51_PAD_NANDF_CS4__FEC_TDAT1,
-	MX51_PAD_NANDF_CS5__FEC_TDAT2,
-	MX51_PAD_NANDF_CS6__FEC_TDAT3,
+	MX51_PAD_NANDF_CS4__FEC_TDATA1,
+	MX51_PAD_NANDF_CS5__FEC_TDATA2,
+	MX51_PAD_NANDF_CS6__FEC_TDATA3,
 	MX51_PAD_NANDF_CS7__FEC_TX_EN,
 	MX51_PAD_NANDF_RDY_INT__FEC_TX_CLK,
 
 	/* FEC PHY reset line */
-	MX51_PAD_EIM_A20__GPIO_2_14,
+	MX51_PAD_EIM_A20__GPIO2_14,
 
 	/* SD 1 */
 	MX51_PAD_SD1_CMD__SD1_CMD,
@@ -147,6 +151,13 @@ static struct pad_desc mx51babbage_pads[
 	MX51_PAD_SD2_DATA1__SD2_DATA1,
 	MX51_PAD_SD2_DATA2__SD2_DATA2,
 	MX51_PAD_SD2_DATA3__SD2_DATA3,
+
+	/* eCSPI1 */
+	MX51_PAD_CSPI1_MISO__ECSPI1_MISO,
+	MX51_PAD_CSPI1_MOSI__ECSPI1_MOSI,
+	MX51_PAD_CSPI1_SCLK__ECSPI1_SCLK,
+	MX51_PAD_CSPI1_SS0__GPIO4_24,
+	MX51_PAD_CSPI1_SS1__GPIO4_25,
 };
 
 /* Serial ports */
@@ -177,12 +188,12 @@ static struct imxi2c_platform_data babba
 
 static int gpio_usbh1_active(void)
 {
-	struct pad_desc usbh1stp_gpio = MX51_PAD_USBH1_STP__GPIO_1_27;
-	struct pad_desc phyreset_gpio = MX51_PAD_EIM_D21__GPIO_2_5;
+	iomux_v3_cfg_t usbh1stp_gpio = MX51_PAD_USBH1_STP__GPIO1_27;
+	iomux_v3_cfg_t phyreset_gpio = MX51_PAD_EIM_D21__GPIO2_5;
 	int ret;
 
 	/* Set USBH1_STP to GPIO and toggle it */
-	mxc_iomux_v3_setup_pad(&usbh1stp_gpio);
+	mxc_iomux_v3_setup_pad(usbh1stp_gpio);
 	ret = gpio_request(BABBAGE_USBH1_STP, "usbh1_stp");
 
 	if (ret) {
@@ -195,7 +206,7 @@ static int gpio_usbh1_active(void)
 	gpio_free(BABBAGE_USBH1_STP);
 
 	/* De-assert USB PHY RESETB */
-	mxc_iomux_v3_setup_pad(&phyreset_gpio);
+	mxc_iomux_v3_setup_pad(phyreset_gpio);
 	ret = gpio_request(BABBAGE_PHY_RESET, "phy_reset");
 
 	if (ret) {
@@ -251,6 +262,8 @@ static int initialize_otg_port(struct pl
 	void __iomem *usbother_base;
 
 	usb_base = ioremap(MX51_OTG_BASE_ADDR, SZ_4K);
+	if (!usb_base)
+		return -ENOMEM;
 	usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET;
 
 	/* Set the PHY clock to 19.2MHz */
@@ -269,6 +282,8 @@ static int initialize_usbh1_port(struct
 	void __iomem *usbother_base;
 
 	usb_base = ioremap(MX51_OTG_BASE_ADDR, SZ_4K);
+	if (!usb_base)
+		return -ENOMEM;
 	usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET;
 
 	/* The clock for the USBH1 ULPI port will come externally from the PHY. */
@@ -310,13 +325,35 @@ static int __init babbage_otg_mode(char
 }
 __setup("otg_mode=", babbage_otg_mode);
 
+static struct spi_board_info mx51_babbage_spi_board_info[] __initdata = {
+	{
+		.modalias = "mtd_dataflash",
+		.max_speed_hz = 25000000,
+		.bus_num = 0,
+		.chip_select = 1,
+		.mode = SPI_MODE_0,
+		.platform_data = NULL,
+	},
+};
+
+static int mx51_babbage_spi_cs[] = {
+	BABBAGE_ECSPI1_CS0,
+	BABBAGE_ECSPI1_CS1,
+};
+
+static const struct spi_imx_master mx51_babbage_spi_pdata __initconst = {
+	.chipselect     = mx51_babbage_spi_cs,
+	.num_chipselect = ARRAY_SIZE(mx51_babbage_spi_cs),
+};
+
 /*
  * Board specific initialization.
  */
 static void __init mxc_board_init(void)
 {
-	struct pad_desc usbh1stp = MX51_PAD_USBH1_STP__USBH1_STP;
-	struct pad_desc power_key = MX51_PAD_EIM_A27__GPIO_2_21;
+	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);
 
 #if defined(CONFIG_CPU_FREQ_IMX)
 	get_cpu_op = mx51_get_cpu_op;
@@ -328,8 +365,7 @@ static void __init mxc_board_init(void)
 	imx51_add_fec(NULL);
 
 	/* Set the PAD settings for the pwr key. */
-	power_key.pad_ctrl = MX51_GPIO_PAD_CTRL_2;
-	mxc_iomux_v3_setup_pad(&power_key);
+	mxc_iomux_v3_setup_pad(power_key);
 	imx51_add_gpio_keys(&imx_button_data);
 
 	imx51_add_imx_i2c(0, &babbage_i2c_data);
@@ -346,11 +382,16 @@ static void __init mxc_board_init(void)
 	gpio_usbh1_active();
 	mxc_register_device(&mxc_usbh1_device, &usbh1_config);
 	/* setback USBH1_STP to be function */
-	mxc_iomux_v3_setup_pad(&usbh1stp);
+	mxc_iomux_v3_setup_pad(usbh1stp);
 	babbage_usbhub_reset();
 
-	imx51_add_esdhc(0, NULL);
-	imx51_add_esdhc(1, NULL);
+	imx51_add_sdhci_esdhc_imx(0, NULL);
+	imx51_add_sdhci_esdhc_imx(1, NULL);
+
+	spi_register_board_info(mx51_babbage_spi_board_info,
+		ARRAY_SIZE(mx51_babbage_spi_board_info));
+	imx51_add_ecspi(0, &mx51_babbage_spi_pdata);
+	imx51_add_imx2_wdt(0, NULL);
 }
 
 static void __init mx51_babbage_timer_init(void)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mx5/board-mx51_efikamx.c linux-libre-2.6.38-gnu1/arch/arm/mach-mx5/board-mx51_efikamx.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mx5/board-mx51_efikamx.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mx5/board-mx51_efikamx.c	2011-03-14 21:20:32.000000000 -0400
@@ -18,9 +18,13 @@
 #include <linux/platform_device.h>
 #include <linux/i2c.h>
 #include <linux/gpio.h>
+#include <linux/leds.h>
+#include <linux/input.h>
 #include <linux/delay.h>
 #include <linux/io.h>
 #include <linux/fsl_devices.h>
+#include <linux/spi/flash.h>
+#include <linux/spi/spi.h>
 
 #include <mach/common.h>
 #include <mach/hardware.h>
@@ -39,12 +43,81 @@
 
 #define	MX51_USB_PLL_DIV_24_MHZ	0x01
 
-static struct pad_desc mx51efikamx_pads[] = {
+#define EFIKAMX_PCBID0		IMX_GPIO_NR(3, 16)
+#define EFIKAMX_PCBID1		IMX_GPIO_NR(3, 17)
+#define EFIKAMX_PCBID2		IMX_GPIO_NR(3, 11)
+
+#define EFIKAMX_BLUE_LED	IMX_GPIO_NR(3, 13)
+#define EFIKAMX_GREEN_LED	IMX_GPIO_NR(3, 14)
+#define EFIKAMX_RED_LED		IMX_GPIO_NR(3, 15)
+
+#define EFIKAMX_POWER_KEY	IMX_GPIO_NR(2, 31)
+
+#define EFIKAMX_SPI_CS0		IMX_GPIO_NR(4, 24)
+#define EFIKAMX_SPI_CS1		IMX_GPIO_NR(4, 25)
+
+/* board 1.1 doesn't have same reset gpio */
+#define EFIKAMX_RESET1_1	IMX_GPIO_NR(3, 2)
+#define EFIKAMX_RESET		IMX_GPIO_NR(1, 4)
+
+/* the pci ids pin have pull up. they're driven low according to board id */
+#define MX51_PAD_PCBID0	IOMUX_PAD(0x518, 0x130, 3, 0x0,   0, PAD_CTL_PUS_100K_UP)
+#define MX51_PAD_PCBID1	IOMUX_PAD(0x51C, 0x134, 3, 0x0,   0, PAD_CTL_PUS_100K_UP)
+#define MX51_PAD_PCBID2	IOMUX_PAD(0x504, 0x128, 3, 0x0,   0, PAD_CTL_PUS_100K_UP)
+#define MX51_PAD_PWRKEY	IOMUX_PAD(0x48c, 0x0f8, 1, 0x0,   0, PAD_CTL_PUS_100K_UP | PAD_CTL_PKE)
+
+static iomux_v3_cfg_t mx51efikamx_pads[] = {
 	/* UART1 */
 	MX51_PAD_UART1_RXD__UART1_RXD,
 	MX51_PAD_UART1_TXD__UART1_TXD,
 	MX51_PAD_UART1_RTS__UART1_RTS,
 	MX51_PAD_UART1_CTS__UART1_CTS,
+	/* board id */
+	MX51_PAD_PCBID0,
+	MX51_PAD_PCBID1,
+	MX51_PAD_PCBID2,
+
+	/* SD 1 */
+	MX51_PAD_SD1_CMD__SD1_CMD,
+	MX51_PAD_SD1_CLK__SD1_CLK,
+	MX51_PAD_SD1_DATA0__SD1_DATA0,
+	MX51_PAD_SD1_DATA1__SD1_DATA1,
+	MX51_PAD_SD1_DATA2__SD1_DATA2,
+	MX51_PAD_SD1_DATA3__SD1_DATA3,
+
+	/* SD 2 */
+	MX51_PAD_SD2_CMD__SD2_CMD,
+	MX51_PAD_SD2_CLK__SD2_CLK,
+	MX51_PAD_SD2_DATA0__SD2_DATA0,
+	MX51_PAD_SD2_DATA1__SD2_DATA1,
+	MX51_PAD_SD2_DATA2__SD2_DATA2,
+	MX51_PAD_SD2_DATA3__SD2_DATA3,
+
+	/* SD/MMC WP/CD */
+	MX51_PAD_GPIO1_0__SD1_CD,
+	MX51_PAD_GPIO1_1__SD1_WP,
+	MX51_PAD_GPIO1_7__SD2_WP,
+	MX51_PAD_GPIO1_8__SD2_CD,
+
+	/* leds */
+	MX51_PAD_CSI1_D9__GPIO3_13,
+	MX51_PAD_CSI1_VSYNC__GPIO3_14,
+	MX51_PAD_CSI1_HSYNC__GPIO3_15,
+
+	/* power key */
+	MX51_PAD_PWRKEY,
+
+	/* spi */
+	MX51_PAD_CSPI1_MOSI__ECSPI1_MOSI,
+	MX51_PAD_CSPI1_MISO__ECSPI1_MISO,
+	MX51_PAD_CSPI1_SS0__GPIO4_24,
+	MX51_PAD_CSPI1_SS1__GPIO4_25,
+	MX51_PAD_CSPI1_RDY__ECSPI1_RDY,
+	MX51_PAD_CSPI1_SCLK__ECSPI1_SCLK,
+
+	/* reset */
+	MX51_PAD_DI1_PIN13__GPIO3_2,
+	MX51_PAD_GPIO1_4__GPIO1_4,
 };
 
 /* Serial ports */
@@ -75,6 +148,8 @@ static int initialize_otg_port(struct pl
 	void __iomem *usb_base;
 	void __iomem *usbother_base;
 	usb_base = ioremap(MX51_OTG_BASE_ADDR, SZ_4K);
+	if (!usb_base)
+		return -ENOMEM;
 	usbother_base = (void __iomem *)(usb_base + MX5_USBOTHER_REGS_OFFSET);
 
 	/* Set the PHY clock to 19.2MHz */
@@ -92,12 +167,182 @@ static struct mxc_usbh_platform_data dr_
 	.flags  = MXC_EHCI_INTERNAL_PHY,
 };
 
+/*   PCBID2  PCBID1 PCBID0  STATE
+	1       1      1    ER1:rev1.1
+	1       1      0    ER2:rev1.2
+	1       0      1    ER3:rev1.3
+	1       0      0    ER4:rev1.4
+*/
+static void __init mx51_efikamx_board_id(void)
+{
+	int id;
+
+	/* things are taking time to settle */
+	msleep(150);
+
+	gpio_request(EFIKAMX_PCBID0, "pcbid0");
+	gpio_direction_input(EFIKAMX_PCBID0);
+	gpio_request(EFIKAMX_PCBID1, "pcbid1");
+	gpio_direction_input(EFIKAMX_PCBID1);
+	gpio_request(EFIKAMX_PCBID2, "pcbid2");
+	gpio_direction_input(EFIKAMX_PCBID2);
+
+	id = gpio_get_value(EFIKAMX_PCBID0);
+	id |= gpio_get_value(EFIKAMX_PCBID1) << 1;
+	id |= gpio_get_value(EFIKAMX_PCBID2) << 2;
+
+	switch (id) {
+	case 7:
+		system_rev = 0x11;
+		break;
+	case 6:
+		system_rev = 0x12;
+		break;
+	case 5:
+		system_rev = 0x13;
+		break;
+	case 4:
+		system_rev = 0x14;
+		break;
+	default:
+		system_rev = 0x10;
+		break;
+	}
+
+	if ((system_rev == 0x10)
+		|| (system_rev == 0x12)
+		|| (system_rev == 0x14)) {
+		printk(KERN_WARNING
+			"EfikaMX: Unsupported board revision 1.%u!\n",
+			system_rev & 0xf);
+	}
+}
+
+static struct gpio_led mx51_efikamx_leds[] = {
+	{
+		.name = "efikamx:green",
+		.default_trigger = "default-on",
+		.gpio = EFIKAMX_GREEN_LED,
+	},
+	{
+		.name = "efikamx:red",
+		.default_trigger = "ide-disk",
+		.gpio = EFIKAMX_RED_LED,
+	},
+	{
+		.name = "efikamx:blue",
+		.default_trigger = "mmc0",
+		.gpio = EFIKAMX_BLUE_LED,
+	},
+};
+
+static struct gpio_led_platform_data mx51_efikamx_leds_data = {
+	.leds = mx51_efikamx_leds,
+	.num_leds = ARRAY_SIZE(mx51_efikamx_leds),
+};
+
+static struct platform_device mx51_efikamx_leds_device = {
+	.name = "leds-gpio",
+	.id = -1,
+	.dev = {
+		.platform_data = &mx51_efikamx_leds_data,
+	},
+};
+
+static struct gpio_keys_button mx51_efikamx_powerkey[] = {
+	{
+		.code = KEY_POWER,
+		.gpio = EFIKAMX_POWER_KEY,
+		.type = EV_PWR,
+		.desc = "Power Button (CM)",
+		.wakeup = 1,
+		.debounce_interval = 10, /* ms */
+	},
+};
+
+static const struct gpio_keys_platform_data mx51_efikamx_powerkey_data __initconst = {
+	.buttons = mx51_efikamx_powerkey,
+	.nbuttons = ARRAY_SIZE(mx51_efikamx_powerkey),
+};
+
+static struct mtd_partition mx51_efikamx_spi_nor_partitions[] = {
+	{
+	 .name = "u-boot",
+	 .offset = 0,
+	 .size = SZ_256K,
+	},
+	{
+	  .name = "config",
+	  .offset = MTDPART_OFS_APPEND,
+	  .size = SZ_64K,
+	},
+};
+
+static struct flash_platform_data mx51_efikamx_spi_flash_data = {
+	.name		= "spi_flash",
+	.parts		= mx51_efikamx_spi_nor_partitions,
+	.nr_parts	= ARRAY_SIZE(mx51_efikamx_spi_nor_partitions),
+	.type		= "sst25vf032b",
+};
+
+static struct spi_board_info mx51_efikamx_spi_board_info[] __initdata = {
+	{
+		.modalias = "m25p80",
+		.max_speed_hz = 25000000,
+		.bus_num = 0,
+		.chip_select = 1,
+		.platform_data = &mx51_efikamx_spi_flash_data,
+		.irq = -1,
+	},
+};
+
+static int mx51_efikamx_spi_cs[] = {
+	EFIKAMX_SPI_CS0,
+	EFIKAMX_SPI_CS1,
+};
+
+static const struct spi_imx_master mx51_efikamx_spi_pdata __initconst = {
+	.chipselect     = mx51_efikamx_spi_cs,
+	.num_chipselect = ARRAY_SIZE(mx51_efikamx_spi_cs),
+};
+
+void mx51_efikamx_reset(void)
+{
+	if (system_rev == 0x11)
+		gpio_direction_output(EFIKAMX_RESET1_1, 0);
+	else
+		gpio_direction_output(EFIKAMX_RESET, 0);
+}
+
 static void __init mxc_board_init(void)
 {
 	mxc_iomux_v3_setup_multiple_pads(mx51efikamx_pads,
 					ARRAY_SIZE(mx51efikamx_pads));
+	mx51_efikamx_board_id();
 	mxc_register_device(&mxc_usbdr_host_device, &dr_utmi_config);
 	mxc_init_imx_uart();
+	imx51_add_sdhci_esdhc_imx(0, NULL);
+
+	/* on < 1.2 boards both SD controllers are used */
+	if (system_rev < 0x12) {
+		imx51_add_sdhci_esdhc_imx(1, NULL);
+		mx51_efikamx_leds[2].default_trigger = "mmc1";
+	}
+
+	platform_device_register(&mx51_efikamx_leds_device);
+	imx51_add_gpio_keys(&mx51_efikamx_powerkey_data);
+
+	spi_register_board_info(mx51_efikamx_spi_board_info,
+		ARRAY_SIZE(mx51_efikamx_spi_board_info));
+	imx51_add_ecspi(0, &mx51_efikamx_spi_pdata);
+
+	if (system_rev == 0x11) {
+		gpio_request(EFIKAMX_RESET1_1, "reset");
+		gpio_direction_output(EFIKAMX_RESET1_1, 1);
+	} else {
+		gpio_request(EFIKAMX_RESET, "reset");
+		gpio_direction_output(EFIKAMX_RESET, 1);
+	}
 }
 
 static void __init mx51_efikamx_timer_init(void)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mx5/board-mx53_evk.c linux-libre-2.6.38-gnu1/arch/arm/mach-mx5/board-mx53_evk.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mx5/board-mx53_evk.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mx5/board-mx53_evk.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (C) 2010 Yong Shen. <Yong.Shen@linaro.org>
+ */
+
+/*
+ * 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/init.h>
+#include <linux/clk.h>
+#include <linux/fec.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/spi/flash.h>
+#include <linux/spi/spi.h>
+#include <mach/common.h>
+#include <mach/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include <mach/imx-uart.h>
+#include <mach/iomux-mx53.h>
+
+#define SMD_FEC_PHY_RST		IMX_GPIO_NR(7, 6)
+#define EVK_ECSPI1_CS0		IMX_GPIO_NR(2, 30)
+#define EVK_ECSPI1_CS1		IMX_GPIO_NR(3, 19)
+
+#include "crm_regs.h"
+#include "devices-imx53.h"
+
+static iomux_v3_cfg_t mx53_evk_pads[] = {
+	MX53_PAD_CSI0_D10__UART1_TXD,
+	MX53_PAD_CSI0_D11__UART1_RXD,
+	MX53_PAD_ATA_DIOW__UART1_TXD,
+	MX53_PAD_ATA_DMACK__UART1_RXD,
+
+	MX53_PAD_ATA_BUFFER_EN__UART2_RXD,
+	MX53_PAD_ATA_DMARQ__UART2_TXD,
+	MX53_PAD_ATA_DIOR__UART2_RTS,
+	MX53_PAD_ATA_INTRQ__UART2_CTS,
+
+	MX53_PAD_ATA_CS_0__UART3_TXD,
+	MX53_PAD_ATA_CS_1__UART3_RXD,
+	MX53_PAD_ATA_DA_1__UART3_CTS,
+	MX53_PAD_ATA_DA_2__UART3_RTS,
+
+	MX53_PAD_EIM_D16__CSPI1_SCLK,
+	MX53_PAD_EIM_D17__CSPI1_MISO,
+	MX53_PAD_EIM_D18__CSPI1_MOSI,
+
+	/* ecspi chip select lines */
+	MX53_PAD_EIM_EB2__GPIO_2_30,
+	MX53_PAD_EIM_D19__GPIO_3_19,
+};
+
+static const struct imxuart_platform_data mx53_evk_uart_pdata __initconst = {
+	.flags = IMXUART_HAVE_RTSCTS,
+};
+
+static inline void mx53_evk_init_uart(void)
+{
+	imx53_add_imx_uart(0, &mx53_evk_uart_pdata);
+	imx53_add_imx_uart(1, &mx53_evk_uart_pdata);
+	imx53_add_imx_uart(2, &mx53_evk_uart_pdata);
+}
+
+static const struct imxi2c_platform_data mx53_evk_i2c_data __initconst = {
+	.bitrate = 100000,
+};
+
+static inline void mx53_evk_fec_reset(void)
+{
+	int ret;
+
+	/* reset FEC PHY */
+	ret = gpio_request(SMD_FEC_PHY_RST, "fec-phy-reset");
+	if (ret) {
+		printk(KERN_ERR"failed to get GPIO_FEC_PHY_RESET: %d\n", ret);
+		return;
+	}
+	gpio_direction_output(SMD_FEC_PHY_RST, 0);
+	gpio_set_value(SMD_FEC_PHY_RST, 0);
+	msleep(1);
+	gpio_set_value(SMD_FEC_PHY_RST, 1);
+}
+
+static struct fec_platform_data mx53_evk_fec_pdata = {
+	.phy = PHY_INTERFACE_MODE_RMII,
+};
+
+static struct spi_board_info mx53_evk_spi_board_info[] __initdata = {
+	{
+		.modalias = "mtd_dataflash",
+		.max_speed_hz = 25000000,
+		.bus_num = 0,
+		.chip_select = 1,
+		.mode = SPI_MODE_0,
+		.platform_data = NULL,
+	},
+};
+
+static int mx53_evk_spi_cs[] = {
+	EVK_ECSPI1_CS0,
+	EVK_ECSPI1_CS1,
+};
+
+static const struct spi_imx_master mx53_evk_spi_data __initconst = {
+	.chipselect     = mx53_evk_spi_cs,
+	.num_chipselect = ARRAY_SIZE(mx53_evk_spi_cs),
+};
+
+static void __init mx53_evk_board_init(void)
+{
+	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);
+
+	imx53_add_imx_i2c(0, &mx53_evk_i2c_data);
+	imx53_add_imx_i2c(1, &mx53_evk_i2c_data);
+
+	imx53_add_sdhci_esdhc_imx(0, NULL);
+	imx53_add_sdhci_esdhc_imx(1, NULL);
+
+	spi_register_board_info(mx53_evk_spi_board_info,
+		ARRAY_SIZE(mx53_evk_spi_board_info));
+	imx53_add_ecspi(0, &mx53_evk_spi_data);
+}
+
+static void __init mx53_evk_timer_init(void)
+{
+	mx53_clocks_init(32768, 24000000, 22579200, 0);
+}
+
+static struct sys_timer mx53_evk_timer = {
+	.init	= mx53_evk_timer_init,
+};
+
+MACHINE_START(MX53_EVK, "Freescale MX53 EVK Board")
+	.map_io = mx53_map_io,
+	.init_irq = mx53_init_irq,
+	.init_machine = mx53_evk_board_init,
+	.timer = &mx53_evk_timer,
+MACHINE_END
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mx5/board-mx53_loco.c linux-libre-2.6.38-gnu1/arch/arm/mach-mx5/board-mx53_loco.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mx5/board-mx53_loco.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mx5/board-mx53_loco.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,111 @@
+/*
+ * 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/init.h>
+#include <linux/clk.h>
+#include <linux/fec.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+
+#include <mach/common.h>
+#include <mach/hardware.h>
+#include <mach/imx-uart.h>
+#include <mach/iomux-mx53.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+
+#include "crm_regs.h"
+#include "devices-imx53.h"
+
+#define LOCO_FEC_PHY_RST		IMX_GPIO_NR(7, 6)
+
+static iomux_v3_cfg_t mx53_loco_pads[] = {
+	MX53_PAD_CSI0_D10__UART1_TXD,
+	MX53_PAD_CSI0_D11__UART1_RXD,
+	MX53_PAD_ATA_DIOW__UART1_TXD,
+	MX53_PAD_ATA_DMACK__UART1_RXD,
+
+	MX53_PAD_ATA_BUFFER_EN__UART2_RXD,
+	MX53_PAD_ATA_DMARQ__UART2_TXD,
+	MX53_PAD_ATA_DIOR__UART2_RTS,
+	MX53_PAD_ATA_INTRQ__UART2_CTS,
+
+	MX53_PAD_ATA_CS_0__UART3_TXD,
+	MX53_PAD_ATA_CS_1__UART3_RXD,
+	MX53_PAD_ATA_DA_1__UART3_CTS,
+	MX53_PAD_ATA_DA_2__UART3_RTS,
+};
+
+static const struct imxuart_platform_data mx53_loco_uart_data __initconst = {
+	.flags = IMXUART_HAVE_RTSCTS,
+};
+
+static inline void mx53_loco_init_uart(void)
+{
+	imx53_add_imx_uart(0, &mx53_loco_uart_data);
+	imx53_add_imx_uart(1, &mx53_loco_uart_data);
+	imx53_add_imx_uart(2, &mx53_loco_uart_data);
+}
+
+static inline void mx53_loco_fec_reset(void)
+{
+	int ret;
+
+	/* reset FEC PHY */
+	ret = gpio_request(LOCO_FEC_PHY_RST, "fec-phy-reset");
+	if (ret) {
+		printk(KERN_ERR"failed to get GPIO_FEC_PHY_RESET: %d\n", ret);
+		return;
+	}
+	gpio_direction_output(LOCO_FEC_PHY_RST, 0);
+	msleep(1);
+	gpio_set_value(LOCO_FEC_PHY_RST, 1);
+}
+
+static struct fec_platform_data mx53_loco_fec_data = {
+	.phy = PHY_INTERFACE_MODE_RMII,
+};
+
+static void __init mx53_loco_board_init(void)
+{
+	mxc_iomux_v3_setup_multiple_pads(mx53_loco_pads,
+					ARRAY_SIZE(mx53_loco_pads));
+	mx53_loco_init_uart();
+	mx53_loco_fec_reset();
+	imx53_add_fec(&mx53_loco_fec_data);
+}
+
+static void __init mx53_loco_timer_init(void)
+{
+	mx53_clocks_init(32768, 24000000, 0, 0);
+}
+
+static struct sys_timer mx53_loco_timer = {
+	.init	= mx53_loco_timer_init,
+};
+
+MACHINE_START(MX53_LOCO, "Freescale MX53 LOCO Board")
+	.map_io = mx53_map_io,
+	.init_irq = mx53_init_irq,
+	.init_machine = mx53_loco_board_init,
+	.timer = &mx53_loco_timer,
+MACHINE_END
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mx5/board-mx53_smd.c linux-libre-2.6.38-gnu1/arch/arm/mach-mx5/board-mx53_smd.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mx5/board-mx53_smd.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mx5/board-mx53_smd.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,111 @@
+/*
+ * 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/init.h>
+#include <linux/clk.h>
+#include <linux/fec.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+
+#include <mach/common.h>
+#include <mach/hardware.h>
+#include <mach/imx-uart.h>
+#include <mach/iomux-mx53.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+
+#include "crm_regs.h"
+#include "devices-imx53.h"
+
+#define SMD_FEC_PHY_RST		IMX_GPIO_NR(7, 6)
+
+static iomux_v3_cfg_t mx53_smd_pads[] = {
+	MX53_PAD_CSI0_D10__UART1_TXD,
+	MX53_PAD_CSI0_D11__UART1_RXD,
+	MX53_PAD_ATA_DIOW__UART1_TXD,
+	MX53_PAD_ATA_DMACK__UART1_RXD,
+
+	MX53_PAD_ATA_BUFFER_EN__UART2_RXD,
+	MX53_PAD_ATA_DMARQ__UART2_TXD,
+	MX53_PAD_ATA_DIOR__UART2_RTS,
+	MX53_PAD_ATA_INTRQ__UART2_CTS,
+
+	MX53_PAD_ATA_CS_0__UART3_TXD,
+	MX53_PAD_ATA_CS_1__UART3_RXD,
+	MX53_PAD_ATA_DA_1__UART3_CTS,
+	MX53_PAD_ATA_DA_2__UART3_RTS,
+};
+
+static const struct imxuart_platform_data mx53_smd_uart_data __initconst = {
+	.flags = IMXUART_HAVE_RTSCTS,
+};
+
+static inline void mx53_smd_init_uart(void)
+{
+	imx53_add_imx_uart(0, &mx53_smd_uart_data);
+	imx53_add_imx_uart(1, &mx53_smd_uart_data);
+	imx53_add_imx_uart(2, &mx53_smd_uart_data);
+}
+
+static inline void mx53_smd_fec_reset(void)
+{
+	int ret;
+
+	/* reset FEC PHY */
+	ret = gpio_request(SMD_FEC_PHY_RST, "fec-phy-reset");
+	if (ret) {
+		printk(KERN_ERR"failed to get GPIO_FEC_PHY_RESET: %d\n", ret);
+		return;
+	}
+	gpio_direction_output(SMD_FEC_PHY_RST, 0);
+	msleep(1);
+	gpio_set_value(SMD_FEC_PHY_RST, 1);
+}
+
+static struct fec_platform_data mx53_smd_fec_data = {
+	.phy = PHY_INTERFACE_MODE_RMII,
+};
+
+static void __init mx53_smd_board_init(void)
+{
+	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);
+}
+
+static void __init mx53_smd_timer_init(void)
+{
+	mx53_clocks_init(32768, 24000000, 22579200, 0);
+}
+
+static struct sys_timer mx53_smd_timer = {
+	.init	= mx53_smd_timer_init,
+};
+
+MACHINE_START(MX53_SMD, "Freescale MX53 SMD Board")
+	.map_io = mx53_map_io,
+	.init_irq = mx53_init_irq,
+	.init_machine = mx53_smd_board_init,
+	.timer = &mx53_smd_timer,
+MACHINE_END
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mx5/clock-mx51.c linux-libre-2.6.38-gnu1/arch/arm/mach-mx5/clock-mx51.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mx5/clock-mx51.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mx5/clock-mx51.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1140 +0,0 @@
-/*
- * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
- * Copyright (C) 2009-2010 Amit Kucheria <amit.kucheria@canonical.com>
- *
- * 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/mm.h>
-#include <linux/delay.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-
-#include <asm/clkdev.h>
-#include <asm/div64.h>
-
-#include <mach/hardware.h>
-#include <mach/common.h>
-#include <mach/clock.h>
-
-#include "crm_regs.h"
-
-/* External clock values passed-in by the board code */
-static unsigned long external_high_reference, external_low_reference;
-static unsigned long oscillator_reference, ckih2_reference;
-
-static struct clk osc_clk;
-static struct clk pll1_main_clk;
-static struct clk pll1_sw_clk;
-static struct clk pll2_sw_clk;
-static struct clk pll3_sw_clk;
-static struct clk lp_apm_clk;
-static struct clk periph_apm_clk;
-static struct clk ahb_clk;
-static struct clk ipg_clk;
-static struct clk usboh3_clk;
-
-#define MAX_DPLL_WAIT_TRIES	1000 /* 1000 * udelay(1) = 1ms */
-
-/* calculate best pre and post dividers to get the required divider */
-static void __calc_pre_post_dividers(u32 div, u32 *pre, u32 *post,
-	u32 max_pre, u32 max_post)
-{
-	if (div >= max_pre * max_post) {
-		*pre = max_pre;
-		*post = max_post;
-	} else if (div >= max_pre) {
-		u32 min_pre, temp_pre, old_err, err;
-		min_pre = DIV_ROUND_UP(div, max_post);
-		old_err = max_pre;
-		for (temp_pre = max_pre; temp_pre >= min_pre; temp_pre--) {
-			err = div % temp_pre;
-			if (err == 0) {
-				*pre = temp_pre;
-				break;
-			}
-			err = temp_pre - err;
-			if (err < old_err) {
-				old_err = err;
-				*pre = temp_pre;
-			}
-		}
-		*post = DIV_ROUND_UP(div, *pre);
-	} else {
-		*pre = div;
-		*post = 1;
-	}
-}
-
-static void _clk_ccgr_setclk(struct clk *clk, unsigned mode)
-{
-	u32 reg = __raw_readl(clk->enable_reg);
-
-	reg &= ~(MXC_CCM_CCGRx_CG_MASK << clk->enable_shift);
-	reg |= mode << clk->enable_shift;
-
-	__raw_writel(reg, clk->enable_reg);
-}
-
-static int _clk_ccgr_enable(struct clk *clk)
-{
-	_clk_ccgr_setclk(clk, MXC_CCM_CCGRx_MOD_ON);
-	return 0;
-}
-
-static void _clk_ccgr_disable(struct clk *clk)
-{
-	_clk_ccgr_setclk(clk, MXC_CCM_CCGRx_MOD_OFF);
-}
-
-static int _clk_ccgr_enable_inrun(struct clk *clk)
-{
-	_clk_ccgr_setclk(clk, MXC_CCM_CCGRx_MOD_IDLE);
-	return 0;
-}
-
-static void _clk_ccgr_disable_inwait(struct clk *clk)
-{
-	_clk_ccgr_setclk(clk, MXC_CCM_CCGRx_MOD_IDLE);
-}
-
-/*
- * For the 4-to-1 muxed input clock
- */
-static inline u32 _get_mux(struct clk *parent, struct clk *m0,
-			   struct clk *m1, struct clk *m2, struct clk *m3)
-{
-	if (parent == m0)
-		return 0;
-	else if (parent == m1)
-		return 1;
-	else if (parent == m2)
-		return 2;
-	else if (parent == m3)
-		return 3;
-	else
-		BUG();
-
-	return -EINVAL;
-}
-
-static inline void __iomem *_get_pll_base(struct clk *pll)
-{
-	if (pll == &pll1_main_clk)
-		return MX51_DPLL1_BASE;
-	else if (pll == &pll2_sw_clk)
-		return MX51_DPLL2_BASE;
-	else if (pll == &pll3_sw_clk)
-		return MX51_DPLL3_BASE;
-	else
-		BUG();
-
-	return NULL;
-}
-
-static unsigned long clk_pll_get_rate(struct clk *clk)
-{
-	long mfi, mfn, mfd, pdf, ref_clk, mfn_abs;
-	unsigned long dp_op, dp_mfd, dp_mfn, dp_ctl, pll_hfsm, dbl;
-	void __iomem *pllbase;
-	s64 temp;
-	unsigned long parent_rate;
-
-	parent_rate = clk_get_rate(clk->parent);
-
-	pllbase = _get_pll_base(clk);
-
-	dp_ctl = __raw_readl(pllbase + MXC_PLL_DP_CTL);
-	pll_hfsm = dp_ctl & MXC_PLL_DP_CTL_HFSM;
-	dbl = dp_ctl & MXC_PLL_DP_CTL_DPDCK0_2_EN;
-
-	if (pll_hfsm == 0) {
-		dp_op = __raw_readl(pllbase + MXC_PLL_DP_OP);
-		dp_mfd = __raw_readl(pllbase + MXC_PLL_DP_MFD);
-		dp_mfn = __raw_readl(pllbase + MXC_PLL_DP_MFN);
-	} else {
-		dp_op = __raw_readl(pllbase + MXC_PLL_DP_HFS_OP);
-		dp_mfd = __raw_readl(pllbase + MXC_PLL_DP_HFS_MFD);
-		dp_mfn = __raw_readl(pllbase + MXC_PLL_DP_HFS_MFN);
-	}
-	pdf = dp_op & MXC_PLL_DP_OP_PDF_MASK;
-	mfi = (dp_op & MXC_PLL_DP_OP_MFI_MASK) >> MXC_PLL_DP_OP_MFI_OFFSET;
-	mfi = (mfi <= 5) ? 5 : mfi;
-	mfd = dp_mfd & MXC_PLL_DP_MFD_MASK;
-	mfn = mfn_abs = dp_mfn & MXC_PLL_DP_MFN_MASK;
-	/* Sign extend to 32-bits */
-	if (mfn >= 0x04000000) {
-		mfn |= 0xFC000000;
-		mfn_abs = -mfn;
-	}
-
-	ref_clk = 2 * parent_rate;
-	if (dbl != 0)
-		ref_clk *= 2;
-
-	ref_clk /= (pdf + 1);
-	temp = (u64) ref_clk * mfn_abs;
-	do_div(temp, mfd + 1);
-	if (mfn < 0)
-		temp = -temp;
-	temp = (ref_clk * mfi) + temp;
-
-	return temp;
-}
-
-static int _clk_pll_set_rate(struct clk *clk, unsigned long rate)
-{
-	u32 reg;
-	void __iomem *pllbase;
-
-	long mfi, pdf, mfn, mfd = 999999;
-	s64 temp64;
-	unsigned long quad_parent_rate;
-	unsigned long pll_hfsm, dp_ctl;
-	unsigned long parent_rate;
-
-	parent_rate = clk_get_rate(clk->parent);
-
-	pllbase = _get_pll_base(clk);
-
-	quad_parent_rate = 4 * parent_rate;
-	pdf = mfi = -1;
-	while (++pdf < 16 && mfi < 5)
-		mfi = rate * (pdf+1) / quad_parent_rate;
-	if (mfi > 15)
-		return -EINVAL;
-	pdf--;
-
-	temp64 = rate * (pdf+1) - quad_parent_rate * mfi;
-	do_div(temp64, quad_parent_rate/1000000);
-	mfn = (long)temp64;
-
-	dp_ctl = __raw_readl(pllbase + MXC_PLL_DP_CTL);
-	/* use dpdck0_2 */
-	__raw_writel(dp_ctl | 0x1000L, pllbase + MXC_PLL_DP_CTL);
-	pll_hfsm = dp_ctl & MXC_PLL_DP_CTL_HFSM;
-	if (pll_hfsm == 0) {
-		reg = mfi << 4 | pdf;
-		__raw_writel(reg, pllbase + MXC_PLL_DP_OP);
-		__raw_writel(mfd, pllbase + MXC_PLL_DP_MFD);
-		__raw_writel(mfn, pllbase + MXC_PLL_DP_MFN);
-	} else {
-		reg = mfi << 4 | pdf;
-		__raw_writel(reg, pllbase + MXC_PLL_DP_HFS_OP);
-		__raw_writel(mfd, pllbase + MXC_PLL_DP_HFS_MFD);
-		__raw_writel(mfn, pllbase + MXC_PLL_DP_HFS_MFN);
-	}
-
-	return 0;
-}
-
-static int _clk_pll_enable(struct clk *clk)
-{
-	u32 reg;
-	void __iomem *pllbase;
-	int i = 0;
-
-	pllbase = _get_pll_base(clk);
-	reg = __raw_readl(pllbase + MXC_PLL_DP_CTL) | MXC_PLL_DP_CTL_UPEN;
-	__raw_writel(reg, pllbase + MXC_PLL_DP_CTL);
-
-	/* Wait for lock */
-	do {
-		reg = __raw_readl(pllbase + MXC_PLL_DP_CTL);
-		if (reg & MXC_PLL_DP_CTL_LRF)
-			break;
-
-		udelay(1);
-	} while (++i < MAX_DPLL_WAIT_TRIES);
-
-	if (i == MAX_DPLL_WAIT_TRIES) {
-		pr_err("MX5: pll locking failed\n");
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static void _clk_pll_disable(struct clk *clk)
-{
-	u32 reg;
-	void __iomem *pllbase;
-
-	pllbase = _get_pll_base(clk);
-	reg = __raw_readl(pllbase + MXC_PLL_DP_CTL) & ~MXC_PLL_DP_CTL_UPEN;
-	__raw_writel(reg, pllbase + MXC_PLL_DP_CTL);
-}
-
-static int _clk_pll1_sw_set_parent(struct clk *clk, struct clk *parent)
-{
-	u32 reg, step;
-
-	reg = __raw_readl(MXC_CCM_CCSR);
-
-	/* When switching from pll_main_clk to a bypass clock, first select a
-	 * multiplexed clock in 'step_sel', then shift the glitchless mux
-	 * 'pll1_sw_clk_sel'.
-	 *
-	 * When switching back, do it in reverse order
-	 */
-	if (parent == &pll1_main_clk) {
-		/* Switch to pll1_main_clk */
-		reg &= ~MXC_CCM_CCSR_PLL1_SW_CLK_SEL;
-		__raw_writel(reg, MXC_CCM_CCSR);
-		/* step_clk mux switched to lp_apm, to save power. */
-		reg = __raw_readl(MXC_CCM_CCSR);
-		reg &= ~MXC_CCM_CCSR_STEP_SEL_MASK;
-		reg |= (MXC_CCM_CCSR_STEP_SEL_LP_APM <<
-				MXC_CCM_CCSR_STEP_SEL_OFFSET);
-	} else {
-		if (parent == &lp_apm_clk) {
-			step = MXC_CCM_CCSR_STEP_SEL_LP_APM;
-		} else  if (parent == &pll2_sw_clk) {
-			step = MXC_CCM_CCSR_STEP_SEL_PLL2_DIVIDED;
-		} else  if (parent == &pll3_sw_clk) {
-			step = MXC_CCM_CCSR_STEP_SEL_PLL3_DIVIDED;
-		} else
-			return -EINVAL;
-
-		reg &= ~MXC_CCM_CCSR_STEP_SEL_MASK;
-		reg |= (step << MXC_CCM_CCSR_STEP_SEL_OFFSET);
-
-		__raw_writel(reg, MXC_CCM_CCSR);
-		/* Switch to step_clk */
-		reg = __raw_readl(MXC_CCM_CCSR);
-		reg |= MXC_CCM_CCSR_PLL1_SW_CLK_SEL;
-	}
-	__raw_writel(reg, MXC_CCM_CCSR);
-	return 0;
-}
-
-static unsigned long clk_pll1_sw_get_rate(struct clk *clk)
-{
-	u32 reg, div;
-	unsigned long parent_rate;
-
-	parent_rate = clk_get_rate(clk->parent);
-
-	reg = __raw_readl(MXC_CCM_CCSR);
-
-	if (clk->parent == &pll2_sw_clk) {
-		div = ((reg & MXC_CCM_CCSR_PLL2_PODF_MASK) >>
-		       MXC_CCM_CCSR_PLL2_PODF_OFFSET) + 1;
-	} else if (clk->parent == &pll3_sw_clk) {
-		div = ((reg & MXC_CCM_CCSR_PLL3_PODF_MASK) >>
-		       MXC_CCM_CCSR_PLL3_PODF_OFFSET) + 1;
-	} else
-		div = 1;
-	return parent_rate / div;
-}
-
-static int _clk_pll2_sw_set_parent(struct clk *clk, struct clk *parent)
-{
-	u32 reg;
-
-	reg = __raw_readl(MXC_CCM_CCSR);
-
-	if (parent == &pll2_sw_clk)
-		reg &= ~MXC_CCM_CCSR_PLL2_SW_CLK_SEL;
-	else
-		reg |= MXC_CCM_CCSR_PLL2_SW_CLK_SEL;
-
-	__raw_writel(reg, MXC_CCM_CCSR);
-	return 0;
-}
-
-static int _clk_lp_apm_set_parent(struct clk *clk, struct clk *parent)
-{
-	u32 reg;
-
-	if (parent == &osc_clk)
-		reg = __raw_readl(MXC_CCM_CCSR) & ~MXC_CCM_CCSR_LP_APM_SEL;
-	else
-		return -EINVAL;
-
-	__raw_writel(reg, MXC_CCM_CCSR);
-
-	return 0;
-}
-
-static unsigned long clk_cpu_get_rate(struct clk *clk)
-{
-	u32 cacrr, div;
-	unsigned long parent_rate;
-
-	parent_rate = clk_get_rate(clk->parent);
-	cacrr = __raw_readl(MXC_CCM_CACRR);
-	div = (cacrr & MXC_CCM_CACRR_ARM_PODF_MASK) + 1;
-
-	return parent_rate / div;
-}
-
-static int clk_cpu_set_rate(struct clk *clk, unsigned long rate)
-{
-	u32 reg, cpu_podf;
-	unsigned long parent_rate;
-
-	parent_rate = clk_get_rate(clk->parent);
-	cpu_podf = parent_rate / rate - 1;
-	/* use post divider to change freq */
-	reg = __raw_readl(MXC_CCM_CACRR);
-	reg &= ~MXC_CCM_CACRR_ARM_PODF_MASK;
-	reg |= cpu_podf << MXC_CCM_CACRR_ARM_PODF_OFFSET;
-	__raw_writel(reg, MXC_CCM_CACRR);
-
-	return 0;
-}
-
-static int _clk_periph_apm_set_parent(struct clk *clk, struct clk *parent)
-{
-	u32 reg, mux;
-	int i = 0;
-
-	mux = _get_mux(parent, &pll1_sw_clk, &pll3_sw_clk, &lp_apm_clk, NULL);
-
-	reg = __raw_readl(MXC_CCM_CBCMR) & ~MXC_CCM_CBCMR_PERIPH_CLK_SEL_MASK;
-	reg |= mux << MXC_CCM_CBCMR_PERIPH_CLK_SEL_OFFSET;
-	__raw_writel(reg, MXC_CCM_CBCMR);
-
-	/* Wait for lock */
-	do {
-		reg = __raw_readl(MXC_CCM_CDHIPR);
-		if (!(reg &  MXC_CCM_CDHIPR_PERIPH_CLK_SEL_BUSY))
-			break;
-
-		udelay(1);
-	} while (++i < MAX_DPLL_WAIT_TRIES);
-
-	if (i == MAX_DPLL_WAIT_TRIES) {
-		pr_err("MX5: Set parent for periph_apm clock failed\n");
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static int _clk_main_bus_set_parent(struct clk *clk, struct clk *parent)
-{
-	u32 reg;
-
-	reg = __raw_readl(MXC_CCM_CBCDR);
-
-	if (parent == &pll2_sw_clk)
-		reg &= ~MXC_CCM_CBCDR_PERIPH_CLK_SEL;
-	else if (parent == &periph_apm_clk)
-		reg |= MXC_CCM_CBCDR_PERIPH_CLK_SEL;
-	else
-		return -EINVAL;
-
-	__raw_writel(reg, MXC_CCM_CBCDR);
-
-	return 0;
-}
-
-static struct clk main_bus_clk = {
-	.parent = &pll2_sw_clk,
-	.set_parent = _clk_main_bus_set_parent,
-};
-
-static unsigned long clk_ahb_get_rate(struct clk *clk)
-{
-	u32 reg, div;
-	unsigned long parent_rate;
-
-	parent_rate = clk_get_rate(clk->parent);
-
-	reg = __raw_readl(MXC_CCM_CBCDR);
-	div = ((reg & MXC_CCM_CBCDR_AHB_PODF_MASK) >>
-	       MXC_CCM_CBCDR_AHB_PODF_OFFSET) + 1;
-	return parent_rate / div;
-}
-
-
-static int _clk_ahb_set_rate(struct clk *clk, unsigned long rate)
-{
-	u32 reg, div;
-	unsigned long parent_rate;
-	int i = 0;
-
-	parent_rate = clk_get_rate(clk->parent);
-
-	div = parent_rate / rate;
-	if (div > 8 || div < 1 || ((parent_rate / div) != rate))
-		return -EINVAL;
-
-	reg = __raw_readl(MXC_CCM_CBCDR);
-	reg &= ~MXC_CCM_CBCDR_AHB_PODF_MASK;
-	reg |= (div - 1) << MXC_CCM_CBCDR_AHB_PODF_OFFSET;
-	__raw_writel(reg, MXC_CCM_CBCDR);
-
-	/* Wait for lock */
-	do {
-		reg = __raw_readl(MXC_CCM_CDHIPR);
-		if (!(reg & MXC_CCM_CDHIPR_AHB_PODF_BUSY))
-			break;
-
-		udelay(1);
-	} while (++i < MAX_DPLL_WAIT_TRIES);
-
-	if (i == MAX_DPLL_WAIT_TRIES) {
-		pr_err("MX5: clk_ahb_set_rate failed\n");
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static unsigned long _clk_ahb_round_rate(struct clk *clk,
-						unsigned long rate)
-{
-	u32 div;
-	unsigned long parent_rate;
-
-	parent_rate = clk_get_rate(clk->parent);
-
-	div = parent_rate / rate;
-	if (div > 8)
-		div = 8;
-	else if (div == 0)
-		div++;
-	return parent_rate / div;
-}
-
-
-static int _clk_max_enable(struct clk *clk)
-{
-	u32 reg;
-
-	_clk_ccgr_enable(clk);
-
-	/* Handshake with MAX when LPM is entered. */
-	reg = __raw_readl(MXC_CCM_CLPCR);
-	reg &= ~MXC_CCM_CLPCR_BYPASS_MAX_LPM_HS;
-	__raw_writel(reg, MXC_CCM_CLPCR);
-
-	return 0;
-}
-
-static void _clk_max_disable(struct clk *clk)
-{
-	u32 reg;
-
-	_clk_ccgr_disable_inwait(clk);
-
-	/* No Handshake with MAX when LPM is entered as its disabled. */
-	reg = __raw_readl(MXC_CCM_CLPCR);
-	reg |= MXC_CCM_CLPCR_BYPASS_MAX_LPM_HS;
-	__raw_writel(reg, MXC_CCM_CLPCR);
-}
-
-static unsigned long clk_ipg_get_rate(struct clk *clk)
-{
-	u32 reg, div;
-	unsigned long parent_rate;
-
-	parent_rate = clk_get_rate(clk->parent);
-
-	reg = __raw_readl(MXC_CCM_CBCDR);
-	div = ((reg & MXC_CCM_CBCDR_IPG_PODF_MASK) >>
-	       MXC_CCM_CBCDR_IPG_PODF_OFFSET) + 1;
-
-	return parent_rate / div;
-}
-
-static unsigned long clk_ipg_per_get_rate(struct clk *clk)
-{
-	u32 reg, prediv1, prediv2, podf;
-	unsigned long parent_rate;
-
-	parent_rate = clk_get_rate(clk->parent);
-
-	if (clk->parent == &main_bus_clk || clk->parent == &lp_apm_clk) {
-		/* the main_bus_clk is the one before the DVFS engine */
-		reg = __raw_readl(MXC_CCM_CBCDR);
-		prediv1 = ((reg & MXC_CCM_CBCDR_PERCLK_PRED1_MASK) >>
-			   MXC_CCM_CBCDR_PERCLK_PRED1_OFFSET) + 1;
-		prediv2 = ((reg & MXC_CCM_CBCDR_PERCLK_PRED2_MASK) >>
-			   MXC_CCM_CBCDR_PERCLK_PRED2_OFFSET) + 1;
-		podf = ((reg & MXC_CCM_CBCDR_PERCLK_PODF_MASK) >>
-			MXC_CCM_CBCDR_PERCLK_PODF_OFFSET) + 1;
-		return parent_rate / (prediv1 * prediv2 * podf);
-	} else if (clk->parent == &ipg_clk)
-		return parent_rate;
-	else
-		BUG();
-}
-
-static int _clk_ipg_per_set_parent(struct clk *clk, struct clk *parent)
-{
-	u32 reg;
-
-	reg = __raw_readl(MXC_CCM_CBCMR);
-
-	reg &= ~MXC_CCM_CBCMR_PERCLK_LP_APM_CLK_SEL;
-	reg &= ~MXC_CCM_CBCMR_PERCLK_IPG_CLK_SEL;
-
-	if (parent == &ipg_clk)
-		reg |= MXC_CCM_CBCMR_PERCLK_IPG_CLK_SEL;
-	else if (parent == &lp_apm_clk)
-		reg |= MXC_CCM_CBCMR_PERCLK_LP_APM_CLK_SEL;
-	else if (parent != &main_bus_clk)
-		return -EINVAL;
-
-	__raw_writel(reg, MXC_CCM_CBCMR);
-
-	return 0;
-}
-
-#define clk_nfc_set_parent	NULL
-
-static unsigned long clk_nfc_get_rate(struct clk *clk)
-{
-	unsigned long rate;
-	u32 reg, div;
-
-	reg = __raw_readl(MXC_CCM_CBCDR);
-	div = ((reg & MXC_CCM_CBCDR_NFC_PODF_MASK) >>
-	       MXC_CCM_CBCDR_NFC_PODF_OFFSET) + 1;
-	rate = clk_get_rate(clk->parent) / div;
-	WARN_ON(rate == 0);
-	return rate;
-}
-
-static unsigned long clk_nfc_round_rate(struct clk *clk,
-						unsigned long rate)
-{
-	u32 div;
-	unsigned long parent_rate = clk_get_rate(clk->parent);
-
-	if (!rate)
-		return -EINVAL;
-
-	div = parent_rate / rate;
-
-	if (parent_rate % rate)
-		div++;
-
-	if (div > 8)
-		return -EINVAL;
-
-	return parent_rate / div;
-
-}
-
-static int clk_nfc_set_rate(struct clk *clk, unsigned long rate)
-{
-	u32 reg, div;
-
-	div = clk_get_rate(clk->parent) / rate;
-	if (div == 0)
-		div++;
-	if (((clk_get_rate(clk->parent) / div) != rate) || (div > 8))
-		return -EINVAL;
-
-	reg = __raw_readl(MXC_CCM_CBCDR);
-	reg &= ~MXC_CCM_CBCDR_NFC_PODF_MASK;
-	reg |= (div - 1) << MXC_CCM_CBCDR_NFC_PODF_OFFSET;
-	__raw_writel(reg, MXC_CCM_CBCDR);
-
-	while (__raw_readl(MXC_CCM_CDHIPR) &
-			MXC_CCM_CDHIPR_NFC_IPG_INT_MEM_PODF_BUSY){
-	}
-
-	return 0;
-}
-
-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 unsigned long get_oscillator_reference_clock_rate(struct clk *clk)
-{
-	return oscillator_reference;
-}
-
-static unsigned long get_ckih2_reference_clock_rate(struct clk *clk)
-{
-	return ckih2_reference;
-}
-
-static unsigned long clk_emi_slow_get_rate(struct clk *clk)
-{
-	u32 reg, div;
-
-	reg = __raw_readl(MXC_CCM_CBCDR);
-	div = ((reg & MXC_CCM_CBCDR_EMI_PODF_MASK) >>
-	       MXC_CCM_CBCDR_EMI_PODF_OFFSET) + 1;
-
-	return clk_get_rate(clk->parent) / div;
-}
-
-/* External high frequency clock */
-static struct clk ckih_clk = {
-	.get_rate = get_high_reference_clock_rate,
-};
-
-static struct clk ckih2_clk = {
-	.get_rate = get_ckih2_reference_clock_rate,
-};
-
-static struct clk osc_clk = {
-	.get_rate = get_oscillator_reference_clock_rate,
-};
-
-/* External low frequency (32kHz) clock */
-static struct clk ckil_clk = {
-	.get_rate = get_low_reference_clock_rate,
-};
-
-static struct clk pll1_main_clk = {
-	.parent = &osc_clk,
-	.get_rate = clk_pll_get_rate,
-	.enable = _clk_pll_enable,
-	.disable = _clk_pll_disable,
-};
-
-/* Clock tree block diagram (WIP):
- * 	CCM: Clock Controller Module
- *
- * PLL output -> |
- *               | CCM Switcher -> CCM_CLK_ROOT_GEN ->
- * PLL bypass -> |
- *
- */
-
-/* PLL1 SW supplies to ARM core */
-static struct clk pll1_sw_clk = {
-	.parent = &pll1_main_clk,
-	.set_parent = _clk_pll1_sw_set_parent,
-	.get_rate = clk_pll1_sw_get_rate,
-};
-
-/* PLL2 SW supplies to AXI/AHB/IP buses */
-static struct clk pll2_sw_clk = {
-	.parent = &osc_clk,
-	.get_rate = clk_pll_get_rate,
-	.set_rate = _clk_pll_set_rate,
-	.set_parent = _clk_pll2_sw_set_parent,
-	.enable = _clk_pll_enable,
-	.disable = _clk_pll_disable,
-};
-
-/* PLL3 SW supplies to serial clocks like USB, SSI, etc. */
-static struct clk pll3_sw_clk = {
-	.parent = &osc_clk,
-	.set_rate = _clk_pll_set_rate,
-	.get_rate = clk_pll_get_rate,
-	.enable = _clk_pll_enable,
-	.disable = _clk_pll_disable,
-};
-
-/* Low-power Audio Playback Mode clock */
-static struct clk lp_apm_clk = {
-	.parent = &osc_clk,
-	.set_parent = _clk_lp_apm_set_parent,
-};
-
-static struct clk periph_apm_clk = {
-	.parent = &pll1_sw_clk,
-	.set_parent = _clk_periph_apm_set_parent,
-};
-
-static struct clk cpu_clk = {
-	.parent = &pll1_sw_clk,
-	.get_rate = clk_cpu_get_rate,
-	.set_rate = clk_cpu_set_rate,
-};
-
-static struct clk ahb_clk = {
-	.parent = &main_bus_clk,
-	.get_rate = clk_ahb_get_rate,
-	.set_rate = _clk_ahb_set_rate,
-	.round_rate = _clk_ahb_round_rate,
-};
-
-/* Main IP interface clock for access to registers */
-static struct clk ipg_clk = {
-	.parent = &ahb_clk,
-	.get_rate = clk_ipg_get_rate,
-};
-
-static struct clk ipg_perclk = {
-	.parent = &lp_apm_clk,
-	.get_rate = clk_ipg_per_get_rate,
-	.set_parent = _clk_ipg_per_set_parent,
-};
-
-static struct clk ahb_max_clk = {
-	.parent = &ahb_clk,
-	.enable_reg = MXC_CCM_CCGR0,
-	.enable_shift = MXC_CCM_CCGRx_CG14_OFFSET,
-	.enable = _clk_max_enable,
-	.disable = _clk_max_disable,
-};
-
-static struct clk aips_tz1_clk = {
-	.parent = &ahb_clk,
-	.secondary = &ahb_max_clk,
-	.enable_reg = MXC_CCM_CCGR0,
-	.enable_shift = MXC_CCM_CCGRx_CG12_OFFSET,
-	.enable = _clk_ccgr_enable,
-	.disable = _clk_ccgr_disable_inwait,
-};
-
-static struct clk aips_tz2_clk = {
-	.parent = &ahb_clk,
-	.secondary = &ahb_max_clk,
-	.enable_reg = MXC_CCM_CCGR0,
-	.enable_shift = MXC_CCM_CCGRx_CG13_OFFSET,
-	.enable = _clk_ccgr_enable,
-	.disable = _clk_ccgr_disable_inwait,
-};
-
-static struct clk gpt_32k_clk = {
-	.id = 0,
-	.parent = &ckil_clk,
-};
-
-static struct clk kpp_clk = {
-	.id = 0,
-};
-
-static struct clk emi_slow_clk = {
-	.parent = &pll2_sw_clk,
-	.enable_reg = MXC_CCM_CCGR5,
-	.enable_shift = MXC_CCM_CCGRx_CG8_OFFSET,
-	.enable = _clk_ccgr_enable,
-	.disable = _clk_ccgr_disable_inwait,
-	.get_rate = clk_emi_slow_get_rate,
-};
-
-#define DEFINE_CLOCK_CCGR(name, i, er, es, pfx, p, s)	\
-	static struct clk name = {			\
-		.id		= i,			\
-		.enable_reg	= er,			\
-		.enable_shift	= es,			\
-		.get_rate	= pfx##_get_rate,	\
-		.set_rate	= pfx##_set_rate,	\
-		.round_rate	= pfx##_round_rate,	\
-		.set_parent	= pfx##_set_parent,	\
-		.enable		= _clk_ccgr_enable,	\
-		.disable	= _clk_ccgr_disable,	\
-		.parent		= p,			\
-		.secondary	= s,			\
-	}
-
-#define DEFINE_CLOCK_MAX(name, i, er, es, pfx, p, s)	\
-	static struct clk name = {			\
-		.id		= i,			\
-		.enable_reg	= er,			\
-		.enable_shift	= es,			\
-		.get_rate	= pfx##_get_rate,	\
-		.set_rate	= pfx##_set_rate,	\
-		.set_parent	= pfx##_set_parent,	\
-		.enable		= _clk_max_enable,	\
-		.disable	= _clk_max_disable,	\
-		.parent		= p,			\
-		.secondary	= s,			\
-	}
-
-#define CLK_GET_RATE(name, nr, bitsname)				\
-static unsigned long clk_##name##_get_rate(struct clk *clk)		\
-{									\
-	u32 reg, pred, podf;						\
-									\
-	reg = __raw_readl(MXC_CCM_CSCDR##nr);				\
-	pred = (reg & MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_MASK)	\
-		>> MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_OFFSET;	\
-	podf = (reg & MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_MASK)	\
-		>> MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_OFFSET;	\
-									\
-	return DIV_ROUND_CLOSEST(clk_get_rate(clk->parent),		\
-			(pred + 1) * (podf + 1));			\
-}
-
-#define CLK_SET_PARENT(name, nr, bitsname)				\
-static int clk_##name##_set_parent(struct clk *clk, struct clk *parent)	\
-{									\
-	u32 reg, mux;							\
-									\
-	mux = _get_mux(parent, &pll1_sw_clk, &pll2_sw_clk,		\
-			&pll3_sw_clk, &lp_apm_clk);			\
-	reg = __raw_readl(MXC_CCM_CSCMR##nr) &				\
-		~MXC_CCM_CSCMR##nr##_##bitsname##_CLK_SEL_MASK;		\
-	reg |= mux << MXC_CCM_CSCMR##nr##_##bitsname##_CLK_SEL_OFFSET;	\
-	__raw_writel(reg, MXC_CCM_CSCMR##nr);				\
-									\
-	return 0;							\
-}
-
-#define CLK_SET_RATE(name, nr, bitsname)				\
-static int clk_##name##_set_rate(struct clk *clk, unsigned long rate)	\
-{									\
-	u32 reg, div, parent_rate;					\
-	u32 pre = 0, post = 0;						\
-									\
-	parent_rate = clk_get_rate(clk->parent);			\
-	div = parent_rate / rate;					\
-									\
-	if ((parent_rate / div) != rate)				\
-		return -EINVAL;						\
-									\
-	__calc_pre_post_dividers(div, &pre, &post,			\
-		(MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_MASK >>	\
-		MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_OFFSET) + 1,	\
-		(MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_MASK >>	\
-		MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_OFFSET) + 1);\
-									\
-	/* Set sdhc1 clock divider */					\
-	reg = __raw_readl(MXC_CCM_CSCDR##nr) &				\
-		~(MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_MASK	\
-		| MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_MASK);	\
-	reg |= (post - 1) <<						\
-		MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_OFFSET;	\
-	reg |= (pre - 1) <<						\
-		MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_OFFSET;	\
-	__raw_writel(reg, MXC_CCM_CSCDR##nr);				\
-									\
-	return 0;							\
-}
-
-/* UART */
-CLK_GET_RATE(uart, 1, UART)
-CLK_SET_PARENT(uart, 1, UART)
-
-static struct clk uart_root_clk = {
-	.parent = &pll2_sw_clk,
-	.get_rate = clk_uart_get_rate,
-	.set_parent = clk_uart_set_parent,
-};
-
-/* USBOH3 */
-CLK_GET_RATE(usboh3, 1, USBOH3)
-CLK_SET_PARENT(usboh3, 1, USBOH3)
-
-static struct clk usboh3_clk = {
-	.parent = &pll2_sw_clk,
-	.get_rate = clk_usboh3_get_rate,
-	.set_parent = clk_usboh3_set_parent,
-};
-
-/* eCSPI */
-CLK_GET_RATE(ecspi, 2, CSPI)
-CLK_SET_PARENT(ecspi, 1, CSPI)
-
-static struct clk ecspi_main_clk = {
-	.parent = &pll3_sw_clk,
-	.get_rate = clk_ecspi_get_rate,
-	.set_parent = clk_ecspi_set_parent,
-};
-
-/* eSDHC */
-CLK_GET_RATE(esdhc1, 1, ESDHC1_MSHC1)
-CLK_SET_PARENT(esdhc1, 1, ESDHC1_MSHC1)
-CLK_SET_RATE(esdhc1, 1, ESDHC1_MSHC1)
-
-CLK_GET_RATE(esdhc2, 1, ESDHC2_MSHC2)
-CLK_SET_PARENT(esdhc2, 1, ESDHC2_MSHC2)
-CLK_SET_RATE(esdhc2, 1, ESDHC2_MSHC2)
-
-#define DEFINE_CLOCK_FULL(name, i, er, es, gr, sr, e, d, p, s)		\
-	static struct clk name = {					\
-		.id		= i,					\
-		.enable_reg	= er,					\
-		.enable_shift	= es,					\
-		.get_rate	= gr,					\
-		.set_rate	= sr,					\
-		.enable		= e,					\
-		.disable	= d,					\
-		.parent		= p,					\
-		.secondary	= s,					\
-	}
-
-#define DEFINE_CLOCK(name, i, er, es, gr, sr, p, s)			\
-	DEFINE_CLOCK_FULL(name, i, er, es, gr, sr, _clk_ccgr_enable, _clk_ccgr_disable, p, s)
-
-/* Shared peripheral bus arbiter */
-DEFINE_CLOCK(spba_clk, 0, MXC_CCM_CCGR5, MXC_CCM_CCGRx_CG0_OFFSET,
-	NULL,  NULL, &ipg_clk, NULL);
-
-/* UART */
-DEFINE_CLOCK(uart1_ipg_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG3_OFFSET,
-	NULL,  NULL, &ipg_clk, &aips_tz1_clk);
-DEFINE_CLOCK(uart2_ipg_clk, 1, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG5_OFFSET,
-	NULL,  NULL, &ipg_clk, &aips_tz1_clk);
-DEFINE_CLOCK(uart3_ipg_clk, 2, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG7_OFFSET,
-	NULL,  NULL, &ipg_clk, &spba_clk);
-DEFINE_CLOCK(uart1_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG4_OFFSET,
-	NULL,  NULL, &uart_root_clk, &uart1_ipg_clk);
-DEFINE_CLOCK(uart2_clk, 1, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG6_OFFSET,
-	NULL,  NULL, &uart_root_clk, &uart2_ipg_clk);
-DEFINE_CLOCK(uart3_clk, 2, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG8_OFFSET,
-	NULL,  NULL, &uart_root_clk, &uart3_ipg_clk);
-
-/* GPT */
-DEFINE_CLOCK(gpt_ipg_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG10_OFFSET,
-	NULL,  NULL, &ipg_clk, NULL);
-DEFINE_CLOCK(gpt_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG9_OFFSET,
-	NULL,  NULL, &ipg_clk, &gpt_ipg_clk);
-
-/* I2C */
-DEFINE_CLOCK(i2c1_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG9_OFFSET,
-	NULL, NULL, &ipg_clk, NULL);
-DEFINE_CLOCK(i2c2_clk, 1, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG10_OFFSET,
-	NULL, NULL, &ipg_clk, NULL);
-DEFINE_CLOCK(hsi2c_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG11_OFFSET,
-	NULL, NULL, &ipg_clk, NULL);
-
-/* FEC */
-DEFINE_CLOCK(fec_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG12_OFFSET,
-	NULL,  NULL, &ipg_clk, NULL);
-
-/* NFC */
-DEFINE_CLOCK_CCGR(nfc_clk, 0, MXC_CCM_CCGR5, MXC_CCM_CCGRx_CG10_OFFSET,
-	clk_nfc, &emi_slow_clk, NULL);
-
-/* SSI */
-DEFINE_CLOCK(ssi1_ipg_clk, 0, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG8_OFFSET,
-	NULL, NULL, &ipg_clk, NULL);
-DEFINE_CLOCK(ssi1_clk, 0, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG9_OFFSET,
-	NULL, NULL, &pll3_sw_clk, &ssi1_ipg_clk);
-DEFINE_CLOCK(ssi2_ipg_clk, 1, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG10_OFFSET,
-	NULL, NULL, &ipg_clk, NULL);
-DEFINE_CLOCK(ssi2_clk, 1, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG11_OFFSET,
-	NULL, NULL, &pll3_sw_clk, &ssi2_ipg_clk);
-
-/* eCSPI */
-DEFINE_CLOCK_FULL(ecspi1_ipg_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG9_OFFSET,
-		NULL, NULL, _clk_ccgr_enable_inrun, _clk_ccgr_disable,
-		&ipg_clk, &spba_clk);
-DEFINE_CLOCK(ecspi1_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG10_OFFSET,
-		NULL, NULL, &ecspi_main_clk, &ecspi1_ipg_clk);
-DEFINE_CLOCK_FULL(ecspi2_ipg_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG11_OFFSET,
-		NULL, NULL, _clk_ccgr_enable_inrun, _clk_ccgr_disable,
-		&ipg_clk, &aips_tz2_clk);
-DEFINE_CLOCK(ecspi2_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG12_OFFSET,
-		NULL, NULL, &ecspi_main_clk, &ecspi2_ipg_clk);
-
-/* CSPI */
-DEFINE_CLOCK(cspi_ipg_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG9_OFFSET,
-		NULL, NULL, &ipg_clk, &aips_tz2_clk);
-DEFINE_CLOCK(cspi_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG13_OFFSET,
-		NULL, NULL, &ipg_clk, &cspi_ipg_clk);
-
-/* SDMA */
-DEFINE_CLOCK(sdma_clk, 1, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG15_OFFSET,
-		NULL, NULL, &ahb_clk, NULL);
-
-/* eSDHC */
-DEFINE_CLOCK_FULL(esdhc1_ipg_clk, 0, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG0_OFFSET,
-	NULL,  NULL, _clk_max_enable, _clk_max_disable, &ipg_clk, NULL);
-DEFINE_CLOCK_MAX(esdhc1_clk, 0, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG1_OFFSET,
-	clk_esdhc1, &pll2_sw_clk, &esdhc1_ipg_clk);
-DEFINE_CLOCK_FULL(esdhc2_ipg_clk, 1, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG2_OFFSET,
-	NULL,  NULL, _clk_max_enable, _clk_max_disable, &ipg_clk, NULL);
-DEFINE_CLOCK_MAX(esdhc2_clk, 1, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG3_OFFSET,
-	clk_esdhc2, &pll2_sw_clk, &esdhc2_ipg_clk);
-
-#define _REGISTER_CLOCK(d, n, c) \
-       { \
-		.dev_id = d, \
-		.con_id = n, \
-		.clk = &c,   \
-       },
-
-static struct clk_lookup lookups[] = {
-	_REGISTER_CLOCK("imx-uart.0", NULL, uart1_clk)
-	_REGISTER_CLOCK("imx-uart.1", NULL, uart2_clk)
-	_REGISTER_CLOCK("imx-uart.2", NULL, uart3_clk)
-	_REGISTER_CLOCK(NULL, "gpt", gpt_clk)
-	_REGISTER_CLOCK("fec.0", NULL, fec_clk)
-	_REGISTER_CLOCK("imx-i2c.0", NULL, i2c1_clk)
-	_REGISTER_CLOCK("imx-i2c.1", NULL, i2c2_clk)
-	_REGISTER_CLOCK("imx-i2c.2", NULL, hsi2c_clk)
-	_REGISTER_CLOCK("mxc-ehci.0", "usb", usboh3_clk)
-	_REGISTER_CLOCK("mxc-ehci.0", "usb_ahb", ahb_clk)
-	_REGISTER_CLOCK("mxc-ehci.1", "usb", usboh3_clk)
-	_REGISTER_CLOCK("mxc-ehci.1", "usb_ahb", ahb_clk)
-	_REGISTER_CLOCK("fsl-usb2-udc", "usb", usboh3_clk)
-	_REGISTER_CLOCK("fsl-usb2-udc", "usb_ahb", ahb_clk)
-	_REGISTER_CLOCK("imx-keypad.0", NULL, kpp_clk)
-	_REGISTER_CLOCK("mxc_nand", NULL, nfc_clk)
-	_REGISTER_CLOCK("imx-ssi.0", NULL, ssi1_clk)
-	_REGISTER_CLOCK("imx-ssi.1", NULL, ssi2_clk)
-	_REGISTER_CLOCK("imx-sdma", NULL, sdma_clk)
-	_REGISTER_CLOCK(NULL, "ckih", ckih_clk)
-	_REGISTER_CLOCK(NULL, "ckih2", ckih2_clk)
-	_REGISTER_CLOCK(NULL, "gpt_32k", gpt_32k_clk)
-	_REGISTER_CLOCK("imx51-ecspi.0", NULL, ecspi1_clk)
-	_REGISTER_CLOCK("imx51-ecspi.1", NULL, ecspi2_clk)
-	_REGISTER_CLOCK("imx51-cspi.0", NULL, cspi_clk)
-	_REGISTER_CLOCK("sdhci-esdhc-imx.0", NULL, esdhc1_clk)
-	_REGISTER_CLOCK("sdhci-esdhc-imx.1", NULL, esdhc2_clk)
-	_REGISTER_CLOCK(NULL, "cpu_clk", cpu_clk)
-};
-
-static void clk_tree_init(void)
-{
-	u32 reg;
-
-	ipg_perclk.set_parent(&ipg_perclk, &lp_apm_clk);
-
-	/*
-	 * Initialise the IPG PER CLK dividers to 3. IPG_PER_CLK should be at
-	 * 8MHz, its derived from lp_apm.
-	 *
-	 * FIXME: Verify if true for all boards
-	 */
-	reg = __raw_readl(MXC_CCM_CBCDR);
-	reg &= ~MXC_CCM_CBCDR_PERCLK_PRED1_MASK;
-	reg &= ~MXC_CCM_CBCDR_PERCLK_PRED2_MASK;
-	reg &= ~MXC_CCM_CBCDR_PERCLK_PODF_MASK;
-	reg |= (2 << MXC_CCM_CBCDR_PERCLK_PRED1_OFFSET);
-	__raw_writel(reg, MXC_CCM_CBCDR);
-}
-
-int __init mx51_clocks_init(unsigned long ckil, unsigned long osc,
-			unsigned long ckih1, unsigned long ckih2)
-{
-	int i;
-
-	external_low_reference = ckil;
-	external_high_reference = ckih1;
-	ckih2_reference = ckih2;
-	oscillator_reference = osc;
-
-	for (i = 0; i < ARRAY_SIZE(lookups); i++)
-		clkdev_add(&lookups[i]);
-
-	clk_tree_init();
-
-	clk_enable(&cpu_clk);
-	clk_enable(&main_bus_clk);
-
-	/* set the usboh3_clk parent to pll2_sw_clk */
-	clk_set_parent(&usboh3_clk, &pll2_sw_clk);
-
-	/* Set SDHC parents to be PLL2 */
-	clk_set_parent(&esdhc1_clk, &pll2_sw_clk);
-	clk_set_parent(&esdhc2_clk, &pll2_sw_clk);
-
-	/* set SDHC root clock as 166.25MHZ*/
-	clk_set_rate(&esdhc1_clk, 166250000);
-	clk_set_rate(&esdhc2_clk, 166250000);
-
-	/* System timer */
-	mxc_timer_init(&gpt_clk, MX51_IO_ADDRESS(MX51_GPT1_BASE_ADDR),
-		MX51_MXC_INT_GPT);
-	return 0;
-}
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mx5/clock-mx51-mx53.c linux-libre-2.6.38-gnu1/arch/arm/mach-mx5/clock-mx51-mx53.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mx5/clock-mx51-mx53.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mx5/clock-mx51-mx53.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,1434 @@
+/*
+ * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (C) 2009-2010 Amit Kucheria <amit.kucheria@canonical.com>
+ *
+ * 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/mm.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/clkdev.h>
+
+#include <asm/div64.h>
+
+#include <mach/hardware.h>
+#include <mach/common.h>
+#include <mach/clock.h>
+
+#include "crm_regs.h"
+
+/* External clock values passed-in by the board code */
+static unsigned long external_high_reference, external_low_reference;
+static unsigned long oscillator_reference, ckih2_reference;
+
+static struct clk osc_clk;
+static struct clk pll1_main_clk;
+static struct clk pll1_sw_clk;
+static struct clk pll2_sw_clk;
+static struct clk pll3_sw_clk;
+static struct clk mx53_pll4_sw_clk;
+static struct clk lp_apm_clk;
+static struct clk periph_apm_clk;
+static struct clk ahb_clk;
+static struct clk ipg_clk;
+static struct clk usboh3_clk;
+static struct clk emi_fast_clk;
+static struct clk ipu_clk;
+static struct clk mipi_hsc1_clk;
+
+#define MAX_DPLL_WAIT_TRIES	1000 /* 1000 * udelay(1) = 1ms */
+
+/* calculate best pre and post dividers to get the required divider */
+static void __calc_pre_post_dividers(u32 div, u32 *pre, u32 *post,
+	u32 max_pre, u32 max_post)
+{
+	if (div >= max_pre * max_post) {
+		*pre = max_pre;
+		*post = max_post;
+	} else if (div >= max_pre) {
+		u32 min_pre, temp_pre, old_err, err;
+		min_pre = DIV_ROUND_UP(div, max_post);
+		old_err = max_pre;
+		for (temp_pre = max_pre; temp_pre >= min_pre; temp_pre--) {
+			err = div % temp_pre;
+			if (err == 0) {
+				*pre = temp_pre;
+				break;
+			}
+			err = temp_pre - err;
+			if (err < old_err) {
+				old_err = err;
+				*pre = temp_pre;
+			}
+		}
+		*post = DIV_ROUND_UP(div, *pre);
+	} else {
+		*pre = div;
+		*post = 1;
+	}
+}
+
+static void _clk_ccgr_setclk(struct clk *clk, unsigned mode)
+{
+	u32 reg = __raw_readl(clk->enable_reg);
+
+	reg &= ~(MXC_CCM_CCGRx_CG_MASK << clk->enable_shift);
+	reg |= mode << clk->enable_shift;
+
+	__raw_writel(reg, clk->enable_reg);
+}
+
+static int _clk_ccgr_enable(struct clk *clk)
+{
+	_clk_ccgr_setclk(clk, MXC_CCM_CCGRx_MOD_ON);
+	return 0;
+}
+
+static void _clk_ccgr_disable(struct clk *clk)
+{
+	_clk_ccgr_setclk(clk, MXC_CCM_CCGRx_MOD_OFF);
+}
+
+static int _clk_ccgr_enable_inrun(struct clk *clk)
+{
+	_clk_ccgr_setclk(clk, MXC_CCM_CCGRx_MOD_IDLE);
+	return 0;
+}
+
+static void _clk_ccgr_disable_inwait(struct clk *clk)
+{
+	_clk_ccgr_setclk(clk, MXC_CCM_CCGRx_MOD_IDLE);
+}
+
+/*
+ * For the 4-to-1 muxed input clock
+ */
+static inline u32 _get_mux(struct clk *parent, struct clk *m0,
+			   struct clk *m1, struct clk *m2, struct clk *m3)
+{
+	if (parent == m0)
+		return 0;
+	else if (parent == m1)
+		return 1;
+	else if (parent == m2)
+		return 2;
+	else if (parent == m3)
+		return 3;
+	else
+		BUG();
+
+	return -EINVAL;
+}
+
+static inline void __iomem *_mx51_get_pll_base(struct clk *pll)
+{
+	if (pll == &pll1_main_clk)
+		return MX51_DPLL1_BASE;
+	else if (pll == &pll2_sw_clk)
+		return MX51_DPLL2_BASE;
+	else if (pll == &pll3_sw_clk)
+		return MX51_DPLL3_BASE;
+	else
+		BUG();
+
+	return NULL;
+}
+
+static inline void __iomem *_mx53_get_pll_base(struct clk *pll)
+{
+	if (pll == &pll1_main_clk)
+		return MX53_DPLL1_BASE;
+	else if (pll == &pll2_sw_clk)
+		return MX53_DPLL2_BASE;
+	else if (pll == &pll3_sw_clk)
+		return MX53_DPLL3_BASE;
+	else if (pll == &mx53_pll4_sw_clk)
+		return MX53_DPLL4_BASE;
+	else
+		BUG();
+
+	return NULL;
+}
+
+static inline void __iomem *_get_pll_base(struct clk *pll)
+{
+	if (cpu_is_mx51())
+		return _mx51_get_pll_base(pll);
+	else
+		return _mx53_get_pll_base(pll);
+}
+
+static unsigned long clk_pll_get_rate(struct clk *clk)
+{
+	long mfi, mfn, mfd, pdf, ref_clk, mfn_abs;
+	unsigned long dp_op, dp_mfd, dp_mfn, dp_ctl, pll_hfsm, dbl;
+	void __iomem *pllbase;
+	s64 temp;
+	unsigned long parent_rate;
+
+	parent_rate = clk_get_rate(clk->parent);
+
+	pllbase = _get_pll_base(clk);
+
+	dp_ctl = __raw_readl(pllbase + MXC_PLL_DP_CTL);
+	pll_hfsm = dp_ctl & MXC_PLL_DP_CTL_HFSM;
+	dbl = dp_ctl & MXC_PLL_DP_CTL_DPDCK0_2_EN;
+
+	if (pll_hfsm == 0) {
+		dp_op = __raw_readl(pllbase + MXC_PLL_DP_OP);
+		dp_mfd = __raw_readl(pllbase + MXC_PLL_DP_MFD);
+		dp_mfn = __raw_readl(pllbase + MXC_PLL_DP_MFN);
+	} else {
+		dp_op = __raw_readl(pllbase + MXC_PLL_DP_HFS_OP);
+		dp_mfd = __raw_readl(pllbase + MXC_PLL_DP_HFS_MFD);
+		dp_mfn = __raw_readl(pllbase + MXC_PLL_DP_HFS_MFN);
+	}
+	pdf = dp_op & MXC_PLL_DP_OP_PDF_MASK;
+	mfi = (dp_op & MXC_PLL_DP_OP_MFI_MASK) >> MXC_PLL_DP_OP_MFI_OFFSET;
+	mfi = (mfi <= 5) ? 5 : mfi;
+	mfd = dp_mfd & MXC_PLL_DP_MFD_MASK;
+	mfn = mfn_abs = dp_mfn & MXC_PLL_DP_MFN_MASK;
+	/* Sign extend to 32-bits */
+	if (mfn >= 0x04000000) {
+		mfn |= 0xFC000000;
+		mfn_abs = -mfn;
+	}
+
+	ref_clk = 2 * parent_rate;
+	if (dbl != 0)
+		ref_clk *= 2;
+
+	ref_clk /= (pdf + 1);
+	temp = (u64) ref_clk * mfn_abs;
+	do_div(temp, mfd + 1);
+	if (mfn < 0)
+		temp = -temp;
+	temp = (ref_clk * mfi) + temp;
+
+	return temp;
+}
+
+static int _clk_pll_set_rate(struct clk *clk, unsigned long rate)
+{
+	u32 reg;
+	void __iomem *pllbase;
+
+	long mfi, pdf, mfn, mfd = 999999;
+	s64 temp64;
+	unsigned long quad_parent_rate;
+	unsigned long pll_hfsm, dp_ctl;
+	unsigned long parent_rate;
+
+	parent_rate = clk_get_rate(clk->parent);
+
+	pllbase = _get_pll_base(clk);
+
+	quad_parent_rate = 4 * parent_rate;
+	pdf = mfi = -1;
+	while (++pdf < 16 && mfi < 5)
+		mfi = rate * (pdf+1) / quad_parent_rate;
+	if (mfi > 15)
+		return -EINVAL;
+	pdf--;
+
+	temp64 = rate * (pdf+1) - quad_parent_rate * mfi;
+	do_div(temp64, quad_parent_rate/1000000);
+	mfn = (long)temp64;
+
+	dp_ctl = __raw_readl(pllbase + MXC_PLL_DP_CTL);
+	/* use dpdck0_2 */
+	__raw_writel(dp_ctl | 0x1000L, pllbase + MXC_PLL_DP_CTL);
+	pll_hfsm = dp_ctl & MXC_PLL_DP_CTL_HFSM;
+	if (pll_hfsm == 0) {
+		reg = mfi << 4 | pdf;
+		__raw_writel(reg, pllbase + MXC_PLL_DP_OP);
+		__raw_writel(mfd, pllbase + MXC_PLL_DP_MFD);
+		__raw_writel(mfn, pllbase + MXC_PLL_DP_MFN);
+	} else {
+		reg = mfi << 4 | pdf;
+		__raw_writel(reg, pllbase + MXC_PLL_DP_HFS_OP);
+		__raw_writel(mfd, pllbase + MXC_PLL_DP_HFS_MFD);
+		__raw_writel(mfn, pllbase + MXC_PLL_DP_HFS_MFN);
+	}
+
+	return 0;
+}
+
+static int _clk_pll_enable(struct clk *clk)
+{
+	u32 reg;
+	void __iomem *pllbase;
+	int i = 0;
+
+	pllbase = _get_pll_base(clk);
+	reg = __raw_readl(pllbase + MXC_PLL_DP_CTL) | MXC_PLL_DP_CTL_UPEN;
+	__raw_writel(reg, pllbase + MXC_PLL_DP_CTL);
+
+	/* Wait for lock */
+	do {
+		reg = __raw_readl(pllbase + MXC_PLL_DP_CTL);
+		if (reg & MXC_PLL_DP_CTL_LRF)
+			break;
+
+		udelay(1);
+	} while (++i < MAX_DPLL_WAIT_TRIES);
+
+	if (i == MAX_DPLL_WAIT_TRIES) {
+		pr_err("MX5: pll locking failed\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static void _clk_pll_disable(struct clk *clk)
+{
+	u32 reg;
+	void __iomem *pllbase;
+
+	pllbase = _get_pll_base(clk);
+	reg = __raw_readl(pllbase + MXC_PLL_DP_CTL) & ~MXC_PLL_DP_CTL_UPEN;
+	__raw_writel(reg, pllbase + MXC_PLL_DP_CTL);
+}
+
+static int _clk_pll1_sw_set_parent(struct clk *clk, struct clk *parent)
+{
+	u32 reg, step;
+
+	reg = __raw_readl(MXC_CCM_CCSR);
+
+	/* When switching from pll_main_clk to a bypass clock, first select a
+	 * multiplexed clock in 'step_sel', then shift the glitchless mux
+	 * 'pll1_sw_clk_sel'.
+	 *
+	 * When switching back, do it in reverse order
+	 */
+	if (parent == &pll1_main_clk) {
+		/* Switch to pll1_main_clk */
+		reg &= ~MXC_CCM_CCSR_PLL1_SW_CLK_SEL;
+		__raw_writel(reg, MXC_CCM_CCSR);
+		/* step_clk mux switched to lp_apm, to save power. */
+		reg = __raw_readl(MXC_CCM_CCSR);
+		reg &= ~MXC_CCM_CCSR_STEP_SEL_MASK;
+		reg |= (MXC_CCM_CCSR_STEP_SEL_LP_APM <<
+				MXC_CCM_CCSR_STEP_SEL_OFFSET);
+	} else {
+		if (parent == &lp_apm_clk) {
+			step = MXC_CCM_CCSR_STEP_SEL_LP_APM;
+		} else  if (parent == &pll2_sw_clk) {
+			step = MXC_CCM_CCSR_STEP_SEL_PLL2_DIVIDED;
+		} else  if (parent == &pll3_sw_clk) {
+			step = MXC_CCM_CCSR_STEP_SEL_PLL3_DIVIDED;
+		} else
+			return -EINVAL;
+
+		reg &= ~MXC_CCM_CCSR_STEP_SEL_MASK;
+		reg |= (step << MXC_CCM_CCSR_STEP_SEL_OFFSET);
+
+		__raw_writel(reg, MXC_CCM_CCSR);
+		/* Switch to step_clk */
+		reg = __raw_readl(MXC_CCM_CCSR);
+		reg |= MXC_CCM_CCSR_PLL1_SW_CLK_SEL;
+	}
+	__raw_writel(reg, MXC_CCM_CCSR);
+	return 0;
+}
+
+static unsigned long clk_pll1_sw_get_rate(struct clk *clk)
+{
+	u32 reg, div;
+	unsigned long parent_rate;
+
+	parent_rate = clk_get_rate(clk->parent);
+
+	reg = __raw_readl(MXC_CCM_CCSR);
+
+	if (clk->parent == &pll2_sw_clk) {
+		div = ((reg & MXC_CCM_CCSR_PLL2_PODF_MASK) >>
+		       MXC_CCM_CCSR_PLL2_PODF_OFFSET) + 1;
+	} else if (clk->parent == &pll3_sw_clk) {
+		div = ((reg & MXC_CCM_CCSR_PLL3_PODF_MASK) >>
+		       MXC_CCM_CCSR_PLL3_PODF_OFFSET) + 1;
+	} else
+		div = 1;
+	return parent_rate / div;
+}
+
+static int _clk_pll2_sw_set_parent(struct clk *clk, struct clk *parent)
+{
+	u32 reg;
+
+	reg = __raw_readl(MXC_CCM_CCSR);
+
+	if (parent == &pll2_sw_clk)
+		reg &= ~MXC_CCM_CCSR_PLL2_SW_CLK_SEL;
+	else
+		reg |= MXC_CCM_CCSR_PLL2_SW_CLK_SEL;
+
+	__raw_writel(reg, MXC_CCM_CCSR);
+	return 0;
+}
+
+static int _clk_lp_apm_set_parent(struct clk *clk, struct clk *parent)
+{
+	u32 reg;
+
+	if (parent == &osc_clk)
+		reg = __raw_readl(MXC_CCM_CCSR) & ~MXC_CCM_CCSR_LP_APM_SEL;
+	else
+		return -EINVAL;
+
+	__raw_writel(reg, MXC_CCM_CCSR);
+
+	return 0;
+}
+
+static unsigned long clk_cpu_get_rate(struct clk *clk)
+{
+	u32 cacrr, div;
+	unsigned long parent_rate;
+
+	parent_rate = clk_get_rate(clk->parent);
+	cacrr = __raw_readl(MXC_CCM_CACRR);
+	div = (cacrr & MXC_CCM_CACRR_ARM_PODF_MASK) + 1;
+
+	return parent_rate / div;
+}
+
+static int clk_cpu_set_rate(struct clk *clk, unsigned long rate)
+{
+	u32 reg, cpu_podf;
+	unsigned long parent_rate;
+
+	parent_rate = clk_get_rate(clk->parent);
+	cpu_podf = parent_rate / rate - 1;
+	/* use post divider to change freq */
+	reg = __raw_readl(MXC_CCM_CACRR);
+	reg &= ~MXC_CCM_CACRR_ARM_PODF_MASK;
+	reg |= cpu_podf << MXC_CCM_CACRR_ARM_PODF_OFFSET;
+	__raw_writel(reg, MXC_CCM_CACRR);
+
+	return 0;
+}
+
+static int _clk_periph_apm_set_parent(struct clk *clk, struct clk *parent)
+{
+	u32 reg, mux;
+	int i = 0;
+
+	mux = _get_mux(parent, &pll1_sw_clk, &pll3_sw_clk, &lp_apm_clk, NULL);
+
+	reg = __raw_readl(MXC_CCM_CBCMR) & ~MXC_CCM_CBCMR_PERIPH_CLK_SEL_MASK;
+	reg |= mux << MXC_CCM_CBCMR_PERIPH_CLK_SEL_OFFSET;
+	__raw_writel(reg, MXC_CCM_CBCMR);
+
+	/* Wait for lock */
+	do {
+		reg = __raw_readl(MXC_CCM_CDHIPR);
+		if (!(reg &  MXC_CCM_CDHIPR_PERIPH_CLK_SEL_BUSY))
+			break;
+
+		udelay(1);
+	} while (++i < MAX_DPLL_WAIT_TRIES);
+
+	if (i == MAX_DPLL_WAIT_TRIES) {
+		pr_err("MX5: Set parent for periph_apm clock failed\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int _clk_main_bus_set_parent(struct clk *clk, struct clk *parent)
+{
+	u32 reg;
+
+	reg = __raw_readl(MXC_CCM_CBCDR);
+
+	if (parent == &pll2_sw_clk)
+		reg &= ~MXC_CCM_CBCDR_PERIPH_CLK_SEL;
+	else if (parent == &periph_apm_clk)
+		reg |= MXC_CCM_CBCDR_PERIPH_CLK_SEL;
+	else
+		return -EINVAL;
+
+	__raw_writel(reg, MXC_CCM_CBCDR);
+
+	return 0;
+}
+
+static struct clk main_bus_clk = {
+	.parent = &pll2_sw_clk,
+	.set_parent = _clk_main_bus_set_parent,
+};
+
+static unsigned long clk_ahb_get_rate(struct clk *clk)
+{
+	u32 reg, div;
+	unsigned long parent_rate;
+
+	parent_rate = clk_get_rate(clk->parent);
+
+	reg = __raw_readl(MXC_CCM_CBCDR);
+	div = ((reg & MXC_CCM_CBCDR_AHB_PODF_MASK) >>
+	       MXC_CCM_CBCDR_AHB_PODF_OFFSET) + 1;
+	return parent_rate / div;
+}
+
+
+static int _clk_ahb_set_rate(struct clk *clk, unsigned long rate)
+{
+	u32 reg, div;
+	unsigned long parent_rate;
+	int i = 0;
+
+	parent_rate = clk_get_rate(clk->parent);
+
+	div = parent_rate / rate;
+	if (div > 8 || div < 1 || ((parent_rate / div) != rate))
+		return -EINVAL;
+
+	reg = __raw_readl(MXC_CCM_CBCDR);
+	reg &= ~MXC_CCM_CBCDR_AHB_PODF_MASK;
+	reg |= (div - 1) << MXC_CCM_CBCDR_AHB_PODF_OFFSET;
+	__raw_writel(reg, MXC_CCM_CBCDR);
+
+	/* Wait for lock */
+	do {
+		reg = __raw_readl(MXC_CCM_CDHIPR);
+		if (!(reg & MXC_CCM_CDHIPR_AHB_PODF_BUSY))
+			break;
+
+		udelay(1);
+	} while (++i < MAX_DPLL_WAIT_TRIES);
+
+	if (i == MAX_DPLL_WAIT_TRIES) {
+		pr_err("MX5: clk_ahb_set_rate failed\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static unsigned long _clk_ahb_round_rate(struct clk *clk,
+						unsigned long rate)
+{
+	u32 div;
+	unsigned long parent_rate;
+
+	parent_rate = clk_get_rate(clk->parent);
+
+	div = parent_rate / rate;
+	if (div > 8)
+		div = 8;
+	else if (div == 0)
+		div++;
+	return parent_rate / div;
+}
+
+
+static int _clk_max_enable(struct clk *clk)
+{
+	u32 reg;
+
+	_clk_ccgr_enable(clk);
+
+	/* Handshake with MAX when LPM is entered. */
+	reg = __raw_readl(MXC_CCM_CLPCR);
+	if (cpu_is_mx51())
+		reg &= ~MX51_CCM_CLPCR_BYPASS_MAX_LPM_HS;
+	else if (cpu_is_mx53())
+		reg &= ~MX53_CCM_CLPCR_BYPASS_MAX_LPM_HS;
+	__raw_writel(reg, MXC_CCM_CLPCR);
+
+	return 0;
+}
+
+static void _clk_max_disable(struct clk *clk)
+{
+	u32 reg;
+
+	_clk_ccgr_disable_inwait(clk);
+
+	/* No Handshake with MAX when LPM is entered as its disabled. */
+	reg = __raw_readl(MXC_CCM_CLPCR);
+	if (cpu_is_mx51())
+		reg |= MX51_CCM_CLPCR_BYPASS_MAX_LPM_HS;
+	else if (cpu_is_mx53())
+		reg &= ~MX53_CCM_CLPCR_BYPASS_MAX_LPM_HS;
+	__raw_writel(reg, MXC_CCM_CLPCR);
+}
+
+static unsigned long clk_ipg_get_rate(struct clk *clk)
+{
+	u32 reg, div;
+	unsigned long parent_rate;
+
+	parent_rate = clk_get_rate(clk->parent);
+
+	reg = __raw_readl(MXC_CCM_CBCDR);
+	div = ((reg & MXC_CCM_CBCDR_IPG_PODF_MASK) >>
+	       MXC_CCM_CBCDR_IPG_PODF_OFFSET) + 1;
+
+	return parent_rate / div;
+}
+
+static unsigned long clk_ipg_per_get_rate(struct clk *clk)
+{
+	u32 reg, prediv1, prediv2, podf;
+	unsigned long parent_rate;
+
+	parent_rate = clk_get_rate(clk->parent);
+
+	if (clk->parent == &main_bus_clk || clk->parent == &lp_apm_clk) {
+		/* the main_bus_clk is the one before the DVFS engine */
+		reg = __raw_readl(MXC_CCM_CBCDR);
+		prediv1 = ((reg & MXC_CCM_CBCDR_PERCLK_PRED1_MASK) >>
+			   MXC_CCM_CBCDR_PERCLK_PRED1_OFFSET) + 1;
+		prediv2 = ((reg & MXC_CCM_CBCDR_PERCLK_PRED2_MASK) >>
+			   MXC_CCM_CBCDR_PERCLK_PRED2_OFFSET) + 1;
+		podf = ((reg & MXC_CCM_CBCDR_PERCLK_PODF_MASK) >>
+			MXC_CCM_CBCDR_PERCLK_PODF_OFFSET) + 1;
+		return parent_rate / (prediv1 * prediv2 * podf);
+	} else if (clk->parent == &ipg_clk)
+		return parent_rate;
+	else
+		BUG();
+}
+
+static int _clk_ipg_per_set_parent(struct clk *clk, struct clk *parent)
+{
+	u32 reg;
+
+	reg = __raw_readl(MXC_CCM_CBCMR);
+
+	reg &= ~MXC_CCM_CBCMR_PERCLK_LP_APM_CLK_SEL;
+	reg &= ~MXC_CCM_CBCMR_PERCLK_IPG_CLK_SEL;
+
+	if (parent == &ipg_clk)
+		reg |= MXC_CCM_CBCMR_PERCLK_IPG_CLK_SEL;
+	else if (parent == &lp_apm_clk)
+		reg |= MXC_CCM_CBCMR_PERCLK_LP_APM_CLK_SEL;
+	else if (parent != &main_bus_clk)
+		return -EINVAL;
+
+	__raw_writel(reg, MXC_CCM_CBCMR);
+
+	return 0;
+}
+
+#define clk_nfc_set_parent	NULL
+
+static unsigned long clk_nfc_get_rate(struct clk *clk)
+{
+	unsigned long rate;
+	u32 reg, div;
+
+	reg = __raw_readl(MXC_CCM_CBCDR);
+	div = ((reg & MXC_CCM_CBCDR_NFC_PODF_MASK) >>
+	       MXC_CCM_CBCDR_NFC_PODF_OFFSET) + 1;
+	rate = clk_get_rate(clk->parent) / div;
+	WARN_ON(rate == 0);
+	return rate;
+}
+
+static unsigned long clk_nfc_round_rate(struct clk *clk,
+						unsigned long rate)
+{
+	u32 div;
+	unsigned long parent_rate = clk_get_rate(clk->parent);
+
+	if (!rate)
+		return -EINVAL;
+
+	div = parent_rate / rate;
+
+	if (parent_rate % rate)
+		div++;
+
+	if (div > 8)
+		return -EINVAL;
+
+	return parent_rate / div;
+
+}
+
+static int clk_nfc_set_rate(struct clk *clk, unsigned long rate)
+{
+	u32 reg, div;
+
+	div = clk_get_rate(clk->parent) / rate;
+	if (div == 0)
+		div++;
+	if (((clk_get_rate(clk->parent) / div) != rate) || (div > 8))
+		return -EINVAL;
+
+	reg = __raw_readl(MXC_CCM_CBCDR);
+	reg &= ~MXC_CCM_CBCDR_NFC_PODF_MASK;
+	reg |= (div - 1) << MXC_CCM_CBCDR_NFC_PODF_OFFSET;
+	__raw_writel(reg, MXC_CCM_CBCDR);
+
+	while (__raw_readl(MXC_CCM_CDHIPR) &
+			MXC_CCM_CDHIPR_NFC_IPG_INT_MEM_PODF_BUSY){
+	}
+
+	return 0;
+}
+
+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 unsigned long get_oscillator_reference_clock_rate(struct clk *clk)
+{
+	return oscillator_reference;
+}
+
+static unsigned long get_ckih2_reference_clock_rate(struct clk *clk)
+{
+	return ckih2_reference;
+}
+
+static unsigned long clk_emi_slow_get_rate(struct clk *clk)
+{
+	u32 reg, div;
+
+	reg = __raw_readl(MXC_CCM_CBCDR);
+	div = ((reg & MXC_CCM_CBCDR_EMI_PODF_MASK) >>
+	       MXC_CCM_CBCDR_EMI_PODF_OFFSET) + 1;
+
+	return clk_get_rate(clk->parent) / div;
+}
+
+static unsigned long _clk_ddr_hf_get_rate(struct clk *clk)
+{
+	unsigned long rate;
+	u32 reg, div;
+
+	reg = __raw_readl(MXC_CCM_CBCDR);
+	div = ((reg & MXC_CCM_CBCDR_DDR_PODF_MASK) >>
+		MXC_CCM_CBCDR_DDR_PODF_OFFSET) + 1;
+	rate = clk_get_rate(clk->parent) / div;
+
+	return rate;
+}
+
+/* External high frequency clock */
+static struct clk ckih_clk = {
+	.get_rate = get_high_reference_clock_rate,
+};
+
+static struct clk ckih2_clk = {
+	.get_rate = get_ckih2_reference_clock_rate,
+};
+
+static struct clk osc_clk = {
+	.get_rate = get_oscillator_reference_clock_rate,
+};
+
+/* External low frequency (32kHz) clock */
+static struct clk ckil_clk = {
+	.get_rate = get_low_reference_clock_rate,
+};
+
+static struct clk pll1_main_clk = {
+	.parent = &osc_clk,
+	.get_rate = clk_pll_get_rate,
+	.enable = _clk_pll_enable,
+	.disable = _clk_pll_disable,
+};
+
+/* Clock tree block diagram (WIP):
+ * 	CCM: Clock Controller Module
+ *
+ * PLL output -> |
+ *               | CCM Switcher -> CCM_CLK_ROOT_GEN ->
+ * PLL bypass -> |
+ *
+ */
+
+/* PLL1 SW supplies to ARM core */
+static struct clk pll1_sw_clk = {
+	.parent = &pll1_main_clk,
+	.set_parent = _clk_pll1_sw_set_parent,
+	.get_rate = clk_pll1_sw_get_rate,
+};
+
+/* PLL2 SW supplies to AXI/AHB/IP buses */
+static struct clk pll2_sw_clk = {
+	.parent = &osc_clk,
+	.get_rate = clk_pll_get_rate,
+	.set_rate = _clk_pll_set_rate,
+	.set_parent = _clk_pll2_sw_set_parent,
+	.enable = _clk_pll_enable,
+	.disable = _clk_pll_disable,
+};
+
+/* PLL3 SW supplies to serial clocks like USB, SSI, etc. */
+static struct clk pll3_sw_clk = {
+	.parent = &osc_clk,
+	.set_rate = _clk_pll_set_rate,
+	.get_rate = clk_pll_get_rate,
+	.enable = _clk_pll_enable,
+	.disable = _clk_pll_disable,
+};
+
+/* PLL4 SW supplies to LVDS Display Bridge(LDB) */
+static struct clk mx53_pll4_sw_clk = {
+	.parent = &osc_clk,
+	.set_rate = _clk_pll_set_rate,
+	.enable = _clk_pll_enable,
+	.disable = _clk_pll_disable,
+};
+
+/* Low-power Audio Playback Mode clock */
+static struct clk lp_apm_clk = {
+	.parent = &osc_clk,
+	.set_parent = _clk_lp_apm_set_parent,
+};
+
+static struct clk periph_apm_clk = {
+	.parent = &pll1_sw_clk,
+	.set_parent = _clk_periph_apm_set_parent,
+};
+
+static struct clk cpu_clk = {
+	.parent = &pll1_sw_clk,
+	.get_rate = clk_cpu_get_rate,
+	.set_rate = clk_cpu_set_rate,
+};
+
+static struct clk ahb_clk = {
+	.parent = &main_bus_clk,
+	.get_rate = clk_ahb_get_rate,
+	.set_rate = _clk_ahb_set_rate,
+	.round_rate = _clk_ahb_round_rate,
+};
+
+static struct clk iim_clk = {
+	.parent = &ipg_clk,
+	.enable_reg = MXC_CCM_CCGR0,
+	.enable_shift = MXC_CCM_CCGRx_CG15_OFFSET,
+};
+
+/* Main IP interface clock for access to registers */
+static struct clk ipg_clk = {
+	.parent = &ahb_clk,
+	.get_rate = clk_ipg_get_rate,
+};
+
+static struct clk ipg_perclk = {
+	.parent = &lp_apm_clk,
+	.get_rate = clk_ipg_per_get_rate,
+	.set_parent = _clk_ipg_per_set_parent,
+};
+
+static struct clk ahb_max_clk = {
+	.parent = &ahb_clk,
+	.enable_reg = MXC_CCM_CCGR0,
+	.enable_shift = MXC_CCM_CCGRx_CG14_OFFSET,
+	.enable = _clk_max_enable,
+	.disable = _clk_max_disable,
+};
+
+static struct clk aips_tz1_clk = {
+	.parent = &ahb_clk,
+	.secondary = &ahb_max_clk,
+	.enable_reg = MXC_CCM_CCGR0,
+	.enable_shift = MXC_CCM_CCGRx_CG12_OFFSET,
+	.enable = _clk_ccgr_enable,
+	.disable = _clk_ccgr_disable_inwait,
+};
+
+static struct clk aips_tz2_clk = {
+	.parent = &ahb_clk,
+	.secondary = &ahb_max_clk,
+	.enable_reg = MXC_CCM_CCGR0,
+	.enable_shift = MXC_CCM_CCGRx_CG13_OFFSET,
+	.enable = _clk_ccgr_enable,
+	.disable = _clk_ccgr_disable_inwait,
+};
+
+static struct clk gpt_32k_clk = {
+	.id = 0,
+	.parent = &ckil_clk,
+};
+
+static struct clk kpp_clk = {
+	.id = 0,
+};
+
+static struct clk dummy_clk = {
+	.id = 0,
+};
+
+static struct clk emi_slow_clk = {
+	.parent = &pll2_sw_clk,
+	.enable_reg = MXC_CCM_CCGR5,
+	.enable_shift = MXC_CCM_CCGRx_CG8_OFFSET,
+	.enable = _clk_ccgr_enable,
+	.disable = _clk_ccgr_disable_inwait,
+	.get_rate = clk_emi_slow_get_rate,
+};
+
+static int clk_ipu_enable(struct clk *clk)
+{
+	u32 reg;
+
+	_clk_ccgr_enable(clk);
+
+	/* Enable handshake with IPU when certain clock rates are changed */
+	reg = __raw_readl(MXC_CCM_CCDR);
+	reg &= ~MXC_CCM_CCDR_IPU_HS_MASK;
+	__raw_writel(reg, MXC_CCM_CCDR);
+
+	/* Enable handshake with IPU when LPM is entered */
+	reg = __raw_readl(MXC_CCM_CLPCR);
+	reg &= ~MXC_CCM_CLPCR_BYPASS_IPU_LPM_HS;
+	__raw_writel(reg, MXC_CCM_CLPCR);
+
+	return 0;
+}
+
+static void clk_ipu_disable(struct clk *clk)
+{
+	u32 reg;
+
+	_clk_ccgr_disable(clk);
+
+	/* Disable handshake with IPU whe dividers are changed */
+	reg = __raw_readl(MXC_CCM_CCDR);
+	reg |= MXC_CCM_CCDR_IPU_HS_MASK;
+	__raw_writel(reg, MXC_CCM_CCDR);
+
+	/* Disable handshake with IPU when LPM is entered */
+	reg = __raw_readl(MXC_CCM_CLPCR);
+	reg |= MXC_CCM_CLPCR_BYPASS_IPU_LPM_HS;
+	__raw_writel(reg, MXC_CCM_CLPCR);
+}
+
+static struct clk ahbmux1_clk = {
+	.parent = &ahb_clk,
+	.secondary = &ahb_max_clk,
+	.enable_reg = MXC_CCM_CCGR0,
+	.enable_shift = MXC_CCM_CCGRx_CG8_OFFSET,
+	.enable = _clk_ccgr_enable,
+	.disable = _clk_ccgr_disable_inwait,
+};
+
+static struct clk ipu_sec_clk = {
+	.parent = &emi_fast_clk,
+	.secondary = &ahbmux1_clk,
+};
+
+static struct clk ddr_hf_clk = {
+	.parent = &pll1_sw_clk,
+	.get_rate = _clk_ddr_hf_get_rate,
+};
+
+static struct clk ddr_clk = {
+	.parent = &ddr_hf_clk,
+};
+
+/* clock definitions for MIPI HSC unit which has been removed
+ * from documentation, but not from hardware
+ */
+static int _clk_hsc_enable(struct clk *clk)
+{
+	u32 reg;
+
+	_clk_ccgr_enable(clk);
+	/* Handshake with IPU when certain clock rates are changed. */
+	reg = __raw_readl(MXC_CCM_CCDR);
+	reg &= ~MXC_CCM_CCDR_HSC_HS_MASK;
+	__raw_writel(reg, MXC_CCM_CCDR);
+
+	reg = __raw_readl(MXC_CCM_CLPCR);
+	reg &= ~MXC_CCM_CLPCR_BYPASS_HSC_LPM_HS;
+	__raw_writel(reg, MXC_CCM_CLPCR);
+
+	return 0;
+}
+
+static void _clk_hsc_disable(struct clk *clk)
+{
+	u32 reg;
+
+	_clk_ccgr_disable(clk);
+	/* No handshake with HSC as its not enabled. */
+	reg = __raw_readl(MXC_CCM_CCDR);
+	reg |= MXC_CCM_CCDR_HSC_HS_MASK;
+	__raw_writel(reg, MXC_CCM_CCDR);
+
+	reg = __raw_readl(MXC_CCM_CLPCR);
+	reg |= MXC_CCM_CLPCR_BYPASS_HSC_LPM_HS;
+	__raw_writel(reg, MXC_CCM_CLPCR);
+}
+
+static struct clk mipi_hsp_clk = {
+	.parent = &ipu_clk,
+	.enable_reg = MXC_CCM_CCGR4,
+	.enable_shift = MXC_CCM_CCGRx_CG6_OFFSET,
+	.enable = _clk_hsc_enable,
+	.disable = _clk_hsc_disable,
+	.secondary = &mipi_hsc1_clk,
+};
+
+#define DEFINE_CLOCK_CCGR(name, i, er, es, pfx, p, s)	\
+	static struct clk name = {			\
+		.id		= i,			\
+		.enable_reg	= er,			\
+		.enable_shift	= es,			\
+		.get_rate	= pfx##_get_rate,	\
+		.set_rate	= pfx##_set_rate,	\
+		.round_rate	= pfx##_round_rate,	\
+		.set_parent	= pfx##_set_parent,	\
+		.enable		= _clk_ccgr_enable,	\
+		.disable	= _clk_ccgr_disable,	\
+		.parent		= p,			\
+		.secondary	= s,			\
+	}
+
+#define DEFINE_CLOCK_MAX(name, i, er, es, pfx, p, s)	\
+	static struct clk name = {			\
+		.id		= i,			\
+		.enable_reg	= er,			\
+		.enable_shift	= es,			\
+		.get_rate	= pfx##_get_rate,	\
+		.set_rate	= pfx##_set_rate,	\
+		.set_parent	= pfx##_set_parent,	\
+		.enable		= _clk_max_enable,	\
+		.disable	= _clk_max_disable,	\
+		.parent		= p,			\
+		.secondary	= s,			\
+	}
+
+#define CLK_GET_RATE(name, nr, bitsname)				\
+static unsigned long clk_##name##_get_rate(struct clk *clk)		\
+{									\
+	u32 reg, pred, podf;						\
+									\
+	reg = __raw_readl(MXC_CCM_CSCDR##nr);				\
+	pred = (reg & MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_MASK)	\
+		>> MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_OFFSET;	\
+	podf = (reg & MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_MASK)	\
+		>> MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_OFFSET;	\
+									\
+	return DIV_ROUND_CLOSEST(clk_get_rate(clk->parent),		\
+			(pred + 1) * (podf + 1));			\
+}
+
+#define CLK_SET_PARENT(name, nr, bitsname)				\
+static int clk_##name##_set_parent(struct clk *clk, struct clk *parent)	\
+{									\
+	u32 reg, mux;							\
+									\
+	mux = _get_mux(parent, &pll1_sw_clk, &pll2_sw_clk,		\
+			&pll3_sw_clk, &lp_apm_clk);			\
+	reg = __raw_readl(MXC_CCM_CSCMR##nr) &				\
+		~MXC_CCM_CSCMR##nr##_##bitsname##_CLK_SEL_MASK;		\
+	reg |= mux << MXC_CCM_CSCMR##nr##_##bitsname##_CLK_SEL_OFFSET;	\
+	__raw_writel(reg, MXC_CCM_CSCMR##nr);				\
+									\
+	return 0;							\
+}
+
+#define CLK_SET_RATE(name, nr, bitsname)				\
+static int clk_##name##_set_rate(struct clk *clk, unsigned long rate)	\
+{									\
+	u32 reg, div, parent_rate;					\
+	u32 pre = 0, post = 0;						\
+									\
+	parent_rate = clk_get_rate(clk->parent);			\
+	div = parent_rate / rate;					\
+									\
+	if ((parent_rate / div) != rate)				\
+		return -EINVAL;						\
+									\
+	__calc_pre_post_dividers(div, &pre, &post,			\
+		(MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_MASK >>	\
+		MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_OFFSET) + 1,	\
+		(MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_MASK >>	\
+		MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_OFFSET) + 1);\
+									\
+	/* Set sdhc1 clock divider */					\
+	reg = __raw_readl(MXC_CCM_CSCDR##nr) &				\
+		~(MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_MASK	\
+		| MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_MASK);	\
+	reg |= (post - 1) <<						\
+		MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_OFFSET;	\
+	reg |= (pre - 1) <<						\
+		MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_OFFSET;	\
+	__raw_writel(reg, MXC_CCM_CSCDR##nr);				\
+									\
+	return 0;							\
+}
+
+/* UART */
+CLK_GET_RATE(uart, 1, UART)
+CLK_SET_PARENT(uart, 1, UART)
+
+static struct clk uart_root_clk = {
+	.parent = &pll2_sw_clk,
+	.get_rate = clk_uart_get_rate,
+	.set_parent = clk_uart_set_parent,
+};
+
+/* USBOH3 */
+CLK_GET_RATE(usboh3, 1, USBOH3)
+CLK_SET_PARENT(usboh3, 1, USBOH3)
+
+static struct clk usboh3_clk = {
+	.parent = &pll2_sw_clk,
+	.get_rate = clk_usboh3_get_rate,
+	.set_parent = clk_usboh3_set_parent,
+	.enable = _clk_ccgr_enable,
+	.disable = _clk_ccgr_disable,
+	.enable_reg = MXC_CCM_CCGR2,
+	.enable_shift = MXC_CCM_CCGRx_CG14_OFFSET,
+};
+
+static struct clk usb_ahb_clk = {
+	.parent = &ipg_clk,
+	.enable = _clk_ccgr_enable,
+	.disable = _clk_ccgr_disable,
+	.enable_reg = MXC_CCM_CCGR2,
+	.enable_shift = MXC_CCM_CCGRx_CG13_OFFSET,
+};
+
+static int clk_usb_phy1_set_parent(struct clk *clk, struct clk *parent)
+{
+	u32 reg;
+
+	reg = __raw_readl(MXC_CCM_CSCMR1) & ~MXC_CCM_CSCMR1_USB_PHY_CLK_SEL;
+
+	if (parent == &pll3_sw_clk)
+		reg |= 1 << MXC_CCM_CSCMR1_USB_PHY_CLK_SEL_OFFSET;
+
+	__raw_writel(reg, MXC_CCM_CSCMR1);
+
+	return 0;
+}
+
+static struct clk usb_phy1_clk = {
+	.parent = &pll3_sw_clk,
+	.set_parent = clk_usb_phy1_set_parent,
+	.enable = _clk_ccgr_enable,
+	.enable_reg = MXC_CCM_CCGR2,
+	.enable_shift = MXC_CCM_CCGRx_CG0_OFFSET,
+	.disable = _clk_ccgr_disable,
+};
+
+/* eCSPI */
+CLK_GET_RATE(ecspi, 2, CSPI)
+CLK_SET_PARENT(ecspi, 1, CSPI)
+
+static struct clk ecspi_main_clk = {
+	.parent = &pll3_sw_clk,
+	.get_rate = clk_ecspi_get_rate,
+	.set_parent = clk_ecspi_set_parent,
+};
+
+/* eSDHC */
+CLK_GET_RATE(esdhc1, 1, ESDHC1_MSHC1)
+CLK_SET_PARENT(esdhc1, 1, ESDHC1_MSHC1)
+CLK_SET_RATE(esdhc1, 1, ESDHC1_MSHC1)
+
+CLK_GET_RATE(esdhc2, 1, ESDHC2_MSHC2)
+CLK_SET_PARENT(esdhc2, 1, ESDHC2_MSHC2)
+CLK_SET_RATE(esdhc2, 1, ESDHC2_MSHC2)
+
+#define DEFINE_CLOCK_FULL(name, i, er, es, gr, sr, e, d, p, s)		\
+	static struct clk name = {					\
+		.id		= i,					\
+		.enable_reg	= er,					\
+		.enable_shift	= es,					\
+		.get_rate	= gr,					\
+		.set_rate	= sr,					\
+		.enable		= e,					\
+		.disable	= d,					\
+		.parent		= p,					\
+		.secondary	= s,					\
+	}
+
+#define DEFINE_CLOCK(name, i, er, es, gr, sr, p, s)			\
+	DEFINE_CLOCK_FULL(name, i, er, es, gr, sr, _clk_ccgr_enable, _clk_ccgr_disable, p, s)
+
+/* Shared peripheral bus arbiter */
+DEFINE_CLOCK(spba_clk, 0, MXC_CCM_CCGR5, MXC_CCM_CCGRx_CG0_OFFSET,
+	NULL,  NULL, &ipg_clk, NULL);
+
+/* UART */
+DEFINE_CLOCK(uart1_ipg_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG3_OFFSET,
+	NULL,  NULL, &ipg_clk, &aips_tz1_clk);
+DEFINE_CLOCK(uart2_ipg_clk, 1, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG5_OFFSET,
+	NULL,  NULL, &ipg_clk, &aips_tz1_clk);
+DEFINE_CLOCK(uart3_ipg_clk, 2, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG7_OFFSET,
+	NULL,  NULL, &ipg_clk, &spba_clk);
+DEFINE_CLOCK(uart1_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG4_OFFSET,
+	NULL,  NULL, &uart_root_clk, &uart1_ipg_clk);
+DEFINE_CLOCK(uart2_clk, 1, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG6_OFFSET,
+	NULL,  NULL, &uart_root_clk, &uart2_ipg_clk);
+DEFINE_CLOCK(uart3_clk, 2, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG8_OFFSET,
+	NULL,  NULL, &uart_root_clk, &uart3_ipg_clk);
+
+/* GPT */
+DEFINE_CLOCK(gpt_ipg_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG10_OFFSET,
+	NULL,  NULL, &ipg_clk, NULL);
+DEFINE_CLOCK(gpt_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG9_OFFSET,
+	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);
+DEFINE_CLOCK(pwm2_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG8_OFFSET,
+	NULL, NULL, &ipg_clk, NULL);
+
+/* I2C */
+DEFINE_CLOCK(i2c1_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG9_OFFSET,
+	NULL, NULL, &ipg_clk, NULL);
+DEFINE_CLOCK(i2c2_clk, 1, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG10_OFFSET,
+	NULL, NULL, &ipg_clk, NULL);
+DEFINE_CLOCK(hsi2c_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG11_OFFSET,
+	NULL, NULL, &ipg_clk, NULL);
+
+/* FEC */
+DEFINE_CLOCK(fec_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG12_OFFSET,
+	NULL,  NULL, &ipg_clk, NULL);
+
+/* NFC */
+DEFINE_CLOCK_CCGR(nfc_clk, 0, MXC_CCM_CCGR5, MXC_CCM_CCGRx_CG10_OFFSET,
+	clk_nfc, &emi_slow_clk, NULL);
+
+/* SSI */
+DEFINE_CLOCK(ssi1_ipg_clk, 0, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG8_OFFSET,
+	NULL, NULL, &ipg_clk, NULL);
+DEFINE_CLOCK(ssi1_clk, 0, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG9_OFFSET,
+	NULL, NULL, &pll3_sw_clk, &ssi1_ipg_clk);
+DEFINE_CLOCK(ssi2_ipg_clk, 1, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG10_OFFSET,
+	NULL, NULL, &ipg_clk, NULL);
+DEFINE_CLOCK(ssi2_clk, 1, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG11_OFFSET,
+	NULL, NULL, &pll3_sw_clk, &ssi2_ipg_clk);
+DEFINE_CLOCK(ssi3_ipg_clk, 2, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG12_OFFSET,
+	NULL, NULL, &ipg_clk, NULL);
+DEFINE_CLOCK(ssi3_clk, 2, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG13_OFFSET,
+	NULL, NULL, &pll3_sw_clk, &ssi3_ipg_clk);
+
+/* eCSPI */
+DEFINE_CLOCK_FULL(ecspi1_ipg_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG9_OFFSET,
+		NULL, NULL, _clk_ccgr_enable_inrun, _clk_ccgr_disable,
+		&ipg_clk, &spba_clk);
+DEFINE_CLOCK(ecspi1_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG10_OFFSET,
+		NULL, NULL, &ecspi_main_clk, &ecspi1_ipg_clk);
+DEFINE_CLOCK_FULL(ecspi2_ipg_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG11_OFFSET,
+		NULL, NULL, _clk_ccgr_enable_inrun, _clk_ccgr_disable,
+		&ipg_clk, &aips_tz2_clk);
+DEFINE_CLOCK(ecspi2_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG12_OFFSET,
+		NULL, NULL, &ecspi_main_clk, &ecspi2_ipg_clk);
+
+/* CSPI */
+DEFINE_CLOCK(cspi_ipg_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG9_OFFSET,
+		NULL, NULL, &ipg_clk, &aips_tz2_clk);
+DEFINE_CLOCK(cspi_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG13_OFFSET,
+		NULL, NULL, &ipg_clk, &cspi_ipg_clk);
+
+/* SDMA */
+DEFINE_CLOCK(sdma_clk, 1, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG15_OFFSET,
+		NULL, NULL, &ahb_clk, NULL);
+
+/* eSDHC */
+DEFINE_CLOCK_FULL(esdhc1_ipg_clk, 0, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG0_OFFSET,
+	NULL,  NULL, _clk_max_enable, _clk_max_disable, &ipg_clk, NULL);
+DEFINE_CLOCK_MAX(esdhc1_clk, 0, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG1_OFFSET,
+	clk_esdhc1, &pll2_sw_clk, &esdhc1_ipg_clk);
+DEFINE_CLOCK_FULL(esdhc2_ipg_clk, 1, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG2_OFFSET,
+	NULL,  NULL, _clk_max_enable, _clk_max_disable, &ipg_clk, NULL);
+DEFINE_CLOCK_MAX(esdhc2_clk, 1, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG3_OFFSET,
+	clk_esdhc2, &pll2_sw_clk, &esdhc2_ipg_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);
+
+/* IPU */
+DEFINE_CLOCK_FULL(ipu_clk, 0, MXC_CCM_CCGR5, MXC_CCM_CCGRx_CG5_OFFSET,
+	NULL,  NULL, clk_ipu_enable, clk_ipu_disable, &ahb_clk, &ipu_sec_clk);
+
+DEFINE_CLOCK_FULL(emi_fast_clk, 0, MXC_CCM_CCGR5, MXC_CCM_CCGRx_CG7_OFFSET,
+		NULL, NULL, _clk_ccgr_enable, _clk_ccgr_disable_inwait,
+		&ddr_clk, NULL);
+
+DEFINE_CLOCK(ipu_di0_clk, 0, MXC_CCM_CCGR6, MXC_CCM_CCGRx_CG5_OFFSET,
+		NULL, NULL, &pll3_sw_clk, NULL);
+DEFINE_CLOCK(ipu_di1_clk, 0, MXC_CCM_CCGR6, MXC_CCM_CCGRx_CG6_OFFSET,
+		NULL, NULL, &pll3_sw_clk, NULL);
+
+#define _REGISTER_CLOCK(d, n, c) \
+       { \
+		.dev_id = d, \
+		.con_id = n, \
+		.clk = &c,   \
+       },
+
+static struct clk_lookup mx51_lookups[] = {
+	_REGISTER_CLOCK("imx-uart.0", NULL, uart1_clk)
+	_REGISTER_CLOCK("imx-uart.1", NULL, uart2_clk)
+	_REGISTER_CLOCK("imx-uart.2", NULL, uart3_clk)
+	_REGISTER_CLOCK(NULL, "gpt", gpt_clk)
+	_REGISTER_CLOCK("fec.0", NULL, fec_clk)
+	_REGISTER_CLOCK("mxc_pwm.0", "pwm", pwm1_clk)
+	_REGISTER_CLOCK("mxc_pwm.1", "pwm", pwm2_clk)
+	_REGISTER_CLOCK("imx-i2c.0", NULL, i2c1_clk)
+	_REGISTER_CLOCK("imx-i2c.1", NULL, i2c2_clk)
+	_REGISTER_CLOCK("imx-i2c.2", NULL, hsi2c_clk)
+	_REGISTER_CLOCK("mxc-ehci.0", "usb", usboh3_clk)
+	_REGISTER_CLOCK("mxc-ehci.0", "usb_ahb", usb_ahb_clk)
+	_REGISTER_CLOCK("mxc-ehci.0", "usb_phy1", usb_phy1_clk)
+	_REGISTER_CLOCK("mxc-ehci.1", "usb", usboh3_clk)
+	_REGISTER_CLOCK("mxc-ehci.1", "usb_ahb", usb_ahb_clk)
+	_REGISTER_CLOCK("mxc-ehci.2", "usb", usboh3_clk)
+	_REGISTER_CLOCK("mxc-ehci.2", "usb_ahb", usb_ahb_clk)
+	_REGISTER_CLOCK("fsl-usb2-udc", "usb", usboh3_clk)
+	_REGISTER_CLOCK("fsl-usb2-udc", "usb_ahb", ahb_clk)
+	_REGISTER_CLOCK("imx-keypad", NULL, kpp_clk)
+	_REGISTER_CLOCK("mxc_nand", NULL, nfc_clk)
+	_REGISTER_CLOCK("imx-ssi.0", NULL, ssi1_clk)
+	_REGISTER_CLOCK("imx-ssi.1", NULL, ssi2_clk)
+	_REGISTER_CLOCK("imx-ssi.2", NULL, ssi3_clk)
+	_REGISTER_CLOCK("imx-sdma", NULL, sdma_clk)
+	_REGISTER_CLOCK(NULL, "ckih", ckih_clk)
+	_REGISTER_CLOCK(NULL, "ckih2", ckih2_clk)
+	_REGISTER_CLOCK(NULL, "gpt_32k", gpt_32k_clk)
+	_REGISTER_CLOCK("imx51-ecspi.0", NULL, ecspi1_clk)
+	_REGISTER_CLOCK("imx51-ecspi.1", NULL, ecspi2_clk)
+	_REGISTER_CLOCK("imx51-cspi.0", NULL, cspi_clk)
+	_REGISTER_CLOCK("sdhci-esdhc-imx.0", NULL, esdhc1_clk)
+	_REGISTER_CLOCK("sdhci-esdhc-imx.1", NULL, esdhc2_clk)
+	_REGISTER_CLOCK(NULL, "cpu_clk", cpu_clk)
+	_REGISTER_CLOCK(NULL, "iim_clk", iim_clk)
+	_REGISTER_CLOCK("imx2-wdt.0", NULL, dummy_clk)
+	_REGISTER_CLOCK("imx2-wdt.1", NULL, dummy_clk)
+	_REGISTER_CLOCK(NULL, "mipi_hsp", mipi_hsp_clk)
+	_REGISTER_CLOCK("imx-ipuv3", NULL, ipu_clk)
+	_REGISTER_CLOCK("imx-ipuv3", "di0", ipu_di0_clk)
+	_REGISTER_CLOCK("imx-ipuv3", "di1", ipu_di1_clk)
+};
+
+static struct clk_lookup mx53_lookups[] = {
+	_REGISTER_CLOCK("imx-uart.0", NULL, uart1_clk)
+	_REGISTER_CLOCK("imx-uart.1", NULL, uart2_clk)
+	_REGISTER_CLOCK("imx-uart.2", NULL, uart3_clk)
+	_REGISTER_CLOCK(NULL, "gpt", gpt_clk)
+	_REGISTER_CLOCK("fec.0", NULL, fec_clk)
+	_REGISTER_CLOCK(NULL, "iim_clk", iim_clk)
+	_REGISTER_CLOCK("imx-i2c.0", NULL, i2c1_clk)
+	_REGISTER_CLOCK("imx-i2c.1", NULL, i2c2_clk)
+	_REGISTER_CLOCK("sdhci-esdhc-imx.0", NULL, esdhc1_clk)
+	_REGISTER_CLOCK("sdhci-esdhc-imx.1", NULL, esdhc2_clk)
+	_REGISTER_CLOCK("imx53-ecspi.0", NULL, ecspi1_clk)
+	_REGISTER_CLOCK("imx53-ecspi.1", NULL, ecspi2_clk)
+	_REGISTER_CLOCK("imx53-cspi.0", NULL, cspi_clk)
+};
+
+static void clk_tree_init(void)
+{
+	u32 reg;
+
+	ipg_perclk.set_parent(&ipg_perclk, &lp_apm_clk);
+
+	/*
+	 * Initialise the IPG PER CLK dividers to 3. IPG_PER_CLK should be at
+	 * 8MHz, its derived from lp_apm.
+	 *
+	 * FIXME: Verify if true for all boards
+	 */
+	reg = __raw_readl(MXC_CCM_CBCDR);
+	reg &= ~MXC_CCM_CBCDR_PERCLK_PRED1_MASK;
+	reg &= ~MXC_CCM_CBCDR_PERCLK_PRED2_MASK;
+	reg &= ~MXC_CCM_CBCDR_PERCLK_PODF_MASK;
+	reg |= (2 << MXC_CCM_CBCDR_PERCLK_PRED1_OFFSET);
+	__raw_writel(reg, MXC_CCM_CBCDR);
+}
+
+int __init mx51_clocks_init(unsigned long ckil, unsigned long osc,
+			unsigned long ckih1, unsigned long ckih2)
+{
+	int i;
+
+	external_low_reference = ckil;
+	external_high_reference = ckih1;
+	ckih2_reference = ckih2;
+	oscillator_reference = osc;
+
+	for (i = 0; i < ARRAY_SIZE(mx51_lookups); i++)
+		clkdev_add(&mx51_lookups[i]);
+
+	clk_tree_init();
+
+	clk_enable(&cpu_clk);
+	clk_enable(&main_bus_clk);
+
+	clk_enable(&iim_clk);
+	mx51_revision();
+	clk_disable(&iim_clk);
+
+	/* move usb_phy_clk to 24MHz */
+	clk_set_parent(&usb_phy1_clk, &osc_clk);
+
+	/* set the usboh3_clk parent to pll2_sw_clk */
+	clk_set_parent(&usboh3_clk, &pll2_sw_clk);
+
+	/* Set SDHC parents to be PLL2 */
+	clk_set_parent(&esdhc1_clk, &pll2_sw_clk);
+	clk_set_parent(&esdhc2_clk, &pll2_sw_clk);
+
+	/* set SDHC root clock as 166.25MHZ*/
+	clk_set_rate(&esdhc1_clk, 166250000);
+	clk_set_rate(&esdhc2_clk, 166250000);
+
+	/* System timer */
+	mxc_timer_init(&gpt_clk, MX51_IO_ADDRESS(MX51_GPT1_BASE_ADDR),
+		MX51_MXC_INT_GPT);
+	return 0;
+}
+
+int __init mx53_clocks_init(unsigned long ckil, unsigned long osc,
+			unsigned long ckih1, unsigned long ckih2)
+{
+	int i;
+
+	external_low_reference = ckil;
+	external_high_reference = ckih1;
+	ckih2_reference = ckih2;
+	oscillator_reference = osc;
+
+	for (i = 0; i < ARRAY_SIZE(mx53_lookups); i++)
+		clkdev_add(&mx53_lookups[i]);
+
+	clk_tree_init();
+
+	clk_set_parent(&uart_root_clk, &pll3_sw_clk);
+	clk_enable(&cpu_clk);
+	clk_enable(&main_bus_clk);
+
+	clk_enable(&iim_clk);
+	mx53_revision();
+	clk_disable(&iim_clk);
+
+	/* System timer */
+	mxc_timer_init(&gpt_clk, MX53_IO_ADDRESS(MX53_GPT1_BASE_ADDR),
+		MX53_INT_GPT);
+	return 0;
+}
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mx5/cpu.c linux-libre-2.6.38-gnu1/arch/arm/mach-mx5/cpu.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mx5/cpu.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mx5/cpu.c	2011-03-14 21:20:32.000000000 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright 2008-2009 Freescale Semiconductor, Inc. All Rights Reserved.
+ * 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
@@ -20,37 +20,18 @@
 
 static int cpu_silicon_rev = -1;
 
-#define SI_REV 0x48
+#define IIM_SREV 0x24
 
-static void query_silicon_parameter(void)
+static int get_mx51_srev(void)
 {
-	void __iomem *rom = ioremap(MX51_IROM_BASE_ADDR, MX51_IROM_SIZE);
-	u32 rev;
-
-	if (!rom) {
-		cpu_silicon_rev = -EINVAL;
-		return;
-	}
-
-	rev = readl(rom + SI_REV);
-	switch (rev) {
-	case 0x1:
-		cpu_silicon_rev = MX51_CHIP_REV_1_0;
-		break;
-	case 0x2:
-		cpu_silicon_rev = MX51_CHIP_REV_1_1;
-		break;
-	case 0x10:
-		cpu_silicon_rev = MX51_CHIP_REV_2_0;
-		break;
-	case 0x20:
-		cpu_silicon_rev = MX51_CHIP_REV_3_0;
-		break;
-	default:
-		cpu_silicon_rev = 0;
-	}
+	void __iomem *iim_base = MX51_IO_ADDRESS(MX51_IIM_BASE_ADDR);
+	u32 rev = readl(iim_base + IIM_SREV) & 0xff;
 
-	iounmap(rom);
+	if (rev == 0x0)
+		return IMX_CHIP_REVISION_2_0;
+	else if (rev == 0x10)
+		return IMX_CHIP_REVISION_3_0;
+	return 0;
 }
 
 /*
@@ -64,7 +45,7 @@ int mx51_revision(void)
 		return -EINVAL;
 
 	if (cpu_silicon_rev == -1)
-		query_silicon_parameter();
+		cpu_silicon_rev = get_mx51_srev();
 
 	return cpu_silicon_rev;
 }
@@ -79,7 +60,10 @@ EXPORT_SYMBOL(mx51_revision);
  */
 static int __init mx51_neon_fixup(void)
 {
-	if (mx51_revision() < MX51_CHIP_REV_3_0 && (elf_hwcap & HWCAP_NEON)) {
+	if (!cpu_is_mx51())
+		return 0;
+
+	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");
 	}
@@ -89,29 +73,65 @@ static int __init mx51_neon_fixup(void)
 late_initcall(mx51_neon_fixup);
 #endif
 
+static int get_mx53_srev(void)
+{
+	void __iomem *iim_base = MX51_IO_ADDRESS(MX53_IIM_BASE_ADDR);
+	u32 rev = readl(iim_base + IIM_SREV) & 0xff;
+
+	if (rev == 0x0)
+		return IMX_CHIP_REVISION_1_0;
+	else if (rev == 0x10)
+		return IMX_CHIP_REVISION_2_0;
+	return 0;
+}
+
+/*
+ * Returns:
+ *	the silicon revision of the cpu
+ *	-EINVAL - not a mx53
+ */
+int mx53_revision(void)
+{
+	if (!cpu_is_mx53())
+		return -EINVAL;
+
+	if (cpu_silicon_rev == -1)
+		cpu_silicon_rev = get_mx53_srev();
+
+	return cpu_silicon_rev;
+}
+EXPORT_SYMBOL(mx53_revision);
+
 static int __init post_cpu_init(void)
 {
 	unsigned int reg;
 	void __iomem *base;
 
-	if (!cpu_is_mx51())
-		return 0;
+	if (cpu_is_mx51() || cpu_is_mx53()) {
+		if (cpu_is_mx51())
+			base = MX51_IO_ADDRESS(MX51_AIPS1_BASE_ADDR);
+		else
+			base = MX53_IO_ADDRESS(MX53_AIPS1_BASE_ADDR);
 
-	base = MX51_IO_ADDRESS(MX51_AIPS1_BASE_ADDR);
-	__raw_writel(0x0, base + 0x40);
-	__raw_writel(0x0, base + 0x44);
-	__raw_writel(0x0, base + 0x48);
-	__raw_writel(0x0, base + 0x4C);
-	reg = __raw_readl(base + 0x50) & 0x00FFFFFF;
-	__raw_writel(reg, base + 0x50);
+		__raw_writel(0x0, base + 0x40);
+		__raw_writel(0x0, base + 0x44);
+		__raw_writel(0x0, base + 0x48);
+		__raw_writel(0x0, base + 0x4C);
+		reg = __raw_readl(base + 0x50) & 0x00FFFFFF;
+		__raw_writel(reg, base + 0x50);
 
-	base = MX51_IO_ADDRESS(MX51_AIPS2_BASE_ADDR);
-	__raw_writel(0x0, base + 0x40);
-	__raw_writel(0x0, base + 0x44);
-	__raw_writel(0x0, base + 0x48);
-	__raw_writel(0x0, base + 0x4C);
-	reg = __raw_readl(base + 0x50) & 0x00FFFFFF;
-	__raw_writel(reg, base + 0x50);
+		if (cpu_is_mx51())
+			base = MX51_IO_ADDRESS(MX51_AIPS2_BASE_ADDR);
+		else
+			base = MX53_IO_ADDRESS(MX53_AIPS2_BASE_ADDR);
+
+		__raw_writel(0x0, base + 0x40);
+		__raw_writel(0x0, base + 0x44);
+		__raw_writel(0x0, base + 0x48);
+		__raw_writel(0x0, base + 0x4C);
+		reg = __raw_readl(base + 0x50) & 0x00FFFFFF;
+		__raw_writel(reg, base + 0x50);
+	}
 
 	return 0;
 }
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mx5/crm_regs.h linux-libre-2.6.38-gnu1/arch/arm/mach-mx5/crm_regs.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mx5/crm_regs.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mx5/crm_regs.h	2011-03-14 21:20:32.000000000 -0400
@@ -18,6 +18,13 @@
 #define MX51_CORTEXA8_BASE	MX51_IO_ADDRESS(MX51_ARM_BASE_ADDR)
 #define MX51_GPC_BASE		MX51_IO_ADDRESS(MX51_GPC_BASE_ADDR)
 
+/*MX53*/
+#define MX53_CCM_BASE		MX53_IO_ADDRESS(MX53_CCM_BASE_ADDR)
+#define MX53_DPLL1_BASE		MX53_IO_ADDRESS(MX53_PLL1_BASE_ADDR)
+#define MX53_DPLL2_BASE		MX53_IO_ADDRESS(MX53_PLL2_BASE_ADDR)
+#define MX53_DPLL3_BASE		MX53_IO_ADDRESS(MX53_PLL3_BASE_ADDR)
+#define MX53_DPLL4_BASE		MX53_IO_ADDRESS(MX53_PLL3_BASE_ADDR)
+
 /* PLL Register Offsets */
 #define MXC_PLL_DP_CTL			0x00
 #define MXC_PLL_DP_CONFIG		0x04
@@ -380,7 +387,8 @@
 /* Define the bits in register CLPCR */
 #define MXC_CCM_CLPCR_BYPASS_HSC_LPM_HS		(0x1 << 23)
 #define MXC_CCM_CLPCR_BYPASS_SCC_LPM_HS		(0x1 << 22)
-#define MXC_CCM_CLPCR_BYPASS_MAX_LPM_HS		(0x1 << 21)
+#define MX51_CCM_CLPCR_BYPASS_MAX_LPM_HS		(0x1 << 21)
+#define MX53_CCM_CLPCR_BYPASS_MAX_LPM_HS		(0x1 << 25)
 #define MXC_CCM_CLPCR_BYPASS_SDMA_LPM_HS	(0x1 << 20)
 #define MXC_CCM_CLPCR_BYPASS_EMI_LPM_HS		(0x1 << 19)
 #define MXC_CCM_CLPCR_BYPASS_IPU_LPM_HS		(0x1 << 18)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mx5/devices.c linux-libre-2.6.38-gnu1/arch/arm/mach-mx5/devices.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mx5/devices.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mx5/devices.c	2011-03-14 21:20:32.000000000 -0400
@@ -97,38 +97,27 @@ struct platform_device mxc_usbh1_device
 	},
 };
 
-static struct resource mxc_wdt_resources[] = {
+static struct resource usbh2_resources[] = {
 	{
-		.start = MX51_WDOG_BASE_ADDR,
-		.end = MX51_WDOG_BASE_ADDR + SZ_16K - 1,
+		.start = MX51_OTG_BASE_ADDR + 0x400,
+		.end = MX51_OTG_BASE_ADDR + 0x400 + 0x1ff,
 		.flags = IORESOURCE_MEM,
 	},
-};
-
-struct platform_device mxc_wdt = {
-	.name = "imx2-wdt",
-	.id = 0,
-	.num_resources = ARRAY_SIZE(mxc_wdt_resources),
-	.resource = mxc_wdt_resources,
-};
-
-static struct resource mxc_kpp_resources[] = {
 	{
-		.start = MX51_MXC_INT_KPP,
-		.end = MX51_MXC_INT_KPP,
+		.start = MX51_MXC_INT_USB_H2,
 		.flags = IORESOURCE_IRQ,
-	} , {
-		.start = MX51_KPP_BASE_ADDR,
-		.end = MX51_KPP_BASE_ADDR + 0x8 - 1,
-		.flags = IORESOURCE_MEM,
 	},
 };
 
-struct platform_device mxc_keypad_device = {
-	.name = "imx-keypad",
-	.id = 0,
-	.num_resources = ARRAY_SIZE(mxc_kpp_resources),
-	.resource = mxc_kpp_resources,
+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),
+	},
 };
 
 static struct mxc_gpio_port mxc_gpio_ports[] = {
@@ -160,9 +149,36 @@ static struct mxc_gpio_port mxc_gpio_por
 		.irq_high = MX51_MXC_INT_GPIO4_HIGH,
 		.virtual_irq_start = MXC_GPIO_IRQ_START + 32 * 3
 	},
+	{
+		.chip.label = "gpio-4",
+		.base = MX53_IO_ADDRESS(MX53_GPIO5_BASE_ADDR),
+		.irq = MX53_INT_GPIO5_LOW,
+		.irq_high = MX53_INT_GPIO5_HIGH,
+		.virtual_irq_start = MXC_GPIO_IRQ_START + 32 * 4
+	},
+	{
+		.chip.label = "gpio-5",
+		.base = MX53_IO_ADDRESS(MX53_GPIO6_BASE_ADDR),
+		.irq = MX53_INT_GPIO6_LOW,
+		.irq_high = MX53_INT_GPIO6_HIGH,
+		.virtual_irq_start = MXC_GPIO_IRQ_START + 32 * 5
+	},
+	{
+		.chip.label = "gpio-6",
+		.base = MX53_IO_ADDRESS(MX53_GPIO7_BASE_ADDR),
+		.irq = MX53_INT_GPIO7_LOW,
+		.irq_high = MX53_INT_GPIO7_HIGH,
+		.virtual_irq_start = MXC_GPIO_IRQ_START + 32 * 6
+	},
 };
 
 int __init imx51_register_gpios(void)
 {
+	return mxc_gpio_init(mxc_gpio_ports, 4);
+}
+
+int __init imx53_register_gpios(void)
+{
 	return mxc_gpio_init(mxc_gpio_ports, ARRAY_SIZE(mxc_gpio_ports));
 }
+
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mx5/devices.h linux-libre-2.6.38-gnu1/arch/arm/mach-mx5/devices.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mx5/devices.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mx5/devices.h	2011-03-14 21:20:32.000000000 -0400
@@ -1,6 +1,5 @@
 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_wdt;
 extern struct platform_device mxc_hsi2c_device;
-extern struct platform_device mxc_keypad_device;
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mx5/devices-imx51.h linux-libre-2.6.38-gnu1/arch/arm/mach-mx5/devices-imx51.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mx5/devices-imx51.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mx5/devices-imx51.h	2011-03-14 21:20:32.000000000 -0400
@@ -31,6 +31,11 @@ extern const struct imx_mxc_nand_data im
 #define imx51_add_mxc_nand(pdata)	\
 	imx_add_mxc_nand(&imx51_mxc_nand_data, pdata)
 
+extern const struct imx_sdhci_esdhc_imx_data
+imx51_sdhci_esdhc_imx_data[] __initconst;
+#define imx51_add_sdhci_esdhc_imx(id, pdata)	\
+	imx_add_sdhci_esdhc_imx(&imx51_sdhci_esdhc_imx_data[id], pdata)
+
 extern const struct imx_spi_imx_data imx51_cspi_data __initconst;
 #define imx51_add_cspi(pdata)	\
 	imx_add_spi_imx(&imx51_cspi_data, pdata)
@@ -39,6 +44,14 @@ extern const struct imx_spi_imx_data imx
 #define imx51_add_ecspi(id, pdata)	\
 	imx_add_spi_imx(&imx51_ecspi_data[id], pdata)
 
-extern const struct imx_esdhc_imx_data imx51_esdhc_data[] __initconst;
-#define imx51_add_esdhc(id, pdata)	\
-	imx_add_esdhc(&imx51_esdhc_data[id], pdata)
+extern const struct imx_imx2_wdt_data imx51_imx2_wdt_data[] __initconst;
+#define imx51_add_imx2_wdt(id, pdata)	\
+	imx_add_imx2_wdt(&imx51_imx2_wdt_data[id])
+
+extern const struct imx_mxc_pwm_data imx51_mxc_pwm_data[] __initconst;
+#define imx51_add_mxc_pwm(id)	\
+	imx_add_mxc_pwm(&imx51_mxc_pwm_data[id])
+
+extern const struct imx_imx_keypad_data imx51_imx_keypad_data __initconst;
+#define imx51_add_imx_keypad(pdata)	\
+	imx_add_imx_keypad(&imx51_imx_keypad_data, pdata)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mx5/devices-imx53.h linux-libre-2.6.38-gnu1/arch/arm/mach-mx5/devices-imx53.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mx5/devices-imx53.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mx5/devices-imx53.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2010 Yong Shen. <Yong.Shen@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License version 2 as published by the
+ * Free Software Foundation.
+ */
+#include <mach/mx53.h>
+#include <mach/devices-common.h>
+
+extern const struct imx_fec_data imx53_fec_data __initconst;
+#define imx53_add_fec(pdata)   \
+	imx_add_fec(&imx53_fec_data, pdata)
+
+extern const struct imx_imx_uart_1irq_data imx53_imx_uart_data[] __initconst;
+#define imx53_add_imx_uart(id, pdata)	\
+	imx_add_imx_uart_1irq(&imx53_imx_uart_data[id], pdata)
+
+
+extern const struct imx_imx_i2c_data imx53_imx_i2c_data[] __initconst;
+#define imx53_add_imx_i2c(id, pdata)	\
+	imx_add_imx_i2c(&imx53_imx_i2c_data[id], pdata)
+
+extern const struct imx_sdhci_esdhc_imx_data
+imx53_sdhci_esdhc_imx_data[] __initconst;
+#define imx53_add_sdhci_esdhc_imx(id, pdata)	\
+	imx_add_sdhci_esdhc_imx(&imx53_sdhci_esdhc_imx_data[id], pdata)
+
+extern const struct imx_spi_imx_data imx53_ecspi_data[] __initconst;
+#define imx53_add_ecspi(id, pdata)	\
+	imx_add_spi_imx(&imx53_ecspi_data[id], pdata)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mx5/devices-mx50.h linux-libre-2.6.38-gnu1/arch/arm/mach-mx5/devices-mx50.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mx5/devices-mx50.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mx5/devices-mx50.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,26 @@
+/*
+ * 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.
+ */
+
+#include <mach/mx50.h>
+#include <mach/devices-common.h>
+
+extern const struct imx_imx_uart_1irq_data imx50_imx_uart_data[] __initconst;
+#define imx50_add_imx_uart(id, pdata)	\
+	imx_add_imx_uart_1irq(&imx50_imx_uart_data[id], pdata)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mx5/eukrea_mbimx51-baseboard.c linux-libre-2.6.38-gnu1/arch/arm/mach-mx5/eukrea_mbimx51-baseboard.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mx5/eukrea_mbimx51-baseboard.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mx5/eukrea_mbimx51-baseboard.c	2011-03-14 21:20:32.000000000 -0400
@@ -21,7 +21,6 @@
 #include <linux/fsl_devices.h>
 #include <linux/i2c/tsc2007.h>
 #include <linux/leds.h>
-#include <linux/input/matrix_keypad.h>
 
 #include <mach/common.h>
 #include <mach/hardware.h>
@@ -33,12 +32,12 @@
 #include "devices-imx51.h"
 #include "devices.h"
 
-#define MBIMX51_TSC2007_GPIO	(2*32 + 30)
+#define MBIMX51_TSC2007_GPIO	IMX_GPIO_NR(3, 30)
 #define MBIMX51_TSC2007_IRQ	(MXC_INTERNAL_IRQS + MBIMX51_TSC2007_GPIO)
-#define MBIMX51_LED0		(2*32 + 5)
-#define MBIMX51_LED1		(2*32 + 6)
-#define MBIMX51_LED2		(2*32 + 7)
-#define MBIMX51_LED3		(2*32 + 8)
+#define MBIMX51_LED0		IMX_GPIO_NR(3, 5)
+#define MBIMX51_LED1		IMX_GPIO_NR(3, 6)
+#define MBIMX51_LED2		IMX_GPIO_NR(3, 7)
+#define MBIMX51_LED3		IMX_GPIO_NR(3, 8)
 
 static struct gpio_led mbimx51_leds[] = {
 	{
@@ -84,7 +83,7 @@ static struct platform_device *devices[]
 	&mbimx51_leds_gpio,
 };
 
-static struct pad_desc mbimx51_pads[] = {
+static iomux_v3_cfg_t mbimx51_pads[] = {
 	/* UART2 */
 	MX51_PAD_UART2_RXD__UART2_RXD,
 	MX51_PAD_UART2_TXD__UART2_TXD,
@@ -96,13 +95,13 @@ static struct pad_desc mbimx51_pads[] =
 	MX51_PAD_KEY_COL5__UART3_CTS,
 
 	/* TSC2007 IRQ */
-	MX51_PAD_NANDF_D10__GPIO_3_30,
+	MX51_PAD_NANDF_D10__GPIO3_30,
 
 	/* LEDS */
-	MX51_PAD_DISPB2_SER_DIN__GPIO_3_5,
-	MX51_PAD_DISPB2_SER_DIO__GPIO_3_6,
-	MX51_PAD_DISPB2_SER_CLK__GPIO_3_7,
-	MX51_PAD_DISPB2_SER_RS__GPIO_3_8,
+	MX51_PAD_DISPB2_SER_DIN__GPIO3_5,
+	MX51_PAD_DISPB2_SER_DIO__GPIO3_6,
+	MX51_PAD_DISPB2_SER_CLK__GPIO3_7,
+	MX51_PAD_DISPB2_SER_RS__GPIO3_8,
 
 	/* KPP */
 	MX51_PAD_KEY_ROW0__KEY_ROW0,
@@ -157,7 +156,7 @@ static int mbimx51_keymap[] = {
 	KEY(3, 3, KEY_ENTER),
 };
 
-static struct matrix_keymap_data mbimx51_map_data = {
+static const struct matrix_keymap_data mbimx51_map_data __initconst = {
 	.keymap		= mbimx51_keymap,
 	.keymap_size	= ARRAY_SIZE(mbimx51_keymap),
 };
@@ -209,7 +208,7 @@ void __init eukrea_mbimx51_baseboard_ini
 
 	platform_add_devices(devices, ARRAY_SIZE(devices));
 
-	mxc_register_device(&mxc_keypad_device, &mbimx51_map_data);
+	imx51_add_imx_keypad(&mbimx51_map_data);
 
 	gpio_request(MBIMX51_TSC2007_GPIO, "tsc2007_irq");
 	gpio_direction_input(MBIMX51_TSC2007_GPIO);
@@ -217,6 +216,6 @@ void __init eukrea_mbimx51_baseboard_ini
 	i2c_register_board_info(1, mbimx51_i2c_devices,
 				ARRAY_SIZE(mbimx51_i2c_devices));
 
-	imx51_add_esdhc(0, NULL);
-	imx51_add_esdhc(1, NULL);
+	imx51_add_sdhci_esdhc_imx(0, NULL);
+	imx51_add_sdhci_esdhc_imx(1, NULL);
 }
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mx5/eukrea_mbimxsd-baseboard.c linux-libre-2.6.38-gnu1/arch/arm/mach-mx5/eukrea_mbimxsd-baseboard.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mx5/eukrea_mbimxsd-baseboard.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mx5/eukrea_mbimxsd-baseboard.c	2011-03-14 21:20:32.000000000 -0400
@@ -45,14 +45,13 @@
 #include "devices-imx51.h"
 #include "devices.h"
 
-#define MBIMXSD_GPIO_3_31 IOMUX_PAD(0x554, 0x16C, 3, 0x0, 0, \
-				MX51_PAD_CTRL_1 | PAD_CTL_PUS_22K_UP)
-
-static struct pad_desc eukrea_mbimxsd_pads[] = {
+static iomux_v3_cfg_t eukrea_mbimxsd_pads[] = {
 	/* LED */
-	MX51_PAD_NANDF_D10__GPIO_3_30,
+	MX51_PAD_NANDF_D10__GPIO3_30,
 	/* SWITCH */
-	MBIMXSD_GPIO_3_31,
+	_MX51_PAD_NANDF_D9__GPIO3_31 | 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),
 	/* UART2 */
 	MX51_PAD_UART2_RXD__UART2_RXD,
 	MX51_PAD_UART2_TXD__UART2_TXD,
@@ -70,8 +69,8 @@ static struct pad_desc eukrea_mbimxsd_pa
 	MX51_PAD_SD1_DATA3__SD1_DATA3,
 };
 
-#define GPIO_LED1	(2 * 32 + 30)
-#define GPIO_SWITCH1	(2 * 32 + 31)
+#define GPIO_LED1	IMX_GPIO_NR(3, 30)
+#define GPIO_SWITCH1	IMX_GPIO_NR(3, 31)
 
 static struct gpio_led eukrea_mbimxsd_leds[] = {
 	{
@@ -149,7 +148,7 @@ void __init eukrea_mbimxsd51_baseboard_i
 	imx51_add_imx_uart(1, NULL);
 	imx51_add_imx_uart(2, &uart_pdata);
 
-	imx51_add_esdhc(0, NULL);
+	imx51_add_sdhci_esdhc_imx(0, NULL);
 
 	gpio_request(GPIO_LED1, "LED1");
 	gpio_direction_output(GPIO_LED1, 1);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mx5/Kconfig linux-libre-2.6.38-gnu1/arch/arm/mach-mx5/Kconfig
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mx5/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mx5/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -1,20 +1,47 @@
 if ARCH_MX5
+# ARCH_MX51 and ARCH_MX50 are left for compatibility
+
+config ARCH_MX50
+	bool
 
 config ARCH_MX51
 	bool
-	default y
+
+config ARCH_MX53
+	bool
+
+config SOC_IMX50
+	bool
 	select MXC_TZIC
 	select ARCH_MXC_IOMUX_V3
 	select ARCH_MXC_AUDMUX_V2
 	select ARCH_HAS_CPUFREQ
+	select ARCH_MX50
+
+config	SOC_IMX51
+	bool
+	select MXC_TZIC
+	select ARCH_MXC_IOMUX_V3
+	select ARCH_MXC_AUDMUX_V2
+	select ARCH_HAS_CPUFREQ
+	select ARCH_MX51
+
+config	SOC_IMX53
+	bool
+	select MXC_TZIC
+	select ARCH_MXC_IOMUX_V3
+	select ARCH_MX53
 
 comment "MX5 platforms:"
 
 config MACH_MX51_BABBAGE
 	bool "Support MX51 BABBAGE platforms"
+	select SOC_IMX51
+	select IMX_HAVE_PLATFORM_IMX2_WDT
 	select IMX_HAVE_PLATFORM_IMX_I2C
 	select IMX_HAVE_PLATFORM_IMX_UART
-	select IMX_HAVE_PLATFORM_ESDHC
+	select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
+	select IMX_HAVE_PLATFORM_SPI_IMX
 	help
 	  Include support for MX51 Babbage platform, also known as MX51EVK in
 	  u-boot. This includes specific configurations for the board and its
@@ -22,7 +49,10 @@ config MACH_MX51_BABBAGE
 
 config MACH_MX51_3DS
 	bool "Support MX51PDK (3DS)"
+	select SOC_IMX51
+	select IMX_HAVE_PLATFORM_IMX_KEYPAD
 	select IMX_HAVE_PLATFORM_IMX_UART
+	select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
 	select IMX_HAVE_PLATFORM_SPI_IMX
 	select MXC_DEBUG_BOARD
 	help
@@ -31,6 +61,7 @@ config MACH_MX51_3DS
 
 config MACH_EUKREA_CPUIMX51
 	bool "Support Eukrea CPUIMX51 module"
+	select SOC_IMX51
 	select IMX_HAVE_PLATFORM_IMX_I2C
 	select IMX_HAVE_PLATFORM_IMX_UART
 	select IMX_HAVE_PLATFORM_MXC_NAND
@@ -47,7 +78,8 @@ choice
 config MACH_EUKREA_MBIMX51_BASEBOARD
 	prompt "Eukrea MBIMX51 development board"
 	bool
-	select IMX_HAVE_PLATFORM_ESDHC
+	select IMX_HAVE_PLATFORM_IMX_KEYPAD
+	select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
 	help
 	  This adds board specific devices that can be found on Eukrea's
 	  MBIMX51 evaluation board.
@@ -56,6 +88,7 @@ endchoice
 
 config MACH_EUKREA_CPUIMX51SD
 	bool "Support Eukrea CPUIMX51SD module"
+	select SOC_IMX51
 	select IMX_HAVE_PLATFORM_IMX_I2C
 	select IMX_HAVE_PLATFORM_SPI_IMX
 	select IMX_HAVE_PLATFORM_IMX_UART
@@ -72,7 +105,7 @@ choice
 config MACH_EUKREA_MBIMXSD51_BASEBOARD
 	prompt "Eukrea MBIMXSD development board"
 	bool
-	select IMX_HAVE_PLATFORM_ESDHC
+	select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
 	help
 	  This adds board specific devices that can be found on Eukrea's
 	  MBIMXSD evaluation board.
@@ -81,9 +114,51 @@ endchoice
 
 config MACH_MX51_EFIKAMX
 	bool "Support MX51 Genesi Efika MX nettop"
+	select SOC_IMX51
 	select IMX_HAVE_PLATFORM_IMX_UART
+	select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
+	select IMX_HAVE_PLATFORM_SPI_IMX
 	help
 	  Include support for Genesi Efika MX nettop. This includes specific
 	  configurations for the board and its peripherals.
 
+config MACH_MX53_EVK
+	bool "Support MX53 EVK platforms"
+	select SOC_IMX53
+	select IMX_HAVE_PLATFORM_IMX_UART
+	select IMX_HAVE_PLATFORM_IMX_I2C
+	select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
+	select IMX_HAVE_PLATFORM_SPI_IMX
+	help
+	  Include support for MX53 EVK platform. This includes specific
+	  configurations for the board and its peripherals.
+
+config MACH_MX53_SMD
+	bool "Support MX53 SMD platforms"
+	select SOC_IMX53
+	select IMX_HAVE_PLATFORM_IMX_UART
+	help
+	  Include support for MX53 SMD platform. This includes specific
+	  configurations for the board and its peripherals.
+
+config MACH_MX53_LOCO
+	bool "Support MX53 LOCO platforms"
+	select SOC_IMX53
+	select IMX_HAVE_PLATFORM_IMX_UART
+	help
+	  Include support for MX53 LOCO platform. This includes specific
+	  configurations for the board and its peripherals.
+
+config MACH_MX50_RDP
+	bool "Support MX50 reference design platform"
+	depends on BROKEN
+	select SOC_IMX50
+	select IMX_HAVE_PLATFORM_IMX_I2C
+	select IMX_HAVE_PLATFORM_IMX_UART
+	select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
+	select IMX_HAVE_PLATFORM_SPI_IMX
+	help
+	  Include support for MX50 reference design platform (RDP) board. This
+	  includes specific configurations for the board and its peripherals.
+
 endif
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mx5/Makefile linux-libre-2.6.38-gnu1/arch/arm/mach-mx5/Makefile
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mx5/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mx5/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -3,13 +3,18 @@
 #
 
 # Object file lists.
-obj-y   := cpu.o mm.o clock-mx51.o devices.o
+obj-y   := cpu.o mm.o clock-mx51-mx53.o devices.o
+obj-$(CONFIG_SOC_IMX50) += mm-mx50.o
 
 obj-$(CONFIG_CPU_FREQ_IMX)    += cpu_op-mx51.o
 obj-$(CONFIG_MACH_MX51_BABBAGE) += board-mx51_babbage.o
 obj-$(CONFIG_MACH_MX51_3DS) += board-mx51_3ds.o
+obj-$(CONFIG_MACH_MX53_EVK) += board-mx53_evk.o
+obj-$(CONFIG_MACH_MX53_SMD) += board-mx53_smd.o
+obj-$(CONFIG_MACH_MX53_LOCO) += board-mx53_loco.o
 obj-$(CONFIG_MACH_EUKREA_CPUIMX51) += board-cpuimx51.o
 obj-$(CONFIG_MACH_EUKREA_MBIMX51_BASEBOARD) += eukrea_mbimx51-baseboard.o
 obj-$(CONFIG_MACH_EUKREA_CPUIMX51SD) += board-cpuimx51sd.o
 obj-$(CONFIG_MACH_EUKREA_MBIMXSD51_BASEBOARD) += eukrea_mbimxsd-baseboard.o
 obj-$(CONFIG_MACH_MX51_EFIKAMX) += board-mx51_efikamx.o
+obj-$(CONFIG_MACH_MX50_RDP) += board-mx50_rdp.o
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mx5/Makefile.boot linux-libre-2.6.38-gnu1/arch/arm/mach-mx5/Makefile.boot
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mx5/Makefile.boot	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mx5/Makefile.boot	2011-03-14 21:20:32.000000000 -0400
@@ -1,3 +1,9 @@
-   zreladdr-y	:= 0x90008000
-params_phys-y	:= 0x90000100
-initrd_phys-y	:= 0x90800000
+   zreladdr-$(CONFIG_ARCH_MX50)	:= 0x70008000
+params_phys-$(CONFIG_ARCH_MX50)	:= 0x70000100
+initrd_phys-$(CONFIG_ARCH_MX50)	:= 0x70800000
+   zreladdr-$(CONFIG_ARCH_MX51)	:= 0x90008000
+params_phys-$(CONFIG_ARCH_MX51)	:= 0x90000100
+initrd_phys-$(CONFIG_ARCH_MX51)	:= 0x90800000
+   zreladdr-$(CONFIG_ARCH_MX53)	:= 0x70008000
+params_phys-$(CONFIG_ARCH_MX53)	:= 0x70000100
+initrd_phys-$(CONFIG_ARCH_MX53)	:= 0x70800000
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mx5/mm.c linux-libre-2.6.38-gnu1/arch/arm/mach-mx5/mm.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mx5/mm.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mx5/mm.c	2011-03-14 21:20:32.000000000 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright 2008-2009 Freescale Semiconductor, Inc. All Rights Reserved.
+ * 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
@@ -23,33 +23,21 @@
 /*
  * Define the MX51 memory map.
  */
-static struct map_desc mxc_io_desc[] __initdata = {
-	{
-		.virtual = MX51_IRAM_BASE_ADDR_VIRT,
-		.pfn = __phys_to_pfn(MX51_IRAM_BASE_ADDR),
-		.length = MX51_IRAM_SIZE,
-		.type = MT_DEVICE
-	}, {
-		.virtual = MX51_DEBUG_BASE_ADDR_VIRT,
-		.pfn = __phys_to_pfn(MX51_DEBUG_BASE_ADDR),
-		.length = MX51_DEBUG_SIZE,
-		.type = MT_DEVICE
-	}, {
-		.virtual = MX51_AIPS1_BASE_ADDR_VIRT,
-		.pfn = __phys_to_pfn(MX51_AIPS1_BASE_ADDR),
-		.length = MX51_AIPS1_SIZE,
-		.type = MT_DEVICE
-	}, {
-		.virtual = MX51_SPBA0_BASE_ADDR_VIRT,
-		.pfn = __phys_to_pfn(MX51_SPBA0_BASE_ADDR),
-		.length = MX51_SPBA0_SIZE,
-		.type = MT_DEVICE
-	}, {
-		.virtual = MX51_AIPS2_BASE_ADDR_VIRT,
-		.pfn = __phys_to_pfn(MX51_AIPS2_BASE_ADDR),
-		.length = MX51_AIPS2_SIZE,
-		.type = MT_DEVICE
-	},
+static struct map_desc mx51_io_desc[] __initdata = {
+	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),
+};
+
+/*
+ * Define the MX53 memory map.
+ */
+static struct map_desc mx53_io_desc[] __initdata = {
+	imx_map_entry(MX53, AIPS1, MT_DEVICE),
+	imx_map_entry(MX53, SPBA0, MT_DEVICE),
+	imx_map_entry(MX53, AIPS2, MT_DEVICE),
 };
 
 /*
@@ -61,8 +49,16 @@ void __init mx51_map_io(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_WDOG_BASE_ADDR));
-	iotable_init(mxc_io_desc, ARRAY_SIZE(mxc_io_desc));
+	mxc_arch_reset_init(MX51_IO_ADDRESS(MX51_WDOG1_BASE_ADDR));
+	iotable_init(mx51_io_desc, ARRAY_SIZE(mx51_io_desc));
+}
+
+void __init mx53_map_io(void)
+{
+	mxc_set_cpu_type(MXC_CPU_MX53);
+	mxc_iomux_v3_init(MX53_IO_ADDRESS(MX53_IOMUXC_BASE_ADDR));
+	mxc_arch_reset_init(MX53_IO_ADDRESS(MX53_WDOG_BASE_ADDR));
+	iotable_init(mx53_io_desc, ARRAY_SIZE(mx53_io_desc));
 }
 
 int imx51_register_gpios(void);
@@ -72,7 +68,7 @@ void __init mx51_init_irq(void)
 	unsigned long tzic_addr;
 	void __iomem *tzic_virt;
 
-	if (mx51_revision() < MX51_CHIP_REV_2_0)
+	if (mx51_revision() < IMX_CHIP_REVISION_2_0)
 		tzic_addr = MX51_TZIC_BASE_ADDR_TO1;
 	else
 		tzic_addr = MX51_TZIC_BASE_ADDR;
@@ -84,3 +80,20 @@ void __init mx51_init_irq(void)
 	tzic_init_irq(tzic_virt);
 	imx51_register_gpios();
 }
+
+int imx53_register_gpios(void);
+
+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);
+	imx53_register_gpios();
+}
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mx5/mm-mx50.c linux-libre-2.6.38-gnu1/arch/arm/mach-mx5/mm-mx50.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mx5/mm-mx50.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mx5/mm-mx50.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,59 @@
+/*
+ * 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>
+
+/*
+ * 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)
+{
+	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));
+	iotable_init(mx50_io_desc, ARRAY_SIZE(mx50_io_desc));
+}
+
+int imx50_register_gpios(void);
+
+void __init mx50_init_irq(void)
+{
+	tzic_init_irq(MX50_IO_ADDRESS(MX50_TZIC_BASE_ADDR));
+	imx50_register_gpios();
+}
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mxc91231/clock.c linux-libre-2.6.38-gnu1/arch/arm/mach-mxc91231/clock.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mxc91231/clock.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mxc91231/clock.c	2011-03-14 21:20:32.000000000 -0400
@@ -2,12 +2,12 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/io.h>
+#include <linux/clkdev.h>
 
 #include <mach/clock.h>
 #include <mach/hardware.h>
 #include <mach/common.h>
 
-#include <asm/clkdev.h>
 #include <asm/bug.h>
 #include <asm/div64.h>
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mxc91231/mm.c linux-libre-2.6.38-gnu1/arch/arm/mach-mxc91231/mm.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mxc91231/mm.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mxc91231/mm.c	2011-03-14 21:20:32.000000000 -0400
@@ -27,48 +27,15 @@
 /*
  * This structure defines the MXC memory map.
  */
-static struct map_desc mxc_io_desc[] __initdata = {
-	{
-		.virtual	= MXC91231_L2CC_BASE_ADDR_VIRT,
-		.pfn		= __phys_to_pfn(MXC91231_L2CC_BASE_ADDR),
-		.length		= MXC91231_L2CC_SIZE,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= MXC91231_X_MEMC_BASE_ADDR_VIRT,
-		.pfn		= __phys_to_pfn(MXC91231_X_MEMC_BASE_ADDR),
-		.length		= MXC91231_X_MEMC_SIZE,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= MXC91231_ROMP_BASE_ADDR_VIRT,
-		.pfn		= __phys_to_pfn(MXC91231_ROMP_BASE_ADDR),
-		.length		= MXC91231_ROMP_SIZE,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= MXC91231_AVIC_BASE_ADDR_VIRT,
-		.pfn		= __phys_to_pfn(MXC91231_AVIC_BASE_ADDR),
-		.length		= MXC91231_AVIC_SIZE,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= MXC91231_AIPS1_BASE_ADDR_VIRT,
-		.pfn		= __phys_to_pfn(MXC91231_AIPS1_BASE_ADDR),
-		.length		= MXC91231_AIPS1_SIZE,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= MXC91231_SPBA0_BASE_ADDR_VIRT,
-		.pfn		= __phys_to_pfn(MXC91231_SPBA0_BASE_ADDR),
-		.length		= MXC91231_SPBA0_SIZE,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= MXC91231_SPBA1_BASE_ADDR_VIRT,
-		.pfn		= __phys_to_pfn(MXC91231_SPBA1_BASE_ADDR),
-		.length		= MXC91231_SPBA1_SIZE,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= MXC91231_AIPS2_BASE_ADDR_VIRT,
-		.pfn		= __phys_to_pfn(MXC91231_AIPS2_BASE_ADDR),
-		.length		= MXC91231_AIPS2_SIZE,
-		.type		= MT_DEVICE,
-	},
+static struct map_desc mxc91231_io_desc[] __initdata = {
+	imx_map_entry(MXC91231, L2CC, MT_DEVICE),
+	imx_map_entry(MXC91231, X_MEMC, MT_DEVICE),
+	imx_map_entry(MXC91231, ROMP, MT_DEVICE),
+	imx_map_entry(MXC91231, AVIC, MT_DEVICE),
+	imx_map_entry(MXC91231, AIPS1, MT_DEVICE),
+	imx_map_entry(MXC91231, SPBA0, MT_DEVICE),
+	imx_map_entry(MXC91231, SPBA1, MT_DEVICE),
+	imx_map_entry(MXC91231, AIPS2, MT_DEVICE),
 };
 
 /*
@@ -80,7 +47,7 @@ void __init mxc91231_map_io(void)
 {
 	mxc_set_cpu_type(MXC_CPU_MXC91231);
 
-	iotable_init(mxc_io_desc, ARRAY_SIZE(mxc_io_desc));
+	iotable_init(mxc91231_io_desc, ARRAY_SIZE(mxc91231_io_desc));
 }
 
 int mxc91231_register_gpios(void);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mxs/clock.c linux-libre-2.6.38-gnu1/arch/arm/mach-mxs/clock.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mxs/clock.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mxs/clock.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,198 @@
+/*
+ * Based on arch/arm/plat-omap/clock.c
+ *
+ * Copyright (C) 2004 - 2005 Nokia corporation
+ * Written by Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com>
+ * Modified for omap shared clock framework by Tony Lindgren <tony@atomide.com>
+ * 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.
+ */
+
+/* #define DEBUG */
+
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/platform_device.h>
+#include <linux/proc_fs.h>
+#include <linux/semaphore.h>
+#include <linux/string.h>
+
+#include <mach/clock.h>
+
+static LIST_HEAD(clocks);
+static DEFINE_MUTEX(clocks_mutex);
+
+/*-------------------------------------------------------------------------
+ * Standard clock functions defined in include/linux/clk.h
+ *-------------------------------------------------------------------------*/
+
+static void __clk_disable(struct clk *clk)
+{
+	if (clk == NULL || IS_ERR(clk))
+		return;
+	WARN_ON(!clk->usecount);
+
+	if (!(--clk->usecount)) {
+		if (clk->disable)
+			clk->disable(clk);
+		__clk_disable(clk->parent);
+	}
+}
+
+static int __clk_enable(struct clk *clk)
+{
+	if (clk == NULL || IS_ERR(clk))
+		return -EINVAL;
+
+	if (clk->usecount++ == 0) {
+		__clk_enable(clk->parent);
+
+		if (clk->enable)
+			clk->enable(clk);
+	}
+	return 0;
+}
+
+/* This function increments the reference count on the clock and enables the
+ * clock if not already enabled. The parent clock tree is recursively enabled
+ */
+int clk_enable(struct clk *clk)
+{
+	int ret = 0;
+
+	if (clk == NULL || IS_ERR(clk))
+		return -EINVAL;
+
+	mutex_lock(&clocks_mutex);
+	ret = __clk_enable(clk);
+	mutex_unlock(&clocks_mutex);
+
+	return ret;
+}
+EXPORT_SYMBOL(clk_enable);
+
+/* This function decrements the reference count on the clock and disables
+ * the clock when reference count is 0. The parent clock tree is
+ * recursively disabled
+ */
+void clk_disable(struct clk *clk)
+{
+	if (clk == NULL || IS_ERR(clk))
+		return;
+
+	mutex_lock(&clocks_mutex);
+	__clk_disable(clk);
+	mutex_unlock(&clocks_mutex);
+}
+EXPORT_SYMBOL(clk_disable);
+
+/* Retrieve the *current* clock rate. If the clock itself
+ * does not provide a special calculation routine, ask
+ * its parent and so on, until one is able to return
+ * a valid clock rate
+ */
+unsigned long clk_get_rate(struct clk *clk)
+{
+	if (clk == NULL || IS_ERR(clk))
+		return 0UL;
+
+	if (clk->get_rate)
+		return clk->get_rate(clk);
+
+	return clk_get_rate(clk->parent);
+}
+EXPORT_SYMBOL(clk_get_rate);
+
+/* Round the requested clock rate to the nearest supported
+ * rate that is less than or equal to the requested rate.
+ * This is dependent on the clock's current parent.
+ */
+long clk_round_rate(struct clk *clk, unsigned long rate)
+{
+	if (clk == NULL || IS_ERR(clk) || !clk->round_rate)
+		return 0;
+
+	return clk->round_rate(clk, rate);
+}
+EXPORT_SYMBOL(clk_round_rate);
+
+/* Set the clock to the requested clock rate. The rate must
+ * match a supported rate exactly based on what clk_round_rate returns
+ */
+int clk_set_rate(struct clk *clk, unsigned long rate)
+{
+	int ret = -EINVAL;
+
+	if (clk == NULL || IS_ERR(clk) || clk->set_rate == NULL || rate == 0)
+		return ret;
+
+	mutex_lock(&clocks_mutex);
+	ret = clk->set_rate(clk, rate);
+	mutex_unlock(&clocks_mutex);
+
+	return ret;
+}
+EXPORT_SYMBOL(clk_set_rate);
+
+/* Set the clock's parent to another clock source */
+int clk_set_parent(struct clk *clk, struct clk *parent)
+{
+	int ret = -EINVAL;
+	struct clk *old;
+
+	if (clk == NULL || IS_ERR(clk) || parent == NULL ||
+	    IS_ERR(parent) || clk->set_parent == NULL)
+		return ret;
+
+	if (clk->usecount)
+		clk_enable(parent);
+
+	mutex_lock(&clocks_mutex);
+	ret = clk->set_parent(clk, parent);
+	if (ret == 0) {
+		old = clk->parent;
+		clk->parent = parent;
+	} else {
+		old = parent;
+	}
+	mutex_unlock(&clocks_mutex);
+
+	if (clk->usecount)
+		clk_disable(old);
+
+	return ret;
+}
+EXPORT_SYMBOL(clk_set_parent);
+
+/* Retrieve the clock's parent clock source */
+struct clk *clk_get_parent(struct clk *clk)
+{
+	struct clk *ret = NULL;
+
+	if (clk == NULL || IS_ERR(clk))
+		return ret;
+
+	return clk->parent;
+}
+EXPORT_SYMBOL(clk_get_parent);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mxs/clock-mx23.c linux-libre-2.6.38-gnu1/arch/arm/mach-mxs/clock-mx23.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mxs/clock-mx23.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mxs/clock-mx23.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,535 @@
+/*
+ * 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.
+ */
+
+#include <linux/mm.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/jiffies.h>
+#include <linux/clkdev.h>
+
+#include <asm/clkdev.h>
+#include <asm/div64.h>
+
+#include <mach/mx23.h>
+#include <mach/common.h>
+#include <mach/clock.h>
+
+#include "regs-clkctrl-mx23.h"
+
+#define CLKCTRL_BASE_ADDR	MX23_IO_ADDRESS(MX23_CLKCTRL_BASE_ADDR)
+#define DIGCTRL_BASE_ADDR	MX23_IO_ADDRESS(MX23_DIGCTL_BASE_ADDR)
+
+#define PARENT_RATE_SHIFT	8
+
+static int _raw_clk_enable(struct clk *clk)
+{
+	u32 reg;
+
+	if (clk->enable_reg) {
+		reg = __raw_readl(clk->enable_reg);
+		reg &= ~(1 << clk->enable_shift);
+		__raw_writel(reg, clk->enable_reg);
+	}
+
+	return 0;
+}
+
+static void _raw_clk_disable(struct clk *clk)
+{
+	u32 reg;
+
+	if (clk->enable_reg) {
+		reg = __raw_readl(clk->enable_reg);
+		reg |= 1 << clk->enable_shift;
+		__raw_writel(reg, clk->enable_reg);
+	}
+}
+
+/*
+ * ref_xtal_clk
+ */
+static unsigned long ref_xtal_clk_get_rate(struct clk *clk)
+{
+	return 24000000;
+}
+
+static struct clk ref_xtal_clk = {
+	.get_rate = ref_xtal_clk_get_rate,
+};
+
+/*
+ * pll_clk
+ */
+static unsigned long pll_clk_get_rate(struct clk *clk)
+{
+	return 480000000;
+}
+
+static int pll_clk_enable(struct clk *clk)
+{
+	__raw_writel(BM_CLKCTRL_PLLCTRL0_POWER |
+			BM_CLKCTRL_PLLCTRL0_EN_USB_CLKS,
+			CLKCTRL_BASE_ADDR + HW_CLKCTRL_PLLCTRL0_SET);
+
+	/* Only a 10us delay is need. PLLCTRL1 LOCK bitfied is only a timer
+	 * and is incorrect (excessive). Per definition of the PLLCTRL0
+	 * POWER field, waiting at least 10us.
+	 */
+	udelay(10);
+
+	return 0;
+}
+
+static void pll_clk_disable(struct clk *clk)
+{
+	__raw_writel(BM_CLKCTRL_PLLCTRL0_POWER |
+			BM_CLKCTRL_PLLCTRL0_EN_USB_CLKS,
+			CLKCTRL_BASE_ADDR + HW_CLKCTRL_PLLCTRL0_CLR);
+}
+
+static struct clk pll_clk = {
+	 .get_rate = pll_clk_get_rate,
+	 .enable = pll_clk_enable,
+	 .disable = pll_clk_disable,
+	 .parent = &ref_xtal_clk,
+};
+
+/*
+ * ref_clk
+ */
+#define _CLK_GET_RATE_REF(name, sr, ss)					\
+static unsigned long name##_get_rate(struct clk *clk)			\
+{									\
+	unsigned long parent_rate;					\
+	u32 reg, div;							\
+									\
+	reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_##sr);		\
+	div = (reg >> BP_CLKCTRL_##sr##_##ss##FRAC) & 0x3f;		\
+	parent_rate = clk_get_rate(clk->parent);			\
+									\
+	return SH_DIV((parent_rate >> PARENT_RATE_SHIFT) * 18,		\
+			div, PARENT_RATE_SHIFT);			\
+}
+
+_CLK_GET_RATE_REF(ref_cpu_clk, FRAC, CPU)
+_CLK_GET_RATE_REF(ref_emi_clk, FRAC, EMI)
+_CLK_GET_RATE_REF(ref_pix_clk, FRAC, PIX)
+_CLK_GET_RATE_REF(ref_io_clk, FRAC, IO)
+
+#define _DEFINE_CLOCK_REF(name, er, es)					\
+	static struct clk name = {					\
+		.enable_reg	= CLKCTRL_BASE_ADDR + HW_CLKCTRL_##er,	\
+		.enable_shift	= BP_CLKCTRL_##er##_CLKGATE##es,	\
+		.get_rate	= name##_get_rate,			\
+		.enable		= _raw_clk_enable,			\
+		.disable	= _raw_clk_disable,			\
+		.parent		= &pll_clk,				\
+	}
+
+_DEFINE_CLOCK_REF(ref_cpu_clk, FRAC, CPU);
+_DEFINE_CLOCK_REF(ref_emi_clk, FRAC, EMI);
+_DEFINE_CLOCK_REF(ref_pix_clk, FRAC, PIX);
+_DEFINE_CLOCK_REF(ref_io_clk, FRAC, IO);
+
+/*
+ * General clocks
+ *
+ * clk_get_rate
+ */
+static unsigned long rtc_clk_get_rate(struct clk *clk)
+{
+	/* ref_xtal_clk is implemented as the only parent */
+	return clk_get_rate(clk->parent) / 768;
+}
+
+static unsigned long clk32k_clk_get_rate(struct clk *clk)
+{
+	return clk->parent->get_rate(clk->parent) / 750;
+}
+
+#define _CLK_GET_RATE(name, rs)						\
+static unsigned long name##_get_rate(struct clk *clk)			\
+{									\
+	u32 reg, div;							\
+									\
+	reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_##rs);		\
+									\
+	if (clk->parent == &ref_xtal_clk)				\
+		div = (reg & BM_CLKCTRL_##rs##_DIV_XTAL) >>		\
+			BP_CLKCTRL_##rs##_DIV_XTAL;			\
+	else								\
+		div = (reg & BM_CLKCTRL_##rs##_DIV_##rs) >>		\
+			BP_CLKCTRL_##rs##_DIV_##rs;			\
+									\
+	if (!div)							\
+		return -EINVAL;						\
+									\
+	return clk_get_rate(clk->parent) / div;				\
+}
+
+_CLK_GET_RATE(cpu_clk, CPU)
+_CLK_GET_RATE(emi_clk, EMI)
+
+#define _CLK_GET_RATE1(name, rs)					\
+static unsigned long name##_get_rate(struct clk *clk)			\
+{									\
+	u32 reg, div;							\
+									\
+	reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_##rs);		\
+	div = (reg & BM_CLKCTRL_##rs##_DIV) >> BP_CLKCTRL_##rs##_DIV;	\
+									\
+	if (!div)							\
+		return -EINVAL;						\
+									\
+	return clk_get_rate(clk->parent) / div;				\
+}
+
+_CLK_GET_RATE1(hbus_clk, HBUS)
+_CLK_GET_RATE1(xbus_clk, XBUS)
+_CLK_GET_RATE1(ssp_clk, SSP)
+_CLK_GET_RATE1(gpmi_clk, GPMI)
+_CLK_GET_RATE1(lcdif_clk, PIX)
+
+#define _CLK_GET_RATE_STUB(name)					\
+static unsigned long name##_get_rate(struct clk *clk)			\
+{									\
+	return clk_get_rate(clk->parent);				\
+}
+
+_CLK_GET_RATE_STUB(uart_clk)
+_CLK_GET_RATE_STUB(audio_clk)
+_CLK_GET_RATE_STUB(pwm_clk)
+
+/*
+ * clk_set_rate
+ */
+static int cpu_clk_set_rate(struct clk *clk, unsigned long rate)
+{
+	u32 reg, bm_busy, div_max, d, f, div, frac;
+	unsigned long diff, parent_rate, calc_rate;
+	int i;
+
+	parent_rate = clk_get_rate(clk->parent);
+
+	if (clk->parent == &ref_xtal_clk) {
+		div_max = BM_CLKCTRL_CPU_DIV_XTAL >> BP_CLKCTRL_CPU_DIV_XTAL;
+		bm_busy = BM_CLKCTRL_CPU_BUSY_REF_XTAL;
+		div = DIV_ROUND_UP(parent_rate, rate);
+		if (div == 0 || div > div_max)
+			return -EINVAL;
+	} else {
+		div_max = BM_CLKCTRL_CPU_DIV_CPU >> BP_CLKCTRL_CPU_DIV_CPU;
+		bm_busy = BM_CLKCTRL_CPU_BUSY_REF_CPU;
+		rate >>= PARENT_RATE_SHIFT;
+		parent_rate >>= PARENT_RATE_SHIFT;
+		diff = parent_rate;
+		div = frac = 1;
+		for (d = 1; d <= div_max; d++) {
+			f = parent_rate * 18 / d / rate;
+			if ((parent_rate * 18 / d) % rate)
+				f++;
+			if (f < 18 || f > 35)
+				continue;
+
+			calc_rate = parent_rate * 18 / f / d;
+			if (calc_rate > rate)
+				continue;
+
+			if (rate - calc_rate < diff) {
+				frac = f;
+				div = d;
+				diff = rate - calc_rate;
+			}
+
+			if (diff == 0)
+				break;
+		}
+
+		if (diff == parent_rate)
+			return -EINVAL;
+
+		reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_FRAC);
+		reg &= ~BM_CLKCTRL_FRAC_CPUFRAC;
+		reg |= frac;
+		__raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_FRAC);
+	}
+
+	reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_CPU);
+	reg &= ~BM_CLKCTRL_CPU_DIV_CPU;
+	reg |= div << BP_CLKCTRL_CPU_DIV_CPU;
+	__raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_CPU);
+
+	for (i = 10000; i; i--)
+		if (!(__raw_readl(CLKCTRL_BASE_ADDR +
+					HW_CLKCTRL_CPU) & bm_busy))
+			break;
+	if (!i)	{
+		pr_err("%s: divider writing timeout\n", __func__);
+		return -ETIMEDOUT;
+	}
+
+	return 0;
+}
+
+#define _CLK_SET_RATE(name, dr)						\
+static int name##_set_rate(struct clk *clk, unsigned long rate)		\
+{									\
+	u32 reg, div_max, div;						\
+	unsigned long parent_rate;					\
+	int i;								\
+									\
+	parent_rate = clk_get_rate(clk->parent);			\
+	div_max = BM_CLKCTRL_##dr##_DIV >> BP_CLKCTRL_##dr##_DIV;	\
+									\
+	div = DIV_ROUND_UP(parent_rate, rate);				\
+	if (div == 0 || div > div_max)					\
+		return -EINVAL;						\
+									\
+	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)) {				\
+		pr_err("%s: clock is gated\n", __func__);		\
+		return -EINVAL;						\
+	}								\
+	__raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_##dr);		\
+									\
+	for (i = 10000; i; i--)						\
+		if (!(__raw_readl(CLKCTRL_BASE_ADDR +			\
+			HW_CLKCTRL_##dr) & BM_CLKCTRL_##dr##_BUSY))	\
+			break;						\
+	if (!i)	{							\
+		pr_err("%s: divider writing timeout\n", __func__);	\
+		return -ETIMEDOUT;					\
+	}								\
+									\
+	return 0;							\
+}
+
+_CLK_SET_RATE(xbus_clk, XBUS)
+_CLK_SET_RATE(ssp_clk, SSP)
+_CLK_SET_RATE(gpmi_clk, GPMI)
+_CLK_SET_RATE(lcdif_clk, PIX)
+
+#define _CLK_SET_RATE_STUB(name)					\
+static int name##_set_rate(struct clk *clk, unsigned long rate)		\
+{									\
+	return -EINVAL;							\
+}
+
+_CLK_SET_RATE_STUB(emi_clk)
+_CLK_SET_RATE_STUB(uart_clk)
+_CLK_SET_RATE_STUB(audio_clk)
+_CLK_SET_RATE_STUB(pwm_clk)
+_CLK_SET_RATE_STUB(clk32k_clk)
+
+/*
+ * clk_set_parent
+ */
+#define _CLK_SET_PARENT(name, bit)					\
+static int name##_set_parent(struct clk *clk, struct clk *parent)	\
+{									\
+	if (parent != clk->parent) {					\
+		__raw_writel(BM_CLKCTRL_CLKSEQ_BYPASS_##bit,		\
+			 CLKCTRL_BASE_ADDR + HW_CLKCTRL_CLKSEQ_TOG);	\
+		clk->parent = parent;					\
+	}								\
+									\
+	return 0;							\
+}
+
+_CLK_SET_PARENT(cpu_clk, CPU)
+_CLK_SET_PARENT(emi_clk, EMI)
+_CLK_SET_PARENT(ssp_clk, SSP)
+_CLK_SET_PARENT(gpmi_clk, GPMI)
+_CLK_SET_PARENT(lcdif_clk, PIX)
+
+#define _CLK_SET_PARENT_STUB(name)					\
+static int name##_set_parent(struct clk *clk, struct clk *parent)	\
+{									\
+	if (parent != clk->parent)					\
+		return -EINVAL;						\
+	else								\
+		return 0;						\
+}
+
+_CLK_SET_PARENT_STUB(uart_clk)
+_CLK_SET_PARENT_STUB(audio_clk)
+_CLK_SET_PARENT_STUB(pwm_clk)
+_CLK_SET_PARENT_STUB(clk32k_clk)
+
+/*
+ * clk definition
+ */
+static struct clk cpu_clk = {
+	.get_rate = cpu_clk_get_rate,
+	.set_rate = cpu_clk_set_rate,
+	.set_parent = cpu_clk_set_parent,
+	.parent = &ref_cpu_clk,
+};
+
+static struct clk hbus_clk = {
+	.get_rate = hbus_clk_get_rate,
+	.parent = &cpu_clk,
+};
+
+static struct clk xbus_clk = {
+	.get_rate = xbus_clk_get_rate,
+	.set_rate = xbus_clk_set_rate,
+	.parent = &ref_xtal_clk,
+};
+
+static struct clk rtc_clk = {
+	.get_rate = rtc_clk_get_rate,
+	.parent = &ref_xtal_clk,
+};
+
+/* usb_clk gate is controlled in DIGCTRL other than CLKCTRL */
+static struct clk usb_clk = {
+	.enable_reg = DIGCTRL_BASE_ADDR,
+	.enable_shift = 2,
+	.enable = _raw_clk_enable,
+	.disable = _raw_clk_disable,
+	.parent = &pll_clk,
+};
+
+#define _DEFINE_CLOCK(name, er, es, p)					\
+	static struct clk name = {					\
+		.enable_reg	= CLKCTRL_BASE_ADDR + HW_CLKCTRL_##er,	\
+		.enable_shift	= BP_CLKCTRL_##er##_##es,		\
+		.get_rate	= name##_get_rate,			\
+		.set_rate	= name##_set_rate,			\
+		.set_parent	= name##_set_parent,			\
+		.enable		= _raw_clk_enable,			\
+		.disable	= _raw_clk_disable,			\
+		.parent		= p,					\
+	}
+
+_DEFINE_CLOCK(emi_clk, EMI, CLKGATE, &ref_xtal_clk);
+_DEFINE_CLOCK(ssp_clk, SSP, CLKGATE, &ref_xtal_clk);
+_DEFINE_CLOCK(gpmi_clk, GPMI, CLKGATE, &ref_xtal_clk);
+_DEFINE_CLOCK(lcdif_clk, PIX, CLKGATE, &ref_xtal_clk);
+_DEFINE_CLOCK(uart_clk, XTAL, UART_CLK_GATE, &ref_xtal_clk);
+_DEFINE_CLOCK(audio_clk, XTAL, FILT_CLK24M_GATE, &ref_xtal_clk);
+_DEFINE_CLOCK(pwm_clk, XTAL, PWM_CLK24M_GATE, &ref_xtal_clk);
+_DEFINE_CLOCK(clk32k_clk, XTAL, TIMROT_CLK32K_GATE, &ref_xtal_clk);
+
+#define _REGISTER_CLOCK(d, n, c) \
+	{ \
+		.dev_id = d, \
+		.con_id = n, \
+		.clk = &c, \
+	},
+
+static struct clk_lookup lookups[] = {
+	/* for amba bus driver */
+	_REGISTER_CLOCK("duart", "apb_pclk", xbus_clk)
+	/* for amba-pl011 driver */
+	_REGISTER_CLOCK("duart", NULL, uart_clk)
+	_REGISTER_CLOCK("rtc", NULL, rtc_clk)
+	_REGISTER_CLOCK(NULL, "hclk", hbus_clk)
+	_REGISTER_CLOCK(NULL, "usb", usb_clk)
+	_REGISTER_CLOCK(NULL, "audio", audio_clk)
+	_REGISTER_CLOCK(NULL, "pwm", pwm_clk)
+};
+
+static int clk_misc_init(void)
+{
+	u32 reg;
+	int i;
+
+	/* Fix up parent per register setting */
+	reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_CLKSEQ);
+	cpu_clk.parent = (reg & BM_CLKCTRL_CLKSEQ_BYPASS_CPU) ?
+			&ref_xtal_clk : &ref_cpu_clk;
+	emi_clk.parent = (reg & BM_CLKCTRL_CLKSEQ_BYPASS_EMI) ?
+			&ref_xtal_clk : &ref_emi_clk;
+	ssp_clk.parent = (reg & BM_CLKCTRL_CLKSEQ_BYPASS_SSP) ?
+			&ref_xtal_clk : &ref_io_clk;
+	gpmi_clk.parent = (reg & BM_CLKCTRL_CLKSEQ_BYPASS_GPMI) ?
+			&ref_xtal_clk : &ref_io_clk;
+	lcdif_clk.parent = (reg & BM_CLKCTRL_CLKSEQ_BYPASS_PIX) ?
+			&ref_xtal_clk : &ref_pix_clk;
+
+	/* Use int div over frac when both are available */
+	__raw_writel(BM_CLKCTRL_CPU_DIV_XTAL_FRAC_EN,
+			CLKCTRL_BASE_ADDR + HW_CLKCTRL_CPU_CLR);
+	__raw_writel(BM_CLKCTRL_CPU_DIV_CPU_FRAC_EN,
+			CLKCTRL_BASE_ADDR + HW_CLKCTRL_CPU_CLR);
+	__raw_writel(BM_CLKCTRL_HBUS_DIV_FRAC_EN,
+			CLKCTRL_BASE_ADDR + HW_CLKCTRL_HBUS_CLR);
+
+	reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_XBUS);
+	reg &= ~BM_CLKCTRL_XBUS_DIV_FRAC_EN;
+	__raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_XBUS);
+
+	reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_SSP);
+	reg &= ~BM_CLKCTRL_SSP_DIV_FRAC_EN;
+	__raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_SSP);
+
+	reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_GPMI);
+	reg &= ~BM_CLKCTRL_GPMI_DIV_FRAC_EN;
+	__raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_GPMI);
+
+	reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_PIX);
+	reg &= ~BM_CLKCTRL_PIX_DIV_FRAC_EN;
+	__raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_PIX);
+
+	/*
+	 * Set safe hbus clock divider. A divider of 3 ensure that
+	 * the Vddd voltage required for the cpu clock is sufficiently
+	 * high for the hbus clock.
+	 */
+	reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_HBUS);
+	reg &= BM_CLKCTRL_HBUS_DIV;
+	reg |= 3 << BP_CLKCTRL_HBUS_DIV;
+	__raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_HBUS);
+
+	for (i = 10000; i; i--)
+		if (!(__raw_readl(CLKCTRL_BASE_ADDR +
+			HW_CLKCTRL_HBUS) & BM_CLKCTRL_HBUS_BUSY))
+			break;
+	if (!i) {
+		pr_err("%s: divider writing timeout\n", __func__);
+		return -ETIMEDOUT;
+	}
+
+	/* Gate off cpu clock in WFI for power saving */
+	__raw_writel(BM_CLKCTRL_CPU_INTERRUPT_WAIT,
+			CLKCTRL_BASE_ADDR + HW_CLKCTRL_CPU_SET);
+
+	return 0;
+}
+
+int __init mx23_clocks_init(void)
+{
+	clk_misc_init();
+
+	clk_enable(&cpu_clk);
+	clk_enable(&hbus_clk);
+	clk_enable(&xbus_clk);
+	clk_enable(&emi_clk);
+	clk_enable(&uart_clk);
+
+	clkdev_add_table(lookups, ARRAY_SIZE(lookups));
+
+	mxs_timer_init(&clk32k_clk, MX23_INT_TIMER0);
+
+	return 0;
+}
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mxs/clock-mx28.c linux-libre-2.6.38-gnu1/arch/arm/mach-mxs/clock-mx28.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mxs/clock-mx28.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mxs/clock-mx28.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,745 @@
+/*
+ * 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.
+ */
+
+#include <linux/mm.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/jiffies.h>
+#include <linux/clkdev.h>
+
+#include <asm/clkdev.h>
+#include <asm/div64.h>
+
+#include <mach/mx28.h>
+#include <mach/common.h>
+#include <mach/clock.h>
+
+#include "regs-clkctrl-mx28.h"
+
+#define CLKCTRL_BASE_ADDR	MX28_IO_ADDRESS(MX28_CLKCTRL_BASE_ADDR)
+#define DIGCTRL_BASE_ADDR	MX28_IO_ADDRESS(MX28_DIGCTL_BASE_ADDR)
+
+#define PARENT_RATE_SHIFT	8
+
+static struct clk pll2_clk;
+static struct clk cpu_clk;
+static struct clk emi_clk;
+static struct clk saif0_clk;
+static struct clk saif1_clk;
+static struct clk clk32k_clk;
+
+static int _raw_clk_enable(struct clk *clk)
+{
+	u32 reg;
+
+	if (clk->enable_reg) {
+		reg = __raw_readl(clk->enable_reg);
+		reg &= ~(1 << clk->enable_shift);
+		__raw_writel(reg, clk->enable_reg);
+	}
+
+	return 0;
+}
+
+static void _raw_clk_disable(struct clk *clk)
+{
+	u32 reg;
+
+	if (clk->enable_reg) {
+		reg = __raw_readl(clk->enable_reg);
+		reg |= 1 << clk->enable_shift;
+		__raw_writel(reg, clk->enable_reg);
+	}
+}
+
+/*
+ * ref_xtal_clk
+ */
+static unsigned long ref_xtal_clk_get_rate(struct clk *clk)
+{
+	return 24000000;
+}
+
+static struct clk ref_xtal_clk = {
+	.get_rate = ref_xtal_clk_get_rate,
+};
+
+/*
+ * pll_clk
+ */
+static unsigned long pll0_clk_get_rate(struct clk *clk)
+{
+	return 480000000;
+}
+
+static unsigned long pll1_clk_get_rate(struct clk *clk)
+{
+	return 480000000;
+}
+
+static unsigned long pll2_clk_get_rate(struct clk *clk)
+{
+	return 50000000;
+}
+
+#define _CLK_ENABLE_PLL(name, r, g)					\
+static int name##_enable(struct clk *clk)				\
+{									\
+	__raw_writel(BM_CLKCTRL_##r##CTRL0_POWER,			\
+		     CLKCTRL_BASE_ADDR + HW_CLKCTRL_##r##CTRL0_SET);	\
+	udelay(10);							\
+									\
+	if (clk == &pll2_clk)						\
+		__raw_writel(BM_CLKCTRL_##r##CTRL0_##g,			\
+			CLKCTRL_BASE_ADDR + HW_CLKCTRL_##r##CTRL0_CLR);	\
+	else								\
+		__raw_writel(BM_CLKCTRL_##r##CTRL0_##g,			\
+			CLKCTRL_BASE_ADDR + HW_CLKCTRL_##r##CTRL0_SET);	\
+									\
+	return 0;							\
+}
+
+_CLK_ENABLE_PLL(pll0_clk, PLL0, EN_USB_CLKS)
+_CLK_ENABLE_PLL(pll1_clk, PLL1, EN_USB_CLKS)
+_CLK_ENABLE_PLL(pll2_clk, PLL2, CLKGATE)
+
+#define _CLK_DISABLE_PLL(name, r, g)					\
+static void name##_disable(struct clk *clk)				\
+{									\
+	__raw_writel(BM_CLKCTRL_##r##CTRL0_POWER,			\
+		     CLKCTRL_BASE_ADDR + HW_CLKCTRL_##r##CTRL0_CLR);	\
+									\
+	if (clk == &pll2_clk)						\
+		__raw_writel(BM_CLKCTRL_##r##CTRL0_##g,			\
+			CLKCTRL_BASE_ADDR + HW_CLKCTRL_##r##CTRL0_SET);	\
+	else								\
+		__raw_writel(BM_CLKCTRL_##r##CTRL0_##g,			\
+			CLKCTRL_BASE_ADDR + HW_CLKCTRL_##r##CTRL0_CLR);	\
+									\
+}
+
+_CLK_DISABLE_PLL(pll0_clk, PLL0, EN_USB_CLKS)
+_CLK_DISABLE_PLL(pll1_clk, PLL1, EN_USB_CLKS)
+_CLK_DISABLE_PLL(pll2_clk, PLL2, CLKGATE)
+
+#define _DEFINE_CLOCK_PLL(name)						\
+	static struct clk name = {					\
+		.get_rate	= name##_get_rate,			\
+		.enable		= name##_enable,			\
+		.disable	= name##_disable,			\
+		.parent		= &ref_xtal_clk,			\
+	}
+
+_DEFINE_CLOCK_PLL(pll0_clk);
+_DEFINE_CLOCK_PLL(pll1_clk);
+_DEFINE_CLOCK_PLL(pll2_clk);
+
+/*
+ * ref_clk
+ */
+#define _CLK_GET_RATE_REF(name, sr, ss)					\
+static unsigned long name##_get_rate(struct clk *clk)			\
+{									\
+	unsigned long parent_rate;					\
+	u32 reg, div;							\
+									\
+	reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_##sr);		\
+	div = (reg >> BP_CLKCTRL_##sr##_##ss##FRAC) & 0x3f;		\
+	parent_rate = clk_get_rate(clk->parent);			\
+									\
+	return SH_DIV((parent_rate >> PARENT_RATE_SHIFT) * 18,		\
+			div, PARENT_RATE_SHIFT);			\
+}
+
+_CLK_GET_RATE_REF(ref_cpu_clk, FRAC0, CPU)
+_CLK_GET_RATE_REF(ref_emi_clk, FRAC0, EMI)
+_CLK_GET_RATE_REF(ref_io0_clk, FRAC0, IO0)
+_CLK_GET_RATE_REF(ref_io1_clk, FRAC0, IO1)
+_CLK_GET_RATE_REF(ref_pix_clk, FRAC1, PIX)
+_CLK_GET_RATE_REF(ref_gpmi_clk, FRAC1, GPMI)
+
+#define _DEFINE_CLOCK_REF(name, er, es)					\
+	static struct clk name = {					\
+		.enable_reg	= CLKCTRL_BASE_ADDR + HW_CLKCTRL_##er,	\
+		.enable_shift	= BP_CLKCTRL_##er##_CLKGATE##es,	\
+		.get_rate	= name##_get_rate,			\
+		.enable		= _raw_clk_enable,			\
+		.disable	= _raw_clk_disable,			\
+		.parent		= &pll0_clk,				\
+	}
+
+_DEFINE_CLOCK_REF(ref_cpu_clk, FRAC0, CPU);
+_DEFINE_CLOCK_REF(ref_emi_clk, FRAC0, EMI);
+_DEFINE_CLOCK_REF(ref_io0_clk, FRAC0, IO0);
+_DEFINE_CLOCK_REF(ref_io1_clk, FRAC0, IO1);
+_DEFINE_CLOCK_REF(ref_pix_clk, FRAC1, PIX);
+_DEFINE_CLOCK_REF(ref_gpmi_clk, FRAC1, GPMI);
+
+/*
+ * General clocks
+ *
+ * clk_get_rate
+ */
+static unsigned long lradc_clk_get_rate(struct clk *clk)
+{
+	return clk_get_rate(clk->parent) / 16;
+}
+
+static unsigned long rtc_clk_get_rate(struct clk *clk)
+{
+	/* ref_xtal_clk is implemented as the only parent */
+	return clk_get_rate(clk->parent) / 768;
+}
+
+static unsigned long clk32k_clk_get_rate(struct clk *clk)
+{
+	return clk->parent->get_rate(clk->parent) / 750;
+}
+
+static unsigned long spdif_clk_get_rate(struct clk *clk)
+{
+	return clk_get_rate(clk->parent) / 4;
+}
+
+#define _CLK_GET_RATE(name, rs)						\
+static unsigned long name##_get_rate(struct clk *clk)			\
+{									\
+	u32 reg, div;							\
+									\
+	reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_##rs);		\
+									\
+	if (clk->parent == &ref_xtal_clk)				\
+		div = (reg & BM_CLKCTRL_##rs##_DIV_XTAL) >>		\
+			BP_CLKCTRL_##rs##_DIV_XTAL;			\
+	else								\
+		div = (reg & BM_CLKCTRL_##rs##_DIV_##rs) >>		\
+			BP_CLKCTRL_##rs##_DIV_##rs;			\
+									\
+	if (!div)							\
+		return -EINVAL;						\
+									\
+	return clk_get_rate(clk->parent) / div;				\
+}
+
+_CLK_GET_RATE(cpu_clk, CPU)
+_CLK_GET_RATE(emi_clk, EMI)
+
+#define _CLK_GET_RATE1(name, rs)					\
+static unsigned long name##_get_rate(struct clk *clk)			\
+{									\
+	u32 reg, div;							\
+									\
+	reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_##rs);		\
+	div = (reg & BM_CLKCTRL_##rs##_DIV) >> BP_CLKCTRL_##rs##_DIV;	\
+									\
+	if (!div)							\
+		return -EINVAL;						\
+									\
+	if (clk == &saif0_clk || clk == &saif1_clk)			\
+		return clk_get_rate(clk->parent) >> 16 * div;		\
+	else								\
+		return clk_get_rate(clk->parent) / div;			\
+}
+
+_CLK_GET_RATE1(hbus_clk, HBUS)
+_CLK_GET_RATE1(xbus_clk, XBUS)
+_CLK_GET_RATE1(ssp0_clk, SSP0)
+_CLK_GET_RATE1(ssp1_clk, SSP1)
+_CLK_GET_RATE1(ssp2_clk, SSP2)
+_CLK_GET_RATE1(ssp3_clk, SSP3)
+_CLK_GET_RATE1(gpmi_clk, GPMI)
+_CLK_GET_RATE1(lcdif_clk, DIS_LCDIF)
+_CLK_GET_RATE1(saif0_clk, SAIF0)
+_CLK_GET_RATE1(saif1_clk, SAIF1)
+
+#define _CLK_GET_RATE_STUB(name)					\
+static unsigned long name##_get_rate(struct clk *clk)			\
+{									\
+	return clk_get_rate(clk->parent);				\
+}
+
+_CLK_GET_RATE_STUB(uart_clk)
+_CLK_GET_RATE_STUB(pwm_clk)
+_CLK_GET_RATE_STUB(can0_clk)
+_CLK_GET_RATE_STUB(can1_clk)
+_CLK_GET_RATE_STUB(fec_clk)
+
+/*
+ * clk_set_rate
+ */
+/* fool compiler */
+#define BM_CLKCTRL_CPU_DIV	0
+#define BP_CLKCTRL_CPU_DIV	0
+#define BM_CLKCTRL_CPU_BUSY	0
+
+#define _CLK_SET_RATE(name, dr, fr, fs)					\
+static int name##_set_rate(struct clk *clk, unsigned long rate)		\
+{									\
+	u32 reg, bm_busy, div_max, d, f, div, frac;			\
+	unsigned long diff, parent_rate, calc_rate;			\
+	int i;								\
+									\
+	parent_rate = clk_get_rate(clk->parent);			\
+	div_max = BM_CLKCTRL_##dr##_DIV >> BP_CLKCTRL_##dr##_DIV;	\
+	bm_busy = BM_CLKCTRL_##dr##_BUSY;				\
+									\
+	if (clk->parent == &ref_xtal_clk) {				\
+		div = DIV_ROUND_UP(parent_rate, rate);			\
+		if (clk == &cpu_clk) {					\
+			div_max = BM_CLKCTRL_CPU_DIV_XTAL >>		\
+				BP_CLKCTRL_CPU_DIV_XTAL;		\
+			bm_busy = BM_CLKCTRL_CPU_BUSY_REF_XTAL;		\
+		}							\
+		if (div == 0 || div > div_max)				\
+			return -EINVAL;					\
+	} else {							\
+		rate >>= PARENT_RATE_SHIFT;				\
+		parent_rate >>= PARENT_RATE_SHIFT;			\
+		diff = parent_rate;					\
+		div = frac = 1;						\
+		if (clk == &cpu_clk) {					\
+			div_max = BM_CLKCTRL_CPU_DIV_CPU >>		\
+				BP_CLKCTRL_CPU_DIV_CPU;			\
+			bm_busy = BM_CLKCTRL_CPU_BUSY_REF_CPU;		\
+		}							\
+		for (d = 1; d <= div_max; d++) {			\
+			f = parent_rate * 18 / d / rate;		\
+			if ((parent_rate * 18 / d) % rate)		\
+				f++;					\
+			if (f < 18 || f > 35)				\
+				continue;				\
+									\
+			calc_rate = parent_rate * 18 / f / d;		\
+			if (calc_rate > rate)				\
+				continue;				\
+									\
+			if (rate - calc_rate < diff) {			\
+				frac = f;				\
+				div = d;				\
+				diff = rate - calc_rate;		\
+			}						\
+									\
+			if (diff == 0)					\
+				break;					\
+		}							\
+									\
+		if (diff == parent_rate)				\
+			return -EINVAL;					\
+									\
+		reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_##fr);	\
+		reg &= ~BM_CLKCTRL_##fr##_##fs##FRAC;			\
+		reg |= frac;						\
+		__raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_##fr);	\
+	}								\
+									\
+	reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_##dr);		\
+	if (clk == &cpu_clk) {						\
+		reg &= ~BM_CLKCTRL_CPU_DIV_CPU;				\
+		reg |= div << BP_CLKCTRL_CPU_DIV_CPU;			\
+	} else {							\
+		reg &= ~BM_CLKCTRL_##dr##_DIV;				\
+		reg |= div << BP_CLKCTRL_##dr##_DIV;			\
+		if (reg & (1 << clk->enable_shift)) {			\
+			pr_err("%s: clock is gated\n", __func__);	\
+			return -EINVAL;					\
+		}							\
+	}								\
+	__raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_##dr);		\
+									\
+	for (i = 10000; i; i--)						\
+		if (!(__raw_readl(CLKCTRL_BASE_ADDR +			\
+			HW_CLKCTRL_##dr) & bm_busy))			\
+			break;						\
+	if (!i)	{							\
+		pr_err("%s: divider writing timeout\n", __func__);	\
+		return -ETIMEDOUT;					\
+	}								\
+									\
+	return 0;							\
+}
+
+_CLK_SET_RATE(cpu_clk, CPU, FRAC0, CPU)
+_CLK_SET_RATE(ssp0_clk, SSP0, FRAC0, IO0)
+_CLK_SET_RATE(ssp1_clk, SSP1, FRAC0, IO0)
+_CLK_SET_RATE(ssp2_clk, SSP2, FRAC0, IO1)
+_CLK_SET_RATE(ssp3_clk, SSP3, FRAC0, IO1)
+_CLK_SET_RATE(lcdif_clk, DIS_LCDIF, FRAC1, PIX)
+_CLK_SET_RATE(gpmi_clk, GPMI, FRAC1, GPMI)
+
+#define _CLK_SET_RATE1(name, dr)					\
+static int name##_set_rate(struct clk *clk, unsigned long rate)		\
+{									\
+	u32 reg, div_max, div;						\
+	unsigned long parent_rate;					\
+	int i;								\
+									\
+	parent_rate = clk_get_rate(clk->parent);			\
+	div_max = BM_CLKCTRL_##dr##_DIV >> BP_CLKCTRL_##dr##_DIV;	\
+									\
+	div = DIV_ROUND_UP(parent_rate, rate);				\
+	if (div == 0 || div > div_max)					\
+		return -EINVAL;						\
+									\
+	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)) {				\
+		pr_err("%s: clock is gated\n", __func__);		\
+		return -EINVAL;						\
+	}								\
+	__raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_##dr);		\
+									\
+	for (i = 10000; i; i--)						\
+		if (!(__raw_readl(CLKCTRL_BASE_ADDR +			\
+			HW_CLKCTRL_##dr) & BM_CLKCTRL_##dr##_BUSY))	\
+			break;						\
+	if (!i)	{							\
+		pr_err("%s: divider writing timeout\n", __func__);	\
+		return -ETIMEDOUT;					\
+	}								\
+									\
+	return 0;							\
+}
+
+_CLK_SET_RATE1(xbus_clk, XBUS)
+
+/* saif clock uses 16 bits frac div */
+#define _CLK_SET_RATE_SAIF(name, rs)					\
+static int name##_set_rate(struct clk *clk, unsigned long rate)		\
+{									\
+	u16 div;							\
+	u32 reg;							\
+	u64 lrate;							\
+	unsigned long parent_rate;					\
+	int i;								\
+									\
+	parent_rate = clk_get_rate(clk->parent);			\
+	if (rate > parent_rate)						\
+		return -EINVAL;						\
+									\
+	lrate = (u64)rate << 16;					\
+	do_div(lrate, parent_rate);					\
+	div = (u16)lrate;						\
+									\
+	if (!div)							\
+		return -EINVAL;						\
+									\
+	reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_##rs);		\
+	reg &= ~BM_CLKCTRL_##rs##_DIV;					\
+	reg |= div << BP_CLKCTRL_##rs##_DIV;				\
+	__raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_##rs);		\
+									\
+	for (i = 10000; i; i--)						\
+		if (!(__raw_readl(CLKCTRL_BASE_ADDR +			\
+			HW_CLKCTRL_##rs) & BM_CLKCTRL_##rs##_BUSY))	\
+			break;						\
+	if (!i) {							\
+		pr_err("%s: divider writing timeout\n", __func__);	\
+		return -ETIMEDOUT;					\
+	}								\
+									\
+	return 0;							\
+}
+
+_CLK_SET_RATE_SAIF(saif0_clk, SAIF0)
+_CLK_SET_RATE_SAIF(saif1_clk, SAIF1)
+
+#define _CLK_SET_RATE_STUB(name)					\
+static int name##_set_rate(struct clk *clk, unsigned long rate)		\
+{									\
+	return -EINVAL;							\
+}
+
+_CLK_SET_RATE_STUB(emi_clk)
+_CLK_SET_RATE_STUB(uart_clk)
+_CLK_SET_RATE_STUB(pwm_clk)
+_CLK_SET_RATE_STUB(spdif_clk)
+_CLK_SET_RATE_STUB(clk32k_clk)
+_CLK_SET_RATE_STUB(can0_clk)
+_CLK_SET_RATE_STUB(can1_clk)
+_CLK_SET_RATE_STUB(fec_clk)
+
+/*
+ * clk_set_parent
+ */
+#define _CLK_SET_PARENT(name, bit)					\
+static int name##_set_parent(struct clk *clk, struct clk *parent)	\
+{									\
+	if (parent != clk->parent) {					\
+		__raw_writel(BM_CLKCTRL_CLKSEQ_BYPASS_##bit,		\
+			 CLKCTRL_BASE_ADDR + HW_CLKCTRL_CLKSEQ_TOG);	\
+		clk->parent = parent;					\
+	}								\
+									\
+	return 0;							\
+}
+
+_CLK_SET_PARENT(cpu_clk, CPU)
+_CLK_SET_PARENT(emi_clk, EMI)
+_CLK_SET_PARENT(ssp0_clk, SSP0)
+_CLK_SET_PARENT(ssp1_clk, SSP1)
+_CLK_SET_PARENT(ssp2_clk, SSP2)
+_CLK_SET_PARENT(ssp3_clk, SSP3)
+_CLK_SET_PARENT(lcdif_clk, DIS_LCDIF)
+_CLK_SET_PARENT(gpmi_clk, GPMI)
+_CLK_SET_PARENT(saif0_clk, SAIF0)
+_CLK_SET_PARENT(saif1_clk, SAIF1)
+
+#define _CLK_SET_PARENT_STUB(name)					\
+static int name##_set_parent(struct clk *clk, struct clk *parent)	\
+{									\
+	if (parent != clk->parent)					\
+		return -EINVAL;						\
+	else								\
+		return 0;						\
+}
+
+_CLK_SET_PARENT_STUB(pwm_clk)
+_CLK_SET_PARENT_STUB(uart_clk)
+_CLK_SET_PARENT_STUB(clk32k_clk)
+_CLK_SET_PARENT_STUB(spdif_clk)
+_CLK_SET_PARENT_STUB(fec_clk)
+_CLK_SET_PARENT_STUB(can0_clk)
+_CLK_SET_PARENT_STUB(can1_clk)
+
+/*
+ * clk definition
+ */
+static struct clk cpu_clk = {
+	.get_rate = cpu_clk_get_rate,
+	.set_rate = cpu_clk_set_rate,
+	.set_parent = cpu_clk_set_parent,
+	.parent = &ref_cpu_clk,
+};
+
+static struct clk hbus_clk = {
+	.get_rate = hbus_clk_get_rate,
+	.parent = &cpu_clk,
+};
+
+static struct clk xbus_clk = {
+	.get_rate = xbus_clk_get_rate,
+	.set_rate = xbus_clk_set_rate,
+	.parent = &ref_xtal_clk,
+};
+
+static struct clk lradc_clk = {
+	.get_rate = lradc_clk_get_rate,
+	.parent = &clk32k_clk,
+};
+
+static struct clk rtc_clk = {
+	.get_rate = rtc_clk_get_rate,
+	.parent = &ref_xtal_clk,
+};
+
+/* usb_clk gate is controlled in DIGCTRL other than CLKCTRL */
+static struct clk usb0_clk = {
+	.enable_reg = DIGCTRL_BASE_ADDR,
+	.enable_shift = 2,
+	.enable = _raw_clk_enable,
+	.disable = _raw_clk_disable,
+	.parent = &pll0_clk,
+};
+
+static struct clk usb1_clk = {
+	.enable_reg = DIGCTRL_BASE_ADDR,
+	.enable_shift = 16,
+	.enable = _raw_clk_enable,
+	.disable = _raw_clk_disable,
+	.parent = &pll1_clk,
+};
+
+#define _DEFINE_CLOCK(name, er, es, p)					\
+	static struct clk name = {					\
+		.enable_reg	= CLKCTRL_BASE_ADDR + HW_CLKCTRL_##er,	\
+		.enable_shift	= BP_CLKCTRL_##er##_##es,		\
+		.get_rate	= name##_get_rate,			\
+		.set_rate	= name##_set_rate,			\
+		.set_parent	= name##_set_parent,			\
+		.enable		= _raw_clk_enable,			\
+		.disable	= _raw_clk_disable,			\
+		.parent		= p,					\
+	}
+
+_DEFINE_CLOCK(emi_clk, EMI, CLKGATE, &ref_xtal_clk);
+_DEFINE_CLOCK(ssp0_clk, SSP0, CLKGATE, &ref_xtal_clk);
+_DEFINE_CLOCK(ssp1_clk, SSP1, CLKGATE, &ref_xtal_clk);
+_DEFINE_CLOCK(ssp2_clk, SSP2, CLKGATE, &ref_xtal_clk);
+_DEFINE_CLOCK(ssp3_clk, SSP3, CLKGATE, &ref_xtal_clk);
+_DEFINE_CLOCK(lcdif_clk, DIS_LCDIF, CLKGATE, &ref_xtal_clk);
+_DEFINE_CLOCK(gpmi_clk, GPMI, CLKGATE, &ref_xtal_clk);
+_DEFINE_CLOCK(saif0_clk, SAIF0, CLKGATE, &ref_xtal_clk);
+_DEFINE_CLOCK(saif1_clk, SAIF1, CLKGATE, &ref_xtal_clk);
+_DEFINE_CLOCK(can0_clk, FLEXCAN, STOP_CAN0, &ref_xtal_clk);
+_DEFINE_CLOCK(can1_clk, FLEXCAN, STOP_CAN1, &ref_xtal_clk);
+_DEFINE_CLOCK(pwm_clk, XTAL, PWM_CLK24M_GATE, &ref_xtal_clk);
+_DEFINE_CLOCK(uart_clk, XTAL, UART_CLK_GATE, &ref_xtal_clk);
+_DEFINE_CLOCK(clk32k_clk, XTAL, TIMROT_CLK32K_GATE, &ref_xtal_clk);
+_DEFINE_CLOCK(spdif_clk, SPDIF, CLKGATE, &pll0_clk);
+_DEFINE_CLOCK(fec_clk, ENET, DISABLE, &hbus_clk);
+
+#define _REGISTER_CLOCK(d, n, c) \
+	{ \
+		.dev_id = d, \
+		.con_id = n, \
+		.clk = &c, \
+	},
+
+static struct clk_lookup lookups[] = {
+	/* for amba bus driver */
+	_REGISTER_CLOCK("duart", "apb_pclk", xbus_clk)
+	/* for amba-pl011 driver */
+	_REGISTER_CLOCK("duart", NULL, uart_clk)
+	_REGISTER_CLOCK("imx28-fec.0", NULL, fec_clk)
+	_REGISTER_CLOCK("imx28-fec.1", NULL, fec_clk)
+	_REGISTER_CLOCK("rtc", NULL, rtc_clk)
+	_REGISTER_CLOCK("pll2", NULL, pll2_clk)
+	_REGISTER_CLOCK(NULL, "hclk", hbus_clk)
+	_REGISTER_CLOCK(NULL, "xclk", xbus_clk)
+	_REGISTER_CLOCK(NULL, "can0", can0_clk)
+	_REGISTER_CLOCK(NULL, "can1", can1_clk)
+	_REGISTER_CLOCK(NULL, "usb0", usb0_clk)
+	_REGISTER_CLOCK(NULL, "usb1", usb1_clk)
+	_REGISTER_CLOCK(NULL, "pwm", pwm_clk)
+	_REGISTER_CLOCK(NULL, "lradc", lradc_clk)
+	_REGISTER_CLOCK(NULL, "spdif", spdif_clk)
+};
+
+static int clk_misc_init(void)
+{
+	u32 reg;
+	int i;
+
+	/* Fix up parent per register setting */
+	reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_CLKSEQ);
+	cpu_clk.parent = (reg & BM_CLKCTRL_CLKSEQ_BYPASS_CPU) ?
+			&ref_xtal_clk : &ref_cpu_clk;
+	emi_clk.parent = (reg & BM_CLKCTRL_CLKSEQ_BYPASS_EMI) ?
+			&ref_xtal_clk : &ref_emi_clk;
+	ssp0_clk.parent = (reg & BM_CLKCTRL_CLKSEQ_BYPASS_SSP0) ?
+			&ref_xtal_clk : &ref_io0_clk;
+	ssp1_clk.parent = (reg & BM_CLKCTRL_CLKSEQ_BYPASS_SSP1) ?
+			&ref_xtal_clk : &ref_io0_clk;
+	ssp2_clk.parent = (reg & BM_CLKCTRL_CLKSEQ_BYPASS_SSP2) ?
+			&ref_xtal_clk : &ref_io1_clk;
+	ssp3_clk.parent = (reg & BM_CLKCTRL_CLKSEQ_BYPASS_SSP3) ?
+			&ref_xtal_clk : &ref_io1_clk;
+	lcdif_clk.parent = (reg & BM_CLKCTRL_CLKSEQ_BYPASS_DIS_LCDIF) ?
+			&ref_xtal_clk : &ref_pix_clk;
+	gpmi_clk.parent = (reg & BM_CLKCTRL_CLKSEQ_BYPASS_GPMI) ?
+			&ref_xtal_clk : &ref_gpmi_clk;
+	saif0_clk.parent = (reg & BM_CLKCTRL_CLKSEQ_BYPASS_SAIF0) ?
+			&ref_xtal_clk : &pll0_clk;
+	saif1_clk.parent = (reg & BM_CLKCTRL_CLKSEQ_BYPASS_SAIF1) ?
+			&ref_xtal_clk : &pll0_clk;
+
+	/* Use int div over frac when both are available */
+	__raw_writel(BM_CLKCTRL_CPU_DIV_XTAL_FRAC_EN,
+			CLKCTRL_BASE_ADDR + HW_CLKCTRL_CPU_CLR);
+	__raw_writel(BM_CLKCTRL_CPU_DIV_CPU_FRAC_EN,
+			CLKCTRL_BASE_ADDR + HW_CLKCTRL_CPU_CLR);
+	__raw_writel(BM_CLKCTRL_HBUS_DIV_FRAC_EN,
+			CLKCTRL_BASE_ADDR + HW_CLKCTRL_HBUS_CLR);
+
+	reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_XBUS);
+	reg &= ~BM_CLKCTRL_XBUS_DIV_FRAC_EN;
+	__raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_XBUS);
+
+	reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_SSP0);
+	reg &= ~BM_CLKCTRL_SSP0_DIV_FRAC_EN;
+	__raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_SSP0);
+
+	reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_SSP1);
+	reg &= ~BM_CLKCTRL_SSP1_DIV_FRAC_EN;
+	__raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_SSP1);
+
+	reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_SSP2);
+	reg &= ~BM_CLKCTRL_SSP2_DIV_FRAC_EN;
+	__raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_SSP2);
+
+	reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_SSP3);
+	reg &= ~BM_CLKCTRL_SSP3_DIV_FRAC_EN;
+	__raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_SSP3);
+
+	reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_GPMI);
+	reg &= ~BM_CLKCTRL_GPMI_DIV_FRAC_EN;
+	__raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_GPMI);
+
+	reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_DIS_LCDIF);
+	reg &= ~BM_CLKCTRL_DIS_LCDIF_DIV_FRAC_EN;
+	__raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_DIS_LCDIF);
+
+	/* 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;
+	__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;
+	__raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_SAIF1);
+
+	/*
+	 * Set safe hbus clock divider. A divider of 3 ensure that
+	 * the Vddd voltage required for the cpu clock is sufficiently
+	 * high for the hbus clock.
+	 */
+	reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_HBUS);
+	reg &= BM_CLKCTRL_HBUS_DIV;
+	reg |= 3 << BP_CLKCTRL_HBUS_DIV;
+	__raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_HBUS);
+
+	for (i = 10000; i; i--)
+		if (!(__raw_readl(CLKCTRL_BASE_ADDR +
+			HW_CLKCTRL_HBUS) & BM_CLKCTRL_HBUS_ASM_BUSY))
+			break;
+	if (!i) {
+		pr_err("%s: divider writing timeout\n", __func__);
+		return -ETIMEDOUT;
+	}
+
+	/* Gate off cpu clock in WFI for power saving */
+	__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);
+
+	return 0;
+}
+
+int __init mx28_clocks_init(void)
+{
+	clk_misc_init();
+
+	clk_enable(&cpu_clk);
+	clk_enable(&hbus_clk);
+	clk_enable(&xbus_clk);
+	clk_enable(&emi_clk);
+	clk_enable(&uart_clk);
+
+	clkdev_add_table(lookups, ARRAY_SIZE(lookups));
+
+	mxs_timer_init(&clk32k_clk, MX28_INT_TIMER0);
+
+	return 0;
+}
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mxs/devices/amba-duart.c linux-libre-2.6.38-gnu1/arch/arm/mach-mxs/devices/amba-duart.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mxs/devices/amba-duart.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mxs/devices/amba-duart.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2009-2010 Pengutronix
+ * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
+ *
+ * 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 version 2 as published by the
+ * Free Software Foundation.
+ */
+#include <asm/irq.h>
+#include <mach/mx23.h>
+#include <mach/mx28.h>
+#include <mach/devices-common.h>
+
+#define MXS_AMBA_DUART_DEVICE(name, soc)			\
+const struct amba_device name##_device __initconst = {		\
+	.dev = {						\
+		.init_name = "duart",				\
+	},							\
+	.res = {						\
+		.start = soc ## _DUART_BASE_ADDR,		\
+		.end = (soc ## _DUART_BASE_ADDR) + SZ_8K - 1,	\
+		.flags = IORESOURCE_MEM,			\
+	},							\
+	.irq = {soc ## _INT_DUART, NO_IRQ},			\
+}
+
+#ifdef CONFIG_SOC_IMX23
+MXS_AMBA_DUART_DEVICE(mx23_duart, MX23);
+#endif
+
+#ifdef CONFIG_SOC_IMX28
+MXS_AMBA_DUART_DEVICE(mx28_duart, MX28);
+#endif
+
+int __init mxs_add_duart(const struct amba_device *dev)
+{
+	return mxs_add_amba_device(dev);
+}
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mxs/devices/Kconfig linux-libre-2.6.38-gnu1/arch/arm/mach-mxs/devices/Kconfig
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mxs/devices/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mxs/devices/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,6 @@
+config MXS_HAVE_AMBA_DUART
+	bool
+	select ARM_AMBA
+
+config MXS_HAVE_PLATFORM_FEC
+	bool
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mxs/devices/Makefile linux-libre-2.6.38-gnu1/arch/arm/mach-mxs/devices/Makefile
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mxs/devices/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mxs/devices/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,2 @@
+obj-$(CONFIG_MXS_HAVE_AMBA_DUART) += amba-duart.o
+obj-$(CONFIG_MXS_HAVE_PLATFORM_FEC) += platform-fec.o
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mxs/devices/platform-fec.c linux-libre-2.6.38-gnu1/arch/arm/mach-mxs/devices/platform-fec.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mxs/devices/platform-fec.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mxs/devices/platform-fec.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2010 Pengutronix
+ * Uwe Kleine-Koenig <u.kleine-koenig@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/mx28.h>
+#include <mach/devices-common.h>
+
+#define mxs_fec_data_entry_single(soc, _id)				\
+	{								\
+		.id = _id,						\
+		.iobase = soc ## _ENET_MAC ## _id ## _BASE_ADDR,	\
+		.irq = soc ## _INT_ENET_MAC ## _id,			\
+	}
+
+#define mxs_fec_data_entry(soc, _id)					\
+	[_id] = mxs_fec_data_entry_single(soc, _id)
+
+#ifdef CONFIG_SOC_IMX28
+const struct mxs_fec_data mx28_fec_data[] __initconst = {
+#define mx28_fec_data_entry(_id)					\
+	mxs_fec_data_entry(MX28, _id)
+	mx28_fec_data_entry(0),
+	mx28_fec_data_entry(1),
+};
+#endif
+
+struct platform_device *__init mxs_add_fec(
+		const struct mxs_fec_data *data,
+		const struct fec_platform_data *pdata)
+{
+	struct resource res[] = {
+		{
+			.start = data->iobase,
+			.end = data->iobase + SZ_16K - 1,
+			.flags = IORESOURCE_MEM,
+		}, {
+			.start = data->irq,
+			.end = data->irq,
+			.flags = IORESOURCE_IRQ,
+		},
+	};
+
+	return mxs_add_platform_device("imx28-fec", data->id,
+			res, ARRAY_SIZE(res), pdata, sizeof(*pdata));
+}
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mxs/devices.c linux-libre-2.6.38-gnu1/arch/arm/mach-mxs/devices.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mxs/devices.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mxs/devices.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2008 Sascha Hauer, 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/amba/bus.h>
+
+struct platform_device *__init mxs_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:
+		platform_device_put(pdev);
+		return ERR_PTR(ret);
+	}
+
+	return pdev;
+}
+
+int __init mxs_add_amba_device(const struct amba_device *dev)
+{
+	struct amba_device *adev = kmalloc(sizeof(*adev), GFP_KERNEL);
+
+	if (!adev) {
+		pr_err("%s: failed to allocate memory", __func__);
+		return -ENOMEM;
+	}
+
+	*adev = *dev;
+
+	return amba_device_register(adev, &iomem_resource);
+}
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mxs/devices-mx23.h linux-libre-2.6.38-gnu1/arch/arm/mach-mxs/devices-mx23.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mxs/devices-mx23.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mxs/devices-mx23.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) 2010 Pengutronix
+ * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
+ *
+ * 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 version 2 as published by the
+ * Free Software Foundation.
+ */
+#include <mach/mx23.h>
+#include <mach/devices-common.h>
+
+extern const struct amba_device mx23_duart_device __initconst;
+#define mx23_add_duart() \
+	mxs_add_duart(&mx23_duart_device)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mxs/devices-mx28.h linux-libre-2.6.38-gnu1/arch/arm/mach-mxs/devices-mx28.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mxs/devices-mx28.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mxs/devices-mx28.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2010 Pengutronix
+ * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
+ *
+ * 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 version 2 as published by the
+ * Free Software Foundation.
+ */
+#include <mach/mx28.h>
+#include <mach/devices-common.h>
+
+extern const struct amba_device mx28_duart_device __initconst;
+#define mx28_add_duart() \
+	mxs_add_duart(&mx28_duart_device)
+
+extern const struct mxs_fec_data mx28_fec_data[] __initconst;
+#define mx28_add_fec(id, pdata) \
+	mxs_add_fec(&mx28_fec_data[id], pdata)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mxs/gpio.c linux-libre-2.6.38-gnu1/arch/arm/mach-mxs/gpio.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mxs/gpio.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mxs/gpio.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,327 @@
+/*
+ * MXC GPIO support. (c) 2008 Daniel Mack <daniel@caiaq.de>
+ * Copyright 2008 Juergen Beisert, kernel@pengutronix.de
+ *
+ * Based on code from Freescale,
+ * Copyright (C) 2004-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.
+ */
+
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/gpio.h>
+#include <mach/mx23.h>
+#include <mach/mx28.h>
+#include <asm-generic/bug.h>
+
+#include "gpio.h"
+
+static struct mxs_gpio_port *mxs_gpio_ports;
+static int gpio_table_size;
+
+#define PINCTRL_DOUT(n)		((cpu_is_mx23() ? 0x0500 : 0x0700) + (n) * 0x10)
+#define PINCTRL_DIN(n)		((cpu_is_mx23() ? 0x0600 : 0x0900) + (n) * 0x10)
+#define PINCTRL_DOE(n)		((cpu_is_mx23() ? 0x0700 : 0x0b00) + (n) * 0x10)
+#define PINCTRL_PIN2IRQ(n)	((cpu_is_mx23() ? 0x0800 : 0x1000) + (n) * 0x10)
+#define PINCTRL_IRQEN(n)	((cpu_is_mx23() ? 0x0900 : 0x1100) + (n) * 0x10)
+#define PINCTRL_IRQLEV(n)	((cpu_is_mx23() ? 0x0a00 : 0x1200) + (n) * 0x10)
+#define PINCTRL_IRQPOL(n)	((cpu_is_mx23() ? 0x0b00 : 0x1300) + (n) * 0x10)
+#define PINCTRL_IRQSTAT(n)	((cpu_is_mx23() ? 0x0c00 : 0x1400) + (n) * 0x10)
+
+#define GPIO_INT_FALL_EDGE	0x0
+#define GPIO_INT_LOW_LEV	0x1
+#define GPIO_INT_RISE_EDGE	0x2
+#define GPIO_INT_HIGH_LEV	0x3
+#define GPIO_INT_LEV_MASK	(1 << 0)
+#define GPIO_INT_POL_MASK	(1 << 1)
+
+/* Note: This driver assumes 32 GPIOs are handled in one register */
+
+static void clear_gpio_irqstatus(struct mxs_gpio_port *port, u32 index)
+{
+	__mxs_clrl(1 << index, port->base + PINCTRL_IRQSTAT(port->id));
+}
+
+static void set_gpio_irqenable(struct mxs_gpio_port *port, u32 index,
+				int enable)
+{
+	if (enable) {
+		__mxs_setl(1 << index, port->base + PINCTRL_IRQEN(port->id));
+		__mxs_setl(1 << index, port->base + PINCTRL_PIN2IRQ(port->id));
+	} else {
+		__mxs_clrl(1 << index, port->base + PINCTRL_IRQEN(port->id));
+	}
+}
+
+static void mxs_gpio_ack_irq(u32 irq)
+{
+	u32 gpio = irq_to_gpio(irq);
+	clear_gpio_irqstatus(&mxs_gpio_ports[gpio / 32], gpio & 0x1f);
+}
+
+static void mxs_gpio_mask_irq(u32 irq)
+{
+	u32 gpio = irq_to_gpio(irq);
+	set_gpio_irqenable(&mxs_gpio_ports[gpio / 32], gpio & 0x1f, 0);
+}
+
+static void mxs_gpio_unmask_irq(u32 irq)
+{
+	u32 gpio = irq_to_gpio(irq);
+	set_gpio_irqenable(&mxs_gpio_ports[gpio / 32], gpio & 0x1f, 1);
+}
+
+static int mxs_gpio_get(struct gpio_chip *chip, unsigned offset);
+
+static int mxs_gpio_set_irq_type(u32 irq, u32 type)
+{
+	u32 gpio = irq_to_gpio(irq);
+	u32 pin_mask = 1 << (gpio & 31);
+	struct mxs_gpio_port *port = &mxs_gpio_ports[gpio / 32];
+	void __iomem *pin_addr;
+	int edge;
+
+	switch (type) {
+	case IRQ_TYPE_EDGE_RISING:
+		edge = GPIO_INT_RISE_EDGE;
+		break;
+	case IRQ_TYPE_EDGE_FALLING:
+		edge = GPIO_INT_FALL_EDGE;
+		break;
+	case IRQ_TYPE_LEVEL_LOW:
+		edge = GPIO_INT_LOW_LEV;
+		break;
+	case IRQ_TYPE_LEVEL_HIGH:
+		edge = GPIO_INT_HIGH_LEV;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/* set level or edge */
+	pin_addr = port->base + PINCTRL_IRQLEV(port->id);
+	if (edge & GPIO_INT_LEV_MASK)
+		__mxs_setl(pin_mask, pin_addr);
+	else
+		__mxs_clrl(pin_mask, pin_addr);
+
+	/* set polarity */
+	pin_addr = port->base + PINCTRL_IRQPOL(port->id);
+	if (edge & GPIO_INT_POL_MASK)
+		__mxs_setl(pin_mask, pin_addr);
+	else
+		__mxs_clrl(pin_mask, pin_addr);
+
+	clear_gpio_irqstatus(port, gpio & 0x1f);
+
+	return 0;
+}
+
+/* MXS has one interrupt *per* gpio port */
+static void mxs_gpio_irq_handler(u32 irq, struct irq_desc *desc)
+{
+	u32 irq_stat;
+	struct mxs_gpio_port *port = (struct mxs_gpio_port *)get_irq_data(irq);
+	u32 gpio_irq_no_base = port->virtual_irq_start;
+
+	desc->irq_data.chip->irq_ack(&desc->irq_data);
+
+	irq_stat = __raw_readl(port->base + PINCTRL_IRQSTAT(port->id)) &
+			__raw_readl(port->base + PINCTRL_IRQEN(port->id));
+
+	while (irq_stat != 0) {
+		int irqoffset = fls(irq_stat) - 1;
+		generic_handle_irq(gpio_irq_no_base + irqoffset);
+		irq_stat &= ~(1 << irqoffset);
+	}
+}
+
+/*
+ * Set interrupt number "irq" in the GPIO as a wake-up source.
+ * While system is running, all registered GPIO interrupts need to have
+ * wake-up enabled. When system is suspended, only selected GPIO interrupts
+ * need to have wake-up enabled.
+ * @param  irq          interrupt source number
+ * @param  enable       enable as wake-up if equal to non-zero
+ * @return       This function returns 0 on success.
+ */
+static int mxs_gpio_set_wake_irq(u32 irq, u32 enable)
+{
+	u32 gpio = irq_to_gpio(irq);
+	u32 gpio_idx = gpio & 0x1f;
+	struct mxs_gpio_port *port = &mxs_gpio_ports[gpio / 32];
+
+	if (enable) {
+		if (port->irq_high && (gpio_idx >= 16))
+			enable_irq_wake(port->irq_high);
+		else
+			enable_irq_wake(port->irq);
+	} else {
+		if (port->irq_high && (gpio_idx >= 16))
+			disable_irq_wake(port->irq_high);
+		else
+			disable_irq_wake(port->irq);
+	}
+
+	return 0;
+}
+
+static struct irq_chip gpio_irq_chip = {
+	.ack = mxs_gpio_ack_irq,
+	.mask = mxs_gpio_mask_irq,
+	.unmask = mxs_gpio_unmask_irq,
+	.set_type = mxs_gpio_set_irq_type,
+	.set_wake = mxs_gpio_set_wake_irq,
+};
+
+static void mxs_set_gpio_direction(struct gpio_chip *chip, unsigned offset,
+				int dir)
+{
+	struct mxs_gpio_port *port =
+		container_of(chip, struct mxs_gpio_port, chip);
+	void __iomem *pin_addr = port->base + PINCTRL_DOE(port->id);
+
+	if (dir)
+		__mxs_setl(1 << offset, pin_addr);
+	else
+		__mxs_clrl(1 << offset, pin_addr);
+}
+
+static int mxs_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+	struct mxs_gpio_port *port =
+		container_of(chip, struct mxs_gpio_port, chip);
+
+	return (__raw_readl(port->base + PINCTRL_DIN(port->id)) >> offset) & 1;
+}
+
+static void mxs_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+	struct mxs_gpio_port *port =
+		container_of(chip, struct mxs_gpio_port, chip);
+	void __iomem *pin_addr = port->base + PINCTRL_DOUT(port->id);
+
+	if (value)
+		__mxs_setl(1 << offset, pin_addr);
+	else
+		__mxs_clrl(1 << offset, pin_addr);
+}
+
+static int mxs_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+	struct mxs_gpio_port *port =
+		container_of(chip, struct mxs_gpio_port, chip);
+
+	return port->virtual_irq_start + offset;
+}
+
+static int mxs_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+	mxs_set_gpio_direction(chip, offset, 0);
+	return 0;
+}
+
+static int mxs_gpio_direction_output(struct gpio_chip *chip,
+				     unsigned offset, int value)
+{
+	mxs_gpio_set(chip, offset, value);
+	mxs_set_gpio_direction(chip, offset, 1);
+	return 0;
+}
+
+int __init mxs_gpio_init(struct mxs_gpio_port *port, int cnt)
+{
+	int i, j;
+
+	/* save for local usage */
+	mxs_gpio_ports = port;
+	gpio_table_size = cnt;
+
+	pr_info("MXS GPIO hardware\n");
+
+	for (i = 0; i < cnt; i++) {
+		/* disable the interrupt and clear the status */
+		__raw_writel(0, port[i].base + PINCTRL_PIN2IRQ(i));
+		__raw_writel(0, port[i].base + PINCTRL_IRQEN(i));
+
+		/* clear address has to be used to clear IRQSTAT bits */
+		__mxs_clrl(~0U, port[i].base + PINCTRL_IRQSTAT(i));
+
+		for (j = port[i].virtual_irq_start;
+			j < port[i].virtual_irq_start + 32; j++) {
+			set_irq_chip(j, &gpio_irq_chip);
+			set_irq_handler(j, handle_level_irq);
+			set_irq_flags(j, IRQF_VALID);
+		}
+
+		/* setup one handler for each entry */
+		set_irq_chained_handler(port[i].irq, mxs_gpio_irq_handler);
+		set_irq_data(port[i].irq, &port[i]);
+
+		/* register gpio chip */
+		port[i].chip.direction_input = mxs_gpio_direction_input;
+		port[i].chip.direction_output = mxs_gpio_direction_output;
+		port[i].chip.get = mxs_gpio_get;
+		port[i].chip.set = mxs_gpio_set;
+		port[i].chip.to_irq = mxs_gpio_to_irq;
+		port[i].chip.base = i * 32;
+		port[i].chip.ngpio = 32;
+
+		/* its a serious configuration bug when it fails */
+		BUG_ON(gpiochip_add(&port[i].chip) < 0);
+	}
+
+	return 0;
+}
+
+#define DEFINE_MXS_GPIO_PORT(soc, _id)					\
+	{								\
+		.chip.label = "gpio-" #_id,				\
+		.id = _id,						\
+		.irq = soc ## _INT_GPIO ## _id,				\
+		.base = soc ## _IO_ADDRESS(				\
+				soc ## _PINCTRL ## _BASE_ADDR),		\
+		.virtual_irq_start = MXS_GPIO_IRQ_START + (_id) * 32,	\
+	}
+
+#define DEFINE_REGISTER_FUNCTION(prefix)				\
+int __init prefix ## _register_gpios(void)				\
+{									\
+	return mxs_gpio_init(prefix ## _gpio_ports,			\
+			ARRAY_SIZE(prefix ## _gpio_ports));		\
+}
+
+#ifdef CONFIG_SOC_IMX23
+static struct mxs_gpio_port mx23_gpio_ports[] = {
+	DEFINE_MXS_GPIO_PORT(MX23, 0),
+	DEFINE_MXS_GPIO_PORT(MX23, 1),
+	DEFINE_MXS_GPIO_PORT(MX23, 2),
+};
+DEFINE_REGISTER_FUNCTION(mx23)
+#endif
+
+#ifdef CONFIG_SOC_IMX28
+static struct mxs_gpio_port mx28_gpio_ports[] = {
+	DEFINE_MXS_GPIO_PORT(MX28, 0),
+	DEFINE_MXS_GPIO_PORT(MX28, 1),
+	DEFINE_MXS_GPIO_PORT(MX28, 2),
+	DEFINE_MXS_GPIO_PORT(MX28, 3),
+	DEFINE_MXS_GPIO_PORT(MX28, 4),
+};
+DEFINE_REGISTER_FUNCTION(mx28)
+#endif
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mxs/gpio.h linux-libre-2.6.38-gnu1/arch/arm/mach-mxs/gpio.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mxs/gpio.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mxs/gpio.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,34 @@
+/*
+ * 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 __MXS_GPIO_H__
+#define __MXS_GPIO_H__
+
+struct mxs_gpio_port {
+	void __iomem *base;
+	int id;
+	int irq;
+	int irq_high;
+	int virtual_irq_start;
+	struct gpio_chip chip;
+};
+
+int mxs_gpio_init(struct mxs_gpio_port*, int);
+
+#endif /* __MXS_GPIO_H__ */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mxs/icoll.c linux-libre-2.6.38-gnu1/arch/arm/mach-mxs/icoll.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mxs/icoll.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mxs/icoll.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,81 @@
+/*
+ * 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+
+#include <mach/mxs.h>
+#include <mach/common.h>
+
+#define HW_ICOLL_VECTOR				0x0000
+#define HW_ICOLL_LEVELACK			0x0010
+#define HW_ICOLL_CTRL				0x0020
+#define HW_ICOLL_INTERRUPTn_SET(n)		(0x0124 + (n) * 0x10)
+#define HW_ICOLL_INTERRUPTn_CLR(n)		(0x0128 + (n) * 0x10)
+#define BM_ICOLL_INTERRUPTn_ENABLE		0x00000004
+#define BV_ICOLL_LEVELACK_IRQLEVELACK__LEVEL0	0x1
+
+static void __iomem *icoll_base = MXS_IO_ADDRESS(MXS_ICOLL_BASE_ADDR);
+
+static void icoll_ack_irq(unsigned int irq)
+{
+	/*
+	 * The Interrupt Collector is able to prioritize irqs.
+	 * Currently only level 0 is used. So acking can use
+	 * BV_ICOLL_LEVELACK_IRQLEVELACK__LEVEL0 unconditionally.
+	 */
+	__raw_writel(BV_ICOLL_LEVELACK_IRQLEVELACK__LEVEL0,
+			icoll_base + HW_ICOLL_LEVELACK);
+}
+
+static void icoll_mask_irq(unsigned int irq)
+{
+	__raw_writel(BM_ICOLL_INTERRUPTn_ENABLE,
+			icoll_base + HW_ICOLL_INTERRUPTn_CLR(irq));
+}
+
+static void icoll_unmask_irq(unsigned int irq)
+{
+	__raw_writel(BM_ICOLL_INTERRUPTn_ENABLE,
+			icoll_base + HW_ICOLL_INTERRUPTn_SET(irq));
+}
+
+static struct irq_chip mxs_icoll_chip = {
+	.ack = icoll_ack_irq,
+	.mask = icoll_mask_irq,
+	.unmask = icoll_unmask_irq,
+};
+
+void __init icoll_init_irq(void)
+{
+	int i;
+
+	/*
+	 * Interrupt Collector reset, which initializes the priority
+	 * for each irq to level 0.
+	 */
+	mxs_reset_block(icoll_base + HW_ICOLL_CTRL);
+
+	for (i = 0; i < MXS_INTERNAL_IRQS; i++) {
+		set_irq_chip(i, &mxs_icoll_chip);
+		set_irq_handler(i, handle_level_irq);
+		set_irq_flags(i, IRQF_VALID);
+	}
+}
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mxs/include/mach/clkdev.h linux-libre-2.6.38-gnu1/arch/arm/mach-mxs/include/mach/clkdev.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mxs/include/mach/clkdev.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mxs/include/mach/clkdev.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,7 @@
+#ifndef __MACH_MXS_CLKDEV_H__
+#define __MACH_MXS_CLKDEV_H__
+
+#define __clk_get(clk) ({ 1; })
+#define __clk_put(clk) do { } while (0)
+
+#endif
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mxs/include/mach/clock.h linux-libre-2.6.38-gnu1/arch/arm/mach-mxs/include/mach/clock.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mxs/include/mach/clock.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mxs/include/mach/clock.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2005-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_CLOCK_H__
+#define __MACH_MXS_CLOCK_H__
+
+#ifndef __ASSEMBLY__
+#include <linux/list.h>
+
+struct module;
+
+struct clk {
+	int id;
+	/* Source clock this clk depends on */
+	struct clk *parent;
+	/* Reference count of clock enable/disable */
+	__s8 usecount;
+	/* Register bit position for clock's enable/disable control. */
+	u8 enable_shift;
+	/* Register address for clock's enable/disable control. */
+	void __iomem *enable_reg;
+	u32 flags;
+	/* get the current clock rate (always a fresh value) */
+	unsigned long (*get_rate) (struct clk *);
+	/* Function ptr to set the clock to a new rate. The rate must match a
+	   supported rate returned from round_rate. Leave blank if clock is not
+	   programmable */
+	int (*set_rate) (struct clk *, unsigned long);
+	/* Function ptr to round the requested clock rate to the nearest
+	   supported rate that is less than or equal to the requested rate. */
+	unsigned long (*round_rate) (struct clk *, unsigned long);
+	/* Function ptr to enable the clock. Leave blank if clock can not
+	   be gated. */
+	int (*enable) (struct clk *);
+	/* Function ptr to disable the clock. Leave blank if clock can not
+	   be gated. */
+	void (*disable) (struct clk *);
+	/* Function ptr to set the parent clock of the clock. */
+	int (*set_parent) (struct clk *, struct clk *);
+};
+
+int clk_register(struct clk *clk);
+void clk_unregister(struct clk *clk);
+
+#endif /* __ASSEMBLY__ */
+#endif /* __MACH_MXS_CLOCK_H__ */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mxs/include/mach/common.h linux-libre-2.6.38-gnu1/arch/arm/mach-mxs/include/mach/common.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mxs/include/mach/common.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mxs/include/mach/common.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,31 @@
+/*
+ * 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 __MACH_MXS_COMMON_H__
+#define __MACH_MXS_COMMON_H__
+
+struct clk;
+
+extern int mxs_reset_block(void __iomem *);
+extern void mxs_timer_init(struct clk *, int);
+
+extern int mx23_register_gpios(void);
+extern int mx23_clocks_init(void);
+extern void mx23_map_io(void);
+extern void mx23_init_irq(void);
+
+extern int mx28_register_gpios(void);
+extern int mx28_clocks_init(void);
+extern void mx28_map_io(void);
+extern void mx28_init_irq(void);
+
+extern void icoll_init_irq(void);
+
+#endif /* __MACH_MXS_COMMON_H__ */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mxs/include/mach/debug-macro.S linux-libre-2.6.38-gnu1/arch/arm/mach-mxs/include/mach/debug-macro.S
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mxs/include/mach/debug-macro.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mxs/include/mach/debug-macro.S	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,38 @@
+/* arch/arm/mach-mxs/include/mach/debug-macro.S
+ *
+ * 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.
+ *
+ */
+
+#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
+#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
+#define UART_PADDR	MX28_DUART_BASE_ADDR
+#endif
+
+#define UART_VADDR	MXS_IO_ADDRESS(UART_PADDR)
+
+		.macro	addruart, rp, rv
+		ldr	\rp, =UART_PADDR	@ physical
+		ldr	\rv, =UART_VADDR	@ virtual
+		.endm
+
+#include <asm/hardware/debug-pl01x.S>
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mxs/include/mach/devices-common.h linux-libre-2.6.38-gnu1/arch/arm/mach-mxs/include/mach/devices-common.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mxs/include/mach/devices-common.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mxs/include/mach/devices-common.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2009-2010 Pengutronix
+ * Uwe Kleine-Koenig <u.kleine-koenig@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/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/init.h>
+#include <linux/amba/bus.h>
+
+struct platform_device *mxs_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);
+
+static inline struct platform_device *mxs_add_platform_device(
+		const char *name, int id,
+		const struct resource *res, unsigned int num_resources,
+		const void *data, size_t size_data)
+{
+	return mxs_add_platform_device_dmamask(
+			name, id, res, num_resources, data, size_data, 0);
+}
+
+int __init mxs_add_amba_device(const struct amba_device *dev);
+
+/* duart */
+int __init mxs_add_duart(const struct amba_device *dev);
+
+/* fec */
+#include <linux/fec.h>
+struct mxs_fec_data {
+	int id;
+	resource_size_t iobase;
+	resource_size_t iosize;
+	resource_size_t irq;
+};
+struct platform_device *__init mxs_add_fec(
+		const struct mxs_fec_data *data,
+		const struct fec_platform_data *pdata);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mxs/include/mach/entry-macro.S linux-libre-2.6.38-gnu1/arch/arm/mach-mxs/include/mach/entry-macro.S
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mxs/include/mach/entry-macro.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mxs/include/mach/entry-macro.S	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,41 @@
+/*
+ * Low-level IRQ helper macros for Freescale MXS-based
+ *
+ * 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.
+ */
+
+#include <mach/mxs.h>
+
+#define MXS_ICOLL_VBASE		MXS_IO_ADDRESS(MXS_ICOLL_BASE_ADDR)
+#define HW_ICOLL_STAT_OFFSET	0x70
+
+	.macro	disable_fiq
+	.endm
+
+	.macro	get_irqnr_and_base, irqnr, irqstat, base, tmp
+	ldr	\irqnr, [\base, #HW_ICOLL_STAT_OFFSET]
+	cmp	\irqnr, #0x7F
+	strne	\irqnr, [\base]
+	moveqs	\irqnr, #0
+	.endm
+
+	.macro  get_irqnr_preamble, base, tmp
+	ldr	\base, =MXS_ICOLL_VBASE
+	.endm
+
+	.macro  arch_ret_to_user, tmp1, tmp2
+	.endm
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mxs/include/mach/gpio.h linux-libre-2.6.38-gnu1/arch/arm/mach-mxs/include/mach/gpio.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mxs/include/mach/gpio.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mxs/include/mach/gpio.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,35 @@
+/*
+ * 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__ */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mxs/include/mach/hardware.h linux-libre-2.6.38-gnu1/arch/arm/mach-mxs/include/mach/hardware.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mxs/include/mach/hardware.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mxs/include/mach/hardware.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2004-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_HARDWARE_H__
+#define __MACH_MXS_HARDWARE_H__
+
+#ifdef __ASSEMBLER__
+#define IOMEM(addr)	(addr)
+#else
+#define IOMEM(addr)	((void __force __iomem *)(addr))
+#endif
+
+#endif /* __MACH_MXS_HARDWARE_H__ */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mxs/include/mach/io.h linux-libre-2.6.38-gnu1/arch/arm/mach-mxs/include/mach/io.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mxs/include/mach/io.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mxs/include/mach/io.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,22 @@
+/*
+ *  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 __MACH_MXS_IO_H__
+#define __MACH_MXS_IO_H__
+
+/* Allow IO space to be anywhere in the memory */
+#define IO_SPACE_LIMIT 0xffffffff
+
+/* io address mapping macro */
+#define __io(a)		__typesafe_io(a)
+
+#define __mem_pci(a)	(a)
+
+#endif /* __MACH_MXS_IO_H__ */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mxs/include/mach/iomux.h linux-libre-2.6.38-gnu1/arch/arm/mach-mxs/include/mach/iomux.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mxs/include/mach/iomux.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mxs/include/mach/iomux.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2009 by Jan Weitzel Phytec Messtechnik GmbH,
+ *			<armlinux@phytec.de>
+ * 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.
+ */
+
+#ifndef __MACH_MXS_IOMUX_H__
+#define __MACH_MXS_IOMUX_H__
+
+/*
+ * IOMUX/PAD Bit field definitions
+ *
+ * PAD_BANK:		 0..2	(3)
+ * PAD_PIN:		 3..7	(5)
+ * PAD_MUXSEL:		 8..9	(2)
+ * PAD_MA:		10..11	(2)
+ * PAD_MA_VALID:	12	(1)
+ * PAD_VOL:		13	(1)
+ * PAD_VOL_VALID:	14	(1)
+ * PAD_PULL:		15	(1)
+ * PAD_PULL_VALID:	16	(1)
+ * RESERVED:		17..31	(15)
+ */
+typedef u32 iomux_cfg_t;
+
+#define MXS_PAD_BANK_SHIFT	0
+#define MXS_PAD_BANK_MASK	((iomux_cfg_t)0x7 << MXS_PAD_BANK_SHIFT)
+#define MXS_PAD_PIN_SHIFT	3
+#define MXS_PAD_PIN_MASK	((iomux_cfg_t)0x1f << MXS_PAD_PIN_SHIFT)
+#define MXS_PAD_MUXSEL_SHIFT	8
+#define MXS_PAD_MUXSEL_MASK	((iomux_cfg_t)0x3 << MXS_PAD_MUXSEL_SHIFT)
+#define MXS_PAD_MA_SHIFT	10
+#define MXS_PAD_MA_MASK		((iomux_cfg_t)0x3 << MXS_PAD_MA_SHIFT)
+#define MXS_PAD_MA_VALID_SHIFT	12
+#define MXS_PAD_MA_VALID_MASK	((iomux_cfg_t)0x1 << MXS_PAD_MA_VALID_SHIFT)
+#define MXS_PAD_VOL_SHIFT	13
+#define MXS_PAD_VOL_MASK	((iomux_cfg_t)0x1 << MXS_PAD_VOL_SHIFT)
+#define MXS_PAD_VOL_VALID_SHIFT	14
+#define MXS_PAD_VOL_VALID_MASK	((iomux_cfg_t)0x1 << MXS_PAD_VOL_VALID_SHIFT)
+#define MXS_PAD_PULL_SHIFT	15
+#define MXS_PAD_PULL_MASK	((iomux_cfg_t)0x1 << MXS_PAD_PULL_SHIFT)
+#define MXS_PAD_PULL_VALID_SHIFT 16
+#define MXS_PAD_PULL_VALID_MASK	((iomux_cfg_t)0x1 << MXS_PAD_PULL_VALID_SHIFT)
+
+#define PAD_MUXSEL_0		0
+#define PAD_MUXSEL_1		1
+#define PAD_MUXSEL_2		2
+#define PAD_MUXSEL_GPIO		3
+
+#define PAD_4MA			0
+#define PAD_8MA			1
+#define PAD_12MA		2
+#define PAD_16MA		3
+
+#define PAD_1V8			0
+#define PAD_3V3			1
+
+#define PAD_NOPULL		0
+#define PAD_PULLUP		1
+
+#define MXS_PAD_4MA	((PAD_4MA << MXS_PAD_MA_SHIFT) | \
+					MXS_PAD_MA_VALID_MASK)
+#define MXS_PAD_8MA	((PAD_8MA << MXS_PAD_MA_SHIFT) | \
+					MXS_PAD_MA_VALID_MASK)
+#define MXS_PAD_12MA	((PAD_12MA << MXS_PAD_MA_SHIFT) | \
+					MXS_PAD_MA_VALID_MASK)
+#define MXS_PAD_16MA	((PAD_16MA << MXS_PAD_MA_SHIFT) | \
+					MXS_PAD_MA_VALID_MASK)
+
+#define MXS_PAD_1V8	((PAD_1V8 << MXS_PAD_VOL_SHIFT) | \
+					MXS_PAD_VOL_VALID_MASK)
+#define MXS_PAD_3V3	((PAD_3V3 << MXS_PAD_VOL_SHIFT) | \
+					MXS_PAD_VOL_VALID_MASK)
+
+#define MXS_PAD_NOPULL	((PAD_NOPULL << MXS_PAD_PULL_SHIFT) | \
+					MXS_PAD_PULL_VALID_MASK)
+#define MXS_PAD_PULLUP	((PAD_PULLUP << MXS_PAD_PULL_SHIFT) | \
+					MXS_PAD_PULL_VALID_MASK)
+
+#define MXS_IOMUX_PAD(_bank, _pin, _muxsel, _ma, _vol, _pull)		\
+		(((iomux_cfg_t)(_bank) << MXS_PAD_BANK_SHIFT) |		\
+		((iomux_cfg_t)(_pin) << MXS_PAD_PIN_SHIFT) |		\
+		((iomux_cfg_t)(_muxsel) << MXS_PAD_MUXSEL_SHIFT) |	\
+		((iomux_cfg_t)(_ma) << MXS_PAD_MA_SHIFT) |		\
+		((iomux_cfg_t)(_vol) << MXS_PAD_VOL_SHIFT) |		\
+		((iomux_cfg_t)(_pull) << MXS_PAD_PULL_SHIFT))
+
+/*
+ * A pad becomes naked, when none of mA, vol or pull
+ * validity bits is set.
+ */
+#define MXS_IOMUX_PAD_NAKED(_bank, _pin, _muxsel) \
+		MXS_IOMUX_PAD(_bank, _pin, _muxsel, 0, 0, 0)
+
+static inline unsigned int PAD_BANK(iomux_cfg_t pad)
+{
+	return (pad & MXS_PAD_BANK_MASK) >> MXS_PAD_BANK_SHIFT;
+}
+
+static inline unsigned int PAD_PIN(iomux_cfg_t pad)
+{
+	return (pad & MXS_PAD_PIN_MASK) >> MXS_PAD_PIN_SHIFT;
+}
+
+static inline unsigned int PAD_MUXSEL(iomux_cfg_t pad)
+{
+	return (pad & MXS_PAD_MUXSEL_MASK) >> MXS_PAD_MUXSEL_SHIFT;
+}
+
+static inline unsigned int PAD_MA(iomux_cfg_t pad)
+{
+	return (pad & MXS_PAD_MA_MASK) >> MXS_PAD_MA_SHIFT;
+}
+
+static inline unsigned int PAD_MA_VALID(iomux_cfg_t pad)
+{
+	return (pad & MXS_PAD_MA_VALID_MASK) >> MXS_PAD_MA_VALID_SHIFT;
+}
+
+static inline unsigned int PAD_VOL(iomux_cfg_t pad)
+{
+	return (pad & MXS_PAD_VOL_MASK) >> MXS_PAD_VOL_SHIFT;
+}
+
+static inline unsigned int PAD_VOL_VALID(iomux_cfg_t pad)
+{
+	return (pad & MXS_PAD_VOL_VALID_MASK) >> MXS_PAD_VOL_VALID_SHIFT;
+}
+
+static inline unsigned int PAD_PULL(iomux_cfg_t pad)
+{
+	return (pad & MXS_PAD_PULL_MASK) >> MXS_PAD_PULL_SHIFT;
+}
+
+static inline unsigned int PAD_PULL_VALID(iomux_cfg_t pad)
+{
+	return (pad & MXS_PAD_PULL_VALID_MASK) >> MXS_PAD_PULL_VALID_SHIFT;
+}
+
+/*
+ * configures a single pad in the iomuxer
+ */
+int mxs_iomux_setup_pad(iomux_cfg_t pad);
+
+/*
+ * configures multiple pads
+ * convenient way to call the above function with tables
+ */
+int mxs_iomux_setup_multiple_pads(const iomux_cfg_t *pad_list, unsigned count);
+
+#endif /* __MACH_MXS_IOMUX_H__*/
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mxs/include/mach/iomux-mx23.h linux-libre-2.6.38-gnu1/arch/arm/mach-mxs/include/mach/iomux-mx23.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mxs/include/mach/iomux-mx23.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mxs/include/mach/iomux-mx23.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,355 @@
+/*
+ * Copyright (C) 2009-2010 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
+ */
+
+#ifndef __MACH_IOMUX_MX23_H__
+#define __MACH_IOMUX_MX23_H__
+
+#include <mach/iomux.h>
+
+/*
+ * The naming convention for the pad modes is MX23_PAD_<padname>__<padmode>
+ * If <padname> or <padmode> refers to a GPIO, it is named GPIO_<unit>_<num>
+ * See also iomux.h
+ *
+ *									BANK	PIN	MUX
+ */
+/* MUXSEL_0 */
+#define MX23_PAD_GPMI_D00__GPMI_D00		MXS_IOMUX_PAD_NAKED(0,  0, PAD_MUXSEL_0)
+#define MX23_PAD_GPMI_D01__GPMI_D01		MXS_IOMUX_PAD_NAKED(0,  1, PAD_MUXSEL_0)
+#define MX23_PAD_GPMI_D02__GPMI_D02		MXS_IOMUX_PAD_NAKED(0,  2, PAD_MUXSEL_0)
+#define MX23_PAD_GPMI_D03__GPMI_D03		MXS_IOMUX_PAD_NAKED(0,  3, PAD_MUXSEL_0)
+#define MX23_PAD_GPMI_D04__GPMI_D04		MXS_IOMUX_PAD_NAKED(0,  4, PAD_MUXSEL_0)
+#define MX23_PAD_GPMI_D05__GPMI_D05		MXS_IOMUX_PAD_NAKED(0,  5, PAD_MUXSEL_0)
+#define MX23_PAD_GPMI_D06__GPMI_D06		MXS_IOMUX_PAD_NAKED(0,  6, PAD_MUXSEL_0)
+#define MX23_PAD_GPMI_D07__GPMI_D07		MXS_IOMUX_PAD_NAKED(0,  7, PAD_MUXSEL_0)
+#define MX23_PAD_GPMI_D08__GPMI_D08		MXS_IOMUX_PAD_NAKED(0,  8, PAD_MUXSEL_0)
+#define MX23_PAD_GPMI_D09__GPMI_D09		MXS_IOMUX_PAD_NAKED(0,  9, PAD_MUXSEL_0)
+#define MX23_PAD_GPMI_D10__GPMI_D10		MXS_IOMUX_PAD_NAKED(0, 10, PAD_MUXSEL_0)
+#define MX23_PAD_GPMI_D11__GPMI_D11		MXS_IOMUX_PAD_NAKED(0, 11, PAD_MUXSEL_0)
+#define MX23_PAD_GPMI_D12__GPMI_D12		MXS_IOMUX_PAD_NAKED(0, 12, PAD_MUXSEL_0)
+#define MX23_PAD_GPMI_D13__GPMI_D13		MXS_IOMUX_PAD_NAKED(0, 13, PAD_MUXSEL_0)
+#define MX23_PAD_GPMI_D14__GPMI_D14		MXS_IOMUX_PAD_NAKED(0, 14, PAD_MUXSEL_0)
+#define MX23_PAD_GPMI_D15__GPMI_D15		MXS_IOMUX_PAD_NAKED(0, 15, PAD_MUXSEL_0)
+#define MX23_PAD_GPMI_CLE__GPMI_CLE		MXS_IOMUX_PAD_NAKED(0, 16, PAD_MUXSEL_0)
+#define MX23_PAD_GPMI_ALE__GPMI_ALE		MXS_IOMUX_PAD_NAKED(0, 17, PAD_MUXSEL_0)
+#define MX23_PAD_GPMI_CE2N__GPMI_CE2N		MXS_IOMUX_PAD_NAKED(0, 18, PAD_MUXSEL_0)
+#define MX23_PAD_GPMI_RDY0__GPMI_RDY0		MXS_IOMUX_PAD_NAKED(0, 19, PAD_MUXSEL_0)
+#define MX23_PAD_GPMI_RDY1__GPMI_RDY1		MXS_IOMUX_PAD_NAKED(0, 20, PAD_MUXSEL_0)
+#define MX23_PAD_GPMI_RDY2__GPMI_RDY2		MXS_IOMUX_PAD_NAKED(0, 21, PAD_MUXSEL_0)
+#define MX23_PAD_GPMI_RDY3__GPMI_RDY3		MXS_IOMUX_PAD_NAKED(0, 22, PAD_MUXSEL_0)
+#define MX23_PAD_GPMI_WPN__GPMI_WPN		MXS_IOMUX_PAD_NAKED(0, 23, PAD_MUXSEL_0)
+#define MX23_PAD_GPMI_WRN__GPMI_WRN		MXS_IOMUX_PAD_NAKED(0, 24, PAD_MUXSEL_0)
+#define MX23_PAD_GPMI_RDN__GPMI_RDN		MXS_IOMUX_PAD_NAKED(0, 25, PAD_MUXSEL_0)
+#define MX23_PAD_AUART1_CTS__AUART1_CTS		MXS_IOMUX_PAD_NAKED(0, 26, PAD_MUXSEL_0)
+#define MX23_PAD_AUART1_RTS__AUART1_RTS		MXS_IOMUX_PAD_NAKED(0, 27, PAD_MUXSEL_0)
+#define MX23_PAD_AUART1_RX__AUART1_RX		MXS_IOMUX_PAD_NAKED(0, 28, PAD_MUXSEL_0)
+#define MX23_PAD_AUART1_TX__AUART1_TX		MXS_IOMUX_PAD_NAKED(0, 29, PAD_MUXSEL_0)
+#define MX23_PAD_I2C_SCL__I2C_SCL		MXS_IOMUX_PAD_NAKED(0, 30, PAD_MUXSEL_0)
+#define MX23_PAD_I2C_SDA__I2C_SDA		MXS_IOMUX_PAD_NAKED(0, 31, PAD_MUXSEL_0)
+
+#define MX23_PAD_LCD_D00__LCD_D00		MXS_IOMUX_PAD_NAKED(1,  0, PAD_MUXSEL_0)
+#define MX23_PAD_LCD_D01__LCD_D01		MXS_IOMUX_PAD_NAKED(1,  1, PAD_MUXSEL_0)
+#define MX23_PAD_LCD_D02__LCD_D02		MXS_IOMUX_PAD_NAKED(1,  2, PAD_MUXSEL_0)
+#define MX23_PAD_LCD_D03__LCD_D03		MXS_IOMUX_PAD_NAKED(1,  3, PAD_MUXSEL_0)
+#define MX23_PAD_LCD_D04__LCD_D04		MXS_IOMUX_PAD_NAKED(1,  4, PAD_MUXSEL_0)
+#define MX23_PAD_LCD_D05__LCD_D05		MXS_IOMUX_PAD_NAKED(1,  5, PAD_MUXSEL_0)
+#define MX23_PAD_LCD_D06__LCD_D06		MXS_IOMUX_PAD_NAKED(1,  6, PAD_MUXSEL_0)
+#define MX23_PAD_LCD_D07__LCD_D07		MXS_IOMUX_PAD_NAKED(1,  7, PAD_MUXSEL_0)
+#define MX23_PAD_LCD_D08__LCD_D08		MXS_IOMUX_PAD_NAKED(1,  8, PAD_MUXSEL_0)
+#define MX23_PAD_LCD_D09__LCD_D09		MXS_IOMUX_PAD_NAKED(1,  9, PAD_MUXSEL_0)
+#define MX23_PAD_LCD_D10__LCD_D10		MXS_IOMUX_PAD_NAKED(1, 10, PAD_MUXSEL_0)
+#define MX23_PAD_LCD_D11__LCD_D11		MXS_IOMUX_PAD_NAKED(1, 11, PAD_MUXSEL_0)
+#define MX23_PAD_LCD_D12__LCD_D12		MXS_IOMUX_PAD_NAKED(1, 12, PAD_MUXSEL_0)
+#define MX23_PAD_LCD_D13__LCD_D13		MXS_IOMUX_PAD_NAKED(1, 13, PAD_MUXSEL_0)
+#define MX23_PAD_LCD_D14__LCD_D14		MXS_IOMUX_PAD_NAKED(1, 14, PAD_MUXSEL_0)
+#define MX23_PAD_LCD_D15__LCD_D15		MXS_IOMUX_PAD_NAKED(1, 15, PAD_MUXSEL_0)
+#define MX23_PAD_LCD_D16__LCD_D16		MXS_IOMUX_PAD_NAKED(1, 16, PAD_MUXSEL_0)
+#define MX23_PAD_LCD_D17__LCD_D17		MXS_IOMUX_PAD_NAKED(1, 17, PAD_MUXSEL_0)
+#define MX23_PAD_LCD_RESET__LCD_RESET		MXS_IOMUX_PAD_NAKED(1, 18, PAD_MUXSEL_0)
+#define MX23_PAD_LCD_RS__LCD_RS			MXS_IOMUX_PAD_NAKED(1, 19, PAD_MUXSEL_0)
+#define MX23_PAD_LCD_WR__LCD_WR			MXS_IOMUX_PAD_NAKED(1, 20, PAD_MUXSEL_0)
+#define MX23_PAD_LCD_CS__LCD_CS			MXS_IOMUX_PAD_NAKED(1, 21, PAD_MUXSEL_0)
+#define MX23_PAD_LCD_DOTCK__LCD_DOTCK		MXS_IOMUX_PAD_NAKED(1, 22, PAD_MUXSEL_0)
+#define MX23_PAD_LCD_ENABLE__LCD_ENABLE		MXS_IOMUX_PAD_NAKED(1, 23, PAD_MUXSEL_0)
+#define MX23_PAD_LCD_HSYNC__LCD_HSYNC		MXS_IOMUX_PAD_NAKED(1, 24, PAD_MUXSEL_0)
+#define MX23_PAD_LCD_VSYNC__LCD_VSYNC		MXS_IOMUX_PAD_NAKED(1, 25, PAD_MUXSEL_0)
+#define MX23_PAD_PWM0__PWM0			MXS_IOMUX_PAD_NAKED(1, 26, PAD_MUXSEL_0)
+#define MX23_PAD_PWM1__PWM1			MXS_IOMUX_PAD_NAKED(1, 27, PAD_MUXSEL_0)
+#define MX23_PAD_PWM2__PWM2			MXS_IOMUX_PAD_NAKED(1, 28, PAD_MUXSEL_0)
+#define MX23_PAD_PWM3__PWM3			MXS_IOMUX_PAD_NAKED(1, 29, PAD_MUXSEL_0)
+#define MX23_PAD_PWM4__PWM4			MXS_IOMUX_PAD_NAKED(1, 30, PAD_MUXSEL_0)
+
+#define MX23_PAD_SSP1_CMD__SSP1_CMD		MXS_IOMUX_PAD_NAKED(2,  0, PAD_MUXSEL_0)
+#define MX23_PAD_SSP1_DETECT__SSP1_DETECT	MXS_IOMUX_PAD_NAKED(2,  1, PAD_MUXSEL_0)
+#define MX23_PAD_SSP1_DATA0__SSP1_DATA0		MXS_IOMUX_PAD_NAKED(2,  2, PAD_MUXSEL_0)
+#define MX23_PAD_SSP1_DATA1__SSP1_DATA1		MXS_IOMUX_PAD_NAKED(2,  3, PAD_MUXSEL_0)
+#define MX23_PAD_SSP1_DATA2__SSP1_DATA2		MXS_IOMUX_PAD_NAKED(2,  4, PAD_MUXSEL_0)
+#define MX23_PAD_SSP1_DATA3__SSP1_DATA3		MXS_IOMUX_PAD_NAKED(2,  5, PAD_MUXSEL_0)
+#define MX23_PAD_SSP1_SCK__SSP1_SCK		MXS_IOMUX_PAD_NAKED(2,  6, PAD_MUXSEL_0)
+#define MX23_PAD_ROTARYA__ROTARYA		MXS_IOMUX_PAD_NAKED(2,  7, PAD_MUXSEL_0)
+#define MX23_PAD_ROTARYB__ROTARYB		MXS_IOMUX_PAD_NAKED(2,  8, PAD_MUXSEL_0)
+#define MX23_PAD_EMI_A00__EMI_A00		MXS_IOMUX_PAD_NAKED(2,  9, PAD_MUXSEL_0)
+#define MX23_PAD_EMI_A01__EMI_A01		MXS_IOMUX_PAD_NAKED(2, 10, PAD_MUXSEL_0)
+#define MX23_PAD_EMI_A02__EMI_A02		MXS_IOMUX_PAD_NAKED(2, 11, PAD_MUXSEL_0)
+#define MX23_PAD_EMI_A03__EMI_A03		MXS_IOMUX_PAD_NAKED(2, 12, PAD_MUXSEL_0)
+#define MX23_PAD_EMI_A04__EMI_A04		MXS_IOMUX_PAD_NAKED(2, 13, PAD_MUXSEL_0)
+#define MX23_PAD_EMI_A05__EMI_A05		MXS_IOMUX_PAD_NAKED(2, 14, PAD_MUXSEL_0)
+#define MX23_PAD_EMI_A06__EMI_A06		MXS_IOMUX_PAD_NAKED(2, 15, PAD_MUXSEL_0)
+#define MX23_PAD_EMI_A07__EMI_A07		MXS_IOMUX_PAD_NAKED(2, 16, PAD_MUXSEL_0)
+#define MX23_PAD_EMI_A08__EMI_A08		MXS_IOMUX_PAD_NAKED(2, 17, PAD_MUXSEL_0)
+#define MX23_PAD_EMI_A09__EMI_A09		MXS_IOMUX_PAD_NAKED(2, 18, PAD_MUXSEL_0)
+#define MX23_PAD_EMI_A10__EMI_A10		MXS_IOMUX_PAD_NAKED(2, 19, PAD_MUXSEL_0)
+#define MX23_PAD_EMI_A11__EMI_A11		MXS_IOMUX_PAD_NAKED(2, 20, PAD_MUXSEL_0)
+#define MX23_PAD_EMI_A12__EMI_A12		MXS_IOMUX_PAD_NAKED(2, 21, PAD_MUXSEL_0)
+#define MX23_PAD_EMI_BA0__EMI_BA0		MXS_IOMUX_PAD_NAKED(2, 22, PAD_MUXSEL_0)
+#define MX23_PAD_EMI_BA1__EMI_BA1		MXS_IOMUX_PAD_NAKED(2, 23, PAD_MUXSEL_0)
+#define MX23_PAD_EMI_CASN__EMI_CASN		MXS_IOMUX_PAD_NAKED(2, 24, PAD_MUXSEL_0)
+#define MX23_PAD_EMI_CE0N__EMI_CE0N		MXS_IOMUX_PAD_NAKED(2, 25, PAD_MUXSEL_0)
+#define MX23_PAD_EMI_CE1N__EMI_CE1N		MXS_IOMUX_PAD_NAKED(2, 26, PAD_MUXSEL_0)
+#define MX23_PAD_GPMI_CE1N__GPMI_CE1N		MXS_IOMUX_PAD_NAKED(2, 27, PAD_MUXSEL_0)
+#define MX23_PAD_GPMI_CE0N__GPMI_CE0N		MXS_IOMUX_PAD_NAKED(2, 28, PAD_MUXSEL_0)
+#define MX23_PAD_EMI_CKE__EMI_CKE		MXS_IOMUX_PAD_NAKED(2, 29, PAD_MUXSEL_0)
+#define MX23_PAD_EMI_RASN__EMI_RASN		MXS_IOMUX_PAD_NAKED(2, 30, PAD_MUXSEL_0)
+#define MX23_PAD_EMI_WEN__EMI_WEN		MXS_IOMUX_PAD_NAKED(2, 31, PAD_MUXSEL_0)
+
+#define MX23_PAD_EMI_D00__EMI_D00		MXS_IOMUX_PAD_NAKED(3,  0, PAD_MUXSEL_0)
+#define MX23_PAD_EMI_D01__EMI_D01		MXS_IOMUX_PAD_NAKED(3,  1, PAD_MUXSEL_0)
+#define MX23_PAD_EMI_D02__EMI_D02		MXS_IOMUX_PAD_NAKED(3,  2, PAD_MUXSEL_0)
+#define MX23_PAD_EMI_D03__EMI_D03		MXS_IOMUX_PAD_NAKED(3,  3, PAD_MUXSEL_0)
+#define MX23_PAD_EMI_D04__EMI_D04		MXS_IOMUX_PAD_NAKED(3,  4, PAD_MUXSEL_0)
+#define MX23_PAD_EMI_D05__EMI_D05		MXS_IOMUX_PAD_NAKED(3,  5, PAD_MUXSEL_0)
+#define MX23_PAD_EMI_D06__EMI_D06		MXS_IOMUX_PAD_NAKED(3,  6, PAD_MUXSEL_0)
+#define MX23_PAD_EMI_D07__EMI_D07		MXS_IOMUX_PAD_NAKED(3,  7, PAD_MUXSEL_0)
+#define MX23_PAD_EMI_D08__EMI_D08		MXS_IOMUX_PAD_NAKED(3,  8, PAD_MUXSEL_0)
+#define MX23_PAD_EMI_D09__EMI_D09		MXS_IOMUX_PAD_NAKED(3,  9, PAD_MUXSEL_0)
+#define MX23_PAD_EMI_D10__EMI_D10		MXS_IOMUX_PAD_NAKED(3, 10, PAD_MUXSEL_0)
+#define MX23_PAD_EMI_D11__EMI_D11		MXS_IOMUX_PAD_NAKED(3, 11, PAD_MUXSEL_0)
+#define MX23_PAD_EMI_D12__EMI_D12		MXS_IOMUX_PAD_NAKED(3, 12, PAD_MUXSEL_0)
+#define MX23_PAD_EMI_D13__EMI_D13		MXS_IOMUX_PAD_NAKED(3, 13, PAD_MUXSEL_0)
+#define MX23_PAD_EMI_D14__EMI_D14		MXS_IOMUX_PAD_NAKED(3, 14, PAD_MUXSEL_0)
+#define MX23_PAD_EMI_D15__EMI_D15		MXS_IOMUX_PAD_NAKED(3, 15, PAD_MUXSEL_0)
+#define MX23_PAD_EMI_DQM0__EMI_DQM0		MXS_IOMUX_PAD_NAKED(3, 16, PAD_MUXSEL_0)
+#define MX23_PAD_EMI_DQM1__EMI_DQM1		MXS_IOMUX_PAD_NAKED(3, 17, PAD_MUXSEL_0)
+#define MX23_PAD_EMI_DQS0__EMI_DQS0		MXS_IOMUX_PAD_NAKED(3, 18, PAD_MUXSEL_0)
+#define MX23_PAD_EMI_DQS1__EMI_DQS1		MXS_IOMUX_PAD_NAKED(3, 19, PAD_MUXSEL_0)
+#define MX23_PAD_EMI_CLK__EMI_CLK		MXS_IOMUX_PAD_NAKED(3, 20, PAD_MUXSEL_0)
+#define MX23_PAD_EMI_CLKN__EMI_CLKN		MXS_IOMUX_PAD_NAKED(3, 21, PAD_MUXSEL_0)
+
+/* MUXSEL_1 */
+#define MX23_PAD_GPMI_D00__LCD_D8		MXS_IOMUX_PAD_NAKED(0,  0, PAD_MUXSEL_1)
+#define MX23_PAD_GPMI_D01__LCD_D9		MXS_IOMUX_PAD_NAKED(0,  1, PAD_MUXSEL_1)
+#define MX23_PAD_GPMI_D02__LCD_D10		MXS_IOMUX_PAD_NAKED(0,  2, PAD_MUXSEL_1)
+#define MX23_PAD_GPMI_D03__LCD_D11		MXS_IOMUX_PAD_NAKED(0,  3, PAD_MUXSEL_1)
+#define MX23_PAD_GPMI_D04__LCD_D12		MXS_IOMUX_PAD_NAKED(0,  4, PAD_MUXSEL_1)
+#define MX23_PAD_GPMI_D05__LCD_D13		MXS_IOMUX_PAD_NAKED(0,  5, PAD_MUXSEL_1)
+#define MX23_PAD_GPMI_D06__LCD_D14		MXS_IOMUX_PAD_NAKED(0,  6, PAD_MUXSEL_1)
+#define MX23_PAD_GPMI_D07__LCD_D15		MXS_IOMUX_PAD_NAKED(0,  7, PAD_MUXSEL_1)
+#define MX23_PAD_GPMI_D08__LCD_D18		MXS_IOMUX_PAD_NAKED(0,  8, PAD_MUXSEL_1)
+#define MX23_PAD_GPMI_D09__LCD_D19		MXS_IOMUX_PAD_NAKED(0,  9, PAD_MUXSEL_1)
+#define MX23_PAD_GPMI_D10__LCD_D20		MXS_IOMUX_PAD_NAKED(0, 10, PAD_MUXSEL_1)
+#define MX23_PAD_GPMI_D11__LCD_D21		MXS_IOMUX_PAD_NAKED(0, 11, PAD_MUXSEL_1)
+#define MX23_PAD_GPMI_D12__LCD_D22		MXS_IOMUX_PAD_NAKED(0, 12, PAD_MUXSEL_1)
+#define MX23_PAD_GPMI_D13__LCD_D23		MXS_IOMUX_PAD_NAKED(0, 13, PAD_MUXSEL_1)
+#define MX23_PAD_GPMI_D14__AUART2_RX		MXS_IOMUX_PAD_NAKED(0, 14, PAD_MUXSEL_1)
+#define MX23_PAD_GPMI_D15__AUART2_TX		MXS_IOMUX_PAD_NAKED(0, 15, PAD_MUXSEL_1)
+#define MX23_PAD_GPMI_CLE__LCD_D16		MXS_IOMUX_PAD_NAKED(0, 16, PAD_MUXSEL_1)
+#define MX23_PAD_GPMI_ALE__LCD_D17		MXS_IOMUX_PAD_NAKED(0, 17, PAD_MUXSEL_1)
+#define MX23_PAD_GPMI_CE2N__ATA_A2		MXS_IOMUX_PAD_NAKED(0, 18, PAD_MUXSEL_1)
+#define MX23_PAD_AUART1_RTS__IR_CLK		MXS_IOMUX_PAD_NAKED(0, 27, PAD_MUXSEL_1)
+#define MX23_PAD_AUART1_RX__IR_RX		MXS_IOMUX_PAD_NAKED(0, 28, PAD_MUXSEL_1)
+#define MX23_PAD_AUART1_TX__IR_TX		MXS_IOMUX_PAD_NAKED(0, 29, PAD_MUXSEL_1)
+#define MX23_PAD_I2C_SCL__GPMI_RDY2		MXS_IOMUX_PAD_NAKED(0, 30, PAD_MUXSEL_1)
+#define MX23_PAD_I2C_SDA__GPMI_CE2N		MXS_IOMUX_PAD_NAKED(0, 31, PAD_MUXSEL_1)
+
+#define MX23_PAD_LCD_D00__ETM_DA8		MXS_IOMUX_PAD_NAKED(1,  0, PAD_MUXSEL_1)
+#define MX23_PAD_LCD_D01__ETM_DA9		MXS_IOMUX_PAD_NAKED(1,  1, PAD_MUXSEL_1)
+#define MX23_PAD_LCD_D02__ETM_DA10		MXS_IOMUX_PAD_NAKED(1,  2, PAD_MUXSEL_1)
+#define MX23_PAD_LCD_D03__ETM_DA11		MXS_IOMUX_PAD_NAKED(1,  3, PAD_MUXSEL_1)
+#define MX23_PAD_LCD_D04__ETM_DA12		MXS_IOMUX_PAD_NAKED(1,  4, PAD_MUXSEL_1)
+#define MX23_PAD_LCD_D05__ETM_DA13		MXS_IOMUX_PAD_NAKED(1,  5, PAD_MUXSEL_1)
+#define MX23_PAD_LCD_D06__ETM_DA14		MXS_IOMUX_PAD_NAKED(1,  6, PAD_MUXSEL_1)
+#define MX23_PAD_LCD_D07__ETM_DA15		MXS_IOMUX_PAD_NAKED(1,  7, PAD_MUXSEL_1)
+#define MX23_PAD_LCD_D08__ETM_DA0		MXS_IOMUX_PAD_NAKED(1,  8, PAD_MUXSEL_1)
+#define MX23_PAD_LCD_D09__ETM_DA1		MXS_IOMUX_PAD_NAKED(1,  9, PAD_MUXSEL_1)
+#define MX23_PAD_LCD_D10__ETM_DA2		MXS_IOMUX_PAD_NAKED(1, 10, PAD_MUXSEL_1)
+#define MX23_PAD_LCD_D11__ETM_DA3		MXS_IOMUX_PAD_NAKED(1, 11, PAD_MUXSEL_1)
+#define MX23_PAD_LCD_D12__ETM_DA4		MXS_IOMUX_PAD_NAKED(1, 12, PAD_MUXSEL_1)
+#define MX23_PAD_LCD_D13__ETM_DA5		MXS_IOMUX_PAD_NAKED(1, 13, PAD_MUXSEL_1)
+#define MX23_PAD_LCD_D14__ETM_DA6		MXS_IOMUX_PAD_NAKED(1, 14, PAD_MUXSEL_1)
+#define MX23_PAD_LCD_D15__ETM_DA7		MXS_IOMUX_PAD_NAKED(1, 15, PAD_MUXSEL_1)
+#define MX23_PAD_LCD_RESET__ETM_TCTL		MXS_IOMUX_PAD_NAKED(1, 18, PAD_MUXSEL_1)
+#define MX23_PAD_LCD_RS__ETM_TCLK		MXS_IOMUX_PAD_NAKED(1, 19, PAD_MUXSEL_1)
+#define MX23_PAD_LCD_DOTCK__GPMI_RDY3		MXS_IOMUX_PAD_NAKED(1, 22, PAD_MUXSEL_1)
+#define MX23_PAD_LCD_ENABLE__I2C_SCL		MXS_IOMUX_PAD_NAKED(1, 23, PAD_MUXSEL_1)
+#define MX23_PAD_LCD_HSYNC__I2C_SDA		MXS_IOMUX_PAD_NAKED(1, 24, PAD_MUXSEL_1)
+#define MX23_PAD_LCD_VSYNC__LCD_BUSY		MXS_IOMUX_PAD_NAKED(1, 25, PAD_MUXSEL_1)
+#define MX23_PAD_PWM0__ROTARYA			MXS_IOMUX_PAD_NAKED(1, 26, PAD_MUXSEL_1)
+#define MX23_PAD_PWM1__ROTARYB			MXS_IOMUX_PAD_NAKED(1, 27, PAD_MUXSEL_1)
+#define MX23_PAD_PWM2__GPMI_RDY3		MXS_IOMUX_PAD_NAKED(1, 28, PAD_MUXSEL_1)
+#define MX23_PAD_PWM3__ETM_TCTL			MXS_IOMUX_PAD_NAKED(1, 29, PAD_MUXSEL_1)
+#define MX23_PAD_PWM4__ETM_TCLK			MXS_IOMUX_PAD_NAKED(1, 30, PAD_MUXSEL_1)
+
+#define MX23_PAD_SSP1_DETECT__GPMI_CE3N		MXS_IOMUX_PAD_NAKED(2,  1, PAD_MUXSEL_1)
+#define MX23_PAD_SSP1_DATA1__I2C_SCL		MXS_IOMUX_PAD_NAKED(2,  3, PAD_MUXSEL_1)
+#define MX23_PAD_SSP1_DATA2__I2C_SDA		MXS_IOMUX_PAD_NAKED(2,  4, PAD_MUXSEL_1)
+#define MX23_PAD_ROTARYA__AUART2_RTS		MXS_IOMUX_PAD_NAKED(2,  7, PAD_MUXSEL_1)
+#define MX23_PAD_ROTARYB__AUART2_CTS		MXS_IOMUX_PAD_NAKED(2,  8, PAD_MUXSEL_1)
+
+/* MUXSEL_2 */
+#define MX23_PAD_GPMI_D00__SSP2_DATA0		MXS_IOMUX_PAD_NAKED(0,  0, PAD_MUXSEL_2)
+#define MX23_PAD_GPMI_D01__SSP2_DATA1		MXS_IOMUX_PAD_NAKED(0,  1, PAD_MUXSEL_2)
+#define MX23_PAD_GPMI_D02__SSP2_DATA2		MXS_IOMUX_PAD_NAKED(0,  2, PAD_MUXSEL_2)
+#define MX23_PAD_GPMI_D03__SSP2_DATA3		MXS_IOMUX_PAD_NAKED(0,  3, PAD_MUXSEL_2)
+#define MX23_PAD_GPMI_D04__SSP2_DATA4		MXS_IOMUX_PAD_NAKED(0,  4, PAD_MUXSEL_2)
+#define MX23_PAD_GPMI_D05__SSP2_DATA5		MXS_IOMUX_PAD_NAKED(0,  5, PAD_MUXSEL_2)
+#define MX23_PAD_GPMI_D06__SSP2_DATA6		MXS_IOMUX_PAD_NAKED(0,  6, PAD_MUXSEL_2)
+#define MX23_PAD_GPMI_D07__SSP2_DATA7		MXS_IOMUX_PAD_NAKED(0,  7, PAD_MUXSEL_2)
+#define MX23_PAD_GPMI_D08__SSP1_DATA4		MXS_IOMUX_PAD_NAKED(0,  8, PAD_MUXSEL_2)
+#define MX23_PAD_GPMI_D09__SSP1_DATA5		MXS_IOMUX_PAD_NAKED(0,  9, PAD_MUXSEL_2)
+#define MX23_PAD_GPMI_D10__SSP1_DATA6		MXS_IOMUX_PAD_NAKED(0, 10, PAD_MUXSEL_2)
+#define MX23_PAD_GPMI_D11__SSP1_DATA7		MXS_IOMUX_PAD_NAKED(0, 11, PAD_MUXSEL_2)
+#define MX23_PAD_GPMI_D15__GPMI_CE3N		MXS_IOMUX_PAD_NAKED(0, 15, PAD_MUXSEL_2)
+#define MX23_PAD_GPMI_RDY0__SSP2_DETECT		MXS_IOMUX_PAD_NAKED(0, 19, PAD_MUXSEL_2)
+#define MX23_PAD_GPMI_RDY1__SSP2_CMD		MXS_IOMUX_PAD_NAKED(0, 20, PAD_MUXSEL_2)
+#define MX23_PAD_GPMI_WRN__SSP2_SCK		MXS_IOMUX_PAD_NAKED(0, 24, PAD_MUXSEL_2)
+#define MX23_PAD_AUART1_CTS__SSP1_DATA4		MXS_IOMUX_PAD_NAKED(0, 26, PAD_MUXSEL_2)
+#define MX23_PAD_AUART1_RTS__SSP1_DATA5		MXS_IOMUX_PAD_NAKED(0, 27, PAD_MUXSEL_2)
+#define MX23_PAD_AUART1_RX__SSP1_DATA6		MXS_IOMUX_PAD_NAKED(0, 28, PAD_MUXSEL_2)
+#define MX23_PAD_AUART1_TX__SSP1_DATA7		MXS_IOMUX_PAD_NAKED(0, 29, PAD_MUXSEL_2)
+#define MX23_PAD_I2C_SCL__AUART1_TX		MXS_IOMUX_PAD_NAKED(0, 30, PAD_MUXSEL_2)
+#define MX23_PAD_I2C_SDA__AUART1_RX		MXS_IOMUX_PAD_NAKED(0, 31, PAD_MUXSEL_2)
+
+#define MX23_PAD_LCD_D08__SAIF2_SDATA0		MXS_IOMUX_PAD_NAKED(1,  8, PAD_MUXSEL_2)
+#define MX23_PAD_LCD_D09__SAIF1_SDATA0		MXS_IOMUX_PAD_NAKED(1,  9, PAD_MUXSEL_2)
+#define MX23_PAD_LCD_D10__SAIF_MCLK_BITCLK	MXS_IOMUX_PAD_NAKED(1, 10, PAD_MUXSEL_2)
+#define MX23_PAD_LCD_D11__SAIF_LRCLK		MXS_IOMUX_PAD_NAKED(1, 11, PAD_MUXSEL_2)
+#define MX23_PAD_LCD_D12__SAIF2_SDATA1		MXS_IOMUX_PAD_NAKED(1, 12, PAD_MUXSEL_2)
+#define MX23_PAD_LCD_D13__SAIF2_SDATA2		MXS_IOMUX_PAD_NAKED(1, 13, PAD_MUXSEL_2)
+#define MX23_PAD_LCD_D14__SAIF1_SDATA2		MXS_IOMUX_PAD_NAKED(1, 14, PAD_MUXSEL_2)
+#define MX23_PAD_LCD_D15__SAIF1_SDATA1		MXS_IOMUX_PAD_NAKED(1, 15, PAD_MUXSEL_2)
+#define MX23_PAD_LCD_D16__SAIF_ALT_BITCLK	MXS_IOMUX_PAD_NAKED(1, 16, PAD_MUXSEL_2)
+#define MX23_PAD_LCD_RESET__GPMI_CE3N		MXS_IOMUX_PAD_NAKED(1, 18, PAD_MUXSEL_2)
+#define MX23_PAD_PWM0__DUART_RX			MXS_IOMUX_PAD_NAKED(1, 26, PAD_MUXSEL_2)
+#define MX23_PAD_PWM1__DUART_TX			MXS_IOMUX_PAD_NAKED(1, 27, PAD_MUXSEL_2)
+#define MX23_PAD_PWM3__AUART1_CTS		MXS_IOMUX_PAD_NAKED(1, 29, PAD_MUXSEL_2)
+#define MX23_PAD_PWM4__AUART1_RTS		MXS_IOMUX_PAD_NAKED(1, 30, PAD_MUXSEL_2)
+
+#define MX23_PAD_SSP1_CMD__JTAG_TDO		MXS_IOMUX_PAD_NAKED(2,  0, PAD_MUXSEL_2)
+#define MX23_PAD_SSP1_DETECT__USB_OTG_ID	MXS_IOMUX_PAD_NAKED(2,  1, PAD_MUXSEL_2)
+#define MX23_PAD_SSP1_DATA0__JTAG_TDI		MXS_IOMUX_PAD_NAKED(2,  2, PAD_MUXSEL_2)
+#define MX23_PAD_SSP1_DATA1__JTAG_TCLK		MXS_IOMUX_PAD_NAKED(2,  3, PAD_MUXSEL_2)
+#define MX23_PAD_SSP1_DATA2__JTAG_RTCK		MXS_IOMUX_PAD_NAKED(2,  4, PAD_MUXSEL_2)
+#define MX23_PAD_SSP1_DATA3__JTAG_TMS		MXS_IOMUX_PAD_NAKED(2,  5, PAD_MUXSEL_2)
+#define MX23_PAD_SSP1_SCK__JTAG_TRST		MXS_IOMUX_PAD_NAKED(2,  6, PAD_MUXSEL_2)
+#define MX23_PAD_ROTARYA__SPDIF			MXS_IOMUX_PAD_NAKED(2,  7, PAD_MUXSEL_2)
+#define MX23_PAD_ROTARYB__GPMI_CE3N		MXS_IOMUX_PAD_NAKED(2,  8, PAD_MUXSEL_2)
+
+/* MUXSEL_GPIO */
+#define MX23_PAD_GPMI_D00__GPO_0_0		MXS_IOMUX_PAD_NAKED(0,  0, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_D01__GPO_0_1		MXS_IOMUX_PAD_NAKED(0,  1, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_D02__GPO_0_2		MXS_IOMUX_PAD_NAKED(0,  2, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_D03__GPO_0_3		MXS_IOMUX_PAD_NAKED(0,  3, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_D04__GPO_0_4		MXS_IOMUX_PAD_NAKED(0,  4, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_D05__GPO_0_5		MXS_IOMUX_PAD_NAKED(0,  5, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_D06__GPO_0_6		MXS_IOMUX_PAD_NAKED(0,  6, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_D07__GPO_0_7		MXS_IOMUX_PAD_NAKED(0,  7, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_D08__GPO_0_8		MXS_IOMUX_PAD_NAKED(0,  8, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_D09__GPO_0_9		MXS_IOMUX_PAD_NAKED(0,  9, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_D10__GPO_0_10		MXS_IOMUX_PAD_NAKED(0, 10, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_D11__GPO_0_11		MXS_IOMUX_PAD_NAKED(0, 11, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_D12__GPO_0_12		MXS_IOMUX_PAD_NAKED(0, 12, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_D13__GPO_0_13		MXS_IOMUX_PAD_NAKED(0, 13, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_D14__GPO_0_14		MXS_IOMUX_PAD_NAKED(0, 14, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_D15__GPO_0_15		MXS_IOMUX_PAD_NAKED(0, 15, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_CLE__GPO_0_16		MXS_IOMUX_PAD_NAKED(0, 16, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_ALE__GPO_0_17		MXS_IOMUX_PAD_NAKED(0, 17, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_CE2N__GPO_0_18		MXS_IOMUX_PAD_NAKED(0, 18, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_RDY0__GPO_0_19		MXS_IOMUX_PAD_NAKED(0, 19, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_RDY1__GPO_0_20		MXS_IOMUX_PAD_NAKED(0, 20, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_RDY2__GPO_0_21		MXS_IOMUX_PAD_NAKED(0, 21, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_RDY3__GPO_0_22		MXS_IOMUX_PAD_NAKED(0, 22, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_WPN__GPO_0_23		MXS_IOMUX_PAD_NAKED(0, 23, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_WRN__GPO_0_24		MXS_IOMUX_PAD_NAKED(0, 24, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_RDN__GPO_0_25		MXS_IOMUX_PAD_NAKED(0, 25, PAD_MUXSEL_GPIO)
+#define MX23_PAD_AUART1_CTS__GPO_0_26		MXS_IOMUX_PAD_NAKED(0, 26, PAD_MUXSEL_GPIO)
+#define MX23_PAD_AUART1_RTS__GPO_0_27		MXS_IOMUX_PAD_NAKED(0, 27, PAD_MUXSEL_GPIO)
+#define MX23_PAD_AUART1_RX__GPO_0_28		MXS_IOMUX_PAD_NAKED(0, 28, PAD_MUXSEL_GPIO)
+#define MX23_PAD_AUART1_TX__GPO_0_29		MXS_IOMUX_PAD_NAKED(0, 29, PAD_MUXSEL_GPIO)
+#define MX23_PAD_I2C_SCL__GPO_0_30		MXS_IOMUX_PAD_NAKED(0, 30, PAD_MUXSEL_GPIO)
+#define MX23_PAD_I2C_SDA__GPO_0_31		MXS_IOMUX_PAD_NAKED(0, 31, PAD_MUXSEL_GPIO)
+
+#define MX23_PAD_LCD_D00__GPO_1_0		MXS_IOMUX_PAD_NAKED(1,  0, PAD_MUXSEL_GPIO)
+#define MX23_PAD_LCD_D01__GPO_1_1		MXS_IOMUX_PAD_NAKED(1,  1, PAD_MUXSEL_GPIO)
+#define MX23_PAD_LCD_D02__GPO_1_2		MXS_IOMUX_PAD_NAKED(1,  2, PAD_MUXSEL_GPIO)
+#define MX23_PAD_LCD_D03__GPO_1_3		MXS_IOMUX_PAD_NAKED(1,  3, PAD_MUXSEL_GPIO)
+#define MX23_PAD_LCD_D04__GPO_1_4		MXS_IOMUX_PAD_NAKED(1,  4, PAD_MUXSEL_GPIO)
+#define MX23_PAD_LCD_D05__GPO_1_5		MXS_IOMUX_PAD_NAKED(1,  5, PAD_MUXSEL_GPIO)
+#define MX23_PAD_LCD_D06__GPO_1_6		MXS_IOMUX_PAD_NAKED(1,  6, PAD_MUXSEL_GPIO)
+#define MX23_PAD_LCD_D07__GPO_1_7		MXS_IOMUX_PAD_NAKED(1,  7, PAD_MUXSEL_GPIO)
+#define MX23_PAD_LCD_D08__GPO_1_8		MXS_IOMUX_PAD_NAKED(1,  8, PAD_MUXSEL_GPIO)
+#define MX23_PAD_LCD_D09__GPO_1_9		MXS_IOMUX_PAD_NAKED(1,  9, PAD_MUXSEL_GPIO)
+#define MX23_PAD_LCD_D10__GPO_1_10		MXS_IOMUX_PAD_NAKED(1, 10, PAD_MUXSEL_GPIO)
+#define MX23_PAD_LCD_D11__GPO_1_11		MXS_IOMUX_PAD_NAKED(1, 11, PAD_MUXSEL_GPIO)
+#define MX23_PAD_LCD_D12__GPO_1_12		MXS_IOMUX_PAD_NAKED(1, 12, PAD_MUXSEL_GPIO)
+#define MX23_PAD_LCD_D13__GPO_1_13		MXS_IOMUX_PAD_NAKED(1, 13, PAD_MUXSEL_GPIO)
+#define MX23_PAD_LCD_D14__GPO_1_14		MXS_IOMUX_PAD_NAKED(1, 14, PAD_MUXSEL_GPIO)
+#define MX23_PAD_LCD_D15__GPO_1_15		MXS_IOMUX_PAD_NAKED(1, 15, PAD_MUXSEL_GPIO)
+#define MX23_PAD_LCD_D16__GPO_1_16		MXS_IOMUX_PAD_NAKED(1, 16, PAD_MUXSEL_GPIO)
+#define MX23_PAD_LCD_D17__GPO_1_17		MXS_IOMUX_PAD_NAKED(1, 17, PAD_MUXSEL_GPIO)
+#define MX23_PAD_LCD_RESET__GPO_1_18		MXS_IOMUX_PAD_NAKED(1, 18, PAD_MUXSEL_GPIO)
+#define MX23_PAD_LCD_RS__GPO_1_19		MXS_IOMUX_PAD_NAKED(1, 19, PAD_MUXSEL_GPIO)
+#define MX23_PAD_LCD_WR__GPO_1_20		MXS_IOMUX_PAD_NAKED(1, 20, PAD_MUXSEL_GPIO)
+#define MX23_PAD_LCD_CS__GPO_1_21		MXS_IOMUX_PAD_NAKED(1, 21, PAD_MUXSEL_GPIO)
+#define MX23_PAD_LCD_DOTCK__GPO_1_22		MXS_IOMUX_PAD_NAKED(1, 22, PAD_MUXSEL_GPIO)
+#define MX23_PAD_LCD_ENABLE__GPO_1_23		MXS_IOMUX_PAD_NAKED(1, 23, PAD_MUXSEL_GPIO)
+#define MX23_PAD_LCD_HSYNC__GPO_1_24		MXS_IOMUX_PAD_NAKED(1, 24, PAD_MUXSEL_GPIO)
+#define MX23_PAD_LCD_VSYNC__GPO_1_25		MXS_IOMUX_PAD_NAKED(1, 25, PAD_MUXSEL_GPIO)
+#define MX23_PAD_PWM0__GPO_1_26			MXS_IOMUX_PAD_NAKED(1, 26, PAD_MUXSEL_GPIO)
+#define MX23_PAD_PWM1__GPO_1_27			MXS_IOMUX_PAD_NAKED(1, 27, PAD_MUXSEL_GPIO)
+#define MX23_PAD_PWM2__GPO_1_28			MXS_IOMUX_PAD_NAKED(1, 28, PAD_MUXSEL_GPIO)
+#define MX23_PAD_PWM3__GPO_1_29			MXS_IOMUX_PAD_NAKED(1, 29, PAD_MUXSEL_GPIO)
+#define MX23_PAD_PWM4__GPO_1_30			MXS_IOMUX_PAD_NAKED(1, 30, PAD_MUXSEL_GPIO)
+
+#define MX23_PAD_SSP1_CMD__GPO_2_0		MXS_IOMUX_PAD_NAKED(2,  0, PAD_MUXSEL_GPIO)
+#define MX23_PAD_SSP1_DETECT__GPO_2_1		MXS_IOMUX_PAD_NAKED(2,  1, PAD_MUXSEL_GPIO)
+#define MX23_PAD_SSP1_DATA0__GPO_2_2		MXS_IOMUX_PAD_NAKED(2,  2, PAD_MUXSEL_GPIO)
+#define MX23_PAD_SSP1_DATA1__GPO_2_3		MXS_IOMUX_PAD_NAKED(2,  3, PAD_MUXSEL_GPIO)
+#define MX23_PAD_SSP1_DATA2__GPO_2_4		MXS_IOMUX_PAD_NAKED(2,  4, PAD_MUXSEL_GPIO)
+#define MX23_PAD_SSP1_DATA3__GPO_2_5		MXS_IOMUX_PAD_NAKED(2,  5, PAD_MUXSEL_GPIO)
+#define MX23_PAD_SSP1_SCK__GPO_2_6		MXS_IOMUX_PAD_NAKED(2,  6, PAD_MUXSEL_GPIO)
+#define MX23_PAD_ROTARYA__GPO_2_7		MXS_IOMUX_PAD_NAKED(2,  7, PAD_MUXSEL_GPIO)
+#define MX23_PAD_ROTARYB__GPO_2_8		MXS_IOMUX_PAD_NAKED(2,  8, PAD_MUXSEL_GPIO)
+#define MX23_PAD_EMI_A00__GPO_2_9		MXS_IOMUX_PAD_NAKED(2,  9, PAD_MUXSEL_GPIO)
+#define MX23_PAD_EMI_A01__GPO_2_10		MXS_IOMUX_PAD_NAKED(2, 10, PAD_MUXSEL_GPIO)
+#define MX23_PAD_EMI_A02__GPO_2_11		MXS_IOMUX_PAD_NAKED(2, 11, PAD_MUXSEL_GPIO)
+#define MX23_PAD_EMI_A03__GPO_2_12		MXS_IOMUX_PAD_NAKED(2, 12, PAD_MUXSEL_GPIO)
+#define MX23_PAD_EMI_A04__GPO_2_13		MXS_IOMUX_PAD_NAKED(2, 13, PAD_MUXSEL_GPIO)
+#define MX23_PAD_EMI_A05__GPO_2_14		MXS_IOMUX_PAD_NAKED(2, 14, PAD_MUXSEL_GPIO)
+#define MX23_PAD_EMI_A06__GPO_2_15		MXS_IOMUX_PAD_NAKED(2, 15, PAD_MUXSEL_GPIO)
+#define MX23_PAD_EMI_A07__GPO_2_16		MXS_IOMUX_PAD_NAKED(2, 16, PAD_MUXSEL_GPIO)
+#define MX23_PAD_EMI_A08__GPO_2_17		MXS_IOMUX_PAD_NAKED(2, 17, PAD_MUXSEL_GPIO)
+#define MX23_PAD_EMI_A09__GPO_2_18		MXS_IOMUX_PAD_NAKED(2, 18, PAD_MUXSEL_GPIO)
+#define MX23_PAD_EMI_A10__GPO_2_19		MXS_IOMUX_PAD_NAKED(2, 19, PAD_MUXSEL_GPIO)
+#define MX23_PAD_EMI_A11__GPO_2_20		MXS_IOMUX_PAD_NAKED(2, 20, PAD_MUXSEL_GPIO)
+#define MX23_PAD_EMI_A12__GPO_2_21		MXS_IOMUX_PAD_NAKED(2, 21, PAD_MUXSEL_GPIO)
+#define MX23_PAD_EMI_BA0__GPO_2_22		MXS_IOMUX_PAD_NAKED(2, 22, PAD_MUXSEL_GPIO)
+#define MX23_PAD_EMI_BA1__GPO_2_23		MXS_IOMUX_PAD_NAKED(2, 23, PAD_MUXSEL_GPIO)
+#define MX23_PAD_EMI_CASN__GPO_2_24		MXS_IOMUX_PAD_NAKED(2, 24, PAD_MUXSEL_GPIO)
+#define MX23_PAD_EMI_CE0N__GPO_2_25		MXS_IOMUX_PAD_NAKED(2, 25, PAD_MUXSEL_GPIO)
+#define MX23_PAD_EMI_CE1N__GPO_2_26		MXS_IOMUX_PAD_NAKED(2, 26, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_CE1N__GPO_2_27		MXS_IOMUX_PAD_NAKED(2, 27, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_CE0N__GPO_2_28		MXS_IOMUX_PAD_NAKED(2, 28, PAD_MUXSEL_GPIO)
+#define MX23_PAD_EMI_CKE__GPO_2_29		MXS_IOMUX_PAD_NAKED(2, 29, PAD_MUXSEL_GPIO)
+#define MX23_PAD_EMI_RASN__GPO_2_30		MXS_IOMUX_PAD_NAKED(2, 30, PAD_MUXSEL_GPIO)
+#define MX23_PAD_EMI_WEN__GPO_2_31		MXS_IOMUX_PAD_NAKED(2, 31, PAD_MUXSEL_GPIO)
+
+#endif /* __MACH_IOMUX_MX23_H__ */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mxs/include/mach/iomux-mx28.h linux-libre-2.6.38-gnu1/arch/arm/mach-mxs/include/mach/iomux-mx28.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mxs/include/mach/iomux-mx28.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mxs/include/mach/iomux-mx28.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,537 @@
+/*
+ * Copyright (C) 2009-2010 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
+ */
+
+#ifndef __MACH_IOMUX_MX28_H__
+#define __MACH_IOMUX_MX28_H__
+
+#include <mach/iomux.h>
+
+/*
+ * The naming convention for the pad modes is MX28_PAD_<padname>__<padmode>
+ * If <padname> or <padmode> refers to a GPIO, it is named GPIO_<unit>_<num>
+ * See also iomux.h
+ *
+ *									BANK	PIN	MUX
+ */
+/* MUXSEL_0 */
+#define MX28_PAD_GPMI_D00__GPMI_D0			MXS_IOMUX_PAD_NAKED(0,  0, PAD_MUXSEL_0)
+#define MX28_PAD_GPMI_D01__GPMI_D1			MXS_IOMUX_PAD_NAKED(0,  1, PAD_MUXSEL_0)
+#define MX28_PAD_GPMI_D02__GPMI_D2			MXS_IOMUX_PAD_NAKED(0,  2, PAD_MUXSEL_0)
+#define MX28_PAD_GPMI_D03__GPMI_D3			MXS_IOMUX_PAD_NAKED(0,  3, PAD_MUXSEL_0)
+#define MX28_PAD_GPMI_D04__GPMI_D4			MXS_IOMUX_PAD_NAKED(0,  4, PAD_MUXSEL_0)
+#define MX28_PAD_GPMI_D05__GPMI_D5			MXS_IOMUX_PAD_NAKED(0,  5, PAD_MUXSEL_0)
+#define MX28_PAD_GPMI_D06__GPMI_D6			MXS_IOMUX_PAD_NAKED(0,  6, PAD_MUXSEL_0)
+#define MX28_PAD_GPMI_D07__GPMI_D7			MXS_IOMUX_PAD_NAKED(0,  7, PAD_MUXSEL_0)
+#define MX28_PAD_GPMI_CE0N__GPMI_CE0N			MXS_IOMUX_PAD_NAKED(0, 16, PAD_MUXSEL_0)
+#define MX28_PAD_GPMI_CE1N__GPMI_CE1N			MXS_IOMUX_PAD_NAKED(0, 17, PAD_MUXSEL_0)
+#define MX28_PAD_GPMI_CE2N__GPMI_CE2N			MXS_IOMUX_PAD_NAKED(0, 18, PAD_MUXSEL_0)
+#define MX28_PAD_GPMI_CE3N__GPMI_CE3N			MXS_IOMUX_PAD_NAKED(0, 19, PAD_MUXSEL_0)
+#define MX28_PAD_GPMI_RDY0__GPMI_READY0			MXS_IOMUX_PAD_NAKED(0, 20, PAD_MUXSEL_0)
+#define MX28_PAD_GPMI_RDY1__GPMI_READY1			MXS_IOMUX_PAD_NAKED(0, 21, PAD_MUXSEL_0)
+#define MX28_PAD_GPMI_RDY2__GPMI_READY2			MXS_IOMUX_PAD_NAKED(0, 22, PAD_MUXSEL_0)
+#define MX28_PAD_GPMI_RDY3__GPMI_READY3			MXS_IOMUX_PAD_NAKED(0, 23, PAD_MUXSEL_0)
+#define MX28_PAD_GPMI_RDN__GPMI_RDN			MXS_IOMUX_PAD_NAKED(0, 24, PAD_MUXSEL_0)
+#define MX28_PAD_GPMI_WRN__GPMI_WRN			MXS_IOMUX_PAD_NAKED(0, 25, PAD_MUXSEL_0)
+#define MX28_PAD_GPMI_ALE__GPMI_ALE			MXS_IOMUX_PAD_NAKED(0, 26, PAD_MUXSEL_0)
+#define MX28_PAD_GPMI_CLE__GPMI_CLE			MXS_IOMUX_PAD_NAKED(0, 27, PAD_MUXSEL_0)
+#define MX28_PAD_GPMI_RESETN__GPMI_RESETN		MXS_IOMUX_PAD_NAKED(0, 28, PAD_MUXSEL_0)
+
+#define MX28_PAD_LCD_D00__LCD_D0			MXS_IOMUX_PAD_NAKED(1,  0, PAD_MUXSEL_0)
+#define MX28_PAD_LCD_D01__LCD_D1			MXS_IOMUX_PAD_NAKED(1,  1, PAD_MUXSEL_0)
+#define MX28_PAD_LCD_D02__LCD_D2			MXS_IOMUX_PAD_NAKED(1,  2, PAD_MUXSEL_0)
+#define MX28_PAD_LCD_D03__LCD_D3			MXS_IOMUX_PAD_NAKED(1,  3, PAD_MUXSEL_0)
+#define MX28_PAD_LCD_D04__LCD_D4			MXS_IOMUX_PAD_NAKED(1,  4, PAD_MUXSEL_0)
+#define MX28_PAD_LCD_D05__LCD_D5			MXS_IOMUX_PAD_NAKED(1,  5, PAD_MUXSEL_0)
+#define MX28_PAD_LCD_D06__LCD_D6			MXS_IOMUX_PAD_NAKED(1,  6, PAD_MUXSEL_0)
+#define MX28_PAD_LCD_D07__LCD_D7			MXS_IOMUX_PAD_NAKED(1,  7, PAD_MUXSEL_0)
+#define MX28_PAD_LCD_D08__LCD_D8			MXS_IOMUX_PAD_NAKED(1,  8, PAD_MUXSEL_0)
+#define MX28_PAD_LCD_D09__LCD_D9			MXS_IOMUX_PAD_NAKED(1,  9, PAD_MUXSEL_0)
+#define MX28_PAD_LCD_D10__LCD_D10			MXS_IOMUX_PAD_NAKED(1, 10, PAD_MUXSEL_0)
+#define MX28_PAD_LCD_D11__LCD_D11			MXS_IOMUX_PAD_NAKED(1, 11, PAD_MUXSEL_0)
+#define MX28_PAD_LCD_D12__LCD_D12			MXS_IOMUX_PAD_NAKED(1, 12, PAD_MUXSEL_0)
+#define MX28_PAD_LCD_D13__LCD_D13			MXS_IOMUX_PAD_NAKED(1, 13, PAD_MUXSEL_0)
+#define MX28_PAD_LCD_D14__LCD_D14			MXS_IOMUX_PAD_NAKED(1, 14, PAD_MUXSEL_0)
+#define MX28_PAD_LCD_D15__LCD_D15			MXS_IOMUX_PAD_NAKED(1, 15, PAD_MUXSEL_0)
+#define MX28_PAD_LCD_D16__LCD_D16			MXS_IOMUX_PAD_NAKED(1, 16, PAD_MUXSEL_0)
+#define MX28_PAD_LCD_D17__LCD_D17			MXS_IOMUX_PAD_NAKED(1, 17, PAD_MUXSEL_0)
+#define MX28_PAD_LCD_D18__LCD_D18			MXS_IOMUX_PAD_NAKED(1, 18, PAD_MUXSEL_0)
+#define MX28_PAD_LCD_D19__LCD_D19			MXS_IOMUX_PAD_NAKED(1, 19, PAD_MUXSEL_0)
+#define MX28_PAD_LCD_D20__LCD_D20			MXS_IOMUX_PAD_NAKED(1, 20, PAD_MUXSEL_0)
+#define MX28_PAD_LCD_D21__LCD_D21			MXS_IOMUX_PAD_NAKED(1, 21, PAD_MUXSEL_0)
+#define MX28_PAD_LCD_D22__LCD_D22			MXS_IOMUX_PAD_NAKED(1, 22, PAD_MUXSEL_0)
+#define MX28_PAD_LCD_D23__LCD_D23			MXS_IOMUX_PAD_NAKED(1, 23, PAD_MUXSEL_0)
+#define MX28_PAD_LCD_RD_E__LCD_RD_E			MXS_IOMUX_PAD_NAKED(1, 24, PAD_MUXSEL_0)
+#define MX28_PAD_LCD_WR_RWN__LCD_WR_RWN			MXS_IOMUX_PAD_NAKED(1, 25, PAD_MUXSEL_0)
+#define MX28_PAD_LCD_RS__LCD_RS				MXS_IOMUX_PAD_NAKED(1, 26, PAD_MUXSEL_0)
+#define MX28_PAD_LCD_CS__LCD_CS				MXS_IOMUX_PAD_NAKED(1, 27, PAD_MUXSEL_0)
+#define MX28_PAD_LCD_VSYNC__LCD_VSYNC			MXS_IOMUX_PAD_NAKED(1, 28, PAD_MUXSEL_0)
+#define MX28_PAD_LCD_HSYNC__LCD_HSYNC			MXS_IOMUX_PAD_NAKED(1, 29, PAD_MUXSEL_0)
+#define MX28_PAD_LCD_DOTCLK__LCD_DOTCLK			MXS_IOMUX_PAD_NAKED(1, 30, PAD_MUXSEL_0)
+#define MX28_PAD_LCD_ENABLE__LCD_ENABLE			MXS_IOMUX_PAD_NAKED(1, 31, PAD_MUXSEL_0)
+
+#define MX28_PAD_SSP0_DATA0__SSP0_D0			MXS_IOMUX_PAD_NAKED(2,  0, PAD_MUXSEL_0)
+#define MX28_PAD_SSP0_DATA1__SSP0_D1			MXS_IOMUX_PAD_NAKED(2,  1, PAD_MUXSEL_0)
+#define MX28_PAD_SSP0_DATA2__SSP0_D2			MXS_IOMUX_PAD_NAKED(2,  2, PAD_MUXSEL_0)
+#define MX28_PAD_SSP0_DATA3__SSP0_D3			MXS_IOMUX_PAD_NAKED(2,  3, PAD_MUXSEL_0)
+#define MX28_PAD_SSP0_DATA4__SSP0_D4			MXS_IOMUX_PAD_NAKED(2,  4, PAD_MUXSEL_0)
+#define MX28_PAD_SSP0_DATA5__SSP0_D5			MXS_IOMUX_PAD_NAKED(2,  5, PAD_MUXSEL_0)
+#define MX28_PAD_SSP0_DATA6__SSP0_D6			MXS_IOMUX_PAD_NAKED(2,  6, PAD_MUXSEL_0)
+#define MX28_PAD_SSP0_DATA7__SSP0_D7			MXS_IOMUX_PAD_NAKED(2,  7, PAD_MUXSEL_0)
+#define MX28_PAD_SSP0_CMD__SSP0_CMD			MXS_IOMUX_PAD_NAKED(2,  8, PAD_MUXSEL_0)
+#define MX28_PAD_SSP0_DETECT__SSP0_CARD_DETECT		MXS_IOMUX_PAD_NAKED(2,  9, PAD_MUXSEL_0)
+#define MX28_PAD_SSP0_SCK__SSP0_SCK			MXS_IOMUX_PAD_NAKED(2, 10, PAD_MUXSEL_0)
+#define MX28_PAD_SSP1_SCK__SSP1_SCK			MXS_IOMUX_PAD_NAKED(2, 12, PAD_MUXSEL_0)
+#define MX28_PAD_SSP1_CMD__SSP1_CMD			MXS_IOMUX_PAD_NAKED(2, 13, PAD_MUXSEL_0)
+#define MX28_PAD_SSP1_DATA0__SSP1_D0			MXS_IOMUX_PAD_NAKED(2, 14, PAD_MUXSEL_0)
+#define MX28_PAD_SSP1_DATA3__SSP1_D3			MXS_IOMUX_PAD_NAKED(2, 15, PAD_MUXSEL_0)
+#define MX28_PAD_SSP2_SCK__SSP2_SCK			MXS_IOMUX_PAD_NAKED(2, 16, PAD_MUXSEL_0)
+#define MX28_PAD_SSP2_MOSI__SSP2_CMD			MXS_IOMUX_PAD_NAKED(2, 17, PAD_MUXSEL_0)
+#define MX28_PAD_SSP2_MISO__SSP2_D0			MXS_IOMUX_PAD_NAKED(2, 18, PAD_MUXSEL_0)
+#define MX28_PAD_SSP2_SS0__SSP2_D3			MXS_IOMUX_PAD_NAKED(2, 19, PAD_MUXSEL_0)
+#define MX28_PAD_SSP2_SS1__SSP2_D4			MXS_IOMUX_PAD_NAKED(2, 20, PAD_MUXSEL_0)
+#define MX28_PAD_SSP2_SS2__SSP2_D5			MXS_IOMUX_PAD_NAKED(2, 21, PAD_MUXSEL_0)
+#define MX28_PAD_SSP3_SCK__SSP3_SCK			MXS_IOMUX_PAD_NAKED(2, 24, PAD_MUXSEL_0)
+#define MX28_PAD_SSP3_MOSI__SSP3_CMD			MXS_IOMUX_PAD_NAKED(2, 25, PAD_MUXSEL_0)
+#define MX28_PAD_SSP3_MISO__SSP3_D0			MXS_IOMUX_PAD_NAKED(2, 26, PAD_MUXSEL_0)
+#define MX28_PAD_SSP3_SS0__SSP3_D3			MXS_IOMUX_PAD_NAKED(2, 27, PAD_MUXSEL_0)
+
+#define MX28_PAD_AUART0_RX__AUART0_RX			MXS_IOMUX_PAD_NAKED(3,  0, PAD_MUXSEL_0)
+#define MX28_PAD_AUART0_TX__AUART0_TX			MXS_IOMUX_PAD_NAKED(3,  1, PAD_MUXSEL_0)
+#define MX28_PAD_AUART0_CTS__AUART0_CTS			MXS_IOMUX_PAD_NAKED(3,  2, PAD_MUXSEL_0)
+#define MX28_PAD_AUART0_RTS__AUART0_RTS			MXS_IOMUX_PAD_NAKED(3,  3, PAD_MUXSEL_0)
+#define MX28_PAD_AUART1_RX__AUART1_RX			MXS_IOMUX_PAD_NAKED(3,  4, PAD_MUXSEL_0)
+#define MX28_PAD_AUART1_TX__AUART1_TX			MXS_IOMUX_PAD_NAKED(3,  5, PAD_MUXSEL_0)
+#define MX28_PAD_AUART1_CTS__AUART1_CTS			MXS_IOMUX_PAD_NAKED(3,  6, PAD_MUXSEL_0)
+#define MX28_PAD_AUART1_RTS__AUART1_RTS			MXS_IOMUX_PAD_NAKED(3,  7, PAD_MUXSEL_0)
+#define MX28_PAD_AUART2_RX__AUART2_RX			MXS_IOMUX_PAD_NAKED(3,  8, PAD_MUXSEL_0)
+#define MX28_PAD_AUART2_TX__AUART2_TX			MXS_IOMUX_PAD_NAKED(3,  9, PAD_MUXSEL_0)
+#define MX28_PAD_AUART2_CTS__AUART2_CTS			MXS_IOMUX_PAD_NAKED(3, 10, PAD_MUXSEL_0)
+#define MX28_PAD_AUART2_RTS__AUART2_RTS			MXS_IOMUX_PAD_NAKED(3, 11, PAD_MUXSEL_0)
+#define MX28_PAD_AUART3_RX__AUART3_RX			MXS_IOMUX_PAD_NAKED(3, 12, PAD_MUXSEL_0)
+#define MX28_PAD_AUART3_TX__AUART3_TX			MXS_IOMUX_PAD_NAKED(3, 13, PAD_MUXSEL_0)
+#define MX28_PAD_AUART3_CTS__AUART3_CTS			MXS_IOMUX_PAD_NAKED(3, 14, PAD_MUXSEL_0)
+#define MX28_PAD_AUART3_RTS__AUART3_RTS			MXS_IOMUX_PAD_NAKED(3, 15, PAD_MUXSEL_0)
+#define MX28_PAD_PWM0__PWM_0				MXS_IOMUX_PAD_NAKED(3, 16, PAD_MUXSEL_0)
+#define MX28_PAD_PWM1__PWM_1				MXS_IOMUX_PAD_NAKED(3, 17, PAD_MUXSEL_0)
+#define MX28_PAD_PWM2__PWM_2				MXS_IOMUX_PAD_NAKED(3, 18, PAD_MUXSEL_0)
+#define MX28_PAD_SAIF0_MCLK__SAIF0_MCLK			MXS_IOMUX_PAD_NAKED(3, 20, PAD_MUXSEL_0)
+#define MX28_PAD_SAIF0_LRCLK__SAIF0_LRCLK		MXS_IOMUX_PAD_NAKED(3, 21, PAD_MUXSEL_0)
+#define MX28_PAD_SAIF0_BITCLK__SAIF0_BITCLK		MXS_IOMUX_PAD_NAKED(3, 22, PAD_MUXSEL_0)
+#define MX28_PAD_SAIF0_SDATA0__SAIF0_SDATA0		MXS_IOMUX_PAD_NAKED(3, 23, PAD_MUXSEL_0)
+#define MX28_PAD_I2C0_SCL__I2C0_SCL			MXS_IOMUX_PAD_NAKED(3, 24, PAD_MUXSEL_0)
+#define MX28_PAD_I2C0_SDA__I2C0_SDA			MXS_IOMUX_PAD_NAKED(3, 25, PAD_MUXSEL_0)
+#define MX28_PAD_SAIF1_SDATA0__SAIF1_SDATA0		MXS_IOMUX_PAD_NAKED(3, 26, PAD_MUXSEL_0)
+#define MX28_PAD_SPDIF__SPDIF_TX			MXS_IOMUX_PAD_NAKED(3, 27, PAD_MUXSEL_0)
+#define MX28_PAD_PWM3__PWM_3				MXS_IOMUX_PAD_NAKED(3, 28, PAD_MUXSEL_0)
+#define MX28_PAD_PWM4__PWM_4				MXS_IOMUX_PAD_NAKED(3, 29, PAD_MUXSEL_0)
+#define MX28_PAD_LCD_RESET__LCD_RESET			MXS_IOMUX_PAD_NAKED(3, 30, PAD_MUXSEL_0)
+
+#define MX28_PAD_ENET0_MDC__ENET0_MDC			MXS_IOMUX_PAD_NAKED(4,  0, PAD_MUXSEL_0)
+#define MX28_PAD_ENET0_MDIO__ENET0_MDIO			MXS_IOMUX_PAD_NAKED(4,  1, PAD_MUXSEL_0)
+#define MX28_PAD_ENET0_RX_EN__ENET0_RX_EN		MXS_IOMUX_PAD_NAKED(4,  2, PAD_MUXSEL_0)
+#define MX28_PAD_ENET0_RXD0__ENET0_RXD0			MXS_IOMUX_PAD_NAKED(4,  3, PAD_MUXSEL_0)
+#define MX28_PAD_ENET0_RXD1__ENET0_RXD1			MXS_IOMUX_PAD_NAKED(4,  4, PAD_MUXSEL_0)
+#define MX28_PAD_ENET0_TX_CLK__ENET0_TX_CLK		MXS_IOMUX_PAD_NAKED(4,  5, PAD_MUXSEL_0)
+#define MX28_PAD_ENET0_TX_EN__ENET0_TX_EN		MXS_IOMUX_PAD_NAKED(4,  6, PAD_MUXSEL_0)
+#define MX28_PAD_ENET0_TXD0__ENET0_TXD0			MXS_IOMUX_PAD_NAKED(4,  7, PAD_MUXSEL_0)
+#define MX28_PAD_ENET0_TXD1__ENET0_TXD1			MXS_IOMUX_PAD_NAKED(4,  8, PAD_MUXSEL_0)
+#define MX28_PAD_ENET0_RXD2__ENET0_RXD2			MXS_IOMUX_PAD_NAKED(4,  9, PAD_MUXSEL_0)
+#define MX28_PAD_ENET0_RXD3__ENET0_RXD3			MXS_IOMUX_PAD_NAKED(4, 10, PAD_MUXSEL_0)
+#define MX28_PAD_ENET0_TXD2__ENET0_TXD2			MXS_IOMUX_PAD_NAKED(4, 11, PAD_MUXSEL_0)
+#define MX28_PAD_ENET0_TXD3__ENET0_TXD3			MXS_IOMUX_PAD_NAKED(4, 12, PAD_MUXSEL_0)
+#define MX28_PAD_ENET0_RX_CLK__ENET0_RX_CLK		MXS_IOMUX_PAD_NAKED(4, 13, PAD_MUXSEL_0)
+#define MX28_PAD_ENET0_COL__ENET0_COL			MXS_IOMUX_PAD_NAKED(4, 14, PAD_MUXSEL_0)
+#define MX28_PAD_ENET0_CRS__ENET0_CRS			MXS_IOMUX_PAD_NAKED(4, 15, PAD_MUXSEL_0)
+#define MX28_PAD_ENET_CLK__CLKCTRL_ENET			MXS_IOMUX_PAD_NAKED(4, 16, PAD_MUXSEL_0)
+#define MX28_PAD_JTAG_RTCK__JTAG_RTCK			MXS_IOMUX_PAD_NAKED(4, 20, PAD_MUXSEL_0)
+
+#define MX28_PAD_EMI_D00__EMI_DATA0			MXS_IOMUX_PAD_NAKED(5,  0, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_D01__EMI_DATA1			MXS_IOMUX_PAD_NAKED(5,  1, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_D02__EMI_DATA2			MXS_IOMUX_PAD_NAKED(5,  2, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_D03__EMI_DATA3			MXS_IOMUX_PAD_NAKED(5,  3, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_D04__EMI_DATA4			MXS_IOMUX_PAD_NAKED(5,  4, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_D05__EMI_DATA5			MXS_IOMUX_PAD_NAKED(5,  5, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_D06__EMI_DATA6			MXS_IOMUX_PAD_NAKED(5,  6, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_D07__EMI_DATA7			MXS_IOMUX_PAD_NAKED(5,  7, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_D08__EMI_DATA8			MXS_IOMUX_PAD_NAKED(5,  8, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_D09__EMI_DATA9			MXS_IOMUX_PAD_NAKED(5,  9, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_D10__EMI_DATA10			MXS_IOMUX_PAD_NAKED(5, 10, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_D11__EMI_DATA11			MXS_IOMUX_PAD_NAKED(5, 11, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_D12__EMI_DATA12			MXS_IOMUX_PAD_NAKED(5, 12, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_D13__EMI_DATA13			MXS_IOMUX_PAD_NAKED(5, 13, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_D14__EMI_DATA14			MXS_IOMUX_PAD_NAKED(5, 14, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_D15__EMI_DATA15			MXS_IOMUX_PAD_NAKED(5, 15, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_ODT0__EMI_ODT0			MXS_IOMUX_PAD_NAKED(5, 16, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_DQM0__EMI_DQM0			MXS_IOMUX_PAD_NAKED(5, 17, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_ODT1__EMI_ODT1			MXS_IOMUX_PAD_NAKED(5, 18, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_DQM1__EMI_DQM1			MXS_IOMUX_PAD_NAKED(5, 19, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_DDR_OPEN_FB__EMI_DDR_OPEN_FEEDBACK	MXS_IOMUX_PAD_NAKED(5, 20, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_CLK__EMI_CLK			MXS_IOMUX_PAD_NAKED(5, 21, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_DQS0__EMI_DQS0			MXS_IOMUX_PAD_NAKED(5, 22, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_DQS1__EMI_DQS1			MXS_IOMUX_PAD_NAKED(5, 23, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_DDR_OPEN__EMI_DDR_OPEN		MXS_IOMUX_PAD_NAKED(5, 26, PAD_MUXSEL_0)
+
+#define MX28_PAD_EMI_A00__EMI_ADDR0			MXS_IOMUX_PAD_NAKED(6,  0, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_A01__EMI_ADDR1			MXS_IOMUX_PAD_NAKED(6,  1, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_A02__EMI_ADDR2			MXS_IOMUX_PAD_NAKED(6,  2, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_A03__EMI_ADDR3			MXS_IOMUX_PAD_NAKED(6,  3, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_A04__EMI_ADDR4			MXS_IOMUX_PAD_NAKED(6,  4, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_A05__EMI_ADDR5			MXS_IOMUX_PAD_NAKED(6,  5, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_A06__EMI_ADDR6			MXS_IOMUX_PAD_NAKED(6,  6, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_A07__EMI_ADDR7			MXS_IOMUX_PAD_NAKED(6,  7, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_A08__EMI_ADDR8			MXS_IOMUX_PAD_NAKED(6,  8, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_A09__EMI_ADDR9			MXS_IOMUX_PAD_NAKED(6,  9, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_A10__EMI_ADDR10			MXS_IOMUX_PAD_NAKED(6, 10, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_A11__EMI_ADDR11			MXS_IOMUX_PAD_NAKED(6, 11, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_A12__EMI_ADDR12			MXS_IOMUX_PAD_NAKED(6, 12, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_A13__EMI_ADDR13			MXS_IOMUX_PAD_NAKED(6, 13, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_A14__EMI_ADDR14			MXS_IOMUX_PAD_NAKED(6, 14, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_BA0__EMI_BA0			MXS_IOMUX_PAD_NAKED(6, 16, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_BA1__EMI_BA1			MXS_IOMUX_PAD_NAKED(6, 17, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_BA2__EMI_BA2			MXS_IOMUX_PAD_NAKED(6, 18, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_CASN__EMI_CASN			MXS_IOMUX_PAD_NAKED(6, 19, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_RASN__EMI_RASN			MXS_IOMUX_PAD_NAKED(6, 20, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_WEN__EMI_WEN			MXS_IOMUX_PAD_NAKED(6, 21, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_CE0N__EMI_CE0N			MXS_IOMUX_PAD_NAKED(6, 22, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_CE1N__EMI_CE1N			MXS_IOMUX_PAD_NAKED(6, 23, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_CKE__EMI_CKE			MXS_IOMUX_PAD_NAKED(6, 24, PAD_MUXSEL_0)
+
+/* MUXSEL_1 */
+#define MX28_PAD_GPMI_D00__SSP1_D0			MXS_IOMUX_PAD_NAKED(0,  0, PAD_MUXSEL_1)
+#define MX28_PAD_GPMI_D01__SSP1_D1			MXS_IOMUX_PAD_NAKED(0,  1, PAD_MUXSEL_1)
+#define MX28_PAD_GPMI_D02__SSP1_D2			MXS_IOMUX_PAD_NAKED(0,  2, PAD_MUXSEL_1)
+#define MX28_PAD_GPMI_D03__SSP1_D3			MXS_IOMUX_PAD_NAKED(0,  3, PAD_MUXSEL_1)
+#define MX28_PAD_GPMI_D04__SSP1_D4			MXS_IOMUX_PAD_NAKED(0,  4, PAD_MUXSEL_1)
+#define MX28_PAD_GPMI_D05__SSP1_D5			MXS_IOMUX_PAD_NAKED(0,  5, PAD_MUXSEL_1)
+#define MX28_PAD_GPMI_D06__SSP1_D6			MXS_IOMUX_PAD_NAKED(0,  6, PAD_MUXSEL_1)
+#define MX28_PAD_GPMI_D07__SSP1_D7			MXS_IOMUX_PAD_NAKED(0,  7, PAD_MUXSEL_1)
+#define MX28_PAD_GPMI_CE0N__SSP3_D0			MXS_IOMUX_PAD_NAKED(0, 16, PAD_MUXSEL_1)
+#define MX28_PAD_GPMI_CE1N__SSP3_D3			MXS_IOMUX_PAD_NAKED(0, 17, PAD_MUXSEL_1)
+#define MX28_PAD_GPMI_CE2N__CAN1_TX			MXS_IOMUX_PAD_NAKED(0, 18, PAD_MUXSEL_1)
+#define MX28_PAD_GPMI_CE3N__CAN1_RX			MXS_IOMUX_PAD_NAKED(0, 19, PAD_MUXSEL_1)
+#define MX28_PAD_GPMI_RDY0__SSP1_CARD_DETECT		MXS_IOMUX_PAD_NAKED(0, 20, PAD_MUXSEL_1)
+#define MX28_PAD_GPMI_RDY1__SSP1_CMD			MXS_IOMUX_PAD_NAKED(0, 21, PAD_MUXSEL_1)
+#define MX28_PAD_GPMI_RDY2__CAN0_TX			MXS_IOMUX_PAD_NAKED(0, 22, PAD_MUXSEL_1)
+#define MX28_PAD_GPMI_RDY3__CAN0_RX			MXS_IOMUX_PAD_NAKED(0, 23, PAD_MUXSEL_1)
+#define MX28_PAD_GPMI_RDN__SSP3_SCK			MXS_IOMUX_PAD_NAKED(0, 24, PAD_MUXSEL_1)
+#define MX28_PAD_GPMI_WRN__SSP1_SCK			MXS_IOMUX_PAD_NAKED(0, 25, PAD_MUXSEL_1)
+#define MX28_PAD_GPMI_ALE__SSP3_D1			MXS_IOMUX_PAD_NAKED(0, 26, PAD_MUXSEL_1)
+#define MX28_PAD_GPMI_CLE__SSP3_D2			MXS_IOMUX_PAD_NAKED(0, 27, PAD_MUXSEL_1)
+#define MX28_PAD_GPMI_RESETN__SSP3_CMD			MXS_IOMUX_PAD_NAKED(0, 28, PAD_MUXSEL_1)
+
+#define MX28_PAD_LCD_D03__ETM_DA8			MXS_IOMUX_PAD_NAKED(1,  3, PAD_MUXSEL_1)
+#define MX28_PAD_LCD_D04__ETM_DA9			MXS_IOMUX_PAD_NAKED(1,  4, PAD_MUXSEL_1)
+#define MX28_PAD_LCD_D08__ETM_DA3			MXS_IOMUX_PAD_NAKED(1,  8, PAD_MUXSEL_1)
+#define MX28_PAD_LCD_D09__ETM_DA4			MXS_IOMUX_PAD_NAKED(1,  9, PAD_MUXSEL_1)
+#define MX28_PAD_LCD_D20__ENET1_1588_EVENT2_OUT		MXS_IOMUX_PAD_NAKED(1, 20, PAD_MUXSEL_1)
+#define MX28_PAD_LCD_D21__ENET1_1588_EVENT2_IN		MXS_IOMUX_PAD_NAKED(1, 21, PAD_MUXSEL_1)
+#define MX28_PAD_LCD_D22__ENET1_1588_EVENT3_OUT		MXS_IOMUX_PAD_NAKED(1, 22, PAD_MUXSEL_1)
+#define MX28_PAD_LCD_D23__ENET1_1588_EVENT3_IN		MXS_IOMUX_PAD_NAKED(1, 23, PAD_MUXSEL_1)
+#define MX28_PAD_LCD_RD_E__LCD_VSYNC			MXS_IOMUX_PAD_NAKED(1, 24, PAD_MUXSEL_1)
+#define MX28_PAD_LCD_WR_RWN__LCD_HSYNC			MXS_IOMUX_PAD_NAKED(1, 25, PAD_MUXSEL_1)
+#define MX28_PAD_LCD_RS__LCD_DOTCLK			MXS_IOMUX_PAD_NAKED(1, 26, PAD_MUXSEL_1)
+#define MX28_PAD_LCD_CS__LCD_ENABLE			MXS_IOMUX_PAD_NAKED(1, 27, PAD_MUXSEL_1)
+#define MX28_PAD_LCD_VSYNC__SAIF1_SDATA0		MXS_IOMUX_PAD_NAKED(1, 28, PAD_MUXSEL_1)
+#define MX28_PAD_LCD_HSYNC__SAIF1_SDATA1		MXS_IOMUX_PAD_NAKED(1, 29, PAD_MUXSEL_1)
+#define MX28_PAD_LCD_DOTCLK__SAIF1_MCLK			MXS_IOMUX_PAD_NAKED(1, 30, PAD_MUXSEL_1)
+
+#define MX28_PAD_SSP0_DATA4__SSP2_D0			MXS_IOMUX_PAD_NAKED(2,  4, PAD_MUXSEL_1)
+#define MX28_PAD_SSP0_DATA5__SSP2_D3			MXS_IOMUX_PAD_NAKED(2,  5, PAD_MUXSEL_1)
+#define MX28_PAD_SSP0_DATA6__SSP2_CMD			MXS_IOMUX_PAD_NAKED(2,  6, PAD_MUXSEL_1)
+#define MX28_PAD_SSP0_DATA7__SSP2_SCK			MXS_IOMUX_PAD_NAKED(2,  7, PAD_MUXSEL_1)
+#define MX28_PAD_SSP1_SCK__SSP2_D1			MXS_IOMUX_PAD_NAKED(2, 12, PAD_MUXSEL_1)
+#define MX28_PAD_SSP1_CMD__SSP2_D2			MXS_IOMUX_PAD_NAKED(2, 13, PAD_MUXSEL_1)
+#define MX28_PAD_SSP1_DATA0__SSP2_D6			MXS_IOMUX_PAD_NAKED(2, 14, PAD_MUXSEL_1)
+#define MX28_PAD_SSP1_DATA3__SSP2_D7			MXS_IOMUX_PAD_NAKED(2, 15, PAD_MUXSEL_1)
+#define MX28_PAD_SSP2_SCK__AUART2_RX			MXS_IOMUX_PAD_NAKED(2, 16, PAD_MUXSEL_1)
+#define MX28_PAD_SSP2_MOSI__AUART2_TX			MXS_IOMUX_PAD_NAKED(2, 17, PAD_MUXSEL_1)
+#define MX28_PAD_SSP2_MISO__AUART3_RX			MXS_IOMUX_PAD_NAKED(2, 18, PAD_MUXSEL_1)
+#define MX28_PAD_SSP2_SS0__AUART3_TX			MXS_IOMUX_PAD_NAKED(2, 19, PAD_MUXSEL_1)
+#define MX28_PAD_SSP2_SS1__SSP2_D1			MXS_IOMUX_PAD_NAKED(2, 20, PAD_MUXSEL_1)
+#define MX28_PAD_SSP2_SS2__SSP2_D2			MXS_IOMUX_PAD_NAKED(2, 21, PAD_MUXSEL_1)
+#define MX28_PAD_SSP3_SCK__AUART4_TX			MXS_IOMUX_PAD_NAKED(2, 24, PAD_MUXSEL_1)
+#define MX28_PAD_SSP3_MOSI__AUART4_RX			MXS_IOMUX_PAD_NAKED(2, 25, PAD_MUXSEL_1)
+#define MX28_PAD_SSP3_MISO__AUART4_RTS			MXS_IOMUX_PAD_NAKED(2, 26, PAD_MUXSEL_1)
+#define MX28_PAD_SSP3_SS0__AUART4_CTS			MXS_IOMUX_PAD_NAKED(2, 27, PAD_MUXSEL_1)
+
+#define MX28_PAD_AUART0_RX__I2C0_SCL			MXS_IOMUX_PAD_NAKED(3,  0, PAD_MUXSEL_1)
+#define MX28_PAD_AUART0_TX__I2C0_SDA			MXS_IOMUX_PAD_NAKED(3,  1, PAD_MUXSEL_1)
+#define MX28_PAD_AUART0_CTS__AUART4_RX			MXS_IOMUX_PAD_NAKED(3,  2, PAD_MUXSEL_1)
+#define MX28_PAD_AUART0_RTS__AUART4_TX			MXS_IOMUX_PAD_NAKED(3,  3, PAD_MUXSEL_1)
+#define MX28_PAD_AUART1_RX__SSP2_CARD_DETECT		MXS_IOMUX_PAD_NAKED(3,  4, PAD_MUXSEL_1)
+#define MX28_PAD_AUART1_TX__SSP3_CARD_DETECT		MXS_IOMUX_PAD_NAKED(3,  5, PAD_MUXSEL_1)
+#define MX28_PAD_AUART1_CTS__USB0_OVERCURRENT		MXS_IOMUX_PAD_NAKED(3,  6, PAD_MUXSEL_1)
+#define MX28_PAD_AUART1_RTS__USB0_ID			MXS_IOMUX_PAD_NAKED(3,  7, PAD_MUXSEL_1)
+#define MX28_PAD_AUART2_RX__SSP3_D1			MXS_IOMUX_PAD_NAKED(3,  8, PAD_MUXSEL_1)
+#define MX28_PAD_AUART2_TX__SSP3_D2			MXS_IOMUX_PAD_NAKED(3,  9, PAD_MUXSEL_1)
+#define MX28_PAD_AUART2_CTS__I2C1_SCL			MXS_IOMUX_PAD_NAKED(3, 10, PAD_MUXSEL_1)
+#define MX28_PAD_AUART2_RTS__I2C1_SDA			MXS_IOMUX_PAD_NAKED(3, 11, PAD_MUXSEL_1)
+#define MX28_PAD_AUART3_RX__CAN0_TX			MXS_IOMUX_PAD_NAKED(3, 12, PAD_MUXSEL_1)
+#define MX28_PAD_AUART3_TX__CAN0_RX			MXS_IOMUX_PAD_NAKED(3, 13, PAD_MUXSEL_1)
+#define MX28_PAD_AUART3_CTS__CAN1_TX			MXS_IOMUX_PAD_NAKED(3, 14, PAD_MUXSEL_1)
+#define MX28_PAD_AUART3_RTS__CAN1_RX			MXS_IOMUX_PAD_NAKED(3, 15, PAD_MUXSEL_1)
+#define MX28_PAD_PWM0__I2C1_SCL				MXS_IOMUX_PAD_NAKED(3, 16, PAD_MUXSEL_1)
+#define MX28_PAD_PWM1__I2C1_SDA				MXS_IOMUX_PAD_NAKED(3, 17, PAD_MUXSEL_1)
+#define MX28_PAD_PWM2__USB0_ID				MXS_IOMUX_PAD_NAKED(3, 18, PAD_MUXSEL_1)
+#define MX28_PAD_SAIF0_MCLK__PWM_3			MXS_IOMUX_PAD_NAKED(3, 20, PAD_MUXSEL_1)
+#define MX28_PAD_SAIF0_LRCLK__PWM_4			MXS_IOMUX_PAD_NAKED(3, 21, PAD_MUXSEL_1)
+#define MX28_PAD_SAIF0_BITCLK__PWM_5			MXS_IOMUX_PAD_NAKED(3, 22, PAD_MUXSEL_1)
+#define MX28_PAD_SAIF0_SDATA0__PWM_6			MXS_IOMUX_PAD_NAKED(3, 23, PAD_MUXSEL_1)
+#define MX28_PAD_I2C0_SCL__TIMROT_ROTARYA		MXS_IOMUX_PAD_NAKED(3, 24, PAD_MUXSEL_1)
+#define MX28_PAD_I2C0_SDA__TIMROT_ROTARYB		MXS_IOMUX_PAD_NAKED(3, 25, PAD_MUXSEL_1)
+#define MX28_PAD_SAIF1_SDATA0__PWM_7			MXS_IOMUX_PAD_NAKED(3, 26, PAD_MUXSEL_1)
+#define MX28_PAD_LCD_RESET__LCD_VSYNC			MXS_IOMUX_PAD_NAKED(3, 30, PAD_MUXSEL_1)
+
+#define MX28_PAD_ENET0_MDC__GPMI_CE4N			MXS_IOMUX_PAD_NAKED(4,  0, PAD_MUXSEL_1)
+#define MX28_PAD_ENET0_MDIO__GPMI_CE5N			MXS_IOMUX_PAD_NAKED(4,  1, PAD_MUXSEL_1)
+#define MX28_PAD_ENET0_RX_EN__GPMI_CE6N			MXS_IOMUX_PAD_NAKED(4,  2, PAD_MUXSEL_1)
+#define MX28_PAD_ENET0_RXD0__GPMI_CE7N			MXS_IOMUX_PAD_NAKED(4,  3, PAD_MUXSEL_1)
+#define MX28_PAD_ENET0_RXD1__GPMI_READY4		MXS_IOMUX_PAD_NAKED(4,  4, PAD_MUXSEL_1)
+#define MX28_PAD_ENET0_TX_CLK__HSADC_TRIGGER		MXS_IOMUX_PAD_NAKED(4,  5, PAD_MUXSEL_1)
+#define MX28_PAD_ENET0_TX_EN__GPMI_READY5		MXS_IOMUX_PAD_NAKED(4,  6, PAD_MUXSEL_1)
+#define MX28_PAD_ENET0_TXD0__GPMI_READY6		MXS_IOMUX_PAD_NAKED(4,  7, PAD_MUXSEL_1)
+#define MX28_PAD_ENET0_TXD1__GPMI_READY7		MXS_IOMUX_PAD_NAKED(4,  8, PAD_MUXSEL_1)
+#define MX28_PAD_ENET0_RXD2__ENET1_RXD0			MXS_IOMUX_PAD_NAKED(4,  9, PAD_MUXSEL_1)
+#define MX28_PAD_ENET0_RXD3__ENET1_RXD1			MXS_IOMUX_PAD_NAKED(4, 10, PAD_MUXSEL_1)
+#define MX28_PAD_ENET0_TXD2__ENET1_TXD0			MXS_IOMUX_PAD_NAKED(4, 11, PAD_MUXSEL_1)
+#define MX28_PAD_ENET0_TXD3__ENET1_TXD1			MXS_IOMUX_PAD_NAKED(4, 12, PAD_MUXSEL_1)
+#define MX28_PAD_ENET0_RX_CLK__ENET0_RX_ER		MXS_IOMUX_PAD_NAKED(4, 13, PAD_MUXSEL_1)
+#define MX28_PAD_ENET0_COL__ENET1_TX_EN			MXS_IOMUX_PAD_NAKED(4, 14, PAD_MUXSEL_1)
+#define MX28_PAD_ENET0_CRS__ENET1_RX_EN			MXS_IOMUX_PAD_NAKED(4, 15, PAD_MUXSEL_1)
+
+/* MUXSEL_2 */
+#define MX28_PAD_GPMI_CE2N__ENET0_RX_ER			MXS_IOMUX_PAD_NAKED(0, 18, PAD_MUXSEL_2)
+#define MX28_PAD_GPMI_CE3N__SAIF1_MCLK			MXS_IOMUX_PAD_NAKED(0, 19, PAD_MUXSEL_2)
+#define MX28_PAD_GPMI_RDY0__USB0_ID			MXS_IOMUX_PAD_NAKED(0, 20, PAD_MUXSEL_2)
+#define MX28_PAD_GPMI_RDY2__ENET0_TX_ER			MXS_IOMUX_PAD_NAKED(0, 22, PAD_MUXSEL_2)
+#define MX28_PAD_GPMI_RDY3__HSADC_TRIGGER		MXS_IOMUX_PAD_NAKED(0, 23, PAD_MUXSEL_2)
+#define MX28_PAD_GPMI_ALE__SSP3_D4			MXS_IOMUX_PAD_NAKED(0, 26, PAD_MUXSEL_2)
+#define MX28_PAD_GPMI_CLE__SSP3_D5			MXS_IOMUX_PAD_NAKED(0, 27, PAD_MUXSEL_2)
+
+#define MX28_PAD_LCD_D00__ETM_DA0			MXS_IOMUX_PAD_NAKED(1,  0, PAD_MUXSEL_2)
+#define MX28_PAD_LCD_D01__ETM_DA1			MXS_IOMUX_PAD_NAKED(1,  1, PAD_MUXSEL_2)
+#define MX28_PAD_LCD_D02__ETM_DA2			MXS_IOMUX_PAD_NAKED(1,  2, PAD_MUXSEL_2)
+#define MX28_PAD_LCD_D03__ETM_DA3			MXS_IOMUX_PAD_NAKED(1,  3, PAD_MUXSEL_2)
+#define MX28_PAD_LCD_D04__ETM_DA4			MXS_IOMUX_PAD_NAKED(1,  4, PAD_MUXSEL_2)
+#define MX28_PAD_LCD_D05__ETM_DA5			MXS_IOMUX_PAD_NAKED(1,  5, PAD_MUXSEL_2)
+#define MX28_PAD_LCD_D06__ETM_DA6			MXS_IOMUX_PAD_NAKED(1,  6, PAD_MUXSEL_2)
+#define MX28_PAD_LCD_D07__ETM_DA7			MXS_IOMUX_PAD_NAKED(1,  7, PAD_MUXSEL_2)
+#define MX28_PAD_LCD_D08__ETM_DA8			MXS_IOMUX_PAD_NAKED(1,  8, PAD_MUXSEL_2)
+#define MX28_PAD_LCD_D09__ETM_DA9			MXS_IOMUX_PAD_NAKED(1,  9, PAD_MUXSEL_2)
+#define MX28_PAD_LCD_D10__ETM_DA10			MXS_IOMUX_PAD_NAKED(1, 10, PAD_MUXSEL_2)
+#define MX28_PAD_LCD_D11__ETM_DA11			MXS_IOMUX_PAD_NAKED(1, 11, PAD_MUXSEL_2)
+#define MX28_PAD_LCD_D12__ETM_DA12			MXS_IOMUX_PAD_NAKED(1, 12, PAD_MUXSEL_2)
+#define MX28_PAD_LCD_D13__ETM_DA13			MXS_IOMUX_PAD_NAKED(1, 13, PAD_MUXSEL_2)
+#define MX28_PAD_LCD_D14__ETM_DA14			MXS_IOMUX_PAD_NAKED(1, 14, PAD_MUXSEL_2)
+#define MX28_PAD_LCD_D15__ETM_DA15			MXS_IOMUX_PAD_NAKED(1, 15, PAD_MUXSEL_2)
+#define MX28_PAD_LCD_D16__ETM_DA7			MXS_IOMUX_PAD_NAKED(1, 16, PAD_MUXSEL_2)
+#define MX28_PAD_LCD_D17__ETM_DA6			MXS_IOMUX_PAD_NAKED(1, 17, PAD_MUXSEL_2)
+#define MX28_PAD_LCD_D18__ETM_DA5			MXS_IOMUX_PAD_NAKED(1, 18, PAD_MUXSEL_2)
+#define MX28_PAD_LCD_D19__ETM_DA4			MXS_IOMUX_PAD_NAKED(1, 19, PAD_MUXSEL_2)
+#define MX28_PAD_LCD_D20__ETM_DA3			MXS_IOMUX_PAD_NAKED(1, 20, PAD_MUXSEL_2)
+#define MX28_PAD_LCD_D21__ETM_DA2			MXS_IOMUX_PAD_NAKED(1, 21, PAD_MUXSEL_2)
+#define MX28_PAD_LCD_D22__ETM_DA1			MXS_IOMUX_PAD_NAKED(1, 22, PAD_MUXSEL_2)
+#define MX28_PAD_LCD_D23__ETM_DA0			MXS_IOMUX_PAD_NAKED(1, 23, PAD_MUXSEL_2)
+#define MX28_PAD_LCD_RD_E__ETM_TCTL			MXS_IOMUX_PAD_NAKED(1, 24, PAD_MUXSEL_2)
+#define MX28_PAD_LCD_WR_RWN__ETM_TCLK			MXS_IOMUX_PAD_NAKED(1, 25, PAD_MUXSEL_2)
+#define MX28_PAD_LCD_HSYNC__ETM_TCTL			MXS_IOMUX_PAD_NAKED(1, 29, PAD_MUXSEL_2)
+#define MX28_PAD_LCD_DOTCLK__ETM_TCLK			MXS_IOMUX_PAD_NAKED(1, 30, PAD_MUXSEL_2)
+
+#define MX28_PAD_SSP1_SCK__ENET0_1588_EVENT2_OUT	MXS_IOMUX_PAD_NAKED(2, 12, PAD_MUXSEL_2)
+#define MX28_PAD_SSP1_CMD__ENET0_1588_EVENT2_IN		MXS_IOMUX_PAD_NAKED(2, 13, PAD_MUXSEL_2)
+#define MX28_PAD_SSP1_DATA0__ENET0_1588_EVENT3_OUT	MXS_IOMUX_PAD_NAKED(2, 14, PAD_MUXSEL_2)
+#define MX28_PAD_SSP1_DATA3__ENET0_1588_EVENT3_IN	MXS_IOMUX_PAD_NAKED(2, 15, PAD_MUXSEL_2)
+#define MX28_PAD_SSP2_SCK__SAIF0_SDATA1			MXS_IOMUX_PAD_NAKED(2, 16, PAD_MUXSEL_2)
+#define MX28_PAD_SSP2_MOSI__SAIF0_SDATA2		MXS_IOMUX_PAD_NAKED(2, 17, PAD_MUXSEL_2)
+#define MX28_PAD_SSP2_MISO__SAIF1_SDATA1		MXS_IOMUX_PAD_NAKED(2, 18, PAD_MUXSEL_2)
+#define MX28_PAD_SSP2_SS0__SAIF1_SDATA2			MXS_IOMUX_PAD_NAKED(2, 19, PAD_MUXSEL_2)
+#define MX28_PAD_SSP2_SS1__USB1_OVERCURRENT		MXS_IOMUX_PAD_NAKED(2, 20, PAD_MUXSEL_2)
+#define MX28_PAD_SSP2_SS2__USB0_OVERCURRENT		MXS_IOMUX_PAD_NAKED(2, 21, PAD_MUXSEL_2)
+#define MX28_PAD_SSP3_SCK__ENET1_1588_EVENT0_OUT	MXS_IOMUX_PAD_NAKED(2, 24, PAD_MUXSEL_2)
+#define MX28_PAD_SSP3_MOSI__ENET1_1588_EVENT0_IN	MXS_IOMUX_PAD_NAKED(2, 25, PAD_MUXSEL_2)
+#define MX28_PAD_SSP3_MISO__ENET1_1588_EVENT1_OUT	MXS_IOMUX_PAD_NAKED(2, 26, PAD_MUXSEL_2)
+#define MX28_PAD_SSP3_SS0__ENET1_1588_EVENT1_IN		MXS_IOMUX_PAD_NAKED(2, 27, PAD_MUXSEL_2)
+
+#define MX28_PAD_AUART0_RX__DUART_CTS			MXS_IOMUX_PAD_NAKED(3,  0, PAD_MUXSEL_2)
+#define MX28_PAD_AUART0_TX__DUART_RTS			MXS_IOMUX_PAD_NAKED(3,  1, PAD_MUXSEL_2)
+#define MX28_PAD_AUART0_CTS__DUART_RX			MXS_IOMUX_PAD_NAKED(3,  2, PAD_MUXSEL_2)
+#define MX28_PAD_AUART0_RTS__DUART_TX			MXS_IOMUX_PAD_NAKED(3,  3, PAD_MUXSEL_2)
+#define MX28_PAD_AUART1_RX__PWM_0			MXS_IOMUX_PAD_NAKED(3,  4, PAD_MUXSEL_2)
+#define MX28_PAD_AUART1_TX__PWM_1			MXS_IOMUX_PAD_NAKED(3,  5, PAD_MUXSEL_2)
+#define MX28_PAD_AUART1_CTS__TIMROT_ROTARYA		MXS_IOMUX_PAD_NAKED(3,  6, PAD_MUXSEL_2)
+#define MX28_PAD_AUART1_RTS__TIMROT_ROTARYB		MXS_IOMUX_PAD_NAKED(3,  7, PAD_MUXSEL_2)
+#define MX28_PAD_AUART2_RX__SSP3_D4			MXS_IOMUX_PAD_NAKED(3,  8, PAD_MUXSEL_2)
+#define MX28_PAD_AUART2_TX__SSP3_D5			MXS_IOMUX_PAD_NAKED(3,  9, PAD_MUXSEL_2)
+#define MX28_PAD_AUART2_CTS__SAIF1_BITCLK		MXS_IOMUX_PAD_NAKED(3, 10, PAD_MUXSEL_2)
+#define MX28_PAD_AUART2_RTS__SAIF1_LRCLK		MXS_IOMUX_PAD_NAKED(3, 11, PAD_MUXSEL_2)
+#define MX28_PAD_AUART3_RX__ENET0_1588_EVENT0_OUT	MXS_IOMUX_PAD_NAKED(3, 12, PAD_MUXSEL_2)
+#define MX28_PAD_AUART3_TX__ENET0_1588_EVENT0_IN	MXS_IOMUX_PAD_NAKED(3, 13, PAD_MUXSEL_2)
+#define MX28_PAD_AUART3_CTS__ENET0_1588_EVENT1_OUT	MXS_IOMUX_PAD_NAKED(3, 14, PAD_MUXSEL_2)
+#define MX28_PAD_AUART3_RTS__ENET0_1588_EVENT1_IN	MXS_IOMUX_PAD_NAKED(3, 15, PAD_MUXSEL_2)
+#define MX28_PAD_PWM0__DUART_RX				MXS_IOMUX_PAD_NAKED(3, 16, PAD_MUXSEL_2)
+#define MX28_PAD_PWM1__DUART_TX				MXS_IOMUX_PAD_NAKED(3, 17, PAD_MUXSEL_2)
+#define MX28_PAD_PWM2__USB1_OVERCURRENT			MXS_IOMUX_PAD_NAKED(3, 18, PAD_MUXSEL_2)
+#define MX28_PAD_SAIF0_MCLK__AUART4_CTS			MXS_IOMUX_PAD_NAKED(3, 20, PAD_MUXSEL_2)
+#define MX28_PAD_SAIF0_LRCLK__AUART4_RTS		MXS_IOMUX_PAD_NAKED(3, 21, PAD_MUXSEL_2)
+#define MX28_PAD_SAIF0_BITCLK__AUART4_RX		MXS_IOMUX_PAD_NAKED(3, 22, PAD_MUXSEL_2)
+#define MX28_PAD_SAIF0_SDATA0__AUART4_TX		MXS_IOMUX_PAD_NAKED(3, 23, PAD_MUXSEL_2)
+#define MX28_PAD_I2C0_SCL__DUART_RX			MXS_IOMUX_PAD_NAKED(3, 24, PAD_MUXSEL_2)
+#define MX28_PAD_I2C0_SDA__DUART_TX			MXS_IOMUX_PAD_NAKED(3, 25, PAD_MUXSEL_2)
+#define MX28_PAD_SAIF1_SDATA0__SAIF0_SDATA1		MXS_IOMUX_PAD_NAKED(3, 26, PAD_MUXSEL_2)
+#define MX28_PAD_SPDIF__ENET1_RX_ER			MXS_IOMUX_PAD_NAKED(3, 27, PAD_MUXSEL_2)
+
+#define MX28_PAD_ENET0_MDC__SAIF0_SDATA1		MXS_IOMUX_PAD_NAKED(4,  0, PAD_MUXSEL_2)
+#define MX28_PAD_ENET0_MDIO__SAIF0_SDATA2		MXS_IOMUX_PAD_NAKED(4,  1, PAD_MUXSEL_2)
+#define MX28_PAD_ENET0_RX_EN__SAIF1_SDATA1		MXS_IOMUX_PAD_NAKED(4,  2, PAD_MUXSEL_2)
+#define MX28_PAD_ENET0_RXD0__SAIF1_SDATA2		MXS_IOMUX_PAD_NAKED(4,  3, PAD_MUXSEL_2)
+#define MX28_PAD_ENET0_TX_CLK__ENET0_1588_EVENT2_OUT	MXS_IOMUX_PAD_NAKED(4,  5, PAD_MUXSEL_2)
+#define MX28_PAD_ENET0_RXD2__ENET0_1588_EVENT0_OUT	MXS_IOMUX_PAD_NAKED(4,  9, PAD_MUXSEL_2)
+#define MX28_PAD_ENET0_RXD3__ENET0_1588_EVENT0_IN	MXS_IOMUX_PAD_NAKED(4, 10, PAD_MUXSEL_2)
+#define MX28_PAD_ENET0_TXD2__ENET0_1588_EVENT1_OUT	MXS_IOMUX_PAD_NAKED(4, 11, PAD_MUXSEL_2)
+#define MX28_PAD_ENET0_TXD3__ENET0_1588_EVENT1_IN	MXS_IOMUX_PAD_NAKED(4, 12, PAD_MUXSEL_2)
+#define MX28_PAD_ENET0_RX_CLK__ENET0_1588_EVENT2_IN	MXS_IOMUX_PAD_NAKED(4, 13, PAD_MUXSEL_2)
+#define MX28_PAD_ENET0_COL__ENET0_1588_EVENT3_OUT	MXS_IOMUX_PAD_NAKED(4, 14, PAD_MUXSEL_2)
+#define MX28_PAD_ENET0_CRS__ENET0_1588_EVENT3_IN	MXS_IOMUX_PAD_NAKED(4, 15, PAD_MUXSEL_2)
+
+/* MUXSEL_GPIO */
+#define MX28_PAD_GPMI_D00__GPIO_0_0			MXS_IOMUX_PAD_NAKED(0,  0, PAD_MUXSEL_GPIO)
+#define MX28_PAD_GPMI_D01__GPIO_0_1			MXS_IOMUX_PAD_NAKED(0,  1, PAD_MUXSEL_GPIO)
+#define MX28_PAD_GPMI_D02__GPIO_0_2			MXS_IOMUX_PAD_NAKED(0,  2, PAD_MUXSEL_GPIO)
+#define MX28_PAD_GPMI_D03__GPIO_0_3			MXS_IOMUX_PAD_NAKED(0,  3, PAD_MUXSEL_GPIO)
+#define MX28_PAD_GPMI_D04__GPIO_0_4			MXS_IOMUX_PAD_NAKED(0,  4, PAD_MUXSEL_GPIO)
+#define MX28_PAD_GPMI_D05__GPIO_0_5			MXS_IOMUX_PAD_NAKED(0,  5, PAD_MUXSEL_GPIO)
+#define MX28_PAD_GPMI_D06__GPIO_0_6			MXS_IOMUX_PAD_NAKED(0,  6, PAD_MUXSEL_GPIO)
+#define MX28_PAD_GPMI_D07__GPIO_0_7			MXS_IOMUX_PAD_NAKED(0,  7, PAD_MUXSEL_GPIO)
+#define MX28_PAD_GPMI_CE0N__GPIO_0_16			MXS_IOMUX_PAD_NAKED(0, 16, PAD_MUXSEL_GPIO)
+#define MX28_PAD_GPMI_CE1N__GPIO_0_17			MXS_IOMUX_PAD_NAKED(0, 17, PAD_MUXSEL_GPIO)
+#define MX28_PAD_GPMI_CE2N__GPIO_0_18			MXS_IOMUX_PAD_NAKED(0, 18, PAD_MUXSEL_GPIO)
+#define MX28_PAD_GPMI_CE3N__GPIO_0_19			MXS_IOMUX_PAD_NAKED(0, 19, PAD_MUXSEL_GPIO)
+#define MX28_PAD_GPMI_RDY0__GPIO_0_20			MXS_IOMUX_PAD_NAKED(0, 20, PAD_MUXSEL_GPIO)
+#define MX28_PAD_GPMI_RDY1__GPIO_0_21			MXS_IOMUX_PAD_NAKED(0, 21, PAD_MUXSEL_GPIO)
+#define MX28_PAD_GPMI_RDY2__GPIO_0_22			MXS_IOMUX_PAD_NAKED(0, 22, PAD_MUXSEL_GPIO)
+#define MX28_PAD_GPMI_RDY3__GPIO_0_23			MXS_IOMUX_PAD_NAKED(0, 23, PAD_MUXSEL_GPIO)
+#define MX28_PAD_GPMI_RDN__GPIO_0_24			MXS_IOMUX_PAD_NAKED(0, 24, PAD_MUXSEL_GPIO)
+#define MX28_PAD_GPMI_WRN__GPIO_0_25			MXS_IOMUX_PAD_NAKED(0, 25, PAD_MUXSEL_GPIO)
+#define MX28_PAD_GPMI_ALE__GPIO_0_26			MXS_IOMUX_PAD_NAKED(0, 26, PAD_MUXSEL_GPIO)
+#define MX28_PAD_GPMI_CLE__GPIO_0_27			MXS_IOMUX_PAD_NAKED(0, 27, PAD_MUXSEL_GPIO)
+#define MX28_PAD_GPMI_RESETN__GPIO_0_28			MXS_IOMUX_PAD_NAKED(0, 28, PAD_MUXSEL_GPIO)
+
+#define MX28_PAD_LCD_D00__GPIO_1_0			MXS_IOMUX_PAD_NAKED(1,  0, PAD_MUXSEL_GPIO)
+#define MX28_PAD_LCD_D01__GPIO_1_1			MXS_IOMUX_PAD_NAKED(1,  1, PAD_MUXSEL_GPIO)
+#define MX28_PAD_LCD_D02__GPIO_1_2			MXS_IOMUX_PAD_NAKED(1,  2, PAD_MUXSEL_GPIO)
+#define MX28_PAD_LCD_D03__GPIO_1_3			MXS_IOMUX_PAD_NAKED(1,  3, PAD_MUXSEL_GPIO)
+#define MX28_PAD_LCD_D04__GPIO_1_4			MXS_IOMUX_PAD_NAKED(1,  4, PAD_MUXSEL_GPIO)
+#define MX28_PAD_LCD_D05__GPIO_1_5			MXS_IOMUX_PAD_NAKED(1,  5, PAD_MUXSEL_GPIO)
+#define MX28_PAD_LCD_D06__GPIO_1_6			MXS_IOMUX_PAD_NAKED(1,  6, PAD_MUXSEL_GPIO)
+#define MX28_PAD_LCD_D07__GPIO_1_7			MXS_IOMUX_PAD_NAKED(1,  7, PAD_MUXSEL_GPIO)
+#define MX28_PAD_LCD_D08__GPIO_1_8			MXS_IOMUX_PAD_NAKED(1,  8, PAD_MUXSEL_GPIO)
+#define MX28_PAD_LCD_D09__GPIO_1_9			MXS_IOMUX_PAD_NAKED(1,  9, PAD_MUXSEL_GPIO)
+#define MX28_PAD_LCD_D10__GPIO_1_10			MXS_IOMUX_PAD_NAKED(1, 10, PAD_MUXSEL_GPIO)
+#define MX28_PAD_LCD_D11__GPIO_1_11			MXS_IOMUX_PAD_NAKED(1, 11, PAD_MUXSEL_GPIO)
+#define MX28_PAD_LCD_D12__GPIO_1_12			MXS_IOMUX_PAD_NAKED(1, 12, PAD_MUXSEL_GPIO)
+#define MX28_PAD_LCD_D13__GPIO_1_13			MXS_IOMUX_PAD_NAKED(1, 13, PAD_MUXSEL_GPIO)
+#define MX28_PAD_LCD_D14__GPIO_1_14			MXS_IOMUX_PAD_NAKED(1, 14, PAD_MUXSEL_GPIO)
+#define MX28_PAD_LCD_D15__GPIO_1_15			MXS_IOMUX_PAD_NAKED(1, 15, PAD_MUXSEL_GPIO)
+#define MX28_PAD_LCD_D16__GPIO_1_16			MXS_IOMUX_PAD_NAKED(1, 16, PAD_MUXSEL_GPIO)
+#define MX28_PAD_LCD_D17__GPIO_1_17			MXS_IOMUX_PAD_NAKED(1, 17, PAD_MUXSEL_GPIO)
+#define MX28_PAD_LCD_D18__GPIO_1_18			MXS_IOMUX_PAD_NAKED(1, 18, PAD_MUXSEL_GPIO)
+#define MX28_PAD_LCD_D19__GPIO_1_19			MXS_IOMUX_PAD_NAKED(1, 19, PAD_MUXSEL_GPIO)
+#define MX28_PAD_LCD_D20__GPIO_1_20			MXS_IOMUX_PAD_NAKED(1, 20, PAD_MUXSEL_GPIO)
+#define MX28_PAD_LCD_D21__GPIO_1_21			MXS_IOMUX_PAD_NAKED(1, 21, PAD_MUXSEL_GPIO)
+#define MX28_PAD_LCD_D22__GPIO_1_22			MXS_IOMUX_PAD_NAKED(1, 22, PAD_MUXSEL_GPIO)
+#define MX28_PAD_LCD_D23__GPIO_1_23			MXS_IOMUX_PAD_NAKED(1, 23, PAD_MUXSEL_GPIO)
+#define MX28_PAD_LCD_RD_E__GPIO_1_24			MXS_IOMUX_PAD_NAKED(1, 24, PAD_MUXSEL_GPIO)
+#define MX28_PAD_LCD_WR_RWN__GPIO_1_25			MXS_IOMUX_PAD_NAKED(1, 25, PAD_MUXSEL_GPIO)
+#define MX28_PAD_LCD_RS__GPIO_1_26			MXS_IOMUX_PAD_NAKED(1, 26, PAD_MUXSEL_GPIO)
+#define MX28_PAD_LCD_CS__GPIO_1_27			MXS_IOMUX_PAD_NAKED(1, 27, PAD_MUXSEL_GPIO)
+#define MX28_PAD_LCD_VSYNC__GPIO_1_28			MXS_IOMUX_PAD_NAKED(1, 28, PAD_MUXSEL_GPIO)
+#define MX28_PAD_LCD_HSYNC__GPIO_1_29			MXS_IOMUX_PAD_NAKED(1, 29, PAD_MUXSEL_GPIO)
+#define MX28_PAD_LCD_DOTCLK__GPIO_1_30			MXS_IOMUX_PAD_NAKED(1, 30, PAD_MUXSEL_GPIO)
+#define MX28_PAD_LCD_ENABLE__GPIO_1_31			MXS_IOMUX_PAD_NAKED(1, 31, PAD_MUXSEL_GPIO)
+
+#define MX28_PAD_SSP0_DATA0__GPIO_2_0			MXS_IOMUX_PAD_NAKED(2,  0, PAD_MUXSEL_GPIO)
+#define MX28_PAD_SSP0_DATA1__GPIO_2_1			MXS_IOMUX_PAD_NAKED(2,  1, PAD_MUXSEL_GPIO)
+#define MX28_PAD_SSP0_DATA2__GPIO_2_2			MXS_IOMUX_PAD_NAKED(2,  2, PAD_MUXSEL_GPIO)
+#define MX28_PAD_SSP0_DATA3__GPIO_2_3			MXS_IOMUX_PAD_NAKED(2,  3, PAD_MUXSEL_GPIO)
+#define MX28_PAD_SSP0_DATA4__GPIO_2_4			MXS_IOMUX_PAD_NAKED(2,  4, PAD_MUXSEL_GPIO)
+#define MX28_PAD_SSP0_DATA5__GPIO_2_5			MXS_IOMUX_PAD_NAKED(2,  5, PAD_MUXSEL_GPIO)
+#define MX28_PAD_SSP0_DATA6__GPIO_2_6			MXS_IOMUX_PAD_NAKED(2,  6, PAD_MUXSEL_GPIO)
+#define MX28_PAD_SSP0_DATA7__GPIO_2_7			MXS_IOMUX_PAD_NAKED(2,  7, PAD_MUXSEL_GPIO)
+#define MX28_PAD_SSP0_CMD__GPIO_2_8			MXS_IOMUX_PAD_NAKED(2,  8, PAD_MUXSEL_GPIO)
+#define MX28_PAD_SSP0_DETECT__GPIO_2_9			MXS_IOMUX_PAD_NAKED(2,  9, PAD_MUXSEL_GPIO)
+#define MX28_PAD_SSP0_SCK__GPIO_2_10			MXS_IOMUX_PAD_NAKED(2, 10, PAD_MUXSEL_GPIO)
+#define MX28_PAD_SSP1_SCK__GPIO_2_12			MXS_IOMUX_PAD_NAKED(2, 12, PAD_MUXSEL_GPIO)
+#define MX28_PAD_SSP1_CMD__GPIO_2_13			MXS_IOMUX_PAD_NAKED(2, 13, PAD_MUXSEL_GPIO)
+#define MX28_PAD_SSP1_DATA0__GPIO_2_14			MXS_IOMUX_PAD_NAKED(2, 14, PAD_MUXSEL_GPIO)
+#define MX28_PAD_SSP1_DATA3__GPIO_2_15			MXS_IOMUX_PAD_NAKED(2, 15, PAD_MUXSEL_GPIO)
+#define MX28_PAD_SSP2_SCK__GPIO_2_16			MXS_IOMUX_PAD_NAKED(2, 16, PAD_MUXSEL_GPIO)
+#define MX28_PAD_SSP2_MOSI__GPIO_2_17			MXS_IOMUX_PAD_NAKED(2, 17, PAD_MUXSEL_GPIO)
+#define MX28_PAD_SSP2_MISO__GPIO_2_18			MXS_IOMUX_PAD_NAKED(2, 18, PAD_MUXSEL_GPIO)
+#define MX28_PAD_SSP2_SS0__GPIO_2_19			MXS_IOMUX_PAD_NAKED(2, 19, PAD_MUXSEL_GPIO)
+#define MX28_PAD_SSP2_SS1__GPIO_2_20			MXS_IOMUX_PAD_NAKED(2, 20, PAD_MUXSEL_GPIO)
+#define MX28_PAD_SSP2_SS2__GPIO_2_21			MXS_IOMUX_PAD_NAKED(2, 21, PAD_MUXSEL_GPIO)
+#define MX28_PAD_SSP3_SCK__GPIO_2_24			MXS_IOMUX_PAD_NAKED(2, 24, PAD_MUXSEL_GPIO)
+#define MX28_PAD_SSP3_MOSI__GPIO_2_25			MXS_IOMUX_PAD_NAKED(2, 25, PAD_MUXSEL_GPIO)
+#define MX28_PAD_SSP3_MISO__GPIO_2_26			MXS_IOMUX_PAD_NAKED(2, 26, PAD_MUXSEL_GPIO)
+#define MX28_PAD_SSP3_SS0__GPIO_2_27			MXS_IOMUX_PAD_NAKED(2, 27, PAD_MUXSEL_GPIO)
+
+#define MX28_PAD_AUART0_RX__GPIO_3_0			MXS_IOMUX_PAD_NAKED(3,  0, PAD_MUXSEL_GPIO)
+#define MX28_PAD_AUART0_TX__GPIO_3_1			MXS_IOMUX_PAD_NAKED(3,  1, PAD_MUXSEL_GPIO)
+#define MX28_PAD_AUART0_CTS__GPIO_3_2			MXS_IOMUX_PAD_NAKED(3,  2, PAD_MUXSEL_GPIO)
+#define MX28_PAD_AUART0_RTS__GPIO_3_3			MXS_IOMUX_PAD_NAKED(3,  3, PAD_MUXSEL_GPIO)
+#define MX28_PAD_AUART1_RX__GPIO_3_4			MXS_IOMUX_PAD_NAKED(3,  4, PAD_MUXSEL_GPIO)
+#define MX28_PAD_AUART1_TX__GPIO_3_5			MXS_IOMUX_PAD_NAKED(3,  5, PAD_MUXSEL_GPIO)
+#define MX28_PAD_AUART1_CTS__GPIO_3_6			MXS_IOMUX_PAD_NAKED(3,  6, PAD_MUXSEL_GPIO)
+#define MX28_PAD_AUART1_RTS__GPIO_3_7			MXS_IOMUX_PAD_NAKED(3,  7, PAD_MUXSEL_GPIO)
+#define MX28_PAD_AUART2_RX__GPIO_3_8			MXS_IOMUX_PAD_NAKED(3,  8, PAD_MUXSEL_GPIO)
+#define MX28_PAD_AUART2_TX__GPIO_3_9			MXS_IOMUX_PAD_NAKED(3,  9, PAD_MUXSEL_GPIO)
+#define MX28_PAD_AUART2_CTS__GPIO_3_10			MXS_IOMUX_PAD_NAKED(3, 10, PAD_MUXSEL_GPIO)
+#define MX28_PAD_AUART2_RTS__GPIO_3_11			MXS_IOMUX_PAD_NAKED(3, 11, PAD_MUXSEL_GPIO)
+#define MX28_PAD_AUART3_RX__GPIO_3_12			MXS_IOMUX_PAD_NAKED(3, 12, PAD_MUXSEL_GPIO)
+#define MX28_PAD_AUART3_TX__GPIO_3_13			MXS_IOMUX_PAD_NAKED(3, 13, PAD_MUXSEL_GPIO)
+#define MX28_PAD_AUART3_CTS__GPIO_3_14			MXS_IOMUX_PAD_NAKED(3, 14, PAD_MUXSEL_GPIO)
+#define MX28_PAD_AUART3_RTS__GPIO_3_15			MXS_IOMUX_PAD_NAKED(3, 15, PAD_MUXSEL_GPIO)
+#define MX28_PAD_PWM0__GPIO_3_16			MXS_IOMUX_PAD_NAKED(3, 16, PAD_MUXSEL_GPIO)
+#define MX28_PAD_PWM1__GPIO_3_17			MXS_IOMUX_PAD_NAKED(3, 17, PAD_MUXSEL_GPIO)
+#define MX28_PAD_PWM2__GPIO_3_18			MXS_IOMUX_PAD_NAKED(3, 18, PAD_MUXSEL_GPIO)
+#define MX28_PAD_SAIF0_MCLK__GPIO_3_20			MXS_IOMUX_PAD_NAKED(3, 20, PAD_MUXSEL_GPIO)
+#define MX28_PAD_SAIF0_LRCLK__GPIO_3_21			MXS_IOMUX_PAD_NAKED(3, 21, PAD_MUXSEL_GPIO)
+#define MX28_PAD_SAIF0_BITCLK__GPIO_3_22		MXS_IOMUX_PAD_NAKED(3, 22, PAD_MUXSEL_GPIO)
+#define MX28_PAD_SAIF0_SDATA0__GPIO_3_23		MXS_IOMUX_PAD_NAKED(3, 23, PAD_MUXSEL_GPIO)
+#define MX28_PAD_I2C0_SCL__GPIO_3_24			MXS_IOMUX_PAD_NAKED(3, 24, PAD_MUXSEL_GPIO)
+#define MX28_PAD_I2C0_SDA__GPIO_3_25			MXS_IOMUX_PAD_NAKED(3, 25, PAD_MUXSEL_GPIO)
+#define MX28_PAD_SAIF1_SDATA0__GPIO_3_26		MXS_IOMUX_PAD_NAKED(3, 26, PAD_MUXSEL_GPIO)
+#define MX28_PAD_SPDIF__GPIO_3_27			MXS_IOMUX_PAD_NAKED(3, 27, PAD_MUXSEL_GPIO)
+#define MX28_PAD_PWM3__GPIO_3_28			MXS_IOMUX_PAD_NAKED(3, 28, PAD_MUXSEL_GPIO)
+#define MX28_PAD_PWM4__GPIO_3_29			MXS_IOMUX_PAD_NAKED(3, 29, PAD_MUXSEL_GPIO)
+#define MX28_PAD_LCD_RESET__GPIO_3_30			MXS_IOMUX_PAD_NAKED(3, 30, PAD_MUXSEL_GPIO)
+
+#define MX28_PAD_ENET0_MDC__GPIO_4_0			MXS_IOMUX_PAD_NAKED(4,  0, PAD_MUXSEL_GPIO)
+#define MX28_PAD_ENET0_MDIO__GPIO_4_1			MXS_IOMUX_PAD_NAKED(4,  1, PAD_MUXSEL_GPIO)
+#define MX28_PAD_ENET0_RX_EN__GPIO_4_2			MXS_IOMUX_PAD_NAKED(4,  2, PAD_MUXSEL_GPIO)
+#define MX28_PAD_ENET0_RXD0__GPIO_4_3			MXS_IOMUX_PAD_NAKED(4,  3, PAD_MUXSEL_GPIO)
+#define MX28_PAD_ENET0_RXD1__GPIO_4_4			MXS_IOMUX_PAD_NAKED(4,  4, PAD_MUXSEL_GPIO)
+#define MX28_PAD_ENET0_TX_CLK__GPIO_4_5			MXS_IOMUX_PAD_NAKED(4,  5, PAD_MUXSEL_GPIO)
+#define MX28_PAD_ENET0_TX_EN__GPIO_4_6			MXS_IOMUX_PAD_NAKED(4,  6, PAD_MUXSEL_GPIO)
+#define MX28_PAD_ENET0_TXD0__GPIO_4_7			MXS_IOMUX_PAD_NAKED(4,  7, PAD_MUXSEL_GPIO)
+#define MX28_PAD_ENET0_TXD1__GPIO_4_8			MXS_IOMUX_PAD_NAKED(4,  8, PAD_MUXSEL_GPIO)
+#define MX28_PAD_ENET0_RXD2__GPIO_4_9			MXS_IOMUX_PAD_NAKED(4,  9, PAD_MUXSEL_GPIO)
+#define MX28_PAD_ENET0_RXD3__GPIO_4_10			MXS_IOMUX_PAD_NAKED(4, 10, PAD_MUXSEL_GPIO)
+#define MX28_PAD_ENET0_TXD2__GPIO_4_11			MXS_IOMUX_PAD_NAKED(4, 11, PAD_MUXSEL_GPIO)
+#define MX28_PAD_ENET0_TXD3__GPIO_4_12			MXS_IOMUX_PAD_NAKED(4, 12, PAD_MUXSEL_GPIO)
+#define MX28_PAD_ENET0_RX_CLK__GPIO_4_13		MXS_IOMUX_PAD_NAKED(4, 13, PAD_MUXSEL_GPIO)
+#define MX28_PAD_ENET0_COL__GPIO_4_14			MXS_IOMUX_PAD_NAKED(4, 14, PAD_MUXSEL_GPIO)
+#define MX28_PAD_ENET0_CRS__GPIO_4_15			MXS_IOMUX_PAD_NAKED(4, 15, PAD_MUXSEL_GPIO)
+#define MX28_PAD_ENET_CLK__GPIO_4_16			MXS_IOMUX_PAD_NAKED(4, 16, PAD_MUXSEL_GPIO)
+#define MX28_PAD_JTAG_RTCK__GPIO_4_20			MXS_IOMUX_PAD_NAKED(4, 20, PAD_MUXSEL_GPIO)
+
+#endif /* __MACH_IOMUX_MX28_H__ */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mxs/include/mach/irqs.h linux-libre-2.6.38-gnu1/arch/arm/mach-mxs/include/mach/irqs.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mxs/include/mach/irqs.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mxs/include/mach/irqs.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,32 @@
+/*
+ *  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 __MACH_MXS_IRQS_H__
+#define __MACH_MXS_IRQS_H__
+
+#define MXS_INTERNAL_IRQS	128
+
+#define MXS_GPIO_IRQ_START	MXS_INTERNAL_IRQS
+
+/* the maximum for MXS-based */
+#define MXS_GPIO_IRQS		(32 * 5)
+
+/*
+ * The next 16 interrupts are for board specific purposes.  Since
+ * the kernel can only run on one machine at a time, we can re-use
+ * these.  If you need more, increase MXS_BOARD_IRQS, but keep it
+ * within sensible limits.
+ */
+#define MXS_BOARD_IRQ_START	(MXS_GPIO_IRQ_START + MXS_GPIO_IRQS)
+#define MXS_BOARD_IRQS		16
+
+#define NR_IRQS			(MXS_BOARD_IRQ_START + MXS_BOARD_IRQS)
+
+#endif /* __MACH_MXS_IRQS_H__ */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mxs/include/mach/memory.h linux-libre-2.6.38-gnu1/arch/arm/mach-mxs/include/mach/memory.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mxs/include/mach/memory.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mxs/include/mach/memory.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,24 @@
+/*
+ * 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-2.6.37-gnu1/arch/arm/mach-mxs/include/mach/mx23.h linux-libre-2.6.38-gnu1/arch/arm/mach-mxs/include/mach/mx23.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mxs/include/mach/mx23.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mxs/include/mach/mx23.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,145 @@
+/*
+ * 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_MX23_H__
+#define __MACH_MX23_H__
+
+#include <mach/mxs.h>
+
+/*
+ * OCRAM
+ */
+#define MX23_OCRAM_BASE_ADDR		0x00000000
+#define MX23_OCRAM_SIZE			SZ_32K
+
+/*
+ * IO
+ */
+#define MX23_IO_BASE_ADDR		0x80000000
+#define MX23_IO_SIZE			SZ_1M
+
+#define MX23_ICOLL_BASE_ADDR		(MX23_IO_BASE_ADDR + 0x000000)
+#define MX23_APBH_DMA_BASE_ADDR		(MX23_IO_BASE_ADDR + 0x004000)
+#define MX23_BCH_BASE_ADDR		(MX23_IO_BASE_ADDR + 0x00a000)
+#define MX23_GPMI_BASE_ADDR		(MX23_IO_BASE_ADDR + 0x00c000)
+#define MX23_SSP1_BASE_ADDR		(MX23_IO_BASE_ADDR + 0x010000)
+#define MX23_PINCTRL_BASE_ADDR		(MX23_IO_BASE_ADDR + 0x018000)
+#define MX23_DIGCTL_BASE_ADDR		(MX23_IO_BASE_ADDR + 0x01c000)
+#define MX23_ETM_BASE_ADDR		(MX23_IO_BASE_ADDR + 0x020000)
+#define MX23_APBX_DMA_BASE_ADDR		(MX23_IO_BASE_ADDR + 0x024000)
+#define MX23_DCP_BASE_ADDR		(MX23_IO_BASE_ADDR + 0x028000)
+#define MX23_PXP_BASE_ADDR		(MX23_IO_BASE_ADDR + 0x02a000)
+#define MX23_OCOTP_BASE_ADDR		(MX23_IO_BASE_ADDR + 0x02c000)
+#define MX23_AXI_AHB0_BASE_ADDR		(MX23_IO_BASE_ADDR + 0x02e000)
+#define MX23_LCDIF_BASE_ADDR		(MX23_IO_BASE_ADDR + 0x030000)
+#define MX23_SSP2_BASE_ADDR		(MX23_IO_BASE_ADDR + 0x034000)
+#define MX23_TVENC_BASE_ADDR		(MX23_IO_BASE_ADDR + 0x038000)
+#define MX23_CLKCTRL_BASE_ADDR		(MX23_IO_BASE_ADDR + 0x040000)
+#define MX23_SAIF0_BASE_ADDR		(MX23_IO_BASE_ADDR + 0x042000)
+#define MX23_POWER_BASE_ADDR		(MX23_IO_BASE_ADDR + 0x044000)
+#define MX23_SAIF1_BASE_ADDR		(MX23_IO_BASE_ADDR + 0x046000)
+#define MX23_AUDIOOUT_BASE_ADDR		(MX23_IO_BASE_ADDR + 0x048000)
+#define MX23_AUDIOIN_BASE_ADDR		(MX23_IO_BASE_ADDR + 0x04c000)
+#define MX23_LRADC_BASE_ADDR		(MX23_IO_BASE_ADDR + 0x050000)
+#define MX23_SPDIF_BASE_ADDR		(MX23_IO_BASE_ADDR + 0x054000)
+#define MX23_I2C0_BASE_ADDR		(MX23_IO_BASE_ADDR + 0x058000)
+#define MX23_RTC_BASE_ADDR		(MX23_IO_BASE_ADDR + 0x05c000)
+#define MX23_PWM_BASE_ADDR		(MX23_IO_BASE_ADDR + 0x064000)
+#define MX23_TIMROT_BASE_ADDR		(MX23_IO_BASE_ADDR + 0x068000)
+#define MX23_AUART1_BASE_ADDR		(MX23_IO_BASE_ADDR + 0x06c000)
+#define MX23_AUART2_BASE_ADDR		(MX23_IO_BASE_ADDR + 0x06e000)
+#define MX23_DUART_BASE_ADDR		(MX23_IO_BASE_ADDR + 0x070000)
+#define MX23_USBPHY_BASE_ADDR		(MX23_IO_BASE_ADDR + 0x07c000)
+#define MX23_USBCTRL_BASE_ADDR		(MX23_IO_BASE_ADDR + 0x080000)
+#define MX23_DRAM_BASE_ADDR		(MX23_IO_BASE_ADDR + 0x0e0000)
+
+#define MX23_IO_P2V(x)			MXS_IO_P2V(x)
+#define MX23_IO_ADDRESS(x)		IOMEM(MX23_IO_P2V(x))
+
+/*
+ * IRQ
+ */
+#define MX23_INT_DUART			0
+#define MX23_INT_COMMS_RX		1
+#define MX23_INT_COMMS_TX		1
+#define MX23_INT_SSP2_ERROR		2
+#define MX23_INT_VDD5V			3
+#define MX23_INT_HEADPHONE_SHORT	4
+#define MX23_INT_DAC_DMA		5
+#define MX23_INT_DAC_ERROR		6
+#define MX23_INT_ADC_DMA		7
+#define MX23_INT_ADC_ERROR		8
+#define MX23_INT_SPDIF_DMA		9
+#define MX23_INT_SAIF2_DMA		9
+#define MX23_INT_SPDIF_ERROR		10
+#define MX23_INT_SAIF1_IRQ		10
+#define MX23_INT_SAIF2_IRQ		10
+#define MX23_INT_USB_CTRL		11
+#define MX23_INT_USB_WAKEUP		12
+#define MX23_INT_GPMI_DMA		13
+#define MX23_INT_SSP1_DMA		14
+#define MX23_INT_SSP_ERROR		15
+#define MX23_INT_GPIO0			16
+#define MX23_INT_GPIO1			17
+#define MX23_INT_GPIO2			18
+#define MX23_INT_SAIF1_DMA		19
+#define MX23_INT_SSP2_DMA		20
+#define MX23_INT_ECC8_IRQ		21
+#define MX23_INT_RTC_ALARM		22
+#define MX23_INT_UARTAPP_TX_DMA		23
+#define MX23_INT_UARTAPP_INTERNAL	24
+#define MX23_INT_UARTAPP_RX_DMA		25
+#define MX23_INT_I2C_DMA		26
+#define MX23_INT_I2C_ERROR		27
+#define MX23_INT_TIMER0			28
+#define MX23_INT_TIMER1			29
+#define MX23_INT_TIMER2			30
+#define MX23_INT_TIMER3			31
+#define MX23_INT_BATT_BRNOUT		32
+#define MX23_INT_VDDD_BRNOUT		33
+#define MX23_INT_VDDIO_BRNOUT		34
+#define MX23_INT_VDD18_BRNOUT		35
+#define MX23_INT_TOUCH_DETECT		36
+#define MX23_INT_LRADC_CH0		37
+#define MX23_INT_LRADC_CH1		38
+#define MX23_INT_LRADC_CH2		39
+#define MX23_INT_LRADC_CH3		40
+#define MX23_INT_LRADC_CH4		41
+#define MX23_INT_LRADC_CH5		42
+#define MX23_INT_LRADC_CH6		43
+#define MX23_INT_LRADC_CH7		44
+#define MX23_INT_LCDIF_DMA		45
+#define MX23_INT_LCDIF_ERROR		46
+#define MX23_INT_DIGCTL_DEBUG_TRAP	47
+#define MX23_INT_RTC_1MSEC		48
+#define MX23_INT_DRI_DMA		49
+#define MX23_INT_DRI_ATTENTION		50
+#define MX23_INT_GPMI_ATTENTION		51
+#define MX23_INT_IR			52
+#define MX23_INT_DCP_VMI		53
+#define MX23_INT_DCP			54
+#define MX23_INT_BCH			56
+#define MX23_INT_PXP			57
+#define MX23_INT_UARTAPP2_TX_DMA	58
+#define MX23_INT_UARTAPP2_INTERNAL	59
+#define MX23_INT_UARTAPP2_RX_DMA	60
+#define MX23_INT_VDAC_DETECT		61
+#define MX23_INT_VDD5V_DROOP		64
+#define MX23_INT_DCDC4P2_BO		65
+
+#endif /* __MACH_MX23_H__ */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mxs/include/mach/mx28.h linux-libre-2.6.38-gnu1/arch/arm/mach-mxs/include/mach/mx28.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mxs/include/mach/mx28.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mxs/include/mach/mx28.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,188 @@
+/*
+ * 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_MX28_H__
+#define __MACH_MX28_H__
+
+#include <mach/mxs.h>
+
+/*
+ * OCRAM
+ */
+#define MX28_OCRAM_BASE_ADDR		0x00000000
+#define MX28_OCRAM_SIZE			SZ_128K
+
+/*
+ * IO
+ */
+#define MX28_IO_BASE_ADDR		0x80000000
+#define MX28_IO_SIZE			SZ_1M
+
+#define MX28_ICOLL_BASE_ADDR		(MX28_IO_BASE_ADDR + 0x000000)
+#define MX28_HSADC_BASE_ADDR		(MX28_IO_BASE_ADDR + 0x002000)
+#define MX28_APBH_DMA_BASE_ADDR		(MX28_IO_BASE_ADDR + 0x004000)
+#define MX28_PERFMON_BASE_ADDR		(MX28_IO_BASE_ADDR + 0x006000)
+#define MX28_BCH_BASE_ADDR		(MX28_IO_BASE_ADDR + 0x00a000)
+#define MX28_GPMI_BASE_ADDR		(MX28_IO_BASE_ADDR + 0x00c000)
+#define MX28_SSP0_BASE_ADDR		(MX28_IO_BASE_ADDR + 0x010000)
+#define MX28_SSP1_BASE_ADDR		(MX28_IO_BASE_ADDR + 0x012000)
+#define MX28_SSP2_BASE_ADDR		(MX28_IO_BASE_ADDR + 0x014000)
+#define MX28_SSP3_BASE_ADDR		(MX28_IO_BASE_ADDR + 0x016000)
+#define MX28_PINCTRL_BASE_ADDR		(MX28_IO_BASE_ADDR + 0x018000)
+#define MX28_DIGCTL_BASE_ADDR		(MX28_IO_BASE_ADDR + 0x01c000)
+#define MX28_ETM_BASE_ADDR		(MX28_IO_BASE_ADDR + 0x022000)
+#define MX28_APBX_DMA_BASE_ADDR		(MX28_IO_BASE_ADDR + 0x024000)
+#define MX28_DCP_BASE_ADDR		(MX28_IO_BASE_ADDR + 0x028000)
+#define MX28_PXP_BASE_ADDR		(MX28_IO_BASE_ADDR + 0x02a000)
+#define MX28_OCOTP_BASE_ADDR		(MX28_IO_BASE_ADDR + 0x02c000)
+#define MX28_AXI_AHB0_BASE_ADDR		(MX28_IO_BASE_ADDR + 0x02e000)
+#define MX28_LCDIF_BASE_ADDR		(MX28_IO_BASE_ADDR + 0x030000)
+#define MX28_CAN0_BASE_ADDR		(MX28_IO_BASE_ADDR + 0x032000)
+#define MX28_CAN1_BASE_ADDR		(MX28_IO_BASE_ADDR + 0x034000)
+#define MX28_SIMDBG_BASE_ADDR		(MX28_IO_BASE_ADDR + 0x03c000)
+#define MX28_SIMGPMISEL_BASE_ADDR	(MX28_IO_BASE_ADDR + 0x03c200)
+#define MX28_SIMSSPSEL_BASE_ADDR	(MX28_IO_BASE_ADDR + 0x03c300)
+#define MX28_SIMMEMSEL_BASE_ADDR	(MX28_IO_BASE_ADDR + 0x03c400)
+#define MX28_GPIOMON_BASE_ADDR		(MX28_IO_BASE_ADDR + 0x03c500)
+#define MX28_SIMENET_BASE_ADDR		(MX28_IO_BASE_ADDR + 0x03c700)
+#define MX28_ARMJTAG_BASE_ADDR		(MX28_IO_BASE_ADDR + 0x03c800)
+#define MX28_CLKCTRL_BASE_ADDR		(MX28_IO_BASE_ADDR + 0x040000)
+#define MX28_SAIF0_BASE_ADDR		(MX28_IO_BASE_ADDR + 0x042000)
+#define MX28_POWER_BASE_ADDR		(MX28_IO_BASE_ADDR + 0x044000)
+#define MX28_SAIF1_BASE_ADDR		(MX28_IO_BASE_ADDR + 0x046000)
+#define MX28_LRADC_BASE_ADDR		(MX28_IO_BASE_ADDR + 0x050000)
+#define MX28_SPDIF_BASE_ADDR		(MX28_IO_BASE_ADDR + 0x054000)
+#define MX28_RTC_BASE_ADDR		(MX28_IO_BASE_ADDR + 0x056000)
+#define MX28_I2C0_BASE_ADDR		(MX28_IO_BASE_ADDR + 0x058000)
+#define MX28_I2C1_BASE_ADDR		(MX28_IO_BASE_ADDR + 0x05a000)
+#define MX28_PWM_BASE_ADDR		(MX28_IO_BASE_ADDR + 0x064000)
+#define MX28_TIMROT_BASE_ADDR		(MX28_IO_BASE_ADDR + 0x068000)
+#define MX28_AUART0_BASE_ADDR		(MX28_IO_BASE_ADDR + 0x06a000)
+#define MX28_AUART1_BASE_ADDR		(MX28_IO_BASE_ADDR + 0x06c000)
+#define MX28_AUART2_BASE_ADDR		(MX28_IO_BASE_ADDR + 0x06e000)
+#define MX28_AUART3_BASE_ADDR		(MX28_IO_BASE_ADDR + 0x070000)
+#define MX28_AUART4_BASE_ADDR		(MX28_IO_BASE_ADDR + 0x072000)
+#define MX28_DUART_BASE_ADDR		(MX28_IO_BASE_ADDR + 0x074000)
+#define MX28_USBPHY0_BASE_ADDR		(MX28_IO_BASE_ADDR + 0x07C000)
+#define MX28_USBPHY1_BASE_ADDR		(MX28_IO_BASE_ADDR + 0x07e000)
+#define MX28_USBCTRL0_BASE_ADDR		(MX28_IO_BASE_ADDR + 0x080000)
+#define MX28_USBCTRL1_BASE_ADDR		(MX28_IO_BASE_ADDR + 0x090000)
+#define MX28_DFLPT_BASE_ADDR		(MX28_IO_BASE_ADDR + 0x0c0000)
+#define MX28_DRAM_BASE_ADDR		(MX28_IO_BASE_ADDR + 0x0e0000)
+#define MX28_ENET_MAC0_BASE_ADDR	(MX28_IO_BASE_ADDR + 0x0f0000)
+#define MX28_ENET_MAC1_BASE_ADDR	(MX28_IO_BASE_ADDR + 0x0f4000)
+
+#define MX28_IO_P2V(x)			MXS_IO_P2V(x)
+#define MX28_IO_ADDRESS(x)		IOMEM(MX28_IO_P2V(x))
+
+/*
+ * IRQ
+ */
+#define MX28_INT_BATT_BRNOUT		0
+#define MX28_INT_VDDD_BRNOUT		1
+#define MX28_INT_VDDIO_BRNOUT		2
+#define MX28_INT_VDDA_BRNOUT		3
+#define MX28_INT_VDD5V_DROOP		4
+#define MX28_INT_DCDC4P2_BRNOUT		5
+#define MX28_INT_VDD5V			6
+#define MX28_INT_CAN0			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_CH0		16
+#define MX28_INT_LRADC_CH1		17
+#define MX28_INT_LRADC_CH2		18
+#define MX28_INT_LRADC_CH3		19
+#define MX28_INT_LRADC_CH4		20
+#define MX28_INT_LRADC_CH5		21
+#define MX28_INT_LRADC_CH6		22
+#define MX28_INT_LRADC_CH7		23
+#define MX28_INT_LRADC_BUTTON0		24
+#define MX28_INT_LRADC_BUTTON1		25
+#define MX28_INT_PERFMON		27
+#define MX28_INT_RTC_1MSEC		28
+#define MX28_INT_RTC_ALARM		29
+#define MX28_INT_COMMS			31
+#define MX28_INT_EMI_ERR		32
+#define MX28_INT_LCDIF			38
+#define MX28_INT_PXP			39
+#define MX28_INT_BCH			41
+#define MX28_INT_GPMI			42
+#define MX28_INT_SPDIF_ERROR		45
+#define MX28_INT_DUART			47
+#define MX28_INT_TIMER0			48
+#define MX28_INT_TIMER1			49
+#define MX28_INT_TIMER2			50
+#define MX28_INT_TIMER3			51
+#define MX28_INT_DCP_VMI		52
+#define MX28_INT_DCP			53
+#define MX28_INT_DCP_SECURE		54
+#define MX28_INT_SAIF1			58
+#define MX28_INT_SAIF0			59
+#define MX28_INT_SPDIF_DMA		66
+#define MX28_INT_I2C0_DMA		68
+#define MX28_INT_I2C1_DMA		69
+#define MX28_INT_AUART0_RX_DMA		70
+#define MX28_INT_AUART0_TX_DMA		71
+#define MX28_INT_AUART1_RX_DMA		72
+#define MX28_INT_AUART1_TX_DMA		73
+#define MX28_INT_AUART2_RX_DMA		74
+#define MX28_INT_AUART2_TX_DMA		75
+#define MX28_INT_AUART3_RX_DMA		76
+#define MX28_INT_AUART3_TX_DMA		77
+#define MX28_INT_AUART4_RX_DMA		78
+#define MX28_INT_AUART4_TX_DMA		79
+#define MX28_INT_SAIF0_DMA		80
+#define MX28_INT_SAIF1_DMA		81
+#define MX28_INT_SSP0_DMA		82
+#define MX28_INT_SSP1_DMA		83
+#define MX28_INT_SSP2_DMA		84
+#define MX28_INT_SSP3_DMA		85
+#define MX28_INT_LCDIF_DMA		86
+#define MX28_INT_HSADC_DMA		87
+#define MX28_INT_GPMI_DMA		88
+#define MX28_INT_DIGCTL_DEBUG_TRAP	89
+#define MX28_INT_USB1			92
+#define MX28_INT_USB0			93
+#define MX28_INT_USB1_WAKEUP		94
+#define MX28_INT_USB0_WAKEUP		95
+#define MX28_INT_SSP0			96
+#define MX28_INT_SSP1			97
+#define MX28_INT_SSP2			98
+#define MX28_INT_SSP3			99
+#define MX28_INT_ENET_SWI		100
+#define MX28_INT_ENET_MAC0		101
+#define MX28_INT_ENET_MAC1		102
+#define MX28_INT_ENET_MAC0_1588		103
+#define MX28_INT_ENET_MAC1_1588		104
+#define MX28_INT_I2C1_ERROR		110
+#define MX28_INT_I2C0_ERROR		111
+#define MX28_INT_AUART0			112
+#define MX28_INT_AUART1			113
+#define MX28_INT_AUART2			114
+#define MX28_INT_AUART3			115
+#define MX28_INT_AUART4			116
+#define MX28_INT_GPIO4			123
+#define MX28_INT_GPIO3			124
+#define MX28_INT_GPIO2			125
+#define MX28_INT_GPIO1			126
+#define MX28_INT_GPIO0			127
+
+#endif /* __MACH_MX28_H__ */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mxs/include/mach/mxs.h linux-libre-2.6.38-gnu1/arch/arm/mach-mxs/include/mach/mxs.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mxs/include/mach/mxs.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mxs/include/mach/mxs.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,105 @@
+/*
+ * 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_H__
+#define __MACH_MXS_H__
+
+#ifndef __ASSEMBLER__
+#include <linux/io.h>
+#endif
+#include <asm/mach-types.h>
+#include <mach/hardware.h>
+
+/*
+ * MXS CPU types
+ */
+#define cpu_is_mx23()		(machine_is_mx23evk())
+#define cpu_is_mx28()		(machine_is_mx28evk())
+
+/*
+ * IO addresses common to MXS-based
+ */
+#define MXS_IO_BASE_ADDR		0x80000000
+#define MXS_IO_SIZE			SZ_1M
+
+#define MXS_ICOLL_BASE_ADDR		(MXS_IO_BASE_ADDR + 0x000000)
+#define MXS_APBH_DMA_BASE_ADDR		(MXS_IO_BASE_ADDR + 0x004000)
+#define MXS_BCH_BASE_ADDR		(MXS_IO_BASE_ADDR + 0x00a000)
+#define MXS_GPMI_BASE_ADDR		(MXS_IO_BASE_ADDR + 0x00c000)
+#define MXS_PINCTRL_BASE_ADDR		(MXS_IO_BASE_ADDR + 0x018000)
+#define MXS_DIGCTL_BASE_ADDR		(MXS_IO_BASE_ADDR + 0x01c000)
+#define MXS_APBX_DMA_BASE_ADDR		(MXS_IO_BASE_ADDR + 0x024000)
+#define MXS_DCP_BASE_ADDR		(MXS_IO_BASE_ADDR + 0x028000)
+#define MXS_PXP_BASE_ADDR		(MXS_IO_BASE_ADDR + 0x02a000)
+#define MXS_OCOTP_BASE_ADDR		(MXS_IO_BASE_ADDR + 0x02c000)
+#define MXS_AXI_AHB0_BASE_ADDR		(MXS_IO_BASE_ADDR + 0x02e000)
+#define MXS_LCDIF_BASE_ADDR		(MXS_IO_BASE_ADDR + 0x030000)
+#define MXS_CLKCTRL_BASE_ADDR		(MXS_IO_BASE_ADDR + 0x040000)
+#define MXS_SAIF0_BASE_ADDR		(MXS_IO_BASE_ADDR + 0x042000)
+#define MXS_POWER_BASE_ADDR		(MXS_IO_BASE_ADDR + 0x044000)
+#define MXS_SAIF1_BASE_ADDR		(MXS_IO_BASE_ADDR + 0x046000)
+#define MXS_LRADC_BASE_ADDR		(MXS_IO_BASE_ADDR + 0x050000)
+#define MXS_SPDIF_BASE_ADDR		(MXS_IO_BASE_ADDR + 0x054000)
+#define MXS_I2C0_BASE_ADDR		(MXS_IO_BASE_ADDR + 0x058000)
+#define MXS_PWM_BASE_ADDR		(MXS_IO_BASE_ADDR + 0x064000)
+#define MXS_TIMROT_BASE_ADDR		(MXS_IO_BASE_ADDR + 0x068000)
+#define MXS_AUART1_BASE_ADDR		(MXS_IO_BASE_ADDR + 0x06c000)
+#define MXS_AUART2_BASE_ADDR		(MXS_IO_BASE_ADDR + 0x06e000)
+#define MXS_DRAM_BASE_ADDR		(MXS_IO_BASE_ADDR + 0x0e0000)
+
+/*
+ * It maps the whole address space to [0xf4000000, 0xf50fffff].
+ *
+ *	OCRAM	0x00000000+0x020000	->	0xf4000000+0x020000
+ *	IO	0x80000000+0x100000	->	0xf5000000+0x100000
+ */
+#define MXS_IO_P2V(x)	(0xf4000000 +					\
+			(((x) & 0x80000000) >> 7) +			\
+			(((x) & 0x000fffff)))
+
+#define MXS_IO_ADDRESS(x)	IOMEM(MXS_IO_P2V(x))
+
+#define mxs_map_entry(soc, name, _type)	{				\
+	.virtual = soc ## _IO_P2V(soc ## _ ## name ## _BASE_ADDR),	\
+	.pfn = __phys_to_pfn(soc ## _ ## name ## _BASE_ADDR),		\
+	.length = soc ## _ ## name ## _SIZE,				\
+	.type = _type,							\
+}
+
+#define MXS_SET_ADDR		0x4
+#define MXS_CLR_ADDR		0x8
+#define MXS_TOG_ADDR		0xc
+
+#ifndef __ASSEMBLER__
+static inline void __mxs_setl(u32 mask, void __iomem *reg)
+{
+	__raw_writel(mask, reg + MXS_SET_ADDR);
+}
+
+static inline void __mxs_clrl(u32 mask, void __iomem *reg)
+{
+	__raw_writel(mask, reg + MXS_CLR_ADDR);
+}
+
+static inline void __mxs_togl(u32 mask, void __iomem *reg)
+{
+	__raw_writel(mask, reg + MXS_TOG_ADDR);
+}
+#endif
+
+#endif /* __MACH_MXS_H__ */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mxs/include/mach/system.h linux-libre-2.6.38-gnu1/arch/arm/mach-mxs/include/mach/system.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mxs/include/mach/system.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mxs/include/mach/system.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,27 @@
+/*
+ *  Copyright (C) 1999 ARM Limited
+ *  Copyright (C) 2000 Deep Blue Solutions Ltd
+ *  Copyright 2004-2008 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.
+ */
+
+#ifndef __MACH_MXS_SYSTEM_H__
+#define __MACH_MXS_SYSTEM_H__
+
+static inline void arch_idle(void)
+{
+	cpu_do_idle();
+}
+
+void arch_reset(char mode, const char *cmd);
+
+#endif /* __MACH_MXS_SYSTEM_H__ */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mxs/include/mach/timex.h linux-libre-2.6.38-gnu1/arch/arm/mach-mxs/include/mach/timex.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mxs/include/mach/timex.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mxs/include/mach/timex.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,21 @@
+/*
+ *  Copyright (C) 1999 ARM Limited
+ * 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 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_MXS_TIMEX_H__
+#define __MACH_MXS_TIMEX_H__
+
+#define CLOCK_TICK_RATE		32000	/* 32K */
+
+#endif /* __MACH_MXS_TIMEX_H__ */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mxs/include/mach/uncompress.h linux-libre-2.6.38-gnu1/arch/arm/mach-mxs/include/mach/uncompress.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mxs/include/mach/uncompress.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mxs/include/mach/uncompress.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,76 @@
+/*
+ *  arch/arm/mach-mxs/include/mach/uncompress.h
+ *
+ *  Copyright (C) 1999 ARM Limited
+ *  Copyright (C) Shane Nay (shane@minirl.com)
+ *  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.
+ */
+#ifndef __MACH_MXS_UNCOMPRESS_H__
+#define __MACH_MXS_UNCOMPRESS_H__
+
+#include <asm/mach-types.h>
+
+static unsigned long mxs_duart_base;
+
+#define MXS_DUART(x)	(*(volatile unsigned long *)(mxs_duart_base + (x)))
+
+#define MXS_DUART_DR		0x00
+#define MXS_DUART_FR		0x18
+#define MXS_DUART_FR_TXFE	(1 << 7)
+#define MXS_DUART_CR		0x30
+#define MXS_DUART_CR_UARTEN	(1 << 0)
+
+/*
+ * The following code assumes the serial port has already been
+ * initialized by the bootloader. If it's not, the output is
+ * simply discarded.
+ */
+
+static void putc(int ch)
+{
+	if (!mxs_duart_base)
+		return;
+	if (!(MXS_DUART(MXS_DUART_CR) & MXS_DUART_CR_UARTEN))
+		return;
+
+	while (!(MXS_DUART(MXS_DUART_FR) & MXS_DUART_FR_TXFE))
+		barrier();
+
+	MXS_DUART(MXS_DUART_DR) = ch;
+}
+
+static inline void flush(void)
+{
+}
+
+#define MX23_DUART_BASE_ADDR	0x80070000
+#define MX28_DUART_BASE_ADDR	0x80074000
+
+static inline void __arch_decomp_setup(unsigned long arch_id)
+{
+	switch (arch_id) {
+	case MACH_TYPE_MX23EVK:
+		mxs_duart_base = MX23_DUART_BASE_ADDR;
+		break;
+	case MACH_TYPE_MX28EVK:
+		mxs_duart_base = MX28_DUART_BASE_ADDR;
+		break;
+	default:
+		break;
+	}
+}
+
+#define arch_decomp_setup()	__arch_decomp_setup(arch_id)
+#define arch_decomp_wdog()
+
+#endif /* __MACH_MXS_UNCOMPRESS_H__ */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mxs/include/mach/vmalloc.h linux-libre-2.6.38-gnu1/arch/arm/mach-mxs/include/mach/vmalloc.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mxs/include/mach/vmalloc.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mxs/include/mach/vmalloc.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,22 @@
+/*
+ *  Copyright (C) 2000 Russell King.
+ *  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 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_MXS_VMALLOC_H__
+#define __MACH_MXS_VMALLOC_H__
+
+/* vmalloc ending address */
+#define VMALLOC_END       0xf4000000UL
+
+#endif /* __MACH_MXS_VMALLOC_H__ */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mxs/iomux.c linux-libre-2.6.38-gnu1/arch/arm/mach-mxs/iomux.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mxs/iomux.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mxs/iomux.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2004-2006,2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (C) 2008 by Sascha Hauer <kernel@pengutronix.de>
+ * Copyright (C) 2009 by Jan Weitzel Phytec Messtechnik GmbH,
+ *                       <armlinux@phytec.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/errno.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/gpio.h>
+
+#include <asm/mach/map.h>
+
+#include <mach/mxs.h>
+#include <mach/iomux.h>
+
+/*
+ * configures a single pad in the iomuxer
+ */
+int mxs_iomux_setup_pad(iomux_cfg_t pad)
+{
+	u32 reg, ofs, bp, bm;
+	void __iomem *iomux_base = MXS_IO_ADDRESS(MXS_PINCTRL_BASE_ADDR);
+
+	/* muxsel */
+	ofs = 0x100;
+	ofs += PAD_BANK(pad) * 0x20 + PAD_PIN(pad) / 16 * 0x10;
+	bp = PAD_PIN(pad) % 16 * 2;
+	bm = 0x3 << bp;
+	reg = __raw_readl(iomux_base + ofs);
+	reg &= ~bm;
+	reg |= PAD_MUXSEL(pad) << bp;
+	__raw_writel(reg, iomux_base + ofs);
+
+	/* drive */
+	ofs = cpu_is_mx23() ? 0x200 : 0x300;
+	ofs += PAD_BANK(pad) * 0x40 + PAD_PIN(pad) / 8 * 0x10;
+	/* mA */
+	if (PAD_MA_VALID(pad)) {
+		bp = PAD_PIN(pad) % 8 * 4;
+		bm = 0x3 << bp;
+		reg = __raw_readl(iomux_base + ofs);
+		reg &= ~bm;
+		reg |= PAD_MA(pad) << bp;
+		__raw_writel(reg, iomux_base + ofs);
+	}
+	/* vol */
+	if (PAD_VOL_VALID(pad)) {
+		bp = PAD_PIN(pad) % 8 * 4 + 2;
+		if (PAD_VOL(pad))
+			__mxs_setl(1 << bp, iomux_base + ofs);
+		else
+			__mxs_clrl(1 << bp, iomux_base + ofs);
+	}
+
+	/* pull */
+	if (PAD_PULL_VALID(pad)) {
+		ofs = cpu_is_mx23() ? 0x400 : 0x600;
+		ofs += PAD_BANK(pad) * 0x10;
+		bp = PAD_PIN(pad);
+		if (PAD_PULL(pad))
+			__mxs_setl(1 << bp, iomux_base + ofs);
+		else
+			__mxs_clrl(1 << bp, iomux_base + ofs);
+	}
+
+	return 0;
+}
+
+int mxs_iomux_setup_multiple_pads(const iomux_cfg_t *pad_list, unsigned count)
+{
+	const iomux_cfg_t *p = pad_list;
+	int i;
+	int ret;
+
+	for (i = 0; i < count; i++) {
+		ret = mxs_iomux_setup_pad(*p);
+		if (ret)
+			return ret;
+		p++;
+	}
+
+	return 0;
+}
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mxs/Kconfig linux-libre-2.6.38-gnu1/arch/arm/mach-mxs/Kconfig
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mxs/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mxs/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,34 @@
+if ARCH_MXS
+
+source "arch/arm/mach-mxs/devices/Kconfig"
+
+config SOC_IMX23
+	bool
+	select CPU_ARM926T
+
+config SOC_IMX28
+	bool
+	select CPU_ARM926T
+
+comment "MXS platforms:"
+
+config MACH_MX23EVK
+	bool "Support MX23EVK Platform"
+	select SOC_IMX23
+	select MXS_HAVE_AMBA_DUART
+	default y
+	help
+	  Include support for MX23EVK platform. This includes specific
+	  configurations for the board and its peripherals.
+
+config MACH_MX28EVK
+	bool "Support MX28EVK Platform"
+	select SOC_IMX28
+	select MXS_HAVE_AMBA_DUART
+	select MXS_HAVE_PLATFORM_FEC
+	default y
+	help
+	  Include support for MX28EVK platform. This includes specific
+	  configurations for the board and its peripherals.
+
+endif
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mxs/mach-mx23evk.c linux-libre-2.6.38-gnu1/arch/arm/mach-mxs/mach-mx23evk.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mxs/mach-mx23evk.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mxs/mach-mx23evk.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,57 @@
+/*
+ * 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/irq.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+
+#include <mach/common.h>
+#include <mach/iomux-mx23.h>
+
+#include "devices-mx23.h"
+
+static const iomux_cfg_t mx23evk_pads[] __initconst = {
+	/* duart */
+	MX23_PAD_PWM0__DUART_RX | MXS_PAD_4MA,
+	MX23_PAD_PWM1__DUART_TX | MXS_PAD_4MA,
+};
+
+static void __init mx23evk_init(void)
+{
+	mxs_iomux_setup_multiple_pads(mx23evk_pads, ARRAY_SIZE(mx23evk_pads));
+
+	mx23_add_duart();
+}
+
+static void __init mx23evk_timer_init(void)
+{
+	mx23_clocks_init();
+}
+
+static struct sys_timer mx23evk_timer = {
+	.init	= mx23evk_timer_init,
+};
+
+MACHINE_START(MX23EVK, "Freescale MX23 EVK")
+	/* Maintainer: Freescale Semiconductor, Inc. */
+	.map_io		= mx23_map_io,
+	.init_irq	= mx23_init_irq,
+	.init_machine	= mx23evk_init,
+	.timer		= &mx23evk_timer,
+MACHINE_END
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mxs/mach-mx28evk.c linux-libre-2.6.38-gnu1/arch/arm/mach-mxs/mach-mx28evk.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mxs/mach-mx28evk.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mxs/mach-mx28evk.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,158 @@
+/*
+ * 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/irq.h>
+#include <linux/clk.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"
+#include "gpio.h"
+
+#define MX28EVK_FEC_PHY_POWER	MXS_GPIO_NR(2, 15)
+#define MX28EVK_FEC_PHY_RESET	MXS_GPIO_NR(4, 13)
+
+static const iomux_cfg_t mx28evk_pads[] __initconst = {
+	/* duart */
+	MX28_PAD_PWM0__DUART_RX |
+		(MXS_PAD_4MA | MXS_PAD_3V3 | MXS_PAD_NOPULL),
+	MX28_PAD_PWM1__DUART_TX |
+		(MXS_PAD_4MA | MXS_PAD_3V3 | MXS_PAD_NOPULL),
+
+	/* fec0 */
+	MX28_PAD_ENET0_MDC__ENET0_MDC |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_ENET0_MDIO__ENET0_MDIO |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_ENET0_RX_EN__ENET0_RX_EN |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_ENET0_RXD0__ENET0_RXD0 |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_ENET0_RXD1__ENET0_RXD1 |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_ENET0_TX_EN__ENET0_TX_EN |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_ENET0_TXD0__ENET0_TXD0 |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_ENET0_TXD1__ENET0_TXD1 |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_ENET_CLK__CLKCTRL_ENET |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	/* fec1 */
+	MX28_PAD_ENET0_CRS__ENET1_RX_EN |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_ENET0_RXD2__ENET1_RXD0 |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_ENET0_RXD3__ENET1_RXD1 |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_ENET0_COL__ENET1_TX_EN |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_ENET0_TXD2__ENET1_TXD0 |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_ENET0_TXD3__ENET1_TXD1 |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	/* phy power line */
+	MX28_PAD_SSP1_DATA3__GPIO_2_15 |
+		(MXS_PAD_4MA | MXS_PAD_3V3 | MXS_PAD_NOPULL),
+	/* phy reset line */
+	MX28_PAD_ENET0_RX_CLK__GPIO_4_13 |
+		(MXS_PAD_4MA | MXS_PAD_3V3 | MXS_PAD_NOPULL),
+};
+
+/* fec */
+static void __init mx28evk_fec_reset(void)
+{
+	int ret;
+	struct clk *clk;
+
+	/* Enable fec phy clock */
+	clk = clk_get_sys("pll2", NULL);
+	if (!IS_ERR(clk))
+		clk_enable(clk);
+
+	/* Power up fec phy */
+	ret = gpio_request(MX28EVK_FEC_PHY_POWER, "fec-phy-power");
+	if (ret) {
+		pr_err("Failed to request gpio fec-phy-%s: %d\n", "power", ret);
+		return;
+	}
+
+	ret = gpio_direction_output(MX28EVK_FEC_PHY_POWER, 0);
+	if (ret) {
+		pr_err("Failed to drive gpio fec-phy-%s: %d\n", "power", ret);
+		return;
+	}
+
+	/* Reset fec phy */
+	ret = gpio_request(MX28EVK_FEC_PHY_RESET, "fec-phy-reset");
+	if (ret) {
+		pr_err("Failed to request gpio fec-phy-%s: %d\n", "reset", ret);
+		return;
+	}
+
+	gpio_direction_output(MX28EVK_FEC_PHY_RESET, 0);
+	if (ret) {
+		pr_err("Failed to drive gpio fec-phy-%s: %d\n", "reset", ret);
+		return;
+	}
+
+	mdelay(1);
+	gpio_set_value(MX28EVK_FEC_PHY_RESET, 1);
+}
+
+static struct fec_platform_data mx28_fec_pdata[] = {
+	{
+		/* fec0 */
+		.phy = PHY_INTERFACE_MODE_RMII,
+	}, {
+		/* fec1 */
+		.phy = PHY_INTERFACE_MODE_RMII,
+	},
+};
+
+static void __init mx28evk_init(void)
+{
+	mxs_iomux_setup_multiple_pads(mx28evk_pads, ARRAY_SIZE(mx28evk_pads));
+
+	mx28_add_duart();
+
+	mx28evk_fec_reset();
+	mx28_add_fec(0, &mx28_fec_pdata[0]);
+	mx28_add_fec(1, &mx28_fec_pdata[1]);
+}
+
+static void __init mx28evk_timer_init(void)
+{
+	mx28_clocks_init();
+}
+
+static struct sys_timer mx28evk_timer = {
+	.init	= mx28evk_timer_init,
+};
+
+MACHINE_START(MX28EVK, "Freescale MX28 EVK")
+	/* Maintainer: Freescale Semiconductor, Inc. */
+	.map_io		= mx28_map_io,
+	.init_irq	= mx28_init_irq,
+	.init_machine	= mx28evk_init,
+	.timer		= &mx28evk_timer,
+MACHINE_END
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mxs/Makefile linux-libre-2.6.38-gnu1/arch/arm/mach-mxs/Makefile
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mxs/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mxs/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,10 @@
+# Common support
+obj-y := clock.o devices.o gpio.o icoll.o iomux.o system.o timer.o
+
+obj-$(CONFIG_SOC_IMX23) += clock-mx23.o mm-mx23.o
+obj-$(CONFIG_SOC_IMX28) += clock-mx28.o mm-mx28.o
+
+obj-$(CONFIG_MACH_MX23EVK) += mach-mx23evk.o
+obj-$(CONFIG_MACH_MX28EVK) += mach-mx28evk.o
+
+obj-y += devices/
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mxs/Makefile.boot linux-libre-2.6.38-gnu1/arch/arm/mach-mxs/Makefile.boot
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mxs/Makefile.boot	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mxs/Makefile.boot	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1 @@
+zreladdr-y := 0x40008000
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mxs/mm-mx23.c linux-libre-2.6.38-gnu1/arch/arm/mach-mxs/mm-mx23.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mxs/mm-mx23.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mxs/mm-mx23.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,45 @@
+/*
+ * 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();
+	mx23_register_gpios();
+}
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mxs/mm-mx28.c linux-libre-2.6.38-gnu1/arch/arm/mach-mxs/mm-mx28.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mxs/mm-mx28.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mxs/mm-mx28.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,45 @@
+/*
+ * 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();
+	mx28_register_gpios();
+}
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mxs/regs-clkctrl-mx23.h linux-libre-2.6.38-gnu1/arch/arm/mach-mxs/regs-clkctrl-mx23.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mxs/regs-clkctrl-mx23.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mxs/regs-clkctrl-mx23.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,455 @@
+/*
+ * Freescale CLKCTRL Register Definitions
+ *
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ * Copyright 2008-2010 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.
+ *
+ * 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
+ *
+ * This file is created by xml file. Don't Edit it.
+ *
+ * Xml Revision: 1.48
+ * Template revision: 26195
+ */
+
+#ifndef __REGS_CLKCTRL_MX23_H__
+#define __REGS_CLKCTRL_MX23_H__
+
+
+#define HW_CLKCTRL_PLLCTRL0	(0x00000000)
+#define HW_CLKCTRL_PLLCTRL0_SET	(0x00000004)
+#define HW_CLKCTRL_PLLCTRL0_CLR	(0x00000008)
+#define HW_CLKCTRL_PLLCTRL0_TOG	(0x0000000c)
+
+#define BP_CLKCTRL_PLLCTRL0_RSRVD6	30
+#define BM_CLKCTRL_PLLCTRL0_RSRVD6	0xC0000000
+#define BF_CLKCTRL_PLLCTRL0_RSRVD6(v) \
+		(((v) << 30) & BM_CLKCTRL_PLLCTRL0_RSRVD6)
+#define BP_CLKCTRL_PLLCTRL0_LFR_SEL	28
+#define BM_CLKCTRL_PLLCTRL0_LFR_SEL	0x30000000
+#define BF_CLKCTRL_PLLCTRL0_LFR_SEL(v)  \
+		(((v) << 28) & BM_CLKCTRL_PLLCTRL0_LFR_SEL)
+#define BV_CLKCTRL_PLLCTRL0_LFR_SEL__DEFAULT   0x0
+#define BV_CLKCTRL_PLLCTRL0_LFR_SEL__TIMES_2   0x1
+#define BV_CLKCTRL_PLLCTRL0_LFR_SEL__TIMES_05  0x2
+#define BV_CLKCTRL_PLLCTRL0_LFR_SEL__UNDEFINED 0x3
+#define BP_CLKCTRL_PLLCTRL0_RSRVD5	26
+#define BM_CLKCTRL_PLLCTRL0_RSRVD5	0x0C000000
+#define BF_CLKCTRL_PLLCTRL0_RSRVD5(v)  \
+		(((v) << 26) & BM_CLKCTRL_PLLCTRL0_RSRVD5)
+#define BP_CLKCTRL_PLLCTRL0_CP_SEL	24
+#define BM_CLKCTRL_PLLCTRL0_CP_SEL	0x03000000
+#define BF_CLKCTRL_PLLCTRL0_CP_SEL(v)  \
+		(((v) << 24) & BM_CLKCTRL_PLLCTRL0_CP_SEL)
+#define BV_CLKCTRL_PLLCTRL0_CP_SEL__DEFAULT   0x0
+#define BV_CLKCTRL_PLLCTRL0_CP_SEL__TIMES_2   0x1
+#define BV_CLKCTRL_PLLCTRL0_CP_SEL__TIMES_05  0x2
+#define BV_CLKCTRL_PLLCTRL0_CP_SEL__UNDEFINED 0x3
+#define BP_CLKCTRL_PLLCTRL0_RSRVD4	22
+#define BM_CLKCTRL_PLLCTRL0_RSRVD4	0x00C00000
+#define BF_CLKCTRL_PLLCTRL0_RSRVD4(v)  \
+		(((v) << 22) & BM_CLKCTRL_PLLCTRL0_RSRVD4)
+#define BP_CLKCTRL_PLLCTRL0_DIV_SEL	20
+#define BM_CLKCTRL_PLLCTRL0_DIV_SEL	0x00300000
+#define BF_CLKCTRL_PLLCTRL0_DIV_SEL(v)  \
+		(((v) << 20) & BM_CLKCTRL_PLLCTRL0_DIV_SEL)
+#define BV_CLKCTRL_PLLCTRL0_DIV_SEL__DEFAULT   0x0
+#define BV_CLKCTRL_PLLCTRL0_DIV_SEL__LOWER     0x1
+#define BV_CLKCTRL_PLLCTRL0_DIV_SEL__LOWEST    0x2
+#define BV_CLKCTRL_PLLCTRL0_DIV_SEL__UNDEFINED 0x3
+#define BM_CLKCTRL_PLLCTRL0_RSRVD3	0x00080000
+#define BM_CLKCTRL_PLLCTRL0_EN_USB_CLKS	0x00040000
+#define BM_CLKCTRL_PLLCTRL0_RSRVD2	0x00020000
+#define BM_CLKCTRL_PLLCTRL0_POWER	0x00010000
+#define BP_CLKCTRL_PLLCTRL0_RSRVD1	0
+#define BM_CLKCTRL_PLLCTRL0_RSRVD1	0x0000FFFF
+#define BF_CLKCTRL_PLLCTRL0_RSRVD1(v)  \
+		(((v) << 0) & BM_CLKCTRL_PLLCTRL0_RSRVD1)
+
+#define HW_CLKCTRL_PLLCTRL1	(0x00000010)
+
+#define BM_CLKCTRL_PLLCTRL1_LOCK	0x80000000
+#define BM_CLKCTRL_PLLCTRL1_FORCE_LOCK	0x40000000
+#define BP_CLKCTRL_PLLCTRL1_RSRVD1	16
+#define BM_CLKCTRL_PLLCTRL1_RSRVD1	0x3FFF0000
+#define BF_CLKCTRL_PLLCTRL1_RSRVD1(v)  \
+		(((v) << 16) & BM_CLKCTRL_PLLCTRL1_RSRVD1)
+#define BP_CLKCTRL_PLLCTRL1_LOCK_COUNT	0
+#define BM_CLKCTRL_PLLCTRL1_LOCK_COUNT	0x0000FFFF
+#define BF_CLKCTRL_PLLCTRL1_LOCK_COUNT(v)  \
+		(((v) << 0) & BM_CLKCTRL_PLLCTRL1_LOCK_COUNT)
+
+#define HW_CLKCTRL_CPU	(0x00000020)
+#define HW_CLKCTRL_CPU_SET	(0x00000024)
+#define HW_CLKCTRL_CPU_CLR	(0x00000028)
+#define HW_CLKCTRL_CPU_TOG	(0x0000002c)
+
+#define BP_CLKCTRL_CPU_RSRVD5	30
+#define BM_CLKCTRL_CPU_RSRVD5	0xC0000000
+#define BF_CLKCTRL_CPU_RSRVD5(v) \
+		(((v) << 30) & BM_CLKCTRL_CPU_RSRVD5)
+#define BM_CLKCTRL_CPU_BUSY_REF_XTAL	0x20000000
+#define BM_CLKCTRL_CPU_BUSY_REF_CPU	0x10000000
+#define BM_CLKCTRL_CPU_RSRVD4	0x08000000
+#define BM_CLKCTRL_CPU_DIV_XTAL_FRAC_EN	0x04000000
+#define BP_CLKCTRL_CPU_DIV_XTAL	16
+#define BM_CLKCTRL_CPU_DIV_XTAL	0x03FF0000
+#define BF_CLKCTRL_CPU_DIV_XTAL(v)  \
+		(((v) << 16) & BM_CLKCTRL_CPU_DIV_XTAL)
+#define BP_CLKCTRL_CPU_RSRVD3	13
+#define BM_CLKCTRL_CPU_RSRVD3	0x0000E000
+#define BF_CLKCTRL_CPU_RSRVD3(v)  \
+		(((v) << 13) & BM_CLKCTRL_CPU_RSRVD3)
+#define BM_CLKCTRL_CPU_INTERRUPT_WAIT	0x00001000
+#define BM_CLKCTRL_CPU_RSRVD2	0x00000800
+#define BM_CLKCTRL_CPU_DIV_CPU_FRAC_EN	0x00000400
+#define BP_CLKCTRL_CPU_RSRVD1	6
+#define BM_CLKCTRL_CPU_RSRVD1	0x000003C0
+#define BF_CLKCTRL_CPU_RSRVD1(v)  \
+		(((v) << 6) & BM_CLKCTRL_CPU_RSRVD1)
+#define BP_CLKCTRL_CPU_DIV_CPU	0
+#define BM_CLKCTRL_CPU_DIV_CPU	0x0000003F
+#define BF_CLKCTRL_CPU_DIV_CPU(v)  \
+		(((v) << 0) & BM_CLKCTRL_CPU_DIV_CPU)
+
+#define HW_CLKCTRL_HBUS	(0x00000030)
+#define HW_CLKCTRL_HBUS_SET	(0x00000034)
+#define HW_CLKCTRL_HBUS_CLR	(0x00000038)
+#define HW_CLKCTRL_HBUS_TOG	(0x0000003c)
+
+#define BP_CLKCTRL_HBUS_RSRVD4	30
+#define BM_CLKCTRL_HBUS_RSRVD4	0xC0000000
+#define BF_CLKCTRL_HBUS_RSRVD4(v) \
+		(((v) << 30) & BM_CLKCTRL_HBUS_RSRVD4)
+#define BM_CLKCTRL_HBUS_BUSY	0x20000000
+#define BM_CLKCTRL_HBUS_DCP_AS_ENABLE	0x10000000
+#define BM_CLKCTRL_HBUS_PXP_AS_ENABLE	0x08000000
+#define BM_CLKCTRL_HBUS_APBHDMA_AS_ENABLE	0x04000000
+#define BM_CLKCTRL_HBUS_APBXDMA_AS_ENABLE	0x02000000
+#define BM_CLKCTRL_HBUS_TRAFFIC_JAM_AS_ENABLE	0x01000000
+#define BM_CLKCTRL_HBUS_TRAFFIC_AS_ENABLE	0x00800000
+#define BM_CLKCTRL_HBUS_CPU_DATA_AS_ENABLE	0x00400000
+#define BM_CLKCTRL_HBUS_CPU_INSTR_AS_ENABLE	0x00200000
+#define BM_CLKCTRL_HBUS_AUTO_SLOW_MODE	0x00100000
+#define BM_CLKCTRL_HBUS_RSRVD2	0x00080000
+#define BP_CLKCTRL_HBUS_SLOW_DIV	16
+#define BM_CLKCTRL_HBUS_SLOW_DIV	0x00070000
+#define BF_CLKCTRL_HBUS_SLOW_DIV(v)  \
+		(((v) << 16) & BM_CLKCTRL_HBUS_SLOW_DIV)
+#define BV_CLKCTRL_HBUS_SLOW_DIV__BY1  0x0
+#define BV_CLKCTRL_HBUS_SLOW_DIV__BY2  0x1
+#define BV_CLKCTRL_HBUS_SLOW_DIV__BY4  0x2
+#define BV_CLKCTRL_HBUS_SLOW_DIV__BY8  0x3
+#define BV_CLKCTRL_HBUS_SLOW_DIV__BY16 0x4
+#define BV_CLKCTRL_HBUS_SLOW_DIV__BY32 0x5
+#define BP_CLKCTRL_HBUS_RSRVD1	6
+#define BM_CLKCTRL_HBUS_RSRVD1	0x0000FFC0
+#define BF_CLKCTRL_HBUS_RSRVD1(v)  \
+		(((v) << 6) & BM_CLKCTRL_HBUS_RSRVD1)
+#define BM_CLKCTRL_HBUS_DIV_FRAC_EN	0x00000020
+#define BP_CLKCTRL_HBUS_DIV	0
+#define BM_CLKCTRL_HBUS_DIV	0x0000001F
+#define BF_CLKCTRL_HBUS_DIV(v)  \
+		(((v) << 0) & BM_CLKCTRL_HBUS_DIV)
+
+#define HW_CLKCTRL_XBUS	(0x00000040)
+
+#define BM_CLKCTRL_XBUS_BUSY	0x80000000
+#define BP_CLKCTRL_XBUS_RSRVD1	11
+#define BM_CLKCTRL_XBUS_RSRVD1	0x7FFFF800
+#define BF_CLKCTRL_XBUS_RSRVD1(v)  \
+		(((v) << 11) & BM_CLKCTRL_XBUS_RSRVD1)
+#define BM_CLKCTRL_XBUS_DIV_FRAC_EN	0x00000400
+#define BP_CLKCTRL_XBUS_DIV	0
+#define BM_CLKCTRL_XBUS_DIV	0x000003FF
+#define BF_CLKCTRL_XBUS_DIV(v)  \
+		(((v) << 0) & BM_CLKCTRL_XBUS_DIV)
+
+#define HW_CLKCTRL_XTAL	(0x00000050)
+#define HW_CLKCTRL_XTAL_SET	(0x00000054)
+#define HW_CLKCTRL_XTAL_CLR	(0x00000058)
+#define HW_CLKCTRL_XTAL_TOG	(0x0000005c)
+
+#define BP_CLKCTRL_XTAL_UART_CLK_GATE	31
+#define BM_CLKCTRL_XTAL_UART_CLK_GATE	0x80000000
+#define BP_CLKCTRL_XTAL_FILT_CLK24M_GATE	30
+#define BM_CLKCTRL_XTAL_FILT_CLK24M_GATE	0x40000000
+#define BP_CLKCTRL_XTAL_PWM_CLK24M_GATE	29
+#define BM_CLKCTRL_XTAL_PWM_CLK24M_GATE	0x20000000
+#define BM_CLKCTRL_XTAL_DRI_CLK24M_GATE	0x10000000
+#define BM_CLKCTRL_XTAL_DIGCTRL_CLK1M_GATE	0x08000000
+#define BP_CLKCTRL_XTAL_TIMROT_CLK32K_GATE	26
+#define BM_CLKCTRL_XTAL_TIMROT_CLK32K_GATE	0x04000000
+#define BP_CLKCTRL_XTAL_RSRVD1	2
+#define BM_CLKCTRL_XTAL_RSRVD1	0x03FFFFFC
+#define BF_CLKCTRL_XTAL_RSRVD1(v)  \
+		(((v) << 2) & BM_CLKCTRL_XTAL_RSRVD1)
+#define BP_CLKCTRL_XTAL_DIV_UART	0
+#define BM_CLKCTRL_XTAL_DIV_UART	0x00000003
+#define BF_CLKCTRL_XTAL_DIV_UART(v)  \
+		(((v) << 0) & BM_CLKCTRL_XTAL_DIV_UART)
+
+#define HW_CLKCTRL_PIX	(0x00000060)
+
+#define BP_CLKCTRL_PIX_CLKGATE	31
+#define BM_CLKCTRL_PIX_CLKGATE	0x80000000
+#define BM_CLKCTRL_PIX_RSRVD2	0x40000000
+#define BM_CLKCTRL_PIX_BUSY	0x20000000
+#define BP_CLKCTRL_PIX_RSRVD1	13
+#define BM_CLKCTRL_PIX_RSRVD1	0x1FFFE000
+#define BF_CLKCTRL_PIX_RSRVD1(v)  \
+		(((v) << 13) & BM_CLKCTRL_PIX_RSRVD1)
+#define BM_CLKCTRL_PIX_DIV_FRAC_EN	0x00001000
+#define BP_CLKCTRL_PIX_DIV	0
+#define BM_CLKCTRL_PIX_DIV	0x00000FFF
+#define BF_CLKCTRL_PIX_DIV(v)  \
+		(((v) << 0) & BM_CLKCTRL_PIX_DIV)
+
+#define HW_CLKCTRL_SSP	(0x00000070)
+
+#define BP_CLKCTRL_SSP_CLKGATE	31
+#define BM_CLKCTRL_SSP_CLKGATE	0x80000000
+#define BM_CLKCTRL_SSP_RSRVD2	0x40000000
+#define BM_CLKCTRL_SSP_BUSY	0x20000000
+#define BP_CLKCTRL_SSP_RSRVD1	10
+#define BM_CLKCTRL_SSP_RSRVD1	0x1FFFFC00
+#define BF_CLKCTRL_SSP_RSRVD1(v)  \
+		(((v) << 10) & BM_CLKCTRL_SSP_RSRVD1)
+#define BM_CLKCTRL_SSP_DIV_FRAC_EN	0x00000200
+#define BP_CLKCTRL_SSP_DIV	0
+#define BM_CLKCTRL_SSP_DIV	0x000001FF
+#define BF_CLKCTRL_SSP_DIV(v)  \
+		(((v) << 0) & BM_CLKCTRL_SSP_DIV)
+
+#define HW_CLKCTRL_GPMI	(0x00000080)
+
+#define BP_CLKCTRL_GPMI_CLKGATE	31
+#define BM_CLKCTRL_GPMI_CLKGATE	0x80000000
+#define BM_CLKCTRL_GPMI_RSRVD2	0x40000000
+#define BM_CLKCTRL_GPMI_BUSY	0x20000000
+#define BP_CLKCTRL_GPMI_RSRVD1	11
+#define BM_CLKCTRL_GPMI_RSRVD1	0x1FFFF800
+#define BF_CLKCTRL_GPMI_RSRVD1(v)  \
+		(((v) << 11) & BM_CLKCTRL_GPMI_RSRVD1)
+#define BM_CLKCTRL_GPMI_DIV_FRAC_EN	0x00000400
+#define BP_CLKCTRL_GPMI_DIV	0
+#define BM_CLKCTRL_GPMI_DIV	0x000003FF
+#define BF_CLKCTRL_GPMI_DIV(v)  \
+		(((v) << 0) & BM_CLKCTRL_GPMI_DIV)
+
+#define HW_CLKCTRL_SPDIF	(0x00000090)
+
+#define BM_CLKCTRL_SPDIF_CLKGATE	0x80000000
+#define BP_CLKCTRL_SPDIF_RSRVD	0
+#define BM_CLKCTRL_SPDIF_RSRVD	0x7FFFFFFF
+#define BF_CLKCTRL_SPDIF_RSRVD(v)  \
+		(((v) << 0) & BM_CLKCTRL_SPDIF_RSRVD)
+
+#define HW_CLKCTRL_EMI	(0x000000a0)
+
+#define BP_CLKCTRL_EMI_CLKGATE	31
+#define BM_CLKCTRL_EMI_CLKGATE	0x80000000
+#define BM_CLKCTRL_EMI_SYNC_MODE_EN	0x40000000
+#define BM_CLKCTRL_EMI_BUSY_REF_XTAL	0x20000000
+#define BM_CLKCTRL_EMI_BUSY_REF_EMI	0x10000000
+#define BM_CLKCTRL_EMI_BUSY_REF_CPU	0x08000000
+#define BM_CLKCTRL_EMI_BUSY_SYNC_MODE	0x04000000
+#define BP_CLKCTRL_EMI_RSRVD3	18
+#define BM_CLKCTRL_EMI_RSRVD3	0x03FC0000
+#define BF_CLKCTRL_EMI_RSRVD3(v)  \
+		(((v) << 18) & BM_CLKCTRL_EMI_RSRVD3)
+#define BM_CLKCTRL_EMI_BUSY_DCC_RESYNC	0x00020000
+#define BM_CLKCTRL_EMI_DCC_RESYNC_ENABLE	0x00010000
+#define BP_CLKCTRL_EMI_RSRVD2	12
+#define BM_CLKCTRL_EMI_RSRVD2	0x0000F000
+#define BF_CLKCTRL_EMI_RSRVD2(v)  \
+		(((v) << 12) & BM_CLKCTRL_EMI_RSRVD2)
+#define BP_CLKCTRL_EMI_DIV_XTAL	8
+#define BM_CLKCTRL_EMI_DIV_XTAL	0x00000F00
+#define BF_CLKCTRL_EMI_DIV_XTAL(v)  \
+		(((v) << 8) & BM_CLKCTRL_EMI_DIV_XTAL)
+#define BP_CLKCTRL_EMI_RSRVD1	6
+#define BM_CLKCTRL_EMI_RSRVD1	0x000000C0
+#define BF_CLKCTRL_EMI_RSRVD1(v)  \
+		(((v) << 6) & BM_CLKCTRL_EMI_RSRVD1)
+#define BP_CLKCTRL_EMI_DIV_EMI	0
+#define BM_CLKCTRL_EMI_DIV_EMI	0x0000003F
+#define BF_CLKCTRL_EMI_DIV_EMI(v)  \
+		(((v) << 0) & BM_CLKCTRL_EMI_DIV_EMI)
+
+#define HW_CLKCTRL_IR	(0x000000b0)
+
+#define BM_CLKCTRL_IR_CLKGATE	0x80000000
+#define BM_CLKCTRL_IR_RSRVD3	0x40000000
+#define BM_CLKCTRL_IR_AUTO_DIV	0x20000000
+#define BM_CLKCTRL_IR_IR_BUSY	0x10000000
+#define BM_CLKCTRL_IR_IROV_BUSY	0x08000000
+#define BP_CLKCTRL_IR_RSRVD2	25
+#define BM_CLKCTRL_IR_RSRVD2	0x06000000
+#define BF_CLKCTRL_IR_RSRVD2(v)  \
+		(((v) << 25) & BM_CLKCTRL_IR_RSRVD2)
+#define BP_CLKCTRL_IR_IROV_DIV	16
+#define BM_CLKCTRL_IR_IROV_DIV	0x01FF0000
+#define BF_CLKCTRL_IR_IROV_DIV(v)  \
+		(((v) << 16) & BM_CLKCTRL_IR_IROV_DIV)
+#define BP_CLKCTRL_IR_RSRVD1	10
+#define BM_CLKCTRL_IR_RSRVD1	0x0000FC00
+#define BF_CLKCTRL_IR_RSRVD1(v)  \
+		(((v) << 10) & BM_CLKCTRL_IR_RSRVD1)
+#define BP_CLKCTRL_IR_IR_DIV	0
+#define BM_CLKCTRL_IR_IR_DIV	0x000003FF
+#define BF_CLKCTRL_IR_IR_DIV(v)  \
+		(((v) << 0) & BM_CLKCTRL_IR_IR_DIV)
+
+#define HW_CLKCTRL_SAIF	(0x000000c0)
+
+#define BM_CLKCTRL_SAIF_CLKGATE	0x80000000
+#define BM_CLKCTRL_SAIF_RSRVD2	0x40000000
+#define BM_CLKCTRL_SAIF_BUSY	0x20000000
+#define BP_CLKCTRL_SAIF_RSRVD1	17
+#define BM_CLKCTRL_SAIF_RSRVD1	0x1FFE0000
+#define BF_CLKCTRL_SAIF_RSRVD1(v)  \
+		(((v) << 17) & BM_CLKCTRL_SAIF_RSRVD1)
+#define BM_CLKCTRL_SAIF_DIV_FRAC_EN	0x00010000
+#define BP_CLKCTRL_SAIF_DIV	0
+#define BM_CLKCTRL_SAIF_DIV	0x0000FFFF
+#define BF_CLKCTRL_SAIF_DIV(v)  \
+		(((v) << 0) & BM_CLKCTRL_SAIF_DIV)
+
+#define HW_CLKCTRL_TV	(0x000000d0)
+
+#define BM_CLKCTRL_TV_CLK_TV108M_GATE	0x80000000
+#define BM_CLKCTRL_TV_CLK_TV_GATE	0x40000000
+#define BP_CLKCTRL_TV_RSRVD	0
+#define BM_CLKCTRL_TV_RSRVD	0x3FFFFFFF
+#define BF_CLKCTRL_TV_RSRVD(v)  \
+		(((v) << 0) & BM_CLKCTRL_TV_RSRVD)
+
+#define HW_CLKCTRL_ETM	(0x000000e0)
+
+#define BM_CLKCTRL_ETM_CLKGATE	0x80000000
+#define BM_CLKCTRL_ETM_RSRVD2	0x40000000
+#define BM_CLKCTRL_ETM_BUSY	0x20000000
+#define BP_CLKCTRL_ETM_RSRVD1	7
+#define BM_CLKCTRL_ETM_RSRVD1	0x1FFFFF80
+#define BF_CLKCTRL_ETM_RSRVD1(v)  \
+		(((v) << 7) & BM_CLKCTRL_ETM_RSRVD1)
+#define BM_CLKCTRL_ETM_DIV_FRAC_EN	0x00000040
+#define BP_CLKCTRL_ETM_DIV	0
+#define BM_CLKCTRL_ETM_DIV	0x0000003F
+#define BF_CLKCTRL_ETM_DIV(v)  \
+		(((v) << 0) & BM_CLKCTRL_ETM_DIV)
+
+#define HW_CLKCTRL_FRAC	(0x000000f0)
+#define HW_CLKCTRL_FRAC_SET	(0x000000f4)
+#define HW_CLKCTRL_FRAC_CLR	(0x000000f8)
+#define HW_CLKCTRL_FRAC_TOG	(0x000000fc)
+
+#define BP_CLKCTRL_FRAC_CLKGATEIO	31
+#define BM_CLKCTRL_FRAC_CLKGATEIO	0x80000000
+#define BM_CLKCTRL_FRAC_IO_STABLE	0x40000000
+#define BP_CLKCTRL_FRAC_IOFRAC	24
+#define BM_CLKCTRL_FRAC_IOFRAC	0x3F000000
+#define BF_CLKCTRL_FRAC_IOFRAC(v)  \
+		(((v) << 24) & BM_CLKCTRL_FRAC_IOFRAC)
+#define BP_CLKCTRL_FRAC_CLKGATEPIX	23
+#define BM_CLKCTRL_FRAC_CLKGATEPIX	0x00800000
+#define BM_CLKCTRL_FRAC_PIX_STABLE	0x00400000
+#define BP_CLKCTRL_FRAC_PIXFRAC	16
+#define BM_CLKCTRL_FRAC_PIXFRAC	0x003F0000
+#define BF_CLKCTRL_FRAC_PIXFRAC(v)  \
+		(((v) << 16) & BM_CLKCTRL_FRAC_PIXFRAC)
+#define BP_CLKCTRL_FRAC_CLKGATEEMI	15
+#define BM_CLKCTRL_FRAC_CLKGATEEMI	0x00008000
+#define BM_CLKCTRL_FRAC_EMI_STABLE	0x00004000
+#define BP_CLKCTRL_FRAC_EMIFRAC	8
+#define BM_CLKCTRL_FRAC_EMIFRAC	0x00003F00
+#define BF_CLKCTRL_FRAC_EMIFRAC(v)  \
+		(((v) << 8) & BM_CLKCTRL_FRAC_EMIFRAC)
+#define BP_CLKCTRL_FRAC_CLKGATECPU	7
+#define BM_CLKCTRL_FRAC_CLKGATECPU	0x00000080
+#define BM_CLKCTRL_FRAC_CPU_STABLE	0x00000040
+#define BP_CLKCTRL_FRAC_CPUFRAC	0
+#define BM_CLKCTRL_FRAC_CPUFRAC	0x0000003F
+#define BF_CLKCTRL_FRAC_CPUFRAC(v)  \
+		(((v) << 0) & BM_CLKCTRL_FRAC_CPUFRAC)
+
+#define HW_CLKCTRL_FRAC1	(0x00000100)
+#define HW_CLKCTRL_FRAC1_SET	(0x00000104)
+#define HW_CLKCTRL_FRAC1_CLR	(0x00000108)
+#define HW_CLKCTRL_FRAC1_TOG	(0x0000010c)
+
+#define BM_CLKCTRL_FRAC1_CLKGATEVID	0x80000000
+#define BM_CLKCTRL_FRAC1_VID_STABLE	0x40000000
+#define BP_CLKCTRL_FRAC1_RSRVD1	0
+#define BM_CLKCTRL_FRAC1_RSRVD1	0x3FFFFFFF
+#define BF_CLKCTRL_FRAC1_RSRVD1(v)  \
+		(((v) << 0) & BM_CLKCTRL_FRAC1_RSRVD1)
+
+#define HW_CLKCTRL_CLKSEQ	(0x00000110)
+#define HW_CLKCTRL_CLKSEQ_SET	(0x00000114)
+#define HW_CLKCTRL_CLKSEQ_CLR	(0x00000118)
+#define HW_CLKCTRL_CLKSEQ_TOG	(0x0000011c)
+
+#define BP_CLKCTRL_CLKSEQ_RSRVD1	9
+#define BM_CLKCTRL_CLKSEQ_RSRVD1	0xFFFFFE00
+#define BF_CLKCTRL_CLKSEQ_RSRVD1(v) \
+		(((v) << 9) & BM_CLKCTRL_CLKSEQ_RSRVD1)
+#define BM_CLKCTRL_CLKSEQ_BYPASS_ETM	0x00000100
+#define BM_CLKCTRL_CLKSEQ_BYPASS_CPU	0x00000080
+#define BM_CLKCTRL_CLKSEQ_BYPASS_EMI	0x00000040
+#define BM_CLKCTRL_CLKSEQ_BYPASS_SSP	0x00000020
+#define BM_CLKCTRL_CLKSEQ_BYPASS_GPMI	0x00000010
+#define BM_CLKCTRL_CLKSEQ_BYPASS_IR	0x00000008
+#define BM_CLKCTRL_CLKSEQ_RSRVD0	0x00000004
+#define BM_CLKCTRL_CLKSEQ_BYPASS_PIX	0x00000002
+#define BM_CLKCTRL_CLKSEQ_BYPASS_SAIF	0x00000001
+
+#define HW_CLKCTRL_RESET	(0x00000120)
+
+#define BP_CLKCTRL_RESET_RSRVD	2
+#define BM_CLKCTRL_RESET_RSRVD	0xFFFFFFFC
+#define BF_CLKCTRL_RESET_RSRVD(v) \
+		(((v) << 2) & BM_CLKCTRL_RESET_RSRVD)
+#define BM_CLKCTRL_RESET_CHIP	0x00000002
+#define BM_CLKCTRL_RESET_DIG	0x00000001
+
+#define HW_CLKCTRL_STATUS	(0x00000130)
+
+#define BP_CLKCTRL_STATUS_CPU_LIMIT	30
+#define BM_CLKCTRL_STATUS_CPU_LIMIT	0xC0000000
+#define BF_CLKCTRL_STATUS_CPU_LIMIT(v) \
+		(((v) << 30) & BM_CLKCTRL_STATUS_CPU_LIMIT)
+#define BP_CLKCTRL_STATUS_RSRVD	0
+#define BM_CLKCTRL_STATUS_RSRVD	0x3FFFFFFF
+#define BF_CLKCTRL_STATUS_RSRVD(v)  \
+		(((v) << 0) & BM_CLKCTRL_STATUS_RSRVD)
+
+#define HW_CLKCTRL_VERSION	(0x00000140)
+
+#define BP_CLKCTRL_VERSION_MAJOR	24
+#define BM_CLKCTRL_VERSION_MAJOR	0xFF000000
+#define BF_CLKCTRL_VERSION_MAJOR(v) \
+		(((v) << 24) & BM_CLKCTRL_VERSION_MAJOR)
+#define BP_CLKCTRL_VERSION_MINOR	16
+#define BM_CLKCTRL_VERSION_MINOR	0x00FF0000
+#define BF_CLKCTRL_VERSION_MINOR(v)  \
+		(((v) << 16) & BM_CLKCTRL_VERSION_MINOR)
+#define BP_CLKCTRL_VERSION_STEP	0
+#define BM_CLKCTRL_VERSION_STEP	0x0000FFFF
+#define BF_CLKCTRL_VERSION_STEP(v)  \
+		(((v) << 0) & BM_CLKCTRL_VERSION_STEP)
+
+#endif /* __REGS_CLKCTRL_MX23_H__ */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mxs/regs-clkctrl-mx28.h linux-libre-2.6.38-gnu1/arch/arm/mach-mxs/regs-clkctrl-mx28.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mxs/regs-clkctrl-mx28.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mxs/regs-clkctrl-mx28.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,663 @@
+/*
+ * Freescale CLKCTRL Register Definitions
+ *
+ * Copyright 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ * This file is created by xml file. Don't Edit it.
+ *
+ * Xml Revision: 1.48
+ * Template revision: 26195
+ */
+
+#ifndef __REGS_CLKCTRL_MX28_H__
+#define __REGS_CLKCTRL_MX28_H__
+
+#define HW_CLKCTRL_PLL0CTRL0	(0x00000000)
+#define HW_CLKCTRL_PLL0CTRL0_SET	(0x00000004)
+#define HW_CLKCTRL_PLL0CTRL0_CLR	(0x00000008)
+#define HW_CLKCTRL_PLL0CTRL0_TOG	(0x0000000c)
+
+#define BP_CLKCTRL_PLL0CTRL0_RSRVD6	30
+#define BM_CLKCTRL_PLL0CTRL0_RSRVD6	0xC0000000
+#define BF_CLKCTRL_PLL0CTRL0_RSRVD6(v) \
+		(((v) << 30) & BM_CLKCTRL_PLL0CTRL0_RSRVD6)
+#define BP_CLKCTRL_PLL0CTRL0_LFR_SEL	28
+#define BM_CLKCTRL_PLL0CTRL0_LFR_SEL	0x30000000
+#define BF_CLKCTRL_PLL0CTRL0_LFR_SEL(v)  \
+		(((v) << 28) & BM_CLKCTRL_PLL0CTRL0_LFR_SEL)
+#define BV_CLKCTRL_PLL0CTRL0_LFR_SEL__DEFAULT   0x0
+#define BV_CLKCTRL_PLL0CTRL0_LFR_SEL__TIMES_2   0x1
+#define BV_CLKCTRL_PLL0CTRL0_LFR_SEL__TIMES_05  0x2
+#define BV_CLKCTRL_PLL0CTRL0_LFR_SEL__UNDEFINED 0x3
+#define BP_CLKCTRL_PLL0CTRL0_RSRVD5	26
+#define BM_CLKCTRL_PLL0CTRL0_RSRVD5	0x0C000000
+#define BF_CLKCTRL_PLL0CTRL0_RSRVD5(v)  \
+		(((v) << 26) & BM_CLKCTRL_PLL0CTRL0_RSRVD5)
+#define BP_CLKCTRL_PLL0CTRL0_CP_SEL	24
+#define BM_CLKCTRL_PLL0CTRL0_CP_SEL	0x03000000
+#define BF_CLKCTRL_PLL0CTRL0_CP_SEL(v)  \
+		(((v) << 24) & BM_CLKCTRL_PLL0CTRL0_CP_SEL)
+#define BV_CLKCTRL_PLL0CTRL0_CP_SEL__DEFAULT   0x0
+#define BV_CLKCTRL_PLL0CTRL0_CP_SEL__TIMES_2   0x1
+#define BV_CLKCTRL_PLL0CTRL0_CP_SEL__TIMES_05  0x2
+#define BV_CLKCTRL_PLL0CTRL0_CP_SEL__UNDEFINED 0x3
+#define BP_CLKCTRL_PLL0CTRL0_RSRVD4	22
+#define BM_CLKCTRL_PLL0CTRL0_RSRVD4	0x00C00000
+#define BF_CLKCTRL_PLL0CTRL0_RSRVD4(v)  \
+		(((v) << 22) & BM_CLKCTRL_PLL0CTRL0_RSRVD4)
+#define BP_CLKCTRL_PLL0CTRL0_DIV_SEL	20
+#define BM_CLKCTRL_PLL0CTRL0_DIV_SEL	0x00300000
+#define BF_CLKCTRL_PLL0CTRL0_DIV_SEL(v)  \
+		(((v) << 20) & BM_CLKCTRL_PLL0CTRL0_DIV_SEL)
+#define BV_CLKCTRL_PLL0CTRL0_DIV_SEL__DEFAULT   0x0
+#define BV_CLKCTRL_PLL0CTRL0_DIV_SEL__LOWER     0x1
+#define BV_CLKCTRL_PLL0CTRL0_DIV_SEL__LOWEST    0x2
+#define BV_CLKCTRL_PLL0CTRL0_DIV_SEL__UNDEFINED 0x3
+#define BM_CLKCTRL_PLL0CTRL0_RSRVD3	0x00080000
+#define BM_CLKCTRL_PLL0CTRL0_EN_USB_CLKS	0x00040000
+#define BM_CLKCTRL_PLL0CTRL0_POWER	0x00020000
+#define BP_CLKCTRL_PLL0CTRL0_RSRVD1	0
+#define BM_CLKCTRL_PLL0CTRL0_RSRVD1	0x0001FFFF
+#define BF_CLKCTRL_PLL0CTRL0_RSRVD1(v)  \
+		(((v) << 0) & BM_CLKCTRL_PLL0CTRL0_RSRVD1)
+
+#define HW_CLKCTRL_PLL0CTRL1	(0x00000010)
+
+#define BM_CLKCTRL_PLL0CTRL1_LOCK	0x80000000
+#define BM_CLKCTRL_PLL0CTRL1_FORCE_LOCK	0x40000000
+#define BP_CLKCTRL_PLL0CTRL1_RSRVD1	16
+#define BM_CLKCTRL_PLL0CTRL1_RSRVD1	0x3FFF0000
+#define BF_CLKCTRL_PLL0CTRL1_RSRVD1(v)  \
+		(((v) << 16) & BM_CLKCTRL_PLL0CTRL1_RSRVD1)
+#define BP_CLKCTRL_PLL0CTRL1_LOCK_COUNT	0
+#define BM_CLKCTRL_PLL0CTRL1_LOCK_COUNT	0x0000FFFF
+#define BF_CLKCTRL_PLL0CTRL1_LOCK_COUNT(v)  \
+		(((v) << 0) & BM_CLKCTRL_PLL0CTRL1_LOCK_COUNT)
+
+#define HW_CLKCTRL_PLL1CTRL0	(0x00000020)
+#define HW_CLKCTRL_PLL1CTRL0_SET	(0x00000024)
+#define HW_CLKCTRL_PLL1CTRL0_CLR	(0x00000028)
+#define HW_CLKCTRL_PLL1CTRL0_TOG	(0x0000002c)
+
+#define BM_CLKCTRL_PLL1CTRL0_CLKGATEEMI	0x80000000
+#define BM_CLKCTRL_PLL1CTRL0_RSRVD6	0x40000000
+#define BP_CLKCTRL_PLL1CTRL0_LFR_SEL	28
+#define BM_CLKCTRL_PLL1CTRL0_LFR_SEL	0x30000000
+#define BF_CLKCTRL_PLL1CTRL0_LFR_SEL(v)  \
+		(((v) << 28) & BM_CLKCTRL_PLL1CTRL0_LFR_SEL)
+#define BV_CLKCTRL_PLL1CTRL0_LFR_SEL__DEFAULT   0x0
+#define BV_CLKCTRL_PLL1CTRL0_LFR_SEL__TIMES_2   0x1
+#define BV_CLKCTRL_PLL1CTRL0_LFR_SEL__TIMES_05  0x2
+#define BV_CLKCTRL_PLL1CTRL0_LFR_SEL__UNDEFINED 0x3
+#define BP_CLKCTRL_PLL1CTRL0_RSRVD5	26
+#define BM_CLKCTRL_PLL1CTRL0_RSRVD5	0x0C000000
+#define BF_CLKCTRL_PLL1CTRL0_RSRVD5(v)  \
+		(((v) << 26) & BM_CLKCTRL_PLL1CTRL0_RSRVD5)
+#define BP_CLKCTRL_PLL1CTRL0_CP_SEL	24
+#define BM_CLKCTRL_PLL1CTRL0_CP_SEL	0x03000000
+#define BF_CLKCTRL_PLL1CTRL0_CP_SEL(v)  \
+		(((v) << 24) & BM_CLKCTRL_PLL1CTRL0_CP_SEL)
+#define BV_CLKCTRL_PLL1CTRL0_CP_SEL__DEFAULT   0x0
+#define BV_CLKCTRL_PLL1CTRL0_CP_SEL__TIMES_2   0x1
+#define BV_CLKCTRL_PLL1CTRL0_CP_SEL__TIMES_05  0x2
+#define BV_CLKCTRL_PLL1CTRL0_CP_SEL__UNDEFINED 0x3
+#define BP_CLKCTRL_PLL1CTRL0_RSRVD4	22
+#define BM_CLKCTRL_PLL1CTRL0_RSRVD4	0x00C00000
+#define BF_CLKCTRL_PLL1CTRL0_RSRVD4(v)  \
+		(((v) << 22) & BM_CLKCTRL_PLL1CTRL0_RSRVD4)
+#define BP_CLKCTRL_PLL1CTRL0_DIV_SEL	20
+#define BM_CLKCTRL_PLL1CTRL0_DIV_SEL	0x00300000
+#define BF_CLKCTRL_PLL1CTRL0_DIV_SEL(v)  \
+		(((v) << 20) & BM_CLKCTRL_PLL1CTRL0_DIV_SEL)
+#define BV_CLKCTRL_PLL1CTRL0_DIV_SEL__DEFAULT   0x0
+#define BV_CLKCTRL_PLL1CTRL0_DIV_SEL__LOWER     0x1
+#define BV_CLKCTRL_PLL1CTRL0_DIV_SEL__LOWEST    0x2
+#define BV_CLKCTRL_PLL1CTRL0_DIV_SEL__UNDEFINED 0x3
+#define BM_CLKCTRL_PLL1CTRL0_RSRVD3	0x00080000
+#define BM_CLKCTRL_PLL1CTRL0_EN_USB_CLKS	0x00040000
+#define BM_CLKCTRL_PLL1CTRL0_POWER	0x00020000
+#define BP_CLKCTRL_PLL1CTRL0_RSRVD1	0
+#define BM_CLKCTRL_PLL1CTRL0_RSRVD1	0x0001FFFF
+#define BF_CLKCTRL_PLL1CTRL0_RSRVD1(v)  \
+		(((v) << 0) & BM_CLKCTRL_PLL1CTRL0_RSRVD1)
+
+#define HW_CLKCTRL_PLL1CTRL1	(0x00000030)
+
+#define BM_CLKCTRL_PLL1CTRL1_LOCK	0x80000000
+#define BM_CLKCTRL_PLL1CTRL1_FORCE_LOCK	0x40000000
+#define BP_CLKCTRL_PLL1CTRL1_RSRVD1	16
+#define BM_CLKCTRL_PLL1CTRL1_RSRVD1	0x3FFF0000
+#define BF_CLKCTRL_PLL1CTRL1_RSRVD1(v)  \
+		(((v) << 16) & BM_CLKCTRL_PLL1CTRL1_RSRVD1)
+#define BP_CLKCTRL_PLL1CTRL1_LOCK_COUNT	0
+#define BM_CLKCTRL_PLL1CTRL1_LOCK_COUNT	0x0000FFFF
+#define BF_CLKCTRL_PLL1CTRL1_LOCK_COUNT(v)  \
+		(((v) << 0) & BM_CLKCTRL_PLL1CTRL1_LOCK_COUNT)
+
+#define HW_CLKCTRL_PLL2CTRL0	(0x00000040)
+#define HW_CLKCTRL_PLL2CTRL0_SET	(0x00000044)
+#define HW_CLKCTRL_PLL2CTRL0_CLR	(0x00000048)
+#define HW_CLKCTRL_PLL2CTRL0_TOG	(0x0000004c)
+
+#define BM_CLKCTRL_PLL2CTRL0_CLKGATE	0x80000000
+#define BM_CLKCTRL_PLL2CTRL0_RSRVD3	0x40000000
+#define BP_CLKCTRL_PLL2CTRL0_LFR_SEL	28
+#define BM_CLKCTRL_PLL2CTRL0_LFR_SEL	0x30000000
+#define BF_CLKCTRL_PLL2CTRL0_LFR_SEL(v)  \
+		(((v) << 28) & BM_CLKCTRL_PLL2CTRL0_LFR_SEL)
+#define BM_CLKCTRL_PLL2CTRL0_RSRVD2	0x08000000
+#define BM_CLKCTRL_PLL2CTRL0_HOLD_RING_OFF_B	0x04000000
+#define BP_CLKCTRL_PLL2CTRL0_CP_SEL	24
+#define BM_CLKCTRL_PLL2CTRL0_CP_SEL	0x03000000
+#define BF_CLKCTRL_PLL2CTRL0_CP_SEL(v)  \
+		(((v) << 24) & BM_CLKCTRL_PLL2CTRL0_CP_SEL)
+#define BM_CLKCTRL_PLL2CTRL0_POWER	0x00800000
+#define BP_CLKCTRL_PLL2CTRL0_RSRVD1	0
+#define BM_CLKCTRL_PLL2CTRL0_RSRVD1	0x007FFFFF
+#define BF_CLKCTRL_PLL2CTRL0_RSRVD1(v)  \
+		(((v) << 0) & BM_CLKCTRL_PLL2CTRL0_RSRVD1)
+
+#define HW_CLKCTRL_CPU	(0x00000050)
+#define HW_CLKCTRL_CPU_SET	(0x00000054)
+#define HW_CLKCTRL_CPU_CLR	(0x00000058)
+#define HW_CLKCTRL_CPU_TOG	(0x0000005c)
+
+#define BP_CLKCTRL_CPU_RSRVD5	30
+#define BM_CLKCTRL_CPU_RSRVD5	0xC0000000
+#define BF_CLKCTRL_CPU_RSRVD5(v) \
+		(((v) << 30) & BM_CLKCTRL_CPU_RSRVD5)
+#define BM_CLKCTRL_CPU_BUSY_REF_XTAL	0x20000000
+#define BM_CLKCTRL_CPU_BUSY_REF_CPU	0x10000000
+#define BM_CLKCTRL_CPU_RSRVD4	0x08000000
+#define BM_CLKCTRL_CPU_DIV_XTAL_FRAC_EN	0x04000000
+#define BP_CLKCTRL_CPU_DIV_XTAL	16
+#define BM_CLKCTRL_CPU_DIV_XTAL	0x03FF0000
+#define BF_CLKCTRL_CPU_DIV_XTAL(v)  \
+		(((v) << 16) & BM_CLKCTRL_CPU_DIV_XTAL)
+#define BP_CLKCTRL_CPU_RSRVD3	13
+#define BM_CLKCTRL_CPU_RSRVD3	0x0000E000
+#define BF_CLKCTRL_CPU_RSRVD3(v)  \
+		(((v) << 13) & BM_CLKCTRL_CPU_RSRVD3)
+#define BM_CLKCTRL_CPU_INTERRUPT_WAIT	0x00001000
+#define BM_CLKCTRL_CPU_RSRVD2	0x00000800
+#define BM_CLKCTRL_CPU_DIV_CPU_FRAC_EN	0x00000400
+#define BP_CLKCTRL_CPU_RSRVD1	6
+#define BM_CLKCTRL_CPU_RSRVD1	0x000003C0
+#define BF_CLKCTRL_CPU_RSRVD1(v)  \
+		(((v) << 6) & BM_CLKCTRL_CPU_RSRVD1)
+#define BP_CLKCTRL_CPU_DIV_CPU	0
+#define BM_CLKCTRL_CPU_DIV_CPU	0x0000003F
+#define BF_CLKCTRL_CPU_DIV_CPU(v)  \
+		(((v) << 0) & BM_CLKCTRL_CPU_DIV_CPU)
+
+#define HW_CLKCTRL_HBUS	(0x00000060)
+#define HW_CLKCTRL_HBUS_SET	(0x00000064)
+#define HW_CLKCTRL_HBUS_CLR	(0x00000068)
+#define HW_CLKCTRL_HBUS_TOG	(0x0000006c)
+
+#define BM_CLKCTRL_HBUS_ASM_BUSY	0x80000000
+#define BM_CLKCTRL_HBUS_DCP_AS_ENABLE	0x40000000
+#define BM_CLKCTRL_HBUS_PXP_AS_ENABLE	0x20000000
+#define BM_CLKCTRL_HBUS_RSRVD2	0x10000000
+#define BM_CLKCTRL_HBUS_ASM_EMIPORT_AS_ENABLE	0x08000000
+#define BM_CLKCTRL_HBUS_APBHDMA_AS_ENABLE	0x04000000
+#define BM_CLKCTRL_HBUS_APBXDMA_AS_ENABLE	0x02000000
+#define BM_CLKCTRL_HBUS_TRAFFIC_JAM_AS_ENABLE	0x01000000
+#define BM_CLKCTRL_HBUS_TRAFFIC_AS_ENABLE	0x00800000
+#define BM_CLKCTRL_HBUS_CPU_DATA_AS_ENABLE	0x00400000
+#define BM_CLKCTRL_HBUS_CPU_INSTR_AS_ENABLE	0x00200000
+#define BM_CLKCTRL_HBUS_ASM_ENABLE	0x00100000
+#define BM_CLKCTRL_HBUS_AUTO_CLEAR_DIV_ENABLE	0x00080000
+#define BP_CLKCTRL_HBUS_SLOW_DIV	16
+#define BM_CLKCTRL_HBUS_SLOW_DIV	0x00070000
+#define BF_CLKCTRL_HBUS_SLOW_DIV(v)  \
+		(((v) << 16) & BM_CLKCTRL_HBUS_SLOW_DIV)
+#define BV_CLKCTRL_HBUS_SLOW_DIV__BY1  0x0
+#define BV_CLKCTRL_HBUS_SLOW_DIV__BY2  0x1
+#define BV_CLKCTRL_HBUS_SLOW_DIV__BY4  0x2
+#define BV_CLKCTRL_HBUS_SLOW_DIV__BY8  0x3
+#define BV_CLKCTRL_HBUS_SLOW_DIV__BY16 0x4
+#define BV_CLKCTRL_HBUS_SLOW_DIV__BY32 0x5
+#define BP_CLKCTRL_HBUS_RSRVD1	6
+#define BM_CLKCTRL_HBUS_RSRVD1	0x0000FFC0
+#define BF_CLKCTRL_HBUS_RSRVD1(v)  \
+		(((v) << 6) & BM_CLKCTRL_HBUS_RSRVD1)
+#define BM_CLKCTRL_HBUS_DIV_FRAC_EN	0x00000020
+#define BP_CLKCTRL_HBUS_DIV	0
+#define BM_CLKCTRL_HBUS_DIV	0x0000001F
+#define BF_CLKCTRL_HBUS_DIV(v)  \
+		(((v) << 0) & BM_CLKCTRL_HBUS_DIV)
+
+#define HW_CLKCTRL_XBUS	(0x00000070)
+
+#define BM_CLKCTRL_XBUS_BUSY	0x80000000
+#define BP_CLKCTRL_XBUS_RSRVD1	12
+#define BM_CLKCTRL_XBUS_RSRVD1	0x7FFFF000
+#define BF_CLKCTRL_XBUS_RSRVD1(v)  \
+		(((v) << 12) & BM_CLKCTRL_XBUS_RSRVD1)
+#define BM_CLKCTRL_XBUS_AUTO_CLEAR_DIV_ENABLE	0x00000800
+#define BM_CLKCTRL_XBUS_DIV_FRAC_EN	0x00000400
+#define BP_CLKCTRL_XBUS_DIV	0
+#define BM_CLKCTRL_XBUS_DIV	0x000003FF
+#define BF_CLKCTRL_XBUS_DIV(v)  \
+		(((v) << 0) & BM_CLKCTRL_XBUS_DIV)
+
+#define HW_CLKCTRL_XTAL	(0x00000080)
+#define HW_CLKCTRL_XTAL_SET	(0x00000084)
+#define HW_CLKCTRL_XTAL_CLR	(0x00000088)
+#define HW_CLKCTRL_XTAL_TOG	(0x0000008c)
+
+#define BP_CLKCTRL_XTAL_UART_CLK_GATE	31
+#define BM_CLKCTRL_XTAL_UART_CLK_GATE	0x80000000
+#define BM_CLKCTRL_XTAL_RSRVD3	0x40000000
+#define BP_CLKCTRL_XTAL_PWM_CLK24M_GATE	29
+#define BM_CLKCTRL_XTAL_PWM_CLK24M_GATE	0x20000000
+#define BP_CLKCTRL_XTAL_RSRVD2	27
+#define BM_CLKCTRL_XTAL_RSRVD2	0x18000000
+#define BF_CLKCTRL_XTAL_RSRVD2(v)  \
+		(((v) << 27) & BM_CLKCTRL_XTAL_RSRVD2)
+#define BP_CLKCTRL_XTAL_TIMROT_CLK32K_GATE	26
+#define BM_CLKCTRL_XTAL_TIMROT_CLK32K_GATE	0x04000000
+#define BP_CLKCTRL_XTAL_RSRVD1	2
+#define BM_CLKCTRL_XTAL_RSRVD1	0x03FFFFFC
+#define BF_CLKCTRL_XTAL_RSRVD1(v)  \
+		(((v) << 2) & BM_CLKCTRL_XTAL_RSRVD1)
+#define BP_CLKCTRL_XTAL_DIV_UART	0
+#define BM_CLKCTRL_XTAL_DIV_UART	0x00000003
+#define BF_CLKCTRL_XTAL_DIV_UART(v)  \
+		(((v) << 0) & BM_CLKCTRL_XTAL_DIV_UART)
+
+#define HW_CLKCTRL_SSP0	(0x00000090)
+
+#define BP_CLKCTRL_SSP0_CLKGATE	31
+#define BM_CLKCTRL_SSP0_CLKGATE	0x80000000
+#define BM_CLKCTRL_SSP0_RSRVD2	0x40000000
+#define BM_CLKCTRL_SSP0_BUSY	0x20000000
+#define BP_CLKCTRL_SSP0_RSRVD1	10
+#define BM_CLKCTRL_SSP0_RSRVD1	0x1FFFFC00
+#define BF_CLKCTRL_SSP0_RSRVD1(v)  \
+		(((v) << 10) & BM_CLKCTRL_SSP0_RSRVD1)
+#define BM_CLKCTRL_SSP0_DIV_FRAC_EN	0x00000200
+#define BP_CLKCTRL_SSP0_DIV	0
+#define BM_CLKCTRL_SSP0_DIV	0x000001FF
+#define BF_CLKCTRL_SSP0_DIV(v)  \
+		(((v) << 0) & BM_CLKCTRL_SSP0_DIV)
+
+#define HW_CLKCTRL_SSP1	(0x000000a0)
+
+#define BP_CLKCTRL_SSP1_CLKGATE	31
+#define BM_CLKCTRL_SSP1_CLKGATE	0x80000000
+#define BM_CLKCTRL_SSP1_RSRVD2	0x40000000
+#define BM_CLKCTRL_SSP1_BUSY	0x20000000
+#define BP_CLKCTRL_SSP1_RSRVD1	10
+#define BM_CLKCTRL_SSP1_RSRVD1	0x1FFFFC00
+#define BF_CLKCTRL_SSP1_RSRVD1(v)  \
+		(((v) << 10) & BM_CLKCTRL_SSP1_RSRVD1)
+#define BM_CLKCTRL_SSP1_DIV_FRAC_EN	0x00000200
+#define BP_CLKCTRL_SSP1_DIV	0
+#define BM_CLKCTRL_SSP1_DIV	0x000001FF
+#define BF_CLKCTRL_SSP1_DIV(v)  \
+		(((v) << 0) & BM_CLKCTRL_SSP1_DIV)
+
+#define HW_CLKCTRL_SSP2	(0x000000b0)
+
+#define BP_CLKCTRL_SSP2_CLKGATE	31
+#define BM_CLKCTRL_SSP2_CLKGATE	0x80000000
+#define BM_CLKCTRL_SSP2_RSRVD2	0x40000000
+#define BM_CLKCTRL_SSP2_BUSY	0x20000000
+#define BP_CLKCTRL_SSP2_RSRVD1	10
+#define BM_CLKCTRL_SSP2_RSRVD1	0x1FFFFC00
+#define BF_CLKCTRL_SSP2_RSRVD1(v)  \
+		(((v) << 10) & BM_CLKCTRL_SSP2_RSRVD1)
+#define BM_CLKCTRL_SSP2_DIV_FRAC_EN	0x00000200
+#define BP_CLKCTRL_SSP2_DIV	0
+#define BM_CLKCTRL_SSP2_DIV	0x000001FF
+#define BF_CLKCTRL_SSP2_DIV(v)  \
+		(((v) << 0) & BM_CLKCTRL_SSP2_DIV)
+
+#define HW_CLKCTRL_SSP3	(0x000000c0)
+
+#define BP_CLKCTRL_SSP3_CLKGATE	31
+#define BM_CLKCTRL_SSP3_CLKGATE	0x80000000
+#define BM_CLKCTRL_SSP3_RSRVD2	0x40000000
+#define BM_CLKCTRL_SSP3_BUSY	0x20000000
+#define BP_CLKCTRL_SSP3_RSRVD1	10
+#define BM_CLKCTRL_SSP3_RSRVD1	0x1FFFFC00
+#define BF_CLKCTRL_SSP3_RSRVD1(v)  \
+		(((v) << 10) & BM_CLKCTRL_SSP3_RSRVD1)
+#define BM_CLKCTRL_SSP3_DIV_FRAC_EN	0x00000200
+#define BP_CLKCTRL_SSP3_DIV	0
+#define BM_CLKCTRL_SSP3_DIV	0x000001FF
+#define BF_CLKCTRL_SSP3_DIV(v)  \
+		(((v) << 0) & BM_CLKCTRL_SSP3_DIV)
+
+#define HW_CLKCTRL_GPMI	(0x000000d0)
+
+#define BP_CLKCTRL_GPMI_CLKGATE	31
+#define BM_CLKCTRL_GPMI_CLKGATE	0x80000000
+#define BM_CLKCTRL_GPMI_RSRVD2	0x40000000
+#define BM_CLKCTRL_GPMI_BUSY	0x20000000
+#define BP_CLKCTRL_GPMI_RSRVD1	11
+#define BM_CLKCTRL_GPMI_RSRVD1	0x1FFFF800
+#define BF_CLKCTRL_GPMI_RSRVD1(v)  \
+		(((v) << 11) & BM_CLKCTRL_GPMI_RSRVD1)
+#define BM_CLKCTRL_GPMI_DIV_FRAC_EN	0x00000400
+#define BP_CLKCTRL_GPMI_DIV	0
+#define BM_CLKCTRL_GPMI_DIV	0x000003FF
+#define BF_CLKCTRL_GPMI_DIV(v)  \
+		(((v) << 0) & BM_CLKCTRL_GPMI_DIV)
+
+#define HW_CLKCTRL_SPDIF	(0x000000e0)
+
+#define BP_CLKCTRL_SPDIF_CLKGATE	31
+#define BM_CLKCTRL_SPDIF_CLKGATE	0x80000000
+#define BP_CLKCTRL_SPDIF_RSRVD	0
+#define BM_CLKCTRL_SPDIF_RSRVD	0x7FFFFFFF
+#define BF_CLKCTRL_SPDIF_RSRVD(v)  \
+		(((v) << 0) & BM_CLKCTRL_SPDIF_RSRVD)
+
+#define HW_CLKCTRL_EMI	(0x000000f0)
+
+#define BP_CLKCTRL_EMI_CLKGATE	31
+#define BM_CLKCTRL_EMI_CLKGATE	0x80000000
+#define BM_CLKCTRL_EMI_SYNC_MODE_EN	0x40000000
+#define BM_CLKCTRL_EMI_BUSY_REF_XTAL	0x20000000
+#define BM_CLKCTRL_EMI_BUSY_REF_EMI	0x10000000
+#define BM_CLKCTRL_EMI_BUSY_REF_CPU	0x08000000
+#define BM_CLKCTRL_EMI_BUSY_SYNC_MODE	0x04000000
+#define BP_CLKCTRL_EMI_RSRVD3	18
+#define BM_CLKCTRL_EMI_RSRVD3	0x03FC0000
+#define BF_CLKCTRL_EMI_RSRVD3(v)  \
+		(((v) << 18) & BM_CLKCTRL_EMI_RSRVD3)
+#define BM_CLKCTRL_EMI_BUSY_DCC_RESYNC	0x00020000
+#define BM_CLKCTRL_EMI_DCC_RESYNC_ENABLE	0x00010000
+#define BP_CLKCTRL_EMI_RSRVD2	12
+#define BM_CLKCTRL_EMI_RSRVD2	0x0000F000
+#define BF_CLKCTRL_EMI_RSRVD2(v)  \
+		(((v) << 12) & BM_CLKCTRL_EMI_RSRVD2)
+#define BP_CLKCTRL_EMI_DIV_XTAL	8
+#define BM_CLKCTRL_EMI_DIV_XTAL	0x00000F00
+#define BF_CLKCTRL_EMI_DIV_XTAL(v)  \
+		(((v) << 8) & BM_CLKCTRL_EMI_DIV_XTAL)
+#define BP_CLKCTRL_EMI_RSRVD1	6
+#define BM_CLKCTRL_EMI_RSRVD1	0x000000C0
+#define BF_CLKCTRL_EMI_RSRVD1(v)  \
+		(((v) << 6) & BM_CLKCTRL_EMI_RSRVD1)
+#define BP_CLKCTRL_EMI_DIV_EMI	0
+#define BM_CLKCTRL_EMI_DIV_EMI	0x0000003F
+#define BF_CLKCTRL_EMI_DIV_EMI(v)  \
+		(((v) << 0) & BM_CLKCTRL_EMI_DIV_EMI)
+
+#define HW_CLKCTRL_SAIF0	(0x00000100)
+
+#define BP_CLKCTRL_SAIF0_CLKGATE	31
+#define BM_CLKCTRL_SAIF0_CLKGATE	0x80000000
+#define BM_CLKCTRL_SAIF0_RSRVD2	0x40000000
+#define BM_CLKCTRL_SAIF0_BUSY	0x20000000
+#define BP_CLKCTRL_SAIF0_RSRVD1	17
+#define BM_CLKCTRL_SAIF0_RSRVD1	0x1FFE0000
+#define BF_CLKCTRL_SAIF0_RSRVD1(v)  \
+		(((v) << 17) & BM_CLKCTRL_SAIF0_RSRVD1)
+#define BM_CLKCTRL_SAIF0_DIV_FRAC_EN	0x00010000
+#define BP_CLKCTRL_SAIF0_DIV	0
+#define BM_CLKCTRL_SAIF0_DIV	0x0000FFFF
+#define BF_CLKCTRL_SAIF0_DIV(v)  \
+		(((v) << 0) & BM_CLKCTRL_SAIF0_DIV)
+
+#define HW_CLKCTRL_SAIF1	(0x00000110)
+
+#define BP_CLKCTRL_SAIF1_CLKGATE	31
+#define BM_CLKCTRL_SAIF1_CLKGATE	0x80000000
+#define BM_CLKCTRL_SAIF1_RSRVD2	0x40000000
+#define BM_CLKCTRL_SAIF1_BUSY	0x20000000
+#define BP_CLKCTRL_SAIF1_RSRVD1	17
+#define BM_CLKCTRL_SAIF1_RSRVD1	0x1FFE0000
+#define BF_CLKCTRL_SAIF1_RSRVD1(v)  \
+		(((v) << 17) & BM_CLKCTRL_SAIF1_RSRVD1)
+#define BM_CLKCTRL_SAIF1_DIV_FRAC_EN	0x00010000
+#define BP_CLKCTRL_SAIF1_DIV	0
+#define BM_CLKCTRL_SAIF1_DIV	0x0000FFFF
+#define BF_CLKCTRL_SAIF1_DIV(v)  \
+		(((v) << 0) & BM_CLKCTRL_SAIF1_DIV)
+
+#define HW_CLKCTRL_DIS_LCDIF	(0x00000120)
+
+#define BP_CLKCTRL_DIS_LCDIF_CLKGATE	31
+#define BM_CLKCTRL_DIS_LCDIF_CLKGATE	0x80000000
+#define BM_CLKCTRL_DIS_LCDIF_RSRVD2	0x40000000
+#define BM_CLKCTRL_DIS_LCDIF_BUSY	0x20000000
+#define BP_CLKCTRL_DIS_LCDIF_RSRVD1	14
+#define BM_CLKCTRL_DIS_LCDIF_RSRVD1	0x1FFFC000
+#define BF_CLKCTRL_DIS_LCDIF_RSRVD1(v)  \
+		(((v) << 14) & BM_CLKCTRL_DIS_LCDIF_RSRVD1)
+#define BM_CLKCTRL_DIS_LCDIF_DIV_FRAC_EN	0x00002000
+#define BP_CLKCTRL_DIS_LCDIF_DIV	0
+#define BM_CLKCTRL_DIS_LCDIF_DIV	0x00001FFF
+#define BF_CLKCTRL_DIS_LCDIF_DIV(v)  \
+		(((v) << 0) & BM_CLKCTRL_DIS_LCDIF_DIV)
+
+#define HW_CLKCTRL_ETM	(0x00000130)
+
+#define BM_CLKCTRL_ETM_CLKGATE	0x80000000
+#define BM_CLKCTRL_ETM_RSRVD2	0x40000000
+#define BM_CLKCTRL_ETM_BUSY	0x20000000
+#define BP_CLKCTRL_ETM_RSRVD1	8
+#define BM_CLKCTRL_ETM_RSRVD1	0x1FFFFF00
+#define BF_CLKCTRL_ETM_RSRVD1(v)  \
+		(((v) << 8) & BM_CLKCTRL_ETM_RSRVD1)
+#define BM_CLKCTRL_ETM_DIV_FRAC_EN	0x00000080
+#define BP_CLKCTRL_ETM_DIV	0
+#define BM_CLKCTRL_ETM_DIV	0x0000007F
+#define BF_CLKCTRL_ETM_DIV(v)  \
+		(((v) << 0) & BM_CLKCTRL_ETM_DIV)
+
+#define HW_CLKCTRL_ENET	(0x00000140)
+
+#define BM_CLKCTRL_ENET_SLEEP	0x80000000
+#define BP_CLKCTRL_ENET_DISABLE	30
+#define BM_CLKCTRL_ENET_DISABLE	0x40000000
+#define BM_CLKCTRL_ENET_STATUS	0x20000000
+#define BM_CLKCTRL_ENET_RSRVD1	0x10000000
+#define BM_CLKCTRL_ENET_BUSY_TIME	0x08000000
+#define BP_CLKCTRL_ENET_DIV_TIME	21
+#define BM_CLKCTRL_ENET_DIV_TIME	0x07E00000
+#define BF_CLKCTRL_ENET_DIV_TIME(v)  \
+		(((v) << 21) & BM_CLKCTRL_ENET_DIV_TIME)
+#define BM_CLKCTRL_ENET_BUSY	0x08000000
+#define BP_CLKCTRL_ENET_DIV	21
+#define BM_CLKCTRL_ENET_DIV	0x07E00000
+#define BF_CLKCTRL_ENET_DIV(v)  \
+		(((v) << 21) & BM_CLKCTRL_ENET_DIV)
+#define BP_CLKCTRL_ENET_TIME_SEL	19
+#define BM_CLKCTRL_ENET_TIME_SEL	0x00180000
+#define BF_CLKCTRL_ENET_TIME_SEL(v)  \
+		(((v) << 19) & BM_CLKCTRL_ENET_TIME_SEL)
+#define BV_CLKCTRL_ENET_TIME_SEL__XTAL      0x0
+#define BV_CLKCTRL_ENET_TIME_SEL__PLL       0x1
+#define BV_CLKCTRL_ENET_TIME_SEL__RMII_CLK  0x2
+#define BV_CLKCTRL_ENET_TIME_SEL__UNDEFINED 0x3
+#define BM_CLKCTRL_ENET_CLK_OUT_EN	0x00040000
+#define BM_CLKCTRL_ENET_RESET_BY_SW_CHIP	0x00020000
+#define BM_CLKCTRL_ENET_RESET_BY_SW	0x00010000
+#define BP_CLKCTRL_ENET_RSRVD0	0
+#define BM_CLKCTRL_ENET_RSRVD0	0x0000FFFF
+#define BF_CLKCTRL_ENET_RSRVD0(v)  \
+		(((v) << 0) & BM_CLKCTRL_ENET_RSRVD0)
+
+#define HW_CLKCTRL_HSADC	(0x00000150)
+
+#define BM_CLKCTRL_HSADC_RSRVD2	0x80000000
+#define BM_CLKCTRL_HSADC_RESETB	0x40000000
+#define BP_CLKCTRL_HSADC_FREQDIV	28
+#define BM_CLKCTRL_HSADC_FREQDIV	0x30000000
+#define BF_CLKCTRL_HSADC_FREQDIV(v)  \
+		(((v) << 28) & BM_CLKCTRL_HSADC_FREQDIV)
+#define BP_CLKCTRL_HSADC_RSRVD1	0
+#define BM_CLKCTRL_HSADC_RSRVD1	0x0FFFFFFF
+#define BF_CLKCTRL_HSADC_RSRVD1(v)  \
+		(((v) << 0) & BM_CLKCTRL_HSADC_RSRVD1)
+
+#define HW_CLKCTRL_FLEXCAN	(0x00000160)
+
+#define BM_CLKCTRL_FLEXCAN_RSRVD2	0x80000000
+#define BP_CLKCTRL_FLEXCAN_STOP_CAN0	30
+#define BM_CLKCTRL_FLEXCAN_STOP_CAN0	0x40000000
+#define BM_CLKCTRL_FLEXCAN_CAN0_STATUS	0x20000000
+#define BP_CLKCTRL_FLEXCAN_STOP_CAN1	28
+#define BM_CLKCTRL_FLEXCAN_STOP_CAN1	0x10000000
+#define BM_CLKCTRL_FLEXCAN_CAN1_STATUS	0x08000000
+#define BP_CLKCTRL_FLEXCAN_RSRVD1	0
+#define BM_CLKCTRL_FLEXCAN_RSRVD1	0x07FFFFFF
+#define BF_CLKCTRL_FLEXCAN_RSRVD1(v)  \
+		(((v) << 0) & BM_CLKCTRL_FLEXCAN_RSRVD1)
+
+#define HW_CLKCTRL_FRAC0	(0x000001b0)
+#define HW_CLKCTRL_FRAC0_SET	(0x000001b4)
+#define HW_CLKCTRL_FRAC0_CLR	(0x000001b8)
+#define HW_CLKCTRL_FRAC0_TOG	(0x000001bc)
+
+#define BP_CLKCTRL_FRAC0_CLKGATEIO0	31
+#define BM_CLKCTRL_FRAC0_CLKGATEIO0	0x80000000
+#define BM_CLKCTRL_FRAC0_IO0_STABLE	0x40000000
+#define BP_CLKCTRL_FRAC0_IO0FRAC	24
+#define BM_CLKCTRL_FRAC0_IO0FRAC	0x3F000000
+#define BF_CLKCTRL_FRAC0_IO0FRAC(v)  \
+		(((v) << 24) & BM_CLKCTRL_FRAC0_IO0FRAC)
+#define BP_CLKCTRL_FRAC0_CLKGATEIO1	23
+#define BM_CLKCTRL_FRAC0_CLKGATEIO1	0x00800000
+#define BM_CLKCTRL_FRAC0_IO1_STABLE	0x00400000
+#define BP_CLKCTRL_FRAC0_IO1FRAC	16
+#define BM_CLKCTRL_FRAC0_IO1FRAC	0x003F0000
+#define BF_CLKCTRL_FRAC0_IO1FRAC(v)  \
+		(((v) << 16) & BM_CLKCTRL_FRAC0_IO1FRAC)
+#define BP_CLKCTRL_FRAC0_CLKGATEEMI	15
+#define BM_CLKCTRL_FRAC0_CLKGATEEMI	0x00008000
+#define BM_CLKCTRL_FRAC0_EMI_STABLE	0x00004000
+#define BP_CLKCTRL_FRAC0_EMIFRAC	8
+#define BM_CLKCTRL_FRAC0_EMIFRAC	0x00003F00
+#define BF_CLKCTRL_FRAC0_EMIFRAC(v)  \
+		(((v) << 8) & BM_CLKCTRL_FRAC0_EMIFRAC)
+#define BP_CLKCTRL_FRAC0_CLKGATECPU	7
+#define BM_CLKCTRL_FRAC0_CLKGATECPU	0x00000080
+#define BM_CLKCTRL_FRAC0_CPU_STABLE	0x00000040
+#define BP_CLKCTRL_FRAC0_CPUFRAC	0
+#define BM_CLKCTRL_FRAC0_CPUFRAC	0x0000003F
+#define BF_CLKCTRL_FRAC0_CPUFRAC(v)  \
+		(((v) << 0) & BM_CLKCTRL_FRAC0_CPUFRAC)
+
+#define HW_CLKCTRL_FRAC1	(0x000001c0)
+#define HW_CLKCTRL_FRAC1_SET	(0x000001c4)
+#define HW_CLKCTRL_FRAC1_CLR	(0x000001c8)
+#define HW_CLKCTRL_FRAC1_TOG	(0x000001cc)
+
+#define BP_CLKCTRL_FRAC1_RSRVD2	24
+#define BM_CLKCTRL_FRAC1_RSRVD2	0xFF000000
+#define BF_CLKCTRL_FRAC1_RSRVD2(v) \
+		(((v) << 24) & BM_CLKCTRL_FRAC1_RSRVD2)
+#define BP_CLKCTRL_FRAC1_CLKGATEGPMI	23
+#define BM_CLKCTRL_FRAC1_CLKGATEGPMI	0x00800000
+#define BM_CLKCTRL_FRAC1_GPMI_STABLE	0x00400000
+#define BP_CLKCTRL_FRAC1_GPMIFRAC	16
+#define BM_CLKCTRL_FRAC1_GPMIFRAC	0x003F0000
+#define BF_CLKCTRL_FRAC1_GPMIFRAC(v)  \
+		(((v) << 16) & BM_CLKCTRL_FRAC1_GPMIFRAC)
+#define BP_CLKCTRL_FRAC1_CLKGATEHSADC	15
+#define BM_CLKCTRL_FRAC1_CLKGATEHSADC	0x00008000
+#define BM_CLKCTRL_FRAC1_HSADC_STABLE	0x00004000
+#define BP_CLKCTRL_FRAC1_HSADCFRAC	8
+#define BM_CLKCTRL_FRAC1_HSADCFRAC	0x00003F00
+#define BF_CLKCTRL_FRAC1_HSADCFRAC(v)  \
+		(((v) << 8) & BM_CLKCTRL_FRAC1_HSADCFRAC)
+#define BP_CLKCTRL_FRAC1_CLKGATEPIX	7
+#define BM_CLKCTRL_FRAC1_CLKGATEPIX	0x00000080
+#define BM_CLKCTRL_FRAC1_PIX_STABLE	0x00000040
+#define BP_CLKCTRL_FRAC1_PIXFRAC	0
+#define BM_CLKCTRL_FRAC1_PIXFRAC	0x0000003F
+#define BF_CLKCTRL_FRAC1_PIXFRAC(v)  \
+		(((v) << 0) & BM_CLKCTRL_FRAC1_PIXFRAC)
+
+#define HW_CLKCTRL_CLKSEQ	(0x000001d0)
+#define HW_CLKCTRL_CLKSEQ_SET	(0x000001d4)
+#define HW_CLKCTRL_CLKSEQ_CLR	(0x000001d8)
+#define HW_CLKCTRL_CLKSEQ_TOG	(0x000001dc)
+
+#define BP_CLKCTRL_CLKSEQ_RSRVD0	19
+#define BM_CLKCTRL_CLKSEQ_RSRVD0	0xFFF80000
+#define BF_CLKCTRL_CLKSEQ_RSRVD0(v) \
+		(((v) << 19) & BM_CLKCTRL_CLKSEQ_RSRVD0)
+#define BM_CLKCTRL_CLKSEQ_BYPASS_CPU	0x00040000
+#define BP_CLKCTRL_CLKSEQ_RSRVD1	15
+#define BM_CLKCTRL_CLKSEQ_RSRVD1	0x00038000
+#define BF_CLKCTRL_CLKSEQ_RSRVD1(v)  \
+		(((v) << 15) & BM_CLKCTRL_CLKSEQ_RSRVD1)
+#define BM_CLKCTRL_CLKSEQ_BYPASS_DIS_LCDIF	0x00004000
+#define BV_CLKCTRL_CLKSEQ_BYPASS_DIS_LCDIF__BYPASS 0x1
+#define BV_CLKCTRL_CLKSEQ_BYPASS_DIS_LCDIF__PFD    0x0
+#define BP_CLKCTRL_CLKSEQ_RSRVD2	9
+#define BM_CLKCTRL_CLKSEQ_RSRVD2	0x00003E00
+#define BF_CLKCTRL_CLKSEQ_RSRVD2(v)  \
+		(((v) << 9) & BM_CLKCTRL_CLKSEQ_RSRVD2)
+#define BM_CLKCTRL_CLKSEQ_BYPASS_ETM	0x00000100
+#define BM_CLKCTRL_CLKSEQ_BYPASS_EMI	0x00000080
+#define BM_CLKCTRL_CLKSEQ_BYPASS_SSP3	0x00000040
+#define BM_CLKCTRL_CLKSEQ_BYPASS_SSP2	0x00000020
+#define BM_CLKCTRL_CLKSEQ_BYPASS_SSP1	0x00000010
+#define BM_CLKCTRL_CLKSEQ_BYPASS_SSP0	0x00000008
+#define BM_CLKCTRL_CLKSEQ_BYPASS_GPMI	0x00000004
+#define BM_CLKCTRL_CLKSEQ_BYPASS_SAIF1	0x00000002
+#define BM_CLKCTRL_CLKSEQ_BYPASS_SAIF0	0x00000001
+
+#define HW_CLKCTRL_RESET	(0x000001e0)
+
+#define BP_CLKCTRL_RESET_RSRVD	6
+#define BM_CLKCTRL_RESET_RSRVD	0xFFFFFFC0
+#define BF_CLKCTRL_RESET_RSRVD(v) \
+		(((v) << 6) & BM_CLKCTRL_RESET_RSRVD)
+#define BM_CLKCTRL_RESET_WDOG_POR_DISABLE	0x00000020
+#define BM_CLKCTRL_RESET_EXTERNAL_RESET_ENABLE	0x00000010
+#define BM_CLKCTRL_RESET_THERMAL_RESET_ENABLE	0x00000008
+#define BM_CLKCTRL_RESET_THERMAL_RESET_DEFAULT	0x00000004
+#define BM_CLKCTRL_RESET_CHIP	0x00000002
+#define BM_CLKCTRL_RESET_DIG	0x00000001
+
+#define HW_CLKCTRL_STATUS	(0x000001f0)
+
+#define BP_CLKCTRL_STATUS_CPU_LIMIT	30
+#define BM_CLKCTRL_STATUS_CPU_LIMIT	0xC0000000
+#define BF_CLKCTRL_STATUS_CPU_LIMIT(v) \
+		(((v) << 30) & BM_CLKCTRL_STATUS_CPU_LIMIT)
+#define BP_CLKCTRL_STATUS_RSRVD	0
+#define BM_CLKCTRL_STATUS_RSRVD	0x3FFFFFFF
+#define BF_CLKCTRL_STATUS_RSRVD(v)  \
+		(((v) << 0) & BM_CLKCTRL_STATUS_RSRVD)
+
+#define HW_CLKCTRL_VERSION	(0x00000200)
+
+#define BP_CLKCTRL_VERSION_MAJOR	24
+#define BM_CLKCTRL_VERSION_MAJOR	0xFF000000
+#define BF_CLKCTRL_VERSION_MAJOR(v) \
+		(((v) << 24) & BM_CLKCTRL_VERSION_MAJOR)
+#define BP_CLKCTRL_VERSION_MINOR	16
+#define BM_CLKCTRL_VERSION_MINOR	0x00FF0000
+#define BF_CLKCTRL_VERSION_MINOR(v)  \
+		(((v) << 16) & BM_CLKCTRL_VERSION_MINOR)
+#define BP_CLKCTRL_VERSION_STEP	0
+#define BM_CLKCTRL_VERSION_STEP	0x0000FFFF
+#define BF_CLKCTRL_VERSION_STEP(v)  \
+		(((v) << 0) & BM_CLKCTRL_VERSION_STEP)
+
+#endif /* __REGS_CLKCTRL_MX28_H__ */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mxs/system.c linux-libre-2.6.38-gnu1/arch/arm/mach-mxs/system.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mxs/system.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mxs/system.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 1999 ARM Limited
+ * Copyright (C) 2000 Deep Blue Solutions Ltd
+ * Copyright 2006-2007,2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 Juergen Beisert, kernel@pengutronix.de
+ * Copyright 2009 Ilya Yanok, Emcraft Systems Ltd, yanok@emcraft.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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+
+#include <asm/proc-fns.h>
+#include <asm/system.h>
+
+#include <mach/mxs.h>
+#include <mach/common.h>
+
+#define MX23_CLKCTRL_RESET_OFFSET	0x120
+#define MX28_CLKCTRL_RESET_OFFSET	0x1e0
+#define MXS_CLKCTRL_RESET_CHIP		(1 << 1)
+
+#define MXS_MODULE_CLKGATE		(1 << 30)
+#define MXS_MODULE_SFTRST		(1 << 31)
+
+static void __iomem *mxs_clkctrl_reset_addr;
+
+/*
+ * Reset the system. It is called by machine_restart().
+ */
+void arch_reset(char mode, const char *cmd)
+{
+	/* reset the chip */
+	__mxs_setl(MXS_CLKCTRL_RESET_CHIP, mxs_clkctrl_reset_addr);
+
+	pr_err("Failed to assert the chip reset\n");
+
+	/* Delay to allow the serial port to show the message */
+	mdelay(50);
+
+	/* We'll take a jump through zero as a poor second */
+	cpu_reset(0);
+}
+
+static int __init mxs_arch_reset_init(void)
+{
+	struct clk *clk;
+
+	mxs_clkctrl_reset_addr = MXS_IO_ADDRESS(MXS_CLKCTRL_BASE_ADDR) +
+				(cpu_is_mx23() ? MX23_CLKCTRL_RESET_OFFSET :
+						 MX28_CLKCTRL_RESET_OFFSET);
+
+	clk = clk_get_sys("rtc", NULL);
+	if (!IS_ERR(clk))
+		clk_enable(clk);
+
+	return 0;
+}
+core_initcall(mxs_arch_reset_init);
+
+/*
+ * Clear the bit and poll it cleared.  This is usually called with
+ * a reset address and mask being either SFTRST(bit 31) or CLKGATE
+ * (bit 30).
+ */
+static int clear_poll_bit(void __iomem *addr, u32 mask)
+{
+	int timeout = 0x400;
+
+	/* clear the bit */
+	__mxs_clrl(mask, addr);
+
+	/*
+	 * SFTRST needs 3 GPMI clocks to settle, the reference manual
+	 * recommends to wait 1us.
+	 */
+	udelay(1);
+
+	/* poll the bit becoming clear */
+	while ((__raw_readl(addr) & mask) && --timeout)
+		/* nothing */;
+
+	return !timeout;
+}
+
+int mxs_reset_block(void __iomem *reset_addr)
+{
+	int ret;
+	int timeout = 0x400;
+
+	/* clear and poll SFTRST */
+	ret = clear_poll_bit(reset_addr, MXS_MODULE_SFTRST);
+	if (unlikely(ret))
+		goto error;
+
+	/* clear CLKGATE */
+	__mxs_clrl(MXS_MODULE_CLKGATE, reset_addr);
+
+	/* set SFTRST to reset the block */
+	__mxs_setl(MXS_MODULE_SFTRST, reset_addr);
+	udelay(1);
+
+	/* poll CLKGATE becoming set */
+	while ((!(__raw_readl(reset_addr) & MXS_MODULE_CLKGATE)) && --timeout)
+		/* nothing */;
+	if (unlikely(!timeout))
+		goto error;
+
+	/* clear and poll SFTRST */
+	ret = clear_poll_bit(reset_addr, MXS_MODULE_SFTRST);
+	if (unlikely(ret))
+		goto error;
+
+	/* clear and poll CLKGATE */
+	ret = clear_poll_bit(reset_addr, MXS_MODULE_CLKGATE);
+	if (unlikely(ret))
+		goto error;
+
+	return 0;
+
+error:
+	pr_err("%s(%p): module reset timeout\n", __func__, reset_addr);
+	return -ETIMEDOUT;
+}
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-mxs/timer.c linux-libre-2.6.38-gnu1/arch/arm/mach-mxs/timer.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-mxs/timer.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-mxs/timer.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,296 @@
+/*
+ *  Copyright (C) 2000-2001 Deep Blue Solutions
+ *  Copyright (C) 2002 Shane Nay (shane@minirl.com)
+ *  Copyright (C) 2006-2007 Pavel Pisa (ppisa@pikron.com)
+ *  Copyright (C) 2008 Juergen Beisert (kernel@pengutronix.de)
+ *  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.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/clockchips.h>
+#include <linux/clk.h>
+
+#include <asm/mach/time.h>
+#include <mach/mxs.h>
+#include <mach/common.h>
+
+/*
+ * There are 2 versions of the timrot on Freescale MXS-based SoCs.
+ * The v1 on MX23 only gets 16 bits counter, while v2 on MX28
+ * extends the counter to 32 bits.
+ *
+ * The implementation uses two timers, one for clock_event and
+ * another for clocksource. MX28 uses timrot 0 and 1, while MX23
+ * uses 0 and 2.
+ */
+
+#define MX23_TIMROT_VERSION_OFFSET	0x0a0
+#define MX28_TIMROT_VERSION_OFFSET	0x120
+#define BP_TIMROT_MAJOR_VERSION		24
+#define BV_TIMROT_VERSION_1		0x01
+#define BV_TIMROT_VERSION_2		0x02
+#define timrot_is_v1()	(timrot_major_version == BV_TIMROT_VERSION_1)
+
+/*
+ * There are 4 registers for each timrotv2 instance, and 2 registers
+ * for each timrotv1. So address step 0x40 in macros below strides
+ * one instance of timrotv2 while two instances of timrotv1.
+ *
+ * As the result, HW_TIMROT_XXXn(1) defines the address of timrot1
+ * on MX28 while timrot2 on MX23.
+ */
+/* common between v1 and v2 */
+#define HW_TIMROT_ROTCTRL		0x00
+#define HW_TIMROT_TIMCTRLn(n)		(0x20 + (n) * 0x40)
+/* v1 only */
+#define HW_TIMROT_TIMCOUNTn(n)		(0x30 + (n) * 0x40)
+/* v2 only */
+#define HW_TIMROT_RUNNING_COUNTn(n)	(0x30 + (n) * 0x40)
+#define HW_TIMROT_FIXED_COUNTn(n)	(0x40 + (n) * 0x40)
+
+#define BM_TIMROT_TIMCTRLn_RELOAD	(1 << 6)
+#define BM_TIMROT_TIMCTRLn_UPDATE	(1 << 7)
+#define BM_TIMROT_TIMCTRLn_IRQ_EN	(1 << 14)
+#define BM_TIMROT_TIMCTRLn_IRQ		(1 << 15)
+#define BP_TIMROT_TIMCTRLn_SELECT	0
+#define BV_TIMROTv1_TIMCTRLn_SELECT__32KHZ_XTAL	0x8
+#define BV_TIMROTv2_TIMCTRLn_SELECT__32KHZ_XTAL	0xb
+
+static struct clock_event_device mxs_clockevent_device;
+static enum clock_event_mode mxs_clockevent_mode = CLOCK_EVT_MODE_UNUSED;
+
+static void __iomem *mxs_timrot_base = MXS_IO_ADDRESS(MXS_TIMROT_BASE_ADDR);
+static u32 timrot_major_version;
+
+static inline void timrot_irq_disable(void)
+{
+	__mxs_clrl(BM_TIMROT_TIMCTRLn_IRQ_EN,
+			mxs_timrot_base + HW_TIMROT_TIMCTRLn(0));
+}
+
+static inline void timrot_irq_enable(void)
+{
+	__mxs_setl(BM_TIMROT_TIMCTRLn_IRQ_EN,
+			mxs_timrot_base + HW_TIMROT_TIMCTRLn(0));
+}
+
+static void timrot_irq_acknowledge(void)
+{
+	__mxs_clrl(BM_TIMROT_TIMCTRLn_IRQ,
+			mxs_timrot_base + HW_TIMROT_TIMCTRLn(0));
+}
+
+static cycle_t timrotv1_get_cycles(struct clocksource *cs)
+{
+	return ~((__raw_readl(mxs_timrot_base + HW_TIMROT_TIMCOUNTn(1))
+			& 0xffff0000) >> 16);
+}
+
+static cycle_t timrotv2_get_cycles(struct clocksource *cs)
+{
+	return ~__raw_readl(mxs_timrot_base + HW_TIMROT_RUNNING_COUNTn(1));
+}
+
+static int timrotv1_set_next_event(unsigned long evt,
+					struct clock_event_device *dev)
+{
+	/* timrot decrements the count */
+	__raw_writel(evt, mxs_timrot_base + HW_TIMROT_TIMCOUNTn(0));
+
+	return 0;
+}
+
+static int timrotv2_set_next_event(unsigned long evt,
+					struct clock_event_device *dev)
+{
+	/* timrot decrements the count */
+	__raw_writel(evt, mxs_timrot_base + HW_TIMROT_FIXED_COUNTn(0));
+
+	return 0;
+}
+
+static irqreturn_t mxs_timer_interrupt(int irq, void *dev_id)
+{
+	struct clock_event_device *evt = dev_id;
+
+	timrot_irq_acknowledge();
+	evt->event_handler(evt);
+
+	return IRQ_HANDLED;
+}
+
+static struct irqaction mxs_timer_irq = {
+	.name		= "MXS Timer Tick",
+	.dev_id		= &mxs_clockevent_device,
+	.flags		= IRQF_TIMER | IRQF_IRQPOLL,
+	.handler	= mxs_timer_interrupt,
+};
+
+#ifdef DEBUG
+static const char *clock_event_mode_label[] const = {
+	[CLOCK_EVT_MODE_PERIODIC] = "CLOCK_EVT_MODE_PERIODIC",
+	[CLOCK_EVT_MODE_ONESHOT]  = "CLOCK_EVT_MODE_ONESHOT",
+	[CLOCK_EVT_MODE_SHUTDOWN] = "CLOCK_EVT_MODE_SHUTDOWN",
+	[CLOCK_EVT_MODE_UNUSED]   = "CLOCK_EVT_MODE_UNUSED"
+};
+#endif /* DEBUG */
+
+static void mxs_set_mode(enum clock_event_mode mode,
+				struct clock_event_device *evt)
+{
+	/* Disable interrupt in timer module */
+	timrot_irq_disable();
+
+	if (mode != mxs_clockevent_mode) {
+		/* Set event time into the furthest future */
+		if (timrot_is_v1())
+			__raw_writel(0xffff,
+				mxs_timrot_base + HW_TIMROT_TIMCOUNTn(1));
+		else
+			__raw_writel(0xffffffff,
+				mxs_timrot_base + HW_TIMROT_FIXED_COUNTn(1));
+
+		/* Clear pending interrupt */
+		timrot_irq_acknowledge();
+	}
+
+#ifdef DEBUG
+	pr_info("%s: changing mode from %s to %s\n", __func__,
+		clock_event_mode_label[mxs_clockevent_mode],
+		clock_event_mode_label[mode]);
+#endif /* DEBUG */
+
+	/* Remember timer mode */
+	mxs_clockevent_mode = mode;
+
+	switch (mode) {
+	case CLOCK_EVT_MODE_PERIODIC:
+		pr_err("%s: Periodic mode is not implemented\n", __func__);
+		break;
+	case CLOCK_EVT_MODE_ONESHOT:
+		timrot_irq_enable();
+		break;
+	case CLOCK_EVT_MODE_SHUTDOWN:
+	case CLOCK_EVT_MODE_UNUSED:
+	case CLOCK_EVT_MODE_RESUME:
+		/* Left event sources disabled, no more interrupts appear */
+		break;
+	}
+}
+
+static struct clock_event_device mxs_clockevent_device = {
+	.name		= "mxs_timrot",
+	.features	= CLOCK_EVT_FEAT_ONESHOT,
+	.shift		= 32,
+	.set_mode	= mxs_set_mode,
+	.set_next_event	= timrotv2_set_next_event,
+	.rating		= 200,
+};
+
+static int __init mxs_clockevent_init(struct clk *timer_clk)
+{
+	unsigned int c = clk_get_rate(timer_clk);
+
+	mxs_clockevent_device.mult =
+		div_sc(c, NSEC_PER_SEC, mxs_clockevent_device.shift);
+	mxs_clockevent_device.cpumask = cpumask_of(0);
+	if (timrot_is_v1()) {
+		mxs_clockevent_device.set_next_event = timrotv1_set_next_event;
+		mxs_clockevent_device.max_delta_ns =
+			clockevent_delta2ns(0xfffe, &mxs_clockevent_device);
+		mxs_clockevent_device.min_delta_ns =
+			clockevent_delta2ns(0xf, &mxs_clockevent_device);
+	} else {
+		mxs_clockevent_device.max_delta_ns =
+			clockevent_delta2ns(0xfffffffe, &mxs_clockevent_device);
+		mxs_clockevent_device.min_delta_ns =
+			clockevent_delta2ns(0xf, &mxs_clockevent_device);
+	}
+
+	clockevents_register_device(&mxs_clockevent_device);
+
+	return 0;
+}
+
+static struct clocksource clocksource_mxs = {
+	.name		= "mxs_timer",
+	.rating		= 200,
+	.read		= timrotv2_get_cycles,
+	.mask		= CLOCKSOURCE_MASK(32),
+	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+static int __init mxs_clocksource_init(struct clk *timer_clk)
+{
+	unsigned int c = clk_get_rate(timer_clk);
+
+	if (timrot_is_v1()) {
+		clocksource_mxs.read = timrotv1_get_cycles;
+		clocksource_mxs.mask = CLOCKSOURCE_MASK(16);
+	}
+
+	clocksource_register_hz(&clocksource_mxs, c);
+
+	return 0;
+}
+
+void __init mxs_timer_init(struct clk *timer_clk, int irq)
+{
+	clk_enable(timer_clk);
+
+	/*
+	 * Initialize timers to a known state
+	 */
+	mxs_reset_block(mxs_timrot_base + HW_TIMROT_ROTCTRL);
+
+	/* get timrot version */
+	timrot_major_version = __raw_readl(mxs_timrot_base +
+				(cpu_is_mx23() ? MX23_TIMROT_VERSION_OFFSET :
+						MX28_TIMROT_VERSION_OFFSET));
+	timrot_major_version >>= BP_TIMROT_MAJOR_VERSION;
+
+	/* one for clock_event */
+	__raw_writel((timrot_is_v1() ?
+			BV_TIMROTv1_TIMCTRLn_SELECT__32KHZ_XTAL :
+			BV_TIMROTv2_TIMCTRLn_SELECT__32KHZ_XTAL) |
+			BM_TIMROT_TIMCTRLn_UPDATE |
+			BM_TIMROT_TIMCTRLn_IRQ_EN,
+			mxs_timrot_base + HW_TIMROT_TIMCTRLn(0));
+
+	/* another for clocksource */
+	__raw_writel((timrot_is_v1() ?
+			BV_TIMROTv1_TIMCTRLn_SELECT__32KHZ_XTAL :
+			BV_TIMROTv2_TIMCTRLn_SELECT__32KHZ_XTAL) |
+			BM_TIMROT_TIMCTRLn_RELOAD,
+			mxs_timrot_base + HW_TIMROT_TIMCTRLn(1));
+
+	/* set clocksource timer fixed count to the maximum */
+	if (timrot_is_v1())
+		__raw_writel(0xffff,
+			mxs_timrot_base + HW_TIMROT_TIMCOUNTn(1));
+	else
+		__raw_writel(0xffffffff,
+			mxs_timrot_base + HW_TIMROT_FIXED_COUNTn(1));
+
+	/* init and register the timer to the framework */
+	mxs_clocksource_init(timer_clk);
+	mxs_clockevent_init(timer_clk);
+
+	/* Make irqs happen */
+	setup_irq(irq, &mxs_timer_irq);
+}
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-netx/generic.c linux-libre-2.6.38-gnu1/arch/arm/mach-netx/generic.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-netx/generic.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-netx/generic.c	2011-03-14 21:20:32.000000000 -0400
@@ -88,13 +88,13 @@ netx_hif_demux_handler(unsigned int irq_
 }
 
 static int
-netx_hif_irq_type(unsigned int _irq, unsigned int type)
+netx_hif_irq_type(struct irq_data *d, unsigned int type)
 {
 	unsigned int val, irq;
 
 	val = readl(NETX_DPMAS_IF_CONF1);
 
-	irq = _irq - NETX_IRQ_HIF_CHAINED(0);
+	irq = d->irq - NETX_IRQ_HIF_CHAINED(0);
 
 	if (type & IRQ_TYPE_EDGE_RISING) {
 		DEBUG_IRQ("rising edges\n");
@@ -119,49 +119,49 @@ netx_hif_irq_type(unsigned int _irq, uns
 }
 
 static void
-netx_hif_ack_irq(unsigned int _irq)
+netx_hif_ack_irq(struct irq_data *d)
 {
 	unsigned int val, irq;
 
-	irq = _irq - NETX_IRQ_HIF_CHAINED(0);
+	irq = d->irq - NETX_IRQ_HIF_CHAINED(0);
 	writel((1 << 24) << irq, NETX_DPMAS_INT_STAT);
 
 	val = readl(NETX_DPMAS_INT_EN);
 	val &= ~((1 << 24) << irq);
 	writel(val, NETX_DPMAS_INT_EN);
 
-	DEBUG_IRQ("%s: irq %d\n", __func__, _irq);
+	DEBUG_IRQ("%s: irq %d\n", __func__, d->irq);
 }
 
 static void
-netx_hif_mask_irq(unsigned int _irq)
+netx_hif_mask_irq(struct irq_data *d)
 {
 	unsigned int val, irq;
 
-	irq = _irq - NETX_IRQ_HIF_CHAINED(0);
+	irq = d->irq - NETX_IRQ_HIF_CHAINED(0);
 	val = readl(NETX_DPMAS_INT_EN);
 	val &= ~((1 << 24) << irq);
 	writel(val, NETX_DPMAS_INT_EN);
-	DEBUG_IRQ("%s: irq %d\n", __func__, _irq);
+	DEBUG_IRQ("%s: irq %d\n", __func__, d->irq);
 }
 
 static void
-netx_hif_unmask_irq(unsigned int _irq)
+netx_hif_unmask_irq(struct irq_data *d)
 {
 	unsigned int val, irq;
 
-	irq = _irq - NETX_IRQ_HIF_CHAINED(0);
+	irq = d->irq - NETX_IRQ_HIF_CHAINED(0);
 	val = readl(NETX_DPMAS_INT_EN);
 	val |= (1 << 24) << irq;
 	writel(val, NETX_DPMAS_INT_EN);
-	DEBUG_IRQ("%s: irq %d\n", __func__, _irq);
+	DEBUG_IRQ("%s: irq %d\n", __func__, d->irq);
 }
 
 static struct irq_chip netx_hif_chip = {
-	.ack = netx_hif_ack_irq,
-	.mask = netx_hif_mask_irq,
-	.unmask = netx_hif_unmask_irq,
-	.set_type = netx_hif_irq_type,
+	.irq_ack = netx_hif_ack_irq,
+	.irq_mask = netx_hif_mask_irq,
+	.irq_unmask = netx_hif_unmask_irq,
+	.irq_set_type = netx_hif_irq_type,
 };
 
 void __init netx_init_irq(void)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-netx/time.c linux-libre-2.6.38-gnu1/arch/arm/mach-netx/time.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-netx/time.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-netx/time.c	2011-03-14 21:20:32.000000000 -0400
@@ -114,7 +114,6 @@ static struct clocksource clocksource_ne
 	.rating		= 200,
 	.read		= netx_get_cycles,
 	.mask		= CLOCKSOURCE_MASK(32),
-	.shift		= 20,
 	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
@@ -151,9 +150,7 @@ static void __init netx_timer_init(void)
 	writel(NETX_GPIO_COUNTER_CTRL_RUN,
 			NETX_GPIO_COUNTER_CTRL(TIMER_CLOCKSOURCE));
 
-	clocksource_netx.mult =
-		clocksource_hz2mult(CLOCK_TICK_RATE, clocksource_netx.shift);
-	clocksource_register(&clocksource_netx);
+	clocksource_register_hz(&clocksource_netx, CLOCK_TICK_RATE);
 
 	netx_clockevent.mult = div_sc(CLOCK_TICK_RATE, NSEC_PER_SEC,
 			netx_clockevent.shift);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-nomadik/clock.c linux-libre-2.6.38-gnu1/arch/arm/mach-nomadik/clock.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-nomadik/clock.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-nomadik/clock.c	2011-03-14 21:20:32.000000000 -0400
@@ -7,7 +7,7 @@
 #include <linux/module.h>
 #include <linux/errno.h>
 #include <linux/clk.h>
-#include <asm/clkdev.h>
+#include <linux/clkdev.h>
 #include "clock.h"
 
 /*
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-ns9xxx/board-a9m9750dev.c linux-libre-2.6.38-gnu1/arch/arm/mach-ns9xxx/board-a9m9750dev.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-ns9xxx/board-a9m9750dev.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-ns9xxx/board-a9m9750dev.c	2011-03-14 21:20:32.000000000 -0400
@@ -37,44 +37,44 @@ void __init board_a9m9750dev_map_io(void
 		     ARRAY_SIZE(board_a9m9750dev_io_desc));
 }
 
-static void a9m9750dev_fpga_ack_irq(unsigned int irq)
+static void a9m9750dev_fpga_ack_irq(struct irq_data *d)
 {
 	/* nothing */
 }
 
-static void a9m9750dev_fpga_mask_irq(unsigned int irq)
+static void a9m9750dev_fpga_mask_irq(struct irq_data *d)
 {
 	u8 ier;
 
 	ier = __raw_readb(FPGA_IER);
 
-	ier &= ~(1 << (irq - FPGA_IRQ(0)));
+	ier &= ~(1 << (d->irq - FPGA_IRQ(0)));
 
 	__raw_writeb(ier, FPGA_IER);
 }
 
-static void a9m9750dev_fpga_maskack_irq(unsigned int irq)
+static void a9m9750dev_fpga_maskack_irq(struct irq_data *d)
 {
-	a9m9750dev_fpga_mask_irq(irq);
-	a9m9750dev_fpga_ack_irq(irq);
+	a9m9750dev_fpga_mask_irq(d);
+	a9m9750dev_fpga_ack_irq(d);
 }
 
-static void a9m9750dev_fpga_unmask_irq(unsigned int irq)
+static void a9m9750dev_fpga_unmask_irq(struct irq_data *d)
 {
 	u8 ier;
 
 	ier = __raw_readb(FPGA_IER);
 
-	ier |= 1 << (irq - FPGA_IRQ(0));
+	ier |= 1 << (d->irq - FPGA_IRQ(0));
 
 	__raw_writeb(ier, FPGA_IER);
 }
 
 static struct irq_chip a9m9750dev_fpga_chip = {
-	.ack		= a9m9750dev_fpga_ack_irq,
-	.mask		= a9m9750dev_fpga_mask_irq,
-	.mask_ack	= a9m9750dev_fpga_maskack_irq,
-	.unmask		= a9m9750dev_fpga_unmask_irq,
+	.irq_ack	= a9m9750dev_fpga_ack_irq,
+	.irq_mask	= a9m9750dev_fpga_mask_irq,
+	.irq_mask_ack	= a9m9750dev_fpga_maskack_irq,
+	.irq_unmask	= a9m9750dev_fpga_unmask_irq,
 };
 
 static void a9m9750dev_fpga_demux_handler(unsigned int irq,
@@ -82,7 +82,7 @@ static void a9m9750dev_fpga_demux_handle
 {
 	u8 stat = __raw_readb(FPGA_ISR);
 
-	desc->chip->mask_ack(irq);
+	desc->irq_data.chip->irq_mask_ack(&desc->irq_data);
 
 	while (stat != 0) {
 		int irqno = fls(stat) - 1;
@@ -92,7 +92,7 @@ static void a9m9750dev_fpga_demux_handle
 		generic_handle_irq(FPGA_IRQ(irqno));
 	}
 
-	desc->chip->unmask(irq);
+	desc->irq_data.chip->irq_unmask(&desc->irq_data);
 }
 
 void __init board_a9m9750dev_init_irq(void)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-ns9xxx/irq.c linux-libre-2.6.38-gnu1/arch/arm/mach-ns9xxx/irq.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-ns9xxx/irq.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-ns9xxx/irq.c	2011-03-14 21:20:32.000000000 -0400
@@ -22,40 +22,40 @@
 #define irq2prio(i) (i)
 #define prio2irq(p) (p)
 
-static void ns9xxx_mask_irq(unsigned int irq)
+static void ns9xxx_mask_irq(struct irq_data *d)
 {
 	/* XXX: better use cpp symbols */
-	int prio = irq2prio(irq);
+	int prio = irq2prio(d->irq);
 	u32 ic = __raw_readl(SYS_IC(prio / 4));
 	ic &= ~(1 << (7 + 8 * (3 - (prio & 3))));
 	__raw_writel(ic, SYS_IC(prio / 4));
 }
 
-static void ns9xxx_ack_irq(unsigned int irq)
+static void ns9xxx_ack_irq(struct irq_data *d)
 {
 	__raw_writel(0, SYS_ISRADDR);
 }
 
-static void ns9xxx_maskack_irq(unsigned int irq)
+static void ns9xxx_maskack_irq(struct irq_data *d)
 {
-	ns9xxx_mask_irq(irq);
-	ns9xxx_ack_irq(irq);
+	ns9xxx_mask_irq(d);
+	ns9xxx_ack_irq(d);
 }
 
-static void ns9xxx_unmask_irq(unsigned int irq)
+static void ns9xxx_unmask_irq(struct irq_data *d)
 {
 	/* XXX: better use cpp symbols */
-	int prio = irq2prio(irq);
+	int prio = irq2prio(d->irq);
 	u32 ic = __raw_readl(SYS_IC(prio / 4));
 	ic |= 1 << (7 + 8 * (3 - (prio & 3)));
 	__raw_writel(ic, SYS_IC(prio / 4));
 }
 
 static struct irq_chip ns9xxx_chip = {
-	.ack		= ns9xxx_ack_irq,
-	.mask		= ns9xxx_mask_irq,
-	.mask_ack	= ns9xxx_maskack_irq,
-	.unmask		= ns9xxx_unmask_irq,
+	.irq_ack	= ns9xxx_ack_irq,
+	.irq_mask	= ns9xxx_mask_irq,
+	.irq_mask_ack	= ns9xxx_maskack_irq,
+	.irq_unmask	= ns9xxx_unmask_irq,
 };
 
 #if 0
@@ -92,10 +92,10 @@ static void handle_prio_irq(unsigned int
 
 	if (desc->status & IRQ_DISABLED)
 out_mask:
-		desc->chip->mask(irq);
+		desc->irq_data.chip->irq_mask(&desc->irq_data);
 
 	/* ack unconditionally to unmask lower prio irqs */
-	desc->chip->ack(irq);
+	desc->irq_data.chip->irq_ack(&desc->irq_data);
 
 	raw_spin_unlock(&desc->lock);
 }
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-ns9xxx/time-ns9360.c linux-libre-2.6.38-gnu1/arch/arm/mach-ns9xxx/time-ns9360.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-ns9xxx/time-ns9360.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-ns9xxx/time-ns9360.c	2011-03-14 21:20:32.000000000 -0400
@@ -35,7 +35,6 @@ static struct clocksource ns9360_clockso
 	.rating	= 300,
 	.read	= ns9360_clocksource_read,
 	.mask	= CLOCKSOURCE_MASK(32),
-	.shift	= 20,
 	.flags	= CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
@@ -148,10 +147,7 @@ static void __init ns9360_timer_init(voi
 
 	__raw_writel(tc, SYS_TC(TIMER_CLOCKSOURCE));
 
-	ns9360_clocksource.mult = clocksource_hz2mult(ns9360_cpuclock(),
-			ns9360_clocksource.shift);
-
-	clocksource_register(&ns9360_clocksource);
+	clocksource_register_hz(&ns9360_clocksource, ns9360_cpuclock());
 
 	latch = SH_DIV(ns9360_cpuclock(), HZ, 0);
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-nuc93x/clock.h linux-libre-2.6.38-gnu1/arch/arm/mach-nuc93x/clock.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-nuc93x/clock.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-nuc93x/clock.h	2011-03-14 21:20:32.000000000 -0400
@@ -10,7 +10,7 @@
  * the Free Software Foundation; either version 2 of the License.
  */
 
-#include <asm/clkdev.h>
+#include <linux/clkdev.h>
 
 void nuc93x_clk_enable(struct clk *clk, int enable);
 void clks_register(struct clk_lookup *clks, size_t num);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-nuc93x/irq.c linux-libre-2.6.38-gnu1/arch/arm/mach-nuc93x/irq.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-nuc93x/irq.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-nuc93x/irq.c	2011-03-14 21:20:32.000000000 -0400
@@ -25,9 +25,9 @@
 #include <mach/hardware.h>
 #include <mach/regs-irq.h>
 
-static void nuc93x_irq_mask(unsigned int irq)
+static void nuc93x_irq_mask(struct irq_data *d)
 {
-	__raw_writel(1 << irq, REG_AIC_MDCR);
+	__raw_writel(1 << d->irq, REG_AIC_MDCR);
 }
 
 /*
@@ -35,21 +35,21 @@ static void nuc93x_irq_mask(unsigned int
  * to REG_AIC_EOSCR for ACK
  */
 
-static void nuc93x_irq_ack(unsigned int irq)
+static void nuc93x_irq_ack(struct irq_data *d)
 {
 	__raw_writel(0x01, REG_AIC_EOSCR);
 }
 
-static void nuc93x_irq_unmask(unsigned int irq)
+static void nuc93x_irq_unmask(struct irq_data *d)
 {
-	__raw_writel(1 << irq, REG_AIC_MECR);
+	__raw_writel(1 << d->irq, REG_AIC_MECR);
 
 }
 
 static struct irq_chip nuc93x_irq_chip = {
-	.ack	   = nuc93x_irq_ack,
-	.mask	   = nuc93x_irq_mask,
-	.unmask	   = nuc93x_irq_unmask,
+	.irq_ack	= nuc93x_irq_ack,
+	.irq_mask	= nuc93x_irq_mask,
+	.irq_unmask	= nuc93x_irq_unmask,
 };
 
 void __init nuc93x_init_irq(void)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap1/ams-delta-fiq.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap1/ams-delta-fiq.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap1/ams-delta-fiq.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap1/ams-delta-fiq.c	2011-03-14 21:20:32.000000000 -0400
@@ -49,7 +49,7 @@ static irqreturn_t deferred_fiq(int irq,
 
 	irq_desc = irq_to_desc(IH_GPIO_BASE);
 	if (irq_desc)
-		irq_chip = irq_desc->chip;
+		irq_chip = irq_desc->irq_data.chip;
 
 	/*
 	 * For each handled GPIO interrupt, keep calling its interrupt handler
@@ -62,13 +62,15 @@ static irqreturn_t deferred_fiq(int irq,
 
 		while (irq_counter[gpio] < fiq_count) {
 			if (gpio != AMS_DELTA_GPIO_PIN_KEYBRD_CLK) {
+				struct irq_data *d = irq_get_irq_data(irq_num);
+
 				/*
 				 * It looks like handle_edge_irq() that
 				 * OMAP GPIO edge interrupts default to,
 				 * expects interrupt already unmasked.
 				 */
-				if (irq_chip && irq_chip->unmask)
-					irq_chip->unmask(irq_num);
+				if (irq_chip && irq_chip->irq_unmask)
+					irq_chip->irq_unmask(d);
 			}
 			generic_handle_irq(irq_num);
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap1/board-ams-delta.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap1/board-ams-delta.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap1/board-ams-delta.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap1/board-ams-delta.c	2011-03-14 21:20:32.000000000 -0400
@@ -28,6 +28,7 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
+#include <plat/io.h>
 #include <plat/board-ams-delta.h>
 #include <mach/gpio.h>
 #include <plat/keypad.h>
@@ -42,84 +43,82 @@
 static u8 ams_delta_latch1_reg;
 static u16 ams_delta_latch2_reg;
 
-static int ams_delta_keymap[] = {
+static const unsigned int ams_delta_keymap[] = {
 	KEY(0, 0, KEY_F1),		/* Advert    */
 
-	KEY(3, 0, KEY_COFFEE),		/* Games     */
-	KEY(2, 0, KEY_QUESTION),	/* Directory */
-	KEY(3, 2, KEY_CONNECT),		/* Internet  */
-	KEY(2, 1, KEY_SHOP),		/* Services  */
+	KEY(0, 3, KEY_COFFEE),		/* Games     */
+	KEY(0, 2, KEY_QUESTION),	/* Directory */
+	KEY(2, 3, KEY_CONNECT),		/* Internet  */
+	KEY(1, 2, KEY_SHOP),		/* Services  */
 	KEY(1, 1, KEY_PHONE),		/* VoiceMail */
 
-	KEY(1, 0, KEY_DELETE),		/* Delete    */
+	KEY(0, 1, KEY_DELETE),		/* Delete    */
 	KEY(2, 2, KEY_PLAY),		/* Play      */
-	KEY(0, 1, KEY_PAGEUP),		/* Up        */
-	KEY(3, 1, KEY_PAGEDOWN),	/* Down      */
-	KEY(0, 2, KEY_EMAIL),		/* ReadEmail */
-	KEY(1, 2, KEY_STOP),		/* Stop      */
+	KEY(1, 0, KEY_PAGEUP),		/* Up        */
+	KEY(1, 3, KEY_PAGEDOWN),	/* Down      */
+	KEY(2, 0, KEY_EMAIL),		/* ReadEmail */
+	KEY(2, 1, KEY_STOP),		/* Stop      */
 
 	/* Numeric keypad portion */
-	KEY(7, 0, KEY_KP1),
-	KEY(6, 0, KEY_KP2),
-	KEY(5, 0, KEY_KP3),
-	KEY(7, 1, KEY_KP4),
-	KEY(6, 1, KEY_KP5),
-	KEY(5, 1, KEY_KP6),
-	KEY(7, 2, KEY_KP7),
-	KEY(6, 2, KEY_KP8),
-	KEY(5, 2, KEY_KP9),
-	KEY(6, 3, KEY_KP0),
-	KEY(7, 3, KEY_KPASTERISK),
-	KEY(5, 3, KEY_KPDOT),		/* # key     */
-	KEY(2, 7, KEY_NUMLOCK),		/* Mute      */
-	KEY(1, 7, KEY_KPMINUS),		/* Recall    */
-	KEY(1, 6, KEY_KPPLUS),		/* Redial    */
-	KEY(6, 7, KEY_KPSLASH),		/* Handsfree */
-	KEY(0, 6, KEY_ENTER),		/* Video     */
+	KEY(0, 7, KEY_KP1),
+	KEY(0, 6, KEY_KP2),
+	KEY(0, 5, KEY_KP3),
+	KEY(1, 7, KEY_KP4),
+	KEY(1, 6, KEY_KP5),
+	KEY(1, 5, KEY_KP6),
+	KEY(2, 7, KEY_KP7),
+	KEY(2, 6, KEY_KP8),
+	KEY(2, 5, KEY_KP9),
+	KEY(3, 6, KEY_KP0),
+	KEY(3, 7, KEY_KPASTERISK),
+	KEY(3, 5, KEY_KPDOT),		/* # key     */
+	KEY(7, 2, KEY_NUMLOCK),		/* Mute      */
+	KEY(7, 1, KEY_KPMINUS),		/* Recall    */
+	KEY(6, 1, KEY_KPPLUS),		/* Redial    */
+	KEY(7, 6, KEY_KPSLASH),		/* Handsfree */
+	KEY(6, 0, KEY_ENTER),		/* Video     */
 
-	KEY(4, 7, KEY_CAMERA),		/* Photo     */
+	KEY(7, 4, KEY_CAMERA),		/* Photo     */
 
-	KEY(4, 0, KEY_F2),		/* Home      */
-	KEY(4, 1, KEY_F3),		/* Office    */
-	KEY(4, 2, KEY_F4),		/* Mobile    */
+	KEY(0, 4, KEY_F2),		/* Home      */
+	KEY(1, 4, KEY_F3),		/* Office    */
+	KEY(2, 4, KEY_F4),		/* Mobile    */
 	KEY(7, 7, KEY_F5),		/* SMS       */
-	KEY(5, 7, KEY_F6),		/* Email     */
+	KEY(7, 5, KEY_F6),		/* Email     */
 
 	/* QWERTY portion of keypad */
-	KEY(4, 3, KEY_Q),
+	KEY(3, 4, KEY_Q),
 	KEY(3, 3, KEY_W),
-	KEY(2, 3, KEY_E),
-	KEY(1, 3, KEY_R),
-	KEY(0, 3, KEY_T),
-	KEY(7, 4, KEY_Y),
-	KEY(6, 4, KEY_U),
-	KEY(5, 4, KEY_I),
+	KEY(3, 2, KEY_E),
+	KEY(3, 1, KEY_R),
+	KEY(3, 0, KEY_T),
+	KEY(4, 7, KEY_Y),
+	KEY(4, 6, KEY_U),
+	KEY(4, 5, KEY_I),
 	KEY(4, 4, KEY_O),
-	KEY(3, 4, KEY_P),
+	KEY(4, 3, KEY_P),
 
-	KEY(2, 4, KEY_A),
-	KEY(1, 4, KEY_S),
-	KEY(0, 4, KEY_D),
-	KEY(7, 5, KEY_F),
-	KEY(6, 5, KEY_G),
+	KEY(4, 2, KEY_A),
+	KEY(4, 1, KEY_S),
+	KEY(4, 0, KEY_D),
+	KEY(5, 7, KEY_F),
+	KEY(5, 6, KEY_G),
 	KEY(5, 5, KEY_H),
-	KEY(4, 5, KEY_J),
-	KEY(3, 5, KEY_K),
-	KEY(2, 5, KEY_L),
+	KEY(5, 4, KEY_J),
+	KEY(5, 3, KEY_K),
+	KEY(5, 2, KEY_L),
 
-	KEY(1, 5, KEY_Z),
-	KEY(0, 5, KEY_X),
-	KEY(7, 6, KEY_C),
+	KEY(5, 1, KEY_Z),
+	KEY(5, 0, KEY_X),
+	KEY(6, 7, KEY_C),
 	KEY(6, 6, KEY_V),
-	KEY(5, 6, KEY_B),
-	KEY(4, 6, KEY_N),
-	KEY(3, 6, KEY_M),
-	KEY(2, 6, KEY_SPACE),
-
-	KEY(0, 7, KEY_LEFTSHIFT),	/* Vol up    */
-	KEY(3, 7, KEY_LEFTCTRL),	/* Vol down  */
+	KEY(6, 5, KEY_B),
+	KEY(6, 4, KEY_N),
+	KEY(6, 3, KEY_M),
+	KEY(6, 2, KEY_SPACE),
 
-	0
+	KEY(7, 0, KEY_LEFTSHIFT),	/* Vol up    */
+	KEY(7, 3, KEY_LEFTCTRL),	/* Vol down  */
 };
 
 void ams_delta_latch1_write(u8 mask, u8 value)
@@ -140,7 +139,6 @@ static void __init ams_delta_init_irq(vo
 {
 	omap1_init_common_hw();
 	omap_init_irq();
-	omap_gpio_init();
 }
 
 static struct map_desc ams_delta_io_desc[] __initdata = {
@@ -181,6 +179,22 @@ static struct omap_board_config_kernel a
 	{ OMAP_TAG_LCD,		&ams_delta_lcd_config },
 };
 
+static struct resource ams_delta_nand_resources[] = {
+	[0] = {
+		.start	= OMAP1_MPUIO_BASE,
+		.end	= OMAP1_MPUIO_BASE +
+				OMAP_MPUIO_IO_CNTL + sizeof(u32) - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct platform_device ams_delta_nand_device = {
+	.name	= "ams-delta-nand",
+	.id	= -1,
+	.num_resources	= ARRAY_SIZE(ams_delta_nand_resources),
+	.resource	= ams_delta_nand_resources,
+};
+
 static struct resource ams_delta_kp_resources[] = {
 	[0] = {
 		.start	= INT_KEYBOARD,
@@ -189,11 +203,15 @@ static struct resource ams_delta_kp_reso
 	},
 };
 
+static const struct matrix_keymap_data ams_delta_keymap_data = {
+	.keymap		= ams_delta_keymap,
+	.keymap_size	= ARRAY_SIZE(ams_delta_keymap),
+};
+
 static struct omap_kp_platform_data ams_delta_kp_data = {
 	.rows		= 8,
 	.cols		= 8,
-	.keymap 	= ams_delta_keymap,
-	.keymapsize	= ARRAY_SIZE(ams_delta_keymap),
+	.keymap_data	= &ams_delta_keymap_data,
 	.delay		= 9,
 };
 
@@ -263,6 +281,7 @@ static struct omap1_cam_platform_data am
 };
 
 static struct platform_device *ams_delta_devices[] __initdata = {
+	&ams_delta_nand_device,
 	&ams_delta_kp_device,
 	&ams_delta_lcd_device,
 	&ams_delta_led_device,
@@ -307,16 +326,14 @@ static void __init ams_delta_init(void)
 #endif
 	platform_add_devices(ams_delta_devices, ARRAY_SIZE(ams_delta_devices));
 
-#ifdef CONFIG_AMS_DELTA_FIQ
 	ams_delta_init_fiq();
-#endif
 
 	omap_writew(omap_readw(ARM_RSTCT1) | 0x0004, ARM_RSTCT1);
 }
 
 static struct plat_serial8250_port ams_delta_modem_ports[] = {
 	{
-		.membase	= (void *) AMS_DELTA_MODEM_VIRT,
+		.membase	= IOMEM(AMS_DELTA_MODEM_VIRT),
 		.mapbase	= AMS_DELTA_MODEM_PHYS,
 		.irq		= -EINVAL, /* changed later */
 		.flags		= UPF_BOOT_AUTOCONF,
@@ -340,6 +357,9 @@ static int __init ams_delta_modem_init(v
 {
 	int err;
 
+	if (!machine_is_ams_delta())
+		return -ENODEV;
+
 	omap_cfg_reg(M14_1510_GPIO2);
 	ams_delta_modem_ports[0].irq =
 			gpio_to_irq(AMS_DELTA_GPIO_PIN_MODEM_IRQ);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap1/board-fsample.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap1/board-fsample.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap1/board-fsample.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap1/board-fsample.c	2011-03-14 21:20:32.000000000 -0400
@@ -69,36 +69,35 @@
 #define fsample_cpld_clear(bit) \
     fsample_cpld_write(0xf0 | ((bit) & 15), FSAMPLE_CPLD_SET_CLR)
 
-static int fsample_keymap[] = {
-	KEY(0,0,KEY_UP),
-	KEY(0,1,KEY_RIGHT),
-	KEY(0,2,KEY_LEFT),
-	KEY(0,3,KEY_DOWN),
-	KEY(0,4,KEY_ENTER),
-	KEY(1,0,KEY_F10),
-	KEY(1,1,KEY_SEND),
-	KEY(1,2,KEY_END),
-	KEY(1,3,KEY_VOLUMEDOWN),
-	KEY(1,4,KEY_VOLUMEUP),
-	KEY(1,5,KEY_RECORD),
-	KEY(2,0,KEY_F9),
-	KEY(2,1,KEY_3),
-	KEY(2,2,KEY_6),
-	KEY(2,3,KEY_9),
-	KEY(2,4,KEY_KPDOT),
-	KEY(3,0,KEY_BACK),
-	KEY(3,1,KEY_2),
-	KEY(3,2,KEY_5),
-	KEY(3,3,KEY_8),
-	KEY(3,4,KEY_0),
-	KEY(3,5,KEY_KPSLASH),
-	KEY(4,0,KEY_HOME),
-	KEY(4,1,KEY_1),
-	KEY(4,2,KEY_4),
-	KEY(4,3,KEY_7),
-	KEY(4,4,KEY_KPASTERISK),
-	KEY(4,5,KEY_POWER),
-	0
+static const unsigned int fsample_keymap[] = {
+	KEY(0, 0, KEY_UP),
+	KEY(1, 0, KEY_RIGHT),
+	KEY(2, 0, KEY_LEFT),
+	KEY(3, 0, KEY_DOWN),
+	KEY(4, 0, KEY_ENTER),
+	KEY(0, 1, KEY_F10),
+	KEY(1, 1, KEY_SEND),
+	KEY(2, 1, KEY_END),
+	KEY(3, 1, KEY_VOLUMEDOWN),
+	KEY(4, 1, KEY_VOLUMEUP),
+	KEY(5, 1, KEY_RECORD),
+	KEY(0, 2, KEY_F9),
+	KEY(1, 2, KEY_3),
+	KEY(2, 2, KEY_6),
+	KEY(3, 2, KEY_9),
+	KEY(4, 2, KEY_KPDOT),
+	KEY(0, 3, KEY_BACK),
+	KEY(1, 3, KEY_2),
+	KEY(2, 3, KEY_5),
+	KEY(3, 3, KEY_8),
+	KEY(4, 3, KEY_0),
+	KEY(5, 3, KEY_KPSLASH),
+	KEY(0, 4, KEY_HOME),
+	KEY(1, 4, KEY_1),
+	KEY(2, 4, KEY_4),
+	KEY(3, 4, KEY_7),
+	KEY(4, 4, KEY_KPASTERISK),
+	KEY(5, 4, KEY_POWER),
 };
 
 static struct smc91x_platdata smc91x_info = {
@@ -120,6 +119,15 @@ static struct resource smc91x_resources[
 	},
 };
 
+static void __init fsample_init_smc91x(void)
+{
+	fpga_write(1, H2P2_DBG_FPGA_LAN_RESET);
+	mdelay(50);
+	fpga_write(fpga_read(H2P2_DBG_FPGA_LAN_RESET) & ~1,
+		   H2P2_DBG_FPGA_LAN_RESET);
+	mdelay(50);
+}
+
 static struct mtd_partition nor_partitions[] = {
 	/* bootloader (U-Boot, etc) in first sector */
 	{
@@ -244,11 +252,15 @@ static struct resource kp_resources[] =
 	},
 };
 
+static const struct matrix_keymap_data fsample_keymap_data = {
+	.keymap		= fsample_keymap,
+	.keymap_size	= ARRAY_SIZE(fsample_keymap),
+};
+
 static struct omap_kp_platform_data kp_data = {
 	.rows		= 8,
 	.cols		= 8,
-	.keymap		= fsample_keymap,
-	.keymapsize	= ARRAY_SIZE(fsample_keymap),
+	.keymap_data	= &fsample_keymap_data,
 	.delay		= 4,
 };
 
@@ -285,6 +297,8 @@ static struct omap_board_config_kernel f
 
 static void __init omap_fsample_init(void)
 {
+	fsample_init_smc91x();
+
 	if (gpio_request(FSAMPLE_NAND_RB_GPIO_PIN, "NAND ready") < 0)
 		BUG();
 	gpio_direction_input(FSAMPLE_NAND_RB_GPIO_PIN);
@@ -312,21 +326,10 @@ static void __init omap_fsample_init(voi
 	omap_register_i2c_bus(1, 100, NULL, 0);
 }
 
-static void __init fsample_init_smc91x(void)
-{
-	fpga_write(1, H2P2_DBG_FPGA_LAN_RESET);
-	mdelay(50);
-	fpga_write(fpga_read(H2P2_DBG_FPGA_LAN_RESET) & ~1,
-		   H2P2_DBG_FPGA_LAN_RESET);
-	mdelay(50);
-}
-
 static void __init omap_fsample_init_irq(void)
 {
 	omap1_init_common_hw();
 	omap_init_irq();
-	omap_gpio_init();
-	fsample_init_smc91x();
 }
 
 /* Only FPGA needs to be mapped here. All others are done with ioremap */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap1/board-h2.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap1/board-h2.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap1/board-h2.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap1/board-h2.c	2011-03-14 21:20:32.000000000 -0400
@@ -52,43 +52,42 @@
 /* At OMAP1610 Innovator the Ethernet is directly connected to CS1 */
 #define OMAP1610_ETHR_START		0x04000300
 
-static int h2_keymap[] = {
+static const unsigned int h2_keymap[] = {
 	KEY(0, 0, KEY_LEFT),
-	KEY(0, 1, KEY_RIGHT),
-	KEY(0, 2, KEY_3),
-	KEY(0, 3, KEY_F10),
-	KEY(0, 4, KEY_F5),
-	KEY(0, 5, KEY_9),
-	KEY(1, 0, KEY_DOWN),
+	KEY(1, 0, KEY_RIGHT),
+	KEY(2, 0, KEY_3),
+	KEY(3, 0, KEY_F10),
+	KEY(4, 0, KEY_F5),
+	KEY(5, 0, KEY_9),
+	KEY(0, 1, KEY_DOWN),
 	KEY(1, 1, KEY_UP),
-	KEY(1, 2, KEY_2),
-	KEY(1, 3, KEY_F9),
-	KEY(1, 4, KEY_F7),
-	KEY(1, 5, KEY_0),
-	KEY(2, 0, KEY_ENTER),
-	KEY(2, 1, KEY_6),
+	KEY(2, 1, KEY_2),
+	KEY(3, 1, KEY_F9),
+	KEY(4, 1, KEY_F7),
+	KEY(5, 1, KEY_0),
+	KEY(0, 2, KEY_ENTER),
+	KEY(1, 2, KEY_6),
 	KEY(2, 2, KEY_1),
-	KEY(2, 3, KEY_F2),
-	KEY(2, 4, KEY_F6),
-	KEY(2, 5, KEY_HOME),
-	KEY(3, 0, KEY_8),
-	KEY(3, 1, KEY_5),
-	KEY(3, 2, KEY_F12),
+	KEY(3, 2, KEY_F2),
+	KEY(4, 2, KEY_F6),
+	KEY(5, 2, KEY_HOME),
+	KEY(0, 3, KEY_8),
+	KEY(1, 3, KEY_5),
+	KEY(2, 3, KEY_F12),
 	KEY(3, 3, KEY_F3),
-	KEY(3, 4, KEY_F8),
-	KEY(3, 5, KEY_END),
-	KEY(4, 0, KEY_7),
-	KEY(4, 1, KEY_4),
-	KEY(4, 2, KEY_F11),
-	KEY(4, 3, KEY_F1),
+	KEY(4, 3, KEY_F8),
+	KEY(5, 3, KEY_END),
+	KEY(0, 4, KEY_7),
+	KEY(1, 4, KEY_4),
+	KEY(2, 4, KEY_F11),
+	KEY(3, 4, KEY_F1),
 	KEY(4, 4, KEY_F4),
-	KEY(4, 5, KEY_ESC),
-	KEY(5, 0, KEY_F13),
-	KEY(5, 1, KEY_F14),
-	KEY(5, 2, KEY_F15),
-	KEY(5, 3, KEY_F16),
-	KEY(5, 4, KEY_SLEEP),
-	0
+	KEY(5, 4, KEY_ESC),
+	KEY(0, 5, KEY_F13),
+	KEY(1, 5, KEY_F14),
+	KEY(2, 5, KEY_F15),
+	KEY(3, 5, KEY_F16),
+	KEY(4, 5, KEY_SLEEP),
 };
 
 static struct mtd_partition h2_nor_partitions[] = {
@@ -270,14 +269,18 @@ static struct resource h2_kp_resources[]
 	},
 };
 
+static const struct matrix_keymap_data h2_keymap_data = {
+	.keymap		= h2_keymap,
+	.keymap_size	= ARRAY_SIZE(h2_keymap),
+};
+
 static struct omap_kp_platform_data h2_kp_data = {
 	.rows		= 8,
 	.cols		= 8,
-	.keymap		= h2_keymap,
-	.keymapsize	= ARRAY_SIZE(h2_keymap),
-	.rep		= 1,
+	.keymap_data	= &h2_keymap_data,
+	.rep		= true,
 	.delay		= 9,
-	.dbounce	= 1,
+	.dbounce	= true,
 };
 
 static struct platform_device h2_kp_device = {
@@ -374,8 +377,6 @@ static void __init h2_init_irq(void)
 {
 	omap1_init_common_hw();
 	omap_init_irq();
-	omap_gpio_init();
-	h2_init_smc91x();
 }
 
 static struct omap_usb_config h2_usb_config __initdata = {
@@ -403,6 +404,8 @@ static struct omap_board_config_kernel h
 
 static void __init h2_init(void)
 {
+	h2_init_smc91x();
+
 	/* Here we assume the NOR boot config:  NOR on CS3 (possibly swapped
 	 * to address 0 by a dip switch), NAND on CS2B.  The NAND driver will
 	 * notice whether a NAND chip is enabled at probe time.
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap1/board-h3.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap1/board-h3.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap1/board-h3.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap1/board-h3.c	2011-03-14 21:20:32.000000000 -0400
@@ -56,43 +56,42 @@
 
 #define H3_TS_GPIO	48
 
-static int h3_keymap[] = {
+static const unsigned int h3_keymap[] = {
 	KEY(0, 0, KEY_LEFT),
-	KEY(0, 1, KEY_RIGHT),
-	KEY(0, 2, KEY_3),
-	KEY(0, 3, KEY_F10),
-	KEY(0, 4, KEY_F5),
-	KEY(0, 5, KEY_9),
-	KEY(1, 0, KEY_DOWN),
+	KEY(1, 0, KEY_RIGHT),
+	KEY(2, 0, KEY_3),
+	KEY(3, 0, KEY_F10),
+	KEY(4, 0, KEY_F5),
+	KEY(5, 0, KEY_9),
+	KEY(0, 1, KEY_DOWN),
 	KEY(1, 1, KEY_UP),
-	KEY(1, 2, KEY_2),
-	KEY(1, 3, KEY_F9),
-	KEY(1, 4, KEY_F7),
-	KEY(1, 5, KEY_0),
-	KEY(2, 0, KEY_ENTER),
-	KEY(2, 1, KEY_6),
+	KEY(2, 1, KEY_2),
+	KEY(3, 1, KEY_F9),
+	KEY(4, 1, KEY_F7),
+	KEY(5, 1, KEY_0),
+	KEY(0, 2, KEY_ENTER),
+	KEY(1, 2, KEY_6),
 	KEY(2, 2, KEY_1),
-	KEY(2, 3, KEY_F2),
-	KEY(2, 4, KEY_F6),
-	KEY(2, 5, KEY_HOME),
-	KEY(3, 0, KEY_8),
-	KEY(3, 1, KEY_5),
-	KEY(3, 2, KEY_F12),
+	KEY(3, 2, KEY_F2),
+	KEY(4, 2, KEY_F6),
+	KEY(5, 2, KEY_HOME),
+	KEY(0, 3, KEY_8),
+	KEY(1, 3, KEY_5),
+	KEY(2, 3, KEY_F12),
 	KEY(3, 3, KEY_F3),
-	KEY(3, 4, KEY_F8),
-	KEY(3, 5, KEY_END),
-	KEY(4, 0, KEY_7),
-	KEY(4, 1, KEY_4),
-	KEY(4, 2, KEY_F11),
-	KEY(4, 3, KEY_F1),
+	KEY(4, 3, KEY_F8),
+	KEY(5, 3, KEY_END),
+	KEY(0, 4, KEY_7),
+	KEY(1, 4, KEY_4),
+	KEY(2, 4, KEY_F11),
+	KEY(3, 4, KEY_F1),
 	KEY(4, 4, KEY_F4),
-	KEY(4, 5, KEY_ESC),
-	KEY(5, 0, KEY_F13),
-	KEY(5, 1, KEY_F14),
-	KEY(5, 2, KEY_F15),
-	KEY(5, 3, KEY_F16),
-	KEY(5, 4, KEY_SLEEP),
-	0
+	KEY(5, 4, KEY_ESC),
+	KEY(0, 5, KEY_F13),
+	KEY(1, 5, KEY_F14),
+	KEY(2, 5, KEY_F15),
+	KEY(3, 5, KEY_F16),
+	KEY(4, 5, KEY_SLEEP),
 };
 
 
@@ -264,6 +263,15 @@ static struct platform_device smc91x_dev
 	.resource	= smc91x_resources,
 };
 
+static void __init h3_init_smc91x(void)
+{
+	omap_cfg_reg(W15_1710_GPIO40);
+	if (gpio_request(40, "SMC91x irq") < 0) {
+		printk("Error requesting gpio 40 for smc91x irq\n");
+		return;
+	}
+}
+
 #define GPTIMER_BASE		0xFFFB1400
 #define GPTIMER_REGS(x)	(0xFFFB1400 + (x * 0x800))
 #define GPTIMER_REGS_SIZE	0x46
@@ -296,14 +304,18 @@ static struct resource h3_kp_resources[]
 	},
 };
 
+static const struct matrix_keymap_data h3_keymap_data = {
+	.keymap		= h3_keymap,
+	.keymap_size	= ARRAY_SIZE(h3_keymap),
+};
+
 static struct omap_kp_platform_data h3_kp_data = {
 	.rows		= 8,
 	.cols		= 8,
-	.keymap		= h3_keymap,
-	.keymapsize	= ARRAY_SIZE(h3_keymap),
-	.rep		= 1,
+	.keymap_data	= &h3_keymap_data,
+	.rep		= true,
 	.delay		= 9,
-	.dbounce	= 1,
+	.dbounce	= true,
 };
 
 static struct platform_device h3_kp_device = {
@@ -376,6 +388,8 @@ static struct i2c_board_info __initdata
 
 static void __init h3_init(void)
 {
+	h3_init_smc91x();
+
 	/* Here we assume the NOR boot config:  NOR on CS3 (possibly swapped
 	 * to address 0 by a dip switch), NAND on CS2B.  The NAND driver will
 	 * notice whether a NAND chip is enabled at probe time.
@@ -422,21 +436,10 @@ static void __init h3_init(void)
 	h3_mmc_init();
 }
 
-static void __init h3_init_smc91x(void)
-{
-	omap_cfg_reg(W15_1710_GPIO40);
-	if (gpio_request(40, "SMC91x irq") < 0) {
-		printk("Error requesting gpio 40 for smc91x irq\n");
-		return;
-	}
-}
-
 static void __init h3_init_irq(void)
 {
 	omap1_init_common_hw();
 	omap_init_irq();
-	omap_gpio_init();
-	h3_init_smc91x();
 }
 
 static void __init h3_map_io(void)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap1/board-htcherald.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap1/board-htcherald.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap1/board-htcherald.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap1/board-htcherald.c	2011-03-14 21:20:32.000000000 -0400
@@ -180,64 +180,68 @@
 
 /* Keyboard definition */
 
-static int htc_herald_keymap[] = {
+static const unsigned int htc_herald_keymap[] = {
 	KEY(0, 0, KEY_RECORD), /* Mail button */
-	KEY(0, 1, KEY_CAMERA), /* Camera */
-	KEY(0, 2, KEY_PHONE), /* Send key */
-	KEY(0, 3, KEY_VOLUMEUP), /* Volume up */
-	KEY(0, 4, KEY_F2),  /* Right bar (landscape) */
-	KEY(0, 5, KEY_MAIL), /* Win key (portrait) */
-	KEY(0, 6, KEY_DIRECTORY), /* Right bar (protrait) */
-	KEY(1, 0, KEY_LEFTCTRL), /* Windows key */
+	KEY(1, 0, KEY_CAMERA), /* Camera */
+	KEY(2, 0, KEY_PHONE), /* Send key */
+	KEY(3, 0, KEY_VOLUMEUP), /* Volume up */
+	KEY(4, 0, KEY_F2),  /* Right bar (landscape) */
+	KEY(5, 0, KEY_MAIL), /* Win key (portrait) */
+	KEY(6, 0, KEY_DIRECTORY), /* Right bar (protrait) */
+	KEY(0, 1, KEY_LEFTCTRL), /* Windows key */
 	KEY(1, 1, KEY_COMMA),
-	KEY(1, 2, KEY_M),
-	KEY(1, 3, KEY_K),
-	KEY(1, 4, KEY_SLASH), /* OK key */
-	KEY(1, 5, KEY_I),
-	KEY(1, 6, KEY_U),
-	KEY(2, 0, KEY_LEFTALT),
-	KEY(2, 1, KEY_TAB),
+	KEY(2, 1, KEY_M),
+	KEY(3, 1, KEY_K),
+	KEY(4, 1, KEY_SLASH), /* OK key */
+	KEY(5, 1, KEY_I),
+	KEY(6, 1, KEY_U),
+	KEY(0, 2, KEY_LEFTALT),
+	KEY(1, 2, KEY_TAB),
 	KEY(2, 2, KEY_N),
-	KEY(2, 3, KEY_J),
-	KEY(2, 4, KEY_ENTER),
-	KEY(2, 5, KEY_H),
-	KEY(2, 6, KEY_Y),
-	KEY(3, 0, KEY_SPACE),
-	KEY(3, 1, KEY_L),
-	KEY(3, 2, KEY_B),
+	KEY(3, 2, KEY_J),
+	KEY(4, 2, KEY_ENTER),
+	KEY(5, 2, KEY_H),
+	KEY(6, 2, KEY_Y),
+	KEY(0, 3, KEY_SPACE),
+	KEY(1, 3, KEY_L),
+	KEY(2, 3, KEY_B),
 	KEY(3, 3, KEY_V),
-	KEY(3, 4, KEY_BACKSPACE),
-	KEY(3, 5, KEY_G),
-	KEY(3, 6, KEY_T),
-	KEY(4, 0, KEY_CAPSLOCK), /* Shift */
-	KEY(4, 1, KEY_C),
-	KEY(4, 2, KEY_F),
-	KEY(4, 3, KEY_R),
+	KEY(4, 3, KEY_BACKSPACE),
+	KEY(5, 3, KEY_G),
+	KEY(6, 3, KEY_T),
+	KEY(0, 4, KEY_CAPSLOCK), /* Shift */
+	KEY(1, 4, KEY_C),
+	KEY(2, 4, KEY_F),
+	KEY(3, 4, KEY_R),
 	KEY(4, 4, KEY_O),
-	KEY(4, 5, KEY_E),
-	KEY(4, 6, KEY_D),
-	KEY(5, 0, KEY_X),
-	KEY(5, 1, KEY_Z),
-	KEY(5, 2, KEY_S),
-	KEY(5, 3, KEY_W),
-	KEY(5, 4, KEY_P),
+	KEY(5, 4, KEY_E),
+	KEY(6, 4, KEY_D),
+	KEY(0, 5, KEY_X),
+	KEY(1, 5, KEY_Z),
+	KEY(2, 5, KEY_S),
+	KEY(3, 5, KEY_W),
+	KEY(4, 5, KEY_P),
 	KEY(5, 5, KEY_Q),
-	KEY(5, 6, KEY_A),
-	KEY(6, 0, KEY_CONNECT), /* Voice button */
-	KEY(6, 2, KEY_CANCEL), /* End key */
-	KEY(6, 3, KEY_VOLUMEDOWN), /* Volume down */
-	KEY(6, 4, KEY_F1), /* Left bar (landscape) */
-	KEY(6, 5, KEY_WWW), /* OK button (portrait) */
+	KEY(6, 5, KEY_A),
+	KEY(0, 6, KEY_CONNECT), /* Voice button */
+	KEY(2, 6, KEY_CANCEL), /* End key */
+	KEY(3, 6, KEY_VOLUMEDOWN), /* Volume down */
+	KEY(4, 6, KEY_F1), /* Left bar (landscape) */
+	KEY(5, 6, KEY_WWW), /* OK button (portrait) */
 	KEY(6, 6, KEY_CALENDAR), /* Left bar (portrait) */
-	0
 };
 
-struct omap_kp_platform_data htcherald_kp_data = {
+static const struct matrix_keymap_data htc_herald_keymap_data = {
+	.keymap		= htc_herald_keymap,
+	.keymap_size	= ARRAY_SIZE(htc_herald_keymap),
+};
+
+static struct omap_kp_platform_data htcherald_kp_data = {
 	.rows	= 7,
 	.cols	= 7,
 	.delay = 20,
-	.rep = 1,
-	.keymap = htc_herald_keymap,
+	.rep = true,
+	.keymap_data = &htc_herald_keymap_data,
 };
 
 static struct resource kp_resources[] = {
@@ -278,7 +282,7 @@ static struct gpio_keys_button herald_gp
 static struct gpio_keys_platform_data herald_gpio_keys_data = {
 	.buttons	= herald_gpio_keys_table,
 	.nbuttons	= ARRAY_SIZE(herald_gpio_keys_table),
-	.rep		= 1,
+	.rep		= true,
 };
 
 static struct platform_device herald_gpiokeys_device = {
@@ -439,7 +443,7 @@ static const struct ads7846_platform_dat
 	.keep_vref_on		= 1,
 	.x_plate_ohms		= 496,
 	.gpio_pendown		= HTCHERALD_GPIO_TS,
-	.pressure_max		= 100000,
+	.pressure_max		= 10000,
 	.pressure_min		= 5000,
 	.x_min			= 528,
 	.x_max			= 3760,
@@ -577,8 +581,6 @@ static void __init htcherald_init(void)
 	printk(KERN_INFO "HTC Herald init.\n");
 
 	/* Do board initialization before we register all the devices */
-	omap_gpio_init();
-
 	omap_board_config = htcherald_config;
 	omap_board_config_size = ARRAY_SIZE(htcherald_config);
 	platform_add_devices(devices, ARRAY_SIZE(devices));
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap1/board-innovator.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap1/board-innovator.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap1/board-innovator.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap1/board-innovator.c	2011-03-14 21:20:32.000000000 -0400
@@ -44,17 +44,16 @@
 /* At OMAP1610 Innovator the Ethernet is directly connected to CS1 */
 #define INNOVATOR1610_ETHR_START	0x04000300
 
-static int innovator_keymap[] = {
+static const unsigned int innovator_keymap[] = {
 	KEY(0, 0, KEY_F1),
-	KEY(0, 3, KEY_DOWN),
+	KEY(3, 0, KEY_DOWN),
 	KEY(1, 1, KEY_F2),
-	KEY(1, 2, KEY_RIGHT),
-	KEY(2, 0, KEY_F3),
-	KEY(2, 1, KEY_F4),
+	KEY(2, 1, KEY_RIGHT),
+	KEY(0, 2, KEY_F3),
+	KEY(1, 2, KEY_F4),
 	KEY(2, 2, KEY_UP),
-	KEY(3, 2, KEY_ENTER),
+	KEY(2, 3, KEY_ENTER),
 	KEY(3, 3, KEY_LEFT),
-	0
 };
 
 static struct mtd_partition innovator_partitions[] = {
@@ -126,11 +125,15 @@ static struct resource innovator_kp_reso
 	},
 };
 
+static const struct matrix_keymap_data innovator_keymap_data = {
+	.keymap		= innovator_keymap,
+	.keymap_size	= ARRAY_SIZE(innovator_keymap),
+};
+
 static struct omap_kp_platform_data innovator_kp_data = {
 	.rows		= 8,
 	.cols		= 8,
-	.keymap		= innovator_keymap,
-	.keymapsize	= ARRAY_SIZE(innovator_keymap),
+	.keymap_data	= &innovator_keymap_data,
 	.delay		= 4,
 };
 
@@ -290,13 +293,6 @@ static void __init innovator_init_irq(vo
 {
 	omap1_init_common_hw();
 	omap_init_irq();
-	omap_gpio_init();
-#ifdef CONFIG_ARCH_OMAP15XX
-	if (cpu_is_omap1510()) {
-		omap1510_fpga_init_irq();
-	}
-#endif
-	innovator_init_smc91x();
 }
 
 #ifdef CONFIG_ARCH_OMAP15XX
@@ -387,6 +383,10 @@ static struct omap_board_config_kernel i
 
 static void __init innovator_init(void)
 {
+	if (cpu_is_omap1510())
+		omap1510_fpga_init_irq();
+	innovator_init_smc91x();
+
 #ifdef CONFIG_ARCH_OMAP15XX
 	if (cpu_is_omap1510()) {
 		unsigned char reg;
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap1/board-nokia770.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap1/board-nokia770.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap1/board-nokia770.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap1/board-nokia770.c	2011-03-14 21:20:32.000000000 -0400
@@ -54,19 +54,18 @@ static void __init omap_nokia770_init_ir
 	omap_init_irq();
 }
 
-static int nokia770_keymap[] = {
-	KEY(0, 1, GROUP_0 | KEY_UP),
-	KEY(0, 2, GROUP_1 | KEY_F5),
-	KEY(1, 0, GROUP_0 | KEY_LEFT),
+static const unsigned int nokia770_keymap[] = {
+	KEY(1, 0, GROUP_0 | KEY_UP),
+	KEY(2, 0, GROUP_1 | KEY_F5),
+	KEY(0, 1, GROUP_0 | KEY_LEFT),
 	KEY(1, 1, GROUP_0 | KEY_ENTER),
-	KEY(1, 2, GROUP_0 | KEY_RIGHT),
-	KEY(2, 0, GROUP_1 | KEY_ESC),
-	KEY(2, 1, GROUP_0 | KEY_DOWN),
+	KEY(2, 1, GROUP_0 | KEY_RIGHT),
+	KEY(0, 2, GROUP_1 | KEY_ESC),
+	KEY(1, 2, GROUP_0 | KEY_DOWN),
 	KEY(2, 2, GROUP_1 | KEY_F4),
-	KEY(3, 0, GROUP_2 | KEY_F7),
-	KEY(3, 1, GROUP_2 | KEY_F8),
-	KEY(3, 2, GROUP_2 | KEY_F6),
-	0
+	KEY(0, 3, GROUP_2 | KEY_F7),
+	KEY(1, 3, GROUP_2 | KEY_F8),
+	KEY(2, 3, GROUP_2 | KEY_F6),
 };
 
 static struct resource nokia770_kp_resources[] = {
@@ -77,11 +76,15 @@ static struct resource nokia770_kp_resou
 	},
 };
 
+static const struct matrix_keymap_data nokia770_keymap_data = {
+	.keymap		= nokia770_keymap,
+	.keymap_size	= ARRAY_SIZE(nokia770_keymap),
+};
+
 static struct omap_kp_platform_data nokia770_kp_data = {
 	.rows		= 8,
 	.cols		= 8,
-	.keymap		= nokia770_keymap,
-	.keymapsize	= ARRAY_SIZE(nokia770_keymap),
+	.keymap_data	= &nokia770_keymap_data,
 	.delay		= 4,
 };
 
@@ -246,7 +249,6 @@ static void __init omap_nokia770_init(vo
 	platform_add_devices(nokia770_devices, ARRAY_SIZE(nokia770_devices));
 	spi_register_board_info(nokia770_spi_board_info,
 				ARRAY_SIZE(nokia770_spi_board_info));
-	omap_gpio_init();
 	omap_serial_init();
 	omap_register_i2c_bus(1, 100, NULL, 0);
 	hwa742_dev_init();
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap1/board-osk.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap1/board-osk.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap1/board-osk.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap1/board-osk.c	2011-03-14 21:20:32.000000000 -0400
@@ -283,9 +283,6 @@ static void __init osk_init_irq(void)
 {
 	omap1_init_common_hw();
 	omap_init_irq();
-	omap_gpio_init();
-	osk_init_smc91x();
-	osk_init_cf();
 }
 
 static struct omap_usb_config osk_usb_config __initdata = {
@@ -341,25 +338,28 @@ static struct i2c_board_info __initdata
 	 */
 };
 
-static const int osk_keymap[] = {
+static const unsigned int osk_keymap[] = {
 	/* KEY(col, row, code) */
 	KEY(0, 0, KEY_F1),		/* SW4 */
-	KEY(0, 3, KEY_UP),		/* (sw2/up) */
+	KEY(3, 0, KEY_UP),		/* (sw2/up) */
 	KEY(1, 1, KEY_LEFTCTRL),	/* SW5 */
-	KEY(1, 2, KEY_LEFT),		/* (sw2/left) */
-	KEY(2, 0, KEY_SPACE),		/* SW3 */
-	KEY(2, 1, KEY_ESC),		/* SW6 */
+	KEY(2, 1, KEY_LEFT),		/* (sw2/left) */
+	KEY(0, 2, KEY_SPACE),		/* SW3 */
+	KEY(1, 2, KEY_ESC),		/* SW6 */
 	KEY(2, 2, KEY_DOWN),		/* (sw2/down) */
-	KEY(3, 2, KEY_ENTER),		/* (sw2/select) */
+	KEY(2, 3, KEY_ENTER),		/* (sw2/select) */
 	KEY(3, 3, KEY_RIGHT),		/* (sw2/right) */
-	0
+};
+
+static const struct matrix_keymap_data osk_keymap_data = {
+	.keymap		= osk_keymap,
+	.keymap_size	= ARRAY_SIZE(osk_keymap),
 };
 
 static struct omap_kp_platform_data osk_kp_data = {
 	.rows		= 8,
 	.cols		= 8,
-	.keymap		= (int *) osk_keymap,
-	.keymapsize	= ARRAY_SIZE(osk_keymap),
+	.keymap_data	= &osk_keymap_data,
 	.delay		= 9,
 };
 
@@ -541,6 +541,9 @@ static void __init osk_init(void)
 {
 	u32 l;
 
+	osk_init_smc91x();
+	osk_init_cf();
+
 	/* Workaround for wrong CS3 (NOR flash) timing
 	 * There are some U-Boot versions out there which configure
 	 * wrong CS3 memory timings. This mainly leads to CRC
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap1/board-palmte.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap1/board-palmte.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap1/board-palmte.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap1/board-palmte.c	2011-03-14 21:20:32.000000000 -0400
@@ -63,28 +63,31 @@ static void __init omap_palmte_init_irq(
 {
 	omap1_init_common_hw();
 	omap_init_irq();
-	omap_gpio_init();
 }
 
-static const int palmte_keymap[] = {
+static const unsigned int palmte_keymap[] = {
 	KEY(0, 0, KEY_F1),		/* Calendar */
-	KEY(0, 1, KEY_F2),		/* Contacts */
-	KEY(0, 2, KEY_F3),		/* Tasks List */
-	KEY(0, 3, KEY_F4),		/* Note Pad */
-	KEY(0, 4, KEY_POWER),
-	KEY(1, 0, KEY_LEFT),
+	KEY(1, 0, KEY_F2),		/* Contacts */
+	KEY(2, 0, KEY_F3),		/* Tasks List */
+	KEY(3, 0, KEY_F4),		/* Note Pad */
+	KEY(4, 0, KEY_POWER),
+	KEY(0, 1, KEY_LEFT),
 	KEY(1, 1, KEY_DOWN),
-	KEY(1, 2, KEY_UP),
-	KEY(1, 3, KEY_RIGHT),
-	KEY(1, 4, KEY_ENTER),
-	0,
+	KEY(2, 1, KEY_UP),
+	KEY(3, 1, KEY_RIGHT),
+	KEY(4, 1, KEY_ENTER),
+};
+
+static const struct matrix_keymap_data palmte_keymap_data = {
+	.keymap		= palmte_keymap,
+	.keymap_size	= ARRAY_SIZE(palmte_keymap),
 };
 
 static struct omap_kp_platform_data palmte_kp_data = {
 	.rows	= 8,
 	.cols	= 8,
-	.keymap = (int *) palmte_keymap,
-	.rep	= 1,
+	.keymap_data = &palmte_keymap_data,
+	.rep	= true,
 	.delay	= 12,
 };
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap1/board-palmtt.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap1/board-palmtt.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap1/board-palmtt.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap1/board-palmtt.c	2011-03-14 21:20:32.000000000 -0400
@@ -51,19 +51,18 @@
 #define PALMTT_MMC_WP_GPIO	8
 #define PALMTT_HDQ_GPIO		11
 
-static int palmtt_keymap[] = {
+static const unsigned int palmtt_keymap[] = {
 	KEY(0, 0, KEY_ESC),
-	KEY(0, 1, KEY_SPACE),
-	KEY(0, 2, KEY_LEFTCTRL),
-	KEY(0, 3, KEY_TAB),
-	KEY(0, 4, KEY_ENTER),
-	KEY(1, 0, KEY_LEFT),
+	KEY(1, 0, KEY_SPACE),
+	KEY(2, 0, KEY_LEFTCTRL),
+	KEY(3, 0, KEY_TAB),
+	KEY(4, 0, KEY_ENTER),
+	KEY(0, 1, KEY_LEFT),
 	KEY(1, 1, KEY_DOWN),
-	KEY(1, 2, KEY_UP),
-	KEY(1, 3, KEY_RIGHT),
-	KEY(2, 0, KEY_SLEEP),
-	KEY(2, 4, KEY_Y),
-	0
+	KEY(2, 1, KEY_UP),
+	KEY(3, 1, KEY_RIGHT),
+	KEY(0, 2, KEY_SLEEP),
+	KEY(4, 2, KEY_Y),
 };
 
 static struct mtd_partition palmtt_partitions[] = {
@@ -136,10 +135,15 @@ static struct resource palmtt_kp_resourc
 	},
 };
 
+static const struct matrix_keymap_data palmtt_keymap_data = {
+	.keymap		= palmtt_keymap,
+	.keymap_size	= ARRAY_SIZE(palmtt_keymap),
+};
+
 static struct omap_kp_platform_data palmtt_kp_data = {
 	.rows	= 6,
 	.cols	= 3,
-	.keymap = palmtt_keymap,
+	.keymap_data = &palmtt_keymap_data,
 };
 
 static struct platform_device palmtt_kp_device = {
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap1/board-palmz71.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap1/board-palmz71.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap1/board-palmz71.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap1/board-palmz71.c	2011-03-14 21:20:32.000000000 -0400
@@ -62,29 +62,32 @@ omap_palmz71_init_irq(void)
 {
 	omap1_init_common_hw();
 	omap_init_irq();
-	omap_gpio_init();
 }
 
-static int palmz71_keymap[] = {
+static const unsigned int palmz71_keymap[] = {
 	KEY(0, 0, KEY_F1),
-	KEY(0, 1, KEY_F2),
-	KEY(0, 2, KEY_F3),
-	KEY(0, 3, KEY_F4),
-	KEY(0, 4, KEY_POWER),
-	KEY(1, 0, KEY_LEFT),
+	KEY(1, 0, KEY_F2),
+	KEY(2, 0, KEY_F3),
+	KEY(3, 0, KEY_F4),
+	KEY(4, 0, KEY_POWER),
+	KEY(0, 1, KEY_LEFT),
 	KEY(1, 1, KEY_DOWN),
-	KEY(1, 2, KEY_UP),
-	KEY(1, 3, KEY_RIGHT),
-	KEY(1, 4, KEY_ENTER),
-	KEY(2, 0, KEY_CAMERA),
-	0,
+	KEY(2, 1, KEY_UP),
+	KEY(3, 1, KEY_RIGHT),
+	KEY(4, 1, KEY_ENTER),
+	KEY(0, 2, KEY_CAMERA),
+};
+
+static const struct matrix_keymap_data palmz71_keymap_data = {
+	.keymap		= palmz71_keymap,
+	.keymap_size	= ARRAY_SIZE(palmz71_keymap),
 };
 
 static struct omap_kp_platform_data palmz71_kp_data = {
 	.rows	= 8,
 	.cols	= 8,
-	.keymap	= palmz71_keymap,
-	.rep	= 1,
+	.keymap_data	= &palmz71_keymap_data,
+	.rep	= true,
 	.delay	= 80,
 };
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap1/board-perseus2.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap1/board-perseus2.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap1/board-perseus2.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap1/board-perseus2.c	2011-03-14 21:20:32.000000000 -0400
@@ -36,36 +36,35 @@
 #include <plat/common.h>
 #include <plat/board.h>
 
-static int p2_keymap[] = {
-	KEY(0,0,KEY_UP),
-	KEY(0,1,KEY_RIGHT),
-	KEY(0,2,KEY_LEFT),
-	KEY(0,3,KEY_DOWN),
-	KEY(0,4,KEY_ENTER),
-	KEY(1,0,KEY_F10),
-	KEY(1,1,KEY_SEND),
-	KEY(1,2,KEY_END),
-	KEY(1,3,KEY_VOLUMEDOWN),
-	KEY(1,4,KEY_VOLUMEUP),
-	KEY(1,5,KEY_RECORD),
-	KEY(2,0,KEY_F9),
-	KEY(2,1,KEY_3),
-	KEY(2,2,KEY_6),
-	KEY(2,3,KEY_9),
-	KEY(2,4,KEY_KPDOT),
-	KEY(3,0,KEY_BACK),
-	KEY(3,1,KEY_2),
-	KEY(3,2,KEY_5),
-	KEY(3,3,KEY_8),
-	KEY(3,4,KEY_0),
-	KEY(3,5,KEY_KPSLASH),
-	KEY(4,0,KEY_HOME),
-	KEY(4,1,KEY_1),
-	KEY(4,2,KEY_4),
-	KEY(4,3,KEY_7),
-	KEY(4,4,KEY_KPASTERISK),
-	KEY(4,5,KEY_POWER),
-	0
+static const unsigned int p2_keymap[] = {
+	KEY(0, 0, KEY_UP),
+	KEY(1, 0, KEY_RIGHT),
+	KEY(2, 0, KEY_LEFT),
+	KEY(3, 0, KEY_DOWN),
+	KEY(4, 0, KEY_ENTER),
+	KEY(0, 1, KEY_F10),
+	KEY(1, 1, KEY_SEND),
+	KEY(2, 1, KEY_END),
+	KEY(3, 1, KEY_VOLUMEDOWN),
+	KEY(4, 1, KEY_VOLUMEUP),
+	KEY(5, 1, KEY_RECORD),
+	KEY(0, 2, KEY_F9),
+	KEY(1, 2, KEY_3),
+	KEY(2, 2, KEY_6),
+	KEY(3, 2, KEY_9),
+	KEY(4, 2, KEY_KPDOT),
+	KEY(0, 3, KEY_BACK),
+	KEY(1, 3, KEY_2),
+	KEY(2, 3, KEY_5),
+	KEY(3, 3, KEY_8),
+	KEY(4, 3, KEY_0),
+	KEY(5, 3, KEY_KPSLASH),
+	KEY(0, 4, KEY_HOME),
+	KEY(1, 4, KEY_1),
+	KEY(2, 4, KEY_4),
+	KEY(3, 4, KEY_7),
+	KEY(4, 4, KEY_KPASTERISK),
+	KEY(5, 4, KEY_POWER),
 };
 
 static struct smc91x_platdata smc91x_info = {
@@ -211,13 +210,17 @@ static struct resource kp_resources[] =
 	},
 };
 
+static const struct matrix_keymap_data p2_keymap_data = {
+	.keymap		= p2_keymap,
+	.keymap_size	= ARRAY_SIZE(p2_keymap),
+};
+
 static struct omap_kp_platform_data kp_data = {
 	.rows		= 8,
 	.cols		= 8,
-	.keymap		= p2_keymap,
-	.keymapsize	= ARRAY_SIZE(p2_keymap),
+	.keymap_data	= &p2_keymap_data,
 	.delay		= 4,
-	.dbounce	= 1,
+	.dbounce	= true,
 };
 
 static struct platform_device kp_device = {
@@ -251,8 +254,19 @@ static struct omap_board_config_kernel p
 	{ OMAP_TAG_LCD,		&perseus2_lcd_config },
 };
 
+static void __init perseus2_init_smc91x(void)
+{
+	fpga_write(1, H2P2_DBG_FPGA_LAN_RESET);
+	mdelay(50);
+	fpga_write(fpga_read(H2P2_DBG_FPGA_LAN_RESET) & ~1,
+		   H2P2_DBG_FPGA_LAN_RESET);
+	mdelay(50);
+}
+
 static void __init omap_perseus2_init(void)
 {
+	perseus2_init_smc91x();
+
 	if (gpio_request(P2_NAND_RB_GPIO_PIN, "NAND ready") < 0)
 		BUG();
 	gpio_direction_input(P2_NAND_RB_GPIO_PIN);
@@ -280,21 +294,10 @@ static void __init omap_perseus2_init(vo
 	omap_register_i2c_bus(1, 100, NULL, 0);
 }
 
-static void __init perseus2_init_smc91x(void)
-{
-	fpga_write(1, H2P2_DBG_FPGA_LAN_RESET);
-	mdelay(50);
-	fpga_write(fpga_read(H2P2_DBG_FPGA_LAN_RESET) & ~1,
-		   H2P2_DBG_FPGA_LAN_RESET);
-	mdelay(50);
-}
-
 static void __init omap_perseus2_init_irq(void)
 {
 	omap1_init_common_hw();
 	omap_init_irq();
-	omap_gpio_init();
-	perseus2_init_smc91x();
 }
 /* Only FPGA needs to be mapped here. All others are done with ioremap */
 static struct map_desc omap_perseus2_io_desc[] __initdata = {
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap1/board-sx1.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap1/board-sx1.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap1/board-sx1.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap1/board-sx1.c	2011-03-14 21:20:32.000000000 -0400
@@ -164,36 +164,35 @@ EXPORT_SYMBOL(sx1_setusbpower);
 
 /*----------- Keypad -------------------------*/
 
-static int sx1_keymap[] = {
-	KEY(5, 3, GROUP_0 | 117), /* camera Qt::Key_F17 */
-	KEY(0, 4, GROUP_0 | 114), /* voice memo Qt::Key_F14 */
-	KEY(1, 4, GROUP_2 | 114), /* voice memo */
-	KEY(2, 4, GROUP_3 | 114), /* voice memo */
+static const unsigned int sx1_keymap[] = {
+	KEY(3, 5, GROUP_0 | 117), /* camera Qt::Key_F17 */
+	KEY(4, 0, GROUP_0 | 114), /* voice memo Qt::Key_F14 */
+	KEY(4, 1, GROUP_2 | 114), /* voice memo */
+	KEY(4, 2, GROUP_3 | 114), /* voice memo */
 	KEY(0, 0, GROUP_1 | KEY_F12),	/* red button Qt::Key_Hangup */
-	KEY(4, 3, GROUP_1 | KEY_LEFT),
-	KEY(2, 3, GROUP_1 | KEY_DOWN),
-	KEY(1, 3, GROUP_1 | KEY_RIGHT),
-	KEY(0, 3, GROUP_1 | KEY_UP),
+	KEY(3, 4, GROUP_1 | KEY_LEFT),
+	KEY(3, 2, GROUP_1 | KEY_DOWN),
+	KEY(3, 1, GROUP_1 | KEY_RIGHT),
+	KEY(3, 0, GROUP_1 | KEY_UP),
 	KEY(3, 3, GROUP_1 | KEY_POWER), /* joystick press or Qt::Key_Select */
-	KEY(5, 0, GROUP_1 | KEY_1),
-	KEY(4, 0, GROUP_1 | KEY_2),
-	KEY(3, 0, GROUP_1 | KEY_3),
-	KEY(3, 4, GROUP_1 | KEY_4),
+	KEY(0, 5, GROUP_1 | KEY_1),
+	KEY(0, 4, GROUP_1 | KEY_2),
+	KEY(0, 3, GROUP_1 | KEY_3),
+	KEY(4, 3, GROUP_1 | KEY_4),
 	KEY(4, 4, GROUP_1 | KEY_5),
-	KEY(5, 4, GROUP_1 | KEY_KPASTERISK),/* "*" */
-	KEY(4, 1, GROUP_1 | KEY_6),
-	KEY(5, 1, GROUP_1 | KEY_7),
-	KEY(3, 1, GROUP_1 | KEY_8),
-	KEY(3, 2, GROUP_1 | KEY_9),
-	KEY(5, 2, GROUP_1 | KEY_0),
-	KEY(4, 2, GROUP_1 | 113),	/* # F13 Toggle input method Qt::Key_F13 */
-	KEY(0, 1, GROUP_1 | KEY_F11),	/* green button Qt::Key_Call */
-	KEY(1, 2, GROUP_1 | KEY_YEN),	/* left soft Qt::Key_Context1 */
+	KEY(4, 5, GROUP_1 | KEY_KPASTERISK),/* "*" */
+	KEY(1, 4, GROUP_1 | KEY_6),
+	KEY(1, 5, GROUP_1 | KEY_7),
+	KEY(1, 3, GROUP_1 | KEY_8),
+	KEY(2, 3, GROUP_1 | KEY_9),
+	KEY(2, 5, GROUP_1 | KEY_0),
+	KEY(2, 4, GROUP_1 | 113), /* # F13 Toggle input method Qt::Key_F13 */
+	KEY(1, 0, GROUP_1 | KEY_F11),	/* green button Qt::Key_Call */
+	KEY(2, 1, GROUP_1 | KEY_YEN),	/* left soft Qt::Key_Context1 */
 	KEY(2, 2, GROUP_1 | KEY_F8),	/* right soft Qt::Key_Back */
-	KEY(2, 1, GROUP_1 | KEY_LEFTSHIFT), /* shift */
+	KEY(1, 2, GROUP_1 | KEY_LEFTSHIFT), /* shift */
 	KEY(1, 1, GROUP_1 | KEY_BACKSPACE), /* C (clear) */
-	KEY(0, 2, GROUP_1 | KEY_F7),	/* menu Qt::Key_Menu */
-	0
+	KEY(2, 0, GROUP_1 | KEY_F7),	/* menu Qt::Key_Menu */
 };
 
 static struct resource sx1_kp_resources[] = {
@@ -204,11 +203,15 @@ static struct resource sx1_kp_resources[
 	},
 };
 
+static const struct matrix_keymap_data sx1_keymap_data = {
+	.keymap		= sx1_keymap,
+	.keymap_size	= ARRAY_SIZE(sx1_keymap),
+};
+
 static struct omap_kp_platform_data sx1_kp_data = {
 	.rows		= 6,
 	.cols		= 6,
-	.keymap	= sx1_keymap,
-	.keymapsize = ARRAY_SIZE(sx1_keymap),
+	.keymap_data	= &sx1_keymap_data,
 	.delay	= 80,
 };
 
@@ -409,7 +412,6 @@ static void __init omap_sx1_init_irq(voi
 {
 	omap1_init_common_hw();
 	omap_init_irq();
-	omap_gpio_init();
 }
 /*----------------------------------------*/
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap1/board-voiceblue.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap1/board-voiceblue.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap1/board-voiceblue.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap1/board-voiceblue.c	2011-03-14 21:20:32.000000000 -0400
@@ -83,6 +83,9 @@ static struct platform_device serial_dev
 
 static int __init ext_uart_init(void)
 {
+	if (!machine_is_voiceblue())
+		return -ENODEV;
+
 	return platform_device_register(&serial_device);
 }
 arch_initcall(ext_uart_init);
@@ -158,7 +161,6 @@ static void __init voiceblue_init_irq(vo
 {
 	omap1_init_common_hw();
 	omap_init_irq();
-	omap_gpio_init();
 }
 
 static void __init voiceblue_init(void)
@@ -236,6 +238,9 @@ static struct notifier_block panic_block
 
 static int __init voiceblue_setup(void)
 {
+	if (!machine_is_voiceblue())
+		return -ENODEV;
+
 	/* Setup panic notifier */
 	atomic_notifier_chain_register(&panic_notifier_list, &panic_block);
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap1/clock.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap1/clock.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap1/clock.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap1/clock.c	2011-03-14 21:20:32.000000000 -0400
@@ -17,9 +17,9 @@
 #include <linux/err.h>
 #include <linux/clk.h>
 #include <linux/io.h>
+#include <linux/clkdev.h>
 
 #include <asm/mach-types.h>
-#include <asm/clkdev.h>
 
 #include <plat/cpu.h>
 #include <plat/usb.h>
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap1/clock_data.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap1/clock_data.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap1/clock_data.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap1/clock_data.c	2011-03-14 21:20:32.000000000 -0400
@@ -143,7 +143,7 @@ static struct arm_idlect1_clk armper_ck
  * activation.  [ GPIO code for 1510 ]
  */
 static struct clk arm_gpio_ck = {
-	.name		= "arm_gpio_ck",
+	.name		= "ick",
 	.ops		= &clkops_generic,
 	.parent		= &ck_dpll1,
 	.flags		= ENABLE_ON_INIT,
@@ -684,7 +684,7 @@ static struct omap_clk omap_clks[] = {
 	CLK(NULL,	"ck_sossi",	&sossi_ck,	CK_16XX),
 	CLK(NULL,	"arm_ck",	&arm_ck,	CK_16XX | CK_1510 | CK_310),
 	CLK(NULL,	"armper_ck",	&armper_ck.clk,	CK_16XX | CK_1510 | CK_310),
-	CLK(NULL,	"arm_gpio_ck",	&arm_gpio_ck,	CK_1510 | CK_310),
+	CLK("omap_gpio.0", "ick",	&arm_gpio_ck,	CK_1510 | CK_310),
 	CLK(NULL,	"armxor_ck",	&armxor_ck.clk,	CK_16XX | CK_1510 | CK_310 | CK_7XX),
 	CLK(NULL,	"armtim_ck",	&armtim_ck.clk,	CK_16XX | CK_1510 | CK_310),
 	CLK("omap_wdt",	"fck",		&armwdt_ck.clk,	CK_16XX | CK_1510 | CK_310),
@@ -736,9 +736,9 @@ static struct omap_clk omap_clks[] = {
 	CLK("mmci-omap.1", "ick",	&armper_ck.clk,	CK_16XX),
 	/* Virtual clocks */
 	CLK(NULL,	"mpu",		&virtual_ck_mpu, CK_16XX | CK_1510 | CK_310),
-	CLK("i2c_omap.1", "fck",	&i2c_fck,	CK_16XX | CK_1510 | CK_310 | CK_7XX),
-	CLK("i2c_omap.1", "ick",	&i2c_ick,	CK_16XX),
-	CLK("i2c_omap.1", "ick",	&dummy_ck,	CK_1510 | CK_310 | CK_7XX),
+	CLK("omap_i2c.1", "fck",	&i2c_fck,	CK_16XX | CK_1510 | CK_310 | CK_7XX),
+	CLK("omap_i2c.1", "ick",	&i2c_ick,	CK_16XX),
+	CLK("omap_i2c.1", "ick",	&dummy_ck,	CK_1510 | CK_310 | CK_7XX),
 	CLK("omap1_spi100k.1", "fck",	&dummy_ck,	CK_7XX),
 	CLK("omap1_spi100k.1", "ick",	&dummy_ck,	CK_7XX),
 	CLK("omap1_spi100k.2", "fck",	&dummy_ck,	CK_7XX),
@@ -823,12 +823,10 @@ int __init omap1_clk_init(void)
 			crystal_type = info->system_clock_type;
 	}
 
-#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
-	ck_ref.rate = 13000000;
-#elif defined(CONFIG_ARCH_OMAP16XX)
-	if (crystal_type == 2)
+	if (cpu_is_omap7xx())
+		ck_ref.rate = 13000000;
+	if (cpu_is_omap16xx() && crystal_type == 2)
 		ck_ref.rate = 19200000;
-#endif
 
 	pr_info("Clocks: ARM_SYSST: 0x%04x DPLL_CTL: 0x%04x ARM_CKCTL: "
 		"0x%04x\n", omap_readw(ARM_SYSST), omap_readw(DPLL_CTL),
@@ -883,10 +881,11 @@ int __init omap1_clk_init(void)
 	       ck_dpll1.rate / 1000000, (ck_dpll1.rate / 100000) % 10,
 	       arm_ck.rate / 1000000, (arm_ck.rate / 100000) % 10);
 
-#if defined(CONFIG_MACH_OMAP_PERSEUS2) || defined(CONFIG_MACH_OMAP_FSAMPLE)
-	/* Select slicer output as OMAP input clock */
-	omap_writew(omap_readw(OMAP7XX_PCC_UPLD_CTRL) & ~0x1, OMAP7XX_PCC_UPLD_CTRL);
-#endif
+	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,
+				OMAP7XX_PCC_UPLD_CTRL);
+	}
 
 	/* Amstrad Delta wants BCLK high when inactive */
 	if (machine_is_ams_delta())
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap1/devices.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap1/devices.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap1/devices.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap1/devices.c	2011-03-14 21:20:32.000000000 -0400
@@ -17,6 +17,7 @@
 #include <linux/io.h>
 #include <linux/spi/spi.h>
 
+#include <mach/camera.h>
 #include <mach/hardware.h>
 #include <asm/mach/map.h>
 
@@ -287,6 +288,9 @@ static inline void omap_init_audio(void)
  */
 static int __init omap1_init_devices(void)
 {
+	if (!cpu_class_is_omap1())
+		return -ENODEV;
+
 	/* please keep these calls, and their implementations above,
 	 * in alphabetical order so they're easier to sort through.
 	 */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap1/dma.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap1/dma.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap1/dma.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap1/dma.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,390 @@
+/*
+ * OMAP1/OMAP7xx - specific DMA driver
+ *
+ * Copyright (C) 2003 - 2008 Nokia Corporation
+ * Author: Juha Yrjölä <juha.yrjola@nokia.com>
+ * DMA channel linking for 1610 by Samuel Ortiz <samuel.ortiz@nokia.com>
+ * Graphics DMA and LCD DMA graphics tranformations
+ * by Imre Deak <imre.deak@nokia.com>
+ * OMAP2/3 support Copyright (C) 2004-2007 Texas Instruments, Inc.
+ * Some functions based on earlier dma-omap.c Copyright (C) 2001 RidgeRun, Inc.
+ *
+ * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
+ * Converted DMA library into platform driver
+ *                   - G, Manjunath Kondaiah <manjugk@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.
+ */
+
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/device.h>
+
+#include <plat/dma.h>
+#include <plat/tc.h>
+#include <plat/irqs.h>
+
+#define OMAP1_DMA_BASE			(0xfffed800)
+#define OMAP1_LOGICAL_DMA_CH_COUNT	17
+#define OMAP1_DMA_STRIDE		0x40
+
+static u32 errata;
+static u32 enable_1510_mode;
+static u8 dma_stride;
+static enum omap_reg_offsets dma_common_ch_start, dma_common_ch_end;
+
+static u16 reg_map[] = {
+	[GCR]		= 0x400,
+	[GSCR]		= 0x404,
+	[GRST1]		= 0x408,
+	[HW_ID]		= 0x442,
+	[PCH2_ID]	= 0x444,
+	[PCH0_ID]	= 0x446,
+	[PCH1_ID]	= 0x448,
+	[PCHG_ID]	= 0x44a,
+	[PCHD_ID]	= 0x44c,
+	[CAPS_0]	= 0x44e,
+	[CAPS_1]	= 0x452,
+	[CAPS_2]	= 0x456,
+	[CAPS_3]	= 0x458,
+	[CAPS_4]	= 0x45a,
+	[PCH2_SR]	= 0x460,
+	[PCH0_SR]	= 0x480,
+	[PCH1_SR]	= 0x482,
+	[PCHD_SR]	= 0x4c0,
+
+	/* Common Registers */
+	[CSDP]		= 0x00,
+	[CCR]		= 0x02,
+	[CICR]		= 0x04,
+	[CSR]		= 0x06,
+	[CEN]		= 0x10,
+	[CFN]		= 0x12,
+	[CSFI]		= 0x14,
+	[CSEI]		= 0x16,
+	[CPC]		= 0x18,	/* 15xx only */
+	[CSAC]		= 0x18,
+	[CDAC]		= 0x1a,
+	[CDEI]		= 0x1c,
+	[CDFI]		= 0x1e,
+	[CLNK_CTRL]	= 0x28,
+
+	/* Channel specific register offsets */
+	[CSSA]		= 0x08,
+	[CDSA]		= 0x0c,
+	[COLOR]		= 0x20,
+	[CCR2]		= 0x24,
+	[LCH_CTRL]	= 0x2a,
+};
+
+static struct resource res[] __initdata = {
+	[0] = {
+		.start	= OMAP1_DMA_BASE,
+		.end	= OMAP1_DMA_BASE + SZ_2K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.name   = "0",
+		.start  = INT_DMA_CH0_6,
+		.flags  = IORESOURCE_IRQ,
+	},
+	[2] = {
+		.name   = "1",
+		.start  = INT_DMA_CH1_7,
+		.flags  = IORESOURCE_IRQ,
+	},
+	[3] = {
+		.name   = "2",
+		.start  = INT_DMA_CH2_8,
+		.flags  = IORESOURCE_IRQ,
+	},
+	[4] = {
+		.name   = "3",
+		.start  = INT_DMA_CH3,
+		.flags  = IORESOURCE_IRQ,
+	},
+	[5] = {
+		.name   = "4",
+		.start  = INT_DMA_CH4,
+		.flags  = IORESOURCE_IRQ,
+	},
+	[6] = {
+		.name   = "5",
+		.start  = INT_DMA_CH5,
+		.flags  = IORESOURCE_IRQ,
+	},
+	/* Handled in lcd_dma.c */
+	[7] = {
+		.name   = "6",
+		.start  = INT_1610_DMA_CH6,
+		.flags  = IORESOURCE_IRQ,
+	},
+	/* irq's for omap16xx and omap7xx */
+	[8] = {
+		.name   = "7",
+		.start  = INT_1610_DMA_CH7,
+		.flags  = IORESOURCE_IRQ,
+	},
+	[9] = {
+		.name   = "8",
+		.start  = INT_1610_DMA_CH8,
+		.flags  = IORESOURCE_IRQ,
+	},
+	[10] = {
+		.name  = "9",
+		.start = INT_1610_DMA_CH9,
+		.flags = IORESOURCE_IRQ,
+	},
+	[11] = {
+		.name  = "10",
+		.start = INT_1610_DMA_CH10,
+		.flags = IORESOURCE_IRQ,
+	},
+	[12] = {
+		.name  = "11",
+		.start = INT_1610_DMA_CH11,
+		.flags = IORESOURCE_IRQ,
+	},
+	[13] = {
+		.name  = "12",
+		.start = INT_1610_DMA_CH12,
+		.flags = IORESOURCE_IRQ,
+	},
+	[14] = {
+		.name  = "13",
+		.start = INT_1610_DMA_CH13,
+		.flags = IORESOURCE_IRQ,
+	},
+	[15] = {
+		.name  = "14",
+		.start = INT_1610_DMA_CH14,
+		.flags = IORESOURCE_IRQ,
+	},
+	[16] = {
+		.name  = "15",
+		.start = INT_1610_DMA_CH15,
+		.flags = IORESOURCE_IRQ,
+	},
+	[17] = {
+		.name  = "16",
+		.start = INT_DMA_LCD,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+static void __iomem *dma_base;
+static inline void dma_write(u32 val, int reg, int lch)
+{
+	u8  stride;
+	u32 offset;
+
+	stride = (reg >= dma_common_ch_start) ? dma_stride : 0;
+	offset = reg_map[reg] + (stride * lch);
+
+	__raw_writew(val, dma_base + offset);
+	if ((reg > CLNK_CTRL && reg < CCEN) ||
+			(reg > PCHD_ID && reg < CAPS_2)) {
+		u32 offset2 = reg_map[reg] + 2 + (stride * lch);
+		__raw_writew(val >> 16, dma_base + offset2);
+	}
+}
+
+static inline u32 dma_read(int reg, int lch)
+{
+	u8 stride;
+	u32 offset, val;
+
+	stride = (reg >= dma_common_ch_start) ? dma_stride : 0;
+	offset = reg_map[reg] + (stride * lch);
+
+	val = __raw_readw(dma_base + offset);
+	if ((reg > CLNK_CTRL && reg < CCEN) ||
+			(reg > PCHD_ID && reg < CAPS_2)) {
+		u16 upper;
+		u32 offset2 = reg_map[reg] + 2 + (stride * lch);
+		upper = __raw_readw(dma_base + offset2);
+		val |= (upper << 16);
+	}
+	return val;
+}
+
+static void omap1_clear_lch_regs(int lch)
+{
+	int i = dma_common_ch_start;
+
+	for (; i <= dma_common_ch_end; i += 1)
+		dma_write(0, i, lch);
+}
+
+static void omap1_clear_dma(int lch)
+{
+	u32 l;
+
+	l = dma_read(CCR, lch);
+	l &= ~OMAP_DMA_CCR_EN;
+	dma_write(l, CCR, lch);
+
+	/* Clear pending interrupts */
+	l = dma_read(CSR, lch);
+}
+
+static void omap1_show_dma_caps(void)
+{
+	if (enable_1510_mode) {
+		printk(KERN_INFO "DMA support for OMAP15xx initialized\n");
+	} else {
+		u16 w;
+		printk(KERN_INFO "OMAP DMA hardware version %d\n",
+							dma_read(HW_ID, 0));
+		printk(KERN_INFO "DMA capabilities: %08x:%08x:%04x:%04x:%04x\n",
+			dma_read(CAPS_0, 0), dma_read(CAPS_1, 0),
+			dma_read(CAPS_2, 0), dma_read(CAPS_3, 0),
+			dma_read(CAPS_4, 0));
+
+		/* Disable OMAP 3.0/3.1 compatibility mode. */
+		w = dma_read(GSCR, 0);
+		w |= 1 << 3;
+		dma_write(w, GSCR, 0);
+	}
+	return;
+}
+
+static u32 configure_dma_errata(void)
+{
+
+	/*
+	 * Erratum 3.2/3.3: sometimes 0 is returned if CSAC/CDAC is
+	 * read before the DMA controller finished disabling the channel.
+	 */
+	if (!cpu_is_omap15xx())
+		SET_DMA_ERRATA(DMA_ERRATA_3_3);
+
+	return errata;
+}
+
+static int __init omap1_system_dma_init(void)
+{
+	struct omap_system_dma_plat_info	*p;
+	struct omap_dma_dev_attr		*d;
+	struct platform_device			*pdev;
+	int ret;
+
+	pdev = platform_device_alloc("omap_dma_system", 0);
+	if (!pdev) {
+		pr_err("%s: Unable to device alloc for dma\n",
+			__func__);
+		return -ENOMEM;
+	}
+
+	dma_base = ioremap(res[0].start, resource_size(&res[0]));
+	if (!dma_base) {
+		pr_err("%s: Unable to ioremap\n", __func__);
+		return -ENODEV;
+	}
+
+	ret = platform_device_add_resources(pdev, res, ARRAY_SIZE(res));
+	if (ret) {
+		dev_err(&pdev->dev, "%s: Unable to add resources for %s%d\n",
+			__func__, pdev->name, pdev->id);
+		goto exit_device_del;
+	}
+
+	p = kzalloc(sizeof(struct omap_system_dma_plat_info), GFP_KERNEL);
+	if (!p) {
+		dev_err(&pdev->dev, "%s: Unable to allocate 'p' for %s\n",
+			__func__, pdev->name);
+		ret = -ENOMEM;
+		goto exit_device_put;
+	}
+
+	d = kzalloc(sizeof(struct omap_dma_dev_attr), GFP_KERNEL);
+	if (!d) {
+		dev_err(&pdev->dev, "%s: Unable to allocate 'd' for %s\n",
+			__func__, pdev->name);
+		ret = -ENOMEM;
+		goto exit_release_p;
+	}
+
+	d->lch_count		= OMAP1_LOGICAL_DMA_CH_COUNT;
+
+	/* Valid attributes for omap1 plus processors */
+	if (cpu_is_omap15xx())
+		d->dev_caps = ENABLE_1510_MODE;
+	enable_1510_mode = d->dev_caps & ENABLE_1510_MODE;
+
+	d->dev_caps		|= SRC_PORT;
+	d->dev_caps		|= DST_PORT;
+	d->dev_caps		|= SRC_INDEX;
+	d->dev_caps		|= DST_INDEX;
+	d->dev_caps		|= IS_BURST_ONLY4;
+	d->dev_caps		|= CLEAR_CSR_ON_READ;
+	d->dev_caps		|= IS_WORD_16;
+
+
+	d->chan = kzalloc(sizeof(struct omap_dma_lch) *
+					(d->lch_count), GFP_KERNEL);
+	if (!d->chan) {
+		dev_err(&pdev->dev, "%s: Memory allocation failed"
+					"for d->chan!!!\n", __func__);
+		goto exit_release_d;
+	}
+
+	if (cpu_is_omap15xx())
+		d->chan_count = 9;
+	else if (cpu_is_omap16xx() || cpu_is_omap7xx()) {
+		if (!(d->dev_caps & ENABLE_1510_MODE))
+			d->chan_count = 16;
+		else
+			d->chan_count = 9;
+	}
+
+	p->dma_attr = d;
+
+	p->show_dma_caps	= omap1_show_dma_caps;
+	p->clear_lch_regs	= omap1_clear_lch_regs;
+	p->clear_dma		= omap1_clear_dma;
+	p->dma_write		= dma_write;
+	p->dma_read		= dma_read;
+	p->disable_irq_lch	= NULL;
+
+	p->errata = configure_dma_errata();
+
+	ret = platform_device_add_data(pdev, p, sizeof(*p));
+	if (ret) {
+		dev_err(&pdev->dev, "%s: Unable to add resources for %s%d\n",
+			__func__, pdev->name, pdev->id);
+		goto exit_release_chan;
+	}
+
+	ret = platform_device_add(pdev);
+	if (ret) {
+		dev_err(&pdev->dev, "%s: Unable to add resources for %s%d\n",
+			__func__, pdev->name, pdev->id);
+		goto exit_release_chan;
+	}
+
+	dma_stride		= OMAP1_DMA_STRIDE;
+	dma_common_ch_start	= CPC;
+	dma_common_ch_end	= COLOR;
+
+	return ret;
+
+exit_release_chan:
+	kfree(d->chan);
+exit_release_d:
+	kfree(d);
+exit_release_p:
+	kfree(p);
+exit_device_put:
+	platform_device_put(pdev);
+exit_device_del:
+	platform_device_del(pdev);
+
+	return ret;
+}
+arch_initcall(omap1_system_dma_init);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap1/flash.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap1/flash.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap1/flash.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap1/flash.c	2011-03-14 21:20:32.000000000 -0400
@@ -11,6 +11,7 @@
 
 #include <plat/io.h>
 #include <plat/tc.h>
+#include <plat/flash.h>
 
 void omap1_set_vpp(struct map_info *map, int enable)
 {
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap1/fpga.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap1/fpga.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap1/fpga.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap1/fpga.c	2011-03-14 21:20:32.000000000 -0400
@@ -30,9 +30,9 @@
 #include <plat/fpga.h>
 #include <mach/gpio.h>
 
-static void fpga_mask_irq(unsigned int irq)
+static void fpga_mask_irq(struct irq_data *d)
 {
-	irq -= OMAP_FPGA_IRQ_BASE;
+	unsigned int irq = d->irq - OMAP_FPGA_IRQ_BASE;
 
 	if (irq < 8)
 		__raw_writeb((__raw_readb(OMAP1510_FPGA_IMR_LO)
@@ -58,14 +58,14 @@ static inline u32 get_fpga_unmasked_irqs
 }
 
 
-static void fpga_ack_irq(unsigned int irq)
+static void fpga_ack_irq(struct irq_data *d)
 {
 	/* Don't need to explicitly ACK FPGA interrupts */
 }
 
-static void fpga_unmask_irq(unsigned int irq)
+static void fpga_unmask_irq(struct irq_data *d)
 {
-	irq -= OMAP_FPGA_IRQ_BASE;
+	unsigned int irq = d->irq - OMAP_FPGA_IRQ_BASE;
 
 	if (irq < 8)
 		__raw_writeb((__raw_readb(OMAP1510_FPGA_IMR_LO) | (1 << irq)),
@@ -78,10 +78,10 @@ static void fpga_unmask_irq(unsigned int
 			      | (1 << (irq - 16))), INNOVATOR_FPGA_IMR2);
 }
 
-static void fpga_mask_ack_irq(unsigned int irq)
+static void fpga_mask_ack_irq(struct irq_data *d)
 {
-	fpga_mask_irq(irq);
-	fpga_ack_irq(irq);
+	fpga_mask_irq(d);
+	fpga_ack_irq(d);
 }
 
 void innovator_fpga_IRQ_demux(unsigned int irq, struct irq_desc *desc)
@@ -105,17 +105,17 @@ void innovator_fpga_IRQ_demux(unsigned i
 
 static struct irq_chip omap_fpga_irq_ack = {
 	.name		= "FPGA-ack",
-	.ack		= fpga_mask_ack_irq,
-	.mask		= fpga_mask_irq,
-	.unmask		= fpga_unmask_irq,
+	.irq_ack	= fpga_mask_ack_irq,
+	.irq_mask	= fpga_mask_irq,
+	.irq_unmask	= fpga_unmask_irq,
 };
 
 
 static struct irq_chip omap_fpga_irq = {
 	.name		= "FPGA",
-	.ack		= fpga_ack_irq,
-	.mask		= fpga_mask_irq,
-	.unmask		= fpga_unmask_irq,
+	.irq_ack	= fpga_ack_irq,
+	.irq_mask	= fpga_mask_irq,
+	.irq_unmask	= fpga_unmask_irq,
 };
 
 /*
@@ -143,7 +143,7 @@ static struct irq_chip omap_fpga_irq = {
  */
 void omap1510_fpga_init_irq(void)
 {
-	int i;
+	int i, res;
 
 	__raw_writeb(0, OMAP1510_FPGA_IMR_LO);
 	__raw_writeb(0, OMAP1510_FPGA_IMR_HI);
@@ -177,10 +177,12 @@ void omap1510_fpga_init_irq(void)
 	 * NOTE: For general GPIO/MPUIO access and interrupts, please see
 	 * gpio.[ch]
 	 */
-	gpio_request(13, "FPGA irq");
+	res = gpio_request(13, "FPGA irq");
+	if (res) {
+		pr_err("%s failed to get gpio\n", __func__);
+		return;
+	}
 	gpio_direction_input(13);
 	set_irq_type(gpio_to_irq(13), IRQ_TYPE_EDGE_RISING);
 	set_irq_chained_handler(OMAP1510_INT_FPGA, innovator_fpga_IRQ_demux);
 }
-
-EXPORT_SYMBOL(omap1510_fpga_init_irq);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap1/gpio15xx.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap1/gpio15xx.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap1/gpio15xx.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap1/gpio15xx.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,99 @@
+/*
+ * OMAP15xx specific gpio init
+ *
+ * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Author:
+ *	Charulatha V <charu@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 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/gpio.h>
+
+#define OMAP1_MPUIO_VBASE		OMAP1_MPUIO_BASE
+#define OMAP1510_GPIO_BASE		0xFFFCE000
+
+/* gpio1 */
+static struct __initdata resource omap15xx_mpu_gpio_resources[] = {
+	{
+		.start	= OMAP1_MPUIO_VBASE,
+		.end	= OMAP1_MPUIO_VBASE + SZ_2K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.start	= INT_MPUIO,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct __initdata omap_gpio_platform_data omap15xx_mpu_gpio_config = {
+	.virtual_irq_start	= IH_MPUIO_BASE,
+	.bank_type		= METHOD_MPUIO,
+	.bank_width		= 16,
+	.bank_stride		= 1,
+};
+
+static struct __initdata platform_device omap15xx_mpu_gpio = {
+	.name           = "omap_gpio",
+	.id             = 0,
+	.dev            = {
+		.platform_data = &omap15xx_mpu_gpio_config,
+	},
+	.num_resources = ARRAY_SIZE(omap15xx_mpu_gpio_resources),
+	.resource = omap15xx_mpu_gpio_resources,
+};
+
+/* gpio2 */
+static struct __initdata resource omap15xx_gpio_resources[] = {
+	{
+		.start	= OMAP1510_GPIO_BASE,
+		.end	= OMAP1510_GPIO_BASE + SZ_2K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.start	= INT_GPIO_BANK1,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct __initdata omap_gpio_platform_data omap15xx_gpio_config = {
+	.virtual_irq_start	= IH_GPIO_BASE,
+	.bank_type		= METHOD_GPIO_1510,
+	.bank_width		= 16,
+};
+
+static struct __initdata platform_device omap15xx_gpio = {
+	.name           = "omap_gpio",
+	.id             = 1,
+	.dev            = {
+		.platform_data = &omap15xx_gpio_config,
+	},
+	.num_resources = ARRAY_SIZE(omap15xx_gpio_resources),
+	.resource = omap15xx_gpio_resources,
+};
+
+/*
+ * omap15xx_gpio_init needs to be done before
+ * machine_init functions access gpio APIs.
+ * Hence omap15xx_gpio_init is a postcore_initcall.
+ */
+static int __init omap15xx_gpio_init(void)
+{
+	if (!cpu_is_omap15xx())
+		return -EINVAL;
+
+	platform_device_register(&omap15xx_mpu_gpio);
+	platform_device_register(&omap15xx_gpio);
+
+	gpio_bank_count = 2;
+	return 0;
+}
+postcore_initcall(omap15xx_gpio_init);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap1/gpio16xx.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap1/gpio16xx.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap1/gpio16xx.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap1/gpio16xx.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,200 @@
+/*
+ * OMAP16xx specific gpio init
+ *
+ * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Author:
+ *	Charulatha V <charu@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 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/gpio.h>
+
+#define OMAP1610_GPIO1_BASE		0xfffbe400
+#define OMAP1610_GPIO2_BASE		0xfffbec00
+#define OMAP1610_GPIO3_BASE		0xfffbb400
+#define OMAP1610_GPIO4_BASE		0xfffbbc00
+#define OMAP1_MPUIO_VBASE		OMAP1_MPUIO_BASE
+
+/* mpu gpio */
+static struct __initdata resource omap16xx_mpu_gpio_resources[] = {
+	{
+		.start	= OMAP1_MPUIO_VBASE,
+		.end	= OMAP1_MPUIO_VBASE + SZ_2K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.start	= INT_MPUIO,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct __initdata omap_gpio_platform_data omap16xx_mpu_gpio_config = {
+	.virtual_irq_start	= IH_MPUIO_BASE,
+	.bank_type		= METHOD_MPUIO,
+	.bank_width		= 16,
+	.bank_stride		= 1,
+};
+
+static struct __initdata platform_device omap16xx_mpu_gpio = {
+	.name           = "omap_gpio",
+	.id             = 0,
+	.dev            = {
+		.platform_data = &omap16xx_mpu_gpio_config,
+	},
+	.num_resources = ARRAY_SIZE(omap16xx_mpu_gpio_resources),
+	.resource = omap16xx_mpu_gpio_resources,
+};
+
+/* gpio1 */
+static struct __initdata resource omap16xx_gpio1_resources[] = {
+	{
+		.start	= OMAP1610_GPIO1_BASE,
+		.end	= OMAP1610_GPIO1_BASE + SZ_2K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.start	= INT_GPIO_BANK1,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct __initdata omap_gpio_platform_data omap16xx_gpio1_config = {
+	.virtual_irq_start	= IH_GPIO_BASE,
+	.bank_type		= METHOD_GPIO_1610,
+	.bank_width		= 16,
+};
+
+static struct __initdata platform_device omap16xx_gpio1 = {
+	.name           = "omap_gpio",
+	.id             = 1,
+	.dev            = {
+		.platform_data = &omap16xx_gpio1_config,
+	},
+	.num_resources = ARRAY_SIZE(omap16xx_gpio1_resources),
+	.resource = omap16xx_gpio1_resources,
+};
+
+/* gpio2 */
+static struct __initdata resource omap16xx_gpio2_resources[] = {
+	{
+		.start	= OMAP1610_GPIO2_BASE,
+		.end	= OMAP1610_GPIO2_BASE + SZ_2K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.start	= INT_1610_GPIO_BANK2,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct __initdata omap_gpio_platform_data omap16xx_gpio2_config = {
+	.virtual_irq_start	= IH_GPIO_BASE + 16,
+	.bank_type		= METHOD_GPIO_1610,
+	.bank_width		= 16,
+};
+
+static struct __initdata platform_device omap16xx_gpio2 = {
+	.name           = "omap_gpio",
+	.id             = 2,
+	.dev            = {
+		.platform_data = &omap16xx_gpio2_config,
+	},
+	.num_resources = ARRAY_SIZE(omap16xx_gpio2_resources),
+	.resource = omap16xx_gpio2_resources,
+};
+
+/* gpio3 */
+static struct __initdata resource omap16xx_gpio3_resources[] = {
+	{
+		.start	= OMAP1610_GPIO3_BASE,
+		.end	= OMAP1610_GPIO3_BASE + SZ_2K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.start	= INT_1610_GPIO_BANK3,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct __initdata omap_gpio_platform_data omap16xx_gpio3_config = {
+	.virtual_irq_start	= IH_GPIO_BASE + 32,
+	.bank_type		= METHOD_GPIO_1610,
+	.bank_width		= 16,
+};
+
+static struct __initdata platform_device omap16xx_gpio3 = {
+	.name           = "omap_gpio",
+	.id             = 3,
+	.dev            = {
+		.platform_data = &omap16xx_gpio3_config,
+	},
+	.num_resources = ARRAY_SIZE(omap16xx_gpio3_resources),
+	.resource = omap16xx_gpio3_resources,
+};
+
+/* gpio4 */
+static struct __initdata resource omap16xx_gpio4_resources[] = {
+	{
+		.start	= OMAP1610_GPIO4_BASE,
+		.end	= OMAP1610_GPIO4_BASE + SZ_2K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.start	= INT_1610_GPIO_BANK4,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct __initdata omap_gpio_platform_data omap16xx_gpio4_config = {
+	.virtual_irq_start	= IH_GPIO_BASE + 48,
+	.bank_type		= METHOD_GPIO_1610,
+	.bank_width		= 16,
+};
+
+static struct __initdata platform_device omap16xx_gpio4 = {
+	.name           = "omap_gpio",
+	.id             = 4,
+	.dev            = {
+		.platform_data = &omap16xx_gpio4_config,
+	},
+	.num_resources = ARRAY_SIZE(omap16xx_gpio4_resources),
+	.resource = omap16xx_gpio4_resources,
+};
+
+static struct __initdata platform_device * omap16xx_gpio_dev[] = {
+	&omap16xx_mpu_gpio,
+	&omap16xx_gpio1,
+	&omap16xx_gpio2,
+	&omap16xx_gpio3,
+	&omap16xx_gpio4,
+};
+
+/*
+ * omap16xx_gpio_init needs to be done before
+ * machine_init functions access gpio APIs.
+ * Hence omap16xx_gpio_init is a postcore_initcall.
+ */
+static int __init omap16xx_gpio_init(void)
+{
+	int i;
+
+	if (!cpu_is_omap16xx())
+		return -EINVAL;
+
+	for (i = 0; i < ARRAY_SIZE(omap16xx_gpio_dev); i++)
+		platform_device_register(omap16xx_gpio_dev[i]);
+
+	gpio_bank_count = ARRAY_SIZE(omap16xx_gpio_dev);
+
+	return 0;
+}
+postcore_initcall(omap16xx_gpio_init);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap1/gpio7xx.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap1/gpio7xx.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap1/gpio7xx.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap1/gpio7xx.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,262 @@
+/*
+ * OMAP7xx specific gpio init
+ *
+ * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Author:
+ *	Charulatha V <charu@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 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/gpio.h>
+
+#define OMAP7XX_GPIO1_BASE		0xfffbc000
+#define OMAP7XX_GPIO2_BASE		0xfffbc800
+#define OMAP7XX_GPIO3_BASE		0xfffbd000
+#define OMAP7XX_GPIO4_BASE		0xfffbd800
+#define OMAP7XX_GPIO5_BASE		0xfffbe000
+#define OMAP7XX_GPIO6_BASE		0xfffbe800
+#define OMAP1_MPUIO_VBASE		OMAP1_MPUIO_BASE
+
+/* mpu gpio */
+static struct __initdata resource omap7xx_mpu_gpio_resources[] = {
+	{
+		.start	= OMAP1_MPUIO_VBASE,
+		.end	= OMAP1_MPUIO_VBASE + SZ_2K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.start	= INT_7XX_MPUIO,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct __initdata omap_gpio_platform_data omap7xx_mpu_gpio_config = {
+	.virtual_irq_start	= IH_MPUIO_BASE,
+	.bank_type		= METHOD_MPUIO,
+	.bank_width		= 32,
+	.bank_stride		= 2,
+};
+
+static struct __initdata platform_device omap7xx_mpu_gpio = {
+	.name           = "omap_gpio",
+	.id             = 0,
+	.dev            = {
+		.platform_data = &omap7xx_mpu_gpio_config,
+	},
+	.num_resources = ARRAY_SIZE(omap7xx_mpu_gpio_resources),
+	.resource = omap7xx_mpu_gpio_resources,
+};
+
+/* gpio1 */
+static struct __initdata resource omap7xx_gpio1_resources[] = {
+	{
+		.start	= OMAP7XX_GPIO1_BASE,
+		.end	= OMAP7XX_GPIO1_BASE + SZ_2K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.start	= INT_7XX_GPIO_BANK1,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct __initdata omap_gpio_platform_data omap7xx_gpio1_config = {
+	.virtual_irq_start	= IH_GPIO_BASE,
+	.bank_type		= METHOD_GPIO_7XX,
+	.bank_width		= 32,
+};
+
+static struct __initdata platform_device omap7xx_gpio1 = {
+	.name           = "omap_gpio",
+	.id             = 1,
+	.dev            = {
+		.platform_data = &omap7xx_gpio1_config,
+	},
+	.num_resources = ARRAY_SIZE(omap7xx_gpio1_resources),
+	.resource = omap7xx_gpio1_resources,
+};
+
+/* gpio2 */
+static struct __initdata resource omap7xx_gpio2_resources[] = {
+	{
+		.start	= OMAP7XX_GPIO2_BASE,
+		.end	= OMAP7XX_GPIO2_BASE + SZ_2K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.start	= INT_7XX_GPIO_BANK2,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct __initdata omap_gpio_platform_data omap7xx_gpio2_config = {
+	.virtual_irq_start	= IH_GPIO_BASE + 32,
+	.bank_type		= METHOD_GPIO_7XX,
+	.bank_width		= 32,
+};
+
+static struct __initdata platform_device omap7xx_gpio2 = {
+	.name           = "omap_gpio",
+	.id             = 2,
+	.dev            = {
+		.platform_data = &omap7xx_gpio2_config,
+	},
+	.num_resources = ARRAY_SIZE(omap7xx_gpio2_resources),
+	.resource = omap7xx_gpio2_resources,
+};
+
+/* gpio3 */
+static struct __initdata resource omap7xx_gpio3_resources[] = {
+	{
+		.start	= OMAP7XX_GPIO3_BASE,
+		.end	= OMAP7XX_GPIO3_BASE + SZ_2K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.start	= INT_7XX_GPIO_BANK3,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct __initdata omap_gpio_platform_data omap7xx_gpio3_config = {
+	.virtual_irq_start	= IH_GPIO_BASE + 64,
+	.bank_type		= METHOD_GPIO_7XX,
+	.bank_width		= 32,
+};
+
+static struct __initdata platform_device omap7xx_gpio3 = {
+	.name           = "omap_gpio",
+	.id             = 3,
+	.dev            = {
+		.platform_data = &omap7xx_gpio3_config,
+	},
+	.num_resources = ARRAY_SIZE(omap7xx_gpio3_resources),
+	.resource = omap7xx_gpio3_resources,
+};
+
+/* gpio4 */
+static struct __initdata resource omap7xx_gpio4_resources[] = {
+	{
+		.start	= OMAP7XX_GPIO4_BASE,
+		.end	= OMAP7XX_GPIO4_BASE + SZ_2K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.start	= INT_7XX_GPIO_BANK4,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct __initdata omap_gpio_platform_data omap7xx_gpio4_config = {
+	.virtual_irq_start	= IH_GPIO_BASE + 96,
+	.bank_type		= METHOD_GPIO_7XX,
+	.bank_width		= 32,
+};
+
+static struct __initdata platform_device omap7xx_gpio4 = {
+	.name           = "omap_gpio",
+	.id             = 4,
+	.dev            = {
+		.platform_data = &omap7xx_gpio4_config,
+	},
+	.num_resources = ARRAY_SIZE(omap7xx_gpio4_resources),
+	.resource = omap7xx_gpio4_resources,
+};
+
+/* gpio5 */
+static struct __initdata resource omap7xx_gpio5_resources[] = {
+	{
+		.start	= OMAP7XX_GPIO5_BASE,
+		.end	= OMAP7XX_GPIO5_BASE + SZ_2K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.start	= INT_7XX_GPIO_BANK5,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct __initdata omap_gpio_platform_data omap7xx_gpio5_config = {
+	.virtual_irq_start	= IH_GPIO_BASE + 128,
+	.bank_type		= METHOD_GPIO_7XX,
+	.bank_width		= 32,
+};
+
+static struct __initdata platform_device omap7xx_gpio5 = {
+	.name           = "omap_gpio",
+	.id             = 5,
+	.dev            = {
+		.platform_data = &omap7xx_gpio5_config,
+	},
+	.num_resources = ARRAY_SIZE(omap7xx_gpio5_resources),
+	.resource = omap7xx_gpio5_resources,
+};
+
+/* gpio6 */
+static struct __initdata resource omap7xx_gpio6_resources[] = {
+	{
+		.start	= OMAP7XX_GPIO6_BASE,
+		.end	= OMAP7XX_GPIO6_BASE + SZ_2K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.start	= INT_7XX_GPIO_BANK6,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct __initdata omap_gpio_platform_data omap7xx_gpio6_config = {
+	.virtual_irq_start	= IH_GPIO_BASE + 160,
+	.bank_type		= METHOD_GPIO_7XX,
+	.bank_width		= 32,
+};
+
+static struct __initdata platform_device omap7xx_gpio6 = {
+	.name           = "omap_gpio",
+	.id             = 6,
+	.dev            = {
+		.platform_data = &omap7xx_gpio6_config,
+	},
+	.num_resources = ARRAY_SIZE(omap7xx_gpio6_resources),
+	.resource = omap7xx_gpio6_resources,
+};
+
+static struct __initdata platform_device * omap7xx_gpio_dev[] = {
+	&omap7xx_mpu_gpio,
+	&omap7xx_gpio1,
+	&omap7xx_gpio2,
+	&omap7xx_gpio3,
+	&omap7xx_gpio4,
+	&omap7xx_gpio5,
+	&omap7xx_gpio6,
+};
+
+/*
+ * omap7xx_gpio_init needs to be done before
+ * machine_init functions access gpio APIs.
+ * Hence omap7xx_gpio_init is a postcore_initcall.
+ */
+static int __init omap7xx_gpio_init(void)
+{
+	int i;
+
+	if (!cpu_is_omap7xx())
+		return -EINVAL;
+
+	for (i = 0; i < ARRAY_SIZE(omap7xx_gpio_dev); i++)
+		platform_device_register(omap7xx_gpio_dev[i]);
+
+	gpio_bank_count = ARRAY_SIZE(omap7xx_gpio_dev);
+
+	return 0;
+}
+postcore_initcall(omap7xx_gpio_init);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap1/include/mach/entry-macro.S linux-libre-2.6.38-gnu1/arch/arm/mach-omap1/include/mach/entry-macro.S
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap1/include/mach/entry-macro.S	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap1/include/mach/entry-macro.S	2011-03-14 21:20:32.000000000 -0400
@@ -14,20 +14,6 @@
 #include <mach/irqs.h>
 #include <asm/hardware/gic.h>
 
-#if (defined(CONFIG_ARCH_OMAP730)||defined(CONFIG_ARCH_OMAP850)) && \
-	(defined(CONFIG_ARCH_OMAP15XX) || defined(CONFIG_ARCH_OMAP16XX))
-#error "FIXME: OMAP7XX doesn't support multiple-OMAP"
-#elif defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
-#define INT_IH2_IRQ		INT_7XX_IH2_IRQ
-#elif defined(CONFIG_ARCH_OMAP15XX)
-#define INT_IH2_IRQ		INT_1510_IH2_IRQ
-#elif defined(CONFIG_ARCH_OMAP16XX)
-#define INT_IH2_IRQ		INT_1610_IH2_IRQ
-#else
-#warning "IH2 IRQ defaulted"
-#define INT_IH2_IRQ		INT_1510_IH2_IRQ
-#endif
-
  		.macro	disable_fiq
 		.endm
 
@@ -47,9 +33,11 @@
 		beq	1510f
 
 		ldr	\irqnr, [\base, #IRQ_SIR_FIQ_REG_OFFSET]
+		ldr	\tmp, =omap_irq_flags	@ irq flags address
+		ldr	\tmp, [\tmp, #0]	@ irq flags value
 		cmp	\irqnr, #0
 		ldreq	\irqnr, [\base, #IRQ_SIR_IRQ_REG_OFFSET]
-		cmpeq	\irqnr, #INT_IH2_IRQ
+		cmpeq	\irqnr, \tmp
 		ldreq	\base, =OMAP1_IO_ADDRESS(OMAP_IH2_BASE)
 		ldreq	\irqnr, [\base, #IRQ_SIR_IRQ_REG_OFFSET]
 		addeqs	\irqnr, \irqnr, #32
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap1/io.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap1/io.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap1/io.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap1/io.c	2011-03-14 21:20:32.000000000 -0400
@@ -142,3 +142,42 @@ void __init omap1_init_common_hw(void)
 	omap1_mux_init();
 }
 
+/*
+ * NOTE: Please use ioremap + __raw_read/write where possible instead of these
+ */
+
+u8 omap_readb(u32 pa)
+{
+	return __raw_readb(OMAP1_IO_ADDRESS(pa));
+}
+EXPORT_SYMBOL(omap_readb);
+
+u16 omap_readw(u32 pa)
+{
+	return __raw_readw(OMAP1_IO_ADDRESS(pa));
+}
+EXPORT_SYMBOL(omap_readw);
+
+u32 omap_readl(u32 pa)
+{
+	return __raw_readl(OMAP1_IO_ADDRESS(pa));
+}
+EXPORT_SYMBOL(omap_readl);
+
+void omap_writeb(u8 v, u32 pa)
+{
+	__raw_writeb(v, OMAP1_IO_ADDRESS(pa));
+}
+EXPORT_SYMBOL(omap_writeb);
+
+void omap_writew(u16 v, u32 pa)
+{
+	__raw_writew(v, OMAP1_IO_ADDRESS(pa));
+}
+EXPORT_SYMBOL(omap_writew);
+
+void omap_writel(u32 v, u32 pa)
+{
+	__raw_writel(v, OMAP1_IO_ADDRESS(pa));
+}
+EXPORT_SYMBOL(omap_writel);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap1/irq.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap1/irq.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap1/irq.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap1/irq.c	2011-03-14 21:20:32.000000000 -0400
@@ -57,6 +57,7 @@ struct omap_irq_bank {
 	unsigned long wake_enable;
 };
 
+u32 omap_irq_flags;
 static unsigned int irq_bank_count;
 static struct omap_irq_bank *irq_banks;
 
@@ -70,48 +71,48 @@ static inline void irq_bank_writel(unsig
 	omap_writel(value, irq_banks[bank].base_reg + offset);
 }
 
-static void omap_ack_irq(unsigned int irq)
+static void omap_ack_irq(struct irq_data *d)
 {
-	if (irq > 31)
+	if (d->irq > 31)
 		omap_writel(0x1, OMAP_IH2_BASE + IRQ_CONTROL_REG_OFFSET);
 
 	omap_writel(0x1, OMAP_IH1_BASE + IRQ_CONTROL_REG_OFFSET);
 }
 
-static void omap_mask_irq(unsigned int irq)
+static void omap_mask_irq(struct irq_data *d)
 {
-	int bank = IRQ_BANK(irq);
+	int bank = IRQ_BANK(d->irq);
 	u32 l;
 
 	l = omap_readl(irq_banks[bank].base_reg + IRQ_MIR_REG_OFFSET);
-	l |= 1 << IRQ_BIT(irq);
+	l |= 1 << IRQ_BIT(d->irq);
 	omap_writel(l, irq_banks[bank].base_reg + IRQ_MIR_REG_OFFSET);
 }
 
-static void omap_unmask_irq(unsigned int irq)
+static void omap_unmask_irq(struct irq_data *d)
 {
-	int bank = IRQ_BANK(irq);
+	int bank = IRQ_BANK(d->irq);
 	u32 l;
 
 	l = omap_readl(irq_banks[bank].base_reg + IRQ_MIR_REG_OFFSET);
-	l &= ~(1 << IRQ_BIT(irq));
+	l &= ~(1 << IRQ_BIT(d->irq));
 	omap_writel(l, irq_banks[bank].base_reg + IRQ_MIR_REG_OFFSET);
 }
 
-static void omap_mask_ack_irq(unsigned int irq)
+static void omap_mask_ack_irq(struct irq_data *d)
 {
-	omap_mask_irq(irq);
-	omap_ack_irq(irq);
+	omap_mask_irq(d);
+	omap_ack_irq(d);
 }
 
-static int omap_wake_irq(unsigned int irq, unsigned int enable)
+static int omap_wake_irq(struct irq_data *d, unsigned int enable)
 {
-	int bank = IRQ_BANK(irq);
+	int bank = IRQ_BANK(d->irq);
 
 	if (enable)
-		irq_banks[bank].wake_enable |= IRQ_BIT(irq);
+		irq_banks[bank].wake_enable |= IRQ_BIT(d->irq);
 	else
-		irq_banks[bank].wake_enable &= ~IRQ_BIT(irq);
+		irq_banks[bank].wake_enable &= ~IRQ_BIT(d->irq);
 
 	return 0;
 }
@@ -168,10 +169,10 @@ static struct omap_irq_bank omap1610_irq
 
 static struct irq_chip omap_irq_chip = {
 	.name		= "MPU",
-	.ack		= omap_mask_ack_irq,
-	.mask		= omap_mask_irq,
-	.unmask		= omap_unmask_irq,
-	.set_wake	= omap_wake_irq,
+	.irq_ack	= omap_mask_ack_irq,
+	.irq_mask	= omap_mask_irq,
+	.irq_unmask	= omap_unmask_irq,
+	.irq_set_wake	= omap_wake_irq,
 };
 
 void __init omap_init_irq(void)
@@ -180,22 +181,26 @@ void __init omap_init_irq(void)
 
 #if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
 	if (cpu_is_omap7xx()) {
+		omap_irq_flags = INT_7XX_IH2_IRQ;
 		irq_banks = omap7xx_irq_banks;
 		irq_bank_count = ARRAY_SIZE(omap7xx_irq_banks);
 	}
 #endif
 #ifdef CONFIG_ARCH_OMAP15XX
 	if (cpu_is_omap1510()) {
+		omap_irq_flags = INT_1510_IH2_IRQ;
 		irq_banks = omap1510_irq_banks;
 		irq_bank_count = ARRAY_SIZE(omap1510_irq_banks);
 	}
 	if (cpu_is_omap310()) {
+		omap_irq_flags = INT_1510_IH2_IRQ;
 		irq_banks = omap310_irq_banks;
 		irq_bank_count = ARRAY_SIZE(omap310_irq_banks);
 	}
 #endif
 #if defined(CONFIG_ARCH_OMAP16XX)
 	if (cpu_is_omap16xx()) {
+		omap_irq_flags = INT_1510_IH2_IRQ;
 		irq_banks = omap1610_irq_banks;
 		irq_bank_count = ARRAY_SIZE(omap1610_irq_banks);
 	}
@@ -234,9 +239,9 @@ void __init omap_init_irq(void)
 	/* Unmask level 2 handler */
 
 	if (cpu_is_omap7xx())
-		omap_unmask_irq(INT_7XX_IH2_IRQ);
+		omap_unmask_irq(irq_get_irq_data(INT_7XX_IH2_IRQ));
 	else if (cpu_is_omap15xx())
-		omap_unmask_irq(INT_1510_IH2_IRQ);
+		omap_unmask_irq(irq_get_irq_data(INT_1510_IH2_IRQ));
 	else if (cpu_is_omap16xx())
-		omap_unmask_irq(INT_1610_IH2_IRQ);
+		omap_unmask_irq(irq_get_irq_data(INT_1610_IH2_IRQ));
 }
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap1/Kconfig linux-libre-2.6.38-gnu1/arch/arm/mach-omap1/Kconfig
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap1/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap1/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -9,6 +9,7 @@ config ARCH_OMAP730
 	depends on ARCH_OMAP1
 	bool "OMAP730 Based System"
 	select CPU_ARM926T
+	select OMAP_MPU_TIMER
 	select ARCH_OMAP_OTG
 
 config ARCH_OMAP850
@@ -22,6 +23,7 @@ config ARCH_OMAP15XX
 	default y
 	bool "OMAP15xx Based System"
 	select CPU_ARM925T
+	select OMAP_MPU_TIMER
 
 config ARCH_OMAP16XX
 	depends on ARCH_OMAP1
@@ -152,20 +154,11 @@ config MACH_NOKIA770
 config MACH_AMS_DELTA
 	bool "Amstrad E3 (Delta)"
 	depends on ARCH_OMAP1 && ARCH_OMAP15XX
+	select FIQ
 	help
 	  Support for the Amstrad E3 (codename Delta) videophone. Say Y here
 	  if you have such a device.
 
-config AMS_DELTA_FIQ
-	bool "Fast Interrupt Request (FIQ) support for the E3"
-	depends on MACH_AMS_DELTA
-	select FIQ
-	help
-	  Provide a FIQ handler for the E3.
-	  This allows for fast handling of interrupts generated
-	  by the clock line of the E3 mailboard (or a PS/2 keyboard)
-	  connected to the GPIO based external keyboard port.
-
 config MACH_OMAP_GENERIC
 	bool "Generic OMAP board"
 	depends on ARCH_OMAP1 && (ARCH_OMAP15XX || ARCH_OMAP16XX)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap1/lcd_dma.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap1/lcd_dma.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap1/lcd_dma.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap1/lcd_dma.c	2011-03-14 21:20:32.000000000 -0400
@@ -37,7 +37,7 @@ int omap_lcd_dma_running(void)
 	 * On OMAP1510, internal LCD controller will start the transfer
 	 * when it gets enabled, so assume DMA running if LCD enabled.
 	 */
-	if (cpu_is_omap1510())
+	if (cpu_is_omap15xx())
 		if (omap_readw(OMAP_LCDC_CONTROL) & OMAP_LCDC_CTRL_LCD_EN)
 			return 1;
 
@@ -95,7 +95,7 @@ EXPORT_SYMBOL(omap_set_lcd_dma_single_tr
 
 void omap_set_lcd_dma_b1_rotation(int rotate)
 {
-	if (cpu_is_omap1510()) {
+	if (cpu_is_omap15xx()) {
 		printk(KERN_ERR "DMA rotation is not supported in 1510 mode\n");
 		BUG();
 		return;
@@ -106,7 +106,7 @@ EXPORT_SYMBOL(omap_set_lcd_dma_b1_rotati
 
 void omap_set_lcd_dma_b1_mirror(int mirror)
 {
-	if (cpu_is_omap1510()) {
+	if (cpu_is_omap15xx()) {
 		printk(KERN_ERR "DMA mirror is not supported in 1510 mode\n");
 		BUG();
 	}
@@ -116,7 +116,7 @@ EXPORT_SYMBOL(omap_set_lcd_dma_b1_mirror
 
 void omap_set_lcd_dma_b1_vxres(unsigned long vxres)
 {
-	if (cpu_is_omap1510()) {
+	if (cpu_is_omap15xx()) {
 		printk(KERN_ERR "DMA virtual resulotion is not supported "
 				"in 1510 mode\n");
 		BUG();
@@ -127,7 +127,7 @@ EXPORT_SYMBOL(omap_set_lcd_dma_b1_vxres)
 
 void omap_set_lcd_dma_b1_scale(unsigned int xscale, unsigned int yscale)
 {
-	if (cpu_is_omap1510()) {
+	if (cpu_is_omap15xx()) {
 		printk(KERN_ERR "DMA scale is not supported in 1510 mode\n");
 		BUG();
 	}
@@ -177,7 +177,7 @@ static void set_b1_regs(void)
 			bottom = PIXADDR(lcd_dma.xres - 1, lcd_dma.yres - 1);
 			/* 1510 DMA requires the bottom address to be 2 more
 			 * than the actual last memory access location. */
-			if (cpu_is_omap1510() &&
+			if (cpu_is_omap15xx() &&
 				lcd_dma.data_type == OMAP_DMA_DATA_TYPE_S32)
 					bottom += 2;
 			ei = PIXSTEP(0, 0, 1, 0);
@@ -241,7 +241,7 @@ static void set_b1_regs(void)
 		return;	/* Suppress warning about uninitialized vars */
 	}
 
-	if (cpu_is_omap1510()) {
+	if (cpu_is_omap15xx()) {
 		omap_writew(top >> 16, OMAP1510_DMA_LCD_TOP_F1_U);
 		omap_writew(top, OMAP1510_DMA_LCD_TOP_F1_L);
 		omap_writew(bottom >> 16, OMAP1510_DMA_LCD_BOT_F1_U);
@@ -343,7 +343,7 @@ void omap_free_lcd_dma(void)
 		BUG();
 		return;
 	}
-	if (!cpu_is_omap1510())
+	if (!cpu_is_omap15xx())
 		omap_writew(omap_readw(OMAP1610_DMA_LCD_CCR) & ~1,
 			    OMAP1610_DMA_LCD_CCR);
 	lcd_dma.reserved = 0;
@@ -360,7 +360,7 @@ void omap_enable_lcd_dma(void)
 	 * connected. Otherwise the OMAP internal controller will
 	 * start the transfer when it gets enabled.
 	 */
-	if (cpu_is_omap1510() || !lcd_dma.ext_ctrl)
+	if (cpu_is_omap15xx() || !lcd_dma.ext_ctrl)
 		return;
 
 	w = omap_readw(OMAP1610_DMA_LCD_CTRL);
@@ -378,14 +378,14 @@ EXPORT_SYMBOL(omap_enable_lcd_dma);
 void omap_setup_lcd_dma(void)
 {
 	BUG_ON(lcd_dma.active);
-	if (!cpu_is_omap1510()) {
+	if (!cpu_is_omap15xx()) {
 		/* Set some reasonable defaults */
 		omap_writew(0x5440, OMAP1610_DMA_LCD_CCR);
 		omap_writew(0x9102, OMAP1610_DMA_LCD_CSDP);
 		omap_writew(0x0004, OMAP1610_DMA_LCD_LCH_CTRL);
 	}
 	set_b1_regs();
-	if (!cpu_is_omap1510()) {
+	if (!cpu_is_omap15xx()) {
 		u16 w;
 
 		w = omap_readw(OMAP1610_DMA_LCD_CCR);
@@ -407,7 +407,7 @@ void omap_stop_lcd_dma(void)
 	u16 w;
 
 	lcd_dma.active = 0;
-	if (cpu_is_omap1510() || !lcd_dma.ext_ctrl)
+	if (cpu_is_omap15xx() || !lcd_dma.ext_ctrl)
 		return;
 
 	w = omap_readw(OMAP1610_DMA_LCD_CCR);
@@ -424,6 +424,9 @@ static int __init omap_init_lcd_dma(void
 {
 	int r;
 
+	if (!cpu_class_is_omap1())
+		return -ENODEV;
+
 	if (cpu_is_omap16xx()) {
 		u16 w;
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap1/leds.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap1/leds.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap1/leds.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap1/leds.c	2011-03-14 21:20:32.000000000 -0400
@@ -17,6 +17,9 @@
 static int __init
 omap_leds_init(void)
 {
+	if (!cpu_class_is_omap1())
+		return -ENODEV;
+
 	if (machine_is_omap_innovator())
 		leds_event = innovator_leds_event;
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap1/mailbox.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap1/mailbox.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap1/mailbox.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap1/mailbox.c	2011-03-14 21:20:32.000000000 -0400
@@ -133,19 +133,18 @@ static struct omap_mbox1_priv omap1_mbox
 	},
 };
 
-struct omap_mbox mbox_dsp_info = {
+static struct omap_mbox mbox_dsp_info = {
 	.name	= "dsp",
 	.ops	= &omap1_mbox_ops,
 	.priv	= &omap1_mbox_dsp_priv,
 };
 
-struct omap_mbox *omap1_mboxes[] = { &mbox_dsp_info, NULL };
+static struct omap_mbox *omap1_mboxes[] = { &mbox_dsp_info, NULL };
 
 static int __devinit omap1_mbox_probe(struct platform_device *pdev)
 {
 	struct resource *mem;
 	int ret;
-	int i;
 	struct omap_mbox **list;
 
 	list = omap1_mboxes;
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap1/Makefile linux-libre-2.6.38-gnu1/arch/arm/mach-omap1/Makefile
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap1/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap1/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -3,12 +3,11 @@
 #
 
 # Common support
-obj-y := io.o id.o sram.o irq.o mux.o flash.o serial.o devices.o
+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
 
 obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o
 
-obj-$(CONFIG_OMAP_MPU_TIMER)	+= time.o
 obj-$(CONFIG_OMAP_32K_TIMER)	+= timer32k.o
 
 # Power Management
@@ -39,8 +38,8 @@ obj-$(CONFIG_MACH_OMAP_PALMTE)		+= board
 obj-$(CONFIG_MACH_OMAP_PALMZ71)		+= board-palmz71.o
 obj-$(CONFIG_MACH_OMAP_PALMTT)		+= board-palmtt.o
 obj-$(CONFIG_MACH_NOKIA770)		+= board-nokia770.o
-obj-$(CONFIG_MACH_AMS_DELTA)		+= board-ams-delta.o
-obj-$(CONFIG_AMS_DELTA_FIQ)		+= ams-delta-fiq.o ams-delta-fiq-handler.o
+obj-$(CONFIG_MACH_AMS_DELTA)		+= board-ams-delta.o ams-delta-fiq.o \
+					   ams-delta-fiq-handler.o
 obj-$(CONFIG_MACH_SX1)			+= board-sx1.o board-sx1-mmc.o
 obj-$(CONFIG_MACH_HERALD)		+= board-htcherald.o
 
@@ -49,6 +48,12 @@ ifeq ($(CONFIG_ARCH_OMAP15XX),y)
 obj-$(CONFIG_MACH_OMAP_INNOVATOR)	+= fpga.o
 endif
 
+# GPIO
+obj-$(CONFIG_ARCH_OMAP730)		+= gpio7xx.o
+obj-$(CONFIG_ARCH_OMAP850)		+= gpio7xx.o
+obj-$(CONFIG_ARCH_OMAP15XX)		+= gpio15xx.o
+obj-$(CONFIG_ARCH_OMAP16XX)		+= gpio16xx.o
+
 # LEDs support
 led-$(CONFIG_MACH_OMAP_H2)		+= leds-h2p2-debug.o
 led-$(CONFIG_MACH_OMAP_H3)		+= leds-h2p2-debug.o
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap1/mcbsp.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap1/mcbsp.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap1/mcbsp.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap1/mcbsp.c	2011-03-14 21:20:32.000000000 -0400
@@ -174,8 +174,11 @@ static struct omap_mcbsp_platform_data o
 #define OMAP16XX_MCBSP_REG_NUM		0
 #endif
 
-int __init omap1_mcbsp_init(void)
+static int __init omap1_mcbsp_init(void)
 {
+	if (!cpu_class_is_omap1())
+		return -ENODEV;
+
 	if (cpu_is_omap7xx()) {
 		omap_mcbsp_count = OMAP7XX_MCBSP_PDATA_SZ;
 		omap_mcbsp_cache_size = OMAP7XX_MCBSP_REG_NUM * sizeof(u16);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap1/mux.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap1/mux.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap1/mux.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap1/mux.c	2011-03-14 21:20:32.000000000 -0400
@@ -343,7 +343,7 @@ MUX_CFG("Y14_1610_CCP_DATAM",	 9,   21,
 #define OMAP1XXX_PINS_SZ	0
 #endif	/* CONFIG_ARCH_OMAP15XX || CONFIG_ARCH_OMAP16XX */
 
-int __init_or_module omap1_cfg_reg(const struct pin_config *cfg)
+static int __init_or_module omap1_cfg_reg(const struct pin_config *cfg)
 {
 	static DEFINE_SPINLOCK(mux_spin_lock);
 	unsigned long flags;
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap1/pm_bus.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap1/pm_bus.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap1/pm_bus.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap1/pm_bus.c	2011-03-14 21:20:32.000000000 -0400
@@ -48,7 +48,6 @@ static int omap1_pm_runtime_suspend(stru
 
 static int omap1_pm_runtime_resume(struct device *dev)
 {
-	int ret = 0;
 	struct clk *iclk, *fclk;
 
 	dev_dbg(dev, "%s\n", __func__);
@@ -73,6 +72,9 @@ static int __init omap1_pm_runtime_init(
 	const struct dev_pm_ops *pm;
 	struct dev_pm_ops *omap_pm;
 
+	if (!cpu_class_is_omap1())
+		return -ENODEV;
+
 	pm = platform_bus_get_pm_ops();
 	if (!pm) {
 		pr_err("%s: unable to get dev_pm_ops from platform_bus\n",
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap1/pm.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap1/pm.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap1/pm.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap1/pm.c	2011-03-14 21:20:32.000000000 -0400
@@ -647,7 +647,7 @@ static struct irqaction omap_wakeup_irq
 
 
 
-static struct platform_suspend_ops omap_pm_ops ={
+static const struct platform_suspend_ops omap_pm_ops = {
 	.prepare	= omap_pm_prepare,
 	.enter		= omap_pm_enter,
 	.finish		= omap_pm_finish,
@@ -661,6 +661,9 @@ static int __init omap_pm_init(void)
 	int error;
 #endif
 
+	if (!cpu_class_is_omap1())
+		return -ENODEV;
+
 	printk("Power Management for TI OMAP.\n");
 
 	/*
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap1/serial.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap1/serial.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap1/serial.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap1/serial.c	2011-03-14 21:20:32.000000000 -0400
@@ -27,6 +27,8 @@
 #include <mach/gpio.h>
 #include <plat/fpga.h>
 
+#include "pm.h"
+
 static struct clk * uart1_ck;
 static struct clk * uart2_ck;
 static struct clk * uart3_ck;
@@ -52,9 +54,11 @@ static inline void omap_serial_outp(stru
  */
 static void __init omap_serial_reset(struct plat_serial8250_port *p)
 {
-	omap_serial_outp(p, UART_OMAP_MDR1, 0x07);	/* disable UART */
+	omap_serial_outp(p, UART_OMAP_MDR1,
+			UART_OMAP_MDR1_DISABLE);	/* disable UART */
 	omap_serial_outp(p, UART_OMAP_SCR, 0x08);	/* TX watermark */
-	omap_serial_outp(p, UART_OMAP_MDR1, 0x00);	/* enable UART */
+	omap_serial_outp(p, UART_OMAP_MDR1,
+			UART_OMAP_MDR1_16X_MODE);	/* enable UART */
 
 	if (!cpu_is_omap15xx()) {
 		omap_serial_outp(p, UART_OMAP_SYSC, 0x01);
@@ -254,6 +258,9 @@ late_initcall(omap_serial_wakeup_init);
 
 static int __init omap_init(void)
 {
+	if (!cpu_class_is_omap1())
+		return -ENODEV;
+
 	return platform_device_register(&serial_device);
 }
 arch_initcall(omap_init);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap1/time.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap1/time.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap1/time.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap1/time.c	2011-03-14 21:20:32.000000000 -0400
@@ -49,9 +49,14 @@
 #include <mach/hardware.h>
 #include <asm/leds.h>
 #include <asm/irq.h>
+#include <asm/sched_clock.h>
+
 #include <asm/mach/irq.h>
 #include <asm/mach/time.h>
 
+#include <plat/common.h>
+
+#ifdef CONFIG_OMAP_MPU_TIMER
 
 #define OMAP_MPU_TIMER_BASE		OMAP_MPU_TIMER1_BASE
 #define OMAP_MPU_TIMER_OFFSET		0x100
@@ -66,7 +71,7 @@ typedef struct {
 ((volatile omap_mpu_timer_regs_t*)OMAP1_IO_ADDRESS(OMAP_MPU_TIMER_BASE +	\
 				 (n)*OMAP_MPU_TIMER_OFFSET))
 
-static inline unsigned long omap_mpu_timer_read(int nr)
+static inline unsigned long notrace omap_mpu_timer_read(int nr)
 {
 	volatile omap_mpu_timer_regs_t* timer = omap_mpu_timer_base(nr);
 	return timer->read_tim;
@@ -208,31 +213,49 @@ static struct clocksource clocksource_mp
 	.rating		= 300,
 	.read		= mpu_read,
 	.mask		= CLOCKSOURCE_MASK(32),
-	.shift		= 24,
 	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
+static DEFINE_CLOCK_DATA(cd);
+
+static inline unsigned long long notrace _omap_mpu_sched_clock(void)
+{
+	u32 cyc = mpu_read(&clocksource_mpu);
+	return cyc_to_sched_clock(&cd, cyc, (u32)~0);
+}
+
+#ifndef CONFIG_OMAP_32K_TIMER
+unsigned long long notrace sched_clock(void)
+{
+	return _omap_mpu_sched_clock();
+}
+#else
+static unsigned long long notrace omap_mpu_sched_clock(void)
+{
+	return _omap_mpu_sched_clock();
+}
+#endif
+
+static void notrace mpu_update_sched_clock(void)
+{
+	u32 cyc = mpu_read(&clocksource_mpu);
+	update_sched_clock(&cd, cyc, (u32)~0);
+}
+
 static void __init omap_init_clocksource(unsigned long rate)
 {
 	static char err[] __initdata = KERN_ERR
 			"%s: can't register clocksource!\n";
 
-	clocksource_mpu.mult
-		= clocksource_khz2mult(rate/1000, clocksource_mpu.shift);
-
 	setup_irq(INT_TIMER2, &omap_mpu_timer2_irq);
 	omap_mpu_timer_start(1, ~0, 1);
+	init_sched_clock(&cd, mpu_update_sched_clock, 32, rate);
 
-	if (clocksource_register(&clocksource_mpu))
+	if (clocksource_register_hz(&clocksource_mpu, rate))
 		printk(err, clocksource_mpu.name);
 }
 
-/*
- * ---------------------------------------------------------------------------
- * Timer initialization
- * ---------------------------------------------------------------------------
- */
-static void __init omap_timer_init(void)
+static void __init omap_mpu_timer_init(void)
 {
 	struct clk	*ck_ref = clk_get(NULL, "ck_ref");
 	unsigned long	rate;
@@ -249,6 +272,66 @@ static void __init omap_timer_init(void)
 	omap_init_clocksource(rate);
 }
 
+#else
+static inline void omap_mpu_timer_init(void)
+{
+	pr_err("Bogus timer, should not happen\n");
+}
+#endif	/* CONFIG_OMAP_MPU_TIMER */
+
+#if defined(CONFIG_OMAP_MPU_TIMER) && defined(CONFIG_OMAP_32K_TIMER)
+static unsigned long long (*preferred_sched_clock)(void);
+
+unsigned long long notrace sched_clock(void)
+{
+	if (!preferred_sched_clock)
+		return 0;
+
+	return preferred_sched_clock();
+}
+
+static inline void preferred_sched_clock_init(bool use_32k_sched_clock)
+{
+	if (use_32k_sched_clock)
+		preferred_sched_clock = omap_32k_sched_clock;
+	else
+		preferred_sched_clock = omap_mpu_sched_clock;
+}
+#else
+static inline void preferred_sched_clock_init(bool use_32k_sched_clcok)
+{
+}
+#endif
+
+static inline int omap_32k_timer_usable(void)
+{
+	int res = false;
+
+	if (cpu_is_omap730() || cpu_is_omap15xx())
+		return res;
+
+#ifdef CONFIG_OMAP_32K_TIMER
+	res = omap_32k_timer_init();
+#endif
+
+	return res;
+}
+
+/*
+ * ---------------------------------------------------------------------------
+ * Timer initialization
+ * ---------------------------------------------------------------------------
+ */
+static void __init omap_timer_init(void)
+{
+	if (omap_32k_timer_usable()) {
+		preferred_sched_clock_init(1);
+	} else {
+		omap_mpu_timer_init();
+		preferred_sched_clock_init(0);
+	}
+}
+
 struct sys_timer omap_timer = {
 	.init		= omap_timer_init,
 };
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap1/timer32k.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap1/timer32k.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap1/timer32k.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap1/timer32k.c	2011-03-14 21:20:32.000000000 -0400
@@ -52,10 +52,9 @@
 #include <asm/irq.h>
 #include <asm/mach/irq.h>
 #include <asm/mach/time.h>
+#include <plat/common.h>
 #include <plat/dmtimer.h>
 
-struct sys_timer omap_timer;
-
 /*
  * ---------------------------------------------------------------------------
  * 32KHz OS timer
@@ -181,14 +180,14 @@ static __init void omap_init_32k_timer(v
  * Timer initialization
  * ---------------------------------------------------------------------------
  */
-static void __init omap_timer_init(void)
+bool __init omap_32k_timer_init(void)
 {
+	omap_init_clocksource_32k();
+
 #ifdef CONFIG_OMAP_DM_TIMER
 	omap_dm_timer_init();
 #endif
 	omap_init_32k_timer();
-}
 
-struct sys_timer omap_timer = {
-	.init		= omap_timer_init,
-};
+	return true;
+}
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/board-2430sdp.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/board-2430sdp.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/board-2430sdp.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/board-2430sdp.c	2011-03-14 21:20:32.000000000 -0400
@@ -135,7 +135,7 @@ static inline void board_smc91x_init(voi
 
 #endif
 
-static struct omap_board_config_kernel sdp2430_config[] = {
+static struct omap_board_config_kernel sdp2430_config[] __initdata = {
 	{OMAP_TAG_LCD, &sdp2430_lcd_config},
 };
 
@@ -143,9 +143,9 @@ static void __init omap_2430sdp_init_irq
 {
 	omap_board_config = sdp2430_config;
 	omap_board_config_size = ARRAY_SIZE(sdp2430_config);
-	omap2_init_common_hw(NULL, NULL);
+	omap2_init_common_infrastructure();
+	omap2_init_common_devices(NULL, NULL);
 	omap_init_irq();
-	omap_gpio_init();
 }
 
 static struct twl4030_gpio_platform_data sdp2430_gpio_data = {
@@ -218,8 +218,6 @@ static struct omap_usb_config sdp2430_us
 static struct omap_board_mux board_mux[] __initdata = {
 	{ .reg_offset = OMAP_MUX_TERMINATOR },
 };
-#else
-#define board_mux	NULL
 #endif
 
 static void __init omap_2430sdp_init(void)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/board-3430sdp.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/board-3430sdp.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/board-3430sdp.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/board-3430sdp.c	2011-03-14 21:20:32.000000000 -0400
@@ -38,6 +38,7 @@
 #include <plat/dma.h>
 #include <plat/gpmc.h>
 #include <plat/display.h>
+#include <plat/panel-generic-dpi.h>
 
 #include <plat/gpmc-smc91x.h>
 
@@ -270,13 +271,18 @@ static struct omap_dss_device sdp3430_lc
 	.platform_disable	= sdp3430_panel_disable_lcd,
 };
 
+static struct panel_generic_dpi_data dvi_panel = {
+	.name			= "generic",
+	.platform_enable	= sdp3430_panel_enable_dvi,
+	.platform_disable	= sdp3430_panel_disable_dvi,
+};
+
 static struct omap_dss_device sdp3430_dvi_device = {
 	.name			= "dvi",
-	.driver_name		= "generic_panel",
 	.type			= OMAP_DISPLAY_TYPE_DPI,
+	.driver_name		= "generic_dpi_panel",
+	.data			= &dvi_panel,
 	.phy.dpi.data_lines	= 24,
-	.platform_enable	= sdp3430_panel_enable_dvi,
-	.platform_disable	= sdp3430_panel_disable_dvi,
 };
 
 static struct omap_dss_device sdp3430_tv_device = {
@@ -326,9 +332,9 @@ static void __init omap_3430sdp_init_irq
 	omap_board_config = sdp3430_config;
 	omap_board_config_size = ARRAY_SIZE(sdp3430_config);
 	omap3_pm_init_cpuidle(omap3_cpuidle_params_table);
-	omap2_init_common_hw(hyb18m512160af6_sdrc_params, NULL);
+	omap2_init_common_infrastructure();
+	omap2_init_common_devices(hyb18m512160af6_sdrc_params, NULL);
 	omap_init_irq();
-	omap_gpio_init();
 }
 
 static int sdp3430_batt_table[] = {
@@ -663,8 +669,6 @@ static const struct ehci_hcd_omap_platfo
 static struct omap_board_mux board_mux[] __initdata = {
 	{ .reg_offset = OMAP_MUX_TERMINATOR },
 };
-#else
-#define board_mux	NULL
 #endif
 
 /*
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/board-3630sdp.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/board-3630sdp.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/board-3630sdp.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/board-3630sdp.c	2011-03-14 21:20:32.000000000 -0400
@@ -73,18 +73,16 @@ static void __init omap_sdp_init_irq(voi
 {
 	omap_board_config = sdp_config;
 	omap_board_config_size = ARRAY_SIZE(sdp_config);
-	omap2_init_common_hw(h8mbx00u0mer0em_sdrc_params,
-			h8mbx00u0mer0em_sdrc_params);
+	omap2_init_common_infrastructure();
+	omap2_init_common_devices(h8mbx00u0mer0em_sdrc_params,
+				  h8mbx00u0mer0em_sdrc_params);
 	omap_init_irq();
-	omap_gpio_init();
 }
 
 #ifdef CONFIG_OMAP_MUX
 static struct omap_board_mux board_mux[] __initdata = {
 	{ .reg_offset = OMAP_MUX_TERMINATOR },
 };
-#else
-#define board_mux	NULL
 #endif
 
 /*
@@ -209,6 +207,7 @@ static void __init omap_sdp_init(void)
 {
 	omap3_mux_init(board_mux, OMAP_PACKAGE_CBP);
 	zoom_peripherals_init();
+	zoom_display_init();
 	board_smc91x_init();
 	board_flash_init(sdp_flash_partitions, chip_sel_sdp);
 	enable_board_wakeup_source();
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/board-4430sdp.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/board-4430sdp.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/board-4430sdp.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/board-4430sdp.c	2011-03-14 21:20:32.000000000 -0400
@@ -23,6 +23,7 @@
 #include <linux/gpio_keys.h>
 #include <linux/regulator/machine.h>
 #include <linux/leds.h>
+#include <linux/leds_pwm.h>
 
 #include <mach/hardware.h>
 #include <mach/omap4-common.h>
@@ -35,6 +36,7 @@
 #include <plat/usb.h>
 #include <plat/mmc.h>
 
+#include "mux.h"
 #include "hsmmc.h"
 #include "timer-gp.h"
 #include "control.h"
@@ -42,6 +44,7 @@
 #define ETH_KS8851_IRQ			34
 #define ETH_KS8851_POWER_ON		48
 #define ETH_KS8851_QUART		138
+#define OMAP4SDP_MDM_PWR_EN_GPIO	157
 #define OMAP4_SFH7741_SENSOR_OUTPUT_GPIO	184
 #define OMAP4_SFH7741_ENABLE_GPIO		188
 
@@ -96,6 +99,28 @@ static struct gpio_led_platform_data sdp
 	.num_leds	= ARRAY_SIZE(sdp4430_gpio_leds),
 };
 
+static struct led_pwm sdp4430_pwm_leds[] = {
+	{
+		.name		= "omap4:green:chrg",
+		.pwm_id		= 1,
+		.max_brightness	= 255,
+		.pwm_period_ns	= 7812500,
+	},
+};
+
+static struct led_pwm_platform_data sdp4430_pwm_data = {
+	.num_leds	= ARRAY_SIZE(sdp4430_pwm_leds),
+	.leds		= sdp4430_pwm_leds,
+};
+
+static struct platform_device sdp4430_leds_pwm = {
+	.name	= "leds_pwm",
+	.id	= -1,
+	.dev	= {
+		.platform_data = &sdp4430_pwm_data,
+	},
+};
+
 static int omap_prox_activate(struct device *dev)
 {
 	gpio_set_value(OMAP4_SFH7741_ENABLE_GPIO , 1);
@@ -203,6 +228,7 @@ static struct platform_device *sdp4430_d
 	&sdp4430_lcd_device,
 	&sdp4430_gpio_keys_device,
 	&sdp4430_leds_gpio,
+	&sdp4430_leds_pwm,
 };
 
 static struct omap_lcd_config sdp4430_lcd_config __initdata = {
@@ -217,20 +243,37 @@ static void __init omap_4430sdp_init_irq
 {
 	omap_board_config = sdp4430_config;
 	omap_board_config_size = ARRAY_SIZE(sdp4430_config);
-	omap2_init_common_hw(NULL, NULL);
+	omap2_init_common_infrastructure();
+	omap2_init_common_devices(NULL, NULL);
 #ifdef CONFIG_OMAP_32K_TIMER
 	omap2_gp_clockevent_set_gptimer(1);
 #endif
 	gic_init_irq();
-	omap_gpio_init();
 }
 
+static const struct ehci_hcd_omap_platform_data ehci_pdata __initconst = {
+	.port_mode[0]	= EHCI_HCD_OMAP_MODE_PHY,
+	.port_mode[1]	= EHCI_HCD_OMAP_MODE_UNKNOWN,
+	.port_mode[2]	= EHCI_HCD_OMAP_MODE_UNKNOWN,
+	.phy_reset	= false,
+	.reset_gpio_port[0]  = -EINVAL,
+	.reset_gpio_port[1]  = -EINVAL,
+	.reset_gpio_port[2]  = -EINVAL,
+};
+
 static struct omap_musb_board_data musb_board_data = {
 	.interface_type		= MUSB_INTERFACE_UTMI,
-	.mode			= MUSB_PERIPHERAL,
+	.mode			= MUSB_OTG,
 	.power			= 100,
 };
 
+static struct twl4030_usb_data omap4_usbphy_data = {
+	.phy_init	= omap4430_phy_init,
+	.phy_exit	= omap4430_phy_exit,
+	.phy_power	= omap4430_phy_power,
+	.phy_set_clock	= omap4430_phy_set_clk,
+};
+
 static struct omap2_hsmmc_info mmc[] = {
 	{
 		.mmc		= 1,
@@ -450,6 +493,7 @@ static struct twl4030_platform_data sdp4
 	.vaux1		= &sdp4430_vaux1,
 	.vaux2		= &sdp4430_vaux2,
 	.vaux3		= &sdp4430_vaux3,
+	.usb		= &omap4_usbphy_data
 };
 
 static struct i2c_board_info __initdata sdp4430_i2c_boardinfo[] = {
@@ -464,6 +508,9 @@ static struct i2c_board_info __initdata
 	{
 		I2C_BOARD_INFO("tmp105", 0x48),
 	},
+	{
+		I2C_BOARD_INFO("bh1780", 0x29),
+	},
 };
 static struct i2c_board_info __initdata sdp4430_i2c_4_boardinfo[] = {
 	{
@@ -505,20 +552,39 @@ static void __init omap_sfh7741prox_init
 	}
 }
 
+#ifdef CONFIG_OMAP_MUX
+static struct omap_board_mux board_mux[] __initdata = {
+	OMAP4_MUX(USBB2_ULPITLL_CLK, OMAP_MUX_MODE4 | OMAP_PIN_OUTPUT),
+	{ .reg_offset = OMAP_MUX_TERMINATOR },
+};
+#else
+#define board_mux	NULL
+#endif
+
 static void __init omap_4430sdp_init(void)
 {
 	int status;
+	int package = OMAP_PACKAGE_CBS;
+
+	if (omap_rev() == OMAP4430_REV_ES1_0)
+		package = OMAP_PACKAGE_CBL;
+	omap4_mux_init(board_mux, package);
 
 	omap4_i2c_init();
 	omap_sfh7741prox_init();
 	platform_add_devices(sdp4430_devices, ARRAY_SIZE(sdp4430_devices));
 	omap_serial_init();
 	omap4_twl6030_hsmmc_init(mmc);
-	/* OMAP4 SDP uses internal transceiver so register nop transceiver */
-	usb_nop_xceiv_register();
-	/* FIXME: allow multi-omap to boot until musb is updated for omap4 */
-	if (!cpu_is_omap44xx())
-		usb_musb_init(&musb_board_data);
+
+	/* Power on the ULPI PHY */
+	status = gpio_request(OMAP4SDP_MDM_PWR_EN_GPIO, "USBB1 PHY VMDM_3V3");
+	if (status)
+		pr_err("%s: Could not get USBB1 PHY GPIO\n", __func__);
+	else
+		gpio_direction_output(OMAP4SDP_MDM_PWR_EN_GPIO, 1);
+
+	usb_ehci_init(&ehci_pdata);
+	usb_musb_init(&musb_board_data);
 
 	status = omap_ethernet_init();
 	if (status) {
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/board-am3517crane.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/board-am3517crane.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/board-am3517crane.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/board-am3517crane.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,116 @@
+/*
+ * Support for AM3517/05 Craneboard
+ * http://www.mistralsolutions.com/products/craneboard.php
+ *
+ * Copyright (C) 2010 Mistral Solutions Pvt Ltd. <www.mistralsolutions.com>
+ * Author: R.Srinath <srinath@mistralsolutions.com>
+ *
+ * Based on mach-omap2/board-am3517evm.c
+ *
+ * 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/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+#include <plat/board.h>
+#include <plat/common.h>
+#include <plat/usb.h>
+
+#include "mux.h"
+#include "control.h"
+
+#define GPIO_USB_POWER		35
+#define GPIO_USB_NRESET		38
+
+
+/* Board initialization */
+static struct omap_board_config_kernel am3517_crane_config[] __initdata = {
+};
+
+#ifdef CONFIG_OMAP_MUX
+static struct omap_board_mux board_mux[] __initdata = {
+	{ .reg_offset = OMAP_MUX_TERMINATOR },
+};
+#else
+#define board_mux	NULL
+#endif
+
+static void __init am3517_crane_init_irq(void)
+{
+	omap_board_config = am3517_crane_config;
+	omap_board_config_size = ARRAY_SIZE(am3517_crane_config);
+
+	omap2_init_common_infrastructure();
+	omap2_init_common_devices(NULL, NULL);
+	omap_init_irq();
+}
+
+static struct ehci_hcd_omap_platform_data ehci_pdata __initdata = {
+	.port_mode[0] = EHCI_HCD_OMAP_MODE_PHY,
+	.port_mode[1] = EHCI_HCD_OMAP_MODE_UNKNOWN,
+	.port_mode[2] = EHCI_HCD_OMAP_MODE_UNKNOWN,
+
+	.phy_reset  = true,
+	.reset_gpio_port[0]  = GPIO_USB_NRESET,
+	.reset_gpio_port[1]  = -EINVAL,
+	.reset_gpio_port[2]  = -EINVAL
+};
+
+static void __init am3517_crane_init(void)
+{
+	int ret;
+
+	omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
+	omap_serial_init();
+
+	/* Configure GPIO for EHCI port */
+	if (omap_mux_init_gpio(GPIO_USB_NRESET, OMAP_PIN_OUTPUT)) {
+		pr_err("Can not configure mux for GPIO_USB_NRESET %d\n",
+			GPIO_USB_NRESET);
+		return;
+	}
+
+	if (omap_mux_init_gpio(GPIO_USB_POWER, OMAP_PIN_OUTPUT)) {
+		pr_err("Can not configure mux for GPIO_USB_POWER %d\n",
+			GPIO_USB_POWER);
+		return;
+	}
+
+	ret = gpio_request(GPIO_USB_POWER, "usb_ehci_enable");
+	if (ret < 0) {
+		pr_err("Can not request GPIO %d\n", GPIO_USB_POWER);
+		return;
+	}
+
+	ret = gpio_direction_output(GPIO_USB_POWER, 1);
+	if (ret < 0) {
+		gpio_free(GPIO_USB_POWER);
+		pr_err("Unable to initialize EHCI power\n");
+		return;
+	}
+
+	usb_ehci_init(&ehci_pdata);
+}
+
+MACHINE_START(CRANEBOARD, "AM3517/05 CRANEBOARD")
+	.boot_params	= 0x80000100,
+	.map_io		= omap3_map_io,
+	.reserve	= omap_reserve,
+	.init_irq	= am3517_crane_init_irq,
+	.init_machine	= am3517_crane_init,
+	.timer		= &omap_timer,
+MACHINE_END
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/board-am3517evm.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/board-am3517evm.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/board-am3517evm.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/board-am3517evm.c	2011-03-14 21:20:32.000000000 -0400
@@ -35,6 +35,7 @@
 #include <plat/common.h>
 #include <plat/usb.h>
 #include <plat/display.h>
+#include <plat/panel-generic-dpi.h>
 
 #include "mux.h"
 #include "control.h"
@@ -303,13 +304,18 @@ static void am3517_evm_panel_disable_lcd
 	lcd_enabled = 0;
 }
 
+static struct panel_generic_dpi_data lcd_panel = {
+	.name			= "sharp_lq",
+	.platform_enable	= am3517_evm_panel_enable_lcd,
+	.platform_disable	= am3517_evm_panel_disable_lcd,
+};
+
 static struct omap_dss_device am3517_evm_lcd_device = {
 	.type			= OMAP_DISPLAY_TYPE_DPI,
 	.name			= "lcd",
-	.driver_name		= "sharp_lq_panel",
+	.driver_name		= "generic_dpi_panel",
+	.data			= &lcd_panel,
 	.phy.dpi.data_lines 	= 16,
-	.platform_enable	= am3517_evm_panel_enable_lcd,
-	.platform_disable	= am3517_evm_panel_disable_lcd,
 };
 
 static int am3517_evm_panel_enable_tv(struct omap_dss_device *dssdev)
@@ -346,13 +352,18 @@ static void am3517_evm_panel_disable_dvi
 	dvi_enabled = 0;
 }
 
+static struct panel_generic_dpi_data dvi_panel = {
+	.name			= "generic",
+	.platform_enable	= am3517_evm_panel_enable_dvi,
+	.platform_disable	= am3517_evm_panel_disable_dvi,
+};
+
 static struct omap_dss_device am3517_evm_dvi_device = {
 	.type			= OMAP_DISPLAY_TYPE_DPI,
 	.name			= "dvi",
-	.driver_name		= "generic_panel",
+	.driver_name		= "generic_dpi_panel",
+	.data			= &dvi_panel,
 	.phy.dpi.data_lines	= 24,
-	.platform_enable	= am3517_evm_panel_enable_dvi,
-	.platform_disable	= am3517_evm_panel_disable_dvi,
 };
 
 static struct omap_dss_device *am3517_evm_dss_devices[] = {
@@ -389,10 +400,9 @@ static void __init am3517_evm_init_irq(v
 {
 	omap_board_config = am3517_evm_config;
 	omap_board_config_size = ARRAY_SIZE(am3517_evm_config);
-
-	omap2_init_common_hw(NULL, NULL);
+	omap2_init_common_infrastructure();
+	omap2_init_common_devices(NULL, NULL);
 	omap_init_irq();
-	omap_gpio_init();
 }
 
 static struct omap_musb_board_data musb_board_data = {
@@ -442,8 +452,6 @@ static struct omap_board_mux board_mux[]
 	OMAP3_MUX(SAD2D_MCAD23, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLDOWN),
 	{ .reg_offset = OMAP_MUX_TERMINATOR },
 };
-#else
-#define board_mux	NULL
 #endif
 
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/board-apollon.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/board-apollon.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/board-apollon.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/board-apollon.c	2011-03-14 21:20:32.000000000 -0400
@@ -270,7 +270,7 @@ static struct omap_lcd_config apollon_lc
 	.ctrl_name	= "internal",
 };
 
-static struct omap_board_config_kernel apollon_config[] = {
+static struct omap_board_config_kernel apollon_config[] __initdata = {
 	{ OMAP_TAG_LCD,		&apollon_lcd_config },
 };
 
@@ -278,10 +278,9 @@ static void __init omap_apollon_init_irq
 {
 	omap_board_config = apollon_config;
 	omap_board_config_size = ARRAY_SIZE(apollon_config);
-	omap2_init_common_hw(NULL, NULL);
+	omap2_init_common_infrastructure();
+	omap2_init_common_devices(NULL, NULL);
 	omap_init_irq();
-	omap_gpio_init();
-	apollon_init_smc91x();
 }
 
 static void __init apollon_led_init(void)
@@ -314,8 +313,6 @@ static void __init apollon_usb_init(void
 static struct omap_board_mux board_mux[] __initdata = {
 	{ .reg_offset = OMAP_MUX_TERMINATOR },
 };
-#else
-#define board_mux	NULL
 #endif
 
 static void __init omap_apollon_init(void)
@@ -324,6 +321,7 @@ static void __init omap_apollon_init(voi
 
 	omap2420_mux_init(board_mux, OMAP_PACKAGE_ZAC);
 
+	apollon_init_smc91x();
 	apollon_led_init();
 	apollon_flash_init();
 	apollon_usb_init();
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/board-cm-t3517.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/board-cm-t3517.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/board-cm-t3517.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/board-cm-t3517.c	2011-03-14 21:20:32.000000000 -0400
@@ -124,8 +124,9 @@ static inline void cm_t3517_init_hecc(vo
 #if defined(CONFIG_RTC_DRV_V3020) || defined(CONFIG_RTC_DRV_V3020_MODULE)
 #define RTC_IO_GPIO		(153)
 #define RTC_WR_GPIO		(154)
-#define RTC_RD_GPIO		(160)
+#define RTC_RD_GPIO		(53)
 #define RTC_CS_GPIO		(163)
+#define RTC_CS_EN_GPIO		(160)
 
 struct v3020_platform_data cm_t3517_v3020_pdata = {
 	.use_gpio	= 1,
@@ -145,6 +146,16 @@ static struct platform_device cm_t3517_r
 
 static void __init cm_t3517_init_rtc(void)
 {
+	int err;
+
+	err = gpio_request(RTC_CS_EN_GPIO, "rtc cs en");
+	if (err) {
+		pr_err("CM-T3517: rtc cs en gpio request failed: %d\n", err);
+		return;
+	}
+
+	gpio_direction_output(RTC_CS_EN_GPIO, 1);
+
 	platform_device_register(&cm_t3517_rtc_device);
 }
 #else
@@ -214,12 +225,12 @@ static struct mtd_partition cm_t3517_nan
 	},
 	{
 		.name           = "linux",
-		.offset         = MTDPART_OFS_APPEND,	/* Offset = 0x280000 */
+		.offset         = MTDPART_OFS_APPEND,	/* Offset = 0x2A0000 */
 		.size           = 32 * NAND_BLOCK_SIZE,
 	},
 	{
 		.name           = "rootfs",
-		.offset         = MTDPART_OFS_APPEND,	/* Offset = 0x680000 */
+		.offset         = MTDPART_OFS_APPEND,	/* Offset = 0x6A0000 */
 		.size           = MTDPART_SIZ_FULL,
 	},
 };
@@ -248,19 +259,27 @@ static void __init cm_t3517_init_irq(voi
 	omap_board_config = cm_t3517_config;
 	omap_board_config_size = ARRAY_SIZE(cm_t3517_config);
 
-	omap2_init_common_hw(NULL, NULL);
+	omap2_init_common_infrastructure();
+	omap2_init_common_devices(NULL, NULL);
 	omap_init_irq();
-	omap_gpio_init();
 }
 
 static struct omap_board_mux board_mux[] __initdata = {
 	/* GPIO186 - Green LED */
 	OMAP3_MUX(SYS_CLKOUT2, OMAP_MUX_MODE4 | OMAP_PIN_OUTPUT),
-	/* RTC GPIOs: IO, WR#, RD#, CS# */
+
+	/* RTC GPIOs: */
+	/* IO - GPIO153 */
 	OMAP3_MUX(MCBSP4_DR, OMAP_MUX_MODE4 | OMAP_PIN_INPUT),
+	/* WR# - GPIO154 */
 	OMAP3_MUX(MCBSP4_DX, OMAP_MUX_MODE4 | OMAP_PIN_INPUT),
-	OMAP3_MUX(MCBSP_CLKS, OMAP_MUX_MODE4 | OMAP_PIN_INPUT),
+	/* RD# - GPIO53 */
+	OMAP3_MUX(GPMC_NCS2, OMAP_MUX_MODE4 | OMAP_PIN_INPUT),
+	/* CS# - GPIO163 */
 	OMAP3_MUX(UART3_CTS_RCTX, OMAP_MUX_MODE4 | OMAP_PIN_INPUT),
+	/* CS EN - GPIO160 */
+	OMAP3_MUX(MCBSP_CLKS, OMAP_MUX_MODE4 | OMAP_PIN_INPUT),
+
 	/* HSUSB1 RESET */
 	OMAP3_MUX(UART2_TX, OMAP_MUX_MODE4 | OMAP_PIN_OUTPUT),
 	/* HSUSB2 RESET */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/board-cm-t35.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/board-cm-t35.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/board-cm-t35.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/board-cm-t35.c	2011-03-14 21:20:32.000000000 -0400
@@ -46,6 +46,7 @@
 #include <plat/gpmc.h>
 #include <plat/usb.h>
 #include <plat/display.h>
+#include <plat/panel-generic-dpi.h>
 #include <plat/mcspi.h>
 
 #include <mach/hardware.h>
@@ -351,22 +352,32 @@ static void cm_t35_panel_disable_tv(stru
 {
 }
 
+static struct panel_generic_dpi_data lcd_panel = {
+	.name			= "toppoly_tdo35s",
+	.platform_enable	= cm_t35_panel_enable_lcd,
+	.platform_disable	= cm_t35_panel_disable_lcd,
+};
+
 static struct omap_dss_device cm_t35_lcd_device = {
 	.name			= "lcd",
-	.driver_name		= "toppoly_tdo35s_panel",
 	.type			= OMAP_DISPLAY_TYPE_DPI,
+	.driver_name		= "generic_dpi_panel",
+	.data			= &lcd_panel,
 	.phy.dpi.data_lines	= 18,
-	.platform_enable	= cm_t35_panel_enable_lcd,
-	.platform_disable	= cm_t35_panel_disable_lcd,
+};
+
+static struct panel_generic_dpi_data dvi_panel = {
+	.name			= "generic",
+	.platform_enable	= cm_t35_panel_enable_dvi,
+	.platform_disable	= cm_t35_panel_disable_dvi,
 };
 
 static struct omap_dss_device cm_t35_dvi_device = {
 	.name			= "dvi",
-	.driver_name		= "generic_panel",
 	.type			= OMAP_DISPLAY_TYPE_DPI,
+	.driver_name		= "generic_dpi_panel",
+	.data			= &dvi_panel,
 	.phy.dpi.data_lines	= 24,
-	.platform_enable	= cm_t35_panel_enable_dvi,
-	.platform_disable	= cm_t35_panel_disable_dvi,
 };
 
 static struct omap_dss_device cm_t35_tv_device = {
@@ -600,8 +611,8 @@ static struct ehci_hcd_omap_platform_dat
 	.port_mode[2] = EHCI_HCD_OMAP_MODE_UNKNOWN,
 
 	.phy_reset  = true,
-	.reset_gpio_port[0]  = -EINVAL,
-	.reset_gpio_port[1]  = -EINVAL,
+	.reset_gpio_port[0]  = OMAP_MAX_GPIO_LINES + 6,
+	.reset_gpio_port[1]  = OMAP_MAX_GPIO_LINES + 7,
 	.reset_gpio_port[2]  = -EINVAL
 };
 
@@ -630,12 +641,6 @@ static int cm_t35_twl_gpio_setup(struct
 	cm_t35_vmmc1_supply.dev = mmc[0].dev;
 	cm_t35_vsim_supply.dev = mmc[0].dev;
 
-	/* setup USB with proper PHY reset GPIOs */
-	ehci_pdata.reset_gpio_port[0] = gpio + 6;
-	ehci_pdata.reset_gpio_port[1] = gpio + 7;
-
-	usb_ehci_init(&ehci_pdata);
-
 	return 0;
 }
 
@@ -683,10 +688,10 @@ static void __init cm_t35_init_irq(void)
 	omap_board_config = cm_t35_config;
 	omap_board_config_size = ARRAY_SIZE(cm_t35_config);
 
-	omap2_init_common_hw(mt46h32m32lf6_sdrc_params,
+	omap2_init_common_infrastructure();
+	omap2_init_common_devices(mt46h32m32lf6_sdrc_params,
 			     mt46h32m32lf6_sdrc_params);
 	omap_init_irq();
-	omap_gpio_init();
 }
 
 static struct omap_board_mux board_mux[] __initdata = {
@@ -805,6 +810,7 @@ static void __init cm_t35_init(void)
 	cm_t35_init_display();
 
 	usb_musb_init(&musb_board_data);
+	usb_ehci_init(&ehci_pdata);
 }
 
 MACHINE_START(CM_T35, "Compulab CM-T35")
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/board-devkit8000.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/board-devkit8000.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/board-devkit8000.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/board-devkit8000.c	2011-03-14 21:20:32.000000000 -0400
@@ -46,6 +46,7 @@
 #include <plat/nand.h>
 #include <plat/usb.h>
 #include <plat/display.h>
+#include <plat/panel-generic-dpi.h>
 
 #include <plat/mcspi.h>
 #include <linux/input/matrix_keypad.h>
@@ -114,31 +115,28 @@ static struct omap2_hsmmc_info mmc[] = {
 
 static int devkit8000_panel_enable_lcd(struct omap_dss_device *dssdev)
 {
-	twl_i2c_write_u8(TWL4030_MODULE_GPIO, 0x80, REG_GPIODATADIR1);
-	twl_i2c_write_u8(TWL4030_MODULE_LED, 0x0, 0x0);
-
 	if (gpio_is_valid(dssdev->reset_gpio))
-		gpio_set_value(dssdev->reset_gpio, 1);
+		gpio_set_value_cansleep(dssdev->reset_gpio, 1);
 	return 0;
 }
 
 static void devkit8000_panel_disable_lcd(struct omap_dss_device *dssdev)
 {
 	if (gpio_is_valid(dssdev->reset_gpio))
-		gpio_set_value(dssdev->reset_gpio, 0);
+		gpio_set_value_cansleep(dssdev->reset_gpio, 0);
 }
 
 static int devkit8000_panel_enable_dvi(struct omap_dss_device *dssdev)
 {
 	if (gpio_is_valid(dssdev->reset_gpio))
-		gpio_set_value(dssdev->reset_gpio, 1);
+		gpio_set_value_cansleep(dssdev->reset_gpio, 1);
 	return 0;
 }
 
 static void devkit8000_panel_disable_dvi(struct omap_dss_device *dssdev)
 {
 	if (gpio_is_valid(dssdev->reset_gpio))
-		gpio_set_value(dssdev->reset_gpio, 0);
+		gpio_set_value_cansleep(dssdev->reset_gpio, 0);
 }
 
 static struct regulator_consumer_supply devkit8000_vmmc1_supply =
@@ -149,23 +147,32 @@ static struct regulator_consumer_supply
 static struct regulator_consumer_supply devkit8000_vio_supply =
 	REGULATOR_SUPPLY("vcc", "spi2.0");
 
+static struct panel_generic_dpi_data lcd_panel = {
+	.name			= "generic",
+	.platform_enable        = devkit8000_panel_enable_lcd,
+	.platform_disable       = devkit8000_panel_disable_lcd,
+};
+
 static struct omap_dss_device devkit8000_lcd_device = {
 	.name                   = "lcd",
-	.driver_name            = "generic_panel",
 	.type                   = OMAP_DISPLAY_TYPE_DPI,
+	.driver_name            = "generic_dpi_panel",
+	.data			= &lcd_panel,
 	.phy.dpi.data_lines     = 24,
-	.reset_gpio             = -EINVAL, /* will be replaced */
-	.platform_enable        = devkit8000_panel_enable_lcd,
-	.platform_disable       = devkit8000_panel_disable_lcd,
 };
+
+static struct panel_generic_dpi_data dvi_panel = {
+	.name			= "generic",
+	.platform_enable        = devkit8000_panel_enable_dvi,
+	.platform_disable       = devkit8000_panel_disable_dvi,
+};
+
 static struct omap_dss_device devkit8000_dvi_device = {
 	.name                   = "dvi",
-	.driver_name            = "generic_panel",
 	.type                   = OMAP_DISPLAY_TYPE_DPI,
+	.driver_name            = "generic_dpi_panel",
+	.data			= &dvi_panel,
 	.phy.dpi.data_lines     = 24,
-	.reset_gpio             = -EINVAL, /* will be replaced */
-	.platform_enable        = devkit8000_panel_enable_dvi,
-	.platform_disable       = devkit8000_panel_disable_dvi,
 };
 
 static struct omap_dss_device devkit8000_tv_device = {
@@ -237,6 +244,8 @@ static struct gpio_led gpio_leds[];
 static int devkit8000_twl_gpio_setup(struct device *dev,
 		unsigned gpio, unsigned ngpio)
 {
+	int ret;
+
 	omap_mux_init_gpio(29, OMAP_PIN_INPUT);
 	/* gpio + 0 is "mmc0_cd" (input/IRQ) */
 	mmc[0].gpio_cd = gpio + 0;
@@ -245,17 +254,23 @@ static int devkit8000_twl_gpio_setup(str
 	/* TWL4030_GPIO_MAX + 1 == ledB, PMU_STAT (out, active low LED) */
 	gpio_leds[2].gpio = gpio + TWL4030_GPIO_MAX + 1;
 
-        /* gpio + 1 is "LCD_PWREN" (out, active high) */
-	devkit8000_lcd_device.reset_gpio = gpio + 1;
-	gpio_request(devkit8000_lcd_device.reset_gpio, "LCD_PWREN");
-	/* Disable until needed */
-	gpio_direction_output(devkit8000_lcd_device.reset_gpio, 0);
+	/* TWL4030_GPIO_MAX + 0 is "LCD_PWREN" (out, active high) */
+	devkit8000_lcd_device.reset_gpio = gpio + TWL4030_GPIO_MAX + 0;
+	ret = gpio_request_one(devkit8000_lcd_device.reset_gpio,
+			GPIOF_DIR_OUT | GPIOF_INIT_LOW, "LCD_PWREN");
+	if (ret < 0) {
+		devkit8000_lcd_device.reset_gpio = -EINVAL;
+		printk(KERN_ERR "Failed to request GPIO for LCD_PWRN\n");
+	}
 
 	/* gpio + 7 is "DVI_PD" (out, active low) */
 	devkit8000_dvi_device.reset_gpio = gpio + 7;
-	gpio_request(devkit8000_dvi_device.reset_gpio, "DVI PowerDown");
-	/* Disable until needed */
-	gpio_direction_output(devkit8000_dvi_device.reset_gpio, 0);
+	ret = gpio_request_one(devkit8000_dvi_device.reset_gpio,
+			GPIOF_DIR_OUT | GPIOF_INIT_LOW, "DVI PowerDown");
+	if (ret < 0) {
+		devkit8000_dvi_device.reset_gpio = -EINVAL;
+		printk(KERN_ERR "Failed to request GPIO for DVI PowerDown\n");
+	}
 
 	return 0;
 }
@@ -265,8 +280,7 @@ static struct twl4030_gpio_platform_data
 	.irq_base	= TWL4030_GPIO_IRQ_BASE,
 	.irq_end	= TWL4030_GPIO_IRQ_END,
 	.use_leds	= true,
-	.pullups	= BIT(1),
-	.pulldowns	= BIT(2) | BIT(6) | BIT(7) | BIT(8) | BIT(13)
+	.pulldowns	= BIT(1) | BIT(2) | BIT(6) | BIT(8) | BIT(13)
 				| BIT(15) | BIT(16) | BIT(17),
 	.setup		= devkit8000_twl_gpio_setup,
 };
@@ -444,13 +458,13 @@ static struct platform_device keys_gpio
 
 static void __init devkit8000_init_irq(void)
 {
-	omap2_init_common_hw(mt46h32m32lf6_sdrc_params,
-			     mt46h32m32lf6_sdrc_params);
+	omap2_init_common_infrastructure();
+	omap2_init_common_devices(mt46h32m32lf6_sdrc_params,
+				  mt46h32m32lf6_sdrc_params);
 	omap_init_irq();
 #ifdef CONFIG_OMAP_32K_TIMER
 	omap2_gp_clockevent_set_gptimer(12);
 #endif
-	omap_gpio_init();
 }
 
 static void __init devkit8000_ads7846_init(void)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/board-generic.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/board-generic.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/board-generic.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/board-generic.c	2011-03-14 21:20:32.000000000 -0400
@@ -37,7 +37,8 @@ static void __init omap_generic_init_irq
 {
 	omap_board_config = generic_config;
 	omap_board_config_size = ARRAY_SIZE(generic_config);
-	omap2_init_common_hw(NULL, NULL);
+	omap2_init_common_infrastructure();
+	omap2_init_common_devices(NULL, NULL);
 	omap_init_irq();
 }
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/board-h4.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/board-h4.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/board-h4.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/board-h4.c	2011-03-14 21:20:32.000000000 -0400
@@ -51,38 +51,37 @@
 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 int h4_keymap[] = {
+static const unsigned int h4_keymap[] = {
 	KEY(0, 0, KEY_LEFT),
-	KEY(0, 1, KEY_RIGHT),
-	KEY(0, 2, KEY_A),
-	KEY(0, 3, KEY_B),
-	KEY(0, 4, KEY_C),
-	KEY(1, 0, KEY_DOWN),
+	KEY(1, 0, KEY_RIGHT),
+	KEY(2, 0, KEY_A),
+	KEY(3, 0, KEY_B),
+	KEY(4, 0, KEY_C),
+	KEY(0, 1, KEY_DOWN),
 	KEY(1, 1, KEY_UP),
-	KEY(1, 2, KEY_E),
-	KEY(1, 3, KEY_F),
-	KEY(1, 4, KEY_G),
-	KEY(2, 0, KEY_ENTER),
-	KEY(2, 1, KEY_I),
+	KEY(2, 1, KEY_E),
+	KEY(3, 1, KEY_F),
+	KEY(4, 1, KEY_G),
+	KEY(0, 2, KEY_ENTER),
+	KEY(1, 2, KEY_I),
 	KEY(2, 2, KEY_J),
-	KEY(2, 3, KEY_K),
-	KEY(2, 4, KEY_3),
-	KEY(3, 0, KEY_M),
-	KEY(3, 1, KEY_N),
-	KEY(3, 2, KEY_O),
+	KEY(3, 2, KEY_K),
+	KEY(4, 2, KEY_3),
+	KEY(0, 3, KEY_M),
+	KEY(1, 3, KEY_N),
+	KEY(2, 3, KEY_O),
 	KEY(3, 3, KEY_P),
-	KEY(3, 4, KEY_Q),
-	KEY(4, 0, KEY_R),
-	KEY(4, 1, KEY_4),
-	KEY(4, 2, KEY_T),
-	KEY(4, 3, KEY_U),
+	KEY(4, 3, KEY_Q),
+	KEY(0, 4, KEY_R),
+	KEY(1, 4, KEY_4),
+	KEY(2, 4, KEY_T),
+	KEY(3, 4, KEY_U),
 	KEY(4, 4, KEY_ENTER),
-	KEY(5, 0, KEY_V),
-	KEY(5, 1, KEY_W),
-	KEY(5, 2, KEY_L),
-	KEY(5, 3, KEY_S),
-	KEY(5, 4, KEY_ENTER),
-	0
+	KEY(0, 5, KEY_V),
+	KEY(1, 5, KEY_W),
+	KEY(2, 5, KEY_L),
+	KEY(3, 5, KEY_S),
+	KEY(4, 5, KEY_ENTER),
 };
 
 static struct mtd_partition h4_partitions[] = {
@@ -136,12 +135,16 @@ 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 omap_kp_platform_data h4_kp_data = {
 	.rows		= 6,
 	.cols		= 7,
-	.keymap 	= h4_keymap,
-	.keymapsize 	= ARRAY_SIZE(h4_keymap),
-	.rep		= 1,
+	.keymap_data	= &h4_keymap_data,
+	.rep		= true,
 	.row_gpios 	= row_gpios,
 	.col_gpios 	= col_gpios,
 };
@@ -283,7 +286,7 @@ 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[] = {
+static struct omap_board_config_kernel h4_config[] __initdata = {
 	{ OMAP_TAG_LCD,		&h4_lcd_config },
 };
 
@@ -291,9 +294,9 @@ static void __init omap_h4_init_irq(void
 {
 	omap_board_config = h4_config;
 	omap_board_config_size = ARRAY_SIZE(h4_config);
-	omap2_init_common_hw(NULL, NULL);
+	omap2_init_common_infrastructure();
+	omap2_init_common_devices(NULL, NULL);
 	omap_init_irq();
-	omap_gpio_init();
 	h4_init_flash();
 }
 
@@ -321,8 +324,6 @@ static struct i2c_board_info __initdata
 static struct omap_board_mux board_mux[] __initdata = {
 	{ .reg_offset = OMAP_MUX_TERMINATOR },
 };
-#else
-#define board_mux	NULL
 #endif
 
 static void __init omap_h4_init(void)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/board-igep0020.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/board-igep0020.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/board-igep0020.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/board-igep0020.c	2011-03-14 21:20:32.000000000 -0400
@@ -17,8 +17,10 @@
 #include <linux/io.h>
 #include <linux/gpio.h>
 #include <linux/interrupt.h>
+#include <linux/input.h>
 
 #include <linux/regulator/machine.h>
+#include <linux/regulator/fixed.h>
 #include <linux/i2c/twl.h>
 #include <linux/mmc/host.h>
 
@@ -30,6 +32,7 @@
 #include <plat/gpmc.h>
 #include <plat/usb.h>
 #include <plat/display.h>
+#include <plat/panel-generic-dpi.h>
 #include <plat/onenand.h>
 
 #include "mux.h"
@@ -136,16 +139,9 @@ static struct mtd_partition igep2_onenan
 	},
 };
 
-static int igep2_onenand_setup(void __iomem *onenand_base, int freq)
-{
-       /* nothing is required to be setup for onenand as of now */
-       return 0;
-}
-
 static struct omap_onenand_platform_data igep2_onenand_data = {
 	.parts = igep2_onenand_partitions,
 	.nr_parts = ARRAY_SIZE(igep2_onenand_partitions),
-	.onenand_setup = igep2_onenand_setup,
 	.dma_channel	= -1,	/* disable DMA in OMAP OneNAND driver */
 };
 
@@ -159,35 +155,34 @@ static struct platform_device igep2_onen
 
 static void __init igep2_flash_init(void)
 {
-	u8		cs = 0;
-	u8		onenandcs = GPMC_CS_NUM + 1;
+	u8 cs = 0;
+	u8 onenandcs = GPMC_CS_NUM + 1;
 
-	while (cs < GPMC_CS_NUM) {
-		u32 ret = 0;
+	for (cs = 0; cs < GPMC_CS_NUM; cs++) {
+		u32 ret;
 		ret = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
 
 		/* Check if NAND/oneNAND is configured */
 		if ((ret & 0xC00) == 0x800)
 			/* NAND found */
-			pr_err("IGEP v2: Unsupported NAND found\n");
+			pr_err("IGEP2: Unsupported NAND found\n");
 		else {
 			ret = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG7);
 			if ((ret & 0x3F) == (ONENAND_MAP >> 24))
 				/* ONENAND found */
 				onenandcs = cs;
 		}
-		cs++;
 	}
+
 	if (onenandcs > GPMC_CS_NUM) {
-		pr_err("IGEP v2: Unable to find configuration in GPMC\n");
+		pr_err("IGEP2: Unable to find configuration in GPMC\n");
 		return;
 	}
 
-	if (onenandcs < GPMC_CS_NUM) {
-		igep2_onenand_data.cs = onenandcs;
-		if (platform_device_register(&igep2_onenand_device) < 0)
-			pr_err("IGEP v2: Unable to register OneNAND device\n");
-	}
+	igep2_onenand_data.cs = onenandcs;
+
+	if (platform_device_register(&igep2_onenand_device) < 0)
+		pr_err("IGEP2: Unable to register OneNAND device\n");
 }
 
 #else
@@ -254,12 +249,8 @@ static inline void __init igep2_init_sms
 static inline void __init igep2_init_smsc911x(void) { }
 #endif
 
-static struct omap_board_config_kernel igep2_config[] __initdata = {
-};
-
-static struct regulator_consumer_supply igep2_vmmc1_supply = {
-	.supply		= "vmmc",
-};
+static struct regulator_consumer_supply igep2_vmmc1_supply =
+	REGULATOR_SUPPLY("vmmc", "mmci-omap-hs.0");
 
 /* VMMC1 for OMAP VDD_MMC1 (i/o) and MMC1 card */
 static struct regulator_init_data igep2_vmmc1 = {
@@ -276,6 +267,52 @@ static struct regulator_init_data igep2_
 	.consumer_supplies      = &igep2_vmmc1_supply,
 };
 
+static struct regulator_consumer_supply igep2_vio_supply =
+	REGULATOR_SUPPLY("vmmc_aux", "mmci-omap-hs.1");
+
+static struct regulator_init_data igep2_vio = {
+	.constraints = {
+		.min_uV			= 1800000,
+		.max_uV			= 1800000,
+		.apply_uV		= 1,
+		.valid_modes_mask	= REGULATOR_MODE_NORMAL
+					| REGULATOR_MODE_STANDBY,
+		.valid_ops_mask		= REGULATOR_CHANGE_VOLTAGE
+					| REGULATOR_CHANGE_MODE
+					| REGULATOR_CHANGE_STATUS,
+	},
+	.num_consumer_supplies  = 1,
+	.consumer_supplies      = &igep2_vio_supply,
+};
+
+static struct regulator_consumer_supply igep2_vmmc2_supply =
+	REGULATOR_SUPPLY("vmmc", "mmci-omap-hs.1");
+
+static struct regulator_init_data igep2_vmmc2 = {
+	.constraints		= {
+		.valid_modes_mask	= REGULATOR_MODE_NORMAL,
+		.always_on		= 1,
+	},
+	.num_consumer_supplies	= 1,
+	.consumer_supplies	= &igep2_vmmc2_supply,
+};
+
+static struct fixed_voltage_config igep2_vwlan = {
+	.supply_name		= "vwlan",
+	.microvolts		= 3300000,
+	.gpio			= -EINVAL,
+	.enabled_at_boot	= 1,
+	.init_data		= &igep2_vmmc2,
+};
+
+static struct platform_device igep2_vwlan_device = {
+	.name		= "reg-fixed-voltage",
+	.id		= 0,
+	.dev = {
+		.platform_data	= &igep2_vwlan,
+	},
+};
+
 static struct omap2_hsmmc_info mmc[] = {
 	{
 		.mmc		= 1,
@@ -317,6 +354,7 @@ static struct gpio_led igep2_gpio_leds[]
 		.name			= "gpio-led:green:d1",
 		.default_trigger	= "heartbeat",
 		.gpio			= -EINVAL, /* gets replaced */
+		.active_low		= 1,
 	},
 };
 
@@ -342,24 +380,21 @@ static void __init igep2_leds_init(void)
 static inline void igep2_leds_init(void)
 {
 	if ((gpio_request(IGEP2_GPIO_LED0_RED, "gpio-led:red:d0") == 0) &&
-	    (gpio_direction_output(IGEP2_GPIO_LED0_RED, 1) == 0)) {
+	    (gpio_direction_output(IGEP2_GPIO_LED0_RED, 0) == 0))
 		gpio_export(IGEP2_GPIO_LED0_RED, 0);
-		gpio_set_value(IGEP2_GPIO_LED0_RED, 0);
-	} else
+	else
 		pr_warning("IGEP v2: Could not obtain gpio GPIO_LED0_RED\n");
 
 	if ((gpio_request(IGEP2_GPIO_LED0_GREEN, "gpio-led:green:d0") == 0) &&
-	    (gpio_direction_output(IGEP2_GPIO_LED0_GREEN, 1) == 0)) {
+	    (gpio_direction_output(IGEP2_GPIO_LED0_GREEN, 0) == 0))
 		gpio_export(IGEP2_GPIO_LED0_GREEN, 0);
-		gpio_set_value(IGEP2_GPIO_LED0_GREEN, 0);
-	} else
+	else
 		pr_warning("IGEP v2: Could not obtain gpio GPIO_LED0_GREEN\n");
 
 	if ((gpio_request(IGEP2_GPIO_LED1_RED, "gpio-led:red:d1") == 0) &&
-	    (gpio_direction_output(IGEP2_GPIO_LED1_RED, 1) == 0)) {
+	    (gpio_direction_output(IGEP2_GPIO_LED1_RED, 0) == 0))
 		gpio_export(IGEP2_GPIO_LED1_RED, 0);
-		gpio_set_value(IGEP2_GPIO_LED1_RED, 0);
-	} else
+	else
 		pr_warning("IGEP v2: Could not obtain gpio GPIO_LED1_RED\n");
 
 }
@@ -373,12 +408,6 @@ static int igep2_twl_gpio_setup(struct d
 	omap2_hsmmc_init(mmc);
 
 	/*
-	 * link regulators to MMC adapters ... we "know" the
-	 * regulators will be set up only *after* we return.
-	 */
-	igep2_vmmc1_supply.dev = mmc[0].dev;
-
-	/*
 	 * REVISIT: need ehci-omap hooks for external VBUS
 	 * power switch and overcurrent detect
 	 */
@@ -397,10 +426,9 @@ static int igep2_twl_gpio_setup(struct d
 	/* TWL4030_GPIO_MAX + 1 == ledB (out, active low LED) */
 #if !defined(CONFIG_LEDS_GPIO) && !defined(CONFIG_LEDS_GPIO_MODULE)
 	if ((gpio_request(gpio+TWL4030_GPIO_MAX+1, "gpio-led:green:d1") == 0)
-	    && (gpio_direction_output(gpio + TWL4030_GPIO_MAX + 1, 1) == 0)) {
+	    && (gpio_direction_output(gpio + TWL4030_GPIO_MAX + 1, 1) == 0))
 		gpio_export(gpio + TWL4030_GPIO_MAX + 1, 0);
-		gpio_set_value(gpio + TWL4030_GPIO_MAX + 1, 0);
-	} else
+	else
 		pr_warning("IGEP v2: Could not obtain gpio GPIO_LED1_GREEN\n");
 #else
 	igep2_gpio_leds[3].gpio = gpio + TWL4030_GPIO_MAX + 1;
@@ -433,13 +461,18 @@ 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",
+	.platform_enable	= igep2_enable_dvi,
+	.platform_disable	= igep2_disable_dvi,
+};
+
 static struct omap_dss_device igep2_dvi_device = {
 	.type			= OMAP_DISPLAY_TYPE_DPI,
 	.name			= "dvi",
-	.driver_name		= "generic_panel",
+	.driver_name		= "generic_dpi_panel",
+	.data			= &dvi_panel,
 	.phy.dpi.data_lines	= 24,
-	.platform_enable	= igep2_enable_dvi,
-	.platform_disable	= igep2_disable_dvi,
 };
 
 static struct omap_dss_device *igep2_dss_devices[] = {
@@ -489,15 +522,15 @@ static void __init igep2_display_init(vo
 
 static struct platform_device *igep2_devices[] __initdata = {
 	&igep2_dss_device,
+	&igep2_vwlan_device,
 };
 
 static void __init igep2_init_irq(void)
 {
-	omap_board_config = igep2_config;
-	omap_board_config_size = ARRAY_SIZE(igep2_config);
-	omap2_init_common_hw(m65kxxxxam_sdrc_params, m65kxxxxam_sdrc_params);
+	omap2_init_common_infrastructure();
+	omap2_init_common_devices(m65kxxxxam_sdrc_params,
+				  m65kxxxxam_sdrc_params);
 	omap_init_irq();
-	omap_gpio_init();
 }
 
 static struct twl4030_codec_audio_data igep2_audio_data = {
@@ -509,6 +542,37 @@ static struct twl4030_codec_data igep2_c
 	.audio = &igep2_audio_data,
 };
 
+static int igep2_keymap[] = {
+	KEY(0, 0, KEY_LEFT),
+	KEY(0, 1, KEY_RIGHT),
+	KEY(0, 2, KEY_A),
+	KEY(0, 3, KEY_B),
+	KEY(1, 0, KEY_DOWN),
+	KEY(1, 1, KEY_UP),
+	KEY(1, 2, KEY_E),
+	KEY(1, 3, KEY_F),
+	KEY(2, 0, KEY_ENTER),
+	KEY(2, 1, KEY_I),
+	KEY(2, 2, KEY_J),
+	KEY(2, 3, KEY_K),
+	KEY(3, 0, KEY_M),
+	KEY(3, 1, KEY_N),
+	KEY(3, 2, KEY_O),
+	KEY(3, 3, KEY_P)
+};
+
+static struct matrix_keymap_data igep2_keymap_data = {
+	.keymap			= igep2_keymap,
+	.keymap_size		= ARRAY_SIZE(igep2_keymap),
+};
+
+static struct twl4030_keypad_data igep2_keypad_pdata = {
+	.keymap_data	= &igep2_keymap_data,
+	.rows		= 4,
+	.cols		= 4,
+	.rep		= 1,
+};
+
 static struct twl4030_platform_data igep2_twldata = {
 	.irq_base	= TWL4030_IRQ_BASE,
 	.irq_end	= TWL4030_IRQ_END,
@@ -517,9 +581,10 @@ static struct twl4030_platform_data igep
 	.usb		= &igep2_usb_data,
 	.codec		= &igep2_codec_data,
 	.gpio		= &igep2_twl4030_gpio_pdata,
+	.keypad		= &igep2_keypad_pdata,
 	.vmmc1          = &igep2_vmmc1,
 	.vpll2		= &igep2_vpll2,
-
+	.vio		= &igep2_vio,
 };
 
 static struct i2c_board_info __initdata igep2_i2c1_boardinfo[] = {
@@ -577,8 +642,6 @@ static const struct ehci_hcd_omap_platfo
 static struct omap_board_mux board_mux[] __initdata = {
 	{ .reg_offset = OMAP_MUX_TERMINATOR },
 };
-#else
-#define board_mux	NULL
 #endif
 
 #if defined(CONFIG_LIBERTAS_SDIO) || defined(CONFIG_LIBERTAS_SDIO_MODULE)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/board-igep0030.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/board-igep0030.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/board-igep0030.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/board-igep0030.c	2011-03-14 21:20:32.000000000 -0400
@@ -19,6 +19,7 @@
 #include <linux/interrupt.h>
 
 #include <linux/regulator/machine.h>
+#include <linux/regulator/fixed.h>
 #include <linux/i2c/twl.h>
 #include <linux/mmc/host.h>
 
@@ -43,7 +44,7 @@
 #define IGEP3_GPIO_WIFI_NRESET	139
 #define IGEP3_GPIO_BT_NRESET	137
 
-#define IGEP3_GPIO_USBH_NRESET  115
+#define IGEP3_GPIO_USBH_NRESET  183
 
 
 #if defined(CONFIG_MTD_ONENAND_OMAP2) || \
@@ -103,7 +104,7 @@ static struct platform_device igep3_onen
 	},
 };
 
-void __init igep3_flash_init(void)
+static void __init igep3_flash_init(void)
 {
 	u8 cs = 0;
 	u8 onenandcs = GPMC_CS_NUM + 1;
@@ -137,12 +138,11 @@ void __init igep3_flash_init(void)
 }
 
 #else
-void __init igep3_flash_init(void) {}
+static void __init igep3_flash_init(void) {}
 #endif
 
-static struct regulator_consumer_supply igep3_vmmc1_supply = {
-	.supply		= "vmmc",
-};
+static struct regulator_consumer_supply igep3_vmmc1_supply =
+	REGULATOR_SUPPLY("vmmc", "mmci-omap-hs.0");
 
 /* VMMC1 for OMAP VDD_MMC1 (i/o) and MMC1 card */
 static struct regulator_init_data igep3_vmmc1 = {
@@ -159,6 +159,52 @@ static struct regulator_init_data igep3_
 	.consumer_supplies      = &igep3_vmmc1_supply,
 };
 
+static struct regulator_consumer_supply igep3_vio_supply =
+	REGULATOR_SUPPLY("vmmc_aux", "mmci-omap-hs.1");
+
+static struct regulator_init_data igep3_vio = {
+	.constraints = {
+		.min_uV			= 1800000,
+		.max_uV			= 1800000,
+		.apply_uV		= 1,
+		.valid_modes_mask	= REGULATOR_MODE_NORMAL
+					| REGULATOR_MODE_STANDBY,
+		.valid_ops_mask		= REGULATOR_CHANGE_VOLTAGE
+					| REGULATOR_CHANGE_MODE
+					| REGULATOR_CHANGE_STATUS,
+	},
+	.num_consumer_supplies	= 1,
+	.consumer_supplies	= &igep3_vio_supply,
+};
+
+static struct regulator_consumer_supply igep3_vmmc2_supply =
+	REGULATOR_SUPPLY("vmmc", "mmci-omap-hs.1");
+
+static struct regulator_init_data igep3_vmmc2 = {
+	.constraints	= {
+		.valid_modes_mask	= REGULATOR_MODE_NORMAL,
+		.always_on		= 1,
+	},
+	.num_consumer_supplies	= 1,
+	.consumer_supplies	= &igep3_vmmc2_supply,
+};
+
+static struct fixed_voltage_config igep3_vwlan = {
+	.supply_name		= "vwlan",
+	.microvolts		= 3300000,
+	.gpio			= -EINVAL,
+	.enabled_at_boot	= 1,
+	.init_data		= &igep3_vmmc2,
+};
+
+static struct platform_device igep3_vwlan_device = {
+	.name	= "reg-fixed-voltage",
+	.id	= 0,
+	.dev	= {
+		.platform_data = &igep3_vwlan,
+	},
+};
+
 static struct omap2_hsmmc_info mmc[] = {
 	[0] = {
 		.mmc		= 1,
@@ -254,12 +300,6 @@ static int igep3_twl4030_gpio_setup(stru
 	mmc[0].gpio_cd = gpio + 0;
 	omap2_hsmmc_init(mmc);
 
-	/*
-	 * link regulators to MMC adapters ... we "know" the
-	 * regulators will be set up only *after* we return.
-	 */
-	igep3_vmmc1_supply.dev = mmc[0].dev;
-
 	/* TWL4030_GPIO_MAX + 1 == ledB (out, active low LED) */
 #if !defined(CONFIG_LEDS_GPIO) && !defined(CONFIG_LEDS_GPIO_MODULE)
 	if ((gpio_request(gpio+TWL4030_GPIO_MAX+1, "gpio-led:green:d1") == 0)
@@ -287,11 +327,16 @@ static struct twl4030_usb_data igep3_twl
 	.usb_mode	= T2_USB_MODE_ULPI,
 };
 
+static struct platform_device *igep3_devices[] __initdata = {
+	&igep3_vwlan_device,
+};
+
 static void __init igep3_init_irq(void)
 {
-	omap2_init_common_hw(m65kxxxxam_sdrc_params, m65kxxxxam_sdrc_params);
+	omap2_init_common_infrastructure();
+	omap2_init_common_devices(m65kxxxxam_sdrc_params,
+				  m65kxxxxam_sdrc_params);
 	omap_init_irq();
-	omap_gpio_init();
 }
 
 static struct twl4030_platform_data igep3_twl4030_pdata = {
@@ -302,6 +347,7 @@ static struct twl4030_platform_data igep
 	.usb		= &igep3_twl4030_usb_data,
 	.gpio		= &igep3_twl4030_gpio_pdata,
 	.vmmc1		= &igep3_vmmc1,
+	.vio		= &igep3_vio,
 };
 
 static struct i2c_board_info __initdata igep3_i2c_boardinfo[] = {
@@ -362,12 +408,22 @@ static void __init igep3_wifi_bt_init(vo
 void __init igep3_wifi_bt_init(void) {}
 #endif
 
+static const struct ehci_hcd_omap_platform_data ehci_pdata __initconst = {
+	.port_mode[0] = EHCI_HCD_OMAP_MODE_UNKNOWN,
+	.port_mode[1] = EHCI_HCD_OMAP_MODE_PHY,
+	.port_mode[2] = EHCI_HCD_OMAP_MODE_UNKNOWN,
+
+	.phy_reset = true,
+	.reset_gpio_port[0] = -EINVAL,
+	.reset_gpio_port[1] = IGEP3_GPIO_USBH_NRESET,
+	.reset_gpio_port[2] = -EINVAL,
+};
+
 #ifdef CONFIG_OMAP_MUX
 static struct omap_board_mux board_mux[] __initdata = {
+	OMAP3_MUX(I2C2_SDA, OMAP_MUX_MODE4 | OMAP_PIN_OUTPUT),
 	{ .reg_offset = OMAP_MUX_TERMINATOR },
 };
-#else
-#define board_mux	NULL
 #endif
 
 static void __init igep3_init(void)
@@ -376,9 +432,10 @@ static void __init igep3_init(void)
 
 	/* Register I2C busses and drivers */
 	igep3_i2c_init();
-
+	platform_add_devices(igep3_devices, ARRAY_SIZE(igep3_devices));
 	omap_serial_init();
 	usb_musb_init(&musb_board_data);
+	usb_ehci_init(&ehci_pdata);
 
 	igep3_flash_init();
 	igep3_leds_init();
@@ -393,6 +450,7 @@ static void __init igep3_init(void)
 
 MACHINE_START(IGEP0030, "IGEP OMAP3 module")
 	.boot_params	= 0x80000100,
+	.reserve	= omap_reserve,
 	.map_io		= omap3_map_io,
 	.init_irq	= igep3_init_irq,
 	.init_machine	= igep3_init,
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/board-ldp.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/board-ldp.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/board-ldp.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/board-ldp.c	2011-03-14 21:20:32.000000000 -0400
@@ -292,10 +292,9 @@ static void __init omap_ldp_init_irq(voi
 {
 	omap_board_config = ldp_config;
 	omap_board_config_size = ARRAY_SIZE(ldp_config);
-	omap2_init_common_hw(NULL, NULL);
+	omap2_init_common_infrastructure();
+	omap2_init_common_devices(NULL, NULL);
 	omap_init_irq();
-	omap_gpio_init();
-	ldp_init_smsc911x();
 }
 
 static struct twl4030_usb_data ldp_usb_data = {
@@ -381,8 +380,6 @@ static struct platform_device *ldp_devic
 static struct omap_board_mux board_mux[] __initdata = {
 	{ .reg_offset = OMAP_MUX_TERMINATOR },
 };
-#else
-#define board_mux	NULL
 #endif
 
 static struct omap_musb_board_data musb_board_data = {
@@ -426,6 +423,7 @@ static struct mtd_partition ldp_nand_par
 static void __init omap_ldp_init(void)
 {
 	omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
+	ldp_init_smsc911x();
 	omap_i2c_init();
 	platform_add_devices(ldp_devices, ARRAY_SIZE(ldp_devices));
 	ts_gpio = 54;
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/board-n8x0.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/board-n8x0.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/board-n8x0.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/board-n8x0.c	2011-03-14 21:20:32.000000000 -0400
@@ -46,8 +46,7 @@ static struct device *mmc_device;
 #define TUSB6010_GPIO_ENABLE	0
 #define TUSB6010_DMACHAN	0x3f
 
-#if defined(CONFIG_USB_TUSB6010) || \
-	defined(CONFIG_USB_TUSB6010_MODULE)
+#ifdef CONFIG_USB_MUSB_TUSB6010
 /*
  * Enable or disable power to TUSB6010. When enabling, turn on 3.3 V and
  * 1.5 V voltage regulators of PM companion chip. Companion chip will then
@@ -134,7 +133,7 @@ err:
 
 static void __init n8x0_usb_init(void) {}
 
-#endif /*CONFIG_USB_TUSB6010 */
+#endif /*CONFIG_USB_MUSB_TUSB6010 */
 
 
 static struct omap2_mcspi_device_config p54spi_mcspi_config = {
@@ -184,23 +183,15 @@ static struct mtd_partition onenand_part
 	},
 };
 
-static struct omap_onenand_platform_data board_onenand_data = {
-	.cs		= 0,
-	.gpio_irq	= 26,
-	.parts		= onenand_partitions,
-	.nr_parts	= ARRAY_SIZE(onenand_partitions),
-	.flags		= ONENAND_SYNC_READ,
+static struct omap_onenand_platform_data board_onenand_data[] = {
+	{
+		.cs		= 0,
+		.gpio_irq	= 26,
+		.parts		= onenand_partitions,
+		.nr_parts	= ARRAY_SIZE(onenand_partitions),
+		.flags		= ONENAND_SYNC_READ,
+	}
 };
-
-static void __init n8x0_onenand_init(void)
-{
-	gpmc_onenand_init(&board_onenand_data);
-}
-
-#else
-
-static void __init n8x0_onenand_init(void) {}
-
 #endif
 
 #if defined(CONFIG_MENELAUS) &&						\
@@ -639,9 +630,9 @@ static void __init n8x0_map_io(void)
 
 static void __init n8x0_init_irq(void)
 {
-	omap2_init_common_hw(NULL, NULL);
+	omap2_init_common_infrastructure();
+	omap2_init_common_devices(NULL, NULL);
 	omap_init_irq();
-	omap_gpio_init();
 }
 
 #ifdef CONFIG_OMAP_MUX
@@ -653,8 +644,43 @@ static struct omap_board_mux board_mux[]
 	OMAP2420_MUX(EAC_AC_DOUT, OMAP_MUX_MODE1 | OMAP_PIN_OUTPUT),
 	{ .reg_offset = OMAP_MUX_TERMINATOR },
 };
+
+static struct omap_device_pad serial2_pads[] __initdata = {
+	{
+		.name	= "uart3_rx_irrx.uart3_rx_irrx",
+		.flags	= OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP,
+		.enable	= OMAP_MUX_MODE0,
+		.idle	= OMAP_MUX_MODE3	/* Mux as GPIO for idle */
+	},
+};
+
+static inline void board_serial_init(void)
+{
+	struct omap_board_data bdata;
+
+	bdata.flags = 0;
+	bdata.pads = NULL;
+	bdata.pads_cnt = 0;
+
+	bdata.id = 0;
+	omap_serial_init_port(&bdata);
+
+	bdata.id = 1;
+	omap_serial_init_port(&bdata);
+
+	bdata.id = 2;
+	bdata.pads = serial2_pads;
+	bdata.pads_cnt = ARRAY_SIZE(serial2_pads);
+	omap_serial_init_port(&bdata);
+}
+
 #else
-#define board_mux	NULL
+
+static inline void board_serial_init(void)
+{
+	omap_serial_init();
+}
+
 #endif
 
 static void __init n8x0_init_machine(void)
@@ -669,9 +695,8 @@ static void __init n8x0_init_machine(voi
 	if (machine_is_nokia_n810())
 		i2c_register_board_info(2, n810_i2c_board_info_2,
 					ARRAY_SIZE(n810_i2c_board_info_2));
-
-	omap_serial_init();
-	n8x0_onenand_init();
+	board_serial_init();
+	gpmc_onenand_init(board_onenand_data);
 	n8x0_mmc_init();
 	n8x0_usb_init();
 }
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/board-omap3beagle.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/board-omap3beagle.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/board-omap3beagle.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/board-omap3beagle.c	2011-03-14 21:20:32.000000000 -0400
@@ -41,6 +41,7 @@
 #include <plat/board.h>
 #include <plat/common.h>
 #include <plat/display.h>
+#include <plat/panel-generic-dpi.h>
 #include <plat/gpmc.h>
 #include <plat/nand.h>
 #include <plat/usb.h>
@@ -194,14 +195,19 @@ static void beagle_disable_dvi(struct om
 		gpio_set_value(dssdev->reset_gpio, 0);
 }
 
+static struct panel_generic_dpi_data dvi_panel = {
+	.name = "generic",
+	.platform_enable = beagle_enable_dvi,
+	.platform_disable = beagle_disable_dvi,
+};
+
 static struct omap_dss_device beagle_dvi_device = {
 	.type = OMAP_DISPLAY_TYPE_DPI,
 	.name = "dvi",
-	.driver_name = "generic_panel",
+	.driver_name = "generic_dpi_panel",
+	.data = &dvi_panel,
 	.phy.dpi.data_lines = 24,
-	.reset_gpio = 170,
-	.platform_enable = beagle_enable_dvi,
-	.platform_disable = beagle_disable_dvi,
+	.reset_gpio = -EINVAL,
 };
 
 static struct omap_dss_device beagle_tv_device = {
@@ -273,6 +279,8 @@ static struct gpio_led gpio_leds[];
 static int beagle_twl_gpio_setup(struct device *dev,
 		unsigned gpio, unsigned ngpio)
 {
+	int r;
+
 	if (omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_XM) {
 		mmc[0].gpio_wp = -EINVAL;
 	} else if ((omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_C1_3) ||
@@ -293,17 +301,63 @@ static int beagle_twl_gpio_setup(struct
 	/* REVISIT: need ehci-omap hooks for external VBUS
 	 * power switch and overcurrent detect
 	 */
+	if (omap3_beagle_get_rev() != OMAP3BEAGLE_BOARD_XM) {
+		r = gpio_request(gpio + 1, "EHCI_nOC");
+		if (!r) {
+			r = gpio_direction_input(gpio + 1);
+			if (r)
+				gpio_free(gpio + 1);
+		}
+		if (r)
+			pr_err("%s: unable to configure EHCI_nOC\n", __func__);
+	}
 
-	gpio_request(gpio + 1, "EHCI_nOC");
-	gpio_direction_input(gpio + 1);
-
-	/* TWL4030_GPIO_MAX + 0 == ledA, EHCI nEN_USB_PWR (out, active low) */
+	/*
+	 * TWL4030_GPIO_MAX + 0 == ledA, EHCI nEN_USB_PWR (out, XM active
+	 * high / others active low)
+	 */
 	gpio_request(gpio + TWL4030_GPIO_MAX, "nEN_USB_PWR");
-	gpio_direction_output(gpio + TWL4030_GPIO_MAX, 0);
+	if (omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_XM)
+		gpio_direction_output(gpio + TWL4030_GPIO_MAX, 1);
+	else
+		gpio_direction_output(gpio + TWL4030_GPIO_MAX, 0);
+
+	/* DVI reset GPIO is different between beagle revisions */
+	if (omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_XM)
+		beagle_dvi_device.reset_gpio = 129;
+	else
+		beagle_dvi_device.reset_gpio = 170;
 
 	/* TWL4030_GPIO_MAX + 1 == ledB, PMU_STAT (out, active low LED) */
 	gpio_leds[2].gpio = gpio + TWL4030_GPIO_MAX + 1;
 
+	/*
+	 * gpio + 1 on Xm controls the TFP410's enable line (active low)
+	 * gpio + 2 control varies depending on the board rev as follows:
+	 * P7/P8 revisions(prototype): Camera EN
+	 * A2+ revisions (production): LDO (supplies DVI, serial, led blocks)
+	 */
+	if (omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_XM) {
+		r = gpio_request(gpio + 1, "nDVI_PWR_EN");
+		if (!r) {
+			r = gpio_direction_output(gpio + 1, 0);
+			if (r)
+				gpio_free(gpio + 1);
+		}
+		if (r)
+			pr_err("%s: unable to configure nDVI_PWR_EN\n",
+				__func__);
+		r = gpio_request(gpio + 2, "DVI_LDO_EN");
+		if (!r) {
+			r = gpio_direction_output(gpio + 2, 1);
+			if (r)
+				gpio_free(gpio + 2);
+		}
+		if (r)
+			pr_err("%s: unable to configure DVI_LDO_EN\n",
+				__func__);
+	}
+
 	return 0;
 }
 
@@ -484,13 +538,13 @@ static struct platform_device keys_gpio
 
 static void __init omap3_beagle_init_irq(void)
 {
-	omap2_init_common_hw(mt46h32m32lf6_sdrc_params,
-			     mt46h32m32lf6_sdrc_params);
+	omap2_init_common_infrastructure();
+	omap2_init_common_devices(mt46h32m32lf6_sdrc_params,
+				  mt46h32m32lf6_sdrc_params);
 	omap_init_irq();
 #ifdef CONFIG_OMAP_32K_TIMER
 	omap2_gp_clockevent_set_gptimer(12);
 #endif
-	omap_gpio_init();
 }
 
 static struct platform_device *omap3_beagle_devices[] __initdata = {
@@ -548,8 +602,6 @@ static const struct ehci_hcd_omap_platfo
 static struct omap_board_mux board_mux[] __initdata = {
 	{ .reg_offset = OMAP_MUX_TERMINATOR },
 };
-#else
-#define board_mux	NULL
 #endif
 
 static struct omap_musb_board_data musb_board_data = {
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/board-omap3evm.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/board-omap3evm.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/board-omap3evm.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/board-omap3evm.c	2011-03-14 21:20:32.000000000 -0400
@@ -43,6 +43,7 @@
 #include <plat/common.h>
 #include <plat/mcspi.h>
 #include <plat/display.h>
+#include <plat/panel-generic-dpi.h>
 
 #include "mux.h"
 #include "sdram-micron-mt46h32m32lf-6.h"
@@ -301,13 +302,18 @@ static void omap3_evm_disable_dvi(struct
 	dvi_enabled = 0;
 }
 
+static struct panel_generic_dpi_data dvi_panel = {
+	.name			= "generic",
+	.platform_enable	= omap3_evm_enable_dvi,
+	.platform_disable	= omap3_evm_disable_dvi,
+};
+
 static struct omap_dss_device omap3_evm_dvi_device = {
 	.name			= "dvi",
-	.driver_name		= "generic_panel",
 	.type			= OMAP_DISPLAY_TYPE_DPI,
+	.driver_name		= "generic_dpi_panel",
+	.data			= &dvi_panel,
 	.phy.dpi.data_lines	= 24,
-	.platform_enable	= omap3_evm_enable_dvi,
-	.platform_disable	= omap3_evm_disable_dvi,
 };
 
 static struct omap_dss_device *omap3_evm_dss_devices[] = {
@@ -623,9 +629,9 @@ static void __init omap3_evm_init_irq(vo
 {
 	omap_board_config = omap3_evm_config;
 	omap_board_config_size = ARRAY_SIZE(omap3_evm_config);
-	omap2_init_common_hw(mt46h32m32lf6_sdrc_params, NULL);
+	omap2_init_common_infrastructure();
+	omap2_init_common_devices(mt46h32m32lf6_sdrc_params, NULL);
 	omap_init_irq();
-	omap_gpio_init();
 }
 
 static struct platform_device *omap3_evm_devices[] __initdata = {
@@ -654,8 +660,6 @@ static struct omap_board_mux board_mux[]
 				OMAP_PIN_OFF_INPUT_PULLUP | OMAP_PIN_OFF_OUTPUT_LOW),
 	{ .reg_offset = OMAP_MUX_TERMINATOR },
 };
-#else
-#define board_mux	NULL
 #endif
 
 static struct omap_musb_board_data musb_board_data = {
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/board-omap3logic.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/board-omap3logic.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/board-omap3logic.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/board-omap3logic.c	2011-03-14 21:20:32.000000000 -0400
@@ -197,17 +197,15 @@ static inline void __init board_smsc911x
 
 static void __init omap3logic_init_irq(void)
 {
-	omap2_init_common_hw(NULL, NULL);
+	omap2_init_common_infrastructure();
+	omap2_init_common_devices(NULL, NULL);
 	omap_init_irq();
-	omap_gpio_init();
 }
 
 #ifdef CONFIG_OMAP_MUX
 static struct omap_board_mux board_mux[] __initdata = {
 	{ .reg_offset = OMAP_MUX_TERMINATOR },
 };
-#else
-#define board_mux       NULL
 #endif
 
 static void __init omap3logic_init(void)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/board-omap3pandora.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/board-omap3pandora.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/board-omap3pandora.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/board-omap3pandora.c	2011-03-14 21:20:32.000000000 -0400
@@ -293,7 +293,7 @@ static struct omap2_hsmmc_info omap3pand
 	},
 	{
 		.mmc		= 3,
-		.caps		= MMC_CAP_4_BIT_DATA,
+		.caps		= MMC_CAP_4_BIT_DATA | MMC_CAP_POWER_OFF_CARD,
 		.gpio_cd	= -EINVAL,
 		.gpio_wp	= -EINVAL,
 		.init_card	= pandora_wl1251_init_card,
@@ -636,37 +636,19 @@ static struct spi_board_info omap3pandor
 
 static void __init omap3pandora_init_irq(void)
 {
-	omap2_init_common_hw(mt46h32m32lf6_sdrc_params,
-			     mt46h32m32lf6_sdrc_params);
+	omap2_init_common_infrastructure();
+	omap2_init_common_devices(mt46h32m32lf6_sdrc_params,
+				  mt46h32m32lf6_sdrc_params);
 	omap_init_irq();
-	omap_gpio_init();
 }
 
-static void pandora_wl1251_set_power(bool enable)
-{
-	/*
-	 * Keep power always on until wl1251_sdio driver learns to re-init
-	 * the chip after powering it down and back up.
-	 */
-}
-
-static struct wl12xx_platform_data pandora_wl1251_pdata = {
-	.set_power	= pandora_wl1251_set_power,
-	.use_eeprom	= true,
-};
-
-static struct platform_device pandora_wl1251_data = {
-	.name           = "wl1251_data",
-	.id             = -1,
-	.dev		= {
-		.platform_data	= &pandora_wl1251_pdata,
-	},
-};
-
-static void pandora_wl1251_init(void)
+static void __init pandora_wl1251_init(void)
 {
+	struct wl12xx_platform_data pandora_wl1251_pdata;
 	int ret;
 
+	memset(&pandora_wl1251_pdata, 0, sizeof(pandora_wl1251_pdata));
+
 	ret = gpio_request(PANDORA_WIFI_IRQ_GPIO, "wl1251 irq");
 	if (ret < 0)
 		goto fail;
@@ -679,6 +661,11 @@ static void pandora_wl1251_init(void)
 	if (pandora_wl1251_pdata.irq < 0)
 		goto fail_irq;
 
+	pandora_wl1251_pdata.use_eeprom = true;
+	ret = wl12xx_set_platform_data(&pandora_wl1251_pdata);
+	if (ret < 0)
+		goto fail_irq;
+
 	return;
 
 fail_irq:
@@ -691,7 +678,6 @@ static struct platform_device *omap3pand
 	&pandora_leds_gpio,
 	&pandora_keys_gpio,
 	&pandora_dss_device,
-	&pandora_wl1251_data,
 	&pandora_vwlan_device,
 };
 
@@ -711,8 +697,6 @@ static const struct ehci_hcd_omap_platfo
 static struct omap_board_mux board_mux[] __initdata = {
 	{ .reg_offset = OMAP_MUX_TERMINATOR },
 };
-#else
-#define board_mux	NULL
 #endif
 
 static struct omap_musb_board_data musb_board_data = {
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/board-omap3stalker.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/board-omap3stalker.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/board-omap3stalker.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/board-omap3stalker.c	2011-03-14 21:20:32.000000000 -0400
@@ -40,6 +40,7 @@
 #include <plat/nand.h>
 #include <plat/usb.h>
 #include <plat/display.h>
+#include <plat/panel-generic-dpi.h>
 
 #include <plat/mcspi.h>
 #include <linux/input/matrix_keypad.h>
@@ -160,13 +161,18 @@ static void omap3_stalker_disable_lcd(st
 	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_panel",
+	.driver_name		= "generic_dpi_panel",
+	.data			= &lcd_panel,
 	.phy.dpi.data_lines	= 24,
 	.type			= OMAP_DISPLAY_TYPE_DPI,
-	.platform_enable	= omap3_stalker_enable_lcd,
-	.platform_disable	= omap3_stalker_disable_lcd,
 };
 
 static int omap3_stalker_enable_tv(struct omap_dss_device *dssdev)
@@ -208,13 +214,18 @@ static void omap3_stalker_disable_dvi(st
 	dvi_enabled = 0;
 }
 
+static struct panel_generic_dpi_data dvi_panel = {
+	.name			= "generic",
+	.platform_enable	= omap3_stalker_enable_dvi,
+	.platform_disable	= omap3_stalker_disable_dvi,
+};
+
 static struct omap_dss_device omap3_stalker_dvi_device = {
 	.name			= "dvi",
-	.driver_name		= "generic_panel",
 	.type			= OMAP_DISPLAY_TYPE_DPI,
+	.driver_name		= "generic_dpi_panel",
+	.data			= &dvi_panel,
 	.phy.dpi.data_lines	= 24,
-	.platform_enable	= omap3_stalker_enable_dvi,
-	.platform_disable	= omap3_stalker_disable_dvi,
 };
 
 static struct omap_dss_device *omap3_stalker_dss_devices[] = {
@@ -584,12 +595,12 @@ static void __init omap3_stalker_init_ir
 {
 	omap_board_config = omap3_stalker_config;
 	omap_board_config_size = ARRAY_SIZE(omap3_stalker_config);
-	omap2_init_common_hw(mt46h32m32lf6_sdrc_params, NULL);
+	omap2_init_common_infrastructure();
+	omap2_init_common_devices(mt46h32m32lf6_sdrc_params, NULL);
 	omap_init_irq();
 #ifdef CONFIG_OMAP_32K_TIMER
 	omap2_gp_clockevent_set_gptimer(12);
 #endif
-	omap_gpio_init();
 }
 
 static struct platform_device *omap3_stalker_devices[] __initdata = {
@@ -616,8 +627,6 @@ static struct omap_board_mux board_mux[]
 		  OMAP_PIN_OFF_INPUT_PULLUP | OMAP_PIN_OFF_WAKEUPENABLE),
 	{.reg_offset = OMAP_MUX_TERMINATOR},
 };
-#else
-#define board_mux	NULL
 #endif
 
 static struct omap_musb_board_data musb_board_data = {
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/board-omap3touchbook.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/board-omap3touchbook.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/board-omap3touchbook.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/board-omap3touchbook.c	2011-03-14 21:20:32.000000000 -0400
@@ -413,8 +413,6 @@ static struct omap_board_config_kernel o
 static struct omap_board_mux board_mux[] __initdata = {
 	{ .reg_offset = OMAP_MUX_TERMINATOR },
 };
-#else
-#define board_mux	NULL
 #endif
 
 static void __init omap3_touchbook_init_irq(void)
@@ -422,13 +420,13 @@ static void __init omap3_touchbook_init_
 	omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
 	omap_board_config = omap3_touchbook_config;
 	omap_board_config_size = ARRAY_SIZE(omap3_touchbook_config);
-	omap2_init_common_hw(mt46h32m32lf6_sdrc_params,
-			     mt46h32m32lf6_sdrc_params);
+	omap2_init_common_infrastructure();
+	omap2_init_common_devices(mt46h32m32lf6_sdrc_params,
+				  mt46h32m32lf6_sdrc_params);
 	omap_init_irq();
 #ifdef CONFIG_OMAP_32K_TIMER
 	omap2_gp_clockevent_set_gptimer(12);
 #endif
-	omap_gpio_init();
 }
 
 static struct platform_device *omap3_touchbook_devices[] __initdata = {
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/board-omap4panda.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/board-omap4panda.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/board-omap4panda.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/board-omap4panda.c	2011-03-14 21:20:32.000000000 -0400
@@ -19,6 +19,7 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
+#include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/leds.h>
 #include <linux/gpio.h>
@@ -40,6 +41,7 @@
 
 #include "hsmmc.h"
 #include "control.h"
+#include "mux.h"
 
 #define GPIO_HUB_POWER		1
 #define GPIO_HUB_NRESET		62
@@ -76,9 +78,9 @@ static struct platform_device *panda_dev
 
 static void __init omap4_panda_init_irq(void)
 {
-	omap2_init_common_hw(NULL, NULL);
+	omap2_init_common_infrastructure();
+	omap2_init_common_devices(NULL, NULL);
 	gic_init_irq();
-	omap_gpio_init();
 }
 
 static const struct ehci_hcd_omap_platform_data ehci_pdata __initconst = {
@@ -94,7 +96,16 @@ static const struct ehci_hcd_omap_platfo
 static void __init omap4_ehci_init(void)
 {
 	int ret;
+	struct clk *phy_ref_clk;
 
+	/* FREF_CLK3 provides the 19.2 MHz reference clock to the PHY */
+	phy_ref_clk = clk_get(NULL, "auxclk3_ck");
+	if (IS_ERR(phy_ref_clk)) {
+		pr_err("Cannot request auxclk3\n");
+		goto error1;
+	}
+	clk_set_rate(phy_ref_clk, 19200000);
+	clk_enable(phy_ref_clk);
 
 	/* disable the power to the usb hub prior to init */
 	ret = gpio_request(GPIO_HUB_POWER, "hub_power");
@@ -133,15 +144,23 @@ error1:
 
 static struct omap_musb_board_data musb_board_data = {
 	.interface_type		= MUSB_INTERFACE_UTMI,
-	.mode			= MUSB_PERIPHERAL,
+	.mode			= MUSB_OTG,
 	.power			= 100,
 };
 
+static struct twl4030_usb_data omap4_usbphy_data = {
+	.phy_init	= omap4430_phy_init,
+	.phy_exit	= omap4430_phy_exit,
+	.phy_power	= omap4430_phy_power,
+	.phy_set_clock	= omap4430_phy_set_clk,
+};
+
 static struct omap2_hsmmc_info mmc[] = {
 	{
 		.mmc		= 1,
 		.caps		= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
 		.gpio_wp	= -EINVAL,
+		.gpio_cd	= -EINVAL,
 	},
 	{}	/* Terminator */
 };
@@ -345,6 +364,7 @@ static struct twl4030_platform_data omap
 	.vaux1		= &omap4_panda_vaux1,
 	.vaux2		= &omap4_panda_vaux2,
 	.vaux3		= &omap4_panda_vaux3,
+	.usb		= &omap4_usbphy_data,
 };
 
 static struct i2c_board_info __initdata omap4_panda_i2c_boardinfo[] = {
@@ -368,18 +388,29 @@ static int __init omap4_panda_i2c_init(v
 	omap_register_i2c_bus(4, 400, NULL, 0);
 	return 0;
 }
+
+#ifdef CONFIG_OMAP_MUX
+static struct omap_board_mux board_mux[] __initdata = {
+	{ .reg_offset = OMAP_MUX_TERMINATOR },
+};
+#else
+#define board_mux	NULL
+#endif
+
 static void __init omap4_panda_init(void)
 {
+	int package = OMAP_PACKAGE_CBS;
+
+	if (omap_rev() == OMAP4430_REV_ES1_0)
+		package = OMAP_PACKAGE_CBL;
+	omap4_mux_init(board_mux, package);
+
 	omap4_panda_i2c_init();
 	platform_add_devices(panda_devices, ARRAY_SIZE(panda_devices));
 	omap_serial_init();
 	omap4_twl6030_hsmmc_init(mmc);
-	/* OMAP4 Panda uses internal transceiver so register nop transceiver */
-	usb_nop_xceiv_register();
 	omap4_ehci_init();
-	/* FIXME: allow multi-omap to boot until musb is updated for omap4 */
-	if (!cpu_is_omap44xx())
-		usb_musb_init(&musb_board_data);
+	usb_musb_init(&musb_board_data);
 }
 
 static void __init omap4_panda_map_io(void)
@@ -391,6 +422,7 @@ static void __init omap4_panda_map_io(vo
 MACHINE_START(OMAP4_PANDA, "OMAP4 Panda board")
 	/* Maintainer: David Anders - Texas Instruments Inc */
 	.boot_params	= 0x80000100,
+	.reserve	= omap_reserve,
 	.map_io		= omap4_panda_map_io,
 	.init_irq	= omap4_panda_init_irq,
 	.init_machine	= omap4_panda_init,
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/board-overo.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/board-overo.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/board-overo.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/board-overo.c	2011-03-14 21:20:32.000000000 -0400
@@ -413,10 +413,10 @@ static void __init overo_init_irq(void)
 {
 	omap_board_config = overo_config;
 	omap_board_config_size = ARRAY_SIZE(overo_config);
-	omap2_init_common_hw(mt46h32m32lf6_sdrc_params,
-			     mt46h32m32lf6_sdrc_params);
+	omap2_init_common_infrastructure();
+	omap2_init_common_devices(mt46h32m32lf6_sdrc_params,
+				  mt46h32m32lf6_sdrc_params);
 	omap_init_irq();
-	omap_gpio_init();
 }
 
 static struct platform_device *overo_devices[] __initdata = {
@@ -438,8 +438,6 @@ static const struct ehci_hcd_omap_platfo
 static struct omap_board_mux board_mux[] __initdata = {
 	{ .reg_offset = OMAP_MUX_TERMINATOR },
 };
-#else
-#define board_mux	NULL
 #endif
 
 static struct omap_musb_board_data musb_board_data = {
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/board-rm680.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/board-rm680.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/board-rm680.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/board-rm680.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,184 @@
+/*
+ * Board support file for Nokia RM-680.
+ *
+ * Copyright (C) 2010 Nokia
+ *
+ * This program is free software; you can 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/i2c.h>
+#include <linux/gpio.h>
+#include <linux/init.h>
+#include <linux/i2c/twl.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/fixed.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/consumer.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach-types.h>
+
+#include <plat/i2c.h>
+#include <plat/mmc.h>
+#include <plat/usb.h>
+#include <plat/gpmc.h>
+#include <plat/common.h>
+#include <plat/onenand.h>
+
+#include "mux.h"
+#include "hsmmc.h"
+#include "sdram-nokia.h"
+
+static struct regulator_consumer_supply rm680_vemmc_consumers[] = {
+	REGULATOR_SUPPLY("vmmc", "mmci-omap-hs.1"),
+};
+
+/* Fixed regulator for internal eMMC */
+static struct regulator_init_data rm680_vemmc = {
+	.constraints =	{
+		.name			= "rm680_vemmc",
+		.valid_modes_mask	= REGULATOR_MODE_NORMAL
+					| REGULATOR_MODE_STANDBY,
+		.valid_ops_mask		= REGULATOR_CHANGE_STATUS
+					| REGULATOR_CHANGE_MODE,
+	},
+	.num_consumer_supplies		= ARRAY_SIZE(rm680_vemmc_consumers),
+	.consumer_supplies		= rm680_vemmc_consumers,
+};
+
+static struct fixed_voltage_config rm680_vemmc_config = {
+	.supply_name		= "VEMMC",
+	.microvolts		= 2900000,
+	.gpio			= 157,
+	.startup_delay		= 150,
+	.enable_high		= 1,
+	.init_data		= &rm680_vemmc,
+};
+
+static struct platform_device rm680_vemmc_device = {
+	.name			= "reg-fixed-voltage",
+	.dev			= {
+		.platform_data	= &rm680_vemmc_config,
+	},
+};
+
+static struct platform_device *rm680_peripherals_devices[] __initdata = {
+	&rm680_vemmc_device,
+};
+
+/* TWL */
+static struct twl4030_gpio_platform_data rm680_gpio_data = {
+	.gpio_base		= OMAP_MAX_GPIO_LINES,
+	.irq_base		= TWL4030_GPIO_IRQ_BASE,
+	.irq_end		= TWL4030_GPIO_IRQ_END,
+	.pullups		= BIT(0),
+	.pulldowns		= BIT(1) | BIT(2) | BIT(8) | BIT(15),
+};
+
+static struct twl4030_usb_data rm680_usb_data = {
+	.usb_mode		= T2_USB_MODE_ULPI,
+};
+
+static struct twl4030_platform_data rm680_twl_data = {
+	.irq_base		= TWL4030_IRQ_BASE,
+	.irq_end		= TWL4030_IRQ_END,
+	.gpio			= &rm680_gpio_data,
+	.usb			= &rm680_usb_data,
+	/* add rest of the children here */
+};
+
+static struct i2c_board_info __initdata rm680_twl_i2c_board_info[] = {
+	{
+		I2C_BOARD_INFO("twl5031", 0x48),
+		.flags		= I2C_CLIENT_WAKE,
+		.irq		= INT_34XX_SYS_NIRQ,
+		.platform_data	= &rm680_twl_data,
+	},
+};
+
+static void __init rm680_i2c_init(void)
+{
+	omap_register_i2c_bus(1, 2900, rm680_twl_i2c_board_info,
+				ARRAY_SIZE(rm680_twl_i2c_board_info));
+	omap_register_i2c_bus(2, 400, NULL, 0);
+	omap_register_i2c_bus(3, 400, NULL, 0);
+}
+
+#if defined(CONFIG_MTD_ONENAND_OMAP2) || \
+	defined(CONFIG_MTD_ONENAND_OMAP2_MODULE)
+static struct omap_onenand_platform_data board_onenand_data[] = {
+	{
+		.gpio_irq	= 65,
+		.flags		= ONENAND_SYNC_READWRITE,
+	}
+};
+#endif
+
+/* eMMC */
+static struct omap2_hsmmc_info mmc[] __initdata = {
+	{
+		.name		= "internal",
+		.mmc		= 2,
+		.caps		= MMC_CAP_4_BIT_DATA | MMC_CAP_MMC_HIGHSPEED,
+		.gpio_cd	= -EINVAL,
+		.gpio_wp	= -EINVAL,
+	},
+	{ /* Terminator */ }
+};
+
+static void __init rm680_peripherals_init(void)
+{
+	platform_add_devices(rm680_peripherals_devices,
+				ARRAY_SIZE(rm680_peripherals_devices));
+	rm680_i2c_init();
+	gpmc_onenand_init(board_onenand_data);
+	omap2_hsmmc_init(mmc);
+}
+
+static void __init rm680_init_irq(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);
+	omap_init_irq();
+}
+
+#ifdef CONFIG_OMAP_MUX
+static struct omap_board_mux board_mux[] __initdata = {
+	{ .reg_offset = OMAP_MUX_TERMINATOR },
+};
+#endif
+
+static struct omap_musb_board_data rm680_musb_data = {
+	.interface_type	= MUSB_INTERFACE_ULPI,
+	.mode		= MUSB_PERIPHERAL,
+	.power		= 100,
+};
+
+static void __init rm680_init(void)
+{
+	omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
+	omap_serial_init();
+	usb_musb_init(&rm680_musb_data);
+	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,
+	.map_io		= rm680_map_io,
+	.reserve	= omap_reserve,
+	.init_irq	= rm680_init_irq,
+	.init_machine	= rm680_init,
+	.timer		= &omap_timer,
+MACHINE_END
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/board-rx51.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/board-rx51.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/board-rx51.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/board-rx51.c	2011-03-14 21:20:32.000000000 -0400
@@ -32,10 +32,10 @@
 
 #include "mux.h"
 #include "pm.h"
+#include "sdram-nokia.h"
 
 #define RX51_GPIO_SLEEP_IND 162
 
-struct omap_sdrc_params *rx51_get_sdram_timings(void);
 extern void rx51_video_mem_init(void);
 
 static struct gpio_led gpio_leds[] = {
@@ -105,10 +105,10 @@ static void __init rx51_init_irq(void)
 	omap_board_config = rx51_config;
 	omap_board_config_size = ARRAY_SIZE(rx51_config);
 	omap3_pm_init_cpuidle(rx51_cpuidle_params);
-	sdrc_params = rx51_get_sdram_timings();
-	omap2_init_common_hw(sdrc_params, sdrc_params);
+	omap2_init_common_infrastructure();
+	sdrc_params = nokia_get_sdram_timings();
+	omap2_init_common_devices(sdrc_params, sdrc_params);
 	omap_init_irq();
-	omap_gpio_init();
 }
 
 extern void __init rx51_peripherals_init(void);
@@ -117,8 +117,6 @@ extern void __init rx51_peripherals_init
 static struct omap_board_mux board_mux[] __initdata = {
 	{ .reg_offset = OMAP_MUX_TERMINATOR },
 };
-#else
-#define board_mux	NULL
 #endif
 
 static struct omap_musb_board_data musb_board_data = {
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/board-rx51-peripherals.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/board-rx51-peripherals.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/board-rx51-peripherals.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/board-rx51-peripherals.c	2011-03-14 21:20:32.000000000 -0400
@@ -23,7 +23,6 @@
 #include <linux/gpio.h>
 #include <linux/gpio_keys.h>
 #include <linux/mmc/host.h>
-#include <sound/tlv320aic3x.h>
 
 #include <plat/mcspi.h>
 #include <plat/board.h>
@@ -293,6 +292,8 @@ static struct omap_board_mux rx51_mmc2_o
 	{ .reg_offset = OMAP_MUX_TERMINATOR },
 };
 
+static struct omap_mux_partition *partition;
+
 /*
  * Current flows to eMMC when eMMC is off and the data lines are pulled up,
  * so pull them down. N.B. we pull 8 lines because we are using 8 lines.
@@ -300,9 +301,9 @@ static struct omap_board_mux rx51_mmc2_o
 static void rx51_mmc2_remux(struct device *dev, int slot, int power_on)
 {
 	if (power_on)
-		omap_mux_write_array(rx51_mmc2_on_mux);
+		omap_mux_write_array(partition, rx51_mmc2_on_mux);
 	else
-		omap_mux_write_array(rx51_mmc2_off_mux);
+		omap_mux_write_array(partition, rx51_mmc2_off_mux);
 }
 
 static struct omap2_hsmmc_info mmc[] __initdata = {
@@ -342,6 +343,8 @@ static struct regulator_consumer_supply
 	/* tlv320aic3x analog supplies */
 	REGULATOR_SUPPLY("AVDD", "2-0018"),
 	REGULATOR_SUPPLY("DRVDD", "2-0018"),
+	REGULATOR_SUPPLY("AVDD", "2-0019"),
+	REGULATOR_SUPPLY("DRVDD", "2-0019"),
 	/* tpa6130a2 */
 	REGULATOR_SUPPLY("Vdd", "2-0060"),
 	/* Keep vmmc as last item. It is not iterated for newer boards */
@@ -352,19 +355,16 @@ static struct regulator_consumer_supply
 	/* tlv320aic3x digital supplies */
 	REGULATOR_SUPPLY("IOVDD", "2-0018"),
 	REGULATOR_SUPPLY("DVDD", "2-0018"),
+	REGULATOR_SUPPLY("IOVDD", "2-0019"),
+	REGULATOR_SUPPLY("DVDD", "2-0019"),
 };
 
-#if defined(CONFIG_FB_OMAP2) || defined(CONFIG_FB_OMAP2_MODULE)
-extern struct platform_device rx51_display_device;
-#endif
-
 static struct regulator_consumer_supply rx51_vaux1_consumers[] = {
-#if defined(CONFIG_FB_OMAP2) || defined(CONFIG_FB_OMAP2_MODULE)
-	{
-		.supply	= "vdds_sdi",
-		.dev	= &rx51_display_device.dev,
-	},
-#endif
+	REGULATOR_SUPPLY("vdds_sdi", "omapdss"),
+};
+
+static struct regulator_consumer_supply rx51_vdac_supply[] = {
+	REGULATOR_SUPPLY("vdda_dac", "omapdss"),
 };
 
 static struct regulator_init_data rx51_vaux1 = {
@@ -484,14 +484,17 @@ static struct regulator_init_data rx51_v
 
 static struct regulator_init_data rx51_vdac = {
 	.constraints = {
+		.name			= "VDAC",
 		.min_uV			= 1800000,
 		.max_uV			= 1800000,
+		.apply_uV		= true,
 		.valid_modes_mask	= REGULATOR_MODE_NORMAL
 					| REGULATOR_MODE_STANDBY,
-		.valid_ops_mask		= REGULATOR_CHANGE_VOLTAGE
-					| REGULATOR_CHANGE_MODE
+		.valid_ops_mask		= REGULATOR_CHANGE_MODE
 					| REGULATOR_CHANGE_STATUS,
 	},
+	.num_consumer_supplies	= 1,
+	.consumer_supplies	= rx51_vdac_supply,
 };
 
 static struct regulator_init_data rx51_vio = {
@@ -717,7 +720,7 @@ static struct twl4030_platform_data rx51
 	.vio			= &rx51_vio,
 };
 
-static struct tpa6130a2_platform_data rx51_tpa6130a2_data __initdata = {
+static struct tpa6130a2_platform_data rx51_tpa6130a2_data __initdata_or_module = {
 	.id			= TPA6130A2,
 	.power_gpio		= 98,
 };
@@ -742,11 +745,19 @@ static struct aic3x_pdata rx51_aic3x_dat
 	.gpio_reset = 60,
 };
 
+static struct aic3x_pdata rx51_aic3x_data2 = {
+	.gpio_reset = 60,
+};
+
 static struct i2c_board_info __initdata rx51_peripherals_i2c_board_info_2[] = {
 	{
 		I2C_BOARD_INFO("tlv320aic3x", 0x18),
 		.platform_data = &rx51_aic3x_data,
 	},
+	{
+		I2C_BOARD_INFO("tlv320aic3x", 0x19),
+		.platform_data = &rx51_aic3x_data2,
+	},
 #if defined(CONFIG_SENSORS_TSL2563) || defined(CONFIG_SENSORS_TSL2563_MODULE)
 	{
 		I2C_BOARD_INFO("tsl2563", 0x29),
@@ -815,25 +826,15 @@ static struct mtd_partition onenand_part
 	},
 };
 
-static struct omap_onenand_platform_data board_onenand_data = {
-	.cs		= 0,
-	.gpio_irq	= 65,
-	.parts		= onenand_partitions,
-	.nr_parts	= ARRAY_SIZE(onenand_partitions),
-	.flags		= ONENAND_SYNC_READWRITE,
+static struct omap_onenand_platform_data board_onenand_data[] = {
+	{
+		.cs		= 0,
+		.gpio_irq	= 65,
+		.parts		= onenand_partitions,
+		.nr_parts	= ARRAY_SIZE(onenand_partitions),
+		.flags		= ONENAND_SYNC_READWRITE,
+	}
 };
-
-static void __init board_onenand_init(void)
-{
-	gpmc_onenand_init(&board_onenand_data);
-}
-
-#else
-
-static inline void board_onenand_init(void)
-{
-}
-
 #endif
 
 #if defined(CONFIG_SMC91X) || defined(CONFIG_SMC91X_MODULE)
@@ -916,13 +917,17 @@ error:
 void __init rx51_peripherals_init(void)
 {
 	rx51_i2c_init();
-	board_onenand_init();
+	gpmc_onenand_init(board_onenand_data);
 	board_smc91x_init();
 	rx51_add_gpio_keys();
 	rx51_init_wl1251();
 	spi_register_board_info(rx51_peripherals_spi_board_info,
 				ARRAY_SIZE(rx51_peripherals_spi_board_info));
-	omap2_hsmmc_init(mmc);
+
+	partition = omap_mux_get("core");
+	if (partition)
+		omap2_hsmmc_init(mmc);
+
 	platform_device_register(&rx51_charger_device);
 }
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/board-rx51-sdram.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/board-rx51-sdram.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/board-rx51-sdram.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/board-rx51-sdram.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,221 +0,0 @@
-/*
- * SDRC register values for RX51
- *
- * Copyright (C) 2008 Nokia Corporation
- *
- * Lauri Leukkunen <lauri.leukkunen@nokia.com>
- *
- * Original code by Juha Yrjola <juha.yrjola@solidboot.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/clk.h>
-#include <linux/err.h>
-#include <linux/io.h>
-
-#include <plat/io.h>
-#include <plat/common.h>
-#include <plat/clock.h>
-#include <plat/sdrc.h>
-
-
-/* In picoseconds, except for tREF (ns), tXP, tCKE, tWTR (clks) */
-struct sdram_timings {
-	u32 casl;
-	u32 tDAL;
-	u32 tDPL;
-	u32 tRRD;
-	u32 tRCD;
-	u32 tRP;
-	u32 tRAS;
-	u32 tRC;
-	u32 tRFC;
-	u32 tXSR;
-
-	u32 tREF; /* in ns */
-
-	u32 tXP;
-	u32 tCKE;
-	u32 tWTR;
-};
-
-static struct omap_sdrc_params rx51_sdrc_params[4];
-
-static const struct sdram_timings rx51_timings[] = {
-	{
-		.casl = 3,
-		.tDAL = 33000,
-		.tDPL = 15000,
-		.tRRD = 12000,
-		.tRCD = 22500,
-		.tRP = 18000,
-		.tRAS = 42000,
-		.tRC = 66000,
-		.tRFC = 138000,
-		.tXSR = 200000,
-
-		.tREF = 7800,
-
-		.tXP = 2,
-		.tCKE = 2,
-		.tWTR = 2
-	},
-};
-
-static unsigned long sdrc_get_fclk_period(long rate)
-{
-	/* In picoseconds */
-	return 1000000000 / rate;
-}
-
-static unsigned int sdrc_ps_to_ticks(unsigned int time_ps, long rate)
-{
-	unsigned long tick_ps;
-
-	/* Calculate in picosecs to yield more exact results */
-	tick_ps = sdrc_get_fclk_period(rate);
-
-	return (time_ps + tick_ps - 1) / tick_ps;
-}
-#undef DEBUG
-#ifdef DEBUG
-static int set_sdrc_timing_regval(u32 *regval, int st_bit, int end_bit,
-				int ticks, long rate, const char *name)
-#else
-static int set_sdrc_timing_regval(u32 *regval, int st_bit, int end_bit,
-			       int ticks)
-#endif
-{
-	int mask, nr_bits;
-
-	nr_bits = end_bit - st_bit + 1;
-	if (ticks >= 1 << nr_bits)
-		return -1;
-	mask = (1 << nr_bits) - 1;
-	*regval &= ~(mask << st_bit);
-	*regval |= ticks << st_bit;
-#ifdef DEBUG
-	printk(KERN_INFO "SDRC %s: %i ticks %i ns\n", name, ticks,
-			(unsigned int)sdrc_get_fclk_period(rate) * ticks /
-			1000);
-#endif
-
-	return 0;
-}
-
-#ifdef DEBUG
-#define SDRC_SET_ONE(reg, st, end, field, rate) \
-	if (set_sdrc_timing_regval((reg), (st), (end), \
-			rx51_timings->field, (rate), #field) < 0) \
-		err = -1;
-#else
-#define SDRC_SET_ONE(reg, st, end, field, rate) \
-	if (set_sdrc_timing_regval((reg), (st), (end), \
-			rx51_timings->field) < 0) \
-		err = -1;
-#endif
-
-#ifdef DEBUG
-static int set_sdrc_timing_regval_ps(u32 *regval, int st_bit, int end_bit,
-				int time, long rate, const char *name)
-#else
-static int set_sdrc_timing_regval_ps(u32 *regval, int st_bit, int end_bit,
-				int time, long rate)
-#endif
-{
-	int ticks, ret;
-	ret = 0;
-
-	if (time == 0)
-		ticks = 0;
-	else
-		ticks = sdrc_ps_to_ticks(time, rate);
-
-#ifdef DEBUG
-	ret = set_sdrc_timing_regval(regval, st_bit, end_bit, ticks,
-				     rate, name);
-#else
-	ret = set_sdrc_timing_regval(regval, st_bit, end_bit, ticks);
-#endif
-
-	return ret;
-}
-
-#ifdef DEBUG
-#define SDRC_SET_ONE_PS(reg, st, end, field, rate) \
-	if (set_sdrc_timing_regval_ps((reg), (st), (end), \
-			rx51_timings->field, \
-			(rate), #field) < 0) \
-		err = -1;
-
-#else
-#define SDRC_SET_ONE_PS(reg, st, end, field, rate) \
-	if (set_sdrc_timing_regval_ps((reg), (st), (end), \
-			rx51_timings->field, (rate)) < 0) \
-		err = -1;
-#endif
-
-static int sdrc_timings(int id, long rate)
-{
-	u32 ticks_per_ms;
-	u32 rfr, l;
-	u32 actim_ctrla = 0, actim_ctrlb = 0;
-	u32 rfr_ctrl;
-	int err = 0;
-	long l3_rate = rate / 1000;
-
-	SDRC_SET_ONE_PS(&actim_ctrla,  0,  4, tDAL, l3_rate);
-	SDRC_SET_ONE_PS(&actim_ctrla,  6,  8, tDPL, l3_rate);
-	SDRC_SET_ONE_PS(&actim_ctrla,  9, 11, tRRD, l3_rate);
-	SDRC_SET_ONE_PS(&actim_ctrla, 12, 14, tRCD, l3_rate);
-	SDRC_SET_ONE_PS(&actim_ctrla, 15, 17, tRP, l3_rate);
-	SDRC_SET_ONE_PS(&actim_ctrla, 18, 21, tRAS, l3_rate);
-	SDRC_SET_ONE_PS(&actim_ctrla, 22, 26, tRC, l3_rate);
-	SDRC_SET_ONE_PS(&actim_ctrla, 27, 31, tRFC, l3_rate);
-
-	SDRC_SET_ONE_PS(&actim_ctrlb,  0,  7, tXSR, l3_rate);
-
-	SDRC_SET_ONE(&actim_ctrlb,  8, 10, tXP, l3_rate);
-	SDRC_SET_ONE(&actim_ctrlb, 12, 14, tCKE, l3_rate);
-	SDRC_SET_ONE(&actim_ctrlb, 16, 17, tWTR, l3_rate);
-
-	ticks_per_ms = l3_rate;
-	rfr = rx51_timings[0].tREF * ticks_per_ms / 1000000;
-	if (rfr > 65535 + 50)
-		rfr = 65535;
-	else
-		rfr -= 50;
-
-#ifdef DEBUG
-	printk(KERN_INFO "SDRC tREF: %i ticks\n", rfr);
-#endif
-
-	l = rfr << 8;
-	rfr_ctrl = l | 0x1; /* autorefresh, reload counter with 1xARCV */
-
-	rx51_sdrc_params[id].rate = rate;
-	rx51_sdrc_params[id].actim_ctrla = actim_ctrla;
-	rx51_sdrc_params[id].actim_ctrlb = actim_ctrlb;
-	rx51_sdrc_params[id].rfr_ctrl = rfr_ctrl;
-	rx51_sdrc_params[id].mr = 0x32;
-
-	rx51_sdrc_params[id + 1].rate = 0;
-
-	return err;
-}
-
-struct omap_sdrc_params *rx51_get_sdram_timings(void)
-{
-	int err;
-
-	err = sdrc_timings(0, 41500000);
-	err |= sdrc_timings(1, 83000000);
-	err |= sdrc_timings(2, 166000000);
-
-	return &rx51_sdrc_params[0];
-}
-
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/board-rx51-video.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/board-rx51-video.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/board-rx51-video.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/board-rx51-video.c	2011-03-14 21:20:32.000000000 -0400
@@ -14,7 +14,6 @@
 #include <linux/gpio.h>
 #include <linux/spi/spi.h>
 #include <linux/mm.h>
-
 #include <asm/mach-types.h>
 #include <plat/display.h>
 #include <plat/vram.h>
@@ -49,8 +48,16 @@ static struct omap_dss_device rx51_lcd_d
 	.platform_disable	= rx51_lcd_disable,
 };
 
+static struct omap_dss_device  rx51_tv_device = {
+	.name			= "tv",
+	.type			= OMAP_DISPLAY_TYPE_VENC,
+	.driver_name		= "venc",
+	.phy.venc.type	        = OMAP_DSS_VENC_TYPE_COMPOSITE,
+};
+
 static struct omap_dss_device *rx51_dss_devices[] = {
 	&rx51_lcd_device,
+	&rx51_tv_device,
 };
 
 static struct omap_dss_board_info rx51_dss_board_info = {
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/board-zoom2.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/board-zoom2.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/board-zoom2.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/board-zoom2.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,117 +0,0 @@
-/*
- * Copyright (C) 2009 Texas Instruments Inc.
- * Mikkel Christensen <mlc@ti.com>
- *
- * Modified from mach-omap2/board-ldp.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/kernel.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/input.h>
-#include <linux/gpio.h>
-#include <linux/i2c/twl.h>
-
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-
-#include <plat/common.h>
-#include <plat/board.h>
-
-#include <mach/board-zoom.h>
-
-#include "board-flash.h"
-#include "mux.h"
-#include "sdram-micron-mt46h32m32lf-6.h"
-
-static void __init omap_zoom2_init_irq(void)
-{
-	omap2_init_common_hw(mt46h32m32lf6_sdrc_params,
-				 mt46h32m32lf6_sdrc_params);
-	omap_init_irq();
-	omap_gpio_init();
-}
-
-#ifdef CONFIG_OMAP_MUX
-static struct omap_board_mux board_mux[] __initdata = {
-	/* WLAN IRQ - GPIO 162 */
-	OMAP3_MUX(MCBSP1_CLKX, OMAP_MUX_MODE4 | OMAP_PIN_INPUT_PULLUP),
-	/* WLAN POWER ENABLE - GPIO 101 */
-	OMAP3_MUX(CAM_D2, OMAP_MUX_MODE4 | OMAP_PIN_OUTPUT),
-	/* WLAN SDIO: MMC3 CMD */
-	OMAP3_MUX(MCSPI1_CS1, OMAP_MUX_MODE3 | OMAP_PIN_INPUT_PULLUP),
-	/* WLAN SDIO: MMC3 CLK */
-	OMAP3_MUX(ETK_CLK, OMAP_MUX_MODE2 | OMAP_PIN_INPUT_PULLUP),
-	/* WLAN SDIO: MMC3 DAT[0-3] */
-	OMAP3_MUX(ETK_D3, OMAP_MUX_MODE2 | OMAP_PIN_INPUT_PULLUP),
-	OMAP3_MUX(ETK_D4, OMAP_MUX_MODE2 | OMAP_PIN_INPUT_PULLUP),
-	OMAP3_MUX(ETK_D5, OMAP_MUX_MODE2 | OMAP_PIN_INPUT_PULLUP),
-	OMAP3_MUX(ETK_D6, OMAP_MUX_MODE2 | OMAP_PIN_INPUT_PULLUP),
-	{ .reg_offset = OMAP_MUX_TERMINATOR },
-};
-#else
-#define board_mux	NULL
-#endif
-
-static struct mtd_partition zoom_nand_partitions[] = {
-	/* All the partition sizes are listed in terms of NAND block size */
-	{
-		.name		= "X-Loader-NAND",
-		.offset		= 0,
-		.size		= 4 * (64 * 2048),	/* 512KB, 0x80000 */
-		.mask_flags	= MTD_WRITEABLE,	/* force read-only */
-	},
-	{
-		.name		= "U-Boot-NAND",
-		.offset		= MTDPART_OFS_APPEND,	/* Offset = 0x80000 */
-		.size		= 10 * (64 * 2048),	/* 1.25MB, 0x140000 */
-		.mask_flags	= MTD_WRITEABLE,	/* force read-only */
-	},
-	{
-		.name		= "Boot Env-NAND",
-		.offset		= MTDPART_OFS_APPEND,   /* Offset = 0x1c0000 */
-		.size		= 2 * (64 * 2048),	/* 256KB, 0x40000 */
-	},
-	{
-		.name		= "Kernel-NAND",
-		.offset		= MTDPART_OFS_APPEND,	/* Offset = 0x0200000*/
-		.size		= 240 * (64 * 2048),	/* 30M, 0x1E00000 */
-	},
-	{
-		.name		= "system",
-		.offset		= MTDPART_OFS_APPEND,	/* Offset = 0x2000000 */
-		.size		= 3328 * (64 * 2048),	/* 416M, 0x1A000000 */
-	},
-	{
-		.name		= "userdata",
-		.offset		= MTDPART_OFS_APPEND,	/* Offset = 0x1C000000*/
-		.size		= 256 * (64 * 2048),	/* 32M, 0x2000000 */
-	},
-	{
-		.name		= "cache",
-		.offset		= MTDPART_OFS_APPEND,	/* Offset = 0x1E000000*/
-		.size		= 256 * (64 * 2048),	/* 32M, 0x2000000 */
-	},
-};
-
-static void __init omap_zoom2_init(void)
-{
-	omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
-	zoom_peripherals_init();
-	board_nand_init(zoom_nand_partitions,
-			ARRAY_SIZE(zoom_nand_partitions), ZOOM_NAND_CS);
-	zoom_debugboard_init();
-}
-
-MACHINE_START(OMAP_ZOOM2, "OMAP Zoom2 board")
-	.boot_params	= 0x80000100,
-	.map_io		= omap3_map_io,
-	.reserve	= omap_reserve,
-	.init_irq	= omap_zoom2_init_irq,
-	.init_machine	= omap_zoom2_init,
-	.timer		= &omap_timer,
-MACHINE_END
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/board-zoom3.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/board-zoom3.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/board-zoom3.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/board-zoom3.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,133 +0,0 @@
-/*
- * Copyright (C) 2009 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 <linux/platform_device.h>
-#include <linux/input.h>
-#include <linux/gpio.h>
-
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-
-#include <mach/board-zoom.h>
-
-#include <plat/common.h>
-#include <plat/board.h>
-#include <plat/usb.h>
-
-#include "board-flash.h"
-#include "mux.h"
-#include "sdram-hynix-h8mbx00u0mer-0em.h"
-
-static struct omap_board_config_kernel zoom_config[] __initdata = {
-};
-
-static struct mtd_partition zoom_nand_partitions[] = {
-	/* All the partition sizes are listed in terms of NAND block size */
-	{
-		.name		= "X-Loader-NAND",
-		.offset		= 0,
-		.size		= 4 * (64 * 2048),	/* 512KB, 0x80000 */
-		.mask_flags	= MTD_WRITEABLE,	/* force read-only */
-	},
-	{
-		.name		= "U-Boot-NAND",
-		.offset		= MTDPART_OFS_APPEND,	/* Offset = 0x80000 */
-		.size		= 10 * (64 * 2048),	/* 1.25MB, 0x140000 */
-		.mask_flags	= MTD_WRITEABLE,	/* force read-only */
-	},
-	{
-		.name		= "Boot Env-NAND",
-		.offset		= MTDPART_OFS_APPEND,   /* Offset = 0x1c0000 */
-		.size		= 2 * (64 * 2048),	/* 256KB, 0x40000 */
-	},
-	{
-		.name		= "Kernel-NAND",
-		.offset		= MTDPART_OFS_APPEND,	/* Offset = 0x0200000*/
-		.size		= 240 * (64 * 2048),	/* 30M, 0x1E00000 */
-	},
-	{
-		.name		= "system",
-		.offset		= MTDPART_OFS_APPEND,	/* Offset = 0x2000000 */
-		.size		= 3328 * (64 * 2048),	/* 416M, 0x1A000000 */
-	},
-	{
-		.name		= "userdata",
-		.offset		= MTDPART_OFS_APPEND,	/* Offset = 0x1C000000*/
-		.size		= 256 * (64 * 2048),	/* 32M, 0x2000000 */
-	},
-	{
-		.name		= "cache",
-		.offset		= MTDPART_OFS_APPEND,	/* Offset = 0x1E000000*/
-		.size		= 256 * (64 * 2048),	/* 32M, 0x2000000 */
-	},
-};
-
-static void __init omap_zoom_init_irq(void)
-{
-	omap_board_config = zoom_config;
-	omap_board_config_size = ARRAY_SIZE(zoom_config);
-	omap2_init_common_hw(h8mbx00u0mer0em_sdrc_params,
-			h8mbx00u0mer0em_sdrc_params);
-	omap_init_irq();
-	omap_gpio_init();
-}
-
-#ifdef CONFIG_OMAP_MUX
-static struct omap_board_mux board_mux[] __initdata = {
-	/* WLAN IRQ - GPIO 162 */
-	OMAP3_MUX(MCBSP1_CLKX, OMAP_MUX_MODE4 | OMAP_PIN_INPUT_PULLUP),
-	/* WLAN POWER ENABLE - GPIO 101 */
-	OMAP3_MUX(CAM_D2, OMAP_MUX_MODE4 | OMAP_PIN_OUTPUT),
-	/* WLAN SDIO: MMC3 CMD */
-	OMAP3_MUX(MCSPI1_CS1, OMAP_MUX_MODE3 | OMAP_PIN_INPUT_PULLUP),
-	/* WLAN SDIO: MMC3 CLK */
-	OMAP3_MUX(ETK_CLK, OMAP_MUX_MODE2 | OMAP_PIN_INPUT_PULLUP),
-	/* WLAN SDIO: MMC3 DAT[0-3] */
-	OMAP3_MUX(ETK_D3, OMAP_MUX_MODE2 | OMAP_PIN_INPUT_PULLUP),
-	OMAP3_MUX(ETK_D4, OMAP_MUX_MODE2 | OMAP_PIN_INPUT_PULLUP),
-	OMAP3_MUX(ETK_D5, OMAP_MUX_MODE2 | OMAP_PIN_INPUT_PULLUP),
-	OMAP3_MUX(ETK_D6, OMAP_MUX_MODE2 | OMAP_PIN_INPUT_PULLUP),
-	{ .reg_offset = OMAP_MUX_TERMINATOR },
-};
-#else
-#define board_mux	NULL
-#endif
-
-static const struct ehci_hcd_omap_platform_data ehci_pdata __initconst = {
-	.port_mode[0]		= EHCI_HCD_OMAP_MODE_UNKNOWN,
-	.port_mode[1]		= EHCI_HCD_OMAP_MODE_PHY,
-	.port_mode[2]		= EHCI_HCD_OMAP_MODE_UNKNOWN,
-	.phy_reset		= true,
-	.reset_gpio_port[0]	= -EINVAL,
-	.reset_gpio_port[1]	= 64,
-	.reset_gpio_port[2]	= -EINVAL,
-};
-
-static void __init omap_zoom_init(void)
-{
-	omap3_mux_init(board_mux, OMAP_PACKAGE_CBP);
-	zoom_peripherals_init();
-	board_nand_init(zoom_nand_partitions,
-			 ARRAY_SIZE(zoom_nand_partitions), ZOOM_NAND_CS);
-	zoom_debugboard_init();
-
-	omap_mux_init_gpio(64, OMAP_PIN_OUTPUT);
-	usb_ehci_init(&ehci_pdata);
-}
-
-MACHINE_START(OMAP_ZOOM3, "OMAP Zoom3 board")
-	.boot_params	= 0x80000100,
-	.map_io		= omap3_map_io,
-	.reserve	= omap_reserve,
-	.init_irq	= omap_zoom_init_irq,
-	.init_machine	= omap_zoom_init,
-	.timer		= &omap_timer,
-MACHINE_END
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/board-zoom.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/board-zoom.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/board-zoom.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/board-zoom.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2009-2010 Texas Instruments Inc.
+ * Mikkel Christensen <mlc@ti.com>
+ * Felipe Balbi <balbi@ti.com>
+ *
+ * Modified from mach-omap2/board-ldp.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/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/input.h>
+#include <linux/gpio.h>
+#include <linux/i2c/twl.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+
+#include <plat/common.h>
+#include <plat/board.h>
+#include <plat/usb.h>
+
+#include <mach/board-zoom.h>
+
+#include "board-flash.h"
+#include "mux.h"
+#include "sdram-micron-mt46h32m32lf-6.h"
+#include "sdram-hynix-h8mbx00u0mer-0em.h"
+
+#define ZOOM3_EHCI_RESET_GPIO		64
+
+static void __init omap_zoom_init_irq(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);
+
+	omap_init_irq();
+}
+
+#ifdef CONFIG_OMAP_MUX
+static struct omap_board_mux board_mux[] __initdata = {
+	/* WLAN IRQ - GPIO 162 */
+	OMAP3_MUX(MCBSP1_CLKX, OMAP_MUX_MODE4 | OMAP_PIN_INPUT_PULLUP),
+	/* WLAN POWER ENABLE - GPIO 101 */
+	OMAP3_MUX(CAM_D2, OMAP_MUX_MODE4 | OMAP_PIN_OUTPUT),
+	/* WLAN SDIO: MMC3 CMD */
+	OMAP3_MUX(MCSPI1_CS1, OMAP_MUX_MODE3 | OMAP_PIN_INPUT_PULLUP),
+	/* WLAN SDIO: MMC3 CLK */
+	OMAP3_MUX(ETK_CLK, OMAP_MUX_MODE2 | OMAP_PIN_INPUT_PULLUP),
+	/* WLAN SDIO: MMC3 DAT[0-3] */
+	OMAP3_MUX(ETK_D3, OMAP_MUX_MODE2 | OMAP_PIN_INPUT_PULLUP),
+	OMAP3_MUX(ETK_D4, OMAP_MUX_MODE2 | OMAP_PIN_INPUT_PULLUP),
+	OMAP3_MUX(ETK_D5, OMAP_MUX_MODE2 | OMAP_PIN_INPUT_PULLUP),
+	OMAP3_MUX(ETK_D6, OMAP_MUX_MODE2 | OMAP_PIN_INPUT_PULLUP),
+	{ .reg_offset = OMAP_MUX_TERMINATOR },
+};
+#endif
+
+static struct mtd_partition zoom_nand_partitions[] = {
+	/* All the partition sizes are listed in terms of NAND block size */
+	{
+		.name		= "X-Loader-NAND",
+		.offset		= 0,
+		.size		= 4 * (64 * 2048),	/* 512KB, 0x80000 */
+		.mask_flags	= MTD_WRITEABLE,	/* force read-only */
+	},
+	{
+		.name		= "U-Boot-NAND",
+		.offset		= MTDPART_OFS_APPEND,	/* Offset = 0x80000 */
+		.size		= 10 * (64 * 2048),	/* 1.25MB, 0x140000 */
+		.mask_flags	= MTD_WRITEABLE,	/* force read-only */
+	},
+	{
+		.name		= "Boot Env-NAND",
+		.offset		= MTDPART_OFS_APPEND,   /* Offset = 0x1c0000 */
+		.size		= 2 * (64 * 2048),	/* 256KB, 0x40000 */
+	},
+	{
+		.name		= "Kernel-NAND",
+		.offset		= MTDPART_OFS_APPEND,	/* Offset = 0x0200000*/
+		.size		= 240 * (64 * 2048),	/* 30M, 0x1E00000 */
+	},
+	{
+		.name		= "system",
+		.offset		= MTDPART_OFS_APPEND,	/* Offset = 0x2000000 */
+		.size		= 3328 * (64 * 2048),	/* 416M, 0x1A000000 */
+	},
+	{
+		.name		= "userdata",
+		.offset		= MTDPART_OFS_APPEND,	/* Offset = 0x1C000000*/
+		.size		= 256 * (64 * 2048),	/* 32M, 0x2000000 */
+	},
+	{
+		.name		= "cache",
+		.offset		= MTDPART_OFS_APPEND,	/* Offset = 0x1E000000*/
+		.size		= 256 * (64 * 2048),	/* 32M, 0x2000000 */
+	},
+};
+
+static const struct ehci_hcd_omap_platform_data ehci_pdata __initconst = {
+	.port_mode[0]		= EHCI_HCD_OMAP_MODE_UNKNOWN,
+	.port_mode[1]		= EHCI_HCD_OMAP_MODE_PHY,
+	.port_mode[2]		= EHCI_HCD_OMAP_MODE_UNKNOWN,
+	.phy_reset		= true,
+	.reset_gpio_port[0]	= -EINVAL,
+	.reset_gpio_port[1]	= ZOOM3_EHCI_RESET_GPIO,
+	.reset_gpio_port[2]	= -EINVAL,
+};
+
+static void __init omap_zoom_init(void)
+{
+	if (machine_is_omap_zoom2()) {
+		omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
+	} else if (machine_is_omap_zoom3()) {
+		omap3_mux_init(board_mux, OMAP_PACKAGE_CBP);
+		omap_mux_init_gpio(ZOOM3_EHCI_RESET_GPIO, OMAP_PIN_OUTPUT);
+		usb_ehci_init(&ehci_pdata);
+	}
+
+	board_nand_init(zoom_nand_partitions,
+			ARRAY_SIZE(zoom_nand_partitions), ZOOM_NAND_CS);
+	zoom_debugboard_init();
+	zoom_peripherals_init();
+	zoom_display_init();
+}
+
+MACHINE_START(OMAP_ZOOM2, "OMAP Zoom2 board")
+	.boot_params	= 0x80000100,
+	.map_io		= omap3_map_io,
+	.reserve	= omap_reserve,
+	.init_irq	= omap_zoom_init_irq,
+	.init_machine	= omap_zoom_init,
+	.timer		= &omap_timer,
+MACHINE_END
+
+MACHINE_START(OMAP_ZOOM3, "OMAP Zoom3 board")
+	.boot_params	= 0x80000100,
+	.map_io		= omap3_map_io,
+	.reserve	= omap_reserve,
+	.init_irq	= omap_zoom_init_irq,
+	.init_machine	= omap_zoom_init,
+	.timer		= &omap_timer,
+MACHINE_END
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/board-zoom-display.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/board-zoom-display.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/board-zoom-display.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/board-zoom-display.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2010 Texas Instruments Inc.
+ *
+ * Modified from mach-omap2/board-zoom-peripherals.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/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/i2c/twl.h>
+#include <linux/spi/spi.h>
+#include <plat/mcspi.h>
+#include <plat/display.h>
+
+#define LCD_PANEL_RESET_GPIO_PROD	96
+#define LCD_PANEL_RESET_GPIO_PILOT	55
+#define LCD_PANEL_QVGA_GPIO		56
+
+static void zoom_lcd_panel_init(void)
+{
+	int ret;
+	unsigned char lcd_panel_reset_gpio;
+
+	lcd_panel_reset_gpio = (omap_rev() > OMAP3430_REV_ES3_0) ?
+			LCD_PANEL_RESET_GPIO_PROD :
+			LCD_PANEL_RESET_GPIO_PILOT;
+
+	ret = gpio_request(lcd_panel_reset_gpio, "lcd reset");
+	if (ret) {
+		pr_err("Failed to get LCD reset GPIO (gpio%d).\n",
+			lcd_panel_reset_gpio);
+		return;
+	}
+	gpio_direction_output(lcd_panel_reset_gpio, 1);
+
+	ret = gpio_request(LCD_PANEL_QVGA_GPIO, "lcd qvga");
+	if (ret) {
+		pr_err("Failed to get LCD_PANEL_QVGA_GPIO (gpio%d).\n",
+			LCD_PANEL_QVGA_GPIO);
+		goto err0;
+	}
+	gpio_direction_output(LCD_PANEL_QVGA_GPIO, 1);
+
+	return;
+err0:
+	gpio_free(lcd_panel_reset_gpio);
+}
+
+static int zoom_panel_enable_lcd(struct omap_dss_device *dssdev)
+{
+	return 0;
+}
+
+static void zoom_panel_disable_lcd(struct omap_dss_device *dssdev)
+{
+}
+
+/*
+ * PWMA/B register offsets (TWL4030_MODULE_PWMA)
+ */
+#define TWL_INTBR_PMBR1	0xD
+#define TWL_INTBR_GPBR1	0xC
+#define TWL_LED_PWMON	0x0
+#define TWL_LED_PWMOFF	0x1
+
+static int zoom_set_bl_intensity(struct omap_dss_device *dssdev, int level)
+{
+	unsigned char c;
+	u8 mux_pwm, enb_pwm;
+
+	if (level > 100)
+		return -1;
+
+	twl_i2c_read_u8(TWL4030_MODULE_INTBR, &mux_pwm, TWL_INTBR_PMBR1);
+	twl_i2c_read_u8(TWL4030_MODULE_INTBR, &enb_pwm, TWL_INTBR_GPBR1);
+
+	if (level == 0) {
+		/* disable pwm1 output and clock */
+		enb_pwm = enb_pwm & 0xF5;
+		/* change pwm1 pin to gpio pin */
+		mux_pwm = mux_pwm & 0xCF;
+		twl_i2c_write_u8(TWL4030_MODULE_INTBR,
+					enb_pwm, TWL_INTBR_GPBR1);
+		twl_i2c_write_u8(TWL4030_MODULE_INTBR,
+					mux_pwm, TWL_INTBR_PMBR1);
+		return 0;
+	}
+
+	if (!((enb_pwm & 0xA) && (mux_pwm & 0x30))) {
+		/* change gpio pin to pwm1 pin */
+		mux_pwm = mux_pwm | 0x30;
+		/* enable pwm1 output and clock*/
+		enb_pwm = enb_pwm | 0x0A;
+		twl_i2c_write_u8(TWL4030_MODULE_INTBR,
+					mux_pwm, TWL_INTBR_PMBR1);
+		twl_i2c_write_u8(TWL4030_MODULE_INTBR,
+					enb_pwm, TWL_INTBR_GPBR1);
+	}
+
+	c = ((50 * (100 - level)) / 100) + 1;
+	twl_i2c_write_u8(TWL4030_MODULE_PWM1, 0x7F, TWL_LED_PWMOFF);
+	twl_i2c_write_u8(TWL4030_MODULE_PWM1, c, TWL_LED_PWMON);
+
+	return 0;
+}
+
+static struct omap_dss_device zoom_lcd_device = {
+	.name			= "lcd",
+	.driver_name		= "NEC_8048_panel",
+	.type			= OMAP_DISPLAY_TYPE_DPI,
+	.phy.dpi.data_lines	= 24,
+	.platform_enable	= zoom_panel_enable_lcd,
+	.platform_disable	= zoom_panel_disable_lcd,
+	.max_backlight_level	= 100,
+	.set_backlight		= zoom_set_bl_intensity,
+};
+
+static struct omap_dss_device *zoom_dss_devices[] = {
+	&zoom_lcd_device,
+};
+
+static struct omap_dss_board_info zoom_dss_data = {
+	.num_devices		= ARRAY_SIZE(zoom_dss_devices),
+	.devices		= zoom_dss_devices,
+	.default_device		= &zoom_lcd_device,
+};
+
+static struct platform_device zoom_dss_device = {
+	.name				= "omapdss",
+	.id				= -1,
+	.dev				= {
+		.platform_data		= &zoom_dss_data,
+	},
+};
+
+static struct omap2_mcspi_device_config dss_lcd_mcspi_config = {
+	.turbo_mode		= 1,
+	.single_channel	= 1,  /* 0: slave, 1: master */
+};
+
+static struct spi_board_info nec_8048_spi_board_info[] __initdata = {
+	[0] = {
+		.modalias		= "nec_8048_spi",
+		.bus_num		= 1,
+		.chip_select		= 2,
+		.max_speed_hz		= 375000,
+		.controller_data	= &dss_lcd_mcspi_config,
+	},
+};
+
+static struct platform_device *zoom_display_devices[] __initdata = {
+	&zoom_dss_device,
+};
+
+void __init zoom_display_init(void)
+{
+	platform_add_devices(zoom_display_devices,
+				ARRAY_SIZE(zoom_display_devices));
+	spi_register_board_info(nec_8048_spi_board_info,
+				ARRAY_SIZE(nec_8048_spi_board_info));
+	zoom_lcd_panel_init();
+}
+
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/board-zoom-peripherals.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/board-zoom-peripherals.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/board-zoom-peripherals.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/board-zoom-peripherals.c	2011-03-14 21:20:32.000000000 -0400
@@ -35,6 +35,8 @@
 #define OMAP_ZOOM_WLAN_PMENA_GPIO	(101)
 #define OMAP_ZOOM_WLAN_IRQ_GPIO		(162)
 
+#define LCD_PANEL_ENABLE_GPIO		(7 + OMAP_MAX_GPIO_LINES)
+
 /* Zoom2 has Qwerty keyboard*/
 static uint32_t board_keymap[] = {
 	KEY(0, 0, KEY_E),
@@ -190,13 +192,13 @@ static struct platform_device omap_vwlan
 	},
 };
 
-struct wl12xx_platform_data omap_zoom_wlan_data __initdata = {
+static struct wl12xx_platform_data omap_zoom_wlan_data __initdata = {
 	.irq = OMAP_GPIO_IRQ(OMAP_ZOOM_WLAN_IRQ_GPIO),
 	/* ZOOM ref clock is 26 MHz */
 	.board_ref_clock = 1,
 };
 
-static struct omap2_hsmmc_info mmc[] __initdata = {
+static struct omap2_hsmmc_info mmc[] = {
 	{
 		.name		= "external",
 		.mmc		= 1,
@@ -224,9 +226,43 @@ static struct omap2_hsmmc_info mmc[] __i
 	{}      /* Terminator */
 };
 
+static struct regulator_consumer_supply zoom_vpll2_supply =
+	REGULATOR_SUPPLY("vdds_dsi", "omapdss");
+
+static struct regulator_consumer_supply zoom_vdda_dac_supply =
+	REGULATOR_SUPPLY("vdda_dac", "omapdss");
+
+static struct regulator_init_data zoom_vpll2 = {
+	.constraints = {
+		.min_uV                 = 1800000,
+		.max_uV                 = 1800000,
+		.valid_modes_mask       = REGULATOR_MODE_NORMAL
+					| REGULATOR_MODE_STANDBY,
+		.valid_ops_mask         = REGULATOR_CHANGE_MODE
+					| REGULATOR_CHANGE_STATUS,
+	},
+	.num_consumer_supplies		= 1,
+	.consumer_supplies		= &zoom_vpll2_supply,
+};
+
+static struct regulator_init_data zoom_vdac = {
+	.constraints = {
+		.min_uV                 = 1800000,
+		.max_uV                 = 1800000,
+		.valid_modes_mask       = REGULATOR_MODE_NORMAL
+					| REGULATOR_MODE_STANDBY,
+		.valid_ops_mask         = REGULATOR_CHANGE_MODE
+					| REGULATOR_CHANGE_STATUS,
+	},
+	.num_consumer_supplies		= 1,
+	.consumer_supplies		= &zoom_vdda_dac_supply,
+};
+
 static int zoom_twl_gpio_setup(struct device *dev,
 		unsigned gpio, unsigned ngpio)
 {
+	int ret;
+
 	/* gpio + 0 is "mmc0_cd" (input/IRQ) */
 	mmc[0].gpio_cd = gpio + 0;
 	omap2_hsmmc_init(mmc);
@@ -238,11 +274,19 @@ static int zoom_twl_gpio_setup(struct de
 	zoom_vsim_supply.dev = mmc[0].dev;
 	zoom_vmmc2_supply.dev = mmc[1].dev;
 
-	return 0;
+	ret = gpio_request(LCD_PANEL_ENABLE_GPIO, "lcd enable");
+	if (ret) {
+		pr_err("Failed to get LCD_PANEL_ENABLE_GPIO (gpio%d).\n",
+				LCD_PANEL_ENABLE_GPIO);
+		return ret;
+	}
+	gpio_direction_output(LCD_PANEL_ENABLE_GPIO, 0);
+
+	return ret;
 }
 
 /* EXTMUTE callback function */
-void zoom2_set_hs_extmute(int mute)
+static void zoom2_set_hs_extmute(int mute)
 {
 	gpio_set_value(ZOOM2_HEADSET_EXTMUTE_GPIO, mute);
 }
@@ -301,7 +345,8 @@ static struct twl4030_platform_data zoom
 	.vmmc1          = &zoom_vmmc1,
 	.vmmc2          = &zoom_vmmc2,
 	.vsim           = &zoom_vsim,
-
+	.vpll2		= &zoom_vpll2,
+	.vdac		= &zoom_vdac,
 };
 
 static struct i2c_board_info __initdata zoom_i2c_boardinfo[] = {
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/clkt2xxx_apll.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/clkt2xxx_apll.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/clkt2xxx_apll.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/clkt2xxx_apll.c	2011-03-14 21:20:32.000000000 -0400
@@ -26,7 +26,7 @@
 
 #include "clock.h"
 #include "clock2xxx.h"
-#include "cm.h"
+#include "cm2xxx_3xxx.h"
 #include "cm-regbits-24xx.h"
 
 /* CM_CLKEN_PLL.EN_{54,96}M_PLL options (24XX) */
@@ -49,14 +49,14 @@ static int omap2_clk_apll_enable(struct
 
 	apll_mask = EN_APLL_LOCKED << clk->enable_bit;
 
-	cval = cm_read_mod_reg(PLL_MOD, CM_CLKEN);
+	cval = omap2_cm_read_mod_reg(PLL_MOD, CM_CLKEN);
 
 	if ((cval & apll_mask) == apll_mask)
 		return 0;   /* apll already enabled */
 
 	cval &= ~apll_mask;
 	cval |= apll_mask;
-	cm_write_mod_reg(cval, PLL_MOD, CM_CLKEN);
+	omap2_cm_write_mod_reg(cval, PLL_MOD, CM_CLKEN);
 
 	omap2_cm_wait_idlest(cm_idlest_pll, status_mask,
 			     OMAP24XX_CM_IDLEST_VAL, clk->name);
@@ -83,9 +83,9 @@ static void omap2_clk_apll_disable(struc
 {
 	u32 cval;
 
-	cval = cm_read_mod_reg(PLL_MOD, CM_CLKEN);
+	cval = omap2_cm_read_mod_reg(PLL_MOD, CM_CLKEN);
 	cval &= ~(EN_APLL_LOCKED << clk->enable_bit);
-	cm_write_mod_reg(cval, PLL_MOD, CM_CLKEN);
+	omap2_cm_write_mod_reg(cval, PLL_MOD, CM_CLKEN);
 }
 
 /* Public data */
@@ -106,7 +106,7 @@ u32 omap2xxx_get_apll_clkin(void)
 {
 	u32 aplls, srate = 0;
 
-	aplls = cm_read_mod_reg(PLL_MOD, CM_CLKSEL1);
+	aplls = omap2_cm_read_mod_reg(PLL_MOD, CM_CLKSEL1);
 	aplls &= OMAP24XX_APLLS_CLKIN_MASK;
 	aplls >>= OMAP24XX_APLLS_CLKIN_SHIFT;
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/clkt2xxx_dpllcore.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/clkt2xxx_dpllcore.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/clkt2xxx_dpllcore.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/clkt2xxx_dpllcore.c	2011-03-14 21:20:32.000000000 -0400
@@ -32,7 +32,7 @@
 #include "clock.h"
 #include "clock2xxx.h"
 #include "opp2xxx.h"
-#include "cm.h"
+#include "cm2xxx_3xxx.h"
 #include "cm-regbits-24xx.h"
 
 /* #define DOWN_VARIABLE_DPLL 1 */		/* Experimental */
@@ -54,7 +54,7 @@ unsigned long omap2xxx_clk_get_core_rate
 
 	core_clk = omap2_get_dpll_rate(clk);
 
-	v = cm_read_mod_reg(PLL_MOD, CM_CLKSEL2);
+	v = omap2_cm_read_mod_reg(PLL_MOD, CM_CLKSEL2);
 	v &= OMAP24XX_CORE_CLK_SRC_MASK;
 
 	if (v == CORE_CLK_SRC_32K)
@@ -73,7 +73,7 @@ static long omap2_dpllcore_round_rate(un
 {
 	u32 high, low, core_clk_src;
 
-	core_clk_src = cm_read_mod_reg(PLL_MOD, CM_CLKSEL2);
+	core_clk_src = omap2_cm_read_mod_reg(PLL_MOD, CM_CLKSEL2);
 	core_clk_src &= OMAP24XX_CORE_CLK_SRC_MASK;
 
 	if (core_clk_src == CORE_CLK_SRC_DPLL) {	/* DPLL clockout */
@@ -111,7 +111,7 @@ int omap2_reprogram_dpllcore(struct clk
 	const struct dpll_data *dd;
 
 	cur_rate = omap2xxx_clk_get_core_rate(dclk);
-	mult = cm_read_mod_reg(PLL_MOD, CM_CLKSEL2);
+	mult = omap2_cm_read_mod_reg(PLL_MOD, CM_CLKSEL2);
 	mult &= OMAP24XX_CORE_CLK_SRC_MASK;
 
 	if ((rate == (cur_rate / 2)) && (mult == 2)) {
@@ -136,7 +136,7 @@ int omap2_reprogram_dpllcore(struct clk
 		tmpset.cm_clksel1_pll &= ~(dd->mult_mask |
 					   dd->div1_mask);
 		div = ((curr_prcm_set->xtal_speed / 1000000) - 1);
-		tmpset.cm_clksel2_pll = cm_read_mod_reg(PLL_MOD, CM_CLKSEL2);
+		tmpset.cm_clksel2_pll = omap2_cm_read_mod_reg(PLL_MOD, CM_CLKSEL2);
 		tmpset.cm_clksel2_pll &= ~OMAP24XX_CORE_CLK_SRC_MASK;
 		if (rate > low) {
 			tmpset.cm_clksel2_pll |= CORE_CLK_SRC_DPLL_X2;
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/clkt2xxx_osc.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/clkt2xxx_osc.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/clkt2xxx_osc.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/clkt2xxx_osc.c	2011-03-14 21:20:32.000000000 -0400
@@ -27,7 +27,7 @@
 
 #include "clock.h"
 #include "clock2xxx.h"
-#include "prm.h"
+#include "prm2xxx_3xxx.h"
 #include "prm-regbits-24xx.h"
 
 static int omap2_enable_osc_ck(struct clk *clk)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/clkt2xxx_sys.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/clkt2xxx_sys.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/clkt2xxx_sys.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/clkt2xxx_sys.c	2011-03-14 21:20:32.000000000 -0400
@@ -26,7 +26,7 @@
 
 #include "clock.h"
 #include "clock2xxx.h"
-#include "prm.h"
+#include "prm2xxx_3xxx.h"
 #include "prm-regbits-24xx.h"
 
 void __iomem *prcm_clksrc_ctrl;
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/clkt2xxx_virt_prcm_set.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/clkt2xxx_virt_prcm_set.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/clkt2xxx_virt_prcm_set.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/clkt2xxx_virt_prcm_set.c	2011-03-14 21:20:32.000000000 -0400
@@ -40,7 +40,7 @@
 #include "clock.h"
 #include "clock2xxx.h"
 #include "opp2xxx.h"
-#include "cm.h"
+#include "cm2xxx_3xxx.h"
 #include "cm-regbits-24xx.h"
 
 const struct prcm_config *curr_prcm_set;
@@ -133,21 +133,21 @@ int omap2_select_table_rate(struct clk *
 			done_rate = CORE_CLK_SRC_DPLL;
 
 		/* MPU divider */
-		cm_write_mod_reg(prcm->cm_clksel_mpu, MPU_MOD, CM_CLKSEL);
+		omap2_cm_write_mod_reg(prcm->cm_clksel_mpu, MPU_MOD, CM_CLKSEL);
 
 		/* dsp + iva1 div(2420), iva2.1(2430) */
-		cm_write_mod_reg(prcm->cm_clksel_dsp,
+		omap2_cm_write_mod_reg(prcm->cm_clksel_dsp,
 				 OMAP24XX_DSP_MOD, CM_CLKSEL);
 
-		cm_write_mod_reg(prcm->cm_clksel_gfx, GFX_MOD, CM_CLKSEL);
+		omap2_cm_write_mod_reg(prcm->cm_clksel_gfx, GFX_MOD, CM_CLKSEL);
 
 		/* Major subsystem dividers */
-		tmp = cm_read_mod_reg(CORE_MOD, CM_CLKSEL1) & OMAP24XX_CLKSEL_DSS2_MASK;
-		cm_write_mod_reg(prcm->cm_clksel1_core | tmp, CORE_MOD,
+		tmp = omap2_cm_read_mod_reg(CORE_MOD, CM_CLKSEL1) & OMAP24XX_CLKSEL_DSS2_MASK;
+		omap2_cm_write_mod_reg(prcm->cm_clksel1_core | tmp, CORE_MOD,
 				 CM_CLKSEL1);
 
 		if (cpu_is_omap2430())
-			cm_write_mod_reg(prcm->cm_clksel_mdm,
+			omap2_cm_write_mod_reg(prcm->cm_clksel_mdm,
 					 OMAP2430_MDM_MOD, CM_CLKSEL);
 
 		/* x2 to enter omap2xxx_sdrc_init_params() */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/clkt_dpll.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/clkt_dpll.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/clkt_dpll.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/clkt_dpll.c	2011-03-14 21:20:32.000000000 -0400
@@ -24,7 +24,6 @@
 #include <plat/clock.h>
 
 #include "clock.h"
-#include "cm.h"
 #include "cm-regbits-24xx.h"
 #include "cm-regbits-34xx.h"
 
@@ -78,7 +77,7 @@ static int _dpll_test_fint(struct clk *c
 	dd = clk->dpll_data;
 
 	/* DPLL divider must result in a valid jitter correction val */
-	fint = clk->parent->rate / (n + 1);
+	fint = clk->parent->rate / n;
 	if (fint < DPLL_FINT_BAND1_MIN) {
 
 		pr_debug("rejecting n=%d due to Fint failure, "
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/clock2420_data.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/clock2420_data.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/clock2420_data.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/clock2420_data.c	2011-03-14 21:20:32.000000000 -0400
@@ -22,8 +22,8 @@
 #include "clock.h"
 #include "clock2xxx.h"
 #include "opp2xxx.h"
-#include "prm.h"
-#include "cm.h"
+#include "cm2xxx_3xxx.h"
+#include "prm2xxx_3xxx.h"
 #include "prm-regbits-24xx.h"
 #include "cm-regbits-24xx.h"
 #include "sdrc.h"
@@ -812,7 +812,7 @@ static struct clk dss2_fck = {		/* Alt c
 	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
 	.clksel_mask	= OMAP24XX_CLKSEL_DSS2_MASK,
 	.clksel		= dss2_fck_clksel,
-	.recalc		= &followparent_recalc,
+	.recalc		= &omap2_clksel_recalc,
 };
 
 static struct clk dss_54m_fck = {	/* Alt clk used in power management */
@@ -1862,10 +1862,10 @@ static struct omap_clk omap2420_clks[] =
 	CLK(NULL,	"eac_fck",	&eac_fck,	CK_242X),
 	CLK("omap_hdq.0", "ick",	&hdq_ick,	CK_242X),
 	CLK("omap_hdq.1", "fck",	&hdq_fck,	CK_242X),
-	CLK("i2c_omap.1", "ick",	&i2c1_ick,	CK_242X),
-	CLK("i2c_omap.1", "fck",	&i2c1_fck,	CK_242X),
-	CLK("i2c_omap.2", "ick",	&i2c2_ick,	CK_242X),
-	CLK("i2c_omap.2", "fck",	&i2c2_fck,	CK_242X),
+	CLK("omap_i2c.1", "ick",	&i2c1_ick,	CK_242X),
+	CLK("omap_i2c.1", "fck",	&i2c1_fck,	CK_242X),
+	CLK("omap_i2c.2", "ick",	&i2c2_ick,	CK_242X),
+	CLK("omap_i2c.2", "fck",	&i2c2_fck,	CK_242X),
 	CLK(NULL,	"gpmc_fck",	&gpmc_fck,	CK_242X),
 	CLK(NULL,	"sdma_fck",	&sdma_fck,	CK_242X),
 	CLK(NULL,	"sdma_ick",	&sdma_ick,	CK_242X),
@@ -1877,7 +1877,7 @@ static struct omap_clk omap2420_clks[] =
 	CLK("omap-aes",	"ick",	&aes_ick,	CK_242X),
 	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("musb-hdrc",	"fck",	&osc_ck,	CK_242X),
 };
 
 /*
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/clock2430.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/clock2430.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/clock2430.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/clock2430.c	2011-03-14 21:20:32.000000000 -0400
@@ -25,7 +25,7 @@
 
 #include "clock.h"
 #include "clock2xxx.h"
-#include "cm.h"
+#include "cm2xxx_3xxx.h"
 #include "cm-regbits-24xx.h"
 
 /**
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/clock2430_data.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/clock2430_data.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/clock2430_data.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/clock2430_data.c	2011-03-14 21:20:32.000000000 -0400
@@ -22,8 +22,8 @@
 #include "clock.h"
 #include "clock2xxx.h"
 #include "opp2xxx.h"
-#include "prm.h"
-#include "cm.h"
+#include "cm2xxx_3xxx.h"
+#include "prm2xxx_3xxx.h"
 #include "prm-regbits-24xx.h"
 #include "cm-regbits-24xx.h"
 #include "sdrc.h"
@@ -800,7 +800,7 @@ static struct clk dss2_fck = {		/* Alt c
 	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
 	.clksel_mask	= OMAP24XX_CLKSEL_DSS2_MASK,
 	.clksel		= dss2_fck_clksel,
-	.recalc		= &followparent_recalc,
+	.recalc		= &omap2_clksel_recalc,
 };
 
 static struct clk dss_54m_fck = {	/* Alt clk used in power management */
@@ -1969,10 +1969,10 @@ static struct omap_clk omap2430_clks[] =
 	CLK(NULL,	"fac_fck",	&fac_fck,	CK_243X),
 	CLK("omap_hdq.0", "ick",	&hdq_ick,	CK_243X),
 	CLK("omap_hdq.1", "fck",	&hdq_fck,	CK_243X),
-	CLK("i2c_omap.1", "ick",	&i2c1_ick,	CK_243X),
-	CLK("i2c_omap.1", "fck",	&i2chs1_fck,	CK_243X),
-	CLK("i2c_omap.2", "ick",	&i2c2_ick,	CK_243X),
-	CLK("i2c_omap.2", "fck",	&i2chs2_fck,	CK_243X),
+	CLK("omap_i2c.1", "ick",	&i2c1_ick,	CK_243X),
+	CLK("omap_i2c.1", "fck",	&i2chs1_fck,	CK_243X),
+	CLK("omap_i2c.2", "ick",	&i2c2_ick,	CK_243X),
+	CLK("omap_i2c.2", "fck",	&i2chs2_fck,	CK_243X),
 	CLK(NULL,	"gpmc_fck",	&gpmc_fck,	CK_243X),
 	CLK(NULL,	"sdma_fck",	&sdma_fck,	CK_243X),
 	CLK(NULL,	"sdma_ick",	&sdma_ick,	CK_243X),
@@ -1983,7 +1983,7 @@ static struct omap_clk omap2430_clks[] =
 	CLK("omap-aes",	"ick",	&aes_ick,	CK_243X),
 	CLK(NULL,	"pka_ick",	&pka_ick,	CK_243X),
 	CLK(NULL,	"usb_fck",	&usb_fck,	CK_243X),
-	CLK("musb_hdrc",	"ick",	&usbhs_ick,	CK_243X),
+	CLK("musb-omap2430",	"ick",	&usbhs_ick,	CK_243X),
 	CLK("mmci-omap-hs.0", "ick",	&mmchs1_ick,	CK_243X),
 	CLK("mmci-omap-hs.0", "fck",	&mmchs1_fck,	CK_243X),
 	CLK("mmci-omap-hs.1", "ick",	&mmchs2_ick,	CK_243X),
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/clock34xx.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/clock34xx.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/clock34xx.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/clock34xx.c	2011-03-14 21:20:32.000000000 -0400
@@ -25,7 +25,7 @@
 
 #include "clock.h"
 #include "clock34xx.h"
-#include "cm.h"
+#include "cm2xxx_3xxx.h"
 #include "cm-regbits-34xx.h"
 
 /**
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/clock3517.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/clock3517.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/clock3517.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/clock3517.c	2011-03-14 21:20:32.000000000 -0400
@@ -25,7 +25,7 @@
 
 #include "clock.h"
 #include "clock3517.h"
-#include "cm.h"
+#include "cm2xxx_3xxx.h"
 #include "cm-regbits-34xx.h"
 
 /*
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/clock3xxx.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/clock3xxx.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/clock3xxx.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/clock3xxx.c	2011-03-14 21:20:32.000000000 -0400
@@ -25,9 +25,9 @@
 
 #include "clock.h"
 #include "clock3xxx.h"
-#include "prm.h"
+#include "prm2xxx_3xxx.h"
 #include "prm-regbits-34xx.h"
-#include "cm.h"
+#include "cm2xxx_3xxx.h"
 #include "cm-regbits-34xx.h"
 
 /*
@@ -94,7 +94,7 @@ static int __init omap3xxx_clk_arch_init
 
 	ret = omap2_clk_switch_mpurate_at_boot("dpll1_ck");
 	if (!ret)
-		omap2_clk_print_new_rates("osc_sys_ck", "arm_fck", "core_ck");
+		omap2_clk_print_new_rates("osc_sys_ck", "core_ck", "arm_fck");
 
 	return ret;
 }
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/clock3xxx_data.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/clock3xxx_data.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/clock3xxx_data.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/clock3xxx_data.c	2011-03-14 21:20:32.000000000 -0400
@@ -28,9 +28,9 @@
 #include "clock36xx.h"
 #include "clock3517.h"
 
-#include "cm.h"
+#include "cm2xxx_3xxx.h"
 #include "cm-regbits-34xx.h"
-#include "prm.h"
+#include "prm2xxx_3xxx.h"
 #include "prm-regbits-34xx.h"
 #include "control.h"
 
@@ -120,7 +120,7 @@ static const struct clksel_rate osc_sys_
 };
 
 static const struct clksel_rate osc_sys_16_8m_rates[] = {
-	{ .div = 1, .val = 5, .flags = RATE_IN_3430ES2PLUS },
+	{ .div = 1, .val = 5, .flags = RATE_IN_3430ES2PLUS_36XX },
 	{ .div = 0 }
 };
 
@@ -452,35 +452,35 @@ static struct clk dpll3_x2_ck = {
 static const struct clksel_rate div31_dpll3_rates[] = {
 	{ .div = 1, .val = 1, .flags = RATE_IN_3XXX },
 	{ .div = 2, .val = 2, .flags = RATE_IN_3XXX },
-	{ .div = 3, .val = 3, .flags = RATE_IN_3430ES2PLUS },
-	{ .div = 4, .val = 4, .flags = RATE_IN_3430ES2PLUS },
-	{ .div = 5, .val = 5, .flags = RATE_IN_3430ES2PLUS },
-	{ .div = 6, .val = 6, .flags = RATE_IN_3430ES2PLUS },
-	{ .div = 7, .val = 7, .flags = RATE_IN_3430ES2PLUS },
-	{ .div = 8, .val = 8, .flags = RATE_IN_3430ES2PLUS },
-	{ .div = 9, .val = 9, .flags = RATE_IN_3430ES2PLUS },
-	{ .div = 10, .val = 10, .flags = RATE_IN_3430ES2PLUS },
-	{ .div = 11, .val = 11, .flags = RATE_IN_3430ES2PLUS },
-	{ .div = 12, .val = 12, .flags = RATE_IN_3430ES2PLUS },
-	{ .div = 13, .val = 13, .flags = RATE_IN_3430ES2PLUS },
-	{ .div = 14, .val = 14, .flags = RATE_IN_3430ES2PLUS },
-	{ .div = 15, .val = 15, .flags = RATE_IN_3430ES2PLUS },
-	{ .div = 16, .val = 16, .flags = RATE_IN_3430ES2PLUS },
-	{ .div = 17, .val = 17, .flags = RATE_IN_3430ES2PLUS },
-	{ .div = 18, .val = 18, .flags = RATE_IN_3430ES2PLUS },
-	{ .div = 19, .val = 19, .flags = RATE_IN_3430ES2PLUS },
-	{ .div = 20, .val = 20, .flags = RATE_IN_3430ES2PLUS },
-	{ .div = 21, .val = 21, .flags = RATE_IN_3430ES2PLUS },
-	{ .div = 22, .val = 22, .flags = RATE_IN_3430ES2PLUS },
-	{ .div = 23, .val = 23, .flags = RATE_IN_3430ES2PLUS },
-	{ .div = 24, .val = 24, .flags = RATE_IN_3430ES2PLUS },
-	{ .div = 25, .val = 25, .flags = RATE_IN_3430ES2PLUS },
-	{ .div = 26, .val = 26, .flags = RATE_IN_3430ES2PLUS },
-	{ .div = 27, .val = 27, .flags = RATE_IN_3430ES2PLUS },
-	{ .div = 28, .val = 28, .flags = RATE_IN_3430ES2PLUS },
-	{ .div = 29, .val = 29, .flags = RATE_IN_3430ES2PLUS },
-	{ .div = 30, .val = 30, .flags = RATE_IN_3430ES2PLUS },
-	{ .div = 31, .val = 31, .flags = RATE_IN_3430ES2PLUS },
+	{ .div = 3, .val = 3, .flags = RATE_IN_3430ES2PLUS_36XX },
+	{ .div = 4, .val = 4, .flags = RATE_IN_3430ES2PLUS_36XX },
+	{ .div = 5, .val = 5, .flags = RATE_IN_3430ES2PLUS_36XX },
+	{ .div = 6, .val = 6, .flags = RATE_IN_3430ES2PLUS_36XX },
+	{ .div = 7, .val = 7, .flags = RATE_IN_3430ES2PLUS_36XX },
+	{ .div = 8, .val = 8, .flags = RATE_IN_3430ES2PLUS_36XX },
+	{ .div = 9, .val = 9, .flags = RATE_IN_3430ES2PLUS_36XX },
+	{ .div = 10, .val = 10, .flags = RATE_IN_3430ES2PLUS_36XX },
+	{ .div = 11, .val = 11, .flags = RATE_IN_3430ES2PLUS_36XX },
+	{ .div = 12, .val = 12, .flags = RATE_IN_3430ES2PLUS_36XX },
+	{ .div = 13, .val = 13, .flags = RATE_IN_3430ES2PLUS_36XX },
+	{ .div = 14, .val = 14, .flags = RATE_IN_3430ES2PLUS_36XX },
+	{ .div = 15, .val = 15, .flags = RATE_IN_3430ES2PLUS_36XX },
+	{ .div = 16, .val = 16, .flags = RATE_IN_3430ES2PLUS_36XX },
+	{ .div = 17, .val = 17, .flags = RATE_IN_3430ES2PLUS_36XX },
+	{ .div = 18, .val = 18, .flags = RATE_IN_3430ES2PLUS_36XX },
+	{ .div = 19, .val = 19, .flags = RATE_IN_3430ES2PLUS_36XX },
+	{ .div = 20, .val = 20, .flags = RATE_IN_3430ES2PLUS_36XX },
+	{ .div = 21, .val = 21, .flags = RATE_IN_3430ES2PLUS_36XX },
+	{ .div = 22, .val = 22, .flags = RATE_IN_3430ES2PLUS_36XX },
+	{ .div = 23, .val = 23, .flags = RATE_IN_3430ES2PLUS_36XX },
+	{ .div = 24, .val = 24, .flags = RATE_IN_3430ES2PLUS_36XX },
+	{ .div = 25, .val = 25, .flags = RATE_IN_3430ES2PLUS_36XX },
+	{ .div = 26, .val = 26, .flags = RATE_IN_3430ES2PLUS_36XX },
+	{ .div = 27, .val = 27, .flags = RATE_IN_3430ES2PLUS_36XX },
+	{ .div = 28, .val = 28, .flags = RATE_IN_3430ES2PLUS_36XX },
+	{ .div = 29, .val = 29, .flags = RATE_IN_3430ES2PLUS_36XX },
+	{ .div = 30, .val = 30, .flags = RATE_IN_3430ES2PLUS_36XX },
+	{ .div = 31, .val = 31, .flags = RATE_IN_3430ES2PLUS_36XX },
 	{ .div = 0 },
 };
 
@@ -602,6 +602,8 @@ static struct dpll_data dpll4_dd_3630 __
 	.autoidle_mask	= OMAP3430_AUTO_PERIPH_DPLL_MASK,
 	.idlest_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST),
 	.idlest_mask	= OMAP3430_ST_PERIPH_CLK_MASK,
+	.dco_mask	= OMAP3630_PERIPH_DPLL_DCO_SEL_MASK,
+	.sddiv_mask	= OMAP3630_PERIPH_DPLL_SD_DIV_MASK,
 	.max_multiplier = OMAP3630_MAX_JTYPE_DPLL_MULT,
 	.min_divider	= 1,
 	.max_divider	= OMAP3_MAX_DPLL_DIV,
@@ -1558,6 +1560,7 @@ static struct clk mcspi4_fck = {
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP3430_EN_MCSPI4_SHIFT,
 	.recalc		= &followparent_recalc,
+	.clkdm_name	= "core_l4_clkdm",
 };
 
 static struct clk mcspi3_fck = {
@@ -1567,6 +1570,7 @@ static struct clk mcspi3_fck = {
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP3430_EN_MCSPI3_SHIFT,
 	.recalc		= &followparent_recalc,
+	.clkdm_name	= "core_l4_clkdm",
 };
 
 static struct clk mcspi2_fck = {
@@ -1576,6 +1580,7 @@ static struct clk mcspi2_fck = {
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP3430_EN_MCSPI2_SHIFT,
 	.recalc		= &followparent_recalc,
+	.clkdm_name	= "core_l4_clkdm",
 };
 
 static struct clk mcspi1_fck = {
@@ -1585,6 +1590,7 @@ static struct clk mcspi1_fck = {
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP3430_EN_MCSPI1_SHIFT,
 	.recalc		= &followparent_recalc,
+	.clkdm_name	= "core_l4_clkdm",
 };
 
 static struct clk uart2_fck = {
@@ -3044,6 +3050,7 @@ static struct clk sr1_fck = {
 	.parent		= &sys_ck,
 	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN),
 	.enable_bit	= OMAP3430_EN_SR1_SHIFT,
+	.clkdm_name	= "wkup_clkdm",
 	.recalc		= &followparent_recalc,
 };
 
@@ -3054,6 +3061,7 @@ static struct clk sr2_fck = {
 	.parent		= &sys_ck,
 	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN),
 	.enable_bit	= OMAP3430_EN_SR2_SHIFT,
+	.clkdm_name	= "wkup_clkdm",
 	.recalc		= &followparent_recalc,
 };
 
@@ -3201,7 +3209,7 @@ static struct omap_clk omap3xxx_clks[] =
 	CLK(NULL,	"omap_32k_fck",	&omap_32k_fck,	CK_3XXX),
 	CLK(NULL,	"virt_12m_ck",	&virt_12m_ck,	CK_3XXX),
 	CLK(NULL,	"virt_13m_ck",	&virt_13m_ck,	CK_3XXX),
-	CLK(NULL,	"virt_16_8m_ck", &virt_16_8m_ck, CK_3430ES2 | CK_AM35XX),
+	CLK(NULL,	"virt_16_8m_ck", &virt_16_8m_ck, CK_3430ES2PLUS | CK_AM35XX  | CK_36XX),
 	CLK(NULL,	"virt_19_2m_ck", &virt_19_2m_ck, CK_3XXX),
 	CLK(NULL,	"virt_26m_ck",	&virt_26m_ck,	CK_3XXX),
 	CLK(NULL,	"virt_38_4m_ck", &virt_38_4m_ck, CK_3XXX),
@@ -3218,8 +3226,8 @@ static struct omap_clk omap3xxx_clks[] =
 	CLK(NULL,	"dpll1_ck",	&dpll1_ck,	CK_3XXX),
 	CLK(NULL,	"dpll1_x2_ck",	&dpll1_x2_ck,	CK_3XXX),
 	CLK(NULL,	"dpll1_x2m2_ck", &dpll1_x2m2_ck, CK_3XXX),
-	CLK(NULL,	"dpll2_ck",	&dpll2_ck,	CK_343X),
-	CLK(NULL,	"dpll2_m2_ck",	&dpll2_m2_ck,	CK_343X),
+	CLK(NULL,	"dpll2_ck",	&dpll2_ck,	CK_34XX | CK_36XX),
+	CLK(NULL,	"dpll2_m2_ck",	&dpll2_m2_ck,	CK_34XX | CK_36XX),
 	CLK(NULL,	"dpll3_ck",	&dpll3_ck,	CK_3XXX),
 	CLK(NULL,	"core_ck",	&core_ck,	CK_3XXX),
 	CLK(NULL,	"dpll3_x2_ck",	&dpll3_x2_ck,	CK_3XXX),
@@ -3248,8 +3256,8 @@ static struct omap_clk omap3xxx_clks[] =
 	CLK(NULL,	"dpll4_m6_ck",	&dpll4_m6_ck,	CK_3XXX),
 	CLK(NULL,	"dpll4_m6x2_ck", &dpll4_m6x2_ck, CK_3XXX),
 	CLK("etb",	"emu_per_alwon_ck", &emu_per_alwon_ck, CK_3XXX),
-	CLK(NULL,	"dpll5_ck",	&dpll5_ck,	CK_3430ES2 | CK_AM35XX),
-	CLK(NULL,	"dpll5_m2_ck",	&dpll5_m2_ck,	CK_3430ES2 | CK_AM35XX),
+	CLK(NULL,	"dpll5_ck",	&dpll5_ck,	CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
+	CLK(NULL,	"dpll5_m2_ck",	&dpll5_m2_ck,	CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
 	CLK(NULL,	"clkout2_src_ck", &clkout2_src_ck, CK_3XXX),
 	CLK(NULL,	"sys_clkout2",	&sys_clkout2,	CK_3XXX),
 	CLK(NULL,	"corex2_fck",	&corex2_fck,	CK_3XXX),
@@ -3257,8 +3265,8 @@ static struct omap_clk omap3xxx_clks[] =
 	CLK(NULL,	"mpu_ck",	&mpu_ck,	CK_3XXX),
 	CLK(NULL,	"arm_fck",	&arm_fck,	CK_3XXX),
 	CLK("etb",	"emu_mpu_alwon_ck", &emu_mpu_alwon_ck, CK_3XXX),
-	CLK(NULL,	"dpll2_fck",	&dpll2_fck,	CK_343X),
-	CLK(NULL,	"iva2_ck",	&iva2_ck,	CK_343X),
+	CLK(NULL,	"dpll2_fck",	&dpll2_fck,	CK_34XX | CK_36XX),
+	CLK(NULL,	"iva2_ck",	&iva2_ck,	CK_34XX | CK_36XX),
 	CLK(NULL,	"l3_ick",	&l3_ick,	CK_3XXX),
 	CLK(NULL,	"l4_ick",	&l4_ick,	CK_3XXX),
 	CLK(NULL,	"rm_ick",	&rm_ick,	CK_3XXX),
@@ -3267,27 +3275,28 @@ static struct omap_clk omap3xxx_clks[] =
 	CLK(NULL,	"gfx_l3_ick",	&gfx_l3_ick,	CK_3430ES1),
 	CLK(NULL,	"gfx_cg1_ck",	&gfx_cg1_ck,	CK_3430ES1),
 	CLK(NULL,	"gfx_cg2_ck",	&gfx_cg2_ck,	CK_3430ES1),
-	CLK(NULL,	"sgx_fck",	&sgx_fck,	CK_3430ES2 | CK_3517),
-	CLK(NULL,	"sgx_ick",	&sgx_ick,	CK_3430ES2 | CK_3517),
+	CLK(NULL,	"sgx_fck",	&sgx_fck,	CK_3430ES2PLUS | CK_3517 | CK_36XX),
+	CLK(NULL,	"sgx_ick",	&sgx_ick,	CK_3430ES2PLUS | CK_3517 | CK_36XX),
 	CLK(NULL,	"d2d_26m_fck",	&d2d_26m_fck,	CK_3430ES1),
-	CLK(NULL,	"modem_fck",	&modem_fck,	CK_343X),
-	CLK(NULL,	"sad2d_ick",	&sad2d_ick,	CK_343X),
-	CLK(NULL,	"mad2d_ick",	&mad2d_ick,	CK_343X),
+	CLK(NULL,	"modem_fck",	&modem_fck,	CK_34XX | CK_36XX),
+	CLK(NULL,	"sad2d_ick",	&sad2d_ick,	CK_34XX | CK_36XX),
+	CLK(NULL,	"mad2d_ick",	&mad2d_ick,	CK_34XX | CK_36XX),
 	CLK(NULL,	"gpt10_fck",	&gpt10_fck,	CK_3XXX),
 	CLK(NULL,	"gpt11_fck",	&gpt11_fck,	CK_3XXX),
-	CLK(NULL,	"cpefuse_fck",	&cpefuse_fck,	CK_3430ES2 | CK_AM35XX),
-	CLK(NULL,	"ts_fck",	&ts_fck,	CK_3430ES2 | CK_AM35XX),
-	CLK(NULL,	"usbtll_fck",	&usbtll_fck,	CK_3430ES2 | CK_AM35XX),
+	CLK(NULL,	"cpefuse_fck",	&cpefuse_fck,	CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
+	CLK(NULL,	"ts_fck",	&ts_fck,	CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
+	CLK(NULL,	"usbtll_fck",	&usbtll_fck,	CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
+	CLK("ehci-omap.0",	"usbtll_fck",	&usbtll_fck,	CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
 	CLK("omap-mcbsp.1",	"prcm_fck",	&core_96m_fck,	CK_3XXX),
 	CLK("omap-mcbsp.5",	"prcm_fck",	&core_96m_fck,	CK_3XXX),
 	CLK(NULL,	"core_96m_fck",	&core_96m_fck,	CK_3XXX),
-	CLK("mmci-omap-hs.2",	"fck",	&mmchs3_fck,	CK_3430ES2 | CK_AM35XX),
+	CLK("mmci-omap-hs.2",	"fck",	&mmchs3_fck,	CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
 	CLK("mmci-omap-hs.1",	"fck",	&mmchs2_fck,	CK_3XXX),
-	CLK(NULL,	"mspro_fck",	&mspro_fck,	CK_343X),
+	CLK(NULL,	"mspro_fck",	&mspro_fck,	CK_34XX | CK_36XX),
 	CLK("mmci-omap-hs.0",	"fck",	&mmchs1_fck,	CK_3XXX),
-	CLK("i2c_omap.3", "fck",	&i2c3_fck,	CK_3XXX),
-	CLK("i2c_omap.2", "fck",	&i2c2_fck,	CK_3XXX),
-	CLK("i2c_omap.1", "fck",	&i2c1_fck,	CK_3XXX),
+	CLK("omap_i2c.3", "fck",	&i2c3_fck,	CK_3XXX),
+	CLK("omap_i2c.2", "fck",	&i2c2_fck,	CK_3XXX),
+	CLK("omap_i2c.1", "fck",	&i2c1_fck,	CK_3XXX),
 	CLK("omap-mcbsp.5", "fck",	&mcbsp5_fck,	CK_3XXX),
 	CLK("omap-mcbsp.1", "fck",	&mcbsp1_fck,	CK_3XXX),
 	CLK(NULL,	"core_48m_fck",	&core_48m_fck,	CK_3XXX),
@@ -3301,34 +3310,35 @@ static struct omap_clk omap3xxx_clks[] =
 	CLK(NULL,	"core_12m_fck",	&core_12m_fck,	CK_3XXX),
 	CLK("omap_hdq.0", "fck",	&hdq_fck,	CK_3XXX),
 	CLK(NULL,	"ssi_ssr_fck",	&ssi_ssr_fck_3430es1,	CK_3430ES1),
-	CLK(NULL,	"ssi_ssr_fck",	&ssi_ssr_fck_3430es2,	CK_3430ES2),
+	CLK(NULL,	"ssi_ssr_fck",	&ssi_ssr_fck_3430es2,	CK_3430ES2PLUS | CK_36XX),
 	CLK(NULL,	"ssi_sst_fck",	&ssi_sst_fck_3430es1,	CK_3430ES1),
-	CLK(NULL,	"ssi_sst_fck",	&ssi_sst_fck_3430es2,	CK_3430ES2),
+	CLK(NULL,	"ssi_sst_fck",	&ssi_sst_fck_3430es2,	CK_3430ES2PLUS | CK_36XX),
 	CLK(NULL,	"core_l3_ick",	&core_l3_ick,	CK_3XXX),
-	CLK("musb_hdrc",	"ick",	&hsotgusb_ick_3430es1,	CK_3430ES1),
-	CLK("musb_hdrc",	"ick",	&hsotgusb_ick_3430es2,	CK_3430ES2),
+	CLK("musb-omap2430",	"ick",	&hsotgusb_ick_3430es1,	CK_3430ES1),
+	CLK("musb-omap2430",	"ick",	&hsotgusb_ick_3430es2,	CK_3430ES2PLUS | CK_36XX),
 	CLK(NULL,	"sdrc_ick",	&sdrc_ick,	CK_3XXX),
 	CLK(NULL,	"gpmc_fck",	&gpmc_fck,	CK_3XXX),
-	CLK(NULL,	"security_l3_ick", &security_l3_ick, CK_343X),
-	CLK(NULL,	"pka_ick",	&pka_ick,	CK_343X),
+	CLK(NULL,	"security_l3_ick", &security_l3_ick, CK_34XX | CK_36XX),
+	CLK(NULL,	"pka_ick",	&pka_ick,	CK_34XX | CK_36XX),
 	CLK(NULL,	"core_l4_ick",	&core_l4_ick,	CK_3XXX),
-	CLK(NULL,	"usbtll_ick",	&usbtll_ick,	CK_3430ES2 | CK_AM35XX),
-	CLK("mmci-omap-hs.2",	"ick",	&mmchs3_ick,	CK_3430ES2 | CK_AM35XX),
-	CLK(NULL,	"icr_ick",	&icr_ick,	CK_343X),
-	CLK("omap-aes",	"ick",	&aes2_ick,	CK_343X),
-	CLK("omap-sham",	"ick",	&sha12_ick,	CK_343X),
-	CLK(NULL,	"des2_ick",	&des2_ick,	CK_343X),
+	CLK(NULL,	"usbtll_ick",	&usbtll_ick,	CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
+	CLK("ehci-omap.0",	"usbtll_ick",	&usbtll_ick,	CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
+	CLK("mmci-omap-hs.2",	"ick",	&mmchs3_ick,	CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
+	CLK(NULL,	"icr_ick",	&icr_ick,	CK_34XX | CK_36XX),
+	CLK("omap-aes",	"ick",	&aes2_ick,	CK_34XX | CK_36XX),
+	CLK("omap-sham",	"ick",	&sha12_ick,	CK_34XX | CK_36XX),
+	CLK(NULL,	"des2_ick",	&des2_ick,	CK_34XX | CK_36XX),
 	CLK("mmci-omap-hs.1",	"ick",	&mmchs2_ick,	CK_3XXX),
 	CLK("mmci-omap-hs.0",	"ick",	&mmchs1_ick,	CK_3XXX),
-	CLK(NULL,	"mspro_ick",	&mspro_ick,	CK_343X),
+	CLK(NULL,	"mspro_ick",	&mspro_ick,	CK_34XX | CK_36XX),
 	CLK("omap_hdq.0", "ick",	&hdq_ick,	CK_3XXX),
 	CLK("omap2_mcspi.4", "ick",	&mcspi4_ick,	CK_3XXX),
 	CLK("omap2_mcspi.3", "ick",	&mcspi3_ick,	CK_3XXX),
 	CLK("omap2_mcspi.2", "ick",	&mcspi2_ick,	CK_3XXX),
 	CLK("omap2_mcspi.1", "ick",	&mcspi1_ick,	CK_3XXX),
-	CLK("i2c_omap.3", "ick",	&i2c3_ick,	CK_3XXX),
-	CLK("i2c_omap.2", "ick",	&i2c2_ick,	CK_3XXX),
-	CLK("i2c_omap.1", "ick",	&i2c1_ick,	CK_3XXX),
+	CLK("omap_i2c.3", "ick",	&i2c3_ick,	CK_3XXX),
+	CLK("omap_i2c.2", "ick",	&i2c2_ick,	CK_3XXX),
+	CLK("omap_i2c.1", "ick",	&i2c1_ick,	CK_3XXX),
 	CLK(NULL,	"uart2_ick",	&uart2_ick,	CK_3XXX),
 	CLK(NULL,	"uart1_ick",	&uart1_ick,	CK_3XXX),
 	CLK(NULL,	"gpt11_ick",	&gpt11_ick,	CK_3XXX),
@@ -3336,37 +3346,40 @@ static struct omap_clk omap3xxx_clks[] =
 	CLK("omap-mcbsp.5", "ick",	&mcbsp5_ick,	CK_3XXX),
 	CLK("omap-mcbsp.1", "ick",	&mcbsp1_ick,	CK_3XXX),
 	CLK(NULL,	"fac_ick",	&fac_ick,	CK_3430ES1),
-	CLK(NULL,	"mailboxes_ick", &mailboxes_ick, CK_343X),
+	CLK(NULL,	"mailboxes_ick", &mailboxes_ick, CK_34XX | CK_36XX),
 	CLK(NULL,	"omapctrl_ick",	&omapctrl_ick,	CK_3XXX),
-	CLK(NULL,	"ssi_l4_ick",	&ssi_l4_ick,	CK_343X),
+	CLK(NULL,	"ssi_l4_ick",	&ssi_l4_ick,	CK_34XX | CK_36XX),
 	CLK(NULL,	"ssi_ick",	&ssi_ick_3430es1,	CK_3430ES1),
-	CLK(NULL,	"ssi_ick",	&ssi_ick_3430es2,	CK_3430ES2),
+	CLK(NULL,	"ssi_ick",	&ssi_ick_3430es2,	CK_3430ES2PLUS | CK_36XX),
 	CLK(NULL,	"usb_l4_ick",	&usb_l4_ick,	CK_3430ES1),
-	CLK(NULL,	"security_l4_ick2", &security_l4_ick2, CK_343X),
-	CLK(NULL,	"aes1_ick",	&aes1_ick,	CK_343X),
-	CLK("omap_rng",	"ick",		&rng_ick,	CK_343X),
-	CLK(NULL,	"sha11_ick",	&sha11_ick,	CK_343X),
-	CLK(NULL,	"des1_ick",	&des1_ick,	CK_343X),
+	CLK(NULL,	"security_l4_ick2", &security_l4_ick2, CK_34XX | CK_36XX),
+	CLK(NULL,	"aes1_ick",	&aes1_ick,	CK_34XX | CK_36XX),
+	CLK("omap_rng",	"ick",		&rng_ick,	CK_34XX | CK_36XX),
+	CLK(NULL,	"sha11_ick",	&sha11_ick,	CK_34XX | CK_36XX),
+	CLK(NULL,	"des1_ick",	&des1_ick,	CK_34XX | CK_36XX),
 	CLK("omapdss",	"dss1_fck",	&dss1_alwon_fck_3430es1, CK_3430ES1),
-	CLK("omapdss",	"dss1_fck",	&dss1_alwon_fck_3430es2, CK_3430ES2 | CK_AM35XX),
+	CLK("omapdss",	"dss1_fck",	&dss1_alwon_fck_3430es2, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
 	CLK("omapdss",	"tv_fck",	&dss_tv_fck,	CK_3XXX),
 	CLK("omapdss",	"video_fck",	&dss_96m_fck,	CK_3XXX),
 	CLK("omapdss",	"dss2_fck",	&dss2_alwon_fck, CK_3XXX),
 	CLK("omapdss",	"ick",		&dss_ick_3430es1,	CK_3430ES1),
-	CLK("omapdss",	"ick",		&dss_ick_3430es2,	CK_3430ES2 | CK_AM35XX),
-	CLK(NULL,	"cam_mclk",	&cam_mclk,	CK_343X),
-	CLK(NULL,	"cam_ick",	&cam_ick,	CK_343X),
-	CLK(NULL,	"csi2_96m_fck",	&csi2_96m_fck,	CK_343X),
-	CLK(NULL,	"usbhost_120m_fck", &usbhost_120m_fck, CK_3430ES2 | CK_AM35XX),
-	CLK(NULL,	"usbhost_48m_fck", &usbhost_48m_fck, CK_3430ES2 | CK_AM35XX),
-	CLK(NULL,	"usbhost_ick",	&usbhost_ick,	CK_3430ES2 | CK_AM35XX),
-	CLK(NULL,	"usim_fck",	&usim_fck,	CK_3430ES2),
+	CLK("omapdss",	"ick",		&dss_ick_3430es2,	CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
+	CLK(NULL,	"cam_mclk",	&cam_mclk,	CK_34XX | CK_36XX),
+	CLK(NULL,	"cam_ick",	&cam_ick,	CK_34XX | CK_36XX),
+	CLK(NULL,	"csi2_96m_fck",	&csi2_96m_fck,	CK_34XX | CK_36XX),
+	CLK(NULL,	"usbhost_120m_fck", &usbhost_120m_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
+	CLK("ehci-omap.0",	"hs_fck", &usbhost_120m_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
+	CLK(NULL,	"usbhost_48m_fck", &usbhost_48m_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
+	CLK("ehci-omap.0",	"fs_fck", &usbhost_48m_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
+	CLK(NULL,	"usbhost_ick",	&usbhost_ick,	CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
+	CLK("ehci-omap.0",	"usbhost_ick",	&usbhost_ick,	CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
+	CLK(NULL,	"usim_fck",	&usim_fck,	CK_3430ES2PLUS | CK_36XX),
 	CLK(NULL,	"gpt1_fck",	&gpt1_fck,	CK_3XXX),
 	CLK(NULL,	"wkup_32k_fck",	&wkup_32k_fck,	CK_3XXX),
 	CLK(NULL,	"gpio1_dbck",	&gpio1_dbck,	CK_3XXX),
 	CLK("omap_wdt",	"fck",		&wdt2_fck,	CK_3XXX),
-	CLK(NULL,	"wkup_l4_ick",	&wkup_l4_ick,	CK_343X),
-	CLK(NULL,	"usim_ick",	&usim_ick,	CK_3430ES2),
+	CLK(NULL,	"wkup_l4_ick",	&wkup_l4_ick,	CK_34XX | CK_36XX),
+	CLK(NULL,	"usim_ick",	&usim_ick,	CK_3430ES2PLUS | CK_36XX),
 	CLK("omap_wdt",	"ick",		&wdt2_ick,	CK_3XXX),
 	CLK(NULL,	"wdt1_ick",	&wdt1_ick,	CK_3XXX),
 	CLK(NULL,	"gpio1_ick",	&gpio1_ick,	CK_3XXX),
@@ -3424,9 +3437,9 @@ static struct omap_clk omap3xxx_clks[] =
 	CLK(NULL,	"atclk_fck",	&atclk_fck,	CK_3XXX),
 	CLK(NULL,	"traceclk_src_fck", &traceclk_src_fck, CK_3XXX),
 	CLK(NULL,	"traceclk_fck",	&traceclk_fck,	CK_3XXX),
-	CLK(NULL,	"sr1_fck",	&sr1_fck,	CK_343X),
-	CLK(NULL,	"sr2_fck",	&sr2_fck,	CK_343X),
-	CLK(NULL,	"sr_l4_ick",	&sr_l4_ick,	CK_343X),
+	CLK(NULL,	"sr1_fck",	&sr1_fck,	CK_34XX | CK_36XX),
+	CLK(NULL,	"sr2_fck",	&sr2_fck,	CK_34XX | CK_36XX),
+	CLK(NULL,	"sr_l4_ick",	&sr_l4_ick,	CK_34XX | CK_36XX),
 	CLK(NULL,	"secure_32k_fck", &secure_32k_fck, CK_3XXX),
 	CLK(NULL,	"gpt12_fck",	&gpt12_fck,	CK_3XXX),
 	CLK(NULL,	"wdt1_fck",	&wdt1_fck,	CK_3XXX),
@@ -3437,8 +3450,8 @@ static struct omap_clk omap3xxx_clks[] =
 	CLK("davinci_emac",	"phy_clk",	&emac_fck,	CK_AM35XX),
 	CLK("vpfe-capture",	"master",	&vpfe_ick,	CK_AM35XX),
 	CLK("vpfe-capture",	"slave",	&vpfe_fck,	CK_AM35XX),
-	CLK("musb_hdrc",	"ick",		&hsotgusb_ick_am35xx,	CK_AM35XX),
-	CLK("musb_hdrc",	"fck",		&hsotgusb_fck_am35xx,	CK_AM35XX),
+	CLK("musb-am35x",	"ick",		&hsotgusb_ick_am35xx,	CK_AM35XX),
+	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),
 };
@@ -3447,38 +3460,37 @@ static struct omap_clk omap3xxx_clks[] =
 int __init omap3xxx_clk_init(void)
 {
 	struct omap_clk *c;
-	u32 cpu_clkflg = CK_3XXX;
+	u32 cpu_clkflg = 0;
 
 	if (cpu_is_omap3517()) {
-		cpu_mask = RATE_IN_3XXX | RATE_IN_3430ES2PLUS;
-		cpu_clkflg |= CK_3517;
+		cpu_mask = RATE_IN_34XX;
+		cpu_clkflg = CK_3517;
 	} else if (cpu_is_omap3505()) {
-		cpu_mask = RATE_IN_3XXX | RATE_IN_3430ES2PLUS;
-		cpu_clkflg |= CK_3505;
+		cpu_mask = RATE_IN_34XX;
+		cpu_clkflg = CK_3505;
+	} else if (cpu_is_omap3630()) {
+		cpu_mask = (RATE_IN_34XX | RATE_IN_36XX);
+		cpu_clkflg = CK_36XX;
 	} else if (cpu_is_omap34xx()) {
-		cpu_mask = RATE_IN_3XXX;
-		cpu_clkflg |= CK_343X;
-
-		/*
-		 * Update this if there are further clock changes between ES2
-		 * and production parts
-		 */
 		if (omap_rev() == OMAP3430_REV_ES1_0) {
-			/* No 3430ES1-only rates exist, so no RATE_IN_3430ES1 */
-			cpu_clkflg |= CK_3430ES1;
+			cpu_mask = RATE_IN_3430ES1;
+			cpu_clkflg = CK_3430ES1;
 		} else {
-			cpu_mask |= RATE_IN_3430ES2PLUS;
-			cpu_clkflg |= CK_3430ES2;
+			/*
+			 * Assume that anything that we haven't matched yet
+			 * has 3430ES2-type clocks.
+			 */
+			cpu_mask = RATE_IN_3430ES2PLUS;
+			cpu_clkflg = CK_3430ES2PLUS;
 		}
+	} else {
+		WARN(1, "clock: could not identify OMAP3 variant\n");
 	}
 
 	if (omap3_has_192mhz_clk())
 		omap_96m_alwon_fck = omap_96m_alwon_fck_3630;
 
 	if (cpu_is_omap3630()) {
-		cpu_mask |= RATE_IN_36XX;
-		cpu_clkflg |= CK_36XX;
-
 		/*
 		 * XXX This type of dynamic rewriting of the clock tree is
 		 * deprecated and should be revised soon.
@@ -3525,10 +3537,9 @@ int __init omap3xxx_clk_init(void)
 
 	recalculate_root_clocks();
 
-	printk(KERN_INFO "Clocking rate (Crystal/Core/MPU): "
-	       "%ld.%01ld/%ld/%ld MHz\n",
-	       (osc_sys_ck.rate / 1000000), (osc_sys_ck.rate / 100000) % 10,
-	       (core_ck.rate / 1000000), (arm_fck.rate / 1000000));
+	pr_info("Clocking rate (Crystal/Core/MPU): %ld.%01ld/%ld/%ld MHz\n",
+		(osc_sys_ck.rate / 1000000), (osc_sys_ck.rate / 100000) % 10,
+		(core_ck.rate / 1000000), (arm_fck.rate / 1000000));
 
 	/*
 	 * Only enable those clocks we will need, let the drivers
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/clock44xx_data.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/clock44xx_data.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/clock44xx_data.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/clock44xx_data.c	2011-03-14 21:20:32.000000000 -0400
@@ -30,11 +30,17 @@
 
 #include "clock.h"
 #include "clock44xx.h"
-#include "cm.h"
+#include "cm1_44xx.h"
+#include "cm2_44xx.h"
 #include "cm-regbits-44xx.h"
-#include "prm.h"
+#include "prm44xx.h"
 #include "prm-regbits-44xx.h"
 #include "control.h"
+#include "scrm44xx.h"
+
+/* OMAP4 modulemode control */
+#define OMAP4430_MODULEMODE_HWCTRL			0
+#define OMAP4430_MODULEMODE_SWCTRL			1
 
 /* Root clocks */
 
@@ -47,7 +53,9 @@ static struct clk extalt_clkin_ck = {
 static struct clk pad_clks_ck = {
 	.name		= "pad_clks_ck",
 	.rate		= 12000000,
-	.ops		= &clkops_null,
+	.ops            = &clkops_omap2_dflt,
+	.enable_reg     = OMAP4430_CM_CLKSEL_ABE,
+	.enable_bit     = OMAP4430_PAD_CLKS_GATE_SHIFT,
 };
 
 static struct clk pad_slimbus_core_clks_ck = {
@@ -65,7 +73,9 @@ static struct clk secure_32k_clk_src_ck
 static struct clk slimbus_clk = {
 	.name		= "slimbus_clk",
 	.rate		= 12000000,
-	.ops		= &clkops_null,
+	.ops            = &clkops_omap2_dflt,
+	.enable_reg     = OMAP4430_CM_CLKSEL_ABE,
+	.enable_bit     = OMAP4430_SLIMBUS_CLK_GATE_SHIFT,
 };
 
 static struct clk sys_32k_ck = {
@@ -265,18 +275,71 @@ static struct clk dpll_abe_ck = {
 	.set_rate	= &omap3_noncore_dpll_set_rate,
 };
 
+static struct clk dpll_abe_x2_ck = {
+	.name		= "dpll_abe_x2_ck",
+	.parent		= &dpll_abe_ck,
+	.ops		= &clkops_null,
+	.recalc		= &omap3_clkoutx2_recalc,
+};
+
+static const struct clksel_rate div31_1to31_rates[] = {
+	{ .div = 1, .val = 1, .flags = RATE_IN_4430 },
+	{ .div = 2, .val = 2, .flags = RATE_IN_4430 },
+	{ .div = 3, .val = 3, .flags = RATE_IN_4430 },
+	{ .div = 4, .val = 4, .flags = RATE_IN_4430 },
+	{ .div = 5, .val = 5, .flags = RATE_IN_4430 },
+	{ .div = 6, .val = 6, .flags = RATE_IN_4430 },
+	{ .div = 7, .val = 7, .flags = RATE_IN_4430 },
+	{ .div = 8, .val = 8, .flags = RATE_IN_4430 },
+	{ .div = 9, .val = 9, .flags = RATE_IN_4430 },
+	{ .div = 10, .val = 10, .flags = RATE_IN_4430 },
+	{ .div = 11, .val = 11, .flags = RATE_IN_4430 },
+	{ .div = 12, .val = 12, .flags = RATE_IN_4430 },
+	{ .div = 13, .val = 13, .flags = RATE_IN_4430 },
+	{ .div = 14, .val = 14, .flags = RATE_IN_4430 },
+	{ .div = 15, .val = 15, .flags = RATE_IN_4430 },
+	{ .div = 16, .val = 16, .flags = RATE_IN_4430 },
+	{ .div = 17, .val = 17, .flags = RATE_IN_4430 },
+	{ .div = 18, .val = 18, .flags = RATE_IN_4430 },
+	{ .div = 19, .val = 19, .flags = RATE_IN_4430 },
+	{ .div = 20, .val = 20, .flags = RATE_IN_4430 },
+	{ .div = 21, .val = 21, .flags = RATE_IN_4430 },
+	{ .div = 22, .val = 22, .flags = RATE_IN_4430 },
+	{ .div = 23, .val = 23, .flags = RATE_IN_4430 },
+	{ .div = 24, .val = 24, .flags = RATE_IN_4430 },
+	{ .div = 25, .val = 25, .flags = RATE_IN_4430 },
+	{ .div = 26, .val = 26, .flags = RATE_IN_4430 },
+	{ .div = 27, .val = 27, .flags = RATE_IN_4430 },
+	{ .div = 28, .val = 28, .flags = RATE_IN_4430 },
+	{ .div = 29, .val = 29, .flags = RATE_IN_4430 },
+	{ .div = 30, .val = 30, .flags = RATE_IN_4430 },
+	{ .div = 31, .val = 31, .flags = RATE_IN_4430 },
+	{ .div = 0 },
+};
+
+static const struct clksel dpll_abe_m2x2_div[] = {
+	{ .parent = &dpll_abe_x2_ck, .rates = div31_1to31_rates },
+	{ .parent = NULL },
+};
+
 static struct clk dpll_abe_m2x2_ck = {
 	.name		= "dpll_abe_m2x2_ck",
-	.parent		= &dpll_abe_ck,
+	.parent		= &dpll_abe_x2_ck,
+	.clksel		= dpll_abe_m2x2_div,
+	.clksel_reg	= OMAP4430_CM_DIV_M2_DPLL_ABE,
+	.clksel_mask	= OMAP4430_DPLL_CLKOUT_DIV_MASK,
 	.ops		= &clkops_null,
-	.recalc		= &followparent_recalc,
+	.recalc		= &omap2_clksel_recalc,
+	.round_rate	= &omap2_clksel_round_rate,
+	.set_rate	= &omap2_clksel_set_rate,
 };
 
 static struct clk abe_24m_fclk = {
 	.name		= "abe_24m_fclk",
 	.parent		= &dpll_abe_m2x2_ck,
 	.ops		= &clkops_null,
-	.recalc		= &followparent_recalc,
+	.fixed_div	= 8,
+	.recalc		= &omap_fixed_divisor_recalc,
 };
 
 static const struct clksel_rate div3_1to4_rates[] = {
@@ -326,50 +389,10 @@ static struct clk aess_fclk = {
 	.set_rate	= &omap2_clksel_set_rate,
 };
 
-static const struct clksel_rate div31_1to31_rates[] = {
-	{ .div = 1, .val = 1, .flags = RATE_IN_4430 },
-	{ .div = 2, .val = 2, .flags = RATE_IN_4430 },
-	{ .div = 3, .val = 3, .flags = RATE_IN_4430 },
-	{ .div = 4, .val = 4, .flags = RATE_IN_4430 },
-	{ .div = 5, .val = 5, .flags = RATE_IN_4430 },
-	{ .div = 6, .val = 6, .flags = RATE_IN_4430 },
-	{ .div = 7, .val = 7, .flags = RATE_IN_4430 },
-	{ .div = 8, .val = 8, .flags = RATE_IN_4430 },
-	{ .div = 9, .val = 9, .flags = RATE_IN_4430 },
-	{ .div = 10, .val = 10, .flags = RATE_IN_4430 },
-	{ .div = 11, .val = 11, .flags = RATE_IN_4430 },
-	{ .div = 12, .val = 12, .flags = RATE_IN_4430 },
-	{ .div = 13, .val = 13, .flags = RATE_IN_4430 },
-	{ .div = 14, .val = 14, .flags = RATE_IN_4430 },
-	{ .div = 15, .val = 15, .flags = RATE_IN_4430 },
-	{ .div = 16, .val = 16, .flags = RATE_IN_4430 },
-	{ .div = 17, .val = 17, .flags = RATE_IN_4430 },
-	{ .div = 18, .val = 18, .flags = RATE_IN_4430 },
-	{ .div = 19, .val = 19, .flags = RATE_IN_4430 },
-	{ .div = 20, .val = 20, .flags = RATE_IN_4430 },
-	{ .div = 21, .val = 21, .flags = RATE_IN_4430 },
-	{ .div = 22, .val = 22, .flags = RATE_IN_4430 },
-	{ .div = 23, .val = 23, .flags = RATE_IN_4430 },
-	{ .div = 24, .val = 24, .flags = RATE_IN_4430 },
-	{ .div = 25, .val = 25, .flags = RATE_IN_4430 },
-	{ .div = 26, .val = 26, .flags = RATE_IN_4430 },
-	{ .div = 27, .val = 27, .flags = RATE_IN_4430 },
-	{ .div = 28, .val = 28, .flags = RATE_IN_4430 },
-	{ .div = 29, .val = 29, .flags = RATE_IN_4430 },
-	{ .div = 30, .val = 30, .flags = RATE_IN_4430 },
-	{ .div = 31, .val = 31, .flags = RATE_IN_4430 },
-	{ .div = 0 },
-};
-
-static const struct clksel dpll_abe_m3_div[] = {
-	{ .parent = &dpll_abe_ck, .rates = div31_1to31_rates },
-	{ .parent = NULL },
-};
-
-static struct clk dpll_abe_m3_ck = {
-	.name		= "dpll_abe_m3_ck",
-	.parent		= &dpll_abe_ck,
-	.clksel		= dpll_abe_m3_div,
+static struct clk dpll_abe_m3x2_ck = {
+	.name		= "dpll_abe_m3x2_ck",
+	.parent		= &dpll_abe_x2_ck,
+	.clksel		= dpll_abe_m2x2_div,
 	.clksel_reg	= OMAP4430_CM_DIV_M3_DPLL_ABE,
 	.clksel_mask	= OMAP4430_DPLL_CLKOUTHIF_DIV_MASK,
 	.ops		= &clkops_null,
@@ -380,7 +403,7 @@ static struct clk dpll_abe_m3_ck = {
 
 static const struct clksel core_hsd_byp_clk_mux_sel[] = {
 	{ .parent = &sys_clkin_ck, .rates = div_1_0_rates },
-	{ .parent = &dpll_abe_m3_ck, .rates = div_1_1_rates },
+	{ .parent = &dpll_abe_m3x2_ck, .rates = div_1_1_rates },
 	{ .parent = NULL },
 };
 
@@ -424,15 +447,22 @@ static struct clk dpll_core_ck = {
 	.recalc		= &omap3_dpll_recalc,
 };
 
-static const struct clksel dpll_core_m6_div[] = {
-	{ .parent = &dpll_core_ck, .rates = div31_1to31_rates },
+static struct clk dpll_core_x2_ck = {
+	.name		= "dpll_core_x2_ck",
+	.parent		= &dpll_core_ck,
+	.ops		= &clkops_null,
+	.recalc		= &omap3_clkoutx2_recalc,
+};
+
+static const struct clksel dpll_core_m6x2_div[] = {
+	{ .parent = &dpll_core_x2_ck, .rates = div31_1to31_rates },
 	{ .parent = NULL },
 };
 
-static struct clk dpll_core_m6_ck = {
-	.name		= "dpll_core_m6_ck",
-	.parent		= &dpll_core_ck,
-	.clksel		= dpll_core_m6_div,
+static struct clk dpll_core_m6x2_ck = {
+	.name		= "dpll_core_m6x2_ck",
+	.parent		= &dpll_core_x2_ck,
+	.clksel		= dpll_core_m6x2_div,
 	.clksel_reg	= OMAP4430_CM_DIV_M6_DPLL_CORE,
 	.clksel_mask	= OMAP4430_HSDIVIDER_CLKOUT3_DIV_MASK,
 	.ops		= &clkops_null,
@@ -443,7 +473,7 @@ static struct clk dpll_core_m6_ck = {
 
 static const struct clksel dbgclk_mux_sel[] = {
 	{ .parent = &sys_clkin_ck, .rates = div_1_0_rates },
-	{ .parent = &dpll_core_m6_ck, .rates = div_1_1_rates },
+	{ .parent = &dpll_core_m6x2_ck, .rates = div_1_1_rates },
 	{ .parent = NULL },
 };
 
@@ -454,10 +484,15 @@ static struct clk dbgclk_mux_ck = {
 	.recalc		= &followparent_recalc,
 };
 
+static const struct clksel dpll_core_m2_div[] = {
+	{ .parent = &dpll_core_ck, .rates = div31_1to31_rates },
+	{ .parent = NULL },
+};
+
 static struct clk dpll_core_m2_ck = {
 	.name		= "dpll_core_m2_ck",
 	.parent		= &dpll_core_ck,
-	.clksel		= dpll_core_m6_div,
+	.clksel		= dpll_core_m2_div,
 	.clksel_reg	= OMAP4430_CM_DIV_M2_DPLL_CORE,
 	.clksel_mask	= OMAP4430_DPLL_CLKOUT_DIV_MASK,
 	.ops		= &clkops_null,
@@ -470,13 +505,14 @@ static struct clk ddrphy_ck = {
 	.name		= "ddrphy_ck",
 	.parent		= &dpll_core_m2_ck,
 	.ops		= &clkops_null,
-	.recalc		= &followparent_recalc,
+	.fixed_div	= 2,
+	.recalc		= &omap_fixed_divisor_recalc,
 };
 
-static struct clk dpll_core_m5_ck = {
-	.name		= "dpll_core_m5_ck",
-	.parent		= &dpll_core_ck,
-	.clksel		= dpll_core_m6_div,
+static struct clk dpll_core_m5x2_ck = {
+	.name		= "dpll_core_m5x2_ck",
+	.parent		= &dpll_core_x2_ck,
+	.clksel		= dpll_core_m6x2_div,
 	.clksel_reg	= OMAP4430_CM_DIV_M5_DPLL_CORE,
 	.clksel_mask	= OMAP4430_HSDIVIDER_CLKOUT2_DIV_MASK,
 	.ops		= &clkops_null,
@@ -486,13 +522,13 @@ static struct clk dpll_core_m5_ck = {
 };
 
 static const struct clksel div_core_div[] = {
-	{ .parent = &dpll_core_m5_ck, .rates = div2_1to2_rates },
+	{ .parent = &dpll_core_m5x2_ck, .rates = div2_1to2_rates },
 	{ .parent = NULL },
 };
 
 static struct clk div_core_ck = {
 	.name		= "div_core_ck",
-	.parent		= &dpll_core_m5_ck,
+	.parent		= &dpll_core_m5x2_ck,
 	.clksel		= div_core_div,
 	.clksel_reg	= OMAP4430_CM_CLKSEL_CORE,
 	.clksel_mask	= OMAP4430_CLKSEL_CORE_MASK,
@@ -511,13 +547,13 @@ static const struct clksel_rate div4_1to
 };
 
 static const struct clksel div_iva_hs_clk_div[] = {
-	{ .parent = &dpll_core_m5_ck, .rates = div4_1to8_rates },
+	{ .parent = &dpll_core_m5x2_ck, .rates = div4_1to8_rates },
 	{ .parent = NULL },
 };
 
 static struct clk div_iva_hs_clk = {
 	.name		= "div_iva_hs_clk",
-	.parent		= &dpll_core_m5_ck,
+	.parent		= &dpll_core_m5x2_ck,
 	.clksel		= div_iva_hs_clk_div,
 	.clksel_reg	= OMAP4430_CM_BYPCLK_DPLL_IVA,
 	.clksel_mask	= OMAP4430_CLKSEL_0_1_MASK,
@@ -529,7 +565,7 @@ static struct clk div_iva_hs_clk = {
 
 static struct clk div_mpu_hs_clk = {
 	.name		= "div_mpu_hs_clk",
-	.parent		= &dpll_core_m5_ck,
+	.parent		= &dpll_core_m5x2_ck,
 	.clksel		= div_iva_hs_clk_div,
 	.clksel_reg	= OMAP4430_CM_BYPCLK_DPLL_MPU,
 	.clksel_mask	= OMAP4430_CLKSEL_0_1_MASK,
@@ -539,10 +575,10 @@ static struct clk div_mpu_hs_clk = {
 	.set_rate	= &omap2_clksel_set_rate,
 };
 
-static struct clk dpll_core_m4_ck = {
-	.name		= "dpll_core_m4_ck",
-	.parent		= &dpll_core_ck,
-	.clksel		= dpll_core_m6_div,
+static struct clk dpll_core_m4x2_ck = {
+	.name		= "dpll_core_m4x2_ck",
+	.parent		= &dpll_core_x2_ck,
+	.clksel		= dpll_core_m6x2_div,
 	.clksel_reg	= OMAP4430_CM_DIV_M4_DPLL_CORE,
 	.clksel_mask	= OMAP4430_HSDIVIDER_CLKOUT1_DIV_MASK,
 	.ops		= &clkops_null,
@@ -553,15 +589,21 @@ static struct clk dpll_core_m4_ck = {
 
 static struct clk dll_clk_div_ck = {
 	.name		= "dll_clk_div_ck",
-	.parent		= &dpll_core_m4_ck,
+	.parent		= &dpll_core_m4x2_ck,
 	.ops		= &clkops_null,
-	.recalc		= &followparent_recalc,
+	.fixed_div	= 2,
+	.recalc		= &omap_fixed_divisor_recalc,
+};
+
+static const struct clksel dpll_abe_m2_div[] = {
+	{ .parent = &dpll_abe_ck, .rates = div31_1to31_rates },
+	{ .parent = NULL },
 };
 
 static struct clk dpll_abe_m2_ck = {
 	.name		= "dpll_abe_m2_ck",
 	.parent		= &dpll_abe_ck,
-	.clksel		= dpll_abe_m3_div,
+	.clksel		= dpll_abe_m2_div,
 	.clksel_reg	= OMAP4430_CM_DIV_M2_DPLL_ABE,
 	.clksel_mask	= OMAP4430_DPLL_CLKOUT_DIV_MASK,
 	.ops		= &clkops_null,
@@ -570,22 +612,24 @@ static struct clk dpll_abe_m2_ck = {
 	.set_rate	= &omap2_clksel_set_rate,
 };
 
-static struct clk dpll_core_m3_ck = {
-	.name		= "dpll_core_m3_ck",
-	.parent		= &dpll_core_ck,
-	.clksel		= dpll_core_m6_div,
+static struct clk dpll_core_m3x2_ck = {
+	.name		= "dpll_core_m3x2_ck",
+	.parent		= &dpll_core_x2_ck,
+	.clksel		= dpll_core_m6x2_div,
 	.clksel_reg	= OMAP4430_CM_DIV_M3_DPLL_CORE,
 	.clksel_mask	= OMAP4430_DPLL_CLKOUTHIF_DIV_MASK,
-	.ops		= &clkops_null,
+	.ops		= &clkops_omap2_dflt,
+	.enable_reg	= OMAP4430_CM_DIV_M3_DPLL_CORE,
+	.enable_bit	= OMAP4430_DPLL_CLKOUTHIF_GATE_CTRL_SHIFT,
 	.recalc		= &omap2_clksel_recalc,
 	.round_rate	= &omap2_clksel_round_rate,
 	.set_rate	= &omap2_clksel_set_rate,
 };
 
-static struct clk dpll_core_m7_ck = {
-	.name		= "dpll_core_m7_ck",
-	.parent		= &dpll_core_ck,
-	.clksel		= dpll_core_m6_div,
+static struct clk dpll_core_m7x2_ck = {
+	.name		= "dpll_core_m7x2_ck",
+	.parent		= &dpll_core_x2_ck,
+	.clksel		= dpll_core_m6x2_div,
 	.clksel_reg	= OMAP4430_CM_DIV_M7_DPLL_CORE,
 	.clksel_mask	= OMAP4430_HSDIVIDER_CLKOUT4_DIV_MASK,
 	.ops		= &clkops_null,
@@ -603,8 +647,12 @@ static const struct clksel iva_hsd_byp_c
 static struct clk iva_hsd_byp_clk_mux_ck = {
 	.name		= "iva_hsd_byp_clk_mux_ck",
 	.parent		= &sys_clkin_ck,
+	.clksel		= iva_hsd_byp_clk_mux_sel,
+	.init		= &omap2_init_clksel_parent,
+	.clksel_reg	= OMAP4430_CM_CLKSEL_DPLL_IVA,
+	.clksel_mask	= OMAP4430_DPLL_BYP_CLKSEL_MASK,
 	.ops		= &clkops_null,
-	.recalc		= &followparent_recalc,
+	.recalc		= &omap2_clksel_recalc,
 };
 
 /* DPLL_IVA */
@@ -638,15 +686,22 @@ static struct clk dpll_iva_ck = {
 	.set_rate	= &omap3_noncore_dpll_set_rate,
 };
 
-static const struct clksel dpll_iva_m4_div[] = {
-	{ .parent = &dpll_iva_ck, .rates = div31_1to31_rates },
+static struct clk dpll_iva_x2_ck = {
+	.name		= "dpll_iva_x2_ck",
+	.parent		= &dpll_iva_ck,
+	.ops		= &clkops_null,
+	.recalc		= &omap3_clkoutx2_recalc,
+};
+
+static const struct clksel dpll_iva_m4x2_div[] = {
+	{ .parent = &dpll_iva_x2_ck, .rates = div31_1to31_rates },
 	{ .parent = NULL },
 };
 
-static struct clk dpll_iva_m4_ck = {
-	.name		= "dpll_iva_m4_ck",
-	.parent		= &dpll_iva_ck,
-	.clksel		= dpll_iva_m4_div,
+static struct clk dpll_iva_m4x2_ck = {
+	.name		= "dpll_iva_m4x2_ck",
+	.parent		= &dpll_iva_x2_ck,
+	.clksel		= dpll_iva_m4x2_div,
 	.clksel_reg	= OMAP4430_CM_DIV_M4_DPLL_IVA,
 	.clksel_mask	= OMAP4430_HSDIVIDER_CLKOUT1_DIV_MASK,
 	.ops		= &clkops_null,
@@ -655,10 +710,10 @@ static struct clk dpll_iva_m4_ck = {
 	.set_rate	= &omap2_clksel_set_rate,
 };
 
-static struct clk dpll_iva_m5_ck = {
-	.name		= "dpll_iva_m5_ck",
-	.parent		= &dpll_iva_ck,
-	.clksel		= dpll_iva_m4_div,
+static struct clk dpll_iva_m5x2_ck = {
+	.name		= "dpll_iva_m5x2_ck",
+	.parent		= &dpll_iva_x2_ck,
+	.clksel		= dpll_iva_m4x2_div,
 	.clksel_reg	= OMAP4430_CM_DIV_M5_DPLL_IVA,
 	.clksel_mask	= OMAP4430_HSDIVIDER_CLKOUT2_DIV_MASK,
 	.ops		= &clkops_null,
@@ -717,9 +772,10 @@ static struct clk dpll_mpu_m2_ck = {
 
 static struct clk per_hs_clk_div_ck = {
 	.name		= "per_hs_clk_div_ck",
-	.parent		= &dpll_abe_m3_ck,
+	.parent		= &dpll_abe_m3x2_ck,
 	.ops		= &clkops_null,
-	.recalc		= &followparent_recalc,
+	.fixed_div	= 2,
+	.recalc		= &omap_fixed_divisor_recalc,
 };
 
 static const struct clksel per_hsd_byp_clk_mux_sel[] = {
@@ -787,29 +843,48 @@ static struct clk dpll_per_m2_ck = {
 	.set_rate	= &omap2_clksel_set_rate,
 };
 
+static struct clk dpll_per_x2_ck = {
+	.name		= "dpll_per_x2_ck",
+	.parent		= &dpll_per_ck,
+	.ops		= &clkops_null,
+	.recalc		= &omap3_clkoutx2_recalc,
+};
+
+static const struct clksel dpll_per_m2x2_div[] = {
+	{ .parent = &dpll_per_x2_ck, .rates = div31_1to31_rates },
+	{ .parent = NULL },
+};
+
 static struct clk dpll_per_m2x2_ck = {
 	.name		= "dpll_per_m2x2_ck",
-	.parent		= &dpll_per_ck,
+	.parent		= &dpll_per_x2_ck,
+	.clksel		= dpll_per_m2x2_div,
+	.clksel_reg	= OMAP4430_CM_DIV_M2_DPLL_PER,
+	.clksel_mask	= OMAP4430_DPLL_CLKOUT_DIV_MASK,
 	.ops		= &clkops_null,
-	.recalc		= &followparent_recalc,
+	.recalc		= &omap2_clksel_recalc,
+	.round_rate	= &omap2_clksel_round_rate,
+	.set_rate	= &omap2_clksel_set_rate,
 };
 
-static struct clk dpll_per_m3_ck = {
-	.name		= "dpll_per_m3_ck",
-	.parent		= &dpll_per_ck,
-	.clksel		= dpll_per_m2_div,
+static struct clk dpll_per_m3x2_ck = {
+	.name		= "dpll_per_m3x2_ck",
+	.parent		= &dpll_per_x2_ck,
+	.clksel		= dpll_per_m2x2_div,
 	.clksel_reg	= OMAP4430_CM_DIV_M3_DPLL_PER,
 	.clksel_mask	= OMAP4430_DPLL_CLKOUTHIF_DIV_MASK,
-	.ops		= &clkops_null,
+	.ops		= &clkops_omap2_dflt,
+	.enable_reg	= OMAP4430_CM_DIV_M3_DPLL_PER,
+	.enable_bit	= OMAP4430_DPLL_CLKOUTHIF_GATE_CTRL_SHIFT,
 	.recalc		= &omap2_clksel_recalc,
 	.round_rate	= &omap2_clksel_round_rate,
 	.set_rate	= &omap2_clksel_set_rate,
 };
 
-static struct clk dpll_per_m4_ck = {
-	.name		= "dpll_per_m4_ck",
-	.parent		= &dpll_per_ck,
-	.clksel		= dpll_per_m2_div,
+static struct clk dpll_per_m4x2_ck = {
+	.name		= "dpll_per_m4x2_ck",
+	.parent		= &dpll_per_x2_ck,
+	.clksel		= dpll_per_m2x2_div,
 	.clksel_reg	= OMAP4430_CM_DIV_M4_DPLL_PER,
 	.clksel_mask	= OMAP4430_HSDIVIDER_CLKOUT1_DIV_MASK,
 	.ops		= &clkops_null,
@@ -818,10 +893,10 @@ static struct clk dpll_per_m4_ck = {
 	.set_rate	= &omap2_clksel_set_rate,
 };
 
-static struct clk dpll_per_m5_ck = {
-	.name		= "dpll_per_m5_ck",
-	.parent		= &dpll_per_ck,
-	.clksel		= dpll_per_m2_div,
+static struct clk dpll_per_m5x2_ck = {
+	.name		= "dpll_per_m5x2_ck",
+	.parent		= &dpll_per_x2_ck,
+	.clksel		= dpll_per_m2x2_div,
 	.clksel_reg	= OMAP4430_CM_DIV_M5_DPLL_PER,
 	.clksel_mask	= OMAP4430_HSDIVIDER_CLKOUT2_DIV_MASK,
 	.ops		= &clkops_null,
@@ -830,10 +905,10 @@ static struct clk dpll_per_m5_ck = {
 	.set_rate	= &omap2_clksel_set_rate,
 };
 
-static struct clk dpll_per_m6_ck = {
-	.name		= "dpll_per_m6_ck",
-	.parent		= &dpll_per_ck,
-	.clksel		= dpll_per_m2_div,
+static struct clk dpll_per_m6x2_ck = {
+	.name		= "dpll_per_m6x2_ck",
+	.parent		= &dpll_per_x2_ck,
+	.clksel		= dpll_per_m2x2_div,
 	.clksel_reg	= OMAP4430_CM_DIV_M6_DPLL_PER,
 	.clksel_mask	= OMAP4430_HSDIVIDER_CLKOUT3_DIV_MASK,
 	.ops		= &clkops_null,
@@ -842,10 +917,10 @@ static struct clk dpll_per_m6_ck = {
 	.set_rate	= &omap2_clksel_set_rate,
 };
 
-static struct clk dpll_per_m7_ck = {
-	.name		= "dpll_per_m7_ck",
-	.parent		= &dpll_per_ck,
-	.clksel		= dpll_per_m2_div,
+static struct clk dpll_per_m7x2_ck = {
+	.name		= "dpll_per_m7x2_ck",
+	.parent		= &dpll_per_x2_ck,
+	.clksel		= dpll_per_m2x2_div,
 	.clksel_reg	= OMAP4430_CM_DIV_M7_DPLL_PER,
 	.clksel_mask	= OMAP4430_HSDIVIDER_CLKOUT4_DIV_MASK,
 	.ops		= &clkops_null,
@@ -868,6 +943,7 @@ static struct dpll_data dpll_unipro_dd =
 	.enable_mask	= OMAP4430_DPLL_EN_MASK,
 	.autoidle_mask	= OMAP4430_AUTO_DPLL_MODE_MASK,
 	.idlest_mask	= OMAP4430_ST_DPLL_CLK_MASK,
+	.sddiv_mask	= OMAP4430_DPLL_SD_DIV_MASK,
 	.max_multiplier	= OMAP4430_MAX_DPLL_MULT,
 	.max_divider	= OMAP4430_MAX_DPLL_DIV,
 	.min_divider	= 1,
@@ -885,14 +961,21 @@ static struct clk dpll_unipro_ck = {
 	.set_rate	= &omap3_noncore_dpll_set_rate,
 };
 
+static struct clk dpll_unipro_x2_ck = {
+	.name		= "dpll_unipro_x2_ck",
+	.parent		= &dpll_unipro_ck,
+	.ops		= &clkops_null,
+	.recalc		= &omap3_clkoutx2_recalc,
+};
+
 static const struct clksel dpll_unipro_m2x2_div[] = {
-	{ .parent = &dpll_unipro_ck, .rates = div31_1to31_rates },
+	{ .parent = &dpll_unipro_x2_ck, .rates = div31_1to31_rates },
 	{ .parent = NULL },
 };
 
 static struct clk dpll_unipro_m2x2_ck = {
 	.name		= "dpll_unipro_m2x2_ck",
-	.parent		= &dpll_unipro_ck,
+	.parent		= &dpll_unipro_x2_ck,
 	.clksel		= dpll_unipro_m2x2_div,
 	.clksel_reg	= OMAP4430_CM_DIV_M2_DPLL_UNIPRO,
 	.clksel_mask	= OMAP4430_DPLL_CLKOUT_DIV_MASK,
@@ -904,16 +987,17 @@ static struct clk dpll_unipro_m2x2_ck =
 
 static struct clk usb_hs_clk_div_ck = {
 	.name		= "usb_hs_clk_div_ck",
-	.parent		= &dpll_abe_m3_ck,
+	.parent		= &dpll_abe_m3x2_ck,
 	.ops		= &clkops_null,
-	.recalc		= &followparent_recalc,
+	.fixed_div	= 3,
+	.recalc		= &omap_fixed_divisor_recalc,
 };
 
 /* DPLL_USB */
 static struct dpll_data dpll_usb_dd = {
 	.mult_div1_reg	= OMAP4430_CM_CLKSEL_DPLL_USB,
 	.clk_bypass	= &usb_hs_clk_div_ck,
-	.flags		= DPLL_J_TYPE | DPLL_NO_DCO_SEL,
+	.flags		= DPLL_J_TYPE,
 	.clk_ref	= &sys_clkin_ck,
 	.control_reg	= OMAP4430_CM_CLKMODE_DPLL_USB,
 	.modes		= (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
@@ -967,7 +1051,7 @@ static struct clk dpll_usb_m2_ck = {
 
 static const struct clksel ducati_clk_mux_sel[] = {
 	{ .parent = &div_core_ck, .rates = div_1_0_rates },
-	{ .parent = &dpll_per_m6_ck, .rates = div_1_1_rates },
+	{ .parent = &dpll_per_m6x2_ck, .rates = div_1_1_rates },
 	{ .parent = NULL },
 };
 
@@ -986,21 +1070,24 @@ static struct clk func_12m_fclk = {
 	.name		= "func_12m_fclk",
 	.parent		= &dpll_per_m2x2_ck,
 	.ops		= &clkops_null,
-	.recalc		= &followparent_recalc,
+	.fixed_div	= 16,
+	.recalc		= &omap_fixed_divisor_recalc,
 };
 
 static struct clk func_24m_clk = {
 	.name		= "func_24m_clk",
 	.parent		= &dpll_per_m2_ck,
 	.ops		= &clkops_null,
-	.recalc		= &followparent_recalc,
+	.fixed_div	= 4,
+	.recalc		= &omap_fixed_divisor_recalc,
 };
 
 static struct clk func_24mc_fclk = {
 	.name		= "func_24mc_fclk",
 	.parent		= &dpll_per_m2x2_ck,
 	.ops		= &clkops_null,
-	.recalc		= &followparent_recalc,
+	.fixed_div	= 8,
+	.recalc		= &omap_fixed_divisor_recalc,
 };
 
 static const struct clksel_rate div2_4to8_rates[] = {
@@ -1030,7 +1117,8 @@ static struct clk func_48mc_fclk = {
 	.name		= "func_48mc_fclk",
 	.parent		= &dpll_per_m2x2_ck,
 	.ops		= &clkops_null,
-	.recalc		= &followparent_recalc,
+	.fixed_div	= 4,
+	.recalc		= &omap_fixed_divisor_recalc,
 };
 
 static const struct clksel_rate div2_2to4_rates[] = {
@@ -1040,13 +1128,13 @@ static const struct clksel_rate div2_2to
 };
 
 static const struct clksel func_64m_fclk_div[] = {
-	{ .parent = &dpll_per_m4_ck, .rates = div2_2to4_rates },
+	{ .parent = &dpll_per_m4x2_ck, .rates = div2_2to4_rates },
 	{ .parent = NULL },
 };
 
 static struct clk func_64m_fclk = {
 	.name		= "func_64m_fclk",
-	.parent		= &dpll_per_m4_ck,
+	.parent		= &dpll_per_m4x2_ck,
 	.clksel		= func_64m_fclk_div,
 	.clksel_reg	= OMAP4430_CM_SCALE_FCLK,
 	.clksel_mask	= OMAP4430_SCALE_FCLK_MASK,
@@ -1147,7 +1235,8 @@ static struct clk lp_clk_div_ck = {
 	.name		= "lp_clk_div_ck",
 	.parent		= &dpll_abe_m2x2_ck,
 	.ops		= &clkops_null,
-	.recalc		= &followparent_recalc,
+	.fixed_div	= 16,
+	.recalc		= &omap_fixed_divisor_recalc,
 };
 
 static const struct clksel l4_wkup_clk_mux_sel[] = {
@@ -1215,12 +1304,13 @@ static struct clk per_abe_24m_fclk = {
 	.name		= "per_abe_24m_fclk",
 	.parent		= &dpll_abe_m2_ck,
 	.ops		= &clkops_null,
-	.recalc		= &followparent_recalc,
+	.fixed_div	= 4,
+	.recalc		= &omap_fixed_divisor_recalc,
 };
 
 static const struct clksel pmd_stm_clock_mux_sel[] = {
 	{ .parent = &sys_clkin_ck, .rates = div_1_0_rates },
-	{ .parent = &dpll_core_m6_ck, .rates = div_1_1_rates },
+	{ .parent = &dpll_core_m6x2_ck, .rates = div_1_1_rates },
 	{ .parent = &tie_low_clock_ck, .rates = div_1_2_rates },
 	{ .parent = NULL },
 };
@@ -1354,7 +1444,7 @@ static struct clk dsp_fck = {
 	.enable_reg	= OMAP4430_CM_TESLA_TESLA_CLKCTRL,
 	.enable_bit	= OMAP4430_MODULEMODE_HWCTRL,
 	.clkdm_name	= "tesla_clkdm",
-	.parent		= &dpll_iva_m4_ck,
+	.parent		= &dpll_iva_m4x2_ck,
 	.recalc		= &followparent_recalc,
 };
 
@@ -1384,7 +1474,7 @@ static struct clk dss_dss_clk = {
 	.enable_reg	= OMAP4430_CM_DSS_DSS_CLKCTRL,
 	.enable_bit	= OMAP4430_OPTFCLKEN_DSSCLK_SHIFT,
 	.clkdm_name	= "l3_dss_clkdm",
-	.parent		= &dpll_per_m5_ck,
+	.parent		= &dpll_per_m5x2_ck,
 	.recalc		= &followparent_recalc,
 };
 
@@ -1441,14 +1531,14 @@ static struct clk emif2_fck = {
 };
 
 static const struct clksel fdif_fclk_div[] = {
-	{ .parent = &dpll_per_m4_ck, .rates = div3_1to4_rates },
+	{ .parent = &dpll_per_m4x2_ck, .rates = div3_1to4_rates },
 	{ .parent = NULL },
 };
 
 /* Merged fdif_fclk into fdif */
 static struct clk fdif_fck = {
 	.name		= "fdif_fck",
-	.parent		= &dpll_per_m4_ck,
+	.parent		= &dpll_per_m4x2_ck,
 	.clksel		= fdif_fclk_div,
 	.clksel_reg	= OMAP4430_CM_CAM_FDIF_CLKCTRL,
 	.clksel_mask	= OMAP4430_CLKSEL_FCLK_MASK,
@@ -1602,15 +1692,15 @@ static struct clk gpmc_ick = {
 };
 
 static const struct clksel sgx_clk_mux_sel[] = {
-	{ .parent = &dpll_core_m7_ck, .rates = div_1_0_rates },
-	{ .parent = &dpll_per_m7_ck, .rates = div_1_1_rates },
+	{ .parent = &dpll_core_m7x2_ck, .rates = div_1_0_rates },
+	{ .parent = &dpll_per_m7x2_ck, .rates = div_1_1_rates },
 	{ .parent = NULL },
 };
 
 /* Merged sgx_clk_mux into gpu */
 static struct clk gpu_fck = {
 	.name		= "gpu_fck",
-	.parent		= &dpll_core_m7_ck,
+	.parent		= &dpll_core_m7x2_ck,
 	.clksel		= sgx_clk_mux_sel,
 	.init		= &omap2_init_clksel_parent,
 	.clksel_reg	= OMAP4430_CM_GFX_GFX_CLKCTRL,
@@ -1729,7 +1819,7 @@ static struct clk iva_fck = {
 	.enable_reg	= OMAP4430_CM_IVAHD_IVAHD_CLKCTRL,
 	.enable_bit	= OMAP4430_MODULEMODE_HWCTRL,
 	.clkdm_name	= "ivahd_clkdm",
-	.parent		= &dpll_iva_m5_ck,
+	.parent		= &dpll_iva_m5x2_ck,
 	.recalc		= &followparent_recalc,
 };
 
@@ -1749,6 +1839,7 @@ static struct clk l3_instr_ick = {
 	.enable_reg	= OMAP4430_CM_L3INSTR_L3_INSTR_CLKCTRL,
 	.enable_bit	= OMAP4430_MODULEMODE_HWCTRL,
 	.clkdm_name	= "l3_instr_clkdm",
+	.flags		= ENABLE_ON_INIT,
 	.parent		= &l3_div_ck,
 	.recalc		= &followparent_recalc,
 };
@@ -1759,6 +1850,7 @@ static struct clk l3_main_3_ick = {
 	.enable_reg	= OMAP4430_CM_L3INSTR_L3_3_CLKCTRL,
 	.enable_bit	= OMAP4430_MODULEMODE_HWCTRL,
 	.clkdm_name	= "l3_instr_clkdm",
+	.flags		= ENABLE_ON_INIT,
 	.parent		= &l3_div_ck,
 	.recalc		= &followparent_recalc,
 };
@@ -2063,6 +2155,7 @@ static struct clk ocp_wp_noc_ick = {
 	.enable_reg	= OMAP4430_CM_L3INSTR_OCP_WP1_CLKCTRL,
 	.enable_bit	= OMAP4430_MODULEMODE_HWCTRL,
 	.clkdm_name	= "l3_instr_clkdm",
+	.flags		= ENABLE_ON_INIT,
 	.parent		= &l3_div_ck,
 	.recalc		= &followparent_recalc,
 };
@@ -2093,7 +2186,7 @@ static struct clk sl2if_ick = {
 	.enable_reg	= OMAP4430_CM_IVAHD_SL2_CLKCTRL,
 	.enable_bit	= OMAP4430_MODULEMODE_HWCTRL,
 	.clkdm_name	= "ivahd_clkdm",
-	.parent		= &dpll_iva_m5_ck,
+	.parent		= &dpll_iva_m5x2_ck,
 	.recalc		= &followparent_recalc,
 };
 
@@ -2438,36 +2531,6 @@ static struct clk usb_host_fs_fck = {
 	.recalc		= &followparent_recalc,
 };
 
-static struct clk usb_host_hs_utmi_p3_clk = {
-	.name		= "usb_host_hs_utmi_p3_clk",
-	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
-	.enable_bit	= OMAP4430_OPTFCLKEN_UTMI_P3_CLK_SHIFT,
-	.clkdm_name	= "l3_init_clkdm",
-	.parent		= &init_60m_fclk,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk usb_host_hs_hsic60m_p1_clk = {
-	.name		= "usb_host_hs_hsic60m_p1_clk",
-	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
-	.enable_bit	= OMAP4430_OPTFCLKEN_HSIC60M_P1_CLK_SHIFT,
-	.clkdm_name	= "l3_init_clkdm",
-	.parent		= &init_60m_fclk,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk usb_host_hs_hsic60m_p2_clk = {
-	.name		= "usb_host_hs_hsic60m_p2_clk",
-	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
-	.enable_bit	= OMAP4430_OPTFCLKEN_HSIC60M_P2_CLK_SHIFT,
-	.clkdm_name	= "l3_init_clkdm",
-	.parent		= &init_60m_fclk,
-	.recalc		= &followparent_recalc,
-};
-
 static const struct clksel utmi_p1_gfclk_sel[] = {
 	{ .parent = &init_60m_fclk, .rates = div_1_0_rates },
 	{ .parent = &xclk60mhsp1_ck, .rates = div_1_1_rates },
@@ -2522,6 +2585,16 @@ static struct clk usb_host_hs_utmi_p2_cl
 	.recalc		= &followparent_recalc,
 };
 
+static struct clk usb_host_hs_utmi_p3_clk = {
+	.name		= "usb_host_hs_utmi_p3_clk",
+	.ops		= &clkops_omap2_dflt,
+	.enable_reg	= OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
+	.enable_bit	= OMAP4430_OPTFCLKEN_UTMI_P3_CLK_SHIFT,
+	.clkdm_name	= "l3_init_clkdm",
+	.parent		= &init_60m_fclk,
+	.recalc		= &followparent_recalc,
+};
+
 static struct clk usb_host_hs_hsic480m_p1_clk = {
 	.name		= "usb_host_hs_hsic480m_p1_clk",
 	.ops		= &clkops_omap2_dflt,
@@ -2532,6 +2605,26 @@ static struct clk usb_host_hs_hsic480m_p
 	.recalc		= &followparent_recalc,
 };
 
+static struct clk usb_host_hs_hsic60m_p1_clk = {
+	.name		= "usb_host_hs_hsic60m_p1_clk",
+	.ops		= &clkops_omap2_dflt,
+	.enable_reg	= OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
+	.enable_bit	= OMAP4430_OPTFCLKEN_HSIC60M_P1_CLK_SHIFT,
+	.clkdm_name	= "l3_init_clkdm",
+	.parent		= &init_60m_fclk,
+	.recalc		= &followparent_recalc,
+};
+
+static struct clk usb_host_hs_hsic60m_p2_clk = {
+	.name		= "usb_host_hs_hsic60m_p2_clk",
+	.ops		= &clkops_omap2_dflt,
+	.enable_reg	= OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
+	.enable_bit	= OMAP4430_OPTFCLKEN_HSIC60M_P2_CLK_SHIFT,
+	.clkdm_name	= "l3_init_clkdm",
+	.parent		= &init_60m_fclk,
+	.recalc		= &followparent_recalc,
+};
+
 static struct clk usb_host_hs_hsic480m_p2_clk = {
 	.name		= "usb_host_hs_hsic480m_p2_clk",
 	.ops		= &clkops_omap2_dflt,
@@ -2656,13 +2749,13 @@ static const struct clksel_rate div2_14t
 };
 
 static const struct clksel usim_fclk_div[] = {
-	{ .parent = &dpll_per_m4_ck, .rates = div2_14to18_rates },
+	{ .parent = &dpll_per_m4x2_ck, .rates = div2_14to18_rates },
 	{ .parent = NULL },
 };
 
 static struct clk usim_ck = {
 	.name		= "usim_ck",
-	.parent		= &dpll_per_m4_ck,
+	.parent		= &dpll_per_m4x2_ck,
 	.clksel		= usim_fclk_div,
 	.clksel_reg	= OMAP4430_CM_WKUP_USIM_CLKCTRL,
 	.clksel_mask	= OMAP4430_CLKSEL_DIV_MASK,
@@ -2747,6 +2840,168 @@ static struct clk trace_clk_div_ck = {
 	.set_rate	= &omap2_clksel_set_rate,
 };
 
+/* SCRM aux clk nodes */
+
+static const struct clksel auxclk_sel[] = {
+	{ .parent = &sys_clkin_ck, .rates = div_1_0_rates },
+	{ .parent = &dpll_core_m3x2_ck, .rates = div_1_1_rates },
+	{ .parent = &dpll_per_m3x2_ck, .rates = div_1_2_rates },
+	{ .parent = NULL },
+};
+
+static struct clk auxclk0_ck = {
+	.name		= "auxclk0_ck",
+	.parent		= &sys_clkin_ck,
+	.init		= &omap2_init_clksel_parent,
+	.ops		= &clkops_omap2_dflt,
+	.clksel		= auxclk_sel,
+	.clksel_reg	= OMAP4_SCRM_AUXCLK0,
+	.clksel_mask	= OMAP4_SRCSELECT_MASK,
+	.recalc		= &omap2_clksel_recalc,
+	.enable_reg	= OMAP4_SCRM_AUXCLK0,
+	.enable_bit	= OMAP4_ENABLE_SHIFT,
+};
+
+static struct clk auxclk1_ck = {
+	.name		= "auxclk1_ck",
+	.parent		= &sys_clkin_ck,
+	.init		= &omap2_init_clksel_parent,
+	.ops		= &clkops_omap2_dflt,
+	.clksel		= auxclk_sel,
+	.clksel_reg	= OMAP4_SCRM_AUXCLK1,
+	.clksel_mask	= OMAP4_SRCSELECT_MASK,
+	.recalc		= &omap2_clksel_recalc,
+	.enable_reg	= OMAP4_SCRM_AUXCLK1,
+	.enable_bit	= OMAP4_ENABLE_SHIFT,
+};
+
+static struct clk auxclk2_ck = {
+	.name		= "auxclk2_ck",
+	.parent		= &sys_clkin_ck,
+	.init		= &omap2_init_clksel_parent,
+	.ops		= &clkops_omap2_dflt,
+	.clksel		= auxclk_sel,
+	.clksel_reg	= OMAP4_SCRM_AUXCLK2,
+	.clksel_mask	= OMAP4_SRCSELECT_MASK,
+	.recalc		= &omap2_clksel_recalc,
+	.enable_reg	= OMAP4_SCRM_AUXCLK2,
+	.enable_bit	= OMAP4_ENABLE_SHIFT,
+};
+static struct clk auxclk3_ck = {
+	.name		= "auxclk3_ck",
+	.parent		= &sys_clkin_ck,
+	.init		= &omap2_init_clksel_parent,
+	.ops		= &clkops_omap2_dflt,
+	.clksel		= auxclk_sel,
+	.clksel_reg	= OMAP4_SCRM_AUXCLK3,
+	.clksel_mask	= OMAP4_SRCSELECT_MASK,
+	.recalc		= &omap2_clksel_recalc,
+	.enable_reg	= OMAP4_SCRM_AUXCLK3,
+	.enable_bit	= OMAP4_ENABLE_SHIFT,
+};
+
+static struct clk auxclk4_ck = {
+	.name		= "auxclk4_ck",
+	.parent		= &sys_clkin_ck,
+	.init		= &omap2_init_clksel_parent,
+	.ops		= &clkops_omap2_dflt,
+	.clksel		= auxclk_sel,
+	.clksel_reg	= OMAP4_SCRM_AUXCLK4,
+	.clksel_mask	= OMAP4_SRCSELECT_MASK,
+	.recalc		= &omap2_clksel_recalc,
+	.enable_reg	= OMAP4_SCRM_AUXCLK4,
+	.enable_bit	= OMAP4_ENABLE_SHIFT,
+};
+
+static struct clk auxclk5_ck = {
+	.name		= "auxclk5_ck",
+	.parent		= &sys_clkin_ck,
+	.init		= &omap2_init_clksel_parent,
+	.ops		= &clkops_omap2_dflt,
+	.clksel		= auxclk_sel,
+	.clksel_reg	= OMAP4_SCRM_AUXCLK5,
+	.clksel_mask	= OMAP4_SRCSELECT_MASK,
+	.recalc		= &omap2_clksel_recalc,
+	.enable_reg	= OMAP4_SCRM_AUXCLK5,
+	.enable_bit	= OMAP4_ENABLE_SHIFT,
+};
+
+static const struct clksel auxclkreq_sel[] = {
+	{ .parent = &auxclk0_ck, .rates = div_1_0_rates },
+	{ .parent = &auxclk1_ck, .rates = div_1_1_rates },
+	{ .parent = &auxclk2_ck, .rates = div_1_2_rates },
+	{ .parent = &auxclk3_ck, .rates = div_1_3_rates },
+	{ .parent = &auxclk4_ck, .rates = div_1_4_rates },
+	{ .parent = &auxclk5_ck, .rates = div_1_5_rates },
+	{ .parent = NULL },
+};
+
+static struct clk auxclkreq0_ck = {
+	.name		= "auxclkreq0_ck",
+	.parent		= &auxclk0_ck,
+	.init		= &omap2_init_clksel_parent,
+	.ops		= &clkops_null,
+	.clksel         = auxclkreq_sel,
+	.clksel_reg	= OMAP4_SCRM_AUXCLKREQ0,
+	.clksel_mask	= OMAP4_MAPPING_MASK,
+	.recalc		= &omap2_clksel_recalc,
+};
+
+static struct clk auxclkreq1_ck = {
+	.name		= "auxclkreq1_ck",
+	.parent		= &auxclk1_ck,
+	.init		= &omap2_init_clksel_parent,
+	.ops		= &clkops_null,
+	.clksel         = auxclkreq_sel,
+	.clksel_reg	= OMAP4_SCRM_AUXCLKREQ1,
+	.clksel_mask	= OMAP4_MAPPING_MASK,
+	.recalc		= &omap2_clksel_recalc,
+};
+
+static struct clk auxclkreq2_ck = {
+	.name		= "auxclkreq2_ck",
+	.parent		= &auxclk2_ck,
+	.init		= &omap2_init_clksel_parent,
+	.ops		= &clkops_null,
+	.clksel         = auxclkreq_sel,
+	.clksel_reg	= OMAP4_SCRM_AUXCLKREQ2,
+	.clksel_mask	= OMAP4_MAPPING_MASK,
+	.recalc		= &omap2_clksel_recalc,
+};
+
+static struct clk auxclkreq3_ck = {
+	.name		= "auxclkreq3_ck",
+	.parent		= &auxclk3_ck,
+	.init		= &omap2_init_clksel_parent,
+	.ops		= &clkops_null,
+	.clksel         = auxclkreq_sel,
+	.clksel_reg	= OMAP4_SCRM_AUXCLKREQ3,
+	.clksel_mask	= OMAP4_MAPPING_MASK,
+	.recalc		= &omap2_clksel_recalc,
+};
+
+static struct clk auxclkreq4_ck = {
+	.name		= "auxclkreq4_ck",
+	.parent		= &auxclk4_ck,
+	.init		= &omap2_init_clksel_parent,
+	.ops		= &clkops_null,
+	.clksel         = auxclkreq_sel,
+	.clksel_reg	= OMAP4_SCRM_AUXCLKREQ4,
+	.clksel_mask	= OMAP4_MAPPING_MASK,
+	.recalc		= &omap2_clksel_recalc,
+};
+
+static struct clk auxclkreq5_ck = {
+	.name		= "auxclkreq5_ck",
+	.parent		= &auxclk5_ck,
+	.init		= &omap2_init_clksel_parent,
+	.ops		= &clkops_null,
+	.clksel         = auxclkreq_sel,
+	.clksel_reg	= OMAP4_SCRM_AUXCLKREQ5,
+	.clksel_mask	= OMAP4_MAPPING_MASK,
+	.recalc		= &omap2_clksel_recalc,
+};
+
 /*
  * clkdev
  */
@@ -2774,43 +3029,48 @@ static struct omap_clk omap44xx_clks[] =
 	CLK(NULL,	"abe_dpll_bypass_clk_mux_ck",	&abe_dpll_bypass_clk_mux_ck,	CK_443X),
 	CLK(NULL,	"abe_dpll_refclk_mux_ck",	&abe_dpll_refclk_mux_ck,	CK_443X),
 	CLK(NULL,	"dpll_abe_ck",			&dpll_abe_ck,	CK_443X),
+	CLK(NULL,	"dpll_abe_x2_ck",		&dpll_abe_x2_ck,	CK_443X),
 	CLK(NULL,	"dpll_abe_m2x2_ck",		&dpll_abe_m2x2_ck,	CK_443X),
 	CLK(NULL,	"abe_24m_fclk",			&abe_24m_fclk,	CK_443X),
 	CLK(NULL,	"abe_clk",			&abe_clk,	CK_443X),
 	CLK(NULL,	"aess_fclk",			&aess_fclk,	CK_443X),
-	CLK(NULL,	"dpll_abe_m3_ck",		&dpll_abe_m3_ck,	CK_443X),
+	CLK(NULL,	"dpll_abe_m3x2_ck",		&dpll_abe_m3x2_ck,	CK_443X),
 	CLK(NULL,	"core_hsd_byp_clk_mux_ck",	&core_hsd_byp_clk_mux_ck,	CK_443X),
 	CLK(NULL,	"dpll_core_ck",			&dpll_core_ck,	CK_443X),
-	CLK(NULL,	"dpll_core_m6_ck",		&dpll_core_m6_ck,	CK_443X),
+	CLK(NULL,	"dpll_core_x2_ck",		&dpll_core_x2_ck,	CK_443X),
+	CLK(NULL,	"dpll_core_m6x2_ck",		&dpll_core_m6x2_ck,	CK_443X),
 	CLK(NULL,	"dbgclk_mux_ck",		&dbgclk_mux_ck,	CK_443X),
 	CLK(NULL,	"dpll_core_m2_ck",		&dpll_core_m2_ck,	CK_443X),
 	CLK(NULL,	"ddrphy_ck",			&ddrphy_ck,	CK_443X),
-	CLK(NULL,	"dpll_core_m5_ck",		&dpll_core_m5_ck,	CK_443X),
+	CLK(NULL,	"dpll_core_m5x2_ck",		&dpll_core_m5x2_ck,	CK_443X),
 	CLK(NULL,	"div_core_ck",			&div_core_ck,	CK_443X),
 	CLK(NULL,	"div_iva_hs_clk",		&div_iva_hs_clk,	CK_443X),
 	CLK(NULL,	"div_mpu_hs_clk",		&div_mpu_hs_clk,	CK_443X),
-	CLK(NULL,	"dpll_core_m4_ck",		&dpll_core_m4_ck,	CK_443X),
+	CLK(NULL,	"dpll_core_m4x2_ck",		&dpll_core_m4x2_ck,	CK_443X),
 	CLK(NULL,	"dll_clk_div_ck",		&dll_clk_div_ck,	CK_443X),
 	CLK(NULL,	"dpll_abe_m2_ck",		&dpll_abe_m2_ck,	CK_443X),
-	CLK(NULL,	"dpll_core_m3_ck",		&dpll_core_m3_ck,	CK_443X),
-	CLK(NULL,	"dpll_core_m7_ck",		&dpll_core_m7_ck,	CK_443X),
+	CLK(NULL,	"dpll_core_m3x2_ck",		&dpll_core_m3x2_ck,	CK_443X),
+	CLK(NULL,	"dpll_core_m7x2_ck",		&dpll_core_m7x2_ck,	CK_443X),
 	CLK(NULL,	"iva_hsd_byp_clk_mux_ck",	&iva_hsd_byp_clk_mux_ck,	CK_443X),
 	CLK(NULL,	"dpll_iva_ck",			&dpll_iva_ck,	CK_443X),
-	CLK(NULL,	"dpll_iva_m4_ck",		&dpll_iva_m4_ck,	CK_443X),
-	CLK(NULL,	"dpll_iva_m5_ck",		&dpll_iva_m5_ck,	CK_443X),
+	CLK(NULL,	"dpll_iva_x2_ck",		&dpll_iva_x2_ck,	CK_443X),
+	CLK(NULL,	"dpll_iva_m4x2_ck",		&dpll_iva_m4x2_ck,	CK_443X),
+	CLK(NULL,	"dpll_iva_m5x2_ck",		&dpll_iva_m5x2_ck,	CK_443X),
 	CLK(NULL,	"dpll_mpu_ck",			&dpll_mpu_ck,	CK_443X),
 	CLK(NULL,	"dpll_mpu_m2_ck",		&dpll_mpu_m2_ck,	CK_443X),
 	CLK(NULL,	"per_hs_clk_div_ck",		&per_hs_clk_div_ck,	CK_443X),
 	CLK(NULL,	"per_hsd_byp_clk_mux_ck",	&per_hsd_byp_clk_mux_ck,	CK_443X),
 	CLK(NULL,	"dpll_per_ck",			&dpll_per_ck,	CK_443X),
 	CLK(NULL,	"dpll_per_m2_ck",		&dpll_per_m2_ck,	CK_443X),
+	CLK(NULL,	"dpll_per_x2_ck",		&dpll_per_x2_ck,	CK_443X),
 	CLK(NULL,	"dpll_per_m2x2_ck",		&dpll_per_m2x2_ck,	CK_443X),
-	CLK(NULL,	"dpll_per_m3_ck",		&dpll_per_m3_ck,	CK_443X),
-	CLK(NULL,	"dpll_per_m4_ck",		&dpll_per_m4_ck,	CK_443X),
-	CLK(NULL,	"dpll_per_m5_ck",		&dpll_per_m5_ck,	CK_443X),
-	CLK(NULL,	"dpll_per_m6_ck",		&dpll_per_m6_ck,	CK_443X),
-	CLK(NULL,	"dpll_per_m7_ck",		&dpll_per_m7_ck,	CK_443X),
+	CLK(NULL,	"dpll_per_m3x2_ck",		&dpll_per_m3x2_ck,	CK_443X),
+	CLK(NULL,	"dpll_per_m4x2_ck",		&dpll_per_m4x2_ck,	CK_443X),
+	CLK(NULL,	"dpll_per_m5x2_ck",		&dpll_per_m5x2_ck,	CK_443X),
+	CLK(NULL,	"dpll_per_m6x2_ck",		&dpll_per_m6x2_ck,	CK_443X),
+	CLK(NULL,	"dpll_per_m7x2_ck",		&dpll_per_m7x2_ck,	CK_443X),
 	CLK(NULL,	"dpll_unipro_ck",		&dpll_unipro_ck,	CK_443X),
+	CLK(NULL,	"dpll_unipro_x2_ck",		&dpll_unipro_x2_ck,	CK_443X),
 	CLK(NULL,	"dpll_unipro_m2x2_ck",		&dpll_unipro_m2x2_ck,	CK_443X),
 	CLK(NULL,	"usb_hs_clk_div_ck",		&usb_hs_clk_div_ck,	CK_443X),
 	CLK(NULL,	"dpll_usb_ck",			&dpll_usb_ck,	CK_443X),
@@ -2856,26 +3116,26 @@ static struct omap_clk omap44xx_clks[] =
 	CLK(NULL,	"emif2_fck",			&emif2_fck,	CK_443X),
 	CLK(NULL,	"fdif_fck",			&fdif_fck,	CK_443X),
 	CLK(NULL,	"fpka_fck",			&fpka_fck,	CK_443X),
-	CLK(NULL,	"gpio1_dbck",			&gpio1_dbclk,	CK_443X),
+	CLK(NULL,	"gpio1_dbclk",			&gpio1_dbclk,	CK_443X),
 	CLK(NULL,	"gpio1_ick",			&gpio1_ick,	CK_443X),
-	CLK(NULL,	"gpio2_dbck",			&gpio2_dbclk,	CK_443X),
+	CLK(NULL,	"gpio2_dbclk",			&gpio2_dbclk,	CK_443X),
 	CLK(NULL,	"gpio2_ick",			&gpio2_ick,	CK_443X),
-	CLK(NULL,	"gpio3_dbck",			&gpio3_dbclk,	CK_443X),
+	CLK(NULL,	"gpio3_dbclk",			&gpio3_dbclk,	CK_443X),
 	CLK(NULL,	"gpio3_ick",			&gpio3_ick,	CK_443X),
-	CLK(NULL,	"gpio4_dbck",			&gpio4_dbclk,	CK_443X),
+	CLK(NULL,	"gpio4_dbclk",			&gpio4_dbclk,	CK_443X),
 	CLK(NULL,	"gpio4_ick",			&gpio4_ick,	CK_443X),
-	CLK(NULL,	"gpio5_dbck",			&gpio5_dbclk,	CK_443X),
+	CLK(NULL,	"gpio5_dbclk",			&gpio5_dbclk,	CK_443X),
 	CLK(NULL,	"gpio5_ick",			&gpio5_ick,	CK_443X),
-	CLK(NULL,	"gpio6_dbck",			&gpio6_dbclk,	CK_443X),
+	CLK(NULL,	"gpio6_dbclk",			&gpio6_dbclk,	CK_443X),
 	CLK(NULL,	"gpio6_ick",			&gpio6_ick,	CK_443X),
 	CLK(NULL,	"gpmc_ick",			&gpmc_ick,	CK_443X),
 	CLK(NULL,	"gpu_fck",			&gpu_fck,	CK_443X),
 	CLK("omap2_hdq.0",	"fck",				&hdq1w_fck,	CK_443X),
 	CLK(NULL,	"hsi_fck",			&hsi_fck,	CK_443X),
-	CLK("i2c_omap.1",	"fck",				&i2c1_fck,	CK_443X),
-	CLK("i2c_omap.2",	"fck",				&i2c2_fck,	CK_443X),
-	CLK("i2c_omap.3",	"fck",				&i2c3_fck,	CK_443X),
-	CLK("i2c_omap.4",	"fck",				&i2c4_fck,	CK_443X),
+	CLK("omap_i2c.1",	"fck",				&i2c1_fck,	CK_443X),
+	CLK("omap_i2c.2",	"fck",				&i2c2_fck,	CK_443X),
+	CLK("omap_i2c.3",	"fck",				&i2c3_fck,	CK_443X),
+	CLK("omap_i2c.4",	"fck",				&i2c4_fck,	CK_443X),
 	CLK(NULL,	"ipu_fck",			&ipu_fck,	CK_443X),
 	CLK(NULL,	"iss_ctrlclk",			&iss_ctrlclk,	CK_443X),
 	CLK(NULL,	"iss_fck",			&iss_fck,	CK_443X),
@@ -2937,29 +3197,35 @@ static struct omap_clk omap44xx_clks[] =
 	CLK(NULL,	"uart3_fck",			&uart3_fck,	CK_443X),
 	CLK(NULL,	"uart4_fck",			&uart4_fck,	CK_443X),
 	CLK(NULL,	"usb_host_fs_fck",		&usb_host_fs_fck,	CK_443X),
-	CLK(NULL,	"usb_host_hs_utmi_p3_clk",	&usb_host_hs_utmi_p3_clk,	CK_443X),
-	CLK(NULL,	"usb_host_hs_hsic60m_p1_clk",	&usb_host_hs_hsic60m_p1_clk,	CK_443X),
-	CLK(NULL,	"usb_host_hs_hsic60m_p2_clk",	&usb_host_hs_hsic60m_p2_clk,	CK_443X),
+	CLK("ehci-omap.0",	"fs_fck",		&usb_host_fs_fck,	CK_443X),
 	CLK(NULL,	"utmi_p1_gfclk",		&utmi_p1_gfclk,	CK_443X),
 	CLK(NULL,	"usb_host_hs_utmi_p1_clk",	&usb_host_hs_utmi_p1_clk,	CK_443X),
 	CLK(NULL,	"utmi_p2_gfclk",		&utmi_p2_gfclk,	CK_443X),
 	CLK(NULL,	"usb_host_hs_utmi_p2_clk",	&usb_host_hs_utmi_p2_clk,	CK_443X),
+	CLK(NULL,	"usb_host_hs_utmi_p3_clk",	&usb_host_hs_utmi_p3_clk,	CK_443X),
 	CLK(NULL,	"usb_host_hs_hsic480m_p1_clk",	&usb_host_hs_hsic480m_p1_clk,	CK_443X),
+	CLK(NULL,	"usb_host_hs_hsic60m_p1_clk",	&usb_host_hs_hsic60m_p1_clk,	CK_443X),
+	CLK(NULL,	"usb_host_hs_hsic60m_p2_clk",	&usb_host_hs_hsic60m_p2_clk,	CK_443X),
 	CLK(NULL,	"usb_host_hs_hsic480m_p2_clk",	&usb_host_hs_hsic480m_p2_clk,	CK_443X),
 	CLK(NULL,	"usb_host_hs_func48mclk",	&usb_host_hs_func48mclk,	CK_443X),
 	CLK(NULL,	"usb_host_hs_fck",		&usb_host_hs_fck,	CK_443X),
+	CLK("ehci-omap.0",	"hs_fck",		&usb_host_hs_fck,	CK_443X),
+	CLK("ehci-omap.0",	"usbhost_ick",		&dummy_ck,		CK_443X),
 	CLK(NULL,	"otg_60m_gfclk",		&otg_60m_gfclk,	CK_443X),
 	CLK(NULL,	"usb_otg_hs_xclk",		&usb_otg_hs_xclk,	CK_443X),
-	CLK("musb_hdrc",	"ick",				&usb_otg_hs_ick,	CK_443X),
+	CLK("musb-omap2430",	"ick",				&usb_otg_hs_ick,	CK_443X),
 	CLK(NULL,	"usb_phy_cm_clk32k",		&usb_phy_cm_clk32k,	CK_443X),
 	CLK(NULL,	"usb_tll_hs_usb_ch2_clk",	&usb_tll_hs_usb_ch2_clk,	CK_443X),
 	CLK(NULL,	"usb_tll_hs_usb_ch0_clk",	&usb_tll_hs_usb_ch0_clk,	CK_443X),
 	CLK(NULL,	"usb_tll_hs_usb_ch1_clk",	&usb_tll_hs_usb_ch1_clk,	CK_443X),
 	CLK(NULL,	"usb_tll_hs_ick",		&usb_tll_hs_ick,	CK_443X),
+	CLK("ehci-omap.0",	"usbtll_ick",		&usb_tll_hs_ick,	CK_443X),
+	CLK("ehci-omap.0",	"usbtll_fck",		&dummy_ck,	CK_443X),
 	CLK(NULL,	"usim_ck",			&usim_ck,	CK_443X),
 	CLK(NULL,	"usim_fclk",			&usim_fclk,	CK_443X),
 	CLK(NULL,	"usim_fck",			&usim_fck,	CK_443X),
 	CLK("omap_wdt",	"fck",				&wd_timer2_fck,	CK_443X),
+	CLK(NULL,	"mailboxes_ick",		&dummy_ck,	CK_443X),
 	CLK(NULL,	"wd_timer3_fck",		&wd_timer3_fck,	CK_443X),
 	CLK(NULL,	"stm_clk_div_ck",		&stm_clk_div_ck,	CK_443X),
 	CLK(NULL,	"trace_clk_div_ck",		&trace_clk_div_ck,	CK_443X),
@@ -2975,10 +3241,10 @@ static struct omap_clk omap44xx_clks[] =
 	CLK(NULL,	"gpt9_ick",			&dummy_ck,	CK_443X),
 	CLK(NULL,	"gpt10_ick",			&dummy_ck,	CK_443X),
 	CLK(NULL,	"gpt11_ick",			&dummy_ck,	CK_443X),
-	CLK("i2c_omap.1",	"ick",				&dummy_ck,	CK_443X),
-	CLK("i2c_omap.2",	"ick",				&dummy_ck,	CK_443X),
-	CLK("i2c_omap.3",	"ick",				&dummy_ck,	CK_443X),
-	CLK("i2c_omap.4",	"ick",				&dummy_ck,	CK_443X),
+	CLK("omap_i2c.1",	"ick",				&dummy_ck,	CK_443X),
+	CLK("omap_i2c.2",	"ick",				&dummy_ck,	CK_443X),
+	CLK("omap_i2c.3",	"ick",				&dummy_ck,	CK_443X),
+	CLK("omap_i2c.4",	"ick",				&dummy_ck,	CK_443X),
 	CLK("mmci-omap-hs.0",	"ick",				&dummy_ck,	CK_443X),
 	CLK("mmci-omap-hs.1",	"ick",				&dummy_ck,	CK_443X),
 	CLK("mmci-omap-hs.2",	"ick",				&dummy_ck,	CK_443X),
@@ -2997,6 +3263,18 @@ static struct omap_clk omap44xx_clks[] =
 	CLK(NULL,	"uart3_ick",			&dummy_ck,	CK_443X),
 	CLK(NULL,	"uart4_ick",			&dummy_ck,	CK_443X),
 	CLK("omap_wdt",	"ick",				&dummy_ck,	CK_443X),
+	CLK(NULL,	"auxclk0_ck",			&auxclk0_ck,	CK_443X),
+	CLK(NULL,	"auxclk1_ck",			&auxclk1_ck,	CK_443X),
+	CLK(NULL,	"auxclk2_ck",			&auxclk2_ck,	CK_443X),
+	CLK(NULL,	"auxclk3_ck",			&auxclk3_ck,	CK_443X),
+	CLK(NULL,	"auxclk4_ck",			&auxclk4_ck,	CK_443X),
+	CLK(NULL,	"auxclk5_ck",			&auxclk5_ck,	CK_443X),
+	CLK(NULL,	"auxclkreq0_ck",		&auxclkreq0_ck,	CK_443X),
+	CLK(NULL,	"auxclkreq1_ck",		&auxclkreq1_ck,	CK_443X),
+	CLK(NULL,	"auxclkreq2_ck",		&auxclkreq2_ck,	CK_443X),
+	CLK(NULL,	"auxclkreq3_ck",		&auxclkreq3_ck,	CK_443X),
+	CLK(NULL,	"auxclkreq4_ck",		&auxclkreq4_ck,	CK_443X),
+	CLK(NULL,	"auxclkreq5_ck",		&auxclkreq5_ck,	CK_443X),
 };
 
 int __init omap4xxx_clk_init(void)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/clock.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/clock.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/clock.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/clock.c	2011-03-14 21:20:32.000000000 -0400
@@ -24,14 +24,12 @@
 #include <linux/bitops.h>
 
 #include <plat/clock.h>
-#include <plat/clockdomain.h>
+#include "clockdomain.h"
 #include <plat/cpu.h>
 #include <plat/prcm.h>
 
 #include "clock.h"
-#include "prm.h"
-#include "prm-regbits-24xx.h"
-#include "cm.h"
+#include "cm2xxx_3xxx.h"
 #include "cm-regbits-24xx.h"
 #include "cm-regbits-34xx.h"
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/clockdomain.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/clockdomain.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/clockdomain.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/clockdomain.c	2011-03-14 21:20:32.000000000 -0400
@@ -13,7 +13,6 @@
  */
 #undef DEBUG
 
-#include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/device.h>
 #include <linux/list.h>
@@ -27,13 +26,16 @@
 
 #include <linux/bitops.h>
 
-#include "prm.h"
+#include "prm2xxx_3xxx.h"
 #include "prm-regbits-24xx.h"
-#include "cm.h"
+#include "cm2xxx_3xxx.h"
+#include "cm-regbits-24xx.h"
+#include "cminst44xx.h"
+#include "prcm44xx.h"
 
 #include <plat/clock.h>
-#include <plat/powerdomain.h>
-#include <plat/clockdomain.h>
+#include "powerdomain.h"
+#include "clockdomain.h"
 #include <plat/prcm.h>
 
 /* clkdm_list contains all registered struct clockdomains */
@@ -141,6 +143,9 @@ static struct clkdm_dep *_clkdm_deps_loo
  * clockdomain is in hardware-supervised mode.	Meant to be called
  * once at clockdomain layer initialization, since these should remain
  * fixed for a particular architecture.  No return value.
+ *
+ * XXX autodeps are deprecated and should be removed at the earliest
+ * opportunity
  */
 static void _autodep_lookup(struct clkdm_autodep *autodep)
 {
@@ -168,6 +173,9 @@ static void _autodep_lookup(struct clkdm
  * Add the "autodep" sleep & wakeup dependencies to clockdomain 'clkdm'
  * in hardware-supervised mode.  Meant to be called from clock framework
  * when a clock inside clockdomain 'clkdm' is enabled.	No return value.
+ *
+ * XXX autodeps are deprecated and should be removed at the earliest
+ * opportunity
  */
 static void _clkdm_add_autodeps(struct clockdomain *clkdm)
 {
@@ -199,6 +207,9 @@ static void _clkdm_add_autodeps(struct c
  * Remove the "autodep" sleep & wakeup dependencies from clockdomain 'clkdm'
  * in hardware-supervised mode.  Meant to be called from clock framework
  * when a clock inside clockdomain 'clkdm' is disabled.  No return value.
+ *
+ * XXX autodeps are deprecated and should be removed at the earliest
+ * opportunity
  */
 static void _clkdm_del_autodeps(struct clockdomain *clkdm)
 {
@@ -223,39 +234,56 @@ static void _clkdm_del_autodeps(struct c
 	}
 }
 
-/*
- * _omap2_clkdm_set_hwsup - set the hwsup idle transition bit
+/**
+ * _enable_hwsup - place a clockdomain into hardware-supervised idle
  * @clkdm: struct clockdomain *
- * @enable: int 0 to disable, 1 to enable
  *
- * Internal helper for actually switching the bit that controls hwsup
- * idle transitions for clkdm.
+ * Place the clockdomain into hardware-supervised idle mode.  No return
+ * value.
+ *
+ * XXX Should this return an error if the clockdomain does not support
+ * hardware-supervised idle mode?
  */
-static void _omap2_clkdm_set_hwsup(struct clockdomain *clkdm, int enable)
+static void _enable_hwsup(struct clockdomain *clkdm)
 {
-	u32 bits, v;
-
-	if (cpu_is_omap24xx()) {
-		if (enable)
-			bits = OMAP24XX_CLKSTCTRL_ENABLE_AUTO;
-		else
-			bits = OMAP24XX_CLKSTCTRL_DISABLE_AUTO;
-	} else if (cpu_is_omap34xx() || cpu_is_omap44xx()) {
-		if (enable)
-			bits = OMAP34XX_CLKSTCTRL_ENABLE_AUTO;
-		else
-			bits = OMAP34XX_CLKSTCTRL_DISABLE_AUTO;
-	} else {
+	if (cpu_is_omap24xx())
+		omap2xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
+					       clkdm->clktrctrl_mask);
+	else if (cpu_is_omap34xx())
+		omap3xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
+					       clkdm->clktrctrl_mask);
+	else if (cpu_is_omap44xx())
+		return omap4_cminst_clkdm_enable_hwsup(clkdm->prcm_partition,
+						       clkdm->cm_inst,
+						       clkdm->clkdm_offs);
+	else
 		BUG();
-	}
-
-	bits = bits << __ffs(clkdm->clktrctrl_mask);
-
-	v = __raw_readl(clkdm->clkstctrl_reg);
-	v &= ~(clkdm->clktrctrl_mask);
-	v |= bits;
-	__raw_writel(v, clkdm->clkstctrl_reg);
+}
 
+/**
+ * _disable_hwsup - place a clockdomain into software-supervised idle
+ * @clkdm: struct clockdomain *
+ *
+ * Place the clockdomain @clkdm into software-supervised idle mode.
+ * No return value.
+ *
+ * XXX Should this return an error if the clockdomain does not support
+ * software-supervised idle mode?
+ */
+static void _disable_hwsup(struct clockdomain *clkdm)
+{
+	if (cpu_is_omap24xx())
+		omap2xxx_cm_clkdm_disable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
+						clkdm->clktrctrl_mask);
+	else if (cpu_is_omap34xx())
+		omap3xxx_cm_clkdm_disable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
+						clkdm->clktrctrl_mask);
+	else if (cpu_is_omap44xx())
+		return omap4_cminst_clkdm_disable_hwsup(clkdm->prcm_partition,
+							clkdm->cm_inst,
+							clkdm->clkdm_offs);
+	else
+		BUG();
 }
 
 /* Public functions */
@@ -395,6 +423,12 @@ int clkdm_add_wkdep(struct clockdomain *
 {
 	struct clkdm_dep *cd;
 
+	if (!cpu_is_omap24xx() && !cpu_is_omap34xx()) {
+		pr_err("clockdomain: %s/%s: %s: not yet implemented\n",
+		       clkdm1->name, clkdm2->name, __func__);
+		return -EINVAL;
+	}
+
 	if (!clkdm1 || !clkdm2)
 		return -EINVAL;
 
@@ -409,7 +443,7 @@ int clkdm_add_wkdep(struct clockdomain *
 		pr_debug("clockdomain: hardware will wake up %s when %s wakes "
 			 "up\n", clkdm1->name, clkdm2->name);
 
-		prm_set_mod_reg_bits((1 << clkdm2->dep_bit),
+		omap2_prm_set_mod_reg_bits((1 << clkdm2->dep_bit),
 				     clkdm1->pwrdm.ptr->prcm_offs, PM_WKDEP);
 	}
 
@@ -430,6 +464,12 @@ int clkdm_del_wkdep(struct clockdomain *
 {
 	struct clkdm_dep *cd;
 
+	if (!cpu_is_omap24xx() && !cpu_is_omap34xx()) {
+		pr_err("clockdomain: %s/%s: %s: not yet implemented\n",
+		       clkdm1->name, clkdm2->name, __func__);
+		return -EINVAL;
+	}
+
 	if (!clkdm1 || !clkdm2)
 		return -EINVAL;
 
@@ -444,7 +484,7 @@ int clkdm_del_wkdep(struct clockdomain *
 		pr_debug("clockdomain: hardware will no longer wake up %s "
 			 "after %s wakes up\n", clkdm1->name, clkdm2->name);
 
-		prm_clear_mod_reg_bits((1 << clkdm2->dep_bit),
+		omap2_prm_clear_mod_reg_bits((1 << clkdm2->dep_bit),
 				       clkdm1->pwrdm.ptr->prcm_offs, PM_WKDEP);
 	}
 
@@ -472,6 +512,12 @@ int clkdm_read_wkdep(struct clockdomain
 	if (!clkdm1 || !clkdm2)
 		return -EINVAL;
 
+	if (!cpu_is_omap24xx() && !cpu_is_omap34xx()) {
+		pr_err("clockdomain: %s/%s: %s: not yet implemented\n",
+		       clkdm1->name, clkdm2->name, __func__);
+		return -EINVAL;
+	}
+
 	cd = _clkdm_deps_lookup(clkdm2, clkdm1->wkdep_srcs);
 	if (IS_ERR(cd)) {
 		pr_debug("clockdomain: hardware cannot set/clear wake up of "
@@ -480,7 +526,7 @@ int clkdm_read_wkdep(struct clockdomain
 	}
 
 	/* XXX It's faster to return the atomic wkdep_usecount */
-	return prm_read_mod_bits_shift(clkdm1->pwrdm.ptr->prcm_offs, PM_WKDEP,
+	return omap2_prm_read_mod_bits_shift(clkdm1->pwrdm.ptr->prcm_offs, PM_WKDEP,
 				       (1 << clkdm2->dep_bit));
 }
 
@@ -499,6 +545,12 @@ int clkdm_clear_all_wkdeps(struct clockd
 	struct clkdm_dep *cd;
 	u32 mask = 0;
 
+	if (!cpu_is_omap24xx() && !cpu_is_omap34xx()) {
+		pr_err("clockdomain: %s: %s: not yet implemented\n",
+		       clkdm->name, __func__);
+		return -EINVAL;
+	}
+
 	if (!clkdm)
 		return -EINVAL;
 
@@ -514,7 +566,7 @@ int clkdm_clear_all_wkdeps(struct clockd
 		atomic_set(&cd->wkdep_usecount, 0);
 	}
 
-	prm_clear_mod_reg_bits(mask, clkdm->pwrdm.ptr->prcm_offs, PM_WKDEP);
+	omap2_prm_clear_mod_reg_bits(mask, clkdm->pwrdm.ptr->prcm_offs, PM_WKDEP);
 
 	return 0;
 }
@@ -553,7 +605,7 @@ int clkdm_add_sleepdep(struct clockdomai
 		pr_debug("clockdomain: will prevent %s from sleeping if %s "
 			 "is active\n", clkdm1->name, clkdm2->name);
 
-		cm_set_mod_reg_bits((1 << clkdm2->dep_bit),
+		omap2_cm_set_mod_reg_bits((1 << clkdm2->dep_bit),
 				    clkdm1->pwrdm.ptr->prcm_offs,
 				    OMAP3430_CM_SLEEPDEP);
 	}
@@ -596,7 +648,7 @@ int clkdm_del_sleepdep(struct clockdomai
 			 "sleeping if %s is active\n", clkdm1->name,
 			 clkdm2->name);
 
-		cm_clear_mod_reg_bits((1 << clkdm2->dep_bit),
+		omap2_cm_clear_mod_reg_bits((1 << clkdm2->dep_bit),
 				      clkdm1->pwrdm.ptr->prcm_offs,
 				      OMAP3430_CM_SLEEPDEP);
 	}
@@ -639,7 +691,7 @@ int clkdm_read_sleepdep(struct clockdoma
 	}
 
 	/* XXX It's faster to return the atomic sleepdep_usecount */
-	return prm_read_mod_bits_shift(clkdm1->pwrdm.ptr->prcm_offs,
+	return omap2_prm_read_mod_bits_shift(clkdm1->pwrdm.ptr->prcm_offs,
 				       OMAP3430_CM_SLEEPDEP,
 				       (1 << clkdm2->dep_bit));
 }
@@ -677,35 +729,13 @@ int clkdm_clear_all_sleepdeps(struct clo
 		atomic_set(&cd->sleepdep_usecount, 0);
 	}
 
-	prm_clear_mod_reg_bits(mask, clkdm->pwrdm.ptr->prcm_offs,
+	omap2_prm_clear_mod_reg_bits(mask, clkdm->pwrdm.ptr->prcm_offs,
 			       OMAP3430_CM_SLEEPDEP);
 
 	return 0;
 }
 
 /**
- * omap2_clkdm_clktrctrl_read - read the clkdm's current state transition mode
- * @clkdm: struct clkdm * of a clockdomain
- *
- * Return the clockdomain @clkdm current state transition mode from the
- * corresponding domain CM_CLKSTCTRL register.	Returns -EINVAL if @clkdm
- * is NULL or the current mode upon success.
- */
-static int omap2_clkdm_clktrctrl_read(struct clockdomain *clkdm)
-{
-	u32 v;
-
-	if (!clkdm)
-		return -EINVAL;
-
-	v = __raw_readl(clkdm->clkstctrl_reg);
-	v &= clkdm->clktrctrl_mask;
-	v >>= __ffs(clkdm->clktrctrl_mask);
-
-	return v;
-}
-
-/**
  * omap2_clkdm_sleep - force clockdomain sleep transition
  * @clkdm: struct clockdomain *
  *
@@ -729,18 +759,19 @@ int omap2_clkdm_sleep(struct clockdomain
 
 	if (cpu_is_omap24xx()) {
 
-		cm_set_mod_reg_bits(OMAP24XX_FORCESTATE_MASK,
+		omap2_cm_set_mod_reg_bits(OMAP24XX_FORCESTATE_MASK,
 			    clkdm->pwrdm.ptr->prcm_offs, OMAP2_PM_PWSTCTRL);
 
-	} else if (cpu_is_omap34xx() || cpu_is_omap44xx()) {
+	} else if (cpu_is_omap34xx()) {
 
-		u32 bits = (OMAP34XX_CLKSTCTRL_FORCE_SLEEP <<
-			 __ffs(clkdm->clktrctrl_mask));
+		omap3xxx_cm_clkdm_force_sleep(clkdm->pwrdm.ptr->prcm_offs,
+					      clkdm->clktrctrl_mask);
 
-		u32 v = __raw_readl(clkdm->clkstctrl_reg);
-		v &= ~(clkdm->clktrctrl_mask);
-		v |= bits;
-		__raw_writel(v, clkdm->clkstctrl_reg);
+	} else if (cpu_is_omap44xx()) {
+
+		omap4_cminst_clkdm_force_sleep(clkdm->prcm_partition,
+					       clkdm->cm_inst,
+					       clkdm->clkdm_offs);
 
 	} else {
 		BUG();
@@ -773,18 +804,19 @@ int omap2_clkdm_wakeup(struct clockdomai
 
 	if (cpu_is_omap24xx()) {
 
-		cm_clear_mod_reg_bits(OMAP24XX_FORCESTATE_MASK,
+		omap2_cm_clear_mod_reg_bits(OMAP24XX_FORCESTATE_MASK,
 			      clkdm->pwrdm.ptr->prcm_offs, OMAP2_PM_PWSTCTRL);
 
-	} else if (cpu_is_omap34xx() || cpu_is_omap44xx()) {
+	} else if (cpu_is_omap34xx()) {
 
-		u32 bits = (OMAP34XX_CLKSTCTRL_FORCE_WAKEUP <<
-			 __ffs(clkdm->clktrctrl_mask));
+		omap3xxx_cm_clkdm_force_wakeup(clkdm->pwrdm.ptr->prcm_offs,
+					       clkdm->clktrctrl_mask);
 
-		u32 v = __raw_readl(clkdm->clkstctrl_reg);
-		v &= ~(clkdm->clktrctrl_mask);
-		v |= bits;
-		__raw_writel(v, clkdm->clkstctrl_reg);
+	} else if (cpu_is_omap44xx()) {
+
+		omap4_cminst_clkdm_force_wakeup(clkdm->prcm_partition,
+						clkdm->cm_inst,
+						clkdm->clkdm_offs);
 
 	} else {
 		BUG();
@@ -822,14 +854,13 @@ void omap2_clkdm_allow_idle(struct clock
 	 * dependency code and data for OMAP4.
 	 */
 	if (cpu_is_omap44xx()) {
-		WARN_ONCE(1, "clockdomain: OMAP4 wakeup/sleep dependency "
-			  "support is not yet implemented\n");
+		pr_err("clockdomain: %s: OMAP4 wakeup/sleep dependency support: not yet implemented\n", clkdm->name);
 	} else {
 		if (atomic_read(&clkdm->usecount) > 0)
 			_clkdm_add_autodeps(clkdm);
 	}
 
-	_omap2_clkdm_set_hwsup(clkdm, 1);
+	_enable_hwsup(clkdm);
 
 	pwrdm_clkdm_state_switch(clkdm);
 }
@@ -857,15 +888,14 @@ void omap2_clkdm_deny_idle(struct clockd
 	pr_debug("clockdomain: disabling automatic idle transitions for %s\n",
 		 clkdm->name);
 
-	_omap2_clkdm_set_hwsup(clkdm, 0);
+	_disable_hwsup(clkdm);
 
 	/*
 	 * XXX This should be removed once TI adds wakeup/sleep
 	 * dependency code and data for OMAP4.
 	 */
 	if (cpu_is_omap44xx()) {
-		WARN_ONCE(1, "clockdomain: OMAP4 wakeup/sleep dependency "
-			  "support is not yet implemented\n");
+		pr_err("clockdomain: %s: OMAP4 wakeup/sleep dependency support: not yet implemented\n", clkdm->name);
 	} else {
 		if (atomic_read(&clkdm->usecount) > 0)
 			_clkdm_del_autodeps(clkdm);
@@ -891,7 +921,7 @@ void omap2_clkdm_deny_idle(struct clockd
  */
 int omap2_clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk)
 {
-	int v;
+	bool hwsup = false;
 
 	/*
 	 * XXX Rewrite this code to maintain a list of enabled
@@ -909,17 +939,27 @@ int omap2_clkdm_clk_enable(struct clockd
 	pr_debug("clockdomain: clkdm %s: clk %s now enabled\n", clkdm->name,
 		 clk->name);
 
-	if (!clkdm->clkstctrl_reg)
-		return 0;
+	if (cpu_is_omap24xx() || cpu_is_omap34xx()) {
 
-	v = omap2_clkdm_clktrctrl_read(clkdm);
+		if (!clkdm->clktrctrl_mask)
+			return 0;
 
-	if ((cpu_is_omap34xx() && v == OMAP34XX_CLKSTCTRL_ENABLE_AUTO) ||
-	    (cpu_is_omap24xx() && v == OMAP24XX_CLKSTCTRL_ENABLE_AUTO)) {
+		hwsup = omap2_cm_is_clkdm_in_hwsup(clkdm->pwrdm.ptr->prcm_offs,
+						   clkdm->clktrctrl_mask);
+
+	} else if (cpu_is_omap44xx()) {
+
+		hwsup = omap4_cminst_is_clkdm_in_hwsup(clkdm->prcm_partition,
+						       clkdm->cm_inst,
+						       clkdm->clkdm_offs);
+
+	}
+
+	if (hwsup) {
 		/* Disable HW transitions when we are changing deps */
-		_omap2_clkdm_set_hwsup(clkdm, 0);
+		_disable_hwsup(clkdm);
 		_clkdm_add_autodeps(clkdm);
-		_omap2_clkdm_set_hwsup(clkdm, 1);
+		_enable_hwsup(clkdm);
 	} else {
 		omap2_clkdm_wakeup(clkdm);
 	}
@@ -946,7 +986,7 @@ int omap2_clkdm_clk_enable(struct clockd
  */
 int omap2_clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk)
 {
-	int v;
+	bool hwsup = false;
 
 	/*
 	 * XXX Rewrite this code to maintain a list of enabled
@@ -971,17 +1011,27 @@ int omap2_clkdm_clk_disable(struct clock
 	pr_debug("clockdomain: clkdm %s: clk %s now disabled\n", clkdm->name,
 		 clk->name);
 
-	if (!clkdm->clkstctrl_reg)
-		return 0;
+	if (cpu_is_omap24xx() || cpu_is_omap34xx()) {
 
-	v = omap2_clkdm_clktrctrl_read(clkdm);
+		if (!clkdm->clktrctrl_mask)
+			return 0;
 
-	if ((cpu_is_omap34xx() && v == OMAP34XX_CLKSTCTRL_ENABLE_AUTO) ||
-	    (cpu_is_omap24xx() && v == OMAP24XX_CLKSTCTRL_ENABLE_AUTO)) {
+		hwsup = omap2_cm_is_clkdm_in_hwsup(clkdm->pwrdm.ptr->prcm_offs,
+						   clkdm->clktrctrl_mask);
+
+	} else if (cpu_is_omap44xx()) {
+
+		hwsup = omap4_cminst_is_clkdm_in_hwsup(clkdm->prcm_partition,
+						       clkdm->cm_inst,
+						       clkdm->clkdm_offs);
+
+	}
+
+	if (hwsup) {
 		/* Disable HW transitions when we are changing deps */
-		_omap2_clkdm_set_hwsup(clkdm, 0);
+		_disable_hwsup(clkdm);
 		_clkdm_del_autodeps(clkdm);
-		_omap2_clkdm_set_hwsup(clkdm, 1);
+		_enable_hwsup(clkdm);
 	} else {
 		omap2_clkdm_sleep(clkdm);
 	}
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/clockdomain.h linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/clockdomain.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/clockdomain.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/clockdomain.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,147 @@
+/*
+ * arch/arm/plat-omap/include/mach/clockdomain.h
+ *
+ * OMAP2/3 clockdomain framework functions
+ *
+ * Copyright (C) 2008 Texas Instruments, Inc.
+ * Copyright (C) 2008-2010 Nokia Corporation
+ *
+ * Paul Walmsley
+ *
+ * This program is free software; you can 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_MACH_OMAP2_CLOCKDOMAIN_H
+#define __ARCH_ARM_MACH_OMAP2_CLOCKDOMAIN_H
+
+#include <linux/init.h>
+
+#include "powerdomain.h"
+#include <plat/clock.h>
+#include <plat/cpu.h>
+
+/* Clockdomain capability flags */
+#define CLKDM_CAN_FORCE_SLEEP			(1 << 0)
+#define CLKDM_CAN_FORCE_WAKEUP			(1 << 1)
+#define CLKDM_CAN_ENABLE_AUTO			(1 << 2)
+#define CLKDM_CAN_DISABLE_AUTO			(1 << 3)
+
+#define CLKDM_CAN_HWSUP		(CLKDM_CAN_ENABLE_AUTO | CLKDM_CAN_DISABLE_AUTO)
+#define CLKDM_CAN_SWSUP		(CLKDM_CAN_FORCE_SLEEP | CLKDM_CAN_FORCE_WAKEUP)
+#define CLKDM_CAN_HWSUP_SWSUP	(CLKDM_CAN_SWSUP | CLKDM_CAN_HWSUP)
+
+/**
+ * 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,
+ * removed when the clockdomain should be allowed to go inactive in
+ * hwsup mode.
+ *
+ * Autodeps are deprecated and should be removed after
+ * omap_hwmod-based fine-grained module idle control is added.
+ */
+struct clkdm_autodep {
+	union {
+		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
+ *
+ * Statically defined.  @clkdm is resolved from @clkdm_name at runtime and
+ * should not be pre-initialized.
+ *
+ * XXX Should also include hardware (fixed) dependencies.
+ */
+struct clkdm_dep {
+	const char *clkdm_name;
+	struct clockdomain *clkdm;
+	atomic_t wkdep_usecount;
+	atomic_t sleepdep_usecount;
+	const struct omap_chip_id omap_chip;
+};
+
+/**
+ * struct clockdomain - OMAP clockdomain
+ * @name: clockdomain name
+ * @pwrdm: powerdomain containing this clockdomain
+ * @clktrctrl_reg: CLKSTCTRL reg for the given clock domain
+ * @clktrctrl_mask: CLKTRCTRL/AUTOSTATE field mask in CM_CLKSTCTRL reg
+ * @flags: Clockdomain capability flags
+ * @dep_bit: Bit shift of this clockdomain's PM_WKDEP/CM_SLEEPDEP bit
+ * @prcm_partition: (OMAP4 only) PRCM partition ID for this clkdm's registers
+ * @cm_inst: (OMAP4 only) CM instance register offset
+ * @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
+ *
+ * @prcm_partition should be a macro from mach-omap2/prcm44xx.h (OMAP4 only)
+ * @cm_inst should be a macro ending in _INST from the OMAP4 CM instance
+ *     definitions (OMAP4 only)
+ * @clkdm_offs should be a macro ending in _CDOFFS from the OMAP4 CM instance
+ *     definitions (OMAP4 only)
+ */
+struct clockdomain {
+	const char *name;
+	union {
+		const char *name;
+		struct powerdomain *ptr;
+	} pwrdm;
+	const u16 clktrctrl_mask;
+	const u8 flags;
+	const u8 dep_bit;
+	const u8 prcm_partition;
+	const s16 cm_inst;
+	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;
+};
+
+void clkdm_init(struct clockdomain **clkdms, struct clkdm_autodep *autodeps);
+struct clockdomain *clkdm_lookup(const char *name);
+
+int clkdm_for_each(int (*fn)(struct clockdomain *clkdm, void *user),
+			void *user);
+struct powerdomain *clkdm_get_pwrdm(struct clockdomain *clkdm);
+
+int clkdm_add_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2);
+int clkdm_del_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2);
+int clkdm_read_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2);
+int clkdm_clear_all_wkdeps(struct clockdomain *clkdm);
+int clkdm_add_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2);
+int clkdm_del_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2);
+int clkdm_read_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2);
+int clkdm_clear_all_sleepdeps(struct clockdomain *clkdm);
+
+void omap2_clkdm_allow_idle(struct clockdomain *clkdm);
+void omap2_clkdm_deny_idle(struct clockdomain *clkdm);
+
+int omap2_clkdm_wakeup(struct clockdomain *clkdm);
+int omap2_clkdm_sleep(struct clockdomain *clkdm);
+
+int omap2_clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk);
+int omap2_clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk);
+
+extern void __init omap2_clockdomains_init(void);
+extern void __init omap44xx_clockdomains_init(void);
+
+#endif
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/clockdomains2xxx_3xxx_data.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/clockdomains2xxx_3xxx_data.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/clockdomains2xxx_3xxx_data.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/clockdomains2xxx_3xxx_data.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,860 @@
+/*
+ * OMAP2/3 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/sleep
+ * dependencies for the OMAP2/3 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).
+ *
+ * 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 "cm-regbits-34xx.h"
+#include "cm-regbits-44xx.h"
+#include "prm-regbits-24xx.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.
+ */
+
+/* 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 */
+
+/* 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 },
+};
+
+
+/* 2430-specific possible wakeup dependencies */
+
+#ifdef CONFIG_ARCH_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_ARCH_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 },
+};
+
+/* 3430: CM_SLEEPDEP_CAM: MPU */
+static struct clkdm_dep cam_sleepdeps[] = {
+	{
+		.clkdm_name = "mpu_clkdm",
+		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
+	},
+	{ 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)
+	},
+	{ NULL },
+};
+
+#endif /* CONFIG_ARCH_OMAP3 */
+
+
+/*
+ * OMAP2/3-common clockdomains
+ *
+ * Even though the 2420 has a single PRCM module from the
+ * interconnect's perspective, internally it does appear to have
+ * separate PRM and CM clockdomains.  The usual test case is
+ * sys_clkout/sys_clkout2.
+ */
+
+/* This is an implicit clockdomain - it is never defined as such in TRM */
+static struct clockdomain wkup_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 = {
+	.name		= "prm_clkdm",
+	.pwrdm		= { .name = "wkup_pwrdm" },
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP24XX | CHIP_IS_OMAP3430),
+};
+
+static struct clockdomain cm_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_ARCH_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_ARCH_OMAP2420 */
+
+
+/*
+ * 2430-only clockdomains
+ */
+
+#if defined(CONFIG_ARCH_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_ARCH_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_ARCH_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_ARCH_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 omap2_clockdomains_init(void)
+{
+	clkdm_init(clockdomains_omap2, clkdm_autodeps);
+}
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/clockdomains44xx_data.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/clockdomains44xx_data.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/clockdomains44xx_data.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/clockdomains44xx_data.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,309 @@
+/*
+ * OMAP4 Clock domains framework
+ *
+ * Copyright (C) 2009 Texas Instruments, Inc.
+ * Copyright (C) 2009 Nokia Corporation
+ *
+ * Abhijit Pagare (abhijitpagare@ti.com)
+ * Benoit Cousson (b-cousson@ti.com)
+ *
+ * This file is automatically generated from the OMAP hardware databases.
+ * We respectfully ask that any modifications to this file be coordinated
+ * with the public linux-omap@vger.kernel.org mailing list and the
+ * authors above to ensure that the autogeneration scripts are kept
+ * up-to-date with the file contents.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/*
+ * To-Do List
+ * -> Populate the Sleep/Wakeup dependencies for the domains
+ */
+
+#include <linux/kernel.h>
+#include <linux/io.h>
+
+#include "clockdomain.h"
+#include "cm1_44xx.h"
+#include "cm2_44xx.h"
+
+#include "cm-regbits-44xx.h"
+#include "prm44xx.h"
+#include "prcm44xx.h"
+#include "prcm_mpu44xx.h"
+
+
+static struct clockdomain l4_cefuse_44xx_clkdm = {
+	.name		  = "l4_cefuse_clkdm",
+	.pwrdm		  = { .name = "cefuse_pwrdm" },
+	.prcm_partition	  = OMAP4430_CM2_PARTITION,
+	.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 = {
+	.name		  = "l4_cfg_clkdm",
+	.pwrdm		  = { .name = "core_pwrdm" },
+	.prcm_partition	  = OMAP4430_CM2_PARTITION,
+	.cm_inst	  = OMAP4430_CM2_CORE_INST,
+	.clkdm_offs	  = OMAP4430_CM2_CORE_L4CFG_CDOFFS,
+	.flags		  = CLKDM_CAN_HWSUP,
+	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+static struct clockdomain tesla_44xx_clkdm = {
+	.name		  = "tesla_clkdm",
+	.pwrdm		  = { .name = "tesla_pwrdm" },
+	.prcm_partition	  = OMAP4430_CM1_PARTITION,
+	.cm_inst	  = OMAP4430_CM1_TESLA_INST,
+	.clkdm_offs	  = OMAP4430_CM1_TESLA_TESLA_CDOFFS,
+	.flags		  = CLKDM_CAN_HWSUP_SWSUP,
+	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+static struct clockdomain l3_gfx_44xx_clkdm = {
+	.name		  = "l3_gfx_clkdm",
+	.pwrdm		  = { .name = "gfx_pwrdm" },
+	.prcm_partition	  = OMAP4430_CM2_PARTITION,
+	.cm_inst	  = OMAP4430_CM2_GFX_INST,
+	.clkdm_offs	  = OMAP4430_CM2_GFX_GFX_CDOFFS,
+	.flags		  = CLKDM_CAN_HWSUP_SWSUP,
+	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+static struct clockdomain ivahd_44xx_clkdm = {
+	.name		  = "ivahd_clkdm",
+	.pwrdm		  = { .name = "ivahd_pwrdm" },
+	.prcm_partition	  = OMAP4430_CM2_PARTITION,
+	.cm_inst	  = OMAP4430_CM2_IVAHD_INST,
+	.clkdm_offs	  = OMAP4430_CM2_IVAHD_IVAHD_CDOFFS,
+	.flags		  = CLKDM_CAN_HWSUP_SWSUP,
+	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+static struct clockdomain l4_secure_44xx_clkdm = {
+	.name		  = "l4_secure_clkdm",
+	.pwrdm		  = { .name = "l4per_pwrdm" },
+	.prcm_partition	  = OMAP4430_CM2_PARTITION,
+	.cm_inst	  = OMAP4430_CM2_L4PER_INST,
+	.clkdm_offs	  = OMAP4430_CM2_L4PER_L4SEC_CDOFFS,
+	.flags		  = CLKDM_CAN_HWSUP_SWSUP,
+	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+static struct clockdomain l4_per_44xx_clkdm = {
+	.name		  = "l4_per_clkdm",
+	.pwrdm		  = { .name = "l4per_pwrdm" },
+	.prcm_partition	  = OMAP4430_CM2_PARTITION,
+	.cm_inst	  = OMAP4430_CM2_L4PER_INST,
+	.clkdm_offs	  = OMAP4430_CM2_L4PER_L4PER_CDOFFS,
+	.flags		  = CLKDM_CAN_HWSUP_SWSUP,
+	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+static struct clockdomain abe_44xx_clkdm = {
+	.name		  = "abe_clkdm",
+	.pwrdm		  = { .name = "abe_pwrdm" },
+	.prcm_partition	  = OMAP4430_CM1_PARTITION,
+	.cm_inst	  = OMAP4430_CM1_ABE_INST,
+	.clkdm_offs	  = OMAP4430_CM1_ABE_ABE_CDOFFS,
+	.flags		  = CLKDM_CAN_HWSUP_SWSUP,
+	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+static struct clockdomain l3_instr_44xx_clkdm = {
+	.name		  = "l3_instr_clkdm",
+	.pwrdm		  = { .name = "core_pwrdm" },
+	.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 = {
+	.name		  = "l3_init_clkdm",
+	.pwrdm		  = { .name = "l3init_pwrdm" },
+	.prcm_partition	  = OMAP4430_CM2_PARTITION,
+	.cm_inst	  = OMAP4430_CM2_L3INIT_INST,
+	.clkdm_offs	  = OMAP4430_CM2_L3INIT_L3INIT_CDOFFS,
+	.flags		  = CLKDM_CAN_HWSUP_SWSUP,
+	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+static struct clockdomain mpuss_44xx_clkdm = {
+	.name		  = "mpuss_clkdm",
+	.pwrdm		  = { .name = "mpu_pwrdm" },
+	.prcm_partition	  = OMAP4430_CM1_PARTITION,
+	.cm_inst	  = OMAP4430_CM1_MPU_INST,
+	.clkdm_offs	  = OMAP4430_CM1_MPU_MPU_CDOFFS,
+	.flags		  = CLKDM_CAN_FORCE_WAKEUP | CLKDM_CAN_HWSUP,
+	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+static struct clockdomain mpu0_44xx_clkdm = {
+	.name		  = "mpu0_clkdm",
+	.pwrdm		  = { .name = "cpu0_pwrdm" },
+	.prcm_partition	  = OMAP4430_PRCM_MPU_PARTITION,
+	.cm_inst	  = OMAP4430_PRCM_MPU_CPU0_INST,
+	.clkdm_offs	  = OMAP4430_PRCM_MPU_CPU0_MPU_CDOFFS,
+	.flags		  = CLKDM_CAN_FORCE_WAKEUP | CLKDM_CAN_HWSUP,
+	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+static struct clockdomain mpu1_44xx_clkdm = {
+	.name		  = "mpu1_clkdm",
+	.pwrdm		  = { .name = "cpu1_pwrdm" },
+	.prcm_partition	  = OMAP4430_PRCM_MPU_PARTITION,
+	.cm_inst	  = OMAP4430_PRCM_MPU_CPU1_INST,
+	.clkdm_offs	  = OMAP4430_PRCM_MPU_CPU1_MPU_CDOFFS,
+	.flags		  = CLKDM_CAN_FORCE_WAKEUP | CLKDM_CAN_HWSUP,
+	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+static struct clockdomain l3_emif_44xx_clkdm = {
+	.name		  = "l3_emif_clkdm",
+	.pwrdm		  = { .name = "core_pwrdm" },
+	.prcm_partition	  = OMAP4430_CM2_PARTITION,
+	.cm_inst	  = OMAP4430_CM2_CORE_INST,
+	.clkdm_offs	  = OMAP4430_CM2_CORE_MEMIF_CDOFFS,
+	.flags		  = CLKDM_CAN_FORCE_WAKEUP | CLKDM_CAN_HWSUP,
+	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+static struct clockdomain l4_ao_44xx_clkdm = {
+	.name		  = "l4_ao_clkdm",
+	.pwrdm		  = { .name = "always_on_core_pwrdm" },
+	.prcm_partition	  = OMAP4430_CM2_PARTITION,
+	.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 = {
+	.name		  = "ducati_clkdm",
+	.pwrdm		  = { .name = "core_pwrdm" },
+	.prcm_partition	  = OMAP4430_CM2_PARTITION,
+	.cm_inst	  = OMAP4430_CM2_CORE_INST,
+	.clkdm_offs	  = OMAP4430_CM2_CORE_DUCATI_CDOFFS,
+	.flags		  = CLKDM_CAN_HWSUP_SWSUP,
+	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+static struct clockdomain l3_2_44xx_clkdm = {
+	.name		  = "l3_2_clkdm",
+	.pwrdm		  = { .name = "core_pwrdm" },
+	.prcm_partition	  = OMAP4430_CM2_PARTITION,
+	.cm_inst	  = OMAP4430_CM2_CORE_INST,
+	.clkdm_offs	  = OMAP4430_CM2_CORE_L3_2_CDOFFS,
+	.flags		  = CLKDM_CAN_HWSUP,
+	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+static struct clockdomain l3_1_44xx_clkdm = {
+	.name		  = "l3_1_clkdm",
+	.pwrdm		  = { .name = "core_pwrdm" },
+	.prcm_partition	  = OMAP4430_CM2_PARTITION,
+	.cm_inst	  = OMAP4430_CM2_CORE_INST,
+	.clkdm_offs	  = OMAP4430_CM2_CORE_L3_1_CDOFFS,
+	.flags		  = CLKDM_CAN_HWSUP,
+	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+static struct clockdomain l3_d2d_44xx_clkdm = {
+	.name		  = "l3_d2d_clkdm",
+	.pwrdm		  = { .name = "core_pwrdm" },
+	.prcm_partition	  = OMAP4430_CM2_PARTITION,
+	.cm_inst	  = OMAP4430_CM2_CORE_INST,
+	.clkdm_offs	  = OMAP4430_CM2_CORE_D2D_CDOFFS,
+	.flags		  = CLKDM_CAN_FORCE_WAKEUP | CLKDM_CAN_HWSUP,
+	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+static struct clockdomain iss_44xx_clkdm = {
+	.name		  = "iss_clkdm",
+	.pwrdm		  = { .name = "cam_pwrdm" },
+	.prcm_partition	  = OMAP4430_CM2_PARTITION,
+	.cm_inst	  = OMAP4430_CM2_CAM_INST,
+	.clkdm_offs	  = OMAP4430_CM2_CAM_CAM_CDOFFS,
+	.flags		  = CLKDM_CAN_HWSUP_SWSUP,
+	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+static struct clockdomain l3_dss_44xx_clkdm = {
+	.name		  = "l3_dss_clkdm",
+	.pwrdm		  = { .name = "dss_pwrdm" },
+	.prcm_partition	  = OMAP4430_CM2_PARTITION,
+	.cm_inst	  = OMAP4430_CM2_DSS_INST,
+	.clkdm_offs	  = OMAP4430_CM2_DSS_DSS_CDOFFS,
+	.flags		  = CLKDM_CAN_HWSUP_SWSUP,
+	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+static struct clockdomain l4_wkup_44xx_clkdm = {
+	.name		  = "l4_wkup_clkdm",
+	.pwrdm		  = { .name = "wkup_pwrdm" },
+	.prcm_partition	  = OMAP4430_PRM_PARTITION,
+	.cm_inst	  = OMAP4430_PRM_WKUP_CM_INST,
+	.clkdm_offs	  = OMAP4430_PRM_WKUP_CM_WKUP_CDOFFS,
+	.flags		  = CLKDM_CAN_HWSUP,
+	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+static struct clockdomain emu_sys_44xx_clkdm = {
+	.name		  = "emu_sys_clkdm",
+	.pwrdm		  = { .name = "emu_pwrdm" },
+	.prcm_partition	  = OMAP4430_PRM_PARTITION,
+	.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 = {
+	.name		  = "l3_dma_clkdm",
+	.pwrdm		  = { .name = "core_pwrdm" },
+	.prcm_partition	  = OMAP4430_CM2_PARTITION,
+	.cm_inst	  = OMAP4430_CM2_CORE_INST,
+	.clkdm_offs	  = OMAP4430_CM2_CORE_SDMA_CDOFFS,
+	.flags		  = CLKDM_CAN_FORCE_WAKEUP | CLKDM_CAN_HWSUP,
+	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+static struct clockdomain *clockdomains_omap44xx[] __initdata = {
+	&l4_cefuse_44xx_clkdm,
+	&l4_cfg_44xx_clkdm,
+	&tesla_44xx_clkdm,
+	&l3_gfx_44xx_clkdm,
+	&ivahd_44xx_clkdm,
+	&l4_secure_44xx_clkdm,
+	&l4_per_44xx_clkdm,
+	&abe_44xx_clkdm,
+	&l3_instr_44xx_clkdm,
+	&l3_init_44xx_clkdm,
+	&mpuss_44xx_clkdm,
+	&mpu0_44xx_clkdm,
+	&mpu1_44xx_clkdm,
+	&l3_emif_44xx_clkdm,
+	&l4_ao_44xx_clkdm,
+	&ducati_44xx_clkdm,
+	&l3_2_44xx_clkdm,
+	&l3_1_44xx_clkdm,
+	&l3_d2d_44xx_clkdm,
+	&iss_44xx_clkdm,
+	&l3_dss_44xx_clkdm,
+	&l4_wkup_44xx_clkdm,
+	&emu_sys_44xx_clkdm,
+	&l3_dma_44xx_clkdm,
+	NULL,
+};
+
+void __init omap44xx_clockdomains_init(void)
+{
+	clkdm_init(clockdomains_omap44xx, NULL);
+}
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/clockdomains44xx.h linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/clockdomains44xx.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/clockdomains44xx.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/clockdomains44xx.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,250 +0,0 @@
-/*
- * OMAP4 Clock domains framework
- *
- * Copyright (C) 2009 Texas Instruments, Inc.
- * Copyright (C) 2009 Nokia Corporation
- *
- * Abhijit Pagare (abhijitpagare@ti.com)
- * Benoit Cousson (b-cousson@ti.com)
- *
- * This file is automatically generated from the OMAP hardware databases.
- * We respectfully ask that any modifications to this file be coordinated
- * with the public linux-omap@vger.kernel.org mailing list and the
- * authors above to ensure that the autogeneration scripts are kept
- * up-to-date with the file contents.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-/*
- * To-Do List
- * -> Populate the Sleep/Wakeup dependencies for the domains
- */
-
-#ifndef __ARCH_ARM_MACH_OMAP2_CLOCKDOMAINS44XX_H
-#define __ARCH_ARM_MACH_OMAP2_CLOCKDOMAINS44XX_H
-
-#include <plat/clockdomain.h>
-
-#if defined(CONFIG_ARCH_OMAP4)
-
-static struct clockdomain l4_cefuse_44xx_clkdm = {
-	.name		  = "l4_cefuse_clkdm",
-	.pwrdm		  = { .name = "cefuse_pwrdm" },
-	.clkstctrl_reg	  = OMAP4430_CM_CEFUSE_CLKSTCTRL,
-	.clktrctrl_mask	  = OMAP4430_CLKTRCTRL_MASK,
-	.flags		  = CLKDM_CAN_FORCE_WAKEUP | CLKDM_CAN_HWSUP,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
-};
-
-static struct clockdomain l4_cfg_44xx_clkdm = {
-	.name		  = "l4_cfg_clkdm",
-	.pwrdm		  = { .name = "core_pwrdm" },
-	.clkstctrl_reg	  = OMAP4430_CM_L4CFG_CLKSTCTRL,
-	.clktrctrl_mask	  = OMAP4430_CLKTRCTRL_MASK,
-	.flags		  = CLKDM_CAN_HWSUP,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
-};
-
-static struct clockdomain tesla_44xx_clkdm = {
-	.name		  = "tesla_clkdm",
-	.pwrdm		  = { .name = "tesla_pwrdm" },
-	.clkstctrl_reg	  = OMAP4430_CM_TESLA_CLKSTCTRL,
-	.clktrctrl_mask	  = OMAP4430_CLKTRCTRL_MASK,
-	.flags		  = CLKDM_CAN_HWSUP_SWSUP,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
-};
-
-static struct clockdomain l3_gfx_44xx_clkdm = {
-	.name		  = "l3_gfx_clkdm",
-	.pwrdm		  = { .name = "gfx_pwrdm" },
-	.clkstctrl_reg	  = OMAP4430_CM_GFX_CLKSTCTRL,
-	.clktrctrl_mask	  = OMAP4430_CLKTRCTRL_MASK,
-	.flags		  = CLKDM_CAN_HWSUP_SWSUP,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
-};
-
-static struct clockdomain ivahd_44xx_clkdm = {
-	.name		  = "ivahd_clkdm",
-	.pwrdm		  = { .name = "ivahd_pwrdm" },
-	.clkstctrl_reg	  = OMAP4430_CM_IVAHD_CLKSTCTRL,
-	.clktrctrl_mask	  = OMAP4430_CLKTRCTRL_MASK,
-	.flags		  = CLKDM_CAN_HWSUP_SWSUP,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
-};
-
-static struct clockdomain l4_secure_44xx_clkdm = {
-	.name		  = "l4_secure_clkdm",
-	.pwrdm		  = { .name = "l4per_pwrdm" },
-	.clkstctrl_reg	  = OMAP4430_CM_L4SEC_CLKSTCTRL,
-	.clktrctrl_mask	  = OMAP4430_CLKTRCTRL_MASK,
-	.flags		  = CLKDM_CAN_HWSUP_SWSUP,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
-};
-
-static struct clockdomain l4_per_44xx_clkdm = {
-	.name		  = "l4_per_clkdm",
-	.pwrdm		  = { .name = "l4per_pwrdm" },
-	.clkstctrl_reg	  = OMAP4430_CM_L4PER_CLKSTCTRL,
-	.clktrctrl_mask	  = OMAP4430_CLKTRCTRL_MASK,
-	.flags		  = CLKDM_CAN_HWSUP_SWSUP,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
-};
-
-static struct clockdomain abe_44xx_clkdm = {
-	.name		  = "abe_clkdm",
-	.pwrdm		  = { .name = "abe_pwrdm" },
-	.clkstctrl_reg	  = OMAP4430_CM1_ABE_CLKSTCTRL,
-	.clktrctrl_mask	  = OMAP4430_CLKTRCTRL_MASK,
-	.flags		  = CLKDM_CAN_HWSUP_SWSUP,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
-};
-
-static struct clockdomain l3_instr_44xx_clkdm = {
-	.name		  = "l3_instr_clkdm",
-	.pwrdm		  = { .name = "core_pwrdm" },
-	.clkstctrl_reg	  = OMAP4430_CM_L3INSTR_CLKSTCTRL,
-	.clktrctrl_mask	  = OMAP4430_CLKTRCTRL_MASK,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
-};
-
-static struct clockdomain l3_init_44xx_clkdm = {
-	.name		  = "l3_init_clkdm",
-	.pwrdm		  = { .name = "l3init_pwrdm" },
-	.clkstctrl_reg	  = OMAP4430_CM_L3INIT_CLKSTCTRL,
-	.clktrctrl_mask	  = OMAP4430_CLKTRCTRL_MASK,
-	.flags		  = CLKDM_CAN_HWSUP_SWSUP,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
-};
-
-static struct clockdomain mpuss_44xx_clkdm = {
-	.name		  = "mpuss_clkdm",
-	.pwrdm		  = { .name = "mpu_pwrdm" },
-	.clkstctrl_reg	  = OMAP4430_CM_MPU_CLKSTCTRL,
-	.clktrctrl_mask	  = OMAP4430_CLKTRCTRL_MASK,
-	.flags		  = CLKDM_CAN_FORCE_WAKEUP | CLKDM_CAN_HWSUP,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
-};
-
-static struct clockdomain mpu0_44xx_clkdm = {
-	.name		  = "mpu0_clkdm",
-	.pwrdm		  = { .name = "cpu0_pwrdm" },
-	.clkstctrl_reg	  = OMAP4430_CM_CPU0_CLKSTCTRL,
-	.clktrctrl_mask	  = OMAP4430_CLKTRCTRL_MASK,
-	.flags		  = CLKDM_CAN_FORCE_WAKEUP | CLKDM_CAN_HWSUP,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
-};
-
-static struct clockdomain mpu1_44xx_clkdm = {
-	.name		  = "mpu1_clkdm",
-	.pwrdm		  = { .name = "cpu1_pwrdm" },
-	.clkstctrl_reg	  = OMAP4430_CM_CPU1_CLKSTCTRL,
-	.clktrctrl_mask	  = OMAP4430_CLKTRCTRL_MASK,
-	.flags		  = CLKDM_CAN_FORCE_WAKEUP | CLKDM_CAN_HWSUP,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
-};
-
-static struct clockdomain l3_emif_44xx_clkdm = {
-	.name		  = "l3_emif_clkdm",
-	.pwrdm		  = { .name = "core_pwrdm" },
-	.clkstctrl_reg	  = OMAP4430_CM_MEMIF_CLKSTCTRL,
-	.clktrctrl_mask	  = OMAP4430_CLKTRCTRL_MASK,
-	.flags		  = CLKDM_CAN_FORCE_WAKEUP | CLKDM_CAN_HWSUP,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
-};
-
-static struct clockdomain l4_ao_44xx_clkdm = {
-	.name		  = "l4_ao_clkdm",
-	.pwrdm		  = { .name = "always_on_core_pwrdm" },
-	.clkstctrl_reg	  = OMAP4430_CM_ALWON_CLKSTCTRL,
-	.clktrctrl_mask	  = OMAP4430_CLKTRCTRL_MASK,
-	.flags		  = CLKDM_CAN_FORCE_WAKEUP | CLKDM_CAN_HWSUP,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
-};
-
-static struct clockdomain ducati_44xx_clkdm = {
-	.name		  = "ducati_clkdm",
-	.pwrdm		  = { .name = "core_pwrdm" },
-	.clkstctrl_reg	  = OMAP4430_CM_DUCATI_CLKSTCTRL,
-	.clktrctrl_mask	  = OMAP4430_CLKTRCTRL_MASK,
-	.flags		  = CLKDM_CAN_HWSUP_SWSUP,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
-};
-
-static struct clockdomain l3_2_44xx_clkdm = {
-	.name		  = "l3_2_clkdm",
-	.pwrdm		  = { .name = "core_pwrdm" },
-	.clkstctrl_reg	  = OMAP4430_CM_L3_2_CLKSTCTRL,
-	.clktrctrl_mask	  = OMAP4430_CLKTRCTRL_MASK,
-	.flags		  = CLKDM_CAN_HWSUP,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
-};
-
-static struct clockdomain l3_1_44xx_clkdm = {
-	.name		  = "l3_1_clkdm",
-	.pwrdm		  = { .name = "core_pwrdm" },
-	.clkstctrl_reg	  = OMAP4430_CM_L3_1_CLKSTCTRL,
-	.clktrctrl_mask	  = OMAP4430_CLKTRCTRL_MASK,
-	.flags		  = CLKDM_CAN_HWSUP,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
-};
-
-static struct clockdomain l3_d2d_44xx_clkdm = {
-	.name		  = "l3_d2d_clkdm",
-	.pwrdm		  = { .name = "core_pwrdm" },
-	.clkstctrl_reg	  = OMAP4430_CM_D2D_CLKSTCTRL,
-	.clktrctrl_mask	  = OMAP4430_CLKTRCTRL_MASK,
-	.flags		  = CLKDM_CAN_FORCE_WAKEUP | CLKDM_CAN_HWSUP,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
-};
-
-static struct clockdomain iss_44xx_clkdm = {
-	.name		  = "iss_clkdm",
-	.pwrdm		  = { .name = "cam_pwrdm" },
-	.clkstctrl_reg	  = OMAP4430_CM_CAM_CLKSTCTRL,
-	.clktrctrl_mask	  = OMAP4430_CLKTRCTRL_MASK,
-	.flags		  = CLKDM_CAN_HWSUP_SWSUP,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
-};
-
-static struct clockdomain l3_dss_44xx_clkdm = {
-	.name		  = "l3_dss_clkdm",
-	.pwrdm		  = { .name = "dss_pwrdm" },
-	.clkstctrl_reg	  = OMAP4430_CM_DSS_CLKSTCTRL,
-	.clktrctrl_mask	  = OMAP4430_CLKTRCTRL_MASK,
-	.flags		  = CLKDM_CAN_HWSUP_SWSUP,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
-};
-
-static struct clockdomain l4_wkup_44xx_clkdm = {
-	.name		  = "l4_wkup_clkdm",
-	.pwrdm		  = { .name = "wkup_pwrdm" },
-	.clkstctrl_reg	  = OMAP4430_CM_WKUP_CLKSTCTRL,
-	.clktrctrl_mask	  = OMAP4430_CLKTRCTRL_MASK,
-	.flags		  = CLKDM_CAN_HWSUP,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
-};
-
-static struct clockdomain emu_sys_44xx_clkdm = {
-	.name		  = "emu_sys_clkdm",
-	.pwrdm		  = { .name = "emu_pwrdm" },
-	.clkstctrl_reg	  = OMAP4430_CM_EMU_CLKSTCTRL,
-	.clktrctrl_mask	  = OMAP4430_CLKTRCTRL_MASK,
-	.flags		  = CLKDM_CAN_HWSUP,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
-};
-
-static struct clockdomain l3_dma_44xx_clkdm = {
-	.name		  = "l3_dma_clkdm",
-	.pwrdm		  = { .name = "core_pwrdm" },
-	.clkstctrl_reg	  = OMAP4430_CM_SDMA_CLKSTCTRL,
-	.clktrctrl_mask	  = OMAP4430_CLKTRCTRL_MASK,
-	.flags		  = CLKDM_CAN_FORCE_WAKEUP | CLKDM_CAN_HWSUP,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
-};
-
-#endif
-
-#endif
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/clockdomains.h linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/clockdomains.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/clockdomains.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/clockdomains.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,937 +0,0 @@
-/*
- * OMAP2/3 clockdomains
- *
- * Copyright (C) 2008-2009 Texas Instruments, Inc.
- * Copyright (C) 2008-2010 Nokia Corporation
- *
- * Written by Paul Walmsley and Jouni Högander
- *
- * This file contains clockdomains and clockdomain wakeup/sleep
- * dependencies for the OMAP2/3 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).
- *
- * 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
- */
-
-#ifndef __ARCH_ARM_MACH_OMAP2_CLOCKDOMAINS_H
-#define __ARCH_ARM_MACH_OMAP2_CLOCKDOMAINS_H
-
-#include <plat/clockdomain.h>
-#include "cm.h"
-#include "prm.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.
- */
-
-/* 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
-
-
-/* 2430-specific possible wakeup dependencies */
-
-#ifdef CONFIG_ARCH_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_ARCH_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 },
-};
-
-/* 3430: CM_SLEEPDEP_CAM: MPU */
-static struct clkdm_dep cam_sleepdeps[] = {
-	{
-		.clkdm_name = "mpu_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{ 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)
-	},
-	{ NULL },
-};
-
-#endif /* CONFIG_ARCH_OMAP3 */
-
-
-/*
- * OMAP2/3-common clockdomains
- *
- * Even though the 2420 has a single PRCM module from the
- * interconnect's perspective, internally it does appear to have
- * separate PRM and CM clockdomains.  The usual test case is
- * sys_clkout/sys_clkout2.
- */
-
-#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
-
-/* This is an implicit clockdomain - it is never defined as such in TRM */
-static struct clockdomain wkup_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 = {
-	.name		= "prm_clkdm",
-	.pwrdm		= { .name = "wkup_pwrdm" },
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP24XX | CHIP_IS_OMAP3430),
-};
-
-static struct clockdomain cm_clkdm = {
-	.name		= "cm_clkdm",
-	.pwrdm		= { .name = "core_pwrdm" },
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP24XX | CHIP_IS_OMAP3430),
-};
-
-#endif
-
-/*
- * 2420-only clockdomains
- */
-
-#if defined(CONFIG_ARCH_OMAP2420)
-
-static struct clockdomain mpu_2420_clkdm = {
-	.name		= "mpu_clkdm",
-	.pwrdm		= { .name = "mpu_pwrdm" },
-	.flags		= CLKDM_CAN_HWSUP,
-	.clkstctrl_reg  = OMAP2420_CM_REGADDR(MPU_MOD, OMAP2_CM_CLKSTCTRL),
-	.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,
-	.clkstctrl_reg  = OMAP2420_CM_REGADDR(OMAP24XX_DSP_MOD,
-						 OMAP2_CM_CLKSTCTRL),
-	.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,
-	.clkstctrl_reg  = OMAP2420_CM_REGADDR(OMAP24XX_DSP_MOD,
-						 OMAP2_CM_CLKSTCTRL),
-	.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,
-	.clkstctrl_reg  = OMAP2420_CM_REGADDR(GFX_MOD, OMAP2_CM_CLKSTCTRL),
-	.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,
-	.clkstctrl_reg  = OMAP2420_CM_REGADDR(CORE_MOD, OMAP2_CM_CLKSTCTRL),
-	.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,
-	.clkstctrl_reg  = OMAP2420_CM_REGADDR(CORE_MOD, OMAP2_CM_CLKSTCTRL),
-	.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,
-	.clkstctrl_reg  = OMAP2420_CM_REGADDR(CORE_MOD, OMAP2_CM_CLKSTCTRL),
-	.clktrctrl_mask = OMAP24XX_AUTOSTATE_DSS_MASK,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
-};
-
-#endif   /* CONFIG_ARCH_OMAP2420 */
-
-
-/*
- * 2430-only clockdomains
- */
-
-#if defined(CONFIG_ARCH_OMAP2430)
-
-static struct clockdomain mpu_2430_clkdm = {
-	.name		= "mpu_clkdm",
-	.pwrdm		= { .name = "mpu_pwrdm" },
-	.flags		= CLKDM_CAN_HWSUP_SWSUP,
-	.clkstctrl_reg  = OMAP2430_CM_REGADDR(MPU_MOD,
-						 OMAP2_CM_CLKSTCTRL),
-	.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,
-	.clkstctrl_reg  = OMAP2430_CM_REGADDR(OMAP2430_MDM_MOD,
-						 OMAP2_CM_CLKSTCTRL),
-	.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,
-	.clkstctrl_reg  = OMAP2430_CM_REGADDR(OMAP24XX_DSP_MOD,
-						 OMAP2_CM_CLKSTCTRL),
-	.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,
-	.clkstctrl_reg  = OMAP2430_CM_REGADDR(GFX_MOD, OMAP2_CM_CLKSTCTRL),
-	.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,
-	.clkstctrl_reg  = OMAP2430_CM_REGADDR(CORE_MOD, OMAP2_CM_CLKSTCTRL),
-	.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,
-	.clkstctrl_reg  = OMAP2430_CM_REGADDR(CORE_MOD, OMAP2_CM_CLKSTCTRL),
-	.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,
-	.clkstctrl_reg  = OMAP2430_CM_REGADDR(CORE_MOD, OMAP2_CM_CLKSTCTRL),
-	.clktrctrl_mask = OMAP24XX_AUTOSTATE_DSS_MASK,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
-};
-
-#endif    /* CONFIG_ARCH_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,
-	.clkstctrl_reg	= OMAP34XX_CM_REGADDR(MPU_MOD, OMAP2_CM_CLKSTCTRL),
-	.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,
-	.clkstctrl_reg	= OMAP34XX_CM_REGADDR(OMAP3430_NEON_MOD,
-						 OMAP2_CM_CLKSTCTRL),
-	.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,
-	.clkstctrl_reg	= OMAP34XX_CM_REGADDR(OMAP3430_IVA2_MOD,
-						 OMAP2_CM_CLKSTCTRL),
-	.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,
-	.clkstctrl_reg	= OMAP34XX_CM_REGADDR(GFX_MOD, OMAP2_CM_CLKSTCTRL),
-	.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,
-	.clkstctrl_reg	= OMAP34XX_CM_REGADDR(OMAP3430ES2_SGX_MOD,
-						 OMAP2_CM_CLKSTCTRL),
-	.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,
-	.clkstctrl_reg	= OMAP34XX_CM_REGADDR(CORE_MOD, OMAP2_CM_CLKSTCTRL),
-	.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,
-	.clkstctrl_reg	= OMAP34XX_CM_REGADDR(CORE_MOD, OMAP2_CM_CLKSTCTRL),
-	.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,
-	.clkstctrl_reg	= OMAP34XX_CM_REGADDR(CORE_MOD, OMAP2_CM_CLKSTCTRL),
-	.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,
-	.clkstctrl_reg	= OMAP34XX_CM_REGADDR(OMAP3430_DSS_MOD,
-						 OMAP2_CM_CLKSTCTRL),
-	.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,
-	.clkstctrl_reg	= OMAP34XX_CM_REGADDR(OMAP3430_CAM_MOD,
-						 OMAP2_CM_CLKSTCTRL),
-	.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,
-	.clkstctrl_reg	= OMAP34XX_CM_REGADDR(OMAP3430ES2_USBHOST_MOD,
-						 OMAP2_CM_CLKSTCTRL),
-	.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,
-	.clkstctrl_reg	= OMAP34XX_CM_REGADDR(OMAP3430_PER_MOD,
-						 OMAP2_CM_CLKSTCTRL),
-	.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,
-	.clkstctrl_reg	= OMAP34XX_CM_REGADDR(OMAP3430_EMU_MOD,
-						 OMAP2_CM_CLKSTCTRL),
-	.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 */
-
-#include "clockdomains44xx.h"
-
-/*
- * 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 },
-	}
-};
-
-/*
- * List of clockdomain pointers per platform
- */
-
-static struct clockdomain *clockdomains_omap[] = {
-
-#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
-	&wkup_clkdm,
-	&cm_clkdm,
-	&prm_clkdm,
-#endif
-
-#ifdef CONFIG_ARCH_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_ARCH_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
-
-#ifdef CONFIG_ARCH_OMAP4
-	&l4_cefuse_44xx_clkdm,
-	&l4_cfg_44xx_clkdm,
-	&tesla_44xx_clkdm,
-	&l3_gfx_44xx_clkdm,
-	&ivahd_44xx_clkdm,
-	&l4_secure_44xx_clkdm,
-	&l4_per_44xx_clkdm,
-	&abe_44xx_clkdm,
-	&l3_instr_44xx_clkdm,
-	&l3_init_44xx_clkdm,
-	&mpuss_44xx_clkdm,
-	&mpu0_44xx_clkdm,
-	&mpu1_44xx_clkdm,
-	&l3_emif_44xx_clkdm,
-	&l4_ao_44xx_clkdm,
-	&ducati_44xx_clkdm,
-	&l3_2_44xx_clkdm,
-	&l3_1_44xx_clkdm,
-	&l3_d2d_44xx_clkdm,
-	&iss_44xx_clkdm,
-	&l3_dss_44xx_clkdm,
-	&l4_wkup_44xx_clkdm,
-	&emu_sys_44xx_clkdm,
-	&l3_dma_44xx_clkdm,
-#endif
-
-	NULL,
-};
-
-#endif
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/clock.h linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/clock.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/clock.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/clock.h	2011-03-14 21:20:32.000000000 -0400
@@ -49,7 +49,6 @@
 
 /* DPLL Type and DCO Selection Flags */
 #define DPLL_J_TYPE		0x1
-#define DPLL_NO_DCO_SEL		0x2
 
 int omap2_clk_enable(struct clk *clk);
 void omap2_clk_disable(struct clk *clk);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/cm1_44xx.h linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/cm1_44xx.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/cm1_44xx.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/cm1_44xx.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,261 @@
+/*
+ * OMAP44xx CM1 instance offset macros
+ *
+ * Copyright (C) 2009-2010 Texas Instruments, Inc.
+ * Copyright (C) 2009-2010 Nokia Corporation
+ *
+ * Paul Walmsley (paul@pwsan.com)
+ * Rajendra Nayak (rnayak@ti.com)
+ * Benoit Cousson (b-cousson@ti.com)
+ *
+ * This file is automatically generated from the OMAP hardware databases.
+ * We respectfully ask that any modifications to this file be coordinated
+ * with the public linux-omap@vger.kernel.org mailing list and the
+ * authors above to ensure that the autogeneration scripts are kept
+ * up-to-date with the file contents.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * XXX This file needs to be updated to align on one of "OMAP4", "OMAP44XX",
+ *     or "OMAP4430".
+ */
+
+#ifndef __ARCH_ARM_MACH_OMAP2_CM1_44XX_H
+#define __ARCH_ARM_MACH_OMAP2_CM1_44XX_H
+
+/* CM1 base address */
+#define OMAP4430_CM1_BASE		0x4a004000
+
+#define OMAP44XX_CM1_REGADDR(inst, reg)				\
+	OMAP2_L4_IO_ADDRESS(OMAP4430_CM1_BASE + (inst) + (reg))
+
+/* CM1 instances */
+#define OMAP4430_CM1_OCP_SOCKET_INST	0x0000
+#define OMAP4430_CM1_CKGEN_INST		0x0100
+#define OMAP4430_CM1_MPU_INST		0x0300
+#define OMAP4430_CM1_TESLA_INST		0x0400
+#define OMAP4430_CM1_ABE_INST		0x0500
+#define OMAP4430_CM1_RESTORE_INST	0x0e00
+#define OMAP4430_CM1_INSTR_INST		0x0f00
+
+/* CM1 clockdomain register offsets (from instance start) */
+#define OMAP4430_CM1_ABE_ABE_CDOFFS		0x0000
+#define OMAP4430_CM1_MPU_MPU_CDOFFS		0x0000
+#define OMAP4430_CM1_TESLA_TESLA_CDOFFS		0x0000
+
+/* CM1 */
+
+/* CM1.OCP_SOCKET_CM1 register offsets */
+#define OMAP4_REVISION_CM1_OFFSET			0x0000
+#define OMAP4430_REVISION_CM1				OMAP44XX_CM1_REGADDR(OMAP4430_CM1_OCP_SOCKET_INST, 0x0000)
+#define OMAP4_CM_CM1_PROFILING_CLKCTRL_OFFSET		0x0040
+#define OMAP4430_CM_CM1_PROFILING_CLKCTRL		OMAP44XX_CM1_REGADDR(OMAP4430_CM1_OCP_SOCKET_INST, 0x0040)
+
+/* CM1.CKGEN_CM1 register offsets */
+#define OMAP4_CM_CLKSEL_CORE_OFFSET			0x0000
+#define OMAP4430_CM_CLKSEL_CORE				OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x0000)
+#define OMAP4_CM_CLKSEL_ABE_OFFSET			0x0008
+#define OMAP4430_CM_CLKSEL_ABE				OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x0008)
+#define OMAP4_CM_DLL_CTRL_OFFSET			0x0010
+#define OMAP4430_CM_DLL_CTRL				OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x0010)
+#define OMAP4_CM_CLKMODE_DPLL_CORE_OFFSET		0x0020
+#define OMAP4430_CM_CLKMODE_DPLL_CORE			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x0020)
+#define OMAP4_CM_IDLEST_DPLL_CORE_OFFSET		0x0024
+#define OMAP4430_CM_IDLEST_DPLL_CORE			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x0024)
+#define OMAP4_CM_AUTOIDLE_DPLL_CORE_OFFSET		0x0028
+#define OMAP4430_CM_AUTOIDLE_DPLL_CORE			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x0028)
+#define OMAP4_CM_CLKSEL_DPLL_CORE_OFFSET		0x002c
+#define OMAP4430_CM_CLKSEL_DPLL_CORE			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x002c)
+#define OMAP4_CM_DIV_M2_DPLL_CORE_OFFSET		0x0030
+#define OMAP4430_CM_DIV_M2_DPLL_CORE			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x0030)
+#define OMAP4_CM_DIV_M3_DPLL_CORE_OFFSET		0x0034
+#define OMAP4430_CM_DIV_M3_DPLL_CORE			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x0034)
+#define OMAP4_CM_DIV_M4_DPLL_CORE_OFFSET		0x0038
+#define OMAP4430_CM_DIV_M4_DPLL_CORE			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x0038)
+#define OMAP4_CM_DIV_M5_DPLL_CORE_OFFSET		0x003c
+#define OMAP4430_CM_DIV_M5_DPLL_CORE			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x003c)
+#define OMAP4_CM_DIV_M6_DPLL_CORE_OFFSET		0x0040
+#define OMAP4430_CM_DIV_M6_DPLL_CORE			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x0040)
+#define OMAP4_CM_DIV_M7_DPLL_CORE_OFFSET		0x0044
+#define OMAP4430_CM_DIV_M7_DPLL_CORE			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x0044)
+#define OMAP4_CM_SSC_DELTAMSTEP_DPLL_CORE_OFFSET	0x0048
+#define OMAP4430_CM_SSC_DELTAMSTEP_DPLL_CORE		OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x0048)
+#define OMAP4_CM_SSC_INSTFREQDIV_DPLL_CORE_OFFSET	0x004c
+#define OMAP4430_CM_SSC_INSTFREQDIV_DPLL_CORE		OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x004c)
+#define OMAP4_CM_EMU_OVERRIDE_DPLL_CORE_OFFSET		0x0050
+#define OMAP4430_CM_EMU_OVERRIDE_DPLL_CORE		OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x0050)
+#define OMAP4_CM_CLKMODE_DPLL_MPU_OFFSET		0x0060
+#define OMAP4430_CM_CLKMODE_DPLL_MPU			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x0060)
+#define OMAP4_CM_IDLEST_DPLL_MPU_OFFSET			0x0064
+#define OMAP4430_CM_IDLEST_DPLL_MPU			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x0064)
+#define OMAP4_CM_AUTOIDLE_DPLL_MPU_OFFSET		0x0068
+#define OMAP4430_CM_AUTOIDLE_DPLL_MPU			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x0068)
+#define OMAP4_CM_CLKSEL_DPLL_MPU_OFFSET			0x006c
+#define OMAP4430_CM_CLKSEL_DPLL_MPU			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x006c)
+#define OMAP4_CM_DIV_M2_DPLL_MPU_OFFSET			0x0070
+#define OMAP4430_CM_DIV_M2_DPLL_MPU			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x0070)
+#define OMAP4_CM_SSC_DELTAMSTEP_DPLL_MPU_OFFSET		0x0088
+#define OMAP4430_CM_SSC_DELTAMSTEP_DPLL_MPU		OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x0088)
+#define OMAP4_CM_SSC_INSTFREQDIV_DPLL_MPU_OFFSET		0x008c
+#define OMAP4430_CM_SSC_INSTFREQDIV_DPLL_MPU		OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x008c)
+#define OMAP4_CM_BYPCLK_DPLL_MPU_OFFSET			0x009c
+#define OMAP4430_CM_BYPCLK_DPLL_MPU			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x009c)
+#define OMAP4_CM_CLKMODE_DPLL_IVA_OFFSET		0x00a0
+#define OMAP4430_CM_CLKMODE_DPLL_IVA			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x00a0)
+#define OMAP4_CM_IDLEST_DPLL_IVA_OFFSET			0x00a4
+#define OMAP4430_CM_IDLEST_DPLL_IVA			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x00a4)
+#define OMAP4_CM_AUTOIDLE_DPLL_IVA_OFFSET		0x00a8
+#define OMAP4430_CM_AUTOIDLE_DPLL_IVA			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x00a8)
+#define OMAP4_CM_CLKSEL_DPLL_IVA_OFFSET			0x00ac
+#define OMAP4430_CM_CLKSEL_DPLL_IVA			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x00ac)
+#define OMAP4_CM_DIV_M4_DPLL_IVA_OFFSET			0x00b8
+#define OMAP4430_CM_DIV_M4_DPLL_IVA			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x00b8)
+#define OMAP4_CM_DIV_M5_DPLL_IVA_OFFSET			0x00bc
+#define OMAP4430_CM_DIV_M5_DPLL_IVA			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x00bc)
+#define OMAP4_CM_SSC_DELTAMSTEP_DPLL_IVA_OFFSET		0x00c8
+#define OMAP4430_CM_SSC_DELTAMSTEP_DPLL_IVA		OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x00c8)
+#define OMAP4_CM_SSC_INSTFREQDIV_DPLL_IVA_OFFSET		0x00cc
+#define OMAP4430_CM_SSC_INSTFREQDIV_DPLL_IVA		OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x00cc)
+#define OMAP4_CM_BYPCLK_DPLL_IVA_OFFSET			0x00dc
+#define OMAP4430_CM_BYPCLK_DPLL_IVA			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x00dc)
+#define OMAP4_CM_CLKMODE_DPLL_ABE_OFFSET		0x00e0
+#define OMAP4430_CM_CLKMODE_DPLL_ABE			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x00e0)
+#define OMAP4_CM_IDLEST_DPLL_ABE_OFFSET			0x00e4
+#define OMAP4430_CM_IDLEST_DPLL_ABE			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x00e4)
+#define OMAP4_CM_AUTOIDLE_DPLL_ABE_OFFSET		0x00e8
+#define OMAP4430_CM_AUTOIDLE_DPLL_ABE			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x00e8)
+#define OMAP4_CM_CLKSEL_DPLL_ABE_OFFSET			0x00ec
+#define OMAP4430_CM_CLKSEL_DPLL_ABE			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x00ec)
+#define OMAP4_CM_DIV_M2_DPLL_ABE_OFFSET			0x00f0
+#define OMAP4430_CM_DIV_M2_DPLL_ABE			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x00f0)
+#define OMAP4_CM_DIV_M3_DPLL_ABE_OFFSET			0x00f4
+#define OMAP4430_CM_DIV_M3_DPLL_ABE			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x00f4)
+#define OMAP4_CM_SSC_DELTAMSTEP_DPLL_ABE_OFFSET		0x0108
+#define OMAP4430_CM_SSC_DELTAMSTEP_DPLL_ABE		OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x0108)
+#define OMAP4_CM_SSC_INSTFREQDIV_DPLL_ABE_OFFSET		0x010c
+#define OMAP4430_CM_SSC_INSTFREQDIV_DPLL_ABE		OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x010c)
+#define OMAP4_CM_CLKMODE_DPLL_DDRPHY_OFFSET		0x0120
+#define OMAP4430_CM_CLKMODE_DPLL_DDRPHY			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x0120)
+#define OMAP4_CM_IDLEST_DPLL_DDRPHY_OFFSET		0x0124
+#define OMAP4430_CM_IDLEST_DPLL_DDRPHY			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x0124)
+#define OMAP4_CM_AUTOIDLE_DPLL_DDRPHY_OFFSET		0x0128
+#define OMAP4430_CM_AUTOIDLE_DPLL_DDRPHY		OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x0128)
+#define OMAP4_CM_CLKSEL_DPLL_DDRPHY_OFFSET		0x012c
+#define OMAP4430_CM_CLKSEL_DPLL_DDRPHY			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x012c)
+#define OMAP4_CM_DIV_M2_DPLL_DDRPHY_OFFSET		0x0130
+#define OMAP4430_CM_DIV_M2_DPLL_DDRPHY			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x0130)
+#define OMAP4_CM_DIV_M4_DPLL_DDRPHY_OFFSET		0x0138
+#define OMAP4430_CM_DIV_M4_DPLL_DDRPHY			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x0138)
+#define OMAP4_CM_DIV_M5_DPLL_DDRPHY_OFFSET		0x013c
+#define OMAP4430_CM_DIV_M5_DPLL_DDRPHY			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x013c)
+#define OMAP4_CM_DIV_M6_DPLL_DDRPHY_OFFSET		0x0140
+#define OMAP4430_CM_DIV_M6_DPLL_DDRPHY			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x0140)
+#define OMAP4_CM_SSC_DELTAMSTEP_DPLL_DDRPHY_OFFSET	0x0148
+#define OMAP4430_CM_SSC_DELTAMSTEP_DPLL_DDRPHY		OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x0148)
+#define OMAP4_CM_SSC_INSTFREQDIV_DPLL_DDRPHY_OFFSET	0x014c
+#define OMAP4430_CM_SSC_INSTFREQDIV_DPLL_DDRPHY		OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x014c)
+#define OMAP4_CM_SHADOW_FREQ_CONFIG1_OFFSET		0x0160
+#define OMAP4430_CM_SHADOW_FREQ_CONFIG1			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x0160)
+#define OMAP4_CM_SHADOW_FREQ_CONFIG2_OFFSET		0x0164
+#define OMAP4430_CM_SHADOW_FREQ_CONFIG2			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x0164)
+#define OMAP4_CM_DYN_DEP_PRESCAL_OFFSET			0x0170
+#define OMAP4430_CM_DYN_DEP_PRESCAL			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x0170)
+#define OMAP4_CM_RESTORE_ST_OFFSET			0x0180
+#define OMAP4430_CM_RESTORE_ST				OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x0180)
+
+/* CM1.MPU_CM1 register offsets */
+#define OMAP4_CM_MPU_CLKSTCTRL_OFFSET			0x0000
+#define OMAP4430_CM_MPU_CLKSTCTRL			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_MPU_INST, 0x0000)
+#define OMAP4_CM_MPU_STATICDEP_OFFSET			0x0004
+#define OMAP4430_CM_MPU_STATICDEP			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_MPU_INST, 0x0004)
+#define OMAP4_CM_MPU_DYNAMICDEP_OFFSET			0x0008
+#define OMAP4430_CM_MPU_DYNAMICDEP			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_MPU_INST, 0x0008)
+#define OMAP4_CM_MPU_MPU_CLKCTRL_OFFSET			0x0020
+#define OMAP4430_CM_MPU_MPU_CLKCTRL			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_MPU_INST, 0x0020)
+
+/* CM1.TESLA_CM1 register offsets */
+#define OMAP4_CM_TESLA_CLKSTCTRL_OFFSET			0x0000
+#define OMAP4430_CM_TESLA_CLKSTCTRL			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_TESLA_INST, 0x0000)
+#define OMAP4_CM_TESLA_STATICDEP_OFFSET			0x0004
+#define OMAP4430_CM_TESLA_STATICDEP			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_TESLA_INST, 0x0004)
+#define OMAP4_CM_TESLA_DYNAMICDEP_OFFSET		0x0008
+#define OMAP4430_CM_TESLA_DYNAMICDEP			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_TESLA_INST, 0x0008)
+#define OMAP4_CM_TESLA_TESLA_CLKCTRL_OFFSET		0x0020
+#define OMAP4430_CM_TESLA_TESLA_CLKCTRL			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_TESLA_INST, 0x0020)
+
+/* CM1.ABE_CM1 register offsets */
+#define OMAP4_CM1_ABE_CLKSTCTRL_OFFSET			0x0000
+#define OMAP4430_CM1_ABE_CLKSTCTRL			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_ABE_INST, 0x0000)
+#define OMAP4_CM1_ABE_L4ABE_CLKCTRL_OFFSET		0x0020
+#define OMAP4430_CM1_ABE_L4ABE_CLKCTRL			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_ABE_INST, 0x0020)
+#define OMAP4_CM1_ABE_AESS_CLKCTRL_OFFSET		0x0028
+#define OMAP4430_CM1_ABE_AESS_CLKCTRL			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_ABE_INST, 0x0028)
+#define OMAP4_CM1_ABE_PDM_CLKCTRL_OFFSET		0x0030
+#define OMAP4430_CM1_ABE_PDM_CLKCTRL			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_ABE_INST, 0x0030)
+#define OMAP4_CM1_ABE_DMIC_CLKCTRL_OFFSET		0x0038
+#define OMAP4430_CM1_ABE_DMIC_CLKCTRL			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_ABE_INST, 0x0038)
+#define OMAP4_CM1_ABE_MCASP_CLKCTRL_OFFSET		0x0040
+#define OMAP4430_CM1_ABE_MCASP_CLKCTRL			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_ABE_INST, 0x0040)
+#define OMAP4_CM1_ABE_MCBSP1_CLKCTRL_OFFSET		0x0048
+#define OMAP4430_CM1_ABE_MCBSP1_CLKCTRL			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_ABE_INST, 0x0048)
+#define OMAP4_CM1_ABE_MCBSP2_CLKCTRL_OFFSET		0x0050
+#define OMAP4430_CM1_ABE_MCBSP2_CLKCTRL			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_ABE_INST, 0x0050)
+#define OMAP4_CM1_ABE_MCBSP3_CLKCTRL_OFFSET		0x0058
+#define OMAP4430_CM1_ABE_MCBSP3_CLKCTRL			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_ABE_INST, 0x0058)
+#define OMAP4_CM1_ABE_SLIMBUS_CLKCTRL_OFFSET		0x0060
+#define OMAP4430_CM1_ABE_SLIMBUS_CLKCTRL		OMAP44XX_CM1_REGADDR(OMAP4430_CM1_ABE_INST, 0x0060)
+#define OMAP4_CM1_ABE_TIMER5_CLKCTRL_OFFSET		0x0068
+#define OMAP4430_CM1_ABE_TIMER5_CLKCTRL			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_ABE_INST, 0x0068)
+#define OMAP4_CM1_ABE_TIMER6_CLKCTRL_OFFSET		0x0070
+#define OMAP4430_CM1_ABE_TIMER6_CLKCTRL			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_ABE_INST, 0x0070)
+#define OMAP4_CM1_ABE_TIMER7_CLKCTRL_OFFSET		0x0078
+#define OMAP4430_CM1_ABE_TIMER7_CLKCTRL			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_ABE_INST, 0x0078)
+#define OMAP4_CM1_ABE_TIMER8_CLKCTRL_OFFSET		0x0080
+#define OMAP4430_CM1_ABE_TIMER8_CLKCTRL			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_ABE_INST, 0x0080)
+#define OMAP4_CM1_ABE_WDT3_CLKCTRL_OFFSET		0x0088
+#define OMAP4430_CM1_ABE_WDT3_CLKCTRL			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_ABE_INST, 0x0088)
+
+/* CM1.RESTORE_CM1 register offsets */
+#define OMAP4_CM_CLKSEL_CORE_RESTORE_OFFSET		0x0000
+#define OMAP4430_CM_CLKSEL_CORE_RESTORE			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_INST, 0x0000)
+#define OMAP4_CM_DIV_M2_DPLL_CORE_RESTORE_OFFSET	0x0004
+#define OMAP4430_CM_DIV_M2_DPLL_CORE_RESTORE		OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_INST, 0x0004)
+#define OMAP4_CM_DIV_M3_DPLL_CORE_RESTORE_OFFSET	0x0008
+#define OMAP4430_CM_DIV_M3_DPLL_CORE_RESTORE		OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_INST, 0x0008)
+#define OMAP4_CM_DIV_M4_DPLL_CORE_RESTORE_OFFSET	0x000c
+#define OMAP4430_CM_DIV_M4_DPLL_CORE_RESTORE		OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_INST, 0x000c)
+#define OMAP4_CM_DIV_M5_DPLL_CORE_RESTORE_OFFSET	0x0010
+#define OMAP4430_CM_DIV_M5_DPLL_CORE_RESTORE		OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_INST, 0x0010)
+#define OMAP4_CM_DIV_M6_DPLL_CORE_RESTORE_OFFSET	0x0014
+#define OMAP4430_CM_DIV_M6_DPLL_CORE_RESTORE		OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_INST, 0x0014)
+#define OMAP4_CM_DIV_M7_DPLL_CORE_RESTORE_OFFSET	0x0018
+#define OMAP4430_CM_DIV_M7_DPLL_CORE_RESTORE		OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_INST, 0x0018)
+#define OMAP4_CM_CLKSEL_DPLL_CORE_RESTORE_OFFSET	0x001c
+#define OMAP4430_CM_CLKSEL_DPLL_CORE_RESTORE		OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_INST, 0x001c)
+#define OMAP4_CM_SSC_DELTAMSTEP_DPLL_CORE_RESTORE_OFFSET	0x0020
+#define OMAP4430_CM_SSC_DELTAMSTEP_DPLL_CORE_RESTORE	OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_INST, 0x0020)
+#define OMAP4_CM_SSC_INSTFREQDIV_DPLL_CORE_RESTORE_OFFSET	0x0024
+#define OMAP4430_CM_SSC_INSTFREQDIV_DPLL_CORE_RESTORE	OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_INST, 0x0024)
+#define OMAP4_CM_CLKMODE_DPLL_CORE_RESTORE_OFFSET	0x0028
+#define OMAP4430_CM_CLKMODE_DPLL_CORE_RESTORE		OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_INST, 0x0028)
+#define OMAP4_CM_SHADOW_FREQ_CONFIG2_RESTORE_OFFSET	0x002c
+#define OMAP4430_CM_SHADOW_FREQ_CONFIG2_RESTORE		OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_INST, 0x002c)
+#define OMAP4_CM_SHADOW_FREQ_CONFIG1_RESTORE_OFFSET	0x0030
+#define OMAP4430_CM_SHADOW_FREQ_CONFIG1_RESTORE		OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_INST, 0x0030)
+#define OMAP4_CM_AUTOIDLE_DPLL_CORE_RESTORE_OFFSET	0x0034
+#define OMAP4430_CM_AUTOIDLE_DPLL_CORE_RESTORE		OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_INST, 0x0034)
+#define OMAP4_CM_MPU_CLKSTCTRL_RESTORE_OFFSET		0x0038
+#define OMAP4430_CM_MPU_CLKSTCTRL_RESTORE		OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_INST, 0x0038)
+#define OMAP4_CM_CM1_PROFILING_CLKCTRL_RESTORE_OFFSET	0x003c
+#define OMAP4430_CM_CM1_PROFILING_CLKCTRL_RESTORE	OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_INST, 0x003c)
+#define OMAP4_CM_DYN_DEP_PRESCAL_RESTORE_OFFSET		0x0040
+#define OMAP4430_CM_DYN_DEP_PRESCAL_RESTORE		OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_INST, 0x0040)
+
+/* Function prototypes */
+extern u32 omap4_cm1_read_inst_reg(s16 inst, u16 idx);
+extern void omap4_cm1_write_inst_reg(u32 val, s16 inst, u16 idx);
+extern u32 omap4_cm1_rmw_inst_reg_bits(u32 mask, u32 bits, s16 inst, s16 idx);
+
+#endif
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/cm2_44xx.h linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/cm2_44xx.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/cm2_44xx.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/cm2_44xx.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,508 @@
+/*
+ * OMAP44xx CM2 instance offset macros
+ *
+ * Copyright (C) 2009-2010 Texas Instruments, Inc.
+ * Copyright (C) 2009-2010 Nokia Corporation
+ *
+ * Paul Walmsley (paul@pwsan.com)
+ * Rajendra Nayak (rnayak@ti.com)
+ * Benoit Cousson (b-cousson@ti.com)
+ *
+ * This file is automatically generated from the OMAP hardware databases.
+ * We respectfully ask that any modifications to this file be coordinated
+ * with the public linux-omap@vger.kernel.org mailing list and the
+ * authors above to ensure that the autogeneration scripts are kept
+ * up-to-date with the file contents.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * XXX This file needs to be updated to align on one of "OMAP4", "OMAP44XX",
+ *     or "OMAP4430".
+ */
+
+#ifndef __ARCH_ARM_MACH_OMAP2_CM2_44XX_H
+#define __ARCH_ARM_MACH_OMAP2_CM2_44XX_H
+
+/* CM2 base address */
+#define OMAP4430_CM2_BASE		0x4a008000
+
+#define OMAP44XX_CM2_REGADDR(inst, reg)				\
+	OMAP2_L4_IO_ADDRESS(OMAP4430_CM2_BASE + (inst) + (reg))
+
+/* CM2 instances */
+#define OMAP4430_CM2_OCP_SOCKET_INST	0x0000
+#define OMAP4430_CM2_CKGEN_INST		0x0100
+#define OMAP4430_CM2_ALWAYS_ON_INST	0x0600
+#define OMAP4430_CM2_CORE_INST		0x0700
+#define OMAP4430_CM2_IVAHD_INST		0x0f00
+#define OMAP4430_CM2_CAM_INST		0x1000
+#define OMAP4430_CM2_DSS_INST		0x1100
+#define OMAP4430_CM2_GFX_INST		0x1200
+#define OMAP4430_CM2_L3INIT_INST		0x1300
+#define OMAP4430_CM2_L4PER_INST		0x1400
+#define OMAP4430_CM2_CEFUSE_INST		0x1600
+#define OMAP4430_CM2_RESTORE_INST	0x1e00
+#define OMAP4430_CM2_INSTR_INST		0x1f00
+
+/* CM2 clockdomain register offsets (from instance start) */
+#define OMAP4430_CM2_ALWAYS_ON_ALWON_CDOFFS	0x0000
+#define OMAP4430_CM2_CORE_L3_1_CDOFFS		0x0000
+#define OMAP4430_CM2_CORE_L3_2_CDOFFS		0x0100
+#define OMAP4430_CM2_CORE_DUCATI_CDOFFS		0x0200
+#define OMAP4430_CM2_CORE_SDMA_CDOFFS		0x0300
+#define OMAP4430_CM2_CORE_MEMIF_CDOFFS		0x0400
+#define OMAP4430_CM2_CORE_D2D_CDOFFS		0x0500
+#define OMAP4430_CM2_CORE_L4CFG_CDOFFS		0x0600
+#define OMAP4430_CM2_CORE_L3INSTR_CDOFFS	0x0700
+#define OMAP4430_CM2_IVAHD_IVAHD_CDOFFS		0x0000
+#define OMAP4430_CM2_CAM_CAM_CDOFFS		0x0000
+#define OMAP4430_CM2_DSS_DSS_CDOFFS		0x0000
+#define OMAP4430_CM2_GFX_GFX_CDOFFS		0x0000
+#define OMAP4430_CM2_L3INIT_L3INIT_CDOFFS	0x0000
+#define OMAP4430_CM2_L4PER_L4PER_CDOFFS		0x0000
+#define OMAP4430_CM2_L4PER_L4SEC_CDOFFS		0x0180
+#define OMAP4430_CM2_CEFUSE_CEFUSE_CDOFFS	0x0000
+
+
+/* CM2 */
+
+/* CM2.OCP_SOCKET_CM2 register offsets */
+#define OMAP4_REVISION_CM2_OFFSET			0x0000
+#define OMAP4430_REVISION_CM2				OMAP44XX_CM2_REGADDR(OMAP4430_CM2_OCP_SOCKET_INST, 0x0000)
+#define OMAP4_CM_CM2_PROFILING_CLKCTRL_OFFSET		0x0040
+#define OMAP4430_CM_CM2_PROFILING_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_OCP_SOCKET_INST, 0x0040)
+
+/* CM2.CKGEN_CM2 register offsets */
+#define OMAP4_CM_CLKSEL_DUCATI_ISS_ROOT_OFFSET		0x0000
+#define OMAP4430_CM_CLKSEL_DUCATI_ISS_ROOT		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_INST, 0x0000)
+#define OMAP4_CM_CLKSEL_USB_60MHZ_OFFSET		0x0004
+#define OMAP4430_CM_CLKSEL_USB_60MHZ			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_INST, 0x0004)
+#define OMAP4_CM_SCALE_FCLK_OFFSET			0x0008
+#define OMAP4430_CM_SCALE_FCLK				OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_INST, 0x0008)
+#define OMAP4_CM_CORE_DVFS_PERF1_OFFSET			0x0010
+#define OMAP4430_CM_CORE_DVFS_PERF1			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_INST, 0x0010)
+#define OMAP4_CM_CORE_DVFS_PERF2_OFFSET			0x0014
+#define OMAP4430_CM_CORE_DVFS_PERF2			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_INST, 0x0014)
+#define OMAP4_CM_CORE_DVFS_PERF3_OFFSET			0x0018
+#define OMAP4430_CM_CORE_DVFS_PERF3			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_INST, 0x0018)
+#define OMAP4_CM_CORE_DVFS_PERF4_OFFSET			0x001c
+#define OMAP4430_CM_CORE_DVFS_PERF4			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_INST, 0x001c)
+#define OMAP4_CM_CORE_DVFS_CURRENT_OFFSET		0x0024
+#define OMAP4430_CM_CORE_DVFS_CURRENT			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_INST, 0x0024)
+#define OMAP4_CM_IVA_DVFS_PERF_TESLA_OFFSET		0x0028
+#define OMAP4430_CM_IVA_DVFS_PERF_TESLA			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_INST, 0x0028)
+#define OMAP4_CM_IVA_DVFS_PERF_IVAHD_OFFSET		0x002c
+#define OMAP4430_CM_IVA_DVFS_PERF_IVAHD			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_INST, 0x002c)
+#define OMAP4_CM_IVA_DVFS_PERF_ABE_OFFSET		0x0030
+#define OMAP4430_CM_IVA_DVFS_PERF_ABE			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_INST, 0x0030)
+#define OMAP4_CM_IVA_DVFS_CURRENT_OFFSET		0x0038
+#define OMAP4430_CM_IVA_DVFS_CURRENT			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_INST, 0x0038)
+#define OMAP4_CM_CLKMODE_DPLL_PER_OFFSET		0x0040
+#define OMAP4430_CM_CLKMODE_DPLL_PER			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_INST, 0x0040)
+#define OMAP4_CM_IDLEST_DPLL_PER_OFFSET			0x0044
+#define OMAP4430_CM_IDLEST_DPLL_PER			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_INST, 0x0044)
+#define OMAP4_CM_AUTOIDLE_DPLL_PER_OFFSET		0x0048
+#define OMAP4430_CM_AUTOIDLE_DPLL_PER			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_INST, 0x0048)
+#define OMAP4_CM_CLKSEL_DPLL_PER_OFFSET			0x004c
+#define OMAP4430_CM_CLKSEL_DPLL_PER			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_INST, 0x004c)
+#define OMAP4_CM_DIV_M2_DPLL_PER_OFFSET			0x0050
+#define OMAP4430_CM_DIV_M2_DPLL_PER			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_INST, 0x0050)
+#define OMAP4_CM_DIV_M3_DPLL_PER_OFFSET			0x0054
+#define OMAP4430_CM_DIV_M3_DPLL_PER			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_INST, 0x0054)
+#define OMAP4_CM_DIV_M4_DPLL_PER_OFFSET			0x0058
+#define OMAP4430_CM_DIV_M4_DPLL_PER			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_INST, 0x0058)
+#define OMAP4_CM_DIV_M5_DPLL_PER_OFFSET			0x005c
+#define OMAP4430_CM_DIV_M5_DPLL_PER			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_INST, 0x005c)
+#define OMAP4_CM_DIV_M6_DPLL_PER_OFFSET			0x0060
+#define OMAP4430_CM_DIV_M6_DPLL_PER			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_INST, 0x0060)
+#define OMAP4_CM_DIV_M7_DPLL_PER_OFFSET			0x0064
+#define OMAP4430_CM_DIV_M7_DPLL_PER			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_INST, 0x0064)
+#define OMAP4_CM_SSC_DELTAMSTEP_DPLL_PER_OFFSET		0x0068
+#define OMAP4430_CM_SSC_DELTAMSTEP_DPLL_PER		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_INST, 0x0068)
+#define OMAP4_CM_SSC_INSTFREQDIV_DPLL_PER_OFFSET		0x006c
+#define OMAP4430_CM_SSC_INSTFREQDIV_DPLL_PER		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_INST, 0x006c)
+#define OMAP4_CM_CLKMODE_DPLL_USB_OFFSET		0x0080
+#define OMAP4430_CM_CLKMODE_DPLL_USB			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_INST, 0x0080)
+#define OMAP4_CM_IDLEST_DPLL_USB_OFFSET			0x0084
+#define OMAP4430_CM_IDLEST_DPLL_USB			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_INST, 0x0084)
+#define OMAP4_CM_AUTOIDLE_DPLL_USB_OFFSET		0x0088
+#define OMAP4430_CM_AUTOIDLE_DPLL_USB			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_INST, 0x0088)
+#define OMAP4_CM_CLKSEL_DPLL_USB_OFFSET			0x008c
+#define OMAP4430_CM_CLKSEL_DPLL_USB			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_INST, 0x008c)
+#define OMAP4_CM_DIV_M2_DPLL_USB_OFFSET			0x0090
+#define OMAP4430_CM_DIV_M2_DPLL_USB			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_INST, 0x0090)
+#define OMAP4_CM_SSC_DELTAMSTEP_DPLL_USB_OFFSET		0x00a8
+#define OMAP4430_CM_SSC_DELTAMSTEP_DPLL_USB		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_INST, 0x00a8)
+#define OMAP4_CM_SSC_INSTFREQDIV_DPLL_USB_OFFSET		0x00ac
+#define OMAP4430_CM_SSC_INSTFREQDIV_DPLL_USB		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_INST, 0x00ac)
+#define OMAP4_CM_CLKDCOLDO_DPLL_USB_OFFSET		0x00b4
+#define OMAP4430_CM_CLKDCOLDO_DPLL_USB			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_INST, 0x00b4)
+#define OMAP4_CM_CLKMODE_DPLL_UNIPRO_OFFSET		0x00c0
+#define OMAP4430_CM_CLKMODE_DPLL_UNIPRO			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_INST, 0x00c0)
+#define OMAP4_CM_IDLEST_DPLL_UNIPRO_OFFSET		0x00c4
+#define OMAP4430_CM_IDLEST_DPLL_UNIPRO			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_INST, 0x00c4)
+#define OMAP4_CM_AUTOIDLE_DPLL_UNIPRO_OFFSET		0x00c8
+#define OMAP4430_CM_AUTOIDLE_DPLL_UNIPRO		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_INST, 0x00c8)
+#define OMAP4_CM_CLKSEL_DPLL_UNIPRO_OFFSET		0x00cc
+#define OMAP4430_CM_CLKSEL_DPLL_UNIPRO			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_INST, 0x00cc)
+#define OMAP4_CM_DIV_M2_DPLL_UNIPRO_OFFSET		0x00d0
+#define OMAP4430_CM_DIV_M2_DPLL_UNIPRO			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_INST, 0x00d0)
+#define OMAP4_CM_SSC_DELTAMSTEP_DPLL_UNIPRO_OFFSET	0x00e8
+#define OMAP4430_CM_SSC_DELTAMSTEP_DPLL_UNIPRO		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_INST, 0x00e8)
+#define OMAP4_CM_SSC_INSTFREQDIV_DPLL_UNIPRO_OFFSET	0x00ec
+#define OMAP4430_CM_SSC_INSTFREQDIV_DPLL_UNIPRO		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_INST, 0x00ec)
+
+/* CM2.ALWAYS_ON_CM2 register offsets */
+#define OMAP4_CM_ALWON_CLKSTCTRL_OFFSET			0x0000
+#define OMAP4430_CM_ALWON_CLKSTCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_ALWAYS_ON_INST, 0x0000)
+#define OMAP4_CM_ALWON_MDMINTC_CLKCTRL_OFFSET		0x0020
+#define OMAP4430_CM_ALWON_MDMINTC_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_ALWAYS_ON_INST, 0x0020)
+#define OMAP4_CM_ALWON_SR_MPU_CLKCTRL_OFFSET		0x0028
+#define OMAP4430_CM_ALWON_SR_MPU_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_ALWAYS_ON_INST, 0x0028)
+#define OMAP4_CM_ALWON_SR_IVA_CLKCTRL_OFFSET		0x0030
+#define OMAP4430_CM_ALWON_SR_IVA_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_ALWAYS_ON_INST, 0x0030)
+#define OMAP4_CM_ALWON_SR_CORE_CLKCTRL_OFFSET		0x0038
+#define OMAP4430_CM_ALWON_SR_CORE_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_ALWAYS_ON_INST, 0x0038)
+#define OMAP4_CM_ALWON_USBPHY_CLKCTRL_OFFSET		0x0040
+#define OMAP4430_CM_ALWON_USBPHY_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_ALWAYS_ON_INST, 0x0040)
+
+/* CM2.CORE_CM2 register offsets */
+#define OMAP4_CM_L3_1_CLKSTCTRL_OFFSET			0x0000
+#define OMAP4430_CM_L3_1_CLKSTCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_INST, 0x0000)
+#define OMAP4_CM_L3_1_DYNAMICDEP_OFFSET			0x0008
+#define OMAP4430_CM_L3_1_DYNAMICDEP			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_INST, 0x0008)
+#define OMAP4_CM_L3_1_L3_1_CLKCTRL_OFFSET		0x0020
+#define OMAP4430_CM_L3_1_L3_1_CLKCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_INST, 0x0020)
+#define OMAP4_CM_L3_2_CLKSTCTRL_OFFSET			0x0100
+#define OMAP4430_CM_L3_2_CLKSTCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_INST, 0x0100)
+#define OMAP4_CM_L3_2_DYNAMICDEP_OFFSET			0x0108
+#define OMAP4430_CM_L3_2_DYNAMICDEP			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_INST, 0x0108)
+#define OMAP4_CM_L3_2_L3_2_CLKCTRL_OFFSET		0x0120
+#define OMAP4430_CM_L3_2_L3_2_CLKCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_INST, 0x0120)
+#define OMAP4_CM_L3_2_GPMC_CLKCTRL_OFFSET		0x0128
+#define OMAP4430_CM_L3_2_GPMC_CLKCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_INST, 0x0128)
+#define OMAP4_CM_L3_2_OCMC_RAM_CLKCTRL_OFFSET		0x0130
+#define OMAP4430_CM_L3_2_OCMC_RAM_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_INST, 0x0130)
+#define OMAP4_CM_DUCATI_CLKSTCTRL_OFFSET		0x0200
+#define OMAP4430_CM_DUCATI_CLKSTCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_INST, 0x0200)
+#define OMAP4_CM_DUCATI_STATICDEP_OFFSET		0x0204
+#define OMAP4430_CM_DUCATI_STATICDEP			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_INST, 0x0204)
+#define OMAP4_CM_DUCATI_DYNAMICDEP_OFFSET		0x0208
+#define OMAP4430_CM_DUCATI_DYNAMICDEP			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_INST, 0x0208)
+#define OMAP4_CM_DUCATI_DUCATI_CLKCTRL_OFFSET		0x0220
+#define OMAP4430_CM_DUCATI_DUCATI_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_INST, 0x0220)
+#define OMAP4_CM_SDMA_CLKSTCTRL_OFFSET			0x0300
+#define OMAP4430_CM_SDMA_CLKSTCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_INST, 0x0300)
+#define OMAP4_CM_SDMA_STATICDEP_OFFSET			0x0304
+#define OMAP4430_CM_SDMA_STATICDEP			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_INST, 0x0304)
+#define OMAP4_CM_SDMA_DYNAMICDEP_OFFSET			0x0308
+#define OMAP4430_CM_SDMA_DYNAMICDEP			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_INST, 0x0308)
+#define OMAP4_CM_SDMA_SDMA_CLKCTRL_OFFSET		0x0320
+#define OMAP4430_CM_SDMA_SDMA_CLKCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_INST, 0x0320)
+#define OMAP4_CM_MEMIF_CLKSTCTRL_OFFSET			0x0400
+#define OMAP4430_CM_MEMIF_CLKSTCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_INST, 0x0400)
+#define OMAP4_CM_MEMIF_DMM_CLKCTRL_OFFSET		0x0420
+#define OMAP4430_CM_MEMIF_DMM_CLKCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_INST, 0x0420)
+#define OMAP4_CM_MEMIF_EMIF_FW_CLKCTRL_OFFSET		0x0428
+#define OMAP4430_CM_MEMIF_EMIF_FW_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_INST, 0x0428)
+#define OMAP4_CM_MEMIF_EMIF_1_CLKCTRL_OFFSET		0x0430
+#define OMAP4430_CM_MEMIF_EMIF_1_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_INST, 0x0430)
+#define OMAP4_CM_MEMIF_EMIF_2_CLKCTRL_OFFSET		0x0438
+#define OMAP4430_CM_MEMIF_EMIF_2_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_INST, 0x0438)
+#define OMAP4_CM_MEMIF_DLL_CLKCTRL_OFFSET		0x0440
+#define OMAP4430_CM_MEMIF_DLL_CLKCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_INST, 0x0440)
+#define OMAP4_CM_MEMIF_EMIF_H1_CLKCTRL_OFFSET		0x0450
+#define OMAP4430_CM_MEMIF_EMIF_H1_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_INST, 0x0450)
+#define OMAP4_CM_MEMIF_EMIF_H2_CLKCTRL_OFFSET		0x0458
+#define OMAP4430_CM_MEMIF_EMIF_H2_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_INST, 0x0458)
+#define OMAP4_CM_MEMIF_DLL_H_CLKCTRL_OFFSET		0x0460
+#define OMAP4430_CM_MEMIF_DLL_H_CLKCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_INST, 0x0460)
+#define OMAP4_CM_D2D_CLKSTCTRL_OFFSET			0x0500
+#define OMAP4430_CM_D2D_CLKSTCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_INST, 0x0500)
+#define OMAP4_CM_D2D_STATICDEP_OFFSET			0x0504
+#define OMAP4430_CM_D2D_STATICDEP			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_INST, 0x0504)
+#define OMAP4_CM_D2D_DYNAMICDEP_OFFSET			0x0508
+#define OMAP4430_CM_D2D_DYNAMICDEP			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_INST, 0x0508)
+#define OMAP4_CM_D2D_SAD2D_CLKCTRL_OFFSET		0x0520
+#define OMAP4430_CM_D2D_SAD2D_CLKCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_INST, 0x0520)
+#define OMAP4_CM_D2D_INSTEM_ICR_CLKCTRL_OFFSET		0x0528
+#define OMAP4430_CM_D2D_INSTEM_ICR_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_INST, 0x0528)
+#define OMAP4_CM_D2D_SAD2D_FW_CLKCTRL_OFFSET		0x0530
+#define OMAP4430_CM_D2D_SAD2D_FW_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_INST, 0x0530)
+#define OMAP4_CM_L4CFG_CLKSTCTRL_OFFSET			0x0600
+#define OMAP4430_CM_L4CFG_CLKSTCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_INST, 0x0600)
+#define OMAP4_CM_L4CFG_DYNAMICDEP_OFFSET		0x0608
+#define OMAP4430_CM_L4CFG_DYNAMICDEP			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_INST, 0x0608)
+#define OMAP4_CM_L4CFG_L4_CFG_CLKCTRL_OFFSET		0x0620
+#define OMAP4430_CM_L4CFG_L4_CFG_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_INST, 0x0620)
+#define OMAP4_CM_L4CFG_HW_SEM_CLKCTRL_OFFSET		0x0628
+#define OMAP4430_CM_L4CFG_HW_SEM_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_INST, 0x0628)
+#define OMAP4_CM_L4CFG_MAILBOX_CLKCTRL_OFFSET		0x0630
+#define OMAP4430_CM_L4CFG_MAILBOX_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_INST, 0x0630)
+#define OMAP4_CM_L4CFG_SAR_ROM_CLKCTRL_OFFSET		0x0638
+#define OMAP4430_CM_L4CFG_SAR_ROM_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_INST, 0x0638)
+#define OMAP4_CM_L3INSTR_CLKSTCTRL_OFFSET		0x0700
+#define OMAP4430_CM_L3INSTR_CLKSTCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_INST, 0x0700)
+#define OMAP4_CM_L3INSTR_L3_3_CLKCTRL_OFFSET		0x0720
+#define OMAP4430_CM_L3INSTR_L3_3_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_INST, 0x0720)
+#define OMAP4_CM_L3INSTR_L3_INSTR_CLKCTRL_OFFSET	0x0728
+#define OMAP4430_CM_L3INSTR_L3_INSTR_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_INST, 0x0728)
+#define OMAP4_CM_L3INSTR_OCP_WP1_CLKCTRL_OFFSET		0x0740
+#define OMAP4430_CM_L3INSTR_OCP_WP1_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_INST, 0x0740)
+
+/* CM2.IVAHD_CM2 register offsets */
+#define OMAP4_CM_IVAHD_CLKSTCTRL_OFFSET			0x0000
+#define OMAP4430_CM_IVAHD_CLKSTCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_IVAHD_INST, 0x0000)
+#define OMAP4_CM_IVAHD_STATICDEP_OFFSET			0x0004
+#define OMAP4430_CM_IVAHD_STATICDEP			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_IVAHD_INST, 0x0004)
+#define OMAP4_CM_IVAHD_DYNAMICDEP_OFFSET		0x0008
+#define OMAP4430_CM_IVAHD_DYNAMICDEP			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_IVAHD_INST, 0x0008)
+#define OMAP4_CM_IVAHD_IVAHD_CLKCTRL_OFFSET		0x0020
+#define OMAP4430_CM_IVAHD_IVAHD_CLKCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_IVAHD_INST, 0x0020)
+#define OMAP4_CM_IVAHD_SL2_CLKCTRL_OFFSET		0x0028
+#define OMAP4430_CM_IVAHD_SL2_CLKCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_IVAHD_INST, 0x0028)
+
+/* CM2.CAM_CM2 register offsets */
+#define OMAP4_CM_CAM_CLKSTCTRL_OFFSET			0x0000
+#define OMAP4430_CM_CAM_CLKSTCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CAM_INST, 0x0000)
+#define OMAP4_CM_CAM_STATICDEP_OFFSET			0x0004
+#define OMAP4430_CM_CAM_STATICDEP			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CAM_INST, 0x0004)
+#define OMAP4_CM_CAM_DYNAMICDEP_OFFSET			0x0008
+#define OMAP4430_CM_CAM_DYNAMICDEP			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CAM_INST, 0x0008)
+#define OMAP4_CM_CAM_ISS_CLKCTRL_OFFSET			0x0020
+#define OMAP4430_CM_CAM_ISS_CLKCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CAM_INST, 0x0020)
+#define OMAP4_CM_CAM_FDIF_CLKCTRL_OFFSET		0x0028
+#define OMAP4430_CM_CAM_FDIF_CLKCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CAM_INST, 0x0028)
+
+/* CM2.DSS_CM2 register offsets */
+#define OMAP4_CM_DSS_CLKSTCTRL_OFFSET			0x0000
+#define OMAP4430_CM_DSS_CLKSTCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_DSS_INST, 0x0000)
+#define OMAP4_CM_DSS_STATICDEP_OFFSET			0x0004
+#define OMAP4430_CM_DSS_STATICDEP			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_DSS_INST, 0x0004)
+#define OMAP4_CM_DSS_DYNAMICDEP_OFFSET			0x0008
+#define OMAP4430_CM_DSS_DYNAMICDEP			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_DSS_INST, 0x0008)
+#define OMAP4_CM_DSS_DSS_CLKCTRL_OFFSET			0x0020
+#define OMAP4430_CM_DSS_DSS_CLKCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_DSS_INST, 0x0020)
+#define OMAP4_CM_DSS_DEISS_CLKCTRL_OFFSET		0x0028
+#define OMAP4430_CM_DSS_DEISS_CLKCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_DSS_INST, 0x0028)
+
+/* CM2.GFX_CM2 register offsets */
+#define OMAP4_CM_GFX_CLKSTCTRL_OFFSET			0x0000
+#define OMAP4430_CM_GFX_CLKSTCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_GFX_INST, 0x0000)
+#define OMAP4_CM_GFX_STATICDEP_OFFSET			0x0004
+#define OMAP4430_CM_GFX_STATICDEP			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_GFX_INST, 0x0004)
+#define OMAP4_CM_GFX_DYNAMICDEP_OFFSET			0x0008
+#define OMAP4430_CM_GFX_DYNAMICDEP			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_GFX_INST, 0x0008)
+#define OMAP4_CM_GFX_GFX_CLKCTRL_OFFSET			0x0020
+#define OMAP4430_CM_GFX_GFX_CLKCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_GFX_INST, 0x0020)
+
+/* CM2.L3INIT_CM2 register offsets */
+#define OMAP4_CM_L3INIT_CLKSTCTRL_OFFSET		0x0000
+#define OMAP4430_CM_L3INIT_CLKSTCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L3INIT_INST, 0x0000)
+#define OMAP4_CM_L3INIT_STATICDEP_OFFSET		0x0004
+#define OMAP4430_CM_L3INIT_STATICDEP			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L3INIT_INST, 0x0004)
+#define OMAP4_CM_L3INIT_DYNAMICDEP_OFFSET		0x0008
+#define OMAP4430_CM_L3INIT_DYNAMICDEP			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L3INIT_INST, 0x0008)
+#define OMAP4_CM_L3INIT_MMC1_CLKCTRL_OFFSET		0x0028
+#define OMAP4430_CM_L3INIT_MMC1_CLKCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L3INIT_INST, 0x0028)
+#define OMAP4_CM_L3INIT_MMC2_CLKCTRL_OFFSET		0x0030
+#define OMAP4430_CM_L3INIT_MMC2_CLKCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L3INIT_INST, 0x0030)
+#define OMAP4_CM_L3INIT_HSI_CLKCTRL_OFFSET		0x0038
+#define OMAP4430_CM_L3INIT_HSI_CLKCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L3INIT_INST, 0x0038)
+#define OMAP4_CM_L3INIT_UNIPRO1_CLKCTRL_OFFSET		0x0040
+#define OMAP4430_CM_L3INIT_UNIPRO1_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L3INIT_INST, 0x0040)
+#define OMAP4_CM_L3INIT_USB_HOST_CLKCTRL_OFFSET		0x0058
+#define OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L3INIT_INST, 0x0058)
+#define OMAP4_CM_L3INIT_USB_OTG_CLKCTRL_OFFSET		0x0060
+#define OMAP4430_CM_L3INIT_USB_OTG_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L3INIT_INST, 0x0060)
+#define OMAP4_CM_L3INIT_USB_TLL_CLKCTRL_OFFSET		0x0068
+#define OMAP4430_CM_L3INIT_USB_TLL_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L3INIT_INST, 0x0068)
+#define OMAP4_CM_L3INIT_P1500_CLKCTRL_OFFSET		0x0078
+#define OMAP4430_CM_L3INIT_P1500_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L3INIT_INST, 0x0078)
+#define OMAP4_CM_L3INIT_EMAC_CLKCTRL_OFFSET		0x0080
+#define OMAP4430_CM_L3INIT_EMAC_CLKCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L3INIT_INST, 0x0080)
+#define OMAP4_CM_L3INIT_SATA_CLKCTRL_OFFSET		0x0088
+#define OMAP4430_CM_L3INIT_SATA_CLKCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L3INIT_INST, 0x0088)
+#define OMAP4_CM_L3INIT_TPPSS_CLKCTRL_OFFSET		0x0090
+#define OMAP4430_CM_L3INIT_TPPSS_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L3INIT_INST, 0x0090)
+#define OMAP4_CM_L3INIT_PCIESS_CLKCTRL_OFFSET		0x0098
+#define OMAP4430_CM_L3INIT_PCIESS_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L3INIT_INST, 0x0098)
+#define OMAP4_CM_L3INIT_CCPTX_CLKCTRL_OFFSET		0x00a8
+#define OMAP4430_CM_L3INIT_CCPTX_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L3INIT_INST, 0x00a8)
+#define OMAP4_CM_L3INIT_XHPI_CLKCTRL_OFFSET		0x00c0
+#define OMAP4430_CM_L3INIT_XHPI_CLKCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L3INIT_INST, 0x00c0)
+#define OMAP4_CM_L3INIT_MMC6_CLKCTRL_OFFSET		0x00c8
+#define OMAP4430_CM_L3INIT_MMC6_CLKCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L3INIT_INST, 0x00c8)
+#define OMAP4_CM_L3INIT_USB_HOST_FS_CLKCTRL_OFFSET	0x00d0
+#define OMAP4430_CM_L3INIT_USB_HOST_FS_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L3INIT_INST, 0x00d0)
+#define OMAP4_CM_L3INIT_USBPHYOCP2SCP_CLKCTRL_OFFSET	0x00e0
+#define OMAP4430_CM_L3INIT_USBPHYOCP2SCP_CLKCTRL	OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L3INIT_INST, 0x00e0)
+
+/* CM2.L4PER_CM2 register offsets */
+#define OMAP4_CM_L4PER_CLKSTCTRL_OFFSET			0x0000
+#define OMAP4430_CM_L4PER_CLKSTCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_INST, 0x0000)
+#define OMAP4_CM_L4PER_DYNAMICDEP_OFFSET		0x0008
+#define OMAP4430_CM_L4PER_DYNAMICDEP			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_INST, 0x0008)
+#define OMAP4_CM_L4PER_ADC_CLKCTRL_OFFSET		0x0020
+#define OMAP4430_CM_L4PER_ADC_CLKCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_INST, 0x0020)
+#define OMAP4_CM_L4PER_DMTIMER10_CLKCTRL_OFFSET		0x0028
+#define OMAP4430_CM_L4PER_DMTIMER10_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_INST, 0x0028)
+#define OMAP4_CM_L4PER_DMTIMER11_CLKCTRL_OFFSET		0x0030
+#define OMAP4430_CM_L4PER_DMTIMER11_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_INST, 0x0030)
+#define OMAP4_CM_L4PER_DMTIMER2_CLKCTRL_OFFSET		0x0038
+#define OMAP4430_CM_L4PER_DMTIMER2_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_INST, 0x0038)
+#define OMAP4_CM_L4PER_DMTIMER3_CLKCTRL_OFFSET		0x0040
+#define OMAP4430_CM_L4PER_DMTIMER3_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_INST, 0x0040)
+#define OMAP4_CM_L4PER_DMTIMER4_CLKCTRL_OFFSET		0x0048
+#define OMAP4430_CM_L4PER_DMTIMER4_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_INST, 0x0048)
+#define OMAP4_CM_L4PER_DMTIMER9_CLKCTRL_OFFSET		0x0050
+#define OMAP4430_CM_L4PER_DMTIMER9_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_INST, 0x0050)
+#define OMAP4_CM_L4PER_ELM_CLKCTRL_OFFSET		0x0058
+#define OMAP4430_CM_L4PER_ELM_CLKCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_INST, 0x0058)
+#define OMAP4_CM_L4PER_GPIO2_CLKCTRL_OFFSET		0x0060
+#define OMAP4430_CM_L4PER_GPIO2_CLKCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_INST, 0x0060)
+#define OMAP4_CM_L4PER_GPIO3_CLKCTRL_OFFSET		0x0068
+#define OMAP4430_CM_L4PER_GPIO3_CLKCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_INST, 0x0068)
+#define OMAP4_CM_L4PER_GPIO4_CLKCTRL_OFFSET		0x0070
+#define OMAP4430_CM_L4PER_GPIO4_CLKCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_INST, 0x0070)
+#define OMAP4_CM_L4PER_GPIO5_CLKCTRL_OFFSET		0x0078
+#define OMAP4430_CM_L4PER_GPIO5_CLKCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_INST, 0x0078)
+#define OMAP4_CM_L4PER_GPIO6_CLKCTRL_OFFSET		0x0080
+#define OMAP4430_CM_L4PER_GPIO6_CLKCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_INST, 0x0080)
+#define OMAP4_CM_L4PER_HDQ1W_CLKCTRL_OFFSET		0x0088
+#define OMAP4430_CM_L4PER_HDQ1W_CLKCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_INST, 0x0088)
+#define OMAP4_CM_L4PER_HECC1_CLKCTRL_OFFSET		0x0090
+#define OMAP4430_CM_L4PER_HECC1_CLKCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_INST, 0x0090)
+#define OMAP4_CM_L4PER_HECC2_CLKCTRL_OFFSET		0x0098
+#define OMAP4430_CM_L4PER_HECC2_CLKCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_INST, 0x0098)
+#define OMAP4_CM_L4PER_I2C1_CLKCTRL_OFFSET		0x00a0
+#define OMAP4430_CM_L4PER_I2C1_CLKCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_INST, 0x00a0)
+#define OMAP4_CM_L4PER_I2C2_CLKCTRL_OFFSET		0x00a8
+#define OMAP4430_CM_L4PER_I2C2_CLKCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_INST, 0x00a8)
+#define OMAP4_CM_L4PER_I2C3_CLKCTRL_OFFSET		0x00b0
+#define OMAP4430_CM_L4PER_I2C3_CLKCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_INST, 0x00b0)
+#define OMAP4_CM_L4PER_I2C4_CLKCTRL_OFFSET		0x00b8
+#define OMAP4430_CM_L4PER_I2C4_CLKCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_INST, 0x00b8)
+#define OMAP4_CM_L4PER_L4PER_CLKCTRL_OFFSET		0x00c0
+#define OMAP4430_CM_L4PER_L4PER_CLKCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_INST, 0x00c0)
+#define OMAP4_CM_L4PER_MCASP2_CLKCTRL_OFFSET		0x00d0
+#define OMAP4430_CM_L4PER_MCASP2_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_INST, 0x00d0)
+#define OMAP4_CM_L4PER_MCASP3_CLKCTRL_OFFSET		0x00d8
+#define OMAP4430_CM_L4PER_MCASP3_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_INST, 0x00d8)
+#define OMAP4_CM_L4PER_MCBSP4_CLKCTRL_OFFSET		0x00e0
+#define OMAP4430_CM_L4PER_MCBSP4_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_INST, 0x00e0)
+#define OMAP4_CM_L4PER_MGATE_CLKCTRL_OFFSET		0x00e8
+#define OMAP4430_CM_L4PER_MGATE_CLKCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_INST, 0x00e8)
+#define OMAP4_CM_L4PER_MCSPI1_CLKCTRL_OFFSET		0x00f0
+#define OMAP4430_CM_L4PER_MCSPI1_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_INST, 0x00f0)
+#define OMAP4_CM_L4PER_MCSPI2_CLKCTRL_OFFSET		0x00f8
+#define OMAP4430_CM_L4PER_MCSPI2_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_INST, 0x00f8)
+#define OMAP4_CM_L4PER_MCSPI3_CLKCTRL_OFFSET		0x0100
+#define OMAP4430_CM_L4PER_MCSPI3_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_INST, 0x0100)
+#define OMAP4_CM_L4PER_MCSPI4_CLKCTRL_OFFSET		0x0108
+#define OMAP4430_CM_L4PER_MCSPI4_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_INST, 0x0108)
+#define OMAP4_CM_L4PER_MMCSD3_CLKCTRL_OFFSET		0x0120
+#define OMAP4430_CM_L4PER_MMCSD3_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_INST, 0x0120)
+#define OMAP4_CM_L4PER_MMCSD4_CLKCTRL_OFFSET		0x0128
+#define OMAP4430_CM_L4PER_MMCSD4_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_INST, 0x0128)
+#define OMAP4_CM_L4PER_MSPROHG_CLKCTRL_OFFSET		0x0130
+#define OMAP4430_CM_L4PER_MSPROHG_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_INST, 0x0130)
+#define OMAP4_CM_L4PER_SLIMBUS2_CLKCTRL_OFFSET		0x0138
+#define OMAP4430_CM_L4PER_SLIMBUS2_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_INST, 0x0138)
+#define OMAP4_CM_L4PER_UART1_CLKCTRL_OFFSET		0x0140
+#define OMAP4430_CM_L4PER_UART1_CLKCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_INST, 0x0140)
+#define OMAP4_CM_L4PER_UART2_CLKCTRL_OFFSET		0x0148
+#define OMAP4430_CM_L4PER_UART2_CLKCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_INST, 0x0148)
+#define OMAP4_CM_L4PER_UART3_CLKCTRL_OFFSET		0x0150
+#define OMAP4430_CM_L4PER_UART3_CLKCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_INST, 0x0150)
+#define OMAP4_CM_L4PER_UART4_CLKCTRL_OFFSET		0x0158
+#define OMAP4430_CM_L4PER_UART4_CLKCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_INST, 0x0158)
+#define OMAP4_CM_L4PER_MMCSD5_CLKCTRL_OFFSET		0x0160
+#define OMAP4430_CM_L4PER_MMCSD5_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_INST, 0x0160)
+#define OMAP4_CM_L4PER_I2C5_CLKCTRL_OFFSET		0x0168
+#define OMAP4430_CM_L4PER_I2C5_CLKCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_INST, 0x0168)
+#define OMAP4_CM_L4SEC_CLKSTCTRL_OFFSET			0x0180
+#define OMAP4430_CM_L4SEC_CLKSTCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_INST, 0x0180)
+#define OMAP4_CM_L4SEC_STATICDEP_OFFSET			0x0184
+#define OMAP4430_CM_L4SEC_STATICDEP			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_INST, 0x0184)
+#define OMAP4_CM_L4SEC_DYNAMICDEP_OFFSET		0x0188
+#define OMAP4430_CM_L4SEC_DYNAMICDEP			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_INST, 0x0188)
+#define OMAP4_CM_L4SEC_AES1_CLKCTRL_OFFSET		0x01a0
+#define OMAP4430_CM_L4SEC_AES1_CLKCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_INST, 0x01a0)
+#define OMAP4_CM_L4SEC_AES2_CLKCTRL_OFFSET		0x01a8
+#define OMAP4430_CM_L4SEC_AES2_CLKCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_INST, 0x01a8)
+#define OMAP4_CM_L4SEC_DES3DES_CLKCTRL_OFFSET		0x01b0
+#define OMAP4430_CM_L4SEC_DES3DES_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_INST, 0x01b0)
+#define OMAP4_CM_L4SEC_PKAEIP29_CLKCTRL_OFFSET		0x01b8
+#define OMAP4430_CM_L4SEC_PKAEIP29_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_INST, 0x01b8)
+#define OMAP4_CM_L4SEC_RNG_CLKCTRL_OFFSET		0x01c0
+#define OMAP4430_CM_L4SEC_RNG_CLKCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_INST, 0x01c0)
+#define OMAP4_CM_L4SEC_SHA2MD51_CLKCTRL_OFFSET		0x01c8
+#define OMAP4430_CM_L4SEC_SHA2MD51_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_INST, 0x01c8)
+#define OMAP4_CM_L4SEC_CRYPTODMA_CLKCTRL_OFFSET		0x01d8
+#define OMAP4430_CM_L4SEC_CRYPTODMA_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_INST, 0x01d8)
+
+/* CM2.CEFUSE_CM2 register offsets */
+#define OMAP4_CM_CEFUSE_CLKSTCTRL_OFFSET		0x0000
+#define OMAP4430_CM_CEFUSE_CLKSTCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CEFUSE_INST, 0x0000)
+#define OMAP4_CM_CEFUSE_CEFUSE_CLKCTRL_OFFSET		0x0020
+#define OMAP4430_CM_CEFUSE_CEFUSE_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CEFUSE_INST, 0x0020)
+
+/* CM2.RESTORE_CM2 register offsets */
+#define OMAP4_CM_L3_1_CLKSTCTRL_RESTORE_OFFSET		0x0000
+#define OMAP4430_CM_L3_1_CLKSTCTRL_RESTORE		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_INST, 0x0000)
+#define OMAP4_CM_L3_2_CLKSTCTRL_RESTORE_OFFSET		0x0004
+#define OMAP4430_CM_L3_2_CLKSTCTRL_RESTORE		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_INST, 0x0004)
+#define OMAP4_CM_L4CFG_CLKSTCTRL_RESTORE_OFFSET		0x0008
+#define OMAP4430_CM_L4CFG_CLKSTCTRL_RESTORE		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_INST, 0x0008)
+#define OMAP4_CM_MEMIF_CLKSTCTRL_RESTORE_OFFSET		0x000c
+#define OMAP4430_CM_MEMIF_CLKSTCTRL_RESTORE		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_INST, 0x000c)
+#define OMAP4_CM_L4PER_CLKSTCTRL_RESTORE_OFFSET		0x0010
+#define OMAP4430_CM_L4PER_CLKSTCTRL_RESTORE		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_INST, 0x0010)
+#define OMAP4_CM_L3INIT_CLKSTCTRL_RESTORE_OFFSET	0x0014
+#define OMAP4430_CM_L3INIT_CLKSTCTRL_RESTORE		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_INST, 0x0014)
+#define OMAP4_CM_L3INSTR_L3_3_CLKCTRL_RESTORE_OFFSET	0x0018
+#define OMAP4430_CM_L3INSTR_L3_3_CLKCTRL_RESTORE	OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_INST, 0x0018)
+#define OMAP4_CM_L3INSTR_L3_INSTR_CLKCTRL_RESTORE_OFFSET	0x001c
+#define OMAP4430_CM_L3INSTR_L3_INSTR_CLKCTRL_RESTORE	OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_INST, 0x001c)
+#define OMAP4_CM_L3INSTR_OCP_WP1_CLKCTRL_RESTORE_OFFSET	0x0020
+#define OMAP4430_CM_L3INSTR_OCP_WP1_CLKCTRL_RESTORE	OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_INST, 0x0020)
+#define OMAP4_CM_CM2_PROFILING_CLKCTRL_RESTORE_OFFSET	0x0024
+#define OMAP4430_CM_CM2_PROFILING_CLKCTRL_RESTORE	OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_INST, 0x0024)
+#define OMAP4_CM_D2D_STATICDEP_RESTORE_OFFSET		0x0028
+#define OMAP4430_CM_D2D_STATICDEP_RESTORE		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_INST, 0x0028)
+#define OMAP4_CM_L3_1_DYNAMICDEP_RESTORE_OFFSET		0x002c
+#define OMAP4430_CM_L3_1_DYNAMICDEP_RESTORE		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_INST, 0x002c)
+#define OMAP4_CM_L3_2_DYNAMICDEP_RESTORE_OFFSET		0x0030
+#define OMAP4430_CM_L3_2_DYNAMICDEP_RESTORE		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_INST, 0x0030)
+#define OMAP4_CM_D2D_DYNAMICDEP_RESTORE_OFFSET		0x0034
+#define OMAP4430_CM_D2D_DYNAMICDEP_RESTORE		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_INST, 0x0034)
+#define OMAP4_CM_L4CFG_DYNAMICDEP_RESTORE_OFFSET	0x0038
+#define OMAP4430_CM_L4CFG_DYNAMICDEP_RESTORE		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_INST, 0x0038)
+#define OMAP4_CM_L4PER_DYNAMICDEP_RESTORE_OFFSET	0x003c
+#define OMAP4430_CM_L4PER_DYNAMICDEP_RESTORE		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_INST, 0x003c)
+#define OMAP4_CM_L4PER_GPIO2_CLKCTRL_RESTORE_OFFSET	0x0040
+#define OMAP4430_CM_L4PER_GPIO2_CLKCTRL_RESTORE		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_INST, 0x0040)
+#define OMAP4_CM_L4PER_GPIO3_CLKCTRL_RESTORE_OFFSET	0x0044
+#define OMAP4430_CM_L4PER_GPIO3_CLKCTRL_RESTORE		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_INST, 0x0044)
+#define OMAP4_CM_L4PER_GPIO4_CLKCTRL_RESTORE_OFFSET	0x0048
+#define OMAP4430_CM_L4PER_GPIO4_CLKCTRL_RESTORE		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_INST, 0x0048)
+#define OMAP4_CM_L4PER_GPIO5_CLKCTRL_RESTORE_OFFSET	0x004c
+#define OMAP4430_CM_L4PER_GPIO5_CLKCTRL_RESTORE		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_INST, 0x004c)
+#define OMAP4_CM_L4PER_GPIO6_CLKCTRL_RESTORE_OFFSET	0x0050
+#define OMAP4430_CM_L4PER_GPIO6_CLKCTRL_RESTORE		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_INST, 0x0050)
+#define OMAP4_CM_L3INIT_USB_HOST_CLKCTRL_RESTORE_OFFSET	0x0054
+#define OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL_RESTORE	OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_INST, 0x0054)
+#define OMAP4_CM_L3INIT_USB_TLL_CLKCTRL_RESTORE_OFFSET	0x0058
+#define OMAP4430_CM_L3INIT_USB_TLL_CLKCTRL_RESTORE	OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_INST, 0x0058)
+#define OMAP4_CM_SDMA_STATICDEP_RESTORE_OFFSET		0x005c
+#define OMAP4430_CM_SDMA_STATICDEP_RESTORE		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_INST, 0x005c)
+
+/* Function prototypes */
+extern u32 omap4_cm2_read_inst_reg(s16 inst, u16 idx);
+extern void omap4_cm2_write_inst_reg(u32 val, s16 inst, u16 idx);
+extern u32 omap4_cm2_rmw_inst_reg_bits(u32 mask, u32 bits, s16 inst, s16 idx);
+
+#endif
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/cm2xxx_3xxx.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/cm2xxx_3xxx.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/cm2xxx_3xxx.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/cm2xxx_3xxx.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,471 @@
+/*
+ * OMAP2/3 CM module functions
+ *
+ * Copyright (C) 2009 Nokia Corporation
+ * Paul Walmsley
+ *
+ * This program is free software; you can 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/delay.h>
+#include <linux/spinlock.h>
+#include <linux/list.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/io.h>
+
+#include <plat/common.h>
+
+#include "cm.h"
+#include "cm2xxx_3xxx.h"
+#include "cm-regbits-24xx.h"
+#include "cm-regbits-34xx.h"
+
+static const u8 cm_idlest_offs[] = {
+	CM_IDLEST1, CM_IDLEST2, OMAP2430_CM_IDLEST3
+};
+
+u32 omap2_cm_read_mod_reg(s16 module, u16 idx)
+{
+	return __raw_readl(cm_base + module + idx);
+}
+
+void omap2_cm_write_mod_reg(u32 val, s16 module, u16 idx)
+{
+	__raw_writel(val, cm_base + module + idx);
+}
+
+/* Read-modify-write a register in a CM module. Caller must lock */
+u32 omap2_cm_rmw_mod_reg_bits(u32 mask, u32 bits, s16 module, s16 idx)
+{
+	u32 v;
+
+	v = omap2_cm_read_mod_reg(module, idx);
+	v &= ~mask;
+	v |= bits;
+	omap2_cm_write_mod_reg(v, module, idx);
+
+	return v;
+}
+
+u32 omap2_cm_set_mod_reg_bits(u32 bits, s16 module, s16 idx)
+{
+	return omap2_cm_rmw_mod_reg_bits(bits, bits, module, idx);
+}
+
+u32 omap2_cm_clear_mod_reg_bits(u32 bits, s16 module, s16 idx)
+{
+	return omap2_cm_rmw_mod_reg_bits(bits, 0x0, module, idx);
+}
+
+/*
+ *
+ */
+
+static void _write_clktrctrl(u8 c, s16 module, u32 mask)
+{
+	u32 v;
+
+	v = omap2_cm_read_mod_reg(module, OMAP2_CM_CLKSTCTRL);
+	v &= ~mask;
+	v |= c << __ffs(mask);
+	omap2_cm_write_mod_reg(v, module, OMAP2_CM_CLKSTCTRL);
+}
+
+bool omap2_cm_is_clkdm_in_hwsup(s16 module, u32 mask)
+{
+	u32 v;
+	bool ret = 0;
+
+	BUG_ON(!cpu_is_omap24xx() && !cpu_is_omap34xx());
+
+	v = omap2_cm_read_mod_reg(module, OMAP2_CM_CLKSTCTRL);
+	v &= mask;
+	v >>= __ffs(mask);
+
+	if (cpu_is_omap24xx())
+		ret = (v == OMAP24XX_CLKSTCTRL_ENABLE_AUTO) ? 1 : 0;
+	else
+		ret = (v == OMAP34XX_CLKSTCTRL_ENABLE_AUTO) ? 1 : 0;
+
+	return ret;
+}
+
+void omap2xxx_cm_clkdm_enable_hwsup(s16 module, u32 mask)
+{
+	_write_clktrctrl(OMAP24XX_CLKSTCTRL_ENABLE_AUTO, module, mask);
+}
+
+void omap2xxx_cm_clkdm_disable_hwsup(s16 module, u32 mask)
+{
+	_write_clktrctrl(OMAP24XX_CLKSTCTRL_DISABLE_AUTO, module, mask);
+}
+
+void omap3xxx_cm_clkdm_enable_hwsup(s16 module, u32 mask)
+{
+	_write_clktrctrl(OMAP34XX_CLKSTCTRL_ENABLE_AUTO, module, mask);
+}
+
+void omap3xxx_cm_clkdm_disable_hwsup(s16 module, u32 mask)
+{
+	_write_clktrctrl(OMAP34XX_CLKSTCTRL_DISABLE_AUTO, module, mask);
+}
+
+void omap3xxx_cm_clkdm_force_sleep(s16 module, u32 mask)
+{
+	_write_clktrctrl(OMAP34XX_CLKSTCTRL_FORCE_SLEEP, module, mask);
+}
+
+void omap3xxx_cm_clkdm_force_wakeup(s16 module, u32 mask)
+{
+	_write_clktrctrl(OMAP34XX_CLKSTCTRL_FORCE_WAKEUP, module, mask);
+}
+
+
+/*
+ *
+ */
+
+/**
+ * omap2_cm_wait_idlest_ready - wait for a module to leave idle or standby
+ * @prcm_mod: PRCM module offset
+ * @idlest_id: CM_IDLESTx register ID (i.e., x = 1, 2, 3)
+ * @idlest_shift: shift of the bit in the CM_IDLEST* register to check
+ *
+ * XXX document
+ */
+int omap2_cm_wait_module_ready(s16 prcm_mod, u8 idlest_id, u8 idlest_shift)
+{
+	int ena = 0, i = 0;
+	u8 cm_idlest_reg;
+	u32 mask;
+
+	if (!idlest_id || (idlest_id > ARRAY_SIZE(cm_idlest_offs)))
+		return -EINVAL;
+
+	cm_idlest_reg = cm_idlest_offs[idlest_id - 1];
+
+	mask = 1 << idlest_shift;
+
+	if (cpu_is_omap24xx())
+		ena = mask;
+	else if (cpu_is_omap34xx())
+		ena = 0;
+	else
+		BUG();
+
+	omap_test_timeout(((omap2_cm_read_mod_reg(prcm_mod, cm_idlest_reg) & mask) == ena),
+			  MAX_MODULE_READY_TIME, i);
+
+	return (i < MAX_MODULE_READY_TIME) ? 0 : -EBUSY;
+}
+
+/*
+ * Context save/restore code - OMAP3 only
+ */
+#ifdef CONFIG_ARCH_OMAP3
+struct omap3_cm_regs {
+	u32 iva2_cm_clksel1;
+	u32 iva2_cm_clksel2;
+	u32 cm_sysconfig;
+	u32 sgx_cm_clksel;
+	u32 dss_cm_clksel;
+	u32 cam_cm_clksel;
+	u32 per_cm_clksel;
+	u32 emu_cm_clksel;
+	u32 emu_cm_clkstctrl;
+	u32 pll_cm_autoidle2;
+	u32 pll_cm_clksel4;
+	u32 pll_cm_clksel5;
+	u32 pll_cm_clken2;
+	u32 cm_polctrl;
+	u32 iva2_cm_fclken;
+	u32 iva2_cm_clken_pll;
+	u32 core_cm_fclken1;
+	u32 core_cm_fclken3;
+	u32 sgx_cm_fclken;
+	u32 wkup_cm_fclken;
+	u32 dss_cm_fclken;
+	u32 cam_cm_fclken;
+	u32 per_cm_fclken;
+	u32 usbhost_cm_fclken;
+	u32 core_cm_iclken1;
+	u32 core_cm_iclken2;
+	u32 core_cm_iclken3;
+	u32 sgx_cm_iclken;
+	u32 wkup_cm_iclken;
+	u32 dss_cm_iclken;
+	u32 cam_cm_iclken;
+	u32 per_cm_iclken;
+	u32 usbhost_cm_iclken;
+	u32 iva2_cm_autoidle2;
+	u32 mpu_cm_autoidle2;
+	u32 iva2_cm_clkstctrl;
+	u32 mpu_cm_clkstctrl;
+	u32 core_cm_clkstctrl;
+	u32 sgx_cm_clkstctrl;
+	u32 dss_cm_clkstctrl;
+	u32 cam_cm_clkstctrl;
+	u32 per_cm_clkstctrl;
+	u32 neon_cm_clkstctrl;
+	u32 usbhost_cm_clkstctrl;
+	u32 core_cm_autoidle1;
+	u32 core_cm_autoidle2;
+	u32 core_cm_autoidle3;
+	u32 wkup_cm_autoidle;
+	u32 dss_cm_autoidle;
+	u32 cam_cm_autoidle;
+	u32 per_cm_autoidle;
+	u32 usbhost_cm_autoidle;
+	u32 sgx_cm_sleepdep;
+	u32 dss_cm_sleepdep;
+	u32 cam_cm_sleepdep;
+	u32 per_cm_sleepdep;
+	u32 usbhost_cm_sleepdep;
+	u32 cm_clkout_ctrl;
+};
+
+static struct omap3_cm_regs cm_context;
+
+void omap3_cm_save_context(void)
+{
+	cm_context.iva2_cm_clksel1 =
+		omap2_cm_read_mod_reg(OMAP3430_IVA2_MOD, CM_CLKSEL1);
+	cm_context.iva2_cm_clksel2 =
+		omap2_cm_read_mod_reg(OMAP3430_IVA2_MOD, CM_CLKSEL2);
+	cm_context.cm_sysconfig = __raw_readl(OMAP3430_CM_SYSCONFIG);
+	cm_context.sgx_cm_clksel =
+		omap2_cm_read_mod_reg(OMAP3430ES2_SGX_MOD, CM_CLKSEL);
+	cm_context.dss_cm_clksel =
+		omap2_cm_read_mod_reg(OMAP3430_DSS_MOD, CM_CLKSEL);
+	cm_context.cam_cm_clksel =
+		omap2_cm_read_mod_reg(OMAP3430_CAM_MOD, CM_CLKSEL);
+	cm_context.per_cm_clksel =
+		omap2_cm_read_mod_reg(OMAP3430_PER_MOD, CM_CLKSEL);
+	cm_context.emu_cm_clksel =
+		omap2_cm_read_mod_reg(OMAP3430_EMU_MOD, CM_CLKSEL1);
+	cm_context.emu_cm_clkstctrl =
+		omap2_cm_read_mod_reg(OMAP3430_EMU_MOD, OMAP2_CM_CLKSTCTRL);
+	cm_context.pll_cm_autoidle2 =
+		omap2_cm_read_mod_reg(PLL_MOD, CM_AUTOIDLE2);
+	cm_context.pll_cm_clksel4 =
+		omap2_cm_read_mod_reg(PLL_MOD, OMAP3430ES2_CM_CLKSEL4);
+	cm_context.pll_cm_clksel5 =
+		omap2_cm_read_mod_reg(PLL_MOD, OMAP3430ES2_CM_CLKSEL5);
+	cm_context.pll_cm_clken2 =
+		omap2_cm_read_mod_reg(PLL_MOD, OMAP3430ES2_CM_CLKEN2);
+	cm_context.cm_polctrl = __raw_readl(OMAP3430_CM_POLCTRL);
+	cm_context.iva2_cm_fclken =
+		omap2_cm_read_mod_reg(OMAP3430_IVA2_MOD, CM_FCLKEN);
+	cm_context.iva2_cm_clken_pll =
+		omap2_cm_read_mod_reg(OMAP3430_IVA2_MOD, OMAP3430_CM_CLKEN_PLL);
+	cm_context.core_cm_fclken1 =
+		omap2_cm_read_mod_reg(CORE_MOD, CM_FCLKEN1);
+	cm_context.core_cm_fclken3 =
+		omap2_cm_read_mod_reg(CORE_MOD, OMAP3430ES2_CM_FCLKEN3);
+	cm_context.sgx_cm_fclken =
+		omap2_cm_read_mod_reg(OMAP3430ES2_SGX_MOD, CM_FCLKEN);
+	cm_context.wkup_cm_fclken =
+		omap2_cm_read_mod_reg(WKUP_MOD, CM_FCLKEN);
+	cm_context.dss_cm_fclken =
+		omap2_cm_read_mod_reg(OMAP3430_DSS_MOD, CM_FCLKEN);
+	cm_context.cam_cm_fclken =
+		omap2_cm_read_mod_reg(OMAP3430_CAM_MOD, CM_FCLKEN);
+	cm_context.per_cm_fclken =
+		omap2_cm_read_mod_reg(OMAP3430_PER_MOD, CM_FCLKEN);
+	cm_context.usbhost_cm_fclken =
+		omap2_cm_read_mod_reg(OMAP3430ES2_USBHOST_MOD, CM_FCLKEN);
+	cm_context.core_cm_iclken1 =
+		omap2_cm_read_mod_reg(CORE_MOD, CM_ICLKEN1);
+	cm_context.core_cm_iclken2 =
+		omap2_cm_read_mod_reg(CORE_MOD, CM_ICLKEN2);
+	cm_context.core_cm_iclken3 =
+		omap2_cm_read_mod_reg(CORE_MOD, CM_ICLKEN3);
+	cm_context.sgx_cm_iclken =
+		omap2_cm_read_mod_reg(OMAP3430ES2_SGX_MOD, CM_ICLKEN);
+	cm_context.wkup_cm_iclken =
+		omap2_cm_read_mod_reg(WKUP_MOD, CM_ICLKEN);
+	cm_context.dss_cm_iclken =
+		omap2_cm_read_mod_reg(OMAP3430_DSS_MOD, CM_ICLKEN);
+	cm_context.cam_cm_iclken =
+		omap2_cm_read_mod_reg(OMAP3430_CAM_MOD, CM_ICLKEN);
+	cm_context.per_cm_iclken =
+		omap2_cm_read_mod_reg(OMAP3430_PER_MOD, CM_ICLKEN);
+	cm_context.usbhost_cm_iclken =
+		omap2_cm_read_mod_reg(OMAP3430ES2_USBHOST_MOD, CM_ICLKEN);
+	cm_context.iva2_cm_autoidle2 =
+		omap2_cm_read_mod_reg(OMAP3430_IVA2_MOD, CM_AUTOIDLE2);
+	cm_context.mpu_cm_autoidle2 =
+		omap2_cm_read_mod_reg(MPU_MOD, CM_AUTOIDLE2);
+	cm_context.iva2_cm_clkstctrl =
+		omap2_cm_read_mod_reg(OMAP3430_IVA2_MOD, OMAP2_CM_CLKSTCTRL);
+	cm_context.mpu_cm_clkstctrl =
+		omap2_cm_read_mod_reg(MPU_MOD, OMAP2_CM_CLKSTCTRL);
+	cm_context.core_cm_clkstctrl =
+		omap2_cm_read_mod_reg(CORE_MOD, OMAP2_CM_CLKSTCTRL);
+	cm_context.sgx_cm_clkstctrl =
+		omap2_cm_read_mod_reg(OMAP3430ES2_SGX_MOD, OMAP2_CM_CLKSTCTRL);
+	cm_context.dss_cm_clkstctrl =
+		omap2_cm_read_mod_reg(OMAP3430_DSS_MOD, OMAP2_CM_CLKSTCTRL);
+	cm_context.cam_cm_clkstctrl =
+		omap2_cm_read_mod_reg(OMAP3430_CAM_MOD, OMAP2_CM_CLKSTCTRL);
+	cm_context.per_cm_clkstctrl =
+		omap2_cm_read_mod_reg(OMAP3430_PER_MOD, OMAP2_CM_CLKSTCTRL);
+	cm_context.neon_cm_clkstctrl =
+		omap2_cm_read_mod_reg(OMAP3430_NEON_MOD, OMAP2_CM_CLKSTCTRL);
+	cm_context.usbhost_cm_clkstctrl =
+		omap2_cm_read_mod_reg(OMAP3430ES2_USBHOST_MOD,
+				      OMAP2_CM_CLKSTCTRL);
+	cm_context.core_cm_autoidle1 =
+		omap2_cm_read_mod_reg(CORE_MOD, CM_AUTOIDLE1);
+	cm_context.core_cm_autoidle2 =
+		omap2_cm_read_mod_reg(CORE_MOD, CM_AUTOIDLE2);
+	cm_context.core_cm_autoidle3 =
+		omap2_cm_read_mod_reg(CORE_MOD, CM_AUTOIDLE3);
+	cm_context.wkup_cm_autoidle =
+		omap2_cm_read_mod_reg(WKUP_MOD, CM_AUTOIDLE);
+	cm_context.dss_cm_autoidle =
+		omap2_cm_read_mod_reg(OMAP3430_DSS_MOD, CM_AUTOIDLE);
+	cm_context.cam_cm_autoidle =
+		omap2_cm_read_mod_reg(OMAP3430_CAM_MOD, CM_AUTOIDLE);
+	cm_context.per_cm_autoidle =
+		omap2_cm_read_mod_reg(OMAP3430_PER_MOD, CM_AUTOIDLE);
+	cm_context.usbhost_cm_autoidle =
+		omap2_cm_read_mod_reg(OMAP3430ES2_USBHOST_MOD, CM_AUTOIDLE);
+	cm_context.sgx_cm_sleepdep =
+		omap2_cm_read_mod_reg(OMAP3430ES2_SGX_MOD,
+				      OMAP3430_CM_SLEEPDEP);
+	cm_context.dss_cm_sleepdep =
+		omap2_cm_read_mod_reg(OMAP3430_DSS_MOD, OMAP3430_CM_SLEEPDEP);
+	cm_context.cam_cm_sleepdep =
+		omap2_cm_read_mod_reg(OMAP3430_CAM_MOD, OMAP3430_CM_SLEEPDEP);
+	cm_context.per_cm_sleepdep =
+		omap2_cm_read_mod_reg(OMAP3430_PER_MOD, OMAP3430_CM_SLEEPDEP);
+	cm_context.usbhost_cm_sleepdep =
+		omap2_cm_read_mod_reg(OMAP3430ES2_USBHOST_MOD,
+				      OMAP3430_CM_SLEEPDEP);
+	cm_context.cm_clkout_ctrl =
+		omap2_cm_read_mod_reg(OMAP3430_CCR_MOD,
+				      OMAP3_CM_CLKOUT_CTRL_OFFSET);
+}
+
+void omap3_cm_restore_context(void)
+{
+	omap2_cm_write_mod_reg(cm_context.iva2_cm_clksel1, OMAP3430_IVA2_MOD,
+			       CM_CLKSEL1);
+	omap2_cm_write_mod_reg(cm_context.iva2_cm_clksel2, OMAP3430_IVA2_MOD,
+			       CM_CLKSEL2);
+	__raw_writel(cm_context.cm_sysconfig, OMAP3430_CM_SYSCONFIG);
+	omap2_cm_write_mod_reg(cm_context.sgx_cm_clksel, OMAP3430ES2_SGX_MOD,
+			       CM_CLKSEL);
+	omap2_cm_write_mod_reg(cm_context.dss_cm_clksel, OMAP3430_DSS_MOD,
+			       CM_CLKSEL);
+	omap2_cm_write_mod_reg(cm_context.cam_cm_clksel, OMAP3430_CAM_MOD,
+			       CM_CLKSEL);
+	omap2_cm_write_mod_reg(cm_context.per_cm_clksel, OMAP3430_PER_MOD,
+			       CM_CLKSEL);
+	omap2_cm_write_mod_reg(cm_context.emu_cm_clksel, OMAP3430_EMU_MOD,
+			       CM_CLKSEL1);
+	omap2_cm_write_mod_reg(cm_context.emu_cm_clkstctrl, OMAP3430_EMU_MOD,
+			       OMAP2_CM_CLKSTCTRL);
+	omap2_cm_write_mod_reg(cm_context.pll_cm_autoidle2, PLL_MOD,
+			       CM_AUTOIDLE2);
+	omap2_cm_write_mod_reg(cm_context.pll_cm_clksel4, PLL_MOD,
+			       OMAP3430ES2_CM_CLKSEL4);
+	omap2_cm_write_mod_reg(cm_context.pll_cm_clksel5, PLL_MOD,
+			       OMAP3430ES2_CM_CLKSEL5);
+	omap2_cm_write_mod_reg(cm_context.pll_cm_clken2, PLL_MOD,
+			       OMAP3430ES2_CM_CLKEN2);
+	__raw_writel(cm_context.cm_polctrl, OMAP3430_CM_POLCTRL);
+	omap2_cm_write_mod_reg(cm_context.iva2_cm_fclken, OMAP3430_IVA2_MOD,
+			       CM_FCLKEN);
+	omap2_cm_write_mod_reg(cm_context.iva2_cm_clken_pll, OMAP3430_IVA2_MOD,
+			       OMAP3430_CM_CLKEN_PLL);
+	omap2_cm_write_mod_reg(cm_context.core_cm_fclken1, CORE_MOD,
+			       CM_FCLKEN1);
+	omap2_cm_write_mod_reg(cm_context.core_cm_fclken3, CORE_MOD,
+			       OMAP3430ES2_CM_FCLKEN3);
+	omap2_cm_write_mod_reg(cm_context.sgx_cm_fclken, OMAP3430ES2_SGX_MOD,
+			       CM_FCLKEN);
+	omap2_cm_write_mod_reg(cm_context.wkup_cm_fclken, WKUP_MOD, CM_FCLKEN);
+	omap2_cm_write_mod_reg(cm_context.dss_cm_fclken, OMAP3430_DSS_MOD,
+			       CM_FCLKEN);
+	omap2_cm_write_mod_reg(cm_context.cam_cm_fclken, OMAP3430_CAM_MOD,
+			       CM_FCLKEN);
+	omap2_cm_write_mod_reg(cm_context.per_cm_fclken, OMAP3430_PER_MOD,
+			       CM_FCLKEN);
+	omap2_cm_write_mod_reg(cm_context.usbhost_cm_fclken,
+			       OMAP3430ES2_USBHOST_MOD, CM_FCLKEN);
+	omap2_cm_write_mod_reg(cm_context.core_cm_iclken1, CORE_MOD,
+			       CM_ICLKEN1);
+	omap2_cm_write_mod_reg(cm_context.core_cm_iclken2, CORE_MOD,
+			       CM_ICLKEN2);
+	omap2_cm_write_mod_reg(cm_context.core_cm_iclken3, CORE_MOD,
+			       CM_ICLKEN3);
+	omap2_cm_write_mod_reg(cm_context.sgx_cm_iclken, OMAP3430ES2_SGX_MOD,
+			       CM_ICLKEN);
+	omap2_cm_write_mod_reg(cm_context.wkup_cm_iclken, WKUP_MOD, CM_ICLKEN);
+	omap2_cm_write_mod_reg(cm_context.dss_cm_iclken, OMAP3430_DSS_MOD,
+			       CM_ICLKEN);
+	omap2_cm_write_mod_reg(cm_context.cam_cm_iclken, OMAP3430_CAM_MOD,
+			       CM_ICLKEN);
+	omap2_cm_write_mod_reg(cm_context.per_cm_iclken, OMAP3430_PER_MOD,
+			       CM_ICLKEN);
+	omap2_cm_write_mod_reg(cm_context.usbhost_cm_iclken,
+			       OMAP3430ES2_USBHOST_MOD, CM_ICLKEN);
+	omap2_cm_write_mod_reg(cm_context.iva2_cm_autoidle2, OMAP3430_IVA2_MOD,
+			       CM_AUTOIDLE2);
+	omap2_cm_write_mod_reg(cm_context.mpu_cm_autoidle2, MPU_MOD,
+			       CM_AUTOIDLE2);
+	omap2_cm_write_mod_reg(cm_context.iva2_cm_clkstctrl, OMAP3430_IVA2_MOD,
+			       OMAP2_CM_CLKSTCTRL);
+	omap2_cm_write_mod_reg(cm_context.mpu_cm_clkstctrl, MPU_MOD,
+			       OMAP2_CM_CLKSTCTRL);
+	omap2_cm_write_mod_reg(cm_context.core_cm_clkstctrl, CORE_MOD,
+			       OMAP2_CM_CLKSTCTRL);
+	omap2_cm_write_mod_reg(cm_context.sgx_cm_clkstctrl, OMAP3430ES2_SGX_MOD,
+			       OMAP2_CM_CLKSTCTRL);
+	omap2_cm_write_mod_reg(cm_context.dss_cm_clkstctrl, OMAP3430_DSS_MOD,
+			       OMAP2_CM_CLKSTCTRL);
+	omap2_cm_write_mod_reg(cm_context.cam_cm_clkstctrl, OMAP3430_CAM_MOD,
+			       OMAP2_CM_CLKSTCTRL);
+	omap2_cm_write_mod_reg(cm_context.per_cm_clkstctrl, OMAP3430_PER_MOD,
+			       OMAP2_CM_CLKSTCTRL);
+	omap2_cm_write_mod_reg(cm_context.neon_cm_clkstctrl, OMAP3430_NEON_MOD,
+			       OMAP2_CM_CLKSTCTRL);
+	omap2_cm_write_mod_reg(cm_context.usbhost_cm_clkstctrl,
+			       OMAP3430ES2_USBHOST_MOD, OMAP2_CM_CLKSTCTRL);
+	omap2_cm_write_mod_reg(cm_context.core_cm_autoidle1, CORE_MOD,
+			       CM_AUTOIDLE1);
+	omap2_cm_write_mod_reg(cm_context.core_cm_autoidle2, CORE_MOD,
+			       CM_AUTOIDLE2);
+	omap2_cm_write_mod_reg(cm_context.core_cm_autoidle3, CORE_MOD,
+			       CM_AUTOIDLE3);
+	omap2_cm_write_mod_reg(cm_context.wkup_cm_autoidle, WKUP_MOD,
+			       CM_AUTOIDLE);
+	omap2_cm_write_mod_reg(cm_context.dss_cm_autoidle, OMAP3430_DSS_MOD,
+			       CM_AUTOIDLE);
+	omap2_cm_write_mod_reg(cm_context.cam_cm_autoidle, OMAP3430_CAM_MOD,
+			       CM_AUTOIDLE);
+	omap2_cm_write_mod_reg(cm_context.per_cm_autoidle, OMAP3430_PER_MOD,
+			       CM_AUTOIDLE);
+	omap2_cm_write_mod_reg(cm_context.usbhost_cm_autoidle,
+			       OMAP3430ES2_USBHOST_MOD, CM_AUTOIDLE);
+	omap2_cm_write_mod_reg(cm_context.sgx_cm_sleepdep, OMAP3430ES2_SGX_MOD,
+			       OMAP3430_CM_SLEEPDEP);
+	omap2_cm_write_mod_reg(cm_context.dss_cm_sleepdep, OMAP3430_DSS_MOD,
+			       OMAP3430_CM_SLEEPDEP);
+	omap2_cm_write_mod_reg(cm_context.cam_cm_sleepdep, OMAP3430_CAM_MOD,
+			       OMAP3430_CM_SLEEPDEP);
+	omap2_cm_write_mod_reg(cm_context.per_cm_sleepdep, OMAP3430_PER_MOD,
+			       OMAP3430_CM_SLEEPDEP);
+	omap2_cm_write_mod_reg(cm_context.usbhost_cm_sleepdep,
+			       OMAP3430ES2_USBHOST_MOD, OMAP3430_CM_SLEEPDEP);
+	omap2_cm_write_mod_reg(cm_context.cm_clkout_ctrl, OMAP3430_CCR_MOD,
+			       OMAP3_CM_CLKOUT_CTRL_OFFSET);
+}
+#endif
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/cm2xxx_3xxx.h linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/cm2xxx_3xxx.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/cm2xxx_3xxx.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/cm2xxx_3xxx.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,147 @@
+/*
+ * OMAP2/3 Clock Management (CM) register definitions
+ *
+ * Copyright (C) 2007-2009 Texas Instruments, Inc.
+ * Copyright (C) 2007-2010 Nokia Corporation
+ * Paul Walmsley
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * The CM hardware modules on the OMAP2/3 are quite similar to each
+ * other.  The CM modules/instances on OMAP4 are quite different, so
+ * they are handled in a separate file.
+ */
+#ifndef __ARCH_ASM_MACH_OMAP2_CM2XXX_3XXX_H
+#define __ARCH_ASM_MACH_OMAP2_CM2XXX_3XXX_H
+
+#include "prcm-common.h"
+
+#define OMAP2420_CM_REGADDR(module, reg)				\
+			OMAP2_L4_IO_ADDRESS(OMAP2420_CM_BASE + (module) + (reg))
+#define OMAP2430_CM_REGADDR(module, reg)				\
+			OMAP2_L4_IO_ADDRESS(OMAP2430_CM_BASE + (module) + (reg))
+#define OMAP34XX_CM_REGADDR(module, reg)				\
+			OMAP2_L4_IO_ADDRESS(OMAP3430_CM_BASE + (module) + (reg))
+
+
+/*
+ * OMAP3-specific global CM registers
+ * Use cm_{read,write}_reg() with these registers.
+ * These registers appear once per CM module.
+ */
+
+#define OMAP3430_CM_REVISION		OMAP34XX_CM_REGADDR(OCP_MOD, 0x0000)
+#define OMAP3430_CM_SYSCONFIG		OMAP34XX_CM_REGADDR(OCP_MOD, 0x0010)
+#define OMAP3430_CM_POLCTRL		OMAP34XX_CM_REGADDR(OCP_MOD, 0x009c)
+
+#define OMAP3_CM_CLKOUT_CTRL_OFFSET	0x0070
+#define OMAP3430_CM_CLKOUT_CTRL		OMAP_CM_REGADDR(OMAP3430_CCR_MOD, 0x0070)
+
+/*
+ * Module specific CM register offsets from CM_BASE + domain offset
+ * Use cm_{read,write}_mod_reg() with these registers.
+ * These register offsets generally appear in more than one PRCM submodule.
+ */
+
+/* Common between OMAP2 and OMAP3 */
+
+#define CM_FCLKEN					0x0000
+#define CM_FCLKEN1					CM_FCLKEN
+#define CM_CLKEN					CM_FCLKEN
+#define CM_ICLKEN					0x0010
+#define CM_ICLKEN1					CM_ICLKEN
+#define CM_ICLKEN2					0x0014
+#define CM_ICLKEN3					0x0018
+#define CM_IDLEST					0x0020
+#define CM_IDLEST1					CM_IDLEST
+#define CM_IDLEST2					0x0024
+#define CM_AUTOIDLE					0x0030
+#define CM_AUTOIDLE1					CM_AUTOIDLE
+#define CM_AUTOIDLE2					0x0034
+#define CM_AUTOIDLE3					0x0038
+#define CM_CLKSEL					0x0040
+#define CM_CLKSEL1					CM_CLKSEL
+#define CM_CLKSEL2					0x0044
+#define OMAP2_CM_CLKSTCTRL				0x0048
+
+/* OMAP2-specific register offsets */
+
+#define OMAP24XX_CM_FCLKEN2				0x0004
+#define OMAP24XX_CM_ICLKEN4				0x001c
+#define OMAP24XX_CM_AUTOIDLE4				0x003c
+
+#define OMAP2430_CM_IDLEST3				0x0028
+
+/* OMAP3-specific register offsets */
+
+#define OMAP3430_CM_CLKEN_PLL				0x0004
+#define OMAP3430ES2_CM_CLKEN2				0x0004
+#define OMAP3430ES2_CM_FCLKEN3				0x0008
+#define OMAP3430_CM_IDLEST_PLL				CM_IDLEST2
+#define OMAP3430_CM_AUTOIDLE_PLL			CM_AUTOIDLE2
+#define OMAP3430ES2_CM_AUTOIDLE2_PLL			CM_AUTOIDLE2
+#define OMAP3430_CM_CLKSEL1				CM_CLKSEL
+#define OMAP3430_CM_CLKSEL1_PLL				CM_CLKSEL
+#define OMAP3430_CM_CLKSEL2_PLL				CM_CLKSEL2
+#define OMAP3430_CM_SLEEPDEP				CM_CLKSEL2
+#define OMAP3430_CM_CLKSEL3				OMAP2_CM_CLKSTCTRL
+#define OMAP3430_CM_CLKSTST				0x004c
+#define OMAP3430ES2_CM_CLKSEL4				0x004c
+#define OMAP3430ES2_CM_CLKSEL5				0x0050
+#define OMAP3430_CM_CLKSEL2_EMU				0x0050
+#define OMAP3430_CM_CLKSEL3_EMU				0x0054
+
+
+/* CM_IDLEST bit field values to indicate deasserted IdleReq */
+
+#define OMAP24XX_CM_IDLEST_VAL				0
+#define OMAP34XX_CM_IDLEST_VAL				1
+
+
+/* Clock management domain register get/set */
+
+#ifndef __ASSEMBLER__
+
+extern u32 omap2_cm_read_mod_reg(s16 module, u16 idx);
+extern void omap2_cm_write_mod_reg(u32 val, s16 module, u16 idx);
+extern u32 omap2_cm_rmw_mod_reg_bits(u32 mask, u32 bits, s16 module, s16 idx);
+
+extern int omap2_cm_wait_module_ready(s16 prcm_mod, u8 idlest_id,
+				      u8 idlest_shift);
+extern u32 omap2_cm_set_mod_reg_bits(u32 bits, s16 module, s16 idx);
+extern u32 omap2_cm_clear_mod_reg_bits(u32 bits, s16 module, s16 idx);
+
+extern bool omap2_cm_is_clkdm_in_hwsup(s16 module, u32 mask);
+extern void omap2xxx_cm_clkdm_enable_hwsup(s16 module, u32 mask);
+extern void omap2xxx_cm_clkdm_disable_hwsup(s16 module, u32 mask);
+
+extern void omap3xxx_cm_clkdm_enable_hwsup(s16 module, u32 mask);
+extern void omap3xxx_cm_clkdm_disable_hwsup(s16 module, u32 mask);
+extern void omap3xxx_cm_clkdm_force_sleep(s16 module, u32 mask);
+extern void omap3xxx_cm_clkdm_force_wakeup(s16 module, u32 mask);
+
+#endif
+
+/* CM register bits shared between 24XX and 3430 */
+
+/* CM_CLKSEL_GFX */
+#define OMAP_CLKSEL_GFX_SHIFT				0
+#define OMAP_CLKSEL_GFX_MASK				(0x7 << 0)
+
+/* CM_ICLKEN_GFX */
+#define OMAP_EN_GFX_SHIFT				0
+#define OMAP_EN_GFX_MASK				(1 << 0)
+
+/* CM_IDLEST_GFX */
+#define OMAP_ST_GFX_MASK				(1 << 0)
+
+
+/* Function prototypes */
+# ifndef __ASSEMBLER__
+extern void omap3_cm_save_context(void);
+extern void omap3_cm_restore_context(void);
+# endif
+
+#endif
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/cm44xx.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/cm44xx.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/cm44xx.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/cm44xx.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,52 @@
+/*
+ * OMAP4 CM1, CM2 module low-level functions
+ *
+ * Copyright (C) 2010 Nokia Corporation
+ * Paul Walmsley
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * These functions are intended to be used only by the cminst44xx.c file.
+ * XXX Perhaps we should just move them there and make them static.
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/io.h>
+
+#include <plat/common.h>
+
+#include "cm.h"
+#include "cm1_44xx.h"
+#include "cm2_44xx.h"
+#include "cm-regbits-44xx.h"
+
+/* CM1 hardware module low-level functions */
+
+/* Read a register in CM1 */
+u32 omap4_cm1_read_inst_reg(s16 inst, u16 reg)
+{
+	return __raw_readl(OMAP44XX_CM1_REGADDR(inst, reg));
+}
+
+/* Write into a register in CM1 */
+void omap4_cm1_write_inst_reg(u32 val, s16 inst, u16 reg)
+{
+	__raw_writel(val, OMAP44XX_CM1_REGADDR(inst, reg));
+}
+
+/* Read a register in CM2 */
+u32 omap4_cm2_read_inst_reg(s16 inst, u16 reg)
+{
+	return __raw_readl(OMAP44XX_CM2_REGADDR(inst, reg));
+}
+
+/* Write into a register in CM2 */
+void omap4_cm2_write_inst_reg(u32 val, s16 inst, u16 reg)
+{
+	__raw_writel(val, OMAP44XX_CM2_REGADDR(inst, reg));
+}
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/cm44xx.h linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/cm44xx.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/cm44xx.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/cm44xx.h	2011-03-14 21:20:32.000000000 -0400
@@ -1,667 +1,31 @@
 /*
- * OMAP44xx CM1 & CM2 instance offset macros
- *
- * Copyright (C) 2009-2010 Texas Instruments, Inc.
- * Copyright (C) 2009-2010 Nokia Corporation
+ * OMAP4 Clock Management (CM) definitions
  *
- * Paul Walmsley (paul@pwsan.com)
- * Rajendra Nayak (rnayak@ti.com)
- * Benoit Cousson (b-cousson@ti.com)
+ * Copyright (C) 2007-2009 Texas Instruments, Inc.
+ * Copyright (C) 2007-2009 Nokia Corporation
  *
- * This file is automatically generated from the OMAP hardware databases.
- * We respectfully ask that any modifications to this file be coordinated
- * with the public linux-omap@vger.kernel.org mailing list and the
- * authors above to ensure that the autogeneration scripts are kept
- * up-to-date with the file contents.
+ * Written by Paul Walmsley
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
+ *
+ * OMAP4 has two separate CM blocks, CM1 and CM2.  This file contains
+ * macros and function prototypes that are applicable to both.
  */
+#ifndef __ARCH_ASM_MACH_OMAP2_CM44XX_H
+#define __ARCH_ASM_MACH_OMAP2_CM44XX_H
 
-#ifndef __ARCH_ARM_MACH_OMAP2_CM44XX_H
-#define __ARCH_ARM_MACH_OMAP2_CM44XX_H
-
-
-/* CM1 */
-
-/* CM1.OCP_SOCKET_CM1 register offsets */
-#define OMAP4_REVISION_CM1_OFFSET			0x0000
-#define OMAP4430_REVISION_CM1				OMAP44XX_CM1_REGADDR(OMAP4430_CM1_OCP_SOCKET_MOD, 0x0000)
-#define OMAP4_CM_CM1_PROFILING_CLKCTRL_OFFSET		0x0040
-#define OMAP4430_CM_CM1_PROFILING_CLKCTRL		OMAP44XX_CM1_REGADDR(OMAP4430_CM1_OCP_SOCKET_MOD, 0x0040)
-
-/* CM1.CKGEN_CM1 register offsets */
-#define OMAP4_CM_CLKSEL_CORE_OFFSET			0x0000
-#define OMAP4430_CM_CLKSEL_CORE				OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x0000)
-#define OMAP4_CM_CLKSEL_ABE_OFFSET			0x0008
-#define OMAP4430_CM_CLKSEL_ABE				OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x0008)
-#define OMAP4_CM_DLL_CTRL_OFFSET			0x0010
-#define OMAP4430_CM_DLL_CTRL				OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x0010)
-#define OMAP4_CM_CLKMODE_DPLL_CORE_OFFSET		0x0020
-#define OMAP4430_CM_CLKMODE_DPLL_CORE			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x0020)
-#define OMAP4_CM_IDLEST_DPLL_CORE_OFFSET		0x0024
-#define OMAP4430_CM_IDLEST_DPLL_CORE			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x0024)
-#define OMAP4_CM_AUTOIDLE_DPLL_CORE_OFFSET		0x0028
-#define OMAP4430_CM_AUTOIDLE_DPLL_CORE			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x0028)
-#define OMAP4_CM_CLKSEL_DPLL_CORE_OFFSET		0x002c
-#define OMAP4430_CM_CLKSEL_DPLL_CORE			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x002c)
-#define OMAP4_CM_DIV_M2_DPLL_CORE_OFFSET		0x0030
-#define OMAP4430_CM_DIV_M2_DPLL_CORE			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x0030)
-#define OMAP4_CM_DIV_M3_DPLL_CORE_OFFSET		0x0034
-#define OMAP4430_CM_DIV_M3_DPLL_CORE			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x0034)
-#define OMAP4_CM_DIV_M4_DPLL_CORE_OFFSET		0x0038
-#define OMAP4430_CM_DIV_M4_DPLL_CORE			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x0038)
-#define OMAP4_CM_DIV_M5_DPLL_CORE_OFFSET		0x003c
-#define OMAP4430_CM_DIV_M5_DPLL_CORE			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x003c)
-#define OMAP4_CM_DIV_M6_DPLL_CORE_OFFSET		0x0040
-#define OMAP4430_CM_DIV_M6_DPLL_CORE			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x0040)
-#define OMAP4_CM_DIV_M7_DPLL_CORE_OFFSET		0x0044
-#define OMAP4430_CM_DIV_M7_DPLL_CORE			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x0044)
-#define OMAP4_CM_SSC_DELTAMSTEP_DPLL_CORE_OFFSET	0x0048
-#define OMAP4430_CM_SSC_DELTAMSTEP_DPLL_CORE		OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x0048)
-#define OMAP4_CM_SSC_MODFREQDIV_DPLL_CORE_OFFSET	0x004c
-#define OMAP4430_CM_SSC_MODFREQDIV_DPLL_CORE		OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x004c)
-#define OMAP4_CM_EMU_OVERRIDE_DPLL_CORE_OFFSET		0x0050
-#define OMAP4430_CM_EMU_OVERRIDE_DPLL_CORE		OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x0050)
-#define OMAP4_CM_CLKMODE_DPLL_MPU_OFFSET		0x0060
-#define OMAP4430_CM_CLKMODE_DPLL_MPU			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x0060)
-#define OMAP4_CM_IDLEST_DPLL_MPU_OFFSET			0x0064
-#define OMAP4430_CM_IDLEST_DPLL_MPU			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x0064)
-#define OMAP4_CM_AUTOIDLE_DPLL_MPU_OFFSET		0x0068
-#define OMAP4430_CM_AUTOIDLE_DPLL_MPU			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x0068)
-#define OMAP4_CM_CLKSEL_DPLL_MPU_OFFSET			0x006c
-#define OMAP4430_CM_CLKSEL_DPLL_MPU			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x006c)
-#define OMAP4_CM_DIV_M2_DPLL_MPU_OFFSET			0x0070
-#define OMAP4430_CM_DIV_M2_DPLL_MPU			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x0070)
-#define OMAP4_CM_SSC_DELTAMSTEP_DPLL_MPU_OFFSET		0x0088
-#define OMAP4430_CM_SSC_DELTAMSTEP_DPLL_MPU		OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x0088)
-#define OMAP4_CM_SSC_MODFREQDIV_DPLL_MPU_OFFSET		0x008c
-#define OMAP4430_CM_SSC_MODFREQDIV_DPLL_MPU		OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x008c)
-#define OMAP4_CM_BYPCLK_DPLL_MPU_OFFSET			0x009c
-#define OMAP4430_CM_BYPCLK_DPLL_MPU			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x009c)
-#define OMAP4_CM_CLKMODE_DPLL_IVA_OFFSET		0x00a0
-#define OMAP4430_CM_CLKMODE_DPLL_IVA			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x00a0)
-#define OMAP4_CM_IDLEST_DPLL_IVA_OFFSET			0x00a4
-#define OMAP4430_CM_IDLEST_DPLL_IVA			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x00a4)
-#define OMAP4_CM_AUTOIDLE_DPLL_IVA_OFFSET		0x00a8
-#define OMAP4430_CM_AUTOIDLE_DPLL_IVA			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x00a8)
-#define OMAP4_CM_CLKSEL_DPLL_IVA_OFFSET			0x00ac
-#define OMAP4430_CM_CLKSEL_DPLL_IVA			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x00ac)
-#define OMAP4_CM_DIV_M4_DPLL_IVA_OFFSET			0x00b8
-#define OMAP4430_CM_DIV_M4_DPLL_IVA			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x00b8)
-#define OMAP4_CM_DIV_M5_DPLL_IVA_OFFSET			0x00bc
-#define OMAP4430_CM_DIV_M5_DPLL_IVA			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x00bc)
-#define OMAP4_CM_SSC_DELTAMSTEP_DPLL_IVA_OFFSET		0x00c8
-#define OMAP4430_CM_SSC_DELTAMSTEP_DPLL_IVA		OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x00c8)
-#define OMAP4_CM_SSC_MODFREQDIV_DPLL_IVA_OFFSET		0x00cc
-#define OMAP4430_CM_SSC_MODFREQDIV_DPLL_IVA		OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x00cc)
-#define OMAP4_CM_BYPCLK_DPLL_IVA_OFFSET			0x00dc
-#define OMAP4430_CM_BYPCLK_DPLL_IVA			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x00dc)
-#define OMAP4_CM_CLKMODE_DPLL_ABE_OFFSET		0x00e0
-#define OMAP4430_CM_CLKMODE_DPLL_ABE			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x00e0)
-#define OMAP4_CM_IDLEST_DPLL_ABE_OFFSET			0x00e4
-#define OMAP4430_CM_IDLEST_DPLL_ABE			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x00e4)
-#define OMAP4_CM_AUTOIDLE_DPLL_ABE_OFFSET		0x00e8
-#define OMAP4430_CM_AUTOIDLE_DPLL_ABE			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x00e8)
-#define OMAP4_CM_CLKSEL_DPLL_ABE_OFFSET			0x00ec
-#define OMAP4430_CM_CLKSEL_DPLL_ABE			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x00ec)
-#define OMAP4_CM_DIV_M2_DPLL_ABE_OFFSET			0x00f0
-#define OMAP4430_CM_DIV_M2_DPLL_ABE			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x00f0)
-#define OMAP4_CM_DIV_M3_DPLL_ABE_OFFSET			0x00f4
-#define OMAP4430_CM_DIV_M3_DPLL_ABE			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x00f4)
-#define OMAP4_CM_SSC_DELTAMSTEP_DPLL_ABE_OFFSET		0x0108
-#define OMAP4430_CM_SSC_DELTAMSTEP_DPLL_ABE		OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x0108)
-#define OMAP4_CM_SSC_MODFREQDIV_DPLL_ABE_OFFSET		0x010c
-#define OMAP4430_CM_SSC_MODFREQDIV_DPLL_ABE		OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x010c)
-#define OMAP4_CM_CLKMODE_DPLL_DDRPHY_OFFSET		0x0120
-#define OMAP4430_CM_CLKMODE_DPLL_DDRPHY			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x0120)
-#define OMAP4_CM_IDLEST_DPLL_DDRPHY_OFFSET		0x0124
-#define OMAP4430_CM_IDLEST_DPLL_DDRPHY			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x0124)
-#define OMAP4_CM_AUTOIDLE_DPLL_DDRPHY_OFFSET		0x0128
-#define OMAP4430_CM_AUTOIDLE_DPLL_DDRPHY		OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x0128)
-#define OMAP4_CM_CLKSEL_DPLL_DDRPHY_OFFSET		0x012c
-#define OMAP4430_CM_CLKSEL_DPLL_DDRPHY			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x012c)
-#define OMAP4_CM_DIV_M2_DPLL_DDRPHY_OFFSET		0x0130
-#define OMAP4430_CM_DIV_M2_DPLL_DDRPHY			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x0130)
-#define OMAP4_CM_DIV_M4_DPLL_DDRPHY_OFFSET		0x0138
-#define OMAP4430_CM_DIV_M4_DPLL_DDRPHY			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x0138)
-#define OMAP4_CM_DIV_M5_DPLL_DDRPHY_OFFSET		0x013c
-#define OMAP4430_CM_DIV_M5_DPLL_DDRPHY			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x013c)
-#define OMAP4_CM_DIV_M6_DPLL_DDRPHY_OFFSET		0x0140
-#define OMAP4430_CM_DIV_M6_DPLL_DDRPHY			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x0140)
-#define OMAP4_CM_SSC_DELTAMSTEP_DPLL_DDRPHY_OFFSET	0x0148
-#define OMAP4430_CM_SSC_DELTAMSTEP_DPLL_DDRPHY		OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x0148)
-#define OMAP4_CM_SSC_MODFREQDIV_DPLL_DDRPHY_OFFSET	0x014c
-#define OMAP4430_CM_SSC_MODFREQDIV_DPLL_DDRPHY		OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x014c)
-#define OMAP4_CM_SHADOW_FREQ_CONFIG1_OFFSET		0x0160
-#define OMAP4430_CM_SHADOW_FREQ_CONFIG1			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x0160)
-#define OMAP4_CM_SHADOW_FREQ_CONFIG2_OFFSET		0x0164
-#define OMAP4430_CM_SHADOW_FREQ_CONFIG2			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x0164)
-#define OMAP4_CM_DYN_DEP_PRESCAL_OFFSET			0x0170
-#define OMAP4430_CM_DYN_DEP_PRESCAL			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x0170)
-#define OMAP4_CM_RESTORE_ST_OFFSET			0x0180
-#define OMAP4430_CM_RESTORE_ST				OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_MOD, 0x0180)
-
-/* CM1.MPU_CM1 register offsets */
-#define OMAP4_CM_MPU_CLKSTCTRL_OFFSET			0x0000
-#define OMAP4430_CM_MPU_CLKSTCTRL			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_MPU_MOD, 0x0000)
-#define OMAP4_CM_MPU_STATICDEP_OFFSET			0x0004
-#define OMAP4430_CM_MPU_STATICDEP			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_MPU_MOD, 0x0004)
-#define OMAP4_CM_MPU_DYNAMICDEP_OFFSET			0x0008
-#define OMAP4430_CM_MPU_DYNAMICDEP			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_MPU_MOD, 0x0008)
-#define OMAP4_CM_MPU_MPU_CLKCTRL_OFFSET			0x0020
-#define OMAP4430_CM_MPU_MPU_CLKCTRL			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_MPU_MOD, 0x0020)
-
-/* CM1.TESLA_CM1 register offsets */
-#define OMAP4_CM_TESLA_CLKSTCTRL_OFFSET			0x0000
-#define OMAP4430_CM_TESLA_CLKSTCTRL			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_TESLA_MOD, 0x0000)
-#define OMAP4_CM_TESLA_STATICDEP_OFFSET			0x0004
-#define OMAP4430_CM_TESLA_STATICDEP			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_TESLA_MOD, 0x0004)
-#define OMAP4_CM_TESLA_DYNAMICDEP_OFFSET		0x0008
-#define OMAP4430_CM_TESLA_DYNAMICDEP			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_TESLA_MOD, 0x0008)
-#define OMAP4_CM_TESLA_TESLA_CLKCTRL_OFFSET		0x0020
-#define OMAP4430_CM_TESLA_TESLA_CLKCTRL			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_TESLA_MOD, 0x0020)
-
-/* CM1.ABE_CM1 register offsets */
-#define OMAP4_CM1_ABE_CLKSTCTRL_OFFSET			0x0000
-#define OMAP4430_CM1_ABE_CLKSTCTRL			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_ABE_MOD, 0x0000)
-#define OMAP4_CM1_ABE_L4ABE_CLKCTRL_OFFSET		0x0020
-#define OMAP4430_CM1_ABE_L4ABE_CLKCTRL			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_ABE_MOD, 0x0020)
-#define OMAP4_CM1_ABE_AESS_CLKCTRL_OFFSET		0x0028
-#define OMAP4430_CM1_ABE_AESS_CLKCTRL			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_ABE_MOD, 0x0028)
-#define OMAP4_CM1_ABE_PDM_CLKCTRL_OFFSET		0x0030
-#define OMAP4430_CM1_ABE_PDM_CLKCTRL			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_ABE_MOD, 0x0030)
-#define OMAP4_CM1_ABE_DMIC_CLKCTRL_OFFSET		0x0038
-#define OMAP4430_CM1_ABE_DMIC_CLKCTRL			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_ABE_MOD, 0x0038)
-#define OMAP4_CM1_ABE_MCASP_CLKCTRL_OFFSET		0x0040
-#define OMAP4430_CM1_ABE_MCASP_CLKCTRL			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_ABE_MOD, 0x0040)
-#define OMAP4_CM1_ABE_MCBSP1_CLKCTRL_OFFSET		0x0048
-#define OMAP4430_CM1_ABE_MCBSP1_CLKCTRL			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_ABE_MOD, 0x0048)
-#define OMAP4_CM1_ABE_MCBSP2_CLKCTRL_OFFSET		0x0050
-#define OMAP4430_CM1_ABE_MCBSP2_CLKCTRL			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_ABE_MOD, 0x0050)
-#define OMAP4_CM1_ABE_MCBSP3_CLKCTRL_OFFSET		0x0058
-#define OMAP4430_CM1_ABE_MCBSP3_CLKCTRL			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_ABE_MOD, 0x0058)
-#define OMAP4_CM1_ABE_SLIMBUS_CLKCTRL_OFFSET		0x0060
-#define OMAP4430_CM1_ABE_SLIMBUS_CLKCTRL		OMAP44XX_CM1_REGADDR(OMAP4430_CM1_ABE_MOD, 0x0060)
-#define OMAP4_CM1_ABE_TIMER5_CLKCTRL_OFFSET		0x0068
-#define OMAP4430_CM1_ABE_TIMER5_CLKCTRL			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_ABE_MOD, 0x0068)
-#define OMAP4_CM1_ABE_TIMER6_CLKCTRL_OFFSET		0x0070
-#define OMAP4430_CM1_ABE_TIMER6_CLKCTRL			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_ABE_MOD, 0x0070)
-#define OMAP4_CM1_ABE_TIMER7_CLKCTRL_OFFSET		0x0078
-#define OMAP4430_CM1_ABE_TIMER7_CLKCTRL			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_ABE_MOD, 0x0078)
-#define OMAP4_CM1_ABE_TIMER8_CLKCTRL_OFFSET		0x0080
-#define OMAP4430_CM1_ABE_TIMER8_CLKCTRL			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_ABE_MOD, 0x0080)
-#define OMAP4_CM1_ABE_WDT3_CLKCTRL_OFFSET		0x0088
-#define OMAP4430_CM1_ABE_WDT3_CLKCTRL			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_ABE_MOD, 0x0088)
-
-/* CM1.RESTORE_CM1 register offsets */
-#define OMAP4_CM_CLKSEL_CORE_RESTORE_OFFSET		0x0000
-#define OMAP4430_CM_CLKSEL_CORE_RESTORE			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_MOD, 0x0000)
-#define OMAP4_CM_DIV_M2_DPLL_CORE_RESTORE_OFFSET	0x0004
-#define OMAP4430_CM_DIV_M2_DPLL_CORE_RESTORE		OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_MOD, 0x0004)
-#define OMAP4_CM_DIV_M3_DPLL_CORE_RESTORE_OFFSET	0x0008
-#define OMAP4430_CM_DIV_M3_DPLL_CORE_RESTORE		OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_MOD, 0x0008)
-#define OMAP4_CM_DIV_M4_DPLL_CORE_RESTORE_OFFSET	0x000c
-#define OMAP4430_CM_DIV_M4_DPLL_CORE_RESTORE		OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_MOD, 0x000c)
-#define OMAP4_CM_DIV_M5_DPLL_CORE_RESTORE_OFFSET	0x0010
-#define OMAP4430_CM_DIV_M5_DPLL_CORE_RESTORE		OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_MOD, 0x0010)
-#define OMAP4_CM_DIV_M6_DPLL_CORE_RESTORE_OFFSET	0x0014
-#define OMAP4430_CM_DIV_M6_DPLL_CORE_RESTORE		OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_MOD, 0x0014)
-#define OMAP4_CM_DIV_M7_DPLL_CORE_RESTORE_OFFSET	0x0018
-#define OMAP4430_CM_DIV_M7_DPLL_CORE_RESTORE		OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_MOD, 0x0018)
-#define OMAP4_CM_CLKSEL_DPLL_CORE_RESTORE_OFFSET	0x001c
-#define OMAP4430_CM_CLKSEL_DPLL_CORE_RESTORE		OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_MOD, 0x001c)
-#define OMAP4_CM_SSC_DELTAMSTEP_DPLL_CORE_RESTORE_OFFSET	0x0020
-#define OMAP4430_CM_SSC_DELTAMSTEP_DPLL_CORE_RESTORE	OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_MOD, 0x0020)
-#define OMAP4_CM_SSC_MODFREQDIV_DPLL_CORE_RESTORE_OFFSET	0x0024
-#define OMAP4430_CM_SSC_MODFREQDIV_DPLL_CORE_RESTORE	OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_MOD, 0x0024)
-#define OMAP4_CM_CLKMODE_DPLL_CORE_RESTORE_OFFSET	0x0028
-#define OMAP4430_CM_CLKMODE_DPLL_CORE_RESTORE		OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_MOD, 0x0028)
-#define OMAP4_CM_SHADOW_FREQ_CONFIG2_RESTORE_OFFSET	0x002c
-#define OMAP4430_CM_SHADOW_FREQ_CONFIG2_RESTORE		OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_MOD, 0x002c)
-#define OMAP4_CM_SHADOW_FREQ_CONFIG1_RESTORE_OFFSET	0x0030
-#define OMAP4430_CM_SHADOW_FREQ_CONFIG1_RESTORE		OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_MOD, 0x0030)
-#define OMAP4_CM_AUTOIDLE_DPLL_CORE_RESTORE_OFFSET	0x0034
-#define OMAP4430_CM_AUTOIDLE_DPLL_CORE_RESTORE		OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_MOD, 0x0034)
-#define OMAP4_CM_MPU_CLKSTCTRL_RESTORE_OFFSET		0x0038
-#define OMAP4430_CM_MPU_CLKSTCTRL_RESTORE		OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_MOD, 0x0038)
-#define OMAP4_CM_CM1_PROFILING_CLKCTRL_RESTORE_OFFSET	0x003c
-#define OMAP4430_CM_CM1_PROFILING_CLKCTRL_RESTORE	OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_MOD, 0x003c)
-#define OMAP4_CM_DYN_DEP_PRESCAL_RESTORE_OFFSET		0x0040
-#define OMAP4430_CM_DYN_DEP_PRESCAL_RESTORE		OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_MOD, 0x0040)
-
-/* CM2 */
-
-/* CM2.OCP_SOCKET_CM2 register offsets */
-#define OMAP4_REVISION_CM2_OFFSET			0x0000
-#define OMAP4430_REVISION_CM2				OMAP44XX_CM2_REGADDR(OMAP4430_CM2_OCP_SOCKET_MOD, 0x0000)
-#define OMAP4_CM_CM2_PROFILING_CLKCTRL_OFFSET		0x0040
-#define OMAP4430_CM_CM2_PROFILING_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_OCP_SOCKET_MOD, 0x0040)
-
-/* CM2.CKGEN_CM2 register offsets */
-#define OMAP4_CM_CLKSEL_DUCATI_ISS_ROOT_OFFSET		0x0000
-#define OMAP4430_CM_CLKSEL_DUCATI_ISS_ROOT		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_MOD, 0x0000)
-#define OMAP4_CM_CLKSEL_USB_60MHZ_OFFSET		0x0004
-#define OMAP4430_CM_CLKSEL_USB_60MHZ			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_MOD, 0x0004)
-#define OMAP4_CM_SCALE_FCLK_OFFSET			0x0008
-#define OMAP4430_CM_SCALE_FCLK				OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_MOD, 0x0008)
-#define OMAP4_CM_CORE_DVFS_PERF1_OFFSET			0x0010
-#define OMAP4430_CM_CORE_DVFS_PERF1			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_MOD, 0x0010)
-#define OMAP4_CM_CORE_DVFS_PERF2_OFFSET			0x0014
-#define OMAP4430_CM_CORE_DVFS_PERF2			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_MOD, 0x0014)
-#define OMAP4_CM_CORE_DVFS_PERF3_OFFSET			0x0018
-#define OMAP4430_CM_CORE_DVFS_PERF3			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_MOD, 0x0018)
-#define OMAP4_CM_CORE_DVFS_PERF4_OFFSET			0x001c
-#define OMAP4430_CM_CORE_DVFS_PERF4			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_MOD, 0x001c)
-#define OMAP4_CM_CORE_DVFS_CURRENT_OFFSET		0x0024
-#define OMAP4430_CM_CORE_DVFS_CURRENT			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_MOD, 0x0024)
-#define OMAP4_CM_IVA_DVFS_PERF_TESLA_OFFSET		0x0028
-#define OMAP4430_CM_IVA_DVFS_PERF_TESLA			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_MOD, 0x0028)
-#define OMAP4_CM_IVA_DVFS_PERF_IVAHD_OFFSET		0x002c
-#define OMAP4430_CM_IVA_DVFS_PERF_IVAHD			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_MOD, 0x002c)
-#define OMAP4_CM_IVA_DVFS_PERF_ABE_OFFSET		0x0030
-#define OMAP4430_CM_IVA_DVFS_PERF_ABE			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_MOD, 0x0030)
-#define OMAP4_CM_IVA_DVFS_CURRENT_OFFSET		0x0038
-#define OMAP4430_CM_IVA_DVFS_CURRENT			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_MOD, 0x0038)
-#define OMAP4_CM_CLKMODE_DPLL_PER_OFFSET		0x0040
-#define OMAP4430_CM_CLKMODE_DPLL_PER			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_MOD, 0x0040)
-#define OMAP4_CM_IDLEST_DPLL_PER_OFFSET			0x0044
-#define OMAP4430_CM_IDLEST_DPLL_PER			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_MOD, 0x0044)
-#define OMAP4_CM_AUTOIDLE_DPLL_PER_OFFSET		0x0048
-#define OMAP4430_CM_AUTOIDLE_DPLL_PER			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_MOD, 0x0048)
-#define OMAP4_CM_CLKSEL_DPLL_PER_OFFSET			0x004c
-#define OMAP4430_CM_CLKSEL_DPLL_PER			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_MOD, 0x004c)
-#define OMAP4_CM_DIV_M2_DPLL_PER_OFFSET			0x0050
-#define OMAP4430_CM_DIV_M2_DPLL_PER			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_MOD, 0x0050)
-#define OMAP4_CM_DIV_M3_DPLL_PER_OFFSET			0x0054
-#define OMAP4430_CM_DIV_M3_DPLL_PER			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_MOD, 0x0054)
-#define OMAP4_CM_DIV_M4_DPLL_PER_OFFSET			0x0058
-#define OMAP4430_CM_DIV_M4_DPLL_PER			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_MOD, 0x0058)
-#define OMAP4_CM_DIV_M5_DPLL_PER_OFFSET			0x005c
-#define OMAP4430_CM_DIV_M5_DPLL_PER			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_MOD, 0x005c)
-#define OMAP4_CM_DIV_M6_DPLL_PER_OFFSET			0x0060
-#define OMAP4430_CM_DIV_M6_DPLL_PER			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_MOD, 0x0060)
-#define OMAP4_CM_DIV_M7_DPLL_PER_OFFSET			0x0064
-#define OMAP4430_CM_DIV_M7_DPLL_PER			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_MOD, 0x0064)
-#define OMAP4_CM_SSC_DELTAMSTEP_DPLL_PER_OFFSET		0x0068
-#define OMAP4430_CM_SSC_DELTAMSTEP_DPLL_PER		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_MOD, 0x0068)
-#define OMAP4_CM_SSC_MODFREQDIV_DPLL_PER_OFFSET		0x006c
-#define OMAP4430_CM_SSC_MODFREQDIV_DPLL_PER		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_MOD, 0x006c)
-#define OMAP4_CM_CLKMODE_DPLL_USB_OFFSET		0x0080
-#define OMAP4430_CM_CLKMODE_DPLL_USB			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_MOD, 0x0080)
-#define OMAP4_CM_IDLEST_DPLL_USB_OFFSET			0x0084
-#define OMAP4430_CM_IDLEST_DPLL_USB			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_MOD, 0x0084)
-#define OMAP4_CM_AUTOIDLE_DPLL_USB_OFFSET		0x0088
-#define OMAP4430_CM_AUTOIDLE_DPLL_USB			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_MOD, 0x0088)
-#define OMAP4_CM_CLKSEL_DPLL_USB_OFFSET			0x008c
-#define OMAP4430_CM_CLKSEL_DPLL_USB			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_MOD, 0x008c)
-#define OMAP4_CM_DIV_M2_DPLL_USB_OFFSET			0x0090
-#define OMAP4430_CM_DIV_M2_DPLL_USB			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_MOD, 0x0090)
-#define OMAP4_CM_SSC_DELTAMSTEP_DPLL_USB_OFFSET		0x00a8
-#define OMAP4430_CM_SSC_DELTAMSTEP_DPLL_USB		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_MOD, 0x00a8)
-#define OMAP4_CM_SSC_MODFREQDIV_DPLL_USB_OFFSET		0x00ac
-#define OMAP4430_CM_SSC_MODFREQDIV_DPLL_USB		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_MOD, 0x00ac)
-#define OMAP4_CM_CLKDCOLDO_DPLL_USB_OFFSET		0x00b4
-#define OMAP4430_CM_CLKDCOLDO_DPLL_USB			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_MOD, 0x00b4)
-#define OMAP4_CM_CLKMODE_DPLL_UNIPRO_OFFSET		0x00c0
-#define OMAP4430_CM_CLKMODE_DPLL_UNIPRO			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_MOD, 0x00c0)
-#define OMAP4_CM_IDLEST_DPLL_UNIPRO_OFFSET		0x00c4
-#define OMAP4430_CM_IDLEST_DPLL_UNIPRO			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_MOD, 0x00c4)
-#define OMAP4_CM_AUTOIDLE_DPLL_UNIPRO_OFFSET		0x00c8
-#define OMAP4430_CM_AUTOIDLE_DPLL_UNIPRO		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_MOD, 0x00c8)
-#define OMAP4_CM_CLKSEL_DPLL_UNIPRO_OFFSET		0x00cc
-#define OMAP4430_CM_CLKSEL_DPLL_UNIPRO			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_MOD, 0x00cc)
-#define OMAP4_CM_DIV_M2_DPLL_UNIPRO_OFFSET		0x00d0
-#define OMAP4430_CM_DIV_M2_DPLL_UNIPRO			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_MOD, 0x00d0)
-#define OMAP4_CM_SSC_DELTAMSTEP_DPLL_UNIPRO_OFFSET	0x00e8
-#define OMAP4430_CM_SSC_DELTAMSTEP_DPLL_UNIPRO		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_MOD, 0x00e8)
-#define OMAP4_CM_SSC_MODFREQDIV_DPLL_UNIPRO_OFFSET	0x00ec
-#define OMAP4430_CM_SSC_MODFREQDIV_DPLL_UNIPRO		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_MOD, 0x00ec)
-
-/* CM2.ALWAYS_ON_CM2 register offsets */
-#define OMAP4_CM_ALWON_CLKSTCTRL_OFFSET			0x0000
-#define OMAP4430_CM_ALWON_CLKSTCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_ALWAYS_ON_MOD, 0x0000)
-#define OMAP4_CM_ALWON_MDMINTC_CLKCTRL_OFFSET		0x0020
-#define OMAP4430_CM_ALWON_MDMINTC_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_ALWAYS_ON_MOD, 0x0020)
-#define OMAP4_CM_ALWON_SR_MPU_CLKCTRL_OFFSET		0x0028
-#define OMAP4430_CM_ALWON_SR_MPU_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_ALWAYS_ON_MOD, 0x0028)
-#define OMAP4_CM_ALWON_SR_IVA_CLKCTRL_OFFSET		0x0030
-#define OMAP4430_CM_ALWON_SR_IVA_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_ALWAYS_ON_MOD, 0x0030)
-#define OMAP4_CM_ALWON_SR_CORE_CLKCTRL_OFFSET		0x0038
-#define OMAP4430_CM_ALWON_SR_CORE_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_ALWAYS_ON_MOD, 0x0038)
-#define OMAP4_CM_ALWON_USBPHY_CLKCTRL_OFFSET		0x0040
-#define OMAP4430_CM_ALWON_USBPHY_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_ALWAYS_ON_MOD, 0x0040)
-
-/* CM2.CORE_CM2 register offsets */
-#define OMAP4_CM_L3_1_CLKSTCTRL_OFFSET			0x0000
-#define OMAP4430_CM_L3_1_CLKSTCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_MOD, 0x0000)
-#define OMAP4_CM_L3_1_DYNAMICDEP_OFFSET			0x0008
-#define OMAP4430_CM_L3_1_DYNAMICDEP			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_MOD, 0x0008)
-#define OMAP4_CM_L3_1_L3_1_CLKCTRL_OFFSET		0x0020
-#define OMAP4430_CM_L3_1_L3_1_CLKCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_MOD, 0x0020)
-#define OMAP4_CM_L3_2_CLKSTCTRL_OFFSET			0x0100
-#define OMAP4430_CM_L3_2_CLKSTCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_MOD, 0x0100)
-#define OMAP4_CM_L3_2_DYNAMICDEP_OFFSET			0x0108
-#define OMAP4430_CM_L3_2_DYNAMICDEP			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_MOD, 0x0108)
-#define OMAP4_CM_L3_2_L3_2_CLKCTRL_OFFSET		0x0120
-#define OMAP4430_CM_L3_2_L3_2_CLKCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_MOD, 0x0120)
-#define OMAP4_CM_L3_2_GPMC_CLKCTRL_OFFSET		0x0128
-#define OMAP4430_CM_L3_2_GPMC_CLKCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_MOD, 0x0128)
-#define OMAP4_CM_L3_2_OCMC_RAM_CLKCTRL_OFFSET		0x0130
-#define OMAP4430_CM_L3_2_OCMC_RAM_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_MOD, 0x0130)
-#define OMAP4_CM_DUCATI_CLKSTCTRL_OFFSET		0x0200
-#define OMAP4430_CM_DUCATI_CLKSTCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_MOD, 0x0200)
-#define OMAP4_CM_DUCATI_STATICDEP_OFFSET		0x0204
-#define OMAP4430_CM_DUCATI_STATICDEP			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_MOD, 0x0204)
-#define OMAP4_CM_DUCATI_DYNAMICDEP_OFFSET		0x0208
-#define OMAP4430_CM_DUCATI_DYNAMICDEP			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_MOD, 0x0208)
-#define OMAP4_CM_DUCATI_DUCATI_CLKCTRL_OFFSET		0x0220
-#define OMAP4430_CM_DUCATI_DUCATI_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_MOD, 0x0220)
-#define OMAP4_CM_SDMA_CLKSTCTRL_OFFSET			0x0300
-#define OMAP4430_CM_SDMA_CLKSTCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_MOD, 0x0300)
-#define OMAP4_CM_SDMA_STATICDEP_OFFSET			0x0304
-#define OMAP4430_CM_SDMA_STATICDEP			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_MOD, 0x0304)
-#define OMAP4_CM_SDMA_DYNAMICDEP_OFFSET			0x0308
-#define OMAP4430_CM_SDMA_DYNAMICDEP			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_MOD, 0x0308)
-#define OMAP4_CM_SDMA_SDMA_CLKCTRL_OFFSET		0x0320
-#define OMAP4430_CM_SDMA_SDMA_CLKCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_MOD, 0x0320)
-#define OMAP4_CM_MEMIF_CLKSTCTRL_OFFSET			0x0400
-#define OMAP4430_CM_MEMIF_CLKSTCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_MOD, 0x0400)
-#define OMAP4_CM_MEMIF_DMM_CLKCTRL_OFFSET		0x0420
-#define OMAP4430_CM_MEMIF_DMM_CLKCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_MOD, 0x0420)
-#define OMAP4_CM_MEMIF_EMIF_FW_CLKCTRL_OFFSET		0x0428
-#define OMAP4430_CM_MEMIF_EMIF_FW_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_MOD, 0x0428)
-#define OMAP4_CM_MEMIF_EMIF_1_CLKCTRL_OFFSET		0x0430
-#define OMAP4430_CM_MEMIF_EMIF_1_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_MOD, 0x0430)
-#define OMAP4_CM_MEMIF_EMIF_2_CLKCTRL_OFFSET		0x0438
-#define OMAP4430_CM_MEMIF_EMIF_2_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_MOD, 0x0438)
-#define OMAP4_CM_MEMIF_DLL_CLKCTRL_OFFSET		0x0440
-#define OMAP4430_CM_MEMIF_DLL_CLKCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_MOD, 0x0440)
-#define OMAP4_CM_MEMIF_EMIF_H1_CLKCTRL_OFFSET		0x0450
-#define OMAP4430_CM_MEMIF_EMIF_H1_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_MOD, 0x0450)
-#define OMAP4_CM_MEMIF_EMIF_H2_CLKCTRL_OFFSET		0x0458
-#define OMAP4430_CM_MEMIF_EMIF_H2_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_MOD, 0x0458)
-#define OMAP4_CM_MEMIF_DLL_H_CLKCTRL_OFFSET		0x0460
-#define OMAP4430_CM_MEMIF_DLL_H_CLKCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_MOD, 0x0460)
-#define OMAP4_CM_D2D_CLKSTCTRL_OFFSET			0x0500
-#define OMAP4430_CM_D2D_CLKSTCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_MOD, 0x0500)
-#define OMAP4_CM_D2D_STATICDEP_OFFSET			0x0504
-#define OMAP4430_CM_D2D_STATICDEP			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_MOD, 0x0504)
-#define OMAP4_CM_D2D_DYNAMICDEP_OFFSET			0x0508
-#define OMAP4430_CM_D2D_DYNAMICDEP			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_MOD, 0x0508)
-#define OMAP4_CM_D2D_SAD2D_CLKCTRL_OFFSET		0x0520
-#define OMAP4430_CM_D2D_SAD2D_CLKCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_MOD, 0x0520)
-#define OMAP4_CM_D2D_MODEM_ICR_CLKCTRL_OFFSET		0x0528
-#define OMAP4430_CM_D2D_MODEM_ICR_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_MOD, 0x0528)
-#define OMAP4_CM_D2D_SAD2D_FW_CLKCTRL_OFFSET		0x0530
-#define OMAP4430_CM_D2D_SAD2D_FW_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_MOD, 0x0530)
-#define OMAP4_CM_L4CFG_CLKSTCTRL_OFFSET			0x0600
-#define OMAP4430_CM_L4CFG_CLKSTCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_MOD, 0x0600)
-#define OMAP4_CM_L4CFG_DYNAMICDEP_OFFSET		0x0608
-#define OMAP4430_CM_L4CFG_DYNAMICDEP			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_MOD, 0x0608)
-#define OMAP4_CM_L4CFG_L4_CFG_CLKCTRL_OFFSET		0x0620
-#define OMAP4430_CM_L4CFG_L4_CFG_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_MOD, 0x0620)
-#define OMAP4_CM_L4CFG_HW_SEM_CLKCTRL_OFFSET		0x0628
-#define OMAP4430_CM_L4CFG_HW_SEM_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_MOD, 0x0628)
-#define OMAP4_CM_L4CFG_MAILBOX_CLKCTRL_OFFSET		0x0630
-#define OMAP4430_CM_L4CFG_MAILBOX_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_MOD, 0x0630)
-#define OMAP4_CM_L4CFG_SAR_ROM_CLKCTRL_OFFSET		0x0638
-#define OMAP4430_CM_L4CFG_SAR_ROM_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_MOD, 0x0638)
-#define OMAP4_CM_L3INSTR_CLKSTCTRL_OFFSET		0x0700
-#define OMAP4430_CM_L3INSTR_CLKSTCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_MOD, 0x0700)
-#define OMAP4_CM_L3INSTR_L3_3_CLKCTRL_OFFSET		0x0720
-#define OMAP4430_CM_L3INSTR_L3_3_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_MOD, 0x0720)
-#define OMAP4_CM_L3INSTR_L3_INSTR_CLKCTRL_OFFSET	0x0728
-#define OMAP4430_CM_L3INSTR_L3_INSTR_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_MOD, 0x0728)
-#define OMAP4_CM_L3INSTR_OCP_WP1_CLKCTRL_OFFSET		0x0740
-#define OMAP4430_CM_L3INSTR_OCP_WP1_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_MOD, 0x0740)
-
-/* CM2.IVAHD_CM2 register offsets */
-#define OMAP4_CM_IVAHD_CLKSTCTRL_OFFSET			0x0000
-#define OMAP4430_CM_IVAHD_CLKSTCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_IVAHD_MOD, 0x0000)
-#define OMAP4_CM_IVAHD_STATICDEP_OFFSET			0x0004
-#define OMAP4430_CM_IVAHD_STATICDEP			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_IVAHD_MOD, 0x0004)
-#define OMAP4_CM_IVAHD_DYNAMICDEP_OFFSET		0x0008
-#define OMAP4430_CM_IVAHD_DYNAMICDEP			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_IVAHD_MOD, 0x0008)
-#define OMAP4_CM_IVAHD_IVAHD_CLKCTRL_OFFSET		0x0020
-#define OMAP4430_CM_IVAHD_IVAHD_CLKCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_IVAHD_MOD, 0x0020)
-#define OMAP4_CM_IVAHD_SL2_CLKCTRL_OFFSET		0x0028
-#define OMAP4430_CM_IVAHD_SL2_CLKCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_IVAHD_MOD, 0x0028)
-
-/* CM2.CAM_CM2 register offsets */
-#define OMAP4_CM_CAM_CLKSTCTRL_OFFSET			0x0000
-#define OMAP4430_CM_CAM_CLKSTCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CAM_MOD, 0x0000)
-#define OMAP4_CM_CAM_STATICDEP_OFFSET			0x0004
-#define OMAP4430_CM_CAM_STATICDEP			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CAM_MOD, 0x0004)
-#define OMAP4_CM_CAM_DYNAMICDEP_OFFSET			0x0008
-#define OMAP4430_CM_CAM_DYNAMICDEP			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CAM_MOD, 0x0008)
-#define OMAP4_CM_CAM_ISS_CLKCTRL_OFFSET			0x0020
-#define OMAP4430_CM_CAM_ISS_CLKCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CAM_MOD, 0x0020)
-#define OMAP4_CM_CAM_FDIF_CLKCTRL_OFFSET		0x0028
-#define OMAP4430_CM_CAM_FDIF_CLKCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CAM_MOD, 0x0028)
-
-/* CM2.DSS_CM2 register offsets */
-#define OMAP4_CM_DSS_CLKSTCTRL_OFFSET			0x0000
-#define OMAP4430_CM_DSS_CLKSTCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_DSS_MOD, 0x0000)
-#define OMAP4_CM_DSS_STATICDEP_OFFSET			0x0004
-#define OMAP4430_CM_DSS_STATICDEP			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_DSS_MOD, 0x0004)
-#define OMAP4_CM_DSS_DYNAMICDEP_OFFSET			0x0008
-#define OMAP4430_CM_DSS_DYNAMICDEP			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_DSS_MOD, 0x0008)
-#define OMAP4_CM_DSS_DSS_CLKCTRL_OFFSET			0x0020
-#define OMAP4430_CM_DSS_DSS_CLKCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_DSS_MOD, 0x0020)
-#define OMAP4_CM_DSS_DEISS_CLKCTRL_OFFSET		0x0028
-#define OMAP4430_CM_DSS_DEISS_CLKCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_DSS_MOD, 0x0028)
 
-/* CM2.GFX_CM2 register offsets */
-#define OMAP4_CM_GFX_CLKSTCTRL_OFFSET			0x0000
-#define OMAP4430_CM_GFX_CLKSTCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_GFX_MOD, 0x0000)
-#define OMAP4_CM_GFX_STATICDEP_OFFSET			0x0004
-#define OMAP4430_CM_GFX_STATICDEP			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_GFX_MOD, 0x0004)
-#define OMAP4_CM_GFX_DYNAMICDEP_OFFSET			0x0008
-#define OMAP4430_CM_GFX_DYNAMICDEP			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_GFX_MOD, 0x0008)
-#define OMAP4_CM_GFX_GFX_CLKCTRL_OFFSET			0x0020
-#define OMAP4430_CM_GFX_GFX_CLKCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_GFX_MOD, 0x0020)
+#include "prcm-common.h"
+#include "cm.h"
 
-/* CM2.L3INIT_CM2 register offsets */
-#define OMAP4_CM_L3INIT_CLKSTCTRL_OFFSET		0x0000
-#define OMAP4430_CM_L3INIT_CLKSTCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L3INIT_MOD, 0x0000)
-#define OMAP4_CM_L3INIT_STATICDEP_OFFSET		0x0004
-#define OMAP4430_CM_L3INIT_STATICDEP			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L3INIT_MOD, 0x0004)
-#define OMAP4_CM_L3INIT_DYNAMICDEP_OFFSET		0x0008
-#define OMAP4430_CM_L3INIT_DYNAMICDEP			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L3INIT_MOD, 0x0008)
-#define OMAP4_CM_L3INIT_MMC1_CLKCTRL_OFFSET		0x0028
-#define OMAP4430_CM_L3INIT_MMC1_CLKCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L3INIT_MOD, 0x0028)
-#define OMAP4_CM_L3INIT_MMC2_CLKCTRL_OFFSET		0x0030
-#define OMAP4430_CM_L3INIT_MMC2_CLKCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L3INIT_MOD, 0x0030)
-#define OMAP4_CM_L3INIT_HSI_CLKCTRL_OFFSET		0x0038
-#define OMAP4430_CM_L3INIT_HSI_CLKCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L3INIT_MOD, 0x0038)
-#define OMAP4_CM_L3INIT_UNIPRO1_CLKCTRL_OFFSET		0x0040
-#define OMAP4430_CM_L3INIT_UNIPRO1_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L3INIT_MOD, 0x0040)
-#define OMAP4_CM_L3INIT_USB_HOST_CLKCTRL_OFFSET		0x0058
-#define OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L3INIT_MOD, 0x0058)
-#define OMAP4_CM_L3INIT_USB_OTG_CLKCTRL_OFFSET		0x0060
-#define OMAP4430_CM_L3INIT_USB_OTG_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L3INIT_MOD, 0x0060)
-#define OMAP4_CM_L3INIT_USB_TLL_CLKCTRL_OFFSET		0x0068
-#define OMAP4430_CM_L3INIT_USB_TLL_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L3INIT_MOD, 0x0068)
-#define OMAP4_CM_L3INIT_P1500_CLKCTRL_OFFSET		0x0078
-#define OMAP4430_CM_L3INIT_P1500_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L3INIT_MOD, 0x0078)
-#define OMAP4_CM_L3INIT_EMAC_CLKCTRL_OFFSET		0x0080
-#define OMAP4430_CM_L3INIT_EMAC_CLKCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L3INIT_MOD, 0x0080)
-#define OMAP4_CM_L3INIT_SATA_CLKCTRL_OFFSET		0x0088
-#define OMAP4430_CM_L3INIT_SATA_CLKCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L3INIT_MOD, 0x0088)
-#define OMAP4_CM_L3INIT_TPPSS_CLKCTRL_OFFSET		0x0090
-#define OMAP4430_CM_L3INIT_TPPSS_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L3INIT_MOD, 0x0090)
-#define OMAP4_CM_L3INIT_PCIESS_CLKCTRL_OFFSET		0x0098
-#define OMAP4430_CM_L3INIT_PCIESS_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L3INIT_MOD, 0x0098)
-#define OMAP4_CM_L3INIT_CCPTX_CLKCTRL_OFFSET		0x00a8
-#define OMAP4430_CM_L3INIT_CCPTX_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L3INIT_MOD, 0x00a8)
-#define OMAP4_CM_L3INIT_XHPI_CLKCTRL_OFFSET		0x00c0
-#define OMAP4430_CM_L3INIT_XHPI_CLKCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L3INIT_MOD, 0x00c0)
-#define OMAP4_CM_L3INIT_MMC6_CLKCTRL_OFFSET		0x00c8
-#define OMAP4430_CM_L3INIT_MMC6_CLKCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L3INIT_MOD, 0x00c8)
-#define OMAP4_CM_L3INIT_USB_HOST_FS_CLKCTRL_OFFSET	0x00d0
-#define OMAP4430_CM_L3INIT_USB_HOST_FS_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L3INIT_MOD, 0x00d0)
-#define OMAP4_CM_L3INIT_USBPHYOCP2SCP_CLKCTRL_OFFSET	0x00e0
-#define OMAP4430_CM_L3INIT_USBPHYOCP2SCP_CLKCTRL	OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L3INIT_MOD, 0x00e0)
+#define OMAP4_CM_CLKSTCTRL				0x0000
 
-/* CM2.L4PER_CM2 register offsets */
-#define OMAP4_CM_L4PER_CLKSTCTRL_OFFSET			0x0000
-#define OMAP4430_CM_L4PER_CLKSTCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_MOD, 0x0000)
-#define OMAP4_CM_L4PER_DYNAMICDEP_OFFSET		0x0008
-#define OMAP4430_CM_L4PER_DYNAMICDEP			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_MOD, 0x0008)
-#define OMAP4_CM_L4PER_ADC_CLKCTRL_OFFSET		0x0020
-#define OMAP4430_CM_L4PER_ADC_CLKCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_MOD, 0x0020)
-#define OMAP4_CM_L4PER_DMTIMER10_CLKCTRL_OFFSET		0x0028
-#define OMAP4430_CM_L4PER_DMTIMER10_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_MOD, 0x0028)
-#define OMAP4_CM_L4PER_DMTIMER11_CLKCTRL_OFFSET		0x0030
-#define OMAP4430_CM_L4PER_DMTIMER11_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_MOD, 0x0030)
-#define OMAP4_CM_L4PER_DMTIMER2_CLKCTRL_OFFSET		0x0038
-#define OMAP4430_CM_L4PER_DMTIMER2_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_MOD, 0x0038)
-#define OMAP4_CM_L4PER_DMTIMER3_CLKCTRL_OFFSET		0x0040
-#define OMAP4430_CM_L4PER_DMTIMER3_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_MOD, 0x0040)
-#define OMAP4_CM_L4PER_DMTIMER4_CLKCTRL_OFFSET		0x0048
-#define OMAP4430_CM_L4PER_DMTIMER4_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_MOD, 0x0048)
-#define OMAP4_CM_L4PER_DMTIMER9_CLKCTRL_OFFSET		0x0050
-#define OMAP4430_CM_L4PER_DMTIMER9_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_MOD, 0x0050)
-#define OMAP4_CM_L4PER_ELM_CLKCTRL_OFFSET		0x0058
-#define OMAP4430_CM_L4PER_ELM_CLKCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_MOD, 0x0058)
-#define OMAP4_CM_L4PER_GPIO2_CLKCTRL_OFFSET		0x0060
-#define OMAP4430_CM_L4PER_GPIO2_CLKCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_MOD, 0x0060)
-#define OMAP4_CM_L4PER_GPIO3_CLKCTRL_OFFSET		0x0068
-#define OMAP4430_CM_L4PER_GPIO3_CLKCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_MOD, 0x0068)
-#define OMAP4_CM_L4PER_GPIO4_CLKCTRL_OFFSET		0x0070
-#define OMAP4430_CM_L4PER_GPIO4_CLKCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_MOD, 0x0070)
-#define OMAP4_CM_L4PER_GPIO5_CLKCTRL_OFFSET		0x0078
-#define OMAP4430_CM_L4PER_GPIO5_CLKCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_MOD, 0x0078)
-#define OMAP4_CM_L4PER_GPIO6_CLKCTRL_OFFSET		0x0080
-#define OMAP4430_CM_L4PER_GPIO6_CLKCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_MOD, 0x0080)
-#define OMAP4_CM_L4PER_HDQ1W_CLKCTRL_OFFSET		0x0088
-#define OMAP4430_CM_L4PER_HDQ1W_CLKCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_MOD, 0x0088)
-#define OMAP4_CM_L4PER_HECC1_CLKCTRL_OFFSET		0x0090
-#define OMAP4430_CM_L4PER_HECC1_CLKCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_MOD, 0x0090)
-#define OMAP4_CM_L4PER_HECC2_CLKCTRL_OFFSET		0x0098
-#define OMAP4430_CM_L4PER_HECC2_CLKCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_MOD, 0x0098)
-#define OMAP4_CM_L4PER_I2C1_CLKCTRL_OFFSET		0x00a0
-#define OMAP4430_CM_L4PER_I2C1_CLKCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_MOD, 0x00a0)
-#define OMAP4_CM_L4PER_I2C2_CLKCTRL_OFFSET		0x00a8
-#define OMAP4430_CM_L4PER_I2C2_CLKCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_MOD, 0x00a8)
-#define OMAP4_CM_L4PER_I2C3_CLKCTRL_OFFSET		0x00b0
-#define OMAP4430_CM_L4PER_I2C3_CLKCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_MOD, 0x00b0)
-#define OMAP4_CM_L4PER_I2C4_CLKCTRL_OFFSET		0x00b8
-#define OMAP4430_CM_L4PER_I2C4_CLKCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_MOD, 0x00b8)
-#define OMAP4_CM_L4PER_L4PER_CLKCTRL_OFFSET		0x00c0
-#define OMAP4430_CM_L4PER_L4PER_CLKCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_MOD, 0x00c0)
-#define OMAP4_CM_L4PER_MCASP2_CLKCTRL_OFFSET		0x00d0
-#define OMAP4430_CM_L4PER_MCASP2_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_MOD, 0x00d0)
-#define OMAP4_CM_L4PER_MCASP3_CLKCTRL_OFFSET		0x00d8
-#define OMAP4430_CM_L4PER_MCASP3_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_MOD, 0x00d8)
-#define OMAP4_CM_L4PER_MCBSP4_CLKCTRL_OFFSET		0x00e0
-#define OMAP4430_CM_L4PER_MCBSP4_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_MOD, 0x00e0)
-#define OMAP4_CM_L4PER_MGATE_CLKCTRL_OFFSET		0x00e8
-#define OMAP4430_CM_L4PER_MGATE_CLKCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_MOD, 0x00e8)
-#define OMAP4_CM_L4PER_MCSPI1_CLKCTRL_OFFSET		0x00f0
-#define OMAP4430_CM_L4PER_MCSPI1_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_MOD, 0x00f0)
-#define OMAP4_CM_L4PER_MCSPI2_CLKCTRL_OFFSET		0x00f8
-#define OMAP4430_CM_L4PER_MCSPI2_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_MOD, 0x00f8)
-#define OMAP4_CM_L4PER_MCSPI3_CLKCTRL_OFFSET		0x0100
-#define OMAP4430_CM_L4PER_MCSPI3_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_MOD, 0x0100)
-#define OMAP4_CM_L4PER_MCSPI4_CLKCTRL_OFFSET		0x0108
-#define OMAP4430_CM_L4PER_MCSPI4_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_MOD, 0x0108)
-#define OMAP4_CM_L4PER_MMCSD3_CLKCTRL_OFFSET		0x0120
-#define OMAP4430_CM_L4PER_MMCSD3_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_MOD, 0x0120)
-#define OMAP4_CM_L4PER_MMCSD4_CLKCTRL_OFFSET		0x0128
-#define OMAP4430_CM_L4PER_MMCSD4_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_MOD, 0x0128)
-#define OMAP4_CM_L4PER_MSPROHG_CLKCTRL_OFFSET		0x0130
-#define OMAP4430_CM_L4PER_MSPROHG_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_MOD, 0x0130)
-#define OMAP4_CM_L4PER_SLIMBUS2_CLKCTRL_OFFSET		0x0138
-#define OMAP4430_CM_L4PER_SLIMBUS2_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_MOD, 0x0138)
-#define OMAP4_CM_L4PER_UART1_CLKCTRL_OFFSET		0x0140
-#define OMAP4430_CM_L4PER_UART1_CLKCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_MOD, 0x0140)
-#define OMAP4_CM_L4PER_UART2_CLKCTRL_OFFSET		0x0148
-#define OMAP4430_CM_L4PER_UART2_CLKCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_MOD, 0x0148)
-#define OMAP4_CM_L4PER_UART3_CLKCTRL_OFFSET		0x0150
-#define OMAP4430_CM_L4PER_UART3_CLKCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_MOD, 0x0150)
-#define OMAP4_CM_L4PER_UART4_CLKCTRL_OFFSET		0x0158
-#define OMAP4430_CM_L4PER_UART4_CLKCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_MOD, 0x0158)
-#define OMAP4_CM_L4PER_MMCSD5_CLKCTRL_OFFSET		0x0160
-#define OMAP4430_CM_L4PER_MMCSD5_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_MOD, 0x0160)
-#define OMAP4_CM_L4PER_I2C5_CLKCTRL_OFFSET		0x0168
-#define OMAP4430_CM_L4PER_I2C5_CLKCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_MOD, 0x0168)
-#define OMAP4_CM_L4SEC_CLKSTCTRL_OFFSET			0x0180
-#define OMAP4430_CM_L4SEC_CLKSTCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_MOD, 0x0180)
-#define OMAP4_CM_L4SEC_STATICDEP_OFFSET			0x0184
-#define OMAP4430_CM_L4SEC_STATICDEP			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_MOD, 0x0184)
-#define OMAP4_CM_L4SEC_DYNAMICDEP_OFFSET		0x0188
-#define OMAP4430_CM_L4SEC_DYNAMICDEP			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_MOD, 0x0188)
-#define OMAP4_CM_L4SEC_AES1_CLKCTRL_OFFSET		0x01a0
-#define OMAP4430_CM_L4SEC_AES1_CLKCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_MOD, 0x01a0)
-#define OMAP4_CM_L4SEC_AES2_CLKCTRL_OFFSET		0x01a8
-#define OMAP4430_CM_L4SEC_AES2_CLKCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_MOD, 0x01a8)
-#define OMAP4_CM_L4SEC_DES3DES_CLKCTRL_OFFSET		0x01b0
-#define OMAP4430_CM_L4SEC_DES3DES_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_MOD, 0x01b0)
-#define OMAP4_CM_L4SEC_PKAEIP29_CLKCTRL_OFFSET		0x01b8
-#define OMAP4430_CM_L4SEC_PKAEIP29_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_MOD, 0x01b8)
-#define OMAP4_CM_L4SEC_RNG_CLKCTRL_OFFSET		0x01c0
-#define OMAP4430_CM_L4SEC_RNG_CLKCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_MOD, 0x01c0)
-#define OMAP4_CM_L4SEC_SHA2MD51_CLKCTRL_OFFSET		0x01c8
-#define OMAP4430_CM_L4SEC_SHA2MD51_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_MOD, 0x01c8)
-#define OMAP4_CM_L4SEC_CRYPTODMA_CLKCTRL_OFFSET		0x01d8
-#define OMAP4430_CM_L4SEC_CRYPTODMA_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_L4PER_MOD, 0x01d8)
+/* Function prototypes */
+# ifndef __ASSEMBLER__
 
-/* CM2.CEFUSE_CM2 register offsets */
-#define OMAP4_CM_CEFUSE_CLKSTCTRL_OFFSET		0x0000
-#define OMAP4430_CM_CEFUSE_CLKSTCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CEFUSE_MOD, 0x0000)
-#define OMAP4_CM_CEFUSE_CEFUSE_CLKCTRL_OFFSET		0x0020
-#define OMAP4430_CM_CEFUSE_CEFUSE_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CEFUSE_MOD, 0x0020)
+extern int omap4_cm_wait_module_ready(void __iomem *clkctrl_reg);
 
-/* CM2.RESTORE_CM2 register offsets */
-#define OMAP4_CM_L3_1_CLKSTCTRL_RESTORE_OFFSET		0x0000
-#define OMAP4430_CM_L3_1_CLKSTCTRL_RESTORE		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x0000)
-#define OMAP4_CM_L3_2_CLKSTCTRL_RESTORE_OFFSET		0x0004
-#define OMAP4430_CM_L3_2_CLKSTCTRL_RESTORE		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x0004)
-#define OMAP4_CM_L4CFG_CLKSTCTRL_RESTORE_OFFSET		0x0008
-#define OMAP4430_CM_L4CFG_CLKSTCTRL_RESTORE		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x0008)
-#define OMAP4_CM_MEMIF_CLKSTCTRL_RESTORE_OFFSET		0x000c
-#define OMAP4430_CM_MEMIF_CLKSTCTRL_RESTORE		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x000c)
-#define OMAP4_CM_L4PER_CLKSTCTRL_RESTORE_OFFSET		0x0010
-#define OMAP4430_CM_L4PER_CLKSTCTRL_RESTORE		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x0010)
-#define OMAP4_CM_L3INIT_CLKSTCTRL_RESTORE_OFFSET	0x0014
-#define OMAP4430_CM_L3INIT_CLKSTCTRL_RESTORE		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x0014)
-#define OMAP4_CM_L3INSTR_L3_3_CLKCTRL_RESTORE_OFFSET	0x0018
-#define OMAP4430_CM_L3INSTR_L3_3_CLKCTRL_RESTORE	OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x0018)
-#define OMAP4_CM_L3INSTR_L3_INSTR_CLKCTRL_RESTORE_OFFSET	0x001c
-#define OMAP4430_CM_L3INSTR_L3_INSTR_CLKCTRL_RESTORE	OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x001c)
-#define OMAP4_CM_L3INSTR_OCP_WP1_CLKCTRL_RESTORE_OFFSET	0x0020
-#define OMAP4430_CM_L3INSTR_OCP_WP1_CLKCTRL_RESTORE	OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x0020)
-#define OMAP4_CM_CM2_PROFILING_CLKCTRL_RESTORE_OFFSET	0x0024
-#define OMAP4430_CM_CM2_PROFILING_CLKCTRL_RESTORE	OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x0024)
-#define OMAP4_CM_D2D_STATICDEP_RESTORE_OFFSET		0x0028
-#define OMAP4430_CM_D2D_STATICDEP_RESTORE		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x0028)
-#define OMAP4_CM_L3_1_DYNAMICDEP_RESTORE_OFFSET		0x002c
-#define OMAP4430_CM_L3_1_DYNAMICDEP_RESTORE		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x002c)
-#define OMAP4_CM_L3_2_DYNAMICDEP_RESTORE_OFFSET		0x0030
-#define OMAP4430_CM_L3_2_DYNAMICDEP_RESTORE		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x0030)
-#define OMAP4_CM_D2D_DYNAMICDEP_RESTORE_OFFSET		0x0034
-#define OMAP4430_CM_D2D_DYNAMICDEP_RESTORE		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x0034)
-#define OMAP4_CM_L4CFG_DYNAMICDEP_RESTORE_OFFSET	0x0038
-#define OMAP4430_CM_L4CFG_DYNAMICDEP_RESTORE		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x0038)
-#define OMAP4_CM_L4PER_DYNAMICDEP_RESTORE_OFFSET	0x003c
-#define OMAP4430_CM_L4PER_DYNAMICDEP_RESTORE		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x003c)
-#define OMAP4_CM_L4PER_GPIO2_CLKCTRL_RESTORE_OFFSET	0x0040
-#define OMAP4430_CM_L4PER_GPIO2_CLKCTRL_RESTORE		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x0040)
-#define OMAP4_CM_L4PER_GPIO3_CLKCTRL_RESTORE_OFFSET	0x0044
-#define OMAP4430_CM_L4PER_GPIO3_CLKCTRL_RESTORE		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x0044)
-#define OMAP4_CM_L4PER_GPIO4_CLKCTRL_RESTORE_OFFSET	0x0048
-#define OMAP4430_CM_L4PER_GPIO4_CLKCTRL_RESTORE		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x0048)
-#define OMAP4_CM_L4PER_GPIO5_CLKCTRL_RESTORE_OFFSET	0x004c
-#define OMAP4430_CM_L4PER_GPIO5_CLKCTRL_RESTORE		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x004c)
-#define OMAP4_CM_L4PER_GPIO6_CLKCTRL_RESTORE_OFFSET	0x0050
-#define OMAP4430_CM_L4PER_GPIO6_CLKCTRL_RESTORE		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x0050)
-#define OMAP4_CM_L3INIT_USB_HOST_CLKCTRL_RESTORE_OFFSET	0x0054
-#define OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL_RESTORE	OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x0054)
-#define OMAP4_CM_L3INIT_USB_TLL_CLKCTRL_RESTORE_OFFSET	0x0058
-#define OMAP4430_CM_L3INIT_USB_TLL_CLKCTRL_RESTORE	OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x0058)
-#define OMAP4_CM_SDMA_STATICDEP_RESTORE_OFFSET		0x005c
-#define OMAP4430_CM_SDMA_STATICDEP_RESTORE		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x005c)
+# endif
 #endif
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/cm4xxx.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/cm4xxx.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/cm4xxx.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/cm4xxx.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,62 +0,0 @@
-/*
- * OMAP4 CM module functions
- *
- * Copyright (C) 2009 Nokia Corporation
- * Paul Walmsley
- *
- * This program is free software; you can 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/types.h>
-#include <linux/delay.h>
-#include <linux/spinlock.h>
-#include <linux/list.h>
-#include <linux/errno.h>
-#include <linux/err.h>
-#include <linux/io.h>
-
-#include <asm/atomic.h>
-
-#include <plat/common.h>
-
-#include "cm.h"
-#include "cm-regbits-44xx.h"
-
-/**
- * omap4_cm_wait_module_ready - wait for a module to be in 'func' state
- * @clkctrl_reg: CLKCTRL module address
- *
- * Wait for the module IDLEST to be functional. If the idle state is in any
- * the non functional state (trans, idle or disabled), module and thus the
- * sysconfig cannot be accessed and will probably lead to an "imprecise
- * external abort"
- *
- * Module idle state:
- *   0x0 func:     Module is fully functional, including OCP
- *   0x1 trans:    Module is performing transition: wakeup, or sleep, or sleep
- *                 abortion
- *   0x2 idle:     Module is in Idle mode (only OCP part). It is functional if
- *                 using separate functional clock
- *   0x3 disabled: Module is disabled and cannot be accessed
- *
- */
-int omap4_cm_wait_module_ready(void __iomem *clkctrl_reg)
-{
-	int i = 0;
-
-	if (!clkctrl_reg)
-		return 0;
-
-	omap_test_timeout((
-		((__raw_readl(clkctrl_reg) & OMAP4430_IDLEST_MASK) == 0) ||
-		 (((__raw_readl(clkctrl_reg) & OMAP4430_IDLEST_MASK) >>
-		  OMAP4430_IDLEST_SHIFT) == 0x2)),
-		MAX_MODULE_READY_TIME, i);
-
-	return (i < MAX_MODULE_READY_TIME) ? 0 : -EBUSY;
-}
-
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/cm.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/cm.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/cm.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/cm.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,68 +0,0 @@
-/*
- * OMAP2/3 CM module functions
- *
- * Copyright (C) 2009 Nokia Corporation
- * Paul Walmsley
- *
- * This program is free software; you can 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/types.h>
-#include <linux/delay.h>
-#include <linux/spinlock.h>
-#include <linux/list.h>
-#include <linux/errno.h>
-#include <linux/err.h>
-#include <linux/io.h>
-
-#include <asm/atomic.h>
-
-#include <plat/common.h>
-
-#include "cm.h"
-#include "cm-regbits-24xx.h"
-#include "cm-regbits-34xx.h"
-
-static const u8 cm_idlest_offs[] = {
-	CM_IDLEST1, CM_IDLEST2, OMAP2430_CM_IDLEST3
-};
-
-/**
- * omap2_cm_wait_idlest_ready - wait for a module to leave idle or standby
- * @prcm_mod: PRCM module offset
- * @idlest_id: CM_IDLESTx register ID (i.e., x = 1, 2, 3)
- * @idlest_shift: shift of the bit in the CM_IDLEST* register to check
- *
- * XXX document
- */
-int omap2_cm_wait_module_ready(s16 prcm_mod, u8 idlest_id, u8 idlest_shift)
-{
-	int ena = 0, i = 0;
-	u8 cm_idlest_reg;
-	u32 mask;
-
-	if (!idlest_id || (idlest_id > ARRAY_SIZE(cm_idlest_offs)))
-		return -EINVAL;
-
-	cm_idlest_reg = cm_idlest_offs[idlest_id - 1];
-
-	mask = 1 << idlest_shift;
-
-	if (cpu_is_omap24xx())
-		ena = mask;
-	else if (cpu_is_omap34xx())
-		ena = 0;
-	else
-		BUG();
-
-	/* XXX should be OMAP2 CM */
-	omap_test_timeout(((cm_read_mod_reg(prcm_mod, cm_idlest_reg) & mask) == ena),
-			  MAX_MODULE_READY_TIME, i);
-
-	return (i < MAX_MODULE_READY_TIME) ? 0 : -EBUSY;
-}
-
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/cm.h linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/cm.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/cm.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/cm.h	2011-03-14 21:20:32.000000000 -0400
@@ -1,8 +1,5 @@
-#ifndef __ARCH_ASM_MACH_OMAP2_CM_H
-#define __ARCH_ASM_MACH_OMAP2_CM_H
-
 /*
- * OMAP2/3 Clock Management (CM) register definitions
+ * OMAP2+ Clock Management prototypes
  *
  * Copyright (C) 2007-2009 Texas Instruments, Inc.
  * Copyright (C) 2007-2009 Nokia Corporation
@@ -13,136 +10,8 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-
-#include "prcm-common.h"
-
-#define OMAP2420_CM_REGADDR(module, reg)				\
-			OMAP2_L4_IO_ADDRESS(OMAP2420_CM_BASE + (module) + (reg))
-#define OMAP2430_CM_REGADDR(module, reg)				\
-			OMAP2_L4_IO_ADDRESS(OMAP2430_CM_BASE + (module) + (reg))
-#define OMAP34XX_CM_REGADDR(module, reg)				\
-			OMAP2_L4_IO_ADDRESS(OMAP3430_CM_BASE + (module) + (reg))
-#define OMAP44XX_CM1_REGADDR(module, reg)				\
-			OMAP2_L4_IO_ADDRESS(OMAP4430_CM1_BASE + (module) + (reg))
-#define OMAP44XX_CM2_REGADDR(module, reg)				\
-			OMAP2_L4_IO_ADDRESS(OMAP4430_CM2_BASE + (module) + (reg))
-
-#include "cm44xx.h"
-
-/*
- * Architecture-specific global CM registers
- * Use cm_{read,write}_reg() with these registers.
- * These registers appear once per CM module.
- */
-
-#define OMAP3430_CM_REVISION		OMAP34XX_CM_REGADDR(OCP_MOD, 0x0000)
-#define OMAP3430_CM_SYSCONFIG		OMAP34XX_CM_REGADDR(OCP_MOD, 0x0010)
-#define OMAP3430_CM_POLCTRL		OMAP34XX_CM_REGADDR(OCP_MOD, 0x009c)
-
-#define OMAP3_CM_CLKOUT_CTRL_OFFSET	0x0070
-#define OMAP3430_CM_CLKOUT_CTRL		OMAP_CM_REGADDR(OMAP3430_CCR_MOD, 0x0070)
-
-/*
- * Module specific CM registers from CM_BASE + domain offset
- * Use cm_{read,write}_mod_reg() with these registers.
- * These register offsets generally appear in more than one PRCM submodule.
- */
-
-/* Common between 24xx and 34xx */
-
-#define CM_FCLKEN					0x0000
-#define CM_FCLKEN1					CM_FCLKEN
-#define CM_CLKEN					CM_FCLKEN
-#define CM_ICLKEN					0x0010
-#define CM_ICLKEN1					CM_ICLKEN
-#define CM_ICLKEN2					0x0014
-#define CM_ICLKEN3					0x0018
-#define CM_IDLEST					0x0020
-#define CM_IDLEST1					CM_IDLEST
-#define CM_IDLEST2					0x0024
-#define CM_AUTOIDLE					0x0030
-#define CM_AUTOIDLE1					CM_AUTOIDLE
-#define CM_AUTOIDLE2					0x0034
-#define CM_AUTOIDLE3					0x0038
-#define CM_CLKSEL					0x0040
-#define CM_CLKSEL1					CM_CLKSEL
-#define CM_CLKSEL2					0x0044
-#define OMAP2_CM_CLKSTCTRL				0x0048
-#define OMAP4_CM_CLKSTCTRL				0x0000
-
-
-/* Architecture-specific registers */
-
-#define OMAP24XX_CM_FCLKEN2				0x0004
-#define OMAP24XX_CM_ICLKEN4				0x001c
-#define OMAP24XX_CM_AUTOIDLE4				0x003c
-
-#define OMAP2430_CM_IDLEST3				0x0028
-
-#define OMAP3430_CM_CLKEN_PLL				0x0004
-#define OMAP3430ES2_CM_CLKEN2				0x0004
-#define OMAP3430ES2_CM_FCLKEN3				0x0008
-#define OMAP3430_CM_IDLEST_PLL				CM_IDLEST2
-#define OMAP3430_CM_AUTOIDLE_PLL			CM_AUTOIDLE2
-#define OMAP3430ES2_CM_AUTOIDLE2_PLL			CM_AUTOIDLE2
-#define OMAP3430_CM_CLKSEL1				CM_CLKSEL
-#define OMAP3430_CM_CLKSEL1_PLL				CM_CLKSEL
-#define OMAP3430_CM_CLKSEL2_PLL				CM_CLKSEL2
-#define OMAP3430_CM_SLEEPDEP				CM_CLKSEL2
-#define OMAP3430_CM_CLKSEL3				OMAP2_CM_CLKSTCTRL
-#define OMAP3430_CM_CLKSTST				0x004c
-#define OMAP3430ES2_CM_CLKSEL4				0x004c
-#define OMAP3430ES2_CM_CLKSEL5				0x0050
-#define OMAP3430_CM_CLKSEL2_EMU				0x0050
-#define OMAP3430_CM_CLKSEL3_EMU				0x0054
-
-/* CM2.CEFUSE_CM2 register offsets */
-
-/* OMAP4 modulemode control */
-#define OMAP4430_MODULEMODE_HWCTRL			0
-#define OMAP4430_MODULEMODE_SWCTRL			1
-
-/* Clock management domain register get/set */
-
-#ifndef __ASSEMBLER__
-
-extern u32 cm_read_mod_reg(s16 module, u16 idx);
-extern void cm_write_mod_reg(u32 val, s16 module, u16 idx);
-extern u32 cm_rmw_mod_reg_bits(u32 mask, u32 bits, s16 module, s16 idx);
-
-extern int omap2_cm_wait_module_ready(s16 prcm_mod, u8 idlest_id,
-				      u8 idlest_shift);
-extern int omap4_cm_wait_module_ready(void __iomem *clkctrl_reg);
-
-static inline u32 cm_set_mod_reg_bits(u32 bits, s16 module, s16 idx)
-{
-	return cm_rmw_mod_reg_bits(bits, bits, module, idx);
-}
-
-static inline u32 cm_clear_mod_reg_bits(u32 bits, s16 module, s16 idx)
-{
-	return cm_rmw_mod_reg_bits(bits, 0x0, module, idx);
-}
-
-#endif
-
-/* CM register bits shared between 24XX and 3430 */
-
-/* CM_CLKSEL_GFX */
-#define OMAP_CLKSEL_GFX_SHIFT				0
-#define OMAP_CLKSEL_GFX_MASK				(0x7 << 0)
-
-/* CM_ICLKEN_GFX */
-#define OMAP_EN_GFX_SHIFT				0
-#define OMAP_EN_GFX_MASK				(1 << 0)
-
-/* CM_IDLEST_GFX */
-#define OMAP_ST_GFX_MASK				(1 << 0)
-
-
-/* CM_IDLEST indicator */
-#define OMAP24XX_CM_IDLEST_VAL		0
-#define OMAP34XX_CM_IDLEST_VAL		1
+#ifndef __ARCH_ASM_MACH_OMAP2_CM_H
+#define __ARCH_ASM_MACH_OMAP2_CM_H
 
 /*
  * MAX_MODULE_READY_TIME: max duration in microseconds to wait for the
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/cminst44xx.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/cminst44xx.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/cminst44xx.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/cminst44xx.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,214 @@
+/*
+ * OMAP4 CM instance functions
+ *
+ * Copyright (C) 2009 Nokia Corporation
+ * Paul Walmsley
+ *
+ * This program is free software; you can 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 is needed since CM instances can be in the PRM, PRCM_MPU, CM1,
+ * or CM2 hardware modules.  For example, the EMU_CM CM instance is in
+ * the PRM hardware module.  What a mess...
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/io.h>
+
+#include <plat/common.h>
+
+#include "cm.h"
+#include "cm1_44xx.h"
+#include "cm2_44xx.h"
+#include "cm44xx.h"
+#include "cminst44xx.h"
+#include "cm-regbits-34xx.h"
+#include "cm-regbits-44xx.h"
+#include "prcm44xx.h"
+#include "prm44xx.h"
+#include "prcm_mpu44xx.h"
+
+static u32 _cm_bases[OMAP4_MAX_PRCM_PARTITIONS] = {
+	[OMAP4430_INVALID_PRCM_PARTITION]	= 0,
+	[OMAP4430_PRM_PARTITION]		= OMAP4430_PRM_BASE,
+	[OMAP4430_CM1_PARTITION]		= OMAP4430_CM1_BASE,
+	[OMAP4430_CM2_PARTITION]		= OMAP4430_CM2_BASE,
+	[OMAP4430_SCRM_PARTITION]		= 0,
+	[OMAP4430_PRCM_MPU_PARTITION]		= OMAP4430_PRCM_MPU_BASE,
+};
+
+/* Read a register in a CM instance */
+u32 omap4_cminst_read_inst_reg(u8 part, s16 inst, u16 idx)
+{
+	BUG_ON(part >= OMAP4_MAX_PRCM_PARTITIONS ||
+	       part == OMAP4430_INVALID_PRCM_PARTITION ||
+	       !_cm_bases[part]);
+	return __raw_readl(OMAP2_L4_IO_ADDRESS(_cm_bases[part] + inst + idx));
+}
+
+/* Write into a register in a CM instance */
+void omap4_cminst_write_inst_reg(u32 val, u8 part, s16 inst, u16 idx)
+{
+	BUG_ON(part >= OMAP4_MAX_PRCM_PARTITIONS ||
+	       part == OMAP4430_INVALID_PRCM_PARTITION ||
+	       !_cm_bases[part]);
+	__raw_writel(val, OMAP2_L4_IO_ADDRESS(_cm_bases[part] + inst + idx));
+}
+
+/* Read-modify-write a register in CM1. Caller must lock */
+u32 omap4_cminst_rmw_inst_reg_bits(u32 mask, u32 bits, u8 part, s16 inst,
+				   s16 idx)
+{
+	u32 v;
+
+	v = omap4_cminst_read_inst_reg(part, inst, idx);
+	v &= ~mask;
+	v |= bits;
+	omap4_cminst_write_inst_reg(v, part, inst, idx);
+
+	return v;
+}
+
+/*
+ *
+ */
+
+/**
+ * _clktrctrl_write - write @c to a CM_CLKSTCTRL.CLKTRCTRL register bitfield
+ * @c: CLKTRCTRL register bitfield (LSB = bit 0, i.e., unshifted)
+ * @part: PRCM partition ID that the CM_CLKSTCTRL register exists in
+ * @inst: CM instance register offset (*_INST macro)
+ * @cdoffs: Clockdomain register offset (*_CDOFFS macro)
+ *
+ * @c must be the unshifted value for CLKTRCTRL - i.e., this function
+ * will handle the shift itself.
+ */
+static void _clktrctrl_write(u8 c, u8 part, s16 inst, u16 cdoffs)
+{
+	u32 v;
+
+	v = omap4_cminst_read_inst_reg(part, inst, cdoffs + OMAP4_CM_CLKSTCTRL);
+	v &= ~OMAP4430_CLKTRCTRL_MASK;
+	v |= c << OMAP4430_CLKTRCTRL_SHIFT;
+	omap4_cminst_write_inst_reg(v, part, inst, cdoffs + OMAP4_CM_CLKSTCTRL);
+}
+
+/**
+ * omap4_cminst_is_clkdm_in_hwsup - is a clockdomain in hwsup idle mode?
+ * @part: PRCM partition ID that the CM_CLKSTCTRL register exists in
+ * @inst: CM instance register offset (*_INST macro)
+ * @cdoffs: Clockdomain register offset (*_CDOFFS macro)
+ *
+ * Returns true if the clockdomain referred to by (@part, @inst, @cdoffs)
+ * is in hardware-supervised idle mode, or 0 otherwise.
+ */
+bool omap4_cminst_is_clkdm_in_hwsup(u8 part, s16 inst, u16 cdoffs)
+{
+	u32 v;
+
+	v = omap4_cminst_read_inst_reg(part, inst, cdoffs + OMAP4_CM_CLKSTCTRL);
+	v &= OMAP4430_CLKTRCTRL_MASK;
+	v >>= OMAP4430_CLKTRCTRL_SHIFT;
+
+	return (v == OMAP34XX_CLKSTCTRL_ENABLE_AUTO) ? true : false;
+}
+
+/**
+ * omap4_cminst_clkdm_enable_hwsup - put a clockdomain in hwsup-idle mode
+ * @part: PRCM partition ID that the clockdomain registers exist in
+ * @inst: CM instance register offset (*_INST macro)
+ * @cdoffs: Clockdomain register offset (*_CDOFFS macro)
+ *
+ * Put a clockdomain referred to by (@part, @inst, @cdoffs) into
+ * hardware-supervised idle mode.  No return value.
+ */
+void omap4_cminst_clkdm_enable_hwsup(u8 part, s16 inst, u16 cdoffs)
+{
+	_clktrctrl_write(OMAP34XX_CLKSTCTRL_ENABLE_AUTO, part, inst, cdoffs);
+}
+
+/**
+ * omap4_cminst_clkdm_disable_hwsup - put a clockdomain in swsup-idle mode
+ * @part: PRCM partition ID that the clockdomain registers exist in
+ * @inst: CM instance register offset (*_INST macro)
+ * @cdoffs: Clockdomain register offset (*_CDOFFS macro)
+ *
+ * Put a clockdomain referred to by (@part, @inst, @cdoffs) into
+ * software-supervised idle mode, i.e., controlled manually by the
+ * Linux OMAP clockdomain code.  No return value.
+ */
+void omap4_cminst_clkdm_disable_hwsup(u8 part, s16 inst, u16 cdoffs)
+{
+	_clktrctrl_write(OMAP34XX_CLKSTCTRL_DISABLE_AUTO, part, inst, cdoffs);
+}
+
+/**
+ * omap4_cminst_clkdm_force_sleep - try to put a clockdomain into idle
+ * @part: PRCM partition ID that the clockdomain registers exist in
+ * @inst: CM instance register offset (*_INST macro)
+ * @cdoffs: Clockdomain register offset (*_CDOFFS macro)
+ *
+ * Put a clockdomain referred to by (@part, @inst, @cdoffs) into idle
+ * No return value.
+ */
+void omap4_cminst_clkdm_force_sleep(u8 part, s16 inst, u16 cdoffs)
+{
+	_clktrctrl_write(OMAP34XX_CLKSTCTRL_FORCE_SLEEP, part, inst, cdoffs);
+}
+
+/**
+ * omap4_cminst_clkdm_force_sleep - try to take a clockdomain out of idle
+ * @part: PRCM partition ID that the clockdomain registers exist in
+ * @inst: CM instance register offset (*_INST macro)
+ * @cdoffs: Clockdomain register offset (*_CDOFFS macro)
+ *
+ * Take a clockdomain referred to by (@part, @inst, @cdoffs) out of idle,
+ * waking it up.  No return value.
+ */
+void omap4_cminst_clkdm_force_wakeup(u8 part, s16 inst, u16 cdoffs)
+{
+	_clktrctrl_write(OMAP34XX_CLKSTCTRL_FORCE_WAKEUP, part, inst, cdoffs);
+}
+
+/*
+ *
+ */
+
+/**
+ * omap4_cm_wait_module_ready - wait for a module to be in 'func' state
+ * @clkctrl_reg: CLKCTRL module address
+ *
+ * Wait for the module IDLEST to be functional. If the idle state is in any
+ * the non functional state (trans, idle or disabled), module and thus the
+ * sysconfig cannot be accessed and will probably lead to an "imprecise
+ * external abort"
+ *
+ * Module idle state:
+ *   0x0 func:     Module is fully functional, including OCP
+ *   0x1 trans:    Module is performing transition: wakeup, or sleep, or sleep
+ *                 abortion
+ *   0x2 idle:     Module is in Idle mode (only OCP part). It is functional if
+ *                 using separate functional clock
+ *   0x3 disabled: Module is disabled and cannot be accessed
+ *
+ */
+int omap4_cm_wait_module_ready(void __iomem *clkctrl_reg)
+{
+	int i = 0;
+
+	if (!clkctrl_reg)
+		return 0;
+
+	omap_test_timeout((
+		((__raw_readl(clkctrl_reg) & OMAP4430_IDLEST_MASK) == 0) ||
+		 (((__raw_readl(clkctrl_reg) & OMAP4430_IDLEST_MASK) >>
+		  OMAP4430_IDLEST_SHIFT) == 0x2)),
+		MAX_MODULE_READY_TIME, i);
+
+	return (i < MAX_MODULE_READY_TIME) ? 0 : -EBUSY;
+}
+
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/cminst44xx.h linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/cminst44xx.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/cminst44xx.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/cminst44xx.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,31 @@
+/*
+ * OMAP4 Clock Management (CM) function prototypes
+ *
+ * Copyright (C) 2010 Nokia Corporation
+ * Paul Walmsley
+ *
+ * This program is free software; you can 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_ASM_MACH_OMAP2_CMINST44XX_H
+#define __ARCH_ASM_MACH_OMAP2_CMINST44XX_H
+
+extern bool omap4_cminst_is_clkdm_in_hwsup(u8 part, s16 inst, u16 cdoffs);
+extern void omap4_cminst_clkdm_enable_hwsup(u8 part, s16 inst, u16 cdoffs);
+extern void omap4_cminst_clkdm_disable_hwsup(u8 part, s16 inst, u16 cdoffs);
+extern void omap4_cminst_clkdm_force_sleep(u8 part, s16 inst, u16 cdoffs);
+extern void omap4_cminst_clkdm_force_wakeup(u8 part, s16 inst, u16 cdoffs);
+
+/*
+ * In an ideal world, we would not export these low-level functions,
+ * but this will probably take some time to fix properly
+ */
+extern u32 omap4_cminst_read_inst_reg(u8 part, s16 inst, u16 idx);
+extern void omap4_cminst_write_inst_reg(u32 val, u8 part, s16 inst, u16 idx);
+extern u32 omap4_cminst_rmw_inst_reg_bits(u32 mask, u32 bits, u8 part,
+					   s16 inst, s16 idx);
+
+extern int omap4_cm_wait_module_ready(void __iomem *clkctrl_reg);
+
+#endif
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/cm-regbits-24xx.h linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/cm-regbits-24xx.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/cm-regbits-24xx.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/cm-regbits-24xx.h	2011-03-14 21:20:32.000000000 -0400
@@ -14,8 +14,6 @@
  * published by the Free Software Foundation.
  */
 
-#include "cm.h"
-
 /* Bits shared between registers */
 
 /* CM_FCLKEN1_CORE and CM_ICLKEN1_CORE shared bits */
@@ -126,8 +124,12 @@
 #define OMAP24XX_ST_HDQ_MASK				(1 << 23)
 #define OMAP2420_ST_I2C2_SHIFT				20
 #define OMAP2420_ST_I2C2_MASK				(1 << 20)
+#define OMAP2430_ST_I2CHS1_SHIFT			19
+#define OMAP2430_ST_I2CHS1_MASK				(1 << 19)
 #define OMAP2420_ST_I2C1_SHIFT				19
 #define OMAP2420_ST_I2C1_MASK				(1 << 19)
+#define OMAP2430_ST_I2CHS2_SHIFT			20
+#define OMAP2430_ST_I2CHS2_MASK				(1 << 20)
 #define OMAP24XX_ST_MCBSP2_SHIFT			16
 #define OMAP24XX_ST_MCBSP2_MASK				(1 << 16)
 #define OMAP24XX_ST_MCBSP1_SHIFT			15
@@ -432,4 +434,9 @@
 #define OMAP2430_AUTOSTATE_MDM_SHIFT			0
 #define OMAP2430_AUTOSTATE_MDM_MASK			(1 << 0)
 
+/* OMAP24XX CM_CLKSTCTRL_*.AUTOSTATE_* register bit values */
+#define OMAP24XX_CLKSTCTRL_DISABLE_AUTO		0x0
+#define OMAP24XX_CLKSTCTRL_ENABLE_AUTO		0x1
+
+
 #endif
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/cm-regbits-34xx.h linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/cm-regbits-34xx.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/cm-regbits-34xx.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/cm-regbits-34xx.h	2011-03-14 21:20:32.000000000 -0400
@@ -14,8 +14,6 @@
  * published by the Free Software Foundation.
  */
 
-#include "cm.h"
-
 /* Bits shared between registers */
 
 /* CM_FCLKEN1_CORE and CM_ICLKEN1_CORE shared bits */
@@ -800,4 +798,15 @@
 #define OMAP3430ES2_CLKACTIVITY_USBHOST_SHIFT		0
 #define OMAP3430ES2_CLKACTIVITY_USBHOST_MASK		(1 << 0)
 
+/*
+ *
+ */
+
+/* OMAP3XXX CM_CLKSTCTRL_*.CLKTRCTRL_* register bit values */
+#define OMAP34XX_CLKSTCTRL_DISABLE_AUTO		0x0
+#define OMAP34XX_CLKSTCTRL_FORCE_SLEEP		0x1
+#define OMAP34XX_CLKSTCTRL_FORCE_WAKEUP		0x2
+#define OMAP34XX_CLKSTCTRL_ENABLE_AUTO		0x3
+
+
 #endif
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/cm-regbits-44xx.h linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/cm-regbits-44xx.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/cm-regbits-44xx.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/cm-regbits-44xx.h	2011-03-14 21:20:32.000000000 -0400
@@ -22,9 +22,6 @@
 #ifndef __ARCH_ARM_MACH_OMAP2_CM_REGBITS_44XX_H
 #define __ARCH_ARM_MACH_OMAP2_CM_REGBITS_44XX_H
 
-#include "cm.h"
-
-
 /*
  * Used by CM_L3_1_DYNAMICDEP, CM_L3_1_DYNAMICDEP_RESTORE, CM_MPU_DYNAMICDEP,
  * CM_TESLA_DYNAMICDEP
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/control.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/control.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/control.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/control.c	2011-03-14 21:20:32.000000000 -0400
@@ -20,12 +20,16 @@
 
 #include "cm-regbits-34xx.h"
 #include "prm-regbits-34xx.h"
-#include "cm.h"
-#include "prm.h"
+#include "prm2xxx_3xxx.h"
+#include "cm2xxx_3xxx.h"
 #include "sdrc.h"
 #include "pm.h"
 #include "control.h"
 
+/* Used by omap3_ctrl_save_padconf() */
+#define START_PADCONF_SAVE		0x2
+#define PADCONF_SAVE_DONE		0x1
+
 static void __iomem *omap2_ctrl_base;
 static void __iomem *omap4_ctrl_pad_base;
 
@@ -134,6 +138,7 @@ struct omap3_control_regs {
 	u32 sramldo4;
 	u32 sramldo5;
 	u32 csi;
+	u32 padconf_sys_nirq;
 };
 
 static struct omap3_control_regs control_context;
@@ -209,6 +214,37 @@ void omap4_ctrl_pad_writel(u32 val, u16
 	__raw_writel(val, OMAP4_CTRL_PAD_REGADDR(offset));
 }
 
+#ifdef CONFIG_ARCH_OMAP3
+
+/**
+ * omap3_ctrl_write_boot_mode - set scratchpad boot mode for the next boot
+ * @bootmode: 8-bit value to pass to some boot code
+ *
+ * Set the bootmode in the scratchpad RAM.  This is used after the
+ * system restarts.  Not sure what actually uses this - it may be the
+ * bootloader, rather than the boot ROM - contrary to the preserved
+ * comment below.  No return value.
+ */
+void omap3_ctrl_write_boot_mode(u8 bootmode)
+{
+	u32 l;
+
+	l = ('B' << 24) | ('M' << 16) | bootmode;
+
+	/*
+	 * Reserve the first word in scratchpad for communicating
+	 * with the boot ROM. A pointer to a data structure
+	 * describing the boot process can be stored there,
+	 * cf. OMAP34xx TRM, Initialization / Software Booting
+	 * Configuration.
+	 *
+	 * XXX This should use some omap_ctrl_writel()-type function
+	 */
+	__raw_writel(l, OMAP2_L4_IO_ADDRESS(OMAP343X_SCRATCHPAD + 4));
+}
+
+#endif
+
 #if defined(CONFIG_ARCH_OMAP3) && defined(CONFIG_PM)
 /*
  * Clears the scratchpad contents in case of cold boot-
@@ -220,13 +256,13 @@ void omap3_clear_scratchpad_contents(voi
 	void __iomem *v_addr;
 	u32 offset = 0;
 	v_addr = OMAP2_L4_IO_ADDRESS(OMAP343X_SCRATCHPAD_ROM);
-	if (prm_read_mod_reg(OMAP3430_GR_MOD, OMAP3_PRM_RSTST_OFFSET) &
+	if (omap2_prm_read_mod_reg(OMAP3430_GR_MOD, OMAP3_PRM_RSTST_OFFSET) &
 	    OMAP3430_GLOBAL_COLD_RST_MASK) {
 		for ( ; offset <= max_offset; offset += 0x4)
 			__raw_writel(0x0, (v_addr + offset));
-		prm_set_mod_reg_bits(OMAP3430_GLOBAL_COLD_RST_MASK,
-				     OMAP3430_GR_MOD,
-				     OMAP3_PRM_RSTST_OFFSET);
+		omap2_prm_set_mod_reg_bits(OMAP3430_GLOBAL_COLD_RST_MASK,
+					   OMAP3430_GR_MOD,
+					   OMAP3_PRM_RSTST_OFFSET);
 	}
 }
 
@@ -239,9 +275,19 @@ void omap3_save_scratchpad_contents(void
 	struct omap3_scratchpad_prcm_block prcm_block_contents;
 	struct omap3_scratchpad_sdrc_block sdrc_block_contents;
 
-	/* Populate the Scratchpad contents */
+	/*
+	 * Populate the Scratchpad contents
+	 *
+	 * The "get_*restore_pointer" functions are used to provide a
+	 * physical restore address where the ROM code jumps while waking
+	 * up from MPU OFF/OSWR state.
+	 * The restore pointer is stored into the scratchpad.
+	 */
 	scratchpad_contents.boot_config_ptr = 0x0;
-	if (omap_rev() != OMAP3430_REV_ES3_0 &&
+	if (cpu_is_omap3630())
+		scratchpad_contents.public_restore_ptr =
+			virt_to_phys(get_omap3630_restore_pointer());
+	else if (omap_rev() != OMAP3430_REV_ES3_0 &&
 					omap_rev() != OMAP3430_REV_ES3_1)
 		scratchpad_contents.public_restore_ptr =
 			virt_to_phys(get_restore_pointer());
@@ -258,32 +304,34 @@ void omap3_save_scratchpad_contents(void
 	scratchpad_contents.sdrc_block_offset = 0x64;
 
 	/* Populate the PRCM block contents */
-	prcm_block_contents.prm_clksrc_ctrl = prm_read_mod_reg(OMAP3430_GR_MOD,
-			OMAP3_PRM_CLKSRC_CTRL_OFFSET);
-	prcm_block_contents.prm_clksel = prm_read_mod_reg(OMAP3430_CCR_MOD,
-			OMAP3_PRM_CLKSEL_OFFSET);
+	prcm_block_contents.prm_clksrc_ctrl =
+		omap2_prm_read_mod_reg(OMAP3430_GR_MOD,
+				       OMAP3_PRM_CLKSRC_CTRL_OFFSET);
+	prcm_block_contents.prm_clksel =
+		omap2_prm_read_mod_reg(OMAP3430_CCR_MOD,
+				       OMAP3_PRM_CLKSEL_OFFSET);
 	prcm_block_contents.cm_clksel_core =
-			cm_read_mod_reg(CORE_MOD, CM_CLKSEL);
+			omap2_cm_read_mod_reg(CORE_MOD, CM_CLKSEL);
 	prcm_block_contents.cm_clksel_wkup =
-			cm_read_mod_reg(WKUP_MOD, CM_CLKSEL);
+			omap2_cm_read_mod_reg(WKUP_MOD, CM_CLKSEL);
 	prcm_block_contents.cm_clken_pll =
-			cm_read_mod_reg(PLL_MOD, CM_CLKEN);
+			omap2_cm_read_mod_reg(PLL_MOD, CM_CLKEN);
 	prcm_block_contents.cm_autoidle_pll =
-			cm_read_mod_reg(PLL_MOD, OMAP3430_CM_AUTOIDLE_PLL);
+			omap2_cm_read_mod_reg(PLL_MOD, OMAP3430_CM_AUTOIDLE_PLL);
 	prcm_block_contents.cm_clksel1_pll =
-			cm_read_mod_reg(PLL_MOD, OMAP3430_CM_CLKSEL1_PLL);
+			omap2_cm_read_mod_reg(PLL_MOD, OMAP3430_CM_CLKSEL1_PLL);
 	prcm_block_contents.cm_clksel2_pll =
-			cm_read_mod_reg(PLL_MOD, OMAP3430_CM_CLKSEL2_PLL);
+			omap2_cm_read_mod_reg(PLL_MOD, OMAP3430_CM_CLKSEL2_PLL);
 	prcm_block_contents.cm_clksel3_pll =
-			cm_read_mod_reg(PLL_MOD, OMAP3430_CM_CLKSEL3);
+			omap2_cm_read_mod_reg(PLL_MOD, OMAP3430_CM_CLKSEL3);
 	prcm_block_contents.cm_clken_pll_mpu =
-			cm_read_mod_reg(MPU_MOD, OMAP3430_CM_CLKEN_PLL);
+			omap2_cm_read_mod_reg(MPU_MOD, OMAP3430_CM_CLKEN_PLL);
 	prcm_block_contents.cm_autoidle_pll_mpu =
-			cm_read_mod_reg(MPU_MOD, OMAP3430_CM_AUTOIDLE_PLL);
+			omap2_cm_read_mod_reg(MPU_MOD, OMAP3430_CM_AUTOIDLE_PLL);
 	prcm_block_contents.cm_clksel1_pll_mpu =
-			cm_read_mod_reg(MPU_MOD, OMAP3430_CM_CLKSEL1_PLL);
+			omap2_cm_read_mod_reg(MPU_MOD, OMAP3430_CM_CLKSEL1_PLL);
 	prcm_block_contents.cm_clksel2_pll_mpu =
-			cm_read_mod_reg(MPU_MOD, OMAP3430_CM_CLKSEL2_PLL);
+			omap2_cm_read_mod_reg(MPU_MOD, OMAP3430_CM_CLKSEL2_PLL);
 	prcm_block_contents.prcm_block_size = 0x0;
 
 	/* Populate the SDRC block contents */
@@ -416,6 +464,8 @@ void omap3_control_save_context(void)
 	control_context.sramldo4 = omap_ctrl_readl(OMAP343X_CONTROL_SRAMLDO4);
 	control_context.sramldo5 = omap_ctrl_readl(OMAP343X_CONTROL_SRAMLDO5);
 	control_context.csi = omap_ctrl_readl(OMAP343X_CONTROL_CSI);
+	control_context.padconf_sys_nirq =
+		omap_ctrl_readl(OMAP343X_CONTROL_PADCONF_SYSNIRQ);
 	return;
 }
 
@@ -472,6 +522,43 @@ void omap3_control_restore_context(void)
 	omap_ctrl_writel(control_context.sramldo4, OMAP343X_CONTROL_SRAMLDO4);
 	omap_ctrl_writel(control_context.sramldo5, OMAP343X_CONTROL_SRAMLDO5);
 	omap_ctrl_writel(control_context.csi, OMAP343X_CONTROL_CSI);
+	omap_ctrl_writel(control_context.padconf_sys_nirq,
+			 OMAP343X_CONTROL_PADCONF_SYSNIRQ);
 	return;
 }
+
+void omap3630_ctrl_disable_rta(void)
+{
+	if (!cpu_is_omap3630())
+		return;
+	omap_ctrl_writel(OMAP36XX_RTA_DISABLE, OMAP36XX_CONTROL_MEM_RTA_CTRL);
+}
+
+/**
+ * omap3_ctrl_save_padconf - save padconf registers to scratchpad RAM
+ *
+ * Tell the SCM to start saving the padconf registers, then wait for
+ * the process to complete.  Returns 0 unconditionally, although it
+ * should also eventually be able to return -ETIMEDOUT, if the save
+ * does not complete.
+ *
+ * XXX This function is missing a timeout.  What should it be?
+ */
+int omap3_ctrl_save_padconf(void)
+{
+	u32 cpo;
+
+	/* Save the padconf registers */
+	cpo = omap_ctrl_readl(OMAP343X_CONTROL_PADCONF_OFF);
+	cpo |= START_PADCONF_SAVE;
+	omap_ctrl_writel(cpo, OMAP343X_CONTROL_PADCONF_OFF);
+
+	/* wait for the save to complete */
+	while (!(omap_ctrl_readl(OMAP343X_CONTROL_GENERAL_PURPOSE_STATUS)
+		 & PADCONF_SAVE_DONE))
+		udelay(1);
+
+	return 0;
+}
+
 #endif /* CONFIG_ARCH_OMAP3 && CONFIG_PM */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/control.h linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/control.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/control.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/control.h	2011-03-14 21:20:32.000000000 -0400
@@ -148,6 +148,15 @@
 #define OMAP343X_CONTROL_TEST_KEY_11	(OMAP2_CONTROL_GENERAL + 0x00f4)
 #define OMAP343X_CONTROL_TEST_KEY_12	(OMAP2_CONTROL_GENERAL + 0x00f8)
 #define OMAP343X_CONTROL_TEST_KEY_13	(OMAP2_CONTROL_GENERAL + 0x00fc)
+#define OMAP343X_CONTROL_FUSE_OPP1_VDD1 (OMAP2_CONTROL_GENERAL + 0x0110)
+#define OMAP343X_CONTROL_FUSE_OPP2_VDD1 (OMAP2_CONTROL_GENERAL + 0x0114)
+#define OMAP343X_CONTROL_FUSE_OPP3_VDD1 (OMAP2_CONTROL_GENERAL + 0x0118)
+#define OMAP343X_CONTROL_FUSE_OPP4_VDD1 (OMAP2_CONTROL_GENERAL + 0x011c)
+#define OMAP343X_CONTROL_FUSE_OPP5_VDD1 (OMAP2_CONTROL_GENERAL + 0x0120)
+#define OMAP343X_CONTROL_FUSE_OPP1_VDD2 (OMAP2_CONTROL_GENERAL + 0x0124)
+#define OMAP343X_CONTROL_FUSE_OPP2_VDD2 (OMAP2_CONTROL_GENERAL + 0x0128)
+#define OMAP343X_CONTROL_FUSE_OPP3_VDD2 (OMAP2_CONTROL_GENERAL + 0x012c)
+#define OMAP343X_CONTROL_FUSE_SR        (OMAP2_CONTROL_GENERAL + 0x0130)
 #define OMAP343X_CONTROL_IVA2_BOOTADDR	(OMAP2_CONTROL_GENERAL + 0x0190)
 #define OMAP343X_CONTROL_IVA2_BOOTMOD	(OMAP2_CONTROL_GENERAL + 0x0194)
 #define OMAP343X_CONTROL_DEBOBS(i)	(OMAP2_CONTROL_GENERAL + 0x01B0 \
@@ -164,6 +173,26 @@
 #define OMAP343X_CONTROL_SRAMLDO5	(OMAP2_CONTROL_GENERAL + 0x02C0)
 #define OMAP343X_CONTROL_CSI		(OMAP2_CONTROL_GENERAL + 0x02C4)
 
+/* OMAP3630 only CONTROL_GENERAL register offsets */
+#define OMAP3630_CONTROL_FUSE_OPP1G_VDD1        (OMAP2_CONTROL_GENERAL + 0x0110)
+#define OMAP3630_CONTROL_FUSE_OPP50_VDD1        (OMAP2_CONTROL_GENERAL + 0x0114)
+#define OMAP3630_CONTROL_FUSE_OPP100_VDD1       (OMAP2_CONTROL_GENERAL + 0x0118)
+#define OMAP3630_CONTROL_FUSE_OPP120_VDD1       (OMAP2_CONTROL_GENERAL + 0x0120)
+#define OMAP3630_CONTROL_FUSE_OPP50_VDD2        (OMAP2_CONTROL_GENERAL + 0x0128)
+#define OMAP3630_CONTROL_FUSE_OPP100_VDD2       (OMAP2_CONTROL_GENERAL + 0x012C)
+
+/* OMAP44xx control efuse offsets */
+#define OMAP44XX_CONTROL_FUSE_IVA_OPP50		0x22C
+#define OMAP44XX_CONTROL_FUSE_IVA_OPP100	0x22F
+#define OMAP44XX_CONTROL_FUSE_IVA_OPPTURBO	0x232
+#define OMAP44XX_CONTROL_FUSE_IVA_OPPNITRO	0x235
+#define OMAP44XX_CONTROL_FUSE_MPU_OPP50		0x240
+#define OMAP44XX_CONTROL_FUSE_MPU_OPP100	0x243
+#define OMAP44XX_CONTROL_FUSE_MPU_OPPTURBO	0x246
+#define OMAP44XX_CONTROL_FUSE_MPU_OPPNITRO	0x249
+#define OMAP44XX_CONTROL_FUSE_CORE_OPP50	0x254
+#define OMAP44XX_CONTROL_FUSE_CORE_OPP100	0x257
+
 /* AM35XX only CONTROL_GENERAL register offsets */
 #define AM35XX_CONTROL_MSUSPENDMUX_6    (OMAP2_CONTROL_GENERAL + 0x0038)
 #define AM35XX_CONTROL_DEVCONF2         (OMAP2_CONTROL_GENERAL + 0x0310)
@@ -204,6 +233,10 @@
 #define OMAP343X_CONTROL_WKUP_DEBOBS3 (OMAP343X_CONTROL_GENERAL_WKUP + 0x014)
 #define OMAP343X_CONTROL_WKUP_DEBOBS4 (OMAP343X_CONTROL_GENERAL_WKUP + 0x018)
 
+/* 36xx-only RTA - Retention till Accesss control registers and bits */
+#define OMAP36XX_CONTROL_MEM_RTA_CTRL	0x40C
+#define OMAP36XX_RTA_DISABLE		0x0
+
 /* 34xx D2D idle-related pins, handled by PM core */
 #define OMAP3_PADCONF_SAD2D_MSTANDBY   0x250
 #define OMAP3_PADCONF_SAD2D_IDLEACK    0x254
@@ -270,6 +303,8 @@
 #define OMAP343X_SCRATCHPAD_ROM		(OMAP343X_CTRL_BASE + 0x860)
 #define OMAP343X_SCRATCHPAD		(OMAP343X_CTRL_BASE + 0x910)
 #define OMAP343X_SCRATCHPAD_ROM_OFFSET	0x19C
+#define OMAP343X_SCRATCHPAD_REGADDR(reg)	OMAP2_L4_IO_ADDRESS(\
+						OMAP343X_SCRATCHPAD + reg)
 
 /* AM35XX_CONTROL_IPSS_CLK_CTRL bits */
 #define AM35XX_USBOTG_VBUSP_CLK_SHIFT   0
@@ -309,7 +344,7 @@
 #define		FEAT_SGX_NONE		2
 
 #define OMAP3_IVA_SHIFT			12
-#define OMAP3_IVA_MASK			(1 << OMAP3_SGX_SHIFT)
+#define OMAP3_IVA_MASK			(1 << OMAP3_IVA_SHIFT)
 #define		FEAT_IVA		0
 #define		FEAT_IVA_NONE		1
 
@@ -347,10 +382,13 @@ extern void omap3_save_scratchpad_conten
 extern void omap3_clear_scratchpad_contents(void);
 extern u32 *get_restore_pointer(void);
 extern u32 *get_es3_restore_pointer(void);
+extern u32 *get_omap3630_restore_pointer(void);
 extern u32 omap3_arm_context[128];
 extern void omap3_control_save_context(void);
 extern void omap3_control_restore_context(void);
-
+extern void omap3_ctrl_write_boot_mode(u8 bootmode);
+extern void omap3630_ctrl_disable_rta(void);
+extern int omap3_ctrl_save_padconf(void);
 #else
 #define omap_ctrl_base_get()		0
 #define omap_ctrl_readb(x)		0
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/cpuidle34xx.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/cpuidle34xx.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/cpuidle34xx.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/cpuidle34xx.c	2011-03-14 21:20:32.000000000 -0400
@@ -27,8 +27,8 @@
 
 #include <plat/prcm.h>
 #include <plat/irqs.h>
-#include <plat/powerdomain.h>
-#include <plat/clockdomain.h>
+#include "powerdomain.h"
+#include "clockdomain.h"
 #include <plat/serial.h>
 
 #include "pm.h"
@@ -47,6 +47,8 @@
 
 #define OMAP3_STATE_MAX OMAP3_STATE_C7
 
+#define CPUIDLE_FLAG_CHECK_BM	0x10000	/* use omap3_enter_idle_bm() */
+
 struct omap3_processor_cx {
 	u8 valid;
 	u8 type;
@@ -252,7 +254,7 @@ static int omap3_enter_idle_bm(struct cp
 	 * FIXME: we currently manage device-specific idle states
 	 *        for PER and CORE in combination with CPU-specific
 	 *        idle states.  This is wrong, and device-specific
-	 *        idle managment needs to be separated out into 
+	 *        idle management needs to be separated out into 
 	 *        its own code.
 	 */
 
@@ -293,25 +295,26 @@ select_state:
 DEFINE_PER_CPU(struct cpuidle_device, omap3_idle_dev);
 
 /**
- * omap3_cpuidle_update_states - Update the cpuidle states.
+ * omap3_cpuidle_update_states() - Update the cpuidle states
+ * @mpu_deepest_state:	Enable states upto and including this for mpu domain
+ * @core_deepest_state:	Enable states upto and including this for core domain
  *
- * Currently, this function toggles the validity of idle states based upon
- * the flag 'enable_off_mode'. When the flag is set all states are valid.
- * Else, states leading to OFF state set to be invalid.
+ * This goes through the list of states available and enables and disables the
+ * validity of C states based on deepest state that can be achieved for the
+ * variable domain
  */
-void omap3_cpuidle_update_states(void)
+void omap3_cpuidle_update_states(u32 mpu_deepest_state, u32 core_deepest_state)
 {
 	int i;
 
 	for (i = OMAP3_STATE_C1; i < OMAP3_MAX_STATES; i++) {
 		struct omap3_processor_cx *cx = &omap3_power_states[i];
 
-		if (enable_off_mode) {
+		if ((cx->mpu_state >= mpu_deepest_state) &&
+		    (cx->core_state >= core_deepest_state)) {
 			cx->valid = 1;
 		} else {
-			if ((cx->mpu_state == PWRDM_POWER_OFF) ||
-				(cx->core_state	== PWRDM_POWER_OFF))
-				cx->valid = 0;
+			cx->valid = 0;
 		}
 	}
 }
@@ -452,6 +455,18 @@ void omap_init_power_states(void)
 	omap3_power_states[OMAP3_STATE_C7].core_state = PWRDM_POWER_OFF;
 	omap3_power_states[OMAP3_STATE_C7].flags = CPUIDLE_FLAG_TIME_VALID |
 				CPUIDLE_FLAG_CHECK_BM;
+
+	/*
+	 * Erratum i583: implementation for ES rev < Es1.2 on 3630. We cannot
+	 * enable OFF mode in a stable form for previous revisions.
+	 * we disable C7 state as a result.
+	 */
+	if (IS_PM34XX_ERRATUM(PM_SDRC_WAKEUP_ERRATUM_i583)) {
+		omap3_power_states[OMAP3_STATE_C7].valid = 0;
+		cpuidle_params_table[OMAP3_STATE_C7].valid = 0;
+		WARN_ONCE(1, "%s: core off state C7 disabled due to i583\n",
+				__func__);
+	}
 }
 
 struct cpuidle_driver omap3_idle_driver = {
@@ -504,7 +519,10 @@ int __init omap3_idle_init(void)
 		return -EINVAL;
 	dev->state_count = count;
 
-	omap3_cpuidle_update_states();
+	if (enable_off_mode)
+		omap3_cpuidle_update_states(PWRDM_POWER_OFF, PWRDM_POWER_OFF);
+	else
+		omap3_cpuidle_update_states(PWRDM_POWER_RET, PWRDM_POWER_RET);
 
 	if (cpuidle_register_device(dev)) {
 		printk(KERN_ERR "%s: CPUidle register device failed\n",
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/devices.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/devices.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/devices.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/devices.c	2011-03-14 21:20:32.000000000 -0400
@@ -638,6 +638,7 @@ static struct platform_device dummy_pdev
 static void __init omap_hsmmc_reset(void)
 {
 	u32 i, nr_controllers;
+	struct clk *iclk, *fclk;
 
 	if (cpu_is_omap242x())
 		return;
@@ -647,7 +648,6 @@ static void __init omap_hsmmc_reset(void
 
 	for (i = 0; i < nr_controllers; i++) {
 		u32 v, base = 0;
-		struct clk *iclk, *fclk;
 		struct device *dev = &dummy_pdev.dev;
 
 		switch (i) {
@@ -678,19 +678,16 @@ static void __init omap_hsmmc_reset(void
 		dummy_pdev.id = i;
 		dev_set_name(&dummy_pdev.dev, "mmci-omap-hs.%d", i);
 		iclk = clk_get(dev, "ick");
-		if (iclk && clk_enable(iclk))
-			iclk = NULL;
+		if (IS_ERR(iclk))
+			goto err1;
+		if (clk_enable(iclk))
+			goto err2;
 
 		fclk = clk_get(dev, "fck");
-		if (fclk && clk_enable(fclk))
-			fclk = NULL;
-
-		if (!iclk || !fclk) {
-			printk(KERN_WARNING
-			       "%s: Unable to enable clocks for MMC%d, "
-			       "cannot reset.\n",  __func__, i);
-			break;
-		}
+		if (IS_ERR(fclk))
+			goto err3;
+		if (clk_enable(fclk))
+			goto err4;
 
 		omap_writel(MMCHS_SYSCONFIG_SWRESET, base + MMCHS_SYSCONFIG);
 		v = omap_readl(base + MMCHS_SYSSTATUS);
@@ -698,15 +695,22 @@ static void __init omap_hsmmc_reset(void
 			 MMCHS_SYSSTATUS_RESETDONE))
 			cpu_relax();
 
-		if (fclk) {
-			clk_disable(fclk);
-			clk_put(fclk);
-		}
-		if (iclk) {
-			clk_disable(iclk);
-			clk_put(iclk);
-		}
+		clk_disable(fclk);
+		clk_put(fclk);
+		clk_disable(iclk);
+		clk_put(iclk);
 	}
+	return;
+
+err4:
+	clk_put(fclk);
+err3:
+	clk_disable(iclk);
+err2:
+	clk_put(iclk);
+err1:
+	printk(KERN_WARNING "%s: Unable to enable clocks for MMC%d, "
+			    "cannot reset.\n",  __func__, i);
 }
 #else
 static inline void omap_hsmmc_reset(void) {}
@@ -951,72 +955,12 @@ static inline void omap_init_vout(void)
 
 /*-------------------------------------------------------------------------*/
 
-/*
- * Inorder to avoid any assumptions from bootloader regarding WDT
- * settings, WDT module is reset during init. This enables the watchdog
- * timer. Hence it is required to disable the watchdog after the WDT reset
- * during init. Otherwise the system would reboot as per the default
- * watchdog timer registers settings.
- */
-#define OMAP_WDT_WPS	(0x34)
-#define OMAP_WDT_SPR	(0x48)
-
-static int omap2_disable_wdt(struct omap_hwmod *oh, void *unused)
-{
-	void __iomem *base;
-	int ret;
-
-	if (!oh) {
-		pr_err("%s: Could not look up wdtimer_hwmod\n", __func__);
-		return -EINVAL;
-	}
-
-	base = omap_hwmod_get_mpu_rt_va(oh);
-	if (!base) {
-		pr_err("%s: Could not get the base address for %s\n",
-				oh->name, __func__);
-		return -EINVAL;
-	}
-
-	/* Enable the clocks before accessing the WDT registers */
-	ret = omap_hwmod_enable(oh);
-	if (ret) {
-		pr_err("%s: Could not enable clocks for %s\n",
-				oh->name, __func__);
-		return ret;
-	}
-
-	/* sequence required to disable watchdog */
-	__raw_writel(0xAAAA, base + OMAP_WDT_SPR);
-	while (__raw_readl(base + OMAP_WDT_WPS) & 0x10)
-		cpu_relax();
-
-	__raw_writel(0x5555, base + OMAP_WDT_SPR);
-	while (__raw_readl(base + OMAP_WDT_WPS) & 0x10)
-		cpu_relax();
-
-	ret = omap_hwmod_idle(oh);
-	if (ret)
-		pr_err("%s: Could not disable clocks for %s\n",
-				oh->name, __func__);
-
-	return ret;
-}
-
-static void __init omap_disable_wdt(void)
-{
-	if (cpu_class_is_omap2())
-		omap_hwmod_for_each_by_class("wd_timer",
-						omap2_disable_wdt, NULL);
-	return;
-}
-
 static int __init omap2_init_devices(void)
 {
-	/* please keep these calls, and their implementations above,
+	/*
+	 * please keep these calls, and their implementations above,
 	 * in alphabetical order so they're easier to sort through.
 	 */
-	omap_disable_wdt();
 	omap_hsmmc_reset();
 	omap_init_audio();
 	omap_init_camera();
@@ -1034,7 +978,7 @@ static int __init omap2_init_devices(voi
 arch_initcall(omap2_init_devices);
 
 #if defined(CONFIG_OMAP_WATCHDOG) || defined(CONFIG_OMAP_WATCHDOG_MODULE)
-struct omap_device_pm_latency omap_wdt_latency[] = {
+static struct omap_device_pm_latency omap_wdt_latency[] = {
 	[0] = {
 		.deactivate_func = omap_device_idle_hwmods,
 		.activate_func   = omap_device_enable_hwmods,
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/dma.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/dma.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/dma.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/dma.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,297 @@
+/*
+ * OMAP2+ DMA driver
+ *
+ * Copyright (C) 2003 - 2008 Nokia Corporation
+ * Author: Juha Yrjölä <juha.yrjola@nokia.com>
+ * DMA channel linking for 1610 by Samuel Ortiz <samuel.ortiz@nokia.com>
+ * Graphics DMA and LCD DMA graphics tranformations
+ * by Imre Deak <imre.deak@nokia.com>
+ * OMAP2/3 support Copyright (C) 2004-2007 Texas Instruments, Inc.
+ * Some functions based on earlier dma-omap.c Copyright (C) 2001 RidgeRun, Inc.
+ *
+ * Copyright (C) 2009 Texas Instruments
+ * Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@ti.com>
+ *
+ * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
+ * Converted DMA library into platform driver
+ *	- G, Manjunath Kondaiah <manjugk@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.
+ */
+
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/device.h>
+
+#include <plat/omap_hwmod.h>
+#include <plat/omap_device.h>
+#include <plat/dma.h>
+
+#define OMAP2_DMA_STRIDE	0x60
+
+static u32 errata;
+static u8 dma_stride;
+
+static struct omap_dma_dev_attr *d;
+
+static enum omap_reg_offsets dma_common_ch_start, dma_common_ch_end;
+
+static u16 reg_map[] = {
+	[REVISION]		= 0x00,
+	[GCR]			= 0x78,
+	[IRQSTATUS_L0]		= 0x08,
+	[IRQSTATUS_L1]		= 0x0c,
+	[IRQSTATUS_L2]		= 0x10,
+	[IRQSTATUS_L3]		= 0x14,
+	[IRQENABLE_L0]		= 0x18,
+	[IRQENABLE_L1]		= 0x1c,
+	[IRQENABLE_L2]		= 0x20,
+	[IRQENABLE_L3]		= 0x24,
+	[SYSSTATUS]		= 0x28,
+	[OCP_SYSCONFIG]		= 0x2c,
+	[CAPS_0]		= 0x64,
+	[CAPS_2]		= 0x6c,
+	[CAPS_3]		= 0x70,
+	[CAPS_4]		= 0x74,
+
+	/* Common register offsets */
+	[CCR]			= 0x80,
+	[CLNK_CTRL]		= 0x84,
+	[CICR]			= 0x88,
+	[CSR]			= 0x8c,
+	[CSDP]			= 0x90,
+	[CEN]			= 0x94,
+	[CFN]			= 0x98,
+	[CSEI]			= 0xa4,
+	[CSFI]			= 0xa8,
+	[CDEI]			= 0xac,
+	[CDFI]			= 0xb0,
+	[CSAC]			= 0xb4,
+	[CDAC]			= 0xb8,
+
+	/* Channel specific register offsets */
+	[CSSA]			= 0x9c,
+	[CDSA]			= 0xa0,
+	[CCEN]			= 0xbc,
+	[CCFN]			= 0xc0,
+	[COLOR]			= 0xc4,
+
+	/* OMAP4 specific registers */
+	[CDP]			= 0xd0,
+	[CNDP]			= 0xd4,
+	[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)
+{
+	u8  stride;
+	u32 offset;
+
+	stride = (reg >= dma_common_ch_start) ? dma_stride : 0;
+	offset = reg_map[reg] + (stride * lch);
+	__raw_writel(val, dma_base + offset);
+}
+
+static inline u32 dma_read(int reg, int lch)
+{
+	u8 stride;
+	u32 offset, val;
+
+	stride = (reg >= dma_common_ch_start) ? dma_stride : 0;
+	offset = reg_map[reg] + (stride * lch);
+	val = __raw_readl(dma_base + offset);
+	return val;
+}
+
+static inline void omap2_disable_irq_lch(int lch)
+{
+	u32 val;
+
+	val = dma_read(IRQENABLE_L0, lch);
+	val &= ~(1 << lch);
+	dma_write(val, IRQENABLE_L0, lch);
+}
+
+static void omap2_clear_dma(int lch)
+{
+	int i = dma_common_ch_start;
+
+	for (; i <= dma_common_ch_end; i += 1)
+		dma_write(0, i, lch);
+}
+
+static void omap2_show_dma_caps(void)
+{
+	u8 revision = dma_read(REVISION, 0) & 0xff;
+	printk(KERN_INFO "OMAP DMA hardware revision %d.%d\n",
+				revision >> 4, revision & 0xf);
+	return;
+}
+
+static u32 configure_dma_errata(void)
+{
+
+	/*
+	 * Errata applicable for OMAP2430ES1.0 and all omap2420
+	 *
+	 * I.
+	 * Erratum ID: Not Available
+	 * Inter Frame DMA buffering issue DMA will wrongly
+	 * buffer elements if packing and bursting is enabled. This might
+	 * result in data gets stalled in FIFO at the end of the block.
+	 * Workaround: DMA channels must have BUFFERING_DISABLED bit set to
+	 * guarantee no data will stay in the DMA FIFO in case inter frame
+	 * buffering occurs
+	 *
+	 * II.
+	 * Erratum ID: Not Available
+	 * DMA may hang when several channels are used in parallel
+	 * In the following configuration, DMA channel hanging can occur:
+	 * a. Channel i, hardware synchronized, is enabled
+	 * b. Another channel (Channel x), software synchronized, is enabled.
+	 * c. Channel i is disabled before end of transfer
+	 * d. Channel i is reenabled.
+	 * e. Steps 1 to 4 are repeated a certain number of times.
+	 * f. A third channel (Channel y), software synchronized, is enabled.
+	 * Channel x and Channel y may hang immediately after step 'f'.
+	 * Workaround:
+	 * For any channel used - make sure NextLCH_ID is set to the value j.
+	 */
+	if (cpu_is_omap2420() || (cpu_is_omap2430() &&
+				(omap_type() == OMAP2430_REV_ES1_0))) {
+
+		SET_DMA_ERRATA(DMA_ERRATA_IFRAME_BUFFERING);
+		SET_DMA_ERRATA(DMA_ERRATA_PARALLEL_CHANNELS);
+	}
+
+	/*
+	 * Erratum ID: i378: OMAP2+: sDMA Channel is not disabled
+	 * after a transaction error.
+	 * Workaround: SW should explicitely disable the channel.
+	 */
+	if (cpu_class_is_omap2())
+		SET_DMA_ERRATA(DMA_ERRATA_i378);
+
+	/*
+	 * Erratum ID: i541: sDMA FIFO draining does not finish
+	 * If sDMA channel is disabled on the fly, sDMA enters standby even
+	 * through FIFO Drain is still in progress
+	 * Workaround: Put sDMA in NoStandby more before a logical channel is
+	 * disabled, then put it back to SmartStandby right after the channel
+	 * finishes FIFO draining.
+	 */
+	if (cpu_is_omap34xx())
+		SET_DMA_ERRATA(DMA_ERRATA_i541);
+
+	/*
+	 * Erratum ID: i88 : Special programming model needed to disable DMA
+	 * before end of block.
+	 * Workaround: software must ensure that the DMA is configured in No
+	 * Standby mode(DMAx_OCP_SYSCONFIG.MIDLEMODE = "01")
+	 */
+	if (omap_type() == OMAP3430_REV_ES1_0)
+		SET_DMA_ERRATA(DMA_ERRATA_i88);
+
+	/*
+	 * Erratum 3.2/3.3: sometimes 0 is returned if CSAC/CDAC is
+	 * read before the DMA controller finished disabling the channel.
+	 */
+	SET_DMA_ERRATA(DMA_ERRATA_3_3);
+
+	/*
+	 * Erratum ID: Not Available
+	 * A bug in ROM code leaves IRQ status for channels 0 and 1 uncleared
+	 * after secure sram context save and restore.
+	 * Work around: Hence we need to manually clear those IRQs to avoid
+	 * spurious interrupts. This affects only secure devices.
+	 */
+	if (cpu_is_omap34xx() && (omap_type() != OMAP2_DEVICE_TYPE_GP))
+		SET_DMA_ERRATA(DMA_ROMCODE_BUG);
+
+	return errata;
+}
+
+/* One time initializations */
+static int __init omap2_system_dma_init_dev(struct omap_hwmod *oh, void *unused)
+{
+	struct omap_device			*od;
+	struct omap_system_dma_plat_info	*p;
+	struct resource				*mem;
+	char					*name = "omap_dma_system";
+
+	dma_stride		= OMAP2_DMA_STRIDE;
+	dma_common_ch_start	= CSDP;
+	if (cpu_is_omap3630() || cpu_is_omap4430())
+		dma_common_ch_end = CCDN;
+	else
+		dma_common_ch_end = CCFN;
+
+	p = kzalloc(sizeof(struct omap_system_dma_plat_info), GFP_KERNEL);
+	if (!p) {
+		pr_err("%s: Unable to allocate pdata for %s:%s\n",
+			__func__, name, oh->name);
+		return -ENOMEM;
+	}
+
+	p->dma_attr		= (struct omap_dma_dev_attr *)oh->dev_attr;
+	p->disable_irq_lch	= omap2_disable_irq_lch;
+	p->show_dma_caps	= omap2_show_dma_caps;
+	p->clear_dma		= omap2_clear_dma;
+	p->dma_write		= dma_write;
+	p->dma_read		= dma_read;
+
+	p->clear_lch_regs	= NULL;
+
+	p->errata		= configure_dma_errata();
+
+	od = omap_device_build(name, 0, oh, p, sizeof(*p),
+			omap2_dma_latency, ARRAY_SIZE(omap2_dma_latency), 0);
+	kfree(p);
+	if (IS_ERR(od)) {
+		pr_err("%s: Cant build omap_device for %s:%s.\n",
+			__func__, name, oh->name);
+		return PTR_ERR(od);
+	}
+
+	mem = platform_get_resource(&od->pdev, IORESOURCE_MEM, 0);
+	if (!mem) {
+		dev_err(&od->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__);
+		return -ENOMEM;
+	}
+
+	d = oh->dev_attr;
+	d->chan = kzalloc(sizeof(struct omap_dma_lch) *
+					(d->lch_count), GFP_KERNEL);
+
+	if (!d->chan) {
+		dev_err(&od->pdev.dev, "%s: kzalloc fail\n", __func__);
+		return -ENOMEM;
+	}
+	return 0;
+}
+
+static int __init omap2_system_dma_init(void)
+{
+	return omap_hwmod_for_each_by_class("dma",
+			omap2_system_dma_init_dev, NULL);
+}
+arch_initcall(omap2_system_dma_init);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/dpll3xxx.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/dpll3xxx.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/dpll3xxx.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/dpll3xxx.c	2011-03-14 21:20:32.000000000 -0400
@@ -26,15 +26,13 @@
 #include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/bitops.h>
+#include <linux/clkdev.h>
 
 #include <plat/cpu.h>
 #include <plat/clock.h>
-#include <asm/clkdev.h>
 
 #include "clock.h"
-#include "prm.h"
-#include "prm-regbits-34xx.h"
-#include "cm.h"
+#include "cm2xxx_3xxx.h"
 #include "cm-regbits-34xx.h"
 
 /* CM_AUTOIDLE_PLL*.AUTO_* bit values */
@@ -225,10 +223,9 @@ static int _omap3_noncore_dpll_stop(stru
 }
 
 /**
- * lookup_dco_sddiv -  Set j-type DPLL4 compensation variables
+ * _lookup_dco - Lookup DCO used by j-type DPLL
  * @clk: pointer to a DPLL struct clk
  * @dco: digital control oscillator selector
- * @sd_div: target sigma-delta divider
  * @m: DPLL multiplier to set
  * @n: DPLL divider to set
  *
@@ -237,11 +234,9 @@ static int _omap3_noncore_dpll_stop(stru
  * XXX This code is not needed for 3430/AM35xx; can it be optimized
  * out in non-multi-OMAP builds for those chips?
  */
-static void lookup_dco_sddiv(struct clk *clk, u8 *dco, u8 *sd_div, u16 m,
-			     u8 n)
+static void _lookup_dco(struct clk *clk, u8 *dco, u16 m, u8 n)
 {
-	unsigned long fint, clkinp, sd; /* watch out for overflow */
-	int mod1, mod2;
+	unsigned long fint, clkinp; /* watch out for overflow */
 
 	clkinp = clk->parent->rate;
 	fint = (clkinp / n) * m;
@@ -250,6 +245,27 @@ static void lookup_dco_sddiv(struct clk
 		*dco = 2;
 	else
 		*dco = 4;
+}
+
+/**
+ * _lookup_sddiv - Calculate sigma delta divider for j-type DPLL
+ * @clk: pointer to a DPLL struct clk
+ * @sd_div: target sigma-delta divider
+ * @m: DPLL multiplier to set
+ * @n: DPLL divider to set
+ *
+ * See 36xx TRM section 3.5.3.3.3.2 "Type B DPLL (Low-Jitter)"
+ *
+ * XXX This code is not needed for 3430/AM35xx; can it be optimized
+ * out in non-multi-OMAP builds for those chips?
+ */
+static void _lookup_sddiv(struct clk *clk, u8 *sd_div, u16 m, u8 n)
+{
+	unsigned long clkinp, sd; /* watch out for overflow */
+	int mod1, mod2;
+
+	clkinp = clk->parent->rate;
+
 	/*
 	 * target sigma-delta to near 250MHz
 	 * sd = ceil[(m/(n+1)) * (clkinp_MHz / 250)]
@@ -278,6 +294,7 @@ static void lookup_dco_sddiv(struct clk
 static int omap3_noncore_dpll_program(struct clk *clk, u16 m, u8 n, u16 freqsel)
 {
 	struct dpll_data *dd = clk->dpll_data;
+	u8 dco, sd_div;
 	u32 v;
 
 	/* 3430 ES2 TRM: 4.7.6.9 DPLL Programming Sequence */
@@ -300,18 +317,16 @@ static int omap3_noncore_dpll_program(st
 	v |= m << __ffs(dd->mult_mask);
 	v |= (n - 1) << __ffs(dd->div1_mask);
 
-	/*
-	 * XXX This code is not needed for 3430/AM35XX; can it be optimized
-	 * out in non-multi-OMAP builds for those chips?
-	 */
-	if ((dd->flags & DPLL_J_TYPE) && !(dd->flags & DPLL_NO_DCO_SEL)) {
-		u8 dco, sd_div;
-		lookup_dco_sddiv(clk, &dco, &sd_div, m, n);
-		/* XXX This probably will need revision for OMAP4 */
-		v &= ~(OMAP3630_PERIPH_DPLL_DCO_SEL_MASK
-			| OMAP3630_PERIPH_DPLL_SD_DIV_MASK);
-		v |= dco << __ffs(OMAP3630_PERIPH_DPLL_DCO_SEL_MASK);
-		v |= sd_div << __ffs(OMAP3630_PERIPH_DPLL_SD_DIV_MASK);
+	/* Configure dco and sd_div for dplls that have these fields */
+	if (dd->dco_mask) {
+		_lookup_dco(clk, &dco, m, n);
+		v &= ~(dd->dco_mask);
+		v |= dco << __ffs(dd->dco_mask);
+	}
+	if (dd->sddiv_mask) {
+		_lookup_sddiv(clk, &sd_div, m, n);
+		v &= ~(dd->sddiv_mask);
+		v |= sd_div << __ffs(dd->sddiv_mask);
 	}
 
 	__raw_writel(v, dd->mult_div1_reg);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/dsp.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/dsp.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/dsp.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/dsp.c	2011-03-14 21:20:32.000000000 -0400
@@ -11,9 +11,16 @@
  * published by the Free Software Foundation.
  */
 
+/*
+ * XXX The function pointers to the PRM/CM functions are incorrect and
+ * should be removed.  No device driver should be changing PRM/CM bits
+ * directly; that's a layering violation -- those bits are the responsibility
+ * of the OMAP PM core code.
+ */
+
 #include <linux/platform_device.h>
-#include "prm.h"
-#include "cm.h"
+#include "cm2xxx_3xxx.h"
+#include "prm2xxx_3xxx.h"
 #ifdef CONFIG_BRIDGE_DVFS
 #include <plat/omap-pm.h>
 #endif
@@ -31,12 +38,12 @@ static struct omap_dsp_platform_data oma
 	.cpu_set_freq = omap_pm_cpu_set_freq,
 	.cpu_get_freq = omap_pm_cpu_get_freq,
 #endif
-	.dsp_prm_read = prm_read_mod_reg,
-	.dsp_prm_write = prm_write_mod_reg,
-	.dsp_prm_rmw_bits = prm_rmw_mod_reg_bits,
-	.dsp_cm_read = cm_read_mod_reg,
-	.dsp_cm_write = cm_write_mod_reg,
-	.dsp_cm_rmw_bits = cm_rmw_mod_reg_bits,
+	.dsp_prm_read = omap2_prm_read_mod_reg,
+	.dsp_prm_write = omap2_prm_write_mod_reg,
+	.dsp_prm_rmw_bits = omap2_prm_rmw_mod_reg_bits,
+	.dsp_cm_read = omap2_cm_read_mod_reg,
+	.dsp_cm_write = omap2_cm_write_mod_reg,
+	.dsp_cm_rmw_bits = omap2_cm_rmw_mod_reg_bits,
 };
 
 static int __init omap_dsp_init(void)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/gpio.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/gpio.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/gpio.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/gpio.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,104 @@
+/*
+ * OMAP2+ specific gpio initialization
+ *
+ * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Author:
+ *	Charulatha V <charu@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 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/gpio.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+
+#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 omap_gpio_platform_data *pdata;
+	struct omap_gpio_dev_attr *dev_attr;
+	char *name = "omap_gpio";
+	int id;
+
+	/*
+	 * extract the device id from name field available in the
+	 * hwmod database and use the same for constructing ids for
+	 * gpio devices.
+	 * CAUTION: Make sure the name in the hwmod database does
+	 * not change. If changed, make corresponding change here
+	 * or make use of static variable mechanism to handle this.
+	 */
+	sscanf(oh->name, "gpio%d", &id);
+
+	pdata = kzalloc(sizeof(struct omap_gpio_platform_data), GFP_KERNEL);
+	if (!pdata) {
+		pr_err("gpio%d: Memory allocation failed\n", id);
+		return -ENOMEM;
+	}
+
+	dev_attr = (struct omap_gpio_dev_attr *)oh->dev_attr;
+	pdata->bank_width = dev_attr->bank_width;
+	pdata->dbck_flag = dev_attr->dbck_flag;
+	pdata->virtual_irq_start = IH_GPIO_BASE + 32 * (id - 1);
+
+	switch (oh->class->rev) {
+	case 0:
+	case 1:
+		pdata->bank_type = METHOD_GPIO_24XX;
+		break;
+	case 2:
+		pdata->bank_type = METHOD_GPIO_44XX;
+		break;
+	default:
+		WARN(1, "Invalid gpio bank_type\n");
+		kfree(pdata);
+		return -EINVAL;
+	}
+
+	od = omap_device_build(name, id - 1, oh, pdata,
+				sizeof(*pdata),	omap_gpio_latency,
+				ARRAY_SIZE(omap_gpio_latency),
+				false);
+	kfree(pdata);
+
+	if (IS_ERR(od)) {
+		WARN(1, "Cant build omap_device for %s:%s.\n",
+					name, oh->name);
+		return PTR_ERR(od);
+	}
+
+	gpio_bank_count++;
+	return 0;
+}
+
+/*
+ * gpio_init needs to be done before
+ * machine_init functions access gpio APIs.
+ * Hence gpio_init is a postcore_initcall.
+ */
+static int __init omap2_gpio_init(void)
+{
+	return omap_hwmod_for_each_by_class("gpio", omap2_gpio_dev_init,
+						NULL);
+}
+postcore_initcall(omap2_gpio_init);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/gpmc.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/gpmc.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/gpmc.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/gpmc.c	2011-03-14 21:20:32.000000000 -0400
@@ -168,6 +168,16 @@ unsigned int gpmc_ns_to_ticks(unsigned i
 	return (time_ns * 1000 + tick_ps - 1) / tick_ps;
 }
 
+unsigned int gpmc_ps_to_ticks(unsigned int time_ps)
+{
+	unsigned long tick_ps;
+
+	/* Calculate in picosecs to yield more exact results */
+	tick_ps = gpmc_get_fclk_period();
+
+	return (time_ps + tick_ps - 1) / tick_ps;
+}
+
 unsigned int gpmc_ticks_to_ns(unsigned int ticks)
 {
 	return ticks * gpmc_get_fclk_period() / 1000;
@@ -235,7 +245,7 @@ int gpmc_cs_calc_divider(int cs, unsigne
 	int div;
 	u32 l;
 
-	l = sync_clk * 1000 + (gpmc_get_fclk_period() - 1);
+	l = sync_clk + (gpmc_get_fclk_period() - 1);
 	div = l / gpmc_get_fclk_period();
 	if (div > 4)
 		return -1;
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/gpmc-nand.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/gpmc-nand.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/gpmc-nand.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/gpmc-nand.c	2011-03-14 21:20:32.000000000 -0400
@@ -41,7 +41,7 @@ static int omap2_nand_gpmc_retime(void)
 		return 0;
 
 	memset(&t, 0, sizeof(t));
-	t.sync_clk = gpmc_round_ns_to_ticks(gpmc_nand_data->gpmc_t->sync_clk);
+	t.sync_clk = gpmc_nand_data->gpmc_t->sync_clk;
 	t.cs_on = gpmc_round_ns_to_ticks(gpmc_nand_data->gpmc_t->cs_on);
 	t.adv_on = gpmc_round_ns_to_ticks(gpmc_nand_data->gpmc_t->adv_on);
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/gpmc-onenand.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/gpmc-onenand.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/gpmc-onenand.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/gpmc-onenand.c	2011-03-14 21:20:32.000000000 -0400
@@ -173,8 +173,17 @@ static int omap2_onenand_set_sync_mode(s
 	}
 
 	switch (freq) {
+	case 104:
+		min_gpmc_clk_period = 9600; /* 104 MHz */
+		t_ces   = 3;
+		t_avds  = 4;
+		t_avdh  = 2;
+		t_ach   = 3;
+		t_aavdh = 6;
+		t_rdyo  = 9;
+		break;
 	case 83:
-		min_gpmc_clk_period = 12; /* 83 MHz */
+		min_gpmc_clk_period = 12000; /* 83 MHz */
 		t_ces   = 5;
 		t_avds  = 4;
 		t_avdh  = 2;
@@ -183,7 +192,7 @@ static int omap2_onenand_set_sync_mode(s
 		t_rdyo  = 9;
 		break;
 	case 66:
-		min_gpmc_clk_period = 15; /* 66 MHz */
+		min_gpmc_clk_period = 15000; /* 66 MHz */
 		t_ces   = 6;
 		t_avds  = 5;
 		t_avdh  = 2;
@@ -192,7 +201,7 @@ static int omap2_onenand_set_sync_mode(s
 		t_rdyo  = 11;
 		break;
 	default:
-		min_gpmc_clk_period = 18; /* 54 MHz */
+		min_gpmc_clk_period = 18500; /* 54 MHz */
 		t_ces   = 7;
 		t_avds  = 7;
 		t_avdh  = 7;
@@ -271,8 +280,8 @@ static int omap2_onenand_set_sync_mode(s
 		t.wr_cycle  = t.rd_cycle;
 		if (cpu_is_omap34xx()) {
 			t.wr_data_mux_bus = gpmc_ticks_to_ns(fclk_offset +
-					gpmc_ns_to_ticks(min_gpmc_clk_period +
-					t_rdyo));
+					gpmc_ps_to_ticks(min_gpmc_clk_period +
+					t_rdyo * 1000));
 			t.wr_access = t.access;
 		}
 	} else {
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/include/mach/board-zoom.h linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/include/mach/board-zoom.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/include/mach/board-zoom.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/include/mach/board-zoom.h	2011-03-14 21:20:32.000000000 -0400
@@ -1,9 +1,12 @@
 /*
  * Defines for zoom boards
  */
+#include <plat/display.h>
+
 #define ZOOM_NAND_CS    0
 
 extern int __init zoom_debugboard_init(void);
 extern void __init zoom_peripherals_init(void);
+extern void __init zoom_display_init(void);
 
 #define ZOOM2_HEADSET_EXTMUTE_GPIO	153
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/include/mach/entry-macro.S linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/include/mach/entry-macro.S
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/include/mach/entry-macro.S	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/include/mach/entry-macro.S	2011-03-14 21:20:32.000000000 -0400
@@ -38,41 +38,13 @@
  */
 
 #ifdef MULTI_OMAP2
-		.pushsection .data
-omap_irq_base:	.word	0
-		.popsection
-
-		/* Configure the interrupt base on the first interrupt */
+		/*
+		 * Configure the interrupt base on the first interrupt.
+		 * See also omap_irq_base_init for setting omap_irq_base.
+		 */
 		.macro  get_irqnr_preamble, base, tmp
-9:
 		ldr	\base, =omap_irq_base	@ irq base address
 		ldr	\base, [\base, #0]	@ irq base value
-		cmp	\base, #0		@ already configured?
-		bne	9997f			@ nothing to do
-
-		mrc	p15, 0, \tmp, c0, c0, 0	@ get processor revision
-		and	\tmp, \tmp, #0x000f0000	@ only check architecture
-		cmp	\tmp, #0x00070000	@ is v6?
-		beq	2400f			@ found v6 so it's omap24xx
-		mrc	p15, 0, \tmp, c0, c0, 0	@ get processor revision
-		and	\tmp, \tmp, #0x000000f0	@ check cortex 8 or 9
-		cmp	\tmp, #0x00000080	@ cortex A-8?
-		beq	3400f			@ found A-8 so it's omap34xx
-		cmp	\tmp, #0x00000090	@ cortex A-9?
-		beq	4400f			@ found A-9 so it's omap44xx
-2400:		ldr	\base, =OMAP2_IRQ_BASE
-		ldr	\tmp, =omap_irq_base
-		str	\base, [\tmp, #0]
-		b	9b
-3400:		ldr	\base, =OMAP3_IRQ_BASE
-		ldr	\tmp, =omap_irq_base
-		str	\base, [\tmp, #0]
-		b	9b
-4400:		ldr	\base, =OMAP4_IRQ_BASE
-		ldr	\tmp, =omap_irq_base
-		str	\base, [\tmp, #0]
-		b	9b
-9997:
 		.endm
 
 		/* Check the pending interrupts. Note that base already set */
@@ -105,6 +77,35 @@ omap_irq_base:	.word	0
 9999:
 		.endm
 
+#ifdef CONFIG_SMP
+		/* We assume that irqstat (the raw value of the IRQ acknowledge
+		 * register) is preserved from the macro above.
+		 * If there is an IPI, we immediately signal end of interrupt
+		 * on the controller, since this requires the original irqstat
+		 * value which we won't easily be able to recreate later.
+		 */
+
+		.macro test_for_ipi, irqnr, irqstat, base, tmp
+		bic	\irqnr, \irqstat, #0x1c00
+		cmp	\irqnr, #16
+		it	cc
+		strcc	\irqstat, [\base, #GIC_CPU_EOI]
+		it	cs
+		cmpcs	\irqnr, \irqnr
+		.endm
+
+		/* As above, this assumes that irqstat and base are preserved */
+
+		.macro test_for_ltirq, irqnr, irqstat, base, tmp
+		bic	\irqnr, \irqstat, #0x1c00
+		mov 	\tmp, #0
+		cmp	\irqnr, #29
+		itt	eq
+		moveq	\tmp, #1
+		streq	\irqstat, [\base, #GIC_CPU_EOI]
+		cmp	\tmp, #0
+		.endm
+#endif	/* CONFIG_SMP */
 
 #else	/* MULTI_OMAP2 */
 
@@ -141,74 +142,16 @@ omap_irq_base:	.word	0
 
 
 #ifdef CONFIG_ARCH_OMAP4
+#define HAVE_GET_IRQNR_PREAMBLE
+#include <asm/hardware/entry-macro-gic.S>
 
 		.macro  get_irqnr_preamble, base, tmp
 		ldr     \base, =OMAP4_IRQ_BASE
 		.endm
 
-		/*
-		 * The interrupt numbering scheme is defined in the
-		 * interrupt controller spec.  To wit:
-		 *
-		 * Interrupts 0-15 are IPI
-		 * 16-28 are reserved
-		 * 29-31 are local.  We allow 30 to be used for the watchdog.
-		 * 32-1020 are global
-		 * 1021-1022 are reserved
-		 * 1023 is "spurious" (no interrupt)
-		 *
-		 * For now, we ignore all local interrupts so only return an
-		 * interrupt if it's between 30 and 1020.  The test_for_ipi
-		 * routine below will pick up on IPIs.
-		 * A simple read from the controller will tell us the number
-		 * of the highest priority enabled interrupt.
-		 * We then just need to check whether it is in the
-		 * valid range for an IRQ (30-1020 inclusive).
-		 */
-		.macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
-		ldr     \irqstat, [\base, #GIC_CPU_INTACK]
-
-		ldr     \tmp, =1021
-
-		bic     \irqnr, \irqstat, #0x1c00
-
-		cmp     \irqnr, #29
-		cmpcc   \irqnr, \irqnr
-		cmpne   \irqnr, \tmp
-		cmpcs   \irqnr, \irqnr
-		.endm
 #endif
-#endif	/* MULTI_OMAP2 */
-
-#ifdef CONFIG_SMP
-		/* We assume that irqstat (the raw value of the IRQ acknowledge
-		 * register) is preserved from the macro above.
-		 * If there is an IPI, we immediately signal end of interrupt
-		 * on the controller, since this requires the original irqstat
-		 * value which we won't easily be able to recreate later.
-		 */
-
-		.macro test_for_ipi, irqnr, irqstat, base, tmp
-		bic	\irqnr, \irqstat, #0x1c00
-		cmp	\irqnr, #16
-		it	cc
-		strcc	\irqstat, [\base, #GIC_CPU_EOI]
-		it	cs
-		cmpcs	\irqnr, \irqnr
-		.endm
-
-		/* As above, this assumes that irqstat and base are preserved */
 
-		.macro test_for_ltirq, irqnr, irqstat, base, tmp
-		bic	\irqnr, \irqstat, #0x1c00
-		mov 	\tmp, #0
-		cmp	\irqnr, #29
-		itt	eq
-		moveq	\tmp, #1
-		streq	\irqstat, [\base, #GIC_CPU_EOI]
-		cmp	\tmp, #0
-		.endm
-#endif	/* CONFIG_SMP */
+#endif	/* MULTI_OMAP2 */
 
 		.macro	irq_prio_table
 		.endm
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/include/mach/omap4-common.h linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/include/mach/omap4-common.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/include/mach/omap4-common.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/include/mach/omap4-common.h	2011-03-14 21:20:32.000000000 -0400
@@ -24,7 +24,6 @@
 extern void __iomem *l2cache_base;
 #endif
 
-extern void __iomem *gic_cpu_base_addr;
 extern void __iomem *gic_dist_base_addr;
 
 extern void __init gic_init_irq(void);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/io.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/io.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/io.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/io.c	2011-03-14 21:20:32.000000000 -0400
@@ -39,13 +39,11 @@
 #include "io.h"
 
 #include <plat/omap-pm.h>
-#include <plat/powerdomain.h>
-#include "powerdomains.h"
-
-#include <plat/clockdomain.h>
-#include "clockdomains.h"
+#include "powerdomain.h"
 
+#include "clockdomain.h"
 #include <plat/omap_hwmod.h>
+#include <plat/multi.h>
 
 /*
  * The machine specific code may provide the extra mapping besides the
@@ -311,24 +309,79 @@ static int __init _omap2_init_reprogram_
 	return v;
 }
 
-void __init omap2_init_common_hw(struct omap_sdrc_params *sdrc_cs0,
-				 struct omap_sdrc_params *sdrc_cs1)
+static int _set_hwmod_postsetup_state(struct omap_hwmod *oh, void *data)
 {
-	u8 skip_setup_idle = 0;
+	return omap_hwmod_set_postsetup_state(oh, *(u8 *)data);
+}
 
-	pwrdm_init(powerdomains_omap);
-	clkdm_init(clockdomains_omap, clkdm_autodeps);
-	if (cpu_is_omap242x())
+void __iomem *omap_irq_base;
+
+/*
+ * Initialize asm_irq_base for entry-macro.S
+ */
+static inline void omap_irq_base_init(void)
+{
+	if (cpu_is_omap24xx())
+		omap_irq_base = OMAP2_L4_IO_ADDRESS(OMAP24XX_IC_BASE);
+	else if (cpu_is_omap34xx())
+		omap_irq_base = OMAP2_L4_IO_ADDRESS(OMAP34XX_IC_BASE);
+	else if (cpu_is_omap44xx())
+		omap_irq_base = OMAP2_L4_IO_ADDRESS(OMAP44XX_GIC_CPU_BASE);
+	else
+		pr_err("Could not initialize omap_irq_base\n");
+}
+
+void __init omap2_init_common_infrastructure(void)
+{
+	u8 postsetup_state;
+
+	if (cpu_is_omap242x()) {
+		omap2xxx_powerdomains_init();
+		omap2_clockdomains_init();
 		omap2420_hwmod_init();
-	else if (cpu_is_omap243x())
+	} else if (cpu_is_omap243x()) {
+		omap2xxx_powerdomains_init();
+		omap2_clockdomains_init();
 		omap2430_hwmod_init();
-	else if (cpu_is_omap34xx())
+	} else if (cpu_is_omap34xx()) {
+		omap3xxx_powerdomains_init();
+		omap2_clockdomains_init();
 		omap3xxx_hwmod_init();
-	else if (cpu_is_omap44xx())
+	} 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");
+        }
 
-	/* The OPP tables have to be registered before a clk init */
-	omap_pm_if_early_init(mpu_opps, dsp_opps, l3_opps);
+	/* Set the default postsetup state for all hwmods */
+#ifdef CONFIG_PM_RUNTIME
+	postsetup_state = _HWMOD_STATE_IDLE;
+#else
+	postsetup_state = _HWMOD_STATE_ENABLED;
+#endif
+	omap_hwmod_for_each(_set_hwmod_postsetup_state, &postsetup_state);
+
+	/*
+	 * Set the default postsetup state for unusual modules (like
+	 * MPU WDT).
+	 *
+	 * The postsetup_state is not actually used until
+	 * 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().
+	 *
+	 * XXX ideally we could detect whether the MPU WDT was currently
+	 * enabled here and make this conditional
+	 */
+	postsetup_state = _HWMOD_STATE_DISABLED;
+	omap_hwmod_for_each_by_class("wd_timer",
+				     _set_hwmod_postsetup_state,
+				     &postsetup_state);
+
+	omap_pm_if_early_init();
 
 	if (cpu_is_omap2420())
 		omap2420_clk_init();
@@ -339,17 +392,61 @@ void __init omap2_init_common_hw(struct
 	else if (cpu_is_omap44xx())
 		omap4xxx_clk_init();
 	else
-		pr_err("Could not init clock framework - unknown CPU\n");
+		pr_err("Could not init clock framework - unknown SoC\n");
+}
 
+void __init omap2_init_common_devices(struct omap_sdrc_params *sdrc_cs0,
+				      struct omap_sdrc_params *sdrc_cs1)
+{
 	omap_serial_early_init();
 
-#ifndef CONFIG_PM_RUNTIME
-	skip_setup_idle = 1;
-#endif
-	omap_hwmod_late_init(skip_setup_idle);
+	omap_hwmod_late_init();
+
 	if (cpu_is_omap24xx() || cpu_is_omap34xx()) {
 		omap2_sdrc_init(sdrc_cs0, sdrc_cs1);
 		_omap2_init_reprogram_sdrc();
 	}
 	gpmc_init();
+
+	omap_irq_base_init();
 }
+
+/*
+ * NOTE: Please use ioremap + __raw_read/write where possible instead of these
+ */
+
+u8 omap_readb(u32 pa)
+{
+	return __raw_readb(OMAP2_L4_IO_ADDRESS(pa));
+}
+EXPORT_SYMBOL(omap_readb);
+
+u16 omap_readw(u32 pa)
+{
+	return __raw_readw(OMAP2_L4_IO_ADDRESS(pa));
+}
+EXPORT_SYMBOL(omap_readw);
+
+u32 omap_readl(u32 pa)
+{
+	return __raw_readl(OMAP2_L4_IO_ADDRESS(pa));
+}
+EXPORT_SYMBOL(omap_readl);
+
+void omap_writeb(u8 v, u32 pa)
+{
+	__raw_writeb(v, OMAP2_L4_IO_ADDRESS(pa));
+}
+EXPORT_SYMBOL(omap_writeb);
+
+void omap_writew(u16 v, u32 pa)
+{
+	__raw_writew(v, OMAP2_L4_IO_ADDRESS(pa));
+}
+EXPORT_SYMBOL(omap_writew);
+
+void omap_writel(u32 v, u32 pa)
+{
+	__raw_writel(v, OMAP2_L4_IO_ADDRESS(pa));
+}
+EXPORT_SYMBOL(omap_writel);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/irq.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/irq.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/irq.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/irq.c	2011-03-14 21:20:32.000000000 -0400
@@ -100,13 +100,14 @@ static int omap_check_spurious(unsigned
 }
 
 /* XXX: FIQ and additional INTC support (only MPU at the moment) */
-static void omap_ack_irq(unsigned int irq)
+static void omap_ack_irq(struct irq_data *d)
 {
 	intc_bank_write_reg(0x1, &irq_banks[0], INTC_CONTROL);
 }
 
-static void omap_mask_irq(unsigned int irq)
+static void omap_mask_irq(struct irq_data *d)
 {
+	unsigned int irq = d->irq;
 	int offset = irq & (~(IRQ_BITS_PER_REG - 1));
 
 	if (cpu_is_omap34xx()) {
@@ -128,8 +129,9 @@ static void omap_mask_irq(unsigned int i
 	intc_bank_write_reg(1 << irq, &irq_banks[0], INTC_MIR_SET0 + offset);
 }
 
-static void omap_unmask_irq(unsigned int irq)
+static void omap_unmask_irq(struct irq_data *d)
 {
+	unsigned int irq = d->irq;
 	int offset = irq & (~(IRQ_BITS_PER_REG - 1));
 
 	irq &= (IRQ_BITS_PER_REG - 1);
@@ -137,17 +139,17 @@ static void omap_unmask_irq(unsigned int
 	intc_bank_write_reg(1 << irq, &irq_banks[0], INTC_MIR_CLEAR0 + offset);
 }
 
-static void omap_mask_ack_irq(unsigned int irq)
+static void omap_mask_ack_irq(struct irq_data *d)
 {
-	omap_mask_irq(irq);
-	omap_ack_irq(irq);
+	omap_mask_irq(d);
+	omap_ack_irq(d);
 }
 
 static struct irq_chip omap_irq_chip = {
-	.name	= "INTC",
-	.ack	= omap_mask_ack_irq,
-	.mask	= omap_mask_irq,
-	.unmask	= omap_unmask_irq,
+	.name		= "INTC",
+	.irq_ack	= omap_mask_ack_irq,
+	.irq_mask	= omap_mask_irq,
+	.irq_unmask	= omap_unmask_irq,
 };
 
 static void __init omap_irq_bank_init_one(struct omap_irq_bank *bank)
@@ -284,7 +286,10 @@ void omap3_intc_suspend(void)
 
 void omap3_intc_prepare_idle(void)
 {
-	/* Disable autoidle as it can stall interrupt controller */
+	/*
+	 * Disable autoidle as it can stall interrupt controller,
+	 * cf. errata ID i540 for 3430 (all revisions up to 3.1.x)
+	 */
 	intc_bank_write_reg(0, &irq_banks[0], INTC_SYSCONFIG);
 }
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/Kconfig linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/Kconfig
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -15,7 +15,7 @@ config ARCH_OMAP2PLUS_TYPICAL
 	select SERIAL_OMAP_CONSOLE
 	select I2C
 	select I2C_OMAP
-	select MFD
+	select MFD_SUPPORT
 	select MENELAUS if ARCH_OMAP2
 	select TWL4030_CORE if ARCH_OMAP3 || ARCH_OMAP4
 	select TWL4030_POWER if ARCH_OMAP3 || ARCH_OMAP4
@@ -35,6 +35,8 @@ config ARCH_OMAP3
 	select CPU_V7
 	select USB_ARCH_HAS_EHCI
 	select ARM_L1_CACHE_SHIFT_6 if !ARCH_OMAP4
+	select ARCH_HAS_OPP
+	select PM_OPP if PM
 
 config ARCH_OMAP4
 	bool "TI OMAP4"
@@ -44,6 +46,9 @@ config ARCH_OMAP4
 	select ARM_GIC
 	select PL310_ERRATA_588369
 	select ARM_ERRATA_720789
+	select ARCH_HAS_OPP
+	select PM_OPP if PM
+	select USB_ARCH_HAS_EHCI
 
 comment "OMAP Core Type"
 	depends on ARCH_OMAP2
@@ -85,6 +90,12 @@ config OMAP_PACKAGE_CUS
 config OMAP_PACKAGE_CBP
        bool
 
+config OMAP_PACKAGE_CBL
+       bool
+
+config OMAP_PACKAGE_CBS
+       bool
+
 comment "OMAP Board Type"
 	depends on ARCH_OMAP2PLUS
 
@@ -128,7 +139,6 @@ config MACH_DEVKIT8000
 	depends on ARCH_OMAP3
 	default y
 	select OMAP_PACKAGE_CUS
-	select OMAP_MUX
 
 config MACH_OMAP_LDP
 	bool "OMAP3 LDP board"
@@ -174,11 +184,17 @@ config MACH_OMAP3517EVM
 	default y
 	select OMAP_PACKAGE_CBB
 
+config MACH_CRANEBOARD
+	bool "AM3517/05 CRANE board"
+	depends on ARCH_OMAP3
+	select OMAP_PACKAGE_CBB
+
 config MACH_OMAP3_PANDORA
 	bool "OMAP3 Pandora"
 	depends on ARCH_OMAP3
 	default y
 	select OMAP_PACKAGE_CBB
+	select REGULATOR_FIXED_VOLTAGE
 
 config MACH_OMAP3_TOUCHBOOK
 	bool "OMAP3 Touch Book"
@@ -210,6 +226,12 @@ config MACH_NOKIA_N8X0
 	select MACH_NOKIA_N810
 	select MACH_NOKIA_N810_WIMAX
 
+config MACH_NOKIA_RM680
+	bool "Nokia RM-680 board"
+	depends on ARCH_OMAP3
+	default y
+	select OMAP_PACKAGE_CBB
+
 config MACH_NOKIA_RX51
 	bool "Nokia RX-51 board"
 	depends on ARCH_OMAP3
@@ -224,6 +246,7 @@ config MACH_OMAP_ZOOM2
 	select SERIAL_8250
 	select SERIAL_CORE_CONSOLE
 	select SERIAL_8250_CONSOLE
+	select REGULATOR_FIXED_VOLTAGE
 
 config MACH_OMAP_ZOOM3
 	bool "OMAP3630 Zoom3 board"
@@ -233,20 +256,19 @@ config MACH_OMAP_ZOOM3
 	select SERIAL_8250
 	select SERIAL_CORE_CONSOLE
 	select SERIAL_8250_CONSOLE
+	select REGULATOR_FIXED_VOLTAGE
 
 config MACH_CM_T35
 	bool "CompuLab CM-T35 module"
 	depends on ARCH_OMAP3
 	default y
 	select OMAP_PACKAGE_CUS
-	select OMAP_MUX
 
 config MACH_CM_T3517
 	bool "CompuLab CM-T3517 module"
 	depends on ARCH_OMAP3
 	default y
 	select OMAP_PACKAGE_CBB
-	select OMAP_MUX
 
 config MACH_IGEP0020
 	bool "IGEP v2 board"
@@ -265,7 +287,6 @@ config MACH_SBC3530
 	depends on ARCH_OMAP3
 	default y
 	select OMAP_PACKAGE_CUS
-	select OMAP_MUX
 
 config MACH_OMAP_3630SDP
 	bool "OMAP3630 SDP board"
@@ -277,11 +298,15 @@ config MACH_OMAP_4430SDP
 	bool "OMAP 4430 SDP board"
 	default y
 	depends on ARCH_OMAP4
+	select OMAP_PACKAGE_CBL
+	select OMAP_PACKAGE_CBS
 
 config MACH_OMAP4_PANDA
 	bool "OMAP4 Panda Board"
 	default y
 	depends on ARCH_OMAP4
+	select OMAP_PACKAGE_CBL
+	select OMAP_PACKAGE_CBS
 
 config OMAP3_EMU
 	bool "OMAP3 debugging peripherals"
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/mailbox.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/mailbox.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/mailbox.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/mailbox.c	2011-03-14 21:20:32.000000000 -0400
@@ -193,10 +193,12 @@ static void omap2_mbox_disable_irq(struc
 		omap_mbox_type_t irq)
 {
 	struct omap_mbox2_priv *p = mbox->priv;
-	u32 l, bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit;
-	l = mbox_read_reg(p->irqdisable);
-	l &= ~bit;
-	mbox_write_reg(l, p->irqdisable);
+	u32 bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit;
+
+	if (!cpu_is_omap44xx())
+		bit = mbox_read_reg(p->irqdisable) & ~bit;
+
+	mbox_write_reg(bit, p->irqdisable);
 }
 
 static void omap2_mbox_ack_irq(struct omap_mbox *mbox,
@@ -281,7 +283,7 @@ static struct omap_mbox_ops omap2_mbox_o
 
 /* FIXME: the following structs should be filled automatically by the user id */
 
-#if defined(CONFIG_ARCH_OMAP3430) || defined(CONFIG_ARCH_OMAP2420)
+#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_ARCH_OMAP2)
 /* DSP */
 static struct omap_mbox2_priv omap2_mbox_dsp_priv = {
 	.tx_fifo = {
@@ -306,7 +308,7 @@ struct omap_mbox mbox_dsp_info = {
 };
 #endif
 
-#if defined(CONFIG_ARCH_OMAP3430)
+#if defined(CONFIG_ARCH_OMAP3)
 struct omap_mbox *omap3_mboxes[] = { &mbox_dsp_info, NULL };
 #endif
 
@@ -334,7 +336,7 @@ static struct omap_mbox mbox_iva_info =
 	.priv	= &omap2_mbox_iva_priv,
 };
 
-struct omap_mbox *omap2_mboxes[] = { &mbox_iva_info, &mbox_dsp_info, NULL };
+struct omap_mbox *omap2_mboxes[] = { &mbox_dsp_info, &mbox_iva_info, NULL };
 #endif
 
 #if defined(CONFIG_ARCH_OMAP4)
@@ -394,15 +396,19 @@ static int __devinit omap2_mbox_probe(st
 
 	if (false)
 		;
-#if defined(CONFIG_ARCH_OMAP3430)
-	else if (cpu_is_omap3430()) {
+#if defined(CONFIG_ARCH_OMAP3)
+	else if (cpu_is_omap34xx()) {
 		list = omap3_mboxes;
 
 		list[0]->irq = platform_get_irq_byname(pdev, "dsp");
 	}
 #endif
-#if defined(CONFIG_ARCH_OMAP2420)
-	else if (cpu_is_omap2420()) {
+#if defined(CONFIG_ARCH_OMAP2)
+	else if (cpu_is_omap2430()) {
+		list = omap2_mboxes;
+
+		list[0]->irq = platform_get_irq_byname(pdev, "dsp");
+	} else if (cpu_is_omap2420()) {
 		list = omap2_mboxes;
 
 		list[0]->irq = platform_get_irq_byname(pdev, "dsp");
@@ -432,9 +438,8 @@ static int __devinit omap2_mbox_probe(st
 		iounmap(mbox_base);
 		return ret;
 	}
-	return 0;
 
-	return ret;
+	return 0;
 }
 
 static int __devexit omap2_mbox_remove(struct platform_device *pdev)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/Makefile linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/Makefile
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -4,30 +4,31 @@
 
 # Common support
 obj-y := id.o io.o control.o mux.o devices.o serial.o gpmc.o timer-gp.o pm.o \
-	 common.o
+	 common.o gpio.o dma.o wd_timer.o
 
-omap-2-3-common				= irq.o sdrc.o prm2xxx_3xxx.o
+omap-2-3-common				= irq.o sdrc.o
 hwmod-common				= omap_hwmod.o \
 					  omap_hwmod_common_data.o
-prcm-common				= prcm.o powerdomain.o
 clock-common				= clock.o clock_common_data.o \
-					  clockdomain.o clkt_dpll.o \
-					  clkt_clksel.o
+					  clkt_dpll.o clkt_clksel.o
 
-obj-$(CONFIG_ARCH_OMAP2) += $(omap-2-3-common) $(prcm-common) $(hwmod-common)
-obj-$(CONFIG_ARCH_OMAP3) += $(omap-2-3-common) $(prcm-common) $(hwmod-common)
-obj-$(CONFIG_ARCH_OMAP4) += $(prcm-common) prm44xx.o $(hwmod-common)
+obj-$(CONFIG_ARCH_OMAP2) += $(omap-2-3-common) $(hwmod-common)
+obj-$(CONFIG_ARCH_OMAP3) += $(omap-2-3-common) $(hwmod-common)
+obj-$(CONFIG_ARCH_OMAP4) += prm44xx.o $(hwmod-common)
 
 obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o
 
+obj-$(CONFIG_TWL4030_CORE) += omap_twl.o
+
 # SMP support ONLY available for OMAP4
 obj-$(CONFIG_SMP)			+= omap-smp.o omap-headsmp.o
 obj-$(CONFIG_LOCAL_TIMERS)		+= timer-mpu.o
 obj-$(CONFIG_HOTPLUG_CPU)		+= omap-hotplug.o
 obj-$(CONFIG_ARCH_OMAP4)		+= omap44xx-smc.o omap4-common.o
 
-AFLAGS_omap-headsmp.o			:=-Wa,-march=armv7-a
-AFLAGS_omap44xx-smc.o			:=-Wa,-march=armv7-a
+plus_sec := $(call as-instr,.arch_extension sec,+sec)
+AFLAGS_omap-headsmp.o			:=-Wa,-march=armv7-a$(plus_sec)
+AFLAGS_omap44xx-smc.o			:=-Wa,-march=armv7-a$(plus_sec)
 
 # Functions loaded to SRAM
 obj-$(CONFIG_ARCH_OMAP2420)		+= sram242x.o
@@ -42,18 +43,29 @@ AFLAGS_sram34xx.o			:=-Wa,-march=armv7-a
 obj-$(CONFIG_ARCH_OMAP2420)		+= mux2420.o
 obj-$(CONFIG_ARCH_OMAP2430)		+= mux2430.o
 obj-$(CONFIG_ARCH_OMAP3)		+= mux34xx.o
+obj-$(CONFIG_ARCH_OMAP4)		+= mux44xx.o
 
 # SMS/SDRC
 obj-$(CONFIG_ARCH_OMAP2)		+= sdrc2xxx.o
 # obj-$(CONFIG_ARCH_OMAP3)		+= sdrc3xxx.o
 
+# OPP table initialization
+ifeq ($(CONFIG_PM_OPP),y)
+obj-y					+= opp.o
+obj-$(CONFIG_ARCH_OMAP3)		+= opp3xxx_data.o
+obj-$(CONFIG_ARCH_OMAP4)		+= opp4xxx_data.o
+endif
+
 # Power Management
 ifeq ($(CONFIG_PM),y)
 obj-$(CONFIG_ARCH_OMAP2)		+= pm24xx.o
-obj-$(CONFIG_ARCH_OMAP2)		+= sleep24xx.o pm_bus.o
-obj-$(CONFIG_ARCH_OMAP3)		+= pm34xx.o sleep34xx.o cpuidle34xx.o pm_bus.o
-obj-$(CONFIG_ARCH_OMAP4)		+= pm44xx.o pm_bus.o
+obj-$(CONFIG_ARCH_OMAP2)		+= sleep24xx.o pm_bus.o voltage.o
+obj-$(CONFIG_ARCH_OMAP3)		+= pm34xx.o sleep34xx.o voltage.o \
+					   cpuidle34xx.o pm_bus.o
+obj-$(CONFIG_ARCH_OMAP4)		+= pm44xx.o voltage.o pm_bus.o
 obj-$(CONFIG_PM_DEBUG)			+= pm-debug.o
+obj-$(CONFIG_OMAP_SMARTREFLEX)          += sr_device.o smartreflex.o
+obj-$(CONFIG_OMAP_SMARTREFLEX_CLASS3)	+= smartreflex-class3.o
 
 AFLAGS_sleep24xx.o			:=-Wa,-march=armv6
 AFLAGS_sleep34xx.o			:=-Wa,-march=armv7-a
@@ -65,10 +77,36 @@ endif
 endif
 
 # PRCM
-obj-$(CONFIG_ARCH_OMAP2)		+= cm.o
-obj-$(CONFIG_ARCH_OMAP3)		+= cm.o
-obj-$(CONFIG_ARCH_OMAP4)		+= cm4xxx.o
+obj-$(CONFIG_ARCH_OMAP2)		+= prcm.o cm2xxx_3xxx.o prm2xxx_3xxx.o
+obj-$(CONFIG_ARCH_OMAP3)		+= prcm.o cm2xxx_3xxx.o prm2xxx_3xxx.o
+# XXX The presence of cm2xxx_3xxx.o on the line below is temporary and
+# will be removed once the OMAP4 part of the codebase is converted to
+# use OMAP4-specific PRCM functions.
+obj-$(CONFIG_ARCH_OMAP4)		+= prcm.o cm2xxx_3xxx.o cminst44xx.o \
+					   cm44xx.o prcm_mpu44xx.o \
+					   prminst44xx.o
 
+# OMAP powerdomain framework
+powerdomain-common			+= powerdomain.o powerdomain-common.o
+obj-$(CONFIG_ARCH_OMAP2)		+= $(powerdomain-common) \
+					   powerdomain2xxx_3xxx.o \
+					   powerdomains2xxx_data.o \
+					   powerdomains2xxx_3xxx_data.o
+obj-$(CONFIG_ARCH_OMAP3)		+= $(powerdomain-common) \
+					   powerdomain2xxx_3xxx.o \
+					   powerdomains3xxx_data.o \
+					   powerdomains2xxx_3xxx_data.o
+obj-$(CONFIG_ARCH_OMAP4)		+= $(powerdomain-common) \
+					   powerdomain44xx.o \
+					   powerdomains44xx_data.o
+
+# PRCM clockdomain control
+obj-$(CONFIG_ARCH_OMAP2)		+= clockdomain.o \
+					   clockdomains2xxx_3xxx_data.o
+obj-$(CONFIG_ARCH_OMAP3)		+= clockdomain.o \
+					   clockdomains2xxx_3xxx_data.o
+obj-$(CONFIG_ARCH_OMAP4)		+= clockdomain.o \
+					   clockdomains44xx_data.o
 # Clock framework
 obj-$(CONFIG_ARCH_OMAP2)		+= $(clock-common) clock2xxx.o \
 					   clkt2xxx_sys.o \
@@ -139,23 +177,29 @@ obj-$(CONFIG_MACH_OMAP_3430SDP)		+= boar
 					   hsmmc.o \
 					   board-flash.o
 obj-$(CONFIG_MACH_NOKIA_N8X0)		+= board-n8x0.o
+obj-$(CONFIG_MACH_NOKIA_RM680)		+= board-rm680.o \
+					   sdram-nokia.o \
+					   hsmmc.o
 obj-$(CONFIG_MACH_NOKIA_RX51)		+= board-rx51.o \
-					   board-rx51-sdram.o \
+					   sdram-nokia.o \
 					   board-rx51-peripherals.o \
 					   board-rx51-video.o \
 					   hsmmc.o
-obj-$(CONFIG_MACH_OMAP_ZOOM2)		+= board-zoom2.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-zoom3.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 \
@@ -168,12 +212,16 @@ obj-$(CONFIG_MACH_IGEP0030)		+= board-ig
 obj-$(CONFIG_MACH_OMAP3_TOUCHBOOK)	+= board-omap3touchbook.o \
 					   hsmmc.o
 obj-$(CONFIG_MACH_OMAP_4430SDP)		+= board-4430sdp.o \
-					   hsmmc.o
+					   hsmmc.o \
+					   omap_phy_internal.o
 obj-$(CONFIG_MACH_OMAP4_PANDA)		+= board-omap4panda.o \
-					   hsmmc.o
+					   hsmmc.o \
+					   omap_phy_internal.o
 
 obj-$(CONFIG_MACH_OMAP3517EVM)		+= board-am3517evm.o
 
+obj-$(CONFIG_MACH_CRANEBOARD)		+= board-am3517crane.o
+
 obj-$(CONFIG_MACH_SBC3530)		+= board-omap3stalker.o \
 					   hsmmc.o
 # Platform specific device init code
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/mux2420.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/mux2420.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/mux2420.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/mux2420.c	2011-03-14 21:20:32.000000000 -0400
@@ -678,11 +678,13 @@ int __init omap2420_mux_init(struct omap
 	case OMAP_PACKAGE_ZAF:
 		/* REVISIT: Please add data */
 	default:
-		pr_warning("mux: No ball data available for omap2420 package\n");
+		pr_warning("%s: No ball data available for omap2420 package\n",
+				__func__);
 	}
 
-	return omap_mux_init(OMAP2420_CONTROL_PADCONF_MUX_PBASE,
+	return omap_mux_init("core", OMAP_MUX_REG_8BIT | OMAP_MUX_GPIO_IN_MODE3,
+			     OMAP2420_CONTROL_PADCONF_MUX_PBASE,
 			     OMAP2420_CONTROL_PADCONF_MUX_SIZE,
-				omap2420_muxmodes, NULL, board_subset,
-				package_balls);
+			     omap2420_muxmodes, NULL, board_subset,
+			     package_balls);
 }
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/mux2430.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/mux2430.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/mux2430.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/mux2430.c	2011-03-14 21:20:32.000000000 -0400
@@ -781,11 +781,13 @@ int __init omap2430_mux_init(struct omap
 		package_balls = omap2430_pop_ball;
 		break;
 	default:
-		pr_warning("mux: No ball data available for omap2420 package\n");
+		pr_warning("%s: No ball data available for omap2420 package\n",
+				__func__);
 	}
 
-	return omap_mux_init(OMAP2430_CONTROL_PADCONF_MUX_PBASE,
+	return omap_mux_init("core", OMAP_MUX_REG_8BIT | OMAP_MUX_GPIO_IN_MODE3,
+			     OMAP2430_CONTROL_PADCONF_MUX_PBASE,
 			     OMAP2430_CONTROL_PADCONF_MUX_SIZE,
-				omap2430_muxmodes, NULL, board_subset,
-				package_balls);
+			     omap2430_muxmodes, NULL, board_subset,
+			     package_balls);
 }
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/mux34xx.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/mux34xx.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/mux34xx.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/mux34xx.c	2011-03-14 21:20:32.000000000 -0400
@@ -703,7 +703,7 @@ static struct omap_mux __initdata omap3_
  * Signals different on CBC package compared to the superset
  */
 #if defined(CONFIG_OMAP_MUX) && defined(CONFIG_OMAP_PACKAGE_CBC)
-struct omap_mux __initdata omap3_cbc_subset[] = {
+static struct omap_mux __initdata omap3_cbc_subset[] = {
 	{ .reg_offset = OMAP_MUX_TERMINATOR },
 };
 #else
@@ -721,7 +721,7 @@ struct omap_mux __initdata omap3_cbc_sub
  */
 #if defined(CONFIG_OMAP_MUX) && defined(CONFIG_DEBUG_FS)	\
 		&& defined(CONFIG_OMAP_PACKAGE_CBC)
-struct omap_ball __initdata omap3_cbc_ball[] = {
+static struct omap_ball __initdata omap3_cbc_ball[] = {
 	_OMAP3_BALLENTRY(CAM_D0, "ae16", NULL),
 	_OMAP3_BALLENTRY(CAM_D1, "ae15", NULL),
 	_OMAP3_BALLENTRY(CAM_D10, "d25", NULL),
@@ -2049,12 +2049,13 @@ int __init omap3_mux_init(struct omap_bo
 		package_balls = omap36xx_cbp_ball;
 		break;
 	default:
-		printk(KERN_ERR "mux: Unknown omap package, mux disabled\n");
+		pr_err("%s Unknown omap package, mux disabled\n", __func__);
 		return -EINVAL;
 	}
 
-	return omap_mux_init(OMAP3_CONTROL_PADCONF_MUX_PBASE,
+	return omap_mux_init("core", 0,
+			     OMAP3_CONTROL_PADCONF_MUX_PBASE,
 			     OMAP3_CONTROL_PADCONF_MUX_SIZE,
-				omap3_muxmodes, package_subset, board_subset,
-				package_balls);
+			     omap3_muxmodes, package_subset, board_subset,
+			     package_balls);
 }
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/mux44xx.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/mux44xx.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/mux44xx.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/mux44xx.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,1625 @@
+/*
+ * OMAP44xx ES1.0 pin mux definition
+ *
+ * Copyright (C) 2010 Texas Instruments, Inc.
+ *
+ * Benoit Cousson (b-cousson@ti.com)
+ *
+ * - Based on mux34xx.c done by Tony Lindgren <tony@atomide.com>
+ *
+ * This file is automatically generated from the OMAP hardware databases.
+ * We respectfully ask that any modifications to this file be coordinated
+ * with the public linux-omap@vger.kernel.org mailing list and the
+ * authors above to ensure that the autogeneration scripts are kept
+ * up-to-date with the file contents.
+ *
+ * This program is free software; you can 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 "mux.h"
+
+#ifdef CONFIG_OMAP_MUX
+
+#define _OMAP4_MUXENTRY(M0, g, m0, m1, m2, m3, m4, m5, m6, m7)	\
+{									\
+	.reg_offset	= (OMAP4_CTRL_MODULE_PAD_##M0##_OFFSET),	\
+	.gpio		= (g),						\
+	.muxnames	= { m0, m1, m2, m3, m4, m5, m6, m7 },		\
+}
+
+#else
+
+#define _OMAP4_MUXENTRY(M0, g, m0, m1, m2, m3, m4, m5, m6, m7)	\
+{									\
+	.reg_offset	= (OMAP4_CTRL_MODULE_PAD_##M0##_OFFSET),	\
+	.gpio		= (g),						\
+}
+
+#endif
+
+#define _OMAP4_BALLENTRY(M0, bb, bt)				\
+{									\
+	.reg_offset	= (OMAP4_CTRL_MODULE_PAD_##M0##_OFFSET),	\
+	.balls		= { bb, bt },					\
+}
+
+/*
+ * Superset of all mux modes for omap4 ES1.0
+ */
+static struct omap_mux __initdata omap4_core_muxmodes[] = {
+	_OMAP4_MUXENTRY(GPMC_AD0, 0, "gpmc_ad0", "sdmmc2_dat0", NULL, NULL,
+			NULL, NULL, NULL, NULL),
+	_OMAP4_MUXENTRY(GPMC_AD1, 0, "gpmc_ad1", "sdmmc2_dat1", NULL, NULL,
+			NULL, NULL, NULL, NULL),
+	_OMAP4_MUXENTRY(GPMC_AD2, 0, "gpmc_ad2", "sdmmc2_dat2", NULL, NULL,
+			NULL, NULL, NULL, NULL),
+	_OMAP4_MUXENTRY(GPMC_AD3, 0, "gpmc_ad3", "sdmmc2_dat3", NULL, NULL,
+			NULL, NULL, NULL, NULL),
+	_OMAP4_MUXENTRY(GPMC_AD4, 0, "gpmc_ad4", "sdmmc2_dat4",
+			"sdmmc2_dir_dat0", NULL, NULL, NULL, NULL, NULL),
+	_OMAP4_MUXENTRY(GPMC_AD5, 0, "gpmc_ad5", "sdmmc2_dat5",
+			"sdmmc2_dir_dat1", NULL, NULL, NULL, NULL, NULL),
+	_OMAP4_MUXENTRY(GPMC_AD6, 0, "gpmc_ad6", "sdmmc2_dat6",
+			"sdmmc2_dir_cmd", NULL, NULL, NULL, NULL, NULL),
+	_OMAP4_MUXENTRY(GPMC_AD7, 0, "gpmc_ad7", "sdmmc2_dat7",
+			"sdmmc2_clk_fdbk", NULL, NULL, NULL, NULL, NULL),
+	_OMAP4_MUXENTRY(GPMC_AD8, 32, "gpmc_ad8", "kpd_row0", "c2c_data15",
+			"gpio_32", NULL, NULL, NULL, NULL),
+	_OMAP4_MUXENTRY(GPMC_AD9, 33, "gpmc_ad9", "kpd_row1", "c2c_data14",
+			"gpio_33", NULL, NULL, NULL, NULL),
+	_OMAP4_MUXENTRY(GPMC_AD10, 34, "gpmc_ad10", "kpd_row2", "c2c_data13",
+			"gpio_34", NULL, NULL, NULL, NULL),
+	_OMAP4_MUXENTRY(GPMC_AD11, 35, "gpmc_ad11", "kpd_row3", "c2c_data12",
+			"gpio_35", NULL, NULL, NULL, NULL),
+	_OMAP4_MUXENTRY(GPMC_AD12, 36, "gpmc_ad12", "kpd_col0", "c2c_data11",
+			"gpio_36", NULL, NULL, NULL, NULL),
+	_OMAP4_MUXENTRY(GPMC_AD13, 37, "gpmc_ad13", "kpd_col1", "c2c_data10",
+			"gpio_37", NULL, NULL, NULL, NULL),
+	_OMAP4_MUXENTRY(GPMC_AD14, 38, "gpmc_ad14", "kpd_col2", "c2c_data9",
+			"gpio_38", NULL, NULL, NULL, NULL),
+	_OMAP4_MUXENTRY(GPMC_AD15, 39, "gpmc_ad15", "kpd_col3", "c2c_data8",
+			"gpio_39", NULL, NULL, NULL, NULL),
+	_OMAP4_MUXENTRY(GPMC_A16, 40, "gpmc_a16", "kpd_row4", "c2c_datain0",
+			"gpio_40", "venc_656_data0", NULL, NULL, NULL),
+	_OMAP4_MUXENTRY(GPMC_A17, 41, "gpmc_a17", "kpd_row5", "c2c_datain1",
+			"gpio_41", "venc_656_data1", NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(GPMC_A18, 42, "gpmc_a18", "kpd_row6", "c2c_datain2",
+			"gpio_42", "venc_656_data2", NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(GPMC_A19, 43, "gpmc_a19", "kpd_row7", "c2c_datain3",
+			"gpio_43", "venc_656_data3", NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(GPMC_A20, 44, "gpmc_a20", "kpd_col4", "c2c_datain4",
+			"gpio_44", "venc_656_data4", NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(GPMC_A21, 45, "gpmc_a21", "kpd_col5", "c2c_datain5",
+			"gpio_45", "venc_656_data5", NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(GPMC_A22, 46, "gpmc_a22", "kpd_col6", "c2c_datain6",
+			"gpio_46", "venc_656_data6", NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(GPMC_A23, 47, "gpmc_a23", "kpd_col7", "c2c_datain7",
+			"gpio_47", "venc_656_data7", NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(GPMC_A24, 48, "gpmc_a24", NULL, "c2c_clkout0",
+			"gpio_48", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(GPMC_A25, 49, "gpmc_a25", NULL, "c2c_clkout1",
+			"gpio_49", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(GPMC_NCS0, 50, "gpmc_ncs0", NULL, NULL, "gpio_50",
+			"sys_ndmareq0", NULL, NULL, NULL),
+	_OMAP4_MUXENTRY(GPMC_NCS1, 51, "gpmc_ncs1", NULL, "c2c_dataout6",
+			"gpio_51", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(GPMC_NCS2, 52, "gpmc_ncs2", NULL, "c2c_dataout7",
+			"gpio_52", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(GPMC_NCS3, 53, "gpmc_ncs3", "gpmc_dir",
+			"c2c_dataout4", "gpio_53", NULL, NULL, NULL,
+			"safe_mode"),
+	_OMAP4_MUXENTRY(GPMC_NWP, 54, "gpmc_nwp", "dsi1_te0", NULL, "gpio_54",
+			"sys_ndmareq1", NULL, NULL, NULL),
+	_OMAP4_MUXENTRY(GPMC_CLK, 55, "gpmc_clk", NULL, NULL, "gpio_55",
+			"sys_ndmareq2", NULL, NULL, NULL),
+	_OMAP4_MUXENTRY(GPMC_NADV_ALE, 56, "gpmc_nadv_ale", "dsi1_te1", NULL,
+			"gpio_56", "sys_ndmareq3", NULL, NULL, NULL),
+	_OMAP4_MUXENTRY(GPMC_NOE, 0, "gpmc_noe", "sdmmc2_clk", NULL, NULL,
+			NULL, NULL, NULL, NULL),
+	_OMAP4_MUXENTRY(GPMC_NWE, 0, "gpmc_nwe", "sdmmc2_cmd", NULL, NULL,
+			NULL, NULL, NULL, NULL),
+	_OMAP4_MUXENTRY(GPMC_NBE0_CLE, 59, "gpmc_nbe0_cle", "dsi2_te0", NULL,
+			"gpio_59", NULL, NULL, NULL, NULL),
+	_OMAP4_MUXENTRY(GPMC_NBE1, 60, "gpmc_nbe1", NULL, "c2c_dataout5",
+			"gpio_60", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(GPMC_WAIT0, 61, "gpmc_wait0", "dsi2_te1", NULL,
+			"gpio_61", NULL, NULL, NULL, NULL),
+	_OMAP4_MUXENTRY(GPMC_WAIT1, 62, "gpmc_wait1", NULL, "c2c_dataout2",
+			"gpio_62", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(C2C_DATA11, 100, "c2c_data11", "usbc1_icusb_txen",
+			"c2c_dataout3", "gpio_100", "sys_ndmareq0", NULL,
+			NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(C2C_DATA12, 101, "c2c_data12", "dsi1_te0",
+			"c2c_clkin0", "gpio_101", "sys_ndmareq1", NULL, NULL,
+			"safe_mode"),
+	_OMAP4_MUXENTRY(C2C_DATA13, 102, "c2c_data13", "dsi1_te1",
+			"c2c_clkin1", "gpio_102", "sys_ndmareq2", NULL, NULL,
+			"safe_mode"),
+	_OMAP4_MUXENTRY(C2C_DATA14, 103, "c2c_data14", "dsi2_te0",
+			"c2c_dataout0", "gpio_103", "sys_ndmareq3", NULL,
+			NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(C2C_DATA15, 104, "c2c_data15", "dsi2_te1",
+			"c2c_dataout1", "gpio_104", NULL, NULL, NULL,
+			"safe_mode"),
+	_OMAP4_MUXENTRY(HDMI_HPD, 63, "hdmi_hpd", NULL, NULL, "gpio_63", NULL,
+			NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(HDMI_CEC, 64, "hdmi_cec", NULL, NULL, "gpio_64", NULL,
+			NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(HDMI_DDC_SCL, 65, "hdmi_ddc_scl", NULL, NULL,
+			"gpio_65", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(HDMI_DDC_SDA, 66, "hdmi_ddc_sda", NULL, NULL,
+			"gpio_66", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(CSI21_DX0, 0, "csi21_dx0", NULL, NULL, "gpi_67", NULL,
+			NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(CSI21_DY0, 0, "csi21_dy0", NULL, NULL, "gpi_68", NULL,
+			NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(CSI21_DX1, 0, "csi21_dx1", NULL, NULL, "gpi_69", NULL,
+			NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(CSI21_DY1, 0, "csi21_dy1", NULL, NULL, "gpi_70", NULL,
+			NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(CSI21_DX2, 0, "csi21_dx2", NULL, NULL, "gpi_71", NULL,
+			NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(CSI21_DY2, 0, "csi21_dy2", NULL, NULL, "gpi_72", NULL,
+			NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(CSI21_DX3, 0, "csi21_dx3", NULL, NULL, "gpi_73", NULL,
+			NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(CSI21_DY3, 0, "csi21_dy3", NULL, NULL, "gpi_74", NULL,
+			NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(CSI21_DX4, 0, "csi21_dx4", NULL, NULL, "gpi_75", NULL,
+			NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(CSI21_DY4, 0, "csi21_dy4", NULL, NULL, "gpi_76", NULL,
+			NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(CSI22_DX0, 0, "csi22_dx0", NULL, NULL, "gpi_77", NULL,
+			NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(CSI22_DY0, 0, "csi22_dy0", NULL, NULL, "gpi_78", NULL,
+			NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(CSI22_DX1, 0, "csi22_dx1", NULL, NULL, "gpi_79", NULL,
+			NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(CSI22_DY1, 0, "csi22_dy1", NULL, NULL, "gpi_80", NULL,
+			NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(CAM_SHUTTER, 81, "cam_shutter", NULL, NULL, "gpio_81",
+			NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(CAM_STROBE, 82, "cam_strobe", NULL, NULL, "gpio_82",
+			NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(CAM_GLOBALRESET, 83, "cam_globalreset", NULL, NULL,
+			"gpio_83", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(USBB1_ULPITLL_CLK, 84, "usbb1_ulpitll_clk",
+			"hsi1_cawake", NULL, "gpio_84", "usbb1_ulpiphy_clk",
+			NULL, "hw_dbg20", "safe_mode"),
+	_OMAP4_MUXENTRY(USBB1_ULPITLL_STP, 85, "usbb1_ulpitll_stp",
+			"hsi1_cadata", "mcbsp4_clkr", "gpio_85",
+			"usbb1_ulpiphy_stp", "usbb1_mm_rxdp", "hw_dbg21",
+			"safe_mode"),
+	_OMAP4_MUXENTRY(USBB1_ULPITLL_DIR, 86, "usbb1_ulpitll_dir",
+			"hsi1_caflag", "mcbsp4_fsr", "gpio_86",
+			"usbb1_ulpiphy_dir", NULL, "hw_dbg22", "safe_mode"),
+	_OMAP4_MUXENTRY(USBB1_ULPITLL_NXT, 87, "usbb1_ulpitll_nxt",
+			"hsi1_acready", "mcbsp4_fsx", "gpio_87",
+			"usbb1_ulpiphy_nxt", "usbb1_mm_rxdm", "hw_dbg23",
+			"safe_mode"),
+	_OMAP4_MUXENTRY(USBB1_ULPITLL_DAT0, 88, "usbb1_ulpitll_dat0",
+			"hsi1_acwake", "mcbsp4_clkx", "gpio_88",
+			"usbb1_ulpiphy_dat0", "usbb1_mm_rxrcv", "hw_dbg24",
+			"safe_mode"),
+	_OMAP4_MUXENTRY(USBB1_ULPITLL_DAT1, 89, "usbb1_ulpitll_dat1",
+			"hsi1_acdata", "mcbsp4_dx", "gpio_89",
+			"usbb1_ulpiphy_dat1", "usbb1_mm_txse0", "hw_dbg25",
+			"safe_mode"),
+	_OMAP4_MUXENTRY(USBB1_ULPITLL_DAT2, 90, "usbb1_ulpitll_dat2",
+			"hsi1_acflag", "mcbsp4_dr", "gpio_90",
+			"usbb1_ulpiphy_dat2", "usbb1_mm_txdat", "hw_dbg26",
+			"safe_mode"),
+	_OMAP4_MUXENTRY(USBB1_ULPITLL_DAT3, 91, "usbb1_ulpitll_dat3",
+			"hsi1_caready", NULL, "gpio_91", "usbb1_ulpiphy_dat3",
+			"usbb1_mm_txen", "hw_dbg27", "safe_mode"),
+	_OMAP4_MUXENTRY(USBB1_ULPITLL_DAT4, 92, "usbb1_ulpitll_dat4",
+			"dmtimer8_pwm_evt", "abe_mcbsp3_dr", "gpio_92",
+			"usbb1_ulpiphy_dat4", NULL, "hw_dbg28", "safe_mode"),
+	_OMAP4_MUXENTRY(USBB1_ULPITLL_DAT5, 93, "usbb1_ulpitll_dat5",
+			"dmtimer9_pwm_evt", "abe_mcbsp3_dx", "gpio_93",
+			"usbb1_ulpiphy_dat5", NULL, "hw_dbg29", "safe_mode"),
+	_OMAP4_MUXENTRY(USBB1_ULPITLL_DAT6, 94, "usbb1_ulpitll_dat6",
+			"dmtimer10_pwm_evt", "abe_mcbsp3_clkx", "gpio_94",
+			"usbb1_ulpiphy_dat6", "abe_dmic_din3", "hw_dbg30",
+			"safe_mode"),
+	_OMAP4_MUXENTRY(USBB1_ULPITLL_DAT7, 95, "usbb1_ulpitll_dat7",
+			"dmtimer11_pwm_evt", "abe_mcbsp3_fsx", "gpio_95",
+			"usbb1_ulpiphy_dat7", "abe_dmic_clk3", "hw_dbg31",
+			"safe_mode"),
+	_OMAP4_MUXENTRY(USBB1_HSIC_DATA, 96, "usbb1_hsic_data", NULL, NULL,
+			"gpio_96", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(USBB1_HSIC_STROBE, 97, "usbb1_hsic_strobe", NULL,
+			NULL, "gpio_97", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(USBC1_ICUSB_DP, 98, "usbc1_icusb_dp", NULL, NULL,
+			"gpio_98", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(USBC1_ICUSB_DM, 99, "usbc1_icusb_dm", NULL, NULL,
+			"gpio_99", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(SDMMC1_CLK, 100, "sdmmc1_clk", NULL, "dpm_emu19",
+			"gpio_100", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(SDMMC1_CMD, 101, "sdmmc1_cmd", NULL, "uart1_rx",
+			"gpio_101", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(SDMMC1_DAT0, 102, "sdmmc1_dat0", NULL, "dpm_emu18",
+			"gpio_102", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(SDMMC1_DAT1, 103, "sdmmc1_dat1", NULL, "dpm_emu17",
+			"gpio_103", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(SDMMC1_DAT2, 104, "sdmmc1_dat2", NULL, "dpm_emu16",
+			"gpio_104", "jtag_tms_tmsc", NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(SDMMC1_DAT3, 105, "sdmmc1_dat3", NULL, "dpm_emu15",
+			"gpio_105", "jtag_tck", NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(SDMMC1_DAT4, 106, "sdmmc1_dat4", NULL, NULL,
+			"gpio_106", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(SDMMC1_DAT5, 107, "sdmmc1_dat5", NULL, NULL,
+			"gpio_107", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(SDMMC1_DAT6, 108, "sdmmc1_dat6", NULL, NULL,
+			"gpio_108", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(SDMMC1_DAT7, 109, "sdmmc1_dat7", NULL, NULL,
+			"gpio_109", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(ABE_MCBSP2_CLKX, 110, "abe_mcbsp2_clkx", "mcspi2_clk",
+			"abe_mcasp_ahclkx", "gpio_110", "usbb2_mm_rxdm",
+			NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(ABE_MCBSP2_DR, 111, "abe_mcbsp2_dr", "mcspi2_somi",
+			"abe_mcasp_axr", "gpio_111", "usbb2_mm_rxdp", NULL,
+			NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(ABE_MCBSP2_DX, 112, "abe_mcbsp2_dx", "mcspi2_simo",
+			"abe_mcasp_amute", "gpio_112", "usbb2_mm_rxrcv", NULL,
+			NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(ABE_MCBSP2_FSX, 113, "abe_mcbsp2_fsx", "mcspi2_cs0",
+			"abe_mcasp_afsx", "gpio_113", "usbb2_mm_txen", NULL,
+			NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(ABE_MCBSP1_CLKX, 114, "abe_mcbsp1_clkx",
+			"abe_slimbus1_clock", NULL, "gpio_114", NULL, NULL,
+			NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(ABE_MCBSP1_DR, 115, "abe_mcbsp1_dr",
+			"abe_slimbus1_data", NULL, "gpio_115", NULL, NULL,
+			NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(ABE_MCBSP1_DX, 116, "abe_mcbsp1_dx", "sdmmc3_dat2",
+			"abe_mcasp_aclkx", "gpio_116", NULL, NULL, NULL,
+			"safe_mode"),
+	_OMAP4_MUXENTRY(ABE_MCBSP1_FSX, 117, "abe_mcbsp1_fsx", "sdmmc3_dat3",
+			"abe_mcasp_amutein", "gpio_117", NULL, NULL, NULL,
+			"safe_mode"),
+	_OMAP4_MUXENTRY(ABE_PDM_UL_DATA, 0, "abe_pdm_ul_data",
+			"abe_mcbsp3_dr", NULL, NULL, NULL, NULL, NULL,
+			"safe_mode"),
+	_OMAP4_MUXENTRY(ABE_PDM_DL_DATA, 0, "abe_pdm_dl_data",
+			"abe_mcbsp3_dx", NULL, NULL, NULL, NULL, NULL,
+			"safe_mode"),
+	_OMAP4_MUXENTRY(ABE_PDM_FRAME, 0, "abe_pdm_frame", "abe_mcbsp3_clkx",
+			NULL, NULL, NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(ABE_PDM_LB_CLK, 0, "abe_pdm_lb_clk", "abe_mcbsp3_fsx",
+			NULL, NULL, NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(ABE_CLKS, 118, "abe_clks", NULL, NULL, "gpio_118",
+			NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(ABE_DMIC_CLK1, 119, "abe_dmic_clk1", NULL, NULL,
+			"gpio_119", "usbb2_mm_txse0", NULL, NULL,
+			"safe_mode"),
+	_OMAP4_MUXENTRY(ABE_DMIC_DIN1, 120, "abe_dmic_din1", NULL, NULL,
+			"gpio_120", "usbb2_mm_txdat", NULL, NULL,
+			"safe_mode"),
+	_OMAP4_MUXENTRY(ABE_DMIC_DIN2, 121, "abe_dmic_din2", "slimbus2_clock",
+			NULL, "gpio_121", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(ABE_DMIC_DIN3, 122, "abe_dmic_din3", "slimbus2_data",
+			"abe_dmic_clk2", "gpio_122", NULL, NULL, NULL,
+			"safe_mode"),
+	_OMAP4_MUXENTRY(UART2_CTS, 123, "uart2_cts", "sdmmc3_clk", NULL,
+			"gpio_123", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(UART2_RTS, 124, "uart2_rts", "sdmmc3_cmd", NULL,
+			"gpio_124", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(UART2_RX, 125, "uart2_rx", "sdmmc3_dat0", NULL,
+			"gpio_125", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(UART2_TX, 126, "uart2_tx", "sdmmc3_dat1", NULL,
+			"gpio_126", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(HDQ_SIO, 127, "hdq_sio", "i2c3_sccb", "i2c2_sccb",
+			"gpio_127", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(I2C1_SCL, 0, "i2c1_scl", NULL, NULL, NULL, NULL, NULL,
+			NULL, NULL),
+	_OMAP4_MUXENTRY(I2C1_SDA, 0, "i2c1_sda", NULL, NULL, NULL, NULL, NULL,
+			NULL, NULL),
+	_OMAP4_MUXENTRY(I2C2_SCL, 128, "i2c2_scl", "uart1_rx", NULL,
+			"gpio_128", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(I2C2_SDA, 129, "i2c2_sda", "uart1_tx", NULL,
+			"gpio_129", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(I2C3_SCL, 130, "i2c3_scl", NULL, NULL, "gpio_130",
+			NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(I2C3_SDA, 131, "i2c3_sda", NULL, NULL, "gpio_131",
+			NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(I2C4_SCL, 132, "i2c4_scl", NULL, NULL, "gpio_132",
+			NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(I2C4_SDA, 133, "i2c4_sda", NULL, NULL, "gpio_133",
+			NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(MCSPI1_CLK, 134, "mcspi1_clk", NULL, NULL, "gpio_134",
+			NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(MCSPI1_SOMI, 135, "mcspi1_somi", NULL, NULL,
+			"gpio_135", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(MCSPI1_SIMO, 136, "mcspi1_simo", NULL, NULL,
+			"gpio_136", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(MCSPI1_CS0, 137, "mcspi1_cs0", NULL, NULL, "gpio_137",
+			NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(MCSPI1_CS1, 138, "mcspi1_cs1", "uart1_rx", NULL,
+			"gpio_138", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(MCSPI1_CS2, 139, "mcspi1_cs2", "uart1_cts",
+			"slimbus2_clock", "gpio_139", NULL, NULL, NULL,
+			"safe_mode"),
+	_OMAP4_MUXENTRY(MCSPI1_CS3, 140, "mcspi1_cs3", "uart1_rts",
+			"slimbus2_data", "gpio_140", NULL, NULL, NULL,
+			"safe_mode"),
+	_OMAP4_MUXENTRY(UART3_CTS_RCTX, 141, "uart3_cts_rctx", "uart1_tx",
+			NULL, "gpio_141", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(UART3_RTS_SD, 142, "uart3_rts_sd", NULL, NULL,
+			"gpio_142", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(UART3_RX_IRRX, 143, "uart3_rx_irrx",
+			"dmtimer8_pwm_evt", NULL, "gpio_143", NULL, NULL,
+			NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(UART3_TX_IRTX, 144, "uart3_tx_irtx",
+			"dmtimer9_pwm_evt", NULL, "gpio_144", NULL, NULL,
+			NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(SDMMC5_CLK, 145, "sdmmc5_clk", "mcspi2_clk",
+			"usbc1_icusb_dp", "gpio_145", NULL, NULL, NULL,
+			"safe_mode"),
+	_OMAP4_MUXENTRY(SDMMC5_CMD, 146, "sdmmc5_cmd", "mcspi2_simo",
+			"usbc1_icusb_dm", "gpio_146", NULL, NULL, NULL,
+			"safe_mode"),
+	_OMAP4_MUXENTRY(SDMMC5_DAT0, 147, "sdmmc5_dat0", "mcspi2_somi",
+			"usbc1_icusb_rcv", "gpio_147", NULL, NULL, NULL,
+			"safe_mode"),
+	_OMAP4_MUXENTRY(SDMMC5_DAT1, 148, "sdmmc5_dat1", NULL,
+			"usbc1_icusb_txen", "gpio_148", NULL, NULL, NULL,
+			"safe_mode"),
+	_OMAP4_MUXENTRY(SDMMC5_DAT2, 149, "sdmmc5_dat2", "mcspi2_cs1", NULL,
+			"gpio_149", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(SDMMC5_DAT3, 150, "sdmmc5_dat3", "mcspi2_cs0", NULL,
+			"gpio_150", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(MCSPI4_CLK, 151, "mcspi4_clk", "sdmmc4_clk", NULL,
+			"gpio_151", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(MCSPI4_SIMO, 152, "mcspi4_simo", "sdmmc4_cmd", NULL,
+			"gpio_152", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(MCSPI4_SOMI, 153, "mcspi4_somi", "sdmmc4_dat0", NULL,
+			"gpio_153", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(MCSPI4_CS0, 154, "mcspi4_cs0", "sdmmc4_dat3", NULL,
+			"gpio_154", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(UART4_RX, 155, "uart4_rx", "sdmmc4_dat2", NULL,
+			"gpio_155", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(UART4_TX, 156, "uart4_tx", "sdmmc4_dat1", NULL,
+			"gpio_156", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(USBB2_ULPITLL_CLK, 157, "usbb2_ulpitll_clk",
+			"usbb2_ulpiphy_clk", "sdmmc4_cmd", "gpio_157",
+			"hsi2_cawake", NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(USBB2_ULPITLL_STP, 158, "usbb2_ulpitll_stp",
+			"usbb2_ulpiphy_stp", "sdmmc4_clk", "gpio_158",
+			"hsi2_cadata", "dispc2_data23", NULL, "reserved"),
+	_OMAP4_MUXENTRY(USBB2_ULPITLL_DIR, 159, "usbb2_ulpitll_dir",
+			"usbb2_ulpiphy_dir", "sdmmc4_dat0", "gpio_159",
+			"hsi2_caflag", "dispc2_data22", NULL, "reserved"),
+	_OMAP4_MUXENTRY(USBB2_ULPITLL_NXT, 160, "usbb2_ulpitll_nxt",
+			"usbb2_ulpiphy_nxt", "sdmmc4_dat1", "gpio_160",
+			"hsi2_acready", "dispc2_data21", NULL, "reserved"),
+	_OMAP4_MUXENTRY(USBB2_ULPITLL_DAT0, 161, "usbb2_ulpitll_dat0",
+			"usbb2_ulpiphy_dat0", "sdmmc4_dat2", "gpio_161",
+			"hsi2_acwake", "dispc2_data20", NULL, "reserved"),
+	_OMAP4_MUXENTRY(USBB2_ULPITLL_DAT1, 162, "usbb2_ulpitll_dat1",
+			"usbb2_ulpiphy_dat1", "sdmmc4_dat3", "gpio_162",
+			"hsi2_acdata", "dispc2_data19", NULL, "reserved"),
+	_OMAP4_MUXENTRY(USBB2_ULPITLL_DAT2, 163, "usbb2_ulpitll_dat2",
+			"usbb2_ulpiphy_dat2", "sdmmc3_dat2", "gpio_163",
+			"hsi2_acflag", "dispc2_data18", NULL, "reserved"),
+	_OMAP4_MUXENTRY(USBB2_ULPITLL_DAT3, 164, "usbb2_ulpitll_dat3",
+			"usbb2_ulpiphy_dat3", "sdmmc3_dat1", "gpio_164",
+			"hsi2_caready", "dispc2_data15", NULL, "reserved"),
+	_OMAP4_MUXENTRY(USBB2_ULPITLL_DAT4, 165, "usbb2_ulpitll_dat4",
+			"usbb2_ulpiphy_dat4", "sdmmc3_dat0", "gpio_165",
+			"mcspi3_somi", "dispc2_data14", NULL, "reserved"),
+	_OMAP4_MUXENTRY(USBB2_ULPITLL_DAT5, 166, "usbb2_ulpitll_dat5",
+			"usbb2_ulpiphy_dat5", "sdmmc3_dat3", "gpio_166",
+			"mcspi3_cs0", "dispc2_data13", NULL, "reserved"),
+	_OMAP4_MUXENTRY(USBB2_ULPITLL_DAT6, 167, "usbb2_ulpitll_dat6",
+			"usbb2_ulpiphy_dat6", "sdmmc3_cmd", "gpio_167",
+			"mcspi3_simo", "dispc2_data12", NULL, "reserved"),
+	_OMAP4_MUXENTRY(USBB2_ULPITLL_DAT7, 168, "usbb2_ulpitll_dat7",
+			"usbb2_ulpiphy_dat7", "sdmmc3_clk", "gpio_168",
+			"mcspi3_clk", "dispc2_data11", NULL, "reserved"),
+	_OMAP4_MUXENTRY(USBB2_HSIC_DATA, 169, "usbb2_hsic_data", NULL, NULL,
+			"gpio_169", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(USBB2_HSIC_STROBE, 170, "usbb2_hsic_strobe", NULL,
+			NULL, "gpio_170", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(UNIPRO_TX0, 171, "unipro_tx0", "kpd_col0", NULL,
+			"gpio_171", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(UNIPRO_TY0, 172, "unipro_ty0", "kpd_col1", NULL,
+			"gpio_172", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(UNIPRO_TX1, 173, "unipro_tx1", "kpd_col2", NULL,
+			"gpio_173", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(UNIPRO_TY1, 174, "unipro_ty1", "kpd_col3", NULL,
+			"gpio_174", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(UNIPRO_TX2, 0, "unipro_tx2", "kpd_col4", NULL,
+			"gpio_0", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(UNIPRO_TY2, 1, "unipro_ty2", "kpd_col5", NULL,
+			"gpio_1", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(UNIPRO_RX0, 0, "unipro_rx0", "kpd_row0", NULL,
+			"gpi_175", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(UNIPRO_RY0, 0, "unipro_ry0", "kpd_row1", NULL,
+			"gpi_176", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(UNIPRO_RX1, 0, "unipro_rx1", "kpd_row2", NULL,
+			"gpi_177", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(UNIPRO_RY1, 0, "unipro_ry1", "kpd_row3", NULL,
+			"gpi_178", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(UNIPRO_RX2, 0, "unipro_rx2", "kpd_row4", NULL,
+			"gpi_2", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(UNIPRO_RY2, 0, "unipro_ry2", "kpd_row5", NULL,
+			"gpi_3", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(USBA0_OTG_CE, 0, "usba0_otg_ce", NULL, NULL, NULL,
+			NULL, NULL, NULL, NULL),
+	_OMAP4_MUXENTRY(USBA0_OTG_DP, 179, "usba0_otg_dp", "uart3_rx_irrx",
+			"uart2_rx", "gpio_179", NULL, NULL, NULL,
+			"safe_mode"),
+	_OMAP4_MUXENTRY(USBA0_OTG_DM, 180, "usba0_otg_dm", "uart3_tx_irtx",
+			"uart2_tx", "gpio_180", NULL, NULL, NULL,
+			"safe_mode"),
+	_OMAP4_MUXENTRY(FREF_CLK1_OUT, 181, "fref_clk1_out", NULL, NULL,
+			"gpio_181", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(FREF_CLK2_OUT, 182, "fref_clk2_out", NULL, NULL,
+			"gpio_182", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(SYS_NIRQ1, 0, "sys_nirq1", NULL, NULL, NULL, NULL,
+			NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(SYS_NIRQ2, 183, "sys_nirq2", NULL, NULL, "gpio_183",
+			NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(SYS_BOOT0, 184, "sys_boot0", NULL, NULL, "gpio_184",
+			NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(SYS_BOOT1, 185, "sys_boot1", NULL, NULL, "gpio_185",
+			NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(SYS_BOOT2, 186, "sys_boot2", NULL, NULL, "gpio_186",
+			NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(SYS_BOOT3, 187, "sys_boot3", NULL, NULL, "gpio_187",
+			NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(SYS_BOOT4, 188, "sys_boot4", NULL, NULL, "gpio_188",
+			NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(SYS_BOOT5, 189, "sys_boot5", NULL, NULL, "gpio_189",
+			NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(DPM_EMU0, 11, "dpm_emu0", NULL, NULL, "gpio_11", NULL,
+			NULL, "hw_dbg0", "safe_mode"),
+	_OMAP4_MUXENTRY(DPM_EMU1, 12, "dpm_emu1", NULL, NULL, "gpio_12", NULL,
+			NULL, "hw_dbg1", "safe_mode"),
+	_OMAP4_MUXENTRY(DPM_EMU2, 13, "dpm_emu2", "usba0_ulpiphy_clk", NULL,
+			"gpio_13", NULL, "dispc2_fid", "hw_dbg2", "reserved"),
+	_OMAP4_MUXENTRY(DPM_EMU3, 14, "dpm_emu3", "usba0_ulpiphy_stp", NULL,
+			"gpio_14", NULL, "dispc2_data10", "hw_dbg3",
+			"reserved"),
+	_OMAP4_MUXENTRY(DPM_EMU4, 15, "dpm_emu4", "usba0_ulpiphy_dir", NULL,
+			"gpio_15", NULL, "dispc2_data9", "hw_dbg4",
+			"reserved"),
+	_OMAP4_MUXENTRY(DPM_EMU5, 16, "dpm_emu5", "usba0_ulpiphy_nxt", NULL,
+			"gpio_16", "rfbi_te_vsync0", "dispc2_data16",
+			"hw_dbg5", "reserved"),
+	_OMAP4_MUXENTRY(DPM_EMU6, 17, "dpm_emu6", "usba0_ulpiphy_dat0",
+			"uart3_tx_irtx", "gpio_17", "rfbi_hsync0",
+			"dispc2_data17", "hw_dbg6", "reserved"),
+	_OMAP4_MUXENTRY(DPM_EMU7, 18, "dpm_emu7", "usba0_ulpiphy_dat1",
+			"uart3_rx_irrx", "gpio_18", "rfbi_cs0",
+			"dispc2_hsync", "hw_dbg7", "reserved"),
+	_OMAP4_MUXENTRY(DPM_EMU8, 19, "dpm_emu8", "usba0_ulpiphy_dat2",
+			"uart3_rts_sd", "gpio_19", "rfbi_re", "dispc2_pclk",
+			"hw_dbg8", "reserved"),
+	_OMAP4_MUXENTRY(DPM_EMU9, 20, "dpm_emu9", "usba0_ulpiphy_dat3",
+			"uart3_cts_rctx", "gpio_20", "rfbi_we",
+			"dispc2_vsync", "hw_dbg9", "reserved"),
+	_OMAP4_MUXENTRY(DPM_EMU10, 21, "dpm_emu10", "usba0_ulpiphy_dat4",
+			NULL, "gpio_21", "rfbi_a0", "dispc2_de", "hw_dbg10",
+			"reserved"),
+	_OMAP4_MUXENTRY(DPM_EMU11, 22, "dpm_emu11", "usba0_ulpiphy_dat5",
+			NULL, "gpio_22", "rfbi_data8", "dispc2_data8",
+			"hw_dbg11", "reserved"),
+	_OMAP4_MUXENTRY(DPM_EMU12, 23, "dpm_emu12", "usba0_ulpiphy_dat6",
+			NULL, "gpio_23", "rfbi_data7", "dispc2_data7",
+			"hw_dbg12", "reserved"),
+	_OMAP4_MUXENTRY(DPM_EMU13, 24, "dpm_emu13", "usba0_ulpiphy_dat7",
+			NULL, "gpio_24", "rfbi_data6", "dispc2_data6",
+			"hw_dbg13", "reserved"),
+	_OMAP4_MUXENTRY(DPM_EMU14, 25, "dpm_emu14", "sys_drm_msecure",
+			"uart1_rx", "gpio_25", "rfbi_data5", "dispc2_data5",
+			"hw_dbg14", "reserved"),
+	_OMAP4_MUXENTRY(DPM_EMU15, 26, "dpm_emu15", "sys_secure_indicator",
+			NULL, "gpio_26", "rfbi_data4", "dispc2_data4",
+			"hw_dbg15", "reserved"),
+	_OMAP4_MUXENTRY(DPM_EMU16, 27, "dpm_emu16", "dmtimer8_pwm_evt",
+			"dsi1_te0", "gpio_27", "rfbi_data3", "dispc2_data3",
+			"hw_dbg16", "reserved"),
+	_OMAP4_MUXENTRY(DPM_EMU17, 28, "dpm_emu17", "dmtimer9_pwm_evt",
+			"dsi1_te1", "gpio_28", "rfbi_data2", "dispc2_data2",
+			"hw_dbg17", "reserved"),
+	_OMAP4_MUXENTRY(DPM_EMU18, 190, "dpm_emu18", "dmtimer10_pwm_evt",
+			"dsi2_te0", "gpio_190", "rfbi_data1", "dispc2_data1",
+			"hw_dbg18", "reserved"),
+	_OMAP4_MUXENTRY(DPM_EMU19, 191, "dpm_emu19", "dmtimer11_pwm_evt",
+			"dsi2_te1", "gpio_191", "rfbi_data0", "dispc2_data0",
+			"hw_dbg19", "reserved"),
+	{ .reg_offset = OMAP_MUX_TERMINATOR },
+};
+
+/*
+ * Balls for 44XX CBL package
+ * 547-pin CBL ES1.0 S-FPGA-N547, 0.40mm Ball Pitch (Top),
+ *				  0.40mm Ball Pitch (Bottom)
+ */
+#if defined(CONFIG_OMAP_MUX) && defined(CONFIG_DEBUG_FS)		\
+		&& defined(CONFIG_OMAP_PACKAGE_CBL)
+static struct omap_ball __initdata omap4_core_cbl_ball[] = {
+	_OMAP4_BALLENTRY(GPMC_AD0, "c12", NULL),
+	_OMAP4_BALLENTRY(GPMC_AD1, "d12", NULL),
+	_OMAP4_BALLENTRY(GPMC_AD2, "c13", NULL),
+	_OMAP4_BALLENTRY(GPMC_AD3, "d13", NULL),
+	_OMAP4_BALLENTRY(GPMC_AD4, "c15", NULL),
+	_OMAP4_BALLENTRY(GPMC_AD5, "d15", NULL),
+	_OMAP4_BALLENTRY(GPMC_AD6, "a16", NULL),
+	_OMAP4_BALLENTRY(GPMC_AD7, "b16", NULL),
+	_OMAP4_BALLENTRY(GPMC_AD8, "c16", NULL),
+	_OMAP4_BALLENTRY(GPMC_AD9, "d16", NULL),
+	_OMAP4_BALLENTRY(GPMC_AD10, "c17", NULL),
+	_OMAP4_BALLENTRY(GPMC_AD11, "d17", NULL),
+	_OMAP4_BALLENTRY(GPMC_AD12, "c18", NULL),
+	_OMAP4_BALLENTRY(GPMC_AD13, "d18", NULL),
+	_OMAP4_BALLENTRY(GPMC_AD14, "c19", NULL),
+	_OMAP4_BALLENTRY(GPMC_AD15, "d19", NULL),
+	_OMAP4_BALLENTRY(GPMC_A16, "b17", NULL),
+	_OMAP4_BALLENTRY(GPMC_A17, "a18", NULL),
+	_OMAP4_BALLENTRY(GPMC_A18, "b18", NULL),
+	_OMAP4_BALLENTRY(GPMC_A19, "a19", NULL),
+	_OMAP4_BALLENTRY(GPMC_A20, "b19", NULL),
+	_OMAP4_BALLENTRY(GPMC_A21, "b20", NULL),
+	_OMAP4_BALLENTRY(GPMC_A22, "a21", NULL),
+	_OMAP4_BALLENTRY(GPMC_A23, "b21", NULL),
+	_OMAP4_BALLENTRY(GPMC_A24, "c20", NULL),
+	_OMAP4_BALLENTRY(GPMC_A25, "d20", NULL),
+	_OMAP4_BALLENTRY(GPMC_NCS0, "b25", NULL),
+	_OMAP4_BALLENTRY(GPMC_NCS1, "c21", NULL),
+	_OMAP4_BALLENTRY(GPMC_NCS2, "d21", NULL),
+	_OMAP4_BALLENTRY(GPMC_NCS3, "c22", NULL),
+	_OMAP4_BALLENTRY(GPMC_NWP, "c25", NULL),
+	_OMAP4_BALLENTRY(GPMC_CLK, "b22", NULL),
+	_OMAP4_BALLENTRY(GPMC_NADV_ALE, "d25", NULL),
+	_OMAP4_BALLENTRY(GPMC_NOE, "b11", NULL),
+	_OMAP4_BALLENTRY(GPMC_NWE, "b12", NULL),
+	_OMAP4_BALLENTRY(GPMC_NBE0_CLE, "c23", NULL),
+	_OMAP4_BALLENTRY(GPMC_NBE1, "d22", NULL),
+	_OMAP4_BALLENTRY(GPMC_WAIT0, "b26", NULL),
+	_OMAP4_BALLENTRY(GPMC_WAIT1, "b23", NULL),
+	_OMAP4_BALLENTRY(C2C_DATA11, "d23", NULL),
+	_OMAP4_BALLENTRY(C2C_DATA12, "a24", NULL),
+	_OMAP4_BALLENTRY(C2C_DATA13, "b24", NULL),
+	_OMAP4_BALLENTRY(C2C_DATA14, "c24", NULL),
+	_OMAP4_BALLENTRY(C2C_DATA15, "d24", NULL),
+	_OMAP4_BALLENTRY(HDMI_HPD, "b9", NULL),
+	_OMAP4_BALLENTRY(HDMI_CEC, "b10", NULL),
+	_OMAP4_BALLENTRY(HDMI_DDC_SCL, "a8", NULL),
+	_OMAP4_BALLENTRY(HDMI_DDC_SDA, "b8", NULL),
+	_OMAP4_BALLENTRY(CSI21_DX0, "r26", NULL),
+	_OMAP4_BALLENTRY(CSI21_DY0, "r25", NULL),
+	_OMAP4_BALLENTRY(CSI21_DX1, "t26", NULL),
+	_OMAP4_BALLENTRY(CSI21_DY1, "t25", NULL),
+	_OMAP4_BALLENTRY(CSI21_DX2, "u26", NULL),
+	_OMAP4_BALLENTRY(CSI21_DY2, "u25", NULL),
+	_OMAP4_BALLENTRY(CSI21_DX3, "v26", NULL),
+	_OMAP4_BALLENTRY(CSI21_DY3, "v25", NULL),
+	_OMAP4_BALLENTRY(CSI21_DX4, "w26", NULL),
+	_OMAP4_BALLENTRY(CSI21_DY4, "w25", NULL),
+	_OMAP4_BALLENTRY(CSI22_DX0, "m26", NULL),
+	_OMAP4_BALLENTRY(CSI22_DY0, "m25", NULL),
+	_OMAP4_BALLENTRY(CSI22_DX1, "n26", NULL),
+	_OMAP4_BALLENTRY(CSI22_DY1, "n25", NULL),
+	_OMAP4_BALLENTRY(CAM_SHUTTER, "t27", NULL),
+	_OMAP4_BALLENTRY(CAM_STROBE, "u27", NULL),
+	_OMAP4_BALLENTRY(CAM_GLOBALRESET, "v27", NULL),
+	_OMAP4_BALLENTRY(USBB1_ULPITLL_CLK, "ae18", NULL),
+	_OMAP4_BALLENTRY(USBB1_ULPITLL_STP, "ag19", NULL),
+	_OMAP4_BALLENTRY(USBB1_ULPITLL_DIR, "af19", NULL),
+	_OMAP4_BALLENTRY(USBB1_ULPITLL_NXT, "ae19", NULL),
+	_OMAP4_BALLENTRY(USBB1_ULPITLL_DAT0, "af18", NULL),
+	_OMAP4_BALLENTRY(USBB1_ULPITLL_DAT1, "ag18", NULL),
+	_OMAP4_BALLENTRY(USBB1_ULPITLL_DAT2, "ae17", NULL),
+	_OMAP4_BALLENTRY(USBB1_ULPITLL_DAT3, "af17", NULL),
+	_OMAP4_BALLENTRY(USBB1_ULPITLL_DAT4, "ah17", NULL),
+	_OMAP4_BALLENTRY(USBB1_ULPITLL_DAT5, "ae16", NULL),
+	_OMAP4_BALLENTRY(USBB1_ULPITLL_DAT6, "af16", NULL),
+	_OMAP4_BALLENTRY(USBB1_ULPITLL_DAT7, "ag16", NULL),
+	_OMAP4_BALLENTRY(USBB1_HSIC_DATA, "af14", NULL),
+	_OMAP4_BALLENTRY(USBB1_HSIC_STROBE, "ae14", NULL),
+	_OMAP4_BALLENTRY(USBC1_ICUSB_DP, "h2", NULL),
+	_OMAP4_BALLENTRY(USBC1_ICUSB_DM, "h3", NULL),
+	_OMAP4_BALLENTRY(SDMMC1_CLK, "d2", NULL),
+	_OMAP4_BALLENTRY(SDMMC1_CMD, "e3", NULL),
+	_OMAP4_BALLENTRY(SDMMC1_DAT0, "e4", NULL),
+	_OMAP4_BALLENTRY(SDMMC1_DAT1, "e2", NULL),
+	_OMAP4_BALLENTRY(SDMMC1_DAT2, "e1", NULL),
+	_OMAP4_BALLENTRY(SDMMC1_DAT3, "f4", NULL),
+	_OMAP4_BALLENTRY(SDMMC1_DAT4, "f3", NULL),
+	_OMAP4_BALLENTRY(SDMMC1_DAT5, "f1", NULL),
+	_OMAP4_BALLENTRY(SDMMC1_DAT6, "g4", NULL),
+	_OMAP4_BALLENTRY(SDMMC1_DAT7, "g3", NULL),
+	_OMAP4_BALLENTRY(ABE_MCBSP2_CLKX, "ad27", NULL),
+	_OMAP4_BALLENTRY(ABE_MCBSP2_DR, "ad26", NULL),
+	_OMAP4_BALLENTRY(ABE_MCBSP2_DX, "ad25", NULL),
+	_OMAP4_BALLENTRY(ABE_MCBSP2_FSX, "ac28", NULL),
+	_OMAP4_BALLENTRY(ABE_MCBSP1_CLKX, "ac26", NULL),
+	_OMAP4_BALLENTRY(ABE_MCBSP1_DR, "ac25", NULL),
+	_OMAP4_BALLENTRY(ABE_MCBSP1_DX, "ab25", NULL),
+	_OMAP4_BALLENTRY(ABE_MCBSP1_FSX, "ac27", NULL),
+	_OMAP4_BALLENTRY(ABE_PDM_UL_DATA, "ag25", NULL),
+	_OMAP4_BALLENTRY(ABE_PDM_DL_DATA, "af25", NULL),
+	_OMAP4_BALLENTRY(ABE_PDM_FRAME, "ae25", NULL),
+	_OMAP4_BALLENTRY(ABE_PDM_LB_CLK, "af26", NULL),
+	_OMAP4_BALLENTRY(ABE_CLKS, "ah26", NULL),
+	_OMAP4_BALLENTRY(ABE_DMIC_CLK1, "ae24", NULL),
+	_OMAP4_BALLENTRY(ABE_DMIC_DIN1, "af24", NULL),
+	_OMAP4_BALLENTRY(ABE_DMIC_DIN2, "ag24", NULL),
+	_OMAP4_BALLENTRY(ABE_DMIC_DIN3, "ah24", NULL),
+	_OMAP4_BALLENTRY(UART2_CTS, "ab26", NULL),
+	_OMAP4_BALLENTRY(UART2_RTS, "ab27", NULL),
+	_OMAP4_BALLENTRY(UART2_RX, "aa25", NULL),
+	_OMAP4_BALLENTRY(UART2_TX, "aa26", NULL),
+	_OMAP4_BALLENTRY(HDQ_SIO, "aa27", NULL),
+	_OMAP4_BALLENTRY(I2C1_SCL, "ae28", NULL),
+	_OMAP4_BALLENTRY(I2C1_SDA, "ae26", NULL),
+	_OMAP4_BALLENTRY(I2C2_SCL, "c26", NULL),
+	_OMAP4_BALLENTRY(I2C2_SDA, "d26", NULL),
+	_OMAP4_BALLENTRY(I2C3_SCL, "w27", NULL),
+	_OMAP4_BALLENTRY(I2C3_SDA, "y27", NULL),
+	_OMAP4_BALLENTRY(I2C4_SCL, "ag21", NULL),
+	_OMAP4_BALLENTRY(I2C4_SDA, "ah22", NULL),
+	_OMAP4_BALLENTRY(MCSPI1_CLK, "af22", NULL),
+	_OMAP4_BALLENTRY(MCSPI1_SOMI, "ae22", NULL),
+	_OMAP4_BALLENTRY(MCSPI1_SIMO, "ag22", NULL),
+	_OMAP4_BALLENTRY(MCSPI1_CS0, "ae23", NULL),
+	_OMAP4_BALLENTRY(MCSPI1_CS1, "af23", NULL),
+	_OMAP4_BALLENTRY(MCSPI1_CS2, "ag23", NULL),
+	_OMAP4_BALLENTRY(MCSPI1_CS3, "ah23", NULL),
+	_OMAP4_BALLENTRY(UART3_CTS_RCTX, "f27", NULL),
+	_OMAP4_BALLENTRY(UART3_RTS_SD, "f28", NULL),
+	_OMAP4_BALLENTRY(UART3_RX_IRRX, "g27", NULL),
+	_OMAP4_BALLENTRY(UART3_TX_IRTX, "g28", NULL),
+	_OMAP4_BALLENTRY(SDMMC5_CLK, "ae5", NULL),
+	_OMAP4_BALLENTRY(SDMMC5_CMD, "af5", NULL),
+	_OMAP4_BALLENTRY(SDMMC5_DAT0, "ae4", NULL),
+	_OMAP4_BALLENTRY(SDMMC5_DAT1, "af4", NULL),
+	_OMAP4_BALLENTRY(SDMMC5_DAT2, "ag3", NULL),
+	_OMAP4_BALLENTRY(SDMMC5_DAT3, "af3", NULL),
+	_OMAP4_BALLENTRY(MCSPI4_CLK, "ae21", NULL),
+	_OMAP4_BALLENTRY(MCSPI4_SIMO, "af20", NULL),
+	_OMAP4_BALLENTRY(MCSPI4_SOMI, "af21", NULL),
+	_OMAP4_BALLENTRY(MCSPI4_CS0, "ae20", NULL),
+	_OMAP4_BALLENTRY(UART4_RX, "ag20", NULL),
+	_OMAP4_BALLENTRY(UART4_TX, "ah19", NULL),
+	_OMAP4_BALLENTRY(USBB2_ULPITLL_CLK, "ag12", NULL),
+	_OMAP4_BALLENTRY(USBB2_ULPITLL_STP, "af12", NULL),
+	_OMAP4_BALLENTRY(USBB2_ULPITLL_DIR, "ae12", NULL),
+	_OMAP4_BALLENTRY(USBB2_ULPITLL_NXT, "ag13", NULL),
+	_OMAP4_BALLENTRY(USBB2_ULPITLL_DAT0, "ae11", NULL),
+	_OMAP4_BALLENTRY(USBB2_ULPITLL_DAT1, "af11", NULL),
+	_OMAP4_BALLENTRY(USBB2_ULPITLL_DAT2, "ag11", NULL),
+	_OMAP4_BALLENTRY(USBB2_ULPITLL_DAT3, "ah11", NULL),
+	_OMAP4_BALLENTRY(USBB2_ULPITLL_DAT4, "ae10", NULL),
+	_OMAP4_BALLENTRY(USBB2_ULPITLL_DAT5, "af10", NULL),
+	_OMAP4_BALLENTRY(USBB2_ULPITLL_DAT6, "ag10", NULL),
+	_OMAP4_BALLENTRY(USBB2_ULPITLL_DAT7, "ae9", NULL),
+	_OMAP4_BALLENTRY(USBB2_HSIC_DATA, "af13", NULL),
+	_OMAP4_BALLENTRY(USBB2_HSIC_STROBE, "ae13", NULL),
+	_OMAP4_BALLENTRY(UNIPRO_TX0, "g26", NULL),
+	_OMAP4_BALLENTRY(UNIPRO_TY0, "g25", NULL),
+	_OMAP4_BALLENTRY(UNIPRO_TX1, "h26", NULL),
+	_OMAP4_BALLENTRY(UNIPRO_TY1, "h25", NULL),
+	_OMAP4_BALLENTRY(UNIPRO_TX2, "j27", NULL),
+	_OMAP4_BALLENTRY(UNIPRO_TY2, "h27", NULL),
+	_OMAP4_BALLENTRY(UNIPRO_RX0, "j26", NULL),
+	_OMAP4_BALLENTRY(UNIPRO_RY0, "j25", NULL),
+	_OMAP4_BALLENTRY(UNIPRO_RX1, "k26", NULL),
+	_OMAP4_BALLENTRY(UNIPRO_RY1, "k25", NULL),
+	_OMAP4_BALLENTRY(UNIPRO_RX2, "l27", NULL),
+	_OMAP4_BALLENTRY(UNIPRO_RY2, "k27", NULL),
+	_OMAP4_BALLENTRY(USBA0_OTG_CE, "c3", NULL),
+	_OMAP4_BALLENTRY(USBA0_OTG_DP, "b5", NULL),
+	_OMAP4_BALLENTRY(USBA0_OTG_DM, "b4", NULL),
+	_OMAP4_BALLENTRY(FREF_CLK1_OUT, "aa28", NULL),
+	_OMAP4_BALLENTRY(FREF_CLK2_OUT, "y28", NULL),
+	_OMAP4_BALLENTRY(SYS_NIRQ1, "ae6", NULL),
+	_OMAP4_BALLENTRY(SYS_NIRQ2, "af6", NULL),
+	_OMAP4_BALLENTRY(SYS_BOOT0, "f26", NULL),
+	_OMAP4_BALLENTRY(SYS_BOOT1, "e27", NULL),
+	_OMAP4_BALLENTRY(SYS_BOOT2, "e26", NULL),
+	_OMAP4_BALLENTRY(SYS_BOOT3, "e25", NULL),
+	_OMAP4_BALLENTRY(SYS_BOOT4, "d28", NULL),
+	_OMAP4_BALLENTRY(SYS_BOOT5, "d27", NULL),
+	_OMAP4_BALLENTRY(DPM_EMU0, "m2", NULL),
+	_OMAP4_BALLENTRY(DPM_EMU1, "n2", NULL),
+	_OMAP4_BALLENTRY(DPM_EMU2, "p2", NULL),
+	_OMAP4_BALLENTRY(DPM_EMU3, "v1", NULL),
+	_OMAP4_BALLENTRY(DPM_EMU4, "v2", NULL),
+	_OMAP4_BALLENTRY(DPM_EMU5, "w1", NULL),
+	_OMAP4_BALLENTRY(DPM_EMU6, "w2", NULL),
+	_OMAP4_BALLENTRY(DPM_EMU7, "w3", NULL),
+	_OMAP4_BALLENTRY(DPM_EMU8, "w4", NULL),
+	_OMAP4_BALLENTRY(DPM_EMU9, "y2", NULL),
+	_OMAP4_BALLENTRY(DPM_EMU10, "y3", NULL),
+	_OMAP4_BALLENTRY(DPM_EMU11, "y4", NULL),
+	_OMAP4_BALLENTRY(DPM_EMU12, "aa1", NULL),
+	_OMAP4_BALLENTRY(DPM_EMU13, "aa2", NULL),
+	_OMAP4_BALLENTRY(DPM_EMU14, "aa3", NULL),
+	_OMAP4_BALLENTRY(DPM_EMU15, "aa4", NULL),
+	_OMAP4_BALLENTRY(DPM_EMU16, "ab2", NULL),
+	_OMAP4_BALLENTRY(DPM_EMU17, "ab3", NULL),
+	_OMAP4_BALLENTRY(DPM_EMU18, "ab4", NULL),
+	_OMAP4_BALLENTRY(DPM_EMU19, "ac4", NULL),
+	{ .reg_offset = OMAP_MUX_TERMINATOR },
+};
+#else
+#define omap4_core_cbl_ball  NULL
+#endif
+
+/*
+ * Superset of all mux modes for omap4 ES2.0
+ */
+static struct omap_mux __initdata omap4_es2_core_muxmodes[] = {
+	_OMAP4_MUXENTRY(GPMC_AD0, 0, "gpmc_ad0", "sdmmc2_dat0", NULL, NULL,
+			NULL, NULL, NULL, NULL),
+	_OMAP4_MUXENTRY(GPMC_AD1, 0, "gpmc_ad1", "sdmmc2_dat1", NULL, NULL,
+			NULL, NULL, NULL, NULL),
+	_OMAP4_MUXENTRY(GPMC_AD2, 0, "gpmc_ad2", "sdmmc2_dat2", NULL, NULL,
+			NULL, NULL, NULL, NULL),
+	_OMAP4_MUXENTRY(GPMC_AD3, 0, "gpmc_ad3", "sdmmc2_dat3", NULL, NULL,
+			NULL, NULL, NULL, NULL),
+	_OMAP4_MUXENTRY(GPMC_AD4, 0, "gpmc_ad4", "sdmmc2_dat4",
+			"sdmmc2_dir_dat0", NULL, NULL, NULL, NULL, NULL),
+	_OMAP4_MUXENTRY(GPMC_AD5, 0, "gpmc_ad5", "sdmmc2_dat5",
+			"sdmmc2_dir_dat1", NULL, NULL, NULL, NULL, NULL),
+	_OMAP4_MUXENTRY(GPMC_AD6, 0, "gpmc_ad6", "sdmmc2_dat6",
+			"sdmmc2_dir_cmd", NULL, NULL, NULL, NULL, NULL),
+	_OMAP4_MUXENTRY(GPMC_AD7, 0, "gpmc_ad7", "sdmmc2_dat7",
+			"sdmmc2_clk_fdbk", NULL, NULL, NULL, NULL, NULL),
+	_OMAP4_MUXENTRY(GPMC_AD8, 32, "gpmc_ad8", "kpd_row0", "c2c_data15",
+			"gpio_32", NULL, "sdmmc1_dat0", NULL, NULL),
+	_OMAP4_MUXENTRY(GPMC_AD9, 33, "gpmc_ad9", "kpd_row1", "c2c_data14",
+			"gpio_33", NULL, "sdmmc1_dat1", NULL, NULL),
+	_OMAP4_MUXENTRY(GPMC_AD10, 34, "gpmc_ad10", "kpd_row2", "c2c_data13",
+			"gpio_34", NULL, "sdmmc1_dat2", NULL, NULL),
+	_OMAP4_MUXENTRY(GPMC_AD11, 35, "gpmc_ad11", "kpd_row3", "c2c_data12",
+			"gpio_35", NULL, "sdmmc1_dat3", NULL, NULL),
+	_OMAP4_MUXENTRY(GPMC_AD12, 36, "gpmc_ad12", "kpd_col0", "c2c_data11",
+			"gpio_36", NULL, "sdmmc1_dat4", NULL, NULL),
+	_OMAP4_MUXENTRY(GPMC_AD13, 37, "gpmc_ad13", "kpd_col1", "c2c_data10",
+			"gpio_37", NULL, "sdmmc1_dat5", NULL, NULL),
+	_OMAP4_MUXENTRY(GPMC_AD14, 38, "gpmc_ad14", "kpd_col2", "c2c_data9",
+			"gpio_38", NULL, "sdmmc1_dat6", NULL, NULL),
+	_OMAP4_MUXENTRY(GPMC_AD15, 39, "gpmc_ad15", "kpd_col3", "c2c_data8",
+			"gpio_39", NULL, "sdmmc1_dat7", NULL, NULL),
+	_OMAP4_MUXENTRY(GPMC_A16, 40, "gpmc_a16", "kpd_row4", "c2c_datain0",
+			"gpio_40", "venc_656_data0", NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(GPMC_A17, 41, "gpmc_a17", "kpd_row5", "c2c_datain1",
+			"gpio_41", "venc_656_data1", NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(GPMC_A18, 42, "gpmc_a18", "kpd_row6", "c2c_datain2",
+			"gpio_42", "venc_656_data2", NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(GPMC_A19, 43, "gpmc_a19", "kpd_row7", "c2c_datain3",
+			"gpio_43", "venc_656_data3", NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(GPMC_A20, 44, "gpmc_a20", "kpd_col4", "c2c_datain4",
+			"gpio_44", "venc_656_data4", NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(GPMC_A21, 45, "gpmc_a21", "kpd_col5", "c2c_datain5",
+			"gpio_45", "venc_656_data5", NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(GPMC_A22, 46, "gpmc_a22", "kpd_col6", "c2c_datain6",
+			"gpio_46", "venc_656_data6", NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(GPMC_A23, 47, "gpmc_a23", "kpd_col7", "c2c_datain7",
+			"gpio_47", "venc_656_data7", NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(GPMC_A24, 48, "gpmc_a24", "kpd_col8", "c2c_clkout0",
+			"gpio_48", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(GPMC_A25, 49, "gpmc_a25", NULL, "c2c_clkout1",
+			"gpio_49", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(GPMC_NCS0, 50, "gpmc_ncs0", NULL, NULL, "gpio_50",
+			"sys_ndmareq0", NULL, NULL, NULL),
+	_OMAP4_MUXENTRY(GPMC_NCS1, 51, "gpmc_ncs1", NULL, "c2c_dataout6",
+			"gpio_51", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(GPMC_NCS2, 52, "gpmc_ncs2", "kpd_row8",
+			"c2c_dataout7", "gpio_52", NULL, NULL, NULL,
+			"safe_mode"),
+	_OMAP4_MUXENTRY(GPMC_NCS3, 53, "gpmc_ncs3", "gpmc_dir",
+			"c2c_dataout4", "gpio_53", NULL, NULL, NULL,
+			"safe_mode"),
+	_OMAP4_MUXENTRY(GPMC_NWP, 54, "gpmc_nwp", "dsi1_te0", NULL, "gpio_54",
+			"sys_ndmareq1", NULL, NULL, NULL),
+	_OMAP4_MUXENTRY(GPMC_CLK, 55, "gpmc_clk", NULL, NULL, "gpio_55",
+			"sys_ndmareq2", "sdmmc1_cmd", NULL, NULL),
+	_OMAP4_MUXENTRY(GPMC_NADV_ALE, 56, "gpmc_nadv_ale", "dsi1_te1", NULL,
+			"gpio_56", "sys_ndmareq3", "sdmmc1_clk", NULL, NULL),
+	_OMAP4_MUXENTRY(GPMC_NOE, 0, "gpmc_noe", "sdmmc2_clk", NULL, NULL,
+			NULL, NULL, NULL, NULL),
+	_OMAP4_MUXENTRY(GPMC_NWE, 0, "gpmc_nwe", "sdmmc2_cmd", NULL, NULL,
+			NULL, NULL, NULL, NULL),
+	_OMAP4_MUXENTRY(GPMC_NBE0_CLE, 59, "gpmc_nbe0_cle", "dsi2_te0", NULL,
+			"gpio_59", NULL, NULL, NULL, NULL),
+	_OMAP4_MUXENTRY(GPMC_NBE1, 60, "gpmc_nbe1", NULL, "c2c_dataout5",
+			"gpio_60", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(GPMC_WAIT0, 61, "gpmc_wait0", "dsi2_te1", NULL,
+			"gpio_61", NULL, NULL, NULL, NULL),
+	_OMAP4_MUXENTRY(GPMC_WAIT1, 62, "gpmc_wait1", NULL, "c2c_dataout2",
+			"gpio_62", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(GPMC_WAIT2, 100, "gpmc_wait2", "usbc1_icusb_txen",
+			"c2c_dataout3", "gpio_100", "sys_ndmareq0", NULL,
+			NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(GPMC_NCS4, 101, "gpmc_ncs4", "dsi1_te0", "c2c_clkin0",
+			"gpio_101", "sys_ndmareq1", NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(GPMC_NCS5, 102, "gpmc_ncs5", "dsi1_te1", "c2c_clkin1",
+			"gpio_102", "sys_ndmareq2", NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(GPMC_NCS6, 103, "gpmc_ncs6", "dsi2_te0",
+			"c2c_dataout0", "gpio_103", "sys_ndmareq3", NULL,
+			NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(GPMC_NCS7, 104, "gpmc_ncs7", "dsi2_te1",
+			"c2c_dataout1", "gpio_104", NULL, NULL, NULL,
+			"safe_mode"),
+	_OMAP4_MUXENTRY(HDMI_HPD, 63, "hdmi_hpd", NULL, NULL, "gpio_63", NULL,
+			NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(HDMI_CEC, 64, "hdmi_cec", NULL, NULL, "gpio_64", NULL,
+			NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(HDMI_DDC_SCL, 65, "hdmi_ddc_scl", NULL, NULL,
+			"gpio_65", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(HDMI_DDC_SDA, 66, "hdmi_ddc_sda", NULL, NULL,
+			"gpio_66", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(CSI21_DX0, 0, "csi21_dx0", NULL, NULL, "gpi_67", NULL,
+			NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(CSI21_DY0, 0, "csi21_dy0", NULL, NULL, "gpi_68", NULL,
+			NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(CSI21_DX1, 0, "csi21_dx1", NULL, NULL, "gpi_69", NULL,
+			NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(CSI21_DY1, 0, "csi21_dy1", NULL, NULL, "gpi_70", NULL,
+			NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(CSI21_DX2, 0, "csi21_dx2", NULL, NULL, "gpi_71", NULL,
+			NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(CSI21_DY2, 0, "csi21_dy2", NULL, NULL, "gpi_72", NULL,
+			NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(CSI21_DX3, 0, "csi21_dx3", NULL, NULL, "gpi_73", NULL,
+			NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(CSI21_DY3, 0, "csi21_dy3", NULL, NULL, "gpi_74", NULL,
+			NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(CSI21_DX4, 0, "csi21_dx4", NULL, NULL, "gpi_75", NULL,
+			NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(CSI21_DY4, 0, "csi21_dy4", NULL, NULL, "gpi_76", NULL,
+			NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(CSI22_DX0, 0, "csi22_dx0", NULL, NULL, "gpi_77", NULL,
+			NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(CSI22_DY0, 0, "csi22_dy0", NULL, NULL, "gpi_78", NULL,
+			NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(CSI22_DX1, 0, "csi22_dx1", NULL, NULL, "gpi_79", NULL,
+			NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(CSI22_DY1, 0, "csi22_dy1", NULL, NULL, "gpi_80", NULL,
+			NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(CAM_SHUTTER, 81, "cam_shutter", NULL, NULL, "gpio_81",
+			NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(CAM_STROBE, 82, "cam_strobe", NULL, NULL, "gpio_82",
+			NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(CAM_GLOBALRESET, 83, "cam_globalreset", NULL, NULL,
+			"gpio_83", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(USBB1_ULPITLL_CLK, 84, "usbb1_ulpitll_clk",
+			"hsi1_cawake", NULL, "gpio_84", "usbb1_ulpiphy_clk",
+			NULL, "hw_dbg20", "safe_mode"),
+	_OMAP4_MUXENTRY(USBB1_ULPITLL_STP, 85, "usbb1_ulpitll_stp",
+			"hsi1_cadata", "mcbsp4_clkr", "gpio_85",
+			"usbb1_ulpiphy_stp", "usbb1_mm_rxdp", "hw_dbg21",
+			"safe_mode"),
+	_OMAP4_MUXENTRY(USBB1_ULPITLL_DIR, 86, "usbb1_ulpitll_dir",
+			"hsi1_caflag", "mcbsp4_fsr", "gpio_86",
+			"usbb1_ulpiphy_dir", NULL, "hw_dbg22", "safe_mode"),
+	_OMAP4_MUXENTRY(USBB1_ULPITLL_NXT, 87, "usbb1_ulpitll_nxt",
+			"hsi1_acready", "mcbsp4_fsx", "gpio_87",
+			"usbb1_ulpiphy_nxt", "usbb1_mm_rxdm", "hw_dbg23",
+			"safe_mode"),
+	_OMAP4_MUXENTRY(USBB1_ULPITLL_DAT0, 88, "usbb1_ulpitll_dat0",
+			"hsi1_acwake", "mcbsp4_clkx", "gpio_88",
+			"usbb1_ulpiphy_dat0", "usbb1_mm_txen", "hw_dbg24",
+			"safe_mode"),
+	_OMAP4_MUXENTRY(USBB1_ULPITLL_DAT1, 89, "usbb1_ulpitll_dat1",
+			"hsi1_acdata", "mcbsp4_dx", "gpio_89",
+			"usbb1_ulpiphy_dat1", "usbb1_mm_txdat", "hw_dbg25",
+			"safe_mode"),
+	_OMAP4_MUXENTRY(USBB1_ULPITLL_DAT2, 90, "usbb1_ulpitll_dat2",
+			"hsi1_acflag", "mcbsp4_dr", "gpio_90",
+			"usbb1_ulpiphy_dat2", "usbb1_mm_txse0", "hw_dbg26",
+			"safe_mode"),
+	_OMAP4_MUXENTRY(USBB1_ULPITLL_DAT3, 91, "usbb1_ulpitll_dat3",
+			"hsi1_caready", NULL, "gpio_91", "usbb1_ulpiphy_dat3",
+			"usbb1_mm_rxrcv", "hw_dbg27", "safe_mode"),
+	_OMAP4_MUXENTRY(USBB1_ULPITLL_DAT4, 92, "usbb1_ulpitll_dat4",
+			"dmtimer8_pwm_evt", "abe_mcbsp3_dr", "gpio_92",
+			"usbb1_ulpiphy_dat4", NULL, "hw_dbg28", "safe_mode"),
+	_OMAP4_MUXENTRY(USBB1_ULPITLL_DAT5, 93, "usbb1_ulpitll_dat5",
+			"dmtimer9_pwm_evt", "abe_mcbsp3_dx", "gpio_93",
+			"usbb1_ulpiphy_dat5", NULL, "hw_dbg29", "safe_mode"),
+	_OMAP4_MUXENTRY(USBB1_ULPITLL_DAT6, 94, "usbb1_ulpitll_dat6",
+			"dmtimer10_pwm_evt", "abe_mcbsp3_clkx", "gpio_94",
+			"usbb1_ulpiphy_dat6", "abe_dmic_din3", "hw_dbg30",
+			"safe_mode"),
+	_OMAP4_MUXENTRY(USBB1_ULPITLL_DAT7, 95, "usbb1_ulpitll_dat7",
+			"dmtimer11_pwm_evt", "abe_mcbsp3_fsx", "gpio_95",
+			"usbb1_ulpiphy_dat7", "abe_dmic_clk3", "hw_dbg31",
+			"safe_mode"),
+	_OMAP4_MUXENTRY(USBB1_HSIC_DATA, 96, "usbb1_hsic_data", NULL, NULL,
+			"gpio_96", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(USBB1_HSIC_STROBE, 97, "usbb1_hsic_strobe", NULL,
+			NULL, "gpio_97", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(USBC1_ICUSB_DP, 98, "usbc1_icusb_dp", NULL, NULL,
+			"gpio_98", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(USBC1_ICUSB_DM, 99, "usbc1_icusb_dm", NULL, NULL,
+			"gpio_99", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(SDMMC1_CLK, 100, "sdmmc1_clk", NULL, "dpm_emu19",
+			"gpio_100", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(SDMMC1_CMD, 101, "sdmmc1_cmd", NULL, "uart1_rx",
+			"gpio_101", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(SDMMC1_DAT0, 102, "sdmmc1_dat0", NULL, "dpm_emu18",
+			"gpio_102", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(SDMMC1_DAT1, 103, "sdmmc1_dat1", NULL, "dpm_emu17",
+			"gpio_103", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(SDMMC1_DAT2, 104, "sdmmc1_dat2", NULL, "dpm_emu16",
+			"gpio_104", "jtag_tms_tmsc", NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(SDMMC1_DAT3, 105, "sdmmc1_dat3", NULL, "dpm_emu15",
+			"gpio_105", "jtag_tck", NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(SDMMC1_DAT4, 106, "sdmmc1_dat4", NULL, NULL,
+			"gpio_106", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(SDMMC1_DAT5, 107, "sdmmc1_dat5", NULL, NULL,
+			"gpio_107", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(SDMMC1_DAT6, 108, "sdmmc1_dat6", NULL, NULL,
+			"gpio_108", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(SDMMC1_DAT7, 109, "sdmmc1_dat7", NULL, NULL,
+			"gpio_109", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(ABE_MCBSP2_CLKX, 110, "abe_mcbsp2_clkx", "mcspi2_clk",
+			"abe_mcasp_ahclkx", "gpio_110", "usbb2_mm_rxdm",
+			NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(ABE_MCBSP2_DR, 111, "abe_mcbsp2_dr", "mcspi2_somi",
+			"abe_mcasp_axr", "gpio_111", "usbb2_mm_rxdp", NULL,
+			NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(ABE_MCBSP2_DX, 112, "abe_mcbsp2_dx", "mcspi2_simo",
+			"abe_mcasp_amute", "gpio_112", "usbb2_mm_rxrcv", NULL,
+			NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(ABE_MCBSP2_FSX, 113, "abe_mcbsp2_fsx", "mcspi2_cs0",
+			"abe_mcasp_afsx", "gpio_113", "usbb2_mm_txen", NULL,
+			NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(ABE_MCBSP1_CLKX, 114, "abe_mcbsp1_clkx",
+			"abe_slimbus1_clock", NULL, "gpio_114", NULL, NULL,
+			NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(ABE_MCBSP1_DR, 115, "abe_mcbsp1_dr",
+			"abe_slimbus1_data", NULL, "gpio_115", NULL, NULL,
+			NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(ABE_MCBSP1_DX, 116, "abe_mcbsp1_dx", "sdmmc3_dat2",
+			"abe_mcasp_aclkx", "gpio_116", NULL, NULL, NULL,
+			"safe_mode"),
+	_OMAP4_MUXENTRY(ABE_MCBSP1_FSX, 117, "abe_mcbsp1_fsx", "sdmmc3_dat3",
+			"abe_mcasp_amutein", "gpio_117", NULL, NULL, NULL,
+			"safe_mode"),
+	_OMAP4_MUXENTRY(ABE_PDM_UL_DATA, 0, "abe_pdm_ul_data",
+			"abe_mcbsp3_dr", NULL, NULL, NULL, NULL, NULL,
+			"safe_mode"),
+	_OMAP4_MUXENTRY(ABE_PDM_DL_DATA, 0, "abe_pdm_dl_data",
+			"abe_mcbsp3_dx", NULL, NULL, NULL, NULL, NULL,
+			"safe_mode"),
+	_OMAP4_MUXENTRY(ABE_PDM_FRAME, 0, "abe_pdm_frame", "abe_mcbsp3_clkx",
+			NULL, NULL, NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(ABE_PDM_LB_CLK, 0, "abe_pdm_lb_clk", "abe_mcbsp3_fsx",
+			NULL, NULL, NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(ABE_CLKS, 118, "abe_clks", NULL, NULL, "gpio_118",
+			NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(ABE_DMIC_CLK1, 119, "abe_dmic_clk1", NULL, NULL,
+			"gpio_119", "usbb2_mm_txse0", "uart4_cts", NULL,
+			"safe_mode"),
+	_OMAP4_MUXENTRY(ABE_DMIC_DIN1, 120, "abe_dmic_din1", NULL, NULL,
+			"gpio_120", "usbb2_mm_txdat", "uart4_rts", NULL,
+			"safe_mode"),
+	_OMAP4_MUXENTRY(ABE_DMIC_DIN2, 121, "abe_dmic_din2", "slimbus2_clock",
+			"abe_mcasp_axr", "gpio_121", NULL,
+			"dmtimer11_pwm_evt", NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(ABE_DMIC_DIN3, 122, "abe_dmic_din3", "slimbus2_data",
+			"abe_dmic_clk2", "gpio_122", NULL, "dmtimer9_pwm_evt",
+			NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(UART2_CTS, 123, "uart2_cts", "sdmmc3_clk", NULL,
+			"gpio_123", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(UART2_RTS, 124, "uart2_rts", "sdmmc3_cmd", NULL,
+			"gpio_124", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(UART2_RX, 125, "uart2_rx", "sdmmc3_dat0", NULL,
+			"gpio_125", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(UART2_TX, 126, "uart2_tx", "sdmmc3_dat1", NULL,
+			"gpio_126", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(HDQ_SIO, 127, "hdq_sio", "i2c3_sccb", "i2c2_sccb",
+			"gpio_127", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(I2C1_SCL, 0, "i2c1_scl", NULL, NULL, NULL, NULL, NULL,
+			NULL, NULL),
+	_OMAP4_MUXENTRY(I2C1_SDA, 0, "i2c1_sda", NULL, NULL, NULL, NULL, NULL,
+			NULL, NULL),
+	_OMAP4_MUXENTRY(I2C2_SCL, 128, "i2c2_scl", "uart1_rx", NULL,
+			"gpio_128", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(I2C2_SDA, 129, "i2c2_sda", "uart1_tx", NULL,
+			"gpio_129", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(I2C3_SCL, 130, "i2c3_scl", NULL, NULL, "gpio_130",
+			NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(I2C3_SDA, 131, "i2c3_sda", NULL, NULL, "gpio_131",
+			NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(I2C4_SCL, 132, "i2c4_scl", NULL, NULL, "gpio_132",
+			NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(I2C4_SDA, 133, "i2c4_sda", NULL, NULL, "gpio_133",
+			NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(MCSPI1_CLK, 134, "mcspi1_clk", NULL, NULL, "gpio_134",
+			NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(MCSPI1_SOMI, 135, "mcspi1_somi", NULL, NULL,
+			"gpio_135", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(MCSPI1_SIMO, 136, "mcspi1_simo", NULL, NULL,
+			"gpio_136", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(MCSPI1_CS0, 137, "mcspi1_cs0", NULL, NULL, "gpio_137",
+			NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(MCSPI1_CS1, 138, "mcspi1_cs1", "uart1_rx", NULL,
+			"gpio_138", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(MCSPI1_CS2, 139, "mcspi1_cs2", "uart1_cts",
+			"slimbus2_clock", "gpio_139", NULL, NULL, NULL,
+			"safe_mode"),
+	_OMAP4_MUXENTRY(MCSPI1_CS3, 140, "mcspi1_cs3", "uart1_rts",
+			"slimbus2_data", "gpio_140", NULL, NULL, NULL,
+			"safe_mode"),
+	_OMAP4_MUXENTRY(UART3_CTS_RCTX, 141, "uart3_cts_rctx", "uart1_tx",
+			NULL, "gpio_141", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(UART3_RTS_SD, 142, "uart3_rts_sd", NULL, NULL,
+			"gpio_142", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(UART3_RX_IRRX, 143, "uart3_rx_irrx",
+			"dmtimer8_pwm_evt", NULL, "gpio_143", NULL, NULL,
+			NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(UART3_TX_IRTX, 144, "uart3_tx_irtx",
+			"dmtimer9_pwm_evt", NULL, "gpio_144", NULL, NULL,
+			NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(SDMMC5_CLK, 145, "sdmmc5_clk", "mcspi2_clk",
+			"usbc1_icusb_dp", "gpio_145", NULL, "sdmmc2_clk",
+			NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(SDMMC5_CMD, 146, "sdmmc5_cmd", "mcspi2_simo",
+			"usbc1_icusb_dm", "gpio_146", NULL, "sdmmc2_cmd",
+			NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(SDMMC5_DAT0, 147, "sdmmc5_dat0", "mcspi2_somi",
+			"usbc1_icusb_rcv", "gpio_147", NULL, "sdmmc2_dat0",
+			NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(SDMMC5_DAT1, 148, "sdmmc5_dat1", NULL,
+			"usbc1_icusb_txen", "gpio_148", NULL, "sdmmc2_dat1",
+			NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(SDMMC5_DAT2, 149, "sdmmc5_dat2", "mcspi2_cs1", NULL,
+			"gpio_149", NULL, "sdmmc2_dat2", NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(SDMMC5_DAT3, 150, "sdmmc5_dat3", "mcspi2_cs0", NULL,
+			"gpio_150", NULL, "sdmmc2_dat3", NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(MCSPI4_CLK, 151, "mcspi4_clk", "sdmmc4_clk",
+			"kpd_col6", "gpio_151", NULL, NULL, NULL,
+			"safe_mode"),
+	_OMAP4_MUXENTRY(MCSPI4_SIMO, 152, "mcspi4_simo", "sdmmc4_cmd",
+			"kpd_col7", "gpio_152", NULL, NULL, NULL,
+			"safe_mode"),
+	_OMAP4_MUXENTRY(MCSPI4_SOMI, 153, "mcspi4_somi", "sdmmc4_dat0",
+			"kpd_row6", "gpio_153", NULL, NULL, NULL,
+			"safe_mode"),
+	_OMAP4_MUXENTRY(MCSPI4_CS0, 154, "mcspi4_cs0", "sdmmc4_dat3",
+			"kpd_row7", "gpio_154", NULL, NULL, NULL,
+			"safe_mode"),
+	_OMAP4_MUXENTRY(UART4_RX, 155, "uart4_rx", "sdmmc4_dat2", "kpd_row8",
+			"gpio_155", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(UART4_TX, 156, "uart4_tx", "sdmmc4_dat1", "kpd_col8",
+			"gpio_156", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(USBB2_ULPITLL_CLK, 157, "usbb2_ulpitll_clk",
+			"usbb2_ulpiphy_clk", "sdmmc4_cmd", "gpio_157",
+			"hsi2_cawake", NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(USBB2_ULPITLL_STP, 158, "usbb2_ulpitll_stp",
+			"usbb2_ulpiphy_stp", "sdmmc4_clk", "gpio_158",
+			"hsi2_cadata", "dispc2_data23", NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(USBB2_ULPITLL_DIR, 159, "usbb2_ulpitll_dir",
+			"usbb2_ulpiphy_dir", "sdmmc4_dat0", "gpio_159",
+			"hsi2_caflag", "dispc2_data22", NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(USBB2_ULPITLL_NXT, 160, "usbb2_ulpitll_nxt",
+			"usbb2_ulpiphy_nxt", "sdmmc4_dat1", "gpio_160",
+			"hsi2_acready", "dispc2_data21", NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(USBB2_ULPITLL_DAT0, 161, "usbb2_ulpitll_dat0",
+			"usbb2_ulpiphy_dat0", "sdmmc4_dat2", "gpio_161",
+			"hsi2_acwake", "dispc2_data20", "usbb2_mm_txen",
+			"safe_mode"),
+	_OMAP4_MUXENTRY(USBB2_ULPITLL_DAT1, 162, "usbb2_ulpitll_dat1",
+			"usbb2_ulpiphy_dat1", "sdmmc4_dat3", "gpio_162",
+			"hsi2_acdata", "dispc2_data19", "usbb2_mm_txdat",
+			"safe_mode"),
+	_OMAP4_MUXENTRY(USBB2_ULPITLL_DAT2, 163, "usbb2_ulpitll_dat2",
+			"usbb2_ulpiphy_dat2", "sdmmc3_dat2", "gpio_163",
+			"hsi2_acflag", "dispc2_data18", "usbb2_mm_txse0",
+			"safe_mode"),
+	_OMAP4_MUXENTRY(USBB2_ULPITLL_DAT3, 164, "usbb2_ulpitll_dat3",
+			"usbb2_ulpiphy_dat3", "sdmmc3_dat1", "gpio_164",
+			"hsi2_caready", "dispc2_data15", "rfbi_data15",
+			"safe_mode"),
+	_OMAP4_MUXENTRY(USBB2_ULPITLL_DAT4, 165, "usbb2_ulpitll_dat4",
+			"usbb2_ulpiphy_dat4", "sdmmc3_dat0", "gpio_165",
+			"mcspi3_somi", "dispc2_data14", "rfbi_data14",
+			"safe_mode"),
+	_OMAP4_MUXENTRY(USBB2_ULPITLL_DAT5, 166, "usbb2_ulpitll_dat5",
+			"usbb2_ulpiphy_dat5", "sdmmc3_dat3", "gpio_166",
+			"mcspi3_cs0", "dispc2_data13", "rfbi_data13",
+			"safe_mode"),
+	_OMAP4_MUXENTRY(USBB2_ULPITLL_DAT6, 167, "usbb2_ulpitll_dat6",
+			"usbb2_ulpiphy_dat6", "sdmmc3_cmd", "gpio_167",
+			"mcspi3_simo", "dispc2_data12", "rfbi_data12",
+			"safe_mode"),
+	_OMAP4_MUXENTRY(USBB2_ULPITLL_DAT7, 168, "usbb2_ulpitll_dat7",
+			"usbb2_ulpiphy_dat7", "sdmmc3_clk", "gpio_168",
+			"mcspi3_clk", "dispc2_data11", "rfbi_data11",
+			"safe_mode"),
+	_OMAP4_MUXENTRY(USBB2_HSIC_DATA, 169, "usbb2_hsic_data", NULL, NULL,
+			"gpio_169", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(USBB2_HSIC_STROBE, 170, "usbb2_hsic_strobe", NULL,
+			NULL, "gpio_170", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(KPD_COL3, 171, "kpd_col3", "kpd_col0", NULL,
+			"gpio_171", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(KPD_COL4, 172, "kpd_col4", "kpd_col1", NULL,
+			"gpio_172", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(KPD_COL5, 173, "kpd_col5", "kpd_col2", NULL,
+			"gpio_173", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(KPD_COL0, 174, "kpd_col0", "kpd_col3", NULL,
+			"gpio_174", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(KPD_COL1, 0, "kpd_col1", "kpd_col4", NULL, "gpio_0",
+			NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(KPD_COL2, 1, "kpd_col2", "kpd_col5", NULL, "gpio_1",
+			NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(KPD_ROW3, 175, "kpd_row3", "kpd_row0", NULL,
+			"gpio_175", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(KPD_ROW4, 176, "kpd_row4", "kpd_row1", NULL,
+			"gpio_176", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(KPD_ROW5, 177, "kpd_row5", "kpd_row2", NULL,
+			"gpio_177", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(KPD_ROW0, 178, "kpd_row0", "kpd_row3", NULL,
+			"gpio_178", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(KPD_ROW1, 2, "kpd_row1", "kpd_row4", NULL, "gpio_2",
+			NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(KPD_ROW2, 3, "kpd_row2", "kpd_row5", NULL, "gpio_3",
+			NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(USBA0_OTG_CE, 0, "usba0_otg_ce", NULL, NULL, NULL,
+			NULL, NULL, NULL, NULL),
+	_OMAP4_MUXENTRY(USBA0_OTG_DP, 0, "usba0_otg_dp", "uart3_rx_irrx",
+			"uart2_rx", NULL, NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(USBA0_OTG_DM, 0, "usba0_otg_dm", "uart3_tx_irtx",
+			"uart2_tx", NULL, NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(FREF_CLK1_OUT, 181, "fref_clk1_out", NULL, NULL,
+			"gpio_181", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(FREF_CLK2_OUT, 182, "fref_clk2_out", NULL, NULL,
+			"gpio_182", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(SYS_NIRQ1, 0, "sys_nirq1", NULL, NULL, NULL, NULL,
+			NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(SYS_NIRQ2, 183, "sys_nirq2", NULL, NULL, "gpio_183",
+			NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(SYS_BOOT0, 184, "sys_boot0", NULL, NULL, "gpio_184",
+			NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(SYS_BOOT1, 185, "sys_boot1", NULL, NULL, "gpio_185",
+			NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(SYS_BOOT2, 186, "sys_boot2", NULL, NULL, "gpio_186",
+			NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(SYS_BOOT3, 187, "sys_boot3", NULL, NULL, "gpio_187",
+			NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(SYS_BOOT4, 188, "sys_boot4", NULL, NULL, "gpio_188",
+			NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(SYS_BOOT5, 189, "sys_boot5", NULL, NULL, "gpio_189",
+			NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(DPM_EMU0, 11, "dpm_emu0", NULL, NULL, "gpio_11", NULL,
+			NULL, "hw_dbg0", "safe_mode"),
+	_OMAP4_MUXENTRY(DPM_EMU1, 12, "dpm_emu1", NULL, NULL, "gpio_12", NULL,
+			NULL, "hw_dbg1", "safe_mode"),
+	_OMAP4_MUXENTRY(DPM_EMU2, 13, "dpm_emu2", "usba0_ulpiphy_clk", NULL,
+			"gpio_13", NULL, "dispc2_fid", "hw_dbg2",
+			"safe_mode"),
+	_OMAP4_MUXENTRY(DPM_EMU3, 14, "dpm_emu3", "usba0_ulpiphy_stp", NULL,
+			"gpio_14", "rfbi_data10", "dispc2_data10", "hw_dbg3",
+			"safe_mode"),
+	_OMAP4_MUXENTRY(DPM_EMU4, 15, "dpm_emu4", "usba0_ulpiphy_dir", NULL,
+			"gpio_15", "rfbi_data9", "dispc2_data9", "hw_dbg4",
+			"safe_mode"),
+	_OMAP4_MUXENTRY(DPM_EMU5, 16, "dpm_emu5", "usba0_ulpiphy_nxt", NULL,
+			"gpio_16", "rfbi_te_vsync0", "dispc2_data16",
+			"hw_dbg5", "safe_mode"),
+	_OMAP4_MUXENTRY(DPM_EMU6, 17, "dpm_emu6", "usba0_ulpiphy_dat0",
+			"uart3_tx_irtx", "gpio_17", "rfbi_hsync0",
+			"dispc2_data17", "hw_dbg6", "safe_mode"),
+	_OMAP4_MUXENTRY(DPM_EMU7, 18, "dpm_emu7", "usba0_ulpiphy_dat1",
+			"uart3_rx_irrx", "gpio_18", "rfbi_cs0",
+			"dispc2_hsync", "hw_dbg7", "safe_mode"),
+	_OMAP4_MUXENTRY(DPM_EMU8, 19, "dpm_emu8", "usba0_ulpiphy_dat2",
+			"uart3_rts_sd", "gpio_19", "rfbi_re", "dispc2_pclk",
+			"hw_dbg8", "safe_mode"),
+	_OMAP4_MUXENTRY(DPM_EMU9, 20, "dpm_emu9", "usba0_ulpiphy_dat3",
+			"uart3_cts_rctx", "gpio_20", "rfbi_we",
+			"dispc2_vsync", "hw_dbg9", "safe_mode"),
+	_OMAP4_MUXENTRY(DPM_EMU10, 21, "dpm_emu10", "usba0_ulpiphy_dat4",
+			NULL, "gpio_21", "rfbi_a0", "dispc2_de", "hw_dbg10",
+			"safe_mode"),
+	_OMAP4_MUXENTRY(DPM_EMU11, 22, "dpm_emu11", "usba0_ulpiphy_dat5",
+			NULL, "gpio_22", "rfbi_data8", "dispc2_data8",
+			"hw_dbg11", "safe_mode"),
+	_OMAP4_MUXENTRY(DPM_EMU12, 23, "dpm_emu12", "usba0_ulpiphy_dat6",
+			NULL, "gpio_23", "rfbi_data7", "dispc2_data7",
+			"hw_dbg12", "safe_mode"),
+	_OMAP4_MUXENTRY(DPM_EMU13, 24, "dpm_emu13", "usba0_ulpiphy_dat7",
+			NULL, "gpio_24", "rfbi_data6", "dispc2_data6",
+			"hw_dbg13", "safe_mode"),
+	_OMAP4_MUXENTRY(DPM_EMU14, 25, "dpm_emu14", "sys_drm_msecure",
+			"uart1_rx", "gpio_25", "rfbi_data5", "dispc2_data5",
+			"hw_dbg14", "safe_mode"),
+	_OMAP4_MUXENTRY(DPM_EMU15, 26, "dpm_emu15", "sys_secure_indicator",
+			NULL, "gpio_26", "rfbi_data4", "dispc2_data4",
+			"hw_dbg15", "safe_mode"),
+	_OMAP4_MUXENTRY(DPM_EMU16, 27, "dpm_emu16", "dmtimer8_pwm_evt",
+			"dsi1_te0", "gpio_27", "rfbi_data3", "dispc2_data3",
+			"hw_dbg16", "safe_mode"),
+	_OMAP4_MUXENTRY(DPM_EMU17, 28, "dpm_emu17", "dmtimer9_pwm_evt",
+			"dsi1_te1", "gpio_28", "rfbi_data2", "dispc2_data2",
+			"hw_dbg17", "safe_mode"),
+	_OMAP4_MUXENTRY(DPM_EMU18, 190, "dpm_emu18", "dmtimer10_pwm_evt",
+			"dsi2_te0", "gpio_190", "rfbi_data1", "dispc2_data1",
+			"hw_dbg18", "safe_mode"),
+	_OMAP4_MUXENTRY(DPM_EMU19, 191, "dpm_emu19", "dmtimer11_pwm_evt",
+			"dsi2_te1", "gpio_191", "rfbi_data0", "dispc2_data0",
+			"hw_dbg19", "safe_mode"),
+	{ .reg_offset = OMAP_MUX_TERMINATOR },
+};
+
+/*
+ * Balls for 44XX CBS package
+ * 547-pin CBL ES2.0 S-FPGA-N547, 0.40mm Ball Pitch (Top),
+ *				  0.40mm Ball Pitch (Bottom)
+ */
+#if defined(CONFIG_OMAP_MUX) && defined(CONFIG_DEBUG_FS)		\
+		&& defined(CONFIG_OMAP_PACKAGE_CBS)
+static struct omap_ball __initdata omap4_core_cbs_ball[] = {
+	_OMAP4_BALLENTRY(GPMC_AD0, "c12", NULL),
+	_OMAP4_BALLENTRY(GPMC_AD1, "d12", NULL),
+	_OMAP4_BALLENTRY(GPMC_AD2, "c13", NULL),
+	_OMAP4_BALLENTRY(GPMC_AD3, "d13", NULL),
+	_OMAP4_BALLENTRY(GPMC_AD4, "c15", NULL),
+	_OMAP4_BALLENTRY(GPMC_AD5, "d15", NULL),
+	_OMAP4_BALLENTRY(GPMC_AD6, "a16", NULL),
+	_OMAP4_BALLENTRY(GPMC_AD7, "b16", NULL),
+	_OMAP4_BALLENTRY(GPMC_AD8, "c16", NULL),
+	_OMAP4_BALLENTRY(GPMC_AD9, "d16", NULL),
+	_OMAP4_BALLENTRY(GPMC_AD10, "c17", NULL),
+	_OMAP4_BALLENTRY(GPMC_AD11, "d17", NULL),
+	_OMAP4_BALLENTRY(GPMC_AD12, "c18", NULL),
+	_OMAP4_BALLENTRY(GPMC_AD13, "d18", NULL),
+	_OMAP4_BALLENTRY(GPMC_AD14, "c19", NULL),
+	_OMAP4_BALLENTRY(GPMC_AD15, "d19", NULL),
+	_OMAP4_BALLENTRY(GPMC_A16, "b17", NULL),
+	_OMAP4_BALLENTRY(GPMC_A17, "a18", NULL),
+	_OMAP4_BALLENTRY(GPMC_A18, "b18", NULL),
+	_OMAP4_BALLENTRY(GPMC_A19, "a19", NULL),
+	_OMAP4_BALLENTRY(GPMC_A20, "b19", NULL),
+	_OMAP4_BALLENTRY(GPMC_A21, "b20", NULL),
+	_OMAP4_BALLENTRY(GPMC_A22, "a21", NULL),
+	_OMAP4_BALLENTRY(GPMC_A23, "b21", NULL),
+	_OMAP4_BALLENTRY(GPMC_A24, "c20", NULL),
+	_OMAP4_BALLENTRY(GPMC_A25, "d20", NULL),
+	_OMAP4_BALLENTRY(GPMC_NCS0, "b25", NULL),
+	_OMAP4_BALLENTRY(GPMC_NCS1, "c21", NULL),
+	_OMAP4_BALLENTRY(GPMC_NCS2, "d21", NULL),
+	_OMAP4_BALLENTRY(GPMC_NCS3, "c22", NULL),
+	_OMAP4_BALLENTRY(GPMC_NWP, "c25", NULL),
+	_OMAP4_BALLENTRY(GPMC_CLK, "b22", NULL),
+	_OMAP4_BALLENTRY(GPMC_NADV_ALE, "d25", NULL),
+	_OMAP4_BALLENTRY(GPMC_NOE, "b11", NULL),
+	_OMAP4_BALLENTRY(GPMC_NWE, "b12", NULL),
+	_OMAP4_BALLENTRY(GPMC_NBE0_CLE, "c23", NULL),
+	_OMAP4_BALLENTRY(GPMC_NBE1, "d22", NULL),
+	_OMAP4_BALLENTRY(GPMC_WAIT0, "b26", NULL),
+	_OMAP4_BALLENTRY(GPMC_WAIT1, "b23", NULL),
+	_OMAP4_BALLENTRY(GPMC_WAIT2, "d23", NULL),
+	_OMAP4_BALLENTRY(GPMC_NCS4, "a24", NULL),
+	_OMAP4_BALLENTRY(GPMC_NCS5, "b24", NULL),
+	_OMAP4_BALLENTRY(GPMC_NCS6, "c24", NULL),
+	_OMAP4_BALLENTRY(GPMC_NCS7, "d24", NULL),
+	_OMAP4_BALLENTRY(HDMI_HPD, "b9", NULL),
+	_OMAP4_BALLENTRY(HDMI_CEC, "b10", NULL),
+	_OMAP4_BALLENTRY(HDMI_DDC_SCL, "a8", NULL),
+	_OMAP4_BALLENTRY(HDMI_DDC_SDA, "b8", NULL),
+	_OMAP4_BALLENTRY(CSI21_DX0, "r26", NULL),
+	_OMAP4_BALLENTRY(CSI21_DY0, "r25", NULL),
+	_OMAP4_BALLENTRY(CSI21_DX1, "t26", NULL),
+	_OMAP4_BALLENTRY(CSI21_DY1, "t25", NULL),
+	_OMAP4_BALLENTRY(CSI21_DX2, "u26", NULL),
+	_OMAP4_BALLENTRY(CSI21_DY2, "u25", NULL),
+	_OMAP4_BALLENTRY(CSI21_DX3, "v26", NULL),
+	_OMAP4_BALLENTRY(CSI21_DY3, "v25", NULL),
+	_OMAP4_BALLENTRY(CSI21_DX4, "w26", NULL),
+	_OMAP4_BALLENTRY(CSI21_DY4, "w25", NULL),
+	_OMAP4_BALLENTRY(CSI22_DX0, "m26", NULL),
+	_OMAP4_BALLENTRY(CSI22_DY0, "m25", NULL),
+	_OMAP4_BALLENTRY(CSI22_DX1, "n26", NULL),
+	_OMAP4_BALLENTRY(CSI22_DY1, "n25", NULL),
+	_OMAP4_BALLENTRY(CAM_SHUTTER, "t27", NULL),
+	_OMAP4_BALLENTRY(CAM_STROBE, "u27", NULL),
+	_OMAP4_BALLENTRY(CAM_GLOBALRESET, "v27", NULL),
+	_OMAP4_BALLENTRY(USBB1_ULPITLL_CLK, "ae18", NULL),
+	_OMAP4_BALLENTRY(USBB1_ULPITLL_STP, "ag19", NULL),
+	_OMAP4_BALLENTRY(USBB1_ULPITLL_DIR, "af19", NULL),
+	_OMAP4_BALLENTRY(USBB1_ULPITLL_NXT, "ae19", NULL),
+	_OMAP4_BALLENTRY(USBB1_ULPITLL_DAT0, "af18", NULL),
+	_OMAP4_BALLENTRY(USBB1_ULPITLL_DAT1, "ag18", NULL),
+	_OMAP4_BALLENTRY(USBB1_ULPITLL_DAT2, "ae17", NULL),
+	_OMAP4_BALLENTRY(USBB1_ULPITLL_DAT3, "af17", NULL),
+	_OMAP4_BALLENTRY(USBB1_ULPITLL_DAT4, "ah17", NULL),
+	_OMAP4_BALLENTRY(USBB1_ULPITLL_DAT5, "ae16", NULL),
+	_OMAP4_BALLENTRY(USBB1_ULPITLL_DAT6, "af16", NULL),
+	_OMAP4_BALLENTRY(USBB1_ULPITLL_DAT7, "ag16", NULL),
+	_OMAP4_BALLENTRY(USBB1_HSIC_DATA, "af14", NULL),
+	_OMAP4_BALLENTRY(USBB1_HSIC_STROBE, "ae14", NULL),
+	_OMAP4_BALLENTRY(USBC1_ICUSB_DP, "h2", NULL),
+	_OMAP4_BALLENTRY(USBC1_ICUSB_DM, "h3", NULL),
+	_OMAP4_BALLENTRY(SDMMC1_CLK, "d2", NULL),
+	_OMAP4_BALLENTRY(SDMMC1_CMD, "e3", NULL),
+	_OMAP4_BALLENTRY(SDMMC1_DAT0, "e4", NULL),
+	_OMAP4_BALLENTRY(SDMMC1_DAT1, "e2", NULL),
+	_OMAP4_BALLENTRY(SDMMC1_DAT2, "e1", NULL),
+	_OMAP4_BALLENTRY(SDMMC1_DAT3, "f4", NULL),
+	_OMAP4_BALLENTRY(SDMMC1_DAT4, "f3", NULL),
+	_OMAP4_BALLENTRY(SDMMC1_DAT5, "f1", NULL),
+	_OMAP4_BALLENTRY(SDMMC1_DAT6, "g4", NULL),
+	_OMAP4_BALLENTRY(SDMMC1_DAT7, "g3", NULL),
+	_OMAP4_BALLENTRY(ABE_MCBSP2_CLKX, "ad27", NULL),
+	_OMAP4_BALLENTRY(ABE_MCBSP2_DR, "ad26", NULL),
+	_OMAP4_BALLENTRY(ABE_MCBSP2_DX, "ad25", NULL),
+	_OMAP4_BALLENTRY(ABE_MCBSP2_FSX, "ac28", NULL),
+	_OMAP4_BALLENTRY(ABE_MCBSP1_CLKX, "ac26", NULL),
+	_OMAP4_BALLENTRY(ABE_MCBSP1_DR, "ac25", NULL),
+	_OMAP4_BALLENTRY(ABE_MCBSP1_DX, "ab25", NULL),
+	_OMAP4_BALLENTRY(ABE_MCBSP1_FSX, "ac27", NULL),
+	_OMAP4_BALLENTRY(ABE_PDM_UL_DATA, "ag25", NULL),
+	_OMAP4_BALLENTRY(ABE_PDM_DL_DATA, "af25", NULL),
+	_OMAP4_BALLENTRY(ABE_PDM_FRAME, "ae25", NULL),
+	_OMAP4_BALLENTRY(ABE_PDM_LB_CLK, "af26", NULL),
+	_OMAP4_BALLENTRY(ABE_CLKS, "ah26", NULL),
+	_OMAP4_BALLENTRY(ABE_DMIC_CLK1, "ae24", NULL),
+	_OMAP4_BALLENTRY(ABE_DMIC_DIN1, "af24", NULL),
+	_OMAP4_BALLENTRY(ABE_DMIC_DIN2, "ag24", NULL),
+	_OMAP4_BALLENTRY(ABE_DMIC_DIN3, "ah24", NULL),
+	_OMAP4_BALLENTRY(UART2_CTS, "ab26", NULL),
+	_OMAP4_BALLENTRY(UART2_RTS, "ab27", NULL),
+	_OMAP4_BALLENTRY(UART2_RX, "aa25", NULL),
+	_OMAP4_BALLENTRY(UART2_TX, "aa26", NULL),
+	_OMAP4_BALLENTRY(HDQ_SIO, "aa27", NULL),
+	_OMAP4_BALLENTRY(I2C1_SCL, "ae28", NULL),
+	_OMAP4_BALLENTRY(I2C1_SDA, "ae26", NULL),
+	_OMAP4_BALLENTRY(I2C2_SCL, "c26", NULL),
+	_OMAP4_BALLENTRY(I2C2_SDA, "d26", NULL),
+	_OMAP4_BALLENTRY(I2C3_SCL, "w27", NULL),
+	_OMAP4_BALLENTRY(I2C3_SDA, "y27", NULL),
+	_OMAP4_BALLENTRY(I2C4_SCL, "ag21", NULL),
+	_OMAP4_BALLENTRY(I2C4_SDA, "ah22", NULL),
+	_OMAP4_BALLENTRY(MCSPI1_CLK, "af22", NULL),
+	_OMAP4_BALLENTRY(MCSPI1_SOMI, "ae22", NULL),
+	_OMAP4_BALLENTRY(MCSPI1_SIMO, "ag22", NULL),
+	_OMAP4_BALLENTRY(MCSPI1_CS0, "ae23", NULL),
+	_OMAP4_BALLENTRY(MCSPI1_CS1, "af23", NULL),
+	_OMAP4_BALLENTRY(MCSPI1_CS2, "ag23", NULL),
+	_OMAP4_BALLENTRY(MCSPI1_CS3, "ah23", NULL),
+	_OMAP4_BALLENTRY(UART3_CTS_RCTX, "f27", NULL),
+	_OMAP4_BALLENTRY(UART3_RTS_SD, "f28", NULL),
+	_OMAP4_BALLENTRY(UART3_RX_IRRX, "g27", NULL),
+	_OMAP4_BALLENTRY(UART3_TX_IRTX, "g28", NULL),
+	_OMAP4_BALLENTRY(SDMMC5_CLK, "ae5", NULL),
+	_OMAP4_BALLENTRY(SDMMC5_CMD, "af5", NULL),
+	_OMAP4_BALLENTRY(SDMMC5_DAT0, "ae4", NULL),
+	_OMAP4_BALLENTRY(SDMMC5_DAT1, "af4", NULL),
+	_OMAP4_BALLENTRY(SDMMC5_DAT2, "ag3", NULL),
+	_OMAP4_BALLENTRY(SDMMC5_DAT3, "af3", NULL),
+	_OMAP4_BALLENTRY(MCSPI4_CLK, "ae21", NULL),
+	_OMAP4_BALLENTRY(MCSPI4_SIMO, "af20", NULL),
+	_OMAP4_BALLENTRY(MCSPI4_SOMI, "af21", NULL),
+	_OMAP4_BALLENTRY(MCSPI4_CS0, "ae20", NULL),
+	_OMAP4_BALLENTRY(UART4_RX, "ag20", NULL),
+	_OMAP4_BALLENTRY(UART4_TX, "ah19", NULL),
+	_OMAP4_BALLENTRY(USBB2_ULPITLL_CLK, "ag12", NULL),
+	_OMAP4_BALLENTRY(USBB2_ULPITLL_STP, "af12", NULL),
+	_OMAP4_BALLENTRY(USBB2_ULPITLL_DIR, "ae12", NULL),
+	_OMAP4_BALLENTRY(USBB2_ULPITLL_NXT, "ag13", NULL),
+	_OMAP4_BALLENTRY(USBB2_ULPITLL_DAT0, "ae11", NULL),
+	_OMAP4_BALLENTRY(USBB2_ULPITLL_DAT1, "af11", NULL),
+	_OMAP4_BALLENTRY(USBB2_ULPITLL_DAT2, "ag11", NULL),
+	_OMAP4_BALLENTRY(USBB2_ULPITLL_DAT3, "ah11", NULL),
+	_OMAP4_BALLENTRY(USBB2_ULPITLL_DAT4, "ae10", NULL),
+	_OMAP4_BALLENTRY(USBB2_ULPITLL_DAT5, "af10", NULL),
+	_OMAP4_BALLENTRY(USBB2_ULPITLL_DAT6, "ag10", NULL),
+	_OMAP4_BALLENTRY(USBB2_ULPITLL_DAT7, "ae9", NULL),
+	_OMAP4_BALLENTRY(USBB2_HSIC_DATA, "af13", NULL),
+	_OMAP4_BALLENTRY(USBB2_HSIC_STROBE, "ae13", NULL),
+	_OMAP4_BALLENTRY(KPD_COL3, "g26", NULL),
+	_OMAP4_BALLENTRY(KPD_COL4, "g25", NULL),
+	_OMAP4_BALLENTRY(KPD_COL5, "h26", NULL),
+	_OMAP4_BALLENTRY(KPD_COL0, "h25", NULL),
+	_OMAP4_BALLENTRY(KPD_COL1, "j27", NULL),
+	_OMAP4_BALLENTRY(KPD_COL2, "h27", NULL),
+	_OMAP4_BALLENTRY(KPD_ROW3, "j26", NULL),
+	_OMAP4_BALLENTRY(KPD_ROW4, "j25", NULL),
+	_OMAP4_BALLENTRY(KPD_ROW5, "k26", NULL),
+	_OMAP4_BALLENTRY(KPD_ROW0, "k25", NULL),
+	_OMAP4_BALLENTRY(KPD_ROW1, "l27", NULL),
+	_OMAP4_BALLENTRY(KPD_ROW2, "k27", NULL),
+	_OMAP4_BALLENTRY(USBA0_OTG_CE, "c3", NULL),
+	_OMAP4_BALLENTRY(USBA0_OTG_DP, "b5", NULL),
+	_OMAP4_BALLENTRY(USBA0_OTG_DM, "b4", NULL),
+	_OMAP4_BALLENTRY(FREF_CLK1_OUT, "aa28", NULL),
+	_OMAP4_BALLENTRY(FREF_CLK2_OUT, "y28", NULL),
+	_OMAP4_BALLENTRY(SYS_NIRQ1, "ae6", NULL),
+	_OMAP4_BALLENTRY(SYS_NIRQ2, "af6", NULL),
+	_OMAP4_BALLENTRY(SYS_BOOT0, "f26", NULL),
+	_OMAP4_BALLENTRY(SYS_BOOT1, "e27", NULL),
+	_OMAP4_BALLENTRY(SYS_BOOT2, "e26", NULL),
+	_OMAP4_BALLENTRY(SYS_BOOT3, "e25", NULL),
+	_OMAP4_BALLENTRY(SYS_BOOT4, "d28", NULL),
+	_OMAP4_BALLENTRY(SYS_BOOT5, "d27", NULL),
+	_OMAP4_BALLENTRY(DPM_EMU0, "m2", NULL),
+	_OMAP4_BALLENTRY(DPM_EMU1, "n2", NULL),
+	_OMAP4_BALLENTRY(DPM_EMU2, "p2", NULL),
+	_OMAP4_BALLENTRY(DPM_EMU3, "v1", NULL),
+	_OMAP4_BALLENTRY(DPM_EMU4, "v2", NULL),
+	_OMAP4_BALLENTRY(DPM_EMU5, "w1", NULL),
+	_OMAP4_BALLENTRY(DPM_EMU6, "w2", NULL),
+	_OMAP4_BALLENTRY(DPM_EMU7, "w3", NULL),
+	_OMAP4_BALLENTRY(DPM_EMU8, "w4", NULL),
+	_OMAP4_BALLENTRY(DPM_EMU9, "y2", NULL),
+	_OMAP4_BALLENTRY(DPM_EMU10, "y3", NULL),
+	_OMAP4_BALLENTRY(DPM_EMU11, "y4", NULL),
+	_OMAP4_BALLENTRY(DPM_EMU12, "aa1", NULL),
+	_OMAP4_BALLENTRY(DPM_EMU13, "aa2", NULL),
+	_OMAP4_BALLENTRY(DPM_EMU14, "aa3", NULL),
+	_OMAP4_BALLENTRY(DPM_EMU15, "aa4", NULL),
+	_OMAP4_BALLENTRY(DPM_EMU16, "ab2", NULL),
+	_OMAP4_BALLENTRY(DPM_EMU17, "ab3", NULL),
+	_OMAP4_BALLENTRY(DPM_EMU18, "ab4", NULL),
+	_OMAP4_BALLENTRY(DPM_EMU19, "ac4", NULL),
+	{ .reg_offset = OMAP_MUX_TERMINATOR },
+};
+#else
+#define omap4_core_cbs_ball  NULL
+#endif
+
+/*
+ * Superset of all mux modes for omap4
+ */
+static struct omap_mux __initdata omap4_wkup_muxmodes[] = {
+	_OMAP4_MUXENTRY(SIM_IO, 0, "sim_io", NULL, NULL, "gpio_wk0", NULL,
+			NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(SIM_CLK, 1, "sim_clk", NULL, NULL, "gpio_wk1", NULL,
+			NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(SIM_RESET, 2, "sim_reset", NULL, NULL, "gpio_wk2",
+			NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(SIM_CD, 3, "sim_cd", NULL, NULL, "gpio_wk3", NULL,
+			NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(SIM_PWRCTRL, 4, "sim_pwrctrl", NULL, NULL, "gpio_wk4",
+			NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(SR_SCL, 0, "sr_scl", NULL, NULL, NULL, NULL, NULL,
+			NULL, NULL),
+	_OMAP4_MUXENTRY(SR_SDA, 0, "sr_sda", NULL, NULL, NULL, NULL, NULL,
+			NULL, NULL),
+	_OMAP4_MUXENTRY(FREF_XTAL_IN, 0, "fref_xtal_in", NULL, NULL, NULL,
+			"c2c_wakereqin", NULL, NULL, NULL),
+	_OMAP4_MUXENTRY(FREF_SLICER_IN, 0, "fref_slicer_in", NULL, NULL,
+			"gpi_wk5", "c2c_wakereqin", NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(FREF_CLK_IOREQ, 0, "fref_clk_ioreq", NULL, NULL, NULL,
+			NULL, NULL, NULL, NULL),
+	_OMAP4_MUXENTRY(FREF_CLK0_OUT, 6, "fref_clk0_out", "fref_clk1_req",
+			"sys_drm_msecure", "gpio_wk6", NULL, NULL, NULL,
+			"safe_mode"),
+	_OMAP4_MUXENTRY(FREF_CLK3_REQ, 30, "fref_clk3_req", "fref_clk1_req",
+			"sys_drm_msecure", "gpio_wk30", "c2c_wakereqin", NULL,
+			NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(FREF_CLK3_OUT, 31, "fref_clk3_out", "fref_clk2_req",
+			"sys_secure_indicator", "gpio_wk31", "c2c_wakereqout",
+			NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(FREF_CLK4_REQ, 7, "fref_clk4_req", "fref_clk5_out",
+			NULL, "gpio_wk7", NULL, NULL, NULL, NULL),
+	_OMAP4_MUXENTRY(FREF_CLK4_OUT, 8, "fref_clk4_out", NULL, NULL,
+			"gpio_wk8", NULL, NULL, NULL, NULL),
+	_OMAP4_MUXENTRY(SYS_32K, 0, "sys_32k", NULL, NULL, NULL, NULL, NULL,
+			NULL, NULL),
+	_OMAP4_MUXENTRY(SYS_NRESPWRON, 0, "sys_nrespwron", NULL, NULL, NULL,
+			NULL, NULL, NULL, NULL),
+	_OMAP4_MUXENTRY(SYS_NRESWARM, 0, "sys_nreswarm", NULL, NULL, NULL,
+			NULL, NULL, NULL, NULL),
+	_OMAP4_MUXENTRY(SYS_PWR_REQ, 0, "sys_pwr_req", NULL, NULL, NULL, NULL,
+			NULL, NULL, NULL),
+	_OMAP4_MUXENTRY(SYS_PWRON_RESET_OUT, 29, "sys_pwron_reset_out", NULL,
+			NULL, "gpio_wk29", NULL, NULL, NULL, NULL),
+	_OMAP4_MUXENTRY(SYS_BOOT6, 9, "sys_boot6", "dpm_emu18", NULL,
+			"gpio_wk9", "c2c_wakereqout", NULL, NULL,
+			"safe_mode"),
+	_OMAP4_MUXENTRY(SYS_BOOT7, 10, "sys_boot7", "dpm_emu19", NULL,
+			"gpio_wk10", NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(JTAG_NTRST, 0, "jtag_ntrst", NULL, NULL, NULL, NULL,
+			NULL, NULL, NULL),
+	_OMAP4_MUXENTRY(JTAG_TCK, 0, "jtag_tck", NULL, NULL, NULL, NULL, NULL,
+			NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(JTAG_RTCK, 0, "jtag_rtck", NULL, NULL, NULL, NULL,
+			NULL, NULL, NULL),
+	_OMAP4_MUXENTRY(JTAG_TMS_TMSC, 0, "jtag_tms_tmsc", NULL, NULL, NULL,
+			NULL, NULL, NULL, "safe_mode"),
+	_OMAP4_MUXENTRY(JTAG_TDI, 0, "jtag_tdi", NULL, NULL, NULL, NULL, NULL,
+			NULL, NULL),
+	_OMAP4_MUXENTRY(JTAG_TDO, 0, "jtag_tdo", NULL, NULL, NULL, NULL, NULL,
+			NULL, NULL),
+	{ .reg_offset = OMAP_MUX_TERMINATOR },
+};
+
+/*
+ * Balls for 44XX CBL & CBS package - wakeup partition
+ * 547-pin CBL ES1.0 S-FPGA-N547, 0.40mm Ball Pitch (Top),
+ *				  0.40mm Ball Pitch (Bottom)
+ */
+#if defined(CONFIG_OMAP_MUX) && defined(CONFIG_DEBUG_FS)		\
+		&& defined(CONFIG_OMAP_PACKAGE_CBL)
+static struct omap_ball __initdata omap4_wkup_cbl_cbs_ball[] = {
+	_OMAP4_BALLENTRY(SIM_IO, "h4", NULL),
+	_OMAP4_BALLENTRY(SIM_CLK, "j2", NULL),
+	_OMAP4_BALLENTRY(SIM_RESET, "g2", NULL),
+	_OMAP4_BALLENTRY(SIM_CD, "j1", NULL),
+	_OMAP4_BALLENTRY(SIM_PWRCTRL, "k1", NULL),
+	_OMAP4_BALLENTRY(SR_SCL, "ag9", NULL),
+	_OMAP4_BALLENTRY(SR_SDA, "af9", NULL),
+	_OMAP4_BALLENTRY(FREF_XTAL_IN, "ah6", NULL),
+	_OMAP4_BALLENTRY(FREF_SLICER_IN, "ag8", NULL),
+	_OMAP4_BALLENTRY(FREF_CLK_IOREQ, "ad1", NULL),
+	_OMAP4_BALLENTRY(FREF_CLK0_OUT, "ad2", NULL),
+	_OMAP4_BALLENTRY(FREF_CLK3_REQ, "ad3", NULL),
+	_OMAP4_BALLENTRY(FREF_CLK3_OUT, "ad4", NULL),
+	_OMAP4_BALLENTRY(FREF_CLK4_REQ, "ac2", NULL),
+	_OMAP4_BALLENTRY(FREF_CLK4_OUT, "ac3", NULL),
+	_OMAP4_BALLENTRY(SYS_32K, "ag7", NULL),
+	_OMAP4_BALLENTRY(SYS_NRESPWRON, "ae7", NULL),
+	_OMAP4_BALLENTRY(SYS_NRESWARM, "af7", NULL),
+	_OMAP4_BALLENTRY(SYS_PWR_REQ, "ah7", NULL),
+	_OMAP4_BALLENTRY(SYS_PWRON_RESET_OUT, "ag6", NULL),
+	_OMAP4_BALLENTRY(SYS_BOOT6, "af8", NULL),
+	_OMAP4_BALLENTRY(SYS_BOOT7, "ae8", NULL),
+	_OMAP4_BALLENTRY(JTAG_NTRST, "ah2", NULL),
+	_OMAP4_BALLENTRY(JTAG_TCK, "ag1", NULL),
+	_OMAP4_BALLENTRY(JTAG_RTCK, "ae3", NULL),
+	_OMAP4_BALLENTRY(JTAG_TMS_TMSC, "ah1", NULL),
+	_OMAP4_BALLENTRY(JTAG_TDI, "ae1", NULL),
+	_OMAP4_BALLENTRY(JTAG_TDO, "ae2", NULL),
+	{ .reg_offset = OMAP_MUX_TERMINATOR },
+};
+#else
+#define omap4_wkup_cbl_cbs_ball  NULL
+#endif
+
+int __init omap4_mux_init(struct omap_board_mux *board_subset, int flags)
+{
+	struct omap_ball *package_balls_core;
+	struct omap_ball *package_balls_wkup = omap4_wkup_cbl_cbs_ball;
+	struct omap_mux *core_muxmodes;
+	int ret;
+
+	switch (flags & OMAP_PACKAGE_MASK) {
+	case OMAP_PACKAGE_CBL:
+		pr_debug("%s: OMAP4430 ES1.0 -> OMAP_PACKAGE_CBL\n", __func__);
+		package_balls_core = omap4_core_cbl_ball;
+		core_muxmodes = omap4_core_muxmodes;
+		break;
+	case OMAP_PACKAGE_CBS:
+		pr_debug("%s: OMAP4430 ES2.X -> OMAP_PACKAGE_CBS\n", __func__);
+		package_balls_core = omap4_core_cbs_ball;
+		core_muxmodes = omap4_es2_core_muxmodes;
+		break;
+	default:
+		pr_err("%s: Unknown omap package, mux disabled\n", __func__);
+		return -EINVAL;
+	}
+
+	ret = omap_mux_init("core",
+			    OMAP_MUX_GPIO_IN_MODE3,
+			    OMAP4_CTRL_MODULE_PAD_CORE_MUX_PBASE,
+			    OMAP4_CTRL_MODULE_PAD_CORE_MUX_SIZE,
+			    core_muxmodes, NULL, board_subset,
+			    package_balls_core);
+	if (ret)
+		return ret;
+
+	ret = omap_mux_init("wkup",
+			    OMAP_MUX_GPIO_IN_MODE3,
+			    OMAP4_CTRL_MODULE_PAD_WKUP_MUX_PBASE,
+			    OMAP4_CTRL_MODULE_PAD_WKUP_MUX_SIZE,
+			    omap4_wkup_muxmodes, NULL, board_subset,
+			    package_balls_wkup);
+
+	return ret;
+}
+
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/mux44xx.h linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/mux44xx.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/mux44xx.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/mux44xx.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,298 @@
+/*
+ * OMAP44xx MUX registers and bitfields
+ *
+ * Copyright (C) 2009-2010 Texas Instruments, Inc.
+ *
+ * Benoit Cousson (b-cousson@ti.com)
+ *
+ * This file is automatically generated from the OMAP hardware databases.
+ * We respectfully ask that any modifications to this file be coordinated
+ * with the public linux-omap@vger.kernel.org mailing list and the
+ * authors above to ensure that the autogeneration scripts are kept
+ * up-to-date with the file contents.
+ *
+ * This program is free software; you can 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_MACH_OMAP2_MUX_44XX_H
+#define __ARCH_ARM_MACH_OMAP2_MUX_44XX_H
+
+#define OMAP4_MUX(M0, mux_value)					\
+{									\
+	.reg_offset	= (OMAP4_CTRL_MODULE_PAD_##M0##_OFFSET),	\
+	.value		= (mux_value),					\
+}
+
+/* ctrl_module_pad_core base address */
+#define OMAP4_CTRL_MODULE_PAD_CORE_MUX_PBASE			0x4a100000
+
+/* ctrl_module_pad_core registers offset */
+#define OMAP4_CTRL_MODULE_PAD_GPMC_AD0_OFFSET			0x0040
+#define OMAP4_CTRL_MODULE_PAD_GPMC_AD1_OFFSET			0x0042
+#define OMAP4_CTRL_MODULE_PAD_GPMC_AD2_OFFSET			0x0044
+#define OMAP4_CTRL_MODULE_PAD_GPMC_AD3_OFFSET			0x0046
+#define OMAP4_CTRL_MODULE_PAD_GPMC_AD4_OFFSET			0x0048
+#define OMAP4_CTRL_MODULE_PAD_GPMC_AD5_OFFSET			0x004a
+#define OMAP4_CTRL_MODULE_PAD_GPMC_AD6_OFFSET			0x004c
+#define OMAP4_CTRL_MODULE_PAD_GPMC_AD7_OFFSET			0x004e
+#define OMAP4_CTRL_MODULE_PAD_GPMC_AD8_OFFSET			0x0050
+#define OMAP4_CTRL_MODULE_PAD_GPMC_AD9_OFFSET			0x0052
+#define OMAP4_CTRL_MODULE_PAD_GPMC_AD10_OFFSET			0x0054
+#define OMAP4_CTRL_MODULE_PAD_GPMC_AD11_OFFSET			0x0056
+#define OMAP4_CTRL_MODULE_PAD_GPMC_AD12_OFFSET			0x0058
+#define OMAP4_CTRL_MODULE_PAD_GPMC_AD13_OFFSET			0x005a
+#define OMAP4_CTRL_MODULE_PAD_GPMC_AD14_OFFSET			0x005c
+#define OMAP4_CTRL_MODULE_PAD_GPMC_AD15_OFFSET			0x005e
+#define OMAP4_CTRL_MODULE_PAD_GPMC_A16_OFFSET			0x0060
+#define OMAP4_CTRL_MODULE_PAD_GPMC_A17_OFFSET			0x0062
+#define OMAP4_CTRL_MODULE_PAD_GPMC_A18_OFFSET			0x0064
+#define OMAP4_CTRL_MODULE_PAD_GPMC_A19_OFFSET			0x0066
+#define OMAP4_CTRL_MODULE_PAD_GPMC_A20_OFFSET			0x0068
+#define OMAP4_CTRL_MODULE_PAD_GPMC_A21_OFFSET			0x006a
+#define OMAP4_CTRL_MODULE_PAD_GPMC_A22_OFFSET			0x006c
+#define OMAP4_CTRL_MODULE_PAD_GPMC_A23_OFFSET			0x006e
+#define OMAP4_CTRL_MODULE_PAD_GPMC_A24_OFFSET			0x0070
+#define OMAP4_CTRL_MODULE_PAD_GPMC_A25_OFFSET			0x0072
+#define OMAP4_CTRL_MODULE_PAD_GPMC_NCS0_OFFSET			0x0074
+#define OMAP4_CTRL_MODULE_PAD_GPMC_NCS1_OFFSET			0x0076
+#define OMAP4_CTRL_MODULE_PAD_GPMC_NCS2_OFFSET			0x0078
+#define OMAP4_CTRL_MODULE_PAD_GPMC_NCS3_OFFSET			0x007a
+#define OMAP4_CTRL_MODULE_PAD_GPMC_NWP_OFFSET			0x007c
+#define OMAP4_CTRL_MODULE_PAD_GPMC_CLK_OFFSET			0x007e
+#define OMAP4_CTRL_MODULE_PAD_GPMC_NADV_ALE_OFFSET		0x0080
+#define OMAP4_CTRL_MODULE_PAD_GPMC_NOE_OFFSET			0x0082
+#define OMAP4_CTRL_MODULE_PAD_GPMC_NWE_OFFSET			0x0084
+#define OMAP4_CTRL_MODULE_PAD_GPMC_NBE0_CLE_OFFSET		0x0086
+#define OMAP4_CTRL_MODULE_PAD_GPMC_NBE1_OFFSET			0x0088
+#define OMAP4_CTRL_MODULE_PAD_GPMC_WAIT0_OFFSET			0x008a
+#define OMAP4_CTRL_MODULE_PAD_GPMC_WAIT1_OFFSET			0x008c
+#define OMAP4_CTRL_MODULE_PAD_C2C_DATA11_OFFSET			0x008e
+#define OMAP4_CTRL_MODULE_PAD_C2C_DATA12_OFFSET			0x0090
+#define OMAP4_CTRL_MODULE_PAD_C2C_DATA13_OFFSET			0x0092
+#define OMAP4_CTRL_MODULE_PAD_C2C_DATA14_OFFSET			0x0094
+#define OMAP4_CTRL_MODULE_PAD_C2C_DATA15_OFFSET			0x0096
+#define OMAP4_CTRL_MODULE_PAD_HDMI_HPD_OFFSET			0x0098
+#define OMAP4_CTRL_MODULE_PAD_HDMI_CEC_OFFSET			0x009a
+#define OMAP4_CTRL_MODULE_PAD_HDMI_DDC_SCL_OFFSET		0x009c
+#define OMAP4_CTRL_MODULE_PAD_HDMI_DDC_SDA_OFFSET		0x009e
+#define OMAP4_CTRL_MODULE_PAD_CSI21_DX0_OFFSET			0x00a0
+#define OMAP4_CTRL_MODULE_PAD_CSI21_DY0_OFFSET			0x00a2
+#define OMAP4_CTRL_MODULE_PAD_CSI21_DX1_OFFSET			0x00a4
+#define OMAP4_CTRL_MODULE_PAD_CSI21_DY1_OFFSET			0x00a6
+#define OMAP4_CTRL_MODULE_PAD_CSI21_DX2_OFFSET			0x00a8
+#define OMAP4_CTRL_MODULE_PAD_CSI21_DY2_OFFSET			0x00aa
+#define OMAP4_CTRL_MODULE_PAD_CSI21_DX3_OFFSET			0x00ac
+#define OMAP4_CTRL_MODULE_PAD_CSI21_DY3_OFFSET			0x00ae
+#define OMAP4_CTRL_MODULE_PAD_CSI21_DX4_OFFSET			0x00b0
+#define OMAP4_CTRL_MODULE_PAD_CSI21_DY4_OFFSET			0x00b2
+#define OMAP4_CTRL_MODULE_PAD_CSI22_DX0_OFFSET			0x00b4
+#define OMAP4_CTRL_MODULE_PAD_CSI22_DY0_OFFSET			0x00b6
+#define OMAP4_CTRL_MODULE_PAD_CSI22_DX1_OFFSET			0x00b8
+#define OMAP4_CTRL_MODULE_PAD_CSI22_DY1_OFFSET			0x00ba
+#define OMAP4_CTRL_MODULE_PAD_CAM_SHUTTER_OFFSET		0x00bc
+#define OMAP4_CTRL_MODULE_PAD_CAM_STROBE_OFFSET			0x00be
+#define OMAP4_CTRL_MODULE_PAD_CAM_GLOBALRESET_OFFSET		0x00c0
+#define OMAP4_CTRL_MODULE_PAD_USBB1_ULPITLL_CLK_OFFSET		0x00c2
+#define OMAP4_CTRL_MODULE_PAD_USBB1_ULPITLL_STP_OFFSET		0x00c4
+#define OMAP4_CTRL_MODULE_PAD_USBB1_ULPITLL_DIR_OFFSET		0x00c6
+#define OMAP4_CTRL_MODULE_PAD_USBB1_ULPITLL_NXT_OFFSET		0x00c8
+#define OMAP4_CTRL_MODULE_PAD_USBB1_ULPITLL_DAT0_OFFSET		0x00ca
+#define OMAP4_CTRL_MODULE_PAD_USBB1_ULPITLL_DAT1_OFFSET		0x00cc
+#define OMAP4_CTRL_MODULE_PAD_USBB1_ULPITLL_DAT2_OFFSET		0x00ce
+#define OMAP4_CTRL_MODULE_PAD_USBB1_ULPITLL_DAT3_OFFSET		0x00d0
+#define OMAP4_CTRL_MODULE_PAD_USBB1_ULPITLL_DAT4_OFFSET		0x00d2
+#define OMAP4_CTRL_MODULE_PAD_USBB1_ULPITLL_DAT5_OFFSET		0x00d4
+#define OMAP4_CTRL_MODULE_PAD_USBB1_ULPITLL_DAT6_OFFSET		0x00d6
+#define OMAP4_CTRL_MODULE_PAD_USBB1_ULPITLL_DAT7_OFFSET		0x00d8
+#define OMAP4_CTRL_MODULE_PAD_USBB1_HSIC_DATA_OFFSET		0x00da
+#define OMAP4_CTRL_MODULE_PAD_USBB1_HSIC_STROBE_OFFSET		0x00dc
+#define OMAP4_CTRL_MODULE_PAD_USBC1_ICUSB_DP_OFFSET		0x00de
+#define OMAP4_CTRL_MODULE_PAD_USBC1_ICUSB_DM_OFFSET		0x00e0
+#define OMAP4_CTRL_MODULE_PAD_SDMMC1_CLK_OFFSET			0x00e2
+#define OMAP4_CTRL_MODULE_PAD_SDMMC1_CMD_OFFSET			0x00e4
+#define OMAP4_CTRL_MODULE_PAD_SDMMC1_DAT0_OFFSET		0x00e6
+#define OMAP4_CTRL_MODULE_PAD_SDMMC1_DAT1_OFFSET		0x00e8
+#define OMAP4_CTRL_MODULE_PAD_SDMMC1_DAT2_OFFSET		0x00ea
+#define OMAP4_CTRL_MODULE_PAD_SDMMC1_DAT3_OFFSET		0x00ec
+#define OMAP4_CTRL_MODULE_PAD_SDMMC1_DAT4_OFFSET		0x00ee
+#define OMAP4_CTRL_MODULE_PAD_SDMMC1_DAT5_OFFSET		0x00f0
+#define OMAP4_CTRL_MODULE_PAD_SDMMC1_DAT6_OFFSET		0x00f2
+#define OMAP4_CTRL_MODULE_PAD_SDMMC1_DAT7_OFFSET		0x00f4
+#define OMAP4_CTRL_MODULE_PAD_ABE_MCBSP2_CLKX_OFFSET		0x00f6
+#define OMAP4_CTRL_MODULE_PAD_ABE_MCBSP2_DR_OFFSET		0x00f8
+#define OMAP4_CTRL_MODULE_PAD_ABE_MCBSP2_DX_OFFSET		0x00fa
+#define OMAP4_CTRL_MODULE_PAD_ABE_MCBSP2_FSX_OFFSET		0x00fc
+#define OMAP4_CTRL_MODULE_PAD_ABE_MCBSP1_CLKX_OFFSET		0x00fe
+#define OMAP4_CTRL_MODULE_PAD_ABE_MCBSP1_DR_OFFSET		0x0100
+#define OMAP4_CTRL_MODULE_PAD_ABE_MCBSP1_DX_OFFSET		0x0102
+#define OMAP4_CTRL_MODULE_PAD_ABE_MCBSP1_FSX_OFFSET		0x0104
+#define OMAP4_CTRL_MODULE_PAD_ABE_PDM_UL_DATA_OFFSET		0x0106
+#define OMAP4_CTRL_MODULE_PAD_ABE_PDM_DL_DATA_OFFSET		0x0108
+#define OMAP4_CTRL_MODULE_PAD_ABE_PDM_FRAME_OFFSET		0x010a
+#define OMAP4_CTRL_MODULE_PAD_ABE_PDM_LB_CLK_OFFSET		0x010c
+#define OMAP4_CTRL_MODULE_PAD_ABE_CLKS_OFFSET			0x010e
+#define OMAP4_CTRL_MODULE_PAD_ABE_DMIC_CLK1_OFFSET		0x0110
+#define OMAP4_CTRL_MODULE_PAD_ABE_DMIC_DIN1_OFFSET		0x0112
+#define OMAP4_CTRL_MODULE_PAD_ABE_DMIC_DIN2_OFFSET		0x0114
+#define OMAP4_CTRL_MODULE_PAD_ABE_DMIC_DIN3_OFFSET		0x0116
+#define OMAP4_CTRL_MODULE_PAD_UART2_CTS_OFFSET			0x0118
+#define OMAP4_CTRL_MODULE_PAD_UART2_RTS_OFFSET			0x011a
+#define OMAP4_CTRL_MODULE_PAD_UART2_RX_OFFSET			0x011c
+#define OMAP4_CTRL_MODULE_PAD_UART2_TX_OFFSET			0x011e
+#define OMAP4_CTRL_MODULE_PAD_HDQ_SIO_OFFSET			0x0120
+#define OMAP4_CTRL_MODULE_PAD_I2C1_SCL_OFFSET			0x0122
+#define OMAP4_CTRL_MODULE_PAD_I2C1_SDA_OFFSET			0x0124
+#define OMAP4_CTRL_MODULE_PAD_I2C2_SCL_OFFSET			0x0126
+#define OMAP4_CTRL_MODULE_PAD_I2C2_SDA_OFFSET			0x0128
+#define OMAP4_CTRL_MODULE_PAD_I2C3_SCL_OFFSET			0x012a
+#define OMAP4_CTRL_MODULE_PAD_I2C3_SDA_OFFSET			0x012c
+#define OMAP4_CTRL_MODULE_PAD_I2C4_SCL_OFFSET			0x012e
+#define OMAP4_CTRL_MODULE_PAD_I2C4_SDA_OFFSET			0x0130
+#define OMAP4_CTRL_MODULE_PAD_MCSPI1_CLK_OFFSET			0x0132
+#define OMAP4_CTRL_MODULE_PAD_MCSPI1_SOMI_OFFSET		0x0134
+#define OMAP4_CTRL_MODULE_PAD_MCSPI1_SIMO_OFFSET		0x0136
+#define OMAP4_CTRL_MODULE_PAD_MCSPI1_CS0_OFFSET			0x0138
+#define OMAP4_CTRL_MODULE_PAD_MCSPI1_CS1_OFFSET			0x013a
+#define OMAP4_CTRL_MODULE_PAD_MCSPI1_CS2_OFFSET			0x013c
+#define OMAP4_CTRL_MODULE_PAD_MCSPI1_CS3_OFFSET			0x013e
+#define OMAP4_CTRL_MODULE_PAD_UART3_CTS_RCTX_OFFSET		0x0140
+#define OMAP4_CTRL_MODULE_PAD_UART3_RTS_SD_OFFSET		0x0142
+#define OMAP4_CTRL_MODULE_PAD_UART3_RX_IRRX_OFFSET		0x0144
+#define OMAP4_CTRL_MODULE_PAD_UART3_TX_IRTX_OFFSET		0x0146
+#define OMAP4_CTRL_MODULE_PAD_SDMMC5_CLK_OFFSET			0x0148
+#define OMAP4_CTRL_MODULE_PAD_SDMMC5_CMD_OFFSET			0x014a
+#define OMAP4_CTRL_MODULE_PAD_SDMMC5_DAT0_OFFSET		0x014c
+#define OMAP4_CTRL_MODULE_PAD_SDMMC5_DAT1_OFFSET		0x014e
+#define OMAP4_CTRL_MODULE_PAD_SDMMC5_DAT2_OFFSET		0x0150
+#define OMAP4_CTRL_MODULE_PAD_SDMMC5_DAT3_OFFSET		0x0152
+#define OMAP4_CTRL_MODULE_PAD_MCSPI4_CLK_OFFSET			0x0154
+#define OMAP4_CTRL_MODULE_PAD_MCSPI4_SIMO_OFFSET		0x0156
+#define OMAP4_CTRL_MODULE_PAD_MCSPI4_SOMI_OFFSET		0x0158
+#define OMAP4_CTRL_MODULE_PAD_MCSPI4_CS0_OFFSET			0x015a
+#define OMAP4_CTRL_MODULE_PAD_UART4_RX_OFFSET			0x015c
+#define OMAP4_CTRL_MODULE_PAD_UART4_TX_OFFSET			0x015e
+#define OMAP4_CTRL_MODULE_PAD_USBB2_ULPITLL_CLK_OFFSET		0x0160
+#define OMAP4_CTRL_MODULE_PAD_USBB2_ULPITLL_STP_OFFSET		0x0162
+#define OMAP4_CTRL_MODULE_PAD_USBB2_ULPITLL_DIR_OFFSET		0x0164
+#define OMAP4_CTRL_MODULE_PAD_USBB2_ULPITLL_NXT_OFFSET		0x0166
+#define OMAP4_CTRL_MODULE_PAD_USBB2_ULPITLL_DAT0_OFFSET		0x0168
+#define OMAP4_CTRL_MODULE_PAD_USBB2_ULPITLL_DAT1_OFFSET		0x016a
+#define OMAP4_CTRL_MODULE_PAD_USBB2_ULPITLL_DAT2_OFFSET		0x016c
+#define OMAP4_CTRL_MODULE_PAD_USBB2_ULPITLL_DAT3_OFFSET		0x016e
+#define OMAP4_CTRL_MODULE_PAD_USBB2_ULPITLL_DAT4_OFFSET		0x0170
+#define OMAP4_CTRL_MODULE_PAD_USBB2_ULPITLL_DAT5_OFFSET		0x0172
+#define OMAP4_CTRL_MODULE_PAD_USBB2_ULPITLL_DAT6_OFFSET		0x0174
+#define OMAP4_CTRL_MODULE_PAD_USBB2_ULPITLL_DAT7_OFFSET		0x0176
+#define OMAP4_CTRL_MODULE_PAD_USBB2_HSIC_DATA_OFFSET		0x0178
+#define OMAP4_CTRL_MODULE_PAD_USBB2_HSIC_STROBE_OFFSET		0x017a
+#define OMAP4_CTRL_MODULE_PAD_UNIPRO_TX0_OFFSET			0x017c
+#define OMAP4_CTRL_MODULE_PAD_UNIPRO_TY0_OFFSET			0x017e
+#define OMAP4_CTRL_MODULE_PAD_UNIPRO_TX1_OFFSET			0x0180
+#define OMAP4_CTRL_MODULE_PAD_UNIPRO_TY1_OFFSET			0x0182
+#define OMAP4_CTRL_MODULE_PAD_UNIPRO_TX2_OFFSET			0x0184
+#define OMAP4_CTRL_MODULE_PAD_UNIPRO_TY2_OFFSET			0x0186
+#define OMAP4_CTRL_MODULE_PAD_UNIPRO_RX0_OFFSET			0x0188
+#define OMAP4_CTRL_MODULE_PAD_UNIPRO_RY0_OFFSET			0x018a
+#define OMAP4_CTRL_MODULE_PAD_UNIPRO_RX1_OFFSET			0x018c
+#define OMAP4_CTRL_MODULE_PAD_UNIPRO_RY1_OFFSET			0x018e
+#define OMAP4_CTRL_MODULE_PAD_UNIPRO_RX2_OFFSET			0x0190
+#define OMAP4_CTRL_MODULE_PAD_UNIPRO_RY2_OFFSET			0x0192
+#define OMAP4_CTRL_MODULE_PAD_USBA0_OTG_CE_OFFSET		0x0194
+#define OMAP4_CTRL_MODULE_PAD_USBA0_OTG_DP_OFFSET		0x0196
+#define OMAP4_CTRL_MODULE_PAD_USBA0_OTG_DM_OFFSET		0x0198
+#define OMAP4_CTRL_MODULE_PAD_FREF_CLK1_OUT_OFFSET		0x019a
+#define OMAP4_CTRL_MODULE_PAD_FREF_CLK2_OUT_OFFSET		0x019c
+#define OMAP4_CTRL_MODULE_PAD_SYS_NIRQ1_OFFSET			0x019e
+#define OMAP4_CTRL_MODULE_PAD_SYS_NIRQ2_OFFSET			0x01a0
+#define OMAP4_CTRL_MODULE_PAD_SYS_BOOT0_OFFSET			0x01a2
+#define OMAP4_CTRL_MODULE_PAD_SYS_BOOT1_OFFSET			0x01a4
+#define OMAP4_CTRL_MODULE_PAD_SYS_BOOT2_OFFSET			0x01a6
+#define OMAP4_CTRL_MODULE_PAD_SYS_BOOT3_OFFSET			0x01a8
+#define OMAP4_CTRL_MODULE_PAD_SYS_BOOT4_OFFSET			0x01aa
+#define OMAP4_CTRL_MODULE_PAD_SYS_BOOT5_OFFSET			0x01ac
+#define OMAP4_CTRL_MODULE_PAD_DPM_EMU0_OFFSET			0x01ae
+#define OMAP4_CTRL_MODULE_PAD_DPM_EMU1_OFFSET			0x01b0
+#define OMAP4_CTRL_MODULE_PAD_DPM_EMU2_OFFSET			0x01b2
+#define OMAP4_CTRL_MODULE_PAD_DPM_EMU3_OFFSET			0x01b4
+#define OMAP4_CTRL_MODULE_PAD_DPM_EMU4_OFFSET			0x01b6
+#define OMAP4_CTRL_MODULE_PAD_DPM_EMU5_OFFSET			0x01b8
+#define OMAP4_CTRL_MODULE_PAD_DPM_EMU6_OFFSET			0x01ba
+#define OMAP4_CTRL_MODULE_PAD_DPM_EMU7_OFFSET			0x01bc
+#define OMAP4_CTRL_MODULE_PAD_DPM_EMU8_OFFSET			0x01be
+#define OMAP4_CTRL_MODULE_PAD_DPM_EMU9_OFFSET			0x01c0
+#define OMAP4_CTRL_MODULE_PAD_DPM_EMU10_OFFSET			0x01c2
+#define OMAP4_CTRL_MODULE_PAD_DPM_EMU11_OFFSET			0x01c4
+#define OMAP4_CTRL_MODULE_PAD_DPM_EMU12_OFFSET			0x01c6
+#define OMAP4_CTRL_MODULE_PAD_DPM_EMU13_OFFSET			0x01c8
+#define OMAP4_CTRL_MODULE_PAD_DPM_EMU14_OFFSET			0x01ca
+#define OMAP4_CTRL_MODULE_PAD_DPM_EMU15_OFFSET			0x01cc
+#define OMAP4_CTRL_MODULE_PAD_DPM_EMU16_OFFSET			0x01ce
+#define OMAP4_CTRL_MODULE_PAD_DPM_EMU17_OFFSET			0x01d0
+#define OMAP4_CTRL_MODULE_PAD_DPM_EMU18_OFFSET			0x01d2
+#define OMAP4_CTRL_MODULE_PAD_DPM_EMU19_OFFSET			0x01d4
+
+/* ES2.0 only */
+#define OMAP4_CTRL_MODULE_PAD_GPMC_WAIT2_OFFSET			0x008e
+#define OMAP4_CTRL_MODULE_PAD_GPMC_NCS4_OFFSET			0x0090
+#define OMAP4_CTRL_MODULE_PAD_GPMC_NCS5_OFFSET			0x0092
+#define OMAP4_CTRL_MODULE_PAD_GPMC_NCS6_OFFSET			0x0094
+#define OMAP4_CTRL_MODULE_PAD_GPMC_NCS7_OFFSET			0x0096
+
+#define OMAP4_CTRL_MODULE_PAD_KPD_COL3_OFFSET			0x017c
+#define OMAP4_CTRL_MODULE_PAD_KPD_COL4_OFFSET			0x017e
+#define OMAP4_CTRL_MODULE_PAD_KPD_COL5_OFFSET			0x0180
+#define OMAP4_CTRL_MODULE_PAD_KPD_COL0_OFFSET			0x0182
+#define OMAP4_CTRL_MODULE_PAD_KPD_COL1_OFFSET			0x0184
+#define OMAP4_CTRL_MODULE_PAD_KPD_COL2_OFFSET			0x0186
+#define OMAP4_CTRL_MODULE_PAD_KPD_ROW3_OFFSET			0x0188
+#define OMAP4_CTRL_MODULE_PAD_KPD_ROW4_OFFSET			0x018a
+#define OMAP4_CTRL_MODULE_PAD_KPD_ROW5_OFFSET			0x018c
+#define OMAP4_CTRL_MODULE_PAD_KPD_ROW0_OFFSET			0x018e
+#define OMAP4_CTRL_MODULE_PAD_KPD_ROW1_OFFSET			0x0190
+#define OMAP4_CTRL_MODULE_PAD_KPD_ROW2_OFFSET			0x0192
+
+
+#define OMAP4_CTRL_MODULE_PAD_CORE_MUX_SIZE			\
+		(OMAP4_CTRL_MODULE_PAD_DPM_EMU19_OFFSET		\
+		 - OMAP4_CTRL_MODULE_PAD_GPMC_AD0_OFFSET + 2)
+
+/* ctrl_module_pad_wkup base address */
+#define OMAP4_CTRL_MODULE_PAD_WKUP_MUX_PBASE			0x4a31e000
+
+/* ctrl_module_pad_wkup registers offset */
+#define OMAP4_CTRL_MODULE_PAD_SIM_IO_OFFSET			0x0040
+#define OMAP4_CTRL_MODULE_PAD_SIM_CLK_OFFSET			0x0042
+#define OMAP4_CTRL_MODULE_PAD_SIM_RESET_OFFSET			0x0044
+#define OMAP4_CTRL_MODULE_PAD_SIM_CD_OFFSET			0x0046
+#define OMAP4_CTRL_MODULE_PAD_SIM_PWRCTRL_OFFSET		0x0048
+#define OMAP4_CTRL_MODULE_PAD_SR_SCL_OFFSET			0x004a
+#define OMAP4_CTRL_MODULE_PAD_SR_SDA_OFFSET			0x004c
+#define OMAP4_CTRL_MODULE_PAD_FREF_XTAL_IN_OFFSET		0x004e
+#define OMAP4_CTRL_MODULE_PAD_FREF_SLICER_IN_OFFSET		0x0050
+#define OMAP4_CTRL_MODULE_PAD_FREF_CLK_IOREQ_OFFSET		0x0052
+#define OMAP4_CTRL_MODULE_PAD_FREF_CLK0_OUT_OFFSET		0x0054
+#define OMAP4_CTRL_MODULE_PAD_FREF_CLK3_REQ_OFFSET		0x0056
+#define OMAP4_CTRL_MODULE_PAD_FREF_CLK3_OUT_OFFSET		0x0058
+#define OMAP4_CTRL_MODULE_PAD_FREF_CLK4_REQ_OFFSET		0x005a
+#define OMAP4_CTRL_MODULE_PAD_FREF_CLK4_OUT_OFFSET		0x005c
+#define OMAP4_CTRL_MODULE_PAD_SYS_32K_OFFSET			0x005e
+#define OMAP4_CTRL_MODULE_PAD_SYS_NRESPWRON_OFFSET		0x0060
+#define OMAP4_CTRL_MODULE_PAD_SYS_NRESWARM_OFFSET		0x0062
+#define OMAP4_CTRL_MODULE_PAD_SYS_PWR_REQ_OFFSET		0x0064
+#define OMAP4_CTRL_MODULE_PAD_SYS_PWRON_RESET_OUT_OFFSET	0x0066
+#define OMAP4_CTRL_MODULE_PAD_SYS_BOOT6_OFFSET			0x0068
+#define OMAP4_CTRL_MODULE_PAD_SYS_BOOT7_OFFSET			0x006a
+#define OMAP4_CTRL_MODULE_PAD_JTAG_NTRST_OFFSET			0x006c
+#define OMAP4_CTRL_MODULE_PAD_JTAG_TCK_OFFSET			0x006e
+#define OMAP4_CTRL_MODULE_PAD_JTAG_RTCK_OFFSET			0x0070
+#define OMAP4_CTRL_MODULE_PAD_JTAG_TMS_TMSC_OFFSET		0x0072
+#define OMAP4_CTRL_MODULE_PAD_JTAG_TDI_OFFSET			0x0074
+#define OMAP4_CTRL_MODULE_PAD_JTAG_TDO_OFFSET			0x0076
+
+#define OMAP4_CTRL_MODULE_PAD_WKUP_MUX_SIZE			\
+		(OMAP4_CTRL_MODULE_PAD_JTAG_TDO_OFFSET		\
+		 - OMAP4_CTRL_MODULE_PAD_SIM_IO_OFFSET + 2)
+
+#endif
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/mux.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/mux.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/mux.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/mux.c	2011-03-14 21:20:32.000000000 -0400
@@ -1,9 +1,9 @@
 /*
  * linux/arch/arm/mach-omap2/mux.c
  *
- * OMAP2 and OMAP3 pin multiplexing configurations
+ * OMAP2, OMAP3 and OMAP4 pin multiplexing configurations
  *
- * Copyright (C) 2004 - 2008 Texas Instruments Inc.
+ * Copyright (C) 2004 - 2010 Texas Instruments Inc.
  * Copyright (C) 2003 - 2008 Nokia Corporation
  *
  * Written by Tony Lindgren
@@ -35,65 +35,79 @@
 
 #include <asm/system.h>
 
+#include <plat/omap_hwmod.h>
+
 #include "control.h"
 #include "mux.h"
 
 #define OMAP_MUX_BASE_OFFSET		0x30	/* Offset from CTRL_BASE */
 #define OMAP_MUX_BASE_SZ		0x5ca
-#define MUXABLE_GPIO_MODE3		BIT(0)
 
 struct omap_mux_entry {
 	struct omap_mux		mux;
 	struct list_head	node;
 };
 
-static unsigned long mux_phys;
-static void __iomem *mux_base;
-static u8 omap_mux_flags;
+static LIST_HEAD(mux_partitions);
+static DEFINE_MUTEX(muxmode_mutex);
 
-u16 omap_mux_read(u16 reg)
+struct omap_mux_partition *omap_mux_get(const char *name)
 {
-	if (cpu_is_omap24xx())
-		return __raw_readb(mux_base + reg);
+	struct omap_mux_partition *partition;
+
+	list_for_each_entry(partition, &mux_partitions, node) {
+		if (!strcmp(name, partition->name))
+			return partition;
+	}
+
+	return NULL;
+}
+
+u16 omap_mux_read(struct omap_mux_partition *partition, u16 reg)
+{
+	if (partition->flags & OMAP_MUX_REG_8BIT)
+		return __raw_readb(partition->base + reg);
 	else
-		return __raw_readw(mux_base + reg);
+		return __raw_readw(partition->base + reg);
 }
 
-void omap_mux_write(u16 val, u16 reg)
+void omap_mux_write(struct omap_mux_partition *partition, u16 val,
+			   u16 reg)
 {
-	if (cpu_is_omap24xx())
-		__raw_writeb(val, mux_base + reg);
+	if (partition->flags & OMAP_MUX_REG_8BIT)
+		__raw_writeb(val, partition->base + reg);
 	else
-		__raw_writew(val, mux_base + reg);
+		__raw_writew(val, partition->base + reg);
 }
 
-void omap_mux_write_array(struct omap_board_mux *board_mux)
+void omap_mux_write_array(struct omap_mux_partition *partition,
+				 struct omap_board_mux *board_mux)
 {
-	while (board_mux->reg_offset !=  OMAP_MUX_TERMINATOR) {
-		omap_mux_write(board_mux->value, board_mux->reg_offset);
+	while (board_mux->reg_offset != OMAP_MUX_TERMINATOR) {
+		omap_mux_write(partition, board_mux->value,
+			       board_mux->reg_offset);
 		board_mux++;
 	}
 }
 
-static LIST_HEAD(muxmodes);
-static DEFINE_MUTEX(muxmode_mutex);
-
 #ifdef CONFIG_OMAP_MUX
 
 static char *omap_mux_options;
 
-int __init omap_mux_init_gpio(int gpio, int val)
+static int __init _omap_mux_init_gpio(struct omap_mux_partition *partition,
+				      int gpio, int val)
 {
 	struct omap_mux_entry *e;
 	struct omap_mux *gpio_mux = NULL;
 	u16 old_mode;
 	u16 mux_mode;
 	int found = 0;
+	struct list_head *muxmodes = &partition->muxmodes;
 
 	if (!gpio)
 		return -EINVAL;
 
-	list_for_each_entry(e, &muxmodes, node) {
+	list_for_each_entry(e, muxmodes, node) {
 		struct omap_mux *m = &e->mux;
 		if (gpio == m->gpio) {
 			gpio_mux = m;
@@ -102,34 +116,52 @@ int __init omap_mux_init_gpio(int gpio,
 	}
 
 	if (found == 0) {
-		printk(KERN_ERR "mux: Could not set gpio%i\n", gpio);
+		pr_err("%s: Could not set gpio%i\n", __func__, gpio);
 		return -ENODEV;
 	}
 
 	if (found > 1) {
-		printk(KERN_INFO "mux: Multiple gpio paths (%d) for gpio%i\n",
-				found, gpio);
+		pr_info("%s: Multiple gpio paths (%d) for gpio%i\n", __func__,
+			found, gpio);
 		return -EINVAL;
 	}
 
-	old_mode = omap_mux_read(gpio_mux->reg_offset);
+	old_mode = omap_mux_read(partition, gpio_mux->reg_offset);
 	mux_mode = val & ~(OMAP_MUX_NR_MODES - 1);
-	if (omap_mux_flags & MUXABLE_GPIO_MODE3)
+	if (partition->flags & OMAP_MUX_GPIO_IN_MODE3)
 		mux_mode |= OMAP_MUX_MODE3;
 	else
 		mux_mode |= OMAP_MUX_MODE4;
-	printk(KERN_DEBUG "mux: Setting signal %s.gpio%i 0x%04x -> 0x%04x\n",
-			gpio_mux->muxnames[0], gpio, old_mode, mux_mode);
-	omap_mux_write(mux_mode, gpio_mux->reg_offset);
+	pr_debug("%s: Setting signal %s.gpio%i 0x%04x -> 0x%04x\n", __func__,
+		 gpio_mux->muxnames[0], gpio, old_mode, mux_mode);
+	omap_mux_write(partition, mux_mode, gpio_mux->reg_offset);
 
 	return 0;
 }
 
-int __init omap_mux_init_signal(const char *muxname, int val)
+int __init omap_mux_init_gpio(int gpio, int val)
 {
+	struct omap_mux_partition *partition;
+	int ret;
+
+	list_for_each_entry(partition, &mux_partitions, node) {
+		ret = _omap_mux_init_gpio(partition, gpio, val);
+		if (!ret)
+			return ret;
+	}
+
+	return -ENODEV;
+}
+
+static int __init _omap_mux_get_by_name(struct omap_mux_partition *partition,
+					const char *muxname,
+					struct omap_mux **found_mux)
+{
+	struct omap_mux *mux = NULL;
 	struct omap_mux_entry *e;
 	const char *mode_name;
-	int found = 0, mode0_len = 0;
+	int found = 0, found_mode = 0, mode0_len = 0;
+	struct list_head *muxmodes = &partition->muxmodes;
 
 	mode_name = strchr(muxname, '.');
 	if (mode_name) {
@@ -139,51 +171,200 @@ int __init omap_mux_init_signal(const ch
 		mode_name = muxname;
 	}
 
-	list_for_each_entry(e, &muxmodes, node) {
-		struct omap_mux *m = &e->mux;
-		char *m0_entry = m->muxnames[0];
+	list_for_each_entry(e, muxmodes, node) {
+		char *m0_entry;
 		int i;
 
+		mux = &e->mux;
+		m0_entry = mux->muxnames[0];
+
 		/* First check for full name in mode0.muxmode format */
 		if (mode0_len && strncmp(muxname, m0_entry, mode0_len))
 			continue;
 
 		/* Then check for muxmode only */
 		for (i = 0; i < OMAP_MUX_NR_MODES; i++) {
-			char *mode_cur = m->muxnames[i];
+			char *mode_cur = mux->muxnames[i];
 
 			if (!mode_cur)
 				continue;
 
 			if (!strcmp(mode_name, mode_cur)) {
-				u16 old_mode;
-				u16 mux_mode;
-
-				old_mode = omap_mux_read(m->reg_offset);
-				mux_mode = val | i;
-				printk(KERN_DEBUG "mux: Setting signal "
-					"%s.%s 0x%04x -> 0x%04x\n",
-					m0_entry, muxname, old_mode, mux_mode);
-				omap_mux_write(mux_mode, m->reg_offset);
+				*found_mux = mux;
 				found++;
+				found_mode = i;
 			}
 		}
 	}
 
-	if (found == 1)
-		return 0;
+	if (found == 1) {
+		return found_mode;
+	}
 
 	if (found > 1) {
-		printk(KERN_ERR "mux: Multiple signal paths (%i) for %s\n",
-				found, muxname);
+		pr_err("%s: Multiple signal paths (%i) for %s\n", __func__,
+		       found, muxname);
 		return -EINVAL;
 	}
 
-	printk(KERN_ERR "mux: Could not set signal %s\n", muxname);
+	pr_err("%s: Could not find signal %s\n", __func__, muxname);
+
+	return -ENODEV;
+}
+
+static int __init
+omap_mux_get_by_name(const char *muxname,
+			struct omap_mux_partition **found_partition,
+			struct omap_mux **found_mux)
+{
+	struct omap_mux_partition *partition;
+
+	list_for_each_entry(partition, &mux_partitions, node) {
+		struct omap_mux *mux = NULL;
+		int mux_mode = _omap_mux_get_by_name(partition, muxname, &mux);
+		if (mux_mode < 0)
+			continue;
+
+		*found_partition = partition;
+		*found_mux = mux;
+
+		return mux_mode;
+	}
 
 	return -ENODEV;
 }
 
+int __init omap_mux_init_signal(const char *muxname, int val)
+{
+	struct omap_mux_partition *partition = NULL;
+	struct omap_mux *mux = NULL;
+	u16 old_mode;
+	int mux_mode;
+
+	mux_mode = omap_mux_get_by_name(muxname, &partition, &mux);
+	if (mux_mode < 0)
+		return mux_mode;
+
+	old_mode = omap_mux_read(partition, mux->reg_offset);
+	mux_mode |= val;
+	pr_debug("%s: Setting signal %s 0x%04x -> 0x%04x\n",
+			 __func__, muxname, old_mode, mux_mode);
+	omap_mux_write(partition, mux_mode, mux->reg_offset);
+
+	return 0;
+}
+
+struct omap_hwmod_mux_info * __init
+omap_hwmod_mux_init(struct omap_device_pad *bpads, int nr_pads)
+{
+	struct omap_hwmod_mux_info *hmux;
+	int i;
+
+	if (!bpads || nr_pads < 1)
+		return NULL;
+
+	hmux = kzalloc(sizeof(struct omap_hwmod_mux_info), GFP_KERNEL);
+	if (!hmux)
+		goto err1;
+
+	hmux->nr_pads = nr_pads;
+
+	hmux->pads = kzalloc(sizeof(struct omap_device_pad) *
+				nr_pads, GFP_KERNEL);
+	if (!hmux->pads)
+		goto err2;
+
+	for (i = 0; i < hmux->nr_pads; i++) {
+		struct omap_mux_partition *partition;
+		struct omap_device_pad *bpad = &bpads[i], *pad = &hmux->pads[i];
+		struct omap_mux *mux;
+		int mux_mode;
+
+		mux_mode = omap_mux_get_by_name(bpad->name, &partition, &mux);
+		if (mux_mode < 0)
+			goto err3;
+		if (!pad->partition)
+			pad->partition = partition;
+		if (!pad->mux)
+			pad->mux = mux;
+
+		pad->name = kzalloc(strlen(bpad->name) + 1, GFP_KERNEL);
+		if (!pad->name) {
+			int j;
+
+			for (j = i - 1; j >= 0; j--)
+				kfree(hmux->pads[j].name);
+			goto err3;
+		}
+		strcpy(pad->name, bpad->name);
+
+		pad->flags = bpad->flags;
+		pad->enable = bpad->enable;
+		pad->idle = bpad->idle;
+		pad->off = bpad->off;
+		pr_debug("%s: Initialized %s\n", __func__, pad->name);
+	}
+
+	return hmux;
+
+err3:
+	kfree(hmux->pads);
+err2:
+	kfree(hmux);
+err1:
+	pr_err("%s: Could not allocate device mux entry\n", __func__);
+
+	return NULL;
+}
+
+/* Assumes the calling function takes care of locking */
+void omap_hwmod_mux(struct omap_hwmod_mux_info *hmux, u8 state)
+{
+	int i;
+
+	for (i = 0; i < hmux->nr_pads; i++) {
+		struct omap_device_pad *pad = &hmux->pads[i];
+		int flags, val = -EINVAL;
+
+		flags = pad->flags;
+
+		switch (state) {
+		case _HWMOD_STATE_ENABLED:
+			if (flags & OMAP_DEVICE_PAD_ENABLED)
+				break;
+			flags |= OMAP_DEVICE_PAD_ENABLED;
+			val = pad->enable;
+			pr_debug("%s: Enabling %s %x\n", __func__,
+					pad->name, val);
+			break;
+		case _HWMOD_STATE_IDLE:
+			if (!(flags & OMAP_DEVICE_PAD_REMUX))
+				break;
+			flags &= ~OMAP_DEVICE_PAD_ENABLED;
+			val = pad->idle;
+			pr_debug("%s: Idling %s %x\n", __func__,
+					pad->name, val);
+			break;
+		case _HWMOD_STATE_DISABLED:
+		default:
+			/* Use safe mode unless OMAP_DEVICE_PAD_REMUX */
+			if (flags & OMAP_DEVICE_PAD_REMUX)
+				val = pad->off;
+			else
+				val = OMAP_MUX_MODE7;
+			flags &= ~OMAP_DEVICE_PAD_ENABLED;
+			pr_debug("%s: Disabling %s %x\n", __func__,
+					pad->name, val);
+		};
+
+		if (val >= 0) {
+			omap_mux_write(pad->partition, val,
+					pad->mux->reg_offset);
+			pad->flags = flags;
+		}
+	}
+}
+
 #ifdef CONFIG_DEBUG_FS
 
 #define OMAP_MUX_MAX_NR_FLAGS	10
@@ -248,13 +429,15 @@ static inline void omap_mux_decode(struc
 	} while (i-- > 0);
 }
 
-#define OMAP_MUX_DEFNAME_LEN	16
+#define OMAP_MUX_DEFNAME_LEN	32
 
 static int omap_mux_dbg_board_show(struct seq_file *s, void *unused)
 {
+	struct omap_mux_partition *partition = s->private;
 	struct omap_mux_entry *e;
+	u8 omap_gen = omap_rev() >> 28;
 
-	list_for_each_entry(e, &muxmodes, node) {
+	list_for_each_entry(e, &partition->muxmodes, node) {
 		struct omap_mux *m = &e->mux;
 		char m0_def[OMAP_MUX_DEFNAME_LEN];
 		char *m0_name = m->muxnames[0];
@@ -272,11 +455,16 @@ static int omap_mux_dbg_board_show(struc
 			}
 			m0_def[i] = toupper(m0_name[i]);
 		}
-		val = omap_mux_read(m->reg_offset);
+		val = omap_mux_read(partition, m->reg_offset);
 		mode = val & OMAP_MUX_MODE7;
+		if (mode != 0)
+			seq_printf(s, "/* %s */\n", m->muxnames[mode]);
 
-		seq_printf(s, "OMAP%i_MUX(%s, ",
-					cpu_is_omap34xx() ? 3 : 0, m0_def);
+		/*
+		 * XXX: Might be revisited to support differences accross
+		 * same OMAP generation.
+		 */
+		seq_printf(s, "OMAP%d_MUX(%s, ", omap_gen, m0_def);
 		omap_mux_decode(s, val);
 		seq_printf(s, "),\n");
 	}
@@ -286,7 +474,7 @@ static int omap_mux_dbg_board_show(struc
 
 static int omap_mux_dbg_board_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, omap_mux_dbg_board_show, &inode->i_private);
+	return single_open(file, omap_mux_dbg_board_show, inode->i_private);
 }
 
 static const struct file_operations omap_mux_dbg_board_fops = {
@@ -296,19 +484,43 @@ static const struct file_operations omap
 	.release	= single_release,
 };
 
+static struct omap_mux_partition *omap_mux_get_partition(struct omap_mux *mux)
+{
+	struct omap_mux_partition *partition;
+
+	list_for_each_entry(partition, &mux_partitions, node) {
+		struct list_head *muxmodes = &partition->muxmodes;
+		struct omap_mux_entry *e;
+
+		list_for_each_entry(e, muxmodes, node) {
+			struct omap_mux *m = &e->mux;
+
+			if (m == mux)
+				return partition;
+		}
+	}
+
+	return NULL;
+}
+
 static int omap_mux_dbg_signal_show(struct seq_file *s, void *unused)
 {
 	struct omap_mux *m = s->private;
+	struct omap_mux_partition *partition;
 	const char *none = "NA";
 	u16 val;
 	int mode;
 
-	val = omap_mux_read(m->reg_offset);
+	partition = omap_mux_get_partition(m);
+	if (!partition)
+		return 0;
+
+	val = omap_mux_read(partition, m->reg_offset);
 	mode = val & OMAP_MUX_MODE7;
 
-	seq_printf(s, "name: %s.%s (0x%08lx/0x%03x = 0x%04x), b %s, t %s\n",
+	seq_printf(s, "name: %s.%s (0x%08x/0x%03x = 0x%04x), b %s, t %s\n",
 			m->muxnames[0], m->muxnames[mode],
-			mux_phys + m->reg_offset, m->reg_offset, val,
+			partition->phys + m->reg_offset, m->reg_offset, val,
 			m->balls[0] ? m->balls[0] : none,
 			m->balls[1] ? m->balls[1] : none);
 	seq_printf(s, "mode: ");
@@ -330,14 +542,15 @@ static int omap_mux_dbg_signal_show(stru
 #define OMAP_MUX_MAX_ARG_CHAR  7
 
 static ssize_t omap_mux_dbg_signal_write(struct file *file,
-						const char __user *user_buf,
-						size_t count, loff_t *ppos)
+					 const char __user *user_buf,
+					 size_t count, loff_t *ppos)
 {
 	char buf[OMAP_MUX_MAX_ARG_CHAR];
 	struct seq_file *seqf;
 	struct omap_mux *m;
 	unsigned long val;
 	int buf_size, ret;
+	struct omap_mux_partition *partition;
 
 	if (count > OMAP_MUX_MAX_ARG_CHAR)
 		return -EINVAL;
@@ -358,7 +571,11 @@ static ssize_t omap_mux_dbg_signal_write
 	seqf = file->private_data;
 	m = seqf->private;
 
-	omap_mux_write((u16)val, m->reg_offset);
+	partition = omap_mux_get_partition(m);
+	if (!partition)
+		return -ENODEV;
+
+	omap_mux_write(partition, (u16)val, m->reg_offset);
 	*ppos += count;
 
 	return count;
@@ -379,22 +596,38 @@ static const struct file_operations omap
 
 static struct dentry *mux_dbg_dir;
 
-static void __init omap_mux_dbg_init(void)
+static void __init omap_mux_dbg_create_entry(
+				struct omap_mux_partition *partition,
+				struct dentry *mux_dbg_dir)
 {
 	struct omap_mux_entry *e;
 
+	list_for_each_entry(e, &partition->muxmodes, node) {
+		struct omap_mux *m = &e->mux;
+
+		(void)debugfs_create_file(m->muxnames[0], S_IWUSR, mux_dbg_dir,
+					  m, &omap_mux_dbg_signal_fops);
+	}
+}
+
+static void __init omap_mux_dbg_init(void)
+{
+	struct omap_mux_partition *partition;
+	static struct dentry *mux_dbg_board_dir;
+
 	mux_dbg_dir = debugfs_create_dir("omap_mux", NULL);
 	if (!mux_dbg_dir)
 		return;
 
-	(void)debugfs_create_file("board", S_IRUGO, mux_dbg_dir,
-					NULL, &omap_mux_dbg_board_fops);
-
-	list_for_each_entry(e, &muxmodes, node) {
-		struct omap_mux *m = &e->mux;
+	mux_dbg_board_dir = debugfs_create_dir("board", mux_dbg_dir);
+	if (!mux_dbg_board_dir)
+		return;
 
-		(void)debugfs_create_file(m->muxnames[0], S_IWUGO, mux_dbg_dir,
-					m, &omap_mux_dbg_signal_fops);
+	list_for_each_entry(partition, &mux_partitions, node) {
+		omap_mux_dbg_create_entry(partition, mux_dbg_dir);
+		(void)debugfs_create_file(partition->name, S_IRUGO,
+					  mux_dbg_board_dir, partition,
+					  &omap_mux_dbg_board_fops);
 	}
 }
 
@@ -421,23 +654,25 @@ static void __init omap_mux_free_names(s
 /* Free all data except for GPIO pins unless CONFIG_DEBUG_FS is set */
 static int __init omap_mux_late_init(void)
 {
-	struct omap_mux_entry *e, *tmp;
+	struct omap_mux_partition *partition;
 
-	list_for_each_entry_safe(e, tmp, &muxmodes, node) {
-		struct omap_mux *m = &e->mux;
-		u16 mode = omap_mux_read(m->reg_offset);
+	list_for_each_entry(partition, &mux_partitions, node) {
+		struct omap_mux_entry *e, *tmp;
+		list_for_each_entry_safe(e, tmp, &partition->muxmodes, node) {
+			struct omap_mux *m = &e->mux;
+			u16 mode = omap_mux_read(partition, m->reg_offset);
 
-		if (OMAP_MODE_GPIO(mode))
-			continue;
+			if (OMAP_MODE_GPIO(mode))
+				continue;
 
 #ifndef CONFIG_DEBUG_FS
-		mutex_lock(&muxmode_mutex);
-		list_del(&e->node);
-		mutex_unlock(&muxmode_mutex);
-		omap_mux_free_names(m);
-		kfree(m);
+			mutex_lock(&muxmode_mutex);
+			list_del(&e->node);
+			mutex_unlock(&muxmode_mutex);
+			omap_mux_free_names(m);
+			kfree(m);
 #endif
-
+		}
 	}
 
 	omap_mux_dbg_init();
@@ -462,8 +697,8 @@ static void __init omap_mux_package_fixu
 			s++;
 		}
 		if (!found)
-			printk(KERN_ERR "mux: Unknown entry offset 0x%x\n",
-					p->reg_offset);
+			pr_err("%s: Unknown entry offset 0x%x\n", __func__,
+			       p->reg_offset);
 		p++;
 	}
 }
@@ -487,8 +722,8 @@ static void __init omap_mux_package_init
 			s++;
 		}
 		if (!found)
-			printk(KERN_ERR "mux: Unknown ball offset 0x%x\n",
-					b->reg_offset);
+			pr_err("%s: Unknown ball offset 0x%x\n", __func__,
+			       b->reg_offset);
 		b++;
 	}
 }
@@ -554,7 +789,7 @@ static void __init omap_mux_set_cmdline_
 }
 
 static int __init omap_mux_copy_names(struct omap_mux *src,
-					struct omap_mux *dst)
+				      struct omap_mux *dst)
 {
 	int i;
 
@@ -592,51 +827,63 @@ free:
 
 #endif	/* CONFIG_OMAP_MUX */
 
-static u16 omap_mux_get_by_gpio(int gpio)
+static struct omap_mux *omap_mux_get_by_gpio(
+				struct omap_mux_partition *partition,
+				int gpio)
 {
 	struct omap_mux_entry *e;
-	u16 offset = OMAP_MUX_TERMINATOR;
+	struct omap_mux *ret = NULL;
 
-	list_for_each_entry(e, &muxmodes, node) {
+	list_for_each_entry(e, &partition->muxmodes, node) {
 		struct omap_mux *m = &e->mux;
 		if (m->gpio == gpio) {
-			offset = m->reg_offset;
+			ret = m;
 			break;
 		}
 	}
 
-	return offset;
+	return ret;
 }
 
 /* Needed for dynamic muxing of GPIO pins for off-idle */
 u16 omap_mux_get_gpio(int gpio)
 {
-	u16 offset;
+	struct omap_mux_partition *partition;
+	struct omap_mux *m;
 
-	offset = omap_mux_get_by_gpio(gpio);
-	if (offset == OMAP_MUX_TERMINATOR) {
-		printk(KERN_ERR "mux: Could not get gpio%i\n", gpio);
-		return offset;
+	list_for_each_entry(partition, &mux_partitions, node) {
+		m = omap_mux_get_by_gpio(partition, gpio);
+		if (m)
+			return omap_mux_read(partition, m->reg_offset);
 	}
 
-	return omap_mux_read(offset);
+	if (!m || m->reg_offset == OMAP_MUX_TERMINATOR)
+		pr_err("%s: Could not get gpio%i\n", __func__, gpio);
+
+	return OMAP_MUX_TERMINATOR;
 }
 
 /* Needed for dynamic muxing of GPIO pins for off-idle */
 void omap_mux_set_gpio(u16 val, int gpio)
 {
-	u16 offset;
+	struct omap_mux_partition *partition;
+	struct omap_mux *m = NULL;
 
-	offset = omap_mux_get_by_gpio(gpio);
-	if (offset == OMAP_MUX_TERMINATOR) {
-		printk(KERN_ERR "mux: Could not set gpio%i\n", gpio);
-		return;
+	list_for_each_entry(partition, &mux_partitions, node) {
+		m = omap_mux_get_by_gpio(partition, gpio);
+		if (m) {
+			omap_mux_write(partition, val, m->reg_offset);
+			return;
+		}
 	}
 
-	omap_mux_write(val, offset);
+	if (!m || m->reg_offset == OMAP_MUX_TERMINATOR)
+		pr_err("%s: Could not set gpio%i\n", __func__, gpio);
 }
 
-static struct omap_mux * __init omap_mux_list_add(struct omap_mux *src)
+static struct omap_mux * __init omap_mux_list_add(
+					struct omap_mux_partition *partition,
+					struct omap_mux *src)
 {
 	struct omap_mux_entry *entry;
 	struct omap_mux *m;
@@ -646,7 +893,7 @@ static struct omap_mux * __init omap_mux
 		return NULL;
 
 	m = &entry->mux;
-	memcpy(m, src, sizeof(struct omap_mux_entry));
+	entry->mux = *src;
 
 #ifdef CONFIG_OMAP_MUX
 	if (omap_mux_copy_names(src, m)) {
@@ -656,7 +903,7 @@ static struct omap_mux * __init omap_mux
 #endif
 
 	mutex_lock(&muxmode_mutex);
-	list_add_tail(&entry->node, &muxmodes);
+	list_add_tail(&entry->node, &partition->muxmodes);
 	mutex_unlock(&muxmode_mutex);
 
 	return m;
@@ -667,7 +914,8 @@ static struct omap_mux * __init omap_mux
  * the GPIO to mux offset mapping that is needed for dynamic muxing
  * of GPIO pins for off-idle.
  */
-static void __init omap_mux_init_list(struct omap_mux *superset)
+static void __init omap_mux_init_list(struct omap_mux_partition *partition,
+				      struct omap_mux *superset)
 {
 	while (superset->reg_offset !=  OMAP_MUX_TERMINATOR) {
 		struct omap_mux *entry;
@@ -679,15 +927,16 @@ static void __init omap_mux_init_list(st
 		}
 #else
 		/* Skip pins that are not muxed as GPIO by bootloader */
-		if (!OMAP_MODE_GPIO(omap_mux_read(superset->reg_offset))) {
+		if (!OMAP_MODE_GPIO(omap_mux_read(partition,
+				    superset->reg_offset))) {
 			superset++;
 			continue;
 		}
 #endif
 
-		entry = omap_mux_list_add(superset);
+		entry = omap_mux_list_add(partition, superset);
 		if (!entry) {
-			printk(KERN_ERR "mux: Could not add entry\n");
+			pr_err("%s: Could not add entry\n", __func__);
 			return;
 		}
 		superset++;
@@ -706,10 +955,11 @@ static void omap_mux_init_package(struct
 		omap_mux_package_init_balls(package_balls, superset);
 }
 
-static void omap_mux_init_signals(struct omap_board_mux *board_mux)
+static void omap_mux_init_signals(struct omap_mux_partition *partition,
+				  struct omap_board_mux *board_mux)
 {
 	omap_mux_set_cmdline_signals();
-	omap_mux_write_array(board_mux);
+	omap_mux_write_array(partition, board_mux);
 }
 
 #else
@@ -720,34 +970,50 @@ static void omap_mux_init_package(struct
 {
 }
 
-static void omap_mux_init_signals(struct omap_board_mux *board_mux)
+static void omap_mux_init_signals(struct omap_mux_partition *partition,
+				  struct omap_board_mux *board_mux)
 {
 }
 
 #endif
 
-int __init omap_mux_init(u32 mux_pbase, u32 mux_size,
-				struct omap_mux *superset,
-				struct omap_mux *package_subset,
-				struct omap_board_mux *board_mux,
-				struct omap_ball *package_balls)
+static u32 mux_partitions_cnt;
+
+int __init omap_mux_init(const char *name, u32 flags,
+			 u32 mux_pbase, u32 mux_size,
+			 struct omap_mux *superset,
+			 struct omap_mux *package_subset,
+			 struct omap_board_mux *board_mux,
+			 struct omap_ball *package_balls)
 {
-	if (mux_base)
-		return -EBUSY;
+	struct omap_mux_partition *partition;
 
-	mux_phys = mux_pbase;
-	mux_base = ioremap(mux_pbase, mux_size);
-	if (!mux_base) {
-		printk(KERN_ERR "mux: Could not ioremap\n");
+	partition = kzalloc(sizeof(struct omap_mux_partition), GFP_KERNEL);
+	if (!partition)
+		return -ENOMEM;
+
+	partition->name = name;
+	partition->flags = flags;
+	partition->size = mux_size;
+	partition->phys = mux_pbase;
+	partition->base = ioremap(mux_pbase, mux_size);
+	if (!partition->base) {
+		pr_err("%s: Could not ioremap mux partition at 0x%08x\n",
+			__func__, partition->phys);
+		kfree(partition);
 		return -ENODEV;
 	}
 
-	if (cpu_is_omap24xx())
-		omap_mux_flags = MUXABLE_GPIO_MODE3;
+	INIT_LIST_HEAD(&partition->muxmodes);
+
+	list_add_tail(&partition->node, &mux_partitions);
+	mux_partitions_cnt++;
+	pr_info("%s: Add partition: #%d: %s, flags: %x\n", __func__,
+		mux_partitions_cnt, partition->name, partition->flags);
 
 	omap_mux_init_package(superset, package_subset, package_balls);
-	omap_mux_init_list(superset);
-	omap_mux_init_signals(board_mux);
+	omap_mux_init_list(partition, superset);
+	omap_mux_init_signals(partition, board_mux);
 
 	return 0;
 }
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/mux.h linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/mux.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/mux.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/mux.h	2011-03-14 21:20:32.000000000 -0400
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2009 Nokia
- * Copyright (C) 2009 Texas Instruments
+ * Copyright (C) 2009-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 version 2 as
@@ -10,6 +10,7 @@
 #include "mux2420.h"
 #include "mux2430.h"
 #include "mux34xx.h"
+#include "mux44xx.h"
 
 #define OMAP_MUX_TERMINATOR	0xffff
 
@@ -37,6 +38,9 @@
 #define OMAP_OFF_PULL_UP		(1 << 13)
 #define OMAP_WAKEUP_EN			(1 << 14)
 
+/* 44xx specific mux bit defines */
+#define OMAP_WAKEUP_EVENT		(1 << 15)
+
 /* Active pin states */
 #define OMAP_PIN_OUTPUT			0
 #define OMAP_PIN_INPUT			OMAP_INPUT_EN
@@ -56,8 +60,10 @@
 
 #define OMAP_MODE_GPIO(x)	(((x) & OMAP_MUX_MODE7) == OMAP_MUX_MODE4)
 
-/* Flags for omap_mux_init */
+/* Flags for omapX_mux_init */
 #define OMAP_PACKAGE_MASK		0xffff
+#define OMAP_PACKAGE_CBS		8		/* 547-pin 0.40 0.40 */
+#define OMAP_PACKAGE_CBL		7		/* 547-pin 0.40 0.40 */
 #define OMAP_PACKAGE_CBP		6		/* 515-pin 0.40 0.50 */
 #define OMAP_PACKAGE_CUS		5		/* 423-pin 0.65 */
 #define OMAP_PACKAGE_CBB		4		/* 515-pin 0.40 0.50 */
@@ -66,14 +72,61 @@
 #define OMAP_PACKAGE_ZAF		1		/* 2420 447-pin SIP */
 
 
-#define OMAP_MUX_NR_MODES	8			/* Available modes */
-#define OMAP_MUX_NR_SIDES	2			/* Bottom & top */
+#define OMAP_MUX_NR_MODES		8		/* Available modes */
+#define OMAP_MUX_NR_SIDES		2		/* Bottom & top */
+
+/*
+ * omap_mux_init flags definition:
+ *
+ * OMAP_MUX_REG_8BIT: Ensure that access to padconf is done in 8 bits.
+ * The default value is 16 bits.
+ * OMAP_MUX_GPIO_IN_MODE3: The GPIO is selected in mode3.
+ * The default is mode4.
+ */
+#define OMAP_MUX_REG_8BIT		(1 << 0)
+#define OMAP_MUX_GPIO_IN_MODE3		(1 << 1)
+
+/**
+ * struct omap_board_data - board specific device data
+ * @id: instance id
+ * @flags: additional flags for platform init code
+ * @pads: array of device specific pads
+ * @pads_cnt: ARRAY_SIZE() of pads
+ */
+struct omap_board_data {
+	int			id;
+	u32			flags;
+	struct omap_device_pad	*pads;
+	int			pads_cnt;
+};
+
+/**
+ * struct mux_partition - contain partition related information
+ * @name: name of the current partition
+ * @flags: flags specific to this partition
+ * @phys: physical address
+ * @size: partition size
+ * @base: virtual address after ioremap
+ * @muxmodes: list of nodes that belong to a partition
+ * @node: list node for the partitions linked list
+ */
+struct omap_mux_partition {
+	const char		*name;
+	u32			flags;
+	u32			phys;
+	u32			size;
+	void __iomem		*base;
+	struct list_head	muxmodes;
+	struct list_head	node;
+};
 
 /**
  * struct omap_mux - data for omap mux register offset and it's value
  * @reg_offset:	mux register offset from the mux base
  * @gpio:	GPIO number
  * @muxnames:	available signal modes for a ball
+ * @balls:	available balls on the package
+ * @partition:	mux partition
  */
 struct omap_mux {
 	u16	reg_offset;
@@ -106,6 +159,34 @@ struct omap_board_mux {
 	u16	value;
 };
 
+#define OMAP_DEVICE_PAD_ENABLED		BIT(7)	/* Not needed for board-*.c */
+#define OMAP_DEVICE_PAD_REMUX		BIT(1)	/* Dynamically remux a pad,
+						   needs enable, idle and off
+						   values */
+#define OMAP_DEVICE_PAD_WAKEUP		BIT(0)	/* Pad is wake-up capable */
+
+/**
+ * struct omap_device_pad - device specific pad configuration
+ * @name:		signal name
+ * @flags:		pad specific runtime flags
+ * @enable:		runtime value for a pad
+ * @idle:		idle value for a pad
+ * @off:		off value for a pad, defaults to safe mode
+ * @partition:		mux partition
+ * @mux:		mux register
+ */
+struct omap_device_pad {
+	char				*name;
+	u8				flags;
+	u16				enable;
+	u16				idle;
+	u16				off;
+	struct omap_mux_partition	*partition;
+	struct omap_mux			*mux;
+};
+
+struct omap_hwmod_mux_info;
+
 #if defined(CONFIG_OMAP_MUX)
 
 /**
@@ -122,6 +203,23 @@ int omap_mux_init_gpio(int gpio, int val
  */
 int omap_mux_init_signal(const char *muxname, int val);
 
+/**
+ * omap_hwmod_mux_init - initialize hwmod specific mux data
+ * @bpads:		Board specific device signal names
+ * @nr_pads:		Number of signal names for the device
+ */
+extern struct omap_hwmod_mux_info *
+omap_hwmod_mux_init(struct omap_device_pad *bpads, int nr_pads);
+
+/**
+ * omap_hwmod_mux - omap hwmod specific pin muxing
+ * @hmux:		Pads for a hwmod
+ * @state:		Desired _HWMOD_STATE
+ *
+ * Called only from omap_hwmod.c, do not use.
+ */
+void omap_hwmod_mux(struct omap_hwmod_mux_info *hmux, u8 state);
+
 #else
 
 static inline int omap_mux_init_gpio(int gpio, int val)
@@ -133,6 +231,18 @@ static inline int omap_mux_init_signal(c
 	return 0;
 }
 
+static inline struct omap_hwmod_mux_info *
+omap_hwmod_mux_init(struct omap_device_pad *bpads, int nr_pads)
+{
+	return NULL;
+}
+
+static inline void omap_hwmod_mux(struct omap_hwmod_mux_info *hmux, u8 state)
+{
+}
+
+static struct omap_board_mux *board_mux __initdata __maybe_unused;
+
 #endif
 
 /**
@@ -151,28 +261,39 @@ u16 omap_mux_get_gpio(int gpio);
 void omap_mux_set_gpio(u16 val, int gpio);
 
 /**
+ * omap_mux_get() - get a mux partition by name
+ * @name:		Name of the mux partition
+ *
+ */
+struct omap_mux_partition *omap_mux_get(const char *name);
+
+/**
  * omap_mux_read() - read mux register
+ * @partition:		Mux partition
  * @mux_offset:		Offset of the mux register
  *
  */
-u16 omap_mux_read(u16 mux_offset);
+u16 omap_mux_read(struct omap_mux_partition *p, u16 mux_offset);
 
 /**
  * omap_mux_write() - write mux register
+ * @partition:		Mux partition
  * @val:		New mux register value
  * @mux_offset:		Offset of the mux register
  *
  * This should be only needed for dynamic remuxing of non-gpio signals.
  */
-void omap_mux_write(u16 val, u16 mux_offset);
+void omap_mux_write(struct omap_mux_partition *p, u16 val, u16 mux_offset);
 
 /**
  * omap_mux_write_array() - write an array of mux registers
+ * @partition:		Mux partition
  * @board_mux:		Array of mux registers terminated by MAP_MUX_TERMINATOR
  *
  * This should be only needed for dynamic remuxing of non-gpio signals.
  */
-void omap_mux_write_array(struct omap_board_mux *board_mux);
+void omap_mux_write_array(struct omap_mux_partition *p,
+			  struct omap_board_mux *board_mux);
 
 /**
  * omap2420_mux_init() - initialize mux system with board specific set
@@ -196,10 +317,19 @@ int omap2430_mux_init(struct omap_board_
 int omap3_mux_init(struct omap_board_mux *board_mux, int flags);
 
 /**
+ * omap4_mux_init() - initialize mux system with board specific set
+ * @board_mux:		Board specific mux table
+ * @flags:		OMAP package type used for the board
+ */
+int omap4_mux_init(struct omap_board_mux *board_mux, int flags);
+
+/**
  * omap_mux_init - private mux init function, do not call
  */
-int omap_mux_init(u32 mux_pbase, u32 mux_size,
-				struct omap_mux *superset,
-				struct omap_mux *package_subset,
-				struct omap_board_mux *board_mux,
-				struct omap_ball *package_balls);
+int omap_mux_init(const char *name, u32 flags,
+		  u32 mux_pbase, u32 mux_size,
+		  struct omap_mux *superset,
+		  struct omap_mux *package_subset,
+		  struct omap_board_mux *board_mux,
+		  struct omap_ball *package_balls);
+
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/omap4-common.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/omap4-common.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/omap4-common.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/omap4-common.c	2011-03-14 21:20:32.000000000 -0400
@@ -26,21 +26,22 @@
 void __iomem *l2cache_base;
 #endif
 
-void __iomem *gic_cpu_base_addr;
 void __iomem *gic_dist_base_addr;
 
 
 void __init gic_init_irq(void)
 {
+	void __iomem *gic_cpu_base;
+
 	/* Static mapping, never released */
 	gic_dist_base_addr = ioremap(OMAP44XX_GIC_DIST_BASE, SZ_4K);
 	BUG_ON(!gic_dist_base_addr);
-	gic_dist_init(0, gic_dist_base_addr, 29);
 
 	/* Static mapping, never released */
-	gic_cpu_base_addr = ioremap(OMAP44XX_GIC_CPU_BASE, SZ_512);
-	BUG_ON(!gic_cpu_base_addr);
-	gic_cpu_init(0, gic_cpu_base_addr);
+	gic_cpu_base = ioremap(OMAP44XX_GIC_CPU_BASE, SZ_512);
+	BUG_ON(!gic_cpu_base);
+
+	gic_init(0, 29, gic_dist_base_addr, gic_cpu_base);
 }
 
 #ifdef CONFIG_CACHE_L2X0
@@ -53,6 +54,8 @@ static void omap4_l2x0_disable(void)
 
 static int __init omap_l2_cache_init(void)
 {
+	u32 aux_ctrl = 0;
+
 	/*
 	 * To avoid code running on other OMAPs in
 	 * multi-omap builds
@@ -64,18 +67,32 @@ static int __init omap_l2_cache_init(voi
 	l2cache_base = ioremap(OMAP44XX_L2CACHE_BASE, SZ_4K);
 	BUG_ON(!l2cache_base);
 
-	/* Enable PL310 L2 Cache controller */
-	omap_smc1(0x102, 0x1);
-
 	/*
 	 * 16-way associativity, parity disabled
 	 * Way size - 32KB (es1.0)
 	 * Way size - 64KB (es2.0 +)
 	 */
-	if (omap_rev() == OMAP4430_REV_ES1_0)
-		l2x0_init(l2cache_base, 0x0e050000, 0xc0000fff);
-	else
-		l2x0_init(l2cache_base, 0x0e070000, 0xc0000fff);
+	aux_ctrl = ((1 << L2X0_AUX_CTRL_ASSOCIATIVITY_SHIFT) |
+			(0x1 << 25) |
+			(0x1 << L2X0_AUX_CTRL_NS_LOCKDOWN_SHIFT) |
+			(0x1 << L2X0_AUX_CTRL_NS_INT_CTRL_SHIFT));
+
+	if (omap_rev() == OMAP4430_REV_ES1_0) {
+		aux_ctrl |= 0x2 << L2X0_AUX_CTRL_WAY_SIZE_SHIFT;
+	} else {
+		aux_ctrl |= ((0x3 << L2X0_AUX_CTRL_WAY_SIZE_SHIFT) |
+			(1 << L2X0_AUX_CTRL_SHARE_OVERRIDE_SHIFT) |
+			(1 << L2X0_AUX_CTRL_DATA_PREFETCH_SHIFT) |
+			(1 << L2X0_AUX_CTRL_INSTR_PREFETCH_SHIFT) |
+			(1 << L2X0_AUX_CTRL_EARLY_BRESP_SHIFT));
+	}
+	if (omap_rev() != OMAP4430_REV_ES1_0)
+		omap_smc1(0x109, aux_ctrl);
+
+	/* Enable PL310 L2 Cache controller */
+	omap_smc1(0x102, 0x1);
+
+	l2x0_init(l2cache_base, aux_ctrl, L2X0_AUX_CTRL_MASK);
 
 	/*
 	 * Override default outer_cache.disable with a OMAP4
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/omap-hotplug.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/omap-hotplug.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/omap-hotplug.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/omap-hotplug.c	2011-03-14 21:20:32.000000000 -0400
@@ -17,16 +17,13 @@
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/smp.h>
-#include <linux/completion.h>
 
 #include <asm/cacheflush.h>
 #include <mach/omap4-common.h>
 
-static DECLARE_COMPLETION(cpu_killed);
-
 int platform_cpu_kill(unsigned int cpu)
 {
-	return wait_for_completion_timeout(&cpu_killed, 5000);
+	return 1;
 }
 
 /*
@@ -35,15 +32,6 @@ int platform_cpu_kill(unsigned int cpu)
  */
 void platform_cpu_die(unsigned int cpu)
 {
-	unsigned int this_cpu = hard_smp_processor_id();
-
-	if (cpu != this_cpu) {
-		pr_crit("platform_cpu_die running on %u, should be %u\n",
-			   this_cpu, cpu);
-		BUG();
-	}
-	pr_notice("CPU%u: shutdown\n", cpu);
-	complete(&cpu_killed);
 	flush_cache_all();
 	dsb();
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/omap_hwmod_2420_data.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/omap_hwmod_2420_data.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/omap_hwmod_2420_data.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/omap_hwmod_2420_data.c	2011-03-14 21:20:32.000000000 -0400
@@ -16,11 +16,14 @@
 #include <plat/cpu.h>
 #include <plat/dma.h>
 #include <plat/serial.h>
+#include <plat/i2c.h>
+#include <plat/gpio.h>
 
 #include "omap_hwmod_common_data.h"
 
-#include "prm-regbits-24xx.h"
 #include "cm-regbits-24xx.h"
+#include "prm-regbits-24xx.h"
+#include "wd_timer.h"
 
 /*
  * OMAP2420 hardware module integration data
@@ -36,6 +39,11 @@ static struct omap_hwmod omap2420_iva_hw
 static struct omap_hwmod omap2420_l3_main_hwmod;
 static struct omap_hwmod omap2420_l4_core_hwmod;
 static struct omap_hwmod omap2420_wd_timer2_hwmod;
+static struct omap_hwmod omap2420_gpio1_hwmod;
+static struct omap_hwmod omap2420_gpio2_hwmod;
+static struct omap_hwmod omap2420_gpio3_hwmod;
+static struct omap_hwmod omap2420_gpio4_hwmod;
+static struct omap_hwmod omap2420_dma_system_hwmod;
 
 /* L3 -> L4_CORE interface */
 static struct omap_hwmod_ocp_if omap2420_l3_main__l4_core = {
@@ -77,6 +85,8 @@ static struct omap_hwmod omap2420_l4_wku
 static struct omap_hwmod omap2420_uart1_hwmod;
 static struct omap_hwmod omap2420_uart2_hwmod;
 static struct omap_hwmod omap2420_uart3_hwmod;
+static struct omap_hwmod omap2420_i2c1_hwmod;
+static struct omap_hwmod omap2420_i2c2_hwmod;
 
 /* L4_CORE -> L4_WKUP interface */
 static struct omap_hwmod_ocp_if omap2420_l4_core__l4_wkup = {
@@ -139,6 +149,45 @@ static struct omap_hwmod_ocp_if omap2_l4
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
+/* I2C IP block address space length (in bytes) */
+#define OMAP2_I2C_AS_LEN		128
+
+/* L4 CORE -> I2C1 interface */
+static struct omap_hwmod_addr_space omap2420_i2c1_addr_space[] = {
+	{
+		.pa_start	= 0x48070000,
+		.pa_end		= 0x48070000 + OMAP2_I2C_AS_LEN - 1,
+		.flags		= ADDR_TYPE_RT,
+	},
+};
+
+static struct omap_hwmod_ocp_if omap2420_l4_core__i2c1 = {
+	.master		= &omap2420_l4_core_hwmod,
+	.slave		= &omap2420_i2c1_hwmod,
+	.clk		= "i2c1_ick",
+	.addr		= omap2420_i2c1_addr_space,
+	.addr_cnt	= ARRAY_SIZE(omap2420_i2c1_addr_space),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* L4 CORE -> I2C2 interface */
+static struct omap_hwmod_addr_space omap2420_i2c2_addr_space[] = {
+	{
+		.pa_start	= 0x48072000,
+		.pa_end		= 0x48072000 + OMAP2_I2C_AS_LEN - 1,
+		.flags		= ADDR_TYPE_RT,
+	},
+};
+
+static struct omap_hwmod_ocp_if omap2420_l4_core__i2c2 = {
+	.master		= &omap2420_l4_core_hwmod,
+	.slave		= &omap2420_i2c2_hwmod,
+	.clk		= "i2c2_ick",
+	.addr		= omap2420_i2c2_addr_space,
+	.addr_cnt	= ARRAY_SIZE(omap2420_i2c2_addr_space),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
 /* Slave interfaces on the L4_CORE interconnect */
 static struct omap_hwmod_ocp_if *omap2420_l4_core_slaves[] = {
 	&omap2420_l3_main__l4_core,
@@ -150,6 +199,8 @@ static struct omap_hwmod_ocp_if *omap242
 	&omap2_l4_core__uart1,
 	&omap2_l4_core__uart2,
 	&omap2_l4_core__uart3,
+	&omap2420_l4_core__i2c1,
+	&omap2420_l4_core__i2c2
 };
 
 /* L4 CORE */
@@ -262,8 +313,9 @@ static struct omap_hwmod_class_sysconfig
 };
 
 static struct omap_hwmod_class omap2420_wd_timer_hwmod_class = {
-	.name = "wd_timer",
-	.sysc = &omap2420_wd_timer_sysc,
+	.name		= "wd_timer",
+	.sysc		= &omap2420_wd_timer_sysc,
+	.pre_shutdown	= &omap2_wd_timer_disable
 };
 
 /* wd_timer2 */
@@ -418,6 +470,400 @@ static struct omap_hwmod omap2420_uart3_
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
 };
 
+/* I2C common */
+static struct omap_hwmod_class_sysconfig i2c_sysc = {
+	.rev_offs	= 0x00,
+	.sysc_offs	= 0x20,
+	.syss_offs	= 0x10,
+	.sysc_flags	= SYSC_HAS_SOFTRESET,
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class i2c_class = {
+	.name		= "i2c",
+	.sysc		= &i2c_sysc,
+};
+
+static struct omap_i2c_dev_attr i2c_dev_attr;
+
+/* I2C1 */
+
+static struct omap_hwmod_irq_info i2c1_mpu_irqs[] = {
+	{ .irq = INT_24XX_I2C1_IRQ, },
+};
+
+static struct omap_hwmod_dma_info i2c1_sdma_reqs[] = {
+	{ .name = "tx", .dma_req = OMAP24XX_DMA_I2C1_TX },
+	{ .name = "rx", .dma_req = OMAP24XX_DMA_I2C1_RX },
+};
+
+static struct omap_hwmod_ocp_if *omap2420_i2c1_slaves[] = {
+	&omap2420_l4_core__i2c1,
+};
+
+static struct omap_hwmod omap2420_i2c1_hwmod = {
+	.name		= "i2c1",
+	.mpu_irqs	= i2c1_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(i2c1_mpu_irqs),
+	.sdma_reqs	= i2c1_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(i2c1_sdma_reqs),
+	.main_clk	= "i2c1_fck",
+	.prcm		= {
+		.omap2 = {
+			.module_offs = CORE_MOD,
+			.prcm_reg_id = 1,
+			.module_bit = OMAP2420_EN_I2C1_SHIFT,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP2420_ST_I2C1_SHIFT,
+		},
+	},
+	.slaves		= omap2420_i2c1_slaves,
+	.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,
+};
+
+/* I2C2 */
+
+static struct omap_hwmod_irq_info i2c2_mpu_irqs[] = {
+	{ .irq = INT_24XX_I2C2_IRQ, },
+};
+
+static struct omap_hwmod_dma_info i2c2_sdma_reqs[] = {
+	{ .name = "tx", .dma_req = OMAP24XX_DMA_I2C2_TX },
+	{ .name = "rx", .dma_req = OMAP24XX_DMA_I2C2_RX },
+};
+
+static struct omap_hwmod_ocp_if *omap2420_i2c2_slaves[] = {
+	&omap2420_l4_core__i2c2,
+};
+
+static struct omap_hwmod omap2420_i2c2_hwmod = {
+	.name		= "i2c2",
+	.mpu_irqs	= i2c2_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(i2c2_mpu_irqs),
+	.sdma_reqs	= i2c2_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(i2c2_sdma_reqs),
+	.main_clk	= "i2c2_fck",
+	.prcm		= {
+		.omap2 = {
+			.module_offs = CORE_MOD,
+			.prcm_reg_id = 1,
+			.module_bit = OMAP2420_EN_I2C2_SHIFT,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP2420_ST_I2C2_SHIFT,
+		},
+	},
+	.slaves		= omap2420_i2c2_slaves,
+	.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,
+};
+
+/* l4_wkup -> gpio1 */
+static struct omap_hwmod_addr_space omap2420_gpio1_addr_space[] = {
+	{
+		.pa_start	= 0x48018000,
+		.pa_end		= 0x480181ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+static struct omap_hwmod_ocp_if omap2420_l4_wkup__gpio1 = {
+	.master		= &omap2420_l4_wkup_hwmod,
+	.slave		= &omap2420_gpio1_hwmod,
+	.clk		= "gpios_ick",
+	.addr		= omap2420_gpio1_addr_space,
+	.addr_cnt	= ARRAY_SIZE(omap2420_gpio1_addr_space),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_wkup -> gpio2 */
+static struct omap_hwmod_addr_space omap2420_gpio2_addr_space[] = {
+	{
+		.pa_start	= 0x4801a000,
+		.pa_end		= 0x4801a1ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+static struct omap_hwmod_ocp_if omap2420_l4_wkup__gpio2 = {
+	.master		= &omap2420_l4_wkup_hwmod,
+	.slave		= &omap2420_gpio2_hwmod,
+	.clk		= "gpios_ick",
+	.addr		= omap2420_gpio2_addr_space,
+	.addr_cnt	= ARRAY_SIZE(omap2420_gpio2_addr_space),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_wkup -> gpio3 */
+static struct omap_hwmod_addr_space omap2420_gpio3_addr_space[] = {
+	{
+		.pa_start	= 0x4801c000,
+		.pa_end		= 0x4801c1ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+static struct omap_hwmod_ocp_if omap2420_l4_wkup__gpio3 = {
+	.master		= &omap2420_l4_wkup_hwmod,
+	.slave		= &omap2420_gpio3_hwmod,
+	.clk		= "gpios_ick",
+	.addr		= omap2420_gpio3_addr_space,
+	.addr_cnt	= ARRAY_SIZE(omap2420_gpio3_addr_space),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_wkup -> gpio4 */
+static struct omap_hwmod_addr_space omap2420_gpio4_addr_space[] = {
+	{
+		.pa_start	= 0x4801e000,
+		.pa_end		= 0x4801e1ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+static struct omap_hwmod_ocp_if omap2420_l4_wkup__gpio4 = {
+	.master		= &omap2420_l4_wkup_hwmod,
+	.slave		= &omap2420_gpio4_hwmod,
+	.clk		= "gpios_ick",
+	.addr		= omap2420_gpio4_addr_space,
+	.addr_cnt	= ARRAY_SIZE(omap2420_gpio4_addr_space),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* gpio dev_attr */
+static struct omap_gpio_dev_attr gpio_dev_attr = {
+	.bank_width = 32,
+	.dbck_flag = false,
+};
+
+static struct omap_hwmod_class_sysconfig omap242x_gpio_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.syss_offs	= 0x0014,
+	.sysc_flags	= (SYSC_HAS_ENAWAKEUP | SYSC_HAS_SIDLEMODE |
+			   SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+	.sysc_fields    = &omap_hwmod_sysc_type1,
+};
+
+/*
+ * 'gpio' class
+ * general purpose io module
+ */
+static struct omap_hwmod_class omap242x_gpio_hwmod_class = {
+	.name = "gpio",
+	.sysc = &omap242x_gpio_sysc,
+	.rev = 0,
+};
+
+/* gpio1 */
+static struct omap_hwmod_irq_info omap242x_gpio1_irqs[] = {
+	{ .irq = 29 }, /* INT_24XX_GPIO_BANK1 */
+};
+
+static struct omap_hwmod_ocp_if *omap2420_gpio1_slaves[] = {
+	&omap2420_l4_wkup__gpio1,
+};
+
+static struct omap_hwmod omap2420_gpio1_hwmod = {
+	.name		= "gpio1",
+	.mpu_irqs	= omap242x_gpio1_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap242x_gpio1_irqs),
+	.main_clk	= "gpios_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP24XX_EN_GPIOS_SHIFT,
+			.module_offs = WKUP_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP24XX_ST_GPIOS_SHIFT,
+		},
+	},
+	.slaves		= omap2420_gpio1_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2420_gpio1_slaves),
+	.class		= &omap242x_gpio_hwmod_class,
+	.dev_attr	= &gpio_dev_attr,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
+};
+
+/* gpio2 */
+static struct omap_hwmod_irq_info omap242x_gpio2_irqs[] = {
+	{ .irq = 30 }, /* INT_24XX_GPIO_BANK2 */
+};
+
+static struct omap_hwmod_ocp_if *omap2420_gpio2_slaves[] = {
+	&omap2420_l4_wkup__gpio2,
+};
+
+static struct omap_hwmod omap2420_gpio2_hwmod = {
+	.name		= "gpio2",
+	.mpu_irqs	= omap242x_gpio2_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap242x_gpio2_irqs),
+	.main_clk	= "gpios_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP24XX_EN_GPIOS_SHIFT,
+			.module_offs = WKUP_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP24XX_ST_GPIOS_SHIFT,
+		},
+	},
+	.slaves		= omap2420_gpio2_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2420_gpio2_slaves),
+	.class		= &omap242x_gpio_hwmod_class,
+	.dev_attr	= &gpio_dev_attr,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
+};
+
+/* gpio3 */
+static struct omap_hwmod_irq_info omap242x_gpio3_irqs[] = {
+	{ .irq = 31 }, /* INT_24XX_GPIO_BANK3 */
+};
+
+static struct omap_hwmod_ocp_if *omap2420_gpio3_slaves[] = {
+	&omap2420_l4_wkup__gpio3,
+};
+
+static struct omap_hwmod omap2420_gpio3_hwmod = {
+	.name		= "gpio3",
+	.mpu_irqs	= omap242x_gpio3_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap242x_gpio3_irqs),
+	.main_clk	= "gpios_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP24XX_EN_GPIOS_SHIFT,
+			.module_offs = WKUP_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP24XX_ST_GPIOS_SHIFT,
+		},
+	},
+	.slaves		= omap2420_gpio3_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2420_gpio3_slaves),
+	.class		= &omap242x_gpio_hwmod_class,
+	.dev_attr	= &gpio_dev_attr,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
+};
+
+/* gpio4 */
+static struct omap_hwmod_irq_info omap242x_gpio4_irqs[] = {
+	{ .irq = 32 }, /* INT_24XX_GPIO_BANK4 */
+};
+
+static struct omap_hwmod_ocp_if *omap2420_gpio4_slaves[] = {
+	&omap2420_l4_wkup__gpio4,
+};
+
+static struct omap_hwmod omap2420_gpio4_hwmod = {
+	.name		= "gpio4",
+	.mpu_irqs	= omap242x_gpio4_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap242x_gpio4_irqs),
+	.main_clk	= "gpios_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP24XX_EN_GPIOS_SHIFT,
+			.module_offs = WKUP_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP24XX_ST_GPIOS_SHIFT,
+		},
+	},
+	.slaves		= omap2420_gpio4_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2420_gpio4_slaves),
+	.class		= &omap242x_gpio_hwmod_class,
+	.dev_attr	= &gpio_dev_attr,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
+};
+
+/* system dma */
+static struct omap_hwmod_class_sysconfig omap2420_dma_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x002c,
+	.syss_offs	= 0x0028,
+	.sysc_flags	= (SYSC_HAS_SOFTRESET | SYSC_HAS_MIDLEMODE |
+			   SYSC_HAS_CLOCKACTIVITY | SYSC_HAS_EMUFREE |
+			   SYSC_HAS_AUTOIDLE),
+	.idlemodes	= (MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap2420_dma_hwmod_class = {
+	.name = "dma",
+	.sysc = &omap2420_dma_sysc,
+};
+
+/* dma attributes */
+static struct omap_dma_dev_attr dma_dev_attr = {
+	.dev_caps  = RESERVE_CHANNEL | DMA_LINKED_LCH | GLOBAL_PRIORITY |
+						IS_CSSA_32 | IS_CDSA_32,
+	.lch_count = 32,
+};
+
+static struct omap_hwmod_irq_info omap2420_dma_system_irqs[] = {
+	{ .name = "0", .irq = 12 }, /* INT_24XX_SDMA_IRQ0 */
+	{ .name = "1", .irq = 13 }, /* INT_24XX_SDMA_IRQ1 */
+	{ .name = "2", .irq = 14 }, /* INT_24XX_SDMA_IRQ2 */
+	{ .name = "3", .irq = 15 }, /* INT_24XX_SDMA_IRQ3 */
+};
+
+static struct omap_hwmod_addr_space omap2420_dma_system_addrs[] = {
+	{
+		.pa_start	= 0x48056000,
+		.pa_end		= 0x4a0560ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* dma_system -> L3 */
+static struct omap_hwmod_ocp_if omap2420_dma_system__l3 = {
+	.master		= &omap2420_dma_system_hwmod,
+	.slave		= &omap2420_l3_main_hwmod,
+	.clk		= "core_l3_ck",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* dma_system master ports */
+static struct omap_hwmod_ocp_if *omap2420_dma_system_masters[] = {
+	&omap2420_dma_system__l3,
+};
+
+/* l4_core -> dma_system */
+static struct omap_hwmod_ocp_if omap2420_l4_core__dma_system = {
+	.master		= &omap2420_l4_core_hwmod,
+	.slave		= &omap2420_dma_system_hwmod,
+	.clk		= "sdma_ick",
+	.addr		= omap2420_dma_system_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap2420_dma_system_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* dma_system slave ports */
+static struct omap_hwmod_ocp_if *omap2420_dma_system_slaves[] = {
+	&omap2420_l4_core__dma_system,
+};
+
+static struct omap_hwmod omap2420_dma_system_hwmod = {
+	.name		= "dma",
+	.class		= &omap2420_dma_hwmod_class,
+	.mpu_irqs	= omap2420_dma_system_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap2420_dma_system_irqs),
+	.main_clk	= "core_l3_ck",
+	.slaves		= omap2420_dma_system_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2420_dma_system_slaves),
+	.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,
+};
+
 static __initdata struct omap_hwmod *omap2420_hwmods[] = {
 	&omap2420_l3_main_hwmod,
 	&omap2420_l4_core_hwmod,
@@ -428,6 +874,17 @@ static __initdata struct omap_hwmod *oma
 	&omap2420_uart1_hwmod,
 	&omap2420_uart2_hwmod,
 	&omap2420_uart3_hwmod,
+	&omap2420_i2c1_hwmod,
+	&omap2420_i2c2_hwmod,
+
+	/* gpio class */
+	&omap2420_gpio1_hwmod,
+	&omap2420_gpio2_hwmod,
+	&omap2420_gpio3_hwmod,
+	&omap2420_gpio4_hwmod,
+
+	/* dma_system class*/
+	&omap2420_dma_system_hwmod,
 	NULL,
 };
 
@@ -435,5 +892,3 @@ int __init omap2420_hwmod_init(void)
 {
 	return omap_hwmod_init(omap2420_hwmods);
 }
-
-
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/omap_hwmod_2430_data.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/omap_hwmod_2430_data.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/omap_hwmod_2430_data.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/omap_hwmod_2430_data.c	2011-03-14 21:20:32.000000000 -0400
@@ -16,11 +16,14 @@
 #include <plat/cpu.h>
 #include <plat/dma.h>
 #include <plat/serial.h>
+#include <plat/i2c.h>
+#include <plat/gpio.h>
 
 #include "omap_hwmod_common_data.h"
 
 #include "prm-regbits-24xx.h"
 #include "cm-regbits-24xx.h"
+#include "wd_timer.h"
 
 /*
  * OMAP2430 hardware module integration data
@@ -36,6 +39,12 @@ static struct omap_hwmod omap2430_iva_hw
 static struct omap_hwmod omap2430_l3_main_hwmod;
 static struct omap_hwmod omap2430_l4_core_hwmod;
 static struct omap_hwmod omap2430_wd_timer2_hwmod;
+static struct omap_hwmod omap2430_gpio1_hwmod;
+static struct omap_hwmod omap2430_gpio2_hwmod;
+static struct omap_hwmod omap2430_gpio3_hwmod;
+static struct omap_hwmod omap2430_gpio4_hwmod;
+static struct omap_hwmod omap2430_gpio5_hwmod;
+static struct omap_hwmod omap2430_dma_system_hwmod;
 
 /* L3 -> L4_CORE interface */
 static struct omap_hwmod_ocp_if omap2430_l3_main__l4_core = {
@@ -77,6 +86,47 @@ static struct omap_hwmod omap2430_l4_wku
 static struct omap_hwmod omap2430_uart1_hwmod;
 static struct omap_hwmod omap2430_uart2_hwmod;
 static struct omap_hwmod omap2430_uart3_hwmod;
+static struct omap_hwmod omap2430_i2c1_hwmod;
+static struct omap_hwmod omap2430_i2c2_hwmod;
+
+/* I2C IP block address space length (in bytes) */
+#define OMAP2_I2C_AS_LEN		128
+
+/* L4 CORE -> I2C1 interface */
+static struct omap_hwmod_addr_space omap2430_i2c1_addr_space[] = {
+	{
+		.pa_start	= 0x48070000,
+		.pa_end		= 0x48070000 + OMAP2_I2C_AS_LEN - 1,
+		.flags		= ADDR_TYPE_RT,
+	},
+};
+
+static struct omap_hwmod_ocp_if omap2430_l4_core__i2c1 = {
+	.master		= &omap2430_l4_core_hwmod,
+	.slave		= &omap2430_i2c1_hwmod,
+	.clk		= "i2c1_ick",
+	.addr		= omap2430_i2c1_addr_space,
+	.addr_cnt	= ARRAY_SIZE(omap2430_i2c1_addr_space),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* L4 CORE -> I2C2 interface */
+static struct omap_hwmod_addr_space omap2430_i2c2_addr_space[] = {
+	{
+		.pa_start	= 0x48072000,
+		.pa_end		= 0x48072000 + OMAP2_I2C_AS_LEN - 1,
+		.flags		= ADDR_TYPE_RT,
+	},
+};
+
+static struct omap_hwmod_ocp_if omap2430_l4_core__i2c2 = {
+	.master		= &omap2430_l4_core_hwmod,
+	.slave		= &omap2430_i2c2_hwmod,
+	.clk		= "i2c2_ick",
+	.addr		= omap2430_i2c2_addr_space,
+	.addr_cnt	= ARRAY_SIZE(omap2430_i2c2_addr_space),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
 
 /* L4_CORE -> L4_WKUP interface */
 static struct omap_hwmod_ocp_if omap2430_l4_core__l4_wkup = {
@@ -262,8 +312,9 @@ static struct omap_hwmod_class_sysconfig
 };
 
 static struct omap_hwmod_class omap2430_wd_timer_hwmod_class = {
-	.name = "wd_timer",
-	.sysc = &omap2430_wd_timer_sysc,
+	.name		= "wd_timer",
+	.sysc		= &omap2430_wd_timer_sysc,
+	.pre_shutdown	= &omap2_wd_timer_disable
 };
 
 /* wd_timer2 */
@@ -418,6 +469,456 @@ static struct omap_hwmod omap2430_uart3_
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 };
 
+/* I2C common */
+static struct omap_hwmod_class_sysconfig i2c_sysc = {
+	.rev_offs	= 0x00,
+	.sysc_offs	= 0x20,
+	.syss_offs	= 0x10,
+	.sysc_flags	= (SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class i2c_class = {
+	.name		= "i2c",
+	.sysc		= &i2c_sysc,
+};
+
+static struct omap_i2c_dev_attr i2c_dev_attr = {
+	.fifo_depth	= 8, /* bytes */
+};
+
+/* I2C1 */
+
+static struct omap_hwmod_irq_info i2c1_mpu_irqs[] = {
+	{ .irq = INT_24XX_I2C1_IRQ, },
+};
+
+static struct omap_hwmod_dma_info i2c1_sdma_reqs[] = {
+	{ .name = "tx", .dma_req = OMAP24XX_DMA_I2C1_TX },
+	{ .name = "rx", .dma_req = OMAP24XX_DMA_I2C1_RX },
+};
+
+static struct omap_hwmod_ocp_if *omap2430_i2c1_slaves[] = {
+	&omap2430_l4_core__i2c1,
+};
+
+static struct omap_hwmod omap2430_i2c1_hwmod = {
+	.name		= "i2c1",
+	.mpu_irqs	= i2c1_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(i2c1_mpu_irqs),
+	.sdma_reqs	= i2c1_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(i2c1_sdma_reqs),
+	.main_clk	= "i2chs1_fck",
+	.prcm		= {
+		.omap2 = {
+			/*
+			 * NOTE: The CM_FCLKEN* and CM_ICLKEN* for
+			 * I2CHS IP's do not follow the usual pattern.
+			 * prcm_reg_id alone cannot be used to program
+			 * the iclk and fclk. Needs to be handled using
+			 * additonal flags when clk handling is moved
+			 * to hwmod framework.
+			 */
+			.module_offs = CORE_MOD,
+			.prcm_reg_id = 1,
+			.module_bit = OMAP2430_EN_I2CHS1_SHIFT,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP2430_ST_I2CHS1_SHIFT,
+		},
+	},
+	.slaves		= omap2430_i2c1_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2430_i2c1_slaves),
+	.class		= &i2c_class,
+	.dev_attr	= &i2c_dev_attr,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
+};
+
+/* I2C2 */
+
+static struct omap_hwmod_irq_info i2c2_mpu_irqs[] = {
+	{ .irq = INT_24XX_I2C2_IRQ, },
+};
+
+static struct omap_hwmod_dma_info i2c2_sdma_reqs[] = {
+	{ .name = "tx", .dma_req = OMAP24XX_DMA_I2C2_TX },
+	{ .name = "rx", .dma_req = OMAP24XX_DMA_I2C2_RX },
+};
+
+static struct omap_hwmod_ocp_if *omap2430_i2c2_slaves[] = {
+	&omap2430_l4_core__i2c2,
+};
+
+static struct omap_hwmod omap2430_i2c2_hwmod = {
+	.name		= "i2c2",
+	.mpu_irqs	= i2c2_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(i2c2_mpu_irqs),
+	.sdma_reqs	= i2c2_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(i2c2_sdma_reqs),
+	.main_clk	= "i2chs2_fck",
+	.prcm		= {
+		.omap2 = {
+			.module_offs = CORE_MOD,
+			.prcm_reg_id = 1,
+			.module_bit = OMAP2430_EN_I2CHS2_SHIFT,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP2430_ST_I2CHS2_SHIFT,
+		},
+	},
+	.slaves		= omap2430_i2c2_slaves,
+	.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 */
+static struct omap_hwmod_addr_space omap2430_gpio1_addr_space[] = {
+	{
+		.pa_start	= 0x4900C000,
+		.pa_end		= 0x4900C1ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+static struct omap_hwmod_ocp_if omap2430_l4_wkup__gpio1 = {
+	.master		= &omap2430_l4_wkup_hwmod,
+	.slave		= &omap2430_gpio1_hwmod,
+	.clk		= "gpios_ick",
+	.addr		= omap2430_gpio1_addr_space,
+	.addr_cnt	= ARRAY_SIZE(omap2430_gpio1_addr_space),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_wkup -> gpio2 */
+static struct omap_hwmod_addr_space omap2430_gpio2_addr_space[] = {
+	{
+		.pa_start	= 0x4900E000,
+		.pa_end		= 0x4900E1ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+static struct omap_hwmod_ocp_if omap2430_l4_wkup__gpio2 = {
+	.master		= &omap2430_l4_wkup_hwmod,
+	.slave		= &omap2430_gpio2_hwmod,
+	.clk		= "gpios_ick",
+	.addr		= omap2430_gpio2_addr_space,
+	.addr_cnt	= ARRAY_SIZE(omap2430_gpio2_addr_space),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_wkup -> gpio3 */
+static struct omap_hwmod_addr_space omap2430_gpio3_addr_space[] = {
+	{
+		.pa_start	= 0x49010000,
+		.pa_end		= 0x490101ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+static struct omap_hwmod_ocp_if omap2430_l4_wkup__gpio3 = {
+	.master		= &omap2430_l4_wkup_hwmod,
+	.slave		= &omap2430_gpio3_hwmod,
+	.clk		= "gpios_ick",
+	.addr		= omap2430_gpio3_addr_space,
+	.addr_cnt	= ARRAY_SIZE(omap2430_gpio3_addr_space),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_wkup -> gpio4 */
+static struct omap_hwmod_addr_space omap2430_gpio4_addr_space[] = {
+	{
+		.pa_start	= 0x49012000,
+		.pa_end		= 0x490121ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+static struct omap_hwmod_ocp_if omap2430_l4_wkup__gpio4 = {
+	.master		= &omap2430_l4_wkup_hwmod,
+	.slave		= &omap2430_gpio4_hwmod,
+	.clk		= "gpios_ick",
+	.addr		= omap2430_gpio4_addr_space,
+	.addr_cnt	= ARRAY_SIZE(omap2430_gpio4_addr_space),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_core -> gpio5 */
+static struct omap_hwmod_addr_space omap2430_gpio5_addr_space[] = {
+	{
+		.pa_start	= 0x480B6000,
+		.pa_end		= 0x480B61ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+static struct omap_hwmod_ocp_if omap2430_l4_core__gpio5 = {
+	.master		= &omap2430_l4_core_hwmod,
+	.slave		= &omap2430_gpio5_hwmod,
+	.clk		= "gpio5_ick",
+	.addr		= omap2430_gpio5_addr_space,
+	.addr_cnt	= ARRAY_SIZE(omap2430_gpio5_addr_space),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* gpio dev_attr */
+static struct omap_gpio_dev_attr gpio_dev_attr = {
+	.bank_width = 32,
+	.dbck_flag = false,
+};
+
+static struct omap_hwmod_class_sysconfig omap243x_gpio_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.syss_offs	= 0x0014,
+	.sysc_flags	= (SYSC_HAS_ENAWAKEUP | SYSC_HAS_SIDLEMODE |
+			   SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+	.sysc_fields    = &omap_hwmod_sysc_type1,
+};
+
+/*
+ * 'gpio' class
+ * general purpose io module
+ */
+static struct omap_hwmod_class omap243x_gpio_hwmod_class = {
+	.name = "gpio",
+	.sysc = &omap243x_gpio_sysc,
+	.rev = 0,
+};
+
+/* gpio1 */
+static struct omap_hwmod_irq_info omap243x_gpio1_irqs[] = {
+	{ .irq = 29 }, /* INT_24XX_GPIO_BANK1 */
+};
+
+static struct omap_hwmod_ocp_if *omap2430_gpio1_slaves[] = {
+	&omap2430_l4_wkup__gpio1,
+};
+
+static struct omap_hwmod omap2430_gpio1_hwmod = {
+	.name		= "gpio1",
+	.mpu_irqs	= omap243x_gpio1_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap243x_gpio1_irqs),
+	.main_clk	= "gpios_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP24XX_EN_GPIOS_SHIFT,
+			.module_offs = WKUP_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP24XX_EN_GPIOS_SHIFT,
+		},
+	},
+	.slaves		= omap2430_gpio1_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2430_gpio1_slaves),
+	.class		= &omap243x_gpio_hwmod_class,
+	.dev_attr	= &gpio_dev_attr,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
+};
+
+/* gpio2 */
+static struct omap_hwmod_irq_info omap243x_gpio2_irqs[] = {
+	{ .irq = 30 }, /* INT_24XX_GPIO_BANK2 */
+};
+
+static struct omap_hwmod_ocp_if *omap2430_gpio2_slaves[] = {
+	&omap2430_l4_wkup__gpio2,
+};
+
+static struct omap_hwmod omap2430_gpio2_hwmod = {
+	.name		= "gpio2",
+	.mpu_irqs	= omap243x_gpio2_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap243x_gpio2_irqs),
+	.main_clk	= "gpios_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP24XX_EN_GPIOS_SHIFT,
+			.module_offs = WKUP_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP24XX_ST_GPIOS_SHIFT,
+		},
+	},
+	.slaves		= omap2430_gpio2_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2430_gpio2_slaves),
+	.class		= &omap243x_gpio_hwmod_class,
+	.dev_attr	= &gpio_dev_attr,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
+};
+
+/* gpio3 */
+static struct omap_hwmod_irq_info omap243x_gpio3_irqs[] = {
+	{ .irq = 31 }, /* INT_24XX_GPIO_BANK3 */
+};
+
+static struct omap_hwmod_ocp_if *omap2430_gpio3_slaves[] = {
+	&omap2430_l4_wkup__gpio3,
+};
+
+static struct omap_hwmod omap2430_gpio3_hwmod = {
+	.name		= "gpio3",
+	.mpu_irqs	= omap243x_gpio3_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap243x_gpio3_irqs),
+	.main_clk	= "gpios_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP24XX_EN_GPIOS_SHIFT,
+			.module_offs = WKUP_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP24XX_ST_GPIOS_SHIFT,
+		},
+	},
+	.slaves		= omap2430_gpio3_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2430_gpio3_slaves),
+	.class		= &omap243x_gpio_hwmod_class,
+	.dev_attr	= &gpio_dev_attr,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
+};
+
+/* gpio4 */
+static struct omap_hwmod_irq_info omap243x_gpio4_irqs[] = {
+	{ .irq = 32 }, /* INT_24XX_GPIO_BANK4 */
+};
+
+static struct omap_hwmod_ocp_if *omap2430_gpio4_slaves[] = {
+	&omap2430_l4_wkup__gpio4,
+};
+
+static struct omap_hwmod omap2430_gpio4_hwmod = {
+	.name		= "gpio4",
+	.mpu_irqs	= omap243x_gpio4_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap243x_gpio4_irqs),
+	.main_clk	= "gpios_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP24XX_EN_GPIOS_SHIFT,
+			.module_offs = WKUP_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP24XX_ST_GPIOS_SHIFT,
+		},
+	},
+	.slaves		= omap2430_gpio4_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2430_gpio4_slaves),
+	.class		= &omap243x_gpio_hwmod_class,
+	.dev_attr	= &gpio_dev_attr,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
+};
+
+/* gpio5 */
+static struct omap_hwmod_irq_info omap243x_gpio5_irqs[] = {
+	{ .irq = 33 }, /* INT_24XX_GPIO_BANK5 */
+};
+
+static struct omap_hwmod_ocp_if *omap2430_gpio5_slaves[] = {
+	&omap2430_l4_core__gpio5,
+};
+
+static struct omap_hwmod omap2430_gpio5_hwmod = {
+	.name		= "gpio5",
+	.mpu_irqs	= omap243x_gpio5_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap243x_gpio5_irqs),
+	.main_clk	= "gpio5_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 2,
+			.module_bit = OMAP2430_EN_GPIO5_SHIFT,
+			.module_offs = CORE_MOD,
+			.idlest_reg_id = 2,
+			.idlest_idle_bit = OMAP2430_ST_GPIO5_SHIFT,
+		},
+	},
+	.slaves		= omap2430_gpio5_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2430_gpio5_slaves),
+	.class		= &omap243x_gpio_hwmod_class,
+	.dev_attr	= &gpio_dev_attr,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
+};
+
+/* dma_system */
+static struct omap_hwmod_class_sysconfig omap2430_dma_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x002c,
+	.syss_offs	= 0x0028,
+	.sysc_flags	= (SYSC_HAS_SOFTRESET | SYSC_HAS_MIDLEMODE |
+			   SYSC_HAS_CLOCKACTIVITY | SYSC_HAS_EMUFREE |
+			   SYSC_HAS_AUTOIDLE),
+	.idlemodes	= (MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap2430_dma_hwmod_class = {
+	.name = "dma",
+	.sysc = &omap2430_dma_sysc,
+};
+
+/* dma attributes */
+static struct omap_dma_dev_attr dma_dev_attr = {
+	.dev_caps  = RESERVE_CHANNEL | DMA_LINKED_LCH | GLOBAL_PRIORITY |
+				IS_CSSA_32 | IS_CDSA_32 | IS_RW_PRIORITY,
+	.lch_count = 32,
+};
+
+static struct omap_hwmod_irq_info omap2430_dma_system_irqs[] = {
+	{ .name = "0", .irq = 12 }, /* INT_24XX_SDMA_IRQ0 */
+	{ .name = "1", .irq = 13 }, /* INT_24XX_SDMA_IRQ1 */
+	{ .name = "2", .irq = 14 }, /* INT_24XX_SDMA_IRQ2 */
+	{ .name = "3", .irq = 15 }, /* INT_24XX_SDMA_IRQ3 */
+};
+
+static struct omap_hwmod_addr_space omap2430_dma_system_addrs[] = {
+	{
+		.pa_start	= 0x48056000,
+		.pa_end		= 0x4a0560ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* dma_system -> L3 */
+static struct omap_hwmod_ocp_if omap2430_dma_system__l3 = {
+	.master		= &omap2430_dma_system_hwmod,
+	.slave		= &omap2430_l3_main_hwmod,
+	.clk		= "core_l3_ck",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* dma_system master ports */
+static struct omap_hwmod_ocp_if *omap2430_dma_system_masters[] = {
+	&omap2430_dma_system__l3,
+};
+
+/* l4_core -> dma_system */
+static struct omap_hwmod_ocp_if omap2430_l4_core__dma_system = {
+	.master		= &omap2430_l4_core_hwmod,
+	.slave		= &omap2430_dma_system_hwmod,
+	.clk		= "sdma_ick",
+	.addr		= omap2430_dma_system_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap2430_dma_system_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* dma_system slave ports */
+static struct omap_hwmod_ocp_if *omap2430_dma_system_slaves[] = {
+	&omap2430_l4_core__dma_system,
+};
+
+static struct omap_hwmod omap2430_dma_system_hwmod = {
+	.name		= "dma",
+	.class		= &omap2430_dma_hwmod_class,
+	.mpu_irqs	= omap2430_dma_system_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap2430_dma_system_irqs),
+	.main_clk	= "core_l3_ck",
+	.slaves		= omap2430_dma_system_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2430_dma_system_slaves),
+	.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,
+};
+
 static __initdata struct omap_hwmod *omap2430_hwmods[] = {
 	&omap2430_l3_main_hwmod,
 	&omap2430_l4_core_hwmod,
@@ -428,6 +929,18 @@ static __initdata struct omap_hwmod *oma
 	&omap2430_uart1_hwmod,
 	&omap2430_uart2_hwmod,
 	&omap2430_uart3_hwmod,
+	&omap2430_i2c1_hwmod,
+	&omap2430_i2c2_hwmod,
+
+	/* gpio class */
+	&omap2430_gpio1_hwmod,
+	&omap2430_gpio2_hwmod,
+	&omap2430_gpio3_hwmod,
+	&omap2430_gpio4_hwmod,
+	&omap2430_gpio5_hwmod,
+
+	/* dma_system class*/
+	&omap2430_dma_system_hwmod,
 	NULL,
 };
 
@@ -435,5 +948,3 @@ int __init omap2430_hwmod_init(void)
 {
 	return omap_hwmod_init(omap2430_hwmods);
 }
-
-
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c	2011-03-14 21:20:32.000000000 -0400
@@ -18,11 +18,16 @@
 #include <plat/cpu.h>
 #include <plat/dma.h>
 #include <plat/serial.h>
+#include <plat/l4_3xxx.h>
+#include <plat/i2c.h>
+#include <plat/gpio.h>
+#include <plat/smartreflex.h>
 
 #include "omap_hwmod_common_data.h"
 
 #include "prm-regbits-34xx.h"
 #include "cm-regbits-34xx.h"
+#include "wd_timer.h"
 
 /*
  * OMAP3xxx hardware module integration data
@@ -39,6 +44,19 @@ static struct omap_hwmod omap3xxx_l3_mai
 static struct omap_hwmod omap3xxx_l4_core_hwmod;
 static struct omap_hwmod omap3xxx_l4_per_hwmod;
 static struct omap_hwmod omap3xxx_wd_timer2_hwmod;
+static struct omap_hwmod omap3xxx_i2c1_hwmod;
+static struct omap_hwmod omap3xxx_i2c2_hwmod;
+static struct omap_hwmod omap3xxx_i2c3_hwmod;
+static struct omap_hwmod omap3xxx_gpio1_hwmod;
+static struct omap_hwmod omap3xxx_gpio2_hwmod;
+static struct omap_hwmod omap3xxx_gpio3_hwmod;
+static struct omap_hwmod omap3xxx_gpio4_hwmod;
+static struct omap_hwmod omap3xxx_gpio5_hwmod;
+static struct omap_hwmod omap3xxx_gpio6_hwmod;
+static struct omap_hwmod omap34xx_sr1_hwmod;
+static struct omap_hwmod omap34xx_sr2_hwmod;
+
+static struct omap_hwmod omap3xxx_dma_system_hwmod;
 
 /* L3 -> L4_CORE interface */
 static struct omap_hwmod_ocp_if omap3xxx_l3_main__l4_core = {
@@ -169,9 +187,125 @@ static struct omap_hwmod_ocp_if omap3_l4
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
+/* I2C IP block address space length (in bytes) */
+#define OMAP2_I2C_AS_LEN		128
+
+/* L4 CORE -> I2C1 interface */
+static struct omap_hwmod_addr_space omap3xxx_i2c1_addr_space[] = {
+	{
+		.pa_start	= 0x48070000,
+		.pa_end		= 0x48070000 + OMAP2_I2C_AS_LEN - 1,
+		.flags		= ADDR_TYPE_RT,
+	},
+};
+
+static struct omap_hwmod_ocp_if omap3_l4_core__i2c1 = {
+	.master		= &omap3xxx_l4_core_hwmod,
+	.slave		= &omap3xxx_i2c1_hwmod,
+	.clk		= "i2c1_ick",
+	.addr		= omap3xxx_i2c1_addr_space,
+	.addr_cnt	= ARRAY_SIZE(omap3xxx_i2c1_addr_space),
+	.fw = {
+		.omap2 = {
+			.l4_fw_region  = OMAP3_L4_CORE_FW_I2C1_REGION,
+			.l4_prot_group = 7,
+			.flags	= OMAP_FIREWALL_L4,
+		}
+	},
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* L4 CORE -> I2C2 interface */
+static struct omap_hwmod_addr_space omap3xxx_i2c2_addr_space[] = {
+	{
+		.pa_start	= 0x48072000,
+		.pa_end		= 0x48072000 + OMAP2_I2C_AS_LEN - 1,
+		.flags		= ADDR_TYPE_RT,
+	},
+};
+
+static struct omap_hwmod_ocp_if omap3_l4_core__i2c2 = {
+	.master		= &omap3xxx_l4_core_hwmod,
+	.slave		= &omap3xxx_i2c2_hwmod,
+	.clk		= "i2c2_ick",
+	.addr		= omap3xxx_i2c2_addr_space,
+	.addr_cnt	= ARRAY_SIZE(omap3xxx_i2c2_addr_space),
+	.fw = {
+		.omap2 = {
+			.l4_fw_region  = OMAP3_L4_CORE_FW_I2C2_REGION,
+			.l4_prot_group = 7,
+			.flags = OMAP_FIREWALL_L4,
+		}
+	},
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* L4 CORE -> I2C3 interface */
+static struct omap_hwmod_addr_space omap3xxx_i2c3_addr_space[] = {
+	{
+		.pa_start	= 0x48060000,
+		.pa_end		= 0x48060000 + OMAP2_I2C_AS_LEN - 1,
+		.flags		= ADDR_TYPE_RT,
+	},
+};
+
+static struct omap_hwmod_ocp_if omap3_l4_core__i2c3 = {
+	.master		= &omap3xxx_l4_core_hwmod,
+	.slave		= &omap3xxx_i2c3_hwmod,
+	.clk		= "i2c3_ick",
+	.addr		= omap3xxx_i2c3_addr_space,
+	.addr_cnt	= ARRAY_SIZE(omap3xxx_i2c3_addr_space),
+	.fw = {
+		.omap2 = {
+			.l4_fw_region  = OMAP3_L4_CORE_FW_I2C3_REGION,
+			.l4_prot_group = 7,
+			.flags = OMAP_FIREWALL_L4,
+		}
+	},
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* L4 CORE -> SR1 interface */
+static struct omap_hwmod_addr_space omap3_sr1_addr_space[] = {
+	{
+		.pa_start	= OMAP34XX_SR1_BASE,
+		.pa_end		= OMAP34XX_SR1_BASE + SZ_1K - 1,
+		.flags		= ADDR_TYPE_RT,
+	},
+};
+
+static struct omap_hwmod_ocp_if omap3_l4_core__sr1 = {
+	.master		= &omap3xxx_l4_core_hwmod,
+	.slave		= &omap34xx_sr1_hwmod,
+	.clk		= "sr_l4_ick",
+	.addr		= omap3_sr1_addr_space,
+	.addr_cnt	= ARRAY_SIZE(omap3_sr1_addr_space),
+	.user		= OCP_USER_MPU,
+};
+
+/* L4 CORE -> SR1 interface */
+static struct omap_hwmod_addr_space omap3_sr2_addr_space[] = {
+	{
+		.pa_start	= OMAP34XX_SR2_BASE,
+		.pa_end		= OMAP34XX_SR2_BASE + SZ_1K - 1,
+		.flags		= ADDR_TYPE_RT,
+	},
+};
+
+static struct omap_hwmod_ocp_if omap3_l4_core__sr2 = {
+	.master		= &omap3xxx_l4_core_hwmod,
+	.slave		= &omap34xx_sr2_hwmod,
+	.clk		= "sr_l4_ick",
+	.addr		= omap3_sr2_addr_space,
+	.addr_cnt	= ARRAY_SIZE(omap3_sr2_addr_space),
+	.user		= OCP_USER_MPU,
+};
+
 /* Slave interfaces on the L4_CORE interconnect */
 static struct omap_hwmod_ocp_if *omap3xxx_l4_core_slaves[] = {
 	&omap3xxx_l3_main__l4_core,
+	&omap3_l4_core__sr1,
+	&omap3_l4_core__sr2,
 };
 
 /* Master interfaces on the L4_CORE interconnect */
@@ -179,6 +313,9 @@ static struct omap_hwmod_ocp_if *omap3xx
 	&omap3xxx_l4_core__l4_wkup,
 	&omap3_l4_core__uart1,
 	&omap3_l4_core__uart2,
+	&omap3_l4_core__i2c1,
+	&omap3_l4_core__i2c2,
+	&omap3_l4_core__i2c3,
 };
 
 /* L4 CORE */
@@ -315,9 +452,22 @@ static struct omap_hwmod_class_sysconfig
 	.sysc_fields    = &omap_hwmod_sysc_type1,
 };
 
+/* I2C common */
+static struct omap_hwmod_class_sysconfig i2c_sysc = {
+	.rev_offs	= 0x00,
+	.sysc_offs	= 0x20,
+	.syss_offs	= 0x10,
+	.sysc_flags	= (SYSC_HAS_CLOCKACTIVITY | SYSC_HAS_SIDLEMODE |
+			   SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET |
+			   SYSC_HAS_AUTOIDLE),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+	.sysc_fields    = &omap_hwmod_sysc_type1,
+};
+
 static struct omap_hwmod_class omap3xxx_wd_timer_hwmod_class = {
-	.name = "wd_timer",
-	.sysc = &omap3xxx_wd_timer_sysc,
+	.name		= "wd_timer",
+	.sysc		= &omap3xxx_wd_timer_sysc,
+	.pre_shutdown	= &omap2_wd_timer_disable
 };
 
 /* wd_timer2 */
@@ -509,6 +659,703 @@ static struct omap_hwmod omap3xxx_uart4_
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3630ES1),
 };
 
+static struct omap_hwmod_class i2c_class = {
+	.name = "i2c",
+	.sysc = &i2c_sysc,
+};
+
+/* I2C1 */
+
+static struct omap_i2c_dev_attr i2c1_dev_attr = {
+	.fifo_depth	= 8, /* bytes */
+};
+
+static struct omap_hwmod_irq_info i2c1_mpu_irqs[] = {
+	{ .irq = INT_24XX_I2C1_IRQ, },
+};
+
+static struct omap_hwmod_dma_info i2c1_sdma_reqs[] = {
+	{ .name = "tx", .dma_req = OMAP24XX_DMA_I2C1_TX },
+	{ .name = "rx", .dma_req = OMAP24XX_DMA_I2C1_RX },
+};
+
+static struct omap_hwmod_ocp_if *omap3xxx_i2c1_slaves[] = {
+	&omap3_l4_core__i2c1,
+};
+
+static struct omap_hwmod omap3xxx_i2c1_hwmod = {
+	.name		= "i2c1",
+	.mpu_irqs	= i2c1_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(i2c1_mpu_irqs),
+	.sdma_reqs	= i2c1_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(i2c1_sdma_reqs),
+	.main_clk	= "i2c1_fck",
+	.prcm		= {
+		.omap2 = {
+			.module_offs = CORE_MOD,
+			.prcm_reg_id = 1,
+			.module_bit = OMAP3430_EN_I2C1_SHIFT,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP3430_ST_I2C1_SHIFT,
+		},
+	},
+	.slaves		= omap3xxx_i2c1_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap3xxx_i2c1_slaves),
+	.class		= &i2c_class,
+	.dev_attr	= &i2c1_dev_attr,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+};
+
+/* I2C2 */
+
+static struct omap_i2c_dev_attr i2c2_dev_attr = {
+	.fifo_depth	= 8, /* bytes */
+};
+
+static struct omap_hwmod_irq_info i2c2_mpu_irqs[] = {
+	{ .irq = INT_24XX_I2C2_IRQ, },
+};
+
+static struct omap_hwmod_dma_info i2c2_sdma_reqs[] = {
+	{ .name = "tx", .dma_req = OMAP24XX_DMA_I2C2_TX },
+	{ .name = "rx", .dma_req = OMAP24XX_DMA_I2C2_RX },
+};
+
+static struct omap_hwmod_ocp_if *omap3xxx_i2c2_slaves[] = {
+	&omap3_l4_core__i2c2,
+};
+
+static struct omap_hwmod omap3xxx_i2c2_hwmod = {
+	.name		= "i2c2",
+	.mpu_irqs	= i2c2_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(i2c2_mpu_irqs),
+	.sdma_reqs	= i2c2_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(i2c2_sdma_reqs),
+	.main_clk	= "i2c2_fck",
+	.prcm		= {
+		.omap2 = {
+			.module_offs = CORE_MOD,
+			.prcm_reg_id = 1,
+			.module_bit = OMAP3430_EN_I2C2_SHIFT,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP3430_ST_I2C2_SHIFT,
+		},
+	},
+	.slaves		= omap3xxx_i2c2_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap3xxx_i2c2_slaves),
+	.class		= &i2c_class,
+	.dev_attr	= &i2c2_dev_attr,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+};
+
+/* I2C3 */
+
+static struct omap_i2c_dev_attr i2c3_dev_attr = {
+	.fifo_depth	= 64, /* bytes */
+};
+
+static struct omap_hwmod_irq_info i2c3_mpu_irqs[] = {
+	{ .irq = INT_34XX_I2C3_IRQ, },
+};
+
+static struct omap_hwmod_dma_info i2c3_sdma_reqs[] = {
+	{ .name = "tx", .dma_req = OMAP34XX_DMA_I2C3_TX },
+	{ .name = "rx", .dma_req = OMAP34XX_DMA_I2C3_RX },
+};
+
+static struct omap_hwmod_ocp_if *omap3xxx_i2c3_slaves[] = {
+	&omap3_l4_core__i2c3,
+};
+
+static struct omap_hwmod omap3xxx_i2c3_hwmod = {
+	.name		= "i2c3",
+	.mpu_irqs	= i2c3_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(i2c3_mpu_irqs),
+	.sdma_reqs	= i2c3_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(i2c3_sdma_reqs),
+	.main_clk	= "i2c3_fck",
+	.prcm		= {
+		.omap2 = {
+			.module_offs = CORE_MOD,
+			.prcm_reg_id = 1,
+			.module_bit = OMAP3430_EN_I2C3_SHIFT,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP3430_ST_I2C3_SHIFT,
+		},
+	},
+	.slaves		= omap3xxx_i2c3_slaves,
+	.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 */
+static struct omap_hwmod_addr_space omap3xxx_gpio1_addrs[] = {
+	{
+		.pa_start	= 0x48310000,
+		.pa_end		= 0x483101ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+static struct omap_hwmod_ocp_if omap3xxx_l4_wkup__gpio1 = {
+	.master		= &omap3xxx_l4_wkup_hwmod,
+	.slave		= &omap3xxx_gpio1_hwmod,
+	.addr		= omap3xxx_gpio1_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap3xxx_gpio1_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_per -> gpio2 */
+static struct omap_hwmod_addr_space omap3xxx_gpio2_addrs[] = {
+	{
+		.pa_start	= 0x49050000,
+		.pa_end		= 0x490501ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+static struct omap_hwmod_ocp_if omap3xxx_l4_per__gpio2 = {
+	.master		= &omap3xxx_l4_per_hwmod,
+	.slave		= &omap3xxx_gpio2_hwmod,
+	.addr		= omap3xxx_gpio2_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap3xxx_gpio2_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_per -> gpio3 */
+static struct omap_hwmod_addr_space omap3xxx_gpio3_addrs[] = {
+	{
+		.pa_start	= 0x49052000,
+		.pa_end		= 0x490521ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+static struct omap_hwmod_ocp_if omap3xxx_l4_per__gpio3 = {
+	.master		= &omap3xxx_l4_per_hwmod,
+	.slave		= &omap3xxx_gpio3_hwmod,
+	.addr		= omap3xxx_gpio3_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap3xxx_gpio3_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_per -> gpio4 */
+static struct omap_hwmod_addr_space omap3xxx_gpio4_addrs[] = {
+	{
+		.pa_start	= 0x49054000,
+		.pa_end		= 0x490541ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+static struct omap_hwmod_ocp_if omap3xxx_l4_per__gpio4 = {
+	.master		= &omap3xxx_l4_per_hwmod,
+	.slave		= &omap3xxx_gpio4_hwmod,
+	.addr		= omap3xxx_gpio4_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap3xxx_gpio4_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_per -> gpio5 */
+static struct omap_hwmod_addr_space omap3xxx_gpio5_addrs[] = {
+	{
+		.pa_start	= 0x49056000,
+		.pa_end		= 0x490561ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+static struct omap_hwmod_ocp_if omap3xxx_l4_per__gpio5 = {
+	.master		= &omap3xxx_l4_per_hwmod,
+	.slave		= &omap3xxx_gpio5_hwmod,
+	.addr		= omap3xxx_gpio5_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap3xxx_gpio5_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_per -> gpio6 */
+static struct omap_hwmod_addr_space omap3xxx_gpio6_addrs[] = {
+	{
+		.pa_start	= 0x49058000,
+		.pa_end		= 0x490581ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+static struct omap_hwmod_ocp_if omap3xxx_l4_per__gpio6 = {
+	.master		= &omap3xxx_l4_per_hwmod,
+	.slave		= &omap3xxx_gpio6_hwmod,
+	.addr		= omap3xxx_gpio6_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap3xxx_gpio6_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/*
+ * 'gpio' class
+ * general purpose io module
+ */
+
+static struct omap_hwmod_class_sysconfig omap3xxx_gpio_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.syss_offs	= 0x0014,
+	.sysc_flags	= (SYSC_HAS_ENAWAKEUP | SYSC_HAS_SIDLEMODE |
+			   SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+	.sysc_fields    = &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap3xxx_gpio_hwmod_class = {
+	.name = "gpio",
+	.sysc = &omap3xxx_gpio_sysc,
+	.rev = 1,
+};
+
+/* gpio_dev_attr*/
+static struct omap_gpio_dev_attr gpio_dev_attr = {
+	.bank_width = 32,
+	.dbck_flag = true,
+};
+
+/* gpio1 */
+static struct omap_hwmod_irq_info omap3xxx_gpio1_irqs[] = {
+	{ .irq = 29 }, /* INT_34XX_GPIO_BANK1 */
+};
+
+static struct omap_hwmod_opt_clk gpio1_opt_clks[] = {
+	{ .role = "dbclk", .clk = "gpio1_dbck", },
+};
+
+static struct omap_hwmod_ocp_if *omap3xxx_gpio1_slaves[] = {
+	&omap3xxx_l4_wkup__gpio1,
+};
+
+static struct omap_hwmod omap3xxx_gpio1_hwmod = {
+	.name		= "gpio1",
+	.mpu_irqs	= omap3xxx_gpio1_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_gpio1_irqs),
+	.main_clk	= "gpio1_ick",
+	.opt_clks	= gpio1_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(gpio1_opt_clks),
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP3430_EN_GPIO1_SHIFT,
+			.module_offs = WKUP_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP3430_ST_GPIO1_SHIFT,
+		},
+	},
+	.slaves		= omap3xxx_gpio1_slaves,
+	.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 */
+static struct omap_hwmod_irq_info omap3xxx_gpio2_irqs[] = {
+	{ .irq = 30 }, /* INT_34XX_GPIO_BANK2 */
+};
+
+static struct omap_hwmod_opt_clk gpio2_opt_clks[] = {
+	{ .role = "dbclk", .clk = "gpio2_dbck", },
+};
+
+static struct omap_hwmod_ocp_if *omap3xxx_gpio2_slaves[] = {
+	&omap3xxx_l4_per__gpio2,
+};
+
+static struct omap_hwmod omap3xxx_gpio2_hwmod = {
+	.name		= "gpio2",
+	.mpu_irqs	= omap3xxx_gpio2_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_gpio2_irqs),
+	.main_clk	= "gpio2_ick",
+	.opt_clks	= gpio2_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(gpio2_opt_clks),
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP3430_EN_GPIO2_SHIFT,
+			.module_offs = OMAP3430_PER_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP3430_ST_GPIO2_SHIFT,
+		},
+	},
+	.slaves		= omap3xxx_gpio2_slaves,
+	.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 */
+static struct omap_hwmod_irq_info omap3xxx_gpio3_irqs[] = {
+	{ .irq = 31 }, /* INT_34XX_GPIO_BANK3 */
+};
+
+static struct omap_hwmod_opt_clk gpio3_opt_clks[] = {
+	{ .role = "dbclk", .clk = "gpio3_dbck", },
+};
+
+static struct omap_hwmod_ocp_if *omap3xxx_gpio3_slaves[] = {
+	&omap3xxx_l4_per__gpio3,
+};
+
+static struct omap_hwmod omap3xxx_gpio3_hwmod = {
+	.name		= "gpio3",
+	.mpu_irqs	= omap3xxx_gpio3_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_gpio3_irqs),
+	.main_clk	= "gpio3_ick",
+	.opt_clks	= gpio3_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(gpio3_opt_clks),
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP3430_EN_GPIO3_SHIFT,
+			.module_offs = OMAP3430_PER_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP3430_ST_GPIO3_SHIFT,
+		},
+	},
+	.slaves		= omap3xxx_gpio3_slaves,
+	.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 */
+static struct omap_hwmod_irq_info omap3xxx_gpio4_irqs[] = {
+	{ .irq = 32 }, /* INT_34XX_GPIO_BANK4 */
+};
+
+static struct omap_hwmod_opt_clk gpio4_opt_clks[] = {
+	{ .role = "dbclk", .clk = "gpio4_dbck", },
+};
+
+static struct omap_hwmod_ocp_if *omap3xxx_gpio4_slaves[] = {
+	&omap3xxx_l4_per__gpio4,
+};
+
+static struct omap_hwmod omap3xxx_gpio4_hwmod = {
+	.name		= "gpio4",
+	.mpu_irqs	= omap3xxx_gpio4_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_gpio4_irqs),
+	.main_clk	= "gpio4_ick",
+	.opt_clks	= gpio4_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(gpio4_opt_clks),
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP3430_EN_GPIO4_SHIFT,
+			.module_offs = OMAP3430_PER_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP3430_ST_GPIO4_SHIFT,
+		},
+	},
+	.slaves		= omap3xxx_gpio4_slaves,
+	.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 */
+static struct omap_hwmod_irq_info omap3xxx_gpio5_irqs[] = {
+	{ .irq = 33 }, /* INT_34XX_GPIO_BANK5 */
+};
+
+static struct omap_hwmod_opt_clk gpio5_opt_clks[] = {
+	{ .role = "dbclk", .clk = "gpio5_dbck", },
+};
+
+static struct omap_hwmod_ocp_if *omap3xxx_gpio5_slaves[] = {
+	&omap3xxx_l4_per__gpio5,
+};
+
+static struct omap_hwmod omap3xxx_gpio5_hwmod = {
+	.name		= "gpio5",
+	.mpu_irqs	= omap3xxx_gpio5_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_gpio5_irqs),
+	.main_clk	= "gpio5_ick",
+	.opt_clks	= gpio5_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(gpio5_opt_clks),
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP3430_EN_GPIO5_SHIFT,
+			.module_offs = OMAP3430_PER_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP3430_ST_GPIO5_SHIFT,
+		},
+	},
+	.slaves		= omap3xxx_gpio5_slaves,
+	.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 */
+static struct omap_hwmod_irq_info omap3xxx_gpio6_irqs[] = {
+	{ .irq = 34 }, /* INT_34XX_GPIO_BANK6 */
+};
+
+static struct omap_hwmod_opt_clk gpio6_opt_clks[] = {
+	{ .role = "dbclk", .clk = "gpio6_dbck", },
+};
+
+static struct omap_hwmod_ocp_if *omap3xxx_gpio6_slaves[] = {
+	&omap3xxx_l4_per__gpio6,
+};
+
+static struct omap_hwmod omap3xxx_gpio6_hwmod = {
+	.name		= "gpio6",
+	.mpu_irqs	= omap3xxx_gpio6_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_gpio6_irqs),
+	.main_clk	= "gpio6_ick",
+	.opt_clks	= gpio6_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(gpio6_opt_clks),
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP3430_EN_GPIO6_SHIFT,
+			.module_offs = OMAP3430_PER_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP3430_ST_GPIO6_SHIFT,
+		},
+	},
+	.slaves		= omap3xxx_gpio6_slaves,
+	.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 */
+static struct omap_hwmod_ocp_if omap3xxx_dma_system__l3 = {
+	.master		= &omap3xxx_dma_system_hwmod,
+	.slave		= &omap3xxx_l3_main_hwmod,
+	.clk		= "core_l3_ick",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* dma attributes */
+static struct omap_dma_dev_attr dma_dev_attr = {
+	.dev_caps  = RESERVE_CHANNEL | DMA_LINKED_LCH | GLOBAL_PRIORITY |
+				IS_CSSA_32 | IS_CDSA_32 | IS_RW_PRIORITY,
+	.lch_count = 32,
+};
+
+static struct omap_hwmod_class_sysconfig omap3xxx_dma_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x002c,
+	.syss_offs	= 0x0028,
+	.sysc_flags	= (SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET |
+			   SYSC_HAS_MIDLEMODE | SYSC_HAS_CLOCKACTIVITY |
+			   SYSC_HAS_EMUFREE | SYSC_HAS_AUTOIDLE),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
+			   MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap3xxx_dma_hwmod_class = {
+	.name = "dma",
+	.sysc = &omap3xxx_dma_sysc,
+};
+
+/* dma_system */
+static struct omap_hwmod_irq_info omap3xxx_dma_system_irqs[] = {
+	{ .name = "0", .irq = 12 }, /* INT_24XX_SDMA_IRQ0 */
+	{ .name = "1", .irq = 13 }, /* INT_24XX_SDMA_IRQ1 */
+	{ .name = "2", .irq = 14 }, /* INT_24XX_SDMA_IRQ2 */
+	{ .name = "3", .irq = 15 }, /* INT_24XX_SDMA_IRQ3 */
+};
+
+static struct omap_hwmod_addr_space omap3xxx_dma_system_addrs[] = {
+	{
+		.pa_start	= 0x48056000,
+		.pa_end		= 0x4a0560ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* dma_system master ports */
+static struct omap_hwmod_ocp_if *omap3xxx_dma_system_masters[] = {
+	&omap3xxx_dma_system__l3,
+};
+
+/* l4_cfg -> dma_system */
+static struct omap_hwmod_ocp_if omap3xxx_l4_core__dma_system = {
+	.master		= &omap3xxx_l4_core_hwmod,
+	.slave		= &omap3xxx_dma_system_hwmod,
+	.clk		= "core_l4_ick",
+	.addr		= omap3xxx_dma_system_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap3xxx_dma_system_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* dma_system slave ports */
+static struct omap_hwmod_ocp_if *omap3xxx_dma_system_slaves[] = {
+	&omap3xxx_l4_core__dma_system,
+};
+
+static struct omap_hwmod omap3xxx_dma_system_hwmod = {
+	.name		= "dma",
+	.class		= &omap3xxx_dma_hwmod_class,
+	.mpu_irqs	= omap3xxx_dma_system_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_dma_system_irqs),
+	.main_clk	= "core_l3_ick",
+	.prcm = {
+		.omap2 = {
+			.module_offs		= CORE_MOD,
+			.prcm_reg_id		= 1,
+			.module_bit		= OMAP3430_ST_SDMA_SHIFT,
+			.idlest_reg_id		= 1,
+			.idlest_idle_bit	= OMAP3430_ST_SDMA_SHIFT,
+		},
+	},
+	.slaves		= omap3xxx_dma_system_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap3xxx_dma_system_slaves),
+	.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,
+};
+
+/* SR common */
+static struct omap_hwmod_sysc_fields omap34xx_sr_sysc_fields = {
+	.clkact_shift	= 20,
+};
+
+static struct omap_hwmod_class_sysconfig omap34xx_sr_sysc = {
+	.sysc_offs	= 0x24,
+	.sysc_flags	= (SYSC_HAS_CLOCKACTIVITY | SYSC_NO_CACHE),
+	.clockact	= CLOCKACT_TEST_ICLK,
+	.sysc_fields	= &omap34xx_sr_sysc_fields,
+};
+
+static struct omap_hwmod_class omap34xx_smartreflex_hwmod_class = {
+	.name = "smartreflex",
+	.sysc = &omap34xx_sr_sysc,
+	.rev  = 1,
+};
+
+static struct omap_hwmod_sysc_fields omap36xx_sr_sysc_fields = {
+	.sidle_shift	= 24,
+	.enwkup_shift	= 26
+};
+
+static struct omap_hwmod_class_sysconfig omap36xx_sr_sysc = {
+	.sysc_offs	= 0x38,
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+	.sysc_flags	= (SYSC_HAS_SIDLEMODE | SYSC_HAS_ENAWAKEUP |
+			SYSC_NO_CACHE),
+	.sysc_fields	= &omap36xx_sr_sysc_fields,
+};
+
+static struct omap_hwmod_class omap36xx_smartreflex_hwmod_class = {
+	.name = "smartreflex",
+	.sysc = &omap36xx_sr_sysc,
+	.rev  = 2,
+};
+
+/* SR1 */
+static struct omap_hwmod_ocp_if *omap3_sr1_slaves[] = {
+	&omap3_l4_core__sr1,
+};
+
+static struct omap_hwmod omap34xx_sr1_hwmod = {
+	.name		= "sr1_hwmod",
+	.class		= &omap34xx_smartreflex_hwmod_class,
+	.main_clk	= "sr1_fck",
+	.vdd_name	= "mpu",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP3430_EN_SR1_SHIFT,
+			.module_offs = WKUP_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP3430_EN_SR1_SHIFT,
+		},
+	},
+	.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,
+};
+
+static struct omap_hwmod omap36xx_sr1_hwmod = {
+	.name		= "sr1_hwmod",
+	.class		= &omap36xx_smartreflex_hwmod_class,
+	.main_clk	= "sr1_fck",
+	.vdd_name	= "mpu",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP3430_EN_SR1_SHIFT,
+			.module_offs = WKUP_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP3430_EN_SR1_SHIFT,
+		},
+	},
+	.slaves		= omap3_sr1_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap3_sr1_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3630ES1),
+};
+
+/* SR2 */
+static struct omap_hwmod_ocp_if *omap3_sr2_slaves[] = {
+	&omap3_l4_core__sr2,
+};
+
+static struct omap_hwmod omap34xx_sr2_hwmod = {
+	.name		= "sr2_hwmod",
+	.class		= &omap34xx_smartreflex_hwmod_class,
+	.main_clk	= "sr2_fck",
+	.vdd_name	= "core",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP3430_EN_SR2_SHIFT,
+			.module_offs = WKUP_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP3430_EN_SR2_SHIFT,
+		},
+	},
+	.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,
+};
+
+static struct omap_hwmod omap36xx_sr2_hwmod = {
+	.name		= "sr2_hwmod",
+	.class		= &omap36xx_smartreflex_hwmod_class,
+	.main_clk	= "sr2_fck",
+	.vdd_name	= "core",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP3430_EN_SR2_SHIFT,
+			.module_offs = WKUP_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP3430_EN_SR2_SHIFT,
+		},
+	},
+	.slaves		= omap3_sr2_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap3_sr2_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3630ES1),
+};
+
 static __initdata struct omap_hwmod *omap3xxx_hwmods[] = {
 	&omap3xxx_l3_main_hwmod,
 	&omap3xxx_l4_core_hwmod,
@@ -521,6 +1368,25 @@ static __initdata struct omap_hwmod *oma
 	&omap3xxx_uart2_hwmod,
 	&omap3xxx_uart3_hwmod,
 	&omap3xxx_uart4_hwmod,
+	&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,
+	&omap3xxx_gpio2_hwmod,
+	&omap3xxx_gpio3_hwmod,
+	&omap3xxx_gpio4_hwmod,
+	&omap3xxx_gpio5_hwmod,
+	&omap3xxx_gpio6_hwmod,
+
+	/* dma_system class*/
+	&omap3xxx_dma_system_hwmod,
 	NULL,
 };
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/omap_hwmod_44xx_data.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/omap_hwmod_44xx_data.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/omap_hwmod_44xx_data.c	2011-03-14 21:20:32.000000000 -0400
@@ -22,11 +22,16 @@
 
 #include <plat/omap_hwmod.h>
 #include <plat/cpu.h>
+#include <plat/gpio.h>
+#include <plat/dma.h>
 
 #include "omap_hwmod_common_data.h"
 
-#include "cm.h"
+#include "cm1_44xx.h"
+#include "cm2_44xx.h"
+#include "prm44xx.h"
 #include "prm-regbits-44xx.h"
+#include "wd_timer.h"
 
 /* Base offset for all OMAP4 interrupts external to MPUSS */
 #define OMAP44XX_IRQ_GIC_START	32
@@ -35,8 +40,11 @@
 #define OMAP44XX_DMA_REQ_START  1
 
 /* Backward references (IPs with Bus Master capability) */
+static struct omap_hwmod omap44xx_dma_system_hwmod;
 static struct omap_hwmod omap44xx_dmm_hwmod;
+static struct omap_hwmod omap44xx_dsp_hwmod;
 static struct omap_hwmod omap44xx_emif_fw_hwmod;
+static struct omap_hwmod omap44xx_iva_hwmod;
 static struct omap_hwmod omap44xx_l3_instr_hwmod;
 static struct omap_hwmod omap44xx_l3_main_1_hwmod;
 static struct omap_hwmod omap44xx_l3_main_2_hwmod;
@@ -58,7 +66,7 @@ static struct omap_hwmod omap44xx_mpu_pr
  * instance(s): dmm
  */
 static struct omap_hwmod_class omap44xx_dmm_hwmod_class = {
-	.name = "dmm",
+	.name	= "dmm",
 };
 
 /* dmm interface data */
@@ -67,7 +75,15 @@ static struct omap_hwmod_ocp_if omap44xx
 	.master		= &omap44xx_l3_main_1_hwmod,
 	.slave		= &omap44xx_dmm_hwmod,
 	.clk		= "l3_div_ck",
-	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+	.user		= OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap44xx_dmm_addrs[] = {
+	{
+		.pa_start	= 0x4e000000,
+		.pa_end		= 0x4e0007ff,
+		.flags		= ADDR_TYPE_RT
+	},
 };
 
 /* mpu -> dmm */
@@ -75,7 +91,9 @@ static struct omap_hwmod_ocp_if omap44xx
 	.master		= &omap44xx_mpu_hwmod,
 	.slave		= &omap44xx_dmm_hwmod,
 	.clk		= "l3_div_ck",
-	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+	.addr		= omap44xx_dmm_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_dmm_addrs),
+	.user		= OCP_USER_MPU,
 };
 
 /* dmm slave ports */
@@ -103,7 +121,7 @@ static struct omap_hwmod omap44xx_dmm_hw
  * instance(s): emif_fw
  */
 static struct omap_hwmod_class omap44xx_emif_fw_hwmod_class = {
-	.name = "emif_fw",
+	.name	= "emif_fw",
 };
 
 /* emif_fw interface data */
@@ -115,12 +133,22 @@ static struct omap_hwmod_ocp_if omap44xx
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
+static struct omap_hwmod_addr_space omap44xx_emif_fw_addrs[] = {
+	{
+		.pa_start	= 0x4a20c000,
+		.pa_end		= 0x4a20c0ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
 /* l4_cfg -> emif_fw */
 static struct omap_hwmod_ocp_if omap44xx_l4_cfg__emif_fw = {
 	.master		= &omap44xx_l4_cfg_hwmod,
 	.slave		= &omap44xx_emif_fw_hwmod,
 	.clk		= "l4_div_ck",
-	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+	.addr		= omap44xx_emif_fw_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_emif_fw_addrs),
+	.user		= OCP_USER_MPU,
 };
 
 /* emif_fw slave ports */
@@ -142,10 +170,18 @@ static struct omap_hwmod omap44xx_emif_f
  * instance(s): l3_instr, l3_main_1, l3_main_2, l3_main_3
  */
 static struct omap_hwmod_class omap44xx_l3_hwmod_class = {
-	.name = "l3",
+	.name	= "l3",
 };
 
 /* l3_instr interface data */
+/* iva -> l3_instr */
+static struct omap_hwmod_ocp_if omap44xx_iva__l3_instr = {
+	.master		= &omap44xx_iva_hwmod,
+	.slave		= &omap44xx_l3_instr_hwmod,
+	.clk		= "l3_div_ck",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
 /* l3_main_3 -> l3_instr */
 static struct omap_hwmod_ocp_if omap44xx_l3_main_3__l3_instr = {
 	.master		= &omap44xx_l3_main_3_hwmod,
@@ -156,6 +192,7 @@ static struct omap_hwmod_ocp_if omap44xx
 
 /* l3_instr slave ports */
 static struct omap_hwmod_ocp_if *omap44xx_l3_instr_slaves[] = {
+	&omap44xx_iva__l3_instr,
 	&omap44xx_l3_main_3__l3_instr,
 };
 
@@ -167,6 +204,15 @@ static struct omap_hwmod omap44xx_l3_ins
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
+/* l3_main_1 interface data */
+/* dsp -> l3_main_1 */
+static struct omap_hwmod_ocp_if omap44xx_dsp__l3_main_1 = {
+	.master		= &omap44xx_dsp_hwmod,
+	.slave		= &omap44xx_l3_main_1_hwmod,
+	.clk		= "l3_div_ck",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
 /* l3_main_2 -> l3_main_1 */
 static struct omap_hwmod_ocp_if omap44xx_l3_main_2__l3_main_1 = {
 	.master		= &omap44xx_l3_main_2_hwmod,
@@ -193,6 +239,7 @@ static struct omap_hwmod_ocp_if omap44xx
 
 /* l3_main_1 slave ports */
 static struct omap_hwmod_ocp_if *omap44xx_l3_main_1_slaves[] = {
+	&omap44xx_dsp__l3_main_1,
 	&omap44xx_l3_main_2__l3_main_1,
 	&omap44xx_l4_cfg__l3_main_1,
 	&omap44xx_mpu__l3_main_1,
@@ -207,6 +254,22 @@ static struct omap_hwmod omap44xx_l3_mai
 };
 
 /* l3_main_2 interface data */
+/* dma_system -> l3_main_2 */
+static struct omap_hwmod_ocp_if omap44xx_dma_system__l3_main_2 = {
+	.master		= &omap44xx_dma_system_hwmod,
+	.slave		= &omap44xx_l3_main_2_hwmod,
+	.clk		= "l3_div_ck",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* iva -> l3_main_2 */
+static struct omap_hwmod_ocp_if omap44xx_iva__l3_main_2 = {
+	.master		= &omap44xx_iva_hwmod,
+	.slave		= &omap44xx_l3_main_2_hwmod,
+	.clk		= "l3_div_ck",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
 /* l3_main_1 -> l3_main_2 */
 static struct omap_hwmod_ocp_if omap44xx_l3_main_1__l3_main_2 = {
 	.master		= &omap44xx_l3_main_1_hwmod,
@@ -225,6 +288,8 @@ static struct omap_hwmod_ocp_if omap44xx
 
 /* l3_main_2 slave ports */
 static struct omap_hwmod_ocp_if *omap44xx_l3_main_2_slaves[] = {
+	&omap44xx_dma_system__l3_main_2,
+	&omap44xx_iva__l3_main_2,
 	&omap44xx_l3_main_1__l3_main_2,
 	&omap44xx_l4_cfg__l3_main_2,
 };
@@ -282,10 +347,18 @@ static struct omap_hwmod omap44xx_l3_mai
  * instance(s): l4_abe, l4_cfg, l4_per, l4_wkup
  */
 static struct omap_hwmod_class omap44xx_l4_hwmod_class = {
-	.name = "l4",
+	.name	= "l4",
 };
 
 /* l4_abe interface data */
+/* dsp -> l4_abe */
+static struct omap_hwmod_ocp_if omap44xx_dsp__l4_abe = {
+	.master		= &omap44xx_dsp_hwmod,
+	.slave		= &omap44xx_l4_abe_hwmod,
+	.clk		= "ocp_abe_iclk",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
 /* l3_main_1 -> l4_abe */
 static struct omap_hwmod_ocp_if omap44xx_l3_main_1__l4_abe = {
 	.master		= &omap44xx_l3_main_1_hwmod,
@@ -304,6 +377,7 @@ static struct omap_hwmod_ocp_if omap44xx
 
 /* l4_abe slave ports */
 static struct omap_hwmod_ocp_if *omap44xx_l4_abe_slaves[] = {
+	&omap44xx_dsp__l4_abe,
 	&omap44xx_l3_main_1__l4_abe,
 	&omap44xx_mpu__l4_abe,
 };
@@ -387,7 +461,7 @@ static struct omap_hwmod omap44xx_l4_wku
  * instance(s): mpu_private
  */
 static struct omap_hwmod_class omap44xx_mpu_bus_hwmod_class = {
-	.name = "mpu_bus",
+	.name	= "mpu_bus",
 };
 
 /* mpu_private interface data */
@@ -413,12 +487,960 @@ static struct omap_hwmod omap44xx_mpu_pr
 };
 
 /*
+ * Modules omap_hwmod structures
+ *
+ * The following IPs are excluded for the moment because:
+ * - They do not need an explicit SW control using omap_hwmod API.
+ * - They still need to be validated with the driver
+ *   properly adapted to omap_hwmod / omap_device
+ *
+ *  aess
+ *  bandgap
+ *  c2c
+ *  c2c_target_fw
+ *  cm_core
+ *  cm_core_aon
+ *  counter_32k
+ *  ctrl_module_core
+ *  ctrl_module_pad_core
+ *  ctrl_module_pad_wkup
+ *  ctrl_module_wkup
+ *  debugss
+ *  dmic
+ *  dss
+ *  dss_dispc
+ *  dss_dsi1
+ *  dss_dsi2
+ *  dss_hdmi
+ *  dss_rfbi
+ *  dss_venc
+ *  efuse_ctrl_cust
+ *  efuse_ctrl_std
+ *  elm
+ *  emif1
+ *  emif2
+ *  fdif
+ *  gpmc
+ *  gpu
+ *  hdq1w
+ *  hsi
+ *  ipu
+ *  iss
+ *  kbd
+ *  mailbox
+ *  mcasp
+ *  mcbsp1
+ *  mcbsp2
+ *  mcbsp3
+ *  mcbsp4
+ *  mcpdm
+ *  mcspi1
+ *  mcspi2
+ *  mcspi3
+ *  mcspi4
+ *  mmc1
+ *  mmc2
+ *  mmc3
+ *  mmc4
+ *  mmc5
+ *  mpu_c0
+ *  mpu_c1
+ *  ocmc_ram
+ *  ocp2scp_usb_phy
+ *  ocp_wp_noc
+ *  prcm
+ *  prcm_mpu
+ *  prm
+ *  scrm
+ *  sl2if
+ *  slimbus1
+ *  slimbus2
+ *  spinlock
+ *  timer1
+ *  timer10
+ *  timer11
+ *  timer2
+ *  timer3
+ *  timer4
+ *  timer5
+ *  timer6
+ *  timer7
+ *  timer8
+ *  timer9
+ *  usb_host_fs
+ *  usb_host_hs
+ *  usb_otg_hs
+ *  usb_phy_cm
+ *  usb_tll_hs
+ *  usim
+ */
+
+/*
+ * 'dma' class
+ * dma controller for data exchange between memory to memory (i.e. internal or
+ * external memory) and gp peripherals to memory or memory to gp peripherals
+ */
+
+static struct omap_hwmod_class_sysconfig omap44xx_dma_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x002c,
+	.syss_offs	= 0x0028,
+	.sysc_flags	= (SYSC_HAS_AUTOIDLE | SYSC_HAS_CLOCKACTIVITY |
+			   SYSC_HAS_EMUFREE | SYSC_HAS_MIDLEMODE |
+			   SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET |
+			   SYSS_HAS_RESET_STATUS),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
+			   MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap44xx_dma_hwmod_class = {
+	.name	= "dma",
+	.sysc	= &omap44xx_dma_sysc,
+};
+
+/* dma dev_attr */
+static struct omap_dma_dev_attr dma_dev_attr = {
+	.dev_caps	= RESERVE_CHANNEL | DMA_LINKED_LCH | GLOBAL_PRIORITY |
+			  IS_CSSA_32 | IS_CDSA_32 | IS_RW_PRIORITY,
+	.lch_count	= 32,
+};
+
+/* dma_system */
+static struct omap_hwmod_irq_info omap44xx_dma_system_irqs[] = {
+	{ .name = "0", .irq = 12 + OMAP44XX_IRQ_GIC_START },
+	{ .name = "1", .irq = 13 + OMAP44XX_IRQ_GIC_START },
+	{ .name = "2", .irq = 14 + OMAP44XX_IRQ_GIC_START },
+	{ .name = "3", .irq = 15 + OMAP44XX_IRQ_GIC_START },
+};
+
+/* dma_system master ports */
+static struct omap_hwmod_ocp_if *omap44xx_dma_system_masters[] = {
+	&omap44xx_dma_system__l3_main_2,
+};
+
+static struct omap_hwmod_addr_space omap44xx_dma_system_addrs[] = {
+	{
+		.pa_start	= 0x4a056000,
+		.pa_end		= 0x4a0560ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_cfg -> dma_system */
+static struct omap_hwmod_ocp_if omap44xx_l4_cfg__dma_system = {
+	.master		= &omap44xx_l4_cfg_hwmod,
+	.slave		= &omap44xx_dma_system_hwmod,
+	.clk		= "l4_div_ck",
+	.addr		= omap44xx_dma_system_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_dma_system_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* dma_system slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_dma_system_slaves[] = {
+	&omap44xx_l4_cfg__dma_system,
+};
+
+static struct omap_hwmod omap44xx_dma_system_hwmod = {
+	.name		= "dma_system",
+	.class		= &omap44xx_dma_hwmod_class,
+	.mpu_irqs	= omap44xx_dma_system_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_dma_system_irqs),
+	.main_clk	= "l3_div_ck",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM_SDMA_SDMA_CLKCTRL,
+		},
+	},
+	.dev_attr	= &dma_dev_attr,
+	.slaves		= omap44xx_dma_system_slaves,
+	.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),
+};
+
+/*
+ * 'dsp' class
+ * dsp sub-system
+ */
+
+static struct omap_hwmod_class omap44xx_dsp_hwmod_class = {
+	.name	= "dsp",
+};
+
+/* dsp */
+static struct omap_hwmod_irq_info omap44xx_dsp_irqs[] = {
+	{ .irq = 28 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_rst_info omap44xx_dsp_resets[] = {
+	{ .name = "mmu_cache", .rst_shift = 1 },
+};
+
+static struct omap_hwmod_rst_info omap44xx_dsp_c0_resets[] = {
+	{ .name = "dsp", .rst_shift = 0 },
+};
+
+/* dsp -> iva */
+static struct omap_hwmod_ocp_if omap44xx_dsp__iva = {
+	.master		= &omap44xx_dsp_hwmod,
+	.slave		= &omap44xx_iva_hwmod,
+	.clk		= "dpll_iva_m5x2_ck",
+};
+
+/* dsp master ports */
+static struct omap_hwmod_ocp_if *omap44xx_dsp_masters[] = {
+	&omap44xx_dsp__l3_main_1,
+	&omap44xx_dsp__l4_abe,
+	&omap44xx_dsp__iva,
+};
+
+/* l4_cfg -> dsp */
+static struct omap_hwmod_ocp_if omap44xx_l4_cfg__dsp = {
+	.master		= &omap44xx_l4_cfg_hwmod,
+	.slave		= &omap44xx_dsp_hwmod,
+	.clk		= "l4_div_ck",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* dsp slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_dsp_slaves[] = {
+	&omap44xx_l4_cfg__dsp,
+};
+
+/* Pseudo hwmod for reset control purpose only */
+static struct omap_hwmod omap44xx_dsp_c0_hwmod = {
+	.name		= "dsp_c0",
+	.class		= &omap44xx_dsp_hwmod_class,
+	.flags		= HWMOD_INIT_NO_RESET,
+	.rst_lines	= omap44xx_dsp_c0_resets,
+	.rst_lines_cnt	= ARRAY_SIZE(omap44xx_dsp_c0_resets),
+	.prcm = {
+		.omap4 = {
+			.rstctrl_reg = OMAP4430_RM_TESLA_RSTCTRL,
+		},
+	},
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+static struct omap_hwmod omap44xx_dsp_hwmod = {
+	.name		= "dsp",
+	.class		= &omap44xx_dsp_hwmod_class,
+	.mpu_irqs	= omap44xx_dsp_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_dsp_irqs),
+	.rst_lines	= omap44xx_dsp_resets,
+	.rst_lines_cnt	= ARRAY_SIZE(omap44xx_dsp_resets),
+	.main_clk	= "dsp_fck",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM_TESLA_TESLA_CLKCTRL,
+			.rstctrl_reg = OMAP4430_RM_TESLA_RSTCTRL,
+		},
+	},
+	.slaves		= omap44xx_dsp_slaves,
+	.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),
+};
+
+/*
+ * 'gpio' class
+ * general purpose io module
+ */
+
+static struct omap_hwmod_class_sysconfig omap44xx_gpio_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.syss_offs	= 0x0114,
+	.sysc_flags	= (SYSC_HAS_AUTOIDLE | SYSC_HAS_ENAWAKEUP |
+			   SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET |
+			   SYSS_HAS_RESET_STATUS),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
+			   SIDLE_SMART_WKUP),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap44xx_gpio_hwmod_class = {
+	.name	= "gpio",
+	.sysc	= &omap44xx_gpio_sysc,
+	.rev	= 2,
+};
+
+/* gpio dev_attr */
+static struct omap_gpio_dev_attr gpio_dev_attr = {
+	.bank_width	= 32,
+	.dbck_flag	= true,
+};
+
+/* gpio1 */
+static struct omap_hwmod omap44xx_gpio1_hwmod;
+static struct omap_hwmod_irq_info omap44xx_gpio1_irqs[] = {
+	{ .irq = 29 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_gpio1_addrs[] = {
+	{
+		.pa_start	= 0x4a310000,
+		.pa_end		= 0x4a3101ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_wkup -> gpio1 */
+static struct omap_hwmod_ocp_if omap44xx_l4_wkup__gpio1 = {
+	.master		= &omap44xx_l4_wkup_hwmod,
+	.slave		= &omap44xx_gpio1_hwmod,
+	.clk		= "l4_wkup_clk_mux_ck",
+	.addr		= omap44xx_gpio1_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_gpio1_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* gpio1 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_gpio1_slaves[] = {
+	&omap44xx_l4_wkup__gpio1,
+};
+
+static struct omap_hwmod_opt_clk gpio1_opt_clks[] = {
+	{ .role = "dbclk", .clk = "gpio1_dbclk" },
+};
+
+static struct omap_hwmod omap44xx_gpio1_hwmod = {
+	.name		= "gpio1",
+	.class		= &omap44xx_gpio_hwmod_class,
+	.mpu_irqs	= omap44xx_gpio1_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_gpio1_irqs),
+	.main_clk	= "gpio1_ick",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM_WKUP_GPIO1_CLKCTRL,
+		},
+	},
+	.opt_clks	= gpio1_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(gpio1_opt_clks),
+	.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 */
+static struct omap_hwmod omap44xx_gpio2_hwmod;
+static struct omap_hwmod_irq_info omap44xx_gpio2_irqs[] = {
+	{ .irq = 30 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_gpio2_addrs[] = {
+	{
+		.pa_start	= 0x48055000,
+		.pa_end		= 0x480551ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_per -> gpio2 */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__gpio2 = {
+	.master		= &omap44xx_l4_per_hwmod,
+	.slave		= &omap44xx_gpio2_hwmod,
+	.clk		= "l4_div_ck",
+	.addr		= omap44xx_gpio2_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_gpio2_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* gpio2 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_gpio2_slaves[] = {
+	&omap44xx_l4_per__gpio2,
+};
+
+static struct omap_hwmod_opt_clk gpio2_opt_clks[] = {
+	{ .role = "dbclk", .clk = "gpio2_dbclk" },
+};
+
+static struct omap_hwmod omap44xx_gpio2_hwmod = {
+	.name		= "gpio2",
+	.class		= &omap44xx_gpio_hwmod_class,
+	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
+	.mpu_irqs	= omap44xx_gpio2_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_gpio2_irqs),
+	.main_clk	= "gpio2_ick",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM_L4PER_GPIO2_CLKCTRL,
+		},
+	},
+	.opt_clks	= gpio2_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(gpio2_opt_clks),
+	.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 */
+static struct omap_hwmod omap44xx_gpio3_hwmod;
+static struct omap_hwmod_irq_info omap44xx_gpio3_irqs[] = {
+	{ .irq = 31 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_gpio3_addrs[] = {
+	{
+		.pa_start	= 0x48057000,
+		.pa_end		= 0x480571ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_per -> gpio3 */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__gpio3 = {
+	.master		= &omap44xx_l4_per_hwmod,
+	.slave		= &omap44xx_gpio3_hwmod,
+	.clk		= "l4_div_ck",
+	.addr		= omap44xx_gpio3_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_gpio3_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* gpio3 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_gpio3_slaves[] = {
+	&omap44xx_l4_per__gpio3,
+};
+
+static struct omap_hwmod_opt_clk gpio3_opt_clks[] = {
+	{ .role = "dbclk", .clk = "gpio3_dbclk" },
+};
+
+static struct omap_hwmod omap44xx_gpio3_hwmod = {
+	.name		= "gpio3",
+	.class		= &omap44xx_gpio_hwmod_class,
+	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
+	.mpu_irqs	= omap44xx_gpio3_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_gpio3_irqs),
+	.main_clk	= "gpio3_ick",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM_L4PER_GPIO3_CLKCTRL,
+		},
+	},
+	.opt_clks	= gpio3_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(gpio3_opt_clks),
+	.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 */
+static struct omap_hwmod omap44xx_gpio4_hwmod;
+static struct omap_hwmod_irq_info omap44xx_gpio4_irqs[] = {
+	{ .irq = 32 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_gpio4_addrs[] = {
+	{
+		.pa_start	= 0x48059000,
+		.pa_end		= 0x480591ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_per -> gpio4 */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__gpio4 = {
+	.master		= &omap44xx_l4_per_hwmod,
+	.slave		= &omap44xx_gpio4_hwmod,
+	.clk		= "l4_div_ck",
+	.addr		= omap44xx_gpio4_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_gpio4_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* gpio4 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_gpio4_slaves[] = {
+	&omap44xx_l4_per__gpio4,
+};
+
+static struct omap_hwmod_opt_clk gpio4_opt_clks[] = {
+	{ .role = "dbclk", .clk = "gpio4_dbclk" },
+};
+
+static struct omap_hwmod omap44xx_gpio4_hwmod = {
+	.name		= "gpio4",
+	.class		= &omap44xx_gpio_hwmod_class,
+	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
+	.mpu_irqs	= omap44xx_gpio4_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_gpio4_irqs),
+	.main_clk	= "gpio4_ick",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM_L4PER_GPIO4_CLKCTRL,
+		},
+	},
+	.opt_clks	= gpio4_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(gpio4_opt_clks),
+	.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 */
+static struct omap_hwmod omap44xx_gpio5_hwmod;
+static struct omap_hwmod_irq_info omap44xx_gpio5_irqs[] = {
+	{ .irq = 33 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_gpio5_addrs[] = {
+	{
+		.pa_start	= 0x4805b000,
+		.pa_end		= 0x4805b1ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_per -> gpio5 */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__gpio5 = {
+	.master		= &omap44xx_l4_per_hwmod,
+	.slave		= &omap44xx_gpio5_hwmod,
+	.clk		= "l4_div_ck",
+	.addr		= omap44xx_gpio5_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_gpio5_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* gpio5 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_gpio5_slaves[] = {
+	&omap44xx_l4_per__gpio5,
+};
+
+static struct omap_hwmod_opt_clk gpio5_opt_clks[] = {
+	{ .role = "dbclk", .clk = "gpio5_dbclk" },
+};
+
+static struct omap_hwmod omap44xx_gpio5_hwmod = {
+	.name		= "gpio5",
+	.class		= &omap44xx_gpio_hwmod_class,
+	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
+	.mpu_irqs	= omap44xx_gpio5_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_gpio5_irqs),
+	.main_clk	= "gpio5_ick",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM_L4PER_GPIO5_CLKCTRL,
+		},
+	},
+	.opt_clks	= gpio5_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(gpio5_opt_clks),
+	.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 */
+static struct omap_hwmod omap44xx_gpio6_hwmod;
+static struct omap_hwmod_irq_info omap44xx_gpio6_irqs[] = {
+	{ .irq = 34 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_gpio6_addrs[] = {
+	{
+		.pa_start	= 0x4805d000,
+		.pa_end		= 0x4805d1ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_per -> gpio6 */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__gpio6 = {
+	.master		= &omap44xx_l4_per_hwmod,
+	.slave		= &omap44xx_gpio6_hwmod,
+	.clk		= "l4_div_ck",
+	.addr		= omap44xx_gpio6_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_gpio6_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* gpio6 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_gpio6_slaves[] = {
+	&omap44xx_l4_per__gpio6,
+};
+
+static struct omap_hwmod_opt_clk gpio6_opt_clks[] = {
+	{ .role = "dbclk", .clk = "gpio6_dbclk" },
+};
+
+static struct omap_hwmod omap44xx_gpio6_hwmod = {
+	.name		= "gpio6",
+	.class		= &omap44xx_gpio_hwmod_class,
+	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
+	.mpu_irqs	= omap44xx_gpio6_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_gpio6_irqs),
+	.main_clk	= "gpio6_ick",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM_L4PER_GPIO6_CLKCTRL,
+		},
+	},
+	.opt_clks	= gpio6_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(gpio6_opt_clks),
+	.dev_attr	= &gpio_dev_attr,
+	.slaves		= omap44xx_gpio6_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_gpio6_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/*
+ * 'i2c' class
+ * multimaster high-speed i2c controller
+ */
+
+static struct omap_hwmod_class_sysconfig omap44xx_i2c_sysc = {
+	.sysc_offs	= 0x0010,
+	.syss_offs	= 0x0090,
+	.sysc_flags	= (SYSC_HAS_AUTOIDLE | SYSC_HAS_CLOCKACTIVITY |
+			   SYSC_HAS_ENAWAKEUP | SYSC_HAS_SIDLEMODE |
+			   SYSC_HAS_SOFTRESET | SYSS_HAS_RESET_STATUS),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
+			   SIDLE_SMART_WKUP),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap44xx_i2c_hwmod_class = {
+	.name	= "i2c",
+	.sysc	= &omap44xx_i2c_sysc,
+};
+
+/* i2c1 */
+static struct omap_hwmod omap44xx_i2c1_hwmod;
+static struct omap_hwmod_irq_info omap44xx_i2c1_irqs[] = {
+	{ .irq = 56 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_dma_info omap44xx_i2c1_sdma_reqs[] = {
+	{ .name = "tx", .dma_req = 26 + OMAP44XX_DMA_REQ_START },
+	{ .name = "rx", .dma_req = 27 + OMAP44XX_DMA_REQ_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_i2c1_addrs[] = {
+	{
+		.pa_start	= 0x48070000,
+		.pa_end		= 0x480700ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_per -> i2c1 */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__i2c1 = {
+	.master		= &omap44xx_l4_per_hwmod,
+	.slave		= &omap44xx_i2c1_hwmod,
+	.clk		= "l4_div_ck",
+	.addr		= omap44xx_i2c1_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_i2c1_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* i2c1 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_i2c1_slaves[] = {
+	&omap44xx_l4_per__i2c1,
+};
+
+static struct omap_hwmod omap44xx_i2c1_hwmod = {
+	.name		= "i2c1",
+	.class		= &omap44xx_i2c_hwmod_class,
+	.flags		= HWMOD_INIT_NO_RESET,
+	.mpu_irqs	= omap44xx_i2c1_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_i2c1_irqs),
+	.sdma_reqs	= omap44xx_i2c1_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_i2c1_sdma_reqs),
+	.main_clk	= "i2c1_fck",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM_L4PER_I2C1_CLKCTRL,
+		},
+	},
+	.slaves		= omap44xx_i2c1_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_i2c1_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/* i2c2 */
+static struct omap_hwmod omap44xx_i2c2_hwmod;
+static struct omap_hwmod_irq_info omap44xx_i2c2_irqs[] = {
+	{ .irq = 57 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_dma_info omap44xx_i2c2_sdma_reqs[] = {
+	{ .name = "tx", .dma_req = 28 + OMAP44XX_DMA_REQ_START },
+	{ .name = "rx", .dma_req = 29 + OMAP44XX_DMA_REQ_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_i2c2_addrs[] = {
+	{
+		.pa_start	= 0x48072000,
+		.pa_end		= 0x480720ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_per -> i2c2 */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__i2c2 = {
+	.master		= &omap44xx_l4_per_hwmod,
+	.slave		= &omap44xx_i2c2_hwmod,
+	.clk		= "l4_div_ck",
+	.addr		= omap44xx_i2c2_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_i2c2_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* i2c2 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_i2c2_slaves[] = {
+	&omap44xx_l4_per__i2c2,
+};
+
+static struct omap_hwmod omap44xx_i2c2_hwmod = {
+	.name		= "i2c2",
+	.class		= &omap44xx_i2c_hwmod_class,
+	.flags		= HWMOD_INIT_NO_RESET,
+	.mpu_irqs	= omap44xx_i2c2_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_i2c2_irqs),
+	.sdma_reqs	= omap44xx_i2c2_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_i2c2_sdma_reqs),
+	.main_clk	= "i2c2_fck",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM_L4PER_I2C2_CLKCTRL,
+		},
+	},
+	.slaves		= omap44xx_i2c2_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_i2c2_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/* i2c3 */
+static struct omap_hwmod omap44xx_i2c3_hwmod;
+static struct omap_hwmod_irq_info omap44xx_i2c3_irqs[] = {
+	{ .irq = 61 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_dma_info omap44xx_i2c3_sdma_reqs[] = {
+	{ .name = "tx", .dma_req = 24 + OMAP44XX_DMA_REQ_START },
+	{ .name = "rx", .dma_req = 25 + OMAP44XX_DMA_REQ_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_i2c3_addrs[] = {
+	{
+		.pa_start	= 0x48060000,
+		.pa_end		= 0x480600ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_per -> i2c3 */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__i2c3 = {
+	.master		= &omap44xx_l4_per_hwmod,
+	.slave		= &omap44xx_i2c3_hwmod,
+	.clk		= "l4_div_ck",
+	.addr		= omap44xx_i2c3_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_i2c3_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* i2c3 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_i2c3_slaves[] = {
+	&omap44xx_l4_per__i2c3,
+};
+
+static struct omap_hwmod omap44xx_i2c3_hwmod = {
+	.name		= "i2c3",
+	.class		= &omap44xx_i2c_hwmod_class,
+	.flags		= HWMOD_INIT_NO_RESET,
+	.mpu_irqs	= omap44xx_i2c3_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_i2c3_irqs),
+	.sdma_reqs	= omap44xx_i2c3_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_i2c3_sdma_reqs),
+	.main_clk	= "i2c3_fck",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM_L4PER_I2C3_CLKCTRL,
+		},
+	},
+	.slaves		= omap44xx_i2c3_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_i2c3_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/* i2c4 */
+static struct omap_hwmod omap44xx_i2c4_hwmod;
+static struct omap_hwmod_irq_info omap44xx_i2c4_irqs[] = {
+	{ .irq = 62 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_dma_info omap44xx_i2c4_sdma_reqs[] = {
+	{ .name = "tx", .dma_req = 123 + OMAP44XX_DMA_REQ_START },
+	{ .name = "rx", .dma_req = 124 + OMAP44XX_DMA_REQ_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_i2c4_addrs[] = {
+	{
+		.pa_start	= 0x48350000,
+		.pa_end		= 0x483500ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_per -> i2c4 */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__i2c4 = {
+	.master		= &omap44xx_l4_per_hwmod,
+	.slave		= &omap44xx_i2c4_hwmod,
+	.clk		= "l4_div_ck",
+	.addr		= omap44xx_i2c4_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_i2c4_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* i2c4 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_i2c4_slaves[] = {
+	&omap44xx_l4_per__i2c4,
+};
+
+static struct omap_hwmod omap44xx_i2c4_hwmod = {
+	.name		= "i2c4",
+	.class		= &omap44xx_i2c_hwmod_class,
+	.flags		= HWMOD_INIT_NO_RESET,
+	.mpu_irqs	= omap44xx_i2c4_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_i2c4_irqs),
+	.sdma_reqs	= omap44xx_i2c4_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_i2c4_sdma_reqs),
+	.main_clk	= "i2c4_fck",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM_L4PER_I2C4_CLKCTRL,
+		},
+	},
+	.slaves		= omap44xx_i2c4_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_i2c4_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/*
+ * 'iva' class
+ * multi-standard video encoder/decoder hardware accelerator
+ */
+
+static struct omap_hwmod_class omap44xx_iva_hwmod_class = {
+	.name	= "iva",
+};
+
+/* iva */
+static struct omap_hwmod_irq_info omap44xx_iva_irqs[] = {
+	{ .name = "sync_1", .irq = 103 + OMAP44XX_IRQ_GIC_START },
+	{ .name = "sync_0", .irq = 104 + OMAP44XX_IRQ_GIC_START },
+	{ .name = "mailbox_0", .irq = 107 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_rst_info omap44xx_iva_resets[] = {
+	{ .name = "logic", .rst_shift = 2 },
+};
+
+static struct omap_hwmod_rst_info omap44xx_iva_seq0_resets[] = {
+	{ .name = "seq0", .rst_shift = 0 },
+};
+
+static struct omap_hwmod_rst_info omap44xx_iva_seq1_resets[] = {
+	{ .name = "seq1", .rst_shift = 1 },
+};
+
+/* iva master ports */
+static struct omap_hwmod_ocp_if *omap44xx_iva_masters[] = {
+	&omap44xx_iva__l3_main_2,
+	&omap44xx_iva__l3_instr,
+};
+
+static struct omap_hwmod_addr_space omap44xx_iva_addrs[] = {
+	{
+		.pa_start	= 0x5a000000,
+		.pa_end		= 0x5a07ffff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l3_main_2 -> iva */
+static struct omap_hwmod_ocp_if omap44xx_l3_main_2__iva = {
+	.master		= &omap44xx_l3_main_2_hwmod,
+	.slave		= &omap44xx_iva_hwmod,
+	.clk		= "l3_div_ck",
+	.addr		= omap44xx_iva_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_iva_addrs),
+	.user		= OCP_USER_MPU,
+};
+
+/* iva slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_iva_slaves[] = {
+	&omap44xx_dsp__iva,
+	&omap44xx_l3_main_2__iva,
+};
+
+/* Pseudo hwmod for reset control purpose only */
+static struct omap_hwmod omap44xx_iva_seq0_hwmod = {
+	.name		= "iva_seq0",
+	.class		= &omap44xx_iva_hwmod_class,
+	.flags		= HWMOD_INIT_NO_RESET,
+	.rst_lines	= omap44xx_iva_seq0_resets,
+	.rst_lines_cnt	= ARRAY_SIZE(omap44xx_iva_seq0_resets),
+	.prcm = {
+		.omap4 = {
+			.rstctrl_reg = OMAP4430_RM_IVAHD_RSTCTRL,
+		},
+	},
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/* Pseudo hwmod for reset control purpose only */
+static struct omap_hwmod omap44xx_iva_seq1_hwmod = {
+	.name		= "iva_seq1",
+	.class		= &omap44xx_iva_hwmod_class,
+	.flags		= HWMOD_INIT_NO_RESET,
+	.rst_lines	= omap44xx_iva_seq1_resets,
+	.rst_lines_cnt	= ARRAY_SIZE(omap44xx_iva_seq1_resets),
+	.prcm = {
+		.omap4 = {
+			.rstctrl_reg = OMAP4430_RM_IVAHD_RSTCTRL,
+		},
+	},
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+static struct omap_hwmod omap44xx_iva_hwmod = {
+	.name		= "iva",
+	.class		= &omap44xx_iva_hwmod_class,
+	.mpu_irqs	= omap44xx_iva_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_iva_irqs),
+	.rst_lines	= omap44xx_iva_resets,
+	.rst_lines_cnt	= ARRAY_SIZE(omap44xx_iva_resets),
+	.main_clk	= "iva_fck",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM_IVAHD_IVAHD_CLKCTRL,
+			.rstctrl_reg = OMAP4430_RM_IVAHD_RSTCTRL,
+		},
+	},
+	.slaves		= omap44xx_iva_slaves,
+	.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),
+};
+
+/*
  * 'mpu' class
  * mpu sub-system
  */
 
 static struct omap_hwmod_class omap44xx_mpu_hwmod_class = {
-	.name = "mpu",
+	.name	= "mpu",
 };
 
 /* mpu */
@@ -453,58 +1475,189 @@ static struct omap_hwmod omap44xx_mpu_hw
 };
 
 /*
- * 'wd_timer' class
- * 32-bit watchdog upward counter that generates a pulse on the reset pin on
- * overflow condition
+ * 'smartreflex' class
+ * smartreflex module (monitor silicon performance and outputs a measure of
+ * performance error)
  */
 
-static struct omap_hwmod_class_sysconfig omap44xx_wd_timer_sysc = {
-	.rev_offs	= 0x0000,
-	.sysc_offs	= 0x0010,
-	.syss_offs	= 0x0014,
-	.sysc_flags	= (SYSC_HAS_SIDLEMODE | SYSC_HAS_EMUFREE |
-			   SYSC_HAS_SOFTRESET),
-	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
-	.sysc_fields	= &omap_hwmod_sysc_type1,
+/* The IP is not compliant to type1 / type2 scheme */
+static struct omap_hwmod_sysc_fields omap_hwmod_sysc_type_smartreflex = {
+	.sidle_shift	= 24,
+	.enwkup_shift	= 26,
 };
 
-/*
- * 'uart' class
- * universal asynchronous receiver/transmitter (uart)
- */
+static struct omap_hwmod_class_sysconfig omap44xx_smartreflex_sysc = {
+	.sysc_offs	= 0x0038,
+	.sysc_flags	= (SYSC_HAS_ENAWAKEUP | SYSC_HAS_SIDLEMODE),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
+			   SIDLE_SMART_WKUP),
+	.sysc_fields	= &omap_hwmod_sysc_type_smartreflex,
+};
 
-static struct omap_hwmod_class_sysconfig omap44xx_uart_sysc = {
-	.rev_offs	= 0x0050,
-	.sysc_offs	= 0x0054,
-	.syss_offs	= 0x0058,
-	.sysc_flags	= (SYSC_HAS_ENAWAKEUP | SYSC_HAS_SIDLEMODE |
-			   SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE),
-	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
-	.sysc_fields	= &omap_hwmod_sysc_type1,
+static struct omap_hwmod_class omap44xx_smartreflex_hwmod_class = {
+	.name	= "smartreflex",
+	.sysc	= &omap44xx_smartreflex_sysc,
+	.rev	= 2,
 };
 
-static struct omap_hwmod_class omap44xx_wd_timer_hwmod_class = {
-	.name = "wd_timer",
-	.sysc = &omap44xx_wd_timer_sysc,
+/* smartreflex_core */
+static struct omap_hwmod omap44xx_smartreflex_core_hwmod;
+static struct omap_hwmod_irq_info omap44xx_smartreflex_core_irqs[] = {
+	{ .irq = 19 + OMAP44XX_IRQ_GIC_START },
 };
 
-/* wd_timer2 */
-static struct omap_hwmod omap44xx_wd_timer2_hwmod;
-static struct omap_hwmod_irq_info omap44xx_wd_timer2_irqs[] = {
-	{ .irq = 80 + OMAP44XX_IRQ_GIC_START },
+static struct omap_hwmod_addr_space omap44xx_smartreflex_core_addrs[] = {
+	{
+		.pa_start	= 0x4a0dd000,
+		.pa_end		= 0x4a0dd03f,
+		.flags		= ADDR_TYPE_RT
+	},
 };
 
-static struct omap_hwmod_addr_space omap44xx_wd_timer2_addrs[] = {
+/* l4_cfg -> smartreflex_core */
+static struct omap_hwmod_ocp_if omap44xx_l4_cfg__smartreflex_core = {
+	.master		= &omap44xx_l4_cfg_hwmod,
+	.slave		= &omap44xx_smartreflex_core_hwmod,
+	.clk		= "l4_div_ck",
+	.addr		= omap44xx_smartreflex_core_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_smartreflex_core_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* smartreflex_core slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_smartreflex_core_slaves[] = {
+	&omap44xx_l4_cfg__smartreflex_core,
+};
+
+static struct omap_hwmod omap44xx_smartreflex_core_hwmod = {
+	.name		= "smartreflex_core",
+	.class		= &omap44xx_smartreflex_hwmod_class,
+	.mpu_irqs	= omap44xx_smartreflex_core_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_smartreflex_core_irqs),
+	.main_clk	= "smartreflex_core_fck",
+	.vdd_name	= "core",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM_ALWON_SR_CORE_CLKCTRL,
+		},
+	},
+	.slaves		= omap44xx_smartreflex_core_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_smartreflex_core_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/* smartreflex_iva */
+static struct omap_hwmod omap44xx_smartreflex_iva_hwmod;
+static struct omap_hwmod_irq_info omap44xx_smartreflex_iva_irqs[] = {
+	{ .irq = 102 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_smartreflex_iva_addrs[] = {
 	{
-		.pa_start	= 0x4a314000,
-		.pa_end		= 0x4a31407f,
+		.pa_start	= 0x4a0db000,
+		.pa_end		= 0x4a0db03f,
 		.flags		= ADDR_TYPE_RT
 	},
 };
 
+/* l4_cfg -> smartreflex_iva */
+static struct omap_hwmod_ocp_if omap44xx_l4_cfg__smartreflex_iva = {
+	.master		= &omap44xx_l4_cfg_hwmod,
+	.slave		= &omap44xx_smartreflex_iva_hwmod,
+	.clk		= "l4_div_ck",
+	.addr		= omap44xx_smartreflex_iva_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_smartreflex_iva_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* smartreflex_iva slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_smartreflex_iva_slaves[] = {
+	&omap44xx_l4_cfg__smartreflex_iva,
+};
+
+static struct omap_hwmod omap44xx_smartreflex_iva_hwmod = {
+	.name		= "smartreflex_iva",
+	.class		= &omap44xx_smartreflex_hwmod_class,
+	.mpu_irqs	= omap44xx_smartreflex_iva_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_smartreflex_iva_irqs),
+	.main_clk	= "smartreflex_iva_fck",
+	.vdd_name	= "iva",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM_ALWON_SR_IVA_CLKCTRL,
+		},
+	},
+	.slaves		= omap44xx_smartreflex_iva_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_smartreflex_iva_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/* smartreflex_mpu */
+static struct omap_hwmod omap44xx_smartreflex_mpu_hwmod;
+static struct omap_hwmod_irq_info omap44xx_smartreflex_mpu_irqs[] = {
+	{ .irq = 18 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_smartreflex_mpu_addrs[] = {
+	{
+		.pa_start	= 0x4a0d9000,
+		.pa_end		= 0x4a0d903f,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_cfg -> smartreflex_mpu */
+static struct omap_hwmod_ocp_if omap44xx_l4_cfg__smartreflex_mpu = {
+	.master		= &omap44xx_l4_cfg_hwmod,
+	.slave		= &omap44xx_smartreflex_mpu_hwmod,
+	.clk		= "l4_div_ck",
+	.addr		= omap44xx_smartreflex_mpu_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_smartreflex_mpu_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* smartreflex_mpu slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_smartreflex_mpu_slaves[] = {
+	&omap44xx_l4_cfg__smartreflex_mpu,
+};
+
+static struct omap_hwmod omap44xx_smartreflex_mpu_hwmod = {
+	.name		= "smartreflex_mpu",
+	.class		= &omap44xx_smartreflex_hwmod_class,
+	.mpu_irqs	= omap44xx_smartreflex_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_smartreflex_mpu_irqs),
+	.main_clk	= "smartreflex_mpu_fck",
+	.vdd_name	= "mpu",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM_ALWON_SR_MPU_CLKCTRL,
+		},
+	},
+	.slaves		= omap44xx_smartreflex_mpu_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_smartreflex_mpu_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/*
+ * 'uart' class
+ * universal asynchronous receiver/transmitter (uart)
+ */
+
+static struct omap_hwmod_class_sysconfig omap44xx_uart_sysc = {
+	.rev_offs	= 0x0050,
+	.sysc_offs	= 0x0054,
+	.syss_offs	= 0x0058,
+	.sysc_flags	= (SYSC_HAS_AUTOIDLE | SYSC_HAS_ENAWAKEUP |
+			   SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET |
+			   SYSS_HAS_RESET_STATUS),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
+			   SIDLE_SMART_WKUP),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
 static struct omap_hwmod_class omap44xx_uart_hwmod_class = {
-	.name = "uart",
-	.sysc = &omap44xx_uart_sysc,
+	.name	= "uart",
+	.sysc	= &omap44xx_uart_sysc,
 };
 
 /* uart1 */
@@ -578,51 +1731,6 @@ static struct omap_hwmod_addr_space omap
 	},
 };
 
-/* l4_wkup -> wd_timer2 */
-static struct omap_hwmod_ocp_if omap44xx_l4_wkup__wd_timer2 = {
-	.master		= &omap44xx_l4_wkup_hwmod,
-	.slave		= &omap44xx_wd_timer2_hwmod,
-	.clk		= "l4_wkup_clk_mux_ck",
-	.addr		= omap44xx_wd_timer2_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap44xx_wd_timer2_addrs),
-	.user		= OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* wd_timer2 slave ports */
-static struct omap_hwmod_ocp_if *omap44xx_wd_timer2_slaves[] = {
-	&omap44xx_l4_wkup__wd_timer2,
-};
-
-static struct omap_hwmod omap44xx_wd_timer2_hwmod = {
-	.name		= "wd_timer2",
-	.class		= &omap44xx_wd_timer_hwmod_class,
-	.mpu_irqs	= omap44xx_wd_timer2_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_wd_timer2_irqs),
-	.main_clk	= "wd_timer2_fck",
-	.prcm = {
-		.omap4 = {
-			.clkctrl_reg = OMAP4430_CM_WKUP_WDT2_CLKCTRL,
-		},
-	},
-	.slaves		= omap44xx_wd_timer2_slaves,
-	.slaves_cnt	= ARRAY_SIZE(omap44xx_wd_timer2_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
-};
-
-/* wd_timer3 */
-static struct omap_hwmod omap44xx_wd_timer3_hwmod;
-static struct omap_hwmod_irq_info omap44xx_wd_timer3_irqs[] = {
-	{ .irq = 36 + OMAP44XX_IRQ_GIC_START },
-};
-
-static struct omap_hwmod_addr_space omap44xx_wd_timer3_addrs[] = {
-	{
-		.pa_start	= 0x40130000,
-		.pa_end		= 0x4013007f,
-		.flags		= ADDR_TYPE_RT
-	},
-};
-
 /* l4_per -> uart2 */
 static struct omap_hwmod_ocp_if omap44xx_l4_per__uart2 = {
 	.master		= &omap44xx_l4_per_hwmod,
@@ -675,25 +1783,6 @@ static struct omap_hwmod_addr_space omap
 	},
 };
 
-/* l4_abe -> wd_timer3 */
-static struct omap_hwmod_ocp_if omap44xx_l4_abe__wd_timer3 = {
-	.master		= &omap44xx_l4_abe_hwmod,
-	.slave		= &omap44xx_wd_timer3_hwmod,
-	.clk		= "ocp_abe_iclk",
-	.addr		= omap44xx_wd_timer3_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap44xx_wd_timer3_addrs),
-	.user		= OCP_USER_MPU,
-};
-
-/* l4_abe -> wd_timer3 (dma) */
-static struct omap_hwmod_addr_space omap44xx_wd_timer3_dma_addrs[] = {
-	{
-		.pa_start	= 0x49030000,
-		.pa_end		= 0x4903007f,
-		.flags		= ADDR_TYPE_RT
-	},
-};
-
 /* l4_per -> uart3 */
 static struct omap_hwmod_ocp_if omap44xx_l4_per__uart3 = {
 	.master		= &omap44xx_l4_per_hwmod,
@@ -747,37 +1836,6 @@ static struct omap_hwmod_addr_space omap
 	},
 };
 
-static struct omap_hwmod_ocp_if omap44xx_l4_abe__wd_timer3_dma = {
-	.master		= &omap44xx_l4_abe_hwmod,
-	.slave		= &omap44xx_wd_timer3_hwmod,
-	.clk		= "ocp_abe_iclk",
-	.addr		= omap44xx_wd_timer3_dma_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap44xx_wd_timer3_dma_addrs),
-	.user		= OCP_USER_SDMA,
-};
-
-/* wd_timer3 slave ports */
-static struct omap_hwmod_ocp_if *omap44xx_wd_timer3_slaves[] = {
-	&omap44xx_l4_abe__wd_timer3,
-	&omap44xx_l4_abe__wd_timer3_dma,
-};
-
-static struct omap_hwmod omap44xx_wd_timer3_hwmod = {
-	.name		= "wd_timer3",
-	.class		= &omap44xx_wd_timer_hwmod_class,
-	.mpu_irqs	= omap44xx_wd_timer3_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_wd_timer3_irqs),
-	.main_clk	= "wd_timer3_fck",
-	.prcm = {
-		.omap4 = {
-			.clkctrl_reg = OMAP4430_CM1_ABE_WDT3_CLKCTRL,
-		},
-	},
-	.slaves		= omap44xx_wd_timer3_slaves,
-	.slaves_cnt	= ARRAY_SIZE(omap44xx_wd_timer3_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
-};
-
 /* l4_per -> uart4 */
 static struct omap_hwmod_ocp_if omap44xx_l4_per__uart4 = {
 	.master		= &omap44xx_l4_per_hwmod,
@@ -811,35 +1869,205 @@ static struct omap_hwmod omap44xx_uart4_
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
+/*
+ * 'wd_timer' class
+ * 32-bit watchdog upward counter that generates a pulse on the reset pin on
+ * overflow condition
+ */
+
+static struct omap_hwmod_class_sysconfig omap44xx_wd_timer_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.syss_offs	= 0x0014,
+	.sysc_flags	= (SYSC_HAS_EMUFREE | SYSC_HAS_SIDLEMODE |
+			   SYSC_HAS_SOFTRESET | SYSS_HAS_RESET_STATUS),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
+			   SIDLE_SMART_WKUP),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap44xx_wd_timer_hwmod_class = {
+	.name		= "wd_timer",
+	.sysc		= &omap44xx_wd_timer_sysc,
+	.pre_shutdown	= &omap2_wd_timer_disable,
+};
+
+/* wd_timer2 */
+static struct omap_hwmod omap44xx_wd_timer2_hwmod;
+static struct omap_hwmod_irq_info omap44xx_wd_timer2_irqs[] = {
+	{ .irq = 80 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_wd_timer2_addrs[] = {
+	{
+		.pa_start	= 0x4a314000,
+		.pa_end		= 0x4a31407f,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_wkup -> wd_timer2 */
+static struct omap_hwmod_ocp_if omap44xx_l4_wkup__wd_timer2 = {
+	.master		= &omap44xx_l4_wkup_hwmod,
+	.slave		= &omap44xx_wd_timer2_hwmod,
+	.clk		= "l4_wkup_clk_mux_ck",
+	.addr		= omap44xx_wd_timer2_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_wd_timer2_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* wd_timer2 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_wd_timer2_slaves[] = {
+	&omap44xx_l4_wkup__wd_timer2,
+};
+
+static struct omap_hwmod omap44xx_wd_timer2_hwmod = {
+	.name		= "wd_timer2",
+	.class		= &omap44xx_wd_timer_hwmod_class,
+	.mpu_irqs	= omap44xx_wd_timer2_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_wd_timer2_irqs),
+	.main_clk	= "wd_timer2_fck",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM_WKUP_WDT2_CLKCTRL,
+		},
+	},
+	.slaves		= omap44xx_wd_timer2_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_wd_timer2_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/* wd_timer3 */
+static struct omap_hwmod omap44xx_wd_timer3_hwmod;
+static struct omap_hwmod_irq_info omap44xx_wd_timer3_irqs[] = {
+	{ .irq = 36 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_wd_timer3_addrs[] = {
+	{
+		.pa_start	= 0x40130000,
+		.pa_end		= 0x4013007f,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_abe -> wd_timer3 */
+static struct omap_hwmod_ocp_if omap44xx_l4_abe__wd_timer3 = {
+	.master		= &omap44xx_l4_abe_hwmod,
+	.slave		= &omap44xx_wd_timer3_hwmod,
+	.clk		= "ocp_abe_iclk",
+	.addr		= omap44xx_wd_timer3_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_wd_timer3_addrs),
+	.user		= OCP_USER_MPU,
+};
+
+static struct omap_hwmod_addr_space omap44xx_wd_timer3_dma_addrs[] = {
+	{
+		.pa_start	= 0x49030000,
+		.pa_end		= 0x4903007f,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_abe -> wd_timer3 (dma) */
+static struct omap_hwmod_ocp_if omap44xx_l4_abe__wd_timer3_dma = {
+	.master		= &omap44xx_l4_abe_hwmod,
+	.slave		= &omap44xx_wd_timer3_hwmod,
+	.clk		= "ocp_abe_iclk",
+	.addr		= omap44xx_wd_timer3_dma_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_wd_timer3_dma_addrs),
+	.user		= OCP_USER_SDMA,
+};
+
+/* wd_timer3 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_wd_timer3_slaves[] = {
+	&omap44xx_l4_abe__wd_timer3,
+	&omap44xx_l4_abe__wd_timer3_dma,
+};
+
+static struct omap_hwmod omap44xx_wd_timer3_hwmod = {
+	.name		= "wd_timer3",
+	.class		= &omap44xx_wd_timer_hwmod_class,
+	.mpu_irqs	= omap44xx_wd_timer3_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_wd_timer3_irqs),
+	.main_clk	= "wd_timer3_fck",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM1_ABE_WDT3_CLKCTRL,
+		},
+	},
+	.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[] = {
+
 	/* dmm class */
 	&omap44xx_dmm_hwmod,
+
 	/* emif_fw class */
 	&omap44xx_emif_fw_hwmod,
+
 	/* l3 class */
 	&omap44xx_l3_instr_hwmod,
 	&omap44xx_l3_main_1_hwmod,
 	&omap44xx_l3_main_2_hwmod,
 	&omap44xx_l3_main_3_hwmod,
+
 	/* l4 class */
 	&omap44xx_l4_abe_hwmod,
 	&omap44xx_l4_cfg_hwmod,
 	&omap44xx_l4_per_hwmod,
 	&omap44xx_l4_wkup_hwmod,
+
 	/* mpu_bus class */
 	&omap44xx_mpu_private_hwmod,
 
+	/* dma class */
+	&omap44xx_dma_system_hwmod,
+
+	/* dsp class */
+	&omap44xx_dsp_hwmod,
+	&omap44xx_dsp_c0_hwmod,
+
+	/* gpio class */
+	&omap44xx_gpio1_hwmod,
+	&omap44xx_gpio2_hwmod,
+	&omap44xx_gpio3_hwmod,
+	&omap44xx_gpio4_hwmod,
+	&omap44xx_gpio5_hwmod,
+	&omap44xx_gpio6_hwmod,
+
+	/* i2c class */
+	&omap44xx_i2c1_hwmod,
+	&omap44xx_i2c2_hwmod,
+	&omap44xx_i2c3_hwmod,
+	&omap44xx_i2c4_hwmod,
+
+	/* iva class */
+	&omap44xx_iva_hwmod,
+	&omap44xx_iva_seq0_hwmod,
+	&omap44xx_iva_seq1_hwmod,
+
 	/* mpu class */
 	&omap44xx_mpu_hwmod,
-	/* wd_timer class */
-	&omap44xx_wd_timer2_hwmod,
-	&omap44xx_wd_timer3_hwmod,
+
+	/* smartreflex class */
+	&omap44xx_smartreflex_core_hwmod,
+	&omap44xx_smartreflex_iva_hwmod,
+	&omap44xx_smartreflex_mpu_hwmod,
 
 	/* uart class */
 	&omap44xx_uart1_hwmod,
 	&omap44xx_uart2_hwmod,
 	&omap44xx_uart3_hwmod,
 	&omap44xx_uart4_hwmod,
+
+	/* wd_timer class */
+	&omap44xx_wd_timer2_hwmod,
+	&omap44xx_wd_timer3_hwmod,
+
 	NULL,
 };
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/omap_hwmod.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/omap_hwmod.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/omap_hwmod.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/omap_hwmod.c	2011-03-14 21:20:32.000000000 -0400
@@ -116,7 +116,6 @@
  * - Open Core Protocol Specification 2.2
  *
  * To do:
- * - pin mux handling
  * - handle IO mapping
  * - bus throughput & module latency measurement code
  *
@@ -135,17 +134,21 @@
 #include <linux/err.h>
 #include <linux/list.h>
 #include <linux/mutex.h>
+#include <linux/spinlock.h>
 
 #include <plat/common.h>
 #include <plat/cpu.h>
-#include <plat/clockdomain.h>
-#include <plat/powerdomain.h>
+#include "clockdomain.h"
+#include "powerdomain.h"
 #include <plat/clock.h>
 #include <plat/omap_hwmod.h>
 #include <plat/prcm.h>
 
-#include "cm.h"
-#include "prm.h"
+#include "cm2xxx_3xxx.h"
+#include "cm44xx.h"
+#include "prm2xxx_3xxx.h"
+#include "prm44xx.h"
+#include "mux.h"
 
 /* Maximum microseconds to wait for OMAP module to softreset */
 #define MAX_MODULE_SOFTRESET_WAIT	10000
@@ -156,8 +159,6 @@
 /* omap_hwmod_list contains all registered struct omap_hwmods */
 static LIST_HEAD(omap_hwmod_list);
 
-static DEFINE_MUTEX(omap_hwmod_mutex);
-
 /* mpu_oh: used to add/remove MPU initiator from sleepdep list */
 static struct omap_hwmod *mpu_oh;
 
@@ -209,10 +210,9 @@ static void _write_sysconfig(u32 v, stru
 
 	/* XXX ensure module interface clock is up */
 
-	if (oh->_sysc_cache != v) {
-		oh->_sysc_cache = v;
-		omap_hwmod_write(v, oh, oh->class->sysc->sysc_offs);
-	}
+	/* Module might have lost context, always update cache and register */
+	oh->_sysc_cache = v;
+	omap_hwmod_write(v, oh, oh->class->sysc->sysc_offs);
 }
 
 /**
@@ -388,12 +388,13 @@ static int _set_module_autoidle(struct o
  * Allow the hardware module @oh to send wakeups.  Returns -EINVAL
  * upon error or 0 upon success.
  */
-static int _enable_wakeup(struct omap_hwmod *oh)
+static int _enable_wakeup(struct omap_hwmod *oh, u32 *v)
 {
-	u32 v, wakeup_mask;
+	u32 wakeup_mask;
 
 	if (!oh->class->sysc ||
-	    !(oh->class->sysc->sysc_flags & SYSC_HAS_ENAWAKEUP))
+	    !((oh->class->sysc->sysc_flags & SYSC_HAS_ENAWAKEUP) ||
+	      (oh->class->sysc->idlemodes & SIDLE_SMART_WKUP)))
 		return -EINVAL;
 
 	if (!oh->class->sysc->sysc_fields) {
@@ -403,9 +404,10 @@ static int _enable_wakeup(struct omap_hw
 
 	wakeup_mask = (0x1 << oh->class->sysc->sysc_fields->enwkup_shift);
 
-	v = oh->_sysc_cache;
-	v |= wakeup_mask;
-	_write_sysconfig(v, oh);
+	*v |= wakeup_mask;
+
+	if (oh->class->sysc->idlemodes & SIDLE_SMART_WKUP)
+		_set_slave_idlemode(oh, HWMOD_IDLEMODE_SMART_WKUP, v);
 
 	/* XXX test pwrdm_get_wken for this hwmod's subsystem */
 
@@ -421,12 +423,13 @@ static int _enable_wakeup(struct omap_hw
  * Prevent the hardware module @oh to send wakeups.  Returns -EINVAL
  * upon error or 0 upon success.
  */
-static int _disable_wakeup(struct omap_hwmod *oh)
+static int _disable_wakeup(struct omap_hwmod *oh, u32 *v)
 {
-	u32 v, wakeup_mask;
+	u32 wakeup_mask;
 
 	if (!oh->class->sysc ||
-	    !(oh->class->sysc->sysc_flags & SYSC_HAS_ENAWAKEUP))
+	    !((oh->class->sysc->sysc_flags & SYSC_HAS_ENAWAKEUP) ||
+	      (oh->class->sysc->idlemodes & SIDLE_SMART_WKUP)))
 		return -EINVAL;
 
 	if (!oh->class->sysc->sysc_fields) {
@@ -436,9 +439,10 @@ static int _disable_wakeup(struct omap_h
 
 	wakeup_mask = (0x1 << oh->class->sysc->sysc_fields->enwkup_shift);
 
-	v = oh->_sysc_cache;
-	v &= ~wakeup_mask;
-	_write_sysconfig(v, oh);
+	*v &= ~wakeup_mask;
+
+	if (oh->class->sysc->idlemodes & SIDLE_SMART_WKUP)
+		_set_slave_idlemode(oh, HWMOD_IDLEMODE_SMART, v);
 
 	/* XXX test pwrdm_get_wken for this hwmod's subsystem */
 
@@ -675,7 +679,7 @@ static void _disable_optional_clocks(str
  * Returns the array index of the OCP slave port that the MPU
  * addresses the device on, or -EINVAL upon error or not found.
  */
-static int _find_mpu_port_index(struct omap_hwmod *oh)
+static int __init _find_mpu_port_index(struct omap_hwmod *oh)
 {
 	int i;
 	int found = 0;
@@ -709,7 +713,7 @@ static int _find_mpu_port_index(struct o
  * Return the virtual address of the base of the register target of
  * device @oh, or NULL on error.
  */
-static void __iomem *_find_mpu_rt_base(struct omap_hwmod *oh, u8 index)
+static void __iomem * __init _find_mpu_rt_base(struct omap_hwmod *oh, u8 index)
 {
 	struct omap_hwmod_ocp_if *os;
 	struct omap_hwmod_addr_space *mem;
@@ -786,11 +790,11 @@ static void _enable_sysc(struct omap_hwm
 	    (sf & SYSC_HAS_CLOCKACTIVITY))
 		_set_clockactivity(oh, oh->class->sysc->clockact, &v);
 
-	_write_sysconfig(v, oh);
-
 	/* If slave is in SMARTIDLE, also enable wakeup */
 	if ((sf & SYSC_HAS_SIDLEMODE) && !(oh->flags & HWMOD_SWSUP_SIDLE))
-		_enable_wakeup(oh);
+		_enable_wakeup(oh, &v);
+
+	_write_sysconfig(v, oh);
 
 	/*
 	 * Set the autoidle bit only after setting the smartidle bit
@@ -836,6 +840,10 @@ static void _idle_sysc(struct omap_hwmod
 		_set_master_standbymode(oh, idlemode, &v);
 	}
 
+	/* If slave is in SMARTIDLE, also enable wakeup */
+	if ((sf & SYSC_HAS_SIDLEMODE) && !(oh->flags & HWMOD_SWSUP_SIDLE))
+		_enable_wakeup(oh, &v);
+
 	_write_sysconfig(v, oh);
 }
 
@@ -874,7 +882,6 @@ static void _shutdown_sysc(struct omap_h
  * @name: find an omap_hwmod by name
  *
  * Return a pointer to an omap_hwmod by name, or NULL if not found.
- * Caller must hold omap_hwmod_mutex.
  */
 static struct omap_hwmod *_lookup(const char *name)
 {
@@ -1089,7 +1096,7 @@ static int _read_hardreset(struct omap_h
 }
 
 /**
- * _reset - reset an omap_hwmod
+ * _ocp_softreset - reset an omap_hwmod via the OCP_SYSCONFIG bit
  * @oh: struct omap_hwmod *
  *
  * Resets an omap_hwmod @oh via the OCP_SYSCONFIG bit.  hwmod must be
@@ -1098,12 +1105,13 @@ static int _read_hardreset(struct omap_h
  * the module did not reset in time, or 0 upon success.
  *
  * In OMAP3 a specific SYSSTATUS register is used to get the reset status.
- * Starting in OMAP4, some IPs does not have SYSSTATUS register and instead
+ * Starting in OMAP4, some IPs do not have SYSSTATUS registers and instead
  * use the SYSCONFIG softreset bit to provide the status.
  *
- * Note that some IP like McBSP does have a reset control but no reset status.
+ * Note that some IP like McBSP do have reset control but don't have
+ * reset status.
  */
-static int _reset(struct omap_hwmod *oh)
+static int _ocp_softreset(struct omap_hwmod *oh)
 {
 	u32 v;
 	int c = 0;
@@ -1124,7 +1132,7 @@ static int _reset(struct omap_hwmod *oh)
 	if (oh->flags & HWMOD_CONTROL_OPT_CLKS_IN_RESET)
 		_enable_optional_clocks(oh);
 
-	pr_debug("omap_hwmod: %s: resetting\n", oh->name);
+	pr_debug("omap_hwmod: %s: resetting via OCP SOFTRESET\n", oh->name);
 
 	v = oh->_sysc_cache;
 	ret = _set_softreset(oh, &v);
@@ -1164,17 +1172,41 @@ dis_opt_clks:
 }
 
 /**
- * _omap_hwmod_enable - enable an omap_hwmod
+ * _reset - reset an omap_hwmod
+ * @oh: struct omap_hwmod *
+ *
+ * Resets an omap_hwmod @oh.  The default software reset mechanism for
+ * most OMAP IP blocks is triggered via the OCP_SYSCONFIG.SOFTRESET
+ * bit.  However, some hwmods cannot be reset via this method: some
+ * are not targets and therefore have no OCP header registers to
+ * access; others (like the IVA) have idiosyncratic reset sequences.
+ * So for these relatively rare cases, custom reset code can be
+ * supplied in the struct omap_hwmod_class .reset function pointer.
+ * Passes along the return value from either _reset() or the custom
+ * reset function - these must return -EINVAL if the hwmod cannot be
+ * reset this way or if the hwmod is in the wrong state, -ETIMEDOUT if
+ * the module did not reset in time, or 0 upon success.
+ */
+static int _reset(struct omap_hwmod *oh)
+{
+	int ret;
+
+	pr_debug("omap_hwmod: %s: resetting\n", oh->name);
+
+	ret = (oh->class->reset) ? oh->class->reset(oh) : _ocp_softreset(oh);
+
+	return ret;
+}
+
+/**
+ * _enable - enable an omap_hwmod
  * @oh: struct omap_hwmod *
  *
  * Enables an omap_hwmod @oh such that the MPU can access the hwmod's
- * register target.  (This function has a full name --
- * _omap_hwmod_enable() rather than simply _enable() -- because it is
- * currently required by the pm34xx.c idle loop.)  Returns -EINVAL if
- * the hwmod is in the wrong state or passes along the return value of
- * _wait_target_ready().
+ * register target.  Returns -EINVAL if the hwmod is in the wrong
+ * state or passes along the return value of _wait_target_ready().
  */
-int _omap_hwmod_enable(struct omap_hwmod *oh)
+static int _enable(struct omap_hwmod *oh)
 {
 	int r;
 
@@ -1197,7 +1229,9 @@ int _omap_hwmod_enable(struct omap_hwmod
 	     oh->_state == _HWMOD_STATE_DISABLED) && oh->rst_lines_cnt == 1)
 		_deassert_hardreset(oh, oh->rst_lines[0].name);
 
-	/* XXX mux balls */
+	/* Mux pins for device runtime if populated */
+	if (oh->mux)
+		omap_hwmod_mux(oh->mux, _HWMOD_STATE_ENABLED);
 
 	_add_initiator_dep(oh, mpu_oh);
 	_enable_clocks(oh);
@@ -1213,6 +1247,7 @@ int _omap_hwmod_enable(struct omap_hwmod
 			_enable_sysc(oh);
 		}
 	} else {
+		_disable_clocks(oh);
 		pr_debug("omap_hwmod: %s: _wait_target_ready: %d\n",
 			 oh->name, r);
 	}
@@ -1221,16 +1256,14 @@ int _omap_hwmod_enable(struct omap_hwmod
 }
 
 /**
- * _omap_hwmod_idle - idle an omap_hwmod
+ * _idle - idle an omap_hwmod
  * @oh: struct omap_hwmod *
  *
  * Idles an omap_hwmod @oh.  This should be called once the hwmod has
- * no further work.  (This function has a full name --
- * _omap_hwmod_idle() rather than simply _idle() -- because it is
- * currently required by the pm34xx.c idle loop.)  Returns -EINVAL if
- * the hwmod is in the wrong state or returns 0.
+ * no further work.  Returns -EINVAL if the hwmod is in the wrong
+ * state or returns 0.
  */
-int _omap_hwmod_idle(struct omap_hwmod *oh)
+static int _idle(struct omap_hwmod *oh)
 {
 	if (oh->_state != _HWMOD_STATE_ENABLED) {
 		WARN(1, "omap_hwmod: %s: idle state can only be entered from "
@@ -1245,6 +1278,10 @@ int _omap_hwmod_idle(struct omap_hwmod *
 	_del_initiator_dep(oh, mpu_oh);
 	_disable_clocks(oh);
 
+	/* Mux pins for device idle if populated */
+	if (oh->mux)
+		omap_hwmod_mux(oh->mux, _HWMOD_STATE_IDLE);
+
 	oh->_state = _HWMOD_STATE_IDLE;
 
 	return 0;
@@ -1261,6 +1298,9 @@ int _omap_hwmod_idle(struct omap_hwmod *
  */
 static int _shutdown(struct omap_hwmod *oh)
 {
+	int ret;
+	u8 prev_state;
+
 	if (oh->_state != _HWMOD_STATE_IDLE &&
 	    oh->_state != _HWMOD_STATE_ENABLED) {
 		WARN(1, "omap_hwmod: %s: disabled state can only be entered "
@@ -1270,6 +1310,18 @@ static int _shutdown(struct omap_hwmod *
 
 	pr_debug("omap_hwmod: %s: disabling\n", oh->name);
 
+	if (oh->class->pre_shutdown) {
+		prev_state = oh->_state;
+		if (oh->_state == _HWMOD_STATE_IDLE)
+			_enable(oh);
+		ret = oh->class->pre_shutdown(oh);
+		if (ret) {
+			if (prev_state == _HWMOD_STATE_IDLE)
+				_idle(oh);
+			return ret;
+		}
+	}
+
 	if (oh->class->sysc)
 		_shutdown_sysc(oh);
 
@@ -1288,7 +1340,9 @@ static int _shutdown(struct omap_hwmod *
 	}
 	/* XXX Should this code also force-disable the optional clocks? */
 
-	/* XXX mux any associated balls to safe mode */
+	/* Mux pins to safe mode or use populated off mode values */
+	if (oh->mux)
+		omap_hwmod_mux(oh->mux, _HWMOD_STATE_DISABLED);
 
 	oh->_state = _HWMOD_STATE_DISABLED;
 
@@ -1298,23 +1352,15 @@ static int _shutdown(struct omap_hwmod *
 /**
  * _setup - do initial configuration of omap_hwmod
  * @oh: struct omap_hwmod *
- * @skip_setup_idle_p: do not idle hwmods at the end of the fn if 1
  *
  * Writes the CLOCKACTIVITY bits @clockact to the hwmod @oh
- * OCP_SYSCONFIG register.  @skip_setup_idle is intended to be used on
- * a system that will not call omap_hwmod_enable() to enable devices
- * (e.g., a system without PM runtime).  Returns -EINVAL if the hwmod
- * is in the wrong state or returns 0.
+ * OCP_SYSCONFIG register.  Returns -EINVAL if the hwmod is in the
+ * wrong state or returns 0.
  */
 static int _setup(struct omap_hwmod *oh, void *data)
 {
 	int i, r;
-	u8 skip_setup_idle;
-
-	if (!oh || !data)
-		return -EINVAL;
-
-	skip_setup_idle = *(u8 *)data;
+	u8 postsetup_state;
 
 	/* Set iclk autoidle mode */
 	if (oh->slaves_cnt > 0) {
@@ -1334,7 +1380,6 @@ static int _setup(struct omap_hwmod *oh,
 		}
 	}
 
-	mutex_init(&oh->_mutex);
 	oh->_state = _HWMOD_STATE_INITIALIZED;
 
 	/*
@@ -1347,7 +1392,7 @@ static int _setup(struct omap_hwmod *oh,
 	if ((oh->flags & HWMOD_INIT_NO_RESET) && oh->rst_lines_cnt == 1)
 		return 0;
 
-	r = _omap_hwmod_enable(oh);
+	r = _enable(oh);
 	if (r) {
 		pr_warning("omap_hwmod: %s: cannot be enabled (%d)\n",
 			   oh->name, oh->_state);
@@ -1359,7 +1404,7 @@ static int _setup(struct omap_hwmod *oh,
 
 		/*
 		 * OCP_SYSCONFIG bits need to be reprogrammed after a softreset.
-		 * The _omap_hwmod_enable() function should be split to
+		 * The _enable() function should be split to
 		 * avoid the rewrite of the OCP_SYSCONFIG register.
 		 */
 		if (oh->class->sysc) {
@@ -1368,12 +1413,77 @@ static int _setup(struct omap_hwmod *oh,
 		}
 	}
 
-	if (!(oh->flags & HWMOD_INIT_NO_IDLE) && !skip_setup_idle)
-		_omap_hwmod_idle(oh);
+	postsetup_state = oh->_postsetup_state;
+	if (postsetup_state == _HWMOD_STATE_UNKNOWN)
+		postsetup_state = _HWMOD_STATE_ENABLED;
+
+	/*
+	 * XXX HWMOD_INIT_NO_IDLE does not belong in hwmod data -
+	 * it should be set by the core code as a runtime flag during startup
+	 */
+	if ((oh->flags & HWMOD_INIT_NO_IDLE) &&
+	    (postsetup_state == _HWMOD_STATE_IDLE))
+		postsetup_state = _HWMOD_STATE_ENABLED;
+
+	if (postsetup_state == _HWMOD_STATE_IDLE)
+		_idle(oh);
+	else if (postsetup_state == _HWMOD_STATE_DISABLED)
+		_shutdown(oh);
+	else if (postsetup_state != _HWMOD_STATE_ENABLED)
+		WARN(1, "hwmod: %s: unknown postsetup state %d! defaulting to enabled\n",
+		     oh->name, postsetup_state);
 
 	return 0;
 }
 
+/**
+ * _register - register a struct omap_hwmod
+ * @oh: struct omap_hwmod *
+ *
+ * Registers the omap_hwmod @oh.  Returns -EEXIST if an omap_hwmod
+ * already has been registered by the same name; -EINVAL if the
+ * omap_hwmod is in the wrong state, if @oh is NULL, if the
+ * omap_hwmod's class field is NULL; if the omap_hwmod is missing a
+ * name, or if the omap_hwmod's class is missing a name; or 0 upon
+ * success.
+ *
+ * XXX The data should be copied into bootmem, so the original data
+ * should be marked __initdata and freed after init.  This would allow
+ * unneeded omap_hwmods to be freed on multi-OMAP configurations.  Note
+ * that the copy process would be relatively complex due to the large number
+ * of substructures.
+ */
+static int __init _register(struct omap_hwmod *oh)
+{
+	int ret, ms_id;
+
+	if (!oh || !oh->name || !oh->class || !oh->class->name ||
+	    (oh->_state != _HWMOD_STATE_UNKNOWN))
+		return -EINVAL;
+
+	pr_debug("omap_hwmod: %s: registering\n", oh->name);
+
+	if (_lookup(oh->name))
+		return -EEXIST;
+
+	ms_id = _find_mpu_port_index(oh);
+	if (!IS_ERR_VALUE(ms_id)) {
+		oh->_mpu_port_index = ms_id;
+		oh->_mpu_rt_va = _find_mpu_rt_base(oh, oh->_mpu_port_index);
+	} else {
+		oh->_int_flags |= _HWMOD_NO_MPU_PORT;
+	}
+
+	list_add_tail(&oh->node, &omap_hwmod_list);
+
+	spin_lock_init(&oh->_lock);
+
+	oh->_state = _HWMOD_STATE_REGISTERED;
+
+	ret = 0;
+
+	return ret;
+}
 
 
 /* Public functions */
@@ -1427,59 +1537,6 @@ int omap_hwmod_set_slave_idlemode(struct
 }
 
 /**
- * omap_hwmod_register - register a struct omap_hwmod
- * @oh: struct omap_hwmod *
- *
- * Registers the omap_hwmod @oh.  Returns -EEXIST if an omap_hwmod
- * already has been registered by the same name; -EINVAL if the
- * omap_hwmod is in the wrong state, if @oh is NULL, if the
- * omap_hwmod's class field is NULL; if the omap_hwmod is missing a
- * name, or if the omap_hwmod's class is missing a name; or 0 upon
- * success.
- *
- * XXX The data should be copied into bootmem, so the original data
- * should be marked __initdata and freed after init.  This would allow
- * unneeded omap_hwmods to be freed on multi-OMAP configurations.  Note
- * that the copy process would be relatively complex due to the large number
- * of substructures.
- */
-int omap_hwmod_register(struct omap_hwmod *oh)
-{
-	int ret, ms_id;
-
-	if (!oh || !oh->name || !oh->class || !oh->class->name ||
-	    (oh->_state != _HWMOD_STATE_UNKNOWN))
-		return -EINVAL;
-
-	mutex_lock(&omap_hwmod_mutex);
-
-	pr_debug("omap_hwmod: %s: registering\n", oh->name);
-
-	if (_lookup(oh->name)) {
-		ret = -EEXIST;
-		goto ohr_unlock;
-	}
-
-	ms_id = _find_mpu_port_index(oh);
-	if (!IS_ERR_VALUE(ms_id)) {
-		oh->_mpu_port_index = ms_id;
-		oh->_mpu_rt_va = _find_mpu_rt_base(oh, oh->_mpu_port_index);
-	} else {
-		oh->_int_flags |= _HWMOD_NO_MPU_PORT;
-	}
-
-	list_add_tail(&oh->node, &omap_hwmod_list);
-
-	oh->_state = _HWMOD_STATE_REGISTERED;
-
-	ret = 0;
-
-ohr_unlock:
-	mutex_unlock(&omap_hwmod_mutex);
-	return ret;
-}
-
-/**
  * omap_hwmod_lookup - look up a registered omap_hwmod by name
  * @name: name of the omap_hwmod to look up
  *
@@ -1493,9 +1550,7 @@ struct omap_hwmod *omap_hwmod_lookup(con
 	if (!name)
 		return NULL;
 
-	mutex_lock(&omap_hwmod_mutex);
 	oh = _lookup(name);
-	mutex_unlock(&omap_hwmod_mutex);
 
 	return oh;
 }
@@ -1521,13 +1576,11 @@ int omap_hwmod_for_each(int (*fn)(struct
 	if (!fn)
 		return -EINVAL;
 
-	mutex_lock(&omap_hwmod_mutex);
 	list_for_each_entry(temp_oh, &omap_hwmod_list, node) {
 		ret = (*fn)(temp_oh, data);
 		if (ret)
 			break;
 	}
-	mutex_unlock(&omap_hwmod_mutex);
 
 	return ret;
 }
@@ -1542,7 +1595,7 @@ int omap_hwmod_for_each(int (*fn)(struct
  * listed in @ohs that are valid for this chip.  Returns -EINVAL if
  * omap_hwmod_init() has already been called or 0 otherwise.
  */
-int omap_hwmod_init(struct omap_hwmod **ohs)
+int __init omap_hwmod_init(struct omap_hwmod **ohs)
 {
 	struct omap_hwmod *oh;
 	int r;
@@ -1558,8 +1611,8 @@ int omap_hwmod_init(struct omap_hwmod **
 	oh = *ohs;
 	while (oh) {
 		if (omap_chip_is(oh->omap_chip)) {
-			r = omap_hwmod_register(oh);
-			WARN(r, "omap_hwmod: %s: omap_hwmod_register returned "
+			r = _register(oh);
+			WARN(r, "omap_hwmod: %s: _register returned "
 			     "%d\n", oh->name, r);
 		}
 		oh = *++ohs;
@@ -1570,13 +1623,12 @@ int omap_hwmod_init(struct omap_hwmod **
 
 /**
  * omap_hwmod_late_init - do some post-clock framework initialization
- * @skip_setup_idle: if 1, do not idle hwmods in _setup()
  *
  * Must be called after omap2_clk_init().  Resolves the struct clk names
  * to struct clk pointers for each registered omap_hwmod.  Also calls
  * _setup() on each hwmod.  Returns 0.
  */
-int omap_hwmod_late_init(u8 skip_setup_idle)
+int omap_hwmod_late_init(void)
 {
 	int r;
 
@@ -1588,36 +1640,7 @@ int omap_hwmod_late_init(u8 skip_setup_i
 	WARN(!mpu_oh, "omap_hwmod: could not find MPU initiator hwmod %s\n",
 	     MPU_INITIATOR_NAME);
 
-	if (skip_setup_idle)
-		pr_debug("omap_hwmod: will leave hwmods enabled during setup\n");
-
-	omap_hwmod_for_each(_setup, &skip_setup_idle);
-
-	return 0;
-}
-
-/**
- * omap_hwmod_unregister - unregister an omap_hwmod
- * @oh: struct omap_hwmod *
- *
- * Unregisters a previously-registered omap_hwmod @oh.  There's probably
- * no use case for this, so it is likely to be removed in a later version.
- *
- * XXX Free all of the bootmem-allocated structures here when that is
- * implemented.  Make it clear that core code is the only code that is
- * expected to unregister modules.
- */
-int omap_hwmod_unregister(struct omap_hwmod *oh)
-{
-	if (!oh)
-		return -EINVAL;
-
-	pr_debug("omap_hwmod: %s: unregistering\n", oh->name);
-
-	mutex_lock(&omap_hwmod_mutex);
-	iounmap(oh->_mpu_rt_va);
-	list_del(&oh->node);
-	mutex_unlock(&omap_hwmod_mutex);
+	omap_hwmod_for_each(_setup, NULL);
 
 	return 0;
 }
@@ -1632,18 +1655,18 @@ int omap_hwmod_unregister(struct omap_hw
 int omap_hwmod_enable(struct omap_hwmod *oh)
 {
 	int r;
+	unsigned long flags;
 
 	if (!oh)
 		return -EINVAL;
 
-	mutex_lock(&oh->_mutex);
-	r = _omap_hwmod_enable(oh);
-	mutex_unlock(&oh->_mutex);
+	spin_lock_irqsave(&oh->_lock, flags);
+	r = _enable(oh);
+	spin_unlock_irqrestore(&oh->_lock, flags);
 
 	return r;
 }
 
-
 /**
  * omap_hwmod_idle - idle an omap_hwmod
  * @oh: struct omap_hwmod *
@@ -1653,12 +1676,14 @@ int omap_hwmod_enable(struct omap_hwmod
  */
 int omap_hwmod_idle(struct omap_hwmod *oh)
 {
+	unsigned long flags;
+
 	if (!oh)
 		return -EINVAL;
 
-	mutex_lock(&oh->_mutex);
-	_omap_hwmod_idle(oh);
-	mutex_unlock(&oh->_mutex);
+	spin_lock_irqsave(&oh->_lock, flags);
+	_idle(oh);
+	spin_unlock_irqrestore(&oh->_lock, flags);
 
 	return 0;
 }
@@ -1673,12 +1698,14 @@ int omap_hwmod_idle(struct omap_hwmod *o
  */
 int omap_hwmod_shutdown(struct omap_hwmod *oh)
 {
+	unsigned long flags;
+
 	if (!oh)
 		return -EINVAL;
 
-	mutex_lock(&oh->_mutex);
+	spin_lock_irqsave(&oh->_lock, flags);
 	_shutdown(oh);
-	mutex_unlock(&oh->_mutex);
+	spin_unlock_irqrestore(&oh->_lock, flags);
 
 	return 0;
 }
@@ -1691,9 +1718,11 @@ int omap_hwmod_shutdown(struct omap_hwmo
  */
 int omap_hwmod_enable_clocks(struct omap_hwmod *oh)
 {
-	mutex_lock(&oh->_mutex);
+	unsigned long flags;
+
+	spin_lock_irqsave(&oh->_lock, flags);
 	_enable_clocks(oh);
-	mutex_unlock(&oh->_mutex);
+	spin_unlock_irqrestore(&oh->_lock, flags);
 
 	return 0;
 }
@@ -1706,9 +1735,11 @@ int omap_hwmod_enable_clocks(struct omap
  */
 int omap_hwmod_disable_clocks(struct omap_hwmod *oh)
 {
-	mutex_lock(&oh->_mutex);
+	unsigned long flags;
+
+	spin_lock_irqsave(&oh->_lock, flags);
 	_disable_clocks(oh);
-	mutex_unlock(&oh->_mutex);
+	spin_unlock_irqrestore(&oh->_lock, flags);
 
 	return 0;
 }
@@ -1752,13 +1783,14 @@ void omap_hwmod_ocp_barrier(struct omap_
 int omap_hwmod_reset(struct omap_hwmod *oh)
 {
 	int r;
+	unsigned long flags;
 
 	if (!oh)
 		return -EINVAL;
 
-	mutex_lock(&oh->_mutex);
+	spin_lock_irqsave(&oh->_lock, flags);
 	r = _reset(oh);
-	mutex_unlock(&oh->_mutex);
+	spin_unlock_irqrestore(&oh->_lock, flags);
 
 	return r;
 }
@@ -1955,13 +1987,18 @@ int omap_hwmod_del_initiator_dep(struct
  */
 int omap_hwmod_enable_wakeup(struct omap_hwmod *oh)
 {
+	unsigned long flags;
+	u32 v;
+
 	if (!oh->class->sysc ||
 	    !(oh->class->sysc->sysc_flags & SYSC_HAS_ENAWAKEUP))
 		return -EINVAL;
 
-	mutex_lock(&oh->_mutex);
-	_enable_wakeup(oh);
-	mutex_unlock(&oh->_mutex);
+	spin_lock_irqsave(&oh->_lock, flags);
+	v = oh->_sysc_cache;
+	_enable_wakeup(oh, &v);
+	_write_sysconfig(v, oh);
+	spin_unlock_irqrestore(&oh->_lock, flags);
 
 	return 0;
 }
@@ -1980,13 +2017,18 @@ int omap_hwmod_enable_wakeup(struct omap
  */
 int omap_hwmod_disable_wakeup(struct omap_hwmod *oh)
 {
+	unsigned long flags;
+	u32 v;
+
 	if (!oh->class->sysc ||
 	    !(oh->class->sysc->sysc_flags & SYSC_HAS_ENAWAKEUP))
 		return -EINVAL;
 
-	mutex_lock(&oh->_mutex);
-	_disable_wakeup(oh);
-	mutex_unlock(&oh->_mutex);
+	spin_lock_irqsave(&oh->_lock, flags);
+	v = oh->_sysc_cache;
+	_disable_wakeup(oh, &v);
+	_write_sysconfig(v, oh);
+	spin_unlock_irqrestore(&oh->_lock, flags);
 
 	return 0;
 }
@@ -2006,13 +2048,14 @@ int omap_hwmod_disable_wakeup(struct oma
 int omap_hwmod_assert_hardreset(struct omap_hwmod *oh, const char *name)
 {
 	int ret;
+	unsigned long flags;
 
 	if (!oh)
 		return -EINVAL;
 
-	mutex_lock(&oh->_mutex);
+	spin_lock_irqsave(&oh->_lock, flags);
 	ret = _assert_hardreset(oh, name);
-	mutex_unlock(&oh->_mutex);
+	spin_unlock_irqrestore(&oh->_lock, flags);
 
 	return ret;
 }
@@ -2032,13 +2075,14 @@ int omap_hwmod_assert_hardreset(struct o
 int omap_hwmod_deassert_hardreset(struct omap_hwmod *oh, const char *name)
 {
 	int ret;
+	unsigned long flags;
 
 	if (!oh)
 		return -EINVAL;
 
-	mutex_lock(&oh->_mutex);
+	spin_lock_irqsave(&oh->_lock, flags);
 	ret = _deassert_hardreset(oh, name);
-	mutex_unlock(&oh->_mutex);
+	spin_unlock_irqrestore(&oh->_lock, flags);
 
 	return ret;
 }
@@ -2057,13 +2101,14 @@ int omap_hwmod_deassert_hardreset(struct
 int omap_hwmod_read_hardreset(struct omap_hwmod *oh, const char *name)
 {
 	int ret;
+	unsigned long flags;
 
 	if (!oh)
 		return -EINVAL;
 
-	mutex_lock(&oh->_mutex);
+	spin_lock_irqsave(&oh->_lock, flags);
 	ret = _read_hardreset(oh, name);
-	mutex_unlock(&oh->_mutex);
+	spin_unlock_irqrestore(&oh->_lock, flags);
 
 	return ret;
 }
@@ -2075,9 +2120,8 @@ int omap_hwmod_read_hardreset(struct oma
  * @fn: callback function pointer to call for each hwmod in class @classname
  * @user: arbitrary context data to pass to the callback function
  *
- * For each omap_hwmod of class @classname, call @fn.  Takes
- * omap_hwmod_mutex to prevent the hwmod list from changing during the
- * iteration.  If the callback function returns something other than
+ * For each omap_hwmod of class @classname, call @fn.
+ * If the callback function returns something other than
  * zero, the iterator is terminated, and the callback function's return
  * value is passed back to the caller.  Returns 0 upon success, -EINVAL
  * if @classname or @fn are NULL, or passes back the error code from @fn.
@@ -2096,8 +2140,6 @@ int omap_hwmod_for_each_by_class(const c
 	pr_debug("omap_hwmod: %s: looking for modules of class %s\n",
 		 __func__, classname);
 
-	mutex_lock(&omap_hwmod_mutex);
-
 	list_for_each_entry(temp_oh, &omap_hwmod_list, node) {
 		if (!strcmp(temp_oh->class->name, classname)) {
 			pr_debug("omap_hwmod: %s: %s: calling callback fn\n",
@@ -2108,8 +2150,6 @@ int omap_hwmod_for_each_by_class(const c
 		}
 	}
 
-	mutex_unlock(&omap_hwmod_mutex);
-
 	if (ret)
 		pr_debug("omap_hwmod: %s: iterator terminated early: %d\n",
 			 __func__, ret);
@@ -2117,3 +2157,64 @@ int omap_hwmod_for_each_by_class(const c
 	return ret;
 }
 
+/**
+ * omap_hwmod_set_postsetup_state - set the post-_setup() state for this hwmod
+ * @oh: struct omap_hwmod *
+ * @state: state that _setup() should leave the hwmod in
+ *
+ * Sets the hwmod state that @oh will enter at the end of _setup() (called by
+ * omap_hwmod_late_init()).  Only valid to call between calls to
+ * omap_hwmod_init() and omap_hwmod_late_init().  Returns 0 upon success or
+ * -EINVAL if there is a problem with the arguments or if the hwmod is
+ * in the wrong state.
+ */
+int omap_hwmod_set_postsetup_state(struct omap_hwmod *oh, u8 state)
+{
+	int ret;
+	unsigned long flags;
+
+	if (!oh)
+		return -EINVAL;
+
+	if (state != _HWMOD_STATE_DISABLED &&
+	    state != _HWMOD_STATE_ENABLED &&
+	    state != _HWMOD_STATE_IDLE)
+		return -EINVAL;
+
+	spin_lock_irqsave(&oh->_lock, flags);
+
+	if (oh->_state != _HWMOD_STATE_REGISTERED) {
+		ret = -EINVAL;
+		goto ohsps_unlock;
+	}
+
+	oh->_postsetup_state = state;
+	ret = 0;
+
+ohsps_unlock:
+	spin_unlock_irqrestore(&oh->_lock, flags);
+
+	return ret;
+}
+
+/**
+ * omap_hwmod_get_context_loss_count - get lost context count
+ * @oh: struct omap_hwmod *
+ *
+ * Query the powerdomain of of @oh to get the context loss
+ * count for this device.
+ *
+ * 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)
+{
+	struct powerdomain *pwrdm;
+	int ret = 0;
+
+	pwrdm = omap_hwmod_get_pwrdm(oh);
+	if (pwrdm)
+		ret = pwrdm_get_context_loss_count(pwrdm);
+
+	return ret;
+}
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/omap-iommu.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/omap-iommu.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/omap-iommu.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/omap-iommu.c	2011-03-14 21:20:32.000000000 -0400
@@ -33,9 +33,11 @@ static struct iommu_device omap3_devices
 			.name = "isp",
 			.nr_tlb_entries = 8,
 			.clk_name = "cam_ick",
+			.da_start = 0x0,
+			.da_end = 0xFFFFF000,
 		},
 	},
-#if defined(CONFIG_MPU_BRIDGE_IOMMU)
+#if defined(CONFIG_OMAP_IOMMU_IVA2)
 	{
 		.base = 0x5d000000,
 		.irq = 28,
@@ -43,6 +45,8 @@ static struct iommu_device omap3_devices
 			.name = "iva2",
 			.nr_tlb_entries = 32,
 			.clk_name = "iva2_ck",
+			.da_start = 0x11000000,
+			.da_end = 0xFFFFF000,
 		},
 	},
 #endif
@@ -64,6 +68,8 @@ static struct iommu_device omap4_devices
 			.name = "ducati",
 			.nr_tlb_entries = 32,
 			.clk_name = "ducati_ick",
+			.da_start = 0x0,
+			.da_end = 0xFFFFF000,
 		},
 	},
 #if defined(CONFIG_MPU_TESLA_IOMMU)
@@ -74,6 +80,8 @@ static struct iommu_device omap4_devices
 			.name = "tesla",
 			.nr_tlb_entries = 32,
 			.clk_name = "tesla_ick",
+			.da_start = 0x0,
+			.da_end = 0xFFFFF000,
 		},
 	},
 #endif
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/omap_opp_data.h linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/omap_opp_data.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/omap_opp_data.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/omap_opp_data.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,72 @@
+/*
+ * OMAP SoC specific OPP Data helpers
+ *
+ * Copyright (C) 2009-2010 Texas Instruments Incorporated - http://www.ti.com/
+ *	Nishanth Menon
+ *	Kevin Hilman
+ * Copyright (C) 2010 Nokia Corporation.
+ *      Eduardo Valentin
+ *
+ * This program is free software; you can 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.
+ */
+#ifndef __ARCH_ARM_MACH_OMAP2_OMAP_OPP_DATA_H
+#define __ARCH_ARM_MACH_OMAP2_OMAP_OPP_DATA_H
+
+#include <plat/omap_hwmod.h>
+
+/*
+ * *BIG FAT WARNING*:
+ * USE the following ONLY in opp data initialization common to an SoC.
+ * DO NOT USE these in board files/pm core etc.
+ */
+
+/**
+ * struct omap_opp_def - OMAP OPP Definition
+ * @hwmod_name:	Name of the hwmod for this domain
+ * @freq:	Frequency in hertz corresponding to this OPP
+ * @u_volt:	Nominal voltage in microvolts corresponding to this OPP
+ * @default_available:	True/false - is this OPP available by default
+ *
+ * OMAP SOCs have a standard set of tuples consisting of frequency and voltage
+ * pairs that the device will support per voltage domain. This is called
+ * Operating Points or OPP. The actual definitions of OMAP Operating Points
+ * varies over silicon within the same family of devices. For a specific
+ * domain, you can have a set of {frequency, voltage} pairs and this is denoted
+ * by an array of omap_opp_def. As the kernel boots and more information is
+ * available, a set of these are activated based on the precise nature of
+ * device the kernel boots up on. It is interesting to remember that each IP
+ * which belongs to a voltage domain may define their own set of OPPs on top
+ * of this - but this is handled by the appropriate driver.
+ */
+struct omap_opp_def {
+	char *hwmod_name;
+
+	unsigned long freq;
+	unsigned long u_volt;
+
+	bool default_available;
+};
+
+/*
+ * Initialization wrapper used to define an OPP for OMAP variants.
+ */
+#define OPP_INITIALIZER(_hwmod_name, _enabled, _freq, _uv)	\
+{								\
+	.hwmod_name	= _hwmod_name,				\
+	.default_available	= _enabled,			\
+	.freq		= _freq,				\
+	.u_volt		= _uv,					\
+}
+
+/* Use this to initialize the default table */
+extern int __init omap_init_opp_table(struct omap_opp_def *opp_def,
+		u32 opp_def_size);
+
+#endif		/* __ARCH_ARM_MACH_OMAP2_OMAP_OPP_DATA_H */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/omap_phy_internal.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/omap_phy_internal.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/omap_phy_internal.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/omap_phy_internal.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,149 @@
+/*
+  * This file configures the internal USB PHY in OMAP4430. Used
+  * with TWL6030 transceiver and MUSB on OMAP4430.
+  *
+  * Copyright (C) 2010 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 as published by
+  * the Free Software Foundation; either version 2 of the License, or
+  * (at your option) any later version.
+  *
+  * Author: Hema HK <hemahk@ti.com>
+  *
+  * 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/types.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/usb.h>
+
+#include <plat/usb.h>
+
+/* OMAP control module register for UTMI PHY */
+#define CONTROL_DEV_CONF		0x300
+#define PHY_PD				0x1
+
+#define USBOTGHS_CONTROL		0x33c
+#define	AVALID				BIT(0)
+#define	BVALID				BIT(1)
+#define	VBUSVALID			BIT(2)
+#define	SESSEND				BIT(3)
+#define	IDDIG				BIT(4)
+
+static struct clk *phyclk, *clk48m, *clk32k;
+static void __iomem *ctrl_base;
+
+int omap4430_phy_init(struct device *dev)
+{
+	ctrl_base = ioremap(OMAP443X_SCM_BASE, SZ_1K);
+	if (!ctrl_base) {
+		dev_err(dev, "control module ioremap failed\n");
+		return -ENOMEM;
+	}
+	/* Power down the phy */
+	__raw_writel(PHY_PD, ctrl_base + CONTROL_DEV_CONF);
+	phyclk = clk_get(dev, "ocp2scp_usb_phy_ick");
+
+	if (IS_ERR(phyclk)) {
+		dev_err(dev, "cannot clk_get ocp2scp_usb_phy_ick\n");
+		iounmap(ctrl_base);
+		return PTR_ERR(phyclk);
+	}
+
+	clk48m = clk_get(dev, "ocp2scp_usb_phy_phy_48m");
+	if (IS_ERR(clk48m)) {
+		dev_err(dev, "cannot clk_get ocp2scp_usb_phy_phy_48m\n");
+		clk_put(phyclk);
+		iounmap(ctrl_base);
+		return PTR_ERR(clk48m);
+	}
+
+	clk32k = clk_get(dev, "usb_phy_cm_clk32k");
+	if (IS_ERR(clk32k)) {
+		dev_err(dev, "cannot clk_get usb_phy_cm_clk32k\n");
+		clk_put(phyclk);
+		clk_put(clk48m);
+		iounmap(ctrl_base);
+		return PTR_ERR(clk32k);
+	}
+	return 0;
+}
+
+int omap4430_phy_set_clk(struct device *dev, int on)
+{
+	static int state;
+
+	if (on && !state) {
+		/* Enable the phy clocks */
+		clk_enable(phyclk);
+		clk_enable(clk48m);
+		clk_enable(clk32k);
+		state = 1;
+	} else if (state) {
+		/* Disable the phy clocks */
+		clk_disable(phyclk);
+		clk_disable(clk48m);
+		clk_disable(clk32k);
+		state = 0;
+	}
+	return 0;
+}
+
+int omap4430_phy_power(struct device *dev, int ID, int on)
+{
+	if (on) {
+		/* enabled the clocks */
+		omap4430_phy_set_clk(dev, 1);
+		/* power on the phy */
+		if (__raw_readl(ctrl_base + CONTROL_DEV_CONF) & PHY_PD) {
+			__raw_writel(~PHY_PD, ctrl_base + CONTROL_DEV_CONF);
+			mdelay(200);
+		}
+		if (ID)
+			/* enable VBUS valid, IDDIG groung */
+			__raw_writel(AVALID | VBUSVALID, ctrl_base +
+							USBOTGHS_CONTROL);
+		else
+			/*
+			 * Enable VBUS Valid, AValid and IDDIG
+			 * high impedence
+			 */
+			__raw_writel(IDDIG | AVALID | VBUSVALID,
+						ctrl_base + USBOTGHS_CONTROL);
+	} else {
+		/* Enable session END and IDIG to high impedence. */
+		__raw_writel(SESSEND | IDDIG, ctrl_base +
+					USBOTGHS_CONTROL);
+		/* Disable the clocks */
+		omap4430_phy_set_clk(dev, 0);
+		/* Power down the phy */
+		__raw_writel(PHY_PD, ctrl_base + CONTROL_DEV_CONF);
+	}
+
+	return 0;
+}
+
+int omap4430_phy_exit(struct device *dev)
+{
+	if (ctrl_base)
+		iounmap(ctrl_base);
+	if (phyclk)
+		clk_put(phyclk);
+	if (clk48m)
+		clk_put(clk48m);
+	if (clk32k)
+		clk_put(clk32k);
+
+	return 0;
+}
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/omap-smp.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/omap-smp.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/omap-smp.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/omap-smp.c	2011-03-14 21:20:32.000000000 -0400
@@ -21,7 +21,6 @@
 #include <linux/io.h>
 
 #include <asm/cacheflush.h>
-#include <asm/localtimer.h>
 #include <asm/smp_scu.h>
 #include <mach/hardware.h>
 #include <mach/omap4-common.h>
@@ -29,28 +28,16 @@
 /* SCU base address */
 static void __iomem *scu_base;
 
-/*
- * Use SCU config register to count number of cores
- */
-static inline unsigned int get_core_count(void)
-{
-	if (scu_base)
-		return scu_get_core_count(scu_base);
-	return 1;
-}
-
 static DEFINE_SPINLOCK(boot_lock);
 
 void __cpuinit platform_secondary_init(unsigned int cpu)
 {
-	trace_hardirqs_off();
-
 	/*
 	 * 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_cpu_init(0, gic_cpu_base_addr);
+	gic_secondary_init(0);
 
 	/*
 	 * Synchronise with the boot thread.
@@ -76,7 +63,7 @@ int __cpuinit boot_secondary(unsigned in
 	omap_modify_auxcoreboot0(0x200, 0xfffffdff);
 	flush_cache_all();
 	smp_wmb();
-	smp_cross_call(cpumask_of(cpu));
+	smp_cross_call(cpumask_of(cpu), 1);
 
 	/*
 	 * Now the secondary core is starting up let it run its
@@ -118,25 +105,9 @@ void __init smp_init_cpus(void)
 	scu_base = ioremap(OMAP44XX_SCU_BASE, SZ_256);
 	BUG_ON(!scu_base);
 
-	ncores = get_core_count();
-
-	for (i = 0; i < ncores; i++)
-		set_cpu_possible(i, true);
-}
-
-void __init smp_prepare_cpus(unsigned int max_cpus)
-{
-	unsigned int ncores = get_core_count();
-	unsigned int cpu = smp_processor_id();
-	int i;
+	ncores = scu_get_core_count(scu_base);
 
 	/* sanity check */
-	if (ncores == 0) {
-		printk(KERN_ERR
-		       "OMAP4: strange core count of 0? Default to 1\n");
-		ncores = 1;
-	}
-
 	if (ncores > NR_CPUS) {
 		printk(KERN_WARNING
 		       "OMAP4: no. of cores (%d) greater than configured "
@@ -144,13 +115,14 @@ void __init smp_prepare_cpus(unsigned in
 		       ncores, NR_CPUS);
 		ncores = NR_CPUS;
 	}
-	smp_store_cpu_info(cpu);
 
-	/*
-	 * are we trying to boot more cores than exist?
-	 */
-	if (max_cpus > ncores)
-		max_cpus = ncores;
+	for (i = 0; i < ncores; i++)
+		set_cpu_possible(i, true);
+}
+
+void __init platform_smp_prepare_cpus(unsigned int max_cpus)
+{
+	int i;
 
 	/*
 	 * Initialise the present map, which describes the set of CPUs
@@ -159,18 +131,10 @@ void __init smp_prepare_cpus(unsigned in
 	for (i = 0; i < max_cpus; i++)
 		set_cpu_present(i, true);
 
-	if (max_cpus > 1) {
-		/*
-		 * Enable the local timer or broadcast device for the
-		 * boot CPU, but only if we have more than one CPU.
-		 */
-		percpu_timer_setup();
-
-		/*
-		 * Initialise the SCU and wake up the secondary core using
-		 * wakeup_secondary().
-		 */
-		scu_enable(scu_base);
-		wakeup_secondary();
-	}
+	/*
+	 * Initialise the SCU and wake up the secondary core using
+	 * wakeup_secondary().
+	 */
+	scu_enable(scu_base);
+	wakeup_secondary();
 }
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/omap_twl.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/omap_twl.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/omap_twl.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/omap_twl.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,279 @@
+/**
+ * OMAP and TWL PMIC specific intializations.
+ *
+ * Copyright (C) 2010 Texas Instruments Incorporated.
+ * Thara Gopinath
+ * Copyright (C) 2009 Texas Instruments Incorporated.
+ * Nishanth Menon
+ * Copyright (C) 2009 Nokia Corporation
+ * Paul Walmsley
+ *
+ * This program is free software; you can 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/io.h>
+#include <linux/kernel.h>
+#include <linux/i2c/twl.h>
+
+#include <plat/voltage.h>
+
+#include "pm.h"
+
+#define OMAP3_SRI2C_SLAVE_ADDR		0x12
+#define OMAP3_VDD_MPU_SR_CONTROL_REG	0x00
+#define OMAP3_VDD_CORE_SR_CONTROL_REG	0x01
+#define OMAP3_VP_CONFIG_ERROROFFSET	0x00
+#define OMAP3_VP_VSTEPMIN_VSTEPMIN	0x1
+#define OMAP3_VP_VSTEPMAX_VSTEPMAX	0x04
+#define OMAP3_VP_VLIMITTO_TIMEOUT_US	200
+
+#define OMAP3430_VP1_VLIMITTO_VDDMIN	0x14
+#define OMAP3430_VP1_VLIMITTO_VDDMAX	0x42
+#define OMAP3430_VP2_VLIMITTO_VDDMIN	0x18
+#define OMAP3430_VP2_VLIMITTO_VDDMAX	0x2c
+
+#define OMAP3630_VP1_VLIMITTO_VDDMIN	0x18
+#define OMAP3630_VP1_VLIMITTO_VDDMAX	0x3c
+#define OMAP3630_VP2_VLIMITTO_VDDMIN	0x18
+#define OMAP3630_VP2_VLIMITTO_VDDMAX	0x30
+
+#define OMAP4_SRI2C_SLAVE_ADDR		0x12
+#define OMAP4_VDD_MPU_SR_VOLT_REG	0x55
+#define OMAP4_VDD_IVA_SR_VOLT_REG	0x5B
+#define OMAP4_VDD_CORE_SR_VOLT_REG	0x61
+
+#define OMAP4_VP_CONFIG_ERROROFFSET	0x00
+#define OMAP4_VP_VSTEPMIN_VSTEPMIN	0x01
+#define OMAP4_VP_VSTEPMAX_VSTEPMAX	0x04
+#define OMAP4_VP_VLIMITTO_TIMEOUT_US	200
+
+#define OMAP4_VP_MPU_VLIMITTO_VDDMIN	0xA
+#define OMAP4_VP_MPU_VLIMITTO_VDDMAX	0x39
+#define OMAP4_VP_IVA_VLIMITTO_VDDMIN	0xA
+#define OMAP4_VP_IVA_VLIMITTO_VDDMAX	0x2D
+#define OMAP4_VP_CORE_VLIMITTO_VDDMIN	0xA
+#define OMAP4_VP_CORE_VLIMITTO_VDDMAX	0x28
+
+static bool is_offset_valid;
+static u8 smps_offset;
+
+#define REG_SMPS_OFFSET         0xE0
+
+static unsigned long twl4030_vsel_to_uv(const u8 vsel)
+{
+	return (((vsel * 125) + 6000)) * 100;
+}
+
+static u8 twl4030_uv_to_vsel(unsigned long uv)
+{
+	return DIV_ROUND_UP(uv - 600000, 12500);
+}
+
+static unsigned long twl6030_vsel_to_uv(const u8 vsel)
+{
+	/*
+	 * In TWL6030 depending on the value of SMPS_OFFSET
+	 * efuse register the voltage range supported in
+	 * standard mode can be either between 0.6V - 1.3V or
+	 * 0.7V - 1.4V. In TWL6030 ES1.0 SMPS_OFFSET efuse
+	 * is programmed to all 0's where as starting from
+	 * TWL6030 ES1.1 the efuse is programmed to 1
+	 */
+	if (!is_offset_valid) {
+		twl_i2c_read_u8(TWL6030_MODULE_ID0, &smps_offset,
+				REG_SMPS_OFFSET);
+		is_offset_valid = true;
+	}
+
+	/*
+	 * There is no specific formula for voltage to vsel
+	 * conversion above 1.3V. There are special hardcoded
+	 * values for voltages above 1.3V. Currently we are
+	 * hardcoding only for 1.35 V which is used for 1GH OPP for
+	 * OMAP4430.
+	 */
+	if (vsel == 0x3A)
+		return 1350000;
+
+	if (smps_offset & 0x8)
+		return ((((vsel - 1) * 125) + 7000)) * 100;
+	else
+		return ((((vsel - 1) * 125) + 6000)) * 100;
+}
+
+static u8 twl6030_uv_to_vsel(unsigned long uv)
+{
+	/*
+	 * In TWL6030 depending on the value of SMPS_OFFSET
+	 * efuse register the voltage range supported in
+	 * standard mode can be either between 0.6V - 1.3V or
+	 * 0.7V - 1.4V. In TWL6030 ES1.0 SMPS_OFFSET efuse
+	 * is programmed to all 0's where as starting from
+	 * TWL6030 ES1.1 the efuse is programmed to 1
+	 */
+	if (!is_offset_valid) {
+		twl_i2c_read_u8(TWL6030_MODULE_ID0, &smps_offset,
+				REG_SMPS_OFFSET);
+		is_offset_valid = true;
+	}
+
+	/*
+	 * There is no specific formula for voltage to vsel
+	 * conversion above 1.3V. There are special hardcoded
+	 * values for voltages above 1.3V. Currently we are
+	 * hardcoding only for 1.35 V which is used for 1GH OPP for
+	 * OMAP4430.
+	 */
+	if (uv == 1350000)
+		return 0x3A;
+
+	if (smps_offset & 0x8)
+		return DIV_ROUND_UP(uv - 700000, 12500) + 1;
+	else
+		return DIV_ROUND_UP(uv - 600000, 12500) + 1;
+}
+
+static struct omap_volt_pmic_info omap3_mpu_volt_info = {
+	.slew_rate		= 4000,
+	.step_size		= 12500,
+	.on_volt		= 1200000,
+	.onlp_volt		= 1000000,
+	.ret_volt		= 975000,
+	.off_volt		= 600000,
+	.volt_setup_time	= 0xfff,
+	.vp_erroroffset		= OMAP3_VP_CONFIG_ERROROFFSET,
+	.vp_vstepmin		= OMAP3_VP_VSTEPMIN_VSTEPMIN,
+	.vp_vstepmax		= OMAP3_VP_VSTEPMAX_VSTEPMAX,
+	.vp_vddmin		= OMAP3430_VP1_VLIMITTO_VDDMIN,
+	.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,
+	.vsel_to_uv		= twl4030_vsel_to_uv,
+	.uv_to_vsel		= twl4030_uv_to_vsel,
+};
+
+static struct omap_volt_pmic_info omap3_core_volt_info = {
+	.slew_rate		= 4000,
+	.step_size		= 12500,
+	.on_volt                = 1200000,
+	.onlp_volt              = 1000000,
+	.ret_volt               = 975000,
+	.off_volt               = 600000,
+	.volt_setup_time        = 0xfff,
+	.vp_erroroffset		= OMAP3_VP_CONFIG_ERROROFFSET,
+	.vp_vstepmin		= OMAP3_VP_VSTEPMIN_VSTEPMIN,
+	.vp_vstepmax		= OMAP3_VP_VSTEPMAX_VSTEPMAX,
+	.vp_vddmin		= OMAP3430_VP2_VLIMITTO_VDDMIN,
+	.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,
+	.vsel_to_uv		= twl4030_vsel_to_uv,
+	.uv_to_vsel		= twl4030_uv_to_vsel,
+};
+
+static struct omap_volt_pmic_info omap4_mpu_volt_info = {
+	.slew_rate		= 4000,
+	.step_size		= 12500,
+	.on_volt		= 1350000,
+	.onlp_volt		= 1350000,
+	.ret_volt		= 837500,
+	.off_volt		= 600000,
+	.volt_setup_time	= 0,
+	.vp_erroroffset		= OMAP4_VP_CONFIG_ERROROFFSET,
+	.vp_vstepmin		= OMAP4_VP_VSTEPMIN_VSTEPMIN,
+	.vp_vstepmax		= OMAP4_VP_VSTEPMAX_VSTEPMAX,
+	.vp_vddmin		= OMAP4_VP_MPU_VLIMITTO_VDDMIN,
+	.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,
+	.vsel_to_uv		= twl6030_vsel_to_uv,
+	.uv_to_vsel		= twl6030_uv_to_vsel,
+};
+
+static struct omap_volt_pmic_info omap4_iva_volt_info = {
+	.slew_rate		= 4000,
+	.step_size		= 12500,
+	.on_volt		= 1100000,
+	.onlp_volt		= 1100000,
+	.ret_volt		= 837500,
+	.off_volt		= 600000,
+	.volt_setup_time	= 0,
+	.vp_erroroffset		= OMAP4_VP_CONFIG_ERROROFFSET,
+	.vp_vstepmin		= OMAP4_VP_VSTEPMIN_VSTEPMIN,
+	.vp_vstepmax		= OMAP4_VP_VSTEPMAX_VSTEPMAX,
+	.vp_vddmin		= OMAP4_VP_IVA_VLIMITTO_VDDMIN,
+	.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,
+	.vsel_to_uv		= twl6030_vsel_to_uv,
+	.uv_to_vsel		= twl6030_uv_to_vsel,
+};
+
+static struct omap_volt_pmic_info omap4_core_volt_info = {
+	.slew_rate		= 4000,
+	.step_size		= 12500,
+	.on_volt		= 1100000,
+	.onlp_volt		= 1100000,
+	.ret_volt		= 837500,
+	.off_volt		= 600000,
+	.volt_setup_time	= 0,
+	.vp_erroroffset		= OMAP4_VP_CONFIG_ERROROFFSET,
+	.vp_vstepmin		= OMAP4_VP_VSTEPMIN_VSTEPMIN,
+	.vp_vstepmax		= OMAP4_VP_VSTEPMAX_VSTEPMAX,
+	.vp_vddmin		= OMAP4_VP_CORE_VLIMITTO_VDDMIN,
+	.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,
+	.vsel_to_uv		= twl6030_vsel_to_uv,
+	.uv_to_vsel		= twl6030_uv_to_vsel,
+};
+
+int __init omap4_twl_init(void)
+{
+	struct voltagedomain *voltdm;
+
+	if (!cpu_is_omap44xx())
+		return -ENODEV;
+
+	voltdm = omap_voltage_domain_lookup("mpu");
+	omap_voltage_register_pmic(voltdm, &omap4_mpu_volt_info);
+
+	voltdm = omap_voltage_domain_lookup("iva");
+	omap_voltage_register_pmic(voltdm, &omap4_iva_volt_info);
+
+	voltdm = omap_voltage_domain_lookup("core");
+	omap_voltage_register_pmic(voltdm, &omap4_core_volt_info);
+
+	return 0;
+}
+
+int __init omap3_twl_init(void)
+{
+	struct voltagedomain *voltdm;
+
+	if (!cpu_is_omap34xx())
+		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;
+	}
+
+	voltdm = omap_voltage_domain_lookup("mpu");
+	omap_voltage_register_pmic(voltdm, &omap3_mpu_volt_info);
+
+	voltdm = omap_voltage_domain_lookup("core");
+	omap_voltage_register_pmic(voltdm, &omap3_core_volt_info);
+
+	return 0;
+}
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/opp3xxx_data.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/opp3xxx_data.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/opp3xxx_data.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/opp3xxx_data.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,107 @@
+/*
+ * OMAP3 OPP table definitions.
+ *
+ * Copyright (C) 2009-2010 Texas Instruments Incorporated - http://www.ti.com/
+ *	Nishanth Menon
+ *	Kevin Hilman
+ * Copyright (C) 2010 Nokia Corporation.
+ *      Eduardo Valentin
+ *
+ * This program is free software; you can 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/module.h>
+
+#include <plat/cpu.h>
+
+#include "omap_opp_data.h"
+
+static struct omap_opp_def __initdata omap34xx_opp_def_list[] = {
+	/* MPU OPP1 */
+	OPP_INITIALIZER("mpu", true, 125000000, 975000),
+	/* MPU OPP2 */
+	OPP_INITIALIZER("mpu", true, 250000000, 1075000),
+	/* MPU OPP3 */
+	OPP_INITIALIZER("mpu", true, 500000000, 1200000),
+	/* MPU OPP4 */
+	OPP_INITIALIZER("mpu", true, 550000000, 1270000),
+	/* MPU OPP5 */
+	OPP_INITIALIZER("mpu", true, 600000000, 1350000),
+
+	/*
+	 * L3 OPP1 - 41.5 MHz is disabled because: The voltage for that OPP is
+	 * almost the same than the one at 83MHz thus providing very little
+	 * gain for the power point of view. In term of energy it will even
+	 * increase the consumption due to the very negative performance
+	 * impact that frequency will do to the MPU and the whole system in
+	 * general.
+	 */
+	OPP_INITIALIZER("l3_main", false, 41500000, 975000),
+	/* L3 OPP2 */
+	OPP_INITIALIZER("l3_main", true, 83000000, 1050000),
+	/* L3 OPP3 */
+	OPP_INITIALIZER("l3_main", true, 166000000, 1150000),
+
+	/* DSP OPP1 */
+	OPP_INITIALIZER("iva", true, 90000000, 975000),
+	/* DSP OPP2 */
+	OPP_INITIALIZER("iva", true, 180000000, 1075000),
+	/* DSP OPP3 */
+	OPP_INITIALIZER("iva", true, 360000000, 1200000),
+	/* DSP OPP4 */
+	OPP_INITIALIZER("iva", true, 400000000, 1270000),
+	/* DSP OPP5 */
+	OPP_INITIALIZER("iva", true, 430000000, 1350000),
+};
+
+static struct omap_opp_def __initdata omap36xx_opp_def_list[] = {
+	/* MPU OPP1 - OPP50 */
+	OPP_INITIALIZER("mpu", true,  300000000, 1012500),
+	/* MPU OPP2 - OPP100 */
+	OPP_INITIALIZER("mpu", true,  600000000, 1200000),
+	/* MPU OPP3 - OPP-Turbo */
+	OPP_INITIALIZER("mpu", false, 800000000, 1325000),
+	/* MPU OPP4 - OPP-SB */
+	OPP_INITIALIZER("mpu", false, 1000000000, 1375000),
+
+	/* L3 OPP1 - OPP50 */
+	OPP_INITIALIZER("l3_main", true, 100000000, 1000000),
+	/* L3 OPP2 - OPP100, OPP-Turbo, OPP-SB */
+	OPP_INITIALIZER("l3_main", true, 200000000, 1200000),
+
+	/* DSP OPP1 - OPP50 */
+	OPP_INITIALIZER("iva", true,  260000000, 1012500),
+	/* DSP OPP2 - OPP100 */
+	OPP_INITIALIZER("iva", true,  520000000, 1200000),
+	/* DSP OPP3 - OPP-Turbo */
+	OPP_INITIALIZER("iva", false, 660000000, 1325000),
+	/* DSP OPP4 - OPP-SB */
+	OPP_INITIALIZER("iva", false, 800000000, 1375000),
+};
+
+/**
+ * omap3_opp_init() - initialize omap3 opp table
+ */
+static int __init omap3_opp_init(void)
+{
+	int r = -ENODEV;
+
+	if (!cpu_is_omap34xx())
+		return r;
+
+	if (cpu_is_omap3630())
+		r = omap_init_opp_table(omap36xx_opp_def_list,
+			ARRAY_SIZE(omap36xx_opp_def_list));
+	else
+		r = omap_init_opp_table(omap34xx_opp_def_list,
+			ARRAY_SIZE(omap34xx_opp_def_list));
+
+	return r;
+}
+device_initcall(omap3_opp_init);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/opp4xxx_data.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/opp4xxx_data.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/opp4xxx_data.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/opp4xxx_data.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,57 @@
+/*
+ * OMAP4 OPP table definitions.
+ *
+ * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
+ *	Nishanth Menon
+ *	Kevin Hilman
+ *	Thara Gopinath
+ * Copyright (C) 2010 Nokia Corporation.
+ *      Eduardo Valentin
+ *
+ * This program is free software; you can 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/module.h>
+
+#include <plat/cpu.h>
+
+#include "omap_opp_data.h"
+
+static struct omap_opp_def __initdata omap44xx_opp_def_list[] = {
+	/* MPU OPP1 - OPP50 */
+	OPP_INITIALIZER("mpu", true, 300000000, 1100000),
+	/* MPU OPP2 - OPP100 */
+	OPP_INITIALIZER("mpu", true, 600000000, 1200000),
+	/* MPU OPP3 - OPP-Turbo */
+	OPP_INITIALIZER("mpu", false, 800000000, 1260000),
+	/* MPU OPP4 - OPP-SB */
+	OPP_INITIALIZER("mpu", false, 1008000000, 1350000),
+	/* L3 OPP1 - OPP50 */
+	OPP_INITIALIZER("l3_main_1", true, 100000000, 930000),
+	/* L3 OPP2 - OPP100, OPP-Turbo, OPP-SB */
+	OPP_INITIALIZER("l3_main_1", true, 200000000, 1100000),
+	/* TODO: add IVA, DSP, aess, fdif, gpu */
+};
+
+/**
+ * omap4_opp_init() - initialize omap4 opp table
+ */
+static int __init omap4_opp_init(void)
+{
+	int r = -ENODEV;
+
+	if (!cpu_is_omap44xx())
+		return r;
+
+	r = omap_init_opp_table(omap44xx_opp_def_list,
+			ARRAY_SIZE(omap44xx_opp_def_list));
+
+	return r;
+}
+device_initcall(omap4_opp_init);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/opp.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/opp.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/opp.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/opp.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,93 @@
+/*
+ * OMAP SoC specific OPP wrapper function
+ *
+ * Copyright (C) 2009-2010 Texas Instruments Incorporated - http://www.ti.com/
+ *	Nishanth Menon
+ *	Kevin Hilman
+ * Copyright (C) 2010 Nokia Corporation.
+ *      Eduardo Valentin
+ *
+ * This program is free software; you can 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/module.h>
+#include <linux/opp.h>
+
+#include <plat/omap_device.h>
+
+#include "omap_opp_data.h"
+
+/* Temp variable to allow multiple calls */
+static u8 __initdata omap_table_init;
+
+/**
+ * omap_init_opp_table() - Initialize opp table as per the CPU type
+ * @opp_def:		opp default list for this silicon
+ * @opp_def_size:	number of opp entries for this silicon
+ *
+ * Register the initial OPP table with the OPP library based on the CPU
+ * type. This is meant to be used only by SoC specific registration.
+ */
+int __init omap_init_opp_table(struct omap_opp_def *opp_def,
+		u32 opp_def_size)
+{
+	int i, r;
+
+	if (!opp_def || !opp_def_size) {
+		pr_err("%s: invalid params!\n", __func__);
+		return -EINVAL;
+	}
+
+	/*
+	 * Initialize only if not already initialized even if the previous
+	 * call failed, because, no reason we'd succeed again.
+	 */
+	if (omap_table_init)
+		return -EEXIST;
+	omap_table_init = 1;
+
+	/* Lets now register with OPP library */
+	for (i = 0; i < opp_def_size; i++) {
+		struct omap_hwmod *oh;
+		struct device *dev;
+
+		if (!opp_def->hwmod_name) {
+			pr_err("%s: NULL name of omap_hwmod, failing [%d].\n",
+				__func__, i);
+			return -EINVAL;
+		}
+		oh = omap_hwmod_lookup(opp_def->hwmod_name);
+		if (!oh || !oh->od) {
+			pr_warn("%s: no hwmod or odev for %s, [%d] "
+				"cannot add OPPs.\n", __func__,
+				opp_def->hwmod_name, i);
+			return -EINVAL;
+		}
+		dev = &oh->od->pdev.dev;
+
+		r = opp_add(dev, opp_def->freq, opp_def->u_volt);
+		if (r) {
+			dev_err(dev, "%s: add OPP %ld failed for %s [%d] "
+				"result=%d\n",
+			       __func__, opp_def->freq,
+			       opp_def->hwmod_name, i, r);
+		} else {
+			if (!opp_def->default_available)
+				r = opp_disable(dev, opp_def->freq);
+			if (r)
+				dev_err(dev, "%s: disable %ld failed for %s "
+					"[%d] result=%d\n",
+					__func__, opp_def->freq,
+					opp_def->hwmod_name, i, r);
+		}
+		opp_def++;
+	}
+
+	return 0;
+}
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/pm24xx.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/pm24xx.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/pm24xx.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/pm24xx.c	2011-03-14 21:20:32.000000000 -0400
@@ -42,16 +42,16 @@
 #include <plat/dma.h>
 #include <plat/board.h>
 
-#include "prm.h"
+#include "prm2xxx_3xxx.h"
 #include "prm-regbits-24xx.h"
-#include "cm.h"
+#include "cm2xxx_3xxx.h"
 #include "cm-regbits-24xx.h"
 #include "sdrc.h"
 #include "pm.h"
 #include "control.h"
 
-#include <plat/powerdomain.h>
-#include <plat/clockdomain.h>
+#include "powerdomain.h"
+#include "clockdomain.h"
 
 #ifdef CONFIG_SUSPEND
 static suspend_state_t suspend_state = PM_SUSPEND_ON;
@@ -79,8 +79,8 @@ static int omap2_fclks_active(void)
 {
 	u32 f1, f2;
 
-	f1 = cm_read_mod_reg(CORE_MOD, CM_FCLKEN1);
-	f2 = cm_read_mod_reg(CORE_MOD, OMAP24XX_CM_FCLKEN2);
+	f1 = omap2_cm_read_mod_reg(CORE_MOD, CM_FCLKEN1);
+	f2 = omap2_cm_read_mod_reg(CORE_MOD, OMAP24XX_CM_FCLKEN2);
 
 	/* Ignore UART clocks.  These are handled by UART core (serial.c) */
 	f1 &= ~(OMAP24XX_EN_UART1_MASK | OMAP24XX_EN_UART2_MASK);
@@ -105,9 +105,9 @@ static void omap2_enter_full_retention(v
 
 	/* Clear old wake-up events */
 	/* REVISIT: These write to reserved bits? */
-	prm_write_mod_reg(0xffffffff, CORE_MOD, PM_WKST1);
-	prm_write_mod_reg(0xffffffff, CORE_MOD, OMAP24XX_PM_WKST2);
-	prm_write_mod_reg(0xffffffff, WKUP_MOD, PM_WKST);
+	omap2_prm_write_mod_reg(0xffffffff, CORE_MOD, PM_WKST1);
+	omap2_prm_write_mod_reg(0xffffffff, CORE_MOD, OMAP24XX_PM_WKST2);
+	omap2_prm_write_mod_reg(0xffffffff, WKUP_MOD, PM_WKST);
 
 	/*
 	 * Set MPU powerdomain's next power state to RETENTION;
@@ -120,7 +120,7 @@ static void omap2_enter_full_retention(v
 	l = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0) | OMAP24XX_USBSTANDBYCTRL;
 	omap_ctrl_writel(l, OMAP2_CONTROL_DEVCONF0);
 
-	omap2_gpio_prepare_for_idle(PWRDM_POWER_RET);
+	omap2_gpio_prepare_for_idle(0);
 
 	if (omap2_pm_debug) {
 		omap2_pm_dump(0, 0, 0);
@@ -134,7 +134,7 @@ static void omap2_enter_full_retention(v
 
 	/* Block console output in case it is on one of the OMAP UARTs */
 	if (!is_suspending())
-		if (try_acquire_console_sem())
+		if (!console_trylock())
 			goto no_sleep;
 
 	omap_uart_prepare_idle(0);
@@ -151,7 +151,7 @@ static void omap2_enter_full_retention(v
 	omap_uart_resume_idle(0);
 
 	if (!is_suspending())
-		release_console_sem();
+		console_unlock();
 
 no_sleep:
 	if (omap2_pm_debug) {
@@ -167,30 +167,30 @@ no_sleep:
 	clk_enable(osc_ck);
 
 	/* clear CORE wake-up events */
-	prm_write_mod_reg(0xffffffff, CORE_MOD, PM_WKST1);
-	prm_write_mod_reg(0xffffffff, CORE_MOD, OMAP24XX_PM_WKST2);
+	omap2_prm_write_mod_reg(0xffffffff, CORE_MOD, PM_WKST1);
+	omap2_prm_write_mod_reg(0xffffffff, CORE_MOD, OMAP24XX_PM_WKST2);
 
 	/* wakeup domain events - bit 1: GPT1, bit5 GPIO */
-	prm_clear_mod_reg_bits(0x4 | 0x1, WKUP_MOD, PM_WKST);
+	omap2_prm_clear_mod_reg_bits(0x4 | 0x1, WKUP_MOD, PM_WKST);
 
 	/* MPU domain wake events */
-	l = prm_read_mod_reg(OCP_MOD, OMAP2_PRCM_IRQSTATUS_MPU_OFFSET);
+	l = omap2_prm_read_mod_reg(OCP_MOD, OMAP2_PRCM_IRQSTATUS_MPU_OFFSET);
 	if (l & 0x01)
-		prm_write_mod_reg(0x01, OCP_MOD,
+		omap2_prm_write_mod_reg(0x01, OCP_MOD,
 				  OMAP2_PRCM_IRQSTATUS_MPU_OFFSET);
 	if (l & 0x20)
-		prm_write_mod_reg(0x20, OCP_MOD,
+		omap2_prm_write_mod_reg(0x20, OCP_MOD,
 				  OMAP2_PRCM_IRQSTATUS_MPU_OFFSET);
 
 	/* Mask future PRCM-to-MPU interrupts */
-	prm_write_mod_reg(0x0, OCP_MOD, OMAP2_PRCM_IRQSTATUS_MPU_OFFSET);
+	omap2_prm_write_mod_reg(0x0, OCP_MOD, OMAP2_PRCM_IRQSTATUS_MPU_OFFSET);
 }
 
 static int omap2_i2c_active(void)
 {
 	u32 l;
 
-	l = cm_read_mod_reg(CORE_MOD, CM_FCLKEN1);
+	l = omap2_cm_read_mod_reg(CORE_MOD, CM_FCLKEN1);
 	return l & (OMAP2420_EN_I2C2_MASK | OMAP2420_EN_I2C1_MASK);
 }
 
@@ -201,13 +201,13 @@ static int omap2_allow_mpu_retention(voi
 	u32 l;
 
 	/* Check for MMC, UART2, UART1, McSPI2, McSPI1 and DSS1. */
-	l = cm_read_mod_reg(CORE_MOD, CM_FCLKEN1);
+	l = omap2_cm_read_mod_reg(CORE_MOD, CM_FCLKEN1);
 	if (l & (OMAP2420_EN_MMC_MASK | OMAP24XX_EN_UART2_MASK |
 		 OMAP24XX_EN_UART1_MASK | OMAP24XX_EN_MCSPI2_MASK |
 		 OMAP24XX_EN_MCSPI1_MASK | OMAP24XX_EN_DSS1_MASK))
 		return 0;
 	/* Check for UART3. */
-	l = cm_read_mod_reg(CORE_MOD, OMAP24XX_CM_FCLKEN2);
+	l = omap2_cm_read_mod_reg(CORE_MOD, OMAP24XX_CM_FCLKEN2);
 	if (l & OMAP24XX_EN_UART3_MASK)
 		return 0;
 	if (sti_console_enabled)
@@ -230,18 +230,18 @@ static void omap2_enter_mpu_retention(vo
 	 * it is in retention mode. */
 	if (omap2_allow_mpu_retention()) {
 		/* REVISIT: These write to reserved bits? */
-		prm_write_mod_reg(0xffffffff, CORE_MOD, PM_WKST1);
-		prm_write_mod_reg(0xffffffff, CORE_MOD, OMAP24XX_PM_WKST2);
-		prm_write_mod_reg(0xffffffff, WKUP_MOD, PM_WKST);
+		omap2_prm_write_mod_reg(0xffffffff, CORE_MOD, PM_WKST1);
+		omap2_prm_write_mod_reg(0xffffffff, CORE_MOD, OMAP24XX_PM_WKST2);
+		omap2_prm_write_mod_reg(0xffffffff, WKUP_MOD, PM_WKST);
 
 		/* Try to enter MPU retention */
-		prm_write_mod_reg((0x01 << OMAP_POWERSTATE_SHIFT) |
+		omap2_prm_write_mod_reg((0x01 << OMAP_POWERSTATE_SHIFT) |
 				  OMAP_LOGICRETSTATE_MASK,
 				  MPU_MOD, OMAP2_PM_PWSTCTRL);
 	} else {
 		/* Block MPU retention */
 
-		prm_write_mod_reg(OMAP_LOGICRETSTATE_MASK, MPU_MOD,
+		omap2_prm_write_mod_reg(OMAP_LOGICRETSTATE_MASK, MPU_MOD,
 						 OMAP2_PM_PWSTCTRL);
 		only_idle = 1;
 	}
@@ -299,16 +299,11 @@ out:
 	local_irq_enable();
 }
 
+#ifdef CONFIG_SUSPEND
 static int omap2_pm_begin(suspend_state_t state)
 {
-	suspend_state = state;
-	return 0;
-}
-
-static int omap2_pm_prepare(void)
-{
-	/* We cannot sleep in idle until we have resumed */
 	disable_hlt();
+	suspend_state = state;
 	return 0;
 }
 
@@ -316,9 +311,9 @@ static int omap2_pm_suspend(void)
 {
 	u32 wken_wkup, mir1;
 
-	wken_wkup = prm_read_mod_reg(WKUP_MOD, PM_WKEN);
+	wken_wkup = omap2_prm_read_mod_reg(WKUP_MOD, PM_WKEN);
 	wken_wkup &= ~OMAP24XX_EN_GPT1_MASK;
-	prm_write_mod_reg(wken_wkup, WKUP_MOD, PM_WKEN);
+	omap2_prm_write_mod_reg(wken_wkup, WKUP_MOD, PM_WKEN);
 
 	/* Mask GPT1 */
 	mir1 = omap_readl(0x480fe0a4);
@@ -328,7 +323,7 @@ static int omap2_pm_suspend(void)
 	omap2_enter_full_retention();
 
 	omap_writel(mir1, 0x480fe0a4);
-	prm_write_mod_reg(wken_wkup, WKUP_MOD, PM_WKEN);
+	omap2_prm_write_mod_reg(wken_wkup, WKUP_MOD, PM_WKEN);
 
 	return 0;
 }
@@ -349,24 +344,21 @@ static int omap2_pm_enter(suspend_state_
 	return ret;
 }
 
-static void omap2_pm_finish(void)
-{
-	enable_hlt();
-}
-
 static void omap2_pm_end(void)
 {
 	suspend_state = PM_SUSPEND_ON;
+	enable_hlt();
 }
 
-static struct platform_suspend_ops omap_pm_ops = {
+static const struct platform_suspend_ops omap_pm_ops = {
 	.begin		= omap2_pm_begin,
-	.prepare	= omap2_pm_prepare,
 	.enter		= omap2_pm_enter,
-	.finish		= omap2_pm_finish,
 	.end		= omap2_pm_end,
 	.valid		= suspend_valid_only_mem,
 };
+#else
+static const struct platform_suspend_ops __initdata omap_pm_ops;
+#endif /* CONFIG_SUSPEND */
 
 /* XXX This function should be shareable between OMAP2xxx and OMAP3 */
 static int __init clkdms_setup(struct clockdomain *clkdm, void *unused)
@@ -388,7 +380,7 @@ static void __init prcm_setup_regs(void)
 	struct powerdomain *pwrdm;
 
 	/* Enable autoidle */
-	prm_write_mod_reg(OMAP24XX_AUTOIDLE_MASK, OCP_MOD,
+	omap2_prm_write_mod_reg(OMAP24XX_AUTOIDLE_MASK, OCP_MOD,
 			  OMAP2_PRCM_SYSCONFIG_OFFSET);
 
 	/*
@@ -427,87 +419,87 @@ static void __init prcm_setup_regs(void)
 	clkdm_add_wkdep(mpu_clkdm, wkup_clkdm);
 
 	/* Enable clock autoidle for all domains */
-	cm_write_mod_reg(OMAP24XX_AUTO_CAM_MASK |
-			 OMAP24XX_AUTO_MAILBOXES_MASK |
-			 OMAP24XX_AUTO_WDT4_MASK |
-			 OMAP2420_AUTO_WDT3_MASK |
-			 OMAP24XX_AUTO_MSPRO_MASK |
-			 OMAP2420_AUTO_MMC_MASK |
-			 OMAP24XX_AUTO_FAC_MASK |
-			 OMAP2420_AUTO_EAC_MASK |
-			 OMAP24XX_AUTO_HDQ_MASK |
-			 OMAP24XX_AUTO_UART2_MASK |
-			 OMAP24XX_AUTO_UART1_MASK |
-			 OMAP24XX_AUTO_I2C2_MASK |
-			 OMAP24XX_AUTO_I2C1_MASK |
-			 OMAP24XX_AUTO_MCSPI2_MASK |
-			 OMAP24XX_AUTO_MCSPI1_MASK |
-			 OMAP24XX_AUTO_MCBSP2_MASK |
-			 OMAP24XX_AUTO_MCBSP1_MASK |
-			 OMAP24XX_AUTO_GPT12_MASK |
-			 OMAP24XX_AUTO_GPT11_MASK |
-			 OMAP24XX_AUTO_GPT10_MASK |
-			 OMAP24XX_AUTO_GPT9_MASK |
-			 OMAP24XX_AUTO_GPT8_MASK |
-			 OMAP24XX_AUTO_GPT7_MASK |
-			 OMAP24XX_AUTO_GPT6_MASK |
-			 OMAP24XX_AUTO_GPT5_MASK |
-			 OMAP24XX_AUTO_GPT4_MASK |
-			 OMAP24XX_AUTO_GPT3_MASK |
-			 OMAP24XX_AUTO_GPT2_MASK |
-			 OMAP2420_AUTO_VLYNQ_MASK |
-			 OMAP24XX_AUTO_DSS_MASK,
-			 CORE_MOD, CM_AUTOIDLE1);
-	cm_write_mod_reg(OMAP24XX_AUTO_UART3_MASK |
-			 OMAP24XX_AUTO_SSI_MASK |
-			 OMAP24XX_AUTO_USB_MASK,
-			 CORE_MOD, CM_AUTOIDLE2);
-	cm_write_mod_reg(OMAP24XX_AUTO_SDRC_MASK |
-			 OMAP24XX_AUTO_GPMC_MASK |
-			 OMAP24XX_AUTO_SDMA_MASK,
-			 CORE_MOD, CM_AUTOIDLE3);
-	cm_write_mod_reg(OMAP24XX_AUTO_PKA_MASK |
-			 OMAP24XX_AUTO_AES_MASK |
-			 OMAP24XX_AUTO_RNG_MASK |
-			 OMAP24XX_AUTO_SHA_MASK |
-			 OMAP24XX_AUTO_DES_MASK,
-			 CORE_MOD, OMAP24XX_CM_AUTOIDLE4);
+	omap2_cm_write_mod_reg(OMAP24XX_AUTO_CAM_MASK |
+			       OMAP24XX_AUTO_MAILBOXES_MASK |
+			       OMAP24XX_AUTO_WDT4_MASK |
+			       OMAP2420_AUTO_WDT3_MASK |
+			       OMAP24XX_AUTO_MSPRO_MASK |
+			       OMAP2420_AUTO_MMC_MASK |
+			       OMAP24XX_AUTO_FAC_MASK |
+			       OMAP2420_AUTO_EAC_MASK |
+			       OMAP24XX_AUTO_HDQ_MASK |
+			       OMAP24XX_AUTO_UART2_MASK |
+			       OMAP24XX_AUTO_UART1_MASK |
+			       OMAP24XX_AUTO_I2C2_MASK |
+			       OMAP24XX_AUTO_I2C1_MASK |
+			       OMAP24XX_AUTO_MCSPI2_MASK |
+			       OMAP24XX_AUTO_MCSPI1_MASK |
+			       OMAP24XX_AUTO_MCBSP2_MASK |
+			       OMAP24XX_AUTO_MCBSP1_MASK |
+			       OMAP24XX_AUTO_GPT12_MASK |
+			       OMAP24XX_AUTO_GPT11_MASK |
+			       OMAP24XX_AUTO_GPT10_MASK |
+			       OMAP24XX_AUTO_GPT9_MASK |
+			       OMAP24XX_AUTO_GPT8_MASK |
+			       OMAP24XX_AUTO_GPT7_MASK |
+			       OMAP24XX_AUTO_GPT6_MASK |
+			       OMAP24XX_AUTO_GPT5_MASK |
+			       OMAP24XX_AUTO_GPT4_MASK |
+			       OMAP24XX_AUTO_GPT3_MASK |
+			       OMAP24XX_AUTO_GPT2_MASK |
+			       OMAP2420_AUTO_VLYNQ_MASK |
+			       OMAP24XX_AUTO_DSS_MASK,
+			       CORE_MOD, CM_AUTOIDLE1);
+	omap2_cm_write_mod_reg(OMAP24XX_AUTO_UART3_MASK |
+			       OMAP24XX_AUTO_SSI_MASK |
+			       OMAP24XX_AUTO_USB_MASK,
+			       CORE_MOD, CM_AUTOIDLE2);
+	omap2_cm_write_mod_reg(OMAP24XX_AUTO_SDRC_MASK |
+			       OMAP24XX_AUTO_GPMC_MASK |
+			       OMAP24XX_AUTO_SDMA_MASK,
+			       CORE_MOD, CM_AUTOIDLE3);
+	omap2_cm_write_mod_reg(OMAP24XX_AUTO_PKA_MASK |
+			       OMAP24XX_AUTO_AES_MASK |
+			       OMAP24XX_AUTO_RNG_MASK |
+			       OMAP24XX_AUTO_SHA_MASK |
+			       OMAP24XX_AUTO_DES_MASK,
+			       CORE_MOD, OMAP24XX_CM_AUTOIDLE4);
 
-	cm_write_mod_reg(OMAP2420_AUTO_DSP_IPI_MASK, OMAP24XX_DSP_MOD,
-			 CM_AUTOIDLE);
+	omap2_cm_write_mod_reg(OMAP2420_AUTO_DSP_IPI_MASK, OMAP24XX_DSP_MOD,
+			       CM_AUTOIDLE);
 
 	/* Put DPLL and both APLLs into autoidle mode */
-	cm_write_mod_reg((0x03 << OMAP24XX_AUTO_DPLL_SHIFT) |
-			 (0x03 << OMAP24XX_AUTO_96M_SHIFT) |
-			 (0x03 << OMAP24XX_AUTO_54M_SHIFT),
-			 PLL_MOD, CM_AUTOIDLE);
+	omap2_cm_write_mod_reg((0x03 << OMAP24XX_AUTO_DPLL_SHIFT) |
+			       (0x03 << OMAP24XX_AUTO_96M_SHIFT) |
+			       (0x03 << OMAP24XX_AUTO_54M_SHIFT),
+			       PLL_MOD, CM_AUTOIDLE);
 
-	cm_write_mod_reg(OMAP24XX_AUTO_OMAPCTRL_MASK |
-			 OMAP24XX_AUTO_WDT1_MASK |
-			 OMAP24XX_AUTO_MPU_WDT_MASK |
-			 OMAP24XX_AUTO_GPIOS_MASK |
-			 OMAP24XX_AUTO_32KSYNC_MASK |
-			 OMAP24XX_AUTO_GPT1_MASK,
-			 WKUP_MOD, CM_AUTOIDLE);
+	omap2_cm_write_mod_reg(OMAP24XX_AUTO_OMAPCTRL_MASK |
+			       OMAP24XX_AUTO_WDT1_MASK |
+			       OMAP24XX_AUTO_MPU_WDT_MASK |
+			       OMAP24XX_AUTO_GPIOS_MASK |
+			       OMAP24XX_AUTO_32KSYNC_MASK |
+			       OMAP24XX_AUTO_GPT1_MASK,
+			       WKUP_MOD, CM_AUTOIDLE);
 
 	/* REVISIT: Configure number of 32 kHz clock cycles for sys_clk
 	 * stabilisation */
-	prm_write_mod_reg(15 << OMAP_SETUP_TIME_SHIFT, OMAP24XX_GR_MOD,
-			  OMAP2_PRCM_CLKSSETUP_OFFSET);
+	omap2_prm_write_mod_reg(15 << OMAP_SETUP_TIME_SHIFT, OMAP24XX_GR_MOD,
+				OMAP2_PRCM_CLKSSETUP_OFFSET);
 
 	/* Configure automatic voltage transition */
-	prm_write_mod_reg(2 << OMAP_SETUP_TIME_SHIFT, OMAP24XX_GR_MOD,
-			  OMAP2_PRCM_VOLTSETUP_OFFSET);
-	prm_write_mod_reg(OMAP24XX_AUTO_EXTVOLT_MASK |
-			  (0x1 << OMAP24XX_SETOFF_LEVEL_SHIFT) |
-			  OMAP24XX_MEMRETCTRL_MASK |
-			  (0x1 << OMAP24XX_SETRET_LEVEL_SHIFT) |
-			  (0x0 << OMAP24XX_VOLT_LEVEL_SHIFT),
-			  OMAP24XX_GR_MOD, OMAP2_PRCM_VOLTCTRL_OFFSET);
+	omap2_prm_write_mod_reg(2 << OMAP_SETUP_TIME_SHIFT, OMAP24XX_GR_MOD,
+				OMAP2_PRCM_VOLTSETUP_OFFSET);
+	omap2_prm_write_mod_reg(OMAP24XX_AUTO_EXTVOLT_MASK |
+				(0x1 << OMAP24XX_SETOFF_LEVEL_SHIFT) |
+				OMAP24XX_MEMRETCTRL_MASK |
+				(0x1 << OMAP24XX_SETRET_LEVEL_SHIFT) |
+				(0x0 << OMAP24XX_VOLT_LEVEL_SHIFT),
+				OMAP24XX_GR_MOD, OMAP2_PRCM_VOLTCTRL_OFFSET);
 
 	/* Enable wake-up events */
-	prm_write_mod_reg(OMAP24XX_EN_GPIOS_MASK | OMAP24XX_EN_GPT1_MASK,
-			  WKUP_MOD, PM_WKEN);
+	omap2_prm_write_mod_reg(OMAP24XX_EN_GPIOS_MASK | OMAP24XX_EN_GPT1_MASK,
+				WKUP_MOD, PM_WKEN);
 }
 
 static int __init omap2_pm_init(void)
@@ -518,7 +510,7 @@ static int __init omap2_pm_init(void)
 		return -ENODEV;
 
 	printk(KERN_INFO "Power Management for OMAP2 initializing\n");
-	l = prm_read_mod_reg(OCP_MOD, OMAP2_PRCM_REVISION_OFFSET);
+	l = omap2_prm_read_mod_reg(OCP_MOD, OMAP2_PRCM_REVISION_OFFSET);
 	printk(KERN_INFO "PRCM revision %d.%d\n", (l >> 4) & 0x0f, l & 0x0f);
 
 	/* Look up important powerdomains */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/pm34xx.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/pm34xx.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/pm34xx.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/pm34xx.c	2011-03-14 21:20:32.000000000 -0400
@@ -31,8 +31,8 @@
 #include <linux/console.h>
 
 #include <plat/sram.h>
-#include <plat/clockdomain.h>
-#include <plat/powerdomain.h>
+#include "clockdomain.h"
+#include "powerdomain.h"
 #include <plat/serial.h>
 #include <plat/sdrc.h>
 #include <plat/prcm.h>
@@ -41,11 +41,11 @@
 
 #include <asm/tlbflush.h>
 
-#include "cm.h"
+#include "cm2xxx_3xxx.h"
 #include "cm-regbits-34xx.h"
 #include "prm-regbits-34xx.h"
 
-#include "prm.h"
+#include "prm2xxx_3xxx.h"
 #include "pm.h"
 #include "sdrc.h"
 #include "control.h"
@@ -68,6 +68,9 @@ static inline bool is_suspending(void)
 #define OMAP343X_TABLE_VALUE_OFFSET	   0xc0
 #define OMAP343X_CONTROL_REG_VALUE_OFFSET  0xc8
 
+/* pm34xx errata defined in pm.h */
+u16 pm34xx_errata;
+
 struct power_state {
 	struct powerdomain *pwrdm;
 	u32 next_state;
@@ -102,12 +105,12 @@ static void omap3_enable_io_chain(void)
 	int timeout = 0;
 
 	if (omap_rev() >= OMAP3430_REV_ES3_1) {
-		prm_set_mod_reg_bits(OMAP3430_EN_IO_CHAIN_MASK, WKUP_MOD,
+		omap2_prm_set_mod_reg_bits(OMAP3430_EN_IO_CHAIN_MASK, WKUP_MOD,
 				     PM_WKEN);
 		/* Do a readback to assure write has been done */
-		prm_read_mod_reg(WKUP_MOD, PM_WKEN);
+		omap2_prm_read_mod_reg(WKUP_MOD, PM_WKEN);
 
-		while (!(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) {
@@ -115,7 +118,7 @@ static void omap3_enable_io_chain(void)
 				       "activation failed.\n");
 				return;
 			}
-			prm_set_mod_reg_bits(OMAP3430_ST_IO_CHAIN_MASK,
+			omap2_prm_set_mod_reg_bits(OMAP3430_ST_IO_CHAIN_MASK,
 					     WKUP_MOD, PM_WKEN);
 		}
 	}
@@ -124,26 +127,17 @@ static void omap3_enable_io_chain(void)
 static void omap3_disable_io_chain(void)
 {
 	if (omap_rev() >= OMAP3430_REV_ES3_1)
-		prm_clear_mod_reg_bits(OMAP3430_EN_IO_CHAIN_MASK, WKUP_MOD,
+		omap2_prm_clear_mod_reg_bits(OMAP3430_EN_IO_CHAIN_MASK, WKUP_MOD,
 				       PM_WKEN);
 }
 
 static void omap3_core_save_context(void)
 {
-	u32 control_padconf_off;
-
-	/* Save the padconf registers */
-	control_padconf_off = omap_ctrl_readl(OMAP343X_CONTROL_PADCONF_OFF);
-	control_padconf_off |= START_PADCONF_SAVE;
-	omap_ctrl_writel(control_padconf_off, OMAP343X_CONTROL_PADCONF_OFF);
-	/* wait for the save to complete */
-	while (!(omap_ctrl_readl(OMAP343X_CONTROL_GENERAL_PURPOSE_STATUS)
-			& PADCONF_SAVE_DONE))
-		udelay(1);
+	omap3_ctrl_save_padconf();
 
 	/*
 	 * Force write last pad into memory, as this can fail in some
-	 * cases according to erratas 1.157, 1.185
+	 * cases according to errata 1.157, 1.185
 	 */
 	omap_ctrl_writel(omap_ctrl_readl(OMAP343X_PADCONF_ETK_D14),
 		OMAP343X_CONTROL_MEM_WKUP + 0x2a0);
@@ -174,9 +168,10 @@ static void omap3_core_restore_context(v
  * once during boot sequence, but this works as we are not using secure
  * services.
  */
-static void omap3_save_secure_ram_context(u32 target_mpu_state)
+static void omap3_save_secure_ram_context(void)
 {
 	u32 ret;
+	int mpu_next_state = pwrdm_read_next_pwrst(mpu_pwrdm);
 
 	if (omap_type() != OMAP2_DEVICE_TYPE_GP) {
 		/*
@@ -187,7 +182,7 @@ static void omap3_save_secure_ram_contex
 		pwrdm_set_next_pwrst(mpu_pwrdm, PWRDM_POWER_ON);
 		ret = _omap_save_secure_sram((u32 *)
 				__pa(omap3_secure_ram_storage));
-		pwrdm_set_next_pwrst(mpu_pwrdm, target_mpu_state);
+		pwrdm_set_next_pwrst(mpu_pwrdm, mpu_next_state);
 		/* Following is for error tracking, it should not happen */
 		if (ret) {
 			printk(KERN_ERR "save_secure_sram() returns %08x\n",
@@ -218,27 +213,27 @@ static int prcm_clear_mod_irqs(s16 modul
 		OMAP3430ES2_PM_MPUGRPSEL3 : OMAP3430_PM_MPUGRPSEL;
 	int c = 0;
 
-	wkst = prm_read_mod_reg(module, wkst_off);
-	wkst &= prm_read_mod_reg(module, grpsel_off);
+	wkst = omap2_prm_read_mod_reg(module, wkst_off);
+	wkst &= omap2_prm_read_mod_reg(module, grpsel_off);
 	if (wkst) {
-		iclk = cm_read_mod_reg(module, iclk_off);
-		fclk = cm_read_mod_reg(module, fclk_off);
+		iclk = omap2_cm_read_mod_reg(module, iclk_off);
+		fclk = omap2_cm_read_mod_reg(module, fclk_off);
 		while (wkst) {
 			clken = wkst;
-			cm_set_mod_reg_bits(clken, module, iclk_off);
+			omap2_cm_set_mod_reg_bits(clken, module, iclk_off);
 			/*
 			 * For USBHOST, we don't know whether HOST1 or
 			 * HOST2 woke us up, so enable both f-clocks
 			 */
 			if (module == OMAP3430ES2_USBHOST_MOD)
 				clken |= 1 << OMAP3430ES2_EN_USBHOST2_SHIFT;
-			cm_set_mod_reg_bits(clken, module, fclk_off);
-			prm_write_mod_reg(wkst, module, wkst_off);
-			wkst = prm_read_mod_reg(module, wkst_off);
+			omap2_cm_set_mod_reg_bits(clken, module, fclk_off);
+			omap2_prm_write_mod_reg(wkst, module, wkst_off);
+			wkst = omap2_prm_read_mod_reg(module, wkst_off);
 			c++;
 		}
-		cm_write_mod_reg(iclk, module, iclk_off);
-		cm_write_mod_reg(fclk, module, fclk_off);
+		omap2_cm_write_mod_reg(iclk, module, iclk_off);
+		omap2_cm_write_mod_reg(fclk, module, fclk_off);
 	}
 
 	return c;
@@ -281,9 +276,9 @@ static irqreturn_t prcm_interrupt_handle
 	u32 irqenable_mpu, irqstatus_mpu;
 	int c = 0;
 
-	irqenable_mpu = prm_read_mod_reg(OCP_MOD,
+	irqenable_mpu = omap2_prm_read_mod_reg(OCP_MOD,
 					 OMAP3_PRM_IRQENABLE_MPU_OFFSET);
-	irqstatus_mpu = prm_read_mod_reg(OCP_MOD,
+	irqstatus_mpu = omap2_prm_read_mod_reg(OCP_MOD,
 					 OMAP3_PRM_IRQSTATUS_MPU_OFFSET);
 	irqstatus_mpu &= irqenable_mpu;
 
@@ -304,10 +299,10 @@ static irqreturn_t prcm_interrupt_handle
 			     "no code to handle it (%08x)\n", irqstatus_mpu);
 		}
 
-		prm_write_mod_reg(irqstatus_mpu, OCP_MOD,
+		omap2_prm_write_mod_reg(irqstatus_mpu, OCP_MOD,
 					OMAP3_PRM_IRQSTATUS_MPU_OFFSET);
 
-		irqstatus_mpu = prm_read_mod_reg(OCP_MOD,
+		irqstatus_mpu = omap2_prm_read_mod_reg(OCP_MOD,
 					OMAP3_PRM_IRQSTATUS_MPU_OFFSET);
 		irqstatus_mpu &= irqenable_mpu;
 
@@ -357,6 +352,7 @@ void omap_sram_idle(void)
 	int mpu_next_state = PWRDM_POWER_ON;
 	int per_next_state = PWRDM_POWER_ON;
 	int core_next_state = PWRDM_POWER_ON;
+	int per_going_off;
 	int core_prev_state, per_prev_state;
 	u32 sdrc_pwr = 0;
 
@@ -395,7 +391,7 @@ void omap_sram_idle(void)
 	if (omap3_has_io_wakeup() &&
 	    (per_next_state < PWRDM_POWER_ON ||
 	     core_next_state < PWRDM_POWER_ON)) {
-		prm_set_mod_reg_bits(OMAP3430_EN_IO_MASK, WKUP_MOD, PM_WKEN);
+		omap2_prm_set_mod_reg_bits(OMAP3430_EN_IO_MASK, WKUP_MOD, PM_WKEN);
 		omap3_enable_io_chain();
 	}
 
@@ -403,14 +399,15 @@ void omap_sram_idle(void)
 	if (!is_suspending())
 		if (per_next_state < PWRDM_POWER_ON ||
 		    core_next_state < PWRDM_POWER_ON)
-			if (try_acquire_console_sem())
+			if (!console_trylock())
 				goto console_still_active;
 
 	/* PER */
 	if (per_next_state < PWRDM_POWER_ON) {
+		per_going_off = (per_next_state == PWRDM_POWER_OFF) ? 1 : 0;
 		omap_uart_prepare_idle(2);
 		omap_uart_prepare_idle(3);
-		omap2_gpio_prepare_for_idle(per_next_state);
+		omap2_gpio_prepare_for_idle(per_going_off);
 		if (per_next_state == PWRDM_POWER_OFF)
 				omap3_per_save_context();
 	}
@@ -421,7 +418,7 @@ void omap_sram_idle(void)
 		omap_uart_prepare_idle(1);
 		if (core_next_state == PWRDM_POWER_OFF) {
 			omap3_core_save_context();
-			omap3_prcm_save_context();
+			omap3_cm_save_context();
 		}
 	}
 
@@ -430,7 +427,7 @@ void omap_sram_idle(void)
 	/*
 	* 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 errata 1.142.
+	* 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 &&
@@ -461,14 +458,14 @@ void omap_sram_idle(void)
 		core_prev_state = pwrdm_read_prev_pwrst(core_pwrdm);
 		if (core_prev_state == PWRDM_POWER_OFF) {
 			omap3_core_restore_context();
-			omap3_prcm_restore_context();
+			omap3_cm_restore_context();
 			omap3_sram_restore_context();
 			omap2_sms_restore_context();
 		}
 		omap_uart_resume_idle(0);
 		omap_uart_resume_idle(1);
 		if (core_next_state == PWRDM_POWER_OFF)
-			prm_clear_mod_reg_bits(OMAP3430_AUTO_OFF_MASK,
+			omap2_prm_clear_mod_reg_bits(OMAP3430_AUTO_OFF_MASK,
 					       OMAP3430_GR_MOD,
 					       OMAP3_PRM_VOLTCTRL_OFFSET);
 	}
@@ -485,14 +482,15 @@ void omap_sram_idle(void)
 	}
 
 	if (!is_suspending())
-		release_console_sem();
+		console_unlock();
 
 console_still_active:
 	/* Disable IO-PAD and IO-CHAIN wakeup */
 	if (omap3_has_io_wakeup() &&
 	    (per_next_state < PWRDM_POWER_ON ||
 	     core_next_state < PWRDM_POWER_ON)) {
-		prm_clear_mod_reg_bits(OMAP3430_EN_IO_MASK, WKUP_MOD, PM_WKEN);
+		omap2_prm_clear_mod_reg_bits(OMAP3430_EN_IO_MASK, WKUP_MOD,
+					     PM_WKEN);
 		omap3_disable_io_chain();
 	}
 
@@ -529,12 +527,6 @@ out:
 }
 
 #ifdef CONFIG_SUSPEND
-static int omap3_pm_prepare(void)
-{
-	disable_hlt();
-	return 0;
-}
-
 static int omap3_pm_suspend(void)
 {
 	struct power_state *pwrst;
@@ -597,14 +589,10 @@ static int omap3_pm_enter(suspend_state_
 	return ret;
 }
 
-static void omap3_pm_finish(void)
-{
-	enable_hlt();
-}
-
 /* Hooks to enable / disable UART interrupts during suspend */
 static int omap3_pm_begin(suspend_state_t state)
 {
+	disable_hlt();
 	suspend_state = state;
 	omap_uart_enable_irqs(0);
 	return 0;
@@ -614,15 +602,14 @@ static void omap3_pm_end(void)
 {
 	suspend_state = PM_SUSPEND_ON;
 	omap_uart_enable_irqs(1);
+	enable_hlt();
 	return;
 }
 
-static struct platform_suspend_ops omap_pm_ops = {
+static const struct platform_suspend_ops omap_pm_ops = {
 	.begin		= omap3_pm_begin,
 	.end		= omap3_pm_end,
-	.prepare	= omap3_pm_prepare,
 	.enter		= omap3_pm_enter,
-	.finish		= omap3_pm_finish,
 	.valid		= suspend_valid_only_mem,
 };
 #endif /* CONFIG_SUSPEND */
@@ -641,21 +628,21 @@ static struct platform_suspend_ops omap_
 static void __init omap3_iva_idle(void)
 {
 	/* ensure IVA2 clock is disabled */
-	cm_write_mod_reg(0, OMAP3430_IVA2_MOD, CM_FCLKEN);
+	omap2_cm_write_mod_reg(0, OMAP3430_IVA2_MOD, CM_FCLKEN);
 
 	/* if no clock activity, nothing else to do */
-	if (!(cm_read_mod_reg(OMAP3430_IVA2_MOD, OMAP3430_CM_CLKSTST) &
+	if (!(omap2_cm_read_mod_reg(OMAP3430_IVA2_MOD, OMAP3430_CM_CLKSTST) &
 	      OMAP3430_CLKACTIVITY_IVA2_MASK))
 		return;
 
 	/* Reset IVA2 */
-	prm_write_mod_reg(OMAP3430_RST1_IVA2_MASK |
+	omap2_prm_write_mod_reg(OMAP3430_RST1_IVA2_MASK |
 			  OMAP3430_RST2_IVA2_MASK |
 			  OMAP3430_RST3_IVA2_MASK,
 			  OMAP3430_IVA2_MOD, OMAP2_RM_RSTCTRL);
 
 	/* Enable IVA2 clock */
-	cm_write_mod_reg(OMAP3430_CM_FCLKEN_IVA2_EN_IVA2_MASK,
+	omap2_cm_write_mod_reg(OMAP3430_CM_FCLKEN_IVA2_EN_IVA2_MASK,
 			 OMAP3430_IVA2_MOD, CM_FCLKEN);
 
 	/* Set IVA2 boot mode to 'idle' */
@@ -663,13 +650,13 @@ static void __init omap3_iva_idle(void)
 			 OMAP343X_CONTROL_IVA2_BOOTMOD);
 
 	/* Un-reset IVA2 */
-	prm_write_mod_reg(0, OMAP3430_IVA2_MOD, OMAP2_RM_RSTCTRL);
+	omap2_prm_write_mod_reg(0, OMAP3430_IVA2_MOD, OMAP2_RM_RSTCTRL);
 
 	/* Disable IVA2 clock */
-	cm_write_mod_reg(0, OMAP3430_IVA2_MOD, CM_FCLKEN);
+	omap2_cm_write_mod_reg(0, OMAP3430_IVA2_MOD, CM_FCLKEN);
 
 	/* Reset IVA2 */
-	prm_write_mod_reg(OMAP3430_RST1_IVA2_MASK |
+	omap2_prm_write_mod_reg(OMAP3430_RST1_IVA2_MASK |
 			  OMAP3430_RST2_IVA2_MASK |
 			  OMAP3430_RST3_IVA2_MASK,
 			  OMAP3430_IVA2_MOD, OMAP2_RM_RSTCTRL);
@@ -693,10 +680,10 @@ static void __init omap3_d2d_idle(void)
 	omap_ctrl_writew(padconf, OMAP3_PADCONF_SAD2D_IDLEACK);
 
 	/* reset modem */
-	prm_write_mod_reg(OMAP3430_RM_RSTCTRL_CORE_MODEM_SW_RSTPWRON_MASK |
+	omap2_prm_write_mod_reg(OMAP3430_RM_RSTCTRL_CORE_MODEM_SW_RSTPWRON_MASK |
 			  OMAP3430_RM_RSTCTRL_CORE_MODEM_SW_RST_MASK,
 			  CORE_MOD, OMAP2_RM_RSTCTRL);
-	prm_write_mod_reg(0, CORE_MOD, OMAP2_RM_RSTCTRL);
+	omap2_prm_write_mod_reg(0, CORE_MOD, OMAP2_RM_RSTCTRL);
 }
 
 static void __init prcm_setup_regs(void)
@@ -711,23 +698,23 @@ static void __init prcm_setup_regs(void)
 
 	/* XXX Reset all wkdeps. This should be done when initializing
 	 * powerdomains */
-	prm_write_mod_reg(0, OMAP3430_IVA2_MOD, PM_WKDEP);
-	prm_write_mod_reg(0, MPU_MOD, PM_WKDEP);
-	prm_write_mod_reg(0, OMAP3430_DSS_MOD, PM_WKDEP);
-	prm_write_mod_reg(0, OMAP3430_NEON_MOD, PM_WKDEP);
-	prm_write_mod_reg(0, OMAP3430_CAM_MOD, PM_WKDEP);
-	prm_write_mod_reg(0, OMAP3430_PER_MOD, PM_WKDEP);
+	omap2_prm_write_mod_reg(0, OMAP3430_IVA2_MOD, PM_WKDEP);
+	omap2_prm_write_mod_reg(0, MPU_MOD, PM_WKDEP);
+	omap2_prm_write_mod_reg(0, OMAP3430_DSS_MOD, PM_WKDEP);
+	omap2_prm_write_mod_reg(0, OMAP3430_NEON_MOD, PM_WKDEP);
+	omap2_prm_write_mod_reg(0, OMAP3430_CAM_MOD, PM_WKDEP);
+	omap2_prm_write_mod_reg(0, OMAP3430_PER_MOD, PM_WKDEP);
 	if (omap_rev() > OMAP3430_REV_ES1_0) {
-		prm_write_mod_reg(0, OMAP3430ES2_SGX_MOD, PM_WKDEP);
-		prm_write_mod_reg(0, OMAP3430ES2_USBHOST_MOD, PM_WKDEP);
+		omap2_prm_write_mod_reg(0, OMAP3430ES2_SGX_MOD, PM_WKDEP);
+		omap2_prm_write_mod_reg(0, OMAP3430ES2_USBHOST_MOD, PM_WKDEP);
 	} else
-		prm_write_mod_reg(0, GFX_MOD, PM_WKDEP);
+		omap2_prm_write_mod_reg(0, GFX_MOD, PM_WKDEP);
 
 	/*
 	 * Enable interface clock autoidle for all modules.
 	 * Note that in the long run this should be done by clockfw
 	 */
-	cm_write_mod_reg(
+	omap2_cm_write_mod_reg(
 		OMAP3430_AUTO_MODEM_MASK |
 		OMAP3430ES2_AUTO_MMC3_MASK |
 		OMAP3430ES2_AUTO_ICR_MASK |
@@ -760,7 +747,7 @@ static void __init prcm_setup_regs(void)
 		OMAP3430_AUTO_SSI_MASK,
 		CORE_MOD, CM_AUTOIDLE1);
 
-	cm_write_mod_reg(
+	omap2_cm_write_mod_reg(
 		OMAP3430_AUTO_PKA_MASK |
 		OMAP3430_AUTO_AES1_MASK |
 		OMAP3430_AUTO_RNG_MASK |
@@ -769,13 +756,13 @@ static void __init prcm_setup_regs(void)
 		CORE_MOD, CM_AUTOIDLE2);
 
 	if (omap_rev() > OMAP3430_REV_ES1_0) {
-		cm_write_mod_reg(
+		omap2_cm_write_mod_reg(
 			OMAP3430_AUTO_MAD2D_MASK |
 			OMAP3430ES2_AUTO_USBTLL_MASK,
 			CORE_MOD, CM_AUTOIDLE3);
 	}
 
-	cm_write_mod_reg(
+	omap2_cm_write_mod_reg(
 		OMAP3430_AUTO_WDT2_MASK |
 		OMAP3430_AUTO_WDT1_MASK |
 		OMAP3430_AUTO_GPIO1_MASK |
@@ -784,17 +771,17 @@ static void __init prcm_setup_regs(void)
 		OMAP3430_AUTO_GPT1_MASK,
 		WKUP_MOD, CM_AUTOIDLE);
 
-	cm_write_mod_reg(
+	omap2_cm_write_mod_reg(
 		OMAP3430_AUTO_DSS_MASK,
 		OMAP3430_DSS_MOD,
 		CM_AUTOIDLE);
 
-	cm_write_mod_reg(
+	omap2_cm_write_mod_reg(
 		OMAP3430_AUTO_CAM_MASK,
 		OMAP3430_CAM_MOD,
 		CM_AUTOIDLE);
 
-	cm_write_mod_reg(
+	omap2_cm_write_mod_reg(
 		omap3630_auto_uart4_mask |
 		OMAP3430_AUTO_GPIO6_MASK |
 		OMAP3430_AUTO_GPIO5_MASK |
@@ -818,7 +805,7 @@ static void __init prcm_setup_regs(void)
 		CM_AUTOIDLE);
 
 	if (omap_rev() > OMAP3430_REV_ES1_0) {
-		cm_write_mod_reg(
+		omap2_cm_write_mod_reg(
 			OMAP3430ES2_AUTO_USBHOST_MASK,
 			OMAP3430ES2_USBHOST_MOD,
 			CM_AUTOIDLE);
@@ -830,16 +817,16 @@ static void __init prcm_setup_regs(void)
 	 * Set all plls to autoidle. This is needed until autoidle is
 	 * enabled by clockfw
 	 */
-	cm_write_mod_reg(1 << OMAP3430_AUTO_IVA2_DPLL_SHIFT,
+	omap2_cm_write_mod_reg(1 << OMAP3430_AUTO_IVA2_DPLL_SHIFT,
 			 OMAP3430_IVA2_MOD, CM_AUTOIDLE2);
-	cm_write_mod_reg(1 << OMAP3430_AUTO_MPU_DPLL_SHIFT,
+	omap2_cm_write_mod_reg(1 << OMAP3430_AUTO_MPU_DPLL_SHIFT,
 			 MPU_MOD,
 			 CM_AUTOIDLE2);
-	cm_write_mod_reg((1 << OMAP3430_AUTO_PERIPH_DPLL_SHIFT) |
+	omap2_cm_write_mod_reg((1 << OMAP3430_AUTO_PERIPH_DPLL_SHIFT) |
 			 (1 << OMAP3430_AUTO_CORE_DPLL_SHIFT),
 			 PLL_MOD,
 			 CM_AUTOIDLE);
-	cm_write_mod_reg(1 << OMAP3430ES2_AUTO_PERIPH2_DPLL_SHIFT,
+	omap2_cm_write_mod_reg(1 << OMAP3430ES2_AUTO_PERIPH2_DPLL_SHIFT,
 			 PLL_MOD,
 			 CM_AUTOIDLE2);
 
@@ -848,31 +835,31 @@ static void __init prcm_setup_regs(void)
 	 * sys_clkreq. In the long run clock framework should
 	 * take care of this.
 	 */
-	prm_rmw_mod_reg_bits(OMAP_AUTOEXTCLKMODE_MASK,
+	omap2_prm_rmw_mod_reg_bits(OMAP_AUTOEXTCLKMODE_MASK,
 			     1 << OMAP_AUTOEXTCLKMODE_SHIFT,
 			     OMAP3430_GR_MOD,
 			     OMAP3_PRM_CLKSRC_CTRL_OFFSET);
 
 	/* setup wakup source */
-	prm_write_mod_reg(OMAP3430_EN_IO_MASK | OMAP3430_EN_GPIO1_MASK |
+	omap2_prm_write_mod_reg(OMAP3430_EN_IO_MASK | OMAP3430_EN_GPIO1_MASK |
 			  OMAP3430_EN_GPT1_MASK | OMAP3430_EN_GPT12_MASK,
 			  WKUP_MOD, PM_WKEN);
 	/* No need to write EN_IO, that is always enabled */
-	prm_write_mod_reg(OMAP3430_GRPSEL_GPIO1_MASK |
+	omap2_prm_write_mod_reg(OMAP3430_GRPSEL_GPIO1_MASK |
 			  OMAP3430_GRPSEL_GPT1_MASK |
 			  OMAP3430_GRPSEL_GPT12_MASK,
 			  WKUP_MOD, OMAP3430_PM_MPUGRPSEL);
 	/* For some reason IO doesn't generate wakeup event even if
 	 * it is selected to mpu wakeup goup */
-	prm_write_mod_reg(OMAP3430_IO_EN_MASK | OMAP3430_WKUP_EN_MASK,
+	omap2_prm_write_mod_reg(OMAP3430_IO_EN_MASK | OMAP3430_WKUP_EN_MASK,
 			  OCP_MOD, OMAP3_PRM_IRQENABLE_MPU_OFFSET);
 
 	/* Enable PM_WKEN to support DSS LPR */
-	prm_write_mod_reg(OMAP3430_PM_WKEN_DSS_EN_DSS_MASK,
+	omap2_prm_write_mod_reg(OMAP3430_PM_WKEN_DSS_EN_DSS_MASK,
 				OMAP3430_DSS_MOD, PM_WKEN);
 
 	/* Enable wakeups in PER */
-	prm_write_mod_reg(omap3630_en_uart4_mask |
+	omap2_prm_write_mod_reg(omap3630_en_uart4_mask |
 			  OMAP3430_EN_GPIO2_MASK | OMAP3430_EN_GPIO3_MASK |
 			  OMAP3430_EN_GPIO4_MASK | OMAP3430_EN_GPIO5_MASK |
 			  OMAP3430_EN_GPIO6_MASK | OMAP3430_EN_UART3_MASK |
@@ -880,7 +867,7 @@ static void __init prcm_setup_regs(void)
 			  OMAP3430_EN_MCBSP4_MASK,
 			  OMAP3430_PER_MOD, PM_WKEN);
 	/* and allow them to wake up MPU */
-	prm_write_mod_reg(omap3630_grpsel_uart4_mask |
+	omap2_prm_write_mod_reg(omap3630_grpsel_uart4_mask |
 			  OMAP3430_GRPSEL_GPIO2_MASK |
 			  OMAP3430_GRPSEL_GPIO3_MASK |
 			  OMAP3430_GRPSEL_GPIO4_MASK |
@@ -893,22 +880,22 @@ static void __init prcm_setup_regs(void)
 			  OMAP3430_PER_MOD, OMAP3430_PM_MPUGRPSEL);
 
 	/* Don't attach IVA interrupts */
-	prm_write_mod_reg(0, WKUP_MOD, OMAP3430_PM_IVAGRPSEL);
-	prm_write_mod_reg(0, CORE_MOD, OMAP3430_PM_IVAGRPSEL1);
-	prm_write_mod_reg(0, CORE_MOD, OMAP3430ES2_PM_IVAGRPSEL3);
-	prm_write_mod_reg(0, OMAP3430_PER_MOD, OMAP3430_PM_IVAGRPSEL);
+	omap2_prm_write_mod_reg(0, WKUP_MOD, OMAP3430_PM_IVAGRPSEL);
+	omap2_prm_write_mod_reg(0, CORE_MOD, OMAP3430_PM_IVAGRPSEL1);
+	omap2_prm_write_mod_reg(0, CORE_MOD, OMAP3430ES2_PM_IVAGRPSEL3);
+	omap2_prm_write_mod_reg(0, OMAP3430_PER_MOD, OMAP3430_PM_IVAGRPSEL);
 
 	/* Clear any pending 'reset' flags */
-	prm_write_mod_reg(0xffffffff, MPU_MOD, OMAP2_RM_RSTST);
-	prm_write_mod_reg(0xffffffff, CORE_MOD, OMAP2_RM_RSTST);
-	prm_write_mod_reg(0xffffffff, OMAP3430_PER_MOD, OMAP2_RM_RSTST);
-	prm_write_mod_reg(0xffffffff, OMAP3430_EMU_MOD, OMAP2_RM_RSTST);
-	prm_write_mod_reg(0xffffffff, OMAP3430_NEON_MOD, OMAP2_RM_RSTST);
-	prm_write_mod_reg(0xffffffff, OMAP3430_DSS_MOD, OMAP2_RM_RSTST);
-	prm_write_mod_reg(0xffffffff, OMAP3430ES2_USBHOST_MOD, OMAP2_RM_RSTST);
+	omap2_prm_write_mod_reg(0xffffffff, MPU_MOD, OMAP2_RM_RSTST);
+	omap2_prm_write_mod_reg(0xffffffff, CORE_MOD, OMAP2_RM_RSTST);
+	omap2_prm_write_mod_reg(0xffffffff, OMAP3430_PER_MOD, OMAP2_RM_RSTST);
+	omap2_prm_write_mod_reg(0xffffffff, OMAP3430_EMU_MOD, OMAP2_RM_RSTST);
+	omap2_prm_write_mod_reg(0xffffffff, OMAP3430_NEON_MOD, OMAP2_RM_RSTST);
+	omap2_prm_write_mod_reg(0xffffffff, OMAP3430_DSS_MOD, OMAP2_RM_RSTST);
+	omap2_prm_write_mod_reg(0xffffffff, OMAP3430ES2_USBHOST_MOD, OMAP2_RM_RSTST);
 
 	/* Clear any pending PRCM interrupts */
-	prm_write_mod_reg(0, OCP_MOD, OMAP3_PRM_IRQSTATUS_MPU_OFFSET);
+	omap2_prm_write_mod_reg(0, OCP_MOD, OMAP3_PRM_IRQSTATUS_MPU_OFFSET);
 
 	omap3_iva_idle();
 	omap3_d2d_idle();
@@ -925,12 +912,29 @@ void omap3_pm_off_mode_enable(int enable
 		state = PWRDM_POWER_RET;
 
 #ifdef CONFIG_CPU_IDLE
-	omap3_cpuidle_update_states();
+	/*
+	 * Erratum i583: implementation for ES rev < Es1.2 on 3630. We cannot
+	 * enable OFF mode in a stable form for previous revisions, restrict
+	 * instead to RET
+	 */
+	if (IS_PM34XX_ERRATUM(PM_SDRC_WAKEUP_ERRATUM_i583))
+		omap3_cpuidle_update_states(state, PWRDM_POWER_RET);
+	else
+		omap3_cpuidle_update_states(state, state);
 #endif
 
 	list_for_each_entry(pwrst, &pwrst_list, node) {
-		pwrst->next_state = state;
-		omap_set_pwrdm_state(pwrst->pwrdm, state);
+		if (IS_PM34XX_ERRATUM(PM_SDRC_WAKEUP_ERRATUM_i583) &&
+				pwrst->pwrdm == core_pwrdm &&
+				state == PWRDM_POWER_OFF) {
+			pwrst->next_state = PWRDM_POWER_RET;
+			WARN_ONCE(1,
+				"%s: Core OFF disabled due to errata i583\n",
+				__func__);
+		} else {
+			pwrst->next_state = state;
+		}
+		omap_set_pwrdm_state(pwrst->pwrdm, pwrst->next_state);
 	}
 }
 
@@ -1002,6 +1006,17 @@ void omap_push_sram_idle(void)
 				save_secure_ram_context_sz);
 }
 
+static void __init pm_errata_configure(void)
+{
+	if (cpu_is_omap3630()) {
+		pm34xx_errata |= PM_RTA_ERRATUM_i608;
+		/* Enable the l2 cache toggling in sleep logic */
+		enable_omap3630_toggle_l2_on_restore();
+		if (omap_rev() < OMAP3630_REV_ES1_2)
+			pm34xx_errata |= PM_SDRC_WAKEUP_ERRATUM_i583;
+	}
+}
+
 static int __init omap3_pm_init(void)
 {
 	struct power_state *pwrst, *tmp;
@@ -1011,6 +1026,8 @@ static int __init omap3_pm_init(void)
 	if (!cpu_is_omap34xx())
 		return -ENODEV;
 
+	pm_errata_configure();
+
 	printk(KERN_ERR "Power Management for TI OMAP3.\n");
 
 	/* XXX prcm_setup_regs needs to be before enabling hw
@@ -1058,6 +1075,14 @@ static int __init omap3_pm_init(void)
 	pm_idle = omap3_pm_idle;
 	omap3_idle_init();
 
+	/*
+	 * RTA is disabled during initialization as per erratum i608
+	 * it is safer to disable RTA by the bootloader, but we would like
+	 * to be doubly sure here and prevent any mishaps.
+	 */
+	if (IS_PM34XX_ERRATUM(PM_RTA_ERRATUM_i608))
+		omap3630_ctrl_disable_rta();
+
 	clkdm_add_wkdep(neon_clkdm, mpu_clkdm);
 	if (omap_type() != OMAP2_DEVICE_TYPE_GP) {
 		omap3_secure_ram_storage =
@@ -1070,7 +1095,7 @@ static int __init omap3_pm_init(void)
 		local_fiq_disable();
 
 		omap_dma_global_context_save();
-		omap3_save_secure_ram_context(PWRDM_POWER_ON);
+		omap3_save_secure_ram_context();
 		omap_dma_global_context_restore();
 
 		local_irq_enable();
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/pm44xx.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/pm44xx.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/pm44xx.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/pm44xx.c	2011-03-14 21:20:32.000000000 -0400
@@ -16,7 +16,7 @@
 #include <linux/err.h>
 #include <linux/slab.h>
 
-#include <plat/powerdomain.h>
+#include "powerdomain.h"
 #include <mach/omap4-common.h>
 
 struct power_state {
@@ -31,12 +31,6 @@ struct power_state {
 static LIST_HEAD(pwrst_list);
 
 #ifdef CONFIG_SUSPEND
-static int omap4_pm_prepare(void)
-{
-	disable_hlt();
-	return 0;
-}
-
 static int omap4_pm_suspend(void)
 {
 	do_wfi();
@@ -59,28 +53,22 @@ static int omap4_pm_enter(suspend_state_
 	return ret;
 }
 
-static void omap4_pm_finish(void)
-{
-	enable_hlt();
-	return;
-}
-
 static int omap4_pm_begin(suspend_state_t state)
 {
+	disable_hlt();
 	return 0;
 }
 
 static void omap4_pm_end(void)
 {
+	enable_hlt();
 	return;
 }
 
-static struct platform_suspend_ops omap_pm_ops = {
+static const struct platform_suspend_ops omap_pm_ops = {
 	.begin		= omap4_pm_begin,
 	.end		= omap4_pm_end,
-	.prepare	= omap4_pm_prepare,
 	.enter		= omap4_pm_enter,
-	.finish		= omap4_pm_finish,
 	.valid		= suspend_valid_only_mem,
 };
 #endif /* CONFIG_SUSPEND */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/pm_bus.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/pm_bus.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/pm_bus.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/pm_bus.c	2011-03-14 21:20:32.000000000 -0400
@@ -20,7 +20,7 @@
 #include <plat/omap-pm.h>
 
 #ifdef CONFIG_PM_RUNTIME
-int omap_pm_runtime_suspend(struct device *dev)
+static int omap_pm_runtime_suspend(struct device *dev)
 {
 	struct platform_device *pdev = to_platform_device(dev);
 	int r, ret = 0;
@@ -37,7 +37,7 @@ int omap_pm_runtime_suspend(struct devic
 	return ret;
 };
 
-int omap_pm_runtime_resume(struct device *dev)
+static int omap_pm_runtime_resume(struct device *dev)
 {
 	struct platform_device *pdev = to_platform_device(dev);
 	int r;
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/pm.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/pm.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/pm.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/pm.c	2011-03-14 21:20:32.000000000 -0400
@@ -13,13 +13,16 @@
 #include <linux/init.h>
 #include <linux/io.h>
 #include <linux/err.h>
+#include <linux/opp.h>
 
 #include <plat/omap-pm.h>
 #include <plat/omap_device.h>
 #include <plat/common.h>
+#include <plat/voltage.h>
 
-#include <plat/powerdomain.h>
-#include <plat/clockdomain.h>
+#include "powerdomain.h"
+#include "clockdomain.h"
+#include "pm.h"
 
 static struct omap_device_pm_latency *pm_lats;
 
@@ -89,10 +92,13 @@ static void omap2_init_processor_devices
 	}
 }
 
+/* Types of sleep_switch used in omap_set_pwrdm_state */
+#define FORCEWAKEUP_SWITCH	0
+#define LOWPOWERSTATE_SWITCH	1
+
 /*
  * This sets pwrdm state (other than mpu & core. Currently only ON &
- * RET are supported. Function is assuming that clkdm doesn't have
- * hw_sup mode enabled.
+ * RET are supported.
  */
 int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state)
 {
@@ -114,9 +120,14 @@ int omap_set_pwrdm_state(struct powerdom
 		return ret;
 
 	if (pwrdm_read_pwrst(pwrdm) < PWRDM_POWER_ON) {
-		omap2_clkdm_wakeup(pwrdm->pwrdm_clkdms[0]);
-		sleep_switch = 1;
-		pwrdm_wait_transition(pwrdm);
+		if ((pwrdm_read_pwrst(pwrdm) > state) &&
+			(pwrdm->flags & PWRDM_HAS_LOWPOWERSTATECHANGE)) {
+			sleep_switch = LOWPOWERSTATE_SWITCH;
+		} else {
+			omap2_clkdm_wakeup(pwrdm->pwrdm_clkdms[0]);
+			pwrdm_wait_transition(pwrdm);
+			sleep_switch = FORCEWAKEUP_SWITCH;
+		}
 	}
 
 	ret = pwrdm_set_next_pwrst(pwrdm, state);
@@ -126,16 +137,106 @@ int omap_set_pwrdm_state(struct powerdom
 		goto err;
 	}
 
-	if (sleep_switch) {
-		omap2_clkdm_allow_idle(pwrdm->pwrdm_clkdms[0]);
-		pwrdm_wait_transition(pwrdm);
-		pwrdm_state_switch(pwrdm);
+	switch (sleep_switch) {
+	case FORCEWAKEUP_SWITCH:
+		if (pwrdm->pwrdm_clkdms[0]->flags & CLKDM_CAN_ENABLE_AUTO)
+			omap2_clkdm_allow_idle(pwrdm->pwrdm_clkdms[0]);
+		else
+			omap2_clkdm_sleep(pwrdm->pwrdm_clkdms[0]);
+		break;
+	case LOWPOWERSTATE_SWITCH:
+		pwrdm_set_lowpwrstchange(pwrdm);
+		break;
+	default:
+		return ret;
 	}
 
+	pwrdm_wait_transition(pwrdm);
+	pwrdm_state_switch(pwrdm);
 err:
 	return ret;
 }
 
+/*
+ * This API is to be called during init to put 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
+ * in the opp entry
+ */
+static int __init omap2_set_init_voltage(char *vdd_name, char *clk_name,
+						struct device *dev)
+{
+	struct voltagedomain *voltdm;
+	struct clk *clk;
+	struct opp *opp;
+	unsigned long freq, bootup_volt;
+
+	if (!vdd_name || !clk_name || !dev) {
+		printk(KERN_ERR "%s: Invalid parameters!\n", __func__);
+		goto exit;
+	}
+
+	voltdm = omap_voltage_domain_lookup(vdd_name);
+	if (IS_ERR(voltdm)) {
+		printk(KERN_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);
+		goto exit;
+	}
+
+	freq = clk->rate;
+	clk_put(clk);
+
+	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",
+			__func__, vdd_name);
+		goto exit;
+	}
+
+	bootup_volt = opp_get_voltage(opp);
+	if (!bootup_volt) {
+		printk(KERN_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);
+	return 0;
+
+exit:
+	printk(KERN_ERR "%s: Unable to put vdd_%s to its init voltage\n\n",
+		__func__, vdd_name);
+	return -EINVAL;
+}
+
+static void __init omap3_init_voltages(void)
+{
+	if (!cpu_is_omap34xx())
+		return;
+
+	omap2_set_init_voltage("mpu", "dpll1_ck", mpu_dev);
+	omap2_set_init_voltage("core", "l3_ick", l3_dev);
+}
+
+static void __init omap4_init_voltages(void)
+{
+	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);
+}
+
 static int __init omap2_common_pm_init(void)
 {
 	omap2_init_processor_devices();
@@ -143,5 +244,24 @@ static int __init omap2_common_pm_init(v
 
 	return 0;
 }
-device_initcall(omap2_common_pm_init);
+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_voltage_late_init();
+
+	/* Initialize the voltages */
+	omap3_init_voltages();
+	omap4_init_voltages();
 
+	/* Smartreflex device init */
+	omap_devinit_smartreflex();
+
+	return 0;
+}
+late_initcall(omap2_common_pm_late_init);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/pm-debug.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/pm-debug.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/pm-debug.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/pm-debug.c	2011-03-14 21:20:32.000000000 -0400
@@ -29,12 +29,13 @@
 
 #include <plat/clock.h>
 #include <plat/board.h>
-#include <plat/powerdomain.h>
-#include <plat/clockdomain.h>
+#include "powerdomain.h"
+#include "clockdomain.h"
 #include <plat/dmtimer.h>
+#include <plat/omap-pm.h>
 
-#include "prm.h"
-#include "cm.h"
+#include "cm2xxx_3xxx.h"
+#include "prm2xxx_3xxx.h"
 #include "pm.h"
 
 int omap2_pm_debug;
@@ -45,10 +46,10 @@ u32 wakeup_timer_milliseconds;
 
 #define DUMP_PRM_MOD_REG(mod, reg)    \
 	regs[reg_count].name = #mod "." #reg; \
-	regs[reg_count++].val = prm_read_mod_reg(mod, reg)
+	regs[reg_count++].val = omap2_prm_read_mod_reg(mod, reg)
 #define DUMP_CM_MOD_REG(mod, reg)     \
 	regs[reg_count].name = #mod "." #reg; \
-	regs[reg_count++].val = cm_read_mod_reg(mod, reg)
+	regs[reg_count++].val = omap2_cm_read_mod_reg(mod, reg)
 #define DUMP_PRM_REG(reg) \
 	regs[reg_count].name = #reg; \
 	regs[reg_count++].val = __raw_readl(reg)
@@ -328,10 +329,10 @@ static void pm_dbg_regset_store(u32 *ptr
 		for (j = pm_dbg_reg_modules[i].low;
 			j <= pm_dbg_reg_modules[i].high; j += 4) {
 			if (pm_dbg_reg_modules[i].type == MOD_CM)
-				val = cm_read_mod_reg(
+				val = omap2_cm_read_mod_reg(
 					pm_dbg_reg_modules[i].offset, j);
 			else
-				val = prm_read_mod_reg(
+				val = omap2_prm_read_mod_reg(
 					pm_dbg_reg_modules[i].offset, j);
 			*(ptr++) = val;
 		}
@@ -581,6 +582,10 @@ static int option_set(void *data, u64 va
 	*option = val;
 
 	if (option == &enable_off_mode) {
+		if (val)
+			omap_pm_enable_off_mode();
+		else
+			omap_pm_disable_off_mode();
 		if (cpu_is_omap34xx())
 			omap3_pm_off_mode_enable(val);
 	}
@@ -632,14 +637,14 @@ static int __init pm_dbg_init(void)
 
 		}
 
-	(void) debugfs_create_file("enable_off_mode", S_IRUGO | S_IWUGO, d,
+	(void) debugfs_create_file("enable_off_mode", S_IRUGO | S_IWUSR, d,
 				   &enable_off_mode, &pm_dbg_option_fops);
-	(void) debugfs_create_file("sleep_while_idle", S_IRUGO | S_IWUGO, d,
+	(void) debugfs_create_file("sleep_while_idle", S_IRUGO | S_IWUSR, d,
 				   &sleep_while_idle, &pm_dbg_option_fops);
-	(void) debugfs_create_file("wakeup_timer_seconds", S_IRUGO | S_IWUGO, d,
+	(void) debugfs_create_file("wakeup_timer_seconds", S_IRUGO | S_IWUSR, d,
 				   &wakeup_timer_seconds, &pm_dbg_option_fops);
 	(void) debugfs_create_file("wakeup_timer_milliseconds",
-			S_IRUGO | S_IWUGO, d, &wakeup_timer_milliseconds,
+			S_IRUGO | S_IWUSR, d, &wakeup_timer_milliseconds,
 			&pm_dbg_option_fops);
 	pm_dbg_init_done = 1;
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/pm.h linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/pm.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/pm.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/pm.h	2011-03-14 21:20:32.000000000 -0400
@@ -11,7 +11,9 @@
 #ifndef __ARCH_ARM_MACH_OMAP2_PM_H
 #define __ARCH_ARM_MACH_OMAP2_PM_H
 
-#include <plat/powerdomain.h>
+#include <linux/err.h>
+
+#include "powerdomain.h"
 
 extern void *omap3_secure_ram_storage;
 extern void omap3_pm_off_mode_enable(int);
@@ -20,6 +22,20 @@ extern int omap3_can_sleep(void);
 extern int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state);
 extern int omap3_idle_init(void);
 
+#if defined(CONFIG_PM_OPP)
+extern int omap3_opp_init(void);
+extern int omap4_opp_init(void);
+#else
+static inline int omap3_opp_init(void)
+{
+	return -EINVAL;
+}
+static inline int omap4_opp_init(void)
+{
+	return -EINVAL;
+}
+#endif
+
 struct cpuidle_params {
 	u8  valid;
 	u32 sleep_latency;
@@ -58,7 +74,7 @@ extern u32 sleep_while_idle;
 #endif
 
 #if defined(CONFIG_CPU_IDLE)
-extern void omap3_cpuidle_update_states(void);
+extern void omap3_cpuidle_update_states(u32, u32);
 #endif
 
 #if defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS)
@@ -80,9 +96,46 @@ extern void save_secure_ram_context(u32
 extern void omap3_save_scratchpad_contents(void);
 
 extern unsigned int omap24xx_idle_loop_suspend_sz;
-extern unsigned int omap34xx_suspend_sz;
 extern unsigned int save_secure_ram_context_sz;
 extern unsigned int omap24xx_cpu_suspend_sz;
 extern unsigned int omap34xx_cpu_suspend_sz;
 
+#define PM_RTA_ERRATUM_i608		(1 << 0)
+#define PM_SDRC_WAKEUP_ERRATUM_i583	(1 << 1)
+
+#if defined(CONFIG_PM) && defined(CONFIG_ARCH_OMAP3)
+extern u16 pm34xx_errata;
+#define IS_PM34XX_ERRATUM(id)		(pm34xx_errata & (id))
+extern void enable_omap3630_toggle_l2_on_restore(void);
+#else
+#define IS_PM34XX_ERRATUM(id)		0
+static inline void enable_omap3630_toggle_l2_on_restore(void) { }
+#endif		/* defined(CONFIG_PM) && defined(CONFIG_ARCH_OMAP3) */
+
+#ifdef CONFIG_OMAP_SMARTREFLEX
+extern int omap_devinit_smartreflex(void);
+extern void omap_enable_smartreflex_on_init(void);
+#else
+static inline int omap_devinit_smartreflex(void)
+{
+	return -EINVAL;
+}
+
+static inline void omap_enable_smartreflex_on_init(void) {}
+#endif
+
+#ifdef CONFIG_TWL4030_CORE
+extern int omap3_twl_init(void);
+extern int omap4_twl_init(void);
+#else
+static inline int omap3_twl_init(void)
+{
+	return -EINVAL;
+}
+static inline int omap4_twl_init(void)
+{
+	return -EINVAL;
+}
+#endif
+
 #endif
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/powerdomain2xxx_3xxx.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/powerdomain2xxx_3xxx.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/powerdomain2xxx_3xxx.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/powerdomain2xxx_3xxx.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,241 @@
+/*
+ * OMAP2 and OMAP3 powerdomain control
+ *
+ * Copyright (C) 2009-2010 Texas Instruments, Inc.
+ * Copyright (C) 2007-2009 Nokia Corporation
+ *
+ * Derived from mach-omap2/powerdomain.c written by Paul Walmsley
+ * Rajendra Nayak <rnayak@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.
+ */
+
+#include <linux/io.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+
+#include <plat/prcm.h>
+
+#include "powerdomain.h"
+#include "prm.h"
+#include "prm-regbits-24xx.h"
+#include "prm-regbits-34xx.h"
+
+
+/* Common functions across OMAP2 and OMAP3 */
+static int omap2_pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst)
+{
+	omap2_prm_rmw_mod_reg_bits(OMAP_POWERSTATE_MASK,
+				(pwrst << OMAP_POWERSTATE_SHIFT),
+				pwrdm->prcm_offs, OMAP2_PM_PWSTCTRL);
+	return 0;
+}
+
+static int omap2_pwrdm_read_next_pwrst(struct powerdomain *pwrdm)
+{
+	return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs,
+					     OMAP2_PM_PWSTCTRL,
+					     OMAP_POWERSTATE_MASK);
+}
+
+static int omap2_pwrdm_read_pwrst(struct powerdomain *pwrdm)
+{
+	return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs,
+					     OMAP2_PM_PWSTST,
+					     OMAP_POWERSTATEST_MASK);
+}
+
+static int omap2_pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank,
+								u8 pwrst)
+{
+	u32 m;
+
+	m = omap2_pwrdm_get_mem_bank_onstate_mask(bank);
+
+	omap2_prm_rmw_mod_reg_bits(m, (pwrst << __ffs(m)), pwrdm->prcm_offs,
+				   OMAP2_PM_PWSTCTRL);
+
+	return 0;
+}
+
+static int omap2_pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 bank,
+								u8 pwrst)
+{
+	u32 m;
+
+	m = omap2_pwrdm_get_mem_bank_retst_mask(bank);
+
+	omap2_prm_rmw_mod_reg_bits(m, (pwrst << __ffs(m)), pwrdm->prcm_offs,
+				   OMAP2_PM_PWSTCTRL);
+
+	return 0;
+}
+
+static int omap2_pwrdm_read_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
+{
+	u32 m;
+
+	m = omap2_pwrdm_get_mem_bank_stst_mask(bank);
+
+	return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs, OMAP2_PM_PWSTST,
+					     m);
+}
+
+static int omap2_pwrdm_read_mem_retst(struct powerdomain *pwrdm, u8 bank)
+{
+	u32 m;
+
+	m = omap2_pwrdm_get_mem_bank_retst_mask(bank);
+
+	return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs,
+					     OMAP2_PM_PWSTCTRL, m);
+}
+
+static int omap2_pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst)
+{
+	u32 v;
+
+	v = pwrst << __ffs(OMAP3430_LOGICL1CACHERETSTATE_MASK);
+	omap2_prm_rmw_mod_reg_bits(OMAP3430_LOGICL1CACHERETSTATE_MASK, v,
+				   pwrdm->prcm_offs, OMAP2_PM_PWSTCTRL);
+
+	return 0;
+}
+
+static int omap2_pwrdm_wait_transition(struct powerdomain *pwrdm)
+{
+	u32 c = 0;
+
+	/*
+	 * REVISIT: pwrdm_wait_transition() may be better implemented
+	 * via a callback and a periodic timer check -- how long do we expect
+	 * powerdomain transitions to take?
+	 */
+
+	/* XXX Is this udelay() value meaningful? */
+	while ((omap2_prm_read_mod_reg(pwrdm->prcm_offs, OMAP2_PM_PWSTST) &
+		OMAP_INTRANSITION_MASK) &&
+		(c++ < PWRDM_TRANSITION_BAILOUT))
+			udelay(1);
+
+	if (c > PWRDM_TRANSITION_BAILOUT) {
+		printk(KERN_ERR "powerdomain: waited too long for "
+			"powerdomain %s to complete transition\n", pwrdm->name);
+		return -EAGAIN;
+	}
+
+	pr_debug("powerdomain: completed transition in %d loops\n", c);
+
+	return 0;
+}
+
+/* Applicable only for OMAP3. Not supported on OMAP2 */
+static int omap3_pwrdm_read_prev_pwrst(struct powerdomain *pwrdm)
+{
+	return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs,
+					     OMAP3430_PM_PREPWSTST,
+					     OMAP3430_LASTPOWERSTATEENTERED_MASK);
+}
+
+static int omap3_pwrdm_read_logic_pwrst(struct powerdomain *pwrdm)
+{
+	return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs,
+					     OMAP2_PM_PWSTST,
+					     OMAP3430_LOGICSTATEST_MASK);
+}
+
+static int omap3_pwrdm_read_logic_retst(struct powerdomain *pwrdm)
+{
+	return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs,
+					     OMAP2_PM_PWSTCTRL,
+					     OMAP3430_LOGICSTATEST_MASK);
+}
+
+static int omap3_pwrdm_read_prev_logic_pwrst(struct powerdomain *pwrdm)
+{
+	return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs,
+					     OMAP3430_PM_PREPWSTST,
+					     OMAP3430_LASTLOGICSTATEENTERED_MASK);
+}
+
+static int omap3_get_mem_bank_lastmemst_mask(u8 bank)
+{
+	switch (bank) {
+	case 0:
+		return OMAP3430_LASTMEM1STATEENTERED_MASK;
+	case 1:
+		return OMAP3430_LASTMEM2STATEENTERED_MASK;
+	case 2:
+		return OMAP3430_LASTSHAREDL2CACHEFLATSTATEENTERED_MASK;
+	case 3:
+		return OMAP3430_LASTL2FLATMEMSTATEENTERED_MASK;
+	default:
+		WARN_ON(1); /* should never happen */
+		return -EEXIST;
+	}
+	return 0;
+}
+
+static int omap3_pwrdm_read_prev_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
+{
+	u32 m;
+
+	m = omap3_get_mem_bank_lastmemst_mask(bank);
+
+	return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs,
+				OMAP3430_PM_PREPWSTST, m);
+}
+
+static int omap3_pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm)
+{
+	omap2_prm_write_mod_reg(0, pwrdm->prcm_offs, OMAP3430_PM_PREPWSTST);
+	return 0;
+}
+
+static int omap3_pwrdm_enable_hdwr_sar(struct powerdomain *pwrdm)
+{
+	return omap2_prm_rmw_mod_reg_bits(0,
+					  1 << OMAP3430ES2_SAVEANDRESTORE_SHIFT,
+					  pwrdm->prcm_offs, OMAP2_PM_PWSTCTRL);
+}
+
+static int omap3_pwrdm_disable_hdwr_sar(struct powerdomain *pwrdm)
+{
+	return omap2_prm_rmw_mod_reg_bits(1 << OMAP3430ES2_SAVEANDRESTORE_SHIFT,
+					  0, pwrdm->prcm_offs,
+					  OMAP2_PM_PWSTCTRL);
+}
+
+struct pwrdm_ops omap2_pwrdm_operations = {
+	.pwrdm_set_next_pwrst	= omap2_pwrdm_set_next_pwrst,
+	.pwrdm_read_next_pwrst	= omap2_pwrdm_read_next_pwrst,
+	.pwrdm_read_pwrst	= omap2_pwrdm_read_pwrst,
+	.pwrdm_set_logic_retst	= omap2_pwrdm_set_logic_retst,
+	.pwrdm_set_mem_onst	= omap2_pwrdm_set_mem_onst,
+	.pwrdm_set_mem_retst	= omap2_pwrdm_set_mem_retst,
+	.pwrdm_read_mem_pwrst	= omap2_pwrdm_read_mem_pwrst,
+	.pwrdm_read_mem_retst	= omap2_pwrdm_read_mem_retst,
+	.pwrdm_wait_transition	= omap2_pwrdm_wait_transition,
+};
+
+struct pwrdm_ops omap3_pwrdm_operations = {
+	.pwrdm_set_next_pwrst	= omap2_pwrdm_set_next_pwrst,
+	.pwrdm_read_next_pwrst	= omap2_pwrdm_read_next_pwrst,
+	.pwrdm_read_pwrst	= omap2_pwrdm_read_pwrst,
+	.pwrdm_read_prev_pwrst	= omap3_pwrdm_read_prev_pwrst,
+	.pwrdm_set_logic_retst	= omap2_pwrdm_set_logic_retst,
+	.pwrdm_read_logic_pwrst	= omap3_pwrdm_read_logic_pwrst,
+	.pwrdm_read_logic_retst	= omap3_pwrdm_read_logic_retst,
+	.pwrdm_read_prev_logic_pwrst	= omap3_pwrdm_read_prev_logic_pwrst,
+	.pwrdm_set_mem_onst	= omap2_pwrdm_set_mem_onst,
+	.pwrdm_set_mem_retst	= omap2_pwrdm_set_mem_retst,
+	.pwrdm_read_mem_pwrst	= omap2_pwrdm_read_mem_pwrst,
+	.pwrdm_read_mem_retst	= omap2_pwrdm_read_mem_retst,
+	.pwrdm_read_prev_mem_pwrst	= omap3_pwrdm_read_prev_mem_pwrst,
+	.pwrdm_clear_all_prev_pwrst	= omap3_pwrdm_clear_all_prev_pwrst,
+	.pwrdm_enable_hdwr_sar	= omap3_pwrdm_enable_hdwr_sar,
+	.pwrdm_disable_hdwr_sar	= omap3_pwrdm_disable_hdwr_sar,
+	.pwrdm_wait_transition	= omap2_pwrdm_wait_transition,
+};
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/powerdomain44xx.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/powerdomain44xx.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/powerdomain44xx.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/powerdomain44xx.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,225 @@
+/*
+ * OMAP4 powerdomain control
+ *
+ * Copyright (C) 2009-2010 Texas Instruments, Inc.
+ * Copyright (C) 2007-2009 Nokia Corporation
+ *
+ * Derived from mach-omap2/powerdomain.c written by Paul Walmsley
+ * Rajendra Nayak <rnayak@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.
+ */
+
+#include <linux/io.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+
+#include "powerdomain.h"
+#include <plat/prcm.h>
+#include "prm2xxx_3xxx.h"
+#include "prm44xx.h"
+#include "prminst44xx.h"
+#include "prm-regbits-44xx.h"
+
+static int omap4_pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst)
+{
+	omap4_prminst_rmw_inst_reg_bits(OMAP_POWERSTATE_MASK,
+					(pwrst << OMAP_POWERSTATE_SHIFT),
+					pwrdm->prcm_partition,
+					pwrdm->prcm_offs, OMAP4_PM_PWSTCTRL);
+	return 0;
+}
+
+static int omap4_pwrdm_read_next_pwrst(struct powerdomain *pwrdm)
+{
+	u32 v;
+
+	v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs,
+					OMAP4_PM_PWSTCTRL);
+	v &= OMAP_POWERSTATE_MASK;
+	v >>= OMAP_POWERSTATE_SHIFT;
+
+	return v;
+}
+
+static int omap4_pwrdm_read_pwrst(struct powerdomain *pwrdm)
+{
+	u32 v;
+
+	v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs,
+					OMAP4_PM_PWSTST);
+	v &= OMAP_POWERSTATEST_MASK;
+	v >>= OMAP_POWERSTATEST_SHIFT;
+
+	return v;
+}
+
+static int omap4_pwrdm_read_prev_pwrst(struct powerdomain *pwrdm)
+{
+	u32 v;
+
+	v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs,
+					OMAP4_PM_PWSTST);
+	v &= OMAP4430_LASTPOWERSTATEENTERED_MASK;
+	v >>= OMAP4430_LASTPOWERSTATEENTERED_SHIFT;
+
+	return v;
+}
+
+static int omap4_pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm)
+{
+	omap4_prminst_rmw_inst_reg_bits(OMAP4430_LOWPOWERSTATECHANGE_MASK,
+					(1 << OMAP4430_LOWPOWERSTATECHANGE_SHIFT),
+					pwrdm->prcm_partition,
+					pwrdm->prcm_offs, OMAP4_PM_PWSTCTRL);
+	return 0;
+}
+
+static int omap4_pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm)
+{
+	omap4_prminst_rmw_inst_reg_bits(OMAP4430_LASTPOWERSTATEENTERED_MASK,
+					OMAP4430_LASTPOWERSTATEENTERED_MASK,
+					pwrdm->prcm_partition,
+					pwrdm->prcm_offs, OMAP4_PM_PWSTST);
+	return 0;
+}
+
+static int omap4_pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst)
+{
+	u32 v;
+
+	v = pwrst << __ffs(OMAP4430_LOGICRETSTATE_MASK);
+	omap4_prminst_rmw_inst_reg_bits(OMAP4430_LOGICRETSTATE_MASK, v,
+					pwrdm->prcm_partition, pwrdm->prcm_offs,
+					OMAP4_PM_PWSTCTRL);
+
+	return 0;
+}
+
+static int omap4_pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank,
+				    u8 pwrst)
+{
+	u32 m;
+
+	m = omap2_pwrdm_get_mem_bank_onstate_mask(bank);
+
+	omap4_prminst_rmw_inst_reg_bits(m, (pwrst << __ffs(m)),
+					pwrdm->prcm_partition, pwrdm->prcm_offs,
+					OMAP4_PM_PWSTCTRL);
+
+	return 0;
+}
+
+static int omap4_pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 bank,
+				     u8 pwrst)
+{
+	u32 m;
+
+	m = omap2_pwrdm_get_mem_bank_retst_mask(bank);
+
+	omap4_prminst_rmw_inst_reg_bits(m, (pwrst << __ffs(m)),
+					pwrdm->prcm_partition, pwrdm->prcm_offs,
+					OMAP4_PM_PWSTCTRL);
+
+	return 0;
+}
+
+static int omap4_pwrdm_read_logic_pwrst(struct powerdomain *pwrdm)
+{
+	u32 v;
+
+	v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs,
+					OMAP4_PM_PWSTST);
+	v &= OMAP4430_LOGICSTATEST_MASK;
+	v >>= OMAP4430_LOGICSTATEST_SHIFT;
+
+	return v;
+}
+
+static int omap4_pwrdm_read_logic_retst(struct powerdomain *pwrdm)
+{
+	u32 v;
+
+	v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs,
+					OMAP4_PM_PWSTCTRL);
+	v &= OMAP4430_LOGICRETSTATE_MASK;
+	v >>= OMAP4430_LOGICRETSTATE_SHIFT;
+
+	return v;
+}
+
+static int omap4_pwrdm_read_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
+{
+	u32 m, v;
+
+	m = omap2_pwrdm_get_mem_bank_stst_mask(bank);
+
+	v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs,
+					OMAP4_PM_PWSTST);
+	v &= m;
+	v >>= __ffs(m);
+
+	return v;
+}
+
+static int omap4_pwrdm_read_mem_retst(struct powerdomain *pwrdm, u8 bank)
+{
+	u32 m, v;
+
+	m = omap2_pwrdm_get_mem_bank_retst_mask(bank);
+
+	v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs,
+					OMAP4_PM_PWSTCTRL);
+	v &= m;
+	v >>= __ffs(m);
+
+	return v;
+}
+
+static int omap4_pwrdm_wait_transition(struct powerdomain *pwrdm)
+{
+	u32 c = 0;
+
+	/*
+	 * REVISIT: pwrdm_wait_transition() may be better implemented
+	 * via a callback and a periodic timer check -- how long do we expect
+	 * powerdomain transitions to take?
+	 */
+
+	/* XXX Is this udelay() value meaningful? */
+	while ((omap4_prminst_read_inst_reg(pwrdm->prcm_partition,
+					    pwrdm->prcm_offs,
+					    OMAP4_PM_PWSTST) &
+		OMAP_INTRANSITION_MASK) &&
+	       (c++ < PWRDM_TRANSITION_BAILOUT))
+		udelay(1);
+
+	if (c > PWRDM_TRANSITION_BAILOUT) {
+		printk(KERN_ERR "powerdomain: waited too long for "
+		       "powerdomain %s to complete transition\n", pwrdm->name);
+		return -EAGAIN;
+	}
+
+	pr_debug("powerdomain: completed transition in %d loops\n", c);
+
+	return 0;
+}
+
+struct pwrdm_ops omap4_pwrdm_operations = {
+	.pwrdm_set_next_pwrst	= omap4_pwrdm_set_next_pwrst,
+	.pwrdm_read_next_pwrst	= omap4_pwrdm_read_next_pwrst,
+	.pwrdm_read_pwrst	= omap4_pwrdm_read_pwrst,
+	.pwrdm_read_prev_pwrst	= omap4_pwrdm_read_prev_pwrst,
+	.pwrdm_set_lowpwrstchange	= omap4_pwrdm_set_lowpwrstchange,
+	.pwrdm_clear_all_prev_pwrst	= omap4_pwrdm_clear_all_prev_pwrst,
+	.pwrdm_set_logic_retst	= omap4_pwrdm_set_logic_retst,
+	.pwrdm_read_logic_pwrst	= omap4_pwrdm_read_logic_pwrst,
+	.pwrdm_read_logic_retst	= omap4_pwrdm_read_logic_retst,
+	.pwrdm_read_mem_pwrst	= omap4_pwrdm_read_mem_pwrst,
+	.pwrdm_read_mem_retst	= omap4_pwrdm_read_mem_retst,
+	.pwrdm_set_mem_onst	= omap4_pwrdm_set_mem_onst,
+	.pwrdm_set_mem_retst	= omap4_pwrdm_set_mem_retst,
+	.pwrdm_wait_transition	= omap4_pwrdm_wait_transition,
+};
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/powerdomain.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/powerdomain.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/powerdomain.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/powerdomain.c	2011-03-14 21:20:32.000000000 -0400
@@ -15,27 +15,19 @@
 #undef DEBUG
 
 #include <linux/kernel.h>
-#include <linux/module.h>
 #include <linux/types.h>
-#include <linux/delay.h>
-#include <linux/spinlock.h>
 #include <linux/list.h>
 #include <linux/errno.h>
-#include <linux/err.h>
-#include <linux/io.h>
-
-#include <asm/atomic.h>
-
-#include "cm.h"
-#include "cm-regbits-34xx.h"
-#include "cm-regbits-44xx.h"
-#include "prm.h"
-#include "prm-regbits-34xx.h"
-#include "prm-regbits-44xx.h"
+#include <linux/string.h>
+#include "cm2xxx_3xxx.h"
+#include "prcm44xx.h"
+#include "cm44xx.h"
+#include "prm2xxx_3xxx.h"
+#include "prm44xx.h"
 
 #include <plat/cpu.h>
-#include <plat/powerdomain.h>
-#include <plat/clockdomain.h>
+#include "powerdomain.h"
+#include "clockdomain.h"
 #include <plat/prcm.h>
 
 #include "pm.h"
@@ -45,41 +37,12 @@ enum {
 	PWRDM_STATE_PREV,
 };
 
-/* Variable holding value of the CPU dependent PWRSTCTRL Register Offset */
-static u16 pwrstctrl_reg_offs;
-
-/* Variable holding value of the CPU dependent PWRSTST Register Offset */
-static u16 pwrstst_reg_offs;
-
-/* OMAP3 and OMAP4 specific register bit initialisations
- * Notice that the names here are not according to each power
- * domain but the bit mapping used applies to all of them
- */
-
-/* OMAP3 and OMAP4 Memory Onstate Masks (common across all power domains) */
-#define OMAP_MEM0_ONSTATE_MASK OMAP3430_SHAREDL1CACHEFLATONSTATE_MASK
-#define OMAP_MEM1_ONSTATE_MASK OMAP3430_L1FLATMEMONSTATE_MASK
-#define OMAP_MEM2_ONSTATE_MASK OMAP3430_SHAREDL2CACHEFLATONSTATE_MASK
-#define OMAP_MEM3_ONSTATE_MASK OMAP3430_L2FLATMEMONSTATE_MASK
-#define OMAP_MEM4_ONSTATE_MASK OMAP4430_OCP_NRET_BANK_ONSTATE_MASK
-
-/* OMAP3 and OMAP4 Memory Retstate Masks (common across all power domains) */
-#define OMAP_MEM0_RETSTATE_MASK OMAP3430_SHAREDL1CACHEFLATRETSTATE_MASK
-#define OMAP_MEM1_RETSTATE_MASK OMAP3430_L1FLATMEMRETSTATE_MASK
-#define OMAP_MEM2_RETSTATE_MASK OMAP3430_SHAREDL2CACHEFLATRETSTATE_MASK
-#define OMAP_MEM3_RETSTATE_MASK OMAP3430_L2FLATMEMRETSTATE_MASK
-#define OMAP_MEM4_RETSTATE_MASK OMAP4430_OCP_NRET_BANK_RETSTATE_MASK
-
-/* OMAP3 and OMAP4 Memory Status bits */
-#define OMAP_MEM0_STATEST_MASK OMAP3430_SHAREDL1CACHEFLATSTATEST_MASK
-#define OMAP_MEM1_STATEST_MASK OMAP3430_L1FLATMEMSTATEST_MASK
-#define OMAP_MEM2_STATEST_MASK OMAP3430_SHAREDL2CACHEFLATSTATEST_MASK
-#define OMAP_MEM3_STATEST_MASK OMAP3430_L2FLATMEMSTATEST_MASK
-#define OMAP_MEM4_STATEST_MASK OMAP4430_OCP_NRET_BANK_STATEST_MASK
 
 /* pwrdm_list contains all registered struct powerdomains */
 static LIST_HEAD(pwrdm_list);
 
+static struct pwrdm_ops *arch_pwrdm;
+
 /* Private functions */
 
 static struct powerdomain *_pwrdm_lookup(const char *name)
@@ -110,12 +73,19 @@ static int _pwrdm_register(struct powerd
 {
 	int i;
 
-	if (!pwrdm)
+	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",
+		       pwrdm->name);
+		return -EINVAL;
+	}
+
 	if (_pwrdm_lookup(pwrdm->name))
 		return -EEXIST;
 
@@ -211,6 +181,7 @@ static int _pwrdm_post_transition_cb(str
 /**
  * pwrdm_init - set up the powerdomain layer
  * @pwrdm_list: array of struct powerdomain pointers to register
+ * @custom_funcs: func pointers for arch specfic implementations
  *
  * Loop through the array of powerdomains @pwrdm_list, registering all
  * that are available on the current CPU. If pwrdm_list is supplied
@@ -218,21 +189,14 @@ static int _pwrdm_post_transition_cb(str
  * registered.  No return value.  XXX pwrdm_list is not really a
  * "list"; it is an array.  Rename appropriately.
  */
-void pwrdm_init(struct powerdomain **pwrdm_list)
+void pwrdm_init(struct powerdomain **pwrdm_list, struct pwrdm_ops *custom_funcs)
 {
 	struct powerdomain **p = NULL;
 
-	if (cpu_is_omap24xx() || cpu_is_omap34xx()) {
-		pwrstctrl_reg_offs = OMAP2_PM_PWSTCTRL;
-		pwrstst_reg_offs = OMAP2_PM_PWSTST;
-	} else if (cpu_is_omap44xx()) {
-		pwrstctrl_reg_offs = OMAP4_PM_PWSTCTRL;
-		pwrstst_reg_offs = OMAP4_PM_PWSTST;
-	} else {
-		printk(KERN_ERR "Power Domain struct not supported for " \
-							"this CPU\n");
-		return;
-	}
+	if (!custom_funcs)
+		WARN(1, "powerdomain: No custom pwrdm functions registered\n");
+	else
+		arch_pwrdm = custom_funcs;
 
 	if (pwrdm_list) {
 		for (p = pwrdm_list; *p; p++)
@@ -431,6 +395,8 @@ int pwrdm_get_mem_bank_count(struct powe
  */
 int pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst)
 {
+	int ret = -EINVAL;
+
 	if (!pwrdm)
 		return -EINVAL;
 
@@ -440,11 +406,10 @@ int pwrdm_set_next_pwrst(struct powerdom
 	pr_debug("powerdomain: setting next powerstate for %s to %0x\n",
 		 pwrdm->name, pwrst);
 
-	prm_rmw_mod_reg_bits(OMAP_POWERSTATE_MASK,
-			     (pwrst << OMAP_POWERSTATE_SHIFT),
-			     pwrdm->prcm_offs, pwrstctrl_reg_offs);
+	if (arch_pwrdm && arch_pwrdm->pwrdm_set_next_pwrst)
+		ret = arch_pwrdm->pwrdm_set_next_pwrst(pwrdm, pwrst);
 
-	return 0;
+	return ret;
 }
 
 /**
@@ -457,11 +422,15 @@ int pwrdm_set_next_pwrst(struct powerdom
  */
 int pwrdm_read_next_pwrst(struct powerdomain *pwrdm)
 {
+	int ret = -EINVAL;
+
 	if (!pwrdm)
 		return -EINVAL;
 
-	return prm_read_mod_bits_shift(pwrdm->prcm_offs,
-				 pwrstctrl_reg_offs, OMAP_POWERSTATE_MASK);
+	if (arch_pwrdm && arch_pwrdm->pwrdm_read_next_pwrst)
+		ret = arch_pwrdm->pwrdm_read_next_pwrst(pwrdm);
+
+	return ret;
 }
 
 /**
@@ -474,11 +443,15 @@ int pwrdm_read_next_pwrst(struct powerdo
  */
 int pwrdm_read_pwrst(struct powerdomain *pwrdm)
 {
+	int ret = -EINVAL;
+
 	if (!pwrdm)
 		return -EINVAL;
 
-	return prm_read_mod_bits_shift(pwrdm->prcm_offs,
-				 pwrstst_reg_offs, OMAP_POWERSTATEST_MASK);
+	if (arch_pwrdm && arch_pwrdm->pwrdm_read_pwrst)
+		ret = arch_pwrdm->pwrdm_read_pwrst(pwrdm);
+
+	return ret;
 }
 
 /**
@@ -491,11 +464,15 @@ int pwrdm_read_pwrst(struct powerdomain
  */
 int pwrdm_read_prev_pwrst(struct powerdomain *pwrdm)
 {
+	int ret = -EINVAL;
+
 	if (!pwrdm)
 		return -EINVAL;
 
-	return prm_read_mod_bits_shift(pwrdm->prcm_offs, OMAP3430_PM_PREPWSTST,
-					OMAP3430_LASTPOWERSTATEENTERED_MASK);
+	if (arch_pwrdm && arch_pwrdm->pwrdm_read_prev_pwrst)
+		ret = arch_pwrdm->pwrdm_read_prev_pwrst(pwrdm);
+
+	return ret;
 }
 
 /**
@@ -511,7 +488,7 @@ int pwrdm_read_prev_pwrst(struct powerdo
  */
 int pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst)
 {
-	u32 v;
+	int ret = -EINVAL;
 
 	if (!pwrdm)
 		return -EINVAL;
@@ -522,17 +499,10 @@ int pwrdm_set_logic_retst(struct powerdo
 	pr_debug("powerdomain: setting next logic powerstate for %s to %0x\n",
 		 pwrdm->name, pwrst);
 
-	/*
-	 * The register bit names below may not correspond to the
-	 * actual names of the bits in each powerdomain's register,
-	 * but the type of value returned is the same for each
-	 * powerdomain.
-	 */
-	v = pwrst << __ffs(OMAP3430_LOGICL1CACHERETSTATE_MASK);
-	prm_rmw_mod_reg_bits(OMAP3430_LOGICL1CACHERETSTATE_MASK, v,
-			     pwrdm->prcm_offs, pwrstctrl_reg_offs);
+	if (arch_pwrdm && arch_pwrdm->pwrdm_set_logic_retst)
+		ret = arch_pwrdm->pwrdm_set_logic_retst(pwrdm, pwrst);
 
-	return 0;
+	return ret;
 }
 
 /**
@@ -552,7 +522,7 @@ int pwrdm_set_logic_retst(struct powerdo
  */
 int pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank, u8 pwrst)
 {
-	u32 m;
+	int ret = -EINVAL;
 
 	if (!pwrdm)
 		return -EINVAL;
@@ -566,37 +536,10 @@ int pwrdm_set_mem_onst(struct powerdomai
 	pr_debug("powerdomain: setting next memory powerstate for domain %s "
 		 "bank %0x while pwrdm-ON to %0x\n", pwrdm->name, bank, pwrst);
 
-	/*
-	 * The register bit names below may not correspond to the
-	 * actual names of the bits in each powerdomain's register,
-	 * but the type of value returned is the same for each
-	 * powerdomain.
-	 */
-	switch (bank) {
-	case 0:
-		m = OMAP_MEM0_ONSTATE_MASK;
-		break;
-	case 1:
-		m = OMAP_MEM1_ONSTATE_MASK;
-		break;
-	case 2:
-		m = OMAP_MEM2_ONSTATE_MASK;
-		break;
-	case 3:
-		m = OMAP_MEM3_ONSTATE_MASK;
-		break;
-	case 4:
-		m = OMAP_MEM4_ONSTATE_MASK;
-		break;
-	default:
-		WARN_ON(1); /* should never happen */
-		return -EEXIST;
-	}
-
-	prm_rmw_mod_reg_bits(m, (pwrst << __ffs(m)),
-			     pwrdm->prcm_offs, pwrstctrl_reg_offs);
+	if (arch_pwrdm && arch_pwrdm->pwrdm_set_mem_onst)
+		ret = arch_pwrdm->pwrdm_set_mem_onst(pwrdm, bank, pwrst);
 
-	return 0;
+	return ret;
 }
 
 /**
@@ -617,7 +560,7 @@ int pwrdm_set_mem_onst(struct powerdomai
  */
 int pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 bank, u8 pwrst)
 {
-	u32 m;
+	int ret = -EINVAL;
 
 	if (!pwrdm)
 		return -EINVAL;
@@ -631,37 +574,10 @@ int pwrdm_set_mem_retst(struct powerdoma
 	pr_debug("powerdomain: setting next memory powerstate for domain %s "
 		 "bank %0x while pwrdm-RET to %0x\n", pwrdm->name, bank, pwrst);
 
-	/*
-	 * The register bit names below may not correspond to the
-	 * actual names of the bits in each powerdomain's register,
-	 * but the type of value returned is the same for each
-	 * powerdomain.
-	 */
-	switch (bank) {
-	case 0:
-		m = OMAP_MEM0_RETSTATE_MASK;
-		break;
-	case 1:
-		m = OMAP_MEM1_RETSTATE_MASK;
-		break;
-	case 2:
-		m = OMAP_MEM2_RETSTATE_MASK;
-		break;
-	case 3:
-		m = OMAP_MEM3_RETSTATE_MASK;
-		break;
-	case 4:
-		m = OMAP_MEM4_RETSTATE_MASK;
-		break;
-	default:
-		WARN_ON(1); /* should never happen */
-		return -EEXIST;
-	}
-
-	prm_rmw_mod_reg_bits(m, (pwrst << __ffs(m)), pwrdm->prcm_offs,
-			     pwrstctrl_reg_offs);
+	if (arch_pwrdm && arch_pwrdm->pwrdm_set_mem_retst)
+		ret = arch_pwrdm->pwrdm_set_mem_retst(pwrdm, bank, pwrst);
 
-	return 0;
+	return ret;
 }
 
 /**
@@ -675,11 +591,15 @@ int pwrdm_set_mem_retst(struct powerdoma
  */
 int pwrdm_read_logic_pwrst(struct powerdomain *pwrdm)
 {
+	int ret = -EINVAL;
+
 	if (!pwrdm)
 		return -EINVAL;
 
-	return prm_read_mod_bits_shift(pwrdm->prcm_offs, pwrstst_reg_offs,
-				       OMAP3430_LOGICSTATEST_MASK);
+	if (arch_pwrdm && arch_pwrdm->pwrdm_read_logic_pwrst)
+		ret = arch_pwrdm->pwrdm_read_logic_pwrst(pwrdm);
+
+	return ret;
 }
 
 /**
@@ -692,17 +612,15 @@ int pwrdm_read_logic_pwrst(struct powerd
  */
 int pwrdm_read_prev_logic_pwrst(struct powerdomain *pwrdm)
 {
+	int ret = -EINVAL;
+
 	if (!pwrdm)
 		return -EINVAL;
 
-	/*
-	 * The register bit names below may not correspond to the
-	 * actual names of the bits in each powerdomain's register,
-	 * but the type of value returned is the same for each
-	 * powerdomain.
-	 */
-	return prm_read_mod_bits_shift(pwrdm->prcm_offs, OMAP3430_PM_PREPWSTST,
-					OMAP3430_LASTLOGICSTATEENTERED_MASK);
+	if (arch_pwrdm && arch_pwrdm->pwrdm_read_prev_logic_pwrst)
+		ret = arch_pwrdm->pwrdm_read_prev_logic_pwrst(pwrdm);
+
+	return ret;
 }
 
 /**
@@ -715,17 +633,15 @@ int pwrdm_read_prev_logic_pwrst(struct p
  */
 int pwrdm_read_logic_retst(struct powerdomain *pwrdm)
 {
+	int ret = -EINVAL;
+
 	if (!pwrdm)
 		return -EINVAL;
 
-	/*
-	 * The register bit names below may not correspond to the
-	 * actual names of the bits in each powerdomain's register,
-	 * but the type of value returned is the same for each
-	 * powerdomain.
-	 */
-	return prm_read_mod_bits_shift(pwrdm->prcm_offs, pwrstctrl_reg_offs,
-				       OMAP3430_LOGICSTATEST_MASK);
+	if (arch_pwrdm && arch_pwrdm->pwrdm_read_logic_retst)
+		ret = arch_pwrdm->pwrdm_read_logic_retst(pwrdm);
+
+	return ret;
 }
 
 /**
@@ -740,46 +656,21 @@ int pwrdm_read_logic_retst(struct powerd
  */
 int pwrdm_read_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
 {
-	u32 m;
+	int ret = -EINVAL;
 
 	if (!pwrdm)
-		return -EINVAL;
+		return ret;
 
 	if (pwrdm->banks < (bank + 1))
-		return -EEXIST;
+		return ret;
 
 	if (pwrdm->flags & PWRDM_HAS_MPU_QUIRK)
 		bank = 1;
 
-	/*
-	 * The register bit names below may not correspond to the
-	 * actual names of the bits in each powerdomain's register,
-	 * but the type of value returned is the same for each
-	 * powerdomain.
-	 */
-	switch (bank) {
-	case 0:
-		m = OMAP_MEM0_STATEST_MASK;
-		break;
-	case 1:
-		m = OMAP_MEM1_STATEST_MASK;
-		break;
-	case 2:
-		m = OMAP_MEM2_STATEST_MASK;
-		break;
-	case 3:
-		m = OMAP_MEM3_STATEST_MASK;
-		break;
-	case 4:
-		m = OMAP_MEM4_STATEST_MASK;
-		break;
-	default:
-		WARN_ON(1); /* should never happen */
-		return -EEXIST;
-	}
+	if (arch_pwrdm && arch_pwrdm->pwrdm_read_mem_pwrst)
+		ret = arch_pwrdm->pwrdm_read_mem_pwrst(pwrdm, bank);
 
-	return prm_read_mod_bits_shift(pwrdm->prcm_offs,
-					 pwrstst_reg_offs, m);
+	return ret;
 }
 
 /**
@@ -795,43 +686,21 @@ int pwrdm_read_mem_pwrst(struct powerdom
  */
 int pwrdm_read_prev_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
 {
-	u32 m;
+	int ret = -EINVAL;
 
 	if (!pwrdm)
-		return -EINVAL;
+		return ret;
 
 	if (pwrdm->banks < (bank + 1))
-		return -EEXIST;
+		return ret;
 
 	if (pwrdm->flags & PWRDM_HAS_MPU_QUIRK)
 		bank = 1;
 
-	/*
-	 * The register bit names below may not correspond to the
-	 * actual names of the bits in each powerdomain's register,
-	 * but the type of value returned is the same for each
-	 * powerdomain.
-	 */
-	switch (bank) {
-	case 0:
-		m = OMAP3430_LASTMEM1STATEENTERED_MASK;
-		break;
-	case 1:
-		m = OMAP3430_LASTMEM2STATEENTERED_MASK;
-		break;
-	case 2:
-		m = OMAP3430_LASTSHAREDL2CACHEFLATSTATEENTERED_MASK;
-		break;
-	case 3:
-		m = OMAP3430_LASTL2FLATMEMSTATEENTERED_MASK;
-		break;
-	default:
-		WARN_ON(1); /* should never happen */
-		return -EEXIST;
-	}
+	if (arch_pwrdm && arch_pwrdm->pwrdm_read_prev_mem_pwrst)
+		ret = arch_pwrdm->pwrdm_read_prev_mem_pwrst(pwrdm, bank);
 
-	return prm_read_mod_bits_shift(pwrdm->prcm_offs,
-					OMAP3430_PM_PREPWSTST, m);
+	return ret;
 }
 
 /**
@@ -846,43 +715,18 @@ int pwrdm_read_prev_mem_pwrst(struct pow
  */
 int pwrdm_read_mem_retst(struct powerdomain *pwrdm, u8 bank)
 {
-	u32 m;
+	int ret = -EINVAL;
 
 	if (!pwrdm)
-		return -EINVAL;
+		return ret;
 
 	if (pwrdm->banks < (bank + 1))
-		return -EEXIST;
+		return ret;
 
-	/*
-	 * The register bit names below may not correspond to the
-	 * actual names of the bits in each powerdomain's register,
-	 * but the type of value returned is the same for each
-	 * powerdomain.
-	 */
-	switch (bank) {
-	case 0:
-		m = OMAP_MEM0_RETSTATE_MASK;
-		break;
-	case 1:
-		m = OMAP_MEM1_RETSTATE_MASK;
-		break;
-	case 2:
-		m = OMAP_MEM2_RETSTATE_MASK;
-		break;
-	case 3:
-		m = OMAP_MEM3_RETSTATE_MASK;
-		break;
-	case 4:
-		m = OMAP_MEM4_RETSTATE_MASK;
-		break;
-	default:
-		WARN_ON(1); /* should never happen */
-		return -EEXIST;
-	}
+	if (arch_pwrdm && arch_pwrdm->pwrdm_read_mem_retst)
+		ret = arch_pwrdm->pwrdm_read_mem_retst(pwrdm, bank);
 
-	return prm_read_mod_bits_shift(pwrdm->prcm_offs,
-					pwrstctrl_reg_offs, m);
+	return ret;
 }
 
 /**
@@ -896,8 +740,10 @@ int pwrdm_read_mem_retst(struct powerdom
  */
 int pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm)
 {
+	int ret = -EINVAL;
+
 	if (!pwrdm)
-		return -EINVAL;
+		return ret;
 
 	/*
 	 * XXX should get the powerdomain's current state here;
@@ -907,9 +753,10 @@ int pwrdm_clear_all_prev_pwrst(struct po
 	pr_debug("powerdomain: clearing previous power state reg for %s\n",
 		 pwrdm->name);
 
-	prm_write_mod_reg(0, pwrdm->prcm_offs, OMAP3430_PM_PREPWSTST);
+	if (arch_pwrdm && arch_pwrdm->pwrdm_clear_all_prev_pwrst)
+		ret = arch_pwrdm->pwrdm_clear_all_prev_pwrst(pwrdm);
 
-	return 0;
+	return ret;
 }
 
 /**
@@ -925,19 +772,21 @@ int pwrdm_clear_all_prev_pwrst(struct po
  */
 int pwrdm_enable_hdwr_sar(struct powerdomain *pwrdm)
 {
+	int ret = -EINVAL;
+
 	if (!pwrdm)
-		return -EINVAL;
+		return ret;
 
 	if (!(pwrdm->flags & PWRDM_HAS_HDWR_SAR))
-		return -EINVAL;
+		return ret;
 
 	pr_debug("powerdomain: %s: setting SAVEANDRESTORE bit\n",
 		 pwrdm->name);
 
-	prm_rmw_mod_reg_bits(0, 1 << OMAP3430ES2_SAVEANDRESTORE_SHIFT,
-			     pwrdm->prcm_offs, pwrstctrl_reg_offs);
+	if (arch_pwrdm && arch_pwrdm->pwrdm_enable_hdwr_sar)
+		ret = arch_pwrdm->pwrdm_enable_hdwr_sar(pwrdm);
 
-	return 0;
+	return ret;
 }
 
 /**
@@ -953,19 +802,21 @@ int pwrdm_enable_hdwr_sar(struct powerdo
  */
 int pwrdm_disable_hdwr_sar(struct powerdomain *pwrdm)
 {
+	int ret = -EINVAL;
+
 	if (!pwrdm)
-		return -EINVAL;
+		return ret;
 
 	if (!(pwrdm->flags & PWRDM_HAS_HDWR_SAR))
-		return -EINVAL;
+		return ret;
 
 	pr_debug("powerdomain: %s: clearing SAVEANDRESTORE bit\n",
 		 pwrdm->name);
 
-	prm_rmw_mod_reg_bits(1 << OMAP3430ES2_SAVEANDRESTORE_SHIFT, 0,
-			     pwrdm->prcm_offs, pwrstctrl_reg_offs);
+	if (arch_pwrdm && arch_pwrdm->pwrdm_disable_hdwr_sar)
+		ret = arch_pwrdm->pwrdm_disable_hdwr_sar(pwrdm);
 
-	return 0;
+	return ret;
 }
 
 /**
@@ -992,6 +843,8 @@ bool pwrdm_has_hdwr_sar(struct powerdoma
  */
 int pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm)
 {
+	int ret = -EINVAL;
+
 	if (!pwrdm)
 		return -EINVAL;
 
@@ -1001,11 +854,10 @@ int pwrdm_set_lowpwrstchange(struct powe
 	pr_debug("powerdomain: %s: setting LOWPOWERSTATECHANGE bit\n",
 		 pwrdm->name);
 
-	prm_rmw_mod_reg_bits(OMAP4430_LOWPOWERSTATECHANGE_MASK,
-			     (1 << OMAP4430_LOWPOWERSTATECHANGE_SHIFT),
-			     pwrdm->prcm_offs, pwrstctrl_reg_offs);
+	if (arch_pwrdm && arch_pwrdm->pwrdm_set_lowpwrstchange)
+		ret = arch_pwrdm->pwrdm_set_lowpwrstchange(pwrdm);
 
-	return 0;
+	return ret;
 }
 
 /**
@@ -1020,32 +872,15 @@ int pwrdm_set_lowpwrstchange(struct powe
  */
 int pwrdm_wait_transition(struct powerdomain *pwrdm)
 {
-	u32 c = 0;
+	int ret = -EINVAL;
 
 	if (!pwrdm)
 		return -EINVAL;
 
-	/*
-	 * REVISIT: pwrdm_wait_transition() may be better implemented
-	 * via a callback and a periodic timer check -- how long do we expect
-	 * powerdomain transitions to take?
-	 */
-
-	/* XXX Is this udelay() value meaningful? */
-	while ((prm_read_mod_reg(pwrdm->prcm_offs, pwrstst_reg_offs) &
-		OMAP_INTRANSITION_MASK) &&
-	       (c++ < PWRDM_TRANSITION_BAILOUT))
-			udelay(1);
-
-	if (c > PWRDM_TRANSITION_BAILOUT) {
-		printk(KERN_ERR "powerdomain: waited too long for "
-		       "powerdomain %s to complete transition\n", pwrdm->name);
-		return -EAGAIN;
-	}
-
-	pr_debug("powerdomain: completed transition in %d loops\n", c);
+	if (arch_pwrdm && arch_pwrdm->pwrdm_wait_transition)
+		ret = arch_pwrdm->pwrdm_wait_transition(pwrdm);
 
-	return 0;
+	return ret;
 }
 
 int pwrdm_state_switch(struct powerdomain *pwrdm)
@@ -1075,3 +910,31 @@ int pwrdm_post_transition(void)
 	return 0;
 }
 
+/**
+ * pwrdm_get_context_loss_count - get powerdomain's context loss count
+ * @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
+ * (and WARNs) upon error, otherwise, returns the context loss count.
+ */
+u32 pwrdm_get_context_loss_count(struct powerdomain *pwrdm)
+{
+	int i, count;
+
+	if (!pwrdm) {
+		WARN(1, "powerdomain: %s: pwrdm is null\n", __func__);
+		return 0;
+	}
+
+	count = pwrdm->state_counter[PWRDM_POWER_OFF];
+	count += pwrdm->ret_logic_off_counter;
+
+	for (i = 0; i < pwrdm->banks; i++)
+		count += pwrdm->ret_mem_off_counter[i];
+
+	pr_debug("powerdomain: %s: context loss count = %u\n",
+		 pwrdm->name, count);
+
+	return count;
+}
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/powerdomain-common.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/powerdomain-common.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/powerdomain-common.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/powerdomain-common.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,110 @@
+/*
+ *  linux/arch/arm/mach-omap2/powerdomain-common.c
+ *  Contains common powerdomain framework functions
+ *
+ *  Copyright (C) 2010 Texas Instruments, Inc.
+ *  Copyright (C) 2010 Nokia Corporation
+ *
+ * Derived from mach-omap2/powerdomain.c written by Paul Walmsley
+ *
+ * This program is free software; you can 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/kernel.h>
+#include "pm.h"
+#include "cm.h"
+#include "cm-regbits-34xx.h"
+#include "cm-regbits-44xx.h"
+#include "prm-regbits-34xx.h"
+#include "prm-regbits-44xx.h"
+
+/*
+ * OMAP3 and OMAP4 specific register bit initialisations
+ * Notice that the names here are not according to each power
+ * domain but the bit mapping used applies to all of them
+ */
+/* OMAP3 and OMAP4 Memory Onstate Masks (common across all power domains) */
+#define OMAP_MEM0_ONSTATE_MASK OMAP3430_SHAREDL1CACHEFLATONSTATE_MASK
+#define OMAP_MEM1_ONSTATE_MASK OMAP3430_L1FLATMEMONSTATE_MASK
+#define OMAP_MEM2_ONSTATE_MASK OMAP3430_SHAREDL2CACHEFLATONSTATE_MASK
+#define OMAP_MEM3_ONSTATE_MASK OMAP3430_L2FLATMEMONSTATE_MASK
+#define OMAP_MEM4_ONSTATE_MASK OMAP4430_OCP_NRET_BANK_ONSTATE_MASK
+
+/* OMAP3 and OMAP4 Memory Retstate Masks (common across all power domains) */
+#define OMAP_MEM0_RETSTATE_MASK OMAP3430_SHAREDL1CACHEFLATRETSTATE_MASK
+#define OMAP_MEM1_RETSTATE_MASK OMAP3430_L1FLATMEMRETSTATE_MASK
+#define OMAP_MEM2_RETSTATE_MASK OMAP3430_SHAREDL2CACHEFLATRETSTATE_MASK
+#define OMAP_MEM3_RETSTATE_MASK OMAP3430_L2FLATMEMRETSTATE_MASK
+#define OMAP_MEM4_RETSTATE_MASK OMAP4430_OCP_NRET_BANK_RETSTATE_MASK
+
+/* OMAP3 and OMAP4 Memory Status bits */
+#define OMAP_MEM0_STATEST_MASK OMAP3430_SHAREDL1CACHEFLATSTATEST_MASK
+#define OMAP_MEM1_STATEST_MASK OMAP3430_L1FLATMEMSTATEST_MASK
+#define OMAP_MEM2_STATEST_MASK OMAP3430_SHAREDL2CACHEFLATSTATEST_MASK
+#define OMAP_MEM3_STATEST_MASK OMAP3430_L2FLATMEMSTATEST_MASK
+#define OMAP_MEM4_STATEST_MASK OMAP4430_OCP_NRET_BANK_STATEST_MASK
+
+/* Common Internal functions used across OMAP rev's*/
+u32 omap2_pwrdm_get_mem_bank_onstate_mask(u8 bank)
+{
+	switch (bank) {
+	case 0:
+		return OMAP_MEM0_ONSTATE_MASK;
+	case 1:
+		return OMAP_MEM1_ONSTATE_MASK;
+	case 2:
+		return OMAP_MEM2_ONSTATE_MASK;
+	case 3:
+		return OMAP_MEM3_ONSTATE_MASK;
+	case 4:
+		return OMAP_MEM4_ONSTATE_MASK;
+	default:
+		WARN_ON(1); /* should never happen */
+		return -EEXIST;
+	}
+	return 0;
+}
+
+u32 omap2_pwrdm_get_mem_bank_retst_mask(u8 bank)
+{
+	switch (bank) {
+	case 0:
+		return OMAP_MEM0_RETSTATE_MASK;
+	case 1:
+		return OMAP_MEM1_RETSTATE_MASK;
+	case 2:
+		return OMAP_MEM2_RETSTATE_MASK;
+	case 3:
+		return OMAP_MEM3_RETSTATE_MASK;
+	case 4:
+		return OMAP_MEM4_RETSTATE_MASK;
+	default:
+		WARN_ON(1); /* should never happen */
+		return -EEXIST;
+	}
+	return 0;
+}
+
+u32 omap2_pwrdm_get_mem_bank_stst_mask(u8 bank)
+{
+	switch (bank) {
+	case 0:
+		return OMAP_MEM0_STATEST_MASK;
+	case 1:
+		return OMAP_MEM1_STATEST_MASK;
+	case 2:
+		return OMAP_MEM2_STATEST_MASK;
+	case 3:
+		return OMAP_MEM3_STATEST_MASK;
+	case 4:
+		return OMAP_MEM4_STATEST_MASK;
+	default:
+		WARN_ON(1); /* should never happen */
+		return -EEXIST;
+	}
+	return 0;
+}
+
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/powerdomain.h linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/powerdomain.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/powerdomain.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/powerdomain.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,233 @@
+/*
+ * OMAP2/3/4 powerdomain control
+ *
+ * Copyright (C) 2007-2008, 2010 Texas Instruments, Inc.
+ * Copyright (C) 2007-2010 Nokia Corporation
+ *
+ * Paul Walmsley
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * XXX This should be moved to the mach-omap2/ directory at the earliest
+ * opportunity.
+ */
+
+#ifndef __ARCH_ARM_MACH_OMAP2_POWERDOMAIN_H
+#define __ARCH_ARM_MACH_OMAP2_POWERDOMAIN_H
+
+#include <linux/types.h>
+#include <linux/list.h>
+
+#include <linux/atomic.h>
+
+#include <plat/cpu.h>
+
+/* Powerdomain basic power states */
+#define PWRDM_POWER_OFF		0x0
+#define PWRDM_POWER_RET		0x1
+#define PWRDM_POWER_INACTIVE	0x2
+#define PWRDM_POWER_ON		0x3
+
+#define PWRDM_MAX_PWRSTS	4
+
+/* Powerdomain allowable state bitfields */
+#define PWRSTS_ON		(1 << PWRDM_POWER_ON)
+#define PWRSTS_OFF		(1 << PWRDM_POWER_OFF)
+#define PWRSTS_OFF_ON		((1 << PWRDM_POWER_OFF) | \
+				 (1 << PWRDM_POWER_ON))
+
+#define PWRSTS_OFF_RET		((1 << PWRDM_POWER_OFF) | \
+				 (1 << PWRDM_POWER_RET))
+
+#define PWRSTS_RET_ON		((1 << PWRDM_POWER_RET) | \
+				 (1 << PWRDM_POWER_ON))
+
+#define PWRSTS_OFF_RET_ON	(PWRSTS_OFF_RET | (1 << PWRDM_POWER_ON))
+
+
+/* Powerdomain flags */
+#define PWRDM_HAS_HDWR_SAR	(1 << 0) /* hardware save-and-restore support */
+#define PWRDM_HAS_MPU_QUIRK	(1 << 1) /* MPU pwr domain has MEM bank 0 bits
+					  * in MEM bank 1 position. This is
+					  * true for OMAP3430
+					  */
+#define PWRDM_HAS_LOWPOWERSTATECHANGE	(1 << 2) /*
+						  * support to transition from a
+						  * sleep state to a lower sleep
+						  * state without waking up the
+						  * powerdomain
+						  */
+
+/*
+ * Number of memory banks that are power-controllable.	On OMAP4430, the
+ * maximum is 5.
+ */
+#define PWRDM_MAX_MEM_BANKS	5
+
+/*
+ * Maximum number of clockdomains that can be associated with a powerdomain.
+ * CORE powerdomain on OMAP4 is the worst case
+ */
+#define PWRDM_MAX_CLKDMS	9
+
+/* XXX A completely arbitrary number. What is reasonable here? */
+#define PWRDM_TRANSITION_BAILOUT 100000
+
+struct clockdomain;
+struct powerdomain;
+
+/**
+ * struct powerdomain - OMAP powerdomain
+ * @name: Powerdomain name
+ * @omap_chip: represents the OMAP chip types containing this pwrdm
+ * @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
+ * @pwrsts_logic_ret: Possible logic power states when pwrdm in RETENTION
+ * @flags: Powerdomain flags
+ * @banks: Number of software-controllable memory banks in this powerdomain
+ * @pwrsts_mem_ret: Possible memory bank pwrstates when pwrdm in RETENTION
+ * @pwrsts_mem_on: Possible memory bank pwrstates when pwrdm in ON
+ * @pwrdm_clkdms: Clockdomains in this powerdomain
+ * @node: list_head linking all powerdomains
+ * @state:
+ * @state_counter:
+ * @timer:
+ * @state_timer:
+ *
+ * @prcm_partition possible values are defined in mach-omap2/prcm44xx.h.
+ */
+struct powerdomain {
+	const char *name;
+	const struct omap_chip_id omap_chip;
+	const s16 prcm_offs;
+	const u8 pwrsts;
+	const u8 pwrsts_logic_ret;
+	const u8 flags;
+	const u8 banks;
+	const u8 pwrsts_mem_ret[PWRDM_MAX_MEM_BANKS];
+	const u8 pwrsts_mem_on[PWRDM_MAX_MEM_BANKS];
+	const u8 prcm_partition;
+	struct clockdomain *pwrdm_clkdms[PWRDM_MAX_CLKDMS];
+	struct list_head node;
+	int state;
+	unsigned state_counter[PWRDM_MAX_PWRSTS];
+	unsigned ret_logic_off_counter;
+	unsigned ret_mem_off_counter[PWRDM_MAX_MEM_BANKS];
+
+#ifdef CONFIG_PM_DEBUG
+	s64 timer;
+	s64 state_timer[PWRDM_MAX_PWRSTS];
+#endif
+};
+
+/**
+ * struct pwrdm_ops - Arch specfic function implementations
+ * @pwrdm_set_next_pwrst: Set the target power state for a pd
+ * @pwrdm_read_next_pwrst: Read the target power state set for a pd
+ * @pwrdm_read_pwrst: Read the current power state of a pd
+ * @pwrdm_read_prev_pwrst: Read the prev power state entered by the pd
+ * @pwrdm_set_logic_retst: Set the logic state in RET for a pd
+ * @pwrdm_set_mem_onst: Set the Memory state in ON for a pd
+ * @pwrdm_set_mem_retst: Set the Memory state in RET for a pd
+ * @pwrdm_read_logic_pwrst: Read the current logic state of a pd
+ * @pwrdm_read_prev_logic_pwrst: Read the previous logic state entered by a pd
+ * @pwrdm_read_logic_retst: Read the logic state in RET for a pd
+ * @pwrdm_read_mem_pwrst: Read the current memory state of a pd
+ * @pwrdm_read_prev_mem_pwrst: Read the previous memory state entered by a pd
+ * @pwrdm_read_mem_retst: Read the memory state in RET for a pd
+ * @pwrdm_clear_all_prev_pwrst: Clear all previous power states logged for a pd
+ * @pwrdm_enable_hdwr_sar: Enable Hardware Save-Restore feature for the pd
+ * @pwrdm_disable_hdwr_sar: Disable Hardware Save-Restore feature for a pd
+ * @pwrdm_set_lowpwrstchange: Enable pd transitions from a shallow to deep sleep
+ * @pwrdm_wait_transition: Wait for a pd state transition to complete
+ */
+struct pwrdm_ops {
+	int	(*pwrdm_set_next_pwrst)(struct powerdomain *pwrdm, u8 pwrst);
+	int	(*pwrdm_read_next_pwrst)(struct powerdomain *pwrdm);
+	int	(*pwrdm_read_pwrst)(struct powerdomain *pwrdm);
+	int	(*pwrdm_read_prev_pwrst)(struct powerdomain *pwrdm);
+	int	(*pwrdm_set_logic_retst)(struct powerdomain *pwrdm, u8 pwrst);
+	int	(*pwrdm_set_mem_onst)(struct powerdomain *pwrdm, u8 bank, u8 pwrst);
+	int	(*pwrdm_set_mem_retst)(struct powerdomain *pwrdm, u8 bank, u8 pwrst);
+	int	(*pwrdm_read_logic_pwrst)(struct powerdomain *pwrdm);
+	int	(*pwrdm_read_prev_logic_pwrst)(struct powerdomain *pwrdm);
+	int	(*pwrdm_read_logic_retst)(struct powerdomain *pwrdm);
+	int	(*pwrdm_read_mem_pwrst)(struct powerdomain *pwrdm, u8 bank);
+	int	(*pwrdm_read_prev_mem_pwrst)(struct powerdomain *pwrdm, u8 bank);
+	int	(*pwrdm_read_mem_retst)(struct powerdomain *pwrdm, u8 bank);
+	int	(*pwrdm_clear_all_prev_pwrst)(struct powerdomain *pwrdm);
+	int	(*pwrdm_enable_hdwr_sar)(struct powerdomain *pwrdm);
+	int	(*pwrdm_disable_hdwr_sar)(struct powerdomain *pwrdm);
+	int	(*pwrdm_set_lowpwrstchange)(struct powerdomain *pwrdm);
+	int	(*pwrdm_wait_transition)(struct powerdomain *pwrdm);
+};
+
+void pwrdm_fw_init(void);
+void pwrdm_init(struct powerdomain **pwrdm_list, struct pwrdm_ops *custom_funcs);
+
+struct powerdomain *pwrdm_lookup(const char *name);
+
+int pwrdm_for_each(int (*fn)(struct powerdomain *pwrdm, void *user),
+			void *user);
+int pwrdm_for_each_nolock(int (*fn)(struct powerdomain *pwrdm, void *user),
+			void *user);
+
+int pwrdm_add_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm);
+int pwrdm_del_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm);
+int pwrdm_for_each_clkdm(struct powerdomain *pwrdm,
+			 int (*fn)(struct powerdomain *pwrdm,
+				   struct clockdomain *clkdm));
+
+int pwrdm_get_mem_bank_count(struct powerdomain *pwrdm);
+
+int pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst);
+int pwrdm_read_next_pwrst(struct powerdomain *pwrdm);
+int pwrdm_read_pwrst(struct powerdomain *pwrdm);
+int pwrdm_read_prev_pwrst(struct powerdomain *pwrdm);
+int pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm);
+
+int pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst);
+int pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank, u8 pwrst);
+int pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 bank, u8 pwrst);
+
+int pwrdm_read_logic_pwrst(struct powerdomain *pwrdm);
+int pwrdm_read_prev_logic_pwrst(struct powerdomain *pwrdm);
+int pwrdm_read_logic_retst(struct powerdomain *pwrdm);
+int pwrdm_read_mem_pwrst(struct powerdomain *pwrdm, u8 bank);
+int pwrdm_read_prev_mem_pwrst(struct powerdomain *pwrdm, u8 bank);
+int pwrdm_read_mem_retst(struct powerdomain *pwrdm, u8 bank);
+
+int pwrdm_enable_hdwr_sar(struct powerdomain *pwrdm);
+int pwrdm_disable_hdwr_sar(struct powerdomain *pwrdm);
+bool pwrdm_has_hdwr_sar(struct powerdomain *pwrdm);
+
+int pwrdm_wait_transition(struct powerdomain *pwrdm);
+
+int pwrdm_state_switch(struct powerdomain *pwrdm);
+int pwrdm_clkdm_state_switch(struct clockdomain *clkdm);
+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);
+
+extern void omap2xxx_powerdomains_init(void);
+extern void omap3xxx_powerdomains_init(void);
+extern void omap44xx_powerdomains_init(void);
+
+extern struct pwrdm_ops omap2_pwrdm_operations;
+extern struct pwrdm_ops omap3_pwrdm_operations;
+extern struct pwrdm_ops omap4_pwrdm_operations;
+
+/* Common Internal functions used across OMAP rev's */
+extern u32 omap2_pwrdm_get_mem_bank_onstate_mask(u8 bank);
+extern u32 omap2_pwrdm_get_mem_bank_retst_mask(u8 bank);
+extern u32 omap2_pwrdm_get_mem_bank_stst_mask(u8 bank);
+
+extern struct powerdomain wkup_omap2_pwrdm;
+extern struct powerdomain gfx_omap2_pwrdm;
+
+
+#endif
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/powerdomains24xx.h linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/powerdomains24xx.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/powerdomains24xx.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/powerdomains24xx.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,115 +0,0 @@
-/*
- * OMAP24XX powerdomain definitions
- *
- * Copyright (C) 2007-2008 Texas Instruments, Inc.
- * Copyright (C) 2007-2009 Nokia Corporation
- *
- * Written by Paul Walmsley
- * Debugging and integration fixes by Jouni Högander
- *
- * This program is free software; you can 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_MACH_OMAP2_POWERDOMAINS24XX
-#define ARCH_ARM_MACH_OMAP2_POWERDOMAINS24XX
-
-/*
- * N.B. If powerdomains are added or removed from this file, update
- * the array in mach-omap2/powerdomains.h.
- */
-
-#include <plat/powerdomain.h>
-
-#include "prcm-common.h"
-#include "prm.h"
-#include "prm-regbits-24xx.h"
-#include "cm.h"
-#include "cm-regbits-24xx.h"
-
-/* 24XX powerdomains and dependencies */
-
-#ifdef CONFIG_ARCH_OMAP2
-
-/* Powerdomains */
-
-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 = PWRDM_POWER_RET,
-	.banks		  = 1,
-	.pwrsts_mem_ret	  = {
-		[0] = PWRDM_POWER_RET,
-	},
-	.pwrsts_mem_on	  = {
-		[0] = PWRDM_POWER_ON,
-	},
-};
-
-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,
-	.pwrsts_mem_ret	  = {
-		[0] = PWRDM_POWER_RET,
-	},
-	.pwrsts_mem_on	  = {
-		[0] = PWRDM_POWER_ON,
-	},
-};
-
-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	  = {
-		[0] = PWRSTS_OFF_RET,	 /* MEM1RETSTATE */
-		[1] = PWRSTS_OFF_RET,	 /* MEM2RETSTATE */
-		[2] = PWRSTS_OFF_RET,	 /* MEM3RETSTATE */
-	},
-	.pwrsts_mem_on	  = {
-		[0] = PWRSTS_OFF_RET_ON, /* MEM1ONSTATE */
-		[1] = PWRSTS_OFF_RET_ON, /* MEM2ONSTATE */
-		[2] = PWRSTS_OFF_RET_ON, /* MEM3ONSTATE */
-	},
-};
-
-#endif	   /* CONFIG_ARCH_OMAP2 */
-
-
-
-/*
- * 2430-specific powerdomains
- */
-
-#ifdef CONFIG_ARCH_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 = PWRDM_POWER_RET,
-	.banks		  = 1,
-	.pwrsts_mem_ret	  = {
-		[0] = PWRDM_POWER_RET, /* MEMRETSTATE */
-	},
-	.pwrsts_mem_on	  = {
-		[0] = PWRDM_POWER_ON,  /* MEMONSTATE */
-	},
-};
-
-#endif     /* CONFIG_ARCH_OMAP2430 */
-
-
-#endif
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/powerdomains2xxx_3xxx_data.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/powerdomains2xxx_3xxx_data.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/powerdomains2xxx_3xxx_data.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/powerdomains2xxx_3xxx_data.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,79 @@
+/*
+ * OMAP2/3 common powerdomain definitions
+ *
+ * Copyright (C) 2007-2008 Texas Instruments, Inc.
+ * Copyright (C) 2007-2010 Nokia Corporation
+ *
+ * Paul Walmsley, Jouni Högander
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/*
+ * 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.
+ *
+ * On the 2420, this is a 'C55 DSP called, simply, the DSP.  Its
+ * powerdomain is called the "DSP power domain."  On the 2430, the
+ * on-board DSP is a 'C64 DSP, now called (along with its hardware
+ * accelerators) the IVA2 or IVA2.1.  Its powerdomain is still called
+ * the "DSP power domain." On the 3430, the DSP is a 'C64 DSP like the
+ * 2430, also known as the IVA2; but its powerdomain is now called the
+ * "IVA2 power domain."
+ *
+ * The 2420 also has something called the IVA, which is a separate ARM
+ * core, and has nothing to do with the DSP/IVA2.
+ *
+ * Ideally the DSP/IVA2 could just be the same powerdomain, but the PRCM
+ * address offset is different between the C55 and C64 DSPs.
+ */
+
+#include "powerdomain.h"
+
+#include "prcm-common.h"
+#include "prm.h"
+
+/* OMAP2/3-common powerdomains */
+
+/*
+ * The GFX powerdomain is not present on 3430ES2, but currently we do not
+ * have a macro to filter it out at compile-time.
+ */
+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 = PWRDM_POWER_RET,
+	.banks		  = 1,
+	.pwrsts_mem_ret	  = {
+		[0] = PWRDM_POWER_RET, /* MEMRETSTATE */
+	},
+	.pwrsts_mem_on	  = {
+		[0] = PWRDM_POWER_ON,  /* MEMONSTATE */
+	},
+};
+
+struct powerdomain wkup_omap2_pwrdm = {
+	.name		= "wkup_pwrdm",
+	.prcm_offs	= WKUP_MOD,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP24XX | CHIP_IS_OMAP3430),
+};
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/powerdomains2xxx_3xxx_data.h linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/powerdomains2xxx_3xxx_data.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/powerdomains2xxx_3xxx_data.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/powerdomains2xxx_3xxx_data.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,22 @@
+/*
+ * OMAP2/3 common powerdomains - prototypes
+ *
+ * Copyright (C) 2008 Texas Instruments, Inc.
+ * Copyright (C) 2008-2010 Nokia Corporation
+ *
+ * Paul Walmsley
+ *
+ * This program is free software; you can 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_MACH_OMAP2_POWERDOMAINS2XXX_3XXX_DATA_H
+#define __ARCH_ARM_MACH_OMAP2_POWERDOMAINS2XXX_3XXX_DATA_H
+
+#include "powerdomain.h"
+
+extern struct powerdomain gfx_omap2_pwrdm;
+extern struct powerdomain wkup_omap2_pwrdm;
+
+#endif
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/powerdomains2xxx_data.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/powerdomains2xxx_data.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/powerdomains2xxx_data.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/powerdomains2xxx_data.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,123 @@
+/*
+ * OMAP2XXX powerdomain definitions
+ *
+ * Copyright (C) 2007-2008 Texas Instruments, Inc.
+ * Copyright (C) 2007-2010 Nokia Corporation
+ *
+ * Paul Walmsley, Jouni Högander
+ *
+ * This program is free software; you can 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 "powerdomain.h"
+#include "powerdomains2xxx_3xxx_data.h"
+
+#include "prcm-common.h"
+#include "prm2xxx_3xxx.h"
+#include "prm-regbits-24xx.h"
+
+/* 24XX powerdomains and dependencies */
+
+/* Powerdomains */
+
+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 = PWRDM_POWER_RET,
+	.banks		  = 1,
+	.pwrsts_mem_ret	  = {
+		[0] = PWRDM_POWER_RET,
+	},
+	.pwrsts_mem_on	  = {
+		[0] = PWRDM_POWER_ON,
+	},
+};
+
+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,
+	.pwrsts_mem_ret	  = {
+		[0] = PWRDM_POWER_RET,
+	},
+	.pwrsts_mem_on	  = {
+		[0] = PWRDM_POWER_ON,
+	},
+};
+
+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	  = {
+		[0] = PWRSTS_OFF_RET,	 /* MEM1RETSTATE */
+		[1] = PWRSTS_OFF_RET,	 /* MEM2RETSTATE */
+		[2] = PWRSTS_OFF_RET,	 /* MEM3RETSTATE */
+	},
+	.pwrsts_mem_on	  = {
+		[0] = PWRSTS_OFF_RET_ON, /* MEM1ONSTATE */
+		[1] = PWRSTS_OFF_RET_ON, /* MEM2ONSTATE */
+		[2] = PWRSTS_OFF_RET_ON, /* MEM3ONSTATE */
+	},
+};
+
+
+/*
+ * 2430-specific powerdomains
+ */
+
+#ifdef CONFIG_ARCH_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 = PWRDM_POWER_RET,
+	.banks		  = 1,
+	.pwrsts_mem_ret	  = {
+		[0] = PWRDM_POWER_RET, /* MEMRETSTATE */
+	},
+	.pwrsts_mem_on	  = {
+		[0] = PWRDM_POWER_ON,  /* MEMONSTATE */
+	},
+};
+
+#endif     /* CONFIG_ARCH_OMAP2430 */
+
+/* As powerdomains are added or removed above, this list must also be changed */
+static struct powerdomain *powerdomains_omap2xxx[] __initdata = {
+
+	&wkup_omap2_pwrdm,
+	&gfx_omap2_pwrdm,
+
+#ifdef CONFIG_ARCH_OMAP2
+	&dsp_pwrdm,
+	&mpu_24xx_pwrdm,
+	&core_24xx_pwrdm,
+#endif
+
+#ifdef CONFIG_ARCH_OMAP2430
+	&mdm_pwrdm,
+#endif
+	NULL
+};
+
+void __init omap2xxx_powerdomains_init(void)
+{
+	pwrdm_init(powerdomains_omap2xxx, &omap2_pwrdm_operations);
+}
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/powerdomains34xx.h linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/powerdomains34xx.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/powerdomains34xx.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/powerdomains34xx.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,259 +0,0 @@
-/*
- * OMAP3 powerdomain definitions
- *
- * Copyright (C) 2007-2008 Texas Instruments, Inc.
- * Copyright (C) 2007-2010 Nokia Corporation
- *
- * Written by Paul Walmsley
- * Debugging and integration fixes by Jouni Högander
- *
- * This program is free software; you can 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_MACH_OMAP2_POWERDOMAINS34XX
-#define ARCH_ARM_MACH_OMAP2_POWERDOMAINS34XX
-
-/*
- * N.B. If powerdomains are added or removed from this file, update
- * the array in mach-omap2/powerdomains.h.
- */
-
-#include <plat/powerdomain.h>
-
-#include "prcm-common.h"
-#include "prm.h"
-#include "prm-regbits-34xx.h"
-#include "cm.h"
-#include "cm-regbits-34xx.h"
-
-/*
- * 34XX-specific powerdomains, dependencies
- */
-
-#ifdef CONFIG_ARCH_OMAP3
-
-/*
- * Powerdomains
- */
-
-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,
-	.pwrsts_mem_ret	  = {
-		[0] = PWRSTS_OFF_RET,
-		[1] = PWRSTS_OFF_RET,
-		[2] = PWRSTS_OFF_RET,
-		[3] = PWRSTS_OFF_RET,
-	},
-	.pwrsts_mem_on	  = {
-		[0] = PWRDM_POWER_ON,
-		[1] = PWRDM_POWER_ON,
-		[2] = PWRSTS_OFF_ON,
-		[3] = PWRDM_POWER_ON,
-	},
-};
-
-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,
-	.banks		  = 1,
-	.pwrsts_mem_ret	  = {
-		[0] = PWRSTS_OFF_RET,
-	},
-	.pwrsts_mem_on	  = {
-		[0] = PWRSTS_OFF_ON,
-	},
-};
-
-/*
- * The USBTLL Save-and-Restore mechanism is broken on
- * 3430s upto ES3.0 and 3630ES1.0. Hence this feature
- * needs to be disabled on these chips.
- * Refer: 3430 errata ID i459 and 3630 errata ID i579
- */
-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,
-	.pwrsts_mem_ret	  = {
-		[0] = PWRSTS_OFF_RET,	 /* MEM1RETSTATE */
-		[1] = PWRSTS_OFF_RET,	 /* MEM2RETSTATE */
-	},
-	.pwrsts_mem_on	  = {
-		[0] = PWRSTS_OFF_RET_ON, /* MEM1ONSTATE */
-		[1] = PWRSTS_OFF_RET_ON, /* MEM2ONSTATE */
-	},
-};
-
-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,
-	.flags		  = PWRDM_HAS_HDWR_SAR, /* for USBTLL only */
-	.banks		  = 2,
-	.pwrsts_mem_ret	  = {
-		[0] = PWRSTS_OFF_RET,	 /* MEM1RETSTATE */
-		[1] = PWRSTS_OFF_RET,	 /* MEM2RETSTATE */
-	},
-	.pwrsts_mem_on	  = {
-		[0] = PWRSTS_OFF_RET_ON, /* MEM1ONSTATE */
-		[1] = PWRSTS_OFF_RET_ON, /* MEM2ONSTATE */
-	},
-};
-
-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 = PWRDM_POWER_RET,
-	.banks		  = 1,
-	.pwrsts_mem_ret	  = {
-		[0] = PWRDM_POWER_RET, /* MEMRETSTATE */
-	},
-	.pwrsts_mem_on	  = {
-		[0] = PWRDM_POWER_ON,  /* MEMONSTATE */
-	},
-};
-
-/*
- * Although the 34XX TRM Rev K Table 4-371 notes that retention is a
- * possible SGX powerstate, the SGX device itself does not support
- * retention.
- */
-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 = PWRDM_POWER_RET,
-	.banks		  = 1,
-	.pwrsts_mem_ret	  = {
-		[0] = PWRDM_POWER_RET, /* MEMRETSTATE */
-	},
-	.pwrsts_mem_on	  = {
-		[0] = PWRDM_POWER_ON,  /* MEMONSTATE */
-	},
-};
-
-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 = PWRDM_POWER_RET,
-	.banks		  = 1,
-	.pwrsts_mem_ret	  = {
-		[0] = PWRDM_POWER_RET, /* MEMRETSTATE */
-	},
-	.pwrsts_mem_on	  = {
-		[0] = PWRDM_POWER_ON,  /* MEMONSTATE */
-	},
-};
-
-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,
-	.pwrsts_mem_ret	  = {
-		[0] = PWRDM_POWER_RET, /* MEMRETSTATE */
-	},
-	.pwrsts_mem_on	  = {
-		[0] = PWRDM_POWER_ON,  /* MEMONSTATE */
-	},
-};
-
-static struct powerdomain emu_pwrdm = {
-	.name		= "emu_pwrdm",
-	.prcm_offs	= OMAP3430_EMU_MOD,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
-};
-
-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 = PWRDM_POWER_RET,
-};
-
-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 = PWRDM_POWER_RET,
-	/*
-	 * REVISIT: Enabling usb host save and restore mechanism seems to
-	 * leave the usb host domain permanently in ACTIVE mode after
-	 * changing the usb host power domain state from OFF to active once.
-	 * Disabling for now.
-	 */
-	/*.flags	  = PWRDM_HAS_HDWR_SAR,*/ /* for USBHOST ctrlr only */
-	.banks		  = 1,
-	.pwrsts_mem_ret	  = {
-		[0] = PWRDM_POWER_RET, /* MEMRETSTATE */
-	},
-	.pwrsts_mem_on	  = {
-		[0] = PWRDM_POWER_ON,  /* MEMONSTATE */
-	},
-};
-
-static struct powerdomain dpll1_pwrdm = {
-	.name		= "dpll1_pwrdm",
-	.prcm_offs	= MPU_MOD,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
-};
-
-static struct powerdomain dpll2_pwrdm = {
-	.name		= "dpll2_pwrdm",
-	.prcm_offs	= OMAP3430_IVA2_MOD,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
-};
-
-static struct powerdomain dpll3_pwrdm = {
-	.name		= "dpll3_pwrdm",
-	.prcm_offs	= PLL_MOD,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
-};
-
-static struct powerdomain dpll4_pwrdm = {
-	.name		= "dpll4_pwrdm",
-	.prcm_offs	= PLL_MOD,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
-};
-
-static struct powerdomain dpll5_pwrdm = {
-	.name		= "dpll5_pwrdm",
-	.prcm_offs	= PLL_MOD,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_GE_OMAP3430ES2),
-};
-
-
-#endif    /* CONFIG_ARCH_OMAP3 */
-
-
-#endif
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/powerdomains3xxx_data.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/powerdomains3xxx_data.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/powerdomains3xxx_data.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/powerdomains3xxx_data.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,287 @@
+/*
+ * OMAP3 powerdomain definitions
+ *
+ * Copyright (C) 2007-2008 Texas Instruments, Inc.
+ * Copyright (C) 2007-2010 Nokia Corporation
+ *
+ * Paul Walmsley, Jouni Högander
+ *
+ * This program is free software; you can 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 "powerdomain.h"
+#include "powerdomains2xxx_3xxx_data.h"
+
+#include "prcm-common.h"
+#include "prm2xxx_3xxx.h"
+#include "prm-regbits-34xx.h"
+#include "cm2xxx_3xxx.h"
+#include "cm-regbits-34xx.h"
+
+/*
+ * 34XX-specific powerdomains, dependencies
+ */
+
+#ifdef CONFIG_ARCH_OMAP3
+
+/*
+ * Powerdomains
+ */
+
+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,
+	.pwrsts_mem_ret	  = {
+		[0] = PWRSTS_OFF_RET,
+		[1] = PWRSTS_OFF_RET,
+		[2] = PWRSTS_OFF_RET,
+		[3] = PWRSTS_OFF_RET,
+	},
+	.pwrsts_mem_on	  = {
+		[0] = PWRDM_POWER_ON,
+		[1] = PWRDM_POWER_ON,
+		[2] = PWRSTS_OFF_ON,
+		[3] = PWRDM_POWER_ON,
+	},
+};
+
+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,
+	.banks		  = 1,
+	.pwrsts_mem_ret	  = {
+		[0] = PWRSTS_OFF_RET,
+	},
+	.pwrsts_mem_on	  = {
+		[0] = PWRSTS_OFF_ON,
+	},
+};
+
+/*
+ * The USBTLL Save-and-Restore mechanism is broken on
+ * 3430s upto ES3.0 and 3630ES1.0. Hence this feature
+ * needs to be disabled on these chips.
+ * Refer: 3430 errata ID i459 and 3630 errata ID i579
+ *
+ * Note: setting the SAR flag could help for errata ID i478
+ *  which applies to 3430 <= ES3.1, but since the SAR feature
+ *  is broken, do not use it.
+ */
+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,
+	.pwrsts_mem_ret	  = {
+		[0] = PWRSTS_OFF_RET,	 /* MEM1RETSTATE */
+		[1] = PWRSTS_OFF_RET,	 /* MEM2RETSTATE */
+	},
+	.pwrsts_mem_on	  = {
+		[0] = PWRSTS_OFF_RET_ON, /* MEM1ONSTATE */
+		[1] = PWRSTS_OFF_RET_ON, /* MEM2ONSTATE */
+	},
+};
+
+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,
+	/*
+	 * Setting the SAR flag for errata ID i478 which applies
+	 *  to 3430 <= ES3.1
+	 */
+	.flags		  = PWRDM_HAS_HDWR_SAR, /* for USBTLL only */
+	.banks		  = 2,
+	.pwrsts_mem_ret	  = {
+		[0] = PWRSTS_OFF_RET,	 /* MEM1RETSTATE */
+		[1] = PWRSTS_OFF_RET,	 /* MEM2RETSTATE */
+	},
+	.pwrsts_mem_on	  = {
+		[0] = PWRSTS_OFF_RET_ON, /* MEM1ONSTATE */
+		[1] = PWRSTS_OFF_RET_ON, /* MEM2ONSTATE */
+	},
+};
+
+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 = PWRDM_POWER_RET,
+	.banks		  = 1,
+	.pwrsts_mem_ret	  = {
+		[0] = PWRDM_POWER_RET, /* MEMRETSTATE */
+	},
+	.pwrsts_mem_on	  = {
+		[0] = PWRDM_POWER_ON,  /* MEMONSTATE */
+	},
+};
+
+/*
+ * Although the 34XX TRM Rev K Table 4-371 notes that retention is a
+ * possible SGX powerstate, the SGX device itself does not support
+ * retention.
+ */
+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 = PWRDM_POWER_RET,
+	.banks		  = 1,
+	.pwrsts_mem_ret	  = {
+		[0] = PWRDM_POWER_RET, /* MEMRETSTATE */
+	},
+	.pwrsts_mem_on	  = {
+		[0] = PWRDM_POWER_ON,  /* MEMONSTATE */
+	},
+};
+
+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 = PWRDM_POWER_RET,
+	.banks		  = 1,
+	.pwrsts_mem_ret	  = {
+		[0] = PWRDM_POWER_RET, /* MEMRETSTATE */
+	},
+	.pwrsts_mem_on	  = {
+		[0] = PWRDM_POWER_ON,  /* MEMONSTATE */
+	},
+};
+
+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,
+	.pwrsts_mem_ret	  = {
+		[0] = PWRDM_POWER_RET, /* MEMRETSTATE */
+	},
+	.pwrsts_mem_on	  = {
+		[0] = PWRDM_POWER_ON,  /* MEMONSTATE */
+	},
+};
+
+static struct powerdomain emu_pwrdm = {
+	.name		= "emu_pwrdm",
+	.prcm_offs	= OMAP3430_EMU_MOD,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+};
+
+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 = PWRDM_POWER_RET,
+};
+
+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 = PWRDM_POWER_RET,
+	/*
+	 * REVISIT: Enabling usb host save and restore mechanism seems to
+	 * leave the usb host domain permanently in ACTIVE mode after
+	 * changing the usb host power domain state from OFF to active once.
+	 * Disabling for now.
+	 */
+	/*.flags	  = PWRDM_HAS_HDWR_SAR,*/ /* for USBHOST ctrlr only */
+	.banks		  = 1,
+	.pwrsts_mem_ret	  = {
+		[0] = PWRDM_POWER_RET, /* MEMRETSTATE */
+	},
+	.pwrsts_mem_on	  = {
+		[0] = PWRDM_POWER_ON,  /* MEMONSTATE */
+	},
+};
+
+static struct powerdomain dpll1_pwrdm = {
+	.name		= "dpll1_pwrdm",
+	.prcm_offs	= MPU_MOD,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+};
+
+static struct powerdomain dpll2_pwrdm = {
+	.name		= "dpll2_pwrdm",
+	.prcm_offs	= OMAP3430_IVA2_MOD,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+};
+
+static struct powerdomain dpll3_pwrdm = {
+	.name		= "dpll3_pwrdm",
+	.prcm_offs	= PLL_MOD,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+};
+
+static struct powerdomain dpll4_pwrdm = {
+	.name		= "dpll4_pwrdm",
+	.prcm_offs	= PLL_MOD,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+};
+
+static struct powerdomain dpll5_pwrdm = {
+	.name		= "dpll5_pwrdm",
+	.prcm_offs	= PLL_MOD,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_GE_OMAP3430ES2),
+};
+
+/* As powerdomains are added or removed above, this list must also be changed */
+static struct powerdomain *powerdomains_omap3xxx[] __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,
+	&dpll5_pwrdm,
+#endif
+	NULL
+};
+
+
+void __init omap3xxx_powerdomains_init(void)
+{
+	pwrdm_init(powerdomains_omap3xxx, &omap3_pwrdm_operations);
+}
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/powerdomains44xx_data.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/powerdomains44xx_data.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/powerdomains44xx_data.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/powerdomains44xx_data.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,355 @@
+/*
+ * OMAP4 Power domains framework
+ *
+ * Copyright (C) 2009-2010 Texas Instruments, Inc.
+ * Copyright (C) 2009-2010 Nokia Corporation
+ *
+ * Abhijit Pagare (abhijitpagare@ti.com)
+ * Benoit Cousson (b-cousson@ti.com)
+ * Paul Walmsley (paul@pwsan.com)
+ *
+ * This file is automatically generated from the OMAP hardware databases.
+ * We respectfully ask that any modifications to this file be coordinated
+ * with the public linux-omap@vger.kernel.org mailing list and the
+ * authors above to ensure that the autogeneration scripts are kept
+ * up-to-date with the file contents.
+ *
+ * This program is free software; you can 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 "powerdomain.h"
+
+#include "prcm-common.h"
+#include "prcm44xx.h"
+#include "prm-regbits-44xx.h"
+#include "prm44xx.h"
+#include "prcm_mpu44xx.h"
+
+/* core_44xx_pwrdm: CORE power domain */
+static struct powerdomain core_44xx_pwrdm = {
+	.name		  = "core_pwrdm",
+	.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,
+	.pwrsts_mem_ret	= {
+		[0] = PWRDM_POWER_OFF,	/* core_nret_bank */
+		[1] = PWRSTS_OFF_RET,	/* core_ocmram */
+		[2] = PWRDM_POWER_RET,	/* core_other_bank */
+		[3] = PWRSTS_OFF_RET,	/* ducati_l2ram */
+		[4] = PWRSTS_OFF_RET,	/* ducati_unicache */
+	},
+	.pwrsts_mem_on	= {
+		[0] = PWRDM_POWER_ON,	/* core_nret_bank */
+		[1] = PWRSTS_OFF_RET,	/* core_ocmram */
+		[2] = PWRDM_POWER_ON,	/* core_other_bank */
+		[3] = PWRDM_POWER_ON,	/* ducati_l2ram */
+		[4] = PWRDM_POWER_ON,	/* ducati_unicache */
+	},
+	.flags		= PWRDM_HAS_LOWPOWERSTATECHANGE,
+};
+
+/* gfx_44xx_pwrdm: 3D accelerator power domain */
+static struct powerdomain gfx_44xx_pwrdm = {
+	.name		  = "gfx_pwrdm",
+	.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	= {
+		[0] = PWRDM_POWER_OFF,	/* gfx_mem */
+	},
+	.pwrsts_mem_on	= {
+		[0] = PWRDM_POWER_ON,	/* gfx_mem */
+	},
+	.flags		= PWRDM_HAS_LOWPOWERSTATECHANGE,
+};
+
+/* abe_44xx_pwrdm: Audio back end power domain */
+static struct powerdomain abe_44xx_pwrdm = {
+	.name		  = "abe_pwrdm",
+	.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 = PWRDM_POWER_OFF,
+	.banks		  = 2,
+	.pwrsts_mem_ret	= {
+		[0] = PWRDM_POWER_RET,	/* aessmem */
+		[1] = PWRDM_POWER_OFF,	/* periphmem */
+	},
+	.pwrsts_mem_on	= {
+		[0] = PWRDM_POWER_ON,	/* aessmem */
+		[1] = PWRDM_POWER_ON,	/* periphmem */
+	},
+	.flags		= PWRDM_HAS_LOWPOWERSTATECHANGE,
+};
+
+/* dss_44xx_pwrdm: Display subsystem power domain */
+static struct powerdomain dss_44xx_pwrdm = {
+	.name		  = "dss_pwrdm",
+	.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,
+	.pwrsts_mem_ret	= {
+		[0] = PWRDM_POWER_OFF,	/* dss_mem */
+	},
+	.pwrsts_mem_on	= {
+		[0] = PWRDM_POWER_ON,	/* dss_mem */
+	},
+	.flags		= PWRDM_HAS_LOWPOWERSTATECHANGE,
+};
+
+/* tesla_44xx_pwrdm: Tesla processor power domain */
+static struct powerdomain tesla_44xx_pwrdm = {
+	.name		  = "tesla_pwrdm",
+	.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,
+	.pwrsts_mem_ret	= {
+		[0] = PWRDM_POWER_RET,	/* tesla_edma */
+		[1] = PWRSTS_OFF_RET,	/* tesla_l1 */
+		[2] = PWRSTS_OFF_RET,	/* tesla_l2 */
+	},
+	.pwrsts_mem_on	= {
+		[0] = PWRDM_POWER_ON,	/* tesla_edma */
+		[1] = PWRDM_POWER_ON,	/* tesla_l1 */
+		[2] = PWRDM_POWER_ON,	/* tesla_l2 */
+	},
+	.flags		= PWRDM_HAS_LOWPOWERSTATECHANGE,
+};
+
+/* wkup_44xx_pwrdm: Wake-up power domain */
+static struct powerdomain wkup_44xx_pwrdm = {
+	.name		  = "wkup_pwrdm",
+	.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	= {
+		[0] = PWRDM_POWER_OFF,	/* wkup_bank */
+	},
+	.pwrsts_mem_on	= {
+		[0] = PWRDM_POWER_ON,	/* wkup_bank */
+	},
+};
+
+/* cpu0_44xx_pwrdm: MPU0 processor and Neon coprocessor power domain */
+static struct powerdomain cpu0_44xx_pwrdm = {
+	.name		  = "cpu0_pwrdm",
+	.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,
+	.pwrsts_mem_ret	= {
+		[0] = PWRSTS_OFF_RET,	/* cpu0_l1 */
+	},
+	.pwrsts_mem_on	= {
+		[0] = PWRDM_POWER_ON,	/* cpu0_l1 */
+	},
+};
+
+/* cpu1_44xx_pwrdm: MPU1 processor and Neon coprocessor power domain */
+static struct powerdomain cpu1_44xx_pwrdm = {
+	.name		  = "cpu1_pwrdm",
+	.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,
+	.pwrsts_mem_ret	= {
+		[0] = PWRSTS_OFF_RET,	/* cpu1_l1 */
+	},
+	.pwrsts_mem_on	= {
+		[0] = PWRDM_POWER_ON,	/* cpu1_l1 */
+	},
+};
+
+/* emu_44xx_pwrdm: Emulation power domain */
+static struct powerdomain emu_44xx_pwrdm = {
+	.name		  = "emu_pwrdm",
+	.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	= {
+		[0] = PWRDM_POWER_OFF,	/* emu_bank */
+	},
+	.pwrsts_mem_on	= {
+		[0] = PWRDM_POWER_ON,	/* emu_bank */
+	},
+};
+
+/* mpu_44xx_pwrdm: Modena processor and the Neon coprocessor power domain */
+static struct powerdomain mpu_44xx_pwrdm = {
+	.name		  = "mpu_pwrdm",
+	.prcm_offs	  = OMAP4430_PRM_MPU_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,
+	.pwrsts_mem_ret	= {
+		[0] = PWRSTS_OFF_RET,	/* mpu_l1 */
+		[1] = PWRSTS_OFF_RET,	/* mpu_l2 */
+		[2] = PWRDM_POWER_RET,	/* mpu_ram */
+	},
+	.pwrsts_mem_on	= {
+		[0] = PWRDM_POWER_ON,	/* mpu_l1 */
+		[1] = PWRDM_POWER_ON,	/* mpu_l2 */
+		[2] = PWRDM_POWER_ON,	/* mpu_ram */
+	},
+};
+
+/* ivahd_44xx_pwrdm: IVA-HD power domain */
+static struct powerdomain ivahd_44xx_pwrdm = {
+	.name		  = "ivahd_pwrdm",
+	.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 = PWRDM_POWER_OFF,
+	.banks		  = 4,
+	.pwrsts_mem_ret	= {
+		[0] = PWRDM_POWER_OFF,	/* hwa_mem */
+		[1] = PWRSTS_OFF_RET,	/* sl2_mem */
+		[2] = PWRSTS_OFF_RET,	/* tcm1_mem */
+		[3] = PWRSTS_OFF_RET,	/* tcm2_mem */
+	},
+	.pwrsts_mem_on	= {
+		[0] = PWRDM_POWER_ON,	/* hwa_mem */
+		[1] = PWRDM_POWER_ON,	/* sl2_mem */
+		[2] = PWRDM_POWER_ON,	/* tcm1_mem */
+		[3] = PWRDM_POWER_ON,	/* tcm2_mem */
+	},
+	.flags		= PWRDM_HAS_LOWPOWERSTATECHANGE,
+};
+
+/* cam_44xx_pwrdm: Camera subsystem power domain */
+static struct powerdomain cam_44xx_pwrdm = {
+	.name		  = "cam_pwrdm",
+	.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	= {
+		[0] = PWRDM_POWER_OFF,	/* cam_mem */
+	},
+	.pwrsts_mem_on	= {
+		[0] = PWRDM_POWER_ON,	/* cam_mem */
+	},
+	.flags		= PWRDM_HAS_LOWPOWERSTATECHANGE,
+};
+
+/* l3init_44xx_pwrdm: L3 initators pheripherals power domain  */
+static struct powerdomain l3init_44xx_pwrdm = {
+	.name		  = "l3init_pwrdm",
+	.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,
+	.pwrsts_mem_ret	= {
+		[0] = PWRDM_POWER_OFF,	/* l3init_bank1 */
+	},
+	.pwrsts_mem_on	= {
+		[0] = PWRDM_POWER_ON,	/* l3init_bank1 */
+	},
+	.flags		= PWRDM_HAS_LOWPOWERSTATECHANGE,
+};
+
+/* l4per_44xx_pwrdm: Target peripherals power domain */
+static struct powerdomain l4per_44xx_pwrdm = {
+	.name		  = "l4per_pwrdm",
+	.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,
+	.pwrsts_mem_ret	= {
+		[0] = PWRDM_POWER_OFF,	/* nonretained_bank */
+		[1] = PWRDM_POWER_RET,	/* retained_bank */
+	},
+	.pwrsts_mem_on	= {
+		[0] = PWRDM_POWER_ON,	/* nonretained_bank */
+		[1] = PWRDM_POWER_ON,	/* retained_bank */
+	},
+	.flags		= PWRDM_HAS_LOWPOWERSTATECHANGE,
+};
+
+/*
+ * always_on_core_44xx_pwrdm: Always ON logic that sits in VDD_CORE voltage
+ * domain
+ */
+static struct powerdomain always_on_core_44xx_pwrdm = {
+	.name		  = "always_on_core_pwrdm",
+	.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",
+	.prcm_offs	  = OMAP4430_PRM_CEFUSE_INST,
+	.prcm_partition	  = OMAP4430_PRM_PARTITION,
+	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+	.pwrsts		  = PWRSTS_OFF_ON,
+};
+
+/*
+ * The following power domains are not under SW control
+ *
+ * always_on_iva
+ * always_on_mpu
+ * stdefuse
+ */
+
+/* As powerdomains are added or removed above, this list must also be changed */
+static struct powerdomain *powerdomains_omap44xx[] __initdata = {
+	&core_44xx_pwrdm,
+	&gfx_44xx_pwrdm,
+	&abe_44xx_pwrdm,
+	&dss_44xx_pwrdm,
+	&tesla_44xx_pwrdm,
+	&wkup_44xx_pwrdm,
+	&cpu0_44xx_pwrdm,
+	&cpu1_44xx_pwrdm,
+	&emu_44xx_pwrdm,
+	&mpu_44xx_pwrdm,
+	&ivahd_44xx_pwrdm,
+	&cam_44xx_pwrdm,
+	&l3init_44xx_pwrdm,
+	&l4per_44xx_pwrdm,
+	&always_on_core_44xx_pwrdm,
+	&cefuse_44xx_pwrdm,
+	NULL
+};
+
+void __init omap44xx_powerdomains_init(void)
+{
+	pwrdm_init(powerdomains_omap44xx, &omap4_pwrdm_operations);
+}
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/powerdomains44xx.h linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/powerdomains44xx.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/powerdomains44xx.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/powerdomains44xx.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,319 +0,0 @@
-/*
- * OMAP4 Power domains framework
- *
- * Copyright (C) 2009-2010 Texas Instruments, Inc.
- * Copyright (C) 2009-2010 Nokia Corporation
- *
- * Abhijit Pagare (abhijitpagare@ti.com)
- * Benoit Cousson (b-cousson@ti.com)
- * Paul Walmsley (paul@pwsan.com)
- *
- * This file is automatically generated from the OMAP hardware databases.
- * We respectfully ask that any modifications to this file be coordinated
- * with the public linux-omap@vger.kernel.org mailing list and the
- * authors above to ensure that the autogeneration scripts are kept
- * up-to-date with the file contents.
- *
- * This program is free software; you can 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_MACH_OMAP2_POWERDOMAINS44XX_H
-#define __ARCH_ARM_MACH_OMAP2_POWERDOMAINS44XX_H
-
-#include <plat/powerdomain.h>
-
-#include "prcm-common.h"
-#include "cm.h"
-#include "cm-regbits-44xx.h"
-#include "prm.h"
-#include "prm-regbits-44xx.h"
-
-#if defined(CONFIG_ARCH_OMAP4)
-
-/* core_44xx_pwrdm: CORE power domain */
-static struct powerdomain core_44xx_pwrdm = {
-	.name		  = "core_pwrdm",
-	.prcm_offs	  = OMAP4430_PRM_CORE_MOD,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
-	.pwrsts		  = PWRSTS_RET_ON,
-	.pwrsts_logic_ret = PWRSTS_OFF_RET,
-	.banks		  = 5,
-	.pwrsts_mem_ret	= {
-		[0] = PWRDM_POWER_OFF,	/* core_nret_bank */
-		[1] = PWRSTS_OFF_RET,	/* core_ocmram */
-		[2] = PWRDM_POWER_RET,	/* core_other_bank */
-		[3] = PWRSTS_OFF_RET,	/* ducati_l2ram */
-		[4] = PWRSTS_OFF_RET,	/* ducati_unicache */
-	},
-	.pwrsts_mem_on	= {
-		[0] = PWRDM_POWER_ON,	/* core_nret_bank */
-		[1] = PWRSTS_OFF_RET,	/* core_ocmram */
-		[2] = PWRDM_POWER_ON,	/* core_other_bank */
-		[3] = PWRDM_POWER_ON,	/* ducati_l2ram */
-		[4] = PWRDM_POWER_ON,	/* ducati_unicache */
-	},
-	.flags		= PWRDM_HAS_LOWPOWERSTATECHANGE,
-};
-
-/* gfx_44xx_pwrdm: 3D accelerator power domain */
-static struct powerdomain gfx_44xx_pwrdm = {
-	.name		  = "gfx_pwrdm",
-	.prcm_offs	  = OMAP4430_PRM_GFX_MOD,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
-	.pwrsts		  = PWRSTS_OFF_ON,
-	.banks		  = 1,
-	.pwrsts_mem_ret	= {
-		[0] = PWRDM_POWER_OFF,	/* gfx_mem */
-	},
-	.pwrsts_mem_on	= {
-		[0] = PWRDM_POWER_ON,	/* gfx_mem */
-	},
-	.flags		= PWRDM_HAS_LOWPOWERSTATECHANGE,
-};
-
-/* abe_44xx_pwrdm: Audio back end power domain */
-static struct powerdomain abe_44xx_pwrdm = {
-	.name		  = "abe_pwrdm",
-	.prcm_offs	  = OMAP4430_PRM_ABE_MOD,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
-	.pwrsts		  = PWRSTS_OFF_RET_ON,
-	.pwrsts_logic_ret = PWRDM_POWER_OFF,
-	.banks		  = 2,
-	.pwrsts_mem_ret	= {
-		[0] = PWRDM_POWER_RET,	/* aessmem */
-		[1] = PWRDM_POWER_OFF,	/* periphmem */
-	},
-	.pwrsts_mem_on	= {
-		[0] = PWRDM_POWER_ON,	/* aessmem */
-		[1] = PWRDM_POWER_ON,	/* periphmem */
-	},
-	.flags		= PWRDM_HAS_LOWPOWERSTATECHANGE,
-};
-
-/* dss_44xx_pwrdm: Display subsystem power domain */
-static struct powerdomain dss_44xx_pwrdm = {
-	.name		  = "dss_pwrdm",
-	.prcm_offs	  = OMAP4430_PRM_DSS_MOD,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
-	.pwrsts		  = PWRSTS_OFF_RET_ON,
-	.pwrsts_logic_ret = PWRSTS_OFF,
-	.banks		  = 1,
-	.pwrsts_mem_ret	= {
-		[0] = PWRDM_POWER_OFF,	/* dss_mem */
-	},
-	.pwrsts_mem_on	= {
-		[0] = PWRDM_POWER_ON,	/* dss_mem */
-	},
-	.flags		= PWRDM_HAS_LOWPOWERSTATECHANGE,
-};
-
-/* tesla_44xx_pwrdm: Tesla processor power domain */
-static struct powerdomain tesla_44xx_pwrdm = {
-	.name		  = "tesla_pwrdm",
-	.prcm_offs	  = OMAP4430_PRM_TESLA_MOD,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
-	.pwrsts		  = PWRSTS_OFF_RET_ON,
-	.pwrsts_logic_ret = PWRSTS_OFF_RET,
-	.banks		  = 3,
-	.pwrsts_mem_ret	= {
-		[0] = PWRDM_POWER_RET,	/* tesla_edma */
-		[1] = PWRSTS_OFF_RET,	/* tesla_l1 */
-		[2] = PWRSTS_OFF_RET,	/* tesla_l2 */
-	},
-	.pwrsts_mem_on	= {
-		[0] = PWRDM_POWER_ON,	/* tesla_edma */
-		[1] = PWRDM_POWER_ON,	/* tesla_l1 */
-		[2] = PWRDM_POWER_ON,	/* tesla_l2 */
-	},
-	.flags		= PWRDM_HAS_LOWPOWERSTATECHANGE,
-};
-
-/* wkup_44xx_pwrdm: Wake-up power domain */
-static struct powerdomain wkup_44xx_pwrdm = {
-	.name		  = "wkup_pwrdm",
-	.prcm_offs	  = OMAP4430_PRM_WKUP_MOD,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
-	.pwrsts		  = PWRSTS_ON,
-	.banks		  = 1,
-	.pwrsts_mem_ret	= {
-		[0] = PWRDM_POWER_OFF,	/* wkup_bank */
-	},
-	.pwrsts_mem_on	= {
-		[0] = PWRDM_POWER_ON,	/* wkup_bank */
-	},
-};
-
-/* cpu0_44xx_pwrdm: MPU0 processor and Neon coprocessor power domain */
-static struct powerdomain cpu0_44xx_pwrdm = {
-	.name		  = "cpu0_pwrdm",
-	.prcm_offs	  = OMAP4430_PRCM_MPU_CPU0_MOD,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
-	.pwrsts		  = PWRSTS_OFF_RET_ON,
-	.pwrsts_logic_ret = PWRSTS_OFF_RET,
-	.banks		  = 1,
-	.pwrsts_mem_ret	= {
-		[0] = PWRSTS_OFF_RET,	/* cpu0_l1 */
-	},
-	.pwrsts_mem_on	= {
-		[0] = PWRDM_POWER_ON,	/* cpu0_l1 */
-	},
-};
-
-/* cpu1_44xx_pwrdm: MPU1 processor and Neon coprocessor power domain */
-static struct powerdomain cpu1_44xx_pwrdm = {
-	.name		  = "cpu1_pwrdm",
-	.prcm_offs	  = OMAP4430_PRCM_MPU_CPU1_MOD,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
-	.pwrsts		  = PWRSTS_OFF_RET_ON,
-	.pwrsts_logic_ret = PWRSTS_OFF_RET,
-	.banks		  = 1,
-	.pwrsts_mem_ret	= {
-		[0] = PWRSTS_OFF_RET,	/* cpu1_l1 */
-	},
-	.pwrsts_mem_on	= {
-		[0] = PWRDM_POWER_ON,	/* cpu1_l1 */
-	},
-};
-
-/* emu_44xx_pwrdm: Emulation power domain */
-static struct powerdomain emu_44xx_pwrdm = {
-	.name		  = "emu_pwrdm",
-	.prcm_offs	  = OMAP4430_PRM_EMU_MOD,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
-	.pwrsts		  = PWRSTS_OFF_ON,
-	.banks		  = 1,
-	.pwrsts_mem_ret	= {
-		[0] = PWRDM_POWER_OFF,	/* emu_bank */
-	},
-	.pwrsts_mem_on	= {
-		[0] = PWRDM_POWER_ON,	/* emu_bank */
-	},
-};
-
-/* mpu_44xx_pwrdm: Modena processor and the Neon coprocessor power domain */
-static struct powerdomain mpu_44xx_pwrdm = {
-	.name		  = "mpu_pwrdm",
-	.prcm_offs	  = OMAP4430_PRM_MPU_MOD,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
-	.pwrsts		  = PWRSTS_OFF_RET_ON,
-	.pwrsts_logic_ret = PWRSTS_OFF_RET,
-	.banks		  = 3,
-	.pwrsts_mem_ret	= {
-		[0] = PWRSTS_OFF_RET,	/* mpu_l1 */
-		[1] = PWRSTS_OFF_RET,	/* mpu_l2 */
-		[2] = PWRDM_POWER_RET,	/* mpu_ram */
-	},
-	.pwrsts_mem_on	= {
-		[0] = PWRDM_POWER_ON,	/* mpu_l1 */
-		[1] = PWRDM_POWER_ON,	/* mpu_l2 */
-		[2] = PWRDM_POWER_ON,	/* mpu_ram */
-	},
-};
-
-/* ivahd_44xx_pwrdm: IVA-HD power domain */
-static struct powerdomain ivahd_44xx_pwrdm = {
-	.name		  = "ivahd_pwrdm",
-	.prcm_offs	  = OMAP4430_PRM_IVAHD_MOD,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
-	.pwrsts		  = PWRSTS_OFF_RET_ON,
-	.pwrsts_logic_ret = PWRDM_POWER_OFF,
-	.banks		  = 4,
-	.pwrsts_mem_ret	= {
-		[0] = PWRDM_POWER_OFF,	/* hwa_mem */
-		[1] = PWRSTS_OFF_RET,	/* sl2_mem */
-		[2] = PWRSTS_OFF_RET,	/* tcm1_mem */
-		[3] = PWRSTS_OFF_RET,	/* tcm2_mem */
-	},
-	.pwrsts_mem_on	= {
-		[0] = PWRDM_POWER_ON,	/* hwa_mem */
-		[1] = PWRDM_POWER_ON,	/* sl2_mem */
-		[2] = PWRDM_POWER_ON,	/* tcm1_mem */
-		[3] = PWRDM_POWER_ON,	/* tcm2_mem */
-	},
-	.flags		= PWRDM_HAS_LOWPOWERSTATECHANGE,
-};
-
-/* cam_44xx_pwrdm: Camera subsystem power domain */
-static struct powerdomain cam_44xx_pwrdm = {
-	.name		  = "cam_pwrdm",
-	.prcm_offs	  = OMAP4430_PRM_CAM_MOD,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
-	.pwrsts		  = PWRSTS_OFF_ON,
-	.banks		  = 1,
-	.pwrsts_mem_ret	= {
-		[0] = PWRDM_POWER_OFF,	/* cam_mem */
-	},
-	.pwrsts_mem_on	= {
-		[0] = PWRDM_POWER_ON,	/* cam_mem */
-	},
-	.flags		= PWRDM_HAS_LOWPOWERSTATECHANGE,
-};
-
-/* l3init_44xx_pwrdm: L3 initators pheripherals power domain  */
-static struct powerdomain l3init_44xx_pwrdm = {
-	.name		  = "l3init_pwrdm",
-	.prcm_offs	  = OMAP4430_PRM_L3INIT_MOD,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
-	.pwrsts		  = PWRSTS_OFF_RET_ON,
-	.pwrsts_logic_ret = PWRSTS_OFF_RET,
-	.banks		  = 1,
-	.pwrsts_mem_ret	= {
-		[0] = PWRDM_POWER_OFF,	/* l3init_bank1 */
-	},
-	.pwrsts_mem_on	= {
-		[0] = PWRDM_POWER_ON,	/* l3init_bank1 */
-	},
-	.flags		= PWRDM_HAS_LOWPOWERSTATECHANGE,
-};
-
-/* l4per_44xx_pwrdm: Target peripherals power domain */
-static struct powerdomain l4per_44xx_pwrdm = {
-	.name		  = "l4per_pwrdm",
-	.prcm_offs	  = OMAP4430_PRM_L4PER_MOD,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
-	.pwrsts		  = PWRSTS_OFF_RET_ON,
-	.pwrsts_logic_ret = PWRSTS_OFF_RET,
-	.banks		  = 2,
-	.pwrsts_mem_ret	= {
-		[0] = PWRDM_POWER_OFF,	/* nonretained_bank */
-		[1] = PWRDM_POWER_RET,	/* retained_bank */
-	},
-	.pwrsts_mem_on	= {
-		[0] = PWRDM_POWER_ON,	/* nonretained_bank */
-		[1] = PWRDM_POWER_ON,	/* retained_bank */
-	},
-	.flags		= PWRDM_HAS_LOWPOWERSTATECHANGE,
-};
-
-/*
- * always_on_core_44xx_pwrdm: Always ON logic that sits in VDD_CORE voltage
- * domain
- */
-static struct powerdomain always_on_core_44xx_pwrdm = {
-	.name		  = "always_on_core_pwrdm",
-	.prcm_offs	  = OMAP4430_PRM_ALWAYS_ON_MOD,
-	.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",
-	.prcm_offs	  = OMAP4430_PRM_CEFUSE_MOD,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
-	.pwrsts		  = PWRSTS_OFF_ON,
-};
-
-/*
- * The following power domains are not under SW control
- *
- * always_on_iva
- * always_on_mpu
- * stdefuse
- */
-
-#endif
-
-#endif
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/powerdomains.h linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/powerdomains.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/powerdomains.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/powerdomains.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,153 +0,0 @@
-/*
- * OMAP2/3 common powerdomain definitions
- *
- * Copyright (C) 2007-2008 Texas Instruments, Inc.
- * Copyright (C) 2007-2009 Nokia Corporation
- *
- * Written by Paul Walmsley
- * Debugging and integration fixes by Jouni Högander
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-/*
- * To Do List
- * -> Move the Sleep/Wakeup dependencies from Power Domain framework to
- *    Clock Domain Framework
- */
-
-#ifndef ARCH_ARM_MACH_OMAP2_POWERDOMAINS
-#define ARCH_ARM_MACH_OMAP2_POWERDOMAINS
-
-/*
- * 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.
- *
- * On the 2420, this is a 'C55 DSP called, simply, the DSP.  Its
- * powerdomain is called the "DSP power domain."  On the 2430, the
- * on-board DSP is a 'C64 DSP, now called (along with its hardware
- * accelerators) the IVA2 or IVA2.1.  Its powerdomain is still called
- * the "DSP power domain." On the 3430, the DSP is a 'C64 DSP like the
- * 2430, also known as the IVA2; but its powerdomain is now called the
- * "IVA2 power domain."
- *
- * The 2420 also has something called the IVA, which is a separate ARM
- * core, and has nothing to do with the DSP/IVA2.
- *
- * Ideally the DSP/IVA2 could just be the same powerdomain, but the PRCM
- * address offset is different between the C55 and C64 DSPs.
- */
-
-#include <plat/powerdomain.h>
-
-#include "prcm-common.h"
-#include "prm.h"
-#include "cm.h"
-#include "powerdomains24xx.h"
-#include "powerdomains34xx.h"
-#include "powerdomains44xx.h"
-
-/* OMAP2/3-common powerdomains */
-
-#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
-
-/*
- * The GFX powerdomain is not present on 3430ES2, but currently we do not
- * have a macro to filter it out at compile-time.
- */
-static 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 = PWRDM_POWER_RET,
-	.banks		  = 1,
-	.pwrsts_mem_ret	  = {
-		[0] = PWRDM_POWER_RET, /* MEMRETSTATE */
-	},
-	.pwrsts_mem_on	  = {
-		[0] = PWRDM_POWER_ON,  /* MEMONSTATE */
-	},
-};
-
-static struct powerdomain wkup_omap2_pwrdm = {
-	.name		= "wkup_pwrdm",
-	.prcm_offs	= WKUP_MOD,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP24XX | CHIP_IS_OMAP3430),
-};
-
-#endif
-
-
-/* As powerdomains are added or removed above, this list must also be changed */
-static struct powerdomain *powerdomains_omap[] __initdata = {
-
-#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
-	&wkup_omap2_pwrdm,
-	&gfx_omap2_pwrdm,
-#endif
-
-#ifdef CONFIG_ARCH_OMAP2
-	&dsp_pwrdm,
-	&mpu_24xx_pwrdm,
-	&core_24xx_pwrdm,
-#endif
-
-#ifdef CONFIG_ARCH_OMAP2430
-	&mdm_pwrdm,
-#endif
-
-#ifdef CONFIG_ARCH_OMAP3
-	&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,
-	&dpll5_pwrdm,
-#endif
-
-#ifdef CONFIG_ARCH_OMAP4
-	&core_44xx_pwrdm,
-	&gfx_44xx_pwrdm,
-	&abe_44xx_pwrdm,
-	&dss_44xx_pwrdm,
-	&tesla_44xx_pwrdm,
-	&wkup_44xx_pwrdm,
-	&cpu0_44xx_pwrdm,
-	&cpu1_44xx_pwrdm,
-	&emu_44xx_pwrdm,
-	&mpu_44xx_pwrdm,
-	&ivahd_44xx_pwrdm,
-	&cam_44xx_pwrdm,
-	&l3init_44xx_pwrdm,
-	&l4per_44xx_pwrdm,
-	&always_on_core_44xx_pwrdm,
-	&cefuse_44xx_pwrdm,
-#endif
-	NULL
-};
-
-
-#endif
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/prcm44xx.h linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/prcm44xx.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/prcm44xx.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/prcm44xx.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,42 @@
+/*
+ * OMAP4 PRCM definitions
+ *
+ * Copyright (C) 2010 Texas Instruments, Inc.
+ * Copyright (C) 2010 Nokia Corporation
+ *
+ * Paul Walmsley
+ *
+ * This program is free software; you can 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 macros and functions that are common to all of
+ * the PRM/CM/PRCM blocks on the OMAP4 devices: PRM, CM1, CM2,
+ * PRCM_MPU, SCRM
+ */
+
+#ifndef __ARCH_ARM_MACH_OMAP2_PRCM44XX_H
+#define __ARCH_ARM_MACH_OMAP2_PRCM44XX_H
+
+/*
+ * OMAP4 PRCM partition IDs
+ *
+ * The numbers and order are arbitrary, but 0 is reserved for the
+ * 'invalid' partition in case someone forgets to add a
+ * .prcm_partition field.
+ */
+#define OMAP4430_INVALID_PRCM_PARTITION		0
+#define OMAP4430_PRM_PARTITION			1
+#define OMAP4430_CM1_PARTITION			2
+#define OMAP4430_CM2_PARTITION			3
+#define OMAP4430_SCRM_PARTITION			4
+#define OMAP4430_PRCM_MPU_PARTITION		5
+
+/*
+ * OMAP4_MAX_PRCM_PARTITIONS: set to the highest value of the PRCM partition
+ * IDs, plus one
+ */
+#define OMAP4_MAX_PRCM_PARTITIONS		6
+
+
+#endif
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/prcm.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/prcm.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/prcm.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/prcm.c	2011-03-14 21:20:32.000000000 -0400
@@ -17,7 +17,8 @@
  * 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/clk.h>
 #include <linux/io.h>
@@ -29,105 +30,27 @@
 
 #include "clock.h"
 #include "clock2xxx.h"
-#include "cm.h"
-#include "prm.h"
+#include "cm2xxx_3xxx.h"
+#include "prm2xxx_3xxx.h"
+#include "prm44xx.h"
+#include "prminst44xx.h"
 #include "prm-regbits-24xx.h"
 #include "prm-regbits-44xx.h"
 #include "control.h"
 
-static void __iomem *prm_base;
-static void __iomem *cm_base;
-static void __iomem *cm2_base;
+void __iomem *prm_base;
+void __iomem *cm_base;
+void __iomem *cm2_base;
 
 #define MAX_MODULE_ENABLE_WAIT		100000
 
-struct omap3_prcm_regs {
-	u32 control_padconf_sys_nirq;
-	u32 iva2_cm_clksel1;
-	u32 iva2_cm_clksel2;
-	u32 cm_sysconfig;
-	u32 sgx_cm_clksel;
-	u32 dss_cm_clksel;
-	u32 cam_cm_clksel;
-	u32 per_cm_clksel;
-	u32 emu_cm_clksel;
-	u32 emu_cm_clkstctrl;
-	u32 pll_cm_autoidle2;
-	u32 pll_cm_clksel4;
-	u32 pll_cm_clksel5;
-	u32 pll_cm_clken2;
-	u32 cm_polctrl;
-	u32 iva2_cm_fclken;
-	u32 iva2_cm_clken_pll;
-	u32 core_cm_fclken1;
-	u32 core_cm_fclken3;
-	u32 sgx_cm_fclken;
-	u32 wkup_cm_fclken;
-	u32 dss_cm_fclken;
-	u32 cam_cm_fclken;
-	u32 per_cm_fclken;
-	u32 usbhost_cm_fclken;
-	u32 core_cm_iclken1;
-	u32 core_cm_iclken2;
-	u32 core_cm_iclken3;
-	u32 sgx_cm_iclken;
-	u32 wkup_cm_iclken;
-	u32 dss_cm_iclken;
-	u32 cam_cm_iclken;
-	u32 per_cm_iclken;
-	u32 usbhost_cm_iclken;
-	u32 iva2_cm_autiidle2;
-	u32 mpu_cm_autoidle2;
-	u32 iva2_cm_clkstctrl;
-	u32 mpu_cm_clkstctrl;
-	u32 core_cm_clkstctrl;
-	u32 sgx_cm_clkstctrl;
-	u32 dss_cm_clkstctrl;
-	u32 cam_cm_clkstctrl;
-	u32 per_cm_clkstctrl;
-	u32 neon_cm_clkstctrl;
-	u32 usbhost_cm_clkstctrl;
-	u32 core_cm_autoidle1;
-	u32 core_cm_autoidle2;
-	u32 core_cm_autoidle3;
-	u32 wkup_cm_autoidle;
-	u32 dss_cm_autoidle;
-	u32 cam_cm_autoidle;
-	u32 per_cm_autoidle;
-	u32 usbhost_cm_autoidle;
-	u32 sgx_cm_sleepdep;
-	u32 dss_cm_sleepdep;
-	u32 cam_cm_sleepdep;
-	u32 per_cm_sleepdep;
-	u32 usbhost_cm_sleepdep;
-	u32 cm_clkout_ctrl;
-	u32 prm_clkout_ctrl;
-	u32 sgx_pm_wkdep;
-	u32 dss_pm_wkdep;
-	u32 cam_pm_wkdep;
-	u32 per_pm_wkdep;
-	u32 neon_pm_wkdep;
-	u32 usbhost_pm_wkdep;
-	u32 core_pm_mpugrpsel1;
-	u32 iva2_pm_ivagrpsel1;
-	u32 core_pm_mpugrpsel3;
-	u32 core_pm_ivagrpsel3;
-	u32 wkup_pm_mpugrpsel;
-	u32 wkup_pm_ivagrpsel;
-	u32 per_pm_mpugrpsel;
-	u32 per_pm_ivagrpsel;
-	u32 wkup_pm_wken;
-};
-
-static struct omap3_prcm_regs prcm_context;
-
 u32 omap_prcm_get_reset_sources(void)
 {
 	/* XXX This presumably needs modification for 34XX */
 	if (cpu_is_omap24xx() || cpu_is_omap34xx())
-		return prm_read_mod_reg(WKUP_MOD, OMAP2_RM_RSTST) & 0x7f;
+		return omap2_prm_read_mod_reg(WKUP_MOD, OMAP2_RM_RSTST) & 0x7f;
 	if (cpu_is_omap44xx())
-		return prm_read_mod_reg(WKUP_MOD, OMAP4_RM_RSTST) & 0x7f;
+		return omap2_prm_read_mod_reg(WKUP_MOD, OMAP4_RM_RSTST) & 0x7f;
 
 	return 0;
 }
@@ -143,126 +66,46 @@ void omap_prcm_arch_reset(char mode, con
 
 		prcm_offs = WKUP_MOD;
 	} else if (cpu_is_omap34xx()) {
-		u32 l;
-
 		prcm_offs = OMAP3430_GR_MOD;
-		l = ('B' << 24) | ('M' << 16) | (cmd ? (u8)*cmd : 0);
-		/* Reserve the first word in scratchpad for communicating
-		 * with the boot ROM. A pointer to a data structure
-		 * describing the boot process can be stored there,
-		 * cf. OMAP34xx TRM, Initialization / Software Booting
-		 * Configuration. */
-		omap_writel(l, OMAP343X_SCRATCHPAD + 4);
-	} else if (cpu_is_omap44xx())
-		prcm_offs = OMAP4430_PRM_DEVICE_MOD;
-	else
+		omap3_ctrl_write_boot_mode((cmd ? (u8)*cmd : 0));
+	} else if (cpu_is_omap44xx()) {
+		omap4_prm_global_warm_sw_reset(); /* never returns */
+	} else {
 		WARN_ON(1);
+	}
 
-	if (cpu_is_omap24xx() || cpu_is_omap34xx())
-		prm_set_mod_reg_bits(OMAP_RST_DPLL3_MASK, prcm_offs,
-						 OMAP2_RM_RSTCTRL);
-	if (cpu_is_omap44xx())
-		prm_set_mod_reg_bits(OMAP4430_RST_GLOBAL_WARM_SW_MASK,
-				     prcm_offs, OMAP4_RM_RSTCTRL);
-}
-
-static inline u32 __omap_prcm_read(void __iomem *base, s16 module, u16 reg)
-{
-	BUG_ON(!base);
-	return __raw_readl(base + module + reg);
-}
-
-static inline void __omap_prcm_write(u32 value, void __iomem *base,
-						s16 module, u16 reg)
-{
-	BUG_ON(!base);
-	__raw_writel(value, base + module + reg);
-}
-
-/* Read a register in a PRM module */
-u32 prm_read_mod_reg(s16 module, u16 idx)
-{
-	return __omap_prcm_read(prm_base, module, idx);
-}
-
-/* Write into a register in a PRM module */
-void prm_write_mod_reg(u32 val, s16 module, u16 idx)
-{
-	__omap_prcm_write(val, prm_base, module, idx);
-}
-
-/* Read-modify-write a register in a PRM module. Caller must lock */
-u32 prm_rmw_mod_reg_bits(u32 mask, u32 bits, s16 module, s16 idx)
-{
-	u32 v;
-
-	v = prm_read_mod_reg(module, idx);
-	v &= ~mask;
-	v |= bits;
-	prm_write_mod_reg(v, module, idx);
-
-	return v;
-}
-
-/* Read a PRM register, AND it, and shift the result down to bit 0 */
-u32 prm_read_mod_bits_shift(s16 domain, s16 idx, u32 mask)
-{
-	u32 v;
-
-	v = prm_read_mod_reg(domain, idx);
-	v &= mask;
-	v >>= __ffs(mask);
-
-	return v;
-}
-
-/* Read a PRM register, AND it, and shift the result down to bit 0 */
-u32 omap4_prm_read_bits_shift(void __iomem *reg, u32 mask)
-{
-	u32 v;
-
-	v = __raw_readl(reg);
-	v &= mask;
-	v >>= __ffs(mask);
-
-	return v;
-}
-
-/* Read-modify-write a register in a PRM module. Caller must lock */
-u32 omap4_prm_rmw_reg_bits(u32 mask, u32 bits, void __iomem *reg)
-{
-	u32 v;
-
-	v = __raw_readl(reg);
-	v &= ~mask;
-	v |= bits;
-	__raw_writel(v, reg);
-
-	return v;
-}
-/* Read a register in a CM module */
-u32 cm_read_mod_reg(s16 module, u16 idx)
-{
-	return __omap_prcm_read(cm_base, module, idx);
-}
-
-/* Write into a register in a CM module */
-void cm_write_mod_reg(u32 val, s16 module, u16 idx)
-{
-	__omap_prcm_write(val, cm_base, module, idx);
-}
-
-/* Read-modify-write a register in a CM module. Caller must lock */
-u32 cm_rmw_mod_reg_bits(u32 mask, u32 bits, s16 module, s16 idx)
-{
-	u32 v;
-
-	v = cm_read_mod_reg(module, idx);
-	v &= ~mask;
-	v |= bits;
-	cm_write_mod_reg(v, module, idx);
+	/*
+	 * As per Errata i520, in some cases, user will not be able to
+	 * access DDR memory after warm-reset.
+	 * This situation occurs while the warm-reset happens during a read
+	 * access to DDR memory. In that particular condition, DDR memory
+	 * does not respond to a corrupted read command due to the warm
+	 * reset occurrence but SDRC is waiting for read completion.
+	 * SDRC is not sensitive to the warm reset, but the interconnect is
+	 * reset on the fly, thus causing a misalignment between SDRC logic,
+	 * interconnect logic and DDR memory state.
+	 * WORKAROUND:
+	 * Steps to perform before a Warm reset is trigged:
+	 * 1. enable self-refresh on idle request
+	 * 2. put SDRC in idle
+	 * 3. wait until SDRC goes to idle
+	 * 4. generate SW reset (Global SW reset)
+	 *
+	 * Steps to be performed after warm reset occurs (in bootloader):
+	 * if HW warm reset is the source, apply below steps before any
+	 * accesses to SDRAM:
+	 * 1. Reset SMS and SDRC and wait till reset is complete
+	 * 2. Re-initialize SMS, SDRC and memory
+	 *
+	 * NOTE: Above work around is required only if arch reset is implemented
+	 * using Global SW reset(GLOBAL_SW_RST). DPLL3 reset does not need
+	 * the WA since it resets SDRC as well as part of cold reset.
+	 */
 
-	return v;
+	/* XXX should be moved to some OMAP2/3 specific code */
+	omap2_prm_set_mod_reg_bits(OMAP_RST_DPLL3_MASK, prcm_offs,
+				   OMAP2_RM_RSTCTRL);
+	omap2_prm_read_mod_reg(prcm_offs, OMAP2_RM_RSTCTRL); /* OCP barrier */
 }
 
 /**
@@ -274,6 +117,9 @@ u32 cm_rmw_mod_reg_bits(u32 mask, u32 bi
  *
  * Returns 1 if the module indicated readiness in time, or 0 if it
  * failed to enable in roughly MAX_MODULE_ENABLE_WAIT microseconds.
+ *
+ * XXX This function is deprecated.  It should be removed once the
+ * hwmod conversion is complete.
  */
 int omap2_cm_wait_idlest(void __iomem *reg, u32 mask, u8 idlest,
 				const char *name)
@@ -316,303 +162,3 @@ void __init omap2_set_globals_prcm(struc
 		WARN_ON(!cm2_base);
 	}
 }
-
-#ifdef CONFIG_ARCH_OMAP3
-void omap3_prcm_save_context(void)
-{
-	prcm_context.control_padconf_sys_nirq =
-			 omap_ctrl_readl(OMAP343X_CONTROL_PADCONF_SYSNIRQ);
-	prcm_context.iva2_cm_clksel1 =
-			 cm_read_mod_reg(OMAP3430_IVA2_MOD, CM_CLKSEL1);
-	prcm_context.iva2_cm_clksel2 =
-			 cm_read_mod_reg(OMAP3430_IVA2_MOD, CM_CLKSEL2);
-	prcm_context.cm_sysconfig = __raw_readl(OMAP3430_CM_SYSCONFIG);
-	prcm_context.sgx_cm_clksel =
-			 cm_read_mod_reg(OMAP3430ES2_SGX_MOD, CM_CLKSEL);
-	prcm_context.dss_cm_clksel =
-			 cm_read_mod_reg(OMAP3430_DSS_MOD, CM_CLKSEL);
-	prcm_context.cam_cm_clksel =
-			 cm_read_mod_reg(OMAP3430_CAM_MOD, CM_CLKSEL);
-	prcm_context.per_cm_clksel =
-			 cm_read_mod_reg(OMAP3430_PER_MOD, CM_CLKSEL);
-	prcm_context.emu_cm_clksel =
-			 cm_read_mod_reg(OMAP3430_EMU_MOD, CM_CLKSEL1);
-	prcm_context.emu_cm_clkstctrl =
-			 cm_read_mod_reg(OMAP3430_EMU_MOD, OMAP2_CM_CLKSTCTRL);
-	prcm_context.pll_cm_autoidle2 =
-			 cm_read_mod_reg(PLL_MOD, CM_AUTOIDLE2);
-	prcm_context.pll_cm_clksel4 =
-			cm_read_mod_reg(PLL_MOD, OMAP3430ES2_CM_CLKSEL4);
-	prcm_context.pll_cm_clksel5 =
-			 cm_read_mod_reg(PLL_MOD, OMAP3430ES2_CM_CLKSEL5);
-	prcm_context.pll_cm_clken2 =
-			cm_read_mod_reg(PLL_MOD, OMAP3430ES2_CM_CLKEN2);
-	prcm_context.cm_polctrl = __raw_readl(OMAP3430_CM_POLCTRL);
-	prcm_context.iva2_cm_fclken =
-			 cm_read_mod_reg(OMAP3430_IVA2_MOD, CM_FCLKEN);
-	prcm_context.iva2_cm_clken_pll = cm_read_mod_reg(OMAP3430_IVA2_MOD,
-			OMAP3430_CM_CLKEN_PLL);
-	prcm_context.core_cm_fclken1 =
-			 cm_read_mod_reg(CORE_MOD, CM_FCLKEN1);
-	prcm_context.core_cm_fclken3 =
-			 cm_read_mod_reg(CORE_MOD, OMAP3430ES2_CM_FCLKEN3);
-	prcm_context.sgx_cm_fclken =
-			 cm_read_mod_reg(OMAP3430ES2_SGX_MOD, CM_FCLKEN);
-	prcm_context.wkup_cm_fclken =
-			 cm_read_mod_reg(WKUP_MOD, CM_FCLKEN);
-	prcm_context.dss_cm_fclken =
-			 cm_read_mod_reg(OMAP3430_DSS_MOD, CM_FCLKEN);
-	prcm_context.cam_cm_fclken =
-			 cm_read_mod_reg(OMAP3430_CAM_MOD, CM_FCLKEN);
-	prcm_context.per_cm_fclken =
-			 cm_read_mod_reg(OMAP3430_PER_MOD, CM_FCLKEN);
-	prcm_context.usbhost_cm_fclken =
-			 cm_read_mod_reg(OMAP3430ES2_USBHOST_MOD, CM_FCLKEN);
-	prcm_context.core_cm_iclken1 =
-			 cm_read_mod_reg(CORE_MOD, CM_ICLKEN1);
-	prcm_context.core_cm_iclken2 =
-			 cm_read_mod_reg(CORE_MOD, CM_ICLKEN2);
-	prcm_context.core_cm_iclken3 =
-			 cm_read_mod_reg(CORE_MOD, CM_ICLKEN3);
-	prcm_context.sgx_cm_iclken =
-			 cm_read_mod_reg(OMAP3430ES2_SGX_MOD, CM_ICLKEN);
-	prcm_context.wkup_cm_iclken =
-			 cm_read_mod_reg(WKUP_MOD, CM_ICLKEN);
-	prcm_context.dss_cm_iclken =
-			 cm_read_mod_reg(OMAP3430_DSS_MOD, CM_ICLKEN);
-	prcm_context.cam_cm_iclken =
-			 cm_read_mod_reg(OMAP3430_CAM_MOD, CM_ICLKEN);
-	prcm_context.per_cm_iclken =
-			 cm_read_mod_reg(OMAP3430_PER_MOD, CM_ICLKEN);
-	prcm_context.usbhost_cm_iclken =
-			 cm_read_mod_reg(OMAP3430ES2_USBHOST_MOD, CM_ICLKEN);
-	prcm_context.iva2_cm_autiidle2 =
-			 cm_read_mod_reg(OMAP3430_IVA2_MOD, CM_AUTOIDLE2);
-	prcm_context.mpu_cm_autoidle2 =
-			 cm_read_mod_reg(MPU_MOD, CM_AUTOIDLE2);
-	prcm_context.iva2_cm_clkstctrl =
-			 cm_read_mod_reg(OMAP3430_IVA2_MOD, OMAP2_CM_CLKSTCTRL);
-	prcm_context.mpu_cm_clkstctrl =
-			 cm_read_mod_reg(MPU_MOD, OMAP2_CM_CLKSTCTRL);
-	prcm_context.core_cm_clkstctrl =
-			 cm_read_mod_reg(CORE_MOD, OMAP2_CM_CLKSTCTRL);
-	prcm_context.sgx_cm_clkstctrl =
-			 cm_read_mod_reg(OMAP3430ES2_SGX_MOD,
-						OMAP2_CM_CLKSTCTRL);
-	prcm_context.dss_cm_clkstctrl =
-			 cm_read_mod_reg(OMAP3430_DSS_MOD, OMAP2_CM_CLKSTCTRL);
-	prcm_context.cam_cm_clkstctrl =
-			 cm_read_mod_reg(OMAP3430_CAM_MOD, OMAP2_CM_CLKSTCTRL);
-	prcm_context.per_cm_clkstctrl =
-			 cm_read_mod_reg(OMAP3430_PER_MOD, OMAP2_CM_CLKSTCTRL);
-	prcm_context.neon_cm_clkstctrl =
-			 cm_read_mod_reg(OMAP3430_NEON_MOD, OMAP2_CM_CLKSTCTRL);
-	prcm_context.usbhost_cm_clkstctrl =
-			 cm_read_mod_reg(OMAP3430ES2_USBHOST_MOD,
-						OMAP2_CM_CLKSTCTRL);
-	prcm_context.core_cm_autoidle1 =
-			 cm_read_mod_reg(CORE_MOD, CM_AUTOIDLE1);
-	prcm_context.core_cm_autoidle2 =
-			 cm_read_mod_reg(CORE_MOD, CM_AUTOIDLE2);
-	prcm_context.core_cm_autoidle3 =
-			 cm_read_mod_reg(CORE_MOD, CM_AUTOIDLE3);
-	prcm_context.wkup_cm_autoidle =
-			 cm_read_mod_reg(WKUP_MOD, CM_AUTOIDLE);
-	prcm_context.dss_cm_autoidle =
-			 cm_read_mod_reg(OMAP3430_DSS_MOD, CM_AUTOIDLE);
-	prcm_context.cam_cm_autoidle =
-			 cm_read_mod_reg(OMAP3430_CAM_MOD, CM_AUTOIDLE);
-	prcm_context.per_cm_autoidle =
-			 cm_read_mod_reg(OMAP3430_PER_MOD, CM_AUTOIDLE);
-	prcm_context.usbhost_cm_autoidle =
-			 cm_read_mod_reg(OMAP3430ES2_USBHOST_MOD, CM_AUTOIDLE);
-	prcm_context.sgx_cm_sleepdep =
-		 cm_read_mod_reg(OMAP3430ES2_SGX_MOD, OMAP3430_CM_SLEEPDEP);
-	prcm_context.dss_cm_sleepdep =
-		 cm_read_mod_reg(OMAP3430_DSS_MOD, OMAP3430_CM_SLEEPDEP);
-	prcm_context.cam_cm_sleepdep =
-		 cm_read_mod_reg(OMAP3430_CAM_MOD, OMAP3430_CM_SLEEPDEP);
-	prcm_context.per_cm_sleepdep =
-		 cm_read_mod_reg(OMAP3430_PER_MOD, OMAP3430_CM_SLEEPDEP);
-	prcm_context.usbhost_cm_sleepdep =
-		 cm_read_mod_reg(OMAP3430ES2_USBHOST_MOD, OMAP3430_CM_SLEEPDEP);
-	prcm_context.cm_clkout_ctrl = cm_read_mod_reg(OMAP3430_CCR_MOD,
-		 OMAP3_CM_CLKOUT_CTRL_OFFSET);
-	prcm_context.prm_clkout_ctrl = prm_read_mod_reg(OMAP3430_CCR_MOD,
-		OMAP3_PRM_CLKOUT_CTRL_OFFSET);
-	prcm_context.sgx_pm_wkdep =
-		 prm_read_mod_reg(OMAP3430ES2_SGX_MOD, PM_WKDEP);
-	prcm_context.dss_pm_wkdep =
-		 prm_read_mod_reg(OMAP3430_DSS_MOD, PM_WKDEP);
-	prcm_context.cam_pm_wkdep =
-		 prm_read_mod_reg(OMAP3430_CAM_MOD, PM_WKDEP);
-	prcm_context.per_pm_wkdep =
-		 prm_read_mod_reg(OMAP3430_PER_MOD, PM_WKDEP);
-	prcm_context.neon_pm_wkdep =
-		 prm_read_mod_reg(OMAP3430_NEON_MOD, PM_WKDEP);
-	prcm_context.usbhost_pm_wkdep =
-		 prm_read_mod_reg(OMAP3430ES2_USBHOST_MOD, PM_WKDEP);
-	prcm_context.core_pm_mpugrpsel1 =
-		 prm_read_mod_reg(CORE_MOD, OMAP3430_PM_MPUGRPSEL1);
-	prcm_context.iva2_pm_ivagrpsel1 =
-		 prm_read_mod_reg(OMAP3430_IVA2_MOD, OMAP3430_PM_IVAGRPSEL1);
-	prcm_context.core_pm_mpugrpsel3 =
-		 prm_read_mod_reg(CORE_MOD, OMAP3430ES2_PM_MPUGRPSEL3);
-	prcm_context.core_pm_ivagrpsel3 =
-		 prm_read_mod_reg(CORE_MOD, OMAP3430ES2_PM_IVAGRPSEL3);
-	prcm_context.wkup_pm_mpugrpsel =
-		 prm_read_mod_reg(WKUP_MOD, OMAP3430_PM_MPUGRPSEL);
-	prcm_context.wkup_pm_ivagrpsel =
-		 prm_read_mod_reg(WKUP_MOD, OMAP3430_PM_IVAGRPSEL);
-	prcm_context.per_pm_mpugrpsel =
-		 prm_read_mod_reg(OMAP3430_PER_MOD, OMAP3430_PM_MPUGRPSEL);
-	prcm_context.per_pm_ivagrpsel =
-		 prm_read_mod_reg(OMAP3430_PER_MOD, OMAP3430_PM_IVAGRPSEL);
-	prcm_context.wkup_pm_wken = prm_read_mod_reg(WKUP_MOD, PM_WKEN);
-	return;
-}
-
-void omap3_prcm_restore_context(void)
-{
-	omap_ctrl_writel(prcm_context.control_padconf_sys_nirq,
-					 OMAP343X_CONTROL_PADCONF_SYSNIRQ);
-	cm_write_mod_reg(prcm_context.iva2_cm_clksel1, OMAP3430_IVA2_MOD,
-					 CM_CLKSEL1);
-	cm_write_mod_reg(prcm_context.iva2_cm_clksel2, OMAP3430_IVA2_MOD,
-					 CM_CLKSEL2);
-	__raw_writel(prcm_context.cm_sysconfig, OMAP3430_CM_SYSCONFIG);
-	cm_write_mod_reg(prcm_context.sgx_cm_clksel, OMAP3430ES2_SGX_MOD,
-					 CM_CLKSEL);
-	cm_write_mod_reg(prcm_context.dss_cm_clksel, OMAP3430_DSS_MOD,
-					 CM_CLKSEL);
-	cm_write_mod_reg(prcm_context.cam_cm_clksel, OMAP3430_CAM_MOD,
-					 CM_CLKSEL);
-	cm_write_mod_reg(prcm_context.per_cm_clksel, OMAP3430_PER_MOD,
-					 CM_CLKSEL);
-	cm_write_mod_reg(prcm_context.emu_cm_clksel, OMAP3430_EMU_MOD,
-					 CM_CLKSEL1);
-	cm_write_mod_reg(prcm_context.emu_cm_clkstctrl, OMAP3430_EMU_MOD,
-					 OMAP2_CM_CLKSTCTRL);
-	cm_write_mod_reg(prcm_context.pll_cm_autoidle2, PLL_MOD,
-					 CM_AUTOIDLE2);
-	cm_write_mod_reg(prcm_context.pll_cm_clksel4, PLL_MOD,
-					OMAP3430ES2_CM_CLKSEL4);
-	cm_write_mod_reg(prcm_context.pll_cm_clksel5, PLL_MOD,
-					 OMAP3430ES2_CM_CLKSEL5);
-	cm_write_mod_reg(prcm_context.pll_cm_clken2, PLL_MOD,
-					OMAP3430ES2_CM_CLKEN2);
-	__raw_writel(prcm_context.cm_polctrl, OMAP3430_CM_POLCTRL);
-	cm_write_mod_reg(prcm_context.iva2_cm_fclken, OMAP3430_IVA2_MOD,
-					 CM_FCLKEN);
-	cm_write_mod_reg(prcm_context.iva2_cm_clken_pll, OMAP3430_IVA2_MOD,
-					OMAP3430_CM_CLKEN_PLL);
-	cm_write_mod_reg(prcm_context.core_cm_fclken1, CORE_MOD, CM_FCLKEN1);
-	cm_write_mod_reg(prcm_context.core_cm_fclken3, CORE_MOD,
-					 OMAP3430ES2_CM_FCLKEN3);
-	cm_write_mod_reg(prcm_context.sgx_cm_fclken, OMAP3430ES2_SGX_MOD,
-					 CM_FCLKEN);
-	cm_write_mod_reg(prcm_context.wkup_cm_fclken, WKUP_MOD, CM_FCLKEN);
-	cm_write_mod_reg(prcm_context.dss_cm_fclken, OMAP3430_DSS_MOD,
-					 CM_FCLKEN);
-	cm_write_mod_reg(prcm_context.cam_cm_fclken, OMAP3430_CAM_MOD,
-					 CM_FCLKEN);
-	cm_write_mod_reg(prcm_context.per_cm_fclken, OMAP3430_PER_MOD,
-					 CM_FCLKEN);
-	cm_write_mod_reg(prcm_context.usbhost_cm_fclken,
-					 OMAP3430ES2_USBHOST_MOD, CM_FCLKEN);
-	cm_write_mod_reg(prcm_context.core_cm_iclken1, CORE_MOD, CM_ICLKEN1);
-	cm_write_mod_reg(prcm_context.core_cm_iclken2, CORE_MOD, CM_ICLKEN2);
-	cm_write_mod_reg(prcm_context.core_cm_iclken3, CORE_MOD, CM_ICLKEN3);
-	cm_write_mod_reg(prcm_context.sgx_cm_iclken, OMAP3430ES2_SGX_MOD,
-					CM_ICLKEN);
-	cm_write_mod_reg(prcm_context.wkup_cm_iclken, WKUP_MOD, CM_ICLKEN);
-	cm_write_mod_reg(prcm_context.dss_cm_iclken, OMAP3430_DSS_MOD,
-					CM_ICLKEN);
-	cm_write_mod_reg(prcm_context.cam_cm_iclken, OMAP3430_CAM_MOD,
-					CM_ICLKEN);
-	cm_write_mod_reg(prcm_context.per_cm_iclken, OMAP3430_PER_MOD,
-					CM_ICLKEN);
-	cm_write_mod_reg(prcm_context.usbhost_cm_iclken,
-					OMAP3430ES2_USBHOST_MOD, CM_ICLKEN);
-	cm_write_mod_reg(prcm_context.iva2_cm_autiidle2, OMAP3430_IVA2_MOD,
-					CM_AUTOIDLE2);
-	cm_write_mod_reg(prcm_context.mpu_cm_autoidle2, MPU_MOD, CM_AUTOIDLE2);
-	cm_write_mod_reg(prcm_context.iva2_cm_clkstctrl, OMAP3430_IVA2_MOD,
-					OMAP2_CM_CLKSTCTRL);
-	cm_write_mod_reg(prcm_context.mpu_cm_clkstctrl, MPU_MOD,
-					OMAP2_CM_CLKSTCTRL);
-	cm_write_mod_reg(prcm_context.core_cm_clkstctrl, CORE_MOD,
-					OMAP2_CM_CLKSTCTRL);
-	cm_write_mod_reg(prcm_context.sgx_cm_clkstctrl, OMAP3430ES2_SGX_MOD,
-					OMAP2_CM_CLKSTCTRL);
-	cm_write_mod_reg(prcm_context.dss_cm_clkstctrl, OMAP3430_DSS_MOD,
-					OMAP2_CM_CLKSTCTRL);
-	cm_write_mod_reg(prcm_context.cam_cm_clkstctrl, OMAP3430_CAM_MOD,
-					OMAP2_CM_CLKSTCTRL);
-	cm_write_mod_reg(prcm_context.per_cm_clkstctrl, OMAP3430_PER_MOD,
-					OMAP2_CM_CLKSTCTRL);
-	cm_write_mod_reg(prcm_context.neon_cm_clkstctrl, OMAP3430_NEON_MOD,
-					OMAP2_CM_CLKSTCTRL);
-	cm_write_mod_reg(prcm_context.usbhost_cm_clkstctrl,
-				OMAP3430ES2_USBHOST_MOD, OMAP2_CM_CLKSTCTRL);
-	cm_write_mod_reg(prcm_context.core_cm_autoidle1, CORE_MOD,
-					CM_AUTOIDLE1);
-	cm_write_mod_reg(prcm_context.core_cm_autoidle2, CORE_MOD,
-					CM_AUTOIDLE2);
-	cm_write_mod_reg(prcm_context.core_cm_autoidle3, CORE_MOD,
-					CM_AUTOIDLE3);
-	cm_write_mod_reg(prcm_context.wkup_cm_autoidle, WKUP_MOD, CM_AUTOIDLE);
-	cm_write_mod_reg(prcm_context.dss_cm_autoidle, OMAP3430_DSS_MOD,
-					CM_AUTOIDLE);
-	cm_write_mod_reg(prcm_context.cam_cm_autoidle, OMAP3430_CAM_MOD,
-					CM_AUTOIDLE);
-	cm_write_mod_reg(prcm_context.per_cm_autoidle, OMAP3430_PER_MOD,
-					CM_AUTOIDLE);
-	cm_write_mod_reg(prcm_context.usbhost_cm_autoidle,
-					OMAP3430ES2_USBHOST_MOD, CM_AUTOIDLE);
-	cm_write_mod_reg(prcm_context.sgx_cm_sleepdep, OMAP3430ES2_SGX_MOD,
-					OMAP3430_CM_SLEEPDEP);
-	cm_write_mod_reg(prcm_context.dss_cm_sleepdep, OMAP3430_DSS_MOD,
-					OMAP3430_CM_SLEEPDEP);
-	cm_write_mod_reg(prcm_context.cam_cm_sleepdep, OMAP3430_CAM_MOD,
-					OMAP3430_CM_SLEEPDEP);
-	cm_write_mod_reg(prcm_context.per_cm_sleepdep, OMAP3430_PER_MOD,
-					OMAP3430_CM_SLEEPDEP);
-	cm_write_mod_reg(prcm_context.usbhost_cm_sleepdep,
-				OMAP3430ES2_USBHOST_MOD, OMAP3430_CM_SLEEPDEP);
-	cm_write_mod_reg(prcm_context.cm_clkout_ctrl, OMAP3430_CCR_MOD,
-					OMAP3_CM_CLKOUT_CTRL_OFFSET);
-	prm_write_mod_reg(prcm_context.prm_clkout_ctrl, OMAP3430_CCR_MOD,
-					OMAP3_PRM_CLKOUT_CTRL_OFFSET);
-	prm_write_mod_reg(prcm_context.sgx_pm_wkdep, OMAP3430ES2_SGX_MOD,
-					PM_WKDEP);
-	prm_write_mod_reg(prcm_context.dss_pm_wkdep, OMAP3430_DSS_MOD,
-					PM_WKDEP);
-	prm_write_mod_reg(prcm_context.cam_pm_wkdep, OMAP3430_CAM_MOD,
-					PM_WKDEP);
-	prm_write_mod_reg(prcm_context.per_pm_wkdep, OMAP3430_PER_MOD,
-					PM_WKDEP);
-	prm_write_mod_reg(prcm_context.neon_pm_wkdep, OMAP3430_NEON_MOD,
-					PM_WKDEP);
-	prm_write_mod_reg(prcm_context.usbhost_pm_wkdep,
-					OMAP3430ES2_USBHOST_MOD, PM_WKDEP);
-	prm_write_mod_reg(prcm_context.core_pm_mpugrpsel1, CORE_MOD,
-					OMAP3430_PM_MPUGRPSEL1);
-	prm_write_mod_reg(prcm_context.iva2_pm_ivagrpsel1, OMAP3430_IVA2_MOD,
-					OMAP3430_PM_IVAGRPSEL1);
-	prm_write_mod_reg(prcm_context.core_pm_mpugrpsel3, CORE_MOD,
-					OMAP3430ES2_PM_MPUGRPSEL3);
-	prm_write_mod_reg(prcm_context.core_pm_ivagrpsel3, CORE_MOD,
-					OMAP3430ES2_PM_IVAGRPSEL3);
-	prm_write_mod_reg(prcm_context.wkup_pm_mpugrpsel, WKUP_MOD,
-					OMAP3430_PM_MPUGRPSEL);
-	prm_write_mod_reg(prcm_context.wkup_pm_ivagrpsel, WKUP_MOD,
-					OMAP3430_PM_IVAGRPSEL);
-	prm_write_mod_reg(prcm_context.per_pm_mpugrpsel, OMAP3430_PER_MOD,
-					OMAP3430_PM_MPUGRPSEL);
-	prm_write_mod_reg(prcm_context.per_pm_ivagrpsel, OMAP3430_PER_MOD,
-					 OMAP3430_PM_IVAGRPSEL);
-	prm_write_mod_reg(prcm_context.wkup_pm_wken, WKUP_MOD, PM_WKEN);
-	return;
-}
-#endif
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/prcm-common.h linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/prcm-common.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/prcm-common.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/prcm-common.h	2011-03-14 21:20:32.000000000 -0400
@@ -8,15 +8,12 @@
  * Copyright (C) 2007-2009 Nokia Corporation
  *
  * Written by Paul Walmsley
- * OMAP4 defines in this file are automatically generated from the OMAP hardware
- * databases.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
 
-
 /* Module offsets from both CM_BASE & PRM_BASE */
 
 /*
@@ -51,75 +48,6 @@
 #define OMAP3430_NEON_MOD				0xb00
 #define OMAP3430ES2_USBHOST_MOD				0xc00
 
-#define BITS(n_bit)	\
-	(((1 << n_bit) - 1) | (1 << n_bit))
-
-#define BITFIELD(l_bit, u_bit)	\
-	(BITS(u_bit) & ~((BITS(l_bit)) >> 1))
-
-/* OMAP44XX specific module offsets */
-
-/* CM1 instances */
-
-#define OMAP4430_CM1_OCP_SOCKET_MOD	0x0000
-#define OMAP4430_CM1_CKGEN_MOD		0x0100
-#define OMAP4430_CM1_MPU_MOD		0x0300
-#define OMAP4430_CM1_TESLA_MOD		0x0400
-#define OMAP4430_CM1_ABE_MOD		0x0500
-#define OMAP4430_CM1_RESTORE_MOD	0x0e00
-#define OMAP4430_CM1_INSTR_MOD		0x0f00
-
-/* CM2 instances */
-
-#define OMAP4430_CM2_OCP_SOCKET_MOD	0x0000
-#define OMAP4430_CM2_CKGEN_MOD		0x0100
-#define OMAP4430_CM2_ALWAYS_ON_MOD	0x0600
-#define OMAP4430_CM2_CORE_MOD		0x0700
-#define OMAP4430_CM2_IVAHD_MOD		0x0f00
-#define OMAP4430_CM2_CAM_MOD		0x1000
-#define OMAP4430_CM2_DSS_MOD		0x1100
-#define OMAP4430_CM2_GFX_MOD		0x1200
-#define OMAP4430_CM2_L3INIT_MOD		0x1300
-#define OMAP4430_CM2_L4PER_MOD		0x1400
-#define OMAP4430_CM2_CEFUSE_MOD		0x1600
-#define OMAP4430_CM2_RESTORE_MOD	0x1e00
-#define OMAP4430_CM2_INSTR_MOD		0x1f00
-
-/* PRM instances */
-
-#define OMAP4430_PRM_OCP_SOCKET_MOD	0x0000
-#define OMAP4430_PRM_CKGEN_MOD		0x0100
-#define OMAP4430_PRM_MPU_MOD		0x0300
-#define OMAP4430_PRM_TESLA_MOD		0x0400
-#define OMAP4430_PRM_ABE_MOD		0x0500
-#define OMAP4430_PRM_ALWAYS_ON_MOD	0x0600
-#define OMAP4430_PRM_CORE_MOD		0x0700
-#define OMAP4430_PRM_IVAHD_MOD		0x0f00
-#define OMAP4430_PRM_CAM_MOD		0x1000
-#define OMAP4430_PRM_DSS_MOD		0x1100
-#define OMAP4430_PRM_GFX_MOD		0x1200
-#define OMAP4430_PRM_L3INIT_MOD		0x1300
-#define OMAP4430_PRM_L4PER_MOD		0x1400
-#define OMAP4430_PRM_CEFUSE_MOD		0x1600
-#define OMAP4430_PRM_WKUP_MOD		0x1700
-#define OMAP4430_PRM_WKUP_CM_MOD	0x1800
-#define OMAP4430_PRM_EMU_MOD		0x1900
-#define OMAP4430_PRM_EMU_CM_MOD		0x1a00
-#define OMAP4430_PRM_DEVICE_MOD		0x1b00
-#define OMAP4430_PRM_INSTR_MOD		0x1f00
-
-/* SCRM instances */
-
-#define OMAP4430_SCRM_SCRM_MOD	0x0000
-
-/* PRCM_MPU instances */
-
-#define OMAP4430_PRCM_MPU_OCP_SOCKET_PRCM_MOD	0x0000
-#define OMAP4430_PRCM_MPU_DEVICE_PRM_MOD	0x0200
-#define OMAP4430_PRCM_MPU_CPU0_MOD		0x0400
-#define OMAP4430_PRCM_MPU_CPU1_MOD		0x0800
-
-
 /* 24XX register bits shared between CM & PRM registers */
 
 /* CM_FCLKEN1_CORE, CM_ICLKEN1_CORE, PM_WKEN1_CORE shared bits */
@@ -461,5 +389,18 @@
 #define OMAP3430_EN_CORE_SHIFT				0
 #define OMAP3430_EN_CORE_MASK				(1 << 0)
 
+
+/*
+ * MAX_MODULE_HARDRESET_WAIT: Maximum microseconds to wait for an OMAP
+ * submodule to exit hardreset
+ */
+#define MAX_MODULE_HARDRESET_WAIT		10000
+
+# ifndef __ASSEMBLER__
+extern void __iomem *prm_base;
+extern void __iomem *cm_base;
+extern void __iomem *cm2_base;
+# endif
+
 #endif
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/prcm_mpu44xx.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/prcm_mpu44xx.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/prcm_mpu44xx.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/prcm_mpu44xx.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,45 @@
+/*
+ * OMAP4 PRCM_MPU module functions
+ *
+ * Copyright (C) 2009 Nokia Corporation
+ * Paul Walmsley
+ *
+ * This program is free software; you can 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/errno.h>
+#include <linux/err.h>
+#include <linux/io.h>
+
+#include <plat/common.h>
+
+#include "prcm_mpu44xx.h"
+#include "cm-regbits-44xx.h"
+
+/* PRCM_MPU low-level functions */
+
+u32 omap4_prcm_mpu_read_inst_reg(s16 inst, u16 reg)
+{
+	return __raw_readl(OMAP44XX_PRCM_MPU_REGADDR(inst, reg));
+}
+
+void omap4_prcm_mpu_write_inst_reg(u32 val, s16 inst, u16 reg)
+{
+	__raw_writel(val, OMAP44XX_PRCM_MPU_REGADDR(inst, reg));
+}
+
+u32 omap4_prcm_mpu_rmw_inst_reg_bits(u32 mask, u32 bits, s16 inst, s16 reg)
+{
+	u32 v;
+
+	v = omap4_prcm_mpu_read_inst_reg(inst, reg);
+	v &= ~mask;
+	v |= bits;
+	omap4_prcm_mpu_write_inst_reg(v, inst, reg);
+
+	return v;
+}
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/prcm_mpu44xx.h linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/prcm_mpu44xx.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/prcm_mpu44xx.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/prcm_mpu44xx.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,104 @@
+/*
+ * OMAP44xx PRCM MPU instance offset macros
+ *
+ * Copyright (C) 2010 Texas Instruments, Inc.
+ * Copyright (C) 2010 Nokia Corporation
+ *
+ * Paul Walmsley (paul@pwsan.com)
+ * Rajendra Nayak (rnayak@ti.com)
+ * Benoit Cousson (b-cousson@ti.com)
+ *
+ * This file is automatically generated from the OMAP hardware databases.
+ * We respectfully ask that any modifications to this file be coordinated
+ * with the public linux-omap@vger.kernel.org mailing list and the
+ * authors above to ensure that the autogeneration scripts are kept
+ * up-to-date with the file contents.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * XXX This file needs to be updated to align on one of "OMAP4", "OMAP44XX",
+ *     or "OMAP4430".
+ */
+
+#ifndef __ARCH_ARM_MACH_OMAP2_PRCM_MPU44XX_H
+#define __ARCH_ARM_MACH_OMAP2_PRCM_MPU44XX_H
+
+#define OMAP4430_PRCM_MPU_BASE			0x48243000
+
+#define OMAP44XX_PRCM_MPU_REGADDR(inst, reg)				\
+	OMAP2_L4_IO_ADDRESS(OMAP4430_PRCM_MPU_BASE + (inst) + (reg))
+
+/* PRCM_MPU instances */
+
+#define OMAP4430_PRCM_MPU_OCP_SOCKET_PRCM_INST	0x0000
+#define OMAP4430_PRCM_MPU_DEVICE_PRM_INST	0x0200
+#define OMAP4430_PRCM_MPU_CPU0_INST		0x0400
+#define OMAP4430_PRCM_MPU_CPU1_INST		0x0800
+
+/* PRCM_MPU clockdomain register offsets (from instance start) */
+#define OMAP4430_PRCM_MPU_CPU0_MPU_CDOFFS	0x0018
+#define OMAP4430_PRCM_MPU_CPU1_MPU_CDOFFS	0x0018
+
+
+/*
+ * PRCM_MPU
+ *
+ * The PRCM_MPU is a local PRCM inside the MPU subsystem. For the PRCM (global)
+ * point of view the PRCM_MPU is a single entity. It shares the same
+ * programming model as the global PRCM and thus can be assimilate as two new
+ * MOD inside the PRCM
+ */
+
+/* PRCM_MPU.OCP_SOCKET_PRCM register offsets */
+#define OMAP4_REVISION_PRCM_OFFSET			0x0000
+#define OMAP4430_REVISION_PRCM				OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_OCP_SOCKET_PRCM_INST, 0x0000)
+
+/* PRCM_MPU.DEVICE_PRM register offsets */
+#define OMAP4_PRCM_MPU_PRM_RSTST_OFFSET			0x0000
+#define OMAP4430_PRCM_MPU_PRM_RSTST			OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_DEVICE_PRM_INST, 0x0000)
+#define OMAP4_PRCM_MPU_PRM_PSCON_COUNT_OFFSET		0x0004
+#define OMAP4430_PRCM_MPU_PRM_PSCON_COUNT		OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_DEVICE_PRM_INST, 0x0004)
+
+/* PRCM_MPU.CPU0 register offsets */
+#define OMAP4_PM_CPU0_PWRSTCTRL_OFFSET			0x0000
+#define OMAP4430_PM_CPU0_PWRSTCTRL			OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_CPU0_INST, 0x0000)
+#define OMAP4_PM_CPU0_PWRSTST_OFFSET			0x0004
+#define OMAP4430_PM_CPU0_PWRSTST			OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_CPU0_INST, 0x0004)
+#define OMAP4_RM_CPU0_CPU0_CONTEXT_OFFSET		0x0008
+#define OMAP4430_RM_CPU0_CPU0_CONTEXT			OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_CPU0_INST, 0x0008)
+#define OMAP4_RM_CPU0_CPU0_RSTCTRL_OFFSET		0x000c
+#define OMAP4430_RM_CPU0_CPU0_RSTCTRL			OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_CPU0_INST, 0x000c)
+#define OMAP4_RM_CPU0_CPU0_RSTST_OFFSET			0x0010
+#define OMAP4430_RM_CPU0_CPU0_RSTST			OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_CPU0_INST, 0x0010)
+#define OMAP4_CM_CPU0_CPU0_CLKCTRL_OFFSET		0x0014
+#define OMAP4430_CM_CPU0_CPU0_CLKCTRL			OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_CPU0_INST, 0x0014)
+#define OMAP4_CM_CPU0_CLKSTCTRL_OFFSET			0x0018
+#define OMAP4430_CM_CPU0_CLKSTCTRL			OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_CPU0_INST, 0x0018)
+
+/* PRCM_MPU.CPU1 register offsets */
+#define OMAP4_PM_CPU1_PWRSTCTRL_OFFSET			0x0000
+#define OMAP4430_PM_CPU1_PWRSTCTRL			OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_CPU1_INST, 0x0000)
+#define OMAP4_PM_CPU1_PWRSTST_OFFSET			0x0004
+#define OMAP4430_PM_CPU1_PWRSTST			OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_CPU1_INST, 0x0004)
+#define OMAP4_RM_CPU1_CPU1_CONTEXT_OFFSET		0x0008
+#define OMAP4430_RM_CPU1_CPU1_CONTEXT			OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_CPU1_INST, 0x0008)
+#define OMAP4_RM_CPU1_CPU1_RSTCTRL_OFFSET		0x000c
+#define OMAP4430_RM_CPU1_CPU1_RSTCTRL			OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_CPU1_INST, 0x000c)
+#define OMAP4_RM_CPU1_CPU1_RSTST_OFFSET			0x0010
+#define OMAP4430_RM_CPU1_CPU1_RSTST			OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_CPU1_INST, 0x0010)
+#define OMAP4_CM_CPU1_CPU1_CLKCTRL_OFFSET		0x0014
+#define OMAP4430_CM_CPU1_CPU1_CLKCTRL			OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_CPU1_INST, 0x0014)
+#define OMAP4_CM_CPU1_CLKSTCTRL_OFFSET			0x0018
+#define OMAP4430_CM_CPU1_CLKSTCTRL			OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_CPU1_INST, 0x0018)
+
+/* Function prototypes */
+# ifndef __ASSEMBLER__
+extern u32 omap4_prcm_mpu_read_inst_reg(s16 inst, u16 idx);
+extern void omap4_prcm_mpu_write_inst_reg(u32 val, s16 inst, u16 idx);
+extern u32 omap4_prcm_mpu_rmw_inst_reg_bits(u32 mask, u32 bits, s16 inst,
+					    s16 idx);
+# endif
+
+#endif
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/prm2xxx_3xxx.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/prm2xxx_3xxx.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/prm2xxx_3xxx.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/prm2xxx_3xxx.c	2011-03-14 21:20:32.000000000 -0400
@@ -12,18 +12,65 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/delay.h>
 #include <linux/errno.h>
 #include <linux/err.h>
+#include <linux/io.h>
 
 #include <plat/common.h>
 #include <plat/cpu.h>
 #include <plat/prcm.h>
 
-#include "prm.h"
+#include "prm2xxx_3xxx.h"
+#include "cm2xxx_3xxx.h"
 #include "prm-regbits-24xx.h"
 #include "prm-regbits-34xx.h"
 
+u32 omap2_prm_read_mod_reg(s16 module, u16 idx)
+{
+	return __raw_readl(prm_base + module + idx);
+}
+
+void omap2_prm_write_mod_reg(u32 val, s16 module, u16 idx)
+{
+	__raw_writel(val, prm_base + module + idx);
+}
+
+/* Read-modify-write a register in a PRM module. Caller must lock */
+u32 omap2_prm_rmw_mod_reg_bits(u32 mask, u32 bits, s16 module, s16 idx)
+{
+	u32 v;
+
+	v = omap2_prm_read_mod_reg(module, idx);
+	v &= ~mask;
+	v |= bits;
+	omap2_prm_write_mod_reg(v, module, idx);
+
+	return v;
+}
+
+/* Read a PRM register, AND it, and shift the result down to bit 0 */
+u32 omap2_prm_read_mod_bits_shift(s16 domain, s16 idx, u32 mask)
+{
+	u32 v;
+
+	v = omap2_prm_read_mod_reg(domain, idx);
+	v &= mask;
+	v >>= __ffs(mask);
+
+	return v;
+}
+
+u32 omap2_prm_set_mod_reg_bits(u32 bits, s16 module, s16 idx)
+{
+	return omap2_prm_rmw_mod_reg_bits(bits, bits, module, idx);
+}
+
+u32 omap2_prm_clear_mod_reg_bits(u32 bits, s16 module, s16 idx)
+{
+	return omap2_prm_rmw_mod_reg_bits(bits, 0x0, module, idx);
+}
+
+
 /**
  * omap2_prm_is_hardreset_asserted - read the HW reset line state of
  * submodules contained in the hwmod module
@@ -39,7 +86,7 @@ int omap2_prm_is_hardreset_asserted(s16
 	if (!(cpu_is_omap24xx() || cpu_is_omap34xx()))
 		return -EINVAL;
 
-	return prm_read_mod_bits_shift(prm_mod, OMAP2_RM_RSTCTRL,
+	return omap2_prm_read_mod_bits_shift(prm_mod, OMAP2_RM_RSTCTRL,
 				       (1 << shift));
 }
 
@@ -63,7 +110,7 @@ int omap2_prm_assert_hardreset(s16 prm_m
 		return -EINVAL;
 
 	mask = 1 << shift;
-	prm_rmw_mod_reg_bits(mask, mask, prm_mod, OMAP2_RM_RSTCTRL);
+	omap2_prm_rmw_mod_reg_bits(mask, mask, prm_mod, OMAP2_RM_RSTCTRL);
 
 	return 0;
 }
@@ -93,18 +140,17 @@ int omap2_prm_deassert_hardreset(s16 prm
 	mask = 1 << shift;
 
 	/* Check the current status to avoid de-asserting the line twice */
-	if (prm_read_mod_bits_shift(prm_mod, OMAP2_RM_RSTCTRL, mask) == 0)
+	if (omap2_prm_read_mod_bits_shift(prm_mod, OMAP2_RM_RSTCTRL, mask) == 0)
 		return -EEXIST;
 
 	/* Clear the reset status by writing 1 to the status bit */
-	prm_rmw_mod_reg_bits(0xffffffff, mask, prm_mod, OMAP2_RM_RSTST);
+	omap2_prm_rmw_mod_reg_bits(0xffffffff, mask, prm_mod, OMAP2_RM_RSTST);
 	/* de-assert the reset control line */
-	prm_rmw_mod_reg_bits(mask, 0, prm_mod, OMAP2_RM_RSTCTRL);
+	omap2_prm_rmw_mod_reg_bits(mask, 0, prm_mod, OMAP2_RM_RSTCTRL);
 	/* wait the status to be set */
-	omap_test_timeout(prm_read_mod_bits_shift(prm_mod, OMAP2_RM_RSTST,
+	omap_test_timeout(omap2_prm_read_mod_bits_shift(prm_mod, OMAP2_RM_RSTST,
 						  mask),
 			  MAX_MODULE_HARDRESET_WAIT, c);
 
 	return (c == MAX_MODULE_HARDRESET_WAIT) ? -EBUSY : 0;
 }
-
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/prm2xxx_3xxx.h linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/prm2xxx_3xxx.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/prm2xxx_3xxx.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/prm2xxx_3xxx.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,428 @@
+/*
+ * OMAP2/3 Power/Reset Management (PRM) register definitions
+ *
+ * Copyright (C) 2007-2009 Texas Instruments, Inc.
+ * Copyright (C) 2008-2010 Nokia Corporation
+ * Paul Walmsley
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * The PRM hardware modules on the OMAP2/3 are quite similar to each
+ * other.  The PRM on OMAP4 has a new register layout, and is handled
+ * in a separate file.
+ */
+#ifndef __ARCH_ARM_MACH_OMAP2_PRM2XXX_3XXX_H
+#define __ARCH_ARM_MACH_OMAP2_PRM2XXX_3XXX_H
+
+#include "prcm-common.h"
+#include "prm.h"
+
+#define OMAP2420_PRM_REGADDR(module, reg)				\
+		OMAP2_L4_IO_ADDRESS(OMAP2420_PRM_BASE + (module) + (reg))
+#define OMAP2430_PRM_REGADDR(module, reg)				\
+		OMAP2_L4_IO_ADDRESS(OMAP2430_PRM_BASE + (module) + (reg))
+#define OMAP34XX_PRM_REGADDR(module, reg)				\
+		OMAP2_L4_IO_ADDRESS(OMAP3430_PRM_BASE + (module) + (reg))
+
+
+/*
+ * OMAP2-specific global PRM registers
+ * Use __raw_{read,write}l() with these registers.
+ *
+ * With a few exceptions, these are the register names beginning with
+ * PRCM_* on 24xx.  (The exceptions are the IRQSTATUS and IRQENABLE
+ * bits.)
+ *
+ */
+
+#define OMAP2_PRCM_REVISION_OFFSET	0x0000
+#define OMAP2420_PRCM_REVISION		OMAP2420_PRM_REGADDR(OCP_MOD, 0x0000)
+#define OMAP2_PRCM_SYSCONFIG_OFFSET	0x0010
+#define OMAP2420_PRCM_SYSCONFIG		OMAP2420_PRM_REGADDR(OCP_MOD, 0x0010)
+
+#define OMAP2_PRCM_IRQSTATUS_MPU_OFFSET	0x0018
+#define OMAP2420_PRCM_IRQSTATUS_MPU	OMAP2420_PRM_REGADDR(OCP_MOD, 0x0018)
+#define OMAP2_PRCM_IRQENABLE_MPU_OFFSET	0x001c
+#define OMAP2420_PRCM_IRQENABLE_MPU	OMAP2420_PRM_REGADDR(OCP_MOD, 0x001c)
+
+#define OMAP2_PRCM_VOLTCTRL_OFFSET	0x0050
+#define OMAP2420_PRCM_VOLTCTRL		OMAP2420_PRM_REGADDR(OCP_MOD, 0x0050)
+#define OMAP2_PRCM_VOLTST_OFFSET	0x0054
+#define OMAP2420_PRCM_VOLTST		OMAP2420_PRM_REGADDR(OCP_MOD, 0x0054)
+#define OMAP2_PRCM_CLKSRC_CTRL_OFFSET	0x0060
+#define OMAP2420_PRCM_CLKSRC_CTRL	OMAP2420_PRM_REGADDR(OCP_MOD, 0x0060)
+#define OMAP2_PRCM_CLKOUT_CTRL_OFFSET	0x0070
+#define OMAP2420_PRCM_CLKOUT_CTRL	OMAP2420_PRM_REGADDR(OCP_MOD, 0x0070)
+#define OMAP2_PRCM_CLKEMUL_CTRL_OFFSET	0x0078
+#define OMAP2420_PRCM_CLKEMUL_CTRL	OMAP2420_PRM_REGADDR(OCP_MOD, 0x0078)
+#define OMAP2_PRCM_CLKCFG_CTRL_OFFSET	0x0080
+#define OMAP2420_PRCM_CLKCFG_CTRL	OMAP2420_PRM_REGADDR(OCP_MOD, 0x0080)
+#define OMAP2_PRCM_CLKCFG_STATUS_OFFSET	0x0084
+#define OMAP2420_PRCM_CLKCFG_STATUS	OMAP2420_PRM_REGADDR(OCP_MOD, 0x0084)
+#define OMAP2_PRCM_VOLTSETUP_OFFSET	0x0090
+#define OMAP2420_PRCM_VOLTSETUP		OMAP2420_PRM_REGADDR(OCP_MOD, 0x0090)
+#define OMAP2_PRCM_CLKSSETUP_OFFSET	0x0094
+#define OMAP2420_PRCM_CLKSSETUP		OMAP2420_PRM_REGADDR(OCP_MOD, 0x0094)
+#define OMAP2_PRCM_POLCTRL_OFFSET	0x0098
+#define OMAP2420_PRCM_POLCTRL		OMAP2420_PRM_REGADDR(OCP_MOD, 0x0098)
+
+#define OMAP2430_PRCM_REVISION		OMAP2430_PRM_REGADDR(OCP_MOD, 0x0000)
+#define OMAP2430_PRCM_SYSCONFIG		OMAP2430_PRM_REGADDR(OCP_MOD, 0x0010)
+
+#define OMAP2430_PRCM_IRQSTATUS_MPU	OMAP2430_PRM_REGADDR(OCP_MOD, 0x0018)
+#define OMAP2430_PRCM_IRQENABLE_MPU	OMAP2430_PRM_REGADDR(OCP_MOD, 0x001c)
+
+#define OMAP2430_PRCM_VOLTCTRL		OMAP2430_PRM_REGADDR(OCP_MOD, 0x0050)
+#define OMAP2430_PRCM_VOLTST		OMAP2430_PRM_REGADDR(OCP_MOD, 0x0054)
+#define OMAP2430_PRCM_CLKSRC_CTRL	OMAP2430_PRM_REGADDR(OCP_MOD, 0x0060)
+#define OMAP2430_PRCM_CLKOUT_CTRL	OMAP2430_PRM_REGADDR(OCP_MOD, 0x0070)
+#define OMAP2430_PRCM_CLKEMUL_CTRL	OMAP2430_PRM_REGADDR(OCP_MOD, 0x0078)
+#define OMAP2430_PRCM_CLKCFG_CTRL	OMAP2430_PRM_REGADDR(OCP_MOD, 0x0080)
+#define OMAP2430_PRCM_CLKCFG_STATUS	OMAP2430_PRM_REGADDR(OCP_MOD, 0x0084)
+#define OMAP2430_PRCM_VOLTSETUP		OMAP2430_PRM_REGADDR(OCP_MOD, 0x0090)
+#define OMAP2430_PRCM_CLKSSETUP		OMAP2430_PRM_REGADDR(OCP_MOD, 0x0094)
+#define OMAP2430_PRCM_POLCTRL		OMAP2430_PRM_REGADDR(OCP_MOD, 0x0098)
+
+/*
+ * OMAP3-specific global PRM registers
+ * Use __raw_{read,write}l() with these registers.
+ *
+ * With a few exceptions, these are the register names beginning with
+ * PRM_* on 34xx.  (The exceptions are the IRQSTATUS and IRQENABLE
+ * bits.)
+ */
+
+#define OMAP3_PRM_REVISION_OFFSET	0x0004
+#define OMAP3430_PRM_REVISION		OMAP34XX_PRM_REGADDR(OCP_MOD, 0x0004)
+#define OMAP3_PRM_SYSCONFIG_OFFSET	0x0014
+#define OMAP3430_PRM_SYSCONFIG		OMAP34XX_PRM_REGADDR(OCP_MOD, 0x0014)
+
+#define OMAP3_PRM_IRQSTATUS_MPU_OFFSET	0x0018
+#define OMAP3430_PRM_IRQSTATUS_MPU	OMAP34XX_PRM_REGADDR(OCP_MOD, 0x0018)
+#define OMAP3_PRM_IRQENABLE_MPU_OFFSET	0x001c
+#define OMAP3430_PRM_IRQENABLE_MPU	OMAP34XX_PRM_REGADDR(OCP_MOD, 0x001c)
+
+
+#define OMAP3_PRM_VC_SMPS_SA_OFFSET	0x0020
+#define OMAP3430_PRM_VC_SMPS_SA		OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0020)
+#define OMAP3_PRM_VC_SMPS_VOL_RA_OFFSET	0x0024
+#define OMAP3430_PRM_VC_SMPS_VOL_RA	OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0024)
+#define OMAP3_PRM_VC_SMPS_CMD_RA_OFFSET	0x0028
+#define OMAP3430_PRM_VC_SMPS_CMD_RA	OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0028)
+#define OMAP3_PRM_VC_CMD_VAL_0_OFFSET	0x002c
+#define OMAP3430_PRM_VC_CMD_VAL_0	OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x002c)
+#define OMAP3_PRM_VC_CMD_VAL_1_OFFSET	0x0030
+#define OMAP3430_PRM_VC_CMD_VAL_1	OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0030)
+#define OMAP3_PRM_VC_CH_CONF_OFFSET	0x0034
+#define OMAP3430_PRM_VC_CH_CONF		OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0034)
+#define OMAP3_PRM_VC_I2C_CFG_OFFSET	0x0038
+#define OMAP3430_PRM_VC_I2C_CFG		OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0038)
+#define OMAP3_PRM_VC_BYPASS_VAL_OFFSET	0x003c
+#define OMAP3430_PRM_VC_BYPASS_VAL	OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x003c)
+#define OMAP3_PRM_RSTCTRL_OFFSET	0x0050
+#define OMAP3430_PRM_RSTCTRL		OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0050)
+#define OMAP3_PRM_RSTTIME_OFFSET	0x0054
+#define OMAP3430_PRM_RSTTIME		OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0054)
+#define OMAP3_PRM_RSTST_OFFSET	0x0058
+#define OMAP3430_PRM_RSTST		OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0058)
+#define OMAP3_PRM_VOLTCTRL_OFFSET	0x0060
+#define OMAP3430_PRM_VOLTCTRL		OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0060)
+#define OMAP3_PRM_SRAM_PCHARGE_OFFSET	0x0064
+#define OMAP3430_PRM_SRAM_PCHARGE	OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0064)
+#define OMAP3_PRM_CLKSRC_CTRL_OFFSET	0x0070
+#define OMAP3430_PRM_CLKSRC_CTRL	OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0070)
+#define OMAP3_PRM_VOLTSETUP1_OFFSET	0x0090
+#define OMAP3430_PRM_VOLTSETUP1		OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0090)
+#define OMAP3_PRM_VOLTOFFSET_OFFSET	0x0094
+#define OMAP3430_PRM_VOLTOFFSET		OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0094)
+#define OMAP3_PRM_CLKSETUP_OFFSET	0x0098
+#define OMAP3430_PRM_CLKSETUP		OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0098)
+#define OMAP3_PRM_POLCTRL_OFFSET	0x009c
+#define OMAP3430_PRM_POLCTRL		OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x009c)
+#define OMAP3_PRM_VOLTSETUP2_OFFSET	0x00a0
+#define OMAP3430_PRM_VOLTSETUP2		OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00a0)
+#define OMAP3_PRM_VP1_CONFIG_OFFSET	0x00b0
+#define OMAP3430_PRM_VP1_CONFIG		OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00b0)
+#define OMAP3_PRM_VP1_VSTEPMIN_OFFSET	0x00b4
+#define OMAP3430_PRM_VP1_VSTEPMIN	OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00b4)
+#define OMAP3_PRM_VP1_VSTEPMAX_OFFSET	0x00b8
+#define OMAP3430_PRM_VP1_VSTEPMAX	OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00b8)
+#define OMAP3_PRM_VP1_VLIMITTO_OFFSET	0x00bc
+#define OMAP3430_PRM_VP1_VLIMITTO	OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00bc)
+#define OMAP3_PRM_VP1_VOLTAGE_OFFSET	0x00c0
+#define OMAP3430_PRM_VP1_VOLTAGE	OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00c0)
+#define OMAP3_PRM_VP1_STATUS_OFFSET	0x00c4
+#define OMAP3430_PRM_VP1_STATUS		OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00c4)
+#define OMAP3_PRM_VP2_CONFIG_OFFSET	0x00d0
+#define OMAP3430_PRM_VP2_CONFIG		OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00d0)
+#define OMAP3_PRM_VP2_VSTEPMIN_OFFSET	0x00d4
+#define OMAP3430_PRM_VP2_VSTEPMIN	OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00d4)
+#define OMAP3_PRM_VP2_VSTEPMAX_OFFSET	0x00d8
+#define OMAP3430_PRM_VP2_VSTEPMAX	OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00d8)
+#define OMAP3_PRM_VP2_VLIMITTO_OFFSET	0x00dc
+#define OMAP3430_PRM_VP2_VLIMITTO	OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00dc)
+#define OMAP3_PRM_VP2_VOLTAGE_OFFSET	0x00e0
+#define OMAP3430_PRM_VP2_VOLTAGE	OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00e0)
+#define OMAP3_PRM_VP2_STATUS_OFFSET	0x00e4
+#define OMAP3430_PRM_VP2_STATUS		OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00e4)
+
+#define OMAP3_PRM_CLKSEL_OFFSET	0x0040
+#define OMAP3430_PRM_CLKSEL		OMAP34XX_PRM_REGADDR(OMAP3430_CCR_MOD, 0x0040)
+#define OMAP3_PRM_CLKOUT_CTRL_OFFSET	0x0070
+#define OMAP3430_PRM_CLKOUT_CTRL	OMAP34XX_PRM_REGADDR(OMAP3430_CCR_MOD, 0x0070)
+
+/*
+ * Module specific PRM register offsets from PRM_BASE + domain offset
+ *
+ * Use prm_{read,write}_mod_reg() with these registers.
+ *
+ * With a few exceptions, these are the register names beginning with
+ * {PM,RM}_* on both OMAP2/3 SoC families..  (The exceptions are the
+ * IRQSTATUS and IRQENABLE bits.)
+ */
+
+/* Register offsets appearing on both OMAP2 and OMAP3 */
+
+#define OMAP2_RM_RSTCTRL				0x0050
+#define OMAP2_RM_RSTTIME				0x0054
+#define OMAP2_RM_RSTST					0x0058
+#define OMAP2_PM_PWSTCTRL				0x00e0
+#define OMAP2_PM_PWSTST					0x00e4
+
+#define PM_WKEN						0x00a0
+#define PM_WKEN1					PM_WKEN
+#define PM_WKST						0x00b0
+#define PM_WKST1					PM_WKST
+#define PM_WKDEP					0x00c8
+#define PM_EVGENCTRL					0x00d4
+#define PM_EVGENONTIM					0x00d8
+#define PM_EVGENOFFTIM					0x00dc
+
+/* OMAP2xxx specific register offsets */
+#define OMAP24XX_PM_WKEN2				0x00a4
+#define OMAP24XX_PM_WKST2				0x00b4
+
+#define OMAP24XX_PRCM_IRQSTATUS_DSP			0x00f0	/* IVA mod */
+#define OMAP24XX_PRCM_IRQENABLE_DSP			0x00f4	/* IVA mod */
+#define OMAP24XX_PRCM_IRQSTATUS_IVA			0x00f8
+#define OMAP24XX_PRCM_IRQENABLE_IVA			0x00fc
+
+/* OMAP3 specific register offsets */
+#define OMAP3430ES2_PM_WKEN3				0x00f0
+#define OMAP3430ES2_PM_WKST3				0x00b8
+
+#define OMAP3430_PM_MPUGRPSEL				0x00a4
+#define OMAP3430_PM_MPUGRPSEL1				OMAP3430_PM_MPUGRPSEL
+#define OMAP3430ES2_PM_MPUGRPSEL3			0x00f8
+
+#define OMAP3430_PM_IVAGRPSEL				0x00a8
+#define OMAP3430_PM_IVAGRPSEL1				OMAP3430_PM_IVAGRPSEL
+#define OMAP3430ES2_PM_IVAGRPSEL3			0x00f4
+
+#define OMAP3430_PM_PREPWSTST				0x00e8
+
+#define OMAP3430_PRM_IRQSTATUS_IVA2			0x00f8
+#define OMAP3430_PRM_IRQENABLE_IVA2			0x00fc
+
+
+#ifndef __ASSEMBLER__
+/*
+ * Stub omap2xxx/omap3xxx functions so that common files
+ * continue to build when custom builds are used
+ */
+#if defined(CONFIG_ARCH_OMAP4) && !(defined(CONFIG_ARCH_OMAP2) ||	\
+					defined(CONFIG_ARCH_OMAP3))
+static inline u32 omap2_prm_read_mod_reg(s16 module, u16 idx)
+{
+	WARN(1, "prm: omap2xxx/omap3xxx specific function and "
+		"not suppose to be used on omap4\n");
+	return 0;
+}
+static inline void omap2_prm_write_mod_reg(u32 val, s16 module, u16 idx)
+{
+	WARN(1, "prm: omap2xxx/omap3xxx specific function and "
+		"not suppose to be used on omap4\n");
+}
+static inline u32 omap2_prm_rmw_mod_reg_bits(u32 mask, u32 bits,
+		s16 module, s16 idx)
+{
+	WARN(1, "prm: omap2xxx/omap3xxx specific function and "
+		"not suppose to be used on omap4\n");
+	return 0;
+}
+static inline u32 omap2_prm_set_mod_reg_bits(u32 bits, s16 module, s16 idx)
+{
+	WARN(1, "prm: omap2xxx/omap3xxx specific function and "
+		"not suppose to be used on omap4\n");
+	return 0;
+}
+static inline u32 omap2_prm_clear_mod_reg_bits(u32 bits, s16 module, s16 idx)
+{
+	WARN(1, "prm: omap2xxx/omap3xxx specific function and "
+		"not suppose to be used on omap4\n");
+	return 0;
+}
+static inline u32 omap2_prm_read_mod_bits_shift(s16 domain, s16 idx, u32 mask)
+{
+	WARN(1, "prm: omap2xxx/omap3xxx specific function and "
+		"not suppose to be used on omap4\n");
+	return 0;
+}
+static inline int omap2_prm_is_hardreset_asserted(s16 prm_mod, u8 shift)
+{
+	WARN(1, "prm: omap2xxx/omap3xxx specific function and "
+		"not suppose to be used on omap4\n");
+	return 0;
+}
+static inline int omap2_prm_assert_hardreset(s16 prm_mod, u8 shift)
+{
+	WARN(1, "prm: omap2xxx/omap3xxx specific function and "
+		"not suppose to be used on omap4\n");
+	return 0;
+}
+static inline int omap2_prm_deassert_hardreset(s16 prm_mod, u8 shift)
+{
+	WARN(1, "prm: omap2xxx/omap3xxx specific function and "
+		"not suppose to be used on omap4\n");
+	return 0;
+}
+#else
+/* Power/reset management domain register get/set */
+extern u32 omap2_prm_read_mod_reg(s16 module, u16 idx);
+extern void omap2_prm_write_mod_reg(u32 val, s16 module, u16 idx);
+extern u32 omap2_prm_rmw_mod_reg_bits(u32 mask, u32 bits, s16 module, s16 idx);
+extern u32 omap2_prm_set_mod_reg_bits(u32 bits, s16 module, s16 idx);
+extern u32 omap2_prm_clear_mod_reg_bits(u32 bits, s16 module, s16 idx);
+extern u32 omap2_prm_read_mod_bits_shift(s16 domain, s16 idx, u32 mask);
+
+/* These omap2_ PRM functions apply to both OMAP2 and 3 */
+extern int omap2_prm_is_hardreset_asserted(s16 prm_mod, u8 shift);
+extern int omap2_prm_assert_hardreset(s16 prm_mod, u8 shift);
+extern int omap2_prm_deassert_hardreset(s16 prm_mod, u8 shift);
+
+#endif	/* CONFIG_ARCH_OMAP4 */
+#endif
+
+/*
+ * Bits common to specific registers
+ *
+ * The 3430 register and bit names are generally used,
+ * since they tend to make more sense
+ */
+
+/* PM_EVGENONTIM_MPU */
+/* Named PM_EVEGENONTIM_MPU on the 24XX */
+#define OMAP_ONTIMEVAL_SHIFT				0
+#define OMAP_ONTIMEVAL_MASK				(0xffffffff << 0)
+
+/* PM_EVGENOFFTIM_MPU */
+/* Named PM_EVEGENOFFTIM_MPU on the 24XX */
+#define OMAP_OFFTIMEVAL_SHIFT				0
+#define OMAP_OFFTIMEVAL_MASK				(0xffffffff << 0)
+
+/* PRM_CLKSETUP and PRCM_VOLTSETUP */
+/* Named PRCM_CLKSSETUP on the 24XX */
+#define OMAP_SETUP_TIME_SHIFT				0
+#define OMAP_SETUP_TIME_MASK				(0xffff << 0)
+
+/* PRM_CLKSRC_CTRL */
+/* Named PRCM_CLKSRC_CTRL on the 24XX */
+#define OMAP_SYSCLKDIV_SHIFT				6
+#define OMAP_SYSCLKDIV_MASK				(0x3 << 6)
+#define OMAP_AUTOEXTCLKMODE_SHIFT			3
+#define OMAP_AUTOEXTCLKMODE_MASK			(0x3 << 3)
+#define OMAP_SYSCLKSEL_SHIFT				0
+#define OMAP_SYSCLKSEL_MASK				(0x3 << 0)
+
+/* PM_EVGENCTRL_MPU */
+#define OMAP_OFFLOADMODE_SHIFT				3
+#define OMAP_OFFLOADMODE_MASK				(0x3 << 3)
+#define OMAP_ONLOADMODE_SHIFT				1
+#define OMAP_ONLOADMODE_MASK				(0x3 << 1)
+#define OMAP_ENABLE_MASK				(1 << 0)
+
+/* PRM_RSTTIME */
+/* Named RM_RSTTIME_WKUP on the 24xx */
+#define OMAP_RSTTIME2_SHIFT				8
+#define OMAP_RSTTIME2_MASK				(0x1f << 8)
+#define OMAP_RSTTIME1_SHIFT				0
+#define OMAP_RSTTIME1_MASK				(0xff << 0)
+
+/* PRM_RSTCTRL */
+/* Named RM_RSTCTRL_WKUP on the 24xx */
+/* 2420 calls RST_DPLL3 'RST_DPLL' */
+#define OMAP_RST_DPLL3_MASK				(1 << 2)
+#define OMAP_RST_GS_MASK				(1 << 1)
+
+
+/*
+ * Bits common to module-shared registers
+ *
+ * Not all registers of a particular type support all of these bits -
+ * check TRM if you are unsure
+ */
+
+/*
+ * 24XX: RM_RSTST_MPU and RM_RSTST_DSP - on 24XX, 'COREDOMAINWKUP_RST' is
+ *	 called 'COREWKUP_RST'
+ *
+ * 3430: RM_RSTST_IVA2, RM_RSTST_MPU, RM_RSTST_GFX, RM_RSTST_DSS,
+ *	 RM_RSTST_CAM, RM_RSTST_PER, RM_RSTST_NEON
+ */
+#define OMAP_COREDOMAINWKUP_RST_MASK			(1 << 3)
+
+/*
+ * 24XX: RM_RSTST_MPU, RM_RSTST_GFX, RM_RSTST_DSP
+ *
+ * 2430: RM_RSTST_MDM
+ *
+ * 3430: RM_RSTST_CORE, RM_RSTST_EMU
+ */
+#define OMAP_DOMAINWKUP_RST_MASK			(1 << 2)
+
+/*
+ * 24XX: RM_RSTST_MPU, RM_RSTST_WKUP, RM_RSTST_DSP
+ *	 On 24XX, 'GLOBALWARM_RST' is called 'GLOBALWMPU_RST'.
+ *
+ * 2430: RM_RSTST_MDM
+ *
+ * 3430: RM_RSTST_CORE, RM_RSTST_EMU
+ */
+#define OMAP_GLOBALWARM_RST_MASK			(1 << 1)
+#define OMAP_GLOBALCOLD_RST_MASK			(1 << 0)
+
+/*
+ * 24XX: PM_WKDEP_GFX, PM_WKDEP_MPU, PM_WKDEP_CORE, PM_WKDEP_DSP
+ *	 2420 TRM sometimes uses "EN_WAKEUP" instead of "EN_WKUP"
+ *
+ * 2430: PM_WKDEP_MDM
+ *
+ * 3430: PM_WKDEP_IVA2, PM_WKDEP_GFX, PM_WKDEP_DSS, PM_WKDEP_CAM,
+ *	 PM_WKDEP_PER
+ */
+#define OMAP_EN_WKUP_SHIFT				4
+#define OMAP_EN_WKUP_MASK				(1 << 4)
+
+/*
+ * 24XX: PM_PWSTCTRL_MPU, PM_PWSTCTRL_CORE, PM_PWSTCTRL_GFX,
+ *	 PM_PWSTCTRL_DSP
+ *
+ * 2430: PM_PWSTCTRL_MDM
+ *
+ * 3430: PM_PWSTCTRL_IVA2, PM_PWSTCTRL_CORE, PM_PWSTCTRL_GFX,
+ *	 PM_PWSTCTRL_DSS, PM_PWSTCTRL_CAM, PM_PWSTCTRL_PER,
+ *	 PM_PWSTCTRL_NEON
+ */
+#define OMAP_LOGICRETSTATE_MASK				(1 << 2)
+
+
+/*
+ * MAX_MODULE_HARDRESET_WAIT: Maximum microseconds to wait for an OMAP
+ * submodule to exit hardreset
+ */
+#define MAX_MODULE_HARDRESET_WAIT		10000
+
+
+#endif
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/prm44xx.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/prm44xx.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/prm44xx.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/prm44xx.c	2011-03-14 21:20:32.000000000 -0400
@@ -15,12 +15,13 @@
 #include <linux/delay.h>
 #include <linux/errno.h>
 #include <linux/err.h>
+#include <linux/io.h>
 
 #include <plat/common.h>
 #include <plat/cpu.h>
 #include <plat/prcm.h>
 
-#include "prm.h"
+#include "prm44xx.h"
 #include "prm-regbits-44xx.h"
 
 /*
@@ -29,6 +30,70 @@
  */
 #define OMAP4_RST_CTRL_ST_OFFSET		4
 
+/* PRM low-level functions */
+
+/* Read a register in a CM/PRM instance in the PRM module */
+u32 omap4_prm_read_inst_reg(s16 inst, u16 reg)
+{
+	return __raw_readl(OMAP44XX_PRM_REGADDR(inst, reg));
+}
+
+/* Write into a register in a CM/PRM instance in the PRM module */
+void omap4_prm_write_inst_reg(u32 val, s16 inst, u16 reg)
+{
+	__raw_writel(val, OMAP44XX_PRM_REGADDR(inst, reg));
+}
+
+/* Read-modify-write a register in a PRM module. Caller must lock */
+u32 omap4_prm_rmw_inst_reg_bits(u32 mask, u32 bits, s16 inst, s16 reg)
+{
+	u32 v;
+
+	v = omap4_prm_read_inst_reg(inst, reg);
+	v &= ~mask;
+	v |= bits;
+	omap4_prm_write_inst_reg(v, inst, reg);
+
+	return v;
+}
+
+/* Read a PRM register, AND it, and shift the result down to bit 0 */
+/* XXX deprecated */
+u32 omap4_prm_read_bits_shift(void __iomem *reg, u32 mask)
+{
+	u32 v;
+
+	v = __raw_readl(reg);
+	v &= mask;
+	v >>= __ffs(mask);
+
+	return v;
+}
+
+/* Read-modify-write a register in a PRM module. Caller must lock */
+/* XXX deprecated */
+u32 omap4_prm_rmw_reg_bits(u32 mask, u32 bits, void __iomem *reg)
+{
+	u32 v;
+
+	v = __raw_readl(reg);
+	v &= ~mask;
+	v |= bits;
+	__raw_writel(v, reg);
+
+	return v;
+}
+
+u32 omap4_prm_set_inst_reg_bits(u32 bits, s16 inst, s16 reg)
+{
+	return omap4_prm_rmw_inst_reg_bits(bits, bits, inst, reg);
+}
+
+u32 omap4_prm_clear_inst_reg_bits(u32 bits, s16 inst, s16 reg)
+{
+	return omap4_prm_rmw_inst_reg_bits(bits, 0x0, inst, reg);
+}
+
 /**
  * omap4_prm_is_hardreset_asserted - read the HW reset line state of
  * submodules contained in the hwmod module
@@ -114,3 +179,17 @@ int omap4_prm_deassert_hardreset(void __
 	return (c == MAX_MODULE_HARDRESET_WAIT) ? -EBUSY : 0;
 }
 
+void omap4_prm_global_warm_sw_reset(void)
+{
+	u32 v;
+
+	v = omap4_prm_read_inst_reg(OMAP4430_PRM_DEVICE_INST,
+				    OMAP4_RM_RSTCTRL);
+	v |= OMAP4430_RST_GLOBAL_WARM_SW_MASK;
+	omap4_prm_write_inst_reg(v, OMAP4430_PRM_DEVICE_INST,
+				 OMAP4_RM_RSTCTRL);
+
+	/* OCP barrier */
+	v = omap4_prm_read_inst_reg(OMAP4430_PRM_DEVICE_INST,
+				    OMAP4_RM_RSTCTRL);
+}
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/prm44xx.h linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/prm44xx.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/prm44xx.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/prm44xx.h	2011-03-14 21:20:32.000000000 -0400
@@ -17,736 +17,762 @@
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
+ *
+ * XXX This file needs to be updated to align on one of "OMAP4", "OMAP44XX",
+ *     or "OMAP4430".
  */
 
 #ifndef __ARCH_ARM_MACH_OMAP2_PRM44XX_H
 #define __ARCH_ARM_MACH_OMAP2_PRM44XX_H
 
+#include "prcm-common.h"
+#include "prm.h"
+
+#define OMAP4430_PRM_BASE		0x4a306000
+
+#define OMAP44XX_PRM_REGADDR(inst, reg)				\
+	OMAP2_L4_IO_ADDRESS(OMAP4430_PRM_BASE +	(inst) + (reg))
+
+
+/* PRM instances */
+#define OMAP4430_PRM_OCP_SOCKET_INST	0x0000
+#define OMAP4430_PRM_CKGEN_INST		0x0100
+#define OMAP4430_PRM_MPU_INST		0x0300
+#define OMAP4430_PRM_TESLA_INST		0x0400
+#define OMAP4430_PRM_ABE_INST		0x0500
+#define OMAP4430_PRM_ALWAYS_ON_INST	0x0600
+#define OMAP4430_PRM_CORE_INST		0x0700
+#define OMAP4430_PRM_IVAHD_INST		0x0f00
+#define OMAP4430_PRM_CAM_INST		0x1000
+#define OMAP4430_PRM_DSS_INST		0x1100
+#define OMAP4430_PRM_GFX_INST		0x1200
+#define OMAP4430_PRM_L3INIT_INST		0x1300
+#define OMAP4430_PRM_L4PER_INST		0x1400
+#define OMAP4430_PRM_CEFUSE_INST		0x1600
+#define OMAP4430_PRM_WKUP_INST		0x1700
+#define OMAP4430_PRM_WKUP_CM_INST	0x1800
+#define OMAP4430_PRM_EMU_INST		0x1900
+#define OMAP4430_PRM_EMU_CM_INST		0x1a00
+#define OMAP4430_PRM_DEVICE_INST		0x1b00
+#define OMAP4430_PRM_INSTR_INST		0x1f00
+
+/* PRM clockdomain register offsets (from instance start) */
+#define OMAP4430_PRM_MPU_MPU_CDOFFS		0x0000
+#define OMAP4430_PRM_TESLA_TESLA_CDOFFS		0x0000
+#define OMAP4430_PRM_ABE_ABE_CDOFFS		0x0000
+#define OMAP4430_PRM_CORE_CORE_CDOFFS		0x0000
+#define OMAP4430_PRM_IVAHD_IVAHD_CDOFFS		0x0000
+#define OMAP4430_PRM_CAM_CAM_CDOFFS		0x0000
+#define OMAP4430_PRM_DSS_DSS_CDOFFS		0x0000
+#define OMAP4430_PRM_GFX_GFX_CDOFFS		0x0000
+#define OMAP4430_PRM_L3INIT_L3INIT_CDOFFS	0x0000
+#define OMAP4430_PRM_L4PER_L4PER_CDOFFS		0x0000
+#define OMAP4430_PRM_CEFUSE_CEFUSE_CDOFFS	0x0000
+#define OMAP4430_PRM_WKUP_CM_WKUP_CDOFFS	0x0000
+#define OMAP4430_PRM_EMU_EMU_CDOFFS		0x0000
+#define OMAP4430_PRM_EMU_CM_EMU_CDOFFS		0x0000
+
+/* OMAP4 specific register offsets */
+#define OMAP4_RM_RSTCTRL				0x0000
+#define OMAP4_RM_RSTTIME				0x0004
+#define OMAP4_RM_RSTST					0x0008
+#define OMAP4_PM_PWSTCTRL				0x0000
+#define OMAP4_PM_PWSTST					0x0004
+
 
 /* PRM */
 
 /* PRM.OCP_SOCKET_PRM register offsets */
 #define OMAP4_REVISION_PRM_OFFSET			0x0000
-#define OMAP4430_REVISION_PRM				OMAP44XX_PRM_REGADDR(OMAP4430_PRM_OCP_SOCKET_MOD, 0x0000)
+#define OMAP4430_REVISION_PRM				OMAP44XX_PRM_REGADDR(OMAP4430_PRM_OCP_SOCKET_INST, 0x0000)
 #define OMAP4_PRM_IRQSTATUS_MPU_OFFSET			0x0010
-#define OMAP4430_PRM_IRQSTATUS_MPU			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_OCP_SOCKET_MOD, 0x0010)
+#define OMAP4430_PRM_IRQSTATUS_MPU			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_OCP_SOCKET_INST, 0x0010)
 #define OMAP4_PRM_IRQSTATUS_MPU_2_OFFSET		0x0014
-#define OMAP4430_PRM_IRQSTATUS_MPU_2			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_OCP_SOCKET_MOD, 0x0014)
+#define OMAP4430_PRM_IRQSTATUS_MPU_2			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_OCP_SOCKET_INST, 0x0014)
 #define OMAP4_PRM_IRQENABLE_MPU_OFFSET			0x0018
-#define OMAP4430_PRM_IRQENABLE_MPU			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_OCP_SOCKET_MOD, 0x0018)
+#define OMAP4430_PRM_IRQENABLE_MPU			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_OCP_SOCKET_INST, 0x0018)
 #define OMAP4_PRM_IRQENABLE_MPU_2_OFFSET		0x001c
-#define OMAP4430_PRM_IRQENABLE_MPU_2			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_OCP_SOCKET_MOD, 0x001c)
+#define OMAP4430_PRM_IRQENABLE_MPU_2			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_OCP_SOCKET_INST, 0x001c)
 #define OMAP4_PRM_IRQSTATUS_DUCATI_OFFSET		0x0020
-#define OMAP4430_PRM_IRQSTATUS_DUCATI			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_OCP_SOCKET_MOD, 0x0020)
+#define OMAP4430_PRM_IRQSTATUS_DUCATI			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_OCP_SOCKET_INST, 0x0020)
 #define OMAP4_PRM_IRQENABLE_DUCATI_OFFSET		0x0028
-#define OMAP4430_PRM_IRQENABLE_DUCATI			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_OCP_SOCKET_MOD, 0x0028)
+#define OMAP4430_PRM_IRQENABLE_DUCATI			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_OCP_SOCKET_INST, 0x0028)
 #define OMAP4_PRM_IRQSTATUS_TESLA_OFFSET		0x0030
-#define OMAP4430_PRM_IRQSTATUS_TESLA			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_OCP_SOCKET_MOD, 0x0030)
+#define OMAP4430_PRM_IRQSTATUS_TESLA			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_OCP_SOCKET_INST, 0x0030)
 #define OMAP4_PRM_IRQENABLE_TESLA_OFFSET		0x0038
-#define OMAP4430_PRM_IRQENABLE_TESLA			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_OCP_SOCKET_MOD, 0x0038)
+#define OMAP4430_PRM_IRQENABLE_TESLA			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_OCP_SOCKET_INST, 0x0038)
 #define OMAP4_CM_PRM_PROFILING_CLKCTRL_OFFSET		0x0040
-#define OMAP4430_CM_PRM_PROFILING_CLKCTRL		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_OCP_SOCKET_MOD, 0x0040)
+#define OMAP4430_CM_PRM_PROFILING_CLKCTRL		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_OCP_SOCKET_INST, 0x0040)
 
 /* PRM.CKGEN_PRM register offsets */
 #define OMAP4_CM_ABE_DSS_SYS_CLKSEL_OFFSET		0x0000
-#define OMAP4430_CM_ABE_DSS_SYS_CLKSEL			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CKGEN_MOD, 0x0000)
+#define OMAP4430_CM_ABE_DSS_SYS_CLKSEL			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CKGEN_INST, 0x0000)
 #define OMAP4_CM_L4_WKUP_CLKSEL_OFFSET			0x0008
-#define OMAP4430_CM_L4_WKUP_CLKSEL			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CKGEN_MOD, 0x0008)
+#define OMAP4430_CM_L4_WKUP_CLKSEL			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CKGEN_INST, 0x0008)
 #define OMAP4_CM_ABE_PLL_REF_CLKSEL_OFFSET		0x000c
-#define OMAP4430_CM_ABE_PLL_REF_CLKSEL			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CKGEN_MOD, 0x000c)
+#define OMAP4430_CM_ABE_PLL_REF_CLKSEL			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CKGEN_INST, 0x000c)
 #define OMAP4_CM_SYS_CLKSEL_OFFSET			0x0010
-#define OMAP4430_CM_SYS_CLKSEL				OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CKGEN_MOD, 0x0010)
+#define OMAP4430_CM_SYS_CLKSEL				OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CKGEN_INST, 0x0010)
 
 /* PRM.MPU_PRM register offsets */
 #define OMAP4_PM_MPU_PWRSTCTRL_OFFSET			0x0000
-#define OMAP4430_PM_MPU_PWRSTCTRL			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_MPU_MOD, 0x0000)
+#define OMAP4430_PM_MPU_PWRSTCTRL			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_MPU_INST, 0x0000)
 #define OMAP4_PM_MPU_PWRSTST_OFFSET			0x0004
-#define OMAP4430_PM_MPU_PWRSTST				OMAP44XX_PRM_REGADDR(OMAP4430_PRM_MPU_MOD, 0x0004)
+#define OMAP4430_PM_MPU_PWRSTST				OMAP44XX_PRM_REGADDR(OMAP4430_PRM_MPU_INST, 0x0004)
 #define OMAP4_RM_MPU_RSTST_OFFSET			0x0014
-#define OMAP4430_RM_MPU_RSTST				OMAP44XX_PRM_REGADDR(OMAP4430_PRM_MPU_MOD, 0x0014)
+#define OMAP4430_RM_MPU_RSTST				OMAP44XX_PRM_REGADDR(OMAP4430_PRM_MPU_INST, 0x0014)
 #define OMAP4_RM_MPU_MPU_CONTEXT_OFFSET			0x0024
-#define OMAP4430_RM_MPU_MPU_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_MPU_MOD, 0x0024)
+#define OMAP4430_RM_MPU_MPU_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_MPU_INST, 0x0024)
 
 /* PRM.TESLA_PRM register offsets */
 #define OMAP4_PM_TESLA_PWRSTCTRL_OFFSET			0x0000
-#define OMAP4430_PM_TESLA_PWRSTCTRL			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_TESLA_MOD, 0x0000)
+#define OMAP4430_PM_TESLA_PWRSTCTRL			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_TESLA_INST, 0x0000)
 #define OMAP4_PM_TESLA_PWRSTST_OFFSET			0x0004
-#define OMAP4430_PM_TESLA_PWRSTST			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_TESLA_MOD, 0x0004)
+#define OMAP4430_PM_TESLA_PWRSTST			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_TESLA_INST, 0x0004)
 #define OMAP4_RM_TESLA_RSTCTRL_OFFSET			0x0010
-#define OMAP4430_RM_TESLA_RSTCTRL			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_TESLA_MOD, 0x0010)
+#define OMAP4430_RM_TESLA_RSTCTRL			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_TESLA_INST, 0x0010)
 #define OMAP4_RM_TESLA_RSTST_OFFSET			0x0014
-#define OMAP4430_RM_TESLA_RSTST				OMAP44XX_PRM_REGADDR(OMAP4430_PRM_TESLA_MOD, 0x0014)
+#define OMAP4430_RM_TESLA_RSTST				OMAP44XX_PRM_REGADDR(OMAP4430_PRM_TESLA_INST, 0x0014)
 #define OMAP4_RM_TESLA_TESLA_CONTEXT_OFFSET		0x0024
-#define OMAP4430_RM_TESLA_TESLA_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_TESLA_MOD, 0x0024)
+#define OMAP4430_RM_TESLA_TESLA_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_TESLA_INST, 0x0024)
 
 /* PRM.ABE_PRM register offsets */
 #define OMAP4_PM_ABE_PWRSTCTRL_OFFSET			0x0000
-#define OMAP4430_PM_ABE_PWRSTCTRL			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_ABE_MOD, 0x0000)
+#define OMAP4430_PM_ABE_PWRSTCTRL			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_ABE_INST, 0x0000)
 #define OMAP4_PM_ABE_PWRSTST_OFFSET			0x0004
-#define OMAP4430_PM_ABE_PWRSTST				OMAP44XX_PRM_REGADDR(OMAP4430_PRM_ABE_MOD, 0x0004)
+#define OMAP4430_PM_ABE_PWRSTST				OMAP44XX_PRM_REGADDR(OMAP4430_PRM_ABE_INST, 0x0004)
 #define OMAP4_RM_ABE_AESS_CONTEXT_OFFSET		0x002c
-#define OMAP4430_RM_ABE_AESS_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_ABE_MOD, 0x002c)
+#define OMAP4430_RM_ABE_AESS_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_ABE_INST, 0x002c)
 #define OMAP4_PM_ABE_PDM_WKDEP_OFFSET			0x0030
-#define OMAP4430_PM_ABE_PDM_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_ABE_MOD, 0x0030)
+#define OMAP4430_PM_ABE_PDM_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_ABE_INST, 0x0030)
 #define OMAP4_RM_ABE_PDM_CONTEXT_OFFSET			0x0034
-#define OMAP4430_RM_ABE_PDM_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_ABE_MOD, 0x0034)
+#define OMAP4430_RM_ABE_PDM_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_ABE_INST, 0x0034)
 #define OMAP4_PM_ABE_DMIC_WKDEP_OFFSET			0x0038
-#define OMAP4430_PM_ABE_DMIC_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_ABE_MOD, 0x0038)
+#define OMAP4430_PM_ABE_DMIC_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_ABE_INST, 0x0038)
 #define OMAP4_RM_ABE_DMIC_CONTEXT_OFFSET		0x003c
-#define OMAP4430_RM_ABE_DMIC_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_ABE_MOD, 0x003c)
+#define OMAP4430_RM_ABE_DMIC_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_ABE_INST, 0x003c)
 #define OMAP4_PM_ABE_MCASP_WKDEP_OFFSET			0x0040
-#define OMAP4430_PM_ABE_MCASP_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_ABE_MOD, 0x0040)
+#define OMAP4430_PM_ABE_MCASP_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_ABE_INST, 0x0040)
 #define OMAP4_RM_ABE_MCASP_CONTEXT_OFFSET		0x0044
-#define OMAP4430_RM_ABE_MCASP_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_ABE_MOD, 0x0044)
+#define OMAP4430_RM_ABE_MCASP_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_ABE_INST, 0x0044)
 #define OMAP4_PM_ABE_MCBSP1_WKDEP_OFFSET		0x0048
-#define OMAP4430_PM_ABE_MCBSP1_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_ABE_MOD, 0x0048)
+#define OMAP4430_PM_ABE_MCBSP1_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_ABE_INST, 0x0048)
 #define OMAP4_RM_ABE_MCBSP1_CONTEXT_OFFSET		0x004c
-#define OMAP4430_RM_ABE_MCBSP1_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_ABE_MOD, 0x004c)
+#define OMAP4430_RM_ABE_MCBSP1_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_ABE_INST, 0x004c)
 #define OMAP4_PM_ABE_MCBSP2_WKDEP_OFFSET		0x0050
-#define OMAP4430_PM_ABE_MCBSP2_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_ABE_MOD, 0x0050)
+#define OMAP4430_PM_ABE_MCBSP2_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_ABE_INST, 0x0050)
 #define OMAP4_RM_ABE_MCBSP2_CONTEXT_OFFSET		0x0054
-#define OMAP4430_RM_ABE_MCBSP2_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_ABE_MOD, 0x0054)
+#define OMAP4430_RM_ABE_MCBSP2_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_ABE_INST, 0x0054)
 #define OMAP4_PM_ABE_MCBSP3_WKDEP_OFFSET		0x0058
-#define OMAP4430_PM_ABE_MCBSP3_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_ABE_MOD, 0x0058)
+#define OMAP4430_PM_ABE_MCBSP3_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_ABE_INST, 0x0058)
 #define OMAP4_RM_ABE_MCBSP3_CONTEXT_OFFSET		0x005c
-#define OMAP4430_RM_ABE_MCBSP3_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_ABE_MOD, 0x005c)
+#define OMAP4430_RM_ABE_MCBSP3_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_ABE_INST, 0x005c)
 #define OMAP4_PM_ABE_SLIMBUS_WKDEP_OFFSET		0x0060
-#define OMAP4430_PM_ABE_SLIMBUS_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_ABE_MOD, 0x0060)
+#define OMAP4430_PM_ABE_SLIMBUS_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_ABE_INST, 0x0060)
 #define OMAP4_RM_ABE_SLIMBUS_CONTEXT_OFFSET		0x0064
-#define OMAP4430_RM_ABE_SLIMBUS_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_ABE_MOD, 0x0064)
+#define OMAP4430_RM_ABE_SLIMBUS_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_ABE_INST, 0x0064)
 #define OMAP4_PM_ABE_TIMER5_WKDEP_OFFSET		0x0068
-#define OMAP4430_PM_ABE_TIMER5_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_ABE_MOD, 0x0068)
+#define OMAP4430_PM_ABE_TIMER5_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_ABE_INST, 0x0068)
 #define OMAP4_RM_ABE_TIMER5_CONTEXT_OFFSET		0x006c
-#define OMAP4430_RM_ABE_TIMER5_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_ABE_MOD, 0x006c)
+#define OMAP4430_RM_ABE_TIMER5_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_ABE_INST, 0x006c)
 #define OMAP4_PM_ABE_TIMER6_WKDEP_OFFSET		0x0070
-#define OMAP4430_PM_ABE_TIMER6_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_ABE_MOD, 0x0070)
+#define OMAP4430_PM_ABE_TIMER6_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_ABE_INST, 0x0070)
 #define OMAP4_RM_ABE_TIMER6_CONTEXT_OFFSET		0x0074
-#define OMAP4430_RM_ABE_TIMER6_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_ABE_MOD, 0x0074)
+#define OMAP4430_RM_ABE_TIMER6_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_ABE_INST, 0x0074)
 #define OMAP4_PM_ABE_TIMER7_WKDEP_OFFSET		0x0078
-#define OMAP4430_PM_ABE_TIMER7_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_ABE_MOD, 0x0078)
+#define OMAP4430_PM_ABE_TIMER7_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_ABE_INST, 0x0078)
 #define OMAP4_RM_ABE_TIMER7_CONTEXT_OFFSET		0x007c
-#define OMAP4430_RM_ABE_TIMER7_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_ABE_MOD, 0x007c)
+#define OMAP4430_RM_ABE_TIMER7_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_ABE_INST, 0x007c)
 #define OMAP4_PM_ABE_TIMER8_WKDEP_OFFSET		0x0080
-#define OMAP4430_PM_ABE_TIMER8_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_ABE_MOD, 0x0080)
+#define OMAP4430_PM_ABE_TIMER8_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_ABE_INST, 0x0080)
 #define OMAP4_RM_ABE_TIMER8_CONTEXT_OFFSET		0x0084
-#define OMAP4430_RM_ABE_TIMER8_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_ABE_MOD, 0x0084)
+#define OMAP4430_RM_ABE_TIMER8_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_ABE_INST, 0x0084)
 #define OMAP4_PM_ABE_WDT3_WKDEP_OFFSET			0x0088
-#define OMAP4430_PM_ABE_WDT3_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_ABE_MOD, 0x0088)
+#define OMAP4430_PM_ABE_WDT3_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_ABE_INST, 0x0088)
 #define OMAP4_RM_ABE_WDT3_CONTEXT_OFFSET		0x008c
-#define OMAP4430_RM_ABE_WDT3_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_ABE_MOD, 0x008c)
+#define OMAP4430_RM_ABE_WDT3_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_ABE_INST, 0x008c)
 
 /* PRM.ALWAYS_ON_PRM register offsets */
 #define OMAP4_RM_ALWON_MDMINTC_CONTEXT_OFFSET		0x0024
-#define OMAP4430_RM_ALWON_MDMINTC_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_ALWAYS_ON_MOD, 0x0024)
+#define OMAP4430_RM_ALWON_MDMINTC_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_ALWAYS_ON_INST, 0x0024)
 #define OMAP4_PM_ALWON_SR_MPU_WKDEP_OFFSET		0x0028
-#define OMAP4430_PM_ALWON_SR_MPU_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_ALWAYS_ON_MOD, 0x0028)
+#define OMAP4430_PM_ALWON_SR_MPU_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_ALWAYS_ON_INST, 0x0028)
 #define OMAP4_RM_ALWON_SR_MPU_CONTEXT_OFFSET		0x002c
-#define OMAP4430_RM_ALWON_SR_MPU_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_ALWAYS_ON_MOD, 0x002c)
+#define OMAP4430_RM_ALWON_SR_MPU_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_ALWAYS_ON_INST, 0x002c)
 #define OMAP4_PM_ALWON_SR_IVA_WKDEP_OFFSET		0x0030
-#define OMAP4430_PM_ALWON_SR_IVA_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_ALWAYS_ON_MOD, 0x0030)
+#define OMAP4430_PM_ALWON_SR_IVA_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_ALWAYS_ON_INST, 0x0030)
 #define OMAP4_RM_ALWON_SR_IVA_CONTEXT_OFFSET		0x0034
-#define OMAP4430_RM_ALWON_SR_IVA_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_ALWAYS_ON_MOD, 0x0034)
+#define OMAP4430_RM_ALWON_SR_IVA_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_ALWAYS_ON_INST, 0x0034)
 #define OMAP4_PM_ALWON_SR_CORE_WKDEP_OFFSET		0x0038
-#define OMAP4430_PM_ALWON_SR_CORE_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_ALWAYS_ON_MOD, 0x0038)
+#define OMAP4430_PM_ALWON_SR_CORE_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_ALWAYS_ON_INST, 0x0038)
 #define OMAP4_RM_ALWON_SR_CORE_CONTEXT_OFFSET		0x003c
-#define OMAP4430_RM_ALWON_SR_CORE_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_ALWAYS_ON_MOD, 0x003c)
+#define OMAP4430_RM_ALWON_SR_CORE_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_ALWAYS_ON_INST, 0x003c)
 
 /* PRM.CORE_PRM register offsets */
 #define OMAP4_PM_CORE_PWRSTCTRL_OFFSET			0x0000
-#define OMAP4430_PM_CORE_PWRSTCTRL			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CORE_MOD, 0x0000)
+#define OMAP4430_PM_CORE_PWRSTCTRL			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CORE_INST, 0x0000)
 #define OMAP4_PM_CORE_PWRSTST_OFFSET			0x0004
-#define OMAP4430_PM_CORE_PWRSTST			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CORE_MOD, 0x0004)
+#define OMAP4430_PM_CORE_PWRSTST			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CORE_INST, 0x0004)
 #define OMAP4_RM_L3_1_L3_1_CONTEXT_OFFSET		0x0024
-#define OMAP4430_RM_L3_1_L3_1_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CORE_MOD, 0x0024)
+#define OMAP4430_RM_L3_1_L3_1_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CORE_INST, 0x0024)
 #define OMAP4_RM_L3_2_L3_2_CONTEXT_OFFSET		0x0124
-#define OMAP4430_RM_L3_2_L3_2_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CORE_MOD, 0x0124)
+#define OMAP4430_RM_L3_2_L3_2_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CORE_INST, 0x0124)
 #define OMAP4_RM_L3_2_GPMC_CONTEXT_OFFSET		0x012c
-#define OMAP4430_RM_L3_2_GPMC_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CORE_MOD, 0x012c)
+#define OMAP4430_RM_L3_2_GPMC_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CORE_INST, 0x012c)
 #define OMAP4_RM_L3_2_OCMC_RAM_CONTEXT_OFFSET		0x0134
-#define OMAP4430_RM_L3_2_OCMC_RAM_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CORE_MOD, 0x0134)
+#define OMAP4430_RM_L3_2_OCMC_RAM_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CORE_INST, 0x0134)
 #define OMAP4_RM_DUCATI_RSTCTRL_OFFSET			0x0210
-#define OMAP4430_RM_DUCATI_RSTCTRL			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CORE_MOD, 0x0210)
+#define OMAP4430_RM_DUCATI_RSTCTRL			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CORE_INST, 0x0210)
 #define OMAP4_RM_DUCATI_RSTST_OFFSET			0x0214
-#define OMAP4430_RM_DUCATI_RSTST			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CORE_MOD, 0x0214)
+#define OMAP4430_RM_DUCATI_RSTST			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CORE_INST, 0x0214)
 #define OMAP4_RM_DUCATI_DUCATI_CONTEXT_OFFSET		0x0224
-#define OMAP4430_RM_DUCATI_DUCATI_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CORE_MOD, 0x0224)
+#define OMAP4430_RM_DUCATI_DUCATI_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CORE_INST, 0x0224)
 #define OMAP4_RM_SDMA_SDMA_CONTEXT_OFFSET		0x0324
-#define OMAP4430_RM_SDMA_SDMA_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CORE_MOD, 0x0324)
+#define OMAP4430_RM_SDMA_SDMA_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CORE_INST, 0x0324)
 #define OMAP4_RM_MEMIF_DMM_CONTEXT_OFFSET		0x0424
-#define OMAP4430_RM_MEMIF_DMM_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CORE_MOD, 0x0424)
+#define OMAP4430_RM_MEMIF_DMM_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CORE_INST, 0x0424)
 #define OMAP4_RM_MEMIF_EMIF_FW_CONTEXT_OFFSET		0x042c
-#define OMAP4430_RM_MEMIF_EMIF_FW_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CORE_MOD, 0x042c)
+#define OMAP4430_RM_MEMIF_EMIF_FW_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CORE_INST, 0x042c)
 #define OMAP4_RM_MEMIF_EMIF_1_CONTEXT_OFFSET		0x0434
-#define OMAP4430_RM_MEMIF_EMIF_1_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CORE_MOD, 0x0434)
+#define OMAP4430_RM_MEMIF_EMIF_1_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CORE_INST, 0x0434)
 #define OMAP4_RM_MEMIF_EMIF_2_CONTEXT_OFFSET		0x043c
-#define OMAP4430_RM_MEMIF_EMIF_2_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CORE_MOD, 0x043c)
+#define OMAP4430_RM_MEMIF_EMIF_2_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CORE_INST, 0x043c)
 #define OMAP4_RM_MEMIF_DLL_CONTEXT_OFFSET		0x0444
-#define OMAP4430_RM_MEMIF_DLL_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CORE_MOD, 0x0444)
+#define OMAP4430_RM_MEMIF_DLL_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CORE_INST, 0x0444)
 #define OMAP4_RM_MEMIF_EMIF_H1_CONTEXT_OFFSET		0x0454
-#define OMAP4430_RM_MEMIF_EMIF_H1_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CORE_MOD, 0x0454)
+#define OMAP4430_RM_MEMIF_EMIF_H1_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CORE_INST, 0x0454)
 #define OMAP4_RM_MEMIF_EMIF_H2_CONTEXT_OFFSET		0x045c
-#define OMAP4430_RM_MEMIF_EMIF_H2_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CORE_MOD, 0x045c)
+#define OMAP4430_RM_MEMIF_EMIF_H2_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CORE_INST, 0x045c)
 #define OMAP4_RM_MEMIF_DLL_H_CONTEXT_OFFSET		0x0464
-#define OMAP4430_RM_MEMIF_DLL_H_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CORE_MOD, 0x0464)
+#define OMAP4430_RM_MEMIF_DLL_H_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CORE_INST, 0x0464)
 #define OMAP4_RM_D2D_SAD2D_CONTEXT_OFFSET		0x0524
-#define OMAP4430_RM_D2D_SAD2D_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CORE_MOD, 0x0524)
-#define OMAP4_RM_D2D_MODEM_ICR_CONTEXT_OFFSET		0x052c
-#define OMAP4430_RM_D2D_MODEM_ICR_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CORE_MOD, 0x052c)
+#define OMAP4430_RM_D2D_SAD2D_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CORE_INST, 0x0524)
+#define OMAP4_RM_D2D_INSTEM_ICR_CONTEXT_OFFSET		0x052c
+#define OMAP4430_RM_D2D_INSTEM_ICR_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CORE_INST, 0x052c)
 #define OMAP4_RM_D2D_SAD2D_FW_CONTEXT_OFFSET		0x0534
-#define OMAP4430_RM_D2D_SAD2D_FW_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CORE_MOD, 0x0534)
+#define OMAP4430_RM_D2D_SAD2D_FW_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CORE_INST, 0x0534)
 #define OMAP4_RM_L4CFG_L4_CFG_CONTEXT_OFFSET		0x0624
-#define OMAP4430_RM_L4CFG_L4_CFG_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CORE_MOD, 0x0624)
+#define OMAP4430_RM_L4CFG_L4_CFG_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CORE_INST, 0x0624)
 #define OMAP4_RM_L4CFG_HW_SEM_CONTEXT_OFFSET		0x062c
-#define OMAP4430_RM_L4CFG_HW_SEM_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CORE_MOD, 0x062c)
+#define OMAP4430_RM_L4CFG_HW_SEM_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CORE_INST, 0x062c)
 #define OMAP4_RM_L4CFG_MAILBOX_CONTEXT_OFFSET		0x0634
-#define OMAP4430_RM_L4CFG_MAILBOX_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CORE_MOD, 0x0634)
+#define OMAP4430_RM_L4CFG_MAILBOX_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CORE_INST, 0x0634)
 #define OMAP4_RM_L4CFG_SAR_ROM_CONTEXT_OFFSET		0x063c
-#define OMAP4430_RM_L4CFG_SAR_ROM_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CORE_MOD, 0x063c)
+#define OMAP4430_RM_L4CFG_SAR_ROM_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CORE_INST, 0x063c)
 #define OMAP4_RM_L3INSTR_L3_3_CONTEXT_OFFSET		0x0724
-#define OMAP4430_RM_L3INSTR_L3_3_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CORE_MOD, 0x0724)
+#define OMAP4430_RM_L3INSTR_L3_3_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CORE_INST, 0x0724)
 #define OMAP4_RM_L3INSTR_L3_INSTR_CONTEXT_OFFSET	0x072c
-#define OMAP4430_RM_L3INSTR_L3_INSTR_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CORE_MOD, 0x072c)
+#define OMAP4430_RM_L3INSTR_L3_INSTR_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CORE_INST, 0x072c)
 #define OMAP4_RM_L3INSTR_OCP_WP1_CONTEXT_OFFSET		0x0744
-#define OMAP4430_RM_L3INSTR_OCP_WP1_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CORE_MOD, 0x0744)
+#define OMAP4430_RM_L3INSTR_OCP_WP1_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CORE_INST, 0x0744)
 
 /* PRM.IVAHD_PRM register offsets */
 #define OMAP4_PM_IVAHD_PWRSTCTRL_OFFSET			0x0000
-#define OMAP4430_PM_IVAHD_PWRSTCTRL			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_IVAHD_MOD, 0x0000)
+#define OMAP4430_PM_IVAHD_PWRSTCTRL			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_IVAHD_INST, 0x0000)
 #define OMAP4_PM_IVAHD_PWRSTST_OFFSET			0x0004
-#define OMAP4430_PM_IVAHD_PWRSTST			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_IVAHD_MOD, 0x0004)
+#define OMAP4430_PM_IVAHD_PWRSTST			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_IVAHD_INST, 0x0004)
 #define OMAP4_RM_IVAHD_RSTCTRL_OFFSET			0x0010
-#define OMAP4430_RM_IVAHD_RSTCTRL			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_IVAHD_MOD, 0x0010)
+#define OMAP4430_RM_IVAHD_RSTCTRL			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_IVAHD_INST, 0x0010)
 #define OMAP4_RM_IVAHD_RSTST_OFFSET			0x0014
-#define OMAP4430_RM_IVAHD_RSTST				OMAP44XX_PRM_REGADDR(OMAP4430_PRM_IVAHD_MOD, 0x0014)
+#define OMAP4430_RM_IVAHD_RSTST				OMAP44XX_PRM_REGADDR(OMAP4430_PRM_IVAHD_INST, 0x0014)
 #define OMAP4_RM_IVAHD_IVAHD_CONTEXT_OFFSET		0x0024
-#define OMAP4430_RM_IVAHD_IVAHD_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_IVAHD_MOD, 0x0024)
+#define OMAP4430_RM_IVAHD_IVAHD_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_IVAHD_INST, 0x0024)
 #define OMAP4_RM_IVAHD_SL2_CONTEXT_OFFSET		0x002c
-#define OMAP4430_RM_IVAHD_SL2_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_IVAHD_MOD, 0x002c)
+#define OMAP4430_RM_IVAHD_SL2_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_IVAHD_INST, 0x002c)
 
 /* PRM.CAM_PRM register offsets */
 #define OMAP4_PM_CAM_PWRSTCTRL_OFFSET			0x0000
-#define OMAP4430_PM_CAM_PWRSTCTRL			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CAM_MOD, 0x0000)
+#define OMAP4430_PM_CAM_PWRSTCTRL			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CAM_INST, 0x0000)
 #define OMAP4_PM_CAM_PWRSTST_OFFSET			0x0004
-#define OMAP4430_PM_CAM_PWRSTST				OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CAM_MOD, 0x0004)
+#define OMAP4430_PM_CAM_PWRSTST				OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CAM_INST, 0x0004)
 #define OMAP4_RM_CAM_ISS_CONTEXT_OFFSET			0x0024
-#define OMAP4430_RM_CAM_ISS_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CAM_MOD, 0x0024)
+#define OMAP4430_RM_CAM_ISS_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CAM_INST, 0x0024)
 #define OMAP4_RM_CAM_FDIF_CONTEXT_OFFSET		0x002c
-#define OMAP4430_RM_CAM_FDIF_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CAM_MOD, 0x002c)
+#define OMAP4430_RM_CAM_FDIF_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CAM_INST, 0x002c)
 
 /* PRM.DSS_PRM register offsets */
 #define OMAP4_PM_DSS_PWRSTCTRL_OFFSET			0x0000
-#define OMAP4430_PM_DSS_PWRSTCTRL			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DSS_MOD, 0x0000)
+#define OMAP4430_PM_DSS_PWRSTCTRL			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DSS_INST, 0x0000)
 #define OMAP4_PM_DSS_PWRSTST_OFFSET			0x0004
-#define OMAP4430_PM_DSS_PWRSTST				OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DSS_MOD, 0x0004)
+#define OMAP4430_PM_DSS_PWRSTST				OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DSS_INST, 0x0004)
 #define OMAP4_PM_DSS_DSS_WKDEP_OFFSET			0x0020
-#define OMAP4430_PM_DSS_DSS_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DSS_MOD, 0x0020)
+#define OMAP4430_PM_DSS_DSS_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DSS_INST, 0x0020)
 #define OMAP4_RM_DSS_DSS_CONTEXT_OFFSET			0x0024
-#define OMAP4430_RM_DSS_DSS_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DSS_MOD, 0x0024)
+#define OMAP4430_RM_DSS_DSS_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DSS_INST, 0x0024)
 #define OMAP4_RM_DSS_DEISS_CONTEXT_OFFSET		0x002c
-#define OMAP4430_RM_DSS_DEISS_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DSS_MOD, 0x002c)
+#define OMAP4430_RM_DSS_DEISS_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DSS_INST, 0x002c)
 
 /* PRM.GFX_PRM register offsets */
 #define OMAP4_PM_GFX_PWRSTCTRL_OFFSET			0x0000
-#define OMAP4430_PM_GFX_PWRSTCTRL			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_GFX_MOD, 0x0000)
+#define OMAP4430_PM_GFX_PWRSTCTRL			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_GFX_INST, 0x0000)
 #define OMAP4_PM_GFX_PWRSTST_OFFSET			0x0004
-#define OMAP4430_PM_GFX_PWRSTST				OMAP44XX_PRM_REGADDR(OMAP4430_PRM_GFX_MOD, 0x0004)
+#define OMAP4430_PM_GFX_PWRSTST				OMAP44XX_PRM_REGADDR(OMAP4430_PRM_GFX_INST, 0x0004)
 #define OMAP4_RM_GFX_GFX_CONTEXT_OFFSET			0x0024
-#define OMAP4430_RM_GFX_GFX_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_GFX_MOD, 0x0024)
+#define OMAP4430_RM_GFX_GFX_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_GFX_INST, 0x0024)
 
 /* PRM.L3INIT_PRM register offsets */
 #define OMAP4_PM_L3INIT_PWRSTCTRL_OFFSET		0x0000
-#define OMAP4430_PM_L3INIT_PWRSTCTRL			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L3INIT_MOD, 0x0000)
+#define OMAP4430_PM_L3INIT_PWRSTCTRL			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L3INIT_INST, 0x0000)
 #define OMAP4_PM_L3INIT_PWRSTST_OFFSET			0x0004
-#define OMAP4430_PM_L3INIT_PWRSTST			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L3INIT_MOD, 0x0004)
+#define OMAP4430_PM_L3INIT_PWRSTST			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L3INIT_INST, 0x0004)
 #define OMAP4_PM_L3INIT_MMC1_WKDEP_OFFSET		0x0028
-#define OMAP4430_PM_L3INIT_MMC1_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L3INIT_MOD, 0x0028)
+#define OMAP4430_PM_L3INIT_MMC1_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L3INIT_INST, 0x0028)
 #define OMAP4_RM_L3INIT_MMC1_CONTEXT_OFFSET		0x002c
-#define OMAP4430_RM_L3INIT_MMC1_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L3INIT_MOD, 0x002c)
+#define OMAP4430_RM_L3INIT_MMC1_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L3INIT_INST, 0x002c)
 #define OMAP4_PM_L3INIT_MMC2_WKDEP_OFFSET		0x0030
-#define OMAP4430_PM_L3INIT_MMC2_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L3INIT_MOD, 0x0030)
+#define OMAP4430_PM_L3INIT_MMC2_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L3INIT_INST, 0x0030)
 #define OMAP4_RM_L3INIT_MMC2_CONTEXT_OFFSET		0x0034
-#define OMAP4430_RM_L3INIT_MMC2_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L3INIT_MOD, 0x0034)
+#define OMAP4430_RM_L3INIT_MMC2_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L3INIT_INST, 0x0034)
 #define OMAP4_PM_L3INIT_HSI_WKDEP_OFFSET		0x0038
-#define OMAP4430_PM_L3INIT_HSI_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L3INIT_MOD, 0x0038)
+#define OMAP4430_PM_L3INIT_HSI_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L3INIT_INST, 0x0038)
 #define OMAP4_RM_L3INIT_HSI_CONTEXT_OFFSET		0x003c
-#define OMAP4430_RM_L3INIT_HSI_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L3INIT_MOD, 0x003c)
+#define OMAP4430_RM_L3INIT_HSI_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L3INIT_INST, 0x003c)
 #define OMAP4_PM_L3INIT_UNIPRO1_WKDEP_OFFSET		0x0040
-#define OMAP4430_PM_L3INIT_UNIPRO1_WKDEP		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L3INIT_MOD, 0x0040)
+#define OMAP4430_PM_L3INIT_UNIPRO1_WKDEP		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L3INIT_INST, 0x0040)
 #define OMAP4_RM_L3INIT_UNIPRO1_CONTEXT_OFFSET		0x0044
-#define OMAP4430_RM_L3INIT_UNIPRO1_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L3INIT_MOD, 0x0044)
+#define OMAP4430_RM_L3INIT_UNIPRO1_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L3INIT_INST, 0x0044)
 #define OMAP4_PM_L3INIT_USB_HOST_WKDEP_OFFSET		0x0058
-#define OMAP4430_PM_L3INIT_USB_HOST_WKDEP		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L3INIT_MOD, 0x0058)
+#define OMAP4430_PM_L3INIT_USB_HOST_WKDEP		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L3INIT_INST, 0x0058)
 #define OMAP4_RM_L3INIT_USB_HOST_CONTEXT_OFFSET		0x005c
-#define OMAP4430_RM_L3INIT_USB_HOST_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L3INIT_MOD, 0x005c)
+#define OMAP4430_RM_L3INIT_USB_HOST_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L3INIT_INST, 0x005c)
 #define OMAP4_PM_L3INIT_USB_OTG_WKDEP_OFFSET		0x0060
-#define OMAP4430_PM_L3INIT_USB_OTG_WKDEP		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L3INIT_MOD, 0x0060)
+#define OMAP4430_PM_L3INIT_USB_OTG_WKDEP		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L3INIT_INST, 0x0060)
 #define OMAP4_RM_L3INIT_USB_OTG_CONTEXT_OFFSET		0x0064
-#define OMAP4430_RM_L3INIT_USB_OTG_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L3INIT_MOD, 0x0064)
+#define OMAP4430_RM_L3INIT_USB_OTG_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L3INIT_INST, 0x0064)
 #define OMAP4_PM_L3INIT_USB_TLL_WKDEP_OFFSET		0x0068
-#define OMAP4430_PM_L3INIT_USB_TLL_WKDEP		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L3INIT_MOD, 0x0068)
+#define OMAP4430_PM_L3INIT_USB_TLL_WKDEP		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L3INIT_INST, 0x0068)
 #define OMAP4_RM_L3INIT_USB_TLL_CONTEXT_OFFSET		0x006c
-#define OMAP4430_RM_L3INIT_USB_TLL_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L3INIT_MOD, 0x006c)
+#define OMAP4430_RM_L3INIT_USB_TLL_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L3INIT_INST, 0x006c)
 #define OMAP4_RM_L3INIT_P1500_CONTEXT_OFFSET		0x007c
-#define OMAP4430_RM_L3INIT_P1500_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L3INIT_MOD, 0x007c)
+#define OMAP4430_RM_L3INIT_P1500_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L3INIT_INST, 0x007c)
 #define OMAP4_RM_L3INIT_EMAC_CONTEXT_OFFSET		0x0084
-#define OMAP4430_RM_L3INIT_EMAC_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L3INIT_MOD, 0x0084)
+#define OMAP4430_RM_L3INIT_EMAC_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L3INIT_INST, 0x0084)
 #define OMAP4_PM_L3INIT_SATA_WKDEP_OFFSET		0x0088
-#define OMAP4430_PM_L3INIT_SATA_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L3INIT_MOD, 0x0088)
+#define OMAP4430_PM_L3INIT_SATA_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L3INIT_INST, 0x0088)
 #define OMAP4_RM_L3INIT_SATA_CONTEXT_OFFSET		0x008c
-#define OMAP4430_RM_L3INIT_SATA_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L3INIT_MOD, 0x008c)
+#define OMAP4430_RM_L3INIT_SATA_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L3INIT_INST, 0x008c)
 #define OMAP4_RM_L3INIT_TPPSS_CONTEXT_OFFSET		0x0094
-#define OMAP4430_RM_L3INIT_TPPSS_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L3INIT_MOD, 0x0094)
+#define OMAP4430_RM_L3INIT_TPPSS_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L3INIT_INST, 0x0094)
 #define OMAP4_PM_L3INIT_PCIESS_WKDEP_OFFSET		0x0098
-#define OMAP4430_PM_L3INIT_PCIESS_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L3INIT_MOD, 0x0098)
+#define OMAP4430_PM_L3INIT_PCIESS_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L3INIT_INST, 0x0098)
 #define OMAP4_RM_L3INIT_PCIESS_CONTEXT_OFFSET		0x009c
-#define OMAP4430_RM_L3INIT_PCIESS_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L3INIT_MOD, 0x009c)
+#define OMAP4430_RM_L3INIT_PCIESS_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L3INIT_INST, 0x009c)
 #define OMAP4_RM_L3INIT_CCPTX_CONTEXT_OFFSET		0x00ac
-#define OMAP4430_RM_L3INIT_CCPTX_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L3INIT_MOD, 0x00ac)
+#define OMAP4430_RM_L3INIT_CCPTX_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L3INIT_INST, 0x00ac)
 #define OMAP4_PM_L3INIT_XHPI_WKDEP_OFFSET		0x00c0
-#define OMAP4430_PM_L3INIT_XHPI_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L3INIT_MOD, 0x00c0)
+#define OMAP4430_PM_L3INIT_XHPI_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L3INIT_INST, 0x00c0)
 #define OMAP4_RM_L3INIT_XHPI_CONTEXT_OFFSET		0x00c4
-#define OMAP4430_RM_L3INIT_XHPI_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L3INIT_MOD, 0x00c4)
+#define OMAP4430_RM_L3INIT_XHPI_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L3INIT_INST, 0x00c4)
 #define OMAP4_PM_L3INIT_MMC6_WKDEP_OFFSET		0x00c8
-#define OMAP4430_PM_L3INIT_MMC6_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L3INIT_MOD, 0x00c8)
+#define OMAP4430_PM_L3INIT_MMC6_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L3INIT_INST, 0x00c8)
 #define OMAP4_RM_L3INIT_MMC6_CONTEXT_OFFSET		0x00cc
-#define OMAP4430_RM_L3INIT_MMC6_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L3INIT_MOD, 0x00cc)
+#define OMAP4430_RM_L3INIT_MMC6_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L3INIT_INST, 0x00cc)
 #define OMAP4_PM_L3INIT_USB_HOST_FS_WKDEP_OFFSET	0x00d0
-#define OMAP4430_PM_L3INIT_USB_HOST_FS_WKDEP		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L3INIT_MOD, 0x00d0)
+#define OMAP4430_PM_L3INIT_USB_HOST_FS_WKDEP		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L3INIT_INST, 0x00d0)
 #define OMAP4_RM_L3INIT_USB_HOST_FS_CONTEXT_OFFSET	0x00d4
-#define OMAP4430_RM_L3INIT_USB_HOST_FS_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L3INIT_MOD, 0x00d4)
+#define OMAP4430_RM_L3INIT_USB_HOST_FS_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L3INIT_INST, 0x00d4)
 #define OMAP4_RM_L3INIT_USBPHYOCP2SCP_CONTEXT_OFFSET	0x00e4
-#define OMAP4430_RM_L3INIT_USBPHYOCP2SCP_CONTEXT	OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L3INIT_MOD, 0x00e4)
+#define OMAP4430_RM_L3INIT_USBPHYOCP2SCP_CONTEXT	OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L3INIT_INST, 0x00e4)
 
 /* PRM.L4PER_PRM register offsets */
 #define OMAP4_PM_L4PER_PWRSTCTRL_OFFSET			0x0000
-#define OMAP4430_PM_L4PER_PWRSTCTRL			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x0000)
+#define OMAP4430_PM_L4PER_PWRSTCTRL			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_INST, 0x0000)
 #define OMAP4_PM_L4PER_PWRSTST_OFFSET			0x0004
-#define OMAP4430_PM_L4PER_PWRSTST			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x0004)
+#define OMAP4430_PM_L4PER_PWRSTST			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_INST, 0x0004)
 #define OMAP4_RM_L4PER_ADC_CONTEXT_OFFSET		0x0024
-#define OMAP4430_RM_L4PER_ADC_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x0024)
+#define OMAP4430_RM_L4PER_ADC_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_INST, 0x0024)
 #define OMAP4_PM_L4PER_DMTIMER10_WKDEP_OFFSET		0x0028
-#define OMAP4430_PM_L4PER_DMTIMER10_WKDEP		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x0028)
+#define OMAP4430_PM_L4PER_DMTIMER10_WKDEP		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_INST, 0x0028)
 #define OMAP4_RM_L4PER_DMTIMER10_CONTEXT_OFFSET		0x002c
-#define OMAP4430_RM_L4PER_DMTIMER10_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x002c)
+#define OMAP4430_RM_L4PER_DMTIMER10_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_INST, 0x002c)
 #define OMAP4_PM_L4PER_DMTIMER11_WKDEP_OFFSET		0x0030
-#define OMAP4430_PM_L4PER_DMTIMER11_WKDEP		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x0030)
+#define OMAP4430_PM_L4PER_DMTIMER11_WKDEP		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_INST, 0x0030)
 #define OMAP4_RM_L4PER_DMTIMER11_CONTEXT_OFFSET		0x0034
-#define OMAP4430_RM_L4PER_DMTIMER11_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x0034)
+#define OMAP4430_RM_L4PER_DMTIMER11_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_INST, 0x0034)
 #define OMAP4_PM_L4PER_DMTIMER2_WKDEP_OFFSET		0x0038
-#define OMAP4430_PM_L4PER_DMTIMER2_WKDEP		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x0038)
+#define OMAP4430_PM_L4PER_DMTIMER2_WKDEP		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_INST, 0x0038)
 #define OMAP4_RM_L4PER_DMTIMER2_CONTEXT_OFFSET		0x003c
-#define OMAP4430_RM_L4PER_DMTIMER2_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x003c)
+#define OMAP4430_RM_L4PER_DMTIMER2_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_INST, 0x003c)
 #define OMAP4_PM_L4PER_DMTIMER3_WKDEP_OFFSET		0x0040
-#define OMAP4430_PM_L4PER_DMTIMER3_WKDEP		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x0040)
+#define OMAP4430_PM_L4PER_DMTIMER3_WKDEP		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_INST, 0x0040)
 #define OMAP4_RM_L4PER_DMTIMER3_CONTEXT_OFFSET		0x0044
-#define OMAP4430_RM_L4PER_DMTIMER3_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x0044)
+#define OMAP4430_RM_L4PER_DMTIMER3_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_INST, 0x0044)
 #define OMAP4_PM_L4PER_DMTIMER4_WKDEP_OFFSET		0x0048
-#define OMAP4430_PM_L4PER_DMTIMER4_WKDEP		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x0048)
+#define OMAP4430_PM_L4PER_DMTIMER4_WKDEP		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_INST, 0x0048)
 #define OMAP4_RM_L4PER_DMTIMER4_CONTEXT_OFFSET		0x004c
-#define OMAP4430_RM_L4PER_DMTIMER4_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x004c)
+#define OMAP4430_RM_L4PER_DMTIMER4_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_INST, 0x004c)
 #define OMAP4_PM_L4PER_DMTIMER9_WKDEP_OFFSET		0x0050
-#define OMAP4430_PM_L4PER_DMTIMER9_WKDEP		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x0050)
+#define OMAP4430_PM_L4PER_DMTIMER9_WKDEP		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_INST, 0x0050)
 #define OMAP4_RM_L4PER_DMTIMER9_CONTEXT_OFFSET		0x0054
-#define OMAP4430_RM_L4PER_DMTIMER9_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x0054)
+#define OMAP4430_RM_L4PER_DMTIMER9_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_INST, 0x0054)
 #define OMAP4_RM_L4PER_ELM_CONTEXT_OFFSET		0x005c
-#define OMAP4430_RM_L4PER_ELM_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x005c)
+#define OMAP4430_RM_L4PER_ELM_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_INST, 0x005c)
 #define OMAP4_PM_L4PER_GPIO2_WKDEP_OFFSET		0x0060
-#define OMAP4430_PM_L4PER_GPIO2_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x0060)
+#define OMAP4430_PM_L4PER_GPIO2_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_INST, 0x0060)
 #define OMAP4_RM_L4PER_GPIO2_CONTEXT_OFFSET		0x0064
-#define OMAP4430_RM_L4PER_GPIO2_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x0064)
+#define OMAP4430_RM_L4PER_GPIO2_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_INST, 0x0064)
 #define OMAP4_PM_L4PER_GPIO3_WKDEP_OFFSET		0x0068
-#define OMAP4430_PM_L4PER_GPIO3_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x0068)
+#define OMAP4430_PM_L4PER_GPIO3_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_INST, 0x0068)
 #define OMAP4_RM_L4PER_GPIO3_CONTEXT_OFFSET		0x006c
-#define OMAP4430_RM_L4PER_GPIO3_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x006c)
+#define OMAP4430_RM_L4PER_GPIO3_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_INST, 0x006c)
 #define OMAP4_PM_L4PER_GPIO4_WKDEP_OFFSET		0x0070
-#define OMAP4430_PM_L4PER_GPIO4_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x0070)
+#define OMAP4430_PM_L4PER_GPIO4_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_INST, 0x0070)
 #define OMAP4_RM_L4PER_GPIO4_CONTEXT_OFFSET		0x0074
-#define OMAP4430_RM_L4PER_GPIO4_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x0074)
+#define OMAP4430_RM_L4PER_GPIO4_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_INST, 0x0074)
 #define OMAP4_PM_L4PER_GPIO5_WKDEP_OFFSET		0x0078
-#define OMAP4430_PM_L4PER_GPIO5_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x0078)
+#define OMAP4430_PM_L4PER_GPIO5_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_INST, 0x0078)
 #define OMAP4_RM_L4PER_GPIO5_CONTEXT_OFFSET		0x007c
-#define OMAP4430_RM_L4PER_GPIO5_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x007c)
+#define OMAP4430_RM_L4PER_GPIO5_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_INST, 0x007c)
 #define OMAP4_PM_L4PER_GPIO6_WKDEP_OFFSET		0x0080
-#define OMAP4430_PM_L4PER_GPIO6_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x0080)
+#define OMAP4430_PM_L4PER_GPIO6_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_INST, 0x0080)
 #define OMAP4_RM_L4PER_GPIO6_CONTEXT_OFFSET		0x0084
-#define OMAP4430_RM_L4PER_GPIO6_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x0084)
+#define OMAP4430_RM_L4PER_GPIO6_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_INST, 0x0084)
 #define OMAP4_RM_L4PER_HDQ1W_CONTEXT_OFFSET		0x008c
-#define OMAP4430_RM_L4PER_HDQ1W_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x008c)
+#define OMAP4430_RM_L4PER_HDQ1W_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_INST, 0x008c)
 #define OMAP4_PM_L4PER_HECC1_WKDEP_OFFSET		0x0090
-#define OMAP4430_PM_L4PER_HECC1_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x0090)
+#define OMAP4430_PM_L4PER_HECC1_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_INST, 0x0090)
 #define OMAP4_RM_L4PER_HECC1_CONTEXT_OFFSET		0x0094
-#define OMAP4430_RM_L4PER_HECC1_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x0094)
+#define OMAP4430_RM_L4PER_HECC1_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_INST, 0x0094)
 #define OMAP4_PM_L4PER_HECC2_WKDEP_OFFSET		0x0098
-#define OMAP4430_PM_L4PER_HECC2_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x0098)
+#define OMAP4430_PM_L4PER_HECC2_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_INST, 0x0098)
 #define OMAP4_RM_L4PER_HECC2_CONTEXT_OFFSET		0x009c
-#define OMAP4430_RM_L4PER_HECC2_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x009c)
+#define OMAP4430_RM_L4PER_HECC2_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_INST, 0x009c)
 #define OMAP4_PM_L4PER_I2C1_WKDEP_OFFSET		0x00a0
-#define OMAP4430_PM_L4PER_I2C1_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x00a0)
+#define OMAP4430_PM_L4PER_I2C1_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_INST, 0x00a0)
 #define OMAP4_RM_L4PER_I2C1_CONTEXT_OFFSET		0x00a4
-#define OMAP4430_RM_L4PER_I2C1_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x00a4)
+#define OMAP4430_RM_L4PER_I2C1_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_INST, 0x00a4)
 #define OMAP4_PM_L4PER_I2C2_WKDEP_OFFSET		0x00a8
-#define OMAP4430_PM_L4PER_I2C2_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x00a8)
+#define OMAP4430_PM_L4PER_I2C2_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_INST, 0x00a8)
 #define OMAP4_RM_L4PER_I2C2_CONTEXT_OFFSET		0x00ac
-#define OMAP4430_RM_L4PER_I2C2_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x00ac)
+#define OMAP4430_RM_L4PER_I2C2_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_INST, 0x00ac)
 #define OMAP4_PM_L4PER_I2C3_WKDEP_OFFSET		0x00b0
-#define OMAP4430_PM_L4PER_I2C3_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x00b0)
+#define OMAP4430_PM_L4PER_I2C3_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_INST, 0x00b0)
 #define OMAP4_RM_L4PER_I2C3_CONTEXT_OFFSET		0x00b4
-#define OMAP4430_RM_L4PER_I2C3_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x00b4)
+#define OMAP4430_RM_L4PER_I2C3_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_INST, 0x00b4)
 #define OMAP4_PM_L4PER_I2C4_WKDEP_OFFSET		0x00b8
-#define OMAP4430_PM_L4PER_I2C4_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x00b8)
+#define OMAP4430_PM_L4PER_I2C4_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_INST, 0x00b8)
 #define OMAP4_RM_L4PER_I2C4_CONTEXT_OFFSET		0x00bc
-#define OMAP4430_RM_L4PER_I2C4_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x00bc)
+#define OMAP4430_RM_L4PER_I2C4_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_INST, 0x00bc)
 #define OMAP4_RM_L4PER_L4_PER_CONTEXT_OFFSET		0x00c0
-#define OMAP4430_RM_L4PER_L4_PER_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x00c0)
+#define OMAP4430_RM_L4PER_L4_PER_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_INST, 0x00c0)
 #define OMAP4_PM_L4PER_MCASP2_WKDEP_OFFSET		0x00d0
-#define OMAP4430_PM_L4PER_MCASP2_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x00d0)
+#define OMAP4430_PM_L4PER_MCASP2_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_INST, 0x00d0)
 #define OMAP4_RM_L4PER_MCASP2_CONTEXT_OFFSET		0x00d4
-#define OMAP4430_RM_L4PER_MCASP2_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x00d4)
+#define OMAP4430_RM_L4PER_MCASP2_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_INST, 0x00d4)
 #define OMAP4_PM_L4PER_MCASP3_WKDEP_OFFSET		0x00d8
-#define OMAP4430_PM_L4PER_MCASP3_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x00d8)
+#define OMAP4430_PM_L4PER_MCASP3_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_INST, 0x00d8)
 #define OMAP4_RM_L4PER_MCASP3_CONTEXT_OFFSET		0x00dc
-#define OMAP4430_RM_L4PER_MCASP3_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x00dc)
+#define OMAP4430_RM_L4PER_MCASP3_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_INST, 0x00dc)
 #define OMAP4_PM_L4PER_MCBSP4_WKDEP_OFFSET		0x00e0
-#define OMAP4430_PM_L4PER_MCBSP4_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x00e0)
+#define OMAP4430_PM_L4PER_MCBSP4_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_INST, 0x00e0)
 #define OMAP4_RM_L4PER_MCBSP4_CONTEXT_OFFSET		0x00e4
-#define OMAP4430_RM_L4PER_MCBSP4_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x00e4)
+#define OMAP4430_RM_L4PER_MCBSP4_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_INST, 0x00e4)
 #define OMAP4_RM_L4PER_MGATE_CONTEXT_OFFSET		0x00ec
-#define OMAP4430_RM_L4PER_MGATE_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x00ec)
+#define OMAP4430_RM_L4PER_MGATE_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_INST, 0x00ec)
 #define OMAP4_PM_L4PER_MCSPI1_WKDEP_OFFSET		0x00f0
-#define OMAP4430_PM_L4PER_MCSPI1_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x00f0)
+#define OMAP4430_PM_L4PER_MCSPI1_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_INST, 0x00f0)
 #define OMAP4_RM_L4PER_MCSPI1_CONTEXT_OFFSET		0x00f4
-#define OMAP4430_RM_L4PER_MCSPI1_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x00f4)
+#define OMAP4430_RM_L4PER_MCSPI1_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_INST, 0x00f4)
 #define OMAP4_PM_L4PER_MCSPI2_WKDEP_OFFSET		0x00f8
-#define OMAP4430_PM_L4PER_MCSPI2_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x00f8)
+#define OMAP4430_PM_L4PER_MCSPI2_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_INST, 0x00f8)
 #define OMAP4_RM_L4PER_MCSPI2_CONTEXT_OFFSET		0x00fc
-#define OMAP4430_RM_L4PER_MCSPI2_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x00fc)
+#define OMAP4430_RM_L4PER_MCSPI2_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_INST, 0x00fc)
 #define OMAP4_PM_L4PER_MCSPI3_WKDEP_OFFSET		0x0100
-#define OMAP4430_PM_L4PER_MCSPI3_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x0100)
+#define OMAP4430_PM_L4PER_MCSPI3_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_INST, 0x0100)
 #define OMAP4_RM_L4PER_MCSPI3_CONTEXT_OFFSET		0x0104
-#define OMAP4430_RM_L4PER_MCSPI3_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x0104)
+#define OMAP4430_RM_L4PER_MCSPI3_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_INST, 0x0104)
 #define OMAP4_PM_L4PER_MCSPI4_WKDEP_OFFSET		0x0108
-#define OMAP4430_PM_L4PER_MCSPI4_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x0108)
+#define OMAP4430_PM_L4PER_MCSPI4_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_INST, 0x0108)
 #define OMAP4_RM_L4PER_MCSPI4_CONTEXT_OFFSET		0x010c
-#define OMAP4430_RM_L4PER_MCSPI4_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x010c)
+#define OMAP4430_RM_L4PER_MCSPI4_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_INST, 0x010c)
 #define OMAP4_PM_L4PER_MMCSD3_WKDEP_OFFSET		0x0120
-#define OMAP4430_PM_L4PER_MMCSD3_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x0120)
+#define OMAP4430_PM_L4PER_MMCSD3_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_INST, 0x0120)
 #define OMAP4_RM_L4PER_MMCSD3_CONTEXT_OFFSET		0x0124
-#define OMAP4430_RM_L4PER_MMCSD3_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x0124)
+#define OMAP4430_RM_L4PER_MMCSD3_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_INST, 0x0124)
 #define OMAP4_PM_L4PER_MMCSD4_WKDEP_OFFSET		0x0128
-#define OMAP4430_PM_L4PER_MMCSD4_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x0128)
+#define OMAP4430_PM_L4PER_MMCSD4_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_INST, 0x0128)
 #define OMAP4_RM_L4PER_MMCSD4_CONTEXT_OFFSET		0x012c
-#define OMAP4430_RM_L4PER_MMCSD4_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x012c)
+#define OMAP4430_RM_L4PER_MMCSD4_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_INST, 0x012c)
 #define OMAP4_RM_L4PER_MSPROHG_CONTEXT_OFFSET		0x0134
-#define OMAP4430_RM_L4PER_MSPROHG_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x0134)
+#define OMAP4430_RM_L4PER_MSPROHG_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_INST, 0x0134)
 #define OMAP4_PM_L4PER_SLIMBUS2_WKDEP_OFFSET		0x0138
-#define OMAP4430_PM_L4PER_SLIMBUS2_WKDEP		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x0138)
+#define OMAP4430_PM_L4PER_SLIMBUS2_WKDEP		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_INST, 0x0138)
 #define OMAP4_RM_L4PER_SLIMBUS2_CONTEXT_OFFSET		0x013c
-#define OMAP4430_RM_L4PER_SLIMBUS2_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x013c)
+#define OMAP4430_RM_L4PER_SLIMBUS2_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_INST, 0x013c)
 #define OMAP4_PM_L4PER_UART1_WKDEP_OFFSET		0x0140
-#define OMAP4430_PM_L4PER_UART1_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x0140)
+#define OMAP4430_PM_L4PER_UART1_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_INST, 0x0140)
 #define OMAP4_RM_L4PER_UART1_CONTEXT_OFFSET		0x0144
-#define OMAP4430_RM_L4PER_UART1_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x0144)
+#define OMAP4430_RM_L4PER_UART1_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_INST, 0x0144)
 #define OMAP4_PM_L4PER_UART2_WKDEP_OFFSET		0x0148
-#define OMAP4430_PM_L4PER_UART2_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x0148)
+#define OMAP4430_PM_L4PER_UART2_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_INST, 0x0148)
 #define OMAP4_RM_L4PER_UART2_CONTEXT_OFFSET		0x014c
-#define OMAP4430_RM_L4PER_UART2_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x014c)
+#define OMAP4430_RM_L4PER_UART2_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_INST, 0x014c)
 #define OMAP4_PM_L4PER_UART3_WKDEP_OFFSET		0x0150
-#define OMAP4430_PM_L4PER_UART3_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x0150)
+#define OMAP4430_PM_L4PER_UART3_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_INST, 0x0150)
 #define OMAP4_RM_L4PER_UART3_CONTEXT_OFFSET		0x0154
-#define OMAP4430_RM_L4PER_UART3_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x0154)
+#define OMAP4430_RM_L4PER_UART3_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_INST, 0x0154)
 #define OMAP4_PM_L4PER_UART4_WKDEP_OFFSET		0x0158
-#define OMAP4430_PM_L4PER_UART4_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x0158)
+#define OMAP4430_PM_L4PER_UART4_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_INST, 0x0158)
 #define OMAP4_RM_L4PER_UART4_CONTEXT_OFFSET		0x015c
-#define OMAP4430_RM_L4PER_UART4_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x015c)
+#define OMAP4430_RM_L4PER_UART4_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_INST, 0x015c)
 #define OMAP4_PM_L4PER_MMCSD5_WKDEP_OFFSET		0x0160
-#define OMAP4430_PM_L4PER_MMCSD5_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x0160)
+#define OMAP4430_PM_L4PER_MMCSD5_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_INST, 0x0160)
 #define OMAP4_RM_L4PER_MMCSD5_CONTEXT_OFFSET		0x0164
-#define OMAP4430_RM_L4PER_MMCSD5_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x0164)
+#define OMAP4430_RM_L4PER_MMCSD5_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_INST, 0x0164)
 #define OMAP4_PM_L4PER_I2C5_WKDEP_OFFSET		0x0168
-#define OMAP4430_PM_L4PER_I2C5_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x0168)
+#define OMAP4430_PM_L4PER_I2C5_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_INST, 0x0168)
 #define OMAP4_RM_L4PER_I2C5_CONTEXT_OFFSET		0x016c
-#define OMAP4430_RM_L4PER_I2C5_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x016c)
+#define OMAP4430_RM_L4PER_I2C5_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_INST, 0x016c)
 #define OMAP4_RM_L4SEC_AES1_CONTEXT_OFFSET		0x01a4
-#define OMAP4430_RM_L4SEC_AES1_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x01a4)
+#define OMAP4430_RM_L4SEC_AES1_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_INST, 0x01a4)
 #define OMAP4_RM_L4SEC_AES2_CONTEXT_OFFSET		0x01ac
-#define OMAP4430_RM_L4SEC_AES2_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x01ac)
+#define OMAP4430_RM_L4SEC_AES2_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_INST, 0x01ac)
 #define OMAP4_RM_L4SEC_DES3DES_CONTEXT_OFFSET		0x01b4
-#define OMAP4430_RM_L4SEC_DES3DES_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x01b4)
+#define OMAP4430_RM_L4SEC_DES3DES_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_INST, 0x01b4)
 #define OMAP4_RM_L4SEC_PKAEIP29_CONTEXT_OFFSET		0x01bc
-#define OMAP4430_RM_L4SEC_PKAEIP29_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x01bc)
+#define OMAP4430_RM_L4SEC_PKAEIP29_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_INST, 0x01bc)
 #define OMAP4_RM_L4SEC_RNG_CONTEXT_OFFSET		0x01c4
-#define OMAP4430_RM_L4SEC_RNG_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x01c4)
+#define OMAP4430_RM_L4SEC_RNG_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_INST, 0x01c4)
 #define OMAP4_RM_L4SEC_SHA2MD51_CONTEXT_OFFSET		0x01cc
-#define OMAP4430_RM_L4SEC_SHA2MD51_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x01cc)
+#define OMAP4430_RM_L4SEC_SHA2MD51_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_INST, 0x01cc)
 #define OMAP4_RM_L4SEC_CRYPTODMA_CONTEXT_OFFSET		0x01dc
-#define OMAP4430_RM_L4SEC_CRYPTODMA_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_MOD, 0x01dc)
+#define OMAP4430_RM_L4SEC_CRYPTODMA_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_L4PER_INST, 0x01dc)
 
 /* PRM.CEFUSE_PRM register offsets */
 #define OMAP4_PM_CEFUSE_PWRSTCTRL_OFFSET		0x0000
-#define OMAP4430_PM_CEFUSE_PWRSTCTRL			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CEFUSE_MOD, 0x0000)
+#define OMAP4430_PM_CEFUSE_PWRSTCTRL			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CEFUSE_INST, 0x0000)
 #define OMAP4_PM_CEFUSE_PWRSTST_OFFSET			0x0004
-#define OMAP4430_PM_CEFUSE_PWRSTST			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CEFUSE_MOD, 0x0004)
+#define OMAP4430_PM_CEFUSE_PWRSTST			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CEFUSE_INST, 0x0004)
 #define OMAP4_RM_CEFUSE_CEFUSE_CONTEXT_OFFSET		0x0024
-#define OMAP4430_RM_CEFUSE_CEFUSE_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CEFUSE_MOD, 0x0024)
+#define OMAP4430_RM_CEFUSE_CEFUSE_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CEFUSE_INST, 0x0024)
 
 /* PRM.WKUP_PRM register offsets */
 #define OMAP4_RM_WKUP_L4WKUP_CONTEXT_OFFSET		0x0024
-#define OMAP4430_RM_WKUP_L4WKUP_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_WKUP_MOD, 0x0024)
+#define OMAP4430_RM_WKUP_L4WKUP_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_WKUP_INST, 0x0024)
 #define OMAP4_RM_WKUP_WDT1_CONTEXT_OFFSET		0x002c
-#define OMAP4430_RM_WKUP_WDT1_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_WKUP_MOD, 0x002c)
+#define OMAP4430_RM_WKUP_WDT1_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_WKUP_INST, 0x002c)
 #define OMAP4_PM_WKUP_WDT2_WKDEP_OFFSET			0x0030
-#define OMAP4430_PM_WKUP_WDT2_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_WKUP_MOD, 0x0030)
+#define OMAP4430_PM_WKUP_WDT2_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_WKUP_INST, 0x0030)
 #define OMAP4_RM_WKUP_WDT2_CONTEXT_OFFSET		0x0034
-#define OMAP4430_RM_WKUP_WDT2_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_WKUP_MOD, 0x0034)
+#define OMAP4430_RM_WKUP_WDT2_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_WKUP_INST, 0x0034)
 #define OMAP4_PM_WKUP_GPIO1_WKDEP_OFFSET		0x0038
-#define OMAP4430_PM_WKUP_GPIO1_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_WKUP_MOD, 0x0038)
+#define OMAP4430_PM_WKUP_GPIO1_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_WKUP_INST, 0x0038)
 #define OMAP4_RM_WKUP_GPIO1_CONTEXT_OFFSET		0x003c
-#define OMAP4430_RM_WKUP_GPIO1_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_WKUP_MOD, 0x003c)
+#define OMAP4430_RM_WKUP_GPIO1_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_WKUP_INST, 0x003c)
 #define OMAP4_PM_WKUP_TIMER1_WKDEP_OFFSET		0x0040
-#define OMAP4430_PM_WKUP_TIMER1_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_WKUP_MOD, 0x0040)
+#define OMAP4430_PM_WKUP_TIMER1_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_WKUP_INST, 0x0040)
 #define OMAP4_RM_WKUP_TIMER1_CONTEXT_OFFSET		0x0044
-#define OMAP4430_RM_WKUP_TIMER1_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_WKUP_MOD, 0x0044)
+#define OMAP4430_RM_WKUP_TIMER1_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_WKUP_INST, 0x0044)
 #define OMAP4_PM_WKUP_TIMER12_WKDEP_OFFSET		0x0048
-#define OMAP4430_PM_WKUP_TIMER12_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_WKUP_MOD, 0x0048)
+#define OMAP4430_PM_WKUP_TIMER12_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_WKUP_INST, 0x0048)
 #define OMAP4_RM_WKUP_TIMER12_CONTEXT_OFFSET		0x004c
-#define OMAP4430_RM_WKUP_TIMER12_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_WKUP_MOD, 0x004c)
+#define OMAP4430_RM_WKUP_TIMER12_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_WKUP_INST, 0x004c)
 #define OMAP4_RM_WKUP_SYNCTIMER_CONTEXT_OFFSET		0x0054
-#define OMAP4430_RM_WKUP_SYNCTIMER_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_WKUP_MOD, 0x0054)
+#define OMAP4430_RM_WKUP_SYNCTIMER_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_WKUP_INST, 0x0054)
 #define OMAP4_PM_WKUP_USIM_WKDEP_OFFSET			0x0058
-#define OMAP4430_PM_WKUP_USIM_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_WKUP_MOD, 0x0058)
+#define OMAP4430_PM_WKUP_USIM_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_WKUP_INST, 0x0058)
 #define OMAP4_RM_WKUP_USIM_CONTEXT_OFFSET		0x005c
-#define OMAP4430_RM_WKUP_USIM_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_WKUP_MOD, 0x005c)
+#define OMAP4430_RM_WKUP_USIM_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_WKUP_INST, 0x005c)
 #define OMAP4_RM_WKUP_SARRAM_CONTEXT_OFFSET		0x0064
-#define OMAP4430_RM_WKUP_SARRAM_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_WKUP_MOD, 0x0064)
+#define OMAP4430_RM_WKUP_SARRAM_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_WKUP_INST, 0x0064)
 #define OMAP4_PM_WKUP_KEYBOARD_WKDEP_OFFSET		0x0078
-#define OMAP4430_PM_WKUP_KEYBOARD_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_WKUP_MOD, 0x0078)
+#define OMAP4430_PM_WKUP_KEYBOARD_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_WKUP_INST, 0x0078)
 #define OMAP4_RM_WKUP_KEYBOARD_CONTEXT_OFFSET		0x007c
-#define OMAP4430_RM_WKUP_KEYBOARD_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_WKUP_MOD, 0x007c)
+#define OMAP4430_RM_WKUP_KEYBOARD_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_WKUP_INST, 0x007c)
 #define OMAP4_PM_WKUP_RTC_WKDEP_OFFSET			0x0080
-#define OMAP4430_PM_WKUP_RTC_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_WKUP_MOD, 0x0080)
+#define OMAP4430_PM_WKUP_RTC_WKDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_WKUP_INST, 0x0080)
 #define OMAP4_RM_WKUP_RTC_CONTEXT_OFFSET		0x0084
-#define OMAP4430_RM_WKUP_RTC_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_WKUP_MOD, 0x0084)
+#define OMAP4430_RM_WKUP_RTC_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_WKUP_INST, 0x0084)
 
 /* PRM.WKUP_CM register offsets */
 #define OMAP4_CM_WKUP_CLKSTCTRL_OFFSET			0x0000
-#define OMAP4430_CM_WKUP_CLKSTCTRL			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_WKUP_CM_MOD, 0x0000)
+#define OMAP4430_CM_WKUP_CLKSTCTRL			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_WKUP_CM_INST, 0x0000)
 #define OMAP4_CM_WKUP_L4WKUP_CLKCTRL_OFFSET		0x0020
-#define OMAP4430_CM_WKUP_L4WKUP_CLKCTRL			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_WKUP_CM_MOD, 0x0020)
+#define OMAP4430_CM_WKUP_L4WKUP_CLKCTRL			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_WKUP_CM_INST, 0x0020)
 #define OMAP4_CM_WKUP_WDT1_CLKCTRL_OFFSET		0x0028
-#define OMAP4430_CM_WKUP_WDT1_CLKCTRL			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_WKUP_CM_MOD, 0x0028)
+#define OMAP4430_CM_WKUP_WDT1_CLKCTRL			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_WKUP_CM_INST, 0x0028)
 #define OMAP4_CM_WKUP_WDT2_CLKCTRL_OFFSET		0x0030
-#define OMAP4430_CM_WKUP_WDT2_CLKCTRL			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_WKUP_CM_MOD, 0x0030)
+#define OMAP4430_CM_WKUP_WDT2_CLKCTRL			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_WKUP_CM_INST, 0x0030)
 #define OMAP4_CM_WKUP_GPIO1_CLKCTRL_OFFSET		0x0038
-#define OMAP4430_CM_WKUP_GPIO1_CLKCTRL			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_WKUP_CM_MOD, 0x0038)
+#define OMAP4430_CM_WKUP_GPIO1_CLKCTRL			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_WKUP_CM_INST, 0x0038)
 #define OMAP4_CM_WKUP_TIMER1_CLKCTRL_OFFSET		0x0040
-#define OMAP4430_CM_WKUP_TIMER1_CLKCTRL			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_WKUP_CM_MOD, 0x0040)
+#define OMAP4430_CM_WKUP_TIMER1_CLKCTRL			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_WKUP_CM_INST, 0x0040)
 #define OMAP4_CM_WKUP_TIMER12_CLKCTRL_OFFSET		0x0048
-#define OMAP4430_CM_WKUP_TIMER12_CLKCTRL		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_WKUP_CM_MOD, 0x0048)
+#define OMAP4430_CM_WKUP_TIMER12_CLKCTRL		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_WKUP_CM_INST, 0x0048)
 #define OMAP4_CM_WKUP_SYNCTIMER_CLKCTRL_OFFSET		0x0050
-#define OMAP4430_CM_WKUP_SYNCTIMER_CLKCTRL		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_WKUP_CM_MOD, 0x0050)
+#define OMAP4430_CM_WKUP_SYNCTIMER_CLKCTRL		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_WKUP_CM_INST, 0x0050)
 #define OMAP4_CM_WKUP_USIM_CLKCTRL_OFFSET		0x0058
-#define OMAP4430_CM_WKUP_USIM_CLKCTRL			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_WKUP_CM_MOD, 0x0058)
+#define OMAP4430_CM_WKUP_USIM_CLKCTRL			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_WKUP_CM_INST, 0x0058)
 #define OMAP4_CM_WKUP_SARRAM_CLKCTRL_OFFSET		0x0060
-#define OMAP4430_CM_WKUP_SARRAM_CLKCTRL			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_WKUP_CM_MOD, 0x0060)
+#define OMAP4430_CM_WKUP_SARRAM_CLKCTRL			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_WKUP_CM_INST, 0x0060)
 #define OMAP4_CM_WKUP_KEYBOARD_CLKCTRL_OFFSET		0x0078
-#define OMAP4430_CM_WKUP_KEYBOARD_CLKCTRL		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_WKUP_CM_MOD, 0x0078)
+#define OMAP4430_CM_WKUP_KEYBOARD_CLKCTRL		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_WKUP_CM_INST, 0x0078)
 #define OMAP4_CM_WKUP_RTC_CLKCTRL_OFFSET		0x0080
-#define OMAP4430_CM_WKUP_RTC_CLKCTRL			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_WKUP_CM_MOD, 0x0080)
+#define OMAP4430_CM_WKUP_RTC_CLKCTRL			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_WKUP_CM_INST, 0x0080)
 #define OMAP4_CM_WKUP_BANDGAP_CLKCTRL_OFFSET		0x0088
-#define OMAP4430_CM_WKUP_BANDGAP_CLKCTRL		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_WKUP_CM_MOD, 0x0088)
+#define OMAP4430_CM_WKUP_BANDGAP_CLKCTRL		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_WKUP_CM_INST, 0x0088)
 
 /* PRM.EMU_PRM register offsets */
 #define OMAP4_PM_EMU_PWRSTCTRL_OFFSET			0x0000
-#define OMAP4430_PM_EMU_PWRSTCTRL			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_EMU_MOD, 0x0000)
+#define OMAP4430_PM_EMU_PWRSTCTRL			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_EMU_INST, 0x0000)
 #define OMAP4_PM_EMU_PWRSTST_OFFSET			0x0004
-#define OMAP4430_PM_EMU_PWRSTST				OMAP44XX_PRM_REGADDR(OMAP4430_PRM_EMU_MOD, 0x0004)
+#define OMAP4430_PM_EMU_PWRSTST				OMAP44XX_PRM_REGADDR(OMAP4430_PRM_EMU_INST, 0x0004)
 #define OMAP4_RM_EMU_DEBUGSS_CONTEXT_OFFSET		0x0024
-#define OMAP4430_RM_EMU_DEBUGSS_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_EMU_MOD, 0x0024)
+#define OMAP4430_RM_EMU_DEBUGSS_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_EMU_INST, 0x0024)
 
 /* PRM.EMU_CM register offsets */
 #define OMAP4_CM_EMU_CLKSTCTRL_OFFSET			0x0000
-#define OMAP4430_CM_EMU_CLKSTCTRL			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_EMU_CM_MOD, 0x0000)
+#define OMAP4430_CM_EMU_CLKSTCTRL			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_EMU_CM_INST, 0x0000)
 #define OMAP4_CM_EMU_DYNAMICDEP_OFFSET			0x0008
-#define OMAP4430_CM_EMU_DYNAMICDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_EMU_CM_MOD, 0x0008)
+#define OMAP4430_CM_EMU_DYNAMICDEP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_EMU_CM_INST, 0x0008)
 #define OMAP4_CM_EMU_DEBUGSS_CLKCTRL_OFFSET		0x0020
-#define OMAP4430_CM_EMU_DEBUGSS_CLKCTRL			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_EMU_CM_MOD, 0x0020)
+#define OMAP4430_CM_EMU_DEBUGSS_CLKCTRL			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_EMU_CM_INST, 0x0020)
 
 /* PRM.DEVICE_PRM register offsets */
 #define OMAP4_PRM_RSTCTRL_OFFSET			0x0000
-#define OMAP4430_PRM_RSTCTRL				OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x0000)
+#define OMAP4430_PRM_RSTCTRL				OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_INST, 0x0000)
 #define OMAP4_PRM_RSTST_OFFSET				0x0004
-#define OMAP4430_PRM_RSTST				OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x0004)
+#define OMAP4430_PRM_RSTST				OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_INST, 0x0004)
 #define OMAP4_PRM_RSTTIME_OFFSET			0x0008
-#define OMAP4430_PRM_RSTTIME				OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x0008)
+#define OMAP4430_PRM_RSTTIME				OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_INST, 0x0008)
 #define OMAP4_PRM_CLKREQCTRL_OFFSET			0x000c
-#define OMAP4430_PRM_CLKREQCTRL				OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x000c)
+#define OMAP4430_PRM_CLKREQCTRL				OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_INST, 0x000c)
 #define OMAP4_PRM_VOLTCTRL_OFFSET			0x0010
-#define OMAP4430_PRM_VOLTCTRL				OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x0010)
+#define OMAP4430_PRM_VOLTCTRL				OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_INST, 0x0010)
 #define OMAP4_PRM_PWRREQCTRL_OFFSET			0x0014
-#define OMAP4430_PRM_PWRREQCTRL				OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x0014)
+#define OMAP4430_PRM_PWRREQCTRL				OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_INST, 0x0014)
 #define OMAP4_PRM_PSCON_COUNT_OFFSET			0x0018
-#define OMAP4430_PRM_PSCON_COUNT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x0018)
+#define OMAP4430_PRM_PSCON_COUNT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_INST, 0x0018)
 #define OMAP4_PRM_IO_COUNT_OFFSET			0x001c
-#define OMAP4430_PRM_IO_COUNT				OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x001c)
+#define OMAP4430_PRM_IO_COUNT				OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_INST, 0x001c)
 #define OMAP4_PRM_IO_PMCTRL_OFFSET			0x0020
-#define OMAP4430_PRM_IO_PMCTRL				OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x0020)
+#define OMAP4430_PRM_IO_PMCTRL				OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_INST, 0x0020)
 #define OMAP4_PRM_VOLTSETUP_WARMRESET_OFFSET		0x0024
-#define OMAP4430_PRM_VOLTSETUP_WARMRESET		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x0024)
+#define OMAP4430_PRM_VOLTSETUP_WARMRESET		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_INST, 0x0024)
 #define OMAP4_PRM_VOLTSETUP_CORE_OFF_OFFSET		0x0028
-#define OMAP4430_PRM_VOLTSETUP_CORE_OFF			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x0028)
+#define OMAP4430_PRM_VOLTSETUP_CORE_OFF			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_INST, 0x0028)
 #define OMAP4_PRM_VOLTSETUP_MPU_OFF_OFFSET		0x002c
-#define OMAP4430_PRM_VOLTSETUP_MPU_OFF			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x002c)
+#define OMAP4430_PRM_VOLTSETUP_MPU_OFF			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_INST, 0x002c)
 #define OMAP4_PRM_VOLTSETUP_IVA_OFF_OFFSET		0x0030
-#define OMAP4430_PRM_VOLTSETUP_IVA_OFF			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x0030)
+#define OMAP4430_PRM_VOLTSETUP_IVA_OFF			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_INST, 0x0030)
 #define OMAP4_PRM_VOLTSETUP_CORE_RET_SLEEP_OFFSET	0x0034
-#define OMAP4430_PRM_VOLTSETUP_CORE_RET_SLEEP		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x0034)
+#define OMAP4430_PRM_VOLTSETUP_CORE_RET_SLEEP		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_INST, 0x0034)
 #define OMAP4_PRM_VOLTSETUP_MPU_RET_SLEEP_OFFSET	0x0038
-#define OMAP4430_PRM_VOLTSETUP_MPU_RET_SLEEP		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x0038)
+#define OMAP4430_PRM_VOLTSETUP_MPU_RET_SLEEP		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_INST, 0x0038)
 #define OMAP4_PRM_VOLTSETUP_IVA_RET_SLEEP_OFFSET	0x003c
-#define OMAP4430_PRM_VOLTSETUP_IVA_RET_SLEEP		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x003c)
+#define OMAP4430_PRM_VOLTSETUP_IVA_RET_SLEEP		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_INST, 0x003c)
 #define OMAP4_PRM_VP_CORE_CONFIG_OFFSET			0x0040
-#define OMAP4430_PRM_VP_CORE_CONFIG			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x0040)
+#define OMAP4430_PRM_VP_CORE_CONFIG			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_INST, 0x0040)
 #define OMAP4_PRM_VP_CORE_STATUS_OFFSET			0x0044
-#define OMAP4430_PRM_VP_CORE_STATUS			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x0044)
+#define OMAP4430_PRM_VP_CORE_STATUS			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_INST, 0x0044)
 #define OMAP4_PRM_VP_CORE_VLIMITTO_OFFSET		0x0048
-#define OMAP4430_PRM_VP_CORE_VLIMITTO			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x0048)
+#define OMAP4430_PRM_VP_CORE_VLIMITTO			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_INST, 0x0048)
 #define OMAP4_PRM_VP_CORE_VOLTAGE_OFFSET		0x004c
-#define OMAP4430_PRM_VP_CORE_VOLTAGE			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x004c)
+#define OMAP4430_PRM_VP_CORE_VOLTAGE			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_INST, 0x004c)
 #define OMAP4_PRM_VP_CORE_VSTEPMAX_OFFSET		0x0050
-#define OMAP4430_PRM_VP_CORE_VSTEPMAX			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x0050)
+#define OMAP4430_PRM_VP_CORE_VSTEPMAX			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_INST, 0x0050)
 #define OMAP4_PRM_VP_CORE_VSTEPMIN_OFFSET		0x0054
-#define OMAP4430_PRM_VP_CORE_VSTEPMIN			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x0054)
+#define OMAP4430_PRM_VP_CORE_VSTEPMIN			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_INST, 0x0054)
 #define OMAP4_PRM_VP_MPU_CONFIG_OFFSET			0x0058
-#define OMAP4430_PRM_VP_MPU_CONFIG			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x0058)
+#define OMAP4430_PRM_VP_MPU_CONFIG			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_INST, 0x0058)
 #define OMAP4_PRM_VP_MPU_STATUS_OFFSET			0x005c
-#define OMAP4430_PRM_VP_MPU_STATUS			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x005c)
+#define OMAP4430_PRM_VP_MPU_STATUS			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_INST, 0x005c)
 #define OMAP4_PRM_VP_MPU_VLIMITTO_OFFSET		0x0060
-#define OMAP4430_PRM_VP_MPU_VLIMITTO			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x0060)
+#define OMAP4430_PRM_VP_MPU_VLIMITTO			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_INST, 0x0060)
 #define OMAP4_PRM_VP_MPU_VOLTAGE_OFFSET			0x0064
-#define OMAP4430_PRM_VP_MPU_VOLTAGE			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x0064)
+#define OMAP4430_PRM_VP_MPU_VOLTAGE			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_INST, 0x0064)
 #define OMAP4_PRM_VP_MPU_VSTEPMAX_OFFSET		0x0068
-#define OMAP4430_PRM_VP_MPU_VSTEPMAX			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x0068)
+#define OMAP4430_PRM_VP_MPU_VSTEPMAX			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_INST, 0x0068)
 #define OMAP4_PRM_VP_MPU_VSTEPMIN_OFFSET		0x006c
-#define OMAP4430_PRM_VP_MPU_VSTEPMIN			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x006c)
+#define OMAP4430_PRM_VP_MPU_VSTEPMIN			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_INST, 0x006c)
 #define OMAP4_PRM_VP_IVA_CONFIG_OFFSET			0x0070
-#define OMAP4430_PRM_VP_IVA_CONFIG			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x0070)
+#define OMAP4430_PRM_VP_IVA_CONFIG			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_INST, 0x0070)
 #define OMAP4_PRM_VP_IVA_STATUS_OFFSET			0x0074
-#define OMAP4430_PRM_VP_IVA_STATUS			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x0074)
+#define OMAP4430_PRM_VP_IVA_STATUS			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_INST, 0x0074)
 #define OMAP4_PRM_VP_IVA_VLIMITTO_OFFSET		0x0078
-#define OMAP4430_PRM_VP_IVA_VLIMITTO			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x0078)
+#define OMAP4430_PRM_VP_IVA_VLIMITTO			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_INST, 0x0078)
 #define OMAP4_PRM_VP_IVA_VOLTAGE_OFFSET			0x007c
-#define OMAP4430_PRM_VP_IVA_VOLTAGE			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x007c)
+#define OMAP4430_PRM_VP_IVA_VOLTAGE			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_INST, 0x007c)
 #define OMAP4_PRM_VP_IVA_VSTEPMAX_OFFSET		0x0080
-#define OMAP4430_PRM_VP_IVA_VSTEPMAX			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x0080)
+#define OMAP4430_PRM_VP_IVA_VSTEPMAX			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_INST, 0x0080)
 #define OMAP4_PRM_VP_IVA_VSTEPMIN_OFFSET		0x0084
-#define OMAP4430_PRM_VP_IVA_VSTEPMIN			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x0084)
+#define OMAP4430_PRM_VP_IVA_VSTEPMIN			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_INST, 0x0084)
 #define OMAP4_PRM_VC_SMPS_SA_OFFSET			0x0088
-#define OMAP4430_PRM_VC_SMPS_SA				OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x0088)
+#define OMAP4430_PRM_VC_SMPS_SA				OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_INST, 0x0088)
 #define OMAP4_PRM_VC_VAL_SMPS_RA_VOL_OFFSET		0x008c
-#define OMAP4430_PRM_VC_VAL_SMPS_RA_VOL			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x008c)
+#define OMAP4430_PRM_VC_VAL_SMPS_RA_VOL			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_INST, 0x008c)
 #define OMAP4_PRM_VC_VAL_SMPS_RA_CMD_OFFSET		0x0090
-#define OMAP4430_PRM_VC_VAL_SMPS_RA_CMD			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x0090)
+#define OMAP4430_PRM_VC_VAL_SMPS_RA_CMD			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_INST, 0x0090)
 #define OMAP4_PRM_VC_VAL_CMD_VDD_CORE_L_OFFSET		0x0094
-#define OMAP4430_PRM_VC_VAL_CMD_VDD_CORE_L		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x0094)
+#define OMAP4430_PRM_VC_VAL_CMD_VDD_CORE_L		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_INST, 0x0094)
 #define OMAP4_PRM_VC_VAL_CMD_VDD_MPU_L_OFFSET		0x0098
-#define OMAP4430_PRM_VC_VAL_CMD_VDD_MPU_L		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x0098)
+#define OMAP4430_PRM_VC_VAL_CMD_VDD_MPU_L		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_INST, 0x0098)
 #define OMAP4_PRM_VC_VAL_CMD_VDD_IVA_L_OFFSET		0x009c
-#define OMAP4430_PRM_VC_VAL_CMD_VDD_IVA_L		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x009c)
+#define OMAP4430_PRM_VC_VAL_CMD_VDD_IVA_L		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_INST, 0x009c)
 #define OMAP4_PRM_VC_VAL_BYPASS_OFFSET			0x00a0
-#define OMAP4430_PRM_VC_VAL_BYPASS			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x00a0)
+#define OMAP4430_PRM_VC_VAL_BYPASS			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_INST, 0x00a0)
 #define OMAP4_PRM_VC_CFG_CHANNEL_OFFSET			0x00a4
-#define OMAP4430_PRM_VC_CFG_CHANNEL			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x00a4)
-#define OMAP4_PRM_VC_CFG_I2C_MODE_OFFSET		0x00a8
-#define OMAP4430_PRM_VC_CFG_I2C_MODE			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x00a8)
+#define OMAP4430_PRM_VC_CFG_CHANNEL			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_INST, 0x00a4)
+#define OMAP4_PRM_VC_CFG_I2C_INSTE_OFFSET		0x00a8
+#define OMAP4430_PRM_VC_CFG_I2C_INSTE			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_INST, 0x00a8)
 #define OMAP4_PRM_VC_CFG_I2C_CLK_OFFSET			0x00ac
-#define OMAP4430_PRM_VC_CFG_I2C_CLK			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x00ac)
+#define OMAP4430_PRM_VC_CFG_I2C_CLK			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_INST, 0x00ac)
 #define OMAP4_PRM_SRAM_COUNT_OFFSET			0x00b0
-#define OMAP4430_PRM_SRAM_COUNT				OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x00b0)
+#define OMAP4430_PRM_SRAM_COUNT				OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_INST, 0x00b0)
 #define OMAP4_PRM_SRAM_WKUP_SETUP_OFFSET		0x00b4
-#define OMAP4430_PRM_SRAM_WKUP_SETUP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x00b4)
+#define OMAP4430_PRM_SRAM_WKUP_SETUP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_INST, 0x00b4)
 #define OMAP4_PRM_LDO_SRAM_CORE_SETUP_OFFSET		0x00b8
-#define OMAP4430_PRM_LDO_SRAM_CORE_SETUP		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x00b8)
+#define OMAP4430_PRM_LDO_SRAM_CORE_SETUP		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_INST, 0x00b8)
 #define OMAP4_PRM_LDO_SRAM_CORE_CTRL_OFFSET		0x00bc
-#define OMAP4430_PRM_LDO_SRAM_CORE_CTRL			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x00bc)
+#define OMAP4430_PRM_LDO_SRAM_CORE_CTRL			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_INST, 0x00bc)
 #define OMAP4_PRM_LDO_SRAM_MPU_SETUP_OFFSET		0x00c0
-#define OMAP4430_PRM_LDO_SRAM_MPU_SETUP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x00c0)
+#define OMAP4430_PRM_LDO_SRAM_MPU_SETUP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_INST, 0x00c0)
 #define OMAP4_PRM_LDO_SRAM_MPU_CTRL_OFFSET		0x00c4
-#define OMAP4430_PRM_LDO_SRAM_MPU_CTRL			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x00c4)
+#define OMAP4430_PRM_LDO_SRAM_MPU_CTRL			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_INST, 0x00c4)
 #define OMAP4_PRM_LDO_SRAM_IVA_SETUP_OFFSET		0x00c8
-#define OMAP4430_PRM_LDO_SRAM_IVA_SETUP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x00c8)
+#define OMAP4430_PRM_LDO_SRAM_IVA_SETUP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_INST, 0x00c8)
 #define OMAP4_PRM_LDO_SRAM_IVA_CTRL_OFFSET		0x00cc
-#define OMAP4430_PRM_LDO_SRAM_IVA_CTRL			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x00cc)
+#define OMAP4430_PRM_LDO_SRAM_IVA_CTRL			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_INST, 0x00cc)
 #define OMAP4_PRM_LDO_ABB_MPU_SETUP_OFFSET		0x00d0
-#define OMAP4430_PRM_LDO_ABB_MPU_SETUP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x00d0)
+#define OMAP4430_PRM_LDO_ABB_MPU_SETUP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_INST, 0x00d0)
 #define OMAP4_PRM_LDO_ABB_MPU_CTRL_OFFSET		0x00d4
-#define OMAP4430_PRM_LDO_ABB_MPU_CTRL			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x00d4)
+#define OMAP4430_PRM_LDO_ABB_MPU_CTRL			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_INST, 0x00d4)
 #define OMAP4_PRM_LDO_ABB_IVA_SETUP_OFFSET		0x00d8
-#define OMAP4430_PRM_LDO_ABB_IVA_SETUP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x00d8)
+#define OMAP4430_PRM_LDO_ABB_IVA_SETUP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_INST, 0x00d8)
 #define OMAP4_PRM_LDO_ABB_IVA_CTRL_OFFSET		0x00dc
-#define OMAP4430_PRM_LDO_ABB_IVA_CTRL			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x00dc)
+#define OMAP4430_PRM_LDO_ABB_IVA_CTRL			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_INST, 0x00dc)
 #define OMAP4_PRM_LDO_BANDGAP_SETUP_OFFSET		0x00e0
-#define OMAP4430_PRM_LDO_BANDGAP_SETUP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x00e0)
+#define OMAP4430_PRM_LDO_BANDGAP_SETUP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_INST, 0x00e0)
 #define OMAP4_PRM_DEVICE_OFF_CTRL_OFFSET		0x00e4
-#define OMAP4430_PRM_DEVICE_OFF_CTRL			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x00e4)
+#define OMAP4430_PRM_DEVICE_OFF_CTRL			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_INST, 0x00e4)
 #define OMAP4_PRM_PHASE1_CNDP_OFFSET			0x00e8
-#define OMAP4430_PRM_PHASE1_CNDP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x00e8)
+#define OMAP4430_PRM_PHASE1_CNDP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_INST, 0x00e8)
 #define OMAP4_PRM_PHASE2A_CNDP_OFFSET			0x00ec
-#define OMAP4430_PRM_PHASE2A_CNDP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x00ec)
+#define OMAP4430_PRM_PHASE2A_CNDP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_INST, 0x00ec)
 #define OMAP4_PRM_PHASE2B_CNDP_OFFSET			0x00f0
-#define OMAP4430_PRM_PHASE2B_CNDP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x00f0)
-#define OMAP4_PRM_MODEM_IF_CTRL_OFFSET			0x00f4
-#define OMAP4430_PRM_MODEM_IF_CTRL			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x00f4)
+#define OMAP4430_PRM_PHASE2B_CNDP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_INST, 0x00f0)
+#define OMAP4_PRM_INSTEM_IF_CTRL_OFFSET			0x00f4
+#define OMAP4430_PRM_INSTEM_IF_CTRL			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_INST, 0x00f4)
 #define OMAP4_PRM_VC_ERRST_OFFSET			0x00f8
-#define OMAP4430_PRM_VC_ERRST				OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x00f8)
+#define OMAP4430_PRM_VC_ERRST				OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_INST, 0x00f8)
 
-/*
- * PRCM_MPU
- *
- * The PRCM_MPU is a local PRCM inside the MPU subsystem. For the PRCM (global)
- * point of view the PRCM_MPU is a single entity. It shares the same
- * programming model as the global PRCM and thus can be assimilate as two new
- * MOD inside the PRCM
- */
+/* Function prototypes */
+# ifndef __ASSEMBLER__
 
-/* PRCM_MPU.OCP_SOCKET_PRCM register offsets */
-#define OMAP4_REVISION_PRCM_OFFSET			0x0000
-#define OMAP4430_REVISION_PRCM				OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_OCP_SOCKET_PRCM_MOD, 0x0000)
+extern u32 omap4_prm_read_inst_reg(s16 inst, u16 idx);
+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);
+extern u32 omap4_prm_rmw_reg_bits(u32 mask, u32 bits, void __iomem *reg);
+extern u32 omap4_prm_set_inst_reg_bits(u32 bits, s16 inst, s16 idx);
+extern u32 omap4_prm_clear_inst_reg_bits(u32 bits, s16 inst, s16 idx);
+extern u32 omap4_prm_read_bits_shift(void __iomem *reg, u32 mask);
 
-/* PRCM_MPU.DEVICE_PRM register offsets */
-#define OMAP4_PRCM_MPU_PRM_RSTST_OFFSET			0x0000
-#define OMAP4430_PRCM_MPU_PRM_RSTST			OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_DEVICE_PRM_MOD, 0x0000)
-#define OMAP4_PRCM_MPU_PRM_PSCON_COUNT_OFFSET		0x0004
-#define OMAP4430_PRCM_MPU_PRM_PSCON_COUNT		OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_DEVICE_PRM_MOD, 0x0004)
+extern int omap4_prm_is_hardreset_asserted(void __iomem *rstctrl_reg, u8 shift);
+extern int omap4_prm_assert_hardreset(void __iomem *rstctrl_reg, u8 shift);
+extern int omap4_prm_deassert_hardreset(void __iomem *rstctrl_reg, u8 shift);
 
-/* PRCM_MPU.CPU0 register offsets */
-#define OMAP4_PM_CPU0_PWRSTCTRL_OFFSET			0x0000
-#define OMAP4430_PM_CPU0_PWRSTCTRL			OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_CPU0_MOD, 0x0000)
-#define OMAP4_PM_CPU0_PWRSTST_OFFSET			0x0004
-#define OMAP4430_PM_CPU0_PWRSTST			OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_CPU0_MOD, 0x0004)
-#define OMAP4_RM_CPU0_CPU0_CONTEXT_OFFSET		0x0008
-#define OMAP4430_RM_CPU0_CPU0_CONTEXT			OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_CPU0_MOD, 0x0008)
-#define OMAP4_RM_CPU0_CPU0_RSTCTRL_OFFSET		0x000c
-#define OMAP4430_RM_CPU0_CPU0_RSTCTRL			OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_CPU0_MOD, 0x000c)
-#define OMAP4_RM_CPU0_CPU0_RSTST_OFFSET			0x0010
-#define OMAP4430_RM_CPU0_CPU0_RSTST			OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_CPU0_MOD, 0x0010)
-#define OMAP4_CM_CPU0_CPU0_CLKCTRL_OFFSET		0x0014
-#define OMAP4430_CM_CPU0_CPU0_CLKCTRL			OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_CPU0_MOD, 0x0014)
-#define OMAP4_CM_CPU0_CLKSTCTRL_OFFSET			0x0018
-#define OMAP4430_CM_CPU0_CLKSTCTRL			OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_CPU0_MOD, 0x0018)
+extern void omap4_prm_global_warm_sw_reset(void);
+
+# endif
 
-/* PRCM_MPU.CPU1 register offsets */
-#define OMAP4_PM_CPU1_PWRSTCTRL_OFFSET			0x0000
-#define OMAP4430_PM_CPU1_PWRSTCTRL			OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_CPU1_MOD, 0x0000)
-#define OMAP4_PM_CPU1_PWRSTST_OFFSET			0x0004
-#define OMAP4430_PM_CPU1_PWRSTST			OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_CPU1_MOD, 0x0004)
-#define OMAP4_RM_CPU1_CPU1_CONTEXT_OFFSET		0x0008
-#define OMAP4430_RM_CPU1_CPU1_CONTEXT			OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_CPU1_MOD, 0x0008)
-#define OMAP4_RM_CPU1_CPU1_RSTCTRL_OFFSET		0x000c
-#define OMAP4430_RM_CPU1_CPU1_RSTCTRL			OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_CPU1_MOD, 0x000c)
-#define OMAP4_RM_CPU1_CPU1_RSTST_OFFSET			0x0010
-#define OMAP4430_RM_CPU1_CPU1_RSTST			OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_CPU1_MOD, 0x0010)
-#define OMAP4_CM_CPU1_CPU1_CLKCTRL_OFFSET		0x0014
-#define OMAP4430_CM_CPU1_CPU1_CLKCTRL			OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_CPU1_MOD, 0x0014)
-#define OMAP4_CM_CPU1_CLKSTCTRL_OFFSET			0x0018
-#define OMAP4430_CM_CPU1_CLKSTCTRL			OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_CPU1_MOD, 0x0018)
 #endif
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/prm.h linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/prm.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/prm.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/prm.h	2011-03-14 21:20:32.000000000 -0400
@@ -1,321 +1,20 @@
-#ifndef __ARCH_ARM_MACH_OMAP2_PRM_H
-#define __ARCH_ARM_MACH_OMAP2_PRM_H
-
 /*
- * OMAP2/3 Power/Reset Management (PRM) register definitions
+ * OMAP2/3/4 Power/Reset Management (PRM) bitfield definitions
  *
  * Copyright (C) 2007-2009 Texas Instruments, Inc.
  * Copyright (C) 2010 Nokia Corporation
  *
- * Written by Paul Walmsley
+ * Paul Walmsley
  *
  * This program is free software; you can 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_MACH_OMAP2_PRM_H
+#define __ARCH_ARM_MACH_OMAP2_PRM_H
 
 #include "prcm-common.h"
 
-#define OMAP2420_PRM_REGADDR(module, reg)				\
-		OMAP2_L4_IO_ADDRESS(OMAP2420_PRM_BASE + (module) + (reg))
-#define OMAP2430_PRM_REGADDR(module, reg)				\
-		OMAP2_L4_IO_ADDRESS(OMAP2430_PRM_BASE + (module) + (reg))
-#define OMAP34XX_PRM_REGADDR(module, reg)				\
-		OMAP2_L4_IO_ADDRESS(OMAP3430_PRM_BASE + (module) + (reg))
-#define OMAP44XX_PRM_REGADDR(module, reg)				\
-		OMAP2_L4_IO_ADDRESS(OMAP4430_PRM_BASE + (module) + (reg))
-#define OMAP44XX_PRCM_MPU_REGADDR(module, reg)				\
-		OMAP2_L4_IO_ADDRESS(OMAP4430_PRCM_MPU_BASE + (module) + (reg))
-
-#include "prm44xx.h"
-
-/*
- * Architecture-specific global PRM registers
- * Use __raw_{read,write}l() with these registers.
- *
- * With a few exceptions, these are the register names beginning with
- * PRCM_* on 24xx, and PRM_* on 34xx.  (The exceptions are the
- * IRQSTATUS and IRQENABLE bits.)
- *
- */
-
-#define OMAP2_PRCM_REVISION_OFFSET	0x0000
-#define OMAP2420_PRCM_REVISION		OMAP2420_PRM_REGADDR(OCP_MOD, 0x0000)
-#define OMAP2_PRCM_SYSCONFIG_OFFSET	0x0010
-#define OMAP2420_PRCM_SYSCONFIG		OMAP2420_PRM_REGADDR(OCP_MOD, 0x0010)
-
-#define OMAP2_PRCM_IRQSTATUS_MPU_OFFSET	0x0018
-#define OMAP2420_PRCM_IRQSTATUS_MPU	OMAP2420_PRM_REGADDR(OCP_MOD, 0x0018)
-#define OMAP2_PRCM_IRQENABLE_MPU_OFFSET	0x001c
-#define OMAP2420_PRCM_IRQENABLE_MPU	OMAP2420_PRM_REGADDR(OCP_MOD, 0x001c)
-
-#define OMAP2_PRCM_VOLTCTRL_OFFSET	0x0050
-#define OMAP2420_PRCM_VOLTCTRL		OMAP2420_PRM_REGADDR(OCP_MOD, 0x0050)
-#define OMAP2_PRCM_VOLTST_OFFSET	0x0054
-#define OMAP2420_PRCM_VOLTST		OMAP2420_PRM_REGADDR(OCP_MOD, 0x0054)
-#define OMAP2_PRCM_CLKSRC_CTRL_OFFSET	0x0060
-#define OMAP2420_PRCM_CLKSRC_CTRL	OMAP2420_PRM_REGADDR(OCP_MOD, 0x0060)
-#define OMAP2_PRCM_CLKOUT_CTRL_OFFSET	0x0070
-#define OMAP2420_PRCM_CLKOUT_CTRL	OMAP2420_PRM_REGADDR(OCP_MOD, 0x0070)
-#define OMAP2_PRCM_CLKEMUL_CTRL_OFFSET	0x0078
-#define OMAP2420_PRCM_CLKEMUL_CTRL	OMAP2420_PRM_REGADDR(OCP_MOD, 0x0078)
-#define OMAP2_PRCM_CLKCFG_CTRL_OFFSET	0x0080
-#define OMAP2420_PRCM_CLKCFG_CTRL	OMAP2420_PRM_REGADDR(OCP_MOD, 0x0080)
-#define OMAP2_PRCM_CLKCFG_STATUS_OFFSET	0x0084
-#define OMAP2420_PRCM_CLKCFG_STATUS	OMAP2420_PRM_REGADDR(OCP_MOD, 0x0084)
-#define OMAP2_PRCM_VOLTSETUP_OFFSET	0x0090
-#define OMAP2420_PRCM_VOLTSETUP		OMAP2420_PRM_REGADDR(OCP_MOD, 0x0090)
-#define OMAP2_PRCM_CLKSSETUP_OFFSET	0x0094
-#define OMAP2420_PRCM_CLKSSETUP		OMAP2420_PRM_REGADDR(OCP_MOD, 0x0094)
-#define OMAP2_PRCM_POLCTRL_OFFSET	0x0098
-#define OMAP2420_PRCM_POLCTRL		OMAP2420_PRM_REGADDR(OCP_MOD, 0x0098)
-
-#define OMAP2430_PRCM_REVISION		OMAP2430_PRM_REGADDR(OCP_MOD, 0x0000)
-#define OMAP2430_PRCM_SYSCONFIG		OMAP2430_PRM_REGADDR(OCP_MOD, 0x0010)
-
-#define OMAP2430_PRCM_IRQSTATUS_MPU	OMAP2430_PRM_REGADDR(OCP_MOD, 0x0018)
-#define OMAP2430_PRCM_IRQENABLE_MPU	OMAP2430_PRM_REGADDR(OCP_MOD, 0x001c)
-
-#define OMAP2430_PRCM_VOLTCTRL		OMAP2430_PRM_REGADDR(OCP_MOD, 0x0050)
-#define OMAP2430_PRCM_VOLTST		OMAP2430_PRM_REGADDR(OCP_MOD, 0x0054)
-#define OMAP2430_PRCM_CLKSRC_CTRL	OMAP2430_PRM_REGADDR(OCP_MOD, 0x0060)
-#define OMAP2430_PRCM_CLKOUT_CTRL	OMAP2430_PRM_REGADDR(OCP_MOD, 0x0070)
-#define OMAP2430_PRCM_CLKEMUL_CTRL	OMAP2430_PRM_REGADDR(OCP_MOD, 0x0078)
-#define OMAP2430_PRCM_CLKCFG_CTRL	OMAP2430_PRM_REGADDR(OCP_MOD, 0x0080)
-#define OMAP2430_PRCM_CLKCFG_STATUS	OMAP2430_PRM_REGADDR(OCP_MOD, 0x0084)
-#define OMAP2430_PRCM_VOLTSETUP		OMAP2430_PRM_REGADDR(OCP_MOD, 0x0090)
-#define OMAP2430_PRCM_CLKSSETUP		OMAP2430_PRM_REGADDR(OCP_MOD, 0x0094)
-#define OMAP2430_PRCM_POLCTRL		OMAP2430_PRM_REGADDR(OCP_MOD, 0x0098)
-
-#define OMAP3_PRM_REVISION_OFFSET	0x0004
-#define OMAP3430_PRM_REVISION		OMAP34XX_PRM_REGADDR(OCP_MOD, 0x0004)
-#define OMAP3_PRM_SYSCONFIG_OFFSET	0x0014
-#define OMAP3430_PRM_SYSCONFIG		OMAP34XX_PRM_REGADDR(OCP_MOD, 0x0014)
-
-#define OMAP3_PRM_IRQSTATUS_MPU_OFFSET	0x0018
-#define OMAP3430_PRM_IRQSTATUS_MPU	OMAP34XX_PRM_REGADDR(OCP_MOD, 0x0018)
-#define OMAP3_PRM_IRQENABLE_MPU_OFFSET	0x001c
-#define OMAP3430_PRM_IRQENABLE_MPU	OMAP34XX_PRM_REGADDR(OCP_MOD, 0x001c)
-
-
-#define OMAP3_PRM_VC_SMPS_SA_OFFSET	0x0020
-#define OMAP3430_PRM_VC_SMPS_SA		OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0020)
-#define OMAP3_PRM_VC_SMPS_VOL_RA_OFFSET	0x0024
-#define OMAP3430_PRM_VC_SMPS_VOL_RA	OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0024)
-#define OMAP3_PRM_VC_SMPS_CMD_RA_OFFSET	0x0028
-#define OMAP3430_PRM_VC_SMPS_CMD_RA	OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0028)
-#define OMAP3_PRM_VC_CMD_VAL_0_OFFSET	0x002c
-#define OMAP3430_PRM_VC_CMD_VAL_0	OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x002c)
-#define OMAP3_PRM_VC_CMD_VAL_1_OFFSET	0x0030
-#define OMAP3430_PRM_VC_CMD_VAL_1	OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0030)
-#define OMAP3_PRM_VC_CH_CONF_OFFSET	0x0034
-#define OMAP3430_PRM_VC_CH_CONF		OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0034)
-#define OMAP3_PRM_VC_I2C_CFG_OFFSET	0x0038
-#define OMAP3430_PRM_VC_I2C_CFG		OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0038)
-#define OMAP3_PRM_VC_BYPASS_VAL_OFFSET	0x003c
-#define OMAP3430_PRM_VC_BYPASS_VAL	OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x003c)
-#define OMAP3_PRM_RSTCTRL_OFFSET	0x0050
-#define OMAP3430_PRM_RSTCTRL		OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0050)
-#define OMAP3_PRM_RSTTIME_OFFSET	0x0054
-#define OMAP3430_PRM_RSTTIME		OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0054)
-#define OMAP3_PRM_RSTST_OFFSET	0x0058
-#define OMAP3430_PRM_RSTST		OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0058)
-#define OMAP3_PRM_VOLTCTRL_OFFSET	0x0060
-#define OMAP3430_PRM_VOLTCTRL		OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0060)
-#define OMAP3_PRM_SRAM_PCHARGE_OFFSET	0x0064
-#define OMAP3430_PRM_SRAM_PCHARGE	OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0064)
-#define OMAP3_PRM_CLKSRC_CTRL_OFFSET	0x0070
-#define OMAP3430_PRM_CLKSRC_CTRL	OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0070)
-#define OMAP3_PRM_VOLTSETUP1_OFFSET	0x0090
-#define OMAP3430_PRM_VOLTSETUP1		OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0090)
-#define OMAP3_PRM_VOLTOFFSET_OFFSET	0x0094
-#define OMAP3430_PRM_VOLTOFFSET		OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0094)
-#define OMAP3_PRM_CLKSETUP_OFFSET	0x0098
-#define OMAP3430_PRM_CLKSETUP		OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0098)
-#define OMAP3_PRM_POLCTRL_OFFSET	0x009c
-#define OMAP3430_PRM_POLCTRL		OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x009c)
-#define OMAP3_PRM_VOLTSETUP2_OFFSET	0x00a0
-#define OMAP3430_PRM_VOLTSETUP2		OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00a0)
-#define OMAP3_PRM_VP1_CONFIG_OFFSET	0x00b0
-#define OMAP3430_PRM_VP1_CONFIG		OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00b0)
-#define OMAP3_PRM_VP1_VSTEPMIN_OFFSET	0x00b4
-#define OMAP3430_PRM_VP1_VSTEPMIN	OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00b4)
-#define OMAP3_PRM_VP1_VSTEPMAX_OFFSET	0x00b8
-#define OMAP3430_PRM_VP1_VSTEPMAX	OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00b8)
-#define OMAP3_PRM_VP1_VLIMITTO_OFFSET	0x00bc
-#define OMAP3430_PRM_VP1_VLIMITTO	OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00bc)
-#define OMAP3_PRM_VP1_VOLTAGE_OFFSET	0x00c0
-#define OMAP3430_PRM_VP1_VOLTAGE	OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00c0)
-#define OMAP3_PRM_VP1_STATUS_OFFSET	0x00c4
-#define OMAP3430_PRM_VP1_STATUS		OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00c4)
-#define OMAP3_PRM_VP2_CONFIG_OFFSET	0x00d0
-#define OMAP3430_PRM_VP2_CONFIG		OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00d0)
-#define OMAP3_PRM_VP2_VSTEPMIN_OFFSET	0x00d4
-#define OMAP3430_PRM_VP2_VSTEPMIN	OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00d4)
-#define OMAP3_PRM_VP2_VSTEPMAX_OFFSET	0x00d8
-#define OMAP3430_PRM_VP2_VSTEPMAX	OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00d8)
-#define OMAP3_PRM_VP2_VLIMITTO_OFFSET	0x00dc
-#define OMAP3430_PRM_VP2_VLIMITTO	OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00dc)
-#define OMAP3_PRM_VP2_VOLTAGE_OFFSET	0x00e0
-#define OMAP3430_PRM_VP2_VOLTAGE	OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00e0)
-#define OMAP3_PRM_VP2_STATUS_OFFSET	0x00e4
-#define OMAP3430_PRM_VP2_STATUS		OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00e4)
-
-#define OMAP3_PRM_CLKSEL_OFFSET	0x0040
-#define OMAP3430_PRM_CLKSEL		OMAP34XX_PRM_REGADDR(OMAP3430_CCR_MOD, 0x0040)
-#define OMAP3_PRM_CLKOUT_CTRL_OFFSET	0x0070
-#define OMAP3430_PRM_CLKOUT_CTRL	OMAP34XX_PRM_REGADDR(OMAP3430_CCR_MOD, 0x0070)
-
-/*
- * Module specific PRM registers from PRM_BASE + domain offset
- *
- * Use prm_{read,write}_mod_reg() with these registers.
- *
- * With a few exceptions, these are the register names beginning with
- * {PM,RM}_* on both architectures.  (The exceptions are the IRQSTATUS
- * and IRQENABLE bits.)
- *
- */
-
-/* Registers appearing on both 24xx and 34xx */
-
-#define OMAP2_RM_RSTCTRL				0x0050
-#define OMAP2_RM_RSTTIME				0x0054
-#define OMAP2_RM_RSTST					0x0058
-#define OMAP2_PM_PWSTCTRL				0x00e0
-#define OMAP2_PM_PWSTST					0x00e4
-
-#define PM_WKEN						0x00a0
-#define PM_WKEN1					PM_WKEN
-#define PM_WKST						0x00b0
-#define PM_WKST1					PM_WKST
-#define PM_WKDEP					0x00c8
-#define PM_EVGENCTRL					0x00d4
-#define PM_EVGENONTIM					0x00d8
-#define PM_EVGENOFFTIM					0x00dc
-
-/* Omap2 specific registers */
-#define OMAP24XX_PM_WKEN2				0x00a4
-#define OMAP24XX_PM_WKST2				0x00b4
-
-#define OMAP24XX_PRCM_IRQSTATUS_DSP			0x00f0	/* IVA mod */
-#define OMAP24XX_PRCM_IRQENABLE_DSP			0x00f4	/* IVA mod */
-#define OMAP24XX_PRCM_IRQSTATUS_IVA			0x00f8
-#define OMAP24XX_PRCM_IRQENABLE_IVA			0x00fc
-
-/* Omap3 specific registers */
-#define OMAP3430ES2_PM_WKEN3				0x00f0
-#define OMAP3430ES2_PM_WKST3				0x00b8
-
-#define OMAP3430_PM_MPUGRPSEL				0x00a4
-#define OMAP3430_PM_MPUGRPSEL1				OMAP3430_PM_MPUGRPSEL
-#define OMAP3430ES2_PM_MPUGRPSEL3			0x00f8
-
-#define OMAP3430_PM_IVAGRPSEL				0x00a8
-#define OMAP3430_PM_IVAGRPSEL1				OMAP3430_PM_IVAGRPSEL
-#define OMAP3430ES2_PM_IVAGRPSEL3			0x00f4
-
-#define OMAP3430_PM_PREPWSTST				0x00e8
-
-#define OMAP3430_PRM_IRQSTATUS_IVA2			0x00f8
-#define OMAP3430_PRM_IRQENABLE_IVA2			0x00fc
-
-/* Omap4 specific registers */
-#define OMAP4_RM_RSTCTRL				0x0000
-#define OMAP4_RM_RSTTIME				0x0004
-#define OMAP4_RM_RSTST					0x0008
-#define OMAP4_PM_PWSTCTRL				0x0000
-#define OMAP4_PM_PWSTST					0x0004
-
-
-#ifndef __ASSEMBLER__
-
-/* Power/reset management domain register get/set */
-extern u32 prm_read_mod_reg(s16 module, u16 idx);
-extern void prm_write_mod_reg(u32 val, s16 module, u16 idx);
-extern u32 prm_rmw_mod_reg_bits(u32 mask, u32 bits, s16 module, s16 idx);
-
-/* Read-modify-write bits in a PRM register (by domain) */
-static inline u32 prm_set_mod_reg_bits(u32 bits, s16 module, s16 idx)
-{
-	return prm_rmw_mod_reg_bits(bits, bits, module, idx);
-}
-
-static inline u32 prm_clear_mod_reg_bits(u32 bits, s16 module, s16 idx)
-{
-	return prm_rmw_mod_reg_bits(bits, 0x0, module, idx);
-}
-
-/* These omap2_ PRM functions apply to both OMAP2 and 3 */
-int omap2_prm_is_hardreset_asserted(s16 prm_mod, u8 shift);
-int omap2_prm_assert_hardreset(s16 prm_mod, u8 shift);
-int omap2_prm_deassert_hardreset(s16 prm_mod, u8 shift);
-
-int omap4_prm_is_hardreset_asserted(void __iomem *rstctrl_reg, u8 shift);
-int omap4_prm_assert_hardreset(void __iomem *rstctrl_reg, u8 shift);
-int omap4_prm_deassert_hardreset(void __iomem *rstctrl_reg, u8 shift);
-
-#endif
-
-/*
- * Bits common to specific registers
- *
- * The 3430 register and bit names are generally used,
- * since they tend to make more sense
- */
-
-/* PM_EVGENONTIM_MPU */
-/* Named PM_EVEGENONTIM_MPU on the 24XX */
-#define OMAP_ONTIMEVAL_SHIFT				0
-#define OMAP_ONTIMEVAL_MASK				(0xffffffff << 0)
-
-/* PM_EVGENOFFTIM_MPU */
-/* Named PM_EVEGENOFFTIM_MPU on the 24XX */
-#define OMAP_OFFTIMEVAL_SHIFT				0
-#define OMAP_OFFTIMEVAL_MASK				(0xffffffff << 0)
-
-/* PRM_CLKSETUP and PRCM_VOLTSETUP */
-/* Named PRCM_CLKSSETUP on the 24XX */
-#define OMAP_SETUP_TIME_SHIFT				0
-#define OMAP_SETUP_TIME_MASK				(0xffff << 0)
-
-/* PRM_CLKSRC_CTRL */
-/* Named PRCM_CLKSRC_CTRL on the 24XX */
-#define OMAP_SYSCLKDIV_SHIFT				6
-#define OMAP_SYSCLKDIV_MASK				(0x3 << 6)
-#define OMAP_AUTOEXTCLKMODE_SHIFT			3
-#define OMAP_AUTOEXTCLKMODE_MASK			(0x3 << 3)
-#define OMAP_SYSCLKSEL_SHIFT				0
-#define OMAP_SYSCLKSEL_MASK				(0x3 << 0)
-
-/* PM_EVGENCTRL_MPU */
-#define OMAP_OFFLOADMODE_SHIFT				3
-#define OMAP_OFFLOADMODE_MASK				(0x3 << 3)
-#define OMAP_ONLOADMODE_SHIFT				1
-#define OMAP_ONLOADMODE_MASK				(0x3 << 1)
-#define OMAP_ENABLE_MASK				(1 << 0)
-
-/* PRM_RSTTIME */
-/* Named RM_RSTTIME_WKUP on the 24xx */
-#define OMAP_RSTTIME2_SHIFT				8
-#define OMAP_RSTTIME2_MASK				(0x1f << 8)
-#define OMAP_RSTTIME1_SHIFT				0
-#define OMAP_RSTTIME1_MASK				(0xff << 0)
-
-/* PRM_RSTCTRL */
-/* Named RM_RSTCTRL_WKUP on the 24xx */
-/* 2420 calls RST_DPLL3 'RST_DPLL' */
-#define OMAP_RST_DPLL3_MASK				(1 << 2)
-#define OMAP_RST_GS_MASK				(1 << 1)
-
-
-/*
- * Bits common to module-shared registers
- *
- * Not all registers of a particular type support all of these bits -
- * check TRM if you are unsure
- */
-
 /*
  * 24XX: PM_PWSTST_CORE, PM_PWSTST_GFX, PM_PWSTST_MPU, PM_PWSTST_DSP
  *
@@ -341,59 +40,6 @@ int omap4_prm_deassert_hardreset(void __
 #define OMAP_POWERSTATEST_MASK				(0x3 << 0)
 
 /*
- * 24XX: RM_RSTST_MPU and RM_RSTST_DSP - on 24XX, 'COREDOMAINWKUP_RST' is
- *	 called 'COREWKUP_RST'
- *
- * 3430: RM_RSTST_IVA2, RM_RSTST_MPU, RM_RSTST_GFX, RM_RSTST_DSS,
- *	 RM_RSTST_CAM, RM_RSTST_PER, RM_RSTST_NEON
- */
-#define OMAP_COREDOMAINWKUP_RST_MASK			(1 << 3)
-
-/*
- * 24XX: RM_RSTST_MPU, RM_RSTST_GFX, RM_RSTST_DSP
- *
- * 2430: RM_RSTST_MDM
- *
- * 3430: RM_RSTST_CORE, RM_RSTST_EMU
- */
-#define OMAP_DOMAINWKUP_RST_MASK			(1 << 2)
-
-/*
- * 24XX: RM_RSTST_MPU, RM_RSTST_WKUP, RM_RSTST_DSP
- *	 On 24XX, 'GLOBALWARM_RST' is called 'GLOBALWMPU_RST'.
- *
- * 2430: RM_RSTST_MDM
- *
- * 3430: RM_RSTST_CORE, RM_RSTST_EMU
- */
-#define OMAP_GLOBALWARM_RST_MASK			(1 << 1)
-#define OMAP_GLOBALCOLD_RST_MASK			(1 << 0)
-
-/*
- * 24XX: PM_WKDEP_GFX, PM_WKDEP_MPU, PM_WKDEP_CORE, PM_WKDEP_DSP
- *	 2420 TRM sometimes uses "EN_WAKEUP" instead of "EN_WKUP"
- *
- * 2430: PM_WKDEP_MDM
- *
- * 3430: PM_WKDEP_IVA2, PM_WKDEP_GFX, PM_WKDEP_DSS, PM_WKDEP_CAM,
- *	 PM_WKDEP_PER
- */
-#define OMAP_EN_WKUP_SHIFT				4
-#define OMAP_EN_WKUP_MASK				(1 << 4)
-
-/*
- * 24XX: PM_PWSTCTRL_MPU, PM_PWSTCTRL_CORE, PM_PWSTCTRL_GFX,
- *	 PM_PWSTCTRL_DSP
- *
- * 2430: PM_PWSTCTRL_MDM
- *
- * 3430: PM_PWSTCTRL_IVA2, PM_PWSTCTRL_CORE, PM_PWSTCTRL_GFX,
- *	 PM_PWSTCTRL_DSS, PM_PWSTCTRL_CAM, PM_PWSTCTRL_PER,
- *	 PM_PWSTCTRL_NEON
- */
-#define OMAP_LOGICRETSTATE_MASK				(1 << 2)
-
-/*
  * 24XX: PM_PWSTCTRL_MPU, PM_PWSTCTRL_CORE, PM_PWSTCTRL_GFX,
  *       PM_PWSTCTRL_DSP, PM_PWSTST_MPU
  *
@@ -407,11 +53,4 @@ int omap4_prm_deassert_hardreset(void __
 #define OMAP_POWERSTATE_MASK				(0x3 << 0)
 
 
-/*
- * MAX_MODULE_HARDRESET_WAIT: Maximum microseconds to wait for an OMAP
- * submodule to exit hardreset
- */
-#define MAX_MODULE_HARDRESET_WAIT		10000
-
-
 #endif
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/prminst44xx.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/prminst44xx.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/prminst44xx.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/prminst44xx.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,66 @@
+/*
+ * OMAP4 PRM instance functions
+ *
+ * Copyright (C) 2009 Nokia Corporation
+ * Paul Walmsley
+ *
+ * This program is free software; you can 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/errno.h>
+#include <linux/err.h>
+#include <linux/io.h>
+
+#include <plat/common.h>
+
+#include "prm44xx.h"
+#include "prminst44xx.h"
+#include "prm-regbits-44xx.h"
+#include "prcm44xx.h"
+#include "prcm_mpu44xx.h"
+
+static u32 _prm_bases[OMAP4_MAX_PRCM_PARTITIONS] = {
+	[OMAP4430_INVALID_PRCM_PARTITION]	= 0,
+	[OMAP4430_PRM_PARTITION]		= OMAP4430_PRM_BASE,
+	[OMAP4430_CM1_PARTITION]		= 0,
+	[OMAP4430_CM2_PARTITION]		= 0,
+	[OMAP4430_SCRM_PARTITION]		= 0,
+	[OMAP4430_PRCM_MPU_PARTITION]		= OMAP4430_PRCM_MPU_BASE,
+};
+
+/* Read a register in a PRM instance */
+u32 omap4_prminst_read_inst_reg(u8 part, s16 inst, u16 idx)
+{
+	BUG_ON(part >= OMAP4_MAX_PRCM_PARTITIONS ||
+	       part == OMAP4430_INVALID_PRCM_PARTITION ||
+	       !_prm_bases[part]);
+	return __raw_readl(OMAP2_L4_IO_ADDRESS(_prm_bases[part] + inst +
+					       idx));
+}
+
+/* Write into a register in a PRM instance */
+void omap4_prminst_write_inst_reg(u32 val, u8 part, s16 inst, u16 idx)
+{
+	BUG_ON(part >= OMAP4_MAX_PRCM_PARTITIONS ||
+	       part == OMAP4430_INVALID_PRCM_PARTITION ||
+	       !_prm_bases[part]);
+	__raw_writel(val, OMAP2_L4_IO_ADDRESS(_prm_bases[part] + inst + idx));
+}
+
+/* Read-modify-write a register in PRM. Caller must lock */
+u32 omap4_prminst_rmw_inst_reg_bits(u32 mask, u32 bits, u8 part, s16 inst,
+				   s16 idx)
+{
+	u32 v;
+
+	v = omap4_prminst_read_inst_reg(part, inst, idx);
+	v &= ~mask;
+	v |= bits;
+	omap4_prminst_write_inst_reg(v, part, inst, idx);
+
+	return v;
+}
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/prminst44xx.h linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/prminst44xx.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/prminst44xx.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/prminst44xx.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,25 @@
+/*
+ * OMAP4 Power/Reset Management (PRM) function prototypes
+ *
+ * Copyright (C) 2010 Nokia Corporation
+ * Paul Walmsley
+ *
+ * This program is free software; you can 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_ASM_MACH_OMAP2_PRMINST44XX_H
+#define __ARCH_ASM_MACH_OMAP2_PRMINST44XX_H
+
+/*
+ * In an ideal world, we would not export these low-level functions,
+ * but this will probably take some time to fix properly
+ */
+extern u32 omap4_prminst_read_inst_reg(u8 part, s16 inst, u16 idx);
+extern void omap4_prminst_write_inst_reg(u32 val, u8 part, s16 inst, u16 idx);
+extern u32 omap4_prminst_rmw_inst_reg_bits(u32 mask, u32 bits, u8 part,
+					   s16 inst, s16 idx);
+
+extern void omap4_prm_global_warm_sw_reset(void);
+
+#endif
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/prm-regbits-24xx.h linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/prm-regbits-24xx.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/prm-regbits-24xx.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/prm-regbits-24xx.h	2011-03-14 21:20:32.000000000 -0400
@@ -14,7 +14,7 @@
  * published by the Free Software Foundation.
  */
 
-#include "prm.h"
+#include "prm2xxx_3xxx.h"
 
 /* Bits shared between registers */
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/prm-regbits-34xx.h linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/prm-regbits-34xx.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/prm-regbits-34xx.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/prm-regbits-34xx.h	2011-03-14 21:20:32.000000000 -0400
@@ -1,6 +1,3 @@
-#ifndef __ARCH_ARM_MACH_OMAP2_PRM_REGBITS_34XX_H
-#define __ARCH_ARM_MACH_OMAP2_PRM_REGBITS_34XX_H
-
 /*
  * OMAP3430 Power/Reset Management register bits
  *
@@ -13,8 +10,11 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
+#ifndef __ARCH_ARM_MACH_OMAP2_PRM_REGBITS_34XX_H
+#define __ARCH_ARM_MACH_OMAP2_PRM_REGBITS_34XX_H
 
-#include "prm.h"
+
+#include "prm2xxx_3xxx.h"
 
 /* Shared register bits */
 
@@ -101,8 +101,11 @@
 #define OMAP3430_GRPSEL_MCSPI3_MASK			(1 << 20)
 #define OMAP3430_GRPSEL_MCSPI2_MASK			(1 << 19)
 #define OMAP3430_GRPSEL_MCSPI1_MASK			(1 << 18)
+#define OMAP3430_GRPSEL_I2C3_SHIFT			17
 #define OMAP3430_GRPSEL_I2C3_MASK			(1 << 17)
+#define OMAP3430_GRPSEL_I2C2_SHIFT			16
 #define OMAP3430_GRPSEL_I2C2_MASK			(1 << 16)
+#define OMAP3430_GRPSEL_I2C1_SHIFT			15
 #define OMAP3430_GRPSEL_I2C1_MASK			(1 << 15)
 #define OMAP3430_GRPSEL_UART2_MASK			(1 << 14)
 #define OMAP3430_GRPSEL_UART1_MASK			(1 << 13)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/prm-regbits-44xx.h linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/prm-regbits-44xx.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/prm-regbits-44xx.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/prm-regbits-44xx.h	2011-03-14 21:20:32.000000000 -0400
@@ -22,8 +22,6 @@
 #ifndef __ARCH_ARM_MACH_OMAP2_PRM_REGBITS_44XX_H
 #define __ARCH_ARM_MACH_OMAP2_PRM_REGBITS_44XX_H
 
-#include "prm.h"
-
 
 /*
  * Used by PRM_LDO_SRAM_CORE_SETUP, PRM_LDO_SRAM_IVA_SETUP,
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/scrm44xx.h linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/scrm44xx.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/scrm44xx.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/scrm44xx.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,175 @@
+/*
+ * OMAP44xx SCRM registers and bitfields
+ *
+ * Copyright (C) 2010 Texas Instruments, Inc.
+ *
+ * Benoit Cousson (b-cousson@ti.com)
+ *
+ * This file is automatically generated from the OMAP hardware databases.
+ * We respectfully ask that any modifications to this file be coordinated
+ * with the public linux-omap@vger.kernel.org mailing list and the
+ * authors above to ensure that the autogeneration scripts are kept
+ * up-to-date with the file contents.
+ *
+ * This program is free software; you can 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_MACH_OMAP2_SCRM_44XX_H
+#define __ARCH_ARM_MACH_OMAP2_SCRM_44XX_H
+
+#define OMAP4_SCRM_BASE				0x4a30a000
+
+#define OMAP44XX_SCRM_REGADDR(reg)	\
+		OMAP2_L4_IO_ADDRESS(OMAP4_SCRM_BASE + (reg))
+
+/* Registers offset */
+#define OMAP4_SCRM_REVISION_SCRM_OFFSET		0x0000
+#define OMAP4_SCRM_REVISION_SCRM		OMAP44XX_SCRM_REGADDR(0x0000)
+#define OMAP4_SCRM_CLKSETUPTIME_OFFSET		0x0100
+#define OMAP4_SCRM_CLKSETUPTIME			OMAP44XX_SCRM_REGADDR(0x0100)
+#define OMAP4_SCRM_PMICSETUPTIME_OFFSET		0x0104
+#define OMAP4_SCRM_PMICSETUPTIME		OMAP44XX_SCRM_REGADDR(0x0104)
+#define OMAP4_SCRM_ALTCLKSRC_OFFSET		0x0110
+#define OMAP4_SCRM_ALTCLKSRC			OMAP44XX_SCRM_REGADDR(0x0110)
+#define OMAP4_SCRM_MODEMCLKM_OFFSET		0x0118
+#define OMAP4_SCRM_MODEMCLKM			OMAP44XX_SCRM_REGADDR(0x0118)
+#define OMAP4_SCRM_D2DCLKM_OFFSET		0x011c
+#define OMAP4_SCRM_D2DCLKM			OMAP44XX_SCRM_REGADDR(0x011c)
+#define OMAP4_SCRM_EXTCLKREQ_OFFSET		0x0200
+#define OMAP4_SCRM_EXTCLKREQ			OMAP44XX_SCRM_REGADDR(0x0200)
+#define OMAP4_SCRM_ACCCLKREQ_OFFSET		0x0204
+#define OMAP4_SCRM_ACCCLKREQ			OMAP44XX_SCRM_REGADDR(0x0204)
+#define OMAP4_SCRM_PWRREQ_OFFSET		0x0208
+#define OMAP4_SCRM_PWRREQ			OMAP44XX_SCRM_REGADDR(0x0208)
+#define OMAP4_SCRM_AUXCLKREQ0_OFFSET		0x0210
+#define OMAP4_SCRM_AUXCLKREQ0			OMAP44XX_SCRM_REGADDR(0x0210)
+#define OMAP4_SCRM_AUXCLKREQ1_OFFSET		0x0214
+#define OMAP4_SCRM_AUXCLKREQ1			OMAP44XX_SCRM_REGADDR(0x0214)
+#define OMAP4_SCRM_AUXCLKREQ2_OFFSET		0x0218
+#define OMAP4_SCRM_AUXCLKREQ2			OMAP44XX_SCRM_REGADDR(0x0218)
+#define OMAP4_SCRM_AUXCLKREQ3_OFFSET		0x021c
+#define OMAP4_SCRM_AUXCLKREQ3			OMAP44XX_SCRM_REGADDR(0x021c)
+#define OMAP4_SCRM_AUXCLKREQ4_OFFSET		0x0220
+#define OMAP4_SCRM_AUXCLKREQ4			OMAP44XX_SCRM_REGADDR(0x0220)
+#define OMAP4_SCRM_AUXCLKREQ5_OFFSET		0x0224
+#define OMAP4_SCRM_AUXCLKREQ5			OMAP44XX_SCRM_REGADDR(0x0224)
+#define OMAP4_SCRM_D2DCLKREQ_OFFSET		0x0234
+#define OMAP4_SCRM_D2DCLKREQ			OMAP44XX_SCRM_REGADDR(0x0234)
+#define OMAP4_SCRM_AUXCLK0_OFFSET		0x0310
+#define OMAP4_SCRM_AUXCLK0			OMAP44XX_SCRM_REGADDR(0x0310)
+#define OMAP4_SCRM_AUXCLK1_OFFSET		0x0314
+#define OMAP4_SCRM_AUXCLK1			OMAP44XX_SCRM_REGADDR(0x0314)
+#define OMAP4_SCRM_AUXCLK2_OFFSET		0x0318
+#define OMAP4_SCRM_AUXCLK2			OMAP44XX_SCRM_REGADDR(0x0318)
+#define OMAP4_SCRM_AUXCLK3_OFFSET		0x031c
+#define OMAP4_SCRM_AUXCLK3			OMAP44XX_SCRM_REGADDR(0x031c)
+#define OMAP4_SCRM_AUXCLK4_OFFSET		0x0320
+#define OMAP4_SCRM_AUXCLK4			OMAP44XX_SCRM_REGADDR(0x0320)
+#define OMAP4_SCRM_AUXCLK5_OFFSET		0x0324
+#define OMAP4_SCRM_AUXCLK5			OMAP44XX_SCRM_REGADDR(0x0324)
+#define OMAP4_SCRM_RSTTIME_OFFSET		0x0400
+#define OMAP4_SCRM_RSTTIME			OMAP44XX_SCRM_REGADDR(0x0400)
+#define OMAP4_SCRM_MODEMRSTCTRL_OFFSET		0x0418
+#define OMAP4_SCRM_MODEMRSTCTRL			OMAP44XX_SCRM_REGADDR(0x0418)
+#define OMAP4_SCRM_D2DRSTCTRL_OFFSET		0x041c
+#define OMAP4_SCRM_D2DRSTCTRL			OMAP44XX_SCRM_REGADDR(0x041c)
+#define OMAP4_SCRM_EXTPWRONRSTCTRL_OFFSET	0x0420
+#define OMAP4_SCRM_EXTPWRONRSTCTRL		OMAP44XX_SCRM_REGADDR(0x0420)
+#define OMAP4_SCRM_EXTWARMRSTST_OFFSET		0x0510
+#define OMAP4_SCRM_EXTWARMRSTST			OMAP44XX_SCRM_REGADDR(0x0510)
+#define OMAP4_SCRM_APEWARMRSTST_OFFSET		0x0514
+#define OMAP4_SCRM_APEWARMRSTST			OMAP44XX_SCRM_REGADDR(0x0514)
+#define OMAP4_SCRM_MODEMWARMRSTST_OFFSET	0x0518
+#define OMAP4_SCRM_MODEMWARMRSTST		OMAP44XX_SCRM_REGADDR(0x0518)
+#define OMAP4_SCRM_D2DWARMRSTST_OFFSET		0x051c
+#define OMAP4_SCRM_D2DWARMRSTST			OMAP44XX_SCRM_REGADDR(0x051c)
+
+/* Registers shifts and masks */
+
+/* REVISION_SCRM */
+#define OMAP4_REV_SHIFT				0
+#define OMAP4_REV_MASK				(0xff << 0)
+
+/* CLKSETUPTIME */
+#define OMAP4_DOWNTIME_SHIFT			16
+#define OMAP4_DOWNTIME_MASK			(0x3f << 16)
+#define OMAP4_SETUPTIME_SHIFT			0
+#define OMAP4_SETUPTIME_MASK			(0xfff << 0)
+
+/* PMICSETUPTIME */
+#define OMAP4_WAKEUPTIME_SHIFT			16
+#define OMAP4_WAKEUPTIME_MASK			(0x3f << 16)
+#define OMAP4_SLEEPTIME_SHIFT			0
+#define OMAP4_SLEEPTIME_MASK			(0x3f << 0)
+
+/* ALTCLKSRC */
+#define OMAP4_ENABLE_EXT_SHIFT			3
+#define OMAP4_ENABLE_EXT_MASK			(1 << 3)
+#define OMAP4_ENABLE_INT_SHIFT			2
+#define OMAP4_ENABLE_INT_MASK			(1 << 2)
+#define OMAP4_ALTCLKSRC_MODE_SHIFT		0
+#define OMAP4_ALTCLKSRC_MODE_MASK		(0x3 << 0)
+
+/* MODEMCLKM */
+#define OMAP4_CLK_32KHZ_SHIFT			0
+#define OMAP4_CLK_32KHZ_MASK			(1 << 0)
+
+/* D2DCLKM */
+#define OMAP4_SYSCLK_SHIFT			1
+#define OMAP4_SYSCLK_MASK			(1 << 1)
+
+/* EXTCLKREQ */
+#define OMAP4_POLARITY_SHIFT			0
+#define OMAP4_POLARITY_MASK			(1 << 0)
+
+/* AUXCLKREQ0 */
+#define OMAP4_MAPPING_SHIFT			2
+#define OMAP4_MAPPING_MASK			(0x7 << 2)
+#define OMAP4_ACCURACY_SHIFT			1
+#define OMAP4_ACCURACY_MASK			(1 << 1)
+
+/* AUXCLK0 */
+#define OMAP4_CLKDIV_SHIFT			16
+#define OMAP4_CLKDIV_MASK			(0xf << 16)
+#define OMAP4_DISABLECLK_SHIFT			9
+#define OMAP4_DISABLECLK_MASK			(1 << 9)
+#define OMAP4_ENABLE_SHIFT			8
+#define OMAP4_ENABLE_MASK			(1 << 8)
+#define OMAP4_SRCSELECT_SHIFT			1
+#define OMAP4_SRCSELECT_MASK			(0x3 << 1)
+
+/* RSTTIME */
+#define OMAP4_RSTTIME_SHIFT			0
+#define OMAP4_RSTTIME_MASK			(0xf << 0)
+
+/* MODEMRSTCTRL */
+#define OMAP4_WARMRST_SHIFT			1
+#define OMAP4_WARMRST_MASK			(1 << 1)
+#define OMAP4_COLDRST_SHIFT			0
+#define OMAP4_COLDRST_MASK			(1 << 0)
+
+/* EXTPWRONRSTCTRL */
+#define OMAP4_PWRONRST_SHIFT			1
+#define OMAP4_PWRONRST_MASK			(1 << 1)
+#define OMAP4_ENABLE_EXTPWRONRSTCTRL_SHIFT	0
+#define OMAP4_ENABLE_EXTPWRONRSTCTRL_MASK	(1 << 0)
+
+/* EXTWARMRSTST */
+#define OMAP4_EXTWARMRSTST_SHIFT		0
+#define OMAP4_EXTWARMRSTST_MASK			(1 << 0)
+
+/* APEWARMRSTST */
+#define OMAP4_APEWARMRSTST_SHIFT		1
+#define OMAP4_APEWARMRSTST_MASK			(1 << 1)
+
+/* MODEMWARMRSTST */
+#define OMAP4_MODEMWARMRSTST_SHIFT		2
+#define OMAP4_MODEMWARMRSTST_MASK		(1 << 2)
+
+/* D2DWARMRSTST */
+#define OMAP4_D2DWARMRSTST_SHIFT		3
+#define OMAP4_D2DWARMRSTST_MASK			(1 << 3)
+
+#endif
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/sdram-nokia.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/sdram-nokia.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/sdram-nokia.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/sdram-nokia.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,279 @@
+/*
+ * SDRC register values for Nokia boards
+ *
+ * Copyright (C) 2008, 2010 Nokia Corporation
+ *
+ * Lauri Leukkunen <lauri.leukkunen@nokia.com>
+ *
+ * Original code by Juha Yrjola <juha.yrjola@solidboot.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/clk.h>
+#include <linux/err.h>
+#include <linux/io.h>
+
+#include <plat/io.h>
+#include <plat/common.h>
+#include <plat/clock.h>
+#include <plat/sdrc.h>
+
+#include "sdram-nokia.h"
+
+/* In picoseconds, except for tREF (ns), tXP, tCKE, tWTR (clks) */
+struct sdram_timings {
+	u32 casl;
+	u32 tDAL;
+	u32 tDPL;
+	u32 tRRD;
+	u32 tRCD;
+	u32 tRP;
+	u32 tRAS;
+	u32 tRC;
+	u32 tRFC;
+	u32 tXSR;
+
+	u32 tREF; /* in ns */
+
+	u32 tXP;
+	u32 tCKE;
+	u32 tWTR;
+};
+
+static const struct sdram_timings nokia_97dot6mhz_timings[] = {
+	{
+		.casl = 3,
+		.tDAL = 30725,
+		.tDPL = 15362,
+		.tRRD = 10241,
+		.tRCD = 20483,
+		.tRP = 15362,
+		.tRAS = 40967,
+		.tRC = 56330,
+		.tRFC = 138266,
+		.tXSR = 204839,
+
+		.tREF = 7798,
+
+		.tXP = 2,
+		.tCKE = 4,
+		.tWTR = 2,
+	},
+};
+
+static const struct sdram_timings nokia_166mhz_timings[] = {
+	{
+		.casl = 3,
+		.tDAL = 33000,
+		.tDPL = 15000,
+		.tRRD = 12000,
+		.tRCD = 22500,
+		.tRP = 18000,
+		.tRAS = 42000,
+		.tRC = 66000,
+		.tRFC = 138000,
+		.tXSR = 200000,
+
+		.tREF = 7800,
+
+		.tXP = 2,
+		.tCKE = 2,
+		.tWTR = 2
+	},
+};
+
+static const struct sdram_timings nokia_195dot2mhz_timings[] = {
+	{
+		.casl = 3,
+		.tDAL = 30725,
+		.tDPL = 15362,
+		.tRRD = 10241,
+		.tRCD = 20483,
+		.tRP = 15362,
+		.tRAS = 40967,
+		.tRC = 56330,
+		.tRFC = 138266,
+		.tXSR = 204839,
+
+		.tREF = 7752,
+
+		.tXP = 2,
+		.tCKE = 4,
+		.tWTR = 2,
+	},
+};
+
+static const struct {
+	long rate;
+	struct sdram_timings const *data;
+} nokia_timings[] = {
+	{ 83000000, nokia_166mhz_timings },
+	{ 97600000, nokia_97dot6mhz_timings },
+	{ 166000000, nokia_166mhz_timings },
+	{ 195200000, nokia_195dot2mhz_timings },
+};
+static struct omap_sdrc_params nokia_sdrc_params[ARRAY_SIZE(nokia_timings) + 1];
+
+static unsigned long sdrc_get_fclk_period(long rate)
+{
+	/* In picoseconds */
+	return 1000000000 / rate;
+}
+
+static unsigned int sdrc_ps_to_ticks(unsigned int time_ps, long rate)
+{
+	unsigned long tick_ps;
+
+	/* Calculate in picosecs to yield more exact results */
+	tick_ps = sdrc_get_fclk_period(rate);
+
+	return (time_ps + tick_ps - 1) / tick_ps;
+}
+#undef DEBUG
+#ifdef DEBUG
+static int set_sdrc_timing_regval(u32 *regval, int st_bit, int end_bit,
+				int ticks, long rate, const char *name)
+#else
+static int set_sdrc_timing_regval(u32 *regval, int st_bit, int end_bit,
+			       int ticks)
+#endif
+{
+	int mask, nr_bits;
+
+	nr_bits = end_bit - st_bit + 1;
+	if (ticks >= 1 << nr_bits)
+		return -1;
+	mask = (1 << nr_bits) - 1;
+	*regval &= ~(mask << st_bit);
+	*regval |= ticks << st_bit;
+#ifdef DEBUG
+	printk(KERN_INFO "SDRC %s: %i ticks %i ns\n", name, ticks,
+			(unsigned int)sdrc_get_fclk_period(rate) * ticks /
+			1000);
+#endif
+
+	return 0;
+}
+
+#ifdef DEBUG
+#define SDRC_SET_ONE(reg, st, end, field, rate) \
+	if (set_sdrc_timing_regval((reg), (st), (end), \
+			memory_timings->field, (rate), #field) < 0) \
+		err = -1;
+#else
+#define SDRC_SET_ONE(reg, st, end, field, rate) \
+	if (set_sdrc_timing_regval((reg), (st), (end), \
+			memory_timings->field) < 0) \
+		err = -1;
+#endif
+
+#ifdef DEBUG
+static int set_sdrc_timing_regval_ps(u32 *regval, int st_bit, int end_bit,
+				int time, long rate, const char *name)
+#else
+static int set_sdrc_timing_regval_ps(u32 *regval, int st_bit, int end_bit,
+				int time, long rate)
+#endif
+{
+	int ticks, ret;
+	ret = 0;
+
+	if (time == 0)
+		ticks = 0;
+	else
+		ticks = sdrc_ps_to_ticks(time, rate);
+
+#ifdef DEBUG
+	ret = set_sdrc_timing_regval(regval, st_bit, end_bit, ticks,
+				     rate, name);
+#else
+	ret = set_sdrc_timing_regval(regval, st_bit, end_bit, ticks);
+#endif
+
+	return ret;
+}
+
+#ifdef DEBUG
+#define SDRC_SET_ONE_PS(reg, st, end, field, rate) \
+	if (set_sdrc_timing_regval_ps((reg), (st), (end), \
+			memory_timings->field, \
+			(rate), #field) < 0) \
+		err = -1;
+
+#else
+#define SDRC_SET_ONE_PS(reg, st, end, field, rate) \
+	if (set_sdrc_timing_regval_ps((reg), (st), (end), \
+			memory_timings->field, (rate)) < 0) \
+		err = -1;
+#endif
+
+static int sdrc_timings(int id, long rate,
+			const struct sdram_timings *memory_timings)
+{
+	u32 ticks_per_ms;
+	u32 rfr, l;
+	u32 actim_ctrla = 0, actim_ctrlb = 0;
+	u32 rfr_ctrl;
+	int err = 0;
+	long l3_rate = rate / 1000;
+
+	SDRC_SET_ONE_PS(&actim_ctrla,  0,  4, tDAL, l3_rate);
+	SDRC_SET_ONE_PS(&actim_ctrla,  6,  8, tDPL, l3_rate);
+	SDRC_SET_ONE_PS(&actim_ctrla,  9, 11, tRRD, l3_rate);
+	SDRC_SET_ONE_PS(&actim_ctrla, 12, 14, tRCD, l3_rate);
+	SDRC_SET_ONE_PS(&actim_ctrla, 15, 17, tRP, l3_rate);
+	SDRC_SET_ONE_PS(&actim_ctrla, 18, 21, tRAS, l3_rate);
+	SDRC_SET_ONE_PS(&actim_ctrla, 22, 26, tRC, l3_rate);
+	SDRC_SET_ONE_PS(&actim_ctrla, 27, 31, tRFC, l3_rate);
+
+	SDRC_SET_ONE_PS(&actim_ctrlb,  0,  7, tXSR, l3_rate);
+
+	SDRC_SET_ONE(&actim_ctrlb,  8, 10, tXP, l3_rate);
+	SDRC_SET_ONE(&actim_ctrlb, 12, 14, tCKE, l3_rate);
+	SDRC_SET_ONE(&actim_ctrlb, 16, 17, tWTR, l3_rate);
+
+	ticks_per_ms = l3_rate;
+	rfr = memory_timings[0].tREF * ticks_per_ms / 1000000;
+	if (rfr > 65535 + 50)
+		rfr = 65535;
+	else
+		rfr -= 50;
+
+#ifdef DEBUG
+	printk(KERN_INFO "SDRC tREF: %i ticks\n", rfr);
+#endif
+
+	l = rfr << 8;
+	rfr_ctrl = l | 0x1; /* autorefresh, reload counter with 1xARCV */
+
+	nokia_sdrc_params[id].rate = rate;
+	nokia_sdrc_params[id].actim_ctrla = actim_ctrla;
+	nokia_sdrc_params[id].actim_ctrlb = actim_ctrlb;
+	nokia_sdrc_params[id].rfr_ctrl = rfr_ctrl;
+	nokia_sdrc_params[id].mr = 0x32;
+
+	nokia_sdrc_params[id + 1].rate = 0;
+
+	return err;
+}
+
+struct omap_sdrc_params *nokia_get_sdram_timings(void)
+{
+	int err = 0;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(nokia_timings); i++) {
+		err |= sdrc_timings(i, nokia_timings[i].rate,
+				       nokia_timings[i].data);
+		if (err)
+			pr_err("%s: error with rate %ld: %d\n", __func__,
+			       nokia_timings[i].rate, err);
+	}
+
+	return err ? NULL : nokia_sdrc_params;
+}
+
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/sdram-nokia.h linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/sdram-nokia.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/sdram-nokia.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/sdram-nokia.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,12 @@
+/*
+ * SDRC register values for Nokia boards
+ *
+ * Copyright (C) 2010 Nokia
+ *
+ * This program is free software; you can 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 omap_sdrc_params *nokia_get_sdram_timings(void);
+
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/sdrc2xxx.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/sdrc2xxx.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/sdrc2xxx.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/sdrc2xxx.c	2011-03-14 21:20:32.000000000 -0400
@@ -28,7 +28,7 @@
 #include <plat/clock.h>
 #include <plat/sram.h>
 
-#include "prm.h"
+#include "prm2xxx_3xxx.h"
 #include "clock.h"
 #include <plat/sdrc.h>
 #include "sdrc.h"
@@ -99,6 +99,10 @@ u32 omap2xxx_sdrc_reprogram(u32 level, u
 	m_type = omap2xxx_sdrc_get_type();
 
 	local_irq_save(flags);
+	/*
+	 * XXX These calls should be abstracted out through a
+	 * prm2xxx.c function
+	 */
 	if (cpu_is_omap2420())
 		__raw_writel(0xffff, OMAP2420_PRCM_VOLTSETUP);
 	else
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/sdrc.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/sdrc.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/sdrc.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/sdrc.c	2011-03-14 21:20:32.000000000 -0400
@@ -27,8 +27,6 @@
 #include <plat/clock.h>
 #include <plat/sram.h>
 
-#include "prm.h"
-
 #include <plat/sdrc.h>
 #include "sdrc.h"
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/sdrc.h linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/sdrc.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/sdrc.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/sdrc.h	2011-03-14 21:20:32.000000000 -0400
@@ -74,5 +74,4 @@ static inline u32 sms_read_reg(u16 reg)
  */
 #define SDRC_MPURATE_LOOPS		96
 
-
 #endif
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/serial.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/serial.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/serial.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/serial.c	2011-03-14 21:20:32.000000000 -0400
@@ -40,11 +40,12 @@
 #include <plat/omap_hwmod.h>
 #include <plat/omap_device.h>
 
-#include "prm.h"
+#include "prm2xxx_3xxx.h"
 #include "pm.h"
-#include "cm.h"
+#include "cm2xxx_3xxx.h"
 #include "prm-regbits-34xx.h"
 #include "control.h"
+#include "mux.h"
 
 #define UART_OMAP_NO_EMPTY_FIFO_READ_IP_REV	0x52
 #define UART_OMAP_WER		0x17	/* Wake-up enable register */
@@ -106,21 +107,16 @@ struct omap_uart_state {
 static LIST_HEAD(uart_list);
 static u8 num_uarts;
 
-/*
- * Since these idle/enable hooks are used in the idle path itself
- * which has interrupts disabled, use the non-locking versions of
- * the hwmod enable/disable functions.
- */
 static int uart_idle_hwmod(struct omap_device *od)
 {
-	_omap_hwmod_idle(od->hwmods[0]);
+	omap_hwmod_idle(od->hwmods[0]);
 
 	return 0;
 }
 
 static int uart_enable_hwmod(struct omap_device *od)
 {
-	_omap_hwmod_enable(od->hwmods[0]);
+	omap_hwmod_enable(od->hwmods[0]);
 
 	return 0;
 }
@@ -169,9 +165,9 @@ static inline void serial_write_reg(stru
 
 static inline void __init omap_uart_reset(struct omap_uart_state *uart)
 {
-	serial_write_reg(uart, UART_OMAP_MDR1, 0x07);
+	serial_write_reg(uart, UART_OMAP_MDR1, UART_OMAP_MDR1_DISABLE);
 	serial_write_reg(uart, UART_OMAP_SCR, 0x08);
-	serial_write_reg(uart, UART_OMAP_MDR1, 0x00);
+	serial_write_reg(uart, UART_OMAP_MDR1, UART_OMAP_MDR1_16X_MODE);
 }
 
 #if defined(CONFIG_PM) && defined(CONFIG_ARCH_OMAP3)
@@ -219,7 +215,7 @@ static void omap_uart_save_context(struc
 		return;
 
 	lcr = serial_read_reg(uart, UART_LCR);
-	serial_write_reg(uart, UART_LCR, 0xBF);
+	serial_write_reg(uart, UART_LCR, UART_LCR_CONF_MODE_B);
 	uart->dll = serial_read_reg(uart, UART_DLL);
 	uart->dlh = serial_read_reg(uart, UART_DLM);
 	serial_write_reg(uart, UART_LCR, lcr);
@@ -227,7 +223,7 @@ static void omap_uart_save_context(struc
 	uart->sysc = serial_read_reg(uart, UART_OMAP_SYSC);
 	uart->scr = serial_read_reg(uart, UART_OMAP_SCR);
 	uart->wer = serial_read_reg(uart, UART_OMAP_WER);
-	serial_write_reg(uart, UART_LCR, 0x80);
+	serial_write_reg(uart, UART_LCR, UART_LCR_CONF_MODE_A);
 	uart->mcr = serial_read_reg(uart, UART_MCR);
 	serial_write_reg(uart, UART_LCR, lcr);
 
@@ -247,32 +243,35 @@ static void omap_uart_restore_context(st
 	uart->context_valid = 0;
 
 	if (uart->errata & UART_ERRATA_i202_MDR1_ACCESS)
-		omap_uart_mdr1_errataset(uart, 0x07, 0xA0);
+		omap_uart_mdr1_errataset(uart, UART_OMAP_MDR1_DISABLE, 0xA0);
 	else
-		serial_write_reg(uart, UART_OMAP_MDR1, 0x7);
-	serial_write_reg(uart, UART_LCR, 0xBF); /* Config B mode */
+		serial_write_reg(uart, UART_OMAP_MDR1, UART_OMAP_MDR1_DISABLE);
+
+	serial_write_reg(uart, UART_LCR, UART_LCR_CONF_MODE_B);
 	efr = serial_read_reg(uart, UART_EFR);
 	serial_write_reg(uart, UART_EFR, UART_EFR_ECB);
 	serial_write_reg(uart, UART_LCR, 0x0); /* Operational mode */
 	serial_write_reg(uart, UART_IER, 0x0);
-	serial_write_reg(uart, UART_LCR, 0xBF); /* Config B mode */
+	serial_write_reg(uart, UART_LCR, UART_LCR_CONF_MODE_B);
 	serial_write_reg(uart, UART_DLL, uart->dll);
 	serial_write_reg(uart, UART_DLM, uart->dlh);
 	serial_write_reg(uart, UART_LCR, 0x0); /* Operational mode */
 	serial_write_reg(uart, UART_IER, uart->ier);
-	serial_write_reg(uart, UART_LCR, 0x80);
+	serial_write_reg(uart, UART_LCR, UART_LCR_CONF_MODE_A);
 	serial_write_reg(uart, UART_MCR, uart->mcr);
-	serial_write_reg(uart, UART_LCR, 0xBF); /* Config B mode */
+	serial_write_reg(uart, UART_LCR, UART_LCR_CONF_MODE_B);
 	serial_write_reg(uart, UART_EFR, efr);
 	serial_write_reg(uart, UART_LCR, UART_LCR_WLEN8);
 	serial_write_reg(uart, UART_OMAP_SCR, uart->scr);
 	serial_write_reg(uart, UART_OMAP_WER, uart->wer);
 	serial_write_reg(uart, UART_OMAP_SYSC, uart->sysc);
+
 	if (uart->errata & UART_ERRATA_i202_MDR1_ACCESS)
-		omap_uart_mdr1_errataset(uart, 0x00, 0xA1);
+		omap_uart_mdr1_errataset(uart, UART_OMAP_MDR1_16X_MODE, 0xA1);
 	else
 		/* UART 16x mode */
-		serial_write_reg(uart, UART_OMAP_MDR1, 0x00);
+		serial_write_reg(uart, UART_OMAP_MDR1,
+				UART_OMAP_MDR1_16X_MODE);
 }
 #else
 static inline void omap_uart_save_context(struct omap_uart_state *uart) {}
@@ -492,6 +491,7 @@ static void omap_uart_idle_init(struct o
 		u32 wk_mask = 0;
 		u32 padconf = 0;
 
+		/* XXX These PRM accesses do not belong here */
 		uart->wk_en = OMAP34XX_PRM_REGADDR(mod, PM_WKEN1);
 		uart->wk_st = OMAP34XX_PRM_REGADDR(mod, PM_WKST1);
 		switch (uart->num) {
@@ -695,16 +695,16 @@ void __init omap_serial_early_init(void)
 
 /**
  * omap_serial_init_port() - initialize single serial port
- * @port: serial port number (0-3)
+ * @bdata: port specific board data pointer
  *
- * This function initialies serial driver for given @port only.
+ * This function initialies serial driver for given port only.
  * Platforms can call this function instead of omap_serial_init()
  * if they don't plan to use all available UARTs as serial ports.
  *
  * Don't mix calls to omap_serial_init_port() and omap_serial_init(),
  * use only one of the two.
  */
-void __init omap_serial_init_port(int port)
+void __init omap_serial_init_port(struct omap_board_data *bdata)
 {
 	struct omap_uart_state *uart;
 	struct omap_hwmod *oh;
@@ -722,13 +722,15 @@ void __init omap_serial_init_port(int po
 	struct omap_uart_port_info omap_up;
 #endif
 
-	if (WARN_ON(port < 0))
+	if (WARN_ON(!bdata))
 		return;
-	if (WARN_ON(port >= num_uarts))
+	if (WARN_ON(bdata->id < 0))
+		return;
+	if (WARN_ON(bdata->id >= num_uarts))
 		return;
 
 	list_for_each_entry(uart, &uart_list, node)
-		if (port == uart->num)
+		if (bdata->id == uart->num)
 			break;
 
 	oh = uart->oh;
@@ -800,6 +802,8 @@ void __init omap_serial_init_port(int po
 	WARN(IS_ERR(od), "Could not build omap_device for %s: %s.\n",
 	     name, oh->name);
 
+	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;
@@ -808,7 +812,7 @@ void __init omap_serial_init_port(int po
 
 	oh->dev_attr = uart;
 
-	acquire_console_sem(); /* in case the earlycon is on the UART */
+	console_lock(); /* in case the earlycon is on the UART */
 
 	/*
 	 * Because of early UART probing, UART did not get idled
@@ -834,7 +838,7 @@ void __init omap_serial_init_port(int po
 	omap_uart_block_sleep(uart);
 	uart->timeout = DEFAULT_TIMEOUT;
 
-	release_console_sem();
+	console_unlock();
 
 	if ((cpu_is_omap34xx() && uart->padconf) ||
 	    (uart->wk_en && uart->wk_mask)) {
@@ -848,7 +852,7 @@ void __init omap_serial_init_port(int po
 }
 
 /**
- * omap_serial_init() - intialize all supported serial ports
+ * omap_serial_init() - initialize all supported serial ports
  *
  * Initializes all available UARTs as serial ports. Platforms
  * can call this function when they want to have default behaviour
@@ -857,7 +861,14 @@ void __init omap_serial_init_port(int po
 void __init omap_serial_init(void)
 {
 	struct omap_uart_state *uart;
+	struct omap_board_data bdata;
 
-	list_for_each_entry(uart, &uart_list, node)
-		omap_serial_init_port(uart->num);
+	list_for_each_entry(uart, &uart_list, node) {
+		bdata.id = uart->num;
+		bdata.flags = 0;
+		bdata.pads = NULL;
+		bdata.pads_cnt = 0;
+		omap_serial_init_port(&bdata);
+
+	}
 }
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/sleep34xx.S linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/sleep34xx.S
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/sleep34xx.S	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/sleep34xx.S	2011-03-14 21:20:32.000000000 -0400
@@ -1,6 +1,4 @@
 /*
- * linux/arch/arm/mach-omap2/sleep.S
- *
  * (C) Copyright 2007
  * Texas Instruments
  * Karthik Dasu <karthik-dp@ti.com>
@@ -26,28 +24,35 @@
  */
 #include <linux/linkage.h>
 #include <asm/assembler.h>
+#include <plat/sram.h>
 #include <mach/io.h>
 
-#include "cm.h"
-#include "prm.h"
+#include "cm2xxx_3xxx.h"
+#include "prm2xxx_3xxx.h"
 #include "sdrc.h"
 #include "control.h"
 
-#define SDRC_SCRATCHPAD_SEM_V	0xfa00291c
-
-#define PM_PREPWSTST_CORE_V	OMAP34XX_PRM_REGADDR(CORE_MOD, \
-				OMAP3430_PM_PREPWSTST)
-#define PM_PREPWSTST_CORE_P	0x48306AE8
-#define PM_PREPWSTST_MPU_V	OMAP34XX_PRM_REGADDR(MPU_MOD, \
-				OMAP3430_PM_PREPWSTST)
+/*
+ * Registers access definitions
+ */
+#define SDRC_SCRATCHPAD_SEM_OFFS	0xc
+#define SDRC_SCRATCHPAD_SEM_V	OMAP343X_SCRATCHPAD_REGADDR\
+					(SDRC_SCRATCHPAD_SEM_OFFS)
+#define PM_PREPWSTST_CORE_P	OMAP3430_PRM_BASE + CORE_MOD +\
+					OMAP3430_PM_PREPWSTST
 #define PM_PWSTCTRL_MPU_P	OMAP3430_PRM_BASE + MPU_MOD + OMAP2_PM_PWSTCTRL
 #define CM_IDLEST1_CORE_V	OMAP34XX_CM_REGADDR(CORE_MOD, CM_IDLEST1)
-#define SRAM_BASE_P		0x40200000
-#define CONTROL_STAT		0x480022F0
-#define SCRATCHPAD_MEM_OFFS	0x310 /* Move this as correct place is
-				       * available */
-#define SCRATCHPAD_BASE_P	(OMAP343X_CTRL_BASE + OMAP343X_CONTROL_MEM_WKUP\
-						+ SCRATCHPAD_MEM_OFFS)
+#define CM_IDLEST_CKGEN_V	OMAP34XX_CM_REGADDR(PLL_MOD, CM_IDLEST)
+#define SRAM_BASE_P		OMAP3_SRAM_PA
+#define CONTROL_STAT		OMAP343X_CTRL_BASE + OMAP343X_CONTROL_STATUS
+#define CONTROL_MEM_RTA_CTRL	(OMAP343X_CTRL_BASE +\
+					OMAP36XX_CONTROL_MEM_RTA_CTRL)
+
+/* Move this as correct place is available */
+#define SCRATCHPAD_MEM_OFFS	0x310
+#define SCRATCHPAD_BASE_P	(OMAP343X_CTRL_BASE +\
+					OMAP343X_CONTROL_MEM_WKUP +\
+					SCRATCHPAD_MEM_OFFS)
 #define SDRC_POWER_V		OMAP34XX_SDRC_REGADDR(SDRC_POWER)
 #define SDRC_SYSCONFIG_P	(OMAP343X_SDRC_BASE + SDRC_SYSCONFIG)
 #define SDRC_MR_0_P		(OMAP343X_SDRC_BASE + SDRC_MR_0)
@@ -59,48 +64,38 @@
 #define SDRC_DLLA_STATUS_V	OMAP34XX_SDRC_REGADDR(SDRC_DLLA_STATUS)
 #define SDRC_DLLA_CTRL_V	OMAP34XX_SDRC_REGADDR(SDRC_DLLA_CTRL)
 
-        .text
-/* Function to acquire the semaphore in scratchpad */
-ENTRY(lock_scratchpad_sem)
-	stmfd	sp!, {lr}	@ save registers on stack
-wait_sem:
-	mov	r0,#1
-	ldr	r1, sdrc_scratchpad_sem
-wait_loop:
-	ldr	r2, [r1]	@ load the lock value
-	cmp	r2, r0		@ is the lock free ?
-	beq	wait_loop	@ not free...
-	swp	r2, r0, [r1]	@ semaphore free so lock it and proceed
-	cmp	r2, r0		@ did we succeed ?
-	beq	wait_sem	@ no - try again
-	ldmfd	sp!, {pc}	@ restore regs and return
-sdrc_scratchpad_sem:
-        .word SDRC_SCRATCHPAD_SEM_V
-ENTRY(lock_scratchpad_sem_sz)
-        .word   . - lock_scratchpad_sem
 
-        .text
-/* Function to release the scratchpad semaphore */
-ENTRY(unlock_scratchpad_sem)
-	stmfd	sp!, {lr}	@ save registers on stack
-	ldr	r3, sdrc_scratchpad_sem
-	mov	r2,#0
-	str	r2,[r3]
-	ldmfd	sp!, {pc}	@ restore regs and return
-ENTRY(unlock_scratchpad_sem_sz)
-        .word   . - unlock_scratchpad_sem
+/*
+ * API functions
+ */
+
+/*
+ * The "get_*restore_pointer" functions are used to provide a
+ * physical restore address where the ROM code jumps while waking
+ * up from MPU OFF/OSWR state.
+ * The restore pointer is stored into the scratchpad.
+ */
 
 	.text
 /* Function call to get the restore pointer for resume from OFF */
 ENTRY(get_restore_pointer)
-        stmfd   sp!, {lr}     @ save registers on stack
+	stmfd	sp!, {lr}	@ save registers on stack
 	adr	r0, restore
-        ldmfd   sp!, {pc}     @ restore regs and return
+	ldmfd	sp!, {pc}	@ restore regs and return
 ENTRY(get_restore_pointer_sz)
-        .word   . - get_restore_pointer
+	.word	. - get_restore_pointer
 
 	.text
-/* Function call to get the restore pointer for for ES3 to resume from OFF */
+/* Function call to get the restore pointer for 3630 resume from OFF */
+ENTRY(get_omap3630_restore_pointer)
+	stmfd	sp!, {lr}	@ save registers on stack
+	adr	r0, restore_3630
+	ldmfd	sp!, {pc}	@ restore regs and return
+ENTRY(get_omap3630_restore_pointer_sz)
+	.word	. - get_omap3630_restore_pointer
+
+	.text
+/* Function call to get the restore pointer for ES3 to resume from OFF */
 ENTRY(get_es3_restore_pointer)
 	stmfd	sp!, {lr}	@ save registers on stack
 	adr	r0, restore_es3
@@ -108,54 +103,23 @@ ENTRY(get_es3_restore_pointer)
 ENTRY(get_es3_restore_pointer_sz)
 	.word	. - get_es3_restore_pointer
 
-ENTRY(es3_sdrc_fix)
-	ldr	r4, sdrc_syscfg		@ get config addr
-	ldr	r5, [r4]		@ get value
-	tst	r5, #0x100		@ is part access blocked
-	it	eq
-	biceq	r5, r5, #0x100		@ clear bit if set
-	str	r5, [r4]		@ write back change
-	ldr	r4, sdrc_mr_0		@ get config addr
-	ldr	r5, [r4]		@ get value
-	str	r5, [r4]		@ write back change
-	ldr	r4, sdrc_emr2_0		@ get config addr
-	ldr	r5, [r4]		@ get value
-	str	r5, [r4]		@ write back change
-	ldr	r4, sdrc_manual_0	@ get config addr
-	mov	r5, #0x2		@ autorefresh command
-	str	r5, [r4]		@ kick off refreshes
-	ldr	r4, sdrc_mr_1		@ get config addr
-	ldr	r5, [r4]		@ get value
-	str	r5, [r4]		@ write back change
-	ldr	r4, sdrc_emr2_1		@ get config addr
-	ldr	r5, [r4]		@ get value
-	str	r5, [r4]		@ write back change
-	ldr	r4, sdrc_manual_1	@ get config addr
-	mov	r5, #0x2		@ autorefresh command
-	str	r5, [r4]		@ kick off refreshes
-	bx	lr
-sdrc_syscfg:
-	.word	SDRC_SYSCONFIG_P
-sdrc_mr_0:
-	.word	SDRC_MR_0_P
-sdrc_emr2_0:
-	.word	SDRC_EMR2_0_P
-sdrc_manual_0:
-	.word	SDRC_MANUAL_0_P
-sdrc_mr_1:
-	.word	SDRC_MR_1_P
-sdrc_emr2_1:
-	.word	SDRC_EMR2_1_P
-sdrc_manual_1:
-	.word	SDRC_MANUAL_1_P
-ENTRY(es3_sdrc_fix_sz)
-	.word	. - es3_sdrc_fix
+	.text
+/*
+ * L2 cache needs to be toggled for stable OFF mode functionality on 3630.
+ * This function sets up a flag that will allow for this toggling to take
+ * place on 3630. Hopefully some version in the future may not need this.
+ */
+ENTRY(enable_omap3630_toggle_l2_on_restore)
+	stmfd	sp!, {lr}	@ save registers on stack
+	/* Setup so that we will disable and enable l2 */
+	mov	r1, #0x1
+	str	r1, l2dis_3630
+	ldmfd	sp!, {pc}	@ restore regs and return
 
+	.text
 /* Function to call rom code to save secure ram context */
 ENTRY(save_secure_ram_context)
 	stmfd	sp!, {r1-r12, lr}	@ save registers on stack
-save_secure_ram_debug:
-	/* b save_secure_ram_debug */	@ enable to debug save code
 	adr	r3, api_params		@ r3 points to parameters
 	str	r0, [r3,#0x4]		@ r0 has sdram address
 	ldr	r12, high_mask
@@ -185,35 +149,162 @@ ENTRY(save_secure_ram_context_sz)
 	.word	. - save_secure_ram_context
 
 /*
+ * ======================
+ * == Idle entry point ==
+ * ======================
+ */
+
+/*
  * Forces OMAP into idle state
  *
- * omap34xx_suspend() - This bit of code just executes the WFI
- * for normal idles.
+ * omap34xx_cpu_suspend() - This bit of code saves the CPU context if needed
+ * and executes the WFI instruction. Calling WFI effectively changes the
+ * power domains states to the desired target power states.
  *
- * Note: This code get's copied to internal SRAM at boot. When the OMAP
- *	 wakes up it continues execution at the point it went to sleep.
+ *
+ * Notes:
+ * - this code gets copied to internal SRAM at boot and after wake-up
+ *   from OFF mode. The execution pointer in SRAM is _omap_sram_idle.
+ * - when the OMAP wakes up it continues at different execution points
+ *   depending on the low power mode (non-OFF vs OFF modes),
+ *   cf. 'Resume path for xxx mode' comments.
  */
 ENTRY(omap34xx_cpu_suspend)
-	stmfd	sp!, {r0-r12, lr}		@ save registers on stack
-loop:
-	/*b	loop*/	@Enable to debug by stepping through code
-	/* r0 contains restore pointer in sdram */
-	/* r1 contains information about saving context */
-	ldr     r4, sdrc_power          @ read the SDRC_POWER register
-	ldr     r5, [r4]                @ read the contents of SDRC_POWER
-	orr     r5, r5, #0x40           @ enable self refresh on idle req
-	str     r5, [r4]                @ write back to SDRC_POWER register
+	stmfd	sp!, {r0-r12, lr}	@ save registers on stack
+
+	/*
+	 * r0 contains restore pointer in sdram
+	 * r1 contains information about saving context:
+	 *   0 - No context lost
+	 *   1 - Only L1 and logic lost
+	 *   2 - Only L2 lost
+	 *   3 - Both L1 and L2 lost
+	 */
 
+	/* Directly jump to WFI is the context save is not required */
 	cmp	r1, #0x0
-	/* If context save is required, do that and execute wfi */
-	bne	save_context_wfi
+	beq	omap3_do_wfi
+
+	/* Otherwise fall through to the save context code */
+save_context_wfi:
+	mov	r8, r0			@ Store SDRAM address in r8
+	mrc	p15, 0, r5, c1, c0, 1	@ Read Auxiliary Control Register
+	mov	r4, #0x1		@ Number of parameters for restore call
+	stmia	r8!, {r4-r5}		@ Push parameters for restore call
+	mrc	p15, 1, r5, c9, c0, 2	@ Read L2 AUX ctrl register
+	stmia	r8!, {r4-r5}		@ Push parameters for restore call
+
+        /* Check what that target sleep state is from r1 */
+	cmp	r1, #0x2		@ Only L2 lost, no need to save context
+	beq	clean_caches
+
+l1_logic_lost:
+	/* Store sp and spsr to SDRAM */
+	mov	r4, sp
+	mrs	r5, spsr
+	mov	r6, lr
+	stmia	r8!, {r4-r6}
+	/* Save all ARM registers */
+	/* Coprocessor access control register */
+	mrc	p15, 0, r6, c1, c0, 2
+	stmia	r8!, {r6}
+	/* TTBR0, TTBR1 and Translation table base control */
+	mrc	p15, 0, r4, c2, c0, 0
+	mrc	p15, 0, r5, c2, c0, 1
+	mrc	p15, 0, r6, c2, c0, 2
+	stmia	r8!, {r4-r6}
+	/*
+	 * Domain access control register, data fault status register,
+	 * and instruction fault status register
+	 */
+	mrc	p15, 0, r4, c3, c0, 0
+	mrc	p15, 0, r5, c5, c0, 0
+	mrc	p15, 0, r6, c5, c0, 1
+	stmia	r8!, {r4-r6}
+	/*
+	 * Data aux fault status register, instruction aux fault status,
+	 * data fault address register and instruction fault address register
+	 */
+	mrc	p15, 0, r4, c5, c1, 0
+	mrc	p15, 0, r5, c5, c1, 1
+	mrc	p15, 0, r6, c6, c0, 0
+	mrc	p15, 0, r7, c6, c0, 2
+	stmia	r8!, {r4-r7}
+	/*
+	 * user r/w thread and process ID, user r/o thread and process ID,
+	 * priv only thread and process ID, cache size selection
+	 */
+	mrc	p15, 0, r4, c13, c0, 2
+	mrc	p15, 0, r5, c13, c0, 3
+	mrc	p15, 0, r6, c13, c0, 4
+	mrc	p15, 2, r7, c0, c0, 0
+	stmia	r8!, {r4-r7}
+	/* Data TLB lockdown, instruction TLB lockdown registers */
+	mrc	p15, 0, r5, c10, c0, 0
+	mrc	p15, 0, r6, c10, c0, 1
+	stmia	r8!, {r5-r6}
+	/* Secure or non secure vector base address, FCSE PID, Context PID*/
+	mrc	p15, 0, r4, c12, c0, 0
+	mrc	p15, 0, r5, c13, c0, 0
+	mrc	p15, 0, r6, c13, c0, 1
+	stmia	r8!, {r4-r6}
+	/* Primary remap, normal remap registers */
+	mrc	p15, 0, r4, c10, c2, 0
+	mrc	p15, 0, r5, c10, c2, 1
+	stmia	r8!,{r4-r5}
+
+	/* Store current cpsr*/
+	mrs	r2, cpsr
+	stmia	r8!, {r2}
+
+	mrc	p15, 0, r4, c1, c0, 0
+	/* save control register */
+	stmia	r8!, {r4}
+
+clean_caches:
+	/*
+	 * Clean Data or unified cache to POU
+	 * How to invalidate only L1 cache???? - #FIX_ME#
+	 * mcr	p15, 0, r11, c7, c11, 1
+	 */
+	cmp	r1, #0x1 		@ Check whether L2 inval is required
+	beq	omap3_do_wfi
+
+clean_l2:
+	/*
+	 * 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
+	 */
+	ldr	r1, kernel_flush
+	mov	lr, pc
+	bx	r1
+
+omap3_do_wfi:
+	ldr	r4, sdrc_power		@ read the SDRC_POWER register
+	ldr	r5, [r4]		@ read the contents of SDRC_POWER
+	orr	r5, r5, #0x40		@ enable self refresh on idle req
+	str	r5, [r4]		@ write back to SDRC_POWER register
+
 	/* Data memory barrier and Data sync barrier */
 	mov	r1, #0
 	mcr	p15, 0, r1, c7, c10, 4
 	mcr	p15, 0, r1, c7, c10, 5
 
+/*
+ * ===================================
+ * == WFI instruction => Enter idle ==
+ * ===================================
+ */
 	wfi				@ wait for interrupt
 
+/*
+ * ===================================
+ * == Resume path for non-OFF modes ==
+ * ===================================
+ */
 	nop
 	nop
 	nop
@@ -226,9 +317,30 @@ loop:
 	nop
 	bl wait_sdrc_ok
 
-	ldmfd	sp!, {r0-r12, pc}		@ restore regs and return
+/*
+ * ===================================
+ * == Exit point from non-OFF modes ==
+ * ===================================
+ */
+	ldmfd	sp!, {r0-r12, pc}	@ restore regs and return
+
+
+/*
+ * ==============================
+ * == Resume path for OFF mode ==
+ * ==============================
+ */
+
+/*
+ * The restore_* functions are called by the ROM code
+ *  when back from WFI in OFF mode.
+ * Cf. the get_*restore_pointer functions.
+ *
+ *  restore_es3: applies to 34xx >= ES3.0
+ *  restore_3630: applies to 36xx
+ *  restore: common code for 3xxx
+ */
 restore_es3:
-	/*b restore_es3*/		@ Enable to debug restore code
 	ldr	r5, pm_prepwstst_core_p
 	ldr	r4, [r5]
 	and	r4, r4, #0x3
@@ -245,82 +357,117 @@ copy_to_sram:
 	bne	copy_to_sram
 	ldr	r1, sram_base
 	blx	r1
+	b	restore
+
+restore_3630:
+	ldr	r1, pm_prepwstst_core_p
+	ldr	r2, [r1]
+	and	r2, r2, #0x3
+	cmp	r2, #0x0	@ Check if previous power state of CORE is OFF
+	bne	restore
+	/* Disable RTA before giving control */
+	ldr	r1, control_mem_rta
+	mov	r2, #OMAP36XX_RTA_DISABLE
+	str	r2, [r1]
+
+	/* Fall through to common code for the remaining logic */
+
 restore:
-	/* b restore*/  @ Enable to debug restore code
-        /* Check what was the reason for mpu reset and store the reason in r9*/
-        /* 1 - Only L1 and logic lost */
-        /* 2 - Only L2 lost - In this case, we wont be here */
-        /* 3 - Both L1 and L2 lost */
-	ldr     r1, pm_pwstctrl_mpu
+	/*
+	 * Check what was the reason for mpu reset and store the reason in r9:
+	 *  0 - No context lost
+	 *  1 - Only L1 and logic lost
+	 *  2 - Only L2 lost - In this case, we wont be here
+	 *  3 - Both L1 and L2 lost
+	 */
+	ldr	r1, pm_pwstctrl_mpu
 	ldr	r2, [r1]
-	and     r2, r2, #0x3
-	cmp     r2, #0x0	@ Check if target power state was OFF or RET
-        moveq   r9, #0x3        @ MPU OFF => L1 and L2 lost
+	and	r2, r2, #0x3
+	cmp	r2, #0x0	@ Check if target power state was OFF or RET
+	moveq	r9, #0x3	@ MPU OFF => L1 and L2 lost
 	movne	r9, #0x1	@ Only L1 and L2 lost => avoid L2 invalidation
 	bne	logic_l1_restore
+
+	ldr	r0, l2dis_3630
+	cmp	r0, #0x1	@ should we disable L2 on 3630?
+	bne	skipl2dis
+	mrc	p15, 0, r0, c1, c0, 1
+	bic	r0, r0, #2	@ disable L2 cache
+	mcr	p15, 0, r0, c1, c0, 1
+skipl2dis:
 	ldr	r0, control_stat
 	ldr	r1, [r0]
 	and	r1, #0x700
 	cmp	r1, #0x300
 	beq	l2_inv_gp
-	mov	r0, #40		@ set service ID for PPA
-	mov	r12, r0		@ copy secure Service ID in r12
-	mov	r1, #0		@ set task id for ROM code in r1
-	mov	r2, #4		@ set some flags in r2, r6
+	mov	r0, #40			@ set service ID for PPA
+	mov	r12, r0			@ copy secure Service ID in r12
+	mov	r1, #0			@ set task id for ROM code in r1
+	mov	r2, #4			@ set some flags in r2, r6
 	mov	r6, #0xff
 	adr	r3, l2_inv_api_params	@ r3 points to dummy parameters
 	mcr	p15, 0, r0, c7, c10, 4	@ data write barrier
 	mcr	p15, 0, r0, c7, c10, 5	@ data memory barrier
 	.word	0xE1600071		@ call SMI monitor (smi #1)
 	/* Write to Aux control register to set some bits */
-	mov	r0, #42		@ set service ID for PPA
-	mov	r12, r0		@ copy secure Service ID in r12
-	mov	r1, #0		@ set task id for ROM code in r1
-	mov	r2, #4		@ set some flags in r2, r6
+	mov	r0, #42			@ set service ID for PPA
+	mov	r12, r0			@ copy secure Service ID in r12
+	mov	r1, #0			@ set task id for ROM code in r1
+	mov	r2, #4			@ set some flags in r2, r6
 	mov	r6, #0xff
 	ldr	r4, scratchpad_base
-	ldr	r3, [r4, #0xBC]	@ r3 points to parameters
+	ldr	r3, [r4, #0xBC]		@ r3 points to parameters
 	mcr	p15, 0, r0, c7, c10, 4	@ data write barrier
 	mcr	p15, 0, r0, c7, c10, 5	@ data memory barrier
 	.word	0xE1600071		@ call SMI monitor (smi #1)
 
 #ifdef CONFIG_OMAP3_L2_AUX_SECURE_SAVE_RESTORE
 	/* Restore L2 aux control register */
-	@ set service ID for PPA
+					@ set service ID for PPA
 	mov	r0, #CONFIG_OMAP3_L2_AUX_SECURE_SERVICE_SET_ID
-	mov	r12, r0		@ copy service ID in r12
-	mov	r1, #0		@ set task ID for ROM code in r1
-	mov	r2, #4		@ set some flags in r2, r6
+	mov	r12, r0			@ copy service ID in r12
+	mov	r1, #0			@ set task ID for ROM code in r1
+	mov	r2, #4			@ set some flags in r2, r6
 	mov	r6, #0xff
 	ldr	r4, scratchpad_base
 	ldr	r3, [r4, #0xBC]
-	adds	r3, r3, #8	@ r3 points to parameters
+	adds	r3, r3, #8		@ r3 points to parameters
 	mcr	p15, 0, r0, c7, c10, 4	@ data write barrier
 	mcr	p15, 0, r0, c7, c10, 5	@ data memory barrier
 	.word	0xE1600071		@ call SMI monitor (smi #1)
 #endif
 	b	logic_l1_restore
+
 l2_inv_api_params:
-	.word   0x1, 0x00
+	.word	0x1, 0x00
 l2_inv_gp:
 	/* Execute smi to invalidate L2 cache */
-	mov r12, #0x1                         @ set up to invalide L2
-smi:    .word 0xE1600070		@ Call SMI monitor (smieq)
+	mov r12, #0x1			@ set up to invalidate L2
+	.word 0xE1600070		@ Call SMI monitor (smieq)
 	/* Write to Aux control register to set some bits */
 	ldr	r4, scratchpad_base
 	ldr	r3, [r4,#0xBC]
 	ldr	r0, [r3,#4]
 	mov	r12, #0x3
-	.word 0xE1600070	@ Call SMI monitor (smieq)
+	.word	0xE1600070		@ Call SMI monitor (smieq)
 	ldr	r4, scratchpad_base
 	ldr	r3, [r4,#0xBC]
 	ldr	r0, [r3,#12]
 	mov	r12, #0x2
-	.word 0xE1600070	@ Call SMI monitor (smieq)
+	.word	0xE1600070		@ Call SMI monitor (smieq)
 logic_l1_restore:
+	ldr	r1, l2dis_3630
+	cmp	r1, #0x1		@ Test if L2 re-enable needed on 3630
+	bne	skipl2reen
+	mrc	p15, 0, r1, c1, c0, 1
+	orr	r1, r1, #2		@ re-enable L2 cache
+	mcr	p15, 0, r1, c1, c0, 1
+skipl2reen:
 	mov	r1, #0
-	/* Invalidate all instruction caches to PoU
-	 * and flush branch target cache */
+	/*
+	 * Invalidate all instruction caches to PoU
+	 * and flush branch target cache
+	 */
 	mcr	p15, 0, r1, c7, c5, 0
 
 	ldr	r4, scratchpad_base
@@ -341,33 +488,33 @@ logic_l1_restore:
 	MCR p15, 0, r6, c2, c0, 1
 	/* Translation table base control register */
 	MCR p15, 0, r7, c2, c0, 2
-	/*domain access Control Register */
+	/* Domain access Control Register */
 	MCR p15, 0, r8, c3, c0, 0
-	/* data fault status Register */
+	/* Data fault status Register */
 	MCR p15, 0, r9, c5, c0, 0
 
-	ldmia  r3!,{r4-r8}
-	/* instruction fault status Register */
+	ldmia	r3!,{r4-r8}
+	/* Instruction fault status Register */
 	MCR p15, 0, r4, c5, c0, 1
-	/*Data Auxiliary Fault Status Register */
+	/* Data Auxiliary Fault Status Register */
 	MCR p15, 0, r5, c5, c1, 0
-	/*Instruction Auxiliary Fault Status Register*/
+	/* Instruction Auxiliary Fault Status Register*/
 	MCR p15, 0, r6, c5, c1, 1
-	/*Data Fault Address Register */
+	/* Data Fault Address Register */
 	MCR p15, 0, r7, c6, c0, 0
-	/*Instruction Fault Address Register*/
+	/* Instruction Fault Address Register*/
 	MCR p15, 0, r8, c6, c0, 2
-	ldmia  r3!,{r4-r7}
+	ldmia	r3!,{r4-r7}
 
-	/* user r/w thread and process ID */
+	/* User r/w thread and process ID */
 	MCR p15, 0, r4, c13, c0, 2
-	/* user ro thread and process ID */
+	/* User ro thread and process ID */
 	MCR p15, 0, r5, c13, c0, 3
-	/*Privileged only thread and process ID */
+	/* Privileged only thread and process ID */
 	MCR p15, 0, r6, c13, c0, 4
-	/* cache size selection */
+	/* Cache size selection */
 	MCR p15, 2, r7, c0, c0, 0
-	ldmia  r3!,{r4-r8}
+	ldmia	r3!,{r4-r8}
 	/* Data TLB lockdown registers */
 	MCR p15, 0, r4, c10, c0, 0
 	/* Instruction TLB lockdown registers */
@@ -379,26 +526,27 @@ logic_l1_restore:
 	/* Context PID */
 	MCR p15, 0, r8, c13, c0, 1
 
-	ldmia  r3!,{r4-r5}
-	/* primary memory remap register */
+	ldmia	r3!,{r4-r5}
+	/* Primary memory remap register */
 	MCR p15, 0, r4, c10, c2, 0
-	/*normal memory remap register */
+	/* Normal memory remap register */
 	MCR p15, 0, r5, c10, c2, 1
 
 	/* Restore cpsr */
-	ldmia	r3!,{r4}	/*load CPSR from SDRAM*/
-	msr	cpsr, r4	/*store cpsr */
+	ldmia	r3!,{r4}		@ load CPSR from SDRAM
+	msr	cpsr, r4		@ store cpsr
 
 	/* Enabling MMU here */
-	mrc	p15, 0, r7, c2, c0, 2 /* Read TTBRControl */
-	/* Extract N (0:2) bits and decide whether to use TTBR0 or TTBR1*/
+	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
-	*/
+	/*
+	 * 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
 usettbr0:
 	mrc	p15, 0, r2, c2, c0, 0
@@ -406,21 +554,25 @@ usettbr0:
 	and	r2, r5
 	mov	r4, pc
 	ldr	r5, table_index_mask
-	and	r4, r5 /* r4 = 31 to 20 bits of pc */
+	and	r4, r5			@ r4 = 31 to 20 bits of pc
 	/* Extract the value to be written to table entry */
 	ldr	r1, table_entry
-	add	r1, r1, r4 /* r1 has value to be written to table entry*/
+	/* r1 has the value to be written to table entry*/
+	add	r1, r1, r4
 	/* Getting the address of table entry to modify */
 	lsr	r4, #18
-	add	r2, r4 /* r2 has the location which needs to be modified */
+	/* r2 has the location which needs to be modified */
+	add	r2, r4
 	/* Storing previous entry of location being modified */
 	ldr	r5, scratchpad_base
 	ldr	r4, [r2]
 	str	r4, [r5, #0xC0]
 	/* Modify the table entry */
 	str	r1, [r2]
-	/* Storing address of entry being modified
-	 * - will be restored after enabling MMU */
+	/*
+	 * Storing address of entry being modified
+	 * - will be restored after enabling MMU
+	 */
 	ldr	r5, scratchpad_base
 	str	r2, [r5, #0xC4]
 
@@ -429,8 +581,11 @@ usettbr0:
 	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  but dont enable caches here*/
-	/* Caches will be enabled after restoring MMU table entry */
+	/*
+	 * 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}
 	/* Store previous value of control register in scratchpad */
 	str	r4, [r5, #0xC8]
@@ -438,212 +593,144 @@ usettbr0:
 	and	r4, r2
 	mcr	p15, 0, r4, c1, c0, 0
 
-	ldmfd	sp!, {r0-r12, pc}		@ restore regs and return
-save_context_wfi:
-	/*b	save_context_wfi*/	@ enable to debug save code
-	mov	r8, r0 /* Store SDRAM address in r8 */
-	mrc	p15, 0, r5, c1, c0, 1	@ Read Auxiliary Control Register
-	mov	r4, #0x1		@ Number of parameters for restore call
-	stmia	r8!, {r4-r5}		@ Push parameters for restore call
-	mrc	p15, 1, r5, c9, c0, 2	@ Read L2 AUX ctrl register
-	stmia	r8!, {r4-r5}		@ Push parameters for restore call
-        /* Check what that target sleep state is:stored in r1*/
-        /* 1 - Only L1 and logic lost */
-        /* 2 - Only L2 lost */
-        /* 3 - Both L1 and L2 lost */
-	cmp	r1, #0x2 /* Only L2 lost */
-	beq	clean_l2
-	cmp	r1, #0x1 /* L2 retained */
-	/* r9 stores whether to clean L2 or not*/
-	moveq	r9, #0x0 /* Dont Clean L2 */
-	movne	r9, #0x1 /* Clean L2 */
-l1_logic_lost:
-	/* Store sp and spsr to SDRAM */
-	mov	r4, sp
-	mrs	r5, spsr
-	mov	r6, lr
-	stmia	r8!, {r4-r6}
-	/* Save all ARM registers */
-	/* Coprocessor access control register */
-	mrc	p15, 0, r6, c1, c0, 2
-	stmia	r8!, {r6}
-	/* TTBR0, TTBR1 and Translation table base control */
-	mrc	p15, 0, r4, c2, c0, 0
-	mrc	p15, 0, r5, c2, c0, 1
-	mrc	p15, 0, r6, c2, c0, 2
-	stmia	r8!, {r4-r6}
-	/* Domain access control register, data fault status register,
-	and instruction fault status register */
-	mrc	p15, 0, r4, c3, c0, 0
-	mrc	p15, 0, r5, c5, c0, 0
-	mrc	p15, 0, r6, c5, c0, 1
-	stmia	r8!, {r4-r6}
-	/* Data aux fault status register, instruction aux fault status,
-	datat fault address register and instruction fault address register*/
-	mrc	p15, 0, r4, c5, c1, 0
-	mrc	p15, 0, r5, c5, c1, 1
-	mrc	p15, 0, r6, c6, c0, 0
-	mrc	p15, 0, r7, c6, c0, 2
-	stmia	r8!, {r4-r7}
-	/* user r/w thread and process ID, user r/o thread and process ID,
-	priv only thread and process ID, cache size selection */
-	mrc	p15, 0, r4, c13, c0, 2
-	mrc	p15, 0, r5, c13, c0, 3
-	mrc	p15, 0, r6, c13, c0, 4
-	mrc	p15, 2, r7, c0, c0, 0
-	stmia	r8!, {r4-r7}
-	/* Data TLB lockdown, instruction TLB lockdown registers */
-	mrc	p15, 0, r5, c10, c0, 0
-	mrc	p15, 0, r6, c10, c0, 1
-	stmia	r8!, {r5-r6}
-	/* Secure or non secure vector base address, FCSE PID, Context PID*/
-	mrc	p15, 0, r4, c12, c0, 0
-	mrc	p15, 0, r5, c13, c0, 0
-	mrc	p15, 0, r6, c13, c0, 1
-	stmia	r8!, {r4-r6}
-	/* Primary remap, normal remap registers */
-	mrc	p15, 0, r4, c10, c2, 0
-	mrc	p15, 0, r5, c10, c2, 1
-	stmia	r8!,{r4-r5}
+/*
+ * ==============================
+ * == Exit point from OFF mode ==
+ * ==============================
+ */
+	ldmfd	sp!, {r0-r12, pc}	@ restore regs and return
 
-	/* Store current cpsr*/
-	mrs	r2, cpsr
-	stmia	r8!, {r2}
 
-	mrc	p15, 0, r4, c1, c0, 0
-	/* save control register */
-	stmia	r8!, {r4}
-clean_caches:
-	/* Clean Data or unified cache to POU*/
-	/* How to invalidate only L1 cache???? - #FIX_ME# */
-	/* mcr	p15, 0, r11, c7, c11, 1 */
-	cmp	r9, #1 /* Check whether L2 inval is required or not*/
-	bne	skip_l2_inval
-clean_l2:
-	/* read clidr */
-	mrc     p15, 1, r0, c0, c0, 1
-	/* extract loc from clidr */
-	ands    r3, r0, #0x7000000
-	/* left align loc bit field */
-	mov     r3, r3, lsr #23
-	/* if loc is 0, then no need to clean */
-	beq     finished
-	/* start clean at cache level 0 */
-	mov     r10, #0
-loop1:
-	/* work out 3x current cache level */
-	add     r2, r10, r10, lsr #1
-	/* extract cache type bits from clidr*/
-	mov     r1, r0, lsr r2
-	/* mask of the bits for current cache only */
-	and     r1, r1, #7
-	/* see what cache we have at this level */
-	cmp     r1, #2
-	/* skip if no cache, or just i-cache */
-	blt     skip
-	/* select current cache level in cssr */
-	mcr     p15, 2, r10, c0, c0, 0
-	/* isb to sych the new cssr&csidr */
-	isb
-	/* read the new csidr */
-	mrc     p15, 1, r1, c0, c0, 0
-	/* extract the length of the cache lines */
-	and     r2, r1, #7
-	/* add 4 (line length offset) */
-	add     r2, r2, #4
-	ldr     r4, assoc_mask
-	/* find maximum number on the way size */
-	ands    r4, r4, r1, lsr #3
-	/* find bit position of way size increment */
-	clz     r5, r4
-	ldr     r7, numset_mask
-	/* extract max number of the index size*/
-	ands    r7, r7, r1, lsr #13
-loop2:
-	mov     r9, r4
-	/* create working copy of max way size*/
-loop3:
-	/* factor way and cache number into r11 */
-	orr     r11, r10, r9, lsl r5
-	/* factor index number into r11 */
-	orr     r11, r11, r7, lsl r2
-	/*clean & invalidate by set/way */
-	mcr     p15, 0, r11, c7, c10, 2
-	/* decrement the way*/
-	subs    r9, r9, #1
-	bge     loop3
-	/*decrement the index */
-	subs    r7, r7, #1
-	bge     loop2
-skip:
-	add     r10, r10, #2
-	/* increment cache number */
-	cmp     r3, r10
-	bgt     loop1
-finished:
-	/*swith back to cache level 0 */
-	mov     r10, #0
-	/* select current cache level in cssr */
-	mcr     p15, 2, r10, c0, c0, 0
-	isb
-skip_l2_inval:
-	/* Data memory barrier and Data sync barrier */
-	mov     r1, #0
-	mcr     p15, 0, r1, c7, c10, 4
-	mcr     p15, 0, r1, c7, c10, 5
+/*
+ * Internal functions
+ */
 
-	wfi                             @ wait for interrupt
-	nop
-	nop
-	nop
-	nop
-	nop
-	nop
-	nop
-	nop
-	nop
-	nop
-	bl wait_sdrc_ok
-	/* restore regs and return */
-	ldmfd   sp!, {r0-r12, pc}
+/* This function implements the erratum ID i443 WA, applies to 34xx >= ES3.0 */
+	.text
+ENTRY(es3_sdrc_fix)
+	ldr	r4, sdrc_syscfg		@ get config addr
+	ldr	r5, [r4]		@ get value
+	tst	r5, #0x100		@ is part access blocked
+	it	eq
+	biceq	r5, r5, #0x100		@ clear bit if set
+	str	r5, [r4]		@ write back change
+	ldr	r4, sdrc_mr_0		@ get config addr
+	ldr	r5, [r4]		@ get value
+	str	r5, [r4]		@ write back change
+	ldr	r4, sdrc_emr2_0		@ get config addr
+	ldr	r5, [r4]		@ get value
+	str	r5, [r4]		@ write back change
+	ldr	r4, sdrc_manual_0	@ get config addr
+	mov	r5, #0x2		@ autorefresh command
+	str	r5, [r4]		@ kick off refreshes
+	ldr	r4, sdrc_mr_1		@ get config addr
+	ldr	r5, [r4]		@ get value
+	str	r5, [r4]		@ write back change
+	ldr	r4, sdrc_emr2_1		@ get config addr
+	ldr	r5, [r4]		@ get value
+	str	r5, [r4]		@ write back change
+	ldr	r4, sdrc_manual_1	@ get config addr
+	mov	r5, #0x2		@ autorefresh command
+	str	r5, [r4]		@ kick off refreshes
+	bx	lr
+
+sdrc_syscfg:
+	.word	SDRC_SYSCONFIG_P
+sdrc_mr_0:
+	.word	SDRC_MR_0_P
+sdrc_emr2_0:
+	.word	SDRC_EMR2_0_P
+sdrc_manual_0:
+	.word	SDRC_MANUAL_0_P
+sdrc_mr_1:
+	.word	SDRC_MR_1_P
+sdrc_emr2_1:
+	.word	SDRC_EMR2_1_P
+sdrc_manual_1:
+	.word	SDRC_MANUAL_1_P
+ENTRY(es3_sdrc_fix_sz)
+	.word	. - es3_sdrc_fix
+
+/*
+ * This function implements the erratum ID i581 WA:
+ *  SDRC state restore before accessing the SDRAM
+ *
+ * Only used at return from non-OFF mode. For OFF
+ * mode the ROM code configures the SDRC and
+ * the DPLL before calling the restore code directly
+ * from DDR.
+ */
 
 /* Make sure SDRC accesses are ok */
 wait_sdrc_ok:
-        ldr     r4, cm_idlest1_core
-        ldr     r5, [r4]
-        and     r5, r5, #0x2
-        cmp     r5, #0
-        bne     wait_sdrc_ok
-        ldr     r4, sdrc_power
-        ldr     r5, [r4]
-        bic     r5, r5, #0x40
-        str     r5, [r4]
+
+/* DPLL3 must be locked before accessing the SDRC. Maybe the HW ensures this */
+	ldr	r4, cm_idlest_ckgen
+wait_dpll3_lock:
+	ldr	r5, [r4]
+	tst	r5, #1
+	beq	wait_dpll3_lock
+
+	ldr	r4, cm_idlest1_core
+wait_sdrc_ready:
+	ldr	r5, [r4]
+	tst	r5, #0x2
+	bne	wait_sdrc_ready
+	/* allow DLL powerdown upon hw idle req */
+	ldr	r4, sdrc_power
+	ldr	r5, [r4]
+	bic	r5, r5, #0x40
+	str	r5, [r4]
+
+is_dll_in_lock_mode:
+	/* Is dll in lock mode? */
+	ldr	r4, sdrc_dlla_ctrl
+	ldr	r5, [r4]
+	tst	r5, #0x4
+	bxne	lr			@ Return if locked
+	/* wait till dll locks */
+wait_dll_lock_timed:
+	ldr	r4, wait_dll_lock_counter
+	add	r4, r4, #1
+	str	r4, wait_dll_lock_counter
+	ldr	r4, sdrc_dlla_status
+	/* Wait 20uS for lock */
+	mov	r6, #8
 wait_dll_lock:
-        /* Is dll in lock mode? */
-        ldr     r4, sdrc_dlla_ctrl
-        ldr     r5, [r4]
-        tst     r5, #0x4
-        bxne    lr
-        /* wait till dll locks */
-        ldr     r4, sdrc_dlla_status
-        ldr     r5, [r4]
-        and     r5, r5, #0x4
-        cmp     r5, #0x4
-        bne     wait_dll_lock
-        bx      lr
+	subs	r6, r6, #0x1
+	beq	kick_dll
+	ldr	r5, [r4]
+	and	r5, r5, #0x4
+	cmp	r5, #0x4
+	bne	wait_dll_lock
+	bx	lr			@ Return when locked
+
+	/* disable/reenable DLL if not locked */
+kick_dll:
+	ldr	r4, sdrc_dlla_ctrl
+	ldr	r5, [r4]
+	mov	r6, r5
+	bic	r6, #(1<<3)		@ disable dll
+	str	r6, [r4]
+	dsb
+	orr	r6, r6, #(1<<3)		@ enable dll
+	str	r6, [r4]
+	dsb
+	ldr	r4, kick_counter
+	add	r4, r4, #1
+	str	r4, kick_counter
+	b	wait_dll_lock_timed
 
 cm_idlest1_core:
 	.word	CM_IDLEST1_CORE_V
+cm_idlest_ckgen:
+	.word	CM_IDLEST_CKGEN_V
 sdrc_dlla_status:
 	.word	SDRC_DLLA_STATUS_V
 sdrc_dlla_ctrl:
 	.word	SDRC_DLLA_CTRL_V
-pm_prepwstst_core:
-	.word	PM_PREPWSTST_CORE_V
 pm_prepwstst_core_p:
 	.word	PM_PREPWSTST_CORE_P
-pm_prepwstst_mpu:
-	.word	PM_PREPWSTST_MPU_V
 pm_pwstctrl_mpu:
 	.word	PM_PWSTCTRL_MPU_P
 scratchpad_base:
@@ -651,13 +738,7 @@ scratchpad_base:
 sram_base:
 	.word	SRAM_BASE_P + 0x8000
 sdrc_power:
-	.word SDRC_POWER_V
-clk_stabilize_delay:
-	.word 0x000001FF
-assoc_mask:
-	.word	0x3ff
-numset_mask:
-	.word	0x7fff
+	.word	SDRC_POWER_V
 ttbrbit_mask:
 	.word	0xFFFFC000
 table_index_mask:
@@ -668,5 +749,20 @@ cache_pred_disable_mask:
 	.word	0xFFFFE7FB
 control_stat:
 	.word	CONTROL_STAT
+control_mem_rta:
+	.word	CONTROL_MEM_RTA_CTRL
+kernel_flush:
+	.word	v7_flush_dcache_all
+l2dis_3630:
+	.word	0
+	/*
+	 * When exporting to userspace while the counters are in SRAM,
+	 * these 2 words need to be at the end to facilitate retrival!
+	 */
+kick_counter:
+	.word	0
+wait_dll_lock_counter:
+	.word	0
+
 ENTRY(omap34xx_cpu_suspend_sz)
 	.word	. - omap34xx_cpu_suspend
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/smartreflex.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/smartreflex.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/smartreflex.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/smartreflex.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,1025 @@
+/*
+ * OMAP SmartReflex Voltage Control
+ *
+ * Author: Thara Gopinath	<thara@ti.com>
+ *
+ * Copyright (C) 2010 Texas Instruments, Inc.
+ * Thara Gopinath <thara@ti.com>
+ *
+ * Copyright (C) 2008 Nokia Corporation
+ * Kalle Jokiniemi
+ *
+ * Copyright (C) 2007 Texas Instruments, Inc.
+ * Lesly A M <x0080970@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.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/debugfs.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/pm_runtime.h>
+
+#include <plat/common.h>
+#include <plat/smartreflex.h>
+
+#include "pm.h"
+
+#define SMARTREFLEX_NAME_LEN	16
+#define NVALUE_NAME_LEN		40
+#define SR_DISABLE_TIMEOUT	200
+
+struct omap_sr {
+	int				srid;
+	int				ip_type;
+	int				nvalue_count;
+	bool				autocomp_active;
+	u32				clk_length;
+	u32				err_weight;
+	u32				err_minlimit;
+	u32				err_maxlimit;
+	u32				accum_data;
+	u32				senn_avgweight;
+	u32				senp_avgweight;
+	u32				senp_mod;
+	u32				senn_mod;
+	unsigned int			irq;
+	void __iomem			*base;
+	struct platform_device		*pdev;
+	struct list_head		node;
+	struct omap_sr_nvalue_table	*nvalue_table;
+	struct voltagedomain		*voltdm;
+};
+
+/* sr_list contains all the instances of smartreflex module */
+static LIST_HEAD(sr_list);
+
+static struct omap_sr_class_data *sr_class;
+static struct omap_sr_pmic_data *sr_pmic_data;
+
+static inline void sr_write_reg(struct omap_sr *sr, unsigned offset, u32 value)
+{
+	__raw_writel(value, (sr->base + offset));
+}
+
+static inline void sr_modify_reg(struct omap_sr *sr, unsigned offset, u32 mask,
+					u32 value)
+{
+	u32 reg_val;
+	u32 errconfig_offs = 0, errconfig_mask = 0;
+
+	reg_val = __raw_readl(sr->base + offset);
+	reg_val &= ~mask;
+
+	/*
+	 * Smartreflex error config register is special as it contains
+	 * certain status bits which if written a 1 into means a clear
+	 * of those bits. So in order to make sure no accidental write of
+	 * 1 happens to those status bits, do a clear of them in the read
+	 * value. This mean this API doesn't rewrite values in these bits
+	 * if they are currently set, but does allow the caller to write
+	 * those bits.
+	 */
+	if (sr->ip_type == SR_TYPE_V1) {
+		errconfig_offs = ERRCONFIG_V1;
+		errconfig_mask = ERRCONFIG_STATUS_V1_MASK;
+	} else if (sr->ip_type == SR_TYPE_V2) {
+		errconfig_offs = ERRCONFIG_V2;
+		errconfig_mask = ERRCONFIG_VPBOUNDINTST_V2;
+	}
+
+	if (offset == errconfig_offs)
+		reg_val &= ~errconfig_mask;
+
+	reg_val |= value;
+
+	__raw_writel(reg_val, (sr->base + offset));
+}
+
+static inline u32 sr_read_reg(struct omap_sr *sr, unsigned offset)
+{
+	return __raw_readl(sr->base + offset);
+}
+
+static struct omap_sr *_sr_lookup(struct voltagedomain *voltdm)
+{
+	struct omap_sr *sr_info;
+
+	if (!voltdm) {
+		pr_err("%s: Null voltage domain passed!\n", __func__);
+		return ERR_PTR(-EINVAL);
+	}
+
+	list_for_each_entry(sr_info, &sr_list, node) {
+		if (voltdm == sr_info->voltdm)
+			return sr_info;
+	}
+
+	return ERR_PTR(-ENODATA);
+}
+
+static irqreturn_t sr_interrupt(int irq, void *data)
+{
+	struct omap_sr *sr_info = (struct omap_sr *)data;
+	u32 status = 0;
+
+	if (sr_info->ip_type == SR_TYPE_V1) {
+		/* Read the status bits */
+		status = sr_read_reg(sr_info, ERRCONFIG_V1);
+
+		/* Clear them by writing back */
+		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);
+
+		/* Clear them by writing back */
+		sr_write_reg(sr_info, IRQSTATUS, status);
+	}
+
+	if (sr_class->class_type == SR_CLASS2 && sr_class->notify)
+		sr_class->notify(sr_info->voltdm, status);
+
+	return IRQ_HANDLED;
+}
+
+static void sr_set_clk_length(struct omap_sr *sr)
+{
+	struct clk *sys_ck;
+	u32 sys_clk_speed;
+
+	if (cpu_is_omap34xx())
+		sys_ck = clk_get(NULL, "sys_ck");
+	else
+		sys_ck = clk_get(NULL, "sys_clkin_ck");
+
+	if (IS_ERR(sys_ck)) {
+		dev_err(&sr->pdev->dev, "%s: unable to get sys clk\n",
+			__func__);
+		return;
+	}
+	sys_clk_speed = clk_get_rate(sys_ck);
+	clk_put(sys_ck);
+
+	switch (sys_clk_speed) {
+	case 12000000:
+		sr->clk_length = SRCLKLENGTH_12MHZ_SYSCLK;
+		break;
+	case 13000000:
+		sr->clk_length = SRCLKLENGTH_13MHZ_SYSCLK;
+		break;
+	case 19200000:
+		sr->clk_length = SRCLKLENGTH_19MHZ_SYSCLK;
+		break;
+	case 26000000:
+		sr->clk_length = SRCLKLENGTH_26MHZ_SYSCLK;
+		break;
+	case 38400000:
+		sr->clk_length = SRCLKLENGTH_38MHZ_SYSCLK;
+		break;
+	default:
+		dev_err(&sr->pdev->dev, "%s: Invalid sysclk value: %d\n",
+			__func__, sys_clk_speed);
+		break;
+	}
+}
+
+static void sr_set_regfields(struct omap_sr *sr)
+{
+	/*
+	 * For time being these values are defined in smartreflex.h
+	 * and populated during init. May be they can be moved to board
+	 * file or pmic specific data structure. In that case these structure
+	 * fields will have to be populated using the pdata or pmic structure.
+	 */
+	if (cpu_is_omap34xx() || cpu_is_omap44xx()) {
+		sr->err_weight = OMAP3430_SR_ERRWEIGHT;
+		sr->err_maxlimit = OMAP3430_SR_ERRMAXLIMIT;
+		sr->accum_data = OMAP3430_SR_ACCUMDATA;
+		if (!(strcmp(sr->voltdm->name, "mpu"))) {
+			sr->senn_avgweight = OMAP3430_SR1_SENNAVGWEIGHT;
+			sr->senp_avgweight = OMAP3430_SR1_SENPAVGWEIGHT;
+		} else {
+			sr->senn_avgweight = OMAP3430_SR2_SENNAVGWEIGHT;
+			sr->senp_avgweight = OMAP3430_SR2_SENPAVGWEIGHT;
+		}
+	}
+}
+
+static void sr_start_vddautocomp(struct omap_sr *sr)
+{
+	if (!sr_class || !(sr_class->enable) || !(sr_class->configure)) {
+		dev_warn(&sr->pdev->dev,
+			"%s: smartreflex class driver not registered\n",
+			__func__);
+		return;
+	}
+
+	if (!sr_class->enable(sr->voltdm))
+		sr->autocomp_active = true;
+}
+
+static void sr_stop_vddautocomp(struct omap_sr *sr)
+{
+	if (!sr_class || !(sr_class->disable)) {
+		dev_warn(&sr->pdev->dev,
+			"%s: smartreflex class driver not registered\n",
+			__func__);
+		return;
+	}
+
+	if (sr->autocomp_active) {
+		sr_class->disable(sr->voltdm, 1);
+		sr->autocomp_active = false;
+	}
+}
+
+/*
+ * This function handles the intializations which have to be done
+ * only when both sr device and class driver regiter has
+ * completed. This will be attempted to be called from both sr class
+ * driver register and sr device intializtion API's. Only one call
+ * will ultimately succeed.
+ *
+ * Currenly this function registers interrrupt handler for a particular SR
+ * if smartreflex class driver is already registered and has
+ * requested for interrupts and the SR interrupt line in present.
+ */
+static int sr_late_init(struct omap_sr *sr_info)
+{
+	char *name;
+	struct omap_sr_data *pdata = sr_info->pdev->dev.platform_data;
+	struct resource *mem;
+	int ret = 0;
+
+	if (sr_class->class_type == SR_CLASS2 &&
+		sr_class->notify_flags && sr_info->irq) {
+
+		name = kzalloc(SMARTREFLEX_NAME_LEN + 1, GFP_KERNEL);
+		strcpy(name, "sr_");
+		strcat(name, sr_info->voltdm->name);
+		ret = request_irq(sr_info->irq, sr_interrupt,
+				0, name, (void *)sr_info);
+		if (ret)
+			goto error;
+	}
+
+	if (pdata && pdata->enable_on_init)
+		sr_start_vddautocomp(sr_info);
+
+	return ret;
+
+error:
+		iounmap(sr_info->base);
+		mem = platform_get_resource(sr_info->pdev, IORESOURCE_MEM, 0);
+		release_mem_region(mem->start, resource_size(mem));
+		list_del(&sr_info->node);
+		dev_err(&sr_info->pdev->dev, "%s: ERROR in registering"
+			"interrupt handler. Smartreflex will"
+			"not function as desired\n", __func__);
+		kfree(name);
+		kfree(sr_info);
+		return ret;
+}
+
+static void sr_v1_disable(struct omap_sr *sr)
+{
+	int timeout = 0;
+
+	/* Enable MCUDisableAcknowledge interrupt */
+	sr_modify_reg(sr, ERRCONFIG_V1,
+			ERRCONFIG_MCUDISACKINTEN, ERRCONFIG_MCUDISACKINTEN);
+
+	/* SRCONFIG - disable SR */
+	sr_modify_reg(sr, SRCONFIG, SRCONFIG_SRENABLE, 0x0);
+
+	/* Disable all other SR interrupts and clear the status */
+	sr_modify_reg(sr, ERRCONFIG_V1,
+			(ERRCONFIG_MCUACCUMINTEN | ERRCONFIG_MCUVALIDINTEN |
+			ERRCONFIG_MCUBOUNDINTEN | ERRCONFIG_VPBOUNDINTEN_V1),
+			(ERRCONFIG_MCUACCUMINTST | ERRCONFIG_MCUVALIDINTST |
+			ERRCONFIG_MCUBOUNDINTST |
+			ERRCONFIG_VPBOUNDINTST_V1));
+
+	/*
+	 * Wait for SR to be disabled.
+	 * wait until ERRCONFIG.MCUDISACKINTST = 1. Typical latency is 1us.
+	 */
+	omap_test_timeout((sr_read_reg(sr, ERRCONFIG_V1) &
+			ERRCONFIG_MCUDISACKINTST), SR_DISABLE_TIMEOUT,
+			timeout);
+
+	if (timeout >= SR_DISABLE_TIMEOUT)
+		dev_warn(&sr->pdev->dev, "%s: Smartreflex disable timedout\n",
+			__func__);
+
+	/* Disable MCUDisableAcknowledge interrupt & clear pending interrupt */
+	sr_modify_reg(sr, ERRCONFIG_V1, ERRCONFIG_MCUDISACKINTEN,
+			ERRCONFIG_MCUDISACKINTST);
+}
+
+static void sr_v2_disable(struct omap_sr *sr)
+{
+	int timeout = 0;
+
+	/* Enable MCUDisableAcknowledge interrupt */
+	sr_write_reg(sr, IRQENABLE_SET, IRQENABLE_MCUDISABLEACKINT);
+
+	/* SRCONFIG - disable SR */
+	sr_modify_reg(sr, SRCONFIG, SRCONFIG_SRENABLE, 0x0);
+
+	/* Disable all other SR interrupts and clear the status */
+	sr_modify_reg(sr, ERRCONFIG_V2, ERRCONFIG_VPBOUNDINTEN_V2,
+			ERRCONFIG_VPBOUNDINTST_V2);
+	sr_write_reg(sr, IRQENABLE_CLR, (IRQENABLE_MCUACCUMINT |
+			IRQENABLE_MCUVALIDINT |
+			IRQENABLE_MCUBOUNDSINT));
+	sr_write_reg(sr, IRQSTATUS, (IRQSTATUS_MCUACCUMINT |
+			IRQSTATUS_MCVALIDINT |
+			IRQSTATUS_MCBOUNDSINT));
+
+	/*
+	 * Wait for SR to be disabled.
+	 * wait until IRQSTATUS.MCUDISACKINTST = 1. Typical latency is 1us.
+	 */
+	omap_test_timeout((sr_read_reg(sr, IRQSTATUS) &
+			IRQSTATUS_MCUDISABLEACKINT), SR_DISABLE_TIMEOUT,
+			timeout);
+
+	if (timeout >= SR_DISABLE_TIMEOUT)
+		dev_warn(&sr->pdev->dev, "%s: Smartreflex disable timedout\n",
+			__func__);
+
+	/* Disable MCUDisableAcknowledge interrupt & clear pending interrupt */
+	sr_write_reg(sr, IRQENABLE_CLR, IRQENABLE_MCUDISABLEACKINT);
+	sr_write_reg(sr, IRQSTATUS, IRQSTATUS_MCUDISABLEACKINT);
+}
+
+static u32 sr_retrieve_nvalue(struct omap_sr *sr, u32 efuse_offs)
+{
+	int i;
+
+	if (!sr->nvalue_table) {
+		dev_warn(&sr->pdev->dev, "%s: Missing ntarget value table\n",
+			__func__);
+		return 0;
+	}
+
+	for (i = 0; i < sr->nvalue_count; i++) {
+		if (sr->nvalue_table[i].efuse_offs == efuse_offs)
+			return sr->nvalue_table[i].nvalue;
+	}
+
+	return 0;
+}
+
+/* Public Functions */
+
+/**
+ * sr_configure_errgen() - Configures the smrtreflex to perform AVS using the
+ *			 error generator module.
+ * @voltdm:	VDD pointer to which the SR module to be configured belongs to.
+ *
+ * This API is to be called from the smartreflex class driver to
+ * configure the error generator module inside the smartreflex module.
+ * SR settings if using the ERROR module inside Smartreflex.
+ * SR CLASS 3 by default uses only the ERROR module where as
+ * SR CLASS 2 can choose between ERROR module and MINMAXAVG
+ * module. Returns 0 on success and error value in case of failure.
+ */
+int sr_configure_errgen(struct voltagedomain *voltdm)
+{
+	u32 sr_config, sr_errconfig, errconfig_offs, vpboundint_en;
+	u32 vpboundint_st, senp_en = 0, senn_en = 0;
+	u8 senp_shift, senn_shift;
+	struct omap_sr *sr = _sr_lookup(voltdm);
+
+	if (IS_ERR(sr)) {
+		pr_warning("%s: omap_sr struct for sr_%s not found\n",
+			__func__, voltdm->name);
+		return -EINVAL;
+	}
+
+	if (!sr->clk_length)
+		sr_set_clk_length(sr);
+
+	senp_en = sr->senp_mod;
+	senn_en = sr->senn_mod;
+
+	sr_config = (sr->clk_length << SRCONFIG_SRCLKLENGTH_SHIFT) |
+		SRCONFIG_SENENABLE | SRCONFIG_ERRGEN_EN;
+
+	if (sr->ip_type == SR_TYPE_V1) {
+		sr_config |= SRCONFIG_DELAYCTRL;
+		senn_shift = SRCONFIG_SENNENABLE_V1_SHIFT;
+		senp_shift = SRCONFIG_SENPENABLE_V1_SHIFT;
+		errconfig_offs = ERRCONFIG_V1;
+		vpboundint_en = ERRCONFIG_VPBOUNDINTEN_V1;
+		vpboundint_st = ERRCONFIG_VPBOUNDINTST_V1;
+	} else if (sr->ip_type == SR_TYPE_V2) {
+		senn_shift = SRCONFIG_SENNENABLE_V2_SHIFT;
+		senp_shift = SRCONFIG_SENPENABLE_V2_SHIFT;
+		errconfig_offs = ERRCONFIG_V2;
+		vpboundint_en = ERRCONFIG_VPBOUNDINTEN_V2;
+		vpboundint_st = ERRCONFIG_VPBOUNDINTST_V2;
+	} else {
+		dev_err(&sr->pdev->dev, "%s: Trying to Configure smartreflex"
+			"module without specifying the ip\n", __func__);
+		return -EINVAL;
+	}
+
+	sr_config |= ((senn_en << senn_shift) | (senp_en << senp_shift));
+	sr_write_reg(sr, SRCONFIG, sr_config);
+	sr_errconfig = (sr->err_weight << ERRCONFIG_ERRWEIGHT_SHIFT) |
+		(sr->err_maxlimit << ERRCONFIG_ERRMAXLIMIT_SHIFT) |
+		(sr->err_minlimit <<  ERRCONFIG_ERRMINLIMIT_SHIFT);
+	sr_modify_reg(sr, errconfig_offs, (SR_ERRWEIGHT_MASK |
+		SR_ERRMAXLIMIT_MASK | SR_ERRMINLIMIT_MASK),
+		sr_errconfig);
+
+	/* Enabling the interrupts if the ERROR module is used */
+	sr_modify_reg(sr, errconfig_offs,
+		vpboundint_en, (vpboundint_en | vpboundint_st));
+
+	return 0;
+}
+
+/**
+ * sr_configure_minmax() - Configures the smrtreflex to perform AVS using the
+ *			 minmaxavg module.
+ * @voltdm:	VDD pointer to which the SR module to be configured belongs to.
+ *
+ * This API is to be called from the smartreflex class driver to
+ * configure the minmaxavg module inside the smartreflex module.
+ * SR settings if using the ERROR module inside Smartreflex.
+ * SR CLASS 3 by default uses only the ERROR module where as
+ * SR CLASS 2 can choose between ERROR module and MINMAXAVG
+ * module. Returns 0 on success and error value in case of failure.
+ */
+int sr_configure_minmax(struct voltagedomain *voltdm)
+{
+	u32 sr_config, sr_avgwt;
+	u32 senp_en = 0, senn_en = 0;
+	u8 senp_shift, senn_shift;
+	struct omap_sr *sr = _sr_lookup(voltdm);
+
+	if (IS_ERR(sr)) {
+		pr_warning("%s: omap_sr struct for sr_%s not found\n",
+			__func__, voltdm->name);
+		return -EINVAL;
+	}
+
+	if (!sr->clk_length)
+		sr_set_clk_length(sr);
+
+	senp_en = sr->senp_mod;
+	senn_en = sr->senn_mod;
+
+	sr_config = (sr->clk_length << SRCONFIG_SRCLKLENGTH_SHIFT) |
+		SRCONFIG_SENENABLE |
+		(sr->accum_data << SRCONFIG_ACCUMDATA_SHIFT);
+
+	if (sr->ip_type == SR_TYPE_V1) {
+		sr_config |= SRCONFIG_DELAYCTRL;
+		senn_shift = SRCONFIG_SENNENABLE_V1_SHIFT;
+		senp_shift = SRCONFIG_SENPENABLE_V1_SHIFT;
+	} else if (sr->ip_type == SR_TYPE_V2) {
+		senn_shift = SRCONFIG_SENNENABLE_V2_SHIFT;
+		senp_shift = SRCONFIG_SENPENABLE_V2_SHIFT;
+	} else {
+		dev_err(&sr->pdev->dev, "%s: Trying to Configure smartreflex"
+			"module without specifying the ip\n", __func__);
+		return -EINVAL;
+	}
+
+	sr_config |= ((senn_en << senn_shift) | (senp_en << senp_shift));
+	sr_write_reg(sr, SRCONFIG, sr_config);
+	sr_avgwt = (sr->senp_avgweight << AVGWEIGHT_SENPAVGWEIGHT_SHIFT) |
+		(sr->senn_avgweight << AVGWEIGHT_SENNAVGWEIGHT_SHIFT);
+	sr_write_reg(sr, AVGWEIGHT, sr_avgwt);
+
+	/*
+	 * Enabling the interrupts if MINMAXAVG module is used.
+	 * TODO: check if all the interrupts are mandatory
+	 */
+	if (sr->ip_type == SR_TYPE_V1) {
+		sr_modify_reg(sr, ERRCONFIG_V1,
+			(ERRCONFIG_MCUACCUMINTEN | ERRCONFIG_MCUVALIDINTEN |
+			ERRCONFIG_MCUBOUNDINTEN),
+			(ERRCONFIG_MCUACCUMINTEN | ERRCONFIG_MCUACCUMINTST |
+			 ERRCONFIG_MCUVALIDINTEN | ERRCONFIG_MCUVALIDINTST |
+			 ERRCONFIG_MCUBOUNDINTEN | ERRCONFIG_MCUBOUNDINTST));
+	} else if (sr->ip_type == SR_TYPE_V2) {
+		sr_write_reg(sr, IRQSTATUS,
+			IRQSTATUS_MCUACCUMINT | IRQSTATUS_MCVALIDINT |
+			IRQSTATUS_MCBOUNDSINT | IRQSTATUS_MCUDISABLEACKINT);
+		sr_write_reg(sr, IRQENABLE_SET,
+			IRQENABLE_MCUACCUMINT | IRQENABLE_MCUVALIDINT |
+			IRQENABLE_MCUBOUNDSINT | IRQENABLE_MCUDISABLEACKINT);
+	}
+
+	return 0;
+}
+
+/**
+ * sr_enable() - Enables the smartreflex module.
+ * @voltdm:	VDD pointer to which the SR module to be configured belongs to.
+ * @volt:	The voltage at which the Voltage domain associated with
+ *		the smartreflex module is operating at.
+ *		This is required only to program the correct Ntarget value.
+ *
+ * This API is to be called from the smartreflex class driver to
+ * enable a smartreflex module. Returns 0 on success. Returns error
+ * value if the voltage passed is wrong or if ntarget value is wrong.
+ */
+int sr_enable(struct voltagedomain *voltdm, unsigned long volt)
+{
+	u32 nvalue_reciprocal;
+	struct omap_volt_data *volt_data;
+	struct omap_sr *sr = _sr_lookup(voltdm);
+	int ret;
+
+	if (IS_ERR(sr)) {
+		pr_warning("%s: omap_sr struct for sr_%s not found\n",
+			__func__, voltdm->name);
+		return -EINVAL;
+	}
+
+	volt_data = omap_voltage_get_voltdata(sr->voltdm, volt);
+
+	if (IS_ERR(volt_data)) {
+		dev_warn(&sr->pdev->dev, "%s: Unable to get voltage table"
+			"for nominal voltage %ld\n", __func__, volt);
+		return -ENODATA;
+	}
+
+	nvalue_reciprocal = sr_retrieve_nvalue(sr, volt_data->sr_efuse_offs);
+
+	if (!nvalue_reciprocal) {
+		dev_warn(&sr->pdev->dev, "%s: NVALUE = 0 at voltage %ld\n",
+			__func__, volt);
+		return -ENODATA;
+	}
+
+	/* errminlimit is opp dependent and hence linked to voltage */
+	sr->err_minlimit = volt_data->sr_errminlimit;
+
+	pm_runtime_get_sync(&sr->pdev->dev);
+
+	/* Check if SR is already enabled. If yes do nothing */
+	if (sr_read_reg(sr, SRCONFIG) & SRCONFIG_SRENABLE)
+		return 0;
+
+	/* Configure SR */
+	ret = sr_class->configure(voltdm);
+	if (ret)
+		return ret;
+
+	sr_write_reg(sr, NVALUERECIPROCAL, nvalue_reciprocal);
+
+	/* SRCONFIG - enable SR */
+	sr_modify_reg(sr, SRCONFIG, SRCONFIG_SRENABLE, SRCONFIG_SRENABLE);
+	return 0;
+}
+
+/**
+ * sr_disable() - Disables the smartreflex module.
+ * @voltdm:	VDD pointer to which the SR module to be configured belongs to.
+ *
+ * This API is to be called from the smartreflex class driver to
+ * disable a smartreflex module.
+ */
+void sr_disable(struct voltagedomain *voltdm)
+{
+	struct omap_sr *sr = _sr_lookup(voltdm);
+
+	if (IS_ERR(sr)) {
+		pr_warning("%s: omap_sr struct for sr_%s not found\n",
+			__func__, voltdm->name);
+		return;
+	}
+
+	/* Check if SR clocks are already disabled. If yes do nothing */
+	if (pm_runtime_suspended(&sr->pdev->dev))
+		return;
+
+	/*
+	 * Disable SR if only it is indeed enabled. Else just
+	 * disable the clocks.
+	 */
+	if (sr_read_reg(sr, SRCONFIG) & SRCONFIG_SRENABLE) {
+		if (sr->ip_type == SR_TYPE_V1)
+			sr_v1_disable(sr);
+		else if (sr->ip_type == SR_TYPE_V2)
+			sr_v2_disable(sr);
+	}
+
+	pm_runtime_put_sync(&sr->pdev->dev);
+}
+
+/**
+ * sr_register_class() - API to register a smartreflex class parameters.
+ * @class_data:	The structure containing various sr class specific data.
+ *
+ * This API is to be called by the smartreflex class driver to register itself
+ * with the smartreflex driver during init. Returns 0 on success else the
+ * error value.
+ */
+int sr_register_class(struct omap_sr_class_data *class_data)
+{
+	struct omap_sr *sr_info;
+
+	if (!class_data) {
+		pr_warning("%s:, Smartreflex class data passed is NULL\n",
+			__func__);
+		return -EINVAL;
+	}
+
+	if (sr_class) {
+		pr_warning("%s: Smartreflex class driver already registered\n",
+			__func__);
+		return -EBUSY;
+	}
+
+	sr_class = class_data;
+
+	/*
+	 * Call into late init to do intializations that require
+	 * both sr driver and sr class driver to be initiallized.
+	 */
+	list_for_each_entry(sr_info, &sr_list, node)
+		sr_late_init(sr_info);
+
+	return 0;
+}
+
+/**
+ * omap_sr_enable() -  API to enable SR clocks and to call into the
+ *			registered smartreflex class enable API.
+ * @voltdm:	VDD pointer to which the SR module to be configured belongs to.
+ *
+ * This API is to be called from the kernel in order to enable
+ * a particular smartreflex module. This API will do the initial
+ * configurations to turn on the smartreflex module and in turn call
+ * into the registered smartreflex class enable API.
+ */
+void omap_sr_enable(struct voltagedomain *voltdm)
+{
+	struct omap_sr *sr = _sr_lookup(voltdm);
+
+	if (IS_ERR(sr)) {
+		pr_warning("%s: omap_sr struct for sr_%s not found\n",
+			__func__, voltdm->name);
+		return;
+	}
+
+	if (!sr->autocomp_active)
+		return;
+
+	if (!sr_class || !(sr_class->enable) || !(sr_class->configure)) {
+		dev_warn(&sr->pdev->dev, "%s: smartreflex class driver not"
+			"registered\n", __func__);
+		return;
+	}
+
+	sr_class->enable(voltdm);
+}
+
+/**
+ * omap_sr_disable() - API to disable SR without resetting the voltage
+ *			processor voltage
+ * @voltdm:	VDD pointer to which the SR module to be configured belongs to.
+ *
+ * This API is to be called from the kernel in order to disable
+ * a particular smartreflex module. This API will in turn call
+ * into the registered smartreflex class disable API. This API will tell
+ * the smartreflex class disable not to reset the VP voltage after
+ * disabling smartreflex.
+ */
+void omap_sr_disable(struct voltagedomain *voltdm)
+{
+	struct omap_sr *sr = _sr_lookup(voltdm);
+
+	if (IS_ERR(sr)) {
+		pr_warning("%s: omap_sr struct for sr_%s not found\n",
+			__func__, voltdm->name);
+		return;
+	}
+
+	if (!sr->autocomp_active)
+		return;
+
+	if (!sr_class || !(sr_class->disable)) {
+		dev_warn(&sr->pdev->dev, "%s: smartreflex class driver not"
+			"registered\n", __func__);
+		return;
+	}
+
+	sr_class->disable(voltdm, 0);
+}
+
+/**
+ * omap_sr_disable_reset_volt() - API to disable SR and reset the
+ *				voltage processor voltage
+ * @voltdm:	VDD pointer to which the SR module to be configured belongs to.
+ *
+ * This API is to be called from the kernel in order to disable
+ * a particular smartreflex module. This API will in turn call
+ * into the registered smartreflex class disable API. This API will tell
+ * the smartreflex class disable to reset the VP voltage after
+ * disabling smartreflex.
+ */
+void omap_sr_disable_reset_volt(struct voltagedomain *voltdm)
+{
+	struct omap_sr *sr = _sr_lookup(voltdm);
+
+	if (IS_ERR(sr)) {
+		pr_warning("%s: omap_sr struct for sr_%s not found\n",
+			__func__, voltdm->name);
+		return;
+	}
+
+	if (!sr->autocomp_active)
+		return;
+
+	if (!sr_class || !(sr_class->disable)) {
+		dev_warn(&sr->pdev->dev, "%s: smartreflex class driver not"
+			"registered\n", __func__);
+		return;
+	}
+
+	sr_class->disable(voltdm, 1);
+}
+
+/**
+ * omap_sr_register_pmic() - API to register pmic specific info.
+ * @pmic_data:	The structure containing pmic specific data.
+ *
+ * This API is to be called from the PMIC specific code to register with
+ * smartreflex driver pmic specific info. Currently the only info required
+ * is the smartreflex init on the PMIC side.
+ */
+void omap_sr_register_pmic(struct omap_sr_pmic_data *pmic_data)
+{
+	if (!pmic_data) {
+		pr_warning("%s: Trying to register NULL PMIC data structure"
+			"with smartreflex\n", __func__);
+		return;
+	}
+
+	sr_pmic_data = pmic_data;
+}
+
+/* PM Debug Fs enteries to enable disable smartreflex. */
+static int omap_sr_autocomp_show(void *data, u64 *val)
+{
+	struct omap_sr *sr_info = (struct omap_sr *) data;
+
+	if (!sr_info) {
+		pr_warning("%s: omap_sr struct not found\n", __func__);
+		return -EINVAL;
+	}
+
+	*val = sr_info->autocomp_active;
+
+	return 0;
+}
+
+static int omap_sr_autocomp_store(void *data, u64 val)
+{
+	struct omap_sr *sr_info = (struct omap_sr *) data;
+
+	if (!sr_info) {
+		pr_warning("%s: omap_sr struct not found\n", __func__);
+		return -EINVAL;
+	}
+
+	/* Sanity check */
+	if (val && (val != 1)) {
+		pr_warning("%s: Invalid argument %lld\n", __func__, val);
+		return -EINVAL;
+	}
+
+	if (!val)
+		sr_stop_vddautocomp(sr_info);
+	else
+		sr_start_vddautocomp(sr_info);
+
+	return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(pm_sr_fops, omap_sr_autocomp_show,
+		omap_sr_autocomp_store, "%llu\n");
+
+static int __init omap_sr_probe(struct platform_device *pdev)
+{
+	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, *dbg_dir, *nvalue_dir;
+	struct omap_volt_data *volt_data;
+	int i, ret = 0;
+
+	if (!sr_info) {
+		dev_err(&pdev->dev, "%s: unable to allocate sr_info\n",
+			__func__);
+		return -ENOMEM;
+	}
+
+	if (!pdata) {
+		dev_err(&pdev->dev, "%s: platform data missing\n", __func__);
+		ret = -EINVAL;
+		goto err_free_devinfo;
+	}
+
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!mem) {
+		dev_err(&pdev->dev, "%s: no mem resource\n", __func__);
+		ret = -ENODEV;
+		goto err_free_devinfo;
+	}
+
+	irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+
+	pm_runtime_enable(&pdev->dev);
+
+	sr_info->pdev = pdev;
+	sr_info->srid = pdev->id;
+	sr_info->voltdm = pdata->voltdm;
+	sr_info->nvalue_table = pdata->nvalue_table;
+	sr_info->nvalue_count = pdata->nvalue_count;
+	sr_info->senn_mod = pdata->senn_mod;
+	sr_info->senp_mod = pdata->senp_mod;
+	sr_info->autocomp_active = false;
+	sr_info->ip_type = pdata->ip_type;
+	sr_info->base = ioremap(mem->start, resource_size(mem));
+	if (!sr_info->base) {
+		dev_err(&pdev->dev, "%s: ioremap fail\n", __func__);
+		ret = -ENOMEM;
+		goto err_release_region;
+	}
+
+	if (irq)
+		sr_info->irq = irq->start;
+
+	sr_set_clk_length(sr_info);
+	sr_set_regfields(sr_info);
+
+	list_add(&sr_info->node, &sr_list);
+
+	/*
+	 * Call into late init to do intializations that require
+	 * both sr driver and sr class driver to be initiallized.
+	 */
+	if (sr_class) {
+		ret = sr_late_init(sr_info);
+		if (ret) {
+			pr_warning("%s: Error in SR late init\n", __func__);
+			goto err_release_region;
+		}
+	}
+
+	dev_info(&pdev->dev, "%s: SmartReflex driver initialized\n", __func__);
+
+	/*
+	 * 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;
+		goto err_release_region;
+	}
+
+	dbg_dir = debugfs_create_dir("smartreflex", vdd_dbg_dir);
+	if (IS_ERR(dbg_dir)) {
+		dev_err(&pdev->dev, "%s: Unable to create debugfs directory\n",
+			__func__);
+		ret = PTR_ERR(dbg_dir);
+		goto err_release_region;
+	}
+
+	(void) debugfs_create_file("autocomp", S_IRUGO | S_IWUSR, dbg_dir,
+				(void *)sr_info, &pm_sr_fops);
+	(void) debugfs_create_x32("errweight", S_IRUGO, dbg_dir,
+			&sr_info->err_weight);
+	(void) debugfs_create_x32("errmaxlimit", S_IRUGO, dbg_dir,
+			&sr_info->err_maxlimit);
+	(void) debugfs_create_x32("errminlimit", S_IRUGO, dbg_dir,
+			&sr_info->err_minlimit);
+
+	nvalue_dir = debugfs_create_dir("nvalue", dbg_dir);
+	if (IS_ERR(nvalue_dir)) {
+		dev_err(&pdev->dev, "%s: Unable to create debugfs directory"
+			"for n-values\n", __func__);
+		ret = PTR_ERR(nvalue_dir);
+		goto err_release_region;
+	}
+
+	omap_voltage_get_volttable(sr_info->voltdm, &volt_data);
+	if (!volt_data) {
+		dev_warn(&pdev->dev, "%s: No Voltage table for the"
+			" corresponding vdd vdd_%s. Cannot create debugfs"
+			"entries for n-values\n",
+			__func__, sr_info->voltdm->name);
+		ret = -ENODATA;
+		goto err_release_region;
+	}
+
+	for (i = 0; i < sr_info->nvalue_count; i++) {
+		char name[NVALUE_NAME_LEN + 1];
+
+		snprintf(name, sizeof(name), "volt_%d",
+			 volt_data[i].volt_nominal);
+		(void) debugfs_create_x32(name, S_IRUGO | S_IWUSR, nvalue_dir,
+				&(sr_info->nvalue_table[i].nvalue));
+	}
+
+	return ret;
+
+err_release_region:
+	release_mem_region(mem->start, resource_size(mem));
+err_free_devinfo:
+	kfree(sr_info);
+
+	return ret;
+}
+
+static int __devexit omap_sr_remove(struct platform_device *pdev)
+{
+	struct omap_sr_data *pdata = pdev->dev.platform_data;
+	struct omap_sr *sr_info;
+	struct resource *mem;
+
+	if (!pdata) {
+		dev_err(&pdev->dev, "%s: platform data missing\n", __func__);
+		return -EINVAL;
+	}
+
+	sr_info = _sr_lookup(pdata->voltdm);
+	if (IS_ERR(sr_info)) {
+		dev_warn(&pdev->dev, "%s: omap_sr struct not found\n",
+			__func__);
+		return -EINVAL;
+	}
+
+	if (sr_info->autocomp_active)
+		sr_stop_vddautocomp(sr_info);
+
+	list_del(&sr_info->node);
+	iounmap(sr_info->base);
+	kfree(sr_info);
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	release_mem_region(mem->start, resource_size(mem));
+
+	return 0;
+}
+
+static struct platform_driver smartreflex_driver = {
+	.remove         = omap_sr_remove,
+	.driver		= {
+		.name	= "smartreflex",
+	},
+};
+
+static int __init sr_init(void)
+{
+	int ret = 0;
+
+	/*
+	 * sr_init is a late init. If by then a pmic specific API is not
+	 * registered either there is no need for anything to be done on
+	 * the PMIC side or somebody has forgotten to register a PMIC
+	 * handler. Warn for the second condition.
+	 */
+	if (sr_pmic_data && sr_pmic_data->sr_pmic_init)
+		sr_pmic_data->sr_pmic_init();
+	else
+		pr_warning("%s: No PMIC hook to init smartreflex\n", __func__);
+
+	ret = platform_driver_probe(&smartreflex_driver, omap_sr_probe);
+	if (ret) {
+		pr_err("%s: platform driver register failed for SR\n",
+			__func__);
+		return ret;
+	}
+
+	return 0;
+}
+
+static void __exit sr_exit(void)
+{
+	platform_driver_unregister(&smartreflex_driver);
+}
+late_initcall(sr_init);
+module_exit(sr_exit);
+
+MODULE_DESCRIPTION("OMAP Smartreflex Driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" DRIVER_NAME);
+MODULE_AUTHOR("Texas Instruments Inc");
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/smartreflex-class3.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/smartreflex-class3.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/smartreflex-class3.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/smartreflex-class3.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,59 @@
+/*
+ * Smart reflex Class 3 specific implementations
+ *
+ * Author: Thara Gopinath       <thara@ti.com>
+ *
+ * Copyright (C) 2010 Texas Instruments, Inc.
+ * 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.
+ */
+
+#include <plat/smartreflex.h>
+
+static int sr_class3_enable(struct voltagedomain *voltdm)
+{
+	unsigned long volt = omap_voltage_get_nom_volt(voltdm);
+
+	if (!volt) {
+		pr_warning("%s: Curr voltage unknown. Cannot enable sr_%s\n",
+				__func__, voltdm->name);
+		return -ENODATA;
+	}
+
+	omap_vp_enable(voltdm);
+	return sr_enable(voltdm, volt);
+}
+
+static int sr_class3_disable(struct voltagedomain *voltdm, int is_volt_reset)
+{
+	omap_vp_disable(voltdm);
+	sr_disable(voltdm);
+	if (is_volt_reset)
+		omap_voltage_reset(voltdm);
+
+	return 0;
+}
+
+static int sr_class3_configure(struct voltagedomain *voltdm)
+{
+	return sr_configure_errgen(voltdm);
+}
+
+/* SR class3 structure */
+static struct omap_sr_class_data class3_data = {
+	.enable = sr_class3_enable,
+	.disable = sr_class3_disable,
+	.configure = sr_class3_configure,
+	.class_type = SR_CLASS3,
+};
+
+/* Smartreflex Class3 init API to be called from board file */
+static int __init sr_class3_init(void)
+{
+	pr_info("SmartReflex Class3 initialized\n");
+	return sr_register_class(&class3_data);
+}
+late_initcall(sr_class3_init);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/sram242x.S linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/sram242x.S
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/sram242x.S	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/sram242x.S	2011-03-14 21:20:32.000000000 -0400
@@ -21,14 +21,20 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  * MA 02111-1307 USA
+ *
+ * Richard Woodruff notes that any changes to this code must be carefully
+ * audited and tested to ensure that they don't cause a TLB miss while
+ * the SDRAM is inaccessible.  Such a situation will crash the system
+ * since it will cause the ARM MMU to attempt to walk the page tables.
+ * These crashes may be intermittent.
  */
 #include <linux/linkage.h>
 #include <asm/assembler.h>
 #include <mach/io.h>
 #include <mach/hardware.h>
 
-#include "prm.h"
-#include "cm.h"
+#include "prm2xxx_3xxx.h"
+#include "cm2xxx_3xxx.h"
 #include "sdrc.h"
 
 	.text
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/sram243x.S linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/sram243x.S
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/sram243x.S	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/sram243x.S	2011-03-14 21:20:32.000000000 -0400
@@ -21,14 +21,20 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  * MA 02111-1307 USA
+ *
+ * Richard Woodruff notes that any changes to this code must be carefully
+ * audited and tested to ensure that they don't cause a TLB miss while
+ * the SDRAM is inaccessible.  Such a situation will crash the system
+ * since it will cause the ARM MMU to attempt to walk the page tables.
+ * These crashes may be intermittent.
  */
 #include <linux/linkage.h>
 #include <asm/assembler.h>
 #include <mach/io.h>
 #include <mach/hardware.h>
 
-#include "prm.h"
-#include "cm.h"
+#include "prm2xxx_3xxx.h"
+#include "cm2xxx_3xxx.h"
 #include "sdrc.h"
 
 	.text
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/sram34xx.S linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/sram34xx.S
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/sram34xx.S	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/sram34xx.S	2011-03-14 21:20:32.000000000 -0400
@@ -32,7 +32,7 @@
 #include <mach/io.h>
 
 #include "sdrc.h"
-#include "cm.h"
+#include "cm2xxx_3xxx.h"
 
 	.text
 
@@ -104,6 +104,12 @@
  * touching the SDRAM.  Until that time, users who know that their use case
  * can satisfy the above requirement can enable the CONFIG_OMAP3_SDRC_AC_TIMING
  * option.
+ *
+ * Richard Woodruff notes that any changes to this code must be carefully
+ * audited and tested to ensure that they don't cause a TLB miss while
+ * the SDRAM is inaccessible.  Such a situation will crash the system
+ * since it will cause the ARM MMU to attempt to walk the page tables.
+ * These crashes may be intermittent.
  */
 ENTRY(omap3_sram_configure_core_dpll)
 	stmfd	sp!, {r1-r12, lr}	@ store regs to stack
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/sr_device.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/sr_device.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/sr_device.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/sr_device.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,147 @@
+/*
+ * OMAP3/OMAP4 smartreflex device file
+ *
+ * Author: Thara Gopinath	<thara@ti.com>
+ *
+ * Based originally on code from smartreflex.c
+ * Copyright (C) 2010 Texas Instruments, Inc.
+ * Thara Gopinath <thara@ti.com>
+ *
+ * Copyright (C) 2008 Nokia Corporation
+ * Kalle Jokiniemi
+ *
+ * Copyright (C) 2007 Texas Instruments, Inc.
+ * Lesly A M <x0080970@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.
+ */
+
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+
+#include <plat/omap_device.h>
+#include <plat/smartreflex.h>
+#include <plat/voltage.h>
+
+#include "control.h"
+#include "pm.h"
+
+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)
+{
+	struct omap_sr_nvalue_table *nvalue_table;
+	int i, count = 0;
+
+	while (volt_data[count].volt_nominal)
+		count++;
+
+	nvalue_table = kzalloc(sizeof(struct omap_sr_nvalue_table)*count,
+			GFP_KERNEL);
+
+	for (i = 0; i < count; i++) {
+		u32 v;
+		/*
+		 * In OMAP4 the efuse registers are 24 bit aligned.
+		 * A __raw_readl will fail for non-32 bit aligned address
+		 * and hence the 8-bit read and shift.
+		 */
+		if (cpu_is_omap44xx()) {
+			u16 offset = volt_data[i].sr_efuse_offs;
+
+			v = omap_ctrl_readb(offset) |
+				omap_ctrl_readb(offset + 1) << 8 |
+				omap_ctrl_readb(offset + 2) << 16;
+		} else {
+			 v = omap_ctrl_readl(volt_data[i].sr_efuse_offs);
+		}
+
+		nvalue_table[i].efuse_offs = volt_data[i].sr_efuse_offs;
+		nvalue_table[i].nvalue = v;
+	}
+
+	sr_data->nvalue_table = nvalue_table;
+	sr_data->nvalue_count = count;
+}
+
+static int sr_dev_init(struct omap_hwmod *oh, void *user)
+{
+	struct omap_sr_data *sr_data;
+	struct omap_device *od;
+	struct omap_volt_data *volt_data;
+	char *name = "smartreflex";
+	static int i;
+
+	sr_data = kzalloc(sizeof(struct omap_sr_data), GFP_KERNEL);
+	if (!sr_data) {
+		pr_err("%s: Unable to allocate memory for %s sr_data.Error!\n",
+			__func__, oh->name);
+		return -ENOMEM;
+	}
+
+	if (!oh->vdd_name) {
+		pr_err("%s: No voltage domain specified for %s."
+			"Cannot initialize\n", __func__, oh->name);
+		goto exit;
+	}
+
+	sr_data->ip_type = oh->class->rev;
+	sr_data->senn_mod = 0x1;
+	sr_data->senp_mod = 0x1;
+
+	sr_data->voltdm = omap_voltage_domain_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);
+		goto exit;
+	}
+
+	omap_voltage_get_volttable(sr_data->voltdm, &volt_data);
+	if (!volt_data) {
+		pr_warning("%s: No Voltage table registerd fo VDD%d."
+			"Something really wrong\n\n", __func__, i + 1);
+		goto exit;
+	}
+
+	sr_set_nvalues(volt_data, sr_data);
+
+	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))
+		pr_warning("%s: Could not build omap_device for %s: %s.\n\n",
+			__func__, name, oh->name);
+exit:
+	i++;
+	kfree(sr_data);
+	return 0;
+}
+
+/*
+ * API to be called from board files to enable smartreflex
+ * autocompensation at init.
+ */
+void __init omap_enable_smartreflex_on_init(void)
+{
+	sr_enable_on_init = true;
+}
+
+int __init omap_devinit_smartreflex(void)
+{
+	return omap_hwmod_for_each_by_class("smartreflex", sr_dev_init, NULL);
+}
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/timer-gp.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/timer-gp.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/timer-gp.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/timer-gp.c	2011-03-14 21:20:32.000000000 -0400
@@ -39,9 +39,12 @@
 #include <asm/mach/time.h>
 #include <plat/dmtimer.h>
 #include <asm/localtimer.h>
+#include <asm/sched_clock.h>
 
 #include "timer-gp.h"
 
+#include <plat/common.h>
+
 /* MAX_GPTIMER_ID: number of GPTIMERs on the chip */
 #define MAX_GPTIMER_ID		12
 
@@ -176,14 +179,19 @@ static void __init omap2_gp_clockevent_i
 /* 
  * When 32k-timer is enabled, don't use GPTimer for clocksource
  * instead, just leave default clocksource which uses the 32k
- * sync counter.  See clocksource setup in see plat-omap/common.c. 
+ * sync counter.  See clocksource setup in plat-omap/counter_32k.c
  */
 
-static inline void __init omap2_gp_clocksource_init(void) {}
+static void __init omap2_gp_clocksource_init(void)
+{
+	omap_init_clocksource_32k();
+}
+
 #else
 /*
  * clocksource
  */
+static DEFINE_CLOCK_DATA(cd);
 static struct omap_dm_timer *gpt_clocksource;
 static cycle_t clocksource_read_cycles(struct clocksource *cs)
 {
@@ -195,15 +203,23 @@ static struct clocksource clocksource_gp
 	.rating		= 300,
 	.read		= clocksource_read_cycles,
 	.mask		= CLOCKSOURCE_MASK(32),
-	.shift		= 24,
 	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
+static void notrace dmtimer_update_sched_clock(void)
+{
+	u32 cyc;
+
+	cyc = omap_dm_timer_read_counter(gpt_clocksource);
+
+	update_sched_clock(&cd, cyc, (u32)~0);
+}
+
 /* Setup free-running counter for clocksource */
 static void __init omap2_gp_clocksource_init(void)
 {
 	static struct omap_dm_timer *gpt;
-	u32 tick_rate, tick_period;
+	u32 tick_rate;
 	static char err1[] __initdata = KERN_ERR
 		"%s: failed to request dm-timer\n";
 	static char err2[] __initdata = KERN_ERR
@@ -216,13 +232,12 @@ static void __init omap2_gp_clocksource_
 
 	omap_dm_timer_set_source(gpt, OMAP_TIMER_SRC_SYS_CLK);
 	tick_rate = clk_get_rate(omap_dm_timer_get_fclk(gpt));
-	tick_period = (tick_rate / HZ) - 1;
 
 	omap_dm_timer_set_load_start(gpt, 1, 0);
 
-	clocksource_gpt.mult =
-		clocksource_khz2mult(tick_rate/1000, clocksource_gpt.shift);
-	if (clocksource_register(&clocksource_gpt))
+	init_sched_clock(&cd, dmtimer_update_sched_clock, 32, tick_rate);
+
+	if (clocksource_register_hz(&clocksource_gpt, tick_rate))
 		printk(err2, clocksource_gpt.name);
 }
 #endif
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/usb-ehci.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/usb-ehci.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/usb-ehci.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/usb-ehci.c	2011-03-14 21:20:32.000000000 -0400
@@ -34,22 +34,15 @@
 
 static struct resource ehci_resources[] = {
 	{
-		.start	= OMAP34XX_EHCI_BASE,
-		.end	= OMAP34XX_EHCI_BASE + SZ_1K - 1,
 		.flags	= IORESOURCE_MEM,
 	},
 	{
-		.start	= OMAP34XX_UHH_CONFIG_BASE,
-		.end	= OMAP34XX_UHH_CONFIG_BASE + SZ_1K - 1,
 		.flags	= IORESOURCE_MEM,
 	},
 	{
-		.start	= OMAP34XX_USBTLL_BASE,
-		.end	= OMAP34XX_USBTLL_BASE + SZ_4K - 1,
 		.flags	= IORESOURCE_MEM,
 	},
 	{         /* general IRQ */
-		.start   = INT_34XX_EHCI_IRQ,
 		.flags   = IORESOURCE_IRQ,
 	}
 };
@@ -214,13 +207,148 @@ static void setup_ehci_io_mux(const enum
 	return;
 }
 
+static void setup_4430ehci_io_mux(const enum ehci_hcd_omap_mode *port_mode)
+{
+	switch (port_mode[0]) {
+	case EHCI_HCD_OMAP_MODE_PHY:
+		omap_mux_init_signal("usbb1_ulpiphy_stp",
+			OMAP_PIN_OUTPUT);
+		omap_mux_init_signal("usbb1_ulpiphy_clk",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb1_ulpiphy_dir",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb1_ulpiphy_nxt",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb1_ulpiphy_dat0",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb1_ulpiphy_dat1",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb1_ulpiphy_dat2",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb1_ulpiphy_dat3",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb1_ulpiphy_dat4",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb1_ulpiphy_dat5",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb1_ulpiphy_dat6",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb1_ulpiphy_dat7",
+			OMAP_PIN_INPUT_PULLDOWN);
+			break;
+	case EHCI_HCD_OMAP_MODE_TLL:
+		omap_mux_init_signal("usbb1_ulpitll_stp",
+			OMAP_PIN_INPUT_PULLUP);
+		omap_mux_init_signal("usbb1_ulpitll_clk",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb1_ulpitll_dir",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb1_ulpitll_nxt",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb1_ulpitll_dat0",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb1_ulpitll_dat1",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb1_ulpitll_dat2",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb1_ulpitll_dat3",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb1_ulpitll_dat4",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb1_ulpitll_dat5",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb1_ulpitll_dat6",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb1_ulpitll_dat7",
+			OMAP_PIN_INPUT_PULLDOWN);
+			break;
+	case EHCI_HCD_OMAP_MODE_UNKNOWN:
+	default:
+			break;
+	}
+	switch (port_mode[1]) {
+	case EHCI_HCD_OMAP_MODE_PHY:
+		omap_mux_init_signal("usbb2_ulpiphy_stp",
+			OMAP_PIN_OUTPUT);
+		omap_mux_init_signal("usbb2_ulpiphy_clk",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb2_ulpiphy_dir",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb2_ulpiphy_nxt",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb2_ulpiphy_dat0",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb2_ulpiphy_dat1",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb2_ulpiphy_dat2",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb2_ulpiphy_dat3",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb2_ulpiphy_dat4",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb2_ulpiphy_dat5",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb2_ulpiphy_dat6",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb2_ulpiphy_dat7",
+			OMAP_PIN_INPUT_PULLDOWN);
+			break;
+	case EHCI_HCD_OMAP_MODE_TLL:
+		omap_mux_init_signal("usbb2_ulpitll_stp",
+			OMAP_PIN_INPUT_PULLUP);
+		omap_mux_init_signal("usbb2_ulpitll_clk",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb2_ulpitll_dir",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb2_ulpitll_nxt",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb2_ulpitll_dat0",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb2_ulpitll_dat1",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb2_ulpitll_dat2",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb2_ulpitll_dat3",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb2_ulpitll_dat4",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb2_ulpitll_dat5",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb2_ulpitll_dat6",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb2_ulpitll_dat7",
+			OMAP_PIN_INPUT_PULLDOWN);
+			break;
+	case EHCI_HCD_OMAP_MODE_UNKNOWN:
+	default:
+			break;
+	}
+}
+
 void __init usb_ehci_init(const struct ehci_hcd_omap_platform_data *pdata)
 {
 	platform_device_add_data(&ehci_device, pdata, sizeof(*pdata));
 
 	/* Setup Pin IO MUX for EHCI */
-	if (cpu_is_omap34xx())
+	if (cpu_is_omap34xx()) {
+		ehci_resources[0].start	= OMAP34XX_EHCI_BASE;
+		ehci_resources[0].end	= OMAP34XX_EHCI_BASE + SZ_1K - 1;
+		ehci_resources[1].start	= OMAP34XX_UHH_CONFIG_BASE;
+		ehci_resources[1].end	= OMAP34XX_UHH_CONFIG_BASE + SZ_1K - 1;
+		ehci_resources[2].start	= OMAP34XX_USBTLL_BASE;
+		ehci_resources[2].end	= OMAP34XX_USBTLL_BASE + SZ_4K - 1;
+		ehci_resources[3].start = INT_34XX_EHCI_IRQ;
 		setup_ehci_io_mux(pdata->port_mode);
+	} else if (cpu_is_omap44xx()) {
+		ehci_resources[0].start	= OMAP44XX_HSUSB_EHCI_BASE;
+		ehci_resources[0].end	= OMAP44XX_HSUSB_EHCI_BASE + SZ_1K - 1;
+		ehci_resources[1].start	= OMAP44XX_UHH_CONFIG_BASE;
+		ehci_resources[1].end	= OMAP44XX_UHH_CONFIG_BASE + SZ_2K - 1;
+		ehci_resources[2].start	= OMAP44XX_USBTLL_BASE;
+		ehci_resources[2].end	= OMAP44XX_USBTLL_BASE + SZ_4K - 1;
+		ehci_resources[3].start = OMAP44XX_IRQ_EHCI;
+		setup_4430ehci_io_mux(pdata->port_mode);
+	}
 
 	if (platform_device_register(&ehci_device) < 0) {
 		printk(KERN_ERR "Unable to register HS-USB (EHCI) device\n");
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/usb-musb.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/usb-musb.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/usb-musb.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/usb-musb.c	2011-03-14 21:20:32.000000000 -0400
@@ -30,8 +30,101 @@
 #include <mach/irqs.h>
 #include <mach/am35xx.h>
 #include <plat/usb.h>
+#include "control.h"
 
-#ifdef CONFIG_USB_MUSB_SOC
+#if defined(CONFIG_USB_MUSB_OMAP2PLUS) || defined (CONFIG_USB_MUSB_AM35X)
+
+static void am35x_musb_reset(void)
+{
+	u32	regval;
+
+	/* Reset the musb interface */
+	regval = omap_ctrl_readl(AM35XX_CONTROL_IP_SW_RESET);
+
+	regval |= AM35XX_USBOTGSS_SW_RST;
+	omap_ctrl_writel(regval, AM35XX_CONTROL_IP_SW_RESET);
+
+	regval &= ~AM35XX_USBOTGSS_SW_RST;
+	omap_ctrl_writel(regval, AM35XX_CONTROL_IP_SW_RESET);
+
+	regval = omap_ctrl_readl(AM35XX_CONTROL_IP_SW_RESET);
+}
+
+static void am35x_musb_phy_power(u8 on)
+{
+	unsigned long timeout = jiffies + msecs_to_jiffies(100);
+	u32 devconf2;
+
+	if (on) {
+		/*
+		 * Start the on-chip PHY and its PLL.
+		 */
+		devconf2 = omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2);
+
+		devconf2 &= ~(CONF2_RESET | CONF2_PHYPWRDN | CONF2_OTGPWRDN);
+		devconf2 |= CONF2_PHY_PLLON;
+
+		omap_ctrl_writel(devconf2, AM35XX_CONTROL_DEVCONF2);
+
+		pr_info(KERN_INFO "Waiting for PHY clock good...\n");
+		while (!(omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2)
+				& CONF2_PHYCLKGD)) {
+			cpu_relax();
+
+			if (time_after(jiffies, timeout)) {
+				pr_err(KERN_ERR "musb PHY clock good timed out\n");
+				break;
+			}
+		}
+	} else {
+		/*
+		 * Power down the on-chip PHY.
+		 */
+		devconf2 = omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2);
+
+		devconf2 &= ~CONF2_PHY_PLLON;
+		devconf2 |=  CONF2_PHYPWRDN | CONF2_OTGPWRDN;
+		omap_ctrl_writel(devconf2, AM35XX_CONTROL_DEVCONF2);
+	}
+}
+
+static void am35x_musb_clear_irq(void)
+{
+	u32 regval;
+
+	regval = omap_ctrl_readl(AM35XX_CONTROL_LVL_INTR_CLEAR);
+	regval |= AM35XX_USBOTGSS_INT_CLR;
+	omap_ctrl_writel(regval, AM35XX_CONTROL_LVL_INTR_CLEAR);
+	regval = omap_ctrl_readl(AM35XX_CONTROL_LVL_INTR_CLEAR);
+}
+
+static void am35x_musb_set_mode(u8 musb_mode)
+{
+	u32 devconf2 = omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2);
+
+	devconf2 &= ~CONF2_OTGMODE;
+	switch (musb_mode) {
+#ifdef	CONFIG_USB_MUSB_HDRC_HCD
+	case MUSB_HOST:		/* Force VBUS valid, ID = 0 */
+		devconf2 |= CONF2_FORCE_HOST;
+		break;
+#endif
+#ifdef	CONFIG_USB_GADGET_MUSB_HDRC
+	case MUSB_PERIPHERAL:	/* Force VBUS valid, ID = 1 */
+		devconf2 |= CONF2_FORCE_DEVICE;
+		break;
+#endif
+#ifdef	CONFIG_USB_MUSB_OTG
+	case MUSB_OTG:		/* Don't override the VBUS/ID comparators */
+		devconf2 |= CONF2_NO_OVERRIDE;
+		break;
+#endif
+	default:
+		pr_info(KERN_INFO "Unsupported mode %u\n", musb_mode);
+	}
+
+	omap_ctrl_writel(devconf2, AM35XX_CONTROL_DEVCONF2);
+}
 
 static struct resource musb_resources[] = {
 	[0] = { /* start and end set dynamically */
@@ -40,10 +133,12 @@ static struct resource musb_resources[]
 	[1] = {	/* general IRQ */
 		.start	= INT_243X_HS_USB_MC,
 		.flags	= IORESOURCE_IRQ,
+		.name	= "mc",
 	},
 	[2] = {	/* DMA IRQ */
 		.start	= INT_243X_HS_USB_DMA,
 		.flags	= IORESOURCE_IRQ,
+		.name	= "dma",
 	},
 };
 
@@ -75,7 +170,7 @@ static struct musb_hdrc_platform_data mu
 static u64 musb_dmamask = DMA_BIT_MASK(32);
 
 static struct platform_device musb_device = {
-	.name		= "musb_hdrc",
+	.name		= "musb-omap2430",
 	.id		= -1,
 	.dev = {
 		.dma_mask		= &musb_dmamask,
@@ -91,8 +186,13 @@ void __init usb_musb_init(struct omap_mu
 	if (cpu_is_omap243x()) {
 		musb_resources[0].start = OMAP243X_HS_BASE;
 	} else if (cpu_is_omap3517() || cpu_is_omap3505()) {
+		musb_device.name = "musb-am35x";
 		musb_resources[0].start = AM35XX_IPSS_USBOTGSS_BASE;
 		musb_resources[1].start = INT_35XX_USBOTG_IRQ;
+		board_data->set_phy_power = am35x_musb_phy_power;
+		board_data->clear_irq = am35x_musb_clear_irq;
+		board_data->set_mode = am35x_musb_set_mode;
+		board_data->reset = am35x_musb_reset;
 	} else if (cpu_is_omap34xx()) {
 		musb_resources[0].start = OMAP34XX_HSUSB_OTG_BASE;
 	} else if (cpu_is_omap44xx()) {
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/usb-tusb6010.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/usb-tusb6010.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/usb-tusb6010.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/usb-tusb6010.c	2011-03-14 21:20:32.000000000 -0400
@@ -120,8 +120,8 @@ static int tusb_set_sync_mode(unsigned s
 	t.adv_on = next_clk(t.cs_on, t_scsnh_advnh - 7000, fclk_ps);
 
 	/* GPMC_CLK rate = fclk rate / div */
-	t.sync_clk = 12 /* 11.1 nsec */;
-	tmp = (t.sync_clk * 1000 + fclk_ps - 1) / fclk_ps;
+	t.sync_clk = 11100 /* 11.1 nsec */;
+	tmp = (t.sync_clk + fclk_ps - 1) / fclk_ps;
 	if (tmp > 4)
 		return -ERANGE;
 	if (tmp <= 0)
@@ -216,6 +216,7 @@ static struct resource tusb_resources[]
 		.flags	= IORESOURCE_MEM,
 	},
 	{ /* IRQ */
+		.name	= "mc",
 		.flags	= IORESOURCE_IRQ,
 	},
 };
@@ -223,7 +224,7 @@ static struct resource tusb_resources[]
 static u64 tusb_dmamask = ~(u32)0;
 
 static struct platform_device tusb_device = {
-	.name		= "musb_hdrc",
+	.name		= "musb-tusb",
 	.id		= -1,
 	.dev = {
 		.dma_mask		= &tusb_dmamask,
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/voltage.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/voltage.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/voltage.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/voltage.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,1572 @@
+/*
+ * OMAP3/OMAP4 Voltage Management Routines
+ *
+ * Author: Thara Gopinath	<thara@ti.com>
+ *
+ * Copyright (C) 2007 Texas Instruments, Inc.
+ * Rajendra Nayak <rnayak@ti.com>
+ * Lesly A M <x0080970@ti.com>
+ *
+ * Copyright (C) 2008 Nokia Corporation
+ * Kalle Jokiniemi
+ *
+ * Copyright (C) 2010 Texas Instruments, Inc.
+ * 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.
+ */
+
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/debugfs.h>
+#include <linux/slab.h>
+
+#include <plat/common.h>
+#include <plat/voltage.h>
+
+#include "prm-regbits-34xx.h"
+#include "prm-regbits-44xx.h"
+#include "prm44xx.h"
+#include "prcm44xx.h"
+#include "prminst44xx.h"
+#include "control.h"
+
+#define VP_IDLE_TIMEOUT		200
+#define VP_TRANXDONE_TIMEOUT	300
+#define VOLTAGE_DIR_SIZE	16
+
+/* Voltage processor register offsets */
+struct vp_reg_offs {
+	u8 vpconfig;
+	u8 vstepmin;
+	u8 vstepmax;
+	u8 vlimitto;
+	u8 vstatus;
+	u8 voltage;
+};
+
+/* Voltage Processor bit field values, shifts and masks */
+struct vp_reg_val {
+	/* PRM module */
+	u16 prm_mod;
+	/* VPx_VPCONFIG */
+	u32 vpconfig_erroroffset;
+	u16 vpconfig_errorgain;
+	u32 vpconfig_errorgain_mask;
+	u8 vpconfig_errorgain_shift;
+	u32 vpconfig_initvoltage_mask;
+	u8 vpconfig_initvoltage_shift;
+	u32 vpconfig_timeouten;
+	u32 vpconfig_initvdd;
+	u32 vpconfig_forceupdate;
+	u32 vpconfig_vpenable;
+	/* VPx_VSTEPMIN */
+	u8 vstepmin_stepmin;
+	u16 vstepmin_smpswaittimemin;
+	u8 vstepmin_stepmin_shift;
+	u8 vstepmin_smpswaittimemin_shift;
+	/* VPx_VSTEPMAX */
+	u8 vstepmax_stepmax;
+	u16 vstepmax_smpswaittimemax;
+	u8 vstepmax_stepmax_shift;
+	u8 vstepmax_smpswaittimemax_shift;
+	/* VPx_VLIMITTO */
+	u8 vlimitto_vddmin;
+	u8 vlimitto_vddmax;
+	u16 vlimitto_timeout;
+	u8 vlimitto_vddmin_shift;
+	u8 vlimitto_vddmax_shift;
+	u8 vlimitto_timeout_shift;
+	/* PRM_IRQSTATUS*/
+	u32 tranxdone_status;
+};
+
+/* Voltage controller registers and offsets */
+struct vc_reg_info {
+	/* PRM module */
+	u16 prm_mod;
+	/* VC register offsets */
+	u8 smps_sa_reg;
+	u8 smps_volra_reg;
+	u8 bypass_val_reg;
+	u8 cmdval_reg;
+	u8 voltsetup_reg;
+	/*VC_SMPS_SA*/
+	u8 smps_sa_shift;
+	u32 smps_sa_mask;
+	/* VC_SMPS_VOL_RA */
+	u8 smps_volra_shift;
+	u32 smps_volra_mask;
+	/* VC_BYPASS_VAL */
+	u8 data_shift;
+	u8 slaveaddr_shift;
+	u8 regaddr_shift;
+	u32 valid;
+	/* VC_CMD_VAL */
+	u8 cmd_on_shift;
+	u8 cmd_onlp_shift;
+	u8 cmd_ret_shift;
+	u8 cmd_off_shift;
+	u32 cmd_on_mask;
+	/* PRM_VOLTSETUP */
+	u8 voltsetup_shift;
+	u32 voltsetup_mask;
+};
+
+/**
+ * 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_offs		: structure containing the offsets for various
+ *			  vp registers
+ * @vp_reg		: the register values, shifts, masks for various
+ *			  vp registers
+ * @vc_reg		: structure containing various various vc registers,
+ *			  shifts, masks etc.
+ * @voltdm		: pointer to the voltage domain structure
+ * @debug_dir		: debug directory for this voltage domain.
+ * @curr_volt		: current voltage for this vdd.
+ * @ocp_mod		: The prm module for accessing the prm irqstatus reg.
+ * @prm_irqst_reg	: prm irqstatus register.
+ * @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 vp_reg_offs vp_offs;
+	struct vp_reg_val vp_reg;
+	struct vc_reg_info vc_reg;
+	struct voltagedomain voltdm;
+	struct dentry *debug_dir;
+	u32 curr_volt;
+	u16 ocp_mod;
+	u8 prm_irqst_reg;
+	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);
+};
+
+static struct omap_vdd_info *vdd_info;
+/*
+ * Number of scalable voltage domains.
+ */
+static int nr_scalable_vdd;
+
+/* OMAP3 VDD sturctures */
+static struct omap_vdd_info omap3_vdd_info[] = {
+	{
+		.vp_offs = {
+			.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,
+		},
+		.voltdm = {
+			.name = "mpu",
+		},
+	},
+	{
+		.vp_offs = {
+			.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,
+		},
+		.voltdm = {
+			.name = "core",
+		},
+	},
+};
+
+#define OMAP3_NR_SCALABLE_VDD ARRAY_SIZE(omap3_vdd_info)
+
+/* OMAP4 VDD sturctures */
+static struct omap_vdd_info omap4_vdd_info[] = {
+	{
+		.vp_offs = {
+			.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,
+		},
+		.voltdm = {
+			.name = "mpu",
+		},
+	},
+	{
+		.vp_offs = {
+			.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,
+		},
+		.voltdm = {
+			.name = "iva",
+		},
+	},
+	{
+		.vp_offs = {
+			.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,
+		},
+		.voltdm = {
+			.name = "core",
+		},
+	},
+};
+
+#define OMAP4_NR_SCALABLE_VDD ARRAY_SIZE(omap4_vdd_info)
+
+/*
+ * Structures containing OMAP3430/OMAP3630 voltage supported and various
+ * voltage dependent data for each VDD.
+ */
+#define VOLT_DATA_DEFINE(_v_nom, _efuse_offs, _errminlimit, _errgain)	\
+{									\
+	.volt_nominal	= _v_nom,					\
+	.sr_efuse_offs	= _efuse_offs,					\
+	.sr_errminlimit	= _errminlimit,					\
+	.vp_errgain	= _errgain					\
+}
+
+/* VDD1 */
+static struct omap_volt_data omap34xx_vddmpu_volt_data[] = {
+	VOLT_DATA_DEFINE(OMAP3430_VDD_MPU_OPP1_UV, OMAP343X_CONTROL_FUSE_OPP1_VDD1, 0xf4, 0x0c),
+	VOLT_DATA_DEFINE(OMAP3430_VDD_MPU_OPP2_UV, OMAP343X_CONTROL_FUSE_OPP2_VDD1, 0xf4, 0x0c),
+	VOLT_DATA_DEFINE(OMAP3430_VDD_MPU_OPP3_UV, OMAP343X_CONTROL_FUSE_OPP3_VDD1, 0xf9, 0x18),
+	VOLT_DATA_DEFINE(OMAP3430_VDD_MPU_OPP4_UV, OMAP343X_CONTROL_FUSE_OPP4_VDD1, 0xf9, 0x18),
+	VOLT_DATA_DEFINE(OMAP3430_VDD_MPU_OPP5_UV, OMAP343X_CONTROL_FUSE_OPP5_VDD1, 0xf9, 0x18),
+	VOLT_DATA_DEFINE(0, 0, 0, 0),
+};
+
+static struct omap_volt_data omap36xx_vddmpu_volt_data[] = {
+	VOLT_DATA_DEFINE(OMAP3630_VDD_MPU_OPP50_UV, OMAP3630_CONTROL_FUSE_OPP50_VDD1, 0xf4, 0x0c),
+	VOLT_DATA_DEFINE(OMAP3630_VDD_MPU_OPP100_UV, OMAP3630_CONTROL_FUSE_OPP100_VDD1, 0xf9, 0x16),
+	VOLT_DATA_DEFINE(OMAP3630_VDD_MPU_OPP120_UV, OMAP3630_CONTROL_FUSE_OPP120_VDD1, 0xfa, 0x23),
+	VOLT_DATA_DEFINE(OMAP3630_VDD_MPU_OPP1G_UV, OMAP3630_CONTROL_FUSE_OPP1G_VDD1, 0xfa, 0x27),
+	VOLT_DATA_DEFINE(0, 0, 0, 0),
+};
+
+/* VDD2 */
+static struct omap_volt_data omap34xx_vddcore_volt_data[] = {
+	VOLT_DATA_DEFINE(OMAP3430_VDD_CORE_OPP1_UV, OMAP343X_CONTROL_FUSE_OPP1_VDD2, 0xf4, 0x0c),
+	VOLT_DATA_DEFINE(OMAP3430_VDD_CORE_OPP2_UV, OMAP343X_CONTROL_FUSE_OPP2_VDD2, 0xf4, 0x0c),
+	VOLT_DATA_DEFINE(OMAP3430_VDD_CORE_OPP3_UV, OMAP343X_CONTROL_FUSE_OPP3_VDD2, 0xf9, 0x18),
+	VOLT_DATA_DEFINE(0, 0, 0, 0),
+};
+
+static struct omap_volt_data omap36xx_vddcore_volt_data[] = {
+	VOLT_DATA_DEFINE(OMAP3630_VDD_CORE_OPP50_UV, OMAP3630_CONTROL_FUSE_OPP50_VDD2, 0xf4, 0x0c),
+	VOLT_DATA_DEFINE(OMAP3630_VDD_CORE_OPP100_UV, OMAP3630_CONTROL_FUSE_OPP100_VDD2, 0xf9, 0x16),
+	VOLT_DATA_DEFINE(0, 0, 0, 0),
+};
+
+/*
+ * Structures containing OMAP4430 voltage supported and various
+ * voltage dependent data for each VDD.
+ */
+static struct omap_volt_data omap44xx_vdd_mpu_volt_data[] = {
+	VOLT_DATA_DEFINE(OMAP4430_VDD_MPU_OPP50_UV, OMAP44XX_CONTROL_FUSE_MPU_OPP50, 0xf4, 0x0c),
+	VOLT_DATA_DEFINE(OMAP4430_VDD_MPU_OPP100_UV, OMAP44XX_CONTROL_FUSE_MPU_OPP100, 0xf9, 0x16),
+	VOLT_DATA_DEFINE(OMAP4430_VDD_MPU_OPPTURBO_UV, OMAP44XX_CONTROL_FUSE_MPU_OPPTURBO, 0xfa, 0x23),
+	VOLT_DATA_DEFINE(OMAP4430_VDD_MPU_OPPNITRO_UV, OMAP44XX_CONTROL_FUSE_MPU_OPPNITRO, 0xfa, 0x27),
+	VOLT_DATA_DEFINE(0, 0, 0, 0),
+};
+
+static struct omap_volt_data omap44xx_vdd_iva_volt_data[] = {
+	VOLT_DATA_DEFINE(OMAP4430_VDD_IVA_OPP50_UV, OMAP44XX_CONTROL_FUSE_IVA_OPP50, 0xf4, 0x0c),
+	VOLT_DATA_DEFINE(OMAP4430_VDD_IVA_OPP100_UV, OMAP44XX_CONTROL_FUSE_IVA_OPP100, 0xf9, 0x16),
+	VOLT_DATA_DEFINE(OMAP4430_VDD_IVA_OPPTURBO_UV, OMAP44XX_CONTROL_FUSE_IVA_OPPTURBO, 0xfa, 0x23),
+	VOLT_DATA_DEFINE(0, 0, 0, 0),
+};
+
+static struct omap_volt_data omap44xx_vdd_core_volt_data[] = {
+	VOLT_DATA_DEFINE(OMAP4430_VDD_CORE_OPP50_UV, OMAP44XX_CONTROL_FUSE_CORE_OPP50, 0xf4, 0x0c),
+	VOLT_DATA_DEFINE(OMAP4430_VDD_CORE_OPP100_UV, OMAP44XX_CONTROL_FUSE_CORE_OPP100, 0xf9, 0x16),
+	VOLT_DATA_DEFINE(0, 0, 0, 0),
+};
+
+static struct dentry *voltage_dir;
+
+/* Init function pointers */
+static void (*vc_init) (struct omap_vdd_info *vdd);
+static int (*vdd_data_configure) (struct omap_vdd_info *vdd);
+
+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);
+}
+
+/* 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(vdd->vp_reg.prm_mod, vdd->vp_offs.voltage);
+	pr_notice("curr_vsel = %x\n", vsel);
+
+	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;
+	u16 mod;
+	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;
+	}
+
+	mod = vdd->vp_reg.prm_mod;
+
+	vsel = vdd->pmic_info->uv_to_vsel(uvdc);
+
+	vpconfig = vdd->read_reg(mod, vdd->vp_offs.vpconfig);
+	vpconfig &= ~(vdd->vp_reg.vpconfig_initvoltage_mask |
+			vdd->vp_reg.vpconfig_initvdd);
+	vpconfig |= vsel << vdd->vp_reg.vpconfig_initvoltage_shift;
+
+	vdd->write_reg(vpconfig, mod, vdd->vp_offs.vpconfig);
+
+	/* Trigger initVDD value copy to voltage processor */
+	vdd->write_reg((vpconfig | vdd->vp_reg.vpconfig_initvdd), mod,
+			vdd->vp_offs.vpconfig);
+
+	/* Clear initVDD copy trigger bit */
+	vdd->write_reg(vpconfig, mod, vdd->vp_offs.vpconfig);
+}
+
+/* Generic voltage init functions */
+static void __init vp_init(struct omap_vdd_info *vdd)
+{
+	u32 vp_val;
+	u16 mod;
+
+	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;
+	}
+
+	mod = vdd->vp_reg.prm_mod;
+
+	vp_val = vdd->vp_reg.vpconfig_erroroffset |
+		(vdd->vp_reg.vpconfig_errorgain <<
+		vdd->vp_reg.vpconfig_errorgain_shift) |
+		vdd->vp_reg.vpconfig_timeouten;
+	vdd->write_reg(vp_val, mod, vdd->vp_offs.vpconfig);
+
+	vp_val = ((vdd->vp_reg.vstepmin_smpswaittimemin <<
+		vdd->vp_reg.vstepmin_smpswaittimemin_shift) |
+		(vdd->vp_reg.vstepmin_stepmin <<
+		vdd->vp_reg.vstepmin_stepmin_shift));
+	vdd->write_reg(vp_val, mod, vdd->vp_offs.vstepmin);
+
+	vp_val = ((vdd->vp_reg.vstepmax_smpswaittimemax <<
+		vdd->vp_reg.vstepmax_smpswaittimemax_shift) |
+		(vdd->vp_reg.vstepmax_stepmax <<
+		vdd->vp_reg.vstepmax_stepmax_shift));
+	vdd->write_reg(vp_val, mod, vdd->vp_offs.vstepmax);
+
+	vp_val = ((vdd->vp_reg.vlimitto_vddmax <<
+		vdd->vp_reg.vlimitto_vddmax_shift) |
+		(vdd->vp_reg.vlimitto_vddmin <<
+		vdd->vp_reg.vlimitto_vddmin_shift) |
+		(vdd->vp_reg.vlimitto_timeout <<
+		vdd->vp_reg.vlimitto_timeout_shift));
+	vdd->write_reg(vp_val, mod, vdd->vp_offs.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_reg.vpconfig_errorgain));
+	(void) debugfs_create_x16("vp_smpswaittimemin", S_IRUGO,
+				vdd->debug_dir,
+				&(vdd->vp_reg.vstepmin_smpswaittimemin));
+	(void) debugfs_create_x8("vp_stepmin", S_IRUGO, vdd->debug_dir,
+				&(vdd->vp_reg.vstepmin_stepmin));
+	(void) debugfs_create_x16("vp_smpswaittimemax", S_IRUGO,
+				vdd->debug_dir,
+				&(vdd->vp_reg.vstepmax_smpswaittimemax));
+	(void) debugfs_create_x8("vp_stepmax", S_IRUGO, vdd->debug_dir,
+				&(vdd->vp_reg.vstepmax_stepmax));
+	(void) debugfs_create_x8("vp_vddmax", S_IRUGO, vdd->debug_dir,
+				&(vdd->vp_reg.vlimitto_vddmax));
+	(void) debugfs_create_x8("vp_vddmin", S_IRUGO, vdd->debug_dir,
+				&(vdd->vp_reg.vlimitto_vddmin));
+	(void) debugfs_create_x16("vp_timeout", S_IRUGO, vdd->debug_dir,
+				&(vdd->vp_reg.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;
+	u32 vc_cmdval, vp_errgain_val;
+	u16 vp_mod, vc_mod;
+
+	/* 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;
+	}
+
+	vp_mod = vdd->vp_reg.prm_mod;
+	vc_mod = vdd->vc_reg.prm_mod;
+
+	/* 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(vp_mod, vdd->vp_offs.voltage);
+
+	/* Setting the ON voltage to the new target voltage */
+	vc_cmdval = vdd->read_reg(vc_mod, vdd->vc_reg.cmdval_reg);
+	vc_cmdval &= ~vdd->vc_reg.cmd_on_mask;
+	vc_cmdval |= (*target_vsel << vdd->vc_reg.cmd_on_shift);
+	vdd->write_reg(vc_cmdval, vc_mod, vdd->vc_reg.cmdval_reg);
+
+	/* Setting vp errorgain based on the voltage */
+	if (volt_data) {
+		vp_errgain_val = vdd->read_reg(vp_mod,
+				vdd->vp_offs.vpconfig);
+		vdd->vp_reg.vpconfig_errorgain = volt_data->vp_errgain;
+		vp_errgain_val &= ~vdd->vp_reg.vpconfig_errorgain_mask;
+		vp_errgain_val |= vdd->vp_reg.vpconfig_errorgain <<
+				vdd->vp_reg.vpconfig_errorgain_shift;
+		vdd->write_reg(vp_errgain_val, vp_mod,
+				vdd->vp_offs.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;
+	u16 mod;
+	u8 target_vsel, current_vsel;
+	int ret;
+
+	ret = _pre_volt_scale(vdd, target_volt, &target_vsel, &current_vsel);
+	if (ret)
+		return ret;
+
+	mod = vdd->vc_reg.prm_mod;
+
+	vc_valid = vdd->vc_reg.valid;
+	vc_bypass_val_reg = vdd->vc_reg.bypass_val_reg;
+	vc_bypass_value = (target_vsel << vdd->vc_reg.data_shift) |
+			(vdd->pmic_info->pmic_reg <<
+			vdd->vc_reg.regaddr_shift) |
+			(vdd->pmic_info->i2c_slave_addr <<
+			vdd->vc_reg.slaveaddr_shift);
+
+	vdd->write_reg(vc_bypass_value, mod, vc_bypass_val_reg);
+	vdd->write_reg(vc_bypass_value | vc_valid, mod, vc_bypass_val_reg);
+
+	vc_bypass_value = vdd->read_reg(mod, 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(mod, 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;
+	u16 mod, ocp_mod;
+	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;
+
+	mod = vdd->vp_reg.prm_mod;
+	ocp_mod = vdd->ocp_mod;
+	prm_irqst_reg = vdd->prm_irqst_reg;
+
+	/*
+	 * Clear all pending TransactionDone interrupt/status. Typical latency
+	 * is <3us
+	 */
+	while (timeout++ < VP_TRANXDONE_TIMEOUT) {
+		vdd->write_reg(vdd->vp_reg.tranxdone_status,
+				ocp_mod, prm_irqst_reg);
+		if (!(vdd->read_reg(ocp_mod, prm_irqst_reg) &
+				vdd->vp_reg.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(mod, vdd->vp_offs.vpconfig);
+	vpconfig &= ~(vdd->vp_reg.vpconfig_initvdd |
+			vdd->vp_reg.vpconfig_forceupdate |
+			vdd->vp_reg.vpconfig_initvoltage_mask);
+	vpconfig |= ((target_vsel <<
+			vdd->vp_reg.vpconfig_initvoltage_shift));
+	vdd->write_reg(vpconfig, mod, vdd->vp_offs.vpconfig);
+
+	/* Trigger initVDD value copy to voltage processor */
+	vpconfig |= vdd->vp_reg.vpconfig_initvdd;
+	vdd->write_reg(vpconfig, mod, vdd->vp_offs.vpconfig);
+
+	/* Force update of voltage */
+	vpconfig |= vdd->vp_reg.vpconfig_forceupdate;
+	vdd->write_reg(vpconfig, mod, vdd->vp_offs.vpconfig);
+
+	/*
+	 * Wait for TransactionDone. Typical latency is <200us.
+	 * Depends on SMPSWAITTIMEMIN/MAX and voltage change
+	 */
+	timeout = 0;
+	omap_test_timeout((vdd->read_reg(ocp_mod, prm_irqst_reg) &
+			vdd->vp_reg.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_reg.tranxdone_status,
+				ocp_mod, prm_irqst_reg);
+		if (!(vdd->read_reg(ocp_mod, prm_irqst_reg) &
+				vdd->vp_reg.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(mod, vdd->vp_offs.vpconfig);
+	/* Clear initVDD copy trigger bit */
+	vpconfig &= ~vdd->vp_reg.vpconfig_initvdd;;
+	vdd->write_reg(vpconfig, mod, vdd->vp_offs.vpconfig);
+	/* Clear force bit */
+	vpconfig &= ~vdd->vp_reg.vpconfig_forceupdate;
+	vdd->write_reg(vpconfig, mod, vdd->vp_offs.vpconfig);
+
+	return 0;
+}
+
+/* OMAP3 specific voltage init functions */
+
+/*
+ * Intializes the voltage controller registers with the PMIC and board
+ * specific parameters and voltage setup times for OMAP3.
+ */
+static void __init omap3_vc_init(struct omap_vdd_info *vdd)
+{
+	u32 vc_val;
+	u16 mod;
+	u8 on_vsel, onlp_vsel, ret_vsel, off_vsel;
+	static bool is_initialized;
+
+	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;
+	}
+
+	mod = vdd->vc_reg.prm_mod;
+
+	/* Set up the SMPS_SA(i2c slave address in VC */
+	vc_val = vdd->read_reg(mod, vdd->vc_reg.smps_sa_reg);
+	vc_val &= ~vdd->vc_reg.smps_sa_mask;
+	vc_val |= vdd->pmic_info->i2c_slave_addr << vdd->vc_reg.smps_sa_shift;
+	vdd->write_reg(vc_val, mod, vdd->vc_reg.smps_sa_reg);
+
+	/* Setup the VOLRA(pmic reg addr) in VC */
+	vc_val = vdd->read_reg(mod, vdd->vc_reg.smps_volra_reg);
+	vc_val &= ~vdd->vc_reg.smps_volra_mask;
+	vc_val |= vdd->pmic_info->pmic_reg << vdd->vc_reg.smps_volra_shift;
+	vdd->write_reg(vc_val, mod, vdd->vc_reg.smps_volra_reg);
+
+	/*Configure the setup times */
+	vc_val = vdd->read_reg(mod, vdd->vc_reg.voltsetup_reg);
+	vc_val &= ~vdd->vc_reg.voltsetup_mask;
+	vc_val |= vdd->pmic_info->volt_setup_time <<
+			vdd->vc_reg.voltsetup_shift;
+	vdd->write_reg(vc_val, mod, vdd->vc_reg.voltsetup_reg);
+
+	/* 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_reg.cmd_on_shift) |
+		(onlp_vsel << vdd->vc_reg.cmd_onlp_shift) |
+		(ret_vsel << vdd->vc_reg.cmd_ret_shift) |
+		(off_vsel << vdd->vc_reg.cmd_off_shift));
+	vdd->write_reg(vc_val, mod, vdd->vc_reg.cmdval_reg);
+
+	if (is_initialized)
+		return;
+
+	/* Generic VC parameters init */
+	vdd->write_reg(OMAP3430_CMD1_MASK | OMAP3430_RAV1_MASK, mod,
+			OMAP3_PRM_VC_CH_CONF_OFFSET);
+	vdd->write_reg(OMAP3430_MCODE_SHIFT | OMAP3430_HSEN_MASK, mod,
+			OMAP3_PRM_VC_I2C_CFG_OFFSET);
+	vdd->write_reg(OMAP3_CLKSETUP, mod, OMAP3_PRM_CLKSETUP_OFFSET);
+	vdd->write_reg(OMAP3_VOLTOFFSET, mod, OMAP3_PRM_VOLTOFFSET_OFFSET);
+	vdd->write_reg(OMAP3_VOLTSETUP2, mod, OMAP3_PRM_VOLTSETUP2_OFFSET);
+	is_initialized = true;
+}
+
+/* Sets up all the VDD related info for OMAP3 */
+static int __init omap3_vdd_data_configure(struct omap_vdd_info *vdd)
+{
+	struct clk *sys_ck;
+	u32 sys_clk_speed, timeout_val, waittime;
+
+	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);
+		return -EINVAL;
+	}
+
+	if (!strcmp(vdd->voltdm.name, "mpu")) {
+		if (cpu_is_omap3630())
+			vdd->volt_data = omap36xx_vddmpu_volt_data;
+		else
+			vdd->volt_data = omap34xx_vddmpu_volt_data;
+
+		vdd->vp_reg.tranxdone_status = OMAP3430_VP1_TRANXDONE_ST_MASK;
+		vdd->vc_reg.cmdval_reg = OMAP3_PRM_VC_CMD_VAL_0_OFFSET;
+		vdd->vc_reg.smps_sa_shift = OMAP3430_PRM_VC_SMPS_SA_SA0_SHIFT;
+		vdd->vc_reg.smps_sa_mask = OMAP3430_PRM_VC_SMPS_SA_SA0_MASK;
+		vdd->vc_reg.smps_volra_shift = OMAP3430_VOLRA0_SHIFT;
+		vdd->vc_reg.smps_volra_mask = OMAP3430_VOLRA0_MASK;
+		vdd->vc_reg.voltsetup_shift = OMAP3430_SETUP_TIME1_SHIFT;
+		vdd->vc_reg.voltsetup_mask = OMAP3430_SETUP_TIME1_MASK;
+	} else if (!strcmp(vdd->voltdm.name, "core")) {
+		if (cpu_is_omap3630())
+			vdd->volt_data = omap36xx_vddcore_volt_data;
+		else
+			vdd->volt_data = omap34xx_vddcore_volt_data;
+
+		vdd->vp_reg.tranxdone_status = OMAP3430_VP2_TRANXDONE_ST_MASK;
+		vdd->vc_reg.cmdval_reg = OMAP3_PRM_VC_CMD_VAL_1_OFFSET;
+		vdd->vc_reg.smps_sa_shift = OMAP3430_PRM_VC_SMPS_SA_SA1_SHIFT;
+		vdd->vc_reg.smps_sa_mask = OMAP3430_PRM_VC_SMPS_SA_SA1_MASK;
+		vdd->vc_reg.smps_volra_shift = OMAP3430_VOLRA1_SHIFT;
+		vdd->vc_reg.smps_volra_mask = OMAP3430_VOLRA1_MASK;
+		vdd->vc_reg.voltsetup_shift = OMAP3430_SETUP_TIME2_SHIFT;
+		vdd->vc_reg.voltsetup_mask = OMAP3430_SETUP_TIME2_MASK;
+	} else {
+		pr_warning("%s: vdd_%s does not exisit in OMAP3\n",
+			__func__, vdd->voltdm.name);
+		return -EINVAL;
+	}
+
+	/*
+	 * Sys clk rate is require to calculate vp timeout value and
+	 * smpswaittimemin and smpswaittimemax.
+	 */
+	sys_ck = clk_get(NULL, "sys_ck");
+	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->curr_volt = 1200000;
+	vdd->ocp_mod = OCP_MOD;
+	vdd->prm_irqst_reg = OMAP3_PRM_IRQSTATUS_MPU_OFFSET;
+	vdd->read_reg = omap3_voltage_read_reg;
+	vdd->write_reg = omap3_voltage_write_reg;
+	vdd->volt_scale = vp_forceupdate_scale_voltage;
+	vdd->vp_enabled = false;
+
+	/* VC parameters */
+	vdd->vc_reg.prm_mod = OMAP3430_GR_MOD;
+	vdd->vc_reg.smps_sa_reg = OMAP3_PRM_VC_SMPS_SA_OFFSET;
+	vdd->vc_reg.smps_volra_reg = OMAP3_PRM_VC_SMPS_VOL_RA_OFFSET;
+	vdd->vc_reg.bypass_val_reg = OMAP3_PRM_VC_BYPASS_VAL_OFFSET;
+	vdd->vc_reg.voltsetup_reg = OMAP3_PRM_VOLTSETUP1_OFFSET;
+	vdd->vc_reg.data_shift = OMAP3430_DATA_SHIFT;
+	vdd->vc_reg.slaveaddr_shift = OMAP3430_SLAVEADDR_SHIFT;
+	vdd->vc_reg.regaddr_shift = OMAP3430_REGADDR_SHIFT;
+	vdd->vc_reg.valid = OMAP3430_VALID_MASK;
+	vdd->vc_reg.cmd_on_shift = OMAP3430_VC_CMD_ON_SHIFT;
+	vdd->vc_reg.cmd_on_mask = OMAP3430_VC_CMD_ON_MASK;
+	vdd->vc_reg.cmd_onlp_shift = OMAP3430_VC_CMD_ONLP_SHIFT;
+	vdd->vc_reg.cmd_ret_shift = OMAP3430_VC_CMD_RET_SHIFT;
+	vdd->vc_reg.cmd_off_shift = OMAP3430_VC_CMD_OFF_SHIFT;
+
+	vdd->vp_reg.prm_mod = OMAP3430_GR_MOD;
+
+	/* VPCONFIG bit fields */
+	vdd->vp_reg.vpconfig_erroroffset = (vdd->pmic_info->vp_erroroffset <<
+				 OMAP3430_ERROROFFSET_SHIFT);
+	vdd->vp_reg.vpconfig_errorgain_mask = OMAP3430_ERRORGAIN_MASK;
+	vdd->vp_reg.vpconfig_errorgain_shift = OMAP3430_ERRORGAIN_SHIFT;
+	vdd->vp_reg.vpconfig_initvoltage_shift = OMAP3430_INITVOLTAGE_SHIFT;
+	vdd->vp_reg.vpconfig_initvoltage_mask = OMAP3430_INITVOLTAGE_MASK;
+	vdd->vp_reg.vpconfig_timeouten = OMAP3430_TIMEOUTEN_MASK;
+	vdd->vp_reg.vpconfig_initvdd = OMAP3430_INITVDD_MASK;
+	vdd->vp_reg.vpconfig_forceupdate = OMAP3430_FORCEUPDATE_MASK;
+	vdd->vp_reg.vpconfig_vpenable = OMAP3430_VPENABLE_MASK;
+
+	/* VSTEPMIN VSTEPMAX bit fields */
+	waittime = ((vdd->pmic_info->step_size / vdd->pmic_info->slew_rate) *
+				sys_clk_speed) / 1000;
+	vdd->vp_reg.vstepmin_smpswaittimemin = waittime;
+	vdd->vp_reg.vstepmax_smpswaittimemax = waittime;
+	vdd->vp_reg.vstepmin_stepmin = vdd->pmic_info->vp_vstepmin;
+	vdd->vp_reg.vstepmax_stepmax = vdd->pmic_info->vp_vstepmax;
+	vdd->vp_reg.vstepmin_smpswaittimemin_shift =
+				OMAP3430_SMPSWAITTIMEMIN_SHIFT;
+	vdd->vp_reg.vstepmax_smpswaittimemax_shift =
+				OMAP3430_SMPSWAITTIMEMAX_SHIFT;
+	vdd->vp_reg.vstepmin_stepmin_shift = OMAP3430_VSTEPMIN_SHIFT;
+	vdd->vp_reg.vstepmax_stepmax_shift = OMAP3430_VSTEPMAX_SHIFT;
+
+	/* VLIMITTO bit fields */
+	timeout_val = (sys_clk_speed * vdd->pmic_info->vp_timeout_us) / 1000;
+	vdd->vp_reg.vlimitto_timeout = timeout_val;
+	vdd->vp_reg.vlimitto_vddmin = vdd->pmic_info->vp_vddmin;
+	vdd->vp_reg.vlimitto_vddmax = vdd->pmic_info->vp_vddmax;
+	vdd->vp_reg.vlimitto_vddmin_shift = OMAP3430_VDDMIN_SHIFT;
+	vdd->vp_reg.vlimitto_vddmax_shift = OMAP3430_VDDMAX_SHIFT;
+	vdd->vp_reg.vlimitto_timeout_shift = OMAP3430_TIMEOUT_SHIFT;
+
+	return 0;
+}
+
+/* OMAP4 specific voltage init functions */
+static void __init omap4_vc_init(struct omap_vdd_info *vdd)
+{
+	u32 vc_val;
+	u16 mod;
+	static bool is_initialized;
+
+	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;
+	}
+
+	mod = vdd->vc_reg.prm_mod;
+
+	/* Set up the SMPS_SA(i2c slave address in VC */
+	vc_val = vdd->read_reg(mod, vdd->vc_reg.smps_sa_reg);
+	vc_val &= ~vdd->vc_reg.smps_sa_mask;
+	vc_val |= vdd->pmic_info->i2c_slave_addr << vdd->vc_reg.smps_sa_shift;
+	vdd->write_reg(vc_val, mod, vdd->vc_reg.smps_sa_reg);
+
+	/* Setup the VOLRA(pmic reg addr) in VC */
+	vc_val = vdd->read_reg(mod, vdd->vc_reg.smps_volra_reg);
+	vc_val &= ~vdd->vc_reg.smps_volra_mask;
+	vc_val |= vdd->pmic_info->pmic_reg << vdd->vc_reg.smps_volra_shift;
+	vdd->write_reg(vc_val, mod, vdd->vc_reg.smps_volra_reg);
+
+	/* TODO: Configure setup times and CMD_VAL values*/
+
+	if (is_initialized)
+		return;
+
+	/* Generic VC parameters init */
+	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, mod, OMAP4_PRM_VC_CFG_CHANNEL_OFFSET);
+
+	vc_val = (0x60 << OMAP4430_SCLL_SHIFT | 0x26 << OMAP4430_SCLH_SHIFT);
+	vdd->write_reg(vc_val, mod, OMAP4_PRM_VC_CFG_I2C_CLK_OFFSET);
+
+	is_initialized = true;
+}
+
+/* Sets up all the VDD related info for OMAP4 */
+static int __init omap4_vdd_data_configure(struct omap_vdd_info *vdd)
+{
+	struct clk *sys_ck;
+	u32 sys_clk_speed, timeout_val, waittime;
+
+	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);
+		return -EINVAL;
+	}
+
+	if (!strcmp(vdd->voltdm.name, "mpu")) {
+		vdd->volt_data = omap44xx_vdd_mpu_volt_data;
+		vdd->vp_reg.tranxdone_status =
+				OMAP4430_VP_MPU_TRANXDONE_ST_MASK;
+		vdd->vc_reg.cmdval_reg = OMAP4_PRM_VC_VAL_CMD_VDD_MPU_L_OFFSET;
+		vdd->vc_reg.smps_sa_shift =
+				OMAP4430_SA_VDD_MPU_L_PRM_VC_SMPS_SA_SHIFT;
+		vdd->vc_reg.smps_sa_mask =
+				OMAP4430_SA_VDD_MPU_L_PRM_VC_SMPS_SA_MASK;
+		vdd->vc_reg.smps_volra_shift = OMAP4430_VOLRA_VDD_MPU_L_SHIFT;
+		vdd->vc_reg.smps_volra_mask = OMAP4430_VOLRA_VDD_MPU_L_MASK;
+		vdd->vc_reg.voltsetup_reg =
+				OMAP4_PRM_VOLTSETUP_MPU_RET_SLEEP_OFFSET;
+		vdd->prm_irqst_reg = OMAP4_PRM_IRQSTATUS_MPU_2_OFFSET;
+	} else if (!strcmp(vdd->voltdm.name, "core")) {
+		vdd->volt_data = omap44xx_vdd_core_volt_data;
+		vdd->vp_reg.tranxdone_status =
+				OMAP4430_VP_CORE_TRANXDONE_ST_MASK;
+		vdd->vc_reg.cmdval_reg =
+				OMAP4_PRM_VC_VAL_CMD_VDD_CORE_L_OFFSET;
+		vdd->vc_reg.smps_sa_shift = OMAP4430_SA_VDD_CORE_L_0_6_SHIFT;
+		vdd->vc_reg.smps_sa_mask = OMAP4430_SA_VDD_CORE_L_0_6_MASK;
+		vdd->vc_reg.smps_volra_shift = OMAP4430_VOLRA_VDD_CORE_L_SHIFT;
+		vdd->vc_reg.smps_volra_mask = OMAP4430_VOLRA_VDD_CORE_L_MASK;
+		vdd->vc_reg.voltsetup_reg =
+				OMAP4_PRM_VOLTSETUP_CORE_RET_SLEEP_OFFSET;
+		vdd->prm_irqst_reg = OMAP4_PRM_IRQSTATUS_MPU_OFFSET;
+	} else if (!strcmp(vdd->voltdm.name, "iva")) {
+		vdd->volt_data = omap44xx_vdd_iva_volt_data;
+		vdd->vp_reg.tranxdone_status =
+				OMAP4430_VP_IVA_TRANXDONE_ST_MASK;
+		vdd->vc_reg.cmdval_reg = OMAP4_PRM_VC_VAL_CMD_VDD_IVA_L_OFFSET;
+		vdd->vc_reg.smps_sa_shift =
+				OMAP4430_SA_VDD_IVA_L_PRM_VC_SMPS_SA_SHIFT;
+		vdd->vc_reg.smps_sa_mask =
+				OMAP4430_SA_VDD_IVA_L_PRM_VC_SMPS_SA_MASK;
+		vdd->vc_reg.smps_volra_shift = OMAP4430_VOLRA_VDD_IVA_L_SHIFT;
+		vdd->vc_reg.smps_volra_mask = OMAP4430_VOLRA_VDD_IVA_L_MASK;
+		vdd->vc_reg.voltsetup_reg =
+				OMAP4_PRM_VOLTSETUP_IVA_RET_SLEEP_OFFSET;
+		vdd->prm_irqst_reg = OMAP4_PRM_IRQSTATUS_MPU_OFFSET;
+	} else {
+		pr_warning("%s: vdd_%s does not exisit in OMAP4\n",
+			__func__, vdd->voltdm.name);
+		return -EINVAL;
+	}
+
+	/*
+	 * Sys clk rate is require to calculate vp timeout value and
+	 * smpswaittimemin and smpswaittimemax.
+	 */
+	sys_ck = clk_get(NULL, "sys_clkin_ck");
+	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->curr_volt = 1200000;
+	vdd->ocp_mod = OMAP4430_PRM_OCP_SOCKET_INST;
+	vdd->read_reg = omap4_voltage_read_reg;
+	vdd->write_reg = omap4_voltage_write_reg;
+	vdd->volt_scale = vp_forceupdate_scale_voltage;
+	vdd->vp_enabled = false;
+
+	/* VC parameters */
+	vdd->vc_reg.prm_mod = OMAP4430_PRM_DEVICE_INST;
+	vdd->vc_reg.smps_sa_reg = OMAP4_PRM_VC_SMPS_SA_OFFSET;
+	vdd->vc_reg.smps_volra_reg = OMAP4_PRM_VC_VAL_SMPS_RA_VOL_OFFSET;
+	vdd->vc_reg.bypass_val_reg = OMAP4_PRM_VC_VAL_BYPASS_OFFSET;
+	vdd->vc_reg.data_shift = OMAP4430_DATA_SHIFT;
+	vdd->vc_reg.slaveaddr_shift = OMAP4430_SLAVEADDR_SHIFT;
+	vdd->vc_reg.regaddr_shift = OMAP4430_REGADDR_SHIFT;
+	vdd->vc_reg.valid = OMAP4430_VALID_MASK;
+	vdd->vc_reg.cmd_on_shift = OMAP4430_ON_SHIFT;
+	vdd->vc_reg.cmd_on_mask = OMAP4430_ON_MASK;
+	vdd->vc_reg.cmd_onlp_shift = OMAP4430_ONLP_SHIFT;
+	vdd->vc_reg.cmd_ret_shift = OMAP4430_RET_SHIFT;
+	vdd->vc_reg.cmd_off_shift = OMAP4430_OFF_SHIFT;
+
+	vdd->vp_reg.prm_mod = OMAP4430_PRM_DEVICE_INST;
+
+	/* VPCONFIG bit fields */
+	vdd->vp_reg.vpconfig_erroroffset = (vdd->pmic_info->vp_erroroffset <<
+				 OMAP4430_ERROROFFSET_SHIFT);
+	vdd->vp_reg.vpconfig_errorgain_mask = OMAP4430_ERRORGAIN_MASK;
+	vdd->vp_reg.vpconfig_errorgain_shift = OMAP4430_ERRORGAIN_SHIFT;
+	vdd->vp_reg.vpconfig_initvoltage_shift = OMAP4430_INITVOLTAGE_SHIFT;
+	vdd->vp_reg.vpconfig_initvoltage_mask = OMAP4430_INITVOLTAGE_MASK;
+	vdd->vp_reg.vpconfig_timeouten = OMAP4430_TIMEOUTEN_MASK;
+	vdd->vp_reg.vpconfig_initvdd = OMAP4430_INITVDD_MASK;
+	vdd->vp_reg.vpconfig_forceupdate = OMAP4430_FORCEUPDATE_MASK;
+	vdd->vp_reg.vpconfig_vpenable = OMAP4430_VPENABLE_MASK;
+
+	/* VSTEPMIN VSTEPMAX bit fields */
+	waittime = ((vdd->pmic_info->step_size / vdd->pmic_info->slew_rate) *
+				sys_clk_speed) / 1000;
+	vdd->vp_reg.vstepmin_smpswaittimemin = waittime;
+	vdd->vp_reg.vstepmax_smpswaittimemax = waittime;
+	vdd->vp_reg.vstepmin_stepmin = vdd->pmic_info->vp_vstepmin;
+	vdd->vp_reg.vstepmax_stepmax = vdd->pmic_info->vp_vstepmax;
+	vdd->vp_reg.vstepmin_smpswaittimemin_shift =
+			OMAP4430_SMPSWAITTIMEMIN_SHIFT;
+	vdd->vp_reg.vstepmax_smpswaittimemax_shift =
+			OMAP4430_SMPSWAITTIMEMAX_SHIFT;
+	vdd->vp_reg.vstepmin_stepmin_shift = OMAP4430_VSTEPMIN_SHIFT;
+	vdd->vp_reg.vstepmax_stepmax_shift = OMAP4430_VSTEPMAX_SHIFT;
+
+	/* VLIMITTO bit fields */
+	timeout_val = (sys_clk_speed * vdd->pmic_info->vp_timeout_us) / 1000;
+	vdd->vp_reg.vlimitto_timeout = timeout_val;
+	vdd->vp_reg.vlimitto_vddmin = vdd->pmic_info->vp_vddmin;
+	vdd->vp_reg.vlimitto_vddmax = vdd->pmic_info->vp_vddmax;
+	vdd->vp_reg.vlimitto_vddmin_shift = OMAP4430_VDDMIN_SHIFT;
+	vdd->vp_reg.vlimitto_vddmax_shift = OMAP4430_VDDMAX_SHIFT;
+	vdd->vp_reg.vlimitto_timeout_shift = OMAP4430_TIMEOUT_SHIFT;
+
+	return 0;
+}
+
+/* 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.
+ *
+ * This API returns the current voltage for the specified voltage processor
+ */
+unsigned long omap_vp_get_curr_volt(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(vdd->vp_reg.prm_mod,
+			vdd->vp_offs.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;
+	u16 mod;
+
+	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;
+	}
+
+	mod = vdd->vp_reg.prm_mod;
+
+	/* If VP is already enabled, do nothing. Return */
+	if (vdd->vp_enabled)
+		return;
+
+	vp_latch_vsel(vdd);
+
+	/* Enable VP */
+	vpconfig = vdd->read_reg(mod, vdd->vp_offs.vpconfig);
+	vpconfig |= vdd->vp_reg.vpconfig_vpenable;
+	vdd->write_reg(vpconfig, mod, vdd->vp_offs.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;
+	u16 mod;
+	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;
+	}
+
+	mod = vdd->vp_reg.prm_mod;
+
+	/* 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(mod, vdd->vp_offs.vpconfig);
+	vpconfig &= ~vdd->vp_reg.vpconfig_vpenable;
+	vdd->write_reg(vpconfig, mod, vdd->vp_offs.vpconfig);
+
+	/*
+	 * Wait for VP idle Typical latency is <2us. Maximum latency is ~100us
+	 */
+	omap_test_timeout((vdd->read_reg(mod, vdd->vp_offs.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;
+}
+
+/**
+ * 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
+ *
+ * This API should be called by the kernel to do the voltage scaling
+ * for a particular voltage domain during dvfs or any other situation.
+ */
+int omap_voltage_scale_vdd(struct voltagedomain *voltdm,
+		unsigned long target_volt)
+{
+	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);
+
+	if (!vdd->volt_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);
+}
+
+/**
+ * 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.
+ *
+ * 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 expecially
+ * while disabling any voltage compensation modules.
+ */
+void omap_voltage_reset(struct voltagedomain *voltdm)
+{
+	unsigned long target_uvdc;
+
+	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) {
+		pr_err("%s: unable to find current voltage for vdd_%s\n",
+			__func__, voltdm->name);
+		return;
+	}
+
+	omap_voltage_scale_vdd(voltdm, target_uvdc);
+}
+
+/**
+ * omap_voltage_get_volttable() - API to get the voltage table associated with a
+ *				particular voltage domain.
+ * @voltdm:	pointer to the VDD for which the voltage table is required
+ * @volt_data:	the voltage table for the particular vdd which is to be
+ *		populated by this API
+ *
+ * This API populates the voltage table associated with a VDD into the
+ * passed parameter pointer. Returns the count of distinct voltages
+ * supported by this vdd.
+ *
+ */
+void omap_voltage_get_volttable(struct voltagedomain *voltdm,
+		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;
+}
+
+/**
+ * omap_voltage_get_voltdata() - API to get the voltage table entry for a
+ *				particular voltage
+ * @voltdm:	pointer to the VDD whose voltage table has to be searched
+ * @volt:	the voltage to be searched in the voltage table
+ *
+ * This API searches through the voltage table for the required voltage
+ * domain and tries to find a matching entry for the passed voltage volt.
+ * If a matching entry is found volt_data is populated with that entry.
+ * This API searches only through the non-compensated voltages int the
+ * voltage table.
+ * Returns pointer to the voltage table entry corresponding to volt on
+ * sucess. Returns -ENODATA if no voltage table exisits for the passed voltage
+ * domain or if there is no matching entry.
+ */
+struct omap_volt_data *omap_voltage_get_voltdata(struct voltagedomain *voltdm,
+		unsigned long volt)
+{
+	struct omap_vdd_info *vdd;
+	int i;
+
+	if (!voltdm || IS_ERR(voltdm)) {
+		pr_warning("%s: VDD specified does not exist!\n", __func__);
+		return ERR_PTR(-EINVAL);
+	}
+
+	vdd = container_of(voltdm, struct omap_vdd_info, voltdm);
+
+	if (!vdd->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];
+	}
+
+	pr_notice("%s: Unable to match the current voltage with the voltage"
+		"table for vdd_%s\n", __func__, voltdm->name);
+
+	return ERR_PTR(-ENODATA);
+}
+
+/**
+ * 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
+ *
+ * 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.
+ */
+int omap_voltage_register_pmic(struct voltagedomain *voltdm,
+		struct omap_volt_pmic_info *pmic_info)
+{
+	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;
+
+	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.
+ * @voltscale_method:	the method to be used for voltage scaling.
+ *
+ * This API can be used by the board files to change the method of voltage
+ * scaling between vpforceupdate and vcbypass. The parameter values are
+ * defined in voltage.h
+ */
+void omap_change_voltscale_method(struct voltagedomain *voltdm,
+		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;
+		return;
+	case VOLTSCALE_VCBYPASS:
+		vdd->volt_scale = vc_bypass_scale_voltage;
+		return;
+	default:
+		pr_warning("%s: Trying to change the method of voltage scaling"
+			"to an unsupported one!\n", __func__);
+	}
+}
+
+/**
+ * omap_voltage_domain_lookup() - API to get the voltage domain pointer
+ * @name:	Name of the voltage domain
+ *
+ * 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.
+ */
+struct voltagedomain *omap_voltage_domain_lookup(char *name)
+{
+	int i;
+
+	if (!vdd_info) {
+		pr_err("%s: Voltage driver init not yet happened.Faulting!\n",
+			__func__);
+		return ERR_PTR(-EINVAL);
+	}
+
+	if (!name) {
+		pr_err("%s: No name to get the votage domain!\n", __func__);
+		return ERR_PTR(-EINVAL);
+	}
+
+	for (i = 0; i < nr_scalable_vdd; i++) {
+		if (!(strcmp(name, vdd_info[i].voltdm.name)))
+			return &vdd_info[i].voltdm;
+	}
+
+	return ERR_PTR(-EINVAL);
+}
+
+/**
+ * omap_voltage_late_init() - Init the various voltage parameters
+ *
+ * This API is to be called in the later stages of the
+ * system boot to init the voltage controller and
+ * voltage processors.
+ */
+int __init omap_voltage_late_init(void)
+{
+	int i;
+
+	if (!vdd_info) {
+		pr_err("%s: Voltage driver support not added\n",
+			__func__);
+		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 (vdd_data_configure(&vdd_info[i]))
+			continue;
+		vc_init(&vdd_info[i]);
+		vp_init(&vdd_info[i]);
+		vdd_debugfs_init(&vdd_info[i]);
+	}
+
+	return 0;
+}
+
+/**
+ * omap_voltage_early_init()- Volatage driver early init
+ */
+static int __init omap_voltage_early_init(void)
+{
+	if (cpu_is_omap34xx()) {
+		vdd_info = omap3_vdd_info;
+		nr_scalable_vdd = OMAP3_NR_SCALABLE_VDD;
+		vc_init = omap3_vc_init;
+		vdd_data_configure = omap3_vdd_data_configure;
+	} else if (cpu_is_omap44xx()) {
+		vdd_info = omap4_vdd_info;
+		nr_scalable_vdd = OMAP4_NR_SCALABLE_VDD;
+		vc_init = omap4_vc_init;
+		vdd_data_configure = omap4_vdd_data_configure;
+	} else {
+		pr_warning("%s: voltage driver support not added\n", __func__);
+	}
+
+	return 0;
+}
+core_initcall(omap_voltage_early_init);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/wd_timer.c linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/wd_timer.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/wd_timer.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/wd_timer.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,56 @@
+/*
+ * OMAP2+ MPU WD_TIMER-specific code
+ *
+ * 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/io.h>
+#include <linux/err.h>
+
+#include <plat/omap_hwmod.h>
+
+#include "wd_timer.h"
+
+/*
+ * In order to avoid any assumptions from bootloader regarding WDT
+ * settings, WDT module is reset during init. This enables the watchdog
+ * timer. Hence it is required to disable the watchdog after the WDT reset
+ * during init. Otherwise the system would reboot as per the default
+ * watchdog timer registers settings.
+ */
+#define OMAP_WDT_WPS		0x34
+#define OMAP_WDT_SPR		0x48
+
+
+int omap2_wd_timer_disable(struct omap_hwmod *oh)
+{
+	void __iomem *base;
+
+	if (!oh) {
+		pr_err("%s: Could not look up wdtimer_hwmod\n", __func__);
+		return -EINVAL;
+	}
+
+	base = omap_hwmod_get_mpu_rt_va(oh);
+	if (!base) {
+		pr_err("%s: Could not get the base address for %s\n",
+				oh->name, __func__);
+		return -EINVAL;
+	}
+
+	/* sequence required to disable watchdog */
+	__raw_writel(0xAAAA, base + OMAP_WDT_SPR);
+	while (__raw_readl(base + OMAP_WDT_WPS) & 0x10)
+		cpu_relax();
+
+	__raw_writel(0x5555, base + OMAP_WDT_SPR);
+	while (__raw_readl(base + OMAP_WDT_WPS) & 0x10)
+		cpu_relax();
+
+	return 0;
+}
+
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/wd_timer.h linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/wd_timer.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-omap2/wd_timer.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-omap2/wd_timer.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,17 @@
+/*
+ * OMAP2+ MPU WD_TIMER-specific function prototypes
+ *
+ * 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 __ARCH_ARM_MACH_OMAP2_WD_TIMER_H
+#define __ARCH_ARM_MACH_OMAP2_WD_TIMER_H
+
+#include <plat/omap_hwmod.h>
+
+extern int omap2_wd_timer_disable(struct omap_hwmod *oh);
+
+#endif
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-orion5x/include/mach/io.h linux-libre-2.6.38-gnu1/arch/arm/mach-orion5x/include/mach/io.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-orion5x/include/mach/io.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-orion5x/include/mach/io.h	2011-03-14 21:20:32.000000000 -0400
@@ -38,8 +38,8 @@ __arch_iounmap(void __iomem *addr)
 		__iounmap(addr);
 }
 
-#define __arch_ioremap(p, s, m)	__arch_ioremap(p, s, m)
-#define __arch_iounmap(a)	__arch_iounmap(a)
+#define __arch_ioremap		__arch_ioremap
+#define __arch_iounmap		__arch_iounmap
 #define __io(a)			__typesafe_io(a)
 #define __mem_pci(a)		(a)
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-orion5x/Kconfig linux-libre-2.6.38-gnu1/arch/arm/mach-orion5x/Kconfig
--- linux-libre-2.6.37-gnu1/arch/arm/mach-orion5x/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-orion5x/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -51,6 +51,13 @@ config MACH_LINKSTATION_PRO
 	  Buffalo Linkstation Pro/Live platform. Both v1 and
 	  v2 devices are supported.
 
+config MACH_LINKSTATION_LSCHL
+	bool "Buffalo Linkstation Live v3 (LS-CHL)"
+	select I2C_BOARDINFO
+	help
+	  Say 'Y' here if you want your kernel to support the
+	  Buffalo Linkstation Live v3 (LS-CHL) platform.
+
 config MACH_LINKSTATION_MINI
 	bool "Buffalo Linkstation Mini"
 	select I2C_BOARDINFO
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-orion5x/ls-chl-setup.c linux-libre-2.6.38-gnu1/arch/arm/mach-orion5x/ls-chl-setup.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-orion5x/ls-chl-setup.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-orion5x/ls-chl-setup.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,327 @@
+/*
+ * arch/arm/mach-orion5x/ls-chl-setup.c
+ *
+ * Maintainer: Ash Hughes <ashley.hughes@blueyonder.co.uk>
+ *
+ * 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/platform_device.h>
+#include <linux/mtd/physmap.h>
+#include <linux/mv643xx_eth.h>
+#include <linux/leds.h>
+#include <linux/gpio_keys.h>
+#include <linux/gpio-fan.h>
+#include <linux/input.h>
+#include <linux/i2c.h>
+#include <linux/ata_platform.h>
+#include <linux/gpio.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/system.h>
+#include <mach/orion5x.h>
+#include "common.h"
+#include "mpp.h"
+
+/*****************************************************************************
+ * Linkstation LS-CHL Info
+ ****************************************************************************/
+
+/*
+ * 256K NOR flash Device bus boot chip select
+ */
+
+#define LSCHL_NOR_BOOT_BASE	0xf4000000
+#define LSCHL_NOR_BOOT_SIZE	SZ_256K
+
+/*****************************************************************************
+ * 256KB NOR Flash on BOOT Device
+ ****************************************************************************/
+
+static struct physmap_flash_data lschl_nor_flash_data = {
+	.width = 1,
+};
+
+static struct resource lschl_nor_flash_resource = {
+	.flags	= IORESOURCE_MEM,
+	.start	= LSCHL_NOR_BOOT_BASE,
+	.end	= LSCHL_NOR_BOOT_BASE + LSCHL_NOR_BOOT_SIZE - 1,
+};
+
+static struct platform_device lschl_nor_flash = {
+	.name = "physmap-flash",
+	.id = 0,
+	.dev = {
+		.platform_data	= &lschl_nor_flash_data,
+	},
+	.num_resources = 1,
+	.resource = &lschl_nor_flash_resource,
+};
+
+/*****************************************************************************
+ * Ethernet
+ ****************************************************************************/
+
+static struct mv643xx_eth_platform_data lschl_eth_data = {
+	.phy_addr = MV643XX_ETH_PHY_ADDR(8),
+};
+
+/*****************************************************************************
+ * RTC 5C372a on I2C bus
+ ****************************************************************************/
+
+static struct i2c_board_info __initdata lschl_i2c_rtc = {
+	I2C_BOARD_INFO("rs5c372a", 0x32),
+};
+
+/*****************************************************************************
+ * LEDs attached to GPIO
+ ****************************************************************************/
+
+#define LSCHL_GPIO_LED_ALARM	2
+#define LSCHL_GPIO_LED_INFO	3
+#define LSCHL_GPIO_LED_FUNC	17
+#define LSCHL_GPIO_LED_PWR	0
+
+static struct gpio_led lschl_led_pins[] = {
+	{
+		.name = "alarm:red",
+		.gpio = LSCHL_GPIO_LED_ALARM,
+		.active_low = 1,
+	}, {
+		.name = "info:amber",
+		.gpio = LSCHL_GPIO_LED_INFO,
+		.active_low = 1,
+	}, {
+		.name = "func:blue:top",
+		.gpio = LSCHL_GPIO_LED_FUNC,
+		.active_low = 1,
+	}, {
+		.name = "power:blue:bottom",
+		.gpio = LSCHL_GPIO_LED_PWR,
+	},
+};
+
+static struct gpio_led_platform_data lschl_led_data = {
+	.leds = lschl_led_pins,
+	.num_leds = ARRAY_SIZE(lschl_led_pins),
+};
+
+static struct platform_device lschl_leds = {
+	.name = "leds-gpio",
+	.id = -1,
+	.dev = {
+		.platform_data = &lschl_led_data,
+	},
+};
+
+/*****************************************************************************
+ * SATA
+ ****************************************************************************/
+static struct mv_sata_platform_data lschl_sata_data = {
+	.n_ports = 2,
+};
+
+/*****************************************************************************
+ * LS-CHL specific power off method: reboot
+ ****************************************************************************/
+/*
+ * On the LS-CHL, the shutdown process is following:
+ * - Userland monitors key events until the power switch goes to off position
+ * - The board reboots
+ * - U-boot starts and goes into an idle mode waiting for the user
+ *   to move the switch to ON position
+ *
+ */
+
+static void lschl_power_off(void)
+{
+	arm_machine_restart('h', NULL);
+}
+
+/*****************************************************************************
+ * General Setup
+ ****************************************************************************/
+#define LSCHL_GPIO_USB_POWER	9
+#define LSCHL_GPIO_AUTO_POWER	17
+#define LSCHL_GPIO_POWER	18
+
+/****************************************************************************
+ * GPIO Attached Keys
+ ****************************************************************************/
+#define LSCHL_GPIO_KEY_FUNC		15
+#define LSCHL_GPIO_KEY_POWER		8
+#define LSCHL_GPIO_KEY_AUTOPOWER	10
+#define LSCHL_SW_POWER		0x00
+#define LSCHL_SW_AUTOPOWER	0x01
+#define LSCHL_SW_FUNC		0x02
+
+static struct gpio_keys_button lschl_buttons[] = {
+	{
+		.type = EV_SW,
+		.code = LSCHL_SW_POWER,
+		.gpio = LSCHL_GPIO_KEY_POWER,
+		.desc = "Power-on Switch",
+		.active_low = 1,
+	}, {
+		.type = EV_SW,
+		.code = LSCHL_SW_AUTOPOWER,
+		.gpio = LSCHL_GPIO_KEY_AUTOPOWER,
+		.desc = "Power-auto Switch",
+		.active_low = 1,
+	}, {
+		.type = EV_SW,
+		.code = LSCHL_SW_FUNC,
+		.gpio = LSCHL_GPIO_KEY_FUNC,
+		.desc = "Function Switch",
+		.active_low = 1,
+	},
+};
+
+static struct gpio_keys_platform_data lschl_button_data = {
+	.buttons = lschl_buttons,
+	.nbuttons = ARRAY_SIZE(lschl_buttons),
+};
+
+static struct platform_device lschl_button_device = {
+	.name = "gpio-keys",
+	.id = -1,
+	.num_resources = 0,
+	.dev = {
+		.platform_data = &lschl_button_data,
+	},
+};
+
+#define LSCHL_GPIO_HDD_POWER	1
+
+/****************************************************************************
+ * GPIO Fan
+ ****************************************************************************/
+
+#define LSCHL_GPIO_FAN_LOW	16
+#define LSCHL_GPIO_FAN_HIGH	14
+#define LSCHL_GPIO_FAN_LOCK	6
+
+static struct gpio_fan_alarm lschl_alarm = {
+	.gpio = LSCHL_GPIO_FAN_LOCK,
+};
+
+static struct gpio_fan_speed lschl_speeds[] = {
+	{
+		.rpm = 0,
+		.ctrl_val = 3,
+	}, {
+		.rpm = 1500,
+		.ctrl_val = 2,
+	}, {
+		.rpm = 3250,
+		.ctrl_val = 1,
+	}, {
+		.rpm = 5000,
+		.ctrl_val = 0,
+	},
+};
+
+static int lschl_gpio_list[] = {
+	LSCHL_GPIO_FAN_HIGH, LSCHL_GPIO_FAN_LOW,
+};
+
+static struct gpio_fan_platform_data lschl_fan_data = {
+	.num_ctrl = ARRAY_SIZE(lschl_gpio_list),
+	.ctrl = lschl_gpio_list,
+	.alarm = &lschl_alarm,
+	.num_speed = ARRAY_SIZE(lschl_speeds),
+	.speed = lschl_speeds,
+};
+
+static struct platform_device lschl_fan_device = {
+	.name = "gpio-fan",
+	.id = -1,
+	.num_resources = 0,
+	.dev = {
+		.platform_data = &lschl_fan_data,
+	},
+};
+
+/****************************************************************************
+ * GPIO Data
+ ****************************************************************************/
+
+static struct orion5x_mpp_mode lschl_mpp_modes[] __initdata = {
+	{  0, MPP_GPIO }, /* LED POWER */
+	{  1, MPP_GPIO }, /* HDD POWER */
+	{  2, MPP_GPIO }, /* LED ALARM */
+	{  3, MPP_GPIO }, /* LED INFO */
+	{  4, MPP_UNUSED },
+	{  5, MPP_UNUSED },
+	{  6, MPP_GPIO }, /* FAN LOCK */
+	{  7, MPP_GPIO }, /* SW INIT */
+	{  8, MPP_GPIO }, /* SW POWER */
+	{  9, MPP_GPIO }, /* USB POWER */
+	{ 10, MPP_GPIO }, /* SW AUTO POWER */
+	{ 11, MPP_UNUSED },
+	{ 12, MPP_UNUSED },
+	{ 13, MPP_UNUSED },
+	{ 14, MPP_GPIO }, /* FAN HIGH */
+	{ 15, MPP_GPIO }, /* SW FUNC */
+	{ 16, MPP_GPIO }, /* FAN LOW */
+	{ 17, MPP_GPIO }, /* LED FUNC */
+	{ 18, MPP_UNUSED },
+	{ 19, MPP_UNUSED },
+	{ -1 },
+};
+
+static void __init lschl_init(void)
+{
+	/*
+	 * Setup basic Orion functions. Needs to be called early.
+	 */
+	orion5x_init();
+
+	orion5x_mpp_conf(lschl_mpp_modes);
+
+	/*
+	 * Configure peripherals.
+	 */
+	orion5x_ehci0_init();
+	orion5x_ehci1_init();
+	orion5x_eth_init(&lschl_eth_data);
+	orion5x_i2c_init();
+	orion5x_sata_init(&lschl_sata_data);
+	orion5x_uart0_init();
+	orion5x_xor_init();
+
+	orion5x_setup_dev_boot_win(LSCHL_NOR_BOOT_BASE,
+				   LSCHL_NOR_BOOT_SIZE);
+	platform_device_register(&lschl_nor_flash);
+
+	platform_device_register(&lschl_leds);
+
+	platform_device_register(&lschl_button_device);
+
+	platform_device_register(&lschl_fan_device);
+
+	i2c_register_board_info(0, &lschl_i2c_rtc, 1);
+
+	/* usb power on */
+	gpio_set_value(LSCHL_GPIO_USB_POWER, 1);
+
+	/* register power-off method */
+	pm_power_off = lschl_power_off;
+
+	pr_info("%s: finished\n", __func__);
+}
+
+MACHINE_START(LINKSTATION_LSCHL, "Buffalo Linkstation LiveV3 (LS-CHL)")
+	/* Maintainer: Ash Hughes <ashley.hughes@blueyonder.co.uk> */
+	.boot_params	= 0x00000100,
+	.init_machine	= lschl_init,
+	.map_io		= orion5x_map_io,
+	.init_irq	= orion5x_init_irq,
+	.timer		= &orion5x_timer,
+	.fixup		= tag_fixup_mem32,
+MACHINE_END
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-orion5x/Makefile linux-libre-2.6.38-gnu1/arch/arm/mach-orion5x/Makefile
--- linux-libre-2.6.37-gnu1/arch/arm/mach-orion5x/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-orion5x/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -21,3 +21,4 @@ obj-$(CONFIG_MACH_WNR854T)	+= wnr854t-se
 obj-$(CONFIG_MACH_RD88F5181L_GE)	+= rd88f5181l-ge-setup.o
 obj-$(CONFIG_MACH_RD88F5181L_FXO)	+= rd88f5181l-fxo-setup.o
 obj-$(CONFIG_MACH_RD88F6183AP_GE)	+= rd88f6183ap-ge-setup.o
+obj-$(CONFIG_MACH_LINKSTATION_LSCHL)	+= ls-chl-setup.o
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-pnx4008/clock.c linux-libre-2.6.38-gnu1/arch/arm/mach-pnx4008/clock.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-pnx4008/clock.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-pnx4008/clock.c	2011-03-14 21:20:32.000000000 -0400
@@ -21,8 +21,7 @@
 #include <linux/err.h>
 #include <linux/delay.h>
 #include <linux/io.h>
-
-#include <asm/clkdev.h>
+#include <linux/clkdev.h>
 
 #include <mach/hardware.h>
 #include <mach/clock.h>
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-pnx4008/irq.c linux-libre-2.6.38-gnu1/arch/arm/mach-pnx4008/irq.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-pnx4008/irq.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-pnx4008/irq.c	2011-03-14 21:20:32.000000000 -0400
@@ -36,44 +36,44 @@
 
 static u8 pnx4008_irq_type[NR_IRQS] = PNX4008_IRQ_TYPES;
 
-static void pnx4008_mask_irq(unsigned int irq)
+static void pnx4008_mask_irq(struct irq_data *d)
 {
-	__raw_writel(__raw_readl(INTC_ER(irq)) & ~INTC_BIT(irq), INTC_ER(irq));	/* mask interrupt */
+	__raw_writel(__raw_readl(INTC_ER(d->irq)) & ~INTC_BIT(d->irq), INTC_ER(d->irq));	/* mask interrupt */
 }
 
-static void pnx4008_unmask_irq(unsigned int irq)
+static void pnx4008_unmask_irq(struct irq_data *d)
 {
-	__raw_writel(__raw_readl(INTC_ER(irq)) | INTC_BIT(irq), INTC_ER(irq));	/* unmask interrupt */
+	__raw_writel(__raw_readl(INTC_ER(d->irq)) | INTC_BIT(d->irq), INTC_ER(d->irq));	/* unmask interrupt */
 }
 
-static void pnx4008_mask_ack_irq(unsigned int irq)
+static void pnx4008_mask_ack_irq(struct irq_data *d)
 {
-	__raw_writel(__raw_readl(INTC_ER(irq)) & ~INTC_BIT(irq), INTC_ER(irq));	/* mask interrupt */
-	__raw_writel(INTC_BIT(irq), INTC_SR(irq));	/* clear interrupt status */
+	__raw_writel(__raw_readl(INTC_ER(d->irq)) & ~INTC_BIT(d->irq), INTC_ER(d->irq));	/* mask interrupt */
+	__raw_writel(INTC_BIT(d->irq), INTC_SR(d->irq));	/* clear interrupt status */
 }
 
-static int pnx4008_set_irq_type(unsigned int irq, unsigned int type)
+static int pnx4008_set_irq_type(struct irq_data *d, unsigned int type)
 {
 	switch (type) {
 	case IRQ_TYPE_EDGE_RISING:
-		__raw_writel(__raw_readl(INTC_ATR(irq)) | INTC_BIT(irq), INTC_ATR(irq));	/*edge sensitive */
-		__raw_writel(__raw_readl(INTC_APR(irq)) | INTC_BIT(irq), INTC_APR(irq));	/*rising edge */
-		set_irq_handler(irq, handle_edge_irq);
+		__raw_writel(__raw_readl(INTC_ATR(d->irq)) | INTC_BIT(d->irq), INTC_ATR(d->irq));	/*edge sensitive */
+		__raw_writel(__raw_readl(INTC_APR(d->irq)) | INTC_BIT(d->irq), INTC_APR(d->irq));	/*rising edge */
+		set_irq_handler(d->irq, handle_edge_irq);
 		break;
 	case IRQ_TYPE_EDGE_FALLING:
-		__raw_writel(__raw_readl(INTC_ATR(irq)) | INTC_BIT(irq), INTC_ATR(irq));	/*edge sensitive */
-		__raw_writel(__raw_readl(INTC_APR(irq)) & ~INTC_BIT(irq), INTC_APR(irq));	/*falling edge */
-		set_irq_handler(irq, handle_edge_irq);
+		__raw_writel(__raw_readl(INTC_ATR(d->irq)) | INTC_BIT(d->irq), INTC_ATR(d->irq));	/*edge sensitive */
+		__raw_writel(__raw_readl(INTC_APR(d->irq)) & ~INTC_BIT(d->irq), INTC_APR(d->irq));	/*falling edge */
+		set_irq_handler(d->irq, handle_edge_irq);
 		break;
 	case IRQ_TYPE_LEVEL_LOW:
-		__raw_writel(__raw_readl(INTC_ATR(irq)) & ~INTC_BIT(irq), INTC_ATR(irq));	/*level sensitive */
-		__raw_writel(__raw_readl(INTC_APR(irq)) & ~INTC_BIT(irq), INTC_APR(irq));	/*low level */
-		set_irq_handler(irq, handle_level_irq);
+		__raw_writel(__raw_readl(INTC_ATR(d->irq)) & ~INTC_BIT(d->irq), INTC_ATR(d->irq));	/*level sensitive */
+		__raw_writel(__raw_readl(INTC_APR(d->irq)) & ~INTC_BIT(d->irq), INTC_APR(d->irq));	/*low level */
+		set_irq_handler(d->irq, handle_level_irq);
 		break;
 	case IRQ_TYPE_LEVEL_HIGH:
-		__raw_writel(__raw_readl(INTC_ATR(irq)) & ~INTC_BIT(irq), INTC_ATR(irq));	/*level sensitive */
-		__raw_writel(__raw_readl(INTC_APR(irq)) | INTC_BIT(irq), INTC_APR(irq));	/* high level */
-		set_irq_handler(irq, handle_level_irq);
+		__raw_writel(__raw_readl(INTC_ATR(d->irq)) & ~INTC_BIT(d->irq), INTC_ATR(d->irq));	/*level sensitive */
+		__raw_writel(__raw_readl(INTC_APR(d->irq)) | INTC_BIT(d->irq), INTC_APR(d->irq));	/* high level */
+		set_irq_handler(d->irq, handle_level_irq);
 		break;
 
 	/* IRQ_TYPE_EDGE_BOTH is not supported */
@@ -85,10 +85,10 @@ static int pnx4008_set_irq_type(unsigned
 }
 
 static struct irq_chip pnx4008_irq_chip = {
-	.ack = pnx4008_mask_ack_irq,
-	.mask = pnx4008_mask_irq,
-	.unmask = pnx4008_unmask_irq,
-	.set_type = pnx4008_set_irq_type,
+	.irq_ack = pnx4008_mask_ack_irq,
+	.irq_mask = pnx4008_mask_irq,
+	.irq_unmask = pnx4008_unmask_irq,
+	.irq_set_type = pnx4008_set_irq_type,
 };
 
 void __init pnx4008_init_irq(void)
@@ -99,14 +99,18 @@ void __init pnx4008_init_irq(void)
 	for (i = 0; i < NR_IRQS; i++) {
 		set_irq_flags(i, IRQF_VALID);
 		set_irq_chip(i, &pnx4008_irq_chip);
-		pnx4008_set_irq_type(i, pnx4008_irq_type[i]);
+		pnx4008_set_irq_type(irq_get_irq_data(i), pnx4008_irq_type[i]);
 	}
 
 	/* configure and enable IRQ 0,1,30,31 (cascade interrupts) */
-	pnx4008_set_irq_type(SUB1_IRQ_N, pnx4008_irq_type[SUB1_IRQ_N]);
-	pnx4008_set_irq_type(SUB2_IRQ_N, pnx4008_irq_type[SUB2_IRQ_N]);
-	pnx4008_set_irq_type(SUB1_FIQ_N, pnx4008_irq_type[SUB1_FIQ_N]);
-	pnx4008_set_irq_type(SUB2_FIQ_N, pnx4008_irq_type[SUB2_FIQ_N]);
+	pnx4008_set_irq_type(irq_get_irq_data(SUB1_IRQ_N),
+			     pnx4008_irq_type[SUB1_IRQ_N]);
+	pnx4008_set_irq_type(irq_get_irq_data(SUB2_IRQ_N),
+			     pnx4008_irq_type[SUB2_IRQ_N]);
+	pnx4008_set_irq_type(irq_get_irq_data(SUB1_FIQ_N),
+			     pnx4008_irq_type[SUB1_FIQ_N]);
+	pnx4008_set_irq_type(irq_get_irq_data(SUB2_FIQ_N),
+			     pnx4008_irq_type[SUB2_FIQ_N]);
 
 	/* mask all others */
 	__raw_writel((1 << SUB2_FIQ_N) | (1 << SUB1_FIQ_N) |
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-pnx4008/pm.c linux-libre-2.6.38-gnu1/arch/arm/mach-pnx4008/pm.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-pnx4008/pm.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-pnx4008/pm.c	2011-03-14 21:20:32.000000000 -0400
@@ -119,7 +119,7 @@ static int pnx4008_pm_valid(suspend_stat
 	       (state == PM_SUSPEND_MEM);
 }
 
-static struct platform_suspend_ops pnx4008_pm_ops = {
+static const struct platform_suspend_ops pnx4008_pm_ops = {
 	.enter = pnx4008_pm_enter,
 	.valid = pnx4008_pm_valid,
 };
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/balloon3.c linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/balloon3.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/balloon3.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/balloon3.c	2011-03-14 21:20:32.000000000 -0400
@@ -477,25 +477,25 @@ static inline void balloon3_leds_init(vo
 /******************************************************************************
  * FPGA IRQ
  ******************************************************************************/
-static void balloon3_mask_irq(unsigned int irq)
+static void balloon3_mask_irq(struct irq_data *d)
 {
-	int balloon3_irq = (irq - BALLOON3_IRQ(0));
+	int balloon3_irq = (d->irq - BALLOON3_IRQ(0));
 	balloon3_irq_enabled &= ~(1 << balloon3_irq);
 	__raw_writel(~balloon3_irq_enabled, BALLOON3_INT_CONTROL_REG);
 }
 
-static void balloon3_unmask_irq(unsigned int irq)
+static void balloon3_unmask_irq(struct irq_data *d)
 {
-	int balloon3_irq = (irq - BALLOON3_IRQ(0));
+	int balloon3_irq = (d->irq - BALLOON3_IRQ(0));
 	balloon3_irq_enabled |= (1 << balloon3_irq);
 	__raw_writel(~balloon3_irq_enabled, BALLOON3_INT_CONTROL_REG);
 }
 
 static struct irq_chip balloon3_irq_chip = {
 	.name		= "FPGA",
-	.ack		= balloon3_mask_irq,
-	.mask		= balloon3_mask_irq,
-	.unmask		= balloon3_unmask_irq,
+	.irq_ack	= balloon3_mask_irq,
+	.irq_mask	= balloon3_mask_irq,
+	.irq_unmask	= balloon3_unmask_irq,
 };
 
 static void balloon3_irq_handler(unsigned int irq, struct irq_desc *desc)
@@ -504,8 +504,13 @@ static void balloon3_irq_handler(unsigne
 					balloon3_irq_enabled;
 	do {
 		/* clear useless edge notification */
-		if (desc->chip->ack)
-			desc->chip->ack(BALLOON3_AUX_NIRQ);
+		if (desc->irq_data.chip->irq_ack) {
+			struct irq_data *d;
+
+			d = irq_get_irq_data(BALLOON3_AUX_NIRQ);
+			desc->irq_data.chip->irq_ack(d);
+		}
+
 		while (pending) {
 			irq = BALLOON3_IRQ(0) + __ffs(pending);
 			generic_handle_irq(irq);
@@ -567,27 +572,29 @@ static inline void balloon3_i2c_init(voi
  * NAND
  ******************************************************************************/
 #if defined(CONFIG_MTD_NAND_PLATFORM)||defined(CONFIG_MTD_NAND_PLATFORM_MODULE)
-static uint16_t balloon3_ctl =
-	BALLOON3_NAND_CONTROL_FLCE0 | BALLOON3_NAND_CONTROL_FLCE1 |
-	BALLOON3_NAND_CONTROL_FLCE2 | BALLOON3_NAND_CONTROL_FLCE3 |
-	BALLOON3_NAND_CONTROL_FLWP;
-
 static void balloon3_nand_cmd_ctl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
 {
 	struct nand_chip *this = mtd->priv;
+	uint8_t balloon3_ctl_set = 0, balloon3_ctl_clr = 0;
 
 	if (ctrl & NAND_CTRL_CHANGE) {
 		if (ctrl & NAND_CLE)
-			balloon3_ctl |= BALLOON3_NAND_CONTROL_FLCLE;
+			balloon3_ctl_set |= BALLOON3_NAND_CONTROL_FLCLE;
 		else
-			balloon3_ctl &= ~BALLOON3_NAND_CONTROL_FLCLE;
+			balloon3_ctl_clr |= BALLOON3_NAND_CONTROL_FLCLE;
 
 		if (ctrl & NAND_ALE)
-			balloon3_ctl |= BALLOON3_NAND_CONTROL_FLALE;
+			balloon3_ctl_set |= BALLOON3_NAND_CONTROL_FLALE;
 		else
-			balloon3_ctl &= ~BALLOON3_NAND_CONTROL_FLALE;
+			balloon3_ctl_clr |= BALLOON3_NAND_CONTROL_FLALE;
 
-		__raw_writel(balloon3_ctl, BALLOON3_NAND_CONTROL_REG);
+		if (balloon3_ctl_clr)
+			__raw_writel(balloon3_ctl_clr,
+				BALLOON3_NAND_CONTROL_REG);
+		if (balloon3_ctl_set)
+			__raw_writel(balloon3_ctl_set,
+				BALLOON3_NAND_CONTROL_REG |
+				BALLOON3_FPGA_SETnCLR);
 	}
 
 	if (cmd != NAND_CMD_NONE)
@@ -599,28 +606,33 @@ static void balloon3_nand_select_chip(st
 	if (chip < 0 || chip > 3)
 		return;
 
-	balloon3_ctl |= BALLOON3_NAND_CONTROL_FLCE0 |
-			BALLOON3_NAND_CONTROL_FLCE1 |
-			BALLOON3_NAND_CONTROL_FLCE2 |
-			BALLOON3_NAND_CONTROL_FLCE3;
+	/* Assert all nCE lines */
+	__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);
 
 	/* Deassert correct nCE line */
-	balloon3_ctl &= ~(BALLOON3_NAND_CONTROL_FLCE0 << chip);
+	__raw_writew(BALLOON3_NAND_CONTROL_FLCE0 << chip,
+		BALLOON3_NAND_CONTROL_REG);
+}
 
-	__raw_writew(balloon3_ctl, BALLOON3_NAND_CONTROL_REG);
+static int balloon3_nand_dev_ready(struct mtd_info *mtd)
+{
+	return __raw_readl(BALLOON3_NAND_STAT_REG) & BALLOON3_NAND_STAT_RNB;
 }
 
 static int balloon3_nand_probe(struct platform_device *pdev)
 {
-	void __iomem *temp_map;
 	uint16_t ver;
 	int ret;
 
-	__raw_writew(BALLOON3_NAND_CONTROL2_16BIT, BALLOON3_NAND_CONTROL2_REG);
+	__raw_writew(BALLOON3_NAND_CONTROL2_16BIT,
+		BALLOON3_NAND_CONTROL2_REG | BALLOON3_FPGA_SETnCLR);
 
 	ver = __raw_readw(BALLOON3_FPGA_VER);
-	if (ver > 0x0201)
-		pr_warn("The FPGA code, version 0x%04x, is newer than rel-0.3. "
+	if (ver < 0x4f08)
+		pr_warn("The FPGA code, version 0x%04x, is too old. "
 			"NAND support might be broken in this version!", ver);
 
 	/* Power up the NAND chips */
@@ -635,7 +647,11 @@ static int balloon3_nand_probe(struct pl
 	gpio_set_value(BALLOON3_GPIO_RUN_NAND, 1);
 
 	/* Deassert all nCE lines and write protect line */
-	__raw_writel(balloon3_ctl, BALLOON3_NAND_CONTROL_REG);
+	__raw_writel(
+		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);
 	return 0;
 
 err2:
@@ -677,7 +693,7 @@ struct platform_nand_data balloon3_nand_
 	},
 	.ctrl = {
 		.hwcontrol	= 0,
-		.dev_ready	= 0,
+		.dev_ready	= balloon3_nand_dev_ready,
 		.select_chip	= balloon3_nand_select_chip,
 		.cmd_ctrl	= balloon3_nand_cmd_ctl,
 		.probe		= balloon3_nand_probe,
@@ -802,7 +818,7 @@ static struct map_desc balloon3_io_desc[
 
 static void __init balloon3_map_io(void)
 {
-	pxa_map_io();
+	pxa27x_map_io();
 	iotable_init(balloon3_io_desc, ARRAY_SIZE(balloon3_io_desc));
 }
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/capc7117.c linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/capc7117.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/capc7117.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/capc7117.c	2011-03-14 21:20:32.000000000 -0400
@@ -149,7 +149,7 @@ static void __init capc7117_init(void)
 MACHINE_START(CAPC7117,
 	      "Embedian CAPC-7117 evaluation kit based on the MXM-8x10 CoM")
 	.boot_params = 0xa0000100,
-	.map_io = pxa_map_io,
+	.map_io = pxa3xx_map_io,
 	.init_irq = pxa3xx_init_irq,
 	.timer = &pxa_timer,
 	.init_machine = capc7117_init
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/clock.c linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/clock.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/clock.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/clock.c	2011-03-14 21:20:32.000000000 -0400
@@ -3,21 +3,11 @@
  */
 #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/delay.h>
+#include <linux/clkdev.h>
 
-#include <asm/clkdev.h>
-#include <mach/pxa2xx-regs.h>
-#include <mach/hardware.h>
-
-#include "devices.h"
-#include "generic.h"
 #include "clock.h"
 
 static DEFINE_SPINLOCK(clocks_lock);
@@ -63,18 +53,19 @@ unsigned long clk_get_rate(struct clk *c
 }
 EXPORT_SYMBOL(clk_get_rate);
 
-
-void clk_cken_enable(struct clk *clk)
+void clk_dummy_enable(struct clk *clk)
 {
-	CKEN |= 1 << clk->cken;
 }
 
-void clk_cken_disable(struct clk *clk)
+void clk_dummy_disable(struct clk *clk)
 {
-	CKEN &= ~(1 << clk->cken);
 }
 
-const struct clkops clk_cken_ops = {
-	.enable		= clk_cken_enable,
-	.disable	= clk_cken_disable,
+const struct clkops clk_dummy_ops = {
+	.enable		= clk_dummy_enable,
+	.disable	= clk_dummy_disable,
+};
+
+struct clk clk_dummy = {
+	.ops		= &clk_dummy_ops,
 };
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/clock.h linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/clock.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/clock.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/clock.h	2011-03-14 21:20:32.000000000 -0400
@@ -1,4 +1,5 @@
-#include <asm/clkdev.h>
+#include <linux/clkdev.h>
+#include <linux/sysdev.h>
 
 struct clkops {
 	void			(*enable)(struct clk *);
@@ -14,6 +15,12 @@ struct clk {
 	unsigned int		enabled;
 };
 
+void clk_dummy_enable(struct clk *);
+void clk_dummy_disable(struct clk *);
+
+extern const struct clkops clk_dummy_ops;
+extern struct clk clk_dummy;
+
 #define INIT_CLKREG(_clk,_devname,_conname)		\
 	{						\
 		.clk		= _clk,			\
@@ -21,14 +28,6 @@ struct clk {
 		.con_id		= _conname,		\
 	}
 
-#define DEFINE_CKEN(_name, _cken, _rate, _delay)	\
-struct clk clk_##_name = {				\
-		.ops	= &clk_cken_ops,		\
-		.rate	= _rate,			\
-		.cken	= CKEN_##_cken,			\
-		.delay	= _delay,			\
-	}
-
 #define DEFINE_CK(_name, _cken, _ops)			\
 struct clk clk_##_name = {				\
 		.ops	= _ops,				\
@@ -42,28 +41,38 @@ struct clk clk_##_name = {				\
 		.delay	= _delay,			\
 	}
 
-extern const struct clkops clk_cken_ops;
-
-void clk_cken_enable(struct clk *clk);
-void clk_cken_disable(struct clk *clk);
-
-#ifdef CONFIG_PXA3xx
-#define DEFINE_PXA3_CKEN(_name, _cken, _rate, _delay)	\
+#define DEFINE_PXA2_CKEN(_name, _cken, _rate, _delay)	\
 struct clk clk_##_name = {				\
-		.ops	= &clk_pxa3xx_cken_ops,		\
+		.ops	= &clk_pxa2xx_cken_ops,		\
 		.rate	= _rate,			\
 		.cken	= CKEN_##_cken,			\
 		.delay	= _delay,			\
 	}
 
-#define DEFINE_PXA3_CK(_name, _cken, _ops)		\
+extern const struct clkops clk_pxa2xx_cken_ops;
+
+void clk_pxa2xx_cken_enable(struct clk *clk);
+void clk_pxa2xx_cken_disable(struct clk *clk);
+
+extern struct sysdev_class pxa2xx_clock_sysclass;
+
+#if defined(CONFIG_PXA3xx) || defined(CONFIG_PXA95x)
+#define DEFINE_PXA3_CKEN(_name, _cken, _rate, _delay)	\
 struct clk clk_##_name = {				\
-		.ops	= _ops,				\
+		.ops	= &clk_pxa3xx_cken_ops,		\
+		.rate	= _rate,			\
 		.cken	= CKEN_##_cken,			\
+		.delay	= _delay,			\
 	}
 
 extern const struct clkops clk_pxa3xx_cken_ops;
+extern const struct clkops clk_pxa3xx_hsio_ops;
+extern const struct clkops clk_pxa3xx_ac97_ops;
+extern const struct clkops clk_pxa3xx_pout_ops;
+extern const struct clkops clk_pxa3xx_smemc_ops;
+
 extern void clk_pxa3xx_cken_enable(struct clk *);
 extern void clk_pxa3xx_cken_disable(struct clk *);
-#endif
 
+extern struct sysdev_class pxa3xx_clock_sysclass;
+#endif
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/clock-pxa2xx.c linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/clock-pxa2xx.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/clock-pxa2xx.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/clock-pxa2xx.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,64 @@
+/*
+ * linux/arch/arm/mach-pxa/clock-pxa2xx.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/init.h>
+#include <linux/sysdev.h>
+
+#include <mach/pxa2xx-regs.h>
+
+#include "clock.h"
+
+void clk_pxa2xx_cken_enable(struct clk *clk)
+{
+	CKEN |= 1 << clk->cken;
+}
+
+void clk_pxa2xx_cken_disable(struct clk *clk)
+{
+	CKEN &= ~(1 << clk->cken);
+}
+
+const struct clkops clk_pxa2xx_cken_ops = {
+	.enable		= clk_pxa2xx_cken_enable,
+	.disable	= clk_pxa2xx_cken_disable,
+};
+
+#ifdef CONFIG_PM
+static uint32_t saved_cken;
+
+static int pxa2xx_clock_suspend(struct sys_device *d, pm_message_t state)
+{
+	saved_cken = CKEN;
+	return 0;
+}
+
+static int pxa2xx_clock_resume(struct sys_device *d)
+{
+	CKEN = saved_cken;
+	return 0;
+}
+#else
+#define pxa2xx_clock_suspend	NULL
+#define pxa2xx_clock_resume	NULL
+#endif
+
+struct sysdev_class pxa2xx_clock_sysclass = {
+	.name		= "pxa2xx-clock",
+	.suspend	= pxa2xx_clock_suspend,
+	.resume		= pxa2xx_clock_resume,
+};
+
+static int __init pxa2xx_clock_init(void)
+{
+	if (cpu_is_pxa2xx())
+		return sysdev_class_register(&pxa2xx_clock_sysclass);
+	return 0;
+}
+postcore_initcall(pxa2xx_clock_init);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/clock-pxa3xx.c linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/clock-pxa3xx.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/clock-pxa3xx.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/clock-pxa3xx.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,217 @@
+/*
+ * linux/arch/arm/mach-pxa/clock-pxa3xx.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/init.h>
+#include <linux/io.h>
+
+#include <mach/smemc.h>
+#include <mach/pxa3xx-regs.h>
+
+#include "clock.h"
+
+/* Crystal clock: 13MHz */
+#define BASE_CLK	13000000
+
+/* Ring Oscillator Clock: 60MHz */
+#define RO_CLK		60000000
+
+#define ACCR_D0CS	(1 << 26)
+#define ACCR_PCCE	(1 << 11)
+
+/* crystal frequency to HSIO bus frequency multiplier (HSS) */
+static unsigned char hss_mult[4] = { 8, 12, 16, 24 };
+
+/*
+ * Get the clock frequency as reflected by CCSR and the turbo flag.
+ * We assume these values have been applied via a fcs.
+ * If info is not 0 we also display the current settings.
+ */
+unsigned int pxa3xx_get_clk_frequency_khz(int info)
+{
+	unsigned long acsr, xclkcfg;
+	unsigned int t, xl, xn, hss, ro, XL, XN, CLK, HSS;
+
+	/* Read XCLKCFG register turbo bit */
+	__asm__ __volatile__("mrc\tp14, 0, %0, c6, c0, 0" : "=r"(xclkcfg));
+	t = xclkcfg & 0x1;
+
+	acsr = ACSR;
+
+	xl  = acsr & 0x1f;
+	xn  = (acsr >> 8) & 0x7;
+	hss = (acsr >> 14) & 0x3;
+
+	XL = xl * BASE_CLK;
+	XN = xn * XL;
+
+	ro = acsr & ACCR_D0CS;
+
+	CLK = (ro) ? RO_CLK : ((t) ? XN : XL);
+	HSS = (ro) ? RO_CLK : hss_mult[hss] * BASE_CLK;
+
+	if (info) {
+		pr_info("RO Mode clock: %d.%02dMHz (%sactive)\n",
+			RO_CLK / 1000000, (RO_CLK % 1000000) / 10000,
+			(ro) ? "" : "in");
+		pr_info("Run Mode clock: %d.%02dMHz (*%d)\n",
+			XL / 1000000, (XL % 1000000) / 10000, xl);
+		pr_info("Turbo Mode clock: %d.%02dMHz (*%d, %sactive)\n",
+			XN / 1000000, (XN % 1000000) / 10000, xn,
+			(t) ? "" : "in");
+		pr_info("HSIO bus clock: %d.%02dMHz\n",
+			HSS / 1000000, (HSS % 1000000) / 10000);
+	}
+
+	return CLK / 1000;
+}
+
+/*
+ * Return the current AC97 clock frequency.
+ */
+static unsigned long clk_pxa3xx_ac97_getrate(struct clk *clk)
+{
+	unsigned long rate = 312000000;
+	unsigned long ac97_div;
+
+	ac97_div = AC97_DIV;
+
+	/* This may loose precision for some rates but won't for the
+	 * standard 24.576MHz.
+	 */
+	rate /= (ac97_div >> 12) & 0x7fff;
+	rate *= (ac97_div & 0xfff);
+
+	return rate;
+}
+
+/*
+ * Return the current HSIO bus clock frequency
+ */
+static unsigned long clk_pxa3xx_hsio_getrate(struct clk *clk)
+{
+	unsigned long acsr;
+	unsigned int hss, hsio_clk;
+
+	acsr = ACSR;
+
+	hss = (acsr >> 14) & 0x3;
+	hsio_clk = (acsr & ACCR_D0CS) ? RO_CLK : hss_mult[hss] * BASE_CLK;
+
+	return hsio_clk;
+}
+
+/* crystal frequency to static memory controller multiplier (SMCFS) */
+static unsigned int smcfs_mult[8] = { 6, 0, 8, 0, 0, 16, };
+static unsigned int df_clkdiv[4] = { 1, 2, 4, 1 };
+
+static unsigned long clk_pxa3xx_smemc_getrate(struct clk *clk)
+{
+	unsigned long acsr = ACSR;
+	unsigned long memclkcfg = __raw_readl(MEMCLKCFG);
+
+	return BASE_CLK * smcfs_mult[(acsr >> 23) & 0x7] /
+			df_clkdiv[(memclkcfg >> 16) & 0x3];
+}
+
+void clk_pxa3xx_cken_enable(struct clk *clk)
+{
+	unsigned long mask = 1ul << (clk->cken & 0x1f);
+
+	if (clk->cken < 32)
+		CKENA |= mask;
+	else
+		CKENB |= mask;
+}
+
+void clk_pxa3xx_cken_disable(struct clk *clk)
+{
+	unsigned long mask = 1ul << (clk->cken & 0x1f);
+
+	if (clk->cken < 32)
+		CKENA &= ~mask;
+	else
+		CKENB &= ~mask;
+}
+
+const struct clkops clk_pxa3xx_cken_ops = {
+	.enable		= clk_pxa3xx_cken_enable,
+	.disable	= clk_pxa3xx_cken_disable,
+};
+
+const struct clkops clk_pxa3xx_hsio_ops = {
+	.enable		= clk_pxa3xx_cken_enable,
+	.disable	= clk_pxa3xx_cken_disable,
+	.getrate	= clk_pxa3xx_hsio_getrate,
+};
+
+const struct clkops clk_pxa3xx_ac97_ops = {
+	.enable		= clk_pxa3xx_cken_enable,
+	.disable	= clk_pxa3xx_cken_disable,
+	.getrate	= clk_pxa3xx_ac97_getrate,
+};
+
+const struct clkops clk_pxa3xx_smemc_ops = {
+	.enable		= clk_pxa3xx_cken_enable,
+	.disable	= clk_pxa3xx_cken_disable,
+	.getrate	= clk_pxa3xx_smemc_getrate,
+};
+
+static void clk_pout_enable(struct clk *clk)
+{
+	OSCC |= OSCC_PEN;
+}
+
+static void clk_pout_disable(struct clk *clk)
+{
+	OSCC &= ~OSCC_PEN;
+}
+
+const struct clkops clk_pxa3xx_pout_ops = {
+	.enable		= clk_pout_enable,
+	.disable	= clk_pout_disable,
+};
+
+#ifdef CONFIG_PM
+static uint32_t cken[2];
+static uint32_t accr;
+
+static int pxa3xx_clock_suspend(struct sys_device *d, pm_message_t state)
+{
+	cken[0] = CKENA;
+	cken[1] = CKENB;
+	accr = ACCR;
+	return 0;
+}
+
+static int pxa3xx_clock_resume(struct sys_device *d)
+{
+	ACCR = accr;
+	CKENA = cken[0];
+	CKENB = cken[1];
+	return 0;
+}
+#else
+#define pxa3xx_clock_suspend	NULL
+#define pxa3xx_clock_resume	NULL
+#endif
+
+struct sysdev_class pxa3xx_clock_sysclass = {
+	.name		= "pxa3xx-clock",
+	.suspend	= pxa3xx_clock_suspend,
+	.resume		= pxa3xx_clock_resume,
+};
+
+static int __init pxa3xx_clock_init(void)
+{
+	if (cpu_is_pxa3xx() || cpu_is_pxa95x())
+		return sysdev_class_register(&pxa3xx_clock_sysclass);
+	return 0;
+}
+postcore_initcall(pxa3xx_clock_init);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/cm-x255.c linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/cm-x255.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/cm-x255.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/cm-x255.c	2011-03-14 21:20:32.000000000 -0400
@@ -17,13 +17,13 @@
 #include <linux/mtd/nand-gpio.h>
 
 #include <linux/spi/spi.h>
+#include <linux/spi/pxa2xx_spi.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
 #include <asm/mach/map.h>
 
 #include <mach/pxa25x.h>
-#include <mach/pxa2xx_spi.h>
 
 #include "generic.h"
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/cm-x270.c linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/cm-x270.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/cm-x270.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/cm-x270.c	2011-03-14 21:20:32.000000000 -0400
@@ -19,12 +19,12 @@
 #include <video/mbxfb.h>
 
 #include <linux/spi/spi.h>
+#include <linux/spi/pxa2xx_spi.h>
 #include <linux/spi/libertas_spi.h>
 
 #include <mach/pxa27x.h>
 #include <mach/ohci.h>
 #include <mach/mmc.h>
-#include <mach/pxa2xx_spi.h>
 
 #include "generic.h"
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/cm-x2xx.c linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/cm-x2xx.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/cm-x2xx.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/cm-x2xx.c	2011-03-14 21:20:32.000000000 -0400
@@ -24,6 +24,7 @@
 #include <mach/pxa2xx-regs.h>
 #include <mach/audio.h>
 #include <mach/pxafb.h>
+#include <mach/smemc.h>
 
 #include <asm/hardware/it8152.h>
 
@@ -392,9 +393,9 @@ static int cmx2xx_suspend(struct sys_dev
 	cmx2xx_pci_suspend();
 
 	/* save MSC registers */
-	sleep_save_msc[0] = MSC0;
-	sleep_save_msc[1] = MSC1;
-	sleep_save_msc[2] = MSC2;
+	sleep_save_msc[0] = __raw_readl(MSC0);
+	sleep_save_msc[1] = __raw_readl(MSC1);
+	sleep_save_msc[2] = __raw_readl(MSC2);
 
 	/* setup power saving mode registers */
 	PCFR = 0x0;
@@ -416,9 +417,9 @@ static int cmx2xx_resume(struct sys_devi
 	cmx2xx_pci_resume();
 
 	/* restore MSC registers */
-	MSC0 = sleep_save_msc[0];
-	MSC1 = sleep_save_msc[1];
-	MSC2 = sleep_save_msc[2];
+	__raw_writel(sleep_save_msc[0], MSC0);
+	__raw_writel(sleep_save_msc[1], MSC1);
+	__raw_writel(sleep_save_msc[2], MSC2);
 
 	return 0;
 }
@@ -498,7 +499,12 @@ static struct map_desc cmx2xx_io_desc[]
 
 static void __init cmx2xx_map_io(void)
 {
-	pxa_map_io();
+	if (cpu_is_pxa25x())
+		pxa25x_map_io();
+
+	if (cpu_is_pxa27x())
+		pxa27x_map_io();
+
 	iotable_init(cmx2xx_io_desc, ARRAY_SIZE(cmx2xx_io_desc));
 
 	it8152_base_address = CMX2XX_IT8152_VIRT;
@@ -506,7 +512,11 @@ static void __init cmx2xx_map_io(void)
 #else
 static void __init cmx2xx_map_io(void)
 {
-	pxa_map_io();
+	if (cpu_is_pxa25x())
+		pxa25x_map_io();
+
+	if (cpu_is_pxa27x())
+		pxa27x_map_io();
 }
 #endif
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/cm-x2xx-pci.c linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/cm-x2xx-pci.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/cm-x2xx-pci.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/cm-x2xx-pci.c	2011-03-14 21:20:32.000000000 -0400
@@ -59,7 +59,7 @@ void __init cmx2xx_pci_adjust_zones(unsi
 static void cmx2xx_it8152_irq_demux(unsigned int irq, struct irq_desc *desc)
 {
 	/* clear our parent irq */
-	desc->chip->ack(irq);
+	desc->irq_data.chip->irq_ack(&desc->irq_data);
 
 	it8152_irq_demux(irq, desc);
 }
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/cm-x300.c linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/cm-x300.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/cm-x300.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/cm-x300.c	2011-03-14 21:20:32.000000000 -0400
@@ -857,7 +857,7 @@ static void __init cm_x300_fixup(struct
 
 MACHINE_START(CM_X300, "CM-X300 module")
 	.boot_params	= 0xa0000100,
-	.map_io		= pxa_map_io,
+	.map_io		= pxa3xx_map_io,
 	.init_irq	= pxa3xx_init_irq,
 	.timer		= &pxa_timer,
 	.init_machine	= cm_x300_init,
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/colibri-evalboard.c linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/colibri-evalboard.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/colibri-evalboard.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/colibri-evalboard.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,121 @@
+/*
+ *  linux/arch/arm/mach-pxa/colibri-evalboard.c
+ *
+ *  Support for Toradex Colibri Evaluation Carrier Board
+ *  Daniel Mack <daniel@caiaq.de>
+ *  Marek Vasut <marek.vasut@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/init.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/sysdev.h>
+#include <linux/interrupt.h>
+#include <linux/gpio.h>
+#include <asm/mach-types.h>
+#include <mach/hardware.h>
+#include <asm/mach/arch.h>
+#include <linux/i2c.h>
+
+#include <mach/pxa27x.h>
+#include <mach/colibri.h>
+#include <mach/mmc.h>
+#include <mach/ohci.h>
+#include <mach/pxa27x-udc.h>
+
+#include <plat/i2c.h>
+
+#include "generic.h"
+#include "devices.h"
+
+/******************************************************************************
+ * SD/MMC card controller
+ ******************************************************************************/
+#if defined(CONFIG_MMC_PXA) || defined(CONFIG_MMC_PXA_MODULE)
+static struct pxamci_platform_data colibri_mci_platform_data = {
+	.ocr_mask		= MMC_VDD_32_33 | MMC_VDD_33_34,
+	.gpio_power		= -1,
+	.gpio_card_ro		= -1,
+	.detect_delay_ms	= 200,
+};
+
+static void __init colibri_mmc_init(void)
+{
+	if (machine_is_colibri())	/* PXA270 Colibri */
+		colibri_mci_platform_data.gpio_card_detect =
+			GPIO0_COLIBRI_PXA270_SD_DETECT;
+	if (machine_is_colibri300())	/* PXA300 Colibri */
+		colibri_mci_platform_data.gpio_card_detect =
+			GPIO13_COLIBRI_PXA300_SD_DETECT;
+	else				/* PXA320 Colibri */
+		colibri_mci_platform_data.gpio_card_detect =
+			GPIO28_COLIBRI_PXA320_SD_DETECT;
+
+	pxa_set_mci_info(&colibri_mci_platform_data);
+}
+#else
+static inline void colibri_mmc_init(void) {}
+#endif
+
+/******************************************************************************
+ * USB Host
+ ******************************************************************************/
+#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
+static int colibri_ohci_init(struct device *dev)
+{
+	UP2OCR = UP2OCR_HXS | UP2OCR_HXOE | UP2OCR_DPPDE | UP2OCR_DMPDE;
+	return 0;
+}
+
+static struct pxaohci_platform_data colibri_ohci_info = {
+	.port_mode	= PMM_PERPORT_MODE,
+	.flags		= ENABLE_PORT1 |
+			  POWER_CONTROL_LOW | POWER_SENSE_LOW,
+	.init		= colibri_ohci_init,
+};
+
+static void __init colibri_uhc_init(void)
+{
+	/* Colibri PXA270 has two usb ports, TBA for 320 */
+	if (machine_is_colibri())
+		colibri_ohci_info.flags	|= ENABLE_PORT2;
+
+	pxa_set_ohci_info(&colibri_ohci_info);
+}
+#else
+static inline void colibri_uhc_init(void) {}
+#endif
+
+/******************************************************************************
+ * I2C RTC
+ ******************************************************************************/
+#if defined(CONFIG_RTC_DRV_DS1307) || defined(CONFIG_RTC_DRV_DS1307_MODULE)
+static struct i2c_board_info __initdata colibri_i2c_devs[] = {
+	{
+		I2C_BOARD_INFO("m41t00", 0x68),
+	},
+};
+
+static void __init colibri_rtc_init(void)
+{
+	pxa_set_i2c_info(NULL);
+	i2c_register_board_info(0, ARRAY_AND_SIZE(colibri_i2c_devs));
+}
+#else
+static inline void colibri_rtc_init(void) {}
+#endif
+
+void __init colibri_evalboard_init(void)
+{
+	pxa_set_ffuart_info(NULL);
+	pxa_set_btuart_info(NULL);
+	pxa_set_stuart_info(NULL);
+
+	colibri_mmc_init();
+	colibri_uhc_init();
+	colibri_rtc_init();
+}
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/colibri-pxa270.c linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/colibri-pxa270.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/colibri-pxa270.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/colibri-pxa270.c	2011-03-14 21:20:32.000000000 -0400
@@ -33,6 +33,103 @@
 #include "generic.h"
 
 /******************************************************************************
+ * Evaluation board MFP
+ ******************************************************************************/
+#ifdef	 CONFIG_MACH_COLIBRI_EVALBOARD
+static mfp_cfg_t colibri_pxa270_evalboard_pin_config[] __initdata = {
+	/* MMC */
+	GPIO32_MMC_CLK,
+	GPIO92_MMC_DAT_0,
+	GPIO109_MMC_DAT_1,
+	GPIO110_MMC_DAT_2,
+	GPIO111_MMC_DAT_3,
+	GPIO112_MMC_CMD,
+	GPIO0_GPIO,	/* SD detect */
+
+	/* FFUART */
+	GPIO39_FFUART_TXD,
+	GPIO34_FFUART_RXD,
+
+	/* UHC */
+	GPIO88_USBH1_PWR,
+	GPIO89_USBH1_PEN,
+	GPIO119_USBH2_PWR,
+	GPIO120_USBH2_PEN,
+
+	/* PCMCIA */
+	GPIO85_nPCE_1,
+	GPIO54_nPCE_2,
+	GPIO55_nPREG,
+	GPIO50_nPIOR,
+	GPIO51_nPIOW,
+	GPIO49_nPWE,
+	GPIO48_nPOE,
+	GPIO57_nIOIS16,
+	GPIO56_nPWAIT,
+	GPIO104_PSKTSEL,
+	GPIO53_GPIO,	/* RESET */
+	GPIO83_GPIO,	/* BVD1 */
+	GPIO82_GPIO,	/* BVD2 */
+	GPIO1_GPIO,	/* READY */
+	GPIO84_GPIO,	/* DETECT */
+	GPIO107_GPIO,	/* PPEN */
+
+	/* I2C */
+	GPIO117_I2C_SCL,
+	GPIO118_I2C_SDA,
+};
+#else
+static mfp_cfg_t colibri_pxa270_evalboard_pin_config[] __initdata = {};
+#endif
+
+#ifdef	CONFIG_MACH_COLIBRI_PXA270_INCOME
+static mfp_cfg_t income_pin_config[] __initdata = {
+	/* MMC */
+	GPIO32_MMC_CLK,
+	GPIO92_MMC_DAT_0,
+	GPIO109_MMC_DAT_1,
+	GPIO110_MMC_DAT_2,
+	GPIO111_MMC_DAT_3,
+	GPIO112_MMC_CMD,
+	GPIO0_GPIO,	/* SD detect */
+	GPIO1_GPIO,	/* SD read-only */
+
+	/* FFUART */
+	GPIO39_FFUART_TXD,
+	GPIO34_FFUART_RXD,
+
+	/* BFUART */
+	GPIO42_BTUART_RXD,
+	GPIO43_BTUART_TXD,
+	GPIO45_BTUART_RTS,
+
+	/* STUART */
+	GPIO46_STUART_RXD,
+	GPIO47_STUART_TXD,
+
+	/* UHC */
+	GPIO88_USBH1_PWR,
+	GPIO89_USBH1_PEN,
+
+	/* LCD */
+	GPIOxx_LCD_TFT_16BPP,
+
+	/* PWM */
+	GPIO16_PWM0_OUT,
+
+	/* I2C */
+	GPIO117_I2C_SCL,
+	GPIO118_I2C_SDA,
+
+	/* LED */
+	GPIO54_GPIO,	/* LED A */
+	GPIO55_GPIO,	/* LED B */
+};
+#else
+static mfp_cfg_t income_pin_config[] __initdata = {};
+#endif
+
+/******************************************************************************
  * Pin configuration
  ******************************************************************************/
 static mfp_cfg_t colibri_pxa270_pin_config[] __initdata = {
@@ -184,10 +281,13 @@ static void __init colibri_pxa270_init(v
 	colibri_pxa270_tsc_init();
 
 	switch (colibri_pxa270_baseboard) {
-	case COLIBRI_PXA270_EVALBOARD:
-		colibri_pxa270_evalboard_init();
+	case COLIBRI_EVALBOARD:
+		pxa2xx_mfp_config(ARRAY_AND_SIZE(
+			colibri_pxa270_evalboard_pin_config));
+		colibri_evalboard_init();
 		break;
 	case COLIBRI_PXA270_INCOME:
+		pxa2xx_mfp_config(ARRAY_AND_SIZE(income_pin_config));
 		colibri_pxa270_income_boardinit();
 		break;
 	default:
@@ -209,7 +309,7 @@ static void __init colibri_pxa270_income
 MACHINE_START(COLIBRI, "Toradex Colibri PXA270")
 	.boot_params	= COLIBRI_SDRAM_BASE + 0x100,
 	.init_machine	= colibri_pxa270_init,
-	.map_io		= pxa_map_io,
+	.map_io		= pxa27x_map_io,
 	.init_irq	= pxa27x_init_irq,
 	.timer		= &pxa_timer,
 MACHINE_END
@@ -217,7 +317,7 @@ MACHINE_END
 MACHINE_START(INCOME, "Income s.r.o. SH-Dmaster PXA270 SBC")
 	.boot_params	= 0xa0000100,
 	.init_machine	= colibri_pxa270_income_init,
-	.map_io		= pxa_map_io,
+	.map_io		= pxa27x_map_io,
 	.init_irq	= pxa27x_init_irq,
 	.timer		= &pxa_timer,
 MACHINE_END
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/colibri-pxa270-evalboard.c linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/colibri-pxa270-evalboard.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/colibri-pxa270-evalboard.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/colibri-pxa270-evalboard.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,111 +0,0 @@
-/*
- *  linux/arch/arm/mach-pxa/colibri-pxa270-evalboard.c
- *
- *  Support for Toradex PXA270 based Colibri Evaluation Carrier Board
- *  Daniel Mack <daniel@caiaq.de>
- *  Marek Vasut <marek.vasut@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/init.h>
-#include <linux/kernel.h>
-#include <linux/platform_device.h>
-#include <linux/sysdev.h>
-#include <linux/interrupt.h>
-#include <linux/gpio.h>
-#include <asm/mach-types.h>
-#include <mach/hardware.h>
-#include <asm/mach/arch.h>
-
-#include <mach/pxa27x.h>
-#include <mach/colibri.h>
-#include <mach/mmc.h>
-#include <mach/ohci.h>
-#include <mach/pxa27x-udc.h>
-
-#include "generic.h"
-#include "devices.h"
-
-/******************************************************************************
- * Pin configuration
- ******************************************************************************/
-static mfp_cfg_t colibri_pxa270_evalboard_pin_config[] __initdata = {
-	/* MMC */
-	GPIO32_MMC_CLK,
-	GPIO92_MMC_DAT_0,
-	GPIO109_MMC_DAT_1,
-	GPIO110_MMC_DAT_2,
-	GPIO111_MMC_DAT_3,
-	GPIO112_MMC_CMD,
-	GPIO0_GPIO,	/* SD detect */
-
-	/* FFUART */
-	GPIO39_FFUART_TXD,
-	GPIO34_FFUART_RXD,
-
-	/* UHC */
-	GPIO88_USBH1_PWR,
-	GPIO89_USBH1_PEN,
-	GPIO119_USBH2_PWR,
-	GPIO120_USBH2_PEN,
-};
-
-/******************************************************************************
- * SD/MMC card controller
- ******************************************************************************/
-#if defined(CONFIG_MMC_PXA) || defined(CONFIG_MMC_PXA_MODULE)
-static struct pxamci_platform_data colibri_pxa270_mci_platform_data = {
-	.ocr_mask		= MMC_VDD_32_33 | MMC_VDD_33_34,
-	.gpio_power		= -1,
-	.gpio_card_detect	= GPIO0_COLIBRI_PXA270_SD_DETECT,
-	.gpio_card_ro		= -1,
-	.detect_delay_ms	= 200,
-};
-
-static void __init colibri_pxa270_mmc_init(void)
-{
-	pxa_set_mci_info(&colibri_pxa270_mci_platform_data);
-}
-#else
-static inline void colibri_pxa270_mmc_init(void) {}
-#endif
-
-/******************************************************************************
- * USB Host
- ******************************************************************************/
-#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
-static int colibri_pxa270_ohci_init(struct device *dev)
-{
-	UP2OCR = UP2OCR_HXS | UP2OCR_HXOE | UP2OCR_DPPDE | UP2OCR_DMPDE;
-	return 0;
-}
-
-static struct pxaohci_platform_data colibri_pxa270_ohci_info = {
-	.port_mode	= PMM_PERPORT_MODE,
-	.flags		= ENABLE_PORT1 | ENABLE_PORT2 |
-			  POWER_CONTROL_LOW | POWER_SENSE_LOW,
-	.init		= colibri_pxa270_ohci_init,
-};
-
-static void __init colibri_pxa270_uhc_init(void)
-{
-	pxa_set_ohci_info(&colibri_pxa270_ohci_info);
-}
-#else
-static inline void colibri_pxa270_uhc_init(void) {}
-#endif
-
-void __init colibri_pxa270_evalboard_init(void)
-{
-	pxa2xx_mfp_config(ARRAY_AND_SIZE(colibri_pxa270_evalboard_pin_config));
-	pxa_set_ffuart_info(NULL);
-	pxa_set_btuart_info(NULL);
-	pxa_set_stuart_info(NULL);
-
-	colibri_pxa270_mmc_init();
-	colibri_pxa270_uhc_init();
-}
-
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/colibri-pxa270-income.c linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/colibri-pxa270-income.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/colibri-pxa270-income.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/colibri-pxa270-income.c	2011-03-14 21:20:32.000000000 -0400
@@ -46,52 +46,6 @@
 #define GPIO113_INCOME_TS_IRQ   (113)
 
 /******************************************************************************
- * Pin configuration
- ******************************************************************************/
-static mfp_cfg_t income_pin_config[] __initdata = {
-	/* MMC */
-	GPIO32_MMC_CLK,
-	GPIO92_MMC_DAT_0,
-	GPIO109_MMC_DAT_1,
-	GPIO110_MMC_DAT_2,
-	GPIO111_MMC_DAT_3,
-	GPIO112_MMC_CMD,
-	GPIO0_GPIO,	/* SD detect */
-	GPIO1_GPIO,	/* SD read-only */
-
-	/* FFUART */
-	GPIO39_FFUART_TXD,
-	GPIO34_FFUART_RXD,
-
-	/* BFUART */
-	GPIO42_BTUART_RXD,
-	GPIO43_BTUART_TXD,
-	GPIO45_BTUART_RTS,
-
-	/* STUART */
-	GPIO46_STUART_RXD,
-	GPIO47_STUART_TXD,
-
-	/* UHC */
-	GPIO88_USBH1_PWR,
-	GPIO89_USBH1_PEN,
-
-	/* LCD */
-	GPIOxx_LCD_TFT_16BPP,
-
-	/* PWM */
-	GPIO16_PWM0_OUT,
-
-	/* I2C */
-	GPIO117_I2C_SCL,
-	GPIO118_I2C_SDA,
-
-	/* LED */
-	GPIO54_GPIO,	/* LED A */
-	GPIO55_GPIO,	/* LED B */
-};
-
-/******************************************************************************
  * SD/MMC card controller
  ******************************************************************************/
 #if defined(CONFIG_MMC_PXA) || defined(CONFIG_MMC_PXA_MODULE)
@@ -257,7 +211,6 @@ static inline void income_pwm_init(void)
 
 void __init colibri_pxa270_income_boardinit(void)
 {
-	pxa2xx_mfp_config(ARRAY_AND_SIZE(income_pin_config));
 	pxa_set_ffuart_info(NULL);
 	pxa_set_btuart_info(NULL);
 	pxa_set_stuart_info(NULL);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/colibri-pxa300.c linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/colibri-pxa300.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/colibri-pxa300.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/colibri-pxa300.c	2011-03-14 21:20:32.000000000 -0400
@@ -31,9 +31,38 @@
 #include "generic.h"
 #include "devices.h"
 
+
+#ifdef CONFIG_MACH_COLIBRI_EVALBOARD
+static mfp_cfg_t colibri_pxa300_evalboard_pin_config[] __initdata = {
+	/* MMC */
+	GPIO7_MMC1_CLK,
+	GPIO14_MMC1_CMD,
+	GPIO3_MMC1_DAT0,
+	GPIO4_MMC1_DAT1,
+	GPIO5_MMC1_DAT2,
+	GPIO6_MMC1_DAT3,
+	GPIO13_GPIO,	/* GPIO13_COLIBRI_PXA300_SD_DETECT */
+
+	/* UHC */
+	GPIO0_2_USBH_PEN,
+	GPIO1_2_USBH_PWR,
+	GPIO77_USB_P3_1,
+	GPIO78_USB_P3_2,
+	GPIO79_USB_P3_3,
+	GPIO80_USB_P3_4,
+	GPIO81_USB_P3_5,
+	GPIO82_USB_P3_6,
+
+	/* I2C */
+	GPIO21_I2C_SCL,
+	GPIO22_I2C_SDA,
+};
+#else
+static mfp_cfg_t colibri_pxa300_evalboard_pin_config[] __initdata = {};
+#endif
+
 #if defined(CONFIG_AX88796)
 #define COLIBRI_ETH_IRQ_GPIO	mfp_to_gpio(GPIO26_GPIO)
-
 /*
  * Asix AX88796 Ethernet
  */
@@ -80,35 +109,6 @@ static void __init colibri_pxa300_init_e
 static inline void __init colibri_pxa300_init_eth(void) {}
 #endif /* CONFIG_AX88796 */
 
-#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
-static mfp_cfg_t colibri_pxa300_usb_pin_config[] __initdata = {
-	GPIO0_2_USBH_PEN,
-	GPIO1_2_USBH_PWR,
-};
-
-static struct pxaohci_platform_data colibri_pxa300_ohci_info = {
-	.port_mode	= PMM_GLOBAL_MODE,
-	.flags		= ENABLE_PORT1 | POWER_CONTROL_LOW | POWER_SENSE_LOW,
-};
-
-void __init colibri_pxa300_init_ohci(void)
-{
-	pxa3xx_mfp_config(ARRAY_AND_SIZE(colibri_pxa300_usb_pin_config));
-	pxa_set_ohci_info(&colibri_pxa300_ohci_info);
-}
-#else
-static inline void colibri_pxa300_init_ohci(void) {}
-#endif /* CONFIG_USB_OHCI_HCD || CONFIG_USB_OHCI_HCD_MODULE */
-
-static mfp_cfg_t colibri_pxa300_mmc_pin_config[] __initdata = {
-	GPIO7_MMC1_CLK,
-	GPIO14_MMC1_CMD,
-	GPIO3_MMC1_DAT0,
-	GPIO4_MMC1_DAT1,
-	GPIO5_MMC1_DAT2,
-	GPIO6_MMC1_DAT3,
-};
-
 #if defined(CONFIG_FB_PXA) || defined(CONFIG_FB_PXA_MODULE)
 static mfp_cfg_t colibri_pxa300_lcd_pin_config[] __initdata = {
 	GPIO54_LCD_LDD_0,
@@ -171,24 +171,21 @@ static inline void colibri_pxa310_init_a
 
 void __init colibri_pxa300_init(void)
 {
-	pxa_set_ffuart_info(NULL);
-	pxa_set_btuart_info(NULL);
-	pxa_set_stuart_info(NULL);
-
 	colibri_pxa300_init_eth();
-	colibri_pxa300_init_ohci();
 	colibri_pxa3xx_init_nand();
 	colibri_pxa300_init_lcd();
 	colibri_pxa3xx_init_lcd(mfp_to_gpio(GPIO39_GPIO));
 	colibri_pxa310_init_ac97();
-	colibri_pxa3xx_init_mmc(ARRAY_AND_SIZE(colibri_pxa300_mmc_pin_config),
-				mfp_to_gpio(MFP_PIN_GPIO13));
+
+	/* Evalboard init */
+	pxa3xx_mfp_config(ARRAY_AND_SIZE(colibri_pxa300_evalboard_pin_config));
+	colibri_evalboard_init();
 }
 
 MACHINE_START(COLIBRI300, "Toradex Colibri PXA300")
 	.boot_params	= COLIBRI_SDRAM_BASE + 0x100,
 	.init_machine	= colibri_pxa300_init,
-	.map_io		= pxa_map_io,
+	.map_io		= pxa3xx_map_io,
 	.init_irq	= pxa3xx_init_irq,
 	.timer		= &pxa_timer,
 MACHINE_END
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/colibri-pxa320.c linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/colibri-pxa320.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/colibri-pxa320.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/colibri-pxa320.c	2011-03-14 21:20:32.000000000 -0400
@@ -35,9 +35,72 @@
 #include "generic.h"
 #include "devices.h"
 
+#ifdef	CONFIG_MACH_COLIBRI_EVALBOARD
+static mfp_cfg_t colibri_pxa320_evalboard_pin_config[] __initdata = {
+	/* MMC */
+	GPIO22_MMC1_CLK,
+	GPIO23_MMC1_CMD,
+	GPIO18_MMC1_DAT0,
+	GPIO19_MMC1_DAT1,
+	GPIO20_MMC1_DAT2,
+	GPIO21_MMC1_DAT3,
+	GPIO28_GPIO,	/* SD detect */
+
+	/* UART 1 configuration (may be set by bootloader) */
+	GPIO99_UART1_CTS,
+	GPIO104_UART1_RTS,
+	GPIO97_UART1_RXD,
+	GPIO98_UART1_TXD,
+	GPIO101_UART1_DTR,
+	GPIO103_UART1_DSR,
+	GPIO100_UART1_DCD,
+	GPIO102_UART1_RI,
+
+	/* UART 2 configuration */
+	GPIO109_UART2_CTS,
+	GPIO112_UART2_RTS,
+	GPIO110_UART2_RXD,
+	GPIO111_UART2_TXD,
+
+	/* UART 3 configuration */
+	GPIO30_UART3_RXD,
+	GPIO31_UART3_TXD,
+
+	/* UHC */
+	GPIO2_2_USBH_PEN,
+	GPIO3_2_USBH_PWR,
+
+	/* I2C */
+	GPIO32_I2C_SCL,
+	GPIO33_I2C_SDA,
+
+	/* PCMCIA */
+	MFP_CFG(GPIO59, AF7),	/* PRST ; AF7 to tristate */
+	MFP_CFG(GPIO61, AF7),	/* PCE1 ; AF7 to tristate */
+	MFP_CFG(GPIO60, AF7),	/* PCE2 ; AF7 to tristate */
+	MFP_CFG(GPIO62, AF7),	/* PCD ; AF7 to tristate */
+	MFP_CFG(GPIO56, AF7),	/* PSKTSEL ; AF7 to tristate */
+	GPIO27_GPIO,		/* RDnWR ; input/tristate */
+	GPIO50_GPIO,		/* PREG ; input/tristate */
+	GPIO2_RDY,
+	GPIO5_NPIOR,
+	GPIO6_NPIOW,
+	GPIO7_NPIOS16,
+	GPIO8_NPWAIT,
+	GPIO29_GPIO,		/* PRDY (READY GPIO) */
+	GPIO57_GPIO,		/* PPEN (POWER GPIO) */
+	GPIO81_GPIO,		/* PCD (DETECT GPIO) */
+	GPIO77_GPIO,		/* PRST (RESET GPIO) */
+	GPIO53_GPIO,		/* PBVD1 */
+	GPIO79_GPIO,		/* PBVD2 */
+	GPIO54_GPIO,		/* POE */
+};
+#else
+static mfp_cfg_t colibri_pxa320_evalboard_pin_config[] __initdata = {};
+#endif
+
 #if defined(CONFIG_AX88796)
 #define COLIBRI_ETH_IRQ_GPIO	mfp_to_gpio(GPIO36_GPIO)
-
 /*
  * Asix AX88796 Ethernet
  */
@@ -84,26 +147,6 @@ static void __init colibri_pxa320_init_e
 static inline void __init colibri_pxa320_init_eth(void) {}
 #endif /* CONFIG_AX88796 */
 
-#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
-static mfp_cfg_t colibri_pxa320_usb_pin_config[] __initdata = {
-	GPIO2_2_USBH_PEN,
-	GPIO3_2_USBH_PWR,
-};
-
-static struct pxaohci_platform_data colibri_pxa320_ohci_info = {
-	.port_mode	= PMM_GLOBAL_MODE,
-	.flags		= ENABLE_PORT1 | POWER_CONTROL_LOW | POWER_SENSE_LOW,
-};
-
-void __init colibri_pxa320_init_ohci(void)
-{
-	pxa3xx_mfp_config(ARRAY_AND_SIZE(colibri_pxa320_usb_pin_config));
-	pxa_set_ohci_info(&colibri_pxa320_ohci_info);
-}
-#else
-static inline void colibri_pxa320_init_ohci(void) {}
-#endif /* CONFIG_USB_OHCI_HCD || CONFIG_USB_OHCI_HCD_MODULE */
-
 #if defined(CONFIG_USB_GADGET_PXA27X)||defined(CONFIG_USB_GADGET_PXA27X_MODULE)
 static struct gpio_vbus_mach_info colibri_pxa320_gpio_vbus_info = {
 	.gpio_vbus		= mfp_to_gpio(MFP_PIN_GPIO96),
@@ -140,15 +183,6 @@ static void __init colibri_pxa320_init_u
 static inline void colibri_pxa320_init_udc(void) {}
 #endif
 
-static mfp_cfg_t colibri_pxa320_mmc_pin_config[] __initdata = {
-	GPIO22_MMC1_CLK,
-	GPIO23_MMC1_CMD,
-	GPIO18_MMC1_DAT0,
-	GPIO19_MMC1_DAT1,
-	GPIO20_MMC1_DAT2,
-	GPIO21_MMC1_DAT3
-};
-
 #if defined(CONFIG_FB_PXA) || defined(CONFIG_FB_PXA_MODULE)
 static mfp_cfg_t colibri_pxa320_lcd_pin_config[] __initdata = {
 	GPIO6_2_LCD_LDD_0,
@@ -205,59 +239,24 @@ static inline void __init colibri_pxa320
 static inline void colibri_pxa320_init_ac97(void) {}
 #endif
 
-/*
- * The following configuration is verified to work with the Toradex Orchid
- * carrier board
- */
-static mfp_cfg_t colibri_pxa320_uart_pin_config[] __initdata = {
-	/* UART 1 configuration (may be set by bootloader) */
-	GPIO99_UART1_CTS,
-	GPIO104_UART1_RTS,
-	GPIO97_UART1_RXD,
-	GPIO98_UART1_TXD,
-	GPIO101_UART1_DTR,
-	GPIO103_UART1_DSR,
-	GPIO100_UART1_DCD,
-	GPIO102_UART1_RI,
-
-	/* UART 2 configuration */
-	GPIO109_UART2_CTS,
-	GPIO112_UART2_RTS,
-	GPIO110_UART2_RXD,
-	GPIO111_UART2_TXD,
-
-	/* UART 3 configuration */
-	GPIO30_UART3_RXD,
-	GPIO31_UART3_TXD,
-};
-
-static void __init colibri_pxa320_init_uart(void)
-{
-	pxa3xx_mfp_config(ARRAY_AND_SIZE(colibri_pxa320_uart_pin_config));
-}
-
 void __init colibri_pxa320_init(void)
 {
-	pxa_set_ffuart_info(NULL);
-	pxa_set_btuart_info(NULL);
-	pxa_set_stuart_info(NULL);
-
 	colibri_pxa320_init_eth();
-	colibri_pxa320_init_ohci();
 	colibri_pxa3xx_init_nand();
 	colibri_pxa320_init_lcd();
 	colibri_pxa3xx_init_lcd(mfp_to_gpio(GPIO49_GPIO));
 	colibri_pxa320_init_ac97();
-	colibri_pxa3xx_init_mmc(ARRAY_AND_SIZE(colibri_pxa320_mmc_pin_config),
-				mfp_to_gpio(MFP_PIN_GPIO28));
-	colibri_pxa320_init_uart();
 	colibri_pxa320_init_udc();
+
+	/* Evalboard init */
+	pxa3xx_mfp_config(ARRAY_AND_SIZE(colibri_pxa320_evalboard_pin_config));
+	colibri_evalboard_init();
 }
 
 MACHINE_START(COLIBRI320, "Toradex Colibri PXA320")
 	.boot_params	= COLIBRI_SDRAM_BASE + 0x100,
 	.init_machine	= colibri_pxa320_init,
-	.map_io		= pxa_map_io,
+	.map_io		= pxa3xx_map_io,
 	.init_irq	= pxa3xx_init_irq,
 	.timer		= &pxa_timer,
 MACHINE_END
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/colibri-pxa3xx.c linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/colibri-pxa3xx.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/colibri-pxa3xx.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/colibri-pxa3xx.c	2011-03-14 21:20:32.000000000 -0400
@@ -64,55 +64,6 @@ void __init colibri_pxa3xx_init_eth(stru
 }
 #endif
 
-#if defined(CONFIG_MMC_PXA) || defined(CONFIG_MMC_PXA_MODULE)
-static int mmc_detect_pin;
-
-static int colibri_pxa3xx_mci_init(struct device *dev,
-				   irq_handler_t colibri_mmc_detect_int,
-				   void *data)
-{
-	int ret;
-
-	ret = gpio_request(mmc_detect_pin, "mmc card detect");
-	if (ret)
-		return ret;
-
-	gpio_direction_input(mmc_detect_pin);
-	ret = request_irq(gpio_to_irq(mmc_detect_pin), colibri_mmc_detect_int,
-			  IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
-			  "MMC card detect", data);
-	if (ret) {
-		gpio_free(mmc_detect_pin);
-		return ret;
-	}
-
-	return 0;
-}
-
-static void colibri_pxa3xx_mci_exit(struct device *dev, void *data)
-{
-	free_irq(mmc_detect_pin, data);
-	gpio_free(gpio_to_irq(mmc_detect_pin));
-}
-
-static struct pxamci_platform_data colibri_pxa3xx_mci_platform_data = {
-	.detect_delay_ms	= 200,
-	.ocr_mask		= MMC_VDD_32_33 | MMC_VDD_33_34,
-	.init			= colibri_pxa3xx_mci_init,
-	.exit			= colibri_pxa3xx_mci_exit,
-	.gpio_card_detect	= -1,
-	.gpio_card_ro		= -1,
-	.gpio_power		= -1,
-};
-
-void __init colibri_pxa3xx_init_mmc(mfp_cfg_t *pins, int len, int detect_pin)
-{
-	pxa3xx_mfp_config(pins, len);
-	mmc_detect_pin = detect_pin;
-	pxa_set_mci_info(&colibri_pxa3xx_mci_platform_data);
-}
-#endif /* CONFIG_MMC_PXA || CONFIG_MMC_PXA_MODULE */
-
 #if defined(CONFIG_FB_PXA) || defined(CONFIG_FB_PXA_MODULE)
 static int lcd_bl_pin;
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/corgi.c linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/corgi.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/corgi.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/corgi.c	2011-03-14 21:20:32.000000000 -0400
@@ -28,6 +28,7 @@
 #include <linux/spi/spi.h>
 #include <linux/spi/ads7846.h>
 #include <linux/spi/corgi_lcd.h>
+#include <linux/spi/pxa2xx_spi.h>
 #include <linux/mtd/sharpsl.h>
 #include <linux/input/matrix_keypad.h>
 #include <video/w100fb.h>
@@ -48,7 +49,6 @@
 #include <mach/irda.h>
 #include <mach/mmc.h>
 #include <mach/udc.h>
-#include <mach/pxa2xx_spi.h>
 #include <mach/corgi.h>
 #include <mach/sharpsl_pm.h>
 
@@ -721,7 +721,7 @@ static void __init fixup_corgi(struct ma
 #ifdef CONFIG_MACH_CORGI
 MACHINE_START(CORGI, "SHARP Corgi")
 	.fixup		= fixup_corgi,
-	.map_io		= pxa_map_io,
+	.map_io		= pxa25x_map_io,
 	.init_irq	= pxa25x_init_irq,
 	.init_machine	= corgi_init,
 	.timer		= &pxa_timer,
@@ -731,7 +731,7 @@ MACHINE_END
 #ifdef CONFIG_MACH_SHEPHERD
 MACHINE_START(SHEPHERD, "SHARP Shepherd")
 	.fixup		= fixup_corgi,
-	.map_io		= pxa_map_io,
+	.map_io		= pxa25x_map_io,
 	.init_irq	= pxa25x_init_irq,
 	.init_machine	= corgi_init,
 	.timer		= &pxa_timer,
@@ -741,7 +741,7 @@ MACHINE_END
 #ifdef CONFIG_MACH_HUSKY
 MACHINE_START(HUSKY, "SHARP Husky")
 	.fixup		= fixup_corgi,
-	.map_io		= pxa_map_io,
+	.map_io		= pxa25x_map_io,
 	.init_irq	= pxa25x_init_irq,
 	.init_machine	= corgi_init,
 	.timer		= &pxa_timer,
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/cpufreq-pxa2xx.c linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/cpufreq-pxa2xx.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/cpufreq-pxa2xx.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/cpufreq-pxa2xx.c	2011-03-14 21:20:32.000000000 -0400
@@ -38,8 +38,10 @@
 #include <linux/cpufreq.h>
 #include <linux/err.h>
 #include <linux/regulator/consumer.h>
+#include <linux/io.h>
 
 #include <mach/pxa2xx-regs.h>
+#include <mach/smemc.h>
 
 #ifdef DEBUG
 static unsigned int freq_debug;
@@ -242,7 +244,7 @@ static void pxa27x_guess_max_freq(void)
 
 static void init_sdram_rows(void)
 {
-	uint32_t mdcnfg = MDCNFG;
+	uint32_t mdcnfg = __raw_readl(MDCNFG);
 	unsigned int drac2 = 0, drac0 = 0;
 
 	if (mdcnfg & (MDCNFG_DE2 | MDCNFG_DE3))
@@ -331,8 +333,8 @@ static int pxa_set_target(struct cpufreq
 	 * we need to preset the smaller DRI before the change.	 If we're
 	 * speeding up we need to set the larger DRI value after the change.
 	 */
-	preset_mdrefr = postset_mdrefr = MDREFR;
-	if ((MDREFR & MDREFR_DRI_MASK) > mdrefr_dri(new_freq_mem)) {
+	preset_mdrefr = postset_mdrefr = __raw_readl(MDREFR);
+	if ((preset_mdrefr & MDREFR_DRI_MASK) > mdrefr_dri(new_freq_mem)) {
 		preset_mdrefr = (preset_mdrefr & ~MDREFR_DRI_MASK);
 		preset_mdrefr |= mdrefr_dri(new_freq_mem);
 	}
@@ -370,7 +372,7 @@ static int pxa_set_target(struct cpufreq
 3:		nop							\n\
 	  "
 		     : "=&r" (unused)
-		     : "r" (&MDREFR), "r" (cclkcfg),
+		     : "r" (MDREFR), "r" (cclkcfg),
 		       "r" (preset_mdrefr), "r" (postset_mdrefr)
 		     : "r4", "r5");
 	local_irq_restore(flags);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/csb726.c linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/csb726.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/csb726.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/csb726.c	2011-03-14 21:20:32.000000000 -0400
@@ -27,6 +27,7 @@
 #include <mach/ohci.h>
 #include <mach/pxa2xx-regs.h>
 #include <mach/audio.h>
+#include <mach/smemc.h>
 
 #include "generic.h"
 #include "devices.h"
@@ -255,9 +256,9 @@ static struct platform_device *devices[]
 static void __init csb726_init(void)
 {
 	pxa2xx_mfp_config(ARRAY_AND_SIZE(csb726_pin_config));
-/*	MSC1 = 0x7ffc3ffc; *//* LAN9215/EXP_CS */
-/*	MSC2 = 0x06697ff4; *//* none/SM501 */
-	MSC2 = (MSC2 & ~0xffff) | 0x7ff4; /* SM501 */
+/*	__raw_writel(0x7ffc3ffc, MSC1); *//* LAN9215/EXP_CS */
+/*	__raw_writel(0x06697ff4, MSC2); *//* none/SM501 */
+	__raw_writel((__raw_readl(MSC2) & ~0xffff) | 0x7ff4, MSC2); /* SM501 */
 
 	pxa_set_ffuart_info(NULL);
 	pxa_set_btuart_info(NULL);
@@ -273,7 +274,7 @@ static void __init csb726_init(void)
 
 MACHINE_START(CSB726, "Cogent CSB726")
 	.boot_params	= 0xa0000100,
-	.map_io         = pxa_map_io,
+	.map_io         = pxa27x_map_io,
 	.init_irq       = pxa27x_init_irq,
 	.init_machine   = csb726_init,
 	.timer          = &pxa_timer,
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/devices.c linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/devices.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/devices.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/devices.c	2011-03-14 21:20:32.000000000 -0400
@@ -3,6 +3,7 @@
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
+#include <linux/spi/pxa2xx_spi.h>
 
 #include <asm/pmu.h>
 #include <mach/udc.h>
@@ -12,7 +13,6 @@
 #include <mach/irda.h>
 #include <mach/ohci.h>
 #include <plat/pxa27x_keypad.h>
-#include <mach/pxa2xx_spi.h>
 #include <mach/camera.h>
 #include <mach/audio.h>
 #include <mach/hardware.h>
@@ -342,27 +342,6 @@ struct platform_device pxa27x_device_i2c
 };
 #endif
 
-#ifdef CONFIG_PXA3xx
-static struct resource pxa3xx_resources_i2c_power[] = {
-	{
-		.start  = 0x40f500c0,
-		.end    = 0x40f500d3,
-		.flags	= IORESOURCE_MEM,
-	}, {
-		.start	= IRQ_PWRI2C,
-		.end	= IRQ_PWRI2C,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-struct platform_device pxa3xx_device_i2c_power = {
-	.name		= "pxa3xx-pwri2c",
-	.id		= 1,
-	.resource	= pxa3xx_resources_i2c_power,
-	.num_resources	= ARRAY_SIZE(pxa3xx_resources_i2c_power),
-};
-#endif
-
 static struct resource pxai2s_resources[] = {
 	{
 		.start	= 0x40400000,
@@ -633,30 +612,35 @@ struct platform_device pxa25x_device_ass
 #endif /* CONFIG_PXA25x */
 
 #if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx)
-
-static struct resource pxa27x_resource_keypad[] = {
+static struct resource pxa27x_resource_camera[] = {
 	[0] = {
-		.start	= 0x41500000,
-		.end	= 0x4150004c,
+		.start	= 0x50000000,
+		.end	= 0x50000fff,
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
-		.start	= IRQ_KEYPAD,
-		.end	= IRQ_KEYPAD,
+		.start	= IRQ_CAMERA,
+		.end	= IRQ_CAMERA,
 		.flags	= IORESOURCE_IRQ,
 	},
 };
 
-struct platform_device pxa27x_device_keypad = {
-	.name		= "pxa27x-keypad",
-	.id		= -1,
-	.resource	= pxa27x_resource_keypad,
-	.num_resources	= ARRAY_SIZE(pxa27x_resource_keypad),
+static u64 pxa27x_dma_mask_camera = DMA_BIT_MASK(32);
+
+static struct platform_device pxa27x_device_camera = {
+	.name		= "pxa27x-camera",
+	.id		= 0, /* This is used to put cameras on this interface */
+	.dev		= {
+		.dma_mask      		= &pxa27x_dma_mask_camera,
+		.coherent_dma_mask	= 0xffffffff,
+	},
+	.num_resources	= ARRAY_SIZE(pxa27x_resource_camera),
+	.resource	= pxa27x_resource_camera,
 };
 
-void __init pxa_set_keypad_info(struct pxa27x_keypad_platform_data *info)
+void __init pxa_set_camera_info(struct pxacamera_platform_data *info)
 {
-	pxa_register_device(&pxa27x_device_keypad, info);
+	pxa_register_device(&pxa27x_device_camera, info);
 }
 
 static u64 pxa27x_ohci_dma_mask = DMA_BIT_MASK(32);
@@ -689,6 +673,33 @@ void __init pxa_set_ohci_info(struct pxa
 {
 	pxa_register_device(&pxa27x_device_ohci, info);
 }
+#endif /* CONFIG_PXA27x || CONFIG_PXA3xx */
+
+#if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx) || defined(CONFIG_PXA95x)
+static struct resource pxa27x_resource_keypad[] = {
+	[0] = {
+		.start	= 0x41500000,
+		.end	= 0x4150004c,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= IRQ_KEYPAD,
+		.end	= IRQ_KEYPAD,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+struct platform_device pxa27x_device_keypad = {
+	.name		= "pxa27x-keypad",
+	.id		= -1,
+	.resource	= pxa27x_resource_keypad,
+	.num_resources	= ARRAY_SIZE(pxa27x_resource_keypad),
+};
+
+void __init pxa_set_keypad_info(struct pxa27x_keypad_platform_data *info)
+{
+	pxa_register_device(&pxa27x_device_keypad, info);
+}
 
 static u64 pxa27x_ssp1_dma_mask = DMA_BIT_MASK(32);
 
@@ -833,79 +844,9 @@ struct platform_device pxa27x_device_pwm
 	.resource	= pxa27x_resource_pwm1,
 	.num_resources	= ARRAY_SIZE(pxa27x_resource_pwm1),
 };
-
-static struct resource pxa27x_resource_camera[] = {
-	[0] = {
-		.start	= 0x50000000,
-		.end	= 0x50000fff,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= IRQ_CAMERA,
-		.end	= IRQ_CAMERA,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static u64 pxa27x_dma_mask_camera = DMA_BIT_MASK(32);
-
-static struct platform_device pxa27x_device_camera = {
-	.name		= "pxa27x-camera",
-	.id		= 0, /* This is used to put cameras on this interface */
-	.dev		= {
-		.dma_mask      		= &pxa27x_dma_mask_camera,
-		.coherent_dma_mask	= 0xffffffff,
-	},
-	.num_resources	= ARRAY_SIZE(pxa27x_resource_camera),
-	.resource	= pxa27x_resource_camera,
-};
-
-void __init pxa_set_camera_info(struct pxacamera_platform_data *info)
-{
-	pxa_register_device(&pxa27x_device_camera, info);
-}
-#endif /* CONFIG_PXA27x || CONFIG_PXA3xx */
+#endif /* CONFIG_PXA27x || CONFIG_PXA3xx || CONFIG_PXA95x*/
 
 #ifdef CONFIG_PXA3xx
-static u64 pxa3xx_ssp4_dma_mask = DMA_BIT_MASK(32);
-
-static struct resource pxa3xx_resource_ssp4[] = {
-	[0] = {
-		.start	= 0x41a00000,
-		.end	= 0x41a0003f,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= IRQ_SSP4,
-		.end	= IRQ_SSP4,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[2] = {
-		/* DRCMR for RX */
-		.start	= 2,
-		.end	= 2,
-		.flags	= IORESOURCE_DMA,
-	},
-	[3] = {
-		/* DRCMR for TX */
-		.start	= 3,
-		.end	= 3,
-		.flags	= IORESOURCE_DMA,
-	},
-};
-
-struct platform_device pxa3xx_device_ssp4 = {
-	/* PXA3xx SSP is basically equivalent to PXA27x */
-	.name		= "pxa27x-ssp",
-	.id		= 3,
-	.dev		= {
-		.dma_mask = &pxa3xx_ssp4_dma_mask,
-		.coherent_dma_mask = DMA_BIT_MASK(32),
-	},
-	.resource	= pxa3xx_resource_ssp4,
-	.num_resources	= ARRAY_SIZE(pxa3xx_resource_ssp4),
-};
-
 static struct resource pxa3xx_resources_mci2[] = {
 	[0] = {
 		.start	= 0x42000000,
@@ -984,6 +925,54 @@ void __init pxa3xx_set_mci3_info(struct
 	pxa_register_device(&pxa3xx_device_mci3, info);
 }
 
+static struct resource pxa3xx_resources_gcu[] = {
+	{
+		.start	= 0x54000000,
+		.end	= 0x54000fff,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.start	= IRQ_GCU,
+		.end	= IRQ_GCU,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static u64 pxa3xx_gcu_dmamask = DMA_BIT_MASK(32);
+
+struct platform_device pxa3xx_device_gcu = {
+	.name		= "pxa3xx-gcu",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(pxa3xx_resources_gcu),
+	.resource	= pxa3xx_resources_gcu,
+	.dev		= {
+		.dma_mask = &pxa3xx_gcu_dmamask,
+		.coherent_dma_mask = 0xffffffff,
+	},
+};
+
+#endif /* CONFIG_PXA3xx */
+
+#if defined(CONFIG_PXA3xx) || defined(CONFIG_PXA95x)
+static struct resource pxa3xx_resources_i2c_power[] = {
+	{
+		.start  = 0x40f500c0,
+		.end    = 0x40f500d3,
+		.flags	= IORESOURCE_MEM,
+	}, {
+		.start	= IRQ_PWRI2C,
+		.end	= IRQ_PWRI2C,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+struct platform_device pxa3xx_device_i2c_power = {
+	.name		= "pxa3xx-pwri2c",
+	.id		= 1,
+	.resource	= pxa3xx_resources_i2c_power,
+	.num_resources	= ARRAY_SIZE(pxa3xx_resources_i2c_power),
+};
+
 static struct resource pxa3xx_resources_nand[] = {
 	[0] = {
 		.start	= 0x43100000,
@@ -1027,33 +1016,45 @@ void __init pxa3xx_set_nand_info(struct
 	pxa_register_device(&pxa3xx_device_nand, info);
 }
 
-static struct resource pxa3xx_resources_gcu[] = {
-	{
-		.start	= 0x54000000,
-		.end	= 0x54000fff,
+static u64 pxa3xx_ssp4_dma_mask = DMA_BIT_MASK(32);
+
+static struct resource pxa3xx_resource_ssp4[] = {
+	[0] = {
+		.start	= 0x41a00000,
+		.end	= 0x41a0003f,
 		.flags	= IORESOURCE_MEM,
 	},
-	{
-		.start	= IRQ_GCU,
-		.end	= IRQ_GCU,
+	[1] = {
+		.start	= IRQ_SSP4,
+		.end	= IRQ_SSP4,
 		.flags	= IORESOURCE_IRQ,
 	},
+	[2] = {
+		/* DRCMR for RX */
+		.start	= 2,
+		.end	= 2,
+		.flags	= IORESOURCE_DMA,
+	},
+	[3] = {
+		/* DRCMR for TX */
+		.start	= 3,
+		.end	= 3,
+		.flags	= IORESOURCE_DMA,
+	},
 };
 
-static u64 pxa3xx_gcu_dmamask = DMA_BIT_MASK(32);
-
-struct platform_device pxa3xx_device_gcu = {
-	.name		= "pxa3xx-gcu",
-	.id		= -1,
-	.num_resources	= ARRAY_SIZE(pxa3xx_resources_gcu),
-	.resource	= pxa3xx_resources_gcu,
+struct platform_device pxa3xx_device_ssp4 = {
+	/* PXA3xx SSP is basically equivalent to PXA27x */
+	.name		= "pxa27x-ssp",
+	.id		= 3,
 	.dev		= {
-		.dma_mask = &pxa3xx_gcu_dmamask,
-		.coherent_dma_mask = 0xffffffff,
+		.dma_mask = &pxa3xx_ssp4_dma_mask,
+		.coherent_dma_mask = DMA_BIT_MASK(32),
 	},
+	.resource	= pxa3xx_resource_ssp4,
+	.num_resources	= ARRAY_SIZE(pxa3xx_resource_ssp4),
 };
-
-#endif /* CONFIG_PXA3xx */
+#endif /* CONFIG_PXA3xx || CONFIG_PXA95x */
 
 /* pxa2xx-spi platform-device ID equals respective SSP platform-device ID + 1.
  * See comment in arch/arm/mach-pxa/ssp.c::ssp_probe() */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/em-x270.c linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/em-x270.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/em-x270.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/em-x270.c	2011-03-14 21:20:32.000000000 -0400
@@ -26,6 +26,7 @@
 #include <linux/spi/spi.h>
 #include <linux/spi/tdo24m.h>
 #include <linux/spi/libertas_spi.h>
+#include <linux/spi/pxa2xx_spi.h>
 #include <linux/power_supply.h>
 #include <linux/apm-emulation.h>
 #include <linux/i2c.h>
@@ -46,7 +47,6 @@
 #include <plat/pxa27x_keypad.h>
 #include <plat/i2c.h>
 #include <mach/camera.h>
-#include <mach/pxa2xx_spi.h>
 
 #include "generic.h"
 #include "devices.h"
@@ -1300,7 +1300,7 @@ static void __init em_x270_init(void)
 
 MACHINE_START(EM_X270, "Compulab EM-X270")
 	.boot_params	= 0xa0000100,
-	.map_io		= pxa_map_io,
+	.map_io		= pxa27x_map_io,
 	.init_irq	= pxa27x_init_irq,
 	.timer		= &pxa_timer,
 	.init_machine	= em_x270_init,
@@ -1308,7 +1308,7 @@ MACHINE_END
 
 MACHINE_START(EXEDA, "Compulab eXeda")
 	.boot_params	= 0xa0000100,
-	.map_io		= pxa_map_io,
+	.map_io		= pxa27x_map_io,
 	.init_irq	= pxa27x_init_irq,
 	.timer		= &pxa_timer,
 	.init_machine	= em_x270_init,
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/eseries.c linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/eseries.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/eseries.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/eseries.c	2011-03-14 21:20:32.000000000 -0400
@@ -181,7 +181,7 @@ static void __init e330_init(void)
 MACHINE_START(E330, "Toshiba e330")
 	/* Maintainer: Ian Molton (spyro@f2s.com) */
 	.boot_params	= 0xa0000100,
-	.map_io		= pxa_map_io,
+	.map_io		= pxa25x_map_io,
 	.nr_irqs	= ESERIES_NR_IRQS,
 	.init_irq	= pxa25x_init_irq,
 	.fixup		= eseries_fixup,
@@ -230,7 +230,7 @@ static void __init e350_init(void)
 MACHINE_START(E350, "Toshiba e350")
 	/* Maintainer: Ian Molton (spyro@f2s.com) */
 	.boot_params	= 0xa0000100,
-	.map_io		= pxa_map_io,
+	.map_io		= pxa25x_map_io,
 	.nr_irqs	= ESERIES_NR_IRQS,
 	.init_irq	= pxa25x_init_irq,
 	.fixup		= eseries_fixup,
@@ -352,7 +352,7 @@ static void __init e400_init(void)
 MACHINE_START(E400, "Toshiba e400")
 	/* Maintainer: Ian Molton (spyro@f2s.com) */
 	.boot_params	= 0xa0000100,
-	.map_io		= pxa_map_io,
+	.map_io		= pxa25x_map_io,
 	.nr_irqs	= ESERIES_NR_IRQS,
 	.init_irq	= pxa25x_init_irq,
 	.fixup		= eseries_fixup,
@@ -540,7 +540,7 @@ static void __init e740_init(void)
 MACHINE_START(E740, "Toshiba e740")
 	/* Maintainer: Ian Molton (spyro@f2s.com) */
 	.boot_params	= 0xa0000100,
-	.map_io		= pxa_map_io,
+	.map_io		= pxa25x_map_io,
 	.nr_irqs	= ESERIES_NR_IRQS,
 	.init_irq	= pxa25x_init_irq,
 	.fixup		= eseries_fixup,
@@ -731,7 +731,7 @@ static void __init e750_init(void)
 MACHINE_START(E750, "Toshiba e750")
 	/* Maintainer: Ian Molton (spyro@f2s.com) */
 	.boot_params	= 0xa0000100,
-	.map_io		= pxa_map_io,
+	.map_io		= pxa25x_map_io,
 	.nr_irqs	= ESERIES_NR_IRQS,
 	.init_irq	= pxa25x_init_irq,
 	.fixup		= eseries_fixup,
@@ -926,7 +926,7 @@ static void __init e800_init(void)
 MACHINE_START(E800, "Toshiba e800")
 	/* Maintainer: Ian Molton (spyro@f2s.com) */
 	.boot_params	= 0xa0000100,
-	.map_io		= pxa_map_io,
+	.map_io		= pxa25x_map_io,
 	.nr_irqs	= ESERIES_NR_IRQS,
 	.init_irq	= pxa25x_init_irq,
 	.fixup		= eseries_fixup,
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/ezx.c linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/ezx.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/ezx.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/ezx.c	2011-03-14 21:20:32.000000000 -0400
@@ -798,7 +798,7 @@ static void __init a780_init(void)
 
 MACHINE_START(EZX_A780, "Motorola EZX A780")
 	.boot_params    = 0xa0000100,
-	.map_io         = pxa_map_io,
+	.map_io         = pxa27x_map_io,
 	.nr_irqs	= EZX_NR_IRQS,
 	.init_irq       = pxa27x_init_irq,
 	.timer          = &pxa_timer,
@@ -863,7 +863,7 @@ static void __init e680_init(void)
 
 MACHINE_START(EZX_E680, "Motorola EZX E680")
 	.boot_params    = 0xa0000100,
-	.map_io         = pxa_map_io,
+	.map_io         = pxa27x_map_io,
 	.nr_irqs	= EZX_NR_IRQS,
 	.init_irq       = pxa27x_init_irq,
 	.timer          = &pxa_timer,
@@ -928,7 +928,7 @@ static void __init a1200_init(void)
 
 MACHINE_START(EZX_A1200, "Motorola EZX A1200")
 	.boot_params    = 0xa0000100,
-	.map_io         = pxa_map_io,
+	.map_io         = pxa27x_map_io,
 	.nr_irqs	= EZX_NR_IRQS,
 	.init_irq       = pxa27x_init_irq,
 	.timer          = &pxa_timer,
@@ -1118,7 +1118,7 @@ static void __init a910_init(void)
 
 MACHINE_START(EZX_A910, "Motorola EZX A910")
 	.boot_params    = 0xa0000100,
-	.map_io         = pxa_map_io,
+	.map_io         = pxa27x_map_io,
 	.nr_irqs	= EZX_NR_IRQS,
 	.init_irq       = pxa27x_init_irq,
 	.timer          = &pxa_timer,
@@ -1183,7 +1183,7 @@ static void __init e6_init(void)
 
 MACHINE_START(EZX_E6, "Motorola EZX E6")
 	.boot_params    = 0xa0000100,
-	.map_io         = pxa_map_io,
+	.map_io         = pxa27x_map_io,
 	.nr_irqs	= EZX_NR_IRQS,
 	.init_irq       = pxa27x_init_irq,
 	.timer          = &pxa_timer,
@@ -1222,7 +1222,7 @@ static void __init e2_init(void)
 
 MACHINE_START(EZX_E2, "Motorola EZX E2")
 	.boot_params    = 0xa0000100,
-	.map_io         = pxa_map_io,
+	.map_io         = pxa27x_map_io,
 	.nr_irqs	= EZX_NR_IRQS,
 	.init_irq       = pxa27x_init_irq,
 	.timer          = &pxa_timer,
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/generic.c linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/generic.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/generic.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/generic.c	2011-03-14 21:20:32.000000000 -0400
@@ -22,12 +22,13 @@
 
 #include <mach/hardware.h>
 #include <asm/system.h>
-#include <asm/pgtable.h>
 #include <asm/mach/map.h>
 #include <asm/mach-types.h>
 
 #include <mach/reset.h>
 #include <mach/gpio.h>
+#include <mach/smemc.h>
+#include <mach/pxa3xx-regs.h>
 
 #include "generic.h"
 
@@ -35,9 +36,10 @@ void clear_reset_status(unsigned int mas
 {
 	if (cpu_is_pxa2xx())
 		pxa2xx_clear_reset_status(mask);
-
-	if (cpu_is_pxa3xx())
-		pxa3xx_clear_reset_status(mask);
+	else {
+		/* RESET_STATUS_* has a 1:1 mapping with ARSR */
+		ARSR = mask;
+	}
 }
 
 unsigned long get_clock_tick_rate(void)
@@ -71,47 +73,17 @@ unsigned int get_clk_frequency_khz(int i
 EXPORT_SYMBOL(get_clk_frequency_khz);
 
 /*
- * Return the current memory clock frequency in units of 10kHz
- */
-unsigned int get_memclk_frequency_10khz(void)
-{
-	if (cpu_is_pxa25x())
-		return pxa25x_get_memclk_frequency_10khz();
-	else if (cpu_is_pxa27x())
-		return pxa27x_get_memclk_frequency_10khz();
-	return 0;
-}
-EXPORT_SYMBOL(get_memclk_frequency_10khz);
-
-/*
  * Intel PXA2xx internal register mapping.
  *
- * Note 1: not all PXA2xx variants implement all those addresses.
- *
- * Note 2: virtual 0xfffe0000-0xffffffff is reserved for the vector table
- *         and cache flush area.
+ * Note: virtual 0xfffe0000-0xffffffff is reserved for the vector table
+ *       and cache flush area.
  */
-static struct map_desc standard_io_desc[] __initdata = {
+static struct map_desc common_io_desc[] __initdata = {
   	{	/* Devs */
 		.virtual	=  0xf2000000,
 		.pfn		= __phys_to_pfn(0x40000000),
 		.length		= 0x02000000,
 		.type		= MT_DEVICE
-	}, {	/* Mem Ctl */
-		.virtual	=  0xf6000000,
-		.pfn		= __phys_to_pfn(0x48000000),
-		.length		= 0x00200000,
-		.type		= MT_DEVICE
-	}, {	/* Camera */
-		.virtual	=  0xfa000000,
-		.pfn		= __phys_to_pfn(0x50000000),
-		.length		= 0x00100000,
-		.type		= MT_DEVICE
-	}, {	/* IMem ctl */
-		.virtual	=  0xfe000000,
-		.pfn		= __phys_to_pfn(0x58000000),
-		.length		= 0x00100000,
-		.type		= MT_DEVICE
 	}, {	/* UNCACHED_PHYS_0 */
 		.virtual	= 0xff000000,
 		.pfn		= __phys_to_pfn(0x00000000),
@@ -122,6 +94,5 @@ static struct map_desc standard_io_desc[
 
 void __init pxa_map_io(void)
 {
-	iotable_init(standard_io_desc, ARRAY_SIZE(standard_io_desc));
-	get_clk_frequency_khz(1);
+	iotable_init(ARRAY_AND_SIZE(common_io_desc));
 }
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/generic.h linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/generic.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/generic.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/generic.h	2011-03-14 21:20:32.000000000 -0400
@@ -9,18 +9,25 @@
  * published by the Free Software Foundation.
  */
 
+struct irq_data;
 struct sys_timer;
 
 extern struct sys_timer pxa_timer;
 extern void __init pxa_init_irq(int irq_nr,
-				int (*set_wake)(unsigned int, unsigned int));
+				int (*set_wake)(struct irq_data *,
+						unsigned int));
 extern void __init pxa25x_init_irq(void);
 #ifdef CONFIG_CPU_PXA26x
 extern void __init pxa26x_init_irq(void);
 #endif
 extern void __init pxa27x_init_irq(void);
 extern void __init pxa3xx_init_irq(void);
+extern void __init pxa95x_init_irq(void);
+
 extern void __init pxa_map_io(void);
+extern void __init pxa25x_map_io(void);
+extern void __init pxa27x_map_io(void);
+extern void __init pxa3xx_map_io(void);
 
 extern unsigned int get_clk_frequency_khz(int info);
 
@@ -32,18 +39,14 @@ extern unsigned int get_clk_frequency_kh
 
 #ifdef CONFIG_PXA25x
 extern unsigned pxa25x_get_clk_frequency_khz(int);
-extern unsigned pxa25x_get_memclk_frequency_10khz(void);
 #else
 #define pxa25x_get_clk_frequency_khz(x)		(0)
-#define pxa25x_get_memclk_frequency_10khz()	(0)
 #endif
 
 #ifdef CONFIG_PXA27x
 extern unsigned pxa27x_get_clk_frequency_khz(int);
-extern unsigned pxa27x_get_memclk_frequency_10khz(void);
 #else
 #define pxa27x_get_clk_frequency_khz(x)		(0)
-#define pxa27x_get_memclk_frequency_10khz()	(0)
 #endif
 
 #if defined(CONFIG_PXA25x) || defined(CONFIG_PXA27x)
@@ -54,10 +57,8 @@ static inline void pxa2xx_clear_reset_st
 
 #ifdef CONFIG_PXA3xx
 extern unsigned pxa3xx_get_clk_frequency_khz(int);
-extern void pxa3xx_clear_reset_status(unsigned int);
 #else
 #define pxa3xx_get_clk_frequency_khz(x)		(0)
-static inline void pxa3xx_clear_reset_status(unsigned int mask) {}
 #endif
 
 extern struct sysdev_class pxa_irq_sysclass;
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/gumstix.c linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/gumstix.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/gumstix.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/gumstix.c	2011-03-14 21:20:32.000000000 -0400
@@ -225,7 +225,7 @@ static void __init gumstix_init(void)
 
 MACHINE_START(GUMSTIX, "Gumstix")
 	.boot_params	= 0xa0000100, /* match u-boot bi_boot_params */
-	.map_io		= pxa_map_io,
+	.map_io		= pxa25x_map_io,
 	.init_irq	= pxa25x_init_irq,
 	.timer		= &pxa_timer,
 	.init_machine	= gumstix_init,
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/h5000.c linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/h5000.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/h5000.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/h5000.c	2011-03-14 21:20:32.000000000 -0400
@@ -32,6 +32,7 @@
 #include <mach/pxa25x.h>
 #include <mach/h5000.h>
 #include <mach/udc.h>
+#include <mach/smemc.h>
 
 #include "generic.h"
 
@@ -172,11 +173,11 @@ static unsigned long h5000_pin_config[]
 
 static void fix_msc(void)
 {
-	MSC0 = 0x129c24f2;
-	MSC1 = 0x7ff424fa;
-	MSC2 = 0x7ff47ff4;
+	__raw_writel(0x129c24f2, MSC0);
+	__raw_writel(0x7ff424fa, MSC1);
+	__raw_writel(0x7ff47ff4, MSC2);
 
-	MDREFR |= 0x02080000;
+	__raw_writel(__raw_readl(MDREFR) | 0x02080000, MDREFR);
 }
 
 /*
@@ -202,7 +203,7 @@ static void __init h5000_init(void)
 
 MACHINE_START(H5400, "HP iPAQ H5000")
 	.boot_params = 0xa0000100,
-	.map_io = pxa_map_io,
+	.map_io = pxa25x_map_io,
 	.init_irq = pxa25x_init_irq,
 	.timer = &pxa_timer,
 	.init_machine = h5000_init,
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/himalaya.c linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/himalaya.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/himalaya.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/himalaya.c	2011-03-14 21:20:32.000000000 -0400
@@ -160,7 +160,7 @@ static void __init himalaya_init(void)
 
 MACHINE_START(HIMALAYA, "HTC Himalaya")
 	.boot_params = 0xa0000100,
-	.map_io = pxa_map_io,
+	.map_io = pxa25x_map_io,
 	.init_irq = pxa25x_init_irq,
 	.init_machine = himalaya_init,
 	.timer = &pxa_timer,
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/hx4700.c linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/hx4700.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/hx4700.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/hx4700.c	2011-03-14 21:20:32.000000000 -0400
@@ -33,6 +33,7 @@
 #include <linux/regulator/max1586.h>
 #include <linux/spi/ads7846.h>
 #include <linux/spi/spi.h>
+#include <linux/spi/pxa2xx_spi.h>
 #include <linux/usb/gpio_vbus.h>
 
 #include <mach/hardware.h>
@@ -43,7 +44,6 @@
 #include <mach/hx4700.h>
 #include <plat/i2c.h>
 #include <mach/irda.h>
-#include <mach/pxa2xx_spi.h>
 
 #include <video/platform_lcd.h>
 #include <video/w100fb.h>
@@ -871,7 +871,7 @@ static void __init hx4700_init(void)
 
 MACHINE_START(H4700, "HP iPAQ HX4700")
 	.boot_params  = 0xa0000100,
-	.map_io       = pxa_map_io,
+	.map_io       = pxa27x_map_io,
 	.nr_irqs      = HX4700_NR_IRQS,
 	.init_irq     = pxa27x_init_irq,
 	.init_machine = hx4700_init,
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/icontrol.c linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/icontrol.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/icontrol.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/icontrol.c	2011-03-14 21:20:32.000000000 -0400
@@ -24,7 +24,7 @@
 #include <mach/mxm8x10.h>
 
 #include <linux/spi/spi.h>
-#include <mach/pxa2xx_spi.h>
+#include <linux/spi/pxa2xx_spi.h>
 #include <linux/can/platform/mcp251x.h>
 
 #include "generic.h"
@@ -192,7 +192,7 @@ static void __init icontrol_init(void)
 
 MACHINE_START(ICONTROL, "iControl/SafeTcam boards using Embedian MXM-8x10 CoM")
 	.boot_params	= 0xa0000100,
-	.map_io		= pxa_map_io,
+	.map_io		= pxa3xx_map_io,
 	.init_irq	= pxa3xx_init_irq,
 	.timer		= &pxa_timer,
 	.init_machine	= icontrol_init
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/idp.c linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/idp.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/idp.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/idp.c	2011-03-14 21:20:32.000000000 -0400
@@ -187,7 +187,7 @@ static struct map_desc idp_io_desc[] __i
 
 static void __init idp_map_io(void)
 {
-	pxa_map_io();
+	pxa25x_map_io();
 	iotable_init(idp_io_desc, ARRAY_SIZE(idp_io_desc));
 }
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/include/mach/addr-map.h linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/include/mach/addr-map.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/include/mach/addr-map.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/include/mach/addr-map.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,48 @@
+#ifndef __ASM_MACH_ADDR_MAP_H
+#define __ASM_MACH_ADDR_MAP_H
+
+/*
+ * Chip Selects
+ */
+#define PXA_CS0_PHYS		0x00000000
+#define PXA_CS1_PHYS		0x04000000
+#define PXA_CS2_PHYS		0x08000000
+#define PXA_CS3_PHYS		0x0C000000
+#define PXA_CS4_PHYS		0x10000000
+#define PXA_CS5_PHYS		0x14000000
+
+#define PXA300_CS0_PHYS		0x00000000	/* PXA300/PXA310 _only_ */
+#define PXA300_CS1_PHYS		0x30000000	/* PXA300/PXA310 _only_ */
+#define PXA3xx_CS2_PHYS		0x10000000
+#define PXA3xx_CS3_PHYS		0x14000000
+
+/*
+ * Peripheral Bus
+ */
+#define PERIPH_PHYS		0x40000000
+#define PERIPH_VIRT		0xf2000000
+#define PERIPH_SIZE		0x02000000
+
+/*
+ * Static Memory Controller (w/ SDRAM controls on PXA25x/PXA27x)
+ */
+#define PXA2XX_SMEMC_PHYS	0x48000000
+#define PXA3XX_SMEMC_PHYS	0x4a000000
+#define SMEMC_VIRT		0xf6000000
+#define SMEMC_SIZE		0x00100000
+
+/*
+ * Dynamic Memory Controller (only on PXA3xx)
+ */
+#define DMEMC_PHYS		0x48100000
+#define DMEMC_VIRT		0xf6100000
+#define DMEMC_SIZE		0x00100000
+
+/*
+ * Internal Memory Controller (PXA27x and later)
+ */
+#define IMEMC_PHYS		0x58000000
+#define IMEMC_VIRT		0xfe000000
+#define IMEMC_SIZE		0x00100000
+
+#endif /* __ASM_MACH_ADDR_MAP_H */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/include/mach/balloon3.h linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/include/mach/balloon3.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/include/mach/balloon3.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/include/mach/balloon3.h	2011-03-14 21:20:32.000000000 -0400
@@ -26,6 +26,8 @@ enum balloon3_features {
 #define BALLOON3_FPGA_VIRT	(0xf1000000)	/* as per balloon2 */
 #define BALLOON3_FPGA_LENGTH	0x01000000
 
+#define	BALLOON3_FPGA_SETnCLR		(0x1000)
+
 /* FPGA / CPLD registers for CF socket */
 #define	BALLOON3_CF_STATUS_REG		(BALLOON3_FPGA_VIRT + 0x00e00008)
 #define	BALLOON3_CF_CONTROL_REG		(BALLOON3_FPGA_VIRT + 0x00e00008)
@@ -35,7 +37,7 @@ enum balloon3_features {
 #define	BALLOON3_NAND_BASE		(PXA_CS4_PHYS + 0x00e00000)
 #define	BALLOON3_NAND_IO_REG		(BALLOON3_FPGA_VIRT + 0x00e00000)
 #define	BALLOON3_NAND_CONTROL2_REG	(BALLOON3_FPGA_VIRT + 0x00e00010)
-#define	BALLOON3_NAND_STAT_REG		(BALLOON3_FPGA_VIRT + 0x00e00010)
+#define	BALLOON3_NAND_STAT_REG		(BALLOON3_FPGA_VIRT + 0x00e00014)
 #define	BALLOON3_NAND_CONTROL_REG	(BALLOON3_FPGA_VIRT + 0x00e00014)
 
 /* fpga/cpld interrupt control register */
@@ -174,7 +176,7 @@ enum balloon3_features {
 #define BALLOON3_CODEC_IRQ	IRQ_GPIO(BALLOON3_GPIO_CODEC_IRQ)
 #define BALLOON3_S0_CD_IRQ	IRQ_GPIO(BALLOON3_GPIO_S0_CD)
 
-#define BALLOON3_NR_IRQS	(IRQ_BOARD_START + 4)
+#define BALLOON3_NR_IRQS	(IRQ_BOARD_START + 16)
 
 extern int balloon3_has(enum balloon3_features feature);
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/include/mach/colibri.h linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/include/mach/colibri.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/include/mach/colibri.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/include/mach/colibri.h	2011-03-14 21:20:32.000000000 -0400
@@ -9,14 +9,14 @@
  */
 
 enum {
-	COLIBRI_PXA270_EVALBOARD = 0,
+	COLIBRI_EVALBOARD = 0,
 	COLIBRI_PXA270_INCOME,
 };
 
-#if defined(CONFIG_MACH_COLIBRI_PXA270_EVALBOARD)
-extern void colibri_pxa270_evalboard_init(void);
+#if defined(CONFIG_MACH_COLIBRI_EVALBOARD)
+extern void colibri_evalboard_init(void);
 #else
-static inline void colibri_pxa270_evalboard_init(void) {}
+static inline void colibri_evalboard_init(void) {}
 #endif
 
 #if defined(CONFIG_MACH_COLIBRI_PXA270_INCOME)
@@ -59,5 +59,11 @@ static inline void colibri_pxa3xx_init_n
 #define GPIO0_COLIBRI_PXA270_SD_DETECT	0
 #define GPIO113_COLIBRI_PXA270_TS_IRQ	113
 
+/* GPIO definitions for Colibri PXA300/310 */
+#define GPIO13_COLIBRI_PXA300_SD_DETECT	13
+
+/* GPIO definitions for Colibri PXA320 */
+#define GPIO28_COLIBRI_PXA320_SD_DETECT	28
+
 #endif /* _COLIBRI_H_ */
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/include/mach/hardware.h linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/include/mach/hardware.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/include/mach/hardware.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/include/mach/hardware.h	2011-03-14 21:20:32.000000000 -0400
@@ -13,6 +13,8 @@
 #ifndef __ASM_ARCH_HARDWARE_H
 #define __ASM_ARCH_HARDWARE_H
 
+#include <mach/addr-map.h>
+
 /*
  * Workarounds for at least 2 errata so far require this.
  * The mapping is set in mach-pxa/generic.c.
@@ -193,14 +195,15 @@
 #define __cpu_is_pxa935(id)	(0)
 #endif
 
-#ifdef CONFIG_CPU_PXA950
-#define __cpu_is_pxa950(id)                             \
-	({                                              \
+#ifdef CONFIG_CPU_PXA955
+#define __cpu_is_pxa955(id)				\
+	({						\
 		unsigned int _id = (id) >> 4 & 0xfff;	\
-		_id == 0x697;				\
-	 })
+		_id == 0x581 || _id == 0xc08		\
+			|| _id == 0xb76;		\
+	})
 #else
-#define __cpu_is_pxa950(id)	(0)
+#define __cpu_is_pxa955(id)	(0)
 #endif
 
 #define cpu_is_pxa210()					\
@@ -253,16 +256,15 @@
 		__cpu_is_pxa935(read_cpuid_id());	\
 	 })
 
-#define cpu_is_pxa950()					\
+#define cpu_is_pxa955()					\
 	({						\
-		__cpu_is_pxa950(read_cpuid_id());	\
-	 })
+		__cpu_is_pxa955(read_cpuid_id());	\
+	})
 
 
 /*
  * CPUID Core Generation Bit
  * <= 0x2 for pxa21x/pxa25x/pxa26x/pxa27x
- * == 0x3 for pxa300/pxa310/pxa320
  */
 #if defined(CONFIG_PXA25x) || defined(CONFIG_PXA27x)
 #define __cpu_is_pxa2xx(id)				\
@@ -277,8 +279,10 @@
 #ifdef CONFIG_PXA3xx
 #define __cpu_is_pxa3xx(id)				\
 	({						\
-		unsigned int _id = (id) >> 13 & 0x7;	\
-		_id == 0x3;				\
+		__cpu_is_pxa300(id)			\
+			|| __cpu_is_pxa310(id)		\
+			|| __cpu_is_pxa320(id)		\
+			|| __cpu_is_pxa93x(id);		\
 	 })
 #else
 #define __cpu_is_pxa3xx(id)	(0)
@@ -287,13 +291,22 @@
 #if defined(CONFIG_CPU_PXA930) || defined(CONFIG_CPU_PXA935)
 #define __cpu_is_pxa93x(id)				\
 	({						\
-		unsigned int _id = (id) >> 4 & 0xfff;	\
-		_id == 0x683 || _id == 0x693;		\
+		__cpu_is_pxa930(id)			\
+			|| __cpu_is_pxa935(id);		\
 	 })
 #else
 #define __cpu_is_pxa93x(id)	(0)
 #endif
 
+#ifdef CONFIG_PXA95x
+#define __cpu_is_pxa95x(id)				\
+	({						\
+		__cpu_is_pxa955(id);			\
+	})
+#else
+#define __cpu_is_pxa95x(id)	(0)
+#endif
+
 #define cpu_is_pxa2xx()					\
 	({						\
 		__cpu_is_pxa2xx(read_cpuid_id());	\
@@ -308,6 +321,12 @@
 	({						\
 		__cpu_is_pxa93x(read_cpuid_id());	\
 	 })
+
+#define cpu_is_pxa95x()					\
+	({						\
+		__cpu_is_pxa95x(read_cpuid_id());	\
+	})
+
 /*
  * return current memory and LCD clock frequency in units of 10kHz
  */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/include/mach/irqs.h linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/include/mach/irqs.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/include/mach/irqs.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/include/mach/irqs.h	2011-03-14 21:20:32.000000000 -0400
@@ -21,16 +21,14 @@
 
 #define PXA_IRQ(x)	(PXA_ISA_IRQ_NUM + (x))
 
-#if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx)
 #define IRQ_SSP3	PXA_IRQ(0)	/* SSP3 service request */
 #define IRQ_MSL		PXA_IRQ(1)	/* MSL Interface interrupt */
-#define IRQ_USBH2	PXA_IRQ(2)	/* USB Host interrupt 1 (OHCI) */
-#define IRQ_USBH1	PXA_IRQ(3)	/* USB Host interrupt 2 (non-OHCI) */
+#define IRQ_USBH2	PXA_IRQ(2)	/* USB Host interrupt 1 (OHCI,PXA27x) */
+#define IRQ_USBH1	PXA_IRQ(3)	/* USB Host interrupt 2 (non-OHCI,PXA27x) */
 #define IRQ_KEYPAD	PXA_IRQ(4)	/* Key pad controller */
-#define IRQ_MEMSTK	PXA_IRQ(5)	/* Memory Stick interrupt */
+#define IRQ_MEMSTK	PXA_IRQ(5)	/* Memory Stick interrupt (PXA27x) */
+#define IRQ_ACIPC0	PXA_IRQ(5)	/* AP-CP Communication (PXA930) */
 #define IRQ_PWRI2C	PXA_IRQ(6)	/* Power I2C interrupt */
-#endif
-
 #define IRQ_HWUART	PXA_IRQ(7)	/* HWUART Transmit/Receive/Error (PXA26x) */
 #define IRQ_OST_4_11	PXA_IRQ(7)	/* OS timer 4-11 matches (PXA27x) */
 #define	IRQ_GPIO0	PXA_IRQ(8)	/* GPIO0 Edge Detect */
@@ -38,7 +36,8 @@
 #define	IRQ_GPIO_2_x	PXA_IRQ(10)	/* GPIO[2-x] Edge Detect */
 #define	IRQ_USB		PXA_IRQ(11)	/* USB Service */
 #define	IRQ_PMU		PXA_IRQ(12)	/* Performance Monitoring Unit */
-#define	IRQ_I2S		PXA_IRQ(13)	/* I2S Interrupt */
+#define	IRQ_I2S		PXA_IRQ(13)	/* I2S Interrupt (PXA27x) */
+#define IRQ_SSP4	PXA_IRQ(13)	/* SSP4 service request (PXA3xx) */
 #define	IRQ_AC97	PXA_IRQ(14)	/* AC97 Interrupt */
 #define IRQ_ASSP	PXA_IRQ(15)	/* Audio SSP Service Request (PXA25x) */
 #define IRQ_USIM	PXA_IRQ(15)     /* Smart Card interface interrupt (PXA27x) */
@@ -47,6 +46,7 @@
 #define	IRQ_LCD		PXA_IRQ(17)	/* LCD Controller Service Request */
 #define	IRQ_I2C		PXA_IRQ(18)	/* I2C Service Request */
 #define	IRQ_ICP		PXA_IRQ(19)	/* ICP Transmit/Receive/Error */
+#define IRQ_ACIPC2	PXA_IRQ(19)	/* AP-CP Communication (PXA930) */
 #define	IRQ_STUART	PXA_IRQ(20)	/* STUART Transmit/Receive/Error */
 #define	IRQ_BTUART	PXA_IRQ(21)	/* BTUART Transmit/Receive/Error */
 #define	IRQ_FFUART	PXA_IRQ(22)	/* FFUART Transmit/Receive/Error*/
@@ -60,19 +60,17 @@
 #define	IRQ_RTC1Hz	PXA_IRQ(30)	/* RTC HZ Clock Tick */
 #define	IRQ_RTCAlrm	PXA_IRQ(31)	/* RTC Alarm */
 
-#if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx)
 #define IRQ_TPM		PXA_IRQ(32)	/* TPM interrupt */
 #define IRQ_CAMERA	PXA_IRQ(33)	/* Camera Interface */
-#endif
-
-#ifdef CONFIG_PXA3xx
-#define IRQ_SSP4	PXA_IRQ(13)	/* SSP4 service request */
 #define IRQ_CIR		PXA_IRQ(34)	/* Consumer IR */
 #define IRQ_COMM_WDT	PXA_IRQ(35) 	/* Comm WDT interrupt */
 #define IRQ_TSI		PXA_IRQ(36)	/* Touch Screen Interface (PXA320) */
+#define IRQ_ENHROT	PXA_IRQ(37)	/* Enhanced Rotary (PXA930) */
 #define IRQ_USIM2	PXA_IRQ(38)	/* USIM2 Controller */
-#define IRQ_GCU		PXA_IRQ(39)	/* Graphics Controller */
+#define IRQ_GCU		PXA_IRQ(39)	/* Graphics Controller (PXA3xx) */
+#define IRQ_ACIPC1	PXA_IRQ(40)	/* AP-CP Communication (PXA930) */
 #define IRQ_MMC2	PXA_IRQ(41)	/* MMC2 Controller */
+#define IRQ_TRKBALL	PXA_IRQ(43)	/* Track Ball (PXA930) */
 #define IRQ_1WIRE	PXA_IRQ(44)	/* 1-Wire Controller */
 #define IRQ_NAND	PXA_IRQ(45)	/* NAND Controller */
 #define IRQ_USB2	PXA_IRQ(46)	/* USB 2.0 Device Controller */
@@ -80,30 +78,14 @@
 #define IRQ_WAKEUP1	PXA_IRQ(50)	/* EXT_WAKEUP1 */
 #define IRQ_DMEMC	PXA_IRQ(51)	/* Dynamic Memory Controller */
 #define IRQ_MMC3	PXA_IRQ(55)	/* MMC3 Controller (PXA310) */
-#endif
 
-#ifdef CONFIG_CPU_PXA935
 #define IRQ_U2O		PXA_IRQ(64)	/* USB OTG 2.0 Controller (PXA935) */
 #define IRQ_U2H		PXA_IRQ(65)	/* USB Host 2.0 Controller (PXA935) */
-
-#define IRQ_MMC3_PXA935	PXA_IRQ(72)	/* MMC3 Controller (PXA935) */
-#define IRQ_MMC4_PXA935	PXA_IRQ(73)	/* MMC4 Controller (PXA935) */
-#define IRQ_MMC5_PXA935	PXA_IRQ(74)	/* MMC5 Controller (PXA935) */
-
+#define IRQ_PXA935_MMC0	PXA_IRQ(72)	/* MMC0 Controller (PXA935) */
+#define IRQ_PXA935_MMC1	PXA_IRQ(73)	/* MMC1 Controller (PXA935) */
+#define IRQ_PXA935_MMC2	PXA_IRQ(74)	/* MMC2 Controller (PXA935) */
+#define IRQ_PXA955_MMC3	PXA_IRQ(75)	/* MMC3 Controller (PXA955) */
 #define IRQ_U2P		PXA_IRQ(93)	/* USB PHY D+/D- Lines (PXA935) */
-#endif
-
-#ifdef CONFIG_CPU_PXA930
-#define IRQ_ENHROT	PXA_IRQ(37)	/* Enhanced Rotary (PXA930) */
-#define IRQ_ACIPC0	PXA_IRQ(5)
-#define IRQ_ACIPC1	PXA_IRQ(40)
-#define IRQ_ACIPC2	PXA_IRQ(19)
-#define IRQ_TRKBALL	PXA_IRQ(43)	/* Track Ball */
-#endif
-
-#ifdef CONFIG_CPU_PXA950
-#define IRQ_GC500	PXA_IRQ(70)	/* Graphics Controller (PXA950) */
-#endif
 
 #define PXA_GPIO_IRQ_BASE	PXA_IRQ(96)
 #define PXA_GPIO_IRQ_NUM	(192)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/include/mach/pxa2xx-regs.h linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/include/mach/pxa2xx-regs.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/include/mach/pxa2xx-regs.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/include/mach/pxa2xx-regs.h	2011-03-14 21:20:32.000000000 -0400
@@ -17,72 +17,6 @@
 #include <mach/hardware.h>
 
 /*
- * PXA Chip selects
- */
-
-#define PXA_CS0_PHYS	0x00000000
-#define PXA_CS1_PHYS	0x04000000
-#define PXA_CS2_PHYS	0x08000000
-#define PXA_CS3_PHYS	0x0C000000
-#define PXA_CS4_PHYS	0x10000000
-#define PXA_CS5_PHYS	0x14000000
-
-/*
- * Memory controller
- */
-
-#define MDCNFG		__REG(0x48000000)  /* SDRAM Configuration Register 0 */
-#define MDREFR		__REG(0x48000004)  /* SDRAM Refresh Control Register */
-#define MSC0		__REG(0x48000008)  /* Static Memory Control Register 0 */
-#define MSC1		__REG(0x4800000C)  /* Static Memory Control Register 1 */
-#define MSC2		__REG(0x48000010)  /* Static Memory Control Register 2 */
-#define MECR		__REG(0x48000014)  /* Expansion Memory (PCMCIA/Compact Flash) Bus Configuration */
-#define SXLCR		__REG(0x48000018)  /* LCR value to be written to SDRAM-Timing Synchronous Flash */
-#define SXCNFG		__REG(0x4800001C)  /* Synchronous Static Memory Control Register */
-#define SXMRS		__REG(0x48000024)  /* MRS value to be written to Synchronous Flash or SMROM */
-#define MCMEM0		__REG(0x48000028)  /* Card interface Common Memory Space Socket 0 Timing */
-#define MCMEM1		__REG(0x4800002C)  /* Card interface Common Memory Space Socket 1 Timing */
-#define MCATT0		__REG(0x48000030)  /* Card interface Attribute Space Socket 0 Timing Configuration */
-#define MCATT1		__REG(0x48000034)  /* Card interface Attribute Space Socket 1 Timing Configuration */
-#define MCIO0		__REG(0x48000038)  /* Card interface I/O Space Socket 0 Timing Configuration */
-#define MCIO1		__REG(0x4800003C)  /* Card interface I/O Space Socket 1 Timing Configuration */
-#define MDMRS		__REG(0x48000040)  /* MRS value to be written to SDRAM */
-#define BOOT_DEF	__REG(0x48000044)  /* Read-Only Boot-Time Register. Contains BOOT_SEL and PKG_SEL */
-
-/*
- * More handy macros for PCMCIA
- *
- * Arg is socket number
- */
-#define MCMEM(s)	__REG2(0x48000028, (s)<<2 )  /* Card interface Common Memory Space Socket s Timing */
-#define MCATT(s)	__REG2(0x48000030, (s)<<2 )  /* Card interface Attribute Space Socket s Timing Configuration */
-#define MCIO(s)		__REG2(0x48000038, (s)<<2 )  /* Card interface I/O Space Socket s Timing Configuration */
-
-/* MECR register defines */
-#define MECR_NOS	(1 << 0)	/* Number Of Sockets: 0 -> 1 sock, 1 -> 2 sock */
-#define MECR_CIT	(1 << 1)	/* Card Is There: 0 -> no card, 1 -> card inserted */
-
-#define MDCNFG_DE0	(1 << 0)	/* SDRAM Bank 0 Enable */
-#define MDCNFG_DE1	(1 << 1)	/* SDRAM Bank 1 Enable */
-#define MDCNFG_DE2	(1 << 16)	/* SDRAM Bank 2 Enable */
-#define MDCNFG_DE3	(1 << 17)	/* SDRAM Bank 3 Enable */
-
-#define MDREFR_K0DB4	(1 << 29)	/* SDCLK0 Divide by 4 Control/Status */
-#define MDREFR_K2FREE	(1 << 25)	/* SDRAM Free-Running Control */
-#define MDREFR_K1FREE	(1 << 24)	/* SDRAM Free-Running Control */
-#define MDREFR_K0FREE	(1 << 23)	/* SDRAM Free-Running Control */
-#define MDREFR_SLFRSH	(1 << 22)	/* SDRAM Self-Refresh Control/Status */
-#define MDREFR_APD	(1 << 20)	/* SDRAM/SSRAM Auto-Power-Down Enable */
-#define MDREFR_K2DB2	(1 << 19)	/* SDCLK2 Divide by 2 Control/Status */
-#define MDREFR_K2RUN	(1 << 18)	/* SDCLK2 Run Control/Status */
-#define MDREFR_K1DB2	(1 << 17)	/* SDCLK1 Divide by 2 Control/Status */
-#define MDREFR_K1RUN	(1 << 16)	/* SDCLK1 Run Control/Status */
-#define MDREFR_E1PIN	(1 << 15)	/* SDCKE1 Level Control/Status */
-#define MDREFR_K0DB2	(1 << 14)	/* SDCLK0 Divide by 2 Control/Status */
-#define MDREFR_K0RUN	(1 << 13)	/* SDCLK0 Run Control/Status */
-#define MDREFR_E0PIN	(1 << 12)	/* SDCKE0 Level Control/Status */
-
-/*
  * Power Manager
  */
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/include/mach/pxa2xx_spi.h linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/include/mach/pxa2xx_spi.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/include/mach/pxa2xx_spi.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/include/mach/pxa2xx_spi.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2005 Stephen Street / StreetFire Sound Labs
- *
- * 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 PXA2XX_SPI_H_
-#define PXA2XX_SPI_H_
-
-#define PXA2XX_CS_ASSERT (0x01)
-#define PXA2XX_CS_DEASSERT (0x02)
-
-/* device.platform_data for SSP controller devices */
-struct pxa2xx_spi_master {
-	u32 clock_enable;
-	u16 num_chipselect;
-	u8 enable_dma;
-};
-
-/* spi_board_info.controller_data for SPI slave devices,
- * copied to spi_device.platform_data ... mostly for dma tuning
- */
-struct pxa2xx_spi_chip {
-	u8 tx_threshold;
-	u8 rx_threshold;
-	u8 dma_burst_size;
-	u32 timeout;
-	u8 enable_loopback;
-	int gpio_cs;
-	void (*cs_control)(u32 command);
-};
-
-extern void pxa2xx_set_spi_info(unsigned id, struct pxa2xx_spi_master *info);
-
-#endif /*PXA2XX_SPI_H_*/
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/include/mach/pxa3xx-regs.h linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/include/mach/pxa3xx-regs.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/include/mach/pxa3xx-regs.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/include/mach/pxa3xx-regs.h	2011-03-14 21:20:32.000000000 -0400
@@ -16,15 +16,6 @@
 #include <mach/hardware.h>
 
 /*
- * Static Chip Selects
- */
-
-#define PXA300_CS0_PHYS		(0x00000000)	/* PXA300/PXA310 _only_ */
-#define PXA300_CS1_PHYS		(0x30000000)	/* PXA300/PXA310 _only_ */
-#define PXA3xx_CS2_PHYS		(0x10000000)
-#define PXA3xx_CS3_PHYS		(0x14000000)
-
-/*
  * Oscillator Configuration Register (OSCC)
  */
 #define OSCC           __REG(0x41350000)  /* Oscillator Configuration Register */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/include/mach/regs-intc.h linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/include/mach/regs-intc.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/include/mach/regs-intc.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/include/mach/regs-intc.h	2011-03-14 21:20:32.000000000 -0400
@@ -27,8 +27,4 @@
 #define ICFP3		__REG(0x40D0013C)  /* Interrupt Controller FIQ Pending Register 3 */
 #define ICPR3		__REG(0x40D00140)  /* Interrupt Controller Pending Register 3 */
 
-#define IPR(x)		__REG(0x40D0001C + (x < 32 ? (x << 2)		\
-				: (x < 64 ? (0x94 + ((x - 32) << 2))	\
-				: (0x128 + ((x - 64) << 2)))))
-
 #endif /* __ASM_MACH_REGS_INTC_H */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/include/mach/smemc.h linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/include/mach/smemc.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/include/mach/smemc.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/include/mach/smemc.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,74 @@
+/*
+ * Static memory controller register definitions for PXA CPUs
+ *
+ * Copyright (C) 2010 Marek Vasut <marek.vasut@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.
+ */
+
+#ifndef __SMEMC_REGS_H
+#define __SMEMC_REGS_H
+
+#define PXA2XX_SMEMC_BASE	0x48000000
+#define PXA3XX_SMEMC_BASE	0x4a000000
+#define SMEMC_VIRT		0xf6000000
+
+#define MDCNFG		(SMEMC_VIRT + 0x00)  /* SDRAM Configuration Register 0 */
+#define MDREFR		(SMEMC_VIRT + 0x04)  /* SDRAM Refresh Control Register */
+#define MSC0		(SMEMC_VIRT + 0x08)  /* Static Memory Control Register 0 */
+#define MSC1		(SMEMC_VIRT + 0x0C)  /* Static Memory Control Register 1 */
+#define MSC2		(SMEMC_VIRT + 0x10)  /* Static Memory Control Register 2 */
+#define MECR		(SMEMC_VIRT + 0x14)  /* Expansion Memory (PCMCIA/Compact Flash) Bus Configuration */
+#define SXLCR		(SMEMC_VIRT + 0x18)  /* LCR value to be written to SDRAM-Timing Synchronous Flash */
+#define SXCNFG		(SMEMC_VIRT + 0x1C)  /* Synchronous Static Memory Control Register */
+#define SXMRS		(SMEMC_VIRT + 0x24)  /* MRS value to be written to Synchronous Flash or SMROM */
+#define MCMEM0		(SMEMC_VIRT + 0x28)  /* Card interface Common Memory Space Socket 0 Timing */
+#define MCMEM1		(SMEMC_VIRT + 0x2C)  /* Card interface Common Memory Space Socket 1 Timing */
+#define MCATT0		(SMEMC_VIRT + 0x30)  /* Card interface Attribute Space Socket 0 Timing Configuration */
+#define MCATT1		(SMEMC_VIRT + 0x34)  /* Card interface Attribute Space Socket 1 Timing Configuration */
+#define MCIO0		(SMEMC_VIRT + 0x38)  /* Card interface I/O Space Socket 0 Timing Configuration */
+#define MCIO1		(SMEMC_VIRT + 0x3C)  /* Card interface I/O Space Socket 1 Timing Configuration */
+#define MDMRS		(SMEMC_VIRT + 0x40)  /* MRS value to be written to SDRAM */
+#define BOOT_DEF	(SMEMC_VIRT + 0x44)  /* Read-Only Boot-Time Register. Contains BOOT_SEL and PKG_SEL */
+#define MEMCLKCFG	(SMEMC_VIRT + 0x68)  /* Clock Configuration */
+#define CSADRCFG0	(SMEMC_VIRT + 0x80)  /* Address Configuration Register for CS0 */
+#define CSADRCFG1	(SMEMC_VIRT + 0x84)  /* Address Configuration Register for CS1 */
+#define CSADRCFG2	(SMEMC_VIRT + 0x88)  /* Address Configuration Register for CS2 */
+#define CSADRCFG3	(SMEMC_VIRT + 0x8C)  /* Address Configuration Register for CS3 */
+
+/*
+ * More handy macros for PCMCIA
+ *
+ * Arg is socket number
+ */
+#define MCMEM(s)	(SMEMC_VIRT + 0x28 + ((s)<<2))  /* Card interface Common Memory Space Socket s Timing */
+#define MCATT(s)	(SMEMC_VIRT + 0x30 + ((s)<<2))  /* Card interface Attribute Space Socket s Timing Configuration */
+#define MCIO(s)		(SMEMC_VIRT + 0x38 + ((s)<<2))  /* Card interface I/O Space Socket s Timing Configuration */
+
+/* MECR register defines */
+#define MECR_NOS	(1 << 0)	/* Number Of Sockets: 0 -> 1 sock, 1 -> 2 sock */
+#define MECR_CIT	(1 << 1)	/* Card Is There: 0 -> no card, 1 -> card inserted */
+
+#define MDCNFG_DE0	(1 << 0)	/* SDRAM Bank 0 Enable */
+#define MDCNFG_DE1	(1 << 1)	/* SDRAM Bank 1 Enable */
+#define MDCNFG_DE2	(1 << 16)	/* SDRAM Bank 2 Enable */
+#define MDCNFG_DE3	(1 << 17)	/* SDRAM Bank 3 Enable */
+
+#define MDREFR_K0DB4	(1 << 29)	/* SDCLK0 Divide by 4 Control/Status */
+#define MDREFR_K2FREE	(1 << 25)	/* SDRAM Free-Running Control */
+#define MDREFR_K1FREE	(1 << 24)	/* SDRAM Free-Running Control */
+#define MDREFR_K0FREE	(1 << 23)	/* SDRAM Free-Running Control */
+#define MDREFR_SLFRSH	(1 << 22)	/* SDRAM Self-Refresh Control/Status */
+#define MDREFR_APD	(1 << 20)	/* SDRAM/SSRAM Auto-Power-Down Enable */
+#define MDREFR_K2DB2	(1 << 19)	/* SDCLK2 Divide by 2 Control/Status */
+#define MDREFR_K2RUN	(1 << 18)	/* SDCLK2 Run Control/Status */
+#define MDREFR_K1DB2	(1 << 17)	/* SDCLK1 Divide by 2 Control/Status */
+#define MDREFR_K1RUN	(1 << 16)	/* SDCLK1 Run Control/Status */
+#define MDREFR_E1PIN	(1 << 15)	/* SDCKE1 Level Control/Status */
+#define MDREFR_K0DB2	(1 << 14)	/* SDCLK0 Divide by 2 Control/Status */
+#define MDREFR_K0RUN	(1 << 13)	/* SDCLK0 Run Control/Status */
+#define MDREFR_E0PIN	(1 << 12)	/* SDCKE0 Level Control/Status */
+
+#endif
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/irq.c linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/irq.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/irq.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/irq.c	2011-03-14 21:20:32.000000000 -0400
@@ -16,20 +16,31 @@
 #include <linux/module.h>
 #include <linux/interrupt.h>
 #include <linux/sysdev.h>
+#include <linux/io.h>
+#include <linux/irq.h>
 
 #include <mach/hardware.h>
-#include <asm/irq.h>
-#include <asm/mach/irq.h>
+#include <mach/irqs.h>
 #include <mach/gpio.h>
-#include <mach/regs-intc.h>
 
 #include "generic.h"
 
-#define MAX_INTERNAL_IRQS	128
+#define IRQ_BASE		(void __iomem *)io_p2v(0x40d00000)
 
-#define IRQ_BIT(n)	(((n) - PXA_IRQ(0)) & 0x1f)
-#define _ICMR(n)	(*((((n) - PXA_IRQ(0)) & ~0x1f) ? &ICMR2 : &ICMR))
-#define _ICLR(n)	(*((((n) - PXA_IRQ(0)) & ~0x1f) ? &ICLR2 : &ICLR))
+#define ICIP			(0x000)
+#define ICMR			(0x004)
+#define ICLR			(0x008)
+#define ICFR			(0x00c)
+#define ICPR			(0x010)
+#define ICCR			(0x014)
+#define ICHP			(0x018)
+#define IPR(i)			(((i) < 32) ? (0x01c + ((i) << 2)) :		\
+				((i) < 64) ? (0x0b0 + (((i) - 32) << 2)) :	\
+				      (0x144 + (((i) - 64) << 2)))
+#define IPR_VALID		(1 << 31)
+#define IRQ_BIT(n)		(((n) - PXA_IRQ(0)) & 0x1f)
+
+#define MAX_INTERNAL_IRQS	128
 
 /*
  * This is for peripheral IRQs internal to the PXA chip.
@@ -37,29 +48,53 @@
 
 static int pxa_internal_irq_nr;
 
-static void pxa_mask_irq(unsigned int irq)
+static inline int cpu_has_ipr(void)
 {
-	_ICMR(irq) &= ~(1 << IRQ_BIT(irq));
+	return !cpu_is_pxa25x();
 }
 
-static void pxa_unmask_irq(unsigned int irq)
+static inline void __iomem *irq_base(int i)
 {
-	_ICMR(irq) |= 1 << IRQ_BIT(irq);
+	static unsigned long phys_base[] = {
+		0x40d00000,
+		0x40d0009c,
+		0x40d00130,
+	};
+
+	return (void __iomem *)io_p2v(phys_base[i]);
+}
+
+static void pxa_mask_irq(struct irq_data *d)
+{
+	void __iomem *base = irq_data_get_irq_chip_data(d);
+	uint32_t icmr = __raw_readl(base + ICMR);
+
+	icmr &= ~(1 << IRQ_BIT(d->irq));
+	__raw_writel(icmr, base + ICMR);
+}
+
+static void pxa_unmask_irq(struct irq_data *d)
+{
+	void __iomem *base = irq_data_get_irq_chip_data(d);
+	uint32_t icmr = __raw_readl(base + ICMR);
+
+	icmr |= 1 << IRQ_BIT(d->irq);
+	__raw_writel(icmr, base + ICMR);
 }
 
 static struct irq_chip pxa_internal_irq_chip = {
 	.name		= "SC",
-	.ack		= pxa_mask_irq,
-	.mask		= pxa_mask_irq,
-	.unmask		= pxa_unmask_irq,
+	.irq_ack	= pxa_mask_irq,
+	.irq_mask	= pxa_mask_irq,
+	.irq_unmask	= pxa_unmask_irq,
 };
 
 /*
  * GPIO IRQs for GPIO 0 and 1
  */
-static int pxa_set_low_gpio_type(unsigned int irq, unsigned int type)
+static int pxa_set_low_gpio_type(struct irq_data *d, unsigned int type)
 {
-	int gpio = irq - IRQ_GPIO0;
+	int gpio = d->irq - IRQ_GPIO0;
 
 	if (__gpio_is_occupied(gpio)) {
 		pr_err("%s failed: GPIO is configured\n", __func__);
@@ -79,27 +114,17 @@ static int pxa_set_low_gpio_type(unsigne
 	return 0;
 }
 
-static void pxa_ack_low_gpio(unsigned int irq)
-{
-	GEDR0 = (1 << (irq - IRQ_GPIO0));
-}
-
-static void pxa_mask_low_gpio(unsigned int irq)
-{
-	ICMR &= ~(1 << (irq - PXA_IRQ(0)));
-}
-
-static void pxa_unmask_low_gpio(unsigned int irq)
+static void pxa_ack_low_gpio(struct irq_data *d)
 {
-	ICMR |= 1 << (irq - PXA_IRQ(0));
+	GEDR0 = (1 << (d->irq - IRQ_GPIO0));
 }
 
 static struct irq_chip pxa_low_gpio_chip = {
 	.name		= "GPIO-l",
-	.ack		= pxa_ack_low_gpio,
-	.mask		= pxa_mask_low_gpio,
-	.unmask		= pxa_unmask_low_gpio,
-	.set_type	= pxa_set_low_gpio_type,
+	.irq_ack	= pxa_ack_low_gpio,
+	.irq_mask	= pxa_mask_irq,
+	.irq_unmask	= pxa_unmask_irq,
+	.irq_set_type	= pxa_set_low_gpio_type,
 };
 
 static void __init pxa_init_low_gpio_irq(set_wake_t fn)
@@ -113,42 +138,44 @@ static void __init pxa_init_low_gpio_irq
 
 	for (irq = IRQ_GPIO0; irq <= IRQ_GPIO1; irq++) {
 		set_irq_chip(irq, &pxa_low_gpio_chip);
+		set_irq_chip_data(irq, irq_base(0));
 		set_irq_handler(irq, handle_edge_irq);
 		set_irq_flags(irq, IRQF_VALID);
 	}
 
-	pxa_low_gpio_chip.set_wake = fn;
+	pxa_low_gpio_chip.irq_set_wake = fn;
 }
 
 void __init pxa_init_irq(int irq_nr, set_wake_t fn)
 {
-	int irq, i;
+	int irq, i, n;
 
 	BUG_ON(irq_nr > MAX_INTERNAL_IRQS);
 
 	pxa_internal_irq_nr = irq_nr;
 
-	for (irq = PXA_IRQ(0); irq < PXA_IRQ(irq_nr); irq += 32) {
-		_ICMR(irq) = 0;	/* disable all IRQs */
-		_ICLR(irq) = 0;	/* all IRQs are IRQ, not FIQ */
-	}
+	for (n = 0; n < irq_nr; n += 32) {
+		void __iomem *base = irq_base(n >> 5);
 
-	/* initialize interrupt priority */
-	if (cpu_is_pxa27x() || cpu_is_pxa3xx()) {
-		for (i = 0; i < irq_nr; i++)
-			IPR(i) = i | (1 << 31);
+		__raw_writel(0, base + ICMR);	/* disable all IRQs */
+		__raw_writel(0, base + ICLR);	/* all IRQs are IRQ, not FIQ */
+		for (i = n; (i < (n + 32)) && (i < irq_nr); i++) {
+			/* initialize interrupt priority */
+			if (cpu_has_ipr())
+				__raw_writel(i | IPR_VALID, IRQ_BASE + IPR(i));
+
+			irq = PXA_IRQ(i);
+			set_irq_chip(irq, &pxa_internal_irq_chip);
+			set_irq_chip_data(irq, base);
+			set_irq_handler(irq, handle_level_irq);
+			set_irq_flags(irq, IRQF_VALID);
+		}
 	}
 
 	/* only unmasked interrupts kick us out of idle */
-	ICCR = 1;
-
-	for (irq = PXA_IRQ(0); irq < PXA_IRQ(irq_nr); irq++) {
-		set_irq_chip(irq, &pxa_internal_irq_chip);
-		set_irq_handler(irq, handle_level_irq);
-		set_irq_flags(irq, IRQF_VALID);
-	}
+	__raw_writel(1, irq_base(0) + ICCR);
 
-	pxa_internal_irq_chip.set_wake = fn;
+	pxa_internal_irq_chip.irq_set_wake = fn;
 	pxa_init_low_gpio_irq(fn);
 }
 
@@ -158,16 +185,18 @@ static unsigned long saved_ipr[MAX_INTER
 
 static int pxa_irq_suspend(struct sys_device *dev, pm_message_t state)
 {
-	int i, irq = PXA_IRQ(0);
+	int i;
 
-	for (i = 0; irq < PXA_IRQ(pxa_internal_irq_nr); i++, irq += 32) {
-		saved_icmr[i] = _ICMR(irq);
-		_ICMR(irq) = 0;
+	for (i = 0; i < pxa_internal_irq_nr / 32; i++) {
+		void __iomem *base = irq_base(i);
+
+		saved_icmr[i] = __raw_readl(base + ICMR);
+		__raw_writel(0, base + ICMR);
 	}
 
-	if (cpu_is_pxa27x() || cpu_is_pxa3xx()) {
+	if (cpu_has_ipr()) {
 		for (i = 0; i < pxa_internal_irq_nr; i++)
-			saved_ipr[i] = IPR(i);
+			saved_ipr[i] = __raw_readl(IRQ_BASE + IPR(i));
 	}
 
 	return 0;
@@ -175,19 +204,20 @@ static int pxa_irq_suspend(struct sys_de
 
 static int pxa_irq_resume(struct sys_device *dev)
 {
-	int i, irq = PXA_IRQ(0);
+	int i;
 
-	if (cpu_is_pxa27x() || cpu_is_pxa3xx()) {
-		for (i = 0; i < pxa_internal_irq_nr; i++)
-			IPR(i) = saved_ipr[i];
-	}
+	for (i = 0; i < pxa_internal_irq_nr / 32; i++) {
+		void __iomem *base = irq_base(i);
 
-	for (i = 0; irq < PXA_IRQ(pxa_internal_irq_nr); i++, irq += 32) {
-		_ICMR(irq) = saved_icmr[i];
-		_ICLR(irq) = 0;
+		__raw_writel(saved_icmr[i], base + ICMR);
+		__raw_writel(0, base + ICLR);
 	}
 
-	ICCR = 1;
+	if (cpu_has_ipr())
+		for (i = 0; i < pxa_internal_irq_nr; i++)
+			__raw_writel(saved_ipr[i], IRQ_BASE + IPR(i));
+
+	__raw_writel(1, IRQ_BASE + ICCR);
 	return 0;
 }
 #else
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/Kconfig linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/Kconfig
--- linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -50,6 +50,10 @@ config MACH_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
@@ -94,6 +98,7 @@ config MACH_ARMCORE
 	select PXA27x
 	select IWMMXT
 	select PXA25x
+	select MIGHT_HAVE_PCI
 
 config MACH_EM_X270
 	bool "CompuLab EM-x270 platform"
@@ -232,10 +237,6 @@ config MACH_COLIBRI
 	bool "Toradex Colibri PXA270"
 	select PXA27x
 
-config MACH_COLIBRI_PXA270_EVALBOARD
-	bool "Toradex Colibri Evaluation Carrier Board support (PXA270)"
-	depends on MACH_COLIBRI
-
 config MACH_COLIBRI_PXA270_INCOME
 	bool "Income s.r.o. PXA270 SBC"
 	depends on MACH_COLIBRI
@@ -253,6 +254,10 @@ config MACH_COLIBRI320
 	select PXA3xx
 	select CPU_PXA320
 
+config MACH_COLIBRI_EVALBOARD
+	bool "Toradex Colibri Evaluation Carrier Board support"
+	depends on MACH_COLIBRI || MACH_COLIBRI300 || MACH_COLIBRI320
+
 config MACH_VPAC270
 	bool "Voipac PXA270"
 	select PXA27x
@@ -652,11 +657,17 @@ config CPU_PXA935
 	help
 	  PXA935 (codename Tavor-P65)
 
-config CPU_PXA950
+config PXA95x
 	bool
-	select CPU_PXA930
+	select CPU_PJ4
 	help
-	  PXA950 (codename Tavor-PV2)
+	  Select code specific to PXA95x variants
+
+config CPU_PXA955
+	bool
+	select PXA95x
+	help
+	  PXA950 (codename MG1)
 
 config PXA_SHARP_C7xx
 	bool
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/littleton.c linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/littleton.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/littleton.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/littleton.c	2011-03-14 21:20:32.000000000 -0400
@@ -22,6 +22,7 @@
 #include <linux/clk.h>
 #include <linux/gpio.h>
 #include <linux/spi/spi.h>
+#include <linux/spi/pxa2xx_spi.h>
 #include <linux/smc91x.h>
 #include <linux/i2c.h>
 #include <linux/leds.h>
@@ -42,7 +43,6 @@
 #include <mach/pxa300.h>
 #include <mach/pxafb.h>
 #include <mach/mmc.h>
-#include <mach/pxa2xx_spi.h>
 #include <plat/pxa27x_keypad.h>
 #include <mach/littleton.h>
 #include <plat/i2c.h>
@@ -438,7 +438,7 @@ static void __init littleton_init(void)
 
 MACHINE_START(LITTLETON, "Marvell Form Factor Development Platform (aka Littleton)")
 	.boot_params	= 0xa0000100,
-	.map_io		= pxa_map_io,
+	.map_io		= pxa3xx_map_io,
 	.nr_irqs	= LITTLETON_NR_IRQS,
 	.init_irq	= pxa3xx_init_irq,
 	.timer		= &pxa_timer,
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/lpd270.c linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/lpd270.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/lpd270.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/lpd270.c	2011-03-14 21:20:32.000000000 -0400
@@ -46,6 +46,7 @@
 #include <mach/mmc.h>
 #include <mach/irda.h>
 #include <mach/ohci.h>
+#include <mach/smemc.h>
 
 #include "generic.h"
 #include "devices.h"
@@ -94,9 +95,9 @@ static unsigned long lpd270_pin_config[]
 
 static unsigned int lpd270_irq_enabled;
 
-static void lpd270_mask_irq(unsigned int irq)
+static void lpd270_mask_irq(struct irq_data *d)
 {
-	int lpd270_irq = irq - LPD270_IRQ(0);
+	int lpd270_irq = d->irq - LPD270_IRQ(0);
 
 	__raw_writew(~(1 << lpd270_irq), LPD270_INT_STATUS);
 
@@ -104,9 +105,9 @@ static void lpd270_mask_irq(unsigned int
 	__raw_writew(lpd270_irq_enabled, LPD270_INT_MASK);
 }
 
-static void lpd270_unmask_irq(unsigned int irq)
+static void lpd270_unmask_irq(struct irq_data *d)
 {
-	int lpd270_irq = irq - LPD270_IRQ(0);
+	int lpd270_irq = d->irq - LPD270_IRQ(0);
 
 	lpd270_irq_enabled |= 1 << lpd270_irq;
 	__raw_writew(lpd270_irq_enabled, LPD270_INT_MASK);
@@ -114,9 +115,9 @@ static void lpd270_unmask_irq(unsigned i
 
 static struct irq_chip lpd270_irq_chip = {
 	.name		= "CPLD",
-	.ack		= lpd270_mask_irq,
-	.mask		= lpd270_mask_irq,
-	.unmask		= lpd270_unmask_irq,
+	.irq_ack	= lpd270_mask_irq,
+	.irq_mask	= lpd270_mask_irq,
+	.irq_unmask	= lpd270_unmask_irq,
 };
 
 static void lpd270_irq_handler(unsigned int irq, struct irq_desc *desc)
@@ -125,7 +126,8 @@ static void lpd270_irq_handler(unsigned
 
 	pending = __raw_readw(LPD270_INT_STATUS) & lpd270_irq_enabled;
 	do {
-		desc->chip->ack(irq);	/* clear useless edge notification */
+		/* clear useless edge notification */
+		desc->irq_data.chip->irq_ack(&desc->irq_data);
 		if (likely(pending)) {
 			irq = LPD270_IRQ(0) + __ffs(pending);
 			generic_handle_irq(irq);
@@ -463,7 +465,7 @@ static void __init lpd270_init(void)
 	pxa_set_btuart_info(NULL);
 	pxa_set_stuart_info(NULL);
 
-	lpd270_flash_data[0].width = (BOOT_DEF & 1) ? 2 : 4;
+	lpd270_flash_data[0].width = (__raw_readl(BOOT_DEF) & 1) ? 2 : 4;
 	lpd270_flash_data[1].width = 4;
 
 	/*
@@ -495,7 +497,7 @@ static struct map_desc lpd270_io_desc[]
 
 static void __init lpd270_map_io(void)
 {
-	pxa_map_io();
+	pxa27x_map_io();
 	iotable_init(lpd270_io_desc, ARRAY_SIZE(lpd270_io_desc));
 
 	/* for use I SRAM as framebuffer.  */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/lubbock.c linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/lubbock.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/lubbock.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/lubbock.c	2011-03-14 21:20:32.000000000 -0400
@@ -25,7 +25,7 @@
 
 #include <linux/spi/spi.h>
 #include <linux/spi/ads7846.h>
-#include <mach/pxa2xx_spi.h>
+#include <linux/spi/pxa2xx_spi.h>
 
 #include <asm/setup.h>
 #include <asm/memory.h>
@@ -50,6 +50,7 @@
 #include <mach/pxafb.h>
 #include <mach/mmc.h>
 #include <mach/pm.h>
+#include <mach/smemc.h>
 
 #include "generic.h"
 #include "clock.h"
@@ -121,15 +122,15 @@ EXPORT_SYMBOL(lubbock_set_misc_wr);
 
 static unsigned long lubbock_irq_enabled;
 
-static void lubbock_mask_irq(unsigned int irq)
+static void lubbock_mask_irq(struct irq_data *d)
 {
-	int lubbock_irq = (irq - LUBBOCK_IRQ(0));
+	int lubbock_irq = (d->irq - LUBBOCK_IRQ(0));
 	LUB_IRQ_MASK_EN = (lubbock_irq_enabled &= ~(1 << lubbock_irq));
 }
 
-static void lubbock_unmask_irq(unsigned int irq)
+static void lubbock_unmask_irq(struct irq_data *d)
 {
-	int lubbock_irq = (irq - LUBBOCK_IRQ(0));
+	int lubbock_irq = (d->irq - LUBBOCK_IRQ(0));
 	/* the irq can be acknowledged only if deasserted, so it's done here */
 	LUB_IRQ_SET_CLR &= ~(1 << lubbock_irq);
 	LUB_IRQ_MASK_EN = (lubbock_irq_enabled |= (1 << lubbock_irq));
@@ -137,16 +138,17 @@ static void lubbock_unmask_irq(unsigned
 
 static struct irq_chip lubbock_irq_chip = {
 	.name		= "FPGA",
-	.ack		= lubbock_mask_irq,
-	.mask		= lubbock_mask_irq,
-	.unmask		= lubbock_unmask_irq,
+	.irq_ack	= lubbock_mask_irq,
+	.irq_mask	= lubbock_mask_irq,
+	.irq_unmask	= lubbock_unmask_irq,
 };
 
 static void lubbock_irq_handler(unsigned int irq, struct irq_desc *desc)
 {
 	unsigned long pending = LUB_IRQ_SET_CLR & lubbock_irq_enabled;
 	do {
-		desc->chip->ack(irq);	/* clear our parent irq */
+		/* clear our parent irq */
+		desc->irq_data.chip->irq_ack(&desc->irq_data);
 		if (likely(pending)) {
 			irq = LUBBOCK_IRQ(0) + __ffs(pending);
 			generic_handle_irq(irq);
@@ -525,7 +527,7 @@ static void __init lubbock_init(void)
 	pxa_set_ac97_info(NULL);
 
 	lubbock_flash_data[0].width = lubbock_flash_data[1].width =
-		(BOOT_DEF & 1) ? 2 : 4;
+		(__raw_readl(BOOT_DEF) & 1) ? 2 : 4;
 	/* Compensate for the nROMBT switch which swaps the flash banks */
 	printk(KERN_NOTICE "Lubbock configured to boot from %s (bank %d)\n",
 	       flashboot?"Flash":"ROM", flashboot);
@@ -549,7 +551,7 @@ static struct map_desc lubbock_io_desc[]
 
 static void __init lubbock_map_io(void)
 {
-	pxa_map_io();
+	pxa25x_map_io();
 	iotable_init(lubbock_io_desc, ARRAY_SIZE(lubbock_io_desc));
 
 	PCFR |= PCFR_OPDE;
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/magician.c linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/magician.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/magician.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/magician.c	2011-03-14 21:20:32.000000000 -0400
@@ -765,7 +765,7 @@ static void __init magician_init(void)
 
 MACHINE_START(MAGICIAN, "HTC Magician")
 	.boot_params = 0xa0000100,
-	.map_io = pxa_map_io,
+	.map_io = pxa27x_map_io,
 	.nr_irqs = MAGICIAN_NR_IRQS,
 	.init_irq = pxa27x_init_irq,
 	.init_machine = magician_init,
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/mainstone.c linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/mainstone.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/mainstone.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/mainstone.c	2011-03-14 21:20:32.000000000 -0400
@@ -51,6 +51,7 @@
 #include <mach/irda.h>
 #include <mach/ohci.h>
 #include <plat/pxa27x_keypad.h>
+#include <mach/smemc.h>
 
 #include "generic.h"
 #include "devices.h"
@@ -122,15 +123,15 @@ static unsigned long mainstone_pin_confi
 
 static unsigned long mainstone_irq_enabled;
 
-static void mainstone_mask_irq(unsigned int irq)
+static void mainstone_mask_irq(struct irq_data *d)
 {
-	int mainstone_irq = (irq - MAINSTONE_IRQ(0));
+	int mainstone_irq = (d->irq - MAINSTONE_IRQ(0));
 	MST_INTMSKENA = (mainstone_irq_enabled &= ~(1 << mainstone_irq));
 }
 
-static void mainstone_unmask_irq(unsigned int irq)
+static void mainstone_unmask_irq(struct irq_data *d)
 {
-	int mainstone_irq = (irq - MAINSTONE_IRQ(0));
+	int mainstone_irq = (d->irq - MAINSTONE_IRQ(0));
 	/* the irq can be acknowledged only if deasserted, so it's done here */
 	MST_INTSETCLR &= ~(1 << mainstone_irq);
 	MST_INTMSKENA = (mainstone_irq_enabled |= (1 << mainstone_irq));
@@ -138,16 +139,17 @@ static void mainstone_unmask_irq(unsigne
 
 static struct irq_chip mainstone_irq_chip = {
 	.name		= "FPGA",
-	.ack		= mainstone_mask_irq,
-	.mask		= mainstone_mask_irq,
-	.unmask		= mainstone_unmask_irq,
+	.irq_ack	= mainstone_mask_irq,
+	.irq_mask	= mainstone_mask_irq,
+	.irq_unmask	= mainstone_unmask_irq,
 };
 
 static void mainstone_irq_handler(unsigned int irq, struct irq_desc *desc)
 {
 	unsigned long pending = MST_INTSETCLR & mainstone_irq_enabled;
 	do {
-		desc->chip->ack(irq);	/* clear useless edge notification */
+		/* clear useless edge notification */
+		desc->irq_data.chip->irq_ack(&desc->irq_data);
 		if (likely(pending)) {
 			irq = MAINSTONE_IRQ(0) + __ffs(pending);
 			generic_handle_irq(irq);
@@ -565,7 +567,7 @@ static void __init mainstone_init(void)
 	pxa_set_btuart_info(NULL);
 	pxa_set_stuart_info(NULL);
 
-	mst_flash_data[0].width = (BOOT_DEF & 1) ? 2 : 4;
+	mst_flash_data[0].width = (__raw_readl(BOOT_DEF) & 1) ? 2 : 4;
 	mst_flash_data[1].width = 4;
 
 	/* Compensate for SW7 which swaps the flash banks */
@@ -614,7 +616,7 @@ static struct map_desc mainstone_io_desc
 
 static void __init mainstone_map_io(void)
 {
-	pxa_map_io();
+	pxa27x_map_io();
 	iotable_init(mainstone_io_desc, ARRAY_SIZE(mainstone_io_desc));
 
  	/*	for use I SRAM as framebuffer.	*/
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/Makefile linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/Makefile
--- linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -16,9 +16,10 @@ endif
 # Generic drivers that other drivers may depend upon
 
 # SoC-specific code
-obj-$(CONFIG_PXA25x)		+= mfp-pxa2xx.o pxa2xx.o pxa25x.o
-obj-$(CONFIG_PXA27x)		+= mfp-pxa2xx.o pxa2xx.o pxa27x.o
-obj-$(CONFIG_PXA3xx)		+= mfp-pxa3xx.o pxa3xx.o smemc.o pxa3xx-ulpi.o
+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_CPU_PXA300)	+= pxa300.o
 obj-$(CONFIG_CPU_PXA320)	+= pxa320.o
 obj-$(CONFIG_CPU_PXA930)	+= pxa930.o
@@ -34,6 +35,7 @@ obj-$(CONFIG_MACH_LITTLETON)	+= littleto
 obj-$(CONFIG_MACH_TAVOREVB)	+= tavorevb.o
 obj-$(CONFIG_MACH_TAVOREVB3)	+= tavorevb3.o
 obj-$(CONFIG_MACH_SAAR)		+= saar.o
+obj-$(CONFIG_MACH_SAARB)	+= saarb.o
 
 # 3rd Party Dev Platforms
 obj-$(CONFIG_ARCH_PXA_IDP)	+= idp.o
@@ -60,7 +62,7 @@ obj-$(CONFIG_MACH_LOGICPD_PXA270)	+= lpd
 obj-$(CONFIG_MACH_PCM027)		+= pcm027.o
 obj-$(CONFIG_MACH_PCM990_BASEBOARD)	+= pcm990-baseboard.o
 obj-$(CONFIG_MACH_COLIBRI)			+= colibri-pxa270.o
-obj-$(CONFIG_MACH_COLIBRI_PXA270_EVALBOARD)	+= colibri-pxa270-evalboard.o
+obj-$(CONFIG_MACH_COLIBRI_EVALBOARD)	+= colibri-evalboard.o
 obj-$(CONFIG_MACH_COLIBRI_PXA270_INCOME)	+= colibri-pxa270-income.o
 obj-$(CONFIG_MACH_COLIBRI300)	+= colibri-pxa3xx.o colibri-pxa300.o
 obj-$(CONFIG_MACH_COLIBRI320)	+= colibri-pxa3xx.o colibri-pxa320.o
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/mioa701.c linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/mioa701.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/mioa701.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/mioa701.c	2011-03-14 21:20:32.000000000 -0400
@@ -819,7 +819,7 @@ static void mioa701_machine_exit(void)
 
 MACHINE_START(MIOA701, "MIO A701")
 	.boot_params	= 0xa0000100,
-	.map_io		= &pxa_map_io,
+	.map_io		= &pxa27x_map_io,
 	.init_irq	= &pxa27x_init_irq,
 	.init_machine	= mioa701_machine_init,
 	.timer		= &pxa_timer,
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/mp900.c linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/mp900.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/mp900.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/mp900.c	2011-03-14 21:20:32.000000000 -0400
@@ -94,7 +94,7 @@ static void __init mp900c_init(void)
 MACHINE_START(NEC_MP900, "MobilePro900/C")
 	.boot_params	= 0xa0220100,
 	.timer		= &pxa_timer,
-	.map_io		= pxa_map_io,
+	.map_io		= pxa25x_map_io,
 	.init_irq	= pxa25x_init_irq,
 	.init_machine	= mp900c_init,
 MACHINE_END
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/mxm8x10.c linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/mxm8x10.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/mxm8x10.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/mxm8x10.c	2011-03-14 21:20:32.000000000 -0400
@@ -337,7 +337,7 @@ void __init mxm_8x10_mmc_init(void)
 }
 #endif
 
-/* USB Open Host Controler Interface */
+/* USB Open Host Controller Interface */
 static struct pxaohci_platform_data mxm_8x10_ohci_platform_data = {
 	.port_mode = PMM_NPS_MODE,
 	.flags = ENABLE_PORT_ALL
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/palm27x.c linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/palm27x.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/palm27x.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/palm27x.c	2011-03-14 21:20:32.000000000 -0400
@@ -323,7 +323,7 @@ static struct platform_pwm_backlight_dat
 	.pwm_id		= 0,
 	.max_brightness	= 0xfe,
 	.dft_brightness	= 0x7e,
-	.pwm_period_ns	= 3500,
+	.pwm_period_ns	= 3500 * 1024,
 	.init		= palm27x_backlight_init,
 	.notify		= palm27x_backlight_notify,
 	.exit		= palm27x_backlight_exit,
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/palmld.c linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/palmld.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/palmld.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/palmld.c	2011-03-14 21:20:32.000000000 -0400
@@ -313,7 +313,7 @@ static struct map_desc palmld_io_desc[]
 
 static void __init palmld_map_io(void)
 {
-	pxa_map_io();
+	pxa27x_map_io();
 	iotable_init(palmld_io_desc, ARRAY_SIZE(palmld_io_desc));
 }
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/palmt5.c linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/palmt5.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/palmt5.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/palmt5.c	2011-03-14 21:20:32.000000000 -0400
@@ -203,7 +203,7 @@ static void __init palmt5_init(void)
 
 MACHINE_START(PALMT5, "Palm Tungsten|T5")
 	.boot_params	= 0xa0000100,
-	.map_io		= pxa_map_io,
+	.map_io		= pxa27x_map_io,
 	.reserve	= palmt5_reserve,
 	.init_irq	= pxa27x_init_irq,
 	.timer		= &pxa_timer,
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/palmtc.c linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/palmtc.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/palmtc.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/palmtc.c	2011-03-14 21:20:32.000000000 -0400
@@ -25,6 +25,7 @@
 #include <linux/power_supply.h>
 #include <linux/gpio_keys.h>
 #include <linux/mtd/physmap.h>
+#include <linux/usb/gpio_vbus.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -116,6 +117,7 @@ static unsigned long palmtc_pin_config[]
 /******************************************************************************
  * SD/MMC card controller
  ******************************************************************************/
+#if defined(CONFIG_MMC_PXA) || defined(CONFIG_MMC_PXA_MODULE)
 static struct pxamci_platform_data palmtc_mci_platform_data = {
 	.ocr_mask		= MMC_VDD_32_33 | MMC_VDD_33_34,
 	.gpio_power		= GPIO_NR_PALMTC_SD_POWER,
@@ -124,9 +126,18 @@ static struct pxamci_platform_data palmt
 	.detect_delay_ms	= 200,
 };
 
+static void __init palmtc_mmc_init(void)
+{
+	pxa_set_mci_info(&palmtc_mci_platform_data);
+}
+#else
+static inline void palmtc_mmc_init(void) {}
+#endif
+
 /******************************************************************************
  * GPIO keys
  ******************************************************************************/
+#if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE)
 static struct gpio_keys_button palmtc_pxa_buttons[] = {
 	{KEY_F8, GPIO_NR_PALMTC_HOTSYNC_BUTTON, 1, "HotSync Button", EV_KEY, 1},
 };
@@ -144,9 +155,18 @@ static struct platform_device palmtc_pxa
 	},
 };
 
+static void __init palmtc_keys_init(void)
+{
+	platform_device_register(&palmtc_pxa_keys);
+}
+#else
+static inline void palmtc_keys_init(void) {}
+#endif
+
 /******************************************************************************
  * Backlight
  ******************************************************************************/
+#if defined(CONFIG_BACKLIGHT_PWM) || defined(CONFIG_BACKLIGHT_PWM_MODULE)
 static int palmtc_backlight_init(struct device *dev)
 {
 	int ret;
@@ -196,17 +216,35 @@ static struct platform_device palmtc_bac
 	},
 };
 
+static void __init palmtc_pwm_init(void)
+{
+	platform_device_register(&palmtc_backlight);
+}
+#else
+static inline void palmtc_pwm_init(void) {}
+#endif
+
 /******************************************************************************
  * IrDA
  ******************************************************************************/
+#if defined(CONFIG_IRDA) || defined(CONFIG_IRDA_MODULE)
 static struct pxaficp_platform_data palmtc_ficp_platform_data = {
 	.gpio_pwdown		= GPIO_NR_PALMTC_IR_DISABLE,
 	.transceiver_cap	= IR_SIRMODE | IR_OFF,
 };
 
+static void __init palmtc_irda_init(void)
+{
+	pxa_set_ficp_info(&palmtc_ficp_platform_data);
+}
+#else
+static inline void palmtc_irda_init(void) {}
+#endif
+
 /******************************************************************************
  * Keyboard
  ******************************************************************************/
+#if defined(CONFIG_KEYBOARD_MATRIX) || defined(CONFIG_KEYBOARD_MATRIX_MODULE)
 static const uint32_t palmtc_matrix_keys[] = {
 	KEY(0, 0, KEY_F1),
 	KEY(0, 1, KEY_X),
@@ -290,27 +328,103 @@ static struct platform_device palmtc_key
 		.platform_data = &palmtc_keypad_platform_data,
 	},
 };
+static void __init palmtc_mkp_init(void)
+{
+	platform_device_register(&palmtc_keyboard);
+}
+#else
+static inline void palmtc_mkp_init(void) {}
+#endif
 
 /******************************************************************************
  * UDC
  ******************************************************************************/
-static struct pxa2xx_udc_mach_info palmtc_udc_info __initdata = {
+#if defined(CONFIG_USB_GADGET_PXA25X)||defined(CONFIG_USB_GADGET_PXA25X_MODULE)
+static struct gpio_vbus_mach_info palmtc_udc_info = {
 	.gpio_vbus		= GPIO_NR_PALMTC_USB_DETECT_N,
 	.gpio_vbus_inverted	= 1,
 	.gpio_pullup		= GPIO_NR_PALMTC_USB_POWER,
 };
 
+static struct platform_device palmtc_gpio_vbus = {
+	.name	= "gpio-vbus",
+	.id	= -1,
+	.dev	= {
+		.platform_data	= &palmtc_udc_info,
+	},
+};
+
+static void __init palmtc_udc_init(void)
+{
+	platform_device_register(&palmtc_gpio_vbus);
+};
+#else
+static inline void palmtc_udc_init(void) {}
+#endif
+
 /******************************************************************************
  * Touchscreen / Battery / GPIO-extender
  ******************************************************************************/
-static struct platform_device palmtc_ucb1400_core = {
+#if	defined(CONFIG_TOUCHSCREEN_UCB1400) || \
+	defined(CONFIG_TOUCHSCREEN_UCB1400_MODULE)
+static struct platform_device palmtc_ucb1400_device = {
 	.name	= "ucb1400_core",
 	.id	= -1,
 };
 
+static void __init palmtc_ts_init(void)
+{
+	pxa_set_ac97_info(NULL);
+	platform_device_register(&palmtc_ucb1400_device);
+}
+#else
+static inline void palmtc_ts_init(void) {}
+#endif
+
+/******************************************************************************
+ * LEDs
+ ******************************************************************************/
+#if defined(CONFIG_LEDS_GPIO) || defined(CONFIG_LEDS_GPIO_MODULE)
+struct gpio_led palmtc_gpio_leds[] = {
+{
+	.name			= "palmtc:green:user",
+	.default_trigger	= "none",
+	.gpio			= GPIO_NR_PALMTC_LED_POWER,
+	.active_low		= 1,
+}, {
+	.name			= "palmtc:vibra:vibra",
+	.default_trigger	= "none",
+	.gpio			= GPIO_NR_PALMTC_VIBRA_POWER,
+	.active_low		= 1,
+}
+
+};
+
+static struct gpio_led_platform_data palmtc_gpio_led_info = {
+	.leds		= palmtc_gpio_leds,
+	.num_leds	= ARRAY_SIZE(palmtc_gpio_leds),
+};
+
+static struct platform_device palmtc_leds = {
+	.name	= "leds-gpio",
+	.id	= -1,
+	.dev	= {
+		.platform_data	= &palmtc_gpio_led_info,
+	}
+};
+
+static void __init palmtc_leds_init(void)
+{
+	platform_device_register(&palmtc_leds);
+}
+#else
+static inline void palmtc_leds_init(void) {}
+#endif
+
 /******************************************************************************
  * NOR Flash
  ******************************************************************************/
+#if defined(CONFIG_MTD_PHYSMAP) || defined(CONFIG_MTD_PHYSMAP_MODULE)
 static struct resource palmtc_flash_resource = {
 	.start	= PXA_CS0_PHYS,
 	.end	= PXA_CS0_PHYS + SZ_16M - 1,
@@ -356,24 +470,33 @@ static struct platform_device palmtc_fla
 	},
 };
 
+static void __init palmtc_nor_init(void)
+{
+	platform_device_register(&palmtc_flash);
+}
+#else
+static inline void palmtc_nor_init(void) {}
+#endif
+
 /******************************************************************************
  * Framebuffer
  ******************************************************************************/
+#if defined(CONFIG_FB_PXA) || defined(CONFIG_FB_PXA_MODULE)
 static struct pxafb_mode_info palmtc_lcd_modes[] = {
-{
-	.pixclock	= 115384,
-	.xres		= 320,
-	.yres		= 320,
-	.bpp		= 16,
+	{
+		.pixclock	= 115384,
+		.xres		= 320,
+		.yres		= 320,
+		.bpp		= 16,
 
-	.left_margin	= 27,
-	.right_margin	= 7,
-	.upper_margin	= 7,
-	.lower_margin	= 8,
+		.left_margin	= 27,
+		.right_margin	= 7,
+		.upper_margin	= 7,
+		.lower_margin	= 8,
 
-	.hsync_len	= 6,
-	.vsync_len	= 1,
-},
+		.hsync_len	= 6,
+		.vsync_len	= 1,
+	},
 };
 
 static struct pxafb_mach_info palmtc_lcd_screen = {
@@ -382,17 +505,17 @@ static struct pxafb_mach_info palmtc_lcd
 	.lcd_conn		= LCD_COLOR_TFT_16BPP | LCD_PCLK_EDGE_FALL,
 };
 
+static void __init palmtc_lcd_init(void)
+{
+	set_pxa_fb_info(&palmtc_lcd_screen);
+}
+#else
+static inline void palmtc_lcd_init(void) {}
+#endif
+
 /******************************************************************************
  * Machine init
  ******************************************************************************/
-static struct platform_device *devices[] __initdata = {
-	&palmtc_backlight,
-	&palmtc_ucb1400_core,
-	&palmtc_keyboard,
-	&palmtc_pxa_keys,
-	&palmtc_flash,
-};
-
 static void __init palmtc_init(void)
 {
 	pxa2xx_mfp_config(ARRAY_AND_SIZE(palmtc_pin_config));
@@ -402,18 +525,21 @@ static void __init palmtc_init(void)
 	pxa_set_stuart_info(NULL);
 	pxa_set_hwuart_info(NULL);
 
-	set_pxa_fb_info(&palmtc_lcd_screen);
-	pxa_set_mci_info(&palmtc_mci_platform_data);
-	pxa_set_udc_info(&palmtc_udc_info);
-	pxa_set_ac97_info(NULL);
-	pxa_set_ficp_info(&palmtc_ficp_platform_data);
-
-	platform_add_devices(devices, ARRAY_SIZE(devices));
+	palmtc_mmc_init();
+	palmtc_keys_init();
+	palmtc_pwm_init();
+	palmtc_irda_init();
+	palmtc_mkp_init();
+	palmtc_udc_init();
+	palmtc_ts_init();
+	palmtc_nor_init();
+	palmtc_lcd_init();
+	palmtc_leds_init();
 };
 
 MACHINE_START(PALMTC, "Palm Tungsten|C")
 	.boot_params 	= 0xa0000100,
-	.map_io		= pxa_map_io,
+	.map_io		= pxa25x_map_io,
 	.init_irq	= pxa25x_init_irq,
 	.timer		= &pxa_timer,
 	.init_machine	= palmtc_init
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/palmte2.c linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/palmte2.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/palmte2.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/palmte2.c	2011-03-14 21:20:32.000000000 -0400
@@ -374,7 +374,7 @@ static void __init palmte2_init(void)
 
 MACHINE_START(PALMTE2, "Palm Tungsten|E2")
 	.boot_params	= 0xa0000100,
-	.map_io		= pxa_map_io,
+	.map_io		= pxa25x_map_io,
 	.init_irq	= pxa25x_init_irq,
 	.timer		= &pxa_timer,
 	.init_machine	= palmte2_init
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/palmtreo.c linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/palmtreo.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/palmtreo.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/palmtreo.c	2011-03-14 21:20:32.000000000 -0400
@@ -442,7 +442,7 @@ static void __init centro_init(void)
 
 MACHINE_START(TREO680, "Palm Treo 680")
 	.boot_params    = 0xa0000100,
-	.map_io         = pxa_map_io,
+	.map_io         = pxa27x_map_io,
 	.reserve	= treo_reserve,
 	.init_irq       = pxa27x_init_irq,
 	.timer          = &pxa_timer,
@@ -451,7 +451,7 @@ MACHINE_END
 
 MACHINE_START(CENTRO, "Palm Centro 685")
 	.boot_params    = 0xa0000100,
-	.map_io         = pxa_map_io,
+	.map_io         = pxa27x_map_io,
 	.reserve	= treo_reserve,
 	.init_irq       = pxa27x_init_irq,
 	.timer          = &pxa_timer,
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/palmtx.c linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/palmtx.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/palmtx.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/palmtx.c	2011-03-14 21:20:32.000000000 -0400
@@ -334,7 +334,7 @@ static struct map_desc palmtx_io_desc[]
 
 static void __init palmtx_map_io(void)
 {
-	pxa_map_io();
+	pxa27x_map_io();
 	iotable_init(palmtx_io_desc, ARRAY_SIZE(palmtx_io_desc));
 }
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/palmz72.c linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/palmz72.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/palmz72.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/palmz72.c	2011-03-14 21:20:32.000000000 -0400
@@ -280,7 +280,7 @@ static void __init palmz72_init(void)
 
 MACHINE_START(PALMZ72, "Palm Zire72")
 	.boot_params	= 0xa0000100,
-	.map_io		= pxa_map_io,
+	.map_io		= pxa27x_map_io,
 	.init_irq	= pxa27x_init_irq,
 	.timer		= &pxa_timer,
 	.init_machine	= palmz72_init
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/pcm027.c linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/pcm027.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/pcm027.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/pcm027.c	2011-03-14 21:20:32.000000000 -0400
@@ -25,12 +25,12 @@
 #include <linux/mtd/physmap.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/max7301.h>
+#include <linux/spi/pxa2xx_spi.h>
 #include <linux/leds.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <mach/pxa27x.h>
-#include <mach/pxa2xx_spi.h>
 #include <mach/pcm027.h>
 #include "generic.h"
 
@@ -244,7 +244,7 @@ static void __init pcm027_init(void)
 
 static void __init pcm027_map_io(void)
 {
-	pxa_map_io();
+	pxa27x_map_io();
 
 	/* initialize sleep mode regs (wake-up sources, etc) */
 	PGSR0 = 0x01308000;
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/pcm990-baseboard.c linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/pcm990-baseboard.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/pcm990-baseboard.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/pcm990-baseboard.c	2011-03-14 21:20:32.000000000 -0400
@@ -241,23 +241,23 @@ static struct platform_device pcm990_bac
 
 static unsigned long pcm990_irq_enabled;
 
-static void pcm990_mask_ack_irq(unsigned int irq)
+static void pcm990_mask_ack_irq(struct irq_data *d)
 {
-	int pcm990_irq = (irq - PCM027_IRQ(0));
+	int pcm990_irq = (d->irq - PCM027_IRQ(0));
 	PCM990_INTMSKENA = (pcm990_irq_enabled &= ~(1 << pcm990_irq));
 }
 
-static void pcm990_unmask_irq(unsigned int irq)
+static void pcm990_unmask_irq(struct irq_data *d)
 {
-	int pcm990_irq = (irq - PCM027_IRQ(0));
+	int pcm990_irq = (d->irq - PCM027_IRQ(0));
 	/* the irq can be acknowledged only if deasserted, so it's done here */
 	PCM990_INTSETCLR |= 1 << pcm990_irq;
 	PCM990_INTMSKENA  = (pcm990_irq_enabled |= (1 << pcm990_irq));
 }
 
 static struct irq_chip pcm990_irq_chip = {
-	.mask_ack	= pcm990_mask_ack_irq,
-	.unmask		= pcm990_unmask_irq,
+	.irq_mask_ack	= pcm990_mask_ack_irq,
+	.irq_unmask	= pcm990_unmask_irq,
 };
 
 static void pcm990_irq_handler(unsigned int irq, struct irq_desc *desc)
@@ -265,7 +265,8 @@ static void pcm990_irq_handler(unsigned
 	unsigned long pending = (~PCM990_INTSETCLR) & pcm990_irq_enabled;
 
 	do {
-		desc->chip->ack(irq);	/* clear our parent IRQ */
+		/* clear our parent IRQ */
+		desc->irq_data.chip->irq_ack(&desc->irq_data);
 		if (likely(pending)) {
 			irq = PCM027_IRQ(0) + __ffs(pending);
 			generic_handle_irq(irq);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/pm.c linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/pm.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/pm.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/pm.c	2011-03-14 21:20:32.000000000 -0400
@@ -33,7 +33,7 @@ int pxa_pm_enter(suspend_state_t state)
 #endif
 
 	/* skip registers saving for standby */
-	if (state != PM_SUSPEND_STANDBY) {
+	if (state != PM_SUSPEND_STANDBY && pxa_cpu_pm_fns->save) {
 		pxa_cpu_pm_fns->save(sleep_save);
 		/* before sleeping, calculate and save a checksum */
 		for (i = 0; i < pxa_cpu_pm_fns->save_count - 1; i++)
@@ -44,7 +44,7 @@ int pxa_pm_enter(suspend_state_t state)
 	pxa_cpu_pm_fns->enter(state);
 	cpu_init();
 
-	if (state != PM_SUSPEND_STANDBY) {
+	if (state != PM_SUSPEND_STANDBY && pxa_cpu_pm_fns->restore) {
 		/* after sleeping, validate the checksum */
 		for (i = 0; i < pxa_cpu_pm_fns->save_count - 1; i++)
 			checksum += sleep_save[i];
@@ -96,7 +96,7 @@ void pxa_pm_finish(void)
 		pxa_cpu_pm_fns->finish();
 }
 
-static struct platform_suspend_ops pxa_pm_ops = {
+static const struct platform_suspend_ops pxa_pm_ops = {
 	.valid		= pxa_pm_valid,
 	.enter		= pxa_pm_enter,
 	.prepare	= pxa_pm_prepare,
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/poodle.c linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/poodle.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/poodle.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/poodle.c	2011-03-14 21:20:32.000000000 -0400
@@ -25,6 +25,7 @@
 #include <linux/i2c.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/ads7846.h>
+#include <linux/spi/pxa2xx_spi.h>
 #include <linux/mtd/sharpsl.h>
 
 #include <mach/hardware.h>
@@ -43,7 +44,6 @@
 #include <mach/irda.h>
 #include <mach/poodle.h>
 #include <mach/pxafb.h>
-#include <mach/pxa2xx_spi.h>
 #include <plat/i2c.h>
 
 #include <asm/hardware/scoop.h>
@@ -466,7 +466,7 @@ static void __init fixup_poodle(struct m
 
 MACHINE_START(POODLE, "SHARP Poodle")
 	.fixup		= fixup_poodle,
-	.map_io		= pxa_map_io,
+	.map_io		= pxa25x_map_io,
 	.nr_irqs	= POODLE_NR_IRQS,	/* 4 for LoCoMo */
 	.init_irq	= pxa25x_init_irq,
 	.timer		= &pxa_timer,
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/pxa25x.c linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/pxa25x.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/pxa25x.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/pxa25x.c	2011-03-14 21:20:32.000000000 -0400
@@ -22,7 +22,9 @@
 #include <linux/platform_device.h>
 #include <linux/suspend.h>
 #include <linux/sysdev.h>
+#include <linux/irq.h>
 
+#include <asm/mach/map.h>
 #include <mach/hardware.h>
 #include <mach/irqs.h>
 #include <mach/gpio.h>
@@ -30,6 +32,7 @@
 #include <mach/reset.h>
 #include <mach/pm.h>
 #include <mach/dma.h>
+#include <mach/smemc.h>
 
 #include "generic.h"
 #include "devices.h"
@@ -90,23 +93,21 @@ unsigned int pxa25x_get_clk_frequency_kh
 	return (turbo & 1) ? (N/1000) : (M/1000);
 }
 
-/*
- * Return the current memory clock frequency in units of 10kHz
- */
-unsigned int pxa25x_get_memclk_frequency_10khz(void)
+static unsigned long clk_pxa25x_mem_getrate(struct clk *clk)
 {
-	return L_clk_mult[(CCCR >> 0) & 0x1f] * BASE_CLK / 10000;
+	return L_clk_mult[(CCCR >> 0) & 0x1f] * BASE_CLK;
 }
 
-static unsigned long clk_pxa25x_lcd_getrate(struct clk *clk)
-{
-	return pxa25x_get_memclk_frequency_10khz() * 10000;
-}
+static const struct clkops clk_pxa25x_mem_ops = {
+	.enable		= clk_dummy_enable,
+	.disable	= clk_dummy_disable,
+	.getrate	= clk_pxa25x_mem_getrate,
+};
 
 static const struct clkops clk_pxa25x_lcd_ops = {
-	.enable		= clk_cken_enable,
-	.disable	= clk_cken_disable,
-	.getrate	= clk_pxa25x_lcd_getrate,
+	.enable		= clk_pxa2xx_cken_enable,
+	.disable	= clk_pxa2xx_cken_disable,
+	.getrate	= clk_pxa25x_mem_getrate,
 };
 
 static unsigned long gpio12_config_32k[] = {
@@ -160,31 +161,30 @@ static const struct clkops clk_pxa25x_gp
  * 95.842MHz -> MMC 19.169MHz, I2C 31.949MHz, FICP 47.923MHz, USB 47.923MHz
  * 147.456MHz -> UART 14.7456MHz, AC97 12.288MHz, I2S 5.672MHz (allegedly)
  */
-static DEFINE_CKEN(pxa25x_hwuart, HWUART, 14745600, 1);
-
-static struct clk_lookup pxa25x_hwuart_clkreg =
-	INIT_CLKREG(&clk_pxa25x_hwuart, "pxa2xx-uart.3", NULL);
 
 /*
  * PXA 2xx clock declarations.
  */
+static DEFINE_PXA2_CKEN(pxa25x_hwuart, HWUART, 14745600, 1);
+static DEFINE_PXA2_CKEN(pxa25x_ffuart, FFUART, 14745600, 1);
+static DEFINE_PXA2_CKEN(pxa25x_btuart, BTUART, 14745600, 1);
+static DEFINE_PXA2_CKEN(pxa25x_stuart, STUART, 14745600, 1);
+static DEFINE_PXA2_CKEN(pxa25x_usb, USB, 47923000, 5);
+static DEFINE_PXA2_CKEN(pxa25x_mmc, MMC, 19169000, 0);
+static DEFINE_PXA2_CKEN(pxa25x_i2c, I2C, 31949000, 0);
+static DEFINE_PXA2_CKEN(pxa25x_ssp, SSP, 3686400, 0);
+static DEFINE_PXA2_CKEN(pxa25x_nssp, NSSP, 3686400, 0);
+static DEFINE_PXA2_CKEN(pxa25x_assp, ASSP, 3686400, 0);
+static DEFINE_PXA2_CKEN(pxa25x_pwm0, PWM0, 3686400, 0);
+static DEFINE_PXA2_CKEN(pxa25x_pwm1, PWM1, 3686400, 0);
+static DEFINE_PXA2_CKEN(pxa25x_ac97, AC97, 24576000, 0);
+static DEFINE_PXA2_CKEN(pxa25x_i2s, I2S, 14745600, 0);
+static DEFINE_PXA2_CKEN(pxa25x_ficp, FICP, 47923000, 0);
+
 static DEFINE_CK(pxa25x_lcd, LCD, &clk_pxa25x_lcd_ops);
-static DEFINE_CKEN(pxa25x_ffuart, FFUART, 14745600, 1);
-static DEFINE_CKEN(pxa25x_btuart, BTUART, 14745600, 1);
-static DEFINE_CKEN(pxa25x_stuart, STUART, 14745600, 1);
-static DEFINE_CKEN(pxa25x_usb, USB, 47923000, 5);
 static DEFINE_CLK(pxa25x_gpio11, &clk_pxa25x_gpio11_ops, 3686400, 0);
 static DEFINE_CLK(pxa25x_gpio12, &clk_pxa25x_gpio12_ops, 32768, 0);
-static DEFINE_CKEN(pxa25x_mmc, MMC, 19169000, 0);
-static DEFINE_CKEN(pxa25x_i2c, I2C, 31949000, 0);
-static DEFINE_CKEN(pxa25x_ssp, SSP, 3686400, 0);
-static DEFINE_CKEN(pxa25x_nssp, NSSP, 3686400, 0);
-static DEFINE_CKEN(pxa25x_assp, ASSP, 3686400, 0);
-static DEFINE_CKEN(pxa25x_pwm0, PWM0, 3686400, 0);
-static DEFINE_CKEN(pxa25x_pwm1, PWM1, 3686400, 0);
-static DEFINE_CKEN(pxa25x_ac97, AC97, 24576000, 0);
-static DEFINE_CKEN(pxa25x_i2s, I2S, 14745600, 0);
-static DEFINE_CKEN(pxa25x_ficp, FICP, 47923000, 0);
+static DEFINE_CLK(pxa25x_mem, &clk_pxa25x_mem_ops, 0, 0);
 
 static struct clk_lookup pxa25x_clkregs[] = {
 	INIT_CLKREG(&clk_pxa25x_lcd, "pxa2xx-fb", NULL),
@@ -205,8 +205,12 @@ static struct clk_lookup pxa25x_clkregs[
 	INIT_CLKREG(&clk_pxa25x_ac97, NULL, "AC97CLK"),
 	INIT_CLKREG(&clk_pxa25x_gpio11, NULL, "GPIO11_CLK"),
 	INIT_CLKREG(&clk_pxa25x_gpio12, NULL, "GPIO12_CLK"),
+	INIT_CLKREG(&clk_pxa25x_mem, "pxa2xx-pcmcia", NULL),
 };
 
+static struct clk_lookup pxa25x_hwuart_clkreg =
+	INIT_CLKREG(&clk_pxa25x_hwuart, "pxa2xx-uart.3", NULL);
+
 #ifdef CONFIG_PM
 
 #define SAVE(x)		sleep_save[SLEEP_SAVE_##x] = x
@@ -219,20 +223,17 @@ static struct clk_lookup pxa25x_clkregs[
  */
 enum {
 	SLEEP_SAVE_PSTR,
-	SLEEP_SAVE_CKEN,
 	SLEEP_SAVE_COUNT
 };
 
 
 static void pxa25x_cpu_pm_save(unsigned long *sleep_save)
 {
-	SAVE(CKEN);
 	SAVE(PSTR);
 }
 
 static void pxa25x_cpu_pm_restore(unsigned long *sleep_save)
 {
-	RESTORE(CKEN);
 	RESTORE(PSTR);
 }
 
@@ -282,15 +283,15 @@ static inline void pxa25x_init_pm(void)
 /* PXA25x: supports wakeup from GPIO0..GPIO15 and RTC alarm
  */
 
-static int pxa25x_set_wake(unsigned int irq, unsigned int on)
+static int pxa25x_set_wake(struct irq_data *d, unsigned int on)
 {
-	int gpio = IRQ_TO_GPIO(irq);
+	int gpio = IRQ_TO_GPIO(d->irq);
 	uint32_t mask = 0;
 
 	if (gpio >= 0 && gpio < 85)
 		return gpio_set_wake(gpio, on);
 
-	if (irq == IRQ_RTCAlrm) {
+	if (d->irq == IRQ_RTCAlrm) {
 		mask = PWER_RTC;
 		goto set_pwer;
 	}
@@ -320,6 +321,22 @@ void __init pxa26x_init_irq(void)
 }
 #endif
 
+static struct map_desc pxa25x_io_desc[] __initdata = {
+	{	/* Mem Ctl */
+		.virtual	= SMEMC_VIRT,
+		.pfn		= __phys_to_pfn(PXA2XX_SMEMC_BASE),
+		.length		= 0x00200000,
+		.type		= MT_DEVICE
+	},
+};
+
+void __init pxa25x_map_io(void)
+{
+	pxa_map_io();
+	iotable_init(ARRAY_AND_SIZE(pxa25x_io_desc));
+	pxa25x_get_clk_frequency_khz(1);
+}
+
 static struct platform_device *pxa25x_devices[] __initdata = {
 	&pxa25x_device_udc,
 	&pxa_device_pmu,
@@ -330,6 +347,7 @@ static struct platform_device *pxa25x_de
 	&pxa25x_device_assp,
 	&pxa25x_device_pwm0,
 	&pxa25x_device_pwm1,
+	&pxa_device_asoc_platform,
 };
 
 static struct sys_device pxa25x_sysdev[] = {
@@ -339,7 +357,9 @@ static struct sys_device pxa25x_sysdev[]
 		.cls	= &pxa2xx_mfp_sysclass,
 	}, {
 		.cls	= &pxa_gpio_sysclass,
-	},
+	}, {
+		.cls	= &pxa2xx_clock_sysclass,
+	}
 };
 
 static int __init pxa25x_init(void)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/pxa27x.c linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/pxa27x.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/pxa27x.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/pxa27x.c	2011-03-14 21:20:32.000000000 -0400
@@ -17,7 +17,10 @@
 #include <linux/suspend.h>
 #include <linux/platform_device.h>
 #include <linux/sysdev.h>
+#include <linux/io.h>
+#include <linux/irq.h>
 
+#include <asm/mach/map.h>
 #include <mach/hardware.h>
 #include <asm/irq.h>
 #include <mach/irqs.h>
@@ -27,6 +30,8 @@
 #include <mach/ohci.h>
 #include <mach/pm.h>
 #include <mach/dma.h>
+#include <mach/smemc.h>
+
 #include <plat/i2c.h>
 
 #include "generic.h"
@@ -107,10 +112,9 @@ unsigned int pxa27x_get_clk_frequency_kh
 }
 
 /*
- * Return the current mem clock frequency in units of 10kHz as
- * reflected by CCCR[A], B, and L
+ * Return the current mem clock frequency as reflected by CCCR[A], B, and L
  */
-unsigned int pxa27x_get_memclk_frequency_10khz(void)
+static unsigned long clk_pxa27x_mem_getrate(struct clk *clk)
 {
 	unsigned long ccsr, clkcfg;
 	unsigned int l, L, m, M;
@@ -129,9 +133,15 @@ unsigned int pxa27x_get_memclk_frequency
 	L = l * BASE_CLK;
 	M = (!cccr_a) ? (L/m) : ((b) ? L : (L/2));
 
-	return (M / 10000);
+	return M;
 }
 
+static const struct clkops clk_pxa27x_mem_ops = {
+	.enable		= clk_dummy_enable,
+	.disable	= clk_dummy_disable,
+	.getrate	= clk_pxa27x_mem_getrate,
+};
+
 /*
  * Return the current LCD clock frequency in units of 10kHz as
  */
@@ -157,36 +167,38 @@ static unsigned long clk_pxa27x_lcd_getr
 }
 
 static const struct clkops clk_pxa27x_lcd_ops = {
-	.enable		= clk_cken_enable,
-	.disable	= clk_cken_disable,
+	.enable		= clk_pxa2xx_cken_enable,
+	.disable	= clk_pxa2xx_cken_disable,
 	.getrate	= clk_pxa27x_lcd_getrate,
 };
 
+static DEFINE_PXA2_CKEN(pxa27x_ffuart, FFUART, 14857000, 1);
+static DEFINE_PXA2_CKEN(pxa27x_btuart, BTUART, 14857000, 1);
+static DEFINE_PXA2_CKEN(pxa27x_stuart, STUART, 14857000, 1);
+static DEFINE_PXA2_CKEN(pxa27x_i2s, I2S, 14682000, 0);
+static DEFINE_PXA2_CKEN(pxa27x_i2c, I2C, 32842000, 0);
+static DEFINE_PXA2_CKEN(pxa27x_usb, USB, 48000000, 5);
+static DEFINE_PXA2_CKEN(pxa27x_mmc, MMC, 19500000, 0);
+static DEFINE_PXA2_CKEN(pxa27x_ficp, FICP, 48000000, 0);
+static DEFINE_PXA2_CKEN(pxa27x_usbhost, USBHOST, 48000000, 0);
+static DEFINE_PXA2_CKEN(pxa27x_pwri2c, PWRI2C, 13000000, 0);
+static DEFINE_PXA2_CKEN(pxa27x_keypad, KEYPAD, 32768, 0);
+static DEFINE_PXA2_CKEN(pxa27x_ssp1, SSP1, 13000000, 0);
+static DEFINE_PXA2_CKEN(pxa27x_ssp2, SSP2, 13000000, 0);
+static DEFINE_PXA2_CKEN(pxa27x_ssp3, SSP3, 13000000, 0);
+static DEFINE_PXA2_CKEN(pxa27x_pwm0, PWM0, 13000000, 0);
+static DEFINE_PXA2_CKEN(pxa27x_pwm1, PWM1, 13000000, 0);
+static DEFINE_PXA2_CKEN(pxa27x_ac97, AC97, 24576000, 0);
+static DEFINE_PXA2_CKEN(pxa27x_ac97conf, AC97CONF, 24576000, 0);
+static DEFINE_PXA2_CKEN(pxa27x_msl, MSL, 48000000, 0);
+static DEFINE_PXA2_CKEN(pxa27x_usim, USIM, 48000000, 0);
+static DEFINE_PXA2_CKEN(pxa27x_memstk, MEMSTK, 19500000, 0);
+static DEFINE_PXA2_CKEN(pxa27x_im, IM, 0, 0);
+static DEFINE_PXA2_CKEN(pxa27x_memc, MEMC, 0, 0);
+
 static DEFINE_CK(pxa27x_lcd, LCD, &clk_pxa27x_lcd_ops);
 static DEFINE_CK(pxa27x_camera, CAMERA, &clk_pxa27x_lcd_ops);
-static DEFINE_CKEN(pxa27x_ffuart, FFUART, 14857000, 1);
-static DEFINE_CKEN(pxa27x_btuart, BTUART, 14857000, 1);
-static DEFINE_CKEN(pxa27x_stuart, STUART, 14857000, 1);
-static DEFINE_CKEN(pxa27x_i2s, I2S, 14682000, 0);
-static DEFINE_CKEN(pxa27x_i2c, I2C, 32842000, 0);
-static DEFINE_CKEN(pxa27x_usb, USB, 48000000, 5);
-static DEFINE_CKEN(pxa27x_mmc, MMC, 19500000, 0);
-static DEFINE_CKEN(pxa27x_ficp, FICP, 48000000, 0);
-static DEFINE_CKEN(pxa27x_usbhost, USBHOST, 48000000, 0);
-static DEFINE_CKEN(pxa27x_pwri2c, PWRI2C, 13000000, 0);
-static DEFINE_CKEN(pxa27x_keypad, KEYPAD, 32768, 0);
-static DEFINE_CKEN(pxa27x_ssp1, SSP1, 13000000, 0);
-static DEFINE_CKEN(pxa27x_ssp2, SSP2, 13000000, 0);
-static DEFINE_CKEN(pxa27x_ssp3, SSP3, 13000000, 0);
-static DEFINE_CKEN(pxa27x_pwm0, PWM0, 13000000, 0);
-static DEFINE_CKEN(pxa27x_pwm1, PWM1, 13000000, 0);
-static DEFINE_CKEN(pxa27x_ac97, AC97, 24576000, 0);
-static DEFINE_CKEN(pxa27x_ac97conf, AC97CONF, 24576000, 0);
-static DEFINE_CKEN(pxa27x_msl, MSL, 48000000, 0);
-static DEFINE_CKEN(pxa27x_usim, USIM, 48000000, 0);
-static DEFINE_CKEN(pxa27x_memstk, MEMSTK, 19500000, 0);
-static DEFINE_CKEN(pxa27x_im, IM, 0, 0);
-static DEFINE_CKEN(pxa27x_memc, MEMC, 0, 0);
+static DEFINE_CLK(pxa27x_mem, &clk_pxa27x_mem_ops, 0, 0);
 
 static struct clk_lookup pxa27x_clkregs[] = {
 	INIT_CLKREG(&clk_pxa27x_lcd, "pxa2xx-fb", NULL),
@@ -215,6 +227,7 @@ static struct clk_lookup pxa27x_clkregs[
 	INIT_CLKREG(&clk_pxa27x_memstk, NULL, "MSTKCLK"),
 	INIT_CLKREG(&clk_pxa27x_im, NULL, "IMCLK"),
 	INIT_CLKREG(&clk_pxa27x_memc, NULL, "MEMCLK"),
+	INIT_CLKREG(&clk_pxa27x_mem, "pxa2xx-pcmcia", NULL),
 };
 
 #ifdef CONFIG_PM
@@ -246,7 +259,6 @@ int __init pxa27x_set_pwrmode(unsigned i
  */
 enum {
 	SLEEP_SAVE_PSTR,
-	SLEEP_SAVE_CKEN,
 	SLEEP_SAVE_MDREFR,
 	SLEEP_SAVE_PCFR,
 	SLEEP_SAVE_COUNT
@@ -254,21 +266,19 @@ enum {
 
 void pxa27x_cpu_pm_save(unsigned long *sleep_save)
 {
-	SAVE(MDREFR);
+	sleep_save[SLEEP_SAVE_MDREFR] = __raw_readl(MDREFR);
 	SAVE(PCFR);
 
-	SAVE(CKEN);
 	SAVE(PSTR);
 }
 
 void pxa27x_cpu_pm_restore(unsigned long *sleep_save)
 {
-	RESTORE(MDREFR);
+	__raw_writel(sleep_save[SLEEP_SAVE_MDREFR], MDREFR);
 	RESTORE(PCFR);
 
 	PSSR = PSSR_RDH | PSSR_PH;
 
-	RESTORE(CKEN);
 	RESTORE(PSTR);
 }
 
@@ -334,18 +344,18 @@ static inline void pxa27x_init_pm(void)
 /* PXA27x:  Various gpios can issue wakeup events.  This logic only
  * handles the simple cases, not the WEMUX2 and WEMUX3 options
  */
-static int pxa27x_set_wake(unsigned int irq, unsigned int on)
+static int pxa27x_set_wake(struct irq_data *d, unsigned int on)
 {
-	int gpio = IRQ_TO_GPIO(irq);
+	int gpio = IRQ_TO_GPIO(d->irq);
 	uint32_t mask;
 
 	if (gpio >= 0 && gpio < 128)
 		return gpio_set_wake(gpio, on);
 
-	if (irq == IRQ_KEYPAD)
+	if (d->irq == IRQ_KEYPAD)
 		return keypad_set_wake(on);
 
-	switch (irq) {
+	switch (d->irq) {
 	case IRQ_RTCAlrm:
 		mask = PWER_RTC;
 		break;
@@ -370,6 +380,27 @@ void __init pxa27x_init_irq(void)
 	pxa_init_gpio(IRQ_GPIO_2_x, 2, 120, pxa27x_set_wake);
 }
 
+static struct map_desc pxa27x_io_desc[] __initdata = {
+	{	/* Mem Ctl */
+		.virtual	= SMEMC_VIRT,
+		.pfn		= __phys_to_pfn(PXA2XX_SMEMC_BASE),
+		.length		= 0x00200000,
+		.type		= MT_DEVICE
+	}, {	/* IMem ctl */
+		.virtual	=  0xfe000000,
+		.pfn		= __phys_to_pfn(0x58000000),
+		.length		= 0x00100000,
+		.type		= MT_DEVICE
+	},
+};
+
+void __init pxa27x_map_io(void)
+{
+	pxa_map_io();
+	iotable_init(ARRAY_AND_SIZE(pxa27x_io_desc));
+	pxa27x_get_clk_frequency_khz(1);
+}
+
 /*
  * device registration specific to PXA27x.
  */
@@ -405,7 +436,9 @@ static struct sys_device pxa27x_sysdev[]
 		.cls	= &pxa2xx_mfp_sysclass,
 	}, {
 		.cls	= &pxa_gpio_sysclass,
-	},
+	}, {
+		.cls	= &pxa2xx_clock_sysclass,
+	}
 };
 
 static int __init pxa27x_init(void)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/pxa3xx.c linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/pxa3xx.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/pxa3xx.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/pxa3xx.c	2011-03-14 21:20:32.000000000 -0400
@@ -22,6 +22,7 @@
 #include <linux/io.h>
 #include <linux/sysdev.h>
 
+#include <asm/mach/map.h>
 #include <mach/hardware.h>
 #include <mach/gpio.h>
 #include <mach/pxa3xx-regs.h>
@@ -30,193 +31,16 @@
 #include <mach/pm.h>
 #include <mach/dma.h>
 #include <mach/regs-intc.h>
+#include <mach/smemc.h>
 #include <plat/i2c.h>
 
 #include "generic.h"
 #include "devices.h"
 #include "clock.h"
 
-/* Crystal clock: 13MHz */
-#define BASE_CLK	13000000
-
-/* Ring Oscillator Clock: 60MHz */
-#define RO_CLK		60000000
-
-#define ACCR_D0CS	(1 << 26)
-#define ACCR_PCCE	(1 << 11)
-
 #define PECR_IE(n)	((1 << ((n) * 2)) << 28)
 #define PECR_IS(n)	((1 << ((n) * 2)) << 29)
 
-/* crystal frequency to static memory controller multiplier (SMCFS) */
-static unsigned char smcfs_mult[8] = { 6, 0, 8, 0, 0, 16, };
-
-/* crystal frequency to HSIO bus frequency multiplier (HSS) */
-static unsigned char hss_mult[4] = { 8, 12, 16, 24 };
-
-/*
- * Get the clock frequency as reflected by CCSR and the turbo flag.
- * We assume these values have been applied via a fcs.
- * If info is not 0 we also display the current settings.
- */
-unsigned int pxa3xx_get_clk_frequency_khz(int info)
-{
-	unsigned long acsr, xclkcfg;
-	unsigned int t, xl, xn, hss, ro, XL, XN, CLK, HSS;
-
-	/* Read XCLKCFG register turbo bit */
-	__asm__ __volatile__("mrc\tp14, 0, %0, c6, c0, 0" : "=r"(xclkcfg));
-	t = xclkcfg & 0x1;
-
-	acsr = ACSR;
-
-	xl  = acsr & 0x1f;
-	xn  = (acsr >> 8) & 0x7;
-	hss = (acsr >> 14) & 0x3;
-
-	XL = xl * BASE_CLK;
-	XN = xn * XL;
-
-	ro = acsr & ACCR_D0CS;
-
-	CLK = (ro) ? RO_CLK : ((t) ? XN : XL);
-	HSS = (ro) ? RO_CLK : hss_mult[hss] * BASE_CLK;
-
-	if (info) {
-		pr_info("RO Mode clock: %d.%02dMHz (%sactive)\n",
-			RO_CLK / 1000000, (RO_CLK % 1000000) / 10000,
-			(ro) ? "" : "in");
-		pr_info("Run Mode clock: %d.%02dMHz (*%d)\n",
-			XL / 1000000, (XL % 1000000) / 10000, xl);
-		pr_info("Turbo Mode clock: %d.%02dMHz (*%d, %sactive)\n",
-			XN / 1000000, (XN % 1000000) / 10000, xn,
-			(t) ? "" : "in");
-		pr_info("HSIO bus clock: %d.%02dMHz\n",
-			HSS / 1000000, (HSS % 1000000) / 10000);
-	}
-
-	return CLK / 1000;
-}
-
-void pxa3xx_clear_reset_status(unsigned int mask)
-{
-	/* RESET_STATUS_* has a 1:1 mapping with ARSR */
-	ARSR = mask;
-}
-
-/*
- * Return the current AC97 clock frequency.
- */
-static unsigned long clk_pxa3xx_ac97_getrate(struct clk *clk)
-{
-	unsigned long rate = 312000000;
-	unsigned long ac97_div;
-
-	ac97_div = AC97_DIV;
-
-	/* This may loose precision for some rates but won't for the
-	 * standard 24.576MHz.
-	 */
-	rate /= (ac97_div >> 12) & 0x7fff;
-	rate *= (ac97_div & 0xfff);
-
-	return rate;
-}
-
-/*
- * Return the current HSIO bus clock frequency
- */
-static unsigned long clk_pxa3xx_hsio_getrate(struct clk *clk)
-{
-	unsigned long acsr;
-	unsigned int hss, hsio_clk;
-
-	acsr = ACSR;
-
-	hss = (acsr >> 14) & 0x3;
-	hsio_clk = (acsr & ACCR_D0CS) ? RO_CLK : hss_mult[hss] * BASE_CLK;
-
-	return hsio_clk;
-}
-
-void clk_pxa3xx_cken_enable(struct clk *clk)
-{
-	unsigned long mask = 1ul << (clk->cken & 0x1f);
-
-	if (clk->cken < 32)
-		CKENA |= mask;
-	else
-		CKENB |= mask;
-}
-
-void clk_pxa3xx_cken_disable(struct clk *clk)
-{
-	unsigned long mask = 1ul << (clk->cken & 0x1f);
-
-	if (clk->cken < 32)
-		CKENA &= ~mask;
-	else
-		CKENB &= ~mask;
-}
-
-const struct clkops clk_pxa3xx_cken_ops = {
-	.enable		= clk_pxa3xx_cken_enable,
-	.disable	= clk_pxa3xx_cken_disable,
-};
-
-static const struct clkops clk_pxa3xx_hsio_ops = {
-	.enable		= clk_pxa3xx_cken_enable,
-	.disable	= clk_pxa3xx_cken_disable,
-	.getrate	= clk_pxa3xx_hsio_getrate,
-};
-
-static const struct clkops clk_pxa3xx_ac97_ops = {
-	.enable		= clk_pxa3xx_cken_enable,
-	.disable	= clk_pxa3xx_cken_disable,
-	.getrate	= clk_pxa3xx_ac97_getrate,
-};
-
-static void clk_pout_enable(struct clk *clk)
-{
-	OSCC |= OSCC_PEN;
-}
-
-static void clk_pout_disable(struct clk *clk)
-{
-	OSCC &= ~OSCC_PEN;
-}
-
-static const struct clkops clk_pout_ops = {
-	.enable		= clk_pout_enable,
-	.disable	= clk_pout_disable,
-};
-
-static void clk_dummy_enable(struct clk *clk)
-{
-}
-
-static void clk_dummy_disable(struct clk *clk)
-{
-}
-
-static const struct clkops clk_dummy_ops = {
-	.enable		= clk_dummy_enable,
-	.disable	= clk_dummy_disable,
-};
-
-static struct clk clk_pxa3xx_pout = {
-	.ops		= &clk_pout_ops,
-	.rate		= 13000000,
-	.delay		= 70,
-};
-
-static struct clk clk_dummy = {
-	.ops		= &clk_dummy_ops,
-};
-
-static DEFINE_PXA3_CK(pxa3xx_lcd, LCD, &clk_pxa3xx_hsio_ops);
-static DEFINE_PXA3_CK(pxa3xx_camera, CAMERA, &clk_pxa3xx_hsio_ops);
-static DEFINE_PXA3_CK(pxa3xx_ac97, AC97, &clk_pxa3xx_ac97_ops);
 static DEFINE_PXA3_CKEN(pxa3xx_ffuart, FFUART, 14857000, 1);
 static DEFINE_PXA3_CKEN(pxa3xx_btuart, BTUART, 14857000, 1);
 static DEFINE_PXA3_CKEN(pxa3xx_stuart, STUART, 14857000, 1);
@@ -234,6 +58,12 @@ static DEFINE_PXA3_CKEN(pxa3xx_pwm1, PWM
 static DEFINE_PXA3_CKEN(pxa3xx_mmc1, MMC1, 19500000, 0);
 static DEFINE_PXA3_CKEN(pxa3xx_mmc2, MMC2, 19500000, 0);
 
+static DEFINE_CK(pxa3xx_lcd, LCD, &clk_pxa3xx_hsio_ops);
+static DEFINE_CK(pxa3xx_smemc, SMC, &clk_pxa3xx_smemc_ops);
+static DEFINE_CK(pxa3xx_camera, CAMERA, &clk_pxa3xx_hsio_ops);
+static DEFINE_CK(pxa3xx_ac97, AC97, &clk_pxa3xx_ac97_ops);
+static DEFINE_CLK(pxa3xx_pout, &clk_pxa3xx_pout_ops, 13000000, 70);
+
 static struct clk_lookup pxa3xx_clkregs[] = {
 	INIT_CLKREG(&clk_pxa3xx_pout, NULL, "CLK_POUT"),
 	/* Power I2C clock is always on */
@@ -258,6 +88,7 @@ static struct clk_lookup pxa3xx_clkregs[
 	INIT_CLKREG(&clk_pxa3xx_pwm1, "pxa27x-pwm.1", NULL),
 	INIT_CLKREG(&clk_pxa3xx_mmc1, "pxa2xx-mci.0", NULL),
 	INIT_CLKREG(&clk_pxa3xx_mmc2, "pxa2xx-mci.1", NULL),
+	INIT_CLKREG(&clk_pxa3xx_smemc, "pxa2xx-pcmcia", NULL),
 };
 
 #ifdef CONFIG_PM
@@ -268,30 +99,6 @@ static struct clk_lookup pxa3xx_clkregs[
 static void __iomem *sram;
 static unsigned long wakeup_src;
 
-#define SAVE(x)		sleep_save[SLEEP_SAVE_##x] = x
-#define RESTORE(x)	x = sleep_save[SLEEP_SAVE_##x]
-
-enum {	SLEEP_SAVE_CKENA,
-	SLEEP_SAVE_CKENB,
-	SLEEP_SAVE_ACCR,
-
-	SLEEP_SAVE_COUNT,
-};
-
-static void pxa3xx_cpu_pm_save(unsigned long *sleep_save)
-{
-	SAVE(CKENA);
-	SAVE(CKENB);
-	SAVE(ACCR);
-}
-
-static void pxa3xx_cpu_pm_restore(unsigned long *sleep_save)
-{
-	RESTORE(ACCR);
-	RESTORE(CKENA);
-	RESTORE(CKENB);
-}
-
 /*
  * Enter a standby mode (S0D1C2 or S0D2C2).  Upon wakeup, the dynamic
  * memory controller has to be reinitialised, so we place some code
@@ -390,9 +197,6 @@ static int pxa3xx_cpu_pm_valid(suspend_s
 }
 
 static struct pxa_cpu_pm_fns pxa3xx_cpu_pm_fns = {
-	.save_count	= SLEEP_SAVE_COUNT,
-	.save		= pxa3xx_cpu_pm_save,
-	.restore	= pxa3xx_cpu_pm_restore,
 	.valid		= pxa3xx_cpu_pm_valid,
 	.enter		= pxa3xx_cpu_pm_enter,
 };
@@ -425,11 +229,11 @@ static void __init pxa3xx_init_pm(void)
 	pxa_cpu_pm_fns = &pxa3xx_cpu_pm_fns;
 }
 
-static int pxa3xx_set_wake(unsigned int irq, unsigned int on)
+static int pxa3xx_set_wake(struct irq_data *d, unsigned int on)
 {
 	unsigned long flags, mask = 0;
 
-	switch (irq) {
+	switch (d->irq) {
 	case IRQ_SSP3:
 		mask = ADXER_MFP_WSSP3;
 		break;
@@ -518,40 +322,40 @@ static inline void pxa3xx_init_pm(void)
 #define pxa3xx_set_wake	NULL
 #endif
 
-static void pxa_ack_ext_wakeup(unsigned int irq)
+static void pxa_ack_ext_wakeup(struct irq_data *d)
 {
-	PECR |= PECR_IS(irq - IRQ_WAKEUP0);
+	PECR |= PECR_IS(d->irq - IRQ_WAKEUP0);
 }
 
-static void pxa_mask_ext_wakeup(unsigned int irq)
+static void pxa_mask_ext_wakeup(struct irq_data *d)
 {
-	ICMR2 &= ~(1 << ((irq - PXA_IRQ(0)) & 0x1f));
-	PECR &= ~PECR_IE(irq - IRQ_WAKEUP0);
+	ICMR2 &= ~(1 << ((d->irq - PXA_IRQ(0)) & 0x1f));
+	PECR &= ~PECR_IE(d->irq - IRQ_WAKEUP0);
 }
 
-static void pxa_unmask_ext_wakeup(unsigned int irq)
+static void pxa_unmask_ext_wakeup(struct irq_data *d)
 {
-	ICMR2 |= 1 << ((irq - PXA_IRQ(0)) & 0x1f);
-	PECR |= PECR_IE(irq - IRQ_WAKEUP0);
+	ICMR2 |= 1 << ((d->irq - PXA_IRQ(0)) & 0x1f);
+	PECR |= PECR_IE(d->irq - IRQ_WAKEUP0);
 }
 
-static int pxa_set_ext_wakeup_type(unsigned int irq, unsigned int flow_type)
+static int pxa_set_ext_wakeup_type(struct irq_data *d, unsigned int flow_type)
 {
 	if (flow_type & IRQ_TYPE_EDGE_RISING)
-		PWER |= 1 << (irq - IRQ_WAKEUP0);
+		PWER |= 1 << (d->irq - IRQ_WAKEUP0);
 
 	if (flow_type & IRQ_TYPE_EDGE_FALLING)
-		PWER |= 1 << (irq - IRQ_WAKEUP0 + 2);
+		PWER |= 1 << (d->irq - IRQ_WAKEUP0 + 2);
 
 	return 0;
 }
 
 static struct irq_chip pxa_ext_wakeup_chip = {
 	.name		= "WAKEUP",
-	.ack		= pxa_ack_ext_wakeup,
-	.mask		= pxa_mask_ext_wakeup,
-	.unmask		= pxa_unmask_ext_wakeup,
-	.set_type	= pxa_set_ext_wakeup_type,
+	.irq_ack	= pxa_ack_ext_wakeup,
+	.irq_mask	= pxa_mask_ext_wakeup,
+	.irq_unmask	= pxa_unmask_ext_wakeup,
+	.irq_set_type	= pxa_set_ext_wakeup_type,
 };
 
 static void __init pxa_init_ext_wakeup_irq(set_wake_t fn)
@@ -564,7 +368,7 @@ static void __init pxa_init_ext_wakeup_i
 		set_irq_flags(irq, IRQF_VALID);
 	}
 
-	pxa_ext_wakeup_chip.set_wake = fn;
+	pxa_ext_wakeup_chip.irq_set_wake = fn;
 }
 
 void __init pxa3xx_init_irq(void)
@@ -580,6 +384,22 @@ void __init pxa3xx_init_irq(void)
 	pxa_init_gpio(IRQ_GPIO_2_x, 2, 127, NULL);
 }
 
+static struct map_desc pxa3xx_io_desc[] __initdata = {
+	{	/* Mem Ctl */
+		.virtual	= SMEMC_VIRT,
+		.pfn		= __phys_to_pfn(PXA3XX_SMEMC_BASE),
+		.length		= 0x00200000,
+		.type		= MT_DEVICE
+	}
+};
+
+void __init pxa3xx_map_io(void)
+{
+	pxa_map_io();
+	iotable_init(ARRAY_AND_SIZE(pxa3xx_io_desc));
+	pxa3xx_get_clk_frequency_khz(1);
+}
+
 /*
  * device registration specific to PXA3xx.
  */
@@ -615,7 +435,9 @@ static struct sys_device pxa3xx_sysdev[]
 		.cls	= &pxa3xx_mfp_sysclass,
 	}, {
 		.cls	= &pxa_gpio_sysclass,
-	},
+	}, {
+		.cls	= &pxa3xx_clock_sysclass,
+	}
 };
 
 static int __init pxa3xx_init(void)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/pxa930.c linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/pxa930.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/pxa930.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/pxa930.c	2011-03-14 21:20:32.000000000 -0400
@@ -192,7 +192,7 @@ static struct mfp_addr_map pxa935_mfp_ad
 
 static int __init pxa930_init(void)
 {
-	if (cpu_is_pxa930() || cpu_is_pxa935() || cpu_is_pxa950()) {
+	if (cpu_is_pxa93x()) {
 		mfp_init_base(io_p2v(MFPR_BASE));
 		mfp_init_addr(pxa930_mfp_addr_map);
 	}
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/pxa95x.c linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/pxa95x.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/pxa95x.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/pxa95x.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,308 @@
+/*
+ * linux/arch/arm/mach-pxa/pxa95x.c
+ *
+ * code specific to PXA95x aka MGx
+ *
+ * Copyright (C) 2009-2010 Marvell International 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/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/pm.h>
+#include <linux/platform_device.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <linux/sysdev.h>
+
+#include <mach/hardware.h>
+#include <mach/gpio.h>
+#include <mach/pxa3xx-regs.h>
+#include <mach/pxa930.h>
+#include <mach/reset.h>
+#include <mach/pm.h>
+#include <mach/dma.h>
+#include <mach/regs-intc.h>
+#include <plat/i2c.h>
+
+#include "generic.h"
+#include "devices.h"
+#include "clock.h"
+
+static struct mfp_addr_map pxa95x_mfp_addr_map[] __initdata = {
+
+	MFP_ADDR(GPIO0, 0x02e0),
+	MFP_ADDR(GPIO1, 0x02dc),
+	MFP_ADDR(GPIO2, 0x02e8),
+	MFP_ADDR(GPIO3, 0x02d8),
+	MFP_ADDR(GPIO4, 0x02e4),
+	MFP_ADDR(GPIO5, 0x02ec),
+	MFP_ADDR(GPIO6, 0x02f8),
+	MFP_ADDR(GPIO7, 0x02fc),
+	MFP_ADDR(GPIO8, 0x0300),
+	MFP_ADDR(GPIO9, 0x02d4),
+	MFP_ADDR(GPIO10, 0x02f4),
+	MFP_ADDR(GPIO11, 0x02f0),
+	MFP_ADDR(GPIO12, 0x0304),
+	MFP_ADDR(GPIO13, 0x0310),
+	MFP_ADDR(GPIO14, 0x0308),
+	MFP_ADDR(GPIO15, 0x030c),
+	MFP_ADDR(GPIO16, 0x04e8),
+	MFP_ADDR(GPIO17, 0x04f4),
+	MFP_ADDR(GPIO18, 0x04f8),
+	MFP_ADDR(GPIO19, 0x04fc),
+	MFP_ADDR(GPIO20, 0x0518),
+	MFP_ADDR(GPIO21, 0x051c),
+	MFP_ADDR(GPIO22, 0x04ec),
+	MFP_ADDR(GPIO23, 0x0500),
+	MFP_ADDR(GPIO24, 0x04f0),
+	MFP_ADDR(GPIO25, 0x0504),
+	MFP_ADDR(GPIO26, 0x0510),
+	MFP_ADDR(GPIO27, 0x0514),
+	MFP_ADDR(GPIO28, 0x0520),
+	MFP_ADDR(GPIO29, 0x0600),
+	MFP_ADDR(GPIO30, 0x0618),
+	MFP_ADDR(GPIO31, 0x0610),
+	MFP_ADDR(GPIO32, 0x060c),
+	MFP_ADDR(GPIO33, 0x061c),
+	MFP_ADDR(GPIO34, 0x0620),
+	MFP_ADDR(GPIO35, 0x0628),
+	MFP_ADDR(GPIO36, 0x062c),
+	MFP_ADDR(GPIO37, 0x0630),
+	MFP_ADDR(GPIO38, 0x0634),
+	MFP_ADDR(GPIO39, 0x0638),
+	MFP_ADDR(GPIO40, 0x063c),
+	MFP_ADDR(GPIO41, 0x0614),
+	MFP_ADDR(GPIO42, 0x0624),
+	MFP_ADDR(GPIO43, 0x0608),
+	MFP_ADDR(GPIO44, 0x0604),
+	MFP_ADDR(GPIO45, 0x050c),
+	MFP_ADDR(GPIO46, 0x0508),
+	MFP_ADDR(GPIO47, 0x02bc),
+	MFP_ADDR(GPIO48, 0x02b4),
+	MFP_ADDR(GPIO49, 0x02b8),
+	MFP_ADDR(GPIO50, 0x02c8),
+	MFP_ADDR(GPIO51, 0x02c0),
+	MFP_ADDR(GPIO52, 0x02c4),
+	MFP_ADDR(GPIO53, 0x02d0),
+	MFP_ADDR(GPIO54, 0x02cc),
+	MFP_ADDR(GPIO55, 0x029c),
+	MFP_ADDR(GPIO56, 0x02a0),
+	MFP_ADDR(GPIO57, 0x0294),
+	MFP_ADDR(GPIO58, 0x0298),
+	MFP_ADDR(GPIO59, 0x02a4),
+	MFP_ADDR(GPIO60, 0x02a8),
+	MFP_ADDR(GPIO61, 0x02b0),
+	MFP_ADDR(GPIO62, 0x02ac),
+	MFP_ADDR(GPIO63, 0x0640),
+	MFP_ADDR(GPIO64, 0x065c),
+	MFP_ADDR(GPIO65, 0x0648),
+	MFP_ADDR(GPIO66, 0x0644),
+	MFP_ADDR(GPIO67, 0x0674),
+	MFP_ADDR(GPIO68, 0x0658),
+	MFP_ADDR(GPIO69, 0x0654),
+	MFP_ADDR(GPIO70, 0x0660),
+	MFP_ADDR(GPIO71, 0x0668),
+	MFP_ADDR(GPIO72, 0x0664),
+	MFP_ADDR(GPIO73, 0x0650),
+	MFP_ADDR(GPIO74, 0x066c),
+	MFP_ADDR(GPIO75, 0x064c),
+	MFP_ADDR(GPIO76, 0x0670),
+	MFP_ADDR(GPIO77, 0x0678),
+	MFP_ADDR(GPIO78, 0x067c),
+	MFP_ADDR(GPIO79, 0x0694),
+	MFP_ADDR(GPIO80, 0x069c),
+	MFP_ADDR(GPIO81, 0x06a0),
+	MFP_ADDR(GPIO82, 0x06a4),
+	MFP_ADDR(GPIO83, 0x0698),
+	MFP_ADDR(GPIO84, 0x06bc),
+	MFP_ADDR(GPIO85, 0x06b4),
+	MFP_ADDR(GPIO86, 0x06b0),
+	MFP_ADDR(GPIO87, 0x06c0),
+	MFP_ADDR(GPIO88, 0x06c4),
+	MFP_ADDR(GPIO89, 0x06ac),
+	MFP_ADDR(GPIO90, 0x0680),
+	MFP_ADDR(GPIO91, 0x0684),
+	MFP_ADDR(GPIO92, 0x0688),
+	MFP_ADDR(GPIO93, 0x0690),
+	MFP_ADDR(GPIO94, 0x068c),
+	MFP_ADDR(GPIO95, 0x06a8),
+	MFP_ADDR(GPIO96, 0x06b8),
+	MFP_ADDR(GPIO97, 0x0410),
+	MFP_ADDR(GPIO98, 0x0418),
+	MFP_ADDR(GPIO99, 0x041c),
+	MFP_ADDR(GPIO100, 0x0414),
+	MFP_ADDR(GPIO101, 0x0408),
+	MFP_ADDR(GPIO102, 0x0324),
+	MFP_ADDR(GPIO103, 0x040c),
+	MFP_ADDR(GPIO104, 0x0400),
+	MFP_ADDR(GPIO105, 0x0328),
+	MFP_ADDR(GPIO106, 0x0404),
+
+	MFP_ADDR(GPIO159, 0x0524),
+	MFP_ADDR(GPIO163, 0x0534),
+	MFP_ADDR(GPIO167, 0x0544),
+	MFP_ADDR(GPIO168, 0x0548),
+	MFP_ADDR(GPIO169, 0x054c),
+	MFP_ADDR(GPIO170, 0x0550),
+	MFP_ADDR(GPIO171, 0x0554),
+	MFP_ADDR(GPIO172, 0x0558),
+	MFP_ADDR(GPIO173, 0x055c),
+
+	MFP_ADDR(nXCVREN, 0x0204),
+	MFP_ADDR(DF_CLE_nOE, 0x020c),
+	MFP_ADDR(DF_nADV1_ALE, 0x0218),
+	MFP_ADDR(DF_SCLK_E, 0x0214),
+	MFP_ADDR(DF_SCLK_S, 0x0210),
+	MFP_ADDR(nBE0, 0x021c),
+	MFP_ADDR(nBE1, 0x0220),
+	MFP_ADDR(DF_nADV2_ALE, 0x0224),
+	MFP_ADDR(DF_INT_RnB, 0x0228),
+	MFP_ADDR(DF_nCS0, 0x022c),
+	MFP_ADDR(DF_nCS1, 0x0230),
+	MFP_ADDR(nLUA, 0x0254),
+	MFP_ADDR(nLLA, 0x0258),
+	MFP_ADDR(DF_nWE, 0x0234),
+	MFP_ADDR(DF_nRE_nOE, 0x0238),
+	MFP_ADDR(DF_ADDR0, 0x024c),
+	MFP_ADDR(DF_ADDR1, 0x0250),
+	MFP_ADDR(DF_ADDR2, 0x025c),
+	MFP_ADDR(DF_ADDR3, 0x0260),
+	MFP_ADDR(DF_IO0, 0x023c),
+	MFP_ADDR(DF_IO1, 0x0240),
+	MFP_ADDR(DF_IO2, 0x0244),
+	MFP_ADDR(DF_IO3, 0x0248),
+	MFP_ADDR(DF_IO4, 0x0264),
+	MFP_ADDR(DF_IO5, 0x0268),
+	MFP_ADDR(DF_IO6, 0x026c),
+	MFP_ADDR(DF_IO7, 0x0270),
+	MFP_ADDR(DF_IO8, 0x0274),
+	MFP_ADDR(DF_IO9, 0x0278),
+	MFP_ADDR(DF_IO10, 0x027c),
+	MFP_ADDR(DF_IO11, 0x0280),
+	MFP_ADDR(DF_IO12, 0x0284),
+	MFP_ADDR(DF_IO13, 0x0288),
+	MFP_ADDR(DF_IO14, 0x028c),
+	MFP_ADDR(DF_IO15, 0x0290),
+
+	MFP_ADDR(GSIM_UIO, 0x0314),
+	MFP_ADDR(GSIM_UCLK, 0x0318),
+	MFP_ADDR(GSIM_UDET, 0x031c),
+	MFP_ADDR(GSIM_nURST, 0x0320),
+
+	MFP_ADDR(PMIC_INT, 0x06c8),
+
+	MFP_ADDR(RDY, 0x0200),
+
+	MFP_ADDR_END,
+};
+
+static DEFINE_CK(pxa95x_lcd, LCD, &clk_pxa3xx_hsio_ops);
+static DEFINE_CLK(pxa95x_pout, &clk_pxa3xx_pout_ops, 13000000, 70);
+static DEFINE_PXA3_CKEN(pxa95x_ffuart, FFUART, 14857000, 1);
+static DEFINE_PXA3_CKEN(pxa95x_btuart, BTUART, 14857000, 1);
+static DEFINE_PXA3_CKEN(pxa95x_stuart, STUART, 14857000, 1);
+static DEFINE_PXA3_CKEN(pxa95x_i2c, I2C, 32842000, 0);
+static DEFINE_PXA3_CKEN(pxa95x_keypad, KEYPAD, 32768, 0);
+static DEFINE_PXA3_CKEN(pxa95x_ssp1, SSP1, 13000000, 0);
+static DEFINE_PXA3_CKEN(pxa95x_ssp2, SSP2, 13000000, 0);
+static DEFINE_PXA3_CKEN(pxa95x_ssp3, SSP3, 13000000, 0);
+static DEFINE_PXA3_CKEN(pxa95x_ssp4, SSP4, 13000000, 0);
+static DEFINE_PXA3_CKEN(pxa95x_pwm0, PWM0, 13000000, 0);
+static DEFINE_PXA3_CKEN(pxa95x_pwm1, PWM1, 13000000, 0);
+
+static struct clk_lookup pxa95x_clkregs[] = {
+	INIT_CLKREG(&clk_pxa95x_pout, NULL, "CLK_POUT"),
+	/* Power I2C clock is always on */
+	INIT_CLKREG(&clk_dummy, "pxa3xx-pwri2c.1", NULL),
+	INIT_CLKREG(&clk_pxa95x_lcd, "pxa2xx-fb", NULL),
+	INIT_CLKREG(&clk_pxa95x_ffuart, "pxa2xx-uart.0", NULL),
+	INIT_CLKREG(&clk_pxa95x_btuart, "pxa2xx-uart.1", NULL),
+	INIT_CLKREG(&clk_pxa95x_stuart, "pxa2xx-uart.2", NULL),
+	INIT_CLKREG(&clk_pxa95x_stuart, "pxa2xx-ir", "UARTCLK"),
+	INIT_CLKREG(&clk_pxa95x_i2c, "pxa2xx-i2c.0", NULL),
+	INIT_CLKREG(&clk_pxa95x_keypad, "pxa27x-keypad", NULL),
+	INIT_CLKREG(&clk_pxa95x_ssp1, "pxa27x-ssp.0", NULL),
+	INIT_CLKREG(&clk_pxa95x_ssp2, "pxa27x-ssp.1", NULL),
+	INIT_CLKREG(&clk_pxa95x_ssp3, "pxa27x-ssp.2", NULL),
+	INIT_CLKREG(&clk_pxa95x_ssp4, "pxa27x-ssp.3", NULL),
+	INIT_CLKREG(&clk_pxa95x_pwm0, "pxa27x-pwm.0", NULL),
+	INIT_CLKREG(&clk_pxa95x_pwm1, "pxa27x-pwm.1", NULL),
+};
+
+void __init pxa95x_init_irq(void)
+{
+	pxa_init_irq(96, NULL);
+	pxa_init_gpio(IRQ_GPIO_2_x, 2, 127, NULL);
+}
+
+/*
+ * device registration specific to PXA93x.
+ */
+
+void __init pxa95x_set_i2c_power_info(struct i2c_pxa_platform_data *info)
+{
+	pxa_register_device(&pxa3xx_device_i2c_power, info);
+}
+
+static struct platform_device *devices[] __initdata = {
+	&sa1100_device_rtc,
+	&pxa_device_rtc,
+	&pxa27x_device_ssp1,
+	&pxa27x_device_ssp2,
+	&pxa27x_device_ssp3,
+	&pxa3xx_device_ssp4,
+	&pxa27x_device_pwm0,
+	&pxa27x_device_pwm1,
+};
+
+static struct sys_device pxa95x_sysdev[] = {
+	{
+		.cls	= &pxa_irq_sysclass,
+	}, {
+		.cls	= &pxa_gpio_sysclass,
+	}, {
+		.cls	= &pxa3xx_clock_sysclass,
+	}
+};
+
+static int __init pxa95x_init(void)
+{
+	int ret = 0, i;
+
+	if (cpu_is_pxa95x()) {
+		mfp_init_base(io_p2v(MFPR_BASE));
+		mfp_init_addr(pxa95x_mfp_addr_map);
+
+		reset_status = ARSR;
+
+		/*
+		 * clear RDH bit every time after reset
+		 *
+		 * Note: the last 3 bits DxS are write-1-to-clear so carefully
+		 * preserve them here in case they will be referenced later
+		 */
+		ASCR &= ~(ASCR_RDH | ASCR_D1S | ASCR_D2S | ASCR_D3S);
+
+		clkdev_add_table(pxa95x_clkregs, ARRAY_SIZE(pxa95x_clkregs));
+
+		if ((ret = pxa_init_dma(IRQ_DMA, 32)))
+			return ret;
+
+		for (i = 0; i < ARRAY_SIZE(pxa95x_sysdev); i++) {
+			ret = sysdev_register(&pxa95x_sysdev[i]);
+			if (ret)
+				pr_err("failed to register sysdev[%d]\n", i);
+		}
+
+		ret = platform_add_devices(devices, ARRAY_SIZE(devices));
+	}
+
+	return ret;
+}
+
+postcore_initcall(pxa95x_init);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/raumfeld.c linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/raumfeld.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/raumfeld.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/raumfeld.c	2011-03-14 21:20:32.000000000 -0400
@@ -588,6 +588,9 @@ static struct pxafb_mach_info raumfeld_s
 	.num_modes	= 1,
 	.video_mem_size = 0x400000,
 	.lcd_conn	= LCD_COLOR_TFT_16BPP | LCD_PCLK_EDGE_FALL,
+#ifdef CONFIG_PXA3XX_GCU
+	.acceleration_enabled = 1,
+#endif
 };
 
 static void __init raumfeld_lcd_init(void)
@@ -616,6 +619,8 @@ static void __init raumfeld_lcd_init(voi
 		pr_warning("Unable to request GPIO_DISPLAY_ENABLE\n");
 	else
 		gpio_direction_output(GPIO_DISPLAY_ENABLE, 1);
+
+	platform_device_register(&pxa3xx_device_gcu);
 }
 
 /**
@@ -1085,7 +1090,7 @@ static void __init raumfeld_speaker_init
 MACHINE_START(RAUMFELD_RC, "Raumfeld Controller")
 	.boot_params	= RAUMFELD_SDRAM_BASE + 0x100,
 	.init_machine	= raumfeld_controller_init,
-	.map_io		= pxa_map_io,
+	.map_io		= pxa3xx_map_io,
 	.init_irq	= pxa3xx_init_irq,
 	.timer		= &pxa_timer,
 MACHINE_END
@@ -1095,7 +1100,7 @@ MACHINE_END
 MACHINE_START(RAUMFELD_CONNECTOR, "Raumfeld Connector")
 	.boot_params	= RAUMFELD_SDRAM_BASE + 0x100,
 	.init_machine	= raumfeld_connector_init,
-	.map_io		= pxa_map_io,
+	.map_io		= pxa3xx_map_io,
 	.init_irq	= pxa3xx_init_irq,
 	.timer		= &pxa_timer,
 MACHINE_END
@@ -1105,7 +1110,7 @@ MACHINE_END
 MACHINE_START(RAUMFELD_SPEAKER, "Raumfeld Speaker")
 	.boot_params	= RAUMFELD_SDRAM_BASE + 0x100,
 	.init_machine	= raumfeld_speaker_init,
-	.map_io		= pxa_map_io,
+	.map_io		= pxa3xx_map_io,
 	.init_irq	= pxa3xx_init_irq,
 	.timer		= &pxa_timer,
 MACHINE_END
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/saarb.c linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/saarb.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/saarb.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/saarb.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,114 @@
+/*
+ *  linux/arch/arm/mach-pxa/saarb.c
+ *
+ *  Support for the Marvell Handheld Platform (aka SAARB)
+ *
+ *  Copyright (C) 2007-2010 Marvell International 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
+ *  publishhed by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/i2c.h>
+#include <linux/mfd/88pm860x.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+
+#include <mach/irqs.h>
+#include <mach/hardware.h>
+#include <mach/mfp.h>
+#include <mach/mfp-pxa930.h>
+#include <mach/gpio.h>
+
+#include <plat/i2c.h>
+
+#include "generic.h"
+
+#define SAARB_NR_IRQS	(IRQ_BOARD_START + 40)
+
+static struct pm860x_touch_pdata saarb_touch = {
+	.gpadc_prebias	= 1,
+	.slot_cycle	= 1,
+	.tsi_prebias	= 6,
+	.pen_prebias	= 16,
+	.pen_prechg	= 2,
+	.res_x		= 300,
+};
+
+static struct pm860x_backlight_pdata saarb_backlight[] = {
+	{
+		.id	= PM8606_ID_BACKLIGHT,
+		.iset	= PM8606_WLED_CURRENT(24),
+		.flags	= PM8606_BACKLIGHT1,
+	},
+	{},
+};
+
+static struct pm860x_led_pdata saarb_led[] = {
+	{
+		.id	= PM8606_ID_LED,
+		.iset	= PM8606_LED_CURRENT(12),
+		.flags	= PM8606_LED1_RED,
+	}, {
+		.id	= PM8606_ID_LED,
+		.iset	= PM8606_LED_CURRENT(12),
+		.flags	= PM8606_LED1_GREEN,
+	}, {
+		.id	= PM8606_ID_LED,
+		.iset	= PM8606_LED_CURRENT(12),
+		.flags	= PM8606_LED1_BLUE,
+	}, {
+		.id	= PM8606_ID_LED,
+		.iset	= PM8606_LED_CURRENT(12),
+		.flags	= PM8606_LED2_RED,
+	}, {
+		.id	= PM8606_ID_LED,
+		.iset	= PM8606_LED_CURRENT(12),
+		.flags	= PM8606_LED2_GREEN,
+	}, {
+		.id	= PM8606_ID_LED,
+		.iset	= PM8606_LED_CURRENT(12),
+		.flags	= PM8606_LED2_BLUE,
+	},
+};
+
+static struct pm860x_platform_data saarb_pm8607_info = {
+	.touch		= &saarb_touch,
+	.backlight	= &saarb_backlight[0],
+	.led		= &saarb_led[0],
+	.companion_addr	= 0x10,
+	.irq_mode	= 0,
+	.irq_base	= IRQ_BOARD_START,
+
+	.i2c_port	= GI2C_PORT,
+};
+
+static struct i2c_board_info saarb_i2c_info[] = {
+	{
+		.type		= "88PM860x",
+		.addr		= 0x34,
+		.platform_data	= &saarb_pm8607_info,
+		.irq		= gpio_to_irq(mfp_to_gpio(MFP_PIN_GPIO83)),
+	},
+};
+
+static void __init saarb_init(void)
+{
+	pxa_set_ffuart_info(NULL);
+	pxa_set_i2c_info(NULL);
+	i2c_register_board_info(0, ARRAY_AND_SIZE(saarb_i2c_info));
+}
+
+MACHINE_START(SAARB, "PXA955 Handheld Platform (aka SAARB)")
+	.boot_params    = 0xa0000100,
+	.map_io         = pxa_map_io,
+	.nr_irqs	= SAARB_NR_IRQS,
+	.init_irq       = pxa95x_init_irq,
+	.timer          = &pxa_timer,
+	.init_machine   = saarb_init,
+MACHINE_END
+
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/saar.c linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/saar.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/saar.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/saar.c	2011-03-14 21:20:32.000000000 -0400
@@ -597,7 +597,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,
-	.map_io         = pxa_map_io,
+	.map_io         = pxa3xx_map_io,
 	.init_irq       = pxa3xx_init_irq,
 	.timer          = &pxa_timer,
 	.init_machine   = saar_init,
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/sharpsl_pm.c linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/sharpsl_pm.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/sharpsl_pm.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/sharpsl_pm.c	2011-03-14 21:20:32.000000000 -0400
@@ -579,7 +579,8 @@ static int sharpsl_ac_check(void)
 static int sharpsl_pm_suspend(struct platform_device *pdev, pm_message_t state)
 {
 	sharpsl_pm.flags |= SHARPSL_SUSPENDED;
-	flush_scheduled_work();
+	flush_delayed_work_sync(&toggle_charger);
+	flush_delayed_work_sync(&sharpsl_bat);
 
 	if (sharpsl_pm.charge_mode == CHRG_ON)
 		sharpsl_pm.flags |= SHARPSL_DO_OFFLINE_CHRG;
@@ -868,7 +869,7 @@ static void sharpsl_apm_get_power_status
 }
 
 #ifdef CONFIG_PM
-static struct platform_suspend_ops sharpsl_pm_ops = {
+static const struct platform_suspend_ops sharpsl_pm_ops = {
 	.prepare	= pxa_pm_prepare,
 	.finish		= pxa_pm_finish,
 	.enter		= corgi_pxa_pm_enter,
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/sleep.S linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/sleep.S
--- linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/sleep.S	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/sleep.S	2011-03-14 21:20:32.000000000 -0400
@@ -14,7 +14,7 @@
 #include <linux/linkage.h>
 #include <asm/assembler.h>
 #include <mach/hardware.h>
-
+#include <mach/smemc.h>
 #include <mach/pxa2xx-regs.h>
 
 #define MDREFR_KDIV	0x200a4000	// all banks
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/smemc.c linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/smemc.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/smemc.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/smemc.c	2011-03-14 21:20:32.000000000 -0400
@@ -9,50 +9,37 @@
 #include <linux/sysdev.h>
 
 #include <mach/hardware.h>
-
-#define SMEMC_PHYS_BASE	(0x4A000000)
-#define SMEMC_PHYS_SIZE	(0x90)
-
-#define MSC0		(0x08)	/* Static Memory Controller Register 0 */
-#define MSC1		(0x0C)	/* Static Memory Controller Register 1 */
-#define SXCNFG		(0x1C)	/* Synchronous Static Memory Control Register */
-#define MEMCLKCFG	(0x68)	/* Clock Configuration */
-#define CSADRCFG0	(0x80)	/* Address Configuration Register for CS0 */
-#define CSADRCFG1	(0x84)	/* Address Configuration Register for CS1 */
-#define CSADRCFG2	(0x88)	/* Address Configuration Register for CS2 */
-#define CSADRCFG3	(0x8C)	/* Address Configuration Register for CS3 */
+#include <mach/smemc.h>
 
 #ifdef CONFIG_PM
-static void __iomem *smemc_mmio_base;
-
 static unsigned long msc[2];
 static unsigned long sxcnfg, memclkcfg;
 static unsigned long csadrcfg[4];
 
 static int pxa3xx_smemc_suspend(struct sys_device *dev, pm_message_t state)
 {
-	msc[0] = __raw_readl(smemc_mmio_base + MSC0);
-	msc[1] = __raw_readl(smemc_mmio_base + MSC1);
-	sxcnfg = __raw_readl(smemc_mmio_base + SXCNFG);
-	memclkcfg = __raw_readl(smemc_mmio_base + MEMCLKCFG);
-	csadrcfg[0] = __raw_readl(smemc_mmio_base + CSADRCFG0);
-	csadrcfg[1] = __raw_readl(smemc_mmio_base + CSADRCFG1);
-	csadrcfg[2] = __raw_readl(smemc_mmio_base + CSADRCFG2);
-	csadrcfg[3] = __raw_readl(smemc_mmio_base + CSADRCFG3);
+	msc[0] = __raw_readl(MSC0);
+	msc[1] = __raw_readl(MSC1);
+	sxcnfg = __raw_readl(SXCNFG);
+	memclkcfg = __raw_readl(MEMCLKCFG);
+	csadrcfg[0] = __raw_readl(CSADRCFG0);
+	csadrcfg[1] = __raw_readl(CSADRCFG1);
+	csadrcfg[2] = __raw_readl(CSADRCFG2);
+	csadrcfg[3] = __raw_readl(CSADRCFG3);
 
 	return 0;
 }
 
 static int pxa3xx_smemc_resume(struct sys_device *dev)
 {
-	__raw_writel(msc[0], smemc_mmio_base + MSC0);
-	__raw_writel(msc[1], smemc_mmio_base + MSC1);
-	__raw_writel(sxcnfg, smemc_mmio_base + SXCNFG);
-	__raw_writel(memclkcfg, smemc_mmio_base + MEMCLKCFG);
-	__raw_writel(csadrcfg[0], smemc_mmio_base + CSADRCFG0);
-	__raw_writel(csadrcfg[1], smemc_mmio_base + CSADRCFG1);
-	__raw_writel(csadrcfg[2], smemc_mmio_base + CSADRCFG2);
-	__raw_writel(csadrcfg[3], smemc_mmio_base + CSADRCFG3);
+	__raw_writel(msc[0], MSC0);
+	__raw_writel(msc[1], MSC1);
+	__raw_writel(sxcnfg, SXCNFG);
+	__raw_writel(memclkcfg, MEMCLKCFG);
+	__raw_writel(csadrcfg[0], CSADRCFG0);
+	__raw_writel(csadrcfg[1], CSADRCFG1);
+	__raw_writel(csadrcfg[2], CSADRCFG2);
+	__raw_writel(csadrcfg[3], CSADRCFG3);
 
 	return 0;
 }
@@ -73,10 +60,6 @@ static int __init smemc_init(void)
 	int ret = 0;
 
 	if (cpu_is_pxa3xx()) {
-		smemc_mmio_base = ioremap(SMEMC_PHYS_BASE, SMEMC_PHYS_SIZE);
-		if (smemc_mmio_base == NULL)
-			return -ENODEV;
-
 		ret = sysdev_class_register(&smemc_sysclass);
 		if (ret)
 			return ret;
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/spitz.c linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/spitz.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/spitz.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/spitz.c	2011-03-14 21:20:32.000000000 -0400
@@ -23,10 +23,12 @@
 #include <linux/spi/spi.h>
 #include <linux/spi/ads7846.h>
 #include <linux/spi/corgi_lcd.h>
-#include <linux/mtd/physmap.h>
+#include <linux/spi/pxa2xx_spi.h>
 #include <linux/mtd/sharpsl.h>
+#include <linux/mtd/physmap.h>
 #include <linux/input/matrix_keypad.h>
 #include <linux/regulator/machine.h>
+#include <linux/io.h>
 
 #include <asm/setup.h>
 #include <asm/mach-types.h>
@@ -41,9 +43,9 @@
 #include <mach/mmc.h>
 #include <mach/ohci.h>
 #include <mach/pxafb.h>
-#include <mach/pxa2xx_spi.h>
 #include <mach/spitz.h>
 #include <mach/sharpsl_pm.h>
+#include <mach/smemc.h>
 
 #include <plat/i2c.h>
 
@@ -929,9 +931,10 @@ static void spitz_poweroff(void)
 
 static void spitz_restart(char mode, const char *cmd)
 {
+	uint32_t msc0 = __raw_readl(MSC0);
 	/* Bootloader magic for a reboot */
-	if ((MSC0 & 0xffff0000) == 0x7ff00000)
-		MSC0 = (MSC0 & 0xffff) | 0x7ee00000;
+	if ((msc0 & 0xffff0000) == 0x7ff00000)
+		__raw_writel((msc0 & 0xffff) | 0x7ee00000, MSC0);
 
 	spitz_poweroff();
 }
@@ -980,7 +983,7 @@ static void __init spitz_fixup(struct ma
 #ifdef CONFIG_MACH_SPITZ
 MACHINE_START(SPITZ, "SHARP Spitz")
 	.fixup		= spitz_fixup,
-	.map_io		= pxa_map_io,
+	.map_io		= pxa27x_map_io,
 	.init_irq	= pxa27x_init_irq,
 	.init_machine	= spitz_init,
 	.timer		= &pxa_timer,
@@ -990,7 +993,7 @@ MACHINE_END
 #ifdef CONFIG_MACH_BORZOI
 MACHINE_START(BORZOI, "SHARP Borzoi")
 	.fixup		= spitz_fixup,
-	.map_io		= pxa_map_io,
+	.map_io		= pxa27x_map_io,
 	.init_irq	= pxa27x_init_irq,
 	.init_machine	= spitz_init,
 	.timer		= &pxa_timer,
@@ -1000,7 +1003,7 @@ MACHINE_END
 #ifdef CONFIG_MACH_AKITA
 MACHINE_START(AKITA, "SHARP Akita")
 	.fixup		= spitz_fixup,
-	.map_io		= pxa_map_io,
+	.map_io		= pxa27x_map_io,
 	.init_irq	= pxa27x_init_irq,
 	.init_machine	= spitz_init,
 	.timer		= &pxa_timer,
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/stargate2.c linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/stargate2.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/stargate2.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/stargate2.c	2011-03-14 21:20:32.000000000 -0400
@@ -46,10 +46,11 @@
 #include <plat/i2c.h>
 #include <mach/mmc.h>
 #include <mach/udc.h>
-#include <mach/pxa2xx_spi.h>
 #include <mach/pxa27x-udc.h>
+#include <mach/smemc.h>
 
 #include <linux/spi/spi.h>
+#include <linux/spi/pxa2xx_spi.h>
 #include <linux/mfd/da903x.h>
 #include <linux/sht15.h>
 
@@ -976,7 +977,7 @@ static void __init stargate2_init(void)
 {
 	/* This is probably a board specific hack as this must be set
 	   prior to connecting the MFP stuff up. */
-	MECR &= ~MECR_NOS;
+	__raw_writel(__raw_readl(MECR) & ~MECR_NOS, MECR);
 
 	pxa2xx_mfp_config(ARRAY_AND_SIZE(stargate2_pin_config));
 
@@ -998,7 +999,7 @@ static void __init stargate2_init(void)
 
 #ifdef CONFIG_MACH_INTELMOTE2
 MACHINE_START(INTELMOTE2, "IMOTE 2")
-	.map_io		= pxa_map_io,
+	.map_io		= pxa27x_map_io,
 	.init_irq	= pxa27x_init_irq,
 	.timer		= &pxa_timer,
 	.init_machine	= imote2_init,
@@ -1008,7 +1009,7 @@ MACHINE_END
 
 #ifdef CONFIG_MACH_STARGATE2
 MACHINE_START(STARGATE2, "Stargate 2")
-	.map_io = pxa_map_io,
+	.map_io = pxa27x_map_io,
 	.nr_irqs = STARGATE_NR_IRQS,
 	.init_irq = pxa27x_init_irq,
 	.timer = &pxa_timer,
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/tavorevb3.c linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/tavorevb3.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/tavorevb3.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/tavorevb3.c	2011-03-14 21:20:32.000000000 -0400
@@ -127,7 +127,7 @@ static void __init evb3_init(void)
 
 MACHINE_START(TAVOREVB3, "PXA950 Evaluation Board (aka TavorEVB3)")
 	.boot_params	= 0xa0000100,
-	.map_io         = pxa_map_io,
+	.map_io         = pxa3xx_map_io,
 	.nr_irqs	= TAVOREVB3_NR_IRQS,
 	.init_irq       = pxa3xx_init_irq,
 	.timer          = &pxa_timer,
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/tavorevb.c linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/tavorevb.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/tavorevb.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/tavorevb.c	2011-03-14 21:20:32.000000000 -0400
@@ -490,7 +490,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,
-	.map_io         = pxa_map_io,
+	.map_io         = pxa3xx_map_io,
 	.init_irq       = pxa3xx_init_irq,
 	.timer          = &pxa_timer,
 	.init_machine   = tavorevb_init,
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/time.c linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/time.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/time.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/time.c	2011-03-14 21:20:32.000000000 -0400
@@ -17,11 +17,11 @@
 #include <linux/interrupt.h>
 #include <linux/clockchips.h>
 #include <linux/sched.h>
-#include <linux/cnt32_to_63.h>
 
 #include <asm/div64.h>
 #include <asm/mach/irq.h>
 #include <asm/mach/time.h>
+#include <asm/sched_clock.h>
 #include <mach/regs-ost.h>
 
 /*
@@ -32,29 +32,18 @@
  * long as there is always less than 582 seconds between successive
  * calls to sched_clock() which should always be the case in practice.
  */
+static DEFINE_CLOCK_DATA(cd);
 
-#define OSCR2NS_SCALE_FACTOR 10
-
-static unsigned long oscr2ns_scale;
-
-static void __init set_oscr2ns_scale(unsigned long oscr_rate)
+unsigned long long notrace sched_clock(void)
 {
-	unsigned long long v = 1000000000ULL << OSCR2NS_SCALE_FACTOR;
-	do_div(v, oscr_rate);
-	oscr2ns_scale = v;
-	/*
-	 * We want an even value to automatically clear the top bit
-	 * returned by cnt32_to_63() without an additional run time
-	 * instruction. So if the LSB is 1 then round it up.
-	 */
-	if (oscr2ns_scale & 1)
-		oscr2ns_scale++;
+	u32 cyc = OSCR;
+	return cyc_to_sched_clock(&cd, cyc, (u32)~0);
 }
 
-unsigned long long sched_clock(void)
+static void notrace pxa_update_sched_clock(void)
 {
-	unsigned long long v = cnt32_to_63(OSCR);
-	return (v * oscr2ns_scale) >> OSCR2NS_SCALE_FACTOR;
+	u32 cyc = OSCR;
+	update_sched_clock(&cd, cyc, (u32)~0);
 }
 
 
@@ -127,7 +116,6 @@ static struct clocksource cksrc_pxa_oscr
 	.rating         = 200,
 	.read           = pxa_read_oscr,
 	.mask           = CLOCKSOURCE_MASK(32),
-	.shift          = 20,
 	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
@@ -145,7 +133,7 @@ static void __init pxa_timer_init(void)
 	OIER = 0;
 	OSSR = OSSR_M0 | OSSR_M1 | OSSR_M2 | OSSR_M3;
 
-	set_oscr2ns_scale(clock_tick_rate);
+	init_sched_clock(&cd, pxa_update_sched_clock, 32, clock_tick_rate);
 
 	ckevt_pxa_osmr0.mult =
 		div_sc(clock_tick_rate, NSEC_PER_SEC, ckevt_pxa_osmr0.shift);
@@ -155,12 +143,9 @@ static void __init pxa_timer_init(void)
 		clockevent_delta2ns(MIN_OSCR_DELTA * 2, &ckevt_pxa_osmr0) + 1;
 	ckevt_pxa_osmr0.cpumask = cpumask_of(0);
 
-	cksrc_pxa_oscr0.mult =
-		clocksource_hz2mult(clock_tick_rate, cksrc_pxa_oscr0.shift);
-
 	setup_irq(IRQ_OST0, &pxa_ost0_irq);
 
-	clocksource_register(&cksrc_pxa_oscr0);
+	clocksource_register_hz(&cksrc_pxa_oscr0, clock_tick_rate);
 	clockevents_register_device(&ckevt_pxa_osmr0);
 }
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/tosa-bt.c linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/tosa-bt.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/tosa-bt.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/tosa-bt.c	2011-03-14 21:20:32.000000000 -0400
@@ -81,8 +81,6 @@ static int tosa_bt_probe(struct platform
 		goto err_rfk_alloc;
 	}
 
-	rfkill_set_led_trigger_name(rfk, "tosa-bt");
-
 	rc = rfkill_register(rfk);
 	if (rc)
 		goto err_rfkill;
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/tosa.c linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/tosa.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/tosa.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/tosa.c	2011-03-14 21:20:32.000000000 -0400
@@ -32,6 +32,7 @@
 #include <linux/gpio.h>
 #include <linux/pda_power.h>
 #include <linux/spi/spi.h>
+#include <linux/spi/pxa2xx_spi.h>
 #include <linux/input/matrix_keypad.h>
 
 #include <asm/setup.h>
@@ -44,8 +45,8 @@
 #include <mach/mmc.h>
 #include <mach/udc.h>
 #include <mach/tosa_bt.h>
-#include <mach/pxa2xx_spi.h>
 #include <mach/audio.h>
+#include <mach/smemc.h>
 
 #include <asm/mach/arch.h>
 #include <mach/tosa.h>
@@ -874,6 +875,11 @@ static struct platform_device sharpsl_ro
 	.dev.platform_data = &sharpsl_rom_data,
 };
 
+static struct platform_device wm9712_device = {
+	.name	= "wm9712-codec",
+	.id	= -1,
+};
+
 static struct platform_device *devices[] __initdata = {
 	&tosascoop_device,
 	&tosascoop_jc_device,
@@ -884,6 +890,7 @@ static struct platform_device *devices[]
 	&tosaled_device,
 	&tosa_bt_device,
 	&sharpsl_rom_device,
+	&wm9712_device,
 };
 
 static void tosa_poweroff(void)
@@ -893,9 +900,11 @@ static void tosa_poweroff(void)
 
 static void tosa_restart(char mode, const char *cmd)
 {
+	uint32_t msc0 = __raw_readl(MSC0);
+
 	/* Bootloader magic for a reboot */
-	if((MSC0 & 0xffff0000) == 0x7ff00000)
-		MSC0 = (MSC0 & 0xffff) | 0x7ee00000;
+	if((msc0 & 0xffff0000) == 0x7ff00000)
+		__raw_writel((msc0 & 0xffff) | 0x7ee00000, MSC0);
 
 	tosa_poweroff();
 }
@@ -953,7 +962,7 @@ static void __init fixup_tosa(struct mac
 
 MACHINE_START(TOSA, "SHARP Tosa")
 	.fixup          = fixup_tosa,
-	.map_io         = pxa_map_io,
+	.map_io         = pxa25x_map_io,
 	.nr_irqs	= TOSA_NR_IRQS,
 	.init_irq       = pxa25x_init_irq,
 	.init_machine   = tosa_init,
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/trizeps4.c linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/trizeps4.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/trizeps4.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/trizeps4.c	2011-03-14 21:20:32.000000000 -0400
@@ -40,13 +40,13 @@
 #include <asm/mach/flash.h>
 
 #include <mach/pxa27x.h>
-#include <mach/pxa2xx_spi.h>
 #include <mach/trizeps4.h>
 #include <mach/audio.h>
 #include <mach/pxafb.h>
 #include <mach/mmc.h>
 #include <mach/irda.h>
 #include <mach/ohci.h>
+#include <mach/smemc.h>
 #include <plat/i2c.h>
 
 #include "generic.h"
@@ -539,10 +539,10 @@ static void __init trizeps4_init(void)
 
 static void __init trizeps4_map_io(void)
 {
-	pxa_map_io();
+	pxa27x_map_io();
 	iotable_init(trizeps4_io_desc, ARRAY_SIZE(trizeps4_io_desc));
 
-	if ((MSC0 & 0x8) && (BOOT_DEF & 0x1)) {
+	if ((__raw_readl(MSC0) & 0x8) && (__raw_readl(BOOT_DEF) & 0x1)) {
 		/* if flash is 16 bit wide its a Trizeps4 WL */
 		__machine_arch_type = MACH_TYPE_TRIZEPS4WL;
 		trizeps4_flash_data[0].width = 2;
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/viper.c linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/viper.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/viper.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/viper.c	2011-03-14 21:20:32.000000000 -0400
@@ -249,9 +249,9 @@ static inline int viper_bit_to_irq(int b
 	return viper_isa_irqs[bit] + PXA_ISA_IRQ(0);
 }
 
-static void viper_ack_irq(unsigned int irq)
+static void viper_ack_irq(struct irq_data *d)
 {
-	int viper_irq = viper_irq_to_bitmask(irq);
+	int viper_irq = viper_irq_to_bitmask(d->irq);
 
 	if (viper_irq & 0xff)
 		VIPER_LO_IRQ_STATUS = viper_irq;
@@ -259,14 +259,14 @@ static void viper_ack_irq(unsigned int i
 		VIPER_HI_IRQ_STATUS = (viper_irq >> 8);
 }
 
-static void viper_mask_irq(unsigned int irq)
+static void viper_mask_irq(struct irq_data *d)
 {
-	viper_irq_enabled_mask &= ~(viper_irq_to_bitmask(irq));
+	viper_irq_enabled_mask &= ~(viper_irq_to_bitmask(d->irq));
 }
 
-static void viper_unmask_irq(unsigned int irq)
+static void viper_unmask_irq(struct irq_data *d)
 {
-	viper_irq_enabled_mask |= viper_irq_to_bitmask(irq);
+	viper_irq_enabled_mask |= viper_irq_to_bitmask(d->irq);
 }
 
 static inline unsigned long viper_irq_pending(void)
@@ -283,7 +283,7 @@ static void viper_irq_handler(unsigned i
 	do {
 		/* we're in a chained irq handler,
 		 * so ack the interrupt by hand */
-		desc->chip->ack(irq);
+		desc->irq_data.chip->irq_ack(&desc->irq_data);
 
 		if (likely(pending)) {
 			irq = viper_bit_to_irq(__ffs(pending));
@@ -294,10 +294,10 @@ static void viper_irq_handler(unsigned i
 }
 
 static struct irq_chip viper_irq_chip = {
-	.name	= "ISA",
-	.ack	= viper_ack_irq,
-	.mask	= viper_mask_irq,
-	.unmask	= viper_unmask_irq
+	.name		= "ISA",
+	.irq_ack	= viper_ack_irq,
+	.irq_mask	= viper_mask_irq,
+	.irq_unmask	= viper_unmask_irq
 };
 
 static void __init viper_init_irq(void)
@@ -983,7 +983,7 @@ static struct map_desc viper_io_desc[] _
 
 static void __init viper_map_io(void)
 {
-	pxa_map_io();
+	pxa25x_map_io();
 
 	iotable_init(viper_io_desc, ARRAY_SIZE(viper_io_desc));
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/vpac270.c linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/vpac270.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/vpac270.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/vpac270.c	2011-03-14 21:20:32.000000000 -0400
@@ -719,7 +719,7 @@ static void __init vpac270_init(void)
 
 MACHINE_START(VPAC270, "Voipac PXA270")
 	.boot_params	= 0xa0000100,
-	.map_io		= pxa_map_io,
+	.map_io		= pxa27x_map_io,
 	.init_irq	= pxa27x_init_irq,
 	.timer		= &pxa_timer,
 	.init_machine	= vpac270_init
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/xcep.c linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/xcep.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/xcep.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/xcep.c	2011-03-14 21:20:32.000000000 -0400
@@ -31,6 +31,7 @@
 #include <mach/hardware.h>
 #include <mach/pxa2xx-regs.h>
 #include <mach/mfp-pxa25x.h>
+#include <mach/smemc.h>
 
 #include "generic.h"
 
@@ -172,9 +173,9 @@ static void __init xcep_init(void)
 
 	/* See Intel XScale Developer's Guide for details */
 	/* Set RDF and RDN to appropriate values (chip select 3 (smc91x)) */
-	MSC1 = (MSC1 & 0xffff) | 0xD5540000;
+	__raw_writel((__raw_readl(MSC1) & 0xffff) | 0xD5540000, MSC1);
 	/* Set RDF and RDN to appropriate values (chip select 5 (fpga)) */
-	MSC2 = (MSC2 & 0xffff) | 0x72A00000;
+	__raw_writel((__raw_readl(MSC2) & 0xffff) | 0x72A00000, MSC2);
 
 	platform_add_devices(ARRAY_AND_SIZE(devices));
 	pxa_set_i2c_info(&xcep_i2c_platform_data);
@@ -183,7 +184,7 @@ static void __init xcep_init(void)
 MACHINE_START(XCEP, "Iskratel XCEP")
 	.boot_params	= 0xa0000100,
 	.init_machine	= xcep_init,
-	.map_io		= pxa_map_io,
+	.map_io		= pxa25x_map_io,
 	.init_irq	= pxa25x_init_irq,
 	.timer		= &pxa_timer,
 MACHINE_END
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/z2.c linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/z2.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/z2.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/z2.c	2011-03-14 21:20:32.000000000 -0400
@@ -20,6 +20,7 @@
 #include <linux/z2_battery.h>
 #include <linux/dma-mapping.h>
 #include <linux/spi/spi.h>
+#include <linux/spi/pxa2xx_spi.h>
 #include <linux/spi/libertas_spi.h>
 #include <linux/spi/lms283gf05.h>
 #include <linux/power_supply.h>
@@ -38,7 +39,6 @@
 #include <mach/pxafb.h>
 #include <mach/mmc.h>
 #include <plat/pxa27x_keypad.h>
-#include <mach/pxa2xx_spi.h>
 
 #include <plat/i2c.h>
 
@@ -704,7 +704,7 @@ static void __init z2_init(void)
 
 MACHINE_START(ZIPIT2, "Zipit Z2")
 	.boot_params	= 0xa0000100,
-	.map_io		= pxa_map_io,
+	.map_io		= pxa27x_map_io,
 	.init_irq	= pxa27x_init_irq,
 	.timer		= &pxa_timer,
 	.init_machine	= z2_init,
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/zeus.c linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/zeus.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/zeus.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/zeus.c	2011-03-14 21:20:32.000000000 -0400
@@ -20,6 +20,7 @@
 #include <linux/dm9000.h>
 #include <linux/mmc/host.h>
 #include <linux/spi/spi.h>
+#include <linux/spi/pxa2xx_spi.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/physmap.h>
@@ -41,12 +42,12 @@
 #include <mach/pxa27x-udc.h>
 #include <mach/udc.h>
 #include <mach/pxafb.h>
-#include <mach/pxa2xx_spi.h>
 #include <mach/mfp-pxa27x.h>
 #include <mach/pm.h>
 #include <mach/audio.h>
 #include <mach/arcom-pcmcia.h>
 #include <mach/zeus.h>
+#include <mach/smemc.h>
 
 #include "generic.h"
 
@@ -82,19 +83,19 @@ static inline int zeus_bit_to_irq(int bi
 	return zeus_isa_irqs[bit] + PXA_ISA_IRQ(0);
 }
 
-static void zeus_ack_irq(unsigned int irq)
+static void zeus_ack_irq(struct irq_data *d)
 {
-	__raw_writew(zeus_irq_to_bitmask(irq), ZEUS_CPLD_ISA_IRQ);
+	__raw_writew(zeus_irq_to_bitmask(d->irq), ZEUS_CPLD_ISA_IRQ);
 }
 
-static void zeus_mask_irq(unsigned int irq)
+static void zeus_mask_irq(struct irq_data *d)
 {
-	zeus_irq_enabled_mask &= ~(zeus_irq_to_bitmask(irq));
+	zeus_irq_enabled_mask &= ~(zeus_irq_to_bitmask(d->irq));
 }
 
-static void zeus_unmask_irq(unsigned int irq)
+static void zeus_unmask_irq(struct irq_data *d)
 {
-	zeus_irq_enabled_mask |= zeus_irq_to_bitmask(irq);
+	zeus_irq_enabled_mask |= zeus_irq_to_bitmask(d->irq);
 }
 
 static inline unsigned long zeus_irq_pending(void)
@@ -110,7 +111,7 @@ static void zeus_irq_handler(unsigned in
 	do {
 		/* we're in a chained irq handler,
 		 * so ack the interrupt by hand */
-		desc->chip->ack(gpio_to_irq(ZEUS_ISA_GPIO));
+		desc->irq_data.chip->irq_ack(&desc->irq_data);
 
 		if (likely(pending)) {
 			irq = zeus_bit_to_irq(__ffs(pending));
@@ -121,10 +122,10 @@ static void zeus_irq_handler(unsigned in
 }
 
 static struct irq_chip zeus_irq_chip = {
-	.name	= "ISA",
-	.ack	= zeus_ack_irq,
-	.mask	= zeus_mask_irq,
-	.unmask	= zeus_unmask_irq,
+	.name		= "ISA",
+	.irq_ack	= zeus_ack_irq,
+	.irq_mask	= zeus_mask_irq,
+	.irq_unmask	= zeus_unmask_irq,
 };
 
 static void __init zeus_init_irq(void)
@@ -823,13 +824,16 @@ static mfp_cfg_t zeus_pin_config[] __ini
 static void __init zeus_init(void)
 {
 	u16 dm9000_msc = DM9K_MSC_VALUE;
+	u32 msc0, msc1;
 
 	system_rev = __raw_readw(ZEUS_CPLD_VERSION);
 	pr_info("Zeus CPLD V%dI%d\n", (system_rev & 0xf0) >> 4, (system_rev & 0x0f));
 
 	/* Fix timings for dm9000s (CS1/CS2)*/
-	MSC0 = (MSC0 & 0xffff) | (dm9000_msc << 16);
-	MSC1 = (MSC1 & 0xffff0000) | dm9000_msc;
+	msc0 = (__raw_readl(MSC0) & 0x0000ffff) | (dm9000_msc << 16);
+	msc1 = (__raw_readl(MSC1) & 0xffff0000) | dm9000_msc;
+	__raw_writel(msc0, MSC0);
+	__raw_writel(msc1, MSC1);
 
 	pm_power_off = zeus_power_off;
 	zeus_setup_apm();
@@ -883,7 +887,7 @@ static struct map_desc zeus_io_desc[] __
 
 static void __init zeus_map_io(void)
 {
-	pxa_map_io();
+	pxa27x_map_io();
 
 	iotable_init(zeus_io_desc, ARRAY_SIZE(zeus_io_desc));
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/zylonite.c linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/zylonite.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-pxa/zylonite.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-pxa/zylonite.c	2011-03-14 21:20:32.000000000 -0400
@@ -423,7 +423,7 @@ static void __init zylonite_init(void)
 
 MACHINE_START(ZYLONITE, "PXA3xx Platform Development Kit (aka Zylonite)")
 	.boot_params	= 0xa0000100,
-	.map_io		= pxa_map_io,
+	.map_io		= pxa3xx_map_io,
 	.nr_irqs	= ZYLONITE_NR_IRQS,
 	.init_irq	= pxa3xx_init_irq,
 	.timer		= &pxa_timer,
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-realview/core.c linux-libre-2.6.38-gnu1/arch/arm/mach-realview/core.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-realview/core.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-realview/core.c	2011-03-14 21:20:32.000000000 -0400
@@ -30,8 +30,8 @@
 #include <linux/ata_platform.h>
 #include <linux/amba/mmci.h>
 #include <linux/gfp.h>
+#include <linux/clkdev.h>
 
-#include <asm/clkdev.h>
 #include <asm/system.h>
 #include <mach/hardware.h>
 #include <asm/irq.h>
@@ -47,15 +47,13 @@
 
 #include <asm/hardware/gic.h>
 
-#include <mach/clkdev.h>
 #include <mach/platform.h>
 #include <mach/irqs.h>
-#include <plat/timer-sp.h>
+#include <asm/hardware/timer-sp.h>
 
-#include "core.h"
+#include <plat/sched_clock.h>
 
-/* used by entry-macro.S and platsmp.c */
-void __iomem *gic_cpu_base_addr;
+#include "core.h"
 
 #ifdef CONFIG_ZONE_DMA
 /*
@@ -658,6 +656,12 @@ void realview_leds_event(led_event_t led
 #endif	/* CONFIG_LEDS */
 
 /*
+ * The sched_clock counter
+ */
+#define REFCOUNTER		(__io_address(REALVIEW_SYS_BASE) + \
+				 REALVIEW_SYS_24MHz_OFFSET)
+
+/*
  * Where is the timer (VA)?
  */
 void __iomem *timer0_va_base;
@@ -672,6 +676,8 @@ void __init realview_timer_init(unsigned
 {
 	u32 val;
 
+	versatile_sched_clock_init(REFCOUNTER, 24000000);
+
 	/* 
 	 * set clock frequency: 
 	 *	REALVIEW_REFCLK is 32KHz
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-realview/core.h linux-libre-2.6.38-gnu1/arch/arm/mach-realview/core.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-realview/core.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-realview/core.h	2011-03-14 21:20:32.000000000 -0400
@@ -53,7 +53,6 @@ extern struct platform_device realview_i
 extern struct mmci_platform_data realview_mmc0_plat_data;
 extern struct mmci_platform_data realview_mmc1_plat_data;
 extern struct clcd_board clcd_plat_data;
-extern void __iomem *gic_cpu_base_addr;
 extern void __iomem *timer0_va_base;
 extern void __iomem *timer1_va_base;
 extern void __iomem *timer2_va_base;
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-realview/hotplug.c linux-libre-2.6.38-gnu1/arch/arm/mach-realview/hotplug.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-realview/hotplug.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-realview/hotplug.c	2011-03-14 21:20:32.000000000 -0400
@@ -11,14 +11,11 @@
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/smp.h>
-#include <linux/completion.h>
 
 #include <asm/cacheflush.h>
 
 extern volatile int pen_release;
 
-static DECLARE_COMPLETION(cpu_killed);
-
 static inline void cpu_enter_lowpower(void)
 {
 	unsigned int v;
@@ -34,10 +31,10 @@ static inline void cpu_enter_lowpower(vo
 	"	bic	%0, %0, #0x20\n"
 	"	mcr	p15, 0, %0, c1, c0, 1\n"
 	"	mrc	p15, 0, %0, c1, c0, 0\n"
-	"	bic	%0, %0, #0x04\n"
+	"	bic	%0, %0, %2\n"
 	"	mcr	p15, 0, %0, c1, c0, 0\n"
 	  : "=&r" (v)
-	  : "r" (0)
+	  : "r" (0), "Ir" (CR_C)
 	  : "cc");
 }
 
@@ -46,17 +43,17 @@ static inline void cpu_leave_lowpower(vo
 	unsigned int v;
 
 	asm volatile(	"mrc	p15, 0, %0, c1, c0, 0\n"
-	"	orr	%0, %0, #0x04\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, #0x20\n"
 	"	mcr	p15, 0, %0, c1, c0, 1\n"
 	  : "=&r" (v)
-	  :
+	  : "Ir" (CR_C)
 	  : "cc");
 }
 
-static inline void platform_do_lowpower(unsigned int cpu)
+static inline void platform_do_lowpower(unsigned int cpu, int *spurious)
 {
 	/*
 	 * there is no power-control hardware on this platform, so all
@@ -80,22 +77,19 @@ static inline void platform_do_lowpower(
 		}
 
 		/*
-		 * getting here, means that we have come out of WFI without
+		 * Getting here, means that we have come out of WFI without
 		 * having been woken up - this shouldn't happen
 		 *
-		 * The trouble is, letting people know about this is not really
-		 * possible, since we are currently running incoherently, and
-		 * therefore cannot safely call printk() or anything else
+		 * Just note it happening - when we're woken, we can report
+		 * its occurrence.
 		 */
-#ifdef DEBUG
-		printk("CPU%u: spurious wakeup call\n", cpu);
-#endif
+		(*spurious)++;
 	}
 }
 
 int platform_cpu_kill(unsigned int cpu)
 {
-	return wait_for_completion_timeout(&cpu_killed, 5000);
+	return 1;
 }
 
 /*
@@ -105,30 +99,22 @@ int platform_cpu_kill(unsigned int cpu)
  */
 void platform_cpu_die(unsigned int cpu)
 {
-#ifdef DEBUG
-	unsigned int this_cpu = hard_smp_processor_id();
-
-	if (cpu != this_cpu) {
-		printk(KERN_CRIT "Eek! platform_cpu_die running on %u, should be %u\n",
-			   this_cpu, cpu);
-		BUG();
-	}
-#endif
-
-	printk(KERN_NOTICE "CPU%u: shutdown\n", cpu);
-	complete(&cpu_killed);
+	int spurious = 0;
 
 	/*
 	 * we're ready for shutdown now, so do it
 	 */
 	cpu_enter_lowpower();
-	platform_do_lowpower(cpu);
+	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)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-realview/include/mach/entry-macro.S linux-libre-2.6.38-gnu1/arch/arm/mach-realview/include/mach/entry-macro.S
--- linux-libre-2.6.37-gnu1/arch/arm/mach-realview/include/mach/entry-macro.S	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-realview/include/mach/entry-macro.S	2011-03-14 21:20:32.000000000 -0400
@@ -8,74 +8,11 @@
  * warranty of any kind, whether express or implied.
  */
 #include <mach/hardware.h>
-#include <asm/hardware/gic.h>
+#include <asm/hardware/entry-macro-gic.S>
 
 		.macro	disable_fiq
 		.endm
 
-		.macro  get_irqnr_preamble, base, tmp
-		ldr	\base, =gic_cpu_base_addr
-		ldr	\base, [\base]
-		.endm
-
 		.macro  arch_ret_to_user, tmp1, tmp2
 		.endm
 
-		/*
-		 * The interrupt numbering scheme is defined in the
-		 * interrupt controller spec.  To wit:
-		 *
-		 * Interrupts 0-15 are IPI
-		 * 16-28 are reserved
-		 * 29-31 are local.  We allow 30 to be used for the watchdog.
-		 * 32-1020 are global
-		 * 1021-1022 are reserved
-		 * 1023 is "spurious" (no interrupt)
-		 *
-		 * For now, we ignore all local interrupts so only return an interrupt if it's
-		 * between 30 and 1020.  The test_for_ipi routine below will pick up on IPIs.
-		 *
-		 * A simple read from the controller will tell us the number of the highest
-                 * priority enabled interrupt.  We then just need to check whether it is in the
-		 * valid range for an IRQ (30-1020 inclusive).
-		 */
-
-		.macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
-
-		ldr     \irqstat, [\base, #GIC_CPU_INTACK] /* bits 12-10 = src CPU, 9-0 = int # */
-
-		ldr	\tmp, =1021
-
-		bic     \irqnr, \irqstat, #0x1c00
-
-		cmp     \irqnr, #29
-		cmpcc	\irqnr, \irqnr
-		cmpne	\irqnr, \tmp
-		cmpcs	\irqnr, \irqnr
-
-		.endm
-
-		/* We assume that irqstat (the raw value of the IRQ acknowledge
-		 * register) is preserved from the macro above.
-		 * If there is an IPI, we immediately signal end of interrupt on the
-		 * controller, since this requires the original irqstat value which
-		 * we won't easily be able to recreate later.
-		 */
-
-		.macro test_for_ipi, irqnr, irqstat, base, tmp
-		bic	\irqnr, \irqstat, #0x1c00
-		cmp	\irqnr, #16
-		strcc	\irqstat, [\base, #GIC_CPU_EOI]
-		cmpcs	\irqnr, \irqnr
-		.endm
-
-		/* As above, this assumes that irqstat and base are preserved.. */
-
-		.macro test_for_ltirq, irqnr, irqstat, base, tmp
-		bic	\irqnr, \irqstat, #0x1c00
-		mov 	\tmp, #0
-		cmp	\irqnr, #29
-		moveq	\tmp, #1
-		streq	\irqstat, [\base, #GIC_CPU_EOI]
-		cmp	\tmp, #0
-		.endm
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-realview/include/mach/smp.h linux-libre-2.6.38-gnu1/arch/arm/mach-realview/include/mach/smp.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-realview/include/mach/smp.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-realview/include/mach/smp.h	2011-03-14 21:20:32.000000000 -0400
@@ -2,14 +2,13 @@
 #define ASMARM_ARCH_SMP_H
 
 #include <asm/hardware/gic.h>
-#include <asm/smp_mpidr.h>
 
 /*
  * We use IRQ1 as the IPI
  */
-static inline void smp_cross_call(const struct cpumask *mask)
+static inline void smp_cross_call(const struct cpumask *mask, int ipi)
 {
-	gic_raise_softirq(mask, 1);
+	gic_raise_softirq(mask, ipi);
 }
 
 #endif
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-realview/Kconfig linux-libre-2.6.38-gnu1/arch/arm/mach-realview/Kconfig
--- linux-libre-2.6.37-gnu1/arch/arm/mach-realview/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-realview/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -2,52 +2,56 @@ menu "RealView platform type"
 	depends on ARCH_REALVIEW
 
 config MACH_REALVIEW_EB
-	bool "Support RealView/EB platform"
+	bool "Support RealView(R) Emulation Baseboard"
 	select ARM_GIC
 	help
-	  Include support for the ARM(R) RealView Emulation Baseboard platform.
+	  Include support for the ARM(R) RealView(R) Emulation Baseboard
+	  platform.
 
 config REALVIEW_EB_A9MP
-	bool "Support Multicore Cortex-A9"
+	bool "Support Multicore Cortex-A9 Tile"
 	depends on MACH_REALVIEW_EB
 	select CPU_V7
 	help
-	  Enable support for the Cortex-A9MPCore tile on the Realview platform.
+	  Enable support for the Cortex-A9MPCore tile fitted to the
+	  Realview(R) Emulation Baseboard platform.
 
 config REALVIEW_EB_ARM11MP
-	bool "Support ARM11MPCore tile"
+	bool "Support ARM11MPCore Tile"
 	depends on MACH_REALVIEW_EB
 	select CPU_V6
 	select ARCH_HAS_BARRIERS if SMP
 	help
-	  Enable support for the ARM11MPCore tile on the Realview platform.
+	  Enable support for the ARM11MPCore tile fitted to the Realview(R)
+	  Emulation Baseboard platform.
 
 config REALVIEW_EB_ARM11MP_REVB
-	bool "Support ARM11MPCore RevB tile"
+	bool "Support ARM11MPCore RevB Tile"
 	depends on REALVIEW_EB_ARM11MP
 	help
-	  Enable support for the ARM11MPCore RevB tile on the Realview
-	  platform. Since there are device address differences, a
-	  kernel built with this option enabled is not compatible with
-	  other revisions of the ARM11MPCore tile.
+	  Enable support for the ARM11MPCore Revision B tile on the
+	  Realview(R) Emulation Baseboard platform. Since there are device
+	  address differences, a kernel built with this option enabled is
+	  not compatible with other revisions of the ARM11MPCore tile.
 
 config MACH_REALVIEW_PB11MP
-	bool "Support RealView/PB11MPCore platform"
+	bool "Support RealView(R) Platform Baseboard for ARM11MPCore"
 	select CPU_V6
 	select ARM_GIC
 	select HAVE_PATA_PLATFORM
 	select ARCH_HAS_BARRIERS if SMP
 	help
-	  Include support for the ARM(R) RealView MPCore Platform Baseboard.
-	  PB11MPCore is a platform with an on-board ARM11MPCore and has
+	  Include support for the ARM(R) RealView(R) Platform Baseboard for
+	  the ARM11MPCore.  This platform has an on-board ARM11MPCore and has
 	  support for PCI-E and Compact Flash.
 
 config MACH_REALVIEW_PB1176
-	bool "Support RealView/PB1176 platform"
+	bool "Support RealView(R) Platform Baseboard for ARM1176JZF-S"
 	select CPU_V6
 	select ARM_GIC
 	help
-	  Include support for the ARM(R) RealView ARM1176 Platform Baseboard.
+	  Include support for the ARM(R) RealView(R) Platform Baseboard for
+	  ARM1176JZF-S.
 
 config REALVIEW_PB1176_SECURE_FLASH
 	bool "Allow access to the secure flash memory block"
@@ -59,23 +63,24 @@ config REALVIEW_PB1176_SECURE_FLASH
 	  block (64MB @ 0x3c000000) is required.
 
 config MACH_REALVIEW_PBA8
-	bool "Support RealView/PB-A8 platform"
+	bool "Support RealView(R) Platform Baseboard for Cortex(tm)-A8 platform"
 	select CPU_V7
 	select ARM_GIC
 	select HAVE_PATA_PLATFORM
 	help
-	  Include support for the ARM(R) RealView Cortex-A8 Platform Baseboard.
-	  PB-A8 is a platform with an on-board Cortex-A8 and has support for
-	  PCI-E and Compact Flash.
+	  Include support for the ARM(R) RealView Platform Baseboard for
+	  Cortex(tm)-A8.  This platform has an on-board Cortex-A8 and has
+	  support for PCI-E and Compact Flash.
 
 config MACH_REALVIEW_PBX
-	bool "Support RealView/PBX platform"
+	bool "Support RealView(R) Platform Baseboard Explore"
 	select ARM_GIC
 	select HAVE_PATA_PLATFORM
 	select ARCH_SPARSEMEM_ENABLE if CPU_V7 && !REALVIEW_HIGH_PHYS_OFFSET
 	select ZONE_DMA if SPARSEMEM
 	help
-	  Include support for the ARM(R) RealView PBX platform.
+	  Include support for the ARM(R) RealView(R) Platform Baseboard
+	  Explore.
 
 config REALVIEW_HIGH_PHYS_OFFSET
 	bool "High physical base address for the RealView platform"
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-realview/platsmp.c linux-libre-2.6.38-gnu1/arch/arm/mach-realview/platsmp.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-realview/platsmp.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-realview/platsmp.c	2011-03-14 21:20:32.000000000 -0400
@@ -19,7 +19,6 @@
 #include <asm/cacheflush.h>
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
-#include <asm/localtimer.h>
 #include <asm/unified.h>
 
 #include <mach/board-eb.h>
@@ -37,6 +36,19 @@ extern void realview_secondary_startup(v
  */
 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 __cpuinit 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)
 {
 	if (machine_is_realview_eb_mp())
@@ -50,33 +62,22 @@ static void __iomem *scu_base_addr(void)
 		return (void __iomem *)0;
 }
 
-static inline unsigned int get_core_count(void)
-{
-	void __iomem *scu_base = scu_base_addr();
-	if (scu_base)
-		return scu_get_core_count(scu_base);
-	return 1;
-}
-
 static DEFINE_SPINLOCK(boot_lock);
 
 void __cpuinit platform_secondary_init(unsigned int cpu)
 {
-	trace_hardirqs_off();
-
 	/*
 	 * 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_cpu_init(0, gic_cpu_base_addr);
+	gic_secondary_init(0);
 
 	/*
 	 * let the primary processor know we're out of the
 	 * pen, then head off into the C entry point
 	 */
-	pen_release = -1;
-	smp_wmb();
+	write_pen_release(-1);
 
 	/*
 	 * Synchronise with the boot thread.
@@ -103,20 +104,14 @@ 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;
-	flush_cache_all();
+	write_pen_release(cpu);
 
 	/*
-	 * XXX
-	 *
-	 * This is a later addition to the booting protocol: the
-	 * bootMonitor now puts secondary cores into WFI, so
-	 * poke_milo() no longer gets the cores moving; we need
-	 * to send a soft interrupt to wake the secondary core.
-	 * Use smp_cross_call() for this, since there's little
-	 * point duplicating the code here
+	 * 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.
 	 */
-	smp_cross_call(cpumask_of(cpu));
+	smp_cross_call(cpumask_of(cpu), 1);
 
 	timeout = jiffies + (1 * HZ);
 	while (time_before(jiffies, timeout)) {
@@ -136,48 +131,18 @@ int __cpuinit boot_secondary(unsigned in
 	return pen_release != -1 ? -ENOSYS : 0;
 }
 
-static void __init poke_milo(void)
-{
-	/* nobody is to be released from the pen yet */
-	pen_release = -1;
-
-	/*
-	 * Write the address of secondary startup into the system-wide flags
-	 * register. The BootMonitor waits for this register to become
-	 * non-zero.
-	 */
-	__raw_writel(BSYM(virt_to_phys(realview_secondary_startup)),
-		     __io_address(REALVIEW_SYS_FLAGSSET));
-
-	mb();
-}
-
 /*
  * 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 = get_core_count();
-
-	for (i = 0; i < ncores; i++)
-		set_cpu_possible(i, true);
-}
+	void __iomem *scu_base = scu_base_addr();
+	unsigned int i, ncores;
 
-void __init smp_prepare_cpus(unsigned int max_cpus)
-{
-	unsigned int ncores = get_core_count();
-	unsigned int cpu = smp_processor_id();
-	int i;
+	ncores = scu_base ? scu_get_core_count(scu_base) : 1;
 
 	/* sanity check */
-	if (ncores == 0) {
-		printk(KERN_ERR
-		       "Realview: strange CM count of 0? Default to 1\n");
-
-		ncores = 1;
-	}
-
 	if (ncores > NR_CPUS) {
 		printk(KERN_WARNING
 		       "Realview: no. of cores (%d) greater than configured "
@@ -186,13 +151,13 @@ void __init smp_prepare_cpus(unsigned in
 		ncores = NR_CPUS;
 	}
 
-	smp_store_cpu_info(cpu);
+	for (i = 0; i < ncores; i++)
+		set_cpu_possible(i, true);
+}
 
-	/*
-	 * are we trying to boot more cores than exist?
-	 */
-	if (max_cpus > ncores)
-		max_cpus = ncores;
+void __init platform_smp_prepare_cpus(unsigned int max_cpus)
+{
+	int i;
 
 	/*
 	 * Initialise the present map, which describes the set of CPUs
@@ -201,21 +166,14 @@ void __init smp_prepare_cpus(unsigned in
 	for (i = 0; i < max_cpus; i++)
 		set_cpu_present(i, true);
 
+	scu_enable(scu_base_addr());
+
 	/*
-	 * Initialise the SCU if there are more than one CPU and let
-	 * them know where to start. Note that, on modern versions of
-	 * MILO, the "poke" doesn't actually do anything until each
-	 * individual core is sent a soft interrupt to get it out of
-	 * WFI
+	 * Write the address of secondary startup into the
+	 * system-wide flags register. The BootMonitor waits
+	 * until it receives a soft interrupt, and then the
+	 * secondary CPU branches to this address.
 	 */
-	if (max_cpus > 1) {
-		/*
-		 * Enable the local timer or broadcast device for the
-		 * boot CPU, but only if we have more than one CPU.
-		 */
-		percpu_timer_setup();
-
-		scu_enable(scu_base_addr());
-		poke_milo();
-	}
+	__raw_writel(BSYM(virt_to_phys(realview_secondary_startup)),
+		     __io_address(REALVIEW_SYS_FLAGSSET));
 }
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-realview/realview_eb.c linux-libre-2.6.38-gnu1/arch/arm/mach-realview/realview_eb.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-realview/realview_eb.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-realview/realview_eb.c	2011-03-14 21:20:32.000000000 -0400
@@ -364,21 +364,19 @@ static void __init gic_init_irq(void)
 		writel(0x00000000, __io_address(REALVIEW_SYS_LOCK));
 
 		/* core tile GIC, primary */
-		gic_cpu_base_addr = __io_address(REALVIEW_EB11MP_GIC_CPU_BASE);
-		gic_dist_init(0, __io_address(REALVIEW_EB11MP_GIC_DIST_BASE), 29);
-		gic_cpu_init(0, gic_cpu_base_addr);
+		gic_init(0, 29, __io_address(REALVIEW_EB11MP_GIC_DIST_BASE),
+			 __io_address(REALVIEW_EB11MP_GIC_CPU_BASE));
 
 #ifndef CONFIG_REALVIEW_EB_ARM11MP_REVB
 		/* board GIC, secondary */
-		gic_dist_init(1, __io_address(REALVIEW_EB_GIC_DIST_BASE), 64);
-		gic_cpu_init(1, __io_address(REALVIEW_EB_GIC_CPU_BASE));
+		gic_init(1, 64, __io_address(REALVIEW_EB_GIC_DIST_BASE),
+			 __io_address(REALVIEW_EB_GIC_CPU_BASE));
 		gic_cascade_irq(1, IRQ_EB11MP_EB_IRQ1);
 #endif
 	} else {
 		/* board GIC, primary */
-		gic_cpu_base_addr = __io_address(REALVIEW_EB_GIC_CPU_BASE);
-		gic_dist_init(0, __io_address(REALVIEW_EB_GIC_DIST_BASE), 29);
-		gic_cpu_init(0, gic_cpu_base_addr);
+		gic_init(0, 29, __io_address(REALVIEW_EB_GIC_DIST_BASE),
+			 __io_address(REALVIEW_EB_GIC_CPU_BASE));
 	}
 }
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-realview/realview_pb1176.c linux-libre-2.6.38-gnu1/arch/arm/mach-realview/realview_pb1176.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-realview/realview_pb1176.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-realview/realview_pb1176.c	2011-03-14 21:20:32.000000000 -0400
@@ -304,13 +304,14 @@ static struct platform_device char_lcd_d
 static void __init gic_init_irq(void)
 {
 	/* ARM1176 DevChip GIC, primary */
-	gic_cpu_base_addr = __io_address(REALVIEW_DC1176_GIC_CPU_BASE);
-	gic_dist_init(0, __io_address(REALVIEW_DC1176_GIC_DIST_BASE), IRQ_DC1176_GIC_START);
-	gic_cpu_init(0, gic_cpu_base_addr);
+	gic_init(0, IRQ_DC1176_GIC_START,
+		 __io_address(REALVIEW_DC1176_GIC_DIST_BASE),
+		 __io_address(REALVIEW_DC1176_GIC_CPU_BASE));
 
 	/* board GIC, secondary */
-	gic_dist_init(1, __io_address(REALVIEW_PB1176_GIC_DIST_BASE), IRQ_PB1176_GIC_START);
-	gic_cpu_init(1, __io_address(REALVIEW_PB1176_GIC_CPU_BASE));
+	gic_init(1, IRQ_PB1176_GIC_START,
+		 __io_address(REALVIEW_PB1176_GIC_DIST_BASE),
+		 __io_address(REALVIEW_PB1176_GIC_CPU_BASE));
 	gic_cascade_irq(1, IRQ_DC1176_PB_IRQ1);
 }
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-realview/realview_pb11mp.c linux-libre-2.6.38-gnu1/arch/arm/mach-realview/realview_pb11mp.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-realview/realview_pb11mp.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-realview/realview_pb11mp.c	2011-03-14 21:20:32.000000000 -0400
@@ -309,13 +309,13 @@ static void __init gic_init_irq(void)
 	writel(0x00000000, __io_address(REALVIEW_SYS_LOCK));
 
 	/* ARM11MPCore test chip GIC, primary */
-	gic_cpu_base_addr = __io_address(REALVIEW_TC11MP_GIC_CPU_BASE);
-	gic_dist_init(0, __io_address(REALVIEW_TC11MP_GIC_DIST_BASE), 29);
-	gic_cpu_init(0, gic_cpu_base_addr);
+	gic_init(0, 29, __io_address(REALVIEW_TC11MP_GIC_DIST_BASE),
+		 __io_address(REALVIEW_TC11MP_GIC_CPU_BASE));
 
 	/* board GIC, secondary */
-	gic_dist_init(1, __io_address(REALVIEW_PB11MP_GIC_DIST_BASE), IRQ_PB11MP_GIC_START);
-	gic_cpu_init(1, __io_address(REALVIEW_PB11MP_GIC_CPU_BASE));
+	gic_init(1, IRQ_PB11MP_GIC_START,
+		 __io_address(REALVIEW_PB11MP_GIC_DIST_BASE),
+		 __io_address(REALVIEW_PB11MP_GIC_CPU_BASE));
 	gic_cascade_irq(1, IRQ_TC11MP_PB_IRQ1);
 }
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-realview/realview_pba8.c linux-libre-2.6.38-gnu1/arch/arm/mach-realview/realview_pba8.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-realview/realview_pba8.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-realview/realview_pba8.c	2011-03-14 21:20:32.000000000 -0400
@@ -273,9 +273,9 @@ static struct platform_device pmu_device
 static void __init gic_init_irq(void)
 {
 	/* ARM PB-A8 on-board GIC */
-	gic_cpu_base_addr = __io_address(REALVIEW_PBA8_GIC_CPU_BASE);
-	gic_dist_init(0, __io_address(REALVIEW_PBA8_GIC_DIST_BASE), IRQ_PBA8_GIC_START);
-	gic_cpu_init(0, __io_address(REALVIEW_PBA8_GIC_CPU_BASE));
+	gic_init(0, IRQ_PBA8_GIC_START,
+		 __io_address(REALVIEW_PBA8_GIC_DIST_BASE),
+		 __io_address(REALVIEW_PBA8_GIC_CPU_BASE));
 }
 
 static void __init realview_pba8_timer_init(void)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-realview/realview_pbx.c linux-libre-2.6.38-gnu1/arch/arm/mach-realview/realview_pbx.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-realview/realview_pbx.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-realview/realview_pbx.c	2011-03-14 21:20:32.000000000 -0400
@@ -313,15 +313,12 @@ static void __init gic_init_irq(void)
 {
 	/* ARM PBX on-board GIC */
 	if (core_tile_pbx11mp() || core_tile_pbxa9mp()) {
-		gic_cpu_base_addr = __io_address(REALVIEW_PBX_TILE_GIC_CPU_BASE);
-		gic_dist_init(0, __io_address(REALVIEW_PBX_TILE_GIC_DIST_BASE),
-			      29);
-		gic_cpu_init(0, __io_address(REALVIEW_PBX_TILE_GIC_CPU_BASE));
+		gic_init(0, 29, __io_address(REALVIEW_PBX_TILE_GIC_DIST_BASE),
+			 __io_address(REALVIEW_PBX_TILE_GIC_CPU_BASE));
 	} else {
-		gic_cpu_base_addr = __io_address(REALVIEW_PBX_GIC_CPU_BASE);
-		gic_dist_init(0, __io_address(REALVIEW_PBX_GIC_DIST_BASE),
-			      IRQ_PBX_GIC_START);
-		gic_cpu_init(0, __io_address(REALVIEW_PBX_GIC_CPU_BASE));
+		gic_init(0, IRQ_PBX_GIC_START,
+			 __io_address(REALVIEW_PBX_GIC_DIST_BASE),
+			 __io_address(REALVIEW_PBX_GIC_CPU_BASE));
 	}
 }
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-rpc/irq.c linux-libre-2.6.38-gnu1/arch/arm/mach-rpc/irq.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-rpc/irq.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-rpc/irq.c	2011-03-14 21:20:32.000000000 -0400
@@ -6,110 +6,110 @@
 #include <asm/hardware/iomd.h>
 #include <asm/irq.h>
 
-static void iomd_ack_irq_a(unsigned int irq)
+static void iomd_ack_irq_a(struct irq_data *d)
 {
 	unsigned int val, mask;
 
-	mask = 1 << irq;
+	mask = 1 << d->irq;
 	val = iomd_readb(IOMD_IRQMASKA);
 	iomd_writeb(val & ~mask, IOMD_IRQMASKA);
 	iomd_writeb(mask, IOMD_IRQCLRA);
 }
 
-static void iomd_mask_irq_a(unsigned int irq)
+static void iomd_mask_irq_a(struct irq_data *d)
 {
 	unsigned int val, mask;
 
-	mask = 1 << irq;
+	mask = 1 << d->irq;
 	val = iomd_readb(IOMD_IRQMASKA);
 	iomd_writeb(val & ~mask, IOMD_IRQMASKA);
 }
 
-static void iomd_unmask_irq_a(unsigned int irq)
+static void iomd_unmask_irq_a(struct irq_data *d)
 {
 	unsigned int val, mask;
 
-	mask = 1 << irq;
+	mask = 1 << d->irq;
 	val = iomd_readb(IOMD_IRQMASKA);
 	iomd_writeb(val | mask, IOMD_IRQMASKA);
 }
 
 static struct irq_chip iomd_a_chip = {
-	.ack	= iomd_ack_irq_a,
-	.mask	= iomd_mask_irq_a,
-	.unmask = iomd_unmask_irq_a,
+	.irq_ack	= iomd_ack_irq_a,
+	.irq_mask	= iomd_mask_irq_a,
+	.irq_unmask	= iomd_unmask_irq_a,
 };
 
-static void iomd_mask_irq_b(unsigned int irq)
+static void iomd_mask_irq_b(struct irq_data *d)
 {
 	unsigned int val, mask;
 
-	mask = 1 << (irq & 7);
+	mask = 1 << (d->irq & 7);
 	val = iomd_readb(IOMD_IRQMASKB);
 	iomd_writeb(val & ~mask, IOMD_IRQMASKB);
 }
 
-static void iomd_unmask_irq_b(unsigned int irq)
+static void iomd_unmask_irq_b(struct irq_data *d)
 {
 	unsigned int val, mask;
 
-	mask = 1 << (irq & 7);
+	mask = 1 << (d->irq & 7);
 	val = iomd_readb(IOMD_IRQMASKB);
 	iomd_writeb(val | mask, IOMD_IRQMASKB);
 }
 
 static struct irq_chip iomd_b_chip = {
-	.ack	= iomd_mask_irq_b,
-	.mask	= iomd_mask_irq_b,
-	.unmask = iomd_unmask_irq_b,
+	.irq_ack	= iomd_mask_irq_b,
+	.irq_mask	= iomd_mask_irq_b,
+	.irq_unmask	= iomd_unmask_irq_b,
 };
 
-static void iomd_mask_irq_dma(unsigned int irq)
+static void iomd_mask_irq_dma(struct irq_data *d)
 {
 	unsigned int val, mask;
 
-	mask = 1 << (irq & 7);
+	mask = 1 << (d->irq & 7);
 	val = iomd_readb(IOMD_DMAMASK);
 	iomd_writeb(val & ~mask, IOMD_DMAMASK);
 }
 
-static void iomd_unmask_irq_dma(unsigned int irq)
+static void iomd_unmask_irq_dma(struct irq_data *d)
 {
 	unsigned int val, mask;
 
-	mask = 1 << (irq & 7);
+	mask = 1 << (d->irq & 7);
 	val = iomd_readb(IOMD_DMAMASK);
 	iomd_writeb(val | mask, IOMD_DMAMASK);
 }
 
 static struct irq_chip iomd_dma_chip = {
-	.ack	= iomd_mask_irq_dma,
-	.mask	= iomd_mask_irq_dma,
-	.unmask = iomd_unmask_irq_dma,
+	.irq_ack	= iomd_mask_irq_dma,
+	.irq_mask	= iomd_mask_irq_dma,
+	.irq_unmask	= iomd_unmask_irq_dma,
 };
 
-static void iomd_mask_irq_fiq(unsigned int irq)
+static void iomd_mask_irq_fiq(struct irq_data *d)
 {
 	unsigned int val, mask;
 
-	mask = 1 << (irq & 7);
+	mask = 1 << (d->irq & 7);
 	val = iomd_readb(IOMD_FIQMASK);
 	iomd_writeb(val & ~mask, IOMD_FIQMASK);
 }
 
-static void iomd_unmask_irq_fiq(unsigned int irq)
+static void iomd_unmask_irq_fiq(struct irq_data *d)
 {
 	unsigned int val, mask;
 
-	mask = 1 << (irq & 7);
+	mask = 1 << (d->irq & 7);
 	val = iomd_readb(IOMD_FIQMASK);
 	iomd_writeb(val | mask, IOMD_FIQMASK);
 }
 
 static struct irq_chip iomd_fiq_chip = {
-	.ack	= iomd_mask_irq_fiq,
-	.mask	= iomd_mask_irq_fiq,
-	.unmask = iomd_unmask_irq_fiq,
+	.irq_ack	= iomd_mask_irq_fiq,
+	.irq_mask	= iomd_mask_irq_fiq,
+	.irq_unmask	= iomd_unmask_irq_fiq,
 };
 
 void __init rpc_init_irq(void)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-s3c2410/bast-irq.c linux-libre-2.6.38-gnu1/arch/arm/mach-s3c2410/bast-irq.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-s3c2410/bast-irq.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-s3c2410/bast-irq.c	2011-03-14 21:20:32.000000000 -0400
@@ -75,38 +75,38 @@ static unsigned char bast_pc104_irqmasks
 static unsigned char bast_pc104_irqs[] = { 3, 5, 7, 10 };
 
 static void
-bast_pc104_mask(unsigned int irqno)
+bast_pc104_mask(struct irq_data *data)
 {
 	unsigned long temp;
 
 	temp = __raw_readb(BAST_VA_PC104_IRQMASK);
-	temp &= ~bast_pc104_irqmasks[irqno];
+	temp &= ~bast_pc104_irqmasks[data->irq];
 	__raw_writeb(temp, BAST_VA_PC104_IRQMASK);
 }
 
 static void
-bast_pc104_maskack(unsigned int irqno)
+bast_pc104_maskack(struct irq_data *data)
 {
 	struct irq_desc *desc = irq_desc + IRQ_ISA;
 
-	bast_pc104_mask(irqno);
-	desc->chip->ack(IRQ_ISA);
+	bast_pc104_mask(data);
+	desc->irq_data.chip->irq_ack(&desc->irq_data);
 }
 
 static void
-bast_pc104_unmask(unsigned int irqno)
+bast_pc104_unmask(struct irq_data *data)
 {
 	unsigned long temp;
 
 	temp = __raw_readb(BAST_VA_PC104_IRQMASK);
-	temp |= bast_pc104_irqmasks[irqno];
+	temp |= bast_pc104_irqmasks[data->irq];
 	__raw_writeb(temp, BAST_VA_PC104_IRQMASK);
 }
 
 static struct irq_chip  bast_pc104_chip = {
-	.mask	     = bast_pc104_mask,
-	.unmask	     = bast_pc104_unmask,
-	.ack	     = bast_pc104_maskack
+	.irq_mask	= bast_pc104_mask,
+	.irq_unmask	= bast_pc104_unmask,
+	.irq_ack	= bast_pc104_maskack
 };
 
 static void
@@ -123,7 +123,7 @@ bast_irq_pc104_demux(unsigned int irq,
 		/* ack if we get an irq with nothing (ie, startup) */
 
 		desc = irq_desc + IRQ_ISA;
-		desc->chip->ack(IRQ_ISA);
+		desc->irq_data.chip->irq_ack(&desc->irq_data);
 	} else {
 		/* handle the IRQ */
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-s3c2410/include/mach/irqs.h linux-libre-2.6.38-gnu1/arch/arm/mach-s3c2410/include/mach/irqs.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-s3c2410/include/mach/irqs.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-s3c2410/include/mach/irqs.h	2011-03-14 21:20:32.000000000 -0400
@@ -152,8 +152,8 @@
 
 #define IRQ_S3C2416_HSMMC0	S3C2410_IRQ(21)		/* S3C2416/S3C2450 */
 
-#define IRQ_HSMMC0		IRQ_S3C2443_HSMMC
-#define IRQ_HSMMC1		IRQ_S3C2416_HSMMC0
+#define IRQ_HSMMC0		IRQ_S3C2416_HSMMC0
+#define IRQ_HSMMC1		IRQ_S3C2443_HSMMC
 
 #define IRQ_S3C2443_LCD1	S3C2410_IRQSUB(14)
 #define IRQ_S3C2443_LCD2	S3C2410_IRQSUB(15)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-s3c2410/include/mach/map.h linux-libre-2.6.38-gnu1/arch/arm/mach-s3c2410/include/mach/map.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-s3c2410/include/mach/map.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-s3c2410/include/mach/map.h	2011-03-14 21:20:32.000000000 -0400
@@ -112,8 +112,8 @@
 #define S3C_PA_IIC          S3C2410_PA_IIC
 #define S3C_PA_UART	    S3C24XX_PA_UART
 #define S3C_PA_USBHOST	S3C2410_PA_USBHOST
-#define S3C_PA_HSMMC0	    S3C2443_PA_HSMMC
-#define S3C_PA_HSMMC1	    S3C2416_PA_HSMMC0
+#define S3C_PA_HSMMC0	    S3C2416_PA_HSMMC0
+#define S3C_PA_HSMMC1	    S3C2443_PA_HSMMC
 #define S3C_PA_WDT	    S3C2410_PA_WATCHDOG
 #define S3C_PA_NAND	    S3C24XX_PA_NAND
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-s3c2410/include/mach/regs-s3c2443-clock.h linux-libre-2.6.38-gnu1/arch/arm/mach-s3c2410/include/mach/regs-s3c2443-clock.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-s3c2410/include/mach/regs-s3c2443-clock.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-s3c2410/include/mach/regs-s3c2443-clock.h	2011-03-14 21:20:32.000000000 -0400
@@ -86,6 +86,7 @@
 #define S3C2443_HCLKCON_LCDC		(1<<9)
 #define S3C2443_HCLKCON_USBH		(1<<11)
 #define S3C2443_HCLKCON_USBD		(1<<12)
+#define S3C2416_HCLKCON_HSMMC0		(1<<15)
 #define S3C2443_HCLKCON_HSMMC		(1<<16)
 #define S3C2443_HCLKCON_CFC		(1<<17)
 #define S3C2443_HCLKCON_SSMC		(1<<18)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-s3c2410/mach-h1940.c linux-libre-2.6.38-gnu1/arch/arm/mach-s3c2410/mach-h1940.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-s3c2410/mach-h1940.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-s3c2410/mach-h1940.c	2011-03-14 21:20:32.000000000 -0400
@@ -387,7 +387,7 @@ static struct platform_device *h1940_dev
 	&s3c_device_wdt,
 	&s3c_device_i2c0,
 	&s3c_device_iis,
-	&s3c_device_pcm,
+	&samsung_asoc_dma,
 	&s3c_device_usbgadget,
 	&h1940_device_leds,
 	&h1940_device_bluetooth,
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-s3c2412/irq.c linux-libre-2.6.38-gnu1/arch/arm/mach-s3c2412/irq.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-s3c2412/irq.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-s3c2412/irq.c	2011-03-14 21:20:32.000000000 -0400
@@ -49,9 +49,9 @@
 */
 
 static void
-s3c2412_irq_mask(unsigned int irqno)
+s3c2412_irq_mask(struct irq_data *data)
 {
-	unsigned long bitval = 1UL << (irqno - IRQ_EINT0);
+	unsigned long bitval = 1UL << (data->irq - IRQ_EINT0);
 	unsigned long mask;
 
 	mask = __raw_readl(S3C2410_INTMSK);
@@ -62,9 +62,9 @@ s3c2412_irq_mask(unsigned int irqno)
 }
 
 static inline void
-s3c2412_irq_ack(unsigned int irqno)
+s3c2412_irq_ack(struct irq_data *data)
 {
-	unsigned long bitval = 1UL << (irqno - IRQ_EINT0);
+	unsigned long bitval = 1UL << (data->irq - IRQ_EINT0);
 
 	__raw_writel(bitval, S3C2412_EINTPEND);
 	__raw_writel(bitval, S3C2410_SRCPND);
@@ -72,9 +72,9 @@ s3c2412_irq_ack(unsigned int irqno)
 }
 
 static inline void
-s3c2412_irq_maskack(unsigned int irqno)
+s3c2412_irq_maskack(struct irq_data *data)
 {
-	unsigned long bitval = 1UL << (irqno - IRQ_EINT0);
+	unsigned long bitval = 1UL << (data->irq - IRQ_EINT0);
 	unsigned long mask;
 
 	mask = __raw_readl(S3C2410_INTMSK);
@@ -89,9 +89,9 @@ s3c2412_irq_maskack(unsigned int irqno)
 }
 
 static void
-s3c2412_irq_unmask(unsigned int irqno)
+s3c2412_irq_unmask(struct irq_data *data)
 {
-	unsigned long bitval = 1UL << (irqno - IRQ_EINT0);
+	unsigned long bitval = 1UL << (data->irq - IRQ_EINT0);
 	unsigned long mask;
 
 	mask = __raw_readl(S3C2412_EINTMASK);
@@ -102,11 +102,11 @@ s3c2412_irq_unmask(unsigned int irqno)
 }
 
 static struct irq_chip s3c2412_irq_eint0t4 = {
-	.ack	   = s3c2412_irq_ack,
-	.mask	   = s3c2412_irq_mask,
-	.unmask	   = s3c2412_irq_unmask,
-	.set_wake  = s3c_irq_wake,
-	.set_type  = s3c_irqext_type,
+	.irq_ack	= s3c2412_irq_ack,
+	.irq_mask	= s3c2412_irq_mask,
+	.irq_unmask	= s3c2412_irq_unmask,
+	.irq_set_wake	= s3c_irq_wake,
+	.irq_set_type	= s3c_irqext_type,
 };
 
 #define INTBIT(x)	(1 << ((x) - S3C2410_IRQSUB(0)))
@@ -132,29 +132,29 @@ static void s3c2412_irq_demux_cfsdi(unsi
 #define INTMSK_CFSDI	(1UL << (IRQ_S3C2412_CFSDI - IRQ_EINT0))
 #define SUBMSK_CFSDI	INTMSK_SUB(IRQ_S3C2412_SDI, IRQ_S3C2412_CF)
 
-static void s3c2412_irq_cfsdi_mask(unsigned int irqno)
+static void s3c2412_irq_cfsdi_mask(struct irq_data *data)
 {
-	s3c_irqsub_mask(irqno, INTMSK_CFSDI, SUBMSK_CFSDI);
+	s3c_irqsub_mask(data->irq, INTMSK_CFSDI, SUBMSK_CFSDI);
 }
 
-static void s3c2412_irq_cfsdi_unmask(unsigned int irqno)
+static void s3c2412_irq_cfsdi_unmask(struct irq_data *data)
 {
-	s3c_irqsub_unmask(irqno, INTMSK_CFSDI);
+	s3c_irqsub_unmask(data->irq, INTMSK_CFSDI);
 }
 
-static void s3c2412_irq_cfsdi_ack(unsigned int irqno)
+static void s3c2412_irq_cfsdi_ack(struct irq_data *data)
 {
-	s3c_irqsub_maskack(irqno, INTMSK_CFSDI, SUBMSK_CFSDI);
+	s3c_irqsub_maskack(data->irq, INTMSK_CFSDI, SUBMSK_CFSDI);
 }
 
 static struct irq_chip s3c2412_irq_cfsdi = {
 	.name		= "s3c2412-cfsdi",
-	.ack		= s3c2412_irq_cfsdi_ack,
-	.mask		= s3c2412_irq_cfsdi_mask,
-	.unmask		= s3c2412_irq_cfsdi_unmask,
+	.irq_ack	= s3c2412_irq_cfsdi_ack,
+	.irq_mask	= s3c2412_irq_cfsdi_mask,
+	.irq_unmask	= s3c2412_irq_cfsdi_unmask,
 };
 
-static int s3c2412_irq_rtc_wake(unsigned int irqno, unsigned int state)
+static int s3c2412_irq_rtc_wake(struct irq_data *data, unsigned int state)
 {
 	unsigned long pwrcfg;
 
@@ -165,7 +165,7 @@ static int s3c2412_irq_rtc_wake(unsigned
 		pwrcfg |= S3C2412_PWRCFG_RTC_MASKIRQ;
 	__raw_writel(pwrcfg, S3C2412_PWRCFG);
 
-	return s3c_irq_chip.set_wake(irqno, state);
+	return s3c_irq_chip.irq_set_wake(data, state);
 }
 
 static struct irq_chip s3c2412_irq_rtc_chip;
@@ -193,7 +193,7 @@ static int s3c2412_irq_add(struct sys_de
 	/* change RTC IRQ's set wake method */
 
 	s3c2412_irq_rtc_chip = s3c_irq_chip;
-	s3c2412_irq_rtc_chip.set_wake = s3c2412_irq_rtc_wake;
+	s3c2412_irq_rtc_chip.irq_set_wake = s3c2412_irq_rtc_wake;
 
 	set_irq_chip(IRQ_RTC, &s3c2412_irq_rtc_chip);
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-s3c2412/Kconfig linux-libre-2.6.38-gnu1/arch/arm/mach-s3c2412/Kconfig
--- linux-libre-2.6.37-gnu1/arch/arm/mach-s3c2412/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-s3c2412/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -59,7 +59,7 @@ config MACH_JIVE
 	  Say Y here if you are using the Logitech Jive.
 
 config MACH_JIVE_SHOW_BOOTLOADER
-	bool "Allow access to bootloader partitions in MTD"
+	bool "Allow access to bootloader partitions in MTD (EXPERIMENTAL)"
 	depends on MACH_JIVE && EXPERIMENTAL
 
 config MACH_SMDK2413
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-s3c2416/clock.c linux-libre-2.6.38-gnu1/arch/arm/mach-s3c2416/clock.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-s3c2416/clock.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-s3c2416/clock.c	2011-03-14 21:20:32.000000000 -0400
@@ -38,12 +38,11 @@ static unsigned int armdiv[8] = {
 	[7] = 8,
 };
 
-/* ID to hardware numbering, 0 is HSMMC1, 1 is HSMMC0 */
 static struct clksrc_clk hsmmc_div[] = {
 	[0] = {
 		.clk = {
 			.name	= "hsmmc-div",
-			.id	= 1,
+			.id	= 0,
 			.parent	= &clk_esysclk.clk,
 		},
 		.reg_div = { .reg = S3C2416_CLKDIV2, .size = 2, .shift = 6 },
@@ -51,7 +50,7 @@ static struct clksrc_clk hsmmc_div[] = {
 	[1] = {
 		.clk = {
 			.name	= "hsmmc-div",
-			.id	= 0,
+			.id	= 1,
 			.parent	= &clk_esysclk.clk,
 		},
 		.reg_div = { .reg = S3C2443_CLKDIV1, .size = 2, .shift = 6 },
@@ -61,7 +60,7 @@ static struct clksrc_clk hsmmc_div[] = {
 static struct clksrc_clk hsmmc_mux[] = {
 	[0] = {
 		.clk	= {
-			.id	= 1,
+			.id	= 0,
 			.name	= "hsmmc-if",
 			.ctrlbit = (1 << 6),
 			.enable = s3c2443_clkcon_enable_s,
@@ -77,7 +76,7 @@ static struct clksrc_clk hsmmc_mux[] = {
 	},
 	[1] = {
 		.clk	= {
-			.id	= 0,
+			.id	= 1,
 			.name	= "hsmmc-if",
 			.ctrlbit = (1 << 12),
 			.enable = s3c2443_clkcon_enable_s,
@@ -93,6 +92,13 @@ static struct clksrc_clk hsmmc_mux[] = {
 	},
 };
 
+static struct clk hsmmc0_clk = {
+	.name		= "hsmmc",
+	.id		= 0,
+	.parent		= &clk_h,
+	.enable		= s3c2443_clkcon_enable_h,
+	.ctrlbit	= S3C2416_HCLKCON_HSMMC0,
+};
 
 static inline unsigned int s3c2416_fclk_div(unsigned long clkcon0)
 {
@@ -130,6 +136,8 @@ void __init s3c2416_init_clocks(int xtal
 	for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++)
 		s3c_register_clksrc(clksrcs[ptr], 1);
 
+	s3c24xx_register_clock(&hsmmc0_clk);
+
 	s3c_pwmclk_init();
 
 }
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-s3c2416/irq.c linux-libre-2.6.38-gnu1/arch/arm/mach-s3c2416/irq.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-s3c2416/irq.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-s3c2416/irq.c	2011-03-14 21:20:32.000000000 -0400
@@ -77,28 +77,27 @@ static void s3c2416_irq_demux_wdtac97(un
 #define INTMSK_WDTAC97	(1UL << (IRQ_WDT - IRQ_EINT0))
 #define SUBMSK_WDTAC97	INTMSK(IRQ_S3C2443_WDT, IRQ_S3C2443_AC97)
 
-static void s3c2416_irq_wdtac97_mask(unsigned int irqno)
+static void s3c2416_irq_wdtac97_mask(struct irq_data *data)
 {
-	s3c_irqsub_mask(irqno, INTMSK_WDTAC97, SUBMSK_WDTAC97);
+	s3c_irqsub_mask(data->irq, INTMSK_WDTAC97, SUBMSK_WDTAC97);
 }
 
-static void s3c2416_irq_wdtac97_unmask(unsigned int irqno)
+static void s3c2416_irq_wdtac97_unmask(struct irq_data *data)
 {
-	s3c_irqsub_unmask(irqno, INTMSK_WDTAC97);
+	s3c_irqsub_unmask(data->irq, INTMSK_WDTAC97);
 }
 
-static void s3c2416_irq_wdtac97_ack(unsigned int irqno)
+static void s3c2416_irq_wdtac97_ack(struct irq_data *data)
 {
-	s3c_irqsub_maskack(irqno, INTMSK_WDTAC97, SUBMSK_WDTAC97);
+	s3c_irqsub_maskack(data->irq, INTMSK_WDTAC97, SUBMSK_WDTAC97);
 }
 
 static struct irq_chip s3c2416_irq_wdtac97 = {
-	.mask	    = s3c2416_irq_wdtac97_mask,
-	.unmask	    = s3c2416_irq_wdtac97_unmask,
-	.ack	    = s3c2416_irq_wdtac97_ack,
+	.irq_mask	= s3c2416_irq_wdtac97_mask,
+	.irq_unmask	= s3c2416_irq_wdtac97_unmask,
+	.irq_ack	= s3c2416_irq_wdtac97_ack,
 };
 
-
 /* LCD sub interrupts */
 
 static void s3c2416_irq_demux_lcd(unsigned int irq, struct irq_desc *desc)
@@ -109,28 +108,27 @@ static void s3c2416_irq_demux_lcd(unsign
 #define INTMSK_LCD	(1UL << (IRQ_LCD - IRQ_EINT0))
 #define SUBMSK_LCD	INTMSK(IRQ_S3C2443_LCD1, IRQ_S3C2443_LCD4)
 
-static void s3c2416_irq_lcd_mask(unsigned int irqno)
+static void s3c2416_irq_lcd_mask(struct irq_data *data)
 {
-	s3c_irqsub_mask(irqno, INTMSK_LCD, SUBMSK_LCD);
+	s3c_irqsub_mask(data->irq, INTMSK_LCD, SUBMSK_LCD);
 }
 
-static void s3c2416_irq_lcd_unmask(unsigned int irqno)
+static void s3c2416_irq_lcd_unmask(struct irq_data *data)
 {
-	s3c_irqsub_unmask(irqno, INTMSK_LCD);
+	s3c_irqsub_unmask(data->irq, INTMSK_LCD);
 }
 
-static void s3c2416_irq_lcd_ack(unsigned int irqno)
+static void s3c2416_irq_lcd_ack(struct irq_data *data)
 {
-	s3c_irqsub_maskack(irqno, INTMSK_LCD, SUBMSK_LCD);
+	s3c_irqsub_maskack(data->irq, INTMSK_LCD, SUBMSK_LCD);
 }
 
 static struct irq_chip s3c2416_irq_lcd = {
-	.mask	    = s3c2416_irq_lcd_mask,
-	.unmask	    = s3c2416_irq_lcd_unmask,
-	.ack	    = s3c2416_irq_lcd_ack,
+	.irq_mask	= s3c2416_irq_lcd_mask,
+	.irq_unmask	= s3c2416_irq_lcd_unmask,
+	.irq_ack	= s3c2416_irq_lcd_ack,
 };
 
-
 /* DMA sub interrupts */
 
 static void s3c2416_irq_demux_dma(unsigned int irq, struct irq_desc *desc)
@@ -142,28 +140,27 @@ static void s3c2416_irq_demux_dma(unsign
 #define SUBMSK_DMA	INTMSK(IRQ_S3C2443_DMA0, IRQ_S3C2443_DMA5)
 
 
-static void s3c2416_irq_dma_mask(unsigned int irqno)
+static void s3c2416_irq_dma_mask(struct irq_data *data)
 {
-	s3c_irqsub_mask(irqno, INTMSK_DMA, SUBMSK_DMA);
+	s3c_irqsub_mask(data->irq, INTMSK_DMA, SUBMSK_DMA);
 }
 
-static void s3c2416_irq_dma_unmask(unsigned int irqno)
+static void s3c2416_irq_dma_unmask(struct irq_data *data)
 {
-	s3c_irqsub_unmask(irqno, INTMSK_DMA);
+	s3c_irqsub_unmask(data->irq, INTMSK_DMA);
 }
 
-static void s3c2416_irq_dma_ack(unsigned int irqno)
+static void s3c2416_irq_dma_ack(struct irq_data *data)
 {
-	s3c_irqsub_maskack(irqno, INTMSK_DMA, SUBMSK_DMA);
+	s3c_irqsub_maskack(data->irq, INTMSK_DMA, SUBMSK_DMA);
 }
 
 static struct irq_chip s3c2416_irq_dma = {
-	.mask	    = s3c2416_irq_dma_mask,
-	.unmask	    = s3c2416_irq_dma_unmask,
-	.ack	    = s3c2416_irq_dma_ack,
+	.irq_mask	= s3c2416_irq_dma_mask,
+	.irq_unmask	= s3c2416_irq_dma_unmask,
+	.irq_ack	= s3c2416_irq_dma_ack,
 };
 
-
 /* UART3 sub interrupts */
 
 static void s3c2416_irq_demux_uart3(unsigned int irq, struct irq_desc *desc)
@@ -174,28 +171,27 @@ static void s3c2416_irq_demux_uart3(unsi
 #define INTMSK_UART3	(1UL << (IRQ_S3C2443_UART3 - IRQ_EINT0))
 #define SUBMSK_UART3	(0x7 << (IRQ_S3C2443_RX3 - S3C2410_IRQSUB(0)))
 
-static void s3c2416_irq_uart3_mask(unsigned int irqno)
+static void s3c2416_irq_uart3_mask(struct irq_data *data)
 {
-	s3c_irqsub_mask(irqno, INTMSK_UART3, SUBMSK_UART3);
+	s3c_irqsub_mask(data->irq, INTMSK_UART3, SUBMSK_UART3);
 }
 
-static void s3c2416_irq_uart3_unmask(unsigned int irqno)
+static void s3c2416_irq_uart3_unmask(struct irq_data *data)
 {
-	s3c_irqsub_unmask(irqno, INTMSK_UART3);
+	s3c_irqsub_unmask(data->irq, INTMSK_UART3);
 }
 
-static void s3c2416_irq_uart3_ack(unsigned int irqno)
+static void s3c2416_irq_uart3_ack(struct irq_data *data)
 {
-	s3c_irqsub_maskack(irqno, INTMSK_UART3, SUBMSK_UART3);
+	s3c_irqsub_maskack(data->irq, INTMSK_UART3, SUBMSK_UART3);
 }
 
 static struct irq_chip s3c2416_irq_uart3 = {
-	.mask	    = s3c2416_irq_uart3_mask,
-	.unmask	    = s3c2416_irq_uart3_unmask,
-	.ack	    = s3c2416_irq_uart3_ack,
+	.irq_mask	= s3c2416_irq_uart3_mask,
+	.irq_unmask	= s3c2416_irq_uart3_unmask,
+	.irq_ack	= s3c2416_irq_uart3_ack,
 };
 
-
 /* IRQ initialisation code */
 
 static int __init s3c2416_add_sub(unsigned int base,
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-s3c2416/Kconfig linux-libre-2.6.38-gnu1/arch/arm/mach-s3c2416/Kconfig
--- linux-libre-2.6.37-gnu1/arch/arm/mach-s3c2416/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-s3c2416/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -31,6 +31,17 @@ config S3C2416_PM
 	help
 	  Internal config node to apply S3C2416 power management
 
+config S3C2416_SETUP_SDHCI
+	bool
+	select S3C2416_SETUP_SDHCI_GPIO
+	help
+	  Internal helper functions for S3C2416 based SDHCI systems
+
+config S3C2416_SETUP_SDHCI_GPIO
+	bool
+	help
+	  Common setup code for SDHCI gpio.
+
 menu "S3C2416 Machines"
 
 config MACH_SMDK2416
@@ -42,6 +53,7 @@ config MACH_SMDK2416
 	select S3C_DEV_HSMMC1
 	select S3C_DEV_NAND
 	select S3C_DEV_USB_HOST
+	select S3C2416_SETUP_SDHCI
 	select S3C2416_PM if PM
 	help
 	  Say Y here if you are using an SMDK2416
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-s3c2416/mach-smdk2416.c linux-libre-2.6.38-gnu1/arch/arm/mach-s3c2416/mach-smdk2416.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-s3c2416/mach-smdk2416.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-s3c2416/mach-smdk2416.c	2011-03-14 21:20:32.000000000 -0400
@@ -46,6 +46,7 @@
 #include <plat/devs.h>
 #include <plat/cpu.h>
 #include <plat/nand.h>
+#include <plat/sdhci.h>
 
 #include <plat/regs-fb-v4.h>
 #include <plat/fb.h>
@@ -110,6 +111,13 @@ static struct s3c2410_uartcfg smdk2416_u
 		.ucon	     = UCON,
 		.ulcon	     = ULCON | 0x50,
 		.ufcon	     = UFCON,
+	},
+	[3] = {
+		.hwport	     = 3,
+		.flags	     = 0,
+		.ucon	     = UCON,
+		.ulcon	     = ULCON,
+		.ufcon	     = UFCON,
 	}
 };
 
@@ -159,6 +167,18 @@ static struct s3c_fb_platdata smdk2416_f
 	.vidcon1	= VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
 };
 
+static struct s3c_sdhci_platdata smdk2416_hsmmc0_pdata __initdata = {
+	.max_width		= 4,
+	.cd_type		= S3C_SDHCI_CD_GPIO,
+	.ext_cd_gpio		= S3C2410_GPF(1),
+	.ext_cd_gpio_invert	= 1,
+};
+
+static struct s3c_sdhci_platdata smdk2416_hsmmc1_pdata __initdata = {
+	.max_width		= 4,
+	.cd_type		= S3C_SDHCI_CD_NONE,
+};
+
 static struct platform_device *smdk2416_devices[] __initdata = {
 	&s3c_device_fb,
 	&s3c_device_wdt,
@@ -180,6 +200,9 @@ static void __init smdk2416_machine_init
 	s3c_i2c0_set_platdata(NULL);
 	s3c_fb_set_platdata(&smdk2416_fb_platdata);
 
+	s3c_sdhci0_set_platdata(&smdk2416_hsmmc0_pdata);
+	s3c_sdhci1_set_platdata(&smdk2416_hsmmc1_pdata);
+
 	gpio_request(S3C2410_GPB(4), "USBHost Power");
 	gpio_direction_output(S3C2410_GPB(4), 1);
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-s3c2416/Makefile linux-libre-2.6.38-gnu1/arch/arm/mach-s3c2416/Makefile
--- linux-libre-2.6.37-gnu1/arch/arm/mach-s3c2416/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-s3c2416/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -14,6 +14,10 @@ obj-$(CONFIG_CPU_S3C2416)	+= irq.o
 obj-$(CONFIG_S3C2416_PM)	+= pm.o
 #obj-$(CONFIG_S3C2416_DMA)	+= dma.o
 
+# Device setup
+obj-$(CONFIG_S3C2416_SETUP_SDHCI) += setup-sdhci.o
+obj-$(CONFIG_S3C2416_SETUP_SDHCI_GPIO) += setup-sdhci-gpio.o
+
 # Machine support
 
 obj-$(CONFIG_MACH_SMDK2416)	+= mach-smdk2416.o
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-s3c2416/s3c2416.c linux-libre-2.6.38-gnu1/arch/arm/mach-s3c2416/s3c2416.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-s3c2416/s3c2416.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-s3c2416/s3c2416.c	2011-03-14 21:20:32.000000000 -0400
@@ -53,6 +53,7 @@
 #include <plat/s3c2416.h>
 #include <plat/devs.h>
 #include <plat/cpu.h>
+#include <plat/sdhci.h>
 
 #include <plat/iic-core.h>
 #include <plat/fb-core.h>
@@ -115,6 +116,10 @@ void __init s3c2416_map_io(void)
 	s3c24xx_gpiocfg_default.set_pull = s3c_gpio_setpull_updown;
 	s3c24xx_gpiocfg_default.get_pull = s3c_gpio_getpull_updown;
 
+	/* initialize device information early */
+	s3c2416_default_sdhci0();
+	s3c2416_default_sdhci1();
+
 	iotable_init(s3c2416_iodesc, ARRAY_SIZE(s3c2416_iodesc));
 }
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-s3c2416/setup-sdhci.c linux-libre-2.6.38-gnu1/arch/arm/mach-s3c2416/setup-sdhci.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-s3c2416/setup-sdhci.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-s3c2416/setup-sdhci.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,61 @@
+/* linux/arch/arm/mach-s3c2416/setup-sdhci.c
+ *
+ * Copyright 2010 Promwad Innovation Company
+ *	Yauhen Kharuzhy <yauhen.kharuzhy@promwad.com>
+ *
+ * S3C2416 - Helper functions for settign up SDHCI device(s) (HSMMC)
+ *
+ * Based on mach-s3c64xx/setup-sdhci.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/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] */
+
+char *s3c2416_hsmmc_clksrcs[4] = {
+	[0] = "hsmmc",
+	[1] = "hsmmc",
+	[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-2.6.37-gnu1/arch/arm/mach-s3c2416/setup-sdhci-gpio.c linux-libre-2.6.38-gnu1/arch/arm/mach-s3c2416/setup-sdhci-gpio.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-s3c2416/setup-sdhci-gpio.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-s3c2416/setup-sdhci-gpio.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,34 @@
+/* linux/arch/arm/plat-s3c2416/setup-sdhci-gpio.c
+ *
+ * Copyright 2010 Promwad Innovation Company
+ *	Yauhen Kharuzhy <yauhen.kharuzhy@promwad.com>
+ *
+ * S3C2416 - Helper functions for setting up SDHCI device(s) GPIO (HSMMC)
+ *
+ * Based on mach-s3c64xx/setup-sdhci-gpio.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/kernel.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+
+#include <mach/regs-gpio.h>
+#include <plat/gpio-cfg.h>
+
+void s3c2416_setup_sdhci0_cfg_gpio(struct platform_device *dev, int width)
+{
+	s3c_gpio_cfgrange_nopull(S3C2410_GPE(5), 2 + width, S3C_GPIO_SFN(2));
+}
+
+void s3c2416_setup_sdhci1_cfg_gpio(struct platform_device *dev, int width)
+{
+	s3c_gpio_cfgrange_nopull(S3C2410_GPL(0), width, S3C_GPIO_SFN(2));
+	s3c_gpio_cfgrange_nopull(S3C2410_GPL(8), 2, S3C_GPIO_SFN(2));
+}
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-s3c2440/include/mach/gta02.h linux-libre-2.6.38-gnu1/arch/arm/mach-s3c2440/include/mach/gta02.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-s3c2440/include/mach/gta02.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-s3c2440/include/mach/gta02.h	2011-03-14 21:20:32.000000000 -0400
@@ -44,19 +44,19 @@
 #define GTA02v3_GPIO_nUSB_FLT	S3C2410_GPG(10)	/* v3 + v4 only */
 #define GTA02v3_GPIO_nGSM_OC	S3C2410_GPG(11)	/* v3 + v4 only */
 
-#define GTA02_GPIO_AMP_SHUT	S3C2440_GPJ1	/* v2 + v3 + v4 only */
-#define GTA02v1_GPIO_WLAN_GPIO10	S3C2440_GPJ2
-#define GTA02_GPIO_HP_IN	S3C2440_GPJ2	/* v2 + v3 + v4 only */
-#define GTA02_GPIO_INT0		S3C2440_GPJ3	/* v2 + v3 + v4 only */
-#define GTA02_GPIO_nGSM_EN	S3C2440_GPJ4
-#define GTA02_GPIO_3D_RESET	S3C2440_GPJ5
-#define GTA02_GPIO_nDL_GSM	S3C2440_GPJ6	/* v4 + v5 only */
-#define GTA02_GPIO_WLAN_GPIO0	S3C2440_GPJ7
-#define GTA02v1_GPIO_BAT_ID	S3C2440_GPJ8
-#define GTA02_GPIO_KEEPACT	S3C2440_GPJ8
-#define GTA02v1_GPIO_HP_IN	S3C2440_GPJ10
-#define GTA02_CHIP_PWD		S3C2440_GPJ11	/* v2 + v3 + v4 only */
-#define GTA02_GPIO_nWLAN_RESET	S3C2440_GPJ12	/* v2 + v3 + v4 only */
+#define GTA02_GPIO_AMP_SHUT	S3C2410_GPJ(1)	/* v2 + v3 + v4 only */
+#define GTA02v1_GPIO_WLAN_GPIO10	S3C2410_GPJ(2)
+#define GTA02_GPIO_HP_IN	S3C2410_GPJ(2)	/* v2 + v3 + v4 only */
+#define GTA02_GPIO_INT0		S3C2410_GPJ(3)	/* v2 + v3 + v4 only */
+#define GTA02_GPIO_nGSM_EN	S3C2410_GPJ(4)
+#define GTA02_GPIO_3D_RESET	S3C2410_GPJ(5)
+#define GTA02_GPIO_nDL_GSM	S3C2410_GPJ(6)	/* v4 + v5 only */
+#define GTA02_GPIO_WLAN_GPIO0	S3C2410_GPJ(7)
+#define GTA02v1_GPIO_BAT_ID	S3C2410_GPJ(8)
+#define GTA02_GPIO_KEEPACT	S3C2410_GPJ(8)
+#define GTA02v1_GPIO_HP_IN	S3C2410_GPJ(10)
+#define GTA02_CHIP_PWD		S3C2410_GPJ(11)	/* v2 + v3 + v4 only */
+#define GTA02_GPIO_nWLAN_RESET	S3C2410_GPJ(12)	/* v2 + v3 + v4 only */
 
 #define GTA02_IRQ_GSENSOR_1	IRQ_EINT0
 #define GTA02_IRQ_MODEM		IRQ_EINT1
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-s3c2440/irq.c linux-libre-2.6.38-gnu1/arch/arm/mach-s3c2440/irq.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-s3c2440/irq.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-s3c2440/irq.c	2011-03-14 21:20:32.000000000 -0400
@@ -69,27 +69,27 @@ static void s3c_irq_demux_wdtac97(unsign
 #define INTMSK_WDT	 (1UL << (IRQ_WDT - IRQ_EINT0))
 
 static void
-s3c_irq_wdtac97_mask(unsigned int irqno)
+s3c_irq_wdtac97_mask(struct irq_data *data)
 {
-	s3c_irqsub_mask(irqno, INTMSK_WDT, 3<<13);
+	s3c_irqsub_mask(data->irq, INTMSK_WDT, 3 << 13);
 }
 
 static void
-s3c_irq_wdtac97_unmask(unsigned int irqno)
+s3c_irq_wdtac97_unmask(struct irq_data *data)
 {
-	s3c_irqsub_unmask(irqno, INTMSK_WDT);
+	s3c_irqsub_unmask(data->irq, INTMSK_WDT);
 }
 
 static void
-s3c_irq_wdtac97_ack(unsigned int irqno)
+s3c_irq_wdtac97_ack(struct irq_data *data)
 {
-	s3c_irqsub_maskack(irqno, INTMSK_WDT, 3<<13);
+	s3c_irqsub_maskack(data->irq, INTMSK_WDT, 3 << 13);
 }
 
 static struct irq_chip s3c_irq_wdtac97 = {
-	.mask	    = s3c_irq_wdtac97_mask,
-	.unmask	    = s3c_irq_wdtac97_unmask,
-	.ack	    = s3c_irq_wdtac97_ack,
+	.irq_mask	= s3c_irq_wdtac97_mask,
+	.irq_unmask	= s3c_irq_wdtac97_unmask,
+	.irq_ack	= s3c_irq_wdtac97_ack,
 };
 
 static int s3c2440_irq_add(struct sys_device *sysdev)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-s3c2440/Kconfig linux-libre-2.6.38-gnu1/arch/arm/mach-s3c2440/Kconfig
--- linux-libre-2.6.37-gnu1/arch/arm/mach-s3c2440/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-s3c2440/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -99,6 +99,7 @@ config MACH_NEO1973_GTA02
 	select POWER_SUPPLY
 	select MACH_NEO1973
 	select S3C2410_PWM
+	select S3C_DEV_USB_HOST
 	help
 	   Say Y here if you are using the Openmoko GTA02 / Freerunner GSM Phone
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-s3c2440/mach-rx1950.c linux-libre-2.6.38-gnu1/arch/arm/mach-s3c2440/mach-rx1950.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-s3c2440/mach-rx1950.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-s3c2440/mach-rx1950.c	2011-03-14 21:20:32.000000000 -0400
@@ -692,7 +692,7 @@ static struct platform_device *rx1950_de
 	&s3c_device_wdt,
 	&s3c_device_i2c0,
 	&s3c_device_iis,
-	&s3c_device_pcm,
+	&samsung_asoc_dma,
 	&s3c_device_usbgadget,
 	&s3c_device_rtc,
 	&s3c_device_nand,
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-s3c2440/s3c244x-irq.c linux-libre-2.6.38-gnu1/arch/arm/mach-s3c2440/s3c244x-irq.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-s3c2440/s3c244x-irq.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-s3c2440/s3c244x-irq.c	2011-03-14 21:20:32.000000000 -0400
@@ -68,27 +68,27 @@ static void s3c_irq_demux_cam(unsigned i
 #define INTMSK_CAM (1UL << (IRQ_CAM - IRQ_EINT0))
 
 static void
-s3c_irq_cam_mask(unsigned int irqno)
+s3c_irq_cam_mask(struct irq_data *data)
 {
-	s3c_irqsub_mask(irqno, INTMSK_CAM, 3<<11);
+	s3c_irqsub_mask(data->irq, INTMSK_CAM, 3 << 11);
 }
 
 static void
-s3c_irq_cam_unmask(unsigned int irqno)
+s3c_irq_cam_unmask(struct irq_data *data)
 {
-	s3c_irqsub_unmask(irqno, INTMSK_CAM);
+	s3c_irqsub_unmask(data->irq, INTMSK_CAM);
 }
 
 static void
-s3c_irq_cam_ack(unsigned int irqno)
+s3c_irq_cam_ack(struct irq_data *data)
 {
-	s3c_irqsub_maskack(irqno, INTMSK_CAM, 3<<11);
+	s3c_irqsub_maskack(data->irq, INTMSK_CAM, 3 << 11);
 }
 
 static struct irq_chip s3c_irq_cam = {
-	.mask	    = s3c_irq_cam_mask,
-	.unmask	    = s3c_irq_cam_unmask,
-	.ack	    = s3c_irq_cam_ack,
+	.irq_mask	= s3c_irq_cam_mask,
+	.irq_unmask	= s3c_irq_cam_unmask,
+	.irq_ack	= s3c_irq_cam_ack,
 };
 
 static int s3c244x_irq_add(struct sys_device *sysdev)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-s3c2443/clock.c linux-libre-2.6.38-gnu1/arch/arm/mach-s3c2443/clock.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-s3c2443/clock.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-s3c2443/clock.c	2011-03-14 21:20:32.000000000 -0400
@@ -196,7 +196,7 @@ static struct clksrc_clk clk_hsspi = {
 static struct clksrc_clk clk_hsmmc_div = {
 	.clk	= {
 		.name		= "hsmmc-div",
-		.id		= -1,
+		.id		= 1,
 		.parent		= &clk_esysclk.clk,
 	},
 	.reg_div = { .reg = S3C2443_CLKDIV1, .size = 2, .shift = 6 },
@@ -231,7 +231,7 @@ static int s3c2443_enable_hsmmc(struct c
 
 static struct clk clk_hsmmc = {
 	.name		= "hsmmc-if",
-	.id		= -1,
+	.id		= 1,
 	.parent		= &clk_hsmmc_div.clk,
 	.enable		= s3c2443_enable_hsmmc,
 	.ops		= &(struct clk_ops) {
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-s3c2443/irq.c linux-libre-2.6.38-gnu1/arch/arm/mach-s3c2443/irq.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-s3c2443/irq.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-s3c2443/irq.c	2011-03-14 21:20:32.000000000 -0400
@@ -75,28 +75,27 @@ static void s3c2443_irq_demux_wdtac97(un
 #define INTMSK_WDTAC97	(1UL << (IRQ_WDT - IRQ_EINT0))
 #define SUBMSK_WDTAC97	INTMSK(IRQ_S3C2443_WDT, IRQ_S3C2443_AC97)
 
-static void s3c2443_irq_wdtac97_mask(unsigned int irqno)
+static void s3c2443_irq_wdtac97_mask(struct irq_data *data)
 {
-	s3c_irqsub_mask(irqno, INTMSK_WDTAC97, SUBMSK_WDTAC97);
+	s3c_irqsub_mask(data->irq, INTMSK_WDTAC97, SUBMSK_WDTAC97);
 }
 
-static void s3c2443_irq_wdtac97_unmask(unsigned int irqno)
+static void s3c2443_irq_wdtac97_unmask(struct irq_data *data)
 {
-	s3c_irqsub_unmask(irqno, INTMSK_WDTAC97);
+	s3c_irqsub_unmask(data->irq, INTMSK_WDTAC97);
 }
 
-static void s3c2443_irq_wdtac97_ack(unsigned int irqno)
+static void s3c2443_irq_wdtac97_ack(struct irq_data *data)
 {
-	s3c_irqsub_maskack(irqno, INTMSK_WDTAC97, SUBMSK_WDTAC97);
+	s3c_irqsub_maskack(data->irq, INTMSK_WDTAC97, SUBMSK_WDTAC97);
 }
 
 static struct irq_chip s3c2443_irq_wdtac97 = {
-	.mask	    = s3c2443_irq_wdtac97_mask,
-	.unmask	    = s3c2443_irq_wdtac97_unmask,
-	.ack	    = s3c2443_irq_wdtac97_ack,
+	.irq_mask	= s3c2443_irq_wdtac97_mask,
+	.irq_unmask	= s3c2443_irq_wdtac97_unmask,
+	.irq_ack	= s3c2443_irq_wdtac97_ack,
 };
 
-
 /* LCD sub interrupts */
 
 static void s3c2443_irq_demux_lcd(unsigned int irq, struct irq_desc *desc)
@@ -107,28 +106,27 @@ static void s3c2443_irq_demux_lcd(unsign
 #define INTMSK_LCD	(1UL << (IRQ_LCD - IRQ_EINT0))
 #define SUBMSK_LCD	INTMSK(IRQ_S3C2443_LCD1, IRQ_S3C2443_LCD4)
 
-static void s3c2443_irq_lcd_mask(unsigned int irqno)
+static void s3c2443_irq_lcd_mask(struct irq_data *data)
 {
-	s3c_irqsub_mask(irqno, INTMSK_LCD, SUBMSK_LCD);
+	s3c_irqsub_mask(data->irq, INTMSK_LCD, SUBMSK_LCD);
 }
 
-static void s3c2443_irq_lcd_unmask(unsigned int irqno)
+static void s3c2443_irq_lcd_unmask(struct irq_data *data)
 {
-	s3c_irqsub_unmask(irqno, INTMSK_LCD);
+	s3c_irqsub_unmask(data->irq, INTMSK_LCD);
 }
 
-static void s3c2443_irq_lcd_ack(unsigned int irqno)
+static void s3c2443_irq_lcd_ack(struct irq_data *data)
 {
-	s3c_irqsub_maskack(irqno, INTMSK_LCD, SUBMSK_LCD);
+	s3c_irqsub_maskack(data->irq, INTMSK_LCD, SUBMSK_LCD);
 }
 
 static struct irq_chip s3c2443_irq_lcd = {
-	.mask	    = s3c2443_irq_lcd_mask,
-	.unmask	    = s3c2443_irq_lcd_unmask,
-	.ack	    = s3c2443_irq_lcd_ack,
+	.irq_mask	= s3c2443_irq_lcd_mask,
+	.irq_unmask	= s3c2443_irq_lcd_unmask,
+	.irq_ack	= s3c2443_irq_lcd_ack,
 };
 
-
 /* DMA sub interrupts */
 
 static void s3c2443_irq_demux_dma(unsigned int irq, struct irq_desc *desc)
@@ -139,29 +137,27 @@ static void s3c2443_irq_demux_dma(unsign
 #define INTMSK_DMA	(1UL << (IRQ_S3C2443_DMA - IRQ_EINT0))
 #define SUBMSK_DMA	INTMSK(IRQ_S3C2443_DMA0, IRQ_S3C2443_DMA5)
 
-
-static void s3c2443_irq_dma_mask(unsigned int irqno)
+static void s3c2443_irq_dma_mask(struct irq_data *data)
 {
-	s3c_irqsub_mask(irqno, INTMSK_DMA, SUBMSK_DMA);
+	s3c_irqsub_mask(data->irq, INTMSK_DMA, SUBMSK_DMA);
 }
 
-static void s3c2443_irq_dma_unmask(unsigned int irqno)
+static void s3c2443_irq_dma_unmask(struct irq_data *data)
 {
-	s3c_irqsub_unmask(irqno, INTMSK_DMA);
+	s3c_irqsub_unmask(data->irq, INTMSK_DMA);
 }
 
-static void s3c2443_irq_dma_ack(unsigned int irqno)
+static void s3c2443_irq_dma_ack(struct irq_data *data)
 {
-	s3c_irqsub_maskack(irqno, INTMSK_DMA, SUBMSK_DMA);
+	s3c_irqsub_maskack(data->irq, INTMSK_DMA, SUBMSK_DMA);
 }
 
 static struct irq_chip s3c2443_irq_dma = {
-	.mask	    = s3c2443_irq_dma_mask,
-	.unmask	    = s3c2443_irq_dma_unmask,
-	.ack	    = s3c2443_irq_dma_ack,
+	.irq_mask	= s3c2443_irq_dma_mask,
+	.irq_unmask	= s3c2443_irq_dma_unmask,
+	.irq_ack	= s3c2443_irq_dma_ack,
 };
 
-
 /* UART3 sub interrupts */
 
 static void s3c2443_irq_demux_uart3(unsigned int irq, struct irq_desc *desc)
@@ -172,28 +168,27 @@ static void s3c2443_irq_demux_uart3(unsi
 #define INTMSK_UART3	(1UL << (IRQ_S3C2443_UART3 - IRQ_EINT0))
 #define SUBMSK_UART3	(0x7 << (IRQ_S3C2443_RX3 - S3C2410_IRQSUB(0)))
 
-static void s3c2443_irq_uart3_mask(unsigned int irqno)
+static void s3c2443_irq_uart3_mask(struct irq_data *data)
 {
-	s3c_irqsub_mask(irqno, INTMSK_UART3, SUBMSK_UART3);
+	s3c_irqsub_mask(data->irq, INTMSK_UART3, SUBMSK_UART3);
 }
 
-static void s3c2443_irq_uart3_unmask(unsigned int irqno)
+static void s3c2443_irq_uart3_unmask(struct irq_data *data)
 {
-	s3c_irqsub_unmask(irqno, INTMSK_UART3);
+	s3c_irqsub_unmask(data->irq, INTMSK_UART3);
 }
 
-static void s3c2443_irq_uart3_ack(unsigned int irqno)
+static void s3c2443_irq_uart3_ack(struct irq_data *data)
 {
-	s3c_irqsub_maskack(irqno, INTMSK_UART3, SUBMSK_UART3);
+	s3c_irqsub_maskack(data->irq, INTMSK_UART3, SUBMSK_UART3);
 }
 
 static struct irq_chip s3c2443_irq_uart3 = {
-	.mask	    = s3c2443_irq_uart3_mask,
-	.unmask	    = s3c2443_irq_uart3_unmask,
-	.ack	    = s3c2443_irq_uart3_ack,
+	.irq_mask	= s3c2443_irq_uart3_mask,
+	.irq_unmask	= s3c2443_irq_uart3_unmask,
+	.irq_ack	= s3c2443_irq_uart3_ack,
 };
 
-
 /* CAM sub interrupts */
 
 static void s3c2443_irq_demux_cam(unsigned int irq, struct irq_desc *desc)
@@ -204,25 +199,25 @@ static void s3c2443_irq_demux_cam(unsign
 #define INTMSK_CAM	(1UL << (IRQ_CAM - IRQ_EINT0))
 #define SUBMSK_CAM	INTMSK(IRQ_S3C2440_CAM_C, IRQ_S3C2440_CAM_P)
 
-static void s3c2443_irq_cam_mask(unsigned int irqno)
+static void s3c2443_irq_cam_mask(struct irq_data *data)
 {
-	s3c_irqsub_mask(irqno, INTMSK_CAM, SUBMSK_CAM);
+	s3c_irqsub_mask(data->irq, INTMSK_CAM, SUBMSK_CAM);
 }
 
-static void s3c2443_irq_cam_unmask(unsigned int irqno)
+static void s3c2443_irq_cam_unmask(struct irq_data *data)
 {
-	s3c_irqsub_unmask(irqno, INTMSK_CAM);
+	s3c_irqsub_unmask(data->irq, INTMSK_CAM);
 }
 
-static void s3c2443_irq_cam_ack(unsigned int irqno)
+static void s3c2443_irq_cam_ack(struct irq_data *data)
 {
-	s3c_irqsub_maskack(irqno, INTMSK_CAM, SUBMSK_CAM);
+	s3c_irqsub_maskack(data->irq, INTMSK_CAM, SUBMSK_CAM);
 }
 
 static struct irq_chip s3c2443_irq_cam = {
-	.mask	    = s3c2443_irq_cam_mask,
-	.unmask	    = s3c2443_irq_cam_unmask,
-	.ack	    = s3c2443_irq_cam_ack,
+	.irq_mask	= s3c2443_irq_cam_mask,
+	.irq_unmask	= s3c2443_irq_cam_unmask,
+	.irq_ack	= s3c2443_irq_cam_ack,
 };
 
 /* IRQ initialisation code */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-s3c2443/Kconfig linux-libre-2.6.38-gnu1/arch/arm/mach-s3c2443/Kconfig
--- linux-libre-2.6.37-gnu1/arch/arm/mach-s3c2443/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-s3c2443/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -10,6 +10,7 @@ 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
 
@@ -25,7 +26,7 @@ config MACH_SMDK2443
 	bool "SMDK2443"
 	select CPU_S3C2443
 	select MACH_SMDK
-	select S3C_DEV_HSMMC
+	select S3C_DEV_HSMMC1
 	help
 	  Say Y here if you are using an SMDK2443
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-s3c2443/mach-smdk2443.c linux-libre-2.6.38-gnu1/arch/arm/mach-s3c2443/mach-smdk2443.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-s3c2443/mach-smdk2443.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-s3c2443/mach-smdk2443.c	2011-03-14 21:20:32.000000000 -0400
@@ -99,13 +99,20 @@ static struct s3c2410_uartcfg smdk2443_u
 		.ucon	     = 0x3c5,
 		.ulcon	     = 0x43,
 		.ufcon	     = 0x51,
+	},
+	[3] = {
+		.hwport	     = 3,
+		.flags	     = 0,
+		.ucon	     = 0x3c5,
+		.ulcon	     = 0x03,
+		.ufcon	     = 0x51,
 	}
 };
 
 static struct platform_device *smdk2443_devices[] __initdata = {
 	&s3c_device_wdt,
 	&s3c_device_i2c0,
-	&s3c_device_hsmmc0,
+	&s3c_device_hsmmc1,
 #ifdef CONFIG_SND_SOC_SMDK2443_WM9710
 	&s3c_device_ac97,
 #endif
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-s3c2443/s3c2443.c linux-libre-2.6.38-gnu1/arch/arm/mach-s3c2443/s3c2443.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-s3c2443/s3c2443.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-s3c2443/s3c2443.c	2011-03-14 21:20:32.000000000 -0400
@@ -16,6 +16,7 @@
 #include <linux/list.h>
 #include <linux/timer.h>
 #include <linux/init.h>
+#include <linux/gpio.h>
 #include <linux/platform_device.h>
 #include <linux/serial_core.h>
 #include <linux/sysdev.h>
@@ -32,6 +33,9 @@
 #include <mach/regs-s3c2443-clock.h>
 #include <mach/reset.h>
 
+#include <plat/gpio-core.h>
+#include <plat/gpio-cfg.h>
+#include <plat/gpio-cfg-helpers.h>
 #include <plat/s3c2443.h>
 #include <plat/devs.h>
 #include <plat/cpu.h>
@@ -86,6 +90,9 @@ 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;
+
 	iotable_init(s3c2443_iodesc, ARRAY_SIZE(s3c2443_iodesc));
 }
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-s3c64xx/clock.c linux-libre-2.6.38-gnu1/arch/arm/mach-s3c64xx/clock.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-s3c64xx/clock.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-s3c64xx/clock.c	2011-03-14 21:20:32.000000000 -0400
@@ -127,7 +127,7 @@ int s3c64xx_sclk_ctrl(struct clk *clk, i
 	return s3c64xx_gate(S3C_SCLK_GATE, clk, enable);
 }
 
-static struct clk init_clocks_disable[] = {
+static struct clk init_clocks_off[] = {
 	{
 		.name		= "nand",
 		.id		= -1,
@@ -151,6 +151,12 @@ static struct clk init_clocks_disable[]
 		.enable		= s3c64xx_pclk_ctrl,
 		.ctrlbit	= S3C_CLKCON_PCLK_IIC,
 	}, {
+		.name		= "i2c",
+		.id		= 1,
+		.parent		= &clk_p,
+		.enable		= s3c64xx_pclk_ctrl,
+		.ctrlbit	= S3C6410_CLKCON_PCLK_I2C1,
+	}, {
 		.name		= "iis",
 		.id		= 0,
 		.parent		= &clk_p,
@@ -695,7 +701,7 @@ static struct clksrc_clk clksrcs[] = {
 	}, {
 		.clk	= {
 			.name		= "audio-bus",
-			.id		= -1,  /* There's only one IISv4 port */
+			.id		= 2,
 			.ctrlbit        = S3C6410_CLKCON_SCLK_AUDIO2,
 			.enable		= s3c64xx_sclk_ctrl,
 		},
@@ -834,10 +840,6 @@ static struct clk *clks[] __initdata = {
 void __init s3c64xx_register_clocks(unsigned long xtal, 
 				    unsigned armclk_divlimit)
 {
-	struct clk *clkp;
-	int ret;
-	int ptr;
-
 	armclk_mask = armclk_divlimit;
 
 	s3c24xx_register_baseclocks(xtal);
@@ -845,17 +847,8 @@ void __init s3c64xx_register_clocks(unsi
 
 	s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks));
 
-	clkp = init_clocks_disable;
-	for (ptr = 0; ptr < ARRAY_SIZE(init_clocks_disable); ptr++, clkp++) {
-
-		ret = s3c24xx_register_clock(clkp);
-		if (ret < 0) {
-			printk(KERN_ERR "Failed to register clock %s (%d)\n",
-			       clkp->name, ret);
-		}
-
-		(clkp->enable)(clkp, 0);
-	}
+	s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
+	s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
 
 	s3c24xx_register_clocks(clks1, ARRAY_SIZE(clks1));
 	s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs));
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-s3c64xx/dev-audio.c linux-libre-2.6.38-gnu1/arch/arm/mach-s3c64xx/dev-audio.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-s3c64xx/dev-audio.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-s3c64xx/dev-audio.c	2011-03-14 21:20:32.000000000 -0400
@@ -22,7 +22,12 @@
 #include <plat/audio.h>
 #include <plat/gpio-cfg.h>
 
-static int s3c64xx_i2sv3_cfg_gpio(struct platform_device *pdev)
+static const char *rclksrc[] = {
+	[0] = "iis",
+	[1] = "audio-bus",
+};
+
+static int s3c64xx_i2s_cfg_gpio(struct platform_device *pdev)
 {
 	unsigned int base;
 
@@ -33,6 +38,12 @@ static int s3c64xx_i2sv3_cfg_gpio(struct
 	case 1:
 		base = S3C64XX_GPE(0);
 		break;
+	case 2:
+		s3c_gpio_cfgpin(S3C64XX_GPC(4), S3C_GPIO_SFN(5));
+		s3c_gpio_cfgpin(S3C64XX_GPC(5), S3C_GPIO_SFN(5));
+		s3c_gpio_cfgpin(S3C64XX_GPC(7), S3C_GPIO_SFN(5));
+		s3c_gpio_cfgpin_range(S3C64XX_GPH(6), 4, S3C_GPIO_SFN(5));
+		return 0;
 	default:
 		printk(KERN_DEBUG "Invalid I2S Controller number: %d\n",
 			pdev->id);
@@ -44,16 +55,6 @@ static int s3c64xx_i2sv3_cfg_gpio(struct
 	return 0;
 }
 
-static int s3c64xx_i2sv4_cfg_gpio(struct platform_device *pdev)
-{
-	s3c_gpio_cfgpin(S3C64XX_GPC(4), S3C_GPIO_SFN(5));
-	s3c_gpio_cfgpin(S3C64XX_GPC(5), S3C_GPIO_SFN(5));
-	s3c_gpio_cfgpin(S3C64XX_GPC(7), S3C_GPIO_SFN(5));
-	s3c_gpio_cfgpin_range(S3C64XX_GPH(6), 4, S3C_GPIO_SFN(5));
-
-	return 0;
-}
-
 static struct resource s3c64xx_iis0_resource[] = {
 	[0] = {
 		.start = S3C64XX_PA_IIS0,
@@ -72,17 +73,22 @@ static struct resource s3c64xx_iis0_reso
 	},
 };
 
-static struct s3c_audio_pdata s3c_i2s0_pdata = {
-	.cfg_gpio = s3c64xx_i2sv3_cfg_gpio,
+static struct s3c_audio_pdata i2sv3_pdata = {
+	.cfg_gpio = s3c64xx_i2s_cfg_gpio,
+	.type = {
+		.i2s = {
+			.src_clk = rclksrc,
+		},
+	},
 };
 
 struct platform_device s3c64xx_device_iis0 = {
-	.name		  = "s3c64xx-iis",
+	.name		  = "samsung-i2s",
 	.id		  = 0,
 	.num_resources	  = ARRAY_SIZE(s3c64xx_iis0_resource),
 	.resource	  = s3c64xx_iis0_resource,
 	.dev = {
-		.platform_data = &s3c_i2s0_pdata,
+		.platform_data = &i2sv3_pdata,
 	},
 };
 EXPORT_SYMBOL(s3c64xx_device_iis0);
@@ -105,17 +111,13 @@ static struct resource s3c64xx_iis1_reso
 	},
 };
 
-static struct s3c_audio_pdata s3c_i2s1_pdata = {
-	.cfg_gpio = s3c64xx_i2sv3_cfg_gpio,
-};
-
 struct platform_device s3c64xx_device_iis1 = {
-	.name		  = "s3c64xx-iis",
+	.name		  = "samsung-i2s",
 	.id		  = 1,
 	.num_resources	  = ARRAY_SIZE(s3c64xx_iis1_resource),
 	.resource	  = s3c64xx_iis1_resource,
 	.dev = {
-		.platform_data = &s3c_i2s1_pdata,
+		.platform_data = &i2sv3_pdata,
 	},
 };
 EXPORT_SYMBOL(s3c64xx_device_iis1);
@@ -138,17 +140,23 @@ static struct resource s3c64xx_iisv4_res
 	},
 };
 
-static struct s3c_audio_pdata s3c_i2sv4_pdata = {
-	.cfg_gpio = s3c64xx_i2sv4_cfg_gpio,
+static struct s3c_audio_pdata i2sv4_pdata = {
+	.cfg_gpio = s3c64xx_i2s_cfg_gpio,
+	.type = {
+		.i2s = {
+			.quirks = QUIRK_PRI_6CHAN,
+			.src_clk = rclksrc,
+		},
+	},
 };
 
 struct platform_device s3c64xx_device_iisv4 = {
-	.name		  = "s3c64xx-iis-v4",
-	.id		  = -1,
+	.name = "samsung-i2s",
+	.id = 2,
 	.num_resources	  = ARRAY_SIZE(s3c64xx_iisv4_resource),
 	.resource	  = s3c64xx_iisv4_resource,
 	.dev = {
-		.platform_data = &s3c_i2sv4_pdata,
+		.platform_data = &i2sv4_pdata,
 	},
 };
 EXPORT_SYMBOL(s3c64xx_device_iisv4);
@@ -288,7 +296,7 @@ static struct s3c_audio_pdata s3c_ac97_p
 static u64 s3c64xx_ac97_dmamask = DMA_BIT_MASK(32);
 
 struct platform_device s3c64xx_device_ac97 = {
-	.name		  = "s3c-ac97",
+	.name		  = "samsung-ac97",
 	.id		  = -1,
 	.num_resources	  = ARRAY_SIZE(s3c64xx_ac97_resource),
 	.resource	  = s3c64xx_ac97_resource,
@@ -307,16 +315,3 @@ void __init s3c64xx_ac97_setup_gpio(int
 	else
 		s3c_ac97_pdata.cfg_gpio = s3c64xx_ac97_cfg_gpe;
 }
-
-static u64 s3c_device_audio_dmamask = 0xffffffffUL;
-
-struct platform_device s3c_device_pcm = {
-	.name		  = "s3c24xx-pcm-audio",
-	.id		  = -1,
-	.dev              = {
-		.dma_mask = &s3c_device_audio_dmamask,
-		.coherent_dma_mask = 0xffffffffUL
-	}
-};
-EXPORT_SYMBOL(s3c_device_pcm);
-
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-s3c64xx/dma.c linux-libre-2.6.38-gnu1/arch/arm/mach-s3c64xx/dma.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-s3c64xx/dma.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-s3c64xx/dma.c	2011-03-14 21:20:32.000000000 -0400
@@ -212,6 +212,7 @@ static int s3c64xx_dma_start(struct s3c2
 
 	config = readl(chan->regs + PL080S_CH_CONFIG);
 	config |= PL080_CONFIG_ENABLE;
+	config &= ~PL080_CONFIG_HALT;
 
 	pr_debug("%s: writing config %08x\n", __func__, config);
 	writel(config, chan->regs + PL080S_CH_CONFIG);
@@ -689,12 +690,12 @@ static int s3c64xx_dma_init1(int chno, e
 
 	regptr = regs + PL080_Cx_BASE(0);
 
-	for (ch = 0; ch < 8; ch++, chno++, chptr++) {
-		printk(KERN_INFO "%s: registering DMA %d (%p)\n",
-		       __func__, chno, regptr);
+	for (ch = 0; ch < 8; ch++, chptr++) {
+		pr_debug("%s: registering DMA %d (%p)\n",
+			 __func__, chno + ch, regptr);
 
 		chptr->bit = 1 << ch;
-		chptr->number = chno;
+		chptr->number = chno + ch;
 		chptr->dmac = dmac;
 		chptr->regs = regptr;
 		regptr += PL080_Cx_STRIDE;
@@ -703,7 +704,8 @@ static int s3c64xx_dma_init1(int chno, e
 	/* for the moment, permanently enable the controller */
 	writel(PL080_CONFIG_ENABLE, regs + PL080_CONFIG);
 
-	printk(KERN_INFO "PL080: IRQ %d, at %p\n", irq, regs);
+	printk(KERN_INFO "PL080: IRQ %d, at %p, channels %d..%d\n",
+	       irq, regs, chno, chno+8);
 
 	return 0;
 
@@ -740,7 +742,7 @@ static int __init s3c64xx_dma_init(void)
 	/* Set all DMA configuration to be DMA, not SDMA */
 	writel(0xffffff, S3C_SYSREG(0x110));
 
-	/* Register standard DMA controlers */
+	/* Register standard DMA controllers */
 	s3c64xx_dma_init1(0, DMACH_UART0, IRQ_DMA0, 0x75000000);
 	s3c64xx_dma_init1(8, DMACH_PCM1_TX, IRQ_DMA1, 0x75100000);
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-s3c64xx/gpiolib.c linux-libre-2.6.38-gnu1/arch/arm/mach-s3c64xx/gpiolib.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-s3c64xx/gpiolib.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-s3c64xx/gpiolib.c	2011-03-14 21:20:32.000000000 -0400
@@ -72,7 +72,7 @@ static struct s3c_gpio_cfg gpio_4bit_cfg
 	.get_pull	= s3c_gpio_getpull_updown,
 };
 
-int s3c64xx_gpio2int_gpm(struct gpio_chip *chip, unsigned pin)
+static int s3c64xx_gpio2int_gpm(struct gpio_chip *chip, unsigned pin)
 {
 	return pin < 5 ? IRQ_EINT(23) + pin : -ENXIO;
 }
@@ -138,7 +138,7 @@ static struct s3c_gpio_chip gpio_4bit[]
 	},
 };
 
-int s3c64xx_gpio2int_gpl(struct gpio_chip *chip, unsigned pin)
+static int s3c64xx_gpio2int_gpl(struct gpio_chip *chip, unsigned pin)
 {
 	return pin >= 8 ? IRQ_EINT(16) + pin - 8 : -ENXIO;
 }
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-s3c64xx/irq-eint.c linux-libre-2.6.38-gnu1/arch/arm/mach-s3c64xx/irq-eint.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-s3c64xx/irq-eint.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-s3c64xx/irq-eint.c	2011-03-14 21:20:32.000000000 -0400
@@ -30,41 +30,41 @@
 #include <plat/pm.h>
 
 #define eint_offset(irq)	((irq) - IRQ_EINT(0))
-#define eint_irq_to_bit(irq)	(1 << eint_offset(irq))
+#define eint_irq_to_bit(irq)	((u32)(1 << eint_offset(irq)))
 
-static inline void s3c_irq_eint_mask(unsigned int irq)
+static inline void s3c_irq_eint_mask(struct irq_data *data)
 {
 	u32 mask;
 
 	mask = __raw_readl(S3C64XX_EINT0MASK);
-	mask |= eint_irq_to_bit(irq);
+	mask |= (u32)data->chip_data;
 	__raw_writel(mask, S3C64XX_EINT0MASK);
 }
 
-static void s3c_irq_eint_unmask(unsigned int irq)
+static void s3c_irq_eint_unmask(struct irq_data *data)
 {
 	u32 mask;
 
 	mask = __raw_readl(S3C64XX_EINT0MASK);
-	mask &= ~eint_irq_to_bit(irq);
+	mask &= ~((u32)data->chip_data);
 	__raw_writel(mask, S3C64XX_EINT0MASK);
 }
 
-static inline void s3c_irq_eint_ack(unsigned int irq)
+static inline void s3c_irq_eint_ack(struct irq_data *data)
 {
-	__raw_writel(eint_irq_to_bit(irq), S3C64XX_EINT0PEND);
+	__raw_writel((u32)data->chip_data, S3C64XX_EINT0PEND);
 }
 
-static void s3c_irq_eint_maskack(unsigned int irq)
+static void s3c_irq_eint_maskack(struct irq_data *data)
 {
 	/* compiler should in-line these */
-	s3c_irq_eint_mask(irq);
-	s3c_irq_eint_ack(irq);
+	s3c_irq_eint_mask(data);
+	s3c_irq_eint_ack(data);
 }
 
-static int s3c_irq_eint_set_type(unsigned int irq, unsigned int type)
+static int s3c_irq_eint_set_type(struct irq_data *data, unsigned int type)
 {
-	int offs = eint_offset(irq);
+	int offs = eint_offset(data->irq);
 	int pin, pin_val;
 	int shift;
 	u32 ctrl, mask;
@@ -140,12 +140,12 @@ static int s3c_irq_eint_set_type(unsigne
 
 static struct irq_chip s3c_irq_eint = {
 	.name		= "s3c-eint",
-	.mask		= s3c_irq_eint_mask,
-	.unmask		= s3c_irq_eint_unmask,
-	.mask_ack	= s3c_irq_eint_maskack,
-	.ack		= s3c_irq_eint_ack,
-	.set_type	= s3c_irq_eint_set_type,
-	.set_wake	= s3c_irqext_wake,
+	.irq_mask	= s3c_irq_eint_mask,
+	.irq_unmask	= s3c_irq_eint_unmask,
+	.irq_mask_ack	= s3c_irq_eint_maskack,
+	.irq_ack	= s3c_irq_eint_ack,
+	.irq_set_type	= s3c_irq_eint_set_type,
+	.irq_set_wake	= s3c_irqext_wake,
 };
 
 /* s3c_irq_demux_eint
@@ -198,6 +198,7 @@ static int __init s3c64xx_init_irq_eint(
 
 	for (irq = IRQ_EINT(0); irq <= IRQ_EINT(27); irq++) {
 		set_irq_chip(irq, &s3c_irq_eint);
+		set_irq_chip_data(irq, (void *)eint_irq_to_bit(irq));
 		set_irq_handler(irq, handle_level_irq);
 		set_irq_flags(irq, IRQF_VALID);
 	}
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-s3c64xx/mach-smdk6410.c linux-libre-2.6.38-gnu1/arch/arm/mach-s3c64xx/mach-smdk6410.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-s3c64xx/mach-smdk6410.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-s3c64xx/mach-smdk6410.c	2011-03-14 21:20:32.000000000 -0400
@@ -28,6 +28,7 @@
 #include <linux/delay.h>
 #include <linux/smsc911x.h>
 #include <linux/regulator/fixed.h>
+#include <linux/regulator/machine.h>
 
 #ifdef CONFIG_SMDK6410_WM1190_EV1
 #include <linux/mfd/wm8350/core.h>
@@ -283,7 +284,7 @@ static struct platform_device *smdk6410_
 	&s3c_device_fb,
 	&s3c_device_ohci,
 	&s3c_device_usb_hsotg,
-	&s3c_device_pcm,
+	&samsung_asoc_dma,
 	&s3c64xx_device_iisv4,
 	&samsung_device_keypad,
 
@@ -351,7 +352,7 @@ static struct regulator_init_data smdk64
 /* VDD_UH_MMC, LDO5 on J5 */
 static struct regulator_init_data smdk6410_vdduh_mmc = {
 	.constraints = {
-		.name = "PVDD_UH/PVDD_MMC",
+		.name = "PVDD_UH+PVDD_MMC",
 		.always_on = 1,
 	},
 };
@@ -417,7 +418,7 @@ static struct regulator_init_data smdk64
 /* S3C64xx internal logic & PLL */
 static struct regulator_init_data wm8350_dcdc1_data = {
 	.constraints = {
-		.name = "PVDD_INT/PVDD_PLL",
+		.name = "PVDD_INT+PVDD_PLL",
 		.min_uV = 1200000,
 		.max_uV = 1200000,
 		.always_on = 1,
@@ -452,7 +453,7 @@ static struct regulator_consumer_supply
 
 static struct regulator_init_data wm8350_dcdc4_data = {
 	.constraints = {
-		.name = "PVDD_HI/PVDD_EXT/PVDD_SYS/PVCCM2MTV",
+		.name = "PVDD_HI+PVDD_EXT+PVDD_SYS+PVCCM2MTV",
 		.min_uV = 3000000,
 		.max_uV = 3000000,
 		.always_on = 1,
@@ -464,7 +465,7 @@ static struct regulator_init_data wm8350
 /* OTGi/1190-EV1 HPVDD & AVDD */
 static struct regulator_init_data wm8350_ldo4_data = {
 	.constraints = {
-		.name = "PVDD_OTGI/HPVDD/AVDD",
+		.name = "PVDD_OTGI+HPVDD+AVDD",
 		.min_uV = 1200000,
 		.max_uV = 1200000,
 		.apply_uV = 1,
@@ -552,7 +553,7 @@ static struct wm831x_backlight_pdata wm1
 
 static struct regulator_init_data wm1192_dcdc3 = {
 	.constraints = {
-		.name = "PVDD_MEM/PVDD_GPS",
+		.name = "PVDD_MEM+PVDD_GPS",
 		.always_on = 1,
 	},
 };
@@ -563,7 +564,7 @@ static struct regulator_consumer_supply
 
 static struct regulator_init_data wm1192_ldo1 = {
 	.constraints = {
-		.name = "PVDD_LCD/PVDD_EXT",
+		.name = "PVDD_LCD+PVDD_EXT",
 		.always_on = 1,
 	},
 	.consumer_supplies = wm1192_ldo1_consumers,
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-s3c64xx/setup-keypad.c linux-libre-2.6.38-gnu1/arch/arm/mach-s3c64xx/setup-keypad.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-s3c64xx/setup-keypad.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-s3c64xx/setup-keypad.c	2011-03-14 21:20:32.000000000 -0400
@@ -17,7 +17,7 @@
 void samsung_keypad_cfg_gpio(unsigned int rows, unsigned int cols)
 {
 	/* Set all the necessary GPK pins to special-function 3: KP_ROW[x] */
-	s3c_gpio_cfgrange_nopull(S3C64XX_GPK(8), 8 + rows, S3C_GPIO_SFN(3));
+	s3c_gpio_cfgrange_nopull(S3C64XX_GPK(8), rows, S3C_GPIO_SFN(3));
 
 	/* Set all the necessary GPL pins to special-function 3: KP_COL[x] */
 	s3c_gpio_cfgrange_nopull(S3C64XX_GPL(0), cols, S3C_GPIO_SFN(3));
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-s3c64xx/setup-sdhci.c linux-libre-2.6.38-gnu1/arch/arm/mach-s3c64xx/setup-sdhci.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-s3c64xx/setup-sdhci.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-s3c64xx/setup-sdhci.c	2011-03-14 21:20:32.000000000 -0400
@@ -56,7 +56,7 @@ void s3c6400_setup_sdhci_cfg_card(struct
 	else
 		ctrl3 = (S3C_SDHCI_CTRL3_FCSEL1 | S3C_SDHCI_CTRL3_FCSEL0);
 
-	printk(KERN_INFO "%s: CTRL 2=%08x, 3=%08x\n", __func__, ctrl2, ctrl3);
+	pr_debug("%s: CTRL 2=%08x, 3=%08x\n", __func__, ctrl2, ctrl3);
 	writel(ctrl2, r + S3C_SDHCI_CONTROL2);
 	writel(ctrl3, r + S3C_SDHCI_CONTROL3);
 }
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-s5p6442/clock.c linux-libre-2.6.38-gnu1/arch/arm/mach-s5p6442/clock.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-s5p6442/clock.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-s5p6442/clock.c	2011-03-14 21:20:32.000000000 -0400
@@ -340,7 +340,7 @@ void __init_or_cpufreq s5p6442_setup_clo
 	clk_pclkd1.rate = pclkd1;
 }
 
-static struct clk init_clocks_disable[] = {
+static struct clk init_clocks_off[] = {
 	{
 		.name		= "pdma",
 		.id		= -1,
@@ -408,23 +408,13 @@ static struct clk *clks[] __initdata = {
 
 void __init s5p6442_register_clocks(void)
 {
-	struct clk *clkptr;
-	int i, ret;
-
 	s3c24xx_register_clocks(clks, ARRAY_SIZE(clks));
 
 	s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs));
 	s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks));
 
-	clkptr = init_clocks_disable;
-	for (i = 0; i < ARRAY_SIZE(init_clocks_disable); i++, clkptr++) {
-		ret = s3c24xx_register_clock(clkptr);
-		if (ret < 0) {
-			printk(KERN_ERR "Fail to register clock %s (%d)\n",
-					clkptr->name, ret);
-		} else
-			(clkptr->enable)(clkptr, 0);
-	}
+	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-2.6.37-gnu1/arch/arm/mach-s5p6442/dev-audio.c linux-libre-2.6.38-gnu1/arch/arm/mach-s5p6442/dev-audio.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-s5p6442/dev-audio.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-s5p6442/dev-audio.c	2011-03-14 21:20:32.000000000 -0400
@@ -29,7 +29,7 @@ static int s5p6442_cfg_i2s(struct platfo
 		base = S5P6442_GPC1(0);
 		break;
 
-	case -1:
+	case 0:
 		base = S5P6442_GPC0(0);
 		break;
 
@@ -42,8 +42,19 @@ static int s5p6442_cfg_i2s(struct platfo
 	return 0;
 }
 
-static struct s3c_audio_pdata s3c_i2s_pdata = {
+static const char *rclksrc_v35[] = {
+	[0] = "busclk",
+	[1] = "i2sclk",
+};
+
+static struct s3c_audio_pdata i2sv35_pdata = {
 	.cfg_gpio = s5p6442_cfg_i2s,
+	.type = {
+		.i2s = {
+			.quirks = QUIRK_SEC_DAI | QUIRK_NEED_RSTCLR,
+			.src_clk = rclksrc_v35,
+		},
+	},
 };
 
 static struct resource s5p6442_iis0_resource[] = {
@@ -62,15 +73,34 @@ static struct resource s5p6442_iis0_reso
 		.end   = DMACH_I2S0_RX,
 		.flags = IORESOURCE_DMA,
 	},
+	[3] = {
+		.start = DMACH_I2S0S_TX,
+		.end = DMACH_I2S0S_TX,
+		.flags = IORESOURCE_DMA,
+	},
 };
 
 struct platform_device s5p6442_device_iis0 = {
-	.name		  = "s3c64xx-iis-v4",
-	.id		  = -1,
+	.name = "samsung-i2s",
+	.id = 0,
 	.num_resources	  = ARRAY_SIZE(s5p6442_iis0_resource),
 	.resource	  = s5p6442_iis0_resource,
 	.dev = {
-		.platform_data = &s3c_i2s_pdata,
+		.platform_data = &i2sv35_pdata,
+	},
+};
+
+static const char *rclksrc_v3[] = {
+	[0] = "iis",
+	[1] = "sclk_audio",
+};
+
+static struct s3c_audio_pdata i2sv3_pdata = {
+	.cfg_gpio = s5p6442_cfg_i2s,
+	.type = {
+		.i2s = {
+			.src_clk = rclksrc_v3,
+		},
 	},
 };
 
@@ -93,12 +123,12 @@ static struct resource s5p6442_iis1_reso
 };
 
 struct platform_device s5p6442_device_iis1 = {
-	.name		  = "s3c64xx-iis",
+	.name		  = "samsung-i2s",
 	.id		  = 1,
 	.num_resources	  = ARRAY_SIZE(s5p6442_iis1_resource),
 	.resource	  = s5p6442_iis1_resource,
 	.dev = {
-		.platform_data = &s3c_i2s_pdata,
+		.platform_data = &i2sv3_pdata,
 	},
 };
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-s5p6442/include/mach/map.h linux-libre-2.6.38-gnu1/arch/arm/mach-s5p6442/include/mach/map.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-s5p6442/include/mach/map.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-s5p6442/include/mach/map.h	2011-03-14 21:20:32.000000000 -0400
@@ -1,6 +1,6 @@
 /* linux/arch/arm/mach-s5p6442/include/mach/map.h
  *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
  *		http://www.samsung.com/
  *
  * S5P6442 - Memory map definitions
@@ -16,53 +16,61 @@
 #include <plat/map-base.h>
 #include <plat/map-s5p.h>
 
-#define S5P6442_PA_CHIPID	(0xE0000000)
-#define S5P_PA_CHIPID		S5P6442_PA_CHIPID
+#define S5P6442_PA_SDRAM	0x20000000
 
-#define S5P6442_PA_SYSCON	(0xE0100000)
-#define S5P_PA_SYSCON		S5P6442_PA_SYSCON
+#define S5P6442_PA_I2S0		0xC0B00000
+#define S5P6442_PA_I2S1		0xF2200000
 
-#define S5P6442_PA_GPIO		(0xE0200000)
+#define S5P6442_PA_CHIPID	0xE0000000
 
-#define S5P6442_PA_VIC0		(0xE4000000)
-#define S5P6442_PA_VIC1		(0xE4100000)
-#define S5P6442_PA_VIC2		(0xE4200000)
+#define S5P6442_PA_SYSCON	0xE0100000
 
-#define S5P6442_PA_MDMA		0xE8000000
-#define S5P6442_PA_PDMA		0xE9000000
+#define S5P6442_PA_GPIO		0xE0200000
 
-#define S5P6442_PA_TIMER	(0xEA000000)
-#define S5P_PA_TIMER		S5P6442_PA_TIMER
+#define S5P6442_PA_VIC0		0xE4000000
+#define S5P6442_PA_VIC1		0xE4100000
+#define S5P6442_PA_VIC2		0xE4200000
 
-#define S5P6442_PA_SYSTIMER   	(0xEA100000)
+#define S5P6442_PA_SROMC	0xE7000000
 
-#define S5P6442_PA_WATCHDOG	(0xEA200000)
+#define S5P6442_PA_MDMA		0xE8000000
+#define S5P6442_PA_PDMA		0xE9000000
 
-#define S5P6442_PA_UART		(0xEC000000)
+#define S5P6442_PA_TIMER	0xEA000000
 
-#define S5P_PA_UART0		(S5P6442_PA_UART + 0x0)
-#define S5P_PA_UART1		(S5P6442_PA_UART + 0x400)
-#define S5P_PA_UART2		(S5P6442_PA_UART + 0x800)
-#define S5P_SZ_UART		SZ_256
+#define S5P6442_PA_SYSTIMER	0xEA100000
 
-#define S5P6442_PA_IIC0		(0xEC100000)
+#define S5P6442_PA_WATCHDOG	0xEA200000
 
-#define S5P6442_PA_SDRAM	(0x20000000)
-#define S5P_PA_SDRAM		S5P6442_PA_SDRAM
+#define S5P6442_PA_UART		0xEC000000
 
-#define S5P6442_PA_SPI		0xEC300000
+#define S5P6442_PA_IIC0		0xEC100000
 
-/* I2S */
-#define S5P6442_PA_I2S0		0xC0B00000
-#define S5P6442_PA_I2S1		0xF2200000
+#define S5P6442_PA_SPI		0xEC300000
 
-/* PCM */
 #define S5P6442_PA_PCM0		0xF2400000
 #define S5P6442_PA_PCM1		0xF2500000
 
-/* compatibiltiy defines. */
+/* Compatibiltiy Defines */
+
+#define S3C_PA_IIC		S5P6442_PA_IIC0
 #define S3C_PA_WDT		S5P6442_PA_WATCHDOG
+
+#define S5P_PA_CHIPID		S5P6442_PA_CHIPID
+#define S5P_PA_SDRAM		S5P6442_PA_SDRAM
+#define S5P_PA_SROMC		S5P6442_PA_SROMC
+#define S5P_PA_SYSCON		S5P6442_PA_SYSCON
+#define S5P_PA_TIMER		S5P6442_PA_TIMER
+
+/* UART */
+
 #define S3C_PA_UART		S5P6442_PA_UART
-#define S3C_PA_IIC		S5P6442_PA_IIC0
+
+#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_SZ_UART		SZ_256
 
 #endif /* __ASM_ARCH_MAP_H */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-s5p6442/mach-smdk6442.c linux-libre-2.6.38-gnu1/arch/arm/mach-s5p6442/mach-smdk6442.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-s5p6442/mach-smdk6442.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-s5p6442/mach-smdk6442.c	2011-03-14 21:20:32.000000000 -0400
@@ -12,6 +12,7 @@
 #include <linux/types.h>
 #include <linux/init.h>
 #include <linux/serial_core.h>
+#include <linux/i2c.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
@@ -25,6 +26,7 @@
 #include <plat/s5p6442.h>
 #include <plat/devs.h>
 #include <plat/cpu.h>
+#include <plat/iic.h>
 
 /* Following are default values for UCON, ULCON and UFCON UART registers */
 #define SMDK6442_UCON_DEFAULT	(S3C2410_UCON_TXILEVEL |	\
@@ -65,10 +67,16 @@ static struct s3c2410_uartcfg smdk6442_u
 };
 
 static struct platform_device *smdk6442_devices[] __initdata = {
+	&s3c_device_i2c0,
+	&samsung_asoc_dma,
 	&s5p6442_device_iis0,
 	&s3c_device_wdt,
 };
 
+static struct i2c_board_info smdk6442_i2c_devs0[] __initdata = {
+	{ I2C_BOARD_INFO("wm8580", 0x1b), },
+};
+
 static void __init smdk6442_map_io(void)
 {
 	s5p_init_io(NULL, 0, S5P_VA_CHIPID);
@@ -78,6 +86,9 @@ static void __init smdk6442_map_io(void)
 
 static void __init smdk6442_machine_init(void)
 {
+	s3c_i2c0_set_platdata(NULL);
+	i2c_register_board_info(0, smdk6442_i2c_devs0,
+			ARRAY_SIZE(smdk6442_i2c_devs0));
 	platform_add_devices(smdk6442_devices, ARRAY_SIZE(smdk6442_devices));
 }
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-s5p6442/setup-i2c0.c linux-libre-2.6.38-gnu1/arch/arm/mach-s5p6442/setup-i2c0.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-s5p6442/setup-i2c0.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-s5p6442/setup-i2c0.c	2011-03-14 21:20:32.000000000 -0400
@@ -14,12 +14,15 @@
 
 #include <linux/kernel.h>
 #include <linux/types.h>
+#include <linux/gpio.h>
 
 struct platform_device; /* don't need the contents */
 
+#include <plat/gpio-cfg.h>
 #include <plat/iic.h>
 
 void s3c_i2c0_cfg_gpio(struct platform_device *dev)
 {
-	/* Will be populated later */
+	s3c_gpio_cfgall_range(S5P6442_GPD1(0), 2,
+			      S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP);
 }
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-s5p64x0/clock-s5p6440.c linux-libre-2.6.38-gnu1/arch/arm/mach-s5p64x0/clock-s5p6440.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-s5p64x0/clock-s5p6440.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-s5p64x0/clock-s5p6440.c	2011-03-14 21:20:32.000000000 -0400
@@ -133,7 +133,7 @@ static struct clksrc_clk clk_pclk_low =
  * recommended to keep the following clocks disabled until the driver requests
  * for enabling the clock.
  */
-static struct clk init_clocks_disable[] = {
+static struct clk init_clocks_off[] = {
 	{
 		.name		= "nand",
 		.id		= -1,
@@ -261,7 +261,7 @@ static struct clk init_clocks_disable[]
 		.enable		= s5p64x0_pclk_ctrl,
 		.ctrlbit	= (1 << 25),
 	}, {
-		.name		= "i2s_v40",
+		.name		= "iis",
 		.id		= 0,
 		.parent		= &clk_pclk_low.clk,
 		.enable		= s5p64x0_pclk_ctrl,
@@ -419,7 +419,7 @@ static struct clksrc_sources clkset_audi
 static struct clksrc_clk clksrcs[] = {
 	{
 		.clk	= {
-			.name		= "mmc_bus",
+			.name		= "sclk_mmc",
 			.id		= 0,
 			.ctrlbit	= (1 << 24),
 			.enable		= s5p64x0_sclk_ctrl,
@@ -429,7 +429,7 @@ static struct clksrc_clk clksrcs[] = {
 		.reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 0, .size = 4 },
 	}, {
 		.clk	= {
-			.name		= "mmc_bus",
+			.name		= "sclk_mmc",
 			.id		= 1,
 			.ctrlbit	= (1 << 25),
 			.enable		= s5p64x0_sclk_ctrl,
@@ -439,7 +439,7 @@ static struct clksrc_clk clksrcs[] = {
 		.reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 4, .size = 4 },
 	}, {
 		.clk	= {
-			.name		= "mmc_bus",
+			.name		= "sclk_mmc",
 			.id		= 2,
 			.ctrlbit	= (1 << 26),
 			.enable		= s5p64x0_sclk_ctrl,
@@ -602,8 +602,6 @@ static struct clk *clks[] __initdata = {
 
 void __init s5p6440_register_clocks(void)
 {
-	struct clk *clkp;
-	int ret;
 	int ptr;
 
 	s3c24xx_register_clocks(clks, ARRAY_SIZE(clks));
@@ -614,16 +612,8 @@ void __init s5p6440_register_clocks(void
 	s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs));
 	s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks));
 
-	clkp = init_clocks_disable;
-	for (ptr = 0; ptr < ARRAY_SIZE(init_clocks_disable); ptr++, clkp++) {
-
-		ret = s3c24xx_register_clock(clkp);
-		if (ret < 0) {
-			printk(KERN_ERR "Failed to register clock %s (%d)\n",
-			       clkp->name, ret);
-		}
-		(clkp->enable)(clkp, 0);
-	}
+	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-2.6.37-gnu1/arch/arm/mach-s5p64x0/clock-s5p6450.c linux-libre-2.6.38-gnu1/arch/arm/mach-s5p64x0/clock-s5p6450.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-s5p64x0/clock-s5p6450.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-s5p64x0/clock-s5p6450.c	2011-03-14 21:20:32.000000000 -0400
@@ -181,7 +181,7 @@ static struct clksrc_clk clk_pclk_low =
  * recommended to keep the following clocks disabled until the driver requests
  * for enabling the clock.
  */
-static struct clk init_clocks_disable[] = {
+static struct clk init_clocks_off[] = {
 	{
 		.name		= "usbhost",
 		.id		= -1,
@@ -231,6 +231,12 @@ static struct clk init_clocks_disable[]
 		.enable		= s5p64x0_pclk_ctrl,
 		.ctrlbit	= (1 << 5),
 	}, {
+		.name		= "rtc",
+		.id		= -1,
+		.parent		= &clk_pclk_low.clk,
+		.enable		= s5p64x0_pclk_ctrl,
+		.ctrlbit	= (1 << 6),
+	}, {
 		.name		= "adc",
 		.id		= -1,
 		.parent		= &clk_pclk_low.clk,
@@ -256,11 +262,23 @@ static struct clk init_clocks_disable[]
 		.ctrlbit	= (1 << 22),
 	}, {
 		.name		= "iis",
-		.id		= -1,
+		.id		= 0,
 		.parent		= &clk_pclk_low.clk,
 		.enable		= s5p64x0_pclk_ctrl,
 		.ctrlbit	= (1 << 26),
 	}, {
+		.name		= "iis",
+		.id		= 1,
+		.parent		= &clk_pclk_low.clk,
+		.enable		= s5p64x0_pclk_ctrl,
+		.ctrlbit	= (1 << 15),
+	}, {
+		.name		= "iis",
+		.id		= 2,
+		.parent		= &clk_pclk_low.clk,
+		.enable		= s5p64x0_pclk_ctrl,
+		.ctrlbit	= (1 << 16),
+	}, {
 		.name		= "i2c",
 		.id		= 1,
 		.parent		= &clk_pclk_low.clk,
@@ -633,8 +651,6 @@ void __init_or_cpufreq s5p6450_setup_clo
 
 void __init s5p6450_register_clocks(void)
 {
-	struct clk *clkp;
-	int ret;
 	int ptr;
 
 	for (ptr = 0; ptr < ARRAY_SIZE(sysclks); ptr++)
@@ -643,16 +659,8 @@ void __init s5p6450_register_clocks(void
 	s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs));
 	s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks));
 
-	clkp = init_clocks_disable;
-	for (ptr = 0; ptr < ARRAY_SIZE(init_clocks_disable); ptr++, clkp++) {
-
-		ret = s3c24xx_register_clock(clkp);
-		if (ret < 0) {
-			printk(KERN_ERR "Failed to register clock %s (%d)\n",
-			       clkp->name, ret);
-		}
-		(clkp->enable)(clkp, 0);
-	}
+	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-2.6.37-gnu1/arch/arm/mach-s5p64x0/dev-audio.c linux-libre-2.6.38-gnu1/arch/arm/mach-s5p64x0/dev-audio.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-s5p64x0/dev-audio.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-s5p64x0/dev-audio.c	2011-03-14 21:20:32.000000000 -0400
@@ -19,15 +19,19 @@
 #include <mach/dma.h>
 #include <mach/irqs.h>
 
+static const char *rclksrc[] = {
+	[0] = "iis",
+	[1] = "sclk_audio2",
+};
+
 static int s5p6440_cfg_i2s(struct platform_device *pdev)
 {
-	/* configure GPIO for i2s port */
 	switch (pdev->id) {
-	case -1:
-		s3c_gpio_cfgpin_range(S5P6440_GPR(4), 5, S3C_GPIO_SFN(5));
-		s3c_gpio_cfgpin_range(S5P6440_GPR(13), 2, S3C_GPIO_SFN(5));
+	case 0:
+		s3c_gpio_cfgpin_range(S5P6440_GPC(4), 2, S3C_GPIO_SFN(5));
+		s3c_gpio_cfgpin(S5P6440_GPC(7), S3C_GPIO_SFN(5));
+		s3c_gpio_cfgpin_range(S5P6440_GPH(6), 4, S3C_GPIO_SFN(5));
 		break;
-
 	default:
 		printk(KERN_ERR "Invalid Device %d\n", pdev->id);
 		return -EINVAL;
@@ -36,17 +40,58 @@ static int s5p6440_cfg_i2s(struct platfo
 	return 0;
 }
 
+static struct s3c_audio_pdata s5p6440_i2s_pdata = {
+	.cfg_gpio = s5p6440_cfg_i2s,
+	.type = {
+		.i2s = {
+			.quirks = QUIRK_PRI_6CHAN,
+			.src_clk = rclksrc,
+		},
+	},
+};
+
+static struct resource s5p64x0_i2s0_resource[] = {
+	[0] = {
+		.start	= S5P64X0_PA_I2S,
+		.end	= S5P64X0_PA_I2S + 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,
+	},
+};
+
+struct platform_device s5p6440_device_iis = {
+	.name		= "samsung-i2s",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(s5p64x0_i2s0_resource),
+	.resource	= s5p64x0_i2s0_resource,
+	.dev = {
+		.platform_data = &s5p6440_i2s_pdata,
+	},
+};
+
 static int s5p6450_cfg_i2s(struct platform_device *pdev)
 {
-	/* configure GPIO for i2s port */
 	switch (pdev->id) {
-	case -1:
-		s3c_gpio_cfgpin(S5P6450_GPB(4), S3C_GPIO_SFN(5));
+	case 0:
 		s3c_gpio_cfgpin_range(S5P6450_GPR(4), 5, S3C_GPIO_SFN(5));
 		s3c_gpio_cfgpin_range(S5P6450_GPR(13), 2, S3C_GPIO_SFN(5));
-
 		break;
-
+	case 1:
+		s3c_gpio_cfgpin(S5P6440_GPB(4), S3C_GPIO_SFN(5));
+		s3c_gpio_cfgpin_range(S5P6450_GPC(0), 4, S3C_GPIO_SFN(5));
+		break;
+	case 2:
+		s3c_gpio_cfgpin_range(S5P6450_GPK(0), 5, S3C_GPIO_SFN(5));
+		break;
 	default:
 		printk(KERN_ERR "Invalid Device %d\n", pdev->id);
 		return -EINVAL;
@@ -55,47 +100,86 @@ static int s5p6450_cfg_i2s(struct platfo
 	return 0;
 }
 
-static struct s3c_audio_pdata s5p6440_i2s_pdata = {
-	.cfg_gpio = s5p6440_cfg_i2s,
+static struct s3c_audio_pdata s5p6450_i2s0_pdata = {
+	.cfg_gpio = s5p6450_cfg_i2s,
+	.type = {
+		.i2s = {
+			.quirks = QUIRK_PRI_6CHAN,
+			.src_clk = rclksrc,
+		},
+	},
+};
+
+struct platform_device s5p6450_device_iis0 = {
+	.name		= "samsung-i2s",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(s5p64x0_i2s0_resource),
+	.resource	= s5p64x0_i2s0_resource,
+	.dev = {
+		.platform_data = &s5p6450_i2s0_pdata,
+	},
 };
 
 static struct s3c_audio_pdata s5p6450_i2s_pdata = {
 	.cfg_gpio = s5p6450_cfg_i2s,
+	.type = {
+		.i2s = {
+			.src_clk = rclksrc,
+		},
+	},
 };
 
-static struct resource s5p64x0_iis0_resource[] = {
+static struct resource s5p6450_i2s1_resource[] = {
 	[0] = {
-		.start	= S5P64X0_PA_I2S,
-		.end	= S5P64X0_PA_I2S + 0x100 - 1,
+		.start	= S5P6450_PA_I2S1,
+		.end	= S5P6450_PA_I2S1 + 0x100 - 1,
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
-		.start	= DMACH_I2S0_TX,
-		.end	= DMACH_I2S0_TX,
+		.start	= DMACH_I2S1_TX,
+		.end	= DMACH_I2S1_TX,
 		.flags	= IORESOURCE_DMA,
 	},
 	[2] = {
-		.start	= DMACH_I2S0_RX,
-		.end	= DMACH_I2S0_RX,
+		.start	= DMACH_I2S1_RX,
+		.end	= DMACH_I2S1_RX,
 		.flags	= IORESOURCE_DMA,
 	},
 };
 
-struct platform_device s5p6440_device_iis = {
-	.name		= "s3c64xx-iis-v4",
-	.id		= -1,
-	.num_resources	= ARRAY_SIZE(s5p64x0_iis0_resource),
-	.resource	= s5p64x0_iis0_resource,
+struct platform_device s5p6450_device_iis1 = {
+	.name		= "samsung-i2s",
+	.id		= 1,
+	.num_resources	= ARRAY_SIZE(s5p6450_i2s1_resource),
+	.resource	= s5p6450_i2s1_resource,
 	.dev = {
-		.platform_data = &s5p6440_i2s_pdata,
+		.platform_data = &s5p6450_i2s_pdata,
 	},
 };
 
-struct platform_device s5p6450_device_iis0 = {
-	.name		= "s3c64xx-iis-v4",
-	.id		= -1,
-	.num_resources	= ARRAY_SIZE(s5p64x0_iis0_resource),
-	.resource	= s5p64x0_iis0_resource,
+static struct resource s5p6450_i2s2_resource[] = {
+	[0] = {
+		.start	= S5P6450_PA_I2S2,
+		.end	= S5P6450_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 s5p6450_device_iis2 = {
+	.name		= "samsung-i2s",
+	.id		= 2,
+	.num_resources	= ARRAY_SIZE(s5p6450_i2s2_resource),
+	.resource	= s5p6450_i2s2_resource,
 	.dev = {
 		.platform_data = &s5p6450_i2s_pdata,
 	},
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-s5p64x0/gpio.c linux-libre-2.6.38-gnu1/arch/arm/mach-s5p64x0/gpio.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-s5p64x0/gpio.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-s5p64x0/gpio.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,342 +0,0 @@
-/* linux/arch/arm/mach-s5p64x0/gpio.c
- *
- * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * S5P64X0 - 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 <mach/regs-gpio.h>
-
-#include <plat/gpio-core.h>
-#include <plat/gpio-cfg.h>
-#include <plat/gpio-cfg-helpers.h>
-
-/* To be implemented S5P6450 GPIO */
-
-/*
- * 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
- *
- * [1] BANKF pins 14,15 do not form part of the external interrupt sources
- * [2] BANK has two control registers, GPxCON0 and GPxCON1
- */
-
-static int s5p64x0_gpiolib_rbank_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;
-	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;
-	}
-
-	s3c_gpio_lock(ourchip, flags);
-
-	con = __raw_readl(regcon);
-	con &= ~(0xf << con_4bit_shift(offset));
-	__raw_writel(con, regcon);
-
-	s3c_gpio_unlock(ourchip, flags);
-
-	return 0;
-}
-
-static int s5p64x0_gpiolib_rbank_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 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;
-	}
-
-	s3c_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);
-
-	s3c_gpio_unlock(ourchip, flags);
-
-	return 0;
-}
-
-int s5p64x0_gpio_setcfg_4bit_rbank(struct s3c_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 (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;
-}
-
-static struct s3c_gpio_cfg s5p64x0_gpio_cfgs[] = {
-	{
-		.cfg_eint	= 0,
-	}, {
-		.cfg_eint	= 7,
-	}, {
-		.cfg_eint	= 3,
-		.set_config	= s5p64x0_gpio_setcfg_4bit_rbank,
-	}, {
-		.cfg_eint	= 0,
-		.set_config	= s3c_gpio_setcfg_s3c24xx,
-		.get_config	= s3c_gpio_getcfg_s3c24xx,
-	}, {
-		.cfg_eint	= 2,
-		.set_config	= s3c_gpio_setcfg_s3c24xx,
-		.get_config	= s3c_gpio_getcfg_s3c24xx,
-	}, {
-		.cfg_eint	= 3,
-		.set_config	= s3c_gpio_setcfg_s3c24xx,
-		.get_config	= s3c_gpio_getcfg_s3c24xx,
-	},
-};
-
-static struct s3c_gpio_chip s5p6440_gpio_4bit[] = {
-	{
-		.base	= S5P6440_GPA_BASE,
-		.config	= &s5p64x0_gpio_cfgs[1],
-		.chip	= {
-			.base	= S5P6440_GPA(0),
-			.ngpio	= S5P6440_GPIO_A_NR,
-			.label	= "GPA",
-		},
-	}, {
-		.base	= S5P6440_GPB_BASE,
-		.config	= &s5p64x0_gpio_cfgs[1],
-		.chip	= {
-			.base	= S5P6440_GPB(0),
-			.ngpio	= S5P6440_GPIO_B_NR,
-			.label	= "GPB",
-		},
-	}, {
-		.base	= S5P6440_GPC_BASE,
-		.config	= &s5p64x0_gpio_cfgs[1],
-		.chip	= {
-			.base	= S5P6440_GPC(0),
-			.ngpio	= S5P6440_GPIO_C_NR,
-			.label	= "GPC",
-		},
-	}, {
-		.base	= S5P6440_GPG_BASE,
-		.config	= &s5p64x0_gpio_cfgs[1],
-		.chip	= {
-			.base	= S5P6440_GPG(0),
-			.ngpio	= S5P6440_GPIO_G_NR,
-			.label	= "GPG",
-		},
-	},
-};
-
-static struct s3c_gpio_chip s5p6440_gpio_4bit2[] = {
-	{
-		.base	= S5P6440_GPH_BASE + 0x4,
-		.config	= &s5p64x0_gpio_cfgs[1],
-		.chip	= {
-			.base	= S5P6440_GPH(0),
-			.ngpio	= S5P6440_GPIO_H_NR,
-			.label	= "GPH",
-		},
-	},
-};
-
-static struct s3c_gpio_chip s5p6440_gpio_rbank_4bit2[] = {
-	{
-		.base	= S5P6440_GPR_BASE + 0x4,
-		.config	= &s5p64x0_gpio_cfgs[2],
-		.chip	= {
-			.base	= S5P6440_GPR(0),
-			.ngpio	= S5P6440_GPIO_R_NR,
-			.label	= "GPR",
-		},
-	},
-};
-
-static struct s3c_gpio_chip s5p6440_gpio_2bit[] = {
-	{
-		.base	= S5P6440_GPF_BASE,
-		.config	= &s5p64x0_gpio_cfgs[5],
-		.chip	= {
-			.base	= S5P6440_GPF(0),
-			.ngpio	= S5P6440_GPIO_F_NR,
-			.label	= "GPF",
-		},
-	}, {
-		.base	= S5P6440_GPI_BASE,
-		.config	= &s5p64x0_gpio_cfgs[3],
-		.chip	= {
-			.base	= S5P6440_GPI(0),
-			.ngpio	= S5P6440_GPIO_I_NR,
-			.label	= "GPI",
-		},
-	}, {
-		.base	= S5P6440_GPJ_BASE,
-		.config	= &s5p64x0_gpio_cfgs[3],
-		.chip	= {
-			.base	= S5P6440_GPJ(0),
-			.ngpio	= S5P6440_GPIO_J_NR,
-			.label	= "GPJ",
-		},
-	}, {
-		.base	= S5P6440_GPN_BASE,
-		.config	= &s5p64x0_gpio_cfgs[4],
-		.chip	= {
-			.base	= S5P6440_GPN(0),
-			.ngpio	= S5P6440_GPIO_N_NR,
-			.label	= "GPN",
-		},
-	}, {
-		.base	= S5P6440_GPP_BASE,
-		.config	= &s5p64x0_gpio_cfgs[5],
-		.chip	= {
-			.base	= S5P6440_GPP(0),
-			.ngpio	= S5P6440_GPIO_P_NR,
-			.label	= "GPP",
-		},
-	},
-};
-
-void __init s5p64x0_gpiolib_set_cfg(struct s3c_gpio_cfg *chipcfg, int nr_chips)
-{
-	for (; nr_chips > 0; nr_chips--, chipcfg++) {
-		if (!chipcfg->set_config)
-			chipcfg->set_config	= s3c_gpio_setcfg_s3c64xx_4bit;
-		if (!chipcfg->get_config)
-			chipcfg->get_config	= s3c_gpio_getcfg_s3c64xx_4bit;
-		if (!chipcfg->set_pull)
-			chipcfg->set_pull	= s3c_gpio_setpull_updown;
-		if (!chipcfg->get_pull)
-			chipcfg->get_pull	= s3c_gpio_getpull_updown;
-	}
-}
-
-static void __init s5p64x0_gpio_add_rbank_4bit2(struct s3c_gpio_chip *chip,
-						int nr_chips)
-{
-	for (; nr_chips > 0; nr_chips--, chip++) {
-		chip->chip.direction_input = s5p64x0_gpiolib_rbank_4bit2_input;
-		chip->chip.direction_output =
-					s5p64x0_gpiolib_rbank_4bit2_output;
-		s3c_gpiolib_add(chip);
-	}
-}
-
-static int __init s5p6440_gpiolib_init(void)
-{
-	struct s3c_gpio_chip *chips = s5p6440_gpio_2bit;
-	int nr_chips = ARRAY_SIZE(s5p6440_gpio_2bit);
-
-	s5p64x0_gpiolib_set_cfg(s5p64x0_gpio_cfgs,
-				ARRAY_SIZE(s5p64x0_gpio_cfgs));
-
-	for (; nr_chips > 0; nr_chips--, chips++)
-		s3c_gpiolib_add(chips);
-
-	samsung_gpiolib_add_4bit_chips(s5p6440_gpio_4bit,
-				ARRAY_SIZE(s5p6440_gpio_4bit));
-
-	samsung_gpiolib_add_4bit2_chips(s5p6440_gpio_4bit2,
-				ARRAY_SIZE(s5p6440_gpio_4bit2));
-
-	s5p64x0_gpio_add_rbank_4bit2(s5p6440_gpio_rbank_4bit2,
-				ARRAY_SIZE(s5p6440_gpio_rbank_4bit2));
-
-	return 0;
-}
-arch_initcall(s5p6440_gpiolib_init);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-s5p64x0/gpiolib.c linux-libre-2.6.38-gnu1/arch/arm/mach-s5p64x0/gpiolib.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-s5p64x0/gpiolib.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-s5p64x0/gpiolib.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,511 @@
+/* linux/arch/arm/mach-s5p64x0/gpiolib.c
+ *
+ * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * S5P64X0 - 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 <mach/regs-gpio.h>
+#include <mach/regs-clock.h>
+
+#include <plat/gpio-core.h>
+#include <plat/gpio-cfg.h>
+#include <plat/gpio-cfg-helpers.h>
+
+/*
+ * 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
+ *
+ * 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 int s5p64x0_gpiolib_rbank_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;
+	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;
+	}
+
+	s3c_gpio_lock(ourchip, flags);
+
+	con = __raw_readl(regcon);
+	con &= ~(0xf << con_4bit_shift(offset));
+	__raw_writel(con, regcon);
+
+	s3c_gpio_unlock(ourchip, flags);
+
+	return 0;
+}
+
+static int s5p64x0_gpiolib_rbank_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 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;
+	}
+
+	s3c_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);
+
+	s3c_gpio_unlock(ourchip, flags);
+
+	return 0;
+}
+
+int s5p64x0_gpio_setcfg_4bit_rbank(struct s3c_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 (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;
+}
+
+static struct s3c_gpio_cfg s5p64x0_gpio_cfgs[] = {
+	{
+		.cfg_eint	= 0,
+	}, {
+		.cfg_eint	= 7,
+	}, {
+		.cfg_eint	= 3,
+		.set_config	= s5p64x0_gpio_setcfg_4bit_rbank,
+	}, {
+		.cfg_eint	= 0,
+		.set_config	= s3c_gpio_setcfg_s3c24xx,
+		.get_config	= s3c_gpio_getcfg_s3c24xx,
+	}, {
+		.cfg_eint	= 2,
+		.set_config	= s3c_gpio_setcfg_s3c24xx,
+		.get_config	= s3c_gpio_getcfg_s3c24xx,
+	}, {
+		.cfg_eint	= 3,
+		.set_config	= s3c_gpio_setcfg_s3c24xx,
+		.get_config	= s3c_gpio_getcfg_s3c24xx,
+	},
+};
+
+static struct s3c_gpio_chip s5p6440_gpio_4bit[] = {
+	{
+		.base	= S5P64X0_GPA_BASE,
+		.config	= &s5p64x0_gpio_cfgs[1],
+		.chip	= {
+			.base	= S5P6440_GPA(0),
+			.ngpio	= S5P6440_GPIO_A_NR,
+			.label	= "GPA",
+		},
+	}, {
+		.base	= S5P64X0_GPB_BASE,
+		.config	= &s5p64x0_gpio_cfgs[1],
+		.chip	= {
+			.base	= S5P6440_GPB(0),
+			.ngpio	= S5P6440_GPIO_B_NR,
+			.label	= "GPB",
+		},
+	}, {
+		.base	= S5P64X0_GPC_BASE,
+		.config	= &s5p64x0_gpio_cfgs[1],
+		.chip	= {
+			.base	= S5P6440_GPC(0),
+			.ngpio	= S5P6440_GPIO_C_NR,
+			.label	= "GPC",
+		},
+	}, {
+		.base	= S5P64X0_GPG_BASE,
+		.config	= &s5p64x0_gpio_cfgs[1],
+		.chip	= {
+			.base	= S5P6440_GPG(0),
+			.ngpio	= S5P6440_GPIO_G_NR,
+			.label	= "GPG",
+		},
+	},
+};
+
+static struct s3c_gpio_chip s5p6440_gpio_4bit2[] = {
+	{
+		.base	= S5P64X0_GPH_BASE + 0x4,
+		.config	= &s5p64x0_gpio_cfgs[1],
+		.chip	= {
+			.base	= S5P6440_GPH(0),
+			.ngpio	= S5P6440_GPIO_H_NR,
+			.label	= "GPH",
+		},
+	},
+};
+
+static struct s3c_gpio_chip s5p6440_gpio_rbank_4bit2[] = {
+	{
+		.base	= S5P64X0_GPR_BASE + 0x4,
+		.config	= &s5p64x0_gpio_cfgs[2],
+		.chip	= {
+			.base	= S5P6440_GPR(0),
+			.ngpio	= S5P6440_GPIO_R_NR,
+			.label	= "GPR",
+		},
+	},
+};
+
+static struct s3c_gpio_chip s5p6440_gpio_2bit[] = {
+	{
+		.base	= S5P64X0_GPF_BASE,
+		.config	= &s5p64x0_gpio_cfgs[5],
+		.chip	= {
+			.base	= S5P6440_GPF(0),
+			.ngpio	= S5P6440_GPIO_F_NR,
+			.label	= "GPF",
+		},
+	}, {
+		.base	= S5P64X0_GPI_BASE,
+		.config	= &s5p64x0_gpio_cfgs[3],
+		.chip	= {
+			.base	= S5P6440_GPI(0),
+			.ngpio	= S5P6440_GPIO_I_NR,
+			.label	= "GPI",
+		},
+	}, {
+		.base	= S5P64X0_GPJ_BASE,
+		.config	= &s5p64x0_gpio_cfgs[3],
+		.chip	= {
+			.base	= S5P6440_GPJ(0),
+			.ngpio	= S5P6440_GPIO_J_NR,
+			.label	= "GPJ",
+		},
+	}, {
+		.base	= S5P64X0_GPN_BASE,
+		.config	= &s5p64x0_gpio_cfgs[4],
+		.chip	= {
+			.base	= S5P6440_GPN(0),
+			.ngpio	= S5P6440_GPIO_N_NR,
+			.label	= "GPN",
+		},
+	}, {
+		.base	= S5P64X0_GPP_BASE,
+		.config	= &s5p64x0_gpio_cfgs[5],
+		.chip	= {
+			.base	= S5P6440_GPP(0),
+			.ngpio	= S5P6440_GPIO_P_NR,
+			.label	= "GPP",
+		},
+	},
+};
+
+static struct s3c_gpio_chip s5p6450_gpio_4bit[] = {
+	{
+		.base	= S5P64X0_GPA_BASE,
+		.config	= &s5p64x0_gpio_cfgs[1],
+		.chip	= {
+			.base	= S5P6450_GPA(0),
+			.ngpio	= S5P6450_GPIO_A_NR,
+			.label	= "GPA",
+		},
+	}, {
+		.base	= S5P64X0_GPB_BASE,
+		.config	= &s5p64x0_gpio_cfgs[1],
+		.chip	= {
+			.base	= S5P6450_GPB(0),
+			.ngpio	= S5P6450_GPIO_B_NR,
+			.label	= "GPB",
+		},
+	}, {
+		.base	= S5P64X0_GPC_BASE,
+		.config	= &s5p64x0_gpio_cfgs[1],
+		.chip	= {
+			.base	= S5P6450_GPC(0),
+			.ngpio	= S5P6450_GPIO_C_NR,
+			.label	= "GPC",
+		},
+	}, {
+		.base	= S5P6450_GPD_BASE,
+		.config	= &s5p64x0_gpio_cfgs[1],
+		.chip	= {
+			.base	= S5P6450_GPD(0),
+			.ngpio	= S5P6450_GPIO_D_NR,
+			.label	= "GPD",
+		},
+	}, {
+		.base	= S5P6450_GPK_BASE,
+		.config	= &s5p64x0_gpio_cfgs[1],
+		.chip	= {
+			.base	= S5P6450_GPK(0),
+			.ngpio	= S5P6450_GPIO_K_NR,
+			.label	= "GPK",
+		},
+	},
+};
+
+static struct s3c_gpio_chip s5p6450_gpio_4bit2[] = {
+	{
+		.base	= S5P64X0_GPG_BASE + 0x4,
+		.config	= &s5p64x0_gpio_cfgs[1],
+		.chip	= {
+			.base	= S5P6450_GPG(0),
+			.ngpio	= S5P6450_GPIO_G_NR,
+			.label	= "GPG",
+		},
+	}, {
+		.base	= S5P64X0_GPH_BASE + 0x4,
+		.config	= &s5p64x0_gpio_cfgs[1],
+		.chip	= {
+			.base	= S5P6450_GPH(0),
+			.ngpio	= S5P6450_GPIO_H_NR,
+			.label	= "GPH",
+		},
+	},
+};
+
+static struct s3c_gpio_chip s5p6450_gpio_rbank_4bit2[] = {
+	{
+		.base	= S5P64X0_GPR_BASE + 0x4,
+		.config	= &s5p64x0_gpio_cfgs[2],
+		.chip	= {
+			.base	= S5P6450_GPR(0),
+			.ngpio	= S5P6450_GPIO_R_NR,
+			.label	= "GPR",
+		},
+	},
+};
+
+static struct s3c_gpio_chip s5p6450_gpio_2bit[] = {
+	{
+		.base	= S5P64X0_GPF_BASE,
+		.config	= &s5p64x0_gpio_cfgs[5],
+		.chip	= {
+			.base	= S5P6450_GPF(0),
+			.ngpio	= S5P6450_GPIO_F_NR,
+			.label	= "GPF",
+		},
+	}, {
+		.base	= S5P64X0_GPI_BASE,
+		.config	= &s5p64x0_gpio_cfgs[3],
+		.chip	= {
+			.base	= S5P6450_GPI(0),
+			.ngpio	= S5P6450_GPIO_I_NR,
+			.label	= "GPI",
+		},
+	}, {
+		.base	= S5P64X0_GPJ_BASE,
+		.config	= &s5p64x0_gpio_cfgs[3],
+		.chip	= {
+			.base	= S5P6450_GPJ(0),
+			.ngpio	= S5P6450_GPIO_J_NR,
+			.label	= "GPJ",
+		},
+	}, {
+		.base	= S5P64X0_GPN_BASE,
+		.config	= &s5p64x0_gpio_cfgs[4],
+		.chip	= {
+			.base	= S5P6450_GPN(0),
+			.ngpio	= S5P6450_GPIO_N_NR,
+			.label	= "GPN",
+		},
+	}, {
+		.base	= S5P64X0_GPP_BASE,
+		.config	= &s5p64x0_gpio_cfgs[5],
+		.chip	= {
+			.base	= S5P6450_GPP(0),
+			.ngpio	= S5P6450_GPIO_P_NR,
+			.label	= "GPP",
+		},
+	}, {
+		.base	= S5P6450_GPQ_BASE,
+		.config	= &s5p64x0_gpio_cfgs[4],
+		.chip	= {
+			.base	= S5P6450_GPQ(0),
+			.ngpio	= S5P6450_GPIO_Q_NR,
+			.label	= "GPQ",
+		},
+	}, {
+		.base	= S5P6450_GPS_BASE,
+		.config	= &s5p64x0_gpio_cfgs[5],
+		.chip	= {
+			.base	= S5P6450_GPS(0),
+			.ngpio	= S5P6450_GPIO_S_NR,
+			.label	= "GPS",
+		},
+	},
+};
+
+void __init s5p64x0_gpiolib_set_cfg(struct s3c_gpio_cfg *chipcfg, int nr_chips)
+{
+	for (; nr_chips > 0; nr_chips--, chipcfg++) {
+		if (!chipcfg->set_config)
+			chipcfg->set_config	= s3c_gpio_setcfg_s3c64xx_4bit;
+		if (!chipcfg->get_config)
+			chipcfg->get_config	= s3c_gpio_getcfg_s3c64xx_4bit;
+		if (!chipcfg->set_pull)
+			chipcfg->set_pull	= s3c_gpio_setpull_updown;
+		if (!chipcfg->get_pull)
+			chipcfg->get_pull	= s3c_gpio_getpull_updown;
+	}
+}
+
+static void __init s5p64x0_gpio_add_rbank_4bit2(struct s3c_gpio_chip *chip,
+						int nr_chips)
+{
+	for (; nr_chips > 0; nr_chips--, chip++) {
+		chip->chip.direction_input = s5p64x0_gpiolib_rbank_4bit2_input;
+		chip->chip.direction_output =
+					s5p64x0_gpiolib_rbank_4bit2_output;
+		s3c_gpiolib_add(chip);
+	}
+}
+
+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) {
+		samsung_gpiolib_add_2bit_chips(s5p6450_gpio_2bit,
+					ARRAY_SIZE(s5p6450_gpio_2bit));
+
+		samsung_gpiolib_add_4bit_chips(s5p6450_gpio_4bit,
+					ARRAY_SIZE(s5p6450_gpio_4bit));
+
+		samsung_gpiolib_add_4bit2_chips(s5p6450_gpio_4bit2,
+					ARRAY_SIZE(s5p6450_gpio_4bit2));
+
+		s5p64x0_gpio_add_rbank_4bit2(s5p6450_gpio_rbank_4bit2,
+					ARRAY_SIZE(s5p6450_gpio_rbank_4bit2));
+	} else {
+		samsung_gpiolib_add_2bit_chips(s5p6440_gpio_2bit,
+					ARRAY_SIZE(s5p6440_gpio_2bit));
+
+		samsung_gpiolib_add_4bit_chips(s5p6440_gpio_4bit,
+					ARRAY_SIZE(s5p6440_gpio_4bit));
+
+		samsung_gpiolib_add_4bit2_chips(s5p6440_gpio_4bit2,
+					ARRAY_SIZE(s5p6440_gpio_4bit2));
+
+		s5p64x0_gpio_add_rbank_4bit2(s5p6440_gpio_rbank_4bit2,
+					ARRAY_SIZE(s5p6440_gpio_rbank_4bit2));
+	}
+
+	return 0;
+}
+core_initcall(s5p64x0_gpiolib_init);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-s5p64x0/include/mach/gpio.h linux-libre-2.6.38-gnu1/arch/arm/mach-s5p64x0/include/mach/gpio.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-s5p64x0/include/mach/gpio.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-s5p64x0/include/mach/gpio.h	2011-03-14 21:20:32.000000000 -0400
@@ -23,7 +23,7 @@
 #define S5P6440_GPIO_A_NR	(6)
 #define S5P6440_GPIO_B_NR	(7)
 #define S5P6440_GPIO_C_NR	(8)
-#define S5P6440_GPIO_F_NR	(2)
+#define S5P6440_GPIO_F_NR	(16)
 #define S5P6440_GPIO_G_NR	(7)
 #define S5P6440_GPIO_H_NR	(10)
 #define S5P6440_GPIO_I_NR	(16)
@@ -36,7 +36,7 @@
 #define S5P6450_GPIO_B_NR	(7)
 #define S5P6450_GPIO_C_NR	(8)
 #define S5P6450_GPIO_D_NR	(8)
-#define S5P6450_GPIO_F_NR	(2)
+#define S5P6450_GPIO_F_NR	(16)
 #define S5P6450_GPIO_G_NR	(14)
 #define S5P6450_GPIO_H_NR	(10)
 #define S5P6450_GPIO_I_NR	(16)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-s5p64x0/include/mach/map.h linux-libre-2.6.38-gnu1/arch/arm/mach-s5p64x0/include/mach/map.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-s5p64x0/include/mach/map.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-s5p64x0/include/mach/map.h	2011-03-14 21:20:32.000000000 -0400
@@ -1,6 +1,6 @@
 /* linux/arch/arm/mach-s5p64x0/include/mach/map.h
  *
- * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2009-2011 Samsung Electronics Co., Ltd.
  *		http://www.samsung.com
  *
  * S5P64X0 - Memory map definitions
@@ -16,59 +16,46 @@
 #include <plat/map-base.h>
 #include <plat/map-s5p.h>
 
-#define S5P64X0_PA_SDRAM	(0x20000000)
-
-#define S5P64X0_PA_CHIPID	(0xE0000000)
-#define S5P_PA_CHIPID		S5P64X0_PA_CHIPID
-
-#define S5P64X0_PA_SYSCON	(0xE0100000)
-#define S5P_PA_SYSCON		S5P64X0_PA_SYSCON
-
-#define S5P64X0_PA_GPIO		(0xE0308000)
-
-#define S5P64X0_PA_VIC0		(0xE4000000)
-#define S5P64X0_PA_VIC1		(0xE4100000)
+#define S5P64X0_PA_SDRAM	0x20000000
 
-#define S5P64X0_PA_PDMA		(0xE9000000)
+#define S5P64X0_PA_CHIPID	0xE0000000
 
-#define S5P64X0_PA_TIMER	(0xEA000000)
-#define S5P_PA_TIMER		S5P64X0_PA_TIMER
+#define S5P64X0_PA_SYSCON	0xE0100000
 
-#define S5P64X0_PA_RTC		(0xEA100000)
+#define S5P64X0_PA_GPIO		0xE0308000
 
-#define S5P64X0_PA_WDT		(0xEA200000)
+#define S5P64X0_PA_VIC0		0xE4000000
+#define S5P64X0_PA_VIC1		0xE4100000
 
-#define S5P6440_PA_UART(x)	(0xEC000000 + ((x) * S3C_UART_OFFSET))
-#define S5P6450_PA_UART(x)	((x < 5) ? (0xEC800000 + ((x) * S3C_UART_OFFSET)) : (0xEC000000))
+#define S5P64X0_PA_SROMC	0xE7000000
 
-#define S5P_PA_UART0		S5P6450_PA_UART(0)
-#define S5P_PA_UART1		S5P6450_PA_UART(1)
-#define S5P_PA_UART2		S5P6450_PA_UART(2)
-#define S5P_PA_UART3		S5P6450_PA_UART(3)
-#define S5P_PA_UART4		S5P6450_PA_UART(4)
-#define S5P_PA_UART5		S5P6450_PA_UART(5)
+#define S5P64X0_PA_PDMA		0xE9000000
 
-#define S5P_SZ_UART		SZ_256
+#define S5P64X0_PA_TIMER	0xEA000000
+#define S5P64X0_PA_RTC		0xEA100000
+#define S5P64X0_PA_WDT		0xEA200000
 
-#define S5P6440_PA_IIC0		(0xEC104000)
-#define S5P6440_PA_IIC1		(0xEC20F000)
-#define S5P6450_PA_IIC0		(0xEC100000)
-#define S5P6450_PA_IIC1		(0xEC200000)
+#define S5P6440_PA_IIC0		0xEC104000
+#define S5P6440_PA_IIC1		0xEC20F000
+#define S5P6450_PA_IIC0		0xEC100000
+#define S5P6450_PA_IIC1		0xEC200000
 
-#define S5P64X0_PA_SPI0		(0xEC400000)
-#define S5P64X0_PA_SPI1		(0xEC500000)
+#define S5P64X0_PA_SPI0		0xEC400000
+#define S5P64X0_PA_SPI1		0xEC500000
 
-#define S5P64X0_PA_HSOTG	(0xED100000)
+#define S5P64X0_PA_HSOTG	0xED100000
 
 #define S5P64X0_PA_HSMMC(x)	(0xED800000 + ((x) * 0x100000))
 
-#define S5P64X0_PA_I2S		(0xF2000000)
+#define S5P64X0_PA_I2S		0xF2000000
+#define S5P6450_PA_I2S1		0xF2800000
+#define S5P6450_PA_I2S2		0xF2900000
 
-#define S5P64X0_PA_PCM		(0xF2100000)
+#define S5P64X0_PA_PCM		0xF2100000
 
-#define S5P64X0_PA_ADC		(0xF3000000)
+#define S5P64X0_PA_ADC		0xF3000000
 
-/* compatibiltiy defines. */
+/* Compatibiltiy Defines */
 
 #define S3C_PA_HSMMC0		S5P64X0_PA_HSMMC(0)
 #define S3C_PA_HSMMC1		S5P64X0_PA_HSMMC(1)
@@ -78,6 +65,25 @@
 #define S3C_PA_RTC		S5P64X0_PA_RTC
 #define S3C_PA_WDT		S5P64X0_PA_WDT
 
+#define S5P_PA_CHIPID		S5P64X0_PA_CHIPID
+#define S5P_PA_SROMC		S5P64X0_PA_SROMC
+#define S5P_PA_SYSCON		S5P64X0_PA_SYSCON
+#define S5P_PA_TIMER		S5P64X0_PA_TIMER
+
 #define SAMSUNG_PA_ADC		S5P64X0_PA_ADC
 
+/* UART */
+
+#define S5P6440_PA_UART(x)	(0xEC000000 + ((x) * S3C_UART_OFFSET))
+#define S5P6450_PA_UART(x)	((x < 5) ? (0xEC800000 + ((x) * S3C_UART_OFFSET)) : (0xEC000000))
+
+#define S5P_PA_UART0		S5P6450_PA_UART(0)
+#define S5P_PA_UART1		S5P6450_PA_UART(1)
+#define S5P_PA_UART2		S5P6450_PA_UART(2)
+#define S5P_PA_UART3		S5P6450_PA_UART(3)
+#define S5P_PA_UART4		S5P6450_PA_UART(4)
+#define S5P_PA_UART5		S5P6450_PA_UART(5)
+
+#define S5P_SZ_UART		SZ_256
+
 #endif /* __ASM_ARCH_MAP_H */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-s5p64x0/include/mach/regs-gpio.h linux-libre-2.6.38-gnu1/arch/arm/mach-s5p64x0/include/mach/regs-gpio.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-s5p64x0/include/mach/regs-gpio.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-s5p64x0/include/mach/regs-gpio.h	2011-03-14 21:20:32.000000000 -0400
@@ -15,48 +15,23 @@
 
 #include <mach/map.h>
 
-/* Will be implemented S5P6442 GPIOlib */
-
 /* Base addresses for each of the banks */
 
-#define S5P6440_GPA_BASE		(S5P_VA_GPIO + 0x0000)
-#define S5P6440_GPB_BASE		(S5P_VA_GPIO + 0x0020)
-#define S5P6440_GPC_BASE		(S5P_VA_GPIO + 0x0040)
-#define S5P6440_GPF_BASE		(S5P_VA_GPIO + 0x00A0)
-#define S5P6440_GPG_BASE		(S5P_VA_GPIO + 0x00C0)
-#define S5P6440_GPH_BASE		(S5P_VA_GPIO + 0x00E0)
-#define S5P6440_GPI_BASE		(S5P_VA_GPIO + 0x0100)
-#define S5P6440_GPJ_BASE		(S5P_VA_GPIO + 0x0120)
-#define S5P6440_GPN_BASE		(S5P_VA_GPIO + 0x0830)
-#define S5P6440_GPP_BASE		(S5P_VA_GPIO + 0x0160)
-#define S5P6440_GPR_BASE		(S5P_VA_GPIO + 0x0290)
-
-#define S5P6440_EINT0CON0		(S5P_VA_GPIO + 0x900)
-#define S5P6440_EINT0FLTCON0		(S5P_VA_GPIO + 0x910)
-#define S5P6440_EINT0FLTCON1		(S5P_VA_GPIO + 0x914)
-#define S5P6440_EINT0MASK		(S5P_VA_GPIO + 0x920)
-#define S5P6440_EINT0PEND		(S5P_VA_GPIO + 0x924)
-
-/* for LCD */
-
-#define S5P6440_SPCON_LCD_SEL_RGB	(1 << 0)
-#define S5P6440_SPCON_LCD_SEL_MASK	(3 << 0)
-
-/*
- * These set of macros are not really useful for the
- * GPF/GPI/GPJ/GPN/GPP, useful for others set of GPIO's (4 bit)
- */
-
-#define S5P6440_GPIO_CONMASK(__gpio)	(0xf << ((__gpio) * 4))
-#define S5P6440_GPIO_INPUT(__gpio)	(0x0 << ((__gpio) * 4))
-#define S5P6440_GPIO_OUTPUT(__gpio)	(0x1 << ((__gpio) * 4))
-
-/*
- * Use these macros for GPF/GPI/GPJ/GPN/GPP set of GPIO (2 bit)
- */
+#define S5P64X0_GPA_BASE		(S5P_VA_GPIO + 0x0000)
+#define S5P64X0_GPB_BASE		(S5P_VA_GPIO + 0x0020)
+#define S5P64X0_GPC_BASE		(S5P_VA_GPIO + 0x0040)
+#define S5P64X0_GPF_BASE		(S5P_VA_GPIO + 0x00A0)
+#define S5P64X0_GPG_BASE		(S5P_VA_GPIO + 0x00C0)
+#define S5P64X0_GPH_BASE		(S5P_VA_GPIO + 0x00E0)
+#define S5P64X0_GPI_BASE		(S5P_VA_GPIO + 0x0100)
+#define S5P64X0_GPJ_BASE		(S5P_VA_GPIO + 0x0120)
+#define S5P64X0_GPN_BASE		(S5P_VA_GPIO + 0x0830)
+#define S5P64X0_GPP_BASE		(S5P_VA_GPIO + 0x0160)
+#define S5P64X0_GPR_BASE		(S5P_VA_GPIO + 0x0290)
 
-#define S5P6440_GPIO2_CONMASK(__gpio)	(0x3 << ((__gpio) * 2))
-#define S5P6440_GPIO2_INPUT(__gpio)	(0x0 << ((__gpio) * 2))
-#define S5P6440_GPIO2_OUTPUT(__gpio)	(0x1 << ((__gpio) * 2))
+#define S5P6450_GPD_BASE		(S5P_VA_GPIO + 0x0060)
+#define S5P6450_GPK_BASE		(S5P_VA_GPIO + 0x0140)
+#define S5P6450_GPQ_BASE		(S5P_VA_GPIO + 0x0180)
+#define S5P6450_GPS_BASE		(S5P_VA_GPIO + 0x0300)
 
 #endif /* __ASM_ARCH_REGS_GPIO_H */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-s5p64x0/mach-smdk6440.c linux-libre-2.6.38-gnu1/arch/arm/mach-s5p64x0/mach-smdk6440.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-s5p64x0/mach-smdk6440.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-s5p64x0/mach-smdk6440.c	2011-03-14 21:20:32.000000000 -0400
@@ -95,6 +95,7 @@ static struct platform_device *smdk6440_
 	&s3c_device_i2c1,
 	&s3c_device_ts,
 	&s3c_device_wdt,
+	&samsung_asoc_dma,
 	&s5p6440_device_iis,
 };
 
@@ -117,6 +118,7 @@ static struct s3c2410_platform_i2c s5p64
 
 static struct i2c_board_info smdk6440_i2c_devs0[] __initdata = {
 	{ I2C_BOARD_INFO("24c08", 0x50), },
+	{ I2C_BOARD_INFO("wm8580", 0x1b), },
 };
 
 static struct i2c_board_info smdk6440_i2c_devs1[] __initdata = {
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-s5p64x0/mach-smdk6450.c linux-libre-2.6.38-gnu1/arch/arm/mach-s5p64x0/mach-smdk6450.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-s5p64x0/mach-smdk6450.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-s5p64x0/mach-smdk6450.c	2011-03-14 21:20:32.000000000 -0400
@@ -113,6 +113,7 @@ static struct platform_device *smdk6450_
 	&s3c_device_i2c1,
 	&s3c_device_ts,
 	&s3c_device_wdt,
+	&samsung_asoc_dma,
 	&s5p6450_device_iis0,
 	/* s5p6450_device_spi0 will be added */
 };
@@ -135,6 +136,7 @@ static struct s3c2410_platform_i2c s5p64
 };
 
 static struct i2c_board_info smdk6450_i2c_devs0[] __initdata = {
+	{ I2C_BOARD_INFO("wm8580", 0x1b), },
 	{ I2C_BOARD_INFO("24c08", 0x50), },	/* Samsung KS24C080C EEPROM */
 };
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-s5p64x0/Makefile linux-libre-2.6.38-gnu1/arch/arm/mach-s5p64x0/Makefile
--- linux-libre-2.6.37-gnu1/arch/arm/mach-s5p64x0/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-s5p64x0/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -12,9 +12,9 @@ obj-				:=
 
 # Core support for S5P64X0 system
 
-obj-$(CONFIG_ARCH_S5P64X0)	+= cpu.o init.o clock.o dma.o
+obj-$(CONFIG_ARCH_S5P64X0)	+= cpu.o init.o clock.o dma.o gpiolib.o
 obj-$(CONFIG_ARCH_S5P64X0)	+= setup-i2c0.o
-obj-$(CONFIG_CPU_S5P6440)	+= clock-s5p6440.o gpio.o
+obj-$(CONFIG_CPU_S5P6440)	+= clock-s5p6440.o
 obj-$(CONFIG_CPU_S5P6450)	+= clock-s5p6450.o
 
 # machine support
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-s5pc100/clock.c linux-libre-2.6.38-gnu1/arch/arm/mach-s5pc100/clock.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-s5pc100/clock.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-s5pc100/clock.c	2011-03-14 21:20:32.000000000 -0400
@@ -396,7 +396,7 @@ static int s5pc100_sclk1_ctrl(struct clk
  * recommended to keep the following clocks disabled until the driver requests
  * for enabling the clock.
  */
-static struct clk init_clocks_disable[] = {
+static struct clk init_clocks_off[] = {
 	{
 		.name		= "cssys",
 		.id		= -1,
@@ -1381,8 +1381,6 @@ static struct clk *clks[] __initdata = {
 
 void __init s5pc100_register_clocks(void)
 {
-	struct clk *clkp;
-	int ret;
 	int ptr;
 
 	s3c24xx_register_clocks(clks, ARRAY_SIZE(clks));
@@ -1393,16 +1391,8 @@ void __init s5pc100_register_clocks(void
 	s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs));
 	s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks));
 
-	clkp = init_clocks_disable;
-	for (ptr = 0; ptr < ARRAY_SIZE(init_clocks_disable); ptr++, clkp++) {
-
-		ret = s3c24xx_register_clock(clkp);
-		if (ret < 0) {
-			printk(KERN_ERR "Failed to register clock %s (%d)\n",
-			       clkp->name, ret);
-		}
-		(clkp->enable)(clkp, 0);
-	}
+	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-2.6.37-gnu1/arch/arm/mach-s5pc100/dev-audio.c linux-libre-2.6.38-gnu1/arch/arm/mach-s5pc100/dev-audio.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-s5pc100/dev-audio.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-s5pc100/dev-audio.c	2011-03-14 21:20:32.000000000 -0400
@@ -23,17 +23,14 @@ static int s5pc100_cfg_i2s(struct platfo
 {
 	/* configure GPIO for i2s port */
 	switch (pdev->id) {
+	case 0: /* Dedicated pins */
+		break;
 	case 1:
 		s3c_gpio_cfgpin_range(S5PC100_GPC(0), 5, S3C_GPIO_SFN(2));
 		break;
-
 	case 2:
 		s3c_gpio_cfgpin_range(S5PC100_GPG3(0), 5, S3C_GPIO_SFN(4));
 		break;
-
-	case -1: /* Dedicated pins */
-		break;
-
 	default:
 		printk(KERN_ERR "Invalid Device %d\n", pdev->id);
 		return -EINVAL;
@@ -42,8 +39,20 @@ static int s5pc100_cfg_i2s(struct platfo
 	return 0;
 }
 
-static struct s3c_audio_pdata s3c_i2s_pdata = {
+static const char *rclksrc_v5[] = {
+	[0] = "iis",
+	[1] = "i2sclkd2",
+};
+
+static struct s3c_audio_pdata i2sv5_pdata = {
 	.cfg_gpio = s5pc100_cfg_i2s,
+	.type = {
+		.i2s = {
+			.quirks = QUIRK_PRI_6CHAN | QUIRK_SEC_DAI
+					 | QUIRK_NEED_RSTCLR,
+			.src_clk = rclksrc_v5,
+		},
+	},
 };
 
 static struct resource s5pc100_iis0_resource[] = {
@@ -62,15 +71,34 @@ static struct resource s5pc100_iis0_reso
 		.end   = DMACH_I2S0_RX,
 		.flags = IORESOURCE_DMA,
 	},
+	[3] = {
+		.start = DMACH_I2S0S_TX,
+		.end = DMACH_I2S0S_TX,
+		.flags = IORESOURCE_DMA,
+	},
 };
 
 struct platform_device s5pc100_device_iis0 = {
-	.name		  = "s3c64xx-iis-v4",
-	.id		  = -1,
+	.name = "samsung-i2s",
+	.id = 0,
 	.num_resources	  = ARRAY_SIZE(s5pc100_iis0_resource),
 	.resource	  = s5pc100_iis0_resource,
 	.dev = {
-		.platform_data = &s3c_i2s_pdata,
+		.platform_data = &i2sv5_pdata,
+	},
+};
+
+static const char *rclksrc_v3[] = {
+	[0] = "iis",
+	[1] = "sclk_audio",
+};
+
+static struct s3c_audio_pdata i2sv3_pdata = {
+	.cfg_gpio = s5pc100_cfg_i2s,
+	.type = {
+		.i2s = {
+			.src_clk = rclksrc_v3,
+		},
 	},
 };
 
@@ -93,12 +121,12 @@ static struct resource s5pc100_iis1_reso
 };
 
 struct platform_device s5pc100_device_iis1 = {
-	.name		  = "s3c64xx-iis",
+	.name		  = "samsung-i2s",
 	.id		  = 1,
 	.num_resources	  = ARRAY_SIZE(s5pc100_iis1_resource),
 	.resource	  = s5pc100_iis1_resource,
 	.dev = {
-		.platform_data = &s3c_i2s_pdata,
+		.platform_data = &i2sv3_pdata,
 	},
 };
 
@@ -121,12 +149,12 @@ static struct resource s5pc100_iis2_reso
 };
 
 struct platform_device s5pc100_device_iis2 = {
-	.name		  = "s3c64xx-iis",
+	.name		  = "samsung-i2s",
 	.id		  = 2,
 	.num_resources	  = ARRAY_SIZE(s5pc100_iis2_resource),
 	.resource	  = s5pc100_iis2_resource,
 	.dev = {
-		.platform_data = &s3c_i2s_pdata,
+		.platform_data = &i2sv3_pdata,
 	},
 };
 
@@ -253,7 +281,7 @@ static struct s3c_audio_pdata s3c_ac97_p
 static u64 s5pc100_ac97_dmamask = DMA_BIT_MASK(32);
 
 struct platform_device s5pc100_device_ac97 = {
-	.name		  = "s3c-ac97",
+	.name		  = "samsung-ac97",
 	.id		  = -1,
 	.num_resources	  = ARRAY_SIZE(s5pc100_ac97_resource),
 	.resource	  = s5pc100_ac97_resource,
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-s5pc100/include/mach/map.h linux-libre-2.6.38-gnu1/arch/arm/mach-s5pc100/include/mach/map.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-s5pc100/include/mach/map.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-s5pc100/include/mach/map.h	2011-03-14 21:20:32.000000000 -0400
@@ -1,5 +1,8 @@
 /* linux/arch/arm/mach-s5pc100/include/mach/map.h
  *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
  * Copyright 2009 Samsung Electronics Co.
  *	Byungho Min <bhmin@samsung.com>
  *
@@ -16,143 +19,115 @@
 #include <plat/map-base.h>
 #include <plat/map-s5p.h>
 
-/*
- * map-base.h has already defined virtual memory address
- * S3C_VA_IRQ		S3C_ADDR(0x00000000)	irq controller(s)
- * S3C_VA_SYS		S3C_ADDR(0x00100000)	system control
- * S3C_VA_MEM		S3C_ADDR(0x00200000)	system control (not used)
- * S3C_VA_TIMER		S3C_ADDR(0x00300000)	timer block
- * S3C_VA_WATCHDOG	S3C_ADDR(0x00400000)	watchdog
- * S3C_VA_UART		S3C_ADDR(0x01000000)	UART
- *
- * S5PC100 specific virtual memory address can be defined here
- * S5PC1XX_VA_GPIO	S3C_ADDR(0x00500000)	GPIO
- *
- */
+#define S5PC100_PA_SDRAM		0x20000000
 
-#define S5PC100_PA_ONENAND_BUF	(0xB0000000)
-#define S5PC100_SZ_ONENAND_BUF	(SZ_256M - SZ_32M)
+#define S5PC100_PA_ONENAND		0xE7100000
+#define S5PC100_PA_ONENAND_BUF		0xB0000000
 
-/* Chip ID */
+#define S5PC100_PA_CHIPID		0xE0000000
 
-#define S5PC100_PA_CHIPID	(0xE0000000)
-#define S5P_PA_CHIPID		S5PC100_PA_CHIPID
+#define S5PC100_PA_SYSCON		0xE0100000
 
-#define S5PC100_PA_SYSCON	(0xE0100000)
-#define S5P_PA_SYSCON		S5PC100_PA_SYSCON
+#define S5PC100_PA_OTHERS		0xE0200000
 
-#define S5PC100_PA_OTHERS	(0xE0200000)
-#define S5PC100_VA_OTHERS	(S3C_VA_SYS + 0x10000)
+#define S5PC100_PA_GPIO			0xE0300000
 
-#define S5PC100_PA_GPIO		(0xE0300000)
-#define S5PC1XX_VA_GPIO		S3C_ADDR(0x00500000)
+#define S5PC100_PA_VIC0			0xE4000000
+#define S5PC100_PA_VIC1			0xE4100000
+#define S5PC100_PA_VIC2			0xE4200000
 
-/* Interrupt */
-#define S5PC100_PA_VIC0		(0xE4000000)
-#define S5PC100_PA_VIC1		(0xE4100000)
-#define S5PC100_PA_VIC2		(0xE4200000)
-#define S5PC100_VA_VIC		S3C_VA_IRQ
-#define S5PC100_VA_VIC_OFFSET	0x10000
-#define S5PC1XX_VA_VIC(x)	(S5PC100_VA_VIC + ((x) * S5PC100_VA_VIC_OFFSET))
+#define S5PC100_PA_SROMC		0xE7000000
 
+#define S5PC100_PA_CFCON		0xE7800000
 
-#define S5PC100_PA_ONENAND	(0xE7100000)
+#define S5PC100_PA_MDMA			0xE8100000
+#define S5PC100_PA_PDMA0		0xE9000000
+#define S5PC100_PA_PDMA1		0xE9200000
 
-#define S5PC100_PA_CFCON	(0xE7800000)
+#define S5PC100_PA_TIMER		0xEA000000
+#define S5PC100_PA_SYSTIMER		0xEA100000
+#define S5PC100_PA_WATCHDOG		0xEA200000
+#define S5PC100_PA_RTC			0xEA300000
 
-/* DMA */
-#define S5PC100_PA_MDMA		(0xE8100000)
-#define S5PC100_PA_PDMA0	(0xE9000000)
-#define S5PC100_PA_PDMA1	(0xE9200000)
+#define S5PC100_PA_UART			0xEC000000
 
-/* Timer */
-#define S5PC100_PA_TIMER	(0xEA000000)
-#define S5P_PA_TIMER		S5PC100_PA_TIMER
+#define S5PC100_PA_IIC0			0xEC100000
+#define S5PC100_PA_IIC1			0xEC200000
 
-#define S5PC100_PA_SYSTIMER	(0xEA100000)
+#define S5PC100_PA_SPI0			0xEC300000
+#define S5PC100_PA_SPI1			0xEC400000
+#define S5PC100_PA_SPI2			0xEC500000
 
-#define S5PC100_PA_WATCHDOG	(0xEA200000)
-#define S5PC100_PA_RTC		(0xEA300000)
+#define S5PC100_PA_USB_HSOTG		0xED200000
+#define S5PC100_PA_USB_HSPHY		0xED300000
 
-#define S5PC100_PA_UART		(0xEC000000)
+#define S5PC100_PA_HSMMC(x)		(0xED800000 + ((x) * 0x100000))
 
-#define S5P_PA_UART0		(S5PC100_PA_UART + 0x0)
-#define S5P_PA_UART1		(S5PC100_PA_UART + 0x400)
-#define S5P_PA_UART2		(S5PC100_PA_UART + 0x800)
-#define S5P_PA_UART3		(S5PC100_PA_UART + 0xC00)
-#define S5P_SZ_UART		SZ_256
+#define S5PC100_PA_FB			0xEE000000
 
-#define S5PC100_PA_IIC0		(0xEC100000)
-#define S5PC100_PA_IIC1		(0xEC200000)
+#define S5PC100_PA_FIMC0		0xEE200000
+#define S5PC100_PA_FIMC1		0xEE300000
+#define S5PC100_PA_FIMC2		0xEE400000
 
-/* SPI */
-#define S5PC100_PA_SPI0		0xEC300000
-#define S5PC100_PA_SPI1		0xEC400000
-#define S5PC100_PA_SPI2		0xEC500000
+#define S5PC100_PA_I2S0			0xF2000000
+#define S5PC100_PA_I2S1			0xF2100000
+#define S5PC100_PA_I2S2			0xF2200000
 
-/* USB HS OTG */
-#define S5PC100_PA_USB_HSOTG	(0xED200000)
-#define S5PC100_PA_USB_HSPHY	(0xED300000)
+#define S5PC100_PA_AC97			0xF2300000
 
-#define S5PC100_PA_FB		(0xEE000000)
+#define S5PC100_PA_PCM0			0xF2400000
+#define S5PC100_PA_PCM1			0xF2500000
 
-#define S5PC100_PA_FIMC0	(0xEE200000)
-#define S5PC100_PA_FIMC1	(0xEE300000)
-#define S5PC100_PA_FIMC2	(0xEE400000)
+#define S5PC100_PA_SPDIF		0xF2600000
 
-#define S5PC100_PA_I2S0		(0xF2000000)
-#define S5PC100_PA_I2S1		(0xF2100000)
-#define S5PC100_PA_I2S2		(0xF2200000)
+#define S5PC100_PA_TSADC		0xF3000000
 
-#define S5PC100_PA_AC97		0xF2300000
+#define S5PC100_PA_KEYPAD		0xF3100000
 
-/* PCM */
-#define S5PC100_PA_PCM0		0xF2400000
-#define S5PC100_PA_PCM1		0xF2500000
+/* Compatibiltiy Defines */
 
-#define S5PC100_PA_SPDIF	0xF2600000
+#define S3C_PA_FB			S5PC100_PA_FB
+#define S3C_PA_HSMMC0			S5PC100_PA_HSMMC(0)
+#define S3C_PA_HSMMC1			S5PC100_PA_HSMMC(1)
+#define S3C_PA_HSMMC2			S5PC100_PA_HSMMC(2)
+#define S3C_PA_IIC			S5PC100_PA_IIC0
+#define S3C_PA_IIC1			S5PC100_PA_IIC1
+#define S3C_PA_KEYPAD			S5PC100_PA_KEYPAD
+#define S3C_PA_ONENAND			S5PC100_PA_ONENAND
+#define S3C_PA_ONENAND_BUF		S5PC100_PA_ONENAND_BUF
+#define S3C_PA_RTC			S5PC100_PA_RTC
+#define S3C_PA_TSADC			S5PC100_PA_TSADC
+#define S3C_PA_USB_HSOTG		S5PC100_PA_USB_HSOTG
+#define S3C_PA_USB_HSPHY		S5PC100_PA_USB_HSPHY
+#define S3C_PA_WDT			S5PC100_PA_WATCHDOG
 
-#define S5PC100_PA_TSADC	(0xF3000000)
+#define S5P_PA_CHIPID			S5PC100_PA_CHIPID
+#define S5P_PA_FIMC0			S5PC100_PA_FIMC0
+#define S5P_PA_FIMC1			S5PC100_PA_FIMC1
+#define S5P_PA_FIMC2			S5PC100_PA_FIMC2
+#define S5P_PA_SDRAM			S5PC100_PA_SDRAM
+#define S5P_PA_SROMC			S5PC100_PA_SROMC
+#define S5P_PA_SYSCON			S5PC100_PA_SYSCON
+#define S5P_PA_TIMER			S5PC100_PA_TIMER
 
-/* KEYPAD */
-#define S5PC100_PA_KEYPAD	(0xF3100000)
+#define SAMSUNG_PA_ADC			S5PC100_PA_TSADC
+#define SAMSUNG_PA_CFCON		S5PC100_PA_CFCON
+#define SAMSUNG_PA_KEYPAD		S5PC100_PA_KEYPAD
 
-#define S5PC100_PA_HSMMC(x)	(0xED800000 + ((x) * 0x100000))
+#define S5PC100_VA_OTHERS		(S3C_VA_SYS + 0x10000)
 
-#define S5PC100_PA_SDRAM	(0x20000000)
-#define S5P_PA_SDRAM		S5PC100_PA_SDRAM
+#define S3C_SZ_ONENAND_BUF		(SZ_256M - SZ_32M)
 
-/* compatibiltiy defines. */
-#define S3C_PA_UART		S5PC100_PA_UART
-#define S3C_PA_IIC		S5PC100_PA_IIC0
-#define S3C_PA_IIC1		S5PC100_PA_IIC1
-#define S3C_PA_FB		S5PC100_PA_FB
-#define S3C_PA_G2D		S5PC100_PA_G2D
-#define S3C_PA_G3D		S5PC100_PA_G3D
-#define S3C_PA_JPEG		S5PC100_PA_JPEG
-#define S3C_PA_ROTATOR		S5PC100_PA_ROTATOR
-#define S5P_VA_VIC0		S5PC1XX_VA_VIC(0)
-#define S5P_VA_VIC1		S5PC1XX_VA_VIC(1)
-#define S5P_VA_VIC2		S5PC1XX_VA_VIC(2)
-#define S3C_PA_USB_HSOTG	S5PC100_PA_USB_HSOTG
-#define S3C_PA_USB_HSPHY	S5PC100_PA_USB_HSPHY
-#define S3C_PA_HSMMC0		S5PC100_PA_HSMMC(0)
-#define S3C_PA_HSMMC1		S5PC100_PA_HSMMC(1)
-#define S3C_PA_HSMMC2		S5PC100_PA_HSMMC(2)
-#define S3C_PA_KEYPAD		S5PC100_PA_KEYPAD
-#define S3C_PA_WDT		S5PC100_PA_WATCHDOG
-#define S3C_PA_TSADC		S5PC100_PA_TSADC
-#define S3C_PA_ONENAND		S5PC100_PA_ONENAND
-#define S3C_PA_ONENAND_BUF	S5PC100_PA_ONENAND_BUF
-#define S3C_SZ_ONENAND_BUF	S5PC100_SZ_ONENAND_BUF
-#define S3C_PA_RTC		S5PC100_PA_RTC
+/* UART */
 
-#define SAMSUNG_PA_ADC		S5PC100_PA_TSADC
-#define SAMSUNG_PA_CFCON	S5PC100_PA_CFCON
-#define SAMSUNG_PA_KEYPAD	S5PC100_PA_KEYPAD
+#define S3C_PA_UART			S5PC100_PA_UART
 
-#define S5P_PA_FIMC0		S5PC100_PA_FIMC0
-#define S5P_PA_FIMC1		S5PC100_PA_FIMC1
-#define S5P_PA_FIMC2		S5PC100_PA_FIMC2
+#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)
 
-#endif /* __ASM_ARCH_C100_MAP_H */
+#define S5P_SZ_UART			SZ_256
+
+#endif /* __ASM_ARCH_MAP_H */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-s5pc100/mach-smdkc100.c linux-libre-2.6.38-gnu1/arch/arm/mach-s5pc100/mach-smdkc100.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-s5pc100/mach-smdkc100.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-s5pc100/mach-smdkc100.c	2011-03-14 21:20:32.000000000 -0400
@@ -96,6 +96,7 @@ static struct s3c2410_uartcfg smdkc100_u
 
 /* I2C0 */
 static struct i2c_board_info i2c_devs0[] __initdata = {
+	{I2C_BOARD_INFO("wm8580", 0x1b),},
 };
 
 /* I2C1 */
@@ -190,6 +191,7 @@ static struct platform_device *smdkc100_
 	&s3c_device_ts,
 	&s3c_device_wdt,
 	&smdkc100_lcd_powerdev,
+	&samsung_asoc_dma,
 	&s5pc100_device_iis0,
 	&samsung_device_keypad,
 	&s5pc100_device_ac97,
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-s5pv210/clock.c linux-libre-2.6.38-gnu1/arch/arm/mach-s5pv210/clock.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-s5pv210/clock.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-s5pv210/clock.c	2011-03-14 21:20:32.000000000 -0400
@@ -309,7 +309,7 @@ static struct clk_ops clk_fout_apll_ops
 	.get_rate	= s5pv210_clk_fout_apll_get_rate,
 };
 
-static struct clk init_clocks_disable[] = {
+static struct clk init_clocks_off[] = {
 	{
 		.name		= "pdma",
 		.id		= 0,
@@ -467,20 +467,20 @@ static struct clk init_clocks_disable[]
 		.enable		= s5pv210_clk_ip3_ctrl,
 		.ctrlbit	= (1<<21),
 	}, {
-		.name		= "i2s_v50",
+		.name		= "iis",
 		.id		= 0,
 		.parent		= &clk_p,
 		.enable		= s5pv210_clk_ip3_ctrl,
 		.ctrlbit	= (1<<4),
 	}, {
-		.name		= "i2s_v32",
-		.id		= 0,
+		.name		= "iis",
+		.id		= 1,
 		.parent		= &clk_p,
 		.enable		= s5pv210_clk_ip3_ctrl,
 		.ctrlbit	= (1 << 5),
 	}, {
-		.name		= "i2s_v32",
-		.id		= 1,
+		.name		= "iis",
+		.id		= 2,
 		.parent		= &clk_p,
 		.enable		= s5pv210_clk_ip3_ctrl,
 		.ctrlbit	= (1 << 6),
@@ -525,6 +525,12 @@ static struct clk init_clocks[] = {
 		.parent		= &clk_pclk_psys.clk,
 		.enable		= s5pv210_clk_ip3_ctrl,
 		.ctrlbit	= (1 << 20),
+	}, {
+		.name		= "sromc",
+		.id		= -1,
+		.parent		= &clk_hclk_psys.clk,
+		.enable		= s5pv210_clk_ip1_ctrl,
+		.ctrlbit	= (1 << 26),
 	},
 };
 
@@ -1220,13 +1226,9 @@ static struct clk *clks[] __initdata = {
 
 void __init s5pv210_register_clocks(void)
 {
-	struct clk *clkp;
-	int ret;
 	int ptr;
 
-	ret = s3c24xx_register_clocks(clks, ARRAY_SIZE(clks));
-	if (ret > 0)
-		printk(KERN_ERR "Failed to register %u clocks\n", ret);
+	s3c24xx_register_clocks(clks, ARRAY_SIZE(clks));
 
 	for (ptr = 0; ptr < ARRAY_SIZE(sysclks); ptr++)
 		s3c_register_clksrc(sysclks[ptr], 1);
@@ -1234,15 +1236,8 @@ void __init s5pv210_register_clocks(void
 	s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs));
 	s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks));
 
-	clkp = init_clocks_disable;
-	for (ptr = 0; ptr < ARRAY_SIZE(init_clocks_disable); ptr++, clkp++) {
-		ret = s3c24xx_register_clock(clkp);
-		if (ret < 0) {
-			printk(KERN_ERR "Failed to register clock %s (%d)\n",
-			       clkp->name, ret);
-		}
-		(clkp->enable)(clkp, 0);
-	}
+	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-2.6.37-gnu1/arch/arm/mach-s5pv210/cpu.c linux-libre-2.6.38-gnu1/arch/arm/mach-s5pv210/cpu.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-s5pv210/cpu.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-s5pv210/cpu.c	2011-03-14 21:20:32.000000000 -0400
@@ -81,11 +81,6 @@ static struct map_desc s5pv210_iodesc[]
 		.length		= SZ_512K,
 		.type		= MT_DEVICE,
 	}, {
-		.virtual	= (unsigned long)S5P_VA_SROMC,
-		.pfn		= __phys_to_pfn(S5PV210_PA_SROMC),
-		.length		= SZ_4K,
-		.type		= MT_DEVICE,
-	}, {
 		.virtual	= (unsigned long)S5P_VA_DMC0,
 		.pfn		= __phys_to_pfn(S5PV210_PA_DMC0),
 		.length		= SZ_4K,
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-s5pv210/dev-audio.c linux-libre-2.6.38-gnu1/arch/arm/mach-s5pv210/dev-audio.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-s5pv210/dev-audio.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-s5pv210/dev-audio.c	2011-03-14 21:20:32.000000000 -0400
@@ -19,22 +19,24 @@
 #include <mach/dma.h>
 #include <mach/irqs.h>
 
+static const char *rclksrc[] = {
+	[0] = "busclk",
+	[1] = "i2sclk",
+};
+
 static int s5pv210_cfg_i2s(struct platform_device *pdev)
 {
 	/* configure GPIO for i2s port */
 	switch (pdev->id) {
+	case 0:
+		s3c_gpio_cfgpin_range(S5PV210_GPI(0), 7, S3C_GPIO_SFN(2));
+		break;
 	case 1:
 		s3c_gpio_cfgpin_range(S5PV210_GPC0(0), 5, S3C_GPIO_SFN(2));
 		break;
-
 	case 2:
 		s3c_gpio_cfgpin_range(S5PV210_GPC1(0), 5, S3C_GPIO_SFN(4));
 		break;
-
-	case -1:
-		s3c_gpio_cfgpin_range(S5PV210_GPI(0), 7, S3C_GPIO_SFN(2));
-		break;
-
 	default:
 		printk(KERN_ERR "Invalid Device %d\n", pdev->id);
 		return -EINVAL;
@@ -43,8 +45,15 @@ static int s5pv210_cfg_i2s(struct platfo
 	return 0;
 }
 
-static struct s3c_audio_pdata s3c_i2s_pdata = {
+static struct s3c_audio_pdata i2sv5_pdata = {
 	.cfg_gpio = s5pv210_cfg_i2s,
+	.type = {
+		.i2s = {
+			.quirks = QUIRK_PRI_6CHAN | QUIRK_SEC_DAI
+					 | QUIRK_NEED_RSTCLR,
+			.src_clk = rclksrc,
+		},
+	},
 };
 
 static struct resource s5pv210_iis0_resource[] = {
@@ -63,15 +72,34 @@ static struct resource s5pv210_iis0_reso
 		.end   = DMACH_I2S0_RX,
 		.flags = IORESOURCE_DMA,
 	},
+	[3] = {
+		.start = DMACH_I2S0S_TX,
+		.end = DMACH_I2S0S_TX,
+		.flags = IORESOURCE_DMA,
+	},
 };
 
 struct platform_device s5pv210_device_iis0 = {
-	.name		  = "s3c64xx-iis-v4",
-	.id		  = -1,
+	.name = "samsung-i2s",
+	.id = 0,
 	.num_resources	  = ARRAY_SIZE(s5pv210_iis0_resource),
 	.resource	  = s5pv210_iis0_resource,
 	.dev = {
-		.platform_data = &s3c_i2s_pdata,
+		.platform_data = &i2sv5_pdata,
+	},
+};
+
+static const char *rclksrc_v3[] = {
+	[0] = "iis",
+	[1] = "audio-bus",
+};
+
+static struct s3c_audio_pdata i2sv3_pdata = {
+	.cfg_gpio = s5pv210_cfg_i2s,
+	.type = {
+		.i2s = {
+			.src_clk = rclksrc_v3,
+		},
 	},
 };
 
@@ -94,12 +122,12 @@ static struct resource s5pv210_iis1_reso
 };
 
 struct platform_device s5pv210_device_iis1 = {
-	.name		  = "s3c64xx-iis",
+	.name		  = "samsung-i2s",
 	.id		  = 1,
 	.num_resources	  = ARRAY_SIZE(s5pv210_iis1_resource),
 	.resource	  = s5pv210_iis1_resource,
 	.dev = {
-		.platform_data = &s3c_i2s_pdata,
+		.platform_data = &i2sv3_pdata,
 	},
 };
 
@@ -122,12 +150,12 @@ static struct resource s5pv210_iis2_reso
 };
 
 struct platform_device s5pv210_device_iis2 = {
-	.name		  = "s3c64xx-iis",
+	.name		  = "samsung-i2s",
 	.id		  = 2,
 	.num_resources	  = ARRAY_SIZE(s5pv210_iis2_resource),
 	.resource	  = s5pv210_iis2_resource,
 	.dev = {
-		.platform_data = &s3c_i2s_pdata,
+		.platform_data = &i2sv3_pdata,
 	},
 };
 
@@ -283,7 +311,7 @@ static struct s3c_audio_pdata s3c_ac97_p
 static u64 s5pv210_ac97_dmamask = DMA_BIT_MASK(32);
 
 struct platform_device s5pv210_device_ac97 = {
-	.name		  = "s3c-ac97",
+	.name		  = "samsung-ac97",
 	.id		  = -1,
 	.num_resources	  = ARRAY_SIZE(s5pv210_ac97_resource),
 	.resource	  = s5pv210_ac97_resource,
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-s5pv210/include/mach/irqs.h linux-libre-2.6.38-gnu1/arch/arm/mach-s5pv210/include/mach/irqs.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-s5pv210/include/mach/irqs.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-s5pv210/include/mach/irqs.h	2011-03-14 21:20:32.000000000 -0400
@@ -65,7 +65,7 @@
 #define IRQ_HSMMC0		S5P_IRQ_VIC1(26)
 #define IRQ_HSMMC1		S5P_IRQ_VIC1(27)
 #define IRQ_HSMMC2		S5P_IRQ_VIC1(28)
-#define IRQ_MIPICSI		S5P_IRQ_VIC1(29)
+#define IRQ_MIPI_CSIS		S5P_IRQ_VIC1(29)
 #define IRQ_MIPIDSI		S5P_IRQ_VIC1(30)
 #define IRQ_ONENAND_AUDI	S5P_IRQ_VIC1(31)
 
@@ -132,5 +132,6 @@
 #define IRQ_LCD_FIFO		IRQ_LCD0
 #define IRQ_LCD_VSYNC		IRQ_LCD1
 #define IRQ_LCD_SYSTEM		IRQ_LCD2
+#define IRQ_MIPI_CSIS0		IRQ_MIPI_CSIS
 
 #endif /* ASM_ARCH_IRQS_H */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-s5pv210/include/mach/map.h linux-libre-2.6.38-gnu1/arch/arm/mach-s5pv210/include/mach/map.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-s5pv210/include/mach/map.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-s5pv210/include/mach/map.h	2011-03-14 21:20:32.000000000 -0400
@@ -1,6 +1,6 @@
 /* linux/arch/arm/mach-s5pv210/include/mach/map.h
  *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
  *		http://www.samsung.com/
  *
  * S5PV210 - Memory map definitions
@@ -16,116 +16,120 @@
 #include <plat/map-base.h>
 #include <plat/map-s5p.h>
 
-#define S5PC110_PA_ONENAND	(0xB0000000)
-#define S5P_PA_ONENAND		S5PC110_PA_ONENAND
+#define S5PV210_PA_SDRAM		0x20000000
 
-#define S5PC110_PA_ONENAND_DMA	(0xB0600000)
-#define S5P_PA_ONENAND_DMA	S5PC110_PA_ONENAND_DMA
+#define S5PV210_PA_SROM_BANK5		0xA8000000
 
-#define S5PV210_PA_CHIPID	(0xE0000000)
-#define S5P_PA_CHIPID		S5PV210_PA_CHIPID
+#define S5PC110_PA_ONENAND		0xB0000000
+#define S5PC110_PA_ONENAND_DMA		0xB0600000
 
-#define S5PV210_PA_SYSCON	(0xE0100000)
-#define S5P_PA_SYSCON		S5PV210_PA_SYSCON
+#define S5PV210_PA_CHIPID		0xE0000000
 
-#define S5PV210_PA_GPIO		(0xE0200000)
+#define S5PV210_PA_SYSCON		0xE0100000
 
-/* SPI */
-#define S5PV210_PA_SPI0		0xE1300000
-#define S5PV210_PA_SPI1		0xE1400000
+#define S5PV210_PA_GPIO			0xE0200000
 
-#define S5PV210_PA_KEYPAD	(0xE1600000)
+#define S5PV210_PA_SPDIF		0xE1100000
 
-#define S5PV210_PA_IIC0		(0xE1800000)
-#define S5PV210_PA_IIC1		(0xFAB00000)
-#define S5PV210_PA_IIC2		(0xE1A00000)
+#define S5PV210_PA_SPI0			0xE1300000
+#define S5PV210_PA_SPI1			0xE1400000
 
-#define S5PV210_PA_TIMER	(0xE2500000)
-#define S5P_PA_TIMER		S5PV210_PA_TIMER
+#define S5PV210_PA_KEYPAD		0xE1600000
 
-#define S5PV210_PA_SYSTIMER	(0xE2600000)
+#define S5PV210_PA_ADC			0xE1700000
 
-#define S5PV210_PA_WATCHDOG	(0xE2700000)
+#define S5PV210_PA_IIC0			0xE1800000
+#define S5PV210_PA_IIC1			0xFAB00000
+#define S5PV210_PA_IIC2			0xE1A00000
 
-#define S5PV210_PA_RTC		(0xE2800000)
-#define S5PV210_PA_UART		(0xE2900000)
+#define S5PV210_PA_AC97			0xE2200000
 
-#define S5P_PA_UART0		(S5PV210_PA_UART + 0x0)
-#define S5P_PA_UART1		(S5PV210_PA_UART + 0x400)
-#define S5P_PA_UART2		(S5PV210_PA_UART + 0x800)
-#define S5P_PA_UART3		(S5PV210_PA_UART + 0xC00)
+#define S5PV210_PA_PCM0			0xE2300000
+#define S5PV210_PA_PCM1			0xE1200000
+#define S5PV210_PA_PCM2			0xE2B00000
 
-#define S5P_SZ_UART		SZ_256
+#define S5PV210_PA_TIMER		0xE2500000
+#define S5PV210_PA_SYSTIMER		0xE2600000
+#define S5PV210_PA_WATCHDOG		0xE2700000
+#define S5PV210_PA_RTC			0xE2800000
 
-#define S3C_VA_UARTx(x)		(S3C_VA_UART + ((x) * S3C_UART_OFFSET))
+#define S5PV210_PA_UART			0xE2900000
 
-#define S5PV210_PA_SROMC	(0xE8000000)
+#define S5PV210_PA_SROMC		0xE8000000
 
-#define S5PV210_PA_CFCON	(0xE8200000)
+#define S5PV210_PA_CFCON		0xE8200000
 
-#define S5PV210_PA_MDMA		0xFA200000
-#define S5PV210_PA_PDMA0	0xE0900000
-#define S5PV210_PA_PDMA1	0xE0A00000
+#define S5PV210_PA_HSMMC(x)		(0xEB000000 + ((x) * 0x100000))
 
-#define S5PV210_PA_FB		(0xF8000000)
+#define S5PV210_PA_HSOTG		0xEC000000
+#define S5PV210_PA_HSPHY		0xEC100000
 
-#define S5PV210_PA_FIMC0	(0xFB200000)
-#define S5PV210_PA_FIMC1	(0xFB300000)
-#define S5PV210_PA_FIMC2	(0xFB400000)
+#define S5PV210_PA_IIS0			0xEEE30000
+#define S5PV210_PA_IIS1			0xE2100000
+#define S5PV210_PA_IIS2			0xE2A00000
 
-#define S5PV210_PA_HSMMC(x)	(0xEB000000 + ((x) * 0x100000))
+#define S5PV210_PA_DMC0			0xF0000000
+#define S5PV210_PA_DMC1			0xF1400000
 
-#define S5PV210_PA_HSOTG	(0xEC000000)
-#define S5PV210_PA_HSPHY	(0xEC100000)
+#define S5PV210_PA_VIC0			0xF2000000
+#define S5PV210_PA_VIC1			0xF2100000
+#define S5PV210_PA_VIC2			0xF2200000
+#define S5PV210_PA_VIC3			0xF2300000
 
-#define S5PV210_PA_VIC0		(0xF2000000)
-#define S5PV210_PA_VIC1		(0xF2100000)
-#define S5PV210_PA_VIC2		(0xF2200000)
-#define S5PV210_PA_VIC3		(0xF2300000)
+#define S5PV210_PA_FB			0xF8000000
 
-#define S5PV210_PA_SDRAM	(0x20000000)
-#define S5P_PA_SDRAM		S5PV210_PA_SDRAM
+#define S5PV210_PA_MDMA			0xFA200000
+#define S5PV210_PA_PDMA0		0xE0900000
+#define S5PV210_PA_PDMA1		0xE0A00000
 
-/* S/PDIF */
-#define S5PV210_PA_SPDIF	0xE1100000
+#define S5PV210_PA_MIPI_CSIS		0xFA600000
 
-/* I2S */
-#define S5PV210_PA_IIS0		0xEEE30000
-#define S5PV210_PA_IIS1		0xE2100000
-#define S5PV210_PA_IIS2		0xE2A00000
+#define S5PV210_PA_FIMC0		0xFB200000
+#define S5PV210_PA_FIMC1		0xFB300000
+#define S5PV210_PA_FIMC2		0xFB400000
 
-/* PCM */
-#define S5PV210_PA_PCM0		0xE2300000
-#define S5PV210_PA_PCM1		0xE1200000
-#define S5PV210_PA_PCM2		0xE2B00000
+/* Compatibiltiy Defines */
 
-/* AC97 */
-#define S5PV210_PA_AC97		0xE2200000
+#define S3C_PA_FB			S5PV210_PA_FB
+#define S3C_PA_HSMMC0			S5PV210_PA_HSMMC(0)
+#define S3C_PA_HSMMC1			S5PV210_PA_HSMMC(1)
+#define S3C_PA_HSMMC2			S5PV210_PA_HSMMC(2)
+#define S3C_PA_HSMMC3			S5PV210_PA_HSMMC(3)
+#define S3C_PA_IIC			S5PV210_PA_IIC0
+#define S3C_PA_IIC1			S5PV210_PA_IIC1
+#define S3C_PA_IIC2			S5PV210_PA_IIC2
+#define S3C_PA_RTC			S5PV210_PA_RTC
+#define S3C_PA_USB_HSOTG		S5PV210_PA_HSOTG
+#define S3C_PA_WDT			S5PV210_PA_WATCHDOG
 
-#define S5PV210_PA_ADC		(0xE1700000)
+#define S5P_PA_CHIPID			S5PV210_PA_CHIPID
+#define S5P_PA_FIMC0			S5PV210_PA_FIMC0
+#define S5P_PA_FIMC1			S5PV210_PA_FIMC1
+#define S5P_PA_FIMC2			S5PV210_PA_FIMC2
+#define S5P_PA_MIPI_CSIS0		S5PV210_PA_MIPI_CSIS
+#define S5P_PA_ONENAND			S5PC110_PA_ONENAND
+#define S5P_PA_ONENAND_DMA		S5PC110_PA_ONENAND_DMA
+#define S5P_PA_SDRAM			S5PV210_PA_SDRAM
+#define S5P_PA_SROMC			S5PV210_PA_SROMC
+#define S5P_PA_SYSCON			S5PV210_PA_SYSCON
+#define S5P_PA_TIMER			S5PV210_PA_TIMER
 
-#define S5PV210_PA_DMC0		(0xF0000000)
-#define S5PV210_PA_DMC1		(0xF1400000)
+#define SAMSUNG_PA_ADC			S5PV210_PA_ADC
+#define SAMSUNG_PA_CFCON		S5PV210_PA_CFCON
+#define SAMSUNG_PA_KEYPAD		S5PV210_PA_KEYPAD
 
-/* compatibiltiy defines. */
-#define S3C_PA_UART		S5PV210_PA_UART
-#define S3C_PA_HSMMC0		S5PV210_PA_HSMMC(0)
-#define S3C_PA_HSMMC1		S5PV210_PA_HSMMC(1)
-#define S3C_PA_HSMMC2		S5PV210_PA_HSMMC(2)
-#define S3C_PA_HSMMC3		S5PV210_PA_HSMMC(3)
-#define S3C_PA_IIC		S5PV210_PA_IIC0
-#define S3C_PA_IIC1		S5PV210_PA_IIC1
-#define S3C_PA_IIC2		S5PV210_PA_IIC2
-#define S3C_PA_FB		S5PV210_PA_FB
-#define S3C_PA_RTC		S5PV210_PA_RTC
-#define S3C_PA_WDT		S5PV210_PA_WATCHDOG
-#define S3C_PA_USB_HSOTG	S5PV210_PA_HSOTG
-#define S5P_PA_FIMC0		S5PV210_PA_FIMC0
-#define S5P_PA_FIMC1		S5PV210_PA_FIMC1
-#define S5P_PA_FIMC2		S5PV210_PA_FIMC2
+/* UART */
 
-#define SAMSUNG_PA_ADC		S5PV210_PA_ADC
-#define SAMSUNG_PA_CFCON	S5PV210_PA_CFCON
-#define SAMSUNG_PA_KEYPAD	S5PV210_PA_KEYPAD
+#define S3C_VA_UARTx(x)			(S3C_VA_UART + ((x) * S3C_UART_OFFSET))
+
+#define S3C_PA_UART			S5PV210_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_SZ_UART			SZ_256
 
 #endif /* __ASM_ARCH_MAP_H */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-s5pv210/include/mach/regs-clock.h linux-libre-2.6.38-gnu1/arch/arm/mach-s5pv210/include/mach/regs-clock.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-s5pv210/include/mach/regs-clock.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-s5pv210/include/mach/regs-clock.h	2011-03-14 21:20:32.000000000 -0400
@@ -161,7 +161,7 @@
 #define S5P_MDNIE_SEL		S5P_CLKREG(0x7008)
 #define S5P_MIPI_PHY_CON0	S5P_CLKREG(0x7200)
 #define S5P_MIPI_PHY_CON1	S5P_CLKREG(0x7204)
-#define S5P_MIPI_CONTROL	S5P_CLKREG(0xE814)
+#define S5P_MIPI_DPHY_CONTROL	S5P_CLKREG(0xE814)
 
 #define S5P_IDLE_CFG_TL_MASK	(3 << 30)
 #define S5P_IDLE_CFG_TM_MASK	(3 << 28)
@@ -195,9 +195,6 @@
 #define S5P_OTHERS_RET_UART		(1 << 28)
 #define S5P_OTHERS_USB_SIG_MASK		(1 << 16)
 
-/* MIPI */
-#define S5P_MIPI_DPHY_EN		(3)
-
 /* S5P_DAC_CONTROL */
 #define S5P_DAC_ENABLE			(1)
 #define S5P_DAC_DISABLE			(0)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-s5pv210/Kconfig linux-libre-2.6.38-gnu1/arch/arm/mach-s5pv210/Kconfig
--- linux-libre-2.6.37-gnu1/arch/arm/mach-s5pv210/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-s5pv210/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -118,6 +118,7 @@ menu "S5PV210 Machines"
 config MACH_SMDKV210
 	bool "SMDKV210"
 	select CPU_S5PV210
+	select S3C_DEV_FB
 	select S3C_DEV_HSMMC
 	select S3C_DEV_HSMMC1
 	select S3C_DEV_HSMMC2
@@ -130,6 +131,7 @@ config MACH_SMDKV210
 	select SAMSUNG_DEV_IDE
 	select SAMSUNG_DEV_KEYPAD
 	select SAMSUNG_DEV_TS
+	select S5PV210_SETUP_FB_24BPP
 	select S5PV210_SETUP_I2C1
 	select S5PV210_SETUP_I2C2
 	select S5PV210_SETUP_IDE
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-s5pv210/mach-aquila.c linux-libre-2.6.38-gnu1/arch/arm/mach-s5pv210/mach-aquila.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-s5pv210/mach-aquila.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-s5pv210/mach-aquila.c	2011-03-14 21:20:32.000000000 -0400
@@ -149,7 +149,7 @@ static struct regulator_init_data aquila
 
 static struct regulator_init_data aquila_ldo3_data = {
 	.constraints	= {
-		.name		= "VUSB/MIPI_1.1V",
+		.name		= "VUSB+MIPI_1.1V",
 		.min_uV		= 1100000,
 		.max_uV		= 1100000,
 		.apply_uV	= 1,
@@ -197,7 +197,7 @@ static struct regulator_init_data aquila
 
 static struct regulator_init_data aquila_ldo8_data = {
 	.constraints	= {
-		.name		= "VUSB/VADC_3.3V",
+		.name		= "VUSB+VADC_3.3V",
 		.min_uV		= 3300000,
 		.max_uV		= 3300000,
 		.apply_uV	= 1,
@@ -207,7 +207,7 @@ static struct regulator_init_data aquila
 
 static struct regulator_init_data aquila_ldo9_data = {
 	.constraints	= {
-		.name		= "VCC/VCAM_2.8V",
+		.name		= "VCC+VCAM_2.8V",
 		.min_uV		= 2800000,
 		.max_uV		= 2800000,
 		.apply_uV	= 1,
@@ -381,9 +381,12 @@ static struct max8998_platform_data aqui
 	.buck1_set1	= S5PV210_GPH0(3),
 	.buck1_set2	= S5PV210_GPH0(4),
 	.buck2_set3	= S5PV210_GPH0(5),
-	.buck1_max_voltage1 = 1200000,
-	.buck1_max_voltage2 = 1200000,
-	.buck2_max_voltage = 1200000,
+	.buck1_voltage1	= 1200000,
+	.buck1_voltage2	= 1200000,
+	.buck1_voltage3	= 1200000,
+	.buck1_voltage4	= 1200000,
+	.buck2_voltage1	= 1200000,
+	.buck2_voltage2	= 1200000,
 };
 #endif
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-s5pv210/mach-goni.c linux-libre-2.6.38-gnu1/arch/arm/mach-s5pv210/mach-goni.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-s5pv210/mach-goni.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-s5pv210/mach-goni.c	2011-03-14 21:20:32.000000000 -0400
@@ -288,7 +288,7 @@ static struct regulator_init_data goni_l
 
 static struct regulator_init_data goni_ldo3_data = {
 	.constraints	= {
-		.name		= "VUSB/MIPI_1.1V",
+		.name		= "VUSB+MIPI_1.1V",
 		.min_uV		= 1100000,
 		.max_uV		= 1100000,
 		.apply_uV	= 1,
@@ -337,7 +337,7 @@ static struct regulator_init_data goni_l
 
 static struct regulator_init_data goni_ldo8_data = {
 	.constraints	= {
-		.name		= "VUSB/VADC_3.3V",
+		.name		= "VUSB+VADC_3.3V",
 		.min_uV		= 3300000,
 		.max_uV		= 3300000,
 		.apply_uV	= 1,
@@ -347,7 +347,7 @@ static struct regulator_init_data goni_l
 
 static struct regulator_init_data goni_ldo9_data = {
 	.constraints	= {
-		.name		= "VCC/VCAM_2.8V",
+		.name		= "VCC+VCAM_2.8V",
 		.min_uV		= 2800000,
 		.max_uV		= 2800000,
 		.apply_uV	= 1,
@@ -521,9 +521,12 @@ static struct max8998_platform_data goni
 	.buck1_set1	= S5PV210_GPH0(3),
 	.buck1_set2	= S5PV210_GPH0(4),
 	.buck2_set3	= S5PV210_GPH0(5),
-	.buck1_max_voltage1 = 1200000,
-	.buck1_max_voltage2 = 1200000,
-	.buck2_max_voltage = 1200000,
+	.buck1_voltage1	= 1200000,
+	.buck1_voltage2	= 1200000,
+	.buck1_voltage3	= 1200000,
+	.buck1_voltage4	= 1200000,
+	.buck2_voltage1	= 1200000,
+	.buck2_voltage2	= 1200000,
 };
 #endif
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-s5pv210/mach-smdkc110.c linux-libre-2.6.38-gnu1/arch/arm/mach-s5pv210/mach-smdkc110.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-s5pv210/mach-smdkc110.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-s5pv210/mach-smdkc110.c	2011-03-14 21:20:32.000000000 -0400
@@ -81,6 +81,7 @@ static struct s3c_ide_platdata smdkc110_
 };
 
 static struct platform_device *smdkc110_devices[] __initdata = {
+	&samsung_asoc_dma,
 	&s5pv210_device_iis0,
 	&s5pv210_device_ac97,
 	&s5pv210_device_spdif,
@@ -94,6 +95,7 @@ static struct platform_device *smdkc110_
 
 static struct i2c_board_info smdkc110_i2c_devs0[] __initdata = {
 	{ I2C_BOARD_INFO("24c08", 0x50), },     /* Samsung S524AD0XD1 */
+	{ I2C_BOARD_INFO("wm8580", 0x1b), },
 };
 
 static struct i2c_board_info smdkc110_i2c_devs1[] __initdata = {
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-s5pv210/mach-smdkv210.c linux-libre-2.6.38-gnu1/arch/arm/mach-s5pv210/mach-smdkv210.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-s5pv210/mach-smdkv210.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-s5pv210/mach-smdkv210.c	2011-03-14 21:20:32.000000000 -0400
@@ -14,16 +14,25 @@
 #include <linux/init.h>
 #include <linux/serial_core.h>
 #include <linux/sysdev.h>
+#include <linux/dm9000.h>
+#include <linux/fb.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <asm/setup.h>
 #include <asm/mach-types.h>
 
+#include <video/platform_lcd.h>
+
 #include <mach/map.h>
 #include <mach/regs-clock.h>
+#include <mach/regs-fb.h>
 
 #include <plat/regs-serial.h>
+#include <plat/regs-srom.h>
+#include <plat/gpio-cfg.h>
 #include <plat/s5pv210.h>
 #include <plat/devs.h>
 #include <plat/cpu.h>
@@ -33,6 +42,7 @@
 #include <plat/iic.h>
 #include <plat/keypad.h>
 #include <plat/pm.h>
+#include <plat/fb.h>
 
 /* Following are default values for UCON, ULCON and UFCON UART registers */
 #define SMDKV210_UCON_DEFAULT	(S3C2410_UCON_TXILEVEL |	\
@@ -102,12 +112,106 @@ static struct samsung_keypad_platdata sm
 	.cols		= 8,
 };
 
+static struct resource smdkv210_dm9000_resources[] = {
+	[0] = {
+		.start	= S5PV210_PA_SROM_BANK5,
+		.end	= S5PV210_PA_SROM_BANK5,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= S5PV210_PA_SROM_BANK5 + 2,
+		.end	= S5PV210_PA_SROM_BANK5 + 2,
+		.flags	= IORESOURCE_MEM,
+	},
+	[2] = {
+		.start	= IRQ_EINT(9),
+		.end	= IRQ_EINT(9),
+		.flags	= IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
+	},
+};
+
+static struct dm9000_plat_data smdkv210_dm9000_platdata = {
+	.flags		= DM9000_PLATF_16BITONLY | DM9000_PLATF_NO_EEPROM,
+	.dev_addr	= { 0x00, 0x09, 0xc0, 0xff, 0xec, 0x48 },
+};
+
+struct platform_device smdkv210_dm9000 = {
+	.name		= "dm9000",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(smdkv210_dm9000_resources),
+	.resource	= smdkv210_dm9000_resources,
+	.dev		= {
+		.platform_data	= &smdkv210_dm9000_platdata,
+	},
+};
+
+static void smdkv210_lte480wv_set_power(struct plat_lcd_data *pd,
+					unsigned int power)
+{
+	if (power) {
+#if !defined(CONFIG_BACKLIGHT_PWM)
+		gpio_request(S5PV210_GPD0(3), "GPD0");
+		gpio_direction_output(S5PV210_GPD0(3), 1);
+		gpio_free(S5PV210_GPD0(3));
+#endif
+
+		/* fire nRESET on power up */
+		gpio_request(S5PV210_GPH0(6), "GPH0");
+
+		gpio_direction_output(S5PV210_GPH0(6), 1);
+
+		gpio_set_value(S5PV210_GPH0(6), 0);
+		mdelay(10);
+
+		gpio_set_value(S5PV210_GPH0(6), 1);
+		mdelay(10);
+
+		gpio_free(S5PV210_GPH0(6));
+	} else {
+#if !defined(CONFIG_BACKLIGHT_PWM)
+		gpio_request(S5PV210_GPD0(3), "GPD0");
+		gpio_direction_output(S5PV210_GPD0(3), 0);
+		gpio_free(S5PV210_GPD0(3));
+#endif
+	}
+}
+
+static struct plat_lcd_data smdkv210_lcd_lte480wv_data = {
+	.set_power	= smdkv210_lte480wv_set_power,
+};
+
+static struct platform_device smdkv210_lcd_lte480wv = {
+	.name			= "platform-lcd",
+	.dev.parent		= &s3c_device_fb.dev,
+	.dev.platform_data	= &smdkv210_lcd_lte480wv_data,
+};
+
+static struct s3c_fb_pd_win smdkv210_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 smdkv210_lcd0_pdata __initdata = {
+	.win[0]		= &smdkv210_fb_win0,
+	.vidcon0	= VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,
+	.vidcon1	= VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
+	.setup_gpio	= s5pv210_fb_gpio_setup_24bpp,
+};
+
 static struct platform_device *smdkv210_devices[] __initdata = {
-	&s5pv210_device_iis0,
-	&s5pv210_device_ac97,
-	&s5pv210_device_spdif,
 	&s3c_device_adc,
 	&s3c_device_cfcon,
+	&s3c_device_fb,
 	&s3c_device_hsmmc0,
 	&s3c_device_hsmmc1,
 	&s3c_device_hsmmc2,
@@ -115,14 +219,38 @@ static struct platform_device *smdkv210_
 	&s3c_device_i2c0,
 	&s3c_device_i2c1,
 	&s3c_device_i2c2,
-	&samsung_device_keypad,
 	&s3c_device_rtc,
 	&s3c_device_ts,
 	&s3c_device_wdt,
+	&s5pv210_device_ac97,
+	&s5pv210_device_iis0,
+	&s5pv210_device_spdif,
+	&samsung_asoc_dma,
+	&samsung_device_keypad,
+	&smdkv210_dm9000,
+	&smdkv210_lcd_lte480wv,
 };
 
+static void __init smdkv210_dm9000_init(void)
+{
+	unsigned int tmp;
+
+	gpio_request(S5PV210_MP01(5), "nCS5");
+	s3c_gpio_cfgpin(S5PV210_MP01(5), S3C_GPIO_SFN(2));
+	gpio_free(S5PV210_MP01(5));
+
+	tmp = (5 << S5P_SROM_BCX__TACC__SHIFT);
+	__raw_writel(tmp, S5P_SROM_BC5);
+
+	tmp = __raw_readl(S5P_SROM_BW);
+	tmp &= (S5P_SROM_BW__CS_MASK << S5P_SROM_BW__NCS5__SHIFT);
+	tmp |= (1 << S5P_SROM_BW__NCS5__SHIFT);
+	__raw_writel(tmp, S5P_SROM_BW);
+}
+
 static struct i2c_board_info smdkv210_i2c_devs0[] __initdata = {
 	{ I2C_BOARD_INFO("24c08", 0x50), },     /* Samsung S524AD0XD1 */
+	{ I2C_BOARD_INFO("wm8580", 0x1b), },
 };
 
 static struct i2c_board_info smdkv210_i2c_devs1[] __initdata = {
@@ -150,6 +278,8 @@ static void __init smdkv210_machine_init
 {
 	s3c_pm_init();
 
+	smdkv210_dm9000_init();
+
 	samsung_keypad_set_platdata(&smdkv210_keypad_data);
 	s3c24xx_ts_set_platdata(&s3c_ts_platform);
 
@@ -165,6 +295,8 @@ static void __init smdkv210_machine_init
 
 	s3c_ide_set_platdata(&smdkv210_ide_pdata);
 
+	s3c_fb_set_platdata(&smdkv210_lcd0_pdata);
+
 	platform_add_devices(smdkv210_devices, ARRAY_SIZE(smdkv210_devices));
 }
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-s5pv310/clock.c linux-libre-2.6.38-gnu1/arch/arm/mach-s5pv310/clock.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-s5pv310/clock.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-s5pv310/clock.c	2011-03-14 21:20:32.000000000 -0400
@@ -244,7 +244,7 @@ static struct clksrc_clk clk_mout_corebu
 		.id		= -1,
 	},
 	.sources	= &clkset_mout_corebus,
-	.reg_src	= { .reg = S5P_CLKSRC_CORE, .shift = 4, .size = 1 },
+	.reg_src	= { .reg = S5P_CLKSRC_DMC, .shift = 4, .size = 1 },
 };
 
 static struct clksrc_clk clk_sclk_dmc = {
@@ -253,7 +253,7 @@ static struct clksrc_clk clk_sclk_dmc =
 		.id		= -1,
 		.parent		= &clk_mout_corebus.clk,
 	},
-	.reg_div	= { .reg = S5P_CLKDIV_CORE0, .shift = 12, .size = 3 },
+	.reg_div	= { .reg = S5P_CLKDIV_DMC0, .shift = 12, .size = 3 },
 };
 
 static struct clksrc_clk clk_aclk_cored = {
@@ -262,7 +262,7 @@ static struct clksrc_clk clk_aclk_cored
 		.id		= -1,
 		.parent		= &clk_sclk_dmc.clk,
 	},
-	.reg_div	= { .reg = S5P_CLKDIV_CORE0, .shift = 16, .size = 3 },
+	.reg_div	= { .reg = S5P_CLKDIV_DMC0, .shift = 16, .size = 3 },
 };
 
 static struct clksrc_clk clk_aclk_corep = {
@@ -271,7 +271,7 @@ static struct clksrc_clk clk_aclk_corep
 		.id		= -1,
 		.parent		= &clk_aclk_cored.clk,
 	},
-	.reg_div	= { .reg = S5P_CLKDIV_CORE0, .shift = 20, .size = 3 },
+	.reg_div	= { .reg = S5P_CLKDIV_DMC0, .shift = 20, .size = 3 },
 };
 
 static struct clksrc_clk clk_aclk_acp = {
@@ -280,7 +280,7 @@ static struct clksrc_clk clk_aclk_acp =
 		.id		= -1,
 		.parent		= &clk_mout_corebus.clk,
 	},
-	.reg_div	= { .reg = S5P_CLKDIV_CORE0, .shift = 0, .size = 3 },
+	.reg_div	= { .reg = S5P_CLKDIV_DMC0, .shift = 0, .size = 3 },
 };
 
 static struct clksrc_clk clk_pclk_acp = {
@@ -289,7 +289,7 @@ static struct clksrc_clk clk_pclk_acp =
 		.id		= -1,
 		.parent		= &clk_aclk_acp.clk,
 	},
-	.reg_div	= { .reg = S5P_CLKDIV_CORE0, .shift = 4, .size = 3 },
+	.reg_div	= { .reg = S5P_CLKDIV_DMC0, .shift = 4, .size = 3 },
 };
 
 /* Core list of CMU_TOP side */
@@ -384,7 +384,7 @@ static struct clksrc_clk clk_sclk_vpll =
 	.reg_src	= { .reg = S5P_CLKSRC_TOP0, .shift = 8, .size = 1 },
 };
 
-static struct clk init_clocks_disable[] = {
+static struct clk init_clocks_off[] = {
 	{
 		.name		= "timers",
 		.id		= -1,
@@ -467,6 +467,16 @@ static struct clk init_clocks_disable[]
 		.enable		= s5pv310_clk_ip_fsys_ctrl,
 		.ctrlbit	= (1 << 10),
 	}, {
+		.name		= "pdma",
+		.id		= 0,
+		.enable		= s5pv310_clk_ip_fsys_ctrl,
+		.ctrlbit	= (1 << 0),
+	}, {
+		.name		= "pdma",
+		.id		= 1,
+		.enable		= s5pv310_clk_ip_fsys_ctrl,
+		.ctrlbit	= (1 << 1),
+	}, {
 		.name		= "adc",
 		.id		= -1,
 		.enable		= s5pv310_clk_ip_peril_ctrl,
@@ -507,6 +517,26 @@ static struct clk init_clocks_disable[]
 		.enable		= s5pv310_clk_ip_peril_ctrl,
 		.ctrlbit	= (1 << 18),
 	}, {
+		.name		= "iis",
+		.id		= 0,
+		.enable		= s5pv310_clk_ip_peril_ctrl,
+		.ctrlbit	= (1 << 19),
+	}, {
+		.name		= "iis",
+		.id		= 1,
+		.enable		= s5pv310_clk_ip_peril_ctrl,
+		.ctrlbit	= (1 << 20),
+	}, {
+		.name		= "iis",
+		.id		= 2,
+		.enable		= s5pv310_clk_ip_peril_ctrl,
+		.ctrlbit	= (1 << 21),
+	}, {
+		.name		= "ac97",
+		.id		= -1,
+		.enable		= s5pv310_clk_ip_peril_ctrl,
+		.ctrlbit	= (1 << 27),
+	}, {
 		.name		= "fimg2d",
 		.id		= -1,
 		.enable		= s5pv310_clk_ip_image_ctrl,
@@ -990,6 +1020,17 @@ static struct clksrc_clk *sysclks[] = {
 	&clk_dout_mmc4,
 };
 
+static int xtal_rate;
+
+static unsigned long s5pv310_fout_apll_get_rate(struct clk *clk)
+{
+	return s5p_get_pll45xx(xtal_rate, __raw_readl(S5P_APLL_CON0), pll_4508);
+}
+
+static struct clk_ops s5pv310_fout_apll_ops = {
+	.get_rate = s5pv310_fout_apll_get_rate,
+};
+
 void __init_or_cpufreq s5pv310_setup_clocks(void)
 {
 	struct clk *xtal_clk;
@@ -1013,6 +1054,9 @@ void __init_or_cpufreq s5pv310_setup_clo
 	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);
@@ -1026,7 +1070,7 @@ void __init_or_cpufreq s5pv310_setup_clo
 	vpll = s5p_get_pll46xx(vpllsrc, __raw_readl(S5P_VPLL_CON0),
 				__raw_readl(S5P_VPLL_CON1), pll_4650);
 
-	clk_fout_apll.rate = apll;
+	clk_fout_apll.ops = &s5pv310_fout_apll_ops;
 	clk_fout_mpll.rate = mpll;
 	clk_fout_epll.rate = epll;
 	clk_fout_vpll.rate = vpll;
@@ -1061,13 +1105,9 @@ static struct clk *clks[] __initdata = {
 
 void __init s5pv310_register_clocks(void)
 {
-	struct clk *clkp;
-	int ret;
 	int ptr;
 
-	ret = s3c24xx_register_clocks(clks, ARRAY_SIZE(clks));
-	if (ret > 0)
-		printk(KERN_ERR "Failed to register %u clocks\n", ret);
+	s3c24xx_register_clocks(clks, ARRAY_SIZE(clks));
 
 	for (ptr = 0; ptr < ARRAY_SIZE(sysclks); ptr++)
 		s3c_register_clksrc(sysclks[ptr], 1);
@@ -1075,15 +1115,8 @@ void __init s5pv310_register_clocks(void
 	s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs));
 	s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks));
 
-	clkp = init_clocks_disable;
-	for (ptr = 0; ptr < ARRAY_SIZE(init_clocks_disable); ptr++, clkp++) {
-		ret = s3c24xx_register_clock(clkp);
-		if (ret < 0) {
-			printk(KERN_ERR "Failed to register clock %s (%d)\n",
-			       clkp->name, ret);
-		}
-		(clkp->enable)(clkp, 0);
-	}
+	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-2.6.37-gnu1/arch/arm/mach-s5pv310/cpu.c linux-libre-2.6.38-gnu1/arch/arm/mach-s5pv310/cpu.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-s5pv310/cpu.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-s5pv310/cpu.c	2011-03-14 21:20:32.000000000 -0400
@@ -24,8 +24,6 @@
 
 #include <mach/regs-irq.h>
 
-void __iomem *gic_cpu_base_addr;
-
 extern int combiner_init(unsigned int combiner_nr, void __iomem *base,
 			 unsigned int irq_start);
 extern void combiner_cascade_irq(unsigned int combiner_nr, unsigned int irq);
@@ -43,6 +41,11 @@ static struct map_desc s5pv310_iodesc[]
 		.length		= SZ_128K,
 		.type		= MT_DEVICE,
 	}, {
+		.virtual	= (unsigned long)S5P_VA_PMU,
+		.pfn		= __phys_to_pfn(S5PV310_PA_PMU),
+		.length		= SZ_64K,
+		.type		= MT_DEVICE,
+	}, {
 		.virtual	= (unsigned long)S5P_VA_COMBINER_BASE,
 		.pfn		= __phys_to_pfn(S5PV310_PA_COMBINER),
 		.length		= SZ_4K,
@@ -73,6 +76,11 @@ static struct map_desc s5pv310_iodesc[]
 		.length		= SZ_256,
 		.type		= MT_DEVICE,
 	}, {
+		.virtual	= (unsigned long)S5P_VA_DMC0,
+		.pfn		= __phys_to_pfn(S5PV310_PA_DMC0),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE,
+	}, {
 		.virtual	= (unsigned long)S3C_VA_UART,
 		.pfn		= __phys_to_pfn(S3C_PA_UART),
 		.length		= SZ_512K,
@@ -122,11 +130,18 @@ void __init s5pv310_init_irq(void)
 {
 	int irq;
 
-	gic_cpu_base_addr = S5P_VA_GIC_CPU;
-	gic_dist_init(0, S5P_VA_GIC_DIST, IRQ_LOCALTIMER);
-	gic_cpu_init(0, S5P_VA_GIC_CPU);
+	gic_init(0, IRQ_LOCALTIMER, S5P_VA_GIC_DIST, S5P_VA_GIC_CPU);
 
 	for (irq = 0; irq < MAX_COMBINER_NR; irq++) {
+
+		/*
+		 * From SPI(0) to SPI(39) and SPI(51), SPI(53) are
+		 * connected to the interrupt combiner. These irqs
+		 * should be initialized to support cascade interrupt.
+		 */
+		if ((irq >= 40) && !(irq == 51) && !(irq == 53))
+			continue;
+
 		combiner_init(irq, (void __iomem *)S5P_VA_COMBINER(irq),
 				COMBINER_IRQ(irq, 0));
 		combiner_cascade_irq(irq, IRQ_SPI(irq));
@@ -168,7 +183,7 @@ static int __init s5pv310_l2x0_cache_ini
 	__raw_writel(L2X0_DYNAMIC_CLK_GATING_EN | L2X0_STNDBY_MODE_EN,
 		     S5P_VA_L2CC + L2X0_POWER_CTRL);
 
-	l2x0_init(S5P_VA_L2CC, 0x7C070001, 0xC200ffff);
+	l2x0_init(S5P_VA_L2CC, 0x7C470001, 0xC200ffff);
 
 	return 0;
 }
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-s5pv310/cpufreq.c linux-libre-2.6.38-gnu1/arch/arm/mach-s5pv310/cpufreq.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-s5pv310/cpufreq.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-s5pv310/cpufreq.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,580 @@
+/* linux/arch/arm/mach-s5pv310/cpufreq.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * S5PV310 - CPU frequency scaling 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/types.h>
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/regulator/consumer.h>
+#include <linux/cpufreq.h>
+
+#include <mach/map.h>
+#include <mach/regs-clock.h>
+#include <mach/regs-mem.h>
+
+#include <plat/clock.h>
+#include <plat/pm.h>
+
+static struct clk *cpu_clk;
+static struct clk *moutcore;
+static struct clk *mout_mpll;
+static struct clk *mout_apll;
+
+#ifdef CONFIG_REGULATOR
+static struct regulator *arm_regulator;
+static struct regulator *int_regulator;
+#endif
+
+static struct cpufreq_freqs freqs;
+static unsigned int memtype;
+
+enum s5pv310_memory_type {
+	DDR2 = 4,
+	LPDDR2,
+	DDR3,
+};
+
+enum cpufreq_level_index {
+	L0, L1, L2, L3, CPUFREQ_LEVEL_END,
+};
+
+static struct cpufreq_frequency_table s5pv310_freq_table[] = {
+	{L0, 1000*1000},
+	{L1, 800*1000},
+	{L2, 400*1000},
+	{L3, 100*1000},
+	{0, CPUFREQ_TABLE_END},
+};
+
+static unsigned int clkdiv_cpu0[CPUFREQ_LEVEL_END][7] = {
+	/*
+	 * Clock divider value for following
+	 * { DIVCORE, DIVCOREM0, DIVCOREM1, DIVPERIPH,
+	 *		DIVATB, DIVPCLK_DBG, DIVAPLL }
+	 */
+
+	/* ARM L0: 1000MHz */
+	{ 0, 3, 7, 3, 3, 0, 1 },
+
+	/* ARM L1: 800MHz */
+	{ 0, 3, 7, 3, 3, 0, 1 },
+
+	/* ARM L2: 400MHz */
+	{ 0, 1, 3, 1, 3, 0, 1 },
+
+	/* ARM L3: 100MHz */
+	{ 0, 0, 1, 0, 3, 1, 1 },
+};
+
+static unsigned int clkdiv_cpu1[CPUFREQ_LEVEL_END][2] = {
+	/*
+	 * Clock divider value for following
+	 * { DIVCOPY, DIVHPM }
+	 */
+
+	 /* ARM L0: 1000MHz */
+	{ 3, 0 },
+
+	/* ARM L1: 800MHz */
+	{ 3, 0 },
+
+	/* ARM L2: 400MHz */
+	{ 3, 0 },
+
+	/* ARM L3: 100MHz */
+	{ 3, 0 },
+};
+
+static unsigned int clkdiv_dmc0[CPUFREQ_LEVEL_END][8] = {
+	/*
+	 * Clock divider value for following
+	 * { DIVACP, DIVACP_PCLK, DIVDPHY, DIVDMC, DIVDMCD
+	 *		DIVDMCP, DIVCOPY2, DIVCORE_TIMERS }
+	 */
+
+	/* DMC L0: 400MHz */
+	{ 3, 1, 1, 1, 1, 1, 3, 1 },
+
+	/* DMC L1: 400MHz */
+	{ 3, 1, 1, 1, 1, 1, 3, 1 },
+
+	/* DMC L2: 266.7MHz */
+	{ 7, 1, 1, 2, 1, 1, 3, 1 },
+
+	/* DMC L3: 200MHz */
+	{ 7, 1, 1, 3, 1, 1, 3, 1 },
+};
+
+static unsigned int clkdiv_top[CPUFREQ_LEVEL_END][5] = {
+	/*
+	 * Clock divider value for following
+	 * { DIVACLK200, DIVACLK100, DIVACLK160, DIVACLK133, DIVONENAND }
+	 */
+
+	/* ACLK200 L0: 200MHz */
+	{ 3, 7, 4, 5, 1 },
+
+	/* ACLK200 L1: 200MHz */
+	{ 3, 7, 4, 5, 1 },
+
+	/* ACLK200 L2: 160MHz */
+	{ 4, 7, 5, 7, 1 },
+
+	/* ACLK200 L3: 133.3MHz */
+	{ 5, 7, 7, 7, 1 },
+};
+
+static unsigned int clkdiv_lr_bus[CPUFREQ_LEVEL_END][2] = {
+	/*
+	 * Clock divider value for following
+	 * { DIVGDL/R, DIVGPL/R }
+	 */
+
+	/* ACLK_GDL/R L0: 200MHz */
+	{ 3, 1 },
+
+	/* ACLK_GDL/R L1: 200MHz */
+	{ 3, 1 },
+
+	/* ACLK_GDL/R L2: 160MHz */
+	{ 4, 1 },
+
+	/* ACLK_GDL/R L3: 133.3MHz */
+	{ 5, 1 },
+};
+
+struct cpufreq_voltage_table {
+	unsigned int	index;		/* any */
+	unsigned int	arm_volt;	/* uV */
+	unsigned int	int_volt;
+};
+
+static struct cpufreq_voltage_table s5pv310_volt_table[CPUFREQ_LEVEL_END] = {
+	{
+		.index		= L0,
+		.arm_volt	= 1200000,
+		.int_volt	= 1100000,
+	}, {
+		.index		= L1,
+		.arm_volt	= 1100000,
+		.int_volt	= 1100000,
+	}, {
+		.index		= L2,
+		.arm_volt	= 1000000,
+		.int_volt	= 1000000,
+	}, {
+		.index		= L3,
+		.arm_volt	= 900000,
+		.int_volt	= 1000000,
+	},
+};
+
+static unsigned int s5pv310_apll_pms_table[CPUFREQ_LEVEL_END] = {
+	/* APLL FOUT L0: 1000MHz */
+	((250 << 16) | (6 << 8) | 1),
+
+	/* APLL FOUT L1: 800MHz */
+	((200 << 16) | (6 << 8) | 1),
+
+	/* APLL FOUT L2 : 400MHz */
+	((200 << 16) | (6 << 8) | 2),
+
+	/* APLL FOUT L3: 100MHz */
+	((200 << 16) | (6 << 8) | 4),
+};
+
+int s5pv310_verify_speed(struct cpufreq_policy *policy)
+{
+	return cpufreq_frequency_table_verify(policy, s5pv310_freq_table);
+}
+
+unsigned int s5pv310_getspeed(unsigned int cpu)
+{
+	return clk_get_rate(cpu_clk) / 1000;
+}
+
+void s5pv310_set_clkdiv(unsigned int div_index)
+{
+	unsigned int tmp;
+
+	/* Change Divider - CPU0 */
+
+	tmp = __raw_readl(S5P_CLKDIV_CPU);
+
+	tmp &= ~(S5P_CLKDIV_CPU0_CORE_MASK | S5P_CLKDIV_CPU0_COREM0_MASK |
+		S5P_CLKDIV_CPU0_COREM1_MASK | S5P_CLKDIV_CPU0_PERIPH_MASK |
+		S5P_CLKDIV_CPU0_ATB_MASK | S5P_CLKDIV_CPU0_PCLKDBG_MASK |
+		S5P_CLKDIV_CPU0_APLL_MASK);
+
+	tmp |= ((clkdiv_cpu0[div_index][0] << S5P_CLKDIV_CPU0_CORE_SHIFT) |
+		(clkdiv_cpu0[div_index][1] << S5P_CLKDIV_CPU0_COREM0_SHIFT) |
+		(clkdiv_cpu0[div_index][2] << S5P_CLKDIV_CPU0_COREM1_SHIFT) |
+		(clkdiv_cpu0[div_index][3] << S5P_CLKDIV_CPU0_PERIPH_SHIFT) |
+		(clkdiv_cpu0[div_index][4] << S5P_CLKDIV_CPU0_ATB_SHIFT) |
+		(clkdiv_cpu0[div_index][5] << S5P_CLKDIV_CPU0_PCLKDBG_SHIFT) |
+		(clkdiv_cpu0[div_index][6] << S5P_CLKDIV_CPU0_APLL_SHIFT));
+
+	__raw_writel(tmp, S5P_CLKDIV_CPU);
+
+	do {
+		tmp = __raw_readl(S5P_CLKDIV_STATCPU);
+	} while (tmp & 0x1111111);
+
+	/* Change Divider - CPU1 */
+
+	tmp = __raw_readl(S5P_CLKDIV_CPU1);
+
+	tmp &= ~((0x7 << 4) | 0x7);
+
+	tmp |= ((clkdiv_cpu1[div_index][0] << 4) |
+		(clkdiv_cpu1[div_index][1] << 0));
+
+	__raw_writel(tmp, S5P_CLKDIV_CPU1);
+
+	do {
+		tmp = __raw_readl(S5P_CLKDIV_STATCPU1);
+	} while (tmp & 0x11);
+
+	/* Change Divider - DMC0 */
+
+	tmp = __raw_readl(S5P_CLKDIV_DMC0);
+
+	tmp &= ~(S5P_CLKDIV_DMC0_ACP_MASK | S5P_CLKDIV_DMC0_ACPPCLK_MASK |
+		S5P_CLKDIV_DMC0_DPHY_MASK | S5P_CLKDIV_DMC0_DMC_MASK |
+		S5P_CLKDIV_DMC0_DMCD_MASK | S5P_CLKDIV_DMC0_DMCP_MASK |
+		S5P_CLKDIV_DMC0_COPY2_MASK | S5P_CLKDIV_DMC0_CORETI_MASK);
+
+	tmp |= ((clkdiv_dmc0[div_index][0] << S5P_CLKDIV_DMC0_ACP_SHIFT) |
+		(clkdiv_dmc0[div_index][1] << S5P_CLKDIV_DMC0_ACPPCLK_SHIFT) |
+		(clkdiv_dmc0[div_index][2] << S5P_CLKDIV_DMC0_DPHY_SHIFT) |
+		(clkdiv_dmc0[div_index][3] << S5P_CLKDIV_DMC0_DMC_SHIFT) |
+		(clkdiv_dmc0[div_index][4] << S5P_CLKDIV_DMC0_DMCD_SHIFT) |
+		(clkdiv_dmc0[div_index][5] << S5P_CLKDIV_DMC0_DMCP_SHIFT) |
+		(clkdiv_dmc0[div_index][6] << S5P_CLKDIV_DMC0_COPY2_SHIFT) |
+		(clkdiv_dmc0[div_index][7] << S5P_CLKDIV_DMC0_CORETI_SHIFT));
+
+	__raw_writel(tmp, S5P_CLKDIV_DMC0);
+
+	do {
+		tmp = __raw_readl(S5P_CLKDIV_STAT_DMC0);
+	} while (tmp & 0x11111111);
+
+	/* Change Divider - TOP */
+
+	tmp = __raw_readl(S5P_CLKDIV_TOP);
+
+	tmp &= ~(S5P_CLKDIV_TOP_ACLK200_MASK | S5P_CLKDIV_TOP_ACLK100_MASK |
+		S5P_CLKDIV_TOP_ACLK160_MASK | S5P_CLKDIV_TOP_ACLK133_MASK |
+		S5P_CLKDIV_TOP_ONENAND_MASK);
+
+	tmp |= ((clkdiv_top[div_index][0] << S5P_CLKDIV_TOP_ACLK200_SHIFT) |
+		(clkdiv_top[div_index][1] << S5P_CLKDIV_TOP_ACLK100_SHIFT) |
+		(clkdiv_top[div_index][2] << S5P_CLKDIV_TOP_ACLK160_SHIFT) |
+		(clkdiv_top[div_index][3] << S5P_CLKDIV_TOP_ACLK133_SHIFT) |
+		(clkdiv_top[div_index][4] << S5P_CLKDIV_TOP_ONENAND_SHIFT));
+
+	__raw_writel(tmp, S5P_CLKDIV_TOP);
+
+	do {
+		tmp = __raw_readl(S5P_CLKDIV_STAT_TOP);
+	} while (tmp & 0x11111);
+
+	/* Change Divider - LEFTBUS */
+
+	tmp = __raw_readl(S5P_CLKDIV_LEFTBUS);
+
+	tmp &= ~(S5P_CLKDIV_BUS_GDLR_MASK | S5P_CLKDIV_BUS_GPLR_MASK);
+
+	tmp |= ((clkdiv_lr_bus[div_index][0] << S5P_CLKDIV_BUS_GDLR_SHIFT) |
+		(clkdiv_lr_bus[div_index][1] << S5P_CLKDIV_BUS_GPLR_SHIFT));
+
+	__raw_writel(tmp, S5P_CLKDIV_LEFTBUS);
+
+	do {
+		tmp = __raw_readl(S5P_CLKDIV_STAT_LEFTBUS);
+	} while (tmp & 0x11);
+
+	/* Change Divider - RIGHTBUS */
+
+	tmp = __raw_readl(S5P_CLKDIV_RIGHTBUS);
+
+	tmp &= ~(S5P_CLKDIV_BUS_GDLR_MASK | S5P_CLKDIV_BUS_GPLR_MASK);
+
+	tmp |= ((clkdiv_lr_bus[div_index][0] << S5P_CLKDIV_BUS_GDLR_SHIFT) |
+		(clkdiv_lr_bus[div_index][1] << S5P_CLKDIV_BUS_GPLR_SHIFT));
+
+	__raw_writel(tmp, S5P_CLKDIV_RIGHTBUS);
+
+	do {
+		tmp = __raw_readl(S5P_CLKDIV_STAT_RIGHTBUS);
+	} while (tmp & 0x11);
+}
+
+static void s5pv310_set_apll(unsigned int index)
+{
+	unsigned int tmp;
+
+	/* 1. MUX_CORE_SEL = MPLL, ARMCLK uses MPLL for lock time */
+	clk_set_parent(moutcore, mout_mpll);
+
+	do {
+		tmp = (__raw_readl(S5P_CLKMUX_STATCPU)
+			>> S5P_CLKSRC_CPU_MUXCORE_SHIFT);
+		tmp &= 0x7;
+	} while (tmp != 0x2);
+
+	/* 2. Set APLL Lock time */
+	__raw_writel(S5P_APLL_LOCKTIME, S5P_APLL_LOCK);
+
+	/* 3. Change PLL PMS values */
+	tmp = __raw_readl(S5P_APLL_CON0);
+	tmp &= ~((0x3ff << 16) | (0x3f << 8) | (0x7 << 0));
+	tmp |= s5pv310_apll_pms_table[index];
+	__raw_writel(tmp, S5P_APLL_CON0);
+
+	/* 4. wait_lock_time */
+	do {
+		tmp = __raw_readl(S5P_APLL_CON0);
+	} while (!(tmp & (0x1 << S5P_APLLCON0_LOCKED_SHIFT)));
+
+	/* 5. MUX_CORE_SEL = APLL */
+	clk_set_parent(moutcore, mout_apll);
+
+	do {
+		tmp = __raw_readl(S5P_CLKMUX_STATCPU);
+		tmp &= S5P_CLKMUX_STATCPU_MUXCORE_MASK;
+	} while (tmp != (0x1 << S5P_CLKSRC_CPU_MUXCORE_SHIFT));
+}
+
+static void s5pv310_set_frequency(unsigned int old_index, unsigned int new_index)
+{
+	unsigned int tmp;
+
+	if (old_index > new_index) {
+		/* The frequency changing to L0 needs to change apll */
+		if (freqs.new == s5pv310_freq_table[L0].frequency) {
+			/* 1. Change the system clock divider values */
+			s5pv310_set_clkdiv(new_index);
+
+			/* 2. Change the apll m,p,s value */
+			s5pv310_set_apll(new_index);
+		} else {
+			/* 1. Change the system clock divider values */
+			s5pv310_set_clkdiv(new_index);
+
+			/* 2. Change just s value in apll m,p,s value */
+			tmp = __raw_readl(S5P_APLL_CON0);
+			tmp &= ~(0x7 << 0);
+			tmp |= (s5pv310_apll_pms_table[new_index] & 0x7);
+			__raw_writel(tmp, S5P_APLL_CON0);
+		}
+	}
+
+	else if (old_index < new_index) {
+		/* The frequency changing from L0 needs to change apll */
+		if (freqs.old == s5pv310_freq_table[L0].frequency) {
+			/* 1. Change the apll m,p,s value */
+			s5pv310_set_apll(new_index);
+
+			/* 2. Change the system clock divider values */
+			s5pv310_set_clkdiv(new_index);
+		} else {
+			/* 1. Change just s value in apll m,p,s value */
+			tmp = __raw_readl(S5P_APLL_CON0);
+			tmp &= ~(0x7 << 0);
+			tmp |= (s5pv310_apll_pms_table[new_index] & 0x7);
+			__raw_writel(tmp, S5P_APLL_CON0);
+
+			/* 2. Change the system clock divider values */
+			s5pv310_set_clkdiv(new_index);
+		}
+	}
+}
+
+static int s5pv310_target(struct cpufreq_policy *policy,
+			  unsigned int target_freq,
+			  unsigned int relation)
+{
+	unsigned int index, old_index;
+	unsigned int arm_volt, int_volt;
+
+	freqs.old = s5pv310_getspeed(policy->cpu);
+
+	if (cpufreq_frequency_table_target(policy, s5pv310_freq_table,
+					   freqs.old, relation, &old_index))
+		return -EINVAL;
+
+	if (cpufreq_frequency_table_target(policy, s5pv310_freq_table,
+					   target_freq, relation, &index))
+		return -EINVAL;
+
+	freqs.new = s5pv310_freq_table[index].frequency;
+	freqs.cpu = policy->cpu;
+
+	if (freqs.new == freqs.old)
+		return 0;
+
+	/* get the voltage value */
+	arm_volt = s5pv310_volt_table[index].arm_volt;
+	int_volt = s5pv310_volt_table[index].int_volt;
+
+	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+
+	/* control regulator */
+	if (freqs.new > freqs.old) {
+		/* Voltage up */
+#ifdef CONFIG_REGULATOR
+		regulator_set_voltage(arm_regulator, arm_volt, arm_volt);
+		regulator_set_voltage(int_regulator, int_volt, int_volt);
+#endif
+	}
+
+	/* Clock Configuration Procedure */
+	s5pv310_set_frequency(old_index, index);
+
+	/* control regulator */
+	if (freqs.new < freqs.old) {
+		/* Voltage down */
+#ifdef CONFIG_REGULATOR
+		regulator_set_voltage(arm_regulator, arm_volt, arm_volt);
+		regulator_set_voltage(int_regulator, int_volt, int_volt);
+#endif
+	}
+
+	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int s5pv310_cpufreq_suspend(struct cpufreq_policy *policy,
+				   pm_message_t pmsg)
+{
+	return 0;
+}
+
+static int s5pv310_cpufreq_resume(struct cpufreq_policy *policy)
+{
+	return 0;
+}
+#endif
+
+static int s5pv310_cpufreq_cpu_init(struct cpufreq_policy *policy)
+{
+	policy->cur = policy->min = policy->max = s5pv310_getspeed(policy->cpu);
+
+	cpufreq_frequency_table_get_attr(s5pv310_freq_table, policy->cpu);
+
+	/* set the transition latency value */
+	policy->cpuinfo.transition_latency = 100000;
+
+	/*
+	 * S5PV310 multi-core processors has 2 cores
+	 * that the frequency cannot be set independently.
+	 * Each cpu is bound to the same speed.
+	 * So the affected cpu is all of the cpus.
+	 */
+	cpumask_setall(policy->cpus);
+
+	return cpufreq_frequency_table_cpuinfo(policy, s5pv310_freq_table);
+}
+
+static struct cpufreq_driver s5pv310_driver = {
+	.flags		= CPUFREQ_STICKY,
+	.verify		= s5pv310_verify_speed,
+	.target		= s5pv310_target,
+	.get		= s5pv310_getspeed,
+	.init		= s5pv310_cpufreq_cpu_init,
+	.name		= "s5pv310_cpufreq",
+#ifdef CONFIG_PM
+	.suspend	= s5pv310_cpufreq_suspend,
+	.resume		= s5pv310_cpufreq_resume,
+#endif
+};
+
+static int __init s5pv310_cpufreq_init(void)
+{
+	cpu_clk = clk_get(NULL, "armclk");
+	if (IS_ERR(cpu_clk))
+		return PTR_ERR(cpu_clk);
+
+	moutcore = clk_get(NULL, "moutcore");
+	if (IS_ERR(moutcore))
+		goto out;
+
+	mout_mpll = clk_get(NULL, "mout_mpll");
+	if (IS_ERR(mout_mpll))
+		goto out;
+
+	mout_apll = clk_get(NULL, "mout_apll");
+	if (IS_ERR(mout_apll))
+		goto out;
+
+#ifdef CONFIG_REGULATOR
+	arm_regulator = regulator_get(NULL, "vdd_arm");
+	if (IS_ERR(arm_regulator)) {
+		printk(KERN_ERR "failed to get resource %s\n", "vdd_arm");
+		goto out;
+	}
+
+	int_regulator = regulator_get(NULL, "vdd_int");
+	if (IS_ERR(int_regulator)) {
+		printk(KERN_ERR "failed to get resource %s\n", "vdd_int");
+		goto out;
+	}
+#endif
+
+	/*
+	 * Check DRAM type.
+	 * Because DVFS level is different according to DRAM type.
+	 */
+	memtype = __raw_readl(S5P_VA_DMC0 + S5P_DMC0_MEMCON_OFFSET);
+	memtype = (memtype >> S5P_DMC0_MEMTYPE_SHIFT);
+	memtype &= S5P_DMC0_MEMTYPE_MASK;
+
+	if ((memtype < DDR2) && (memtype > DDR3)) {
+		printk(KERN_ERR "%s: wrong memtype= 0x%x\n", __func__, memtype);
+		goto out;
+	} else {
+		printk(KERN_DEBUG "%s: memtype= 0x%x\n", __func__, memtype);
+	}
+
+	return cpufreq_register_driver(&s5pv310_driver);
+
+out:
+	if (!IS_ERR(cpu_clk))
+		clk_put(cpu_clk);
+
+	if (!IS_ERR(moutcore))
+		clk_put(moutcore);
+
+	if (!IS_ERR(mout_mpll))
+		clk_put(mout_mpll);
+
+	if (!IS_ERR(mout_apll))
+		clk_put(mout_apll);
+
+#ifdef CONFIG_REGULATOR
+	if (!IS_ERR(arm_regulator))
+		regulator_put(arm_regulator);
+
+	if (!IS_ERR(int_regulator))
+		regulator_put(int_regulator);
+#endif
+
+	printk(KERN_ERR "%s: failed initialization\n", __func__);
+
+	return -EINVAL;
+}
+late_initcall(s5pv310_cpufreq_init);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-s5pv310/dev-audio.c linux-libre-2.6.38-gnu1/arch/arm/mach-s5pv310/dev-audio.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-s5pv310/dev-audio.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-s5pv310/dev-audio.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,364 @@
+/* linux/arch/arm/mach-s5pv310/dev-audio.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 <linux/gpio.h>
+
+#include <plat/gpio-cfg.h>
+#include <plat/audio.h>
+
+#include <mach/map.h>
+#include <mach/dma.h>
+#include <mach/irqs.h>
+
+static const char *rclksrc[] = {
+	[0] = "busclk",
+	[1] = "i2sclk",
+};
+
+static int s5pv310_cfg_i2s(struct platform_device *pdev)
+{
+	/* configure GPIO for i2s port */
+	switch (pdev->id) {
+	case 0:
+		s3c_gpio_cfgpin_range(S5PV310_GPZ(0), 7, S3C_GPIO_SFN(2));
+		break;
+	case 1:
+		s3c_gpio_cfgpin_range(S5PV310_GPC0(0), 5, S3C_GPIO_SFN(2));
+		break;
+	case 2:
+		s3c_gpio_cfgpin_range(S5PV310_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 = s5pv310_cfg_i2s,
+	.type = {
+		.i2s = {
+			.quirks = QUIRK_PRI_6CHAN | QUIRK_SEC_DAI
+					 | QUIRK_NEED_RSTCLR,
+			.src_clk = rclksrc,
+		},
+	},
+};
+
+static struct resource s5pv310_i2s0_resource[] = {
+	[0] = {
+		.start	= S5PV310_PA_I2S0,
+		.end	= S5PV310_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 s5pv310_device_i2s0 = {
+	.name = "samsung-i2s",
+	.id = 0,
+	.num_resources = ARRAY_SIZE(s5pv310_i2s0_resource),
+	.resource = s5pv310_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 = s5pv310_cfg_i2s,
+	.type = {
+		.i2s = {
+			.quirks = QUIRK_NO_MUXPSR,
+			.src_clk = rclksrc_v3,
+		},
+	},
+};
+
+static struct resource s5pv310_i2s1_resource[] = {
+	[0] = {
+		.start	= S5PV310_PA_I2S1,
+		.end	= S5PV310_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 s5pv310_device_i2s1 = {
+	.name = "samsung-i2s",
+	.id = 1,
+	.num_resources = ARRAY_SIZE(s5pv310_i2s1_resource),
+	.resource = s5pv310_i2s1_resource,
+	.dev = {
+		.platform_data = &i2sv3_pdata,
+	},
+};
+
+static struct resource s5pv310_i2s2_resource[] = {
+	[0] = {
+		.start	= S5PV310_PA_I2S2,
+		.end	= S5PV310_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 s5pv310_device_i2s2 = {
+	.name = "samsung-i2s",
+	.id = 2,
+	.num_resources = ARRAY_SIZE(s5pv310_i2s2_resource),
+	.resource = s5pv310_i2s2_resource,
+	.dev = {
+		.platform_data = &i2sv3_pdata,
+	},
+};
+
+/* PCM Controller platform_devices */
+
+static int s5pv310_pcm_cfg_gpio(struct platform_device *pdev)
+{
+	switch (pdev->id) {
+	case 0:
+		s3c_gpio_cfgpin_range(S5PV310_GPZ(0), 5, S3C_GPIO_SFN(3));
+		break;
+	case 1:
+		s3c_gpio_cfgpin_range(S5PV310_GPC0(0), 5, S3C_GPIO_SFN(3));
+		break;
+	case 2:
+		s3c_gpio_cfgpin_range(S5PV310_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 = s5pv310_pcm_cfg_gpio,
+};
+
+static struct resource s5pv310_pcm0_resource[] = {
+	[0] = {
+		.start	= S5PV310_PA_PCM0,
+		.end	= S5PV310_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 s5pv310_device_pcm0 = {
+	.name = "samsung-pcm",
+	.id = 0,
+	.num_resources = ARRAY_SIZE(s5pv310_pcm0_resource),
+	.resource = s5pv310_pcm0_resource,
+	.dev = {
+		.platform_data = &s3c_pcm_pdata,
+	},
+};
+
+static struct resource s5pv310_pcm1_resource[] = {
+	[0] = {
+		.start	= S5PV310_PA_PCM1,
+		.end	= S5PV310_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 s5pv310_device_pcm1 = {
+	.name = "samsung-pcm",
+	.id = 1,
+	.num_resources = ARRAY_SIZE(s5pv310_pcm1_resource),
+	.resource = s5pv310_pcm1_resource,
+	.dev = {
+		.platform_data = &s3c_pcm_pdata,
+	},
+};
+
+static struct resource s5pv310_pcm2_resource[] = {
+	[0] = {
+		.start	= S5PV310_PA_PCM2,
+		.end	= S5PV310_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 s5pv310_device_pcm2 = {
+	.name = "samsung-pcm",
+	.id = 2,
+	.num_resources = ARRAY_SIZE(s5pv310_pcm2_resource),
+	.resource = s5pv310_pcm2_resource,
+	.dev = {
+		.platform_data = &s3c_pcm_pdata,
+	},
+};
+
+/* AC97 Controller platform devices */
+
+static int s5pv310_ac97_cfg_gpio(struct platform_device *pdev)
+{
+	return s3c_gpio_cfgpin_range(S5PV310_GPC0(0), 5, S3C_GPIO_SFN(4));
+}
+
+static struct resource s5pv310_ac97_resource[] = {
+	[0] = {
+		.start	= S5PV310_PA_AC97,
+		.end	= S5PV310_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 = s5pv310_ac97_cfg_gpio,
+};
+
+static u64 s5pv310_ac97_dmamask = DMA_BIT_MASK(32);
+
+struct platform_device s5pv310_device_ac97 = {
+	.name = "samsung-ac97",
+	.id = -1,
+	.num_resources = ARRAY_SIZE(s5pv310_ac97_resource),
+	.resource = s5pv310_ac97_resource,
+	.dev = {
+		.platform_data = &s3c_ac97_pdata,
+		.dma_mask = &s5pv310_ac97_dmamask,
+		.coherent_dma_mask = DMA_BIT_MASK(32),
+	},
+};
+
+/* S/PDIF Controller platform_device */
+
+static int s5pv310_spdif_cfg_gpio(struct platform_device *pdev)
+{
+	s3c_gpio_cfgpin_range(S5PV310_GPC1(0), 2, S3C_GPIO_SFN(3));
+
+	return 0;
+}
+
+static struct resource s5pv310_spdif_resource[] = {
+	[0] = {
+		.start	= S5PV310_PA_SPDIF,
+		.end	= S5PV310_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 = s5pv310_spdif_cfg_gpio,
+};
+
+static u64 s5pv310_spdif_dmamask = DMA_BIT_MASK(32);
+
+struct platform_device s5pv310_device_spdif = {
+	.name = "samsung-spdif",
+	.id = -1,
+	.num_resources = ARRAY_SIZE(s5pv310_spdif_resource),
+	.resource = s5pv310_spdif_resource,
+	.dev = {
+		.platform_data = &samsung_spdif_pdata,
+		.dma_mask = &s5pv310_spdif_dmamask,
+		.coherent_dma_mask = DMA_BIT_MASK(32),
+	},
+};
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-s5pv310/dev-pd.c linux-libre-2.6.38-gnu1/arch/arm/mach-s5pv310/dev-pd.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-s5pv310/dev-pd.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-s5pv310/dev-pd.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,139 @@
+/* linux/arch/arm/mach-s5pv310/dev-pd.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * S5PV310 - 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 s5pv310_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 s5pv310_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 s5pv310_device_pd[] = {
+	{
+		.name		= "samsung-pd",
+		.id		= 0,
+		.dev = {
+			.platform_data = &(struct samsung_pd_info) {
+				.enable		= s5pv310_pd_enable,
+				.disable	= s5pv310_pd_disable,
+				.base		= S5P_PMU_MFC_CONF,
+			},
+		},
+	}, {
+		.name		= "samsung-pd",
+		.id		= 1,
+		.dev = {
+			.platform_data = &(struct samsung_pd_info) {
+				.enable		= s5pv310_pd_enable,
+				.disable	= s5pv310_pd_disable,
+				.base		= S5P_PMU_G3D_CONF,
+			},
+		},
+	}, {
+		.name		= "samsung-pd",
+		.id		= 2,
+		.dev = {
+			.platform_data = &(struct samsung_pd_info) {
+				.enable		= s5pv310_pd_enable,
+				.disable	= s5pv310_pd_disable,
+				.base		= S5P_PMU_LCD0_CONF,
+			},
+		},
+	}, {
+		.name		= "samsung-pd",
+		.id		= 3,
+		.dev = {
+			.platform_data = &(struct samsung_pd_info) {
+				.enable		= s5pv310_pd_enable,
+				.disable	= s5pv310_pd_disable,
+				.base		= S5P_PMU_LCD1_CONF,
+			},
+		},
+	}, {
+		.name		= "samsung-pd",
+		.id		= 4,
+		.dev = {
+			.platform_data = &(struct samsung_pd_info) {
+				.enable		= s5pv310_pd_enable,
+				.disable	= s5pv310_pd_disable,
+				.base		= S5P_PMU_TV_CONF,
+			},
+		},
+	}, {
+		.name		= "samsung-pd",
+		.id		= 5,
+		.dev = {
+			.platform_data = &(struct samsung_pd_info) {
+				.enable		= s5pv310_pd_enable,
+				.disable	= s5pv310_pd_disable,
+				.base		= S5P_PMU_CAM_CONF,
+			},
+		},
+	}, {
+		.name		= "samsung-pd",
+		.id		= 6,
+		.dev = {
+			.platform_data = &(struct samsung_pd_info) {
+				.enable		= s5pv310_pd_enable,
+				.disable	= s5pv310_pd_disable,
+				.base		= S5P_PMU_GPS_CONF,
+			},
+		},
+	},
+};
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-s5pv310/dev-sysmmu.c linux-libre-2.6.38-gnu1/arch/arm/mach-s5pv310/dev-sysmmu.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-s5pv310/dev-sysmmu.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-s5pv310/dev-sysmmu.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,187 @@
+/* linux/arch/arm/mach-s5pv310/dev-sysmmu.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/platform_device.h>
+#include <linux/dma-mapping.h>
+
+#include <mach/map.h>
+#include <mach/irqs.h>
+
+static struct resource s5pv310_sysmmu_resource[] = {
+	[0] = {
+		.start	= S5PV310_PA_SYSMMU_MDMA,
+		.end	= S5PV310_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	= S5PV310_PA_SYSMMU_SSS,
+		.end	= S5PV310_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	= S5PV310_PA_SYSMMU_FIMC0,
+		.end	= S5PV310_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	= S5PV310_PA_SYSMMU_FIMC1,
+		.end	= S5PV310_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	= S5PV310_PA_SYSMMU_FIMC2,
+		.end	= S5PV310_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	= S5PV310_PA_SYSMMU_FIMC3,
+		.end	= S5PV310_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	= S5PV310_PA_SYSMMU_JPEG,
+		.end	= S5PV310_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	= S5PV310_PA_SYSMMU_FIMD0,
+		.end	= S5PV310_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	= S5PV310_PA_SYSMMU_FIMD1,
+		.end	= S5PV310_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	= S5PV310_PA_SYSMMU_PCIe,
+		.end	= S5PV310_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	= S5PV310_PA_SYSMMU_G2D,
+		.end	= S5PV310_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	= S5PV310_PA_SYSMMU_ROTATOR,
+		.end	= S5PV310_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	= S5PV310_PA_SYSMMU_MDMA2,
+		.end	= S5PV310_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	= S5PV310_PA_SYSMMU_TV,
+		.end	= S5PV310_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	= S5PV310_PA_SYSMMU_MFC_L,
+		.end	= S5PV310_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	= S5PV310_PA_SYSMMU_MFC_R,
+		.end	= S5PV310_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 s5pv310_device_sysmmu = {
+	.name		= "s5p-sysmmu",
+	.id		= 32,
+	.num_resources	= ARRAY_SIZE(s5pv310_sysmmu_resource),
+	.resource	= s5pv310_sysmmu_resource,
+};
+
+EXPORT_SYMBOL(s5pv310_device_sysmmu);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-s5pv310/dma.c linux-libre-2.6.38-gnu1/arch/arm/mach-s5pv310/dma.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-s5pv310/dma.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-s5pv310/dma.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,168 @@
+/*
+ * 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 s5pv310_pdma0_resource[] = {
+	[0] = {
+		.start	= S5PV310_PA_PDMA0,
+		.end	= S5PV310_PA_PDMA0 + SZ_4K,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= IRQ_PDMA0,
+		.end	= IRQ_PDMA0,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct s3c_pl330_platdata s5pv310_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 s5pv310_device_pdma0 = {
+	.name		= "s3c-pl330",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(s5pv310_pdma0_resource),
+	.resource	= s5pv310_pdma0_resource,
+	.dev		= {
+		.dma_mask = &dma_dmamask,
+		.coherent_dma_mask = DMA_BIT_MASK(32),
+		.platform_data = &s5pv310_pdma0_pdata,
+	},
+};
+
+static struct resource s5pv310_pdma1_resource[] = {
+	[0] = {
+		.start	= S5PV310_PA_PDMA1,
+		.end	= S5PV310_PA_PDMA1 + SZ_4K,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= IRQ_PDMA1,
+		.end	= IRQ_PDMA1,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct s3c_pl330_platdata s5pv310_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 s5pv310_device_pdma1 = {
+	.name		= "s3c-pl330",
+	.id		= 1,
+	.num_resources	= ARRAY_SIZE(s5pv310_pdma1_resource),
+	.resource	= s5pv310_pdma1_resource,
+	.dev		= {
+		.dma_mask = &dma_dmamask,
+		.coherent_dma_mask = DMA_BIT_MASK(32),
+		.platform_data = &s5pv310_pdma1_pdata,
+	},
+};
+
+static struct platform_device *s5pv310_dmacs[] __initdata = {
+	&s5pv310_device_pdma0,
+	&s5pv310_device_pdma1,
+};
+
+static int __init s5pv310_dma_init(void)
+{
+	platform_add_devices(s5pv310_dmacs, ARRAY_SIZE(s5pv310_dmacs));
+
+	return 0;
+}
+arch_initcall(s5pv310_dma_init);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-s5pv310/hotplug.c linux-libre-2.6.38-gnu1/arch/arm/mach-s5pv310/hotplug.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-s5pv310/hotplug.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-s5pv310/hotplug.c	2011-03-14 21:20:32.000000000 -0400
@@ -13,14 +13,11 @@
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/smp.h>
-#include <linux/completion.h>
 
 #include <asm/cacheflush.h>
 
 extern volatile int pen_release;
 
-static DECLARE_COMPLETION(cpu_killed);
-
 static inline void cpu_enter_lowpower(void)
 {
 	unsigned int v;
@@ -36,10 +33,10 @@ static inline void cpu_enter_lowpower(vo
 	"	bic	%0, %0, #0x20\n"
 	"	mcr	p15, 0, %0, c1, c0, 1\n"
 	"	mrc	p15, 0, %0, c1, c0, 0\n"
-	"	bic	%0, %0, #0x04\n"
+	"	bic	%0, %0, %2\n"
 	"	mcr	p15, 0, %0, c1, c0, 0\n"
 	  : "=&r" (v)
-	  : "r" (0)
+	  : "r" (0), "Ir" (CR_C)
 	  : "cc");
 }
 
@@ -49,17 +46,17 @@ static inline void cpu_leave_lowpower(vo
 
 	asm volatile(
 	"mrc	p15, 0, %0, c1, c0, 0\n"
-	"	orr	%0, %0, #0x04\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, #0x20\n"
 	"	mcr	p15, 0, %0, c1, c0, 1\n"
 	  : "=&r" (v)
-	  :
+	  : "Ir" (CR_C)
 	  : "cc");
 }
 
-static inline void platform_do_lowpower(unsigned int cpu)
+static inline void platform_do_lowpower(unsigned int cpu, int *spurious)
 {
 	/*
 	 * there is no power-control hardware on this platform, so all
@@ -83,22 +80,19 @@ static inline void platform_do_lowpower(
 		}
 
 		/*
-		 * getting here, means that we have come out of WFI without
+		 * Getting here, means that we have come out of WFI without
 		 * having been woken up - this shouldn't happen
 		 *
-		 * The trouble is, letting people know about this is not really
-		 * possible, since we are currently running incoherently, and
-		 * therefore cannot safely call printk() or anything else
+		 * Just note it happening - when we're woken, we can report
+		 * its occurrence.
 		 */
-#ifdef DEBUG
-		printk(KERN_WARN "CPU%u: spurious wakeup call\n", cpu);
-#endif
+		(*spurious)++;
 	}
 }
 
 int platform_cpu_kill(unsigned int cpu)
 {
-	return wait_for_completion_timeout(&cpu_killed, 5000);
+	return 1;
 }
 
 /*
@@ -108,30 +102,22 @@ int platform_cpu_kill(unsigned int cpu)
  */
 void platform_cpu_die(unsigned int cpu)
 {
-#ifdef DEBUG
-	unsigned int this_cpu = hard_smp_processor_id();
-
-	if (cpu != this_cpu) {
-		printk(KERN_CRIT "Eek! platform_cpu_die running on %u, should be %u\n",
-			   this_cpu, cpu);
-		BUG();
-	}
-#endif
-
-	printk(KERN_NOTICE "CPU%u: shutdown\n", cpu);
-	complete(&cpu_killed);
+	int spurious = 0;
 
 	/*
 	 * we're ready for shutdown now, so do it
 	 */
 	cpu_enter_lowpower();
-	platform_do_lowpower(cpu);
+	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)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-s5pv310/include/mach/dma.h linux-libre-2.6.38-gnu1/arch/arm/mach-s5pv310/include/mach/dma.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-s5pv310/include/mach/dma.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-s5pv310/include/mach/dma.h	2011-03-14 21:20:32.000000000 -0400
@@ -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 S3C DMA API driver for PL330 */
+#include <plat/s3c-dma-pl330.h>
+
+#endif /* __MACH_DMA_H */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-s5pv310/include/mach/irqs.h linux-libre-2.6.38-gnu1/arch/arm/mach-s5pv310/include/mach/irqs.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-s5pv310/include/mach/irqs.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-s5pv310/include/mach/irqs.h	2011-03-14 21:20:32.000000000 -0400
@@ -25,6 +25,8 @@
 
 #define IRQ_SPI(x)		S5P_IRQ(x+32)
 
+#define IRQ_MCT1		IRQ_SPI(35)
+
 #define IRQ_EINT0		IRQ_SPI(40)
 #define IRQ_EINT1		IRQ_SPI(41)
 #define IRQ_EINT2		IRQ_SPI(42)
@@ -36,9 +38,8 @@
 #define IRQ_JPEG		IRQ_SPI(48)
 #define IRQ_2D			IRQ_SPI(49)
 #define IRQ_PCIE		IRQ_SPI(50)
-#define IRQ_SYSTEM_TIMER	IRQ_SPI(51)
+#define IRQ_MCT0		IRQ_SPI(51)
 #define IRQ_MFC			IRQ_SPI(52)
-#define IRQ_WDT			IRQ_SPI(53)
 #define IRQ_AUDIO_SS		IRQ_SPI(54)
 #define IRQ_AC97		IRQ_SPI(55)
 #define IRQ_SPDIF		IRQ_SPI(56)
@@ -54,6 +55,27 @@
 #define COMBINER_GROUP(x)	((x) * MAX_IRQ_IN_COMBINER + IRQ_SPI(64))
 #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_PDMA0		COMBINER_IRQ(21, 0)
+#define IRQ_PDMA1		COMBINER_IRQ(21, 1)
+
 #define IRQ_TIMER0_VIC		COMBINER_IRQ(22, 0)
 #define IRQ_TIMER1_VIC		COMBINER_IRQ(22, 1)
 #define IRQ_TIMER2_VIC		COMBINER_IRQ(22, 2)
@@ -83,8 +105,13 @@
 #define IRQ_HSMMC2		COMBINER_IRQ(29, 2)
 #define IRQ_HSMMC3		COMBINER_IRQ(29, 3)
 
+#define IRQ_MIPI_CSIS0		COMBINER_IRQ(30, 0)
+#define IRQ_MIPI_CSIS1		COMBINER_IRQ(30, 1)
+
 #define IRQ_ONENAND_AUDI	COMBINER_IRQ(34, 0)
 
+#define IRQ_MCT_L1		COMBINER_IRQ(35, 3)
+
 #define IRQ_EINT4		COMBINER_IRQ(37, 0)
 #define IRQ_EINT5		COMBINER_IRQ(37, 1)
 #define IRQ_EINT6		COMBINER_IRQ(37, 2)
@@ -101,7 +128,11 @@
 
 #define IRQ_EINT16_31		COMBINER_IRQ(39, 0)
 
-#define MAX_COMBINER_NR		40
+#define IRQ_MCT_L0		COMBINER_IRQ(51, 0)
+
+#define IRQ_WDT			COMBINER_IRQ(53, 0)
+
+#define MAX_COMBINER_NR		54
 
 #define S5P_IRQ_EINT_BASE	COMBINER_IRQ(MAX_COMBINER_NR, 0)
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-s5pv310/include/mach/map.h linux-libre-2.6.38-gnu1/arch/arm/mach-s5pv310/include/mach/map.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-s5pv310/include/mach/map.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-s5pv310/include/mach/map.h	2011-03-14 21:20:32.000000000 -0400
@@ -1,6 +1,6 @@
 /* linux/arch/arm/mach-s5pv310/include/mach/map.h
  *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
  *		http://www.samsung.com/
  *
  * S5PV310 - Memory map definitions
@@ -23,64 +23,86 @@
 
 #include <plat/map-s5p.h>
 
-#define S5PV310_PA_SYSRAM		(0x02025000)
+#define S5PV310_PA_SYSRAM		0x02025000
+
+#define S5PV310_PA_I2S0			0x03830000
+#define S5PV310_PA_I2S1			0xE3100000
+#define S5PV310_PA_I2S2			0xE2A00000
+
+#define S5PV310_PA_PCM0			0x03840000
+#define S5PV310_PA_PCM1			0x13980000
+#define S5PV310_PA_PCM2			0x13990000
 
 #define S5PV310_PA_SROM_BANK(x)		(0x04000000 + ((x) * 0x01000000))
 
-#define S5PC210_PA_ONENAND		(0x0C000000)
-#define S5P_PA_ONENAND			S5PC210_PA_ONENAND
+#define S5PC210_PA_ONENAND		0x0C000000
+#define S5PC210_PA_ONENAND_DMA		0x0C600000
 
-#define S5PC210_PA_ONENAND_DMA		(0x0C600000)
-#define S5P_PA_ONENAND_DMA		S5PC210_PA_ONENAND_DMA
+#define S5PV310_PA_CHIPID		0x10000000
 
-#define S5PV310_PA_CHIPID		(0x10000000)
-#define S5P_PA_CHIPID			S5PV310_PA_CHIPID
+#define S5PV310_PA_SYSCON		0x10010000
+#define S5PV310_PA_PMU			0x10020000
+#define S5PV310_PA_CMU			0x10030000
 
-#define S5PV310_PA_SYSCON		(0x10010000)
-#define S5P_PA_SYSCON			S5PV310_PA_SYSCON
+#define S5PV310_PA_WATCHDOG		0x10060000
+#define S5PV310_PA_RTC			0x10070000
 
-#define S5PV310_PA_CMU			(0x10030000)
+#define S5PV310_PA_DMC0			0x10400000
 
-#define S5PV310_PA_WATCHDOG		(0x10060000)
-#define S5PV310_PA_RTC			(0x10070000)
+#define S5PV310_PA_COMBINER		0x10448000
 
-#define S5PV310_PA_COMBINER		(0x10448000)
+#define S5PV310_PA_COREPERI		0x10500000
+#define S5PV310_PA_GIC_CPU		0x10500100
+#define S5PV310_PA_TWD			0x10500600
+#define S5PV310_PA_GIC_DIST		0x10501000
+#define S5PV310_PA_L2CC			0x10502000
 
-#define S5PV310_PA_COREPERI		(0x10500000)
-#define S5PV310_PA_GIC_CPU		(0x10500100)
-#define S5PV310_PA_TWD			(0x10500600)
-#define S5PV310_PA_GIC_DIST		(0x10501000)
-#define S5PV310_PA_L2CC			(0x10502000)
+#define S5PV310_PA_MDMA			0x10810000
+#define S5PV310_PA_PDMA0		0x12680000
+#define S5PV310_PA_PDMA1		0x12690000
 
-#define S5PV310_PA_GPIO1		(0x11400000)
-#define S5PV310_PA_GPIO2		(0x11000000)
-#define S5PV310_PA_GPIO3		(0x03860000)
+#define S5PV310_PA_SYSMMU_MDMA		0x10A40000
+#define S5PV310_PA_SYSMMU_SSS		0x10A50000
+#define S5PV310_PA_SYSMMU_FIMC0		0x11A20000
+#define S5PV310_PA_SYSMMU_FIMC1		0x11A30000
+#define S5PV310_PA_SYSMMU_FIMC2		0x11A40000
+#define S5PV310_PA_SYSMMU_FIMC3		0x11A50000
+#define S5PV310_PA_SYSMMU_JPEG		0x11A60000
+#define S5PV310_PA_SYSMMU_FIMD0		0x11E20000
+#define S5PV310_PA_SYSMMU_FIMD1		0x12220000
+#define S5PV310_PA_SYSMMU_PCIe		0x12620000
+#define S5PV310_PA_SYSMMU_G2D		0x12A20000
+#define S5PV310_PA_SYSMMU_ROTATOR	0x12A30000
+#define S5PV310_PA_SYSMMU_MDMA2		0x12A40000
+#define S5PV310_PA_SYSMMU_TV		0x12E20000
+#define S5PV310_PA_SYSMMU_MFC_L		0x13620000
+#define S5PV310_PA_SYSMMU_MFC_R		0x13630000
 
-#define S5PV310_PA_HSMMC(x)		(0x12510000 + ((x) * 0x10000))
+#define S5PV310_PA_GPIO1		0x11400000
+#define S5PV310_PA_GPIO2		0x11000000
+#define S5PV310_PA_GPIO3		0x03860000
 
-#define S5PV310_PA_SROMC		(0x12570000)
+#define S5PV310_PA_MIPI_CSIS0		0x11880000
+#define S5PV310_PA_MIPI_CSIS1		0x11890000
 
-#define S5PV310_PA_UART			(0x13800000)
+#define S5PV310_PA_HSMMC(x)		(0x12510000 + ((x) * 0x10000))
 
-#define S5P_PA_UART(x)			(S5PV310_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 S5PV310_PA_SROMC		0x12570000
 
-#define S5P_SZ_UART			SZ_256
+#define S5PV310_PA_UART			0x13800000
 
 #define S5PV310_PA_IIC(x)		(0x13860000 + ((x) * 0x10000))
 
-#define S5PV310_PA_TIMER		(0x139D0000)
-#define S5P_PA_TIMER			S5PV310_PA_TIMER
+#define S5PV310_PA_AC97			0x139A0000
 
-#define S5PV310_PA_SDRAM		(0x40000000)
-#define S5P_PA_SDRAM			S5PV310_PA_SDRAM
+#define S5PV310_PA_TIMER		0x139D0000
+
+#define S5PV310_PA_SDRAM		0x40000000
+
+#define S5PV310_PA_SPDIF		0xE1100000
+
+/* Compatibiltiy Defines */
 
-/* compatibiltiy defines. */
-#define S3C_PA_UART			S5PV310_PA_UART
 #define S3C_PA_HSMMC0			S5PV310_PA_HSMMC(0)
 #define S3C_PA_HSMMC1			S5PV310_PA_HSMMC(1)
 #define S3C_PA_HSMMC2			S5PV310_PA_HSMMC(2)
@@ -96,4 +118,27 @@
 #define S3C_PA_RTC			S5PV310_PA_RTC
 #define S3C_PA_WDT			S5PV310_PA_WATCHDOG
 
+#define S5P_PA_CHIPID			S5PV310_PA_CHIPID
+#define S5P_PA_MIPI_CSIS0		S5PV310_PA_MIPI_CSIS0
+#define S5P_PA_MIPI_CSIS1		S5PV310_PA_MIPI_CSIS1
+#define S5P_PA_ONENAND			S5PC210_PA_ONENAND
+#define S5P_PA_ONENAND_DMA		S5PC210_PA_ONENAND_DMA
+#define S5P_PA_SDRAM			S5PV310_PA_SDRAM
+#define S5P_PA_SROMC			S5PV310_PA_SROMC
+#define S5P_PA_SYSCON			S5PV310_PA_SYSCON
+#define S5P_PA_TIMER			S5PV310_PA_TIMER
+
+/* UART */
+
+#define S3C_PA_UART			S5PV310_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-2.6.37-gnu1/arch/arm/mach-s5pv310/include/mach/regs-clock.h linux-libre-2.6.38-gnu1/arch/arm/mach-s5pv310/include/mach/regs-clock.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-s5pv310/include/mach/regs-clock.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-s5pv310/include/mach/regs-clock.h	2011-03-14 21:20:32.000000000 -0400
@@ -19,6 +19,12 @@
 
 #define S5P_INFORM0			S5P_CLKREG(0x800)
 
+#define S5P_CLKDIV_LEFTBUS		S5P_CLKREG(0x04500)
+#define S5P_CLKDIV_STAT_LEFTBUS		S5P_CLKREG(0x04600)
+
+#define S5P_CLKDIV_RIGHTBUS		S5P_CLKREG(0x08500)
+#define S5P_CLKDIV_STAT_RIGHTBUS	S5P_CLKREG(0x08600)
+
 #define S5P_EPLL_CON0			S5P_CLKREG(0x0C110)
 #define S5P_EPLL_CON1			S5P_CLKREG(0x0C114)
 #define S5P_VPLL_CON0			S5P_CLKREG(0x0C120)
@@ -58,6 +64,8 @@
 #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_IP_CAM		S5P_CLKREG(0x0C920)
 #define S5P_CLKGATE_IP_IMAGE		S5P_CLKREG(0x0C930)
 #define S5P_CLKGATE_IP_LCD0		S5P_CLKREG(0x0C934)
@@ -66,8 +74,9 @@
 #define S5P_CLKGATE_IP_PERIL		S5P_CLKREG(0x0C950)
 #define S5P_CLKGATE_IP_PERIR		S5P_CLKREG(0x0C960)
 
-#define S5P_CLKSRC_CORE			S5P_CLKREG(0x10200)
-#define S5P_CLKDIV_CORE0		S5P_CLKREG(0x10500)
+#define S5P_CLKSRC_DMC			S5P_CLKREG(0x10200)
+#define S5P_CLKDIV_DMC0			S5P_CLKREG(0x10500)
+#define S5P_CLKDIV_STAT_DMC0		S5P_CLKREG(0x10600)
 
 #define S5P_APLL_LOCK			S5P_CLKREG(0x14000)
 #define S5P_MPLL_LOCK			S5P_CLKREG(0x14004)
@@ -80,10 +89,77 @@
 #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)
 
+/* APLL_LOCK */
+#define S5P_APLL_LOCKTIME		(0x1C20)	/* 300us */
+
+/* APLL_CON0 */
+#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)
+
+/* CLK_SRC_CPU */
+#define S5P_CLKSRC_CPU_MUXCORE_SHIFT	(16)
+#define S5P_CLKMUX_STATCPU_MUXCORE_MASK	(0x7 << S5P_CLKSRC_CPU_MUXCORE_SHIFT)
+
+/* CLKDIV_CPU0 */
+#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)
+
+/* CLKDIV_DMC0 */
+#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)
+
+/* CLKDIV_TOP */
+#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)
+
+/* CLKDIV_LEFTBUS / CLKDIV_RIGHTBUS*/
+#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 */
 
 #define S5P_EPLL_CON			S5P_EPLL_CON0
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-s5pv310/include/mach/regs-mem.h linux-libre-2.6.38-gnu1/arch/arm/mach-s5pv310/include/mach/regs-mem.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-s5pv310/include/mach/regs-mem.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-s5pv310/include/mach/regs-mem.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,23 @@
+/* linux/arch/arm/mach-s5pv310/include/mach/regs-mem.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * S5PV310 - 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-2.6.37-gnu1/arch/arm/mach-s5pv310/include/mach/regs-pmu.h linux-libre-2.6.38-gnu1/arch/arm/mach-s5pv310/include/mach/regs-pmu.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-s5pv310/include/mach/regs-pmu.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-s5pv310/include/mach/regs-pmu.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,30 @@
+/* linux/arch/arm/mach-s5pv310/include/mach/regs-pmu.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * S5PV310 - 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_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_INT_LOCAL_PWR_EN		0x7
+
+#endif /* __ASM_ARCH_REGS_PMU_H */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-s5pv310/include/mach/regs-srom.h linux-libre-2.6.38-gnu1/arch/arm/mach-s5pv310/include/mach/regs-srom.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-s5pv310/include/mach/regs-srom.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-s5pv310/include/mach/regs-srom.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,50 +0,0 @@
-/* linux/arch/arm/mach-s5pv310/include/mach/regs-srom.h
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * S5PV310 - 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_ARCH_REGS_SROM_H
-#define __ASM_ARCH_REGS_SROM_H __FILE__
-
-#include <mach/map.h>
-
-#define S5PV310_SROMREG(x)	(S5P_VA_SROMC + (x))
-
-#define S5PV310_SROM_BW		S5PV310_SROMREG(0x0)
-#define S5PV310_SROM_BC0	S5PV310_SROMREG(0x4)
-#define S5PV310_SROM_BC1	S5PV310_SROMREG(0x8)
-#define S5PV310_SROM_BC2	S5PV310_SROMREG(0xc)
-#define S5PV310_SROM_BC3	S5PV310_SROMREG(0x10)
-
-/* one register BW holds 4 x 4-bit packed settings for NCS0 - NCS3 */
-
-#define S5PV310_SROM_BW__DATAWIDTH__SHIFT	0
-#define S5PV310_SROM_BW__ADDRMODE__SHIFT	1
-#define S5PV310_SROM_BW__WAITENABLE__SHIFT	2
-#define S5PV310_SROM_BW__BYTEENABLE__SHIFT	3
-
-#define S5PV310_SROM_BW__CS_MASK		0xf
-
-#define S5PV310_SROM_BW__NCS0__SHIFT		0
-#define S5PV310_SROM_BW__NCS1__SHIFT		4
-#define S5PV310_SROM_BW__NCS2__SHIFT		8
-#define S5PV310_SROM_BW__NCS3__SHIFT		12
-
-/* applies to same to BCS0 - BCS3 */
-
-#define S5PV310_SROM_BCX__PMC__SHIFT		0
-#define S5PV310_SROM_BCX__TACP__SHIFT		4
-#define S5PV310_SROM_BCX__TCAH__SHIFT		8
-#define S5PV310_SROM_BCX__TCOH__SHIFT		12
-#define S5PV310_SROM_BCX__TACC__SHIFT		16
-#define S5PV310_SROM_BCX__TCOS__SHIFT		24
-#define S5PV310_SROM_BCX__TACS__SHIFT		28
-
-#endif /* __ASM_ARCH_REGS_SROM_H */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-s5pv310/include/mach/regs-sysmmu.h linux-libre-2.6.38-gnu1/arch/arm/mach-s5pv310/include/mach/regs-sysmmu.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-s5pv310/include/mach/regs-sysmmu.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-s5pv310/include/mach/regs-sysmmu.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,24 @@
+/* linux/arch/arm/mach-s5pv310/include/mach/regs-sysmmu.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * S5PV310 - 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_PAGE_FAULT_ADDR		0x024
+
+#endif /* __ASM_ARCH_REGS_SYSMMU_H */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-s5pv310/include/mach/smp.h linux-libre-2.6.38-gnu1/arch/arm/mach-s5pv310/include/mach/smp.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-s5pv310/include/mach/smp.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-s5pv310/include/mach/smp.h	2011-03-14 21:20:32.000000000 -0400
@@ -7,16 +7,13 @@
 #define ASM_ARCH_SMP_H __FILE__
 
 #include <asm/hardware/gic.h>
-#include <asm/smp_mpidr.h>
-
-extern void __iomem *gic_cpu_base_addr;
 
 /*
  * We use IRQ1 as the IPI
  */
-static inline void smp_cross_call(const struct cpumask *mask)
+static inline void smp_cross_call(const struct cpumask *mask, int ipi)
 {
-	gic_raise_softirq(mask, 1);
+	gic_raise_softirq(mask, ipi);
 }
 
 #endif
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-s5pv310/include/mach/sysmmu.h linux-libre-2.6.38-gnu1/arch/arm/mach-s5pv310/include/mach/sysmmu.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-s5pv310/include/mach/sysmmu.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-s5pv310/include/mach/sysmmu.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,122 @@
+/* linux/arch/arm/mach-s5pv310/include/mach/sysmmu.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * Samsung sysmmu driver for S5PV310
+ *
+ * This program is free software; you can 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__
+
+#define S5PV310_SYSMMU_TOTAL_IPNUM	16
+#define S5P_SYSMMU_TOTAL_IPNUM		S5PV310_SYSMMU_TOTAL_IPNUM
+
+enum s5pv310_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,
+};
+
+static char *sysmmu_ips_name[S5PV310_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"	,
+};
+
+typedef enum s5pv310_sysmmu_ips sysmmu_ips;
+
+struct sysmmu_tt_info {
+	unsigned long *pgd;
+	unsigned long pgd_paddr;
+	unsigned long *pte;
+};
+
+struct sysmmu_controller {
+	const char		*name;
+
+	/* channels registers */
+	void __iomem		*regs;
+
+	/* channel irq */
+	unsigned int		irq;
+
+	sysmmu_ips		ips;
+
+	/* Translation Table Info. */
+	struct sysmmu_tt_info	*tt_info;
+
+	struct resource		*mem;
+	struct device		*dev;
+
+	/* SysMMU controller enable - true : enable */
+	bool			enable;
+};
+
+/**
+ * s5p_sysmmu_enable() - enable system mmu of ip
+ * @ips: The ip connected system mmu.
+ *
+ * This function enable system mmu to transfer address
+ * from virtual address to physical address
+ */
+int s5p_sysmmu_enable(sysmmu_ips ips);
+
+/**
+ * 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
+ */
+int 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
+ */
+int 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
+ */
+int s5p_sysmmu_tlb_invalidate(sysmmu_ips ips);
+#endif /* __ASM_ARM_ARCH_SYSMMU_H */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-s5pv310/irq-combiner.c linux-libre-2.6.38-gnu1/arch/arm/mach-s5pv310/irq-combiner.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-s5pv310/irq-combiner.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-s5pv310/irq-combiner.c	2011-03-14 21:20:32.000000000 -0400
@@ -24,29 +24,32 @@ static DEFINE_SPINLOCK(irq_controller_lo
 
 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(unsigned int irq)
+static inline void __iomem *combiner_base(struct irq_data *data)
 {
-	struct combiner_chip_data *combiner_data = get_irq_chip_data(irq);
+	struct combiner_chip_data *combiner_data =
+		irq_data_get_irq_chip_data(data);
+
 	return combiner_data->base;
 }
 
-static void combiner_mask_irq(unsigned int irq)
+static void combiner_mask_irq(struct irq_data *data)
 {
-	u32 mask = 1 << (irq % 32);
+	u32 mask = 1 << (data->irq % 32);
 
-	__raw_writel(mask, combiner_base(irq) + COMBINER_ENABLE_CLEAR);
+	__raw_writel(mask, combiner_base(data) + COMBINER_ENABLE_CLEAR);
 }
 
-static void combiner_unmask_irq(unsigned int irq)
+static void combiner_unmask_irq(struct irq_data *data)
 {
-	u32 mask = 1 << (irq % 32);
+	u32 mask = 1 << (data->irq % 32);
 
-	__raw_writel(mask, combiner_base(irq) + COMBINER_ENABLE_SET);
+	__raw_writel(mask, combiner_base(data) + COMBINER_ENABLE_SET);
 }
 
 static void combiner_handle_cascade_irq(unsigned int irq, struct irq_desc *desc)
@@ -57,11 +60,12 @@ static void combiner_handle_cascade_irq(
 	unsigned long status;
 
 	/* primary controller ack'ing */
-	chip->ack(irq);
+	chip->irq_ack(&desc->irq_data);
 
 	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;
@@ -76,13 +80,13 @@ static void combiner_handle_cascade_irq(
 
  out:
 	/* primary controller unmasking */
-	chip->unmask(irq);
+	chip->irq_unmask(&desc->irq_data);
 }
 
 static struct irq_chip combiner_chip = {
 	.name		= "COMBINER",
-	.mask		= combiner_mask_irq,
-	.unmask		= combiner_unmask_irq,
+	.irq_mask	= combiner_mask_irq,
+	.irq_unmask	= combiner_unmask_irq,
 };
 
 void __init combiner_cascade_irq(unsigned int combiner_nr, unsigned int irq)
@@ -104,10 +108,12 @@ void __init combiner_init(unsigned int c
 
 	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(0xffffffff, base + COMBINER_ENABLE_CLEAR);
+	__raw_writel(combiner_data[combiner_nr].irq_mask,
+		     base + COMBINER_ENABLE_CLEAR);
 
 	/* Setup the Linux IRQ subsystem */
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-s5pv310/irq-eint.c linux-libre-2.6.38-gnu1/arch/arm/mach-s5pv310/irq-eint.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-s5pv310/irq-eint.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-s5pv310/irq-eint.c	2011-03-14 21:20:32.000000000 -0400
@@ -48,42 +48,43 @@ static unsigned int s5pv310_get_irq_nr(u
 	return ret;
 }
 
-static inline void s5pv310_irq_eint_mask(unsigned int irq)
+static inline void s5pv310_irq_eint_mask(struct irq_data *data)
 {
 	u32 mask;
 
 	spin_lock(&eint_lock);
-	mask = __raw_readl(S5P_EINT_MASK(EINT_REG_NR(irq)));
-	mask |= eint_irq_to_bit(irq);
-	__raw_writel(mask, S5P_EINT_MASK(EINT_REG_NR(irq)));
+	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 s5pv310_irq_eint_unmask(unsigned int irq)
+static void s5pv310_irq_eint_unmask(struct irq_data *data)
 {
 	u32 mask;
 
 	spin_lock(&eint_lock);
-	mask = __raw_readl(S5P_EINT_MASK(EINT_REG_NR(irq)));
-	mask &= ~(eint_irq_to_bit(irq));
-	__raw_writel(mask, S5P_EINT_MASK(EINT_REG_NR(irq)));
+	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 s5pv310_irq_eint_ack(unsigned int irq)
+static inline void s5pv310_irq_eint_ack(struct irq_data *data)
 {
-	__raw_writel(eint_irq_to_bit(irq), S5P_EINT_PEND(EINT_REG_NR(irq)));
+	__raw_writel(eint_irq_to_bit(data->irq),
+		     S5P_EINT_PEND(EINT_REG_NR(data->irq)));
 }
 
-static void s5pv310_irq_eint_maskack(unsigned int irq)
+static void s5pv310_irq_eint_maskack(struct irq_data *data)
 {
-	s5pv310_irq_eint_mask(irq);
-	s5pv310_irq_eint_ack(irq);
+	s5pv310_irq_eint_mask(data);
+	s5pv310_irq_eint_ack(data);
 }
 
-static int s5pv310_irq_eint_set_type(unsigned int irq, unsigned int type)
+static int s5pv310_irq_eint_set_type(struct irq_data *data, unsigned int type)
 {
-	int offs = EINT_OFFSET(irq);
+	int offs = EINT_OFFSET(data->irq);
 	int shift;
 	u32 ctrl, mask;
 	u32 newvalue = 0;
@@ -118,10 +119,10 @@ static int s5pv310_irq_eint_set_type(uns
 	mask = 0x7 << shift;
 
 	spin_lock(&eint_lock);
-	ctrl = __raw_readl(S5P_EINT_CON(EINT_REG_NR(irq)));
+	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(irq)));
+	__raw_writel(ctrl, S5P_EINT_CON(EINT_REG_NR(data->irq)));
 	spin_unlock(&eint_lock);
 
 	switch (offs) {
@@ -146,13 +147,13 @@ static int s5pv310_irq_eint_set_type(uns
 
 static struct irq_chip s5pv310_irq_eint = {
 	.name		= "s5pv310-eint",
-	.mask		= s5pv310_irq_eint_mask,
-	.unmask		= s5pv310_irq_eint_unmask,
-	.mask_ack	= s5pv310_irq_eint_maskack,
-	.ack		= s5pv310_irq_eint_ack,
-	.set_type	= s5pv310_irq_eint_set_type,
+	.irq_mask	= s5pv310_irq_eint_mask,
+	.irq_unmask	= s5pv310_irq_eint_unmask,
+	.irq_mask_ack	= s5pv310_irq_eint_maskack,
+	.irq_ack	= s5pv310_irq_eint_ack,
+	.irq_set_type	= s5pv310_irq_eint_set_type,
 #ifdef CONFIG_PM
-	.set_wake	= s3c_irqext_wake,
+	.irq_set_wake	= s3c_irqext_wake,
 #endif
 };
 
@@ -192,14 +193,14 @@ static void s5pv310_irq_eint0_15(unsigne
 	u32 *irq_data = get_irq_data(irq);
 	struct irq_chip *chip = get_irq_chip(irq);
 
-	chip->mask(irq);
+	chip->irq_mask(&desc->irq_data);
 
-	if (chip->ack)
-		chip->ack(irq);
+	if (chip->irq_ack)
+		chip->irq_ack(&desc->irq_data);
 
 	generic_handle_irq(*irq_data);
 
-	chip->unmask(irq);
+	chip->irq_unmask(&desc->irq_data);
 }
 
 int __init s5pv310_init_irq_eint(void)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-s5pv310/Kconfig linux-libre-2.6.38-gnu1/arch/arm/mach-s5pv310/Kconfig
--- linux-libre-2.6.37-gnu1/arch/arm/mach-s5pv310/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-s5pv310/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -11,9 +11,15 @@ if ARCH_S5PV310
 
 config CPU_S5PV310
 	bool
+	select S3C_PL330_DMA
 	help
 	  Enable S5PV310 CPU support
 
+config S5PV310_DEV_PD
+	bool
+	help
+	  Compile in platform device definitions for Power Domain
+
 config S5PV310_SETUP_I2C1
 	bool
 	help
@@ -60,6 +66,11 @@ config S5PV310_SETUP_SDHCI_GPIO
 	help
 	  Common setup code for SDHCI gpio.
 
+config S5PV310_DEV_SYSMMU
+	bool
+	help
+	  Common setup code for SYSTEM MMU in S5PV310
+
 # machine support
 
 menu "S5PC210 Machines"
@@ -69,11 +80,15 @@ config MACH_SMDKC210
 	select CPU_S5PV310
 	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 S5PV310_DEV_PD
+	select S5PV310_SETUP_I2C1
 	select S5PV310_SETUP_SDHCI
+	select S5PV310_DEV_SYSMMU
 	help
 	  Machine support for Samsung SMDKC210
 	  S5PC210(MCP) is one of package option of S5PV310
@@ -82,6 +97,10 @@ config MACH_UNIVERSAL_C210
 	bool "Mobile UNIVERSAL_C210 Board"
 	select CPU_S5PV310
 	select S5P_DEV_ONENAND
+	select S3C_DEV_HSMMC
+	select S3C_DEV_HSMMC2
+	select S3C_DEV_HSMMC3
+	select S5PV310_SETUP_SDHCI
 	select S3C_DEV_I2C1
 	select S5PV310_SETUP_I2C1
 	help
@@ -97,10 +116,14 @@ config MACH_SMDKV310
 	select CPU_S5PV310
 	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 S5PV310_DEV_PD
+	select S5PV310_DEV_SYSMMU
+	select S5PV310_SETUP_I2C1
 	select S5PV310_SETUP_SDHCI
 	help
 	  Machine support for Samsung SMDKV310
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-s5pv310/mach-smdkc210.c linux-libre-2.6.38-gnu1/arch/arm/mach-s5pv310/mach-smdkc210.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-s5pv310/mach-smdkc210.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-s5pv310/mach-smdkc210.c	2011-03-14 21:20:32.000000000 -0400
@@ -14,18 +14,21 @@
 #include <linux/platform_device.h>
 #include <linux/smsc911x.h>
 #include <linux/io.h>
+#include <linux/i2c.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
 
 #include <plat/regs-serial.h>
+#include <plat/regs-srom.h>
 #include <plat/s5pv310.h>
 #include <plat/cpu.h>
 #include <plat/devs.h>
 #include <plat/sdhci.h>
+#include <plat/iic.h>
+#include <plat/pd.h>
 
 #include <mach/map.h>
-#include <mach/regs-srom.h>
 
 /* Following are default values for UCON, ULCON and UFCON UART registers */
 #define SMDKC210_UCON_DEFAULT	(S3C2410_UCON_TXILEVEL |	\
@@ -139,13 +142,29 @@ static struct platform_device smdkc210_s
 	},
 };
 
+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,
+	&s5pv310_device_ac97,
+	&s5pv310_device_i2s0,
+	&s5pv310_device_pd[PD_MFC],
+	&s5pv310_device_pd[PD_G3D],
+	&s5pv310_device_pd[PD_LCD0],
+	&s5pv310_device_pd[PD_LCD1],
+	&s5pv310_device_pd[PD_CAM],
+	&s5pv310_device_pd[PD_TV],
+	&s5pv310_device_pd[PD_GPS],
+	&s5pv310_device_sysmmu,
+	&samsung_asoc_dma,
 	&smdkc210_smsc911x,
 };
 
@@ -154,23 +173,22 @@ static void __init smdkc210_smsc911x_ini
 	u32 cs1;
 
 	/* configure nCS1 width to 16 bits */
-	cs1 = __raw_readl(S5PV310_SROM_BW) &
-		    ~(S5PV310_SROM_BW__CS_MASK <<
-				    S5PV310_SROM_BW__NCS1__SHIFT);
-	cs1 |= ((1 << S5PV310_SROM_BW__DATAWIDTH__SHIFT) |
-		(1 << S5PV310_SROM_BW__WAITENABLE__SHIFT) |
-		(1 << S5PV310_SROM_BW__BYTEENABLE__SHIFT)) <<
-		S5PV310_SROM_BW__NCS1__SHIFT;
-	__raw_writel(cs1, S5PV310_SROM_BW);
+	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 << S5PV310_SROM_BCX__PMC__SHIFT) |
-		     (0x9 << S5PV310_SROM_BCX__TACP__SHIFT) |
-		     (0xc << S5PV310_SROM_BCX__TCAH__SHIFT) |
-		     (0x1 << S5PV310_SROM_BCX__TCOH__SHIFT) |
-		     (0x6 << S5PV310_SROM_BCX__TACC__SHIFT) |
-		     (0x1 << S5PV310_SROM_BCX__TCOS__SHIFT) |
-		     (0x1 << S5PV310_SROM_BCX__TACS__SHIFT), S5PV310_SROM_BC1);
+	__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 smdkc210_map_io(void)
@@ -182,6 +200,9 @@ static void __init smdkc210_map_io(void)
 
 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);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-s5pv310/mach-smdkv310.c linux-libre-2.6.38-gnu1/arch/arm/mach-s5pv310/mach-smdkv310.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-s5pv310/mach-smdkv310.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-s5pv310/mach-smdkv310.c	2011-03-14 21:20:32.000000000 -0400
@@ -14,18 +14,21 @@
 #include <linux/platform_device.h>
 #include <linux/smsc911x.h>
 #include <linux/io.h>
+#include <linux/i2c.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
 
 #include <plat/regs-serial.h>
+#include <plat/regs-srom.h>
 #include <plat/s5pv310.h>
 #include <plat/cpu.h>
 #include <plat/devs.h>
 #include <plat/sdhci.h>
+#include <plat/iic.h>
+#include <plat/pd.h>
 
 #include <mach/map.h>
-#include <mach/regs-srom.h>
 
 /* Following are default values for UCON, ULCON and UFCON UART registers */
 #define SMDKV310_UCON_DEFAULT	(S3C2410_UCON_TXILEVEL |	\
@@ -139,13 +142,29 @@ static struct platform_device smdkv310_s
 	},
 };
 
+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,
+	&s5pv310_device_ac97,
+	&s5pv310_device_i2s0,
+	&s5pv310_device_pd[PD_MFC],
+	&s5pv310_device_pd[PD_G3D],
+	&s5pv310_device_pd[PD_LCD0],
+	&s5pv310_device_pd[PD_LCD1],
+	&s5pv310_device_pd[PD_CAM],
+	&s5pv310_device_pd[PD_TV],
+	&s5pv310_device_pd[PD_GPS],
+	&s5pv310_device_sysmmu,
+	&samsung_asoc_dma,
 	&smdkv310_smsc911x,
 };
 
@@ -154,23 +173,22 @@ static void __init smdkv310_smsc911x_ini
 	u32 cs1;
 
 	/* configure nCS1 width to 16 bits */
-	cs1 = __raw_readl(S5PV310_SROM_BW) &
-		    ~(S5PV310_SROM_BW__CS_MASK <<
-				    S5PV310_SROM_BW__NCS1__SHIFT);
-	cs1 |= ((1 << S5PV310_SROM_BW__DATAWIDTH__SHIFT) |
-		(1 << S5PV310_SROM_BW__WAITENABLE__SHIFT) |
-		(1 << S5PV310_SROM_BW__BYTEENABLE__SHIFT)) <<
-		S5PV310_SROM_BW__NCS1__SHIFT;
-	__raw_writel(cs1, S5PV310_SROM_BW);
+	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 << S5PV310_SROM_BCX__PMC__SHIFT) |
-		     (0x9 << S5PV310_SROM_BCX__TACP__SHIFT) |
-		     (0xc << S5PV310_SROM_BCX__TCAH__SHIFT) |
-		     (0x1 << S5PV310_SROM_BCX__TCOH__SHIFT) |
-		     (0x6 << S5PV310_SROM_BCX__TACC__SHIFT) |
-		     (0x1 << S5PV310_SROM_BCX__TCOS__SHIFT) |
-		     (0x1 << S5PV310_SROM_BCX__TACS__SHIFT), S5PV310_SROM_BC1);
+	__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 smdkv310_map_io(void)
@@ -182,6 +200,9 @@ static void __init smdkv310_map_io(void)
 
 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);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-s5pv310/mach-universal_c210.c linux-libre-2.6.38-gnu1/arch/arm/mach-s5pv310/mach-universal_c210.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-s5pv310/mach-universal_c210.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-s5pv310/mach-universal_c210.c	2011-03-14 21:20:32.000000000 -0400
@@ -13,6 +13,9 @@
 #include <linux/i2c.h>
 #include <linux/gpio_keys.h>
 #include <linux/gpio.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/fixed.h>
+#include <linux/mmc/host.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
@@ -21,6 +24,7 @@
 #include <plat/s5pv310.h>
 #include <plat/cpu.h>
 #include <plat/devs.h>
+#include <plat/sdhci.h>
 
 #include <mach/map.h>
 
@@ -116,6 +120,73 @@ static struct platform_device universal_
 	},
 };
 
+/* 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			= S5PV310_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		= S5PV310_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 */
@@ -127,6 +198,13 @@ static struct i2c_board_info i2c1_devs[]
 };
 
 static struct platform_device *universal_devices[] __initdata = {
+	/* Samsung Platform Devices */
+	&mmc0_fixed_voltage,
+	&s3c_device_hsmmc0,
+	&s3c_device_hsmmc2,
+	&s3c_device_hsmmc3,
+
+	/* Universal Devices */
 	&universal_gpio_keys,
 	&s5p_device_onenand,
 };
@@ -140,6 +218,8 @@ static void __init universal_map_io(void
 
 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));
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-s5pv310/Makefile linux-libre-2.6.38-gnu1/arch/arm/mach-s5pv310/Makefile
--- linux-libre-2.6.37-gnu1/arch/arm/mach-s5pv310/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-s5pv310/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -13,7 +13,8 @@ obj-				:=
 # Core support for S5PV310 system
 
 obj-$(CONFIG_CPU_S5PV310)	+= cpu.o init.o clock.o irq-combiner.o
-obj-$(CONFIG_CPU_S5PV310)	+= setup-i2c0.o time.o gpiolib.o irq-eint.o
+obj-$(CONFIG_CPU_S5PV310)	+= setup-i2c0.o time.o gpiolib.o irq-eint.o dma.o
+obj-$(CONFIG_CPU_FREQ)		+= cpufreq.o
 
 obj-$(CONFIG_SMP)		+= platsmp.o headsmp.o
 obj-$(CONFIG_LOCAL_TIMERS)	+= localtimer.o
@@ -27,6 +28,10 @@ obj-$(CONFIG_MACH_UNIVERSAL_C210)	+= mac
 
 # device support
 
+obj-y					+= dev-audio.o
+obj-$(CONFIG_S5PV310_DEV_PD)		+= dev-pd.o
+obj-$(CONFIG_S5PV310_DEV_SYSMMU)	+= dev-sysmmu.o
+
 obj-$(CONFIG_S5PV310_SETUP_I2C1)	+= setup-i2c1.o
 obj-$(CONFIG_S5PV310_SETUP_I2C2)	+= setup-i2c2.o
 obj-$(CONFIG_S5PV310_SETUP_I2C3)	+= setup-i2c3.o
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-s5pv310/platsmp.c linux-libre-2.6.38-gnu1/arch/arm/mach-s5pv310/platsmp.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-s5pv310/platsmp.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-s5pv310/platsmp.c	2011-03-14 21:20:32.000000000 -0400
@@ -22,7 +22,6 @@
 #include <linux/io.h>
 
 #include <asm/cacheflush.h>
-#include <asm/localtimer.h>
 #include <asm/smp_scu.h>
 #include <asm/unified.h>
 
@@ -38,6 +37,19 @@ extern void s5pv310_secondary_startup(vo
 
 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);
@@ -47,21 +59,18 @@ static DEFINE_SPINLOCK(boot_lock);
 
 void __cpuinit platform_secondary_init(unsigned int cpu)
 {
-	trace_hardirqs_off();
-
 	/*
 	 * 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_cpu_init(0, gic_cpu_base_addr);
+	gic_secondary_init(0);
 
 	/*
 	 * let the primary processor know we're out of the
 	 * pen, then head off into the C entry point
 	 */
-	pen_release = -1;
-	smp_wmb();
+	write_pen_release(-1);
 
 	/*
 	 * Synchronise with the boot thread.
@@ -88,16 +97,14 @@ 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;
-	__cpuc_flush_dcache_area((void *)&pen_release, sizeof(pen_release));
-	outer_clean_range(__pa(&pen_release), __pa(&pen_release + 1));
+	write_pen_release(cpu);
 
 	/*
 	 * 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.
 	 */
-	smp_cross_call(cpumask_of(cpu));
+	smp_cross_call(cpumask_of(cpu), 1);
 
 	timeout = jiffies + (1 * HZ);
 	while (time_before(jiffies, timeout)) {
@@ -130,13 +137,6 @@ void __init smp_init_cpus(void)
 	ncores = scu_base ? scu_get_core_count(scu_base) : 1;
 
 	/* sanity check */
-	if (ncores == 0) {
-		printk(KERN_ERR
-		       "S5PV310: strange CM count of 0? Default to 1\n");
-
-		ncores = 1;
-	}
-
 	if (ncores > NR_CPUS) {
 		printk(KERN_WARNING
 		       "S5PV310: no. of cores (%d) greater than configured "
@@ -149,18 +149,10 @@ void __init smp_init_cpus(void)
 		set_cpu_possible(i, true);
 }
 
-void __init smp_prepare_cpus(unsigned int max_cpus)
+void __init platform_smp_prepare_cpus(unsigned int max_cpus)
 {
-	unsigned int ncores = num_possible_cpus();
-	unsigned int cpu = smp_processor_id();
 	int i;
 
-	smp_store_cpu_info(cpu);
-
-	/* are we trying to boot more cores than exist? */
-	if (max_cpus > ncores)
-		max_cpus = ncores;
-
 	/*
 	 * Initialise the present map, which describes the set of CPUs
 	 * actually populated at the present time.
@@ -168,25 +160,13 @@ void __init smp_prepare_cpus(unsigned in
 	for (i = 0; i < max_cpus; i++)
 		set_cpu_present(i, true);
 
+	scu_enable(scu_base_addr());
+
 	/*
-	 * Initialise the SCU if there are more than one CPU and let
-	 * them know where to start.
+	 * 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.
 	 */
-	if (max_cpus > 1) {
-		/*
-		 * Enable the local timer or broadcast device for the
-		 * boot CPU, but only if we have more than one CPU.
-		 */
-		percpu_timer_setup();
-
-		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(s5pv310_secondary_startup)), S5P_VA_SYSRAM);
-	}
 }
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-s5pv310/time.c linux-libre-2.6.38-gnu1/arch/arm/mach-s5pv310/time.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-s5pv310/time.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-s5pv310/time.c	2011-03-14 21:20:32.000000000 -0400
@@ -211,7 +211,6 @@ struct clocksource pwm_clocksource = {
 	.rating		= 250,
 	.read		= s5pv310_pwm4_read,
 	.mask		= CLOCKSOURCE_MASK(32),
-	.shift		= 20,
 	.flags		= CLOCK_SOURCE_IS_CONTINUOUS ,
 };
 
@@ -230,10 +229,7 @@ static void __init s5pv310_clocksource_i
 	s5pv310_pwm_init(4, ~0);
 	s5pv310_pwm_start(4, 1);
 
-	pwm_clocksource.mult =
-		clocksource_khz2mult(clock_rate/1000, pwm_clocksource.shift);
-
-	if (clocksource_register(&pwm_clocksource))
+	if (clocksource_register_hz(&pwm_clocksource, clock_rate))
 		panic("%s: can't register clocksource\n", pwm_clocksource.name);
 }
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-sa1100/collie.c linux-libre-2.6.38-gnu1/arch/arm/mach-sa1100/collie.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-sa1100/collie.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-sa1100/collie.c	2011-03-14 21:20:32.000000000 -0400
@@ -241,6 +241,9 @@ static struct locomo_platform_data locom
 struct platform_device collie_locomo_device = {
 	.name		= "locomo",
 	.id		= 0,
+	.dev		= {
+		.platform_data	= &locomo_info,
+	},
 	.num_resources	= ARRAY_SIZE(locomo_resources),
 	.resource	= locomo_resources,
 };
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-sa1100/cpu-sa1100.c linux-libre-2.6.38-gnu1/arch/arm/mach-sa1100/cpu-sa1100.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-sa1100/cpu-sa1100.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-sa1100/cpu-sa1100.c	2011-03-14 21:20:32.000000000 -0400
@@ -94,48 +94,47 @@
 
 #include "generic.h"
 
-typedef struct {
+struct sa1100_dram_regs {
 	int speed;
 	u32 mdcnfg;
 	u32 mdcas0;
 	u32 mdcas1;
 	u32 mdcas2;
-} sa1100_dram_regs_t;
+};
 
 
 static struct cpufreq_driver sa1100_driver;
 
-static sa1100_dram_regs_t sa1100_dram_settings[] =
-{
-	/* speed,     mdcnfg,     mdcas0,     mdcas1,     mdcas2  clock frequency */
-	{  59000, 0x00dc88a3, 0xcccccccf, 0xfffffffc, 0xffffffff }, /*  59.0 MHz */
-	{  73700, 0x011490a3, 0xcccccccf, 0xfffffffc, 0xffffffff }, /*  73.7 MHz */
-	{  88500, 0x014e90a3, 0xcccccccf, 0xfffffffc, 0xffffffff }, /*  88.5 MHz */
-	{ 103200, 0x01889923, 0xcccccccf, 0xfffffffc, 0xffffffff }, /* 103.2 MHz */
-	{ 118000, 0x01c29923, 0x9999998f, 0xfffffff9, 0xffffffff }, /* 118.0 MHz */
-	{ 132700, 0x01fb2123, 0x9999998f, 0xfffffff9, 0xffffffff }, /* 132.7 MHz */
-	{ 147500, 0x02352123, 0x3333330f, 0xfffffff3, 0xffffffff }, /* 147.5 MHz */
-	{ 162200, 0x026b29a3, 0x38e38e1f, 0xfff8e38e, 0xffffffff }, /* 162.2 MHz */
-	{ 176900, 0x02a329a3, 0x71c71c1f, 0xfff1c71c, 0xffffffff }, /* 176.9 MHz */
-	{ 191700, 0x02dd31a3, 0xe38e383f, 0xffe38e38, 0xffffffff }, /* 191.7 MHz */
-	{ 206400, 0x03153223, 0xc71c703f, 0xffc71c71, 0xffffffff }, /* 206.4 MHz */
-	{ 221200, 0x034fba23, 0xc71c703f, 0xffc71c71, 0xffffffff }, /* 221.2 MHz */
-	{ 235900, 0x03853a23, 0xe1e1e07f, 0xe1e1e1e1, 0xffffffe1 }, /* 235.9 MHz */
-	{ 250700, 0x03bf3aa3, 0xc3c3c07f, 0xc3c3c3c3, 0xffffffc3 }, /* 250.7 MHz */
-	{ 265400, 0x03f7c2a3, 0xc3c3c07f, 0xc3c3c3c3, 0xffffffc3 }, /* 265.4 MHz */
-	{ 280200, 0x0431c2a3, 0x878780ff, 0x87878787, 0xffffff87 }, /* 280.2 MHz */
+static struct sa1100_dram_regs sa1100_dram_settings[] = {
+	/*speed,     mdcnfg,     mdcas0,     mdcas1,     mdcas2,   clock freq */
+	{ 59000, 0x00dc88a3, 0xcccccccf, 0xfffffffc, 0xffffffff},/*  59.0 MHz */
+	{ 73700, 0x011490a3, 0xcccccccf, 0xfffffffc, 0xffffffff},/*  73.7 MHz */
+	{ 88500, 0x014e90a3, 0xcccccccf, 0xfffffffc, 0xffffffff},/*  88.5 MHz */
+	{103200, 0x01889923, 0xcccccccf, 0xfffffffc, 0xffffffff},/* 103.2 MHz */
+	{118000, 0x01c29923, 0x9999998f, 0xfffffff9, 0xffffffff},/* 118.0 MHz */
+	{132700, 0x01fb2123, 0x9999998f, 0xfffffff9, 0xffffffff},/* 132.7 MHz */
+	{147500, 0x02352123, 0x3333330f, 0xfffffff3, 0xffffffff},/* 147.5 MHz */
+	{162200, 0x026b29a3, 0x38e38e1f, 0xfff8e38e, 0xffffffff},/* 162.2 MHz */
+	{176900, 0x02a329a3, 0x71c71c1f, 0xfff1c71c, 0xffffffff},/* 176.9 MHz */
+	{191700, 0x02dd31a3, 0xe38e383f, 0xffe38e38, 0xffffffff},/* 191.7 MHz */
+	{206400, 0x03153223, 0xc71c703f, 0xffc71c71, 0xffffffff},/* 206.4 MHz */
+	{221200, 0x034fba23, 0xc71c703f, 0xffc71c71, 0xffffffff},/* 221.2 MHz */
+	{235900, 0x03853a23, 0xe1e1e07f, 0xe1e1e1e1, 0xffffffe1},/* 235.9 MHz */
+	{250700, 0x03bf3aa3, 0xc3c3c07f, 0xc3c3c3c3, 0xffffffc3},/* 250.7 MHz */
+	{265400, 0x03f7c2a3, 0xc3c3c07f, 0xc3c3c3c3, 0xffffffc3},/* 265.4 MHz */
+	{280200, 0x0431c2a3, 0x878780ff, 0x87878787, 0xffffff87},/* 280.2 MHz */
 	{ 0, 0, 0, 0, 0 } /* last entry */
 };
 
 static void sa1100_update_dram_timings(int current_speed, int new_speed)
 {
-	sa1100_dram_regs_t *settings = sa1100_dram_settings;
+	struct sa1100_dram_regs *settings = sa1100_dram_settings;
 
 	/* find speed */
 	while (settings->speed != 0) {
-		if(new_speed == settings->speed)
+		if (new_speed == settings->speed)
 			break;
-		
+
 		settings++;
 	}
 
@@ -149,7 +148,7 @@ static void sa1100_update_dram_timings(i
 		/* We're going FASTER, so first relax the memory
 		 * timings before changing the core frequency
 		 */
-		
+
 		/* Half the memory access clock */
 		MDCNFG |= MDCNFG_CDB2;
 
@@ -187,7 +186,7 @@ static int sa1100_target(struct cpufreq_
 	struct cpufreq_freqs freqs;
 
 	new_ppcr = sa11x0_freq_to_ppcr(target_freq);
-	switch(relation){
+	switch (relation) {
 	case CPUFREQ_RELATION_L:
 		if (sa11x0_ppcr_to_freq(new_ppcr) > policy->max)
 			new_ppcr--;
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-sa1100/cpu-sa1110.c linux-libre-2.6.38-gnu1/arch/arm/mach-sa1100/cpu-sa1110.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-sa1100/cpu-sa1110.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-sa1100/cpu-sa1110.c	2011-03-14 21:20:32.000000000 -0400
@@ -16,28 +16,24 @@
  *
  * The SDRAM type can be passed on the command line as cpu_sa1110.sdram=type
  */
-#include <linux/moduleparam.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/cpufreq.h>
 #include <linux/delay.h>
 #include <linux/init.h>
-#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/moduleparam.h>
+#include <linux/types.h>
 
-#include <mach/hardware.h>
 #include <asm/cputype.h>
 #include <asm/mach-types.h>
-#include <asm/system.h>
+
+#include <mach/hardware.h>
 
 #include "generic.h"
 
 #undef DEBUG
 
-static struct cpufreq_driver sa1110_driver;
-
 struct sdram_params {
-	const char name[16];
+	const char name[20];
 	u_char  rows;		/* bits				 */
 	u_char  cas_latency;	/* cycles			 */
 	u_char  tck;		/* clock cycle time (ns)	 */
@@ -107,6 +103,15 @@ static struct sdram_params sdram_tbl[] _
 		.twr		= 8,
 		.refresh	= 64000,
 		.cas_latency	= 3,
+	}, {	/* Micron MT48LC8M16A2TG-75 */
+		.name		= "MT48LC8M16A2TG-75",
+		.rows		= 12,
+		.tck		= 8,
+		.trcd		= 20,
+		.trp		= 20,
+		.twr		= 8,
+		.refresh	= 64000,
+		.cas_latency	= 3,
 	},
 };
 
@@ -180,11 +185,13 @@ sdram_calculate_timing(struct sdram_info
 		sd->mdrefr |= MDREFR_K1DB2;
 
 	/* initial number of '1's in MDCAS + 1 */
-	set_mdcas(sd->mdcas, sd_khz >= 62000, ns_to_cycles(sdram->trcd, mem_khz));
+	set_mdcas(sd->mdcas, sd_khz >= 62000,
+		ns_to_cycles(sdram->trcd, mem_khz));
 
 #ifdef DEBUG
-	printk("MDCNFG: %08x MDREFR: %08x MDCAS0: %08x MDCAS1: %08x MDCAS2: %08x\n",
-		sd->mdcnfg, sd->mdrefr, sd->mdcas[0], sd->mdcas[1], sd->mdcas[2]);
+	printk(KERN_DEBUG "MDCNFG: %08x MDREFR: %08x MDCAS0: %08x MDCAS1: %08x MDCAS2: %08x\n",
+		sd->mdcnfg, sd->mdrefr, sd->mdcas[0], sd->mdcas[1],
+		sd->mdcas[2]);
 #endif
 }
 
@@ -213,7 +220,7 @@ sdram_update_refresh(u_int cpu_khz, stru
 
 #ifdef DEBUG
 	mdelay(250);
-	printk("new dri value = %d\n", dri);
+	printk(KERN_DEBUG "new dri value = %d\n", dri);
 #endif
 
 	sdram_set_refresh(dri);
@@ -232,7 +239,7 @@ static int sa1110_target(struct cpufreq_
 	unsigned long flags;
 	unsigned int ppcr, unused;
 
-	switch(relation){
+	switch (relation) {
 	case CPUFREQ_RELATION_L:
 		ppcr = sa11x0_freq_to_ppcr(target_freq);
 		if (sa11x0_ppcr_to_freq(ppcr) > policy->max)
@@ -280,11 +287,10 @@ static int sa1110_target(struct cpufreq_
 	 * We wait 20ms to be safe.
 	 */
 	sdram_set_refresh(2);
-	if (!irqs_disabled()) {
+	if (!irqs_disabled())
 		msleep(20);
-	} else {
+	else
 		mdelay(20);
-	}
 
 	/*
 	 * Reprogram the DRAM timings with interrupts disabled, and
@@ -295,7 +301,7 @@ static int sa1110_target(struct cpufreq_
 	local_irq_save(flags);
 	asm("mcr p15, 0, %0, c7, c10, 4" : : "r" (0));
 	udelay(10);
-	__asm__ __volatile__("					\n\
+	__asm__ __volatile__("\n\
 		b	2f					\n\
 		.align	5					\n\
 1:		str	%3, [%1, #0]		@ MDCNFG	\n\
@@ -336,7 +342,9 @@ static int __init sa1110_cpu_init(struct
 	return 0;
 }
 
-static struct cpufreq_driver sa1110_driver = {
+/* sa1110_driver needs __refdata because it must remain after init registers
+ * it with cpufreq_register_driver() */
+static struct cpufreq_driver sa1110_driver __refdata = {
 	.flags		= CPUFREQ_STICKY,
 	.verify		= sa11x0_verify_speed,
 	.target		= sa1110_target,
@@ -349,7 +357,8 @@ static struct sdram_params *sa1110_find_
 {
 	struct sdram_params *sdram;
 
-	for (sdram = sdram_tbl; sdram < sdram_tbl + ARRAY_SIZE(sdram_tbl); sdram++)
+	for (sdram = sdram_tbl; sdram < sdram_tbl + ARRAY_SIZE(sdram_tbl);
+	     sdram++)
 		if (strcmp(name, sdram->name) == 0)
 			return sdram;
 
@@ -369,14 +378,14 @@ static int __init sa1110_clk_init(void)
 	if (!name[0]) {
 		if (machine_is_assabet())
 			name = "TC59SM716-CL3";
-
 		if (machine_is_pt_system3())
 			name = "K4S641632D";
-
 		if (machine_is_h3100())
 			name = "KM416S4030CT";
 		if (machine_is_jornada720())
-		        name = "K4S281632B-1H";
+			name = "K4S281632B-1H";
+		if (machine_is_nanoengine())
+			name = "MT48LC8M16A2TG-75";
 	}
 
 	sdram = sa1110_find_sdram(name);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-sa1100/generic.c linux-libre-2.6.38-gnu1/arch/arm/mach-sa1100/generic.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-sa1100/generic.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-sa1100/generic.c	2011-03-14 21:20:32.000000000 -0400
@@ -16,14 +16,11 @@
 #include <linux/pm.h>
 #include <linux/cpufreq.h>
 #include <linux/ioport.h>
-#include <linux/sched.h>	/* just for sched_clock() - funny that */
 #include <linux/platform_device.h>
-#include <linux/cnt32_to_63.h>
 
 #include <asm/div64.h>
 #include <mach/hardware.h>
 #include <asm/system.h>
-#include <asm/pgtable.h>
 #include <asm/mach/map.h>
 #include <asm/mach/flash.h>
 #include <asm/irq.h>
@@ -110,27 +107,6 @@ unsigned int sa11x0_getspeed(unsigned in
 }
 
 /*
- * This is the SA11x0 sched_clock implementation.  This has
- * a resolution of 271ns, and a maximum value of 32025597s (370 days).
- *
- * The return value is guaranteed to be monotonic in that range as
- * long as there is always less than 582 seconds between successive
- * calls to this function.
- *
- *  ( * 1E9 / 3686400 => * 78125 / 288)
- */
-unsigned long long sched_clock(void)
-{
-	unsigned long long v = cnt32_to_63(OSCR);
-
-	/* the <<1 gets rid of the cnt_32_to_63 top bit saving on a bic insn */
-	v *= 78125<<1;
-	do_div(v, 288<<1);
-
-	return v;
-}
-
-/*
  * Default power-off for SA1100
  */
 static void sa1100_power_off(void)
@@ -163,10 +139,15 @@ static void sa11x0_register_device(struc
 
 static struct resource sa11x0udc_resources[] = {
 	[0] = {
-		.start	= 0x80000000,
-		.end	= 0x8000ffff,
+		.start	= __PREG(Ser0UDCCR),
+		.end	= __PREG(Ser0UDCCR) + 0xffff,
 		.flags	= IORESOURCE_MEM,
 	},
+	[1] = {
+		.start	= IRQ_Ser0UDC,
+		.end	= IRQ_Ser0UDC,
+		.flags	= IORESOURCE_IRQ,
+	},
 };
 
 static u64 sa11x0udc_dma_mask = 0xffffffffUL;
@@ -184,10 +165,15 @@ static struct platform_device sa11x0udc_
 
 static struct resource sa11x0uart1_resources[] = {
 	[0] = {
-		.start	= 0x80010000,
-		.end	= 0x8001ffff,
+		.start	= __PREG(Ser1UTCR0),
+		.end	= __PREG(Ser1UTCR0) + 0xffff,
 		.flags	= IORESOURCE_MEM,
 	},
+	[1] = {
+		.start	= IRQ_Ser1UART,
+		.end	= IRQ_Ser1UART,
+		.flags	= IORESOURCE_IRQ,
+	},
 };
 
 static struct platform_device sa11x0uart1_device = {
@@ -199,10 +185,15 @@ static struct platform_device sa11x0uart
 
 static struct resource sa11x0uart3_resources[] = {
 	[0] = {
-		.start	= 0x80050000,
-		.end	= 0x8005ffff,
+		.start	= __PREG(Ser3UTCR0),
+		.end	= __PREG(Ser3UTCR0) + 0xffff,
 		.flags	= IORESOURCE_MEM,
 	},
+	[1] = {
+		.start	= IRQ_Ser3UART,
+		.end	= IRQ_Ser3UART,
+		.flags	= IORESOURCE_IRQ,
+	},
 };
 
 static struct platform_device sa11x0uart3_device = {
@@ -214,10 +205,15 @@ static struct platform_device sa11x0uart
 
 static struct resource sa11x0mcp_resources[] = {
 	[0] = {
-		.start	= 0x80060000,
-		.end	= 0x8006ffff,
+		.start	= __PREG(Ser4MCCR0),
+		.end	= __PREG(Ser4MCCR0) + 0xffff,
 		.flags	= IORESOURCE_MEM,
 	},
+	[1] = {
+		.start	= IRQ_Ser4MCP,
+		.end	= IRQ_Ser4MCP,
+		.flags	= IORESOURCE_IRQ,
+	},
 };
 
 static u64 sa11x0mcp_dma_mask = 0xffffffffUL;
@@ -244,6 +240,11 @@ static struct resource sa11x0ssp_resourc
 		.end	= 0x8007ffff,
 		.flags	= IORESOURCE_MEM,
 	},
+	[1] = {
+		.start	= IRQ_Ser4SSP,
+		.end	= IRQ_Ser4SSP,
+		.flags	= IORESOURCE_IRQ,
+	},
 };
 
 static u64 sa11x0ssp_dma_mask = 0xffffffffUL;
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-sa1100/include/mach/hardware.h linux-libre-2.6.38-gnu1/arch/arm/mach-sa1100/include/mach/hardware.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-sa1100/include/mach/hardware.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-sa1100/include/mach/hardware.h	2011-03-14 21:20:32.000000000 -0400
@@ -76,4 +76,12 @@ static inline unsigned long get_clock_ti
 #include "SA-1101.h"
 #endif
 
+#if defined(CONFIG_ARCH_SA1100) && defined(CONFIG_PCI)
+#define PCIBIOS_MIN_IO		0
+#define PCIBIOS_MIN_MEM		0
+#define pcibios_assign_all_busses()	1
+#define HAVE_ARCH_PCI_SET_DMA_MASK	1
+#endif
+
+
 #endif  /* _ASM_ARCH_HARDWARE_H */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-sa1100/include/mach/nanoengine.h linux-libre-2.6.38-gnu1/arch/arm/mach-sa1100/include/mach/nanoengine.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-sa1100/include/mach/nanoengine.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-sa1100/include/mach/nanoengine.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,52 @@
+/*
+ * arch/arm/mach-sa1100/include/mach/nanoengine.h
+ *
+ * This file contains the hardware specific definitions for nanoEngine.
+ * Only include this file from SA1100-specific files.
+ *
+ * Copyright (C) 2010 Marcelo Roberto Jimenez <mroberto@cpti.cetuc.puc-rio.br>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+#ifndef __ASM_ARCH_NANOENGINE_H
+#define __ASM_ARCH_NANOENGINE_H
+
+#include <mach/irqs.h>
+
+#define GPIO_PC_READY0	GPIO_GPIO(11) /* ready for socket 0 (active high)*/
+#define GPIO_PC_READY1	GPIO_GPIO(12) /* ready for socket 1 (active high) */
+#define GPIO_PC_CD0	GPIO_GPIO(13) /* detect for socket 0 (active low) */
+#define GPIO_PC_CD1	GPIO_GPIO(14) /* detect for socket 1 (active low) */
+#define GPIO_PC_RESET0	GPIO_GPIO(15) /* reset socket 0 */
+#define GPIO_PC_RESET1	GPIO_GPIO(16) /* reset socket 1 */
+
+#define NANOENGINE_IRQ_GPIO_PCI		IRQ_GPIO0
+#define NANOENGINE_IRQ_GPIO_PC_READY0	IRQ_GPIO11
+#define NANOENGINE_IRQ_GPIO_PC_READY1	IRQ_GPIO12
+#define NANOENGINE_IRQ_GPIO_PC_CD0	IRQ_GPIO13
+#define NANOENGINE_IRQ_GPIO_PC_CD1	IRQ_GPIO14
+
+/*
+ * nanoEngine Memory Map:
+ *
+ * 0000.0000 - 003F.0000 -   4 MB Flash
+ * C000.0000 - C1FF.FFFF -  32 MB SDRAM
+ * 1860.0000 - 186F.FFFF -   1 MB Internal PCI Memory Read/Write
+ * 18A1.0000 - 18A1.FFFF -  64 KB Internal PCI Config Space
+ * 4000.0000 - 47FF.FFFF - 128 MB External Bus I/O - Multiplexed Mode
+ * 4800.0000 - 4FFF.FFFF - 128 MB External Bus I/O - Non-Multiplexed Mode
+ *
+ */
+
+#define NANO_PCI_MEM_RW_PHYS		0x18600000
+#define NANO_PCI_MEM_RW_VIRT		0xf1000000
+#define NANO_PCI_MEM_RW_SIZE		SZ_1M
+#define NANO_PCI_CONFIG_SPACE_PHYS	0x18A10000
+#define NANO_PCI_CONFIG_SPACE_VIRT	0xf2000000
+#define NANO_PCI_CONFIG_SPACE_SIZE	SZ_64K
+
+#endif
+
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-sa1100/irq.c linux-libre-2.6.38-gnu1/arch/arm/mach-sa1100/irq.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-sa1100/irq.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-sa1100/irq.c	2011-03-14 21:20:32.000000000 -0400
@@ -37,14 +37,14 @@ static int GPIO_IRQ_mask = (1 << 11) - 1
 #define GPIO_11_27_IRQ(i)	((i) - 21)
 #define GPIO11_27_MASK(irq)	(1 << GPIO_11_27_IRQ(irq))
 
-static int sa1100_gpio_type(unsigned int irq, unsigned int type)
+static int sa1100_gpio_type(struct irq_data *d, unsigned int type)
 {
 	unsigned int mask;
 
-	if (irq <= 10)
-		mask = 1 << irq;
+	if (d->irq <= 10)
+		mask = 1 << d->irq;
 	else
-		mask = GPIO11_27_MASK(irq);
+		mask = GPIO11_27_MASK(d->irq);
 
 	if (type == IRQ_TYPE_PROBE) {
 		if ((GPIO_IRQ_rising_edge | GPIO_IRQ_falling_edge) & mask)
@@ -70,37 +70,37 @@ static int sa1100_gpio_type(unsigned int
 /*
  * GPIO IRQs must be acknowledged.  This is for IRQs from 0 to 10.
  */
-static void sa1100_low_gpio_ack(unsigned int irq)
+static void sa1100_low_gpio_ack(struct irq_data *d)
 {
-	GEDR = (1 << irq);
+	GEDR = (1 << d->irq);
 }
 
-static void sa1100_low_gpio_mask(unsigned int irq)
+static void sa1100_low_gpio_mask(struct irq_data *d)
 {
-	ICMR &= ~(1 << irq);
+	ICMR &= ~(1 << d->irq);
 }
 
-static void sa1100_low_gpio_unmask(unsigned int irq)
+static void sa1100_low_gpio_unmask(struct irq_data *d)
 {
-	ICMR |= 1 << irq;
+	ICMR |= 1 << d->irq;
 }
 
-static int sa1100_low_gpio_wake(unsigned int irq, unsigned int on)
+static int sa1100_low_gpio_wake(struct irq_data *d, unsigned int on)
 {
 	if (on)
-		PWER |= 1 << irq;
+		PWER |= 1 << d->irq;
 	else
-		PWER &= ~(1 << irq);
+		PWER &= ~(1 << d->irq);
 	return 0;
 }
 
 static struct irq_chip sa1100_low_gpio_chip = {
 	.name		= "GPIO-l",
-	.ack		= sa1100_low_gpio_ack,
-	.mask		= sa1100_low_gpio_mask,
-	.unmask		= sa1100_low_gpio_unmask,
-	.set_type	= sa1100_gpio_type,
-	.set_wake	= sa1100_low_gpio_wake,
+	.irq_ack	= sa1100_low_gpio_ack,
+	.irq_mask	= sa1100_low_gpio_mask,
+	.irq_unmask	= sa1100_low_gpio_unmask,
+	.irq_set_type	= sa1100_gpio_type,
+	.irq_set_wake	= sa1100_low_gpio_wake,
 };
 
 /*
@@ -139,16 +139,16 @@ sa1100_high_gpio_handler(unsigned int ir
  * In addition, the IRQs are all collected up into one bit in the
  * interrupt controller registers.
  */
-static void sa1100_high_gpio_ack(unsigned int irq)
+static void sa1100_high_gpio_ack(struct irq_data *d)
 {
-	unsigned int mask = GPIO11_27_MASK(irq);
+	unsigned int mask = GPIO11_27_MASK(d->irq);
 
 	GEDR = mask;
 }
 
-static void sa1100_high_gpio_mask(unsigned int irq)
+static void sa1100_high_gpio_mask(struct irq_data *d)
 {
-	unsigned int mask = GPIO11_27_MASK(irq);
+	unsigned int mask = GPIO11_27_MASK(d->irq);
 
 	GPIO_IRQ_mask &= ~mask;
 
@@ -156,9 +156,9 @@ static void sa1100_high_gpio_mask(unsign
 	GFER &= ~mask;
 }
 
-static void sa1100_high_gpio_unmask(unsigned int irq)
+static void sa1100_high_gpio_unmask(struct irq_data *d)
 {
-	unsigned int mask = GPIO11_27_MASK(irq);
+	unsigned int mask = GPIO11_27_MASK(d->irq);
 
 	GPIO_IRQ_mask |= mask;
 
@@ -166,44 +166,44 @@ static void sa1100_high_gpio_unmask(unsi
 	GFER = GPIO_IRQ_falling_edge & GPIO_IRQ_mask;
 }
 
-static int sa1100_high_gpio_wake(unsigned int irq, unsigned int on)
+static int sa1100_high_gpio_wake(struct irq_data *d, unsigned int on)
 {
 	if (on)
-		PWER |= GPIO11_27_MASK(irq);
+		PWER |= GPIO11_27_MASK(d->irq);
 	else
-		PWER &= ~GPIO11_27_MASK(irq);
+		PWER &= ~GPIO11_27_MASK(d->irq);
 	return 0;
 }
 
 static struct irq_chip sa1100_high_gpio_chip = {
 	.name		= "GPIO-h",
-	.ack		= sa1100_high_gpio_ack,
-	.mask		= sa1100_high_gpio_mask,
-	.unmask		= sa1100_high_gpio_unmask,
-	.set_type	= sa1100_gpio_type,
-	.set_wake	= sa1100_high_gpio_wake,
+	.irq_ack	= sa1100_high_gpio_ack,
+	.irq_mask	= sa1100_high_gpio_mask,
+	.irq_unmask	= sa1100_high_gpio_unmask,
+	.irq_set_type	= sa1100_gpio_type,
+	.irq_set_wake	= sa1100_high_gpio_wake,
 };
 
 /*
  * We don't need to ACK IRQs on the SA1100 unless they're GPIOs
  * this is for internal IRQs i.e. from 11 to 31.
  */
-static void sa1100_mask_irq(unsigned int irq)
+static void sa1100_mask_irq(struct irq_data *d)
 {
-	ICMR &= ~(1 << irq);
+	ICMR &= ~(1 << d->irq);
 }
 
-static void sa1100_unmask_irq(unsigned int irq)
+static void sa1100_unmask_irq(struct irq_data *d)
 {
-	ICMR |= (1 << irq);
+	ICMR |= (1 << d->irq);
 }
 
 /*
  * Apart form GPIOs, only the RTC alarm can be a wakeup event.
  */
-static int sa1100_set_wake(unsigned int irq, unsigned int on)
+static int sa1100_set_wake(struct irq_data *d, unsigned int on)
 {
-	if (irq == IRQ_RTCAlrm) {
+	if (d->irq == IRQ_RTCAlrm) {
 		if (on)
 			PWER |= PWER_RTC;
 		else
@@ -215,10 +215,10 @@ static int sa1100_set_wake(unsigned int
 
 static struct irq_chip sa1100_normal_chip = {
 	.name		= "SC",
-	.ack		= sa1100_mask_irq,
-	.mask		= sa1100_mask_irq,
-	.unmask		= sa1100_unmask_irq,
-	.set_wake	= sa1100_set_wake,
+	.irq_ack	= sa1100_mask_irq,
+	.irq_mask	= sa1100_mask_irq,
+	.irq_unmask	= sa1100_unmask_irq,
+	.irq_set_wake	= sa1100_set_wake,
 };
 
 static struct resource irq_resource = {
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-sa1100/Kconfig linux-libre-2.6.38-gnu1/arch/arm/mach-sa1100/Kconfig
--- linux-libre-2.6.37-gnu1/arch/arm/mach-sa1100/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-sa1100/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -118,6 +118,16 @@ config SA1100_LART
 	  (also known as the LART).  See <http://www.lartmaker.nl/> for
 	  information on the LART.
 
+config SA1100_NANOENGINE
+	bool "nanoEngine"
+	select CPU_FREQ_SA1110
+	select PCI
+	select PCI_NANOENGINE
+	help
+	  Say Y here if you are using the Bright Star Engineering nanoEngine.
+	  See <http://www.brightstareng.com/arm/nanoeng.htm> for information
+	  on the BSE nanoEngine.
+
 config SA1100_PLEB
 	bool "PLEB"
 	select CPU_FREQ_SA1100
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-sa1100/Makefile linux-libre-2.6.38-gnu1/arch/arm/mach-sa1100/Makefile
--- linux-libre-2.6.37-gnu1/arch/arm/mach-sa1100/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-sa1100/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -37,6 +37,9 @@ obj-$(CONFIG_SA1100_JORNADA720_SSP)	+= j
 obj-$(CONFIG_SA1100_LART)		+= lart.o
 led-$(CONFIG_SA1100_LART)		+= leds-lart.o
 
+obj-$(CONFIG_SA1100_NANOENGINE)		+= nanoengine.o
+obj-$(CONFIG_PCI_NANOENGINE)		+= pci-nanoengine.o
+
 obj-$(CONFIG_SA1100_PLEB)		+= pleb.o
 
 obj-$(CONFIG_SA1100_SHANNON)		+= shannon.o
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-sa1100/nanoengine.c linux-libre-2.6.38-gnu1/arch/arm/mach-sa1100/nanoengine.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-sa1100/nanoengine.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-sa1100/nanoengine.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,119 @@
+/*
+ * linux/arch/arm/mach-sa1100/nanoengine.c
+ *
+ * Bright Star Engineering's nanoEngine board init code.
+ *
+ * Copyright (C) 2010 Marcelo Roberto Jimenez <mroberto@cpti.cetuc.puc-rio.br>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/root_dev.h>
+
+#include <asm/mach-types.h>
+#include <asm/setup.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/flash.h>
+#include <asm/mach/map.h>
+#include <asm/mach/serial_sa1100.h>
+
+#include <mach/hardware.h>
+#include <mach/nanoengine.h>
+
+#include "generic.h"
+
+/* Flash bank 0 */
+static struct mtd_partition nanoengine_partitions[] = {
+	{
+		.name	= "nanoEngine boot firmware and parameter table",
+		.size		= 0x00010000,  /* 32K */
+		.offset		= 0,
+		.mask_flags	= MTD_WRITEABLE,
+	}, {
+		.name		= "kernel/initrd reserved",
+		.size		= 0x002f0000,
+		.offset		= 0x00010000,
+		.mask_flags	= MTD_WRITEABLE,
+	}, {
+		.name		= "experimental filesystem allocation",
+		.size		= 0x00100000,
+		.offset		= 0x00300000,
+		.mask_flags	= MTD_WRITEABLE,
+	}
+};
+
+static struct flash_platform_data nanoengine_flash_data = {
+	.map_name	= "jedec_probe",
+	.parts		= nanoengine_partitions,
+	.nr_parts	= ARRAY_SIZE(nanoengine_partitions),
+};
+
+static struct resource nanoengine_flash_resources[] = {
+	{
+		.start	= SA1100_CS0_PHYS,
+		.end	= SA1100_CS0_PHYS + SZ_32M - 1,
+		.flags	= IORESOURCE_MEM,
+	}, {
+		.start	= SA1100_CS1_PHYS,
+		.end	= SA1100_CS1_PHYS + SZ_32M - 1,
+		.flags	= IORESOURCE_MEM,
+	}
+};
+
+static struct map_desc nanoengine_io_desc[] __initdata = {
+	{
+		/* System Registers */
+		.virtual	= 0xf0000000,
+		.pfn		= __phys_to_pfn(0x10000000),
+		.length		= 0x00100000,
+		.type		= MT_DEVICE
+	}, {
+		/* Internal PCI Memory Read/Write */
+		.virtual	= NANO_PCI_MEM_RW_VIRT,
+		.pfn		= __phys_to_pfn(NANO_PCI_MEM_RW_PHYS),
+		.length		= NANO_PCI_MEM_RW_SIZE,
+		.type		= MT_DEVICE
+	}, {
+		/* Internal PCI Config Space */
+		.virtual	= NANO_PCI_CONFIG_SPACE_VIRT,
+		.pfn		= __phys_to_pfn(NANO_PCI_CONFIG_SPACE_PHYS),
+		.length		= NANO_PCI_CONFIG_SPACE_SIZE,
+		.type		= MT_DEVICE
+	}
+};
+
+static void __init nanoengine_map_io(void)
+{
+	sa1100_map_io();
+	iotable_init(nanoengine_io_desc, ARRAY_SIZE(nanoengine_io_desc));
+
+	sa1100_register_uart(0, 1);
+	sa1100_register_uart(1, 2);
+	sa1100_register_uart(2, 3);
+	Ser1SDCR0 |= SDCR0_UART;
+	/* disable IRDA -- UART2 is used as a normal serial port */
+	Ser2UTCR4 = 0;
+	Ser2HSCR0 = 0;
+}
+
+static void __init nanoengine_init(void)
+{
+	sa11x0_register_mtd(&nanoengine_flash_data, nanoengine_flash_resources,
+		ARRAY_SIZE(nanoengine_flash_resources));
+}
+
+MACHINE_START(NANOENGINE, "BSE nanoEngine")
+	.boot_params	= 0xc0000000,
+	.map_io		= nanoengine_map_io,
+	.init_irq	= sa1100_init_irq,
+	.timer		= &sa1100_timer,
+	.init_machine	= nanoengine_init,
+MACHINE_END
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-sa1100/neponset.c linux-libre-2.6.38-gnu1/arch/arm/mach-sa1100/neponset.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-sa1100/neponset.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-sa1100/neponset.c	2011-03-14 21:20:32.000000000 -0400
@@ -35,7 +35,7 @@ neponset_irq_handler(unsigned int irq, s
 		/*
 		 * Acknowledge the parent IRQ.
 		 */
-		desc->chip->ack(irq);
+		desc->irq_data.chip->irq_ack(&desc->irq_data);
 
 		/*
 		 * Read the interrupt reason register.  Let's have all
@@ -53,7 +53,7 @@ neponset_irq_handler(unsigned int irq, s
 		 * recheck the register for any pending IRQs.
 		 */
 		if (irr & (IRR_ETHERNET | IRR_USAR)) {
-			desc->chip->mask(irq);
+			desc->irq_data.chip->irq_mask(&desc->irq_data);
 
 			/*
 			 * Ack the interrupt now to prevent re-entering
@@ -61,7 +61,7 @@ neponset_irq_handler(unsigned int irq, s
 			 * since we'll check the IRR register prior to
 			 * leaving.
 			 */
-			desc->chip->ack(irq);
+			desc->irq_data.chip->irq_ack(&desc->irq_data);
 
 			if (irr & IRR_ETHERNET) {
 				generic_handle_irq(IRQ_NEPONSET_SMC9196);
@@ -71,7 +71,7 @@ neponset_irq_handler(unsigned int irq, s
 				generic_handle_irq(IRQ_NEPONSET_USAR);
 			}
 
-			desc->chip->unmask(irq);
+			desc->irq_data.chip->irq_unmask(&desc->irq_data);
 		}
 
 		if (irr & IRR_SA1111) {
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-sa1100/pci-nanoengine.c linux-libre-2.6.38-gnu1/arch/arm/mach-sa1100/pci-nanoengine.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-sa1100/pci-nanoengine.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-sa1100/pci-nanoengine.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,284 @@
+/*
+ * linux/arch/arm/mach-sa1100/pci-nanoengine.c
+ *
+ * PCI functions for BSE nanoEngine PCI
+ *
+ * Copyright (C) 2010 Marcelo Roberto Jimenez <mroberto@cpti.cetuc.puc-rio.br>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <linux/kernel.h>
+#include <linux/irq.h>
+#include <linux/pci.h>
+#include <linux/spinlock.h>
+
+#include <asm/mach/pci.h>
+#include <asm/mach-types.h>
+
+#include <mach/nanoengine.h>
+
+static DEFINE_SPINLOCK(nano_lock);
+
+static int nanoengine_get_pci_address(struct pci_bus *bus,
+	unsigned int devfn, int where, unsigned long *address)
+{
+	int ret = PCIBIOS_DEVICE_NOT_FOUND;
+	unsigned int busnr = bus->number;
+
+	*address = NANO_PCI_CONFIG_SPACE_VIRT +
+		((bus->number << 16) | (devfn << 8) | (where & ~3));
+
+	ret = (busnr > 255 || devfn > 255 || where > 255) ?
+		PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL;
+
+	return ret;
+}
+
+static int nanoengine_read_config(struct pci_bus *bus, unsigned int devfn, int where,
+	int size, u32 *val)
+{
+	int ret;
+	unsigned long address;
+	unsigned long flags;
+	u32 v;
+
+	/* nanoEngine PCI bridge does not return -1 for a non-existing
+	 * device. We must fake the answer. We know that the only valid
+	 * device is device zero at bus 0, which is the network chip. */
+	if (bus->number != 0 || (devfn >> 3) != 0) {
+		v = -1;
+		nanoengine_get_pci_address(bus, devfn, where, &address);
+		goto exit_function;
+	}
+
+	spin_lock_irqsave(&nano_lock, flags);
+
+	ret = nanoengine_get_pci_address(bus, devfn, where, &address);
+	if (ret != PCIBIOS_SUCCESSFUL)
+		return ret;
+	v = __raw_readl(address);
+
+	spin_unlock_irqrestore(&nano_lock, flags);
+
+	v >>= ((where & 3) * 8);
+	v &= (unsigned long)(-1) >> ((4 - size) * 8);
+
+exit_function:
+	*val = v;
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int nanoengine_write_config(struct pci_bus *bus, unsigned int devfn, int where,
+	int size, u32 val)
+{
+	int ret;
+	unsigned long address;
+	unsigned long flags;
+	unsigned shift;
+	u32 v;
+
+	shift = (where & 3) * 8;
+
+	spin_lock_irqsave(&nano_lock, flags);
+
+	ret = nanoengine_get_pci_address(bus, devfn, where, &address);
+	if (ret != PCIBIOS_SUCCESSFUL)
+		return ret;
+	v = __raw_readl(address);
+	switch (size) {
+	case 1:
+		v &= ~(0xFF << shift);
+		v |= val << shift;
+		break;
+	case 2:
+		v &= ~(0xFFFF << shift);
+		v |= val << shift;
+		break;
+	case 4:
+		v = val;
+		break;
+	}
+	__raw_writel(v, address);
+
+	spin_unlock_irqrestore(&nano_lock, flags);
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static struct pci_ops pci_nano_ops = {
+	.read	= nanoengine_read_config,
+	.write	= nanoengine_write_config,
+};
+
+static int __init pci_nanoengine_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+	return NANOENGINE_IRQ_GPIO_PCI;
+}
+
+struct pci_bus * __init pci_nanoengine_scan_bus(int nr, struct pci_sys_data *sys)
+{
+	return pci_scan_bus(sys->busnr, &pci_nano_ops, sys);
+}
+
+static struct resource pci_io_ports = {
+	.name	= "PCI IO",
+	.start	= 0x400,
+	.end	= 0x7FF,
+	.flags	= IORESOURCE_IO,
+};
+
+static struct resource pci_non_prefetchable_memory = {
+	.name	= "PCI non-prefetchable",
+	.start	= NANO_PCI_MEM_RW_PHYS,
+	/* nanoEngine documentation says there is a 1 Megabyte window here,
+	 * but PCI reports just 128 + 8 kbytes. */
+	.end	= NANO_PCI_MEM_RW_PHYS + NANO_PCI_MEM_RW_SIZE - 1,
+/*	.end	= NANO_PCI_MEM_RW_PHYS + SZ_128K + SZ_8K - 1,*/
+	.flags	= IORESOURCE_MEM,
+};
+
+/*
+ * nanoEngine PCI reports 1 Megabyte of prefetchable memory, but it
+ * overlaps with previously defined memory.
+ *
+ * Here is what happens:
+ *
+# dmesg
+...
+pci 0000:00:00.0: [8086:1209] type 0 class 0x000200
+pci 0000:00:00.0: reg 10: [mem 0x00021000-0x00021fff]
+pci 0000:00:00.0: reg 14: [io  0x0000-0x003f]
+pci 0000:00:00.0: reg 18: [mem 0x00000000-0x0001ffff]
+pci 0000:00:00.0: reg 30: [mem 0x00000000-0x000fffff pref]
+pci 0000:00:00.0: supports D1 D2
+pci 0000:00:00.0: PME# supported from D0 D1 D2 D3hot
+pci 0000:00:00.0: PME# disabled
+PCI: bus0: Fast back to back transfers enabled
+pci 0000:00:00.0: BAR 6: can't assign mem pref (size 0x100000)
+pci 0000:00:00.0: BAR 2: assigned [mem 0x18600000-0x1861ffff]
+pci 0000:00:00.0: BAR 2: set to [mem 0x18600000-0x1861ffff] (PCI address [0x0-0x1ffff])
+pci 0000:00:00.0: BAR 0: assigned [mem 0x18620000-0x18620fff]
+pci 0000:00:00.0: BAR 0: set to [mem 0x18620000-0x18620fff] (PCI address [0x20000-0x20fff])
+pci 0000:00:00.0: BAR 1: assigned [io  0x0400-0x043f]
+pci 0000:00:00.0: BAR 1: set to [io  0x0400-0x043f] (PCI address [0x0-0x3f])
+ *
+ * On the other hand, if we do not request the prefetchable memory resource,
+ * linux will alloc it first and the two non-prefetchable memory areas that
+ * are our real interest will not be mapped. So we choose to map it to an
+ * unused area. It gets recognized as expansion ROM, but becomes disabled.
+ *
+ * Here is what happens then:
+ *
+# dmesg
+...
+pci 0000:00:00.0: [8086:1209] type 0 class 0x000200
+pci 0000:00:00.0: reg 10: [mem 0x00021000-0x00021fff]
+pci 0000:00:00.0: reg 14: [io  0x0000-0x003f]
+pci 0000:00:00.0: reg 18: [mem 0x00000000-0x0001ffff]
+pci 0000:00:00.0: reg 30: [mem 0x00000000-0x000fffff pref]
+pci 0000:00:00.0: supports D1 D2
+pci 0000:00:00.0: PME# supported from D0 D1 D2 D3hot
+pci 0000:00:00.0: PME# disabled
+PCI: bus0: Fast back to back transfers enabled
+pci 0000:00:00.0: BAR 6: assigned [mem 0x78000000-0x780fffff pref]
+pci 0000:00:00.0: BAR 2: assigned [mem 0x18600000-0x1861ffff]
+pci 0000:00:00.0: BAR 2: set to [mem 0x18600000-0x1861ffff] (PCI address [0x0-0x1ffff])
+pci 0000:00:00.0: BAR 0: assigned [mem 0x18620000-0x18620fff]
+pci 0000:00:00.0: BAR 0: set to [mem 0x18620000-0x18620fff] (PCI address [0x20000-0x20fff])
+pci 0000:00:00.0: BAR 1: assigned [io  0x0400-0x043f]
+pci 0000:00:00.0: BAR 1: set to [io  0x0400-0x043f] (PCI address [0x0-0x3f])
+
+# lspci -vv -s 0000:00:00.0
+00:00.0 Class 0200: Device 8086:1209 (rev 09)
+        Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr+ Stepping- SERR+ FastB2B- DisINTx-
+        Status: Cap+ 66MHz- UDF- FastB2B+ ParErr- DEVSEL=medium >TAbort- <TAbort- <MAbort- >SERR+ <PERR+ INTx-
+        Latency: 0 (2000ns min, 14000ns max), Cache Line Size: 32 bytes
+        Interrupt: pin A routed to IRQ 0
+        Region 0: Memory at 18620000 (32-bit, non-prefetchable) [size=4K]
+        Region 1: I/O ports at 0400 [size=64]
+        Region 2: [virtual] Memory at 18600000 (32-bit, non-prefetchable) [size=128K]
+        [virtual] Expansion ROM at 78000000 [disabled] [size=1M]
+        Capabilities: [dc] Power Management version 2
+                Flags: PMEClk- DSI+ D1+ D2+ AuxCurrent=0mA PME(D0+,D1+,D2+,D3hot+,D3cold-)
+                Status: D0 NoSoftRst- PME-Enable- DSel=0 DScale=2 PME-
+        Kernel driver in use: e100
+        Kernel modules: e100
+ *
+ */
+static struct resource pci_prefetchable_memory = {
+	.name	= "PCI prefetchable",
+	.start	= 0x78000000,
+	.end	= 0x78000000 + NANO_PCI_MEM_RW_SIZE - 1,
+	.flags	= IORESOURCE_MEM  | IORESOURCE_PREFETCH,
+};
+
+static int __init pci_nanoengine_setup_resources(struct resource **resource)
+{
+	if (request_resource(&ioport_resource, &pci_io_ports)) {
+		printk(KERN_ERR "PCI: unable to allocate io port region\n");
+		return -EBUSY;
+	}
+	if (request_resource(&iomem_resource, &pci_non_prefetchable_memory)) {
+		release_resource(&pci_io_ports);
+		printk(KERN_ERR "PCI: unable to allocate non prefetchable\n");
+		return -EBUSY;
+	}
+	if (request_resource(&iomem_resource, &pci_prefetchable_memory)) {
+		release_resource(&pci_io_ports);
+		release_resource(&pci_non_prefetchable_memory);
+		printk(KERN_ERR "PCI: unable to allocate prefetchable\n");
+		return -EBUSY;
+	}
+	resource[0] = &pci_io_ports;
+	resource[1] = &pci_non_prefetchable_memory;
+	resource[2] = &pci_prefetchable_memory;
+
+	return 1;
+}
+
+int __init pci_nanoengine_setup(int nr, struct pci_sys_data *sys)
+{
+	int ret = 0;
+
+	if (nr == 0) {
+		sys->mem_offset = NANO_PCI_MEM_RW_PHYS;
+		sys->io_offset = 0x400;
+		ret = pci_nanoengine_setup_resources(sys->resource);
+		/* Enable alternate memory bus master mode, see
+		 * "Intel StrongARM SA1110 Developer's Manual",
+		 * section 10.8, "Alternate Memory Bus Master Mode". */
+		GPDR = (GPDR & ~GPIO_MBREQ) | GPIO_MBGNT;
+		GAFR |= GPIO_MBGNT | GPIO_MBREQ;
+		TUCR |= TUCR_MBGPIO;
+	}
+
+	return ret;
+}
+
+static struct hw_pci nanoengine_pci __initdata = {
+	.map_irq		= pci_nanoengine_map_irq,
+	.nr_controllers		= 1,
+	.scan			= pci_nanoengine_scan_bus,
+	.setup			= pci_nanoengine_setup,
+};
+
+static int __init nanoengine_pci_init(void)
+{
+	if (machine_is_nanoengine())
+		pci_common_init(&nanoengine_pci);
+	return 0;
+}
+
+subsys_initcall(nanoengine_pci_init);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-sa1100/pm.c linux-libre-2.6.38-gnu1/arch/arm/mach-sa1100/pm.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-sa1100/pm.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-sa1100/pm.c	2011-03-14 21:20:32.000000000 -0400
@@ -120,7 +120,7 @@ unsigned long sleep_phys_sp(void *sp)
 	return virt_to_phys(sp);
 }
 
-static struct platform_suspend_ops sa11x0_pm_ops = {
+static const struct platform_suspend_ops sa11x0_pm_ops = {
 	.enter		= sa11x0_pm_enter,
 	.valid		= suspend_valid_only_mem,
 };
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-sa1100/simpad.c linux-libre-2.6.38-gnu1/arch/arm/mach-sa1100/simpad.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-sa1100/simpad.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-sa1100/simpad.c	2011-03-14 21:20:32.000000000 -0400
@@ -166,9 +166,6 @@ static void __init simpad_map_io(void)
 	PCFR = 0;
 	PSDR = 0;
 
-	sa11x0_register_mtd(&simpad_flash_data, simpad_flash_resources,
-			      ARRAY_SIZE(simpad_flash_resources));
-	sa11x0_register_mcp(&simpad_mcp_data);
 }
 
 static void simpad_power_off(void)
@@ -216,6 +213,10 @@ static int __init simpad_init(void)
 
 	pm_power_off = simpad_power_off;
 
+	sa11x0_register_mtd(&simpad_flash_data, simpad_flash_resources,
+			      ARRAY_SIZE(simpad_flash_resources));
+	sa11x0_register_mcp(&simpad_mcp_data);
+
 	ret = platform_add_devices(devices, ARRAY_SIZE(devices));
 	if(ret)
 		printk(KERN_WARNING "simpad: Unable to register mq200 framebuffer device");
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-sa1100/time.c linux-libre-2.6.38-gnu1/arch/arm/mach-sa1100/time.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-sa1100/time.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-sa1100/time.c	2011-03-14 21:20:32.000000000 -0400
@@ -12,12 +12,39 @@
 #include <linux/errno.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
+#include <linux/sched.h>	/* just for sched_clock() - funny that */
 #include <linux/timex.h>
 #include <linux/clockchips.h>
 
 #include <asm/mach/time.h>
+#include <asm/sched_clock.h>
 #include <mach/hardware.h>
 
+/*
+ * This is the SA11x0 sched_clock implementation.
+ */
+static DEFINE_CLOCK_DATA(cd);
+
+/*
+ * Constants generated by clocks_calc_mult_shift(m, s, 3.6864MHz,
+ * NSEC_PER_SEC, 60).
+ * This gives a resolution of about 271ns and a wrap period of about 19min.
+ */
+#define SC_MULT		2275555556u
+#define SC_SHIFT	23
+
+unsigned long long notrace sched_clock(void)
+{
+	u32 cyc = OSCR;
+	return cyc_to_fixed_sched_clock(&cd, cyc, (u32)~0, SC_MULT, SC_SHIFT);
+}
+
+static void notrace sa1100_update_sched_clock(void)
+{
+	u32 cyc = OSCR;
+	update_sched_clock(&cd, cyc, (u32)~0);
+}
+
 #define MIN_OSCR_DELTA 2
 
 static irqreturn_t sa1100_ost0_interrupt(int irq, void *dev_id)
@@ -81,7 +108,6 @@ static struct clocksource cksrc_sa1100_o
 	.rating		= 200,
 	.read		= sa1100_read_oscr,
 	.mask		= CLOCKSOURCE_MASK(32),
-	.shift		= 20,
 	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
@@ -97,6 +123,9 @@ static void __init sa1100_timer_init(voi
 	OIER = 0;		/* disable any timer interrupts */
 	OSSR = 0xf;		/* clear status on all timers */
 
+	init_fixed_sched_clock(&cd, sa1100_update_sched_clock, 32,
+			       3686400, SC_MULT, SC_SHIFT);
+
 	ckevt_sa1100_osmr0.mult =
 		div_sc(3686400, NSEC_PER_SEC, ckevt_sa1100_osmr0.shift);
 	ckevt_sa1100_osmr0.max_delta_ns =
@@ -105,12 +134,9 @@ static void __init sa1100_timer_init(voi
 		clockevent_delta2ns(MIN_OSCR_DELTA * 2, &ckevt_sa1100_osmr0) + 1;
 	ckevt_sa1100_osmr0.cpumask = cpumask_of(0);
 
-	cksrc_sa1100_oscr.mult =
-		clocksource_hz2mult(CLOCK_TICK_RATE, cksrc_sa1100_oscr.shift);
-
 	setup_irq(IRQ_OST0, &sa1100_timer_irq);
 
-	clocksource_register(&cksrc_sa1100_oscr);
+	clocksource_register_hz(&cksrc_sa1100_oscr, CLOCK_TICK_RATE);
 	clockevents_register_device(&ckevt_sa1100_osmr0);
 }
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-shark/irq.c linux-libre-2.6.38-gnu1/arch/arm/mach-shark/irq.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-shark/irq.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-shark/irq.c	2011-03-14 21:20:32.000000000 -0400
@@ -30,35 +30,35 @@ static unsigned char cached_irq_mask[2]
  * These have to be protected by the irq controller spinlock
  * before being called.
  */
-static void shark_disable_8259A_irq(unsigned int irq)
+static void shark_disable_8259A_irq(struct irq_data *d)
 {
 	unsigned int mask;
-	if (irq<8) {
-	  mask = 1 << irq;
+	if (d->irq<8) {
+	  mask = 1 << d->irq;
 	  cached_irq_mask[0] |= mask;
 	  outb(cached_irq_mask[1],0xA1);
 	} else {
-	  mask = 1 << (irq-8);
+	  mask = 1 << (d->irq-8);
 	  cached_irq_mask[1] |= mask;
 	  outb(cached_irq_mask[0],0x21);
 	}
 }
 
-static void shark_enable_8259A_irq(unsigned int irq)
+static void shark_enable_8259A_irq(struct irq_data *d)
 {
 	unsigned int mask;
-	if (irq<8) {
-	  mask = ~(1 << irq);
+	if (d->irq<8) {
+	  mask = ~(1 << d->irq);
 	  cached_irq_mask[0] &= mask;
 	  outb(cached_irq_mask[0],0x21);
 	} else {
-	  mask = ~(1 << (irq-8));
+	  mask = ~(1 << (d->irq-8));
 	  cached_irq_mask[1] &= mask;
 	  outb(cached_irq_mask[1],0xA1);
 	}
 }
 
-static void shark_ack_8259A_irq(unsigned int irq){}
+static void shark_ack_8259A_irq(struct irq_data *d){}
 
 static irqreturn_t bogus_int(int irq, void *dev_id)
 {
@@ -69,10 +69,10 @@ static irqreturn_t bogus_int(int irq, vo
 static struct irqaction cascade;
 
 static struct irq_chip fb_chip = {
-	.name	= "XT-PIC",
-	.ack	= shark_ack_8259A_irq,
-	.mask	= shark_disable_8259A_irq,
-	.unmask = shark_enable_8259A_irq,
+	.name		= "XT-PIC",
+	.irq_ack	= shark_ack_8259A_irq,
+	.irq_mask	= shark_disable_8259A_irq,
+	.irq_unmask	= shark_enable_8259A_irq,
 };
 
 void __init shark_init_irq(void)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-shmobile/board-ag5evm.c linux-libre-2.6.38-gnu1/arch/arm/mach-shmobile/board-ag5evm.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-shmobile/board-ag5evm.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-shmobile/board-ag5evm.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,492 @@
+/*
+ * arch/arm/mach-shmobile/board-ag5evm.c
+ *
+ * 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/dma-mapping.h>
+#include <linux/serial_sci.h>
+#include <linux/smsc911x.h>
+#include <linux/gpio.h>
+#include <linux/input.h>
+#include <linux/input/sh_keysc.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/sh_mmcif.h>
+#include <linux/sh_clk.h>
+#include <video/sh_mobile_lcdc.h>
+#include <video/sh_mipi_dsi.h>
+#include <sound/sh_fsi.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>
+
+static struct resource smsc9220_resources[] = {
+	[0] = {
+		.start		= 0x14000000,
+		.end		= 0x14000000 + SZ_64K - 1,
+		.flags		= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start		= gic_spi(33), /* PINT1 */
+		.flags		= IORESOURCE_IRQ,
+	},
+};
+
+static struct smsc911x_platform_config smsc9220_platdata = {
+	.flags		= SMSC911X_USE_32BIT | SMSC911X_SAVE_MAC_ADDRESS,
+	.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),
+};
+
+static struct sh_keysc_info keysc_platdata = {
+	.mode		= SH_KEYSC_MODE_6,
+	.scan_timing	= 3,
+	.delay		= 100,
+	.keycodes	= {
+		KEY_A, KEY_B, KEY_C, KEY_D, KEY_E, KEY_F, KEY_G,
+		KEY_H, KEY_I, KEY_J, KEY_K, KEY_L, KEY_M, KEY_N,
+		KEY_O, KEY_P, KEY_Q, KEY_R, KEY_S, KEY_T, KEY_U,
+		KEY_V, KEY_W, KEY_X, KEY_Y, KEY_Z, KEY_HOME, KEY_SLEEP,
+		KEY_SPACE, KEY_9, KEY_6, KEY_3, KEY_WAKEUP, KEY_RIGHT, \
+		KEY_COFFEE,
+		KEY_0, KEY_8, KEY_5, KEY_2, KEY_DOWN, KEY_ENTER, KEY_UP,
+		KEY_KPASTERISK, KEY_7, KEY_4, KEY_1, KEY_STOP, KEY_LEFT, \
+		KEY_COMPUTER,
+	},
+};
+
+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,
+	},
+};
+
+/* FSI A */
+static struct sh_fsi_platform_info fsi_info = {
+	.porta_flags = SH_FSI_OUT_SLAVE_MODE	|
+		       SH_FSI_IN_SLAVE_MODE	|
+		       SH_FSI_OFMT(I2S)		|
+		       SH_FSI_IFMT(I2S),
+};
+
+static struct resource fsi_resources[] = {
+	[0] = {
+		.name	= "FSI",
+		.start	= 0xEC230000,
+		.end	= 0xEC230400 - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start  = gic_spi(146),
+		.flags  = IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device fsi_device = {
+	.name		= "sh_fsi2",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(fsi_resources),
+	.resource	= fsi_resources,
+	.dev	= {
+		.platform_data	= &fsi_info,
+	},
+};
+
+static struct resource sh_mmcif_resources[] = {
+	[0] = {
+		.name	= "MMCIF",
+		.start	= 0xe6bd0000,
+		.end	= 0xe6bd00ff,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= gic_spi(141),
+		.flags	= IORESOURCE_IRQ,
+	},
+	[2] = {
+		.start	= gic_spi(140),
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct sh_mmcif_plat_data sh_mmcif_platdata = {
+	.sup_pclk	= 0,
+	.ocr		= MMC_VDD_165_195,
+	.caps		= MMC_CAP_8_BIT_DATA | MMC_CAP_NONREMOVABLE,
+};
+
+static struct platform_device mmc_device = {
+	.name		= "sh_mmcif",
+	.id		= 0,
+	.dev		= {
+		.dma_mask		= NULL,
+		.coherent_dma_mask	= 0xffffffff,
+		.platform_data		= &sh_mmcif_platdata,
+	},
+	.num_resources	= ARRAY_SIZE(sh_mmcif_resources),
+	.resource	= sh_mmcif_resources,
+};
+
+/* IrDA */
+static struct resource irda_resources[] = {
+	[0] = {
+		.start	= 0xE6D00000,
+		.end	= 0xE6D01FD4 - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= gic_spi(95),
+		.flags  = IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device irda_device = {
+	.name           = "sh_irda",
+	.id		= 0,
+	.resource       = irda_resources,
+	.num_resources  = ARRAY_SIZE(irda_resources),
+};
+
+static unsigned char lcd_backlight_seq[3][2] = {
+	{ 0x04, 0x07 },
+	{ 0x23, 0x80 },
+	{ 0x03, 0x01 },
+};
+
+static void lcd_backlight_on(void)
+{
+	struct i2c_adapter *a;
+	struct i2c_msg msg;
+	int k;
+
+	a = i2c_get_adapter(1);
+	for (k = 0; a && k < 3; k++) {
+		msg.addr = 0x6d;
+		msg.buf = &lcd_backlight_seq[k][0];
+		msg.len = 2;
+		msg.flags = 0;
+		if (i2c_transfer(a, &msg, 1) != 1)
+			break;
+	}
+}
+
+static void lcd_backlight_reset(void)
+{
+	gpio_set_value(GPIO_PORT235, 0);
+	mdelay(24);
+	gpio_set_value(GPIO_PORT235, 1);
+}
+
+static void lcd_on(void *board_data, struct fb_info *info)
+{
+	lcd_backlight_on();
+}
+
+static void lcd_off(void *board_data)
+{
+	lcd_backlight_reset();
+}
+
+/* LCDC0 */
+static const struct fb_videomode lcdc0_modes[] = {
+	{
+		.name		= "R63302(QHD)",
+		.xres		= 544,
+		.yres		= 961,
+		.left_margin	= 72,
+		.right_margin	= 600,
+		.hsync_len	= 16,
+		.upper_margin	= 8,
+		.lower_margin	= 8,
+		.vsync_len	= 2,
+		.sync		= FB_SYNC_VERT_HIGH_ACT | FB_SYNC_HOR_HIGH_ACT,
+	},
+};
+
+static struct sh_mobile_lcdc_info lcdc0_info = {
+	.clock_source = LCDC_CLK_PERIPHERAL,
+	.ch[0] = {
+		.chan = LCDC_CHAN_MAINLCD,
+		.interface_type = RGB24,
+		.clock_divider = 1,
+		.flags = LCDC_FLAGS_DWPOL,
+		.lcd_size_cfg.width = 44,
+		.lcd_size_cfg.height = 79,
+		.bpp = 16,
+		.lcd_cfg = lcdc0_modes,
+		.num_cfg = ARRAY_SIZE(lcdc0_modes),
+		.board_cfg = {
+			.display_on = lcd_on,
+			.display_off = lcd_off,
+		},
+	}
+};
+
+static struct resource lcdc0_resources[] = {
+	[0] = {
+		.name	= "LCDC0",
+		.start	= 0xfe940000, /* P4-only space */
+		.end	= 0xfe943fff,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= intcs_evt2irq(0x580),
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device lcdc0_device = {
+	.name		= "sh_mobile_lcdc_fb",
+	.num_resources	= ARRAY_SIZE(lcdc0_resources),
+	.resource	= lcdc0_resources,
+	.id             = 0,
+	.dev	= {
+		.platform_data	= &lcdc0_info,
+		.coherent_dma_mask = ~0,
+	},
+};
+
+/* MIPI-DSI */
+static struct resource mipidsi0_resources[] = {
+	[0] = {
+		.start  = 0xfeab0000,
+		.end    = 0xfeab3fff,
+		.flags  = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start  = 0xfeab4000,
+		.end    = 0xfeab7fff,
+		.flags  = IORESOURCE_MEM,
+	},
+};
+
+static struct sh_mipi_dsi_info mipidsi0_info = {
+	.data_format	= MIPI_RGB888,
+	.lcd_chan	= &lcdc0_info.ch[0],
+	.vsynw_offset	= 20,
+	.clksrc		= 1,
+	.flags		= SH_MIPI_DSI_HSABM,
+};
+
+static struct platform_device mipidsi0_device = {
+	.name           = "sh-mipi-dsi",
+	.num_resources  = ARRAY_SIZE(mipidsi0_resources),
+	.resource       = mipidsi0_resources,
+	.id             = 0,
+	.dev	= {
+		.platform_data	= &mipidsi0_info,
+	},
+};
+
+static struct platform_device *ag5evm_devices[] __initdata = {
+	&eth_device,
+	&keysc_device,
+	&fsi_device,
+	&mmc_device,
+	&irda_device,
+	&lcdc0_device,
+	&mipidsi0_device,
+};
+
+static struct map_desc ag5evm_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 ag5evm_map_io(void)
+{
+	iotable_init(ag5evm_io_desc, ARRAY_SIZE(ag5evm_io_desc));
+
+	/* 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)
+{
+	sh73a0_pinmux_init();
+
+	/* enable SCIFA2 */
+	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);
+
+	/* enable 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);
+	gpio_request(GPIO_FN_PORT149_KEYOUT9, NULL);
+
+	/* enable I2C channel 2 and 3 */
+	gpio_request(GPIO_FN_PORT236_I2C_SDA2, NULL);
+	gpio_request(GPIO_FN_PORT237_I2C_SCL2, NULL);
+	gpio_request(GPIO_FN_PORT248_I2C_SCL3, NULL);
+	gpio_request(GPIO_FN_PORT249_I2C_SDA3, NULL);
+
+	/* 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_PORT208, NULL); /* Reset */
+	gpio_direction_output(GPIO_PORT208, 1);
+
+	/* enable SMSC911X */
+	gpio_request(GPIO_PORT144, NULL); /* PINTA2 */
+	gpio_direction_input(GPIO_PORT144);
+	gpio_request(GPIO_PORT145, NULL); /* RESET */
+	gpio_direction_output(GPIO_PORT145, 1);
+
+	/* FSI A */
+	gpio_request(GPIO_FN_FSIACK, NULL);
+	gpio_request(GPIO_FN_FSIAILR, NULL);
+	gpio_request(GPIO_FN_FSIAIBT, NULL);
+	gpio_request(GPIO_FN_FSIAISLD, NULL);
+	gpio_request(GPIO_FN_FSIAOSLD, NULL);
+
+	/* IrDA */
+	gpio_request(GPIO_FN_PORT241_IRDA_OUT, NULL);
+	gpio_request(GPIO_FN_PORT242_IRDA_IN,  NULL);
+	gpio_request(GPIO_FN_PORT243_IRDA_FIRSEL, NULL);
+
+	/* LCD panel */
+	gpio_request(GPIO_PORT217, NULL); /* RESET */
+	gpio_direction_output(GPIO_PORT217, 0);
+	mdelay(1);
+	gpio_set_value(GPIO_PORT217, 1);
+	mdelay(100);
+
+	/* LCD backlight controller */
+	gpio_request(GPIO_PORT235, NULL); /* RESET */
+	gpio_direction_output(GPIO_PORT235, 0);
+	lcd_backlight_reset();
+
+	/* MIPI-DSI clock setup */
+	__raw_writel(0x2a809010, DSI0PHYCR);
+
+#ifdef CONFIG_CACHE_L2X0
+	/* Shared attribute override enable, 64K*8way */
+	l2x0_init(__io(0xf0100000), 0x00460000, 0xc2000fff);
+#endif
+	sh73a0_add_standard_devices();
+	platform_add_devices(ag5evm_devices, ARRAY_SIZE(ag5evm_devices));
+}
+
+static void __init ag5evm_timer_init(void)
+{
+	sh73a0_clock_init();
+	shmobile_timer.init();
+	return;
+}
+
+struct sys_timer ag5evm_timer = {
+	.init	= ag5evm_timer_init,
+};
+
+MACHINE_START(AG5EVM, "ag5evm")
+	.map_io		= ag5evm_map_io,
+	.init_irq	= ag5evm_init_irq,
+	.handle_irq	= shmobile_handle_irq_gic,
+	.init_machine	= ag5evm_init,
+	.timer		= &ag5evm_timer,
+MACHINE_END
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-shmobile/board-ap4evb.c linux-libre-2.6.38-gnu1/arch/arm/mach-shmobile/board-ap4evb.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-shmobile/board-ap4evb.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-shmobile/board-ap4evb.c	2011-03-14 21:20:32.000000000 -0400
@@ -61,6 +61,7 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <asm/mach/time.h>
+#include <asm/setup.h>
 
 /*
  * Address	Interface		BusWidth	note
@@ -246,10 +247,7 @@ static struct platform_device smc911x_de
  */
 static int slot_cn7_get_cd(struct platform_device *pdev)
 {
-	if (gpio_is_valid(GPIO_PORT41))
-		return !gpio_get_value(GPIO_PORT41);
-	else
-		return -ENXIO;
+	return !gpio_get_value(GPIO_PORT41);
 }
 
 /* SH_MMCIF */
@@ -272,6 +270,15 @@ static struct resource sh_mmcif_resource
 	},
 };
 
+static struct sh_mmcif_dma sh_mmcif_dma = {
+	.chan_priv_rx	= {
+		.slave_id	= SHDMA_SLAVE_MMCIF_RX,
+	},
+	.chan_priv_tx	= {
+		.slave_id	= SHDMA_SLAVE_MMCIF_TX,
+	},
+};
+
 static struct sh_mmcif_plat_data sh_mmcif_plat = {
 	.sup_pclk	= 0,
 	.ocr		= MMC_VDD_165_195 | MMC_VDD_32_33 | MMC_VDD_33_34,
@@ -279,6 +286,7 @@ static struct sh_mmcif_plat_data sh_mmci
 			  MMC_CAP_8_BIT_DATA |
 			  MMC_CAP_NEEDS_POLL,
 	.get_cd		= slot_cn7_get_cd,
+	.dma		= &sh_mmcif_dma,
 };
 
 static struct platform_device sh_mmcif_device = {
@@ -297,6 +305,7 @@ static struct platform_device sh_mmcif_d
 static struct sh_mobile_sdhi_info sdhi0_info = {
 	.dma_slave_tx	= SHDMA_SLAVE_SDHI0_TX,
 	.dma_slave_rx	= SHDMA_SLAVE_SDHI0_RX,
+	.tmio_caps	= MMC_CAP_SDIO_IRQ,
 };
 
 static struct resource sdhi0_resources[] = {
@@ -328,7 +337,7 @@ static struct sh_mobile_sdhi_info sdhi1_
 	.dma_slave_rx	= SHDMA_SLAVE_SDHI1_RX,
 	.tmio_ocr_mask	= MMC_VDD_165_195,
 	.tmio_flags	= TMIO_MMC_WRPROTECT_DISABLE,
-	.tmio_caps	= MMC_CAP_NEEDS_POLL,
+	.tmio_caps	= MMC_CAP_NEEDS_POLL | MMC_CAP_SDIO_IRQ,
 	.get_cd		= slot_cn7_get_cd,
 };
 
@@ -501,7 +510,12 @@ static struct platform_device keysc_devi
 static struct resource mipidsi0_resources[] = {
 	[0] = {
 		.start  = 0xffc60000,
-		.end    = 0xffc68fff,
+		.end    = 0xffc63073,
+		.flags  = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start  = 0xffc68000,
+		.end    = 0xffc680ef,
 		.flags  = IORESOURCE_MEM,
 	},
 };
@@ -509,6 +523,7 @@ static struct resource mipidsi0_resource
 static struct sh_mipi_dsi_info mipidsi0_info = {
 	.data_format	= MIPI_RGB888,
 	.lcd_chan	= &lcdc_info.ch[0],
+	.vsynw_offset	= 17,
 };
 
 static struct platform_device mipidsi0_device = {
@@ -521,44 +536,6 @@ static struct platform_device mipidsi0_d
 	},
 };
 
-/* This function will disappear when we switch to (runtime) PM */
-static int __init ap4evb_init_display_clk(void)
-{
-	struct clk *lcdc_clk;
-	struct clk *dsitx_clk;
-	int ret;
-
-	lcdc_clk = clk_get(&lcdc_device.dev, "sh_mobile_lcdc_fb.0");
-	if (IS_ERR(lcdc_clk))
-		return PTR_ERR(lcdc_clk);
-
-	dsitx_clk = clk_get(&mipidsi0_device.dev, "sh-mipi-dsi.0");
-	if (IS_ERR(dsitx_clk)) {
-		ret = PTR_ERR(dsitx_clk);
-		goto eclkdsitxget;
-	}
-
-	ret = clk_enable(lcdc_clk);
-	if (ret < 0)
-		goto eclklcdcon;
-
-	ret = clk_enable(dsitx_clk);
-	if (ret < 0)
-		goto eclkdsitxon;
-
-	return 0;
-
-eclkdsitxon:
-	clk_disable(lcdc_clk);
-eclklcdcon:
-	clk_put(dsitx_clk);
-eclkdsitxget:
-	clk_put(lcdc_clk);
-
-	return ret;
-}
-device_initcall(ap4evb_init_display_clk);
-
 static struct platform_device *qhd_devices[] __initdata = {
 	&mipidsi0_device,
 	&keysc_device,
@@ -664,9 +641,8 @@ static int fsi_hdmi_set_rate(struct devi
 		return -EIO;
 
 	ret = __fsi_set_round_rate(fsib_clk, fsib_rate, enable);
-	clk_put(fsib_clk);
 	if (ret < 0)
-		return ret;
+		goto fsi_set_rate_end;
 
 	/* FSI DIV setting */
 	ret = __fsi_set_round_rate(fdiv_clk, fdiv_rate, enable);
@@ -674,10 +650,14 @@ static int fsi_hdmi_set_rate(struct devi
 		/* disable FSI B */
 		if (enable)
 			__fsi_set_round_rate(fsib_clk, fsib_rate, 0);
-		return ret;
+		goto fsi_set_rate_end;
 	}
 
-	return ackmd_bpfmd;
+	ret = ackmd_bpfmd;
+
+fsi_set_rate_end:
+	clk_put(fsib_clk);
+	return ret;
 }
 
 static int fsi_set_rate(struct device *dev, int is_porta, int rate, int enable)
@@ -729,6 +709,10 @@ static struct platform_device fsi_device
 	},
 };
 
+static struct platform_device fsi_ak4643_device = {
+	.name		= "sh_fsi2_a_ak4643",
+};
+
 static struct sh_mobile_lcdc_info sh_mobile_lcdc1_info = {
 	.clock_source = LCDC_CLK_EXTERNAL,
 	.ch[0] = {
@@ -764,10 +748,15 @@ static struct platform_device lcdc1_devi
 	},
 };
 
+static long ap4evb_clk_optimize(unsigned long target, unsigned long *best_freq,
+				unsigned long *parent_freq);
+
+
 static struct sh_mobile_hdmi_info hdmi_info = {
 	.lcd_chan = &sh_mobile_lcdc1_info.ch[0],
 	.lcd_dev = &lcdc1_device.dev,
 	.flags = HDMI_SND_SRC_SPDIF,
+	.clk_optimize_parent = ap4evb_clk_optimize,
 };
 
 static struct resource hdmi_resources[] = {
@@ -794,6 +783,25 @@ static struct platform_device hdmi_devic
 	},
 };
 
+static long ap4evb_clk_optimize(unsigned long target, unsigned long *best_freq,
+				unsigned long *parent_freq)
+{
+	struct clk *hdmi_ick = clk_get(&hdmi_device.dev, "ick");
+	long error;
+
+	if (IS_ERR(hdmi_ick)) {
+		int ret = PTR_ERR(hdmi_ick);
+		pr_err("Cannot get HDMI ICK: %d\n", ret);
+		return ret;
+	}
+
+	error = clk_round_parent(hdmi_ick, target, best_freq, parent_freq, 1, 64);
+
+	clk_put(hdmi_ick);
+
+	return error;
+}
+
 static struct gpio_led ap4evb_leds[] = {
 	{
 		.name			= "led4",
@@ -927,6 +935,7 @@ static struct platform_device *ap4evb_de
 	&sdhi1_device,
 	&usb1_host_device,
 	&fsi_device,
+	&fsi_ak4643_device,
 	&sh_mmcif_device,
 	&lcdc1_device,
 	&lcdc_device,
@@ -1181,7 +1190,7 @@ static void __init ap4evb_init(void)
 	gpio_request(GPIO_FN_OVCN2_1,    NULL);
 
 	/* setup USB phy */
-	__raw_writew(0x8a0a, 0xE6058130);	/* USBCR2 */
+	__raw_writew(0x8a0a, 0xE6058130);	/* USBCR4 */
 
 	/* enable FSI2 port A (ak4643) */
 	gpio_request(GPIO_FN_FSIAIBT,	NULL);
@@ -1294,7 +1303,7 @@ static void __init ap4evb_init(void)
 
 	lcdc_info.clock_source			= LCDC_CLK_BUS;
 	lcdc_info.ch[0].interface_type		= RGB18;
-	lcdc_info.ch[0].clock_divider		= 2;
+	lcdc_info.ch[0].clock_divider		= 3;
 	lcdc_info.ch[0].flags			= 0;
 	lcdc_info.ch[0].lcd_size_cfg.width	= 152;
 	lcdc_info.ch[0].lcd_size_cfg.height	= 91;
@@ -1355,6 +1364,7 @@ static struct sys_timer ap4evb_timer = {
 MACHINE_START(AP4EVB, "ap4evb")
 	.map_io		= ap4evb_map_io,
 	.init_irq	= sh7372_init_irq,
+	.handle_irq	= shmobile_handle_irq_intc,
 	.init_machine	= ap4evb_init,
 	.timer		= &ap4evb_timer,
 MACHINE_END
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-shmobile/board-g3evm.c linux-libre-2.6.38-gnu1/arch/arm/mach-shmobile/board-g3evm.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-shmobile/board-g3evm.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-shmobile/board-g3evm.c	2011-03-14 21:20:32.000000000 -0400
@@ -347,7 +347,6 @@ static void __init g3evm_init(void)
 	gpio_request(GPIO_FN_IRDA_OUT, NULL);
 	gpio_request(GPIO_FN_IRDA_IN, NULL);
 	gpio_request(GPIO_FN_IRDA_FIRSEL, NULL);
-	set_irq_type(evt2irq(0x480), IRQ_TYPE_LEVEL_LOW);
 
 	sh7367_add_standard_devices();
 
@@ -367,6 +366,7 @@ static struct sys_timer g3evm_timer = {
 MACHINE_START(G3EVM, "g3evm")
 	.map_io		= g3evm_map_io,
 	.init_irq	= sh7367_init_irq,
+	.handle_irq	= shmobile_handle_irq_intc,
 	.init_machine	= g3evm_init,
 	.timer		= &g3evm_timer,
 MACHINE_END
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-shmobile/board-g4evm.c linux-libre-2.6.38-gnu1/arch/arm/mach-shmobile/board-g4evm.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-shmobile/board-g4evm.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-shmobile/board-g4evm.c	2011-03-14 21:20:32.000000000 -0400
@@ -30,6 +30,7 @@
 #include <linux/io.h>
 #include <linux/input.h>
 #include <linux/input/sh_keysc.h>
+#include <linux/mmc/host.h>
 #include <linux/mfd/sh_mobile_sdhi.h>
 #include <linux/gpio.h>
 #include <mach/sh7377.h>
@@ -196,6 +197,10 @@ static struct platform_device keysc_devi
 };
 
 /* SDHI */
+static struct sh_mobile_sdhi_info sdhi0_info = {
+	.tmio_caps	= MMC_CAP_SDIO_IRQ,
+};
+
 static struct resource sdhi0_resources[] = {
 	[0] = {
 		.name	= "SDHI0",
@@ -214,6 +219,13 @@ static struct platform_device sdhi0_devi
 	.num_resources  = ARRAY_SIZE(sdhi0_resources),
 	.resource       = sdhi0_resources,
 	.id             = 0,
+	.dev	= {
+		.platform_data	= &sdhi0_info,
+	},
+};
+
+static struct sh_mobile_sdhi_info sdhi1_info = {
+	.tmio_caps	= MMC_CAP_NONREMOVABLE | MMC_CAP_SDIO_IRQ,
 };
 
 static struct resource sdhi1_resources[] = {
@@ -234,6 +246,9 @@ static struct platform_device sdhi1_devi
 	.num_resources  = ARRAY_SIZE(sdhi1_resources),
 	.resource       = sdhi1_resources,
 	.id             = 1,
+	.dev	= {
+		.platform_data	= &sdhi1_info,
+	},
 };
 
 static struct platform_device *g4evm_devices[] __initdata = {
@@ -394,6 +409,7 @@ static struct sys_timer g4evm_timer = {
 MACHINE_START(G4EVM, "g4evm")
 	.map_io		= g4evm_map_io,
 	.init_irq	= sh7377_init_irq,
+	.handle_irq	= shmobile_handle_irq_intc,
 	.init_machine	= g4evm_init,
 	.timer		= &g4evm_timer,
 MACHINE_END
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-shmobile/board-mackerel.c linux-libre-2.6.38-gnu1/arch/arm/mach-shmobile/board-mackerel.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-shmobile/board-mackerel.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-shmobile/board-mackerel.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,1220 @@
+/*
+ * mackerel board support
+ *
+ * Copyright (C) 2010 Renesas Solutions Corp.
+ * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+ *
+ * based on ap4evb
+ * Copyright (C) 2010  Magnus Damm
+ * Copyright (C) 2008  Yoshihiro Shimoda
+ *
+ * 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/delay.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/input.h>
+#include <linux/io.h>
+#include <linux/i2c.h>
+#include <linux/leds.h>
+#include <linux/mfd/sh_mobile_sdhi.h>
+#include <linux/mfd/tmio.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/sh_mmcif.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/physmap.h>
+#include <linux/smsc911x.h>
+#include <linux/sh_intc.h>
+#include <linux/tca6416_keypad.h>
+#include <linux/usb/r8a66597.h>
+
+#include <video/sh_mobile_hdmi.h>
+#include <video/sh_mobile_lcdc.h>
+#include <media/sh_mobile_ceu.h>
+#include <media/soc_camera.h>
+#include <media/soc_camera_platform.h>
+#include <sound/sh_fsi.h>
+
+#include <mach/common.h>
+#include <mach/sh7372.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include <asm/mach/map.h>
+#include <asm/mach-types.h>
+
+/*
+ * Address	Interface		BusWidth	note
+ * ------------------------------------------------------------------
+ * 0x0000_0000	NOR Flash ROM (MCP)	16bit		SW7 : bit1 = ON
+ * 0x0800_0000	user area		-
+ * 0x1000_0000	NOR Flash ROM (MCP)	16bit		SW7 : bit1 = OFF
+ * 0x1400_0000	Ether (LAN9220)		16bit
+ * 0x1600_0000	user area		-		cannot use with NAND
+ * 0x1800_0000	user area		-
+ * 0x1A00_0000	-
+ * 0x4000_0000	LPDDR2-SDRAM (POP)	32bit
+ */
+
+/*
+ * CPU mode
+ *
+ * SW4                                     | Boot Area| Master   | Remarks
+ *  1  | 2   | 3   | 4   | 5   | 6   | 8   |          | Processor|
+ * ----+-----+-----+-----+-----+-----+-----+----------+----------+--------------
+ * ON  | ON  | OFF | ON  | ON  | OFF | OFF | External | System   | External ROM
+ * ON  | ON  | ON  | ON  | ON  | OFF | OFF | External | System   | ROM Debug
+ * ON  | ON  | X   | ON  | OFF | OFF | OFF | Built-in | System   | ROM Debug
+ * X   | OFF | X   | X   | X   | X   | OFF | Built-in | System   | MaskROM
+ * OFF | X   | X   | X   | X   | X   | OFF | Built-in | System   | MaskROM
+ * X   | X   | X   | OFF | X   | X   | OFF | Built-in | System   | MaskROM
+ * OFF | ON  | OFF | X   | X   | OFF | ON  | External | System   | Standalone
+ * ON  | OFF | OFF | X   | X   | OFF | ON  | External | Realtime | Standalone
+*/
+
+/*
+ * NOR Flash ROM
+ *
+ *  SW1  |     SW2    | SW7  | NOR Flash ROM
+ *  bit1 | bit1  bit2 | bit1 | Memory allocation
+ * ------+------------+------+------------------
+ *  OFF  | ON     OFF | ON   |    Area 0
+ *  OFF  | ON     OFF | OFF  |    Area 4
+ */
+
+/*
+ * SMSC 9220
+ *
+ *  SW1		SMSC 9220
+ * -----------------------
+ *  ON		access disable
+ *  OFF		access enable
+ */
+
+/*
+ * NAND Flash ROM
+ *
+ *  SW1  |     SW2    | SW7  | NAND Flash ROM
+ *  bit1 | bit1  bit2 | bit2 | Memory allocation
+ * ------+------------+------+------------------
+ *  OFF  | ON     OFF | ON   |    FCE 0
+ *  OFF  | ON     OFF | OFF  |    FCE 1
+ */
+
+/*
+ * External interrupt pin settings
+ *
+ * IRQX  | pin setting        | device             | level
+ * ------+--------------------+--------------------+-------
+ * IRQ0  | ICR1A.IRQ0SA=0010  | SDHI2 card detect  | Low
+ * IRQ6  | ICR1A.IRQ6SA=0011  | Ether(LAN9220)     | High
+ * IRQ7  | ICR1A.IRQ7SA=0010  | LCD Tuch Panel     | Low
+ * IRQ8  | ICR2A.IRQ8SA=0010  | MMC/SD card detect | Low
+ * IRQ9  | ICR2A.IRQ9SA=0010  | KEY(TCA6408)       | Low
+ * IRQ21 | ICR4A.IRQ21SA=0011 | Sensor(ADXL345)    | High
+ * IRQ22 | ICR4A.IRQ22SA=0011 | Sensor(AK8975)     | High
+ */
+
+/*
+ * USB
+ *
+ * USB0 : CN22 : Function
+ * USB1 : CN31 : Function/Host *1
+ *
+ * J30 (for CN31) *1
+ * ----------+---------------+-------------
+ * 1-2 short | VBUS 5V       | Host
+ * open      | external VBUS | Function
+ *
+ * *1
+ * CN31 is used as Host in Linux.
+ */
+
+/*
+ * SDHI0 (CN12)
+ *
+ * SW56 : OFF
+ *
+ */
+
+/* MMC /SDHI1 (CN7)
+ *
+ * I/O voltage : 1.8v
+ *
+ * Power voltage : 1.8v or 3.3v
+ *  J22 : select power voltage *1
+ *	1-2 pin : 1.8v
+ *	2-3 pin : 3.3v
+ *
+ * *1
+ * Please change J22 depends the card to be used.
+ * MMC's OCR field set to support either voltage for the card inserted.
+ *
+ *	SW1	|	SW33
+ *		| bit1 | bit2 | bit3 | bit4
+ * -------------+------+------+------+-------
+ * MMC0   OFF	|  OFF |   X  |  ON  |  X       (Use MMCIF)
+ * SDHI1  OFF	|  ON  |   X  |  OFF |  X       (Use MFD_SH_MOBILE_SDHI)
+ *
+ */
+
+/*
+ * SDHI2 (CN23)
+ *
+ * microSD card sloct
+ *
+ */
+
+/*
+ * FIXME !!
+ *
+ * gpio_no_direction
+ * are quick_hack.
+ *
+ * current gpio frame work doesn't have
+ * the method to control only pull up/down/free.
+ * this function should be replaced by correct gpio function
+ */
+static void __init gpio_no_direction(u32 addr)
+{
+	__raw_writeb(0x00, addr);
+}
+
+/* MTD */
+static struct mtd_partition nor_flash_partitions[] = {
+	{
+		.name		= "loader",
+		.offset		= 0x00000000,
+		.size		= 512 * 1024,
+		.mask_flags	= MTD_WRITEABLE,
+	},
+	{
+		.name		= "bootenv",
+		.offset		= MTDPART_OFS_APPEND,
+		.size		= 512 * 1024,
+		.mask_flags	= MTD_WRITEABLE,
+	},
+	{
+		.name		= "kernel_ro",
+		.offset		= MTDPART_OFS_APPEND,
+		.size		= 8 * 1024 * 1024,
+		.mask_flags	= MTD_WRITEABLE,
+	},
+	{
+		.name		= "kernel",
+		.offset		= MTDPART_OFS_APPEND,
+		.size		= 8 * 1024 * 1024,
+	},
+	{
+		.name		= "data",
+		.offset		= MTDPART_OFS_APPEND,
+		.size		= MTDPART_SIZ_FULL,
+	},
+};
+
+static struct physmap_flash_data nor_flash_data = {
+	.width		= 2,
+	.parts		= nor_flash_partitions,
+	.nr_parts	= ARRAY_SIZE(nor_flash_partitions),
+};
+
+static struct resource nor_flash_resources[] = {
+	[0]	= {
+		.start	= 0x00000000,
+		.end	= 0x08000000 - 1,
+		.flags	= IORESOURCE_MEM,
+	}
+};
+
+static struct platform_device nor_flash_device = {
+	.name		= "physmap-flash",
+	.dev		= {
+		.platform_data	= &nor_flash_data,
+	},
+	.num_resources	= ARRAY_SIZE(nor_flash_resources),
+	.resource	= nor_flash_resources,
+};
+
+/* SMSC */
+static struct resource smc911x_resources[] = {
+	{
+		.start	= 0x14000000,
+		.end	= 0x16000000 - 1,
+		.flags	= IORESOURCE_MEM,
+	}, {
+		.start	= evt2irq(0x02c0) /* IRQ6A */,
+		.flags	= IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL,
+	},
+};
+
+static struct smsc911x_platform_config smsc911x_info = {
+	.flags		= SMSC911X_USE_16BIT | SMSC911X_SAVE_MAC_ADDRESS,
+	.irq_polarity   = SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
+	.irq_type       = SMSC911X_IRQ_TYPE_PUSH_PULL,
+};
+
+static struct platform_device smc911x_device = {
+	.name           = "smsc911x",
+	.id             = -1,
+	.num_resources  = ARRAY_SIZE(smc911x_resources),
+	.resource       = smc911x_resources,
+	.dev            = {
+		.platform_data = &smsc911x_info,
+	},
+};
+
+/* LCDC */
+static struct fb_videomode mackerel_lcdc_modes[] = {
+	{
+		.name		= "WVGA Panel",
+		.xres		= 800,
+		.yres		= 480,
+		.left_margin	= 220,
+		.right_margin	= 110,
+		.hsync_len	= 70,
+		.upper_margin	= 20,
+		.lower_margin	= 5,
+		.vsync_len	= 5,
+		.sync		= 0,
+	},
+};
+
+static struct sh_mobile_lcdc_info lcdc_info = {
+	.clock_source = LCDC_CLK_BUS,
+	.ch[0] = {
+		.chan = LCDC_CHAN_MAINLCD,
+		.bpp = 16,
+		.lcd_cfg = mackerel_lcdc_modes,
+		.num_cfg = ARRAY_SIZE(mackerel_lcdc_modes),
+		.interface_type		= RGB24,
+		.clock_divider		= 3,
+		.flags			= 0,
+		.lcd_size_cfg.width	= 152,
+		.lcd_size_cfg.height	= 91,
+	}
+};
+
+static struct resource lcdc_resources[] = {
+	[0] = {
+		.name	= "LCDC",
+		.start	= 0xfe940000,
+		.end	= 0xfe943fff,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= intcs_evt2irq(0x580),
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device lcdc_device = {
+	.name		= "sh_mobile_lcdc_fb",
+	.num_resources	= ARRAY_SIZE(lcdc_resources),
+	.resource	= lcdc_resources,
+	.dev	= {
+		.platform_data	= &lcdc_info,
+		.coherent_dma_mask = ~0,
+	},
+};
+
+/* HDMI */
+static struct sh_mobile_lcdc_info hdmi_lcdc_info = {
+	.clock_source = LCDC_CLK_EXTERNAL,
+	.ch[0] = {
+		.chan = LCDC_CHAN_MAINLCD,
+		.bpp = 16,
+		.interface_type = RGB24,
+		.clock_divider = 1,
+		.flags = LCDC_FLAGS_DWPOL,
+	}
+};
+
+static struct resource hdmi_lcdc_resources[] = {
+	[0] = {
+		.name	= "LCDC1",
+		.start	= 0xfe944000,
+		.end	= 0xfe947fff,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= intcs_evt2irq(0x1780),
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device hdmi_lcdc_device = {
+	.name		= "sh_mobile_lcdc_fb",
+	.num_resources	= ARRAY_SIZE(hdmi_lcdc_resources),
+	.resource	= hdmi_lcdc_resources,
+	.id		= 1,
+	.dev	= {
+		.platform_data	= &hdmi_lcdc_info,
+		.coherent_dma_mask = ~0,
+	},
+};
+
+static struct sh_mobile_hdmi_info hdmi_info = {
+	.lcd_chan	= &hdmi_lcdc_info.ch[0],
+	.lcd_dev	= &hdmi_lcdc_device.dev,
+	.flags		= HDMI_SND_SRC_SPDIF,
+};
+
+static struct resource hdmi_resources[] = {
+	[0] = {
+		.name	= "HDMI",
+		.start	= 0xe6be0000,
+		.end	= 0xe6be00ff,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		/* There's also an HDMI interrupt on INTCS @ 0x18e0 */
+		.start	= evt2irq(0x17e0),
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device hdmi_device = {
+	.name		= "sh-mobile-hdmi",
+	.num_resources	= ARRAY_SIZE(hdmi_resources),
+	.resource	= hdmi_resources,
+	.id             = -1,
+	.dev	= {
+		.platform_data	= &hdmi_info,
+	},
+};
+
+static int __init hdmi_init_pm_clock(void)
+{
+	struct clk *hdmi_ick = clk_get(&hdmi_device.dev, "ick");
+	int ret;
+	long rate;
+
+	if (IS_ERR(hdmi_ick)) {
+		ret = PTR_ERR(hdmi_ick);
+		pr_err("Cannot get HDMI ICK: %d\n", ret);
+		goto out;
+	}
+
+	ret = clk_set_parent(&sh7372_pllc2_clk, &sh7372_dv_clki_div2_clk);
+	if (ret < 0) {
+		pr_err("Cannot set PLLC2 parent: %d, %d users\n",
+		       ret, sh7372_pllc2_clk.usecount);
+		goto out;
+	}
+
+	pr_debug("PLLC2 initial frequency %lu\n",
+		 clk_get_rate(&sh7372_pllc2_clk));
+
+	rate = clk_round_rate(&sh7372_pllc2_clk, 594000000);
+	if (rate < 0) {
+		pr_err("Cannot get suitable rate: %ld\n", rate);
+		ret = rate;
+		goto out;
+	}
+
+	ret = clk_set_rate(&sh7372_pllc2_clk, rate);
+	if (ret < 0) {
+		pr_err("Cannot set rate %ld: %d\n", rate, ret);
+		goto out;
+	}
+
+	ret = clk_enable(&sh7372_pllc2_clk);
+	if (ret < 0) {
+		pr_err("Cannot enable pllc2 clock\n");
+		goto out;
+	}
+
+	pr_debug("PLLC2 set frequency %lu\n", rate);
+
+	ret = clk_set_parent(hdmi_ick, &sh7372_pllc2_clk);
+	if (ret < 0) {
+		pr_err("Cannot set HDMI parent: %d\n", ret);
+		goto out;
+	}
+
+out:
+	if (!IS_ERR(hdmi_ick))
+		clk_put(hdmi_ick);
+	return ret;
+}
+device_initcall(hdmi_init_pm_clock);
+
+/* USB1 (Host) */
+static void usb1_host_port_power(int port, int power)
+{
+	if (!power) /* only power-on is supported for now */
+		return;
+
+	/* set VBOUT/PWEN and EXTLP1 in DVSTCTR */
+	__raw_writew(__raw_readw(0xE68B0008) | 0x600, 0xE68B0008);
+}
+
+static struct r8a66597_platdata usb1_host_data = {
+	.on_chip	= 1,
+	.port_power	= usb1_host_port_power,
+};
+
+static struct resource usb1_host_resources[] = {
+	[0] = {
+		.name	= "USBHS",
+		.start	= 0xE68B0000,
+		.end	= 0xE68B00E6 - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= evt2irq(0x1ce0) /* USB1_USB1I0 */,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device usb1_host_device = {
+	.name	= "r8a66597_hcd",
+	.id	= 1,
+	.dev = {
+		.dma_mask		= NULL,         /*  not use dma */
+		.coherent_dma_mask	= 0xffffffff,
+		.platform_data		= &usb1_host_data,
+	},
+	.num_resources	= ARRAY_SIZE(usb1_host_resources),
+	.resource	= usb1_host_resources,
+};
+
+/* LED */
+static struct gpio_led mackerel_leds[] = {
+	{
+		.name		= "led0",
+		.gpio		= GPIO_PORT0,
+		.default_state	= LEDS_GPIO_DEFSTATE_ON,
+	},
+	{
+		.name		= "led1",
+		.gpio		= GPIO_PORT1,
+		.default_state	= LEDS_GPIO_DEFSTATE_ON,
+	},
+	{
+		.name		= "led2",
+		.gpio		= GPIO_PORT2,
+		.default_state	= LEDS_GPIO_DEFSTATE_ON,
+	},
+	{
+		.name		= "led3",
+		.gpio		= GPIO_PORT159,
+		.default_state	= LEDS_GPIO_DEFSTATE_ON,
+	}
+};
+
+static struct gpio_led_platform_data mackerel_leds_pdata = {
+	.leds = mackerel_leds,
+	.num_leds = ARRAY_SIZE(mackerel_leds),
+};
+
+static struct platform_device leds_device = {
+	.name = "leds-gpio",
+	.id = 0,
+	.dev = {
+		.platform_data  = &mackerel_leds_pdata,
+	},
+};
+
+/* FSI */
+#define IRQ_FSI evt2irq(0x1840)
+static int __fsi_set_round_rate(struct clk *clk, long rate, int enable)
+{
+	int ret;
+
+	if (rate <= 0)
+		return 0;
+
+	if (!enable) {
+		clk_disable(clk);
+		return 0;
+	}
+
+	ret = clk_set_rate(clk, clk_round_rate(clk, rate));
+	if (ret < 0)
+		return ret;
+
+	return clk_enable(clk);
+}
+
+static int fsi_set_rate(struct device *dev, int is_porta, int rate, int enable)
+{
+	struct clk *fsib_clk;
+	struct clk *fdiv_clk = &sh7372_fsidivb_clk;
+	long fsib_rate = 0;
+	long fdiv_rate = 0;
+	int ackmd_bpfmd;
+	int ret;
+
+	/* FSIA is slave mode. nothing to do here */
+	if (is_porta)
+		return 0;
+
+	/* clock start */
+	switch (rate) {
+	case 44100:
+		fsib_rate	= rate * 256;
+		ackmd_bpfmd	= SH_FSI_ACKMD_256 | SH_FSI_BPFMD_64;
+		break;
+	case 48000:
+		fsib_rate	= 85428000; /* around 48kHz x 256 x 7 */
+		fdiv_rate	= rate * 256;
+		ackmd_bpfmd	= SH_FSI_ACKMD_256 | SH_FSI_BPFMD_64;
+		break;
+	default:
+		pr_err("unsupported rate in FSI2 port B\n");
+		return -EINVAL;
+	}
+
+	/* FSI B setting */
+	fsib_clk = clk_get(dev, "ickb");
+	if (IS_ERR(fsib_clk))
+		return -EIO;
+
+	/* fsib */
+	ret = __fsi_set_round_rate(fsib_clk, fsib_rate, enable);
+	if (ret < 0)
+		goto fsi_set_rate_end;
+
+	/* FSI DIV */
+	ret = __fsi_set_round_rate(fdiv_clk, fdiv_rate, enable);
+	if (ret < 0) {
+		/* disable FSI B */
+		if (enable)
+			__fsi_set_round_rate(fsib_clk, fsib_rate, 0);
+		goto fsi_set_rate_end;
+	}
+
+	ret = ackmd_bpfmd;
+
+fsi_set_rate_end:
+	clk_put(fsib_clk);
+	return ret;
+}
+
+static struct sh_fsi_platform_info fsi_info = {
+	.porta_flags =	SH_FSI_BRS_INV		|
+			SH_FSI_OUT_SLAVE_MODE	|
+			SH_FSI_IN_SLAVE_MODE	|
+			SH_FSI_OFMT(PCM)	|
+			SH_FSI_IFMT(PCM),
+
+	.portb_flags =	SH_FSI_BRS_INV	|
+			SH_FSI_BRM_INV	|
+			SH_FSI_LRS_INV	|
+			SH_FSI_OFMT(SPDIF),
+
+	.set_rate = fsi_set_rate,
+};
+
+static struct resource fsi_resources[] = {
+	[0] = {
+		.name	= "FSI",
+		.start	= 0xFE3C0000,
+		.end	= 0xFE3C0400 - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start  = IRQ_FSI,
+		.flags  = IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device fsi_device = {
+	.name		= "sh_fsi2",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(fsi_resources),
+	.resource	= fsi_resources,
+	.dev	= {
+		.platform_data	= &fsi_info,
+	},
+};
+
+static struct platform_device fsi_ak4643_device = {
+	.name		= "sh_fsi2_a_ak4643",
+};
+
+/*
+ * The card detect pin of the top SD/MMC slot (CN7) is active low and is
+ * connected to GPIO A22 of SH7372 (GPIO_PORT41).
+ */
+static int slot_cn7_get_cd(struct platform_device *pdev)
+{
+	return !gpio_get_value(GPIO_PORT41);
+}
+
+/* SDHI0 */
+static struct sh_mobile_sdhi_info sdhi0_info = {
+	.dma_slave_tx	= SHDMA_SLAVE_SDHI0_TX,
+	.dma_slave_rx	= SHDMA_SLAVE_SDHI0_RX,
+	.tmio_caps	= MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ,
+};
+
+static struct resource sdhi0_resources[] = {
+	[0] = {
+		.name	= "SDHI0",
+		.start	= 0xe6850000,
+		.end	= 0xe68501ff,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= evt2irq(0x0e00) /* SDHI0 */,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device sdhi0_device = {
+	.name		= "sh_mobile_sdhi",
+	.num_resources	= ARRAY_SIZE(sdhi0_resources),
+	.resource	= sdhi0_resources,
+	.id		= 0,
+	.dev	= {
+		.platform_data	= &sdhi0_info,
+	},
+};
+
+#if !defined(CONFIG_MMC_SH_MMCIF)
+/* SDHI1 */
+static struct sh_mobile_sdhi_info sdhi1_info = {
+	.dma_slave_tx	= SHDMA_SLAVE_SDHI1_TX,
+	.dma_slave_rx	= SHDMA_SLAVE_SDHI1_RX,
+	.tmio_ocr_mask	= MMC_VDD_165_195,
+	.tmio_flags	= TMIO_MMC_WRPROTECT_DISABLE,
+	.tmio_caps	= MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ |
+			  MMC_CAP_NEEDS_POLL,
+	.get_cd		= slot_cn7_get_cd,
+};
+
+static struct resource sdhi1_resources[] = {
+	[0] = {
+		.name	= "SDHI1",
+		.start	= 0xe6860000,
+		.end	= 0xe68601ff,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= evt2irq(0x0e80),
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device sdhi1_device = {
+	.name		= "sh_mobile_sdhi",
+	.num_resources	= ARRAY_SIZE(sdhi1_resources),
+	.resource	= sdhi1_resources,
+	.id		= 1,
+	.dev	= {
+		.platform_data	= &sdhi1_info,
+	},
+};
+#endif
+
+/*
+ * The card detect pin of the top SD/MMC slot (CN23) is active low and is
+ * connected to GPIO SCIFB_SCK of SH7372 (GPIO_PORT162).
+ */
+static int slot_cn23_get_cd(struct platform_device *pdev)
+{
+	return !gpio_get_value(GPIO_PORT162);
+}
+
+/* SDHI2 */
+static struct sh_mobile_sdhi_info sdhi2_info = {
+	.dma_slave_tx	= SHDMA_SLAVE_SDHI2_TX,
+	.dma_slave_rx	= SHDMA_SLAVE_SDHI2_RX,
+	.tmio_flags	= TMIO_MMC_WRPROTECT_DISABLE,
+	.tmio_caps	= MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ |
+			  MMC_CAP_NEEDS_POLL,
+	.get_cd		= slot_cn23_get_cd,
+};
+
+static struct resource sdhi2_resources[] = {
+	[0] = {
+		.name	= "SDHI2",
+		.start	= 0xe6870000,
+		.end	= 0xe68701ff,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= evt2irq(0x1200),
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device sdhi2_device = {
+	.name	= "sh_mobile_sdhi",
+	.num_resources	= ARRAY_SIZE(sdhi2_resources),
+	.resource	= sdhi2_resources,
+	.id		= 2,
+	.dev	= {
+		.platform_data	= &sdhi2_info,
+	},
+};
+
+/* SH_MMCIF */
+static struct resource sh_mmcif_resources[] = {
+	[0] = {
+		.name	= "MMCIF",
+		.start	= 0xE6BD0000,
+		.end	= 0xE6BD00FF,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		/* MMC ERR */
+		.start	= evt2irq(0x1ac0),
+		.flags	= IORESOURCE_IRQ,
+	},
+	[2] = {
+		/* MMC NOR */
+		.start	= evt2irq(0x1ae0),
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct sh_mmcif_plat_data sh_mmcif_plat = {
+	.sup_pclk	= 0,
+	.ocr		= MMC_VDD_165_195 | MMC_VDD_32_33 | MMC_VDD_33_34,
+	.caps		= MMC_CAP_4_BIT_DATA |
+			  MMC_CAP_8_BIT_DATA |
+			  MMC_CAP_NEEDS_POLL,
+	.get_cd		= slot_cn7_get_cd,
+};
+
+static struct platform_device sh_mmcif_device = {
+	.name		= "sh_mmcif",
+	.id		= 0,
+	.dev		= {
+		.dma_mask		= NULL,
+		.coherent_dma_mask	= 0xffffffff,
+		.platform_data		= &sh_mmcif_plat,
+	},
+	.num_resources	= ARRAY_SIZE(sh_mmcif_resources),
+	.resource	= sh_mmcif_resources,
+};
+
+
+static int mackerel_camera_add(struct soc_camera_link *icl, struct device *dev);
+static void mackerel_camera_del(struct soc_camera_link *icl);
+
+static int camera_set_capture(struct soc_camera_platform_info *info,
+			      int enable)
+{
+	return 0; /* camera sensor always enabled */
+}
+
+static struct soc_camera_platform_info camera_info = {
+	.format_name = "UYVY",
+	.format_depth = 16,
+	.format = {
+		.code = V4L2_MBUS_FMT_UYVY8_2X8,
+		.colorspace = V4L2_COLORSPACE_SMPTE170M,
+		.field = V4L2_FIELD_NONE,
+		.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,
+	.set_capture = camera_set_capture,
+};
+
+static struct soc_camera_link camera_link = {
+	.bus_id		= 0,
+	.add_device	= mackerel_camera_add,
+	.del_device	= mackerel_camera_del,
+	.module_name	= "soc_camera_platform",
+	.priv		= &camera_info,
+};
+
+static void dummy_release(struct device *dev)
+{
+}
+
+static struct platform_device camera_device = {
+	.name		= "soc_camera_platform",
+	.dev		= {
+		.platform_data	= &camera_info,
+		.release	= dummy_release,
+	},
+};
+
+static int mackerel_camera_add(struct soc_camera_link *icl,
+			       struct device *dev)
+{
+	if (icl != &camera_link)
+		return -ENODEV;
+
+	camera_info.dev = dev;
+
+	return platform_device_register(&camera_device);
+}
+
+static void mackerel_camera_del(struct soc_camera_link *icl)
+{
+	if (icl != &camera_link)
+		return;
+
+	platform_device_unregister(&camera_device);
+	memset(&camera_device.dev.kobj, 0,
+	       sizeof(camera_device.dev.kobj));
+}
+
+static struct sh_mobile_ceu_info sh_mobile_ceu_info = {
+	.flags = SH_CEU_FLAG_USE_8BIT_BUS,
+};
+
+static struct resource ceu_resources[] = {
+	[0] = {
+		.name	= "CEU",
+		.start	= 0xfe910000,
+		.end	= 0xfe91009f,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start  = intcs_evt2irq(0x880),
+		.flags  = IORESOURCE_IRQ,
+	},
+	[2] = {
+		/* place holder for contiguous memory */
+	},
+};
+
+static struct platform_device ceu_device = {
+	.name		= "sh_mobile_ceu",
+	.id             = 0, /* "ceu0" clock */
+	.num_resources	= ARRAY_SIZE(ceu_resources),
+	.resource	= ceu_resources,
+	.dev		= {
+		.platform_data	= &sh_mobile_ceu_info,
+	},
+};
+
+static struct platform_device mackerel_camera = {
+	.name	= "soc-camera-pdrv",
+	.id	= 0,
+	.dev	= {
+		.platform_data = &camera_link,
+	},
+};
+
+static struct platform_device *mackerel_devices[] __initdata = {
+	&nor_flash_device,
+	&smc911x_device,
+	&lcdc_device,
+	&usb1_host_device,
+	&leds_device,
+	&fsi_device,
+	&fsi_ak4643_device,
+	&sdhi0_device,
+#if !defined(CONFIG_MMC_SH_MMCIF)
+	&sdhi1_device,
+#endif
+	&sdhi2_device,
+	&sh_mmcif_device,
+	&ceu_device,
+	&mackerel_camera,
+	&hdmi_lcdc_device,
+	&hdmi_device,
+};
+
+/* Keypad Initialization */
+#define KEYPAD_BUTTON(ev_type, ev_code, act_low) \
+{								\
+	.type		= ev_type,				\
+	.code		= ev_code,				\
+	.active_low	= act_low,				\
+}
+
+#define KEYPAD_BUTTON_LOW(event_code) KEYPAD_BUTTON(EV_KEY, event_code, 1)
+
+static struct tca6416_button mackerel_gpio_keys[] = {
+	KEYPAD_BUTTON_LOW(KEY_HOME),
+	KEYPAD_BUTTON_LOW(KEY_MENU),
+	KEYPAD_BUTTON_LOW(KEY_BACK),
+	KEYPAD_BUTTON_LOW(KEY_POWER),
+};
+
+static struct tca6416_keys_platform_data mackerel_tca6416_keys_info = {
+	.buttons	= mackerel_gpio_keys,
+	.nbuttons	= ARRAY_SIZE(mackerel_gpio_keys),
+	.rep		= 1,
+	.use_polling	= 0,
+	.pinmask	= 0x000F,
+};
+
+/* I2C */
+#define IRQ7 evt2irq(0x02e0)
+#define IRQ9 evt2irq(0x0320)
+
+static struct i2c_board_info i2c0_devices[] = {
+	{
+		I2C_BOARD_INFO("ak4643", 0x13),
+	},
+	/* Keypad */
+	{
+		I2C_BOARD_INFO("tca6408-keys", 0x20),
+		.platform_data = &mackerel_tca6416_keys_info,
+		.irq = IRQ9,
+	},
+	/* Touchscreen */
+	{
+		I2C_BOARD_INFO("st1232-ts", 0x55),
+		.irq = IRQ7,
+	},
+};
+
+#define IRQ21 evt2irq(0x32a0)
+
+static struct i2c_board_info i2c1_devices[] = {
+	/* Accelerometer */
+	{
+		I2C_BOARD_INFO("adxl34x", 0x53),
+		.irq = IRQ21,
+	},
+};
+
+static struct map_desc mackerel_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 mackerel_map_io(void)
+{
+	iotable_init(mackerel_io_desc, ARRAY_SIZE(mackerel_io_desc));
+
+	/* setup early devices and console here as well */
+	sh7372_add_early_devices();
+	shmobile_setup_console();
+}
+
+#define GPIO_PORT9CR	0xE6051009
+#define GPIO_PORT10CR	0xE605100A
+#define SRCR4		0xe61580bc
+#define USCCR1		0xE6058144
+static void __init mackerel_init(void)
+{
+	u32 srcr4;
+	struct clk *clk;
+
+	sh7372_pinmux_init();
+
+	/* enable SCIFA0 */
+	gpio_request(GPIO_FN_SCIFA0_TXD, NULL);
+	gpio_request(GPIO_FN_SCIFA0_RXD, NULL);
+
+	/* enable SMSC911X */
+	gpio_request(GPIO_FN_CS5A,	NULL);
+	gpio_request(GPIO_FN_IRQ6_39,	NULL);
+
+	/* LCDC */
+	gpio_request(GPIO_FN_LCDD23,   NULL);
+	gpio_request(GPIO_FN_LCDD22,   NULL);
+	gpio_request(GPIO_FN_LCDD21,   NULL);
+	gpio_request(GPIO_FN_LCDD20,   NULL);
+	gpio_request(GPIO_FN_LCDD19,   NULL);
+	gpio_request(GPIO_FN_LCDD18,   NULL);
+	gpio_request(GPIO_FN_LCDD17,   NULL);
+	gpio_request(GPIO_FN_LCDD16,   NULL);
+	gpio_request(GPIO_FN_LCDD15,   NULL);
+	gpio_request(GPIO_FN_LCDD14,   NULL);
+	gpio_request(GPIO_FN_LCDD13,   NULL);
+	gpio_request(GPIO_FN_LCDD12,   NULL);
+	gpio_request(GPIO_FN_LCDD11,   NULL);
+	gpio_request(GPIO_FN_LCDD10,   NULL);
+	gpio_request(GPIO_FN_LCDD9,    NULL);
+	gpio_request(GPIO_FN_LCDD8,    NULL);
+	gpio_request(GPIO_FN_LCDD7,    NULL);
+	gpio_request(GPIO_FN_LCDD6,    NULL);
+	gpio_request(GPIO_FN_LCDD5,    NULL);
+	gpio_request(GPIO_FN_LCDD4,    NULL);
+	gpio_request(GPIO_FN_LCDD3,    NULL);
+	gpio_request(GPIO_FN_LCDD2,    NULL);
+	gpio_request(GPIO_FN_LCDD1,    NULL);
+	gpio_request(GPIO_FN_LCDD0,    NULL);
+	gpio_request(GPIO_FN_LCDDISP,  NULL);
+	gpio_request(GPIO_FN_LCDDCK,   NULL);
+
+	gpio_request(GPIO_PORT31, NULL); /* backlight */
+	gpio_direction_output(GPIO_PORT31, 1);
+
+	gpio_request(GPIO_PORT151, NULL); /* LCDDON */
+	gpio_direction_output(GPIO_PORT151, 1);
+
+	/* USB enable */
+	gpio_request(GPIO_FN_VBUS0_1,    NULL);
+	gpio_request(GPIO_FN_IDIN_1_18,  NULL);
+	gpio_request(GPIO_FN_PWEN_1_115, NULL);
+	gpio_request(GPIO_FN_OVCN_1_114, NULL);
+	gpio_request(GPIO_FN_EXTLP_1,    NULL);
+	gpio_request(GPIO_FN_OVCN2_1,    NULL);
+
+	/* setup USB phy */
+	__raw_writew(0x8a0a, 0xE6058130);	/* USBCR4 */
+
+	/* enable FSI2 port A (ak4643) */
+	gpio_request(GPIO_FN_FSIAIBT,	NULL);
+	gpio_request(GPIO_FN_FSIAILR,	NULL);
+	gpio_request(GPIO_FN_FSIAISLD,	NULL);
+	gpio_request(GPIO_FN_FSIAOSLD,	NULL);
+	gpio_request(GPIO_PORT161,	NULL);
+	gpio_direction_output(GPIO_PORT161, 0); /* slave */
+
+	gpio_request(GPIO_PORT9,  NULL);
+	gpio_request(GPIO_PORT10, NULL);
+	gpio_no_direction(GPIO_PORT9CR);  /* FSIAOBT needs no direction */
+	gpio_no_direction(GPIO_PORT10CR); /* FSIAOLR needs no direction */
+
+	intc_set_priority(IRQ_FSI, 3); /* irq priority FSI(3) > SMSC911X(2) */
+
+	/* setup FSI2 port B (HDMI) */
+	gpio_request(GPIO_FN_FSIBCK, NULL);
+	__raw_writew(__raw_readw(USCCR1) & ~(1 << 6), USCCR1); /* use SPDIF */
+
+	/* set SPU2 clock to 119.6 MHz */
+	clk = clk_get(NULL, "spu_clk");
+	if (!IS_ERR(clk)) {
+		clk_set_rate(clk, clk_round_rate(clk, 119600000));
+		clk_put(clk);
+	}
+
+	/* enable Keypad */
+	gpio_request(GPIO_FN_IRQ9_42,	NULL);
+	set_irq_type(IRQ9, IRQ_TYPE_LEVEL_HIGH);
+
+	/* enable Touchscreen */
+	gpio_request(GPIO_FN_IRQ7_40,	NULL);
+	set_irq_type(IRQ7, IRQ_TYPE_LEVEL_LOW);
+
+	/* enable Accelerometer */
+	gpio_request(GPIO_FN_IRQ21,	NULL);
+	set_irq_type(IRQ21, IRQ_TYPE_LEVEL_HIGH);
+
+	/* enable SDHI0 */
+	gpio_request(GPIO_FN_SDHICD0, NULL);
+	gpio_request(GPIO_FN_SDHIWP0, NULL);
+	gpio_request(GPIO_FN_SDHICMD0, NULL);
+	gpio_request(GPIO_FN_SDHICLK0, NULL);
+	gpio_request(GPIO_FN_SDHID0_3, NULL);
+	gpio_request(GPIO_FN_SDHID0_2, NULL);
+	gpio_request(GPIO_FN_SDHID0_1, NULL);
+	gpio_request(GPIO_FN_SDHID0_0, NULL);
+
+#if !defined(CONFIG_MMC_SH_MMCIF)
+	/* enable SDHI1 */
+	gpio_request(GPIO_FN_SDHICMD1, NULL);
+	gpio_request(GPIO_FN_SDHICLK1, NULL);
+	gpio_request(GPIO_FN_SDHID1_3, NULL);
+	gpio_request(GPIO_FN_SDHID1_2, NULL);
+	gpio_request(GPIO_FN_SDHID1_1, NULL);
+	gpio_request(GPIO_FN_SDHID1_0, NULL);
+#endif
+	/* card detect pin for MMC slot (CN7) */
+	gpio_request(GPIO_PORT41, NULL);
+	gpio_direction_input(GPIO_PORT41);
+
+	/* enable SDHI2 */
+	gpio_request(GPIO_FN_SDHICMD2, NULL);
+	gpio_request(GPIO_FN_SDHICLK2, NULL);
+	gpio_request(GPIO_FN_SDHID2_3, NULL);
+	gpio_request(GPIO_FN_SDHID2_2, NULL);
+	gpio_request(GPIO_FN_SDHID2_1, NULL);
+	gpio_request(GPIO_FN_SDHID2_0, NULL);
+
+	/* card detect pin for microSD slot (CN23) */
+	gpio_request(GPIO_PORT162, NULL);
+	gpio_direction_input(GPIO_PORT162);
+
+	/* MMCIF */
+	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_FN_MMCCLK0, NULL);
+
+	/* enable GPS module (GT-720F) */
+	gpio_request(GPIO_FN_SCIFA2_TXD1, NULL);
+	gpio_request(GPIO_FN_SCIFA2_RXD1, NULL);
+
+	/* CEU */
+	gpio_request(GPIO_FN_VIO_CLK, NULL);
+	gpio_request(GPIO_FN_VIO_VD, NULL);
+	gpio_request(GPIO_FN_VIO_HD, NULL);
+	gpio_request(GPIO_FN_VIO_FIELD, NULL);
+	gpio_request(GPIO_FN_VIO_CKO, NULL);
+	gpio_request(GPIO_FN_VIO_D7, NULL);
+	gpio_request(GPIO_FN_VIO_D6, NULL);
+	gpio_request(GPIO_FN_VIO_D5, NULL);
+	gpio_request(GPIO_FN_VIO_D4, NULL);
+	gpio_request(GPIO_FN_VIO_D3, NULL);
+	gpio_request(GPIO_FN_VIO_D2, NULL);
+	gpio_request(GPIO_FN_VIO_D1, NULL);
+	gpio_request(GPIO_FN_VIO_D0, NULL);
+
+	/* HDMI */
+	gpio_request(GPIO_FN_HDMI_HPD, NULL);
+	gpio_request(GPIO_FN_HDMI_CEC, NULL);
+
+	/* Reset HDMI, must be held at least one EXTALR (32768Hz) period */
+	srcr4 = __raw_readl(SRCR4);
+	__raw_writel(srcr4 | (1 << 13), SRCR4);
+	udelay(50);
+	__raw_writel(srcr4 & ~(1 << 13), SRCR4);
+
+	i2c_register_board_info(0, i2c0_devices,
+				ARRAY_SIZE(i2c0_devices));
+	i2c_register_board_info(1, i2c1_devices,
+				ARRAY_SIZE(i2c1_devices));
+
+	sh7372_add_standard_devices();
+
+	platform_add_devices(mackerel_devices, ARRAY_SIZE(mackerel_devices));
+}
+
+static void __init mackerel_timer_init(void)
+{
+	sh7372_clock_init();
+	shmobile_timer.init();
+
+	/* External clock source */
+	clk_set_rate(&sh7372_dv_clki_clk, 27000000);
+}
+
+static struct sys_timer mackerel_timer = {
+	.init		= mackerel_timer_init,
+};
+
+MACHINE_START(MACKEREL, "mackerel")
+	.map_io		= mackerel_map_io,
+	.init_irq	= sh7372_init_irq,
+	.handle_irq	= shmobile_handle_irq_intc,
+	.init_machine	= mackerel_init,
+	.timer		= &mackerel_timer,
+MACHINE_END
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-shmobile/clock-sh7367.c linux-libre-2.6.38-gnu1/arch/arm/mach-shmobile/clock-sh7367.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-shmobile/clock-sh7367.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-shmobile/clock-sh7367.c	2011-03-14 21:20:32.000000000 -0400
@@ -20,8 +20,8 @@
 #include <linux/kernel.h>
 #include <linux/io.h>
 #include <linux/sh_clk.h>
+#include <linux/clkdev.h>
 #include <mach/common.h>
-#include <asm/clkdev.h>
 
 /* SH7367 registers */
 #define RTFRQCR    0xe6150000
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-shmobile/clock-sh7372.c linux-libre-2.6.38-gnu1/arch/arm/mach-shmobile/clock-sh7372.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-shmobile/clock-sh7372.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-shmobile/clock-sh7372.c	2011-03-14 21:20:32.000000000 -0400
@@ -20,8 +20,8 @@
 #include <linux/kernel.h>
 #include <linux/io.h>
 #include <linux/sh_clk.h>
+#include <linux/clkdev.h>
 #include <mach/common.h>
-#include <asm/clkdev.h>
 
 /* SH7372 registers */
 #define FRQCRA		0xe6150000
@@ -234,7 +234,9 @@ static int pllc2_set_rate(struct clk *cl
 
 	value = __raw_readl(PLLC2CR) & ~(0x3f << 24);
 
-	__raw_writel((value & ~0x80000000) | ((idx + 19) << 24), PLLC2CR);
+	__raw_writel(value | ((idx + 19) << 24), PLLC2CR);
+
+	clk->rate = clk->freq_table[idx].frequency;
 
 	return 0;
 }
@@ -507,7 +509,7 @@ enum { MSTP001,
        MSTP223,
        MSTP207, MSTP206, MSTP204, MSTP203, MSTP202, MSTP201, MSTP200,
        MSTP329, MSTP328, MSTP323, MSTP322, MSTP314, MSTP313, MSTP312,
-       MSTP415, MSTP413, MSTP411, MSTP410, MSTP406, MSTP403,
+       MSTP423, MSTP415, MSTP413, MSTP411, MSTP410, MSTP406, MSTP403,
        MSTP_NR };
 
 #define MSTP(_parent, _reg, _bit, _flags) \
@@ -543,6 +545,7 @@ static struct clk mstp_clks[MSTP_NR] = {
 	[MSTP314] = MSTP(&div4_clks[DIV4_HP], SMSTPCR3, 14, 0), /* SDHI0 */
 	[MSTP313] = MSTP(&div4_clks[DIV4_HP], SMSTPCR3, 13, 0), /* SDHI1 */
 	[MSTP312] = MSTP(&div4_clks[DIV4_HP], SMSTPCR3, 12, 0), /* MMC */
+	[MSTP423] = MSTP(&div4_clks[DIV4_B], SMSTPCR4, 23, 0), /* DSITX1 */
 	[MSTP415] = MSTP(&div4_clks[DIV4_HP], SMSTPCR4, 15, 0), /* SDHI2 */
 	[MSTP413] = MSTP(&pllc1_div2_clk, SMSTPCR4, 13, 0), /* HDMI */
 	[MSTP411] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR4, 11, 0), /* IIC3 */
@@ -596,9 +599,10 @@ static struct clk_lookup lookups[] = {
 	CLKDEV_CON_ID("spu_clk", &div6_clks[DIV6_SPU]),
 	CLKDEV_CON_ID("vou_clk", &div6_clks[DIV6_VOU]),
 	CLKDEV_CON_ID("hdmi_clk", &div6_reparent_clks[DIV6_HDMI]),
-	CLKDEV_CON_ID("dsit_clk", &div6_clks[DIV6_DSIT]),
-	CLKDEV_CON_ID("dsi0p_clk", &div6_clks[DIV6_DSI0P]),
-	CLKDEV_CON_ID("dsi1p_clk", &div6_clks[DIV6_DSI1P]),
+	CLKDEV_ICK_ID("dsit_clk", "sh-mipi-dsi.0", &div6_clks[DIV6_DSIT]),
+	CLKDEV_ICK_ID("dsit_clk", "sh-mipi-dsi.1", &div6_clks[DIV6_DSIT]),
+	CLKDEV_ICK_ID("dsi0p_clk", "sh-mipi-dsi.0", &div6_clks[DIV6_DSI0P]),
+	CLKDEV_ICK_ID("dsi1p_clk", "sh-mipi-dsi.1", &div6_clks[DIV6_DSI1P]),
 
 	/* MSTP32 clocks */
 	CLKDEV_DEV_ID("i2c-sh_mobile.2", &mstp_clks[MSTP001]), /* IIC2 */
@@ -610,7 +614,7 @@ static struct clk_lookup lookups[] = {
 	CLKDEV_DEV_ID("sh-mobile-csi2.0", &mstp_clks[MSTP126]), /* CSI2 */
 	CLKDEV_DEV_ID("sh_tmu.0", &mstp_clks[MSTP125]), /* TMU00 */
 	CLKDEV_DEV_ID("sh_tmu.1", &mstp_clks[MSTP125]), /* TMU01 */
-	CLKDEV_DEV_ID("sh-mipi-dsi.0", &mstp_clks[MSTP118]), /* DSITX */
+	CLKDEV_DEV_ID("sh-mipi-dsi.0", &mstp_clks[MSTP118]), /* DSITX0 */
 	CLKDEV_DEV_ID("sh_mobile_lcdc_fb.1", &mstp_clks[MSTP117]), /* LCDC1 */
 	CLKDEV_DEV_ID("i2c-sh_mobile.0", &mstp_clks[MSTP116]), /* IIC0 */
 	CLKDEV_DEV_ID("uio_pdrv_genirq.5", &mstp_clks[MSTP106]), /* JPU */
@@ -633,6 +637,7 @@ static struct clk_lookup lookups[] = {
 	CLKDEV_DEV_ID("sh_mobile_sdhi.0", &mstp_clks[MSTP314]), /* SDHI0 */
 	CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[MSTP313]), /* SDHI1 */
 	CLKDEV_DEV_ID("sh_mmcif.0", &mstp_clks[MSTP312]), /* MMC */
+	CLKDEV_DEV_ID("sh-mipi-dsi.1", &mstp_clks[MSTP423]), /* DSITX1 */
 	CLKDEV_DEV_ID("sh_mobile_sdhi.2", &mstp_clks[MSTP415]), /* SDHI2 */
 	CLKDEV_DEV_ID("sh-mobile-hdmi", &mstp_clks[MSTP413]), /* HDMI */
 	CLKDEV_DEV_ID("i2c-sh_mobile.3", &mstp_clks[MSTP411]), /* IIC3 */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-shmobile/clock-sh7377.c linux-libre-2.6.38-gnu1/arch/arm/mach-shmobile/clock-sh7377.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-shmobile/clock-sh7377.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-shmobile/clock-sh7377.c	2011-03-14 21:20:32.000000000 -0400
@@ -20,8 +20,8 @@
 #include <linux/kernel.h>
 #include <linux/io.h>
 #include <linux/sh_clk.h>
+#include <linux/clkdev.h>
 #include <mach/common.h>
-#include <asm/clkdev.h>
 
 /* SH7377 registers */
 #define RTFRQCR    0xe6150000
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-shmobile/clock-sh73a0.c linux-libre-2.6.38-gnu1/arch/arm/mach-shmobile/clock-sh73a0.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-shmobile/clock-sh73a0.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-shmobile/clock-sh73a0.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,388 @@
+/*
+ * sh73a0 clock framework support
+ *
+ * Copyright (C) 2010 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/init.h>
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/sh_clk.h>
+#include <linux/clkdev.h>
+#include <mach/common.h>
+
+#define FRQCRA		0xe6150000
+#define FRQCRB		0xe6150004
+#define FRQCRD		0xe61500e4
+#define VCLKCR1		0xe6150008
+#define VCLKCR2		0xe615000C
+#define VCLKCR3		0xe615001C
+#define ZBCKCR		0xe6150010
+#define FLCKCR		0xe6150014
+#define SD0CKCR		0xe6150074
+#define SD1CKCR		0xe6150078
+#define SD2CKCR		0xe615007C
+#define FSIACKCR	0xe6150018
+#define FSIBCKCR	0xe6150090
+#define SUBCKCR		0xe6150080
+#define SPUACKCR	0xe6150084
+#define SPUVCKCR	0xe6150094
+#define MSUCKCR		0xe6150088
+#define HSICKCR		0xe615008C
+#define MFCK1CR		0xe6150098
+#define MFCK2CR		0xe615009C
+#define DSITCKCR	0xe6150060
+#define DSI0PCKCR	0xe6150064
+#define DSI1PCKCR	0xe6150068
+#define DSI0PHYCR	0xe615006C
+#define DSI1PHYCR	0xe6150070
+#define PLLECR		0xe61500d0
+#define PLL0CR		0xe61500d8
+#define PLL1CR		0xe6150028
+#define PLL2CR		0xe615002c
+#define PLL3CR		0xe61500dc
+#define SMSTPCR0	0xe6150130
+#define SMSTPCR1	0xe6150134
+#define SMSTPCR2	0xe6150138
+#define SMSTPCR3	0xe615013c
+#define SMSTPCR4	0xe6150140
+#define SMSTPCR5	0xe6150144
+#define CKSCR		0xe61500c0
+
+/* Fixed 32 KHz root clock from EXTALR pin */
+static struct clk r_clk = {
+	.rate           = 32768,
+};
+
+/*
+ * 26MHz default rate for the EXTAL1 root input clock.
+ * If needed, reset this with clk_set_rate() from the platform code.
+ */
+struct clk sh73a0_extal1_clk = {
+	.rate		= 26000000,
+};
+
+/*
+ * 48MHz default rate for the EXTAL2 root input clock.
+ * If needed, reset this with clk_set_rate() from the platform code.
+ */
+struct clk sh73a0_extal2_clk = {
+	.rate		= 48000000,
+};
+
+/* A fixed divide-by-2 block */
+static unsigned long div2_recalc(struct clk *clk)
+{
+	return clk->parent->rate / 2;
+}
+
+static struct clk_ops div2_clk_ops = {
+	.recalc		= div2_recalc,
+};
+
+/* Divide extal1 by two */
+static struct clk extal1_div2_clk = {
+	.ops		= &div2_clk_ops,
+	.parent		= &sh73a0_extal1_clk,
+};
+
+/* Divide extal2 by two */
+static struct clk extal2_div2_clk = {
+	.ops		= &div2_clk_ops,
+	.parent		= &sh73a0_extal2_clk,
+};
+
+static struct clk_ops main_clk_ops = {
+	.recalc		= followparent_recalc,
+};
+
+/* Main clock */
+static struct clk main_clk = {
+	.ops		= &main_clk_ops,
+};
+
+/* PLL0, PLL1, PLL2, PLL3 */
+static unsigned long pll_recalc(struct clk *clk)
+{
+	unsigned long mult = 1;
+
+	if (__raw_readl(PLLECR) & (1 << clk->enable_bit)) {
+		mult = (((__raw_readl(clk->enable_reg) >> 24) & 0x3f) + 1);
+		/* handle CFG bit for PLL1 and PLL2 */
+		switch (clk->enable_bit) {
+		case 1:
+		case 2:
+			if (__raw_readl(clk->enable_reg) & (1 << 20))
+				mult *= 2;
+		}
+	}
+
+	return clk->parent->rate * mult;
+}
+
+static struct clk_ops pll_clk_ops = {
+	.recalc		= pll_recalc,
+};
+
+static struct clk pll0_clk = {
+	.ops		= &pll_clk_ops,
+	.flags		= CLK_ENABLE_ON_INIT,
+	.parent		= &main_clk,
+	.enable_reg	= (void __iomem *)PLL0CR,
+	.enable_bit	= 0,
+};
+
+static struct clk pll1_clk = {
+	.ops		= &pll_clk_ops,
+	.flags		= CLK_ENABLE_ON_INIT,
+	.parent		= &main_clk,
+	.enable_reg	= (void __iomem *)PLL1CR,
+	.enable_bit	= 1,
+};
+
+static struct clk pll2_clk = {
+	.ops		= &pll_clk_ops,
+	.flags		= CLK_ENABLE_ON_INIT,
+	.parent		= &main_clk,
+	.enable_reg	= (void __iomem *)PLL2CR,
+	.enable_bit	= 2,
+};
+
+static struct clk pll3_clk = {
+	.ops		= &pll_clk_ops,
+	.flags		= CLK_ENABLE_ON_INIT,
+	.parent		= &main_clk,
+	.enable_reg	= (void __iomem *)PLL3CR,
+	.enable_bit	= 3,
+};
+
+/* Divide PLL1 by two */
+static struct clk pll1_div2_clk = {
+	.ops		= &div2_clk_ops,
+	.parent		= &pll1_clk,
+};
+
+static struct clk *main_clks[] = {
+	&r_clk,
+	&sh73a0_extal1_clk,
+	&sh73a0_extal2_clk,
+	&extal1_div2_clk,
+	&extal2_div2_clk,
+	&main_clk,
+	&pll0_clk,
+	&pll1_clk,
+	&pll2_clk,
+	&pll3_clk,
+	&pll1_div2_clk,
+};
+
+static void div4_kick(struct clk *clk)
+{
+	unsigned long value;
+
+	/* set KICK bit in FRQCRB to update hardware setting */
+	value = __raw_readl(FRQCRB);
+	value |= (1 << 31);
+	__raw_writel(value, FRQCRB);
+}
+
+static int divisors[] = { 2, 3, 4, 6, 8, 12, 16, 18,
+			  24, 0, 36, 48, 7 };
+
+static struct clk_div_mult_table div4_div_mult_table = {
+	.divisors = divisors,
+	.nr_divisors = ARRAY_SIZE(divisors),
+};
+
+static struct clk_div4_table div4_table = {
+	.div_mult_table = &div4_div_mult_table,
+	.kick = div4_kick,
+};
+
+enum { DIV4_I, DIV4_ZG, DIV4_M3, DIV4_B, DIV4_M1, DIV4_M2,
+	DIV4_Z, DIV4_ZTR, DIV4_ZT, DIV4_ZX, DIV4_HP, DIV4_NR };
+
+#define DIV4(_reg, _bit, _mask, _flags) \
+	SH_CLK_DIV4(&pll1_clk, _reg, _bit, _mask, _flags)
+
+static struct clk div4_clks[DIV4_NR] = {
+	[DIV4_I] = DIV4(FRQCRA, 20, 0xfff, CLK_ENABLE_ON_INIT),
+	[DIV4_ZG] = DIV4(FRQCRA, 16, 0xbff, CLK_ENABLE_ON_INIT),
+	[DIV4_M3] = DIV4(FRQCRA, 12, 0xfff, CLK_ENABLE_ON_INIT),
+	[DIV4_B] = DIV4(FRQCRA, 8, 0xfff, CLK_ENABLE_ON_INIT),
+	[DIV4_M1] = DIV4(FRQCRA, 4, 0xfff, 0),
+	[DIV4_M2] = DIV4(FRQCRA, 0, 0xfff, 0),
+	[DIV4_Z] = DIV4(FRQCRB, 24, 0xbff, 0),
+	[DIV4_ZTR] = DIV4(FRQCRB, 20, 0xfff, 0),
+	[DIV4_ZT] = DIV4(FRQCRB, 16, 0xfff, 0),
+	[DIV4_ZX] = DIV4(FRQCRB, 12, 0xfff, 0),
+	[DIV4_HP] = DIV4(FRQCRB, 4, 0xfff, 0),
+};
+
+enum { DIV6_VCK1, DIV6_VCK2, DIV6_VCK3, DIV6_ZB1,
+	DIV6_FLCTL, DIV6_SDHI0, DIV6_SDHI1, DIV6_SDHI2,
+	DIV6_FSIA, DIV6_FSIB, DIV6_SUB,
+	DIV6_SPUA, DIV6_SPUV, DIV6_MSU,
+	DIV6_HSI,  DIV6_MFG1, DIV6_MFG2,
+	DIV6_DSIT, DIV6_DSI0P, DIV6_DSI1P,
+	DIV6_NR };
+
+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_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),
+	[DIV6_SDHI2] = SH_CLK_DIV6(&pll1_div2_clk, SD2CKCR, 0),
+	[DIV6_FSIA] = SH_CLK_DIV6(&pll1_div2_clk, FSIACKCR, 0),
+	[DIV6_FSIB] = SH_CLK_DIV6(&pll1_div2_clk, FSIBCKCR, 0),
+	[DIV6_SUB] = SH_CLK_DIV6(&sh73a0_extal2_clk, SUBCKCR, 0),
+	[DIV6_SPUA] = SH_CLK_DIV6(&pll1_div2_clk, SPUACKCR, 0),
+	[DIV6_SPUV] = SH_CLK_DIV6(&pll1_div2_clk, SPUVCKCR, 0),
+	[DIV6_MSU] = SH_CLK_DIV6(&pll1_div2_clk, MSUCKCR, 0),
+	[DIV6_HSI] = SH_CLK_DIV6(&pll1_div2_clk, HSICKCR, 0),
+	[DIV6_MFG1] = SH_CLK_DIV6(&pll1_div2_clk, MFCK1CR, 0),
+	[DIV6_MFG2] = SH_CLK_DIV6(&pll1_div2_clk, MFCK2CR, 0),
+	[DIV6_DSIT] = SH_CLK_DIV6(&pll1_div2_clk, DSITCKCR, 0),
+	[DIV6_DSI0P] = SH_CLK_DIV6(&pll1_div2_clk, DSI0PCKCR, 0),
+	[DIV6_DSI1P] = SH_CLK_DIV6(&pll1_div2_clk, DSI1PCKCR, 0),
+};
+
+enum { MSTP001,
+	MSTP129, MSTP128, MSTP127, MSTP126, MSTP125, MSTP118, MSTP116, MSTP100,
+	MSTP219,
+	MSTP207, MSTP206, MSTP204, MSTP203, MSTP202, MSTP201, MSTP200,
+	MSTP331, MSTP329, MSTP325, MSTP323, MSTP312,
+	MSTP411, MSTP410, MSTP403,
+	MSTP_NR };
+
+#define MSTP(_parent, _reg, _bit, _flags) \
+	SH_CLK_MSTP32(_parent, _reg, _bit, _flags)
+
+static struct clk mstp_clks[MSTP_NR] = {
+	[MSTP001] = MSTP(&div4_clks[DIV4_HP], SMSTPCR0, 1, 0), /* IIC2 */
+	[MSTP129] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 29, 0), /* CEU1 */
+	[MSTP128] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 28, 0), /* CSI2-RX1 */
+	[MSTP127] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 27, 0), /* CEU0 */
+	[MSTP126] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 26, 0), /* CSI2-RX0 */
+	[MSTP125] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR1, 25, 0), /* TMU0 */
+	[MSTP118] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 18, 0), /* DSITX0 */
+	[MSTP116] = MSTP(&div4_clks[DIV4_HP], SMSTPCR1, 16, 0), /* IIC0 */
+	[MSTP100] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 0, 0), /* LCDC0 */
+	[MSTP219] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 19, 0), /* SCIFA7 */
+	[MSTP207] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 7, 0), /* SCIFA5 */
+	[MSTP206] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 6, 0), /* SCIFB */
+	[MSTP204] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 4, 0), /* SCIFA0 */
+	[MSTP203] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 3, 0), /* SCIFA1 */
+	[MSTP202] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 2, 0), /* SCIFA2 */
+	[MSTP201] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 1, 0), /* SCIFA3 */
+	[MSTP200] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 0, 0), /* SCIFA4 */
+	[MSTP331] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR3, 31, 0), /* SCIFA6 */
+	[MSTP329] = MSTP(&r_clk, SMSTPCR3, 29, 0), /* CMT10 */
+	[MSTP325] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR3, 25, 0), /* IrDA */
+	[MSTP323] = MSTP(&div4_clks[DIV4_HP], SMSTPCR3, 23, 0), /* IIC1 */
+	[MSTP312] = MSTP(&div4_clks[DIV4_HP], SMSTPCR3, 12, 0), /* MMCIF0 */
+	[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 */
+};
+
+#define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk }
+#define CLKDEV_DEV_ID(_id, _clk) { .dev_id = _id, .clk = _clk }
+#define CLKDEV_ICK_ID(_cid, _did, _clk) { .con_id = _cid, .dev_id = _did, .clk = _clk }
+
+static struct clk_lookup lookups[] = {
+	/* main clocks */
+	CLKDEV_CON_ID("r_clk", &r_clk),
+
+	/* DIV6 clocks */
+	CLKDEV_CON_ID("vck1_clk", &div6_clks[DIV6_VCK1]),
+	CLKDEV_CON_ID("vck2_clk", &div6_clks[DIV6_VCK2]),
+	CLKDEV_CON_ID("vck3_clk", &div6_clks[DIV6_VCK3]),
+	CLKDEV_ICK_ID("dsit_clk", "sh-mipi-dsi.0", &div6_clks[DIV6_DSIT]),
+	CLKDEV_ICK_ID("dsit_clk", "sh-mipi-dsi.1", &div6_clks[DIV6_DSIT]),
+	CLKDEV_ICK_ID("dsi0p_clk", "sh-mipi-dsi.0", &div6_clks[DIV6_DSI0P]),
+	CLKDEV_ICK_ID("dsi1p_clk", "sh-mipi-dsi.1", &div6_clks[DIV6_DSI1P]),
+
+	/* MSTP32 clocks */
+	CLKDEV_DEV_ID("i2c-sh_mobile.2", &mstp_clks[MSTP001]), /* I2C2 */
+	CLKDEV_DEV_ID("sh_mobile_ceu.1", &mstp_clks[MSTP129]), /* CEU1 */
+	CLKDEV_DEV_ID("sh-mobile-csi2.1", &mstp_clks[MSTP128]), /* CSI2-RX1 */
+	CLKDEV_DEV_ID("sh_mobile_ceu.0", &mstp_clks[MSTP127]), /* CEU0 */
+	CLKDEV_DEV_ID("sh-mobile-csi2.0", &mstp_clks[MSTP126]), /* CSI2-RX0 */
+	CLKDEV_DEV_ID("sh_tmu.0", &mstp_clks[MSTP125]), /* TMU00 */
+	CLKDEV_DEV_ID("sh_tmu.1", &mstp_clks[MSTP125]), /* TMU01 */
+	CLKDEV_DEV_ID("sh-mipi-dsi.0", &mstp_clks[MSTP118]), /* DSITX */
+	CLKDEV_DEV_ID("i2c-sh_mobile.0", &mstp_clks[MSTP116]), /* I2C0 */
+	CLKDEV_DEV_ID("sh_mobile_lcdc_fb.0", &mstp_clks[MSTP100]), /* LCDC0 */
+	CLKDEV_DEV_ID("sh-sci.7", &mstp_clks[MSTP219]), /* SCIFA7 */
+	CLKDEV_DEV_ID("sh-sci.5", &mstp_clks[MSTP207]), /* SCIFA5 */
+	CLKDEV_DEV_ID("sh-sci.8", &mstp_clks[MSTP206]), /* SCIFB */
+	CLKDEV_DEV_ID("sh-sci.0", &mstp_clks[MSTP204]), /* SCIFA0 */
+	CLKDEV_DEV_ID("sh-sci.1", &mstp_clks[MSTP203]), /* SCIFA1 */
+	CLKDEV_DEV_ID("sh-sci.2", &mstp_clks[MSTP202]), /* SCIFA2 */
+	CLKDEV_DEV_ID("sh-sci.3", &mstp_clks[MSTP201]), /* SCIFA3 */
+	CLKDEV_DEV_ID("sh-sci.4", &mstp_clks[MSTP200]), /* SCIFA4 */
+	CLKDEV_DEV_ID("sh-sci.6", &mstp_clks[MSTP331]), /* SCIFA6 */
+	CLKDEV_DEV_ID("sh_cmt.10", &mstp_clks[MSTP329]), /* CMT10 */
+	CLKDEV_DEV_ID("sh_irda.0", &mstp_clks[MSTP325]), /* IrDA */
+	CLKDEV_DEV_ID("i2c-sh_mobile.1", &mstp_clks[MSTP323]), /* I2C1 */
+	CLKDEV_DEV_ID("sh_mmcif.0", &mstp_clks[MSTP312]), /* MMCIF0 */
+	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 */
+};
+
+void __init sh73a0_clock_init(void)
+{
+	int k, ret = 0;
+
+	/* detect main clock parent */
+	switch ((__raw_readl(CKSCR) >> 24) & 0x03) {
+	case 0:
+		main_clk.parent = &sh73a0_extal1_clk;
+		break;
+	case 1:
+		main_clk.parent = &extal1_div2_clk;
+		break;
+	case 2:
+		main_clk.parent = &sh73a0_extal2_clk;
+		break;
+	case 3:
+		main_clk.parent = &extal2_div2_clk;
+		break;
+	}
+
+	for (k = 0; !ret && (k < ARRAY_SIZE(main_clks)); k++)
+		ret = clk_register(main_clks[k]);
+
+	if (!ret)
+		ret = sh_clk_div4_register(div4_clks, DIV4_NR, &div4_table);
+
+	if (!ret)
+		ret = sh_clk_div6_register(div6_clks, DIV6_NR);
+
+	if (!ret)
+		ret = sh_clk_mstp32_register(mstp_clks, MSTP_NR);
+
+	clkdev_add_table(lookups, ARRAY_SIZE(lookups));
+
+	if (!ret)
+		clk_init();
+	else
+		panic("failed to setup sh73a0 clocks\n");
+}
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-shmobile/entry-gic.S linux-libre-2.6.38-gnu1/arch/arm/mach-shmobile/entry-gic.S
--- linux-libre-2.6.37-gnu1/arch/arm/mach-shmobile/entry-gic.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-shmobile/entry-gic.S	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,18 @@
+/*
+ * ARM Interrupt demux handler using GIC
+ *
+ * Copyright (C) 2010 Magnus Damm
+ * Copyright (C) 2011 Paul Mundt
+ * Copyright (C) 2010 - 2011 Renesas Solutions Corp.
+ *
+ * This file is licensed under  the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <asm/assembler.h>
+#include <asm/entry-macro-multi.S>
+#include <asm/hardware/gic.h>
+#include <asm/hardware/entry-macro-gic.S>
+
+	arch_irq_handler shmobile_handle_irq_gic
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-shmobile/entry-intc.S linux-libre-2.6.38-gnu1/arch/arm/mach-shmobile/entry-intc.S
--- linux-libre-2.6.37-gnu1/arch/arm/mach-shmobile/entry-intc.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-shmobile/entry-intc.S	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,57 @@
+/*
+ * ARM Interrupt demux handler using INTC
+ *
+ * Copyright (C) 2010 Magnus Damm
+ * Copyright (C) 2008 Renesas Solutions Corp.
+ *
+ * This file is licensed under  the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <asm/entry-macro-multi.S>
+
+#define INTCA_BASE	0xe6980000
+#define INTFLGA_OFFS	0x00000018 /* accept pending interrupt */
+#define INTEVTA_OFFS	0x00000020 /* vector number of accepted interrupt */
+#define INTLVLA_OFFS	0x00000030 /* priority level of accepted interrupt */
+#define INTLVLB_OFFS	0x00000034 /* previous priority level */
+
+	.macro  get_irqnr_preamble, base, tmp
+	ldr     \base, =INTCA_BASE
+	.endm
+
+	.macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
+	/* The single INTFLGA read access below results in the following:
+	 *
+	 * 1. INTLVLB is updated with old priority value from INTLVLA
+	 * 2. Highest priority interrupt is accepted
+	 * 3. INTLVLA is updated to contain priority of accepted interrupt
+	 * 4. Accepted interrupt vector is stored in INTFLGA and INTEVTA
+	 */
+	ldr     \irqnr, [\base, #INTFLGA_OFFS]
+
+	/* Restore INTLVLA with the value saved in INTLVLB.
+	 * This is required to support interrupt priorities properly.
+	 */
+	ldrb	\tmp, [\base, #INTLVLB_OFFS]
+	strb    \tmp, [\base, #INTLVLA_OFFS]
+
+	/* Handle invalid vector number case */
+	cmp	\irqnr, #0
+	beq	1000f
+
+	/* Convert vector to irq number, same as the evt2irq() macro */
+	lsr	\irqnr, \irqnr, #0x5
+	subs	\irqnr, \irqnr, #16
+
+1000:
+	.endm
+
+	.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-2.6.37-gnu1/arch/arm/mach-shmobile/headsmp.S linux-libre-2.6.38-gnu1/arch/arm/mach-shmobile/headsmp.S
--- linux-libre-2.6.37-gnu1/arch/arm/mach-shmobile/headsmp.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-shmobile/headsmp.S	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,27 @@
+/*
+ * SMP support for R-Mobile / SH-Mobile
+ *
+ * Copyright (C) 2010  Magnus Damm
+ * Copyright (C) 2010  Takashi Yoshii
+ *
+ * Based on vexpress, 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>
+#include <asm/memory.h>
+
+	__INIT
+
+/*
+ * Reset vector for secondary CPUs.
+ * This will be mapped at address 0 by SBAR register.
+ * We need _long_ jump to the physical address.
+ */
+	.align  12
+ENTRY(shmobile_secondary_vector)
+	ldr     pc, 1f
+1:	.long   secondary_startup - PAGE_OFFSET + PHYS_OFFSET
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-shmobile/hotplug.c linux-libre-2.6.38-gnu1/arch/arm/mach-shmobile/hotplug.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-shmobile/hotplug.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-shmobile/hotplug.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,41 @@
+/*
+ * SMP support for R-Mobile / SH-Mobile
+ *
+ * Copyright (C) 2010  Magnus Damm
+ *
+ * Based on realview, 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>
+
+int platform_cpu_kill(unsigned int cpu)
+{
+	return 1;
+}
+
+void platform_cpu_die(unsigned int cpu)
+{
+	while (1) {
+		/*
+		 * here's the WFI
+		 */
+		asm(".word	0xe320f003\n"
+		    :
+		    :
+		    : "memory", "cc");
+	}
+}
+
+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-2.6.37-gnu1/arch/arm/mach-shmobile/include/mach/common.h linux-libre-2.6.38-gnu1/arch/arm/mach-shmobile/include/mach/common.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-shmobile/include/mach/common.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-shmobile/include/mach/common.h	2011-03-14 21:20:32.000000000 -0400
@@ -3,8 +3,11 @@
 
 extern struct sys_timer shmobile_timer;
 extern void shmobile_setup_console(void);
+extern void shmobile_secondary_vector(void);
 struct clk;
 extern int clk_init(void);
+extern void shmobile_handle_irq_intc(struct pt_regs *);
+extern void shmobile_handle_irq_gic(struct pt_regs *);
 
 extern void sh7367_init_irq(void);
 extern void sh7367_add_early_devices(void);
@@ -30,4 +33,17 @@ extern void sh7372_pinmux_init(void);
 extern struct clk sh7372_extal1_clk;
 extern struct clk sh7372_extal2_clk;
 
+extern void sh73a0_init_irq(void);
+extern void sh73a0_add_early_devices(void);
+extern void sh73a0_add_standard_devices(void);
+extern void sh73a0_clock_init(void);
+extern void sh73a0_pinmux_init(void);
+extern struct clk sh73a0_extal1_clk;
+extern struct clk sh73a0_extal2_clk;
+
+extern unsigned int sh73a0_get_core_count(void);
+extern void sh73a0_secondary_init(unsigned int cpu);
+extern int sh73a0_boot_secondary(unsigned int cpu);
+extern void sh73a0_smp_prepare_cpus(void);
+
 #endif /* __ARCH_MACH_COMMON_H */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-shmobile/include/mach/entry-macro.S linux-libre-2.6.38-gnu1/arch/arm/mach-shmobile/include/mach/entry-macro.S
--- linux-libre-2.6.37-gnu1/arch/arm/mach-shmobile/include/mach/entry-macro.S	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-shmobile/include/mach/entry-macro.S	2011-03-14 21:20:32.000000000 -0400
@@ -1,6 +1,5 @@
 /*
- * Copyright (C) 2010 Magnus Damm
- * Copyright (C) 2008 Renesas Solutions Corp.
+ * Copyright (C) 2010  Paul Mundt
  *
  * 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
@@ -15,47 +14,21 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
-#include <mach/irqs.h>
-
-#define INTCA_BASE	0xe6980000
-#define INTFLGA_OFFS	0x00000018 /* accept pending interrupt */
-#define INTEVTA_OFFS	0x00000020 /* vector number of accepted interrupt */
-#define INTLVLA_OFFS	0x00000030 /* priority level of accepted interrupt */
-#define INTLVLB_OFFS	0x00000034 /* previous priority level */
 
 	.macro  disable_fiq
 	.endm
 
 	.macro  get_irqnr_preamble, base, tmp
-	ldr     \base, =INTCA_BASE
-	.endm
-
-	.macro  arch_ret_to_user, tmp1, tmp2
 	.endm
 
 	.macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
-	/* The single INTFLGA read access below results in the following:
-	 *
-	 * 1. INTLVLB is updated with old priority value from INTLVLA
-	 * 2. Highest priority interrupt is accepted
-	 * 3. INTLVLA is updated to contain priority of accepted interrupt
-	 * 4. Accepted interrupt vector is stored in INTFLGA and INTEVTA
-	 */
-	ldr     \irqnr, [\base, #INTFLGA_OFFS]
-
-	/* Restore INTLVLA with the value saved in INTLVLB.
-	 * This is required to support interrupt priorities properly.
-	 */
-	ldrb	\tmp, [\base, #INTLVLB_OFFS]
-	strb    \tmp, [\base, #INTLVLA_OFFS]
+	.endm
 
-	/* Handle invalid vector number case */
-	cmp	\irqnr, #0
-	beq	1000f
+	.macro  test_for_ipi, irqnr, irqstat, base, tmp
+	.endm
 
-	/* Convert vector to irq number, same as the evt2irq() macro */
-	lsr	\irqnr, \irqnr, #0x5
-	subs	\irqnr, \irqnr, #16
+	.macro  test_for_ltirq, irqnr, irqstat, base, tmp
+	.endm
 
-1000:
+	.macro  arch_ret_to_user, tmp1, tmp2
 	.endm
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-shmobile/include/mach/hardware.h linux-libre-2.6.38-gnu1/arch/arm/mach-shmobile/include/mach/hardware.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-shmobile/include/mach/hardware.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-shmobile/include/mach/hardware.h	2011-03-14 21:20:32.000000000 -0400
@@ -1,7 +1,4 @@
 #ifndef __ASM_MACH_HARDWARE_H
 #define __ASM_MACH_HARDWARE_H
 
-/* INTFLGA register - used by low level interrupt code in entry-macro.S */
-#define INTFLGA			0xe6980018
-
 #endif /* __ASM_MACH_HARDWARE_H */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-shmobile/include/mach/head-ap4evb.txt linux-libre-2.6.38-gnu1/arch/arm/mach-shmobile/include/mach/head-ap4evb.txt
--- linux-libre-2.6.37-gnu1/arch/arm/mach-shmobile/include/mach/head-ap4evb.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-shmobile/include/mach/head-ap4evb.txt	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,94 @@
+LIST "partner-jet-setup.txt"
+LIST "(C) Copyright 2010 Renesas Solutions Corp"
+LIST "Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>"
+
+LIST "RWT Setting"
+EW 0xE6020004, 0xA500
+EW 0xE6030004, 0xA500
+
+LIST "GPIO Setting"
+EB 0xE6051013, 0xA2
+
+LIST "CPG"
+ED 0xE61500C0, 0x00000002
+
+WAIT 1, 0xFE40009C
+
+LIST "FRQCR"
+ED 0xE6150000, 0x2D1305C3
+ED 0xE61500E0, 0x9E40358E
+ED 0xE6150004, 0x80331050
+
+WAIT 1, 0xFE40009C
+
+ED 0xE61500E4, 0x00002000
+
+WAIT 1, 0xFE40009C
+
+LIST "PLL"
+ED 0xE6150028, 0x00004000
+
+WAIT 1, 0xFE40009C
+
+ED 0xE615002C, 0x93000040
+
+WAIT 1, 0xFE40009C
+
+LIST "SUB/USBClk"
+ED 0xE6150080, 0x00000180
+
+LIST "BSC"
+ED 0xFEC10000, 0x00E0001B
+
+LIST "SBSC1"
+ED 0xFE400354, 0x01AD8000
+ED 0xFE400354, 0x01AD8001
+
+WAIT 5, 0xFE40009C
+
+ED 0xFE400008, 0xBCC90151
+ED 0xFE400040, 0x41774113
+ED 0xFE400044, 0x2712E229
+ED 0xFE400048, 0x20C18505
+ED 0xFE40004C, 0x00110209
+ED 0xFE400010, 0x00000087
+
+WAIT 30, 0xFE40009C
+
+ED 0xFE400084, 0x0000003F
+EB 0xFE500000, 0x00
+
+WAIT 5, 0xFE40009C
+
+ED 0xFE400084, 0x0000FF0A
+EB 0xFE500000, 0x00
+
+WAIT 1, 0xFE40009C
+
+ED 0xFE400084, 0x00002201
+EB 0xFE500000, 0x00
+ED 0xFE400084, 0x00000302
+EB 0xFE500000, 0x00
+EB 0xFE5C0000, 0x00
+ED 0xFE400008, 0xBCC90159
+ED 0xFE40008C, 0x88800004
+ED 0xFE400094, 0x00000004
+ED 0xFE400028, 0xA55A0032
+ED 0xFE40002C, 0xA55A000C
+ED 0xFE400020, 0xA55A2048
+ED 0xFE400008, 0xBCC90959
+
+LIST "Change CPGA setting"
+ED 0xE61500E0, 0x9E40352E
+ED 0xE6150004, 0x80331050
+
+WAIT 1, 0xFE40009C
+
+ED 0xFE400354, 0x01AD8002
+
+LIST "SCIF0 - Serial port for earlyprintk"
+EB 0xE6053098, 0x11
+EB 0xE6053098, 0xe1
+EW 0xE6C40000, 0x0000
+EB 0xE6C40004, 0x19
+EW 0xE6C40008, 0x3000
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-shmobile/include/mach/head-mackerel.txt linux-libre-2.6.38-gnu1/arch/arm/mach-shmobile/include/mach/head-mackerel.txt
--- linux-libre-2.6.37-gnu1/arch/arm/mach-shmobile/include/mach/head-mackerel.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-shmobile/include/mach/head-mackerel.txt	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,94 @@
+LIST "partner-jet-setup.txt"
+LIST "(C) Copyright 2010 Renesas Solutions Corp"
+LIST "Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>"
+
+LIST "RWT Setting"
+EW 0xE6020004, 0xA500
+EW 0xE6030004, 0xA500
+
+LIST "GPIO Setting"
+EB 0xE6051013, 0xA2
+
+LIST "CPG"
+ED 0xE61500C0, 0x00000002
+
+WAIT 1, 0xFE40009C
+
+LIST "FRQCR"
+ED 0xE6150000, 0x2D1305C3
+ED 0xE61500E0, 0x9E40358E
+ED 0xE6150004, 0x80331050
+
+WAIT 1, 0xFE40009C
+
+ED 0xE61500E4, 0x00002000
+
+WAIT 1, 0xFE40009C
+
+LIST "PLL"
+ED 0xE6150028, 0x00004000
+
+WAIT 1, 0xFE40009C
+
+ED 0xE615002C, 0x93000040
+
+WAIT 1, 0xFE40009C
+
+LIST "SUB/USBClk"
+ED 0xE6150080, 0x00000180
+
+LIST "BSC"
+ED 0xFEC10000, 0x00E0001B
+
+LIST "SBSC1"
+ED 0xFE400354, 0x01AD8000
+ED 0xFE400354, 0x01AD8001
+
+WAIT 5, 0xFE40009C
+
+ED 0xFE400008, 0xBCC90151
+ED 0xFE400040, 0x41774113
+ED 0xFE400044, 0x2712E229
+ED 0xFE400048, 0x20C18505
+ED 0xFE40004C, 0x00110209
+ED 0xFE400010, 0x00000087
+
+WAIT 30, 0xFE40009C
+
+ED 0xFE400084, 0x0000003F
+EB 0xFE500000, 0x00
+
+WAIT 5, 0xFE40009C
+
+ED 0xFE400084, 0x0000FF0A
+EB 0xFE500000, 0x00
+
+WAIT 1, 0xFE40009C
+
+ED 0xFE400084, 0x00002201
+EB 0xFE500000, 0x00
+ED 0xFE400084, 0x00000302
+EB 0xFE500000, 0x00
+EB 0xFE5C0000, 0x00
+ED 0xFE400008, 0xBCC90159
+ED 0xFE40008C, 0x88800004
+ED 0xFE400094, 0x00000004
+ED 0xFE400028, 0xA55A0032
+ED 0xFE40002C, 0xA55A000C
+ED 0xFE400020, 0xA55A2048
+ED 0xFE400008, 0xBCC90959
+
+LIST "Change CPGA setting"
+ED 0xE61500E0, 0x9E40352E
+ED 0xE6150004, 0x80331050
+
+WAIT 1, 0xFE40009C
+
+ED 0xFE400354, 0x01AD8002
+
+LIST "SCIF0 - Serial port for earlyprintk"
+EB 0xE6053098, 0x11
+EB 0xE6053098, 0xe1
+EW 0xE6C40000, 0x0000
+EB 0xE6C40004, 0x19
+EW 0xE6C40008, 0x3000
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-shmobile/include/mach/irqs.h linux-libre-2.6.38-gnu1/arch/arm/mach-shmobile/include/mach/irqs.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-shmobile/include/mach/irqs.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-shmobile/include/mach/irqs.h	2011-03-14 21:20:32.000000000 -0400
@@ -1,7 +1,10 @@
 #ifndef __ASM_MACH_IRQS_H
 #define __ASM_MACH_IRQS_H
 
-#define NR_IRQS         512
+#define NR_IRQS         1024
+
+/* GIC */
+#define gic_spi(nr)		((nr) + 32)
 
 /* INTCA */
 #define evt2irq(evt)		(((evt) >> 5) - 16)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-shmobile/include/mach/sh7372.h linux-libre-2.6.38-gnu1/arch/arm/mach-shmobile/include/mach/sh7372.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-shmobile/include/mach/sh7372.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-shmobile/include/mach/sh7372.h	2011-03-14 21:20:32.000000000 -0400
@@ -455,6 +455,8 @@ enum {
 	SHDMA_SLAVE_SDHI1_TX,
 	SHDMA_SLAVE_SDHI2_RX,
 	SHDMA_SLAVE_SDHI2_TX,
+	SHDMA_SLAVE_MMCIF_RX,
+	SHDMA_SLAVE_MMCIF_TX,
 };
 
 extern struct clk sh7372_extal1_clk;
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-shmobile/include/mach/sh73a0.h linux-libre-2.6.38-gnu1/arch/arm/mach-shmobile/include/mach/sh73a0.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-shmobile/include/mach/sh73a0.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-shmobile/include/mach/sh73a0.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,467 @@
+#ifndef __ASM_SH73A0_H__
+#define __ASM_SH73A0_H__
+
+/* Pin Function Controller:
+ * GPIO_FN_xx - GPIO used to select pin function and MSEL switch
+ * GPIO_PORTxx - GPIO mapped to real I/O pin on CPU
+ */
+enum {
+	/* Hardware manual Table 25-1 (GPIO) */
+	GPIO_PORT0, GPIO_PORT1, GPIO_PORT2, GPIO_PORT3, GPIO_PORT4,
+	GPIO_PORT5, GPIO_PORT6, GPIO_PORT7, GPIO_PORT8, GPIO_PORT9,
+
+	GPIO_PORT10, GPIO_PORT11, GPIO_PORT12, GPIO_PORT13, GPIO_PORT14,
+	GPIO_PORT15, GPIO_PORT16, GPIO_PORT17, GPIO_PORT18, GPIO_PORT19,
+
+	GPIO_PORT20, GPIO_PORT21, GPIO_PORT22, GPIO_PORT23, GPIO_PORT24,
+	GPIO_PORT25, GPIO_PORT26, GPIO_PORT27, GPIO_PORT28, GPIO_PORT29,
+
+	GPIO_PORT30, GPIO_PORT31, GPIO_PORT32, GPIO_PORT33, GPIO_PORT34,
+	GPIO_PORT35, GPIO_PORT36, GPIO_PORT37, GPIO_PORT38, GPIO_PORT39,
+
+	GPIO_PORT40, GPIO_PORT41, GPIO_PORT42, GPIO_PORT43, GPIO_PORT44,
+	GPIO_PORT45, GPIO_PORT46, GPIO_PORT47, GPIO_PORT48, GPIO_PORT49,
+
+	GPIO_PORT50, GPIO_PORT51, GPIO_PORT52, GPIO_PORT53, GPIO_PORT54,
+	GPIO_PORT55, GPIO_PORT56, GPIO_PORT57, GPIO_PORT58, GPIO_PORT59,
+
+	GPIO_PORT60, GPIO_PORT61, GPIO_PORT62, GPIO_PORT63, GPIO_PORT64,
+	GPIO_PORT65, GPIO_PORT66, GPIO_PORT67, GPIO_PORT68, GPIO_PORT69,
+
+	GPIO_PORT70, GPIO_PORT71, GPIO_PORT72, GPIO_PORT73, GPIO_PORT74,
+	GPIO_PORT75, GPIO_PORT76, GPIO_PORT77, GPIO_PORT78, GPIO_PORT79,
+
+	GPIO_PORT80, GPIO_PORT81, GPIO_PORT82, GPIO_PORT83, GPIO_PORT84,
+	GPIO_PORT85, GPIO_PORT86, GPIO_PORT87, GPIO_PORT88, GPIO_PORT89,
+
+	GPIO_PORT90, GPIO_PORT91, GPIO_PORT92, GPIO_PORT93, GPIO_PORT94,
+	GPIO_PORT95, GPIO_PORT96, GPIO_PORT97, GPIO_PORT98, GPIO_PORT99,
+
+	GPIO_PORT100, GPIO_PORT101, GPIO_PORT102, GPIO_PORT103, GPIO_PORT104,
+	GPIO_PORT105, GPIO_PORT106, GPIO_PORT107, GPIO_PORT108, GPIO_PORT109,
+
+	GPIO_PORT110, GPIO_PORT111, GPIO_PORT112, GPIO_PORT113, GPIO_PORT114,
+	GPIO_PORT115, GPIO_PORT116, GPIO_PORT117, GPIO_PORT118,
+
+	GPIO_PORT128, GPIO_PORT129,
+
+	GPIO_PORT130, GPIO_PORT131, GPIO_PORT132, GPIO_PORT133, GPIO_PORT134,
+	GPIO_PORT135, GPIO_PORT136, GPIO_PORT137, GPIO_PORT138, GPIO_PORT139,
+
+	GPIO_PORT140, GPIO_PORT141, GPIO_PORT142, GPIO_PORT143, GPIO_PORT144,
+	GPIO_PORT145, GPIO_PORT146, GPIO_PORT147, GPIO_PORT148, GPIO_PORT149,
+
+	GPIO_PORT150, GPIO_PORT151, GPIO_PORT152, GPIO_PORT153, GPIO_PORT154,
+	GPIO_PORT155, GPIO_PORT156, GPIO_PORT157, GPIO_PORT158, GPIO_PORT159,
+
+	GPIO_PORT160, GPIO_PORT161, GPIO_PORT162, GPIO_PORT163, GPIO_PORT164,
+
+	GPIO_PORT192, GPIO_PORT193, GPIO_PORT194,
+	GPIO_PORT195, GPIO_PORT196, GPIO_PORT197, GPIO_PORT198, GPIO_PORT199,
+
+	GPIO_PORT200, GPIO_PORT201, GPIO_PORT202, GPIO_PORT203, GPIO_PORT204,
+	GPIO_PORT205, GPIO_PORT206, GPIO_PORT207, GPIO_PORT208, GPIO_PORT209,
+
+	GPIO_PORT210, GPIO_PORT211, GPIO_PORT212, GPIO_PORT213, GPIO_PORT214,
+	GPIO_PORT215, GPIO_PORT216, GPIO_PORT217, GPIO_PORT218, GPIO_PORT219,
+
+	GPIO_PORT220, GPIO_PORT221, GPIO_PORT222, GPIO_PORT223, GPIO_PORT224,
+	GPIO_PORT225, GPIO_PORT226, GPIO_PORT227, GPIO_PORT228, GPIO_PORT229,
+
+	GPIO_PORT230, GPIO_PORT231, GPIO_PORT232, GPIO_PORT233, GPIO_PORT234,
+	GPIO_PORT235, GPIO_PORT236, GPIO_PORT237, GPIO_PORT238, GPIO_PORT239,
+
+	GPIO_PORT240, GPIO_PORT241, GPIO_PORT242, GPIO_PORT243, GPIO_PORT244,
+	GPIO_PORT245, GPIO_PORT246, GPIO_PORT247, GPIO_PORT248, GPIO_PORT249,
+
+	GPIO_PORT250, GPIO_PORT251, GPIO_PORT252, GPIO_PORT253, GPIO_PORT254,
+	GPIO_PORT255, GPIO_PORT256, GPIO_PORT257, GPIO_PORT258, GPIO_PORT259,
+
+	GPIO_PORT260, GPIO_PORT261, GPIO_PORT262, GPIO_PORT263, GPIO_PORT264,
+	GPIO_PORT265, GPIO_PORT266, GPIO_PORT267, GPIO_PORT268, GPIO_PORT269,
+
+	GPIO_PORT270, GPIO_PORT271, GPIO_PORT272, GPIO_PORT273, GPIO_PORT274,
+	GPIO_PORT275, GPIO_PORT276, GPIO_PORT277, GPIO_PORT278, GPIO_PORT279,
+
+	GPIO_PORT280, GPIO_PORT281, GPIO_PORT282,
+
+	GPIO_PORT288, GPIO_PORT289,
+
+	GPIO_PORT290, GPIO_PORT291, GPIO_PORT292, GPIO_PORT293, GPIO_PORT294,
+	GPIO_PORT295, GPIO_PORT296, GPIO_PORT297, GPIO_PORT298, GPIO_PORT299,
+
+	GPIO_PORT300, GPIO_PORT301, GPIO_PORT302, GPIO_PORT303, GPIO_PORT304,
+	GPIO_PORT305, GPIO_PORT306, GPIO_PORT307, GPIO_PORT308, GPIO_PORT309,
+
+	/* Table 25-1 (Function 0-7) */
+	GPIO_FN_VBUS_0,
+	GPIO_FN_GPI0,
+	GPIO_FN_GPI1,
+	GPIO_FN_GPI2,
+	GPIO_FN_GPI3,
+	GPIO_FN_GPI4,
+	GPIO_FN_GPI5,
+	GPIO_FN_GPI6,
+	GPIO_FN_GPI7,
+	GPIO_FN_SCIFA7_RXD,
+	GPIO_FN_SCIFA7_CTS_,
+	GPIO_FN_GPO7, GPIO_FN_MFG0_OUT2,
+	GPIO_FN_GPO6, GPIO_FN_MFG1_OUT2,
+	GPIO_FN_GPO5, GPIO_FN_SCIFA0_SCK, GPIO_FN_FSICOSLDT3, \
+	GPIO_FN_PORT16_VIO_CKOR,
+	GPIO_FN_SCIFA0_TXD,
+	GPIO_FN_SCIFA7_TXD,
+	GPIO_FN_SCIFA7_RTS_, GPIO_FN_PORT19_VIO_CKO2,
+	GPIO_FN_GPO0,
+	GPIO_FN_GPO1,
+	GPIO_FN_GPO2, GPIO_FN_STATUS0,
+	GPIO_FN_GPO3, GPIO_FN_STATUS1,
+	GPIO_FN_GPO4, GPIO_FN_STATUS2,
+	GPIO_FN_VINT,
+	GPIO_FN_TCKON,
+	GPIO_FN_XDVFS1, GPIO_FN_PORT27_I2C_SCL2, GPIO_FN_PORT27_I2C_SCL3, \
+	GPIO_FN_MFG0_OUT1, GPIO_FN_PORT27_IROUT,
+	GPIO_FN_XDVFS2, GPIO_FN_PORT28_I2C_SDA2, GPIO_FN_PORT28_I2C_SDA3, \
+	GPIO_FN_PORT28_TPU1TO1,
+	GPIO_FN_SIM_RST, GPIO_FN_PORT29_TPU1TO1,
+	GPIO_FN_SIM_CLK, GPIO_FN_PORT30_VIO_CKOR,
+	GPIO_FN_SIM_D, GPIO_FN_PORT31_IROUT,
+	GPIO_FN_SCIFA4_TXD,
+	GPIO_FN_SCIFA4_RXD, GPIO_FN_XWUP,
+	GPIO_FN_SCIFA4_RTS_,
+	GPIO_FN_SCIFA4_CTS_,
+	GPIO_FN_FSIBOBT, GPIO_FN_FSIBIBT,
+	GPIO_FN_FSIBOLR, GPIO_FN_FSIBILR,
+	GPIO_FN_FSIBOSLD,
+	GPIO_FN_FSIBISLD,
+	GPIO_FN_VACK,
+	GPIO_FN_XTAL1L,
+	GPIO_FN_SCIFA0_RTS_, GPIO_FN_FSICOSLDT2,
+	GPIO_FN_SCIFA0_RXD,
+	GPIO_FN_SCIFA0_CTS_, GPIO_FN_FSICOSLDT1,
+	GPIO_FN_FSICOBT, GPIO_FN_FSICIBT, GPIO_FN_FSIDOBT, GPIO_FN_FSIDIBT,
+	GPIO_FN_FSICOLR, GPIO_FN_FSICILR, GPIO_FN_FSIDOLR, GPIO_FN_FSIDILR,
+	GPIO_FN_FSICOSLD, GPIO_FN_PORT47_FSICSPDIF,
+	GPIO_FN_FSICISLD, GPIO_FN_FSIDISLD,
+	GPIO_FN_FSIACK, GPIO_FN_PORT49_IRDA_OUT, GPIO_FN_PORT49_IROUT, \
+	GPIO_FN_FSIAOMC,
+	GPIO_FN_FSIAOLR, GPIO_FN_BBIF2_TSYNC2, GPIO_FN_TPU2TO2, GPIO_FN_FSIAILR,
+
+	GPIO_FN_FSIAOBT, GPIO_FN_BBIF2_TSCK2, GPIO_FN_TPU2TO3, GPIO_FN_FSIAIBT,
+	GPIO_FN_FSIAOSLD, GPIO_FN_BBIF2_TXD2,
+	GPIO_FN_FSIASPDIF, GPIO_FN_PORT53_IRDA_IN, GPIO_FN_TPU3TO3, \
+	GPIO_FN_FSIBSPDIF, GPIO_FN_PORT53_FSICSPDIF,
+	GPIO_FN_FSIBCK, GPIO_FN_PORT54_IRDA_FIRSEL, GPIO_FN_TPU3TO2, \
+	GPIO_FN_FSIBOMC, GPIO_FN_FSICCK, GPIO_FN_FSICOMC,
+	GPIO_FN_FSIAISLD, GPIO_FN_TPU0TO0,
+	GPIO_FN_A0, GPIO_FN_BS_,
+	GPIO_FN_A12, GPIO_FN_PORT58_KEYOUT7, GPIO_FN_TPU4TO2,
+	GPIO_FN_A13, GPIO_FN_PORT59_KEYOUT6, GPIO_FN_TPU0TO1,
+	GPIO_FN_A14, GPIO_FN_KEYOUT5,
+	GPIO_FN_A15, GPIO_FN_KEYOUT4,
+	GPIO_FN_A16, GPIO_FN_KEYOUT3, GPIO_FN_MSIOF0_SS1,
+	GPIO_FN_A17, GPIO_FN_KEYOUT2, GPIO_FN_MSIOF0_TSYNC,
+	GPIO_FN_A18, GPIO_FN_KEYOUT1, GPIO_FN_MSIOF0_TSCK,
+	GPIO_FN_A19, GPIO_FN_KEYOUT0, GPIO_FN_MSIOF0_TXD,
+	GPIO_FN_A20, GPIO_FN_KEYIN0, GPIO_FN_MSIOF0_RSCK,
+	GPIO_FN_A21, GPIO_FN_KEYIN1, GPIO_FN_MSIOF0_RSYNC,
+	GPIO_FN_A22, GPIO_FN_KEYIN2, GPIO_FN_MSIOF0_MCK0,
+	GPIO_FN_A23, GPIO_FN_KEYIN3, GPIO_FN_MSIOF0_MCK1,
+	GPIO_FN_A24, GPIO_FN_KEYIN4, GPIO_FN_MSIOF0_RXD,
+	GPIO_FN_A25, GPIO_FN_KEYIN5, GPIO_FN_MSIOF0_SS2,
+	GPIO_FN_A26, GPIO_FN_KEYIN6,
+	GPIO_FN_KEYIN7,
+	GPIO_FN_D0_NAF0,
+	GPIO_FN_D1_NAF1,
+	GPIO_FN_D2_NAF2,
+	GPIO_FN_D3_NAF3,
+	GPIO_FN_D4_NAF4,
+	GPIO_FN_D5_NAF5,
+	GPIO_FN_D6_NAF6,
+	GPIO_FN_D7_NAF7,
+	GPIO_FN_D8_NAF8,
+	GPIO_FN_D9_NAF9,
+	GPIO_FN_D10_NAF10,
+	GPIO_FN_D11_NAF11,
+	GPIO_FN_D12_NAF12,
+	GPIO_FN_D13_NAF13,
+	GPIO_FN_D14_NAF14,
+	GPIO_FN_D15_NAF15,
+	GPIO_FN_CS4_,
+	GPIO_FN_CS5A_, GPIO_FN_PORT91_RDWR,
+	GPIO_FN_CS5B_, GPIO_FN_FCE1_,
+	GPIO_FN_CS6B_, GPIO_FN_DACK0,
+	GPIO_FN_FCE0_, GPIO_FN_CS6A_,
+	GPIO_FN_WAIT_, GPIO_FN_DREQ0,
+	GPIO_FN_RD__FSC,
+	GPIO_FN_WE0__FWE, GPIO_FN_RDWR_FWE,
+	GPIO_FN_WE1_,
+	GPIO_FN_FRB,
+	GPIO_FN_CKO,
+	GPIO_FN_NBRSTOUT_,
+	GPIO_FN_NBRST_,
+	GPIO_FN_BBIF2_TXD,
+	GPIO_FN_BBIF2_RXD,
+	GPIO_FN_BBIF2_SYNC,
+	GPIO_FN_BBIF2_SCK,
+	GPIO_FN_SCIFA3_CTS_, GPIO_FN_MFG3_IN2,
+	GPIO_FN_SCIFA3_RXD, GPIO_FN_MFG3_IN1,
+	GPIO_FN_BBIF1_SS2, GPIO_FN_SCIFA3_RTS_, GPIO_FN_MFG3_OUT1,
+	GPIO_FN_SCIFA3_TXD,
+	GPIO_FN_HSI_RX_DATA, GPIO_FN_BBIF1_RXD,
+	GPIO_FN_HSI_TX_WAKE, GPIO_FN_BBIF1_TSCK,
+	GPIO_FN_HSI_TX_DATA, GPIO_FN_BBIF1_TSYNC,
+	GPIO_FN_HSI_TX_READY, GPIO_FN_BBIF1_TXD,
+	GPIO_FN_HSI_RX_READY, GPIO_FN_BBIF1_RSCK, GPIO_FN_PORT115_I2C_SCL2, \
+	GPIO_FN_PORT115_I2C_SCL3,
+	GPIO_FN_HSI_RX_WAKE, GPIO_FN_BBIF1_RSYNC, GPIO_FN_PORT116_I2C_SDA2, \
+	GPIO_FN_PORT116_I2C_SDA3,
+	GPIO_FN_HSI_RX_FLAG, GPIO_FN_BBIF1_SS1, GPIO_FN_BBIF1_FLOW,
+	GPIO_FN_HSI_TX_FLAG,
+	GPIO_FN_VIO_VD, GPIO_FN_PORT128_LCD2VSYN, GPIO_FN_VIO2_VD, \
+	GPIO_FN_LCD2D0,
+
+	GPIO_FN_VIO_HD, GPIO_FN_PORT129_LCD2HSYN, GPIO_FN_PORT129_LCD2CS_, \
+	GPIO_FN_VIO2_HD, GPIO_FN_LCD2D1,
+	GPIO_FN_VIO_D0, GPIO_FN_PORT130_MSIOF2_RXD, GPIO_FN_LCD2D10,
+	GPIO_FN_VIO_D1, GPIO_FN_PORT131_KEYOUT6, GPIO_FN_PORT131_MSIOF2_SS1, \
+	GPIO_FN_PORT131_KEYOUT11, GPIO_FN_LCD2D11,
+	GPIO_FN_VIO_D2, GPIO_FN_PORT132_KEYOUT7, GPIO_FN_PORT132_MSIOF2_SS2, \
+	GPIO_FN_PORT132_KEYOUT10, GPIO_FN_LCD2D12,
+	GPIO_FN_VIO_D3, GPIO_FN_MSIOF2_TSYNC, GPIO_FN_LCD2D13,
+	GPIO_FN_VIO_D4, GPIO_FN_MSIOF2_TXD, GPIO_FN_LCD2D14,
+	GPIO_FN_VIO_D5, GPIO_FN_MSIOF2_TSCK, GPIO_FN_LCD2D15,
+	GPIO_FN_VIO_D6, GPIO_FN_PORT136_KEYOUT8, GPIO_FN_LCD2D16,
+	GPIO_FN_VIO_D7, GPIO_FN_PORT137_KEYOUT9, GPIO_FN_LCD2D17,
+	GPIO_FN_VIO_D8, GPIO_FN_PORT138_KEYOUT8, GPIO_FN_VIO2_D0, \
+	GPIO_FN_LCD2D6,
+	GPIO_FN_VIO_D9, GPIO_FN_PORT139_KEYOUT9, GPIO_FN_VIO2_D1, \
+	GPIO_FN_LCD2D7,
+	GPIO_FN_VIO_D10, GPIO_FN_TPU0TO2, GPIO_FN_VIO2_D2, GPIO_FN_LCD2D8,
+	GPIO_FN_VIO_D11, GPIO_FN_TPU0TO3, GPIO_FN_VIO2_D3, GPIO_FN_LCD2D9,
+	GPIO_FN_VIO_D12, GPIO_FN_PORT142_KEYOUT10, GPIO_FN_VIO2_D4, \
+	GPIO_FN_LCD2D2,
+	GPIO_FN_VIO_D13, GPIO_FN_PORT143_KEYOUT11, GPIO_FN_PORT143_KEYOUT6, \
+	GPIO_FN_VIO2_D5, GPIO_FN_LCD2D3,
+	GPIO_FN_VIO_D14, GPIO_FN_PORT144_KEYOUT7, GPIO_FN_VIO2_D6, \
+	GPIO_FN_LCD2D4,
+	GPIO_FN_VIO_D15, GPIO_FN_TPU1TO3, GPIO_FN_PORT145_LCD2DISP, \
+	GPIO_FN_PORT145_LCD2RS, GPIO_FN_VIO2_D7, GPIO_FN_LCD2D5,
+	GPIO_FN_VIO_CLK, GPIO_FN_LCD2DCK, GPIO_FN_PORT146_LCD2WR_, \
+	GPIO_FN_VIO2_CLK, GPIO_FN_LCD2D18,
+	GPIO_FN_VIO_FIELD, GPIO_FN_LCD2RD_, GPIO_FN_VIO2_FIELD, GPIO_FN_LCD2D19,
+	GPIO_FN_VIO_CKO,
+	GPIO_FN_A27, GPIO_FN_PORT149_RDWR, GPIO_FN_MFG0_IN1, \
+	GPIO_FN_PORT149_KEYOUT9,
+	GPIO_FN_MFG0_IN2,
+	GPIO_FN_TS_SPSYNC3, GPIO_FN_MSIOF2_RSCK,
+	GPIO_FN_TS_SDAT3, GPIO_FN_MSIOF2_RSYNC,
+	GPIO_FN_TPU1TO2, GPIO_FN_TS_SDEN3, GPIO_FN_PORT153_MSIOF2_SS1,
+	GPIO_FN_SCIFA2_TXD1, GPIO_FN_MSIOF2_MCK0,
+	GPIO_FN_SCIFA2_RXD1, GPIO_FN_MSIOF2_MCK1,
+	GPIO_FN_SCIFA2_RTS1_, GPIO_FN_PORT156_MSIOF2_SS2,
+	GPIO_FN_SCIFA2_CTS1_, GPIO_FN_PORT157_MSIOF2_RXD,
+	GPIO_FN_DINT_, GPIO_FN_SCIFA2_SCK1, GPIO_FN_TS_SCK3,
+	GPIO_FN_PORT159_SCIFB_SCK, GPIO_FN_PORT159_SCIFA5_SCK, GPIO_FN_NMI,
+	GPIO_FN_PORT160_SCIFB_TXD, GPIO_FN_PORT160_SCIFA5_TXD,
+	GPIO_FN_PORT161_SCIFB_CTS_, GPIO_FN_PORT161_SCIFA5_CTS_,
+	GPIO_FN_PORT162_SCIFB_RXD, GPIO_FN_PORT162_SCIFA5_RXD,
+	GPIO_FN_PORT163_SCIFB_RTS_, GPIO_FN_PORT163_SCIFA5_RTS_, \
+	GPIO_FN_TPU3TO0,
+	GPIO_FN_LCDD0,
+	GPIO_FN_LCDD1, GPIO_FN_PORT193_SCIFA5_CTS_, GPIO_FN_BBIF2_TSYNC1,
+	GPIO_FN_LCDD2, GPIO_FN_PORT194_SCIFA5_RTS_, GPIO_FN_BBIF2_TSCK1,
+	GPIO_FN_LCDD3, GPIO_FN_PORT195_SCIFA5_RXD, GPIO_FN_BBIF2_TXD1,
+	GPIO_FN_LCDD4, GPIO_FN_PORT196_SCIFA5_TXD,
+	GPIO_FN_LCDD5, GPIO_FN_PORT197_SCIFA5_SCK, GPIO_FN_MFG2_OUT2, \
+	GPIO_FN_TPU2TO1,
+	GPIO_FN_LCDD6,
+	GPIO_FN_LCDD7, GPIO_FN_TPU4TO1, GPIO_FN_MFG4_OUT2,
+	GPIO_FN_LCDD8, GPIO_FN_D16,
+	GPIO_FN_LCDD9, GPIO_FN_D17,
+	GPIO_FN_LCDD10, GPIO_FN_D18,
+	GPIO_FN_LCDD11, GPIO_FN_D19,
+	GPIO_FN_LCDD12, GPIO_FN_D20,
+	GPIO_FN_LCDD13, GPIO_FN_D21,
+	GPIO_FN_LCDD14, GPIO_FN_D22,
+	GPIO_FN_LCDD15, GPIO_FN_PORT207_MSIOF0L_SS1, GPIO_FN_D23,
+	GPIO_FN_LCDD16, GPIO_FN_PORT208_MSIOF0L_SS2, GPIO_FN_D24,
+	GPIO_FN_LCDD17, GPIO_FN_D25,
+	GPIO_FN_LCDD18, GPIO_FN_DREQ2, GPIO_FN_PORT210_MSIOF0L_SS1, GPIO_FN_D26,
+	GPIO_FN_LCDD19, GPIO_FN_PORT211_MSIOF0L_SS2, GPIO_FN_D27,
+	GPIO_FN_LCDD20, GPIO_FN_TS_SPSYNC1, GPIO_FN_MSIOF0L_MCK0, GPIO_FN_D28,
+	GPIO_FN_LCDD21, GPIO_FN_TS_SDAT1, GPIO_FN_MSIOF0L_MCK1, GPIO_FN_D29,
+	GPIO_FN_LCDD22, GPIO_FN_TS_SDEN1, GPIO_FN_MSIOF0L_RSCK, GPIO_FN_D30,
+	GPIO_FN_LCDD23, GPIO_FN_TS_SCK1, GPIO_FN_MSIOF0L_RSYNC, GPIO_FN_D31,
+	GPIO_FN_LCDDCK, GPIO_FN_LCDWR_,
+	GPIO_FN_LCDRD_, GPIO_FN_DACK2, GPIO_FN_PORT217_LCD2RS, \
+	GPIO_FN_MSIOF0L_TSYNC, GPIO_FN_VIO2_FIELD3, GPIO_FN_PORT217_LCD2DISP,
+	GPIO_FN_LCDHSYN, GPIO_FN_LCDCS_, GPIO_FN_LCDCS2_, GPIO_FN_DACK3, \
+	GPIO_FN_PORT218_VIO_CKOR,
+	GPIO_FN_LCDDISP, GPIO_FN_LCDRS, GPIO_FN_PORT219_LCD2WR_, \
+	GPIO_FN_DREQ3, GPIO_FN_MSIOF0L_TSCK, GPIO_FN_VIO2_CLK3, \
+	GPIO_FN_LCD2DCK_2,
+	GPIO_FN_LCDVSYN, GPIO_FN_LCDVSYN2,
+	GPIO_FN_LCDLCLK, GPIO_FN_DREQ1, GPIO_FN_PORT221_LCD2CS_, \
+	GPIO_FN_PWEN, GPIO_FN_MSIOF0L_RXD, GPIO_FN_VIO2_HD3, \
+	GPIO_FN_PORT221_LCD2HSYN,
+	GPIO_FN_LCDDON, GPIO_FN_LCDDON2, GPIO_FN_DACK1, GPIO_FN_OVCN, \
+	GPIO_FN_MSIOF0L_TXD, GPIO_FN_VIO2_VD3, GPIO_FN_PORT222_LCD2VSYN,
+
+	GPIO_FN_SCIFA1_TXD, GPIO_FN_OVCN2,
+	GPIO_FN_EXTLP, GPIO_FN_SCIFA1_SCK, GPIO_FN_PORT226_VIO_CKO2,
+	GPIO_FN_SCIFA1_RTS_, GPIO_FN_IDIN,
+	GPIO_FN_SCIFA1_RXD,
+	GPIO_FN_SCIFA1_CTS_, GPIO_FN_MFG1_IN1,
+	GPIO_FN_MSIOF1_TXD, GPIO_FN_SCIFA2_TXD2,
+	GPIO_FN_MSIOF1_TSYNC, GPIO_FN_SCIFA2_CTS2_,
+	GPIO_FN_MSIOF1_TSCK, GPIO_FN_SCIFA2_SCK2,
+	GPIO_FN_MSIOF1_RXD, GPIO_FN_SCIFA2_RXD2,
+	GPIO_FN_MSIOF1_RSCK, GPIO_FN_SCIFA2_RTS2_, GPIO_FN_VIO2_CLK2, \
+	GPIO_FN_LCD2D20,
+	GPIO_FN_MSIOF1_RSYNC, GPIO_FN_MFG1_IN2, GPIO_FN_VIO2_VD2, \
+	GPIO_FN_LCD2D21,
+	GPIO_FN_MSIOF1_MCK0, GPIO_FN_PORT236_I2C_SDA2,
+	GPIO_FN_MSIOF1_MCK1, GPIO_FN_PORT237_I2C_SCL2,
+	GPIO_FN_MSIOF1_SS1, GPIO_FN_VIO2_FIELD2, GPIO_FN_LCD2D22,
+	GPIO_FN_MSIOF1_SS2, GPIO_FN_VIO2_HD2, GPIO_FN_LCD2D23,
+	GPIO_FN_SCIFA6_TXD,
+	GPIO_FN_PORT241_IRDA_OUT, GPIO_FN_PORT241_IROUT, GPIO_FN_MFG4_OUT1, \
+	GPIO_FN_TPU4TO0,
+	GPIO_FN_PORT242_IRDA_IN, GPIO_FN_MFG4_IN2,
+	GPIO_FN_PORT243_IRDA_FIRSEL, GPIO_FN_PORT243_VIO_CKO2,
+	GPIO_FN_PORT244_SCIFA5_CTS_, GPIO_FN_MFG2_IN1, \
+	GPIO_FN_PORT244_SCIFB_CTS_, GPIO_FN_MSIOF2R_RXD,
+	GPIO_FN_PORT245_SCIFA5_RTS_, GPIO_FN_MFG2_IN2, \
+	GPIO_FN_PORT245_SCIFB_RTS_, GPIO_FN_MSIOF2R_TXD,
+	GPIO_FN_PORT246_SCIFA5_RXD, GPIO_FN_MFG1_OUT1, \
+	GPIO_FN_PORT246_SCIFB_RXD, GPIO_FN_TPU1TO0,
+	GPIO_FN_PORT247_SCIFA5_TXD, GPIO_FN_MFG3_OUT2, \
+	GPIO_FN_PORT247_SCIFB_TXD, GPIO_FN_TPU3TO1,
+	GPIO_FN_PORT248_SCIFA5_SCK, GPIO_FN_MFG2_OUT1, \
+	GPIO_FN_PORT248_SCIFB_SCK, GPIO_FN_TPU2TO0, \
+	GPIO_FN_PORT248_I2C_SCL3, GPIO_FN_MSIOF2R_TSCK,
+	GPIO_FN_PORT249_IROUT, GPIO_FN_MFG4_IN1, \
+	GPIO_FN_PORT249_I2C_SDA3, GPIO_FN_MSIOF2R_TSYNC,
+	GPIO_FN_SDHICLK0,
+	GPIO_FN_SDHICD0,
+	GPIO_FN_SDHID0_0,
+	GPIO_FN_SDHID0_1,
+	GPIO_FN_SDHID0_2,
+	GPIO_FN_SDHID0_3,
+	GPIO_FN_SDHICMD0,
+	GPIO_FN_SDHIWP0,
+	GPIO_FN_SDHICLK1,
+	GPIO_FN_SDHID1_0, GPIO_FN_TS_SPSYNC2,
+	GPIO_FN_SDHID1_1, GPIO_FN_TS_SDAT2,
+	GPIO_FN_SDHID1_2, GPIO_FN_TS_SDEN2,
+	GPIO_FN_SDHID1_3, GPIO_FN_TS_SCK2,
+	GPIO_FN_SDHICMD1,
+	GPIO_FN_SDHICLK2,
+	GPIO_FN_SDHID2_0, GPIO_FN_TS_SPSYNC4,
+	GPIO_FN_SDHID2_1, GPIO_FN_TS_SDAT4,
+	GPIO_FN_SDHID2_2, GPIO_FN_TS_SDEN4,
+	GPIO_FN_SDHID2_3, GPIO_FN_TS_SCK4,
+	GPIO_FN_SDHICMD2,
+	GPIO_FN_MMCCLK0,
+	GPIO_FN_MMCD0_0,
+	GPIO_FN_MMCD0_1,
+	GPIO_FN_MMCD0_2,
+	GPIO_FN_MMCD0_3,
+	GPIO_FN_MMCD0_4, GPIO_FN_TS_SPSYNC5,
+	GPIO_FN_MMCD0_5, GPIO_FN_TS_SDAT5,
+	GPIO_FN_MMCD0_6, GPIO_FN_TS_SDEN5,
+	GPIO_FN_MMCD0_7, GPIO_FN_TS_SCK5,
+	GPIO_FN_MMCCMD0,
+	GPIO_FN_RESETOUTS_, GPIO_FN_EXTAL2OUT,
+	GPIO_FN_MCP_WAIT__MCP_FRB,
+	GPIO_FN_MCP_CKO, GPIO_FN_MMCCLK1,
+	GPIO_FN_MCP_D15_MCP_NAF15,
+	GPIO_FN_MCP_D14_MCP_NAF14,
+	GPIO_FN_MCP_D13_MCP_NAF13,
+	GPIO_FN_MCP_D12_MCP_NAF12,
+	GPIO_FN_MCP_D11_MCP_NAF11,
+	GPIO_FN_MCP_D10_MCP_NAF10,
+	GPIO_FN_MCP_D9_MCP_NAF9,
+	GPIO_FN_MCP_D8_MCP_NAF8, GPIO_FN_MMCCMD1,
+	GPIO_FN_MCP_D7_MCP_NAF7, GPIO_FN_MMCD1_7,
+
+	GPIO_FN_MCP_D6_MCP_NAF6, GPIO_FN_MMCD1_6,
+	GPIO_FN_MCP_D5_MCP_NAF5, GPIO_FN_MMCD1_5,
+	GPIO_FN_MCP_D4_MCP_NAF4, GPIO_FN_MMCD1_4,
+	GPIO_FN_MCP_D3_MCP_NAF3, GPIO_FN_MMCD1_3,
+	GPIO_FN_MCP_D2_MCP_NAF2, GPIO_FN_MMCD1_2,
+	GPIO_FN_MCP_D1_MCP_NAF1, GPIO_FN_MMCD1_1,
+	GPIO_FN_MCP_D0_MCP_NAF0, GPIO_FN_MMCD1_0,
+	GPIO_FN_MCP_NBRSTOUT_,
+	GPIO_FN_MCP_WE0__MCP_FWE, GPIO_FN_MCP_RDWR_MCP_FWE,
+
+	/* MSEL2 special case */
+	GPIO_FN_TSIF2_TS_XX1,
+	GPIO_FN_TSIF2_TS_XX2,
+	GPIO_FN_TSIF2_TS_XX3,
+	GPIO_FN_TSIF2_TS_XX4,
+	GPIO_FN_TSIF2_TS_XX5,
+	GPIO_FN_TSIF1_TS_XX1,
+	GPIO_FN_TSIF1_TS_XX2,
+	GPIO_FN_TSIF1_TS_XX3,
+	GPIO_FN_TSIF1_TS_XX4,
+	GPIO_FN_TSIF1_TS_XX5,
+	GPIO_FN_TSIF0_TS_XX1,
+	GPIO_FN_TSIF0_TS_XX2,
+	GPIO_FN_TSIF0_TS_XX3,
+	GPIO_FN_TSIF0_TS_XX4,
+	GPIO_FN_TSIF0_TS_XX5,
+	GPIO_FN_MST1_TS_XX1,
+	GPIO_FN_MST1_TS_XX2,
+	GPIO_FN_MST1_TS_XX3,
+	GPIO_FN_MST1_TS_XX4,
+	GPIO_FN_MST1_TS_XX5,
+	GPIO_FN_MST0_TS_XX1,
+	GPIO_FN_MST0_TS_XX2,
+	GPIO_FN_MST0_TS_XX3,
+	GPIO_FN_MST0_TS_XX4,
+	GPIO_FN_MST0_TS_XX5,
+
+	/* MSEL3 special cases */
+	GPIO_FN_SDHI0_VCCQ_MC0_ON,
+	GPIO_FN_SDHI0_VCCQ_MC0_OFF,
+	GPIO_FN_DEBUG_MON_VIO,
+	GPIO_FN_DEBUG_MON_LCDD,
+	GPIO_FN_LCDC_LCDC0,
+	GPIO_FN_LCDC_LCDC1,
+
+	/* MSEL4 special cases */
+	GPIO_FN_IRQ9_MEM_INT,
+	GPIO_FN_IRQ9_MCP_INT,
+	GPIO_FN_A11,
+	GPIO_FN_KEYOUT8,
+	GPIO_FN_TPU4TO3,
+	GPIO_FN_RESETA_N_PU_ON,
+	GPIO_FN_RESETA_N_PU_OFF,
+	GPIO_FN_EDBGREQ_PD,
+	GPIO_FN_EDBGREQ_PU,
+
+	/* Functions with pull-ups */
+	GPIO_FN_KEYIN0_PU,
+	GPIO_FN_KEYIN1_PU,
+	GPIO_FN_KEYIN2_PU,
+	GPIO_FN_KEYIN3_PU,
+	GPIO_FN_KEYIN4_PU,
+	GPIO_FN_KEYIN5_PU,
+	GPIO_FN_KEYIN6_PU,
+	GPIO_FN_KEYIN7_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_MMCCMD0_PU,
+	GPIO_FN_MMCCMD1_PU,
+	GPIO_FN_FSIACK_PU,
+	GPIO_FN_FSIAILR_PU,
+	GPIO_FN_FSIAIBT_PU,
+	GPIO_FN_FSIAISLD_PU,
+};
+
+#endif /* __ASM_SH73A0_H__ */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-shmobile/include/mach/smp.h linux-libre-2.6.38-gnu1/arch/arm/mach-shmobile/include/mach/smp.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-shmobile/include/mach/smp.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-shmobile/include/mach/smp.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,16 @@
+#ifndef __MACH_SMP_H
+#define __MACH_SMP_H
+
+#include <asm/hardware/gic.h>
+
+/*
+ * We use IRQ1 as the IPI
+ */
+static inline void smp_cross_call(const struct cpumask *mask, int ipi)
+{
+#if defined(CONFIG_ARM_GIC)
+	gic_raise_softirq(mask, ipi);
+#endif
+}
+
+#endif
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-shmobile/include/mach/zboot.h linux-libre-2.6.38-gnu1/arch/arm/mach-shmobile/include/mach/zboot.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-shmobile/include/mach/zboot.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-shmobile/include/mach/zboot.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,23 @@
+#ifndef ZBOOT_H
+#define ZBOOT_H
+
+#include <asm/mach-types.h>
+#include <mach/zboot_macros.h>
+
+/**************************************************
+ *
+ *		board specific settings
+ *
+ **************************************************/
+
+#ifdef CONFIG_MACH_AP4EVB
+#define MACH_TYPE	MACH_TYPE_AP4EVB
+#include "mach/head-ap4evb.txt"
+#elif CONFIG_MACH_MACKEREL
+#define MACH_TYPE	MACH_TYPE_MACKEREL
+#include "mach/head-mackerel.txt"
+#else
+#error "unsupported board."
+#endif
+
+#endif /* ZBOOT_H */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-shmobile/include/mach/zboot_macros.h linux-libre-2.6.38-gnu1/arch/arm/mach-shmobile/include/mach/zboot_macros.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-shmobile/include/mach/zboot_macros.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-shmobile/include/mach/zboot_macros.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,65 @@
+#ifndef __ZBOOT_MACRO_H
+#define __ZBOOT_MACRO_H
+
+/* The LIST command is used to include comments in the script */
+.macro	LIST comment
+.endm
+
+/* The ED command is used to write a 32-bit word */
+.macro ED, addr, data
+	LDR	r0, 1f
+	LDR	r1, 2f
+	STR	r1, [r0]
+	B	3f
+1 :	.long	\addr
+2 :	.long	\data
+3 :
+.endm
+
+/* The EW command is used to write a 16-bit word */
+.macro EW, addr, data
+	LDR	r0, 1f
+	LDR	r1, 2f
+	STRH	r1, [r0]
+	B	3f
+1 :	.long	\addr
+2 :	.long	\data
+3 :
+.endm
+
+/* The EB command is used to write an 8-bit word */
+.macro EB, addr, data
+	LDR	r0, 1f
+	LDR	r1, 2f
+	STRB	r1, [r0]
+	B	3f
+1 :	.long	\addr
+2 :	.long	\data
+3 :
+.endm
+
+/* The WAIT command is used to delay the execution */
+.macro  WAIT, time, reg
+	LDR	r1, 1f
+	LDR	r0, 2f
+	STR	r0, [r1]
+10 :
+	LDR	r0, [r1]
+	CMP	r0, #0x00000000
+	BNE	10b
+	NOP
+	B	3f
+1 :	.long	\reg
+2 :	.long	\time * 100
+3 :
+.endm
+
+/* The DD command is used to read a 32-bit word */
+.macro  DD, start, end
+	LDR	r1, 1f
+	B	2f
+1 :	.long	\start
+2 :
+.endm
+
+#endif /* __ZBOOT_MACRO_H */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-shmobile/intc-sh7367.c linux-libre-2.6.38-gnu1/arch/arm/mach-shmobile/intc-sh7367.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-shmobile/intc-sh7367.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-shmobile/intc-sh7367.c	2011-03-14 21:20:32.000000000 -0400
@@ -189,10 +189,10 @@ static struct intc_mask_reg intca_mask_r
 	  { SCIFB, SCIFA5, SCIFA4, MSIOF1,
 	    0, 0, MSIOF2, 0 } },
 	{ 0xe694009c, 0xe69400dc, 8, /* IMR7A / IMCR7A */
-	  { DISABLED, DISABLED, ENABLED, ENABLED,
+	  { DISABLED, ENABLED, ENABLED, ENABLED,
 	    FLCTL_FLTREQ1I, FLCTL_FLTREQ0I, FLCTL_FLTENDI, FLCTL_FLSTEI } },
 	{ 0xe69400a0, 0xe69400e0, 8, /* IMR8A / IMCR8A */
-	  { DISABLED, DISABLED, ENABLED, ENABLED,
+	  { DISABLED, ENABLED, ENABLED, ENABLED,
 	    TTI20, USBDMAC_USHDMI, SPU, SIU } },
 	{ 0xe69400a4, 0xe69400e4, 8, /* IMR9A / IMCR9A */
 	  { CMT1_CMT13, CMT1_CMT12, CMT1_CMT11, CMT1_CMT10,
@@ -207,7 +207,7 @@ static struct intc_mask_reg intca_mask_r
 	  { 0, 0, TPU0, TPU1,
 	    TPU2, TPU3, TPU4, 0 } },
 	{ 0xe69400b4, 0xe69400f4, 8, /* IMR13A / IMCR13A */
-	  { DISABLED, DISABLED, ENABLED, ENABLED,
+	  { DISABLED, ENABLED, ENABLED, ENABLED,
 	    MISTY, CMT3, RWDT1, RWDT0 } },
 };
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-shmobile/intc-sh7372.c linux-libre-2.6.38-gnu1/arch/arm/mach-shmobile/intc-sh7372.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-shmobile/intc-sh7372.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-shmobile/intc-sh7372.c	2011-03-14 21:20:32.000000000 -0400
@@ -230,10 +230,10 @@ static struct intc_mask_reg intca_mask_r
 	  { SCIFB, SCIFA5, SCIFA4, MSIOF1,
 	    0, 0, MSIOF2, 0 } },
 	{ 0xe694009c, 0xe69400dc, 8, /* IMR7A / IMCR7A */
-	  { DISABLED, DISABLED, ENABLED, ENABLED,
+	  { DISABLED, ENABLED, ENABLED, ENABLED,
 	    FLCTL_FLTREQ1I, FLCTL_FLTREQ0I, FLCTL_FLTENDI, FLCTL_FLSTEI } },
 	{ 0xe69400a0, 0xe69400e0, 8, /* IMR8A / IMCR8A */
-	  { 0, DISABLED, ENABLED, ENABLED,
+	  { 0, ENABLED, ENABLED, ENABLED,
 	    TTI20, USBHSDMAC0_USHDMI, 0, 0 } },
 	{ 0xe69400a4, 0xe69400e4, 8, /* IMR9A / IMCR9A */
 	  { CMT1_CMT13, CMT1_CMT12, CMT1_CMT11, CMT1_CMT10,
@@ -365,6 +365,7 @@ static struct intc_desc intca_desc __ini
 
 enum {
 	UNUSED_INTCS = 0,
+	ENABLED_INTCS,
 
 	INTCS,
 
@@ -413,7 +414,7 @@ enum {
 	CMT4,
 	DSITX1_DSITX1_0,
 	DSITX1_DSITX1_1,
-	/* MFIS2 */
+	MFIS2_INTCS, /* Priority always enabled using ENABLED_INTCS */
 	CPORTS2R,
 	/* CEC */
 	JPU6E,
@@ -477,7 +478,7 @@ static struct intc_vect intcs_vectors[]
 	INTCS_VECT(CMT4, 0x1980),
 	INTCS_VECT(DSITX1_DSITX1_0, 0x19a0),
 	INTCS_VECT(DSITX1_DSITX1_1, 0x19c0),
-	/* MFIS2 */
+	INTCS_VECT(MFIS2_INTCS, 0x1a00),
 	INTCS_VECT(CPORTS2R, 0x1a20),
 	/* CEC */
 	INTCS_VECT(JPU6E, 0x1a80),
@@ -543,7 +544,7 @@ static struct intc_mask_reg intcs_mask_r
 	  { 0, TMU1_TUNI2, TMU1_TUNI1, TMU1_TUNI0,
 	    CMT4, DSITX1_DSITX1_0, DSITX1_DSITX1_1, 0 } },
 	{ 0xffd5019c, 0xffd501dc, 8, /* IMR7SA3 / IMCR7SA3 */
-	  { 0, CPORTS2R, 0, 0,
+	  { MFIS2_INTCS, CPORTS2R, 0, 0,
 	    JPU6E, 0, 0, 0 } },
 	{ 0xffd20104, 0, 16, /* INTAMASK */
 	  { 0, 0, 0, 0, 0, 0, 0, 0,
@@ -571,7 +572,8 @@ static struct intc_prio_reg intcs_prio_r
 	{ 0xffd50030, 0, 16, 4, /* IPRMS3 */ { TMU1, 0, 0, 0 } },
 	{ 0xffd50034, 0, 16, 4, /* IPRNS3 */ { CMT4, DSITX1_DSITX1_0,
 					       DSITX1_DSITX1_1, 0 } },
-	{ 0xffd50038, 0, 16, 4, /* IPROS3 */ { 0, CPORTS2R, 0, 0 } },
+	{ 0xffd50038, 0, 16, 4, /* IPROS3 */ { ENABLED_INTCS, CPORTS2R,
+					       0, 0 } },
 	{ 0xffd5003c, 0, 16, 4, /* IPRPS3 */ { JPU6E, 0, 0, 0 } },
 };
 
@@ -590,6 +592,7 @@ static struct resource intcs_resources[]
 
 static struct intc_desc intcs_desc __initdata = {
 	.name = "sh7372-intcs",
+	.force_enable = ENABLED_INTCS,
 	.resource = intcs_resources,
 	.num_resources = ARRAY_SIZE(intcs_resources),
 	.hw = INTC_HW_DESC(intcs_vectors, intcs_groups, intcs_mask_registers,
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-shmobile/intc-sh7377.c linux-libre-2.6.38-gnu1/arch/arm/mach-shmobile/intc-sh7377.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-shmobile/intc-sh7377.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-shmobile/intc-sh7377.c	2011-03-14 21:20:32.000000000 -0400
@@ -234,10 +234,10 @@ static struct intc_mask_reg intca_mask_r
 	  { SCIFB, SCIFA5, SCIFA4, MSIOF1,
 	    0, 0, MSIOF2, 0 } },
 	{ 0xe694009c, 0xe69400dc, 8, /* IMR7A / IMCR7A */
-	  { DISABLED, DISABLED, ENABLED, ENABLED,
+	  { DISABLED, ENABLED, ENABLED, ENABLED,
 	    FLCTL_FLTREQ1I, FLCTL_FLTREQ0I, FLCTL_FLTENDI, FLCTL_FLSTEI } },
 	{ 0xe69400a0, 0xe69400e0, 8, /* IMR8A / IMCR8A */
-	  { DISABLED, DISABLED, ENABLED, ENABLED,
+	  { DISABLED, ENABLED, ENABLED, ENABLED,
 	    TTI20, USBDMAC_USHDMI, 0, MSUG } },
 	{ 0xe69400a4, 0xe69400e4, 8, /* IMR9A / IMCR9A */
 	  { CMT1_CMT13, CMT1_CMT12, CMT1_CMT11, CMT1_CMT10,
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-shmobile/intc-sh73a0.c linux-libre-2.6.38-gnu1/arch/arm/mach-shmobile/intc-sh73a0.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-shmobile/intc-sh73a0.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-shmobile/intc-sh73a0.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,268 @@
+/*
+ * sh73a0 processor support - INTC hardware block
+ *
+ * Copyright (C) 2010  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; 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/io.h>
+#include <linux/sh_intc.h>
+#include <asm/hardware/gic.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+
+enum {
+	UNUSED = 0,
+
+	/* interrupt sources INTCS */
+	PINTCS_PINT1, PINTCS_PINT2,
+	RTDMAC_0_DEI0, RTDMAC_0_DEI1, RTDMAC_0_DEI2, RTDMAC_0_DEI3,
+	CEU, MFI, BBIF2, VPU, TSIF1, _3DG_SGX543, _2DDMAC_2DDM0,
+	RTDMAC_1_DEI4, RTDMAC_1_DEI5, RTDMAC_1_DADERR,
+	KEYSC_KEY, VINT, MSIOF,
+	TMU0_TUNI00, TMU0_TUNI01, TMU0_TUNI02,
+	CMT0, TSIF0, CMT2, LMB, MSUG, MSU_MSU, MSU_MSU2,
+	CTI, RWDT0, ICB, PEP, ASA, JPU_JPEG, LCDC, LCRC,
+	RTDMAC_2_DEI6, RTDMAC_2_DEI7, RTDMAC_2_DEI8, RTDMAC_2_DEI9,
+	RTDMAC_3_DEI10, RTDMAC_3_DEI11,
+	FRC, GCU, LCDC1, CSIRX,
+	DSITX0_DSITX00, DSITX0_DSITX01,
+	SPU2_SPU0, SPU2_SPU1, FSI,
+	TMU1_TUNI10, TMU1_TUNI11, TMU1_TUNI12,
+	TSIF2, CMT4, MFIS2, CPORTS2R, TSG, DMASCH1, SCUW,
+	VIO60, VIO61, CEU21, CSI21, DSITX1_DSITX10, DSITX1_DSITX11,
+	DISP, DSRV, EMUX2_EMUX20I, EMUX2_EMUX21I,
+	MSTIF0_MST00I, MSTIF0_MST01I, MSTIF1_MST10I, MSTIF1_MST11I,
+	SPUV,
+
+	/* interrupt groups INTCS */
+	RTDMAC_0, RTDMAC_1, RTDMAC_2, RTDMAC_3,
+	DSITX0, SPU2, TMU1, MSU,
+};
+
+static struct intc_vect intcs_vectors[] = {
+	INTCS_VECT(PINTCS_PINT1, 0x0600), INTCS_VECT(PINTCS_PINT2, 0x0620),
+	INTCS_VECT(RTDMAC_0_DEI0, 0x0800), INTCS_VECT(RTDMAC_0_DEI1, 0x0820),
+	INTCS_VECT(RTDMAC_0_DEI2, 0x0840), INTCS_VECT(RTDMAC_0_DEI3, 0x0860),
+	INTCS_VECT(CEU, 0x0880), INTCS_VECT(MFI, 0x0900),
+	INTCS_VECT(BBIF2, 0x0960), INTCS_VECT(VPU, 0x0980),
+	INTCS_VECT(TSIF1, 0x09a0), INTCS_VECT(_3DG_SGX543, 0x09e0),
+	INTCS_VECT(_2DDMAC_2DDM0, 0x0a00),
+	INTCS_VECT(RTDMAC_1_DEI4, 0x0b80), INTCS_VECT(RTDMAC_1_DEI5, 0x0ba0),
+	INTCS_VECT(RTDMAC_1_DADERR, 0x0bc0),
+	INTCS_VECT(KEYSC_KEY, 0x0be0), INTCS_VECT(VINT, 0x0c80),
+	INTCS_VECT(MSIOF, 0x0d20),
+	INTCS_VECT(TMU0_TUNI00, 0x0e80), INTCS_VECT(TMU0_TUNI01, 0x0ea0),
+	INTCS_VECT(TMU0_TUNI02, 0x0ec0),
+	INTCS_VECT(CMT0, 0x0f00), INTCS_VECT(TSIF0, 0x0f20),
+	INTCS_VECT(CMT2, 0x0f40), INTCS_VECT(LMB, 0x0f60),
+	INTCS_VECT(MSUG, 0x0f80),
+	INTCS_VECT(MSU_MSU, 0x0fa0), INTCS_VECT(MSU_MSU2, 0x0fc0),
+	INTCS_VECT(CTI, 0x0400), INTCS_VECT(RWDT0, 0x0440),
+	INTCS_VECT(ICB, 0x0480), INTCS_VECT(PEP, 0x04a0),
+	INTCS_VECT(ASA, 0x04c0), INTCS_VECT(JPU_JPEG, 0x0560),
+	INTCS_VECT(LCDC, 0x0580), INTCS_VECT(LCRC, 0x05a0),
+	INTCS_VECT(RTDMAC_2_DEI6, 0x1300), INTCS_VECT(RTDMAC_2_DEI7, 0x1320),
+	INTCS_VECT(RTDMAC_2_DEI8, 0x1340), INTCS_VECT(RTDMAC_2_DEI9, 0x1360),
+	INTCS_VECT(RTDMAC_3_DEI10, 0x1380), INTCS_VECT(RTDMAC_3_DEI11, 0x13a0),
+	INTCS_VECT(FRC, 0x1700), INTCS_VECT(GCU, 0x1760),
+	INTCS_VECT(LCDC1, 0x1780), INTCS_VECT(CSIRX, 0x17a0),
+	INTCS_VECT(DSITX0_DSITX00, 0x17c0), INTCS_VECT(DSITX0_DSITX01, 0x17e0),
+	INTCS_VECT(SPU2_SPU0, 0x1800), INTCS_VECT(SPU2_SPU1, 0x1820),
+	INTCS_VECT(FSI, 0x1840),
+	INTCS_VECT(TMU1_TUNI10, 0x1900), INTCS_VECT(TMU1_TUNI11, 0x1920),
+	INTCS_VECT(TMU1_TUNI12, 0x1940),
+	INTCS_VECT(TSIF2, 0x1960), INTCS_VECT(CMT4, 0x1980),
+	INTCS_VECT(MFIS2, 0x1a00), INTCS_VECT(CPORTS2R, 0x1a20),
+	INTCS_VECT(TSG, 0x1ae0), INTCS_VECT(DMASCH1, 0x1b00),
+	INTCS_VECT(SCUW, 0x1b40),
+	INTCS_VECT(VIO60, 0x1b60), INTCS_VECT(VIO61, 0x1b80),
+	INTCS_VECT(CEU21, 0x1ba0), INTCS_VECT(CSI21, 0x1be0),
+	INTCS_VECT(DSITX1_DSITX10, 0x1c00), INTCS_VECT(DSITX1_DSITX11, 0x1c20),
+	INTCS_VECT(DISP, 0x1c40), INTCS_VECT(DSRV, 0x1c60),
+	INTCS_VECT(EMUX2_EMUX20I, 0x1c80), INTCS_VECT(EMUX2_EMUX21I, 0x1ca0),
+	INTCS_VECT(MSTIF0_MST00I, 0x1cc0), INTCS_VECT(MSTIF0_MST01I, 0x1ce0),
+	INTCS_VECT(MSTIF1_MST10I, 0x1d00), INTCS_VECT(MSTIF1_MST11I, 0x1d20),
+	INTCS_VECT(SPUV, 0x2300),
+};
+
+static struct intc_group intcs_groups[] __initdata = {
+	INTC_GROUP(RTDMAC_0, RTDMAC_0_DEI0, RTDMAC_0_DEI1,
+		   RTDMAC_0_DEI2, RTDMAC_0_DEI3),
+	INTC_GROUP(RTDMAC_1, RTDMAC_1_DEI4, RTDMAC_1_DEI5, RTDMAC_1_DADERR),
+	INTC_GROUP(RTDMAC_2, RTDMAC_2_DEI6, RTDMAC_2_DEI7,
+		   RTDMAC_2_DEI8, RTDMAC_2_DEI9),
+	INTC_GROUP(RTDMAC_3, RTDMAC_3_DEI10, RTDMAC_3_DEI11),
+	INTC_GROUP(TMU1, TMU1_TUNI12, TMU1_TUNI11, TMU1_TUNI10),
+	INTC_GROUP(DSITX0, DSITX0_DSITX00, DSITX0_DSITX01),
+	INTC_GROUP(SPU2, SPU2_SPU0, SPU2_SPU1),
+	INTC_GROUP(MSU, MSU_MSU, MSU_MSU2),
+};
+
+static struct intc_mask_reg intcs_mask_registers[] = {
+	{ 0xffd20184, 0xffd201c4, 8, /* IMR1SA / IMCR1SA */
+	  { 0, 0, 0, CEU,
+	    0, 0, 0, 0 } },
+	{ 0xffd20188, 0xffd201c8, 8, /* IMR2SA / IMCR2SA */
+	  { 0, 0, 0, VPU,
+	    BBIF2, 0, 0, MFI } },
+	{ 0xffd2018c, 0xffd201cc, 8, /* IMR3SA / IMCR3SA */
+	  { 0, 0, 0, _2DDMAC_2DDM0,
+	    0, ASA, PEP, ICB } },
+	{ 0xffd20190, 0xffd201d0, 8, /* IMR4SA / IMCR4SA */
+	  { 0, 0, 0, CTI,
+	    JPU_JPEG, 0, LCRC, LCDC } },
+	{ 0xffd20194, 0xffd201d4, 8, /* IMR5SA / IMCR5SA */
+	  { KEYSC_KEY, RTDMAC_1_DADERR, RTDMAC_1_DEI5, RTDMAC_1_DEI4,
+	    RTDMAC_0_DEI3, RTDMAC_0_DEI2, RTDMAC_0_DEI1, RTDMAC_0_DEI0 } },
+	{ 0xffd20198, 0xffd201d8, 8, /* IMR6SA / IMCR6SA */
+	  { 0, 0, MSIOF, 0,
+	    _3DG_SGX543, 0, 0, 0 } },
+	{ 0xffd2019c, 0xffd201dc, 8, /* IMR7SA / IMCR7SA */
+	  { 0, TMU0_TUNI02, TMU0_TUNI01, TMU0_TUNI00,
+	    0, 0, 0, 0 } },
+	{ 0xffd201a0, 0xffd201e0, 8, /* IMR8SA / IMCR8SA */
+	  { 0, 0, 0, 0,
+	    0, MSU_MSU, MSU_MSU2, MSUG } },
+	{ 0xffd201a4, 0xffd201e4, 8, /* IMR9SA / IMCR9SA */
+	  { 0, RWDT0, CMT2, CMT0,
+	    0, 0, 0, 0 } },
+	{ 0xffd201ac, 0xffd201ec, 8, /* IMR11SA / IMCR11SA */
+	  { 0, 0, 0, 0,
+	    0, TSIF1, LMB, TSIF0 } },
+	{ 0xffd201b0, 0xffd201f0, 8, /* IMR12SA / IMCR12SA */
+	  { 0, 0, 0, 0,
+	    0, 0, PINTCS_PINT2, PINTCS_PINT1 } },
+	{ 0xffd50180, 0xffd501c0, 8, /* IMR0SA3 / IMCR0SA3 */
+	  { RTDMAC_2_DEI6, RTDMAC_2_DEI7, RTDMAC_2_DEI8, RTDMAC_2_DEI9,
+	    RTDMAC_3_DEI10, RTDMAC_3_DEI11, 0, 0 } },
+	{ 0xffd50190, 0xffd501d0, 8, /* IMR4SA3 / IMCR4SA3 */
+	  { FRC, 0, 0, GCU,
+	    LCDC1, CSIRX, DSITX0_DSITX00, DSITX0_DSITX01 } },
+	{ 0xffd50194, 0xffd501d4, 8, /* IMR5SA3 / IMCR5SA3 */
+	  { SPU2_SPU0, SPU2_SPU1, FSI, 0,
+	    0, 0, 0, 0 } },
+	{ 0xffd50198, 0xffd501d8, 8, /* IMR6SA3 / IMCR6SA3 */
+	  { TMU1_TUNI10, TMU1_TUNI11, TMU1_TUNI12, 0,
+	    TSIF2, CMT4, 0, 0 } },
+	{ 0xffd5019c, 0xffd501dc, 8, /* IMR7SA3 / IMCR7SA3 */
+	  { MFIS2, CPORTS2R, 0, 0,
+	    0, 0, 0, TSG } },
+	{ 0xffd501a0, 0xffd501e0, 8, /* IMR8SA3 / IMCR8SA3 */
+	  { DMASCH1, 0, SCUW, VIO60,
+	    VIO61, CEU21, 0, CSI21 } },
+	{ 0xffd501a4, 0xffd501e4, 8, /* IMR9SA3 / IMCR9SA3 */
+	  { DSITX1_DSITX10, DSITX1_DSITX11, DISP, DSRV,
+	    EMUX2_EMUX20I, EMUX2_EMUX21I, MSTIF0_MST00I, MSTIF0_MST01I } },
+	{ 0xffd501a8, 0xffd501e8, 8, /* IMR10SA3 / IMCR10SA3 */
+	  { MSTIF0_MST00I, MSTIF0_MST01I, 0, 0,
+	    0, 0, 0, 0  } },
+	{ 0xffd60180, 0xffd601c0, 8, /* IMR0SA4 / IMCR0SA4 */
+	  { SPUV, 0, 0, 0,
+	    0, 0, 0, 0  } },
+};
+
+/* Priority is needed for INTCA to receive the INTCS interrupt */
+static struct intc_prio_reg intcs_prio_registers[] = {
+	{ 0xffd20000, 0, 16, 4, /* IPRAS */ { CTI, 0, _2DDMAC_2DDM0, ICB } },
+	{ 0xffd20004, 0, 16, 4, /* IPRBS */ { JPU_JPEG, LCDC, 0, LCRC } },
+	{ 0xffd20008, 0, 16, 4, /* IPRCS */ { BBIF2, 0, 0, 0 } },
+	{ 0xffd2000c, 0, 16, 4, /* IPRDS */ { PINTCS_PINT1, PINTCS_PINT2,
+					      0, 0 } },
+	{ 0xffd20010, 0, 16, 4, /* IPRES */ { RTDMAC_0, CEU, MFI, VPU } },
+	{ 0xffd20014, 0, 16, 4, /* IPRFS */ { KEYSC_KEY, RTDMAC_1,
+					      CMT2, CMT0 } },
+	{ 0xffd20018, 0, 16, 4, /* IPRGS */ { TMU0_TUNI00, TMU0_TUNI01,
+					      TMU0_TUNI02, TSIF1 } },
+	{ 0xffd2001c, 0, 16, 4, /* IPRHS */ { VINT, 0, 0, 0 } },
+	{ 0xffd20020, 0, 16, 4, /* IPRIS */ { 0, MSIOF, TSIF0, 0 } },
+	{ 0xffd20024, 0, 16, 4, /* IPRJS */ { 0, _3DG_SGX543, MSUG, MSU } },
+	{ 0xffd20028, 0, 16, 4, /* IPRKS */ { 0, ASA, LMB, PEP } },
+	{ 0xffd20030, 0, 16, 4, /* IPRMS */ { 0, 0, 0, RWDT0 } },
+	{ 0xffd50000, 0, 16, 4, /* IPRAS3 */ { RTDMAC_2, 0, 0, 0 } },
+	{ 0xffd50004, 0, 16, 4, /* IPRBS3 */ { RTDMAC_3, 0, 0, 0 } },
+	{ 0xffd50020, 0, 16, 4, /* IPRIS3 */ { FRC, 0, 0, 0 } },
+	{ 0xffd50024, 0, 16, 4, /* IPRJS3 */ { LCDC1, CSIRX, DSITX0, 0 } },
+	{ 0xffd50028, 0, 16, 4, /* IPRKS3 */ { SPU2, 0, FSI, 0 } },
+	{ 0xffd50030, 0, 16, 4, /* IPRMS3 */ { TMU1, 0, 0, TSIF2 } },
+	{ 0xffd50034, 0, 16, 4, /* IPRNS3 */ { CMT4, 0, 0, 0 } },
+	{ 0xffd50038, 0, 16, 4, /* IPROS3 */ { MFIS2, CPORTS2R, 0, 0 } },
+	{ 0xffd50040, 0, 16, 4, /* IPRQS3 */ { DMASCH1, 0, SCUW, VIO60 } },
+	{ 0xffd50044, 0, 16, 4, /* IPRRS3 */ { VIO61, CEU21, 0, CSI21 } },
+	{ 0xffd50048, 0, 16, 4, /* IPRSS3 */ { DSITX1_DSITX10, DSITX1_DSITX11,
+					       DISP, DSRV } },
+	{ 0xffd5004c, 0, 16, 4, /* IPRTS3 */ { EMUX2_EMUX20I, EMUX2_EMUX21I,
+					       MSTIF0_MST00I, MSTIF0_MST01I } },
+	{ 0xffd50050, 0, 16, 4, /* IPRUS3 */ { MSTIF1_MST10I, MSTIF1_MST11I,
+					       0, 0 } },
+	{ 0xffd60000, 0, 16, 4, /* IPRAS4 */ { SPUV, 0, 0, 0 } },
+};
+
+static struct resource intcs_resources[] __initdata = {
+	[0] = {
+		.start	= 0xffd20000,
+		.end	= 0xffd201ff,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 0xffd50000,
+		.end	= 0xffd501ff,
+		.flags	= IORESOURCE_MEM,
+	},
+	[2] = {
+		.start	= 0xffd60000,
+		.end	= 0xffd601ff,
+		.flags	= IORESOURCE_MEM,
+	}
+};
+
+static struct intc_desc intcs_desc __initdata = {
+	.name = "sh73a0-intcs",
+	.resource = intcs_resources,
+	.num_resources = ARRAY_SIZE(intcs_resources),
+	.hw = INTC_HW_DESC(intcs_vectors, intcs_groups, intcs_mask_registers,
+			   intcs_prio_registers, NULL, NULL),
+};
+
+static struct irqaction sh73a0_intcs_cascade;
+
+static irqreturn_t sh73a0_intcs_demux(int irq, void *dev_id)
+{
+	unsigned int evtcodeas = ioread32((void __iomem *)dev_id);
+
+	generic_handle_irq(intcs_evt2irq(evtcodeas));
+
+	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);
+
+	gic_init(0, 29, gic_dist_base, gic_cpu_base);
+
+	register_intc_controller(&intcs_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);
+}
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-shmobile/Kconfig linux-libre-2.6.38-gnu1/arch/arm/mach-shmobile/Kconfig
--- linux-libre-2.6.37-gnu1/arch/arm/mach-shmobile/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-shmobile/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -5,26 +5,27 @@ comment "SH-Mobile System Type"
 config ARCH_SH7367
 	bool "SH-Mobile G3 (SH7367)"
 	select CPU_V6
-	select HAVE_CLK
-	select COMMON_CLKDEV
 	select SH_CLK_CPG
-	select GENERIC_CLOCKEVENTS
+	select ARCH_WANT_OPTIONAL_GPIOLIB
 
 config ARCH_SH7377
 	bool "SH-Mobile G4 (SH7377)"
 	select CPU_V7
-	select HAVE_CLK
-	select COMMON_CLKDEV
 	select SH_CLK_CPG
-	select GENERIC_CLOCKEVENTS
+	select ARCH_WANT_OPTIONAL_GPIOLIB
 
 config ARCH_SH7372
 	bool "SH-Mobile AP4 (SH7372)"
 	select CPU_V7
-	select HAVE_CLK
-	select COMMON_CLKDEV
 	select SH_CLK_CPG
-	select GENERIC_CLOCKEVENTS
+	select ARCH_WANT_OPTIONAL_GPIOLIB
+
+config ARCH_SH73A0
+	bool "SH-Mobile AG5 (R8A73A00)"
+	select CPU_V7
+	select SH_CLK_CPG
+	select ARCH_WANT_OPTIONAL_GPIOLIB
+	select ARM_GIC
 
 comment "SH-Mobile Board Type"
 
@@ -57,6 +58,17 @@ config AP4EVB_WVGA
 
 endchoice
 
+config MACH_AG5EVM
+	bool "AG5EVM board"
+	select ARCH_REQUIRE_GPIOLIB
+	select SH_LCD_MIPI_DSI
+	depends on ARCH_SH73A0
+
+config MACH_MACKEREL
+	bool "mackerel board"
+	depends on ARCH_SH7372
+	select ARCH_REQUIRE_GPIOLIB
+
 comment "SH-Mobile System Configuration"
 
 menu "Memory configuration"
@@ -64,8 +76,8 @@ menu "Memory configuration"
 config MEMORY_START
 	hex "Physical memory start address"
 	default "0x50000000" if MACH_G3EVM
-	default "0x40000000" if MACH_G4EVM
-	default "0x40000000" if MACH_AP4EVB
+	default "0x40000000" if MACH_G4EVM || MACH_AP4EVB || MACH_AG5EVM || \
+				MACH_MACKEREL
 	default "0x00000000"
 	---help---
 	  Tweak this only when porting to a new machine which does not
@@ -76,7 +88,8 @@ config MEMORY_SIZE
 	hex "Physical memory size"
 	default "0x08000000" if MACH_G3EVM
 	default "0x08000000" if MACH_G4EVM
-	default "0x10000000" if MACH_AP4EVB
+	default "0x20000000" if MACH_AG5EVM
+	default "0x10000000" if MACH_AP4EVB || MACH_MACKEREL
 	default "0x04000000"
 	help
 	  This sets the default memory size assumed by your kernel. It can
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-shmobile/localtimer.c linux-libre-2.6.38-gnu1/arch/arm/mach-shmobile/localtimer.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-shmobile/localtimer.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-shmobile/localtimer.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,25 @@
+/*
+ * SMP support for R-Mobile / SH-Mobile - local timer portion
+ *
+ * Copyright (C) 2010  Magnus Damm
+ *
+ * Based on vexpress, 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/smp.h>
+#include <linux/clockchips.h>
+#include <asm/smp_twd.h>
+#include <asm/localtimer.h>
+
+/*
+ * Setup the local clock events for a CPU.
+ */
+void __cpuinit local_timer_setup(struct clock_event_device *evt)
+{
+	evt->irq = 29;
+	twd_timer_setup(evt);
+}
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-shmobile/Makefile linux-libre-2.6.38-gnu1/arch/arm/mach-shmobile/Makefile
--- linux-libre-2.6.37-gnu1/arch/arm/mach-shmobile/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-shmobile/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -9,14 +9,34 @@ obj-y				:= timer.o console.o clock.o pm
 obj-$(CONFIG_ARCH_SH7367)	+= setup-sh7367.o clock-sh7367.o intc-sh7367.o
 obj-$(CONFIG_ARCH_SH7377)	+= setup-sh7377.o clock-sh7377.o intc-sh7377.o
 obj-$(CONFIG_ARCH_SH7372)	+= setup-sh7372.o clock-sh7372.o intc-sh7372.o
+obj-$(CONFIG_ARCH_SH73A0)	+= setup-sh73a0.o clock-sh73a0.o intc-sh73a0.o
+
+# SMP objects
+smp-y				:= platsmp.o headsmp.o
+smp-$(CONFIG_HOTPLUG_CPU)	+= hotplug.o
+smp-$(CONFIG_LOCAL_TIMERS)	+= localtimer.o
+smp-$(CONFIG_ARCH_SH73A0)	+= smp-sh73a0.o
 
 # Pinmux setup
-pfc-$(CONFIG_ARCH_SH7367)	:= pfc-sh7367.o
-pfc-$(CONFIG_ARCH_SH7377)	:= pfc-sh7377.o
-pfc-$(CONFIG_ARCH_SH7372)	:= pfc-sh7372.o
-obj-$(CONFIG_GENERIC_GPIO)	+= $(pfc-y)
+pfc-y				:=
+pfc-$(CONFIG_ARCH_SH7367)	+= pfc-sh7367.o
+pfc-$(CONFIG_ARCH_SH7377)	+= pfc-sh7377.o
+pfc-$(CONFIG_ARCH_SH7372)	+= pfc-sh7372.o
+pfc-$(CONFIG_ARCH_SH73A0)	+= pfc-sh73a0.o
+
+# IRQ objects
+obj-$(CONFIG_ARCH_SH7367)	+= entry-intc.o
+obj-$(CONFIG_ARCH_SH7377)	+= entry-intc.o
+obj-$(CONFIG_ARCH_SH7372)	+= entry-intc.o
+obj-$(CONFIG_ARCH_SH73A0)	+= entry-gic.o
 
 # Board objects
 obj-$(CONFIG_MACH_G3EVM)	+= board-g3evm.o
 obj-$(CONFIG_MACH_G4EVM)	+= board-g4evm.o
 obj-$(CONFIG_MACH_AP4EVB)	+= board-ap4evb.o
+obj-$(CONFIG_MACH_AG5EVM)	+= board-ag5evm.o
+obj-$(CONFIG_MACH_MACKEREL)	+= board-mackerel.o
+
+# Framework support
+obj-$(CONFIG_SMP)		+= $(smp-y)
+obj-$(CONFIG_GENERIC_GPIO)	+= $(pfc-y)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-shmobile/pfc-sh73a0.c linux-libre-2.6.38-gnu1/arch/arm/mach-shmobile/pfc-sh73a0.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-shmobile/pfc-sh73a0.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-shmobile/pfc-sh73a0.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,2746 @@
+/*
+ * sh73a0 processor support - PFC hardware block
+ *
+ * Copyright (C) 2010 Renesas Solutions Corp.
+ * Copyright (C) 2010 NISHIMOTO Hiroki
+ *
+ * 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/init.h>
+#include <linux/kernel.h>
+#include <linux/gpio.h>
+#include <mach/sh73a0.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)
+
+enum {
+	PINMUX_RESERVED = 0,
+
+	PINMUX_DATA_BEGIN,
+	PORT_310(DATA),			/* PORT0_DATA -> PORT309_DATA */
+	PINMUX_DATA_END,
+
+	PINMUX_INPUT_BEGIN,
+	PORT_310(IN),			/* PORT0_IN -> PORT309_IN */
+	PINMUX_INPUT_END,
+
+	PINMUX_INPUT_PULLUP_BEGIN,
+	PORT_310(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 */
+	PINMUX_INPUT_PULLDOWN_END,
+
+	PINMUX_OUTPUT_BEGIN,
+	PORT_310(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 */
+
+	MSEL2CR_MSEL19_0, MSEL2CR_MSEL19_1,
+	MSEL2CR_MSEL18_0, MSEL2CR_MSEL18_1,
+	MSEL2CR_MSEL17_0, MSEL2CR_MSEL17_1,
+	MSEL2CR_MSEL16_0, MSEL2CR_MSEL16_1,
+	MSEL2CR_MSEL14_0, MSEL2CR_MSEL14_1,
+	MSEL2CR_MSEL13_0, MSEL2CR_MSEL13_1,
+	MSEL2CR_MSEL12_0, MSEL2CR_MSEL12_1,
+	MSEL2CR_MSEL11_0, MSEL2CR_MSEL11_1,
+	MSEL2CR_MSEL10_0, MSEL2CR_MSEL10_1,
+	MSEL2CR_MSEL9_0, MSEL2CR_MSEL9_1,
+	MSEL2CR_MSEL8_0, MSEL2CR_MSEL8_1,
+	MSEL2CR_MSEL7_0, MSEL2CR_MSEL7_1,
+	MSEL2CR_MSEL6_0, MSEL2CR_MSEL6_1,
+	MSEL2CR_MSEL4_0, MSEL2CR_MSEL4_1,
+	MSEL2CR_MSEL5_0, MSEL2CR_MSEL5_1,
+	MSEL2CR_MSEL3_0, MSEL2CR_MSEL3_1,
+	MSEL2CR_MSEL2_0, MSEL2CR_MSEL2_1,
+	MSEL2CR_MSEL1_0, MSEL2CR_MSEL1_1,
+	MSEL2CR_MSEL0_0, MSEL2CR_MSEL0_1,
+	MSEL3CR_MSEL28_0, MSEL3CR_MSEL28_1,
+	MSEL3CR_MSEL15_0, MSEL3CR_MSEL15_1,
+	MSEL3CR_MSEL11_0, MSEL3CR_MSEL11_1,
+	MSEL3CR_MSEL9_0, MSEL3CR_MSEL9_1,
+	MSEL3CR_MSEL6_0, MSEL3CR_MSEL6_1,
+	MSEL3CR_MSEL2_0, MSEL3CR_MSEL2_1,
+	MSEL4CR_MSEL29_0, MSEL4CR_MSEL29_1,
+	MSEL4CR_MSEL27_0, MSEL4CR_MSEL27_1,
+	MSEL4CR_MSEL26_0, MSEL4CR_MSEL26_1,
+	MSEL4CR_MSEL22_0, MSEL4CR_MSEL22_1,
+	MSEL4CR_MSEL21_0, MSEL4CR_MSEL21_1,
+	MSEL4CR_MSEL20_0, MSEL4CR_MSEL20_1,
+	MSEL4CR_MSEL19_0, MSEL4CR_MSEL19_1,
+	MSEL4CR_MSEL15_0, MSEL4CR_MSEL15_1,
+	MSEL4CR_MSEL13_0, MSEL4CR_MSEL13_1,
+	MSEL4CR_MSEL12_0, MSEL4CR_MSEL12_1,
+	MSEL4CR_MSEL11_0, MSEL4CR_MSEL11_1,
+	MSEL4CR_MSEL10_0, MSEL4CR_MSEL10_1,
+	MSEL4CR_MSEL9_0, MSEL4CR_MSEL9_1,
+	MSEL4CR_MSEL8_0, MSEL4CR_MSEL8_1,
+	MSEL4CR_MSEL7_0, MSEL4CR_MSEL7_1,
+	MSEL4CR_MSEL4_0, MSEL4CR_MSEL4_1,
+	MSEL4CR_MSEL1_0, MSEL4CR_MSEL1_1,
+	PINMUX_FUNCTION_END,
+
+	PINMUX_MARK_BEGIN,
+	/* Hardware manual Table 25-1 (Function 0-7) */
+	VBUS_0_MARK,
+	GPI0_MARK,
+	GPI1_MARK,
+	GPI2_MARK,
+	GPI3_MARK,
+	GPI4_MARK,
+	GPI5_MARK,
+	GPI6_MARK,
+	GPI7_MARK,
+	SCIFA7_RXD_MARK,
+	SCIFA7_CTS__MARK,
+	GPO7_MARK, MFG0_OUT2_MARK,
+	GPO6_MARK, MFG1_OUT2_MARK,
+	GPO5_MARK, SCIFA0_SCK_MARK, FSICOSLDT3_MARK, PORT16_VIO_CKOR_MARK,
+	SCIFA0_TXD_MARK,
+	SCIFA7_TXD_MARK,
+	SCIFA7_RTS__MARK, PORT19_VIO_CKO2_MARK,
+	GPO0_MARK,
+	GPO1_MARK,
+	GPO2_MARK, STATUS0_MARK,
+	GPO3_MARK, STATUS1_MARK,
+	GPO4_MARK, STATUS2_MARK,
+	VINT_MARK,
+	TCKON_MARK,
+	XDVFS1_MARK, PORT27_I2C_SCL2_MARK, PORT27_I2C_SCL3_MARK, \
+	MFG0_OUT1_MARK, PORT27_IROUT_MARK,
+	XDVFS2_MARK, PORT28_I2C_SDA2_MARK, PORT28_I2C_SDA3_MARK, \
+	PORT28_TPU1TO1_MARK,
+	SIM_RST_MARK, PORT29_TPU1TO1_MARK,
+	SIM_CLK_MARK, PORT30_VIO_CKOR_MARK,
+	SIM_D_MARK, PORT31_IROUT_MARK,
+	SCIFA4_TXD_MARK,
+	SCIFA4_RXD_MARK, XWUP_MARK,
+	SCIFA4_RTS__MARK,
+	SCIFA4_CTS__MARK,
+	FSIBOBT_MARK, FSIBIBT_MARK,
+	FSIBOLR_MARK, FSIBILR_MARK,
+	FSIBOSLD_MARK,
+	FSIBISLD_MARK,
+	VACK_MARK,
+	XTAL1L_MARK,
+	SCIFA0_RTS__MARK, FSICOSLDT2_MARK,
+	SCIFA0_RXD_MARK,
+	SCIFA0_CTS__MARK, FSICOSLDT1_MARK,
+	FSICOBT_MARK, FSICIBT_MARK, FSIDOBT_MARK, FSIDIBT_MARK,
+	FSICOLR_MARK, FSICILR_MARK, FSIDOLR_MARK, FSIDILR_MARK,
+	FSICOSLD_MARK, PORT47_FSICSPDIF_MARK,
+	FSICISLD_MARK, FSIDISLD_MARK,
+	FSIACK_MARK, PORT49_IRDA_OUT_MARK, PORT49_IROUT_MARK, FSIAOMC_MARK,
+	FSIAOLR_MARK, BBIF2_TSYNC2_MARK, TPU2TO2_MARK, FSIAILR_MARK,
+
+	FSIAOBT_MARK, BBIF2_TSCK2_MARK, TPU2TO3_MARK, FSIAIBT_MARK,
+	FSIAOSLD_MARK, BBIF2_TXD2_MARK,
+	FSIASPDIF_MARK, PORT53_IRDA_IN_MARK, TPU3TO3_MARK, FSIBSPDIF_MARK, \
+	PORT53_FSICSPDIF_MARK,
+	FSIBCK_MARK, PORT54_IRDA_FIRSEL_MARK, TPU3TO2_MARK, FSIBOMC_MARK, \
+	FSICCK_MARK, FSICOMC_MARK,
+	FSIAISLD_MARK, TPU0TO0_MARK,
+	A0_MARK, BS__MARK,
+	A12_MARK, PORT58_KEYOUT7_MARK, TPU4TO2_MARK,
+	A13_MARK, PORT59_KEYOUT6_MARK, TPU0TO1_MARK,
+	A14_MARK, KEYOUT5_MARK,
+	A15_MARK, KEYOUT4_MARK,
+	A16_MARK, KEYOUT3_MARK, MSIOF0_SS1_MARK,
+	A17_MARK, KEYOUT2_MARK, MSIOF0_TSYNC_MARK,
+	A18_MARK, KEYOUT1_MARK, MSIOF0_TSCK_MARK,
+	A19_MARK, KEYOUT0_MARK, MSIOF0_TXD_MARK,
+	A20_MARK, KEYIN0_MARK, MSIOF0_RSCK_MARK,
+	A21_MARK, KEYIN1_MARK, MSIOF0_RSYNC_MARK,
+	A22_MARK, KEYIN2_MARK, MSIOF0_MCK0_MARK,
+	A23_MARK, KEYIN3_MARK, MSIOF0_MCK1_MARK,
+	A24_MARK, KEYIN4_MARK, MSIOF0_RXD_MARK,
+	A25_MARK, KEYIN5_MARK, MSIOF0_SS2_MARK,
+	A26_MARK, KEYIN6_MARK,
+	KEYIN7_MARK,
+	D0_NAF0_MARK,
+	D1_NAF1_MARK,
+	D2_NAF2_MARK,
+	D3_NAF3_MARK,
+	D4_NAF4_MARK,
+	D5_NAF5_MARK,
+	D6_NAF6_MARK,
+	D7_NAF7_MARK,
+	D8_NAF8_MARK,
+	D9_NAF9_MARK,
+	D10_NAF10_MARK,
+	D11_NAF11_MARK,
+	D12_NAF12_MARK,
+	D13_NAF13_MARK,
+	D14_NAF14_MARK,
+	D15_NAF15_MARK,
+	CS4__MARK,
+	CS5A__MARK, PORT91_RDWR_MARK,
+	CS5B__MARK, FCE1__MARK,
+	CS6B__MARK, DACK0_MARK,
+	FCE0__MARK, CS6A__MARK,
+	WAIT__MARK, DREQ0_MARK,
+	RD__FSC_MARK,
+	WE0__FWE_MARK, RDWR_FWE_MARK,
+	WE1__MARK,
+	FRB_MARK,
+	CKO_MARK,
+	NBRSTOUT__MARK,
+	NBRST__MARK,
+	BBIF2_TXD_MARK,
+	BBIF2_RXD_MARK,
+	BBIF2_SYNC_MARK,
+	BBIF2_SCK_MARK,
+	SCIFA3_CTS__MARK, MFG3_IN2_MARK,
+	SCIFA3_RXD_MARK, MFG3_IN1_MARK,
+	BBIF1_SS2_MARK, SCIFA3_RTS__MARK, MFG3_OUT1_MARK,
+	SCIFA3_TXD_MARK,
+	HSI_RX_DATA_MARK, BBIF1_RXD_MARK,
+	HSI_TX_WAKE_MARK, BBIF1_TSCK_MARK,
+	HSI_TX_DATA_MARK, BBIF1_TSYNC_MARK,
+	HSI_TX_READY_MARK, BBIF1_TXD_MARK,
+	HSI_RX_READY_MARK, BBIF1_RSCK_MARK, PORT115_I2C_SCL2_MARK, \
+	PORT115_I2C_SCL3_MARK,
+	HSI_RX_WAKE_MARK, BBIF1_RSYNC_MARK, PORT116_I2C_SDA2_MARK, \
+	PORT116_I2C_SDA3_MARK,
+	HSI_RX_FLAG_MARK, BBIF1_SS1_MARK, BBIF1_FLOW_MARK,
+	HSI_TX_FLAG_MARK,
+	VIO_VD_MARK, PORT128_LCD2VSYN_MARK, VIO2_VD_MARK, LCD2D0_MARK,
+
+	VIO_HD_MARK, PORT129_LCD2HSYN_MARK, PORT129_LCD2CS__MARK, \
+	VIO2_HD_MARK, LCD2D1_MARK,
+	VIO_D0_MARK, PORT130_MSIOF2_RXD_MARK, LCD2D10_MARK,
+	VIO_D1_MARK, PORT131_KEYOUT6_MARK, PORT131_MSIOF2_SS1_MARK, \
+	PORT131_KEYOUT11_MARK, LCD2D11_MARK,
+	VIO_D2_MARK, PORT132_KEYOUT7_MARK, PORT132_MSIOF2_SS2_MARK, \
+	PORT132_KEYOUT10_MARK, LCD2D12_MARK,
+	VIO_D3_MARK, MSIOF2_TSYNC_MARK, LCD2D13_MARK,
+	VIO_D4_MARK, MSIOF2_TXD_MARK, LCD2D14_MARK,
+	VIO_D5_MARK, MSIOF2_TSCK_MARK, LCD2D15_MARK,
+	VIO_D6_MARK, PORT136_KEYOUT8_MARK, LCD2D16_MARK,
+	VIO_D7_MARK, PORT137_KEYOUT9_MARK, LCD2D17_MARK,
+	VIO_D8_MARK, PORT138_KEYOUT8_MARK, VIO2_D0_MARK, LCD2D6_MARK,
+	VIO_D9_MARK, PORT139_KEYOUT9_MARK, VIO2_D1_MARK, LCD2D7_MARK,
+	VIO_D10_MARK, TPU0TO2_MARK, VIO2_D2_MARK, LCD2D8_MARK,
+	VIO_D11_MARK, TPU0TO3_MARK, VIO2_D3_MARK, LCD2D9_MARK,
+	VIO_D12_MARK, PORT142_KEYOUT10_MARK, VIO2_D4_MARK, LCD2D2_MARK,
+	VIO_D13_MARK, PORT143_KEYOUT11_MARK, PORT143_KEYOUT6_MARK, \
+	VIO2_D5_MARK, LCD2D3_MARK,
+	VIO_D14_MARK, PORT144_KEYOUT7_MARK, VIO2_D6_MARK, LCD2D4_MARK,
+	VIO_D15_MARK, TPU1TO3_MARK, PORT145_LCD2DISP_MARK, \
+	PORT145_LCD2RS_MARK, VIO2_D7_MARK, LCD2D5_MARK,
+	VIO_CLK_MARK, LCD2DCK_MARK, PORT146_LCD2WR__MARK, VIO2_CLK_MARK, \
+	LCD2D18_MARK,
+	VIO_FIELD_MARK, LCD2RD__MARK, VIO2_FIELD_MARK, LCD2D19_MARK,
+	VIO_CKO_MARK,
+	A27_MARK, PORT149_RDWR_MARK, MFG0_IN1_MARK, PORT149_KEYOUT9_MARK,
+	MFG0_IN2_MARK,
+	TS_SPSYNC3_MARK, MSIOF2_RSCK_MARK,
+	TS_SDAT3_MARK, MSIOF2_RSYNC_MARK,
+	TPU1TO2_MARK, TS_SDEN3_MARK, PORT153_MSIOF2_SS1_MARK,
+	SCIFA2_TXD1_MARK, MSIOF2_MCK0_MARK,
+	SCIFA2_RXD1_MARK, MSIOF2_MCK1_MARK,
+	SCIFA2_RTS1__MARK, PORT156_MSIOF2_SS2_MARK,
+	SCIFA2_CTS1__MARK, PORT157_MSIOF2_RXD_MARK,
+	DINT__MARK, SCIFA2_SCK1_MARK, TS_SCK3_MARK,
+	PORT159_SCIFB_SCK_MARK, PORT159_SCIFA5_SCK_MARK, NMI_MARK,
+	PORT160_SCIFB_TXD_MARK, PORT160_SCIFA5_TXD_MARK,
+	PORT161_SCIFB_CTS__MARK, PORT161_SCIFA5_CTS__MARK,
+	PORT162_SCIFB_RXD_MARK, PORT162_SCIFA5_RXD_MARK,
+	PORT163_SCIFB_RTS__MARK, PORT163_SCIFA5_RTS__MARK, TPU3TO0_MARK,
+	LCDD0_MARK,
+	LCDD1_MARK, PORT193_SCIFA5_CTS__MARK, BBIF2_TSYNC1_MARK,
+	LCDD2_MARK, PORT194_SCIFA5_RTS__MARK, BBIF2_TSCK1_MARK,
+	LCDD3_MARK, PORT195_SCIFA5_RXD_MARK, BBIF2_TXD1_MARK,
+	LCDD4_MARK, PORT196_SCIFA5_TXD_MARK,
+	LCDD5_MARK, PORT197_SCIFA5_SCK_MARK, MFG2_OUT2_MARK, TPU2TO1_MARK,
+	LCDD6_MARK,
+	LCDD7_MARK, TPU4TO1_MARK, MFG4_OUT2_MARK,
+	LCDD8_MARK, D16_MARK,
+	LCDD9_MARK, D17_MARK,
+	LCDD10_MARK, D18_MARK,
+	LCDD11_MARK, D19_MARK,
+	LCDD12_MARK, D20_MARK,
+	LCDD13_MARK, D21_MARK,
+	LCDD14_MARK, D22_MARK,
+	LCDD15_MARK, PORT207_MSIOF0L_SS1_MARK, D23_MARK,
+	LCDD16_MARK, PORT208_MSIOF0L_SS2_MARK, D24_MARK,
+	LCDD17_MARK, D25_MARK,
+	LCDD18_MARK, DREQ2_MARK, PORT210_MSIOF0L_SS1_MARK, D26_MARK,
+	LCDD19_MARK, PORT211_MSIOF0L_SS2_MARK, D27_MARK,
+	LCDD20_MARK, TS_SPSYNC1_MARK, MSIOF0L_MCK0_MARK, D28_MARK,
+	LCDD21_MARK, TS_SDAT1_MARK, MSIOF0L_MCK1_MARK, D29_MARK,
+	LCDD22_MARK, TS_SDEN1_MARK, MSIOF0L_RSCK_MARK, D30_MARK,
+	LCDD23_MARK, TS_SCK1_MARK, MSIOF0L_RSYNC_MARK, D31_MARK,
+	LCDDCK_MARK, LCDWR__MARK,
+	LCDRD__MARK, DACK2_MARK, PORT217_LCD2RS_MARK, MSIOF0L_TSYNC_MARK, \
+	VIO2_FIELD3_MARK, PORT217_LCD2DISP_MARK,
+	LCDHSYN_MARK, LCDCS__MARK, LCDCS2__MARK, DACK3_MARK, \
+	PORT218_VIO_CKOR_MARK,
+	LCDDISP_MARK, LCDRS_MARK, PORT219_LCD2WR__MARK, DREQ3_MARK, \
+	MSIOF0L_TSCK_MARK, VIO2_CLK3_MARK, LCD2DCK_2_MARK,
+	LCDVSYN_MARK, LCDVSYN2_MARK,
+	LCDLCLK_MARK, DREQ1_MARK, PORT221_LCD2CS__MARK, PWEN_MARK, \
+	MSIOF0L_RXD_MARK, VIO2_HD3_MARK, PORT221_LCD2HSYN_MARK,
+	LCDDON_MARK, LCDDON2_MARK, DACK1_MARK, OVCN_MARK, MSIOF0L_TXD_MARK, \
+	VIO2_VD3_MARK, PORT222_LCD2VSYN_MARK,
+
+	SCIFA1_TXD_MARK, OVCN2_MARK,
+	EXTLP_MARK, SCIFA1_SCK_MARK, PORT226_VIO_CKO2_MARK,
+	SCIFA1_RTS__MARK, IDIN_MARK,
+	SCIFA1_RXD_MARK,
+	SCIFA1_CTS__MARK, MFG1_IN1_MARK,
+	MSIOF1_TXD_MARK, SCIFA2_TXD2_MARK,
+	MSIOF1_TSYNC_MARK, SCIFA2_CTS2__MARK,
+	MSIOF1_TSCK_MARK, SCIFA2_SCK2_MARK,
+	MSIOF1_RXD_MARK, SCIFA2_RXD2_MARK,
+	MSIOF1_RSCK_MARK, SCIFA2_RTS2__MARK, VIO2_CLK2_MARK, LCD2D20_MARK,
+	MSIOF1_RSYNC_MARK, MFG1_IN2_MARK, VIO2_VD2_MARK, LCD2D21_MARK,
+	MSIOF1_MCK0_MARK, PORT236_I2C_SDA2_MARK,
+	MSIOF1_MCK1_MARK, PORT237_I2C_SCL2_MARK,
+	MSIOF1_SS1_MARK, VIO2_FIELD2_MARK, LCD2D22_MARK,
+	MSIOF1_SS2_MARK, VIO2_HD2_MARK, LCD2D23_MARK,
+	SCIFA6_TXD_MARK,
+	PORT241_IRDA_OUT_MARK, PORT241_IROUT_MARK, MFG4_OUT1_MARK, TPU4TO0_MARK,
+	PORT242_IRDA_IN_MARK, MFG4_IN2_MARK,
+	PORT243_IRDA_FIRSEL_MARK, PORT243_VIO_CKO2_MARK,
+	PORT244_SCIFA5_CTS__MARK, MFG2_IN1_MARK, PORT244_SCIFB_CTS__MARK, \
+	MSIOF2R_RXD_MARK,
+	PORT245_SCIFA5_RTS__MARK, MFG2_IN2_MARK, PORT245_SCIFB_RTS__MARK, \
+	MSIOF2R_TXD_MARK,
+	PORT246_SCIFA5_RXD_MARK, MFG1_OUT1_MARK, PORT246_SCIFB_RXD_MARK, \
+	TPU1TO0_MARK,
+	PORT247_SCIFA5_TXD_MARK, MFG3_OUT2_MARK, PORT247_SCIFB_TXD_MARK, \
+	TPU3TO1_MARK,
+	PORT248_SCIFA5_SCK_MARK, MFG2_OUT1_MARK, PORT248_SCIFB_SCK_MARK, \
+	TPU2TO0_MARK, PORT248_I2C_SCL3_MARK, MSIOF2R_TSCK_MARK,
+	PORT249_IROUT_MARK, MFG4_IN1_MARK, PORT249_I2C_SDA3_MARK, \
+	MSIOF2R_TSYNC_MARK,
+	SDHICLK0_MARK,
+	SDHICD0_MARK,
+	SDHID0_0_MARK,
+	SDHID0_1_MARK,
+	SDHID0_2_MARK,
+	SDHID0_3_MARK,
+	SDHICMD0_MARK,
+	SDHIWP0_MARK,
+	SDHICLK1_MARK,
+	SDHID1_0_MARK, TS_SPSYNC2_MARK,
+	SDHID1_1_MARK, TS_SDAT2_MARK,
+	SDHID1_2_MARK, TS_SDEN2_MARK,
+	SDHID1_3_MARK, TS_SCK2_MARK,
+	SDHICMD1_MARK,
+	SDHICLK2_MARK,
+	SDHID2_0_MARK, TS_SPSYNC4_MARK,
+	SDHID2_1_MARK, TS_SDAT4_MARK,
+	SDHID2_2_MARK, TS_SDEN4_MARK,
+	SDHID2_3_MARK, TS_SCK4_MARK,
+	SDHICMD2_MARK,
+	MMCCLK0_MARK,
+	MMCD0_0_MARK,
+	MMCD0_1_MARK,
+	MMCD0_2_MARK,
+	MMCD0_3_MARK,
+	MMCD0_4_MARK, TS_SPSYNC5_MARK,
+	MMCD0_5_MARK, TS_SDAT5_MARK,
+	MMCD0_6_MARK, TS_SDEN5_MARK,
+	MMCD0_7_MARK, TS_SCK5_MARK,
+	MMCCMD0_MARK,
+	RESETOUTS__MARK, EXTAL2OUT_MARK,
+	MCP_WAIT__MCP_FRB_MARK,
+	MCP_CKO_MARK, MMCCLK1_MARK,
+	MCP_D15_MCP_NAF15_MARK,
+	MCP_D14_MCP_NAF14_MARK,
+	MCP_D13_MCP_NAF13_MARK,
+	MCP_D12_MCP_NAF12_MARK,
+	MCP_D11_MCP_NAF11_MARK,
+	MCP_D10_MCP_NAF10_MARK,
+	MCP_D9_MCP_NAF9_MARK,
+	MCP_D8_MCP_NAF8_MARK, MMCCMD1_MARK,
+	MCP_D7_MCP_NAF7_MARK, MMCD1_7_MARK,
+
+	MCP_D6_MCP_NAF6_MARK, MMCD1_6_MARK,
+	MCP_D5_MCP_NAF5_MARK, MMCD1_5_MARK,
+	MCP_D4_MCP_NAF4_MARK, MMCD1_4_MARK,
+	MCP_D3_MCP_NAF3_MARK, MMCD1_3_MARK,
+	MCP_D2_MCP_NAF2_MARK, MMCD1_2_MARK,
+	MCP_D1_MCP_NAF1_MARK, MMCD1_1_MARK,
+	MCP_D0_MCP_NAF0_MARK, MMCD1_0_MARK,
+	MCP_NBRSTOUT__MARK,
+	MCP_WE0__MCP_FWE_MARK, MCP_RDWR_MCP_FWE_MARK,
+
+	/* MSEL2 special cases */
+	TSIF2_TS_XX1_MARK,
+	TSIF2_TS_XX2_MARK,
+	TSIF2_TS_XX3_MARK,
+	TSIF2_TS_XX4_MARK,
+	TSIF2_TS_XX5_MARK,
+	TSIF1_TS_XX1_MARK,
+	TSIF1_TS_XX2_MARK,
+	TSIF1_TS_XX3_MARK,
+	TSIF1_TS_XX4_MARK,
+	TSIF1_TS_XX5_MARK,
+	TSIF0_TS_XX1_MARK,
+	TSIF0_TS_XX2_MARK,
+	TSIF0_TS_XX3_MARK,
+	TSIF0_TS_XX4_MARK,
+	TSIF0_TS_XX5_MARK,
+	MST1_TS_XX1_MARK,
+	MST1_TS_XX2_MARK,
+	MST1_TS_XX3_MARK,
+	MST1_TS_XX4_MARK,
+	MST1_TS_XX5_MARK,
+	MST0_TS_XX1_MARK,
+	MST0_TS_XX2_MARK,
+	MST0_TS_XX3_MARK,
+	MST0_TS_XX4_MARK,
+	MST0_TS_XX5_MARK,
+
+	/* MSEL3 special cases */
+	SDHI0_VCCQ_MC0_ON_MARK,
+	SDHI0_VCCQ_MC0_OFF_MARK,
+	DEBUG_MON_VIO_MARK,
+	DEBUG_MON_LCDD_MARK,
+	LCDC_LCDC0_MARK,
+	LCDC_LCDC1_MARK,
+
+	/* MSEL4 special cases */
+	IRQ9_MEM_INT_MARK,
+	IRQ9_MCP_INT_MARK,
+	A11_MARK,
+	KEYOUT8_MARK,
+	TPU4TO3_MARK,
+	RESETA_N_PU_ON_MARK,
+	RESETA_N_PU_OFF_MARK,
+	EDBGREQ_PD_MARK,
+	EDBGREQ_PU_MARK,
+
+	/* Functions with pull-ups */
+	KEYIN0_PU_MARK,
+	KEYIN1_PU_MARK,
+	KEYIN2_PU_MARK,
+	KEYIN3_PU_MARK,
+	KEYIN4_PU_MARK,
+	KEYIN5_PU_MARK,
+	KEYIN6_PU_MARK,
+	KEYIN7_PU_MARK,
+	SDHID1_0_PU_MARK,
+	SDHID1_1_PU_MARK,
+	SDHID1_2_PU_MARK,
+	SDHID1_3_PU_MARK,
+	SDHICMD1_PU_MARK,
+	MMCCMD0_PU_MARK,
+	MMCCMD1_PU_MARK,
+	FSIACK_PU_MARK,
+	FSIAILR_PU_MARK,
+	FSIAIBT_PU_MARK,
+	FSIAISLD_PU_MARK,
+
+	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 */
+
+	/* Table 25-1 (I/O and Pull U/D) */
+	PORT_DATA_I_PD(0),
+	PORT_DATA_I_PU(1),
+	PORT_DATA_I_PU(2),
+	PORT_DATA_I_PU(3),
+	PORT_DATA_I_PU(4),
+	PORT_DATA_I_PU(5),
+	PORT_DATA_I_PU(6),
+	PORT_DATA_I_PU(7),
+	PORT_DATA_I_PU(8),
+	PORT_DATA_I_PD(9),
+	PORT_DATA_I_PD(10),
+	PORT_DATA_I_PU_PD(11),
+	PORT_DATA_IO_PU_PD(12),
+	PORT_DATA_IO_PU_PD(13),
+	PORT_DATA_IO_PU_PD(14),
+	PORT_DATA_IO_PU_PD(15),
+	PORT_DATA_IO_PD(16),
+	PORT_DATA_IO_PD(17),
+	PORT_DATA_IO_PU(18),
+	PORT_DATA_IO_PU(19),
+	PORT_DATA_O(20),
+	PORT_DATA_O(21),
+	PORT_DATA_O(22),
+	PORT_DATA_O(23),
+	PORT_DATA_O(24),
+	PORT_DATA_I_PD(25),
+	PORT_DATA_I_PD(26),
+	PORT_DATA_IO_PU(27),
+	PORT_DATA_IO_PU(28),
+	PORT_DATA_IO_PD(29),
+	PORT_DATA_IO_PD(30),
+	PORT_DATA_IO_PU(31),
+	PORT_DATA_IO_PD(32),
+	PORT_DATA_I_PU_PD(33),
+	PORT_DATA_IO_PD(34),
+	PORT_DATA_I_PU_PD(35),
+	PORT_DATA_IO_PD(36),
+	PORT_DATA_IO(37),
+	PORT_DATA_O(38),
+	PORT_DATA_I_PU(39),
+	PORT_DATA_I_PU_PD(40),
+	PORT_DATA_O(41),
+	PORT_DATA_IO_PD(42),
+	PORT_DATA_IO_PU_PD(43),
+	PORT_DATA_IO_PU_PD(44),
+	PORT_DATA_IO_PD(45),
+	PORT_DATA_IO_PD(46),
+	PORT_DATA_IO_PD(47),
+	PORT_DATA_I_PD(48),
+	PORT_DATA_IO_PU_PD(49),
+	PORT_DATA_IO_PD(50),
+
+	PORT_DATA_IO_PD(51),
+	PORT_DATA_O(52),
+	PORT_DATA_IO_PU_PD(53),
+	PORT_DATA_IO_PU_PD(54),
+	PORT_DATA_IO_PD(55),
+	PORT_DATA_I_PU_PD(56),
+	PORT_DATA_IO(57),
+	PORT_DATA_IO(58),
+	PORT_DATA_IO(59),
+	PORT_DATA_IO(60),
+	PORT_DATA_IO(61),
+	PORT_DATA_IO_PD(62),
+	PORT_DATA_IO_PD(63),
+	PORT_DATA_IO_PU_PD(64),
+	PORT_DATA_IO_PD(65),
+	PORT_DATA_IO_PU_PD(66),
+	PORT_DATA_IO_PU_PD(67),
+	PORT_DATA_IO_PU_PD(68),
+	PORT_DATA_IO_PU_PD(69),
+	PORT_DATA_IO_PU_PD(70),
+	PORT_DATA_IO_PU_PD(71),
+	PORT_DATA_IO_PU_PD(72),
+	PORT_DATA_I_PU_PD(73),
+	PORT_DATA_IO_PU(74),
+	PORT_DATA_IO_PU(75),
+	PORT_DATA_IO_PU(76),
+	PORT_DATA_IO_PU(77),
+	PORT_DATA_IO_PU(78),
+	PORT_DATA_IO_PU(79),
+	PORT_DATA_IO_PU(80),
+	PORT_DATA_IO_PU(81),
+	PORT_DATA_IO_PU(82),
+	PORT_DATA_IO_PU(83),
+	PORT_DATA_IO_PU(84),
+	PORT_DATA_IO_PU(85),
+	PORT_DATA_IO_PU(86),
+	PORT_DATA_IO_PU(87),
+	PORT_DATA_IO_PU(88),
+	PORT_DATA_IO_PU(89),
+	PORT_DATA_O(90),
+	PORT_DATA_IO_PU(91),
+	PORT_DATA_O(92),
+	PORT_DATA_IO_PU(93),
+	PORT_DATA_O(94),
+	PORT_DATA_I_PU_PD(95),
+	PORT_DATA_IO(96),
+	PORT_DATA_IO(97),
+	PORT_DATA_IO(98),
+	PORT_DATA_I_PU(99),
+	PORT_DATA_O(100),
+	PORT_DATA_O(101),
+	PORT_DATA_I_PU(102),
+	PORT_DATA_IO_PD(103),
+	PORT_DATA_I_PU_PD(104),
+	PORT_DATA_I_PD(105),
+	PORT_DATA_I_PD(106),
+	PORT_DATA_I_PU_PD(107),
+	PORT_DATA_I_PU_PD(108),
+	PORT_DATA_IO_PD(109),
+	PORT_DATA_IO_PD(110),
+	PORT_DATA_IO_PU_PD(111),
+	PORT_DATA_IO_PU_PD(112),
+	PORT_DATA_IO_PU_PD(113),
+	PORT_DATA_IO_PD(114),
+	PORT_DATA_IO_PU(115),
+	PORT_DATA_IO_PU(116),
+	PORT_DATA_IO_PU_PD(117),
+	PORT_DATA_IO_PU_PD(118),
+	PORT_DATA_IO_PD(128),
+
+	PORT_DATA_IO_PD(129),
+	PORT_DATA_IO_PU_PD(130),
+	PORT_DATA_IO_PD(131),
+	PORT_DATA_IO_PD(132),
+	PORT_DATA_IO_PD(133),
+	PORT_DATA_IO_PU_PD(134),
+	PORT_DATA_IO_PU_PD(135),
+	PORT_DATA_IO_PU_PD(136),
+	PORT_DATA_IO_PU_PD(137),
+	PORT_DATA_IO_PD(138),
+	PORT_DATA_IO_PD(139),
+	PORT_DATA_IO_PD(140),
+	PORT_DATA_IO_PD(141),
+	PORT_DATA_IO_PD(142),
+	PORT_DATA_IO_PD(143),
+	PORT_DATA_IO_PU_PD(144),
+	PORT_DATA_IO_PD(145),
+	PORT_DATA_IO_PU_PD(146),
+	PORT_DATA_IO_PU_PD(147),
+	PORT_DATA_IO_PU_PD(148),
+	PORT_DATA_IO_PU_PD(149),
+	PORT_DATA_I_PU_PD(150),
+	PORT_DATA_IO_PU_PD(151),
+	PORT_DATA_IO_PU_PD(152),
+	PORT_DATA_IO_PD(153),
+	PORT_DATA_IO_PD(154),
+	PORT_DATA_I_PU_PD(155),
+	PORT_DATA_IO_PU_PD(156),
+	PORT_DATA_I_PD(157),
+	PORT_DATA_IO_PD(158),
+	PORT_DATA_IO_PU_PD(159),
+	PORT_DATA_IO_PU_PD(160),
+	PORT_DATA_I_PU_PD(161),
+	PORT_DATA_I_PU_PD(162),
+	PORT_DATA_IO_PU_PD(163),
+	PORT_DATA_I_PU_PD(164),
+	PORT_DATA_IO_PD(192),
+	PORT_DATA_IO_PU_PD(193),
+	PORT_DATA_IO_PD(194),
+	PORT_DATA_IO_PU_PD(195),
+	PORT_DATA_IO_PD(196),
+	PORT_DATA_IO_PD(197),
+	PORT_DATA_IO_PD(198),
+	PORT_DATA_IO_PD(199),
+	PORT_DATA_IO_PU_PD(200),
+	PORT_DATA_IO_PU_PD(201),
+	PORT_DATA_IO_PU_PD(202),
+	PORT_DATA_IO_PU_PD(203),
+	PORT_DATA_IO_PU_PD(204),
+	PORT_DATA_IO_PU_PD(205),
+	PORT_DATA_IO_PU_PD(206),
+	PORT_DATA_IO_PD(207),
+	PORT_DATA_IO_PD(208),
+	PORT_DATA_IO_PD(209),
+	PORT_DATA_IO_PD(210),
+	PORT_DATA_IO_PD(211),
+	PORT_DATA_IO_PD(212),
+	PORT_DATA_IO_PD(213),
+	PORT_DATA_IO_PU_PD(214),
+	PORT_DATA_IO_PU_PD(215),
+	PORT_DATA_IO_PD(216),
+	PORT_DATA_IO_PD(217),
+	PORT_DATA_O(218),
+	PORT_DATA_IO_PD(219),
+	PORT_DATA_IO_PD(220),
+	PORT_DATA_IO_PU_PD(221),
+	PORT_DATA_IO_PU_PD(222),
+	PORT_DATA_I_PU_PD(223),
+	PORT_DATA_I_PU_PD(224),
+
+	PORT_DATA_IO_PU_PD(225),
+	PORT_DATA_O(226),
+	PORT_DATA_IO_PU_PD(227),
+	PORT_DATA_I_PU_PD(228),
+	PORT_DATA_I_PD(229),
+	PORT_DATA_IO(230),
+	PORT_DATA_IO_PU_PD(231),
+	PORT_DATA_IO_PU_PD(232),
+	PORT_DATA_I_PU_PD(233),
+	PORT_DATA_IO_PU_PD(234),
+	PORT_DATA_IO_PU_PD(235),
+	PORT_DATA_IO_PU_PD(236),
+	PORT_DATA_IO_PD(237),
+	PORT_DATA_IO_PU_PD(238),
+	PORT_DATA_IO_PU_PD(239),
+	PORT_DATA_IO_PU_PD(240),
+	PORT_DATA_O(241),
+	PORT_DATA_I_PD(242),
+	PORT_DATA_IO_PU_PD(243),
+	PORT_DATA_IO_PU_PD(244),
+	PORT_DATA_IO_PU_PD(245),
+	PORT_DATA_IO_PU_PD(246),
+	PORT_DATA_IO_PU_PD(247),
+	PORT_DATA_IO_PU_PD(248),
+	PORT_DATA_IO_PU_PD(249),
+	PORT_DATA_IO_PU_PD(250),
+	PORT_DATA_IO_PU_PD(251),
+	PORT_DATA_IO_PU_PD(252),
+	PORT_DATA_IO_PU_PD(253),
+	PORT_DATA_IO_PU_PD(254),
+	PORT_DATA_IO_PU_PD(255),
+	PORT_DATA_IO_PU_PD(256),
+	PORT_DATA_IO_PU_PD(257),
+	PORT_DATA_IO_PU_PD(258),
+	PORT_DATA_IO_PU_PD(259),
+	PORT_DATA_IO_PU_PD(260),
+	PORT_DATA_IO_PU_PD(261),
+	PORT_DATA_IO_PU_PD(262),
+	PORT_DATA_IO_PU_PD(263),
+	PORT_DATA_IO_PU_PD(264),
+	PORT_DATA_IO_PU_PD(265),
+	PORT_DATA_IO_PU_PD(266),
+	PORT_DATA_IO_PU_PD(267),
+	PORT_DATA_IO_PU_PD(268),
+	PORT_DATA_IO_PU_PD(269),
+	PORT_DATA_IO_PU_PD(270),
+	PORT_DATA_IO_PU_PD(271),
+	PORT_DATA_IO_PU_PD(272),
+	PORT_DATA_IO_PU_PD(273),
+	PORT_DATA_IO_PU_PD(274),
+	PORT_DATA_IO_PU_PD(275),
+	PORT_DATA_IO_PU_PD(276),
+	PORT_DATA_IO_PU_PD(277),
+	PORT_DATA_IO_PU_PD(278),
+	PORT_DATA_IO_PU_PD(279),
+	PORT_DATA_IO_PU_PD(280),
+	PORT_DATA_O(281),
+	PORT_DATA_O(282),
+	PORT_DATA_I_PU(288),
+	PORT_DATA_IO_PU_PD(289),
+	PORT_DATA_IO_PU_PD(290),
+	PORT_DATA_IO_PU_PD(291),
+	PORT_DATA_IO_PU_PD(292),
+	PORT_DATA_IO_PU_PD(293),
+	PORT_DATA_IO_PU_PD(294),
+	PORT_DATA_IO_PU_PD(295),
+	PORT_DATA_IO_PU_PD(296),
+	PORT_DATA_IO_PU_PD(297),
+	PORT_DATA_IO_PU_PD(298),
+
+	PORT_DATA_IO_PU_PD(299),
+	PORT_DATA_IO_PU_PD(300),
+	PORT_DATA_IO_PU_PD(301),
+	PORT_DATA_IO_PU_PD(302),
+	PORT_DATA_IO_PU_PD(303),
+	PORT_DATA_IO_PU_PD(304),
+	PORT_DATA_IO_PU_PD(305),
+	PORT_DATA_O(306),
+	PORT_DATA_O(307),
+	PORT_DATA_I_PU(308),
+	PORT_DATA_O(309),
+
+	/* Table 25-1 (Function 0-7) */
+	PINMUX_DATA(VBUS_0_MARK, PORT0_FN1),
+	PINMUX_DATA(GPI0_MARK, PORT1_FN1),
+	PINMUX_DATA(GPI1_MARK, PORT2_FN1),
+	PINMUX_DATA(GPI2_MARK, PORT3_FN1),
+	PINMUX_DATA(GPI3_MARK, PORT4_FN1),
+	PINMUX_DATA(GPI4_MARK, PORT5_FN1),
+	PINMUX_DATA(GPI5_MARK, PORT6_FN1),
+	PINMUX_DATA(GPI6_MARK, PORT7_FN1),
+	PINMUX_DATA(GPI7_MARK, PORT8_FN1),
+	PINMUX_DATA(SCIFA7_RXD_MARK, PORT12_FN2),
+	PINMUX_DATA(SCIFA7_CTS__MARK, PORT13_FN2),
+	PINMUX_DATA(GPO7_MARK, PORT14_FN1), \
+	PINMUX_DATA(MFG0_OUT2_MARK, PORT14_FN4),
+	PINMUX_DATA(GPO6_MARK, PORT15_FN1), \
+	PINMUX_DATA(MFG1_OUT2_MARK, PORT15_FN4),
+	PINMUX_DATA(GPO5_MARK, PORT16_FN1), \
+	PINMUX_DATA(SCIFA0_SCK_MARK, PORT16_FN2), \
+	PINMUX_DATA(FSICOSLDT3_MARK, PORT16_FN3), \
+	PINMUX_DATA(PORT16_VIO_CKOR_MARK, PORT16_FN4),
+	PINMUX_DATA(SCIFA0_TXD_MARK, PORT17_FN2),
+	PINMUX_DATA(SCIFA7_TXD_MARK, PORT18_FN2),
+	PINMUX_DATA(SCIFA7_RTS__MARK, PORT19_FN2), \
+	PINMUX_DATA(PORT19_VIO_CKO2_MARK, PORT19_FN3),
+	PINMUX_DATA(GPO0_MARK, PORT20_FN1),
+	PINMUX_DATA(GPO1_MARK, PORT21_FN1),
+	PINMUX_DATA(GPO2_MARK, PORT22_FN1), \
+	PINMUX_DATA(STATUS0_MARK, PORT22_FN2),
+	PINMUX_DATA(GPO3_MARK, PORT23_FN1), \
+	PINMUX_DATA(STATUS1_MARK, PORT23_FN2),
+	PINMUX_DATA(GPO4_MARK, PORT24_FN1), \
+	PINMUX_DATA(STATUS2_MARK, PORT24_FN2),
+	PINMUX_DATA(VINT_MARK, PORT25_FN1),
+	PINMUX_DATA(TCKON_MARK, PORT26_FN1),
+	PINMUX_DATA(XDVFS1_MARK, PORT27_FN1), \
+	PINMUX_DATA(PORT27_I2C_SCL2_MARK, PORT27_FN2, MSEL2CR_MSEL17_0,
+		MSEL2CR_MSEL16_1), \
+	PINMUX_DATA(PORT27_I2C_SCL3_MARK, PORT27_FN3, MSEL2CR_MSEL19_0,
+		MSEL2CR_MSEL18_0), \
+	PINMUX_DATA(MFG0_OUT1_MARK, PORT27_FN4), \
+	PINMUX_DATA(PORT27_IROUT_MARK, PORT27_FN7),
+	PINMUX_DATA(XDVFS2_MARK, PORT28_FN1), \
+	PINMUX_DATA(PORT28_I2C_SDA2_MARK, PORT28_FN2, MSEL2CR_MSEL17_0,
+		MSEL2CR_MSEL16_1), \
+	PINMUX_DATA(PORT28_I2C_SDA3_MARK, PORT28_FN3, MSEL2CR_MSEL19_0,
+		MSEL2CR_MSEL18_0), \
+	PINMUX_DATA(PORT28_TPU1TO1_MARK, PORT28_FN7),
+	PINMUX_DATA(SIM_RST_MARK, PORT29_FN1), \
+	PINMUX_DATA(PORT29_TPU1TO1_MARK, PORT29_FN4),
+	PINMUX_DATA(SIM_CLK_MARK, PORT30_FN1), \
+	PINMUX_DATA(PORT30_VIO_CKOR_MARK, PORT30_FN4),
+	PINMUX_DATA(SIM_D_MARK, PORT31_FN1), \
+	PINMUX_DATA(PORT31_IROUT_MARK, PORT31_FN4),
+	PINMUX_DATA(SCIFA4_TXD_MARK, PORT32_FN2),
+	PINMUX_DATA(SCIFA4_RXD_MARK, PORT33_FN2), \
+	PINMUX_DATA(XWUP_MARK, PORT33_FN3),
+	PINMUX_DATA(SCIFA4_RTS__MARK, PORT34_FN2),
+	PINMUX_DATA(SCIFA4_CTS__MARK, PORT35_FN2),
+	PINMUX_DATA(FSIBOBT_MARK, PORT36_FN1), \
+	PINMUX_DATA(FSIBIBT_MARK, PORT36_FN2),
+	PINMUX_DATA(FSIBOLR_MARK, PORT37_FN1), \
+	PINMUX_DATA(FSIBILR_MARK, PORT37_FN2),
+	PINMUX_DATA(FSIBOSLD_MARK, PORT38_FN1),
+	PINMUX_DATA(FSIBISLD_MARK, PORT39_FN1),
+	PINMUX_DATA(VACK_MARK, PORT40_FN1),
+	PINMUX_DATA(XTAL1L_MARK, PORT41_FN1),
+	PINMUX_DATA(SCIFA0_RTS__MARK, PORT42_FN2), \
+	PINMUX_DATA(FSICOSLDT2_MARK, PORT42_FN3),
+	PINMUX_DATA(SCIFA0_RXD_MARK, PORT43_FN2),
+	PINMUX_DATA(SCIFA0_CTS__MARK, PORT44_FN2), \
+	PINMUX_DATA(FSICOSLDT1_MARK, PORT44_FN3),
+	PINMUX_DATA(FSICOBT_MARK, PORT45_FN1), \
+	PINMUX_DATA(FSICIBT_MARK, PORT45_FN2), \
+	PINMUX_DATA(FSIDOBT_MARK, PORT45_FN3), \
+	PINMUX_DATA(FSIDIBT_MARK, PORT45_FN4),
+	PINMUX_DATA(FSICOLR_MARK, PORT46_FN1), \
+	PINMUX_DATA(FSICILR_MARK, PORT46_FN2), \
+	PINMUX_DATA(FSIDOLR_MARK, PORT46_FN3), \
+	PINMUX_DATA(FSIDILR_MARK, PORT46_FN4),
+	PINMUX_DATA(FSICOSLD_MARK, PORT47_FN1), \
+	PINMUX_DATA(PORT47_FSICSPDIF_MARK, PORT47_FN2),
+	PINMUX_DATA(FSICISLD_MARK, PORT48_FN1), \
+	PINMUX_DATA(FSIDISLD_MARK, PORT48_FN3),
+	PINMUX_DATA(FSIACK_MARK, PORT49_FN1), \
+	PINMUX_DATA(PORT49_IRDA_OUT_MARK, PORT49_FN2, MSEL4CR_MSEL19_1), \
+	PINMUX_DATA(PORT49_IROUT_MARK, PORT49_FN4), \
+	PINMUX_DATA(FSIAOMC_MARK, PORT49_FN5),
+	PINMUX_DATA(FSIAOLR_MARK, PORT50_FN1), \
+	PINMUX_DATA(BBIF2_TSYNC2_MARK, PORT50_FN2), \
+	PINMUX_DATA(TPU2TO2_MARK, PORT50_FN3), \
+	PINMUX_DATA(FSIAILR_MARK, PORT50_FN5),
+
+	PINMUX_DATA(FSIAOBT_MARK, PORT51_FN1), \
+	PINMUX_DATA(BBIF2_TSCK2_MARK, PORT51_FN2), \
+	PINMUX_DATA(TPU2TO3_MARK, PORT51_FN3), \
+	PINMUX_DATA(FSIAIBT_MARK, PORT51_FN5),
+	PINMUX_DATA(FSIAOSLD_MARK, PORT52_FN1), \
+	PINMUX_DATA(BBIF2_TXD2_MARK, PORT52_FN2),
+	PINMUX_DATA(FSIASPDIF_MARK, PORT53_FN1), \
+	PINMUX_DATA(PORT53_IRDA_IN_MARK, PORT53_FN2, MSEL4CR_MSEL19_1), \
+	PINMUX_DATA(TPU3TO3_MARK, PORT53_FN3), \
+	PINMUX_DATA(FSIBSPDIF_MARK, PORT53_FN5), \
+	PINMUX_DATA(PORT53_FSICSPDIF_MARK, PORT53_FN6),
+	PINMUX_DATA(FSIBCK_MARK, PORT54_FN1), \
+	PINMUX_DATA(PORT54_IRDA_FIRSEL_MARK, PORT54_FN2, MSEL4CR_MSEL19_1), \
+	PINMUX_DATA(TPU3TO2_MARK, PORT54_FN3), \
+	PINMUX_DATA(FSIBOMC_MARK, PORT54_FN5), \
+	PINMUX_DATA(FSICCK_MARK, PORT54_FN6), \
+	PINMUX_DATA(FSICOMC_MARK, PORT54_FN7),
+	PINMUX_DATA(FSIAISLD_MARK, PORT55_FN1), \
+	PINMUX_DATA(TPU0TO0_MARK, PORT55_FN3),
+	PINMUX_DATA(A0_MARK, PORT57_FN1), \
+	PINMUX_DATA(BS__MARK, PORT57_FN2),
+	PINMUX_DATA(A12_MARK, PORT58_FN1), \
+	PINMUX_DATA(PORT58_KEYOUT7_MARK, PORT58_FN2), \
+	PINMUX_DATA(TPU4TO2_MARK, PORT58_FN4),
+	PINMUX_DATA(A13_MARK, PORT59_FN1), \
+	PINMUX_DATA(PORT59_KEYOUT6_MARK, PORT59_FN2), \
+	PINMUX_DATA(TPU0TO1_MARK, PORT59_FN4),
+	PINMUX_DATA(A14_MARK, PORT60_FN1), \
+	PINMUX_DATA(KEYOUT5_MARK, PORT60_FN2),
+	PINMUX_DATA(A15_MARK, PORT61_FN1), \
+	PINMUX_DATA(KEYOUT4_MARK, PORT61_FN2),
+	PINMUX_DATA(A16_MARK, PORT62_FN1), \
+	PINMUX_DATA(KEYOUT3_MARK, PORT62_FN2), \
+	PINMUX_DATA(MSIOF0_SS1_MARK, PORT62_FN4, MSEL3CR_MSEL11_0),
+	PINMUX_DATA(A17_MARK, PORT63_FN1), \
+	PINMUX_DATA(KEYOUT2_MARK, PORT63_FN2), \
+	PINMUX_DATA(MSIOF0_TSYNC_MARK, PORT63_FN4, MSEL3CR_MSEL11_0),
+	PINMUX_DATA(A18_MARK, PORT64_FN1), \
+	PINMUX_DATA(KEYOUT1_MARK, PORT64_FN2), \
+	PINMUX_DATA(MSIOF0_TSCK_MARK, PORT64_FN4, MSEL3CR_MSEL11_0),
+	PINMUX_DATA(A19_MARK, PORT65_FN1), \
+	PINMUX_DATA(KEYOUT0_MARK, PORT65_FN2), \
+	PINMUX_DATA(MSIOF0_TXD_MARK, PORT65_FN4, MSEL3CR_MSEL11_0),
+	PINMUX_DATA(A20_MARK, PORT66_FN1), \
+	PINMUX_DATA(KEYIN0_MARK, PORT66_FN2), \
+	PINMUX_DATA(MSIOF0_RSCK_MARK, PORT66_FN4, MSEL3CR_MSEL11_0),
+	PINMUX_DATA(A21_MARK, PORT67_FN1), \
+	PINMUX_DATA(KEYIN1_MARK, PORT67_FN2), \
+	PINMUX_DATA(MSIOF0_RSYNC_MARK, PORT67_FN4, MSEL3CR_MSEL11_0),
+	PINMUX_DATA(A22_MARK, PORT68_FN1), \
+	PINMUX_DATA(KEYIN2_MARK, PORT68_FN2), \
+	PINMUX_DATA(MSIOF0_MCK0_MARK, PORT68_FN4, MSEL3CR_MSEL11_0),
+	PINMUX_DATA(A23_MARK, PORT69_FN1), \
+	PINMUX_DATA(KEYIN3_MARK, PORT69_FN2), \
+	PINMUX_DATA(MSIOF0_MCK1_MARK, PORT69_FN4, MSEL3CR_MSEL11_0),
+	PINMUX_DATA(A24_MARK, PORT70_FN1), \
+	PINMUX_DATA(KEYIN4_MARK, PORT70_FN2), \
+	PINMUX_DATA(MSIOF0_RXD_MARK, PORT70_FN4, MSEL3CR_MSEL11_0),
+	PINMUX_DATA(A25_MARK, PORT71_FN1), \
+	PINMUX_DATA(KEYIN5_MARK, PORT71_FN2), \
+	PINMUX_DATA(MSIOF0_SS2_MARK, PORT71_FN4, MSEL3CR_MSEL11_0),
+	PINMUX_DATA(A26_MARK, PORT72_FN1), \
+	PINMUX_DATA(KEYIN6_MARK, PORT72_FN2),
+	PINMUX_DATA(KEYIN7_MARK, PORT73_FN2),
+	PINMUX_DATA(D0_NAF0_MARK, PORT74_FN1),
+	PINMUX_DATA(D1_NAF1_MARK, PORT75_FN1),
+	PINMUX_DATA(D2_NAF2_MARK, PORT76_FN1),
+	PINMUX_DATA(D3_NAF3_MARK, PORT77_FN1),
+	PINMUX_DATA(D4_NAF4_MARK, PORT78_FN1),
+	PINMUX_DATA(D5_NAF5_MARK, PORT79_FN1),
+	PINMUX_DATA(D6_NAF6_MARK, PORT80_FN1),
+	PINMUX_DATA(D7_NAF7_MARK, PORT81_FN1),
+	PINMUX_DATA(D8_NAF8_MARK, PORT82_FN1),
+	PINMUX_DATA(D9_NAF9_MARK, PORT83_FN1),
+	PINMUX_DATA(D10_NAF10_MARK, PORT84_FN1),
+	PINMUX_DATA(D11_NAF11_MARK, PORT85_FN1),
+	PINMUX_DATA(D12_NAF12_MARK, PORT86_FN1),
+	PINMUX_DATA(D13_NAF13_MARK, PORT87_FN1),
+	PINMUX_DATA(D14_NAF14_MARK, PORT88_FN1),
+	PINMUX_DATA(D15_NAF15_MARK, PORT89_FN1),
+	PINMUX_DATA(CS4__MARK, PORT90_FN1),
+	PINMUX_DATA(CS5A__MARK, PORT91_FN1), \
+	PINMUX_DATA(PORT91_RDWR_MARK, PORT91_FN2),
+	PINMUX_DATA(CS5B__MARK, PORT92_FN1), \
+	PINMUX_DATA(FCE1__MARK, PORT92_FN2),
+	PINMUX_DATA(CS6B__MARK, PORT93_FN1), \
+	PINMUX_DATA(DACK0_MARK, PORT93_FN4),
+	PINMUX_DATA(FCE0__MARK, PORT94_FN1), \
+	PINMUX_DATA(CS6A__MARK, PORT94_FN2),
+	PINMUX_DATA(WAIT__MARK, PORT95_FN1), \
+	PINMUX_DATA(DREQ0_MARK, PORT95_FN2),
+	PINMUX_DATA(RD__FSC_MARK, PORT96_FN1),
+	PINMUX_DATA(WE0__FWE_MARK, PORT97_FN1), \
+	PINMUX_DATA(RDWR_FWE_MARK, PORT97_FN2),
+	PINMUX_DATA(WE1__MARK, PORT98_FN1),
+	PINMUX_DATA(FRB_MARK, PORT99_FN1),
+	PINMUX_DATA(CKO_MARK, PORT100_FN1),
+	PINMUX_DATA(NBRSTOUT__MARK, PORT101_FN1),
+	PINMUX_DATA(NBRST__MARK, PORT102_FN1),
+	PINMUX_DATA(BBIF2_TXD_MARK, PORT103_FN3),
+	PINMUX_DATA(BBIF2_RXD_MARK, PORT104_FN3),
+	PINMUX_DATA(BBIF2_SYNC_MARK, PORT105_FN3),
+	PINMUX_DATA(BBIF2_SCK_MARK, PORT106_FN3),
+	PINMUX_DATA(SCIFA3_CTS__MARK, PORT107_FN3), \
+	PINMUX_DATA(MFG3_IN2_MARK, PORT107_FN4),
+	PINMUX_DATA(SCIFA3_RXD_MARK, PORT108_FN3), \
+	PINMUX_DATA(MFG3_IN1_MARK, PORT108_FN4),
+	PINMUX_DATA(BBIF1_SS2_MARK, PORT109_FN2), \
+	PINMUX_DATA(SCIFA3_RTS__MARK, PORT109_FN3), \
+	PINMUX_DATA(MFG3_OUT1_MARK, PORT109_FN4),
+	PINMUX_DATA(SCIFA3_TXD_MARK, PORT110_FN3),
+	PINMUX_DATA(HSI_RX_DATA_MARK, PORT111_FN1), \
+	PINMUX_DATA(BBIF1_RXD_MARK, PORT111_FN3),
+	PINMUX_DATA(HSI_TX_WAKE_MARK, PORT112_FN1), \
+	PINMUX_DATA(BBIF1_TSCK_MARK, PORT112_FN3),
+	PINMUX_DATA(HSI_TX_DATA_MARK, PORT113_FN1), \
+	PINMUX_DATA(BBIF1_TSYNC_MARK, PORT113_FN3),
+	PINMUX_DATA(HSI_TX_READY_MARK, PORT114_FN1), \
+	PINMUX_DATA(BBIF1_TXD_MARK, PORT114_FN3),
+	PINMUX_DATA(HSI_RX_READY_MARK, PORT115_FN1), \
+	PINMUX_DATA(BBIF1_RSCK_MARK, PORT115_FN3), \
+	PINMUX_DATA(PORT115_I2C_SCL2_MARK, PORT115_FN5, MSEL2CR_MSEL17_1), \
+	PINMUX_DATA(PORT115_I2C_SCL3_MARK, PORT115_FN6, MSEL2CR_MSEL19_1),
+	PINMUX_DATA(HSI_RX_WAKE_MARK, PORT116_FN1), \
+	PINMUX_DATA(BBIF1_RSYNC_MARK, PORT116_FN3), \
+	PINMUX_DATA(PORT116_I2C_SDA2_MARK, PORT116_FN5, MSEL2CR_MSEL17_1), \
+	PINMUX_DATA(PORT116_I2C_SDA3_MARK, PORT116_FN6, MSEL2CR_MSEL19_1),
+	PINMUX_DATA(HSI_RX_FLAG_MARK, PORT117_FN1), \
+	PINMUX_DATA(BBIF1_SS1_MARK, PORT117_FN2), \
+	PINMUX_DATA(BBIF1_FLOW_MARK, PORT117_FN3),
+	PINMUX_DATA(HSI_TX_FLAG_MARK, PORT118_FN1),
+	PINMUX_DATA(VIO_VD_MARK, PORT128_FN1), \
+	PINMUX_DATA(PORT128_LCD2VSYN_MARK, PORT128_FN4, MSEL3CR_MSEL2_0), \
+	PINMUX_DATA(VIO2_VD_MARK, PORT128_FN6, MSEL4CR_MSEL27_0), \
+	PINMUX_DATA(LCD2D0_MARK, PORT128_FN7),
+
+	PINMUX_DATA(VIO_HD_MARK, PORT129_FN1), \
+	PINMUX_DATA(PORT129_LCD2HSYN_MARK, PORT129_FN4), \
+	PINMUX_DATA(PORT129_LCD2CS__MARK, PORT129_FN5), \
+	PINMUX_DATA(VIO2_HD_MARK, PORT129_FN6, MSEL4CR_MSEL27_0), \
+	PINMUX_DATA(LCD2D1_MARK, PORT129_FN7),
+	PINMUX_DATA(VIO_D0_MARK, PORT130_FN1), \
+	PINMUX_DATA(PORT130_MSIOF2_RXD_MARK, PORT130_FN3, MSEL4CR_MSEL11_0,
+		MSEL4CR_MSEL10_1), \
+	PINMUX_DATA(LCD2D10_MARK, PORT130_FN7),
+	PINMUX_DATA(VIO_D1_MARK, PORT131_FN1), \
+	PINMUX_DATA(PORT131_KEYOUT6_MARK, PORT131_FN2), \
+	PINMUX_DATA(PORT131_MSIOF2_SS1_MARK, PORT131_FN3), \
+	PINMUX_DATA(PORT131_KEYOUT11_MARK, PORT131_FN4), \
+	PINMUX_DATA(LCD2D11_MARK, PORT131_FN7),
+	PINMUX_DATA(VIO_D2_MARK, PORT132_FN1), \
+	PINMUX_DATA(PORT132_KEYOUT7_MARK, PORT132_FN2), \
+	PINMUX_DATA(PORT132_MSIOF2_SS2_MARK, PORT132_FN3), \
+	PINMUX_DATA(PORT132_KEYOUT10_MARK, PORT132_FN4), \
+	PINMUX_DATA(LCD2D12_MARK, PORT132_FN7),
+	PINMUX_DATA(VIO_D3_MARK, PORT133_FN1), \
+	PINMUX_DATA(MSIOF2_TSYNC_MARK, PORT133_FN3, MSEL4CR_MSEL11_0), \
+	PINMUX_DATA(LCD2D13_MARK, PORT133_FN7),
+	PINMUX_DATA(VIO_D4_MARK, PORT134_FN1), \
+	PINMUX_DATA(MSIOF2_TXD_MARK, PORT134_FN3, MSEL4CR_MSEL11_0), \
+	PINMUX_DATA(LCD2D14_MARK, PORT134_FN7),
+	PINMUX_DATA(VIO_D5_MARK, PORT135_FN1), \
+	PINMUX_DATA(MSIOF2_TSCK_MARK, PORT135_FN3, MSEL4CR_MSEL11_0), \
+	PINMUX_DATA(LCD2D15_MARK, PORT135_FN7),
+	PINMUX_DATA(VIO_D6_MARK, PORT136_FN1), \
+	PINMUX_DATA(PORT136_KEYOUT8_MARK, PORT136_FN2), \
+	PINMUX_DATA(LCD2D16_MARK, PORT136_FN7),
+	PINMUX_DATA(VIO_D7_MARK, PORT137_FN1), \
+	PINMUX_DATA(PORT137_KEYOUT9_MARK, PORT137_FN2), \
+	PINMUX_DATA(LCD2D17_MARK, PORT137_FN7),
+	PINMUX_DATA(VIO_D8_MARK, PORT138_FN1), \
+	PINMUX_DATA(PORT138_KEYOUT8_MARK, PORT138_FN2), \
+	PINMUX_DATA(VIO2_D0_MARK, PORT138_FN6), \
+	PINMUX_DATA(LCD2D6_MARK, PORT138_FN7),
+	PINMUX_DATA(VIO_D9_MARK, PORT139_FN1), \
+	PINMUX_DATA(PORT139_KEYOUT9_MARK, PORT139_FN2), \
+	PINMUX_DATA(VIO2_D1_MARK, PORT139_FN6), \
+	PINMUX_DATA(LCD2D7_MARK, PORT139_FN7),
+	PINMUX_DATA(VIO_D10_MARK, PORT140_FN1), \
+	PINMUX_DATA(TPU0TO2_MARK, PORT140_FN4), \
+	PINMUX_DATA(VIO2_D2_MARK, PORT140_FN6), \
+	PINMUX_DATA(LCD2D8_MARK, PORT140_FN7),
+	PINMUX_DATA(VIO_D11_MARK, PORT141_FN1), \
+	PINMUX_DATA(TPU0TO3_MARK, PORT141_FN4), \
+	PINMUX_DATA(VIO2_D3_MARK, PORT141_FN6), \
+	PINMUX_DATA(LCD2D9_MARK, PORT141_FN7),
+	PINMUX_DATA(VIO_D12_MARK, PORT142_FN1), \
+	PINMUX_DATA(PORT142_KEYOUT10_MARK, PORT142_FN2), \
+	PINMUX_DATA(VIO2_D4_MARK, PORT142_FN6), \
+	PINMUX_DATA(LCD2D2_MARK, PORT142_FN7),
+	PINMUX_DATA(VIO_D13_MARK, PORT143_FN1), \
+	PINMUX_DATA(PORT143_KEYOUT11_MARK, PORT143_FN2), \
+	PINMUX_DATA(PORT143_KEYOUT6_MARK, PORT143_FN3), \
+	PINMUX_DATA(VIO2_D5_MARK, PORT143_FN6), \
+	PINMUX_DATA(LCD2D3_MARK, PORT143_FN7),
+	PINMUX_DATA(VIO_D14_MARK, PORT144_FN1), \
+	PINMUX_DATA(PORT144_KEYOUT7_MARK, PORT144_FN2), \
+	PINMUX_DATA(VIO2_D6_MARK, PORT144_FN6), \
+	PINMUX_DATA(LCD2D4_MARK, PORT144_FN7),
+	PINMUX_DATA(VIO_D15_MARK, PORT145_FN1), \
+	PINMUX_DATA(TPU1TO3_MARK, PORT145_FN3), \
+	PINMUX_DATA(PORT145_LCD2DISP_MARK, PORT145_FN4), \
+	PINMUX_DATA(PORT145_LCD2RS_MARK, PORT145_FN5), \
+	PINMUX_DATA(VIO2_D7_MARK, PORT145_FN6), \
+	PINMUX_DATA(LCD2D5_MARK, PORT145_FN7),
+	PINMUX_DATA(VIO_CLK_MARK, PORT146_FN1), \
+	PINMUX_DATA(LCD2DCK_MARK, PORT146_FN4), \
+	PINMUX_DATA(PORT146_LCD2WR__MARK, PORT146_FN5), \
+	PINMUX_DATA(VIO2_CLK_MARK, PORT146_FN6, MSEL4CR_MSEL27_0), \
+	PINMUX_DATA(LCD2D18_MARK, PORT146_FN7),
+	PINMUX_DATA(VIO_FIELD_MARK, PORT147_FN1), \
+	PINMUX_DATA(LCD2RD__MARK, PORT147_FN4), \
+	PINMUX_DATA(VIO2_FIELD_MARK, PORT147_FN6, MSEL4CR_MSEL27_0), \
+	PINMUX_DATA(LCD2D19_MARK, PORT147_FN7),
+	PINMUX_DATA(VIO_CKO_MARK, PORT148_FN1),
+	PINMUX_DATA(A27_MARK, PORT149_FN1), \
+	PINMUX_DATA(PORT149_RDWR_MARK, PORT149_FN2), \
+	PINMUX_DATA(MFG0_IN1_MARK, PORT149_FN3), \
+	PINMUX_DATA(PORT149_KEYOUT9_MARK, PORT149_FN4),
+	PINMUX_DATA(MFG0_IN2_MARK, PORT150_FN3),
+	PINMUX_DATA(TS_SPSYNC3_MARK, PORT151_FN4), \
+	PINMUX_DATA(MSIOF2_RSCK_MARK, PORT151_FN5),
+	PINMUX_DATA(TS_SDAT3_MARK, PORT152_FN4), \
+	PINMUX_DATA(MSIOF2_RSYNC_MARK, PORT152_FN5),
+	PINMUX_DATA(TPU1TO2_MARK, PORT153_FN3), \
+	PINMUX_DATA(TS_SDEN3_MARK, PORT153_FN4), \
+	PINMUX_DATA(PORT153_MSIOF2_SS1_MARK, PORT153_FN5),
+	PINMUX_DATA(SCIFA2_TXD1_MARK, PORT154_FN2, MSEL3CR_MSEL9_0), \
+	PINMUX_DATA(MSIOF2_MCK0_MARK, PORT154_FN5),
+	PINMUX_DATA(SCIFA2_RXD1_MARK, PORT155_FN2, MSEL3CR_MSEL9_0), \
+	PINMUX_DATA(MSIOF2_MCK1_MARK, PORT155_FN5),
+	PINMUX_DATA(SCIFA2_RTS1__MARK, PORT156_FN2, MSEL3CR_MSEL9_0), \
+	PINMUX_DATA(PORT156_MSIOF2_SS2_MARK, PORT156_FN5),
+	PINMUX_DATA(SCIFA2_CTS1__MARK, PORT157_FN2, MSEL3CR_MSEL9_0), \
+	PINMUX_DATA(PORT157_MSIOF2_RXD_MARK, PORT157_FN5, MSEL4CR_MSEL11_0,
+		MSEL4CR_MSEL10_0),
+	PINMUX_DATA(DINT__MARK, PORT158_FN1), \
+	PINMUX_DATA(SCIFA2_SCK1_MARK, PORT158_FN2, MSEL3CR_MSEL9_0), \
+	PINMUX_DATA(TS_SCK3_MARK, PORT158_FN4),
+	PINMUX_DATA(PORT159_SCIFB_SCK_MARK, PORT159_FN1, MSEL4CR_MSEL22_0), \
+	PINMUX_DATA(PORT159_SCIFA5_SCK_MARK, PORT159_FN2, MSEL4CR_MSEL21_1), \
+	PINMUX_DATA(NMI_MARK, PORT159_FN3),
+	PINMUX_DATA(PORT160_SCIFB_TXD_MARK, PORT160_FN1, MSEL4CR_MSEL22_0), \
+	PINMUX_DATA(PORT160_SCIFA5_TXD_MARK, PORT160_FN2, MSEL4CR_MSEL21_1),
+	PINMUX_DATA(PORT161_SCIFB_CTS__MARK, PORT161_FN1, MSEL4CR_MSEL22_0), \
+	PINMUX_DATA(PORT161_SCIFA5_CTS__MARK, PORT161_FN2, MSEL4CR_MSEL21_1),
+	PINMUX_DATA(PORT162_SCIFB_RXD_MARK, PORT162_FN1, MSEL4CR_MSEL22_0), \
+	PINMUX_DATA(PORT162_SCIFA5_RXD_MARK, PORT162_FN2, MSEL4CR_MSEL21_1),
+	PINMUX_DATA(PORT163_SCIFB_RTS__MARK, PORT163_FN1, MSEL4CR_MSEL22_0), \
+	PINMUX_DATA(PORT163_SCIFA5_RTS__MARK, PORT163_FN2, MSEL4CR_MSEL21_1), \
+	PINMUX_DATA(TPU3TO0_MARK, PORT163_FN5),
+	PINMUX_DATA(LCDD0_MARK, PORT192_FN1),
+	PINMUX_DATA(LCDD1_MARK, PORT193_FN1), \
+	PINMUX_DATA(PORT193_SCIFA5_CTS__MARK, PORT193_FN3, MSEL4CR_MSEL21_0,
+		MSEL4CR_MSEL20_1), \
+	PINMUX_DATA(BBIF2_TSYNC1_MARK, PORT193_FN5),
+	PINMUX_DATA(LCDD2_MARK, PORT194_FN1), \
+	PINMUX_DATA(PORT194_SCIFA5_RTS__MARK, PORT194_FN3, MSEL4CR_MSEL21_0,
+		MSEL4CR_MSEL20_1), \
+	PINMUX_DATA(BBIF2_TSCK1_MARK, PORT194_FN5),
+	PINMUX_DATA(LCDD3_MARK, PORT195_FN1), \
+	PINMUX_DATA(PORT195_SCIFA5_RXD_MARK, PORT195_FN3, MSEL4CR_MSEL21_0,
+		MSEL4CR_MSEL20_1), \
+	PINMUX_DATA(BBIF2_TXD1_MARK, PORT195_FN5),
+	PINMUX_DATA(LCDD4_MARK, PORT196_FN1), \
+	PINMUX_DATA(PORT196_SCIFA5_TXD_MARK, PORT196_FN3, MSEL4CR_MSEL21_0,
+		MSEL4CR_MSEL20_1),
+	PINMUX_DATA(LCDD5_MARK, PORT197_FN1), \
+	PINMUX_DATA(PORT197_SCIFA5_SCK_MARK, PORT197_FN3, MSEL4CR_MSEL21_0,
+		MSEL4CR_MSEL20_1), \
+	PINMUX_DATA(MFG2_OUT2_MARK, PORT197_FN5), \
+	PINMUX_DATA(TPU2TO1_MARK, PORT197_FN7),
+	PINMUX_DATA(LCDD6_MARK, PORT198_FN1),
+	PINMUX_DATA(LCDD7_MARK, PORT199_FN1), \
+	PINMUX_DATA(TPU4TO1_MARK, PORT199_FN2), \
+	PINMUX_DATA(MFG4_OUT2_MARK, PORT199_FN5),
+	PINMUX_DATA(LCDD8_MARK, PORT200_FN1), \
+	PINMUX_DATA(D16_MARK, PORT200_FN6),
+	PINMUX_DATA(LCDD9_MARK, PORT201_FN1), \
+	PINMUX_DATA(D17_MARK, PORT201_FN6),
+	PINMUX_DATA(LCDD10_MARK, PORT202_FN1), \
+	PINMUX_DATA(D18_MARK, PORT202_FN6),
+	PINMUX_DATA(LCDD11_MARK, PORT203_FN1), \
+	PINMUX_DATA(D19_MARK, PORT203_FN6),
+	PINMUX_DATA(LCDD12_MARK, PORT204_FN1), \
+	PINMUX_DATA(D20_MARK, PORT204_FN6),
+	PINMUX_DATA(LCDD13_MARK, PORT205_FN1), \
+	PINMUX_DATA(D21_MARK, PORT205_FN6),
+	PINMUX_DATA(LCDD14_MARK, PORT206_FN1), \
+	PINMUX_DATA(D22_MARK, PORT206_FN6),
+	PINMUX_DATA(LCDD15_MARK, PORT207_FN1), \
+	PINMUX_DATA(PORT207_MSIOF0L_SS1_MARK, PORT207_FN2, MSEL3CR_MSEL11_1), \
+	PINMUX_DATA(D23_MARK, PORT207_FN6),
+	PINMUX_DATA(LCDD16_MARK, PORT208_FN1), \
+	PINMUX_DATA(PORT208_MSIOF0L_SS2_MARK, PORT208_FN2, MSEL3CR_MSEL11_1), \
+	PINMUX_DATA(D24_MARK, PORT208_FN6),
+	PINMUX_DATA(LCDD17_MARK, PORT209_FN1), \
+	PINMUX_DATA(D25_MARK, PORT209_FN6),
+	PINMUX_DATA(LCDD18_MARK, PORT210_FN1), \
+	PINMUX_DATA(DREQ2_MARK, PORT210_FN2), \
+	PINMUX_DATA(PORT210_MSIOF0L_SS1_MARK, PORT210_FN5, MSEL3CR_MSEL11_1), \
+	PINMUX_DATA(D26_MARK, PORT210_FN6),
+	PINMUX_DATA(LCDD19_MARK, PORT211_FN1), \
+	PINMUX_DATA(PORT211_MSIOF0L_SS2_MARK, PORT211_FN5, MSEL3CR_MSEL11_1), \
+	PINMUX_DATA(D27_MARK, PORT211_FN6),
+	PINMUX_DATA(LCDD20_MARK, PORT212_FN1), \
+	PINMUX_DATA(TS_SPSYNC1_MARK, PORT212_FN2), \
+	PINMUX_DATA(MSIOF0L_MCK0_MARK, PORT212_FN5, MSEL3CR_MSEL11_1), \
+	PINMUX_DATA(D28_MARK, PORT212_FN6),
+	PINMUX_DATA(LCDD21_MARK, PORT213_FN1), \
+	PINMUX_DATA(TS_SDAT1_MARK, PORT213_FN2), \
+	PINMUX_DATA(MSIOF0L_MCK1_MARK, PORT213_FN5, MSEL3CR_MSEL11_1), \
+	PINMUX_DATA(D29_MARK, PORT213_FN6),
+	PINMUX_DATA(LCDD22_MARK, PORT214_FN1), \
+	PINMUX_DATA(TS_SDEN1_MARK, PORT214_FN2), \
+	PINMUX_DATA(MSIOF0L_RSCK_MARK, PORT214_FN5, MSEL3CR_MSEL11_1), \
+	PINMUX_DATA(D30_MARK, PORT214_FN6),
+	PINMUX_DATA(LCDD23_MARK, PORT215_FN1), \
+	PINMUX_DATA(TS_SCK1_MARK, PORT215_FN2), \
+	PINMUX_DATA(MSIOF0L_RSYNC_MARK, PORT215_FN5, MSEL3CR_MSEL11_1), \
+	PINMUX_DATA(D31_MARK, PORT215_FN6),
+	PINMUX_DATA(LCDDCK_MARK, PORT216_FN1), \
+	PINMUX_DATA(LCDWR__MARK, PORT216_FN2),
+	PINMUX_DATA(LCDRD__MARK, PORT217_FN1), \
+	PINMUX_DATA(DACK2_MARK, PORT217_FN2), \
+	PINMUX_DATA(PORT217_LCD2RS_MARK, PORT217_FN3), \
+	PINMUX_DATA(MSIOF0L_TSYNC_MARK, PORT217_FN5, MSEL3CR_MSEL11_1), \
+	PINMUX_DATA(VIO2_FIELD3_MARK, PORT217_FN6, MSEL4CR_MSEL27_1,
+		MSEL4CR_MSEL26_1), \
+	PINMUX_DATA(PORT217_LCD2DISP_MARK, PORT217_FN7),
+	PINMUX_DATA(LCDHSYN_MARK, PORT218_FN1), \
+	PINMUX_DATA(LCDCS__MARK, PORT218_FN2), \
+	PINMUX_DATA(LCDCS2__MARK, PORT218_FN3), \
+	PINMUX_DATA(DACK3_MARK, PORT218_FN4), \
+	PINMUX_DATA(PORT218_VIO_CKOR_MARK, PORT218_FN5),
+	PINMUX_DATA(LCDDISP_MARK, PORT219_FN1), \
+	PINMUX_DATA(LCDRS_MARK, PORT219_FN2), \
+	PINMUX_DATA(PORT219_LCD2WR__MARK, PORT219_FN3), \
+	PINMUX_DATA(DREQ3_MARK, PORT219_FN4), \
+	PINMUX_DATA(MSIOF0L_TSCK_MARK, PORT219_FN5, MSEL3CR_MSEL11_1), \
+	PINMUX_DATA(VIO2_CLK3_MARK, PORT219_FN6, MSEL4CR_MSEL27_1,
+		MSEL4CR_MSEL26_1), \
+	PINMUX_DATA(LCD2DCK_2_MARK, PORT219_FN7),
+	PINMUX_DATA(LCDVSYN_MARK, PORT220_FN1), \
+	PINMUX_DATA(LCDVSYN2_MARK, PORT220_FN2),
+	PINMUX_DATA(LCDLCLK_MARK, PORT221_FN1), \
+	PINMUX_DATA(DREQ1_MARK, PORT221_FN2), \
+	PINMUX_DATA(PORT221_LCD2CS__MARK, PORT221_FN3), \
+	PINMUX_DATA(PWEN_MARK, PORT221_FN4), \
+	PINMUX_DATA(MSIOF0L_RXD_MARK, PORT221_FN5, MSEL3CR_MSEL11_1), \
+	PINMUX_DATA(VIO2_HD3_MARK, PORT221_FN6, MSEL4CR_MSEL27_1,
+		MSEL4CR_MSEL26_1), \
+	PINMUX_DATA(PORT221_LCD2HSYN_MARK, PORT221_FN7),
+	PINMUX_DATA(LCDDON_MARK, PORT222_FN1), \
+	PINMUX_DATA(LCDDON2_MARK, PORT222_FN2), \
+	PINMUX_DATA(DACK1_MARK, PORT222_FN3), \
+	PINMUX_DATA(OVCN_MARK, PORT222_FN4), \
+	PINMUX_DATA(MSIOF0L_TXD_MARK, PORT222_FN5, MSEL3CR_MSEL11_1), \
+	PINMUX_DATA(VIO2_VD3_MARK, PORT222_FN6, MSEL4CR_MSEL27_1,
+		MSEL4CR_MSEL26_1), \
+	PINMUX_DATA(PORT222_LCD2VSYN_MARK, PORT222_FN7, MSEL3CR_MSEL2_1),
+
+	PINMUX_DATA(SCIFA1_TXD_MARK, PORT225_FN2), \
+	PINMUX_DATA(OVCN2_MARK, PORT225_FN4),
+	PINMUX_DATA(EXTLP_MARK, PORT226_FN1), \
+	PINMUX_DATA(SCIFA1_SCK_MARK, PORT226_FN2), \
+	PINMUX_DATA(PORT226_VIO_CKO2_MARK, PORT226_FN5),
+	PINMUX_DATA(SCIFA1_RTS__MARK, PORT227_FN2), \
+	PINMUX_DATA(IDIN_MARK, PORT227_FN4),
+	PINMUX_DATA(SCIFA1_RXD_MARK, PORT228_FN2),
+	PINMUX_DATA(SCIFA1_CTS__MARK, PORT229_FN2), \
+	PINMUX_DATA(MFG1_IN1_MARK, PORT229_FN3),
+	PINMUX_DATA(MSIOF1_TXD_MARK, PORT230_FN1), \
+	PINMUX_DATA(SCIFA2_TXD2_MARK, PORT230_FN2, MSEL3CR_MSEL9_1),
+	PINMUX_DATA(MSIOF1_TSYNC_MARK, PORT231_FN1), \
+	PINMUX_DATA(SCIFA2_CTS2__MARK, PORT231_FN2, MSEL3CR_MSEL9_1),
+	PINMUX_DATA(MSIOF1_TSCK_MARK, PORT232_FN1), \
+	PINMUX_DATA(SCIFA2_SCK2_MARK, PORT232_FN2, MSEL3CR_MSEL9_1),
+	PINMUX_DATA(MSIOF1_RXD_MARK, PORT233_FN1), \
+	PINMUX_DATA(SCIFA2_RXD2_MARK, PORT233_FN2, MSEL3CR_MSEL9_1),
+	PINMUX_DATA(MSIOF1_RSCK_MARK, PORT234_FN1), \
+	PINMUX_DATA(SCIFA2_RTS2__MARK, PORT234_FN2, MSEL3CR_MSEL9_1), \
+	PINMUX_DATA(VIO2_CLK2_MARK, PORT234_FN6, MSEL4CR_MSEL27_1,
+		MSEL4CR_MSEL26_0), \
+	PINMUX_DATA(LCD2D20_MARK, PORT234_FN7),
+	PINMUX_DATA(MSIOF1_RSYNC_MARK, PORT235_FN1), \
+	PINMUX_DATA(MFG1_IN2_MARK, PORT235_FN3), \
+	PINMUX_DATA(VIO2_VD2_MARK, PORT235_FN6, MSEL4CR_MSEL27_1,
+		MSEL4CR_MSEL26_0), \
+	PINMUX_DATA(LCD2D21_MARK, PORT235_FN7),
+	PINMUX_DATA(MSIOF1_MCK0_MARK, PORT236_FN1), \
+	PINMUX_DATA(PORT236_I2C_SDA2_MARK, PORT236_FN2, MSEL2CR_MSEL17_0,
+		MSEL2CR_MSEL16_0),
+	PINMUX_DATA(MSIOF1_MCK1_MARK, PORT237_FN1), \
+	PINMUX_DATA(PORT237_I2C_SCL2_MARK, PORT237_FN2, MSEL2CR_MSEL17_0,
+		MSEL2CR_MSEL16_0),
+	PINMUX_DATA(MSIOF1_SS1_MARK, PORT238_FN1), \
+	PINMUX_DATA(VIO2_FIELD2_MARK, PORT238_FN6, MSEL4CR_MSEL27_1,
+		MSEL4CR_MSEL26_0), \
+	PINMUX_DATA(LCD2D22_MARK, PORT238_FN7),
+	PINMUX_DATA(MSIOF1_SS2_MARK, PORT239_FN1), \
+	PINMUX_DATA(VIO2_HD2_MARK, PORT239_FN6, MSEL4CR_MSEL27_1,
+		MSEL4CR_MSEL26_0), \
+	PINMUX_DATA(LCD2D23_MARK, PORT239_FN7),
+	PINMUX_DATA(SCIFA6_TXD_MARK, PORT240_FN1),
+	PINMUX_DATA(PORT241_IRDA_OUT_MARK, PORT241_FN1, MSEL4CR_MSEL19_0), \
+	PINMUX_DATA(PORT241_IROUT_MARK, PORT241_FN2), \
+	PINMUX_DATA(MFG4_OUT1_MARK, PORT241_FN3), \
+	PINMUX_DATA(TPU4TO0_MARK, PORT241_FN4),
+	PINMUX_DATA(PORT242_IRDA_IN_MARK, PORT242_FN1, MSEL4CR_MSEL19_0), \
+	PINMUX_DATA(MFG4_IN2_MARK, PORT242_FN3),
+	PINMUX_DATA(PORT243_IRDA_FIRSEL_MARK, PORT243_FN1, MSEL4CR_MSEL19_0), \
+	PINMUX_DATA(PORT243_VIO_CKO2_MARK, PORT243_FN2),
+	PINMUX_DATA(PORT244_SCIFA5_CTS__MARK, PORT244_FN1, MSEL4CR_MSEL21_0,
+		MSEL4CR_MSEL20_0), \
+	PINMUX_DATA(MFG2_IN1_MARK, PORT244_FN2), \
+	PINMUX_DATA(PORT244_SCIFB_CTS__MARK, PORT244_FN3, MSEL4CR_MSEL22_1), \
+	PINMUX_DATA(MSIOF2R_RXD_MARK, PORT244_FN7, MSEL4CR_MSEL11_1),
+	PINMUX_DATA(PORT245_SCIFA5_RTS__MARK, PORT245_FN1, MSEL4CR_MSEL21_0,
+		MSEL4CR_MSEL20_0), \
+	PINMUX_DATA(MFG2_IN2_MARK, PORT245_FN2), \
+	PINMUX_DATA(PORT245_SCIFB_RTS__MARK, PORT245_FN3, MSEL4CR_MSEL22_1), \
+	PINMUX_DATA(MSIOF2R_TXD_MARK, PORT245_FN7, MSEL4CR_MSEL11_1),
+	PINMUX_DATA(PORT246_SCIFA5_RXD_MARK, PORT246_FN1, MSEL4CR_MSEL21_0,
+		MSEL4CR_MSEL20_0), \
+	PINMUX_DATA(MFG1_OUT1_MARK, PORT246_FN2), \
+	PINMUX_DATA(PORT246_SCIFB_RXD_MARK, PORT246_FN3, MSEL4CR_MSEL22_1), \
+	PINMUX_DATA(TPU1TO0_MARK, PORT246_FN4),
+	PINMUX_DATA(PORT247_SCIFA5_TXD_MARK, PORT247_FN1, MSEL4CR_MSEL21_0,
+		MSEL4CR_MSEL20_0), \
+	PINMUX_DATA(MFG3_OUT2_MARK, PORT247_FN2), \
+	PINMUX_DATA(PORT247_SCIFB_TXD_MARK, PORT247_FN3, MSEL4CR_MSEL22_1), \
+	PINMUX_DATA(TPU3TO1_MARK, PORT247_FN4),
+	PINMUX_DATA(PORT248_SCIFA5_SCK_MARK, PORT248_FN1, MSEL4CR_MSEL21_0,
+		MSEL4CR_MSEL20_0), \
+	PINMUX_DATA(MFG2_OUT1_MARK, PORT248_FN2), \
+	PINMUX_DATA(PORT248_SCIFB_SCK_MARK, PORT248_FN3, MSEL4CR_MSEL22_1), \
+	PINMUX_DATA(TPU2TO0_MARK, PORT248_FN4), \
+	PINMUX_DATA(PORT248_I2C_SCL3_MARK, PORT248_FN5, MSEL2CR_MSEL19_0,
+		MSEL2CR_MSEL18_0), \
+	PINMUX_DATA(MSIOF2R_TSCK_MARK, PORT248_FN7, MSEL4CR_MSEL11_1),
+	PINMUX_DATA(PORT249_IROUT_MARK, PORT249_FN1), \
+	PINMUX_DATA(MFG4_IN1_MARK, PORT249_FN2), \
+	PINMUX_DATA(PORT249_I2C_SDA3_MARK, PORT249_FN5, MSEL2CR_MSEL19_0,
+		MSEL2CR_MSEL18_0), \
+	PINMUX_DATA(MSIOF2R_TSYNC_MARK, PORT249_FN7, MSEL4CR_MSEL11_1),
+	PINMUX_DATA(SDHICLK0_MARK, PORT250_FN1),
+	PINMUX_DATA(SDHICD0_MARK, PORT251_FN1),
+	PINMUX_DATA(SDHID0_0_MARK, PORT252_FN1),
+	PINMUX_DATA(SDHID0_1_MARK, PORT253_FN1),
+	PINMUX_DATA(SDHID0_2_MARK, PORT254_FN1),
+	PINMUX_DATA(SDHID0_3_MARK, PORT255_FN1),
+	PINMUX_DATA(SDHICMD0_MARK, PORT256_FN1),
+	PINMUX_DATA(SDHIWP0_MARK, PORT257_FN1),
+	PINMUX_DATA(SDHICLK1_MARK, PORT258_FN1),
+	PINMUX_DATA(SDHID1_0_MARK, PORT259_FN1), \
+	PINMUX_DATA(TS_SPSYNC2_MARK, PORT259_FN3),
+	PINMUX_DATA(SDHID1_1_MARK, PORT260_FN1), \
+	PINMUX_DATA(TS_SDAT2_MARK, PORT260_FN3),
+	PINMUX_DATA(SDHID1_2_MARK, PORT261_FN1), \
+	PINMUX_DATA(TS_SDEN2_MARK, PORT261_FN3),
+	PINMUX_DATA(SDHID1_3_MARK, PORT262_FN1), \
+	PINMUX_DATA(TS_SCK2_MARK, PORT262_FN3),
+	PINMUX_DATA(SDHICMD1_MARK, PORT263_FN1),
+	PINMUX_DATA(SDHICLK2_MARK, PORT264_FN1),
+	PINMUX_DATA(SDHID2_0_MARK, PORT265_FN1), \
+	PINMUX_DATA(TS_SPSYNC4_MARK, PORT265_FN3),
+	PINMUX_DATA(SDHID2_1_MARK, PORT266_FN1), \
+	PINMUX_DATA(TS_SDAT4_MARK, PORT266_FN3),
+	PINMUX_DATA(SDHID2_2_MARK, PORT267_FN1), \
+	PINMUX_DATA(TS_SDEN4_MARK, PORT267_FN3),
+	PINMUX_DATA(SDHID2_3_MARK, PORT268_FN1), \
+	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(TS_SPSYNC5_MARK, PORT275_FN3),
+	PINMUX_DATA(MMCD0_5_MARK, PORT276_FN1, MSEL4CR_MSEL15_0), \
+	PINMUX_DATA(TS_SDAT5_MARK, PORT276_FN3),
+	PINMUX_DATA(MMCD0_6_MARK, PORT277_FN1, MSEL4CR_MSEL15_0), \
+	PINMUX_DATA(TS_SDEN5_MARK, PORT277_FN3),
+	PINMUX_DATA(MMCD0_7_MARK, PORT278_FN1, MSEL4CR_MSEL15_0), \
+	PINMUX_DATA(TS_SCK5_MARK, PORT278_FN3),
+	PINMUX_DATA(MMCCMD0_MARK, PORT279_FN1, MSEL4CR_MSEL15_0),
+	PINMUX_DATA(RESETOUTS__MARK, PORT281_FN1), \
+	PINMUX_DATA(EXTAL2OUT_MARK, PORT281_FN2),
+	PINMUX_DATA(MCP_WAIT__MCP_FRB_MARK, PORT288_FN1),
+	PINMUX_DATA(MCP_CKO_MARK, PORT289_FN1), \
+	PINMUX_DATA(MMCCLK1_MARK, PORT289_FN2, MSEL4CR_MSEL15_1),
+	PINMUX_DATA(MCP_D15_MCP_NAF15_MARK, PORT290_FN1),
+	PINMUX_DATA(MCP_D14_MCP_NAF14_MARK, PORT291_FN1),
+	PINMUX_DATA(MCP_D13_MCP_NAF13_MARK, PORT292_FN1),
+	PINMUX_DATA(MCP_D12_MCP_NAF12_MARK, PORT293_FN1),
+	PINMUX_DATA(MCP_D11_MCP_NAF11_MARK, PORT294_FN1),
+	PINMUX_DATA(MCP_D10_MCP_NAF10_MARK, PORT295_FN1),
+	PINMUX_DATA(MCP_D9_MCP_NAF9_MARK, PORT296_FN1),
+	PINMUX_DATA(MCP_D8_MCP_NAF8_MARK, PORT297_FN1), \
+	PINMUX_DATA(MMCCMD1_MARK, PORT297_FN2, MSEL4CR_MSEL15_1),
+	PINMUX_DATA(MCP_D7_MCP_NAF7_MARK, PORT298_FN1), \
+	PINMUX_DATA(MMCD1_7_MARK, PORT298_FN2, MSEL4CR_MSEL15_1),
+
+	PINMUX_DATA(MCP_D6_MCP_NAF6_MARK, PORT299_FN1), \
+	PINMUX_DATA(MMCD1_6_MARK, PORT299_FN2, MSEL4CR_MSEL15_1),
+	PINMUX_DATA(MCP_D5_MCP_NAF5_MARK, PORT300_FN1), \
+	PINMUX_DATA(MMCD1_5_MARK, PORT300_FN2, MSEL4CR_MSEL15_1),
+	PINMUX_DATA(MCP_D4_MCP_NAF4_MARK, PORT301_FN1), \
+	PINMUX_DATA(MMCD1_4_MARK, PORT301_FN2, MSEL4CR_MSEL15_1),
+	PINMUX_DATA(MCP_D3_MCP_NAF3_MARK, PORT302_FN1), \
+	PINMUX_DATA(MMCD1_3_MARK, PORT302_FN2, MSEL4CR_MSEL15_1),
+	PINMUX_DATA(MCP_D2_MCP_NAF2_MARK, PORT303_FN1), \
+	PINMUX_DATA(MMCD1_2_MARK, PORT303_FN2, MSEL4CR_MSEL15_1),
+	PINMUX_DATA(MCP_D1_MCP_NAF1_MARK, PORT304_FN1), \
+	PINMUX_DATA(MMCD1_1_MARK, PORT304_FN2, MSEL4CR_MSEL15_1),
+	PINMUX_DATA(MCP_D0_MCP_NAF0_MARK, PORT305_FN1), \
+	PINMUX_DATA(MMCD1_0_MARK, PORT305_FN2, MSEL4CR_MSEL15_1),
+	PINMUX_DATA(MCP_NBRSTOUT__MARK, PORT306_FN1),
+	PINMUX_DATA(MCP_WE0__MCP_FWE_MARK, PORT309_FN1), \
+	PINMUX_DATA(MCP_RDWR_MCP_FWE_MARK, PORT309_FN2),
+
+	/* MSEL2 special cases */
+	PINMUX_DATA(TSIF2_TS_XX1_MARK, MSEL2CR_MSEL14_0, MSEL2CR_MSEL13_0,
+		MSEL2CR_MSEL12_0),
+	PINMUX_DATA(TSIF2_TS_XX2_MARK, MSEL2CR_MSEL14_0, MSEL2CR_MSEL13_0,
+		MSEL2CR_MSEL12_1),
+	PINMUX_DATA(TSIF2_TS_XX3_MARK, MSEL2CR_MSEL14_0, MSEL2CR_MSEL13_1,
+		MSEL2CR_MSEL12_0),
+	PINMUX_DATA(TSIF2_TS_XX4_MARK, MSEL2CR_MSEL14_0, MSEL2CR_MSEL13_1,
+		MSEL2CR_MSEL12_1),
+	PINMUX_DATA(TSIF2_TS_XX5_MARK, MSEL2CR_MSEL14_1, MSEL2CR_MSEL13_0,
+		MSEL2CR_MSEL12_0),
+	PINMUX_DATA(TSIF1_TS_XX1_MARK, MSEL2CR_MSEL11_0, MSEL2CR_MSEL10_0,
+		MSEL2CR_MSEL9_0),
+	PINMUX_DATA(TSIF1_TS_XX2_MARK, MSEL2CR_MSEL11_0, MSEL2CR_MSEL10_0,
+		MSEL2CR_MSEL9_1),
+	PINMUX_DATA(TSIF1_TS_XX3_MARK, MSEL2CR_MSEL11_0, MSEL2CR_MSEL10_1,
+		MSEL2CR_MSEL9_0),
+	PINMUX_DATA(TSIF1_TS_XX4_MARK, MSEL2CR_MSEL11_0, MSEL2CR_MSEL10_1,
+		MSEL2CR_MSEL9_1),
+	PINMUX_DATA(TSIF1_TS_XX5_MARK, MSEL2CR_MSEL11_1, MSEL2CR_MSEL10_0,
+		MSEL2CR_MSEL9_0),
+	PINMUX_DATA(TSIF0_TS_XX1_MARK, MSEL2CR_MSEL8_0, MSEL2CR_MSEL7_0,
+		MSEL2CR_MSEL6_0),
+	PINMUX_DATA(TSIF0_TS_XX2_MARK, MSEL2CR_MSEL8_0, MSEL2CR_MSEL7_0,
+		MSEL2CR_MSEL6_1),
+	PINMUX_DATA(TSIF0_TS_XX3_MARK, MSEL2CR_MSEL8_0, MSEL2CR_MSEL7_1,
+		MSEL2CR_MSEL6_0),
+	PINMUX_DATA(TSIF0_TS_XX4_MARK, MSEL2CR_MSEL8_0, MSEL2CR_MSEL7_1,
+		MSEL2CR_MSEL6_1),
+	PINMUX_DATA(TSIF0_TS_XX5_MARK, MSEL2CR_MSEL8_1, MSEL2CR_MSEL7_0,
+		MSEL2CR_MSEL6_0),
+	PINMUX_DATA(MST1_TS_XX1_MARK, MSEL2CR_MSEL5_0, MSEL2CR_MSEL4_0,
+		MSEL2CR_MSEL3_0),
+	PINMUX_DATA(MST1_TS_XX2_MARK, MSEL2CR_MSEL5_0, MSEL2CR_MSEL4_0,
+		MSEL2CR_MSEL3_1),
+	PINMUX_DATA(MST1_TS_XX3_MARK, MSEL2CR_MSEL5_0, MSEL2CR_MSEL4_1,
+		MSEL2CR_MSEL3_0),
+	PINMUX_DATA(MST1_TS_XX4_MARK, MSEL2CR_MSEL5_0, MSEL2CR_MSEL4_1,
+		MSEL2CR_MSEL3_1),
+	PINMUX_DATA(MST1_TS_XX5_MARK, MSEL2CR_MSEL5_1, MSEL2CR_MSEL4_0,
+		MSEL2CR_MSEL3_0),
+	PINMUX_DATA(MST0_TS_XX1_MARK, MSEL2CR_MSEL2_0, MSEL2CR_MSEL1_0,
+		MSEL2CR_MSEL0_0),
+	PINMUX_DATA(MST0_TS_XX2_MARK, MSEL2CR_MSEL2_0, MSEL2CR_MSEL1_0,
+		MSEL2CR_MSEL0_1),
+	PINMUX_DATA(MST0_TS_XX3_MARK, MSEL2CR_MSEL2_0, MSEL2CR_MSEL1_1,
+		MSEL2CR_MSEL0_0),
+	PINMUX_DATA(MST0_TS_XX4_MARK, MSEL2CR_MSEL2_0, MSEL2CR_MSEL1_1,
+		MSEL2CR_MSEL0_1),
+	PINMUX_DATA(MST0_TS_XX5_MARK, MSEL2CR_MSEL2_1, MSEL2CR_MSEL1_0,
+		MSEL2CR_MSEL0_0),
+
+	/* MSEL3 special cases */
+	PINMUX_DATA(SDHI0_VCCQ_MC0_ON_MARK, MSEL3CR_MSEL28_1),
+	PINMUX_DATA(SDHI0_VCCQ_MC0_OFF_MARK, MSEL3CR_MSEL28_0),
+	PINMUX_DATA(DEBUG_MON_VIO_MARK, MSEL3CR_MSEL15_0),
+	PINMUX_DATA(DEBUG_MON_LCDD_MARK, MSEL3CR_MSEL15_1),
+	PINMUX_DATA(LCDC_LCDC0_MARK, MSEL3CR_MSEL6_0),
+	PINMUX_DATA(LCDC_LCDC1_MARK, MSEL3CR_MSEL6_1),
+
+	/* MSEL4 special cases */
+	PINMUX_DATA(IRQ9_MEM_INT_MARK, MSEL4CR_MSEL29_0),
+	PINMUX_DATA(IRQ9_MCP_INT_MARK, MSEL4CR_MSEL29_1),
+	PINMUX_DATA(A11_MARK, MSEL4CR_MSEL13_0, MSEL4CR_MSEL12_0),
+	PINMUX_DATA(KEYOUT8_MARK, MSEL4CR_MSEL13_0, MSEL4CR_MSEL12_1),
+	PINMUX_DATA(TPU4TO3_MARK, MSEL4CR_MSEL13_1, MSEL4CR_MSEL12_0),
+	PINMUX_DATA(RESETA_N_PU_ON_MARK, MSEL4CR_MSEL4_0),
+	PINMUX_DATA(RESETA_N_PU_OFF_MARK, MSEL4CR_MSEL4_1),
+	PINMUX_DATA(EDBGREQ_PD_MARK, MSEL4CR_MSEL1_0),
+	PINMUX_DATA(EDBGREQ_PU_MARK, MSEL4CR_MSEL1_1),
+
+	/* Functions with pull-ups */
+	PINMUX_DATA(KEYIN0_PU_MARK, PORT66_FN2, PORT66_IN_PU),
+	PINMUX_DATA(KEYIN1_PU_MARK, PORT67_FN2, PORT67_IN_PU),
+	PINMUX_DATA(KEYIN2_PU_MARK, PORT68_FN2, PORT68_IN_PU),
+	PINMUX_DATA(KEYIN3_PU_MARK, PORT69_FN2, PORT69_IN_PU),
+	PINMUX_DATA(KEYIN4_PU_MARK, PORT70_FN2, PORT70_IN_PU),
+	PINMUX_DATA(KEYIN5_PU_MARK, PORT71_FN2, PORT71_IN_PU),
+	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(MMCCMD0_PU_MARK, PORT279_FN1, PORT279_IN_PU,
+		MSEL4CR_MSEL15_0),
+	PINMUX_DATA(MMCCMD1_PU_MARK, PORT297_FN2, PORT279_IN_PU,
+		MSEL4CR_MSEL15_1),
+	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(),
+
+	/* Table 25-1 (Functions 0-7) */
+	GPIO_FN(VBUS_0),
+	GPIO_FN(GPI0),
+	GPIO_FN(GPI1),
+	GPIO_FN(GPI2),
+	GPIO_FN(GPI3),
+	GPIO_FN(GPI4),
+	GPIO_FN(GPI5),
+	GPIO_FN(GPI6),
+	GPIO_FN(GPI7),
+	GPIO_FN(SCIFA7_RXD),
+	GPIO_FN(SCIFA7_CTS_),
+	GPIO_FN(GPO7), \
+	GPIO_FN(MFG0_OUT2),
+	GPIO_FN(GPO6), \
+	GPIO_FN(MFG1_OUT2),
+	GPIO_FN(GPO5), \
+	GPIO_FN(SCIFA0_SCK), \
+	GPIO_FN(FSICOSLDT3), \
+	GPIO_FN(PORT16_VIO_CKOR),
+	GPIO_FN(SCIFA0_TXD),
+	GPIO_FN(SCIFA7_TXD),
+	GPIO_FN(SCIFA7_RTS_), \
+	GPIO_FN(PORT19_VIO_CKO2),
+	GPIO_FN(GPO0),
+	GPIO_FN(GPO1),
+	GPIO_FN(GPO2), \
+	GPIO_FN(STATUS0),
+	GPIO_FN(GPO3), \
+	GPIO_FN(STATUS1),
+	GPIO_FN(GPO4), \
+	GPIO_FN(STATUS2),
+	GPIO_FN(VINT),
+	GPIO_FN(TCKON),
+	GPIO_FN(XDVFS1), \
+	GPIO_FN(PORT27_I2C_SCL2), \
+	GPIO_FN(PORT27_I2C_SCL3), \
+	GPIO_FN(MFG0_OUT1), \
+	GPIO_FN(PORT27_IROUT),
+	GPIO_FN(XDVFS2), \
+	GPIO_FN(PORT28_I2C_SDA2), \
+	GPIO_FN(PORT28_I2C_SDA3), \
+	GPIO_FN(PORT28_TPU1TO1),
+	GPIO_FN(SIM_RST), \
+	GPIO_FN(PORT29_TPU1TO1),
+	GPIO_FN(SIM_CLK), \
+	GPIO_FN(PORT30_VIO_CKOR),
+	GPIO_FN(SIM_D), \
+	GPIO_FN(PORT31_IROUT),
+	GPIO_FN(SCIFA4_TXD),
+	GPIO_FN(SCIFA4_RXD), \
+	GPIO_FN(XWUP),
+	GPIO_FN(SCIFA4_RTS_),
+	GPIO_FN(SCIFA4_CTS_),
+	GPIO_FN(FSIBOBT), \
+	GPIO_FN(FSIBIBT),
+	GPIO_FN(FSIBOLR), \
+	GPIO_FN(FSIBILR),
+	GPIO_FN(FSIBOSLD),
+	GPIO_FN(FSIBISLD),
+	GPIO_FN(VACK),
+	GPIO_FN(XTAL1L),
+	GPIO_FN(SCIFA0_RTS_), \
+	GPIO_FN(FSICOSLDT2),
+	GPIO_FN(SCIFA0_RXD),
+	GPIO_FN(SCIFA0_CTS_), \
+	GPIO_FN(FSICOSLDT1),
+	GPIO_FN(FSICOBT), \
+	GPIO_FN(FSICIBT), \
+	GPIO_FN(FSIDOBT), \
+	GPIO_FN(FSIDIBT),
+	GPIO_FN(FSICOLR), \
+	GPIO_FN(FSICILR), \
+	GPIO_FN(FSIDOLR), \
+	GPIO_FN(FSIDILR),
+	GPIO_FN(FSICOSLD), \
+	GPIO_FN(PORT47_FSICSPDIF),
+	GPIO_FN(FSICISLD), \
+	GPIO_FN(FSIDISLD),
+	GPIO_FN(FSIACK), \
+	GPIO_FN(PORT49_IRDA_OUT), \
+	GPIO_FN(PORT49_IROUT), \
+	GPIO_FN(FSIAOMC),
+	GPIO_FN(FSIAOLR), \
+	GPIO_FN(BBIF2_TSYNC2), \
+	GPIO_FN(TPU2TO2), \
+	GPIO_FN(FSIAILR),
+
+	GPIO_FN(FSIAOBT), \
+	GPIO_FN(BBIF2_TSCK2), \
+	GPIO_FN(TPU2TO3), \
+	GPIO_FN(FSIAIBT),
+	GPIO_FN(FSIAOSLD), \
+	GPIO_FN(BBIF2_TXD2),
+	GPIO_FN(FSIASPDIF), \
+	GPIO_FN(PORT53_IRDA_IN), \
+	GPIO_FN(TPU3TO3), \
+	GPIO_FN(FSIBSPDIF), \
+	GPIO_FN(PORT53_FSICSPDIF),
+	GPIO_FN(FSIBCK), \
+	GPIO_FN(PORT54_IRDA_FIRSEL), \
+	GPIO_FN(TPU3TO2), \
+	GPIO_FN(FSIBOMC), \
+	GPIO_FN(FSICCK), \
+	GPIO_FN(FSICOMC),
+	GPIO_FN(FSIAISLD), \
+	GPIO_FN(TPU0TO0),
+	GPIO_FN(A0), \
+	GPIO_FN(BS_),
+	GPIO_FN(A12), \
+	GPIO_FN(PORT58_KEYOUT7), \
+	GPIO_FN(TPU4TO2),
+	GPIO_FN(A13), \
+	GPIO_FN(PORT59_KEYOUT6), \
+	GPIO_FN(TPU0TO1),
+	GPIO_FN(A14), \
+	GPIO_FN(KEYOUT5),
+	GPIO_FN(A15), \
+	GPIO_FN(KEYOUT4),
+	GPIO_FN(A16), \
+	GPIO_FN(KEYOUT3), \
+	GPIO_FN(MSIOF0_SS1),
+	GPIO_FN(A17), \
+	GPIO_FN(KEYOUT2), \
+	GPIO_FN(MSIOF0_TSYNC),
+	GPIO_FN(A18), \
+	GPIO_FN(KEYOUT1), \
+	GPIO_FN(MSIOF0_TSCK),
+	GPIO_FN(A19), \
+	GPIO_FN(KEYOUT0), \
+	GPIO_FN(MSIOF0_TXD),
+	GPIO_FN(A20), \
+	GPIO_FN(KEYIN0), \
+	GPIO_FN(MSIOF0_RSCK),
+	GPIO_FN(A21), \
+	GPIO_FN(KEYIN1), \
+	GPIO_FN(MSIOF0_RSYNC),
+	GPIO_FN(A22), \
+	GPIO_FN(KEYIN2), \
+	GPIO_FN(MSIOF0_MCK0),
+	GPIO_FN(A23), \
+	GPIO_FN(KEYIN3), \
+	GPIO_FN(MSIOF0_MCK1),
+	GPIO_FN(A24), \
+	GPIO_FN(KEYIN4), \
+	GPIO_FN(MSIOF0_RXD),
+	GPIO_FN(A25), \
+	GPIO_FN(KEYIN5), \
+	GPIO_FN(MSIOF0_SS2),
+	GPIO_FN(A26), \
+	GPIO_FN(KEYIN6),
+	GPIO_FN(KEYIN7),
+	GPIO_FN(D0_NAF0),
+	GPIO_FN(D1_NAF1),
+	GPIO_FN(D2_NAF2),
+	GPIO_FN(D3_NAF3),
+	GPIO_FN(D4_NAF4),
+	GPIO_FN(D5_NAF5),
+	GPIO_FN(D6_NAF6),
+	GPIO_FN(D7_NAF7),
+	GPIO_FN(D8_NAF8),
+	GPIO_FN(D9_NAF9),
+	GPIO_FN(D10_NAF10),
+	GPIO_FN(D11_NAF11),
+	GPIO_FN(D12_NAF12),
+	GPIO_FN(D13_NAF13),
+	GPIO_FN(D14_NAF14),
+	GPIO_FN(D15_NAF15),
+	GPIO_FN(CS4_),
+	GPIO_FN(CS5A_), \
+	GPIO_FN(PORT91_RDWR),
+	GPIO_FN(CS5B_), \
+	GPIO_FN(FCE1_),
+	GPIO_FN(CS6B_), \
+	GPIO_FN(DACK0),
+	GPIO_FN(FCE0_), \
+	GPIO_FN(CS6A_),
+	GPIO_FN(WAIT_), \
+	GPIO_FN(DREQ0),
+	GPIO_FN(RD__FSC),
+	GPIO_FN(WE0__FWE), \
+	GPIO_FN(RDWR_FWE),
+	GPIO_FN(WE1_),
+	GPIO_FN(FRB),
+	GPIO_FN(CKO),
+	GPIO_FN(NBRSTOUT_),
+	GPIO_FN(NBRST_),
+	GPIO_FN(BBIF2_TXD),
+	GPIO_FN(BBIF2_RXD),
+	GPIO_FN(BBIF2_SYNC),
+	GPIO_FN(BBIF2_SCK),
+	GPIO_FN(SCIFA3_CTS_), \
+	GPIO_FN(MFG3_IN2),
+	GPIO_FN(SCIFA3_RXD), \
+	GPIO_FN(MFG3_IN1),
+	GPIO_FN(BBIF1_SS2), \
+	GPIO_FN(SCIFA3_RTS_), \
+	GPIO_FN(MFG3_OUT1),
+	GPIO_FN(SCIFA3_TXD),
+	GPIO_FN(HSI_RX_DATA), \
+	GPIO_FN(BBIF1_RXD),
+	GPIO_FN(HSI_TX_WAKE), \
+	GPIO_FN(BBIF1_TSCK),
+	GPIO_FN(HSI_TX_DATA), \
+	GPIO_FN(BBIF1_TSYNC),
+	GPIO_FN(HSI_TX_READY), \
+	GPIO_FN(BBIF1_TXD),
+	GPIO_FN(HSI_RX_READY), \
+	GPIO_FN(BBIF1_RSCK), \
+	GPIO_FN(PORT115_I2C_SCL2), \
+	GPIO_FN(PORT115_I2C_SCL3),
+	GPIO_FN(HSI_RX_WAKE), \
+	GPIO_FN(BBIF1_RSYNC), \
+	GPIO_FN(PORT116_I2C_SDA2), \
+	GPIO_FN(PORT116_I2C_SDA3),
+	GPIO_FN(HSI_RX_FLAG), \
+	GPIO_FN(BBIF1_SS1), \
+	GPIO_FN(BBIF1_FLOW),
+	GPIO_FN(HSI_TX_FLAG),
+	GPIO_FN(VIO_VD), \
+	GPIO_FN(PORT128_LCD2VSYN), \
+	GPIO_FN(VIO2_VD), \
+	GPIO_FN(LCD2D0),
+
+	GPIO_FN(VIO_HD), \
+	GPIO_FN(PORT129_LCD2HSYN), \
+	GPIO_FN(PORT129_LCD2CS_), \
+	GPIO_FN(VIO2_HD), \
+	GPIO_FN(LCD2D1),
+	GPIO_FN(VIO_D0), \
+	GPIO_FN(PORT130_MSIOF2_RXD), \
+	GPIO_FN(LCD2D10),
+	GPIO_FN(VIO_D1), \
+	GPIO_FN(PORT131_KEYOUT6), \
+	GPIO_FN(PORT131_MSIOF2_SS1), \
+	GPIO_FN(PORT131_KEYOUT11), \
+	GPIO_FN(LCD2D11),
+	GPIO_FN(VIO_D2), \
+	GPIO_FN(PORT132_KEYOUT7), \
+	GPIO_FN(PORT132_MSIOF2_SS2), \
+	GPIO_FN(PORT132_KEYOUT10), \
+	GPIO_FN(LCD2D12),
+	GPIO_FN(VIO_D3), \
+	GPIO_FN(MSIOF2_TSYNC), \
+	GPIO_FN(LCD2D13),
+	GPIO_FN(VIO_D4), \
+	GPIO_FN(MSIOF2_TXD), \
+	GPIO_FN(LCD2D14),
+	GPIO_FN(VIO_D5), \
+	GPIO_FN(MSIOF2_TSCK), \
+	GPIO_FN(LCD2D15),
+	GPIO_FN(VIO_D6), \
+	GPIO_FN(PORT136_KEYOUT8), \
+	GPIO_FN(LCD2D16),
+	GPIO_FN(VIO_D7), \
+	GPIO_FN(PORT137_KEYOUT9), \
+	GPIO_FN(LCD2D17),
+	GPIO_FN(VIO_D8), \
+	GPIO_FN(PORT138_KEYOUT8), \
+	GPIO_FN(VIO2_D0), \
+	GPIO_FN(LCD2D6),
+	GPIO_FN(VIO_D9), \
+	GPIO_FN(PORT139_KEYOUT9), \
+	GPIO_FN(VIO2_D1), \
+	GPIO_FN(LCD2D7),
+	GPIO_FN(VIO_D10), \
+	GPIO_FN(TPU0TO2), \
+	GPIO_FN(VIO2_D2), \
+	GPIO_FN(LCD2D8),
+	GPIO_FN(VIO_D11), \
+	GPIO_FN(TPU0TO3), \
+	GPIO_FN(VIO2_D3), \
+	GPIO_FN(LCD2D9),
+	GPIO_FN(VIO_D12), \
+	GPIO_FN(PORT142_KEYOUT10), \
+	GPIO_FN(VIO2_D4), \
+	GPIO_FN(LCD2D2),
+	GPIO_FN(VIO_D13), \
+	GPIO_FN(PORT143_KEYOUT11), \
+	GPIO_FN(PORT143_KEYOUT6), \
+	GPIO_FN(VIO2_D5), \
+	GPIO_FN(LCD2D3),
+	GPIO_FN(VIO_D14), \
+	GPIO_FN(PORT144_KEYOUT7), \
+	GPIO_FN(VIO2_D6), \
+	GPIO_FN(LCD2D4),
+	GPIO_FN(VIO_D15), \
+	GPIO_FN(TPU1TO3), \
+	GPIO_FN(PORT145_LCD2DISP), \
+	GPIO_FN(PORT145_LCD2RS), \
+	GPIO_FN(VIO2_D7), \
+	GPIO_FN(LCD2D5),
+	GPIO_FN(VIO_CLK), \
+	GPIO_FN(LCD2DCK), \
+	GPIO_FN(PORT146_LCD2WR_), \
+	GPIO_FN(VIO2_CLK), \
+	GPIO_FN(LCD2D18),
+	GPIO_FN(VIO_FIELD), \
+	GPIO_FN(LCD2RD_), \
+	GPIO_FN(VIO2_FIELD), \
+	GPIO_FN(LCD2D19),
+	GPIO_FN(VIO_CKO),
+	GPIO_FN(A27), \
+	GPIO_FN(PORT149_RDWR), \
+	GPIO_FN(MFG0_IN1), \
+	GPIO_FN(PORT149_KEYOUT9),
+	GPIO_FN(MFG0_IN2),
+	GPIO_FN(TS_SPSYNC3), \
+	GPIO_FN(MSIOF2_RSCK),
+	GPIO_FN(TS_SDAT3), \
+	GPIO_FN(MSIOF2_RSYNC),
+	GPIO_FN(TPU1TO2), \
+	GPIO_FN(TS_SDEN3), \
+	GPIO_FN(PORT153_MSIOF2_SS1),
+	GPIO_FN(SCIFA2_TXD1), \
+	GPIO_FN(MSIOF2_MCK0),
+	GPIO_FN(SCIFA2_RXD1), \
+	GPIO_FN(MSIOF2_MCK1),
+	GPIO_FN(SCIFA2_RTS1_), \
+	GPIO_FN(PORT156_MSIOF2_SS2),
+	GPIO_FN(SCIFA2_CTS1_), \
+	GPIO_FN(PORT157_MSIOF2_RXD),
+	GPIO_FN(DINT_), \
+	GPIO_FN(SCIFA2_SCK1), \
+	GPIO_FN(TS_SCK3),
+	GPIO_FN(PORT159_SCIFB_SCK), \
+	GPIO_FN(PORT159_SCIFA5_SCK), \
+	GPIO_FN(NMI),
+	GPIO_FN(PORT160_SCIFB_TXD), \
+	GPIO_FN(PORT160_SCIFA5_TXD),
+	GPIO_FN(PORT161_SCIFB_CTS_), \
+	GPIO_FN(PORT161_SCIFA5_CTS_),
+	GPIO_FN(PORT162_SCIFB_RXD), \
+	GPIO_FN(PORT162_SCIFA5_RXD),
+	GPIO_FN(PORT163_SCIFB_RTS_), \
+	GPIO_FN(PORT163_SCIFA5_RTS_), \
+	GPIO_FN(TPU3TO0),
+	GPIO_FN(LCDD0),
+	GPIO_FN(LCDD1), \
+	GPIO_FN(PORT193_SCIFA5_CTS_), \
+	GPIO_FN(BBIF2_TSYNC1),
+	GPIO_FN(LCDD2), \
+	GPIO_FN(PORT194_SCIFA5_RTS_), \
+	GPIO_FN(BBIF2_TSCK1),
+	GPIO_FN(LCDD3), \
+	GPIO_FN(PORT195_SCIFA5_RXD), \
+	GPIO_FN(BBIF2_TXD1),
+	GPIO_FN(LCDD4), \
+	GPIO_FN(PORT196_SCIFA5_TXD),
+	GPIO_FN(LCDD5), \
+	GPIO_FN(PORT197_SCIFA5_SCK), \
+	GPIO_FN(MFG2_OUT2), \
+	GPIO_FN(TPU2TO1),
+	GPIO_FN(LCDD6),
+	GPIO_FN(LCDD7), \
+	GPIO_FN(TPU4TO1), \
+	GPIO_FN(MFG4_OUT2),
+	GPIO_FN(LCDD8), \
+	GPIO_FN(D16),
+	GPIO_FN(LCDD9), \
+	GPIO_FN(D17),
+	GPIO_FN(LCDD10), \
+	GPIO_FN(D18),
+	GPIO_FN(LCDD11), \
+	GPIO_FN(D19),
+	GPIO_FN(LCDD12), \
+	GPIO_FN(D20),
+	GPIO_FN(LCDD13), \
+	GPIO_FN(D21),
+	GPIO_FN(LCDD14), \
+	GPIO_FN(D22),
+	GPIO_FN(LCDD15), \
+	GPIO_FN(PORT207_MSIOF0L_SS1), \
+	GPIO_FN(D23),
+	GPIO_FN(LCDD16), \
+	GPIO_FN(PORT208_MSIOF0L_SS2), \
+	GPIO_FN(D24),
+	GPIO_FN(LCDD17), \
+	GPIO_FN(D25),
+	GPIO_FN(LCDD18), \
+	GPIO_FN(DREQ2), \
+	GPIO_FN(PORT210_MSIOF0L_SS1), \
+	GPIO_FN(D26),
+	GPIO_FN(LCDD19), \
+	GPIO_FN(PORT211_MSIOF0L_SS2), \
+	GPIO_FN(D27),
+	GPIO_FN(LCDD20), \
+	GPIO_FN(TS_SPSYNC1), \
+	GPIO_FN(MSIOF0L_MCK0), \
+	GPIO_FN(D28),
+	GPIO_FN(LCDD21), \
+	GPIO_FN(TS_SDAT1), \
+	GPIO_FN(MSIOF0L_MCK1), \
+	GPIO_FN(D29),
+	GPIO_FN(LCDD22), \
+	GPIO_FN(TS_SDEN1), \
+	GPIO_FN(MSIOF0L_RSCK), \
+	GPIO_FN(D30),
+	GPIO_FN(LCDD23), \
+	GPIO_FN(TS_SCK1), \
+	GPIO_FN(MSIOF0L_RSYNC), \
+	GPIO_FN(D31),
+	GPIO_FN(LCDDCK), \
+	GPIO_FN(LCDWR_),
+	GPIO_FN(LCDRD_), \
+	GPIO_FN(DACK2), \
+	GPIO_FN(PORT217_LCD2RS), \
+	GPIO_FN(MSIOF0L_TSYNC), \
+	GPIO_FN(VIO2_FIELD3), \
+	GPIO_FN(PORT217_LCD2DISP),
+	GPIO_FN(LCDHSYN), \
+	GPIO_FN(LCDCS_), \
+	GPIO_FN(LCDCS2_), \
+	GPIO_FN(DACK3), \
+	GPIO_FN(PORT218_VIO_CKOR),
+	GPIO_FN(LCDDISP), \
+	GPIO_FN(LCDRS), \
+	GPIO_FN(PORT219_LCD2WR_), \
+	GPIO_FN(DREQ3), \
+	GPIO_FN(MSIOF0L_TSCK), \
+	GPIO_FN(VIO2_CLK3), \
+	GPIO_FN(LCD2DCK_2),
+	GPIO_FN(LCDVSYN), \
+	GPIO_FN(LCDVSYN2),
+	GPIO_FN(LCDLCLK), \
+	GPIO_FN(DREQ1), \
+	GPIO_FN(PORT221_LCD2CS_), \
+	GPIO_FN(PWEN), \
+	GPIO_FN(MSIOF0L_RXD), \
+	GPIO_FN(VIO2_HD3), \
+	GPIO_FN(PORT221_LCD2HSYN),
+	GPIO_FN(LCDDON), \
+	GPIO_FN(LCDDON2), \
+	GPIO_FN(DACK1), \
+	GPIO_FN(OVCN), \
+	GPIO_FN(MSIOF0L_TXD), \
+	GPIO_FN(VIO2_VD3), \
+	GPIO_FN(PORT222_LCD2VSYN),
+
+	GPIO_FN(SCIFA1_TXD), \
+	GPIO_FN(OVCN2),
+	GPIO_FN(EXTLP), \
+	GPIO_FN(SCIFA1_SCK), \
+	GPIO_FN(PORT226_VIO_CKO2),
+	GPIO_FN(SCIFA1_RTS_), \
+	GPIO_FN(IDIN),
+	GPIO_FN(SCIFA1_RXD),
+	GPIO_FN(SCIFA1_CTS_), \
+	GPIO_FN(MFG1_IN1),
+	GPIO_FN(MSIOF1_TXD), \
+	GPIO_FN(SCIFA2_TXD2),
+	GPIO_FN(MSIOF1_TSYNC), \
+	GPIO_FN(SCIFA2_CTS2_),
+	GPIO_FN(MSIOF1_TSCK), \
+	GPIO_FN(SCIFA2_SCK2),
+	GPIO_FN(MSIOF1_RXD), \
+	GPIO_FN(SCIFA2_RXD2),
+	GPIO_FN(MSIOF1_RSCK), \
+	GPIO_FN(SCIFA2_RTS2_), \
+	GPIO_FN(VIO2_CLK2), \
+	GPIO_FN(LCD2D20),
+	GPIO_FN(MSIOF1_RSYNC), \
+	GPIO_FN(MFG1_IN2), \
+	GPIO_FN(VIO2_VD2), \
+	GPIO_FN(LCD2D21),
+	GPIO_FN(MSIOF1_MCK0), \
+	GPIO_FN(PORT236_I2C_SDA2),
+	GPIO_FN(MSIOF1_MCK1), \
+	GPIO_FN(PORT237_I2C_SCL2),
+	GPIO_FN(MSIOF1_SS1), \
+	GPIO_FN(VIO2_FIELD2), \
+	GPIO_FN(LCD2D22),
+	GPIO_FN(MSIOF1_SS2), \
+	GPIO_FN(VIO2_HD2), \
+	GPIO_FN(LCD2D23),
+	GPIO_FN(SCIFA6_TXD),
+	GPIO_FN(PORT241_IRDA_OUT), \
+	GPIO_FN(PORT241_IROUT), \
+	GPIO_FN(MFG4_OUT1), \
+	GPIO_FN(TPU4TO0),
+	GPIO_FN(PORT242_IRDA_IN), \
+	GPIO_FN(MFG4_IN2),
+	GPIO_FN(PORT243_IRDA_FIRSEL), \
+	GPIO_FN(PORT243_VIO_CKO2),
+	GPIO_FN(PORT244_SCIFA5_CTS_), \
+	GPIO_FN(MFG2_IN1), \
+	GPIO_FN(PORT244_SCIFB_CTS_), \
+	GPIO_FN(MSIOF2R_RXD),
+	GPIO_FN(PORT245_SCIFA5_RTS_), \
+	GPIO_FN(MFG2_IN2), \
+	GPIO_FN(PORT245_SCIFB_RTS_), \
+	GPIO_FN(MSIOF2R_TXD),
+	GPIO_FN(PORT246_SCIFA5_RXD), \
+	GPIO_FN(MFG1_OUT1), \
+	GPIO_FN(PORT246_SCIFB_RXD), \
+	GPIO_FN(TPU1TO0),
+	GPIO_FN(PORT247_SCIFA5_TXD), \
+	GPIO_FN(MFG3_OUT2), \
+	GPIO_FN(PORT247_SCIFB_TXD), \
+	GPIO_FN(TPU3TO1),
+	GPIO_FN(PORT248_SCIFA5_SCK), \
+	GPIO_FN(MFG2_OUT1), \
+	GPIO_FN(PORT248_SCIFB_SCK), \
+	GPIO_FN(TPU2TO0), \
+	GPIO_FN(PORT248_I2C_SCL3), \
+	GPIO_FN(MSIOF2R_TSCK),
+	GPIO_FN(PORT249_IROUT), \
+	GPIO_FN(MFG4_IN1), \
+	GPIO_FN(PORT249_I2C_SDA3), \
+	GPIO_FN(MSIOF2R_TSYNC),
+	GPIO_FN(SDHICLK0),
+	GPIO_FN(SDHICD0),
+	GPIO_FN(SDHID0_0),
+	GPIO_FN(SDHID0_1),
+	GPIO_FN(SDHID0_2),
+	GPIO_FN(SDHID0_3),
+	GPIO_FN(SDHICMD0),
+	GPIO_FN(SDHIWP0),
+	GPIO_FN(SDHICLK1),
+	GPIO_FN(SDHID1_0), \
+	GPIO_FN(TS_SPSYNC2),
+	GPIO_FN(SDHID1_1), \
+	GPIO_FN(TS_SDAT2),
+	GPIO_FN(SDHID1_2), \
+	GPIO_FN(TS_SDEN2),
+	GPIO_FN(SDHID1_3), \
+	GPIO_FN(TS_SCK2),
+	GPIO_FN(SDHICMD1),
+	GPIO_FN(SDHICLK2),
+	GPIO_FN(SDHID2_0), \
+	GPIO_FN(TS_SPSYNC4),
+	GPIO_FN(SDHID2_1), \
+	GPIO_FN(TS_SDAT4),
+	GPIO_FN(SDHID2_2), \
+	GPIO_FN(TS_SDEN4),
+	GPIO_FN(SDHID2_3), \
+	GPIO_FN(TS_SCK4),
+	GPIO_FN(SDHICMD2),
+	GPIO_FN(MMCCLK0),
+	GPIO_FN(MMCD0_0),
+	GPIO_FN(MMCD0_1),
+	GPIO_FN(MMCD0_2),
+	GPIO_FN(MMCD0_3),
+	GPIO_FN(MMCD0_4), \
+	GPIO_FN(TS_SPSYNC5),
+	GPIO_FN(MMCD0_5), \
+	GPIO_FN(TS_SDAT5),
+	GPIO_FN(MMCD0_6), \
+	GPIO_FN(TS_SDEN5),
+	GPIO_FN(MMCD0_7), \
+	GPIO_FN(TS_SCK5),
+	GPIO_FN(MMCCMD0),
+	GPIO_FN(RESETOUTS_), \
+	GPIO_FN(EXTAL2OUT),
+	GPIO_FN(MCP_WAIT__MCP_FRB),
+	GPIO_FN(MCP_CKO), \
+	GPIO_FN(MMCCLK1),
+	GPIO_FN(MCP_D15_MCP_NAF15),
+	GPIO_FN(MCP_D14_MCP_NAF14),
+	GPIO_FN(MCP_D13_MCP_NAF13),
+	GPIO_FN(MCP_D12_MCP_NAF12),
+	GPIO_FN(MCP_D11_MCP_NAF11),
+	GPIO_FN(MCP_D10_MCP_NAF10),
+	GPIO_FN(MCP_D9_MCP_NAF9),
+	GPIO_FN(MCP_D8_MCP_NAF8), \
+	GPIO_FN(MMCCMD1),
+	GPIO_FN(MCP_D7_MCP_NAF7), \
+	GPIO_FN(MMCD1_7),
+
+	GPIO_FN(MCP_D6_MCP_NAF6), \
+	GPIO_FN(MMCD1_6),
+	GPIO_FN(MCP_D5_MCP_NAF5), \
+	GPIO_FN(MMCD1_5),
+	GPIO_FN(MCP_D4_MCP_NAF4), \
+	GPIO_FN(MMCD1_4),
+	GPIO_FN(MCP_D3_MCP_NAF3), \
+	GPIO_FN(MMCD1_3),
+	GPIO_FN(MCP_D2_MCP_NAF2), \
+	GPIO_FN(MMCD1_2),
+	GPIO_FN(MCP_D1_MCP_NAF1), \
+	GPIO_FN(MMCD1_1),
+	GPIO_FN(MCP_D0_MCP_NAF0), \
+	GPIO_FN(MMCD1_0),
+	GPIO_FN(MCP_NBRSTOUT_),
+	GPIO_FN(MCP_WE0__MCP_FWE), \
+	GPIO_FN(MCP_RDWR_MCP_FWE),
+
+	/* MSEL2 special cases */
+	GPIO_FN(TSIF2_TS_XX1),
+	GPIO_FN(TSIF2_TS_XX2),
+	GPIO_FN(TSIF2_TS_XX3),
+	GPIO_FN(TSIF2_TS_XX4),
+	GPIO_FN(TSIF2_TS_XX5),
+	GPIO_FN(TSIF1_TS_XX1),
+	GPIO_FN(TSIF1_TS_XX2),
+	GPIO_FN(TSIF1_TS_XX3),
+	GPIO_FN(TSIF1_TS_XX4),
+	GPIO_FN(TSIF1_TS_XX5),
+	GPIO_FN(TSIF0_TS_XX1),
+	GPIO_FN(TSIF0_TS_XX2),
+	GPIO_FN(TSIF0_TS_XX3),
+	GPIO_FN(TSIF0_TS_XX4),
+	GPIO_FN(TSIF0_TS_XX5),
+	GPIO_FN(MST1_TS_XX1),
+	GPIO_FN(MST1_TS_XX2),
+	GPIO_FN(MST1_TS_XX3),
+	GPIO_FN(MST1_TS_XX4),
+	GPIO_FN(MST1_TS_XX5),
+	GPIO_FN(MST0_TS_XX1),
+	GPIO_FN(MST0_TS_XX2),
+	GPIO_FN(MST0_TS_XX3),
+	GPIO_FN(MST0_TS_XX4),
+	GPIO_FN(MST0_TS_XX5),
+
+	/* MSEL3 special cases */
+	GPIO_FN(SDHI0_VCCQ_MC0_ON),
+	GPIO_FN(SDHI0_VCCQ_MC0_OFF),
+	GPIO_FN(DEBUG_MON_VIO),
+	GPIO_FN(DEBUG_MON_LCDD),
+	GPIO_FN(LCDC_LCDC0),
+	GPIO_FN(LCDC_LCDC1),
+
+	/* MSEL4 special cases */
+	GPIO_FN(IRQ9_MEM_INT),
+	GPIO_FN(IRQ9_MCP_INT),
+	GPIO_FN(A11),
+	GPIO_FN(KEYOUT8),
+	GPIO_FN(TPU4TO3),
+	GPIO_FN(RESETA_N_PU_ON),
+	GPIO_FN(RESETA_N_PU_OFF),
+	GPIO_FN(EDBGREQ_PD),
+	GPIO_FN(EDBGREQ_PU),
+
+	/* Functions with pull-ups */
+	GPIO_FN(KEYIN0_PU),
+	GPIO_FN(KEYIN1_PU),
+	GPIO_FN(KEYIN2_PU),
+	GPIO_FN(KEYIN3_PU),
+	GPIO_FN(KEYIN4_PU),
+	GPIO_FN(KEYIN5_PU),
+	GPIO_FN(KEYIN6_PU),
+	GPIO_FN(KEYIN7_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(MMCCMD0_PU),
+	GPIO_FN(MMCCMD1_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 */
+	PORTCR(2, 0xe6050002), /* PORT2CR */
+	PORTCR(3, 0xe6050003), /* PORT3CR */
+	PORTCR(4, 0xe6050004), /* PORT4CR */
+	PORTCR(5, 0xe6050005), /* PORT5CR */
+	PORTCR(6, 0xe6050006), /* PORT6CR */
+	PORTCR(7, 0xe6050007), /* PORT7CR */
+	PORTCR(8, 0xe6050008), /* PORT8CR */
+	PORTCR(9, 0xe6050009), /* PORT9CR */
+
+	PORTCR(10, 0xe605000a), /* PORT10CR */
+	PORTCR(11, 0xe605000b), /* PORT11CR */
+	PORTCR(12, 0xe605000c), /* PORT12CR */
+	PORTCR(13, 0xe605000d), /* PORT13CR */
+	PORTCR(14, 0xe605000e), /* PORT14CR */
+	PORTCR(15, 0xe605000f), /* PORT15CR */
+	PORTCR(16, 0xe6050010), /* PORT16CR */
+	PORTCR(17, 0xe6050011), /* PORT17CR */
+	PORTCR(18, 0xe6050012), /* PORT18CR */
+	PORTCR(19, 0xe6050013), /* PORT19CR */
+
+	PORTCR(20, 0xe6050014), /* PORT20CR */
+	PORTCR(21, 0xe6050015), /* PORT21CR */
+	PORTCR(22, 0xe6050016), /* PORT22CR */
+	PORTCR(23, 0xe6050017), /* PORT23CR */
+	PORTCR(24, 0xe6050018), /* PORT24CR */
+	PORTCR(25, 0xe6050019), /* PORT25CR */
+	PORTCR(26, 0xe605001a), /* PORT26CR */
+	PORTCR(27, 0xe605001b), /* PORT27CR */
+	PORTCR(28, 0xe605001c), /* PORT28CR */
+	PORTCR(29, 0xe605001d), /* PORT29CR */
+
+	PORTCR(30, 0xe605001e), /* PORT30CR */
+	PORTCR(31, 0xe605001f), /* PORT31CR */
+	PORTCR(32, 0xe6051020), /* PORT32CR */
+	PORTCR(33, 0xe6051021), /* PORT33CR */
+	PORTCR(34, 0xe6051022), /* PORT34CR */
+	PORTCR(35, 0xe6051023), /* PORT35CR */
+	PORTCR(36, 0xe6051024), /* PORT36CR */
+	PORTCR(37, 0xe6051025), /* PORT37CR */
+	PORTCR(38, 0xe6051026), /* PORT38CR */
+	PORTCR(39, 0xe6051027), /* PORT39CR */
+
+	PORTCR(40, 0xe6051028), /* PORT40CR */
+	PORTCR(41, 0xe6051029), /* PORT41CR */
+	PORTCR(42, 0xe605102a), /* PORT42CR */
+	PORTCR(43, 0xe605102b), /* PORT43CR */
+	PORTCR(44, 0xe605102c), /* PORT44CR */
+	PORTCR(45, 0xe605102d), /* PORT45CR */
+	PORTCR(46, 0xe605102e), /* PORT46CR */
+	PORTCR(47, 0xe605102f), /* PORT47CR */
+	PORTCR(48, 0xe6051030), /* PORT48CR */
+	PORTCR(49, 0xe6051031), /* PORT49CR */
+
+	PORTCR(50, 0xe6051032), /* PORT50CR */
+	PORTCR(51, 0xe6051033), /* PORT51CR */
+	PORTCR(52, 0xe6051034), /* PORT52CR */
+	PORTCR(53, 0xe6051035), /* PORT53CR */
+	PORTCR(54, 0xe6051036), /* PORT54CR */
+	PORTCR(55, 0xe6051037), /* PORT55CR */
+	PORTCR(56, 0xe6051038), /* PORT56CR */
+	PORTCR(57, 0xe6051039), /* PORT57CR */
+	PORTCR(58, 0xe605103a), /* PORT58CR */
+	PORTCR(59, 0xe605103b), /* PORT59CR */
+
+	PORTCR(60, 0xe605103c), /* PORT60CR */
+	PORTCR(61, 0xe605103d), /* PORT61CR */
+	PORTCR(62, 0xe605103e), /* PORT62CR */
+	PORTCR(63, 0xe605103f), /* PORT63CR */
+	PORTCR(64, 0xe6051040), /* PORT64CR */
+	PORTCR(65, 0xe6051041), /* PORT65CR */
+	PORTCR(66, 0xe6051042), /* PORT66CR */
+	PORTCR(67, 0xe6051043), /* PORT67CR */
+	PORTCR(68, 0xe6051044), /* PORT68CR */
+	PORTCR(69, 0xe6051045), /* PORT69CR */
+
+	PORTCR(70, 0xe6051046), /* PORT70CR */
+	PORTCR(71, 0xe6051047), /* PORT71CR */
+	PORTCR(72, 0xe6051048), /* PORT72CR */
+	PORTCR(73, 0xe6051049), /* PORT73CR */
+	PORTCR(74, 0xe605104a), /* PORT74CR */
+	PORTCR(75, 0xe605104b), /* PORT75CR */
+	PORTCR(76, 0xe605104c), /* PORT76CR */
+	PORTCR(77, 0xe605104d), /* PORT77CR */
+	PORTCR(78, 0xe605104e), /* PORT78CR */
+	PORTCR(79, 0xe605104f), /* PORT79CR */
+
+	PORTCR(80, 0xe6051050), /* PORT80CR */
+	PORTCR(81, 0xe6051051), /* PORT81CR */
+	PORTCR(82, 0xe6051052), /* PORT82CR */
+	PORTCR(83, 0xe6051053), /* PORT83CR */
+	PORTCR(84, 0xe6051054), /* PORT84CR */
+	PORTCR(85, 0xe6051055), /* PORT85CR */
+	PORTCR(86, 0xe6051056), /* PORT86CR */
+	PORTCR(87, 0xe6051057), /* PORT87CR */
+	PORTCR(88, 0xe6051058), /* PORT88CR */
+	PORTCR(89, 0xe6051059), /* PORT89CR */
+
+	PORTCR(90, 0xe605105a), /* PORT90CR */
+	PORTCR(91, 0xe605105b), /* PORT91CR */
+	PORTCR(92, 0xe605105c), /* PORT92CR */
+	PORTCR(93, 0xe605105d), /* PORT93CR */
+	PORTCR(94, 0xe605105e), /* PORT94CR */
+	PORTCR(95, 0xe605105f), /* PORT95CR */
+	PORTCR(96, 0xe6052060), /* PORT96CR */
+	PORTCR(97, 0xe6052061), /* PORT97CR */
+	PORTCR(98, 0xe6052062), /* PORT98CR */
+	PORTCR(99, 0xe6052063), /* PORT99CR */
+
+	PORTCR(100, 0xe6052064), /* PORT100CR */
+	PORTCR(101, 0xe6052065), /* PORT101CR */
+	PORTCR(102, 0xe6052066), /* PORT102CR */
+	PORTCR(103, 0xe6052067), /* PORT103CR */
+	PORTCR(104, 0xe6052068), /* PORT104CR */
+	PORTCR(105, 0xe6052069), /* PORT105CR */
+	PORTCR(106, 0xe605206a), /* PORT106CR */
+	PORTCR(107, 0xe605206b), /* PORT107CR */
+	PORTCR(108, 0xe605206c), /* PORT108CR */
+	PORTCR(109, 0xe605206d), /* PORT109CR */
+
+	PORTCR(110, 0xe605206e), /* PORT110CR */
+	PORTCR(111, 0xe605206f), /* PORT111CR */
+	PORTCR(112, 0xe6052070), /* PORT112CR */
+	PORTCR(113, 0xe6052071), /* PORT113CR */
+	PORTCR(114, 0xe6052072), /* PORT114CR */
+	PORTCR(115, 0xe6052073), /* PORT115CR */
+	PORTCR(116, 0xe6052074), /* PORT116CR */
+	PORTCR(117, 0xe6052075), /* PORT117CR */
+	PORTCR(118, 0xe6052076), /* PORT118CR */
+
+	PORTCR(128, 0xe6052080), /* PORT128CR */
+	PORTCR(129, 0xe6052081), /* PORT129CR */
+
+	PORTCR(130, 0xe6052082), /* PORT130CR */
+	PORTCR(131, 0xe6052083), /* PORT131CR */
+	PORTCR(132, 0xe6052084), /* PORT132CR */
+	PORTCR(133, 0xe6052085), /* PORT133CR */
+	PORTCR(134, 0xe6052086), /* PORT134CR */
+	PORTCR(135, 0xe6052087), /* PORT135CR */
+	PORTCR(136, 0xe6052088), /* PORT136CR */
+	PORTCR(137, 0xe6052089), /* PORT137CR */
+	PORTCR(138, 0xe605208a), /* PORT138CR */
+	PORTCR(139, 0xe605208b), /* PORT139CR */
+
+	PORTCR(140, 0xe605208c), /* PORT140CR */
+	PORTCR(141, 0xe605208d), /* PORT141CR */
+	PORTCR(142, 0xe605208e), /* PORT142CR */
+	PORTCR(143, 0xe605208f), /* PORT143CR */
+	PORTCR(144, 0xe6052090), /* PORT144CR */
+	PORTCR(145, 0xe6052091), /* PORT145CR */
+	PORTCR(146, 0xe6052092), /* PORT146CR */
+	PORTCR(147, 0xe6052093), /* PORT147CR */
+	PORTCR(148, 0xe6052094), /* PORT148CR */
+	PORTCR(149, 0xe6052095), /* PORT149CR */
+
+	PORTCR(150, 0xe6052096), /* PORT150CR */
+	PORTCR(151, 0xe6052097), /* PORT151CR */
+	PORTCR(152, 0xe6052098), /* PORT152CR */
+	PORTCR(153, 0xe6052099), /* PORT153CR */
+	PORTCR(154, 0xe605209a), /* PORT154CR */
+	PORTCR(155, 0xe605209b), /* PORT155CR */
+	PORTCR(156, 0xe605209c), /* PORT156CR */
+	PORTCR(157, 0xe605209d), /* PORT157CR */
+	PORTCR(158, 0xe605209e), /* PORT158CR */
+	PORTCR(159, 0xe605209f), /* PORT159CR */
+
+	PORTCR(160, 0xe60520a0), /* PORT160CR */
+	PORTCR(161, 0xe60520a1), /* PORT161CR */
+	PORTCR(162, 0xe60520a2), /* PORT162CR */
+	PORTCR(163, 0xe60520a3), /* PORT163CR */
+	PORTCR(164, 0xe60520a4), /* PORT164CR */
+
+	PORTCR(192, 0xe60520c0), /* PORT192CR */
+	PORTCR(193, 0xe60520c1), /* PORT193CR */
+	PORTCR(194, 0xe60520c2), /* PORT194CR */
+	PORTCR(195, 0xe60520c3), /* PORT195CR */
+	PORTCR(196, 0xe60520c4), /* PORT196CR */
+	PORTCR(197, 0xe60520c5), /* PORT197CR */
+	PORTCR(198, 0xe60520c6), /* PORT198CR */
+	PORTCR(199, 0xe60520c7), /* PORT199CR */
+
+	PORTCR(200, 0xe60520c8), /* PORT200CR */
+	PORTCR(201, 0xe60520c9), /* PORT201CR */
+	PORTCR(202, 0xe60520ca), /* PORT202CR */
+	PORTCR(203, 0xe60520cb), /* PORT203CR */
+	PORTCR(204, 0xe60520cc), /* PORT204CR */
+	PORTCR(205, 0xe60520cd), /* PORT205CR */
+	PORTCR(206, 0xe60520ce), /* PORT206CR */
+	PORTCR(207, 0xe60520cf), /* PORT207CR */
+	PORTCR(208, 0xe60520d0), /* PORT208CR */
+	PORTCR(209, 0xe60520d1), /* PORT209CR */
+
+	PORTCR(210, 0xe60520d2), /* PORT210CR */
+	PORTCR(211, 0xe60520d3), /* PORT211CR */
+	PORTCR(212, 0xe60520d4), /* PORT212CR */
+	PORTCR(213, 0xe60520d5), /* PORT213CR */
+	PORTCR(214, 0xe60520d6), /* PORT214CR */
+	PORTCR(215, 0xe60520d7), /* PORT215CR */
+	PORTCR(216, 0xe60520d8), /* PORT216CR */
+	PORTCR(217, 0xe60520d9), /* PORT217CR */
+	PORTCR(218, 0xe60520da), /* PORT218CR */
+	PORTCR(219, 0xe60520db), /* PORT219CR */
+
+	PORTCR(220, 0xe60520dc), /* PORT220CR */
+	PORTCR(221, 0xe60520dd), /* PORT221CR */
+	PORTCR(222, 0xe60520de), /* PORT222CR */
+	PORTCR(223, 0xe60520df), /* PORT223CR */
+	PORTCR(224, 0xe60530e0), /* PORT224CR */
+	PORTCR(225, 0xe60530e1), /* PORT225CR */
+	PORTCR(226, 0xe60530e2), /* PORT226CR */
+	PORTCR(227, 0xe60530e3), /* PORT227CR */
+	PORTCR(228, 0xe60530e4), /* PORT228CR */
+	PORTCR(229, 0xe60530e5), /* PORT229CR */
+
+	PORTCR(230, 0xe60530e6), /* PORT230CR */
+	PORTCR(231, 0xe60530e7), /* PORT231CR */
+	PORTCR(232, 0xe60530e8), /* PORT232CR */
+	PORTCR(233, 0xe60530e9), /* PORT233CR */
+	PORTCR(234, 0xe60530ea), /* PORT234CR */
+	PORTCR(235, 0xe60530eb), /* PORT235CR */
+	PORTCR(236, 0xe60530ec), /* PORT236CR */
+	PORTCR(237, 0xe60530ed), /* PORT237CR */
+	PORTCR(238, 0xe60530ee), /* PORT238CR */
+	PORTCR(239, 0xe60530ef), /* PORT239CR */
+
+	PORTCR(240, 0xe60530f0), /* PORT240CR */
+	PORTCR(241, 0xe60530f1), /* PORT241CR */
+	PORTCR(242, 0xe60530f2), /* PORT242CR */
+	PORTCR(243, 0xe60530f3), /* PORT243CR */
+	PORTCR(244, 0xe60530f4), /* PORT244CR */
+	PORTCR(245, 0xe60530f5), /* PORT245CR */
+	PORTCR(246, 0xe60530f6), /* PORT246CR */
+	PORTCR(247, 0xe60530f7), /* PORT247CR */
+	PORTCR(248, 0xe60530f8), /* PORT248CR */
+	PORTCR(249, 0xe60530f9), /* PORT249CR */
+
+	PORTCR(250, 0xe60530fa), /* PORT250CR */
+	PORTCR(251, 0xe60530fb), /* PORT251CR */
+	PORTCR(252, 0xe60530fc), /* PORT252CR */
+	PORTCR(253, 0xe60530fd), /* PORT253CR */
+	PORTCR(254, 0xe60530fe), /* PORT254CR */
+	PORTCR(255, 0xe60530ff), /* PORT255CR */
+	PORTCR(256, 0xe6053100), /* PORT256CR */
+	PORTCR(257, 0xe6053101), /* PORT257CR */
+	PORTCR(258, 0xe6053102), /* PORT258CR */
+	PORTCR(259, 0xe6053103), /* PORT259CR */
+
+	PORTCR(260, 0xe6053104), /* PORT260CR */
+	PORTCR(261, 0xe6053105), /* PORT261CR */
+	PORTCR(262, 0xe6053106), /* PORT262CR */
+	PORTCR(263, 0xe6053107), /* PORT263CR */
+	PORTCR(264, 0xe6053108), /* PORT264CR */
+	PORTCR(265, 0xe6053109), /* PORT265CR */
+	PORTCR(266, 0xe605310a), /* PORT266CR */
+	PORTCR(267, 0xe605310b), /* PORT267CR */
+	PORTCR(268, 0xe605310c), /* PORT268CR */
+	PORTCR(269, 0xe605310d), /* PORT269CR */
+
+	PORTCR(270, 0xe605310e), /* PORT270CR */
+	PORTCR(271, 0xe605310f), /* PORT271CR */
+	PORTCR(272, 0xe6053110), /* PORT272CR */
+	PORTCR(273, 0xe6053111), /* PORT273CR */
+	PORTCR(274, 0xe6053112), /* PORT274CR */
+	PORTCR(275, 0xe6053113), /* PORT275CR */
+	PORTCR(276, 0xe6053114), /* PORT276CR */
+	PORTCR(277, 0xe6053115), /* PORT277CR */
+	PORTCR(278, 0xe6053116), /* PORT278CR */
+	PORTCR(279, 0xe6053117), /* PORT279CR */
+
+	PORTCR(280, 0xe6053118), /* PORT280CR */
+	PORTCR(281, 0xe6053119), /* PORT281CR */
+	PORTCR(282, 0xe605311a), /* PORT282CR */
+
+	PORTCR(288, 0xe6052120), /* PORT288CR */
+	PORTCR(289, 0xe6052121), /* PORT289CR */
+
+	PORTCR(290, 0xe6052122), /* PORT290CR */
+	PORTCR(291, 0xe6052123), /* PORT291CR */
+	PORTCR(292, 0xe6052124), /* PORT292CR */
+	PORTCR(293, 0xe6052125), /* PORT293CR */
+	PORTCR(294, 0xe6052126), /* PORT294CR */
+	PORTCR(295, 0xe6052127), /* PORT295CR */
+	PORTCR(296, 0xe6052128), /* PORT296CR */
+	PORTCR(297, 0xe6052129), /* PORT297CR */
+	PORTCR(298, 0xe605212a), /* PORT298CR */
+	PORTCR(299, 0xe605212b), /* PORT299CR */
+
+	PORTCR(300, 0xe605212c), /* PORT300CR */
+	PORTCR(301, 0xe605212d), /* PORT301CR */
+	PORTCR(302, 0xe605212e), /* PORT302CR */
+	PORTCR(303, 0xe605212f), /* PORT303CR */
+	PORTCR(304, 0xe6052130), /* PORT304CR */
+	PORTCR(305, 0xe6052131), /* PORT305CR */
+	PORTCR(306, 0xe6052132), /* PORT306CR */
+	PORTCR(307, 0xe6052133), /* PORT307CR */
+	PORTCR(308, 0xe6052134), /* PORT308CR */
+	PORTCR(309, 0xe6052135), /* PORT309CR */
+
+	{ PINMUX_CFG_REG("MSEL2CR", 0xe605801c, 32, 1) {
+			0, 0,
+			0, 0,
+			0, 0,
+			0, 0,
+			0, 0,
+			0, 0,
+			0, 0,
+			0, 0,
+			0, 0,
+			0, 0,
+			0, 0,
+			0, 0,
+			MSEL2CR_MSEL19_0, MSEL2CR_MSEL19_1,
+			MSEL2CR_MSEL18_0, MSEL2CR_MSEL18_1,
+			MSEL2CR_MSEL17_0, MSEL2CR_MSEL17_1,
+			MSEL2CR_MSEL16_0, MSEL2CR_MSEL16_1,
+			0, 0,
+			MSEL2CR_MSEL14_0, MSEL2CR_MSEL14_1,
+			MSEL2CR_MSEL13_0, MSEL2CR_MSEL13_1,
+			MSEL2CR_MSEL12_0, MSEL2CR_MSEL12_1,
+			MSEL2CR_MSEL11_0, MSEL2CR_MSEL11_1,
+			MSEL2CR_MSEL10_0, MSEL2CR_MSEL10_1,
+			MSEL2CR_MSEL9_0, MSEL2CR_MSEL9_1,
+			MSEL2CR_MSEL8_0, MSEL2CR_MSEL8_1,
+			MSEL2CR_MSEL7_0, MSEL2CR_MSEL7_1,
+			MSEL2CR_MSEL6_0, MSEL2CR_MSEL6_1,
+			MSEL2CR_MSEL5_0, MSEL2CR_MSEL5_1,
+			MSEL2CR_MSEL4_0, MSEL2CR_MSEL4_1,
+			MSEL2CR_MSEL3_0, MSEL2CR_MSEL3_1,
+			MSEL2CR_MSEL2_0, MSEL2CR_MSEL2_1,
+			MSEL2CR_MSEL1_0, MSEL2CR_MSEL1_1,
+			MSEL2CR_MSEL0_0, MSEL2CR_MSEL0_1,
+		}
+	},
+	{ PINMUX_CFG_REG("MSEL3CR", 0xe6058020, 32, 1) {
+			0, 0,
+			0, 0,
+			0, 0,
+			MSEL3CR_MSEL28_0, MSEL3CR_MSEL28_1,
+			0, 0,
+			0, 0,
+			0, 0,
+			0, 0,
+			0, 0,
+			0, 0,
+			0, 0,
+			0, 0,
+			0, 0,
+			0, 0,
+			0, 0,
+			0, 0,
+			MSEL3CR_MSEL15_0, MSEL3CR_MSEL15_1,
+			0, 0,
+			0, 0,
+			0, 0,
+			MSEL3CR_MSEL11_0, MSEL3CR_MSEL11_1,
+			0, 0,
+			MSEL3CR_MSEL9_0, MSEL3CR_MSEL9_1,
+			0, 0,
+			0, 0,
+			MSEL3CR_MSEL6_0, MSEL3CR_MSEL6_1,
+			0, 0,
+			0, 0,
+			0, 0,
+			MSEL3CR_MSEL2_0, MSEL3CR_MSEL2_1,
+			0, 0,
+			0, 0,
+		}
+	},
+	{ PINMUX_CFG_REG("MSEL4CR", 0xe6058024, 32, 1) {
+			0, 0,
+			0, 0,
+			MSEL4CR_MSEL29_0, MSEL4CR_MSEL29_1,
+			0, 0,
+			MSEL4CR_MSEL27_0, MSEL4CR_MSEL27_1,
+			MSEL4CR_MSEL26_0, MSEL4CR_MSEL26_1,
+			0, 0,
+			0, 0,
+			0, 0,
+			MSEL4CR_MSEL22_0, MSEL4CR_MSEL22_1,
+			MSEL4CR_MSEL21_0, MSEL4CR_MSEL21_1,
+			MSEL4CR_MSEL20_0, MSEL4CR_MSEL20_1,
+			MSEL4CR_MSEL19_0, MSEL4CR_MSEL19_1,
+			0, 0,
+			0, 0,
+			0, 0,
+			MSEL4CR_MSEL15_0, MSEL4CR_MSEL15_1,
+			0, 0,
+			MSEL4CR_MSEL13_0, MSEL4CR_MSEL13_1,
+			MSEL4CR_MSEL12_0, MSEL4CR_MSEL12_1,
+			MSEL4CR_MSEL11_0, MSEL4CR_MSEL11_1,
+			MSEL4CR_MSEL10_0, MSEL4CR_MSEL10_1,
+			MSEL4CR_MSEL9_0, MSEL4CR_MSEL9_1,
+			MSEL4CR_MSEL8_0, MSEL4CR_MSEL8_1,
+			MSEL4CR_MSEL7_0, MSEL4CR_MSEL7_1,
+			0, 0,
+			0, 0,
+			MSEL4CR_MSEL4_0, MSEL4CR_MSEL4_1,
+			0, 0,
+			0, 0,
+			MSEL4CR_MSEL1_0, MSEL4CR_MSEL1_1,
+			0, 0,
+		}
+	},
+	{ },
+};
+
+static struct pinmux_data_reg pinmux_data_regs[] = {
+	{ PINMUX_DATA_REG("PORTL031_000DR", 0xe6054000, 32) {
+			PORT31_DATA, PORT30_DATA, PORT29_DATA, PORT28_DATA,
+			PORT27_DATA, PORT26_DATA, PORT25_DATA, PORT24_DATA,
+			PORT23_DATA, PORT22_DATA, PORT21_DATA, PORT20_DATA,
+			PORT19_DATA, PORT18_DATA, PORT17_DATA, PORT16_DATA,
+			PORT15_DATA, PORT14_DATA, PORT13_DATA, PORT12_DATA,
+			PORT11_DATA, PORT10_DATA, PORT9_DATA, PORT8_DATA,
+			PORT7_DATA, PORT6_DATA, PORT5_DATA, PORT4_DATA,
+			PORT3_DATA, PORT2_DATA, PORT1_DATA, PORT0_DATA }
+	},
+	{ PINMUX_DATA_REG("PORTD063_032DR", 0xe6055000, 32) {
+			PORT63_DATA, PORT62_DATA, PORT61_DATA, PORT60_DATA,
+			PORT59_DATA, PORT58_DATA, PORT57_DATA, PORT56_DATA,
+			PORT55_DATA, PORT54_DATA, PORT53_DATA, PORT52_DATA,
+			PORT51_DATA, PORT50_DATA, PORT49_DATA, PORT48_DATA,
+			PORT47_DATA, PORT46_DATA, PORT45_DATA, PORT44_DATA,
+			PORT43_DATA, PORT42_DATA, PORT41_DATA, PORT40_DATA,
+			PORT39_DATA, PORT38_DATA, PORT37_DATA, PORT36_DATA,
+			PORT35_DATA, PORT34_DATA, PORT33_DATA, PORT32_DATA }
+	},
+	{ PINMUX_DATA_REG("PORTD095_064DR", 0xe6055004, 32) {
+			PORT95_DATA, PORT94_DATA, PORT93_DATA, PORT92_DATA,
+			PORT91_DATA, PORT90_DATA, PORT89_DATA, PORT88_DATA,
+			PORT87_DATA, PORT86_DATA, PORT85_DATA, PORT84_DATA,
+			PORT83_DATA, PORT82_DATA, PORT81_DATA, PORT80_DATA,
+			PORT79_DATA, PORT78_DATA, PORT77_DATA, PORT76_DATA,
+			PORT75_DATA, PORT74_DATA, PORT73_DATA, PORT72_DATA,
+			PORT71_DATA, PORT70_DATA, PORT69_DATA, PORT68_DATA,
+			PORT67_DATA, PORT66_DATA, PORT65_DATA, PORT64_DATA }
+	},
+	{ PINMUX_DATA_REG("PORTR127_096DR", 0xe6056000, 32) {
+			0, 0, 0, 0,
+			0, 0, 0, 0,
+			0, PORT118_DATA, PORT117_DATA, PORT116_DATA,
+			PORT115_DATA, PORT114_DATA, PORT113_DATA, PORT112_DATA,
+			PORT111_DATA, PORT110_DATA, PORT109_DATA, PORT108_DATA,
+			PORT107_DATA, PORT106_DATA, PORT105_DATA, PORT104_DATA,
+			PORT103_DATA, PORT102_DATA, PORT101_DATA, PORT100_DATA,
+			PORT99_DATA, PORT98_DATA, PORT97_DATA, PORT96_DATA }
+	},
+	{ PINMUX_DATA_REG("PORTR159_128DR", 0xe6056004, 32) {
+			PORT159_DATA, PORT158_DATA, PORT157_DATA, PORT156_DATA,
+			PORT155_DATA, PORT154_DATA, PORT153_DATA, PORT152_DATA,
+			PORT151_DATA, PORT150_DATA, PORT149_DATA, PORT148_DATA,
+			PORT147_DATA, PORT146_DATA, PORT145_DATA, PORT144_DATA,
+			PORT143_DATA, PORT142_DATA, PORT141_DATA, PORT140_DATA,
+			PORT139_DATA, PORT138_DATA, PORT137_DATA, PORT136_DATA,
+			PORT135_DATA, PORT134_DATA, PORT133_DATA, PORT132_DATA,
+			PORT131_DATA, PORT130_DATA, PORT129_DATA, PORT128_DATA }
+	},
+	{ PINMUX_DATA_REG("PORTR191_160DR", 0xe6056008, 32) {
+			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, PORT164_DATA,
+			PORT163_DATA, PORT162_DATA, PORT161_DATA, PORT160_DATA }
+	},
+	{ PINMUX_DATA_REG("PORTR223_192DR", 0xe605600C, 32) {
+			PORT223_DATA, PORT222_DATA, PORT221_DATA, PORT220_DATA,
+			PORT219_DATA, PORT218_DATA, PORT217_DATA, PORT216_DATA,
+			PORT215_DATA, PORT214_DATA, PORT213_DATA, PORT212_DATA,
+			PORT211_DATA, PORT210_DATA, PORT209_DATA, PORT208_DATA,
+			PORT207_DATA, PORT206_DATA, PORT205_DATA, PORT204_DATA,
+			PORT203_DATA, PORT202_DATA, PORT201_DATA, PORT200_DATA,
+			PORT199_DATA, PORT198_DATA, PORT197_DATA, PORT196_DATA,
+			PORT195_DATA, PORT194_DATA, PORT193_DATA, PORT192_DATA }
+	},
+	{ PINMUX_DATA_REG("PORTU255_224DR", 0xe6057000, 32) {
+			PORT255_DATA, PORT254_DATA, PORT253_DATA, PORT252_DATA,
+			PORT251_DATA, PORT250_DATA, PORT249_DATA, PORT248_DATA,
+			PORT247_DATA, PORT246_DATA, PORT245_DATA, PORT244_DATA,
+			PORT243_DATA, PORT242_DATA, PORT241_DATA, PORT240_DATA,
+			PORT239_DATA, PORT238_DATA, PORT237_DATA, PORT236_DATA,
+			PORT235_DATA, PORT234_DATA, PORT233_DATA, PORT232_DATA,
+			PORT231_DATA, PORT230_DATA, PORT229_DATA, PORT228_DATA,
+			PORT227_DATA, PORT226_DATA, PORT225_DATA, PORT224_DATA }
+	},
+	{ PINMUX_DATA_REG("PORTU287_256DR", 0xe6057004, 32) {
+			0, 0, 0, 0,
+			0, PORT282_DATA, PORT281_DATA, PORT280_DATA,
+			PORT279_DATA, PORT278_DATA, PORT277_DATA, PORT276_DATA,
+			PORT275_DATA, PORT274_DATA, PORT273_DATA, PORT272_DATA,
+			PORT271_DATA, PORT270_DATA, PORT269_DATA, PORT268_DATA,
+			PORT267_DATA, PORT266_DATA, PORT265_DATA, PORT264_DATA,
+			PORT263_DATA, PORT262_DATA, PORT261_DATA, PORT260_DATA,
+			PORT259_DATA, PORT258_DATA, PORT257_DATA, PORT256_DATA }
+	},
+	{ PINMUX_DATA_REG("PORTR319_288DR", 0xe6056010, 32) {
+			0, 0, 0, 0,
+			0, 0, 0, 0,
+			0, 0, PORT309_DATA, PORT308_DATA,
+			PORT307_DATA, PORT306_DATA, PORT305_DATA, PORT304_DATA,
+			PORT303_DATA, PORT302_DATA, PORT301_DATA, PORT300_DATA,
+			PORT299_DATA, PORT298_DATA, PORT297_DATA, PORT296_DATA,
+			PORT295_DATA, PORT294_DATA, PORT293_DATA, PORT292_DATA,
+			PORT291_DATA, PORT290_DATA, PORT289_DATA, PORT288_DATA }
+	},
+	{ },
+};
+
+static struct pinmux_info sh73a0_pinmux_info = {
+	.name = "sh73a0_pfc",
+	.reserved_id = PINMUX_RESERVED,
+	.data = { PINMUX_DATA_BEGIN, PINMUX_DATA_END },
+	.input = { PINMUX_INPUT_BEGIN, PINMUX_INPUT_END },
+	.input_pu = { PINMUX_INPUT_PULLUP_BEGIN, PINMUX_INPUT_PULLUP_END },
+	.input_pd = { PINMUX_INPUT_PULLDOWN_BEGIN, PINMUX_INPUT_PULLDOWN_END },
+	.output = { PINMUX_OUTPUT_BEGIN, PINMUX_OUTPUT_END },
+	.mark = { PINMUX_MARK_BEGIN, PINMUX_MARK_END },
+	.function = { PINMUX_FUNCTION_BEGIN, PINMUX_FUNCTION_END },
+
+	.first_gpio = GPIO_PORT0,
+	.last_gpio = GPIO_FN_FSIAISLD_PU,
+
+	.gpios = pinmux_gpios,
+	.cfg_regs = pinmux_config_regs,
+	.data_regs = pinmux_data_regs,
+
+	.gpio_data = pinmux_data,
+	.gpio_data_size = ARRAY_SIZE(pinmux_data),
+};
+
+void sh73a0_pinmux_init(void)
+{
+	register_pinmux(&sh73a0_pinmux_info);
+}
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-shmobile/platsmp.c linux-libre-2.6.38-gnu1/arch/arm/mach-shmobile/platsmp.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-shmobile/platsmp.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-shmobile/platsmp.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,70 @@
+/*
+ * SMP support for R-Mobile / SH-Mobile
+ *
+ * Copyright (C) 2010  Magnus Damm
+ * Copyright (C) 2011  Paul Mundt
+ *
+ * Based on vexpress, 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/smp.h>
+#include <linux/io.h>
+#include <asm/localtimer.h>
+#include <asm/mach-types.h>
+#include <mach/common.h>
+
+static unsigned int __init shmobile_smp_get_core_count(void)
+{
+	if (machine_is_ag5evm())
+		return sh73a0_get_core_count();
+
+	return 1;
+}
+
+static void __init shmobile_smp_prepare_cpus(void)
+{
+	if (machine_is_ag5evm())
+		sh73a0_smp_prepare_cpus();
+}
+
+void __cpuinit platform_secondary_init(unsigned int cpu)
+{
+	trace_hardirqs_off();
+
+	if (machine_is_ag5evm())
+		sh73a0_secondary_init(cpu);
+}
+
+int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
+{
+	if (machine_is_ag5evm())
+		return sh73a0_boot_secondary(cpu);
+
+	return -ENOSYS;
+}
+
+void __init smp_init_cpus(void)
+{
+	unsigned int ncores = shmobile_smp_get_core_count();
+	unsigned int i;
+
+	for (i = 0; i < ncores; i++)
+		set_cpu_possible(i, true);
+}
+
+void __init platform_smp_prepare_cpus(unsigned int max_cpus)
+{
+	int i;
+
+	for (i = 0; i < max_cpus; i++)
+		set_cpu_present(i, true);
+
+	shmobile_smp_prepare_cpus();
+}
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-shmobile/setup-sh7367.c linux-libre-2.6.38-gnu1/arch/arm/mach-shmobile/setup-sh7367.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-shmobile/setup-sh7367.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-shmobile/setup-sh7367.c	2011-03-14 21:20:32.000000000 -0400
@@ -35,6 +35,8 @@
 static struct plat_sci_port scif0_platform_data = {
 	.mapbase	= 0xe6c40000,
 	.flags		= UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_RE | SCSCR_TE,
+	.scbrr_algo_id	= SCBRR_ALGO_4,
 	.type		= PORT_SCIF,
 	.irqs		= { evt2irq(0xc00), evt2irq(0xc00),
 			    evt2irq(0xc00), evt2irq(0xc00) },
@@ -52,6 +54,8 @@ static struct platform_device scif0_devi
 static struct plat_sci_port scif1_platform_data = {
 	.mapbase	= 0xe6c50000,
 	.flags		= UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_RE | SCSCR_TE,
+	.scbrr_algo_id	= SCBRR_ALGO_4,
 	.type		= PORT_SCIF,
 	.irqs		= { evt2irq(0xc20), evt2irq(0xc20),
 			    evt2irq(0xc20), evt2irq(0xc20) },
@@ -69,6 +73,8 @@ static struct platform_device scif1_devi
 static struct plat_sci_port scif2_platform_data = {
 	.mapbase	= 0xe6c60000,
 	.flags		= UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_RE | SCSCR_TE,
+	.scbrr_algo_id	= SCBRR_ALGO_4,
 	.type		= PORT_SCIF,
 	.irqs		= { evt2irq(0xc40), evt2irq(0xc40),
 			    evt2irq(0xc40), evt2irq(0xc40) },
@@ -86,6 +92,8 @@ static struct platform_device scif2_devi
 static struct plat_sci_port scif3_platform_data = {
 	.mapbase	= 0xe6c70000,
 	.flags		= UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_RE | SCSCR_TE,
+	.scbrr_algo_id	= SCBRR_ALGO_4,
 	.type		= PORT_SCIF,
 	.irqs		= { evt2irq(0xc60), evt2irq(0xc60),
 			    evt2irq(0xc60), evt2irq(0xc60) },
@@ -103,6 +111,8 @@ static struct platform_device scif3_devi
 static struct plat_sci_port scif4_platform_data = {
 	.mapbase	= 0xe6c80000,
 	.flags		= UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_RE | SCSCR_TE,
+	.scbrr_algo_id	= SCBRR_ALGO_4,
 	.type		= PORT_SCIF,
 	.irqs		= { evt2irq(0xd20), evt2irq(0xd20),
 			    evt2irq(0xd20), evt2irq(0xd20) },
@@ -120,6 +130,8 @@ static struct platform_device scif4_devi
 static struct plat_sci_port scif5_platform_data = {
 	.mapbase	= 0xe6cb0000,
 	.flags		= UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_RE | SCSCR_TE,
+	.scbrr_algo_id	= SCBRR_ALGO_4,
 	.type		= PORT_SCIF,
 	.irqs		= { evt2irq(0xd40), evt2irq(0xd40),
 			    evt2irq(0xd40), evt2irq(0xd40) },
@@ -137,6 +149,8 @@ static struct platform_device scif5_devi
 static struct plat_sci_port scif6_platform_data = {
 	.mapbase	= 0xe6c30000,
 	.flags		= UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_RE | SCSCR_TE,
+	.scbrr_algo_id	= SCBRR_ALGO_4,
 	.type		= PORT_SCIF,
 	.irqs		= { evt2irq(0xd60), evt2irq(0xd60),
 			    evt2irq(0xd60), evt2irq(0xd60) },
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-shmobile/setup-sh7372.c linux-libre-2.6.38-gnu1/arch/arm/mach-shmobile/setup-sh7372.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-shmobile/setup-sh7372.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-shmobile/setup-sh7372.c	2011-03-14 21:20:32.000000000 -0400
@@ -38,6 +38,8 @@
 static struct plat_sci_port scif0_platform_data = {
 	.mapbase	= 0xe6c40000,
 	.flags		= UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_RE | SCSCR_TE,
+	.scbrr_algo_id	= SCBRR_ALGO_4,
 	.type		= PORT_SCIFA,
 	.irqs		= { evt2irq(0x0c00), evt2irq(0x0c00),
 			    evt2irq(0x0c00), evt2irq(0x0c00) },
@@ -55,6 +57,8 @@ static struct platform_device scif0_devi
 static struct plat_sci_port scif1_platform_data = {
 	.mapbase	= 0xe6c50000,
 	.flags		= UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_RE | SCSCR_TE,
+	.scbrr_algo_id	= SCBRR_ALGO_4,
 	.type		= PORT_SCIFA,
 	.irqs		= { evt2irq(0x0c20), evt2irq(0x0c20),
 			    evt2irq(0x0c20), evt2irq(0x0c20) },
@@ -72,6 +76,8 @@ static struct platform_device scif1_devi
 static struct plat_sci_port scif2_platform_data = {
 	.mapbase	= 0xe6c60000,
 	.flags		= UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_RE | SCSCR_TE,
+	.scbrr_algo_id	= SCBRR_ALGO_4,
 	.type		= PORT_SCIFA,
 	.irqs		= { evt2irq(0x0c40), evt2irq(0x0c40),
 			    evt2irq(0x0c40), evt2irq(0x0c40) },
@@ -89,6 +95,8 @@ static struct platform_device scif2_devi
 static struct plat_sci_port scif3_platform_data = {
 	.mapbase	= 0xe6c70000,
 	.flags		= UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_RE | SCSCR_TE,
+	.scbrr_algo_id	= SCBRR_ALGO_4,
 	.type		= PORT_SCIFA,
 	.irqs		= { evt2irq(0x0c60), evt2irq(0x0c60),
 			    evt2irq(0x0c60), evt2irq(0x0c60) },
@@ -106,6 +114,8 @@ static struct platform_device scif3_devi
 static struct plat_sci_port scif4_platform_data = {
 	.mapbase	= 0xe6c80000,
 	.flags		= UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_RE | SCSCR_TE,
+	.scbrr_algo_id	= SCBRR_ALGO_4,
 	.type		= PORT_SCIFA,
 	.irqs		= { evt2irq(0x0d20), evt2irq(0x0d20),
 			    evt2irq(0x0d20), evt2irq(0x0d20) },
@@ -123,6 +133,8 @@ static struct platform_device scif4_devi
 static struct plat_sci_port scif5_platform_data = {
 	.mapbase	= 0xe6cb0000,
 	.flags		= UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_RE | SCSCR_TE,
+	.scbrr_algo_id	= SCBRR_ALGO_4,
 	.type		= PORT_SCIFA,
 	.irqs		= { evt2irq(0x0d40), evt2irq(0x0d40),
 			    evt2irq(0x0d40), evt2irq(0x0d40) },
@@ -140,6 +152,8 @@ static struct platform_device scif5_devi
 static struct plat_sci_port scif6_platform_data = {
 	.mapbase	= 0xe6c30000,
 	.flags		= UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_RE | SCSCR_TE,
+	.scbrr_algo_id	= SCBRR_ALGO_4,
 	.type		= PORT_SCIFB,
 	.irqs		= { evt2irq(0x0d60), evt2irq(0x0d60),
 			    evt2irq(0x0d60), evt2irq(0x0d60) },
@@ -416,6 +430,16 @@ static const struct sh_dmae_slave_config
 		.addr		= 0xe6870030,
 		.chcr		= DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_16BIT),
 		.mid_rid	= 0xce,
+	}, {
+		.slave_id	= SHDMA_SLAVE_MMCIF_TX,
+		.addr		= 0xe6bd0034,
+		.chcr		= DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_32BIT),
+		.mid_rid	= 0xd1,
+	}, {
+		.slave_id	= SHDMA_SLAVE_MMCIF_RX,
+		.addr		= 0xe6bd0034,
+		.chcr		= DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_32BIT),
+		.mid_rid	= 0xd2,
 	},
 };
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-shmobile/setup-sh7377.c linux-libre-2.6.38-gnu1/arch/arm/mach-shmobile/setup-sh7377.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-shmobile/setup-sh7377.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-shmobile/setup-sh7377.c	2011-03-14 21:20:32.000000000 -0400
@@ -36,6 +36,8 @@
 static struct plat_sci_port scif0_platform_data = {
 	.mapbase	= 0xe6c40000,
 	.flags		= UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_RE | SCSCR_TE,
+	.scbrr_algo_id	= SCBRR_ALGO_4,
 	.type		= PORT_SCIF,
 	.irqs		= { evt2irq(0xc00), evt2irq(0xc00),
 			    evt2irq(0xc00), evt2irq(0xc00) },
@@ -53,6 +55,8 @@ static struct platform_device scif0_devi
 static struct plat_sci_port scif1_platform_data = {
 	.mapbase	= 0xe6c50000,
 	.flags		= UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_RE | SCSCR_TE,
+	.scbrr_algo_id	= SCBRR_ALGO_4,
 	.type		= PORT_SCIF,
 	.irqs		= { evt2irq(0xc20), evt2irq(0xc20),
 			    evt2irq(0xc20), evt2irq(0xc20) },
@@ -70,6 +74,8 @@ static struct platform_device scif1_devi
 static struct plat_sci_port scif2_platform_data = {
 	.mapbase	= 0xe6c60000,
 	.flags		= UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_RE | SCSCR_TE,
+	.scbrr_algo_id	= SCBRR_ALGO_4,
 	.type		= PORT_SCIF,
 	.irqs		= { evt2irq(0xc40), evt2irq(0xc40),
 			    evt2irq(0xc40), evt2irq(0xc40) },
@@ -87,6 +93,8 @@ static struct platform_device scif2_devi
 static struct plat_sci_port scif3_platform_data = {
 	.mapbase	= 0xe6c70000,
 	.flags		= UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_RE | SCSCR_TE,
+	.scbrr_algo_id	= SCBRR_ALGO_4,
 	.type		= PORT_SCIF,
 	.irqs		= { evt2irq(0xc60), evt2irq(0xc60),
 			    evt2irq(0xc60), evt2irq(0xc60) },
@@ -104,6 +112,8 @@ static struct platform_device scif3_devi
 static struct plat_sci_port scif4_platform_data = {
 	.mapbase	= 0xe6c80000,
 	.flags		= UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_RE | SCSCR_TE,
+	.scbrr_algo_id	= SCBRR_ALGO_4,
 	.type		= PORT_SCIF,
 	.irqs		= { evt2irq(0xd20), evt2irq(0xd20),
 			    evt2irq(0xd20), evt2irq(0xd20) },
@@ -121,6 +131,8 @@ static struct platform_device scif4_devi
 static struct plat_sci_port scif5_platform_data = {
 	.mapbase	= 0xe6cb0000,
 	.flags		= UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_RE | SCSCR_TE,
+	.scbrr_algo_id	= SCBRR_ALGO_4,
 	.type		= PORT_SCIF,
 	.irqs		= { evt2irq(0xd40), evt2irq(0xd40),
 			    evt2irq(0xd40), evt2irq(0xd40) },
@@ -138,6 +150,8 @@ static struct platform_device scif5_devi
 static struct plat_sci_port scif6_platform_data = {
 	.mapbase	= 0xe6cc0000,
 	.flags		= UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_RE | SCSCR_TE,
+	.scbrr_algo_id	= SCBRR_ALGO_4,
 	.type		= PORT_SCIF,
 	.irqs		= { intcs_evt2irq(0x1a80), intcs_evt2irq(0x1a80),
 			    intcs_evt2irq(0x1a80), intcs_evt2irq(0x1a80) },
@@ -155,6 +169,8 @@ static struct platform_device scif6_devi
 static struct plat_sci_port scif7_platform_data = {
 	.mapbase	= 0xe6c30000,
 	.flags		= UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_RE | SCSCR_TE,
+	.scbrr_algo_id	= SCBRR_ALGO_4,
 	.type		= PORT_SCIF,
 	.irqs		= { evt2irq(0xd60), evt2irq(0xd60),
 			    evt2irq(0xd60), evt2irq(0xd60) },
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-shmobile/setup-sh73a0.c linux-libre-2.6.38-gnu1/arch/arm/mach-shmobile/setup-sh73a0.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-shmobile/setup-sh73a0.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-shmobile/setup-sh73a0.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,430 @@
+/*
+ * sh73a0 processor support
+ *
+ * Copyright (C) 2010  Takashi Yoshii
+ * Copyright (C) 2010  Magnus Damm
+ * Copyright (C) 2008  Yoshihiro Shimoda
+ *
+ * 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/input.h>
+#include <linux/io.h>
+#include <linux/serial_sci.h>
+#include <linux/sh_intc.h>
+#include <linux/sh_timer.h>
+#include <mach/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+
+static struct plat_sci_port scif0_platform_data = {
+	.mapbase	= 0xe6c40000,
+	.flags		= UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_RE | SCSCR_TE,
+	.scbrr_algo_id	= SCBRR_ALGO_4,
+	.type		= PORT_SCIFA,
+	.irqs		= { gic_spi(72), gic_spi(72),
+			    gic_spi(72), gic_spi(72) },
+};
+
+static struct platform_device scif0_device = {
+	.name		= "sh-sci",
+	.id		= 0,
+	.dev		= {
+		.platform_data	= &scif0_platform_data,
+	},
+};
+
+static struct plat_sci_port scif1_platform_data = {
+	.mapbase	= 0xe6c50000,
+	.flags		= UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_RE | SCSCR_TE,
+	.scbrr_algo_id	= SCBRR_ALGO_4,
+	.type		= PORT_SCIFA,
+	.irqs		= { gic_spi(73), gic_spi(73),
+			    gic_spi(73), gic_spi(73) },
+};
+
+static struct platform_device scif1_device = {
+	.name		= "sh-sci",
+	.id		= 1,
+	.dev		= {
+		.platform_data	= &scif1_platform_data,
+	},
+};
+
+static struct plat_sci_port scif2_platform_data = {
+	.mapbase	= 0xe6c60000,
+	.flags		= UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_RE | SCSCR_TE,
+	.scbrr_algo_id	= SCBRR_ALGO_4,
+	.type		= PORT_SCIFA,
+	.irqs		= { gic_spi(74), gic_spi(74),
+			    gic_spi(74), gic_spi(74) },
+};
+
+static struct platform_device scif2_device = {
+	.name		= "sh-sci",
+	.id		= 2,
+	.dev		= {
+		.platform_data	= &scif2_platform_data,
+	},
+};
+
+static struct plat_sci_port scif3_platform_data = {
+	.mapbase	= 0xe6c70000,
+	.flags		= UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_RE | SCSCR_TE,
+	.scbrr_algo_id	= SCBRR_ALGO_4,
+	.type		= PORT_SCIFA,
+	.irqs		= { gic_spi(75), gic_spi(75),
+			    gic_spi(75), gic_spi(75) },
+};
+
+static struct platform_device scif3_device = {
+	.name		= "sh-sci",
+	.id		= 3,
+	.dev		= {
+		.platform_data	= &scif3_platform_data,
+	},
+};
+
+static struct plat_sci_port scif4_platform_data = {
+	.mapbase	= 0xe6c80000,
+	.flags		= UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_RE | SCSCR_TE,
+	.scbrr_algo_id	= SCBRR_ALGO_4,
+	.type		= PORT_SCIFA,
+	.irqs		= { gic_spi(78), gic_spi(78),
+			    gic_spi(78), gic_spi(78) },
+};
+
+static struct platform_device scif4_device = {
+	.name		= "sh-sci",
+	.id		= 4,
+	.dev		= {
+		.platform_data	= &scif4_platform_data,
+	},
+};
+
+static struct plat_sci_port scif5_platform_data = {
+	.mapbase	= 0xe6cb0000,
+	.flags		= UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_RE | SCSCR_TE,
+	.scbrr_algo_id	= SCBRR_ALGO_4,
+	.type		= PORT_SCIFA,
+	.irqs		= { gic_spi(79), gic_spi(79),
+			    gic_spi(79), gic_spi(79) },
+};
+
+static struct platform_device scif5_device = {
+	.name		= "sh-sci",
+	.id		= 5,
+	.dev		= {
+		.platform_data	= &scif5_platform_data,
+	},
+};
+
+static struct plat_sci_port scif6_platform_data = {
+	.mapbase	= 0xe6cc0000,
+	.flags		= UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_RE | SCSCR_TE,
+	.scbrr_algo_id	= SCBRR_ALGO_4,
+	.type		= PORT_SCIFA,
+	.irqs		= { gic_spi(156), gic_spi(156),
+			    gic_spi(156), gic_spi(156) },
+};
+
+static struct platform_device scif6_device = {
+	.name		= "sh-sci",
+	.id		= 6,
+	.dev		= {
+		.platform_data	= &scif6_platform_data,
+	},
+};
+
+static struct plat_sci_port scif7_platform_data = {
+	.mapbase	= 0xe6cd0000,
+	.flags		= UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_RE | SCSCR_TE,
+	.scbrr_algo_id	= SCBRR_ALGO_4,
+	.type		= PORT_SCIFA,
+	.irqs		= { gic_spi(143), gic_spi(143),
+			    gic_spi(143), gic_spi(143) },
+};
+
+static struct platform_device scif7_device = {
+	.name		= "sh-sci",
+	.id		= 7,
+	.dev		= {
+		.platform_data	= &scif7_platform_data,
+	},
+};
+
+static struct plat_sci_port scif8_platform_data = {
+	.mapbase	= 0xe6c30000,
+	.flags		= UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_RE | SCSCR_TE,
+	.scbrr_algo_id	= SCBRR_ALGO_4,
+	.type		= PORT_SCIFB,
+	.irqs		= { gic_spi(80), gic_spi(80),
+			    gic_spi(80), gic_spi(80) },
+};
+
+static struct platform_device scif8_device = {
+	.name		= "sh-sci",
+	.id		= 8,
+	.dev		= {
+		.platform_data	= &scif8_platform_data,
+	},
+};
+
+static struct sh_timer_config cmt10_platform_data = {
+	.name = "CMT10",
+	.channel_offset = 0x10,
+	.timer_bit = 0,
+	.clockevent_rating = 125,
+	.clocksource_rating = 125,
+};
+
+static struct resource cmt10_resources[] = {
+	[0] = {
+		.name	= "CMT10",
+		.start	= 0xe6138010,
+		.end	= 0xe613801b,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= gic_spi(65),
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device cmt10_device = {
+	.name		= "sh_cmt",
+	.id		= 10,
+	.dev = {
+		.platform_data	= &cmt10_platform_data,
+	},
+	.resource	= cmt10_resources,
+	.num_resources	= ARRAY_SIZE(cmt10_resources),
+};
+
+/* TMU */
+static struct sh_timer_config tmu00_platform_data = {
+	.name = "TMU00",
+	.channel_offset = 0x4,
+	.timer_bit = 0,
+	.clockevent_rating = 200,
+};
+
+static struct resource tmu00_resources[] = {
+	[0] = {
+		.name	= "TMU00",
+		.start	= 0xfff60008,
+		.end	= 0xfff60013,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= intcs_evt2irq(0x0e80), /* TMU0_TUNI00 */
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device tmu00_device = {
+	.name		= "sh_tmu",
+	.id		= 0,
+	.dev = {
+		.platform_data	= &tmu00_platform_data,
+	},
+	.resource	= tmu00_resources,
+	.num_resources	= ARRAY_SIZE(tmu00_resources),
+};
+
+static struct sh_timer_config tmu01_platform_data = {
+	.name = "TMU01",
+	.channel_offset = 0x10,
+	.timer_bit = 1,
+	.clocksource_rating = 200,
+};
+
+static struct resource tmu01_resources[] = {
+	[0] = {
+		.name	= "TMU01",
+		.start	= 0xfff60014,
+		.end	= 0xfff6001f,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= intcs_evt2irq(0x0ea0), /* TMU0_TUNI01 */
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device tmu01_device = {
+	.name		= "sh_tmu",
+	.id		= 1,
+	.dev = {
+		.platform_data	= &tmu01_platform_data,
+	},
+	.resource	= tmu01_resources,
+	.num_resources	= ARRAY_SIZE(tmu01_resources),
+};
+
+static struct resource i2c0_resources[] = {
+	[0] = {
+		.name	= "IIC0",
+		.start	= 0xe6820000,
+		.end	= 0xe6820425 - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= gic_spi(167),
+		.end	= gic_spi(170),
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct resource i2c1_resources[] = {
+	[0] = {
+		.name	= "IIC1",
+		.start	= 0xe6822000,
+		.end	= 0xe6822425 - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= gic_spi(51),
+		.end	= gic_spi(54),
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct resource i2c2_resources[] = {
+	[0] = {
+		.name	= "IIC2",
+		.start	= 0xe6824000,
+		.end	= 0xe6824425 - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= gic_spi(171),
+		.end	= gic_spi(174),
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct resource i2c3_resources[] = {
+	[0] = {
+		.name	= "IIC3",
+		.start	= 0xe6826000,
+		.end	= 0xe6826425 - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= gic_spi(183),
+		.end	= gic_spi(186),
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct resource i2c4_resources[] = {
+	[0] = {
+		.name	= "IIC4",
+		.start	= 0xe6828000,
+		.end	= 0xe6828425 - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= gic_spi(187),
+		.end	= gic_spi(190),
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device i2c0_device = {
+	.name		= "i2c-sh_mobile",
+	.id		= 0,
+	.resource	= i2c0_resources,
+	.num_resources	= ARRAY_SIZE(i2c0_resources),
+};
+
+static struct platform_device i2c1_device = {
+	.name		= "i2c-sh_mobile",
+	.id		= 1,
+	.resource	= i2c1_resources,
+	.num_resources	= ARRAY_SIZE(i2c1_resources),
+};
+
+static struct platform_device i2c2_device = {
+	.name		= "i2c-sh_mobile",
+	.id		= 2,
+	.resource	= i2c2_resources,
+	.num_resources	= ARRAY_SIZE(i2c2_resources),
+};
+
+static struct platform_device i2c3_device = {
+	.name		= "i2c-sh_mobile",
+	.id		= 3,
+	.resource	= i2c3_resources,
+	.num_resources	= ARRAY_SIZE(i2c3_resources),
+};
+
+static struct platform_device i2c4_device = {
+	.name		= "i2c-sh_mobile",
+	.id		= 4,
+	.resource	= i2c4_resources,
+	.num_resources	= ARRAY_SIZE(i2c4_resources),
+};
+
+static struct platform_device *sh73a0_early_devices[] __initdata = {
+	&scif0_device,
+	&scif1_device,
+	&scif2_device,
+	&scif3_device,
+	&scif4_device,
+	&scif5_device,
+	&scif6_device,
+	&scif7_device,
+	&scif8_device,
+	&cmt10_device,
+	&tmu00_device,
+	&tmu01_device,
+};
+
+static struct platform_device *sh73a0_late_devices[] __initdata = {
+	&i2c0_device,
+	&i2c1_device,
+	&i2c2_device,
+	&i2c3_device,
+	&i2c4_device,
+};
+
+void __init sh73a0_add_standard_devices(void)
+{
+	platform_add_devices(sh73a0_early_devices,
+			    ARRAY_SIZE(sh73a0_early_devices));
+	platform_add_devices(sh73a0_late_devices,
+			    ARRAY_SIZE(sh73a0_late_devices));
+}
+
+void __init sh73a0_add_early_devices(void)
+{
+	early_platform_add_devices(sh73a0_early_devices,
+				   ARRAY_SIZE(sh73a0_early_devices));
+}
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-shmobile/smp-sh73a0.c linux-libre-2.6.38-gnu1/arch/arm/mach-shmobile/smp-sh73a0.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-shmobile/smp-sh73a0.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-shmobile/smp-sh73a0.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,97 @@
+/*
+ * SMP support for R-Mobile / SH-Mobile - sh73a0 portion
+ *
+ * Copyright (C) 2010  Magnus Damm
+ * Copyright (C) 2010  Takashi Yoshii
+ *
+ * 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/smp.h>
+#include <linux/spinlock.h>
+#include <linux/io.h>
+#include <mach/common.h>
+#include <asm/smp_scu.h>
+#include <asm/smp_twd.h>
+#include <asm/hardware/gic.h>
+
+#define WUPCR		0xe6151010
+#define SRESCR		0xe6151018
+#define PSTR		0xe6151040
+#define SBAR            0xe6180020
+#define APARMBAREA      0xe6f10020
+
+static void __iomem *scu_base_addr(void)
+{
+	return (void __iomem *)0xf0000000;
+}
+
+static DEFINE_SPINLOCK(scu_lock);
+static unsigned long tmp;
+
+static void modify_scu_cpu_psr(unsigned long set, unsigned long clr)
+{
+	void __iomem *scu_base = scu_base_addr();
+
+	spin_lock(&scu_lock);
+	tmp = __raw_readl(scu_base + 8);
+	tmp &= ~clr;
+	tmp |= set;
+	spin_unlock(&scu_lock);
+
+	/* disable cache coherency after releasing the lock */
+	__raw_writel(tmp, scu_base + 8);
+}
+
+unsigned int __init sh73a0_get_core_count(void)
+{
+	void __iomem *scu_base = scu_base_addr();
+
+	return scu_get_core_count(scu_base);
+}
+
+void __cpuinit sh73a0_secondary_init(unsigned int cpu)
+{
+	gic_secondary_init(0);
+}
+
+int __cpuinit sh73a0_boot_secondary(unsigned int cpu)
+{
+	/* enable cache coherency */
+	modify_scu_cpu_psr(0, 3 << (cpu * 8));
+
+	if (((__raw_readw(__io(PSTR)) >> (4 * cpu)) & 3) == 3)
+		__raw_writel(1 << cpu, __io(WUPCR));	/* wake up */
+	else
+		__raw_writel(1 << cpu, __io(SRESCR));	/* reset */
+
+	return 0;
+}
+
+void __init sh73a0_smp_prepare_cpus(void)
+{
+#ifdef CONFIG_HAVE_ARM_TWD
+	twd_base = (void __iomem *)0xf0000600;
+#endif
+
+	scu_enable(scu_base_addr());
+
+	/* Map the reset vector (in headsmp.S) */
+	__raw_writel(0, __io(APARMBAREA));      /* 4k */
+	__raw_writel(__pa(shmobile_secondary_vector), __io(SBAR));
+
+	/* enable cache coherency on CPU0 */
+	modify_scu_cpu_psr(0, 3 << (0 * 8));
+}
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-spear3xx/include/mach/spear320.h linux-libre-2.6.38-gnu1/arch/arm/mach-spear3xx/include/mach/spear320.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-spear3xx/include/mach/spear320.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-spear3xx/include/mach/spear320.h	2011-03-14 21:20:32.000000000 -0400
@@ -62,7 +62,7 @@
 #define SPEAR320_SMII1_BASE		0xAB000000
 #define SPEAR320_SMII1_SIZE		0x01000000
 
-#define SPEAR320_SOC_CONFIG_BASE	0xB4000000
+#define SPEAR320_SOC_CONFIG_BASE	0xB3000000
 #define SPEAR320_SOC_CONFIG_SIZE	0x00000070
 /* Interrupt registers offsets and masks */
 #define INT_STS_MASK_REG		0x04
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-spear3xx/spear300.c linux-libre-2.6.38-gnu1/arch/arm/mach-spear3xx/spear300.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-spear3xx/spear300.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-spear3xx/spear300.c	2011-03-14 21:20:32.000000000 -0400
@@ -371,7 +371,7 @@ struct pmx_driver pmx_driver = {
 };
 
 /* Add spear300 specific devices here */
-/* arm gpio1 device registeration */
+/* arm gpio1 device registration */
 static struct pl061_platform_data gpio1_plat_data = {
 	.gpio_base	= 8,
 	.irq_base	= SPEAR_GPIO1_INT_BASE,
@@ -451,7 +451,7 @@ void __init spear300_init(void)
 	/* call spear3xx family common init function */
 	spear3xx_init();
 
-	/* shared irq registeration */
+	/* shared irq registration */
 	shirq_ras1.regs.base =
 		ioremap(SPEAR300_TELECOM_BASE, SPEAR300_TELECOM_REG_SIZE);
 	if (shirq_ras1.regs.base) {
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-spear3xx/spear310.c linux-libre-2.6.38-gnu1/arch/arm/mach-spear3xx/spear310.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-spear3xx/spear310.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-spear3xx/spear310.c	2011-03-14 21:20:32.000000000 -0400
@@ -266,7 +266,7 @@ void __init spear310_init(void)
 	/* call spear3xx family common init function */
 	spear3xx_init();
 
-	/* shared irq registeration */
+	/* shared irq registration */
 	base = ioremap(SPEAR310_SOC_CONFIG_BASE, SPEAR310_SOC_CONFIG_SIZE);
 	if (base) {
 		/* shirq 1 */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-spear3xx/spear320.c linux-libre-2.6.38-gnu1/arch/arm/mach-spear3xx/spear320.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-spear3xx/spear320.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-spear3xx/spear320.c	2011-03-14 21:20:32.000000000 -0400
@@ -519,7 +519,7 @@ void __init spear320_init(void)
 	/* call spear3xx family common init function */
 	spear3xx_init();
 
-	/* shared irq registeration */
+	/* shared irq registration */
 	base = ioremap(SPEAR320_SOC_CONFIG_BASE, SPEAR320_SOC_CONFIG_SIZE);
 	if (base) {
 		/* shirq 1 */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-spear3xx/spear3xx.c linux-libre-2.6.38-gnu1/arch/arm/mach-spear3xx/spear3xx.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-spear3xx/spear3xx.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-spear3xx/spear3xx.c	2011-03-14 21:20:32.000000000 -0400
@@ -22,7 +22,7 @@
 #include <mach/spear.h>
 
 /* Add spear3xx machines common devices here */
-/* gpio device registeration */
+/* gpio device registration */
 static struct pl061_platform_data gpio_plat_data = {
 	.gpio_base	= 0,
 	.irq_base	= SPEAR_GPIO_INT_BASE,
@@ -41,7 +41,7 @@ struct amba_device gpio_device = {
 	.irq = {IRQ_BASIC_GPIO, NO_IRQ},
 };
 
-/* uart device registeration */
+/* uart device registration */
 struct amba_device uart_device = {
 	.dev = {
 		.init_name = "uart",
@@ -543,6 +543,6 @@ void spear_pmx_init(struct pmx_driver *p
 
 pmx_fail:
 	if (ret)
-		printk(KERN_ERR "padmux: registeration failed. err no: %d\n",
+		printk(KERN_ERR "padmux: registration failed. err no: %d\n",
 				ret);
 }
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-spear6xx/spear6xx.c linux-libre-2.6.38-gnu1/arch/arm/mach-spear6xx/spear6xx.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-spear6xx/spear6xx.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-spear6xx/spear6xx.c	2011-03-14 21:20:32.000000000 -0400
@@ -23,7 +23,7 @@
 #include <mach/spear.h>
 
 /* Add spear6xx machines common devices here */
-/* uart device registeration */
+/* uart device registration */
 struct amba_device uart_device[] = {
 	{
 		.dev = {
@@ -50,7 +50,7 @@ struct amba_device uart_device[] = {
 	}
 };
 
-/* gpio device registeration */
+/* gpio device registration */
 static struct pl061_platform_data gpio_plat_data[] = {
 	{
 		.gpio_base	= 0,
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-stmp378x/stmp378x.c linux-libre-2.6.38-gnu1/arch/arm/mach-stmp378x/stmp378x.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-stmp378x/stmp378x.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-stmp378x/stmp378x.c	2011-03-14 21:20:32.000000000 -0400
@@ -47,7 +47,7 @@
 /*
  * IRQ handling
  */
-static void stmp378x_ack_irq(unsigned int irq)
+static void stmp378x_ack_irq(struct irq_data *d)
 {
 	/* Tell ICOLL to release IRQ line */
 	__raw_writel(0, REGS_ICOLL_BASE + HW_ICOLL_VECTOR);
@@ -60,24 +60,24 @@ static void stmp378x_ack_irq(unsigned in
 	(void)__raw_readl(REGS_ICOLL_BASE + HW_ICOLL_STAT);
 }
 
-static void stmp378x_mask_irq(unsigned int irq)
+static void stmp378x_mask_irq(struct irq_data *d)
 {
 	/* IRQ disable */
 	stmp3xxx_clearl(BM_ICOLL_INTERRUPTn_ENABLE,
-			REGS_ICOLL_BASE + HW_ICOLL_INTERRUPTn + irq * 0x10);
+			REGS_ICOLL_BASE + HW_ICOLL_INTERRUPTn + d->irq * 0x10);
 }
 
-static void stmp378x_unmask_irq(unsigned int irq)
+static void stmp378x_unmask_irq(struct irq_data *d)
 {
 	/* IRQ enable */
 	stmp3xxx_setl(BM_ICOLL_INTERRUPTn_ENABLE,
-		      REGS_ICOLL_BASE + HW_ICOLL_INTERRUPTn + irq * 0x10);
+		      REGS_ICOLL_BASE + HW_ICOLL_INTERRUPTn + d->irq * 0x10);
 }
 
 static struct irq_chip stmp378x_chip = {
-	.ack	= stmp378x_ack_irq,
-	.mask	= stmp378x_mask_irq,
-	.unmask = stmp378x_unmask_irq,
+	.irq_ack	= stmp378x_ack_irq,
+	.irq_mask	= stmp378x_mask_irq,
+	.irq_unmask	= stmp378x_unmask_irq,
 };
 
 void __init stmp378x_init_irq(void)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-stmp37xx/stmp37xx.c linux-libre-2.6.38-gnu1/arch/arm/mach-stmp37xx/stmp37xx.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-stmp37xx/stmp37xx.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-stmp37xx/stmp37xx.c	2011-03-14 21:20:32.000000000 -0400
@@ -43,11 +43,11 @@
 /*
  * IRQ handling
  */
-static void stmp37xx_ack_irq(unsigned int irq)
+static void stmp37xx_ack_irq(struct irq_data *d)
 {
 	/* Disable IRQ */
-	stmp3xxx_clearl(0x04 << ((irq % 4) * 8),
-		REGS_ICOLL_BASE + HW_ICOLL_PRIORITYn + irq / 4 * 0x10);
+	stmp3xxx_clearl(0x04 << ((d->irq % 4) * 8),
+		REGS_ICOLL_BASE + HW_ICOLL_PRIORITYn + d->irq / 4 * 0x10);
 
 	/* ACK current interrupt */
 	__raw_writel(1, REGS_ICOLL_BASE + HW_ICOLL_LEVELACK);
@@ -56,24 +56,24 @@ static void stmp37xx_ack_irq(unsigned in
 	(void)__raw_readl(REGS_ICOLL_BASE + HW_ICOLL_STAT);
 }
 
-static void stmp37xx_mask_irq(unsigned int irq)
+static void stmp37xx_mask_irq(struct irq_data *d)
 {
 	/* IRQ disable */
-	stmp3xxx_clearl(0x04 << ((irq % 4) * 8),
-		REGS_ICOLL_BASE + HW_ICOLL_PRIORITYn + irq / 4 * 0x10);
+	stmp3xxx_clearl(0x04 << ((d->irq % 4) * 8),
+		REGS_ICOLL_BASE + HW_ICOLL_PRIORITYn + d->irq / 4 * 0x10);
 }
 
-static void stmp37xx_unmask_irq(unsigned int irq)
+static void stmp37xx_unmask_irq(struct irq_data *d)
 {
 	/* IRQ enable */
-	stmp3xxx_setl(0x04 << ((irq % 4) * 8),
-		REGS_ICOLL_BASE + HW_ICOLL_PRIORITYn + irq / 4 * 0x10);
+	stmp3xxx_setl(0x04 << ((d->irq % 4) * 8),
+		REGS_ICOLL_BASE + HW_ICOLL_PRIORITYn + d->irq / 4 * 0x10);
 }
 
 static struct irq_chip stmp37xx_chip = {
-	.ack	= stmp37xx_ack_irq,
-	.mask	= stmp37xx_mask_irq,
-	.unmask = stmp37xx_unmask_irq,
+	.irq_ack	= stmp37xx_ack_irq,
+	.irq_mask	= stmp37xx_mask_irq,
+	.irq_unmask	= stmp37xx_unmask_irq,
 };
 
 void __init stmp37xx_init_irq(void)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-tcc8k/clock.c linux-libre-2.6.38-gnu1/arch/arm/mach-tcc8k/clock.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-tcc8k/clock.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-tcc8k/clock.c	2011-03-14 21:20:32.000000000 -0400
@@ -12,8 +12,7 @@
 #include <linux/io.h>
 #include <linux/module.h>
 #include <linux/spinlock.h>
-
-#include <asm/clkdev.h>
+#include <linux/clkdev.h>
 
 #include <mach/clock.h>
 #include <mach/irqs.h>
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-tcc8k/irq.c linux-libre-2.6.38-gnu1/arch/arm/mach-tcc8k/irq.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-tcc8k/irq.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-tcc8k/irq.c	2011-03-14 21:20:32.000000000 -0400
@@ -18,65 +18,65 @@
 #include "common.h"
 
 /* Disable IRQ */
-static void tcc8000_mask_ack_irq0(unsigned int irq)
+static void tcc8000_mask_ack_irq0(struct irq_data *d)
 {
-	PIC0_IEN &= ~(1 << irq);
-	PIC0_CREQ |=  (1 << irq);
+	PIC0_IEN &= ~(1 << d->irq);
+	PIC0_CREQ |=  (1 << d->irq);
 }
 
-static void tcc8000_mask_ack_irq1(unsigned int irq)
+static void tcc8000_mask_ack_irq1(struct irq_data *d)
 {
-	PIC1_IEN &= ~(1 << (irq - 32));
-	PIC1_CREQ |= (1 << (irq - 32));
+	PIC1_IEN &= ~(1 << (d->irq - 32));
+	PIC1_CREQ |= (1 << (d->irq - 32));
 }
 
-static void tcc8000_mask_irq0(unsigned int irq)
+static void tcc8000_mask_irq0(struct irq_data *d)
 {
-	PIC0_IEN &= ~(1 << irq);
+	PIC0_IEN &= ~(1 << d->irq);
 }
 
-static void tcc8000_mask_irq1(unsigned int irq)
+static void tcc8000_mask_irq1(struct irq_data *d)
 {
-	PIC1_IEN &= ~(1 << (irq - 32));
+	PIC1_IEN &= ~(1 << (d->irq - 32));
 }
 
-static void tcc8000_ack_irq0(unsigned int irq)
+static void tcc8000_ack_irq0(struct irq_data *d)
 {
-	PIC0_CREQ |=  (1 << irq);
+	PIC0_CREQ |=  (1 << d->irq);
 }
 
-static void tcc8000_ack_irq1(unsigned int irq)
+static void tcc8000_ack_irq1(struct irq_data *d)
 {
-	PIC1_CREQ |= (1 << (irq - 32));
+	PIC1_CREQ |= (1 << (d->irq - 32));
 }
 
 /* Enable IRQ */
-static void tcc8000_unmask_irq0(unsigned int irq)
+static void tcc8000_unmask_irq0(struct irq_data *d)
 {
-	PIC0_IEN |= (1 << irq);
-	PIC0_INTOEN |= (1 << irq);
+	PIC0_IEN |= (1 << d->irq);
+	PIC0_INTOEN |= (1 << d->irq);
 }
 
-static void tcc8000_unmask_irq1(unsigned int irq)
+static void tcc8000_unmask_irq1(struct irq_data *d)
 {
-	PIC1_IEN |= (1 << (irq - 32));
-	PIC1_INTOEN |= (1 << (irq - 32));
+	PIC1_IEN |= (1 << (d->irq - 32));
+	PIC1_INTOEN |= (1 << (d->irq - 32));
 }
 
 static struct irq_chip tcc8000_irq_chip0 = {
 	.name		= "tcc_irq0",
-	.mask		= tcc8000_mask_irq0,
-	.ack		= tcc8000_ack_irq0,
-	.mask_ack	= tcc8000_mask_ack_irq0,
-	.unmask		= tcc8000_unmask_irq0,
+	.irq_mask	= tcc8000_mask_irq0,
+	.irq_ack	= tcc8000_ack_irq0,
+	.irq_mask_ack	= tcc8000_mask_ack_irq0,
+	.irq_unmask	= tcc8000_unmask_irq0,
 };
 
 static struct irq_chip tcc8000_irq_chip1 = {
 	.name		= "tcc_irq1",
-	.mask		= tcc8000_mask_irq1,
-	.ack		= tcc8000_ack_irq1,
-	.mask_ack	= tcc8000_mask_ack_irq1,
-	.unmask		= tcc8000_unmask_irq1,
+	.irq_mask	= tcc8000_mask_irq1,
+	.irq_ack	= tcc8000_ack_irq1,
+	.irq_mask_ack	= tcc8000_mask_ack_irq1,
+	.irq_unmask	= tcc8000_unmask_irq1,
 };
 
 void __init tcc8k_init_irq(void)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-tcc8k/time.c linux-libre-2.6.38-gnu1/arch/arm/mach-tcc8k/time.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-tcc8k/time.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-tcc8k/time.c	2011-03-14 21:20:32.000000000 -0400
@@ -35,7 +35,6 @@ static struct clocksource clocksource_tc
 	.rating		= 200,
 	.read		= tcc_get_cycles,
 	.mask		= CLOCKSOURCE_MASK(32),
-	.shift		= 28,
 	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
@@ -103,9 +102,7 @@ static int __init tcc_clockevent_init(st
 {
 	unsigned int c = clk_get_rate(clock);
 
-	clocksource_tcc.mult = clocksource_hz2mult(c,
-					clocksource_tcc.shift);
-	clocksource_register(&clocksource_tcc);
+	clocksource_register_hz(&clocksource_tcc, c);
 
 	clockevent_tcc.mult = div_sc(c, NSEC_PER_SEC,
 					clockevent_tcc.shift);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-tegra/clock.c linux-libre-2.6.38-gnu1/arch/arm/mach-tegra/clock.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-tegra/clock.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-tegra/clock.c	2011-03-14 21:20:32.000000000 -0400
@@ -25,7 +25,7 @@
 #include <linux/slab.h>
 #include <linux/seq_file.h>
 #include <linux/regulator/consumer.h>
-#include <asm/clkdev.h>
+#include <linux/clkdev.h>
 
 #include "clock.h"
 #include "board.h"
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-tegra/clock.h linux-libre-2.6.38-gnu1/arch/arm/mach-tegra/clock.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-tegra/clock.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-tegra/clock.h	2011-03-14 21:20:32.000000000 -0400
@@ -21,7 +21,7 @@
 #define __MACH_TEGRA_CLOCK_H
 
 #include <linux/list.h>
-#include <asm/clkdev.h>
+#include <linux/clkdev.h>
 
 #define DIV_BUS			(1 << 0)
 #define DIV_U71			(1 << 1)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-tegra/gpio.c linux-libre-2.6.38-gnu1/arch/arm/mach-tegra/gpio.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-tegra/gpio.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-tegra/gpio.c	2011-03-14 21:20:32.000000000 -0400
@@ -142,31 +142,31 @@ static struct gpio_chip tegra_gpio_chip
 	.ngpio			= TEGRA_NR_GPIOS,
 };
 
-static void tegra_gpio_irq_ack(unsigned int irq)
+static void tegra_gpio_irq_ack(struct irq_data *d)
 {
-	int gpio = irq - INT_GPIO_BASE;
+	int gpio = d->irq - INT_GPIO_BASE;
 
 	__raw_writel(1 << GPIO_BIT(gpio), GPIO_INT_CLR(gpio));
 }
 
-static void tegra_gpio_irq_mask(unsigned int irq)
+static void tegra_gpio_irq_mask(struct irq_data *d)
 {
-	int gpio = irq - INT_GPIO_BASE;
+	int gpio = d->irq - INT_GPIO_BASE;
 
 	tegra_gpio_mask_write(GPIO_MSK_INT_ENB(gpio), gpio, 0);
 }
 
-static void tegra_gpio_irq_unmask(unsigned int irq)
+static void tegra_gpio_irq_unmask(struct irq_data *d)
 {
-	int gpio = irq - INT_GPIO_BASE;
+	int gpio = d->irq - INT_GPIO_BASE;
 
 	tegra_gpio_mask_write(GPIO_MSK_INT_ENB(gpio), gpio, 1);
 }
 
-static int tegra_gpio_irq_set_type(unsigned int irq, unsigned int type)
+static int tegra_gpio_irq_set_type(struct irq_data *d, unsigned int type)
 {
-	int gpio = irq - INT_GPIO_BASE;
-	struct tegra_gpio_bank *bank = get_irq_chip_data(irq);
+	int gpio = d->irq - INT_GPIO_BASE;
+	struct tegra_gpio_bank *bank = irq_data_get_irq_chip_data(d);
 	int port = GPIO_PORT(gpio);
 	int lvl_type;
 	int val;
@@ -207,9 +207,9 @@ static int tegra_gpio_irq_set_type(unsig
 	spin_unlock_irqrestore(&bank->lvl_lock[port], flags);
 
 	if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
-		__set_irq_handler_unlocked(irq, handle_level_irq);
+		__set_irq_handler_unlocked(d->irq, handle_level_irq);
 	else if (type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
-		__set_irq_handler_unlocked(irq, handle_edge_irq);
+		__set_irq_handler_unlocked(d->irq, handle_edge_irq);
 
 	return 0;
 }
@@ -221,7 +221,7 @@ static void tegra_gpio_irq_handler(unsig
 	int pin;
 	int unmasked = 0;
 
-	desc->chip->ack(irq);
+	desc->irq_data.chip->irq_ack(&desc->irq_data);
 
 	bank = get_irq_data(irq);
 
@@ -240,7 +240,7 @@ static void tegra_gpio_irq_handler(unsig
 			 */
 			if (lvl & (0x100 << pin)) {
 				unmasked = 1;
-				desc->chip->unmask(irq);
+				desc->irq_data.chip->irq_unmask(&desc->irq_data);
 			}
 
 			generic_handle_irq(gpio_to_irq(gpio + pin));
@@ -248,7 +248,7 @@ static void tegra_gpio_irq_handler(unsig
 	}
 
 	if (!unmasked)
-		desc->chip->unmask(irq);
+		desc->irq_data.chip->irq_unmask(&desc->irq_data);
 
 }
 
@@ -316,21 +316,21 @@ void tegra_gpio_suspend(void)
 	local_irq_restore(flags);
 }
 
-static int tegra_gpio_wake_enable(unsigned int irq, unsigned int enable)
+static int tegra_gpio_wake_enable(struct irq_data *d, unsigned int enable)
 {
-	struct tegra_gpio_bank *bank = get_irq_chip_data(irq);
+	struct tegra_gpio_bank *bank = irq_data_get_irq_chip_data(d);
 	return set_irq_wake(bank->irq, enable);
 }
 #endif
 
 static struct irq_chip tegra_gpio_irq_chip = {
 	.name		= "GPIO",
-	.ack		= tegra_gpio_irq_ack,
-	.mask		= tegra_gpio_irq_mask,
-	.unmask		= tegra_gpio_irq_unmask,
-	.set_type	= tegra_gpio_irq_set_type,
+	.irq_ack	= tegra_gpio_irq_ack,
+	.irq_mask	= tegra_gpio_irq_mask,
+	.irq_unmask	= tegra_gpio_irq_unmask,
+	.irq_set_type	= tegra_gpio_irq_set_type,
 #ifdef CONFIG_PM
-	.set_wake	= tegra_gpio_wake_enable,
+	.irq_set_wake	= tegra_gpio_wake_enable,
 #endif
 };
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-tegra/hotplug.c linux-libre-2.6.38-gnu1/arch/arm/mach-tegra/hotplug.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-tegra/hotplug.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-tegra/hotplug.c	2011-03-14 21:20:32.000000000 -0400
@@ -11,12 +11,9 @@
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/smp.h>
-#include <linux/completion.h>
 
 #include <asm/cacheflush.h>
 
-static DECLARE_COMPLETION(cpu_killed);
-
 static inline void cpu_enter_lowpower(void)
 {
 	unsigned int v;
@@ -32,10 +29,10 @@ static inline void cpu_enter_lowpower(vo
 	"	bic	%0, %0, #0x20\n"
 	"	mcr	p15, 0, %0, c1, c0, 1\n"
 	"	mrc	p15, 0, %0, c1, c0, 0\n"
-	"	bic	%0, %0, #0x04\n"
+	"	bic	%0, %0, %2\n"
 	"	mcr	p15, 0, %0, c1, c0, 0\n"
 	  : "=&r" (v)
-	  : "r" (0)
+	  : "r" (0), "Ir" (CR_C)
 	  : "cc");
 }
 
@@ -45,17 +42,17 @@ static inline void cpu_leave_lowpower(vo
 
 	asm volatile(
 	"mrc	p15, 0, %0, c1, c0, 0\n"
-	"	orr	%0, %0, #0x04\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, #0x20\n"
 	"	mcr	p15, 0, %0, c1, c0, 1\n"
 	  : "=&r" (v)
-	  :
+	  : "Ir" (CR_C)
 	  : "cc");
 }
 
-static inline void platform_do_lowpower(unsigned int cpu)
+static inline void platform_do_lowpower(unsigned int cpu, int *spurious)
 {
 	/*
 	 * there is no power-control hardware on this platform, so all
@@ -79,22 +76,19 @@ static inline void platform_do_lowpower(
 		/*}*/
 
 		/*
-		 * getting here, means that we have come out of WFI without
+		 * Getting here, means that we have come out of WFI without
 		 * having been woken up - this shouldn't happen
 		 *
-		 * The trouble is, letting people know about this is not really
-		 * possible, since we are currently running incoherently, and
-		 * therefore cannot safely call printk() or anything else
+		 * Just note it happening - when we're woken, we can report
+		 * its occurrence.
 		 */
-#ifdef DEBUG
-		printk(KERN_WARN "CPU%u: spurious wakeup call\n", cpu);
-#endif
+		(*spurious)++;
 	}
 }
 
 int platform_cpu_kill(unsigned int cpu)
 {
-	return wait_for_completion_timeout(&cpu_killed, 5000);
+	return 1;
 }
 
 /*
@@ -104,30 +98,22 @@ int platform_cpu_kill(unsigned int cpu)
  */
 void platform_cpu_die(unsigned int cpu)
 {
-#ifdef DEBUG
-	unsigned int this_cpu = hard_smp_processor_id();
-
-	if (cpu != this_cpu) {
-		printk(KERN_CRIT "Eek! platform_cpu_die running on %u, should be %u\n",
-			   this_cpu, cpu);
-		BUG();
-	}
-#endif
-
-	printk(KERN_NOTICE "CPU%u: shutdown\n", cpu);
-	complete(&cpu_killed);
+	int spurious = 0;
 
 	/*
 	 * we're ready for shutdown now, so do it
 	 */
 	cpu_enter_lowpower();
-	platform_do_lowpower(cpu);
+	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)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-tegra/include/mach/clkdev.h linux-libre-2.6.38-gnu1/arch/arm/mach-tegra/include/mach/clkdev.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-tegra/include/mach/clkdev.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-tegra/include/mach/clkdev.h	2011-03-14 21:20:32.000000000 -0400
@@ -20,6 +20,8 @@
 #ifndef __MACH_CLKDEV_H
 #define __MACH_CLKDEV_H
 
+struct clk;
+
 static inline int __clk_get(struct clk *clk)
 {
 	return 1;
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-tegra/include/mach/clk.h linux-libre-2.6.38-gnu1/arch/arm/mach-tegra/include/mach/clk.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-tegra/include/mach/clk.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-tegra/include/mach/clk.h	2011-03-14 21:20:32.000000000 -0400
@@ -20,6 +20,8 @@
 #ifndef __MACH_CLK_H
 #define __MACH_CLK_H
 
+struct clk;
+
 void tegra_periph_reset_deassert(struct clk *c);
 void tegra_periph_reset_assert(struct clk *c);
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-tegra/include/mach/entry-macro.S linux-libre-2.6.38-gnu1/arch/arm/mach-tegra/include/mach/entry-macro.S
--- linux-libre-2.6.37-gnu1/arch/arm/mach-tegra/include/mach/entry-macro.S	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-tegra/include/mach/entry-macro.S	2011-03-14 21:20:32.000000000 -0400
@@ -16,8 +16,8 @@
 #include <mach/io.h>
 
 #if defined(CONFIG_ARM_GIC)
-
-#include <asm/hardware/gic.h>
+#define HAVE_GET_IRQNR_PREAMBLE
+#include <asm/hardware/entry-macro-gic.S>
 
 	/* Uses the GIC interrupt controller built into the cpu */
 #define ICTRL_BASE (IO_CPU_VIRT + 0x100)
@@ -32,68 +32,6 @@
 
 	.macro  arch_ret_to_user, tmp1, tmp2
 	.endm
-
-	/*
-	 * The interrupt numbering scheme is defined in the
-	 * interrupt controller spec.  To wit:
-	 *
-	 * Interrupts 0-15 are IPI
-	 * 16-28 are reserved
-	 * 29-31 are local.  We allow 30 to be used for the watchdog.
-	 * 32-1020 are global
-	 * 1021-1022 are reserved
-	 * 1023 is "spurious" (no interrupt)
-	 *
-	 * For now, we ignore all local interrupts so only return an interrupt
-	 * if it's between 30 and 1020.  The test_for_ipi routine below will
-	 * pick up on IPIs.
-	 *
-	 * A simple read from the controller will tell us the number of the
-	 * highest priority enabled interrupt.  We then just need to check
-	 * whether it is in the valid range for an IRQ (30-1020 inclusive).
-	 */
-
-	.macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
-
-	/* bits 12-10 = src CPU, 9-0 = int # */
-	ldr     \irqstat, [\base, #GIC_CPU_INTACK]
-
-	ldr		\tmp, =1021
-
-	bic     \irqnr, \irqstat, #0x1c00
-
-	cmp     \irqnr, #29
-	cmpcc	\irqnr, \irqnr
-	cmpne	\irqnr, \tmp
-	cmpcs	\irqnr, \irqnr
-
-	.endm
-
-	/* We assume that irqstat (the raw value of the IRQ acknowledge
-	 * register) is preserved from the macro above.
-	 * If there is an IPI, we immediately signal end of interrupt on the
-	 * controller, since this requires the original irqstat value which
-	 * we won't easily be able to recreate later.
-	 */
-
-	.macro test_for_ipi, irqnr, irqstat, base, tmp
-	bic	\irqnr, \irqstat, #0x1c00
-	cmp	\irqnr, #16
-	strcc	\irqstat, [\base, #GIC_CPU_EOI]
-	cmpcs	\irqnr, \irqnr
-	.endm
-
-	/* As above, this assumes that irqstat and base are preserved.. */
-
-	.macro test_for_ltirq, irqnr, irqstat, base, tmp
-	bic	\irqnr, \irqstat, #0x1c00
-	mov 	\tmp, #0
-	cmp	\irqnr, #29
-	moveq	\tmp, #1
-	streq	\irqstat, [\base, #GIC_CPU_EOI]
-	cmp	\tmp, #0
-	.endm
-
 #else
 	/* legacy interrupt controller for AP16 */
 	.macro	disable_fiq
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-tegra/include/mach/io.h linux-libre-2.6.38-gnu1/arch/arm/mach-tegra/include/mach/io.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-tegra/include/mach/io.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-tegra/include/mach/io.h	2011-03-14 21:20:32.000000000 -0400
@@ -65,8 +65,8 @@
 
 #ifndef __ASSEMBLER__
 
-#define __arch_ioremap(p, s, t)	tegra_ioremap(p, s, t)
-#define __arch_iounmap(v)	tegra_iounmap(v)
+#define __arch_ioremap		tegra_ioremap
+#define __arch_iounmap		tegra_iounmap
 
 void __iomem *tegra_ioremap(unsigned long phys, size_t size, unsigned int type);
 void tegra_iounmap(volatile void __iomem *addr);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-tegra/include/mach/kbc.h linux-libre-2.6.38-gnu1/arch/arm/mach-tegra/include/mach/kbc.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-tegra/include/mach/kbc.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-tegra/include/mach/kbc.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,62 @@
+/*
+ * Platform definitions for tegra-kbc keyboard input driver
+ *
+ * Copyright (c) 2010-2011, NVIDIA 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.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#ifndef ASMARM_ARCH_TEGRA_KBC_H
+#define ASMARM_ARCH_TEGRA_KBC_H
+
+#include <linux/types.h>
+#include <linux/input/matrix_keypad.h>
+
+#ifdef CONFIG_ARCH_TEGRA_2x_SOC
+#define KBC_MAX_GPIO	24
+#define KBC_MAX_KPENT	8
+#else
+#define KBC_MAX_GPIO	20
+#define KBC_MAX_KPENT	7
+#endif
+
+#define KBC_MAX_ROW	16
+#define KBC_MAX_COL	8
+#define KBC_MAX_KEY	(KBC_MAX_ROW * KBC_MAX_COL)
+
+struct tegra_kbc_pin_cfg {
+	bool is_row;
+	unsigned char num;
+};
+
+struct tegra_kbc_wake_key {
+	u8 row:4;
+	u8 col:4;
+};
+
+struct tegra_kbc_platform_data {
+	unsigned int debounce_cnt;
+	unsigned int repeat_cnt;
+
+	unsigned int wake_cnt; /* 0:wake on any key >1:wake on wake_cfg */
+	const struct tegra_kbc_wake_key *wake_cfg;
+
+	struct tegra_kbc_pin_cfg pin_cfg[KBC_MAX_GPIO];
+	const struct matrix_keymap_data *keymap_data;
+
+	bool wakeup;
+	bool use_fn_map;
+};
+#endif
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-tegra/include/mach/sdhci.h linux-libre-2.6.38-gnu1/arch/arm/mach-tegra/include/mach/sdhci.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-tegra/include/mach/sdhci.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-tegra/include/mach/sdhci.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,29 @@
+/*
+ * include/asm-arm/arch-tegra/include/mach/sdhci.h
+ *
+ * Copyright (C) 2009 Palm, Inc.
+ * Author: Yvonne Yip <y@palm.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_ARM_ARCH_TEGRA_SDHCI_H
+#define __ASM_ARM_ARCH_TEGRA_SDHCI_H
+
+#include <linux/mmc/host.h>
+
+struct tegra_sdhci_platform_data {
+	int cd_gpio;
+	int wp_gpio;
+	int power_gpio;
+	int is_8bit;
+};
+
+#endif
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-tegra/include/mach/smp.h linux-libre-2.6.38-gnu1/arch/arm/mach-tegra/include/mach/smp.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-tegra/include/mach/smp.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-tegra/include/mach/smp.h	2011-03-14 21:20:32.000000000 -0400
@@ -2,21 +2,13 @@
 #define ASMARM_ARCH_SMP_H
 
 #include <asm/hardware/gic.h>
-#include <asm/smp_mpidr.h>
 
 /*
  * We use IRQ1 as the IPI
  */
-static inline void smp_cross_call(const struct cpumask *mask)
-{
-	gic_raise_softirq(mask, 1);
-}
-
-/*
- * Do nothing on MPcore.
- */
-static inline void smp_cross_call_done(cpumask_t callmap)
+static inline void smp_cross_call(const struct cpumask *mask, int ipi)
 {
+	gic_raise_softirq(mask, ipi);
 }
 
 #endif
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-tegra/irq.c linux-libre-2.6.38-gnu1/arch/arm/mach-tegra/irq.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-tegra/irq.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-tegra/irq.c	2011-03-14 21:20:32.000000000 -0400
@@ -46,30 +46,30 @@
 #define ICTLR_COP_IER_CLR	0x38
 #define ICTLR_COP_IEP_CLASS	0x3c
 
-static void (*gic_mask_irq)(unsigned int irq);
-static void (*gic_unmask_irq)(unsigned int irq);
+static void (*tegra_gic_mask_irq)(struct irq_data *d);
+static void (*tegra_gic_unmask_irq)(struct irq_data *d);
 
-#define irq_to_ictlr(irq) (((irq)-32) >> 5)
+#define irq_to_ictlr(irq) (((irq) - 32) >> 5)
 static void __iomem *tegra_ictlr_base = IO_ADDRESS(TEGRA_PRIMARY_ICTLR_BASE);
-#define ictlr_to_virt(ictlr) (tegra_ictlr_base + (ictlr)*0x100)
+#define ictlr_to_virt(ictlr) (tegra_ictlr_base + (ictlr) * 0x100)
 
-static void tegra_mask(unsigned int irq)
+static void tegra_mask(struct irq_data *d)
 {
-	void __iomem *addr = ictlr_to_virt(irq_to_ictlr(irq));
-	gic_mask_irq(irq);
-	writel(1<<(irq&31), addr+ICTLR_CPU_IER_CLR);
+	void __iomem *addr = ictlr_to_virt(irq_to_ictlr(d->irq));
+	tegra_gic_mask_irq(d);
+	writel(1 << (d->irq & 31), addr+ICTLR_CPU_IER_CLR);
 }
 
-static void tegra_unmask(unsigned int irq)
+static void tegra_unmask(struct irq_data *d)
 {
-	void __iomem *addr = ictlr_to_virt(irq_to_ictlr(irq));
-	gic_unmask_irq(irq);
-	writel(1<<(irq&31), addr+ICTLR_CPU_IER_SET);
+	void __iomem *addr = ictlr_to_virt(irq_to_ictlr(d->irq));
+	tegra_gic_unmask_irq(d);
+	writel(1<<(d->irq&31), addr+ICTLR_CPU_IER_SET);
 }
 
 #ifdef CONFIG_PM
 
-static int tegra_set_wake(unsigned int irq, unsigned int on)
+static int tegra_set_wake(struct irq_data *d, unsigned int on)
 {
 	return 0;
 }
@@ -77,10 +77,10 @@ static int tegra_set_wake(unsigned int i
 
 static struct irq_chip tegra_irq = {
 	.name		= "PPI",
-	.mask		= tegra_mask,
-	.unmask		= tegra_unmask,
+	.irq_mask	= tegra_mask,
+	.irq_unmask	= tegra_unmask,
 #ifdef CONFIG_PM
-	.set_wake	= tegra_set_wake,
+	.irq_set_wake	= tegra_set_wake,
 #endif
 };
 
@@ -94,15 +94,15 @@ void __init tegra_init_irq(void)
 		writel(0, ictlr_to_virt(i) + ICTLR_CPU_IEP_CLASS);
 	}
 
-	gic_dist_init(0, IO_ADDRESS(TEGRA_ARM_INT_DIST_BASE), 29);
-	gic_cpu_init(0, IO_ADDRESS(TEGRA_ARM_PERIF_BASE + 0x100));
+	gic_init(0, 29, IO_ADDRESS(TEGRA_ARM_INT_DIST_BASE),
+		 IO_ADDRESS(TEGRA_ARM_PERIF_BASE + 0x100));
 
 	gic = get_irq_chip(29);
-	gic_unmask_irq = gic->unmask;
-	gic_mask_irq = gic->mask;
-	tegra_irq.ack = gic->ack;
+	tegra_gic_unmask_irq = gic->irq_unmask;
+	tegra_gic_mask_irq = gic->irq_mask;
+	tegra_irq.irq_ack = gic->irq_ack;
 #ifdef CONFIG_SMP
-	tegra_irq.set_affinity = gic->set_affinity;
+	tegra_irq.irq_set_affinity = gic->irq_set_affinity;
 #endif
 
 	for (i = INT_PRI_BASE; i < INT_GPIO_BASE; i++) {
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-tegra/platsmp.c linux-libre-2.6.38-gnu1/arch/arm/mach-tegra/platsmp.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-tegra/platsmp.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-tegra/platsmp.c	2011-03-14 21:20:32.000000000 -0400
@@ -22,7 +22,6 @@
 #include <asm/cacheflush.h>
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
-#include <asm/localtimer.h>
 #include <asm/smp_scu.h>
 
 #include <mach/iomap.h>
@@ -41,14 +40,12 @@ static void __iomem *scu_base = IO_ADDRE
 
 void __cpuinit platform_secondary_init(unsigned int cpu)
 {
-	trace_hardirqs_off();
-
 	/*
 	 * 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_cpu_init(0, IO_ADDRESS(TEGRA_ARM_PERIF_BASE) + 0x100);
+	gic_secondary_init(0);
 
 	/*
 	 * Synchronise with the boot thread.
@@ -117,24 +114,20 @@ 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;
+	}
+
 	for (i = 0; i < ncores; i++)
 		cpu_set(i, cpu_possible_map);
 }
 
-void __init smp_prepare_cpus(unsigned int max_cpus)
+void __init platform_smp_prepare_cpus(unsigned int max_cpus)
 {
-	unsigned int ncores = scu_get_core_count(scu_base);
-	unsigned int cpu = smp_processor_id();
 	int i;
 
-	smp_store_cpu_info(cpu);
-
-	/*
-	 * are we trying to boot more cores than exist?
-	 */
-	if (max_cpus > ncores)
-		max_cpus = ncores;
-
 	/*
 	 * Initialise the present map, which describes the set of CPUs
 	 * actually populated at the present time.
@@ -142,15 +135,5 @@ void __init smp_prepare_cpus(unsigned in
 	for (i = 0; i < max_cpus; i++)
 		set_cpu_present(i, true);
 
-	/*
-	 * Initialise the SCU if there are more than one CPU and let
-	 * them know where to start. Note that, on modern versions of
-	 * MILO, the "poke" doesn't actually do anything until each
-	 * individual core is sent a soft interrupt to get it out of
-	 * WFI
-	 */
-	if (max_cpus > 1) {
-		percpu_timer_setup();
-		scu_enable(scu_base);
-	}
+	scu_enable(scu_base);
 }
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-tegra/tegra2_clocks.c linux-libre-2.6.38-gnu1/arch/arm/mach-tegra/tegra2_clocks.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-tegra/tegra2_clocks.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-tegra/tegra2_clocks.c	2011-03-14 21:20:32.000000000 -0400
@@ -24,8 +24,7 @@
 #include <linux/delay.h>
 #include <linux/io.h>
 #include <linux/hrtimer.h>
-
-#include <asm/clkdev.h>
+#include <linux/clkdev.h>
 
 #include <mach/iomap.h>
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-tegra/timer.c linux-libre-2.6.38-gnu1/arch/arm/mach-tegra/timer.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-tegra/timer.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-tegra/timer.c	2011-03-14 21:20:32.000000000 -0400
@@ -18,6 +18,7 @@
  */
 
 #include <linux/init.h>
+#include <linux/sched.h>
 #include <linux/time.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
@@ -25,10 +26,10 @@
 #include <linux/clocksource.h>
 #include <linux/clk.h>
 #include <linux/io.h>
-#include <linux/cnt32_to_63.h>
 
 #include <asm/mach/time.h>
 #include <asm/localtimer.h>
+#include <asm/sched_clock.h>
 
 #include <mach/iomap.h>
 #include <mach/irqs.h>
@@ -91,7 +92,7 @@ static void tegra_timer_set_mode(enum cl
 
 static cycle_t tegra_clocksource_read(struct clocksource *cs)
 {
-	return cnt32_to_63(timer_readl(TIMERUS_CNTR_1US));
+	return timer_readl(TIMERUS_CNTR_1US);
 }
 
 static struct clock_event_device tegra_clockevent = {
@@ -106,14 +107,29 @@ static struct clocksource tegra_clocksou
 	.name	= "timer_us",
 	.rating	= 300,
 	.read	= tegra_clocksource_read,
-	.mask	= 0x7FFFFFFFFFFFFFFFULL,
+	.mask	= CLOCKSOURCE_MASK(32),
 	.flags	= CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
-unsigned long long sched_clock(void)
+static DEFINE_CLOCK_DATA(cd);
+
+/*
+ * Constants generated by clocks_calc_mult_shift(m, s, 1MHz, NSEC_PER_SEC, 60).
+ * This gives a resolution of about 1us and a wrap period of about 1h11min.
+ */
+#define SC_MULT		4194304000u
+#define SC_SHIFT	22
+
+unsigned long long notrace sched_clock(void)
 {
-	return clocksource_cyc2ns(tegra_clocksource.read(&tegra_clocksource),
-		tegra_clocksource.mult, tegra_clocksource.shift);
+	u32 cyc = timer_readl(TIMERUS_CNTR_1US);
+	return cyc_to_fixed_sched_clock(&cd, cyc, (u32)~0, SC_MULT, SC_SHIFT);
+}
+
+static void notrace tegra_update_sched_clock(void)
+{
+	u32 cyc = timer_readl(TIMERUS_CNTR_1US);
+	update_sched_clock(&cd, cyc, (u32)~0);
 }
 
 static irqreturn_t tegra_timer_interrupt(int irq, void *dev_id)
@@ -158,6 +174,9 @@ static void __init tegra_init_timer(void
 		WARN(1, "Unknown clock rate");
 	}
 
+	init_fixed_sched_clock(&cd, tegra_update_sched_clock, 32,
+			       1000000, SC_MULT, SC_SHIFT);
+
 	if (clocksource_register_hz(&tegra_clocksource, 1000000)) {
 		printk(KERN_ERR "Failed to register clocksource\n");
 		BUG();
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-u300/clock.c linux-libre-2.6.38-gnu1/arch/arm/mach-u300/clock.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-u300/clock.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-u300/clock.c	2011-03-14 21:20:32.000000000 -0400
@@ -25,8 +25,8 @@
 #include <linux/timer.h>
 #include <linux/io.h>
 #include <linux/seq_file.h>
+#include <linux/clkdev.h>
 
-#include <asm/clkdev.h>
 #include <mach/hardware.h>
 #include <mach/syscon.h>
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-u300/include/mach/coh901318.h linux-libre-2.6.38-gnu1/arch/arm/mach-u300/include/mach/coh901318.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-u300/include/mach/coh901318.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-u300/include/mach/coh901318.h	2011-03-14 21:20:32.000000000 -0400
@@ -24,7 +24,7 @@
  * @src_addr: transfer source address
  * @dst_addr: transfer destination address
  * @link_addr:  physical address to next lli
- * @virt_link_addr: virtual addres of next lli (only used by pool_free)
+ * @virt_link_addr: virtual address of next lli (only used by pool_free)
  * @phy_this: physical address of current lli (only used by pool_free)
  */
 struct coh901318_lli {
@@ -90,7 +90,7 @@ struct powersave {
  * struct coh901318_platform - platform arch structure
  * @chans_slave: specifying dma slave channels
  * @chans_memcpy: specifying dma memcpy channels
- * @access_memory_state: requesting DMA memeory access (on / off)
+ * @access_memory_state: requesting DMA memory access (on / off)
  * @chan_conf: dma channel configurations
  * @max_channels: max number of dma chanenls
  */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-u300/Kconfig linux-libre-2.6.38-gnu1/arch/arm/mach-u300/Kconfig
--- linux-libre-2.6.37-gnu1/arch/arm/mach-u300/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-u300/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -64,7 +64,7 @@ config MACH_U300_DUAL_RAM
 	bool "Dual RAM"
 	help
 		Select this if you want support for Dual RAM phones.
-		This is two RAM memorys on different EMIFs.
+		This is two RAM memories on different EMIFs.
 endchoice
 
 config U300_DEBUG
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-u300/timer.c linux-libre-2.6.38-gnu1/arch/arm/mach-u300/timer.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-u300/timer.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-u300/timer.c	2011-03-14 21:20:32.000000000 -0400
@@ -9,6 +9,7 @@
  * Author: Linus Walleij <linus.walleij@stericsson.com>
  */
 #include <linux/interrupt.h>
+#include <linux/sched.h>
 #include <linux/time.h>
 #include <linux/timex.h>
 #include <linux/clockchips.h>
@@ -21,6 +22,7 @@
 #include <mach/hardware.h>
 
 /* Generic stuff */
+#include <asm/sched_clock.h>
 #include <asm/mach/map.h>
 #include <asm/mach/time.h>
 #include <asm/mach/irq.h>
@@ -352,12 +354,18 @@ static struct clocksource clocksource_u3
  * this wraps around for now, since it is just a relative time
  * stamp. (Inspired by OMAP implementation.)
  */
+static DEFINE_CLOCK_DATA(cd);
+
 unsigned long long notrace sched_clock(void)
 {
-	return clocksource_cyc2ns(clocksource_u300_1mhz.read(
-				  &clocksource_u300_1mhz),
-				  clocksource_u300_1mhz.mult,
-				  clocksource_u300_1mhz.shift);
+	u32 cyc = readl(U300_TIMER_APP_VBASE + U300_TIMER_APP_GPT2CC);
+	return cyc_to_sched_clock(&cd, cyc, (u32)~0);
+}
+
+static void notrace u300_update_sched_clock(void)
+{
+	u32 cyc = readl(U300_TIMER_APP_VBASE + U300_TIMER_APP_GPT2CC);
+	update_sched_clock(&cd, cyc, (u32)~0);
 }
 
 
@@ -375,6 +383,8 @@ static void __init u300_timer_init(void)
 	clk_enable(clk);
 	rate = clk_get_rate(clk);
 
+	init_sched_clock(&cd, u300_update_sched_clock, 32, rate);
+
 	/*
 	 * Disable the "OS" and "DD" timers - these are designed for Symbian!
 	 * Example usage in cnh1601578 cpu subsystem pd_timer_app.c
@@ -412,9 +422,7 @@ static void __init u300_timer_init(void)
 	writel(U300_TIMER_APP_EGPT2_TIMER_ENABLE,
 		U300_TIMER_APP_VBASE + U300_TIMER_APP_EGPT2);
 
-	clocksource_calc_mult_shift(&clocksource_u300_1mhz,
-				    rate, APPTIMER_MIN_RANGE);
-	if (clocksource_register(&clocksource_u300_1mhz))
+	if (clocksource_register_hz(&clocksource_u300_1mhz, rate))
 		printk(KERN_ERR "timer: failed to initialize clock "
 		       "source %s\n", clocksource_u300_1mhz.name);
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-ux500/board-mop500.c linux-libre-2.6.38-gnu1/arch/arm/mach-ux500/board-mop500.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-ux500/board-mop500.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-ux500/board-mop500.c	2011-03-14 21:20:32.000000000 -0400
@@ -13,27 +13,29 @@
 #include <linux/interrupt.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
+#include <linux/i2c.h>
 #include <linux/gpio.h>
 #include <linux/amba/bus.h>
 #include <linux/amba/pl022.h>
 #include <linux/spi/spi.h>
 #include <linux/mfd/ab8500.h>
-#include <linux/input/matrix_keypad.h>
+#include <linux/mfd/tc3589x.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 
 #include <plat/pincfg.h>
 #include <plat/i2c.h>
-#include <plat/ske.h>
 
 #include <mach/hardware.h>
 #include <mach/setup.h>
 #include <mach/devices.h>
 #include <mach/irqs.h>
 
+#include "devices-db8500.h"
 #include "pins-db8500.h"
 #include "board-mop500.h"
+#include "board-mop500-regulators.h"
 
 static pin_cfg_t mop500_pins[] = {
 	/* SSP0 */
@@ -69,33 +71,25 @@ static pin_cfg_t mop500_pins[] = {
 	GPIO166_KP_O2,
 	GPIO167_KP_O1,
 	GPIO168_KP_O0,
-};
 
-static void ab4500_spi_cs_control(u32 command)
-{
-	/* set the FRM signal, which is CS  - TODO */
-}
+	/* GPIO_EXP_INT */
+	GPIO217_GPIO,
 
-struct pl022_config_chip ab4500_chip_info = {
-	.com_mode = INTERRUPT_TRANSFER,
-	.iface = SSP_INTERFACE_MOTOROLA_SPI,
-	/* we can act as master only */
-	.hierarchy = SSP_MASTER,
-	.slave_tx_disable = 0,
-	.rx_lev_trig = SSP_RX_1_OR_MORE_ELEM,
-	.tx_lev_trig = SSP_TX_1_OR_MORE_EMPTY_LOC,
-	.cs_control = ab4500_spi_cs_control,
+	/* STMPE1601 IRQ */
+	GPIO218_GPIO    | PIN_INPUT_PULLUP,
 };
 
 static struct ab8500_platform_data ab8500_platdata = {
 	.irq_base	= MOP500_AB8500_IRQ_BASE,
+	.regulator	= ab8500_regulators,
+	.num_regulator	= ARRAY_SIZE(ab8500_regulators),
 };
 
 static struct resource ab8500_resources[] = {
 	[0] = {
-		.start = IRQ_AB8500,
-		.end = IRQ_AB8500,
-		.flags = IORESOURCE_IRQ
+		.start	= IRQ_DB8500_AB8500,
+		.end	= IRQ_DB8500_AB8500,
+		.flags	= IORESOURCE_IRQ
 	}
 };
 
@@ -109,19 +103,6 @@ struct platform_device ab8500_device = {
 	.resource = ab8500_resources,
 };
 
-static struct spi_board_info ab8500_spi_devices[] = {
-	{
-		.modalias = "ab8500-spi",
-		.controller_data = &ab4500_chip_info,
-		.platform_data = &ab8500_platdata,
-		.max_speed_hz = 12000000,
-		.bus_num = 0,
-		.chip_select = 0,
-		.mode = SPI_MODE_3,
-		.irq = IRQ_DB8500_AB8500,
-	},
-};
-
 static struct pl022_ssp_controller ssp0_platform_data = {
 	.bus_id = 0,
 	/* pl022 not yet supports dma */
@@ -132,6 +113,34 @@ static struct pl022_ssp_controller ssp0_
 	.num_chipselect = 5,
 };
 
+/*
+ * TC35892
+ */
+
+static void mop500_tc35892_init(struct tc3589x *tc3589x, unsigned int base)
+{
+	mop500_sdi_tc35892_init();
+}
+
+static struct tc3589x_gpio_platform_data mop500_tc35892_gpio_data = {
+	.gpio_base	= MOP500_EGPIO(0),
+	.setup		= mop500_tc35892_init,
+};
+
+static struct tc3589x_platform_data mop500_tc35892_data = {
+	.block		= TC3589x_BLOCK_GPIO,
+	.gpio		= &mop500_tc35892_gpio_data,
+	.irq_base	= MOP500_EGPIO_IRQ_BASE,
+};
+
+static struct i2c_board_info mop500_i2c0_devices[] = {
+	{
+		I2C_BOARD_INFO("tc3589x", 0x42),
+		.irq            = NOMADIK_GPIO_TO_IRQ(217),
+		.platform_data  = &mop500_tc35892_data,
+	},
+};
+
 #define U8500_I2C_CONTROLLER(id, _slsu, _tft, _rft, clk, _sm) \
 static struct nmk_i2c_controller u8500_i2c##id##_data = { \
 	/*				\
@@ -161,159 +170,49 @@ U8500_I2C_CONTROLLER(1, 0xe, 1, 1, 10000
 U8500_I2C_CONTROLLER(2,	0xe, 1, 1, 100000, I2C_FREQ_MODE_STANDARD);
 U8500_I2C_CONTROLLER(3,	0xe, 1, 1, 100000, I2C_FREQ_MODE_STANDARD);
 
-static struct amba_device *amba_devs[] __initdata = {
-	&ux500_uart0_device,
-	&ux500_uart1_device,
-	&ux500_uart2_device,
-	&u8500_ssp0_device,
-};
-
-static const unsigned int ux500_keymap[] = {
-	KEY(2, 5, KEY_END),
-	KEY(4, 1, KEY_POWER),
-	KEY(3, 5, KEY_VOLUMEDOWN),
-	KEY(1, 3, KEY_3),
-	KEY(5, 2, KEY_RIGHT),
-	KEY(5, 0, KEY_9),
-
-	KEY(0, 5, KEY_MENU),
-	KEY(7, 6, KEY_ENTER),
-	KEY(4, 5, KEY_0),
-	KEY(6, 7, KEY_2),
-	KEY(3, 4, KEY_UP),
-	KEY(3, 3, KEY_DOWN),
-
-	KEY(6, 4, KEY_SEND),
-	KEY(6, 2, KEY_BACK),
-	KEY(4, 2, KEY_VOLUMEUP),
-	KEY(5, 5, KEY_1),
-	KEY(4, 3, KEY_LEFT),
-	KEY(3, 2, KEY_7),
-};
-
-static const struct matrix_keymap_data ux500_keymap_data = {
-	.keymap         = ux500_keymap,
-	.keymap_size    = ARRAY_SIZE(ux500_keymap),
-};
-
-/*
- * Nomadik SKE keypad
- */
-#define ROW_PIN_I0      164
-#define ROW_PIN_I1      163
-#define ROW_PIN_I2      162
-#define ROW_PIN_I3      161
-#define ROW_PIN_I4      156
-#define ROW_PIN_I5      155
-#define ROW_PIN_I6      154
-#define ROW_PIN_I7      153
-#define COL_PIN_O0      168
-#define COL_PIN_O1      167
-#define COL_PIN_O2      166
-#define COL_PIN_O3      165
-#define COL_PIN_O4      160
-#define COL_PIN_O5      159
-#define COL_PIN_O6      158
-#define COL_PIN_O7      157
-
-#define SKE_KPD_MAX_ROWS        8
-#define SKE_KPD_MAX_COLS        8
+static void __init mop500_i2c_init(void)
+{
+	db8500_add_i2c0(&u8500_i2c0_data);
+	db8500_add_i2c1(&u8500_i2c1_data);
+	db8500_add_i2c2(&u8500_i2c2_data);
+	db8500_add_i2c3(&u8500_i2c3_data);
+}
 
-static int ske_kp_rows[] = {
-	ROW_PIN_I0, ROW_PIN_I1, ROW_PIN_I2, ROW_PIN_I3,
-	ROW_PIN_I4, ROW_PIN_I5, ROW_PIN_I6, ROW_PIN_I7,
+/* add any platform devices here - TODO */
+static struct platform_device *platform_devs[] __initdata = {
 };
 
-/*
- * ske_set_gpio_row: request and set gpio rows
- */
-static int ske_set_gpio_row(int gpio)
+static void __init mop500_spi_init(void)
 {
-	int ret;
-
-	ret = gpio_request(gpio, "ske-kp");
-	if (ret < 0) {
-		pr_err("ske_set_gpio_row: gpio request failed\n");
-		return ret;
-	}
-
-	ret = gpio_direction_output(gpio, 1);
-	if (ret < 0) {
-		pr_err("ske_set_gpio_row: gpio direction failed\n");
-		gpio_free(gpio);
-	}
-
-	return ret;
+	db8500_add_ssp0(&ssp0_platform_data);
 }
 
-/*
- * ske_kp_init - enable the gpio configuration
- */
-static int ske_kp_init(void)
+static void __init mop500_uart_init(void)
 {
-	int ret, i;
-
-	for (i = 0; i < SKE_KPD_MAX_ROWS; i++) {
-		ret = ske_set_gpio_row(ske_kp_rows[i]);
-		if (ret < 0) {
-			pr_err("ske_kp_init: failed init\n");
-			return ret;
-		}
-	}
-
-	return 0;
+	db8500_add_uart0();
+	db8500_add_uart1();
+	db8500_add_uart2();
 }
 
-static struct ske_keypad_platform_data ske_keypad_board = {
-	.init           = ske_kp_init,
-	.keymap_data    = &ux500_keymap_data,
-	.no_autorepeat  = true,
-	.krow           = SKE_KPD_MAX_ROWS,     /* 8x8 matrix */
-	.kcol           = SKE_KPD_MAX_COLS,
-	.debounce_ms    = 40,                   /* in millsecs */
-};
-
-
-
-/* add any platform devices here - TODO */
-static struct platform_device *platform_devs[] __initdata = {
-	&u8500_i2c0_device,
-	&ux500_i2c1_device,
-	&ux500_i2c2_device,
-	&ux500_i2c3_device,
-	&ux500_ske_keypad_device,
-};
-
 static void __init u8500_init_machine(void)
 {
-	int i;
-
 	u8500_init_devices();
 
 	nmk_config_pins(mop500_pins, ARRAY_SIZE(mop500_pins));
 
-	u8500_i2c0_device.dev.platform_data = &u8500_i2c0_data;
-	ux500_i2c1_device.dev.platform_data = &u8500_i2c1_data;
-	ux500_i2c2_device.dev.platform_data = &u8500_i2c2_data;
-	ux500_i2c3_device.dev.platform_data = &u8500_i2c3_data;
-	ux500_ske_keypad_device.dev.platform_data = &ske_keypad_board;
-
-	u8500_ssp0_device.dev.platform_data = &ssp0_platform_data;
-
-	/* Register the active AMBA devices on this board */
-	for (i = 0; i < ARRAY_SIZE(amba_devs); i++)
-		amba_device_register(amba_devs[i], &iomem_resource);
-
 	platform_add_devices(platform_devs, ARRAY_SIZE(platform_devs));
 
+	mop500_i2c_init();
 	mop500_sdi_init();
+	mop500_spi_init();
+	mop500_uart_init();
 
-	/* If HW is early drop (ED) or V1.0 then use SPI to access AB8500 */
-	if (cpu_is_u8500ed() || cpu_is_u8500v10())
-		spi_register_board_info(ab8500_spi_devices,
-			ARRAY_SIZE(ab8500_spi_devices));
-	else /* If HW is v.1.1 or later use I2C to access AB8500 */
-		platform_device_register(&ab8500_device);
+	mop500_keypad_init();
+
+	platform_device_register(&ab8500_device);
+
+	i2c_register_board_info(0, mop500_i2c0_devices,
+				ARRAY_SIZE(mop500_i2c0_devices));
 }
 
 MACHINE_START(U8500, "ST-Ericsson MOP500 platform")
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-ux500/board-mop500.h linux-libre-2.6.38-gnu1/arch/arm/mach-ux500/board-mop500.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-ux500/board-mop500.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-ux500/board-mop500.h	2011-03-14 21:20:32.000000000 -0400
@@ -7,6 +7,15 @@
 #ifndef __BOARD_MOP500_H
 #define __BOARD_MOP500_H
 
+#define MOP500_EGPIO(x)			(NOMADIK_NR_GPIO + (x))
+
+/* GPIOs on the TC35892 expander */
+#define GPIO_SDMMC_CD			MOP500_EGPIO(3)
+#define GPIO_SDMMC_EN			MOP500_EGPIO(17)
+#define GPIO_SDMMC_1V8_3V_SEL		MOP500_EGPIO(18)
+
 extern void mop500_sdi_init(void);
+extern void mop500_sdi_tc35892_init(void);
+extern void mop500_keypad_init(void);
 
 #endif
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-ux500/board-mop500-keypads.c linux-libre-2.6.38-gnu1/arch/arm/mach-ux500/board-mop500-keypads.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-ux500/board-mop500-keypads.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-ux500/board-mop500-keypads.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,229 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * License Terms: GNU General Public License v2
+ *
+ * Keypad layouts for various boards
+ */
+
+#include <linux/i2c.h>
+#include <linux/gpio.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/stmpe.h>
+#include <linux/mfd/tc3589x.h>
+#include <linux/input/matrix_keypad.h>
+
+#include <plat/pincfg.h>
+#include <plat/ske.h>
+
+#include <mach/devices.h>
+#include <mach/hardware.h>
+
+#include "devices-db8500.h"
+#include "board-mop500.h"
+
+/* STMPE/SKE keypad use this key layout */
+static const unsigned int mop500_keymap[] = {
+	KEY(2, 5, KEY_END),
+	KEY(4, 1, KEY_POWER),
+	KEY(3, 5, KEY_VOLUMEDOWN),
+	KEY(1, 3, KEY_3),
+	KEY(5, 2, KEY_RIGHT),
+	KEY(5, 0, KEY_9),
+
+	KEY(0, 5, KEY_MENU),
+	KEY(7, 6, KEY_ENTER),
+	KEY(4, 5, KEY_0),
+	KEY(6, 7, KEY_2),
+	KEY(3, 4, KEY_UP),
+	KEY(3, 3, KEY_DOWN),
+
+	KEY(6, 4, KEY_SEND),
+	KEY(6, 2, KEY_BACK),
+	KEY(4, 2, KEY_VOLUMEUP),
+	KEY(5, 5, KEY_1),
+	KEY(4, 3, KEY_LEFT),
+	KEY(3, 2, KEY_7),
+};
+
+static const struct matrix_keymap_data mop500_keymap_data = {
+	.keymap		= mop500_keymap,
+	.keymap_size    = ARRAY_SIZE(mop500_keymap),
+};
+
+/*
+ * Nomadik SKE keypad
+ */
+#define ROW_PIN_I0      164
+#define ROW_PIN_I1      163
+#define ROW_PIN_I2      162
+#define ROW_PIN_I3      161
+#define ROW_PIN_I4      156
+#define ROW_PIN_I5      155
+#define ROW_PIN_I6      154
+#define ROW_PIN_I7      153
+#define COL_PIN_O0      168
+#define COL_PIN_O1      167
+#define COL_PIN_O2      166
+#define COL_PIN_O3      165
+#define COL_PIN_O4      160
+#define COL_PIN_O5      159
+#define COL_PIN_O6      158
+#define COL_PIN_O7      157
+
+#define SKE_KPD_MAX_ROWS	8
+#define SKE_KPD_MAX_COLS	8
+
+static int ske_kp_rows[] = {
+	ROW_PIN_I0, ROW_PIN_I1, ROW_PIN_I2, ROW_PIN_I3,
+	ROW_PIN_I4, ROW_PIN_I5, ROW_PIN_I6, ROW_PIN_I7,
+};
+
+/*
+ * ske_set_gpio_row: request and set gpio rows
+ */
+static int ske_set_gpio_row(int gpio)
+{
+	int ret;
+
+	ret = gpio_request(gpio, "ske-kp");
+	if (ret < 0) {
+		pr_err("ske_set_gpio_row: gpio request failed\n");
+		return ret;
+	}
+
+	ret = gpio_direction_output(gpio, 1);
+	if (ret < 0) {
+		pr_err("ske_set_gpio_row: gpio direction failed\n");
+		gpio_free(gpio);
+	}
+
+	return ret;
+}
+
+/*
+ * ske_kp_init - enable the gpio configuration
+ */
+static int ske_kp_init(void)
+{
+	int ret, i;
+
+	for (i = 0; i < SKE_KPD_MAX_ROWS; i++) {
+		ret = ske_set_gpio_row(ske_kp_rows[i]);
+		if (ret < 0) {
+			pr_err("ske_kp_init: failed init\n");
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+static struct ske_keypad_platform_data ske_keypad_board = {
+	.init		= ske_kp_init,
+	.keymap_data    = &mop500_keymap_data,
+	.no_autorepeat  = true,
+	.krow		= SKE_KPD_MAX_ROWS,     /* 8x8 matrix */
+	.kcol		= SKE_KPD_MAX_COLS,
+	.debounce_ms    = 40,			/* in millisecs */
+};
+
+/*
+ * STMPE1601
+ */
+static struct stmpe_keypad_platform_data stmpe1601_keypad_data = {
+	.debounce_ms    = 64,
+	.scan_count     = 8,
+	.no_autorepeat  = true,
+	.keymap_data    = &mop500_keymap_data,
+};
+
+static struct stmpe_platform_data stmpe1601_data = {
+	.id             = 1,
+	.blocks         = STMPE_BLOCK_KEYPAD,
+	.irq_trigger    = IRQF_TRIGGER_FALLING,
+	.irq_base       = MOP500_STMPE1601_IRQ(0),
+	.keypad         = &stmpe1601_keypad_data,
+	.autosleep      = true,
+	.autosleep_timeout = 1024,
+};
+
+static struct i2c_board_info mop500_i2c0_devices_stuib[] = {
+	{
+		I2C_BOARD_INFO("stmpe1601", 0x40),
+		.irq = NOMADIK_GPIO_TO_IRQ(218),
+		.platform_data = &stmpe1601_data,
+		.flags = I2C_CLIENT_WAKE,
+	},
+};
+
+/*
+ * TC35893
+ */
+
+static const unsigned int uib_keymap[] = {
+	KEY(3, 1, KEY_END),
+	KEY(4, 1, KEY_POWER),
+	KEY(6, 4, KEY_VOLUMEDOWN),
+	KEY(4, 2, KEY_EMAIL),
+	KEY(3, 3, KEY_RIGHT),
+	KEY(2, 5, KEY_BACKSPACE),
+
+	KEY(6, 7, KEY_MENU),
+	KEY(5, 0, KEY_ENTER),
+	KEY(4, 3, KEY_0),
+	KEY(3, 4, KEY_DOT),
+	KEY(5, 2, KEY_UP),
+	KEY(3, 5, KEY_DOWN),
+
+	KEY(4, 5, KEY_SEND),
+	KEY(0, 5, KEY_BACK),
+	KEY(6, 2, KEY_VOLUMEUP),
+	KEY(1, 3, KEY_SPACE),
+	KEY(7, 6, KEY_LEFT),
+	KEY(5, 5, KEY_SEARCH),
+};
+
+static struct matrix_keymap_data uib_keymap_data = {
+	.keymap         = uib_keymap,
+	.keymap_size    = ARRAY_SIZE(uib_keymap),
+};
+
+static struct tc3589x_keypad_platform_data tc35893_data = {
+	.krow = TC_KPD_ROWS,
+	.kcol = TC_KPD_COLUMNS,
+	.debounce_period = TC_KPD_DEBOUNCE_PERIOD,
+	.settle_time = TC_KPD_SETTLE_TIME,
+	.irqtype = IRQF_TRIGGER_FALLING,
+	.enable_wakeup = true,
+	.keymap_data    = &uib_keymap_data,
+	.no_autorepeat  = true,
+};
+
+static struct tc3589x_platform_data tc3589x_keypad_data = {
+	.block = TC3589x_BLOCK_KEYPAD,
+	.keypad = &tc35893_data,
+	.irq_base = MOP500_EGPIO_IRQ_BASE,
+};
+
+static struct i2c_board_info mop500_i2c0_devices_uib[] = {
+	{
+		I2C_BOARD_INFO("tc3589x", 0x44),
+		.platform_data = &tc3589x_keypad_data,
+		.irq = NOMADIK_GPIO_TO_IRQ(218),
+		.flags = I2C_CLIENT_WAKE,
+	},
+};
+
+void mop500_keypad_init(void)
+{
+	db8500_add_ske_keypad(&ske_keypad_board);
+
+	i2c_register_board_info(0, mop500_i2c0_devices_stuib,
+			ARRAY_SIZE(mop500_i2c0_devices_stuib));
+
+	i2c_register_board_info(0, mop500_i2c0_devices_uib,
+			ARRAY_SIZE(mop500_i2c0_devices_uib));
+
+}
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-ux500/board-mop500-regulators.c linux-libre-2.6.38-gnu1/arch/arm/mach-ux500/board-mop500-regulators.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-ux500/board-mop500-regulators.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-ux500/board-mop500-regulators.c	2011-03-14 21:20:32.000000000 -0400
@@ -3,99 +3,94 @@
  *
  * License Terms: GNU General Public License v2
  *
- * Author: Sundar Iyer <sundar.iyer@stericsson.com>
+ * Authors: Sundar Iyer <sundar.iyer@stericsson.com>
+ *          Bengt Jonsson <bengt.g.jonsson@stericsson.com>
  *
  * MOP500 board specific initialization for regulators
  */
 #include <linux/kernel.h>
 #include <linux/regulator/machine.h>
+#include <linux/regulator/ab8500.h>
 
-/* supplies to the display/camera */
-static struct regulator_init_data ab8500_vaux1_regulator = {
-	.constraints = {
-		.name = "V-DISPLAY",
-		.min_uV = 2500000,
-		.max_uV = 2900000,
-		.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE|
-					REGULATOR_CHANGE_STATUS,
+/* AB8500 regulators */
+struct regulator_init_data ab8500_regulators[AB8500_NUM_REGULATORS] = {
+	/* supplies to the display/camera */
+	[AB8500_LDO_AUX1] = {
+		.constraints = {
+			.name = "V-DISPLAY",
+			.min_uV = 2500000,
+			.max_uV = 2900000,
+			.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+					  REGULATOR_CHANGE_STATUS,
+		},
 	},
-};
-
-/* supplies to the on-board eMMC */
-static struct regulator_init_data ab8500_vaux2_regulator = {
-	.constraints = {
-		.name = "V-eMMC1",
-		.min_uV = 1100000,
-		.max_uV = 3300000,
-		.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE|
-					REGULATOR_CHANGE_STATUS,
+	/* supplies to the on-board eMMC */
+	[AB8500_LDO_AUX2] = {
+		.constraints = {
+			.name = "V-eMMC1",
+			.min_uV = 1100000,
+			.max_uV = 3300000,
+			.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+					  REGULATOR_CHANGE_STATUS,
+		},
 	},
-};
-
-/* supply for VAUX3, supplies to SDcard slots */
-static struct regulator_init_data ab8500_vaux3_regulator = {
-	.constraints = {
-		.name = "V-MMC-SD",
-		.min_uV = 1100000,
-		.max_uV = 3300000,
-		.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE|
-					REGULATOR_CHANGE_STATUS,
+	/* supply for VAUX3, supplies to SDcard slots */
+	[AB8500_LDO_AUX3] = {
+		.constraints = {
+			.name = "V-MMC-SD",
+			.min_uV = 1100000,
+			.max_uV = 3300000,
+			.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+					  REGULATOR_CHANGE_STATUS,
+		},
 	},
-};
-
-/* supply for tvout, gpadc, TVOUT LDO */
-static struct regulator_init_data ab8500_vtvout_init = {
-	.constraints = {
-		.name = "V-TVOUT",
-		.valid_ops_mask = REGULATOR_CHANGE_STATUS,
+	/* supply for tvout, gpadc, TVOUT LDO */
+	[AB8500_LDO_TVOUT] = {
+		.constraints = {
+			.name = "V-TVOUT",
+			.valid_ops_mask = REGULATOR_CHANGE_STATUS,
+		},
 	},
-};
-
-/* supply for ab8500-vaudio, VAUDIO LDO */
-static struct regulator_init_data ab8500_vaudio_init = {
-	.constraints = {
-		.name = "V-AUD",
-		.valid_ops_mask = REGULATOR_CHANGE_STATUS,
+	/* supply for ab8500-vaudio, VAUDIO LDO */
+	[AB8500_LDO_AUDIO] = {
+		.constraints = {
+			.name = "V-AUD",
+			.valid_ops_mask = REGULATOR_CHANGE_STATUS,
+		},
 	},
-};
-
-/* supply for v-anamic1 VAMic1-LDO */
-static struct regulator_init_data ab8500_vamic1_init = {
-	.constraints = {
-		.name = "V-AMIC1",
-		.valid_ops_mask = REGULATOR_CHANGE_STATUS,
+	/* supply for v-anamic1 VAMic1-LDO */
+	[AB8500_LDO_ANAMIC1] = {
+		.constraints = {
+			.name = "V-AMIC1",
+			.valid_ops_mask = REGULATOR_CHANGE_STATUS,
+		},
 	},
-};
-
-/* supply for v-amic2, VAMIC2 LDO, reuse constants for AMIC1 */
-static struct regulator_init_data ab8500_vamic2_init = {
-	.constraints = {
-		.name = "V-AMIC2",
-		.valid_ops_mask = REGULATOR_CHANGE_STATUS,
+	/* supply for v-amic2, VAMIC2 LDO, reuse constants for AMIC1 */
+	[AB8500_LDO_ANAMIC2] = {
+		.constraints = {
+			.name = "V-AMIC2",
+			.valid_ops_mask = REGULATOR_CHANGE_STATUS,
+		},
 	},
-};
-
-/* supply for v-dmic, VDMIC LDO */
-static struct regulator_init_data ab8500_vdmic_init = {
-	.constraints = {
-		.name = "V-DMIC",
-		.valid_ops_mask = REGULATOR_CHANGE_STATUS,
+	/* supply for v-dmic, VDMIC LDO */
+	[AB8500_LDO_DMIC] = {
+		.constraints = {
+			.name = "V-DMIC",
+			.valid_ops_mask = REGULATOR_CHANGE_STATUS,
+		},
 	},
-};
-
-/* supply for v-intcore12, VINTCORE12 LDO */
-static struct regulator_init_data ab8500_vintcore_init = {
-	.constraints = {
-		.name = "V-INTCORE",
-		.valid_ops_mask = REGULATOR_CHANGE_STATUS,
+	/* supply for v-intcore12, VINTCORE12 LDO */
+	[AB8500_LDO_INTCORE] = {
+		.constraints = {
+			.name = "V-INTCORE",
+			.valid_ops_mask = REGULATOR_CHANGE_STATUS,
+		},
 	},
-};
-
-/* supply for U8500 CSI/DSI, VANA LDO */
-static struct regulator_init_data ab8500_vana_init = {
-	.constraints = {
-		.name = "V-CSI/DSI",
-		.valid_ops_mask = REGULATOR_CHANGE_STATUS,
+	/* supply for U8500 CSI/DSI, VANA LDO */
+	[AB8500_LDO_ANA] = {
+		.constraints = {
+			.name = "V-CSI/DSI",
+			.valid_ops_mask = REGULATOR_CHANGE_STATUS,
+		},
 	},
 };
-
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-ux500/board-mop500-regulators.h linux-libre-2.6.38-gnu1/arch/arm/mach-ux500/board-mop500-regulators.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-ux500/board-mop500-regulators.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-ux500/board-mop500-regulators.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * License Terms: GNU General Public License v2
+ *
+ * Author: Bengt Jonsson <bengt.g.jonsson@stericsson.com> for ST-Ericsson
+ *
+ * MOP500 board specific initialization for regulators
+ */
+
+#ifndef __BOARD_MOP500_REGULATORS_H
+#define __BOARD_MOP500_REGULATORS_H
+
+#include <linux/regulator/machine.h>
+#include <linux/regulator/ab8500.h>
+
+extern struct regulator_init_data ab8500_regulators[AB8500_NUM_REGULATORS];
+
+#endif
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-ux500/board-mop500-sdi.c linux-libre-2.6.38-gnu1/arch/arm/mach-ux500/board-mop500-sdi.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-ux500/board-mop500-sdi.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-ux500/board-mop500-sdi.c	2011-03-14 21:20:32.000000000 -0400
@@ -16,10 +16,24 @@
 #include <mach/devices.h>
 #include <mach/hardware.h>
 
+#include "devices-db8500.h"
 #include "pins-db8500.h"
 #include "board-mop500.h"
 
 static pin_cfg_t mop500_sdi_pins[] = {
+	/* SDI0 (MicroSD slot) */
+	GPIO18_MC0_CMDDIR,
+	GPIO19_MC0_DAT0DIR,
+	GPIO20_MC0_DAT2DIR,
+	GPIO21_MC0_DAT31DIR,
+	GPIO22_MC0_FBCLK,
+	GPIO23_MC0_CLK,
+	GPIO24_MC0_CMD,
+	GPIO25_MC0_DAT0,
+	GPIO26_MC0_DAT1,
+	GPIO27_MC0_DAT2,
+	GPIO28_MC0_DAT3,
+
 	/* SDI4 (on-board eMMC) */
 	GPIO197_MC4_DAT3,
 	GPIO198_MC4_DAT2,
@@ -50,6 +64,55 @@ static pin_cfg_t mop500_sdi2_pins[] = {
 };
 
 /*
+ * SDI 0 (MicroSD slot)
+ */
+
+/* MMCIPOWER bits */
+#define MCI_DATA2DIREN		(1 << 2)
+#define MCI_CMDDIREN		(1 << 3)
+#define MCI_DATA0DIREN		(1 << 4)
+#define MCI_DATA31DIREN		(1 << 5)
+#define MCI_FBCLKEN		(1 << 7)
+
+static u32 mop500_sdi0_vdd_handler(struct device *dev, unsigned int vdd,
+				   unsigned char power_mode)
+{
+	if (power_mode == MMC_POWER_UP)
+		gpio_set_value_cansleep(GPIO_SDMMC_EN, 1);
+	else if (power_mode == MMC_POWER_OFF)
+		gpio_set_value_cansleep(GPIO_SDMMC_EN, 0);
+
+	return MCI_FBCLKEN | MCI_CMDDIREN | MCI_DATA0DIREN |
+	       MCI_DATA2DIREN | MCI_DATA31DIREN;
+}
+
+static struct mmci_platform_data mop500_sdi0_data = {
+	.vdd_handler	= mop500_sdi0_vdd_handler,
+	.ocr_mask	= MMC_VDD_29_30,
+	.f_max		= 100000000,
+	.capabilities	= MMC_CAP_4_BIT_DATA,
+	.gpio_cd	= GPIO_SDMMC_CD,
+	.gpio_wp	= -1,
+};
+
+void mop500_sdi_tc35892_init(void)
+{
+	int ret;
+
+	ret = gpio_request(GPIO_SDMMC_EN, "SDMMC_EN");
+	if (!ret)
+		ret = gpio_request(GPIO_SDMMC_1V8_3V_SEL,
+				   "GPIO_SDMMC_1V8_3V_SEL");
+	if (ret)
+		return;
+
+	gpio_direction_output(GPIO_SDMMC_1V8_3V_SEL, 1);
+	gpio_direction_output(GPIO_SDMMC_EN, 0);
+
+	db8500_add_sdi0(&mop500_sdi0_data);
+}
+
+/*
  * SDI 2 (POP eMMC, not on DB8500ed)
  */
 
@@ -74,18 +137,24 @@ static struct mmci_platform_data mop500_
 	.gpio_wp	= -1,
 };
 
-void mop500_sdi_init(void)
+void __init mop500_sdi_init(void)
 {
 	nmk_config_pins(mop500_sdi_pins, ARRAY_SIZE(mop500_sdi_pins));
 
-	u8500_sdi2_device.dev.platform_data = &mop500_sdi2_data;
-	u8500_sdi4_device.dev.platform_data = &mop500_sdi4_data;
+	/*
+	 * sdi0 will finally be added when the TC35892 initializes and calls
+	 * mop500_sdi_tc35892_init() above.
+	 */
 
+	/* PoP:ed eMMC */
 	if (!cpu_is_u8500ed()) {
 		nmk_config_pins(mop500_sdi2_pins, ARRAY_SIZE(mop500_sdi2_pins));
-		amba_device_register(&u8500_sdi2_device, &iomem_resource);
+		/* POP eMMC on v1.0 has problems with high speed */
+		if (!cpu_is_u8500v10())
+			mop500_sdi2_data.capabilities |= MMC_CAP_MMC_HIGHSPEED;
+		db8500_add_sdi2(&mop500_sdi2_data);
 	}
 
 	/* On-board eMMC */
-	amba_device_register(&u8500_sdi4_device, &iomem_resource);
+	db8500_add_sdi4(&mop500_sdi4_data);
 }
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-ux500/board-u5500.c linux-libre-2.6.38-gnu1/arch/arm/mach-ux500/board-u5500.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-ux500/board-u5500.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-ux500/board-u5500.c	2011-03-14 21:20:32.000000000 -0400
@@ -9,6 +9,7 @@
 #include <linux/platform_device.h>
 #include <linux/amba/bus.h>
 #include <linux/gpio.h>
+#include <linux/irq.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
@@ -17,20 +18,24 @@
 #include <mach/devices.h>
 #include <mach/setup.h>
 
-static struct amba_device *amba_board_devs[] __initdata = {
-	&ux500_uart0_device,
-	&ux500_uart1_device,
-	&ux500_uart2_device,
-};
+#include "devices-db5500.h"
+
+static void __init u5500_uart_init(void)
+{
+	db5500_add_uart0();
+	db5500_add_uart1();
+	db5500_add_uart2();
+}
 
 static void __init u5500_init_machine(void)
 {
 	u5500_init_devices();
 
-	amba_add_devices(amba_board_devs, ARRAY_SIZE(amba_board_devs));
+	u5500_sdi_init();
+	u5500_uart_init();
 }
 
-MACHINE_START(U8500, "ST-Ericsson U5500 Platform")
+MACHINE_START(U5500, "ST-Ericsson U5500 Platform")
 	.boot_params	= 0x00000100,
 	.map_io		= u5500_map_io,
 	.init_irq	= ux500_init_irq,
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-ux500/board-u5500-sdi.c linux-libre-2.6.38-gnu1/arch/arm/mach-ux500/board-u5500-sdi.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-ux500/board-u5500-sdi.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-ux500/board-u5500-sdi.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * Author: Hanumath Prasad <ulf.hansson@stericsson.com>
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#include <linux/amba/mmci.h>
+#include <linux/mmc/host.h>
+#include <linux/gpio.h>
+
+#include <plat/pincfg.h>
+#include <mach/db5500-regs.h>
+#include <plat/ste_dma40.h>
+
+#include "pins-db5500.h"
+#include "devices-db5500.h"
+#include "ste-dma40-db5500.h"
+
+static pin_cfg_t u5500_sdi_pins[] = {
+	/* SDI0 (POP eMMC) */
+	GPIO5_MC0_DAT0		| PIN_DIR_INPUT | PIN_PULL_UP,
+	GPIO6_MC0_DAT1		| PIN_DIR_INPUT | PIN_PULL_UP,
+	GPIO7_MC0_DAT2		| PIN_DIR_INPUT | PIN_PULL_UP,
+	GPIO8_MC0_DAT3		| PIN_DIR_INPUT | PIN_PULL_UP,
+	GPIO9_MC0_DAT4		| PIN_DIR_INPUT | PIN_PULL_UP,
+	GPIO10_MC0_DAT5		| PIN_DIR_INPUT | PIN_PULL_UP,
+	GPIO11_MC0_DAT6		| PIN_DIR_INPUT | PIN_PULL_UP,
+	GPIO12_MC0_DAT7		| PIN_DIR_INPUT | PIN_PULL_UP,
+	GPIO13_MC0_CMD		| PIN_DIR_INPUT | PIN_PULL_UP,
+	GPIO14_MC0_CLK		| PIN_DIR_OUTPUT | PIN_VAL_LOW,
+};
+
+static struct mmci_platform_data u5500_sdi0_data = {
+	.ocr_mask	= MMC_VDD_165_195,
+	.f_max		= 50000000,
+	.capabilities	= MMC_CAP_4_BIT_DATA |
+				MMC_CAP_8_BIT_DATA |
+				MMC_CAP_MMC_HIGHSPEED,
+	.gpio_cd	= -1,
+	.gpio_wp	= -1,
+};
+
+void __init u5500_sdi_init(void)
+{
+	nmk_config_pins(u5500_sdi_pins, ARRAY_SIZE(u5500_sdi_pins));
+
+	db5500_add_sdi0(&u5500_sdi0_data);
+}
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-ux500/clock.c linux-libre-2.6.38-gnu1/arch/arm/mach-ux500/clock.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-ux500/clock.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-ux500/clock.c	2011-03-14 21:20:32.000000000 -0400
@@ -13,13 +13,18 @@
 #include <linux/err.h>
 #include <linux/clk.h>
 #include <linux/io.h>
-
-#include <asm/clkdev.h>
+#include <linux/clkdev.h>
 
 #include <plat/mtu.h>
 #include <mach/hardware.h>
 #include "clock.h"
 
+#ifdef CONFIG_DEBUG_FS
+#include <linux/debugfs.h>
+#include <linux/uaccess.h>	/* for copy_from_user */
+static LIST_HEAD(clk_list);
+#endif
+
 #define PRCC_PCKEN		0x00
 #define PRCC_PCKDIS		0x04
 #define PRCC_KCKEN		0x08
@@ -131,9 +136,8 @@ EXPORT_SYMBOL(clk_disable);
  */
 static unsigned long clk_mtu_get_rate(struct clk *clk)
 {
-	void __iomem *addr = __io_address(UX500_PRCMU_BASE)
-		+ PRCM_TCR;
-	u32 tcr = readl(addr);
+	void __iomem *addr;
+	u32 tcr;
 	int mtu = (int) clk->data;
 	/*
 	 * One of these is selected eventually
@@ -144,6 +148,21 @@ static unsigned long clk_mtu_get_rate(st
 	unsigned long mturate;
 	unsigned long retclk;
 
+	if (cpu_is_u5500())
+		addr = __io_address(U5500_PRCMU_BASE);
+	else if (cpu_is_u8500())
+		addr = __io_address(U8500_PRCMU_BASE);
+	else
+		ux500_unknown_soc();
+
+	/*
+	 * On a startup, always conifgure the TCR to the doze mode;
+	 * bootloaders do it for us. Do this in the kernel too.
+	 */
+	writel(PRCM_TCR_DOZE_MODE, addr + PRCM_TCR);
+
+	tcr = readl(addr + PRCM_TCR);
+
 	/* Get the rate from the parent as a default */
 	if (clk->parent_periph)
 		mturate = clk_get_rate(clk->parent_periph);
@@ -153,45 +172,6 @@ static unsigned long clk_mtu_get_rate(st
 		/* We need to be connected SOMEWHERE */
 		BUG();
 
-	/*
-	 * Are we in doze mode?
-	 * In this mode the parent peripheral or the fixed 32768 Hz
-	 * clock is fed into the block.
-	 */
-	if (!(tcr & PRCM_TCR_DOZE_MODE)) {
-		/*
-		 * Here we're using the clock input from the APE ULP
-		 * clock domain. But first: are the timers stopped?
-		 */
-		if (tcr & PRCM_TCR_STOPPED) {
-			clk32k = 0;
-			mturate = 0;
-		} else {
-			/* Else default mode: 0 and 2.4 MHz */
-			clk32k = 0;
-			if (cpu_is_u5500())
-				/* DB5500 divides by 8 */
-				mturate /= 8;
-			else if (cpu_is_u8500ed()) {
-				/*
-				 * This clocking setting must not be used
-				 * in the ED chip, it is simply not
-				 * connected anywhere!
-				 */
-				mturate = 0;
-				BUG();
-			} else
-				/*
-				 * In this mode the ulp38m4 clock is divided
-				 * by a factor 16, on the DB8500 typically
-				 * 38400000 / 16 ~ 2.4 MHz.
-				 * TODO: Replace the constant with a reference
-				 * to the ULP source once this is modeled.
-				 */
-				mturate = 38400000 / 16;
-		}
-	}
-
 	/* Return the clock selected for this MTU */
 	if (tcr & (1 << mtu))
 		retclk = clk32k;
@@ -317,6 +297,7 @@ static struct clkops clk_prcc_ops = {
 };
 
 static struct clk clk_32khz = {
+	.name =  "clk_32khz",
 	.rate = 32000,
 };
 
@@ -366,94 +347,96 @@ static DEFINE_PRCMU_CLK(uiccclk,	0x4, 1,
  */
 
 /* Peripheral Cluster #1 */
-static DEFINE_PRCC_CLK(1, i2c4, 	10, 9, &clk_i2cclk);
+static DEFINE_PRCC_CLK(1, i2c4,		10, 9, &clk_i2cclk);
 static DEFINE_PRCC_CLK(1, gpio0,	9, -1, NULL);
-static DEFINE_PRCC_CLK(1, slimbus0, 	8,  8, &clk_slimclk);
-static DEFINE_PRCC_CLK(1, spi3_ed, 	7,  7, NULL);
-static DEFINE_PRCC_CLK(1, spi3_v1, 	7, -1, NULL);
-static DEFINE_PRCC_CLK(1, i2c2, 	6,  6, &clk_i2cclk);
+static DEFINE_PRCC_CLK(1, slimbus0,	8,  8, &clk_slimclk);
+static DEFINE_PRCC_CLK(1, spi3_ed,	7,  7, NULL);
+static DEFINE_PRCC_CLK(1, spi3_v1,	7, -1, NULL);
+static DEFINE_PRCC_CLK(1, i2c2,		6,  6, &clk_i2cclk);
 static DEFINE_PRCC_CLK(1, sdi0,		5,  5, &clk_sdmmcclk);
-static DEFINE_PRCC_CLK(1, msp1_ed, 	4,  4, &clk_msp02clk);
-static DEFINE_PRCC_CLK(1, msp1_v1, 	4,  4, &clk_msp1clk);
-static DEFINE_PRCC_CLK(1, msp0, 	3,  3, &clk_msp02clk);
-static DEFINE_PRCC_CLK(1, i2c1, 	2,  2, &clk_i2cclk);
-static DEFINE_PRCC_CLK(1, uart1, 	1,  1, &clk_uartclk);
-static DEFINE_PRCC_CLK(1, uart0, 	0,  0, &clk_uartclk);
+static DEFINE_PRCC_CLK(1, msp1_ed,	4,  4, &clk_msp02clk);
+static DEFINE_PRCC_CLK(1, msp1_v1,	4,  4, &clk_msp1clk);
+static DEFINE_PRCC_CLK(1, msp0,		3,  3, &clk_msp02clk);
+static DEFINE_PRCC_CLK(1, i2c1,		2,  2, &clk_i2cclk);
+static DEFINE_PRCC_CLK(1, uart1,	1,  1, &clk_uartclk);
+static DEFINE_PRCC_CLK(1, uart0,	0,  0, &clk_uartclk);
 
 /* Peripheral Cluster #2 */
 
 static DEFINE_PRCC_CLK(2, gpio1_ed,	12, -1, NULL);
-static DEFINE_PRCC_CLK(2, ssitx_ed, 	11, -1, NULL);
-static DEFINE_PRCC_CLK(2, ssirx_ed, 	10, -1, NULL);
-static DEFINE_PRCC_CLK(2, spi0_ed, 	 9, -1, NULL);
-static DEFINE_PRCC_CLK(2, sdi3_ed, 	 8,  6, &clk_sdmmcclk);
-static DEFINE_PRCC_CLK(2, sdi1_ed, 	 7,  5, &clk_sdmmcclk);
-static DEFINE_PRCC_CLK(2, msp2_ed, 	 6,  4, &clk_msp02clk);
-static DEFINE_PRCC_CLK(2, sdi4_ed, 	 4,  2, &clk_sdmmcclk);
+static DEFINE_PRCC_CLK(2, ssitx_ed,	11, -1, NULL);
+static DEFINE_PRCC_CLK(2, ssirx_ed,	10, -1, NULL);
+static DEFINE_PRCC_CLK(2, spi0_ed,	 9, -1, NULL);
+static DEFINE_PRCC_CLK(2, sdi3_ed,	 8,  6, &clk_sdmmcclk);
+static DEFINE_PRCC_CLK(2, sdi1_ed,	 7,  5, &clk_sdmmcclk);
+static DEFINE_PRCC_CLK(2, msp2_ed,	 6,  4, &clk_msp02clk);
+static DEFINE_PRCC_CLK(2, sdi4_ed,	 4,  2, &clk_sdmmcclk);
 static DEFINE_PRCC_CLK(2, pwl_ed,	 3,  1, NULL);
-static DEFINE_PRCC_CLK(2, spi1_ed, 	 2, -1, NULL);
-static DEFINE_PRCC_CLK(2, spi2_ed, 	 1, -1, NULL);
-static DEFINE_PRCC_CLK(2, i2c3_ed, 	 0,  0, &clk_i2cclk);
+static DEFINE_PRCC_CLK(2, spi1_ed,	 2, -1, NULL);
+static DEFINE_PRCC_CLK(2, spi2_ed,	 1, -1, NULL);
+static DEFINE_PRCC_CLK(2, i2c3_ed,	 0,  0, &clk_i2cclk);
 
 static DEFINE_PRCC_CLK(2, gpio1_v1,	11, -1, NULL);
-static DEFINE_PRCC_CLK(2, ssitx_v1, 	10,  7, NULL);
-static DEFINE_PRCC_CLK(2, ssirx_v1, 	 9,  6, NULL);
-static DEFINE_PRCC_CLK(2, spi0_v1, 	 8, -1, NULL);
-static DEFINE_PRCC_CLK(2, sdi3_v1, 	 7,  5, &clk_sdmmcclk);
-static DEFINE_PRCC_CLK(2, sdi1_v1, 	 6,  4, &clk_sdmmcclk);
-static DEFINE_PRCC_CLK(2, msp2_v1, 	 5,  3, &clk_msp02clk);
-static DEFINE_PRCC_CLK(2, sdi4_v1, 	 4,  2, &clk_sdmmcclk);
+static DEFINE_PRCC_CLK(2, ssitx_v1,	10,  7, NULL);
+static DEFINE_PRCC_CLK(2, ssirx_v1,	 9,  6, NULL);
+static DEFINE_PRCC_CLK(2, spi0_v1,	 8, -1, NULL);
+static DEFINE_PRCC_CLK(2, sdi3_v1,	 7,  5, &clk_sdmmcclk);
+static DEFINE_PRCC_CLK(2, sdi1_v1,	 6,  4, &clk_sdmmcclk);
+static DEFINE_PRCC_CLK(2, msp2_v1,	 5,  3, &clk_msp02clk);
+static DEFINE_PRCC_CLK(2, sdi4_v1,	 4,  2, &clk_sdmmcclk);
 static DEFINE_PRCC_CLK(2, pwl_v1,	 3,  1, NULL);
-static DEFINE_PRCC_CLK(2, spi1_v1, 	 2, -1, NULL);
-static DEFINE_PRCC_CLK(2, spi2_v1, 	 1, -1, NULL);
-static DEFINE_PRCC_CLK(2, i2c3_v1, 	 0,  0, &clk_i2cclk);
+static DEFINE_PRCC_CLK(2, spi1_v1,	 2, -1, NULL);
+static DEFINE_PRCC_CLK(2, spi2_v1,	 1, -1, NULL);
+static DEFINE_PRCC_CLK(2, i2c3_v1,	 0,  0, &clk_i2cclk);
 
 /* Peripheral Cluster #3 */
-static DEFINE_PRCC_CLK(3, gpio2, 	8, -1, NULL);
-static DEFINE_PRCC_CLK(3, sdi5, 	7,  7, &clk_sdmmcclk);
-static DEFINE_PRCC_CLK(3, uart2, 	6,  6, &clk_uartclk);
-static DEFINE_PRCC_CLK(3, ske, 		5,  5, &clk_32khz);
-static DEFINE_PRCC_CLK(3, sdi2, 	4,  4, &clk_sdmmcclk);
-static DEFINE_PRCC_CLK(3, i2c0, 	3,  3, &clk_i2cclk);
-static DEFINE_PRCC_CLK(3, ssp1_ed, 	2,  2, &clk_i2cclk);
-static DEFINE_PRCC_CLK(3, ssp0_ed, 	1,  1, &clk_i2cclk);
-static DEFINE_PRCC_CLK(3, ssp1_v1, 	2,  2, &clk_sspclk);
-static DEFINE_PRCC_CLK(3, ssp0_v1, 	1,  1, &clk_sspclk);
-static DEFINE_PRCC_CLK(3, fsmc, 	0, -1, NULL);
+static DEFINE_PRCC_CLK(3, gpio2,	8, -1, NULL);
+static DEFINE_PRCC_CLK(3, sdi5,		7,  7, &clk_sdmmcclk);
+static DEFINE_PRCC_CLK(3, uart2,	6,  6, &clk_uartclk);
+static DEFINE_PRCC_CLK(3, ske,		5,  5, &clk_32khz);
+static DEFINE_PRCC_CLK(3, sdi2,		4,  4, &clk_sdmmcclk);
+static DEFINE_PRCC_CLK(3, i2c0,		3,  3, &clk_i2cclk);
+static DEFINE_PRCC_CLK(3, ssp1_ed,	2,  2, &clk_i2cclk);
+static DEFINE_PRCC_CLK(3, ssp0_ed,	1,  1, &clk_i2cclk);
+static DEFINE_PRCC_CLK(3, ssp1_v1,	2,  2, &clk_sspclk);
+static DEFINE_PRCC_CLK(3, ssp0_v1,	1,  1, &clk_sspclk);
+static DEFINE_PRCC_CLK(3, fsmc,		0, -1, NULL);
 
 /* Peripheral Cluster #4 is in the always on domain */
 
 /* Peripheral Cluster #5 */
-static DEFINE_PRCC_CLK(5, gpio3, 	1, -1, NULL);
-static DEFINE_PRCC_CLK(5, usb_ed, 	0,  0, &clk_i2cclk);
-static DEFINE_PRCC_CLK(5, usb_v1, 	0,  0, NULL);
+static DEFINE_PRCC_CLK(5, gpio3,	1, -1, NULL);
+static DEFINE_PRCC_CLK(5, usb_ed,	0,  0, &clk_i2cclk);
+static DEFINE_PRCC_CLK(5, usb_v1,	0,  0, NULL);
 
 /* Peripheral Cluster #6 */
 
 /* MTU ID in data */
 static DEFINE_PRCC_CLK_CUSTOM(6, mtu1_v1, 8, -1, NULL, clk_mtu_get_rate, 1);
 static DEFINE_PRCC_CLK_CUSTOM(6, mtu0_v1, 7, -1, NULL, clk_mtu_get_rate, 0);
-static DEFINE_PRCC_CLK(6, cfgreg_v1, 	6,  6, NULL);
-static DEFINE_PRCC_CLK(6, dmc_ed, 	6,  6, NULL);
-static DEFINE_PRCC_CLK(6, hash1, 	5, -1, NULL);
-static DEFINE_PRCC_CLK(6, unipro_v1, 	4,  1, &clk_uniproclk);
-static DEFINE_PRCC_CLK(6, cryp1_ed, 	4, -1, NULL);
-static DEFINE_PRCC_CLK(6, pka, 		3, -1, NULL);
-static DEFINE_PRCC_CLK(6, hash0, 	2, -1, NULL);
-static DEFINE_PRCC_CLK(6, cryp0, 	1, -1, NULL);
-static DEFINE_PRCC_CLK(6, rng_ed, 	0,  0, &clk_i2cclk);
-static DEFINE_PRCC_CLK(6, rng_v1, 	0,  0, &clk_rngclk);
+static DEFINE_PRCC_CLK(6, cfgreg_v1,	6,  6, NULL);
+static DEFINE_PRCC_CLK(6, dmc_ed,	6,  6, NULL);
+static DEFINE_PRCC_CLK(6, hash1,	5, -1, NULL);
+static DEFINE_PRCC_CLK(6, unipro_v1,	4,  1, &clk_uniproclk);
+static DEFINE_PRCC_CLK(6, cryp1_ed,	4, -1, NULL);
+static DEFINE_PRCC_CLK(6, pka,		3, -1, NULL);
+static DEFINE_PRCC_CLK(6, hash0,	2, -1, NULL);
+static DEFINE_PRCC_CLK(6, cryp0,	1, -1, NULL);
+static DEFINE_PRCC_CLK(6, rng_ed,	0,  0, &clk_i2cclk);
+static DEFINE_PRCC_CLK(6, rng_v1,	0,  0, &clk_rngclk);
 
 /* Peripheral Cluster #7 */
 
-static DEFINE_PRCC_CLK(7, tzpc0_ed, 	4, -1, NULL);
+static DEFINE_PRCC_CLK(7, tzpc0_ed,	4, -1, NULL);
 /* MTU ID in data */
 static DEFINE_PRCC_CLK_CUSTOM(7, mtu1_ed, 3, -1, NULL, clk_mtu_get_rate, 1);
 static DEFINE_PRCC_CLK_CUSTOM(7, mtu0_ed, 2, -1, NULL, clk_mtu_get_rate, 0);
-static DEFINE_PRCC_CLK(7, wdg_ed, 	1, -1, NULL);
-static DEFINE_PRCC_CLK(7, cfgreg_ed, 	0, -1, NULL);
+static DEFINE_PRCC_CLK(7, wdg_ed,	1, -1, NULL);
+static DEFINE_PRCC_CLK(7, cfgreg_ed,	0, -1, NULL);
 
-static struct clk clk_dummy_apb_pclk;
+static struct clk clk_dummy_apb_pclk = {
+	.name = "apb_pclk",
+};
 
 static struct clk_lookup u8500_common_clks[] = {
 	CLK(dummy_apb_pclk, NULL,	"apb_pclk"),
@@ -554,7 +537,7 @@ static struct clk_lookup u8500_ed_clks[]
 
 static struct clk_lookup u8500_v1_clks[] = {
 	/* Peripheral Cluster #1 */
-	CLK(i2c4,	"nmk-i2c.4", 	NULL),
+	CLK(i2c4,	"nmk-i2c.4",	NULL),
 	CLK(spi3_v1,	"spi3",		NULL),
 	CLK(msp1_v1,	"msp1",		NULL),
 
@@ -599,6 +582,183 @@ static struct clk_lookup u8500_v1_clks[]
 	CLK(uiccclk,	"uicc",		NULL),
 };
 
+#ifdef CONFIG_DEBUG_FS
+/*
+ *	debugfs support to trace clock tree hierarchy and attributes with
+ *	powerdebug
+ */
+static struct dentry *clk_debugfs_root;
+
+void __init clk_debugfs_add_table(struct clk_lookup *cl, size_t num)
+{
+	while (num--) {
+		/* Check that the clock has not been already registered */
+		if (!(cl->clk->list.prev != cl->clk->list.next))
+			list_add_tail(&cl->clk->list, &clk_list);
+
+		cl++;
+	}
+}
+
+static ssize_t usecount_dbg_read(struct file *file, char __user *buf,
+						  size_t size, loff_t *off)
+{
+	struct clk *clk = file->f_dentry->d_inode->i_private;
+	char cusecount[128];
+	unsigned int len;
+
+	len = sprintf(cusecount, "%u\n", clk->enabled);
+	return simple_read_from_buffer(buf, size, off, cusecount, len);
+}
+
+static ssize_t rate_dbg_read(struct file *file, char __user *buf,
+					  size_t size, loff_t *off)
+{
+	struct clk *clk = file->f_dentry->d_inode->i_private;
+	char crate[128];
+	unsigned int rate;
+	unsigned int len;
+
+	rate = clk_get_rate(clk);
+	len = sprintf(crate, "%u\n", rate);
+	return simple_read_from_buffer(buf, size, off, crate, len);
+}
+
+static const struct file_operations usecount_fops = {
+	.read = usecount_dbg_read,
+};
+
+static const struct file_operations set_rate_fops = {
+	.read = rate_dbg_read,
+};
+
+static struct dentry *clk_debugfs_register_dir(struct clk *c,
+						struct dentry *p_dentry)
+{
+	struct dentry *d, *clk_d, *child, *child_tmp;
+	char s[255];
+	char *p = s;
+
+	if (c->name == NULL)
+		p += sprintf(p, "BUG");
+	else
+		p += sprintf(p, "%s", c->name);
+
+	clk_d = debugfs_create_dir(s, p_dentry);
+	if (!clk_d)
+		return NULL;
+
+	d = debugfs_create_file("usecount", S_IRUGO,
+				clk_d, c, &usecount_fops);
+	if (!d)
+		goto err_out;
+	d = debugfs_create_file("rate", S_IRUGO,
+				clk_d, c, &set_rate_fops);
+	if (!d)
+		goto err_out;
+	/*
+	 * TODO : not currently available in ux500
+	 * d = debugfs_create_x32("flags", S_IRUGO, clk_d, (u32 *)&c->flags);
+	 * if (!d)
+	 *	goto err_out;
+	 */
+
+	return clk_d;
+
+err_out:
+	d = clk_d;
+	list_for_each_entry_safe(child, child_tmp, &d->d_subdirs, d_u.d_child)
+		debugfs_remove(child);
+	debugfs_remove(clk_d);
+	return NULL;
+}
+
+static void clk_debugfs_remove_dir(struct dentry *cdentry)
+{
+	struct dentry *d, *child, *child_tmp;
+
+	d = cdentry;
+	list_for_each_entry_safe(child, child_tmp, &d->d_subdirs, d_u.d_child)
+		debugfs_remove(child);
+	debugfs_remove(cdentry);
+	return ;
+}
+
+static int clk_debugfs_register_one(struct clk *c)
+{
+	struct clk *pa = c->parent_periph;
+	struct clk *bpa = c->parent_cluster;
+
+	if (!(bpa && !pa)) {
+		c->dent = clk_debugfs_register_dir(c,
+				pa ? pa->dent : clk_debugfs_root);
+		if (!c->dent)
+			return -ENOMEM;
+	}
+
+	if (bpa) {
+		c->dent_bus = clk_debugfs_register_dir(c,
+				bpa->dent_bus ? bpa->dent_bus : bpa->dent);
+		if ((!c->dent_bus) &&  (c->dent)) {
+			clk_debugfs_remove_dir(c->dent);
+			c->dent = NULL;
+			return -ENOMEM;
+		}
+	}
+	return 0;
+}
+
+static int clk_debugfs_register(struct clk *c)
+{
+	int err;
+	struct clk *pa = c->parent_periph;
+	struct clk *bpa = c->parent_cluster;
+
+	if (pa && (!pa->dent && !pa->dent_bus)) {
+		err = clk_debugfs_register(pa);
+		if (err)
+			return err;
+	}
+
+	if (bpa && (!bpa->dent && !bpa->dent_bus)) {
+		err = clk_debugfs_register(bpa);
+		if (err)
+			return err;
+	}
+
+	if ((!c->dent) && (!c->dent_bus)) {
+		err = clk_debugfs_register_one(c);
+		if (err)
+			return err;
+	}
+	return 0;
+}
+
+static int __init clk_debugfs_init(void)
+{
+	struct clk *c;
+	struct dentry *d;
+	int err;
+
+	d = debugfs_create_dir("clock", NULL);
+	if (!d)
+		return -ENOMEM;
+	clk_debugfs_root = d;
+
+	list_for_each_entry(c, &clk_list, list) {
+		err = clk_debugfs_register(c);
+		if (err)
+			goto err_out;
+	}
+	return 0;
+err_out:
+	debugfs_remove_recursive(clk_debugfs_root);
+	return err;
+}
+
+late_initcall(clk_debugfs_init);
+#endif /* defined(CONFIG_DEBUG_FS) */
+
 int __init clk_init(void)
 {
 	if (cpu_is_u8500ed()) {
@@ -609,7 +769,8 @@ int __init clk_init(void)
 		/* Clock tree for U5500 not implemented yet */
 		clk_prcc_ops.enable = clk_prcc_ops.disable = NULL;
 		clk_prcmu_ops.enable = clk_prcmu_ops.disable = NULL;
-		clk_per6clk.rate = 26000000;
+		clk_uartclk.rate = 36360000;
+		clk_sdmmcclk.rate = 99900000;
 	}
 
 	clkdev_add_table(u8500_common_clks, ARRAY_SIZE(u8500_common_clks));
@@ -618,5 +779,12 @@ int __init clk_init(void)
 	else
 		clkdev_add_table(u8500_v1_clks, ARRAY_SIZE(u8500_v1_clks));
 
+#ifdef CONFIG_DEBUG_FS
+	clk_debugfs_add_table(u8500_common_clks, ARRAY_SIZE(u8500_common_clks));
+	if (cpu_is_u8500ed())
+		clk_debugfs_add_table(u8500_ed_clks, ARRAY_SIZE(u8500_ed_clks));
+	else
+		clk_debugfs_add_table(u8500_v1_clks, ARRAY_SIZE(u8500_v1_clks));
+#endif
 	return 0;
 }
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-ux500/clock.h linux-libre-2.6.38-gnu1/arch/arm/mach-ux500/clock.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-ux500/clock.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-ux500/clock.h	2011-03-14 21:20:32.000000000 -0400
@@ -90,6 +90,10 @@ struct clk {
 
 	struct clk		*parent_cluster;
 	struct clk		*parent_periph;
+#if defined(CONFIG_DEBUG_FS)
+	struct dentry		*dent;		/* For visible tree hierarchy */
+	struct dentry		*dent_bus;	/* For visible tree hierarchy */
+#endif
 };
 
 #define DEFINE_PRCMU_CLK(_name, _cg_off, _cg_bit, _reg)		\
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-ux500/cpu.c linux-libre-2.6.38-gnu1/arch/arm/mach-ux500/cpu.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-ux500/cpu.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-ux500/cpu.c	2011-03-14 21:20:32.000000000 -0400
@@ -6,7 +6,6 @@
  */
 
 #include <linux/platform_device.h>
-#include <linux/amba/bus.h>
 #include <linux/io.h>
 #include <linux/clk.h>
 
@@ -20,54 +19,36 @@
 #include <mach/hardware.h>
 #include <mach/setup.h>
 #include <mach/devices.h>
+#include <mach/prcmu.h>
 
 #include "clock.h"
 
-static struct map_desc ux500_io_desc[] __initdata = {
-	__IO_DEV_DESC(UX500_UART0_BASE, SZ_4K),
-	__IO_DEV_DESC(UX500_UART2_BASE, SZ_4K),
-
-	__IO_DEV_DESC(UX500_GIC_CPU_BASE, SZ_4K),
-	__IO_DEV_DESC(UX500_GIC_DIST_BASE, SZ_4K),
-	__IO_DEV_DESC(UX500_L2CC_BASE, SZ_4K),
-	__IO_DEV_DESC(UX500_TWD_BASE, SZ_4K),
-	__IO_DEV_DESC(UX500_SCU_BASE, SZ_4K),
-
-	__IO_DEV_DESC(UX500_CLKRST1_BASE, SZ_4K),
-	__IO_DEV_DESC(UX500_CLKRST2_BASE, SZ_4K),
-	__IO_DEV_DESC(UX500_CLKRST3_BASE, SZ_4K),
-	__IO_DEV_DESC(UX500_CLKRST5_BASE, SZ_4K),
-	__IO_DEV_DESC(UX500_CLKRST6_BASE, SZ_4K),
-
-	__IO_DEV_DESC(UX500_MTU0_BASE, SZ_4K),
-	__IO_DEV_DESC(UX500_MTU1_BASE, SZ_4K),
-
-	__IO_DEV_DESC(UX500_BACKUPRAM0_BASE, SZ_8K),
-};
-
-static struct amba_device *ux500_amba_devs[] __initdata = {
-	&ux500_pl031_device,
-};
+#ifdef CONFIG_CACHE_L2X0
+static void __iomem *l2x0_base;
+#endif
 
-void __init ux500_map_io(void)
+void __init ux500_init_irq(void)
 {
-	iotable_init(ux500_io_desc, ARRAY_SIZE(ux500_io_desc));
-}
+	void __iomem *dist_base;
+	void __iomem *cpu_base;
 
-void __init ux500_init_devices(void)
-{
-	amba_add_devices(ux500_amba_devs, ARRAY_SIZE(ux500_amba_devs));
-}
+	if (cpu_is_u5500()) {
+		dist_base = __io_address(U5500_GIC_DIST_BASE);
+		cpu_base = __io_address(U5500_GIC_CPU_BASE);
+	} else if (cpu_is_u8500()) {
+		dist_base = __io_address(U8500_GIC_DIST_BASE);
+		cpu_base = __io_address(U8500_GIC_CPU_BASE);
+	} else
+		ux500_unknown_soc();
 
-void __init ux500_init_irq(void)
-{
-	gic_dist_init(0, __io_address(UX500_GIC_DIST_BASE), 29);
-	gic_cpu_init(0, __io_address(UX500_GIC_CPU_BASE));
+	gic_init(0, 29, dist_base, cpu_base);
 
 	/*
 	 * Init clocks here so that they are available for system timer
 	 * initialization.
 	 */
+	if (cpu_is_u8500())
+		prcmu_early_init();
 	clk_init();
 }
 
@@ -81,7 +62,8 @@ static inline void ux500_cache_wait(void
 
 static inline void ux500_cache_sync(void)
 {
-	void __iomem *base = __io_address(UX500_L2CC_BASE);
+	void __iomem *base = l2x0_base;
+
 	writel_relaxed(0, base + L2X0_CACHE_SYNC);
 	ux500_cache_wait(base + L2X0_CACHE_SYNC, 1);
 }
@@ -103,20 +85,23 @@ static void ux500_l2x0_disable(void)
  */
 static void ux500_l2x0_inv_all(void)
 {
-	void __iomem *l2x0_base = __io_address(UX500_L2CC_BASE);
+	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, l2x0_base + L2X0_INV_WAY);
-	ux500_cache_wait(l2x0_base + L2X0_INV_WAY, l2x0_way_mask);
+	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)
 {
-	void __iomem *l2x0_base;
-
-	l2x0_base = __io_address(UX500_L2CC_BASE);
+	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);
@@ -134,13 +119,21 @@ static void __init ux500_timer_init(void
 {
 #ifdef CONFIG_LOCAL_TIMERS
 	/* Setup the local timer base */
-	twd_base = __io_address(UX500_TWD_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
-	/* Setup the MTU base */
-	if (cpu_is_u8500ed())
+	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
-		mtu_base = __io_address(UX500_MTU0_BASE);
+		ux500_unknown_soc();
 
 	nmdk_timer_init();
 }
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-ux500/cpu-db5500.c linux-libre-2.6.38-gnu1/arch/arm/mach-ux500/cpu-db5500.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-ux500/cpu-db5500.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-ux500/cpu-db5500.c	2011-03-14 21:20:32.000000000 -0400
@@ -8,15 +8,33 @@
 #include <linux/platform_device.h>
 #include <linux/amba/bus.h>
 #include <linux/io.h>
+#include <linux/irq.h>
 
 #include <asm/mach/map.h>
 
+#include <plat/gpio.h>
+
 #include <mach/hardware.h>
 #include <mach/devices.h>
 #include <mach/setup.h>
 #include <mach/irqs.h>
 
+#include "devices-db5500.h"
+
+static struct map_desc u5500_uart_io_desc[] __initdata = {
+	__IO_DEV_DESC(U5500_UART0_BASE, SZ_4K),
+	__IO_DEV_DESC(U5500_UART2_BASE, SZ_4K),
+};
+
 static struct map_desc u5500_io_desc[] __initdata = {
+	__IO_DEV_DESC(U5500_GIC_CPU_BASE, SZ_4K),
+	__IO_DEV_DESC(U5500_GIC_DIST_BASE, SZ_4K),
+	__IO_DEV_DESC(U5500_L2CC_BASE, SZ_4K),
+	__IO_DEV_DESC(U5500_TWD_BASE, SZ_4K),
+	__IO_DEV_DESC(U5500_MTU0_BASE, SZ_4K),
+	__IO_DEV_DESC(U5500_SCU_BASE, SZ_4K),
+	__IO_DEV_DESC(U5500_BACKUPRAM0_BASE, SZ_8K),
+
 	__IO_DEV_DESC(U5500_GPIO0_BASE, SZ_4K),
 	__IO_DEV_DESC(U5500_GPIO1_BASE, SZ_4K),
 	__IO_DEV_DESC(U5500_GPIO2_BASE, SZ_4K),
@@ -110,21 +128,39 @@ static struct platform_device mbox2_devi
 };
 
 static struct platform_device *u5500_platform_devs[] __initdata = {
-	&u5500_gpio_devs[0],
-	&u5500_gpio_devs[1],
-	&u5500_gpio_devs[2],
-	&u5500_gpio_devs[3],
-	&u5500_gpio_devs[4],
-	&u5500_gpio_devs[5],
-	&u5500_gpio_devs[6],
-	&u5500_gpio_devs[7],
 	&mbox0_device,
 	&mbox1_device,
 	&mbox2_device,
 };
 
+static resource_size_t __initdata db5500_gpio_base[] = {
+	U5500_GPIOBANK0_BASE,
+	U5500_GPIOBANK1_BASE,
+	U5500_GPIOBANK2_BASE,
+	U5500_GPIOBANK3_BASE,
+	U5500_GPIOBANK4_BASE,
+	U5500_GPIOBANK5_BASE,
+	U5500_GPIOBANK6_BASE,
+	U5500_GPIOBANK7_BASE,
+};
+
+static void __init db5500_add_gpios(void)
+{
+	struct nmk_gpio_platform_data pdata = {
+		/* No custom data yet */
+	};
+
+	dbx500_add_gpios(ARRAY_AND_SIZE(db5500_gpio_base),
+			 IRQ_DB5500_GPIO0, &pdata);
+}
+
 void __init u5500_map_io(void)
 {
+	/*
+	 * Map the UARTs early so that the DEBUG_LL stuff continues to work.
+	 */
+	iotable_init(u5500_uart_io_desc, ARRAY_SIZE(u5500_uart_io_desc));
+
 	ux500_map_io();
 
 	iotable_init(u5500_io_desc, ARRAY_SIZE(u5500_io_desc));
@@ -132,7 +168,9 @@ void __init u5500_map_io(void)
 
 void __init u5500_init_devices(void)
 {
-	ux500_init_devices();
+	db5500_add_gpios();
+	db5500_dma_init();
+	db5500_add_rtc();
 
 	platform_add_devices(u5500_platform_devs,
 			     ARRAY_SIZE(u5500_platform_devs));
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-ux500/cpu-db8500.c linux-libre-2.6.38-gnu1/arch/arm/mach-ux500/cpu-db8500.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-ux500/cpu-db8500.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-ux500/cpu-db8500.c	2011-03-14 21:20:32.000000000 -0400
@@ -22,115 +22,93 @@
 #include <mach/setup.h>
 #include <mach/devices.h>
 
+#include "devices-db8500.h"
+
 static struct platform_device *platform_devs[] __initdata = {
-	&u8500_gpio_devs[0],
-	&u8500_gpio_devs[1],
-	&u8500_gpio_devs[2],
-	&u8500_gpio_devs[3],
-	&u8500_gpio_devs[4],
-	&u8500_gpio_devs[5],
-	&u8500_gpio_devs[6],
-	&u8500_gpio_devs[7],
-	&u8500_gpio_devs[8],
 	&u8500_dma40_device,
 };
 
 /* minimum static i/o mapping required to boot U8500 platforms */
+static struct map_desc u8500_uart_io_desc[] __initdata = {
+	__IO_DEV_DESC(U8500_UART0_BASE, SZ_4K),
+	__IO_DEV_DESC(U8500_UART2_BASE, SZ_4K),
+};
+
 static struct map_desc u8500_io_desc[] __initdata = {
+	__IO_DEV_DESC(U8500_GIC_CPU_BASE, SZ_4K),
+	__IO_DEV_DESC(U8500_GIC_DIST_BASE, SZ_4K),
+	__IO_DEV_DESC(U8500_L2CC_BASE, SZ_4K),
+	__IO_DEV_DESC(U8500_TWD_BASE, SZ_4K),
+	__IO_DEV_DESC(U8500_MTU0_BASE, SZ_4K),
+	__IO_DEV_DESC(U8500_SCU_BASE, SZ_4K),
+	__IO_DEV_DESC(U8500_BACKUPRAM0_BASE, SZ_8K),
+
+	__IO_DEV_DESC(U8500_CLKRST1_BASE, SZ_4K),
+	__IO_DEV_DESC(U8500_CLKRST2_BASE, SZ_4K),
+	__IO_DEV_DESC(U8500_CLKRST3_BASE, SZ_4K),
+	__IO_DEV_DESC(U8500_CLKRST5_BASE, SZ_4K),
+	__IO_DEV_DESC(U8500_CLKRST6_BASE, SZ_4K),
+
 	__IO_DEV_DESC(U8500_PRCMU_BASE, SZ_4K),
-	__IO_DEV_DESC(U8500_PRCMU_TCDM_BASE, SZ_4K),
 	__IO_DEV_DESC(U8500_GPIO0_BASE, SZ_4K),
 	__IO_DEV_DESC(U8500_GPIO1_BASE, SZ_4K),
 	__IO_DEV_DESC(U8500_GPIO2_BASE, SZ_4K),
 	__IO_DEV_DESC(U8500_GPIO3_BASE, SZ_4K),
-	__MEM_DEV_DESC(U8500_BOOT_ROM_BASE, SZ_1M),
 };
 
-static struct map_desc u8500ed_io_desc[] __initdata = {
+static struct map_desc u8500_ed_io_desc[] __initdata = {
 	__IO_DEV_DESC(U8500_MTU0_BASE_ED, SZ_4K),
 	__IO_DEV_DESC(U8500_CLKRST7_BASE_ED, SZ_8K),
 };
 
-static struct map_desc u8500v1_io_desc[] __initdata = {
+static struct map_desc u8500_v1_io_desc[] __initdata = {
 	__IO_DEV_DESC(U8500_MTU0_BASE, SZ_4K),
+	__IO_DEV_DESC(U8500_PRCMU_TCDM_BASE_V1, SZ_4K),
 };
 
-/*
- * Functions to differentiate between later ASICs
- * We look into the end of the ROM to locate the hardcoded ASIC ID.
- * This is only needed to differentiate between minor revisions and
- * process variants of an ASIC, the major revisions are encoded in
- * the cpuid.
- */
-#define U8500_ASIC_ID_LOC_ED_V1	(U8500_BOOT_ROM_BASE + 0x1FFF4)
-#define U8500_ASIC_ID_LOC_V2	(U8500_BOOT_ROM_BASE + 0x1DBF4)
-#define U8500_ASIC_REV_ED	0x01
-#define U8500_ASIC_REV_V10	0xA0
-#define U8500_ASIC_REV_V11	0xA1
-#define U8500_ASIC_REV_V20	0xB0
-
-/**
- * struct db8500_asic_id - fields of the ASIC ID
- * @process: the manufacturing process, 0x40 is 40 nm
- *  0x00 is "standard"
- * @partnumber: hithereto 0x8500 for DB8500
- * @revision: version code in the series
- * This field definion is not formally defined but makes
- * sense.
- */
-struct db8500_asic_id {
-	u8 process;
-	u16 partnumber;
-	u8 revision;
+static struct map_desc u8500_v2_io_desc[] __initdata = {
+	__IO_DEV_DESC(U8500_PRCMU_TCDM_BASE, SZ_4K),
 };
 
-/* This isn't going to change at runtime */
-static struct db8500_asic_id db8500_id;
-
-static void __init get_db8500_asic_id(void)
+void __init u8500_map_io(void)
 {
-	u32 asicid;
-
-	if (cpu_is_u8500v1() || cpu_is_u8500ed())
-		asicid = readl(__io_address(U8500_ASIC_ID_LOC_ED_V1));
-	else if (cpu_is_u8500v2())
-		asicid = readl(__io_address(U8500_ASIC_ID_LOC_V2));
-	else
-		BUG();
+	/*
+	 * Map the UARTs early so that the DEBUG_LL stuff continues to work.
+	 */
+	iotable_init(u8500_uart_io_desc, ARRAY_SIZE(u8500_uart_io_desc));
 
-	db8500_id.process = (asicid >> 24);
-	db8500_id.partnumber = (asicid >> 16) & 0xFFFFU;
-	db8500_id.revision = asicid & 0xFFU;
-}
+	ux500_map_io();
 
-bool cpu_is_u8500v10(void)
-{
-	return (db8500_id.revision == U8500_ASIC_REV_V10);
-}
+	iotable_init(u8500_io_desc, ARRAY_SIZE(u8500_io_desc));
 
-bool cpu_is_u8500v11(void)
-{
-	return (db8500_id.revision == U8500_ASIC_REV_V11);
+	if (cpu_is_u8500ed())
+		iotable_init(u8500_ed_io_desc, ARRAY_SIZE(u8500_ed_io_desc));
+	else if (cpu_is_u8500v1())
+		iotable_init(u8500_v1_io_desc, ARRAY_SIZE(u8500_v1_io_desc));
+	else if (cpu_is_u8500v2())
+		iotable_init(u8500_v2_io_desc, ARRAY_SIZE(u8500_v2_io_desc));
 }
 
-bool cpu_is_u8500v20(void)
-{
-	return (db8500_id.revision == U8500_ASIC_REV_V20);
-}
+static resource_size_t __initdata db8500_gpio_base[] = {
+	U8500_GPIOBANK0_BASE,
+	U8500_GPIOBANK1_BASE,
+	U8500_GPIOBANK2_BASE,
+	U8500_GPIOBANK3_BASE,
+	U8500_GPIOBANK4_BASE,
+	U8500_GPIOBANK5_BASE,
+	U8500_GPIOBANK6_BASE,
+	U8500_GPIOBANK7_BASE,
+	U8500_GPIOBANK8_BASE,
+};
 
-void __init u8500_map_io(void)
+static void __init db8500_add_gpios(void)
 {
-	ux500_map_io();
-
-	iotable_init(u8500_io_desc, ARRAY_SIZE(u8500_io_desc));
-
-	if (cpu_is_u8500ed())
-		iotable_init(u8500ed_io_desc, ARRAY_SIZE(u8500ed_io_desc));
-	else
-		iotable_init(u8500v1_io_desc, ARRAY_SIZE(u8500v1_io_desc));
+	struct nmk_gpio_platform_data pdata = {
+		/* No custom data yet */
+	};
 
-	/* Read out the ASIC ID as early as we can */
-	get_db8500_asic_id();
+	dbx500_add_gpios(ARRAY_AND_SIZE(db8500_gpio_base),
+			 IRQ_DB8500_GPIO0, &pdata);
 }
 
 /*
@@ -138,26 +116,13 @@ void __init u8500_map_io(void)
  */
 void __init u8500_init_devices(void)
 {
-	/* Display some ASIC boilerplate */
-	pr_info("DB8500: process: %02x, revision ID: 0x%02x\n",
-		db8500_id.process, db8500_id.revision);
-	if (cpu_is_u8500ed())
-		pr_info("DB8500: Early Drop (ED)\n");
-	else if (cpu_is_u8500v10())
-		pr_info("DB8500: version 1.0\n");
-	else if (cpu_is_u8500v11())
-		pr_info("DB8500: version 1.1\n");
-	else if (cpu_is_u8500v20())
-		pr_info("DB8500: version 2.0\n");
-	else
-		pr_warning("ASIC: UNKNOWN SILICON VERSION!\n");
-
-	ux500_init_devices();
-
 	if (cpu_is_u8500ed())
 		dma40_u8500ed_fixup();
 
-	/* Register the platform devices */
+	db8500_add_rtc();
+	db8500_add_gpios();
+
+	platform_device_register_simple("cpufreq-u8500", -1, NULL, 0);
 	platform_add_devices(platform_devs, ARRAY_SIZE(platform_devs));
 
 	return ;
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-ux500/cpufreq.c linux-libre-2.6.38-gnu1/arch/arm/mach-ux500/cpufreq.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-ux500/cpufreq.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-ux500/cpufreq.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,211 @@
+/*
+ * CPU frequency scaling for u8500
+ * Inspired by linux/arch/arm/mach-davinci/cpufreq.c
+ *
+ * Copyright (C) STMicroelectronics 2009
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * License Terms: GNU General Public License v2
+ *
+ * Author: Sundar Iyer <sundar.iyer@stericsson.com>
+ * Author: Martin Persson <martin.persson@stericsson.com>
+ * Author: Jonas Aaberg <jonas.aberg@stericsson.com>
+ *
+ */
+
+#include <linux/platform_device.h>
+#include <linux/kernel.h>
+#include <linux/cpufreq.h>
+#include <linux/delay.h>
+
+#include <mach/hardware.h>
+#include <mach/prcmu.h>
+#include <mach/prcmu-defs.h>
+
+#define DRIVER_NAME "cpufreq-u8500"
+#define CPUFREQ_NAME "u8500"
+
+static struct device *dev;
+
+static struct cpufreq_frequency_table freq_table[] = {
+	[0] = {
+		.index = 0,
+		.frequency = 200000,
+	},
+	[1] = {
+		.index = 1,
+		.frequency = 300000,
+	},
+	[2] = {
+		.index = 2,
+		.frequency = 600000,
+	},
+	[3] = {
+		/* Used for CPU_OPP_MAX, if available */
+		.index = 3,
+		.frequency = CPUFREQ_TABLE_END,
+	},
+	[4] = {
+		.index = 4,
+		.frequency = CPUFREQ_TABLE_END,
+	},
+};
+
+static enum prcmu_cpu_opp index2opp[] = {
+	CPU_OPP_EXT_CLK,
+	CPU_OPP_50,
+	CPU_OPP_100,
+	CPU_OPP_MAX
+};
+
+static int u8500_cpufreq_verify_speed(struct cpufreq_policy *policy)
+{
+	return cpufreq_frequency_table_verify(policy, freq_table);
+}
+
+static int u8500_cpufreq_target(struct cpufreq_policy *policy,
+				unsigned int target_freq,
+				unsigned int relation)
+{
+	struct cpufreq_freqs freqs;
+	unsigned int index;
+	int ret = 0;
+
+	/*
+	 * Ensure desired rate is within allowed range.  Some govenors
+	 * (ondemand) will just pass target_freq=0 to get the minimum.
+	 */
+	if (target_freq < policy->cpuinfo.min_freq)
+		target_freq = policy->cpuinfo.min_freq;
+	if (target_freq > policy->cpuinfo.max_freq)
+		target_freq = policy->cpuinfo.max_freq;
+
+	ret = cpufreq_frequency_table_target(policy, freq_table,
+					     target_freq, relation, &index);
+	if (ret < 0) {
+		dev_err(dev, "Could not look up next frequency\n");
+		return ret;
+	}
+
+	freqs.old = policy->cur;
+	freqs.new = freq_table[index].frequency;
+	freqs.cpu = policy->cpu;
+
+	if (freqs.old == freqs.new) {
+		dev_dbg(dev, "Current and target frequencies are equal\n");
+		return 0;
+	}
+
+	dev_dbg(dev, "transition: %u --> %u\n", freqs.old, freqs.new);
+	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+
+	ret = prcmu_set_cpu_opp(index2opp[index]);
+	if (ret < 0) {
+		dev_err(dev, "Failed to set OPP level\n");
+		return ret;
+	}
+
+	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+
+	return ret;
+}
+
+static unsigned int u8500_cpufreq_getspeed(unsigned int cpu)
+{
+	int i;
+
+	for (i = 0; prcmu_get_cpu_opp() != index2opp[i]; i++)
+		;
+	return freq_table[i].frequency;
+}
+
+static int __cpuinit u8500_cpu_init(struct cpufreq_policy *policy)
+{
+	int res;
+
+	BUILD_BUG_ON(ARRAY_SIZE(index2opp) + 1 != ARRAY_SIZE(freq_table));
+
+	if (cpu_is_u8500v2()) {
+		freq_table[1].frequency = 400000;
+		freq_table[2].frequency = 800000;
+		if (prcmu_has_arm_maxopp())
+			freq_table[3].frequency = 1000000;
+	}
+
+	/* get policy fields based on the table */
+	res = cpufreq_frequency_table_cpuinfo(policy, freq_table);
+	if (!res)
+		cpufreq_frequency_table_get_attr(freq_table, policy->cpu);
+	else {
+		dev_err(dev, "u8500-cpufreq : Failed to read policy table\n");
+		return res;
+	}
+
+	policy->min = policy->cpuinfo.min_freq;
+	policy->max = policy->cpuinfo.max_freq;
+	policy->cur = u8500_cpufreq_getspeed(policy->cpu);
+	policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
+
+	/*
+	 * FIXME : Need to take time measurement across the target()
+	 *	   function with no/some/all drivers in the notification
+	 *	   list.
+	 */
+	policy->cpuinfo.transition_latency = 200 * 1000; /* in ns */
+
+	/* policy sharing between dual CPUs */
+	cpumask_copy(policy->cpus, &cpu_present_map);
+
+	policy->shared_type = CPUFREQ_SHARED_TYPE_ALL;
+
+	return res;
+}
+
+static struct freq_attr *u8500_cpufreq_attr[] = {
+	&cpufreq_freq_attr_scaling_available_freqs,
+	NULL,
+};
+static int u8500_cpu_exit(struct cpufreq_policy *policy)
+{
+	cpufreq_frequency_table_put_attr(policy->cpu);
+	return 0;
+}
+
+static struct cpufreq_driver u8500_driver = {
+	.owner = THIS_MODULE,
+	.flags = CPUFREQ_STICKY,
+	.verify = u8500_cpufreq_verify_speed,
+	.target = u8500_cpufreq_target,
+	.get = u8500_cpufreq_getspeed,
+	.init = u8500_cpu_init,
+	.exit = u8500_cpu_exit,
+	.name = CPUFREQ_NAME,
+	.attr = u8500_cpufreq_attr,
+};
+
+static int __init u8500_cpufreq_probe(struct platform_device *pdev)
+{
+	dev = &pdev->dev;
+	return cpufreq_register_driver(&u8500_driver);
+}
+
+static int __exit u8500_cpufreq_remove(struct platform_device *pdev)
+{
+	return cpufreq_unregister_driver(&u8500_driver);
+}
+
+static struct platform_driver u8500_cpufreq_driver = {
+	.driver = {
+		.name	 = DRIVER_NAME,
+		.owner	 = THIS_MODULE,
+	},
+	.remove = __exit_p(u8500_cpufreq_remove),
+};
+
+static int __init u8500_cpufreq_init(void)
+{
+	return platform_driver_probe(&u8500_cpufreq_driver,
+				     &u8500_cpufreq_probe);
+}
+
+device_initcall(u8500_cpufreq_init);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-ux500/devices.c linux-libre-2.6.38-gnu1/arch/arm/mach-ux500/devices.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-ux500/devices.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-ux500/devices.c	2011-03-14 21:20:32.000000000 -0400
@@ -14,69 +14,6 @@
 #include <mach/hardware.h>
 #include <mach/setup.h>
 
-#define __MEM_4K_RESOURCE(x) \
-	.res = {.start = (x), .end = (x) + SZ_4K - 1, .flags = IORESOURCE_MEM}
-
-struct amba_device ux500_pl031_device = {
-	.dev = {
-		.init_name = "pl031",
-	},
-	.res = {
-		.start	= UX500_RTC_BASE,
-		.end	= UX500_RTC_BASE + SZ_4K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	.irq = {IRQ_RTC_RTT, NO_IRQ},
-};
-
-struct amba_device ux500_uart0_device = {
-	.dev = { .init_name = "uart0" },
-	__MEM_4K_RESOURCE(UX500_UART0_BASE),
-	.irq = {IRQ_UART0, NO_IRQ},
-};
-
-struct amba_device ux500_uart1_device = {
-	.dev = { .init_name = "uart1" },
-	__MEM_4K_RESOURCE(UX500_UART1_BASE),
-	.irq = {IRQ_UART1, NO_IRQ},
-};
-
-struct amba_device ux500_uart2_device = {
-	.dev = { .init_name = "uart2" },
-	__MEM_4K_RESOURCE(UX500_UART2_BASE),
-	.irq = {IRQ_UART2, NO_IRQ},
-};
-
-#define UX500_I2C_RESOURCES(id, size)				\
-static struct resource ux500_i2c##id##_resources[] = {		\
-	[0] = {							\
-		.start	= UX500_I2C##id##_BASE,			\
-		.end	= UX500_I2C##id##_BASE + size - 1,	\
-		.flags	= IORESOURCE_MEM,			\
-	},							\
-	[1] = {							\
-		.start	= IRQ_I2C##id,				\
-		.end	= IRQ_I2C##id,				\
-		.flags	= IORESOURCE_IRQ			\
-	}							\
-}
-
-UX500_I2C_RESOURCES(1, SZ_4K);
-UX500_I2C_RESOURCES(2, SZ_4K);
-UX500_I2C_RESOURCES(3, SZ_4K);
-
-#define UX500_I2C_PDEVICE(cid)					\
-struct platform_device ux500_i2c##cid##_device = {		\
-	.name		= "nmk-i2c",				\
-	.id		= cid,					\
-	.num_resources	= 2,					\
-	.resource	= ux500_i2c##cid##_resources,		\
-}
-
-UX500_I2C_PDEVICE(1);
-UX500_I2C_PDEVICE(2);
-UX500_I2C_PDEVICE(3);
-
 void __init amba_add_devices(struct amba_device *devs[], int num)
 {
 	int i;
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-ux500/devices-common.c linux-libre-2.6.38-gnu1/arch/arm/mach-ux500/devices-common.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-ux500/devices-common.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-ux500/devices-common.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+
+#include <linux/kernel.h>
+#include <linux/dma-mapping.h>
+#include <linux/err.h>
+#include <linux/irq.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/amba/bus.h>
+
+#include <plat/gpio.h>
+
+#include <mach/hardware.h>
+
+#include "devices-common.h"
+
+struct amba_device *
+dbx500_add_amba_device(const char *name, resource_size_t base,
+		       int irq, void *pdata, unsigned int periphid)
+{
+	struct amba_device *dev;
+	int ret;
+
+	dev = kzalloc(sizeof *dev, GFP_KERNEL);
+	if (!dev)
+		return ERR_PTR(-ENOMEM);
+
+	dev->dev.init_name = name;
+
+	dev->res.start = base;
+	dev->res.end = base + SZ_4K - 1;
+	dev->res.flags = IORESOURCE_MEM;
+
+	dev->dma_mask = DMA_BIT_MASK(32);
+	dev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
+
+	dev->irq[0] = irq;
+	dev->irq[1] = NO_IRQ;
+
+	dev->periphid = periphid;
+
+	dev->dev.platform_data = pdata;
+
+	ret = amba_device_register(dev, &iomem_resource);
+	if (ret) {
+		kfree(dev);
+		return ERR_PTR(ret);
+	}
+
+	return dev;
+}
+
+static struct platform_device *
+dbx500_add_platform_device(const char *name, int id, void *pdata,
+			   struct resource *res, int resnum)
+{
+	struct platform_device *dev;
+	int ret;
+
+	dev = platform_device_alloc(name, id);
+	if (!dev)
+		return ERR_PTR(-ENOMEM);
+
+	dev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
+	dev->dev.dma_mask = &dev->dev.coherent_dma_mask;
+
+	ret = platform_device_add_resources(dev, res, resnum);
+	if (ret)
+		goto out_free;
+
+	dev->dev.platform_data = pdata;
+
+	ret = platform_device_add(dev);
+	if (ret)
+		goto out_free;
+
+	return dev;
+
+out_free:
+	platform_device_put(dev);
+	return ERR_PTR(ret);
+}
+
+struct platform_device *
+dbx500_add_platform_device_4k1irq(const char *name, int id,
+				  resource_size_t base,
+				  int irq, void *pdata)
+{
+	struct resource resources[] = {
+		[0] = {
+			.start	= base,
+			.end	= base + SZ_4K - 1,
+			.flags	= IORESOURCE_MEM,
+		},
+		[1] = {
+			.start	= irq,
+			.end	= irq,
+			.flags	= IORESOURCE_IRQ,
+		}
+	};
+
+	return dbx500_add_platform_device(name, id, pdata, resources,
+					  ARRAY_SIZE(resources));
+}
+
+static struct platform_device *
+dbx500_add_gpio(int id, resource_size_t addr, int irq,
+		struct nmk_gpio_platform_data *pdata)
+{
+	struct resource resources[] = {
+		{
+			.start	= addr,
+			.end	= addr + 127,
+			.flags	= IORESOURCE_MEM,
+		},
+		{
+			.start	= irq,
+			.end	= irq,
+			.flags	= IORESOURCE_IRQ,
+		}
+	};
+
+	return platform_device_register_resndata(NULL, "gpio", id,
+				resources, ARRAY_SIZE(resources),
+				pdata, sizeof(*pdata));
+}
+
+void dbx500_add_gpios(resource_size_t *base, int num, int irq,
+		      struct nmk_gpio_platform_data *pdata)
+{
+	int first = 0;
+	int i;
+
+	for (i = 0; i < num; i++, first += 32, irq++) {
+		pdata->first_gpio = first;
+		pdata->first_irq = NOMADIK_GPIO_TO_IRQ(first);
+
+		dbx500_add_gpio(i, base[i], irq, pdata);
+	}
+}
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-ux500/devices-common.h linux-libre-2.6.38-gnu1/arch/arm/mach-ux500/devices-common.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-ux500/devices-common.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-ux500/devices-common.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+
+#ifndef __DEVICES_COMMON_H
+#define __DEVICES_COMMON_H
+
+extern struct amba_device *
+dbx500_add_amba_device(const char *name, resource_size_t base,
+		       int irq, void *pdata, unsigned int periphid);
+
+extern struct platform_device *
+dbx500_add_platform_device_4k1irq(const char *name, int id,
+				  resource_size_t base,
+				  int irq, void *pdata);
+
+struct spi_master_cntlr;
+
+static inline struct amba_device *
+dbx500_add_msp_spi(const char *name, resource_size_t base, int irq,
+		   struct spi_master_cntlr *pdata)
+{
+	return dbx500_add_amba_device(name, base, irq, pdata, 0);
+}
+
+static inline struct amba_device *
+dbx500_add_spi(const char *name, resource_size_t base, int irq,
+				   struct spi_master_cntlr *pdata)
+{
+	return dbx500_add_amba_device(name, base, irq, pdata, 0);
+}
+
+struct mmci_platform_data;
+
+static inline struct amba_device *
+dbx500_add_sdi(const char *name, resource_size_t base, int irq,
+	       struct mmci_platform_data *pdata)
+{
+	return dbx500_add_amba_device(name, base, irq, pdata, 0);
+}
+
+static inline struct amba_device *
+dbx500_add_uart(const char *name, resource_size_t base, int irq)
+{
+	return dbx500_add_amba_device(name, base, irq, NULL, 0);
+}
+
+struct nmk_i2c_controller;
+
+static inline struct platform_device *
+dbx500_add_i2c(int id, resource_size_t base, int irq,
+	       struct nmk_i2c_controller *pdata)
+{
+	return dbx500_add_platform_device_4k1irq("nmk-i2c", id, base, irq,
+						 pdata);
+}
+
+struct msp_i2s_platform_data;
+
+static inline struct platform_device *
+dbx500_add_msp_i2s(int id, resource_size_t base, int irq,
+		   struct msp_i2s_platform_data *pdata)
+{
+	return dbx500_add_platform_device_4k1irq("MSP_I2S", id, base, irq,
+						 pdata);
+}
+
+static inline struct amba_device *
+dbx500_add_rtc(resource_size_t base, int irq)
+{
+	return dbx500_add_amba_device("rtc-pl031", base, irq, NULL, 0);
+}
+
+struct nmk_gpio_platform_data;
+
+void dbx500_add_gpios(resource_size_t *base, int num, int irq,
+		      struct nmk_gpio_platform_data *pdata);
+
+#endif
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-ux500/devices-db5500.c linux-libre-2.6.38-gnu1/arch/arm/mach-ux500/devices-db5500.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-ux500/devices-db5500.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-ux500/devices-db5500.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) ST-Ericsson SA 2010
- *
- * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson
- * License terms: GNU General Public License (GPL) version 2
- */
-
-#include <linux/platform_device.h>
-#include <linux/interrupt.h>
-#include <linux/gpio.h>
-
-#include <mach/hardware.h>
-#include <mach/devices.h>
-
-static struct nmk_gpio_platform_data u5500_gpio_data[] = {
-	GPIO_DATA("GPIO-0-31", 0),
-	GPIO_DATA("GPIO-32-63", 32), /* 36..63 not routed to pin */
-	GPIO_DATA("GPIO-64-95", 64), /* 83..95 not routed to pin */
-	GPIO_DATA("GPIO-96-127", 96), /* 102..127 not routed to pin */
-	GPIO_DATA("GPIO-128-159", 128), /* 149..159 not routed to pin */
-	GPIO_DATA("GPIO-160-191", 160),
-	GPIO_DATA("GPIO-192-223", 192),
-	GPIO_DATA("GPIO-224-255", 224), /* 228..255 not routed to pin */
-};
-
-static struct resource u5500_gpio_resources[] = {
-	GPIO_RESOURCE(0),
-	GPIO_RESOURCE(1),
-	GPIO_RESOURCE(2),
-	GPIO_RESOURCE(3),
-	GPIO_RESOURCE(4),
-	GPIO_RESOURCE(5),
-	GPIO_RESOURCE(6),
-	GPIO_RESOURCE(7),
-};
-
-struct platform_device u5500_gpio_devs[] = {
-	GPIO_DEVICE(0),
-	GPIO_DEVICE(1),
-	GPIO_DEVICE(2),
-	GPIO_DEVICE(3),
-	GPIO_DEVICE(4),
-	GPIO_DEVICE(5),
-	GPIO_DEVICE(6),
-	GPIO_DEVICE(7),
-};
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-ux500/devices-db5500.h linux-libre-2.6.38-gnu1/arch/arm/mach-ux500/devices-db5500.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-ux500/devices-db5500.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-ux500/devices-db5500.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+
+#ifndef __DEVICES_DB5500_H
+#define __DEVICES_DB5500_H
+
+#include "devices-common.h"
+
+#define db5500_add_i2c1(pdata) \
+	dbx500_add_i2c(1, U5500_I2C1_BASE, IRQ_DB5500_I2C1, pdata)
+#define db5500_add_i2c2(pdata) \
+	dbx500_add_i2c(2, U5500_I2C2_BASE, IRQ_DB5500_I2C2, pdata)
+#define db5500_add_i2c3(pdata) \
+	dbx500_add_i2c(3, U5500_I2C3_BASE, IRQ_DB5500_I2C3, pdata)
+
+#define db5500_add_msp0_i2s(pdata) \
+	dbx500_add_msp_i2s(0, U5500_MSP0_BASE, IRQ_DB5500_MSP0, pdata)
+#define db5500_add_msp1_i2s(pdata) \
+	dbx500_add_msp_i2s(1, U5500_MSP1_BASE, IRQ_DB5500_MSP1, pdata)
+#define db5500_add_msp2_i2s(pdata) \
+	dbx500_add_msp_i2s(2, U5500_MSP2_BASE, IRQ_DB5500_MSP2, pdata)
+
+#define db5500_add_msp0_spi(pdata) \
+	dbx500_add_msp_spi("msp0", U5500_MSP0_BASE, IRQ_DB5500_MSP0, pdata)
+#define db5500_add_msp1_spi(pdata) \
+	dbx500_add_msp_spi("msp1", U5500_MSP1_BASE, IRQ_DB5500_MSP1, pdata)
+#define db5500_add_msp2_spi(pdata) \
+	dbx500_add_msp_spi("msp2", U5500_MSP2_BASE, IRQ_DB5500_MSP2, pdata)
+
+#define db5500_add_rtc() \
+	dbx500_add_rtc(U5500_RTC_BASE, IRQ_DB5500_RTC);
+
+#define db5500_add_sdi0(pdata) \
+	dbx500_add_sdi("sdi0", U5500_SDI0_BASE, IRQ_DB5500_SDMMC0, pdata)
+#define db5500_add_sdi1(pdata) \
+	dbx500_add_sdi("sdi1", U5500_SDI1_BASE, IRQ_DB5500_SDMMC1, pdata)
+#define db5500_add_sdi2(pdata) \
+	dbx500_add_sdi("sdi2", U5500_SDI2_BASE, IRQ_DB5500_SDMMC2, pdata)
+#define db5500_add_sdi3(pdata) \
+	dbx500_add_sdi("sdi3", U5500_SDI3_BASE, IRQ_DB5500_SDMMC3, pdata)
+#define db5500_add_sdi4(pdata) \
+	dbx500_add_sdi("sdi4", U5500_SDI4_BASE, IRQ_DB5500_SDMMC4, pdata)
+
+#define db5500_add_spi0(pdata) \
+	dbx500_add_spi("spi0", U5500_SPI0_BASE, IRQ_DB5500_SPI0, pdata)
+#define db5500_add_spi1(pdata) \
+	dbx500_add_spi("spi1", U5500_SPI1_BASE, IRQ_DB5500_SPI1, pdata)
+#define db5500_add_spi2(pdata) \
+	dbx500_add_spi("spi2", U5500_SPI2_BASE, IRQ_DB5500_SPI2, pdata)
+#define db5500_add_spi3(pdata) \
+	dbx500_add_spi("spi3", U5500_SPI3_BASE, IRQ_DB5500_SPI3, pdata)
+
+#define db5500_add_uart0() \
+	dbx500_add_uart("uart0", U5500_UART0_BASE, IRQ_DB5500_UART0)
+#define db5500_add_uart1() \
+	dbx500_add_uart("uart1", U5500_UART1_BASE, IRQ_DB5500_UART1)
+#define db5500_add_uart2() \
+	dbx500_add_uart("uart2", U5500_UART2_BASE, IRQ_DB5500_UART2)
+#define db5500_add_uart3() \
+	dbx500_add_uart("uart3", U5500_UART3_BASE, IRQ_DB5500_UART3)
+
+#endif
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-ux500/devices-db8500.c linux-libre-2.6.38-gnu1/arch/arm/mach-ux500/devices-db8500.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-ux500/devices-db8500.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-ux500/devices-db8500.c	2011-03-14 21:20:32.000000000 -0400
@@ -19,173 +19,6 @@
 
 #include "ste-dma40-db8500.h"
 
-static struct nmk_gpio_platform_data u8500_gpio_data[] = {
-	GPIO_DATA("GPIO-0-31", 0),
-	GPIO_DATA("GPIO-32-63", 32), /* 37..63 not routed to pin */
-	GPIO_DATA("GPIO-64-95", 64),
-	GPIO_DATA("GPIO-96-127", 96), /* 98..127 not routed to pin */
-	GPIO_DATA("GPIO-128-159", 128),
-	GPIO_DATA("GPIO-160-191", 160), /* 172..191 not routed to pin */
-	GPIO_DATA("GPIO-192-223", 192),
-	GPIO_DATA("GPIO-224-255", 224), /* 231..255 not routed to pin */
-	GPIO_DATA("GPIO-256-288", 256), /* 268..288 not routed to pin */
-};
-
-static struct resource u8500_gpio_resources[] = {
-	GPIO_RESOURCE(0),
-	GPIO_RESOURCE(1),
-	GPIO_RESOURCE(2),
-	GPIO_RESOURCE(3),
-	GPIO_RESOURCE(4),
-	GPIO_RESOURCE(5),
-	GPIO_RESOURCE(6),
-	GPIO_RESOURCE(7),
-	GPIO_RESOURCE(8),
-};
-
-struct platform_device u8500_gpio_devs[] = {
-	GPIO_DEVICE(0),
-	GPIO_DEVICE(1),
-	GPIO_DEVICE(2),
-	GPIO_DEVICE(3),
-	GPIO_DEVICE(4),
-	GPIO_DEVICE(5),
-	GPIO_DEVICE(6),
-	GPIO_DEVICE(7),
-	GPIO_DEVICE(8),
-};
-
-struct amba_device u8500_ssp0_device = {
-	.dev = {
-		.coherent_dma_mask = ~0,
-		.init_name = "ssp0",
-	},
-	.res = {
-		.start = U8500_SSP0_BASE,
-		.end   = U8500_SSP0_BASE + SZ_4K - 1,
-		.flags = IORESOURCE_MEM,
-	},
-	.irq = {IRQ_DB8500_SSP0, NO_IRQ },
-	/* ST-Ericsson modified id */
-	.periphid = SSP_PER_ID,
-};
-
-static struct resource u8500_i2c0_resources[] = {
-	[0] = {
-		.start	= U8500_I2C0_BASE,
-		.end	= U8500_I2C0_BASE + SZ_4K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= IRQ_DB8500_I2C0,
-		.end	= IRQ_DB8500_I2C0,
-		.flags	= IORESOURCE_IRQ,
-	}
-};
-
-struct platform_device u8500_i2c0_device = {
-	.name		= "nmk-i2c",
-	.id		= 0,
-	.resource	= u8500_i2c0_resources,
-	.num_resources	= ARRAY_SIZE(u8500_i2c0_resources),
-};
-
-static struct resource u8500_i2c4_resources[] = {
-	[0] = {
-		.start	= U8500_I2C4_BASE,
-		.end	= U8500_I2C4_BASE + SZ_4K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= IRQ_DB8500_I2C4,
-		.end	= IRQ_DB8500_I2C4,
-		.flags	= IORESOURCE_IRQ,
-	}
-};
-
-struct platform_device u8500_i2c4_device = {
-	.name		= "nmk-i2c",
-	.id		= 4,
-	.resource	= u8500_i2c4_resources,
-	.num_resources	= ARRAY_SIZE(u8500_i2c4_resources),
-};
-
-/*
- * SD/MMC
- */
-
-struct amba_device u8500_sdi0_device = {
-	.dev		= {
-		.init_name = "sdi0",
-	},
-	.res		= {
-		.start	= U8500_SDI0_BASE,
-		.end	= U8500_SDI0_BASE + SZ_4K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	.irq		= {IRQ_DB8500_SDMMC0, NO_IRQ},
-};
-
-struct amba_device u8500_sdi1_device = {
-	.dev		= {
-		.init_name = "sdi1",
-	},
-	.res		= {
-		.start	= U8500_SDI1_BASE,
-		.end	= U8500_SDI1_BASE + SZ_4K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	.irq		= {IRQ_DB8500_SDMMC1, NO_IRQ},
-};
-
-struct amba_device u8500_sdi2_device = {
-	.dev		= {
-		.init_name = "sdi2",
-	},
-	.res		= {
-		.start	= U8500_SDI2_BASE,
-		.end	= U8500_SDI2_BASE + SZ_4K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	.irq		= {IRQ_DB8500_SDMMC2, NO_IRQ},
-};
-
-struct amba_device u8500_sdi3_device = {
-	.dev		= {
-		.init_name = "sdi3",
-	},
-	.res		= {
-		.start	= U8500_SDI3_BASE,
-		.end	= U8500_SDI3_BASE + SZ_4K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	.irq		= {IRQ_DB8500_SDMMC3, NO_IRQ},
-};
-
-struct amba_device u8500_sdi4_device = {
-	.dev		= {
-		.init_name = "sdi4",
-	},
-	.res		= {
-		.start	= U8500_SDI4_BASE,
-		.end	= U8500_SDI4_BASE + SZ_4K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	.irq		= {IRQ_DB8500_SDMMC4, NO_IRQ},
-};
-
-struct amba_device u8500_sdi5_device = {
-	.dev		= {
-		.init_name = "sdi5",
-	},
-	.res		= {
-		.start	= U8500_SDI5_BASE,
-		.end	= U8500_SDI5_BASE + SZ_4K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	.irq		= {IRQ_DB8500_SDMMC5, NO_IRQ},
-};
-
 static struct resource dma40_resources[] = {
 	[0] = {
 		.start = U8500_DMA_BASE,
@@ -295,7 +128,7 @@ struct resource keypad_resources[] = {
 	},
 };
 
-struct platform_device ux500_ske_keypad_device = {
+struct platform_device u8500_ske_keypad_device = {
 	.name = "nmk-ske-keypad",
 	.id = -1,
 	.num_resources = ARRAY_SIZE(keypad_resources),
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-ux500/devices-db8500.h linux-libre-2.6.38-gnu1/arch/arm/mach-ux500/devices-db8500.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-ux500/devices-db8500.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-ux500/devices-db8500.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+
+#ifndef __DEVICES_DB8500_H
+#define __DEVICES_DB8500_H
+
+#include "devices-common.h"
+
+struct ske_keypad_platform_data;
+struct pl022_ssp_controller;
+
+static inline struct platform_device *
+db8500_add_ske_keypad(struct ske_keypad_platform_data *pdata)
+{
+	return dbx500_add_platform_device_4k1irq("nmk-ske-keypad", -1,
+						 U8500_SKE_BASE,
+						 IRQ_DB8500_KB, pdata);
+}
+
+static inline struct amba_device *
+db8500_add_ssp(const char *name, resource_size_t base, int irq,
+	       struct pl022_ssp_controller *pdata)
+{
+	return dbx500_add_amba_device(name, base, irq, pdata, SSP_PER_ID);
+}
+
+
+#define db8500_add_i2c0(pdata) \
+	dbx500_add_i2c(0, U8500_I2C0_BASE, IRQ_DB8500_I2C0, pdata)
+#define db8500_add_i2c1(pdata) \
+	dbx500_add_i2c(1, U8500_I2C1_BASE, IRQ_DB8500_I2C1, pdata)
+#define db8500_add_i2c2(pdata) \
+	dbx500_add_i2c(2, U8500_I2C2_BASE, IRQ_DB8500_I2C2, pdata)
+#define db8500_add_i2c3(pdata) \
+	dbx500_add_i2c(3, U8500_I2C3_BASE, IRQ_DB8500_I2C3, pdata)
+#define db8500_add_i2c4(pdata) \
+	dbx500_add_i2c(4, U8500_I2C4_BASE, IRQ_DB8500_I2C4, pdata)
+
+#define db8500_add_msp0_i2s(pdata) \
+	dbx500_add_msp_i2s(0, U8500_MSP0_BASE, IRQ_DB8500_MSP0, pdata)
+#define db8500_add_msp1_i2s(pdata) \
+	dbx500_add_msp_i2s(1, U8500_MSP1_BASE, IRQ_DB8500_MSP1, pdata)
+#define db8500_add_msp2_i2s(pdata) \
+	dbx500_add_msp_i2s(2, U8500_MSP2_BASE, IRQ_DB8500_MSP2, pdata)
+#define db8500_add_msp3_i2s(pdata) \
+	dbx500_add_msp_i2s(3, U8500_MSP3_BASE, IRQ_DB8500_MSP1, pdata)
+
+#define db8500_add_msp0_spi(pdata) \
+	dbx500_add_msp_spi("msp0", U8500_MSP0_BASE, IRQ_DB8500_MSP0, pdata)
+#define db8500_add_msp1_spi(pdata) \
+	dbx500_add_msp_spi("msp1", U8500_MSP1_BASE, IRQ_DB8500_MSP1, pdata)
+#define db8500_add_msp2_spi(pdata) \
+	dbx500_add_msp_spi("msp2", U8500_MSP2_BASE, IRQ_DB8500_MSP2, pdata)
+#define db8500_add_msp3_spi(pdata) \
+	dbx500_add_msp_spi("msp3", U8500_MSP3_BASE, IRQ_DB8500_MSP1, pdata)
+
+#define db8500_add_rtc() \
+	dbx500_add_rtc(U8500_RTC_BASE, IRQ_DB8500_RTC);
+
+#define db8500_add_sdi0(pdata) \
+	dbx500_add_sdi("sdi0", U8500_SDI0_BASE, IRQ_DB8500_SDMMC0, pdata)
+#define db8500_add_sdi1(pdata) \
+	dbx500_add_sdi("sdi1", U8500_SDI1_BASE, IRQ_DB8500_SDMMC1, pdata)
+#define db8500_add_sdi2(pdata) \
+	dbx500_add_sdi("sdi2", U8500_SDI2_BASE, IRQ_DB8500_SDMMC2, pdata)
+#define db8500_add_sdi3(pdata) \
+	dbx500_add_sdi("sdi3", U8500_SDI3_BASE, IRQ_DB8500_SDMMC3, pdata)
+#define db8500_add_sdi4(pdata) \
+	dbx500_add_sdi("sdi4", U8500_SDI4_BASE, IRQ_DB8500_SDMMC4, pdata)
+#define db8500_add_sdi5(pdata) \
+	dbx500_add_sdi("sdi5", U8500_SDI5_BASE, IRQ_DB8500_SDMMC5, pdata)
+
+#define db8500_add_ssp0(pdata) \
+	db8500_add_ssp("ssp0", U8500_SSP0_BASE, IRQ_DB8500_SSP0, pdata)
+#define db8500_add_ssp1(pdata) \
+	db8500_add_ssp("ssp1", U8500_SSP1_BASE, IRQ_DB8500_SSP1, pdata)
+
+#define db8500_add_spi0(pdata) \
+	dbx500_add_spi("spi0", U8500_SPI0_BASE, IRQ_DB8500_SPI0, pdata)
+#define db8500_add_spi1(pdata) \
+	dbx500_add_spi("spi1", U8500_SPI1_BASE, IRQ_DB8500_SPI1, pdata)
+#define db8500_add_spi2(pdata) \
+	dbx500_add_spi("spi2", U8500_SPI2_BASE, IRQ_DB8500_SPI2, pdata)
+#define db8500_add_spi3(pdata) \
+	dbx500_add_spi("spi3", U8500_SPI3_BASE, IRQ_DB8500_SPI3, pdata)
+
+#define db8500_add_uart0() \
+	dbx500_add_uart("uart0", U8500_UART0_BASE, IRQ_DB8500_UART0)
+#define db8500_add_uart1() \
+	dbx500_add_uart("uart1", U8500_UART1_BASE, IRQ_DB8500_UART1)
+#define db8500_add_uart2() \
+	dbx500_add_uart("uart2", U8500_UART2_BASE, IRQ_DB8500_UART2)
+
+#endif
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-ux500/dma-db5500.c linux-libre-2.6.38-gnu1/arch/arm/mach-ux500/dma-db5500.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-ux500/dma-db5500.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-ux500/dma-db5500.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * Author: Per Forlin <per.forlin@stericsson.com> for ST-Ericsson
+ * Author: Jonas Aaberg <jonas.aberg@stericsson.com> for ST-Ericsson
+ * Author: Rabin Vincent <rabinv.vincent@stericsson.com> for ST-Ericsson
+ *
+ * License terms: GNU General Public License (GPL), version 2
+ */
+
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+
+#include <plat/ste_dma40.h>
+#include <mach/setup.h>
+#include <mach/hardware.h>
+
+#include "ste-dma40-db5500.h"
+
+static struct resource dma40_resources[] = {
+	[0] = {
+		.start = U5500_DMA_BASE,
+		.end   = U5500_DMA_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+		.name  = "base",
+	},
+	[1] = {
+		.start = U5500_DMA_LCPA_BASE,
+		.end   = U5500_DMA_LCPA_BASE + 2 * SZ_1K - 1,
+		.flags = IORESOURCE_MEM,
+		.name  = "lcpa",
+	},
+	[2] = {
+		.start = IRQ_DB5500_DMA,
+		.end   = IRQ_DB5500_DMA,
+		.flags = IORESOURCE_IRQ
+	}
+};
+
+/* Default configuration for physical memcpy */
+static struct stedma40_chan_cfg dma40_memcpy_conf_phy = {
+	.mode = STEDMA40_MODE_PHYSICAL,
+	.dir = STEDMA40_MEM_TO_MEM,
+
+	.src_info.data_width = STEDMA40_BYTE_WIDTH,
+	.src_info.psize = STEDMA40_PSIZE_PHY_1,
+	.src_info.flow_ctrl = STEDMA40_NO_FLOW_CTRL,
+
+	.dst_info.data_width = STEDMA40_BYTE_WIDTH,
+	.dst_info.psize = STEDMA40_PSIZE_PHY_1,
+	.dst_info.flow_ctrl = STEDMA40_NO_FLOW_CTRL,
+};
+
+/* Default configuration for logical memcpy */
+static struct stedma40_chan_cfg dma40_memcpy_conf_log = {
+	.dir = STEDMA40_MEM_TO_MEM,
+
+	.src_info.data_width = STEDMA40_BYTE_WIDTH,
+	.src_info.psize = STEDMA40_PSIZE_LOG_1,
+	.src_info.flow_ctrl = STEDMA40_NO_FLOW_CTRL,
+
+	.dst_info.data_width = STEDMA40_BYTE_WIDTH,
+	.dst_info.psize = STEDMA40_PSIZE_LOG_1,
+	.dst_info.flow_ctrl = STEDMA40_NO_FLOW_CTRL,
+};
+
+/*
+ * Mapping between soruce event lines and physical device address This was
+ * created assuming that the event line is tied to a device and therefore the
+ * address is constant, however this is not true for at least USB, and the
+ * values are just placeholders for USB.  This table is preserved and used for
+ * now.
+ */
+static const dma_addr_t dma40_rx_map[DB5500_DMA_NR_DEV] = {
+	[DB5500_DMA_DEV24_SDMMC0_RX] = -1,
+};
+
+/* Mapping between destination event lines and physical device address */
+static const dma_addr_t dma40_tx_map[DB5500_DMA_NR_DEV] = {
+	[DB5500_DMA_DEV24_SDMMC0_TX] = -1,
+};
+
+static int dma40_memcpy_event[] = {
+	DB5500_DMA_MEMCPY_TX_1,
+	DB5500_DMA_MEMCPY_TX_2,
+	DB5500_DMA_MEMCPY_TX_3,
+	DB5500_DMA_MEMCPY_TX_4,
+	DB5500_DMA_MEMCPY_TX_5,
+};
+
+static struct stedma40_platform_data dma40_plat_data = {
+	.dev_len		= ARRAY_SIZE(dma40_rx_map),
+	.dev_rx			= dma40_rx_map,
+	.dev_tx			= dma40_tx_map,
+	.memcpy			= dma40_memcpy_event,
+	.memcpy_len		= ARRAY_SIZE(dma40_memcpy_event),
+	.memcpy_conf_phy	= &dma40_memcpy_conf_phy,
+	.memcpy_conf_log	= &dma40_memcpy_conf_log,
+	.disabled_channels	= {-1},
+};
+
+static struct platform_device dma40_device = {
+	.dev = {
+		.platform_data = &dma40_plat_data,
+	},
+	.name		= "dma40",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(dma40_resources),
+	.resource	= dma40_resources
+};
+
+void __init db5500_dma_init(void)
+{
+	int ret;
+
+	ret = platform_device_register(&dma40_device);
+	if (ret)
+		dev_err(&dma40_device.dev, "unable to register device: %d\n", ret);
+
+}
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-ux500/headsmp.S linux-libre-2.6.38-gnu1/arch/arm/mach-ux500/headsmp.S
--- linux-libre-2.6.37-gnu1/arch/arm/mach-ux500/headsmp.S	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-ux500/headsmp.S	2011-03-14 21:20:32.000000000 -0400
@@ -23,7 +23,6 @@ ENTRY(u8500_secondary_startup)
 	ldmia	r4, {r5, r6}
 	sub	r4, r4, r5
 	add	r6, r6, r4
-	dsb
 pen:	ldr	r7, [r6]
 	cmp	r7, r0
 	bne	pen
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-ux500/hotplug.c linux-libre-2.6.38-gnu1/arch/arm/mach-ux500/hotplug.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-ux500/hotplug.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-ux500/hotplug.c	2011-03-14 21:20:32.000000000 -0400
@@ -11,14 +11,11 @@
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/smp.h>
-#include <linux/completion.h>
 
 #include <asm/cacheflush.h>
 
 extern volatile int pen_release;
 
-static DECLARE_COMPLETION(cpu_killed);
-
 static inline void platform_do_lowpower(unsigned int cpu)
 {
 	flush_cache_all();
@@ -38,7 +35,7 @@ static inline void platform_do_lowpower(
 
 int platform_cpu_kill(unsigned int cpu)
 {
-	return wait_for_completion_timeout(&cpu_killed, 5000);
+	return 1;
 }
 
 /*
@@ -48,19 +45,6 @@ int platform_cpu_kill(unsigned int cpu)
  */
 void platform_cpu_die(unsigned int cpu)
 {
-#ifdef DEBUG
-	unsigned int this_cpu = hard_smp_processor_id();
-
-	if (cpu != this_cpu) {
-		printk(KERN_CRIT "Eek! platform_cpu_die running on %u, should be %u\n",
-			   this_cpu, cpu);
-		BUG();
-	}
-#endif
-
-	printk(KERN_NOTICE "CPU%u: shutdown\n", cpu);
-	complete(&cpu_killed);
-
 	/* directly enter low power state, skipping secure registers */
 	platform_do_lowpower(cpu);
 }
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-ux500/id.c linux-libre-2.6.38-gnu1/arch/arm/mach-ux500/id.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-ux500/id.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-ux500/id.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/io.h>
+
+#include <asm/cputype.h>
+#include <asm/tlbflush.h>
+#include <asm/cacheflush.h>
+#include <asm/mach/map.h>
+
+#include <mach/hardware.h>
+#include <mach/setup.h>
+
+struct dbx500_asic_id dbx500_id;
+
+static unsigned int ux500_read_asicid(phys_addr_t addr)
+{
+	phys_addr_t base = addr & ~0xfff;
+	struct map_desc desc = {
+		.virtual	= IO_ADDRESS(base),
+		.pfn		= __phys_to_pfn(base),
+		.length		= SZ_16K,
+		.type		= MT_DEVICE,
+	};
+
+	iotable_init(&desc, 1);
+
+	/* As in devicemaps_init() */
+	local_flush_tlb_all();
+	flush_cache_all();
+
+	return readl(__io_address(addr));
+}
+
+static void ux500_print_soc_info(unsigned int asicid)
+{
+	unsigned int rev = dbx500_revision();
+
+	pr_info("DB%4x ", dbx500_partnumber());
+
+	if (rev == 0x01)
+		pr_cont("Early Drop");
+	else if (rev >= 0xA0)
+		pr_cont("v%d.%d" , (rev >> 4) - 0xA + 1, rev & 0xf);
+	else
+		pr_cont("Unknown");
+
+	pr_cont(" [%#010x]\n", asicid);
+}
+
+static unsigned int partnumber(unsigned int asicid)
+{
+	return (asicid >> 8) & 0xffff;
+}
+
+/*
+ * SOC		MIDR		ASICID ADDRESS		ASICID VALUE
+ * DB8500ed	0x410fc090	0x9001FFF4		0x00850001
+ * DB8500v1	0x411fc091	0x9001FFF4		0x008500A0
+ * DB8500v1.1	0x411fc091	0x9001FFF4		0x008500A1
+ * DB8500v2	0x412fc091	0x9001DBF4		0x008500B0
+ * DB5500v1	0x412fc091	0x9001FFF4		0x005500A0
+ */
+
+void __init ux500_map_io(void)
+{
+	unsigned int cpuid = read_cpuid_id();
+	unsigned int asicid = 0;
+	phys_addr_t addr = 0;
+
+	switch (cpuid) {
+	case 0x410fc090: /* DB8500ed */
+	case 0x411fc091: /* DB8500v1 */
+		addr = 0x9001FFF4;
+		break;
+
+	case 0x412fc091: /* DB8500v2 / DB5500v1 */
+		asicid = ux500_read_asicid(0x9001DBF4);
+		if (partnumber(asicid) == 0x8500)
+			/* DB8500v2 */
+			break;
+
+		/* DB5500v1 */
+		addr = 0x9001FFF4;
+		break;
+	}
+
+	if (addr)
+		asicid = ux500_read_asicid(addr);
+
+	if (!asicid) {
+		pr_err("Unable to identify SoC\n");
+		ux500_unknown_soc();
+	}
+
+	dbx500_id.process = asicid >> 24;
+	dbx500_id.partnumber = partnumber(asicid);
+	dbx500_id.revision = asicid & 0xff;
+
+	ux500_print_soc_info(asicid);
+}
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-ux500/include/mach/db5500-regs.h linux-libre-2.6.38-gnu1/arch/arm/mach-ux500/include/mach/db5500-regs.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-ux500/include/mach/db5500-regs.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-ux500/include/mach/db5500-regs.h	2011-03-14 21:20:32.000000000 -0400
@@ -114,4 +114,8 @@
 #define U5500_MBOX2_LOCAL_START	(U5500_MBOX_BASE + 0x20)
 #define U5500_MBOX2_LOCAL_END	(U5500_MBOX_BASE + 0x3F)
 
+#define U5500_ESRAM_BASE		0x40000000
+#define U5500_ESRAM_DMA_LCPA_OFFSET	0x10000
+#define U5500_DMA_LCPA_BASE    (U5500_ESRAM_BASE + U5500_ESRAM_DMA_LCPA_OFFSET)
+
 #endif
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-ux500/include/mach/db8500-regs.h linux-libre-2.6.38-gnu1/arch/arm/mach-ux500/include/mach/db8500-regs.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-ux500/include/mach/db8500-regs.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-ux500/include/mach/db8500-regs.h	2011-03-14 21:20:32.000000000 -0400
@@ -92,7 +92,8 @@
 #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_TCDM_BASE	(U8500_PER4_BASE + 0x0f000)
+#define U8500_PRCMU_TCDM_BASE_V1 (U8500_PER4_BASE + 0x0f000)
+#define U8500_PRCMU_TCDM_BASE   (U8500_PER4_BASE + 0x68000)
 
 /* per3 base addresses */
 #define U8500_FSMC_BASE		(U8500_PER3_BASE + 0x0000)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-ux500/include/mach/debug-macro.S linux-libre-2.6.38-gnu1/arch/arm/mach-ux500/include/mach/debug-macro.S
--- linux-libre-2.6.37-gnu1/arch/arm/mach-ux500/include/mach/debug-macro.S	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-ux500/include/mach/debug-macro.S	2011-03-14 21:20:32.000000000 -0400
@@ -14,7 +14,24 @@
 #error Invalid Ux500 debug UART
 #endif
 
-#define __UX500_UART(n)	UX500_UART##n##_BASE
+/*
+ * DEBUG_LL only works if only one SOC is built in.  We don't use #else below
+ * in order to get "__UX500_UART redefined" warnings if more than one SOC is
+ * built, so that there's some hint during the build that something is wrong.
+ */
+
+#ifdef CONFIG_UX500_SOC_DB5500
+#define __UX500_UART(n)	U5500_UART##n##_BASE
+#endif
+
+#ifdef CONFIG_UX500_SOC_DB8500
+#define __UX500_UART(n)	U8500_UART##n##_BASE
+#endif
+
+#ifndef __UX500_UART
+#error Unknown SOC
+#endif
+
 #define UX500_UART(n)	__UX500_UART(n)
 #define UART_BASE	UX500_UART(CONFIG_UX500_DEBUG_UART)
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-ux500/include/mach/devices.h linux-libre-2.6.38-gnu1/arch/arm/mach-ux500/include/mach/devices.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-ux500/include/mach/devices.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-ux500/include/mach/devices.h	2011-03-14 21:20:32.000000000 -0400
@@ -14,27 +14,10 @@ extern struct platform_device u5500_gpio
 extern struct platform_device u8500_gpio_devs[];
 
 extern struct amba_device ux500_pl031_device;
-extern struct amba_device u8500_ssp0_device;
-extern struct amba_device ux500_uart0_device;
-extern struct amba_device ux500_uart1_device;
-extern struct amba_device ux500_uart2_device;
 
-extern struct platform_device ux500_i2c1_device;
-extern struct platform_device ux500_i2c2_device;
-extern struct platform_device ux500_i2c3_device;
-
-extern struct platform_device u8500_i2c0_device;
-extern struct platform_device u8500_i2c4_device;
 extern struct platform_device u8500_dma40_device;
 extern struct platform_device ux500_ske_keypad_device;
 
-extern struct amba_device u8500_sdi0_device;
-extern struct amba_device u8500_sdi1_device;
-extern struct amba_device u8500_sdi2_device;
-extern struct amba_device u8500_sdi3_device;
-extern struct amba_device u8500_sdi4_device;
-extern struct amba_device u8500_sdi5_device;
-
 void dma40_u8500ed_fixup(void);
 
 #endif
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-ux500/include/mach/entry-macro.S linux-libre-2.6.38-gnu1/arch/arm/mach-ux500/include/mach/entry-macro.S
--- linux-libre-2.6.37-gnu1/arch/arm/mach-ux500/include/mach/entry-macro.S	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-ux500/include/mach/entry-macro.S	2011-03-14 21:20:32.000000000 -0400
@@ -11,79 +11,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, =IO_ADDRESS(UX500_GIC_CPU_BASE)
-		.endm
-
 		.macro  arch_ret_to_user, tmp1, tmp2
 		.endm
-
-		/*
-		 * The interrupt numbering scheme is defined in the
-		 * interrupt controller spec.  To wit:
-		 *
-		 * Interrupts 0-15 are IPI
-		 * 16-28 are reserved
-		 * 29-31 are local.  We allow 30 to be used for the watchdog.
-		 * 32-1020 are global
-		 * 1021-1022 are reserved
-		 * 1023 is "spurious" (no interrupt)
-		 *
-		 * For now, we ignore all local interrupts so only return an
-		 * interrupt if it's between 30 and 1020. The test_for_ipi
-		 * routine below will pick up on IPIs.
-		 *
-		 * A simple read from the controller will tell us the number
-		 * of the highest priority enabled interrupt. We then just
-		 * need to check whether it is in the valid range for an
-		 * IRQ (30-1020 inclusive).
-		 */
-
-		.macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
-
-		/* bits 12-10 = src CPU, 9-0 = int # */
-		ldr     \irqstat, [\base, #GIC_CPU_INTACK]
-
-		ldr	\tmp, =1021
-
-		bic     \irqnr, \irqstat, #0x1c00
-
-		cmp     \irqnr, #29
-		cmpcc	\irqnr, \irqnr
-		cmpne	\irqnr, \tmp
-		cmpcs	\irqnr, \irqnr
-
-		.endm
-
-		/* We assume that irqstat (the raw value of the IRQ
-		 * acknowledge register) is preserved from the macro above.
-		 * If there is an IPI, we immediately signal end of
-		 * interrupt on the controller, since this requires the
-		 * original irqstat value which we won't easily be able
-		 * to recreate later.
-		 */
-
-		.macro test_for_ipi, irqnr, irqstat, base, tmp
-		bic	\irqnr, \irqstat, #0x1c00
-		cmp	\irqnr, #16
-		strcc	\irqstat, [\base, #GIC_CPU_EOI]
-		cmpcs	\irqnr, \irqnr
-		.endm
-
-		/* As above, this assumes that irqstat and base
-		 * are preserved..
-		 */
-
-		.macro test_for_ltirq, irqnr, irqstat, base, tmp
-		bic	\irqnr, \irqstat, #0x1c00
-		mov 	\tmp, #0
-		cmp	\irqnr, #29
-		moveq	\tmp, #1
-		streq	\irqstat, [\base, #GIC_CPU_EOI]
-		cmp	\tmp, #0
-		.endm
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-ux500/include/mach/gpio.h linux-libre-2.6.38-gnu1/arch/arm/mach-ux500/include/mach/gpio.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-ux500/include/mach/gpio.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-ux500/include/mach/gpio.h	2011-03-14 21:20:32.000000000 -0400
@@ -9,42 +9,4 @@
 
 #include <plat/gpio.h>
 
-#define __GPIO_RESOURCE(soc, block)					\
-	{								\
-		.start	= soc##_GPIOBANK##block##_BASE,			\
-		.end	= soc##_GPIOBANK##block##_BASE + 127,		\
-		.flags	= IORESOURCE_MEM,				\
-	},								\
-	{								\
-		.start	= IRQ_GPIO##block,				\
-		.end	= IRQ_GPIO##block,				\
-		.flags	= IORESOURCE_IRQ,				\
-	}
-
-#define __GPIO_DEVICE(soc, block)					\
-	{								\
-		.name		= "gpio",				\
-		.id		= block,				\
-		.num_resources	= 2,					\
-		.resource	= &soc##_gpio_resources[block * 2],	\
-		.dev = {						\
-			.platform_data = &soc##_gpio_data[block],	\
-		},							\
-	}
-
-#define GPIO_DATA(_name, first)						\
-	{								\
-		.name		= _name,				\
-		.first_gpio	= first,				\
-		.first_irq	= NOMADIK_GPIO_TO_IRQ(first),		\
-	}
-
-#ifdef CONFIG_UX500_SOC_DB8500
-#define GPIO_RESOURCE(block)	__GPIO_RESOURCE(U8500, block)
-#define GPIO_DEVICE(block)	__GPIO_DEVICE(u8500, block)
-#elif defined(CONFIG_UX500_SOC_DB5500)
-#define GPIO_RESOURCE(block)	__GPIO_RESOURCE(U5500, block)
-#define GPIO_DEVICE(block)	__GPIO_DEVICE(u5500, block)
-#endif
-
 #endif /* __ASM_ARCH_GPIO_H */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-ux500/include/mach/hardware.h linux-libre-2.6.38-gnu1/arch/arm/mach-ux500/include/mach/hardware.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-ux500/include/mach/hardware.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-ux500/include/mach/hardware.h	2011-03-14 21:20:32.000000000 -0400
@@ -29,118 +29,14 @@
 #include <mach/db8500-regs.h>
 #include <mach/db5500-regs.h>
 
-#ifdef CONFIG_UX500_SOC_DB8500
-#define UX500(periph)		U8500_##periph##_BASE
-#elif defined(CONFIG_UX500_SOC_DB5500)
-#define UX500(periph)		U5500_##periph##_BASE
-#endif
-
-#define UX500_BACKUPRAM0_BASE	UX500(BACKUPRAM0)
-#define UX500_BACKUPRAM1_BASE	UX500(BACKUPRAM1)
-#define UX500_B2R2_BASE		UX500(B2R2)
-
-#define UX500_CLKRST1_BASE	UX500(CLKRST1)
-#define UX500_CLKRST2_BASE	UX500(CLKRST2)
-#define UX500_CLKRST3_BASE	UX500(CLKRST3)
-#define UX500_CLKRST5_BASE	UX500(CLKRST5)
-#define UX500_CLKRST6_BASE	UX500(CLKRST6)
-
-#define UX500_DMA_BASE		UX500(DMA)
-#define UX500_FSMC_BASE		UX500(FSMC)
-
-#define UX500_GIC_CPU_BASE	UX500(GIC_CPU)
-#define UX500_GIC_DIST_BASE	UX500(GIC_DIST)
-
-#define UX500_I2C1_BASE		UX500(I2C1)
-#define UX500_I2C2_BASE		UX500(I2C2)
-#define UX500_I2C3_BASE		UX500(I2C3)
-
-#define UX500_L2CC_BASE		UX500(L2CC)
-#define UX500_MCDE_BASE		UX500(MCDE)
-#define UX500_MTU0_BASE		UX500(MTU0)
-#define UX500_MTU1_BASE		UX500(MTU1)
-#define UX500_PRCMU_BASE	UX500(PRCMU)
-
-#define UX500_RNG_BASE		UX500(RNG)
-#define UX500_RTC_BASE		UX500(RTC)
-
-#define UX500_SCU_BASE		UX500(SCU)
-
-#define UX500_SDI0_BASE		UX500(SDI0)
-#define UX500_SDI1_BASE		UX500(SDI1)
-#define UX500_SDI2_BASE		UX500(SDI2)
-#define UX500_SDI3_BASE		UX500(SDI3)
-#define UX500_SDI4_BASE		UX500(SDI4)
-
-#define UX500_SPI0_BASE		UX500(SPI0)
-#define UX500_SPI1_BASE		UX500(SPI1)
-#define UX500_SPI2_BASE		UX500(SPI2)
-#define UX500_SPI3_BASE		UX500(SPI3)
-
-#define UX500_SIA_BASE		UX500(SIA)
-#define UX500_SVA_BASE		UX500(SVA)
-
-#define UX500_TWD_BASE		UX500(TWD)
-
-#define UX500_UART0_BASE	UX500(UART0)
-#define UX500_UART1_BASE	UX500(UART1)
-#define UX500_UART2_BASE	UX500(UART2)
-
-#define UX500_USBOTG_BASE	UX500(USBOTG)
-
 /* ST-Ericsson modified pl022 id */
 #define SSP_PER_ID		0x01080022
 
 #ifndef __ASSEMBLY__
 
-#include <asm/cputype.h>
-
-static inline bool cpu_is_u8500(void)
-{
-#ifdef CONFIG_UX500_SOC_DB8500
-	return 1;
-#else
-	return 0;
-#endif
-}
-
-#define CPUID_DB8500ED	0x410fc090
-#define CPUID_DB8500V1	0x411fc091
-#define CPUID_DB8500V2	0x412fc091
-
-static inline bool cpu_is_u8500ed(void)
-{
-	return cpu_is_u8500() && (read_cpuid_id() == CPUID_DB8500ED);
-}
-
-static inline bool cpu_is_u8500v1(void)
-{
-	return cpu_is_u8500() && (read_cpuid_id() == CPUID_DB8500V1);
-}
-
-static inline bool cpu_is_u8500v2(void)
-{
-	return cpu_is_u8500() && (read_cpuid_id() == CPUID_DB8500V2);
-}
-
-#ifdef CONFIG_UX500_SOC_DB8500
-bool cpu_is_u8500v10(void);
-bool cpu_is_u8500v11(void);
-bool cpu_is_u8500v20(void);
-#else
-static inline bool cpu_is_u8500v10(void) { return false; }
-static inline bool cpu_is_u8500v11(void) { return false; }
-static inline bool cpu_is_u8500v20(void) { return false; }
-#endif
+#include <mach/id.h>
 
-static inline bool cpu_is_u5500(void)
-{
-#ifdef CONFIG_UX500_SOC_DB5500
-	return 1;
-#else
-	return 0;
-#endif
-}
+#define ARRAY_AND_SIZE(x)	(x), ARRAY_SIZE(x)
 
 #endif
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-ux500/include/mach/id.h linux-libre-2.6.38-gnu1/arch/arm/mach-ux500/include/mach/id.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-ux500/include/mach/id.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-ux500/include/mach/id.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#ifndef __MACH_UX500_ID
+#define __MACH_UX500_ID
+
+/**
+ * struct dbx500_asic_id - fields of the ASIC ID
+ * @process: the manufacturing process, 0x40 is 40 nm 0x00 is "standard"
+ * @partnumber: hithereto 0x8500 for DB8500
+ * @revision: version code in the series
+ */
+struct dbx500_asic_id {
+	u16	partnumber;
+	u8	revision;
+	u8	process;
+};
+
+extern struct dbx500_asic_id dbx500_id;
+
+static inline unsigned int __attribute_const__ dbx500_partnumber(void)
+{
+	return dbx500_id.partnumber;
+}
+
+static inline unsigned int __attribute_const__ dbx500_revision(void)
+{
+	return dbx500_id.revision;
+}
+
+/*
+ * SOCs
+ */
+
+static inline bool __attribute_const__ cpu_is_u8500(void)
+{
+	return dbx500_partnumber() == 0x8500;
+}
+
+static inline bool __attribute_const__ cpu_is_u5500(void)
+{
+	return dbx500_partnumber() == 0x5500;
+}
+
+/*
+ * 8500 revisions
+ */
+
+static inline bool __attribute_const__ cpu_is_u8500ed(void)
+{
+	return cpu_is_u8500() && dbx500_revision() == 0x00;
+}
+
+static inline bool __attribute_const__ cpu_is_u8500v1(void)
+{
+	return cpu_is_u8500() && (dbx500_revision() & 0xf0) == 0xA0;
+}
+
+static inline bool __attribute_const__ cpu_is_u8500v10(void)
+{
+	return cpu_is_u8500() && dbx500_revision() == 0xA0;
+}
+
+static inline bool __attribute_const__ cpu_is_u8500v11(void)
+{
+	return cpu_is_u8500() && dbx500_revision() == 0xA1;
+}
+
+static inline bool __attribute_const__ cpu_is_u8500v2(void)
+{
+	return cpu_is_u8500() && ((dbx500_revision() & 0xf0) == 0xB0);
+}
+
+#define ux500_unknown_soc()	BUG()
+
+#endif
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-ux500/include/mach/irqs-board-mop500.h linux-libre-2.6.38-gnu1/arch/arm/mach-ux500/include/mach/irqs-board-mop500.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-ux500/include/mach/irqs-board-mop500.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-ux500/include/mach/irqs-board-mop500.h	2011-03-14 21:20:32.000000000 -0400
@@ -8,12 +8,36 @@
 #ifndef __MACH_IRQS_BOARD_MOP500_H
 #define __MACH_IRQS_BOARD_MOP500_H
 
-#define AB8500_NR_IRQS			104
+/* Number of AB8500 irqs is taken from header file */
+#include <linux/mfd/ab8500.h>
 
 #define MOP500_AB8500_IRQ_BASE		IRQ_BOARD_START
 #define MOP500_AB8500_IRQ_END		(MOP500_AB8500_IRQ_BASE \
 					 + AB8500_NR_IRQS)
-#define MOP500_IRQ_END			MOP500_AB8500_IRQ_END
+
+/* TC35892 */
+#define TC35892_NR_INTERNAL_IRQS	8
+#define TC35892_INT_GPIO(x)		(TC35892_NR_INTERNAL_IRQS + (x))
+#define TC35892_NR_GPIOS		24
+#define TC35892_NR_IRQS			TC35892_INT_GPIO(TC35892_NR_GPIOS)
+
+#define MOP500_EGPIO_NR_IRQS		TC35892_NR_IRQS
+
+#define MOP500_EGPIO_IRQ_BASE		MOP500_AB8500_IRQ_END
+#define MOP500_EGPIO_IRQ_END		(MOP500_EGPIO_IRQ_BASE \
+					 + MOP500_EGPIO_NR_IRQS)
+/* STMPE1601 irqs */
+#define STMPE_NR_INTERNAL_IRQS          9
+#define STMPE_INT_GPIO(x)               (STMPE_NR_INTERNAL_IRQS + (x))
+#define STMPE_NR_GPIOS                  24
+#define STMPE_NR_IRQS                   STMPE_INT_GPIO(STMPE_NR_GPIOS)
+
+#define MOP500_STMPE1601_IRQBASE        MOP500_EGPIO_IRQ_END
+#define MOP500_STMPE1601_IRQ(x)         (MOP500_STMPE1601_IRQBASE + (x))
+
+#define MOP500_NR_IRQS          MOP500_STMPE1601_IRQ(STMPE_NR_INTERNAL_IRQS)
+
+#define MOP500_IRQ_END          MOP500_NR_IRQS
 
 #if MOP500_IRQ_END > IRQ_BOARD_END
 #undef IRQ_BOARD_END
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-ux500/include/mach/irqs.h linux-libre-2.6.38-gnu1/arch/arm/mach-ux500/include/mach/irqs.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-ux500/include/mach/irqs.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-ux500/include/mach/irqs.h	2011-03-14 21:20:32.000000000 -0400
@@ -21,50 +21,6 @@
 
 /* Interrupt numbers generic for shared peripheral */
 #define IRQ_MTU0		(IRQ_SHPI_START + 4)
-#define IRQ_SPI2		(IRQ_SHPI_START + 6)
-#define IRQ_SPI0		(IRQ_SHPI_START + 8)
-#define IRQ_UART0		(IRQ_SHPI_START + 11)
-#define IRQ_I2C3		(IRQ_SHPI_START + 12)
-#define IRQ_SSP0		(IRQ_SHPI_START + 14)
-#define IRQ_MTU1		(IRQ_SHPI_START + 17)
-#define IRQ_RTC_RTT		(IRQ_SHPI_START + 18)
-#define IRQ_UART1		(IRQ_SHPI_START + 19)
-#define IRQ_I2C0		(IRQ_SHPI_START + 21)
-#define IRQ_I2C1		(IRQ_SHPI_START + 22)
-#define IRQ_USBOTG		(IRQ_SHPI_START + 23)
-#define IRQ_DMA			(IRQ_SHPI_START + 25)
-#define IRQ_UART2		(IRQ_SHPI_START + 26)
-#define IRQ_HSIR_EXCEP		(IRQ_SHPI_START + 29)
-#define IRQ_MSP0		(IRQ_SHPI_START + 31)
-#define IRQ_HSIR_CH0_OVRRUN	(IRQ_SHPI_START + 32)
-#define IRQ_HSIR_CH1_OVRRUN	(IRQ_SHPI_START + 33)
-#define IRQ_HSIR_CH2_OVRRUN	(IRQ_SHPI_START + 34)
-#define IRQ_HSIR_CH3_OVRRUN	(IRQ_SHPI_START + 35)
-#define IRQ_AB8500		(IRQ_SHPI_START + 40)
-#define IRQ_PRCMU               (IRQ_SHPI_START + 47)
-#define IRQ_DISP		(IRQ_SHPI_START + 48)
-#define IRQ_SiPI3		(IRQ_SHPI_START + 49)
-#define IRQ_I2C4		(IRQ_SHPI_START + 51)
-#define IRQ_SSP1		(IRQ_SHPI_START + 52)
-#define IRQ_I2C2		(IRQ_SHPI_START + 55)
-#define IRQ_SDMMC0		(IRQ_SHPI_START + 60)
-#define IRQ_MSP1		(IRQ_SHPI_START + 62)
-#define IRQ_SPI1		(IRQ_SHPI_START + 96)
-#define IRQ_MSP2		(IRQ_SHPI_START + 98)
-#define IRQ_SDMMC4		(IRQ_SHPI_START + 99)
-#define IRQ_HSIRD0		(IRQ_SHPI_START + 104)
-#define IRQ_HSIRD1		(IRQ_SHPI_START + 105)
-#define IRQ_HSITD0		(IRQ_SHPI_START + 106)
-#define IRQ_HSITD1		(IRQ_SHPI_START + 107)
-#define IRQ_GPIO0		(IRQ_SHPI_START + 119)
-#define IRQ_GPIO1		(IRQ_SHPI_START + 120)
-#define IRQ_GPIO2		(IRQ_SHPI_START + 121)
-#define IRQ_GPIO3		(IRQ_SHPI_START + 122)
-#define IRQ_GPIO4		(IRQ_SHPI_START + 123)
-#define IRQ_GPIO5		(IRQ_SHPI_START + 124)
-#define IRQ_GPIO6		(IRQ_SHPI_START + 125)
-#define IRQ_GPIO7		(IRQ_SHPI_START + 126)
-#define IRQ_GPIO8		(IRQ_SHPI_START + 127)
 
 /* There are 128 shared peripheral interrupts assigned to
  * INTID[160:32]. The first 32 interrupts are reserved.
@@ -80,7 +36,7 @@
 /* This will be overridden by board-specific irq headers */
 #define IRQ_BOARD_END			IRQ_BOARD_START
 
-#ifdef CONFIG_MACH_U8500_MOP
+#ifdef CONFIG_MACH_U8500
 #include <mach/irqs-board-mop500.h>
 #endif
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-ux500/include/mach/mbox-db5500.h linux-libre-2.6.38-gnu1/arch/arm/mach-ux500/include/mach/mbox-db5500.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-ux500/include/mach/mbox-db5500.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-ux500/include/mach/mbox-db5500.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ * Author: Stefan Nilsson <stefan.xk.nilsson@stericsson.com> for ST-Ericsson.
+ * Author: Martin Persson <martin.persson@stericsson.com> for ST-Ericsson.
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+
+#ifndef __INC_STE_MBOX_H
+#define __INC_STE_MBOX_H
+
+#define MBOX_BUF_SIZE 16
+#define MBOX_NAME_SIZE 8
+
+/**
+  * mbox_recv_cb_t - Definition of the mailbox callback.
+  * @mbox_msg:	The mailbox message.
+  * @priv:	The clients private data as specified in the call to mbox_setup.
+  *
+  * This function will be called upon reception of new mailbox messages.
+  */
+typedef void mbox_recv_cb_t (u32 mbox_msg, void *priv);
+
+/**
+  * struct mbox - Mailbox instance struct
+  * @list:		Linked list head.
+  * @pdev:		Pointer to device struct.
+  * @cb:		Callback function. Will be called
+  *			when new data is received.
+  * @client_data:	Clients private data. Will be sent back
+  *			in the callback function.
+  * @virtbase_peer:	Virtual address for outgoing mailbox.
+  * @virtbase_local:	Virtual address for incoming mailbox.
+  * @buffer:		Then internal queue for outgoing messages.
+  * @name:		Name of this mailbox.
+  * @buffer_available:	Completion variable to achieve "blocking send".
+  *			This variable will be signaled when there is
+  *			internal buffer space available.
+  * @client_blocked:	To keep track if any client is currently
+  *			blocked.
+  * @lock:		Spinlock to protect this mailbox instance.
+  * @write_index:	Index in internal buffer to write to.
+  * @read_index:	Index in internal buffer to read from.
+  * @allocated:		Indicates whether this particular mailbox
+  *			id has been allocated by someone.
+  */
+struct mbox {
+	struct list_head list;
+	struct platform_device *pdev;
+	mbox_recv_cb_t *cb;
+	void *client_data;
+	void __iomem *virtbase_peer;
+	void __iomem *virtbase_local;
+	u32 buffer[MBOX_BUF_SIZE];
+	char name[MBOX_NAME_SIZE];
+	struct completion buffer_available;
+	u8 client_blocked;
+	spinlock_t lock;
+	u8 write_index;
+	u8 read_index;
+	bool allocated;
+};
+
+/**
+  * mbox_setup - Set up a mailbox and return its instance.
+  * @mbox_id:	The ID number of the mailbox. 0 or 1 for modem CPU,
+  *		2 for modem DSP.
+  * @mbox_cb:	Pointer to the callback function to be called when a new message
+  *		is received.
+  * @priv:	Client user data which will be returned in the callback.
+  *
+  * Returns a mailbox instance to be specified in subsequent calls to mbox_send.
+  */
+struct mbox *mbox_setup(u8 mbox_id, mbox_recv_cb_t *mbox_cb, void *priv);
+
+/**
+  * mbox_send - Send a mailbox message.
+  * @mbox:	Mailbox instance (returned by mbox_setup)
+  * @mbox_msg:	The mailbox message to send.
+  * @block:	Specifies whether this call will block until send is possible,
+  *		or return an error if the mailbox buffer is full.
+  *
+  * Returns 0 on success or a negative error code on error. -ENOMEM indicates
+  * that the internal buffer is full and you have to try again later (or
+  * specify "block" in order to block until send is possible).
+  */
+int mbox_send(struct mbox *mbox, u32 mbox_msg, bool block);
+
+#endif /*INC_STE_MBOX_H*/
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-ux500/include/mach/mbox.h linux-libre-2.6.38-gnu1/arch/arm/mach-ux500/include/mach/mbox.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-ux500/include/mach/mbox.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-ux500/include/mach/mbox.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,88 +0,0 @@
-/*
- * Copyright (C) ST-Ericsson SA 2010
- * Author: Stefan Nilsson <stefan.xk.nilsson@stericsson.com> for ST-Ericsson.
- * Author: Martin Persson <martin.persson@stericsson.com> for ST-Ericsson.
- * License terms: GNU General Public License (GPL), version 2.
- */
-
-#ifndef __INC_STE_MBOX_H
-#define __INC_STE_MBOX_H
-
-#define MBOX_BUF_SIZE 16
-#define MBOX_NAME_SIZE 8
-
-/**
-  * mbox_recv_cb_t - Definition of the mailbox callback.
-  * @mbox_msg:	The mailbox message.
-  * @priv:	The clients private data as specified in the call to mbox_setup.
-  *
-  * This function will be called upon reception of new mailbox messages.
-  */
-typedef void mbox_recv_cb_t (u32 mbox_msg, void *priv);
-
-/**
-  * struct mbox - Mailbox instance struct
-  * @list:		Linked list head.
-  * @pdev:		Pointer to device struct.
-  * @cb:		Callback function. Will be called
-  *			when new data is received.
-  * @client_data:	Clients private data. Will be sent back
-  *			in the callback function.
-  * @virtbase_peer:	Virtual address for outgoing mailbox.
-  * @virtbase_local:	Virtual address for incoming mailbox.
-  * @buffer:		Then internal queue for outgoing messages.
-  * @name:		Name of this mailbox.
-  * @buffer_available:	Completion variable to achieve "blocking send".
-  *			This variable will be signaled when there is
-  *			internal buffer space available.
-  * @client_blocked:	To keep track if any client is currently
-  *			blocked.
-  * @lock:		Spinlock to protect this mailbox instance.
-  * @write_index:	Index in internal buffer to write to.
-  * @read_index:	Index in internal buffer to read from.
-  * @allocated:		Indicates whether this particular mailbox
-  *			id has been allocated by someone.
-  */
-struct mbox {
-	struct list_head list;
-	struct platform_device *pdev;
-	mbox_recv_cb_t *cb;
-	void *client_data;
-	void __iomem *virtbase_peer;
-	void __iomem *virtbase_local;
-	u32 buffer[MBOX_BUF_SIZE];
-	char name[MBOX_NAME_SIZE];
-	struct completion buffer_available;
-	u8 client_blocked;
-	spinlock_t lock;
-	u8 write_index;
-	u8 read_index;
-	bool allocated;
-};
-
-/**
-  * mbox_setup - Set up a mailbox and return its instance.
-  * @mbox_id:	The ID number of the mailbox. 0 or 1 for modem CPU,
-  *		2 for modem DSP.
-  * @mbox_cb:	Pointer to the callback function to be called when a new message
-  *		is received.
-  * @priv:	Client user data which will be returned in the callback.
-  *
-  * Returns a mailbox instance to be specified in subsequent calls to mbox_send.
-  */
-struct mbox *mbox_setup(u8 mbox_id, mbox_recv_cb_t *mbox_cb, void *priv);
-
-/**
-  * mbox_send - Send a mailbox message.
-  * @mbox:	Mailbox instance (returned by mbox_setup)
-  * @mbox_msg:	The mailbox message to send.
-  * @block:	Specifies whether this call will block until send is possible,
-  *		or return an error if the mailbox buffer is full.
-  *
-  * Returns 0 on success or a negative error code on error. -ENOMEM indicates
-  * that the internal buffer is full and you have to try again later (or
-  * specify "block" in order to block until send is possible).
-  */
-int mbox_send(struct mbox *mbox, u32 mbox_msg, bool block);
-
-#endif /*INC_STE_MBOX_H*/
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-ux500/include/mach/prcmu-defs.h linux-libre-2.6.38-gnu1/arch/arm/mach-ux500/include/mach/prcmu-defs.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-ux500/include/mach/prcmu-defs.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-ux500/include/mach/prcmu-defs.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) STMicroelectronics 2009
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * Author: Sundar Iyer <sundar.iyer@stericsson.com>
+ * Author: Martin Persson <martin.persson@stericsson.com>
+ *
+ * License Terms: GNU General Public License v2
+ *
+ * PRCM Unit definitions
+ */
+
+#ifndef __MACH_PRCMU_DEFS_H
+#define __MACH_PRCMU_DEFS_H
+
+enum prcmu_cpu_opp {
+	CPU_OPP_INIT	  = 0x00,
+	CPU_OPP_NO_CHANGE = 0x01,
+	CPU_OPP_100	  = 0x02,
+	CPU_OPP_50	  = 0x03,
+	CPU_OPP_MAX	  = 0x04,
+	CPU_OPP_EXT_CLK	  = 0x07
+};
+enum prcmu_ape_opp {
+	APE_OPP_NO_CHANGE = 0x00,
+	APE_OPP_100	  = 0x02,
+	APE_OPP_50	  = 0x03,
+};
+
+#endif /* __MACH_PRCMU_DEFS_H */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-ux500/include/mach/prcmu.h linux-libre-2.6.38-gnu1/arch/arm/mach-ux500/include/mach/prcmu.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-ux500/include/mach/prcmu.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-ux500/include/mach/prcmu.h	2011-03-14 21:20:32.000000000 -0400
@@ -2,14 +2,27 @@
  * Copyright (C) STMicroelectronics 2009
  * Copyright (C) ST-Ericsson SA 2010
  *
+ * Author: Kumar Sanghvi <kumar.sanghvi@stericsson.com>
+ * Author: Sundar Iyer <sundar.iyer@stericsson.com>
+ * Author: Mattias Nilsson <mattias.i.nilsson@stericsson.com>
+ *
  * License Terms: GNU General Public License v2
  *
- * PRCMU f/w APIs
+ * PRCM Unit f/w API
  */
 #ifndef __MACH_PRCMU_H
 #define __MACH_PRCMU_H
+#include <mach/prcmu-defs.h>
 
+void __init prcmu_early_init(void);
 int prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size);
 int prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size);
+int prcmu_set_ape_opp(enum prcmu_ape_opp opp);
+int prcmu_set_cpu_opp(enum prcmu_cpu_opp opp);
+int prcmu_set_ape_cpu_opps(enum prcmu_ape_opp ape_opp,
+			   enum prcmu_cpu_opp cpu_opp);
+int prcmu_get_ape_opp(void);
+int prcmu_get_cpu_opp(void);
+bool prcmu_has_arm_maxopp(void);
 
 #endif /* __MACH_PRCMU_H */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-ux500/include/mach/prcmu-regs.h linux-libre-2.6.38-gnu1/arch/arm/mach-ux500/include/mach/prcmu-regs.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-ux500/include/mach/prcmu-regs.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-ux500/include/mach/prcmu-regs.h	2011-03-14 21:20:32.000000000 -0400
@@ -1,10 +1,15 @@
 /*
- * Copyright (c) 2009 ST-Ericsson SA
+ * Copyright (C) STMicroelectronics 2009
+ * Copyright (C) ST-Ericsson SA 2010
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2
- * as published by the Free Software Foundation.
+ * Author: Kumar Sanghvi <kumar.sanghvi@stericsson.com>
+ * Author: Sundar Iyer <sundar.iyer@stericsson.com>
+ *
+ * License Terms: GNU General Public License v2
+ *
+ * PRCM Unit registers
  */
+
 #ifndef __MACH_PRCMU_REGS_H
 #define __MACH_PRCMU_REGS_H
 
@@ -88,4 +93,4 @@
 /* Miscellaneous unit registers */
 #define PRCM_DSI_SW_RESET          (_PRCMU_BASE + 0x324)
 
-#endif /* __MACH_PRCMU__REGS_H */
+#endif /* __MACH_PRCMU_REGS_H */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-ux500/include/mach/setup.h linux-libre-2.6.38-gnu1/arch/arm/mach-ux500/include/mach/setup.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-ux500/include/mach/setup.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-ux500/include/mach/setup.h	2011-03-14 21:20:32.000000000 -0400
@@ -14,18 +14,23 @@
 #include <asm/mach/time.h>
 #include <linux/init.h>
 
-extern void __init ux500_map_io(void);
+void __init ux500_map_io(void);
 extern void __init u5500_map_io(void);
 extern void __init u8500_map_io(void);
 
-extern void __init ux500_init_devices(void);
 extern void __init u5500_init_devices(void);
 extern void __init u8500_init_devices(void);
 
 extern void __init ux500_init_irq(void);
+
+extern void __init u5500_sdi_init(void);
+
+extern void __init db5500_dma_init(void);
+
 /* We re-use nomadik_timer for this platform */
 extern void nmdk_timer_init(void);
 
+struct amba_device;
 extern void __init amba_add_devices(struct amba_device *devs[], int num);
 
 struct sys_timer;
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-ux500/include/mach/smp.h linux-libre-2.6.38-gnu1/arch/arm/mach-ux500/include/mach/smp.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-ux500/include/mach/smp.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-ux500/include/mach/smp.h	2011-03-14 21:20:32.000000000 -0400
@@ -10,7 +10,6 @@
 #define ASMARM_ARCH_SMP_H
 
 #include <asm/hardware/gic.h>
-#include <asm/smp_mpidr.h>
 
 /* This is required to wakeup the secondary core */
 extern void u8500_secondary_startup(void);
@@ -18,8 +17,8 @@ extern void u8500_secondary_startup(void
 /*
  * We use IRQ1 as the IPI
  */
-static inline void smp_cross_call(const struct cpumask *mask)
+static inline void smp_cross_call(const struct cpumask *mask, int ipi)
 {
-	gic_raise_softirq(mask, 1);
+	gic_raise_softirq(mask, ipi);
 }
 #endif
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-ux500/include/mach/uncompress.h linux-libre-2.6.38-gnu1/arch/arm/mach-ux500/include/mach/uncompress.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-ux500/include/mach/uncompress.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-ux500/include/mach/uncompress.h	2011-03-14 21:20:32.000000000 -0400
@@ -19,38 +19,43 @@
 #define __ASM_ARCH_UNCOMPRESS_H
 
 #include <asm/setup.h>
+#include <asm/mach-types.h>
 #include <linux/io.h>
+#include <linux/amba/serial.h>
 #include <mach/hardware.h>
 
-#define U8500_UART_DR		0x80007000
-#define U8500_UART_LCRH		0x8000702c
-#define U8500_UART_CR		0x80007030
-#define U8500_UART_FR		0x80007018
+static u32 ux500_uart_base;
 
 static void putc(const char c)
 {
 	/* Do nothing if the UART is not enabled. */
-	if (!(__raw_readb(U8500_UART_CR) & 0x1))
+	if (!(__raw_readb(ux500_uart_base + UART011_CR) & 0x1))
 		return;
 
 	if (c == '\n')
 		putc('\r');
 
-	while (__raw_readb(U8500_UART_FR) & (1 << 5))
+	while (__raw_readb(ux500_uart_base + UART01x_FR) & (1 << 5))
 		barrier();
-	__raw_writeb(c, U8500_UART_DR);
+	__raw_writeb(c, ux500_uart_base + UART01x_DR);
 }
 
 static void flush(void)
 {
-	if (!(__raw_readb(U8500_UART_CR) & 0x1))
+	if (!(__raw_readb(ux500_uart_base + UART011_CR) & 0x1))
 		return;
-	while (__raw_readb(U8500_UART_FR) & (1 << 3))
+	while (__raw_readb(ux500_uart_base + UART01x_FR) & (1 << 3))
 		barrier();
 }
 
 static inline void arch_decomp_setup(void)
 {
+	if (machine_is_u8500())
+		ux500_uart_base = U8500_UART2_BASE;
+	else if (machine_is_u5500())
+		ux500_uart_base = U5500_UART0_BASE;
+	else /* not much can be done to help here */
+		ux500_uart_base = U8500_UART2_BASE;
 }
 
 #define arch_decomp_wdog() /* nothing to do here */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-ux500/Kconfig linux-libre-2.6.38-gnu1/arch/arm/mach-ux500/Kconfig
--- linux-libre-2.6.37-gnu1/arch/arm/mach-ux500/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-ux500/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -7,28 +7,30 @@ config UX500_SOC_COMMON
 	select HAS_MTU
 	select NOMADIK_GPIO
 
-config UX500_SOC_DB8500
-	bool
+menu "Ux500 SoC"
 
 config UX500_SOC_DB5500
-	bool
+	bool "DB5500"
 
-choice
-	prompt "Ux500 target platform"
-	default MACH_U8500_MOP
+config UX500_SOC_DB8500
+	bool "DB8500"
 
-config MACH_U8500_MOP
+endmenu
+
+menu "Ux500 target platform"
+
+config MACH_U8500
 	bool "U8500 Development platform"
-	select UX500_SOC_DB8500
+	depends on UX500_SOC_DB8500
 	help
 	  Include support for the mop500 development platform.
 
 config MACH_U5500
 	bool "U5500 Development platform"
-	select UX500_SOC_DB5500
+	depends on UX500_SOC_DB5500
 	help
 	  Include support for the U5500 development platform.
-endchoice
+endmenu
 
 config UX500_DEBUG_UART
 	int "Ux500 UART to use for low-level debug"
@@ -39,14 +41,14 @@ config UX500_DEBUG_UART
 
 config U5500_MODEM_IRQ
 	bool "Modem IRQ support"
-	depends on MACH_U5500
+	depends on UX500_SOC_DB5500
 	default y
 	help
 	  Add support for handling IRQ:s from modem side
 
 config U5500_MBOX
 	bool "Mailbox support"
-	depends on MACH_U5500 && U5500_MODEM_IRQ
+	depends on U5500_MODEM_IRQ
 	default y
 	help
 	  Add support for U5500 mailbox communication with modem side
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-ux500/Makefile linux-libre-2.6.38-gnu1/arch/arm/mach-ux500/Makefile
--- linux-libre-2.6.37-gnu1/arch/arm/mach-ux500/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-ux500/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -2,14 +2,17 @@
 # Makefile for the linux kernel, U8500 machine.
 #
 
-obj-y				:= clock.o cpu.o devices.o
-obj-$(CONFIG_UX500_SOC_DB5500)	+= cpu-db5500.o devices-db5500.o
+obj-y				:= clock.o cpu.o devices.o devices-common.o \
+				   id.o
+obj-$(CONFIG_UX500_SOC_DB5500)	+= cpu-db5500.o dma-db5500.o
 obj-$(CONFIG_UX500_SOC_DB8500)	+= cpu-db8500.o devices-db8500.o prcmu.o
-obj-$(CONFIG_MACH_U8500_MOP)	+= board-mop500.o board-mop500-sdi.o
-obj-$(CONFIG_MACH_U5500)	+= board-u5500.o
+obj-$(CONFIG_MACH_U8500)	+= board-mop500.o board-mop500-sdi.o \
+				board-mop500-keypads.o
+obj-$(CONFIG_MACH_U5500)	+= board-u5500.o board-u5500-sdi.o
 obj-$(CONFIG_SMP)		+= platsmp.o headsmp.o
 obj-$(CONFIG_HOTPLUG_CPU)	+= hotplug.o
 obj-$(CONFIG_LOCAL_TIMERS)	+= localtimer.o
 obj-$(CONFIG_REGULATOR_AB8500)	+= board-mop500-regulators.o
-obj-$(CONFIG_U5500_MODEM_IRQ)	+= modem_irq.o
-obj-$(CONFIG_U5500_MBOX)	+= mbox.o
+obj-$(CONFIG_U5500_MODEM_IRQ)	+= modem-irq-db5500.o
+obj-$(CONFIG_U5500_MBOX)	+= mbox-db5500.o
+obj-$(CONFIG_CPU_FREQ)		+= cpufreq.o
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-ux500/mbox.c linux-libre-2.6.38-gnu1/arch/arm/mach-ux500/mbox.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-ux500/mbox.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-ux500/mbox.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,567 +0,0 @@
-/*
- * Copyright (C) ST-Ericsson SA 2010
- * Author: Stefan Nilsson <stefan.xk.nilsson@stericsson.com> for ST-Ericsson.
- * Author: Martin Persson <martin.persson@stericsson.com> for ST-Ericsson.
- * License terms: GNU General Public License (GPL), version 2.
- */
-
-/*
- * Mailbox nomenclature:
- *
- *       APE           MODEM
- *           mbox pairX
- *   ..........................
- *   .                       .
- *   .           peer        .
- *   .     send  ----        .
- *   .      -->  |  |        .
- *   .           |  |        .
- *   .           ----        .
- *   .                       .
- *   .           local       .
- *   .     rec   ----        .
- *   .           |  | <--    .
- *   .           |  |        .
- *   .           ----        .
- *   .........................
- */
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/device.h>
-#include <linux/interrupt.h>
-#include <linux/spinlock.h>
-#include <linux/errno.h>
-#include <linux/io.h>
-#include <linux/irq.h>
-#include <linux/platform_device.h>
-#include <linux/debugfs.h>
-#include <linux/seq_file.h>
-#include <linux/completion.h>
-#include <mach/mbox.h>
-
-#define MBOX_NAME "mbox"
-
-#define MBOX_FIFO_DATA        0x000
-#define MBOX_FIFO_ADD         0x004
-#define MBOX_FIFO_REMOVE      0x008
-#define MBOX_FIFO_THRES_FREE  0x00C
-#define MBOX_FIFO_THRES_OCCUP 0x010
-#define MBOX_FIFO_STATUS      0x014
-
-#define MBOX_DISABLE_IRQ 0x4
-#define MBOX_ENABLE_IRQ  0x0
-#define MBOX_LATCH 1
-
-/* Global list of all mailboxes */
-static struct list_head mboxs = LIST_HEAD_INIT(mboxs);
-
-static struct mbox *get_mbox_with_id(u8 id)
-{
-	u8 i;
-	struct list_head *pos = &mboxs;
-	for (i = 0; i <= id; i++)
-		pos = pos->next;
-
-	return (struct mbox *) list_entry(pos, struct mbox, list);
-}
-
-int mbox_send(struct mbox *mbox, u32 mbox_msg, bool block)
-{
-	int res = 0;
-
-	spin_lock(&mbox->lock);
-
-	dev_dbg(&(mbox->pdev->dev),
-		"About to buffer 0x%X to mailbox 0x%X."
-		" ri = %d, wi = %d\n",
-		mbox_msg, (u32)mbox, mbox->read_index,
-		mbox->write_index);
-
-	/* Check if write buffer is full */
-	while (((mbox->write_index + 1) % MBOX_BUF_SIZE) == mbox->read_index) {
-		if (!block) {
-			dev_dbg(&(mbox->pdev->dev),
-			"Buffer full in non-blocking call! "
-			"Returning -ENOMEM!\n");
-			res = -ENOMEM;
-			goto exit;
-		}
-		spin_unlock(&mbox->lock);
-		dev_dbg(&(mbox->pdev->dev),
-			"Buffer full in blocking call! Sleeping...\n");
-		mbox->client_blocked = 1;
-		wait_for_completion(&mbox->buffer_available);
-		dev_dbg(&(mbox->pdev->dev),
-			"Blocking send was woken up! Trying again...\n");
-		spin_lock(&mbox->lock);
-	}
-
-	mbox->buffer[mbox->write_index] = mbox_msg;
-	mbox->write_index = (mbox->write_index + 1) % MBOX_BUF_SIZE;
-
-	/*
-	 * Indicate that we want an IRQ as soon as there is a slot
-	 * in the FIFO
-	 */
-	writel(MBOX_ENABLE_IRQ, mbox->virtbase_peer + MBOX_FIFO_THRES_FREE);
-
-exit:
-	spin_unlock(&mbox->lock);
-	return res;
-}
-EXPORT_SYMBOL(mbox_send);
-
-#if defined(CONFIG_DEBUG_FS)
-/*
- * Expected input: <value> <nbr sends>
- * Example: "echo 0xdeadbeef 4 > mbox-node" sends 0xdeadbeef 4 times
- */
-static ssize_t mbox_write_fifo(struct device *dev,
-			       struct device_attribute *attr,
-			       const char *buf,
-			       size_t count)
-{
-	unsigned long mbox_mess;
-	unsigned long nbr_sends;
-	unsigned long i;
-	char int_buf[16];
-	char *token;
-	char *val;
-
-	struct mbox *mbox = (struct mbox *) dev->platform_data;
-
-	strncpy((char *) &int_buf, buf, sizeof(int_buf));
-	token = (char *) &int_buf;
-
-	/* Parse message */
-	val = strsep(&token, " ");
-	if ((val == NULL) || (strict_strtoul(val, 16, &mbox_mess) != 0))
-		mbox_mess = 0xDEADBEEF;
-
-	val = strsep(&token, " ");
-	if ((val == NULL) || (strict_strtoul(val, 10, &nbr_sends) != 0))
-		nbr_sends = 1;
-
-	dev_dbg(dev, "Will write 0x%lX %ld times using data struct at 0x%X\n",
-		mbox_mess, nbr_sends, (u32) mbox);
-
-	for (i = 0; i < nbr_sends; i++)
-		mbox_send(mbox, mbox_mess, true);
-
-	return count;
-}
-
-static ssize_t mbox_read_fifo(struct device *dev,
-			      struct device_attribute *attr,
-			      char *buf)
-{
-	int mbox_value;
-	struct mbox *mbox = (struct mbox *) dev->platform_data;
-
-	if ((readl(mbox->virtbase_local + MBOX_FIFO_STATUS) & 0x7) <= 0)
-		return sprintf(buf, "Mailbox is empty\n");
-
-	mbox_value = readl(mbox->virtbase_local + MBOX_FIFO_DATA);
-	writel(MBOX_LATCH, (mbox->virtbase_local + MBOX_FIFO_REMOVE));
-
-	return sprintf(buf, "0x%X\n", mbox_value);
-}
-
-static DEVICE_ATTR(fifo, S_IWUGO | S_IRUGO, mbox_read_fifo, mbox_write_fifo);
-
-static int mbox_show(struct seq_file *s, void *data)
-{
-	struct list_head *pos;
-	u8 mbox_index = 0;
-
-	list_for_each(pos, &mboxs) {
-		struct mbox *m =
-			(struct mbox *) list_entry(pos, struct mbox, list);
-		if (m == NULL) {
-			seq_printf(s,
-				   "Unable to retrieve mailbox %d\n",
-				   mbox_index);
-			continue;
-		}
-
-		spin_lock(&m->lock);
-		if ((m->virtbase_peer == NULL) || (m->virtbase_local == NULL)) {
-			seq_printf(s, "MAILBOX %d not setup or corrupt\n",
-				   mbox_index);
-			spin_unlock(&m->lock);
-			continue;
-		}
-
-		seq_printf(s,
-		"===========================\n"
-		" MAILBOX %d\n"
-		" PEER MAILBOX DUMP\n"
-		"---------------------------\n"
-		"FIFO:                 0x%X (%d)\n"
-		"Free     Threshold:   0x%.2X (%d)\n"
-		"Occupied Threshold:   0x%.2X (%d)\n"
-		"Status:               0x%.2X (%d)\n"
-		"   Free spaces  (ot):    %d (%d)\n"
-		"   Occup spaces (ot):    %d (%d)\n"
-		"===========================\n"
-		" LOCAL MAILBOX DUMP\n"
-		"---------------------------\n"
-		"FIFO:                 0x%.X (%d)\n"
-		"Free     Threshold:   0x%.2X (%d)\n"
-		"Occupied Threshold:   0x%.2X (%d)\n"
-		"Status:               0x%.2X (%d)\n"
-		"   Free spaces  (ot):    %d (%d)\n"
-		"   Occup spaces (ot):    %d (%d)\n"
-		"===========================\n"
-		"write_index: %d\n"
-		"read_index : %d\n"
-		"===========================\n"
-		"\n",
-		mbox_index,
-		readl(m->virtbase_peer + MBOX_FIFO_DATA),
-		readl(m->virtbase_peer + MBOX_FIFO_DATA),
-		readl(m->virtbase_peer + MBOX_FIFO_THRES_FREE),
-		readl(m->virtbase_peer + MBOX_FIFO_THRES_FREE),
-		readl(m->virtbase_peer + MBOX_FIFO_THRES_OCCUP),
-		readl(m->virtbase_peer + MBOX_FIFO_THRES_OCCUP),
-		readl(m->virtbase_peer + MBOX_FIFO_STATUS),
-		readl(m->virtbase_peer + MBOX_FIFO_STATUS),
-		(readl(m->virtbase_peer + MBOX_FIFO_STATUS) >> 4) & 0x7,
-		(readl(m->virtbase_peer + MBOX_FIFO_STATUS) >> 7) & 0x1,
-		(readl(m->virtbase_peer + MBOX_FIFO_STATUS) >> 0) & 0x7,
-		(readl(m->virtbase_peer + MBOX_FIFO_STATUS) >> 3) & 0x1,
-		readl(m->virtbase_local + MBOX_FIFO_DATA),
-		readl(m->virtbase_local + MBOX_FIFO_DATA),
-		readl(m->virtbase_local + MBOX_FIFO_THRES_FREE),
-		readl(m->virtbase_local + MBOX_FIFO_THRES_FREE),
-		readl(m->virtbase_local + MBOX_FIFO_THRES_OCCUP),
-		readl(m->virtbase_local + MBOX_FIFO_THRES_OCCUP),
-		readl(m->virtbase_local + MBOX_FIFO_STATUS),
-		readl(m->virtbase_local + MBOX_FIFO_STATUS),
-		(readl(m->virtbase_local + MBOX_FIFO_STATUS) >> 4) & 0x7,
-		(readl(m->virtbase_local + MBOX_FIFO_STATUS) >> 7) & 0x1,
-		(readl(m->virtbase_local + MBOX_FIFO_STATUS) >> 0) & 0x7,
-		(readl(m->virtbase_local + MBOX_FIFO_STATUS) >> 3) & 0x1,
-		m->write_index, m->read_index);
-		mbox_index++;
-		spin_unlock(&m->lock);
-	}
-
-	return 0;
-}
-
-static int mbox_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, mbox_show, NULL);
-}
-
-static const struct file_operations mbox_operations = {
-	.owner = THIS_MODULE,
-	.open = mbox_open,
-	.read = seq_read,
-	.llseek = seq_lseek,
-	.release = single_release,
-};
-#endif
-
-static irqreturn_t mbox_irq(int irq, void *arg)
-{
-	u32 mbox_value;
-	int nbr_occup;
-	int nbr_free;
-	struct mbox *mbox = (struct mbox *) arg;
-
-	spin_lock(&mbox->lock);
-
-	dev_dbg(&(mbox->pdev->dev),
-		"mbox IRQ [%d] received. ri = %d, wi = %d\n",
-		irq, mbox->read_index, mbox->write_index);
-
-	/*
-	 * Check if we have any outgoing messages, and if there is space for
-	 * them in the FIFO.
-	 */
-	if (mbox->read_index != mbox->write_index) {
-		/*
-		 * Check by reading FREE for LOCAL since that indicates
-		 * OCCUP for PEER
-		 */
-		nbr_free = (readl(mbox->virtbase_local + MBOX_FIFO_STATUS)
-			    >> 4) & 0x7;
-		dev_dbg(&(mbox->pdev->dev),
-			"Status indicates %d empty spaces in the FIFO!\n",
-			nbr_free);
-
-		while ((nbr_free > 0) &&
-		       (mbox->read_index != mbox->write_index)) {
-			/* Write the message and latch it into the FIFO */
-			writel(mbox->buffer[mbox->read_index],
-			       (mbox->virtbase_peer + MBOX_FIFO_DATA));
-			writel(MBOX_LATCH,
-			       (mbox->virtbase_peer + MBOX_FIFO_ADD));
-			dev_dbg(&(mbox->pdev->dev),
-				"Wrote message 0x%X to addr 0x%X\n",
-				mbox->buffer[mbox->read_index],
-				(u32) (mbox->virtbase_peer + MBOX_FIFO_DATA));
-
-			nbr_free--;
-			mbox->read_index =
-				(mbox->read_index + 1) % MBOX_BUF_SIZE;
-		}
-
-		/*
-		 * Check if we still want IRQ:s when there is free
-		 * space to send
-		 */
-		if (mbox->read_index != mbox->write_index) {
-			dev_dbg(&(mbox->pdev->dev),
-				"Still have messages to send, but FIFO full. "
-				"Request IRQ again!\n");
-			writel(MBOX_ENABLE_IRQ,
-			       mbox->virtbase_peer + MBOX_FIFO_THRES_FREE);
-		} else {
-			dev_dbg(&(mbox->pdev->dev),
-				"No more messages to send. "
-				"Do not request IRQ again!\n");
-			writel(MBOX_DISABLE_IRQ,
-			       mbox->virtbase_peer + MBOX_FIFO_THRES_FREE);
-		}
-
-		/*
-		 * Check if we can signal any blocked clients that it is OK to
-		 * start buffering again
-		 */
-		if (mbox->client_blocked &&
-		    (((mbox->write_index + 1) % MBOX_BUF_SIZE)
-		     != mbox->read_index)) {
-			dev_dbg(&(mbox->pdev->dev),
-				"Waking up blocked client\n");
-			complete(&mbox->buffer_available);
-			mbox->client_blocked = 0;
-		}
-	}
-
-	/* Check if we have any incoming messages */
-	nbr_occup = readl(mbox->virtbase_local + MBOX_FIFO_STATUS) & 0x7;
-	if (nbr_occup == 0)
-		goto exit;
-
-	if (mbox->cb == NULL) {
-		dev_dbg(&(mbox->pdev->dev), "No receive callback registered, "
-			"leaving %d incoming messages in fifo!\n", nbr_occup);
-		goto exit;
-	}
-
-	/* Read and acknowledge the message */
-	mbox_value = readl(mbox->virtbase_local + MBOX_FIFO_DATA);
-	writel(MBOX_LATCH, (mbox->virtbase_local + MBOX_FIFO_REMOVE));
-
-	/* Notify consumer of new mailbox message */
-	dev_dbg(&(mbox->pdev->dev), "Calling callback for message 0x%X!\n",
-		mbox_value);
-	mbox->cb(mbox_value, mbox->client_data);
-
-exit:
-	dev_dbg(&(mbox->pdev->dev), "Exit mbox IRQ. ri = %d, wi = %d\n",
-		mbox->read_index, mbox->write_index);
-	spin_unlock(&mbox->lock);
-
-	return IRQ_HANDLED;
-}
-
-/* Setup is executed once for each mbox pair */
-struct mbox *mbox_setup(u8 mbox_id, mbox_recv_cb_t *mbox_cb, void *priv)
-{
-	struct resource *resource;
-	int irq;
-	int res;
-	struct mbox *mbox;
-
-	mbox = get_mbox_with_id(mbox_id);
-	if (mbox == NULL) {
-		dev_err(&(mbox->pdev->dev), "Incorrect mailbox id: %d!\n",
-			mbox_id);
-		goto exit;
-	}
-
-	/*
-	 * Check if mailbox has been allocated to someone else,
-	 * otherwise allocate it
-	 */
-	if (mbox->allocated) {
-		dev_err(&(mbox->pdev->dev), "Mailbox number %d is busy!\n",
-			mbox_id);
-		mbox = NULL;
-		goto exit;
-	}
-	mbox->allocated = true;
-
-	dev_dbg(&(mbox->pdev->dev), "Initiating mailbox number %d: 0x%X...\n",
-		mbox_id, (u32)mbox);
-
-	mbox->client_data = priv;
-	mbox->cb = mbox_cb;
-
-	/* Get addr for peer mailbox and ioremap it */
-	resource = platform_get_resource_byname(mbox->pdev,
-						IORESOURCE_MEM,
-						"mbox_peer");
-	if (resource == NULL) {
-		dev_err(&(mbox->pdev->dev),
-			"Unable to retrieve mbox peer resource\n");
-		mbox = NULL;
-		goto exit;
-	}
-	dev_dbg(&(mbox->pdev->dev),
-		"Resource name: %s start: 0x%X, end: 0x%X\n",
-		resource->name, resource->start, resource->end);
-	mbox->virtbase_peer =
-		ioremap(resource->start, resource->end - resource->start);
-	if (!mbox->virtbase_peer) {
-		dev_err(&(mbox->pdev->dev), "Unable to ioremap peer mbox\n");
-		mbox = NULL;
-		goto exit;
-	}
-	dev_dbg(&(mbox->pdev->dev),
-		"ioremapped peer physical: (0x%X-0x%X) to virtual: 0x%X\n",
-		resource->start, resource->end, (u32) mbox->virtbase_peer);
-
-	/* Get addr for local mailbox and ioremap it */
-	resource = platform_get_resource_byname(mbox->pdev,
-						IORESOURCE_MEM,
-						"mbox_local");
-	if (resource == NULL) {
-		dev_err(&(mbox->pdev->dev),
-			"Unable to retrieve mbox local resource\n");
-		mbox = NULL;
-		goto exit;
-	}
-	dev_dbg(&(mbox->pdev->dev),
-		"Resource name: %s start: 0x%X, end: 0x%X\n",
-		resource->name, resource->start, resource->end);
-	mbox->virtbase_local =
-		ioremap(resource->start, resource->end - resource->start);
-	if (!mbox->virtbase_local) {
-		dev_err(&(mbox->pdev->dev), "Unable to ioremap local mbox\n");
-		mbox = NULL;
-		goto exit;
-	}
-	dev_dbg(&(mbox->pdev->dev),
-		"ioremapped local physical: (0x%X-0x%X) to virtual: 0x%X\n",
-		resource->start, resource->end, (u32) mbox->virtbase_peer);
-
-	init_completion(&mbox->buffer_available);
-	mbox->client_blocked = 0;
-
-	/* Get IRQ for mailbox and allocate it */
-	irq = platform_get_irq_byname(mbox->pdev, "mbox_irq");
-	if (irq < 0) {
-		dev_err(&(mbox->pdev->dev),
-			"Unable to retrieve mbox irq resource\n");
-		mbox = NULL;
-		goto exit;
-	}
-
-	dev_dbg(&(mbox->pdev->dev), "Allocating irq %d...\n", irq);
-	res = request_irq(irq, mbox_irq, 0, mbox->name, (void *) mbox);
-	if (res < 0) {
-		dev_err(&(mbox->pdev->dev),
-			"Unable to allocate mbox irq %d\n", irq);
-		mbox = NULL;
-		goto exit;
-	}
-
-	/* Set up mailbox to not launch IRQ on free space in mailbox */
-	writel(MBOX_DISABLE_IRQ, mbox->virtbase_peer + MBOX_FIFO_THRES_FREE);
-
-	/*
-	 * Set up mailbox to launch IRQ on new message if we have
-	 * a callback set. If not, do not raise IRQ, but keep message
-	 * in FIFO for manual retrieval
-	 */
-	if (mbox_cb != NULL)
-		writel(MBOX_ENABLE_IRQ,
-		       mbox->virtbase_local + MBOX_FIFO_THRES_OCCUP);
-	else
-		writel(MBOX_DISABLE_IRQ,
-		       mbox->virtbase_local + MBOX_FIFO_THRES_OCCUP);
-
-#if defined(CONFIG_DEBUG_FS)
-	res = device_create_file(&(mbox->pdev->dev), &dev_attr_fifo);
-	if (res != 0)
-		dev_warn(&(mbox->pdev->dev),
-			 "Unable to create mbox sysfs entry");
-
-	(void) debugfs_create_file("mbox", S_IFREG | S_IRUGO, NULL,
-				   NULL, &mbox_operations);
-#endif
-
-	dev_info(&(mbox->pdev->dev),
-		 "Mailbox driver with index %d initated!\n", mbox_id);
-
-exit:
-	return mbox;
-}
-EXPORT_SYMBOL(mbox_setup);
-
-
-int __init mbox_probe(struct platform_device *pdev)
-{
-	struct mbox local_mbox;
-	struct mbox *mbox;
-	int res = 0;
-	dev_dbg(&(pdev->dev), "Probing mailbox (pdev = 0x%X)...\n", (u32) pdev);
-
-	memset(&local_mbox, 0x0, sizeof(struct mbox));
-
-	/* Associate our mbox data with the platform device */
-	res = platform_device_add_data(pdev,
-				       (void *) &local_mbox,
-				       sizeof(struct mbox));
-	if (res != 0) {
-		dev_err(&(pdev->dev),
-			"Unable to allocate driver platform data!\n");
-		goto exit;
-	}
-
-	mbox = (struct mbox *) pdev->dev.platform_data;
-	mbox->pdev = pdev;
-	mbox->write_index = 0;
-	mbox->read_index = 0;
-
-	INIT_LIST_HEAD(&(mbox->list));
-	list_add_tail(&(mbox->list), &mboxs);
-
-	sprintf(mbox->name, "%s", MBOX_NAME);
-	spin_lock_init(&mbox->lock);
-
-	dev_info(&(pdev->dev), "Mailbox driver loaded\n");
-
-exit:
-	return res;
-}
-
-static struct platform_driver mbox_driver = {
-	.driver = {
-		.name = MBOX_NAME,
-		.owner = THIS_MODULE,
-	},
-};
-
-static int __init mbox_init(void)
-{
-	return platform_driver_probe(&mbox_driver, mbox_probe);
-}
-
-module_init(mbox_init);
-
-void __exit mbox_exit(void)
-{
-	platform_driver_unregister(&mbox_driver);
-}
-
-module_exit(mbox_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("MBOX driver");
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-ux500/mbox-db5500.c linux-libre-2.6.38-gnu1/arch/arm/mach-ux500/mbox-db5500.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-ux500/mbox-db5500.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-ux500/mbox-db5500.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,567 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ * Author: Stefan Nilsson <stefan.xk.nilsson@stericsson.com> for ST-Ericsson.
+ * Author: Martin Persson <martin.persson@stericsson.com> for ST-Ericsson.
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+
+/*
+ * Mailbox nomenclature:
+ *
+ *       APE           MODEM
+ *           mbox pairX
+ *   ..........................
+ *   .                       .
+ *   .           peer        .
+ *   .     send  ----        .
+ *   .      -->  |  |        .
+ *   .           |  |        .
+ *   .           ----        .
+ *   .                       .
+ *   .           local       .
+ *   .     rec   ----        .
+ *   .           |  | <--    .
+ *   .           |  |        .
+ *   .           ----        .
+ *   .........................
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/errno.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/platform_device.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#include <linux/completion.h>
+#include <mach/mbox-db5500.h>
+
+#define MBOX_NAME "mbox"
+
+#define MBOX_FIFO_DATA        0x000
+#define MBOX_FIFO_ADD         0x004
+#define MBOX_FIFO_REMOVE      0x008
+#define MBOX_FIFO_THRES_FREE  0x00C
+#define MBOX_FIFO_THRES_OCCUP 0x010
+#define MBOX_FIFO_STATUS      0x014
+
+#define MBOX_DISABLE_IRQ 0x4
+#define MBOX_ENABLE_IRQ  0x0
+#define MBOX_LATCH 1
+
+/* Global list of all mailboxes */
+static struct list_head mboxs = LIST_HEAD_INIT(mboxs);
+
+static struct mbox *get_mbox_with_id(u8 id)
+{
+	u8 i;
+	struct list_head *pos = &mboxs;
+	for (i = 0; i <= id; i++)
+		pos = pos->next;
+
+	return (struct mbox *) list_entry(pos, struct mbox, list);
+}
+
+int mbox_send(struct mbox *mbox, u32 mbox_msg, bool block)
+{
+	int res = 0;
+
+	spin_lock(&mbox->lock);
+
+	dev_dbg(&(mbox->pdev->dev),
+		"About to buffer 0x%X to mailbox 0x%X."
+		" ri = %d, wi = %d\n",
+		mbox_msg, (u32)mbox, mbox->read_index,
+		mbox->write_index);
+
+	/* Check if write buffer is full */
+	while (((mbox->write_index + 1) % MBOX_BUF_SIZE) == mbox->read_index) {
+		if (!block) {
+			dev_dbg(&(mbox->pdev->dev),
+			"Buffer full in non-blocking call! "
+			"Returning -ENOMEM!\n");
+			res = -ENOMEM;
+			goto exit;
+		}
+		spin_unlock(&mbox->lock);
+		dev_dbg(&(mbox->pdev->dev),
+			"Buffer full in blocking call! Sleeping...\n");
+		mbox->client_blocked = 1;
+		wait_for_completion(&mbox->buffer_available);
+		dev_dbg(&(mbox->pdev->dev),
+			"Blocking send was woken up! Trying again...\n");
+		spin_lock(&mbox->lock);
+	}
+
+	mbox->buffer[mbox->write_index] = mbox_msg;
+	mbox->write_index = (mbox->write_index + 1) % MBOX_BUF_SIZE;
+
+	/*
+	 * Indicate that we want an IRQ as soon as there is a slot
+	 * in the FIFO
+	 */
+	writel(MBOX_ENABLE_IRQ, mbox->virtbase_peer + MBOX_FIFO_THRES_FREE);
+
+exit:
+	spin_unlock(&mbox->lock);
+	return res;
+}
+EXPORT_SYMBOL(mbox_send);
+
+#if defined(CONFIG_DEBUG_FS)
+/*
+ * Expected input: <value> <nbr sends>
+ * Example: "echo 0xdeadbeef 4 > mbox-node" sends 0xdeadbeef 4 times
+ */
+static ssize_t mbox_write_fifo(struct device *dev,
+			       struct device_attribute *attr,
+			       const char *buf,
+			       size_t count)
+{
+	unsigned long mbox_mess;
+	unsigned long nbr_sends;
+	unsigned long i;
+	char int_buf[16];
+	char *token;
+	char *val;
+
+	struct mbox *mbox = (struct mbox *) dev->platform_data;
+
+	strncpy((char *) &int_buf, buf, sizeof(int_buf));
+	token = (char *) &int_buf;
+
+	/* Parse message */
+	val = strsep(&token, " ");
+	if ((val == NULL) || (strict_strtoul(val, 16, &mbox_mess) != 0))
+		mbox_mess = 0xDEADBEEF;
+
+	val = strsep(&token, " ");
+	if ((val == NULL) || (strict_strtoul(val, 10, &nbr_sends) != 0))
+		nbr_sends = 1;
+
+	dev_dbg(dev, "Will write 0x%lX %ld times using data struct at 0x%X\n",
+		mbox_mess, nbr_sends, (u32) mbox);
+
+	for (i = 0; i < nbr_sends; i++)
+		mbox_send(mbox, mbox_mess, true);
+
+	return count;
+}
+
+static ssize_t mbox_read_fifo(struct device *dev,
+			      struct device_attribute *attr,
+			      char *buf)
+{
+	int mbox_value;
+	struct mbox *mbox = (struct mbox *) dev->platform_data;
+
+	if ((readl(mbox->virtbase_local + MBOX_FIFO_STATUS) & 0x7) <= 0)
+		return sprintf(buf, "Mailbox is empty\n");
+
+	mbox_value = readl(mbox->virtbase_local + MBOX_FIFO_DATA);
+	writel(MBOX_LATCH, (mbox->virtbase_local + MBOX_FIFO_REMOVE));
+
+	return sprintf(buf, "0x%X\n", mbox_value);
+}
+
+static DEVICE_ATTR(fifo, S_IWUGO | S_IRUGO, mbox_read_fifo, mbox_write_fifo);
+
+static int mbox_show(struct seq_file *s, void *data)
+{
+	struct list_head *pos;
+	u8 mbox_index = 0;
+
+	list_for_each(pos, &mboxs) {
+		struct mbox *m =
+			(struct mbox *) list_entry(pos, struct mbox, list);
+		if (m == NULL) {
+			seq_printf(s,
+				   "Unable to retrieve mailbox %d\n",
+				   mbox_index);
+			continue;
+		}
+
+		spin_lock(&m->lock);
+		if ((m->virtbase_peer == NULL) || (m->virtbase_local == NULL)) {
+			seq_printf(s, "MAILBOX %d not setup or corrupt\n",
+				   mbox_index);
+			spin_unlock(&m->lock);
+			continue;
+		}
+
+		seq_printf(s,
+		"===========================\n"
+		" MAILBOX %d\n"
+		" PEER MAILBOX DUMP\n"
+		"---------------------------\n"
+		"FIFO:                 0x%X (%d)\n"
+		"Free     Threshold:   0x%.2X (%d)\n"
+		"Occupied Threshold:   0x%.2X (%d)\n"
+		"Status:               0x%.2X (%d)\n"
+		"   Free spaces  (ot):    %d (%d)\n"
+		"   Occup spaces (ot):    %d (%d)\n"
+		"===========================\n"
+		" LOCAL MAILBOX DUMP\n"
+		"---------------------------\n"
+		"FIFO:                 0x%.X (%d)\n"
+		"Free     Threshold:   0x%.2X (%d)\n"
+		"Occupied Threshold:   0x%.2X (%d)\n"
+		"Status:               0x%.2X (%d)\n"
+		"   Free spaces  (ot):    %d (%d)\n"
+		"   Occup spaces (ot):    %d (%d)\n"
+		"===========================\n"
+		"write_index: %d\n"
+		"read_index : %d\n"
+		"===========================\n"
+		"\n",
+		mbox_index,
+		readl(m->virtbase_peer + MBOX_FIFO_DATA),
+		readl(m->virtbase_peer + MBOX_FIFO_DATA),
+		readl(m->virtbase_peer + MBOX_FIFO_THRES_FREE),
+		readl(m->virtbase_peer + MBOX_FIFO_THRES_FREE),
+		readl(m->virtbase_peer + MBOX_FIFO_THRES_OCCUP),
+		readl(m->virtbase_peer + MBOX_FIFO_THRES_OCCUP),
+		readl(m->virtbase_peer + MBOX_FIFO_STATUS),
+		readl(m->virtbase_peer + MBOX_FIFO_STATUS),
+		(readl(m->virtbase_peer + MBOX_FIFO_STATUS) >> 4) & 0x7,
+		(readl(m->virtbase_peer + MBOX_FIFO_STATUS) >> 7) & 0x1,
+		(readl(m->virtbase_peer + MBOX_FIFO_STATUS) >> 0) & 0x7,
+		(readl(m->virtbase_peer + MBOX_FIFO_STATUS) >> 3) & 0x1,
+		readl(m->virtbase_local + MBOX_FIFO_DATA),
+		readl(m->virtbase_local + MBOX_FIFO_DATA),
+		readl(m->virtbase_local + MBOX_FIFO_THRES_FREE),
+		readl(m->virtbase_local + MBOX_FIFO_THRES_FREE),
+		readl(m->virtbase_local + MBOX_FIFO_THRES_OCCUP),
+		readl(m->virtbase_local + MBOX_FIFO_THRES_OCCUP),
+		readl(m->virtbase_local + MBOX_FIFO_STATUS),
+		readl(m->virtbase_local + MBOX_FIFO_STATUS),
+		(readl(m->virtbase_local + MBOX_FIFO_STATUS) >> 4) & 0x7,
+		(readl(m->virtbase_local + MBOX_FIFO_STATUS) >> 7) & 0x1,
+		(readl(m->virtbase_local + MBOX_FIFO_STATUS) >> 0) & 0x7,
+		(readl(m->virtbase_local + MBOX_FIFO_STATUS) >> 3) & 0x1,
+		m->write_index, m->read_index);
+		mbox_index++;
+		spin_unlock(&m->lock);
+	}
+
+	return 0;
+}
+
+static int mbox_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, mbox_show, NULL);
+}
+
+static const struct file_operations mbox_operations = {
+	.owner = THIS_MODULE,
+	.open = mbox_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
+#endif
+
+static irqreturn_t mbox_irq(int irq, void *arg)
+{
+	u32 mbox_value;
+	int nbr_occup;
+	int nbr_free;
+	struct mbox *mbox = (struct mbox *) arg;
+
+	spin_lock(&mbox->lock);
+
+	dev_dbg(&(mbox->pdev->dev),
+		"mbox IRQ [%d] received. ri = %d, wi = %d\n",
+		irq, mbox->read_index, mbox->write_index);
+
+	/*
+	 * Check if we have any outgoing messages, and if there is space for
+	 * them in the FIFO.
+	 */
+	if (mbox->read_index != mbox->write_index) {
+		/*
+		 * Check by reading FREE for LOCAL since that indicates
+		 * OCCUP for PEER
+		 */
+		nbr_free = (readl(mbox->virtbase_local + MBOX_FIFO_STATUS)
+			    >> 4) & 0x7;
+		dev_dbg(&(mbox->pdev->dev),
+			"Status indicates %d empty spaces in the FIFO!\n",
+			nbr_free);
+
+		while ((nbr_free > 0) &&
+		       (mbox->read_index != mbox->write_index)) {
+			/* Write the message and latch it into the FIFO */
+			writel(mbox->buffer[mbox->read_index],
+			       (mbox->virtbase_peer + MBOX_FIFO_DATA));
+			writel(MBOX_LATCH,
+			       (mbox->virtbase_peer + MBOX_FIFO_ADD));
+			dev_dbg(&(mbox->pdev->dev),
+				"Wrote message 0x%X to addr 0x%X\n",
+				mbox->buffer[mbox->read_index],
+				(u32) (mbox->virtbase_peer + MBOX_FIFO_DATA));
+
+			nbr_free--;
+			mbox->read_index =
+				(mbox->read_index + 1) % MBOX_BUF_SIZE;
+		}
+
+		/*
+		 * Check if we still want IRQ:s when there is free
+		 * space to send
+		 */
+		if (mbox->read_index != mbox->write_index) {
+			dev_dbg(&(mbox->pdev->dev),
+				"Still have messages to send, but FIFO full. "
+				"Request IRQ again!\n");
+			writel(MBOX_ENABLE_IRQ,
+			       mbox->virtbase_peer + MBOX_FIFO_THRES_FREE);
+		} else {
+			dev_dbg(&(mbox->pdev->dev),
+				"No more messages to send. "
+				"Do not request IRQ again!\n");
+			writel(MBOX_DISABLE_IRQ,
+			       mbox->virtbase_peer + MBOX_FIFO_THRES_FREE);
+		}
+
+		/*
+		 * Check if we can signal any blocked clients that it is OK to
+		 * start buffering again
+		 */
+		if (mbox->client_blocked &&
+		    (((mbox->write_index + 1) % MBOX_BUF_SIZE)
+		     != mbox->read_index)) {
+			dev_dbg(&(mbox->pdev->dev),
+				"Waking up blocked client\n");
+			complete(&mbox->buffer_available);
+			mbox->client_blocked = 0;
+		}
+	}
+
+	/* Check if we have any incoming messages */
+	nbr_occup = readl(mbox->virtbase_local + MBOX_FIFO_STATUS) & 0x7;
+	if (nbr_occup == 0)
+		goto exit;
+
+	if (mbox->cb == NULL) {
+		dev_dbg(&(mbox->pdev->dev), "No receive callback registered, "
+			"leaving %d incoming messages in fifo!\n", nbr_occup);
+		goto exit;
+	}
+
+	/* Read and acknowledge the message */
+	mbox_value = readl(mbox->virtbase_local + MBOX_FIFO_DATA);
+	writel(MBOX_LATCH, (mbox->virtbase_local + MBOX_FIFO_REMOVE));
+
+	/* Notify consumer of new mailbox message */
+	dev_dbg(&(mbox->pdev->dev), "Calling callback for message 0x%X!\n",
+		mbox_value);
+	mbox->cb(mbox_value, mbox->client_data);
+
+exit:
+	dev_dbg(&(mbox->pdev->dev), "Exit mbox IRQ. ri = %d, wi = %d\n",
+		mbox->read_index, mbox->write_index);
+	spin_unlock(&mbox->lock);
+
+	return IRQ_HANDLED;
+}
+
+/* Setup is executed once for each mbox pair */
+struct mbox *mbox_setup(u8 mbox_id, mbox_recv_cb_t *mbox_cb, void *priv)
+{
+	struct resource *resource;
+	int irq;
+	int res;
+	struct mbox *mbox;
+
+	mbox = get_mbox_with_id(mbox_id);
+	if (mbox == NULL) {
+		dev_err(&(mbox->pdev->dev), "Incorrect mailbox id: %d!\n",
+			mbox_id);
+		goto exit;
+	}
+
+	/*
+	 * Check if mailbox has been allocated to someone else,
+	 * otherwise allocate it
+	 */
+	if (mbox->allocated) {
+		dev_err(&(mbox->pdev->dev), "Mailbox number %d is busy!\n",
+			mbox_id);
+		mbox = NULL;
+		goto exit;
+	}
+	mbox->allocated = true;
+
+	dev_dbg(&(mbox->pdev->dev), "Initiating mailbox number %d: 0x%X...\n",
+		mbox_id, (u32)mbox);
+
+	mbox->client_data = priv;
+	mbox->cb = mbox_cb;
+
+	/* Get addr for peer mailbox and ioremap it */
+	resource = platform_get_resource_byname(mbox->pdev,
+						IORESOURCE_MEM,
+						"mbox_peer");
+	if (resource == NULL) {
+		dev_err(&(mbox->pdev->dev),
+			"Unable to retrieve mbox peer resource\n");
+		mbox = NULL;
+		goto exit;
+	}
+	dev_dbg(&(mbox->pdev->dev),
+		"Resource name: %s start: 0x%X, end: 0x%X\n",
+		resource->name, resource->start, resource->end);
+	mbox->virtbase_peer =
+		ioremap(resource->start, resource->end - resource->start);
+	if (!mbox->virtbase_peer) {
+		dev_err(&(mbox->pdev->dev), "Unable to ioremap peer mbox\n");
+		mbox = NULL;
+		goto exit;
+	}
+	dev_dbg(&(mbox->pdev->dev),
+		"ioremapped peer physical: (0x%X-0x%X) to virtual: 0x%X\n",
+		resource->start, resource->end, (u32) mbox->virtbase_peer);
+
+	/* Get addr for local mailbox and ioremap it */
+	resource = platform_get_resource_byname(mbox->pdev,
+						IORESOURCE_MEM,
+						"mbox_local");
+	if (resource == NULL) {
+		dev_err(&(mbox->pdev->dev),
+			"Unable to retrieve mbox local resource\n");
+		mbox = NULL;
+		goto exit;
+	}
+	dev_dbg(&(mbox->pdev->dev),
+		"Resource name: %s start: 0x%X, end: 0x%X\n",
+		resource->name, resource->start, resource->end);
+	mbox->virtbase_local =
+		ioremap(resource->start, resource->end - resource->start);
+	if (!mbox->virtbase_local) {
+		dev_err(&(mbox->pdev->dev), "Unable to ioremap local mbox\n");
+		mbox = NULL;
+		goto exit;
+	}
+	dev_dbg(&(mbox->pdev->dev),
+		"ioremapped local physical: (0x%X-0x%X) to virtual: 0x%X\n",
+		resource->start, resource->end, (u32) mbox->virtbase_peer);
+
+	init_completion(&mbox->buffer_available);
+	mbox->client_blocked = 0;
+
+	/* Get IRQ for mailbox and allocate it */
+	irq = platform_get_irq_byname(mbox->pdev, "mbox_irq");
+	if (irq < 0) {
+		dev_err(&(mbox->pdev->dev),
+			"Unable to retrieve mbox irq resource\n");
+		mbox = NULL;
+		goto exit;
+	}
+
+	dev_dbg(&(mbox->pdev->dev), "Allocating irq %d...\n", irq);
+	res = request_irq(irq, mbox_irq, 0, mbox->name, (void *) mbox);
+	if (res < 0) {
+		dev_err(&(mbox->pdev->dev),
+			"Unable to allocate mbox irq %d\n", irq);
+		mbox = NULL;
+		goto exit;
+	}
+
+	/* Set up mailbox to not launch IRQ on free space in mailbox */
+	writel(MBOX_DISABLE_IRQ, mbox->virtbase_peer + MBOX_FIFO_THRES_FREE);
+
+	/*
+	 * Set up mailbox to launch IRQ on new message if we have
+	 * a callback set. If not, do not raise IRQ, but keep message
+	 * in FIFO for manual retrieval
+	 */
+	if (mbox_cb != NULL)
+		writel(MBOX_ENABLE_IRQ,
+		       mbox->virtbase_local + MBOX_FIFO_THRES_OCCUP);
+	else
+		writel(MBOX_DISABLE_IRQ,
+		       mbox->virtbase_local + MBOX_FIFO_THRES_OCCUP);
+
+#if defined(CONFIG_DEBUG_FS)
+	res = device_create_file(&(mbox->pdev->dev), &dev_attr_fifo);
+	if (res != 0)
+		dev_warn(&(mbox->pdev->dev),
+			 "Unable to create mbox sysfs entry");
+
+	(void) debugfs_create_file("mbox", S_IFREG | S_IRUGO, NULL,
+				   NULL, &mbox_operations);
+#endif
+
+	dev_info(&(mbox->pdev->dev),
+		 "Mailbox driver with index %d initated!\n", mbox_id);
+
+exit:
+	return mbox;
+}
+EXPORT_SYMBOL(mbox_setup);
+
+
+int __init mbox_probe(struct platform_device *pdev)
+{
+	struct mbox local_mbox;
+	struct mbox *mbox;
+	int res = 0;
+	dev_dbg(&(pdev->dev), "Probing mailbox (pdev = 0x%X)...\n", (u32) pdev);
+
+	memset(&local_mbox, 0x0, sizeof(struct mbox));
+
+	/* Associate our mbox data with the platform device */
+	res = platform_device_add_data(pdev,
+				       (void *) &local_mbox,
+				       sizeof(struct mbox));
+	if (res != 0) {
+		dev_err(&(pdev->dev),
+			"Unable to allocate driver platform data!\n");
+		goto exit;
+	}
+
+	mbox = (struct mbox *) pdev->dev.platform_data;
+	mbox->pdev = pdev;
+	mbox->write_index = 0;
+	mbox->read_index = 0;
+
+	INIT_LIST_HEAD(&(mbox->list));
+	list_add_tail(&(mbox->list), &mboxs);
+
+	sprintf(mbox->name, "%s", MBOX_NAME);
+	spin_lock_init(&mbox->lock);
+
+	dev_info(&(pdev->dev), "Mailbox driver loaded\n");
+
+exit:
+	return res;
+}
+
+static struct platform_driver mbox_driver = {
+	.driver = {
+		.name = MBOX_NAME,
+		.owner = THIS_MODULE,
+	},
+};
+
+static int __init mbox_init(void)
+{
+	return platform_driver_probe(&mbox_driver, mbox_probe);
+}
+
+module_init(mbox_init);
+
+void __exit mbox_exit(void)
+{
+	platform_driver_unregister(&mbox_driver);
+}
+
+module_exit(mbox_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("MBOX driver");
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-ux500/modem_irq.c linux-libre-2.6.38-gnu1/arch/arm/mach-ux500/modem_irq.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-ux500/modem_irq.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-ux500/modem_irq.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,139 +0,0 @@
-/*
- * Copyright (C) ST-Ericsson SA 2010
- * Author: Stefan Nilsson <stefan.xk.nilsson@stericsson.com> for ST-Ericsson.
- * Author: Martin Persson <martin.persson@stericsson.com> for ST-Ericsson.
- * License terms: GNU General Public License (GPL), version 2.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/irq.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-
-#define MODEM_INTCON_BASE_ADDR 0xBFFD3000
-#define MODEM_INTCON_SIZE 0xFFF
-
-#define DEST_IRQ41_OFFSET 0x2A4
-#define DEST_IRQ43_OFFSET 0x2AC
-#define DEST_IRQ45_OFFSET 0x2B4
-
-#define PRIO_IRQ41_OFFSET 0x6A4
-#define PRIO_IRQ43_OFFSET 0x6AC
-#define PRIO_IRQ45_OFFSET 0x6B4
-
-#define ALLOW_IRQ_OFFSET 0x104
-
-#define MODEM_INTCON_CPU_NBR 0x1
-#define MODEM_INTCON_PRIO_HIGH 0x0
-
-#define MODEM_INTCON_ALLOW_IRQ41 0x0200
-#define MODEM_INTCON_ALLOW_IRQ43 0x0800
-#define MODEM_INTCON_ALLOW_IRQ45 0x2000
-
-#define MODEM_IRQ_REG_OFFSET 0x4
-
-struct modem_irq {
-	void __iomem *modem_intcon_base;
-};
-
-
-static void setup_modem_intcon(void __iomem *modem_intcon_base)
-{
-	/* IC_DESTINATION_BASE_ARRAY - Which CPU to receive the IRQ */
-	writel(MODEM_INTCON_CPU_NBR, modem_intcon_base + DEST_IRQ41_OFFSET);
-	writel(MODEM_INTCON_CPU_NBR, modem_intcon_base + DEST_IRQ43_OFFSET);
-	writel(MODEM_INTCON_CPU_NBR, modem_intcon_base + DEST_IRQ45_OFFSET);
-
-	/* IC_PRIORITY_BASE_ARRAY - IRQ priority in modem IRQ controller */
-	writel(MODEM_INTCON_PRIO_HIGH, modem_intcon_base + PRIO_IRQ41_OFFSET);
-	writel(MODEM_INTCON_PRIO_HIGH, modem_intcon_base + PRIO_IRQ43_OFFSET);
-	writel(MODEM_INTCON_PRIO_HIGH, modem_intcon_base + PRIO_IRQ45_OFFSET);
-
-	/* IC_ALLOW_ARRAY - IRQ enable */
-	writel(MODEM_INTCON_ALLOW_IRQ41 |
-		   MODEM_INTCON_ALLOW_IRQ43 |
-		   MODEM_INTCON_ALLOW_IRQ45,
-		   modem_intcon_base + ALLOW_IRQ_OFFSET);
-}
-
-static irqreturn_t modem_cpu_irq_handler(int irq, void *data)
-{
-	int real_irq;
-	int virt_irq;
-	struct modem_irq *mi = (struct modem_irq *)data;
-
-	/* Read modem side IRQ number from modem IRQ controller */
-	real_irq = readl(mi->modem_intcon_base + MODEM_IRQ_REG_OFFSET) & 0xFF;
-	virt_irq = IRQ_MODEM_EVENTS_BASE + real_irq;
-
-	pr_debug("modem_irq: Worker read addr 0x%X and got value 0x%X "
-		 "which will be 0x%X (%d) which translates to "
-		 "virtual IRQ 0x%X (%d)!\n",
-		   (u32)mi->modem_intcon_base + MODEM_IRQ_REG_OFFSET,
-		   real_irq,
-		   real_irq & 0xFF,
-		   real_irq & 0xFF,
-		   virt_irq,
-		   virt_irq);
-
-	if (virt_irq != 0)
-		generic_handle_irq(virt_irq);
-
-	pr_debug("modem_irq: Done handling virtual IRQ %d!\n", virt_irq);
-
-	return IRQ_HANDLED;
-}
-
-static void create_virtual_irq(int irq, struct irq_chip *modem_irq_chip)
-{
-	set_irq_chip(irq, modem_irq_chip);
-	set_irq_handler(irq, handle_simple_irq);
-	set_irq_flags(irq, IRQF_VALID);
-
-	pr_debug("modem_irq: Created virtual IRQ %d\n", irq);
-}
-
-static int modem_irq_init(void)
-{
-	int err;
-	static struct irq_chip  modem_irq_chip;
-	struct modem_irq *mi;
-
-	pr_info("modem_irq: Set up IRQ handler for incoming modem IRQ %d\n",
-		   IRQ_DB5500_MODEM);
-
-	mi = kmalloc(sizeof(struct modem_irq), GFP_KERNEL);
-	if (!mi) {
-		pr_err("modem_irq: Could not allocate device\n");
-		return -ENOMEM;
-	}
-
-	mi->modem_intcon_base =
-		ioremap(MODEM_INTCON_BASE_ADDR, MODEM_INTCON_SIZE);
-	pr_debug("modem_irq: ioremapped modem_intcon_base from "
-		 "phy 0x%x to virt 0x%x\n", MODEM_INTCON_BASE_ADDR,
-		 (u32)mi->modem_intcon_base);
-
-	setup_modem_intcon(mi->modem_intcon_base);
-
-	modem_irq_chip = dummy_irq_chip;
-	modem_irq_chip.name = "modem_irq";
-
-	/* Create the virtual IRQ:s needed */
-	create_virtual_irq(MBOX_PAIR0_VIRT_IRQ, &modem_irq_chip);
-	create_virtual_irq(MBOX_PAIR1_VIRT_IRQ, &modem_irq_chip);
-	create_virtual_irq(MBOX_PAIR2_VIRT_IRQ, &modem_irq_chip);
-
-	err = request_threaded_irq(IRQ_DB5500_MODEM, NULL,
-				   modem_cpu_irq_handler, IRQF_ONESHOT,
-				   "modem_irq", mi);
-	if (err)
-		pr_err("modem_irq: Could not register IRQ %d\n",
-		       IRQ_DB5500_MODEM);
-
-	return 0;
-}
-
-arch_initcall(modem_irq_init);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-ux500/modem-irq-db5500.c linux-libre-2.6.38-gnu1/arch/arm/mach-ux500/modem-irq-db5500.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-ux500/modem-irq-db5500.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-ux500/modem-irq-db5500.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ * Author: Stefan Nilsson <stefan.xk.nilsson@stericsson.com> for ST-Ericsson.
+ * Author: Martin Persson <martin.persson@stericsson.com> for ST-Ericsson.
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+
+#include <mach/id.h>
+
+#define MODEM_INTCON_BASE_ADDR 0xBFFD3000
+#define MODEM_INTCON_SIZE 0xFFF
+
+#define DEST_IRQ41_OFFSET 0x2A4
+#define DEST_IRQ43_OFFSET 0x2AC
+#define DEST_IRQ45_OFFSET 0x2B4
+
+#define PRIO_IRQ41_OFFSET 0x6A4
+#define PRIO_IRQ43_OFFSET 0x6AC
+#define PRIO_IRQ45_OFFSET 0x6B4
+
+#define ALLOW_IRQ_OFFSET 0x104
+
+#define MODEM_INTCON_CPU_NBR 0x1
+#define MODEM_INTCON_PRIO_HIGH 0x0
+
+#define MODEM_INTCON_ALLOW_IRQ41 0x0200
+#define MODEM_INTCON_ALLOW_IRQ43 0x0800
+#define MODEM_INTCON_ALLOW_IRQ45 0x2000
+
+#define MODEM_IRQ_REG_OFFSET 0x4
+
+struct modem_irq {
+	void __iomem *modem_intcon_base;
+};
+
+
+static void setup_modem_intcon(void __iomem *modem_intcon_base)
+{
+	/* IC_DESTINATION_BASE_ARRAY - Which CPU to receive the IRQ */
+	writel(MODEM_INTCON_CPU_NBR, modem_intcon_base + DEST_IRQ41_OFFSET);
+	writel(MODEM_INTCON_CPU_NBR, modem_intcon_base + DEST_IRQ43_OFFSET);
+	writel(MODEM_INTCON_CPU_NBR, modem_intcon_base + DEST_IRQ45_OFFSET);
+
+	/* IC_PRIORITY_BASE_ARRAY - IRQ priority in modem IRQ controller */
+	writel(MODEM_INTCON_PRIO_HIGH, modem_intcon_base + PRIO_IRQ41_OFFSET);
+	writel(MODEM_INTCON_PRIO_HIGH, modem_intcon_base + PRIO_IRQ43_OFFSET);
+	writel(MODEM_INTCON_PRIO_HIGH, modem_intcon_base + PRIO_IRQ45_OFFSET);
+
+	/* IC_ALLOW_ARRAY - IRQ enable */
+	writel(MODEM_INTCON_ALLOW_IRQ41 |
+		   MODEM_INTCON_ALLOW_IRQ43 |
+		   MODEM_INTCON_ALLOW_IRQ45,
+		   modem_intcon_base + ALLOW_IRQ_OFFSET);
+}
+
+static irqreturn_t modem_cpu_irq_handler(int irq, void *data)
+{
+	int real_irq;
+	int virt_irq;
+	struct modem_irq *mi = (struct modem_irq *)data;
+
+	/* Read modem side IRQ number from modem IRQ controller */
+	real_irq = readl(mi->modem_intcon_base + MODEM_IRQ_REG_OFFSET) & 0xFF;
+	virt_irq = IRQ_MODEM_EVENTS_BASE + real_irq;
+
+	pr_debug("modem_irq: Worker read addr 0x%X and got value 0x%X "
+		 "which will be 0x%X (%d) which translates to "
+		 "virtual IRQ 0x%X (%d)!\n",
+		   (u32)mi->modem_intcon_base + MODEM_IRQ_REG_OFFSET,
+		   real_irq,
+		   real_irq & 0xFF,
+		   real_irq & 0xFF,
+		   virt_irq,
+		   virt_irq);
+
+	if (virt_irq != 0)
+		generic_handle_irq(virt_irq);
+
+	pr_debug("modem_irq: Done handling virtual IRQ %d!\n", virt_irq);
+
+	return IRQ_HANDLED;
+}
+
+static void create_virtual_irq(int irq, struct irq_chip *modem_irq_chip)
+{
+	set_irq_chip(irq, modem_irq_chip);
+	set_irq_handler(irq, handle_simple_irq);
+	set_irq_flags(irq, IRQF_VALID);
+
+	pr_debug("modem_irq: Created virtual IRQ %d\n", irq);
+}
+
+static int modem_irq_init(void)
+{
+	int err;
+	static struct irq_chip  modem_irq_chip;
+	struct modem_irq *mi;
+
+	if (!cpu_is_u5500())
+		return -ENODEV;
+
+	pr_info("modem_irq: Set up IRQ handler for incoming modem IRQ %d\n",
+		   IRQ_DB5500_MODEM);
+
+	mi = kmalloc(sizeof(struct modem_irq), GFP_KERNEL);
+	if (!mi) {
+		pr_err("modem_irq: Could not allocate device\n");
+		return -ENOMEM;
+	}
+
+	mi->modem_intcon_base =
+		ioremap(MODEM_INTCON_BASE_ADDR, MODEM_INTCON_SIZE);
+	pr_debug("modem_irq: ioremapped modem_intcon_base from "
+		 "phy 0x%x to virt 0x%x\n", MODEM_INTCON_BASE_ADDR,
+		 (u32)mi->modem_intcon_base);
+
+	setup_modem_intcon(mi->modem_intcon_base);
+
+	modem_irq_chip = dummy_irq_chip;
+	modem_irq_chip.name = "modem_irq";
+
+	/* Create the virtual IRQ:s needed */
+	create_virtual_irq(MBOX_PAIR0_VIRT_IRQ, &modem_irq_chip);
+	create_virtual_irq(MBOX_PAIR1_VIRT_IRQ, &modem_irq_chip);
+	create_virtual_irq(MBOX_PAIR2_VIRT_IRQ, &modem_irq_chip);
+
+	err = request_threaded_irq(IRQ_DB5500_MODEM, NULL,
+				   modem_cpu_irq_handler, IRQF_ONESHOT,
+				   "modem_irq", mi);
+	if (err)
+		pr_err("modem_irq: Could not register IRQ %d\n",
+		       IRQ_DB5500_MODEM);
+
+	return 0;
+}
+
+arch_initcall(modem_irq_init);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-ux500/platsmp.c linux-libre-2.6.38-gnu1/arch/arm/mach-ux500/platsmp.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-ux500/platsmp.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-ux500/platsmp.c	2011-03-14 21:20:32.000000000 -0400
@@ -18,39 +18,57 @@
 #include <linux/io.h>
 
 #include <asm/cacheflush.h>
-#include <asm/localtimer.h>
 #include <asm/smp_scu.h>
 #include <mach/hardware.h>
+#include <mach/setup.h>
 
 /*
  * control for which core is the next to come out of the secondary
  * boot "holding pen"
  */
-volatile int __cpuinitdata pen_release = -1;
+volatile int pen_release = -1;
 
-static unsigned int __init get_core_count(void)
+/*
+ * 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)
 {
-	return scu_get_core_count(__io_address(UX500_SCU_BASE));
+	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)
+{
+	if (cpu_is_u5500())
+		return __io_address(U5500_SCU_BASE);
+	else if (cpu_is_u8500())
+		return __io_address(U8500_SCU_BASE);
+	else
+		ux500_unknown_soc();
+
+	return NULL;
 }
 
 static DEFINE_SPINLOCK(boot_lock);
 
 void __cpuinit platform_secondary_init(unsigned int cpu)
 {
-	trace_hardirqs_off();
-
 	/*
 	 * 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_cpu_init(0, __io_address(UX500_GIC_CPU_BASE));
+	gic_secondary_init(0);
 
 	/*
 	 * let the primary processor know we're out of the
 	 * pen, then head off into the C entry point
 	 */
-	pen_release = -1;
+	write_pen_release(-1);
 
 	/*
 	 * Synchronise with the boot thread.
@@ -74,11 +92,9 @@ 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.
 	 */
-	pen_release = cpu;
-	__cpuc_flush_dcache_area((void *)&pen_release, sizeof(pen_release));
-	outer_clean_range(__pa(&pen_release), __pa(&pen_release) + 1);
+	write_pen_release(cpu);
 
-	smp_cross_call(cpumask_of(cpu));
+	smp_cross_call(cpumask_of(cpu), 1);
 
 	timeout = jiffies + (1 * HZ);
 	while (time_before(jiffies, timeout)) {
@@ -97,8 +113,14 @@ int __cpuinit boot_secondary(unsigned in
 
 static void __init wakeup_secondary(void)
 {
-	/* nobody is to be released from the pen yet */
-	pen_release = -1;
+	void __iomem *backupram;
+
+	if (cpu_is_u5500())
+		backupram = __io_address(U5500_BACKUPRAM0_BASE);
+	else if (cpu_is_u8500())
+		backupram = __io_address(U8500_BACKUPRAM0_BASE);
+	else
+		ux500_unknown_soc();
 
 	/*
 	 * write the address of secondary startup into the backup ram register
@@ -106,15 +128,13 @@ static void __init wakeup_secondary(void
 	 * backup ram register at offset 0x1FF0, which is what boot rom code
 	 * is waiting for. This would wake up the secondary core from WFE
 	 */
-#define U8500_CPU1_JUMPADDR_OFFSET 0x1FF4
+#define UX500_CPU1_JUMPADDR_OFFSET 0x1FF4
 	__raw_writel(virt_to_phys(u8500_secondary_startup),
-		__io_address(UX500_BACKUPRAM0_BASE) +
-		U8500_CPU1_JUMPADDR_OFFSET);
+		     backupram + UX500_CPU1_JUMPADDR_OFFSET);
 
-#define U8500_CPU1_WAKEMAGIC_OFFSET 0x1FF0
+#define UX500_CPU1_WAKEMAGIC_OFFSET 0x1FF0
 	__raw_writel(0xA1FEED01,
-		__io_address(UX500_BACKUPRAM0_BASE) +
-		U8500_CPU1_WAKEMAGIC_OFFSET);
+		     backupram + UX500_CPU1_WAKEMAGIC_OFFSET);
 
 	/* make sure write buffer is drained */
 	mb();
@@ -126,40 +146,27 @@ static void __init wakeup_secondary(void
  */
 void __init smp_init_cpus(void)
 {
-	unsigned int i, ncores = get_core_count();
-
-	for (i = 0; i < ncores; i++)
-		set_cpu_possible(i, true);
-}
+	void __iomem *scu_base = scu_base_addr();
+	unsigned int i, ncores;
 
-void __init smp_prepare_cpus(unsigned int max_cpus)
-{
-	unsigned int ncores = get_core_count();
-	unsigned int cpu = smp_processor_id();
-	int i;
+	ncores = scu_base ? scu_get_core_count(scu_base) : 1;
 
 	/* sanity check */
-	if (ncores == 0) {
-		printk(KERN_ERR
-		       "U8500: strange CM count of 0? Default to 1\n");
-		ncores = 1;
-	}
-
-	if (ncores > num_possible_cpus())	{
+	if (ncores > NR_CPUS) {
 		printk(KERN_WARNING
 		       "U8500: no. of cores (%d) greater than configured "
 		       "maximum of %d - clipping\n",
-		       ncores, num_possible_cpus());
-		ncores = num_possible_cpus();
+		       ncores, NR_CPUS);
+		ncores = NR_CPUS;
 	}
 
-	smp_store_cpu_info(cpu);
+	for (i = 0; i < ncores; i++)
+		set_cpu_possible(i, true);
+}
 
-	/*
-	 * are we trying to boot more cores than exist?
-	 */
-	if (max_cpus > ncores)
-		max_cpus = ncores;
+void __init platform_smp_prepare_cpus(unsigned int max_cpus)
+{
+	int i;
 
 	/*
 	 * Initialise the present map, which describes the set of CPUs
@@ -168,13 +175,6 @@ void __init smp_prepare_cpus(unsigned in
 	for (i = 0; i < max_cpus; i++)
 		set_cpu_present(i, true);
 
-	if (max_cpus > 1) {
-		/*
-		 * Enable the local timer or broadcast device for the
-		 * boot CPU, but only if we have more than one CPU.
-		 */
-		percpu_timer_setup();
-		scu_enable(__io_address(UX500_SCU_BASE));
-		wakeup_secondary();
-	}
+	scu_enable(scu_base_addr());
+	wakeup_secondary();
 }
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-ux500/prcmu.c linux-libre-2.6.38-gnu1/arch/arm/mach-ux500/prcmu.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-ux500/prcmu.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-ux500/prcmu.c	2011-03-14 21:20:32.000000000 -0400
@@ -1,10 +1,14 @@
 /*
- * Copyright (C) ST Ericsson SA 2010
+ * Copyright (C) STMicroelectronics 2009
+ * Copyright (C) ST-Ericsson SA 2010
  *
  * License Terms: GNU General Public License v2
+ * Author: Kumar Sanghvi <kumar.sanghvi@stericsson.com>
+ * Author: Sundar Iyer <sundar.iyer@stericsson.com>
  * Author: Mattias Nilsson <mattias.i.nilsson@stericsson.com>
  *
- * U8500 PRCMU driver.
+ * U8500 PRCM Unit interface driver
+ *
  */
 #include <linux/kernel.h>
 #include <linux/module.h>
@@ -19,11 +23,26 @@
 
 #include <mach/hardware.h>
 #include <mach/prcmu-regs.h>
+#include <mach/prcmu-defs.h>
 
-#define PRCMU_TCDM_BASE __io_address(U8500_PRCMU_TCDM_BASE)
+/* Global var to runtime determine TCDM base for v2 or v1 */
+static __iomem void *tcdm_base;
 
-#define REQ_MB5 (PRCMU_TCDM_BASE + 0xE44)
-#define ACK_MB5 (PRCMU_TCDM_BASE + 0xDF4)
+#define _MBOX_HEADER		(tcdm_base + 0xFE8)
+#define MBOX_HEADER_REQ_MB0	(_MBOX_HEADER + 0x0)
+
+#define REQ_MB1 (tcdm_base + 0xFD0)
+#define REQ_MB5 (tcdm_base + 0xE44)
+
+#define REQ_MB1_ARMOPP		(REQ_MB1 + 0x0)
+#define REQ_MB1_APEOPP		(REQ_MB1 + 0x1)
+#define REQ_MB1_BOOSTOPP	(REQ_MB1 + 0x2)
+
+#define ACK_MB1 (tcdm_base + 0xE04)
+#define ACK_MB5 (tcdm_base + 0xDF4)
+
+#define ACK_MB1_CURR_ARMOPP		(ACK_MB1 + 0x0)
+#define ACK_MB1_CURR_APEOPP		(ACK_MB1 + 0x1)
 
 #define REQ_MB5_I2C_SLAVE_OP (REQ_MB5)
 #define REQ_MB5_I2C_HW_BITS (REQ_MB5 + 1)
@@ -33,10 +52,33 @@
 #define ACK_MB5_I2C_STATUS (ACK_MB5 + 1)
 #define ACK_MB5_I2C_VAL (ACK_MB5 + 3)
 
-#define I2C_WRITE(slave) ((slave) << 1)
-#define I2C_READ(slave) (((slave) << 1) | BIT(0))
+#define PRCM_AVS_VARM_MAX_OPP		(tcdm_base + 0x2E4)
+#define PRCM_AVS_ISMODEENABLE		7
+#define PRCM_AVS_ISMODEENABLE_MASK	(1 << PRCM_AVS_ISMODEENABLE)
+
+#define I2C_WRITE(slave) \
+	(((slave) << 1) | (cpu_is_u8500v2() ? BIT(6) : 0))
+#define I2C_READ(slave) \
+	(((slave) << 1) | (cpu_is_u8500v2() ? BIT(6) : 0) | BIT(0))
 #define I2C_STOP_EN BIT(3)
 
+enum mb1_h {
+	MB1H_ARM_OPP = 1,
+	MB1H_APE_OPP,
+	MB1H_ARM_APE_OPP,
+};
+
+static struct {
+	struct mutex lock;
+	struct completion work;
+	struct {
+		u8 arm_opp;
+		u8 ape_opp;
+		u8 arm_status;
+		u8 ape_status;
+	} ack;
+} mb1_transfer;
+
 enum ack_mb5_status {
 	I2C_WR_OK = 0x01,
 	I2C_RD_OK = 0x02,
@@ -145,6 +187,104 @@ unlock_and_return:
 }
 EXPORT_SYMBOL(prcmu_abb_write);
 
+static int set_ape_cpu_opps(u8 header, enum prcmu_ape_opp ape_opp,
+			    enum prcmu_cpu_opp cpu_opp)
+{
+	bool do_ape;
+	bool do_arm;
+	int err = 0;
+
+	do_ape = ((header == MB1H_APE_OPP) || (header == MB1H_ARM_APE_OPP));
+	do_arm = ((header == MB1H_ARM_OPP) || (header == MB1H_ARM_APE_OPP));
+
+	mutex_lock(&mb1_transfer.lock);
+
+	while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(1))
+		cpu_relax();
+
+	writeb(0, MBOX_HEADER_REQ_MB0);
+	writeb(cpu_opp, REQ_MB1_ARMOPP);
+	writeb(ape_opp, REQ_MB1_APEOPP);
+	writeb(0, REQ_MB1_BOOSTOPP);
+	writel(MBOX_BIT(1), PRCM_MBOX_CPU_SET);
+	wait_for_completion(&mb1_transfer.work);
+	if ((do_ape) && (mb1_transfer.ack.ape_status != 0))
+		err = -EIO;
+	if ((do_arm) && (mb1_transfer.ack.arm_status != 0))
+		err = -EIO;
+
+	mutex_unlock(&mb1_transfer.lock);
+
+	return err;
+}
+
+/**
+ * prcmu_set_ape_opp() - Set the OPP of the APE.
+ * @opp:	The OPP to set.
+ *
+ * This function sets the OPP of the APE.
+ */
+int prcmu_set_ape_opp(enum prcmu_ape_opp opp)
+{
+	return set_ape_cpu_opps(MB1H_APE_OPP, opp, APE_OPP_NO_CHANGE);
+}
+EXPORT_SYMBOL(prcmu_set_ape_opp);
+
+/**
+ * prcmu_set_cpu_opp() - Set the OPP of the CPU.
+ * @opp:	The OPP to set.
+ *
+ * This function sets the OPP of the CPU.
+ */
+int prcmu_set_cpu_opp(enum prcmu_cpu_opp opp)
+{
+	return set_ape_cpu_opps(MB1H_ARM_OPP, CPU_OPP_NO_CHANGE, opp);
+}
+EXPORT_SYMBOL(prcmu_set_cpu_opp);
+
+/**
+ * prcmu_set_ape_cpu_opps() - Set the OPPs of the APE and the CPU.
+ * @ape_opp:	The APE OPP to set.
+ * @cpu_opp:	The CPU OPP to set.
+ *
+ * This function sets the OPPs of the APE and the CPU.
+ */
+int prcmu_set_ape_cpu_opps(enum prcmu_ape_opp ape_opp,
+			   enum prcmu_cpu_opp cpu_opp)
+{
+	return set_ape_cpu_opps(MB1H_ARM_APE_OPP, ape_opp, cpu_opp);
+}
+EXPORT_SYMBOL(prcmu_set_ape_cpu_opps);
+
+/**
+ * prcmu_get_ape_opp() - Get the OPP of the APE.
+ *
+ * This function gets the OPP of the APE.
+ */
+enum prcmu_ape_opp prcmu_get_ape_opp(void)
+{
+	return readb(ACK_MB1_CURR_APEOPP);
+}
+EXPORT_SYMBOL(prcmu_get_ape_opp);
+
+/**
+ * prcmu_get_cpu_opp() - Get the OPP of the CPU.
+ *
+ * This function gets the OPP of the CPU. The OPP is specified in %%.
+ * PRCMU_OPP_EXT is a special OPP value, not specified in %%.
+ */
+int prcmu_get_cpu_opp(void)
+{
+	return readb(ACK_MB1_CURR_ARMOPP);
+}
+EXPORT_SYMBOL(prcmu_get_cpu_opp);
+
+bool prcmu_has_arm_maxopp(void)
+{
+	return (readb(PRCM_AVS_VARM_MAX_OPP) & PRCM_AVS_ISMODEENABLE_MASK)
+		== PRCM_AVS_ISMODEENABLE_MASK;
+}
+
 static void read_mailbox_0(void)
 {
 	writel(MBOX_BIT(0), PRCM_ARM_IT1_CLEAR);
@@ -152,6 +292,9 @@ static void read_mailbox_0(void)
 
 static void read_mailbox_1(void)
 {
+	mb1_transfer.ack.arm_opp = readb(ACK_MB1_CURR_ARMOPP);
+	mb1_transfer.ack.ape_opp = readb(ACK_MB1_CURR_APEOPP);
+	complete(&mb1_transfer.work);
 	writel(MBOX_BIT(1), PRCM_ARM_IT1_CLEAR);
 }
 
@@ -217,15 +360,35 @@ static irqreturn_t prcmu_irq_handler(int
 	return IRQ_HANDLED;
 }
 
+void __init prcmu_early_init(void)
+{
+	if (cpu_is_u8500v11() || cpu_is_u8500ed()) {
+		tcdm_base = __io_address(U8500_PRCMU_TCDM_BASE_V1);
+	} else if (cpu_is_u8500v2()) {
+		tcdm_base = __io_address(U8500_PRCMU_TCDM_BASE);
+	} else {
+		pr_err("prcmu: Unsupported chip version\n");
+		BUG();
+	}
+}
+
 static int __init prcmu_init(void)
 {
+	if (cpu_is_u8500ed()) {
+		pr_err("prcmu: Unsupported chip version\n");
+		return 0;
+	}
+
+	mutex_init(&mb1_transfer.lock);
+	init_completion(&mb1_transfer.work);
 	mutex_init(&mb5_transfer.lock);
 	init_completion(&mb5_transfer.work);
 
 	/* Clean up the mailbox interrupts after pre-kernel code. */
 	writel((MBOX_BIT(NUM_MBOX) - 1), PRCM_ARM_IT1_CLEAR);
 
-	return request_irq(IRQ_PRCMU, prcmu_irq_handler, 0, "prcmu", NULL);
+	return request_irq(IRQ_DB8500_PRCMU1, prcmu_irq_handler, 0,
+			   "prcmu", NULL);
 }
 
 arch_initcall(prcmu_init);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-versatile/core.c linux-libre-2.6.38-gnu1/arch/arm/mach-versatile/core.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-versatile/core.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-versatile/core.c	2011-03-14 21:20:32.000000000 -0400
@@ -31,8 +31,8 @@
 #include <linux/amba/pl022.h>
 #include <linux/io.h>
 #include <linux/gfp.h>
+#include <linux/clkdev.h>
 
-#include <asm/clkdev.h>
 #include <asm/system.h>
 #include <asm/irq.h>
 #include <asm/leds.h>
@@ -46,10 +46,11 @@
 #include <asm/mach/irq.h>
 #include <asm/mach/time.h>
 #include <asm/mach/map.h>
-#include <mach/clkdev.h>
 #include <mach/hardware.h>
 #include <mach/platform.h>
-#include <plat/timer-sp.h>
+#include <asm/hardware/timer-sp.h>
+
+#include <plat/sched_clock.h>
 
 #include "core.h"
 
@@ -62,23 +63,25 @@
 #define VA_VIC_BASE		__io_address(VERSATILE_VIC_BASE)
 #define VA_SIC_BASE		__io_address(VERSATILE_SIC_BASE)
 
-static void sic_mask_irq(unsigned int irq)
+static void sic_mask_irq(struct irq_data *d)
 {
-	irq -= IRQ_SIC_START;
+	unsigned int irq = d->irq - IRQ_SIC_START;
+
 	writel(1 << irq, VA_SIC_BASE + SIC_IRQ_ENABLE_CLEAR);
 }
 
-static void sic_unmask_irq(unsigned int irq)
+static void sic_unmask_irq(struct irq_data *d)
 {
-	irq -= IRQ_SIC_START;
+	unsigned int irq = d->irq - IRQ_SIC_START;
+
 	writel(1 << irq, VA_SIC_BASE + SIC_IRQ_ENABLE_SET);
 }
 
 static struct irq_chip sic_chip = {
-	.name	= "SIC",
-	.ack	= sic_mask_irq,
-	.mask	= sic_mask_irq,
-	.unmask	= sic_unmask_irq,
+	.name		= "SIC",
+	.irq_ack	= sic_mask_irq,
+	.irq_mask	= sic_mask_irq,
+	.irq_unmask	= sic_unmask_irq,
 };
 
 static void
@@ -886,6 +889,12 @@ void __init versatile_init(void)
 }
 
 /*
+ * The sched_clock counter
+ */
+#define REFCOUNTER		(__io_address(VERSATILE_SYS_BASE) + \
+				 VERSATILE_SYS_24MHz_OFFSET)
+
+/*
  * Where is the timer (VA)?
  */
 #define TIMER0_VA_BASE		 __io_address(VERSATILE_TIMER0_1_BASE)
@@ -900,6 +909,8 @@ static void __init versatile_timer_init(
 {
 	u32 val;
 
+	versatile_sched_clock_init(REFCOUNTER, 24000000);
+
 	/* 
 	 * set clock frequency: 
 	 *	VERSATILE_REFCLK is 32KHz
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-versatile/Kconfig linux-libre-2.6.38-gnu1/arch/arm/mach-versatile/Kconfig
--- linux-libre-2.6.37-gnu1/arch/arm/mach-versatile/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-versatile/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -2,16 +2,19 @@ menu "Versatile platform type"
 	depends on ARCH_VERSATILE
 
 config ARCH_VERSATILE_PB
-	bool "Support Versatile/PB platform"
+	bool "Support Versatile Platform Baseboard for ARM926EJ-S"
 	select CPU_ARM926T
+	select MIGHT_HAVE_PCI
 	default y
 	help
-	  Include support for the ARM(R) Versatile/PB platform.
+	  Include support for the ARM(R) Versatile Platform Baseboard
+	  for the ARM926EJ-S.
 
 config MACH_VERSATILE_AB
-	bool "Support Versatile/AB platform"
+	bool "Support Versatile Application Baseboard for ARM926EJ-S"
 	select CPU_ARM926T
 	help
-	  Include support for the ARM(R) Versatile/AP platform.
+	  Include support for the ARM(R) Versatile Application Baseboard
+	  for the ARM926EJ-S.
 
 endmenu
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-vexpress/core.h linux-libre-2.6.38-gnu1/arch/arm/mach-vexpress/core.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-vexpress/core.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-vexpress/core.h	2011-03-14 21:20:32.000000000 -0400
@@ -22,5 +22,3 @@ struct map_desc;
 
 void v2m_map_io(struct map_desc *tile, size_t num);
 extern struct sys_timer v2m_timer;
-
-extern void __iomem *gic_cpu_base_addr;
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-vexpress/ct-ca9x4.c linux-libre-2.6.38-gnu1/arch/arm/mach-vexpress/ct-ca9x4.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-vexpress/ct-ca9x4.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-vexpress/ct-ca9x4.c	2011-03-14 21:20:32.000000000 -0400
@@ -8,8 +8,8 @@
 #include <linux/platform_device.h>
 #include <linux/amba/bus.h>
 #include <linux/amba/clcd.h>
+#include <linux/clkdev.h>
 
-#include <asm/clkdev.h>
 #include <asm/pgtable.h>
 #include <asm/hardware/arm_timer.h>
 #include <asm/hardware/cache-l2x0.h>
@@ -18,10 +18,9 @@
 #include <asm/pmu.h>
 #include <asm/smp_twd.h>
 
-#include <mach/clkdev.h>
 #include <mach/ct-ca9x4.h>
 
-#include <plat/timer-sp.h>
+#include <asm/hardware/timer-sp.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
@@ -60,13 +59,10 @@ static void __init ct_ca9x4_map_io(void)
 	v2m_map_io(ct_ca9x4_io_desc, ARRAY_SIZE(ct_ca9x4_io_desc));
 }
 
-void __iomem *gic_cpu_base_addr;
-
 static void __init ct_ca9x4_init_irq(void)
 {
-	gic_cpu_base_addr = MMIO_P2V(A9_MPCORE_GIC_CPU);
-	gic_dist_init(0, MMIO_P2V(A9_MPCORE_GIC_DIST), 29);
-	gic_cpu_init(0, gic_cpu_base_addr);
+	gic_init(0, 29, MMIO_P2V(A9_MPCORE_GIC_DIST),
+		 MMIO_P2V(A9_MPCORE_GIC_CPU));
 }
 
 #if 0
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-vexpress/hotplug.c linux-libre-2.6.38-gnu1/arch/arm/mach-vexpress/hotplug.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-vexpress/hotplug.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-vexpress/hotplug.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,128 @@
+/*
+ *  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 <asm/cacheflush.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)
+{
+	/*
+	 * there is no power-control hardware on this platform, so all
+	 * we can do is put the core into WFI; this is safe as the calling
+	 * code will have already disabled interrupts
+	 */
+	for (;;) {
+		/*
+		 * 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-2.6.37-gnu1/arch/arm/mach-vexpress/include/mach/entry-macro.S linux-libre-2.6.38-gnu1/arch/arm/mach-vexpress/include/mach/entry-macro.S
--- linux-libre-2.6.37-gnu1/arch/arm/mach-vexpress/include/mach/entry-macro.S	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-vexpress/include/mach/entry-macro.S	2011-03-14 21:20:32.000000000 -0400
@@ -1,67 +1,7 @@
-#include <asm/hardware/gic.h>
+#include <asm/hardware/entry-macro-gic.S>
 
 	.macro	disable_fiq
 	.endm
 
-	.macro	get_irqnr_preamble, base, tmp
-	ldr	\base, =gic_cpu_base_addr
-	ldr	\base, [\base]
-	.endm
-
 	.macro	arch_ret_to_user, tmp1, tmp2
 	.endm
-
-	/*
-	 * The interrupt numbering scheme is defined in the
-	 * interrupt controller spec.  To wit:
-	 *
-	 * Interrupts 0-15 are IPI
-	 * 16-28 are reserved
-	 * 29-31 are local.  We allow 30 to be used for the watchdog.
-	 * 32-1020 are global
-	 * 1021-1022 are reserved
-	 * 1023 is "spurious" (no interrupt)
-	 *
-	 * For now, we ignore all local interrupts so only return an interrupt if it's
-	 * between 30 and 1020.  The test_for_ipi routine below will pick up on IPIs.
-	 *
-	 * A simple read from the controller will tell us the number of the highest
-	 * priority enabled interrupt.  We then just need to check whether it is in the
-	 * valid range for an IRQ (30-1020 inclusive).
-	 */
-
-	.macro	get_irqnr_and_base, irqnr, irqstat, base, tmp
-	ldr     \irqstat, [\base, #GIC_CPU_INTACK] /* bits 12-10 = src CPU, 9-0 = int # */
-	ldr	\tmp, =1021
-	bic     \irqnr, \irqstat, #0x1c00
-	cmp     \irqnr, #29
-	cmpcc	\irqnr, \irqnr
-	cmpne	\irqnr, \tmp
-	cmpcs	\irqnr, \irqnr
-	.endm
-
-	/* We assume that irqstat (the raw value of the IRQ acknowledge
-	 * register) is preserved from the macro above.
-	 * If there is an IPI, we immediately signal end of interrupt on the
-	 * controller, since this requires the original irqstat value which
-	 * we won't easily be able to recreate later.
-	 */
-
-	.macro test_for_ipi, irqnr, irqstat, base, tmp
-	bic	\irqnr, \irqstat, #0x1c00
-	cmp	\irqnr, #16
-	strcc	\irqstat, [\base, #GIC_CPU_EOI]
-	cmpcs	\irqnr, \irqnr
-	.endm
-
-	/* As above, this assumes that irqstat and base are preserved.. */
-
-	.macro test_for_ltirq, irqnr, irqstat, base, tmp
-	bic	\irqnr, \irqstat, #0x1c00
-	mov 	\tmp, #0
-	cmp	\irqnr, #29
-	moveq	\tmp, #1
-	streq	\irqstat, [\base, #GIC_CPU_EOI]
-	cmp	\tmp, #0
-	.endm
-
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-vexpress/include/mach/smp.h linux-libre-2.6.38-gnu1/arch/arm/mach-vexpress/include/mach/smp.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-vexpress/include/mach/smp.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-vexpress/include/mach/smp.h	2011-03-14 21:20:32.000000000 -0400
@@ -2,13 +2,12 @@
 #define __MACH_SMP_H
 
 #include <asm/hardware/gic.h>
-#include <asm/smp_mpidr.h>
 
 /*
  * We use IRQ1 as the IPI
  */
-static inline void smp_cross_call(const struct cpumask *mask)
+static inline void smp_cross_call(const struct cpumask *mask, int ipi)
 {
-	gic_raise_softirq(mask, 1);
+	gic_raise_softirq(mask, ipi);
 }
 #endif
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-vexpress/Makefile linux-libre-2.6.38-gnu1/arch/arm/mach-vexpress/Makefile
--- linux-libre-2.6.37-gnu1/arch/arm/mach-vexpress/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-vexpress/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -5,4 +5,5 @@
 obj-y					:= v2m.o
 obj-$(CONFIG_ARCH_VEXPRESS_CA9X4)	+= ct-ca9x4.o
 obj-$(CONFIG_SMP)			+= platsmp.o headsmp.o
+obj-$(CONFIG_HOTPLUG_CPU)		+= hotplug.o
 obj-$(CONFIG_LOCAL_TIMERS)		+= localtimer.o
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-vexpress/platsmp.c linux-libre-2.6.38-gnu1/arch/arm/mach-vexpress/platsmp.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-vexpress/platsmp.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-vexpress/platsmp.c	2011-03-14 21:20:32.000000000 -0400
@@ -17,7 +17,6 @@
 #include <linux/io.h>
 
 #include <asm/cacheflush.h>
-#include <asm/localtimer.h>
 #include <asm/smp_scu.h>
 #include <asm/unified.h>
 
@@ -35,6 +34,19 @@ extern void vexpress_secondary_startup(v
  */
 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 __cpuinit 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 MMIO_P2V(A9_MPCORE_SCU);
@@ -44,21 +56,18 @@ static DEFINE_SPINLOCK(boot_lock);
 
 void __cpuinit platform_secondary_init(unsigned int cpu)
 {
-	trace_hardirqs_off();
-
 	/*
 	 * 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_cpu_init(0, gic_cpu_base_addr);
+	gic_secondary_init(0);
 
 	/*
 	 * let the primary processor know we're out of the
 	 * pen, then head off into the C entry point
 	 */
-	pen_release = -1;
-	smp_wmb();
+	write_pen_release(-1);
 
 	/*
 	 * Synchronise with the boot thread.
@@ -83,16 +92,14 @@ int __cpuinit boot_secondary(unsigned in
 	 * since we haven't sent them a soft interrupt, they shouldn't
 	 * be there.
 	 */
-	pen_release = cpu;
-	__cpuc_flush_dcache_area((void *)&pen_release, sizeof(pen_release));
-	outer_clean_range(__pa(&pen_release), __pa(&pen_release + 1));
+	write_pen_release(cpu);
 
 	/*
 	 * 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.
 	 */
-	smp_cross_call(cpumask_of(cpu));
+	smp_cross_call(cpumask_of(cpu), 1);
 
 	timeout = jiffies + (1 * HZ);
 	while (time_before(jiffies, timeout)) {
@@ -124,13 +131,6 @@ void __init smp_init_cpus(void)
 	ncores = scu_base ? scu_get_core_count(scu_base) : 1;
 
 	/* sanity check */
-	if (ncores == 0) {
-		printk(KERN_ERR
-		       "vexpress: strange CM count of 0? Default to 1\n");
-
-		ncores = 1;
-	}
-
 	if (ncores > NR_CPUS) {
 		printk(KERN_WARNING
 		       "vexpress: no. of cores (%d) greater than configured "
@@ -143,20 +143,10 @@ void __init smp_init_cpus(void)
 		set_cpu_possible(i, true);
 }
 
-void __init smp_prepare_cpus(unsigned int max_cpus)
+void __init platform_smp_prepare_cpus(unsigned int max_cpus)
 {
-	unsigned int ncores = num_possible_cpus();
-	unsigned int cpu = smp_processor_id();
 	int i;
 
-	smp_store_cpu_info(cpu);
-
-	/*
-	 * are we trying to boot more cores than exist?
-	 */
-	if (max_cpus > ncores)
-		max_cpus = ncores;
-
 	/*
 	 * Initialise the present map, which describes the set of CPUs
 	 * actually populated at the present time.
@@ -164,27 +154,15 @@ void __init smp_prepare_cpus(unsigned in
 	for (i = 0; i < max_cpus; i++)
 		set_cpu_present(i, true);
 
+	scu_enable(scu_base_addr());
+
 	/*
-	 * Initialise the SCU if there are more than one CPU and let
-	 * them know where to start.
+	 * 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.
 	 */
-	if (max_cpus > 1) {
-		/*
-		 * Enable the local timer or broadcast device for the
-		 * boot CPU, but only if we have more than one CPU.
-		 */
-		percpu_timer_setup();
-
-		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.
-		 */
-		writel(~0, MMIO_P2V(V2M_SYS_FLAGSCLR));
-		writel(BSYM(virt_to_phys(vexpress_secondary_startup)),
-			MMIO_P2V(V2M_SYS_FLAGSSET));
-	}
+	writel(~0, MMIO_P2V(V2M_SYS_FLAGSCLR));
+	writel(BSYM(virt_to_phys(vexpress_secondary_startup)),
+		MMIO_P2V(V2M_SYS_FLAGSSET));
 }
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-vexpress/v2m.c linux-libre-2.6.38-gnu1/arch/arm/mach-vexpress/v2m.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-vexpress/v2m.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-vexpress/v2m.c	2011-03-14 21:20:32.000000000 -0400
@@ -11,18 +11,19 @@
 #include <linux/spinlock.h>
 #include <linux/sysdev.h>
 #include <linux/usb/isp1760.h>
+#include <linux/clkdev.h>
 
-#include <asm/clkdev.h>
 #include <asm/sizes.h>
 #include <asm/mach/flash.h>
 #include <asm/mach/map.h>
 #include <asm/mach/time.h>
 #include <asm/hardware/arm_timer.h>
+#include <asm/hardware/timer-sp.h>
+#include <asm/hardware/sp810.h>
 
-#include <mach/clkdev.h>
 #include <mach/motherboard.h>
 
-#include <plat/timer-sp.h>
+#include <plat/sched_clock.h>
 
 #include "core.h"
 
@@ -50,6 +51,16 @@ void __init v2m_map_io(struct map_desc *
 
 static void __init v2m_timer_init(void)
 {
+	u32 scctrl;
+
+	versatile_sched_clock_init(MMIO_P2V(V2M_SYS_24MHZ), 24000000);
+
+	/* Select 1MHz TIMCLK as the reference clock for SP804 timers */
+	scctrl = readl(MMIO_P2V(V2M_SYSCTL + SCCTRL));
+	scctrl |= SCCTRL_TIMEREN0SEL_TIMCLK;
+	scctrl |= SCCTRL_TIMEREN1SEL_TIMCLK;
+	writel(scctrl, MMIO_P2V(V2M_SYSCTL + SCCTRL));
+
 	writel(0, MMIO_P2V(V2M_TIMER0) + TIMER_CTRL);
 	writel(0, MMIO_P2V(V2M_TIMER1) + TIMER_CTRL);
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-w90x900/clock.h linux-libre-2.6.38-gnu1/arch/arm/mach-w90x900/clock.h
--- linux-libre-2.6.37-gnu1/arch/arm/mach-w90x900/clock.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-w90x900/clock.h	2011-03-14 21:20:32.000000000 -0400
@@ -10,7 +10,7 @@
  * the Free Software Foundation; either version 2 of the License.
  */
 
-#include <asm/clkdev.h>
+#include <linux/clkdev.h>
 
 void nuc900_clk_enable(struct clk *clk, int enable);
 void nuc900_subclk_enable(struct clk *clk, int enable);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-w90x900/irq.c linux-libre-2.6.38-gnu1/arch/arm/mach-w90x900/irq.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-w90x900/irq.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-w90x900/irq.c	2011-03-14 21:20:32.000000000 -0400
@@ -92,15 +92,15 @@ static void nuc900_group_enable(struct g
 	__raw_writel(regval, REG_AIC_GEN);
 }
 
-static void nuc900_irq_mask(unsigned int irq)
+static void nuc900_irq_mask(struct irq_data *d)
 {
 	struct group_irq *group_irq;
 
 	group_irq = NULL;
 
-	__raw_writel(1 << irq, REG_AIC_MDCR);
+	__raw_writel(1 << d->irq, REG_AIC_MDCR);
 
-	switch (irq) {
+	switch (d->irq) {
 	case IRQ_GROUP0:
 		group_irq = &group_nirq0;
 		break;
@@ -143,20 +143,20 @@ static void nuc900_irq_mask(unsigned int
  * to REG_AIC_EOSCR for ACK
  */
 
-static void nuc900_irq_ack(unsigned int irq)
+static void nuc900_irq_ack(struct irq_data *d)
 {
 	__raw_writel(0x01, REG_AIC_EOSCR);
 }
 
-static void nuc900_irq_unmask(unsigned int irq)
+static void nuc900_irq_unmask(struct irq_data *d)
 {
 	struct group_irq *group_irq;
 
 	group_irq = NULL;
 
-	__raw_writel(1 << irq, REG_AIC_MECR);
+	__raw_writel(1 << d->irq, REG_AIC_MECR);
 
-	switch (irq) {
+	switch (d->irq) {
 	case IRQ_GROUP0:
 		group_irq = &group_nirq0;
 		break;
@@ -195,9 +195,9 @@ static void nuc900_irq_unmask(unsigned i
 }
 
 static struct irq_chip nuc900_irq_chip = {
-	.ack	   = nuc900_irq_ack,
-	.mask	   = nuc900_irq_mask,
-	.unmask	   = nuc900_irq_unmask,
+	.irq_ack	= nuc900_irq_ack,
+	.irq_mask	= nuc900_irq_mask,
+	.irq_unmask	= nuc900_irq_unmask,
 };
 
 void __init nuc900_init_irq(void)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mach-w90x900/time.c linux-libre-2.6.38-gnu1/arch/arm/mach-w90x900/time.c
--- linux-libre-2.6.37-gnu1/arch/arm/mach-w90x900/time.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mach-w90x900/time.c	2011-03-14 21:20:32.000000000 -0400
@@ -153,7 +153,6 @@ static struct clocksource clocksource_nu
 	.rating	= 200,
 	.read	= nuc900_get_cycles,
 	.mask	= CLOCKSOURCE_MASK(TDR_SHIFT),
-	.shift	= 10,
 	.flags	= CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
@@ -176,9 +175,7 @@ static void __init nuc900_clocksource_in
 	val |= (COUNTEN | PERIOD | PRESCALE);
 	__raw_writel(val, REG_TCSR1);
 
-	clocksource_nuc900.mult =
-		clocksource_khz2mult((rate / 1000), clocksource_nuc900.shift);
-	clocksource_register(&clocksource_nuc900);
+	clocksource_register_hz(&clocksource_nuc900, rate);
 }
 
 static void __init nuc900_timer_init(void)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/Makefile linux-libre-2.6.38-gnu1/arch/arm/Makefile
--- linux-libre-2.6.37-gnu1/arch/arm/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -15,7 +15,7 @@ ifeq ($(CONFIG_CPU_ENDIAN_BE8),y)
 LDFLAGS_vmlinux	+= --be8
 endif
 
-OBJCOPYFLAGS	:=-O binary -R .note -R .note.gnu.build-id -R .comment -S
+OBJCOPYFLAGS	:=-O binary -R .comment -S
 GZFLAGS		:=-9
 #KBUILD_CFLAGS	+=-pipe
 # Explicitly specifiy 32-bit ARM ISA since toolchain default can be -mthumb:
@@ -154,10 +154,11 @@ machine-$(CONFIG_ARCH_MSM)		:= msm
 machine-$(CONFIG_ARCH_MV78XX0)		:= mv78xx0
 machine-$(CONFIG_ARCH_MX1)		:= imx
 machine-$(CONFIG_ARCH_MX2)		:= imx
-machine-$(CONFIG_ARCH_MX25)		:= mx25
+machine-$(CONFIG_ARCH_MX25)		:= imx
 machine-$(CONFIG_ARCH_MX3)		:= mx3
 machine-$(CONFIG_ARCH_MX5)		:= mx5
 machine-$(CONFIG_ARCH_MXC91231)		:= mxc91231
+machine-$(CONFIG_ARCH_MXS)		:= mxs
 machine-$(CONFIG_ARCH_NETX)		:= netx
 machine-$(CONFIG_ARCH_NOMADIK)		:= nomadik
 machine-$(CONFIG_ARCH_NS9XXX)		:= ns9xxx
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mm/cache-l2x0.c linux-libre-2.6.38-gnu1/arch/arm/mm/cache-l2x0.c
--- linux-libre-2.6.37-gnu1/arch/arm/mm/cache-l2x0.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mm/cache-l2x0.c	2011-03-14 21:20:32.000000000 -0400
@@ -49,7 +49,13 @@ static inline void cache_wait(void __iom
 static inline void cache_sync(void)
 {
 	void __iomem *base = l2x0_base;
+
+#ifdef CONFIG_ARM_ERRATA_753970
+	/* write to an unmmapped register */
+	writel_relaxed(0, base + L2X0_DUMMY_REG);
+#else
 	writel_relaxed(0, base + L2X0_CACHE_SYNC);
+#endif
 	cache_wait(base + L2X0_CACHE_SYNC, 1);
 }
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mm/dma-mapping.c linux-libre-2.6.38-gnu1/arch/arm/mm/dma-mapping.c
--- linux-libre-2.6.37-gnu1/arch/arm/mm/dma-mapping.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mm/dma-mapping.c	2011-03-14 21:20:32.000000000 -0400
@@ -312,7 +312,7 @@ __dma_alloc(struct device *dev, size_t s
 		addr = page_address(page);
 
 	if (addr)
-		*handle = page_to_dma(dev, page);
+		*handle = pfn_to_dma(dev, page_to_pfn(page));
 
 	return addr;
 }
@@ -407,7 +407,7 @@ void dma_free_coherent(struct device *de
 	if (!arch_is_coherent())
 		__dma_free_remap(cpu_addr, size);
 
-	__dma_free_buffer(dma_to_page(dev, handle), size);
+	__dma_free_buffer(pfn_to_page(dma_to_pfn(dev, handle)), size);
 }
 EXPORT_SYMBOL(dma_free_coherent);
 
@@ -555,17 +555,20 @@ int dma_map_sg(struct device *dev, struc
 	struct scatterlist *s;
 	int i, j;
 
+	BUG_ON(!valid_dma_direction(dir));
+
 	for_each_sg(sg, s, nents, i) {
-		s->dma_address = dma_map_page(dev, sg_page(s), s->offset,
+		s->dma_address = __dma_map_page(dev, sg_page(s), s->offset,
 						s->length, dir);
 		if (dma_mapping_error(dev, s->dma_address))
 			goto bad_mapping;
 	}
+	debug_dma_map_sg(dev, sg, nents, nents, dir);
 	return nents;
 
  bad_mapping:
 	for_each_sg(sg, s, i, j)
-		dma_unmap_page(dev, sg_dma_address(s), sg_dma_len(s), dir);
+		__dma_unmap_page(dev, sg_dma_address(s), sg_dma_len(s), dir);
 	return 0;
 }
 EXPORT_SYMBOL(dma_map_sg);
@@ -574,7 +577,7 @@ EXPORT_SYMBOL(dma_map_sg);
  * dma_unmap_sg - unmap a set of SG buffers mapped by dma_map_sg
  * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
  * @sg: list of buffers
- * @nents: number of buffers to unmap (returned from dma_map_sg)
+ * @nents: number of buffers to unmap (same as was passed to dma_map_sg)
  * @dir: DMA transfer direction (same as was passed to dma_map_sg)
  *
  * Unmap a set of streaming mode DMA translations.  Again, CPU access
@@ -586,8 +589,10 @@ void dma_unmap_sg(struct device *dev, st
 	struct scatterlist *s;
 	int i;
 
+	debug_dma_unmap_sg(dev, sg, nents, dir);
+
 	for_each_sg(sg, s, nents, i)
-		dma_unmap_page(dev, sg_dma_address(s), sg_dma_len(s), dir);
+		__dma_unmap_page(dev, sg_dma_address(s), sg_dma_len(s), dir);
 }
 EXPORT_SYMBOL(dma_unmap_sg);
 
@@ -612,6 +617,8 @@ void dma_sync_sg_for_cpu(struct device *
 		__dma_page_dev_to_cpu(sg_page(s), s->offset,
 				      s->length, dir);
 	}
+
+	debug_dma_sync_sg_for_cpu(dev, sg, nents, dir);
 }
 EXPORT_SYMBOL(dma_sync_sg_for_cpu);
 
@@ -636,5 +643,16 @@ void dma_sync_sg_for_device(struct devic
 		__dma_page_cpu_to_dev(sg_page(s), s->offset,
 				      s->length, dir);
 	}
+
+	debug_dma_sync_sg_for_device(dev, sg, nents, dir);
 }
 EXPORT_SYMBOL(dma_sync_sg_for_device);
+
+#define PREALLOC_DMA_DEBUG_ENTRIES	4096
+
+static int __init dma_debug_do_init(void)
+{
+	dma_debug_init(PREALLOC_DMA_DEBUG_ENTRIES);
+	return 0;
+}
+fs_initcall(dma_debug_do_init);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mm/fault-armv.c linux-libre-2.6.38-gnu1/arch/arm/mm/fault-armv.c
--- linux-libre-2.6.37-gnu1/arch/arm/mm/fault-armv.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mm/fault-armv.c	2011-03-14 21:20:32.000000000 -0400
@@ -26,7 +26,7 @@
 
 #include "mm.h"
 
-static unsigned long shared_pte_mask = L_PTE_MT_BUFFERABLE;
+static pteval_t shared_pte_mask = L_PTE_MT_BUFFERABLE;
 
 #if __LINUX_ARM_ARCH__ < 6
 /*
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mm/fault.c linux-libre-2.6.38-gnu1/arch/arm/mm/fault.c
--- linux-libre-2.6.37-gnu1/arch/arm/mm/fault.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mm/fault.c	2011-03-14 21:20:32.000000000 -0400
@@ -108,7 +108,7 @@ void show_pte(struct mm_struct *mm, unsi
 
 		pte = pte_offset_map(pmd, addr);
 		printk(", *pte=%08lx", pte_val(*pte));
-		printk(", *ppte=%08lx", pte_val(pte[-PTRS_PER_PTE]));
+		printk(", *ppte=%08lx", pte_val(pte[PTE_HWTABLE_PTRS]));
 		pte_unmap(pte);
 	} while(0);
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mm/flush.c linux-libre-2.6.38-gnu1/arch/arm/mm/flush.c
--- linux-libre-2.6.37-gnu1/arch/arm/mm/flush.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mm/flush.c	2011-03-14 21:20:32.000000000 -0400
@@ -18,7 +18,6 @@
 #include <asm/smp_plat.h>
 #include <asm/system.h>
 #include <asm/tlbflush.h>
-#include <asm/smp_plat.h>
 
 #include "mm.h"
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mm/idmap.c linux-libre-2.6.38-gnu1/arch/arm/mm/idmap.c
--- linux-libre-2.6.37-gnu1/arch/arm/mm/idmap.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mm/idmap.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,67 @@
+#include <linux/kernel.h>
+
+#include <asm/cputype.h>
+#include <asm/pgalloc.h>
+#include <asm/pgtable.h>
+
+static void idmap_add_pmd(pgd_t *pgd, unsigned long addr, unsigned long end,
+	unsigned long prot)
+{
+	pmd_t *pmd = pmd_offset(pgd, addr);
+
+	addr = (addr & PMD_MASK) | prot;
+	pmd[0] = __pmd(addr);
+	addr += SECTION_SIZE;
+	pmd[1] = __pmd(addr);
+	flush_pmd_entry(pmd);
+}
+
+void identity_mapping_add(pgd_t *pgd, unsigned long addr, unsigned long end)
+{
+	unsigned long prot, next;
+
+	prot = PMD_TYPE_SECT | PMD_SECT_AP_WRITE;
+	if (cpu_architecture() <= CPU_ARCH_ARMv5TEJ && !cpu_is_xscale())
+		prot |= PMD_BIT4;
+
+	pgd += pgd_index(addr);
+	do {
+		next = pgd_addr_end(addr, end);
+		idmap_add_pmd(pgd, addr, next, prot);
+	} while (pgd++, addr = next, addr != end);
+}
+
+#ifdef CONFIG_SMP
+static void idmap_del_pmd(pgd_t *pgd, unsigned long addr, unsigned long end)
+{
+	pmd_t *pmd = pmd_offset(pgd, addr);
+	pmd_clear(pmd);
+}
+
+void identity_mapping_del(pgd_t *pgd, unsigned long addr, unsigned long end)
+{
+	unsigned long next;
+
+	pgd += pgd_index(addr);
+	do {
+		next = pgd_addr_end(addr, end);
+		idmap_del_pmd(pgd, addr, next);
+	} while (pgd++, addr = next, addr != end);
+}
+#endif
+
+/*
+ * In order to soft-boot, we need to insert a 1:1 mapping in place of
+ * the user-mode pages.  This will then ensure that we have predictable
+ * results when turning the mmu off
+ */
+void setup_mm_for_reboot(char mode)
+{
+	/*
+	 * We need to access to user-mode page tables here. For kernel threads
+	 * we don't have any user-mode mappings so we use the context that we
+	 * "borrowed".
+	 */
+	identity_mapping_add(current->active_mm->pgd, 0, TASK_SIZE);
+	local_flush_tlb_all();
+}
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mm/init.c linux-libre-2.6.38-gnu1/arch/arm/mm/init.c
--- linux-libre-2.6.37-gnu1/arch/arm/mm/init.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mm/init.c	2011-03-14 21:20:32.000000000 -0400
@@ -297,6 +297,12 @@ void __init arm_memblock_init(struct mem
 	memblock_reserve(__pa(_stext), _end - _stext);
 #endif
 #ifdef CONFIG_BLK_DEV_INITRD
+	if (phys_initrd_size &&
+	    memblock_is_region_reserved(phys_initrd_start, phys_initrd_size)) {
+		pr_err("INITRD: 0x%08lx+0x%08lx overlaps in-use memory region - disabling initrd\n",
+		       phys_initrd_start, phys_initrd_size);
+		phys_initrd_start = phys_initrd_size = 0;
+	}
 	if (phys_initrd_size) {
 		memblock_reserve(phys_initrd_start, phys_initrd_size);
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mm/ioremap.c linux-libre-2.6.38-gnu1/arch/arm/mm/ioremap.c
--- linux-libre-2.6.37-gnu1/arch/arm/mm/ioremap.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mm/ioremap.c	2011-03-14 21:20:32.000000000 -0400
@@ -204,12 +204,8 @@ void __iomem * __arm_ioremap_pfn_caller(
 	/*
 	 * Don't allow RAM to be mapped - this causes problems with ARMv6+
 	 */
-	if (pfn_valid(pfn)) {
-		printk(KERN_WARNING "BUG: Your driver calls ioremap() on system memory.  This leads\n"
-		       "to architecturally unpredictable behaviour on ARMv6+, and ioremap()\n"
-		       "will fail in the next kernel release.  Please fix your driver.\n");
-		WARN_ON(1);
-	}
+	if (WARN_ON(pfn_valid(pfn)))
+		return NULL;
 
 	type = get_mem_type(mtype);
 	if (!type)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mm/Kconfig linux-libre-2.6.38-gnu1/arch/arm/mm/Kconfig
--- linux-libre-2.6.37-gnu1/arch/arm/mm/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mm/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -382,6 +382,12 @@ config CPU_FEROCEON_OLD_ID
 	  for which the CPU ID is equal to the ARM926 ID.
 	  Relevant for Feroceon-1850 and early Feroceon-2850.
 
+# Marvell PJ4
+config CPU_PJ4
+	bool
+	select CPU_V7
+	select ARM_THUMBEE
+
 # ARMv6
 config CPU_V6
 	bool "Support ARM V6 processor" if ARCH_INTEGRATOR || MACH_REALVIEW_EB || MACH_REALVIEW_PBX || ARCH_DOVE
@@ -399,7 +405,7 @@ config CPU_V6
 config CPU_32v6K
 	bool "Support ARM V6K processor extensions" if !SMP
 	depends on CPU_V6 || CPU_V7
-	default y if SMP && !(ARCH_MX3 || ARCH_OMAP2)
+	default y if SMP
 	help
 	  Say Y here if your ARMv6 processor supports the 'K' extension.
 	  This enables the kernel to use some instructions not present
@@ -410,7 +416,7 @@ config CPU_32v6K
 # ARMv7
 config CPU_V7
 	bool "Support ARM V7 processor" if ARCH_INTEGRATOR || MACH_REALVIEW_EB || MACH_REALVIEW_PBX
-	select CPU_32v6K if !ARCH_OMAP2
+	select CPU_32v6K
 	select CPU_32v7
 	select CPU_ABRT_EV7
 	select CPU_PABRT_V7
@@ -599,6 +605,14 @@ config CPU_CP15_MPU
 	help
 	  Processor has the CP15 register, which has MPU related registers.
 
+config CPU_USE_DOMAINS
+	bool
+	depends on MMU
+	default y if !CPU_32v6K
+	help
+	  This option enables or disables the use of domain switching
+	  via the set_fs() function.
+
 #
 # CPU supports 36-bit I/O
 #
@@ -628,6 +642,33 @@ config ARM_THUMBEE
 	  Say Y here if you have a CPU with the ThumbEE extension and code to
 	  make use of it. Say N for code that can run on CPUs without ThumbEE.
 
+config SWP_EMULATE
+	bool "Emulate SWP/SWPB instructions"
+	depends on !CPU_USE_DOMAINS && CPU_V7 && !CPU_V6
+	select HAVE_PROC_CPU if PROC_FS
+	default y if SMP
+	help
+	  ARMv6 architecture deprecates use of the SWP/SWPB instructions.
+	  ARMv7 multiprocessing extensions introduce the ability to disable
+	  these instructions, triggering an undefined instruction exception
+	  when executed. Say Y here to enable software emulation of these
+	  instructions for userspace (not kernel) using LDREX/STREX.
+	  Also creates /proc/cpu/swp_emulation for statistics.
+
+	  In some older versions of glibc [<=2.8] SWP is used during futex
+	  trylock() operations with the assumption that the code will not
+	  be preempted. This invalid assumption may be more likely to fail
+	  with SWP emulation enabled, leading to deadlock of the user
+	  application.
+
+	  NOTE: when accessing uncached shared regions, LDREX/STREX rely
+	  on an external transaction monitoring block called a global
+	  monitor to maintain update atomicity. If your system does not
+	  implement a global monitor, this option can cause programs that
+	  perform SWP operations to uncached memory to deadlock.
+
+	  If unsure, say Y.
+
 config CPU_BIG_ENDIAN
 	bool "Build big-endian kernel"
 	depends on ARCH_SUPPORTS_BIG_ENDIAN
@@ -772,7 +813,7 @@ config CACHE_L2X0
 	depends on REALVIEW_EB_ARM11MP || MACH_REALVIEW_PB11MP || MACH_REALVIEW_PB1176 || \
 		   REALVIEW_EB_A9MP || ARCH_MX35 || ARCH_MX31 || MACH_REALVIEW_PBX || \
 		   ARCH_NOMADIK || ARCH_OMAP4 || ARCH_S5PV310 || ARCH_TEGRA || \
-		   ARCH_U8500 || ARCH_VEXPRESS_CA9X4
+		   ARCH_U8500 || ARCH_VEXPRESS_CA9X4 || ARCH_SHMOBILE
 	default y
 	select OUTER_CACHE
 	select OUTER_CACHE_SYNC
@@ -789,7 +830,7 @@ config CACHE_PL310
 
 config CACHE_TAUROS2
 	bool "Enable the Tauros2 L2 cache controller"
-	depends on (ARCH_DOVE || ARCH_MMP)
+	depends on (ARCH_DOVE || ARCH_MMP || CPU_PJ4)
 	default y
 	select OUTER_CACHE
 	help
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mm/Makefile linux-libre-2.6.38-gnu1/arch/arm/mm/Makefile
--- linux-libre-2.6.37-gnu1/arch/arm/mm/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mm/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -5,8 +5,8 @@
 obj-y				:= dma-mapping.o extable.o fault.o init.o \
 				   iomap.o
 
-obj-$(CONFIG_MMU)		+= fault-armv.o flush.o ioremap.o mmap.o \
-				   pgd.o mmu.o vmregion.o
+obj-$(CONFIG_MMU)		+= fault-armv.o flush.o idmap.o ioremap.o \
+				   mmap.o pgd.o mmu.o vmregion.o
 
 ifneq ($(CONFIG_MMU),y)
 obj-y				+= nommu.o
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mm/mm.h linux-libre-2.6.38-gnu1/arch/arm/mm/mm.h
--- linux-libre-2.6.37-gnu1/arch/arm/mm/mm.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mm/mm.h	2011-03-14 21:20:32.000000000 -0400
@@ -16,7 +16,7 @@ static inline pmd_t *pmd_off_k(unsigned
 }
 
 struct mem_type {
-	unsigned int prot_pte;
+	pteval_t prot_pte;
 	unsigned int prot_l1;
 	unsigned int prot_sect;
 	unsigned int domain;
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mm/mmu.c linux-libre-2.6.38-gnu1/arch/arm/mm/mmu.c
--- linux-libre-2.6.37-gnu1/arch/arm/mm/mmu.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mm/mmu.c	2011-03-14 21:20:32.000000000 -0400
@@ -24,6 +24,7 @@
 #include <asm/smp_plat.h>
 #include <asm/tlb.h>
 #include <asm/highmem.h>
+#include <asm/traps.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
@@ -62,7 +63,7 @@ struct cachepolicy {
 	const char	policy[16];
 	unsigned int	cr_mask;
 	unsigned int	pmd;
-	unsigned int	pte;
+	pteval_t	pte;
 };
 
 static struct cachepolicy cache_policies[] __initdata = {
@@ -190,7 +191,7 @@ void adjust_cr(unsigned long mask, unsig
 }
 #endif
 
-#define PROT_PTE_DEVICE		L_PTE_PRESENT|L_PTE_YOUNG|L_PTE_DIRTY|L_PTE_WRITE
+#define PROT_PTE_DEVICE		L_PTE_PRESENT|L_PTE_YOUNG|L_PTE_DIRTY|L_PTE_XN
 #define PROT_SECT_DEVICE	PMD_TYPE_SECT|PMD_SECT_AP_WRITE
 
 static struct mem_type mem_types[] = {
@@ -235,19 +236,18 @@ static struct mem_type mem_types[] = {
 	},
 	[MT_LOW_VECTORS] = {
 		.prot_pte  = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |
-				L_PTE_EXEC,
+				L_PTE_RDONLY,
 		.prot_l1   = PMD_TYPE_TABLE,
 		.domain    = DOMAIN_USER,
 	},
 	[MT_HIGH_VECTORS] = {
 		.prot_pte  = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |
-				L_PTE_USER | L_PTE_EXEC,
+				L_PTE_USER | L_PTE_RDONLY,
 		.prot_l1   = PMD_TYPE_TABLE,
 		.domain    = DOMAIN_USER,
 	},
 	[MT_MEMORY] = {
-		.prot_pte  = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |
-				L_PTE_WRITE | L_PTE_EXEC,
+		.prot_pte  = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY,
 		.prot_l1   = PMD_TYPE_TABLE,
 		.prot_sect = PMD_TYPE_SECT | PMD_SECT_AP_WRITE,
 		.domain    = DOMAIN_KERNEL,
@@ -258,21 +258,20 @@ static struct mem_type mem_types[] = {
 	},
 	[MT_MEMORY_NONCACHED] = {
 		.prot_pte  = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |
-				L_PTE_WRITE | L_PTE_EXEC | L_PTE_MT_BUFFERABLE,
+				L_PTE_MT_BUFFERABLE,
 		.prot_l1   = PMD_TYPE_TABLE,
 		.prot_sect = PMD_TYPE_SECT | PMD_SECT_AP_WRITE,
 		.domain    = DOMAIN_KERNEL,
 	},
 	[MT_MEMORY_DTCM] = {
 		.prot_pte  = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |
-				L_PTE_WRITE,
+				L_PTE_XN,
 		.prot_l1   = PMD_TYPE_TABLE,
 		.prot_sect = PMD_TYPE_SECT | PMD_SECT_XN,
 		.domain    = DOMAIN_KERNEL,
 	},
 	[MT_MEMORY_ITCM] = {
-		.prot_pte  = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |
-				L_PTE_WRITE | L_PTE_EXEC,
+		.prot_pte  = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY,
 		.prot_l1   = PMD_TYPE_TABLE,
 		.domain    = DOMAIN_KERNEL,
 	},
@@ -479,7 +478,7 @@ static void __init build_mem_type_table(
 
 	pgprot_user   = __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | user_pgprot);
 	pgprot_kernel = __pgprot(L_PTE_PRESENT | L_PTE_YOUNG |
-				 L_PTE_DIRTY | L_PTE_WRITE | kern_pgprot);
+				 L_PTE_DIRTY | kern_pgprot);
 
 	mem_types[MT_LOW_VECTORS].prot_l1 |= ecc_mask;
 	mem_types[MT_HIGH_VECTORS].prot_l1 |= ecc_mask;
@@ -535,7 +534,7 @@ static pte_t * __init early_pte_alloc(pm
 {
 	if (pmd_none(*pmd)) {
 		pte_t *pte = early_alloc(2 * PTRS_PER_PTE * sizeof(pte_t));
-		__pmd_populate(pmd, __pa(pte) | prot);
+		__pmd_populate(pmd, __pa(pte), prot);
 	}
 	BUG_ON(pmd_bad(*pmd));
 	return pte_offset_kernel(pmd, addr);
@@ -553,7 +552,7 @@ static void __init alloc_init_pte(pmd_t
 }
 
 static void __init alloc_init_section(pgd_t *pgd, unsigned long addr,
-				      unsigned long end, unsigned long phys,
+				      unsigned long end, phys_addr_t phys,
 				      const struct mem_type *type)
 {
 	pmd_t *pmd = pmd_offset(pgd, addr);
@@ -588,7 +587,8 @@ static void __init alloc_init_section(pg
 static void __init create_36bit_mapping(struct map_desc *md,
 					const struct mem_type *type)
 {
-	unsigned long phys, addr, length, end;
+	unsigned long addr, length, end;
+	phys_addr_t phys;
 	pgd_t *pgd;
 
 	addr = md->virtual;
@@ -914,12 +914,11 @@ static void __init devicemaps_init(struc
 {
 	struct map_desc map;
 	unsigned long addr;
-	void *vectors;
 
 	/*
 	 * Allocate the vector page early.
 	 */
-	vectors = early_alloc(PAGE_SIZE);
+	vectors_page = early_alloc(PAGE_SIZE);
 
 	for (addr = VMALLOC_END; addr; addr += PGDIR_SIZE)
 		pmd_clear(pmd_off_k(addr));
@@ -959,7 +958,7 @@ static void __init devicemaps_init(struc
 	 * location (0xffff0000).  If we aren't using high-vectors, also
 	 * create a mapping at the low-vectors virtual address.
 	 */
-	map.pfn = __phys_to_pfn(virt_to_phys(vectors));
+	map.pfn = __phys_to_pfn(virt_to_phys(vectors_page));
 	map.virtual = 0xffff0000;
 	map.length = PAGE_SIZE;
 	map.type = MT_HIGH_VECTORS;
@@ -1044,38 +1043,3 @@ void __init paging_init(struct machine_d
 	empty_zero_page = virt_to_page(zero_page);
 	__flush_dcache_page(NULL, empty_zero_page);
 }
-
-/*
- * In order to soft-boot, we need to insert a 1:1 mapping in place of
- * the user-mode pages.  This will then ensure that we have predictable
- * results when turning the mmu off
- */
-void setup_mm_for_reboot(char mode)
-{
-	unsigned long base_pmdval;
-	pgd_t *pgd;
-	int i;
-
-	/*
-	 * We need to access to user-mode page tables here. For kernel threads
-	 * we don't have any user-mode mappings so we use the context that we
-	 * "borrowed".
-	 */
-	pgd = current->active_mm->pgd;
-
-	base_pmdval = PMD_SECT_AP_WRITE | PMD_SECT_AP_READ | PMD_TYPE_SECT;
-	if (cpu_architecture() <= CPU_ARCH_ARMv5TEJ && !cpu_is_xscale())
-		base_pmdval |= PMD_BIT4;
-
-	for (i = 0; i < FIRST_USER_PGD_NR + USER_PTRS_PER_PGD; i++, pgd++) {
-		unsigned long pmdval = (i << PGDIR_SHIFT) | base_pmdval;
-		pmd_t *pmd;
-
-		pmd = pmd_off(pgd, i << PGDIR_SHIFT);
-		pmd[0] = __pmd(pmdval);
-		pmd[1] = __pmd(pmdval + (1 << (PGDIR_SHIFT - 1)));
-		flush_pmd_entry(pmd);
-	}
-
-	local_flush_tlb_all();
-}
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mm/pgd.c linux-libre-2.6.38-gnu1/arch/arm/mm/pgd.c
--- linux-libre-2.6.37-gnu1/arch/arm/mm/pgd.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mm/pgd.c	2011-03-14 21:20:32.000000000 -0400
@@ -17,12 +17,10 @@
 
 #include "mm.h"
 
-#define FIRST_KERNEL_PGD_NR	(FIRST_USER_PGD_NR + USER_PTRS_PER_PGD)
-
 /*
  * need to get a 16k page for level 1
  */
-pgd_t *get_pgd_slow(struct mm_struct *mm)
+pgd_t *pgd_alloc(struct mm_struct *mm)
 {
 	pgd_t *new_pgd, *init_pgd;
 	pmd_t *new_pmd, *init_pmd;
@@ -32,14 +30,14 @@ pgd_t *get_pgd_slow(struct mm_struct *mm
 	if (!new_pgd)
 		goto no_pgd;
 
-	memset(new_pgd, 0, FIRST_KERNEL_PGD_NR * sizeof(pgd_t));
+	memset(new_pgd, 0, USER_PTRS_PER_PGD * sizeof(pgd_t));
 
 	/*
 	 * Copy over the kernel and IO PGD entries
 	 */
 	init_pgd = pgd_offset_k(0);
-	memcpy(new_pgd + FIRST_KERNEL_PGD_NR, init_pgd + FIRST_KERNEL_PGD_NR,
-		       (PTRS_PER_PGD - FIRST_KERNEL_PGD_NR) * sizeof(pgd_t));
+	memcpy(new_pgd + USER_PTRS_PER_PGD, init_pgd + USER_PTRS_PER_PGD,
+		       (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
 
 	clean_dcache_area(new_pgd, PTRS_PER_PGD * sizeof(pgd_t));
 
@@ -52,7 +50,7 @@ pgd_t *get_pgd_slow(struct mm_struct *mm
 		if (!new_pmd)
 			goto no_pmd;
 
-		new_pte = pte_alloc_map(mm, new_pmd, 0);
+		new_pte = pte_alloc_map(mm, NULL, new_pmd, 0);
 		if (!new_pte)
 			goto no_pte;
 
@@ -73,28 +71,29 @@ no_pgd:
 	return NULL;
 }
 
-void free_pgd_slow(struct mm_struct *mm, pgd_t *pgd)
+void pgd_free(struct mm_struct *mm, pgd_t *pgd_base)
 {
+	pgd_t *pgd;
 	pmd_t *pmd;
 	pgtable_t pte;
 
-	if (!pgd)
+	if (!pgd_base)
 		return;
 
-	/* pgd is always present and good */
-	pmd = pmd_off(pgd, 0);
-	if (pmd_none(*pmd))
-		goto free;
-	if (pmd_bad(*pmd)) {
-		pmd_ERROR(*pmd);
-		pmd_clear(pmd);
-		goto free;
-	}
+	pgd = pgd_base + pgd_index(0);
+	if (pgd_none_or_clear_bad(pgd))
+		goto no_pgd;
+
+	pmd = pmd_offset(pgd, 0);
+	if (pmd_none_or_clear_bad(pmd))
+		goto no_pmd;
 
 	pte = pmd_pgtable(*pmd);
 	pmd_clear(pmd);
 	pte_free(mm, pte);
+no_pmd:
+	pgd_clear(pgd);
 	pmd_free(mm, pmd);
-free:
-	free_pages((unsigned long) pgd, 2);
+no_pgd:
+	free_pages((unsigned long) pgd_base, 2);
 }
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mm/proc-macros.S linux-libre-2.6.38-gnu1/arch/arm/mm/proc-macros.S
--- linux-libre-2.6.37-gnu1/arch/arm/mm/proc-macros.S	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mm/proc-macros.S	2011-03-14 21:20:32.000000000 -0400
@@ -91,7 +91,7 @@
 #if L_PTE_SHARED != PTE_EXT_SHARED
 #error PTE shared bit mismatch
 #endif
-#if (L_PTE_EXEC+L_PTE_USER+L_PTE_WRITE+L_PTE_DIRTY+L_PTE_YOUNG+\
+#if (L_PTE_XN+L_PTE_USER+L_PTE_RDONLY+L_PTE_DIRTY+L_PTE_YOUNG+\
      L_PTE_FILE+L_PTE_PRESENT) > L_PTE_SHARED
 #error Invalid Linux PTE bit settings
 #endif
@@ -109,6 +109,10 @@
  *  110x   0   1   0	r/w	r/o
  *  11x0   0   1   0	r/w	r/o
  *  1111   0   1   1	r/w	r/w
+ *
+ * If !CONFIG_CPU_USE_DOMAINS, the following permissions are changed:
+ *  110x   1   1   1	r/o	r/o
+ *  11x0   1   1   1	r/o	r/o
  */
 	.macro	armv6_mt_table pfx
 \pfx\()_mt_table:
@@ -131,7 +135,7 @@
 	.endm
 
 	.macro	armv6_set_pte_ext pfx
-	str	r1, [r0], #-2048		@ linux version
+	str	r1, [r0], #2048			@ linux version
 
 	bic	r3, r1, #0x000003fc
 	bic	r3, r3, #PTE_TYPE_MASK
@@ -142,17 +146,20 @@
 	and	r2, r1, #L_PTE_MT_MASK
 	ldr	r2, [ip, r2]
 
-	tst	r1, #L_PTE_WRITE
-	tstne	r1, #L_PTE_DIRTY
-	orreq	r3, r3, #PTE_EXT_APX
+	eor	r1, r1, #L_PTE_DIRTY
+	tst	r1, #L_PTE_DIRTY|L_PTE_RDONLY
+	orrne	r3, r3, #PTE_EXT_APX
 
 	tst	r1, #L_PTE_USER
 	orrne	r3, r3, #PTE_EXT_AP1
+#ifdef CONFIG_CPU_USE_DOMAINS
+	@ allow kernel read/write access to read-only user pages
 	tstne	r3, #PTE_EXT_APX
 	bicne	r3, r3, #PTE_EXT_APX | PTE_EXT_AP0
+#endif
 
-	tst	r1, #L_PTE_EXEC
-	orreq	r3, r3, #PTE_EXT_XN
+	tst	r1, #L_PTE_XN
+	orrne	r3, r3, #PTE_EXT_XN
 
 	orr	r3, r3, r2
 
@@ -180,9 +187,9 @@
  *  1111  0xff	r/w	r/w
  */
 	.macro	armv3_set_pte_ext wc_disable=1
-	str	r1, [r0], #-2048		@ linux version
+	str	r1, [r0], #2048			@ linux version
 
-	eor	r3, r1, #L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_WRITE | L_PTE_DIRTY
+	eor	r3, r1, #L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY
 
 	bic	r2, r1, #PTE_SMALL_AP_MASK	@ keep C, B bits
 	bic	r2, r2, #PTE_TYPE_MASK
@@ -191,7 +198,7 @@
 	tst	r3, #L_PTE_USER			@ user?
 	orrne	r2, r2, #PTE_SMALL_AP_URO_SRW
 
-	tst	r3, #L_PTE_WRITE | L_PTE_DIRTY	@ write and dirty?
+	tst	r3, #L_PTE_RDONLY | L_PTE_DIRTY	@ write and dirty?
 	orreq	r2, r2, #PTE_SMALL_AP_UNO_SRW
 
 	tst	r3, #L_PTE_PRESENT | L_PTE_YOUNG	@ present and young?
@@ -203,7 +210,7 @@
 	bicne	r2, r2, #PTE_BUFFERABLE
 #endif
 	.endif
-	str	r2, [r0]			@ hardware version
+	str	r2, [r0]		@ hardware version
 	.endm
 
 
@@ -223,9 +230,9 @@
  *  1111  11	r/w	r/w
  */
 	.macro	xscale_set_pte_ext_prologue
-	str	r1, [r0], #-2048		@ linux version
+	str	r1, [r0]			@ linux version
 
-	eor	r3, r1, #L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_WRITE | L_PTE_DIRTY
+	eor	r3, r1, #L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY
 
 	bic	r2, r1, #PTE_SMALL_AP_MASK	@ keep C, B bits
 	orr	r2, r2, #PTE_TYPE_EXT		@ extended page
@@ -233,7 +240,7 @@
 	tst	r3, #L_PTE_USER			@ user?
 	orrne	r2, r2, #PTE_EXT_AP_URO_SRW	@ yes -> user r/o, system r/w
 
-	tst	r3, #L_PTE_WRITE | L_PTE_DIRTY	@ write and dirty?
+	tst	r3, #L_PTE_RDONLY | L_PTE_DIRTY	@ write and dirty?
 	orreq	r2, r2, #PTE_EXT_AP_UNO_SRW	@ yes -> user n/a, system r/w
 						@ combined with user -> user r/w
 	.endm
@@ -242,7 +249,7 @@
 	tst	r3, #L_PTE_PRESENT | L_PTE_YOUNG	@ present and young?
 	movne	r2, #0				@ no -> fault
 
-	str	r2, [r0]			@ hardware version
+	str	r2, [r0, #2048]!		@ hardware version
 	mov	ip, #0
 	mcr	p15, 0, r0, c7, c10, 1		@ clean L1 D line
 	mcr	p15, 0, ip, c7, c10, 4		@ data write barrier
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mm/proc-v7.S linux-libre-2.6.38-gnu1/arch/arm/mm/proc-v7.S
--- linux-libre-2.6.37-gnu1/arch/arm/mm/proc-v7.S	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mm/proc-v7.S	2011-03-14 21:20:32.000000000 -0400
@@ -124,15 +124,13 @@ ENDPROC(cpu_v7_switch_mm)
  *	Set a level 2 translation table entry.
  *
  *	- ptep  - pointer to level 2 translation table entry
- *		  (hardware version is stored at -1024 bytes)
+ *		  (hardware version is stored at +2048 bytes)
  *	- pte   - PTE value to store
  *	- ext	- value for extended PTE bits
  */
 ENTRY(cpu_v7_set_pte_ext)
 #ifdef CONFIG_MMU
- ARM(	str	r1, [r0], #-2048	)	@ linux version
- THUMB(	str	r1, [r0]		)	@ linux version
- THUMB(	sub	r0, r0, #2048		)
+	str	r1, [r0]			@ linux version
 
 	bic	r3, r1, #0x000003f0
 	bic	r3, r3, #PTE_TYPE_MASK
@@ -142,23 +140,28 @@ ENTRY(cpu_v7_set_pte_ext)
 	tst	r1, #1 << 4
 	orrne	r3, r3, #PTE_EXT_TEX(1)
 
-	tst	r1, #L_PTE_WRITE
-	tstne	r1, #L_PTE_DIRTY
-	orreq	r3, r3, #PTE_EXT_APX
+	eor	r1, r1, #L_PTE_DIRTY
+	tst	r1, #L_PTE_RDONLY | L_PTE_DIRTY
+	orrne	r3, r3, #PTE_EXT_APX
 
 	tst	r1, #L_PTE_USER
 	orrne	r3, r3, #PTE_EXT_AP1
+#ifdef CONFIG_CPU_USE_DOMAINS
+	@ allow kernel read/write access to read-only user pages
 	tstne	r3, #PTE_EXT_APX
 	bicne	r3, r3, #PTE_EXT_APX | PTE_EXT_AP0
+#endif
 
-	tst	r1, #L_PTE_EXEC
-	orreq	r3, r3, #PTE_EXT_XN
+	tst	r1, #L_PTE_XN
+	orrne	r3, r3, #PTE_EXT_XN
 
 	tst	r1, #L_PTE_YOUNG
 	tstne	r1, #L_PTE_PRESENT
 	moveq	r3, #0
 
-	str	r3, [r0]
+ ARM(	str	r3, [r0, #2048]! )
+ THUMB(	add	r0, r0, #2048 )
+ THUMB(	str	r3, [r0] )
 	mcr	p15, 0, r0, c7, c10, 1		@ flush_pte
 #endif
 	mov	pc, lr
@@ -261,6 +264,12 @@ __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
+	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
+#endif
 
 3:	mov	r10, #0
 #ifdef HARVARD_CACHE
@@ -273,8 +282,6 @@ __v7_setup:
 	ALT_SMP(orr	r4, r4, #TTB_FLAGS_SMP)
 	ALT_UP(orr	r4, r4, #TTB_FLAGS_UP)
 	mcr	p15, 0, r4, c2, c0, 1		@ load TTB1
-	mov	r10, #0x1f			@ domains 0, 1 = manager
-	mcr	p15, 0, r10, c3, c0, 0		@ load domain access register
 	/*
 	 * Memory region attributes with SCTLR.TRE=1
 	 *
@@ -313,6 +320,10 @@ __v7_setup:
 #ifdef CONFIG_CPU_ENDIAN_BE8
 	orr	r6, r6, #1 << 25		@ big-endian page tables
 #endif
+#ifdef CONFIG_SWP_EMULATE
+	orr     r5, r5, #(1 << 10)              @ set SW bit in "clear"
+	bic     r6, r6, #(1 << 10)              @ clear it in "mmuset"
+#endif
    	mrc	p15, 0, r0, c1, c0, 0		@ read control register
 	bic	r0, r0, r5			@ clear bits them
 	orr	r0, r0, r6			@ set them
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/mm/proc-xscale.S linux-libre-2.6.38-gnu1/arch/arm/mm/proc-xscale.S
--- linux-libre-2.6.37-gnu1/arch/arm/mm/proc-xscale.S	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/mm/proc-xscale.S	2011-03-14 21:20:32.000000000 -0400
@@ -500,8 +500,8 @@ ENTRY(cpu_xscale_set_pte_ext)
 	@
 	@ Erratum 40: must set memory to write-through for user read-only pages
 	@
-	and	ip, r1, #(L_PTE_MT_MASK | L_PTE_USER | L_PTE_WRITE) & ~(4 << 2)
-	teq	ip, #L_PTE_MT_WRITEBACK | L_PTE_USER
+	and	ip, r1, #(L_PTE_MT_MASK | L_PTE_USER | L_PTE_RDONLY) & ~(4 << 2)
+	teq	ip, #L_PTE_MT_WRITEBACK | L_PTE_USER | L_PTE_RDONLY
 
 	moveq	r1, #L_PTE_MT_WRITETHROUGH
 	and	r1, r1, #L_PTE_MT_MASK
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/oprofile/common.c linux-libre-2.6.38-gnu1/arch/arm/oprofile/common.c
--- linux-libre-2.6.37-gnu1/arch/arm/oprofile/common.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/oprofile/common.c	2011-03-14 21:20:32.000000000 -0400
@@ -10,8 +10,6 @@
  */
 
 #include <linux/cpumask.h>
-#include <linux/err.h>
-#include <linux/errno.h>
 #include <linux/init.h>
 #include <linux/mutex.h>
 #include <linux/oprofile.h>
@@ -46,6 +44,7 @@ char *op_name_from_perf_id(void)
 		return NULL;
 	}
 }
+#endif
 
 static int report_trace(struct stackframe *frame, void *d)
 {
@@ -85,7 +84,7 @@ static struct frame_tail* user_backtrace
 
 	/* frame pointers should strictly progress back up the stack
 	 * (towards higher addresses) */
-	if (tail >= buftail[0].fp)
+	if (tail + 1 >= buftail[0].fp)
 		return NULL;
 
 	return buftail[0].fp-1;
@@ -111,6 +110,7 @@ static void arm_backtrace(struct pt_regs
 
 int __init oprofile_arch_init(struct oprofile_operations *ops)
 {
+	/* provide backtrace support also in timer mode: */
 	ops->backtrace		= arm_backtrace;
 
 	return oprofile_perf_init(ops);
@@ -120,11 +120,3 @@ void __exit oprofile_arch_exit(void)
 {
 	oprofile_perf_exit();
 }
-#else
-int __init oprofile_arch_init(struct oprofile_operations *ops)
-{
-	pr_info("oprofile: hardware counters not available\n");
-	return -ENODEV;
-}
-void __exit oprofile_arch_exit(void) {}
-#endif /* CONFIG_HW_PERF_EVENTS */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-iop/time.c linux-libre-2.6.38-gnu1/arch/arm/plat-iop/time.c
--- linux-libre-2.6.37-gnu1/arch/arm/plat-iop/time.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-iop/time.c	2011-03-14 21:20:32.000000000 -0400
@@ -17,6 +17,7 @@
 #include <linux/interrupt.h>
 #include <linux/time.h>
 #include <linux/init.h>
+#include <linux/sched.h>
 #include <linux/timex.h>
 #include <linux/sched.h>
 #include <linux/io.h>
@@ -24,6 +25,7 @@
 #include <linux/clockchips.h>
 #include <mach/hardware.h>
 #include <asm/irq.h>
+#include <asm/sched_clock.h>
 #include <asm/uaccess.h>
 #include <asm/mach/irq.h>
 #include <asm/mach/time.h>
@@ -50,15 +52,21 @@ static struct clocksource iop_clocksourc
 	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
+static DEFINE_CLOCK_DATA(cd);
+
 /*
  * IOP sched_clock() implementation via its clocksource.
  */
-unsigned long long sched_clock(void)
+unsigned long long notrace sched_clock(void)
 {
-	cycle_t cyc = iop_clocksource_read(NULL);
-	struct clocksource *cs = &iop_clocksource;
+	u32 cyc = 0xffffffffu - read_tcr1();
+	return cyc_to_sched_clock(&cd, cyc, (u32)~0);
+}
 
-	return clocksource_cyc2ns(cyc, cs->mult, cs->shift);
+static void notrace iop_update_sched_clock(void)
+{
+	u32 cyc = 0xffffffffu - read_tcr1();
+	update_sched_clock(&cd, cyc, (u32)~0);
 }
 
 /*
@@ -88,6 +96,7 @@ static void iop_set_mode(enum clock_even
 	case CLOCK_EVT_MODE_PERIODIC:
 		write_tmr0(tmr & ~IOP_TMR_EN);
 		write_tcr0(ticks_per_jiffy - 1);
+		write_trr0(ticks_per_jiffy - 1);
 		tmr |= (IOP_TMR_RELOAD | IOP_TMR_EN);
 		break;
 	case CLOCK_EVT_MODE_ONESHOT:
@@ -143,6 +152,8 @@ void __init iop_init_time(unsigned long
 {
 	u32 timer_ctl;
 
+	init_sched_clock(&cd, iop_update_sched_clock, 32, tick_rate);
+
 	ticks_per_jiffy = DIV_ROUND_CLOSEST(tick_rate, HZ);
 	iop_tick_rate = tick_rate;
 
@@ -153,6 +164,7 @@ void __init iop_init_time(unsigned long
 	 * Set up interrupting clockevent timer 0.
 	 */
 	write_tmr0(timer_ctl & ~IOP_TMR_EN);
+	write_tisr(1);
 	setup_irq(IRQ_IOP_TIMER0, &iop_timer_irq);
 	clockevents_calc_mult_shift(&iop_clockevent,
 				    tick_rate, IOP_MIN_RANGE);
@@ -162,9 +174,6 @@ void __init iop_init_time(unsigned long
 		clockevent_delta2ns(0xf, &iop_clockevent);
 	iop_clockevent.cpumask = cpumask_of(0);
 	clockevents_register_device(&iop_clockevent);
-	write_trr0(ticks_per_jiffy - 1);
-	write_tcr0(ticks_per_jiffy - 1);
-	write_tmr0(timer_ctl);
 
 	/*
 	 * Set up free-running clocksource timer 1.
@@ -172,7 +181,5 @@ void __init iop_init_time(unsigned long
 	write_trr1(0xffffffff);
 	write_tcr1(0xffffffff);
 	write_tmr1(timer_ctl);
-	clocksource_calc_mult_shift(&iop_clocksource, tick_rate,
-				    IOP_MIN_RANGE);
-	clocksource_register(&iop_clocksource);
+	clocksource_register_hz(&iop_clocksource, tick_rate);
 }
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/3ds_debugboard.c linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/3ds_debugboard.c
--- linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/3ds_debugboard.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/3ds_debugboard.c	2011-03-14 21:20:32.000000000 -0400
@@ -60,7 +60,6 @@
 #define EXPIO_INT_BUTTON_B	(MXC_BOARD_IRQ_START + 4)
 
 static void __iomem *brd_io;
-static void expio_ack_irq(u32 irq);
 
 static struct resource smsc911x_resources[] = {
 	{
@@ -93,7 +92,8 @@ static void mxc_expio_irq_handler(u32 ir
 	u32 int_valid;
 	u32 expio_irq;
 
-	desc->chip->mask(irq);	/* irq = gpio irq number */
+	/* irq = gpio irq number */
+	desc->irq_data.chip->irq_mask(&desc->irq_data);
 
 	imr_val = __raw_readw(brd_io + INTR_MASK_REG);
 	int_valid = __raw_readw(brd_io + INTR_STATUS_REG) & ~imr_val;
@@ -110,37 +110,37 @@ static void mxc_expio_irq_handler(u32 ir
 			d->handle_irq(expio_irq, d);
 	}
 
-	desc->chip->ack(irq);
-	desc->chip->unmask(irq);
+	desc->irq_data.chip->irq_ack(&desc->irq_data);
+	desc->irq_data.chip->irq_unmask(&desc->irq_data);
 }
 
 /*
  * Disable an expio pin's interrupt by setting the bit in the imr.
  * Irq is an expio virtual irq number
  */
-static void expio_mask_irq(u32 irq)
+static void expio_mask_irq(struct irq_data *d)
 {
 	u16 reg;
-	u32 expio = MXC_IRQ_TO_EXPIO(irq);
+	u32 expio = MXC_IRQ_TO_EXPIO(d->irq);
 
 	reg = __raw_readw(brd_io + INTR_MASK_REG);
 	reg |= (1 << expio);
 	__raw_writew(reg, brd_io + INTR_MASK_REG);
 }
 
-static void expio_ack_irq(u32 irq)
+static void expio_ack_irq(struct irq_data *d)
 {
-	u32 expio = MXC_IRQ_TO_EXPIO(irq);
+	u32 expio = MXC_IRQ_TO_EXPIO(d->irq);
 
 	__raw_writew(1 << expio, brd_io + INTR_RESET_REG);
 	__raw_writew(0, brd_io + INTR_RESET_REG);
-	expio_mask_irq(irq);
+	expio_mask_irq(d);
 }
 
-static void expio_unmask_irq(u32 irq)
+static void expio_unmask_irq(struct irq_data *d)
 {
 	u16 reg;
-	u32 expio = MXC_IRQ_TO_EXPIO(irq);
+	u32 expio = MXC_IRQ_TO_EXPIO(d->irq);
 
 	reg = __raw_readw(brd_io + INTR_MASK_REG);
 	reg &= ~(1 << expio);
@@ -148,9 +148,9 @@ static void expio_unmask_irq(u32 irq)
 }
 
 static struct irq_chip expio_irq_chip = {
-	.ack = expio_ack_irq,
-	.mask = expio_mask_irq,
-	.unmask = expio_unmask_irq,
+	.irq_ack = expio_ack_irq,
+	.irq_mask = expio_mask_irq,
+	.irq_unmask = expio_unmask_irq,
 };
 
 int __init mxc_expio_init(u32 base, u32 p_irq)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/audmux-v2.c linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/audmux-v2.c
--- linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/audmux-v2.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/audmux-v2.c	2011-03-14 21:20:32.000000000 -0400
@@ -209,7 +209,7 @@ static int mxc_audmux_v2_init(void)
 		audmux_base = MX35_IO_ADDRESS(MX35_AUDMUX_BASE_ADDR);
 	}
 #endif
-#if defined(CONFIG_ARCH_MX25)
+#if defined(CONFIG_SOC_IMX25)
 	if (cpu_is_mx25()) {
 		audmux_clk = clk_get(NULL, "audmux");
 		if (IS_ERR(audmux_clk)) {
@@ -220,7 +220,7 @@ static int mxc_audmux_v2_init(void)
 		}
 		audmux_base = MX25_IO_ADDRESS(MX25_AUDMUX_BASE_ADDR);
 	}
-#endif
+#endif /* if defined(CONFIG_SOC_IMX25) */
 	audmux_debugfs_init();
 
 	return 0;
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/avic.c linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/avic.c
--- linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/avic.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/avic.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,158 @@
+/*
+ * Copyright 2004-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.
+ */
+
+#include <linux/module.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <mach/common.h>
+#include <asm/mach/irq.h>
+#include <mach/hardware.h>
+
+#include "irq-common.h"
+
+#define AVIC_INTCNTL		0x00	/* int control reg */
+#define AVIC_NIMASK		0x04	/* int mask reg */
+#define AVIC_INTENNUM		0x08	/* int enable number reg */
+#define AVIC_INTDISNUM		0x0C	/* int disable number reg */
+#define AVIC_INTENABLEH		0x10	/* int enable reg high */
+#define AVIC_INTENABLEL		0x14	/* int enable reg low */
+#define AVIC_INTTYPEH		0x18	/* int type reg high */
+#define AVIC_INTTYPEL		0x1C	/* int type reg low */
+#define AVIC_NIPRIORITY(x)	(0x20 + 4 * (7 - (x))) /* int priority */
+#define AVIC_NIVECSR		0x40	/* norm int vector/status */
+#define AVIC_FIVECSR		0x44	/* fast int vector/status */
+#define AVIC_INTSRCH		0x48	/* int source reg high */
+#define AVIC_INTSRCL		0x4C	/* int source reg low */
+#define AVIC_INTFRCH		0x50	/* int force reg high */
+#define AVIC_INTFRCL		0x54	/* int force reg low */
+#define AVIC_NIPNDH		0x58	/* norm int pending high */
+#define AVIC_NIPNDL		0x5C	/* norm int pending low */
+#define AVIC_FIPNDH		0x60	/* fast int pending high */
+#define AVIC_FIPNDL		0x64	/* fast int pending low */
+
+void __iomem *avic_base;
+
+#ifdef CONFIG_MXC_IRQ_PRIOR
+static int avic_irq_set_priority(unsigned char irq, unsigned char prio)
+{
+	unsigned int temp;
+	unsigned int mask = 0x0F << irq % 8 * 4;
+
+	if (irq >= MXC_INTERNAL_IRQS)
+		return -EINVAL;;
+
+	temp = __raw_readl(avic_base + AVIC_NIPRIORITY(irq / 8));
+	temp &= ~mask;
+	temp |= prio & mask;
+
+	__raw_writel(temp, avic_base + AVIC_NIPRIORITY(irq / 8));
+
+	return 0;
+}
+#endif
+
+#ifdef CONFIG_FIQ
+static int avic_set_irq_fiq(unsigned int irq, unsigned int type)
+{
+	unsigned int irqt;
+
+	if (irq >= MXC_INTERNAL_IRQS)
+		return -EINVAL;
+
+	if (irq < MXC_INTERNAL_IRQS / 2) {
+		irqt = __raw_readl(avic_base + AVIC_INTTYPEL) & ~(1 << irq);
+		__raw_writel(irqt | (!!type << irq), avic_base + AVIC_INTTYPEL);
+	} else {
+		irq -= MXC_INTERNAL_IRQS / 2;
+		irqt = __raw_readl(avic_base + AVIC_INTTYPEH) & ~(1 << irq);
+		__raw_writel(irqt | (!!type << irq), avic_base + AVIC_INTTYPEH);
+	}
+
+	return 0;
+}
+#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,
+	},
+#ifdef CONFIG_MXC_IRQ_PRIOR
+	.set_priority = avic_irq_set_priority,
+#endif
+#ifdef CONFIG_FIQ
+	.set_irq_fiq = avic_set_irq_fiq,
+#endif
+};
+
+/*
+ * This function initializes the AVIC hardware and disables all the
+ * interrupts. It registers the interrupt enable and disable functions
+ * to the kernel for each interrupt source.
+ */
+void __init mxc_init_irq(void __iomem *irqbase)
+{
+	int i;
+
+	avic_base = irqbase;
+
+	/* put the AVIC into the reset value with
+	 * all interrupts disabled
+	 */
+	__raw_writel(0, avic_base + AVIC_INTCNTL);
+	__raw_writel(0x1f, avic_base + AVIC_NIMASK);
+
+	/* disable all interrupts */
+	__raw_writel(0, avic_base + AVIC_INTENABLEH);
+	__raw_writel(0, avic_base + AVIC_INTENABLEL);
+
+	/* all IRQ no FIQ */
+	__raw_writel(0, avic_base + AVIC_INTTYPEH);
+	__raw_writel(0, avic_base + AVIC_INTTYPEL);
+	for (i = 0; i < MXC_INTERNAL_IRQS; i++) {
+		set_irq_chip(i, &mxc_avic_chip.base);
+		set_irq_handler(i, handle_level_irq);
+		set_irq_flags(i, IRQF_VALID);
+	}
+
+	/* Set default priority value (0) for all IRQ's */
+	for (i = 0; i < 8; i++)
+		__raw_writel(0, avic_base + AVIC_NIPRIORITY(i));
+
+#ifdef CONFIG_FIQ
+	/* Initialize FIQ */
+	init_FIQ();
+#endif
+
+	printk(KERN_INFO "MXC IRQ initialized\n");
+}
+
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/cpufreq.c linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/cpufreq.c
--- linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/cpufreq.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/cpufreq.c	2011-03-14 21:20:32.000000000 -0400
@@ -144,7 +144,6 @@ static int __init mxc_cpufreq_init(struc
 	imx_freq_table[i].frequency = CPUFREQ_TABLE_END;
 
 	policy->cur = clk_get_rate(cpu_clk) / 1000;
-	policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
 	policy->min = policy->cpuinfo.min_freq = cpu_freq_khz_min;
 	policy->max = policy->cpuinfo.max_freq = cpu_freq_khz_max;
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/devices/Kconfig linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/devices/Kconfig
--- linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/devices/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/devices/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -1,29 +1,73 @@
-config IMX_HAVE_PLATFORM_ESDHC
-	bool
-
 config IMX_HAVE_PLATFORM_FEC
 	bool
-	default y if ARCH_MX25 || SOC_IMX27 || ARCH_MX35 || ARCH_MX51
+	default y if ARCH_MX25 || SOC_IMX27 || SOC_IMX35 || SOC_IMX51 || SOC_IMX53
 
 config IMX_HAVE_PLATFORM_FLEXCAN
 	select HAVE_CAN_FLEXCAN if CAN
 	bool
 
+config IMX_HAVE_PLATFORM_FSL_USB2_UDC
+	bool
+
 config IMX_HAVE_PLATFORM_GPIO_KEYS
 	bool
-	default y if ARCH_MX51
+	default y if SOC_IMX51
+
+config IMX_HAVE_PLATFORM_IMX21_HCD
+	bool
 	
+config IMX_HAVE_PLATFORM_IMX2_WDT
+	bool
+
+config IMX_HAVE_PLATFORM_IMXDI_RTC
+	bool
+
+config IMX_HAVE_PLATFORM_IMX_FB
+	bool
+	select HAVE_FB_IMX
+
 config IMX_HAVE_PLATFORM_IMX_I2C
 	bool
 
+config IMX_HAVE_PLATFORM_IMX_KEYPAD
+	bool
+
 config IMX_HAVE_PLATFORM_IMX_SSI
 	bool
 
 config IMX_HAVE_PLATFORM_IMX_UART
 	bool
 
+config IMX_HAVE_PLATFORM_IMX_UDC
+	bool
+
+config IMX_HAVE_PLATFORM_MX1_CAMERA
+	bool
+
+config IMX_HAVE_PLATFORM_MX2_CAMERA
+	bool
+
+config IMX_HAVE_PLATFORM_MXC_EHCI
+	bool
+
+config IMX_HAVE_PLATFORM_MXC_MMC
+	bool
+
 config IMX_HAVE_PLATFORM_MXC_NAND
 	bool
 
+config IMX_HAVE_PLATFORM_MXC_PWM
+	bool
+
+config IMX_HAVE_PLATFORM_MXC_RNGA
+	bool
+	select ARCH_HAS_RNGA
+
+config IMX_HAVE_PLATFORM_MXC_W1
+	bool
+
+config IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
+	bool
+
 config IMX_HAVE_PLATFORM_SPI_IMX
 	bool
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/devices/Makefile linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/devices/Makefile
--- linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/devices/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/devices/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -1,10 +1,24 @@
-obj-$(CONFIG_IMX_HAVE_PLATFORM_ESDHC) += platform-esdhc.o
 obj-$(CONFIG_IMX_HAVE_PLATFORM_FEC) += platform-fec.o
 obj-$(CONFIG_IMX_HAVE_PLATFORM_FLEXCAN) += platform-flexcan.o
+obj-$(CONFIG_IMX_HAVE_PLATFORM_FSL_USB2_UDC) += platform-fsl-usb2-udc.o
 obj-$(CONFIG_IMX_HAVE_PLATFORM_GPIO_KEYS) += platform-gpio_keys.o
+obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX21_HCD) += platform-imx21-hcd.o
+obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX2_WDT) += platform-imx2-wdt.o
+obj-$(CONFIG_IMX_HAVE_PLATFORM_IMXDI_RTC) += platform-imxdi_rtc.o
 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_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
+obj-$(CONFIG_IMX_HAVE_PLATFORM_MX1_CAMERA) += platform-mx1-camera.o
+obj-$(CONFIG_IMX_HAVE_PLATFORM_MX2_CAMERA) += platform-mx2-camera.o
+obj-$(CONFIG_IMX_HAVE_PLATFORM_MXC_EHCI) += platform-mxc-ehci.o
+obj-$(CONFIG_IMX_HAVE_PLATFORM_MXC_MMC) += platform-mxc-mmc.o
 obj-$(CONFIG_IMX_HAVE_PLATFORM_MXC_NAND) += platform-mxc_nand.o
+obj-$(CONFIG_IMX_HAVE_PLATFORM_MXC_PWM) += platform-mxc_pwm.o
+obj-$(CONFIG_IMX_HAVE_PLATFORM_MXC_RNGA) += platform-mxc_rnga.o
+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
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/devices/platform-esdhc.c linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/devices/platform-esdhc.c
--- linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/devices/platform-esdhc.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/devices/platform-esdhc.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2010 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 <mach/hardware.h>
-#include <mach/devices-common.h>
-#include <mach/esdhc.h>
-
-#define imx_esdhc_imx_data_entry_single(soc, _id, hwid) \
-	{								\
-		.id = _id,						\
-		.iobase = soc ## _ESDHC ## hwid ## _BASE_ADDR,	\
-		.irq = soc ## _INT_ESDHC ## hwid,			\
-	}
-
-#define imx_esdhc_imx_data_entry(soc, id, hwid)	\
-	[id] = imx_esdhc_imx_data_entry_single(soc, id, hwid)
-
-#ifdef CONFIG_ARCH_MX25
-const struct imx_esdhc_imx_data imx25_esdhc_data[] __initconst = {
-#define imx25_esdhc_data_entry(_id, _hwid)				\
-	imx_esdhc_imx_data_entry(MX25, _id, _hwid)
-	imx25_esdhc_data_entry(0, 1),
-	imx25_esdhc_data_entry(1, 2),
-};
-#endif /* ifdef CONFIG_ARCH_MX25 */
-
-#ifdef CONFIG_ARCH_MX35
-const struct imx_esdhc_imx_data imx35_esdhc_data[] __initconst = {
-#define imx35_esdhc_data_entry(_id, _hwid)                           \
-	imx_esdhc_imx_data_entry(MX35, _id, _hwid)
-	imx35_esdhc_data_entry(0, 1),
-	imx35_esdhc_data_entry(1, 2),
-	imx35_esdhc_data_entry(2, 3),
-};
-#endif /* ifdef CONFIG_ARCH_MX35 */
-
-#ifdef CONFIG_ARCH_MX51
-const struct imx_esdhc_imx_data imx51_esdhc_data[] __initconst = {
-#define imx51_esdhc_data_entry(_id, _hwid)				\
-	imx_esdhc_imx_data_entry(MX51, _id, _hwid)
-	imx51_esdhc_data_entry(0, 1),
-	imx51_esdhc_data_entry(1, 2),
-	imx51_esdhc_data_entry(2, 3),
-	imx51_esdhc_data_entry(3, 4),
-};
-#endif /* ifdef CONFIG_ARCH_MX51 */
-
-struct platform_device *__init imx_add_esdhc(
-		const struct imx_esdhc_imx_data *data,
-		const struct esdhc_platform_data *pdata)
-{
-	struct resource res[] = {
-		{
-			.start = data->iobase,
-			.end = data->iobase + SZ_16K - 1,
-			.flags = IORESOURCE_MEM,
-		}, {
-			.start = data->irq,
-			.end = data->irq,
-			.flags = IORESOURCE_IRQ,
-		},
-	};
-
-	return imx_add_platform_device("sdhci-esdhc-imx", data->id, res,
-			ARRAY_SIZE(res), pdata, sizeof(*pdata));
-}
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/devices/platform-fec.c linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/devices/platform-fec.c
--- linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/devices/platform-fec.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/devices/platform-fec.c	2011-03-14 21:20:32.000000000 -0400
@@ -16,26 +16,31 @@
 		.irq = soc ## _INT_FEC,					\
 	}
 
-#ifdef CONFIG_ARCH_MX25
+#ifdef CONFIG_SOC_IMX25
 const struct imx_fec_data imx25_fec_data __initconst =
 	imx_fec_data_entry_single(MX25);
-#endif /* ifdef CONFIG_ARCH_MX25 */
+#endif /* ifdef CONFIG_SOC_IMX25 */
 
 #ifdef CONFIG_SOC_IMX27
 const struct imx_fec_data imx27_fec_data __initconst =
 	imx_fec_data_entry_single(MX27);
 #endif /* ifdef CONFIG_SOC_IMX27 */
 
-#ifdef CONFIG_ARCH_MX35
+#ifdef CONFIG_SOC_IMX35
 const struct imx_fec_data imx35_fec_data __initconst =
 	imx_fec_data_entry_single(MX35);
 #endif
 
-#ifdef CONFIG_ARCH_MX51
+#ifdef CONFIG_SOC_IMX51
 const struct imx_fec_data imx51_fec_data __initconst =
 	imx_fec_data_entry_single(MX51);
 #endif
 
+#ifdef CONFIG_SOC_IMX53
+const struct imx_fec_data imx53_fec_data __initconst =
+	imx_fec_data_entry_single(MX53);
+#endif
+
 struct platform_device *__init imx_add_fec(
 		const struct imx_fec_data *data,
 		const struct fec_platform_data *pdata)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/devices/platform-flexcan.c linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/devices/platform-flexcan.c
--- linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/devices/platform-flexcan.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/devices/platform-flexcan.c	2011-03-14 21:20:32.000000000 -0400
@@ -5,26 +5,54 @@
  * 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>
 
-struct platform_device *__init imx_add_flexcan(int id,
-		resource_size_t iobase, resource_size_t iosize,
-		resource_size_t irq,
+#define imx_flexcan_data_entry_single(soc, _id, _hwid, _size)		\
+	{								\
+		.id = _id,						\
+		.iobase = soc ## _CAN ## _hwid ## _BASE_ADDR,		\
+		.iosize = _size,					\
+		.irq = soc ## _INT_CAN ## _hwid,			\
+	}
+
+#define imx_flexcan_data_entry(soc, _id, _hwid, _size)			\
+	[_id] = imx_flexcan_data_entry_single(soc, _id, _hwid, _size)
+
+#ifdef CONFIG_SOC_IMX25
+const struct imx_flexcan_data imx25_flexcan_data[] __initconst = {
+#define imx25_flexcan_data_entry(_id, _hwid)				\
+	imx_flexcan_data_entry(MX25, _id, _hwid, SZ_16K)
+	imx25_flexcan_data_entry(0, 1),
+	imx25_flexcan_data_entry(1, 2),
+};
+#endif /* ifdef CONFIG_SOC_IMX25 */
+
+#ifdef CONFIG_SOC_IMX35
+const struct imx_flexcan_data imx35_flexcan_data[] __initconst = {
+#define imx35_flexcan_data_entry(_id, _hwid)				\
+	imx_flexcan_data_entry(MX35, _id, _hwid, SZ_16K)
+	imx35_flexcan_data_entry(0, 1),
+	imx35_flexcan_data_entry(1, 2),
+};
+#endif /* ifdef CONFIG_SOC_IMX35 */
+
+struct platform_device *__init imx_add_flexcan(
+		const struct imx_flexcan_data *data,
 		const struct flexcan_platform_data *pdata)
 {
 	struct resource res[] = {
 		{
-			.start = iobase,
-			.end = iobase + iosize - 1,
+			.start = data->iobase,
+			.end = data->iobase + data->iosize - 1,
 			.flags = IORESOURCE_MEM,
 		}, {
-			.start = irq,
-			.end = irq,
+			.start = data->irq,
+			.end = data->irq,
 			.flags = IORESOURCE_IRQ,
 		},
 	};
 
-	return imx_add_platform_device("flexcan", id, res, ARRAY_SIZE(res),
-			pdata, sizeof(*pdata));
+	return imx_add_platform_device("flexcan", data->id,
+			res, ARRAY_SIZE(res), pdata, sizeof(*pdata));
 }
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/devices/platform-fsl-usb2-udc.c linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/devices/platform-fsl-usb2-udc.c
--- linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/devices/platform-fsl-usb2-udc.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/devices/platform-fsl-usb2-udc.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2010 Pengutronix
+ * Uwe Kleine-Koenig <u.kleine-koenig@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 <mach/hardware.h>
+#include <mach/devices-common.h>
+
+#define imx_fsl_usb2_udc_data_entry_single(soc)				\
+	{								\
+		.iobase = soc ## _USB_OTG_BASE_ADDR,			\
+		.irq = soc ## _INT_USB_OTG,				\
+	}
+
+#ifdef CONFIG_SOC_IMX25
+const struct imx_fsl_usb2_udc_data imx25_fsl_usb2_udc_data __initconst =
+	imx_fsl_usb2_udc_data_entry_single(MX25);
+#endif /* ifdef CONFIG_SOC_IMX25 */
+
+#ifdef CONFIG_SOC_IMX27
+const struct imx_fsl_usb2_udc_data imx27_fsl_usb2_udc_data __initconst =
+	imx_fsl_usb2_udc_data_entry_single(MX27);
+#endif /* ifdef CONFIG_SOC_IMX27 */
+
+#ifdef CONFIG_SOC_IMX31
+const struct imx_fsl_usb2_udc_data imx31_fsl_usb2_udc_data __initconst =
+	imx_fsl_usb2_udc_data_entry_single(MX31);
+#endif /* ifdef CONFIG_SOC_IMX31 */
+
+#ifdef CONFIG_SOC_IMX35
+const struct imx_fsl_usb2_udc_data imx35_fsl_usb2_udc_data __initconst =
+	imx_fsl_usb2_udc_data_entry_single(MX35);
+#endif /* ifdef CONFIG_SOC_IMX35 */
+
+struct platform_device *__init imx_add_fsl_usb2_udc(
+		const struct imx_fsl_usb2_udc_data *data,
+		const struct fsl_usb2_platform_data *pdata)
+{
+	struct resource res[] = {
+		{
+			.start = data->iobase,
+			.end = data->iobase + SZ_512 - 1,
+			.flags = IORESOURCE_MEM,
+		}, {
+			.start = data->irq,
+			.end = data->irq,
+			.flags = IORESOURCE_IRQ,
+		},
+	};
+	return imx_add_platform_device_dmamask("fsl-usb2-udc", -1,
+			res, ARRAY_SIZE(res),
+			pdata, sizeof(*pdata), DMA_BIT_MASK(32));
+}
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/devices/platform-imx21-hcd.c linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/devices/platform-imx21-hcd.c
--- linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/devices/platform-imx21-hcd.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/devices/platform-imx21-hcd.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2010 Pengutronix
+ * Uwe Kleine-Koenig <u.kleine-koenig@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 <mach/hardware.h>
+#include <mach/devices-common.h>
+
+#define imx_imx21_hcd_data_entry_single(soc)				\
+	{								\
+		.iobase = soc ## _USBOTG_BASE_ADDR,			\
+		.irq = soc ## _INT_USBHOST,				\
+	}
+
+#ifdef CONFIG_SOC_IMX21
+const struct imx_imx21_hcd_data imx21_imx21_hcd_data __initconst =
+	imx_imx21_hcd_data_entry_single(MX21);
+#endif /* ifdef CONFIG_SOC_IMX21 */
+
+struct platform_device *__init imx_add_imx21_hcd(
+		const struct imx_imx21_hcd_data *data,
+		const struct mx21_usbh_platform_data *pdata)
+{
+	struct resource res[] = {
+		{
+			.start = data->iobase,
+			.end = data->iobase + SZ_8K - 1,
+			.flags = IORESOURCE_MEM,
+		}, {
+			.start = data->irq,
+			.end = data->irq,
+			.flags = IORESOURCE_IRQ,
+		},
+	};
+	return imx_add_platform_device_dmamask("imx21-hcd", 0,
+			res, ARRAY_SIZE(res),
+			pdata, sizeof(*pdata), DMA_BIT_MASK(32));
+}
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/devices/platform-imx2-wdt.c linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/devices/platform-imx2-wdt.c
--- linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/devices/platform-imx2-wdt.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/devices/platform-imx2-wdt.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2010 Pengutronix
+ * Uwe Kleine-Koenig <u.kleine-koenig@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/hardware.h>
+#include <mach/devices-common.h>
+
+#define imx_imx2_wdt_data_entry_single(soc, _id, _hwid, _size)		\
+	{								\
+		.id = _id,						\
+		.iobase = soc ## _WDOG ## _hwid ## _BASE_ADDR,		\
+		.iosize = _size,					\
+	}
+#define imx_imx2_wdt_data_entry(soc, _id, _hwid, _size)			\
+	[_id] = imx_imx2_wdt_data_entry_single(soc, _id, _hwid, _size)
+
+#ifdef CONFIG_SOC_IMX21
+const struct imx_imx2_wdt_data imx21_imx2_wdt_data __initconst =
+	imx_imx2_wdt_data_entry_single(MX21, 0, , SZ_4K);
+#endif /* ifdef CONFIG_SOC_IMX21 */
+
+#ifdef CONFIG_SOC_IMX25
+const struct imx_imx2_wdt_data imx25_imx2_wdt_data __initconst =
+	imx_imx2_wdt_data_entry_single(MX25, 0, , SZ_16K);
+#endif /* ifdef CONFIG_SOC_IMX25 */
+
+#ifdef CONFIG_SOC_IMX27
+const struct imx_imx2_wdt_data imx27_imx2_wdt_data __initconst =
+	imx_imx2_wdt_data_entry_single(MX27, 0, , SZ_4K);
+#endif /* ifdef CONFIG_SOC_IMX27 */
+
+#ifdef CONFIG_SOC_IMX31
+const struct imx_imx2_wdt_data imx31_imx2_wdt_data __initconst =
+	imx_imx2_wdt_data_entry_single(MX31, 0, , SZ_16K);
+#endif /* ifdef CONFIG_SOC_IMX31 */
+
+#ifdef CONFIG_SOC_IMX35
+const struct imx_imx2_wdt_data imx35_imx2_wdt_data __initconst =
+	imx_imx2_wdt_data_entry_single(MX35, 0, , SZ_16K);
+#endif /* ifdef CONFIG_SOC_IMX35 */
+
+#ifdef CONFIG_SOC_IMX51
+const struct imx_imx2_wdt_data imx51_imx2_wdt_data[] __initconst = {
+#define imx51_imx2_wdt_data_entry(_id, _hwid)				\
+	imx_imx2_wdt_data_entry(MX51, _id, _hwid, SZ_16K)
+	imx51_imx2_wdt_data_entry(0, 1),
+	imx51_imx2_wdt_data_entry(1, 2),
+};
+#endif /* ifdef CONFIG_SOC_IMX51 */
+
+struct platform_device *__init imx_add_imx2_wdt(
+		const struct imx_imx2_wdt_data *data)
+{
+	struct resource res[] = {
+		{
+			.start = data->iobase,
+			.end = data->iobase + data->iosize - 1,
+			.flags = IORESOURCE_MEM,
+		},
+	};
+	return imx_add_platform_device("imx2-wdt", data->id,
+			res, ARRAY_SIZE(res), NULL, 0);
+}
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/devices/platform-imxdi_rtc.c linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/devices/platform-imxdi_rtc.c
--- linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/devices/platform-imxdi_rtc.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/devices/platform-imxdi_rtc.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2010 Pengutronix
+ * Uwe Kleine-Koenig <u.kleine-koenig@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/hardware.h>
+#include <mach/devices-common.h>
+
+#define imx_imxdi_rtc_data_entry_single(soc)				\
+	{								\
+		.iobase = soc ## _DRYICE_BASE_ADDR,			\
+		.irq = soc ## _INT_DRYICE,				\
+	}
+
+#ifdef CONFIG_SOC_IMX25
+const struct imx_imxdi_rtc_data imx25_imxdi_rtc_data __initconst =
+	imx_imxdi_rtc_data_entry_single(MX25);
+#endif /* ifdef CONFIG_SOC_IMX25 */
+
+struct platform_device *__init imx_add_imxdi_rtc(
+		const struct imx_imxdi_rtc_data *data)
+{
+	struct resource res[] = {
+		{
+			.start = data->iobase,
+			.end = data->iobase + SZ_16K,
+			.flags = IORESOURCE_MEM,
+		}, {
+			.start = data->irq,
+			.end = data->irq,
+			.flags = IORESOURCE_IRQ,
+		},
+	};
+
+	return imx_add_platform_device("imxdi_rtc", 0,
+			res, ARRAY_SIZE(res), NULL, 0);
+}
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/devices/platform-imx-dma.c linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/devices/platform-imx-dma.c
--- linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/devices/platform-imx-dma.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/devices/platform-imx-dma.c	2011-03-14 21:20:32.000000000 -0400
@@ -31,25 +31,25 @@ struct imx_imx_sdma_data {
 		},							\
 	}
 
-#ifdef CONFIG_ARCH_MX25
-const struct imx_imx_sdma_data imx25_imx_sdma_data __initconst =
+#ifdef CONFIG_SOC_IMX25
+struct imx_imx_sdma_data imx25_imx_sdma_data __initconst =
 	imx_imx_sdma_data_entry_single(MX25, 1, "imx25", 0);
-#endif /* ifdef CONFIG_ARCH_MX25 */
+#endif /* ifdef CONFIG_SOC_IMX25 */
 
-#ifdef CONFIG_ARCH_MX31
+#ifdef CONFIG_SOC_IMX31
 struct imx_imx_sdma_data imx31_imx_sdma_data __initdata =
 	imx_imx_sdma_data_entry_single(MX31, 1, "imx31", 0);
-#endif /* ifdef CONFIG_ARCH_MX31 */
+#endif /* ifdef CONFIG_SOC_IMX31 */
 
-#ifdef CONFIG_ARCH_MX35
+#ifdef CONFIG_SOC_IMX35
 struct imx_imx_sdma_data imx35_imx_sdma_data __initdata =
 	imx_imx_sdma_data_entry_single(MX35, 2, "imx35", 0);
-#endif /* ifdef CONFIG_ARCH_MX35 */
+#endif /* ifdef CONFIG_SOC_IMX35 */
 
-#ifdef CONFIG_ARCH_MX51
-const struct imx_imx_sdma_data imx51_imx_sdma_data __initconst =
+#ifdef CONFIG_SOC_IMX51
+struct imx_imx_sdma_data imx51_imx_sdma_data __initconst =
 	imx_imx_sdma_data_entry_single(MX51, 2, "imx51", 0);
-#endif /* ifdef CONFIG_ARCH_MX51 */
+#endif /* ifdef CONFIG_SOC_IMX51 */
 
 static struct platform_device __init __maybe_unused *imx_add_imx_sdma(
 		const struct imx_imx_sdma_data *data)
@@ -76,6 +76,83 @@ static struct platform_device __init __m
 	return imx_add_platform_device("imx-dma", -1, NULL, 0, NULL, 0);
 }
 
+#ifdef CONFIG_ARCH_MX25
+static struct sdma_script_start_addrs addr_imx25_to1 = {
+	.ap_2_ap_addr = 729,
+	.uart_2_mcu_addr = 904,
+	.per_2_app_addr = 1255,
+	.mcu_2_app_addr = 834,
+	.uartsh_2_mcu_addr = 1120,
+	.per_2_shp_addr = 1329,
+	.mcu_2_shp_addr = 1048,
+	.ata_2_mcu_addr = 1560,
+	.mcu_2_ata_addr = 1479,
+	.app_2_per_addr = 1189,
+	.app_2_mcu_addr = 770,
+	.shp_2_per_addr = 1407,
+	.shp_2_mcu_addr = 979,
+};
+#endif
+
+#ifdef CONFIG_ARCH_MX31
+static struct sdma_script_start_addrs addr_imx31_to1 = {
+	.per_2_per_addr = 1677,
+};
+
+static struct sdma_script_start_addrs addr_imx31_to2 = {
+	.ap_2_ap_addr = 423,
+	.ap_2_bp_addr = 829,
+	.bp_2_ap_addr = 1029,
+};
+#endif
+
+#ifdef CONFIG_ARCH_MX35
+static struct sdma_script_start_addrs addr_imx35_to1 = {
+	.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 addr_imx35_to2 = {
+	.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,
+};
+#endif
+
+#ifdef CONFIG_SOC_IMX51
+static struct sdma_script_start_addrs addr_imx51_to1 = {
+	.ap_2_ap_addr = 642,
+	.uart_2_mcu_addr = 817,
+	.mcu_2_app_addr = 747,
+	.mcu_2_shp_addr = 961,
+	.ata_2_mcu_addr = 1473,
+	.mcu_2_ata_addr = 1392,
+	.app_2_per_addr = 1033,
+	.app_2_mcu_addr = 683,
+	.shp_2_per_addr = 1251,
+	.shp_2_mcu_addr = 892,
+};
+#endif
+
 static int __init imxXX_add_imx_dma(void)
 {
 	struct platform_device *ret;
@@ -86,30 +163,42 @@ static int __init imxXX_add_imx_dma(void
 	else
 #endif
 
-#if defined(CONFIG_ARCH_MX25)
-	if (cpu_is_mx25())
+#if defined(CONFIG_SOC_IMX25)
+	if (cpu_is_mx25()) {
+		imx25_imx_sdma_data.pdata.script_addrs = &addr_imx25_to1;
 		ret = imx_add_imx_sdma(&imx25_imx_sdma_data);
-	else
+	} else
 #endif
 
-#if defined(CONFIG_ARCH_MX31)
+#if defined(CONFIG_SOC_IMX31)
 	if (cpu_is_mx31()) {
-		imx31_imx_sdma_data.pdata.to_version = mx31_revision() >> 4;
+		int to_version = mx31_revision() >> 4;
+		imx31_imx_sdma_data.pdata.to_version = to_version;
+		if (to_version == 1)
+			imx31_imx_sdma_data.pdata.script_addrs = &addr_imx31_to1;
+		else
+			imx31_imx_sdma_data.pdata.script_addrs = &addr_imx31_to2;
 		ret = imx_add_imx_sdma(&imx31_imx_sdma_data);
 	} else
 #endif
 
-#if defined(CONFIG_ARCH_MX35)
+#if defined(CONFIG_SOC_IMX35)
 	if (cpu_is_mx35()) {
-		imx35_imx_sdma_data.pdata.to_version = mx35_revision() >> 4;
+		int to_version = mx35_revision() >> 4;
+		imx35_imx_sdma_data.pdata.to_version = to_version;
+		if (to_version == 1)
+			imx35_imx_sdma_data.pdata.script_addrs = &addr_imx35_to1;
+		else
+			imx35_imx_sdma_data.pdata.script_addrs = &addr_imx35_to2;
 		ret = imx_add_imx_sdma(&imx35_imx_sdma_data);
 	} else
 #endif
 
 #if defined(CONFIG_ARCH_MX51)
-	if (cpu_is_mx51())
+	if (cpu_is_mx51()) {
+		imx51_imx_sdma_data.pdata.script_addrs = &addr_imx51_to1;
 		ret = imx_add_imx_sdma(&imx51_imx_sdma_data);
-	else
+	} else
 #endif
 		ret = ERR_PTR(-ENODEV);
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/devices/platform-imx-fb.c linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/devices/platform-imx-fb.c
--- linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/devices/platform-imx-fb.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/devices/platform-imx-fb.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2010 Pengutronix
+ * Uwe Kleine-Koenig <u.kleine-koenig@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 <mach/hardware.h>
+#include <mach/devices-common.h>
+
+#define imx_imx_fb_data_entry_single(soc, _size)			\
+	{								\
+		.iobase = soc ## _LCDC_BASE_ADDR,			\
+		.iosize = _size,					\
+		.irq = soc ## _INT_LCDC,				\
+	}
+
+#ifdef CONFIG_SOC_IMX21
+const struct imx_imx_fb_data imx21_imx_fb_data __initconst =
+	imx_imx_fb_data_entry_single(MX21, SZ_4K);
+#endif /* ifdef CONFIG_SOC_IMX21 */
+
+#ifdef CONFIG_SOC_IMX25
+const struct imx_imx_fb_data imx25_imx_fb_data __initconst =
+	imx_imx_fb_data_entry_single(MX25, SZ_16K);
+#endif /* ifdef CONFIG_SOC_IMX25 */
+
+#ifdef CONFIG_SOC_IMX27
+const struct imx_imx_fb_data imx27_imx_fb_data __initconst =
+	imx_imx_fb_data_entry_single(MX27, SZ_4K);
+#endif /* ifdef CONFIG_SOC_IMX27 */
+
+struct platform_device *__init imx_add_imx_fb(
+		const struct imx_imx_fb_data *data,
+		const struct imx_fb_platform_data *pdata)
+{
+	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_dmamask("imx-fb", 0,
+			res, ARRAY_SIZE(res),
+			pdata, sizeof(*pdata), DMA_BIT_MASK(32));
+}
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/devices/platform-imx-i2c.c linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/devices/platform-imx-i2c.c
--- linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/devices/platform-imx-i2c.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/devices/platform-imx-i2c.c	2011-03-14 21:20:32.000000000 -0400
@@ -30,7 +30,7 @@ const struct imx_imx_i2c_data imx21_imx_
 	imx_imx_i2c_data_entry_single(MX21, 0, , SZ_4K);
 #endif /* ifdef CONFIG_SOC_IMX21 */
 
-#ifdef CONFIG_ARCH_MX25
+#ifdef CONFIG_SOC_IMX25
 const struct imx_imx_i2c_data imx25_imx_i2c_data[] __initconst = {
 #define imx25_imx_i2c_data_entry(_id, _hwid)				\
 	imx_imx_i2c_data_entry(MX25, _id, _hwid, SZ_16K)
@@ -38,7 +38,7 @@ const struct imx_imx_i2c_data imx25_imx_
 	imx25_imx_i2c_data_entry(1, 2),
 	imx25_imx_i2c_data_entry(2, 3),
 };
-#endif /* ifdef CONFIG_ARCH_MX25 */
+#endif /* ifdef CONFIG_SOC_IMX25 */
 
 #ifdef CONFIG_SOC_IMX27
 const struct imx_imx_i2c_data imx27_imx_i2c_data[] __initconst = {
@@ -49,7 +49,7 @@ const struct imx_imx_i2c_data imx27_imx_
 };
 #endif /* ifdef CONFIG_SOC_IMX27 */
 
-#ifdef CONFIG_ARCH_MX31
+#ifdef CONFIG_SOC_IMX31
 const struct imx_imx_i2c_data imx31_imx_i2c_data[] __initconst = {
 #define imx31_imx_i2c_data_entry(_id, _hwid)				\
 	imx_imx_i2c_data_entry(MX31, _id, _hwid, SZ_4K)
@@ -57,9 +57,9 @@ const struct imx_imx_i2c_data imx31_imx_
 	imx31_imx_i2c_data_entry(1, 2),
 	imx31_imx_i2c_data_entry(2, 3),
 };
-#endif /* ifdef CONFIG_ARCH_MX31 */
+#endif /* ifdef CONFIG_SOC_IMX31 */
 
-#ifdef CONFIG_ARCH_MX35
+#ifdef CONFIG_SOC_IMX35
 const struct imx_imx_i2c_data imx35_imx_i2c_data[] __initconst = {
 #define imx35_imx_i2c_data_entry(_id, _hwid)				\
 	imx_imx_i2c_data_entry(MX35, _id, _hwid, SZ_4K)
@@ -67,16 +67,25 @@ const struct imx_imx_i2c_data imx35_imx_
 	imx35_imx_i2c_data_entry(1, 2),
 	imx35_imx_i2c_data_entry(2, 3),
 };
-#endif /* ifdef CONFIG_ARCH_MX35 */
+#endif /* ifdef CONFIG_SOC_IMX35 */
 
-#ifdef CONFIG_ARCH_MX51
+#ifdef CONFIG_SOC_IMX51
 const struct imx_imx_i2c_data imx51_imx_i2c_data[] __initconst = {
 #define imx51_imx_i2c_data_entry(_id, _hwid)				\
 	imx_imx_i2c_data_entry(MX51, _id, _hwid, SZ_4K)
 	imx51_imx_i2c_data_entry(0, 1),
 	imx51_imx_i2c_data_entry(1, 2),
 };
-#endif /* ifdef CONFIG_ARCH_MX51 */
+#endif /* ifdef CONFIG_SOC_IMX51 */
+
+#ifdef CONFIG_SOC_IMX53
+const struct imx_imx_i2c_data imx53_imx_i2c_data[] __initconst = {
+#define imx53_imx_i2c_data_entry(_id, _hwid)				\
+	imx_imx_i2c_data_entry(MX53, _id, _hwid, SZ_4K)
+	imx53_imx_i2c_data_entry(0, 1),
+	imx53_imx_i2c_data_entry(1, 2),
+};
+#endif /* ifdef CONFIG_SOC_IMX51 */
 
 struct platform_device *__init imx_add_imx_i2c(
 		const struct imx_imx_i2c_data *data,
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/devices/platform-imx-keypad.c linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/devices/platform-imx-keypad.c
--- linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/devices/platform-imx-keypad.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/devices/platform-imx-keypad.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2010 Pengutronix
+ * Uwe Kleine-Koenig <u.kleine-koenig@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 <mach/hardware.h>
+#include <mach/devices-common.h>
+
+#define imx_imx_keypad_data_entry_single(soc, _size)			\
+	{								\
+		.iobase = soc ## _KPP_BASE_ADDR,			\
+		.iosize = _size,					\
+		.irq = soc ## _INT_KPP,					\
+	}
+
+#ifdef CONFIG_SOC_IMX21
+const struct imx_imx_keypad_data imx21_imx_keypad_data __initconst =
+	imx_imx_keypad_data_entry_single(MX21, SZ_16);
+#endif /* ifdef CONFIG_SOC_IMX21 */
+
+#ifdef CONFIG_SOC_IMX25
+const struct imx_imx_keypad_data imx25_imx_keypad_data __initconst =
+	imx_imx_keypad_data_entry_single(MX25, SZ_16K);
+#endif /* ifdef CONFIG_SOC_IMX25 */
+
+#ifdef CONFIG_SOC_IMX27
+const struct imx_imx_keypad_data imx27_imx_keypad_data __initconst =
+	imx_imx_keypad_data_entry_single(MX27, SZ_16);
+#endif /* ifdef CONFIG_SOC_IMX27 */
+
+#ifdef CONFIG_SOC_IMX31
+const struct imx_imx_keypad_data imx31_imx_keypad_data __initconst =
+	imx_imx_keypad_data_entry_single(MX31, SZ_16);
+#endif /* ifdef CONFIG_SOC_IMX31 */
+
+#ifdef CONFIG_SOC_IMX35
+const struct imx_imx_keypad_data imx35_imx_keypad_data __initconst =
+	imx_imx_keypad_data_entry_single(MX35, SZ_16);
+#endif /* ifdef CONFIG_SOC_IMX35 */
+
+#ifdef CONFIG_SOC_IMX51
+const struct imx_imx_keypad_data imx51_imx_keypad_data __initconst =
+	imx_imx_keypad_data_entry_single(MX51, SZ_16);
+#endif /* ifdef CONFIG_SOC_IMX51 */
+
+struct platform_device *__init imx_add_imx_keypad(
+		const struct imx_imx_keypad_data *data,
+		const struct matrix_keymap_data *pdata)
+{
+	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("imx-keypad", -1,
+			res, ARRAY_SIZE(res), pdata, sizeof(*pdata));
+}
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/devices/platform-imx-ssi.c linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/devices/platform-imx-ssi.c
--- linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/devices/platform-imx-ssi.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/devices/platform-imx-ssi.c	2011-03-14 21:20:32.000000000 -0400
@@ -30,14 +30,14 @@ const struct imx_imx_ssi_data imx21_imx_
 };
 #endif /* ifdef CONFIG_SOC_IMX21 */
 
-#ifdef CONFIG_ARCH_MX25
+#ifdef CONFIG_SOC_IMX25
 const struct imx_imx_ssi_data imx25_imx_ssi_data[] __initconst = {
 #define imx25_imx_ssi_data_entry(_id, _hwid)				\
 	imx_imx_ssi_data_entry(MX25, _id, _hwid, SZ_4K)
 	imx25_imx_ssi_data_entry(0, 1),
 	imx25_imx_ssi_data_entry(1, 2),
 };
-#endif /* ifdef CONFIG_ARCH_MX25 */
+#endif /* ifdef CONFIG_SOC_IMX25 */
 
 #ifdef CONFIG_SOC_IMX27
 const struct imx_imx_ssi_data imx27_imx_ssi_data[] __initconst = {
@@ -48,32 +48,33 @@ const struct imx_imx_ssi_data imx27_imx_
 };
 #endif /* ifdef CONFIG_SOC_IMX27 */
 
-#ifdef CONFIG_ARCH_MX31
+#ifdef CONFIG_SOC_IMX31
 const struct imx_imx_ssi_data imx31_imx_ssi_data[] __initconst = {
 #define imx31_imx_ssi_data_entry(_id, _hwid)				\
 	imx_imx_ssi_data_entry(MX31, _id, _hwid, SZ_4K)
 	imx31_imx_ssi_data_entry(0, 1),
 	imx31_imx_ssi_data_entry(1, 2),
 };
-#endif /* ifdef CONFIG_ARCH_MX31 */
+#endif /* ifdef CONFIG_SOC_IMX31 */
 
-#ifdef CONFIG_ARCH_MX35
+#ifdef CONFIG_SOC_IMX35
 const struct imx_imx_ssi_data imx35_imx_ssi_data[] __initconst = {
 #define imx35_imx_ssi_data_entry(_id, _hwid)				\
 	imx_imx_ssi_data_entry(MX35, _id, _hwid, SZ_4K)
 	imx35_imx_ssi_data_entry(0, 1),
 	imx35_imx_ssi_data_entry(1, 2),
 };
-#endif /* ifdef CONFIG_ARCH_MX35 */
+#endif /* ifdef CONFIG_SOC_IMX35 */
 
-#ifdef CONFIG_ARCH_MX51
+#ifdef CONFIG_SOC_IMX51
 const struct imx_imx_ssi_data imx51_imx_ssi_data[] __initconst = {
 #define imx51_imx_ssi_data_entry(_id, _hwid)				\
 	imx_imx_ssi_data_entry(MX51, _id, _hwid, SZ_4K)
 	imx51_imx_ssi_data_entry(0, 1),
 	imx51_imx_ssi_data_entry(1, 2),
+	imx51_imx_ssi_data_entry(2, 3),
 };
-#endif /* ifdef CONFIG_ARCH_MX51 */
+#endif /* ifdef CONFIG_SOC_IMX51 */
 
 struct platform_device *__init imx_add_imx_ssi(
 		const struct imx_imx_ssi_data *data,
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/devices/platform-imx-uart.c linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/devices/platform-imx-uart.c
--- linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/devices/platform-imx-uart.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/devices/platform-imx-uart.c	2011-03-14 21:20:32.000000000 -0400
@@ -47,7 +47,7 @@ const struct imx_imx_uart_1irq_data imx2
 };
 #endif
 
-#ifdef CONFIG_ARCH_MX25
+#ifdef CONFIG_SOC_IMX25
 const struct imx_imx_uart_1irq_data imx25_imx_uart_data[] __initconst = {
 #define imx25_imx_uart_data_entry(_id, _hwid)				\
 	imx_imx_uart_1irq_data_entry(MX25, _id, _hwid, SZ_16K)
@@ -57,7 +57,7 @@ const struct imx_imx_uart_1irq_data imx2
 	imx25_imx_uart_data_entry(3, 4),
 	imx25_imx_uart_data_entry(4, 5),
 };
-#endif /* ifdef CONFIG_ARCH_MX25 */
+#endif /* ifdef CONFIG_SOC_IMX25 */
 
 #ifdef CONFIG_SOC_IMX27
 const struct imx_imx_uart_1irq_data imx27_imx_uart_data[] __initconst = {
@@ -72,7 +72,7 @@ const struct imx_imx_uart_1irq_data imx2
 };
 #endif /* ifdef CONFIG_SOC_IMX27 */
 
-#ifdef CONFIG_ARCH_MX31
+#ifdef CONFIG_SOC_IMX31
 const struct imx_imx_uart_1irq_data imx31_imx_uart_data[] __initconst = {
 #define imx31_imx_uart_data_entry(_id, _hwid)				\
 	imx_imx_uart_1irq_data_entry(MX31, _id, _hwid, SZ_4K)
@@ -82,9 +82,9 @@ const struct imx_imx_uart_1irq_data imx3
 	imx31_imx_uart_data_entry(3, 4),
 	imx31_imx_uart_data_entry(4, 5),
 };
-#endif /* ifdef CONFIG_ARCH_MX31 */
+#endif /* ifdef CONFIG_SOC_IMX31 */
 
-#ifdef CONFIG_ARCH_MX35
+#ifdef CONFIG_SOC_IMX35
 const struct imx_imx_uart_1irq_data imx35_imx_uart_data[] __initconst = {
 #define imx35_imx_uart_data_entry(_id, _hwid)				\
 	imx_imx_uart_1irq_data_entry(MX31, _id, _hwid, SZ_16K)
@@ -92,9 +92,21 @@ const struct imx_imx_uart_1irq_data imx3
 	imx35_imx_uart_data_entry(1, 2),
 	imx35_imx_uart_data_entry(2, 3),
 };
-#endif /* ifdef CONFIG_ARCH_MX35 */
+#endif /* ifdef CONFIG_SOC_IMX35 */
 
-#ifdef CONFIG_ARCH_MX51
+#ifdef CONFIG_SOC_IMX50
+const struct imx_imx_uart_1irq_data imx50_imx_uart_data[] __initconst = {
+#define imx50_imx_uart_data_entry(_id, _hwid)				\
+	imx_imx_uart_1irq_data_entry(MX50, _id, _hwid, SZ_4K)
+	imx50_imx_uart_data_entry(0, 1),
+	imx50_imx_uart_data_entry(1, 2),
+	imx50_imx_uart_data_entry(2, 3),
+	imx50_imx_uart_data_entry(3, 4),
+	imx50_imx_uart_data_entry(4, 5),
+};
+#endif /* ifdef CONFIG_SOC_IMX50 */
+
+#ifdef CONFIG_SOC_IMX51
 const struct imx_imx_uart_1irq_data imx51_imx_uart_data[] __initconst = {
 #define imx51_imx_uart_data_entry(_id, _hwid)				\
 	imx_imx_uart_1irq_data_entry(MX51, _id, _hwid, SZ_4K)
@@ -102,7 +114,17 @@ const struct imx_imx_uart_1irq_data imx5
 	imx51_imx_uart_data_entry(1, 2),
 	imx51_imx_uart_data_entry(2, 3),
 };
-#endif /* ifdef CONFIG_ARCH_MX51 */
+#endif /* ifdef CONFIG_SOC_IMX51 */
+
+#ifdef CONFIG_SOC_IMX53
+const struct imx_imx_uart_1irq_data imx53_imx_uart_data[] __initconst = {
+#define imx53_imx_uart_data_entry(_id, _hwid)				\
+	imx_imx_uart_1irq_data_entry(MX53, _id, _hwid, SZ_4K)
+	imx53_imx_uart_data_entry(0, 1),
+	imx53_imx_uart_data_entry(1, 2),
+	imx53_imx_uart_data_entry(2, 3),
+};
+#endif /* ifdef CONFIG_SOC_IMX53 */
 
 struct platform_device *__init imx_add_imx_uart_3irq(
 		const struct imx_imx_uart_3irq_data *data,
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/devices/platform-imx_udc.c linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/devices/platform-imx_udc.c
--- linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/devices/platform-imx_udc.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/devices/platform-imx_udc.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2010 Pengutronix
+ * Uwe Kleine-Koenig <u.kleine-koenig@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 <mach/hardware.h>
+#include <mach/devices-common.h>
+
+#define imx_imx_udc_data_entry_single(soc, _size)			\
+	{								\
+		.iobase = soc ## _USBD_BASE_ADDR,			\
+		.iosize = _size,					\
+		.irq0 = soc ## _INT_USBD0,				\
+		.irq1 = soc ## _INT_USBD1,				\
+		.irq2 = soc ## _INT_USBD2,				\
+		.irq3 = soc ## _INT_USBD3,				\
+		.irq4 = soc ## _INT_USBD4,				\
+		.irq5 = soc ## _INT_USBD5,				\
+		.irq6 = soc ## _INT_USBD6,				\
+	}
+
+#define imx_imx_udc_data_entry(soc, _size)				\
+	[_id] = imx_imx_udc_data_entry_single(soc, _size)
+
+#ifdef CONFIG_SOC_IMX1
+const struct imx_imx_udc_data imx1_imx_udc_data __initconst =
+	imx_imx_udc_data_entry_single(MX1, SZ_4K);
+#endif /* ifdef CONFIG_SOC_IMX1 */
+
+struct platform_device *__init imx_add_imx_udc(
+		const struct imx_imx_udc_data *data,
+		const struct imxusb_platform_data *pdata)
+{
+	struct resource res[] = {
+		{
+			.start = data->iobase,
+			.end = data->iobase + data->iosize - 1,
+			.flags = IORESOURCE_MEM,
+		}, {
+			.start = data->irq0,
+			.end = data->irq0,
+			.flags = IORESOURCE_IRQ,
+		}, {
+			.start = data->irq1,
+			.end = data->irq1,
+			.flags = IORESOURCE_IRQ,
+		}, {
+			.start = data->irq2,
+			.end = data->irq2,
+			.flags = IORESOURCE_IRQ,
+		}, {
+			.start = data->irq3,
+			.end = data->irq3,
+			.flags = IORESOURCE_IRQ,
+		}, {
+			.start = data->irq4,
+			.end = data->irq4,
+			.flags = IORESOURCE_IRQ,
+		}, {
+			.start = data->irq5,
+			.end = data->irq5,
+			.flags = IORESOURCE_IRQ,
+		}, {
+			.start = data->irq6,
+			.end = data->irq6,
+			.flags = IORESOURCE_IRQ,
+		},
+	};
+
+	return imx_add_platform_device("imx_udc", 0,
+			res, ARRAY_SIZE(res), pdata, sizeof(*pdata));
+}
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/devices/platform-mx1-camera.c linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/devices/platform-mx1-camera.c
--- linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/devices/platform-mx1-camera.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/devices/platform-mx1-camera.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2010 Pengutronix
+ * Uwe Kleine-Koenig <u.kleine-koenig@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 <mach/hardware.h>
+#include <mach/devices-common.h>
+
+#define imx_mx1_camera_data_entry_single(soc, _size)			\
+	{								\
+		.iobase = soc ## _CSI ## _BASE_ADDR,			\
+		.iosize = _size,					\
+		.irq = soc ## _INT_CSI,					\
+	}
+
+#ifdef CONFIG_SOC_IMX1
+const struct imx_mx1_camera_data imx1_mx1_camera_data __initconst =
+	imx_mx1_camera_data_entry_single(MX1, 10);
+#endif /* ifdef CONFIG_SOC_IMX1 */
+
+struct platform_device *__init imx_add_mx1_camera(
+		const struct imx_mx1_camera_data *data,
+		const struct mx1_camera_pdata *pdata)
+{
+	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_dmamask("mx1-camera", 0,
+			res, ARRAY_SIZE(res),
+			pdata, sizeof(*pdata), DMA_BIT_MASK(32));
+}
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/devices/platform-mx2-camera.c linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/devices/platform-mx2-camera.c
--- linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/devices/platform-mx2-camera.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/devices/platform-mx2-camera.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2010 Pengutronix
+ * Uwe Kleine-Koenig <u.kleine-koenig@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 <mach/hardware.h>
+#include <mach/devices-common.h>
+
+#define imx_mx2_camera_data_entry_single(soc)				\
+	{								\
+		.iobasecsi = soc ## _CSI_BASE_ADDR,			\
+		.iosizecsi = SZ_4K,					\
+		.irqcsi = soc ## _INT_CSI,				\
+	}
+#define imx_mx2_camera_data_entry_single_emma(soc)			\
+	{								\
+		.iobasecsi = soc ## _CSI_BASE_ADDR,			\
+		.iosizecsi = SZ_32,					\
+		.irqcsi = soc ## _INT_CSI,				\
+		.iobaseemmaprp = soc ## _EMMAPRP_BASE_ADDR,		\
+		.iosizeemmaprp = SZ_32,					\
+		.irqemmaprp = soc ## _INT_EMMAPRP,			\
+	}
+
+#ifdef CONFIG_SOC_IMX25
+const struct imx_mx2_camera_data imx25_mx2_camera_data __initconst =
+	imx_mx2_camera_data_entry_single(MX25);
+#endif /* ifdef CONFIG_SOC_IMX25 */
+
+#ifdef CONFIG_SOC_IMX27
+const struct imx_mx2_camera_data imx27_mx2_camera_data __initconst =
+	imx_mx2_camera_data_entry_single_emma(MX27);
+#endif /* ifdef CONFIG_SOC_IMX27 */
+
+struct platform_device *__init imx_add_mx2_camera(
+		const struct imx_mx2_camera_data *data,
+		const struct mx2_camera_platform_data *pdata)
+{
+	struct resource res[] = {
+		{
+			.start = data->iobasecsi,
+			.end = data->iobasecsi + data->iosizecsi - 1,
+			.flags = IORESOURCE_MEM,
+		}, {
+			.start = data->irqcsi,
+			.end = data->irqcsi,
+			.flags = IORESOURCE_IRQ,
+		}, {
+			.start = data->iobaseemmaprp,
+			.end = data->iobaseemmaprp + data->iosizeemmaprp - 1,
+			.flags = IORESOURCE_MEM,
+		}, {
+			.start = data->irqemmaprp,
+			.end = data->irqemmaprp,
+			.flags = IORESOURCE_IRQ,
+		},
+	};
+	return imx_add_platform_device_dmamask("mx2-camera", 0,
+			res, data->iobaseemmaprp ? 4 : 2,
+			pdata, sizeof(*pdata), DMA_BIT_MASK(32));
+}
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/devices/platform-mxc-ehci.c linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/devices/platform-mxc-ehci.c
--- linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/devices/platform-mxc-ehci.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/devices/platform-mxc-ehci.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2010 Pengutronix
+ * Uwe Kleine-Koenig <u.kleine-koenig@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 <mach/hardware.h>
+#include <mach/devices-common.h>
+
+#define imx_mxc_ehci_data_entry_single(soc, _id, hs)			\
+	{								\
+		.id = _id,						\
+		.iobase = soc ## _USB_ ## hs ## _BASE_ADDR,		\
+		.irq = soc ## _INT_USB_ ## hs,				\
+	}
+
+#ifdef CONFIG_SOC_IMX25
+const struct imx_mxc_ehci_data imx25_mxc_ehci_otg_data __initconst =
+	imx_mxc_ehci_data_entry_single(MX25, 0, OTG);
+const struct imx_mxc_ehci_data imx25_mxc_ehci_hs_data __initconst =
+	imx_mxc_ehci_data_entry_single(MX25, 1, HS);
+#endif /* ifdef CONFIG_SOC_IMX25 */
+
+#ifdef CONFIG_SOC_IMX27
+const struct imx_mxc_ehci_data imx27_mxc_ehci_otg_data __initconst =
+	imx_mxc_ehci_data_entry_single(MX27, 0, OTG);
+const struct imx_mxc_ehci_data imx27_mxc_ehci_hs_data[] __initconst = {
+	imx_mxc_ehci_data_entry_single(MX27, 1, HS1),
+	imx_mxc_ehci_data_entry_single(MX27, 2, HS2),
+};
+#endif /* ifdef CONFIG_SOC_IMX27 */
+
+#ifdef CONFIG_SOC_IMX31
+const struct imx_mxc_ehci_data imx31_mxc_ehci_otg_data __initconst =
+	imx_mxc_ehci_data_entry_single(MX31, 0, OTG);
+const struct imx_mxc_ehci_data imx31_mxc_ehci_hs_data[] __initconst = {
+	imx_mxc_ehci_data_entry_single(MX31, 1, HS1),
+	imx_mxc_ehci_data_entry_single(MX31, 2, HS2),
+};
+#endif /* ifdef CONFIG_SOC_IMX31 */
+
+#ifdef CONFIG_SOC_IMX35
+const struct imx_mxc_ehci_data imx35_mxc_ehci_otg_data __initconst =
+	imx_mxc_ehci_data_entry_single(MX35, 0, OTG);
+const struct imx_mxc_ehci_data imx35_mxc_ehci_hs_data __initconst =
+	imx_mxc_ehci_data_entry_single(MX35, 1, HS);
+#endif /* ifdef CONFIG_SOC_IMX35 */
+
+struct platform_device *__init imx_add_mxc_ehci(
+		const struct imx_mxc_ehci_data *data,
+		const struct mxc_usbh_platform_data *pdata)
+{
+	struct resource res[] = {
+		{
+			.start = data->iobase,
+			.end = data->iobase + SZ_512 - 1,
+			.flags = IORESOURCE_MEM,
+		}, {
+			.start = data->irq,
+			.end = data->irq,
+			.flags = IORESOURCE_IRQ,
+		},
+	};
+	return imx_add_platform_device_dmamask("mxc-ehci", data->id,
+			res, ARRAY_SIZE(res),
+			pdata, sizeof(*pdata), DMA_BIT_MASK(32));
+}
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/devices/platform-mxc-mmc.c linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/devices/platform-mxc-mmc.c
--- linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/devices/platform-mxc-mmc.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/devices/platform-mxc-mmc.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2010 Pengutronix
+ * Uwe Kleine-Koenig <u.kleine-koenig@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 <mach/hardware.h>
+#include <mach/devices-common.h>
+
+#define imx_mxc_mmc_data_entry_single(soc, _id, _hwid, _size)		\
+	{								\
+		.id = _id,						\
+		.iobase = soc ## _SDHC ## _hwid ## _BASE_ADDR,		\
+		.iosize = _size,					\
+		.irq = soc ## _INT_SDHC ## _hwid,			\
+		.dmareq = soc ## _DMA_REQ_SDHC ## _hwid,		\
+	}
+#define imx_mxc_mmc_data_entry(soc, _id, _hwid, _size)			\
+	[_id] = imx_mxc_mmc_data_entry_single(soc, _id, _hwid, _size)
+
+#ifdef CONFIG_SOC_IMX21
+const struct imx_mxc_mmc_data imx21_mxc_mmc_data[] __initconst = {
+#define imx21_mxc_mmc_data_entry(_id, _hwid)				\
+	imx_mxc_mmc_data_entry(MX21, _id, _hwid, SZ_4K)
+	imx21_mxc_mmc_data_entry(0, 1),
+	imx21_mxc_mmc_data_entry(1, 2),
+};
+#endif /* ifdef CONFIG_SOC_IMX21 */
+
+#ifdef CONFIG_SOC_IMX27
+const struct imx_mxc_mmc_data imx27_mxc_mmc_data[] __initconst = {
+#define imx27_mxc_mmc_data_entry(_id, _hwid)				\
+	imx_mxc_mmc_data_entry(MX27, _id, _hwid, SZ_4K)
+	imx27_mxc_mmc_data_entry(0, 1),
+	imx27_mxc_mmc_data_entry(1, 2),
+};
+#endif /* ifdef CONFIG_SOC_IMX27 */
+
+#ifdef CONFIG_SOC_IMX31
+const struct imx_mxc_mmc_data imx31_mxc_mmc_data[] __initconst = {
+#define imx31_mxc_mmc_data_entry(_id, _hwid)				\
+	imx_mxc_mmc_data_entry(MX31, _id, _hwid, SZ_16K)
+	imx31_mxc_mmc_data_entry(0, 1),
+	imx31_mxc_mmc_data_entry(1, 2),
+};
+#endif /* ifdef CONFIG_SOC_IMX31 */
+
+struct platform_device *__init imx_add_mxc_mmc(
+		const struct imx_mxc_mmc_data *data,
+		const struct imxmmc_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,
+		}, {
+			.start = data->dmareq,
+			.end = data->dmareq,
+			.flags = IORESOURCE_DMA,
+		},
+	};
+	return imx_add_platform_device_dmamask("mxc-mmc", data->id,
+			res, ARRAY_SIZE(res),
+			pdata, sizeof(*pdata), DMA_BIT_MASK(32));
+}
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/devices/platform-mxc_nand.c linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/devices/platform-mxc_nand.c
--- linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/devices/platform-mxc_nand.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/devices/platform-mxc_nand.c	2011-03-14 21:20:32.000000000 -0400
@@ -31,27 +31,27 @@ const struct imx_mxc_nand_data imx21_mxc
 	imx_mxc_nand_data_entry_single(MX21, SZ_4K);
 #endif /* ifdef CONFIG_SOC_IMX21 */
 
-#ifdef CONFIG_ARCH_MX25
+#ifdef CONFIG_SOC_IMX25
 const struct imx_mxc_nand_data imx25_mxc_nand_data __initconst =
 	imx_mxc_nand_data_entry_single(MX25, SZ_8K);
-#endif /* ifdef CONFIG_ARCH_MX25 */
+#endif /* ifdef CONFIG_SOC_IMX25 */
 
 #ifdef CONFIG_SOC_IMX27
 const struct imx_mxc_nand_data imx27_mxc_nand_data __initconst =
 	imx_mxc_nand_data_entry_single(MX27, SZ_4K);
 #endif /* ifdef CONFIG_SOC_IMX27 */
 
-#ifdef CONFIG_ARCH_MX31
+#ifdef CONFIG_SOC_IMX31
 const struct imx_mxc_nand_data imx31_mxc_nand_data __initconst =
 	imx_mxc_nand_data_entry_single(MX31, SZ_4K);
 #endif
 
-#ifdef CONFIG_ARCH_MX35
+#ifdef CONFIG_SOC_IMX35
 const struct imx_mxc_nand_data imx35_mxc_nand_data __initconst =
 	imx_mxc_nand_data_entry_single(MX35, SZ_8K);
 #endif
 
-#ifdef CONFIG_ARCH_MX51
+#ifdef CONFIG_SOC_IMX51
 const struct imx_mxc_nand_data imx51_mxc_nand_data __initconst =
 	imx_mxc_nandv3_data_entry_single(MX51, SZ_16K);
 #endif
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/devices/platform-mxc_pwm.c linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/devices/platform-mxc_pwm.c
--- linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/devices/platform-mxc_pwm.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/devices/platform-mxc_pwm.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2009-2010 Pengutronix
+ * Uwe Kleine-Koenig <u.kleine-koenig@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 <mach/hardware.h>
+#include <mach/devices-common.h>
+
+#define imx_mxc_pwm_data_entry_single(soc, _id, _hwid, _size)		\
+	{								\
+		.id = _id,						\
+		.iobase = soc ## _PWM ## _hwid ## _BASE_ADDR,		\
+		.iosize = _size,					\
+		.irq = soc ## _INT_PWM ## _hwid,			\
+	}
+#define imx_mxc_pwm_data_entry(soc, _id, _hwid, _size)			\
+	[_id] = imx_mxc_pwm_data_entry_single(soc, _id, _hwid, _size)
+
+#ifdef CONFIG_SOC_IMX21
+const struct imx_mxc_pwm_data imx21_mxc_pwm_data __initconst =
+	imx_mxc_pwm_data_entry_single(MX21, 0, , SZ_4K);
+#endif /* ifdef CONFIG_SOC_IMX21 */
+
+#ifdef CONFIG_SOC_IMX25
+const struct imx_mxc_pwm_data imx25_mxc_pwm_data[] __initconst = {
+#define imx25_mxc_pwm_data_entry(_id, _hwid)				\
+	imx_mxc_pwm_data_entry(MX25, _id, _hwid, SZ_16K)
+	imx25_mxc_pwm_data_entry(0, 1),
+	imx25_mxc_pwm_data_entry(1, 2),
+	imx25_mxc_pwm_data_entry(2, 3),
+	imx25_mxc_pwm_data_entry(3, 4),
+};
+#endif /* ifdef CONFIG_SOC_IMX25 */
+
+#ifdef CONFIG_SOC_IMX27
+const struct imx_mxc_pwm_data imx27_mxc_pwm_data __initconst =
+	imx_mxc_pwm_data_entry_single(MX27, 0, , SZ_4K);
+#endif /* ifdef CONFIG_SOC_IMX27 */
+
+#ifdef CONFIG_SOC_IMX51
+const struct imx_mxc_pwm_data imx51_mxc_pwm_data[] __initconst = {
+#define imx51_mxc_pwm_data_entry(_id, _hwid)				\
+	imx_mxc_pwm_data_entry(MX51, _id, _hwid, SZ_16K)
+	imx51_mxc_pwm_data_entry(0, 1),
+	imx51_mxc_pwm_data_entry(1, 2),
+};
+#endif /* ifdef CONFIG_SOC_IMX51 */
+
+struct platform_device *__init imx_add_mxc_pwm(
+		const struct imx_mxc_pwm_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("mxc_pwm", data->id,
+			res, ARRAY_SIZE(res), NULL, 0);
+}
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/devices/platform-mxc_rnga.c linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/devices/platform-mxc_rnga.c
--- linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/devices/platform-mxc_rnga.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/devices/platform-mxc_rnga.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2010 Pengutronix
+ * Uwe Kleine-Koenig <u.kleine-koenig@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 <mach/hardware.h>
+#include <mach/devices-common.h>
+
+struct imx_mxc_rnga_data {
+	resource_size_t iobase;
+};
+
+#define imx_mxc_rnga_data_entry_single(soc)				\
+	{								\
+		.iobase = soc ## _RNGA_BASE_ADDR,			\
+	}
+
+#ifdef CONFIG_SOC_IMX31
+static const struct imx_mxc_rnga_data imx31_mxc_rnga_data __initconst =
+	imx_mxc_rnga_data_entry_single(MX31);
+#endif /* ifdef CONFIG_SOC_IMX31 */
+
+static struct platform_device *__init imx_add_mxc_rnga(
+		const struct imx_mxc_rnga_data *data)
+{
+	struct resource res[] = {
+		{
+			.start = data->iobase,
+			.end = data->iobase + SZ_16K - 1,
+			.flags = IORESOURCE_MEM,
+		},
+	};
+	return imx_add_platform_device("mxc_rnga", -1,
+			res, ARRAY_SIZE(res), NULL, 0);
+}
+
+static int __init imxXX_add_mxc_rnga(void)
+{
+	struct platform_device *ret;
+
+#if defined(CONFIG_SOC_IMX31)
+	if (cpu_is_mx31())
+		ret = imx_add_mxc_rnga(&imx31_mxc_rnga_data);
+	else
+#endif /* if defined(CONFIG_SOC_IMX31) */
+		ret = ERR_PTR(-ENODEV);
+
+	if (IS_ERR(ret))
+		return PTR_ERR(ret);
+
+	return 0;
+}
+arch_initcall(imxXX_add_mxc_rnga);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/devices/platform-mxc_w1.c linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/devices/platform-mxc_w1.c
--- linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/devices/platform-mxc_w1.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/devices/platform-mxc_w1.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2010 Pengutronix
+ * Uwe Kleine-Koenig <u.kleine-koenig@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 <mach/hardware.h>
+#include <mach/devices-common.h>
+
+#define imx_mxc_w1_data_entry_single(soc)				\
+	{								\
+		.iobase = soc ## _OWIRE_BASE_ADDR,			\
+	}
+
+#ifdef CONFIG_SOC_IMX21
+const struct imx_mxc_w1_data imx21_mxc_w1_data __initconst =
+	imx_mxc_w1_data_entry_single(MX21);
+#endif /* ifdef CONFIG_SOC_IMX21 */
+
+#ifdef CONFIG_SOC_IMX27
+const struct imx_mxc_w1_data imx27_mxc_w1_data __initconst =
+	imx_mxc_w1_data_entry_single(MX27);
+#endif /* ifdef CONFIG_SOC_IMX27 */
+
+#ifdef CONFIG_SOC_IMX31
+const struct imx_mxc_w1_data imx31_mxc_w1_data __initconst =
+	imx_mxc_w1_data_entry_single(MX31);
+#endif /* ifdef CONFIG_SOC_IMX31 */
+
+#ifdef CONFIG_SOC_IMX35
+const struct imx_mxc_w1_data imx35_mxc_w1_data __initconst =
+	imx_mxc_w1_data_entry_single(MX35);
+#endif /* ifdef CONFIG_SOC_IMX35 */
+
+struct platform_device *__init imx_add_mxc_w1(
+		const struct imx_mxc_w1_data *data)
+{
+	struct resource res[] = {
+		{
+			.start = data->iobase,
+			.end = data->iobase + SZ_4K - 1,
+			.flags = IORESOURCE_MEM,
+		},
+	};
+
+	return imx_add_platform_device("mxc_w1", 0,
+			res, ARRAY_SIZE(res), NULL, 0);
+}
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/devices/platform-sdhci-esdhc-imx.c linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/devices/platform-sdhci-esdhc-imx.c
--- linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/devices/platform-sdhci-esdhc-imx.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/devices/platform-sdhci-esdhc-imx.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2010 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 <mach/hardware.h>
+#include <mach/devices-common.h>
+#include <mach/esdhc.h>
+
+#define imx_sdhci_esdhc_imx_data_entry_single(soc, _id, hwid) \
+	{								\
+		.id = _id,						\
+		.iobase = soc ## _ESDHC ## hwid ## _BASE_ADDR,	\
+		.irq = soc ## _INT_ESDHC ## hwid,			\
+	}
+
+#define imx_sdhci_esdhc_imx_data_entry(soc, id, hwid)	\
+	[id] = imx_sdhci_esdhc_imx_data_entry_single(soc, id, hwid)
+
+#ifdef CONFIG_SOC_IMX25
+const struct imx_sdhci_esdhc_imx_data
+imx25_sdhci_esdhc_imx_data[] __initconst = {
+#define imx25_sdhci_esdhc_imx_data_entry(_id, _hwid)			\
+	imx_sdhci_esdhc_imx_data_entry(MX25, _id, _hwid)
+	imx25_sdhci_esdhc_imx_data_entry(0, 1),
+	imx25_sdhci_esdhc_imx_data_entry(1, 2),
+};
+#endif /* ifdef CONFIG_SOC_IMX25 */
+
+#ifdef CONFIG_SOC_IMX35
+const struct imx_sdhci_esdhc_imx_data
+imx35_sdhci_esdhc_imx_data[] __initconst = {
+#define imx35_sdhci_esdhc_imx_data_entry(_id, _hwid)			\
+	imx_sdhci_esdhc_imx_data_entry(MX35, _id, _hwid)
+	imx35_sdhci_esdhc_imx_data_entry(0, 1),
+	imx35_sdhci_esdhc_imx_data_entry(1, 2),
+	imx35_sdhci_esdhc_imx_data_entry(2, 3),
+};
+#endif /* ifdef CONFIG_SOC_IMX35 */
+
+#ifdef CONFIG_SOC_IMX51
+const struct imx_sdhci_esdhc_imx_data
+imx51_sdhci_esdhc_imx_data[] __initconst = {
+#define imx51_sdhci_esdhc_imx_data_entry(_id, _hwid)			\
+	imx_sdhci_esdhc_imx_data_entry(MX51, _id, _hwid)
+	imx51_sdhci_esdhc_imx_data_entry(0, 1),
+	imx51_sdhci_esdhc_imx_data_entry(1, 2),
+	imx51_sdhci_esdhc_imx_data_entry(2, 3),
+	imx51_sdhci_esdhc_imx_data_entry(3, 4),
+};
+#endif /* ifdef CONFIG_SOC_IMX51 */
+
+#ifdef CONFIG_SOC_IMX53
+const struct imx_sdhci_esdhc_imx_data
+imx53_sdhci_esdhc_imx_data[] __initconst = {
+#define imx53_sdhci_esdhc_imx_data_entry(_id, _hwid)			\
+	imx_sdhci_esdhc_imx_data_entry(MX53, _id, _hwid)
+	imx53_sdhci_esdhc_imx_data_entry(0, 1),
+	imx53_sdhci_esdhc_imx_data_entry(1, 2),
+	imx53_sdhci_esdhc_imx_data_entry(2, 3),
+	imx53_sdhci_esdhc_imx_data_entry(3, 4),
+};
+#endif /* ifdef CONFIG_SOC_IMX53 */
+
+struct platform_device *__init imx_add_sdhci_esdhc_imx(
+		const struct imx_sdhci_esdhc_imx_data *data,
+		const struct esdhc_platform_data *pdata)
+{
+	struct resource res[] = {
+		{
+			.start = data->iobase,
+			.end = data->iobase + SZ_16K - 1,
+			.flags = IORESOURCE_MEM,
+		}, {
+			.start = data->irq,
+			.end = data->irq,
+			.flags = IORESOURCE_IRQ,
+		},
+	};
+
+	return imx_add_platform_device("sdhci-esdhc-imx", data->id, res,
+			ARRAY_SIZE(res), pdata, sizeof(*pdata));
+}
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/devices/platform-spi_imx.c linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/devices/platform-spi_imx.c
--- linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/devices/platform-spi_imx.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/devices/platform-spi_imx.c	2011-03-14 21:20:32.000000000 -0400
@@ -30,7 +30,7 @@ const struct imx_spi_imx_data imx21_cspi
 };
 #endif
 
-#ifdef CONFIG_ARCH_MX25
+#ifdef CONFIG_SOC_IMX25
 const struct imx_spi_imx_data imx25_cspi_data[] __initconst = {
 #define imx25_cspi_data_entry(_id, _hwid)				\
 	imx_spi_imx_data_entry(MX25, CSPI, "imx25-cspi", _id, _hwid, SZ_16K)
@@ -38,7 +38,7 @@ const struct imx_spi_imx_data imx25_cspi
 	imx25_cspi_data_entry(1, 2),
 	imx25_cspi_data_entry(2, 3),
 };
-#endif /* ifdef CONFIG_ARCH_MX25 */
+#endif /* ifdef CONFIG_SOC_IMX25 */
 
 #ifdef CONFIG_SOC_IMX27
 const struct imx_spi_imx_data imx27_cspi_data[] __initconst = {
@@ -50,7 +50,7 @@ const struct imx_spi_imx_data imx27_cspi
 };
 #endif /* ifdef CONFIG_SOC_IMX27 */
 
-#ifdef CONFIG_ARCH_MX31
+#ifdef CONFIG_SOC_IMX31
 const struct imx_spi_imx_data imx31_cspi_data[] __initconst = {
 #define imx31_cspi_data_entry(_id, _hwid)				\
 	imx_spi_imx_data_entry(MX31, CSPI, "imx31-cspi", _id, _hwid, SZ_4K)
@@ -58,18 +58,18 @@ const struct imx_spi_imx_data imx31_cspi
 	imx31_cspi_data_entry(1, 2),
 	imx31_cspi_data_entry(2, 3),
 };
-#endif /* ifdef CONFIG_ARCH_MX31 */
+#endif /* ifdef CONFIG_SOC_IMX31 */
 
-#ifdef CONFIG_ARCH_MX35
+#ifdef CONFIG_SOC_IMX35
 const struct imx_spi_imx_data imx35_cspi_data[] __initconst = {
 #define imx35_cspi_data_entry(_id, _hwid)                           \
 	imx_spi_imx_data_entry(MX35, CSPI, "imx35-cspi", _id, _hwid, SZ_4K)
 	imx35_cspi_data_entry(0, 1),
 	imx35_cspi_data_entry(1, 2),
 };
-#endif /* ifdef CONFIG_ARCH_MX35 */
+#endif /* ifdef CONFIG_SOC_IMX35 */
 
-#ifdef CONFIG_ARCH_MX51
+#ifdef CONFIG_SOC_IMX51
 const struct imx_spi_imx_data imx51_cspi_data __initconst =
 	imx_spi_imx_data_entry_single(MX51, CSPI, "imx51-cspi", 0, , SZ_4K);
 
@@ -79,7 +79,19 @@ const struct imx_spi_imx_data imx51_ecsp
 	imx51_ecspi_data_entry(0, 1),
 	imx51_ecspi_data_entry(1, 2),
 };
-#endif /* ifdef CONFIG_ARCH_MX51 */
+#endif /* ifdef CONFIG_SOC_IMX51 */
+
+#ifdef CONFIG_SOC_IMX53
+const struct imx_spi_imx_data imx53_cspi_data __initconst =
+	imx_spi_imx_data_entry_single(MX53, CSPI, "imx53-cspi", 0, , SZ_4K);
+
+const struct imx_spi_imx_data imx53_ecspi_data[] __initconst = {
+#define imx53_ecspi_data_entry(_id, _hwid)				\
+	imx_spi_imx_data_entry(MX53, ECSPI, "imx53-ecspi", _id, _hwid, SZ_4K)
+	imx53_ecspi_data_entry(0, 1),
+	imx53_ecspi_data_entry(1, 2),
+};
+#endif /* ifdef CONFIG_SOC_IMX53 */
 
 struct platform_device *__init imx_add_spi_imx(
 		const struct imx_spi_imx_data *data,
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/devices.c linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/devices.c
--- linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/devices.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/devices.c	2011-03-14 21:20:32.000000000 -0400
@@ -17,6 +17,7 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/err.h>
 #include <linux/platform_device.h>
@@ -36,9 +37,10 @@ int __init mxc_register_device(struct pl
 	return ret;
 }
 
-struct platform_device *__init imx_add_platform_device(const char *name, int id,
+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)
+		const void *data, size_t size_data, u64 dmamask)
 {
 	int ret = -ENOMEM;
 	struct platform_device *pdev;
@@ -47,6 +49,23 @@ struct platform_device *__init imx_add_p
 	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)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/ehci.c linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/ehci.c
--- linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/ehci.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/ehci.c	2011-03-14 21:20:32.000000000 -0400
@@ -49,6 +49,7 @@
 
 #define MXC_OTG_OFFSET		0
 #define MXC_H1_OFFSET		0x200
+#define MXC_H2_OFFSET		0x400
 
 /* USB_CTRL */
 #define MXC_OTG_UCTRL_OWIE_BIT		(1 << 27)	/* OTG wakeup intr enable */
@@ -61,6 +62,11 @@
 #define MXC_OTG_PHYCTRL_OC_DIS_BIT	(1 << 8)	/* OTG Disable Overcurrent Event */
 #define MXC_H1_OC_DIS_BIT			(1 << 5)	/* UH1 Disable Overcurrent Event */
 
+/* USBH2CTRL */
+#define MXC_H2_UCTRL_H2UIE_BIT		(1 << 8)
+#define MXC_H2_UCTRL_H2WIE_BIT		(1 << 7)
+#define MXC_H2_UCTRL_H2PM_BIT		(1 << 4)
+
 #define MXC_USBCMD_OFFSET			0x140
 
 /* USBCMD */
@@ -69,9 +75,9 @@
 int mxc_initialize_usb_hw(int port, unsigned int flags)
 {
 	unsigned int v;
-#if defined(CONFIG_ARCH_MX25)
+#if defined(CONFIG_SOC_IMX25)
 	if (cpu_is_mx25()) {
-		v = readl(MX25_IO_ADDRESS(MX25_OTG_BASE_ADDR +
+		v = readl(MX25_IO_ADDRESS(MX25_USB_BASE_ADDR +
 				     USBCTRL_OTGBASE_OFFSET));
 
 		switch (port) {
@@ -108,14 +114,14 @@ int mxc_initialize_usb_hw(int port, unsi
 			return -EINVAL;
 		}
 
-		writel(v, MX25_IO_ADDRESS(MX25_OTG_BASE_ADDR +
+		writel(v, MX25_IO_ADDRESS(MX25_USB_BASE_ADDR +
 				     USBCTRL_OTGBASE_OFFSET));
 		return 0;
 	}
-#endif /* CONFIG_ARCH_MX25 */
+#endif /* if defined(CONFIG_SOC_IMX25) */
 #if defined(CONFIG_ARCH_MX3)
 	if (cpu_is_mx31()) {
-		v = readl(MX31_IO_ADDRESS(MX31_OTG_BASE_ADDR +
+		v = readl(MX31_IO_ADDRESS(MX31_USB_BASE_ADDR +
 				     USBCTRL_OTGBASE_OFFSET));
 
 		switch (port) {
@@ -153,13 +159,13 @@ int mxc_initialize_usb_hw(int port, unsi
 			return -EINVAL;
 		}
 
-		writel(v, MX31_IO_ADDRESS(MX31_OTG_BASE_ADDR +
+		writel(v, MX31_IO_ADDRESS(MX31_USB_BASE_ADDR +
 				     USBCTRL_OTGBASE_OFFSET));
 		return 0;
 	}
 
 	if (cpu_is_mx35()) {
-		v = readl(MX35_IO_ADDRESS(MX35_OTG_BASE_ADDR +
+		v = readl(MX35_IO_ADDRESS(MX35_USB_BASE_ADDR +
 				     USBCTRL_OTGBASE_OFFSET));
 
 		switch (port) {
@@ -196,7 +202,7 @@ int mxc_initialize_usb_hw(int port, unsi
 			return -EINVAL;
 		}
 
-		writel(v, MX35_IO_ADDRESS(MX35_OTG_BASE_ADDR +
+		writel(v, MX35_IO_ADDRESS(MX35_USB_BASE_ADDR +
 				     USBCTRL_OTGBASE_OFFSET));
 		return 0;
 	}
@@ -206,7 +212,7 @@ int mxc_initialize_usb_hw(int port, unsi
 		/* On i.MX27 we can use the i.MX31 USBCTRL bits, they
 		 * are identical
 		 */
-		v = readl(MX27_IO_ADDRESS(MX27_OTG_BASE_ADDR +
+		v = readl(MX27_IO_ADDRESS(MX27_USB_BASE_ADDR +
 				     USBCTRL_OTGBASE_OFFSET));
 		switch (port) {
 		case 0:	/* OTG port */
@@ -241,12 +247,12 @@ int mxc_initialize_usb_hw(int port, unsi
 		default:
 			return -EINVAL;
 		}
-		writel(v, MX27_IO_ADDRESS(MX27_OTG_BASE_ADDR +
+		writel(v, MX27_IO_ADDRESS(MX27_USB_BASE_ADDR +
 				     USBCTRL_OTGBASE_OFFSET));
 		return 0;
 	}
 #endif /* CONFIG_MACH_MX27 */
-#ifdef CONFIG_ARCH_MX51
+#ifdef CONFIG_SOC_IMX51
 	if (cpu_is_mx51()) {
 		void __iomem *usb_base;
 		void __iomem *usbotg_base;
@@ -254,6 +260,10 @@ int mxc_initialize_usb_hw(int port, unsi
 		int ret = 0;
 
 		usb_base = ioremap(MX51_OTG_BASE_ADDR, SZ_4K);
+		if (!usb_base) {
+			printk(KERN_ERR "%s(): ioremap failed\n", __func__);
+			return -ENOMEM;
+		}
 
 		switch (port) {
 		case 0:	/* OTG port */
@@ -262,6 +272,9 @@ int mxc_initialize_usb_hw(int port, unsi
 		case 1:	/* Host 1 port */
 			usbotg_base = usb_base + MXC_H1_OFFSET;
 			break;
+		case 2: /* Host 2 port */
+			usbotg_base = usb_base + MXC_H2_OFFSET;
+			break;
 		default:
 			printk(KERN_ERR"%s no such port %d\n", __func__, port);
 			ret = -ENOENT;
@@ -274,10 +287,13 @@ int mxc_initialize_usb_hw(int port, unsi
 			if (flags & MXC_EHCI_INTERNAL_PHY) {
 				v = __raw_readl(usbother_base + MXC_USB_PHY_CTR_FUNC_OFFSET);
 
-				if (flags & MXC_EHCI_POWER_PINS_ENABLED)
-					v |= (MXC_OTG_PHYCTRL_OC_DIS_BIT | MXC_OTG_UCTRL_OPM_BIT); /* OC/USBPWR is not used */
-				else
-					v &= ~(MXC_OTG_PHYCTRL_OC_DIS_BIT | MXC_OTG_UCTRL_OPM_BIT); /* OC/USBPWR is used */
+				if (flags & MXC_EHCI_POWER_PINS_ENABLED) {
+					/* OC/USBPWR is not used */
+					v |= MXC_OTG_PHYCTRL_OC_DIS_BIT;
+				} else {
+					/* OC/USBPWR is used */
+					v &= ~MXC_OTG_PHYCTRL_OC_DIS_BIT;
+				}
 				__raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC_OFFSET);
 
 				v = __raw_readl(usbother_base + MXC_USBCTRL_OFFSET);
@@ -285,16 +301,23 @@ int mxc_initialize_usb_hw(int port, unsi
 					v |= MXC_OTG_UCTRL_OWIE_BIT;/* OTG wakeup enable */
 				else
 					v &= ~MXC_OTG_UCTRL_OWIE_BIT;/* OTG wakeup disable */
+				if (flags & MXC_EHCI_POWER_PINS_ENABLED)
+					v |= MXC_OTG_UCTRL_OPM_BIT;
+				else
+					v &= ~MXC_OTG_UCTRL_OPM_BIT;
 				__raw_writel(v, usbother_base + MXC_USBCTRL_OFFSET);
 			}
 			break;
 		case 1:	/* Host 1 */
 			/*Host ULPI */
 			v = __raw_readl(usbother_base + MXC_USBCTRL_OFFSET);
-			if (flags & MXC_EHCI_WAKEUP_ENABLED)
-				v &= ~(MXC_H1_UCTRL_H1WIE_BIT | MXC_H1_UCTRL_H1UIE_BIT);/* HOST1 wakeup/ULPI intr disable */
-			else
-				v &= ~(MXC_H1_UCTRL_H1WIE_BIT | MXC_H1_UCTRL_H1UIE_BIT);/* HOST1 wakeup/ULPI intr disable */
+			if (flags & MXC_EHCI_WAKEUP_ENABLED) {
+				/* HOST1 wakeup/ULPI intr enable */
+				v |= (MXC_H1_UCTRL_H1WIE_BIT | MXC_H1_UCTRL_H1UIE_BIT);
+			} else {
+				/* HOST1 wakeup/ULPI intr disable */
+				v &= ~(MXC_H1_UCTRL_H1WIE_BIT | MXC_H1_UCTRL_H1UIE_BIT);
+			}
 
 			if (flags & MXC_EHCI_POWER_PINS_ENABLED)
 				v &= ~MXC_H1_UCTRL_H1PM_BIT; /* HOST1 power mask used*/
@@ -315,6 +338,22 @@ int mxc_initialize_usb_hw(int port, unsi
 				v &= MXC_UCMD_ITC_NO_THRESHOLD_MASK;
 			__raw_writel(v, usbotg_base + MXC_USBCMD_OFFSET);
 			break;
+		case 2: /* Host 2 ULPI */
+			v = __raw_readl(usbother_base + MXC_USBH2CTRL_OFFSET);
+			if (flags & MXC_EHCI_WAKEUP_ENABLED) {
+				/* HOST1 wakeup/ULPI intr enable */
+				v |= (MXC_H2_UCTRL_H2WIE_BIT | MXC_H2_UCTRL_H2UIE_BIT);
+			} else {
+				/* HOST1 wakeup/ULPI intr disable */
+				v &= ~(MXC_H2_UCTRL_H2WIE_BIT | MXC_H2_UCTRL_H2UIE_BIT);
+			}
+
+			if (flags & MXC_EHCI_POWER_PINS_ENABLED)
+				v &= ~MXC_H2_UCTRL_H2PM_BIT; /* HOST2 power mask used*/
+			else
+				v |= MXC_H2_UCTRL_H2PM_BIT; /* HOST2 power mask used*/
+			__raw_writel(v, usbother_base + MXC_USBH2CTRL_OFFSET);
+			break;
 		}
 
 error:
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/epit.c linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/epit.c
--- linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/epit.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/epit.c	2011-03-14 21:20:32.000000000 -0400
@@ -93,7 +93,6 @@ static struct clocksource clocksource_ep
 	.rating		= 200,
 	.read		= epit_read,
 	.mask		= CLOCKSOURCE_MASK(32),
-	.shift		= 20,
 	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
@@ -101,9 +100,7 @@ static int __init epit_clocksource_init(
 {
 	unsigned int c = clk_get_rate(timer_clk);
 
-	clocksource_epit.mult = clocksource_hz2mult(c,
-					clocksource_epit.shift);
-	clocksource_register(&clocksource_epit);
+	clocksource_register_hz(&clocksource_epit, c);
 
 	return 0;
 }
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/gpio.c linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/gpio.c
--- linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/gpio.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/gpio.c	2011-03-14 21:20:32.000000000 -0400
@@ -63,29 +63,29 @@ static void _set_gpio_irqenable(struct m
 	__raw_writel(l, port->base + GPIO_IMR);
 }
 
-static void gpio_ack_irq(u32 irq)
+static void gpio_ack_irq(struct irq_data *d)
 {
-	u32 gpio = irq_to_gpio(irq);
+	u32 gpio = irq_to_gpio(d->irq);
 	_clear_gpio_irqstatus(&mxc_gpio_ports[gpio / 32], gpio & 0x1f);
 }
 
-static void gpio_mask_irq(u32 irq)
+static void gpio_mask_irq(struct irq_data *d)
 {
-	u32 gpio = irq_to_gpio(irq);
+	u32 gpio = irq_to_gpio(d->irq);
 	_set_gpio_irqenable(&mxc_gpio_ports[gpio / 32], gpio & 0x1f, 0);
 }
 
-static void gpio_unmask_irq(u32 irq)
+static void gpio_unmask_irq(struct irq_data *d)
 {
-	u32 gpio = irq_to_gpio(irq);
+	u32 gpio = irq_to_gpio(d->irq);
 	_set_gpio_irqenable(&mxc_gpio_ports[gpio / 32], gpio & 0x1f, 1);
 }
 
 static int mxc_gpio_get(struct gpio_chip *chip, unsigned offset);
 
-static int gpio_set_irq_type(u32 irq, u32 type)
+static int gpio_set_irq_type(struct irq_data *d, u32 type)
 {
-	u32 gpio = irq_to_gpio(irq);
+	u32 gpio = irq_to_gpio(d->irq);
 	struct mxc_gpio_port *port = &mxc_gpio_ports[gpio / 32];
 	u32 bit, val;
 	int edge;
@@ -175,7 +175,7 @@ static void mxc_gpio_irq_handler(struct
 static void mx3_gpio_irq_handler(u32 irq, struct irq_desc *desc)
 {
 	u32 irq_stat;
-	struct mxc_gpio_port *port = (struct mxc_gpio_port *)get_irq_data(irq);
+	struct mxc_gpio_port *port = get_irq_data(irq);
 
 	irq_stat = __raw_readl(port->base + GPIO_ISR) &
 			__raw_readl(port->base + GPIO_IMR);
@@ -188,7 +188,7 @@ static void mx2_gpio_irq_handler(u32 irq
 {
 	int i;
 	u32 irq_msk, irq_stat;
-	struct mxc_gpio_port *port = (struct mxc_gpio_port *)get_irq_data(irq);
+	struct mxc_gpio_port *port = get_irq_data(irq);
 
 	/* walk through all interrupt status registers */
 	for (i = 0; i < gpio_table_size; i++) {
@@ -211,9 +211,9 @@ static void mx2_gpio_irq_handler(u32 irq
  * @param  enable       enable as wake-up if equal to non-zero
  * @return       This function returns 0 on success.
  */
-static int gpio_set_wake_irq(u32 irq, u32 enable)
+static int gpio_set_wake_irq(struct irq_data *d, u32 enable)
 {
-	u32 gpio = irq_to_gpio(irq);
+	u32 gpio = irq_to_gpio(d->irq);
 	u32 gpio_idx = gpio & 0x1F;
 	struct mxc_gpio_port *port = &mxc_gpio_ports[gpio / 32];
 
@@ -233,11 +233,11 @@ static int gpio_set_wake_irq(u32 irq, u3
 }
 
 static struct irq_chip gpio_irq_chip = {
-	.ack = gpio_ack_irq,
-	.mask = gpio_mask_irq,
-	.unmask = gpio_unmask_irq,
-	.set_type = gpio_set_irq_type,
-	.set_wake = gpio_set_wake_irq,
+	.irq_ack = gpio_ack_irq,
+	.irq_mask = gpio_mask_irq,
+	.irq_unmask = gpio_unmask_irq,
+	.irq_set_type = gpio_set_irq_type,
+	.irq_set_wake = gpio_set_wake_irq,
 };
 
 static void _set_gpio_direction(struct gpio_chip *chip, unsigned offset,
@@ -349,3 +349,113 @@ int __init mxc_gpio_init(struct mxc_gpio
 
 	return 0;
 }
+
+#define DEFINE_IMX_GPIO_PORT_IRQ_HIGH(soc, _id, _hwid, _irq, _irq_high)	\
+	{								\
+		.chip.label = "gpio-" #_id,				\
+		.irq = _irq,						\
+		.irq_high = _irq_high,					\
+		.base = soc ## _IO_ADDRESS(				\
+				soc ## _GPIO ## _hwid ## _BASE_ADDR),	\
+		.virtual_irq_start = MXC_GPIO_IRQ_START + (_id) * 32,	\
+	}
+
+#define DEFINE_IMX_GPIO_PORT_IRQ(soc, _id, _hwid, _irq)			\
+	DEFINE_IMX_GPIO_PORT_IRQ_HIGH(soc, _id, _hwid, _irq, 0)
+#define DEFINE_IMX_GPIO_PORT(soc, _id, _hwid)				\
+	DEFINE_IMX_GPIO_PORT_IRQ(soc, _id, _hwid, 0)
+
+#define DEFINE_REGISTER_FUNCTION(prefix)				\
+int __init prefix ## _register_gpios(void)				\
+{									\
+	return mxc_gpio_init(prefix ## _gpio_ports,			\
+			ARRAY_SIZE(prefix ## _gpio_ports));		\
+}
+
+#if defined(CONFIG_SOC_IMX1)
+static struct mxc_gpio_port imx1_gpio_ports[] = {
+	DEFINE_IMX_GPIO_PORT_IRQ(MX1, 0, 1, MX1_GPIO_INT_PORTA),
+	DEFINE_IMX_GPIO_PORT_IRQ(MX1, 1, 2, MX1_GPIO_INT_PORTB),
+	DEFINE_IMX_GPIO_PORT_IRQ(MX1, 2, 3, MX1_GPIO_INT_PORTC),
+	DEFINE_IMX_GPIO_PORT_IRQ(MX1, 3, 4, MX1_GPIO_INT_PORTD),
+};
+
+DEFINE_REGISTER_FUNCTION(imx1)
+
+#endif /* if defined(CONFIG_SOC_IMX1) */
+
+#if defined(CONFIG_SOC_IMX21)
+static struct mxc_gpio_port imx21_gpio_ports[] = {
+	DEFINE_IMX_GPIO_PORT_IRQ(MX21, 0, 1, MX21_INT_GPIO),
+	DEFINE_IMX_GPIO_PORT(MX21, 1, 2),
+	DEFINE_IMX_GPIO_PORT(MX21, 2, 3),
+	DEFINE_IMX_GPIO_PORT(MX21, 3, 4),
+	DEFINE_IMX_GPIO_PORT(MX21, 4, 5),
+	DEFINE_IMX_GPIO_PORT(MX21, 5, 6),
+};
+
+DEFINE_REGISTER_FUNCTION(imx21)
+
+#endif /* if defined(CONFIG_SOC_IMX21) */
+
+#if defined(CONFIG_SOC_IMX25)
+static struct mxc_gpio_port imx25_gpio_ports[] = {
+	DEFINE_IMX_GPIO_PORT_IRQ(MX25, 0, 1, MX25_INT_GPIO1),
+	DEFINE_IMX_GPIO_PORT_IRQ(MX25, 1, 2, MX25_INT_GPIO2),
+	DEFINE_IMX_GPIO_PORT_IRQ(MX25, 2, 3, MX25_INT_GPIO3),
+	DEFINE_IMX_GPIO_PORT_IRQ(MX25, 3, 4, MX25_INT_GPIO4),
+};
+
+DEFINE_REGISTER_FUNCTION(imx25)
+
+#endif /* if defined(CONFIG_SOC_IMX25) */
+
+#if defined(CONFIG_SOC_IMX27)
+static struct mxc_gpio_port imx27_gpio_ports[] = {
+	DEFINE_IMX_GPIO_PORT_IRQ(MX27, 0, 1, MX27_INT_GPIO),
+	DEFINE_IMX_GPIO_PORT(MX27, 1, 2),
+	DEFINE_IMX_GPIO_PORT(MX27, 2, 3),
+	DEFINE_IMX_GPIO_PORT(MX27, 3, 4),
+	DEFINE_IMX_GPIO_PORT(MX27, 4, 5),
+	DEFINE_IMX_GPIO_PORT(MX27, 5, 6),
+};
+
+DEFINE_REGISTER_FUNCTION(imx27)
+
+#endif /* if defined(CONFIG_SOC_IMX27) */
+
+#if defined(CONFIG_SOC_IMX31)
+static struct mxc_gpio_port imx31_gpio_ports[] = {
+	DEFINE_IMX_GPIO_PORT_IRQ(MX31, 0, 1, MX31_INT_GPIO1),
+	DEFINE_IMX_GPIO_PORT_IRQ(MX31, 1, 2, MX31_INT_GPIO2),
+	DEFINE_IMX_GPIO_PORT_IRQ(MX31, 2, 3, MX31_INT_GPIO3),
+};
+
+DEFINE_REGISTER_FUNCTION(imx31)
+
+#endif /* if defined(CONFIG_SOC_IMX31) */
+
+#if defined(CONFIG_SOC_IMX35)
+static struct mxc_gpio_port imx35_gpio_ports[] = {
+	DEFINE_IMX_GPIO_PORT_IRQ(MX35, 0, 1, MX35_INT_GPIO1),
+	DEFINE_IMX_GPIO_PORT_IRQ(MX35, 1, 2, MX35_INT_GPIO2),
+	DEFINE_IMX_GPIO_PORT_IRQ(MX35, 2, 3, MX35_INT_GPIO3),
+};
+
+DEFINE_REGISTER_FUNCTION(imx35)
+
+#endif /* if defined(CONFIG_SOC_IMX35) */
+
+#if defined(CONFIG_SOC_IMX50)
+static struct mxc_gpio_port imx50_gpio_ports[] = {
+	DEFINE_IMX_GPIO_PORT_IRQ_HIGH(MX50, 0, 1, MX50_INT_GPIO1_LOW, MX50_INT_GPIO1_HIGH),
+	DEFINE_IMX_GPIO_PORT_IRQ_HIGH(MX50, 1, 2, MX50_INT_GPIO2_LOW, MX50_INT_GPIO2_HIGH),
+	DEFINE_IMX_GPIO_PORT_IRQ_HIGH(MX50, 2, 3, MX50_INT_GPIO3_LOW, MX50_INT_GPIO3_HIGH),
+	DEFINE_IMX_GPIO_PORT_IRQ_HIGH(MX50, 3, 4, MX50_INT_GPIO3_LOW, MX50_INT_GPIO3_HIGH),
+	DEFINE_IMX_GPIO_PORT_IRQ_HIGH(MX50, 4, 5, MX50_INT_GPIO3_LOW, MX50_INT_GPIO3_HIGH),
+	DEFINE_IMX_GPIO_PORT_IRQ_HIGH(MX50, 5, 6, MX50_INT_GPIO3_LOW, MX50_INT_GPIO3_HIGH),
+};
+
+DEFINE_REGISTER_FUNCTION(imx50)
+
+#endif /* if defined(CONFIG_SOC_IMX50) */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/include/mach/common.h linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/include/mach/common.h
--- linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/include/mach/common.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/include/mach/common.h	2011-03-14 21:20:32.000000000 -0400
@@ -20,7 +20,9 @@ extern void mx25_map_io(void);
 extern void mx27_map_io(void);
 extern void mx31_map_io(void);
 extern void mx35_map_io(void);
+extern void mx50_map_io(void);
 extern void mx51_map_io(void);
+extern void mx53_map_io(void);
 extern void mxc91231_map_io(void);
 extern void mxc_init_irq(void __iomem *);
 extern void tzic_init_irq(void __iomem *);
@@ -30,7 +32,9 @@ extern void mx25_init_irq(void);
 extern void mx27_init_irq(void);
 extern void mx31_init_irq(void);
 extern void mx35_init_irq(void);
+extern void mx50_init_irq(void);
 extern void mx51_init_irq(void);
+extern void mx53_init_irq(void);
 extern void mxc91231_init_irq(void);
 extern void epit_timer_init(struct clk *timer_clk, void __iomem *base, int irq);
 extern void mxc_timer_init(struct clk *timer_clk, void __iomem *, int);
@@ -42,6 +46,8 @@ extern int mx31_clocks_init(unsigned lon
 extern int mx35_clocks_init(void);
 extern int mx51_clocks_init(unsigned long ckil, unsigned long osc,
 			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 mxc91231_clocks_init(unsigned long fref);
 extern int mxc_register_gpios(void);
 extern int mxc_register_device(struct platform_device *pdev, void *data);
@@ -50,5 +56,6 @@ extern void mxc_arch_reset_init(void __i
 extern void mxc91231_power_off(void);
 extern void mxc91231_arch_reset(int, const char *);
 extern void mxc91231_prepare_idle(void);
-
+extern void mx51_efikamx_reset(void);
+extern int mx53_revision(void);
 #endif
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/include/mach/debug-macro.S linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/include/mach/debug-macro.S
--- linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/include/mach/debug-macro.S	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/include/mach/debug-macro.S	2011-03-14 21:20:32.000000000 -0400
@@ -10,58 +10,49 @@
  * published by the Free Software Foundation.
  *
  */
-#define IMX_NEEDS_DEPRECATED_SYMBOLS
+#include <mach/hardware.h>
 
 #ifdef CONFIG_ARCH_MX1
-#include <mach/mx1.h>
-#define UART_PADDR	UART1_BASE_ADDR
-#define UART_VADDR	IO_ADDRESS(UART1_BASE_ADDR)
+#define UART_PADDR	MX1_UART1_BASE_ADDR
 #endif
 
 #ifdef CONFIG_ARCH_MX25
 #ifdef UART_PADDR
 #error "CONFIG_DEBUG_LL is incompatible with multiple archs"
 #endif
-#include <mach/mx25.h>
 #define UART_PADDR	MX25_UART1_BASE_ADDR
-#define UART_VADDR	MX25_AIPS1_IO_ADDRESS(MX25_UART1_BASE_ADDR)
 #endif
 
 #ifdef CONFIG_ARCH_MX2
 #ifdef UART_PADDR
 #error "CONFIG_DEBUG_LL is incompatible with multiple archs"
 #endif
-#include <mach/mx2x.h>
-#define UART_PADDR	UART1_BASE_ADDR
-#define UART_VADDR	AIPI_IO_ADDRESS(UART1_BASE_ADDR)
+#define UART_PADDR	MX2x_UART1_BASE_ADDR
 #endif
 
 #ifdef CONFIG_ARCH_MX3
 #ifdef UART_PADDR
 #error "CONFIG_DEBUG_LL is incompatible with multiple archs"
 #endif
-#include <mach/mx3x.h>
-#define UART_PADDR	UART1_BASE_ADDR
-#define UART_VADDR	AIPS1_IO_ADDRESS(UART1_BASE_ADDR)
+#define UART_PADDR	MX3x_UART1_BASE_ADDR
 #endif
 
 #ifdef CONFIG_ARCH_MX5
 #ifdef UART_PADDR
 #error "CONFIG_DEBUG_LL is incompatible with multiple archs"
 #endif
-#include <mach/mx51.h>
 #define UART_PADDR	MX51_UART1_BASE_ADDR
-#define UART_VADDR	MX51_AIPS1_IO_ADDRESS(MX51_UART1_BASE_ADDR)
 #endif
 
 #ifdef CONFIG_ARCH_MXC91231
 #ifdef UART_PADDR
 #error "CONFIG_DEBUG_LL is incompatible with multiple archs"
 #endif
-#include <mach/mxc91231.h>
 #define UART_PADDR	MXC91231_UART2_BASE_ADDR
-#define UART_VADDR	MXC91231_IO_ADDRESS(MXC91231_UART2_BASE_ADDR)
 #endif
+
+#define UART_VADDR	IMX_IO_ADDRESS(UART_PADDR)
+
 		.macro	addruart, rp, rv
 		ldr	\rp, =UART_PADDR	@ physical
 		ldr	\rv, =UART_VADDR	@ virtual
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/include/mach/devices-common.h linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/include/mach/devices-common.h
--- linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/include/mach/devices-common.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/include/mach/devices-common.h	2011-03-14 21:20:32.000000000 -0400
@@ -10,9 +10,19 @@
 #include <linux/platform_device.h>
 #include <linux/init.h>
 
-struct platform_device *imx_add_platform_device(const char *name, int id,
+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);
+		const void *data, size_t size_data, u64 dmamask);
+
+static inline struct platform_device *imx_add_platform_device(
+		const char *name, int id,
+		const struct resource *res, unsigned int num_resources,
+		const void *data, size_t size_data)
+{
+	return imx_add_platform_device_dmamask(
+			name, id, res, num_resources, data, size_data, 0);
+}
 
 #include <linux/fec.h>
 struct imx_fec_data {
@@ -24,15 +34,63 @@ struct platform_device *__init imx_add_f
 		const struct fec_platform_data *pdata);
 
 #include <linux/can/platform/flexcan.h>
-struct platform_device *__init imx_add_flexcan(int id,
-		resource_size_t iobase, resource_size_t iosize,
-		resource_size_t irq,
+struct imx_flexcan_data {
+	int id;
+	resource_size_t iobase;
+	resource_size_t iosize;
+	resource_size_t irq;
+};
+struct platform_device *__init imx_add_flexcan(
+		const struct imx_flexcan_data *data,
 		const struct flexcan_platform_data *pdata);
 
+#include <linux/fsl_devices.h>
+struct imx_fsl_usb2_udc_data {
+	resource_size_t iobase;
+	resource_size_t irq;
+};
+struct platform_device *__init imx_add_fsl_usb2_udc(
+		const struct imx_fsl_usb2_udc_data *data,
+		const struct fsl_usb2_platform_data *pdata);
+
 #include <linux/gpio_keys.h>
 struct platform_device *__init imx_add_gpio_keys(
 		const struct gpio_keys_platform_data *pdata);
 
+#include <mach/mx21-usbhost.h>
+struct imx_imx21_hcd_data {
+	resource_size_t iobase;
+	resource_size_t irq;
+};
+struct platform_device *__init imx_add_imx21_hcd(
+		const struct imx_imx21_hcd_data *data,
+		const struct mx21_usbh_platform_data *pdata);
+
+struct imx_imx2_wdt_data {
+	int id;
+	resource_size_t iobase;
+	resource_size_t iosize;
+};
+struct platform_device *__init imx_add_imx2_wdt(
+		const struct imx_imx2_wdt_data *data);
+
+struct imx_imxdi_rtc_data {
+	resource_size_t iobase;
+	resource_size_t irq;
+};
+struct platform_device *__init imx_add_imxdi_rtc(
+		const struct imx_imxdi_rtc_data *data);
+
+#include <mach/imxfb.h>
+struct imx_imx_fb_data {
+	resource_size_t iobase;
+	resource_size_t iosize;
+	resource_size_t irq;
+};
+struct platform_device *__init imx_add_imx_fb(
+		const struct imx_imx_fb_data *data,
+		const struct imx_fb_platform_data *pdata);
+
 #include <mach/i2c.h>
 struct imx_imx_i2c_data {
 	int id;
@@ -44,6 +102,16 @@ struct platform_device *__init imx_add_i
 		const struct imx_imx_i2c_data *data,
 		const struct imxi2c_platform_data *pdata);
 
+#include <linux/input/matrix_keypad.h>
+struct imx_imx_keypad_data {
+	resource_size_t iobase;
+	resource_size_t iosize;
+	resource_size_t irq;
+};
+struct platform_device *__init imx_add_imx_keypad(
+		const struct imx_imx_keypad_data *data,
+		const struct matrix_keymap_data *pdata);
+
 #include <mach/ssi.h>
 struct imx_imx_ssi_data {
 	int id;
@@ -82,6 +150,67 @@ struct platform_device *__init imx_add_i
 		const struct imx_imx_uart_1irq_data *data,
 		const struct imxuart_platform_data *pdata);
 
+#include <mach/usb.h>
+struct imx_imx_udc_data {
+	resource_size_t iobase;
+	resource_size_t iosize;
+	resource_size_t irq0;
+	resource_size_t irq1;
+	resource_size_t irq2;
+	resource_size_t irq3;
+	resource_size_t irq4;
+	resource_size_t irq5;
+	resource_size_t irq6;
+};
+struct platform_device *__init imx_add_imx_udc(
+		const struct imx_imx_udc_data *data,
+		const struct imxusb_platform_data *pdata);
+
+#include <mach/mx1_camera.h>
+struct imx_mx1_camera_data {
+	resource_size_t iobase;
+	resource_size_t iosize;
+	resource_size_t irq;
+};
+struct platform_device *__init imx_add_mx1_camera(
+		const struct imx_mx1_camera_data *data,
+		const struct mx1_camera_pdata *pdata);
+
+#include <mach/mx2_cam.h>
+struct imx_mx2_camera_data {
+	resource_size_t iobasecsi;
+	resource_size_t iosizecsi;
+	resource_size_t irqcsi;
+	resource_size_t iobaseemmaprp;
+	resource_size_t iosizeemmaprp;
+	resource_size_t irqemmaprp;
+};
+struct platform_device *__init imx_add_mx2_camera(
+		const struct imx_mx2_camera_data *data,
+		const struct mx2_camera_platform_data *pdata);
+
+#include <mach/mxc_ehci.h>
+struct imx_mxc_ehci_data {
+	int id;
+	resource_size_t iobase;
+	resource_size_t irq;
+};
+struct platform_device *__init imx_add_mxc_ehci(
+		const struct imx_mxc_ehci_data *data,
+		const struct mxc_usbh_platform_data *pdata);
+
+#include <mach/mmc.h>
+struct imx_mxc_mmc_data {
+	int id;
+	resource_size_t iobase;
+	resource_size_t iosize;
+	resource_size_t irq;
+	resource_size_t dmareq;
+};
+struct platform_device *__init imx_add_mxc_mmc(
+		const struct imx_mxc_mmc_data *data,
+		const struct imxmmc_platform_data *pdata);
+
 #include <mach/mxc_nand.h>
 struct imx_mxc_nand_data {
 	/*
@@ -99,24 +228,39 @@ struct platform_device *__init imx_add_m
 		const struct imx_mxc_nand_data *data,
 		const struct mxc_nand_platform_data *pdata);
 
-#include <mach/spi.h>
-struct imx_spi_imx_data {
-	const char *devid;
+struct imx_mxc_pwm_data {
 	int id;
 	resource_size_t iobase;
 	resource_size_t iosize;
-	int irq;
+	resource_size_t irq;
 };
-struct platform_device *__init imx_add_spi_imx(
-		const struct imx_spi_imx_data *data,
-		const struct spi_imx_master *pdata);
+struct platform_device *__init imx_add_mxc_pwm(
+		const struct imx_mxc_pwm_data *data);
+
+struct imx_mxc_w1_data {
+	resource_size_t iobase;
+};
+struct platform_device *__init imx_add_mxc_w1(
+		const struct imx_mxc_w1_data *data);
 
 #include <mach/esdhc.h>
-struct imx_esdhc_imx_data {
+struct imx_sdhci_esdhc_imx_data {
 	int id;
 	resource_size_t iobase;
 	resource_size_t irq;
 };
-struct platform_device *__init imx_add_esdhc(
-		const struct imx_esdhc_imx_data *data,
+struct platform_device *__init imx_add_sdhci_esdhc_imx(
+		const struct imx_sdhci_esdhc_imx_data *data,
 		const struct esdhc_platform_data *pdata);
+
+#include <mach/spi.h>
+struct imx_spi_imx_data {
+	const char *devid;
+	int id;
+	resource_size_t iobase;
+	resource_size_t iosize;
+	int irq;
+};
+struct platform_device *__init imx_add_spi_imx(
+		const struct imx_spi_imx_data *data,
+		const struct spi_imx_master *pdata);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/include/mach/entry-macro.S linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/include/mach/entry-macro.S
--- linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/include/mach/entry-macro.S	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/include/mach/entry-macro.S	2011-03-14 21:20:32.000000000 -0400
@@ -54,15 +54,15 @@
 #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
-	mov     \irqstat, #0x0D80
-1000:
-	ldr     \tmp,   [\irqstat, \base]
-	cmp     \tmp, #0
-	bne     1001f
-	addeq   \irqnr, \irqnr, #32
-	addeq   \irqstat, \irqstat, #4
+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
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/include/mach/gpio.h linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/include/mach/gpio.h
--- linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/include/mach/gpio.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/include/mach/gpio.h	2011-03-14 21:20:32.000000000 -0400
@@ -23,6 +23,11 @@
 #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
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/include/mach/hardware.h linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/include/mach/hardware.h
--- linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/include/mach/hardware.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/include/mach/hardware.h	2011-03-14 21:20:32.000000000 -0400
@@ -22,13 +22,92 @@
 
 #include <asm/sizes.h>
 
-#define IMX_IO_ADDRESS(addr, module)					\
-	((void __force __iomem *)					\
-	 (((unsigned long)((addr) - (module ## _BASE_ADDR)) < module ## _SIZE) ?\
-	 (addr) - (module ## _BASE_ADDR) + (module ## _BASE_ADDR_VIRT) : 0))
+#ifdef __ASSEMBLER__
+#define IOMEM(addr)	(addr)
+#else
+#define IOMEM(addr)	((void __force __iomem *)(addr))
+#endif
+
+#define IMX_IO_P2V_MODULE(addr, module)					\
+	(((addr) - module ## _BASE_ADDR) < module ## _SIZE ?		\
+	 (addr) - (module ## _BASE_ADDR) + (module ## _BASE_ADDR_VIRT) : 0)
+
+/*
+ * This is rather complicated for humans and ugly to verify, but for a machine
+ * it's OK.  Still more as it is usually only applied to constants.  The upsides
+ * on using this approach are:
+ *
+ *  - same mapping on all i.MX machines
+ *  - works for assembler, too
+ *  - no need to nurture #defines for virtual addresses
+ *
+ * The downside it, it's hard to verify (but I have a script for that).
+ *
+ * Obviously this needs to be injective for each SoC.  In general it maps the
+ * whole address space to [0xf4000000, 0xf5ffffff].  So [0xf6000000,0xfeffffff]
+ * is free for per-machine use (e.g. KZM_ARM11_01 uses 64MiB there).
+ *
+ * It applies the following mappings for the different SoCs:
+ *
+ * mx1:
+ *	IO	0x00200000+0x100000	->	0xf4000000+0x100000
+ * mx21:
+ *	AIPI	0x10000000+0x100000	->	0xf4400000+0x100000
+ *	SAHB1	0x80000000+0x100000	->	0xf4000000+0x100000
+ *	X_MEMC	0xdf000000+0x004000	->	0xf5f00000+0x004000
+ * mx25:
+ *	AIPS1	0x43f00000+0x100000	->	0xf5300000+0x100000
+ *	AIPS2	0x53f00000+0x100000	->	0xf5700000+0x100000
+ *	AVIC	0x68000000+0x100000	->	0xf5800000+0x100000
+ * mx27:
+ *	AIPI	0x10000000+0x100000	->	0xf4400000+0x100000
+ *	SAHB1	0x80000000+0x100000	->	0xf4000000+0x100000
+ *	X_MEMC	0xd8000000+0x100000	->	0xf5c00000+0x100000
+ * mx31:
+ *	AIPS1	0x43f00000+0x100000	->	0xf5300000+0x100000
+ *	AIPS2	0x53f00000+0x100000	->	0xf5700000+0x100000
+ *	AVIC	0x68000000+0x100000	->	0xf5800000+0x100000
+ *	X_MEMC	0xb8000000+0x010000	->	0xf4c00000+0x010000
+ *	SPBA0	0x50000000+0x100000	->	0xf5400000+0x100000
+ * mx35:
+ *	AIPS1	0x43f00000+0x100000	->	0xf5300000+0x100000
+ *	AIPS2	0x53f00000+0x100000	->	0xf5700000+0x100000
+ *	AVIC	0x68000000+0x100000	->	0xf5800000+0x100000
+ *	X_MEMC	0xb8000000+0x010000	->	0xf4c00000+0x010000
+ *	SPBA0	0x50000000+0x100000	->	0xf5400000+0x100000
+ * mx50:
+ *	TZIC	0x0fffc000+0x004000	->	0xf4bfc000+0x004000
+ *	SPBA0	0x50000000+0x100000	->	0xf5400000+0x100000
+ *	AIPS1	0x53f00000+0x100000	->	0xf5700000+0x100000
+ *	AIPS2	0x63f00000+0x100000	->	0xf5300000+0x100000
+ * mx51:
+ *	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
+ * mxc91231:
+ *	L2CC	0x30000000+0x010000	->	0xf4400000+0x010000
+ *	X_MEMC	0xb8000000+0x010000	->	0xf4c00000+0x010000
+ *	ROMP	0x60000000+0x010000	->	0xf5000000+0x010000
+ *	AVIC	0x68000000+0x010000	->	0xf5800000+0x010000
+ *	AIPS1	0x43f00000+0x100000	->	0xf5300000+0x100000
+ *	SPBA0	0x50000000+0x100000	->	0xf5400000+0x100000
+ *	SPBA1	0x52000000+0x100000	->	0xf5600000+0x100000
+ *	AIPS2	0x53f00000+0x100000	->	0xf5700000+0x100000
+ */
+#define IMX_IO_P2V(x)	(						\
+			0xf4000000 +					\
+			(((x) & 0x50000000) >> 6) +			\
+			(((x) & 0x0b000000) >> 4) +			\
+			(((x) & 0x000fffff)))
+
+#define IMX_IO_ADDRESS(x)	IOMEM(IMX_IO_P2V(x))
 
 #ifdef CONFIG_ARCH_MX5
+#include <mach/mx50.h>
 #include <mach/mx51.h>
+#include <mach/mx53.h>
 #endif
 
 #ifdef CONFIG_ARCH_MX3
@@ -61,4 +140,11 @@
 
 #include <mach/mxc.h>
 
+#define imx_map_entry(soc, name, _type)	{				\
+	.virtual = soc ## _IO_P2V(soc ## _ ## name ## _BASE_ADDR),	\
+	.pfn = __phys_to_pfn(soc ## _ ## name ## _BASE_ADDR),		\
+	.length = soc ## _ ## name ## _SIZE,				\
+	.type = _type,							\
+}
+
 #endif /* __ASM_ARCH_MXC_HARDWARE_H__ */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/include/mach/imxfb.h linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/include/mach/imxfb.h
--- linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/include/mach/imxfb.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/include/mach/imxfb.h	2011-03-14 21:20:32.000000000 -0400
@@ -1,6 +1,8 @@
 /*
  * This structure describes the machine which we are running on.
  */
+#ifndef __MACH_IMXFB_H__
+#define __MACH_IMXFB_H__
 
 #include <linux/fb.h>
 
@@ -79,3 +81,4 @@ struct imx_fb_platform_data {
 };
 
 void set_imx_fb_info(struct imx_fb_platform_data *);
+#endif /* ifndef __MACH_IMXFB_H__ */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/include/mach/iomux-mx50.h linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/include/mach/iomux-mx50.h
--- linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/include/mach/iomux-mx50.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/include/mach/iomux-mx50.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,977 @@
+/*
+ * 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.
+ */
+
+#ifndef __MACH_IOMUX_MX50_H__
+#define __MACH_IOMUX_MX50_H__
+
+#include <mach/iomux-v3.h>
+
+#define MX50_ELCDIF_PAD_CTRL	(PAD_CTL_PKE | PAD_CTL_DSE_HIGH)
+
+#define MX50_SD_PAD_CTRL	(PAD_CTL_HYS | PAD_CTL_PKE | PAD_CTL_PUE | \
+					PAD_CTL_PUS_47K_UP | PAD_CTL_DSE_HIGH)
+
+#define MX50_UART_PAD_CTRL	(PAD_CTL_DSE_HIGH | PAD_CTL_PKE)
+
+#define MX50_I2C_PAD_CTRL	(PAD_CTL_ODE | PAD_CTL_DSE_HIGH | \
+					PAD_CTL_PUS_100K_UP | PAD_CTL_HYS)
+
+#define MX50_USB_PAD_CTRL	(PAD_CTL_PKE | PAD_CTL_PUE | \
+					PAD_CTL_DSE_HIGH | PAD_CTL_PUS_47K_UP)
+
+#define MX50_FEC_PAD_CTRL	(PAD_CTL_HYS | PAD_CTL_PKE | PAD_CTL_PUE | \
+					PAD_CTL_PUS_22K_UP | PAD_CTL_ODE | \
+					PAD_CTL_DSE_HIGH)
+
+#define MX50_OWIRE_PAD_CTRL	(PAD_CTL_HYS | PAD_CTL_PKE | PAD_CTL_PUE | \
+					PAD_CTL_PUS_100K_UP | PAD_CTL_ODE | \
+					PAD_CTL_DSE_HIGH | PAD_CTL_SRE_FAST)
+
+#define MX50_KEYPAD_CTRL        (PAD_CTL_HYS | PAD_CTL_PKE | PAD_CTL_PUE | \
+					PAD_CTL_PUS_100K_UP | PAD_CTL_DSE_HIGH)
+
+#define MX50_CSPI_SS_PAD	(PAD_CTL_PKE | PAD_CTL_PUE | \
+					PAD_CTL_PUS_22K_UP | PAD_CTL_DSE_HIGH)
+
+#define MX50_PAD_KEY_COL0__KEY_COL0	IOMUX_PAD(0x2CC, 0x20, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_KEY_COL0__GPIO_4_0	IOMUX_PAD(0x2CC, 0x20, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_KEY_COL0__NANDF_CLE	IOMUX_PAD(0x2CC, 0x20, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
+
+#define MX50_PAD_KEY_ROW0__KEY_ROW0	IOMUX_PAD(0x2D0, 0x24, 0, 0x0, 0, MX50_KEYPAD_CTRL)
+#define MX50_PAD_KEY_ROW0__GPIO_4_1	IOMUX_PAD(0x2D0, 0x24, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_KEY_ROW0__NANDF_ALE	IOMUX_PAD(0x2D0, 0x24, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
+
+#define MX50_PAD_KEY_COL1__KEY_COL1	IOMUX_PAD(0x2D4, 0x28, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_KEY_COL1__GPIO_4_2	IOMUX_PAD(0x2D4, 0x28, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_KEY_COL1__NANDF_CE0	IOMUX_PAD(0x2D4, 0x28, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
+
+#define MX50_PAD_KEY_ROW1__KEY_ROW1	IOMUX_PAD(0x2D8, 0x2C, 0, 0x0, 0, MX50_KEYPAD_CTRL)
+#define MX50_PAD_KEY_ROW1__GPIO_4_3	IOMUX_PAD(0x2D8, 0x2C, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_KEY_ROW1__NANDF_CE1	IOMUX_PAD(0x2D8, 0x2C, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
+
+#define MX50_PAD_KEY_COL2__KEY_COL2	IOMUX_PAD(0x2DC, 0x30, 0, 0x0, 0, MX50_KEYPAD_CTRL)
+#define MX50_PAD_KEY_COL2__GPIO_4_4	IOMUX_PAD(0x2DC, 0x30, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_KEY_COL2__NANDF_CE2	IOMUX_PAD(0x2DC, 0x30, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
+
+#define MX50_PAD_KEY_ROW2__KEY_ROW2	IOMUX_PAD(0x2E0, 0x34, 0, 0x0, 0, MX50_KEYPAD_CTRL)
+#define MX50_PAD_KEY_ROW2__GPIO_4_5	IOMUX_PAD(0x2E0, 0x34, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_KEY_ROW2__NANDF_CE3	IOMUX_PAD(0x2E0, 0x34, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
+
+#define MX50_PAD_KEY_COL3__KEY_COL3	IOMUX_PAD(0x2E4, 0x38, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_KEY_COL3__GPIO_4_6	IOMUX_PAD(0x2E4, 0x38, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_KEY_COL3__NANDF_READY	IOMUX_PAD(0x2E4, 0x38, 2, 0x7b4, 0, PAD_CTL_PKE | \
+							PAD_CTL_PUE | PAD_CTL_PUS_100K_UP)
+#define MX50_PAD_KEY_COL3__SDMA_EXT0	IOMUX_PAD(0x2E4, 0x38, 6, 0x7b8, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_KEY_ROW3__KEY_ROW3	IOMUX_PAD(0x2E8, 0x3C, 0, 0x0, 0, MX50_KEYPAD_CTRL)
+#define MX50_PAD_KEY_ROW3__GPIO_4_7	IOMUX_PAD(0x2E8, 0x3C, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_KEY_ROW3__NANDF_DQS	IOMUX_PAD(0x2E8, 0x3C, 2, 0x7b0, 0, PAD_CTL_DSE_HIGH)
+#define MX50_PAD_KEY_ROW3__SDMA_EXT1	IOMUX_PAD(0x2E8, 0x3C, 6, 0x7bc, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_I2C1_SCL__I2C1_SCL	IOMUX_PAD(0x2EC, 0x40, IOMUX_CONFIG_SION, 0x0, 0, \
+							MX50_I2C_PAD_CTRL)
+#define MX50_PAD_I2C1_SCL__GPIO_6_18	IOMUX_PAD(0x2EC, 0x40, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_I2C1_SCL__UART2_TXD	IOMUX_PAD(0x2EC, 0x40, 2, 0x7cc, 0, MX50_UART_PAD_CTRL)
+
+#define MX50_PAD_I2C1_SDA__I2C1_SDA	IOMUX_PAD(0x2F0, 0x44, IOMUX_CONFIG_SION, 0x0, 0, \
+							MX50_I2C_PAD_CTRL)
+#define MX50_PAD_I2C1_SDA__GPIO_6_19	IOMUX_PAD(0x2F0, 0x44, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_I2C1_SDA__UART2_RXD	IOMUX_PAD(0x2F0, 0x44, 2, 0x7cc, 1, MX50_UART_PAD_CTRL)
+
+#define MX50_PAD_I2C2_SCL__I2C2_SCL	IOMUX_PAD(0x2F4, 0x48, IOMUX_CONFIG_SION, 0x0, 0, \
+							MX50_I2C_PAD_CTRL)
+#define MX50_PAD_I2C2_SCL__GPIO_6_20	IOMUX_PAD(0x2F4, 0x48, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_I2C2_SCL__UART2_CTS	IOMUX_PAD(0x2F4, 0x48, 2, 0x7c8, 0, MX50_UART_PAD_CTRL)
+#define MX50_PAD_I2C2_SCL__DCDC_OK	IOMUX_PAD(0x2F4, 0x48, 7, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_I2C2_SDA__I2C2_SDA	IOMUX_PAD(0x2F8, 0x4C, IOMUX_CONFIG_SION, 0x0, 0, \
+							MX50_I2C_PAD_CTRL)
+#define MX50_PAD_I2C2_SDA__GPIO_6_21	IOMUX_PAD(0x2F8, 0x4C, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_I2C2_SDA__UART2_RTS	IOMUX_PAD(0x2F8, 0x4C, 2, 0x7c8, 1, MX50_UART_PAD_CTRL)
+#define MX50_PAD_I2C2_SDA__PWRSTABLE	IOMUX_PAD(0x2F8, 0x4C, 7, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_I2C3_SCL__I2C3_SCL	IOMUX_PAD(0x2FC, 0x50, IOMUX_CONFIG_SION, 0x0, 0, \
+							MX50_I2C_PAD_CTRL)
+#define MX50_PAD_I2C3_SCL__GPIO_6_22	IOMUX_PAD(0x2FC, 0x50, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_I2C3_SCL__FEC_MDC	IOMUX_PAD(0x2FC, 0x50, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
+#define MX50_PAD_I2C3_SCL__PMIC_RDY	IOMUX_PAD(0x2FC, 0x50, 3, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_I2C3_SCL__GPT_CAPIN1	IOMUX_PAD(0x2FC, 0x50, 5, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_I2C3_SCL__USBOTG_OC	IOMUX_PAD(0x2FC, 0x50, 7, 0x7E8, 0, MX50_USB_PAD_CTRL)
+
+#define MX50_PAD_I2C3_SDA__I2C3_SDA	IOMUX_PAD(0x300, 0x54, IOMUX_CONFIG_SION, 0x0, 0, \
+								MX50_I2C_PAD_CTRL)
+#define MX50_PAD_I2C3_SDA__GPIO_6_23	IOMUX_PAD(0x300, 0x54, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_I2C3_SDA__FEC_MDIO	IOMUX_PAD(0x300, 0x54, 2, 0x774, 0, MX50_FEC_PAD_CTRL)
+#define MX50_PAD_I2C3_SDA__PWRFAIL_INT	IOMUX_PAD(0x300, 0x54, 3, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_I2C3_SDA__ALARM_DEB	IOMUX_PAD(0x300, 0x54, 4, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_I2C3_SDA__GPT_CAPIN1	IOMUX_PAD(0x300, 0x54, 5, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_I2C3_SDA__USBOTG_PWR	IOMUX_PAD(0x300, 0x54, 7, 0x0, 0, \
+							PAD_CTL_PKE | PAD_CTL_DSE_HIGH)
+
+#define MX50_PAD_PWM1__PWM1_PWMO	IOMUX_PAD(0x304, 0x58, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_PWM1__GPIO_6_24	IOMUX_PAD(0x304, 0x58, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_PWM1__USBOTG_OC	IOMUX_PAD(0x304, 0x58, 2, 0x7E8, 1, MX50_USB_PAD_CTRL)
+#define MX50_PAD_PWM1__GPT_CMPOUT1	IOMUX_PAD(0x304, 0x58, 5, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_PWM2__PWM2_PWMO	IOMUX_PAD(0x308, 0x5C, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_PWM2__GPIO_6_25	IOMUX_PAD(0x308, 0x5C, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_PWM2__USBOTG_PWR	IOMUX_PAD(0x308, 0x5C, 2, 0x0, 0, \
+							PAD_CTL_PKE | PAD_CTL_DSE_HIGH)
+#define MX50_PAD_PWM2__DCDC_PWM		IOMUX_PAD(0x308, 0x5C, 4, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_PWM2__GPT_CMPOUT2	IOMUX_PAD(0x308, 0x5C, 5, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_PWM2__ANY_PU_RST	IOMUX_PAD(0x308, 0x5C, 7, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_OWIRE__OWIRE		IOMUX_PAD(0x30C, 0x60, 0, 0x0, 0, MX50_OWIRE_PAD_CTRL)
+#define MX50_PAD_OWIRE__GPIO_6_26	IOMUX_PAD(0x30C, 0x60, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_OWIRE__USBH1_OC	IOMUX_PAD(0x30C, 0x60, 2, 0x0, 0, MX50_USB_PAD_CTRL)
+#define MX50_PAD_OWIRE__SSI_EXT1_CLK	IOMUX_PAD(0x30C, 0x60, 3, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_OWIRE__EPDC_PWRIRQ	IOMUX_PAD(0x30C, 0x60, 4, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_OWIRE__GPT_CMPOUT3	IOMUX_PAD(0x30C, 0x60, 5, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_EPITO__EPITO		IOMUX_PAD(0x310, 0x64, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPITO__GPIO_6_27	IOMUX_PAD(0x310, 0x64, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPITO__USBH1_PWR	IOMUX_PAD(0x310, 0x64, 2, 0x0, 0, \
+							PAD_CTL_PKE | PAD_CTL_DSE_HIGH)
+#define MX50_PAD_EPITO__SSI_EXT2_CLK	IOMUX_PAD(0x310, 0x64, 3, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPITO__TOG_EN		IOMUX_PAD(0x310, 0x64, 4, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPITO__GPT_CLKIN	IOMUX_PAD(0x310, 0x64, 5, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_WDOG__WDOG		IOMUX_PAD(0x314, 0x68, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_WDOG__GPIO_6_28	IOMUX_PAD(0x314, 0x68, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_WDOG__WDOG_RST		IOMUX_PAD(0x314, 0x68, 2, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_WDOG__XTAL32K		IOMUX_PAD(0x314, 0x68, 6, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_SSI_TXFS__SSI_TXFS	IOMUX_PAD(0x318, 0x6C, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_SSI_TXFS__GPIO_6_0	IOMUX_PAD(0x318, 0x6C, 1, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_SSI_TXC__SSI_TXC	IOMUX_PAD(0x31C, 0x70, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_SSI_TXC__GPIO_6_1	IOMUX_PAD(0x31C, 0x70, 1, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_SSI_TXD__SSI_TXD	IOMUX_PAD(0x320, 0x74, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_SSI_TXD__GPIO_6_2	IOMUX_PAD(0x320, 0x74, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_SSI_TXD__CSPI_RDY	IOMUX_PAD(0x320, 0x74, 4, 0x6e8, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_SSI_RXD__SSI_RXD	IOMUX_PAD(0x324, 0x78, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_SSI_RXD__GPIO_6_3	IOMUX_PAD(0x324, 0x78, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_SSI_RXD__CSPI_SS3	IOMUX_PAD(0x324, 0x78, 4, 0x6f4, 0, MX50_CSPI_SS_PAD)
+
+#define MX50_PAD_SSI_RXFS__AUD3_RXFS	IOMUX_PAD(0x328, 0x7C, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_SSI_RXFS__GPIO_6_4	IOMUX_PAD(0x328, 0x7C, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_SSI_RXFS__UART5_TXD	IOMUX_PAD(0x328, 0x7C, 2, 0x7e4, 0, MX50_UART_PAD_CTRL)
+#define MX50_PAD_SSI_RXFS__WEIM_D6	IOMUX_PAD(0x328, 0x7C, 3, 0x804, 0, NO_PAD_CTRL)
+#define MX50_PAD_SSI_RXFS__CSPI_SS2	IOMUX_PAD(0x328, 0x7C, 4, 0x6f0, 0, MX50_CSPI_SS_PAD)
+#define MX50_PAD_SSI_RXFS__FEC_COL	IOMUX_PAD(0x328, 0x7C, 5, 0x770, 0, PAD_CTL_DSE_HIGH)
+#define MX50_PAD_SSI_RXFS__FEC_MDC	IOMUX_PAD(0x328, 0x7C, 6, 0x0, 0, PAD_CTL_DSE_HIGH)
+
+#define MX50_PAD_SSI_RXC__AUD3_RXC	IOMUX_PAD(0x32C, 0x80, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_SSI_RXC__GPIO_6_5	IOMUX_PAD(0x32C, 0x80, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_SSI_RXC__UART5_RXD	IOMUX_PAD(0x32C, 0x80, 2, 0x7e4, 1, MX50_UART_PAD_CTRL)
+#define MX50_PAD_SSI_RXC__WEIM_D7	IOMUX_PAD(0x32C, 0x80, 3, 0x808, 0, NO_PAD_CTRL)
+#define MX50_PAD_SSI_RXC__CSPI_SS1	IOMUX_PAD(0x32C, 0x80, 4, 0x6ec, 0, MX50_CSPI_SS_PAD)
+#define MX50_PAD_SSI_RXC__FEC_RX_CLK	IOMUX_PAD(0x32C, 0x80, 5, 0x780, 0, NO_PAD_CTRL)
+#define MX50_PAD_SSI_RXC__FEC_MDIO	IOMUX_PAD(0x32C, 0x80, 6, 0x774, 1, MX50_FEC_PAD_CTRL)
+
+#define MX50_PAD_UART1_TXD__UART1_TXD	IOMUX_PAD(0x330, 0x84, 0, 0x7c4, 0, MX50_UART_PAD_CTRL)
+#define MX50_PAD_UART1_TXD__GPIO_6_6	IOMUX_PAD(0x330, 0x84, 1, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_UART1_RXD__UART1_RXD	IOMUX_PAD(0x334, 0x88, 0, 0x7c4, 1, MX50_UART_PAD_CTRL)
+#define MX50_PAD_UART1_RXD__GPIO_6_7	IOMUX_PAD(0x334, 0x88, 1, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_UART1_CTS__UART1_CTS	IOMUX_PAD(0x338, 0x8C, 0, 0x7c0, 0, MX50_UART_PAD_CTRL)
+#define MX50_PAD_UART1_CTS__GPIO_6_8	IOMUX_PAD(0x338, 0x8C, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_UART1_CTS__UART5_TXD	IOMUX_PAD(0x338, 0x8C, 2, 0x7e4, 2, MX50_UART_PAD_CTRL)
+#define MX50_PAD_UART1_CTS__SD4_D4	IOMUX_PAD(0x338, 0x8C, 4, 0x760, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_UART1_CTS__SD4_CMD	IOMUX_PAD(0x338, 0x8C, 5, 0x74c, 0, MX50_SD_PAD_CTRL)
+
+#define MX50_PAD_UART1_RTS__UART1_RTS	IOMUX_PAD(0x33C, 0x90, 0, 0x7c0, 1, MX50_UART_PAD_CTRL)
+#define MX50_PAD_UART1_RTS__GPIO_6_9	IOMUX_PAD(0x33C, 0x90, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_UART1_RTS__UART5_RXD	IOMUX_PAD(0x33C, 0x90, 2, 0x7e4, 3, MX50_UART_PAD_CTRL)
+#define MX50_PAD_UART1_RTS__SD4_D5	IOMUX_PAD(0x33C, 0x90, 4, 0x0, 1, MX50_SD_PAD_CTRL)
+#define MX50_PAD_UART1_RTS__SD4_CLK	IOMUX_PAD(0x33C, 0x90, 5, 0x0, 1, MX50_SD_PAD_CTRL)
+
+#define MX50_PAD_UART2_TXD__UART2_TXD	IOMUX_PAD(0x340, 0x94, 0, 0x7cc, 2, MX50_UART_PAD_CTRL)
+#define MX50_PAD_UART2_TXD__GPIO_6_10	IOMUX_PAD(0x340, 0x94, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_UART2_TXD__SD4_D6	IOMUX_PAD(0x340, 0x94, 4, 0x768, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_UART2_TXD__SD4_D4	IOMUX_PAD(0x340, 0x94, 5, 0x760, 1, MX50_SD_PAD_CTRL)
+
+#define MX50_PAD_UART2_RXD__UART2_RXD	IOMUX_PAD(0x344, 0x98, 0, 0x7cc, 3, MX50_UART_PAD_CTRL)
+#define MX50_PAD_UART2_RXD__GPIO_6_11	IOMUX_PAD(0x344, 0x98, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_UART2_RXD__SD4_D7	IOMUX_PAD(0x344, 0x98, 4, 0x76c, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_UART2_RXD__SD4_D5	IOMUX_PAD(0x344, 0x98, 5, 0x764, 1, MX50_SD_PAD_CTRL)
+
+#define MX50_PAD_UART2_CTS__UART2_CTS	IOMUX_PAD(0x348, 0x9C, 0, 0x7c8, 2, MX50_UART_PAD_CTRL)
+#define MX50_PAD_UART2_CTS__GPIO_6_12	IOMUX_PAD(0x348, 0x9C, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_UART2_CTS__SD4_CMD	IOMUX_PAD(0x348, 0x9C, 4, 0x74c, 1, MX50_SD_PAD_CTRL)
+#define MX50_PAD_UART2_CTS__SD4_D6	IOMUX_PAD(0x348, 0x9C, 5, 0x768, 1, MX50_SD_PAD_CTRL)
+
+#define MX50_PAD_UART2_RTS__UART2_RTS	IOMUX_PAD(0x34C, 0xA0, 0, 0x7c8, 3, MX50_UART_PAD_CTRL)
+#define MX50_PAD_UART2_RTS__GPIO_6_13	IOMUX_PAD(0x34C, 0xA0, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_UART2_RTS__SD4_CLK	IOMUX_PAD(0x34C, 0xA0, 4, 0x748, 1, MX50_SD_PAD_CTRL)
+#define MX50_PAD_UART2_RTS__SD4_D7	IOMUX_PAD(0x34C, 0xA0, 5, 0x76c, 1, MX50_SD_PAD_CTRL)
+
+#define MX50_PAD_UART3_TXD__UART3_TXD	IOMUX_PAD(0x350, 0xA4, 0, 0x7d4, 0, MX50_UART_PAD_CTRL)
+#define MX50_PAD_UART3_TXD__GPIO_6_14	IOMUX_PAD(0x350, 0xA4, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_UART3_TXD__SD1_D4	IOMUX_PAD(0x350, 0xA4, 3, 0x0, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_UART3_TXD__SD4_D0	IOMUX_PAD(0x350, 0xA4, 4, 0x750, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_UART3_TXD__SD2_WP	IOMUX_PAD(0x350, 0xA4, 5, 0x744, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_UART3_TXD__WEIM_D12	IOMUX_PAD(0x350, 0xA4, 6, 0x81c, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_UART3_RXD__UART3_RXD	IOMUX_PAD(0x354, 0xA8, 0, 0x7d4, 1, MX50_UART_PAD_CTRL)
+#define MX50_PAD_UART3_RXD__GPIO_6_15	IOMUX_PAD(0x354, 0xA8, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_UART3_RXD__SD1_D5	IOMUX_PAD(0x354, 0xA8, 3, 0x0, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_UART3_RXD__SD4_D1	IOMUX_PAD(0x354, 0xA8, 4, 0x754, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_UART3_RXD__SD2_CD	IOMUX_PAD(0x354, 0xA8, 5, 0x740, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_UART3_RXD__WEIM_D13	IOMUX_PAD(0x354, 0xA8, 6, 0x820, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_UART4_TXD__UART4_TXD	IOMUX_PAD(0x358, 0xAC, 0, 0x7dc, 0, MX50_UART_PAD_CTRL)
+#define MX50_PAD_UART4_TXD__GPIO_6_16	IOMUX_PAD(0x358, 0xAC, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_UART4_TXD__UART3_CTS	IOMUX_PAD(0x358, 0xAC, 2, 0x7d0, 0, MX50_UART_PAD_CTRL)
+#define MX50_PAD_UART4_TXD__SD1_D6	IOMUX_PAD(0x358, 0xAC, 3, 0x0, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_UART4_TXD__SD4_D2	IOMUX_PAD(0x358, 0xAC, 4, 0x758, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_UART4_TXD__SD2_LCTL	IOMUX_PAD(0x358, 0xAC, 5, 0x0, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_UART4_TXD__WEIM_D14	IOMUX_PAD(0x358, 0xAC, 6, 0x824, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_UART4_RXD__UART4_RXD	IOMUX_PAD(0x35C, 0xB0, 0, 0x7dc, 1, MX50_UART_PAD_CTRL)
+#define MX50_PAD_UART4_RXD__GPIO_6_17	IOMUX_PAD(0x35C, 0xB0, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_UART4_RXD__UART3_RTS	IOMUX_PAD(0x35C, 0xB0, 2, 0x7d0, 1, MX50_UART_PAD_CTRL)
+#define MX50_PAD_UART4_RXD__SD1_D7	IOMUX_PAD(0x35C, 0xB0, 3, 0x0, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_UART4_RXD__SD4_D3	IOMUX_PAD(0x35C, 0xB0, 4, 0x75c, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_UART4_RXD__SD1_LCTL	IOMUX_PAD(0x35C, 0xB0, 5, 0x0, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_UART4_RXD__WEIM_D15	IOMUX_PAD(0x35C, 0xB0, 6, 0x828, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_CSPI_SCLK__CSPI_SCLK	IOMUX_PAD(0x360, 0xB4, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_CSPI_SCLK__GPIO_4_8	IOMUX_PAD(0x360, 0xB4, 1, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_CSPI_MOSI__CSPI_MOSI	IOMUX_PAD(0x364, 0xB8, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_CSPI_MOSI__GPIO_4_9	IOMUX_PAD(0x364, 0xB8, 1, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_CSPI_MISO__CSPI_MISO	IOMUX_PAD(0x368, 0xBC, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_CSPI_MISO__GPIO_4_10	IOMUX_PAD(0x368, 0xBC, 1, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_CSPI_SS0__CSPI_SS0	IOMUX_PAD(0x36C, 0xC0, 0, 0x0, 0, MX50_CSPI_SS_PAD)
+#define MX50_PAD_CSPI_SS0__GPIO_4_11	IOMUX_PAD(0x36C, 0xC0, 1, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_ECSPI1_SCLK__ECSPI1_SCLK	IOMUX_PAD(0x370, 0xC4, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_ECSPI1_SCLK__GPIO_4_12		IOMUX_PAD(0x370, 0xC4, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_ECSPI1_SCLK__CSPI_RDY		IOMUX_PAD(0x370, 0xC4, 2, 0x6e8, 1, NO_PAD_CTRL)
+#define MX50_PAD_ECSPI1_SCLK__ECSPI2_RDY	IOMUX_PAD(0x370, 0xC4, 3, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_ECSPI1_SCLK__UART3_RTS		IOMUX_PAD(0x370, 0xC4, 4, 0x7d0, 2, MX50_UART_PAD_CTRL)
+#define MX50_PAD_ECSPI1_SCLK__EPDC_SDCE6	IOMUX_PAD(0x370, 0xC4, 5, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_ECSPI1_SCLK__WEIM_D8		IOMUX_PAD(0x370, 0xC4, 7, 0x80c, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_ECSPI1_MOSI__ECSPI1_MOSI	IOMUX_PAD(0x374, 0xC8, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_ECSPI1_MOSI__GPIO_4_13		IOMUX_PAD(0x374, 0xC8, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_ECSPI1_MOSI__CSPI_SS1		IOMUX_PAD(0x374, 0xC8, 2, 0x6ec, 1, MX50_CSPI_SS_PAD)
+#define MX50_PAD_ECSPI1_MOSI__ECSPI2_SS1	IOMUX_PAD(0x374, 0xC8, 3, 0x0, 0, MX50_CSPI_SS_PAD)
+#define MX50_PAD_ECSPI1_MOSI__UART3_CTS		IOMUX_PAD(0x374, 0xC8, 4, 0x7d0, 3, MX50_UART_PAD_CTRL)
+#define MX50_PAD_ECSPI1_MOSI__EPDC_SDCE7	IOMUX_PAD(0x374, 0xC8, 5, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_ECSPI1_MOSI__WEIM_D9		IOMUX_PAD(0x374, 0xC8, 7, 0x810, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_ECSPI1_MISO__ECSPI1_MISO	IOMUX_PAD(0x378, 0xCC, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_ECSPI1_MISO__GPIO_4_14		IOMUX_PAD(0x378, 0xCC, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_ECSPI1_MISO__CSPI_SS2		IOMUX_PAD(0x378, 0xCC, 2, 0x6f0, 1, MX50_CSPI_SS_PAD)
+#define MX50_PAD_ECSPI1_MISO__ECSPI2_SS2	IOMUX_PAD(0x378, 0xCC, 3, 0x0, 0, MX50_CSPI_SS_PAD)
+#define MX50_PAD_ECSPI1_MISO__UART4_RTS		IOMUX_PAD(0x378, 0xCC, 4, 0x7d8, 0, MX50_UART_PAD_CTRL)
+#define MX50_PAD_ECSPI1_MISO__EPDC_SDCE8	IOMUX_PAD(0x378, 0xCC, 5, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_ECSPI1_MISO__WEIM_D10		IOMUX_PAD(0x378, 0xCC, 7, 0x814, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_ECSPI1_SS0__ECSPI1_SS0		IOMUX_PAD(0x37C, 0xD0, 0, 0x0, 0, MX50_CSPI_SS_PAD)
+#define MX50_PAD_ECSPI1_SS0__GPIO_4_15		IOMUX_PAD(0x37C, 0xD0, 1, 0x0, 0, PAD_CTL_PUS_100K_UP)
+#define MX50_PAD_ECSPI1_SS0__CSPI_SS3		IOMUX_PAD(0x37C, 0xD0, 2, 0x6f4, 1, MX50_CSPI_SS_PAD)
+#define MX50_PAD_ECSPI1_SS0__ECSPI2_SS3		IOMUX_PAD(0x37C, 0xD0, 3, 0x0, 0, MX50_CSPI_SS_PAD)
+#define MX50_PAD_ECSPI1_SS0__UART4_CTS		IOMUX_PAD(0x37C, 0xD0, 4, 0x7d8, 1, MX50_UART_PAD_CTRL)
+#define MX50_PAD_ECSPI1_SS0__EPDC_SDCE9		IOMUX_PAD(0x37C, 0xD0, 5, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_ECSPI1_SS0__WEIM_D11		IOMUX_PAD(0x37C, 0xD0, 7, 0x818, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_ECSPI2_SCLK__ECSPI2_SCLK	IOMUX_PAD(0x380, 0xD4, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_ECSPI2_SCLK__GPIO_4_16		IOMUX_PAD(0x380, 0xD4, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_ECSPI2_SCLK__ELCDIF_WR		IOMUX_PAD(0x380, 0xD4, 2, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_ECSPI2_SCLK__ECSPI1_RDY	IOMUX_PAD(0x380, 0xD4, 3, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_ECSPI2_SCLK__UART5_RTS		IOMUX_PAD(0x380, 0xD4, 4, 0x7e0, 0, MX50_UART_PAD_CTRL)
+#define MX50_PAD_ECSPI2_SCLK__ELCDIF_DOTCLK	IOMUX_PAD(0x380, 0xD4, 5, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_ECSPI2_SCLK__NANDF_CEN4	IOMUX_PAD(0x380, 0xD4, 6, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_ECSPI2_SCLK__WEIM_D8		IOMUX_PAD(0x380, 0xD4, 7, 0x80c, 1, NO_PAD_CTRL)
+
+#define MX50_PAD_ECSPI2_MOSI__ECSPI2_MOSI	IOMUX_PAD(0x384, 0xD8, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_ECSPI2_MOSI__GPIO_4_17		IOMUX_PAD(0x384, 0xD8, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_ECSPI2_MOSI__ELCDIF_RD		IOMUX_PAD(0x384, 0xD8, 2, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_ECSPI2_MOSI__ECSPI1_SS1	IOMUX_PAD(0x384, 0xD8, 3, 0x0, 0, MX50_CSPI_SS_PAD)
+#define MX50_PAD_ECSPI2_MOSI__UART5_CTS		IOMUX_PAD(0x384, 0xD8, 4, 0x7e0, 1, MX50_UART_PAD_CTRL)
+#define MX50_PAD_ECSPI2_MOSI__ELCDIF_EN		IOMUX_PAD(0x384, 0xD8, 5, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_ECSPI2_MOSI__NANDF_CEN5	IOMUX_PAD(0x384, 0xD8, 6, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_ECSPI2_MOSI__WEIM_D9		IOMUX_PAD(0x384, 0xD8, 7, 0x810, 1, NO_PAD_CTRL)
+
+#define MX50_PAD_ECSPI2_MISO__ECSPI2_MISO	IOMUX_PAD(0x388, 0xDC, 0, 0x73c, 0, NO_PAD_CTRL)
+#define MX50_PAD_ECSPI2_MISO__GPIO_4_18		IOMUX_PAD(0x388, 0xDC, 1, 0x0, 0, PAD_CTL_PUS_100K_UP)
+#define MX50_PAD_ECSPI2_MISO__ELCDIF_RS		IOMUX_PAD(0x388, 0xDC, 2, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_ECSPI2_MISO__ECSPI1_SS2	IOMUX_PAD(0x388, 0xDC, 3, 0x0, 0, MX50_CSPI_SS_PAD)
+#define MX50_PAD_ECSPI2_MISO__UART5_TXD		IOMUX_PAD(0x388, 0xDC, 4, 0x7e4, 4, MX50_UART_PAD_CTRL)
+#define MX50_PAD_ECSPI2_MISO__ELCDIF_VSYNC	IOMUX_PAD(0x388, 0xDC, 5, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_ECSPI2_MISO__NANDF_CEN6	IOMUX_PAD(0x388, 0xDC, 6, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_ECSPI2_MISO__WEIM_D10		IOMUX_PAD(0x388, 0xDC, 7, 0x814, 1, NO_PAD_CTRL)
+
+#define MX50_PAD_ECSPI2_SS0__ECSPI2_SS0		IOMUX_PAD(0x38C, 0xE0, 0, 0x0, 0, MX50_CSPI_SS_PAD)
+#define MX50_PAD_ECSPI2_SS0__GPIO_4_19		IOMUX_PAD(0x38C, 0xE0, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_ECSPI2_SS0__ELCDIF_CS		IOMUX_PAD(0x38C, 0xE0, 2, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_ECSPI2_SS0__ECSPI1_SS3		IOMUX_PAD(0x38C, 0xE0, 3, 0x0, 0, MX50_CSPI_SS_PAD)
+#define MX50_PAD_ECSPI2_SS0__UART5_RXD		IOMUX_PAD(0x38C, 0xE0, 4, 0x7e4, 5, MX50_UART_PAD_CTRL)
+#define MX50_PAD_ECSPI2_SS0__ELCDIF_HSYNC	IOMUX_PAD(0x38C, 0xE0, 5, 0x6f8, 0, NO_PAD_CTRL)
+#define MX50_PAD_ECSPI2_SS0__NANDF_CEN7		IOMUX_PAD(0x38C, 0xE0, 6, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_ECSPI2_SS0__WEIM_D11		IOMUX_PAD(0x38C, 0xE0, 7, 0x818, 1, NO_PAD_CTRL)
+
+#define MX50_PAD_SD1_CLK__SD1_CLK	IOMUX_PAD(0x390, 0xE4, IOMUX_CONFIG_SION, 0x0, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_SD1_CLK__GPIO_5_0	IOMUX_PAD(0x390, 0xE4, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_SD1_CLK__CLKO		IOMUX_PAD(0x390, 0xE4, 7, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_SD1_CMD__SD1_CMD	IOMUX_PAD(0x394, 0xE8, IOMUX_CONFIG_SION, 0x0, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_SD1_CMD__GPIO_5_1	IOMUX_PAD(0x394, 0xE8, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_SD1_CMD__CLKO2		IOMUX_PAD(0x394, 0xE8, 7, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_SD1_D0__SD1_D0		IOMUX_PAD(0x398, 0xEC, 0, 0x0, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_SD1_D0__GPIO_5_2	IOMUX_PAD(0x398, 0xEC, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_SD1_D0__PLL1_BYP	IOMUX_PAD(0x398, 0xEC, 7, 0x6dc, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_SD1_D1__SD1_D1		IOMUX_PAD(0x39C, 0xF0, 0, 0x0, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_SD1_D1__GPIO_5_3	IOMUX_PAD(0x39C, 0xF0, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_SD1_D1__PLL2_BYP	IOMUX_PAD(0x39C, 0xF0, 7, 0x6e0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_SD1_D2__SD1_D2		IOMUX_PAD(0x3A0, 0xF4, 0, 0x0, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_SD1_D2__GPIO_5_4	IOMUX_PAD(0x3A0, 0xF4, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_SD1_D2__PLL3_BYP	IOMUX_PAD(0x3A0, 0xF4, 7, 0x6e4, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_SD1_D3__SD1_D3		IOMUX_PAD(0x3A4, 0xF8, 0, 0x0, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_SD1_D3__GPIO_5_5	IOMUX_PAD(0x3A4, 0xF8, 1, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_SD2_CLK__SD2_CLK	IOMUX_PAD(0x3A8, 0xFC, IOMUX_CONFIG_SION, 0x0, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_SD2_CLK__GPIO_5_6	IOMUX_PAD(0x3A8, 0xFC, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_SD2_CLK__MSHC_SCLK	IOMUX_PAD(0x3A8, 0xFC, 2, 0x0, 0, MX50_SD_PAD_CTRL)
+
+#define MX50_PAD_SD2_CMD__SD2_CMD	IOMUX_PAD(0x3AC, 0x100, IOMUX_CONFIG_SION, 0x0, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_SD2_CMD__GPIO_5_7	IOMUX_PAD(0x3AC, 0x100, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_SD2_CMD__MSHC_BS	IOMUX_PAD(0x3AC, 0x100, 2, 0x0, 0, MX50_SD_PAD_CTRL)
+
+#define MX50_PAD_SD2_D0__SD2_D0		IOMUX_PAD(0x3B0, 0x104, 0, 0x0, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_SD2_D0__GPIO_5_8	IOMUX_PAD(0x3B0, 0x104, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_SD2_D0__MSHC_D0	IOMUX_PAD(0x3B0, 0x104, 2, 0x0, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_SD2_D0__KEY_COL4	IOMUX_PAD(0x3B0, 0x104, 3, 0x790, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_SD2_D1__SD2_D1		IOMUX_PAD(0x3B4, 0x108, 0, 0x0, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_SD2_D1__GPIO_5_9	IOMUX_PAD(0x3B4, 0x108, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_SD2_D1__MSHC_D1	IOMUX_PAD(0x3B4, 0x108, 2, 0x0, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_SD2_D1__KEY_ROW4	IOMUX_PAD(0x3B4, 0x108, 3, 0x7a0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_SD2_D2__SD2_D2		IOMUX_PAD(0x3B8, 0x10C, 0, 0x0, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_SD2_D2__GPIO_5_10	IOMUX_PAD(0x3B8, 0x10C, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_SD2_D2__MSHC_D2	IOMUX_PAD(0x3B8, 0x10C, 2, 0x0, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_SD2_D2__KEY_COL5	IOMUX_PAD(0x3B8, 0x10C, 3, 0x794, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_SD2_D3__SD2_D3		IOMUX_PAD(0x3BC, 0x110, 0, 0x0, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_SD2_D3__GPIO_5_11	IOMUX_PAD(0x3BC, 0x110, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_SD2_D3__MSHC_D3	IOMUX_PAD(0x3BC, 0x110, 2, 0x0, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_SD2_D3__KEY_ROW5	IOMUX_PAD(0x3BC, 0x110, 3, 0x7a4, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_SD2_D4__SD2_D4		IOMUX_PAD(0x3C0, 0x114, 0, 0x0, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_SD2_D4__GPIO_5_12	IOMUX_PAD(0x3C0, 0x114, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_SD2_D4__AUD4_RXFS	IOMUX_PAD(0x3C0, 0x114, 2, 0x6d0, 0, NO_PAD_CTRL)
+#define MX50_PAD_SD2_D4__KEY_COL6	IOMUX_PAD(0x3C0, 0x114, 3, 0x798, 0, NO_PAD_CTRL)
+#define MX50_PAD_SD2_D4__WEIM_D0	IOMUX_PAD(0x3C0, 0x114, 4, 0x7ec, 0, NO_PAD_CTRL)
+#define MX50_PAD_SD2_D4__CCM_OUT0	IOMUX_PAD(0x3C0, 0x114, 7, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_SD2_D5__SD2_D5		IOMUX_PAD(0x3C4, 0x118, 0, 0x0, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_SD2_D5__GPIO_5_13	IOMUX_PAD(0x3C4, 0x118, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_SD2_D5__AUD4_RXC	IOMUX_PAD(0x3C4, 0x118, 2, 0x6cc, 0, NO_PAD_CTRL)
+#define MX50_PAD_SD2_D5__KEY_ROW6	IOMUX_PAD(0x3C4, 0x118, 3, 0x7a8, 0, NO_PAD_CTRL)
+#define MX50_PAD_SD2_D5__WEIM_D1	IOMUX_PAD(0x3C4, 0x118, 4, 0x7f0, 0, NO_PAD_CTRL)
+#define MX50_PAD_SD2_D5__CCM_OUT1	IOMUX_PAD(0x3C4, 0x118, 7, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_SD2_D6__SD2_D6		IOMUX_PAD(0x3C8, 0x11C, 0, 0x0, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_SD2_D6__GPIO_5_14	IOMUX_PAD(0x3C8, 0x11C, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_SD2_D6__AUD4_RXD	IOMUX_PAD(0x3C8, 0x11C, 2, 0x6c4, 0, NO_PAD_CTRL)
+#define MX50_PAD_SD2_D6__KEY_COL7	IOMUX_PAD(0x3C8, 0x11C, 3, 0x79c, 0, NO_PAD_CTRL)
+#define MX50_PAD_SD2_D6__WEIM_D2	IOMUX_PAD(0x3C8, 0x11C, 4, 0x7f4, 0, NO_PAD_CTRL)
+#define MX50_PAD_SD2_D6__CCM_OUT2	IOMUX_PAD(0x3C8, 0x11C, 7, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_SD2_D7__SD2_D7		IOMUX_PAD(0x3CC, 0x120, 0, 0x0, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_SD2_D7__GPIO_5_15	IOMUX_PAD(0x3CC, 0x120, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_SD2_D7__AUD4_TXFS	IOMUX_PAD(0x3CC, 0x120, 2, 0x6d8, 0, NO_PAD_CTRL)
+#define MX50_PAD_SD2_D7__KEY_ROW7	IOMUX_PAD(0x3CC, 0x120, 3, 0x7ac, 0, NO_PAD_CTRL)
+#define MX50_PAD_SD2_D7__WEIM_D3	IOMUX_PAD(0x3CC, 0x120, 4, 0x7f8, 0, NO_PAD_CTRL)
+#define MX50_PAD_SD2_D7__CCM_STOP	IOMUX_PAD(0x3CC, 0x120, 7, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_SD2_WP__SD2_WP		IOMUX_PAD(0x3D0, 0x124, 0, 0x744, 1, MX50_SD_PAD_CTRL)
+#define MX50_PAD_SD2_WP__GPIO_5_16	IOMUX_PAD(0x3D0, 0x124, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_SD2_WP__AUD4_TXD	IOMUX_PAD(0x3D0, 0x124, 2, 0x6c8, 0, NO_PAD_CTRL)
+#define MX50_PAD_SD2_WP__WEIM_D4	IOMUX_PAD(0x3D0, 0x124, 4, 0x7fc, 0, NO_PAD_CTRL)
+#define MX50_PAD_SD2_WP__CCM_WAIT	IOMUX_PAD(0x3D0, 0x124, 7, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_SD2_CD__SD2_CD		IOMUX_PAD(0x3D4, 0x128, 0, 0x740, 1, MX50_SD_PAD_CTRL)
+#define MX50_PAD_SD2_CD__GPIO_5_17	IOMUX_PAD(0x3D4, 0x128, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_SD2_CD__AUD4_TXC	IOMUX_PAD(0x3D4, 0x128, 2, 0x6d4, 0, NO_PAD_CTRL)
+#define MX50_PAD_SD2_CD__WEIM_D5	IOMUX_PAD(0x3D4, 0x128, 4, 0x800, 0, NO_PAD_CTRL)
+#define MX50_PAD_SD2_CD__CCM_REF_EN	IOMUX_PAD(0x3D4, 0x128, 7, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_PMIC_ON_REQ__PMIC_ON_REQ	IOMUX_PAD(0x3D8, 0, 0, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_PMIC_STBY_REQ__PMIC_STBY_REQ	IOMUX_PAD(0x3DC, 0, 0, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_PMIC_PORT_B__PMIC_PORT_B	IOMUX_PAD(0x3E0, 0, 0, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_PMIC_BOOT_MODE1__PMIC_BOOT_MODE1	IOMUX_PAD(0x3E4, 0, 0, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_PMIC_RESET_IN_B__PMIC_RESET_IN_B	IOMUX_PAD(0x3E8, 0, 0, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_PMIC_BOOT_MODE0__PMIC_BOOT_MODE0	IOMUX_PAD(0x3EC, 0, 0, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_PMIC_TEST_MODE__PMIC_TEST_MODE	IOMUX_PAD(0x3F0, 0, 0, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_PMIC_JTAG_TMS__PMIC_JTAG_TMS	IOMUX_PAD(0x3F4, 0, 0, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_PMIC_JTAG_MOD__PMIC_JTAG_MOD	IOMUX_PAD(0x3F8, 0, 0, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_PMIC_JTAG_TRSTB__PMIC_JTAG_TRSTB	IOMUX_PAD(0x3FC, 0, 0, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_PMIC_JTAG_TDI__PMIC_JTAG_TDI	IOMUX_PAD(0x400, 0, 0, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_PMIC_JTAG_TCK__PMIC_JTAG_TCK	IOMUX_PAD(0x404, 0, 0, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_PMIC_JTAG_TDO__PMIC_JTAG_TDO	IOMUX_PAD(0x408, 0, 0, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_DISP_D0__DISP_D0	IOMUX_PAD(0x40C, 0x12C, 0, 0x6fc, 0, MX50_ELCDIF_PAD_CTRL)
+#define MX50_PAD_DISP_D0__GPIO_2_0	IOMUX_PAD(0x40C, 0x12C, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_DISP_D0__FEC_TXCLK	IOMUX_PAD(0x40C, 0x12C, 2, 0x78c, 0, PAD_CTL_HYS | PAD_CTL_PKE)
+
+#define MX50_PAD_DISP_D1__DISP_D1	IOMUX_PAD(0x410, 0x130, 0, 0x700, 0, MX50_ELCDIF_PAD_CTRL)
+#define MX50_PAD_DISP_D1__GPIO_2_1	IOMUX_PAD(0x410, 0x130, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_DISP_D1__FEC_RX_ER	IOMUX_PAD(0x410, 0x130, 2, 0x788, 0, PAD_CTL_HYS | PAD_CTL_PKE)
+#define MX50_PAD_DISP_D1__WEIM_A17	IOMUX_PAD(0x410, 0x130, 3, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_DISP_D2__DISP_D2	IOMUX_PAD(0x414, 0x134, 0, 0x704, 0, MX50_ELCDIF_PAD_CTRL)
+#define MX50_PAD_DISP_D2__GPIO_2_2	IOMUX_PAD(0x414, 0x134, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_DISP_D2__FEC_RX_DV	IOMUX_PAD(0x414, 0x134, 2, 0x784, 0, PAD_CTL_HYS | PAD_CTL_PKE)
+#define MX50_PAD_DISP_D2__WEIM_A18	IOMUX_PAD(0x414, 0x134, 3, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_DISP_D3__DISP_D3	IOMUX_PAD(0x418, 0x138, 0, 0x708, 0, MX50_ELCDIF_PAD_CTRL)
+#define MX50_PAD_DISP_D3__GPIO_2_3	IOMUX_PAD(0x418, 0x138, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_DISP_D3__FEC_RXD1	IOMUX_PAD(0x418, 0x138, 2, 0x77C, 0, PAD_CTL_HYS | PAD_CTL_PKE)
+#define MX50_PAD_DISP_D3__WEIM_A19	IOMUX_PAD(0x418, 0x138, 3, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_DISP_D3__FEC_COL	IOMUX_PAD(0x418, 0x138, 4, 0x770, 1, NO_PAD_CTRL)
+
+#define MX50_PAD_DISP_D4__DISP_D4	IOMUX_PAD(0x41C, 0x13C, 0, 0x70c, 0, MX50_ELCDIF_PAD_CTRL)
+#define MX50_PAD_DISP_D4__GPIO_2_4	IOMUX_PAD(0x41C, 0x13C, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_DISP_D4__FEC_RXD0	IOMUX_PAD(0x41C, 0x13C, 2, 0x778, 0, PAD_CTL_HYS | PAD_CTL_PKE)
+#define MX50_PAD_DISP_D4__WEIM_A20	IOMUX_PAD(0x41C, 0x13C, 3, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_DISP_D5__DISP_D5	IOMUX_PAD(0x420, 0x140, 0, 0x710, 0, MX50_ELCDIF_PAD_CTRL)
+#define MX50_PAD_DISP_D5__GPIO_2_5	IOMUX_PAD(0x420, 0x140, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_DISP_D5__FEC_TX_EN	IOMUX_PAD(0x420, 0x140, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
+#define MX50_PAD_DISP_D5__WEIM_A21	IOMUX_PAD(0x420, 0x140, 3, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_DISP_D6__DISP_D6	IOMUX_PAD(0x424, 0x144, 0, 0x714, 0, MX50_ELCDIF_PAD_CTRL)
+#define MX50_PAD_DISP_D6__GPIO_2_6	IOMUX_PAD(0x424, 0x144, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_DISP_D6__FEC_TXD1	IOMUX_PAD(0x424, 0x144, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
+#define MX50_PAD_DISP_D6__WEIM_A22	IOMUX_PAD(0x424, 0x144, 3, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_DISP_D6__FEC_RX_CLK	IOMUX_PAD(0x424, 0x144, 4, 0x780, 1, NO_PAD_CTRL)
+
+#define MX50_PAD_DISP_D7__DISP_D7	IOMUX_PAD(0x428, 0x148, 0, 0x718, 0, MX50_ELCDIF_PAD_CTRL)
+#define MX50_PAD_DISP_D7__GPIO_2_7	IOMUX_PAD(0x428, 0x148, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_DISP_D7__FEC_TXD0	IOMUX_PAD(0x428, 0x148, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
+#define MX50_PAD_DISP_D7__WEIM_A23	IOMUX_PAD(0x428, 0x148, 3, 0x0, 0, NO_PAD_CTRL)
+
+
+#define MX50_PAD_DISP_WR__ELCDIF_WR	IOMUX_PAD(0x42C, 0x14C, 0, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
+#define MX50_PAD_DISP_WR__GPIO_2_16	IOMUX_PAD(0x42C, 0x14C, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_DISP_WR__ELCDIF_PIXCLK	IOMUX_PAD(0x42C, 0x14C, 2, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
+#define MX50_PAD_DISP_WR__WEIM_A24	IOMUX_PAD(0x42C, 0x14C, 3, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_DISP_RD__ELCDIF_RD	IOMUX_PAD(0x430, 0x150, 0, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
+#define MX50_PAD_DISP_RD__GPIO_2_19	IOMUX_PAD(0x430, 0x150, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_DISP_RD__ELCDIF_EN	IOMUX_PAD(0x430, 0x150, 2, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
+#define MX50_PAD_DISP_RD__WEIM_A25	IOMUX_PAD(0x430, 0x150, 3, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_DISP_RS__ELCDIF_RS	IOMUX_PAD(0x434, 0x154, 0, 0x73c, 1, MX50_ELCDIF_PAD_CTRL)
+#define MX50_PAD_DISP_RS__GPIO_2_17	IOMUX_PAD(0x434, 0x154, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_DISP_RS__ELCDIF_VSYNC	IOMUX_PAD(0x434, 0x154, 2, 0x73c, 1, MX50_ELCDIF_PAD_CTRL)
+#define MX50_PAD_DISP_RS__WEIM_A26	IOMUX_PAD(0x434, 0x154, 3, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_DISP_CS__ELCDIF_CS	IOMUX_PAD(0x438, 0x158, 0, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
+#define MX50_PAD_DISP_CS__GPIO_2_21	IOMUX_PAD(0x438, 0x158, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_DISP_CS__ELCDIF_HSYNC	IOMUX_PAD(0x438, 0x158, 2, 0x6f8, 1, MX50_ELCDIF_PAD_CTRL)
+#define MX50_PAD_DISP_CS__WEIM_A27	IOMUX_PAD(0x438, 0x158, 3, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_DISP_CS__WEIM_CS3	IOMUX_PAD(0x438, 0x158, 4, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_DISP_BUSY__ELCDIF_HSYNC	IOMUX_PAD(0x43C, 0x15C, 0, 0x6f8, 2, MX50_ELCDIF_PAD_CTRL)
+#define MX50_PAD_DISP_BUSY__GPIO_2_18		IOMUX_PAD(0x43C, 0x15C, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_DISP_BUSY__WEIM_CS3		IOMUX_PAD(0x43C, 0x15C, 3, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_DISP_RESET__ELCDIF_RST	IOMUX_PAD(0x440, 0x160, 0, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
+#define MX50_PAD_DISP_RESET__GPIO_2_20	IOMUX_PAD(0x440, 0x160, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_DISP_RESET__WEIM_CS3	IOMUX_PAD(0x440, 0x160, 4, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_SD3_CMD__SD3_CMD	IOMUX_PAD(0x444, 0x164, 0, 0x0, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_SD3_CMD__GPIO_5_18	IOMUX_PAD(0x444, 0x164, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PIN_SD3_CMD__NANDF_WRN	IOMUX_PAD(0x444, 0x164, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
+#define MX50_PAD_SD3_CMD__SSP_CMD	IOMUX_PAD(0x444, 0x164, 3, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_SD3_CLK__SD3_CLK	IOMUX_PAD(0x448, 0x168, 0, 0x0, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_SD3_CLK__GPIO_5_19	IOMUX_PAD(0x448, 0x168, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PIN_SD3_CLK__NANDF_RDN	IOMUX_PAD(0x448, 0x168, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
+#define MX50_PAD_SD3_CLK__SSP_CLK	IOMUX_PAD(0x448, 0x168, 3, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_SD3_D0__SD3_D0		IOMUX_PAD(0x44C, 0x16C, 0, 0x0, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_SD3_D0__GPIO_5_20	IOMUX_PAD(0x44C, 0x16C, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PIN_SD3_D0__NANDF_D4	IOMUX_PAD(0x44C, 0x16C, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
+#define MX50_PAD_SD3_D0__SSP_D0		IOMUX_PAD(0x44C, 0x16C, 3, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_SD3_D0__PLL1_BYP	IOMUX_PAD(0x44C, 0x16C, 7, 0x6dc, 1, NO_PAD_CTRL)
+
+#define MX50_PAD_SD3_D1__SD3_D1		IOMUX_PAD(0x450, 0x170, 0, 0x0, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_SD3_D1__GPIO_5_21	IOMUX_PAD(0x450, 0x170, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PIN_SD3_D1__NANDF_D5	IOMUX_PAD(0x450, 0x170, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
+#define MX50_PAD_SD3_D1__PLL2_BYP	IOMUX_PAD(0x450, 0x170, 7, 0x6e0, 1, NO_PAD_CTRL)
+
+#define MX50_PAD_SD3_D2__SD3_D2		IOMUX_PAD(0x454, 0x174, 0, 0x0, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_SD3_D2__GPIO_5_22	IOMUX_PAD(0x454, 0x174, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PIN_SD3_D2__NANDF_D6	IOMUX_PAD(0x454, 0x174, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
+#define MX50_PAD_SD3_D2__SSP_D2		IOMUX_PAD(0x454, 0x174, 3, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_SD3_D2__PLL3_BYP	IOMUX_PAD(0x454, 0x174, 7, 0x6e4, 1, NO_PAD_CTRL)
+
+#define MX50_PAD_SD3_D3__SD3_D3		IOMUX_PAD(0x458, 0x178, 0, 0x0, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_SD3_D3__GPIO_5_23	IOMUX_PAD(0x458, 0x178, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PIN_SD3_D3__NANDF_D7	IOMUX_PAD(0x458, 0x178, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
+#define MX50_PAD_SD3_D3__SSP_D3		IOMUX_PAD(0x458, 0x178, 3, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_SD3_D4__SD3_D4		IOMUX_PAD(0x45C, 0x17C, 0, 0x0, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_SD3_D4__GPIO_5_24	IOMUX_PAD(0x45C, 0x17C, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PIN_SD3_D4__NANDF_D0	IOMUX_PAD(0x45C, 0x17C, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
+#define MX50_PAD_SD3_D4__SSP_D4		IOMUX_PAD(0x45C, 0x17C, 1, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_SD3_D5__SD3_D5		IOMUX_PAD(0x460, 0x180, 0, 0x0, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_SD3_D5__GPIO_5_25	IOMUX_PAD(0x460, 0x180, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PIN_SD3_D5__NANDF_D1	IOMUX_PAD(0x460, 0x180, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
+#define MX50_PAD_SD3_D5__SSP_D5		IOMUX_PAD(0x460, 0x180, 3, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_SD3_D6__SD3_D6		IOMUX_PAD(0x464, 0x184, 0, 0x0, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_SD3_D6__GPIO_5_26	IOMUX_PAD(0x464, 0x184, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PIN_SD3_D6__NANDF_D2	IOMUX_PAD(0x464, 0x184, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
+#define MX50_PAD_SD3_D6__SSP_D6		IOMUX_PAD(0x464, 0x184, 3, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_SD3_D7__SD3_D7		IOMUX_PAD(0x468, 0x188, 0, 0x0, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_SD3_D7__GPIO_5_27	IOMUX_PAD(0x468, 0x188, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PIN_SD3_D7__NANDF_D3	IOMUX_PAD(0x468, 0x188, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
+#define MX50_PAD_SD3_D7__SSP_D7		IOMUX_PAD(0x468, 0x188, 3, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_SD3_WP__SD3_WP		IOMUX_PAD(0x46C, 0x18C, 0, 0x0, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_SD3_WP__GPIO_5_28	IOMUX_PAD(0x46C, 0x18C, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PIN_SD3_WP__NANDF_RESETN	IOMUX_PAD(0x46C, 0x18C, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
+#define MX50_PAD_SD3_WP__SSP_CD		IOMUX_PAD(0x46C, 0x18C, 3, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_SD3_WP__SD4_LCTL	IOMUX_PAD(0x46C, 0x18C, 4, 0x0, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_SD3_WP__WEIM_CS3	IOMUX_PAD(0x46C, 0x18C, 5, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_DISP_D8__DISP_D8	IOMUX_PAD(0x470, 0x190, 0, 0x71c, 0, MX50_ELCDIF_PAD_CTRL)
+#define MX50_PAD_DISP_D8__GPIO_2_8	IOMUX_PAD(0x470, 0x190, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_DISP_D8__NANDF_CLE	IOMUX_PAD(0x470, 0x190, 2, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_DISP_D8__SD1_LCTL	IOMUX_PAD(0x470, 0x190, 3, 0x0, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_DISP_D8__SD4_CMD	IOMUX_PAD(0x470, 0x190, 4, 0x74c, 2, MX50_SD_PAD_CTRL)
+#define MX50_PAD_DISP_D8__KEY_COL4	IOMUX_PAD(0x470, 0x190, 5, 0x790, 1, NO_PAD_CTRL)
+#define MX50_PAD_DISP_D8__FEC_TX_CLK	IOMUX_PAD(0x470, 0x190, 6, 0x78c, 1, NO_PAD_CTRL)
+
+#define MX50_PAD_DISP_D9__DISP_D9	IOMUX_PAD(0x474, 0x194, 0, 0x720, 0, MX50_ELCDIF_PAD_CTRL)
+#define MX50_PAD_DISP_D9__GPIO_2_9	IOMUX_PAD(0x474, 0x194, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_DISP_D9__NANDF_ALE	IOMUX_PAD(0x474, 0x194, 2, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_DISP_D9__SD2_LCTL	IOMUX_PAD(0x474, 0x194, 3, 0x0, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_DISP_D9__SD4_CLK	IOMUX_PAD(0x474, 0x194, 4, 0x748, 2, MX50_SD_PAD_CTRL)
+#define MX50_PAD_DISP_D9__KEY_ROW4	IOMUX_PAD(0x474, 0x194, 5, 0x7a0, 1, NO_PAD_CTRL)
+#define MX50_PAD_DISP_D9__FEC_RX_ER	IOMUX_PAD(0x474, 0x194, 6, 0x788, 1, NO_PAD_CTRL)
+
+#define MX50_PAD_DISP_D10__DISP_D10	IOMUX_PAD(0x478, 0x198, 0, 0x724, 0, MX50_ELCDIF_PAD_CTRL)
+#define MX50_PAD_DISP_D10__GPIO_2_10	IOMUX_PAD(0x478, 0x198, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_DISP_D10__NANDF_CEN0	IOMUX_PAD(0x478, 0x198, 2, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_DISP_D10__SD3_LCTL	IOMUX_PAD(0x478, 0x198, 3, 0x0, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_DISP_D10__SD4_D0	IOMUX_PAD(0x478, 0x198, 4, 0x750, 1, MX50_SD_PAD_CTRL)
+#define MX50_PAD_DISP_D10__KEY_COL5	IOMUX_PAD(0x478, 0x198, 5, 0x794, 1, NO_PAD_CTRL)
+#define MX50_PAD_DISP_D10__FEC_RX_DV	IOMUX_PAD(0x478, 0x198, 6, 0x784, 1, NO_PAD_CTRL)
+
+#define MX50_PAD_DISP_D11__DISP_D11	IOMUX_PAD(0x47C, 0x19C, 0, 0x728, 0, MX50_ELCDIF_PAD_CTRL)
+#define MX50_PAD_DISP_D11__GPIO_2_11	IOMUX_PAD(0x47C, 0x19C, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_DISP_D11__NANDF_CEN1	IOMUX_PAD(0x47C, 0x19C, 2, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_DISP_D11__SD4_D1	IOMUX_PAD(0x47C, 0x19C, 4, 0x754, 1, MX50_SD_PAD_CTRL)
+#define MX50_PAD_DISP_D11__KEY_ROW5	IOMUX_PAD(0x47C, 0x19C, 5, 0x7a4, 1, NO_PAD_CTRL)
+#define MX50_PAD_DISP_D11__FEC_RDAT1	IOMUX_PAD(0x47C, 0x19C, 6, 0x77c, 1, NO_PAD_CTRL)
+
+#define MX50_PAD_DISP_D12__DISP_D12	IOMUX_PAD(0x480, 0x1A0, 0, 0x72c, 0, MX50_ELCDIF_PAD_CTRL)
+#define MX50_PAD_DISP_D12__GPIO_2_12	IOMUX_PAD(0x480, 0x1A0, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_DISP_D12__NANDF_CEN2	IOMUX_PAD(0x480, 0x1A0, 2, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_DISP_D12__SD1_CD	IOMUX_PAD(0x480, 0x1A0, 3, 0x0, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_DISP_D12__SD4_D2	IOMUX_PAD(0x480, 0x1A0, 4, 0x758, 1, MX50_SD_PAD_CTRL)
+#define MX50_PAD_DISP_D12__KEY_COL6	IOMUX_PAD(0x480, 0x1A0, 5, 0x798, 1, NO_PAD_CTRL)
+#define MX50_PAD_DISP_D12__FEC_RDAT0	IOMUX_PAD(0x480, 0x1A0, 6, 0x778, 1, NO_PAD_CTRL)
+
+#define MX50_PAD_DISP_D13__DISP_D13	IOMUX_PAD(0x484, 0x1A4, 0, 0x730, 0, MX50_ELCDIF_PAD_CTRL)
+#define MX50_PAD_DISP_D13__GPIO_2_13	IOMUX_PAD(0x484, 0x1A4, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_DISP_D13__NANDF_CEN3	IOMUX_PAD(0x484, 0x1A4, 2, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_DISP_D13__SD3_CD	IOMUX_PAD(0x484, 0x1A4, 3, 0x0, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_DISP_D13__SD4_D3	IOMUX_PAD(0x484, 0x1A4, 4, 0x75c, 1, MX50_SD_PAD_CTRL)
+#define MX50_PAD_DISP_D13__KEY_ROW6	IOMUX_PAD(0x484, 0x1A4, 5, 0x7a8, 1, NO_PAD_CTRL)
+#define MX50_PAD_DISP_D13__FEC_TX_EN	IOMUX_PAD(0x484, 0x1A4, 6, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_DISP_D14__DISP_D14	IOMUX_PAD(0x488, 0x1A8, 0, 0x734, 0, MX50_ELCDIF_PAD_CTRL)
+#define MX50_PAD_DISP_D14__GPIO_2_14	IOMUX_PAD(0x488, 0x1A8, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_DISP_D14__NANDF_RDY0	IOMUX_PAD(0x488, 0x1A8, 2, 0x7b4, 1, NO_PAD_CTRL)
+#define MX50_PAD_DISP_D14__SD1_WP	IOMUX_PAD(0x488, 0x1A8, 3, 0x0, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_DISP_D14__SD4_WP	IOMUX_PAD(0x488, 0x1A8, 4, 0x0, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_DISP_D14__KEY_COL7	IOMUX_PAD(0x488, 0x1A8, 5, 0x79c, 1, NO_PAD_CTRL)
+#define MX50_PAD_DISP_D14__FEC_TDAT1	IOMUX_PAD(0x488, 0x1A8, 6, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_DISP_D15__DISP_D15	IOMUX_PAD(0x48C, 0x1AC, 0, 0x738, 0, MX50_ELCDIF_PAD_CTRL)
+#define MX50_PAD_DISP_D15__GPIO_2_15	IOMUX_PAD(0x48C, 0x1AC, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_DISP_D15__NANDF_DQS	IOMUX_PAD(0x48C, 0x1AC, 2, 0x7b0, 1, NO_PAD_CTRL)
+#define MX50_PAD_DISP_D15__SD3_RST	IOMUX_PAD(0x48C, 0x1AC, 3, 0x0, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_DISP_D15__SD4_CD	IOMUX_PAD(0x48C, 0x1AC, 4, 0x0, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_DISP_D15__KEY_ROW7	IOMUX_PAD(0x48C, 0x1AC, 5, 0x7ac, 1, NO_PAD_CTRL)
+#define MX50_PAD_DISP_D15__FEC_TDAT0	IOMUX_PAD(0x48C, 0x1AC, 6, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_EPDC_D0__EPDC_D0	IOMUX_PAD(0x54C, 0x1B0, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_D0__GPIO_3_0	IOMUX_PAD(0x54C, 0x1B0, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_D0__WEIM_D0	IOMUX_PAD(0x54C, 0x1B0, 2, 0x7ec, 1, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_D0__ELCDIF_RS	IOMUX_PAD(0x54C, 0x1B0, 3, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
+#define MX50_PAD_EPDC_D0__ELCDIF_PIXCLK	IOMUX_PAD(0x54C, 0x1B0, 4, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
+
+#define MX50_PAD_EPDC_D1__EPDC_D1	IOMUX_PAD(0x550, 0x1B4, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_D1__GPIO_3_1	IOMUX_PAD(0x550, 0x1B4, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_D1__WEIM_D1	IOMUX_PAD(0x550, 0x1B4, 2, 0x7f0, 1, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_D1__ELCDIF_CS	IOMUX_PAD(0x550, 0x1B4, 3, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
+#define MX50_PAD_EPDC_D1__ELCDIF_EN	IOMUX_PAD(0x550, 0x1B4, 4, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
+
+#define MX50_PAD_EPDC_D2__EPDC_D2	IOMUX_PAD(0x554, 0x1B8, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_D2__GPIO_3_2	IOMUX_PAD(0x554, 0x1B8, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_D2__WEIM_D2	IOMUX_PAD(0x554, 0x1B8, 2, 0x7f4, 1, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_D2__ELCDIF_WR	IOMUX_PAD(0x554, 0x1B8, 3, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
+#define MX50_PAD_EPDC_D2__ELCDIF_VSYNC	IOMUX_PAD(0x554, 0x1B8, 4, 0x73c, 2, MX50_ELCDIF_PAD_CTRL)
+
+#define MX50_PAD_EPDC_D3__EPDC_D3	IOMUX_PAD(0x558, 0x1BC, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_D3__GPIO_3_3	IOMUX_PAD(0x558, 0x1BC, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_D3__WEIM_D3	IOMUX_PAD(0x558, 0x1BC, 2, 0x7f8, 1, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_D3__ELCDIF_RD	IOMUX_PAD(0x558, 0x1BC, 3, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
+#define MX50_PAD_EPDC_D3__ELCDIF_HSYNC	IOMUX_PAD(0x558, 0x1BC, 4, 0x6f8, 3, MX50_ELCDIF_PAD_CTRL)
+
+#define MX50_PAD_EPDC_D4__EPDC_D4	IOMUX_PAD(0x55C, 0x1C0, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_D4__GPIO_3_4	IOMUX_PAD(0x55C, 0x1C0, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_D4__WEIM_D4	IOMUX_PAD(0x55C, 0x1C0, 2, 0x7fc, 1, NO_PAD_CTRL)
+
+#define MX50_PAD_EPDC_D5__EPDC_D5	IOMUX_PAD(0x560, 0x1C4, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_D5__GPIO_3_5	IOMUX_PAD(0x560, 0x1C4, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_D5__WEIM_D5	IOMUX_PAD(0x560, 0x1C4, 2, 0x800, 1, NO_PAD_CTRL)
+
+#define MX50_PAD_EPDC_D6__EPDC_D6	IOMUX_PAD(0x564, 0x1C8, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_D6__GPIO_3_6	IOMUX_PAD(0x564, 0x1C8, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_D6__WEIM_D6	IOMUX_PAD(0x564, 0x1C8, 2, 0x804, 1, NO_PAD_CTRL)
+
+#define MX50_PAD_EPDC_D7__EPDC_D7	IOMUX_PAD(0x568, 0x1CC, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_D7__GPIO_3_7	IOMUX_PAD(0x568, 0x1CC, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_D7__WEIM_D7	IOMUX_PAD(0x568, 0x1CC, 2, 0x808, 1, NO_PAD_CTRL)
+
+#define MX50_PAD_EPDC_D8__EPDC_D8	IOMUX_PAD(0x56C, 0x1D0, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_D8__GPIO_3_8	IOMUX_PAD(0x56C, 0x1D0, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_D8__WEIM_D8	IOMUX_PAD(0x56C, 0x1D0, 2, 0x80c, 2, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_D8__ELCDIF_D24	IOMUX_PAD(0x56C, 0x1D0, 3, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
+
+#define MX50_PAD_EPDC_D9__EPDC_D9	IOMUX_PAD(0x570, 0x1D4, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_D9__GPIO_3_9	IOMUX_PAD(0x570, 0x1D4, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_D9__WEIM_D9	IOMUX_PAD(0x570, 0x1D4, 2, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_D9__ELCDIF_D25	IOMUX_PAD(0x570, 0x1D4, 3, 0x810, 2, MX50_ELCDIF_PAD_CTRL)
+
+#define MX50_PAD_EPDC_D10__EPDC_D10	IOMUX_PAD(0x574, 0x1D8, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_D10__GPIO_3_10	IOMUX_PAD(0x574, 0x1D8, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_D10__WEIM_D10	IOMUX_PAD(0x574, 0x1D8, 2, 0x814, 2, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_D10__ELCDIF_D26	IOMUX_PAD(0x574, 0x1D8, 3, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_EPDC_D11__EPDC_D11	IOMUX_PAD(0x578, 0x1DC, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_D11__GPIO_3_11	IOMUX_PAD(0x578, 0x1DC, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_D11__WEIM_D11	IOMUX_PAD(0x578, 0x1DC, 2, 0x818, 2, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_D11__ELCDIF_D27	IOMUX_PAD(0x578, 0x1DC, 3, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
+
+#define MX50_PAD_EPDC_D12__EPDC_D12	IOMUX_PAD(0x57C, 0x1E0, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_D12__GPIO_3_12	IOMUX_PAD(0x57C, 0x1E0, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_D12__WEIM_D12	IOMUX_PAD(0x57C, 0x1E0, 2, 0x81c, 1, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_D12__ELCDIF_D28	IOMUX_PAD(0x57C, 0x1E0, 3, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
+
+#define MX50_PAD_EPDC_D13__EPDC_D13	IOMUX_PAD(0x580, 0x1E4, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_D13__GPIO_3_13	IOMUX_PAD(0x580, 0x1E4, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_D13__WEIM_D13	IOMUX_PAD(0x580, 0x1E4, 2, 0x820, 1, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_D13__ELCDIF_D29	IOMUX_PAD(0x580, 0x1E4, 3, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
+
+#define MX50_PAD_EPDC_D14__EPDC_D14	IOMUX_PAD(0x584, 0x1E8, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_D14__GPIO_3_14	IOMUX_PAD(0x584, 0x1E8, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_D14__WEIM_D14	IOMUX_PAD(0x584, 0x1E8, 2, 0x824, 1, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_D14__ELCDIF_D30	IOMUX_PAD(0x584, 0x1E8, 3, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
+#define MX50_PAD_EPDC_D14__AUD6_TXD	IOMUX_PAD(0x584, 0x1E8, 4, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_EPDC_D15__EPDC_D15	IOMUX_PAD(0x588, 0x1EC, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_D15__GPIO_3_15	IOMUX_PAD(0x588, 0x1EC, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_D15__WEIM_D15	IOMUX_PAD(0x588, 0x1EC, 2, 0x828, 1, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_D15__ELCDIF_D31	IOMUX_PAD(0x588, 0x1EC, 3, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
+#define MX50_PAD_EPDC_D15__AUD6_TXC	IOMUX_PAD(0x588, 0x1EC, 4, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_EPDC_GDCLK__EPDC_GDCLK	IOMUX_PAD(0x58C, 0x1F0, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_GDCLK__GPIO_3_16	IOMUX_PAD(0x58C, 0x1F0, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_GDCLK__WEIM_D16	IOMUX_PAD(0x58C, 0x1F0, 2, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_GDCLK__ELCDIF_D16	IOMUX_PAD(0x58C, 0x1F0, 3, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
+#define MX50_PAD_EPDC_GDCLK__AUD6_TXFS	IOMUX_PAD(0x58C, 0x1F0, 4, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_EPDC_GDSP__EPDC_GDSP	IOMUX_PAD(0x590, 0x1F4, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_GDSP__GPIO_3_17	IOMUX_PAD(0x590, 0x1F4, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_GDSP__WEIM_D17	IOMUX_PAD(0x590, 0x1F4, 2, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_GDSP__ELCDIF_D17	IOMUX_PAD(0x590, 0x1F4, 3, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
+#define MX50_PAD_EPDC_GDSP__AUD6_RXD	IOMUX_PAD(0x590, 0x1F4, 4, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_EPDC_GDOE__EPDC_GDOE	IOMUX_PAD(0x594, 0x1F8, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_GDOE__GPIO_3_18	IOMUX_PAD(0x594, 0x1F8, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_GDOE__WEIM_D18	IOMUX_PAD(0x594, 0x1F8, 2, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_GDOE__ELCDIF_D18	IOMUX_PAD(0x594, 0x1F8, 3, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
+#define MX50_PAD_EPDC_GDOE__AUD6_RXC	IOMUX_PAD(0x594, 0x1F8, 4, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_EPDC_GDRL__EPDC_GDRL	IOMUX_PAD(0x598, 0x1FC, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_GDRL__GPIO_3_19	IOMUX_PAD(0x598, 0x1FC, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_GDRL__WEIM_D19	IOMUX_PAD(0x598, 0x1FC, 2, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_GDRL__ELCDIF_D19	IOMUX_PAD(0x598, 0x1FC, 3, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
+#define MX50_PAD_EPDC_GDRL__AUD6_RXFS	IOMUX_PAD(0x598, 0x1FC, 4, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_EPDC_SDCLK__EPDC_SDCLK	IOMUX_PAD(0x59C, 0x200, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_SDCLK__GPIO_3_20	IOMUX_PAD(0x59C, 0x200, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_SDCLK__WEIM_D20	IOMUX_PAD(0x59C, 0x200, 2, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_SDCLK__ELCDIF_D20	IOMUX_PAD(0x59C, 0x200, 3, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
+#define MX50_PAD_EPDC_SDCLK__AUD5_TXD	IOMUX_PAD(0x59C, 0x200, 4, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_EPDC_SDOEZ__EPDC_SDOEZ	IOMUX_PAD(0x5A0, 0x204, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_SDOEZ__GPIO_3_21	IOMUX_PAD(0x5A0, 0x204, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_SDOEZ__WEIM_D21	IOMUX_PAD(0x5A0, 0x204, 2, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_SDOEZ__ELCDIF_D21	IOMUX_PAD(0x5A0, 0x204, 3, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
+#define MX50_PAD_EPDC_SDOEZ__AUD5_TXC	IOMUX_PAD(0x5A0, 0x204, 4, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_EPDC_SDOED__EPDC_SDOED	IOMUX_PAD(0x5A4, 0x208, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_SDOED__GPIO_3_22	IOMUX_PAD(0x5A4, 0x208, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_SDOED__WEIM_D22	IOMUX_PAD(0x5A4, 0x208, 2, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_SDOED__ELCDIF_D22	IOMUX_PAD(0x5A4, 0x208, 3, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
+#define MX50_PAD_EPDC_SDOED__AUD5_TXFS	IOMUX_PAD(0x5A4, 0x208, 4, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_EPDC_SDOE__EPDC_SDOE	IOMUX_PAD(0x5A8, 0x20C, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_SDOE__GPIO_3_23	IOMUX_PAD(0x5A8, 0x20C, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_SDOE__WEIM_D23	IOMUX_PAD(0x5A8, 0x20C, 2, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_SDOE__ELCDIF_D23	IOMUX_PAD(0x5A8, 0x20C, 3, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
+#define MX50_PAD_EPDC_SDOE__AUD5_RXD	IOMUX_PAD(0x5A8, 0x20C, 4, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_EPDC_SDLE__EPDC_SDLE	IOMUX_PAD(0x5AC, 0x210, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_SDLE__GPIO_3_24	IOMUX_PAD(0x5AC, 0x210, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_SDLE__WEIM_D24	IOMUX_PAD(0x5AC, 0x210, 2, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_SDLE__ELCDIF_D8	IOMUX_PAD(0x5AC, 0x210, 3, 0x71c, 1, MX50_ELCDIF_PAD_CTRL)
+#define MX50_PAD_EPDC_SDLE__AUD5_RXC	IOMUX_PAD(0x5AC, 0x210, 4, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_EPDC_SDCLKN__EPDC_SDCLKN	IOMUX_PAD(0x5B0, 0x214, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_SDCLKN__GPIO_3_25		IOMUX_PAD(0x5B0, 0x214, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_SDCLKN__WEIM_D25		IOMUX_PAD(0x5B0, 0x214, 2, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_SDCLKN__ELCDIF_D9		IOMUX_PAD(0x5B0, 0x214, 3, 0x720, 1, MX50_ELCDIF_PAD_CTRL)
+#define MX50_PAD_EPDC_SDCLKN__AUD5_RXFS		IOMUX_PAD(0x5B0, 0x214, 4, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_EPDC_SDSHR__EPDC_SDSHR	IOMUX_PAD(0x5B4, 0x218, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_SDSHR__GPIO_3_26	IOMUX_PAD(0x5B4, 0x218, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_SDSHR__WEIM_D26	IOMUX_PAD(0x5B4, 0x218, 2, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_SDSHR__ELCDIF_D10	IOMUX_PAD(0x5B4, 0x218, 3, 0x724, 1, MX50_ELCDIF_PAD_CTRL)
+#define MX50_PAD_EPDC_SDSHR__AUD4_TXD	IOMUX_PAD(0x5B4, 0x218, 4, 0x6c8, 1, NO_PAD_CTRL)
+
+#define MX50_PAD_EPDC_PWRCOM__EPDC_PWRCOM	IOMUX_PAD(0x5B8, 0x21C, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_PWRCOM__GPIO_3_27		IOMUX_PAD(0x5B8, 0x21C, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_PWRCOM__WEIM_D27		IOMUX_PAD(0x5B8, 0x21C, 2, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_PWRCOM__ELCDIF_D11	IOMUX_PAD(0x5B8, 0x21C, 3, 0x728, 1, MX50_ELCDIF_PAD_CTRL)
+#define MX50_PAD_EPDC_PWRCOM__AUD4_TXC		IOMUX_PAD(0x5B8, 0x21C, 4, 0x6d4, 1, NO_PAD_CTRL)
+
+#define MX50_PAD_EPDC_PWRSTAT__EPDC_PWRSTAT	IOMUX_PAD(0x5BC, 0x220, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_PWRSTAT__GPIO_3_28	IOMUX_PAD(0x5BC, 0x220, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_PWRSTAT__WEIM_D28		IOMUX_PAD(0x5BC, 0x220, 2, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_PWRSTAT__ELCDIF_D12	IOMUX_PAD(0x5BC, 0x220, 3, 0x72c, 1, MX50_ELCDIF_PAD_CTRL)
+#define MX50_PAD_EPDC_PWRSTAT__AUD4_TXFS	IOMUX_PAD(0x5BC, 0x220, 4, 0x6d8, 1, NO_PAD_CTRL)
+
+#define MX50_PAD_EPDC_PWRCTRL0__EPDC_PWRCTRL0	IOMUX_PAD(0x5C0, 0x224, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_PWRCTRL0__GPIO_3_29	IOMUX_PAD(0x5C0, 0x224, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_PWRCTRL0__WEIM_D29	IOMUX_PAD(0x5C0, 0x224, 2, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_PWRCTRL0__ELCDIF_D13	IOMUX_PAD(0x5C0, 0x224, 3, 0x730, 1, MX50_ELCDIF_PAD_CTRL)
+#define MX50_PAD_EPDC_PWRCTRL0__AUD4_RXD	IOMUX_PAD(0x5C0, 0x224, 4, 0x6c4, 1, NO_PAD_CTRL)
+
+#define MX50_PAD_EPDC_PWRCTRL1__EPDC_PWRCTRL1	IOMUX_PAD(0x5C4, 0x228, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_PWRCTRL1__GPIO_3_30	IOMUX_PAD(0x5C4, 0x228, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_PWRCTRL1__WEIM_D30	IOMUX_PAD(0x5C4, 0x228, 2, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_PWRCTRL1__ELCDIF_D14	IOMUX_PAD(0x5C4, 0x228, 3, 0x734, 1, MX50_ELCDIF_PAD_CTRL)
+#define MX50_PAD_EPDC_PWRCTRL1__AUD4_RXC	IOMUX_PAD(0x5C4, 0x228, 4, 0x6cc, 1, NO_PAD_CTRL)
+
+#define MX50_PAD_EPDC_PWRCTRL2__EPDC_PWRCTRL2	IOMUX_PAD(0x5C8, 0x22C, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_PWRCTRL2__GPIO_3_31	IOMUX_PAD(0x5C8, 0x22C, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_PWRCTRL2__WEIM_D31	IOMUX_PAD(0x5C8, 0x22C, 2, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_PWRCTRL2__ELCDIF_D15	IOMUX_PAD(0x5C8, 0x22C, 3, 0x738, 1, MX50_ELCDIF_PAD_CTRL)
+#define MX50_PAD_EPDC_PWRCTRL2__AUD4_RXFS	IOMUX_PAD(0x5C8, 0x22C, 4, 0x6d0, 1, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_PWRCTRL2__SDMA_EXT0	IOMUX_PAD(0x5C8, 0x22C, 6, 0x7b8, 1, NO_PAD_CTRL)
+
+#define MX50_PAD_EPDC_PWRCTRL3__PWRCTRL3	IOMUX_PAD(0x5CC, 0x230, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_PWRCTRL3__GPIO_4_20	IOMUX_PAD(0x5CC, 0x230, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_PWRCTRL3__WEIM_EB2	IOMUX_PAD(0x5CC, 0x230, 2, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_PWRCTRL3__SDMA_EXT1	IOMUX_PAD(0x5CC, 0x230, 6, 0x7bc, 1, NO_PAD_CTRL)
+
+#define MX50_PAD_EPDC_VCOM0__EPDC_VCOM0	IOMUX_PAD(0x5D0, 0x234, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_VCOM0__GPIO_4_21	IOMUX_PAD(0x5D0, 0x234, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_VCOM0__WEIM_EB3	IOMUX_PAD(0x5D0, 0x234, 2, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_EPDC_VCOM1__EPDC_VCOM1	IOMUX_PAD(0x5D4, 0x238, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_VCOM1__GPIO_4_22	IOMUX_PAD(0x5D4, 0x238, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_VCOM1__WEIM_CS3	IOMUX_PAD(0x5D4, 0x238, 2, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_EPDC_BDR0__EPDC_BDR0	IOMUX_PAD(0x5D8, 0x23C, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_BDR0__GPIO_4_23	IOMUX_PAD(0x5D8, 0x23C, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_BDR0__ELCDIF_D7	IOMUX_PAD(0x5D8, 0x23C, 3, 0x718, 1, MX50_ELCDIF_PAD_CTRL)
+
+#define MX50_PAD_EPDC_BDR1__EPDC_BDR1	IOMUX_PAD(0x5DC, 0x240, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_BDR1__GPIO_4_24	IOMUX_PAD(0x5DC, 0x240, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_BDR1__ELCDIF_D6	IOMUX_PAD(0x5DC, 0x240, 3, 0x714, 1, MX50_ELCDIF_PAD_CTRL)
+
+#define MX50_PAD_EPDC_SDCE0__EPDC_SDCE0	IOMUX_PAD(0x5E0, 0x244, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_SDCE0__GPIO_4_25	IOMUX_PAD(0x5E0, 0x244, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_SDCE0__ELCDIF_D5	IOMUX_PAD(0x5E0, 0x244, 3, 0x710, 1, MX50_ELCDIF_PAD_CTRL)
+
+#define MX50_PAD_EPDC_SDCE1__EPDC_SDCE1	IOMUX_PAD(0x5E4, 0x248, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_SDCE1__GPIO_4_26	IOMUX_PAD(0x5E4, 0x248, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_SDCE1__ELCDIF_D4	IOMUX_PAD(0x5E4, 0x248, 2, 0x70c, 1, MX50_ELCDIF_PAD_CTRL)
+
+#define MX50_PAD_EPDC_SDCE2__EPDC_SDCE2		IOMUX_PAD(0x5E8, 0x24C, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_SDCE2__GPIO_4_27		IOMUX_PAD(0x5E8, 0x24C, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_SDCE2__ELCDIF_DAT3	IOMUX_PAD(0x5E8, 0x24C, 3, 0x708, 1, MX50_ELCDIF_PAD_CTRL)
+
+#define MX50_PAD_EPDC_SDCE3__EPDC_SDCE3	IOMUX_PAD(0x5EC, 0x250, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_SDCE3__GPIO_4_28	IOMUX_PAD(0x5EC, 0x250, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_SDCE3__ELCDIF_D2	IOMUX_PAD(0x5EC, 0x250, 3, 0x704, 1, MX50_ELCDIF_PAD_CTRL)
+
+#define MX50_PAD_EPDC_SDCE4__EPDC_SDCE4	IOMUX_PAD(0x5F0, 0x254, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_SDCE4__GPIO_4_29	IOMUX_PAD(0x5F0, 0x254, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_SDCE4__ELCDIF_D1	IOMUX_PAD(0x5F0, 0x254, 3, 0x700, 1, MX50_ELCDIF_PAD_CTRL)
+
+#define MX50_PAD_EPDC_SDCE5__EPDC_SDCE5	IOMUX_PAD(0x5F4, 0x258, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_SDCE5__GPIO_4_30	IOMUX_PAD(0x5F4, 0x258, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_SDCE5__ELCDIF_D0	IOMUX_PAD(0x5F4, 0x258, 3, 0x6fc, 1, MX50_ELCDIF_PAD_CTRL)
+
+#define MX50_PAD_EIM_DA0__WEIM_A0	IOMUX_PAD(0x5F8, 0x25C, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EIM_DA0__GPIO_1_0	IOMUX_PAD(0x5F8, 0x25C, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EIM_DA0__KEY_COL4	IOMUX_PAD(0x5f8, 0x25C, 3, 0x790, 2, NO_PAD_CTRL)
+
+#define MX50_PAD_EIM_DA1__WEIM_A1	IOMUX_PAD(0x5FC, 0x260, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EIM_DA1__GPIO_1_1	IOMUX_PAD(0x5FC, 0x260, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EIM_DA1__KEY_ROW4	IOMUX_PAD(0x5fc, 0x260, 3, 0x7a0, 2, MX50_KEYPAD_CTRL)
+
+#define MX50_PAD_EIM_DA2__WEIM_A2	IOMUX_PAD(0x600, 0x264, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EIM_DA2__GPIO_1_2	IOMUX_PAD(0x600, 0x264, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EIM_DA2__KEY_COL5	IOMUX_PAD(0x600, 0x264, 3, 0x794, 2, NO_PAD_CTRL)
+
+#define MX50_PAD_EIM_DA3__WEIM_A3	IOMUX_PAD(0x604, 0x268, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EIM_DA3__GPIO_1_3	IOMUX_PAD(0x604, 0x268, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EIM_DA3__KEY_ROW5	IOMUX_PAD(0x604, 0x268, 3, 0x7a4, 2, MX50_KEYPAD_CTRL)
+
+#define MX50_PAD_EIM_DA4__WEIM_A4	IOMUX_PAD(0x608, 0x26C, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EIM_DA4__GPIO_1_4	IOMUX_PAD(0x608, 0x26C, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EIM_DA4__KEY_COL6	IOMUX_PAD(0x608, 0x26C, 3, 0x798, 2, NO_PAD_CTRL)
+
+#define MX50_PAD_EIM_DA5__WEIM_A5	IOMUX_PAD(0x60C, 0x270, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EIM_DA5__GPIO_1_5	IOMUX_PAD(0x60C, 0x270, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EIM_DA5__KEY_ROW6	IOMUX_PAD(0x60C, 0x270, 3, 0x7a8, 2, MX50_KEYPAD_CTRL)
+
+#define MX50_PAD_EIM_DA6__WEIM_A6	IOMUX_PAD(0x610, 0x274, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EIM_DA6__GPIO_1_6	IOMUX_PAD(0x610, 0x274, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EIM_DA6__KEY_COL7	IOMUX_PAD(0x610, 0x274, 3, 0x79c, 2, NO_PAD_CTRL)
+
+#define MX50_PAD_EIM_DA7__WEIM_A7	IOMUX_PAD(0x614, 0x278, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EIM_DA7__GPIO_1_7	IOMUX_PAD(0x614, 0x278, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EIM_DA7__KEY_ROW7	IOMUX_PAD(0x614, 0x278, 3, 0x7ac, 2, MX50_KEYPAD_CTRL)
+
+#define MX50_PAD_EIM_DA8__WEIM_A8	IOMUX_PAD(0x618, 0x27C, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EIM_DA8__GPIO_1_8	IOMUX_PAD(0x618, 0x27C, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PIN_EIM_DA8__NANDF_CLE	IOMUX_PAD(0x618, 0x27C, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
+
+#define MX50_PAD_EIM_DA9__WEIM_A9	IOMUX_PAD(0x61C, 0x280, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EIM_DA9__GPIO_1_9	IOMUX_PAD(0x61C, 0x280, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PIN_EIM_DA9__NANDF_ALE	IOMUX_PAD(0x61C, 0x280, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
+
+#define MX50_PAD_EIM_DA10__WEIM_A10	IOMUX_PAD(0x620, 0x284, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EIM_DA10__GPIO_1_10	IOMUX_PAD(0x620, 0x284, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PIN_EIM_DA10__NANDF_CE0	IOMUX_PAD(0x620, 0x284, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
+
+#define MX50_PAD_EIM_DA11__WEIM_A11	IOMUX_PAD(0x624, 0x288, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EIM_DA11__GPIO_1_11	IOMUX_PAD(0x624, 0x288, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PIN_EIM_DA11__NANDF_CE1	IOMUX_PAD(0x624, 0x288, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
+
+#define MX50_PAD_EIM_DA12__WEIM_A12	IOMUX_PAD(0x628, 0x28C, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EIM_DA12__GPIO_1_12	IOMUX_PAD(0x628, 0x28C, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PIN_EIM_DA12__NANDF_CE2	IOMUX_PAD(0x628, 0x28C, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
+#define MX50_PAD_EIM_DA12__EPDC_SDCE6	IOMUX_PAD(0x628, 0x28C, 3, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_EIM_DA13__WEIM_A13	IOMUX_PAD(0x62C, 0x290, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EIM_DA13__GPIO_1_13	IOMUX_PAD(0x62C, 0x290, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PIN_EIM_DA13__NANDF_CE3	IOMUX_PAD(0x62C, 0x290, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
+#define MX50_PIN_EIM_DA13__EPDC_SDCE7	IOMUX_PAD(0x62C, 0x290, 3, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_EIM_DA14__WEIM_A14	IOMUX_PAD(0x630, 0x294, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EIM_DA14__GPIO_1_14	IOMUX_PAD(0x630, 0x294, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EIM_DA14__NANDF_READY	IOMUX_PAD(0x630, 0x294, 2, 0x7B4, 2, PAD_CTL_PKE | \
+							PAD_CTL_PUE | PAD_CTL_PUS_100K_UP)
+#define MX50_PAD_EIM_DA14__EPDC_SDCE8	IOMUX_PAD(0x630, 0x294, 3, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_EIM_DA15__WEIM_A15	IOMUX_PAD(0x634, 0x298, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EIM_DA15__GPIO_1_15	IOMUX_PAD(0x634, 0x298, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PIN_EIM_DA15__NANDF_DQS	IOMUX_PAD(0x634, 0x298, 2, 0x7B0, 2, PAD_CTL_DSE_HIGH)
+#define MX50_PAD_EIM_DA15__EPDC_SDCE9	IOMUX_PAD(0x634, 0x298, 3, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_EIM_CS2__WEIM_CS2	IOMUX_PAD(0x638, 0x29C, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EIM_CS2__GPIO_1_16	IOMUX_PAD(0x638, 0x29C, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EIM_CS2__WEIM_A27	IOMUX_PAD(0x638, 0x29C, 2, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_EIM_CS1__WEIM_CS1	IOMUX_PAD(0x63C, 0x2A0, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EIM_CS1__GPIO_1_17	IOMUX_PAD(0x63C, 0x2A0, 1, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_EIM_CS0__WEIM_CS0	IOMUX_PAD(0x640, 0x2A4, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EIM_CS0__GPIO_1_18	IOMUX_PAD(0x640, 0x2A4, 1, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_EIM_EB0__WEIM_EB0	IOMUX_PAD(0x644, 0x2A8, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EIM_EB0__GPIO_1_19	IOMUX_PAD(0x644, 0x2A8, 1, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_EIM_EB1__WEIM_EB1	IOMUX_PAD(0x648, 0x2AC, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EIM_EB1__GPIO_1_20	IOMUX_PAD(0x648, 0x2AC, 1, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_EIM_WAIT__WEIM_WAIT	IOMUX_PAD(0x64C, 0x2B0, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EIM_WAIT__GPIO_1_21	IOMUX_PAD(0x64C, 0x2B0, 1, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_EIM_BCLK__WEIM_BCLK	IOMUX_PAD(0x650, 0x2B4, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EIM_BCLK__GPIO_1_22	IOMUX_PAD(0x650, 0x2B4, 1, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_EIM_RDY__WEIM_RDY	IOMUX_PAD(0x654, 0x2B8, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EIM_RDY__GPIO_1_23	IOMUX_PAD(0x654, 0x2B8, 1, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_EIM_OE__WEIM_OE	IOMUX_PAD(0x658, 0x2BC, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EIM_OE__GPIO_1_24	IOMUX_PAD(0x658, 0x2BC, 1, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_EIM_RW__WEIM_RW	IOMUX_PAD(0x65C, 0x2C0, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EIM_RW__GPIO_1_25	IOMUX_PAD(0x65C, 0x2C0, 1, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_EIM_LBA__WEIM_LBA	IOMUX_PAD(0x660, 0x2C4, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EIM_LBA__GPIO_1_26	IOMUX_PAD(0x660, 0x2C4, 1, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_EIM_CRE__WEIM_CRE	IOMUX_PAD(0x664, 0x2C8, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EIM_CRE__GPIO_1_27	IOMUX_PAD(0x664, 0x2C8, 1, 0x0, 0, NO_PAD_CTRL)
+
+#endif /* __MACH_IOMUX_MX50_H__ */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/include/mach/iomux-mx51.h linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/include/mach/iomux-mx51.h
--- linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/include/mach/iomux-mx51.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/include/mach/iomux-mx51.h	2011-03-14 21:20:32.000000000 -0400
@@ -15,373 +15,1553 @@
 
 #include <mach/iomux-v3.h>
 
-/*
- * various IOMUX alternate output functions (1-7)
- */
-typedef enum iomux_config {
-	IOMUX_CONFIG_ALT0,
-	IOMUX_CONFIG_ALT1,
-	IOMUX_CONFIG_ALT2,
-	IOMUX_CONFIG_ALT3,
-	IOMUX_CONFIG_ALT4,
-	IOMUX_CONFIG_ALT5,
-	IOMUX_CONFIG_ALT6,
-	IOMUX_CONFIG_ALT7,
-	IOMUX_CONFIG_GPIO,      /* added to help user use GPIO mode */
-	IOMUX_CONFIG_SION = 0x1 << 4,   /* LOOPBACK:MUX SION bit */
-} iomux_pin_cfg_t;
-
 /* Pad control groupings */
-#define MX51_UART1_PAD_CTRL	(PAD_CTL_HYS | PAD_CTL_PKE | PAD_CTL_PUE | \
-				PAD_CTL_DSE_HIGH)
-#define MX51_UART2_PAD_CTRL	(PAD_CTL_PKE | PAD_CTL_PUE | PAD_CTL_DSE_HIGH | \
-				PAD_CTL_SRE_FAST)
-#define MX51_UART3_PAD_CTRL	(PAD_CTL_PKE | PAD_CTL_DSE_HIGH | \
-				PAD_CTL_SRE_FAST)
+#define MX51_UART_PAD_CTRL	(PAD_CTL_PKE | PAD_CTL_PUE | PAD_CTL_DSE_HIGH | \
+				PAD_CTL_HYS | PAD_CTL_SRE_FAST)
 #define MX51_I2C_PAD_CTRL	(PAD_CTL_SRE_FAST | PAD_CTL_ODE | \
-				PAD_CTL_DSE_HIGH | PAD_CTL_PUS_100K_UP | PAD_CTL_HYS)
-#define MX51_USBH1_PAD_CTRL	(PAD_CTL_SRE_FAST | PAD_CTL_DSE_HIGH | \
-				PAD_CTL_PUS_100K_UP | PAD_CTL_PUE | \
-				PAD_CTL_PKE | PAD_CTL_HYS)
-#define MX51_GPIO_PAD_CTRL		(PAD_CTL_DSE_HIGH | PAD_CTL_PKE | \
-				PAD_CTL_SRE_FAST)
-#define MX51_GPIO_PAD_CTRL_2	(PAD_CTL_SRE_FAST | PAD_CTL_DSE_HIGH | \
-					PAD_CTL_PUS_100K_UP)
-#define MX51_ECSPI_PAD_CTRL	(PAD_CTL_HYS | PAD_CTL_PKE | PAD_CTL_DSE_HIGH | \
-				PAD_CTL_SRE_FAST)
-#define MX51_SDHCI_PAD_CTRL	(PAD_CTL_DSE_HIGH | PAD_CTL_PUS_47K_UP | \
-				PAD_CTL_PKE | PAD_CTL_PUE | PAD_CTL_SRE_FAST | \
-				PAD_CTL_DVS)
+				PAD_CTL_DSE_HIGH | PAD_CTL_PUS_100K_UP | \
+				PAD_CTL_HYS)
+#define MX51_ESDHC_PAD_CTRL	(PAD_CTL_SRE_FAST | PAD_CTL_ODE | \
+				PAD_CTL_DSE_HIGH | PAD_CTL_PUS_100K_UP | \
+				PAD_CTL_HYS)
+#define MX51_USBH1_PAD_CTRL	(PAD_CTL_PKE | PAD_CTL_SRE_FAST | \
+				PAD_CTL_DSE_HIGH | PAD_CTL_PUS_100K_UP | \
+				PAD_CTL_HYS | PAD_CTL_PUE)
+#define MX51_ECSPI_PAD_CTRL	(PAD_CTL_PKE | PAD_CTL_HYS | \
+				PAD_CTL_DSE_HIGH | PAD_CTL_SRE_FAST)
+#define MX51_SDHCI_PAD_CTRL	(PAD_CTL_PKE | PAD_CTL_DSE_HIGH | \
+				PAD_CTL_PUS_47K_UP | PAD_CTL_PUE | \
+				PAD_CTL_SRE_FAST | PAD_CTL_DVS)
+#define MX51_GPIO_PAD_CTRL	(PAD_CTL_DSE_HIGH | PAD_CTL_PKE | PAD_CTL_SRE_FAST)
 
-#define MX51_PAD_CTRL_1	(PAD_CTL_SRE_FAST | PAD_CTL_DSE_HIGH | \
-					PAD_CTL_PUE | PAD_CTL_PKE | PAD_CTL_HYS)
-#define MX51_PAD_CTRL_2	(PAD_CTL_HYS | PAD_CTL_PKE)
-#define MX51_PAD_CTRL_3	(PAD_CTL_PKE | PAD_CTL_PUS_100K_UP)
-#define MX51_PAD_CTRL_4	(PAD_CTL_DVS | PAD_CTL_HYS | PAD_CTL_PKE)
-#define MX51_PAD_CTRL_5	(PAD_CTL_DVS | PAD_CTL_DSE_HIGH)
+#define MX51_PAD_CTRL_2		(PAD_CTL_PKE | PAD_CTL_HYS)
+#define MX51_PAD_CTRL_3		(PAD_CTL_PKE | PAD_CTL_PUS_100K_UP)
+#define MX51_PAD_CTRL_4		(PAD_CTL_PKE | PAD_CTL_DVS | PAD_CTL_HYS)
+#define MX51_PAD_CTRL_5		(PAD_CTL_DVS | PAD_CTL_DSE_HIGH)
 
 /*
  * The naming convention for the pad modes is MX51_PAD_<padname>__<padmode>
- * If <padname> or <padmode> refers to a GPIO, it is named GPIO_<unit>_<num>
+ * If <padname> or <padmode> refers to a GPIO, it is named GPIO<unit>_<num>
  * See also iomux-v3.h
  */
 
-/*							  PAD    MUX   ALT INPSE PATH PADCTRL */
-#define MX51_PAD_EIM_DA0__EIM_DA0		IOMUX_PAD(0x7a8, 0x01c, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_DA1__EIM_DA1		IOMUX_PAD(0x7a8, 0x020, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_DA2__EIM_DA2		IOMUX_PAD(0x7a8, 0x024, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_DA3__EIM_DA3		IOMUX_PAD(0x7a8, 0x028, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_DA4__EIM_DA4		IOMUX_PAD(0x7ac, 0x02c, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_DA5__EIM_DA5		IOMUX_PAD(0x7ac, 0x030, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_DA6__EIM_DA6		IOMUX_PAD(0x7ac, 0x034, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_DA7__EIM_DA7		IOMUX_PAD(0x7ac, 0x038, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_DA8__EIM_DA8		IOMUX_PAD(0x7b0, 0x03c, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_DA9__EIM_DA9		IOMUX_PAD(0x7b0, 0x040, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_DA10__EIM_DA10		IOMUX_PAD(0x7b0, 0x044, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_DA11__EIM_DA11		IOMUX_PAD(0x7b0, 0x048, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_DA12__EIM_DA12		IOMUX_PAD(0x7bc, 0x04c, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_DA13__EIM_DA13		IOMUX_PAD(0x7bc, 0x050, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_DA14__EIM_DA14		IOMUX_PAD(0x7bc, 0x054, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_DA15__EIM_DA15		IOMUX_PAD(0x7bc, 0x058, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D16__GPIO_2_0              IOMUX_PAD(0x3f0, 0x05c, 1, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D16__I2C1_SDA		IOMUX_PAD(0x3f0, 0x05c, (4 | IOMUX_CONFIG_SION), \
-							0x09b4, 0, MX51_I2C_PAD_CTRL)
-#define MX51_PAD_EIM_D17__GPIO_2_1              IOMUX_PAD(0x3f4, 0x060, 1, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D18__GPIO_2_2              IOMUX_PAD(0x3f8, 0x064, 1, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D19__GPIO_2_3              IOMUX_PAD(0x3fc, 0x068, 1, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D19__I2C1_SCL		IOMUX_PAD(0x3fc, 0x068, (4 | IOMUX_CONFIG_SION), \
-							0x09b0, 0, MX51_I2C_PAD_CTRL)
-#define MX51_PAD_EIM_D20__GPIO_2_4              IOMUX_PAD(0x400, 0x06c, 1, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D21__GPIO_2_5		IOMUX_PAD(0x404, 0x070, 1, 0x0,   0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_EIM_D22__GPIO_2_6              IOMUX_PAD(0x408, 0x074, 1, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D23__GPIO_2_7              IOMUX_PAD(0x40c, 0x078, 1, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D24__UART3_CTS             IOMUX_PAD(0x410, 0x07c, 3, 0x0,   0, MX51_UART3_PAD_CTRL)
-#define MX51_PAD_EIM_D25__UART3_RXD             IOMUX_PAD(0x414, 0x080, 3, 0x9f4, 0, MX51_UART3_PAD_CTRL)
-#define MX51_PAD_EIM_D25__UART2_CTS		IOMUX_PAD(0x414, 0x080, 4, 0x0,   0, MX51_UART2_PAD_CTRL)
-#define MX51_PAD_EIM_D26__UART3_TXD             IOMUX_PAD(0x418, 0x084, 3, 0x0,   0, MX51_UART3_PAD_CTRL)
-#define MX51_PAD_EIM_D26__UART2_RTS		IOMUX_PAD(0x418, 0x084, 4, 0x9e8, 3, MX51_UART2_PAD_CTRL)
-#define MX51_PAD_EIM_D27__UART3_RTS             IOMUX_PAD(0x41c, 0x088, 3, 0x9f0, 3, MX51_UART3_PAD_CTRL)
-#define MX51_PAD_EIM_D28__EIM_D28               IOMUX_PAD(0x420, 0x08c, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D29__EIM_D29               IOMUX_PAD(0x424, 0x090, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D30__EIM_D30               IOMUX_PAD(0x428, 0x094, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D31__EIM_D31               IOMUX_PAD(0x42c, 0x09c, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_A16__GPIO_2_10             IOMUX_PAD(0x430, 0x09c, 1, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_A17__GPIO_2_11             IOMUX_PAD(0x434, 0x0a0, 1, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_A18__GPIO_2_12             IOMUX_PAD(0x438, 0x0a4, 1, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_A19__GPIO_2_13             IOMUX_PAD(0x43c, 0x0a8, 1, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_A20__GPIO_2_14             IOMUX_PAD(0x440, 0x0ac, 1, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_A21__GPIO_2_15             IOMUX_PAD(0x444, 0x0b0, 1, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_A22__GPIO_2_16             IOMUX_PAD(0x448, 0x0b4, 1, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_A23__GPIO_2_17             IOMUX_PAD(0x44c, 0x0b8, 1, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_A24__GPIO_2_18             IOMUX_PAD(0x450, 0x0bc, 1, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_A25__GPIO_2_19             IOMUX_PAD(0x454, 0x0c0, 1, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_A26__GPIO_2_20             IOMUX_PAD(0x458, 0x0c4, 1, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_A27__GPIO_2_21             IOMUX_PAD(0x45c, 0x0c8, 1, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_EB0__EIM_EB0               IOMUX_PAD(0x460, 0x0cc, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_EB1__EIM_EB1               IOMUX_PAD(0x464, 0x0d0, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_EB2__GPIO_2_22             IOMUX_PAD(0x468, 0x0d4, 1, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_EB2__FEC_MDIO		IOMUX_PAD(0x468, 0x0d4, 3, 0x0,   0, MX51_PAD_CTRL_1 | PAD_CTL_PUS_22K_UP)
-#define MX51_PAD_EIM_EB3__GPIO_2_23             IOMUX_PAD(0x46c, 0x0d8, 1, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_EB3__FEC_RDAT1		IOMUX_PAD(0x46c, 0x0d8, 3, 0x0,   0, MX51_PAD_CTRL_2)
-#define MX51_PAD_EIM_OE__GPIO_2_24              IOMUX_PAD(0x470, 0x0dc, 1, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_CS0__GPIO_2_25             IOMUX_PAD(0x474, 0x0e0, 1, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_CS1__GPIO_2_26             IOMUX_PAD(0x478, 0x0e4, 1, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_CS2__GPIO_2_27             IOMUX_PAD(0x47c, 0x0e8, 1, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_CS2__FEC_RDAT2		IOMUX_PAD(0x47c, 0x0e8, 3, 0x0,   0, MX51_PAD_CTRL_2)
-#define MX51_PAD_EIM_CS3__GPIO_2_28             IOMUX_PAD(0x480, 0x0ec, 1, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_CS3__FEC_RDAT3		IOMUX_PAD(0x480, 0x0ec, 3, 0x0,   0, MX51_PAD_CTRL_2)
-#define MX51_PAD_EIM_CS4__GPIO_2_29             IOMUX_PAD(0x484, 0x0f0, 1, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_CS4__FEC_RX_ER		IOMUX_PAD(0x484, 0x0f0, 3, 0x0,   0, MX51_PAD_CTRL_2)
-#define MX51_PAD_EIM_CS5__GPIO_2_30             IOMUX_PAD(0x488, 0x0f4, 1, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_CS5__FEC_CRS		IOMUX_PAD(0x488, 0x0f4, 3, 0x0,   0, MX51_PAD_CTRL_2)
-#define MX51_PAD_EIM_DTACK__GPIO_2_31           IOMUX_PAD(0x48c, 0x0f8, 1, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_LBA__GPIO_3_1              IOMUX_PAD(0x494, 0x0FC, 1, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_CRE__GPIO_3_2              IOMUX_PAD(0x4A0, 0x100, 1, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_DRAM_CS1__DRAM_CS1             IOMUX_PAD(0x4D0, 0x104, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_WE_B__GPIO_3_3           IOMUX_PAD(0x4E4, 0x108, 3, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_RE_B__GPIO_3_4           IOMUX_PAD(0x4E8, 0x10C, 3, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_ALE__GPIO_3_5            IOMUX_PAD(0x4EC, 0x110, 3, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_CLE__GPIO_3_6            IOMUX_PAD(0x4F0, 0x114, 3, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_WP_B__GPIO_3_7           IOMUX_PAD(0x4F4, 0x118, 3, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_RB0__GPIO_3_8            IOMUX_PAD(0x4F8, 0x11C, 3, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_RB1__GPIO_3_9            IOMUX_PAD(0x4FC, 0x120, 3, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_RB2__GPIO_3_10           IOMUX_PAD(0x500, 0x124, 3, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_RB2__ECSPI2_SCLK         IOMUX_PAD(0x500, 0x124, 2, 0x0,   0, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_NANDF_RB2__FEC_COL		IOMUX_PAD(0x500, 0x124, 1, 0x0,   0, MX51_PAD_CTRL_2)
-#define MX51_PAD_NANDF_RB3__GPIO_3_11           IOMUX_PAD(0x504, 0x128, 3, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_RB3__ECSPI2_MISO         IOMUX_PAD(0x504, 0x128, 2, 0x0,   0, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_NANDF_RB3__FEC_RXCLK		IOMUX_PAD(0x504, 0x128, 1, 0x0,   0, MX51_PAD_CTRL_2)
-#define MX51_PAD_NANDF_RB6__FEC_RDAT0		IOMUX_PAD(0x5DC, 0x134, 1, 0x0,   0, MX51_PAD_CTRL_4)
-#define MX51_PAD_NANDF_RB7__FEC_TDAT0		IOMUX_PAD(0x5E0, 0x138, 1, 0x0,   0, MX51_PAD_CTRL_5)
-#define MX51_PAD_GPIO_NAND__GPIO_3_12           IOMUX_PAD(0x514, 0x12C, 3, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_CS0__GPIO_3_16           IOMUX_PAD(0x518, 0x130, 3, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_CS1__GPIO_3_17           IOMUX_PAD(0x51C, 0x134, 3, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_CS2__GPIO_3_18           IOMUX_PAD(0x520, 0x138, 3, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_CS2__FEC_TX_ER		IOMUX_PAD(0x520, 0x138, 2, 0x0,   0, MX51_PAD_CTRL_5)
-#define MX51_PAD_NANDF_CS3__GPIO_3_19           IOMUX_PAD(0x524, 0x13C, 3, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_CS3__FEC_MDC		IOMUX_PAD(0x524, 0x13C, 2, 0x0,   0, MX51_PAD_CTRL_5)
-#define MX51_PAD_NANDF_CS4__GPIO_3_20           IOMUX_PAD(0x528, 0x140, 3, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_CS4__FEC_TDAT1		IOMUX_PAD(0x528, 0x140, 2, 0x0,   0, MX51_PAD_CTRL_5)
-#define MX51_PAD_NANDF_CS5__GPIO_3_21           IOMUX_PAD(0x52C, 0x144, 3, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_CS5__FEC_TDAT2		IOMUX_PAD(0x52C, 0x144, 2, 0x0,   0, MX51_PAD_CTRL_5)
-#define MX51_PAD_NANDF_CS6__GPIO_3_22           IOMUX_PAD(0x530, 0x148, 3, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_CS6__FEC_TDAT3		IOMUX_PAD(0x530, 0x148, 2, 0x0,   0, MX51_PAD_CTRL_5)
-#define MX51_PAD_NANDF_CS7__GPIO_3_23           IOMUX_PAD(0x534, 0x14C, 3, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_CS7__FEC_TX_EN		IOMUX_PAD(0x534, 0x14C, 1, 0x0,   0, MX51_PAD_CTRL_5)
-#define MX51_PAD_NANDF_RDY_INT__GPIO_3_24       IOMUX_PAD(0x538, 0x150, 3, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_RDY_INT__FEC_TX_CLK	IOMUX_PAD(0x538, 0x150, 1, 0x0,   0, MX51_PAD_CTRL_4)
-#define MX51_PAD_NANDF_D15__GPIO_3_25           IOMUX_PAD(0x53C, 0x154, 3, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D15__ECSPI2_MOSI         IOMUX_PAD(0x53C, 0x154, 2, 0x0,   0, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_NANDF_D14__GPIO_3_26           IOMUX_PAD(0x540, 0x158, 3, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D13__GPIO_3_27           IOMUX_PAD(0x544, 0x15C, 3, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D12__GPIO_3_28           IOMUX_PAD(0x548, 0x160, 3, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D11__GPIO_3_29           IOMUX_PAD(0x54C, 0x164, 3, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D10__GPIO_3_30           IOMUX_PAD(0x550, 0x168, 3, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D9__GPIO_3_31            IOMUX_PAD(0x554, 0x16C, 3, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D8__GPIO_4_0             IOMUX_PAD(0x558, 0x170, 3, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D7__GPIO_4_1             IOMUX_PAD(0x55C, 0x174, 3, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D6__GPIO_4_2             IOMUX_PAD(0x560, 0x178, 3, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D5__GPIO_4_3             IOMUX_PAD(0x564, 0x17C, 3, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D4__GPIO_4_4             IOMUX_PAD(0x568, 0x180, 3, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D3__GPIO_4_5             IOMUX_PAD(0x56C, 0x184, 3, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D2__GPIO_4_6             IOMUX_PAD(0x570, 0x188, 3, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D1__GPIO_4_7             IOMUX_PAD(0x574, 0x18C, 3, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D0__GPIO_4_8             IOMUX_PAD(0x578, 0x190, 3, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_CSI1_D8__GPIO_3_12             IOMUX_PAD(0x57C, 0x194, 3, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_CSI1_D9__GPIO_3_13             IOMUX_PAD(0x580, 0x198, 3, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_CSI1_D10__CSI1_D10             IOMUX_PAD(0x584, 0x19C, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_CSI1_D11__CSI1_D11             IOMUX_PAD(0x588, 0x1A0, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_CSI1_D12__CSI1_D12             IOMUX_PAD(0x58C, 0x1A4, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_CSI1_D13__CSI1_D13             IOMUX_PAD(0x590, 0x1A8, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_CSI1_D14__CSI1_D14             IOMUX_PAD(0x594, 0x1AC, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_CSI1_D15__CSI1_D15             IOMUX_PAD(0x598, 0x1B0, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_CSI1_D16__CSI1_D16             IOMUX_PAD(0x59C, 0x1B4, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_CSI1_D17__CSI1_D17             IOMUX_PAD(0x5A0, 0x1B8, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_CSI1_D18__CSI1_D18             IOMUX_PAD(0x5A4, 0x1BC, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_CSI1_D19__CSI1_D19             IOMUX_PAD(0x5A8, 0x1C0, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_CSI1_VSYNC__CSI1_VSYNC         IOMUX_PAD(0x5AC, 0x1C4, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_CSI1_HSYNC__CSI1_HSYNC         IOMUX_PAD(0x5B0, 0x1C8, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_CSI1_PIXCLK__CSI1_PIXCLK       IOMUX_PAD(0x5B4, 0x000, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_CSI1_MCLK__CSI1_MCLK           IOMUX_PAD(0x5B8, 0x000, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_CSI1_PKE0__CSI1_PKE0           IOMUX_PAD(0x860, 0x000, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_CSI2_D12__GPIO_4_9             IOMUX_PAD(0x5BC, 0x1CC, 3, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_CSI2_D13__GPIO_4_10            IOMUX_PAD(0x5C0, 0x1D0, 3, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_CSI2_D14__GPIO_4_11            IOMUX_PAD(0x5C4, 0x1D4, 3, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_CSI2_D15__GPIO_4_12            IOMUX_PAD(0x5C8, 0x1D8, 3, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_CSI2_D16__GPIO_4_11            IOMUX_PAD(0x5CC, 0x1DC, 3, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_CSI2_D17__GPIO_4_12            IOMUX_PAD(0x5D0, 0x1E0, 3, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_CSI2_D18__GPIO_4_11            IOMUX_PAD(0x5D4, 0x1E4, 3, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_CSI2_D19__GPIO_4_12            IOMUX_PAD(0x5D8, 0x1E8, 3, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_CSI2_VSYNC__GPIO_4_13          IOMUX_PAD(0x5DC, 0x1EC, 3, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_CSI2_HSYNC__GPIO_4_14          IOMUX_PAD(0x5E0, 0x1F0, 3, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_CSI2_PIXCLK__GPIO_4_15         IOMUX_PAD(0x5E4, 0x1F4, 3, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_I2C1_CLK__GPIO_4_16            IOMUX_PAD(0x5E8, 0x1F8, 3, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_I2C1_CLK__HSI2C_CLK		IOMUX_PAD(0x5E8, 0x1F8, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_I2C1_DAT__GPIO_4_17            IOMUX_PAD(0x5EC, 0x1FC, 3, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_I2C1_DAT__HSI2C_DAT		IOMUX_PAD(0x5EC, 0x1FC, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_AUD3_BB_TXD__AUD3_BB_TXD       IOMUX_PAD(0x5F0, 0x200, IOMUX_CONFIG_SION, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_AUD3_BB_TXD__GPIO_4_18         IOMUX_PAD(0x5F0, 0x200, 3, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_AUD3_BB_RXD__AUD3_BB_RXD       IOMUX_PAD(0x5F4, 0x204, IOMUX_CONFIG_SION, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_AUD3_BB_RXD__GPIO_4_19         IOMUX_PAD(0x5F4, 0x204, 3, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_AUD3_BB_CK__AUD3_BB_CK         IOMUX_PAD(0x5F8, 0x208, IOMUX_CONFIG_SION, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_AUD3_BB_CK__GPIO_4_20          IOMUX_PAD(0x5F8, 0x208, 3, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_AUD3_BB_FS__AUD3_BB_FS         IOMUX_PAD(0x5FC, 0x20C, IOMUX_CONFIG_SION, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_AUD3_BB_FS__GPIO_4_21          IOMUX_PAD(0x5FC, 0x20C, 3, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_CSPI1_MOSI__ECSPI1_MOSI        IOMUX_PAD(0x600, 0x210, 0, 0x0,   0, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_CSPI1_MOSI__GPIO_4_22          IOMUX_PAD(0x600, 0x210, 3, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_CSPI1_MISO__ECSPI1_MISO        IOMUX_PAD(0x604, 0x214, 0, 0x0,   0, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_CSPI1_MISO__GPIO_4_23          IOMUX_PAD(0x604, 0x214, 3, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_CSPI1_SS0__ECSPI1_SS0          IOMUX_PAD(0x608, 0x218, 0, 0x0,   0, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_CSPI1_SS0__GPIO_4_24           IOMUX_PAD(0x608, 0x218, 3, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_CSPI1_SS1__ECSPI1_SS1          IOMUX_PAD(0x60C, 0x21C, 0, 0x0,   0, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_CSPI1_SS1__GPIO_4_25           IOMUX_PAD(0x60C, 0x21C, 3, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_CSPI1_RDY__ECSPI1_RDY          IOMUX_PAD(0x610, 0x220, 0, 0x0,   0, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_CSPI1_RDY__GPIO_4_26           IOMUX_PAD(0x610, 0x220, 3, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_CSPI1_SCLK__ECSPI1_SCLK        IOMUX_PAD(0x614, 0x224, 0, 0x0,   0, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_CSPI1_SCLK__GPIO_4_27          IOMUX_PAD(0x614, 0x224, 3, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_UART1_RXD__UART1_RXD           IOMUX_PAD(0x618, 0x228, 0, 0x9e4, 0, MX51_UART1_PAD_CTRL | PAD_CTL_SRE_FAST)
-#define MX51_PAD_UART1_TXD__UART1_TXD           IOMUX_PAD(0x61C, 0x22C, 0, 0x0,   0, MX51_UART1_PAD_CTRL | PAD_CTL_SRE_FAST)
-#define MX51_PAD_UART1_RTS__UART1_RTS           IOMUX_PAD(0x620, 0x230, 0, 0x9e0, 0, MX51_UART1_PAD_CTRL)
-#define MX51_PAD_UART1_CTS__UART1_CTS           IOMUX_PAD(0x624, 0x234, 0, 0x0,   0, MX51_UART1_PAD_CTRL)
-#define MX51_PAD_UART2_RXD__UART2_RXD           IOMUX_PAD(0x628, 0x238, 0, 0x9ec, 2, MX51_UART2_PAD_CTRL)
-#define MX51_PAD_UART2_TXD__UART2_TXD           IOMUX_PAD(0x62C, 0x23C, 0, 0x0,   0, MX51_UART2_PAD_CTRL)
-#define MX51_PAD_UART3_RXD__UART3_RXD		IOMUX_PAD(0x630, 0x240, 1, 0x9f4, 4, MX51_UART3_PAD_CTRL)
-#define MX51_PAD_UART3_RXD__GPIO_1_22           IOMUX_PAD(0x630, 0x240, 3, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_UART3_TXD__UART3_TXD		IOMUX_PAD(0x634, 0x244, 1, 0x0,   0, MX51_UART3_PAD_CTRL)
-#define MX51_PAD_UART3_TXD__GPIO_1_23           IOMUX_PAD(0x634, 0x244, 3, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_OWIRE_LINE__GPIO_1_24          IOMUX_PAD(0x638, 0x248, 3, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_KEY_ROW0__KEY_ROW0             IOMUX_PAD(0x63C, 0x24C, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_KEY_ROW1__KEY_ROW1             IOMUX_PAD(0x640, 0x250, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_KEY_ROW2__KEY_ROW2             IOMUX_PAD(0x644, 0x254, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_KEY_ROW3__KEY_ROW3             IOMUX_PAD(0x648, 0x258, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_KEY_COL0__KEY_COL0             IOMUX_PAD(0x64C, 0x25C, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_KEY_COL1__KEY_COL1             IOMUX_PAD(0x650, 0x260, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_KEY_COL2__KEY_COL2             IOMUX_PAD(0x654, 0x264, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_KEY_COL3__KEY_COL3             IOMUX_PAD(0x658, 0x268, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_KEY_COL4__KEY_COL4             IOMUX_PAD(0x65C, 0x26C, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_KEY_COL4__UART3_RTS		IOMUX_PAD(0x65C, 0x26C, 2, 0x9f0, 4, MX51_UART3_PAD_CTRL)
-#define MX51_PAD_KEY_COL4__I2C2_SCL		IOMUX_PAD(0x65C, 0x26C, (3 | IOMUX_CONFIG_SION), \
-							0x09b8, 1, MX51_I2C_PAD_CTRL)
-#define MX51_PAD_KEY_COL5__KEY_COL5             IOMUX_PAD(0x660, 0x270, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_KEY_COL5__UART3_CTS		IOMUX_PAD(0x660, 0x270, 2, 0,     0, MX51_UART3_PAD_CTRL)
-#define MX51_PAD_KEY_COL5__I2C2_SDA		IOMUX_PAD(0x660, 0x270, (3 | IOMUX_CONFIG_SION), \
-							0x09bc, 1, MX51_I2C_PAD_CTRL)
-#define MX51_PAD_USBH1_CLK__USBH1_CLK           IOMUX_PAD(0x678, 0x278, 0, 0x0,   0, MX51_USBH1_PAD_CTRL)
-#define MX51_PAD_USBH1_DIR__USBH1_DIR           IOMUX_PAD(0x67C, 0x27C, 0, 0x0,   0, MX51_USBH1_PAD_CTRL)
-#define MX51_PAD_USBH1_STP__USBH1_STP           IOMUX_PAD(0x680, 0x280, 0, 0x0,   0, MX51_USBH1_PAD_CTRL)
-#define MX51_PAD_USBH1_STP__GPIO_1_27           IOMUX_PAD(0x680, 0x280, 2, 0x0,   0, MX51_USBH1_PAD_CTRL)
-#define MX51_PAD_USBH1_NXT__USBH1_NXT           IOMUX_PAD(0x684, 0x284, 0, 0x0,   0, MX51_USBH1_PAD_CTRL)
-#define MX51_PAD_USBH1_DATA0__USBH1_DATA0       IOMUX_PAD(0x688, 0x288, 0, 0x0,   0, MX51_USBH1_PAD_CTRL)
-#define MX51_PAD_USBH1_DATA1__USBH1_DATA1       IOMUX_PAD(0x68C, 0x28C, 0, 0x0,   0, MX51_USBH1_PAD_CTRL)
-#define MX51_PAD_USBH1_DATA2__USBH1_DATA2       IOMUX_PAD(0x690, 0x290, 0, 0x0,   0, MX51_USBH1_PAD_CTRL)
-#define MX51_PAD_USBH1_DATA3__USBH1_DATA3       IOMUX_PAD(0x694, 0x294, 0, 0x0,   0, MX51_USBH1_PAD_CTRL)
-#define MX51_PAD_USBH1_DATA4__USBH1_DATA4       IOMUX_PAD(0x698, 0x298, 0, 0x0,   0, MX51_USBH1_PAD_CTRL)
-#define MX51_PAD_USBH1_DATA5__USBH1_DATA5       IOMUX_PAD(0x69C, 0x29C, 0, 0x0,   0, MX51_USBH1_PAD_CTRL)
-#define MX51_PAD_USBH1_DATA6__USBH1_DATA6       IOMUX_PAD(0x6A0, 0x2A0, 0, 0x0,   0, MX51_USBH1_PAD_CTRL)
-#define MX51_PAD_USBH1_DATA7__USBH1_DATA7       IOMUX_PAD(0x6A4, 0x2A4, 0, 0x0,   0, MX51_USBH1_PAD_CTRL)
-#define MX51_PAD_DI1_PIN11__GPIO_3_0            IOMUX_PAD(0x6A8, 0x2A8, 4, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_DI1_PIN12__GPIO_3_1            IOMUX_PAD(0x6AC, 0x2AC, 4, 0x978, 1, NO_PAD_CTRL)
-#define MX51_PAD_DI1_PIN13__GPIO_3_2            IOMUX_PAD(0x6B0, 0x2B0, 4, 0x97c, 1, NO_PAD_CTRL)
-#define MX51_PAD_DI1_D0_CS__GPIO_3_3            IOMUX_PAD(0x6B4, 0x2B4, 4, 0x980, 1, NO_PAD_CTRL)
-#define MX51_PAD_DI1_D1_CS__GPIO_3_4            IOMUX_PAD(0x6B8, 0x2B8, 4, 0x984, 1, NO_PAD_CTRL)
-#define MX51_PAD_DISPB2_SER_DIN__GPIO_3_5       IOMUX_PAD(0x6BC, 0x2BC, 4, 0x988, 1, NO_PAD_CTRL)
-#define MX51_PAD_DISPB2_SER_DIO__GPIO_3_6       IOMUX_PAD(0x6C0, 0x2C0, 4, 0x98c, 1, NO_PAD_CTRL)
-#define MX51_PAD_DISPB2_SER_CLK__GPIO_3_7       IOMUX_PAD(0x6C4, 0x2C4, 4, 0x990, 1, NO_PAD_CTRL)
-#define MX51_PAD_DISPB2_SER_RS__GPIO_3_8        IOMUX_PAD(0x6C8, 0x2C8, 4, 0x994, 1, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT0__DISP1_DAT0         IOMUX_PAD(0x6CC, 0x2CC, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT1__DISP1_DAT1         IOMUX_PAD(0x6D0, 0x2D0, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT2__DISP1_DAT2         IOMUX_PAD(0x6D4, 0x2D4, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT3__DISP1_DAT3         IOMUX_PAD(0x6D8, 0x2D8, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT4__DISP1_DAT4         IOMUX_PAD(0x6DC, 0x2DC, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT5__DISP1_DAT5         IOMUX_PAD(0x6E0, 0x2E0, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT6__DISP1_DAT6         IOMUX_PAD(0x6E4, 0x2E4, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT7__DISP1_DAT7         IOMUX_PAD(0x6E8, 0x2E8, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT8__DISP1_DAT8         IOMUX_PAD(0x6EC, 0x2EC, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT9__DISP1_DAT9         IOMUX_PAD(0x6F0, 0x2F0, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT10__DISP1_DAT10       IOMUX_PAD(0x6F4, 0x2F4, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT11__DISP1_DAT11       IOMUX_PAD(0x6F8, 0x2F8, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT12__DISP1_DAT12       IOMUX_PAD(0x6FC, 0x2FC, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT13__DISP1_DAT13       IOMUX_PAD(0x700, 0x300, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT14__DISP1_DAT14       IOMUX_PAD(0x704, 0x304, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT15__DISP1_DAT15       IOMUX_PAD(0x708, 0x308, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT16__DISP1_DAT16       IOMUX_PAD(0x70C, 0x30C, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT17__DISP1_DAT17       IOMUX_PAD(0x710, 0x310, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT18__DISP1_DAT18       IOMUX_PAD(0x714, 0x314, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT19__DISP1_DAT19       IOMUX_PAD(0x718, 0x318, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT20__DISP1_DAT20       IOMUX_PAD(0x71C, 0x31C, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT21__DISP1_DAT21       IOMUX_PAD(0x720, 0x320, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT22__DISP1_DAT22       IOMUX_PAD(0x724, 0x324, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT23__DISP1_DAT23       IOMUX_PAD(0x728, 0x328, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_DI1_PIN3__DI1_PIN3             IOMUX_PAD(0x72C, 0x32C, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_DI1_PIN2__DI1_PIN2             IOMUX_PAD(0x734, 0x330, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_DI_GP1__DI_GP1                 IOMUX_PAD(0x73C, 0x334, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_DI_GP2__DI_GP2                 IOMUX_PAD(0x740, 0x338, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_DI_GP3__DI_GP3                 IOMUX_PAD(0x744, 0x33C, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_DI2_PIN4__DI2_PIN4             IOMUX_PAD(0x748, 0x340, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_DI2_PIN2__DI2_PIN2             IOMUX_PAD(0x74C, 0x344, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_DI2_PIN3__DI2_PIN3             IOMUX_PAD(0x750, 0x348, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_DI2_DISP_CLK__DI2_DISP_CLK     IOMUX_PAD(0x754, 0x34C, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_DI_GP4__DI_GP4                 IOMUX_PAD(0x758, 0x350, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT0__DISP2_DAT0         IOMUX_PAD(0x75C, 0x354, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT1__DISP2_DAT1         IOMUX_PAD(0x760, 0x358, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT2__DISP2_DAT2         IOMUX_PAD(0x764, 0x35C, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT3__DISP2_DAT3         IOMUX_PAD(0x768, 0x360, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT4__DISP2_DAT4         IOMUX_PAD(0x76C, 0x364, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT5__DISP2_DAT5         IOMUX_PAD(0x770, 0x368, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT6__GPIO_1_19          IOMUX_PAD(0x774, 0x36C, 5, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT7__GPIO_1_29          IOMUX_PAD(0x778, 0x370, 5, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT8__GPIO_1_30          IOMUX_PAD(0x77C, 0x374, 5, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT9__GPIO_1_31          IOMUX_PAD(0x780, 0x378, 5, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT10__DISP2_DAT10       IOMUX_PAD(0x784, 0x37C, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT11__DISP2_DAT11       IOMUX_PAD(0x788, 0x380, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT12__DISP2_DAT12       IOMUX_PAD(0x78C, 0x384, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT13__DISP2_DAT13       IOMUX_PAD(0x790, 0x388, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT14__DISP2_DAT14       IOMUX_PAD(0x794, 0x38C, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT15__DISP2_DAT15       IOMUX_PAD(0x798, 0x390, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_SD1_CMD__SD1_CMD		IOMUX_PAD(0x79C, 0x394, IOMUX_CONFIG_SION, 0x0, 0, \
-							MX51_SDHCI_PAD_CTRL)
-#define MX51_PAD_SD1_CMD__AUD5_RXFS             IOMUX_PAD(0x79C, 0x394, 1, 0x8e0, 1, NO_PAD_CTRL)
-#define MX51_PAD_SD1_CLK__SD1_CLK		IOMUX_PAD(0x7A0, 0x398, IOMUX_CONFIG_SION, 0x0, 0, \
-							MX51_SDHCI_PAD_CTRL | PAD_CTL_HYS)
-#define MX51_PAD_SD1_CLK__AUD5_RXC              IOMUX_PAD(0x7A0, 0x398, 1, 0x8dc, 1, NO_PAD_CTRL)
-#define MX51_PAD_SD1_DATA0__SD1_DATA0		IOMUX_PAD(0x7A4, 0x39C, IOMUX_CONFIG_SION, 0x0, 0, \
-							MX51_SDHCI_PAD_CTRL)
-#define MX51_PAD_SD1_DATA0__AUD5_TXD            IOMUX_PAD(0x7A4, 0x39C, 1, 0x8d8, 2, NO_PAD_CTRL)
-#define MX51_PAD_SD1_DATA1__SD1_DATA1		IOMUX_PAD(0x7A8, 0x3A0, IOMUX_CONFIG_SION, 0x0, 0, \
-							MX51_SDHCI_PAD_CTRL)
-#define MX51_PAD_SD1_DATA1__AUD5_RXD            IOMUX_PAD(0x7A8, 0x3A0, 1, 0x8d4, 2, NO_PAD_CTRL)
-#define MX51_PAD_SD1_DATA2__SD1_DATA2		IOMUX_PAD(0x7AC, 0x3A4, IOMUX_CONFIG_SION, 0x0, 0, \
-							MX51_SDHCI_PAD_CTRL)
-#define MX51_PAD_SD1_DATA2__AUD5_TXC            IOMUX_PAD(0x7AC, 0x3A4, 1, 0x8e4, 2, NO_PAD_CTRL)
-#define MX51_PAD_SD1_DATA3__SD1_DATA3		IOMUX_PAD(0x7B0, 0x3A8, IOMUX_CONFIG_SION, 0x0, 0, \
-							MX51_SDHCI_PAD_CTRL)
-#define MX51_PAD_SD1_DATA3__AUD5_TXFS           IOMUX_PAD(0x7B0, 0x3A8, 1, 0x8e8, 2, NO_PAD_CTRL)
-#define MX51_PAD_SD2_CMD__SD2_CMD		IOMUX_PAD(0x7BC, 0x3B4, IOMUX_CONFIG_SION, 0x0, 1, \
-							MX51_SDHCI_PAD_CTRL)
-#define MX51_PAD_SD2_CLK__SD2_CLK		IOMUX_PAD(0x7C0, 0x3B8, IOMUX_CONFIG_SION, 0x0, 0, \
-							MX51_SDHCI_PAD_CTRL | PAD_CTL_HYS)
-#define MX51_PAD_SD2_DATA0__SD2_DATA0		IOMUX_PAD(0x7C4, 0x3BC, IOMUX_CONFIG_SION, 0x0, 0, \
-							MX51_SDHCI_PAD_CTRL)
-#define MX51_PAD_SD2_DATA1__SD2_DATA1		IOMUX_PAD(0x7C8, 0x3C0, IOMUX_CONFIG_SION, 0x0, 0, \
-							MX51_SDHCI_PAD_CTRL)
-#define MX51_PAD_SD2_DATA2__SD2_DATA2		IOMUX_PAD(0x7CC, 0x3C4, IOMUX_CONFIG_SION, 0x0, 0, \
-							MX51_SDHCI_PAD_CTRL)
-#define MX51_PAD_SD2_DATA3__SD2_DATA3		IOMUX_PAD(0x7D0, 0x3C8, IOMUX_CONFIG_SION, 0x0, 0, \
-							MX51_SDHCI_PAD_CTRL)
-#define MX51_PAD_GPIO_1_0__GPIO_1_0		IOMUX_PAD(0x7B4, 0x3AC, 1, 0x0,   0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_GPIO_1_1__GPIO_1_1		IOMUX_PAD(0x7B8, 0x3B0, 1, 0x0,   0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_GPIO_1_2__GPIO_1_2		IOMUX_PAD(0x7D4, 0x3CC, 1, 0x0,   0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_GPIO_1_2__I2C2_SCL		IOMUX_PAD(0x7D4, 0x3CC, (2 | IOMUX_CONFIG_SION), \
-							0x9b8,   3, MX51_I2C_PAD_CTRL)
-#define MX51_PAD_GPIO_1_3__GPIO_1_3		IOMUX_PAD(0x7D8, 0x3D0, 1, 0x0,   0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_GPIO_1_3__I2C2_SDA		IOMUX_PAD(0x7D8, 0x3D0, (2 | IOMUX_CONFIG_SION), \
-							0x9bc,   3, MX51_I2C_PAD_CTRL)
-#define MX51_PAD_PMIC_INT_REQ__PMIC_INT_REQ	IOMUX_PAD(0x7FC, 0x3D4, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_GPIO_1_4__GPIO_1_4		IOMUX_PAD(0x804, 0x3D8, 1, 0x0,   0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_GPIO_1_5__GPIO_1_5		IOMUX_PAD(0x808, 0x3DC, 1, 0x0,   0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_GPIO_1_6__GPIO_1_6		IOMUX_PAD(0x80C, 0x3E0, 1, 0x0,   0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_GPIO_1_7__GPIO_1_7		IOMUX_PAD(0x810, 0x3E4, 1, 0x0,   0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_GPIO_1_8__GPIO_1_8		IOMUX_PAD(0x814, 0x3E8, 1, 0x0,   0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_GPIO_1_9__GPIO_1_9		IOMUX_PAD(0x818, 0x3EC, 1, 0x0,   0, MX51_GPIO_PAD_CTRL)
+/* 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, 0x09ec, 3, 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, 0x09ec, 5, 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 | \
+		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(NO_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(NO_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(NO_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(NO_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(NO_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(NO_PAD_CTRL))
+#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(NO_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(NO_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(NO_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(NO_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(NO_PAD_CTRL))
+#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(NO_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(NO_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(NO_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(NO_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(NO_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(NO_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(NO_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(NO_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(NO_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))
 
 #endif /* __MACH_IOMUX_MX51_H__ */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/include/mach/iomux-mx53.h linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/include/mach/iomux-mx53.h
--- linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/include/mach/iomux-mx53.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/include/mach/iomux-mx53.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,325 @@
+/*
+ * 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.
+ */
+
+#ifndef __MACH_IOMUX_MX53_H__
+#define __MACH_IOMUX_MX53_H__
+
+#include <mach/iomux-v3.h>
+
+/*
+ * various IOMUX alternate output functions (1-7)
+ */
+typedef enum iomux_config {
+	IOMUX_CONFIG_ALT0,
+	IOMUX_CONFIG_ALT1,
+	IOMUX_CONFIG_ALT2,
+	IOMUX_CONFIG_ALT3,
+	IOMUX_CONFIG_ALT4,
+	IOMUX_CONFIG_ALT5,
+	IOMUX_CONFIG_ALT6,
+	IOMUX_CONFIG_ALT7,
+	IOMUX_CONFIG_GPIO, /* added to help user use GPIO mode */
+} iomux_pin_cfg_t;
+
+/* 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_MUX_I	0x00
+#define NON_PAD_I	0x00
+
+#define MX53_UART_PAD_CTRL		(PAD_CTL_PKE | PAD_CTL_PUE |	\
+		PAD_CTL_DSE_HIGH | PAD_CTL_SRE_FAST | PAD_CTL_HYS)
+/* UART1 */
+#define MX53_PAD_CSI0_D10__UART1_TXD	IOMUX_PAD(0x414, 0xE8, 2, 0x0, 0, MX53_UART_PAD_CTRL)
+#define MX53_PAD_CSI0_D11__UART1_RXD	IOMUX_PAD(0x418, 0xEC, 2, 0x878, 1, MX53_UART_PAD_CTRL)
+#define MX53_PAD_ATA_DIOW__UART1_TXD	IOMUX_PAD(0x5F0, 0x270, 3, 0x0,	0, MX53_UART_PAD_CTRL)
+#define MX53_PAD_ATA_DMACK__UART1_RXD	IOMUX_PAD(0x5F4, 0x274, 3, 0x880, 3, MX53_UART_PAD_CTRL)
+
+/* UART2 */
+#define MX53_PAD_ATA_BUFFER_EN__UART2_RXD	IOMUX_PAD(0x5FC, 0x27C, 3, 0x880, 3, MX53_UART_PAD_CTRL)
+#define MX53_PAD_ATA_DMARQ__UART2_TXD	IOMUX_PAD(0x5F8, 0x278, 3, 0x0, 0, MX53_UART_PAD_CTRL)
+#define MX53_PAD_ATA_DIOR__UART2_RTS	IOMUX_PAD(0x604, 0x284, 3, 0x87C, 3, MX53_UART_PAD_CTRL)
+#define MX53_PAD_ATA_INTRQ__UART2_CTS	IOMUX_PAD(0x600, 0x280, 3, 0x0, 0, MX53_UART_PAD_CTRL)
+
+/* UART3 */
+#define MX53_PAD_ATA_CS_0__UART3_TXD	IOMUX_PAD(0x61C, 0x29C, 4, 0x0, 0, MX53_UART_PAD_CTRL)
+#define MX53_PAD_ATA_CS_1__UART3_RXD	IOMUX_PAD(0x620, 0x2A0, 4, 0x888, 3, MX53_UART_PAD_CTRL)
+#define MX53_PAD_ATA_DA_1__UART3_CTS	IOMUX_PAD(0x614, 0x294, 4, 0x0, 0, MX53_UART_PAD_CTRL)
+#define MX53_PAD_ATA_DA_2__UART3_RTS	IOMUX_PAD(0x618, 0x298, 4, 0x884, 5, MX53_UART_PAD_CTRL)
+
+#define MX53_PAD_GPIO_19__GPIO_4_5		IOMUX_PAD(0x348, 0x20,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL0__GPIO_4_6		IOMUX_PAD(0x34C, 0x24,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW0__GPIO_4_7		IOMUX_PAD(0x350, 0x28,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL1__GPIO_4_8		IOMUX_PAD(0x354, 0x2C,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW1__GPIO_4_9		IOMUX_PAD(0x358, 0x30,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL2__GPIO_4_10		IOMUX_PAD(0x35C, 0x34,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW2__GPIO_4_11	IOMUX_PAD(0x360, 0x38,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL3__GPIO_4_12		IOMUX_PAD(0x364, 0x3C,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW3__GPIO_4_13	IOMUX_PAD(0x368, 0x40,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL4__GPIO_4_14		IOMUX_PAD(0x36C, 0x44,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW4__GPIO_4_15	IOMUX_PAD(0x370, 0x48,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_NVCC_KEYPAD__NVCC_KEYPAD	IOMUX_PAD(0x374, NON_MUX_I,IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_DISP_CLK__GPIO_4_16	IOMUX_PAD(0x378, 0x4C,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN15__GPIO_4_17	IOMUX_PAD(0x37C, 0x50,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN2__GPIO_4_18		IOMUX_PAD(0x380, 0x54,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN3__GPIO_4_19		IOMUX_PAD(0x384, 0x58,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN4__GPIO_4_20		IOMUX_PAD(0x388, 0x5C,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT0__GPIO_4_21	IOMUX_PAD(0x38C, 0x60,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT1__GPIO_4_22	IOMUX_PAD(0x390, 0x64,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT2__GPIO_4_23	IOMUX_PAD(0x394, 0x68,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT3__GPIO_4_24	IOMUX_PAD(0x398, 0x6C,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT4__GPIO_4_25	IOMUX_PAD(0x39C, 0x70,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT5__GPIO_4_26	IOMUX_PAD(0x3A0, 0x74,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT6__GPIO_4_27	IOMUX_PAD(0x3A4, 0x78,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT7__GPIO_4_28	IOMUX_PAD(0x3A8, 0x7C,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT8__GPIO_4_29	IOMUX_PAD(0x3AC, 0x80,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT9__GPIO_4_30	IOMUX_PAD(0x3B0, 0x84,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT10__GPIO_4_31	IOMUX_PAD(0x3B4, 0x88,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT11__GPIO_5_5	IOMUX_PAD(0x3B8, 0x8C,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT12__GPIO_5_6	IOMUX_PAD(0x3BC, 0x90,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT13__GPIO_5_7	IOMUX_PAD(0x3C0, 0x94,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT14__GPIO_5_8	IOMUX_PAD(0x3C4, 0x98,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT15__GPIO_5_9	IOMUX_PAD(0x3C8, 0x9C,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT16__GPIO_5_10	IOMUX_PAD(0x3CC, 0xA0,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT17__GPIO_5_11	IOMUX_PAD(0x3D0, 0xA4,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT18__GPIO_5_12	IOMUX_PAD(0x3D4, 0xA8,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT19__GPIO_5_13	IOMUX_PAD(0x3D8, 0xAC,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT20__GPIO_5_14	IOMUX_PAD(0x3DC, 0xB0,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT21__GPIO_5_15	IOMUX_PAD(0x3E0, 0xB4,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT22__GPIO_5_16	IOMUX_PAD(0x3E4, 0xB8,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT23__GPIO_5_17	IOMUX_PAD(0x3E8, 0xBC,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_PIXCLK__GPIO_5_18	IOMUX_PAD(0x3EC, 0xC0,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_MCLK__GPIO_5_19	IOMUX_PAD(0x3F0, 0xC4,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DATA_EN__GPIO_5_20	IOMUX_PAD(0x3F4, 0xC8,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_VSYNC__GPIO_5_21	IOMUX_PAD(0x3F8, 0xCC,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_D4__GPIO_5_22		IOMUX_PAD(0x3FC, 0xD0,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_D5__GPIO_5_23		IOMUX_PAD(0x400, 0xD4,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_D6__GPIO_5_24		IOMUX_PAD(0x404, 0xD8,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_D7__GPIO_5_25		IOMUX_PAD(0x408, 0xDC,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_D8__GPIO_5_26		IOMUX_PAD(0x40C, 0xE0,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_D9__GPIO_5_27		IOMUX_PAD(0x410, 0xE4,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_D10__GPIO_5_28		IOMUX_PAD(0x414, 0xE8,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_D11__GPIO_5_29		IOMUX_PAD(0x418, 0xEC,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_D12__GPIO_5_30		IOMUX_PAD(0x41C, 0xF0,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_D13__GPIO_5_31		IOMUX_PAD(0x420, 0xF4,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_D14__GPIO_6_0		IOMUX_PAD(0x424, 0xF8,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_D15__GPIO_6_1		IOMUX_PAD(0x428, 0xFC,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_D16__GPIO_6_2		IOMUX_PAD(0x42C, 0x100,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_D17__GPIO_6_3		IOMUX_PAD(0x430, 0x104,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_D18__GPIO_6_4		IOMUX_PAD(0x434, 0x108,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_D19__GPIO_6_5		IOMUX_PAD(0x438, 0x10C,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_NVCC_CSI0__NVCC_CSI0	IOMUX_PAD(0x43C, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_JTAG_TMS__JTAG_TMS		IOMUX_PAD(0x440, NON_MUX_I,IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_JTAG_MOD__JTAG_MOD		IOMUX_PAD(0x444, NON_MUX_I,IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_JTAG_TRSTB__JTAG_TRSTB	IOMUX_PAD(0x448, NON_MUX_I,IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_JTAG_TDI__JTAG_TDI		IOMUX_PAD(0x44C, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_JTAG_TCK__JTAG_TCK		IOMUX_PAD(0x450, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_JTAG_TDO__JTAG_TDO		IOMUX_PAD(0x454, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A25__GPIO_5_2		IOMUX_PAD(0x458, 0x110,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_EB2__GPIO_2_30		IOMUX_PAD(0x45C, 0x114,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D16__GPIO_3_16		IOMUX_PAD(0x460, 0x118,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D17__GPIO_3_17		IOMUX_PAD(0x464, 0x11C,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D18__GPIO_3_18		IOMUX_PAD(0x468, 0x120,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D16__CSPI1_SCLK		IOMUX_PAD(0x460, 0x118,IOMUX_CONFIG_ALT4, 0x79c, 3, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D17__CSPI1_MISO		IOMUX_PAD(0x464, 0x11C,IOMUX_CONFIG_ALT4, 0x7a0, 3, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D18__CSPI1_MOSI		IOMUX_PAD(0x468, 0x120,IOMUX_CONFIG_ALT4, 0x7a4, 3, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D19__GPIO_3_19		IOMUX_PAD(0x46C, 0x124,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D20__GPIO_3_20		IOMUX_PAD(0x470, 0x128,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D21__GPIO_3_21		IOMUX_PAD(0x474, 0x12C,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D22__GPIO_3_22		IOMUX_PAD(0x478, 0x130,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D23__GPIO_3_23		IOMUX_PAD(0x47C, 0x134,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_EB3__GPIO_2_31		IOMUX_PAD(0x480, 0x138,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D24__GPIO_3_24		IOMUX_PAD(0x484, 0x13C,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D25__GPIO_3_25		IOMUX_PAD(0x488, 0x140,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D26__GPIO_3_26		IOMUX_PAD(0x48C, 0x144,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D27__GPIO_3_27		IOMUX_PAD(0x490, 0x148,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D28__GPIO_3_28		IOMUX_PAD(0x494, 0x14C,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D29__GPIO_3_29		IOMUX_PAD(0x498, 0x150,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D30__GPIO_3_30		IOMUX_PAD(0x49C, 0x154,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D31__GPIO_3_31		IOMUX_PAD(0x4A0, 0x158,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_NVCC_EIM1__NVCC_EIM1	IOMUX_PAD(0x4A4, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A24__GPIO_5_4		IOMUX_PAD(0x4A8, 0x15C,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A23__GPIO_6_6		IOMUX_PAD(0x4AC, 0x160,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A22__GPIO_2_16		IOMUX_PAD(0x4B0, 0x164,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A21__GPIO_2_17		IOMUX_PAD(0x4B4, 0x168,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A20__GPIO_2_18		IOMUX_PAD(0x4B8, 0x16C,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A19__GPIO_2_19		IOMUX_PAD(0x4BC, 0x170,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A18__GPIO_2_20		IOMUX_PAD(0x4C0, 0x174,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A17__GPIO_2_21		IOMUX_PAD(0x4C4, 0x178,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A16__GPIO_2_22		IOMUX_PAD(0x4C8, 0x17C,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_CS0__GPIO_2_23		IOMUX_PAD(0x4CC, 0x180,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_CS1__GPIO_2_24		IOMUX_PAD(0x4D0, 0x184,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_OE__GPIO_2_25		IOMUX_PAD(0x4D4, 0x188,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_RW__GPIO_2_26		IOMUX_PAD(0x4D8, 0x18C,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_LBA__GPIO_2_27		IOMUX_PAD(0x4DC, 0x190,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_NVCC_EIM4__NVCC_EIM4	IOMUX_PAD(0x4E0, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_EB0__GPIO_2_28		IOMUX_PAD(0x4E4, 0x194,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_EB1__GPIO_2_29		IOMUX_PAD(0x4E8, 0x198,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA0__GPIO_3_0		IOMUX_PAD(0x4EC, 0x19C,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA1__GPIO_3_1		IOMUX_PAD(0x4F0, 0x1A0,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA2__GPIO_3_2		IOMUX_PAD(0x4F4, 0x1A4,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA3__GPIO_3_3		IOMUX_PAD(0x4F8, 0x1A8,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA4__GPIO_3_4		IOMUX_PAD(0x4FC, 0x1AC,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA5__GPIO_3_5		IOMUX_PAD(0x500, 0x1B0,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA6__GPIO_3_6		IOMUX_PAD(0x504, 0x1B4,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA7__GPIO_3_7		IOMUX_PAD(0x508, 0x1B8,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA8__GPIO_3_8		IOMUX_PAD(0x50C, 0x1BC,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA9__GPIO_3_9		IOMUX_PAD(0x510, 0x1C0,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA10__GPIO_3_10		IOMUX_PAD(0x514, 0x1C4,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA11__GPIO_3_11		IOMUX_PAD(0x518, 0x1C8,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA12__GPIO_3_12		IOMUX_PAD(0x51C, 0x1CC,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA13__GPIO_3_13		IOMUX_PAD(0x520, 0x1D0,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA14__GPIO_3_14		IOMUX_PAD(0x524, 0x1D4,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA15__GPIO_3_15		IOMUX_PAD(0x528, 0x1D8,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_WE_B__GPIO_6_12	IOMUX_PAD(0x52C, 0x1DC,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_RE_B__GPIO_6_13	IOMUX_PAD(0x530, 0x1E0,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_WAIT__GPIO_5_0		IOMUX_PAD(0x534, 0x1E4,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_BCLK__EIM_BCLK		IOMUX_PAD(0x538, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_NVCC_EIM7__NVCC_EIM7	IOMUX_PAD(0x53C, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_LVDS1_TX3_P__GPIO_6_22	IOMUX_PAD(NON_PAD_I, 0x1EC, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_LVDS1_TX2_P__GPIO_6_24	IOMUX_PAD(NON_PAD_I, 0x1F0, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_LVDS1_CLK_P__GPIO_6_26	IOMUX_PAD(NON_PAD_I, 0x1F4, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_LVDS1_TX1_P__GPIO_6_28	IOMUX_PAD(NON_PAD_I, 0x1F8, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_LVDS1_TX0_P__GPIO_6_30	IOMUX_PAD(NON_PAD_I, 0x1FC, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_LVDS0_TX3_P__GPIO_7_22	IOMUX_PAD(NON_PAD_I, 0x200, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_LVDS0_CLK_P__GPIO_7_24	IOMUX_PAD(NON_PAD_I, 0x204, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_LVDS0_TX2_P__GPIO_7_26	IOMUX_PAD(NON_PAD_I, 0x208, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_LVDS0_TX1_P__GPIO_7_28	IOMUX_PAD(NON_PAD_I, 0x20C, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_LVDS0_TX0_P__GPIO_7_30	IOMUX_PAD(NON_PAD_I, 0x210, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_10__GPIO_4_0		IOMUX_PAD(0x540, 0x214, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_11__GPIO_4_1		IOMUX_PAD(0x544, 0x218, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_12__GPIO_4_2		IOMUX_PAD(0x548, 0x21C, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_13__GPIO_4_3		IOMUX_PAD(0x54C, 0x220, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_14__GPIO_4_4		IOMUX_PAD(0x550, 0x224, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_DRAM_DQM3__DRAM_DQM3	IOMUX_PAD(0x554, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_DRAM_SDQS3__DRAM_SDQS3	IOMUX_PAD(0x558, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_DRAM_SDCKE1__DRAM_SDCKE1	IOMUX_PAD(0x55C, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_DRAM_DQM2__DRAM_DQM2	IOMUX_PAD(0x560, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_DRAM_SDODT1__DRAM_SDODT1	IOMUX_PAD(0x564, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_DRAM_SDQS2__DRAM_SDQS2	IOMUX_PAD(0x568, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_DRAM_RESET__DRAM_RESET	IOMUX_PAD(0x56C, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_DRAM_SDCLK1__DRAM_SDCLK1	IOMUX_PAD(0x570, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_DRAM_CAS__DRAM_CAS		IOMUX_PAD(0x574, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_DRAM_SDCLK0__DRAM_SDCLK0	IOMUX_PAD(0x578, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_DRAM_SDQS0__DRAM_SDQS0	IOMUX_PAD(0x57C, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_DRAM_SDODT0__DRAM_SDODT0	IOMUX_PAD(0x580, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_DRAM_DQM0__DRAM_DQM0	IOMUX_PAD(0x584, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_DRAM_RAS__DRAM_RAS		IOMUX_PAD(0x588, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_DRAM_SDCKE0__DRAM_SDCKE0	IOMUX_PAD(0x58C, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_DRAM_SDQS1__DRAM_SDQS1	IOMUX_PAD(0x590, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_DRAM_DQM1__DRAM_DQM1	IOMUX_PAD(0x594, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_PMIC_ON_REQ__PMIC_ON_REQ	IOMUX_PAD(0x598, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_PMIC_STBY_REQ__PMIC_STBY_REQ	IOMUX_PAD(0x59C, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CLE__GPIO_6_7		IOMUX_PAD(0x5A0, 0x228,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_ALE__GPIO_6_8	IOMUX_PAD(0x5A4, 0x22C,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_WP_B__GPIO_6_9	IOMUX_PAD(0x5A8, 0x230,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_RB0__GPIO_6_10	IOMUX_PAD(0x5AC, 0x234,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CS0__GPIO_6_11	IOMUX_PAD(0x5B0, 0x238,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CS1__GPIO_6_14	IOMUX_PAD(0x5B4, 0x23C,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CS2__GPIO_6_15	IOMUX_PAD(0x5B8, 0x240,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CS3__GPIO_6_16	IOMUX_PAD(0x5BC, 0x244,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_NVCC_NANDF__NVCC_NANDF	IOMUX_PAD(0x5C0, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_MDIO__GPIO_1_22		IOMUX_PAD(0x5C4, 0x248,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_REF_CLK__GPIO_1_23	IOMUX_PAD(0x5C8, 0x24C,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_RX_ER__GPIO_1_24	IOMUX_PAD(0x5CC, 0x250,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_CRS_DV__GPIO_1_25	IOMUX_PAD(0x5D0, 0x254,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_RXD1__GPIO_1_26		IOMUX_PAD(0x5D4, 0x258,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_RXD0__GPIO_1_27		IOMUX_PAD(0x5D8, 0x25C,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_TX_EN__GPIO_1_28	IOMUX_PAD(0x5DC, 0x260,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_TXD1__GPIO_1_29		IOMUX_PAD(0x5E0, 0x264,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_TXD0__GPIO_1_30		IOMUX_PAD(0x5E4, 0x268,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_MDC__GPIO_1_31		IOMUX_PAD(0x5E8, 0x26C,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_NVCC_FEC__NVCC_FEC		IOMUX_PAD(0x5EC, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_ATA_DIOW__GPIO_6_17	IOMUX_PAD(0x5F0, 0x270,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_ATA_DMACK__GPIO_6_18	IOMUX_PAD(0x5F4, 0x274,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_ATA_DMARQ__GPIO_7_0	IOMUX_PAD(0x5F8, 0x278,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_ATA_BUFFER_EN__GPIO_7_1	IOMUX_PAD(0x5FC, 0x27C,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_ATA_INTRQ__GPIO_7_2		IOMUX_PAD(0x600, 0x280,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_ATA_DIOR__GPIO_7_3		IOMUX_PAD(0x604, 0x284,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_ATA_RESET_B__GPIO_7_4	IOMUX_PAD(0x608, 0x288,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_ATA_IORDY__GPIO_7_5		IOMUX_PAD(0x60C, 0x28C,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_ATA_DA_0__GPIO_7_6		IOMUX_PAD(0x610, 0x290,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_ATA_DA_1__GPIO_7_7		IOMUX_PAD(0x614, 0x294,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_ATA_DA_2__GPIO_7_8		IOMUX_PAD(0x618, 0x298,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_ATA_CS_0__GPIO_7_9		IOMUX_PAD(0x61C, 0x29C,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_ATA_CS_1__GPIO_7_10		IOMUX_PAD(0x620, 0x2A0,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_NVCC_ATA2__NVCC_ATA2	IOMUX_PAD(0x624, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_ATA_DATA0__GPIO_2_0	IOMUX_PAD(0x628, 0x2A4,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_ATA_DATA1__GPIO_2_1	IOMUX_PAD(0x62C, 0x2A8,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_ATA_DATA2__GPIO_2_2	IOMUX_PAD(0x630, 0x2AC,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_ATA_DATA3__GPIO_2_3	IOMUX_PAD(0x634, 0x2B0,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_ATA_DATA4__GPIO_2_4	IOMUX_PAD(0x638, 0x2B4,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_ATA_DATA5__GPIO_2_5	IOMUX_PAD(0x63C, 0x2B8,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_ATA_DATA6__GPIO_2_6	IOMUX_PAD(0x640, 0x2BC,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_ATA_DATA7__GPIO_2_7	IOMUX_PAD(0x644, 0x2C0,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_ATA_DATA8__GPIO_2_8	IOMUX_PAD(0x648, 0x2C4,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_ATA_DATA9__GPIO_2_9	IOMUX_PAD(0x64C, 0x2C8,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_ATA_DATA10__GPIO_2_10	IOMUX_PAD(0x650, 0x2CC,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_ATA_DATA11__GPIO_2_11	IOMUX_PAD(0x654, 0x2D0,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_ATA_DATA12__GPIO_2_12	IOMUX_PAD(0x658, 0x2D4,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_ATA_DATA13__GPIO_2_13	IOMUX_PAD(0x65C, 0x2D8,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_ATA_DATA14__GPIO_2_14	IOMUX_PAD(0x660, 0x2DC,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_ATA_DATA15__GPIO_2_15	IOMUX_PAD(0x664, 0x2E0,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_NVCC_ATA0__NVCC_ATA0	IOMUX_PAD(0x668, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD1_DATA0__GPIO_1_16	IOMUX_PAD(0x66C, 0x2E4,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD1_DATA1__GPIO_1_17	IOMUX_PAD(0x670, 0x2E8,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD1_CMD__GPIO_1_18		IOMUX_PAD(0x674, 0x2EC,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD1_DATA2__GPIO_1_19	IOMUX_PAD(0x678, 0x2F0,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD1_CLK__GPIO_1_20		IOMUX_PAD(0x67C, 0x2F4,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD1_DATA3__GPIO_1_21	IOMUX_PAD(0x680, 0x2F8,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_NVCC_SD1__NVCC_SD1		IOMUX_PAD(0x684, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD2_CLK__GPIO_1_10		IOMUX_PAD(0x688, 0x2FC,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD2_CMD__GPIO_1_11		IOMUX_PAD(0x68C, 0x300,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD2_DATA3__GPIO_1_12	IOMUX_PAD(0x690, 0x304,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD2_DATA2__GPIO_1_13	IOMUX_PAD(0x694, 0x308,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD2_DATA1__GPIO_1_14	IOMUX_PAD(0x698, 0x30C,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD2_DATA0__GPIO_1_15	IOMUX_PAD(0x69C, 0x310,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_NVCC_SD2__NVCC_SD2		IOMUX_PAD(0x6A0, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_0__GPIO_1_0		IOMUX_PAD(0x6A4, 0x314,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_1__GPIO_1_1		IOMUX_PAD(0x6A8, 0x318,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_9__GPIO_1_9		IOMUX_PAD(0x6AC, 0x31C,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_3__GPIO_1_3		IOMUX_PAD(0x6B0, 0x320,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_6__GPIO_1_6		IOMUX_PAD(0x6B4, 0x324,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_2__GPIO_1_2		IOMUX_PAD(0x6B8, 0x328,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_4__GPIO_1_4		IOMUX_PAD(0x6BC, 0x32C,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_5__GPIO_1_5		IOMUX_PAD(0x6C0, 0x330,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_7__GPIO_1_7		IOMUX_PAD(0x6C4, 0x334,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_8__GPIO_1_8		IOMUX_PAD(0x6C8, 0x338,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_16__GPIO_7_11		IOMUX_PAD(0x6CC, 0x33C,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_17__GPIO_7_12		IOMUX_PAD(0x6D0, 0x340,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_18__GPIO_7_13		IOMUX_PAD(0x6D4, 0x344,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_NVCC_GPIO__NVCC_GPIO	IOMUX_PAD(0x6D8, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_POR_B__POR_B			IOMUX_PAD(0x6DC, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_BOOT_MODE1__BOOT_MODE1	IOMUX_PAD(0x6E0, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_RESET_IN_B__RESET_IN_B	IOMUX_PAD(0x6E4, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_BOOT_MODE0__BOOT_MODE0	IOMUX_PAD(0x6E8, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_TEST_MODE__TEST_MODE	IOMUX_PAD(0x6EC, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_GRP_ADDDS__GRP_ADDDS	IOMUX_PAD(0x6F0, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_GRP_DDRMODE_CTL__GRP_DDRMODE_CTL	IOMUX_PAD(0x6F4, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_GRP_DDRPKE__GRP_DDRPKE	IOMUX_PAD(0x6FC, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_GRP_DDRPK__GRP_DDRPK	IOMUX_PAD(0x708, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_GRP_TERM_CTL3__GRP_TERM_CTL3	IOMUX_PAD(0x70C, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_GRP_DDRHYS__GRP_DDRHYS	IOMUX_PAD(0x710, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_GRP_DDRMODE__GRP_DDRMODE	IOMUX_PAD(0x714, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_GRP_B0DS__GRP_B0DS		IOMUX_PAD(0x718, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_GRP_B1DS__GRP_B1DS		IOMUX_PAD(0x71C, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_GRP_CTLDS__GRP_CTLDS	IOMUX_PAD(0x720, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_GRP_DDR_TYPE__GRP_DDR_TYPE	IOMUX_PAD(0x724, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_GRP_B2DS__GRP_B2DS		IOMUX_PAD(0x728, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_GRP_B3DS__GRP_B3DS		IOMUX_PAD(0x72C, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
+
+#endif	/* __MACH_IOMUX_MX53_H__ */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/include/mach/iomux-v3.h linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/include/mach/iomux-v3.h
--- linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/include/mach/iomux-v3.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/include/mach/iomux-v3.h	2011-03-14 21:20:32.000000000 -0400
@@ -42,28 +42,44 @@
  * If <padname> or <padmode> refers to a GPIO, it is named
  * GPIO_<unit>_<num>
  *
- */
+ * IOMUX/PAD Bit field definitions
+ *
+ * MUX_CTRL_OFS:	    0..11 (12)
+ * PAD_CTRL_OFS:	   12..23 (12)
+ * SEL_INPUT_OFS:	   24..35 (12)
+ * MUX_MODE + SION:	   36..40  (5)
+ * PAD_CTRL + NO_PAD_CTRL: 41..57 (17)
+ * SEL_INP:		   58..61  (4)
+ * reserved:		     63    (1)
+*/
 
-struct pad_desc {
-	unsigned mux_ctrl_ofs:12; /* IOMUXC_SW_MUX_CTL_PAD offset */
-	unsigned mux_mode:8;
-	unsigned pad_ctrl_ofs:12; /* IOMUXC_SW_PAD_CTRL offset */
-#define	NO_PAD_CTRL	(1 << 16)
-	unsigned pad_ctrl:17;
-	unsigned select_input_ofs:12; /* IOMUXC_SELECT_INPUT offset */
-	unsigned select_input:3;
-};
+typedef u64 iomux_v3_cfg_t;
 
-#define IOMUX_PAD(_pad_ctrl_ofs, _mux_ctrl_ofs, _mux_mode, _select_input_ofs, \
-		_select_input, _pad_ctrl)				\
-		{							\
-			.mux_ctrl_ofs     = _mux_ctrl_ofs,		\
-			.mux_mode         = _mux_mode,			\
-			.pad_ctrl_ofs     = _pad_ctrl_ofs,		\
-			.pad_ctrl         = _pad_ctrl,			\
-			.select_input_ofs = _select_input_ofs,		\
-			.select_input     = _select_input,		\
-		}
+#define MUX_CTRL_OFS_SHIFT	0
+#define MUX_CTRL_OFS_MASK	((iomux_v3_cfg_t)0xfff << MUX_CTRL_OFS_SHIFT)
+#define MUX_PAD_CTRL_OFS_SHIFT	12
+#define MUX_PAD_CTRL_OFS_MASK	((iomux_v3_cfg_t)0xfff << MUX_PAD_CTRL_OFS_SHIFT)
+#define MUX_SEL_INPUT_OFS_SHIFT	24
+#define MUX_SEL_INPUT_OFS_MASK	((iomux_v3_cfg_t)0xfff << MUX_SEL_INPUT_OFS_SHIFT)
+
+#define MUX_MODE_SHIFT		36
+#define MUX_MODE_MASK		((iomux_v3_cfg_t)0x1f << MUX_MODE_SHIFT)
+#define MUX_PAD_CTRL_SHIFT	41
+#define MUX_PAD_CTRL_MASK	((iomux_v3_cfg_t)0x1ffff << MUX_PAD_CTRL_SHIFT)
+#define NO_PAD_CTRL		((iomux_v3_cfg_t)1 << (MUX_PAD_CTRL_SHIFT + 16))
+#define MUX_SEL_INPUT_SHIFT	58
+#define MUX_SEL_INPUT_MASK	((iomux_v3_cfg_t)0xf << MUX_SEL_INPUT_SHIFT)
+
+#define MUX_PAD_CTRL(x)		((iomux_v3_cfg_t)(x) << MUX_PAD_CTRL_SHIFT)
+
+#define IOMUX_PAD(_pad_ctrl_ofs, _mux_ctrl_ofs, _mux_mode, _sel_input_ofs, \
+		_sel_input, _pad_ctrl)					\
+	(((iomux_v3_cfg_t)(_mux_ctrl_ofs) << MUX_CTRL_OFS_SHIFT) |	\
+		((iomux_v3_cfg_t)(_mux_mode) << MUX_MODE_SHIFT) |	\
+		((iomux_v3_cfg_t)(_pad_ctrl_ofs) << MUX_PAD_CTRL_OFS_SHIFT) | \
+		((iomux_v3_cfg_t)(_pad_ctrl) << MUX_PAD_CTRL_SHIFT) |	\
+		((iomux_v3_cfg_t)(_sel_input_ofs) << MUX_SEL_INPUT_OFS_SHIFT) | \
+		((iomux_v3_cfg_t)(_sel_input) << MUX_SEL_INPUT_SHIFT))
 
 /*
  * Use to set PAD control
@@ -89,6 +105,7 @@ struct pad_desc {
 #define PAD_CTL_SRE_FAST		(1 << 0)
 #define PAD_CTL_SRE_SLOW		(0 << 0)
 
+#define IOMUX_CONFIG_SION		(0x1 << 4)
 
 #define MX51_NUM_GPIO_PORT	4
 
@@ -107,13 +124,13 @@ struct pad_desc {
 /*
  * setups a single pad in the iomuxer
  */
-int mxc_iomux_v3_setup_pad(struct pad_desc *pad);
+int mxc_iomux_v3_setup_pad(iomux_v3_cfg_t pad);
 
 /*
  * setups mutliple pads
  * convenient way to call the above function with tables
  */
-int mxc_iomux_v3_setup_multiple_pads(struct pad_desc *pad_list, unsigned count);
+int mxc_iomux_v3_setup_multiple_pads(iomux_v3_cfg_t *pad_list, unsigned count);
 
 /*
  * Initialise the iomux controller
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/include/mach/irqs.h linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/include/mach/irqs.h
--- linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/include/mach/irqs.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/include/mach/irqs.h	2011-03-14 21:20:32.000000000 -0400
@@ -23,13 +23,17 @@
 #define MXC_GPIO_IRQ_START	MXC_INTERNAL_IRQS
 
 /* these are ordered by size to support multi-SoC kernels */
-#if defined CONFIG_ARCH_MX2
+#if defined CONFIG_ARCH_MX53
+#define MXC_GPIO_IRQS		(32 * 7)
+#elif defined CONFIG_ARCH_MX2
+#define MXC_GPIO_IRQS		(32 * 6)
+#elif defined CONFIG_ARCH_MX50
 #define MXC_GPIO_IRQS		(32 * 6)
 #elif defined CONFIG_ARCH_MX1
 #define MXC_GPIO_IRQS		(32 * 4)
 #elif defined CONFIG_ARCH_MX25
 #define MXC_GPIO_IRQS		(32 * 4)
-#elif defined CONFIG_ARCH_MX5
+#elif defined CONFIG_ARCH_MX51
 #define MXC_GPIO_IRQS		(32 * 4)
 #elif defined CONFIG_ARCH_MXC91231
 #define MXC_GPIO_IRQS		(32 * 4)
@@ -66,7 +70,7 @@ extern int imx_irq_set_priority(unsigned
 
 /* all normal IRQs can be FIQs */
 #define FIQ_START	0
-/* switch betwean IRQ and FIQ */
+/* switch between IRQ and FIQ */
 extern int mxc_set_irq_fiq(unsigned int irq, unsigned int type);
 
 #endif /* __ASM_ARCH_MXC_IRQS_H__ */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/include/mach/memory.h linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/include/mach/memory.h
--- linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/include/mach/memory.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/include/mach/memory.h	2011-03-14 21:20:32.000000000 -0400
@@ -16,7 +16,9 @@
 #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)
 #define MXC91231_PHYS_OFFSET	UL(0x90000000)
 
 #if !defined(CONFIG_RUNTIME_PHYS_OFFSET)
@@ -32,8 +34,12 @@
 #  define PHYS_OFFSET		MX3x_PHYS_OFFSET
 # elif defined CONFIG_ARCH_MXC91231
 #  define PHYS_OFFSET		MXC91231_PHYS_OFFSET
-# elif defined CONFIG_ARCH_MX5
+# elif defined CONFIG_ARCH_MX50
+#  define PHYS_OFFSET		MX50_PHYS_OFFSET
+# elif defined CONFIG_ARCH_MX51
 #  define PHYS_OFFSET		MX51_PHYS_OFFSET
+# elif defined CONFIG_ARCH_MX53
+#  define PHYS_OFFSET		MX53_PHYS_OFFSET
 # endif
 #endif
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/include/mach/mx1.h linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/include/mach/mx1.h
--- linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/include/mach/mx1.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/include/mach/mx1.h	2011-03-14 21:20:32.000000000 -0400
@@ -19,7 +19,6 @@
  */
 #define MX1_IO_BASE_ADDR	0x00200000
 #define MX1_IO_SIZE		SZ_1M
-#define MX1_IO_BASE_ADDR_VIRT	VMALLOC_END
 
 #define MX1_CS0_PHYS		0x10000000
 #define MX1_CS0_SIZE		0x02000000
@@ -66,6 +65,10 @@
 #define MX1_CCM_BASE_ADDR		(0x1B000 + MX1_IO_BASE_ADDR)
 #define MX1_SCM_BASE_ADDR		(0x1B804 + MX1_IO_BASE_ADDR)
 #define MX1_GPIO_BASE_ADDR		(0x1C000 + MX1_IO_BASE_ADDR)
+#define MX1_GPIO1_BASE_ADDR		(0x1C000 + MX1_IO_BASE_ADDR)
+#define MX1_GPIO2_BASE_ADDR		(0x1C100 + MX1_IO_BASE_ADDR)
+#define MX1_GPIO3_BASE_ADDR		(0x1C200 + MX1_IO_BASE_ADDR)
+#define MX1_GPIO4_BASE_ADDR		(0x1C300 + MX1_IO_BASE_ADDR)
 #define MX1_EIM_BASE_ADDR		(0x20000 + MX1_IO_BASE_ADDR)
 #define MX1_SDRAMC_BASE_ADDR		(0x21000 + MX1_IO_BASE_ADDR)
 #define MX1_MMA_BASE_ADDR		(0x22000 + MX1_IO_BASE_ADDR)
@@ -73,12 +76,12 @@
 #define MX1_CSI_BASE_ADDR		(0x24000 + MX1_IO_BASE_ADDR)
 
 /* macro to get at IO space when running virtually */
-#define MX1_IO_ADDRESS(x) (						\
-	IMX_IO_ADDRESS(x, MX1_IO))
+#define MX1_IO_P2V(x)			IMX_IO_P2V(x)
+#define MX1_IO_ADDRESS(x)		IOMEM(MX1_IO_P2V(x))
 
 /* fixed interrput numbers */
 #define MX1_INT_SOFTINT		0
-#define MX1_CSI_INT		6
+#define MX1_INT_CSI		6
 #define MX1_DSPA_MAC_INT	7
 #define MX1_DSPA_INT		8
 #define MX1_COMP_INT		9
@@ -115,13 +118,13 @@
 #define MX1_SSI_RX_INT		44
 #define MX1_SSI_RX_ERR_INT	45
 #define MX1_TOUCH_INT		46
-#define MX1_USBD_INT0		47
-#define MX1_USBD_INT1		48
-#define MX1_USBD_INT2		49
-#define MX1_USBD_INT3		50
-#define MX1_USBD_INT4		51
-#define MX1_USBD_INT5		52
-#define MX1_USBD_INT6		53
+#define MX1_INT_USBD0		47
+#define MX1_INT_USBD1		48
+#define MX1_INT_USBD2		49
+#define MX1_INT_USBD3		50
+#define MX1_INT_USBD4		51
+#define MX1_INT_USBD5		52
+#define MX1_INT_USBD6		53
 #define MX1_BTSYS_INT		55
 #define MX1_BTTIM_INT		56
 #define MX1_BTWUI_INT		57
@@ -164,134 +167,6 @@
  * to not break drivers/usb/gadget/imx_udc.  Should go
  * away after this driver uses the new name.
  */
-#define USBD_INT0		MX1_USBD_INT0
-
-#ifdef IMX_NEEDS_DEPRECATED_SYMBOLS
-/* these should go away */
-#define IMX_IO_PHYS MX1_IO_BASE_ADDR
-#define IMX_IO_SIZE MX1_IO_SIZE
-#define IMX_IO_BASE MX1_IO_BASE_ADDR_VIRT
-#define IMX_CS0_PHYS MX1_CS0_PHYS
-#define IMX_CS0_SIZE MX1_CS0_SIZE
-#define IMX_CS1_PHYS MX1_CS1_PHYS
-#define IMX_CS1_SIZE MX1_CS1_SIZE
-#define IMX_CS2_PHYS MX1_CS2_PHYS
-#define IMX_CS2_SIZE MX1_CS2_SIZE
-#define IMX_CS3_PHYS MX1_CS3_PHYS
-#define IMX_CS3_SIZE MX1_CS3_SIZE
-#define IMX_CS4_PHYS MX1_CS4_PHYS
-#define IMX_CS4_SIZE MX1_CS4_SIZE
-#define IMX_CS5_PHYS MX1_CS5_PHYS
-#define IMX_CS5_SIZE MX1_CS5_SIZE
-#define AIPI1_BASE_ADDR MX1_AIPI1_BASE_ADDR
-#define WDT_BASE_ADDR MX1_WDT_BASE_ADDR
-#define TIM1_BASE_ADDR MX1_TIM1_BASE_ADDR
-#define TIM2_BASE_ADDR MX1_TIM2_BASE_ADDR
-#define RTC_BASE_ADDR MX1_RTC_BASE_ADDR
-#define LCDC_BASE_ADDR MX1_LCDC_BASE_ADDR
-#define UART1_BASE_ADDR MX1_UART1_BASE_ADDR
-#define UART2_BASE_ADDR MX1_UART2_BASE_ADDR
-#define PWM_BASE_ADDR MX1_PWM_BASE_ADDR
-#define DMA_BASE_ADDR MX1_DMA_BASE_ADDR
-#define AIPI2_BASE_ADDR MX1_AIPI2_BASE_ADDR
-#define SIM_BASE_ADDR MX1_SIM_BASE_ADDR
-#define USBD_BASE_ADDR MX1_USBD_BASE_ADDR
-#define SPI1_BASE_ADDR MX1_SPI1_BASE_ADDR
-#define MMC_BASE_ADDR MX1_MMC_BASE_ADDR
-#define ASP_BASE_ADDR MX1_ASP_BASE_ADDR
-#define BTA_BASE_ADDR MX1_BTA_BASE_ADDR
-#define I2C_BASE_ADDR MX1_I2C_BASE_ADDR
-#define SSI_BASE_ADDR MX1_SSI_BASE_ADDR
-#define SPI2_BASE_ADDR MX1_SPI2_BASE_ADDR
-#define MSHC_BASE_ADDR MX1_MSHC_BASE_ADDR
-#define CCM_BASE_ADDR MX1_CCM_BASE_ADDR
-#define SCM_BASE_ADDR MX1_SCM_BASE_ADDR
-#define GPIO_BASE_ADDR MX1_GPIO_BASE_ADDR
-#define EIM_BASE_ADDR MX1_EIM_BASE_ADDR
-#define SDRAMC_BASE_ADDR MX1_SDRAMC_BASE_ADDR
-#define MMA_BASE_ADDR MX1_MMA_BASE_ADDR
-#define AVIC_BASE_ADDR MX1_AVIC_BASE_ADDR
-#define CSI_BASE_ADDR MX1_CSI_BASE_ADDR
-#define IO_ADDRESS(x) MX1_IO_ADDRESS(x)
-#define AVIC_IO_ADDRESS(x) IO_ADDRESS(x)
-#define INT_SOFTINT MX1_INT_SOFTINT
-#define CSI_INT MX1_CSI_INT
-#define DSPA_MAC_INT MX1_DSPA_MAC_INT
-#define DSPA_INT MX1_DSPA_INT
-#define COMP_INT MX1_COMP_INT
-#define MSHC_XINT MX1_MSHC_XINT
-#define GPIO_INT_PORTA MX1_GPIO_INT_PORTA
-#define GPIO_INT_PORTB MX1_GPIO_INT_PORTB
-#define GPIO_INT_PORTC MX1_GPIO_INT_PORTC
-#define LCDC_INT MX1_LCDC_INT
-#define SIM_INT MX1_SIM_INT
-#define SIM_DATA_INT MX1_SIM_DATA_INT
-#define RTC_INT MX1_RTC_INT
-#define RTC_SAMINT MX1_RTC_SAMINT
-#define UART2_MINT_PFERR MX1_UART2_MINT_PFERR
-#define UART2_MINT_RTS MX1_UART2_MINT_RTS
-#define UART2_MINT_DTR MX1_UART2_MINT_DTR
-#define UART2_MINT_UARTC MX1_UART2_MINT_UARTC
-#define UART2_MINT_TX MX1_UART2_MINT_TX
-#define UART2_MINT_RX MX1_UART2_MINT_RX
-#define UART1_MINT_PFERR MX1_UART1_MINT_PFERR
-#define UART1_MINT_RTS MX1_UART1_MINT_RTS
-#define UART1_MINT_DTR MX1_UART1_MINT_DTR
-#define UART1_MINT_UARTC MX1_UART1_MINT_UARTC
-#define UART1_MINT_TX MX1_UART1_MINT_TX
-#define UART1_MINT_RX MX1_UART1_MINT_RX
-#define VOICE_DAC_INT MX1_VOICE_DAC_INT
-#define VOICE_ADC_INT MX1_VOICE_ADC_INT
-#define PEN_DATA_INT MX1_PEN_DATA_INT
-#define PWM_INT MX1_PWM_INT
-#define SDHC_INT MX1_SDHC_INT
-#define I2C_INT MX1_INT_I2C
-#define CSPI_INT MX1_CSPI_INT
-#define SSI_TX_INT MX1_SSI_TX_INT
-#define SSI_TX_ERR_INT MX1_SSI_TX_ERR_INT
-#define SSI_RX_INT MX1_SSI_RX_INT
-#define SSI_RX_ERR_INT MX1_SSI_RX_ERR_INT
-#define TOUCH_INT MX1_TOUCH_INT
-#define USBD_INT1 MX1_USBD_INT1
-#define USBD_INT2 MX1_USBD_INT2
-#define USBD_INT3 MX1_USBD_INT3
-#define USBD_INT4 MX1_USBD_INT4
-#define USBD_INT5 MX1_USBD_INT5
-#define USBD_INT6 MX1_USBD_INT6
-#define BTSYS_INT MX1_BTSYS_INT
-#define BTTIM_INT MX1_BTTIM_INT
-#define BTWUI_INT MX1_BTWUI_INT
-#define TIM2_INT MX1_TIM2_INT
-#define TIM1_INT MX1_TIM1_INT
-#define DMA_ERR MX1_DMA_ERR
-#define DMA_INT MX1_DMA_INT
-#define GPIO_INT_PORTD MX1_GPIO_INT_PORTD
-#define WDT_INT MX1_WDT_INT
-#define DMA_REQ_UART3_T MX1_DMA_REQ_UART3_T
-#define DMA_REQ_UART3_R MX1_DMA_REQ_UART3_R
-#define DMA_REQ_SSI2_T MX1_DMA_REQ_SSI2_T
-#define DMA_REQ_SSI2_R MX1_DMA_REQ_SSI2_R
-#define DMA_REQ_CSI_STAT MX1_DMA_REQ_CSI_STAT
-#define DMA_REQ_CSI_R MX1_DMA_REQ_CSI_R
-#define DMA_REQ_MSHC MX1_DMA_REQ_MSHC
-#define DMA_REQ_DSPA_DCT_DOUT MX1_DMA_REQ_DSPA_DCT_DOUT
-#define DMA_REQ_DSPA_DCT_DIN MX1_DMA_REQ_DSPA_DCT_DIN
-#define DMA_REQ_DSPA_MAC MX1_DMA_REQ_DSPA_MAC
-#define DMA_REQ_EXT MX1_DMA_REQ_EXT
-#define DMA_REQ_SDHC MX1_DMA_REQ_SDHC
-#define DMA_REQ_SPI1_R MX1_DMA_REQ_SPI1_R
-#define DMA_REQ_SPI1_T MX1_DMA_REQ_SPI1_T
-#define DMA_REQ_SSI_T MX1_DMA_REQ_SSI_T
-#define DMA_REQ_SSI_R MX1_DMA_REQ_SSI_R
-#define DMA_REQ_ASP_DAC MX1_DMA_REQ_ASP_DAC
-#define DMA_REQ_ASP_ADC MX1_DMA_REQ_ASP_ADC
-#define DMA_REQ_USP_EP(x) MX1_DMA_REQ_USP_EP(x)
-#define DMA_REQ_SPI2_R MX1_DMA_REQ_SPI2_R
-#define DMA_REQ_SPI2_T MX1_DMA_REQ_SPI2_T
-#define DMA_REQ_UART2_T MX1_DMA_REQ_UART2_T
-#define DMA_REQ_UART2_R MX1_DMA_REQ_UART2_R
-#define DMA_REQ_UART1_T MX1_DMA_REQ_UART1_T
-#define DMA_REQ_UART1_R MX1_DMA_REQ_UART1_R
-#endif /* ifdef IMX_NEEDS_DEPRECATED_SYMBOLS */
+#define USBD_INT0		MX1_INT_USBD0
 
 #endif /* ifndef __MACH_MX1_H__ */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/include/mach/mx21.h linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/include/mach/mx21.h
--- linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/include/mach/mx21.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/include/mach/mx21.h	2011-03-14 21:20:32.000000000 -0400
@@ -26,7 +26,6 @@
 #define __MACH_MX21_H__
 
 #define MX21_AIPI_BASE_ADDR		0x10000000
-#define MX21_AIPI_BASE_ADDR_VIRT	0xf4000000
 #define MX21_AIPI_SIZE			SZ_1M
 #define MX21_DMA_BASE_ADDR			(MX21_AIPI_BASE_ADDR + 0x01000)
 #define MX21_WDOG_BASE_ADDR			(MX21_AIPI_BASE_ADDR + 0x02000)
@@ -49,6 +48,12 @@
 #define MX21_SDHC1_BASE_ADDR			(MX21_AIPI_BASE_ADDR + 0x13000)
 #define MX21_SDHC2_BASE_ADDR			(MX21_AIPI_BASE_ADDR + 0x14000)
 #define MX21_GPIO_BASE_ADDR			(MX21_AIPI_BASE_ADDR + 0x15000)
+#define MX21_GPIO1_BASE_ADDR			(MX21_GPIO_BASE_ADDR + 0x000)
+#define MX21_GPIO2_BASE_ADDR			(MX21_GPIO_BASE_ADDR + 0x100)
+#define MX21_GPIO3_BASE_ADDR			(MX21_GPIO_BASE_ADDR + 0x200)
+#define MX21_GPIO4_BASE_ADDR			(MX21_GPIO_BASE_ADDR + 0x300)
+#define MX21_GPIO5_BASE_ADDR			(MX21_GPIO_BASE_ADDR + 0x400)
+#define MX21_GPIO6_BASE_ADDR			(MX21_GPIO_BASE_ADDR + 0x500)
 #define MX21_AUDMUX_BASE_ADDR			(MX21_AIPI_BASE_ADDR + 0x16000)
 #define MX21_CSPI3_BASE_ADDR			(MX21_AIPI_BASE_ADDR + 0x17000)
 #define MX21_LCDC_BASE_ADDR			(MX21_AIPI_BASE_ADDR + 0x21000)
@@ -64,7 +69,6 @@
 #define MX21_AVIC_BASE_ADDR		0x10040000
 
 #define MX21_SAHB1_BASE_ADDR		0x80000000
-#define MX21_SAHB1_BASE_ADDR_VIRT	0xf4100000
 #define MX21_SAHB1_SIZE			SZ_1M
 #define MX21_CSI_BASE_ADDR			(MX2x_SAHB1_BASE_ADDR + 0x0000)
 
@@ -82,7 +86,6 @@
 
 /* NAND, SDRAM, WEIM etc controllers */
 #define MX21_X_MEMC_BASE_ADDR		0xdf000000
-#define MX21_X_MEMC_BASE_ADDR_VIRT	0xf4200000
 #define MX21_X_MEMC_SIZE		SZ_256K
 
 #define MX21_SDRAMC_BASE_ADDR		(MX21_X_MEMC_BASE_ADDR + 0x0000)
@@ -92,10 +95,8 @@
 
 #define MX21_IRAM_BASE_ADDR		0xffffe800	/* internal ram */
 
-#define MX21_IO_ADDRESS(x) (						\
-	IMX_IO_ADDRESS(x, MX21_AIPI) ?:					\
-	IMX_IO_ADDRESS(x, MX21_SAHB1) ?:				\
-	IMX_IO_ADDRESS(x, MX21_X_MEMC))
+#define MX21_IO_P2V(x)			IMX_IO_P2V(x)
+#define MX21_IO_ADDRESS(x)		IOMEM(MX21_IO_P2V(x))
 
 /* fixed interrupt numbers */
 #define MX21_INT_CSPI3		6
@@ -184,39 +185,4 @@
 #define MX21_DMA_REQ_CSI_STAT	30
 #define MX21_DMA_REQ_CSI_RX	31
 
-#ifdef IMX_NEEDS_DEPRECATED_SYMBOLS
-/* these should go away */
-#define SDRAM_BASE_ADDR MX21_SDRAM_BASE_ADDR
-#define CSD1_BASE_ADDR MX21_CSD1_BASE_ADDR
-#define CS0_BASE_ADDR MX21_CS0_BASE_ADDR
-#define CS1_BASE_ADDR MX21_CS1_BASE_ADDR
-#define CS2_BASE_ADDR MX21_CS2_BASE_ADDR
-#define CS3_BASE_ADDR MX21_CS3_BASE_ADDR
-#define CS4_BASE_ADDR MX21_CS4_BASE_ADDR
-#define PCMCIA_MEM_BASE_ADDR MX21_PCMCIA_MEM_BASE_ADDR
-#define CS5_BASE_ADDR MX21_CS5_BASE_ADDR
-#define X_MEMC_BASE_ADDR MX21_X_MEMC_BASE_ADDR
-#define X_MEMC_BASE_ADDR_VIRT MX21_X_MEMC_BASE_ADDR_VIRT
-#define X_MEMC_SIZE MX21_X_MEMC_SIZE
-#define SDRAMC_BASE_ADDR MX21_SDRAMC_BASE_ADDR
-#define EIM_BASE_ADDR MX21_EIM_BASE_ADDR
-#define PCMCIA_CTL_BASE_ADDR MX21_PCMCIA_CTL_BASE_ADDR
-#define NFC_BASE_ADDR MX21_NFC_BASE_ADDR
-#define IRAM_BASE_ADDR MX21_IRAM_BASE_ADDR
-#define MXC_INT_FIRI MX21_INT_FIRI
-#define MXC_INT_BMI MX21_INT_BMI
-#define MXC_INT_EMMAENC MX21_INT_EMMAENC
-#define MXC_INT_EMMADEC MX21_INT_EMMADEC
-#define MXC_INT_USBWKUP MX21_INT_USBWKUP
-#define MXC_INT_USBDMA MX21_INT_USBDMA
-#define MXC_INT_USBHOST MX21_INT_USBHOST
-#define MXC_INT_USBFUNC MX21_INT_USBFUNC
-#define MXC_INT_USBMNP MX21_INT_USBMNP
-#define MXC_INT_USBCTRL MX21_INT_USBCTRL
-#define MXC_INT_USBCTRL MX21_INT_USBCTRL
-#define DMA_REQ_FIRI_RX MX21_DMA_REQ_FIRI_RX
-#define DMA_REQ_BMI_TX MX21_DMA_REQ_BMI_TX
-#define DMA_REQ_BMI_RX MX21_DMA_REQ_BMI_RX
-#endif
-
 #endif /* ifndef __MACH_MX21_H__ */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/include/mach/mx25.h linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/include/mach/mx25.h
--- linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/include/mach/mx25.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/include/mach/mx25.h	2011-03-14 21:20:32.000000000 -0400
@@ -2,13 +2,10 @@
 #define __MACH_MX25_H__
 
 #define MX25_AIPS1_BASE_ADDR		0x43f00000
-#define MX25_AIPS1_BASE_ADDR_VIRT	0xfc000000
 #define MX25_AIPS1_SIZE			SZ_1M
 #define MX25_AIPS2_BASE_ADDR		0x53f00000
-#define MX25_AIPS2_BASE_ADDR_VIRT	0xfc200000
 #define MX25_AIPS2_SIZE			SZ_1M
 #define MX25_AVIC_BASE_ADDR		0x68000000
-#define MX25_AVIC_BASE_ADDR_VIRT	0xfc400000
 #define MX25_AVIC_SIZE			SZ_1M
 
 #define MX25_I2C1_BASE_ADDR		(MX25_AIPS1_BASE_ADDR + 0x80000)
@@ -21,20 +18,15 @@
 
 #define MX25_CRM_BASE_ADDR		(MX25_AIPS2_BASE_ADDR + 0x80000)
 #define MX25_GPT1_BASE_ADDR		(MX25_AIPS2_BASE_ADDR + 0x90000)
+#define MX25_GPIO4_BASE_ADDR		(MX25_AIPS2_BASE_ADDR + 0x9c000)
+#define MX25_PWM2_BASE_ADDR		(MX25_AIPS2_BASE_ADDR + 0xa0000)
+#define MX25_GPIO3_BASE_ADDR		(MX25_AIPS2_BASE_ADDR + 0xa4000)
+#define MX25_PWM3_BASE_ADDR		(MX25_AIPS2_BASE_ADDR + 0xa8000)
+#define MX25_PWM4_BASE_ADDR		(MX25_AIPS2_BASE_ADDR + 0xc8000)
+#define MX25_GPIO1_BASE_ADDR		(MX25_AIPS2_BASE_ADDR + 0xcc000)
+#define MX25_GPIO2_BASE_ADDR		(MX25_AIPS2_BASE_ADDR + 0xd0000)
 #define MX25_WDOG_BASE_ADDR		(MX25_AIPS2_BASE_ADDR + 0xdc000)
-
-#define MX25_GPIO1_BASE_ADDR_VIRT	(MX25_AIPS2_BASE_ADDR_VIRT + 0xcc000)
-#define MX25_GPIO2_BASE_ADDR_VIRT	(MX25_AIPS2_BASE_ADDR_VIRT + 0xd0000)
-#define MX25_GPIO3_BASE_ADDR_VIRT	(MX25_AIPS2_BASE_ADDR_VIRT + 0xa4000)
-#define MX25_GPIO4_BASE_ADDR_VIRT	(MX25_AIPS2_BASE_ADDR_VIRT + 0x9c000)
-
-#define MX25_IO_ADDRESS(x) (					\
-	IMX_IO_ADDRESS(x, MX25_AIPS1) ?:			\
-	IMX_IO_ADDRESS(x, MX25_AIPS2) ?:			\
-	IMX_IO_ADDRESS(x, MX25_AVIC))
-
-#define MX25_AIPS1_IO_ADDRESS(x) \
-	(((x) - MX25_AIPS1_BASE_ADDR) + MX25_AIPS1_BASE_ADDR_VIRT)
+#define MX25_PWM1_BASE_ADDR		(MX25_AIPS2_BASE_ADDR + 0xe0000)
 
 #define MX25_UART1_BASE_ADDR		0x43f90000
 #define MX25_UART2_BASE_ADDR		0x43f94000
@@ -55,9 +47,19 @@
 #define MX25_LCDC_BASE_ADDR		0x53fbc000
 #define MX25_KPP_BASE_ADDR		0x43fa8000
 #define MX25_SDMA_BASE_ADDR		0x53fd4000
-#define MX25_OTG_BASE_ADDR		0x53ff4000
+#define MX25_USB_BASE_ADDR		0x53ff4000
+#define MX25_USB_OTG_BASE_ADDR			(MX25_USB_BASE_ADDR + 0x0000)
+/*
+ * The reference manual (IMX25RM, Rev. 1, 06/2009) specifies an offset of 0x200
+ * for the host controller.  Early documentation drafts specified 0x400 and
+ * Freescale internal sources confirm only the latter value to work.
+ */
+#define MX25_USB_HS_BASE_ADDR			(MX25_USB_BASE_ADDR + 0x0400)
 #define MX25_CSI_BASE_ADDR		0x53ff8000
 
+#define MX25_IO_P2V(x)			IMX_IO_P2V(x)
+#define MX25_IO_ADDRESS(x)		IOMEM(MX25_IO_P2V(x))
+
 #define MX25_INT_CSPI3		0
 #define MX25_INT_I2C1		3
 #define MX25_INT_I2C2		4
@@ -69,18 +71,28 @@
 #define MX25_INT_SSI1		12
 #define MX25_INT_CSPI2		13
 #define MX25_INT_CSPI1		14
+#define MX25_INT_GPIO3		16
 #define MX25_INT_CSI		17
 #define MX25_INT_UART3		18
+#define MX25_INT_GPIO4		23
 #define MX25_INT_KPP		24
 #define MX25_INT_DRYICE		25
+#define MX25_INT_PWM1		26
 #define MX25_INT_UART2		32
 #define MX25_INT_NFC		33
 #define MX25_INT_SDMA		34
+#define MX25_INT_USB_HS		35
+#define MX25_INT_PWM2		36
+#define MX25_INT_USB_OTG	37
 #define MX25_INT_LCDC		39
 #define MX25_INT_UART5		40
+#define MX25_INT_PWM3		41
+#define MX25_INT_PWM4		42
 #define MX25_INT_CAN1		43
 #define MX25_INT_CAN2		44
 #define MX25_INT_UART1		45
+#define MX25_INT_GPIO2		51
+#define MX25_INT_GPIO1		52
 #define MX25_INT_FEC		57
 
 #define MX25_DMA_REQ_SSI2_RX1	22
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/include/mach/mx27.h linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/include/mach/mx27.h
--- linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/include/mach/mx27.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/include/mach/mx27.h	2011-03-14 21:20:32.000000000 -0400
@@ -29,7 +29,6 @@
 #endif
 
 #define MX27_AIPI_BASE_ADDR		0x10000000
-#define MX27_AIPI_BASE_ADDR_VIRT	0xf4000000
 #define MX27_AIPI_SIZE			SZ_1M
 #define MX27_DMA_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x01000)
 #define MX27_WDOG_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x02000)
@@ -52,6 +51,12 @@
 #define MX27_SDHC1_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x13000)
 #define MX27_SDHC2_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x14000)
 #define MX27_GPIO_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x15000)
+#define MX27_GPIO1_BASE_ADDR			(MX27_GPIO_BASE_ADDR + 0x000)
+#define MX27_GPIO2_BASE_ADDR			(MX27_GPIO_BASE_ADDR + 0x100)
+#define MX27_GPIO3_BASE_ADDR			(MX27_GPIO_BASE_ADDR + 0x200)
+#define MX27_GPIO4_BASE_ADDR			(MX27_GPIO_BASE_ADDR + 0x300)
+#define MX27_GPIO5_BASE_ADDR			(MX27_GPIO_BASE_ADDR + 0x400)
+#define MX27_GPIO6_BASE_ADDR			(MX27_GPIO_BASE_ADDR + 0x500)
 #define MX27_AUDMUX_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x16000)
 #define MX27_CSPI3_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x17000)
 #define MX27_MSHC_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x18000)
@@ -65,11 +70,13 @@
 #define MX27_LCDC_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x21000)
 #define MX27_SLCDC_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x22000)
 #define MX27_VPU_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x23000)
-#define MX27_USBOTG_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x24000)
-#define MX27_OTG_BASE_ADDR			MX27_USBOTG_BASE_ADDR
+#define MX27_USB_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x24000)
+#define MX27_USB_OTG_BASE_ADDR			(MX27_USB_BASE_ADDR + 0x0000)
+#define MX27_USB_HS1_BASE_ADDR			(MX27_USB_BASE_ADDR + 0x0200)
+#define MX27_USB_HS2_BASE_ADDR			(MX27_USB_BASE_ADDR + 0x0400)
 #define MX27_SAHARA_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x25000)
-#define MX27_EMMA_PP_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x26000)
-#define MX27_EMMA_PRP_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x26400)
+#define MX27_EMMAPP_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x26000)
+#define MX27_EMMAPRP_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x26400)
 #define MX27_CCM_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x27000)
 #define MX27_SYSCTRL_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x27800)
 #define MX27_IIM_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x28000)
@@ -87,7 +94,6 @@
 #define MX27_ROMP_BASE_ADDR		0x10041000
 
 #define MX27_SAHB1_BASE_ADDR		0x80000000
-#define MX27_SAHB1_BASE_ADDR_VIRT	0xf4100000
 #define MX27_SAHB1_SIZE			SZ_1M
 #define MX27_CSI_BASE_ADDR			(MX27_SAHB1_BASE_ADDR + 0x0000)
 #define MX27_ATA_BASE_ADDR			(MX27_SAHB1_BASE_ADDR + 0x1000)
@@ -105,7 +111,6 @@
 
 /* NAND, SDRAM, WEIM, M3IF, EMI controllers */
 #define MX27_X_MEMC_BASE_ADDR		0xd8000000
-#define MX27_X_MEMC_BASE_ADDR_VIRT	0xf4200000
 #define MX27_X_MEMC_SIZE		SZ_1M
 #define MX27_NFC_BASE_ADDR			(MX27_X_MEMC_BASE_ADDR)
 #define MX27_SDRAMC_BASE_ADDR			(MX27_X_MEMC_BASE_ADDR + 0x1000)
@@ -123,10 +128,8 @@
 /* IRAM */
 #define MX27_IRAM_BASE_ADDR		0xffff4c00	/* internal ram */
 
-#define MX27_IO_ADDRESS(x) (						\
-	IMX_IO_ADDRESS(x, MX27_AIPI) ?:					\
-	IMX_IO_ADDRESS(x, MX27_SAHB1) ?:				\
-	IMX_IO_ADDRESS(x, MX27_X_MEMC))
+#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,
@@ -192,9 +195,9 @@ static inline void mx27_setup_weimcs(siz
 #define MX27_INT_EMMAPRP	51
 #define MX27_INT_EMMAPP		52
 #define MX27_INT_VPU		53
-#define MX27_INT_USB1		54
-#define MX27_INT_USB2		55
-#define MX27_INT_USB3		56
+#define MX27_INT_USB_HS1	54
+#define MX27_INT_USB_HS2	55
+#define MX27_INT_USB_OTG	56
 #define MX27_INT_SCC_SMN	57
 #define MX27_INT_SCC_SCM	58
 #define MX27_INT_SAHARA		59
@@ -241,82 +244,8 @@ static inline void mx27_setup_weimcs(siz
 #define MX27_DMA_REQ_SDHC3	36
 #define MX27_DMA_REQ_NFC	37
 
-/* silicon revisions specific to i.MX27 */
-#define CHIP_REV_1_0		0x00
-#define CHIP_REV_2_0		0x01
-
 #ifndef __ASSEMBLY__
 extern int mx27_revision(void);
 #endif
 
-#ifdef IMX_NEEDS_DEPRECATED_SYMBOLS
-/* these should go away */
-#define MSHC_BASE_ADDR MX27_MSHC_BASE_ADDR
-#define GPT5_BASE_ADDR MX27_GPT5_BASE_ADDR
-#define GPT4_BASE_ADDR MX27_GPT4_BASE_ADDR
-#define UART5_BASE_ADDR MX27_UART5_BASE_ADDR
-#define UART6_BASE_ADDR MX27_UART6_BASE_ADDR
-#define I2C2_BASE_ADDR MX27_I2C2_BASE_ADDR
-#define SDHC3_BASE_ADDR MX27_SDHC3_BASE_ADDR
-#define GPT6_BASE_ADDR MX27_GPT6_BASE_ADDR
-#define VPU_BASE_ADDR MX27_VPU_BASE_ADDR
-#define OTG_BASE_ADDR MX27_OTG_BASE_ADDR
-#define SAHARA_BASE_ADDR MX27_SAHARA_BASE_ADDR
-#define IIM_BASE_ADDR MX27_IIM_BASE_ADDR
-#define RTIC_BASE_ADDR MX27_RTIC_BASE_ADDR
-#define FEC_BASE_ADDR MX27_FEC_BASE_ADDR
-#define SCC_BASE_ADDR MX27_SCC_BASE_ADDR
-#define ETB_BASE_ADDR MX27_ETB_BASE_ADDR
-#define ETB_RAM_BASE_ADDR MX27_ETB_RAM_BASE_ADDR
-#define ROMP_BASE_ADDR MX27_ROMP_BASE_ADDR
-#define ATA_BASE_ADDR MX27_ATA_BASE_ADDR
-#define SDRAM_BASE_ADDR MX27_SDRAM_BASE_ADDR
-#define CSD1_BASE_ADDR MX27_CSD1_BASE_ADDR
-#define CS0_BASE_ADDR MX27_CS0_BASE_ADDR
-#define CS1_BASE_ADDR MX27_CS1_BASE_ADDR
-#define CS2_BASE_ADDR MX27_CS2_BASE_ADDR
-#define CS3_BASE_ADDR MX27_CS3_BASE_ADDR
-#define CS4_BASE_ADDR MX27_CS4_BASE_ADDR
-#define CS5_BASE_ADDR MX27_CS5_BASE_ADDR
-#define X_MEMC_BASE_ADDR MX27_X_MEMC_BASE_ADDR
-#define X_MEMC_BASE_ADDR_VIRT MX27_X_MEMC_BASE_ADDR_VIRT
-#define X_MEMC_SIZE MX27_X_MEMC_SIZE
-#define NFC_BASE_ADDR MX27_NFC_BASE_ADDR
-#define SDRAMC_BASE_ADDR MX27_SDRAMC_BASE_ADDR
-#define WEIM_BASE_ADDR MX27_WEIM_BASE_ADDR
-#define M3IF_BASE_ADDR MX27_M3IF_BASE_ADDR
-#define PCMCIA_CTL_BASE_ADDR MX27_PCMCIA_CTL_BASE_ADDR
-#define PCMCIA_MEM_BASE_ADDR MX27_PCMCIA_MEM_BASE_ADDR
-#define IRAM_BASE_ADDR MX27_IRAM_BASE_ADDR
-#define MXC_INT_I2C2 MX27_INT_I2C2
-#define MXC_INT_GPT6 MX27_INT_GPT6
-#define MXC_INT_GPT5 MX27_INT_GPT5
-#define MXC_INT_GPT4 MX27_INT_GPT4
-#define MXC_INT_RTIC MX27_INT_RTIC
-#define MXC_INT_SDHC MX27_INT_SDHC
-#define MXC_INT_SDHC3 MX27_INT_SDHC3
-#define MXC_INT_ATA MX27_INT_ATA
-#define MXC_INT_UART6 MX27_INT_UART6
-#define MXC_INT_UART5 MX27_INT_UART5
-#define MXC_INT_FEC MX27_INT_FEC
-#define MXC_INT_VPU MX27_INT_VPU
-#define MXC_INT_USB1 MX27_INT_USB1
-#define MXC_INT_USB2 MX27_INT_USB2
-#define MXC_INT_USB3 MX27_INT_USB3
-#define MXC_INT_SCC_SMN MX27_INT_SCC_SMN
-#define MXC_INT_SCC_SCM MX27_INT_SCC_SCM
-#define MXC_INT_SAHARA MX27_INT_SAHARA
-#define MXC_INT_IIM MX27_INT_IIM
-#define MXC_INT_CCM MX27_INT_CCM
-#define DMA_REQ_MSHC MX27_DMA_REQ_MSHC
-#define DMA_REQ_ATA_TX MX27_DMA_REQ_ATA_TX
-#define DMA_REQ_ATA_RCV MX27_DMA_REQ_ATA_RCV
-#define DMA_REQ_UART5_TX MX27_DMA_REQ_UART5_TX
-#define DMA_REQ_UART5_RX MX27_DMA_REQ_UART5_RX
-#define DMA_REQ_UART6_TX MX27_DMA_REQ_UART6_TX
-#define DMA_REQ_UART6_RX MX27_DMA_REQ_UART6_RX
-#define DMA_REQ_SDHC3 MX27_DMA_REQ_SDHC3
-#define DMA_REQ_NFC MX27_DMA_REQ_NFC
-#endif
-
 #endif /* ifndef __MACH_MX27_H__ */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/include/mach/mx2x.h linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/include/mach/mx2x.h
--- linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/include/mach/mx2x.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/include/mach/mx2x.h	2011-03-14 21:20:32.000000000 -0400
@@ -27,7 +27,6 @@
 
 /* Register offsets */
 #define MX2x_AIPI_BASE_ADDR		0x10000000
-#define MX2x_AIPI_BASE_ADDR_VIRT	0xf4000000
 #define MX2x_AIPI_SIZE			SZ_1M
 #define MX2x_DMA_BASE_ADDR			(MX2x_AIPI_BASE_ADDR + 0x01000)
 #define MX2x_WDOG_BASE_ADDR			(MX2x_AIPI_BASE_ADDR + 0x02000)
@@ -65,43 +64,9 @@
 #define MX2x_AVIC_BASE_ADDR		0x10040000
 
 #define MX2x_SAHB1_BASE_ADDR		0x80000000
-#define MX2x_SAHB1_BASE_ADDR_VIRT	0xf4100000
 #define MX2x_SAHB1_SIZE			SZ_1M
 #define MX2x_CSI_BASE_ADDR			(MX2x_SAHB1_BASE_ADDR + 0x0000)
 
-/*
- * This macro defines the physical to virtual address mapping for all the
- * peripheral modules. It is used by passing in the physical address as x
- * and returning the virtual address. If the physical address is not mapped,
- * it returns 0xDEADBEEF
- */
-#define IO_ADDRESS(x)   \
-	(void __force __iomem *) \
-	(((x >= AIPI_BASE_ADDR) && (x < (AIPI_BASE_ADDR + AIPI_SIZE))) ? \
-		AIPI_IO_ADDRESS(x) : \
-	((x >= SAHB1_BASE_ADDR) && (x < (SAHB1_BASE_ADDR + SAHB1_SIZE))) ? \
-		SAHB1_IO_ADDRESS(x) : \
-	((x >= X_MEMC_BASE_ADDR) && (x < (X_MEMC_BASE_ADDR + X_MEMC_SIZE))) ? \
-		X_MEMC_IO_ADDRESS(x) : 0xDEADBEEF)
-
-/* define the address mapping macros: in physical address order */
-#define AIPI_IO_ADDRESS(x)  \
-	(((x) - AIPI_BASE_ADDR) + AIPI_BASE_ADDR_VIRT)
-
-#define AVIC_IO_ADDRESS(x)	AIPI_IO_ADDRESS(x)
-
-#define SAHB1_IO_ADDRESS(x)  \
-	(((x) - SAHB1_BASE_ADDR) + SAHB1_BASE_ADDR_VIRT)
-
-#define CS4_IO_ADDRESS(x)  \
-	(((x) - CS4_BASE_ADDR) + CS4_BASE_ADDR_VIRT)
-
-#define X_MEMC_IO_ADDRESS(x)  \
-	(((x) - X_MEMC_BASE_ADDR) + X_MEMC_BASE_ADDR_VIRT)
-
-#define PCMCIA_IO_ADDRESS(x) \
-	(((x) - X_MEMC_BASE_ADDR) + X_MEMC_BASE_ADDR_VIRT)
-
 /* fixed interrupt numbers */
 #define MX2x_INT_CSPI3		6
 #define MX2x_INT_GPIO		8
@@ -176,118 +141,4 @@
 #define MX2x_DMA_REQ_CSI_STAT	30
 #define MX2x_DMA_REQ_CSI_RX	31
 
-#ifdef IMX_NEEDS_DEPRECATED_SYMBOLS
-/* these should go away */
-#define AIPI_BASE_ADDR MX2x_AIPI_BASE_ADDR
-#define AIPI_BASE_ADDR_VIRT MX2x_AIPI_BASE_ADDR_VIRT
-#define AIPI_SIZE MX2x_AIPI_SIZE
-#define DMA_BASE_ADDR MX2x_DMA_BASE_ADDR
-#define WDOG_BASE_ADDR MX2x_WDOG_BASE_ADDR
-#define GPT1_BASE_ADDR MX2x_GPT1_BASE_ADDR
-#define GPT2_BASE_ADDR MX2x_GPT2_BASE_ADDR
-#define GPT3_BASE_ADDR MX2x_GPT3_BASE_ADDR
-#define PWM_BASE_ADDR MX2x_PWM_BASE_ADDR
-#define RTC_BASE_ADDR MX2x_RTC_BASE_ADDR
-#define KPP_BASE_ADDR MX2x_KPP_BASE_ADDR
-#define OWIRE_BASE_ADDR MX2x_OWIRE_BASE_ADDR
-#define UART1_BASE_ADDR MX2x_UART1_BASE_ADDR
-#define UART2_BASE_ADDR MX2x_UART2_BASE_ADDR
-#define UART3_BASE_ADDR MX2x_UART3_BASE_ADDR
-#define UART4_BASE_ADDR MX2x_UART4_BASE_ADDR
-#define CSPI1_BASE_ADDR MX2x_CSPI1_BASE_ADDR
-#define CSPI2_BASE_ADDR MX2x_CSPI2_BASE_ADDR
-#define SSI1_BASE_ADDR MX2x_SSI1_BASE_ADDR
-#define SSI2_BASE_ADDR MX2x_SSI2_BASE_ADDR
-#define I2C_BASE_ADDR MX2x_I2C_BASE_ADDR
-#define SDHC1_BASE_ADDR MX2x_SDHC1_BASE_ADDR
-#define SDHC2_BASE_ADDR MX2x_SDHC2_BASE_ADDR
-#define GPIO_BASE_ADDR MX2x_GPIO_BASE_ADDR
-#define AUDMUX_BASE_ADDR MX2x_AUDMUX_BASE_ADDR
-#define CSPI3_BASE_ADDR MX2x_CSPI3_BASE_ADDR
-#define LCDC_BASE_ADDR MX2x_LCDC_BASE_ADDR
-#define SLCDC_BASE_ADDR MX2x_SLCDC_BASE_ADDR
-#define USBOTG_BASE_ADDR MX2x_USBOTG_BASE_ADDR
-#define EMMA_PP_BASE_ADDR MX2x_EMMA_PP_BASE_ADDR
-#define EMMA_PRP_BASE_ADDR MX2x_EMMA_PRP_BASE_ADDR
-#define CCM_BASE_ADDR MX2x_CCM_BASE_ADDR
-#define SYSCTRL_BASE_ADDR MX2x_SYSCTRL_BASE_ADDR
-#define JAM_BASE_ADDR MX2x_JAM_BASE_ADDR
-#define MAX_BASE_ADDR MX2x_MAX_BASE_ADDR
-#define AVIC_BASE_ADDR MX2x_AVIC_BASE_ADDR
-#define SAHB1_BASE_ADDR MX2x_SAHB1_BASE_ADDR
-#define SAHB1_BASE_ADDR_VIRT MX2x_SAHB1_BASE_ADDR_VIRT
-#define SAHB1_SIZE MX2x_SAHB1_SIZE
-#define CSI_BASE_ADDR MX2x_CSI_BASE_ADDR
-#define MXC_INT_CSPI3 MX2x_INT_CSPI3
-#define MXC_INT_GPIO MX2x_INT_GPIO
-#define MXC_INT_SDHC2 MX2x_INT_SDHC2
-#define MXC_INT_SDHC1 MX2x_INT_SDHC1
-#define MXC_INT_I2C MX2x_INT_I2C
-#define MXC_INT_SSI2 MX2x_INT_SSI2
-#define MXC_INT_SSI1 MX2x_INT_SSI1
-#define MXC_INT_CSPI2 MX2x_INT_CSPI2
-#define MXC_INT_CSPI1 MX2x_INT_CSPI1
-#define MXC_INT_UART4 MX2x_INT_UART4
-#define MXC_INT_UART3 MX2x_INT_UART3
-#define MXC_INT_UART2 MX2x_INT_UART2
-#define MXC_INT_UART1 MX2x_INT_UART1
-#define MXC_INT_KPP MX2x_INT_KPP
-#define MXC_INT_RTC MX2x_INT_RTC
-#define MXC_INT_PWM MX2x_INT_PWM
-#define MXC_INT_GPT3 MX2x_INT_GPT3
-#define MXC_INT_GPT2 MX2x_INT_GPT2
-#define MXC_INT_GPT1 MX2x_INT_GPT1
-#define MXC_INT_WDOG MX2x_INT_WDOG
-#define MXC_INT_PCMCIA MX2x_INT_PCMCIA
-#define MXC_INT_NANDFC MX2x_INT_NANDFC
-#define MXC_INT_CSI MX2x_INT_CSI
-#define MXC_INT_DMACH0 MX2x_INT_DMACH0
-#define MXC_INT_DMACH1 MX2x_INT_DMACH1
-#define MXC_INT_DMACH2 MX2x_INT_DMACH2
-#define MXC_INT_DMACH3 MX2x_INT_DMACH3
-#define MXC_INT_DMACH4 MX2x_INT_DMACH4
-#define MXC_INT_DMACH5 MX2x_INT_DMACH5
-#define MXC_INT_DMACH6 MX2x_INT_DMACH6
-#define MXC_INT_DMACH7 MX2x_INT_DMACH7
-#define MXC_INT_DMACH8 MX2x_INT_DMACH8
-#define MXC_INT_DMACH9 MX2x_INT_DMACH9
-#define MXC_INT_DMACH10 MX2x_INT_DMACH10
-#define MXC_INT_DMACH11 MX2x_INT_DMACH11
-#define MXC_INT_DMACH12 MX2x_INT_DMACH12
-#define MXC_INT_DMACH13 MX2x_INT_DMACH13
-#define MXC_INT_DMACH14 MX2x_INT_DMACH14
-#define MXC_INT_DMACH15 MX2x_INT_DMACH15
-#define MXC_INT_EMMAPRP MX2x_INT_EMMAPRP
-#define MXC_INT_EMMAPP MX2x_INT_EMMAPP
-#define MXC_INT_SLCDC MX2x_INT_SLCDC
-#define MXC_INT_LCDC MX2x_INT_LCDC
-#define DMA_REQ_CSPI3_RX MX2x_DMA_REQ_CSPI3_RX
-#define DMA_REQ_CSPI3_TX MX2x_DMA_REQ_CSPI3_TX
-#define DMA_REQ_EXT MX2x_DMA_REQ_EXT
-#define DMA_REQ_SDHC2 MX2x_DMA_REQ_SDHC2
-#define DMA_REQ_SDHC1 MX2x_DMA_REQ_SDHC1
-#define DMA_REQ_SSI2_RX0 MX2x_DMA_REQ_SSI2_RX0
-#define DMA_REQ_SSI2_TX0 MX2x_DMA_REQ_SSI2_TX0
-#define DMA_REQ_SSI2_RX1 MX2x_DMA_REQ_SSI2_RX1
-#define DMA_REQ_SSI2_TX1 MX2x_DMA_REQ_SSI2_TX1
-#define DMA_REQ_SSI1_RX0 MX2x_DMA_REQ_SSI1_RX0
-#define DMA_REQ_SSI1_TX0 MX2x_DMA_REQ_SSI1_TX0
-#define DMA_REQ_SSI1_RX1 MX2x_DMA_REQ_SSI1_RX1
-#define DMA_REQ_SSI1_TX1 MX2x_DMA_REQ_SSI1_TX1
-#define DMA_REQ_CSPI2_RX MX2x_DMA_REQ_CSPI2_RX
-#define DMA_REQ_CSPI2_TX MX2x_DMA_REQ_CSPI2_TX
-#define DMA_REQ_CSPI1_RX MX2x_DMA_REQ_CSPI1_RX
-#define DMA_REQ_CSPI1_TX MX2x_DMA_REQ_CSPI1_TX
-#define DMA_REQ_UART4_RX MX2x_DMA_REQ_UART4_RX
-#define DMA_REQ_UART4_TX MX2x_DMA_REQ_UART4_TX
-#define DMA_REQ_UART3_RX MX2x_DMA_REQ_UART3_RX
-#define DMA_REQ_UART3_TX MX2x_DMA_REQ_UART3_TX
-#define DMA_REQ_UART2_RX MX2x_DMA_REQ_UART2_RX
-#define DMA_REQ_UART2_TX MX2x_DMA_REQ_UART2_TX
-#define DMA_REQ_UART1_RX MX2x_DMA_REQ_UART1_RX
-#define DMA_REQ_UART1_TX MX2x_DMA_REQ_UART1_TX
-#define DMA_REQ_CSI_STAT MX2x_DMA_REQ_CSI_STAT
-#define DMA_REQ_CSI_RX MX2x_DMA_REQ_CSI_RX
-#endif
-
 #endif /* ifndef __MACH_MX2x_H__ */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/include/mach/mx31.h linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/include/mach/mx31.h
--- linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/include/mach/mx31.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/include/mach/mx31.h	2011-03-14 21:20:32.000000000 -0400
@@ -15,7 +15,6 @@
 #define MX31_L2CC_SIZE			SZ_1M
 
 #define MX31_AIPS1_BASE_ADDR		0x43f00000
-#define MX31_AIPS1_BASE_ADDR_VIRT	0xfc000000
 #define MX31_AIPS1_SIZE			SZ_1M
 #define MX31_MAX_BASE_ADDR			(MX31_AIPS1_BASE_ADDR + 0x04000)
 #define MX31_EVTMON_BASE_ADDR			(MX31_AIPS1_BASE_ADDR + 0x08000)
@@ -25,7 +24,10 @@
 #define MX31_ECT_CTIO_BASE_ADDR			(MX31_AIPS1_BASE_ADDR + 0x18000)
 #define MX31_I2C1_BASE_ADDR			(MX31_AIPS1_BASE_ADDR + 0x80000)
 #define MX31_I2C3_BASE_ADDR			(MX31_AIPS1_BASE_ADDR + 0x84000)
-#define MX31_OTG_BASE_ADDR			(MX31_AIPS1_BASE_ADDR + 0x88000)
+#define MX31_USB_BASE_ADDR			(MX31_AIPS1_BASE_ADDR + 0x88000)
+#define MX31_USB_OTG_BASE_ADDR			(MX31_USB_BASE_ADDR + 0x0000)
+#define MX31_USB_HS1_BASE_ADDR			(MX31_USB_BASE_ADDR + 0x0200)
+#define MX31_USB_HS2_BASE_ADDR			(MX31_USB_BASE_ADDR + 0x0400)
 #define MX31_ATA_BASE_ADDR			(MX31_AIPS1_BASE_ADDR + 0x8c000)
 #define MX31_UART1_BASE_ADDR			(MX31_AIPS1_BASE_ADDR + 0x90000)
 #define MX31_UART2_BASE_ADDR			(MX31_AIPS1_BASE_ADDR + 0x94000)
@@ -41,10 +43,9 @@
 #define MX31_ECT_IP2_BASE_ADDR			(MX31_AIPS1_BASE_ADDR + 0xbc000)
 
 #define MX31_SPBA0_BASE_ADDR		0x50000000
-#define MX31_SPBA0_BASE_ADDR_VIRT	0xfc100000
 #define MX31_SPBA0_SIZE			SZ_1M
-#define MX31_MMC_SDHC1_BASE_ADDR		(MX31_SPBA0_BASE_ADDR + 0x04000)
-#define MX31_MMC_SDHC2_BASE_ADDR		(MX31_SPBA0_BASE_ADDR + 0x08000)
+#define MX31_SDHC1_BASE_ADDR			(MX31_SPBA0_BASE_ADDR + 0x04000)
+#define MX31_SDHC2_BASE_ADDR			(MX31_SPBA0_BASE_ADDR + 0x08000)
 #define MX31_UART3_BASE_ADDR			(MX31_SPBA0_BASE_ADDR + 0x0c000)
 #define MX31_CSPI2_BASE_ADDR			(MX31_SPBA0_BASE_ADDR + 0x10000)
 #define MX31_SSI2_BASE_ADDR			(MX31_SPBA0_BASE_ADDR + 0x14000)
@@ -55,7 +56,6 @@
 #define MX31_SPBA_CTRL_BASE_ADDR		(MX31_SPBA0_BASE_ADDR + 0x3c000)
 
 #define MX31_AIPS2_BASE_ADDR		0x53f00000
-#define MX31_AIPS2_BASE_ADDR_VIRT	0xfc200000
 #define MX31_AIPS2_SIZE			SZ_1M
 #define MX31_CCM_BASE_ADDR			(MX31_AIPS2_BASE_ADDR + 0x80000)
 #define MX31_CSPI3_BASE_ADDR			(MX31_AIPS2_BASE_ADDR + 0x84000)
@@ -84,7 +84,6 @@
 #define MX31_ROMP_SIZE			SZ_1M
 
 #define MX31_AVIC_BASE_ADDR		0x68000000
-#define MX31_AVIC_BASE_ADDR_VIRT	0xfc400000
 #define MX31_AVIC_SIZE			SZ_1M
 
 #define MX31_IPU_MEM_BASE_ADDR		0x70000000
@@ -97,15 +96,14 @@
 #define MX31_CS3_BASE_ADDR		0xb2000000
 
 #define MX31_CS4_BASE_ADDR		0xb4000000
-#define MX31_CS4_BASE_ADDR_VIRT		0xf4000000
+#define MX31_CS4_BASE_ADDR_VIRT		0xf6000000
 #define MX31_CS4_SIZE			SZ_32M
 
 #define MX31_CS5_BASE_ADDR		0xb6000000
-#define MX31_CS5_BASE_ADDR_VIRT		0xf6000000
+#define MX31_CS5_BASE_ADDR_VIRT		0xf8000000
 #define MX31_CS5_SIZE			SZ_32M
 
 #define MX31_X_MEMC_BASE_ADDR		0xb8000000
-#define MX31_X_MEMC_BASE_ADDR_VIRT	0xfc320000
 #define MX31_X_MEMC_SIZE		SZ_64K
 #define MX31_NFC_BASE_ADDR			(MX31_X_MEMC_BASE_ADDR + 0x0000)
 #define MX31_ESDCTL_BASE_ADDR			(MX31_X_MEMC_BASE_ADDR + 0x1000)
@@ -121,12 +119,8 @@
 
 #define MX31_PCMCIA_MEM_BASE_ADDR	0xbc000000
 
-#define MX31_IO_ADDRESS(x) (						\
-	IMX_IO_ADDRESS(x, MX31_AIPS1) ?:				\
-	IMX_IO_ADDRESS(x, MX31_AIPS2) ?:				\
-	IMX_IO_ADDRESS(x, MX31_AVIC) ?:					\
-	IMX_IO_ADDRESS(x, MX31_X_MEMC) ?:				\
-	IMX_IO_ADDRESS(x, MX31_SPBA0))
+#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,
@@ -143,8 +137,8 @@ static inline void mx31_setup_weimcs(siz
 #define MX31_INT_MPEG4_ENCODER	5
 #define MX31_INT_RTIC		6
 #define MX31_INT_FIRI		7
-#define MX31_INT_MMC_SDHC2	8
-#define MX31_INT_MMC_SDHC1	9
+#define MX31_INT_SDHC2		8
+#define MX31_INT_SDHC1		9
 #define MX31_INT_I2C1		10
 #define MX31_INT_SSI2		11
 #define MX31_INT_SSI1		12
@@ -170,10 +164,9 @@ static inline void mx31_setup_weimcs(siz
 #define MX31_INT_UART2		32
 #define MX31_INT_NFC		33
 #define MX31_INT_SDMA		34
-#define MX31_INT_USB1		35
-#define MX31_INT_USB2		36
-#define MX31_INT_USB3		37
-#define MX31_INT_USB4		38
+#define MX31_INT_USB_HS1	35
+#define MX31_INT_USB_HS2	36
+#define MX31_INT_USB_OTG	37
 #define MX31_INT_MSHC1		39
 #define MX31_INT_MSHC2		40
 #define MX31_INT_IPU_ERR	41
@@ -197,6 +190,8 @@ static inline void mx31_setup_weimcs(siz
 #define MX31_INT_EXT_WDOG	62
 #define MX31_INT_EXT_TV		63
 
+#define MX31_DMA_REQ_SDHC1	20
+#define MX31_DMA_REQ_SDHC2	21
 #define MX31_DMA_REQ_SSI2_RX1	22
 #define MX31_DMA_REQ_SSI2_TX1	23
 #define MX31_DMA_REQ_SSI2_RX0	24
@@ -208,52 +203,4 @@ static inline void mx31_setup_weimcs(siz
 
 #define MX31_PROD_SIGNATURE		0x1	/* For MX31 */
 
-/* silicon revisions specific to i.MX31 */
-#define MX31_CHIP_REV_1_0		0x10
-#define MX31_CHIP_REV_1_1		0x11
-#define MX31_CHIP_REV_1_2		0x12
-#define MX31_CHIP_REV_1_3		0x13
-#define MX31_CHIP_REV_2_0		0x20
-#define MX31_CHIP_REV_2_1		0x21
-#define MX31_CHIP_REV_2_2		0x22
-#define MX31_CHIP_REV_2_3		0x23
-#define MX31_CHIP_REV_3_0		0x30
-#define MX31_CHIP_REV_3_1		0x31
-#define MX31_CHIP_REV_3_2		0x32
-
-#define MX31_SYSTEM_REV_MIN		MX31_CHIP_REV_1_0
-#define MX31_SYSTEM_REV_NUM		3
-
-#ifdef IMX_NEEDS_DEPRECATED_SYMBOLS
-/* these should go away */
-#define ATA_BASE_ADDR MX31_ATA_BASE_ADDR
-#define UART4_BASE_ADDR MX31_UART4_BASE_ADDR
-#define UART5_BASE_ADDR MX31_UART5_BASE_ADDR
-#define MMC_SDHC1_BASE_ADDR MX31_MMC_SDHC1_BASE_ADDR
-#define MMC_SDHC2_BASE_ADDR MX31_MMC_SDHC2_BASE_ADDR
-#define SIM1_BASE_ADDR MX31_SIM1_BASE_ADDR
-#define IIM_BASE_ADDR MX31_IIM_BASE_ADDR
-#define CSPI3_BASE_ADDR MX31_CSPI3_BASE_ADDR
-#define FIRI_BASE_ADDR MX31_FIRI_BASE_ADDR
-#define SCM_BASE_ADDR MX31_SCM_BASE_ADDR
-#define SMN_BASE_ADDR MX31_SMN_BASE_ADDR
-#define MPEG4_ENC_BASE_ADDR MX31_MPEG4_ENC_BASE_ADDR
-#define MXC_INT_MPEG4_ENCODER MX31_INT_MPEG4_ENCODER
-#define MXC_INT_FIRI MX31_INT_FIRI
-#define MXC_INT_MBX MX31_INT_MBX
-#define MXC_INT_CSPI3 MX31_INT_CSPI3
-#define MXC_INT_SIM2 MX31_INT_SIM2
-#define MXC_INT_SIM1 MX31_INT_SIM1
-#define MXC_INT_CCM_DVFS MX31_INT_CCM_DVFS
-#define MXC_INT_USB1 MX31_INT_USB1
-#define MXC_INT_USB2 MX31_INT_USB2
-#define MXC_INT_USB3 MX31_INT_USB3
-#define MXC_INT_USB4 MX31_INT_USB4
-#define MXC_INT_MSHC2 MX31_INT_MSHC2
-#define MXC_INT_UART4 MX31_INT_UART4
-#define MXC_INT_UART5 MX31_INT_UART5
-#define MXC_INT_CCM MX31_INT_CCM
-#define MXC_INT_PCMCIA MX31_INT_PCMCIA
-#endif
-
 #endif /* ifndef __MACH_MX31_H__ */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/include/mach/mx35.h linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/include/mach/mx35.h
--- linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/include/mach/mx35.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/include/mach/mx35.h	2011-03-14 21:20:32.000000000 -0400
@@ -11,7 +11,6 @@
 #define MX35_L2CC_SIZE			SZ_1M
 
 #define MX35_AIPS1_BASE_ADDR		0x43f00000
-#define MX35_AIPS1_BASE_ADDR_VIRT	0xfc000000
 #define MX35_AIPS1_SIZE			SZ_1M
 #define MX35_MAX_BASE_ADDR			(MX35_AIPS1_BASE_ADDR + 0x04000)
 #define MX35_EVTMON_BASE_ADDR			(MX35_AIPS1_BASE_ADDR + 0x08000)
@@ -33,7 +32,6 @@
 #define MX35_ECT_IP2_BASE_ADDR			(MX35_AIPS1_BASE_ADDR + 0xbc000)
 
 #define MX35_SPBA0_BASE_ADDR		0x50000000
-#define MX35_SPBA0_BASE_ADDR_VIRT	0xfc100000
 #define MX35_SPBA0_SIZE			SZ_1M
 #define MX35_UART3_BASE_ADDR			(MX35_SPBA0_BASE_ADDR + 0x0c000)
 #define MX35_CSPI2_BASE_ADDR			(MX35_SPBA0_BASE_ADDR + 0x10000)
@@ -44,7 +42,6 @@
 #define MX35_SPBA_CTRL_BASE_ADDR		(MX35_SPBA0_BASE_ADDR + 0x3c000)
 
 #define MX35_AIPS2_BASE_ADDR		0x53f00000
-#define MX35_AIPS2_BASE_ADDR_VIRT	0xfc200000
 #define MX35_AIPS2_SIZE			SZ_1M
 #define MX35_CCM_BASE_ADDR			(MX35_AIPS2_BASE_ADDR + 0x80000)
 #define MX35_GPT1_BASE_ADDR			(MX35_AIPS2_BASE_ADDR + 0x90000)
@@ -68,15 +65,19 @@
 #define MX35_CAN2_BASE_ADDR			(MX35_AIPS2_BASE_ADDR + 0xe8000)
 #define MX35_RTIC_BASE_ADDR			(MX35_AIPS2_BASE_ADDR + 0xec000)
 #define MX35_IIM_BASE_ADDR			(MX35_AIPS2_BASE_ADDR + 0xf0000)
-
-#define MX35_OTG_BASE_ADDR		0x53ff4000
+#define MX35_USB_BASE_ADDR			(MX35_AIPS2_BASE_ADDR + 0xf4000)
+#define MX35_USB_OTG_BASE_ADDR			(MX35_USB_BASE_ADDR + 0x0000)
+/*
+ * The Reference Manual (IMX35RM, Rev. 2, 3/2009) claims an offset of 0x200 for
+ * HS.  When host support was implemented only a preliminary document was
+ * available, which told 0x400.  This works fine.
+ */
+#define MX35_USB_HS_BASE_ADDR			(MX35_USB_BASE_ADDR + 0x0400)
 
 #define MX35_ROMP_BASE_ADDR		0x60000000
-#define MX35_ROMP_BASE_ADDR_VIRT	0xfc500000
 #define MX35_ROMP_SIZE			SZ_1M
 
 #define MX35_AVIC_BASE_ADDR		0x68000000
-#define MX35_AVIC_BASE_ADDR_VIRT	0xfc400000
 #define MX35_AVIC_SIZE			SZ_1M
 
 /*
@@ -92,18 +93,17 @@
 #define MX35_CS3_BASE_ADDR		0xb2000000
 
 #define MX35_CS4_BASE_ADDR		0xb4000000
-#define MX35_CS4_BASE_ADDR_VIRT		0xf4000000
+#define MX35_CS4_BASE_ADDR_VIRT		0xf6000000
 #define MX35_CS4_SIZE			SZ_32M
 
 #define MX35_CS5_BASE_ADDR		0xb6000000
-#define MX35_CS5_BASE_ADDR_VIRT		0xf6000000
+#define MX35_CS5_BASE_ADDR_VIRT		0xf8000000
 #define MX35_CS5_SIZE			SZ_32M
 
 /*
  * NAND, SDRAM, WEIM, M3IF, EMI controllers
  */
 #define MX35_X_MEMC_BASE_ADDR		0xb8000000
-#define MX35_X_MEMC_BASE_ADDR_VIRT	0xfc320000
 #define MX35_X_MEMC_SIZE		SZ_64K
 #define MX35_ESDCTL_BASE_ADDR			(MX35_X_MEMC_BASE_ADDR + 0x1000)
 #define MX35_WEIM_BASE_ADDR			(MX35_X_MEMC_BASE_ADDR + 0x2000)
@@ -114,12 +114,8 @@
 #define MX35_NFC_BASE_ADDR		0xbb000000
 #define MX35_PCMCIA_MEM_BASE_ADDR	0xbc000000
 
-#define MX35_IO_ADDRESS(x) (						\
-	IMX_IO_ADDRESS(x, MX35_AIPS1) ?:				\
-	IMX_IO_ADDRESS(x, MX35_AIPS2) ?:				\
-	IMX_IO_ADDRESS(x, MX35_AVIC) ?:					\
-	IMX_IO_ADDRESS(x, MX35_X_MEMC) ?:				\
-	IMX_IO_ADDRESS(x, MX35_SPBA0))
+#define MX35_IO_P2V(x)			IMX_IO_P2V(x)
+#define MX35_IO_ADDRESS(x)		IOMEM(MX35_IO_P2V(x))
 
 /*
  * Interrupt numbers
@@ -153,8 +149,8 @@
 #define MX35_INT_UART2		32
 #define MX35_INT_NFC		33
 #define MX35_INT_SDMA		34
-#define MX35_INT_USBHS		35
-#define MX35_INT_USBOTG		37
+#define MX35_INT_USB_HS		35
+#define MX35_INT_USB_OTG	37
 #define MX35_INT_MSHC1		39
 #define MX35_INT_ESAI		40
 #define MX35_INT_IPU_ERR	41
@@ -190,23 +186,4 @@
 
 #define MX35_PROD_SIGNATURE		0x1	/* For MX31 */
 
-#define MX35_SYSTEM_REV_MIN		MX3x_CHIP_REV_1_0
-#define MX35_SYSTEM_REV_NUM		3
-
-#ifdef IMX_NEEDS_DEPRECATED_SYMBOLS
-/* these should go away */
-#define MXC_FEC_BASE_ADDR MX35_FEC_BASE_ADDR
-#define MXC_INT_OWIRE MX35_INT_OWIRE
-#define MXC_INT_GPU2D MX35_INT_GPU2D
-#define MXC_INT_ASRC MX35_INT_ASRC
-#define MXC_INT_USBHS MX35_INT_USBHS
-#define MXC_INT_USBOTG MX35_INT_USBOTG
-#define MXC_INT_ESAI MX35_INT_ESAI
-#define MXC_INT_CAN1 MX35_INT_CAN1
-#define MXC_INT_CAN2 MX35_INT_CAN2
-#define MXC_INT_MLB MX35_INT_MLB
-#define MXC_INT_SPDIF MX35_INT_SPDIF
-#define MXC_INT_FEC MX35_INT_FEC
-#endif
-
 #endif /* ifndef __MACH_MX35_H__ */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/include/mach/mx3x.h linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/include/mach/mx3x.h
--- linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/include/mach/mx3x.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/include/mach/mx3x.h	2011-03-14 21:20:32.000000000 -0400
@@ -44,7 +44,6 @@
  * AIPS 1
  */
 #define MX3x_AIPS1_BASE_ADDR		0x43f00000
-#define MX3x_AIPS1_BASE_ADDR_VIRT	0xfc000000
 #define MX3x_AIPS1_SIZE			SZ_1M
 #define MX3x_MAX_BASE_ADDR			(MX3x_AIPS1_BASE_ADDR + 0x04000)
 #define MX3x_EVTMON_BASE_ADDR			(MX3x_AIPS1_BASE_ADDR + 0x08000)
@@ -69,7 +68,6 @@
  * SPBA global module enabled #0
  */
 #define MX3x_SPBA0_BASE_ADDR		0x50000000
-#define MX3x_SPBA0_BASE_ADDR_VIRT	0xfc100000
 #define MX3x_SPBA0_SIZE			SZ_1M
 #define MX3x_UART3_BASE_ADDR			(MX3x_SPBA0_BASE_ADDR + 0x0c000)
 #define MX3x_CSPI2_BASE_ADDR			(MX3x_SPBA0_BASE_ADDR + 0x10000)
@@ -82,7 +80,6 @@
  * AIPS 2
  */
 #define MX3x_AIPS2_BASE_ADDR		0x53f00000
-#define MX3x_AIPS2_BASE_ADDR_VIRT	0xfc200000
 #define MX3x_AIPS2_SIZE			SZ_1M
 #define MX3x_CCM_BASE_ADDR			(MX3x_AIPS2_BASE_ADDR + 0x80000)
 #define MX3x_GPT1_BASE_ADDR			(MX3x_AIPS2_BASE_ADDR + 0x90000)
@@ -105,11 +102,9 @@
  * ROMP and AVIC
  */
 #define MX3x_ROMP_BASE_ADDR		0x60000000
-#define MX3x_ROMP_BASE_ADDR_VIRT	0xfc500000
 #define MX3x_ROMP_SIZE			SZ_1M
 
 #define MX3x_AVIC_BASE_ADDR		0x68000000
-#define MX3x_AVIC_BASE_ADDR_VIRT	0xfc400000
 #define MX3x_AVIC_SIZE			SZ_1M
 
 /*
@@ -125,18 +120,17 @@
 #define MX3x_CS3_BASE_ADDR		0xb2000000
 
 #define MX3x_CS4_BASE_ADDR		0xb4000000
-#define MX3x_CS4_BASE_ADDR_VIRT		0xf4000000
+#define MX3x_CS4_BASE_ADDR_VIRT		0xf6000000
 #define MX3x_CS4_SIZE			SZ_32M
 
 #define MX3x_CS5_BASE_ADDR		0xb6000000
-#define MX3x_CS5_BASE_ADDR_VIRT		0xf6000000
+#define MX3x_CS5_BASE_ADDR_VIRT		0xf8000000
 #define MX3x_CS5_SIZE			SZ_32M
 
 /*
  * NAND, SDRAM, WEIM, M3IF, EMI controllers
  */
 #define MX3x_X_MEMC_BASE_ADDR		0xb8000000
-#define MX3x_X_MEMC_BASE_ADDR_VIRT	0xfc320000
 #define MX3x_X_MEMC_SIZE		SZ_64K
 #define MX3x_ESDCTL_BASE_ADDR			(MX3x_X_MEMC_BASE_ADDR + 0x1000)
 #define MX3x_WEIM_BASE_ADDR			(MX3x_X_MEMC_BASE_ADDR + 0x2000)
@@ -146,56 +140,6 @@
 
 #define MX3x_PCMCIA_MEM_BASE_ADDR	0xbc000000
 
-/*!
- * This macro defines the physical to virtual address mapping for all the
- * peripheral modules. It is used by passing in the physical address as x
- * and returning the virtual address. If the physical address is not mapped,
- * it returns 0xDEADBEEF
- */
-#define IO_ADDRESS(x)   \
-	(void __force __iomem *) \
-	(((x >= AIPS1_BASE_ADDR) && (x < (AIPS1_BASE_ADDR + AIPS1_SIZE))) ? AIPS1_IO_ADDRESS(x):\
-	((x >= SPBA0_BASE_ADDR) && (x < (SPBA0_BASE_ADDR + SPBA0_SIZE))) ? SPBA0_IO_ADDRESS(x):\
-	((x >= AIPS2_BASE_ADDR) && (x < (AIPS2_BASE_ADDR + AIPS2_SIZE))) ? AIPS2_IO_ADDRESS(x):\
-	((x >= ROMP_BASE_ADDR) && (x < (ROMP_BASE_ADDR + ROMP_SIZE))) ? ROMP_IO_ADDRESS(x):\
-	((x >= AVIC_BASE_ADDR) && (x < (AVIC_BASE_ADDR + AVIC_SIZE))) ? AVIC_IO_ADDRESS(x):\
-	((x >= CS4_BASE_ADDR) && (x < (CS4_BASE_ADDR + CS4_SIZE))) ? CS4_IO_ADDRESS(x):\
-	((x >= X_MEMC_BASE_ADDR) && (x < (X_MEMC_BASE_ADDR + X_MEMC_SIZE))) ? X_MEMC_IO_ADDRESS(x):\
-	0xDEADBEEF)
-
-/*
- * define the address mapping macros: in physical address order
- */
-#define L2CC_IO_ADDRESS(x)  \
-	(((x) - L2CC_BASE_ADDR) + L2CC_BASE_ADDR_VIRT)
-
-#define AIPS1_IO_ADDRESS(x)  \
-	(((x) - AIPS1_BASE_ADDR) + AIPS1_BASE_ADDR_VIRT)
-
-#define SPBA0_IO_ADDRESS(x)  \
-	(((x) - SPBA0_BASE_ADDR) + SPBA0_BASE_ADDR_VIRT)
-
-#define AIPS2_IO_ADDRESS(x)  \
-	(((x) - AIPS2_BASE_ADDR) + AIPS2_BASE_ADDR_VIRT)
-
-#define ROMP_IO_ADDRESS(x)  \
-	(((x) - ROMP_BASE_ADDR) + ROMP_BASE_ADDR_VIRT)
-
-#define AVIC_IO_ADDRESS(x)  \
-	(((x) - AVIC_BASE_ADDR) + AVIC_BASE_ADDR_VIRT)
-
-#define CS4_IO_ADDRESS(x)  \
-	(((x) - CS4_BASE_ADDR) + CS4_BASE_ADDR_VIRT)
-
-#define CS5_IO_ADDRESS(x)  \
-	(((x) - CS5_BASE_ADDR) + CS5_BASE_ADDR_VIRT)
-
-#define X_MEMC_IO_ADDRESS(x)  \
-	(((x) - X_MEMC_BASE_ADDR) + X_MEMC_BASE_ADDR_VIRT)
-
-#define PCMCIA_IO_ADDRESS(x) \
-	(((x) - X_MEMC_BASE_ADDR) + X_MEMC_BASE_ADDR_VIRT)
-
 /*
  * Interrupt numbers
  */
@@ -240,22 +184,6 @@
 
 #define MX3x_PROD_SIGNATURE		0x1	/* For MX31 */
 
-/* silicon revisions specific to i.MX31 and i.MX35 */
-#define MX3x_CHIP_REV_1_0		0x10
-#define MX3x_CHIP_REV_1_1		0x11
-#define MX3x_CHIP_REV_1_2		0x12
-#define MX3x_CHIP_REV_1_3		0x13
-#define MX3x_CHIP_REV_2_0		0x20
-#define MX3x_CHIP_REV_2_1		0x21
-#define MX3x_CHIP_REV_2_2		0x22
-#define MX3x_CHIP_REV_2_3		0x23
-#define MX3x_CHIP_REV_3_0		0x30
-#define MX3x_CHIP_REV_3_1		0x31
-#define MX3x_CHIP_REV_3_2		0x32
-
-#define MX3x_SYSTEM_REV_MIN		MX3x_CHIP_REV_1_0
-#define MX3x_SYSTEM_REV_NUM		3
-
 /* Mandatory defines used globally */
 
 #if !defined(__ASSEMBLY__) && !defined(__MXC_BOOT_UNCOMPRESS)
@@ -277,126 +205,4 @@ static inline int mx35_revision(void)
 }
 #endif
 
-#ifdef IMX_NEEDS_DEPRECATED_SYMBOLS
-/* these should go away */
-#define L2CC_BASE_ADDR MX3x_L2CC_BASE_ADDR
-#define L2CC_SIZE MX3x_L2CC_SIZE
-#define AIPS1_BASE_ADDR MX3x_AIPS1_BASE_ADDR
-#define AIPS1_BASE_ADDR_VIRT MX3x_AIPS1_BASE_ADDR_VIRT
-#define AIPS1_SIZE MX3x_AIPS1_SIZE
-#define MAX_BASE_ADDR MX3x_MAX_BASE_ADDR
-#define EVTMON_BASE_ADDR MX3x_EVTMON_BASE_ADDR
-#define CLKCTL_BASE_ADDR MX3x_CLKCTL_BASE_ADDR
-#define ETB_SLOT4_BASE_ADDR MX3x_ETB_SLOT4_BASE_ADDR
-#define ETB_SLOT5_BASE_ADDR MX3x_ETB_SLOT5_BASE_ADDR
-#define ECT_CTIO_BASE_ADDR MX3x_ECT_CTIO_BASE_ADDR
-#define I2C_BASE_ADDR MX3x_I2C_BASE_ADDR
-#define I2C3_BASE_ADDR MX3x_I2C3_BASE_ADDR
-#define UART1_BASE_ADDR MX3x_UART1_BASE_ADDR
-#define UART2_BASE_ADDR MX3x_UART2_BASE_ADDR
-#define I2C2_BASE_ADDR MX3x_I2C2_BASE_ADDR
-#define OWIRE_BASE_ADDR MX3x_OWIRE_BASE_ADDR
-#define SSI1_BASE_ADDR MX3x_SSI1_BASE_ADDR
-#define CSPI1_BASE_ADDR MX3x_CSPI1_BASE_ADDR
-#define KPP_BASE_ADDR MX3x_KPP_BASE_ADDR
-#define IOMUXC_BASE_ADDR MX3x_IOMUXC_BASE_ADDR
-#define ECT_IP1_BASE_ADDR MX3x_ECT_IP1_BASE_ADDR
-#define ECT_IP2_BASE_ADDR MX3x_ECT_IP2_BASE_ADDR
-#define SPBA0_BASE_ADDR MX3x_SPBA0_BASE_ADDR
-#define SPBA0_BASE_ADDR_VIRT MX3x_SPBA0_BASE_ADDR_VIRT
-#define SPBA0_SIZE MX3x_SPBA0_SIZE
-#define UART3_BASE_ADDR MX3x_UART3_BASE_ADDR
-#define CSPI2_BASE_ADDR MX3x_CSPI2_BASE_ADDR
-#define SSI2_BASE_ADDR MX3x_SSI2_BASE_ADDR
-#define ATA_DMA_BASE_ADDR MX3x_ATA_DMA_BASE_ADDR
-#define MSHC1_BASE_ADDR MX3x_MSHC1_BASE_ADDR
-#define SPBA_CTRL_BASE_ADDR MX3x_SPBA_CTRL_BASE_ADDR
-#define AIPS2_BASE_ADDR MX3x_AIPS2_BASE_ADDR
-#define AIPS2_BASE_ADDR_VIRT MX3x_AIPS2_BASE_ADDR_VIRT
-#define AIPS2_SIZE MX3x_AIPS2_SIZE
-#define CCM_BASE_ADDR MX3x_CCM_BASE_ADDR
-#define GPT1_BASE_ADDR MX3x_GPT1_BASE_ADDR
-#define EPIT1_BASE_ADDR MX3x_EPIT1_BASE_ADDR
-#define EPIT2_BASE_ADDR MX3x_EPIT2_BASE_ADDR
-#define GPIO3_BASE_ADDR MX3x_GPIO3_BASE_ADDR
-#define SCC_BASE_ADDR MX3x_SCC_BASE_ADDR
-#define RNGA_BASE_ADDR MX3x_RNGA_BASE_ADDR
-#define IPU_CTRL_BASE_ADDR MX3x_IPU_CTRL_BASE_ADDR
-#define AUDMUX_BASE_ADDR MX3x_AUDMUX_BASE_ADDR
-#define GPIO1_BASE_ADDR MX3x_GPIO1_BASE_ADDR
-#define GPIO2_BASE_ADDR MX3x_GPIO2_BASE_ADDR
-#define SDMA_BASE_ADDR MX3x_SDMA_BASE_ADDR
-#define RTC_BASE_ADDR MX3x_RTC_BASE_ADDR
-#define WDOG_BASE_ADDR MX3x_WDOG_BASE_ADDR
-#define PWM_BASE_ADDR MX3x_PWM_BASE_ADDR
-#define RTIC_BASE_ADDR MX3x_RTIC_BASE_ADDR
-#define ROMP_BASE_ADDR MX3x_ROMP_BASE_ADDR
-#define ROMP_BASE_ADDR_VIRT MX3x_ROMP_BASE_ADDR_VIRT
-#define ROMP_SIZE MX3x_ROMP_SIZE
-#define AVIC_BASE_ADDR MX3x_AVIC_BASE_ADDR
-#define AVIC_BASE_ADDR_VIRT MX3x_AVIC_BASE_ADDR_VIRT
-#define AVIC_SIZE MX3x_AVIC_SIZE
-#define IPU_MEM_BASE_ADDR MX3x_IPU_MEM_BASE_ADDR
-#define CSD0_BASE_ADDR MX3x_CSD0_BASE_ADDR
-#define CSD1_BASE_ADDR MX3x_CSD1_BASE_ADDR
-#define CS0_BASE_ADDR MX3x_CS0_BASE_ADDR
-#define CS1_BASE_ADDR MX3x_CS1_BASE_ADDR
-#define CS2_BASE_ADDR MX3x_CS2_BASE_ADDR
-#define CS3_BASE_ADDR MX3x_CS3_BASE_ADDR
-#define CS4_BASE_ADDR MX3x_CS4_BASE_ADDR
-#define CS4_BASE_ADDR_VIRT MX3x_CS4_BASE_ADDR_VIRT
-#define CS4_SIZE MX3x_CS4_SIZE
-#define CS5_BASE_ADDR MX3x_CS5_BASE_ADDR
-#define CS5_BASE_ADDR_VIRT MX3x_CS5_BASE_ADDR_VIRT
-#define CS5_SIZE MX3x_CS5_SIZE
-#define X_MEMC_BASE_ADDR MX3x_X_MEMC_BASE_ADDR
-#define X_MEMC_BASE_ADDR_VIRT MX3x_X_MEMC_BASE_ADDR_VIRT
-#define X_MEMC_SIZE MX3x_X_MEMC_SIZE
-#define ESDCTL_BASE_ADDR MX3x_ESDCTL_BASE_ADDR
-#define WEIM_BASE_ADDR MX3x_WEIM_BASE_ADDR
-#define M3IF_BASE_ADDR MX3x_M3IF_BASE_ADDR
-#define EMI_CTL_BASE_ADDR MX3x_EMI_CTL_BASE_ADDR
-#define PCMCIA_CTL_BASE_ADDR MX3x_PCMCIA_CTL_BASE_ADDR
-#define PCMCIA_MEM_BASE_ADDR MX3x_PCMCIA_MEM_BASE_ADDR
-#define MXC_INT_I2C3 MX3x_INT_I2C3
-#define MXC_INT_I2C2 MX3x_INT_I2C2
-#define MXC_INT_RTIC MX3x_INT_RTIC
-#define MXC_INT_I2C MX3x_INT_I2C
-#define MXC_INT_CSPI2 MX3x_INT_CSPI2
-#define MXC_INT_CSPI1 MX3x_INT_CSPI1
-#define MXC_INT_ATA MX3x_INT_ATA
-#define MXC_INT_UART3 MX3x_INT_UART3
-#define MXC_INT_IIM MX3x_INT_IIM
-#define MXC_INT_RNGA MX3x_INT_RNGA
-#define MXC_INT_EVTMON MX3x_INT_EVTMON
-#define MXC_INT_KPP MX3x_INT_KPP
-#define MXC_INT_RTC MX3x_INT_RTC
-#define MXC_INT_PWM MX3x_INT_PWM
-#define MXC_INT_EPIT2 MX3x_INT_EPIT2
-#define MXC_INT_EPIT1 MX3x_INT_EPIT1
-#define MXC_INT_GPT MX3x_INT_GPT
-#define MXC_INT_POWER_FAIL MX3x_INT_POWER_FAIL
-#define MXC_INT_UART2 MX3x_INT_UART2
-#define MXC_INT_NANDFC MX3x_INT_NANDFC
-#define MXC_INT_SDMA MX3x_INT_SDMA
-#define MXC_INT_MSHC1 MX3x_INT_MSHC1
-#define MXC_INT_IPU_ERR MX3x_INT_IPU_ERR
-#define MXC_INT_IPU_SYN MX3x_INT_IPU_SYN
-#define MXC_INT_UART1 MX3x_INT_UART1
-#define MXC_INT_ECT MX3x_INT_ECT
-#define MXC_INT_SCC_SCM MX3x_INT_SCC_SCM
-#define MXC_INT_SCC_SMN MX3x_INT_SCC_SMN
-#define MXC_INT_GPIO2 MX3x_INT_GPIO2
-#define MXC_INT_GPIO1 MX3x_INT_GPIO1
-#define MXC_INT_WDOG MX3x_INT_WDOG
-#define MXC_INT_GPIO3 MX3x_INT_GPIO3
-#define MXC_INT_EXT_POWER MX3x_INT_EXT_POWER
-#define MXC_INT_EXT_TEMPER MX3x_INT_EXT_TEMPER
-#define MXC_INT_EXT_SENSOR60 MX3x_INT_EXT_SENSOR60
-#define MXC_INT_EXT_SENSOR61 MX3x_INT_EXT_SENSOR61
-#define MXC_INT_EXT_WDOG MX3x_INT_EXT_WDOG
-#define MXC_INT_EXT_TV MX3x_INT_EXT_TV
-#define PROD_SIGNATURE MX3x_PROD_SIGNATURE
-#endif
-
 #endif /* ifndef __MACH_MX3x_H__ */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/include/mach/mx50.h linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/include/mach/mx50.h
--- linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/include/mach/mx50.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/include/mach/mx50.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,285 @@
+#ifndef __MACH_MX50_H__
+#define __MACH_MX50_H__
+
+/*
+ * IROM
+ */
+#define MX50_IROM_BASE_ADDR		0x0
+#define MX50_IROM_SIZE			SZ_64K
+
+/* TZIC */
+#define MX50_TZIC_BASE_ADDR		0x0fffc000
+#define MX50_TZIC_SIZE			SZ_16K
+
+/*
+ * IRAM
+ */
+#define MX50_IRAM_BASE_ADDR	0xf8000000	/* internal ram */
+#define MX50_IRAM_PARTITIONS	16
+#define MX50_IRAM_SIZE		(MX50_IRAM_PARTITIONS * SZ_8K)	/* 128KB */
+
+/*
+ * Databahn
+ */
+#define MX50_DATABAHN_BASE_ADDR			0x14000000
+
+/*
+ * Graphics Memory of GPU
+ */
+#define MX50_GPU2D_BASE_ADDR		0x20000000
+
+#define MX50_DEBUG_BASE_ADDR		0x40000000
+#define MX50_DEBUG_SIZE			SZ_1M
+#define MX50_ETB_BASE_ADDR		(MX50_DEBUG_BASE_ADDR + 0x00001000)
+#define MX50_ETM_BASE_ADDR		(MX50_DEBUG_BASE_ADDR + 0x00002000)
+#define MX50_TPIU_BASE_ADDR		(MX50_DEBUG_BASE_ADDR + 0x00003000)
+#define MX50_CTI0_BASE_ADDR		(MX50_DEBUG_BASE_ADDR + 0x00004000)
+#define MX50_CTI1_BASE_ADDR		(MX50_DEBUG_BASE_ADDR + 0x00005000)
+#define MX50_CTI2_BASE_ADDR		(MX50_DEBUG_BASE_ADDR + 0x00006000)
+#define MX50_CTI3_BASE_ADDR		(MX50_DEBUG_BASE_ADDR + 0x00007000)
+#define MX50_CORTEX_DBG_BASE_ADDR	(MX50_DEBUG_BASE_ADDR + 0x00008000)
+
+#define MX50_APBHDMA_BASE_ADDR		(MX50_DEBUG_BASE_ADDR + 0x01000000)
+#define MX50_OCOTP_CTRL_BASE_ADDR	(MX50_DEBUG_BASE_ADDR + 0x01002000)
+#define MX50_DIGCTL_BASE_ADDR		(MX50_DEBUG_BASE_ADDR + 0x01004000)
+#define MX50_GPMI_BASE_ADDR		(MX50_DEBUG_BASE_ADDR + 0x01006000)
+#define MX50_BCH_BASE_ADDR		(MX50_DEBUG_BASE_ADDR + 0x01008000)
+#define MX50_ELCDIF_BASE_ADDR		(MX50_DEBUG_BASE_ADDR + 0x0100a000)
+#define MX50_EPXP_BASE_ADDR		(MX50_DEBUG_BASE_ADDR + 0x0100c000)
+#define MX50_DCP_BASE_ADDR		(MX50_DEBUG_BASE_ADDR + 0x0100e000)
+#define MX50_EPDC_BASE_ADDR		(MX50_DEBUG_BASE_ADDR + 0x01010000)
+#define MX50_QOSC_BASE_ADDR		(MX50_DEBUG_BASE_ADDR + 0x01012000)
+#define MX50_PERFMON_BASE_ADDR		(MX50_DEBUG_BASE_ADDR + 0x01014000)
+#define MX50_SSP_BASE_ADDR		(MX50_DEBUG_BASE_ADDR + 0x01016000)
+#define MX50_ANATOP_BASE_ADDR		(MX50_DEBUG_BASE_ADDR + 0x01018000)
+#define MX50_NIC_BASE_ADDR		(MX50_DEBUG_BASE_ADDR + 0x08000000)
+
+/*
+ * SPBA global module enabled #0
+ */
+#define MX50_SPBA0_BASE_ADDR		0x50000000
+#define MX50_SPBA0_SIZE			SZ_1M
+
+#define MX50_MMC_SDHC1_BASE_ADDR	(MX50_SPBA0_BASE_ADDR + 0x00004000)
+#define MX50_MMC_SDHC2_BASE_ADDR	(MX50_SPBA0_BASE_ADDR + 0x00008000)
+#define MX50_UART3_BASE_ADDR		(MX50_SPBA0_BASE_ADDR + 0x0000c000)
+#define MX50_CSPI1_BASE_ADDR		(MX50_SPBA0_BASE_ADDR + 0x00010000)
+#define MX50_SSI2_BASE_ADDR		(MX50_SPBA0_BASE_ADDR + 0x00014000)
+#define MX50_MMC_SDHC3_BASE_ADDR	(MX50_SPBA0_BASE_ADDR + 0x00020000)
+#define MX50_MMC_SDHC4_BASE_ADDR	(MX50_SPBA0_BASE_ADDR + 0x00024000)
+
+/*
+ * AIPS 1
+ */
+#define MX50_AIPS1_BASE_ADDR	0x53f00000
+#define MX50_AIPS1_SIZE		SZ_1M
+
+#define MX50_OTG_BASE_ADDR	(MX50_AIPS1_BASE_ADDR + 0x00080000)
+#define MX50_GPIO1_BASE_ADDR	(MX50_AIPS1_BASE_ADDR + 0x00084000)
+#define MX50_GPIO2_BASE_ADDR	(MX50_AIPS1_BASE_ADDR + 0x00088000)
+#define MX50_GPIO3_BASE_ADDR	(MX50_AIPS1_BASE_ADDR + 0x0008c000)
+#define MX50_GPIO4_BASE_ADDR	(MX50_AIPS1_BASE_ADDR + 0x00090000)
+#define MX50_KPP_BASE_ADDR	(MX50_AIPS1_BASE_ADDR + 0x00094000)
+#define MX50_WDOG_BASE_ADDR	(MX50_AIPS1_BASE_ADDR + 0x00098000)
+#define MX50_GPT1_BASE_ADDR	(MX50_AIPS1_BASE_ADDR + 0x000a0000)
+#define MX50_SRTC_BASE_ADDR	(MX50_AIPS1_BASE_ADDR + 0x000a4000)
+#define MX50_IOMUXC_BASE_ADDR	(MX50_AIPS1_BASE_ADDR + 0x000a8000)
+#define MX50_EPIT1_BASE_ADDR	(MX50_AIPS1_BASE_ADDR + 0x000ac000)
+#define MX50_PWM1_BASE_ADDR	(MX50_AIPS1_BASE_ADDR + 0x000b4000)
+#define MX50_PWM2_BASE_ADDR	(MX50_AIPS1_BASE_ADDR + 0x000b8000)
+#define MX50_UART1_BASE_ADDR	(MX50_AIPS1_BASE_ADDR + 0x000bc000)
+#define MX50_UART2_BASE_ADDR	(MX50_AIPS1_BASE_ADDR + 0x000c0000)
+#define MX50_SRC_BASE_ADDR	(MX50_AIPS1_BASE_ADDR + 0x000d0000)
+#define MX50_CCM_BASE_ADDR	(MX50_AIPS1_BASE_ADDR + 0x000d4000)
+#define MX50_GPC_BASE_ADDR	(MX50_AIPS1_BASE_ADDR + 0x000d8000)
+#define MX50_GPIO5_BASE_ADDR	(MX50_AIPS1_BASE_ADDR + 0x000dc000)
+#define MX50_GPIO6_BASE_ADDR	(MX50_AIPS1_BASE_ADDR + 0x000e0000)
+#define MX50_I2C3_BASE_ADDR	(MX50_AIPS1_BASE_ADDR + 0x000ec000)
+#define MX50_UART4_BASE_ADDR	(MX50_AIPS1_BASE_ADDR + 0x000f0000)
+
+#define MX50_MSHC_BASE_ADDR	(MX50_AIPS1_BASE_ADDR + 0x000f4000)
+#define MX50_RNGB_BASE_ADDR	(MX50_AIPS1_BASE_ADDR + 0x000f8000)
+
+/*
+ * AIPS 2
+ */
+#define MX50_AIPS2_BASE_ADDR	0x63f00000
+#define MX50_AIPS2_SIZE		SZ_1M
+
+#define MX50_PLL1_BASE_ADDR	(MX50_AIPS2_BASE_ADDR + 0x00080000)
+#define MX50_PLL2_BASE_ADDR	(MX50_AIPS2_BASE_ADDR + 0x00084000)
+#define MX50_PLL3_BASE_ADDR	(MX50_AIPS2_BASE_ADDR + 0x00088000)
+#define MX50_UART5_BASE_ADDR	(MX50_AIPS2_BASE_ADDR + 0x00090000)
+#define MX50_AHBMAX_BASE_ADDR	(MX50_AIPS2_BASE_ADDR + 0x00094000)
+#define MX50_ARM_BASE_ADDR	(MX50_AIPS2_BASE_ADDR + 0x000a0000)
+#define MX50_OWIRE_BASE_ADDR	(MX50_AIPS2_BASE_ADDR + 0x000a4000)
+#define MX50_CSPI2_BASE_ADDR	(MX50_AIPS2_BASE_ADDR + 0x000ac000)
+#define MX50_SDMA_BASE_ADDR	(MX50_AIPS2_BASE_ADDR + 0x000b0000)
+#define MX50_ROMCP_BASE_ADDR	(MX50_AIPS2_BASE_ADDR + 0x000b8000)
+#define MX50_CSPI3_BASE_ADDR	(MX50_AIPS2_BASE_ADDR + 0x000c0000)
+#define MX50_I2C2_BASE_ADDR	(MX50_AIPS2_BASE_ADDR + 0x000c4000)
+#define MX50_I2C1_BASE_ADDR	(MX50_AIPS2_BASE_ADDR + 0x000c8000)
+#define MX50_SSI1_BASE_ADDR	(MX50_AIPS2_BASE_ADDR + 0x000cc000)
+#define MX50_AUDMUX_BASE_ADDR	(MX50_AIPS2_BASE_ADDR + 0x000d0000)
+#define MX50_WEIM_BASE_ADDR	(MX50_AIPS2_BASE_ADDR + 0x000d8000)
+#define MX50_FEC_BASE_ADDR	(MX50_AIPS2_BASE_ADDR + 0x000ec000)
+
+/*
+ * Memory regions and CS
+ */
+#define MX50_CSD0_BASE_ADDR		0x70000000
+#define MX50_CSD1_BASE_ADDR		0xb0000000
+#define MX50_CS0_BASE_ADDR		0xf0000000
+
+#define MX50_IO_P2V(x)			IMX_IO_P2V(x)
+#define MX50_IO_ADDRESS(x)		IOMEM(MX50_IO_P2V(x))
+
+/*
+ * defines for SPBA modules
+ */
+#define MX50_SPBA_SDHC1		0x04
+#define MX50_SPBA_SDHC2		0x08
+#define MX50_SPBA_UART3		0x0c
+#define MX50_SPBA_CSPI1		0x10
+#define MX50_SPBA_SSI2		0x14
+#define MX50_SPBA_SDHC3		0x20
+#define MX50_SPBA_SDHC4		0x24
+#define MX50_SPBA_SPDIF		0x28
+#define MX50_SPBA_ATA		0x30
+#define MX50_SPBA_SLIM		0x34
+#define MX50_SPBA_HSI2C		0x38
+#define MX50_SPBA_CTRL		0x3c
+
+/*
+ * DMA request assignments
+ */
+#define MX50_DMA_REQ_GPC		1
+#define MX50_DMA_REQ_ATA_UART4_RX	2
+#define MX50_DMA_REQ_ATA_UART4_TX	3
+#define MX50_DMA_REQ_CSPI1_RX		6
+#define MX50_DMA_REQ_CSPI1_TX		7
+#define MX50_DMA_REQ_CSPI2_RX		8
+#define MX50_DMA_REQ_CSPI2_TX		9
+#define MX50_DMA_REQ_I2C3_SDHC3		10
+#define MX50_DMA_REQ_SDHC4		11
+#define MX50_DMA_REQ_UART2_FIRI_RX	12
+#define MX50_DMA_REQ_UART2_FIRI_TX	13
+#define MX50_DMA_REQ_EXT0		14
+#define MX50_DMA_REQ_EXT1		15
+#define MX50_DMA_REQ_UART5_RX		16
+#define MX50_DMA_REQ_UART5_TX		17
+#define MX50_DMA_REQ_UART1_RX		18
+#define MX50_DMA_REQ_UART1_TX		19
+#define MX50_DMA_REQ_I2C1_SDHC1		20
+#define MX50_DMA_REQ_I2C2_SDHC2		21
+#define MX50_DMA_REQ_SSI2_RX2		22
+#define MX50_DMA_REQ_SSI2_TX2		23
+#define MX50_DMA_REQ_SSI2_RX1		24
+#define MX50_DMA_REQ_SSI2_TX1		25
+#define MX50_DMA_REQ_SSI1_RX2		26
+#define MX50_DMA_REQ_SSI1_TX2		27
+#define MX50_DMA_REQ_SSI1_RX1		28
+#define MX50_DMA_REQ_SSI1_TX1		29
+#define MX50_DMA_REQ_CSPI_RX		38
+#define MX50_DMA_REQ_CSPI_TX		39
+#define MX50_DMA_REQ_UART3_RX		42
+#define MX50_DMA_REQ_UART3_TX		43
+
+/*
+ * Interrupt numbers
+ */
+#define MX50_INT_MMC_SDHC1	1
+#define MX50_INT_MMC_SDHC2	2
+#define MX50_INT_MMC_SDHC3	3
+#define MX50_INT_MMC_SDHC4	4
+#define MX50_INT_DAP		5
+#define MX50_INT_SDMA		6
+#define MX50_INT_IOMUX		7
+#define MX50_INT_UART4		13
+#define MX50_INT_USB_H1		14
+#define MX50_INT_USB_OTG	18
+#define MX50_INT_DATABAHN	19
+#define MX50_INT_ELCDIF		20
+#define MX50_INT_EPXP		21
+#define MX50_INT_SRTC_NTZ	24
+#define MX50_INT_SRTC_TZ	25
+#define MX50_INT_EPDC		27
+#define MX50_INT_NIC		28
+#define MX50_INT_SSI1		29
+#define MX50_INT_SSI2		30
+#define MX50_INT_UART1		31
+#define MX50_INT_UART2		32
+#define MX50_INT_UART3		33
+#define MX50_INT_RESV34		34
+#define MX50_INT_RESV35		35
+#define MX50_INT_CSPI1		36
+#define MX50_INT_CSPI2		37
+#define MX50_INT_CSPI		38
+#define MX50_INT_GPT		39
+#define MX50_INT_EPIT1		40
+#define MX50_INT_GPIO1_INT7	42
+#define MX50_INT_GPIO1_INT6	43
+#define MX50_INT_GPIO1_INT5	44
+#define MX50_INT_GPIO1_INT4	45
+#define MX50_INT_GPIO1_INT3	46
+#define MX50_INT_GPIO1_INT2	47
+#define MX50_INT_GPIO1_INT1	48
+#define MX50_INT_GPIO1_INT0	49
+#define MX50_INT_GPIO1_LOW	50
+#define MX50_INT_GPIO1_HIGH	51
+#define MX50_INT_GPIO2_LOW	52
+#define MX50_INT_GPIO2_HIGH	53
+#define MX50_INT_GPIO3_LOW	54
+#define MX50_INT_GPIO3_HIGH	55
+#define MX50_INT_GPIO4_LOW	56
+#define MX50_INT_GPIO4_HIGH	57
+#define MX50_INT_WDOG1		58
+#define MX50_INT_KPP		60
+#define MX50_INT_PWM1		61
+#define MX50_INT_I2C1		62
+#define MX50_INT_I2C2		63
+#define MX50_INT_I2C3		64
+#define MX50_INT_RESV65		65
+#define MX50_INT_DCDC		66
+#define MX50_INT_THERMAL_ALARM	67
+#define MX50_INT_ANA3		68
+#define MX50_INT_ANA4		69
+#define MX50_INT_CCM1		71
+#define MX50_INT_CCM2		72
+#define MX50_INT_GPC1		73
+#define MX50_INT_GPC2		74
+#define MX50_INT_SRC		75
+#define MX50_INT_NM		76
+#define MX50_INT_PMU		77
+#define MX50_INT_CTI_IRQ	78
+#define MX50_INT_CTI1_TG0	79
+#define MX50_INT_CTI1_TG1	80
+#define MX50_INT_GPU2_IRQ	84
+#define MX50_INT_GPU2_BUSY	85
+#define MX50_INT_UART5		86
+#define MX50_INT_FEC		87
+#define MX50_INT_OWIRE		88
+#define MX50_INT_CTI1_TG2	89
+#define MX50_INT_SJC		90
+#define MX50_INT_DCP_CHAN1_3	91
+#define MX50_INT_DCP_CHAN0	92
+#define MX50_INT_PWM2		94
+#define MX50_INT_RNGB		97
+#define MX50_INT_CTI1_TG3	98
+#define MX50_INT_RAWNAND_BCH	100
+#define MX50_INT_RAWNAND_GPMI	102
+#define MX50_INT_GPIO5_LOW	103
+#define MX50_INT_GPIO5_HIGH	104
+#define MX50_INT_GPIO6_LOW	105
+#define MX50_INT_GPIO6_HIGH	106
+#define MX50_INT_MSHC		109
+#define MX50_INT_APBHDMA_CHAN0	110
+#define MX50_INT_APBHDMA_CHAN1	111
+#define MX50_INT_APBHDMA_CHAN2	112
+#define MX50_INT_APBHDMA_CHAN3	113
+#define MX50_INT_APBHDMA_CHAN4	114
+#define MX50_INT_APBHDMA_CHAN5	115
+#define MX50_INT_APBHDMA_CHAN6	116
+#define MX50_INT_APBHDMA_CHAN7	117
+
+#endif /* ifndef __MACH_MX50_H__ */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/include/mach/mx51.h linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/include/mach/mx51.h
--- linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/include/mach/mx51.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/include/mach/mx51.h	2011-03-14 21:20:32.000000000 -0400
@@ -2,31 +2,6 @@
 #define __MACH_MX51_H__
 
 /*
- * MX51 memory map:
- *
- *
- * Virt		Phys		Size	What
- * ---------------------------------------------------------------------------
- * fa3e0000	1ffe0000	128K	IRAM (SCCv2 RAM)
- *         	30000000	256M	GPU
- *         	40000000	512M	IPU
- * fa200000	60000000	1M	DEBUG
- * fb100000	70000000	1M	SPBA 0
- * fb000000	73f00000	1M	AIPS 1
- * fb200000	83f00000	1M	AIPS 2
- *		8fffc000	16K	TZIC (interrupt controller)
- *         	90000000	256M	CSD0 SDRAM/DDR
- *         	a0000000	256M	CSD1 SDRAM/DDR
- *         	b0000000	128M	CS0 Flash
- *         	b8000000	128M	CS1 Flash
- *         	c0000000	128M	CS2 Flash
- *         	c8000000	64M	CS3 Flash
- *         	cc000000	32M	CS4 SRAM
- *         	ce000000	32M	CS5 SRAM
- *		cfff0000	64K	NFC (NAND Flash AXI)
- */
-
-/*
  * IROM
  */
 #define MX51_IROM_BASE_ADDR		0x0
@@ -36,7 +11,6 @@
  * IRAM
  */
 #define MX51_IRAM_BASE_ADDR		0x1ffe0000	/* internal ram */
-#define MX51_IRAM_BASE_ADDR_VIRT	0xfa3e0000
 #define MX51_IRAM_PARTITIONS		16
 #define MX51_IRAM_SIZE		(MX51_IRAM_PARTITIONS * SZ_8K)	/* 128KB */
 
@@ -45,7 +19,6 @@
 #define MX51_IPU_CTRL_BASE_ADDR		0x40000000
 
 #define MX51_DEBUG_BASE_ADDR		0x60000000
-#define MX51_DEBUG_BASE_ADDR_VIRT	0xfa200000
 #define MX51_DEBUG_SIZE			SZ_1M
 
 #define MX51_ETB_BASE_ADDR		(MX51_DEBUG_BASE_ADDR + 0x01000)
@@ -61,7 +34,6 @@
  * SPBA global module enabled #0
  */
 #define MX51_SPBA0_BASE_ADDR		0x70000000
-#define MX51_SPBA0_BASE_ADDR_VIRT	0xfb100000
 #define MX51_SPBA0_SIZE			SZ_1M
 
 #define MX51_ESDHC1_BASE_ADDR		(MX51_SPBA0_BASE_ADDR + 0x04000)
@@ -81,7 +53,6 @@
  * AIPS 1
  */
 #define MX51_AIPS1_BASE_ADDR		0x73f00000
-#define MX51_AIPS1_BASE_ADDR_VIRT	0xfb000000
 #define MX51_AIPS1_SIZE			SZ_1M
 
 #define MX51_OTG_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0x80000)
@@ -90,7 +61,7 @@
 #define MX51_GPIO3_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0x8c000)
 #define MX51_GPIO4_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0x90000)
 #define MX51_KPP_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0x94000)
-#define MX51_WDOG_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0x98000)
+#define MX51_WDOG1_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0x98000)
 #define MX51_WDOG2_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0x9c000)
 #define MX51_GPT1_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0xa0000)
 #define MX51_SRTC_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0xa4000)
@@ -109,7 +80,6 @@
  * AIPS 2
  */
 #define MX51_AIPS2_BASE_ADDR		0x83f00000
-#define MX51_AIPS2_BASE_ADDR_VIRT	0xfb200000
 #define MX51_AIPS2_SIZE			SZ_1M
 
 #define MX51_PLL1_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0x80000)
@@ -139,7 +109,7 @@
 #define MX51_MIPI_HSC_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xdc000)
 #define MX51_ATA_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xe0000)
 #define MX51_SIM_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xe4000)
-#define MX51_SSI3BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xe8000)
+#define MX51_SSI3_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xe8000)
 #define MX51_FEC_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xec000)
 #define MX51_TVE_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xf0000)
 #define MX51_VPU_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xf4000)
@@ -163,16 +133,8 @@
 #define MX51_GPU2D_BASE_ADDR		0xd0000000
 #define MX51_TZIC_BASE_ADDR		0xe0000000
 
-#define MX51_IO_ADDRESS(x) (						\
-	IMX_IO_ADDRESS(x, MX51_IRAM) ?:					\
-	IMX_IO_ADDRESS(x, MX51_DEBUG) ?:				\
-	IMX_IO_ADDRESS(x, MX51_SPBA0) ?:				\
-	IMX_IO_ADDRESS(x, MX51_AIPS1) ?:				\
-	IMX_IO_ADDRESS(x, MX51_AIPS2))
-
-/* This is currently used in <mach/debug-macro.S>, but should go away */
-#define MX51_AIPS1_IO_ADDRESS(x)  \
-	(((x) - MX51_AIPS1_BASE_ADDR) + MX51_AIPS1_BASE_ADDR_VIRT)
+#define MX51_IO_P2V(x)			IMX_IO_P2V(x)
+#define MX51_IO_ADDRESS(x)		IOMEM(MX51_IO_P2V(x))
 
 /*
  * defines for SPBA modules
@@ -261,9 +223,9 @@
 #define MX51_DMA_REQ_EMI_WR		32
 #define MX51_DMA_REQ_CTI2_1		33
 #define MX51_DMA_REQ_EPIT2		34
-#define MX51_DMA_REQ_SSI3_RX2		35
+#define MX51_DMA_REQ_SSI3_RX1		35
 #define MX51_DMA_REQ_IPU		36
-#define MX51_DMA_REQ_SSI3_TX2		37
+#define MX51_DMA_REQ_SSI3_TX1		37
 #define MX51_DMA_REQ_CSPI_RX		38
 #define MX51_DMA_REQ_CSPI_TX		39
 #define MX51_DMA_REQ_SDHC3		40
@@ -272,8 +234,8 @@
 #define MX51_DMA_REQ_UART3_RX		43
 #define MX51_DMA_REQ_UART3_TX		44
 #define MX51_DMA_REQ_SPDIF		45
-#define MX51_DMA_REQ_SSI3_RX1		46
-#define MX51_DMA_REQ_SSI3_TX1		47
+#define MX51_DMA_REQ_SSI3_RX0		46
+#define MX51_DMA_REQ_SSI3_TX0		47
 
 /*
  * Interrupt numbers
@@ -289,8 +251,8 @@
 #define MX51_MXC_INT_IOMUX		7
 #define MX51_INT_NFC			8
 #define MX51_MXC_INT_VPU		9
-#define MX51_MXC_INT_IPU_ERR		10
-#define MX51_MXC_INT_IPU_SYN		11
+#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
@@ -339,8 +301,8 @@
 #define MX51_MXC_INT_GPIO4_HIGH		57
 #define MX51_MXC_INT_WDOG1		58
 #define MX51_MXC_INT_WDOG2		59
-#define MX51_MXC_INT_KPP		60
-#define MX51_MXC_INT_PWM1		61
+#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
@@ -373,9 +335,9 @@
 #define MX51_MXC_INT_SPDIF		91
 #define MX51_MXC_INT_TVE		92
 #define MX51_MXC_INT_FIRI		93
-#define MX51_MXC_INT_PWM2		94
+#define MX51_INT_PWM2			94
 #define MX51_MXC_INT_SLIM_EXP		95
-#define MX51_MXC_INT_SSI3		96
+#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
@@ -383,19 +345,6 @@
 #define MX51_MXC_INT_EMI_NFC		101
 #define MX51_MXC_INT_GPU_IDLE		102
 
-/* silicon revisions specific to i.MX51 */
-#define MX51_CHIP_REV_1_0		0x10
-#define MX51_CHIP_REV_1_1		0x11
-#define MX51_CHIP_REV_1_2		0x12
-#define MX51_CHIP_REV_1_3		0x13
-#define MX51_CHIP_REV_2_0		0x20
-#define MX51_CHIP_REV_2_1		0x21
-#define MX51_CHIP_REV_2_2		0x22
-#define MX51_CHIP_REV_2_3		0x23
-#define MX51_CHIP_REV_3_0		0x30
-#define MX51_CHIP_REV_3_1		0x31
-#define MX51_CHIP_REV_3_2		0x32
-
 #if !defined(__ASSEMBLY__) && !defined(__MXC_BOOT_UNCOMPRESS)
 extern int mx51_revision(void);
 #endif
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/include/mach/mx53.h linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/include/mach/mx53.h
--- linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/include/mach/mx53.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/include/mach/mx53.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,353 @@
+#ifndef __MACH_MX53_H__
+#define __MACH_MX53_H__
+
+/*
+ * IROM
+ */
+#define MX53_IROM_BASE_ADDR		0x0
+#define MX53_IROM_SIZE			SZ_64K
+
+/* TZIC */
+#define MX53_TZIC_BASE_ADDR		0x0FFFC000
+
+/*
+ * AHCI SATA
+ */
+#define MX53_SATA_BASE_ADDR		0x10000000
+
+/*
+ * NFC
+ */
+#define MX53_NFC_AXI_BASE_ADDR	0xF7FF0000	/* NAND flash AXI */
+#define MX53_NFC_AXI_SIZE		SZ_64K
+
+/*
+ * IRAM
+ */
+#define MX53_IRAM_BASE_ADDR	0xF8000000	/* internal ram */
+#define MX53_IRAM_PARTITIONS	16
+#define MX53_IRAM_SIZE		(MX53_IRAM_PARTITIONS * SZ_8K)	/* 128KB */
+
+/*
+ * Graphics Memory of GPU
+ */
+#define MX53_IPU_CTRL_BASE_ADDR	0x18000000
+#define MX53_GPU2D_BASE_ADDR		0x20000000
+#define MX53_GPU_BASE_ADDR		0x30000000
+#define MX53_GPU_GMEM_BASE_ADDR	0xF8020000
+
+#define MX53_DEBUG_BASE_ADDR		0x40000000
+#define MX53_DEBUG_SIZE		SZ_1M
+#define MX53_ETB_BASE_ADDR		(MX53_DEBUG_BASE_ADDR + 0x00001000)
+#define MX53_ETM_BASE_ADDR		(MX53_DEBUG_BASE_ADDR + 0x00002000)
+#define MX53_TPIU_BASE_ADDR		(MX53_DEBUG_BASE_ADDR + 0x00003000)
+#define MX53_CTI0_BASE_ADDR		(MX53_DEBUG_BASE_ADDR + 0x00004000)
+#define MX53_CTI1_BASE_ADDR		(MX53_DEBUG_BASE_ADDR + 0x00005000)
+#define MX53_CTI2_BASE_ADDR		(MX53_DEBUG_BASE_ADDR + 0x00006000)
+#define MX53_CTI3_BASE_ADDR		(MX53_DEBUG_BASE_ADDR + 0x00007000)
+#define MX53_CORTEX_DBG_BASE_ADDR	(MX53_DEBUG_BASE_ADDR + 0x00008000)
+
+/*
+ * SPBA global module enabled #0
+ */
+#define MX53_SPBA0_BASE_ADDR		0x50000000
+#define MX53_SPBA0_SIZE		SZ_1M
+
+#define MX53_ESDHC1_BASE_ADDR	(MX53_SPBA0_BASE_ADDR + 0x00004000)
+#define MX53_ESDHC2_BASE_ADDR	(MX53_SPBA0_BASE_ADDR + 0x00008000)
+#define MX53_UART3_BASE_ADDR		(MX53_SPBA0_BASE_ADDR + 0x0000C000)
+#define MX53_ECSPI1_BASE_ADDR		(MX53_SPBA0_BASE_ADDR + 0x00010000)
+#define MX53_SSI2_BASE_ADDR		(MX53_SPBA0_BASE_ADDR + 0x00014000)
+#define MX53_ESDHC3_BASE_ADDR	(MX53_SPBA0_BASE_ADDR + 0x00020000)
+#define MX53_ESDHC4_BASE_ADDR	(MX53_SPBA0_BASE_ADDR + 0x00024000)
+#define MX53_SPDIF_BASE_ADDR		(MX53_SPBA0_BASE_ADDR + 0x00028000)
+#define MX53_ASRC_BASE_ADDR		(MX53_SPBA0_BASE_ADDR + 0x0002C000)
+#define MX53_ATA_DMA_BASE_ADDR	(MX53_SPBA0_BASE_ADDR + 0x00030000)
+#define MX53_SLIM_DMA_BASE_ADDR	(MX53_SPBA0_BASE_ADDR + 0x00034000)
+#define MX53_HSI2C_DMA_BASE_ADDR	(MX53_SPBA0_BASE_ADDR + 0x00038000)
+#define MX53_SPBA_CTRL_BASE_ADDR	(MX53_SPBA0_BASE_ADDR + 0x0003C000)
+
+/*
+ * AIPS 1
+ */
+#define MX53_AIPS1_BASE_ADDR	0x53F00000
+#define MX53_AIPS1_SIZE		SZ_1M
+
+#define MX53_OTG_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x00080000)
+#define MX53_GPIO1_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x00084000)
+#define MX53_GPIO2_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x00088000)
+#define MX53_GPIO3_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x0008C000)
+#define MX53_GPIO4_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x00090000)
+#define MX53_KPP_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x00094000)
+#define MX53_WDOG_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x00098000)
+#define MX53_WDOG2_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x0009C000)
+#define MX53_GPT1_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x000A0000)
+#define MX53_SRTC_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x000A4000)
+#define MX53_IOMUXC_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x000A8000)
+#define MX53_EPIT1_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x000AC000)
+#define MX53_EPIT2_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x000B0000)
+#define MX53_PWM1_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x000B4000)
+#define MX53_PWM2_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x000B8000)
+#define MX53_UART1_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x000BC000)
+#define MX53_UART2_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x000C0000)
+#define MX53_SRC_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x000D0000)
+#define MX53_CCM_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x000D4000)
+#define MX53_GPC_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x000D8000)
+#define MX53_GPIO5_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x000DC000)
+#define MX53_GPIO6_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x000E0000)
+#define MX53_GPIO7_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x000E4000)
+#define MX53_ATA_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x000E8000)
+#define MX53_I2C3_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x000EC000)
+#define MX53_UART4_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x000F0000)
+
+/*
+ * AIPS 2
+ */
+#define MX53_AIPS2_BASE_ADDR		0x63F00000
+#define MX53_AIPS2_SIZE			SZ_1M
+
+#define MX53_PLL1_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x00080000)
+#define MX53_PLL2_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x00084000)
+#define MX53_PLL3_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x00088000)
+#define MX53_PLL4_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x0008C000)
+#define MX53_UART5_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x00090000)
+#define MX53_AHBMAX_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x00094000)
+#define MX53_IIM_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x00098000)
+#define MX53_CSU_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x0009C000)
+#define MX53_ARM_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000A0000)
+#define MX53_OWIRE_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000A4000)
+#define MX53_FIRI_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000A8000)
+#define MX53_ECSPI2_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000AC000)
+#define MX53_SDMA_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000B0000)
+#define MX53_SCC_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000B4000)
+#define MX53_ROMCP_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000B8000)
+#define MX53_RTIC_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000BC000)
+#define MX53_CSPI_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000C0000)
+#define MX53_I2C2_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000C4000)
+#define MX53_I2C1_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000C8000)
+#define MX53_SSI1_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000CC000)
+#define MX53_AUDMUX_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000D0000)
+#define MX53_RTC_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000D4000)
+#define MX53_M4IF_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000D8000)
+#define MX53_ESDCTL_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000D9000)
+#define MX53_WEIM_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000DA000)
+#define MX53_NFC_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000DB000)
+#define MX53_EMI_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000DBF00)
+#define MX53_MIPI_HSC_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000DC000)
+#define MX53_MLB_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000E4000)
+#define MX53_SSI3_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000E8000)
+#define MX53_FEC_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000EC000)
+#define MX53_TVE_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000F0000)
+#define MX53_VPU_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000F4000)
+#define MX53_SAHARA_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000F8000)
+#define MX53_PTP_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000FC000)
+
+/*
+ * Memory regions and CS
+ */
+#define MX53_CSD0_BASE_ADDR		0x90000000
+#define MX53_CSD1_BASE_ADDR		0xA0000000
+#define MX53_CS0_BASE_ADDR		0xB0000000
+#define MX53_CS1_BASE_ADDR		0xB8000000
+#define MX53_CS2_BASE_ADDR		0xC0000000
+#define MX53_CS3_BASE_ADDR		0xC8000000
+#define MX53_CS4_BASE_ADDR		0xCC000000
+#define MX53_CS5_BASE_ADDR		0xCE000000
+
+#define MX53_IO_P2V(x)			IMX_IO_P2V(x)
+#define MX53_IO_ADDRESS(x)		IOMEM(MX53_IO_P2V(x))
+
+/*
+ * defines for SPBA modules
+ */
+#define MX53_SPBA_SDHC1	0x04
+#define MX53_SPBA_SDHC2	0x08
+#define MX53_SPBA_UART3	0x0C
+#define MX53_SPBA_CSPI1	0x10
+#define MX53_SPBA_SSI2		0x14
+#define MX53_SPBA_SDHC3	0x20
+#define MX53_SPBA_SDHC4	0x24
+#define MX53_SPBA_SPDIF	0x28
+#define MX53_SPBA_ATA		0x30
+#define MX53_SPBA_SLIM		0x34
+#define MX53_SPBA_HSI2C	0x38
+#define MX53_SPBA_CTRL		0x3C
+
+/*
+ * DMA request assignments
+ */
+#define MX53_DMA_REQ_SSI3_TX1		47
+#define MX53_DMA_REQ_SSI3_RX1		46
+#define MX53_DMA_REQ_SSI3_TX2		45
+#define MX53_DMA_REQ_SSI3_RX2		44
+#define MX53_DMA_REQ_UART3_TX	43
+#define MX53_DMA_REQ_UART3_RX	42
+#define MX53_DMA_REQ_ESAI_TX		41
+#define MX53_DMA_REQ_ESAI_RX		40
+#define MX53_DMA_REQ_CSPI_TX		39
+#define MX53_DMA_REQ_CSPI_RX		38
+#define MX53_DMA_REQ_ASRC_DMA6	37
+#define MX53_DMA_REQ_ASRC_DMA5	36
+#define MX53_DMA_REQ_ASRC_DMA4	35
+#define MX53_DMA_REQ_ASRC_DMA3	34
+#define MX53_DMA_REQ_ASRC_DMA2	33
+#define MX53_DMA_REQ_ASRC_DMA1	32
+#define MX53_DMA_REQ_EMI_WR		31
+#define MX53_DMA_REQ_EMI_RD		30
+#define MX53_DMA_REQ_SSI1_TX1		29
+#define MX53_DMA_REQ_SSI1_RX1		28
+#define MX53_DMA_REQ_SSI1_TX2		27
+#define MX53_DMA_REQ_SSI1_RX2		26
+#define MX53_DMA_REQ_SSI2_TX1		25
+#define MX53_DMA_REQ_SSI2_RX1		24
+#define MX53_DMA_REQ_SSI2_TX2		23
+#define MX53_DMA_REQ_SSI2_RX2		22
+#define MX53_DMA_REQ_I2C2_SDHC2	21
+#define MX53_DMA_REQ_I2C1_SDHC1	20
+#define MX53_DMA_REQ_UART1_TX	19
+#define MX53_DMA_REQ_UART1_RX	18
+#define MX53_DMA_REQ_UART5_TX	17
+#define MX53_DMA_REQ_UART5_RX	16
+#define MX53_DMA_REQ_SPDIF_TX		15
+#define MX53_DMA_REQ_SPDIF_RX		14
+#define MX53_DMA_REQ_UART2_FIRI_TX	13
+#define MX53_DMA_REQ_UART2_FIRI_RX	12
+#define MX53_DMA_REQ_SDHC4		11
+#define MX53_DMA_REQ_I2C3_SDHC3	10
+#define MX53_DMA_REQ_CSPI2_TX		9
+#define MX53_DMA_REQ_CSPI2_RX		8
+#define MX53_DMA_REQ_CSPI1_TX		7
+#define MX53_DMA_REQ_CSPI1_RX		6
+#define MX53_DMA_REQ_IPU		5
+#define MX53_DMA_REQ_ATA_TX_END	4
+#define MX53_DMA_REQ_ATA_UART4_TX	3
+#define MX53_DMA_REQ_ATA_UART4_RX	2
+#define MX53_DMA_REQ_GPC		1
+#define MX53_DMA_REQ_VPU		0
+
+/*
+ * Interrupt numbers
+ */
+#define MX53_INT_RESV0		0
+#define MX53_INT_ESDHC1	1
+#define MX53_INT_ESDHC2	2
+#define MX53_INT_ESDHC3	3
+#define MX53_INT_ESDHC4	4
+#define MX53_INT_RESV5	5
+#define MX53_INT_SDMA	6
+#define MX53_INT_IOMUX	7
+#define MX53_INT_NFC	8
+#define MX53_INT_VPU	9
+#define MX53_INT_IPU_ERR	10
+#define MX53_INT_IPU_SYN	11
+#define MX53_INT_GPU	12
+#define MX53_INT_RESV13	13
+#define MX53_INT_USB_H1	14
+#define MX53_INT_EMI	15
+#define MX53_INT_USB_H2	16
+#define MX53_INT_USB_H3	17
+#define MX53_INT_USB_OTG	18
+#define MX53_INT_SAHARA_H0	19
+#define MX53_INT_SAHARA_H1	20
+#define MX53_INT_SCC_SMN	21
+#define MX53_INT_SCC_STZ	22
+#define MX53_INT_SCC_SCM	23
+#define MX53_INT_SRTC_NTZ	24
+#define MX53_INT_SRTC_TZ	25
+#define MX53_INT_RTIC	26
+#define MX53_INT_CSU	27
+#define MX53_INT_SATA	28
+#define MX53_INT_SSI1	29
+#define MX53_INT_SSI2	30
+#define MX53_INT_UART1	31
+#define MX53_INT_UART2	32
+#define MX53_INT_UART3	33
+#define MX53_INT_RESV34	34
+#define MX53_INT_RESV35	35
+#define MX53_INT_ECSPI1	36
+#define MX53_INT_ECSPI2	37
+#define MX53_INT_CSPI	38
+#define MX53_INT_GPT	39
+#define MX53_INT_EPIT1	40
+#define MX53_INT_EPIT2	41
+#define MX53_INT_GPIO1_INT7	42
+#define MX53_INT_GPIO1_INT6	43
+#define MX53_INT_GPIO1_INT5	44
+#define MX53_INT_GPIO1_INT4	45
+#define MX53_INT_GPIO1_INT3	46
+#define MX53_INT_GPIO1_INT2	47
+#define MX53_INT_GPIO1_INT1	48
+#define MX53_INT_GPIO1_INT0	49
+#define MX53_INT_GPIO1_LOW	50
+#define MX53_INT_GPIO1_HIGH	51
+#define MX53_INT_GPIO2_LOW	52
+#define MX53_INT_GPIO2_HIGH	53
+#define MX53_INT_GPIO3_LOW	54
+#define MX53_INT_GPIO3_HIGH	55
+#define MX53_INT_GPIO4_LOW	56
+#define MX53_INT_GPIO4_HIGH	57
+#define MX53_INT_WDOG1	58
+#define MX53_INT_WDOG2	59
+#define MX53_INT_KPP	60
+#define MX53_INT_PWM1	61
+#define MX53_INT_I2C1	62
+#define MX53_INT_I2C2	63
+#define MX53_INT_I2C3	64
+#define MX53_INT_RESV65	65
+#define MX53_INT_RESV66	66
+#define MX53_INT_SPDIF	67
+#define MX53_INT_SIM_DAT	68
+#define MX53_INT_IIM	69
+#define MX53_INT_ATA	70
+#define MX53_INT_CCM1	71
+#define MX53_INT_CCM2	72
+#define MX53_INT_GPC1	73
+#define MX53_INT_GPC2	74
+#define MX53_INT_SRC	75
+#define MX53_INT_NM		76
+#define MX53_INT_PMU	77
+#define MX53_INT_CTI_IRQ	78
+#define MX53_INT_CTI1_TG0	79
+#define MX53_INT_CTI1_TG1	80
+#define MX53_INT_ESAI	81
+#define MX53_INT_CAN1	82
+#define MX53_INT_CAN2	83
+#define MX53_INT_GPU2_IRQ	84
+#define MX53_INT_GPU2_BUSY	85
+#define MX53_INT_RESV86	86
+#define MX53_INT_FEC	87
+#define MX53_INT_OWIRE	88
+#define MX53_INT_CTI1_TG2	89
+#define MX53_INT_SJC	90
+#define MX53_INT_TVE	92
+#define MX53_INT_FIRI	93
+#define MX53_INT_PWM2	94
+#define MX53_INT_SLIM_EXP	95
+#define MX53_INT_SSI3	96
+#define MX53_INT_EMI_BOOT	97
+#define MX53_INT_CTI1_TG3	98
+#define MX53_INT_SMC_RX	99
+#define MX53_INT_VPU_IDLE	100
+#define MX53_INT_EMI_NFC	101
+#define MX53_INT_GPU_IDLE	102
+#define MX53_INT_GPIO5_LOW	103
+#define MX53_INT_GPIO5_HIGH	104
+#define MX53_INT_GPIO6_LOW	105
+#define MX53_INT_GPIO6_HIGH	106
+#define MX53_INT_GPIO7_LOW	107
+#define MX53_INT_GPIO7_HIGH	108
+
+/* silicon revisions specific to i.MX53 */
+#define MX53_CHIP_REV_1_0		0x10
+#define MX53_CHIP_REV_1_1		0x11
+#define MX53_CHIP_REV_1_2		0x12
+#define MX53_CHIP_REV_1_3		0x13
+#define MX53_CHIP_REV_2_0		0x20
+#define MX53_CHIP_REV_2_1		0x21
+#define MX53_CHIP_REV_2_2		0x22
+#define MX53_CHIP_REV_2_3		0x23
+#define MX53_CHIP_REV_3_0		0x30
+#define MX53_CHIP_REV_3_1		0x31
+#define MX53_CHIP_REV_3_2		0x32
+
+#endif /* ifndef __MACH_MX53_H__ */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/include/mach/mxc91231.h linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/include/mach/mxc91231.h
--- linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/include/mach/mxc91231.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/include/mach/mxc91231.h	2011-03-14 21:20:32.000000000 -0400
@@ -21,14 +21,12 @@
  * L2CC
  */
 #define MXC91231_L2CC_BASE_ADDR		0x30000000
-#define MXC91231_L2CC_BASE_ADDR_VIRT	0xF9000000
 #define MXC91231_L2CC_SIZE		SZ_64K
 
 /*
  * AIPS 1
  */
 #define MXC91231_AIPS1_BASE_ADDR	0x43F00000
-#define MXC91231_AIPS1_BASE_ADDR_VIRT	0xFC000000
 #define MXC91231_AIPS1_SIZE		SZ_1M
 
 #define MXC91231_AIPS1_CTRL_BASE_ADDR	MXC91231_AIPS1_BASE_ADDR
@@ -53,7 +51,6 @@
  * AIPS 2
  */
 #define MXC91231_AIPS2_BASE_ADDR	0x53F00000
-#define MXC91231_AIPS2_BASE_ADDR_VIRT	0xFC100000
 #define MXC91231_AIPS2_SIZE		SZ_1M
 
 #define MXC91231_GEMK_BASE_ADDR		(MXC91231_AIPS2_BASE_ADDR + 0x8C000)
@@ -79,7 +76,6 @@
  * SPBA global module 0
  */
 #define MXC91231_SPBA0_BASE_ADDR	0x50000000
-#define MXC91231_SPBA0_BASE_ADDR_VIRT	0xFC200000
 #define MXC91231_SPBA0_SIZE		SZ_1M
 
 #define MXC91231_MMC_SDHC1_BASE_ADDR	(MXC91231_SPBA0_BASE_ADDR + 0x04000)
@@ -109,7 +105,6 @@
  * SPBA global module 1
  */
 #define MXC91231_SPBA1_BASE_ADDR	0x52000000
-#define MXC91231_SPBA1_BASE_ADDR_VIRT	0xFC300000
 #define MXC91231_SPBA1_SIZE		SZ_1M
 
 #define MXC91231_MQSPI_BASE_ADDR	(MXC91231_SPBA1_BASE_ADDR + 0x34000)
@@ -144,18 +139,15 @@
  * ROMP and AVIC
  */
 #define MXC91231_ROMP_BASE_ADDR		0x60000000
-#define MXC91231_ROMP_BASE_ADDR_VIRT	0xFC400000
 #define MXC91231_ROMP_SIZE		SZ_64K
 
 #define MXC91231_AVIC_BASE_ADDR		0x68000000
-#define MXC91231_AVIC_BASE_ADDR_VIRT	0xFC410000
 #define MXC91231_AVIC_SIZE		SZ_64K
 
 /*
  * NAND, SDRAM, WEIM, M3IF, EMI controllers
  */
 #define MXC91231_X_MEMC_BASE_ADDR	0xB8000000
-#define MXC91231_X_MEMC_BASE_ADDR_VIRT	0xFC420000
 #define MXC91231_X_MEMC_SIZE		SZ_64K
 
 #define MXC91231_NFC_BASE_ADDR		(MXC91231_X_MEMC_BASE_ADDR + 0x0000)
@@ -183,19 +175,10 @@
 /*
  * This macro defines the physical to virtual address mapping for all the
  * peripheral modules. It is used by passing in the physical address as x
- * and returning the virtual address. If the physical address is not mapped,
- * it returns 0.
+ * and returning the virtual address.
  */
-
-#define MXC91231_IO_ADDRESS(x) (					\
-	IMX_IO_ADDRESS(x, MXC91231_L2CC) ?:				\
-	IMX_IO_ADDRESS(x, MXC91231_X_MEMC) ?:				\
-	IMX_IO_ADDRESS(x, MXC91231_ROMP) ?:				\
-	IMX_IO_ADDRESS(x, MXC91231_AVIC) ?:				\
-	IMX_IO_ADDRESS(x, MXC91231_AIPS1) ?:				\
-	IMX_IO_ADDRESS(x, MXC91231_SPBA0) ?:				\
-	IMX_IO_ADDRESS(x, MXC91231_SPBA1) ?:				\
-	IMX_IO_ADDRESS(x, MXC91231_AIPS2))
+#define MXC91231_IO_P2V(x)		IMX_IO_P2V(x)
+#define MXC91231_IO_ADDRESS(x)		IOMEM(MXC91231_IO_P2V(x))
 
 /*
  * Interrupt numbers
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/include/mach/mxc_ehci.h linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/include/mach/mxc_ehci.h
--- linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/include/mach/mxc_ehci.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/include/mach/mxc_ehci.h	2011-03-14 21:20:32.000000000 -0400
@@ -31,6 +31,7 @@
 #define MXC_USBCTRL_OFFSET		0
 #define MXC_USB_PHY_CTR_FUNC_OFFSET	0x8
 #define MXC_USB_PHY_CTR_FUNC2_OFFSET	0xc
+#define MXC_USBH2CTRL_OFFSET		0x14
 
 #define MX5_USBOTHER_REGS_OFFSET	0x800
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/include/mach/mxc.h linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/include/mach/mxc.h
--- linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/include/mach/mxc.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/include/mach/mxc.h	2011-03-14 21:20:32.000000000 -0400
@@ -32,9 +32,25 @@
 #define MXC_CPU_MX27		27
 #define MXC_CPU_MX31		31
 #define MXC_CPU_MX35		35
+#define MXC_CPU_MX50		50
 #define MXC_CPU_MX51		51
+#define MXC_CPU_MX53		53
 #define MXC_CPU_MXC91231	91231
 
+#define IMX_CHIP_REVISION_1_0		0x10
+#define IMX_CHIP_REVISION_1_1		0x11
+#define IMX_CHIP_REVISION_1_2		0x12
+#define IMX_CHIP_REVISION_1_3		0x13
+#define IMX_CHIP_REVISION_2_0		0x20
+#define IMX_CHIP_REVISION_2_1		0x21
+#define IMX_CHIP_REVISION_2_2		0x22
+#define IMX_CHIP_REVISION_2_3		0x23
+#define IMX_CHIP_REVISION_3_0		0x30
+#define IMX_CHIP_REVISION_3_1		0x31
+#define IMX_CHIP_REVISION_3_2		0x32
+#define IMX_CHIP_REVISION_3_3		0x33
+#define IMX_CHIP_REVISION_UNKNOWN	0xff
+
 #ifndef __ASSEMBLY__
 extern unsigned int __mxc_cpu_type;
 #endif
@@ -111,7 +127,19 @@ extern unsigned int __mxc_cpu_type;
 # define cpu_is_mx35()		(0)
 #endif
 
-#ifdef CONFIG_ARCH_MX5
+#ifdef CONFIG_ARCH_MX50
+# ifdef mxc_cpu_type
+#  undef mxc_cpu_type
+#  define mxc_cpu_type __mxc_cpu_type
+# else
+#  define mxc_cpu_type MXC_CPU_MX50
+# endif
+# define cpu_is_mx50()		(mxc_cpu_type == MXC_CPU_MX50)
+#else
+# define cpu_is_mx50()		(0)
+#endif
+
+#ifdef CONFIG_ARCH_MX51
 # ifdef mxc_cpu_type
 #  undef mxc_cpu_type
 #  define mxc_cpu_type __mxc_cpu_type
@@ -123,6 +151,18 @@ extern unsigned int __mxc_cpu_type;
 # define cpu_is_mx51()		(0)
 #endif
 
+#ifdef CONFIG_ARCH_MX53
+# ifdef mxc_cpu_type
+#  undef mxc_cpu_type
+#  define mxc_cpu_type __mxc_cpu_type
+# else
+#  define mxc_cpu_type MXC_CPU_MX53
+# endif
+# define cpu_is_mx53()		(mxc_cpu_type == MXC_CPU_MX53)
+#else
+# define cpu_is_mx53()		(0)
+#endif
+
 #ifdef CONFIG_ARCH_MXC91231
 # ifdef mxc_cpu_type
 #  undef mxc_cpu_type
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/include/mach/sdma.h linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/include/mach/sdma.h
--- linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/include/mach/sdma.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/include/mach/sdma.h	2011-03-14 21:20:32.000000000 -0400
@@ -2,16 +2,62 @@
 #define __MACH_MXC_SDMA_H__
 
 /**
+ * struct sdma_script_start_addrs - SDMA script start pointers
+ *
+ * start addresses of the different functions in the physical
+ * address space of the SDMA engine.
+ */
+struct sdma_script_start_addrs {
+	s32 ap_2_ap_addr;
+	s32 ap_2_bp_addr;
+	s32 ap_2_ap_fixed_addr;
+	s32 bp_2_ap_addr;
+	s32 loopback_on_dsp_side_addr;
+	s32 mcu_interrupt_only_addr;
+	s32 firi_2_per_addr;
+	s32 firi_2_mcu_addr;
+	s32 per_2_firi_addr;
+	s32 mcu_2_firi_addr;
+	s32 uart_2_per_addr;
+	s32 uart_2_mcu_addr;
+	s32 per_2_app_addr;
+	s32 mcu_2_app_addr;
+	s32 per_2_per_addr;
+	s32 uartsh_2_per_addr;
+	s32 uartsh_2_mcu_addr;
+	s32 per_2_shp_addr;
+	s32 mcu_2_shp_addr;
+	s32 ata_2_mcu_addr;
+	s32 mcu_2_ata_addr;
+	s32 app_2_per_addr;
+	s32 app_2_mcu_addr;
+	s32 shp_2_per_addr;
+	s32 shp_2_mcu_addr;
+	s32 mshc_2_mcu_addr;
+	s32 mcu_2_mshc_addr;
+	s32 spdif_2_mcu_addr;
+	s32 mcu_2_spdif_addr;
+	s32 asrc_2_mcu_addr;
+	s32 ext_mem_2_ipu_addr;
+	s32 descrambler_addr;
+	s32 dptc_dvfs_addr;
+	s32 utra_addr;
+	s32 ram_code_start_addr;
+};
+
+/**
  * struct sdma_platform_data - platform specific data for SDMA engine
  *
  * @sdma_version	The version of this SDMA engine
  * @cpu_name		used to generate the firmware name
  * @to_version		CPU Tape out version
+ * @script_addrs	SDMA scripts addresses in SDMA ROM
  */
 struct sdma_platform_data {
 	int sdma_version;
 	char *cpu_name;
 	int to_version;
+	struct sdma_script_start_addrs *script_addrs;
 };
 
 #endif /* __MACH_MXC_SDMA_H__ */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/include/mach/uncompress.h linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/include/mach/uncompress.h
--- linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/include/mach/uncompress.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/include/mach/uncompress.h	2011-03-14 21:20:32.000000000 -0400
@@ -63,6 +63,8 @@ static inline void flush(void)
 #define MX3X_UART1_BASE_ADDR	0x43F90000
 #define MX3X_UART2_BASE_ADDR	0x43F94000
 #define MX51_UART1_BASE_ADDR	0x73fbc000
+#define MX50_UART1_BASE_ADDR	0x53fbc000
+#define MX53_UART1_BASE_ADDR	0x53fbc000
 
 static __inline__ void __arch_decomp_setup(unsigned long arch_id)
 {
@@ -93,6 +95,7 @@ static __inline__ void __arch_decomp_set
 	case MACH_TYPE_MX35_3DS:
 	case MACH_TYPE_PCM043:
 	case MACH_TYPE_LILLY1131:
+	case MACH_TYPE_VPR200:
 		uart_base = MX3X_UART1_BASE_ADDR;
 		break;
 	case MACH_TYPE_MAGX_ZN5:
@@ -100,8 +103,15 @@ static __inline__ void __arch_decomp_set
 		break;
 	case MACH_TYPE_MX51_BABBAGE:
 	case MACH_TYPE_EUKREA_CPUIMX51SD:
+	case MACH_TYPE_MX51_3DS:
 		uart_base = MX51_UART1_BASE_ADDR;
 		break;
+	case MACH_TYPE_MX50_RDP:
+		uart_base = MX50_UART1_BASE_ADDR;
+		break;
+	case MACH_TYPE_MX53_EVK:
+		uart_base = MX53_UART1_BASE_ADDR;
+		break;
 	default:
 		break;
 	}
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/iomux-v3.c linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/iomux-v3.c
--- linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/iomux-v3.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/iomux-v3.c	2011-03-14 21:20:32.000000000 -0400
@@ -32,31 +32,38 @@
 static void __iomem *base;
 
 /*
- * setups a single pad in the iomuxer
+ * configures a single pad in the iomuxer
  */
-int mxc_iomux_v3_setup_pad(struct pad_desc *pad)
+int mxc_iomux_v3_setup_pad(iomux_v3_cfg_t pad)
 {
-	if (pad->mux_ctrl_ofs)
-		__raw_writel(pad->mux_mode, base + pad->mux_ctrl_ofs);
+	u32 mux_ctrl_ofs = (pad & MUX_CTRL_OFS_MASK) >> MUX_CTRL_OFS_SHIFT;
+	u32 mux_mode = (pad & MUX_MODE_MASK) >> MUX_MODE_SHIFT;
+	u32 sel_input_ofs = (pad & MUX_SEL_INPUT_OFS_MASK) >> MUX_SEL_INPUT_OFS_SHIFT;
+	u32 sel_input = (pad & MUX_SEL_INPUT_MASK) >> MUX_SEL_INPUT_SHIFT;
+	u32 pad_ctrl_ofs = (pad & MUX_PAD_CTRL_OFS_MASK) >> MUX_PAD_CTRL_OFS_SHIFT;
+	u32 pad_ctrl = (pad & MUX_PAD_CTRL_MASK) >> MUX_PAD_CTRL_SHIFT;
 
-	if (pad->select_input_ofs)
-		__raw_writel(pad->select_input,
-				base + pad->select_input_ofs);
+	if (mux_ctrl_ofs)
+		__raw_writel(mux_mode, base + mux_ctrl_ofs);
+
+	if (sel_input_ofs)
+		__raw_writel(sel_input, base + sel_input_ofs);
+
+	if (!(pad_ctrl & NO_PAD_CTRL) && pad_ctrl_ofs)
+		__raw_writel(pad_ctrl, base + pad_ctrl_ofs);
 
-	if (!(pad->pad_ctrl & NO_PAD_CTRL) && pad->pad_ctrl_ofs)
-		__raw_writel(pad->pad_ctrl, base + pad->pad_ctrl_ofs);
 	return 0;
 }
 EXPORT_SYMBOL(mxc_iomux_v3_setup_pad);
 
-int mxc_iomux_v3_setup_multiple_pads(struct pad_desc *pad_list, unsigned count)
+int mxc_iomux_v3_setup_multiple_pads(iomux_v3_cfg_t *pad_list, unsigned count)
 {
-	struct pad_desc *p = pad_list;
+	iomux_v3_cfg_t *p = pad_list;
 	int i;
 	int ret;
 
 	for (i = 0; i < count; i++) {
-		ret = mxc_iomux_v3_setup_pad(p);
+		ret = mxc_iomux_v3_setup_pad(*p);
 		if (ret)
 			return ret;
 		p++;
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/irq.c linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/irq.c
--- linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/irq.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/irq.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,152 +0,0 @@
-/*
- * Copyright 2004-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.
- */
-
-#include <linux/module.h>
-#include <linux/irq.h>
-#include <linux/io.h>
-#include <mach/common.h>
-#include <asm/mach/irq.h>
-#include <mach/hardware.h>
-
-#define AVIC_INTCNTL		0x00	/* int control reg */
-#define AVIC_NIMASK		0x04	/* int mask reg */
-#define AVIC_INTENNUM		0x08	/* int enable number reg */
-#define AVIC_INTDISNUM		0x0C	/* int disable number reg */
-#define AVIC_INTENABLEH		0x10	/* int enable reg high */
-#define AVIC_INTENABLEL		0x14	/* int enable reg low */
-#define AVIC_INTTYPEH		0x18	/* int type reg high */
-#define AVIC_INTTYPEL		0x1C	/* int type reg low */
-#define AVIC_NIPRIORITY(x)	(0x20 + 4 * (7 - (x))) /* int priority */
-#define AVIC_NIVECSR		0x40	/* norm int vector/status */
-#define AVIC_FIVECSR		0x44	/* fast int vector/status */
-#define AVIC_INTSRCH		0x48	/* int source reg high */
-#define AVIC_INTSRCL		0x4C	/* int source reg low */
-#define AVIC_INTFRCH		0x50	/* int force reg high */
-#define AVIC_INTFRCL		0x54	/* int force reg low */
-#define AVIC_NIPNDH		0x58	/* norm int pending high */
-#define AVIC_NIPNDL		0x5C	/* norm int pending low */
-#define AVIC_FIPNDH		0x60	/* fast int pending high */
-#define AVIC_FIPNDL		0x64	/* fast int pending low */
-
-void __iomem *avic_base;
-
-int imx_irq_set_priority(unsigned char irq, unsigned char prio)
-{
-#ifdef CONFIG_MXC_IRQ_PRIOR
-	unsigned int temp;
-	unsigned int mask = 0x0F << irq % 8 * 4;
-
-	if (irq >= MXC_INTERNAL_IRQS)
-		return -EINVAL;;
-
-	temp = __raw_readl(avic_base + AVIC_NIPRIORITY(irq / 8));
-	temp &= ~mask;
-	temp |= prio & mask;
-
-	__raw_writel(temp, avic_base + AVIC_NIPRIORITY(irq / 8));
-
-	return 0;
-#else
-	return -ENOSYS;
-#endif
-}
-EXPORT_SYMBOL(imx_irq_set_priority);
-
-#ifdef CONFIG_FIQ
-int mxc_set_irq_fiq(unsigned int irq, unsigned int type)
-{
-	unsigned int irqt;
-
-	if (irq >= MXC_INTERNAL_IRQS)
-		return -EINVAL;
-
-	if (irq < MXC_INTERNAL_IRQS / 2) {
-		irqt = __raw_readl(avic_base + AVIC_INTTYPEL) & ~(1 << irq);
-		__raw_writel(irqt | (!!type << irq), avic_base + AVIC_INTTYPEL);
-	} else {
-		irq -= MXC_INTERNAL_IRQS / 2;
-		irqt = __raw_readl(avic_base + AVIC_INTTYPEH) & ~(1 << irq);
-		__raw_writel(irqt | (!!type << irq), avic_base + AVIC_INTTYPEH);
-	}
-
-	return 0;
-}
-EXPORT_SYMBOL(mxc_set_irq_fiq);
-#endif /* CONFIG_FIQ */
-
-/* Disable interrupt number "irq" in the AVIC */
-static void mxc_mask_irq(unsigned int irq)
-{
-	__raw_writel(irq, avic_base + AVIC_INTDISNUM);
-}
-
-/* Enable interrupt number "irq" in the AVIC */
-static void mxc_unmask_irq(unsigned int irq)
-{
-	__raw_writel(irq, avic_base + AVIC_INTENNUM);
-}
-
-static struct irq_chip mxc_avic_chip = {
-	.ack = mxc_mask_irq,
-	.mask = mxc_mask_irq,
-	.unmask = mxc_unmask_irq,
-};
-
-/*
- * This function initializes the AVIC hardware and disables all the
- * interrupts. It registers the interrupt enable and disable functions
- * to the kernel for each interrupt source.
- */
-void __init mxc_init_irq(void __iomem *irqbase)
-{
-	int i;
-
-	avic_base = irqbase;
-
-	/* put the AVIC into the reset value with
-	 * all interrupts disabled
-	 */
-	__raw_writel(0, avic_base + AVIC_INTCNTL);
-	__raw_writel(0x1f, avic_base + AVIC_NIMASK);
-
-	/* disable all interrupts */
-	__raw_writel(0, avic_base + AVIC_INTENABLEH);
-	__raw_writel(0, avic_base + AVIC_INTENABLEL);
-
-	/* all IRQ no FIQ */
-	__raw_writel(0, avic_base + AVIC_INTTYPEH);
-	__raw_writel(0, avic_base + AVIC_INTTYPEL);
-	for (i = 0; i < MXC_INTERNAL_IRQS; i++) {
-		set_irq_chip(i, &mxc_avic_chip);
-		set_irq_handler(i, handle_level_irq);
-		set_irq_flags(i, IRQF_VALID);
-	}
-
-	/* Set default priority value (0) for all IRQ's */
-	for (i = 0; i < 8; i++)
-		__raw_writel(0, avic_base + AVIC_NIPRIORITY(i));
-
-#ifdef CONFIG_FIQ
-	/* Initialize FIQ */
-	init_FIQ();
-#endif
-
-	printk(KERN_INFO "MXC IRQ initialized\n");
-}
-
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/irq-common.c linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/irq-common.c
--- linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/irq-common.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/irq-common.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) BitBox Ltd 2010
+ *
+ * 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 <linux/irq.h>
+
+#include "irq-common.h"
+
+int imx_irq_set_priority(unsigned char irq, unsigned char prio)
+{
+	struct mxc_irq_chip *chip;
+	struct irq_chip *base;
+	int ret;
+
+	ret = -ENOSYS;
+
+	base = get_irq_chip(irq);
+	if (base) {
+		chip = container_of(base, struct mxc_irq_chip, base);
+		if (chip->set_priority)
+			ret = chip->set_priority(irq, prio);
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL(imx_irq_set_priority);
+
+int mxc_set_irq_fiq(unsigned int irq, unsigned int type)
+{
+	struct mxc_irq_chip *chip;
+	struct irq_chip *base;
+	int ret;
+
+	ret = -ENOSYS;
+
+	base = get_irq_chip(irq);
+	if (base) {
+		chip = container_of(base, struct mxc_irq_chip, base);
+		if (chip->set_irq_fiq)
+			ret = chip->set_irq_fiq(irq, type);
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL(mxc_set_irq_fiq);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/irq-common.h linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/irq-common.h
--- linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/irq-common.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/irq-common.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) BitBox Ltd 2010
+ *
+ * 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 __PLAT_MXC_IRQ_COMMON_H__
+#define __PLAT_MXC_IRQ_COMMON_H__
+
+struct mxc_irq_chip
+{
+	struct irq_chip	base;
+	int (*set_priority)(unsigned char irq, unsigned char prio);
+	int (*set_irq_fiq)(unsigned int irq, unsigned int type);
+};
+
+#endif
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/Kconfig linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/Kconfig
--- linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -21,10 +21,6 @@ config ARCH_MX2
 
 config ARCH_MX25
 	bool "MX25-based"
-	select CPU_ARM926T
-	select ARCH_MXC_IOMUX_V3
-	select HAVE_FB_IMX
-	select ARCH_MXC_AUDMUX_V2
 	help
 	  This enables support for systems based on the Freescale i.MX25 family
 
@@ -51,7 +47,6 @@ endchoice
 
 source "arch/arm/mach-imx/Kconfig"
 source "arch/arm/mach-mx3/Kconfig"
-source "arch/arm/mach-mx25/Kconfig"
 source "arch/arm/mach-mxc91231/Kconfig"
 source "arch/arm/mach-mx5/Kconfig"
 
@@ -68,12 +63,10 @@ config MXC_IRQ_PRIOR
 	  Say N here, unless you have a specialized requirement.
 
 config MXC_TZIC
-	bool "Enable TrustZone Interrupt Controller"
-	depends on ARCH_MX51
-	help
-	  This will be automatically selected for all processors
-	  containing this interrupt controller.
-	  Say N here only if you are really sure.
+	bool
+
+config MXC_AVIC
+	bool
 
 config MXC_PWM
 	tristate "Enable PWM driver"
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/Makefile linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/Makefile
--- linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -3,10 +3,11 @@
 #
 
 # Common support
-obj-y := irq.o clock.o gpio.o time.o devices.o cpu.o system.o
+obj-y := clock.o gpio.o time.o devices.o cpu.o system.o irq-common.o
 
-# MX51 uses the TZIC interrupt controller, older platforms use AVIC (irq.o)
+# MX51 uses the TZIC interrupt controller, older platforms use AVIC
 obj-$(CONFIG_MXC_TZIC) += tzic.o
+obj-$(CONFIG_MXC_AVIC) += avic.o
 
 obj-$(CONFIG_IMX_HAVE_IOMUX_V1) += iomux-v1.o
 obj-$(CONFIG_ARCH_MXC_IOMUX_V3) += iomux-v3.o
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/pwm.c linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/pwm.c
--- linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/pwm.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/pwm.c	2011-03-14 21:20:32.000000000 -0400
@@ -57,7 +57,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()) {
+	if (cpu_is_mx27() || cpu_is_mx3() || cpu_is_mx25() || cpu_is_mx51()) {
 		unsigned long long c;
 		unsigned long period_cycles, duty_cycles, prescale;
 		u32 cr;
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/system.c linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/system.c
--- linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/system.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/system.c	2011-03-14 21:20:32.000000000 -0400
@@ -26,6 +26,7 @@
 #include <mach/common.h>
 #include <asm/proc-fns.h>
 #include <asm/system.h>
+#include <asm/mach-types.h>
 
 static void __iomem *wdog_base;
 
@@ -42,12 +43,19 @@ void arch_reset(char mode, const char *c
 		return;
 	}
 #endif
+#ifdef CONFIG_MACH_MX51_EFIKAMX
+	if (machine_is_mx51_efikamx()) {
+		mx51_efikamx_reset();
+		return;
+	}
+#endif
+
 	if (cpu_is_mx1()) {
 		wcr_enable = (1 << 0);
 	} else {
 		struct clk *clk;
 
-		clk = clk_get_sys("imx-wdt.0", NULL);
+		clk = clk_get_sys("imx2-wdt.0", NULL);
 		if (!IS_ERR(clk))
 			clk_enable(clk);
 		wcr_enable = (1 << 2);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/time.c linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/time.c
--- linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/time.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/time.c	2011-03-14 21:20:32.000000000 -0400
@@ -120,7 +120,6 @@ static struct clocksource clocksource_mx
 	.rating		= 200,
 	.read		= mx1_2_get_cycles,
 	.mask		= CLOCKSOURCE_MASK(32),
-	.shift 		= 20,
 	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
@@ -131,9 +130,7 @@ static int __init mxc_clocksource_init(s
 	if (timer_is_v2())
 		clocksource_mxc.read = v2_get_cycles;
 
-	clocksource_mxc.mult = clocksource_hz2mult(c,
-					clocksource_mxc.shift);
-	clocksource_register(&clocksource_mxc);
+	clocksource_register_hz(&clocksource_mxc, c);
 
 	return 0;
 }
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/tzic.c linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/tzic.c
--- linux-libre-2.6.37-gnu1/arch/arm/plat-mxc/tzic.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-mxc/tzic.c	2011-03-14 21:20:32.000000000 -0400
@@ -21,6 +21,8 @@
 #include <mach/hardware.h>
 #include <mach/common.h>
 
+#include "irq-common.h"
+
 /*
  *****************************************
  * TZIC Registers                        *
@@ -47,51 +49,70 @@
 
 void __iomem *tzic_base; /* Used as irq controller base in entry-macro.S */
 
+#ifdef CONFIG_FIQ
+static int tzic_set_irq_fiq(unsigned int irq, unsigned int type)
+{
+	unsigned int index, mask, value;
+
+	index = irq >> 5;
+	if (unlikely(index >= 4))
+		return -EINVAL;
+	mask = 1U << (irq & 0x1F);
+
+	value = __raw_readl(tzic_base + TZIC_INTSEC0(index)) | mask;
+	if (type)
+		value &= ~mask;
+	__raw_writel(value, tzic_base + TZIC_INTSEC0(index));
+
+	return 0;
+}
+#endif
+
 /**
- * tzic_mask_irq() - Disable interrupt number "irq" in the TZIC
+ * tzic_mask_irq() - Disable interrupt source "d" in the TZIC
  *
- * @param  irq          interrupt source number
+ * @param  d            interrupt source
  */
-static void tzic_mask_irq(unsigned int irq)
+static void tzic_mask_irq(struct irq_data *d)
 {
 	int index, off;
 
-	index = irq >> 5;
-	off = irq & 0x1F;
+	index = d->irq >> 5;
+	off = d->irq & 0x1F;
 	__raw_writel(1 << off, tzic_base + TZIC_ENCLEAR0(index));
 }
 
 /**
- * tzic_unmask_irq() - Enable interrupt number "irq" in the TZIC
+ * tzic_unmask_irq() - Enable interrupt source "d" in the TZIC
  *
- * @param  irq          interrupt source number
+ * @param  d            interrupt source
  */
-static void tzic_unmask_irq(unsigned int irq)
+static void tzic_unmask_irq(struct irq_data *d)
 {
 	int index, off;
 
-	index = irq >> 5;
-	off = irq & 0x1F;
+	index = d->irq >> 5;
+	off = d->irq & 0x1F;
 	__raw_writel(1 << off, tzic_base + TZIC_ENSET0(index));
 }
 
 static unsigned int wakeup_intr[4];
 
 /**
- * tzic_set_wake_irq() - Set interrupt number "irq" in the TZIC as a wake-up source.
+ * tzic_set_wake_irq() - Set interrupt source "d" in the TZIC as a wake-up source.
  *
- * @param  irq          interrupt source number
+ * @param  d            interrupt source
  * @param  enable       enable as wake-up if equal to non-zero
  * 			disble as wake-up if equal to zero
  *
  * @return       This function returns 0 on success.
  */
-static int tzic_set_wake_irq(unsigned int irq, unsigned int enable)
+static int tzic_set_wake_irq(struct irq_data *d, unsigned int enable)
 {
 	unsigned int index, off;
 
-	index = irq >> 5;
-	off = irq & 0x1F;
+	index = d->irq >> 5;
+	off = d->irq & 0x1F;
 
 	if (index > 3)
 		return -EINVAL;
@@ -104,12 +125,17 @@ static int tzic_set_wake_irq(unsigned in
 	return 0;
 }
 
-static struct irq_chip mxc_tzic_chip = {
-	.name = "MXC_TZIC",
-	.ack = tzic_mask_irq,
-	.mask = tzic_mask_irq,
-	.unmask = tzic_unmask_irq,
-	.set_wake = tzic_set_wake_irq,
+static struct mxc_irq_chip mxc_tzic_chip = {
+	.base = {
+		.name = "MXC_TZIC",
+		.irq_ack = tzic_mask_irq,
+		.irq_mask = tzic_mask_irq,
+		.irq_unmask = tzic_unmask_irq,
+		.irq_set_wake = tzic_set_wake_irq,
+	},
+#ifdef CONFIG_FIQ
+	.set_irq_fiq = tzic_set_irq_fiq,
+#endif
 };
 
 /*
@@ -141,10 +167,16 @@ void __init tzic_init_irq(void __iomem *
 	/* all IRQ no FIQ Warning :: No selection */
 
 	for (i = 0; i < MXC_INTERNAL_IRQS; i++) {
-		set_irq_chip(i, &mxc_tzic_chip);
+		set_irq_chip(i, &mxc_tzic_chip.base);
 		set_irq_handler(i, handle_level_irq);
 		set_irq_flags(i, IRQF_VALID);
 	}
+
+#ifdef CONFIG_FIQ
+	/* Initialize FIQ */
+	init_FIQ();
+#endif
+
 	pr_info("TrustZone Interrupt Controller (TZIC) initialized\n");
 }
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-nomadik/gpio.c linux-libre-2.6.38-gnu1/arch/arm/plat-nomadik/gpio.c
--- linux-libre-2.6.37-gnu1/arch/arm/plat-nomadik/gpio.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-nomadik/gpio.c	2011-03-14 21:20:32.000000000 -0400
@@ -119,7 +119,7 @@ static void __nmk_gpio_make_output(struc
 }
 
 static void __nmk_config_pin(struct nmk_gpio_chip *nmk_chip, unsigned offset,
-			     pin_cfg_t cfg)
+			     pin_cfg_t cfg, bool sleep)
 {
 	static const char *afnames[] = {
 		[NMK_GPIO_ALT_GPIO]	= "GPIO",
@@ -145,11 +145,34 @@ static void __nmk_config_pin(struct nmk_
 	int output = PIN_DIR(cfg);
 	int val = PIN_VAL(cfg);
 
-	dev_dbg(nmk_chip->chip.dev, "pin %d: af %s, pull %s, slpm %s (%s%s)\n",
-		pin, afnames[af], pullnames[pull], slpmnames[slpm],
+	dev_dbg(nmk_chip->chip.dev, "pin %d [%#lx]: af %s, pull %s, slpm %s (%s%s)\n",
+		pin, cfg, afnames[af], pullnames[pull], slpmnames[slpm],
 		output ? "output " : "input",
 		output ? (val ? "high" : "low") : "");
 
+	if (sleep) {
+		int slpm_pull = PIN_SLPM_PULL(cfg);
+		int slpm_output = PIN_SLPM_DIR(cfg);
+		int slpm_val = PIN_SLPM_VAL(cfg);
+
+		/*
+		 * The SLPM_* values are normal values + 1 to allow zero to
+		 * mean "same as normal".
+		 */
+		if (slpm_pull)
+			pull = slpm_pull - 1;
+		if (slpm_output)
+			output = slpm_output - 1;
+		if (slpm_val)
+			val = slpm_val - 1;
+
+		dev_dbg(nmk_chip->chip.dev, "pin %d: sleep pull %s, dir %s, val %s\n",
+			pin,
+			slpm_pull ? pullnames[pull] : "same",
+			slpm_output ? (output ? "output" : "input") : "same",
+			slpm_val ? (val ? "high" : "low") : "same");
+	}
+
 	if (output)
 		__nmk_gpio_make_output(nmk_chip, offset, val);
 	else {
@@ -175,7 +198,7 @@ static void __nmk_config_pin(struct nmk_
  * side-effects.  The gpio can be manipulated later using standard GPIO API
  * calls.
  */
-int nmk_config_pin(pin_cfg_t cfg)
+int nmk_config_pin(pin_cfg_t cfg, bool sleep)
 {
 	struct nmk_gpio_chip *nmk_chip;
 	int gpio = PIN_NUM(cfg);
@@ -186,7 +209,7 @@ int nmk_config_pin(pin_cfg_t cfg)
 		return -EINVAL;
 
 	spin_lock_irqsave(&nmk_chip->lock, flags);
-	__nmk_config_pin(nmk_chip, gpio - nmk_chip->chip.base, cfg);
+	__nmk_config_pin(nmk_chip, gpio - nmk_chip->chip.base, cfg, sleep);
 	spin_unlock_irqrestore(&nmk_chip->lock, flags);
 
 	return 0;
@@ -207,7 +230,7 @@ int nmk_config_pins(pin_cfg_t *cfgs, int
 	int i;
 
 	for (i = 0; i < num; i++) {
-		int ret = nmk_config_pin(cfgs[i]);
+		ret = nmk_config_pin(cfgs[i], false);
 		if (ret)
 			break;
 	}
@@ -216,6 +239,21 @@ int nmk_config_pins(pin_cfg_t *cfgs, int
 }
 EXPORT_SYMBOL(nmk_config_pins);
 
+int nmk_config_pins_sleep(pin_cfg_t *cfgs, int num)
+{
+	int ret = 0;
+	int i;
+
+	for (i = 0; i < num; i++) {
+		ret = nmk_config_pin(cfgs[i], true);
+		if (ret)
+			break;
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL(nmk_config_pins_sleep);
+
 /**
  * nmk_gpio_set_slpm() - configure the sleep mode of a pin
  * @gpio: pin number
@@ -318,13 +356,13 @@ static inline int nmk_gpio_get_bitmask(i
 	return 1 << (gpio % 32);
 }
 
-static void nmk_gpio_irq_ack(unsigned int irq)
+static void nmk_gpio_irq_ack(struct irq_data *d)
 {
 	int gpio;
 	struct nmk_gpio_chip *nmk_chip;
 
-	gpio = NOMADIK_IRQ_TO_GPIO(irq);
-	nmk_chip = get_irq_chip_data(irq);
+	gpio = NOMADIK_IRQ_TO_GPIO(d->irq);
+	nmk_chip = irq_data_get_irq_chip_data(d);
 	if (!nmk_chip)
 		return;
 	writel(nmk_gpio_get_bitmask(gpio), nmk_chip->addr + NMK_GPIO_IC);
@@ -363,7 +401,7 @@ static void __nmk_gpio_irq_modify(struct
 	}
 }
 
-static int nmk_gpio_irq_modify(unsigned int irq, enum nmk_gpio_irq_type which,
+static int nmk_gpio_irq_modify(struct irq_data *d, enum nmk_gpio_irq_type which,
 			       bool enable)
 {
 	int gpio;
@@ -371,8 +409,8 @@ static int nmk_gpio_irq_modify(unsigned
 	unsigned long flags;
 	u32 bitmask;
 
-	gpio = NOMADIK_IRQ_TO_GPIO(irq);
-	nmk_chip = get_irq_chip_data(irq);
+	gpio = NOMADIK_IRQ_TO_GPIO(d->irq);
+	nmk_chip = irq_data_get_irq_chip_data(d);
 	bitmask = nmk_gpio_get_bitmask(gpio);
 	if (!nmk_chip)
 		return -EINVAL;
@@ -384,24 +422,24 @@ static int nmk_gpio_irq_modify(unsigned
 	return 0;
 }
 
-static void nmk_gpio_irq_mask(unsigned int irq)
+static void nmk_gpio_irq_mask(struct irq_data *d)
 {
-	nmk_gpio_irq_modify(irq, NORMAL, false);
+	nmk_gpio_irq_modify(d, NORMAL, false);
 }
 
-static void nmk_gpio_irq_unmask(unsigned int irq)
+static void nmk_gpio_irq_unmask(struct irq_data *d)
 {
-	nmk_gpio_irq_modify(irq, NORMAL, true);
+	nmk_gpio_irq_modify(d, NORMAL, true);
 }
 
-static int nmk_gpio_irq_set_wake(unsigned int irq, unsigned int on)
+static int nmk_gpio_irq_set_wake(struct irq_data *d, unsigned int on)
 {
 	struct nmk_gpio_chip *nmk_chip;
 	unsigned long flags;
 	int gpio;
 
-	gpio = NOMADIK_IRQ_TO_GPIO(irq);
-	nmk_chip = get_irq_chip_data(irq);
+	gpio = NOMADIK_IRQ_TO_GPIO(d->irq);
+	nmk_chip = irq_data_get_irq_chip_data(d);
 	if (!nmk_chip)
 		return -EINVAL;
 
@@ -419,9 +457,9 @@ static int nmk_gpio_irq_set_wake(unsigne
 	return 0;
 }
 
-static int nmk_gpio_irq_set_type(unsigned int irq, unsigned int type)
+static int nmk_gpio_irq_set_type(struct irq_data *d, unsigned int type)
 {
-	struct irq_desc *desc = irq_to_desc(irq);
+	struct irq_desc *desc = irq_to_desc(d->irq);
 	bool enabled = !(desc->status & IRQ_DISABLED);
 	bool wake = desc->wake_depth;
 	int gpio;
@@ -429,8 +467,8 @@ static int nmk_gpio_irq_set_type(unsigne
 	unsigned long flags;
 	u32 bitmask;
 
-	gpio = NOMADIK_IRQ_TO_GPIO(irq);
-	nmk_chip = get_irq_chip_data(irq);
+	gpio = NOMADIK_IRQ_TO_GPIO(d->irq);
+	nmk_chip = irq_data_get_irq_chip_data(d);
 	bitmask = nmk_gpio_get_bitmask(gpio);
 	if (!nmk_chip)
 		return -EINVAL;
@@ -469,11 +507,11 @@ static int nmk_gpio_irq_set_type(unsigne
 
 static struct irq_chip nmk_gpio_irq_chip = {
 	.name		= "Nomadik-GPIO",
-	.ack		= nmk_gpio_irq_ack,
-	.mask		= nmk_gpio_irq_mask,
-	.unmask		= nmk_gpio_irq_unmask,
-	.set_type	= nmk_gpio_irq_set_type,
-	.set_wake	= nmk_gpio_irq_set_wake,
+	.irq_ack	= nmk_gpio_irq_ack,
+	.irq_mask	= nmk_gpio_irq_mask,
+	.irq_unmask	= nmk_gpio_irq_unmask,
+	.irq_set_type	= nmk_gpio_irq_set_type,
+	.irq_set_wake	= nmk_gpio_irq_set_wake,
 };
 
 static void nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
@@ -484,12 +522,12 @@ static void nmk_gpio_irq_handler(unsigne
 	u32 pending;
 	unsigned int first_irq;
 
-	if (host_chip->mask_ack)
-		host_chip->mask_ack(irq);
+	if (host_chip->irq_mask_ack)
+		host_chip->irq_mask_ack(&desc->irq_data);
 	else {
-		host_chip->mask(irq);
-		if (host_chip->ack)
-			host_chip->ack(irq);
+		host_chip->irq_mask(&desc->irq_data);
+		if (host_chip->irq_ack)
+			host_chip->irq_ack(&desc->irq_data);
 	}
 
 	nmk_chip = get_irq_data(irq);
@@ -499,7 +537,7 @@ static void nmk_gpio_irq_handler(unsigne
 		generic_handle_irq(gpio_irq);
 	}
 
-	host_chip->unmask(irq);
+	host_chip->irq_unmask(&desc->irq_data);
 }
 
 static int nmk_gpio_init_irq(struct nmk_gpio_chip *nmk_chip)
@@ -634,7 +672,7 @@ static int __devinit nmk_gpio_probe(stru
 
 	chip = &nmk_chip->chip;
 	chip->base = pdata->first_gpio;
-	chip->label = pdata->name;
+	chip->label = pdata->name ?: dev_name(&dev->dev);
 	chip->dev = &dev->dev;
 	chip->owner = THIS_MODULE;
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-nomadik/include/plat/pincfg.h linux-libre-2.6.38-gnu1/arch/arm/plat-nomadik/include/plat/pincfg.h
--- linux-libre-2.6.37-gnu1/arch/arm/plat-nomadik/include/plat/pincfg.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-nomadik/include/plat/pincfg.h	2011-03-14 21:20:32.000000000 -0400
@@ -19,16 +19,22 @@
  *	bit  9..10 - Alternate Function Selection
  *	bit 11..12 - Pull up/down state
  *	bit     13 - Sleep mode behaviour
- *	bit     14 - (sleep mode) Direction
- *	bit     15 - (sleep mode) Value (if output)
+ *	bit     14 - Direction
+ *	bit     15 - Value (if output)
+ *	bit 16..18 - SLPM pull up/down state
+ *	bit 19..20 - SLPM direction
+ *	bit 21..22 - SLPM Value (if output)
  *
  * to facilitate the definition, the following macros are provided
  *
  * PIN_CFG_DEFAULT - default config (0):
  *		     pull up/down = disabled
  *		     sleep mode = input/wakeup
- *		     (sleep mode) direction = input
- *		     (sleep mode) value = low
+ *		     direction = input
+ *		     value = low
+ *		     SLPM direction = same as normal
+ *		     SLPM pull = same as normal
+ *		     SLPM value = same as normal
  *
  * PIN_CFG	   - default config with alternate function
  * PIN_CFG_PULL	   - default config with alternate function and pull up/down
@@ -75,30 +81,64 @@ typedef unsigned long pin_cfg_t;
 #define PIN_VAL_LOW		(0 << PIN_VAL_SHIFT)
 #define PIN_VAL_HIGH		(1 << PIN_VAL_SHIFT)
 
-/* Shortcuts.  Use these instead of separate DIR and VAL.  */
-#define PIN_INPUT		PIN_DIR_INPUT
+#define PIN_SLPM_PULL_SHIFT	16
+#define PIN_SLPM_PULL_MASK	(0x7 << PIN_SLPM_PULL_SHIFT)
+#define PIN_SLPM_PULL(x)	\
+	(((x) & PIN_SLPM_PULL_MASK) >> PIN_SLPM_PULL_SHIFT)
+#define PIN_SLPM_PULL_NONE	\
+	((1 + NMK_GPIO_PULL_NONE) << PIN_SLPM_PULL_SHIFT)
+#define PIN_SLPM_PULL_UP	\
+	((1 + NMK_GPIO_PULL_UP) << PIN_SLPM_PULL_SHIFT)
+#define PIN_SLPM_PULL_DOWN	\
+	((1 + NMK_GPIO_PULL_DOWN) << PIN_SLPM_PULL_SHIFT)
+
+#define PIN_SLPM_DIR_SHIFT	19
+#define PIN_SLPM_DIR_MASK	(0x3 << PIN_SLPM_DIR_SHIFT)
+#define PIN_SLPM_DIR(x)		\
+	(((x) & PIN_SLPM_DIR_MASK) >> PIN_SLPM_DIR_SHIFT)
+#define PIN_SLPM_DIR_INPUT	((1 + 0) << PIN_SLPM_DIR_SHIFT)
+#define PIN_SLPM_DIR_OUTPUT	((1 + 1) << PIN_SLPM_DIR_SHIFT)
+
+#define PIN_SLPM_VAL_SHIFT	21
+#define PIN_SLPM_VAL_MASK	(0x3 << PIN_SLPM_VAL_SHIFT)
+#define PIN_SLPM_VAL(x)		\
+	(((x) & PIN_SLPM_VAL_MASK) >> PIN_SLPM_VAL_SHIFT)
+#define PIN_SLPM_VAL_LOW	((1 + 0) << PIN_SLPM_VAL_SHIFT)
+#define PIN_SLPM_VAL_HIGH	((1 + 1) << PIN_SLPM_VAL_SHIFT)
+
+/* Shortcuts.  Use these instead of separate DIR, PULL, and VAL.  */
+#define PIN_INPUT_PULLDOWN	(PIN_DIR_INPUT | PIN_PULL_DOWN)
+#define PIN_INPUT_PULLUP	(PIN_DIR_INPUT | PIN_PULL_UP)
+#define PIN_INPUT_NOPULL	(PIN_DIR_INPUT | PIN_PULL_NONE)
 #define PIN_OUTPUT_LOW		(PIN_DIR_OUTPUT | PIN_VAL_LOW)
 #define PIN_OUTPUT_HIGH		(PIN_DIR_OUTPUT | PIN_VAL_HIGH)
 
-/*
- * These are the same as the ones above, but should make more sense to the
- * reader when seen along with a setting a pin to AF mode.
- */
-#define PIN_SLPM_INPUT		PIN_INPUT
-#define PIN_SLPM_OUTPUT_LOW	PIN_OUTPUT_LOW
-#define PIN_SLPM_OUTPUT_HIGH	PIN_OUTPUT_HIGH
+#define PIN_SLPM_INPUT_PULLDOWN	(PIN_SLPM_DIR_INPUT | PIN_SLPM_PULL_DOWN)
+#define PIN_SLPM_INPUT_PULLUP	(PIN_SLPM_DIR_INPUT | PIN_SLPM_PULL_UP)
+#define PIN_SLPM_INPUT_NOPULL	(PIN_SLPM_DIR_INPUT | PIN_SLPM_PULL_NONE)
+#define PIN_SLPM_OUTPUT_LOW	(PIN_SLPM_DIR_OUTPUT | PIN_SLPM_VAL_LOW)
+#define PIN_SLPM_OUTPUT_HIGH	(PIN_SLPM_DIR_OUTPUT | PIN_SLPM_VAL_HIGH)
 
-#define PIN_CFG_DEFAULT		(PIN_PULL_NONE | PIN_SLPM_INPUT)
+#define PIN_CFG_DEFAULT		(0)
 
 #define PIN_CFG(num, alt)		\
 	(PIN_CFG_DEFAULT |\
 	 (PIN_NUM(num) | PIN_##alt))
 
+#define PIN_CFG_INPUT(num, alt, pull)		\
+	(PIN_CFG_DEFAULT |\
+	 (PIN_NUM(num) | PIN_##alt | PIN_INPUT_##pull))
+
+#define PIN_CFG_OUTPUT(num, alt, val)		\
+	(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);
+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);
 
 #endif
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-nomadik/include/plat/ste_dma40.h linux-libre-2.6.38-gnu1/arch/arm/plat-nomadik/include/plat/ste_dma40.h
--- linux-libre-2.6.37-gnu1/arch/arm/plat-nomadik/include/plat/ste_dma40.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-nomadik/include/plat/ste_dma40.h	2011-03-14 21:20:32.000000000 -0400
@@ -13,6 +13,14 @@
 #include <linux/workqueue.h>
 #include <linux/interrupt.h>
 
+/*
+ * Maxium size for a single dma descriptor
+ * Size is limited to 16 bits.
+ * Size is in the units of addr-widths (1,2,4,8 bytes)
+ * Larger transfers will be split up to multiple linked desc
+ */
+#define STEDMA40_MAX_SEG_SIZE 0xFFFF
+
 /* dev types for memcpy */
 #define STEDMA40_DEV_DST_MEMORY (-1)
 #define	STEDMA40_DEV_SRC_MEMORY (-1)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-nomadik/Kconfig linux-libre-2.6.38-gnu1/arch/arm/plat-nomadik/Kconfig
--- linux-libre-2.6.37-gnu1/arch/arm/plat-nomadik/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-nomadik/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -14,6 +14,7 @@ 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
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-nomadik/timer.c linux-libre-2.6.38-gnu1/arch/arm/plat-nomadik/timer.c
--- linux-libre-2.6.37-gnu1/arch/arm/plat-nomadik/timer.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-nomadik/timer.c	2011-03-14 21:20:32.000000000 -0400
@@ -17,9 +17,9 @@
 #include <linux/clk.h>
 #include <linux/jiffies.h>
 #include <linux/err.h>
-#include <linux/cnt32_to_63.h>
-#include <linux/timer.h>
+#include <linux/sched.h>
 #include <asm/mach/time.h>
+#include <asm/sched_clock.h>
 
 #include <plat/mtu.h>
 
@@ -52,81 +52,24 @@ static struct clocksource nmdk_clksrc =
  * Override the global weak sched_clock symbol with this
  * local implementation which uses the clocksource to get some
  * better resolution when scheduling the kernel.
- *
- * Because the hardware timer period may be quite short
- * (32.3 secs on the 133 MHz MTU timer selection on ux500)
- * and because cnt32_to_63() needs to be called at least once per
- * half period to work properly, a kernel keepwarm() timer is set up
- * to ensure this requirement is always met.
- *
- * Also the sched_clock timer will wrap around at some point,
- * here we set it to run continously for a year.
  */
-#define SCHED_CLOCK_MIN_WRAP 3600*24*365
-static struct timer_list cnt32_to_63_keepwarm_timer;
-static u32 sched_mult;
-static u32 sched_shift;
+static DEFINE_CLOCK_DATA(cd);
 
 unsigned long long notrace sched_clock(void)
 {
-	u64 cycles;
+	u32 cyc;
 
 	if (unlikely(!mtu_base))
 		return 0;
 
-	cycles = cnt32_to_63(-readl(mtu_base + MTU_VAL(0)));
-	/*
-	 * sched_mult is guaranteed to be even so will
-	 * shift out bit 63
-	 */
-	return (cycles * sched_mult) >> sched_shift;
-}
-
-/* Just kick sched_clock every so often */
-static void cnt32_to_63_keepwarm(unsigned long data)
-{
-	mod_timer(&cnt32_to_63_keepwarm_timer, round_jiffies(jiffies + data));
-	(void) sched_clock();
+	cyc = -readl(mtu_base + MTU_VAL(0));
+	return cyc_to_sched_clock(&cd, cyc, (u32)~0);
 }
 
-/*
- * Set up a timer to keep sched_clock():s 32_to_63 algorithm warm
- * once in half a 32bit timer wrap interval.
- */
-static void __init nmdk_sched_clock_init(unsigned long rate)
+static void notrace nomadik_update_sched_clock(void)
 {
-	u32 v;
-	unsigned long delta;
-	u64 days;
-
-	/* Find the apropriate mult and shift factors */
-	clocks_calc_mult_shift(&sched_mult, &sched_shift,
-			       rate, NSEC_PER_SEC, SCHED_CLOCK_MIN_WRAP);
-	/* We need to multiply by an even number to get rid of bit 63 */
-	if (sched_mult & 1)
-		sched_mult++;
-
-	/* Let's see what we get, take max counter and scale it */
-	days = (0xFFFFFFFFFFFFFFFFLLU * sched_mult) >> sched_shift;
-	do_div(days, NSEC_PER_SEC);
-	do_div(days, (3600*24));
-
-	pr_info("sched_clock: using %d bits @ %lu Hz wrap in %lu days\n",
-		(64 - sched_shift), rate, (unsigned long) days);
-
-	/*
-	 * Program a timer to kick us at half 32bit wraparound
-	 * Formula: seconds per wrap = (2^32) / f
-	 */
-	v = 0xFFFFFFFFUL / rate;
-	/* We want half of the wrap time to keep cnt32_to_63 warm */
-	v /= 2;
-	pr_debug("sched_clock: prescaled timer rate: %lu Hz, "
-		 "initialize keepwarm timer every %d seconds\n", rate, v);
-	/* Convert seconds to jiffies */
-	delta = msecs_to_jiffies(v*1000);
-	setup_timer(&cnt32_to_63_keepwarm_timer, cnt32_to_63_keepwarm, delta);
-	mod_timer(&cnt32_to_63_keepwarm_timer, round_jiffies(jiffies + delta));
+	u32 cyc = -readl(mtu_base + MTU_VAL(0));
+	update_sched_clock(&cd, cyc, (u32)~0);
 }
 
 /* Clockevent device: use one-shot mode */
@@ -222,7 +165,6 @@ void __init nmdk_timer_init(void)
 	} else {
 		cr |= MTU_CRn_PRESCALE_1;
 	}
-	clocksource_calc_mult_shift(&nmdk_clksrc, rate, MTU_MIN_RANGE);
 
 	/* Timer 0 is the free running clocksource */
 	writel(cr, mtu_base + MTU_CR(0));
@@ -233,11 +175,11 @@ void __init nmdk_timer_init(void)
 	/* Now the clock source is ready */
 	nmdk_clksrc.read = nmdk_read_timer;
 
-	if (clocksource_register(&nmdk_clksrc))
+	if (clocksource_register_hz(&nmdk_clksrc, rate))
 		pr_err("timer: failed to initialize clock source %s\n",
 		       nmdk_clksrc.name);
 
-	nmdk_sched_clock_init(rate);
+	init_sched_clock(&cd, nomadik_update_sched_clock, 32, rate);
 
 	/* Timer 1 is used for events */
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-omap/counter_32k.c linux-libre-2.6.38-gnu1/arch/arm/plat-omap/counter_32k.c
--- linux-libre-2.6.37-gnu1/arch/arm/plat-omap/counter_32k.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-omap/counter_32k.c	2011-03-14 21:20:32.000000000 -0400
@@ -15,8 +15,11 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/clk.h>
-#include <linux/io.h>
 #include <linux/err.h>
+#include <linux/io.h>
+#include <linux/sched.h>
+
+#include <asm/sched_clock.h>
 
 #include <plat/common.h>
 #include <plat/board.h>
@@ -33,8 +36,6 @@
 
 #define OMAP16XX_TIMER_32K_SYNCHRONIZED		0xfffbc410
 
-#if !(defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP15XX))
-
 #include <linux/clocksource.h>
 
 /*
@@ -45,7 +46,7 @@
 static u32 offset_32k __read_mostly;
 
 #ifdef CONFIG_ARCH_OMAP16XX
-static cycle_t omap16xx_32k_read(struct clocksource *cs)
+static cycle_t notrace omap16xx_32k_read(struct clocksource *cs)
 {
 	return omap_readl(OMAP16XX_TIMER_32K_SYNCHRONIZED) - offset_32k;
 }
@@ -54,7 +55,7 @@ static cycle_t omap16xx_32k_read(struct
 #endif
 
 #ifdef CONFIG_ARCH_OMAP2420
-static cycle_t omap2420_32k_read(struct clocksource *cs)
+static cycle_t notrace omap2420_32k_read(struct clocksource *cs)
 {
 	return omap_readl(OMAP2420_32KSYNCT_BASE + 0x10) - offset_32k;
 }
@@ -63,7 +64,7 @@ static cycle_t omap2420_32k_read(struct
 #endif
 
 #ifdef CONFIG_ARCH_OMAP2430
-static cycle_t omap2430_32k_read(struct clocksource *cs)
+static cycle_t notrace omap2430_32k_read(struct clocksource *cs)
 {
 	return omap_readl(OMAP2430_32KSYNCT_BASE + 0x10) - offset_32k;
 }
@@ -72,7 +73,7 @@ static cycle_t omap2430_32k_read(struct
 #endif
 
 #ifdef CONFIG_ARCH_OMAP3
-static cycle_t omap34xx_32k_read(struct clocksource *cs)
+static cycle_t notrace omap34xx_32k_read(struct clocksource *cs)
 {
 	return omap_readl(OMAP3430_32KSYNCT_BASE + 0x10) - offset_32k;
 }
@@ -81,7 +82,7 @@ static cycle_t omap34xx_32k_read(struct
 #endif
 
 #ifdef CONFIG_ARCH_OMAP4
-static cycle_t omap44xx_32k_read(struct clocksource *cs)
+static cycle_t notrace omap44xx_32k_read(struct clocksource *cs)
 {
 	return omap_readl(OMAP4430_32KSYNCT_BASE + 0x10) - offset_32k;
 }
@@ -93,7 +94,7 @@ static cycle_t omap44xx_32k_read(struct
  * Kernel assumes that sched_clock can be called early but may not have
  * things ready yet.
  */
-static cycle_t omap_32k_read_dummy(struct clocksource *cs)
+static cycle_t notrace omap_32k_read_dummy(struct clocksource *cs)
 {
 	return 0;
 }
@@ -103,7 +104,6 @@ static struct clocksource clocksource_32
 	.rating		= 250,
 	.read		= omap_32k_read_dummy,
 	.mask		= CLOCKSOURCE_MASK(32),
-	.shift		= 10,
 	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
@@ -111,10 +111,37 @@ static struct clocksource clocksource_32
  * Returns current time from boot in nsecs. It's OK for this to wrap
  * around for now, as it's just a relative time stamp.
  */
-unsigned long long sched_clock(void)
+static DEFINE_CLOCK_DATA(cd);
+
+/*
+ * Constants generated by clocks_calc_mult_shift(m, s, 32768, NSEC_PER_SEC, 60).
+ * This gives a resolution of about 30us and a wrap period of about 36hrs.
+ */
+#define SC_MULT		4000000000u
+#define SC_SHIFT	17
+
+static inline unsigned long long notrace _omap_32k_sched_clock(void)
 {
-	return clocksource_cyc2ns(clocksource_32k.read(&clocksource_32k),
-				  clocksource_32k.mult, clocksource_32k.shift);
+	u32 cyc = clocksource_32k.read(&clocksource_32k);
+	return cyc_to_fixed_sched_clock(&cd, cyc, (u32)~0, SC_MULT, SC_SHIFT);
+}
+
+#ifndef CONFIG_OMAP_MPU_TIMER
+unsigned long long notrace sched_clock(void)
+{
+	return _omap_32k_sched_clock();
+}
+#else
+unsigned long long notrace omap_32k_sched_clock(void)
+{
+	return _omap_32k_sched_clock();
+}
+#endif
+
+static void notrace omap_update_sched_clock(void)
+{
+	u32 cyc = clocksource_32k.read(&clocksource_32k);
+	update_sched_clock(&cd, cyc, (u32)~0);
 }
 
 /**
@@ -143,7 +170,7 @@ void read_persistent_clock(struct timesp
 	*ts = *tsp;
 }
 
-static int __init omap_init_clocksource_32k(void)
+int __init omap_init_clocksource_32k(void)
 {
 	static char err[] __initdata = KERN_ERR
 			"%s: can't register clocksource!\n";
@@ -168,17 +195,13 @@ static int __init omap_init_clocksource_
 		if (!IS_ERR(sync_32k_ick))
 			clk_enable(sync_32k_ick);
 
-		clocksource_32k.mult = clocksource_hz2mult(32768,
-					    clocksource_32k.shift);
-
 		offset_32k = clocksource_32k.read(&clocksource_32k);
 
-		if (clocksource_register(&clocksource_32k))
+		if (clocksource_register_hz(&clocksource_32k, 32768))
 			printk(err, clocksource_32k.name);
+
+		init_fixed_sched_clock(&cd, omap_update_sched_clock, 32,
+				       32768, SC_MULT, SC_SHIFT);
 	}
 	return 0;
 }
-arch_initcall(omap_init_clocksource_32k);
-
-#endif	/* !(defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP15XX)) */
-
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-omap/devices.c linux-libre-2.6.38-gnu1/arch/arm/plat-omap/devices.c
--- linux-libre-2.6.37-gnu1/arch/arm/plat-omap/devices.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-omap/devices.c	2011-03-14 21:20:32.000000000 -0400
@@ -232,46 +232,6 @@ static void omap_init_uwire(void)
 static inline void omap_init_uwire(void) {}
 #endif
 
-/*-------------------------------------------------------------------------*/
-
-#if	defined(CONFIG_OMAP_WATCHDOG) || defined(CONFIG_OMAP_WATCHDOG_MODULE)
-
-static struct resource wdt_resources[] = {
-	{
-		.flags		= IORESOURCE_MEM,
-	},
-};
-
-static struct platform_device omap_wdt_device = {
-	.name	   = "omap_wdt",
-	.id	     = -1,
-	.num_resources	= ARRAY_SIZE(wdt_resources),
-	.resource	= wdt_resources,
-};
-
-static void omap_init_wdt(void)
-{
-	if (cpu_is_omap16xx())
-		wdt_resources[0].start = 0xfffeb000;
-	else if (cpu_is_omap2420())
-		wdt_resources[0].start = 0x48022000; /* WDT2 */
-	else if (cpu_is_omap2430())
-		wdt_resources[0].start = 0x49016000; /* WDT2 */
-	else if (cpu_is_omap343x())
-		wdt_resources[0].start = 0x48314000; /* WDT2 */
-	else if (cpu_is_omap44xx())
-		wdt_resources[0].start = 0x4a314000;
-	else
-		return;
-
-	wdt_resources[0].end = wdt_resources[0].start + 0x4f;
-
-	(void) platform_device_register(&omap_wdt_device);
-}
-#else
-static inline void omap_init_wdt(void) {}
-#endif
-
 #if defined(CONFIG_TIDSPBRIDGE) || defined(CONFIG_TIDSPBRIDGE_MODULE)
 
 static phys_addr_t omap_dsp_phys_mempool_base;
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-omap/dma.c linux-libre-2.6.38-gnu1/arch/arm/plat-omap/dma.c
--- linux-libre-2.6.37-gnu1/arch/arm/plat-omap/dma.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-omap/dma.c	2011-03-14 21:20:32.000000000 -0400
@@ -15,6 +15,10 @@
  *
  * Support functions for the OMAP internal DMA channels.
  *
+ * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
+ * Converted DMA library into DMA platform driver.
+ *	- G, Manjunath Kondaiah <manjugk@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.
@@ -49,11 +53,15 @@ enum { DMA_CHAIN_STARTED, DMA_CHAIN_NOTS
 #endif
 
 #define OMAP_DMA_ACTIVE			0x01
-#define OMAP2_DMA_CSR_CLEAR_MASK	0xffe
+#define OMAP2_DMA_CSR_CLEAR_MASK	0xffffffff
 
 #define OMAP_FUNC_MUX_ARM_BASE		(0xfffe1000 + 0xec)
 
+static struct omap_system_dma_plat_info *p;
+static struct omap_dma_dev_attr *d;
+
 static int enable_1510_mode;
+static u32 errata;
 
 static struct omap_dma_global_context_registers {
 	u32 dma_irqenable_l0;
@@ -61,27 +69,6 @@ static struct omap_dma_global_context_re
 	u32 dma_gcr;
 } omap_dma_global_context;
 
-struct omap_dma_lch {
-	int next_lch;
-	int dev_id;
-	u16 saved_csr;
-	u16 enabled_irqs;
-	const char *dev_name;
-	void (*callback)(int lch, u16 ch_status, void *data);
-	void *data;
-
-#ifndef CONFIG_ARCH_OMAP1
-	/* required for Dynamic chaining */
-	int prev_linked_ch;
-	int next_linked_ch;
-	int state;
-	int chain_id;
-
-	int status;
-#endif
-	long flags;
-};
-
 struct dma_link_info {
 	int *linked_dmach_q;
 	int no_of_lchs_linked;
@@ -137,15 +124,6 @@ static int omap_dma_reserve_channels;
 
 static spinlock_t dma_chan_lock;
 static struct omap_dma_lch *dma_chan;
-static void __iomem *omap_dma_base;
-
-static const u8 omap1_dma_irq[OMAP1_LOGICAL_DMA_CH_COUNT] = {
-	INT_DMA_CH0_6, INT_DMA_CH1_7, INT_DMA_CH2_8, INT_DMA_CH3,
-	INT_DMA_CH4, INT_DMA_CH5, INT_1610_DMA_CH6, INT_1610_DMA_CH7,
-	INT_1610_DMA_CH8, INT_1610_DMA_CH9, INT_1610_DMA_CH10,
-	INT_1610_DMA_CH11, INT_1610_DMA_CH12, INT_1610_DMA_CH13,
-	INT_1610_DMA_CH14, INT_1610_DMA_CH15, INT_DMA_LCD
-};
 
 static inline void disable_lnk(int lch);
 static void omap_disable_channel_irq(int lch);
@@ -154,24 +132,6 @@ static inline void omap_enable_channel_i
 #define REVISIT_24XX()		printk(KERN_ERR "FIXME: no %s on 24xx\n", \
 						__func__);
 
-#define dma_read(reg)							\
-({									\
-	u32 __val;							\
-	if (cpu_class_is_omap1())					\
-		__val = __raw_readw(omap_dma_base + OMAP1_DMA_##reg);	\
-	else								\
-		__val = __raw_readl(omap_dma_base + OMAP_DMA4_##reg);	\
-	__val;								\
-})
-
-#define dma_write(val, reg)						\
-({									\
-	if (cpu_class_is_omap1())					\
-		__raw_writew((u16)(val), omap_dma_base + OMAP1_DMA_##reg); \
-	else								\
-		__raw_writel((val), omap_dma_base + OMAP_DMA4_##reg);	\
-})
-
 #ifdef CONFIG_ARCH_OMAP15XX
 /* Returns 1 if the DMA module is in OMAP1510-compatible mode, 0 otherwise */
 int omap_dma_in_1510_mode(void)
@@ -206,16 +166,6 @@ static inline void set_gdma_dev(int req,
 #define set_gdma_dev(req, dev)	do {} while (0)
 #endif
 
-/* Omap1 only */
-static void clear_lch_regs(int lch)
-{
-	int i;
-	void __iomem *lch_base = omap_dma_base + OMAP1_DMA_CH_BASE(lch);
-
-	for (i = 0; i < 0x2c; i += 2)
-		__raw_writew(0, lch_base + i);
-}
-
 void omap_set_dma_priority(int lch, int dst_port, int priority)
 {
 	unsigned long reg;
@@ -248,12 +198,12 @@ void omap_set_dma_priority(int lch, int
 	if (cpu_class_is_omap2()) {
 		u32 ccr;
 
-		ccr = dma_read(CCR(lch));
+		ccr = p->dma_read(CCR, lch);
 		if (priority)
 			ccr |= (1 << 6);
 		else
 			ccr &= ~(1 << 6);
-		dma_write(ccr, CCR(lch));
+		p->dma_write(ccr, CCR, lch);
 	}
 }
 EXPORT_SYMBOL(omap_set_dma_priority);
@@ -264,31 +214,31 @@ void omap_set_dma_transfer_params(int lc
 {
 	u32 l;
 
-	l = dma_read(CSDP(lch));
+	l = p->dma_read(CSDP, lch);
 	l &= ~0x03;
 	l |= data_type;
-	dma_write(l, CSDP(lch));
+	p->dma_write(l, CSDP, lch);
 
 	if (cpu_class_is_omap1()) {
 		u16 ccr;
 
-		ccr = dma_read(CCR(lch));
+		ccr = p->dma_read(CCR, lch);
 		ccr &= ~(1 << 5);
 		if (sync_mode == OMAP_DMA_SYNC_FRAME)
 			ccr |= 1 << 5;
-		dma_write(ccr, CCR(lch));
+		p->dma_write(ccr, CCR, lch);
 
-		ccr = dma_read(CCR2(lch));
+		ccr = p->dma_read(CCR2, lch);
 		ccr &= ~(1 << 2);
 		if (sync_mode == OMAP_DMA_SYNC_BLOCK)
 			ccr |= 1 << 2;
-		dma_write(ccr, CCR2(lch));
+		p->dma_write(ccr, CCR2, lch);
 	}
 
 	if (cpu_class_is_omap2() && dma_trigger) {
 		u32 val;
 
-		val = dma_read(CCR(lch));
+		val = p->dma_read(CCR, lch);
 
 		/* DMA_SYNCHRO_CONTROL_UPPER depends on the channel number */
 		val &= ~((1 << 23) | (3 << 19) | 0x1f);
@@ -313,11 +263,11 @@ void omap_set_dma_transfer_params(int lc
 		} else {
 			val &= ~(1 << 24);	/* dest synch */
 		}
-		dma_write(val, CCR(lch));
+		p->dma_write(val, CCR, lch);
 	}
 
-	dma_write(elem_count, CEN(lch));
-	dma_write(frame_count, CFN(lch));
+	p->dma_write(elem_count, CEN, lch);
+	p->dma_write(frame_count, CFN, lch);
 }
 EXPORT_SYMBOL(omap_set_dma_transfer_params);
 
@@ -328,7 +278,7 @@ void omap_set_dma_color_mode(int lch, en
 	if (cpu_class_is_omap1()) {
 		u16 w;
 
-		w = dma_read(CCR2(lch));
+		w = p->dma_read(CCR2, lch);
 		w &= ~0x03;
 
 		switch (mode) {
@@ -343,23 +293,22 @@ void omap_set_dma_color_mode(int lch, en
 		default:
 			BUG();
 		}
-		dma_write(w, CCR2(lch));
+		p->dma_write(w, CCR2, lch);
 
-		w = dma_read(LCH_CTRL(lch));
+		w = p->dma_read(LCH_CTRL, lch);
 		w &= ~0x0f;
 		/* Default is channel type 2D */
 		if (mode) {
-			dma_write((u16)color, COLOR_L(lch));
-			dma_write((u16)(color >> 16), COLOR_U(lch));
+			p->dma_write(color, COLOR, lch);
 			w |= 1;		/* Channel type G */
 		}
-		dma_write(w, LCH_CTRL(lch));
+		p->dma_write(w, LCH_CTRL, lch);
 	}
 
 	if (cpu_class_is_omap2()) {
 		u32 val;
 
-		val = dma_read(CCR(lch));
+		val = p->dma_read(CCR, lch);
 		val &= ~((1 << 17) | (1 << 16));
 
 		switch (mode) {
@@ -374,10 +323,10 @@ void omap_set_dma_color_mode(int lch, en
 		default:
 			BUG();
 		}
-		dma_write(val, CCR(lch));
+		p->dma_write(val, CCR, lch);
 
 		color &= 0xffffff;
-		dma_write(color, COLOR(lch));
+		p->dma_write(color, COLOR, lch);
 	}
 }
 EXPORT_SYMBOL(omap_set_dma_color_mode);
@@ -387,10 +336,10 @@ void omap_set_dma_write_mode(int lch, en
 	if (cpu_class_is_omap2()) {
 		u32 csdp;
 
-		csdp = dma_read(CSDP(lch));
+		csdp = p->dma_read(CSDP, lch);
 		csdp &= ~(0x3 << 16);
 		csdp |= (mode << 16);
-		dma_write(csdp, CSDP(lch));
+		p->dma_write(csdp, CSDP, lch);
 	}
 }
 EXPORT_SYMBOL(omap_set_dma_write_mode);
@@ -400,10 +349,10 @@ void omap_set_dma_channel_mode(int lch,
 	if (cpu_class_is_omap1() && !cpu_is_omap15xx()) {
 		u32 l;
 
-		l = dma_read(LCH_CTRL(lch));
+		l = p->dma_read(LCH_CTRL, lch);
 		l &= ~0x7;
 		l |= mode;
-		dma_write(l, LCH_CTRL(lch));
+		p->dma_write(l, LCH_CTRL, lch);
 	}
 }
 EXPORT_SYMBOL(omap_set_dma_channel_mode);
@@ -418,27 +367,21 @@ void omap_set_dma_src_params(int lch, in
 	if (cpu_class_is_omap1()) {
 		u16 w;
 
-		w = dma_read(CSDP(lch));
+		w = p->dma_read(CSDP, lch);
 		w &= ~(0x1f << 2);
 		w |= src_port << 2;
-		dma_write(w, CSDP(lch));
+		p->dma_write(w, CSDP, lch);
 	}
 
-	l = dma_read(CCR(lch));
+	l = p->dma_read(CCR, lch);
 	l &= ~(0x03 << 12);
 	l |= src_amode << 12;
-	dma_write(l, CCR(lch));
-
-	if (cpu_class_is_omap1()) {
-		dma_write(src_start >> 16, CSSA_U(lch));
-		dma_write((u16)src_start, CSSA_L(lch));
-	}
+	p->dma_write(l, CCR, lch);
 
-	if (cpu_class_is_omap2())
-		dma_write(src_start, CSSA(lch));
+	p->dma_write(src_start, CSSA, lch);
 
-	dma_write(src_ei, CSEI(lch));
-	dma_write(src_fi, CSFI(lch));
+	p->dma_write(src_ei, CSEI, lch);
+	p->dma_write(src_fi, CSFI, lch);
 }
 EXPORT_SYMBOL(omap_set_dma_src_params);
 
@@ -466,8 +409,8 @@ void omap_set_dma_src_index(int lch, int
 	if (cpu_class_is_omap2())
 		return;
 
-	dma_write(eidx, CSEI(lch));
-	dma_write(fidx, CSFI(lch));
+	p->dma_write(eidx, CSEI, lch);
+	p->dma_write(fidx, CSFI, lch);
 }
 EXPORT_SYMBOL(omap_set_dma_src_index);
 
@@ -475,11 +418,11 @@ void omap_set_dma_src_data_pack(int lch,
 {
 	u32 l;
 
-	l = dma_read(CSDP(lch));
+	l = p->dma_read(CSDP, lch);
 	l &= ~(1 << 6);
 	if (enable)
 		l |= (1 << 6);
-	dma_write(l, CSDP(lch));
+	p->dma_write(l, CSDP, lch);
 }
 EXPORT_SYMBOL(omap_set_dma_src_data_pack);
 
@@ -488,7 +431,7 @@ void omap_set_dma_src_burst_mode(int lch
 	unsigned int burst = 0;
 	u32 l;
 
-	l = dma_read(CSDP(lch));
+	l = p->dma_read(CSDP, lch);
 	l &= ~(0x03 << 7);
 
 	switch (burst_mode) {
@@ -524,7 +467,7 @@ void omap_set_dma_src_burst_mode(int lch
 	}
 
 	l |= (burst << 7);
-	dma_write(l, CSDP(lch));
+	p->dma_write(l, CSDP, lch);
 }
 EXPORT_SYMBOL(omap_set_dma_src_burst_mode);
 
@@ -536,27 +479,21 @@ void omap_set_dma_dest_params(int lch, i
 	u32 l;
 
 	if (cpu_class_is_omap1()) {
-		l = dma_read(CSDP(lch));
+		l = p->dma_read(CSDP, lch);
 		l &= ~(0x1f << 9);
 		l |= dest_port << 9;
-		dma_write(l, CSDP(lch));
+		p->dma_write(l, CSDP, lch);
 	}
 
-	l = dma_read(CCR(lch));
+	l = p->dma_read(CCR, lch);
 	l &= ~(0x03 << 14);
 	l |= dest_amode << 14;
-	dma_write(l, CCR(lch));
-
-	if (cpu_class_is_omap1()) {
-		dma_write(dest_start >> 16, CDSA_U(lch));
-		dma_write(dest_start, CDSA_L(lch));
-	}
+	p->dma_write(l, CCR, lch);
 
-	if (cpu_class_is_omap2())
-		dma_write(dest_start, CDSA(lch));
+	p->dma_write(dest_start, CDSA, lch);
 
-	dma_write(dst_ei, CDEI(lch));
-	dma_write(dst_fi, CDFI(lch));
+	p->dma_write(dst_ei, CDEI, lch);
+	p->dma_write(dst_fi, CDFI, lch);
 }
 EXPORT_SYMBOL(omap_set_dma_dest_params);
 
@@ -565,8 +502,8 @@ void omap_set_dma_dest_index(int lch, in
 	if (cpu_class_is_omap2())
 		return;
 
-	dma_write(eidx, CDEI(lch));
-	dma_write(fidx, CDFI(lch));
+	p->dma_write(eidx, CDEI, lch);
+	p->dma_write(fidx, CDFI, lch);
 }
 EXPORT_SYMBOL(omap_set_dma_dest_index);
 
@@ -574,11 +511,11 @@ void omap_set_dma_dest_data_pack(int lch
 {
 	u32 l;
 
-	l = dma_read(CSDP(lch));
+	l = p->dma_read(CSDP, lch);
 	l &= ~(1 << 13);
 	if (enable)
 		l |= 1 << 13;
-	dma_write(l, CSDP(lch));
+	p->dma_write(l, CSDP, lch);
 }
 EXPORT_SYMBOL(omap_set_dma_dest_data_pack);
 
@@ -587,7 +524,7 @@ void omap_set_dma_dest_burst_mode(int lc
 	unsigned int burst = 0;
 	u32 l;
 
-	l = dma_read(CSDP(lch));
+	l = p->dma_read(CSDP, lch);
 	l &= ~(0x03 << 14);
 
 	switch (burst_mode) {
@@ -620,7 +557,7 @@ void omap_set_dma_dest_burst_mode(int lc
 		return;
 	}
 	l |= (burst << 14);
-	dma_write(l, CSDP(lch));
+	p->dma_write(l, CSDP, lch);
 }
 EXPORT_SYMBOL(omap_set_dma_dest_burst_mode);
 
@@ -630,18 +567,18 @@ static inline void omap_enable_channel_i
 
 	/* Clear CSR */
 	if (cpu_class_is_omap1())
-		status = dma_read(CSR(lch));
+		status = p->dma_read(CSR, lch);
 	else if (cpu_class_is_omap2())
-		dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR(lch));
+		p->dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR, lch);
 
 	/* Enable some nice interrupts. */
-	dma_write(dma_chan[lch].enabled_irqs, CICR(lch));
+	p->dma_write(dma_chan[lch].enabled_irqs, CICR, lch);
 }
 
 static void omap_disable_channel_irq(int lch)
 {
 	if (cpu_class_is_omap2())
-		dma_write(0, CICR(lch));
+		p->dma_write(0, CICR, lch);
 }
 
 void omap_enable_dma_irq(int lch, u16 bits)
@@ -660,7 +597,7 @@ static inline void enable_lnk(int lch)
 {
 	u32 l;
 
-	l = dma_read(CLNK_CTRL(lch));
+	l = p->dma_read(CLNK_CTRL, lch);
 
 	if (cpu_class_is_omap1())
 		l &= ~(1 << 14);
@@ -675,18 +612,18 @@ static inline void enable_lnk(int lch)
 			l = dma_chan[lch].next_linked_ch | (1 << 15);
 #endif
 
-	dma_write(l, CLNK_CTRL(lch));
+	p->dma_write(l, CLNK_CTRL, lch);
 }
 
 static inline void disable_lnk(int lch)
 {
 	u32 l;
 
-	l = dma_read(CLNK_CTRL(lch));
+	l = p->dma_read(CLNK_CTRL, lch);
 
 	/* Disable interrupts */
 	if (cpu_class_is_omap1()) {
-		dma_write(0, CICR(lch));
+		p->dma_write(0, CICR, lch);
 		/* Set the STOP_LNK bit */
 		l |= 1 << 14;
 	}
@@ -697,7 +634,7 @@ static inline void disable_lnk(int lch)
 		l &= ~(1 << 15);
 	}
 
-	dma_write(l, CLNK_CTRL(lch));
+	p->dma_write(l, CLNK_CTRL, lch);
 	dma_chan[lch].flags &= ~OMAP_DMA_ACTIVE;
 }
 
@@ -710,9 +647,9 @@ static inline void omap2_enable_irq_lch(
 		return;
 
 	spin_lock_irqsave(&dma_chan_lock, flags);
-	val = dma_read(IRQENABLE_L0);
+	val = p->dma_read(IRQENABLE_L0, lch);
 	val |= 1 << lch;
-	dma_write(val, IRQENABLE_L0);
+	p->dma_write(val, IRQENABLE_L0, lch);
 	spin_unlock_irqrestore(&dma_chan_lock, flags);
 }
 
@@ -725,9 +662,9 @@ static inline void omap2_disable_irq_lch
 		return;
 
 	spin_lock_irqsave(&dma_chan_lock, flags);
-	val = dma_read(IRQENABLE_L0);
+	val = p->dma_read(IRQENABLE_L0, lch);
 	val &= ~(1 << lch);
-	dma_write(val, IRQENABLE_L0);
+	p->dma_write(val, IRQENABLE_L0, lch);
 	spin_unlock_irqrestore(&dma_chan_lock, flags);
 }
 
@@ -754,8 +691,8 @@ int omap_request_dma(int dev_id, const c
 	chan = dma_chan + free_ch;
 	chan->dev_id = dev_id;
 
-	if (cpu_class_is_omap1())
-		clear_lch_regs(free_ch);
+	if (p->clear_lch_regs)
+		p->clear_lch_regs(free_ch);
 
 	if (cpu_class_is_omap2())
 		omap_clear_dma(free_ch);
@@ -792,17 +729,17 @@ int omap_request_dma(int dev_id, const c
 		 * Disable the 1510 compatibility mode and set the sync device
 		 * id.
 		 */
-		dma_write(dev_id | (1 << 10), CCR(free_ch));
+		p->dma_write(dev_id | (1 << 10), CCR, free_ch);
 	} else if (cpu_is_omap7xx() || cpu_is_omap15xx()) {
-		dma_write(dev_id, CCR(free_ch));
+		p->dma_write(dev_id, CCR, free_ch);
 	}
 
 	if (cpu_class_is_omap2()) {
 		omap2_enable_irq_lch(free_ch);
 		omap_enable_channel_irq(free_ch);
 		/* Clear the CSR register and IRQ status register */
-		dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR(free_ch));
-		dma_write(1 << free_ch, IRQSTATUS_L0);
+		p->dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR, free_ch);
+		p->dma_write(1 << free_ch, IRQSTATUS_L0, 0);
 	}
 
 	*dma_ch_out = free_ch;
@@ -823,23 +760,23 @@ void omap_free_dma(int lch)
 
 	if (cpu_class_is_omap1()) {
 		/* Disable all DMA interrupts for the channel. */
-		dma_write(0, CICR(lch));
+		p->dma_write(0, CICR, lch);
 		/* Make sure the DMA transfer is stopped. */
-		dma_write(0, CCR(lch));
+		p->dma_write(0, CCR, lch);
 	}
 
 	if (cpu_class_is_omap2()) {
 		omap2_disable_irq_lch(lch);
 
 		/* Clear the CSR register and IRQ status register */
-		dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR(lch));
-		dma_write(1 << lch, IRQSTATUS_L0);
+		p->dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR, lch);
+		p->dma_write(1 << lch, IRQSTATUS_L0, lch);
 
 		/* Disable all DMA interrupts for the channel. */
-		dma_write(0, CICR(lch));
+		p->dma_write(0, CICR, lch);
 
 		/* Make sure the DMA transfer is stopped. */
-		dma_write(0, CCR(lch));
+		p->dma_write(0, CCR, lch);
 		omap_clear_dma(lch);
 	}
 
@@ -880,7 +817,7 @@ omap_dma_set_global_params(int arb_rate,
 	reg |= (0x3 & tparams) << 12;
 	reg |= (arb_rate & 0xff) << 16;
 
-	dma_write(reg, GCR);
+	p->dma_write(reg, GCR, 0);
 }
 EXPORT_SYMBOL(omap_dma_set_global_params);
 
@@ -903,14 +840,14 @@ omap_dma_set_prio_lch(int lch, unsigned
 		printk(KERN_ERR "Invalid channel id\n");
 		return -EINVAL;
 	}
-	l = dma_read(CCR(lch));
+	l = p->dma_read(CCR, lch);
 	l &= ~((1 << 6) | (1 << 26));
 	if (cpu_is_omap2430() || cpu_is_omap34xx() ||  cpu_is_omap44xx())
 		l |= ((read_prio & 0x1) << 6) | ((write_prio & 0x1) << 26);
 	else
 		l |= ((read_prio & 0x1) << 6);
 
-	dma_write(l, CCR(lch));
+	p->dma_write(l, CCR, lch);
 
 	return 0;
 }
@@ -925,25 +862,7 @@ void omap_clear_dma(int lch)
 	unsigned long flags;
 
 	local_irq_save(flags);
-
-	if (cpu_class_is_omap1()) {
-		u32 l;
-
-		l = dma_read(CCR(lch));
-		l &= ~OMAP_DMA_CCR_EN;
-		dma_write(l, CCR(lch));
-
-		/* Clear pending interrupts */
-		l = dma_read(CSR(lch));
-	}
-
-	if (cpu_class_is_omap2()) {
-		int i;
-		void __iomem *lch_base = omap_dma_base + OMAP_DMA4_CH_BASE(lch);
-		for (i = 0; i < 0x44; i += 4)
-			__raw_writel(0, lch_base + i);
-	}
-
+	p->clear_dma(lch);
 	local_irq_restore(flags);
 }
 EXPORT_SYMBOL(omap_clear_dma);
@@ -957,13 +876,13 @@ void omap_start_dma(int lch)
 	 * before starting dma transfer.
 	 */
 	if (cpu_is_omap15xx())
-		dma_write(0, CPC(lch));
+		p->dma_write(0, CPC, lch);
 	else
-		dma_write(0, CDAC(lch));
+		p->dma_write(0, CDAC, lch);
 
 	if (!omap_dma_in_1510_mode() && dma_chan[lch].next_lch != -1) {
 		int next_lch, cur_lch;
-		char dma_chan_link_map[OMAP_DMA4_LOGICAL_DMA_CH_COUNT];
+		char dma_chan_link_map[dma_lch_count];
 
 		dma_chan_link_map[lch] = 1;
 		/* Set the link register of the first channel */
@@ -985,32 +904,18 @@ void omap_start_dma(int lch)
 
 			cur_lch = next_lch;
 		} while (next_lch != -1);
-	} else if (cpu_is_omap242x() ||
-		(cpu_is_omap243x() &&  omap_type() <= OMAP2430_REV_ES1_0)) {
-
-		/* Errata: Need to write lch even if not using chaining */
-		dma_write(lch, CLNK_CTRL(lch));
-	}
+	} else if (IS_DMA_ERRATA(DMA_ERRATA_PARALLEL_CHANNELS))
+		p->dma_write(lch, CLNK_CTRL, lch);
 
 	omap_enable_channel_irq(lch);
 
-	l = dma_read(CCR(lch));
-
-	/*
-	 * Errata: Inter Frame DMA buffering issue (All OMAP2420 and
-	 * OMAP2430ES1.0): DMA will wrongly buffer elements if packing and
-	 * bursting is enabled. This might result in data gets stalled in
-	 * FIFO at the end of the block.
-	 * Workaround: DMA channels must have BUFFERING_DISABLED bit set to
-	 * guarantee no data will stay in the DMA FIFO in case inter frame
-	 * buffering occurs.
-	 */
-	if (cpu_is_omap2420() ||
-	    (cpu_is_omap2430() && (omap_type() == OMAP2430_REV_ES1_0)))
-		l |= OMAP_DMA_CCR_BUFFERING_DISABLE;
+	l = p->dma_read(CCR, lch);
 
+	if (IS_DMA_ERRATA(DMA_ERRATA_IFRAME_BUFFERING))
+			l |= OMAP_DMA_CCR_BUFFERING_DISABLE;
 	l |= OMAP_DMA_CCR_EN;
-	dma_write(l, CCR(lch));
+
+	p->dma_write(l, CCR, lch);
 
 	dma_chan[lch].flags |= OMAP_DMA_ACTIVE;
 }
@@ -1022,46 +927,46 @@ void omap_stop_dma(int lch)
 
 	/* Disable all interrupts on the channel */
 	if (cpu_class_is_omap1())
-		dma_write(0, CICR(lch));
+		p->dma_write(0, CICR, lch);
 
-	l = dma_read(CCR(lch));
-	/* OMAP3 Errata i541: sDMA FIFO draining does not finish */
-	if (cpu_is_omap34xx() && (l & OMAP_DMA_CCR_SEL_SRC_DST_SYNC)) {
+	l = p->dma_read(CCR, lch);
+	if (IS_DMA_ERRATA(DMA_ERRATA_i541) &&
+			(l & OMAP_DMA_CCR_SEL_SRC_DST_SYNC)) {
 		int i = 0;
 		u32 sys_cf;
 
 		/* Configure No-Standby */
-		l = dma_read(OCP_SYSCONFIG);
+		l = p->dma_read(OCP_SYSCONFIG, lch);
 		sys_cf = l;
 		l &= ~DMA_SYSCONFIG_MIDLEMODE_MASK;
 		l |= DMA_SYSCONFIG_MIDLEMODE(DMA_IDLEMODE_NO_IDLE);
-		dma_write(l , OCP_SYSCONFIG);
+		p->dma_write(l , OCP_SYSCONFIG, 0);
 
-		l = dma_read(CCR(lch));
+		l = p->dma_read(CCR, lch);
 		l &= ~OMAP_DMA_CCR_EN;
-		dma_write(l, CCR(lch));
+		p->dma_write(l, CCR, lch);
 
 		/* Wait for sDMA FIFO drain */
-		l = dma_read(CCR(lch));
+		l = p->dma_read(CCR, lch);
 		while (i < 100 && (l & (OMAP_DMA_CCR_RD_ACTIVE |
 					OMAP_DMA_CCR_WR_ACTIVE))) {
 			udelay(5);
 			i++;
-			l = dma_read(CCR(lch));
+			l = p->dma_read(CCR, lch);
 		}
 		if (i >= 100)
 			printk(KERN_ERR "DMA drain did not complete on "
 					"lch %d\n", lch);
 		/* Restore OCP_SYSCONFIG */
-		dma_write(sys_cf, OCP_SYSCONFIG);
+		p->dma_write(sys_cf, OCP_SYSCONFIG, lch);
 	} else {
 		l &= ~OMAP_DMA_CCR_EN;
-		dma_write(l, CCR(lch));
+		p->dma_write(l, CCR, lch);
 	}
 
 	if (!omap_dma_in_1510_mode() && dma_chan[lch].next_lch != -1) {
 		int next_lch, cur_lch = lch;
-		char dma_chan_link_map[OMAP_DMA4_LOGICAL_DMA_CH_COUNT];
+		char dma_chan_link_map[dma_lch_count];
 
 		memset(dma_chan_link_map, 0, sizeof(dma_chan_link_map));
 		do {
@@ -1122,19 +1027,15 @@ dma_addr_t omap_get_dma_src_pos(int lch)
 	dma_addr_t offset = 0;
 
 	if (cpu_is_omap15xx())
-		offset = dma_read(CPC(lch));
+		offset = p->dma_read(CPC, lch);
 	else
-		offset = dma_read(CSAC(lch));
+		offset = p->dma_read(CSAC, lch);
 
-	/*
-	 * omap 3.2/3.3 erratum: sometimes 0 is returned if CSAC/CDAC is
-	 * read before the DMA controller finished disabling the channel.
-	 */
-	if (!cpu_is_omap15xx() && offset == 0)
-		offset = dma_read(CSAC(lch));
+	if (IS_DMA_ERRATA(DMA_ERRATA_3_3) && offset == 0)
+		offset = p->dma_read(CSAC, lch);
 
 	if (cpu_class_is_omap1())
-		offset |= (dma_read(CSSA_U(lch)) << 16);
+		offset |= (p->dma_read(CSSA, lch) & 0xFFFF0000);
 
 	return offset;
 }
@@ -1153,19 +1054,19 @@ dma_addr_t omap_get_dma_dst_pos(int lch)
 	dma_addr_t offset = 0;
 
 	if (cpu_is_omap15xx())
-		offset = dma_read(CPC(lch));
+		offset = p->dma_read(CPC, lch);
 	else
-		offset = dma_read(CDAC(lch));
+		offset = p->dma_read(CDAC, lch);
 
 	/*
 	 * omap 3.2/3.3 erratum: sometimes 0 is returned if CSAC/CDAC is
 	 * read before the DMA controller finished disabling the channel.
 	 */
 	if (!cpu_is_omap15xx() && offset == 0)
-		offset = dma_read(CDAC(lch));
+		offset = p->dma_read(CDAC, lch);
 
 	if (cpu_class_is_omap1())
-		offset |= (dma_read(CDSA_U(lch)) << 16);
+		offset |= (p->dma_read(CDSA, lch) & 0xFFFF0000);
 
 	return offset;
 }
@@ -1173,7 +1074,7 @@ EXPORT_SYMBOL(omap_get_dma_dst_pos);
 
 int omap_get_dma_active_status(int lch)
 {
-	return (dma_read(CCR(lch)) & OMAP_DMA_CCR_EN) != 0;
+	return (p->dma_read(CCR, lch) & OMAP_DMA_CCR_EN) != 0;
 }
 EXPORT_SYMBOL(omap_get_dma_active_status);
 
@@ -1186,7 +1087,7 @@ int omap_dma_running(void)
 			return 1;
 
 	for (lch = 0; lch < dma_chan_count; lch++)
-		if (dma_read(CCR(lch)) & OMAP_DMA_CCR_EN)
+		if (p->dma_read(CCR, lch) & OMAP_DMA_CCR_EN)
 			return 1;
 
 	return 0;
@@ -1201,8 +1102,8 @@ void omap_dma_link_lch(int lch_head, int
 {
 	if (omap_dma_in_1510_mode()) {
 		if (lch_head == lch_queue) {
-			dma_write(dma_read(CCR(lch_head)) | (3 << 8),
-								CCR(lch_head));
+			p->dma_write(p->dma_read(CCR, lch_head) | (3 << 8),
+								CCR, lch_head);
 			return;
 		}
 		printk(KERN_ERR "DMA linking is not supported in 1510 mode\n");
@@ -1228,8 +1129,8 @@ void omap_dma_unlink_lch(int lch_head, i
 {
 	if (omap_dma_in_1510_mode()) {
 		if (lch_head == lch_queue) {
-			dma_write(dma_read(CCR(lch_head)) & ~(3 << 8),
-								CCR(lch_head));
+			p->dma_write(p->dma_read(CCR, lch_head) & ~(3 << 8),
+								CCR, lch_head);
 			return;
 		}
 		printk(KERN_ERR "DMA linking is not supported in 1510 mode\n");
@@ -1255,8 +1156,6 @@ void omap_dma_unlink_lch(int lch_head, i
 }
 EXPORT_SYMBOL(omap_dma_unlink_lch);
 
-/*----------------------------------------------------------------------------*/
-
 #ifndef CONFIG_ARCH_OMAP1
 /* Create chain of DMA channesls */
 static void create_dma_lch_chain(int lch_head, int lch_queue)
@@ -1281,15 +1180,15 @@ static void create_dma_lch_chain(int lch
 					lch_queue;
 	}
 
-	l = dma_read(CLNK_CTRL(lch_head));
+	l = p->dma_read(CLNK_CTRL, lch_head);
 	l &= ~(0x1f);
 	l |= lch_queue;
-	dma_write(l, CLNK_CTRL(lch_head));
+	p->dma_write(l, CLNK_CTRL, lch_head);
 
-	l = dma_read(CLNK_CTRL(lch_queue));
+	l = p->dma_read(CLNK_CTRL, lch_queue);
 	l &= ~(0x1f);
 	l |= (dma_chan[lch_queue].next_linked_ch);
-	dma_write(l, CLNK_CTRL(lch_queue));
+	p->dma_write(l, CLNK_CTRL, lch_queue);
 }
 
 /**
@@ -1565,13 +1464,13 @@ int omap_dma_chain_a_transfer(int chain_
 
 	/* Set the params to the free channel */
 	if (src_start != 0)
-		dma_write(src_start, CSSA(lch));
+		p->dma_write(src_start, CSSA, lch);
 	if (dest_start != 0)
-		dma_write(dest_start, CDSA(lch));
+		p->dma_write(dest_start, CDSA, lch);
 
 	/* Write the buffer size */
-	dma_write(elem_count, CEN(lch));
-	dma_write(frame_count, CFN(lch));
+	p->dma_write(elem_count, CEN, lch);
+	p->dma_write(frame_count, CFN, lch);
 
 	/*
 	 * If the chain is dynamically linked,
@@ -1604,8 +1503,8 @@ int omap_dma_chain_a_transfer(int chain_
 				enable_lnk(dma_chan[lch].prev_linked_ch);
 				dma_chan[lch].state = DMA_CH_QUEUED;
 				start_dma = 0;
-				if (0 == ((1 << 7) & dma_read(
-					CCR(dma_chan[lch].prev_linked_ch)))) {
+				if (0 == ((1 << 7) & p->dma_read(
+					CCR, dma_chan[lch].prev_linked_ch))) {
 					disable_lnk(dma_chan[lch].
 						    prev_linked_ch);
 					pr_debug("\n prev ch is stopped\n");
@@ -1621,7 +1520,7 @@ int omap_dma_chain_a_transfer(int chain_
 			}
 			omap_enable_channel_irq(lch);
 
-			l = dma_read(CCR(lch));
+			l = p->dma_read(CCR, lch);
 
 			if ((0 == (l & (1 << 24))))
 				l &= ~(1 << 25);
@@ -1632,12 +1531,12 @@ int omap_dma_chain_a_transfer(int chain_
 					l |= (1 << 7);
 					dma_chan[lch].state = DMA_CH_STARTED;
 					pr_debug("starting %d\n", lch);
-					dma_write(l, CCR(lch));
+					p->dma_write(l, CCR, lch);
 				} else
 					start_dma = 0;
 			} else {
 				if (0 == (l & (1 << 7)))
-					dma_write(l, CCR(lch));
+					p->dma_write(l, CCR, lch);
 			}
 			dma_chan[lch].flags |= OMAP_DMA_ACTIVE;
 		}
@@ -1682,7 +1581,7 @@ int omap_start_dma_chain_transfers(int c
 		omap_enable_channel_irq(channels[0]);
 	}
 
-	l = dma_read(CCR(channels[0]));
+	l = p->dma_read(CCR, channels[0]);
 	l |= (1 << 7);
 	dma_linked_lch[chain_id].chain_state = DMA_CHAIN_STARTED;
 	dma_chan[channels[0]].state = DMA_CH_STARTED;
@@ -1691,7 +1590,7 @@ int omap_start_dma_chain_transfers(int c
 		l &= ~(1 << 25);
 	else
 		l |= (1 << 25);
-	dma_write(l, CCR(channels[0]));
+	p->dma_write(l, CCR, channels[0]);
 
 	dma_chan[channels[0]].flags |= OMAP_DMA_ACTIVE;
 
@@ -1711,7 +1610,7 @@ int omap_stop_dma_chain_transfers(int ch
 {
 	int *channels;
 	u32 l, i;
-	u32 sys_cf;
+	u32 sys_cf = 0;
 
 	/* Check for input params */
 	if (unlikely((chain_id < 0 || chain_id >= dma_lch_count))) {
@@ -1726,22 +1625,20 @@ int omap_stop_dma_chain_transfers(int ch
 	}
 	channels = dma_linked_lch[chain_id].linked_dmach_q;
 
-	/*
-	 * DMA Errata:
-	 * Special programming model needed to disable DMA before end of block
-	 */
-	sys_cf = dma_read(OCP_SYSCONFIG);
-	l = sys_cf;
-	/* Middle mode reg set no Standby */
-	l &= ~((1 << 12)|(1 << 13));
-	dma_write(l, OCP_SYSCONFIG);
+	if (IS_DMA_ERRATA(DMA_ERRATA_i88)) {
+		sys_cf = p->dma_read(OCP_SYSCONFIG, 0);
+		l = sys_cf;
+		/* Middle mode reg set no Standby */
+		l &= ~((1 << 12)|(1 << 13));
+		p->dma_write(l, OCP_SYSCONFIG, 0);
+	}
 
 	for (i = 0; i < dma_linked_lch[chain_id].no_of_lchs_linked; i++) {
 
 		/* Stop the Channel transmission */
-		l = dma_read(CCR(channels[i]));
+		l = p->dma_read(CCR, channels[i]);
 		l &= ~(1 << 7);
-		dma_write(l, CCR(channels[i]));
+		p->dma_write(l, CCR, channels[i]);
 
 		/* Disable the link in all the channels */
 		disable_lnk(channels[i]);
@@ -1753,8 +1650,8 @@ int omap_stop_dma_chain_transfers(int ch
 	/* Reset the Queue pointers */
 	OMAP_DMA_CHAIN_QINIT(chain_id);
 
-	/* Errata - put in the old value */
-	dma_write(sys_cf, OCP_SYSCONFIG);
+	if (IS_DMA_ERRATA(DMA_ERRATA_i88))
+		p->dma_write(sys_cf, OCP_SYSCONFIG, 0);
 
 	return 0;
 }
@@ -1796,8 +1693,8 @@ int omap_get_dma_chain_index(int chain_i
 	/* Get the current channel */
 	lch = channels[dma_linked_lch[chain_id].q_head];
 
-	*ei = dma_read(CCEN(lch));
-	*fi = dma_read(CCFN(lch));
+	*ei = p->dma_read(CCEN, lch);
+	*fi = p->dma_read(CCFN, lch);
 
 	return 0;
 }
@@ -1834,7 +1731,7 @@ int omap_get_dma_chain_dst_pos(int chain
 	/* Get the current channel */
 	lch = channels[dma_linked_lch[chain_id].q_head];
 
-	return dma_read(CDAC(lch));
+	return p->dma_read(CDAC, lch);
 }
 EXPORT_SYMBOL(omap_get_dma_chain_dst_pos);
 
@@ -1868,7 +1765,7 @@ int omap_get_dma_chain_src_pos(int chain
 	/* Get the current channel */
 	lch = channels[dma_linked_lch[chain_id].q_head];
 
-	return dma_read(CSAC(lch));
+	return p->dma_read(CSAC, lch);
 }
 EXPORT_SYMBOL(omap_get_dma_chain_src_pos);
 #endif	/* ifndef CONFIG_ARCH_OMAP1 */
@@ -1885,7 +1782,7 @@ static int omap1_dma_handle_ch(int ch)
 		csr = dma_chan[ch].saved_csr;
 		dma_chan[ch].saved_csr = 0;
 	} else
-		csr = dma_read(CSR(ch));
+		csr = p->dma_read(CSR, ch);
 	if (enable_1510_mode && ch <= 2 && (csr >> 7) != 0) {
 		dma_chan[ch + 6].saved_csr = csr >> 7;
 		csr &= 0x7f;
@@ -1938,13 +1835,13 @@ static irqreturn_t omap1_dma_irq_handler
 
 static int omap2_dma_handle_ch(int ch)
 {
-	u32 status = dma_read(CSR(ch));
+	u32 status = p->dma_read(CSR, ch);
 
 	if (!status) {
 		if (printk_ratelimit())
 			printk(KERN_WARNING "Spurious DMA IRQ for lch %d\n",
 				ch);
-		dma_write(1 << ch, IRQSTATUS_L0);
+		p->dma_write(1 << ch, IRQSTATUS_L0, ch);
 		return 0;
 	}
 	if (unlikely(dma_chan[ch].dev_id == -1)) {
@@ -1960,17 +1857,12 @@ static int omap2_dma_handle_ch(int ch)
 	if (unlikely(status & OMAP2_DMA_TRANS_ERR_IRQ)) {
 		printk(KERN_INFO "DMA transaction error with device %d\n",
 		       dma_chan[ch].dev_id);
-		if (cpu_class_is_omap2()) {
-			/*
-			 * Errata: sDMA Channel is not disabled
-			 * after a transaction error. So we explicitely
-			 * disable the channel
-			 */
+		if (IS_DMA_ERRATA(DMA_ERRATA_i378)) {
 			u32 ccr;
 
-			ccr = dma_read(CCR(ch));
+			ccr = p->dma_read(CCR, ch);
 			ccr &= ~OMAP_DMA_CCR_EN;
-			dma_write(ccr, CCR(ch));
+			p->dma_write(ccr, CCR, ch);
 			dma_chan[ch].flags &= ~OMAP_DMA_ACTIVE;
 		}
 	}
@@ -1981,16 +1873,16 @@ static int omap2_dma_handle_ch(int ch)
 		printk(KERN_INFO "DMA misaligned error with device %d\n",
 		       dma_chan[ch].dev_id);
 
-	dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR(ch));
-	dma_write(1 << ch, IRQSTATUS_L0);
+	p->dma_write(status, CSR, ch);
+	p->dma_write(1 << ch, IRQSTATUS_L0, ch);
 	/* read back the register to flush the write */
-	dma_read(IRQSTATUS_L0);
+	p->dma_read(IRQSTATUS_L0, ch);
 
 	/* If the ch is not chained then chain_id will be -1 */
 	if (dma_chan[ch].chain_id != -1) {
 		int chain_id = dma_chan[ch].chain_id;
 		dma_chan[ch].state = DMA_CH_NOTSTARTED;
-		if (dma_read(CLNK_CTRL(ch)) & (1 << 15))
+		if (p->dma_read(CLNK_CTRL, ch) & (1 << 15))
 			dma_chan[dma_chan[ch].next_linked_ch].state =
 							DMA_CH_STARTED;
 		if (dma_linked_lch[chain_id].chain_mode ==
@@ -2000,11 +1892,10 @@ static int omap2_dma_handle_ch(int ch)
 		if (!OMAP_DMA_CHAIN_QEMPTY(chain_id))
 			OMAP_DMA_CHAIN_INCQHEAD(chain_id);
 
-		status = dma_read(CSR(ch));
+		status = p->dma_read(CSR, ch);
+		p->dma_write(status, CSR, ch);
 	}
 
-	dma_write(status, CSR(ch));
-
 	if (likely(dma_chan[ch].callback != NULL))
 		dma_chan[ch].callback(ch, status, dma_chan[ch].data);
 
@@ -2017,13 +1908,13 @@ static irqreturn_t omap2_dma_irq_handler
 	u32 val, enable_reg;
 	int i;
 
-	val = dma_read(IRQSTATUS_L0);
+	val = p->dma_read(IRQSTATUS_L0, 0);
 	if (val == 0) {
 		if (printk_ratelimit())
 			printk(KERN_WARNING "Spurious DMA IRQ\n");
 		return IRQ_HANDLED;
 	}
-	enable_reg = dma_read(IRQENABLE_L0);
+	enable_reg = p->dma_read(IRQENABLE_L0, 0);
 	val &= enable_reg; /* Dispatch only relevant interrupts */
 	for (i = 0; i < dma_lch_count && val != 0; i++) {
 		if (val & 1)
@@ -2049,119 +1940,66 @@ static struct irqaction omap24xx_dma_irq
 void omap_dma_global_context_save(void)
 {
 	omap_dma_global_context.dma_irqenable_l0 =
-		dma_read(IRQENABLE_L0);
+		p->dma_read(IRQENABLE_L0, 0);
 	omap_dma_global_context.dma_ocp_sysconfig =
-		dma_read(OCP_SYSCONFIG);
-	omap_dma_global_context.dma_gcr = dma_read(GCR);
+		p->dma_read(OCP_SYSCONFIG, 0);
+	omap_dma_global_context.dma_gcr = p->dma_read(GCR, 0);
 }
 
 void omap_dma_global_context_restore(void)
 {
 	int ch;
 
-	dma_write(omap_dma_global_context.dma_gcr, GCR);
-	dma_write(omap_dma_global_context.dma_ocp_sysconfig,
-		OCP_SYSCONFIG);
-	dma_write(omap_dma_global_context.dma_irqenable_l0,
-		IRQENABLE_L0);
+	p->dma_write(omap_dma_global_context.dma_gcr, GCR, 0);
+	p->dma_write(omap_dma_global_context.dma_ocp_sysconfig,
+		OCP_SYSCONFIG, 0);
+	p->dma_write(omap_dma_global_context.dma_irqenable_l0,
+		IRQENABLE_L0, 0);
 
-	/*
-	 * A bug in ROM code leaves IRQ status for channels 0 and 1 uncleared
-	 * after secure sram context save and restore. Hence we need to
-	 * manually clear those IRQs to avoid spurious interrupts. This
-	 * affects only secure devices.
-	 */
-	if (cpu_is_omap34xx() && (omap_type() != OMAP2_DEVICE_TYPE_GP))
-		dma_write(0x3 , IRQSTATUS_L0);
+	if (IS_DMA_ERRATA(DMA_ROMCODE_BUG))
+		p->dma_write(0x3 , IRQSTATUS_L0, 0);
 
 	for (ch = 0; ch < dma_chan_count; ch++)
 		if (dma_chan[ch].dev_id != -1)
 			omap_clear_dma(ch);
 }
 
-/*----------------------------------------------------------------------------*/
-
-static int __init omap_init_dma(void)
+static int __devinit omap_system_dma_probe(struct platform_device *pdev)
 {
-	unsigned long base;
-	int ch, r;
+	int ch, ret = 0;
+	int dma_irq;
+	char irq_name[4];
+	int irq_rel;
 
-	if (cpu_class_is_omap1()) {
-		base = OMAP1_DMA_BASE;
-		dma_lch_count = OMAP1_LOGICAL_DMA_CH_COUNT;
-	} else if (cpu_is_omap24xx()) {
-		base = OMAP24XX_DMA4_BASE;
-		dma_lch_count = OMAP_DMA4_LOGICAL_DMA_CH_COUNT;
-	} else if (cpu_is_omap34xx()) {
-		base = OMAP34XX_DMA4_BASE;
-		dma_lch_count = OMAP_DMA4_LOGICAL_DMA_CH_COUNT;
-	} else if (cpu_is_omap44xx()) {
-		base = OMAP44XX_DMA4_BASE;
-		dma_lch_count = OMAP_DMA4_LOGICAL_DMA_CH_COUNT;
-	} else {
-		pr_err("DMA init failed for unsupported omap\n");
-		return -ENODEV;
+	p = pdev->dev.platform_data;
+	if (!p) {
+		dev_err(&pdev->dev, "%s: System DMA initialized without"
+			"platform data\n", __func__);
+		return -EINVAL;
 	}
 
-	omap_dma_base = ioremap(base, SZ_4K);
-	BUG_ON(!omap_dma_base);
+	d			= p->dma_attr;
+	errata			= p->errata;
 
-	if (cpu_class_is_omap2() && omap_dma_reserve_channels
+	if ((d->dev_caps & RESERVE_CHANNEL) && omap_dma_reserve_channels
 			&& (omap_dma_reserve_channels <= dma_lch_count))
-		dma_lch_count = omap_dma_reserve_channels;
+		d->lch_count	= omap_dma_reserve_channels;
 
-	dma_chan = kzalloc(sizeof(struct omap_dma_lch) * dma_lch_count,
-				GFP_KERNEL);
-	if (!dma_chan) {
-		r = -ENOMEM;
-		goto out_unmap;
-	}
+	dma_lch_count		= d->lch_count;
+	dma_chan_count		= dma_lch_count;
+	dma_chan		= d->chan;
+	enable_1510_mode	= d->dev_caps & ENABLE_1510_MODE;
 
 	if (cpu_class_is_omap2()) {
 		dma_linked_lch = kzalloc(sizeof(struct dma_link_info) *
 						dma_lch_count, GFP_KERNEL);
 		if (!dma_linked_lch) {
-			r = -ENOMEM;
-			goto out_free;
+			ret = -ENOMEM;
+			goto exit_dma_lch_fail;
 		}
 	}
 
-	if (cpu_is_omap15xx()) {
-		printk(KERN_INFO "DMA support for OMAP15xx initialized\n");
-		dma_chan_count = 9;
-		enable_1510_mode = 1;
-	} else if (cpu_is_omap16xx() || cpu_is_omap7xx()) {
-		printk(KERN_INFO "OMAP DMA hardware version %d\n",
-		       dma_read(HW_ID));
-		printk(KERN_INFO "DMA capabilities: %08x:%08x:%04x:%04x:%04x\n",
-		       (dma_read(CAPS_0_U) << 16) |
-		       dma_read(CAPS_0_L),
-		       (dma_read(CAPS_1_U) << 16) |
-		       dma_read(CAPS_1_L),
-		       dma_read(CAPS_2), dma_read(CAPS_3),
-		       dma_read(CAPS_4));
-		if (!enable_1510_mode) {
-			u16 w;
-
-			/* Disable OMAP 3.0/3.1 compatibility mode. */
-			w = dma_read(GSCR);
-			w |= 1 << 3;
-			dma_write(w, GSCR);
-			dma_chan_count = 16;
-		} else
-			dma_chan_count = 9;
-	} else if (cpu_class_is_omap2()) {
-		u8 revision = dma_read(REVISION) & 0xff;
-		printk(KERN_INFO "OMAP DMA hardware revision %d.%d\n",
-		       revision >> 4, revision & 0xf);
-		dma_chan_count = dma_lch_count;
-	} else {
-		dma_chan_count = 0;
-		return 0;
-	}
-
 	spin_lock_init(&dma_chan_lock);
-
 	for (ch = 0; ch < dma_chan_count; ch++) {
 		omap_clear_dma(ch);
 		if (cpu_class_is_omap2())
@@ -2178,20 +2016,23 @@ static int __init omap_init_dma(void)
 			 * request_irq() doesn't like dev_id (ie. ch) being
 			 * zero, so we have to kludge around this.
 			 */
-			r = request_irq(omap1_dma_irq[ch],
-					omap1_dma_irq_handler, 0, "DMA",
-					(void *) (ch + 1));
-			if (r != 0) {
-				int i;
+			sprintf(&irq_name[0], "%d", ch);
+			dma_irq = platform_get_irq_byname(pdev, irq_name);
 
-				printk(KERN_ERR "unable to request IRQ %d "
-				       "for DMA (error %d)\n",
-				       omap1_dma_irq[ch], r);
-				for (i = 0; i < ch; i++)
-					free_irq(omap1_dma_irq[i],
-						 (void *) (i + 1));
-				goto out_free;
+			if (dma_irq < 0) {
+				ret = dma_irq;
+				goto exit_dma_irq_fail;
 			}
+
+			/* INT_DMA_LCD is handled in lcd_dma.c */
+			if (dma_irq == INT_DMA_LCD)
+				continue;
+
+			ret = request_irq(dma_irq,
+					omap1_dma_irq_handler, 0, "DMA",
+					(void *) (ch + 1));
+			if (ret != 0)
+				goto exit_dma_irq_fail;
 		}
 	}
 
@@ -2200,46 +2041,91 @@ static int __init omap_init_dma(void)
 				DMA_DEFAULT_FIFO_DEPTH, 0);
 
 	if (cpu_class_is_omap2()) {
-		int irq;
-		if (cpu_is_omap44xx())
-			irq = OMAP44XX_IRQ_SDMA_0;
-		else
-			irq = INT_24XX_SDMA_IRQ0;
-		setup_irq(irq, &omap24xx_dma_irq);
-	}
-
-	if (cpu_is_omap34xx() || cpu_is_omap44xx()) {
-		/* Enable smartidle idlemodes and autoidle */
-		u32 v = dma_read(OCP_SYSCONFIG);
-		v &= ~(DMA_SYSCONFIG_MIDLEMODE_MASK |
-				DMA_SYSCONFIG_SIDLEMODE_MASK |
-				DMA_SYSCONFIG_AUTOIDLE);
-		v |= (DMA_SYSCONFIG_MIDLEMODE(DMA_IDLEMODE_SMARTIDLE) |
-			DMA_SYSCONFIG_SIDLEMODE(DMA_IDLEMODE_SMARTIDLE) |
-			DMA_SYSCONFIG_AUTOIDLE);
-		dma_write(v , OCP_SYSCONFIG);
-		/* reserve dma channels 0 and 1 in high security devices */
-		if (cpu_is_omap34xx() &&
-			(omap_type() != OMAP2_DEVICE_TYPE_GP)) {
-			printk(KERN_INFO "Reserving DMA channels 0 and 1 for "
-					"HS ROM code\n");
-			dma_chan[0].dev_id = 0;
-			dma_chan[1].dev_id = 1;
+		strcpy(irq_name, "0");
+		dma_irq = platform_get_irq_byname(pdev, irq_name);
+		if (dma_irq < 0) {
+			dev_err(&pdev->dev, "failed: request IRQ %d", dma_irq);
+			goto exit_dma_lch_fail;
+		}
+		ret = setup_irq(dma_irq, &omap24xx_dma_irq);
+		if (ret) {
+			dev_err(&pdev->dev, "set_up failed for IRQ %d"
+				"for DMA (error %d)\n", dma_irq, ret);
+			goto exit_dma_lch_fail;
 		}
 	}
 
+	/* reserve dma channels 0 and 1 in high security devices */
+	if (cpu_is_omap34xx() &&
+		(omap_type() != OMAP2_DEVICE_TYPE_GP)) {
+		printk(KERN_INFO "Reserving DMA channels 0 and 1 for "
+				"HS ROM code\n");
+		dma_chan[0].dev_id = 0;
+		dma_chan[1].dev_id = 1;
+	}
+	p->show_dma_caps();
 	return 0;
 
-out_free:
+exit_dma_irq_fail:
+	dev_err(&pdev->dev, "unable to request IRQ %d"
+			"for DMA (error %d)\n", dma_irq, ret);
+	for (irq_rel = 0; irq_rel < ch;	irq_rel++) {
+		dma_irq = platform_get_irq(pdev, irq_rel);
+		free_irq(dma_irq, (void *)(irq_rel + 1));
+	}
+
+exit_dma_lch_fail:
+	kfree(p);
+	kfree(d);
 	kfree(dma_chan);
+	return ret;
+}
 
-out_unmap:
-	iounmap(omap_dma_base);
+static int __devexit omap_system_dma_remove(struct platform_device *pdev)
+{
+	int dma_irq;
 
-	return r;
+	if (cpu_class_is_omap2()) {
+		char irq_name[4];
+		strcpy(irq_name, "0");
+		dma_irq = platform_get_irq_byname(pdev, irq_name);
+		remove_irq(dma_irq, &omap24xx_dma_irq);
+	} else {
+		int irq_rel = 0;
+		for ( ; irq_rel < dma_chan_count; irq_rel++) {
+			dma_irq = platform_get_irq(pdev, irq_rel);
+			free_irq(dma_irq, (void *)(irq_rel + 1));
+		}
+	}
+	kfree(p);
+	kfree(d);
+	kfree(dma_chan);
+	return 0;
 }
 
-arch_initcall(omap_init_dma);
+static struct platform_driver omap_system_dma_driver = {
+	.probe		= omap_system_dma_probe,
+	.remove		= omap_system_dma_remove,
+	.driver		= {
+		.name	= "omap_dma_system"
+	},
+};
+
+static int __init omap_system_dma_init(void)
+{
+	return platform_driver_register(&omap_system_dma_driver);
+}
+arch_initcall(omap_system_dma_init);
+
+static void __exit omap_system_dma_exit(void)
+{
+	platform_driver_unregister(&omap_system_dma_driver);
+}
+
+MODULE_DESCRIPTION("OMAP SYSTEM DMA DRIVER");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" DRIVER_NAME);
+MODULE_AUTHOR("Texas Instruments Inc");
 
 /*
  * Reserve the omap SDMA channels using cmdline bootarg
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-omap/gpio.c linux-libre-2.6.38-gnu1/arch/arm/plat-omap/gpio.c
--- linux-libre-2.6.37-gnu1/arch/arm/plat-omap/gpio.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-omap/gpio.c	2011-03-14 21:20:32.000000000 -0400
@@ -21,18 +21,18 @@
 #include <linux/err.h>
 #include <linux/clk.h>
 #include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/pm_runtime.h>
 
 #include <mach/hardware.h>
 #include <asm/irq.h>
 #include <mach/irqs.h>
 #include <mach/gpio.h>
 #include <asm/mach/irq.h>
-#include <plat/powerdomain.h>
 
 /*
  * OMAP1510 GPIO registers
  */
-#define OMAP1510_GPIO_BASE		0xfffce000
 #define OMAP1510_GPIO_DATA_INPUT	0x00
 #define OMAP1510_GPIO_DATA_OUTPUT	0x04
 #define OMAP1510_GPIO_DIR_CONTROL	0x08
@@ -46,10 +46,6 @@
 /*
  * OMAP1610 specific GPIO registers
  */
-#define OMAP1610_GPIO1_BASE		0xfffbe400
-#define OMAP1610_GPIO2_BASE		0xfffbec00
-#define OMAP1610_GPIO3_BASE		0xfffbb400
-#define OMAP1610_GPIO4_BASE		0xfffbbc00
 #define OMAP1610_GPIO_REVISION		0x0000
 #define OMAP1610_GPIO_SYSCONFIG		0x0010
 #define OMAP1610_GPIO_SYSSTATUS		0x0014
@@ -71,12 +67,6 @@
 /*
  * OMAP7XX specific GPIO registers
  */
-#define OMAP7XX_GPIO1_BASE		0xfffbc000
-#define OMAP7XX_GPIO2_BASE		0xfffbc800
-#define OMAP7XX_GPIO3_BASE		0xfffbd000
-#define OMAP7XX_GPIO4_BASE		0xfffbd800
-#define OMAP7XX_GPIO5_BASE		0xfffbe000
-#define OMAP7XX_GPIO6_BASE		0xfffbe800
 #define OMAP7XX_GPIO_DATA_INPUT		0x00
 #define OMAP7XX_GPIO_DATA_OUTPUT	0x04
 #define OMAP7XX_GPIO_DIR_CONTROL	0x08
@@ -84,25 +74,10 @@
 #define OMAP7XX_GPIO_INT_MASK		0x10
 #define OMAP7XX_GPIO_INT_STATUS		0x14
 
-#define OMAP1_MPUIO_VBASE		OMAP1_MPUIO_BASE
-
 /*
- * omap24xx specific GPIO registers
+ * omap2+ specific GPIO registers
  */
-#define OMAP242X_GPIO1_BASE		0x48018000
-#define OMAP242X_GPIO2_BASE		0x4801a000
-#define OMAP242X_GPIO3_BASE		0x4801c000
-#define OMAP242X_GPIO4_BASE		0x4801e000
-
-#define OMAP243X_GPIO1_BASE		0x4900C000
-#define OMAP243X_GPIO2_BASE		0x4900E000
-#define OMAP243X_GPIO3_BASE		0x49010000
-#define OMAP243X_GPIO4_BASE		0x49012000
-#define OMAP243X_GPIO5_BASE		0x480B6000
-
 #define OMAP24XX_GPIO_REVISION		0x0000
-#define OMAP24XX_GPIO_SYSCONFIG		0x0010
-#define OMAP24XX_GPIO_SYSSTATUS		0x0014
 #define OMAP24XX_GPIO_IRQSTATUS1	0x0018
 #define OMAP24XX_GPIO_IRQSTATUS2	0x0028
 #define OMAP24XX_GPIO_IRQENABLE2	0x002c
@@ -126,7 +101,6 @@
 #define OMAP24XX_GPIO_SETDATAOUT	0x0094
 
 #define OMAP4_GPIO_REVISION		0x0000
-#define OMAP4_GPIO_SYSCONFIG		0x0010
 #define OMAP4_GPIO_EOI			0x0020
 #define OMAP4_GPIO_IRQSTATUSRAW0	0x0024
 #define OMAP4_GPIO_IRQSTATUSRAW1	0x0028
@@ -138,7 +112,6 @@
 #define OMAP4_GPIO_IRQSTATUSCLR1	0x0040
 #define OMAP4_GPIO_IRQWAKEN0		0x0044
 #define OMAP4_GPIO_IRQWAKEN1		0x0048
-#define OMAP4_GPIO_SYSSTATUS		0x0114
 #define OMAP4_GPIO_IRQENABLE1		0x011c
 #define OMAP4_GPIO_WAKE_EN		0x0120
 #define OMAP4_GPIO_IRQSTATUS2		0x0128
@@ -159,26 +132,6 @@
 #define OMAP4_GPIO_SETWKUENA		0x0184
 #define OMAP4_GPIO_CLEARDATAOUT		0x0190
 #define OMAP4_GPIO_SETDATAOUT		0x0194
-/*
- * omap34xx specific GPIO registers
- */
-
-#define OMAP34XX_GPIO1_BASE		0x48310000
-#define OMAP34XX_GPIO2_BASE		0x49050000
-#define OMAP34XX_GPIO3_BASE		0x49052000
-#define OMAP34XX_GPIO4_BASE		0x49054000
-#define OMAP34XX_GPIO5_BASE		0x49056000
-#define OMAP34XX_GPIO6_BASE		0x49058000
-
-/*
- * OMAP44XX  specific GPIO registers
- */
-#define OMAP44XX_GPIO1_BASE             0x4a310000
-#define OMAP44XX_GPIO2_BASE             0x48055000
-#define OMAP44XX_GPIO3_BASE             0x48057000
-#define OMAP44XX_GPIO4_BASE             0x48059000
-#define OMAP44XX_GPIO5_BASE             0x4805B000
-#define OMAP44XX_GPIO6_BASE             0x4805D000
 
 struct gpio_bank {
 	unsigned long pbase;
@@ -190,14 +143,12 @@ struct gpio_bank {
 	u32 suspend_wakeup;
 	u32 saved_wakeup;
 #endif
-#ifdef CONFIG_ARCH_OMAP2PLUS
 	u32 non_wakeup_gpios;
 	u32 enabled_non_wakeup_gpios;
 
 	u32 saved_datain;
 	u32 saved_fallingdetect;
 	u32 saved_risingdetect;
-#endif
 	u32 level_mask;
 	u32 toggle_mask;
 	spinlock_t lock;
@@ -205,104 +156,13 @@ struct gpio_bank {
 	struct clk *dbck;
 	u32 mod_usage;
 	u32 dbck_enable_mask;
+	struct device *dev;
+	bool dbck_flag;
+	int stride;
 };
 
-#define METHOD_MPUIO		0
-#define METHOD_GPIO_1510	1
-#define METHOD_GPIO_1610	2
-#define METHOD_GPIO_7XX		3
-#define METHOD_GPIO_24XX	5
-#define METHOD_GPIO_44XX	6
-
-#ifdef CONFIG_ARCH_OMAP16XX
-static struct gpio_bank gpio_bank_1610[5] = {
-	{ OMAP1_MPUIO_VBASE, NULL, INT_MPUIO, IH_MPUIO_BASE,
-		METHOD_MPUIO },
-	{ OMAP1610_GPIO1_BASE, NULL, INT_GPIO_BANK1, IH_GPIO_BASE,
-		METHOD_GPIO_1610 },
-	{ OMAP1610_GPIO2_BASE, NULL, INT_1610_GPIO_BANK2, IH_GPIO_BASE + 16,
-		METHOD_GPIO_1610 },
-	{ OMAP1610_GPIO3_BASE, NULL, INT_1610_GPIO_BANK3, IH_GPIO_BASE + 32,
-		METHOD_GPIO_1610 },
-	{ OMAP1610_GPIO4_BASE, NULL, INT_1610_GPIO_BANK4, IH_GPIO_BASE + 48,
-		METHOD_GPIO_1610 },
-};
-#endif
-
-#ifdef CONFIG_ARCH_OMAP15XX
-static struct gpio_bank gpio_bank_1510[2] = {
-	{ OMAP1_MPUIO_VBASE, NULL, INT_MPUIO, IH_MPUIO_BASE,
-		METHOD_MPUIO },
-	{ OMAP1510_GPIO_BASE, NULL, INT_GPIO_BANK1, IH_GPIO_BASE,
-		METHOD_GPIO_1510 }
-};
-#endif
-
-#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
-static struct gpio_bank gpio_bank_7xx[7] = {
-	{ OMAP1_MPUIO_VBASE, NULL, INT_7XX_MPUIO, IH_MPUIO_BASE,
-		METHOD_MPUIO },
-	{ OMAP7XX_GPIO1_BASE, NULL, INT_7XX_GPIO_BANK1, IH_GPIO_BASE,
-		METHOD_GPIO_7XX },
-	{ OMAP7XX_GPIO2_BASE, NULL, INT_7XX_GPIO_BANK2, IH_GPIO_BASE + 32,
-		METHOD_GPIO_7XX },
-	{ OMAP7XX_GPIO3_BASE, NULL, INT_7XX_GPIO_BANK3, IH_GPIO_BASE + 64,
-		METHOD_GPIO_7XX },
-	{ OMAP7XX_GPIO4_BASE, NULL, INT_7XX_GPIO_BANK4,  IH_GPIO_BASE + 96,
-		METHOD_GPIO_7XX },
-	{ OMAP7XX_GPIO5_BASE, NULL, INT_7XX_GPIO_BANK5,  IH_GPIO_BASE + 128,
-		METHOD_GPIO_7XX },
-	{ OMAP7XX_GPIO6_BASE, NULL, INT_7XX_GPIO_BANK6,  IH_GPIO_BASE + 160,
-		METHOD_GPIO_7XX },
-};
-#endif
-
-#ifdef CONFIG_ARCH_OMAP2
-
-static struct gpio_bank gpio_bank_242x[4] = {
-	{ OMAP242X_GPIO1_BASE, NULL, INT_24XX_GPIO_BANK1, IH_GPIO_BASE,
-		METHOD_GPIO_24XX },
-	{ OMAP242X_GPIO2_BASE, NULL, INT_24XX_GPIO_BANK2, IH_GPIO_BASE + 32,
-		METHOD_GPIO_24XX },
-	{ OMAP242X_GPIO3_BASE, NULL, INT_24XX_GPIO_BANK3, IH_GPIO_BASE + 64,
-		METHOD_GPIO_24XX },
-	{ OMAP242X_GPIO4_BASE, NULL, INT_24XX_GPIO_BANK4, IH_GPIO_BASE + 96,
-		METHOD_GPIO_24XX },
-};
-
-static struct gpio_bank gpio_bank_243x[5] = {
-	{ OMAP243X_GPIO1_BASE, NULL, INT_24XX_GPIO_BANK1, IH_GPIO_BASE,
-		METHOD_GPIO_24XX },
-	{ OMAP243X_GPIO2_BASE, NULL, INT_24XX_GPIO_BANK2, IH_GPIO_BASE + 32,
-		METHOD_GPIO_24XX },
-	{ OMAP243X_GPIO3_BASE, NULL, INT_24XX_GPIO_BANK3, IH_GPIO_BASE + 64,
-		METHOD_GPIO_24XX },
-	{ OMAP243X_GPIO4_BASE, NULL, INT_24XX_GPIO_BANK4, IH_GPIO_BASE + 96,
-		METHOD_GPIO_24XX },
-	{ OMAP243X_GPIO5_BASE, NULL, INT_24XX_GPIO_BANK5, IH_GPIO_BASE + 128,
-		METHOD_GPIO_24XX },
-};
-
-#endif
-
 #ifdef CONFIG_ARCH_OMAP3
-static struct gpio_bank gpio_bank_34xx[6] = {
-	{ OMAP34XX_GPIO1_BASE, NULL, INT_34XX_GPIO_BANK1, IH_GPIO_BASE,
-		METHOD_GPIO_24XX },
-	{ OMAP34XX_GPIO2_BASE, NULL, INT_34XX_GPIO_BANK2, IH_GPIO_BASE + 32,
-		METHOD_GPIO_24XX },
-	{ OMAP34XX_GPIO3_BASE, NULL, INT_34XX_GPIO_BANK3, IH_GPIO_BASE + 64,
-		METHOD_GPIO_24XX },
-	{ OMAP34XX_GPIO4_BASE, NULL, INT_34XX_GPIO_BANK4, IH_GPIO_BASE + 96,
-		METHOD_GPIO_24XX },
-	{ OMAP34XX_GPIO5_BASE, NULL, INT_34XX_GPIO_BANK5, IH_GPIO_BASE + 128,
-		METHOD_GPIO_24XX },
-	{ OMAP34XX_GPIO6_BASE, NULL, INT_34XX_GPIO_BANK6, IH_GPIO_BASE + 160,
-		METHOD_GPIO_24XX },
-};
-
 struct omap3_gpio_regs {
-	u32 sysconfig;
 	u32 irqenable1;
 	u32 irqenable2;
 	u32 wake_en;
@@ -318,26 +178,16 @@ struct omap3_gpio_regs {
 static struct omap3_gpio_regs gpio_context[OMAP34XX_NR_GPIOS];
 #endif
 
-#ifdef CONFIG_ARCH_OMAP4
-static struct gpio_bank gpio_bank_44xx[6] = {
-	{ OMAP44XX_GPIO1_BASE, NULL, OMAP44XX_IRQ_GPIO1, IH_GPIO_BASE,
-		METHOD_GPIO_44XX },
-	{ OMAP44XX_GPIO2_BASE, NULL, OMAP44XX_IRQ_GPIO2, IH_GPIO_BASE + 32,
-		METHOD_GPIO_44XX },
-	{ OMAP44XX_GPIO3_BASE, NULL, OMAP44XX_IRQ_GPIO3, IH_GPIO_BASE + 64,
-		METHOD_GPIO_44XX },
-	{ OMAP44XX_GPIO4_BASE, NULL, OMAP44XX_IRQ_GPIO4, IH_GPIO_BASE + 96,
-		METHOD_GPIO_44XX },
-	{ OMAP44XX_GPIO5_BASE, NULL, OMAP44XX_IRQ_GPIO5, IH_GPIO_BASE + 128,
-		METHOD_GPIO_44XX },
-	{ OMAP44XX_GPIO6_BASE, NULL, OMAP44XX_IRQ_GPIO6, IH_GPIO_BASE + 160,
-		METHOD_GPIO_44XX },
-};
+/*
+ * TODO: Cleanup gpio_bank usage as it is having information
+ * related to all instances of the device
+ */
+static struct gpio_bank *gpio_bank;
 
-#endif
+static int bank_width;
 
-static struct gpio_bank *gpio_bank;
-static int gpio_bank_count;
+/* TODO: Analyze removing gpio_bank_count usage from driver code */
+int gpio_bank_count;
 
 static inline struct gpio_bank *get_gpio_bank(int gpio)
 {
@@ -417,7 +267,7 @@ static void _set_gpio_direction(struct g
 	switch (bank->method) {
 #ifdef CONFIG_ARCH_OMAP1
 	case METHOD_MPUIO:
-		reg += OMAP_MPUIO_IO_CNTL;
+		reg += OMAP_MPUIO_IO_CNTL / bank->stride;
 		break;
 #endif
 #ifdef CONFIG_ARCH_OMAP15XX
@@ -465,7 +315,7 @@ static void _set_gpio_dataout(struct gpi
 	switch (bank->method) {
 #ifdef CONFIG_ARCH_OMAP1
 	case METHOD_MPUIO:
-		reg += OMAP_MPUIO_OUTPUT;
+		reg += OMAP_MPUIO_OUTPUT / bank->stride;
 		l = __raw_readl(reg);
 		if (enable)
 			l |= 1 << gpio;
@@ -537,7 +387,7 @@ static int _get_gpio_datain(struct gpio_
 	switch (bank->method) {
 #ifdef CONFIG_ARCH_OMAP1
 	case METHOD_MPUIO:
-		reg += OMAP_MPUIO_INPUT_LATCH;
+		reg += OMAP_MPUIO_INPUT_LATCH / bank->stride;
 		break;
 #endif
 #ifdef CONFIG_ARCH_OMAP15XX
@@ -583,7 +433,7 @@ static int _get_gpio_dataout(struct gpio
 	switch (bank->method) {
 #ifdef CONFIG_ARCH_OMAP1
 	case METHOD_MPUIO:
-		reg += OMAP_MPUIO_OUTPUT;
+		reg += OMAP_MPUIO_OUTPUT / bank->stride;
 		break;
 #endif
 #ifdef CONFIG_ARCH_OMAP15XX
@@ -642,6 +492,9 @@ static void _set_gpio_debounce(struct gp
 	u32			val;
 	u32			l;
 
+	if (!bank->dbck_flag)
+		return;
+
 	if (debounce < 32)
 		debounce = 0x01;
 	else if (debounce > 7936)
@@ -651,7 +504,7 @@ static void _set_gpio_debounce(struct gp
 
 	l = 1 << get_gpio_index(gpio);
 
-	if (cpu_is_omap44xx())
+	if (bank->method == METHOD_GPIO_44XX)
 		reg += OMAP4_GPIO_DEBOUNCINGTIME;
 	else
 		reg += OMAP24XX_GPIO_DEBOUNCE_VAL;
@@ -659,7 +512,7 @@ static void _set_gpio_debounce(struct gp
 	__raw_writel(debounce, reg);
 
 	reg = bank->base;
-	if (cpu_is_omap44xx())
+	if (bank->method == METHOD_GPIO_44XX)
 		reg += OMAP4_GPIO_DEBOUNCENABLE;
 	else
 		reg += OMAP24XX_GPIO_DEBOUNCE_EN;
@@ -668,12 +521,10 @@ static void _set_gpio_debounce(struct gp
 
 	if (debounce) {
 		val |= l;
-		if (cpu_is_omap34xx() || cpu_is_omap44xx())
-			clk_enable(bank->dbck);
+		clk_enable(bank->dbck);
 	} else {
 		val &= ~l;
-		if (cpu_is_omap34xx() || cpu_is_omap44xx())
-			clk_disable(bank->dbck);
+		clk_disable(bank->dbck);
 	}
 	bank->dbck_enable_mask = val;
 
@@ -769,7 +620,7 @@ static void _toggle_gpio_edge_triggering
 
 	switch (bank->method) {
 	case METHOD_MPUIO:
-		reg += OMAP_MPUIO_GPIO_INT_EDGE;
+		reg += OMAP_MPUIO_GPIO_INT_EDGE / bank->stride;
 		break;
 #ifdef CONFIG_ARCH_OMAP15XX
 	case METHOD_GPIO_1510:
@@ -803,7 +654,7 @@ static int _set_gpio_triggering(struct g
 	switch (bank->method) {
 #ifdef CONFIG_ARCH_OMAP1
 	case METHOD_MPUIO:
-		reg += OMAP_MPUIO_GPIO_INT_EDGE;
+		reg += OMAP_MPUIO_GPIO_INT_EDGE / bank->stride;
 		l = __raw_readl(reg);
 		if ((trigger & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH)
 			bank->toggle_mask |= 1 << gpio;
@@ -867,7 +718,7 @@ static int _set_gpio_triggering(struct g
 	case METHOD_GPIO_24XX:
 	case METHOD_GPIO_44XX:
 		set_24xx_gpio_triggering(bank, gpio, trigger);
-		break;
+		return 0;
 #endif
 	default:
 		goto bad;
@@ -878,17 +729,17 @@ bad:
 	return -EINVAL;
 }
 
-static int gpio_irq_type(unsigned irq, unsigned type)
+static int gpio_irq_type(struct irq_data *d, unsigned type)
 {
 	struct gpio_bank *bank;
 	unsigned gpio;
 	int retval;
 	unsigned long flags;
 
-	if (!cpu_class_is_omap2() && irq > IH_MPUIO_BASE)
-		gpio = OMAP_MPUIO(irq - IH_MPUIO_BASE);
+	if (!cpu_class_is_omap2() && d->irq > IH_MPUIO_BASE)
+		gpio = OMAP_MPUIO(d->irq - IH_MPUIO_BASE);
 	else
-		gpio = irq - IH_GPIO_BASE;
+		gpio = d->irq - IH_GPIO_BASE;
 
 	if (check_gpio(gpio) < 0)
 		return -EINVAL;
@@ -901,19 +752,21 @@ static int gpio_irq_type(unsigned irq, u
 			&& (type & (IRQ_TYPE_LEVEL_LOW|IRQ_TYPE_LEVEL_HIGH)))
 		return -EINVAL;
 
-	bank = get_irq_chip_data(irq);
+	bank = irq_data_get_irq_chip_data(d);
 	spin_lock_irqsave(&bank->lock, flags);
 	retval = _set_gpio_triggering(bank, get_gpio_index(gpio), type);
 	if (retval == 0) {
-		irq_desc[irq].status &= ~IRQ_TYPE_SENSE_MASK;
-		irq_desc[irq].status |= type;
+		struct irq_desc *desc = irq_to_desc(d->irq);
+
+		desc->status &= ~IRQ_TYPE_SENSE_MASK;
+		desc->status |= type;
 	}
 	spin_unlock_irqrestore(&bank->lock, flags);
 
 	if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
-		__set_irq_handler_unlocked(irq, handle_level_irq);
+		__set_irq_handler_unlocked(d->irq, handle_level_irq);
 	else if (type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
-		__set_irq_handler_unlocked(irq, handle_edge_irq);
+		__set_irq_handler_unlocked(d->irq, handle_edge_irq);
 
 	return retval;
 }
@@ -989,7 +842,7 @@ static u32 _get_gpio_irqbank_mask(struct
 	switch (bank->method) {
 #ifdef CONFIG_ARCH_OMAP1
 	case METHOD_MPUIO:
-		reg += OMAP_MPUIO_GPIO_MASKIT;
+		reg += OMAP_MPUIO_GPIO_MASKIT / bank->stride;
 		mask = 0xffff;
 		inv = 1;
 		break;
@@ -1046,7 +899,7 @@ static void _enable_gpio_irqbank(struct
 	switch (bank->method) {
 #ifdef CONFIG_ARCH_OMAP1
 	case METHOD_MPUIO:
-		reg += OMAP_MPUIO_GPIO_MASKIT;
+		reg += OMAP_MPUIO_GPIO_MASKIT / bank->stride;
 		l = __raw_readl(reg);
 		if (enable)
 			l &= ~(gpio_mask);
@@ -1170,15 +1023,15 @@ static void _reset_gpio(struct gpio_bank
 }
 
 /* Use disable_irq_wake() and enable_irq_wake() functions from drivers */
-static int gpio_wake_enable(unsigned int irq, unsigned int enable)
+static int gpio_wake_enable(struct irq_data *d, unsigned int enable)
 {
-	unsigned int gpio = irq - IH_GPIO_BASE;
+	unsigned int gpio = d->irq - IH_GPIO_BASE;
 	struct gpio_bank *bank;
 	int retval;
 
 	if (check_gpio(gpio) < 0)
 		return -ENODEV;
-	bank = get_irq_chip_data(irq);
+	bank = irq_data_get_irq_chip_data(d);
 	retval = _set_gpio_wakeup(bank, get_gpio_index(gpio), enable);
 
 	return retval;
@@ -1291,12 +1144,13 @@ static void gpio_irq_handler(unsigned in
 	u32 retrigger = 0;
 	int unmasked = 0;
 
-	desc->chip->ack(irq);
+	desc->irq_data.chip->irq_ack(&desc->irq_data);
 
 	bank = get_irq_data(irq);
 #ifdef CONFIG_ARCH_OMAP1
 	if (bank->method == METHOD_MPUIO)
-		isr_reg = bank->base + OMAP_MPUIO_GPIO_INT;
+		isr_reg = bank->base +
+				OMAP_MPUIO_GPIO_INT / bank->stride;
 #endif
 #ifdef CONFIG_ARCH_OMAP15XX
 	if (bank->method == METHOD_GPIO_1510)
@@ -1318,6 +1172,10 @@ static void gpio_irq_handler(unsigned in
 	if (bank->method == METHOD_GPIO_44XX)
 		isr_reg = bank->base + OMAP4_GPIO_IRQSTATUS0;
 #endif
+
+	if (WARN_ON(!isr_reg))
+		goto exit;
+
 	while(1) {
 		u32 isr_saved, level_mask = 0;
 		u32 enabled;
@@ -1343,7 +1201,7 @@ static void gpio_irq_handler(unsigned in
 		configured, we could unmask GPIO bank interrupt immediately */
 		if (!level_mask && !unmasked) {
 			unmasked = 1;
-			desc->chip->unmask(irq);
+			desc->irq_data.chip->irq_unmask(&desc->irq_data);
 		}
 
 		isr |= retrigger;
@@ -1377,42 +1235,42 @@ static void gpio_irq_handler(unsigned in
 	configured, we must unmask the bank interrupt only after
 	handler(s) are executed in order to avoid spurious bank
 	interrupt */
+exit:
 	if (!unmasked)
-		desc->chip->unmask(irq);
-
+		desc->irq_data.chip->irq_unmask(&desc->irq_data);
 }
 
-static void gpio_irq_shutdown(unsigned int irq)
+static void gpio_irq_shutdown(struct irq_data *d)
 {
-	unsigned int gpio = irq - IH_GPIO_BASE;
-	struct gpio_bank *bank = get_irq_chip_data(irq);
+	unsigned int gpio = d->irq - IH_GPIO_BASE;
+	struct gpio_bank *bank = irq_data_get_irq_chip_data(d);
 
 	_reset_gpio(bank, gpio);
 }
 
-static void gpio_ack_irq(unsigned int irq)
+static void gpio_ack_irq(struct irq_data *d)
 {
-	unsigned int gpio = irq - IH_GPIO_BASE;
-	struct gpio_bank *bank = get_irq_chip_data(irq);
+	unsigned int gpio = d->irq - IH_GPIO_BASE;
+	struct gpio_bank *bank = irq_data_get_irq_chip_data(d);
 
 	_clear_gpio_irqstatus(bank, gpio);
 }
 
-static void gpio_mask_irq(unsigned int irq)
+static void gpio_mask_irq(struct irq_data *d)
 {
-	unsigned int gpio = irq - IH_GPIO_BASE;
-	struct gpio_bank *bank = get_irq_chip_data(irq);
+	unsigned int gpio = d->irq - IH_GPIO_BASE;
+	struct gpio_bank *bank = irq_data_get_irq_chip_data(d);
 
 	_set_gpio_irqenable(bank, gpio, 0);
 	_set_gpio_triggering(bank, get_gpio_index(gpio), IRQ_TYPE_NONE);
 }
 
-static void gpio_unmask_irq(unsigned int irq)
+static void gpio_unmask_irq(struct irq_data *d)
 {
-	unsigned int gpio = irq - IH_GPIO_BASE;
-	struct gpio_bank *bank = get_irq_chip_data(irq);
+	unsigned int gpio = d->irq - IH_GPIO_BASE;
+	struct gpio_bank *bank = irq_data_get_irq_chip_data(d);
 	unsigned int irq_mask = 1 << get_gpio_index(gpio);
-	struct irq_desc *desc = irq_to_desc(irq);
+	struct irq_desc *desc = irq_to_desc(d->irq);
 	u32 trigger = desc->status & IRQ_TYPE_SENSE_MASK;
 
 	if (trigger)
@@ -1430,12 +1288,12 @@ static void gpio_unmask_irq(unsigned int
 
 static struct irq_chip gpio_irq_chip = {
 	.name		= "GPIO",
-	.shutdown	= gpio_irq_shutdown,
-	.ack		= gpio_ack_irq,
-	.mask		= gpio_mask_irq,
-	.unmask		= gpio_unmask_irq,
-	.set_type	= gpio_irq_type,
-	.set_wake	= gpio_wake_enable,
+	.irq_shutdown	= gpio_irq_shutdown,
+	.irq_ack	= gpio_ack_irq,
+	.irq_mask	= gpio_mask_irq,
+	.irq_unmask	= gpio_unmask_irq,
+	.irq_set_type	= gpio_irq_type,
+	.irq_set_wake	= gpio_wake_enable,
 };
 
 /*---------------------------------------------------------------------*/
@@ -1444,36 +1302,36 @@ static struct irq_chip gpio_irq_chip = {
 
 /* MPUIO uses the always-on 32k clock */
 
-static void mpuio_ack_irq(unsigned int irq)
+static void mpuio_ack_irq(struct irq_data *d)
 {
 	/* The ISR is reset automatically, so do nothing here. */
 }
 
-static void mpuio_mask_irq(unsigned int irq)
+static void mpuio_mask_irq(struct irq_data *d)
 {
-	unsigned int gpio = OMAP_MPUIO(irq - IH_MPUIO_BASE);
-	struct gpio_bank *bank = get_irq_chip_data(irq);
+	unsigned int gpio = OMAP_MPUIO(d->irq - IH_MPUIO_BASE);
+	struct gpio_bank *bank = irq_data_get_irq_chip_data(d);
 
 	_set_gpio_irqenable(bank, gpio, 0);
 }
 
-static void mpuio_unmask_irq(unsigned int irq)
+static void mpuio_unmask_irq(struct irq_data *d)
 {
-	unsigned int gpio = OMAP_MPUIO(irq - IH_MPUIO_BASE);
-	struct gpio_bank *bank = get_irq_chip_data(irq);
+	unsigned int gpio = OMAP_MPUIO(d->irq - IH_MPUIO_BASE);
+	struct gpio_bank *bank = irq_data_get_irq_chip_data(d);
 
 	_set_gpio_irqenable(bank, gpio, 1);
 }
 
 static struct irq_chip mpuio_irq_chip = {
 	.name		= "MPUIO",
-	.ack		= mpuio_ack_irq,
-	.mask		= mpuio_mask_irq,
-	.unmask		= mpuio_unmask_irq,
-	.set_type	= gpio_irq_type,
+	.irq_ack	= mpuio_ack_irq,
+	.irq_mask	= mpuio_mask_irq,
+	.irq_unmask	= mpuio_unmask_irq,
+	.irq_set_type	= gpio_irq_type,
 #ifdef CONFIG_ARCH_OMAP16XX
 	/* REVISIT: assuming only 16xx supports MPUIO wake events */
-	.set_wake	= gpio_wake_enable,
+	.irq_set_wake	= gpio_wake_enable,
 #endif
 };
 
@@ -1489,7 +1347,8 @@ static int omap_mpuio_suspend_noirq(stru
 {
 	struct platform_device *pdev = to_platform_device(dev);
 	struct gpio_bank	*bank = platform_get_drvdata(pdev);
-	void __iomem		*mask_reg = bank->base + OMAP_MPUIO_GPIO_MASKIT;
+	void __iomem		*mask_reg = bank->base +
+					OMAP_MPUIO_GPIO_MASKIT / bank->stride;
 	unsigned long		flags;
 
 	spin_lock_irqsave(&bank->lock, flags);
@@ -1504,7 +1363,8 @@ static int omap_mpuio_resume_noirq(struc
 {
 	struct platform_device *pdev = to_platform_device(dev);
 	struct gpio_bank	*bank = platform_get_drvdata(pdev);
-	void __iomem		*mask_reg = bank->base + OMAP_MPUIO_GPIO_MASKIT;
+	void __iomem		*mask_reg = bank->base +
+					OMAP_MPUIO_GPIO_MASKIT / bank->stride;
 	unsigned long		flags;
 
 	spin_lock_irqsave(&bank->lock, flags);
@@ -1540,7 +1400,8 @@ static struct platform_device omap_mpuio
 
 static inline void mpuio_init(void)
 {
-	platform_set_drvdata(&omap_mpuio_device, &gpio_bank_1610[0]);
+	struct gpio_bank *bank = get_gpio_bank(OMAP_MPUIO(0));
+	platform_set_drvdata(&omap_mpuio_device, bank);
 
 	if (platform_driver_register(&omap_mpuio_driver) == 0)
 		(void) platform_device_register(&omap_mpuio_device);
@@ -1583,7 +1444,7 @@ static int gpio_is_input(struct gpio_ban
 
 	switch (bank->method) {
 	case METHOD_MPUIO:
-		reg += OMAP_MPUIO_IO_CNTL;
+		reg += OMAP_MPUIO_IO_CNTL / bank->stride;
 		break;
 	case METHOD_GPIO_1510:
 		reg += OMAP1510_GPIO_DIR_CONTROL;
@@ -1645,6 +1506,13 @@ static int gpio_debounce(struct gpio_chi
 	unsigned long flags;
 
 	bank = container_of(chip, struct gpio_bank, chip);
+
+	if (!bank->dbck) {
+		bank->dbck = clk_get(bank->dev, "dbclk");
+		if (IS_ERR(bank->dbck))
+			dev_err(bank->dev, "Could not get gpio dbck\n");
+	}
+
 	spin_lock_irqsave(&bank->lock, flags);
 	_set_gpio_debounce(bank, offset, debounce);
 	spin_unlock_irqrestore(&bank->lock, flags);
@@ -1673,34 +1541,16 @@ static int gpio_2irq(struct gpio_chip *c
 
 /*---------------------------------------------------------------------*/
 
-static int initialized;
-#if defined(CONFIG_ARCH_OMAP1) || defined(CONFIG_ARCH_OMAP2)
-static struct clk * gpio_ick;
-#endif
-
-#if defined(CONFIG_ARCH_OMAP2)
-static struct clk * gpio_fck;
-#endif
-
-#if defined(CONFIG_ARCH_OMAP2430)
-static struct clk * gpio5_ick;
-static struct clk * gpio5_fck;
-#endif
-
-#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_ARCH_OMAP4)
-static struct clk *gpio_iclks[OMAP34XX_NR_GPIOS];
-#endif
-
-static void __init omap_gpio_show_rev(void)
+static void __init omap_gpio_show_rev(struct gpio_bank *bank)
 {
 	u32 rev;
 
-	if (cpu_is_omap16xx())
-		rev = __raw_readw(gpio_bank[1].base + OMAP1610_GPIO_REVISION);
+	if (cpu_is_omap16xx() && !(bank->method != METHOD_MPUIO))
+		rev = __raw_readw(bank->base + OMAP1610_GPIO_REVISION);
 	else if (cpu_is_omap24xx() || cpu_is_omap34xx())
-		rev = __raw_readl(gpio_bank[0].base + OMAP24XX_GPIO_REVISION);
+		rev = __raw_readl(bank->base + OMAP24XX_GPIO_REVISION);
 	else if (cpu_is_omap44xx())
-		rev = __raw_readl(gpio_bank[0].base + OMAP4_GPIO_REVISION);
+		rev = __raw_readl(bank->base + OMAP4_GPIO_REVISION);
 	else
 		return;
 
@@ -1713,250 +1563,192 @@ static void __init omap_gpio_show_rev(vo
  */
 static struct lock_class_key gpio_lock_class;
 
-static int __init _omap_gpio_init(void)
+static inline int init_gpio_info(struct platform_device *pdev)
 {
-	int i;
-	int gpio = 0;
-	struct gpio_bank *bank;
-	int bank_size = SZ_8K;	/* Module 4KB + L4 4KB except on omap1 */
-	char clk_name[11];
-
-	initialized = 1;
-
-#if defined(CONFIG_ARCH_OMAP1)
-	if (cpu_is_omap15xx()) {
-		gpio_ick = clk_get(NULL, "arm_gpio_ck");
-		if (IS_ERR(gpio_ick))
-			printk("Could not get arm_gpio_ck\n");
-		else
-			clk_enable(gpio_ick);
+	/* TODO: Analyze removing gpio_bank_count usage from driver code */
+	gpio_bank = kzalloc(gpio_bank_count * sizeof(struct gpio_bank),
+				GFP_KERNEL);
+	if (!gpio_bank) {
+		dev_err(&pdev->dev, "Memory alloc failed for gpio_bank\n");
+		return -ENOMEM;
 	}
-#endif
-#if defined(CONFIG_ARCH_OMAP2)
+	return 0;
+}
+
+/* TODO: Cleanup cpu_is_* checks */
+static void omap_gpio_mod_init(struct gpio_bank *bank, int id)
+{
 	if (cpu_class_is_omap2()) {
-		gpio_ick = clk_get(NULL, "gpios_ick");
-		if (IS_ERR(gpio_ick))
-			printk("Could not get gpios_ick\n");
-		else
-			clk_enable(gpio_ick);
-		gpio_fck = clk_get(NULL, "gpios_fck");
-		if (IS_ERR(gpio_fck))
-			printk("Could not get gpios_fck\n");
-		else
-			clk_enable(gpio_fck);
+		if (cpu_is_omap44xx()) {
+			__raw_writel(0xffffffff, bank->base +
+					OMAP4_GPIO_IRQSTATUSCLR0);
+			__raw_writel(0x00000000, bank->base +
+					 OMAP4_GPIO_DEBOUNCENABLE);
+			/* Initialize interface clk ungated, module enabled */
+			__raw_writel(0, bank->base + OMAP4_GPIO_CTRL);
+		} else if (cpu_is_omap34xx()) {
+			__raw_writel(0x00000000, bank->base +
+					OMAP24XX_GPIO_IRQENABLE1);
+			__raw_writel(0xffffffff, bank->base +
+					OMAP24XX_GPIO_IRQSTATUS1);
+			__raw_writel(0x00000000, bank->base +
+					OMAP24XX_GPIO_DEBOUNCE_EN);
 
-		/*
-		 * On 2430 & 3430 GPIO 5 uses CORE L4 ICLK
-		 */
-#if defined(CONFIG_ARCH_OMAP2430)
-		if (cpu_is_omap2430()) {
-			gpio5_ick = clk_get(NULL, "gpio5_ick");
-			if (IS_ERR(gpio5_ick))
-				printk("Could not get gpio5_ick\n");
-			else
-				clk_enable(gpio5_ick);
-			gpio5_fck = clk_get(NULL, "gpio5_fck");
-			if (IS_ERR(gpio5_fck))
-				printk("Could not get gpio5_fck\n");
-			else
-				clk_enable(gpio5_fck);
+			/* Initialize interface clk ungated, module enabled */
+			__raw_writel(0, bank->base + OMAP24XX_GPIO_CTRL);
+		} else if (cpu_is_omap24xx()) {
+			static const u32 non_wakeup_gpios[] = {
+				0xe203ffc0, 0x08700040
+			};
+			if (id < ARRAY_SIZE(non_wakeup_gpios))
+				bank->non_wakeup_gpios = non_wakeup_gpios[id];
 		}
-#endif
-	}
-#endif
+	} else if (cpu_class_is_omap1()) {
+		if (bank_is_mpuio(bank))
+			__raw_writew(0xffff, bank->base +
+				OMAP_MPUIO_GPIO_MASKIT / bank->stride);
+		if (cpu_is_omap15xx() && bank->method == METHOD_GPIO_1510) {
+			__raw_writew(0xffff, bank->base
+						+ OMAP1510_GPIO_INT_MASK);
+			__raw_writew(0x0000, bank->base
+						+ OMAP1510_GPIO_INT_STATUS);
+		}
+		if (cpu_is_omap16xx() && bank->method == METHOD_GPIO_1610) {
+			__raw_writew(0x0000, bank->base
+						+ OMAP1610_GPIO_IRQENABLE1);
+			__raw_writew(0xffff, bank->base
+						+ OMAP1610_GPIO_IRQSTATUS1);
+			__raw_writew(0x0014, bank->base
+						+ OMAP1610_GPIO_SYSCONFIG);
 
-#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_ARCH_OMAP4)
-	if (cpu_is_omap34xx() || cpu_is_omap44xx()) {
-		for (i = 0; i < OMAP34XX_NR_GPIOS; i++) {
-			sprintf(clk_name, "gpio%d_ick", i + 1);
-			gpio_iclks[i] = clk_get(NULL, clk_name);
-			if (IS_ERR(gpio_iclks[i]))
-				printk(KERN_ERR "Could not get %s\n", clk_name);
-			else
-				clk_enable(gpio_iclks[i]);
+			/*
+			 * Enable system clock for GPIO module.
+			 * The CAM_CLK_CTRL *is* really the right place.
+			 */
+			omap_writel(omap_readl(ULPD_CAM_CLK_CTRL) | 0x04,
+						ULPD_CAM_CLK_CTRL);
+		}
+		if (cpu_is_omap7xx() && bank->method == METHOD_GPIO_7XX) {
+			__raw_writel(0xffffffff, bank->base
+						+ OMAP7XX_GPIO_INT_MASK);
+			__raw_writel(0x00000000, bank->base
+						+ OMAP7XX_GPIO_INT_STATUS);
 		}
 	}
-#endif
+}
 
+static void __init omap_gpio_chip_init(struct gpio_bank *bank)
+{
+	int j;
+	static int gpio;
 
-#ifdef CONFIG_ARCH_OMAP15XX
-	if (cpu_is_omap15xx()) {
-		gpio_bank_count = 2;
-		gpio_bank = gpio_bank_1510;
-		bank_size = SZ_2K;
-	}
-#endif
-#if defined(CONFIG_ARCH_OMAP16XX)
-	if (cpu_is_omap16xx()) {
-		gpio_bank_count = 5;
-		gpio_bank = gpio_bank_1610;
-		bank_size = SZ_2K;
-	}
-#endif
-#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
-	if (cpu_is_omap7xx()) {
-		gpio_bank_count = 7;
-		gpio_bank = gpio_bank_7xx;
-		bank_size = SZ_2K;
-	}
-#endif
-#ifdef CONFIG_ARCH_OMAP2
-	if (cpu_is_omap242x()) {
-		gpio_bank_count = 4;
-		gpio_bank = gpio_bank_242x;
-	}
-	if (cpu_is_omap243x()) {
-		gpio_bank_count = 5;
-		gpio_bank = gpio_bank_243x;
-	}
-#endif
-#ifdef CONFIG_ARCH_OMAP3
-	if (cpu_is_omap34xx()) {
-		gpio_bank_count = OMAP34XX_NR_GPIOS;
-		gpio_bank = gpio_bank_34xx;
-	}
+	bank->mod_usage = 0;
+	/*
+	 * REVISIT eventually switch from OMAP-specific gpio structs
+	 * over to the generic ones
+	 */
+	bank->chip.request = omap_gpio_request;
+	bank->chip.free = omap_gpio_free;
+	bank->chip.direction_input = gpio_input;
+	bank->chip.get = gpio_get;
+	bank->chip.direction_output = gpio_output;
+	bank->chip.set_debounce = gpio_debounce;
+	bank->chip.set = gpio_set;
+	bank->chip.to_irq = gpio_2irq;
+	if (bank_is_mpuio(bank)) {
+		bank->chip.label = "mpuio";
+#ifdef CONFIG_ARCH_OMAP16XX
+		bank->chip.dev = &omap_mpuio_device.dev;
 #endif
-#ifdef CONFIG_ARCH_OMAP4
-	if (cpu_is_omap44xx()) {
-		gpio_bank_count = OMAP34XX_NR_GPIOS;
-		gpio_bank = gpio_bank_44xx;
+		bank->chip.base = OMAP_MPUIO(0);
+	} else {
+		bank->chip.label = "gpio";
+		bank->chip.base = gpio;
+		gpio += bank_width;
 	}
-#endif
-	for (i = 0; i < gpio_bank_count; i++) {
-		int j, gpio_count = 16;
+	bank->chip.ngpio = bank_width;
 
-		bank = &gpio_bank[i];
-		spin_lock_init(&bank->lock);
+	gpiochip_add(&bank->chip);
 
-		/* Static mapping, never released */
-		bank->base = ioremap(bank->pbase, bank_size);
-		if (!bank->base) {
-			printk(KERN_ERR "Could not ioremap gpio bank%i\n", i);
-			continue;
-		}
+	for (j = bank->virtual_irq_start;
+		     j < bank->virtual_irq_start + bank_width; j++) {
+		struct irq_desc *d = irq_to_desc(j);
 
+		lockdep_set_class(&d->lock, &gpio_lock_class);
+		set_irq_chip_data(j, bank);
 		if (bank_is_mpuio(bank))
-			__raw_writew(0xffff, bank->base + OMAP_MPUIO_GPIO_MASKIT);
-		if (cpu_is_omap15xx() && bank->method == METHOD_GPIO_1510) {
-			__raw_writew(0xffff, bank->base + OMAP1510_GPIO_INT_MASK);
-			__raw_writew(0x0000, bank->base + OMAP1510_GPIO_INT_STATUS);
-		}
-		if (cpu_is_omap16xx() && bank->method == METHOD_GPIO_1610) {
-			__raw_writew(0x0000, bank->base + OMAP1610_GPIO_IRQENABLE1);
-			__raw_writew(0xffff, bank->base + OMAP1610_GPIO_IRQSTATUS1);
-			__raw_writew(0x0014, bank->base + OMAP1610_GPIO_SYSCONFIG);
-		}
-		if (cpu_is_omap7xx() && bank->method == METHOD_GPIO_7XX) {
-			__raw_writel(0xffffffff, bank->base + OMAP7XX_GPIO_INT_MASK);
-			__raw_writel(0x00000000, bank->base + OMAP7XX_GPIO_INT_STATUS);
+			set_irq_chip(j, &mpuio_irq_chip);
+		else
+			set_irq_chip(j, &gpio_irq_chip);
+		set_irq_handler(j, handle_simple_irq);
+		set_irq_flags(j, IRQF_VALID);
+	}
+	set_irq_chained_handler(bank->irq, gpio_irq_handler);
+	set_irq_data(bank->irq, bank);
+}
 
-			gpio_count = 32; /* 7xx has 32-bit GPIOs */
-		}
+static int __devinit omap_gpio_probe(struct platform_device *pdev)
+{
+	static int gpio_init_done;
+	struct omap_gpio_platform_data *pdata;
+	struct resource *res;
+	int id;
+	struct gpio_bank *bank;
 
-#ifdef CONFIG_ARCH_OMAP2PLUS
-		if ((bank->method == METHOD_GPIO_24XX) ||
-				(bank->method == METHOD_GPIO_44XX)) {
-			static const u32 non_wakeup_gpios[] = {
-				0xe203ffc0, 0x08700040
-			};
+	if (!pdev->dev.platform_data)
+		return -EINVAL;
 
-			if (cpu_is_omap44xx()) {
-				__raw_writel(0xffffffff, bank->base +
-						OMAP4_GPIO_IRQSTATUSCLR0);
-				__raw_writew(0x0015, bank->base +
-						OMAP4_GPIO_SYSCONFIG);
-				__raw_writel(0x00000000, bank->base +
-						 OMAP4_GPIO_DEBOUNCENABLE);
-				/*
-				 * Initialize interface clock ungated,
-				 * module enabled
-				 */
-				__raw_writel(0, bank->base + OMAP4_GPIO_CTRL);
-			} else {
-				__raw_writel(0x00000000, bank->base +
-						OMAP24XX_GPIO_IRQENABLE1);
-				__raw_writel(0xffffffff, bank->base +
-						OMAP24XX_GPIO_IRQSTATUS1);
-				__raw_writew(0x0015, bank->base +
-						OMAP24XX_GPIO_SYSCONFIG);
-				__raw_writel(0x00000000, bank->base +
-						OMAP24XX_GPIO_DEBOUNCE_EN);
+	pdata = pdev->dev.platform_data;
 
-				/*
-				 * Initialize interface clock ungated,
-				 * module enabled
-				 */
-				__raw_writel(0, bank->base +
-						OMAP24XX_GPIO_CTRL);
-			}
-			if (cpu_is_omap24xx() &&
-			    i < ARRAY_SIZE(non_wakeup_gpios))
-				bank->non_wakeup_gpios = non_wakeup_gpios[i];
-			gpio_count = 32;
-		}
-#endif
+	if (!gpio_init_done) {
+		int ret;
 
-		bank->mod_usage = 0;
-		/* REVISIT eventually switch from OMAP-specific gpio structs
-		 * over to the generic ones
-		 */
-		bank->chip.request = omap_gpio_request;
-		bank->chip.free = omap_gpio_free;
-		bank->chip.direction_input = gpio_input;
-		bank->chip.get = gpio_get;
-		bank->chip.direction_output = gpio_output;
-		bank->chip.set_debounce = gpio_debounce;
-		bank->chip.set = gpio_set;
-		bank->chip.to_irq = gpio_2irq;
-		if (bank_is_mpuio(bank)) {
-			bank->chip.label = "mpuio";
-#ifdef CONFIG_ARCH_OMAP16XX
-			bank->chip.dev = &omap_mpuio_device.dev;
-#endif
-			bank->chip.base = OMAP_MPUIO(0);
-		} else {
-			bank->chip.label = "gpio";
-			bank->chip.base = gpio;
-			gpio += gpio_count;
-		}
-		bank->chip.ngpio = gpio_count;
+		ret = init_gpio_info(pdev);
+		if (ret)
+			return ret;
+	}
 
-		gpiochip_add(&bank->chip);
+	id = pdev->id;
+	bank = &gpio_bank[id];
 
-		for (j = bank->virtual_irq_start;
-		     j < bank->virtual_irq_start + gpio_count; j++) {
-			lockdep_set_class(&irq_desc[j].lock, &gpio_lock_class);
-			set_irq_chip_data(j, bank);
-			if (bank_is_mpuio(bank))
-				set_irq_chip(j, &mpuio_irq_chip);
-			else
-				set_irq_chip(j, &gpio_irq_chip);
-			set_irq_handler(j, handle_simple_irq);
-			set_irq_flags(j, IRQF_VALID);
-		}
-		set_irq_chained_handler(bank->irq, gpio_irq_handler);
-		set_irq_data(bank->irq, bank);
+	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (unlikely(!res)) {
+		dev_err(&pdev->dev, "GPIO Bank %i Invalid IRQ resource\n", id);
+		return -ENODEV;
+	}
 
-		if (cpu_is_omap34xx() || cpu_is_omap44xx()) {
-			sprintf(clk_name, "gpio%d_dbck", i + 1);
-			bank->dbck = clk_get(NULL, clk_name);
-			if (IS_ERR(bank->dbck))
-				printk(KERN_ERR "Could not get %s\n", clk_name);
-		}
+	bank->irq = res->start;
+	bank->virtual_irq_start = pdata->virtual_irq_start;
+	bank->method = pdata->bank_type;
+	bank->dev = &pdev->dev;
+	bank->dbck_flag = pdata->dbck_flag;
+	bank->stride = pdata->bank_stride;
+	bank_width = pdata->bank_width;
+
+	spin_lock_init(&bank->lock);
+
+	/* Static mapping, never released */
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (unlikely(!res)) {
+		dev_err(&pdev->dev, "GPIO Bank %i Invalid mem resource\n", id);
+		return -ENODEV;
 	}
 
-	/* Enable system clock for GPIO module.
-	 * The CAM_CLK_CTRL *is* really the right place. */
-	if (cpu_is_omap16xx())
-		omap_writel(omap_readl(ULPD_CAM_CLK_CTRL) | 0x04, ULPD_CAM_CLK_CTRL);
+	bank->base = ioremap(res->start, resource_size(res));
+	if (!bank->base) {
+		dev_err(&pdev->dev, "Could not ioremap gpio bank%i\n", id);
+		return -ENOMEM;
+	}
 
-	/* Enable autoidle for the OCP interface */
-	if (cpu_is_omap24xx())
-		omap_writel(1 << 0, 0x48019010);
-	if (cpu_is_omap34xx())
-		omap_writel(1 << 0, 0x48306814);
+	pm_runtime_enable(bank->dev);
+	pm_runtime_get_sync(bank->dev);
 
-	omap_gpio_show_rev();
+	omap_gpio_mod_init(bank, id);
+	omap_gpio_chip_init(bank);
+	omap_gpio_show_rev(bank);
+
+	if (!gpio_init_done)
+		gpio_init_done = 1;
 
 	return 0;
 }
@@ -2074,7 +1866,7 @@ static struct sys_device omap_gpio_devic
 
 static int workaround_enabled;
 
-void omap2_gpio_prepare_for_idle(int power_state)
+void omap2_gpio_prepare_for_idle(int off_mode)
 {
 	int i, c = 0;
 	int min = 0;
@@ -2090,7 +1882,7 @@ void omap2_gpio_prepare_for_idle(int pow
 		for (j = 0; j < hweight_long(bank->dbck_enable_mask); j++)
 			clk_disable(bank->dbck);
 
-		if (power_state > PWRDM_POWER_OFF)
+		if (!off_mode)
 			continue;
 
 		/* If going to OFF, remove triggering for all
@@ -2251,8 +2043,6 @@ void omap_gpio_save_context(void)
 	/* saving banks from 2-6 only since GPIO1 is in WKUP */
 	for (i = 1; i < gpio_bank_count; i++) {
 		struct gpio_bank *bank = &gpio_bank[i];
-		gpio_context[i].sysconfig =
-			__raw_readl(bank->base + OMAP24XX_GPIO_SYSCONFIG);
 		gpio_context[i].irqenable1 =
 			__raw_readl(bank->base + OMAP24XX_GPIO_IRQENABLE1);
 		gpio_context[i].irqenable2 =
@@ -2283,8 +2073,6 @@ void omap_gpio_restore_context(void)
 
 	for (i = 1; i < gpio_bank_count; i++) {
 		struct gpio_bank *bank = &gpio_bank[i];
-		__raw_writel(gpio_context[i].sysconfig,
-				bank->base + OMAP24XX_GPIO_SYSCONFIG);
 		__raw_writel(gpio_context[i].irqenable1,
 				bank->base + OMAP24XX_GPIO_IRQENABLE1);
 		__raw_writel(gpio_context[i].irqenable2,
@@ -2309,25 +2097,28 @@ void omap_gpio_restore_context(void)
 }
 #endif
 
+static struct platform_driver omap_gpio_driver = {
+	.probe		= omap_gpio_probe,
+	.driver		= {
+		.name	= "omap_gpio",
+	},
+};
+
 /*
- * This may get called early from board specific init
- * for boards that have interrupts routed via FPGA.
+ * gpio driver register needs to be done before
+ * machine_init functions access gpio APIs.
+ * Hence omap_gpio_drv_reg() is a postcore_initcall.
  */
-int __init omap_gpio_init(void)
+static int __init omap_gpio_drv_reg(void)
 {
-	if (!initialized)
-		return _omap_gpio_init();
-	else
-		return 0;
+	return platform_driver_register(&omap_gpio_driver);
 }
+postcore_initcall(omap_gpio_drv_reg);
 
 static int __init omap_gpio_sysinit(void)
 {
 	int ret = 0;
 
-	if (!initialized)
-		ret = _omap_gpio_init();
-
 	mpuio_init();
 
 #if defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP2PLUS)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-omap/i2c.c linux-libre-2.6.38-gnu1/arch/arm/plat-omap/i2c.c
--- linux-libre-2.6.37-gnu1/arch/arm/plat-omap/i2c.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-omap/i2c.c	2011-03-14 21:20:32.000000000 -0400
@@ -27,20 +27,20 @@
 #include <linux/platform_device.h>
 #include <linux/i2c.h>
 #include <linux/i2c-omap.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/clk.h>
 
 #include <mach/irqs.h>
 #include <plat/mux.h>
 #include <plat/i2c.h>
 #include <plat/omap-pm.h>
+#include <plat/omap_device.h>
 
 #define OMAP_I2C_SIZE		0x3f
 #define OMAP1_I2C_BASE		0xfffb3800
-#define OMAP2_I2C_BASE1		0x48070000
-#define OMAP2_I2C_BASE2		0x48072000
-#define OMAP2_I2C_BASE3		0x48060000
-#define OMAP4_I2C_BASE4		0x48350000
 
-static const char name[] = "i2c_omap";
+static const char name[] = "omap_i2c";
 
 #define I2C_RESOURCE_BUILDER(base, irq)			\
 	{						\
@@ -55,15 +55,6 @@ static const char name[] = "i2c_omap";
 
 static struct resource i2c_resources[][2] = {
 	{ I2C_RESOURCE_BUILDER(0, 0) },
-#if	defined(CONFIG_ARCH_OMAP2PLUS)
-	{ I2C_RESOURCE_BUILDER(OMAP2_I2C_BASE2, 0) },
-#endif
-#if	defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_ARCH_OMAP4)
-	{ I2C_RESOURCE_BUILDER(OMAP2_I2C_BASE3, 0) },
-#endif
-#if	defined(CONFIG_ARCH_OMAP4)
-	{ I2C_RESOURCE_BUILDER(OMAP4_I2C_BASE4, 0) },
-#endif
 };
 
 #define I2C_DEV_BUILDER(bus_id, res, data)		\
@@ -77,18 +68,11 @@ static struct resource i2c_resources[][2
 		},					\
 	}
 
-static struct omap_i2c_bus_platform_data i2c_pdata[ARRAY_SIZE(i2c_resources)];
+#define MAX_OMAP_I2C_HWMOD_NAME_LEN	16
+#define OMAP_I2C_MAX_CONTROLLERS 4
+static struct omap_i2c_bus_platform_data i2c_pdata[OMAP_I2C_MAX_CONTROLLERS];
 static struct platform_device omap_i2c_devices[] = {
 	I2C_DEV_BUILDER(1, i2c_resources[0], &i2c_pdata[0]),
-#if	defined(CONFIG_ARCH_OMAP2PLUS)
-	I2C_DEV_BUILDER(2, i2c_resources[1], &i2c_pdata[1]),
-#endif
-#if	defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_ARCH_OMAP4)
-	I2C_DEV_BUILDER(3, i2c_resources[2], &i2c_pdata[2]),
-#endif
-#if	defined(CONFIG_ARCH_OMAP4)
-	I2C_DEV_BUILDER(4, i2c_resources[3], &i2c_pdata[3]),
-#endif
 };
 
 #define OMAP_I2C_CMDLINE_SETUP	(BIT(31))
@@ -109,35 +93,25 @@ static int __init omap_i2c_nr_ports(void
 	return ports;
 }
 
-/* Shared between omap2 and 3 */
-static resource_size_t omap2_i2c_irq[3] __initdata = {
-	INT_24XX_I2C1_IRQ,
-	INT_24XX_I2C2_IRQ,
-	INT_34XX_I2C3_IRQ,
-};
-
-static resource_size_t omap4_i2c_irq[4] __initdata = {
-	OMAP44XX_IRQ_I2C1,
-	OMAP44XX_IRQ_I2C2,
-	OMAP44XX_IRQ_I2C3,
-	OMAP44XX_IRQ_I2C4,
-};
-
-static inline int omap1_i2c_add_bus(struct platform_device *pdev, int bus_id)
+static inline int omap1_i2c_add_bus(int bus_id)
 {
-	struct omap_i2c_bus_platform_data *pd;
+	struct platform_device *pdev;
+	struct omap_i2c_bus_platform_data *pdata;
 	struct resource *res;
 
-	pd = pdev->dev.platform_data;
+	omap1_i2c_mux_pins(bus_id);
+
+	pdev = &omap_i2c_devices[bus_id - 1];
 	res = pdev->resource;
 	res[0].start = OMAP1_I2C_BASE;
 	res[0].end = res[0].start + OMAP_I2C_SIZE;
 	res[1].start = INT_I2C;
-	omap1_i2c_mux_pins(bus_id);
+	pdata = &i2c_pdata[bus_id - 1];
 
 	return platform_device_register(pdev);
 }
 
+
 /*
  * XXX This function is a temporary compatibility wrapper - only
  * needed until the I2C driver can be converted to call
@@ -148,52 +122,64 @@ static void omap_pm_set_max_mpu_wakeup_l
 	omap_pm_set_max_mpu_wakeup_lat(dev, t);
 }
 
-static inline int omap2_i2c_add_bus(struct platform_device *pdev, int bus_id)
-{
-	struct resource *res;
-	resource_size_t *irq;
+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,
+	},
+};
 
-	res = pdev->resource;
+#ifdef CONFIG_ARCH_OMAP2PLUS
+static inline int omap2_i2c_add_bus(int bus_id)
+{
+	int l;
+	struct omap_hwmod *oh;
+	struct omap_device *od;
+	char oh_name[MAX_OMAP_I2C_HWMOD_NAME_LEN];
+	struct omap_i2c_bus_platform_data *pdata;
 
-	if (!cpu_is_omap44xx())
-		irq = omap2_i2c_irq;
-	else
-		irq = omap4_i2c_irq;
+	omap2_i2c_mux_pins(bus_id);
 
-	if (bus_id == 1) {
-		res[0].start = OMAP2_I2C_BASE1;
-		res[0].end = res[0].start + OMAP_I2C_SIZE;
+	l = snprintf(oh_name, MAX_OMAP_I2C_HWMOD_NAME_LEN, "i2c%d", bus_id);
+	WARN(l >= MAX_OMAP_I2C_HWMOD_NAME_LEN,
+		"String buffer overflow in I2C%d device setup\n", bus_id);
+	oh = omap_hwmod_lookup(oh_name);
+	if (!oh) {
+			pr_err("Could not look up %s\n", oh_name);
+			return -EEXIST;
 	}
 
-	res[1].start = irq[bus_id - 1];
-	omap2_i2c_mux_pins(bus_id);
-
+	pdata = &i2c_pdata[bus_id - 1];
 	/*
 	 * 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
 	 * completes.
+	 * Only omap3 has support for constraints
 	 */
-	if (cpu_is_omap34xx()) {
-		struct omap_i2c_bus_platform_data *pd;
-
-		pd = pdev->dev.platform_data;
-		pd->set_mpu_wkup_lat = omap_pm_set_max_mpu_wakeup_lat_compat;
-	}
+	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,
+			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);
 
-	return platform_device_register(pdev);
+	return PTR_ERR(od);
+}
+#else
+static inline int omap2_i2c_add_bus(int bus_id)
+{
+	return 0;
 }
+#endif
 
 static int __init omap_i2c_add_bus(int bus_id)
 {
-	struct platform_device *pdev;
-
-	pdev = &omap_i2c_devices[bus_id - 1];
-
 	if (cpu_class_is_omap1())
-		return omap1_i2c_add_bus(pdev, bus_id);
+		return omap1_i2c_add_bus(bus_id);
 	else
-		return omap2_i2c_add_bus(pdev, bus_id);
+		return omap2_i2c_add_bus(bus_id);
 }
 
 /**
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-omap/include/plat/clkdev_omap.h linux-libre-2.6.38-gnu1/arch/arm/plat-omap/include/plat/clkdev_omap.h
--- linux-libre-2.6.37-gnu1/arch/arm/plat-omap/include/plat/clkdev_omap.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-omap/include/plat/clkdev_omap.h	2011-03-14 21:20:32.000000000 -0400
@@ -8,7 +8,7 @@
 #ifndef __ARCH_ARM_PLAT_OMAP_INCLUDE_PLAT_CLKDEV_OMAP_H
 #define __ARCH_ARM_PLAT_OMAP_INCLUDE_PLAT_CLKDEV_OMAP_H
 
-#include <asm/clkdev.h>
+#include <linux/clkdev.h>
 
 struct omap_clk {
 	u16				cpu;
@@ -31,18 +31,18 @@ struct omap_clk {
 #define CK_1510		(1 << 2)
 #define CK_16XX		(1 << 3)	/* 16xx, 17xx, 5912 */
 #define CK_242X		(1 << 4)
-#define CK_243X		(1 << 5)
-#define CK_3XXX		(1 << 6)	/* OMAP3 + AM3 common clocks*/
-#define CK_343X		(1 << 7)	/* OMAP34xx common clocks */
-#define CK_3430ES1	(1 << 8)	/* 34xxES1 only */
-#define CK_3430ES2	(1 << 9)	/* 34xxES2, ES3, non-Sitara 35xx only */
-#define CK_3505		(1 << 10)
-#define CK_3517		(1 << 11)
-#define CK_36XX		(1 << 12)	/* OMAP36xx/37xx-specific clocks */
-#define CK_443X		(1 << 13)
+#define CK_243X		(1 << 5)	/* 243x, 253x */
+#define CK_3430ES1	(1 << 6)	/* 34xxES1 only */
+#define CK_3430ES2PLUS	(1 << 7)	/* 34xxES2, ES3, non-Sitara 35xx only */
+#define CK_3505		(1 << 8)
+#define CK_3517		(1 << 9)
+#define CK_36XX		(1 << 10)	/* 36xx/37xx-specific clocks */
+#define CK_443X		(1 << 11)
 
-#define CK_AM35XX	(CK_3505 | CK_3517)	/* all Sitara AM35xx */
 
+#define CK_34XX		(CK_3430ES1 | CK_3430ES2PLUS)
+#define CK_AM35XX	(CK_3505 | CK_3517)	/* all Sitara AM35xx */
+#define CK_3XXX		(CK_34XX | CK_AM35XX | CK_36XX)
 
 
 #endif
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-omap/include/plat/clockdomain.h linux-libre-2.6.38-gnu1/arch/arm/plat-omap/include/plat/clockdomain.h
--- linux-libre-2.6.37-gnu1/arch/arm/plat-omap/include/plat/clockdomain.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-omap/include/plat/clockdomain.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,141 +0,0 @@
-/*
- * arch/arm/plat-omap/include/mach/clockdomain.h
- *
- * OMAP2/3 clockdomain framework functions
- *
- * Copyright (C) 2008 Texas Instruments, Inc.
- * Copyright (C) 2008-2009 Nokia Corporation
- *
- * Written by Paul Walmsley
- *
- * This program is free software; you can 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_OMAP_CLOCKDOMAIN_H
-#define __ASM_ARM_ARCH_OMAP_CLOCKDOMAIN_H
-
-#include <plat/powerdomain.h>
-#include <plat/clock.h>
-#include <plat/cpu.h>
-
-/* Clockdomain capability flags */
-#define CLKDM_CAN_FORCE_SLEEP			(1 << 0)
-#define CLKDM_CAN_FORCE_WAKEUP			(1 << 1)
-#define CLKDM_CAN_ENABLE_AUTO			(1 << 2)
-#define CLKDM_CAN_DISABLE_AUTO			(1 << 3)
-
-#define CLKDM_CAN_HWSUP		(CLKDM_CAN_ENABLE_AUTO | CLKDM_CAN_DISABLE_AUTO)
-#define CLKDM_CAN_SWSUP		(CLKDM_CAN_FORCE_SLEEP | CLKDM_CAN_FORCE_WAKEUP)
-#define CLKDM_CAN_HWSUP_SWSUP	(CLKDM_CAN_SWSUP | CLKDM_CAN_HWSUP)
-
-/* OMAP24XX CM_CLKSTCTRL_*.AUTOSTATE_* register bit values */
-#define OMAP24XX_CLKSTCTRL_DISABLE_AUTO		0x0
-#define OMAP24XX_CLKSTCTRL_ENABLE_AUTO		0x1
-
-/* OMAP3XXX CM_CLKSTCTRL_*.CLKTRCTRL_* register bit values */
-#define OMAP34XX_CLKSTCTRL_DISABLE_AUTO		0x0
-#define OMAP34XX_CLKSTCTRL_FORCE_SLEEP		0x1
-#define OMAP34XX_CLKSTCTRL_FORCE_WAKEUP		0x2
-#define OMAP34XX_CLKSTCTRL_ENABLE_AUTO		0x3
-
-/**
- * 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,
- * removed when the clockdomain should be allowed to go inactive in
- * hwsup mode.
- *
- * Autodeps are deprecated and should be removed after
- * omap_hwmod-based fine-grained module idle control is added.
- */
-struct clkdm_autodep {
-	union {
-		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
- *
- * Statically defined.  @clkdm is resolved from @clkdm_name at runtime and
- * should not be pre-initialized.
- *
- * XXX Should also include hardware (fixed) dependencies.
- */
-struct clkdm_dep {
-	const char *clkdm_name;
-	struct clockdomain *clkdm;
-	atomic_t wkdep_usecount;
-	atomic_t sleepdep_usecount;
-	const struct omap_chip_id omap_chip;
-};
-
-/**
- * struct clockdomain - OMAP clockdomain
- * @name: clockdomain name
- * @pwrdm: powerdomain containing this clockdomain
- * @clktrctrl_reg: CLKSTCTRL reg for the given clock domain
- * @clktrctrl_mask: CLKTRCTRL/AUTOSTATE field mask in CM_CLKSTCTRL reg
- * @flags: Clockdomain capability flags
- * @dep_bit: Bit shift of this clockdomain's PM_WKDEP/CM_SLEEPDEP bit
- * @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
- */
-struct clockdomain {
-	const char *name;
-	union {
-		const char *name;
-		struct powerdomain *ptr;
-	} pwrdm;
-	void __iomem *clkstctrl_reg;
-	const u16 clktrctrl_mask;
-	const u8 flags;
-	const u8 dep_bit;
-	struct clkdm_dep *wkdep_srcs;
-	struct clkdm_dep *sleepdep_srcs;
-	const struct omap_chip_id omap_chip;
-	atomic_t usecount;
-	struct list_head node;
-};
-
-void clkdm_init(struct clockdomain **clkdms, struct clkdm_autodep *autodeps);
-struct clockdomain *clkdm_lookup(const char *name);
-
-int clkdm_for_each(int (*fn)(struct clockdomain *clkdm, void *user),
-			void *user);
-struct powerdomain *clkdm_get_pwrdm(struct clockdomain *clkdm);
-
-int clkdm_add_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2);
-int clkdm_del_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2);
-int clkdm_read_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2);
-int clkdm_clear_all_wkdeps(struct clockdomain *clkdm);
-int clkdm_add_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2);
-int clkdm_del_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2);
-int clkdm_read_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2);
-int clkdm_clear_all_sleepdeps(struct clockdomain *clkdm);
-
-void omap2_clkdm_allow_idle(struct clockdomain *clkdm);
-void omap2_clkdm_deny_idle(struct clockdomain *clkdm);
-
-int omap2_clkdm_wakeup(struct clockdomain *clkdm);
-int omap2_clkdm_sleep(struct clockdomain *clkdm);
-
-int omap2_clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk);
-int omap2_clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk);
-
-#endif
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-omap/include/plat/clock.h linux-libre-2.6.38-gnu1/arch/arm/plat-omap/include/plat/clock.h
--- linux-libre-2.6.37-gnu1/arch/arm/plat-omap/include/plat/clock.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-omap/include/plat/clock.h	2011-03-14 21:20:32.000000000 -0400
@@ -49,13 +49,18 @@ struct clkops {
 /* struct clksel_rate.flags possibilities */
 #define RATE_IN_242X		(1 << 0)
 #define RATE_IN_243X		(1 << 1)
-#define RATE_IN_3XXX		(1 << 2)	/* rates common to all OMAP3 */
-#define RATE_IN_3430ES2		(1 << 3)	/* 3430ES2 rates only */
+#define RATE_IN_3430ES1		(1 << 2)	/* 3430ES1 rates only */
+#define RATE_IN_3430ES2PLUS	(1 << 3)	/* 3430 ES >= 2 rates only */
 #define RATE_IN_36XX		(1 << 4)
 #define RATE_IN_4430		(1 << 5)
 
 #define RATE_IN_24XX		(RATE_IN_242X | RATE_IN_243X)
-#define RATE_IN_3430ES2PLUS	(RATE_IN_3430ES2 | RATE_IN_36XX)
+#define RATE_IN_34XX		(RATE_IN_3430ES1 | RATE_IN_3430ES2PLUS)
+#define RATE_IN_3XXX		(RATE_IN_34XX | RATE_IN_36XX)
+
+/* RATE_IN_3430ES2PLUS_36XX includes 34xx/35xx with ES >=2, and all 36xx/37xx */
+#define RATE_IN_3430ES2PLUS_36XX	(RATE_IN_3430ES2PLUS | RATE_IN_36XX)
+
 
 /**
  * struct clksel_rate - register bitfield values corresponding to clk divisors
@@ -119,8 +124,7 @@ struct clksel {
  *
  * Possible values for @flags:
  * DPLL_J_TYPE: "J-type DPLL" (only some 36xx, 4xxx DPLLs)
- * NO_DCO_SEL: don't program DCO (only for some J-type DPLLs)
-
+ *
  * @freqsel_mask is only used on the OMAP34xx family and AM35xx.
  *
  * XXX Some DPLLs have multiple bypass inputs, so it's not technically
@@ -156,6 +160,8 @@ struct dpll_data {
 	u32			autoidle_mask;
 	u32			freqsel_mask;
 	u32			idlest_mask;
+	u32			dco_mask;
+	u32			sddiv_mask;
 	u8			auto_recal_bit;
 	u8			recal_en_bit;
 	u8			recal_st_bit;
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-omap/include/plat/common.h linux-libre-2.6.38-gnu1/arch/arm/plat-omap/include/plat/common.h
--- linux-libre-2.6.37-gnu1/arch/arm/plat-omap/include/plat/common.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-omap/include/plat/common.h	2011-03-14 21:20:32.000000000 -0400
@@ -27,12 +27,17 @@
 #ifndef __ARCH_ARM_MACH_OMAP_COMMON_H
 #define __ARCH_ARM_MACH_OMAP_COMMON_H
 
+#include <linux/delay.h>
+
 #include <plat/i2c.h>
 
 struct sys_timer;
 
 extern void omap_map_common_io(void);
 extern struct sys_timer omap_timer;
+extern bool omap_32k_timer_init(void);
+extern int __init omap_init_clocksource_32k(void);
+extern unsigned long long notrace omap_32k_sched_clock(void);
 
 extern void omap_reserve(void);
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-omap/include/plat/display.h linux-libre-2.6.38-gnu1/arch/arm/plat-omap/include/plat/display.h
--- linux-libre-2.6.37-gnu1/arch/arm/plat-omap/include/plat/display.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-omap/include/plat/display.h	2011-03-14 21:20:32.000000000 -0400
@@ -42,6 +42,10 @@
 #define DISPC_IRQ_SYNC_LOST		(1 << 14)
 #define DISPC_IRQ_SYNC_LOST_DIGIT	(1 << 15)
 #define DISPC_IRQ_WAKEUP		(1 << 16)
+#define DISPC_IRQ_SYNC_LOST2		(1 << 17)
+#define DISPC_IRQ_VSYNC2		(1 << 18)
+#define DISPC_IRQ_ACBIAS_COUNT_STAT2	(1 << 21)
+#define DISPC_IRQ_FRAMEDONE2		(1 << 22)
 
 struct omap_dss_device;
 struct omap_overlay_manager;
@@ -64,6 +68,7 @@ enum omap_plane {
 enum omap_channel {
 	OMAP_DSS_CHANNEL_LCD	= 0,
 	OMAP_DSS_CHANNEL_DIGIT	= 1,
+	OMAP_DSS_CHANNEL_LCD2	= 2,
 };
 
 enum omap_color_mode {
@@ -142,6 +147,7 @@ enum omap_dss_display_state {
 enum omap_dss_overlay_managers {
 	OMAP_DSS_OVL_MGR_LCD,
 	OMAP_DSS_OVL_MGR_TV,
+	OMAP_DSS_OVL_MGR_LCD2,
 };
 
 enum omap_dss_rotation_type {
@@ -268,6 +274,7 @@ struct omap_overlay_info {
 	u16 out_width;	/* if 0, out_width == width */
 	u16 out_height;	/* if 0, out_height == height */
 	u8 global_alpha;
+	u8 pre_mult_alpha;
 };
 
 struct omap_overlay {
@@ -351,6 +358,8 @@ struct omap_dss_device {
 
 	enum omap_display_type type;
 
+	enum omap_channel channel;
+
 	union {
 		struct {
 			u8 data_lines;
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-omap/include/plat/dma.h linux-libre-2.6.38-gnu1/arch/arm/plat-omap/include/plat/dma.h
--- linux-libre-2.6.37-gnu1/arch/arm/plat-omap/include/plat/dma.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-omap/include/plat/dma.h	2011-03-14 21:20:32.000000000 -0400
@@ -21,141 +21,15 @@
 #ifndef __ASM_ARCH_DMA_H
 #define __ASM_ARCH_DMA_H
 
-/* Move omap4 specific defines to dma-44xx.h */
-#include "dma-44xx.h"
-
-/* Hardware registers for omap1 */
-#define OMAP1_DMA_BASE			(0xfffed800)
-
-#define OMAP1_DMA_GCR			0x400
-#define OMAP1_DMA_GSCR			0x404
-#define OMAP1_DMA_GRST			0x408
-#define OMAP1_DMA_HW_ID			0x442
-#define OMAP1_DMA_PCH2_ID		0x444
-#define OMAP1_DMA_PCH0_ID		0x446
-#define OMAP1_DMA_PCH1_ID		0x448
-#define OMAP1_DMA_PCHG_ID		0x44a
-#define OMAP1_DMA_PCHD_ID		0x44c
-#define OMAP1_DMA_CAPS_0_U		0x44e
-#define OMAP1_DMA_CAPS_0_L		0x450
-#define OMAP1_DMA_CAPS_1_U		0x452
-#define OMAP1_DMA_CAPS_1_L		0x454
-#define OMAP1_DMA_CAPS_2		0x456
-#define OMAP1_DMA_CAPS_3		0x458
-#define OMAP1_DMA_CAPS_4		0x45a
-#define OMAP1_DMA_PCH2_SR		0x460
-#define OMAP1_DMA_PCH0_SR		0x480
-#define OMAP1_DMA_PCH1_SR		0x482
-#define OMAP1_DMA_PCHD_SR		0x4c0
-
-/* Hardware registers for omap2 and omap3 */
-#define OMAP24XX_DMA4_BASE		(L4_24XX_BASE + 0x56000)
-#define OMAP34XX_DMA4_BASE		(L4_34XX_BASE + 0x56000)
-#define OMAP44XX_DMA4_BASE		(L4_44XX_BASE + 0x56000)
-
-#define OMAP_DMA4_REVISION		0x00
-#define OMAP_DMA4_GCR			0x78
-#define OMAP_DMA4_IRQSTATUS_L0		0x08
-#define OMAP_DMA4_IRQSTATUS_L1		0x0c
-#define OMAP_DMA4_IRQSTATUS_L2		0x10
-#define OMAP_DMA4_IRQSTATUS_L3		0x14
-#define OMAP_DMA4_IRQENABLE_L0		0x18
-#define OMAP_DMA4_IRQENABLE_L1		0x1c
-#define OMAP_DMA4_IRQENABLE_L2		0x20
-#define OMAP_DMA4_IRQENABLE_L3		0x24
-#define OMAP_DMA4_SYSSTATUS		0x28
-#define OMAP_DMA4_OCP_SYSCONFIG		0x2c
-#define OMAP_DMA4_CAPS_0		0x64
-#define OMAP_DMA4_CAPS_2		0x6c
-#define OMAP_DMA4_CAPS_3		0x70
-#define OMAP_DMA4_CAPS_4		0x74
-
-#define OMAP1_LOGICAL_DMA_CH_COUNT	17
-#define OMAP_DMA4_LOGICAL_DMA_CH_COUNT	32	/* REVISIT: Is this 32 + 2? */
-
-/* Common channel specific registers for omap1 */
-#define OMAP1_DMA_CH_BASE(n)		(0x40 * (n) + 0x00)
-#define OMAP1_DMA_CSDP(n)		(0x40 * (n) + 0x00)
-#define OMAP1_DMA_CCR(n)		(0x40 * (n) + 0x02)
-#define OMAP1_DMA_CICR(n)		(0x40 * (n) + 0x04)
-#define OMAP1_DMA_CSR(n)		(0x40 * (n) + 0x06)
-#define OMAP1_DMA_CEN(n)		(0x40 * (n) + 0x10)
-#define OMAP1_DMA_CFN(n)		(0x40 * (n) + 0x12)
-#define OMAP1_DMA_CSFI(n)		(0x40 * (n) + 0x14)
-#define OMAP1_DMA_CSEI(n)		(0x40 * (n) + 0x16)
-#define OMAP1_DMA_CPC(n)		(0x40 * (n) + 0x18)	/* 15xx only */
-#define OMAP1_DMA_CSAC(n)		(0x40 * (n) + 0x18)
-#define OMAP1_DMA_CDAC(n)		(0x40 * (n) + 0x1a)
-#define OMAP1_DMA_CDEI(n)		(0x40 * (n) + 0x1c)
-#define OMAP1_DMA_CDFI(n)		(0x40 * (n) + 0x1e)
-#define OMAP1_DMA_CLNK_CTRL(n)		(0x40 * (n) + 0x28)
-
-/* Common channel specific registers for omap2 */
-#define OMAP_DMA4_CH_BASE(n)		(0x60 * (n) + 0x80)
-#define OMAP_DMA4_CCR(n)		(0x60 * (n) + 0x80)
-#define OMAP_DMA4_CLNK_CTRL(n)		(0x60 * (n) + 0x84)
-#define OMAP_DMA4_CICR(n)		(0x60 * (n) + 0x88)
-#define OMAP_DMA4_CSR(n)		(0x60 * (n) + 0x8c)
-#define OMAP_DMA4_CSDP(n)		(0x60 * (n) + 0x90)
-#define OMAP_DMA4_CEN(n)		(0x60 * (n) + 0x94)
-#define OMAP_DMA4_CFN(n)		(0x60 * (n) + 0x98)
-#define OMAP_DMA4_CSEI(n)		(0x60 * (n) + 0xa4)
-#define OMAP_DMA4_CSFI(n)		(0x60 * (n) + 0xa8)
-#define OMAP_DMA4_CDEI(n)		(0x60 * (n) + 0xac)
-#define OMAP_DMA4_CDFI(n)		(0x60 * (n) + 0xb0)
-#define OMAP_DMA4_CSAC(n)		(0x60 * (n) + 0xb4)
-#define OMAP_DMA4_CDAC(n)		(0x60 * (n) + 0xb8)
-
-/* Channel specific registers only on omap1 */
-#define OMAP1_DMA_CSSA_L(n)		(0x40 * (n) + 0x08)
-#define OMAP1_DMA_CSSA_U(n)		(0x40 * (n) + 0x0a)
-#define OMAP1_DMA_CDSA_L(n)		(0x40 * (n) + 0x0c)
-#define OMAP1_DMA_CDSA_U(n)		(0x40 * (n) + 0x0e)
-#define OMAP1_DMA_COLOR_L(n)		(0x40 * (n) + 0x20)
-#define OMAP1_DMA_COLOR_U(n)		(0x40 * (n) + 0x22)
-#define OMAP1_DMA_CCR2(n)		(0x40 * (n) + 0x24)
-#define OMAP1_DMA_LCH_CTRL(n)		(0x40 * (n) + 0x2a)	/* not on 15xx */
-#define OMAP1_DMA_CCEN(n)		0
-#define OMAP1_DMA_CCFN(n)		0
-
-/* Channel specific registers only on omap2 */
-#define OMAP_DMA4_CSSA(n)		(0x60 * (n) + 0x9c)
-#define OMAP_DMA4_CDSA(n)		(0x60 * (n) + 0xa0)
-#define OMAP_DMA4_CCEN(n)		(0x60 * (n) + 0xbc)
-#define OMAP_DMA4_CCFN(n)		(0x60 * (n) + 0xc0)
-#define OMAP_DMA4_COLOR(n)		(0x60 * (n) + 0xc4)
-
-/* Additional registers available on OMAP4 */
-#define OMAP_DMA4_CDP(n)		(0x60 * (n) + 0xd0)
-#define OMAP_DMA4_CNDP(n)		(0x60 * (n) + 0xd4)
-#define OMAP_DMA4_CCDN(n)		(0x60 * (n) + 0xd8)
-
-/* Dummy defines to keep multi-omap compiles happy */
-#define OMAP1_DMA_REVISION		0
-#define OMAP1_DMA_IRQSTATUS_L0		0
-#define OMAP1_DMA_IRQENABLE_L0		0
-#define OMAP1_DMA_OCP_SYSCONFIG		0
-#define OMAP_DMA4_HW_ID			0
-#define OMAP_DMA4_CAPS_0_L		0
-#define OMAP_DMA4_CAPS_0_U		0
-#define OMAP_DMA4_CAPS_1_L		0
-#define OMAP_DMA4_CAPS_1_U		0
-#define OMAP_DMA4_GSCR			0
-#define OMAP_DMA4_CPC(n)		0
+#include <linux/platform_device.h>
 
-#define OMAP_DMA4_LCH_CTRL(n)		0
-#define OMAP_DMA4_COLOR_L(n)		0
-#define OMAP_DMA4_COLOR_U(n)		0
-#define OMAP_DMA4_CCR2(n)		0
-#define OMAP1_DMA_CSSA(n)		0
-#define OMAP1_DMA_CDSA(n)		0
-#define OMAP_DMA4_CSSA_L(n)		0
-#define OMAP_DMA4_CSSA_U(n)		0
-#define OMAP_DMA4_CDSA_L(n)		0
-#define OMAP_DMA4_CDSA_U(n)		0
-#define OMAP1_DMA_COLOR(n)		0
+/*
+ * TODO: These dma channel defines should go away once all
+ * the omap drivers hwmod adapted.
+ */
 
-/*----------------------------------------------------------------------------*/
+/* Move omap4 specific defines to dma-44xx.h */
+#include "dma-44xx.h"
 
 /* DMA channels for omap1 */
 #define OMAP_DMA_NO_DEVICE		0
@@ -405,6 +279,63 @@
 #define DMA_CH_PRIO_HIGH		0x1
 #define DMA_CH_PRIO_LOW			0x0 /* Def */
 
+/* Errata handling */
+#define IS_DMA_ERRATA(id)		(errata & (id))
+#define SET_DMA_ERRATA(id)		(errata |= (id))
+
+#define DMA_ERRATA_IFRAME_BUFFERING	BIT(0x0)
+#define DMA_ERRATA_PARALLEL_CHANNELS	BIT(0x1)
+#define DMA_ERRATA_i378			BIT(0x2)
+#define DMA_ERRATA_i541			BIT(0x3)
+#define DMA_ERRATA_i88			BIT(0x4)
+#define DMA_ERRATA_3_3			BIT(0x5)
+#define DMA_ROMCODE_BUG			BIT(0x6)
+
+/* Attributes for OMAP DMA Contrller */
+#define DMA_LINKED_LCH			BIT(0x0)
+#define GLOBAL_PRIORITY			BIT(0x1)
+#define RESERVE_CHANNEL			BIT(0x2)
+#define IS_CSSA_32			BIT(0x3)
+#define IS_CDSA_32			BIT(0x4)
+#define IS_RW_PRIORITY			BIT(0x5)
+#define ENABLE_1510_MODE		BIT(0x6)
+#define SRC_PORT			BIT(0x7)
+#define DST_PORT			BIT(0x8)
+#define SRC_INDEX			BIT(0x9)
+#define DST_INDEX			BIT(0xA)
+#define IS_BURST_ONLY4			BIT(0xB)
+#define CLEAR_CSR_ON_READ		BIT(0xC)
+#define IS_WORD_16			BIT(0xD)
+
+enum omap_reg_offsets {
+
+GCR,		GSCR,		GRST1,		HW_ID,
+PCH2_ID,	PCH0_ID,	PCH1_ID,	PCHG_ID,
+PCHD_ID,	CAPS_0,		CAPS_1,		CAPS_2,
+CAPS_3,		CAPS_4,		PCH2_SR,	PCH0_SR,
+PCH1_SR,	PCHD_SR,	REVISION,	IRQSTATUS_L0,
+IRQSTATUS_L1,	IRQSTATUS_L2,	IRQSTATUS_L3,	IRQENABLE_L0,
+IRQENABLE_L1,	IRQENABLE_L2,	IRQENABLE_L3,	SYSSTATUS,
+OCP_SYSCONFIG,
+
+/* omap1+ specific */
+CPC, CCR2, LCH_CTRL,
+
+/* Common registers for all omap's */
+CSDP,		CCR,		CICR,		CSR,
+CEN,		CFN,		CSFI,		CSEI,
+CSAC,		CDAC,		CDEI,
+CDFI,		CLNK_CTRL,
+
+/* Channel specific registers */
+CSSA,		CDSA,		COLOR,
+CCEN,		CCFN,
+
+/* omap3630 and omap4 specific */
+CDP,		CNDP,		CCDN,
+
+};
+
 enum omap_dma_burst_mode {
 	OMAP_DMA_DATA_BURST_DIS = 0,
 	OMAP_DMA_DATA_BURST_4,
@@ -470,6 +401,41 @@ struct omap_dma_channel_params {
 #endif
 };
 
+struct omap_dma_lch {
+	int next_lch;
+	int dev_id;
+	u16 saved_csr;
+	u16 enabled_irqs;
+	const char *dev_name;
+	void (*callback)(int lch, u16 ch_status, void *data);
+	void *data;
+	long flags;
+	/* required for Dynamic chaining */
+	int prev_linked_ch;
+	int next_linked_ch;
+	int state;
+	int chain_id;
+	int status;
+};
+
+struct omap_dma_dev_attr {
+	u32 dev_caps;
+	u16 lch_count;
+	u16 chan_count;
+	struct omap_dma_lch *chan;
+};
+
+/* System DMA platform data structure */
+struct omap_system_dma_plat_info {
+	struct omap_dma_dev_attr *dma_attr;
+	u32 errata;
+	void (*disable_irq_lch)(int lch);
+	void (*show_dma_caps)(void);
+	void (*clear_lch_regs)(int lch);
+	void (*clear_dma)(int lch);
+	void (*dma_write)(u32 val, int reg, int lch);
+	u32 (*dma_read)(int reg, int lch);
+};
 
 extern void omap_set_dma_priority(int lch, int dst_port, int priority);
 extern int omap_request_dma(int dev_id, const char *dev_name,
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-omap/include/plat/fpga.h linux-libre-2.6.38-gnu1/arch/arm/plat-omap/include/plat/fpga.h
--- linux-libre-2.6.37-gnu1/arch/arm/plat-omap/include/plat/fpga.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-omap/include/plat/fpga.h	2011-03-14 21:20:32.000000000 -0400
@@ -19,11 +19,7 @@
 #ifndef __ASM_ARCH_OMAP_FPGA_H
 #define __ASM_ARCH_OMAP_FPGA_H
 
-#if defined(CONFIG_MACH_OMAP_INNOVATOR) && defined(CONFIG_ARCH_OMAP15XX)
 extern void omap1510_fpga_init_irq(void);
-#else
-#define omap1510_fpga_init_irq()	(0)
-#endif
 
 #define fpga_read(reg)			__raw_readb(reg)
 #define fpga_write(val, reg)		__raw_writeb(val, reg)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-omap/include/plat/gpio.h linux-libre-2.6.38-gnu1/arch/arm/plat-omap/include/plat/gpio.h
--- linux-libre-2.6.37-gnu1/arch/arm/plat-omap/include/plat/gpio.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-omap/include/plat/gpio.h	2011-03-14 21:20:32.000000000 -0400
@@ -27,26 +27,15 @@
 #define __ASM_ARCH_OMAP_GPIO_H
 
 #include <linux/io.h>
+#include <linux/platform_device.h>
 #include <mach/irqs.h>
 
 #define OMAP1_MPUIO_BASE			0xfffb5000
 
-#if (defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850))
-
-#define OMAP_MPUIO_INPUT_LATCH		0x00
-#define OMAP_MPUIO_OUTPUT		0x02
-#define OMAP_MPUIO_IO_CNTL		0x04
-#define OMAP_MPUIO_KBR_LATCH		0x08
-#define OMAP_MPUIO_KBC			0x0a
-#define OMAP_MPUIO_GPIO_EVENT_MODE	0x0c
-#define OMAP_MPUIO_GPIO_INT_EDGE	0x0e
-#define OMAP_MPUIO_KBD_INT		0x10
-#define OMAP_MPUIO_GPIO_INT		0x12
-#define OMAP_MPUIO_KBD_MASKIT		0x14
-#define OMAP_MPUIO_GPIO_MASKIT		0x16
-#define OMAP_MPUIO_GPIO_DEBOUNCING	0x18
-#define OMAP_MPUIO_LATCH		0x1a
-#else
+/*
+ * These are the omap15xx/16xx offsets. The omap7xx offset are
+ * OMAP_MPUIO_ / 2 offsets below.
+ */
 #define OMAP_MPUIO_INPUT_LATCH		0x00
 #define OMAP_MPUIO_OUTPUT		0x04
 #define OMAP_MPUIO_IO_CNTL		0x08
@@ -60,7 +49,6 @@
 #define OMAP_MPUIO_GPIO_MASKIT		0x2c
 #define OMAP_MPUIO_GPIO_DEBOUNCING	0x30
 #define OMAP_MPUIO_LATCH		0x34
-#endif
 
 #define OMAP34XX_NR_GPIOS		6
 
@@ -71,8 +59,30 @@
 				 IH_MPUIO_BASE + ((nr) & 0x0f) : \
 				 IH_GPIO_BASE + (nr))
 
-extern int omap_gpio_init(void);	/* Call from board init only */
-extern void omap2_gpio_prepare_for_idle(int power_state);
+#define METHOD_MPUIO		0
+#define METHOD_GPIO_1510	1
+#define METHOD_GPIO_1610	2
+#define METHOD_GPIO_7XX		3
+#define METHOD_GPIO_24XX	5
+#define METHOD_GPIO_44XX	6
+
+struct omap_gpio_dev_attr {
+	int bank_width;		/* GPIO bank width */
+	bool dbck_flag;		/* dbck required or not - True for OMAP3&4 */
+};
+
+struct omap_gpio_platform_data {
+	u16 virtual_irq_start;
+	int bank_type;
+	int bank_width;		/* GPIO bank width */
+	int bank_stride;	/* Only needed for omap1 MPUIO */
+	bool dbck_flag;		/* dbck required or not - True for OMAP3&4 */
+};
+
+/* TODO: Analyze removing gpio_bank_count usage from driver code */
+extern int gpio_bank_count;
+
+extern void omap2_gpio_prepare_for_idle(int off_mode);
 extern void omap2_gpio_resume_after_idle(void);
 extern void omap_set_gpio_debounce(int gpio, int enable);
 extern void omap_set_gpio_debounce_time(int gpio, int enable);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-omap/include/plat/gpmc.h linux-libre-2.6.38-gnu1/arch/arm/plat-omap/include/plat/gpmc.h
--- linux-libre-2.6.37-gnu1/arch/arm/plat-omap/include/plat/gpmc.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-omap/include/plat/gpmc.h	2011-03-14 21:20:32.000000000 -0400
@@ -80,12 +80,12 @@
 #define GPMC_PREFETCH_STATUS_COUNT(val)	(val & 0x00003fff)
 
 /*
- * Note that all values in this struct are in nanoseconds, while
- * the register values are in gpmc_fck cycles.
+ * Note that all values in this struct are in nanoseconds except sync_clk
+ * (which is in picoseconds), while the register values are in gpmc_fck cycles.
  */
 struct gpmc_timings {
-	/* Minimum clock period for synchronous mode */
-	u16 sync_clk;
+	/* Minimum clock period for synchronous mode (in picoseconds) */
+	u32 sync_clk;
 
 	/* Chip-select signal timings corresponding to GPMC_CS_CONFIG2 */
 	u16 cs_on;		/* Assertion time */
@@ -117,6 +117,7 @@ struct gpmc_timings {
 };
 
 extern unsigned int gpmc_ns_to_ticks(unsigned int time_ns);
+extern unsigned int gpmc_ps_to_ticks(unsigned int time_ps);
 extern unsigned int gpmc_ticks_to_ns(unsigned int ticks);
 extern unsigned int gpmc_round_ns_to_ticks(unsigned int time_ns);
 extern unsigned long gpmc_get_fclk_period(void);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-omap/include/plat/i2c.h linux-libre-2.6.38-gnu1/arch/arm/plat-omap/include/plat/i2c.h
--- linux-libre-2.6.37-gnu1/arch/arm/plat-omap/include/plat/i2c.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-omap/include/plat/i2c.h	2011-03-14 21:20:32.000000000 -0400
@@ -36,6 +36,19 @@ static inline int omap_register_i2c_bus(
 }
 #endif
 
+/**
+ * i2c_dev_attr - OMAP I2C controller device attributes for omap_hwmod
+ * @fifo_depth: total controller FIFO size (in bytes)
+ * @flags: differences in hardware support capability
+ *
+ * @fifo_depth represents what exists on the hardware, not what is
+ * actually configured at runtime by the device driver.
+ */
+struct omap_i2c_dev_attr {
+	u8	fifo_depth;
+	u8	flags;
+};
+
 void __init omap1_i2c_mux_pins(int bus_id);
 void __init omap2_i2c_mux_pins(int bus_id);
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-omap/include/plat/io.h linux-libre-2.6.38-gnu1/arch/arm/plat-omap/include/plat/io.h
--- linux-libre-2.6.37-gnu1/arch/arm/plat-omap/include/plat/io.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-omap/include/plat/io.h	2011-03-14 21:20:32.000000000 -0400
@@ -291,11 +291,12 @@ static inline void omap44xx_map_common_i
 }
 #endif
 
-extern void omap2_init_common_hw(struct omap_sdrc_params *sdrc_cs0,
-				 struct omap_sdrc_params *sdrc_cs1);
+extern void omap2_init_common_infrastructure(void);
+extern void omap2_init_common_devices(struct omap_sdrc_params *sdrc_cs0,
+				      struct omap_sdrc_params *sdrc_cs1);
 
-#define __arch_ioremap(p,s,t)	omap_ioremap(p,s,t)
-#define __arch_iounmap(v)	omap_iounmap(v)
+#define __arch_ioremap	omap_ioremap
+#define __arch_iounmap	omap_iounmap
 
 void __iomem *omap_ioremap(unsigned long phys, size_t size, unsigned int type);
 void omap_iounmap(volatile void __iomem *addr);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-omap/include/plat/iommu.h linux-libre-2.6.38-gnu1/arch/arm/plat-omap/include/plat/iommu.h
--- linux-libre-2.6.37-gnu1/arch/arm/plat-omap/include/plat/iommu.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-omap/include/plat/iommu.h	2011-03-14 21:20:32.000000000 -0400
@@ -50,6 +50,8 @@ struct iommu {
 	int (*isr)(struct iommu *obj);
 
 	void *ctx; /* iommu context: registres saved area */
+	u32 da_start;
+	u32 da_end;
 };
 
 struct cr_regs {
@@ -103,6 +105,8 @@ struct iommu_platform_data {
 	const char *name;
 	const char *clk_name;
 	const int nr_tlb_entries;
+	u32 da_start;
+	u32 da_end;
 };
 
 #if defined(CONFIG_ARCH_OMAP1)
@@ -152,6 +156,7 @@ extern void flush_iotlb_all(struct iommu
 extern int iopgtable_store_entry(struct iommu *obj, struct iotlb_entry *e);
 extern size_t iopgtable_clear_entry(struct iommu *obj, u32 iova);
 
+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);
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-omap/include/plat/irqs.h linux-libre-2.6.38-gnu1/arch/arm/plat-omap/include/plat/irqs.h
--- linux-libre-2.6.37-gnu1/arch/arm/plat-omap/include/plat/irqs.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-omap/include/plat/irqs.h	2011-03-14 21:20:32.000000000 -0400
@@ -77,7 +77,7 @@
 /*
  * OMAP-1610 specific IRQ numbers for interrupt handler 1
  */
-#define INT_1610_IH2_IRQ	0
+#define INT_1610_IH2_IRQ	INT_1510_IH2_IRQ
 #define INT_1610_IH2_FIQ	2
 #define INT_1610_McBSP2_TX	4
 #define INT_1610_McBSP2_RX	5
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-omap/include/plat/keypad.h linux-libre-2.6.38-gnu1/arch/arm/plat-omap/include/plat/keypad.h
--- linux-libre-2.6.37-gnu1/arch/arm/plat-omap/include/plat/keypad.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-omap/include/plat/keypad.h	2011-03-14 21:20:32.000000000 -0400
@@ -10,16 +10,18 @@
 #ifndef ASMARM_ARCH_KEYPAD_H
 #define ASMARM_ARCH_KEYPAD_H
 
-#warning: Please update the board to use matrix_keypad.h instead
+#ifndef CONFIG_ARCH_OMAP1
+#warning Please update the board to use matrix-keypad driver
+#endif
+#include <linux/input/matrix_keypad.h>
 
 struct omap_kp_platform_data {
 	int rows;
 	int cols;
-	int *keymap;
-	unsigned int keymapsize;
-	unsigned int rep:1;
+	const struct matrix_keymap_data *keymap_data;
+	bool rep;
 	unsigned long delay;
-	unsigned int dbounce:1;
+	bool dbounce;
 	/* specific to OMAP242x*/
 	unsigned int *row_gpios;
 	unsigned int *col_gpios;
@@ -28,18 +30,21 @@ struct omap_kp_platform_data {
 /* Group (0..3) -- when multiple keys are pressed, only the
  * keys pressed in the same group are considered as pressed. This is
  * in order to workaround certain crappy HW designs that produce ghost
- * keypresses. */
-#define GROUP_0		(0 << 16)
-#define GROUP_1		(1 << 16)
-#define GROUP_2		(2 << 16)
-#define GROUP_3		(3 << 16)
+ * keypresses. Two free bits, not used by neither row/col nor keynum,
+ * must be available for use as group bits. The below GROUP_SHIFT
+ * macro definition is based on some prior knowledge of the
+ * matrix_keypad defined KEY() macro internals.
+ */
+#define GROUP_SHIFT	14
+#define GROUP_0		(0 << GROUP_SHIFT)
+#define GROUP_1		(1 << GROUP_SHIFT)
+#define GROUP_2		(2 << GROUP_SHIFT)
+#define GROUP_3		(3 << GROUP_SHIFT)
 #define GROUP_MASK	GROUP_3
+#if KEY_MAX & GROUP_MASK
+#error Group bits in conflict with keynum bits
+#endif
 
-#define KEY_PERSISTENT		0x00800000
-#define KEYNUM_MASK		0x00EFFFFF
-#define KEY(col, row, val) (((col) << 28) | ((row) << 24) | (val))
-#define PERSISTENT_KEY(col, row) (((col) << 28) | ((row) << 24) | \
-						KEY_PERSISTENT)
 
 #endif
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-omap/include/plat/l4_3xxx.h linux-libre-2.6.38-gnu1/arch/arm/plat-omap/include/plat/l4_3xxx.h
--- linux-libre-2.6.37-gnu1/arch/arm/plat-omap/include/plat/l4_3xxx.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-omap/include/plat/l4_3xxx.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,24 @@
+/*
+ * arch/arm/plat-omap/include/mach/l4_3xxx.h - L4 firewall definitions
+ *
+ * Copyright (C) 2009 Nokia Corporation
+ * Paul Walmsley
+ *
+ * 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 __ARCH_ARM_PLAT_OMAP_INCLUDE_MACH_L4_3XXX_H
+#define __ARCH_ARM_PLAT_OMAP_INCLUDE_MACH_L4_3XXX_H
+
+/* L4 CORE */
+#define OMAP3_L4_CORE_FW_I2C1_REGION				21
+#define OMAP3_L4_CORE_FW_I2C1_TA_REGION				22
+#define OMAP3_L4_CORE_FW_I2C2_REGION				23
+#define OMAP3_L4_CORE_FW_I2C2_TA_REGION				24
+#define OMAP3_L4_CORE_FW_I2C3_REGION				73
+#define OMAP3_L4_CORE_FW_I2C3_TA_REGION				74
+
+#endif
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-omap/include/plat/mailbox.h linux-libre-2.6.38-gnu1/arch/arm/plat-omap/include/plat/mailbox.h
--- linux-libre-2.6.37-gnu1/arch/arm/plat-omap/include/plat/mailbox.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-omap/include/plat/mailbox.h	2011-03-14 21:20:32.000000000 -0400
@@ -46,8 +46,8 @@ struct omap_mbox_queue {
 	struct kfifo		fifo;
 	struct work_struct	work;
 	struct tasklet_struct	tasklet;
-	int	(*callback)(void *);
 	struct omap_mbox	*mbox;
+	bool full;
 };
 
 struct omap_mbox {
@@ -57,13 +57,15 @@ struct omap_mbox {
 	struct omap_mbox_ops	*ops;
 	struct device		*dev;
 	void			*priv;
+	int			use_count;
+	struct blocking_notifier_head   notifier;
 };
 
 int omap_mbox_msg_send(struct omap_mbox *, mbox_msg_t msg);
 void omap_mbox_init_seq(struct omap_mbox *);
 
-struct omap_mbox *omap_mbox_get(const char *);
-void omap_mbox_put(struct omap_mbox *);
+struct omap_mbox *omap_mbox_get(const char *, struct notifier_block *nb);
+void omap_mbox_put(struct omap_mbox *mbox, struct notifier_block *nb);
 
 int omap_mbox_register(struct device *parent, struct omap_mbox **);
 int omap_mbox_unregister(void);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-omap/include/plat/memory.h linux-libre-2.6.38-gnu1/arch/arm/plat-omap/include/plat/memory.h
--- linux-libre-2.6.37-gnu1/arch/arm/plat-omap/include/plat/memory.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-omap/include/plat/memory.h	2011-03-14 21:20:32.000000000 -0400
@@ -61,17 +61,17 @@
 #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_page_to_dma(dev, page)	\
-	({ dma_addr_t __dma = page_to_phys(page); \
+#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_page(dev, addr)	\
+#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_page(__dma);					\
+	   __phys_to_pfn(__dma);				\
 	})
 
 #define __arch_dma_to_virt(dev, addr)	({ (void *) (is_lbus_device(dev) ? \
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-omap/include/plat/omap44xx.h linux-libre-2.6.38-gnu1/arch/arm/plat-omap/include/plat/omap44xx.h
--- linux-libre-2.6.37-gnu1/arch/arm/plat-omap/include/plat/omap44xx.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-omap/include/plat/omap44xx.h	2011-03-14 21:20:32.000000000 -0400
@@ -52,5 +52,10 @@
 #define OMAP4_MMU1_BASE			0x55082000
 #define OMAP4_MMU2_BASE			0x4A066000
 
+#define OMAP44XX_USBTLL_BASE		(L4_44XX_BASE + 0x62000)
+#define OMAP44XX_UHH_CONFIG_BASE	(L4_44XX_BASE + 0x64000)
+#define OMAP44XX_HSUSB_OHCI_BASE	(L4_44XX_BASE + 0x64800)
+#define OMAP44XX_HSUSB_EHCI_BASE	(L4_44XX_BASE + 0x64C00)
+
 #endif /* __ASM_ARCH_OMAP44XX_H */
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-omap/include/plat/omap_device.h linux-libre-2.6.38-gnu1/arch/arm/plat-omap/include/plat/omap_device.h
--- linux-libre-2.6.37-gnu1/arch/arm/plat-omap/include/plat/omap_device.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-omap/include/plat/omap_device.h	2011-03-14 21:20:32.000000000 -0400
@@ -107,6 +107,7 @@ void __iomem *omap_device_get_rt_va(stru
 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);
 
 /* Other */
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-omap/include/plat/omap_hwmod.h linux-libre-2.6.38-gnu1/arch/arm/plat-omap/include/plat/omap_hwmod.h
--- linux-libre-2.6.37-gnu1/arch/arm/plat-omap/include/plat/omap_hwmod.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-omap/include/plat/omap_hwmod.h	2011-03-14 21:20:32.000000000 -0400
@@ -23,7 +23,7 @@
  * - add pinmuxing
  * - init_conn_id_bit (CONNID_BIT_VECTOR)
  * - implement default hwmod SMS/SDRC flags?
- * - remove unused fields
+ * - move Linux-specific data ("non-ROM data") out
  *
  */
 #ifndef __ARCH_ARM_PLAT_OMAP_INCLUDE_MACH_OMAP_HWMOD_H
@@ -32,8 +32,9 @@
 #include <linux/kernel.h>
 #include <linux/list.h>
 #include <linux/ioport.h>
-#include <linux/mutex.h>
+#include <linux/spinlock.h>
 #include <plat/cpu.h>
+#include <plat/voltage.h>
 
 struct omap_device;
 
@@ -76,6 +77,20 @@ extern struct omap_hwmod_sysc_fields oma
 #define HWMOD_IDLEMODE_FORCE		(1 << 0)
 #define HWMOD_IDLEMODE_NO		(1 << 1)
 #define HWMOD_IDLEMODE_SMART		(1 << 2)
+/* Slave idle mode flag only */
+#define HWMOD_IDLEMODE_SMART_WKUP	(1 << 3)
+
+/**
+ * struct omap_hwmod_mux_info - hwmod specific mux configuration
+ * @pads:              array of omap_device_pad entries
+ * @nr_pads:           number of omap_device_pad entries
+ *
+ * Note that this is currently built during init as needed.
+ */
+struct omap_hwmod_mux_info {
+	int				nr_pads;
+	struct omap_device_pad		*pads;
+};
 
 /**
  * struct omap_hwmod_irq_info - MPU IRQs used by the hwmod
@@ -159,7 +174,7 @@ struct omap_hwmod_omap2_firewall {
  * ADDR_MAP_ON_INIT: Map this address space during omap_hwmod init.
  * ADDR_TYPE_RT: Address space contains module register target data.
  */
-#define ADDR_MAP_ON_INIT	(1 << 0)
+#define ADDR_MAP_ON_INIT	(1 << 0)	/* XXX does not belong */
 #define ADDR_TYPE_RT		(1 << 1)
 
 /**
@@ -200,8 +215,6 @@ struct omap_hwmod_addr_space {
  * @fw: interface firewall data
  * @addr_cnt: ARRAY_SIZE(@addr)
  * @width: OCP data width
- * @thread_cnt: number of threads
- * @max_burst_len: maximum burst length in @width sized words (0 if unlimited)
  * @user: initiators using this interface (see OCP_USER_* macros above)
  * @flags: OCP interface flags (see OCPIF_* macros above)
  *
@@ -221,8 +234,6 @@ struct omap_hwmod_ocp_if {
 	}				fw;
 	u8				addr_cnt;
 	u8				width;
-	u8				thread_cnt;
-	u8				max_burst_len;
 	u8				user;
 	u8				flags;
 };
@@ -231,11 +242,12 @@ struct omap_hwmod_ocp_if {
 /* Macros for use in struct omap_hwmod_sysconfig */
 
 /* Flags for use in omap_hwmod_sysconfig.idlemodes */
-#define MASTER_STANDBY_SHIFT	2
+#define MASTER_STANDBY_SHIFT	4
 #define SLAVE_IDLE_SHIFT	0
 #define SIDLE_FORCE		(HWMOD_IDLEMODE_FORCE << SLAVE_IDLE_SHIFT)
 #define SIDLE_NO		(HWMOD_IDLEMODE_NO << SLAVE_IDLE_SHIFT)
 #define SIDLE_SMART		(HWMOD_IDLEMODE_SMART << SLAVE_IDLE_SHIFT)
+#define SIDLE_SMART_WKUP	(HWMOD_IDLEMODE_SMART_WKUP << SLAVE_IDLE_SHIFT)
 #define MSTANDBY_FORCE		(HWMOD_IDLEMODE_FORCE << MASTER_STANDBY_SHIFT)
 #define MSTANDBY_NO		(HWMOD_IDLEMODE_NO << MASTER_STANDBY_SHIFT)
 #define MSTANDBY_SMART		(HWMOD_IDLEMODE_SMART << MASTER_STANDBY_SHIFT)
@@ -339,7 +351,7 @@ struct omap_hwmod_omap2_prcm {
 /**
  * struct omap_hwmod_omap4_prcm - OMAP4-specific PRCM data
  * @clkctrl_reg: PRCM address of the clock control register
- * @rstctrl_reg: adress of the XXX_RSTCTRL register located in the PRM
+ * @rstctrl_reg: address of the XXX_RSTCTRL register located in the PRM
  * @submodule_wkdep_bit: bit shift of the WKDEP range
  */
 struct omap_hwmod_omap4_prcm {
@@ -357,14 +369,14 @@ struct omap_hwmod_omap4_prcm {
  * HWMOD_SWSUP_MSTDBY: omap_hwmod code should manually bring module in and out
  *     of standby, rather than relying on module smart-standby
  * HWMOD_INIT_NO_RESET: don't reset this module at boot - important for
- *     SDRAM controller, etc.
+ *     SDRAM controller, etc. XXX probably belongs outside the main hwmod file
  * HWMOD_INIT_NO_IDLE: don't idle this module at boot - important for SDRAM
- *     controller, etc.
+ *     controller, etc. XXX probably belongs outside the main hwmod file
  * HWMOD_NO_AUTOIDLE: disable module autoidle (OCP_SYSCONFIG.AUTOIDLE)
  *     when module is enabled, rather than the default, which is to
  *     enable autoidle
  * HWMOD_SET_DEFAULT_CLOCKACT: program CLOCKACTIVITY bits at startup
- * HWMOD_NO_IDLEST : this module does not have idle status - this is the case
+ * HWMOD_NO_IDLEST: this module does not have idle status - this is the case
  *     only for few initiator modules on OMAP2 & 3.
  * HWMOD_CONTROL_OPT_CLKS_IN_RESET: Enable all optional clocks during reset.
  *     This is needed for devices like DSS that require optional clocks enabled
@@ -415,14 +427,31 @@ struct omap_hwmod_omap4_prcm {
  * @name: name of the hwmod_class
  * @sysc: device SYSCONFIG/SYSSTATUS register data
  * @rev: revision of the IP class
+ * @pre_shutdown: ptr to fn to be executed immediately prior to device shutdown
+ * @reset: ptr to fn to be executed in place of the standard hwmod reset fn
  *
  * Represent the class of a OMAP hardware "modules" (e.g. timer,
  * smartreflex, gpio, uart...)
+ *
+ * @pre_shutdown is a function that will be run immediately before
+ * hwmod clocks are disabled, etc.  It is intended for use for hwmods
+ * like the MPU watchdog, which cannot be disabled with the standard
+ * omap_hwmod_shutdown().  The function should return 0 upon success,
+ * or some negative error upon failure.  Returning an error will cause
+ * omap_hwmod_shutdown() to abort the device shutdown and return an
+ * error.
+ *
+ * If @reset is defined, then the function it points to will be
+ * executed in place of the standard hwmod _reset() code in
+ * mach-omap2/omap_hwmod.c.  This is needed for IP blocks which have
+ * unusual reset sequences - usually processor IP blocks like the IVA.
  */
 struct omap_hwmod_class {
 	const char				*name;
 	struct omap_hwmod_class_sysconfig	*sysc;
 	u32					rev;
+	int					(*pre_shutdown)(struct omap_hwmod *oh);
+	int					(*reset)(struct omap_hwmod *oh);
 };
 
 /**
@@ -436,14 +465,14 @@ struct omap_hwmod_class {
  * @main_clk: main clock: OMAP clock name
  * @_clk: pointer to the main struct clk (filled in at runtime)
  * @opt_clks: other device clocks that drivers can request (0..*)
+ * @vdd_name: voltage domain name
+ * @voltdm: pointer to voltage domain (filled in at runtime)
  * @masters: ptr to array of OCP ifs that this hwmod can initiate on
  * @slaves: ptr to array of OCP ifs that this hwmod can respond on
  * @dev_attr: arbitrary device attributes that can be passed to the driver
  * @_sysc_cache: internal-use hwmod flags
  * @_mpu_rt_va: cached register target start address (internal use)
  * @_mpu_port_index: cached MPU register target slave ID (internal use)
- * @msuspendmux_reg_id: CONTROL_MSUSPENDMUX register ID (1-6)
- * @msuspendmux_shift: CONTROL_MSUSPENDMUX register bit shift
  * @mpu_irqs_cnt: number of @mpu_irqs
  * @sdma_reqs_cnt: number of @sdma_reqs
  * @opt_clks_cnt: number of @opt_clks
@@ -452,9 +481,10 @@ struct omap_hwmod_class {
  * @response_lat: device OCP response latency (in interface clock cycles)
  * @_int_flags: internal-use hwmod flags
  * @_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
- * @_mutex: mutex serializing operations on this hwmod
+ * @_lock: spinlock serializing operations on this hwmod
  * @node: list node for hwmod list (internal use)
  *
  * @main_clk refers to this module's "main clock," which for our
@@ -469,6 +499,7 @@ struct omap_hwmod {
 	const char			*name;
 	struct omap_hwmod_class		*class;
 	struct omap_device		*od;
+	struct omap_hwmod_mux_info	*mux;
 	struct omap_hwmod_irq_info	*mpu_irqs;
 	struct omap_hwmod_dma_info	*sdma_reqs;
 	struct omap_hwmod_rst_info	*rst_lines;
@@ -479,17 +510,17 @@ struct omap_hwmod {
 	const char			*main_clk;
 	struct clk			*_clk;
 	struct omap_hwmod_opt_clk	*opt_clks;
+	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;
 	u32				_sysc_cache;
 	void __iomem			*_mpu_rt_va;
-	struct mutex			_mutex;
+	spinlock_t			_lock;
 	struct list_head		node;
 	u16				flags;
 	u8				_mpu_port_index;
-	u8				msuspendmux_reg_id;
-	u8				msuspendmux_shift;
 	u8				response_lat;
 	u8				mpu_irqs_cnt;
 	u8				sdma_reqs_cnt;
@@ -500,16 +531,15 @@ struct omap_hwmod {
 	u8				hwmods_cnt;
 	u8				_int_flags;
 	u8				_state;
+	u8				_postsetup_state;
 	const struct omap_chip_id	omap_chip;
 };
 
 int omap_hwmod_init(struct omap_hwmod **ohs);
-int omap_hwmod_register(struct omap_hwmod *oh);
-int omap_hwmod_unregister(struct omap_hwmod *oh);
 struct omap_hwmod *omap_hwmod_lookup(const char *name);
 int omap_hwmod_for_each(int (*fn)(struct omap_hwmod *oh, void *data),
 			void *data);
-int omap_hwmod_late_init(u8 skip_setup_idle);
+int omap_hwmod_late_init(void);
 
 int omap_hwmod_enable(struct omap_hwmod *oh);
 int _omap_hwmod_enable(struct omap_hwmod *oh);
@@ -556,6 +586,9 @@ int omap_hwmod_for_each_by_class(const c
 					   void *user),
 				 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);
+
 /*
  * Chip variant-specific hwmod init routines - XXX should be converted
  * to use initcalls once the initial boot ordering is straightened out
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-omap/include/plat/omap-pm.h linux-libre-2.6.38-gnu1/arch/arm/plat-omap/include/plat/omap-pm.h
--- linux-libre-2.6.37-gnu1/arch/arm/plat-omap/include/plat/omap-pm.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-omap/include/plat/omap-pm.h	2011-03-14 21:20:32.000000000 -0400
@@ -17,26 +17,7 @@
 #include <linux/device.h>
 #include <linux/cpufreq.h>
 #include <linux/clk.h>
-
-#include "powerdomain.h"
-
-/**
- * struct omap_opp - clock frequency-to-OPP ID table for DSP, MPU
- * @rate: target clock rate
- * @opp_id: OPP ID
- * @min_vdd: minimum VDD1 voltage (in millivolts) for this OPP
- *
- * Operating performance point data.  Can vary by OMAP chip and board.
- */
-struct omap_opp {
-	unsigned long rate;
-	u8 opp_id;
-	u16 min_vdd;
-};
-
-extern struct omap_opp *mpu_opps;
-extern struct omap_opp *dsp_opps;
-extern struct omap_opp *l3_opps;
+#include <linux/opp.h>
 
 /*
  * agent_id values for use with omap_pm_set_min_bus_tput():
@@ -59,9 +40,11 @@ extern struct omap_opp *l3_opps;
  * framework starts.  The "_if_" is to avoid name collisions with the
  * PM idle-loop code.
  */
-int __init omap_pm_if_early_init(struct omap_opp *mpu_opp_table,
-				 struct omap_opp *dsp_opp_table,
-				 struct omap_opp *l3_opp_table);
+#ifdef CONFIG_OMAP_PM_NONE
+#define omap_pm_if_early_init() 0
+#else
+int __init omap_pm_if_early_init(void);
+#endif
 
 /**
  * omap_pm_if_init - OMAP PM init code called after clock fw init
@@ -69,7 +52,11 @@ int __init omap_pm_if_early_init(struct
  * The main initialization code.  OPP tables are passed in here.  The
  * "_if_" is to avoid name collisions with the PM idle-loop code.
  */
+#ifdef CONFIG_OMAP_PM_NONE
+#define omap_pm_if_init() 0
+#else
 int __init omap_pm_if_init(void);
+#endif
 
 /**
  * omap_pm_if_exit - OMAP PM exit code
@@ -363,9 +350,11 @@ 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 -EINVAL upon error.
+ * or zero upon error.
  */
-int omap_pm_get_dev_context_loss_count(struct device *dev);
+u32 omap_pm_get_dev_context_loss_count(struct device *dev);
 
+void omap_pm_enable_off_mode(void);
+void omap_pm_disable_off_mode(void);
 
 #endif
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-omap/include/plat/omap-serial.h linux-libre-2.6.38-gnu1/arch/arm/plat-omap/include/plat/omap-serial.h
--- linux-libre-2.6.37-gnu1/arch/arm/plat-omap/include/plat/omap-serial.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-omap/include/plat/omap-serial.h	2011-03-14 21:20:32.000000000 -0400
@@ -22,7 +22,7 @@
 
 #include <plat/mux.h>
 
-#define DRIVER_NAME	"omap-hsuart"
+#define DRIVER_NAME	"omap_uart"
 
 /*
  * Use tty device name as ttyO, [O -> OMAP]
@@ -31,20 +31,8 @@
  */
 #define OMAP_SERIAL_NAME	"ttyO"
 
-#define OMAP_MDR1_DISABLE	0x07
-#define OMAP_MDR1_MODE13X	0x03
-#define OMAP_MDR1_MODE16X	0x00
 #define OMAP_MODE13X_SPEED	230400
 
-/*
- * LCR = 0XBF: Switch to Configuration Mode B.
- * In configuration mode b allow access
- * to EFR,DLL,DLH.
- * Reference OMAP TRM Chapter 17
- * Section: 1.4.3 Mode Selection
- */
-#define OMAP_UART_LCR_CONF_MDB	0XBF
-
 /* WER = 0x7F
  * Enable module level wakeup in WER reg
  */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-omap/include/plat/onenand.h linux-libre-2.6.38-gnu1/arch/arm/plat-omap/include/plat/onenand.h
--- linux-libre-2.6.37-gnu1/arch/arm/plat-omap/include/plat/onenand.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-omap/include/plat/onenand.h	2011-03-14 21:20:32.000000000 -0400
@@ -23,6 +23,7 @@ struct omap_onenand_platform_data {
 	int                     (*onenand_setup)(void __iomem *, int freq);
 	int			dma_channel;
 	u8			flags;
+	u8			regulator_can_sleep;
 };
 
 #define ONENAND_MAX_PARTITIONS 8
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-omap/include/plat/panel-generic-dpi.h linux-libre-2.6.38-gnu1/arch/arm/plat-omap/include/plat/panel-generic-dpi.h
--- linux-libre-2.6.37-gnu1/arch/arm/plat-omap/include/plat/panel-generic-dpi.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-omap/include/plat/panel-generic-dpi.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,37 @@
+/*
+ * Header for generic DPI panel driver
+ *
+ * Copyright (C) 2010 Canonical Ltd.
+ * Author: Bryan Wu <bryan.wu@canonical.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.
+ *
+ * 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_PLAT_OMAP_PANEL_GENERIC_DPI_H
+#define __ARCH_ARM_PLAT_OMAP_PANEL_GENERIC_DPI_H
+
+#include "display.h"
+
+/**
+ * struct panel_generic_dpi_data - panel driver configuration data
+ * @name: panel name
+ * @platform_enable: platform specific panel enable function
+ * @platform_disable: platform specific panel disable function
+ */
+struct panel_generic_dpi_data {
+	const char *name;
+	int (*platform_enable)(struct omap_dss_device *dssdev);
+	void (*platform_disable)(struct omap_dss_device *dssdev);
+};
+
+#endif /* __ARCH_ARM_PLAT_OMAP_PANEL_GENERIC_DPI_H */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-omap/include/plat/powerdomain.h linux-libre-2.6.38-gnu1/arch/arm/plat-omap/include/plat/powerdomain.h
--- linux-libre-2.6.37-gnu1/arch/arm/plat-omap/include/plat/powerdomain.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-omap/include/plat/powerdomain.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,167 +0,0 @@
-/*
- * OMAP2/3 powerdomain control
- *
- * Copyright (C) 2007-2008 Texas Instruments, Inc.
- * Copyright (C) 2007-2009 Nokia Corporation
- *
- * Written by Paul Walmsley
- *
- * This program is free software; you can 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_OMAP_POWERDOMAIN
-#define ASM_ARM_ARCH_OMAP_POWERDOMAIN
-
-#include <linux/types.h>
-#include <linux/list.h>
-
-#include <asm/atomic.h>
-
-#include <plat/cpu.h>
-
-
-/* Powerdomain basic power states */
-#define PWRDM_POWER_OFF		0x0
-#define PWRDM_POWER_RET		0x1
-#define PWRDM_POWER_INACTIVE	0x2
-#define PWRDM_POWER_ON		0x3
-
-#define PWRDM_MAX_PWRSTS	4
-
-/* Powerdomain allowable state bitfields */
-#define PWRSTS_ON		(1 << PWRDM_POWER_ON)
-#define PWRSTS_OFF		(1 << PWRDM_POWER_OFF)
-#define PWRSTS_OFF_ON		((1 << PWRDM_POWER_OFF) | \
-				 (1 << PWRDM_POWER_ON))
-
-#define PWRSTS_OFF_RET		((1 << PWRDM_POWER_OFF) | \
-				 (1 << PWRDM_POWER_RET))
-
-#define PWRSTS_RET_ON		((1 << PWRDM_POWER_RET) | \
-				 (1 << PWRDM_POWER_ON))
-
-#define PWRSTS_OFF_RET_ON	(PWRSTS_OFF_RET | (1 << PWRDM_POWER_ON))
-
-
-/* Powerdomain flags */
-#define PWRDM_HAS_HDWR_SAR	(1 << 0) /* hardware save-and-restore support */
-#define PWRDM_HAS_MPU_QUIRK	(1 << 1) /* MPU pwr domain has MEM bank 0 bits
-					  * in MEM bank 1 position. This is
-					  * true for OMAP3430
-					  */
-#define PWRDM_HAS_LOWPOWERSTATECHANGE	(1 << 2) /*
-						  * support to transition from a
-						  * sleep state to a lower sleep
-						  * state without waking up the
-						  * powerdomain
-						  */
-
-/*
- * Number of memory banks that are power-controllable.	On OMAP4430, the
- * maximum is 5.
- */
-#define PWRDM_MAX_MEM_BANKS	5
-
-/*
- * Maximum number of clockdomains that can be associated with a powerdomain.
- * CORE powerdomain on OMAP4 is the worst case
- */
-#define PWRDM_MAX_CLKDMS	9
-
-/* XXX A completely arbitrary number. What is reasonable here? */
-#define PWRDM_TRANSITION_BAILOUT 100000
-
-struct clockdomain;
-struct powerdomain;
-
-/**
- * struct powerdomain - OMAP powerdomain
- * @name: Powerdomain name
- * @omap_chip: represents the OMAP chip types containing this pwrdm
- * @prcm_offs: the address offset from CM_BASE/PRM_BASE
- * @pwrsts: Possible powerdomain power states
- * @pwrsts_logic_ret: Possible logic power states when pwrdm in RETENTION
- * @flags: Powerdomain flags
- * @banks: Number of software-controllable memory banks in this powerdomain
- * @pwrsts_mem_ret: Possible memory bank pwrstates when pwrdm in RETENTION
- * @pwrsts_mem_on: Possible memory bank pwrstates when pwrdm in ON
- * @pwrdm_clkdms: Clockdomains in this powerdomain
- * @node: list_head linking all powerdomains
- * @state:
- * @state_counter:
- * @timer:
- * @state_timer:
- */
-struct powerdomain {
-	const char *name;
-	const struct omap_chip_id omap_chip;
-	const s16 prcm_offs;
-	const u8 pwrsts;
-	const u8 pwrsts_logic_ret;
-	const u8 flags;
-	const u8 banks;
-	const u8 pwrsts_mem_ret[PWRDM_MAX_MEM_BANKS];
-	const u8 pwrsts_mem_on[PWRDM_MAX_MEM_BANKS];
-	struct clockdomain *pwrdm_clkdms[PWRDM_MAX_CLKDMS];
-	struct list_head node;
-	int state;
-	unsigned state_counter[PWRDM_MAX_PWRSTS];
-	unsigned ret_logic_off_counter;
-	unsigned ret_mem_off_counter[PWRDM_MAX_MEM_BANKS];
-
-#ifdef CONFIG_PM_DEBUG
-	s64 timer;
-	s64 state_timer[PWRDM_MAX_PWRSTS];
-#endif
-};
-
-
-void pwrdm_init(struct powerdomain **pwrdm_list);
-
-struct powerdomain *pwrdm_lookup(const char *name);
-
-int pwrdm_for_each(int (*fn)(struct powerdomain *pwrdm, void *user),
-			void *user);
-int pwrdm_for_each_nolock(int (*fn)(struct powerdomain *pwrdm, void *user),
-			void *user);
-
-int pwrdm_add_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm);
-int pwrdm_del_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm);
-int pwrdm_for_each_clkdm(struct powerdomain *pwrdm,
-			 int (*fn)(struct powerdomain *pwrdm,
-				   struct clockdomain *clkdm));
-
-int pwrdm_get_mem_bank_count(struct powerdomain *pwrdm);
-
-int pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst);
-int pwrdm_read_next_pwrst(struct powerdomain *pwrdm);
-int pwrdm_read_pwrst(struct powerdomain *pwrdm);
-int pwrdm_read_prev_pwrst(struct powerdomain *pwrdm);
-int pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm);
-
-int pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst);
-int pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank, u8 pwrst);
-int pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 bank, u8 pwrst);
-
-int pwrdm_read_logic_pwrst(struct powerdomain *pwrdm);
-int pwrdm_read_prev_logic_pwrst(struct powerdomain *pwrdm);
-int pwrdm_read_logic_retst(struct powerdomain *pwrdm);
-int pwrdm_read_mem_pwrst(struct powerdomain *pwrdm, u8 bank);
-int pwrdm_read_prev_mem_pwrst(struct powerdomain *pwrdm, u8 bank);
-int pwrdm_read_mem_retst(struct powerdomain *pwrdm, u8 bank);
-
-int pwrdm_enable_hdwr_sar(struct powerdomain *pwrdm);
-int pwrdm_disable_hdwr_sar(struct powerdomain *pwrdm);
-bool pwrdm_has_hdwr_sar(struct powerdomain *pwrdm);
-
-int pwrdm_wait_transition(struct powerdomain *pwrdm);
-
-int pwrdm_state_switch(struct powerdomain *pwrdm);
-int pwrdm_clkdm_state_switch(struct clockdomain *clkdm);
-int pwrdm_pre_transition(void);
-int pwrdm_post_transition(void);
-int pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm);
-
-#endif
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-omap/include/plat/prcm.h linux-libre-2.6.38-gnu1/arch/arm/plat-omap/include/plat/prcm.h
--- linux-libre-2.6.37-gnu1/arch/arm/plat-omap/include/plat/prcm.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-omap/include/plat/prcm.h	2011-03-14 21:20:32.000000000 -0400
@@ -18,6 +18,10 @@
  * 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
+ *
+ * XXX This file is deprecated.  The PRCM is an OMAP2+-only subsystem,
+ * so this file doesn't belong in plat-omap/include/plat.  Please
+ * do not add anything new to this file.
  */
 
 #ifndef __ASM_ARM_ARCH_OMAP_PRCM_H
@@ -28,22 +32,6 @@ void omap_prcm_arch_reset(char mode, con
 int omap2_cm_wait_idlest(void __iomem *reg, u32 mask, u8 idlest,
 			 const char *name);
 
-#define START_PADCONF_SAVE 0x2
-#define PADCONF_SAVE_DONE  0x1
-
-void omap3_prcm_save_context(void);
-void omap3_prcm_restore_context(void);
-
-u32 prm_read_mod_reg(s16 module, u16 idx);
-void prm_write_mod_reg(u32 val, s16 module, u16 idx);
-u32 prm_rmw_mod_reg_bits(u32 mask, u32 bits, s16 module, s16 idx);
-u32 prm_read_mod_bits_shift(s16 domain, s16 idx, u32 mask);
-u32 omap4_prm_read_bits_shift(void __iomem *reg, u32 mask);
-u32 omap4_prm_rmw_reg_bits(u32 mask, u32 bits, void __iomem *reg);
-u32 cm_read_mod_reg(s16 module, u16 idx);
-void cm_write_mod_reg(u32 val, s16 module, u16 idx);
-u32 cm_rmw_mod_reg_bits(u32 mask, u32 bits, s16 module, s16 idx);
-
 #endif
 
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-omap/include/plat/serial.h linux-libre-2.6.38-gnu1/arch/arm/plat-omap/include/plat/serial.h
--- linux-libre-2.6.37-gnu1/arch/arm/plat-omap/include/plat/serial.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-omap/include/plat/serial.h	2011-03-14 21:20:32.000000000 -0400
@@ -93,9 +93,12 @@
 			})
 
 #ifndef __ASSEMBLER__
+
+struct omap_board_data;
+
 extern void __init omap_serial_early_init(void);
 extern void omap_serial_init(void);
-extern void omap_serial_init_port(int port);
+extern void omap_serial_init_port(struct omap_board_data *bdata);
 extern int omap_uart_can_sleep(void);
 extern void omap_uart_check_wakeup(void);
 extern void omap_uart_prepare_suspend(void);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-omap/include/plat/smartreflex.h linux-libre-2.6.38-gnu1/arch/arm/plat-omap/include/plat/smartreflex.h
--- linux-libre-2.6.37-gnu1/arch/arm/plat-omap/include/plat/smartreflex.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-omap/include/plat/smartreflex.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,245 @@
+/*
+ * OMAP Smartreflex Defines and Routines
+ *
+ * Author: Thara Gopinath	<thara@ti.com>
+ *
+ * Copyright (C) 2010 Texas Instruments, Inc.
+ * Thara Gopinath <thara@ti.com>
+ *
+ * Copyright (C) 2008 Nokia Corporation
+ * Kalle Jokiniemi
+ *
+ * Copyright (C) 2007 Texas Instruments, Inc.
+ * Lesly A M <x0080970@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.
+ */
+
+#ifndef __ASM_ARM_OMAP_SMARTREFLEX_H
+#define __ASM_ARM_OMAP_SMARTREFLEX_H
+
+#include <linux/platform_device.h>
+#include <plat/voltage.h>
+
+/*
+ * Different Smartreflex IPs version. The v1 is the 65nm version used in
+ * OMAP3430. The v2 is the update for the 45nm version of the IP
+ * used in OMAP3630 and OMAP4430
+ */
+#define SR_TYPE_V1	1
+#define SR_TYPE_V2	2
+
+/* SMART REFLEX REG ADDRESS OFFSET */
+#define SRCONFIG		0x00
+#define SRSTATUS		0x04
+#define SENVAL			0x08
+#define SENMIN			0x0C
+#define SENMAX			0x10
+#define SENAVG			0x14
+#define AVGWEIGHT		0x18
+#define NVALUERECIPROCAL	0x1c
+#define SENERROR_V1		0x20
+#define ERRCONFIG_V1		0x24
+#define IRQ_EOI			0x20
+#define IRQSTATUS_RAW		0x24
+#define IRQSTATUS		0x28
+#define IRQENABLE_SET		0x2C
+#define IRQENABLE_CLR		0x30
+#define SENERROR_V2		0x34
+#define ERRCONFIG_V2		0x38
+
+/* Bit/Shift Positions */
+
+/* SRCONFIG */
+#define SRCONFIG_ACCUMDATA_SHIFT	22
+#define SRCONFIG_SRCLKLENGTH_SHIFT	12
+#define SRCONFIG_SENNENABLE_V1_SHIFT	5
+#define SRCONFIG_SENPENABLE_V1_SHIFT	3
+#define SRCONFIG_SENNENABLE_V2_SHIFT	1
+#define SRCONFIG_SENPENABLE_V2_SHIFT	0
+#define SRCONFIG_CLKCTRL_SHIFT		0
+
+#define SRCONFIG_ACCUMDATA_MASK		(0x3ff << 22)
+
+#define SRCONFIG_SRENABLE		BIT(11)
+#define SRCONFIG_SENENABLE		BIT(10)
+#define SRCONFIG_ERRGEN_EN		BIT(9)
+#define SRCONFIG_MINMAXAVG_EN		BIT(8)
+#define SRCONFIG_DELAYCTRL		BIT(2)
+
+/* AVGWEIGHT */
+#define AVGWEIGHT_SENPAVGWEIGHT_SHIFT	2
+#define AVGWEIGHT_SENNAVGWEIGHT_SHIFT	0
+
+/* NVALUERECIPROCAL */
+#define NVALUERECIPROCAL_SENPGAIN_SHIFT	20
+#define NVALUERECIPROCAL_SENNGAIN_SHIFT	16
+#define NVALUERECIPROCAL_RNSENP_SHIFT	8
+#define NVALUERECIPROCAL_RNSENN_SHIFT	0
+
+/* ERRCONFIG */
+#define ERRCONFIG_ERRWEIGHT_SHIFT	16
+#define ERRCONFIG_ERRMAXLIMIT_SHIFT	8
+#define ERRCONFIG_ERRMINLIMIT_SHIFT	0
+
+#define SR_ERRWEIGHT_MASK		(0x07 << 16)
+#define SR_ERRMAXLIMIT_MASK		(0xff << 8)
+#define SR_ERRMINLIMIT_MASK		(0xff << 0)
+
+#define ERRCONFIG_VPBOUNDINTEN_V1	BIT(31)
+#define ERRCONFIG_VPBOUNDINTST_V1	BIT(30)
+#define	ERRCONFIG_MCUACCUMINTEN		BIT(29)
+#define ERRCONFIG_MCUACCUMINTST		BIT(28)
+#define	ERRCONFIG_MCUVALIDINTEN		BIT(27)
+#define ERRCONFIG_MCUVALIDINTST		BIT(26)
+#define ERRCONFIG_MCUBOUNDINTEN		BIT(25)
+#define	ERRCONFIG_MCUBOUNDINTST		BIT(24)
+#define	ERRCONFIG_MCUDISACKINTEN	BIT(23)
+#define ERRCONFIG_VPBOUNDINTST_V2	BIT(23)
+#define ERRCONFIG_MCUDISACKINTST	BIT(22)
+#define ERRCONFIG_VPBOUNDINTEN_V2	BIT(22)
+
+#define ERRCONFIG_STATUS_V1_MASK	(ERRCONFIG_VPBOUNDINTST_V1 | \
+					ERRCONFIG_MCUACCUMINTST | \
+					ERRCONFIG_MCUVALIDINTST | \
+					ERRCONFIG_MCUBOUNDINTST | \
+					ERRCONFIG_MCUDISACKINTST)
+/* IRQSTATUS */
+#define IRQSTATUS_MCUACCUMINT		BIT(3)
+#define IRQSTATUS_MCVALIDINT		BIT(2)
+#define IRQSTATUS_MCBOUNDSINT		BIT(1)
+#define IRQSTATUS_MCUDISABLEACKINT	BIT(0)
+
+/* IRQENABLE_SET and IRQENABLE_CLEAR */
+#define IRQENABLE_MCUACCUMINT		BIT(3)
+#define IRQENABLE_MCUVALIDINT		BIT(2)
+#define IRQENABLE_MCUBOUNDSINT		BIT(1)
+#define IRQENABLE_MCUDISABLEACKINT	BIT(0)
+
+/* Common Bit values */
+
+#define SRCLKLENGTH_12MHZ_SYSCLK	0x3c
+#define SRCLKLENGTH_13MHZ_SYSCLK	0x41
+#define SRCLKLENGTH_19MHZ_SYSCLK	0x60
+#define SRCLKLENGTH_26MHZ_SYSCLK	0x82
+#define SRCLKLENGTH_38MHZ_SYSCLK	0xC0
+
+/*
+ * 3430 specific values. Maybe these should be passed from board file or
+ * pmic structures.
+ */
+#define OMAP3430_SR_ACCUMDATA		0x1f4
+
+#define OMAP3430_SR1_SENPAVGWEIGHT	0x03
+#define OMAP3430_SR1_SENNAVGWEIGHT	0x03
+
+#define OMAP3430_SR2_SENPAVGWEIGHT	0x01
+#define OMAP3430_SR2_SENNAVGWEIGHT	0x01
+
+#define OMAP3430_SR_ERRWEIGHT		0x04
+#define OMAP3430_SR_ERRMAXLIMIT		0x02
+
+/**
+ * struct omap_sr_pmic_data - Strucutre to be populated by pmic code to pass
+ *				pmic specific info to smartreflex driver
+ *
+ * @sr_pmic_init:	API to initialize smartreflex on the PMIC side.
+ */
+struct omap_sr_pmic_data {
+	void (*sr_pmic_init) (void);
+};
+
+#ifdef CONFIG_OMAP_SMARTREFLEX
+/*
+ * The smart reflex driver supports CLASS1 CLASS2 and CLASS3 SR.
+ * The smartreflex class driver should pass the class type.
+ * Should be used to populate the class_type field of the
+ * omap_smartreflex_class_data structure.
+ */
+#define SR_CLASS1	0x1
+#define SR_CLASS2	0x2
+#define SR_CLASS3	0x3
+
+/**
+ * struct omap_sr_class_data - Smartreflex class driver info
+ *
+ * @enable:		API to enable a particular class smaartreflex.
+ * @disable:		API to disable a particular class smartreflex.
+ * @configure:		API to configure a particular class smartreflex.
+ * @notify:		API to notify the class driver about an event in SR.
+ *			Not needed for class3.
+ * @notify_flags:	specify the events to be notified to the class driver
+ * @class_type:		specify which smartreflex class.
+ *			Can be used by the SR driver to take any class
+ *			based decisions.
+ */
+struct omap_sr_class_data {
+	int (*enable)(struct voltagedomain *voltdm);
+	int (*disable)(struct voltagedomain *voltdm, int is_volt_reset);
+	int (*configure)(struct voltagedomain *voltdm);
+	int (*notify)(struct voltagedomain *voltdm, u32 status);
+	u8 notify_flags;
+	u8 class_type;
+};
+
+/**
+ * struct omap_sr_nvalue_table	- Smartreflex n-target value info
+ *
+ * @efuse_offs:	The offset of the efuse where n-target values are stored.
+ * @nvalue:	The n-target value.
+ */
+struct omap_sr_nvalue_table {
+	u32 efuse_offs;
+	u32 nvalue;
+};
+
+/**
+ * struct omap_sr_data - Smartreflex platform data.
+ *
+ * @ip_type:		Smartreflex IP type.
+ * @senp_mod:		SENPENABLE value for the sr
+ * @senn_mod:		SENNENABLE value for sr
+ * @nvalue_count:	Number of distinct nvalues in the nvalue table
+ * @enable_on_init:	whether this sr module needs to enabled at
+ *			boot up or not.
+ * @nvalue_table:	table containing the  efuse offsets and nvalues
+ *			corresponding to them.
+ * @voltdm:		Pointer to the voltage domain associated with the SR
+ */
+struct omap_sr_data {
+	int				ip_type;
+	u32				senp_mod;
+	u32				senn_mod;
+	int				nvalue_count;
+	bool				enable_on_init;
+	struct omap_sr_nvalue_table	*nvalue_table;
+	struct voltagedomain		*voltdm;
+};
+
+/* Smartreflex module enable/disable interface */
+void omap_sr_enable(struct voltagedomain *voltdm);
+void omap_sr_disable(struct voltagedomain *voltdm);
+void omap_sr_disable_reset_volt(struct voltagedomain *voltdm);
+
+/* API to register the pmic specific data with the smartreflex driver. */
+void omap_sr_register_pmic(struct omap_sr_pmic_data *pmic_data);
+
+/* Smartreflex driver hooks to be called from Smartreflex class driver */
+int sr_enable(struct voltagedomain *voltdm, unsigned long volt);
+void sr_disable(struct voltagedomain *voltdm);
+int sr_configure_errgen(struct voltagedomain *voltdm);
+int sr_configure_minmax(struct voltagedomain *voltdm);
+
+/* API to register the smartreflex class driver with the smartreflex driver */
+int sr_register_class(struct omap_sr_class_data *class_data);
+#else
+static inline void omap_sr_enable(struct voltagedomain *voltdm) {}
+static inline void omap_sr_disable(struct voltagedomain *voltdm) {}
+static inline void omap_sr_disable_reset_volt(
+		struct voltagedomain *voltdm) {}
+static inline void omap_sr_register_pmic(
+		struct omap_sr_pmic_data *pmic_data) {}
+#endif
+#endif
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-omap/include/plat/smp.h linux-libre-2.6.38-gnu1/arch/arm/plat-omap/include/plat/smp.h
--- linux-libre-2.6.37-gnu1/arch/arm/plat-omap/include/plat/smp.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-omap/include/plat/smp.h	2011-03-14 21:20:32.000000000 -0400
@@ -18,7 +18,6 @@
 #define OMAP_ARCH_SMP_H
 
 #include <asm/hardware/gic.h>
-#include <asm/smp_mpidr.h>
 
 /* Needed for secondary core boot */
 extern void omap_secondary_startup(void);
@@ -29,9 +28,9 @@ extern u32 omap_read_auxcoreboot0(void);
 /*
  * We use Soft IRQ1 as the IPI
  */
-static inline void smp_cross_call(const struct cpumask *mask)
+static inline void smp_cross_call(const struct cpumask *mask, int ipi)
 {
-	gic_raise_softirq(mask, 1);
+	gic_raise_softirq(mask, ipi);
 }
 
 #endif
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-omap/include/plat/sram.h linux-libre-2.6.38-gnu1/arch/arm/plat-omap/include/plat/sram.h
--- linux-libre-2.6.37-gnu1/arch/arm/plat-omap/include/plat/sram.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-omap/include/plat/sram.h	2011-03-14 21:20:32.000000000 -0400
@@ -11,6 +11,7 @@
 #ifndef __ARCH_ARM_OMAP_SRAM_H
 #define __ARCH_ARM_OMAP_SRAM_H
 
+#ifndef __ASSEMBLY__
 extern void * omap_sram_push(void * start, unsigned long size);
 extern void omap_sram_reprogram_clock(u32 dpllctl, u32 ckctl);
 
@@ -74,4 +75,14 @@ extern void omap_push_sram_idle(void);
 static inline void omap_push_sram_idle(void) {}
 #endif /* CONFIG_PM */
 
+#endif /* __ASSEMBLY__ */
+
+/*
+ * OMAP2+: define the SRAM PA addresses.
+ * Used by the SRAM management code and the idle sleep code.
+ */
+#define OMAP2_SRAM_PA		0x40200000
+#define OMAP3_SRAM_PA           0x40200000
+#define OMAP4_SRAM_PA		0x40300000
+
 #endif
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-omap/include/plat/uncompress.h linux-libre-2.6.38-gnu1/arch/arm/plat-omap/include/plat/uncompress.h
--- linux-libre-2.6.37-gnu1/arch/arm/plat-omap/include/plat/uncompress.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-omap/include/plat/uncompress.h	2011-03-14 21:20:32.000000000 -0400
@@ -145,8 +145,11 @@ static inline void __arch_decomp_setup(u
 		/* omap3 based boards using UART3 */
 		DEBUG_LL_OMAP3(3, cm_t35);
 		DEBUG_LL_OMAP3(3, cm_t3517);
+		DEBUG_LL_OMAP3(3, craneboard);
+		DEBUG_LL_OMAP3(3, devkit8000);
 		DEBUG_LL_OMAP3(3, igep0020);
 		DEBUG_LL_OMAP3(3, igep0030);
+		DEBUG_LL_OMAP3(3, nokia_rm680);
 		DEBUG_LL_OMAP3(3, nokia_rx51);
 		DEBUG_LL_OMAP3(3, omap3517evm);
 		DEBUG_LL_OMAP3(3, omap3_beagle);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-omap/include/plat/usb.h linux-libre-2.6.38-gnu1/arch/arm/plat-omap/include/plat/usb.h
--- linux-libre-2.6.37-gnu1/arch/arm/plat-omap/include/plat/usb.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-omap/include/plat/usb.h	2011-03-14 21:20:32.000000000 -0400
@@ -11,6 +11,7 @@ enum ehci_hcd_omap_mode {
 	EHCI_HCD_OMAP_MODE_UNKNOWN,
 	EHCI_HCD_OMAP_MODE_PHY,
 	EHCI_HCD_OMAP_MODE_TLL,
+	EHCI_HCD_OMAP_MODE_HSIC,
 };
 
 enum ohci_omap3_port_mode {
@@ -69,6 +70,10 @@ struct omap_musb_board_data {
 	u8	mode;
 	u16	power;
 	unsigned extvbus:1;
+	void	(*set_phy_power)(u8 on);
+	void	(*clear_irq)(void);
+	void	(*set_mode)(u8 mode);
+	void	(*reset)(void);
 };
 
 enum musb_interface    {MUSB_INTERFACE_ULPI, MUSB_INTERFACE_UTMI};
@@ -79,6 +84,11 @@ extern void usb_ehci_init(const struct e
 
 extern void usb_ohci_init(const struct ohci_hcd_omap_platform_data *pdata);
 
+extern int omap4430_phy_power(struct device *dev, int ID, int on);
+extern int omap4430_phy_set_clk(struct device *dev, int on);
+extern int omap4430_phy_init(struct device *dev);
+extern int omap4430_phy_exit(struct device *dev);
+
 #endif
 
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-omap/include/plat/voltage.h linux-libre-2.6.38-gnu1/arch/arm/plat-omap/include/plat/voltage.h
--- linux-libre-2.6.37-gnu1/arch/arm/plat-omap/include/plat/voltage.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-omap/include/plat/voltage.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,155 @@
+/*
+ * OMAP Voltage Management Routines
+ *
+ * Author: Thara Gopinath	<thara@ti.com>
+ *
+ * Copyright (C) 2009 Texas Instruments, Inc.
+ * 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.
+ */
+
+#ifndef __ARCH_ARM_MACH_OMAP2_VOLTAGE_H
+#define __ARCH_ARM_MACH_OMAP2_VOLTAGE_H
+
+#include <linux/err.h>
+
+#define VOLTSCALE_VPFORCEUPDATE		1
+#define VOLTSCALE_VCBYPASS		2
+
+/*
+ * OMAP3 GENERIC setup times. Revisit to see if these needs to be
+ * passed from board or PMIC file
+ */
+#define OMAP3_CLKSETUP		0xff
+#define OMAP3_VOLTOFFSET	0xff
+#define OMAP3_VOLTSETUP2	0xff
+
+/* Voltage value defines */
+#define OMAP3430_VDD_MPU_OPP1_UV		975000
+#define OMAP3430_VDD_MPU_OPP2_UV		1075000
+#define OMAP3430_VDD_MPU_OPP3_UV		1200000
+#define OMAP3430_VDD_MPU_OPP4_UV		1270000
+#define OMAP3430_VDD_MPU_OPP5_UV		1350000
+
+#define OMAP3430_VDD_CORE_OPP1_UV		975000
+#define OMAP3430_VDD_CORE_OPP2_UV		1050000
+#define OMAP3430_VDD_CORE_OPP3_UV		1150000
+
+#define OMAP3630_VDD_MPU_OPP50_UV		1012500
+#define OMAP3630_VDD_MPU_OPP100_UV		1200000
+#define OMAP3630_VDD_MPU_OPP120_UV		1325000
+#define OMAP3630_VDD_MPU_OPP1G_UV		1375000
+
+#define OMAP3630_VDD_CORE_OPP50_UV		1000000
+#define OMAP3630_VDD_CORE_OPP100_UV		1200000
+
+#define OMAP4430_VDD_MPU_OPP50_UV		930000
+#define OMAP4430_VDD_MPU_OPP100_UV		1100000
+#define OMAP4430_VDD_MPU_OPPTURBO_UV		1260000
+#define OMAP4430_VDD_MPU_OPPNITRO_UV		1350000
+
+#define OMAP4430_VDD_IVA_OPP50_UV		930000
+#define OMAP4430_VDD_IVA_OPP100_UV		1100000
+#define OMAP4430_VDD_IVA_OPPTURBO_UV		1260000
+
+#define OMAP4430_VDD_CORE_OPP50_UV		930000
+#define OMAP4430_VDD_CORE_OPP100_UV		1100000
+
+/**
+ * struct voltagedomain - omap voltage domain global structure.
+ * @name:	Name of the voltage domain which can be used as a unique
+ *		identifier.
+ */
+struct voltagedomain {
+	char *name;
+};
+
+/**
+ * struct omap_volt_data - Omap voltage specific data.
+ * @voltage_nominal:	The possible voltage value in uV
+ * @sr_efuse_offs:	The offset of the efuse register(from system
+ *			control module base address) from where to read
+ *			the n-target value for the smartreflex module.
+ * @sr_errminlimit:	Error min limit value for smartreflex. This value
+ *			differs at differnet opp and thus is linked
+ *			with voltage.
+ * @vp_errorgain:	Error gain value for the voltage processor. This
+ *			field also differs according to the voltage/opp.
+ */
+struct omap_volt_data {
+	u32	volt_nominal;
+	u32	sr_efuse_offs;
+	u8	sr_errminlimit;
+	u8	vp_errgain;
+};
+
+/**
+ * struct omap_volt_pmic_info - PMIC specific data required by voltage driver.
+ * @slew_rate:	PMIC slew rate (in uv/us)
+ * @step_size:	PMIC voltage step size (in uv)
+ * @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 {
+	int slew_rate;
+	int step_size;
+	u32 on_volt;
+	u32 onlp_volt;
+	u32 ret_volt;
+	u32 off_volt;
+	u16 volt_setup_time;
+	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;
+	unsigned long (*vsel_to_uv) (const u8 vsel);
+	u8 (*uv_to_vsel) (unsigned long uV);
+};
+
+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);
+#ifdef CONFIG_PM
+int omap_voltage_register_pmic(struct voltagedomain *voltdm,
+		struct omap_volt_pmic_info *pmic_info);
+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
+
+#endif
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-omap/io.c linux-libre-2.6.38-gnu1/arch/arm/plat-omap/io.c
--- linux-libre-2.6.37-gnu1/arch/arm/plat-omap/io.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-omap/io.c	2011-03-14 21:20:32.000000000 -0400
@@ -136,61 +136,3 @@ void omap_iounmap(volatile void __iomem
 		__iounmap(addr);
 }
 EXPORT_SYMBOL(omap_iounmap);
-
-/*
- * NOTE: Please use ioremap + __raw_read/write where possible instead of these
- */
-
-u8 omap_readb(u32 pa)
-{
-	if (cpu_class_is_omap1())
-		return __raw_readb(OMAP1_IO_ADDRESS(pa));
-	else
-		return __raw_readb(OMAP2_L4_IO_ADDRESS(pa));
-}
-EXPORT_SYMBOL(omap_readb);
-
-u16 omap_readw(u32 pa)
-{
-	if (cpu_class_is_omap1())
-		return __raw_readw(OMAP1_IO_ADDRESS(pa));
-	else
-		return __raw_readw(OMAP2_L4_IO_ADDRESS(pa));
-}
-EXPORT_SYMBOL(omap_readw);
-
-u32 omap_readl(u32 pa)
-{
-	if (cpu_class_is_omap1())
-		return __raw_readl(OMAP1_IO_ADDRESS(pa));
-	else
-		return __raw_readl(OMAP2_L4_IO_ADDRESS(pa));
-}
-EXPORT_SYMBOL(omap_readl);
-
-void omap_writeb(u8 v, u32 pa)
-{
-	if (cpu_class_is_omap1())
-		__raw_writeb(v, OMAP1_IO_ADDRESS(pa));
-	else
-		__raw_writeb(v, OMAP2_L4_IO_ADDRESS(pa));
-}
-EXPORT_SYMBOL(omap_writeb);
-
-void omap_writew(u16 v, u32 pa)
-{
-	if (cpu_class_is_omap1())
-		__raw_writew(v, OMAP1_IO_ADDRESS(pa));
-	else
-		__raw_writew(v, OMAP2_L4_IO_ADDRESS(pa));
-}
-EXPORT_SYMBOL(omap_writew);
-
-void omap_writel(u32 v, u32 pa)
-{
-	if (cpu_class_is_omap1())
-		__raw_writel(v, OMAP1_IO_ADDRESS(pa));
-	else
-		__raw_writel(v, OMAP2_L4_IO_ADDRESS(pa));
-}
-EXPORT_SYMBOL(omap_writel);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-omap/iommu.c linux-libre-2.6.38-gnu1/arch/arm/plat-omap/iommu.c
--- linux-libre-2.6.37-gnu1/arch/arm/plat-omap/iommu.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-omap/iommu.c	2011-03-14 21:20:32.000000000 -0400
@@ -830,6 +830,28 @@ static int device_match_by_alias(struct
 }
 
 /**
+ * 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
  **/
@@ -922,6 +944,8 @@ static int __devinit omap_iommu_probe(st
 	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);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-omap/iovmm.c linux-libre-2.6.38-gnu1/arch/arm/plat-omap/iovmm.c
--- linux-libre-2.6.37-gnu1/arch/arm/plat-omap/iovmm.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-omap/iovmm.c	2011-03-14 21:20:32.000000000 -0400
@@ -87,35 +87,43 @@ static size_t sgtable_len(const struct s
 }
 #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 int sgtable_nents(size_t bytes)
+static unsigned sgtable_nents(size_t bytes, u32 da, u32 pa)
 {
-	int i;
-	unsigned int nr_entries;
-	const unsigned long pagesize[] = { SZ_16M, SZ_1M, SZ_64K, SZ_4K, };
+	unsigned nr_entries = 0, ent_sz;
 
 	if (!IS_ALIGNED(bytes, PAGE_SIZE)) {
 		pr_err("%s: wrong size %08x\n", __func__, bytes);
 		return 0;
 	}
 
-	nr_entries = 0;
-	for (i = 0; i < ARRAY_SIZE(pagesize); i++) {
-		if (bytes >= pagesize[i]) {
-			nr_entries += (bytes / pagesize[i]);
-			bytes %= pagesize[i];
-		}
+	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;
 	}
-	BUG_ON(bytes);
 
 	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)
+static struct sg_table *sgtable_alloc(const size_t bytes, u32 flags,
+							u32 da, u32 pa)
 {
 	unsigned int nr_entries;
 	int err;
@@ -127,9 +135,8 @@ static struct sg_table *sgtable_alloc(co
 	if (!IS_ALIGNED(bytes, PAGE_SIZE))
 		return ERR_PTR(-EINVAL);
 
-	/* FIXME: IOVMF_DA_FIXED should support 'superpages' */
-	if ((flags & IOVMF_LINEAR) && (flags & IOVMF_DA_ANON)) {
-		nr_entries = sgtable_nents(bytes);
+	if (flags & IOVMF_LINEAR) {
+		nr_entries = sgtable_nents(bytes, da, pa);
 		if (!nr_entries)
 			return ERR_PTR(-EINVAL);
 	} else
@@ -273,13 +280,14 @@ static struct iovm_struct *alloc_iovm_ar
 	alignement = PAGE_SIZE;
 
 	if (flags & IOVMF_DA_ANON) {
-		/*
-		 * Reserve the first page for NULL
-		 */
-		start = PAGE_SIZE;
+		start = obj->da_start;
+
 		if (flags & IOVMF_LINEAR)
 			alignement = iopgsz_max(bytes);
 		start = roundup(start, alignement);
+	} else if (start < obj->da_start || start > obj->da_end ||
+					obj->da_end - start < bytes) {
+		return ERR_PTR(-EINVAL);
 	}
 
 	tmp = NULL;
@@ -289,19 +297,19 @@ static struct iovm_struct *alloc_iovm_ar
 	prev_end = 0;
 	list_for_each_entry(tmp, &obj->mmap, list) {
 
-		if (prev_end >= start)
+		if (prev_end > start)
 			break;
 
-		if (start + bytes < tmp->da_start)
+		if (tmp->da_start > start && (tmp->da_start - start) >= bytes)
 			goto found;
 
-		if (flags & IOVMF_DA_ANON)
+		if (tmp->da_end >= start && flags & IOVMF_DA_ANON)
 			start = roundup(tmp->da_end + 1, alignement);
 
 		prev_end = tmp->da_end;
 	}
 
-	if ((start > prev_end) && (ULONG_MAX - start >= bytes))
+	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",
@@ -409,7 +417,8 @@ static inline void sgtable_drain_vmalloc
 	BUG_ON(!sgt);
 }
 
-static void sgtable_fill_kmalloc(struct sg_table *sgt, u32 pa, size_t len)
+static void sgtable_fill_kmalloc(struct sg_table *sgt, u32 pa, u32 da,
+								size_t len)
 {
 	unsigned int i;
 	struct scatterlist *sg;
@@ -418,9 +427,10 @@ static void sgtable_fill_kmalloc(struct
 	va = phys_to_virt(pa);
 
 	for_each_sg(sgt->sgl, sg, sgt->nents, i) {
-		size_t bytes;
+		unsigned bytes;
 
-		bytes = iopgsz_max(len);
+		bytes = max_alignment(da | pa);
+		bytes = min_t(unsigned, bytes, iopgsz_max(len));
 
 		BUG_ON(!iopgsz_ok(bytes));
 
@@ -429,6 +439,7 @@ static void sgtable_fill_kmalloc(struct
 		 * 'pa' is cotinuous(linear).
 		 */
 		pa += bytes;
+		da += bytes;
 		len -= bytes;
 	}
 	BUG_ON(len);
@@ -695,18 +706,18 @@ u32 iommu_vmalloc(struct iommu *obj, u32
 	if (!va)
 		return -ENOMEM;
 
-	sgt = sgtable_alloc(bytes, flags);
+	flags &= IOVMF_HW_MASK;
+	flags |= IOVMF_DISCONT;
+	flags |= IOVMF_ALLOC;
+	flags |= (da ? IOVMF_DA_FIXED : IOVMF_DA_ANON);
+
+	sgt = sgtable_alloc(bytes, flags, da, 0);
 	if (IS_ERR(sgt)) {
 		da = PTR_ERR(sgt);
 		goto err_sgt_alloc;
 	}
 	sgtable_fill_vmalloc(sgt, va);
 
-	flags &= IOVMF_HW_MASK;
-	flags |= IOVMF_DISCONT;
-	flags |= IOVMF_ALLOC;
-	flags |= (da ? IOVMF_DA_FIXED : IOVMF_DA_ANON);
-
 	da = __iommu_vmap(obj, da, sgt, va, bytes, flags);
 	if (IS_ERR_VALUE(da))
 		goto err_iommu_vmap;
@@ -746,11 +757,11 @@ static u32 __iommu_kmap(struct iommu *ob
 {
 	struct sg_table *sgt;
 
-	sgt = sgtable_alloc(bytes, flags);
+	sgt = sgtable_alloc(bytes, flags, da, pa);
 	if (IS_ERR(sgt))
 		return PTR_ERR(sgt);
 
-	sgtable_fill_kmalloc(sgt, pa, bytes);
+	sgtable_fill_kmalloc(sgt, pa, da, bytes);
 
 	da = map_iommu_region(obj, da, sgt, va, bytes, flags);
 	if (IS_ERR_VALUE(da)) {
@@ -811,7 +822,7 @@ void iommu_kunmap(struct iommu *obj, u32
 	struct sg_table *sgt;
 	typedef void (*func_t)(const void *);
 
-	sgt = unmap_vm_area(obj, da, (func_t)__iounmap,
+	sgt = unmap_vm_area(obj, da, (func_t)iounmap,
 			    IOVMF_LINEAR | IOVMF_MMIO);
 	if (!sgt)
 		dev_dbg(obj->dev, "%s: No sgt\n", __func__);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-omap/Kconfig linux-libre-2.6.38-gnu1/arch/arm/plat-omap/Kconfig
--- linux-libre-2.6.37-gnu1/arch/arm/plat-omap/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-omap/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -11,13 +11,14 @@ choice
 
 config ARCH_OMAP1
 	bool "TI OMAP1"
-	select COMMON_CLKDEV
+	select CLKDEV_LOOKUP
 	help
 	  "Systems based on omap7xx, omap15xx or omap16xx"
 
 config ARCH_OMAP2PLUS
 	bool "TI OMAP2/3/4"
-	select COMMON_CLKDEV
+	select CLKDEV_LOOKUP
+	select OMAP_DM_TIMER
 	help
 	  "Systems based on OMAP2, OMAP3 or OMAP4"
 
@@ -35,6 +36,37 @@ config OMAP_DEBUG_LEDS
 	depends on OMAP_DEBUG_DEVICES
 	default y if LEDS_CLASS
 
+config OMAP_SMARTREFLEX
+	bool "SmartReflex support"
+	depends on (ARCH_OMAP3 || ARCH_OMAP4) && PM
+	help
+	  Say Y if you want to enable SmartReflex.
+
+	  SmartReflex can perform continuous dynamic voltage
+	  scaling around the nominal operating point voltage
+	  according to silicon characteristics and operating
+	  conditions. Enabling SmartReflex reduces power
+	  consumption.
+
+	  Please note, that by default SmartReflex is only
+	  initialized. To enable the automatic voltage
+	  compensation for vdd mpu  and vdd core from user space,
+	  user must write 1 to
+		/debug/voltage/vdd_<X>/smartreflex/autocomp,
+	  where X is mpu or core for OMAP3.
+	  Optionallly autocompensation can be enabled in the kernel
+	  by default during system init via the enable_on_init flag
+	  which an be passed as platform data to the smartreflex driver.
+
+config OMAP_SMARTREFLEX_CLASS3
+	bool "Class 3 mode of Smartreflex Implementation"
+	depends on OMAP_SMARTREFLEX && TWL4030_CORE
+	help
+	  Say Y to enable Class 3 implementation of Smartreflex
+
+	  Class 3 implementation of Smartreflex employs continuous hardware
+	  voltage calibration.
+
 config OMAP_RESET_CLOCKS
 	bool "Reset unused clocks during boot"
 	depends on ARCH_OMAP
@@ -109,12 +141,12 @@ config OMAP_IOMMU_DEBUG
 
          Say N unless you know you need this.
 
-choice
-	prompt "System timer"
-	default OMAP_32K_TIMER if !ARCH_OMAP15XX
+config OMAP_IOMMU_IVA2
+	bool
 
 config OMAP_MPU_TIMER
 	bool "Use mpu timer"
+	depends on ARCH_OMAP1
 	help
 	  Select this option if you want to use the OMAP mpu timer. This
 	  timer provides more intra-tick resolution than the 32KHz timer,
@@ -123,6 +155,7 @@ config OMAP_MPU_TIMER
 config OMAP_32K_TIMER
 	bool "Use 32KHz timer"
 	depends on ARCH_OMAP16XX || ARCH_OMAP2PLUS
+	default y if (ARCH_OMAP16XX || ARCH_OMAP2PLUS)
 	help
 	  Select this option if you want to enable the OMAP 32KHz timer.
 	  This timer saves power compared to the OMAP_MPU_TIMER, and has
@@ -130,8 +163,6 @@ config OMAP_32K_TIMER
 	  intra-tick resolution than OMAP_MPU_TIMER. The 32KHz timer is
 	  currently only available for OMAP16XX, 24XX, 34XX and OMAP4.
 
-endchoice
-
 config OMAP3_L2_AUX_SECURE_SAVE_RESTORE
 	bool "OMAP3 HS/EMU save and restore for L2 AUX control register"
 	depends on ARCH_OMAP3 && PM
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-omap/mailbox.c linux-libre-2.6.38-gnu1/arch/arm/plat-omap/mailbox.c
--- linux-libre-2.6.37-gnu1/arch/arm/plat-omap/mailbox.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-omap/mailbox.c	2011-03-14 21:20:32.000000000 -0400
@@ -28,12 +28,12 @@
 #include <linux/slab.h>
 #include <linux/kfifo.h>
 #include <linux/err.h>
+#include <linux/notifier.h>
 
 #include <plat/mailbox.h>
 
 static struct workqueue_struct *mboxd;
 static struct omap_mbox **mboxes;
-static bool rq_full;
 
 static int mbox_configured;
 static DEFINE_MUTEX(mbox_configured_lock);
@@ -93,20 +93,25 @@ int omap_mbox_msg_send(struct omap_mbox
 	struct omap_mbox_queue *mq = mbox->txq;
 	int ret = 0, len;
 
-	spin_lock(&mq->lock);
+	spin_lock_bh(&mq->lock);
 
 	if (kfifo_avail(&mq->fifo) < sizeof(msg)) {
 		ret = -ENOMEM;
 		goto out;
 	}
 
+	if (kfifo_is_empty(&mq->fifo) && !__mbox_poll_for_space(mbox)) {
+		mbox_fifo_write(mbox, msg);
+		goto out;
+	}
+
 	len = kfifo_in(&mq->fifo, (unsigned char *)&msg, sizeof(msg));
 	WARN_ON(len != sizeof(msg));
 
 	tasklet_schedule(&mbox->txq->tasklet);
 
 out:
-	spin_unlock(&mq->lock);
+	spin_unlock_bh(&mq->lock);
 	return ret;
 }
 EXPORT_SYMBOL(omap_mbox_msg_send);
@@ -146,8 +151,14 @@ static void mbox_rx_work(struct work_str
 		len = kfifo_out(&mq->fifo, (unsigned char *)&msg, sizeof(msg));
 		WARN_ON(len != sizeof(msg));
 
-		if (mq->callback)
-			mq->callback((void *)msg);
+		blocking_notifier_call_chain(&mq->mbox->notifier, len,
+								(void *)msg);
+		spin_lock_irq(&mq->lock);
+		if (mq->full) {
+			mq->full = false;
+			omap_mbox_enable_irq(mq->mbox, IRQ_RX);
+		}
+		spin_unlock_irq(&mq->lock);
 	}
 }
 
@@ -170,7 +181,7 @@ static void __mbox_rx_interrupt(struct o
 	while (!mbox_fifo_empty(mbox)) {
 		if (unlikely(kfifo_avail(&mq->fifo) < sizeof(msg))) {
 			omap_mbox_disable_irq(mbox, IRQ_RX);
-			rq_full = true;
+			mq->full = true;
 			goto nomem;
 		}
 
@@ -239,83 +250,90 @@ static int omap_mbox_startup(struct omap
 	int ret = 0;
 	struct omap_mbox_queue *mq;
 
-	if (mbox->ops->startup) {
-		mutex_lock(&mbox_configured_lock);
-		if (!mbox_configured)
+	mutex_lock(&mbox_configured_lock);
+	if (!mbox_configured++) {
+		if (likely(mbox->ops->startup)) {
 			ret = mbox->ops->startup(mbox);
-
-		if (ret) {
-			mutex_unlock(&mbox_configured_lock);
-			return ret;
-		}
-		mbox_configured++;
-		mutex_unlock(&mbox_configured_lock);
-	}
-
-	ret = request_irq(mbox->irq, mbox_interrupt, IRQF_SHARED,
-				mbox->name, mbox);
-	if (ret) {
-		printk(KERN_ERR
-			"failed to register mailbox interrupt:%d\n", ret);
-		goto fail_request_irq;
+			if (unlikely(ret))
+				goto fail_startup;
+		} else
+			goto fail_startup;
 	}
 
-	mq = mbox_queue_alloc(mbox, NULL, mbox_tx_tasklet);
-	if (!mq) {
-		ret = -ENOMEM;
-		goto fail_alloc_txq;
-	}
-	mbox->txq = mq;
+	if (!mbox->use_count++) {
+		ret = request_irq(mbox->irq, mbox_interrupt, IRQF_SHARED,
+							mbox->name, mbox);
+		if (unlikely(ret)) {
+			pr_err("failed to register mailbox interrupt:%d\n",
+									ret);
+			goto fail_request_irq;
+		}
+		mq = mbox_queue_alloc(mbox, NULL, mbox_tx_tasklet);
+		if (!mq) {
+			ret = -ENOMEM;
+			goto fail_alloc_txq;
+		}
+		mbox->txq = mq;
 
-	mq = mbox_queue_alloc(mbox, mbox_rx_work, NULL);
-	if (!mq) {
-		ret = -ENOMEM;
-		goto fail_alloc_rxq;
+		mq = mbox_queue_alloc(mbox, mbox_rx_work, NULL);
+		if (!mq) {
+			ret = -ENOMEM;
+			goto fail_alloc_rxq;
+		}
+		mbox->rxq = mq;
+		mq->mbox = mbox;
 	}
-	mbox->rxq = mq;
-
+	mutex_unlock(&mbox_configured_lock);
 	return 0;
 
- fail_alloc_rxq:
+fail_alloc_rxq:
 	mbox_queue_free(mbox->txq);
- fail_alloc_txq:
+fail_alloc_txq:
 	free_irq(mbox->irq, mbox);
- fail_request_irq:
+fail_request_irq:
 	if (mbox->ops->shutdown)
 		mbox->ops->shutdown(mbox);
-
+	mbox->use_count--;
+fail_startup:
+	mbox_configured--;
+	mutex_unlock(&mbox_configured_lock);
 	return ret;
 }
 
 static void omap_mbox_fini(struct omap_mbox *mbox)
 {
-	free_irq(mbox->irq, mbox);
-	tasklet_kill(&mbox->txq->tasklet);
-	flush_work(&mbox->rxq->work);
-	mbox_queue_free(mbox->txq);
-	mbox_queue_free(mbox->rxq);
+	mutex_lock(&mbox_configured_lock);
 
-	if (mbox->ops->shutdown) {
-		mutex_lock(&mbox_configured_lock);
-		if (mbox_configured > 0)
-			mbox_configured--;
-		if (!mbox_configured)
+	if (!--mbox->use_count) {
+		free_irq(mbox->irq, mbox);
+		tasklet_kill(&mbox->txq->tasklet);
+		flush_work(&mbox->rxq->work);
+		mbox_queue_free(mbox->txq);
+		mbox_queue_free(mbox->rxq);
+	}
+
+	if (likely(mbox->ops->shutdown)) {
+		if (!--mbox_configured)
 			mbox->ops->shutdown(mbox);
-		mutex_unlock(&mbox_configured_lock);
 	}
+
+	mutex_unlock(&mbox_configured_lock);
 }
 
-struct omap_mbox *omap_mbox_get(const char *name)
+struct omap_mbox *omap_mbox_get(const char *name, struct notifier_block *nb)
 {
-	struct omap_mbox *mbox;
-	int ret;
+	struct omap_mbox *_mbox, *mbox = NULL;
+	int i, ret;
 
 	if (!mboxes)
 		return ERR_PTR(-EINVAL);
 
-	for (mbox = *mboxes; mbox; mbox++)
-		if (!strcmp(mbox->name, name))
+	for (i = 0; (_mbox = mboxes[i]); i++) {
+		if (!strcmp(_mbox->name, name)) {
+			mbox = _mbox;
 			break;
+		}
+	}
 
 	if (!mbox)
 		return ERR_PTR(-ENOENT);
@@ -324,12 +342,16 @@ struct omap_mbox *omap_mbox_get(const ch
 	if (ret)
 		return ERR_PTR(-ENODEV);
 
+	if (nb)
+		blocking_notifier_chain_register(&mbox->notifier, nb);
+
 	return mbox;
 }
 EXPORT_SYMBOL(omap_mbox_get);
 
-void omap_mbox_put(struct omap_mbox *mbox)
+void omap_mbox_put(struct omap_mbox *mbox, struct notifier_block *nb)
 {
+	blocking_notifier_chain_unregister(&mbox->notifier, nb);
 	omap_mbox_fini(mbox);
 }
 EXPORT_SYMBOL(omap_mbox_put);
@@ -353,6 +375,8 @@ int omap_mbox_register(struct device *pa
 			ret = PTR_ERR(mbox->dev);
 			goto err_out;
 		}
+
+		BLOCKING_INIT_NOTIFIER_HEAD(&mbox->notifier);
 	}
 	return 0;
 
@@ -391,7 +415,8 @@ static int __init omap_mbox_init(void)
 
 	/* kfifo size sanity check: alignment and minimal size */
 	mbox_kfifo_size = ALIGN(mbox_kfifo_size, sizeof(mbox_msg_t));
-	mbox_kfifo_size = max_t(unsigned int, mbox_kfifo_size, sizeof(mbox_msg_t));
+	mbox_kfifo_size = max_t(unsigned int, mbox_kfifo_size,
+							sizeof(mbox_msg_t));
 
 	return 0;
 }
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-omap/mcbsp.c linux-libre-2.6.38-gnu1/arch/arm/plat-omap/mcbsp.c
--- linux-libre-2.6.37-gnu1/arch/arm/plat-omap/mcbsp.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-omap/mcbsp.c	2011-03-14 21:20:32.000000000 -0400
@@ -28,6 +28,8 @@
 #include <plat/dma.h>
 #include <plat/mcbsp.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;
@@ -234,9 +236,9 @@ static void omap_st_on(struct omap_mcbsp
 	 * Sidetone uses McBSP ICLK - which must not idle when sidetones
 	 * are enabled or sidetones start sounding ugly.
 	 */
-	w = cm_read_mod_reg(OMAP3430_PER_MOD, CM_AUTOIDLE);
+	w = omap2_cm_read_mod_reg(OMAP3430_PER_MOD, CM_AUTOIDLE);
 	w &= ~(1 << (mcbsp->id - 2));
-	cm_write_mod_reg(w, OMAP3430_PER_MOD, CM_AUTOIDLE);
+	omap2_cm_write_mod_reg(w, OMAP3430_PER_MOD, CM_AUTOIDLE);
 
 	/* Enable McBSP Sidetone */
 	w = MCBSP_READ(mcbsp, SSELCR);
@@ -263,9 +265,9 @@ static void omap_st_off(struct omap_mcbs
 	w = MCBSP_READ(mcbsp, SSELCR);
 	MCBSP_WRITE(mcbsp, SSELCR, w & ~(SIDETONEEN));
 
-	w = cm_read_mod_reg(OMAP3430_PER_MOD, CM_AUTOIDLE);
+	w = omap2_cm_read_mod_reg(OMAP3430_PER_MOD, CM_AUTOIDLE);
 	w |= 1 << (mcbsp->id - 2);
-	cm_write_mod_reg(w, OMAP3430_PER_MOD, CM_AUTOIDLE);
+	omap2_cm_write_mod_reg(w, OMAP3430_PER_MOD, CM_AUTOIDLE);
 }
 
 static void omap_st_fir_write(struct omap_mcbsp *mcbsp, s16 *fir)
@@ -755,7 +757,7 @@ int omap_mcbsp_request(unsigned int id)
 		goto err_kfree;
 	}
 
-	mcbsp->free = 0;
+	mcbsp->free = false;
 	mcbsp->reg_cache = reg_cache;
 	spin_unlock(&mcbsp->lock);
 
@@ -815,7 +817,7 @@ err_clk_disable:
 	clk_disable(mcbsp->iclk);
 
 	spin_lock(&mcbsp->lock);
-	mcbsp->free = 1;
+	mcbsp->free = true;
 	mcbsp->reg_cache = NULL;
 err_kfree:
 	spin_unlock(&mcbsp->lock);
@@ -858,7 +860,7 @@ void omap_mcbsp_free(unsigned int id)
 	if (mcbsp->free)
 		dev_err(mcbsp->dev, "McBSP%d was not reserved\n", mcbsp->id);
 	else
-		mcbsp->free = 1;
+		mcbsp->free = true;
 	mcbsp->reg_cache = NULL;
 	spin_unlock(&mcbsp->lock);
 
@@ -1771,7 +1773,7 @@ static int __devinit omap_mcbsp_probe(st
 
 	spin_lock_init(&mcbsp->lock);
 	mcbsp->id = id + 1;
-	mcbsp->free = 1;
+	mcbsp->free = true;
 	mcbsp->dma_tx_lch = -1;
 	mcbsp->dma_rx_lch = -1;
 
@@ -1836,17 +1838,11 @@ static int __devexit omap_mcbsp_remove(s
 
 		omap34xx_device_exit(mcbsp);
 
-		clk_disable(mcbsp->fclk);
-		clk_disable(mcbsp->iclk);
 		clk_put(mcbsp->fclk);
 		clk_put(mcbsp->iclk);
 
 		iounmap(mcbsp->io_base);
-
-		mcbsp->fclk = NULL;
-		mcbsp->iclk = NULL;
-		mcbsp->free = 0;
-		mcbsp->dev = NULL;
+		kfree(mcbsp);
 	}
 
 	return 0;
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-omap/omap_device.c linux-libre-2.6.38-gnu1/arch/arm/plat-omap/omap_device.c
--- linux-libre-2.6.37-gnu1/arch/arm/plat-omap/omap_device.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-omap/omap_device.c	2011-03-14 21:20:32.000000000 -0400
@@ -280,6 +280,34 @@ static void _add_optional_clock_alias(st
 /* Public functions for use by core code */
 
 /**
+ * omap_device_get_context_loss_count - get lost context count
+ * @od: struct omap_device *
+ *
+ * Using the primary hwmod, query the context loss count for this
+ * device.
+ *
+ * Callers should consider context for this device lost any time this
+ * function returns a value different than the value the caller got
+ * the last time it called this function.
+ *
+ * If any hwmods exist for the omap_device assoiated with @pdev,
+ * return the context loss counter for that hwmod, otherwise return
+ * zero.
+ */
+u32 omap_device_get_context_loss_count(struct platform_device *pdev)
+{
+	struct omap_device *od;
+	u32 ret = 0;
+
+	od = _find_by_pdev(pdev);
+
+	if (od->hwmods_cnt)
+		ret = omap_hwmod_get_context_loss_count(od->hwmods[0]);
+
+	return ret;
+}
+
+/**
  * omap_device_count_resources - count number of struct resource entries needed
  * @od: struct omap_device *
  *
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-omap/omap-pm-noop.c linux-libre-2.6.38-gnu1/arch/arm/plat-omap/omap-pm-noop.c
--- linux-libre-2.6.37-gnu1/arch/arm/plat-omap/omap-pm-noop.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-omap/omap-pm-noop.c	2011-03-14 21:20:32.000000000 -0400
@@ -20,15 +20,14 @@
 #include <linux/init.h>
 #include <linux/cpufreq.h>
 #include <linux/device.h>
+#include <linux/platform_device.h>
 
 /* Interface documentation is in mach/omap-pm.h */
 #include <plat/omap-pm.h>
+#include <plat/omap_device.h>
 
-#include <plat/powerdomain.h>
-
-struct omap_opp *dsp_opps;
-struct omap_opp *mpu_opps;
-struct omap_opp *l3_opps;
+static bool off_mode_enabled;
+static u32 dummy_context_loss_counter;
 
 /*
  * Device-driver-originated constraints (via board-*.c files)
@@ -284,37 +283,70 @@ unsigned long omap_pm_cpu_get_freq(void)
 	return 0;
 }
 
+/**
+ * omap_pm_enable_off_mode - notify OMAP PM that off-mode is enabled
+ *
+ * Intended for use only by OMAP PM core code to notify this layer
+ * that off mode has been enabled.
+ */
+void omap_pm_enable_off_mode(void)
+{
+	off_mode_enabled = true;
+}
+
+/**
+ * omap_pm_disable_off_mode - notify OMAP PM that off-mode is disabled
+ *
+ * Intended for use only by OMAP PM core code to notify this layer
+ * that off mode has been disabled.
+ */
+void omap_pm_disable_off_mode(void)
+{
+	off_mode_enabled = false;
+}
+
 /*
  * Device context loss tracking
  */
 
-int omap_pm_get_dev_context_loss_count(struct device *dev)
+#ifdef CONFIG_ARCH_OMAP2PLUS
+
+u32 omap_pm_get_dev_context_loss_count(struct device *dev)
 {
-	if (!dev) {
-		WARN_ON(1);
-		return -EINVAL;
-	};
+	struct platform_device *pdev = to_platform_device(dev);
+	u32 count;
 
-	pr_debug("OMAP PM: returning context loss count for dev %s\n",
-		 dev_name(dev));
+	if (WARN_ON(!dev))
+		return 0;
 
-	/*
-	 * Map the device to the powerdomain.  Return the powerdomain
-	 * off counter.
-	 */
+	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;
+	}
 
-	return 0;
+	pr_debug("OMAP PM: context loss count for dev %s = %d\n",
+		 dev_name(dev), count);
+
+	return count;
 }
 
+#else
+
+u32 omap_pm_get_dev_context_loss_count(struct device *dev)
+{
+	return dummy_context_loss_counter;
+}
+
+#endif
 
 /* Should be called before clk framework init */
-int __init omap_pm_if_early_init(struct omap_opp *mpu_opp_table,
-				 struct omap_opp *dsp_opp_table,
-				 struct omap_opp *l3_opp_table)
+int __init omap_pm_if_early_init(void)
 {
-	mpu_opps = mpu_opp_table;
-	dsp_opps = dsp_opp_table;
-	l3_opps = l3_opp_table;
 	return 0;
 }
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-omap/sram.c linux-libre-2.6.38-gnu1/arch/arm/plat-omap/sram.c
--- linux-libre-2.6.37-gnu1/arch/arm/plat-omap/sram.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-omap/sram.c	2011-03-14 21:20:32.000000000 -0400
@@ -33,23 +33,21 @@
 
 #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)
-# include "../mach-omap2/prm.h"
-# include "../mach-omap2/cm.h"
+# include "../mach-omap2/prm2xxx_3xxx.h"
 # include "../mach-omap2/sdrc.h"
 #endif
 
 #define OMAP1_SRAM_PA		0x20000000
 #define OMAP1_SRAM_VA		VMALLOC_END
-#define OMAP2_SRAM_PA		0x40200000
-#define OMAP2_SRAM_PUB_PA	0x4020f800
+#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_PA           0x40200000
 #define OMAP3_SRAM_VA           0xfe400000
-#define OMAP3_SRAM_PUB_PA       0x40208000
+#define OMAP3_SRAM_PUB_PA       (OMAP3_SRAM_PA + 0x8000)
 #define OMAP3_SRAM_PUB_VA       (OMAP3_SRAM_VA + 0x8000)
-#define OMAP4_SRAM_PA		0x40300000
 #define OMAP4_SRAM_VA		0xfe400000
 #define OMAP4_SRAM_PUB_PA	(OMAP4_SRAM_PA + 0x4000)
 #define OMAP4_SRAM_PUB_VA	(OMAP4_SRAM_VA + 0x4000)
@@ -270,7 +268,7 @@ void omap_sram_reprogram_clock(u32 dpllc
 	_omap_sram_reprogram_clock(dpllctl, ckctl);
 }
 
-int __init omap1_sram_init(void)
+static int __init omap1_sram_init(void)
 {
 	_omap_sram_reprogram_clock =
 			omap_sram_push(omap1_sram_reprogram_clock,
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-orion/gpio.c linux-libre-2.6.38-gnu1/arch/arm/plat-orion/gpio.c
--- linux-libre-2.6.37-gnu1/arch/arm/plat-orion/gpio.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-orion/gpio.c	2011-03-14 21:20:32.000000000 -0400
@@ -232,20 +232,19 @@ EXPORT_SYMBOL(orion_gpio_set_blink);
  *        polarity    LEVEL          mask
  *
  ****************************************************************************/
-
-static void gpio_irq_ack(u32 irq)
+static void gpio_irq_ack(struct irq_data *d)
 {
-	int type = irq_desc[irq].status & IRQ_TYPE_SENSE_MASK;
+	int type = irq_desc[d->irq].status & IRQ_TYPE_SENSE_MASK;
 	if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) {
-		int pin = irq_to_gpio(irq);
+		int pin = irq_to_gpio(d->irq);
 		writel(~(1 << (pin & 31)), GPIO_EDGE_CAUSE(pin));
 	}
 }
 
-static void gpio_irq_mask(u32 irq)
+static void gpio_irq_mask(struct irq_data *d)
 {
-	int pin = irq_to_gpio(irq);
-	int type = irq_desc[irq].status & IRQ_TYPE_SENSE_MASK;
+	int pin = irq_to_gpio(d->irq);
+	int type = irq_desc[d->irq].status & IRQ_TYPE_SENSE_MASK;
 	u32 reg = (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) ?
 		GPIO_EDGE_MASK(pin) : GPIO_LEVEL_MASK(pin);
 	u32 u = readl(reg);
@@ -253,10 +252,10 @@ static void gpio_irq_mask(u32 irq)
 	writel(u, reg);
 }
 
-static void gpio_irq_unmask(u32 irq)
+static void gpio_irq_unmask(struct irq_data *d)
 {
-	int pin = irq_to_gpio(irq);
-	int type = irq_desc[irq].status & IRQ_TYPE_SENSE_MASK;
+	int pin = irq_to_gpio(d->irq);
+	int type = irq_desc[d->irq].status & IRQ_TYPE_SENSE_MASK;
 	u32 reg = (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) ?
 		GPIO_EDGE_MASK(pin) : GPIO_LEVEL_MASK(pin);
 	u32 u = readl(reg);
@@ -264,20 +263,20 @@ static void gpio_irq_unmask(u32 irq)
 	writel(u, reg);
 }
 
-static int gpio_irq_set_type(u32 irq, u32 type)
+static int gpio_irq_set_type(struct irq_data *d, u32 type)
 {
-	int pin = irq_to_gpio(irq);
+	int pin = irq_to_gpio(d->irq);
 	struct irq_desc *desc;
 	u32 u;
 
 	u = readl(GPIO_IO_CONF(pin)) & (1 << (pin & 31));
 	if (!u) {
 		printk(KERN_ERR "orion gpio_irq_set_type failed "
-				"(irq %d, pin %d).\n", irq, pin);
+				"(irq %d, pin %d).\n", d->irq, pin);
 		return -EINVAL;
 	}
 
-	desc = irq_desc + irq;
+	desc = irq_desc + d->irq;
 
 	/*
 	 * Set edge/level type.
@@ -287,7 +286,7 @@ static int gpio_irq_set_type(u32 irq, u3
 	} else if (type & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) {
 		desc->handle_irq = handle_level_irq;
 	} else {
-		printk(KERN_ERR "failed to set irq=%d (type=%d)\n", irq, type);
+		printk(KERN_ERR "failed to set irq=%d (type=%d)\n", d->irq, type);
 		return -EINVAL;
 	}
 
@@ -325,10 +324,10 @@ static int gpio_irq_set_type(u32 irq, u3
 
 struct irq_chip orion_gpio_irq_chip = {
 	.name		= "orion_gpio_irq",
-	.ack		= gpio_irq_ack,
-	.mask		= gpio_irq_mask,
-	.unmask		= gpio_irq_unmask,
-	.set_type	= gpio_irq_set_type,
+	.irq_ack	= gpio_irq_ack,
+	.irq_mask	= gpio_irq_mask,
+	.irq_unmask	= gpio_irq_unmask,
+	.irq_set_type	= gpio_irq_set_type,
 };
 
 void orion_gpio_irq_handler(int pinoff)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-orion/irq.c linux-libre-2.6.38-gnu1/arch/arm/plat-orion/irq.c
--- linux-libre-2.6.37-gnu1/arch/arm/plat-orion/irq.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-orion/irq.c	2011-03-14 21:20:32.000000000 -0400
@@ -14,31 +14,31 @@
 #include <linux/io.h>
 #include <plat/irq.h>
 
-static void orion_irq_mask(u32 irq)
+static void orion_irq_mask(struct irq_data *d)
 {
-	void __iomem *maskaddr = get_irq_chip_data(irq);
+	void __iomem *maskaddr = irq_data_get_irq_chip_data(d);
 	u32 mask;
 
 	mask = readl(maskaddr);
-	mask &= ~(1 << (irq & 31));
+	mask &= ~(1 << (d->irq & 31));
 	writel(mask, maskaddr);
 }
 
-static void orion_irq_unmask(u32 irq)
+static void orion_irq_unmask(struct irq_data *d)
 {
-	void __iomem *maskaddr = get_irq_chip_data(irq);
+	void __iomem *maskaddr = irq_data_get_irq_chip_data(d);
 	u32 mask;
 
 	mask = readl(maskaddr);
-	mask |= 1 << (irq & 31);
+	mask |= 1 << (d->irq & 31);
 	writel(mask, maskaddr);
 }
 
 static struct irq_chip orion_irq_chip = {
 	.name		= "orion_irq",
-	.mask		= orion_irq_mask,
-	.mask_ack	= orion_irq_mask,
-	.unmask		= orion_irq_unmask,
+	.irq_mask	= orion_irq_mask,
+	.irq_mask_ack	= orion_irq_mask,
+	.irq_unmask	= orion_irq_unmask,
 };
 
 void __init orion_irq_init(unsigned int irq_start, void __iomem *maskaddr)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-orion/time.c linux-libre-2.6.38-gnu1/arch/arm/plat-orion/time.c
--- linux-libre-2.6.37-gnu1/arch/arm/plat-orion/time.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-orion/time.c	2011-03-14 21:20:32.000000000 -0400
@@ -13,11 +13,11 @@
 
 #include <linux/kernel.h>
 #include <linux/sched.h>
-#include <linux/cnt32_to_63.h>
 #include <linux/timer.h>
 #include <linux/clockchips.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
+#include <asm/sched_clock.h>
 #include <asm/mach/time.h>
 #include <mach/bridge-regs.h>
 #include <mach/hardware.h>
@@ -44,52 +44,26 @@ static u32 ticks_per_jiffy;
 
 /*
  * Orion's sched_clock implementation. It has a resolution of
- * at least 7.5ns (133MHz TCLK) and a maximum value of 834 days.
- *
- * Because the hardware timer period is quite short (21 secs if
- * 200MHz TCLK) and because cnt32_to_63() needs to be called at
- * least once per half period to work properly, a kernel timer is
- * set up to ensure this requirement is always met.
+ * at least 7.5ns (133MHz TCLK).
  */
-#define TCLK2NS_SCALE_FACTOR 8
-
-static unsigned long tclk2ns_scale;
+static DEFINE_CLOCK_DATA(cd);
 
-unsigned long long sched_clock(void)
+unsigned long long notrace sched_clock(void)
 {
-	unsigned long long v = cnt32_to_63(0xffffffff - readl(TIMER0_VAL));
-	return (v * tclk2ns_scale) >> TCLK2NS_SCALE_FACTOR;
+	u32 cyc = 0xffffffff - readl(TIMER0_VAL);
+	return cyc_to_sched_clock(&cd, cyc, (u32)~0);
 }
 
-static struct timer_list cnt32_to_63_keepwarm_timer;
 
-static void cnt32_to_63_keepwarm(unsigned long data)
+static void notrace orion_update_sched_clock(void)
 {
-	mod_timer(&cnt32_to_63_keepwarm_timer, round_jiffies(jiffies + data));
-	(void) sched_clock();
+	u32 cyc = 0xffffffff - readl(TIMER0_VAL);
+	update_sched_clock(&cd, cyc, (u32)~0);
 }
 
 static void __init setup_sched_clock(unsigned long tclk)
 {
-	unsigned long long v;
-	unsigned long data;
-
-	v = NSEC_PER_SEC;
-	v <<= TCLK2NS_SCALE_FACTOR;
-	v += tclk/2;
-	do_div(v, tclk);
-	/*
-	 * We want an even value to automatically clear the top bit
-	 * returned by cnt32_to_63() without an additional run time
-	 * instruction. So if the LSB is 1 then round it up.
-	 */
-	if (v & 1)
-		v++;
-	tclk2ns_scale = v;
-
-	data = (0xffffffffUL / tclk / 2 - 2) * HZ;
-	setup_timer(&cnt32_to_63_keepwarm_timer, cnt32_to_63_keepwarm, data);
-	mod_timer(&cnt32_to_63_keepwarm_timer, round_jiffies(jiffies + data));
+	init_sched_clock(&cd, orion_update_sched_clock, 32, tclk);
 }
 
 /*
@@ -102,7 +76,6 @@ static cycle_t orion_clksrc_read(struct
 
 static struct clocksource orion_clksrc = {
 	.name		= "orion_clocksource",
-	.shift		= 20,
 	.rating		= 300,
 	.read		= orion_clksrc_read,
 	.mask		= CLOCKSOURCE_MASK(32),
@@ -245,8 +218,7 @@ void __init orion_time_init(unsigned int
 	writel(u & ~BRIDGE_INT_TIMER0, BRIDGE_MASK);
 	u = readl(TIMER_CTRL);
 	writel(u | TIMER0_EN | TIMER0_RELOAD_EN, TIMER_CTRL);
-	orion_clksrc.mult = clocksource_hz2mult(tclk, orion_clksrc.shift);
-	clocksource_register(&orion_clksrc);
+	clocksource_register_hz(&orion_clksrc, tclk);
 
 	/*
 	 * Setup clockevent timer (interrupt-driven.)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-pxa/gpio.c linux-libre-2.6.38-gnu1/arch/arm/plat-pxa/gpio.c
--- linux-libre-2.6.37-gnu1/arch/arm/plat-pxa/gpio.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-pxa/gpio.c	2011-03-14 21:20:32.000000000 -0400
@@ -155,10 +155,10 @@ static inline void update_edge_detect(st
 	__raw_writel(gfer, c->regbase + GFER_OFFSET);
 }
 
-static int pxa_gpio_irq_type(unsigned int irq, unsigned int type)
+static int pxa_gpio_irq_type(struct irq_data *d, unsigned int type)
 {
 	struct pxa_gpio_chip *c;
-	int gpio = irq_to_gpio(irq);
+	int gpio = irq_to_gpio(d->irq);
 	unsigned long gpdr, mask = GPIO_bit(gpio);
 
 	c = gpio_to_chip(gpio);
@@ -195,7 +195,7 @@ static int pxa_gpio_irq_type(unsigned in
 
 	update_edge_detect(c);
 
-	pr_debug("%s: IRQ%d (GPIO%d) - edge%s%s\n", __func__, irq, gpio,
+	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;
@@ -227,17 +227,17 @@ static void pxa_gpio_demux_handler(unsig
 	} while (loop);
 }
 
-static void pxa_ack_muxed_gpio(unsigned int irq)
+static void pxa_ack_muxed_gpio(struct irq_data *d)
 {
-	int gpio = irq_to_gpio(irq);
+	int gpio = irq_to_gpio(d->irq);
 	struct pxa_gpio_chip *c = gpio_to_chip(gpio);
 
 	__raw_writel(GPIO_bit(gpio), c->regbase + GEDR_OFFSET);
 }
 
-static void pxa_mask_muxed_gpio(unsigned int irq)
+static void pxa_mask_muxed_gpio(struct irq_data *d)
 {
-	int gpio = irq_to_gpio(irq);
+	int gpio = irq_to_gpio(d->irq);
 	struct pxa_gpio_chip *c = gpio_to_chip(gpio);
 	uint32_t grer, gfer;
 
@@ -249,9 +249,9 @@ static void pxa_mask_muxed_gpio(unsigned
 	__raw_writel(gfer, c->regbase + GFER_OFFSET);
 }
 
-static void pxa_unmask_muxed_gpio(unsigned int irq)
+static void pxa_unmask_muxed_gpio(struct irq_data *d)
 {
-	int gpio = irq_to_gpio(irq);
+	int gpio = irq_to_gpio(d->irq);
 	struct pxa_gpio_chip *c = gpio_to_chip(gpio);
 
 	c->irq_mask |= GPIO_bit(gpio);
@@ -260,10 +260,10 @@ static void pxa_unmask_muxed_gpio(unsign
 
 static struct irq_chip pxa_muxed_gpio_chip = {
 	.name		= "GPIO",
-	.ack		= pxa_ack_muxed_gpio,
-	.mask		= pxa_mask_muxed_gpio,
-	.unmask		= pxa_unmask_muxed_gpio,
-	.set_type	= pxa_gpio_irq_type,
+	.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)
@@ -291,7 +291,7 @@ void __init pxa_init_gpio(int mux_irq, i
 
 	/* Install handler for GPIO>=2 edge detect interrupts */
 	set_irq_chained_handler(mux_irq, pxa_gpio_demux_handler);
-	pxa_muxed_gpio_chip.set_wake = fn;
+	pxa_muxed_gpio_chip.irq_set_wake = fn;
 }
 
 #ifdef CONFIG_PM
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-pxa/include/plat/gpio.h linux-libre-2.6.38-gnu1/arch/arm/plat-pxa/include/plat/gpio.h
--- linux-libre-2.6.37-gnu1/arch/arm/plat-pxa/include/plat/gpio.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-pxa/include/plat/gpio.h	2011-03-14 21:20:32.000000000 -0400
@@ -1,6 +1,8 @@
 #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:
@@ -56,7 +58,7 @@ static inline void gpio_set_value(unsign
  */
 extern int pxa_last_gpio;
 
-typedef int (*set_wake_t)(unsigned int irq, unsigned int on);
+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-2.6.37-gnu1/arch/arm/plat-pxa/include/plat/mfp.h linux-libre-2.6.38-gnu1/arch/arm/plat-pxa/include/plat/mfp.h
--- linux-libre-2.6.37-gnu1/arch/arm/plat-pxa/include/plat/mfp.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-pxa/include/plat/mfp.h	2011-03-14 21:20:32.000000000 -0400
@@ -423,7 +423,7 @@ typedef unsigned long mfp_cfg_t;
 	((MFP_CFG_DEFAULT & ~(MFP_AF_MASK | MFP_DS_MASK | MFP_LPM_STATE_MASK)) |\
 	 (MFP_PIN(MFP_PIN_##pin) | MFP_##af | MFP_##drv | MFP_LPM_##lpm))
 
-#if defined(CONFIG_PXA3xx) || defined(CONFIG_ARCH_MMP)
+#if defined(CONFIG_PXA3xx) || defined(CONFIG_PXA95x) || defined(CONFIG_ARCH_MMP)
 /*
  * each MFP pin will have a MFPR register, since the offset of the
  * register varies between processors, the processor specific code
@@ -470,6 +470,6 @@ void mfp_write(int mfp, unsigned long mf
 void mfp_config(unsigned long *mfp_cfgs, int num);
 void mfp_config_run(void);
 void mfp_config_lpm(void);
-#endif /* CONFIG_PXA3xx || CONFIG_ARCH_MMP */
+#endif /* CONFIG_PXA3xx || CONFIG_PXA95x || CONFIG_ARCH_MMP */
 
 #endif /* __ASM_PLAT_MFP_H */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-pxa/include/plat/ssp.h linux-libre-2.6.38-gnu1/arch/arm/plat-pxa/include/plat/ssp.h
--- linux-libre-2.6.37-gnu1/arch/arm/plat-pxa/include/plat/ssp.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-pxa/include/plat/ssp.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,186 +0,0 @@
-/*
- *  ssp.h
- *
- *  Copyright (C) 2003 Russell King, 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.
- *
- * This driver supports the following PXA CPU/SSP ports:-
- *
- *       PXA250     SSP
- *       PXA255     SSP, NSSP
- *       PXA26x     SSP, NSSP, ASSP
- *       PXA27x     SSP1, SSP2, SSP3
- *       PXA3xx     SSP1, SSP2, SSP3, SSP4
- */
-
-#ifndef __ASM_ARCH_SSP_H
-#define __ASM_ARCH_SSP_H
-
-#include <linux/list.h>
-#include <linux/io.h>
-
-/*
- * SSP Serial Port Registers
- * PXA250, PXA255, PXA26x and PXA27x SSP controllers are all slightly different.
- * PXA255, PXA26x and PXA27x have extra ports, registers and bits.
- */
-
-#define SSCR0		(0x00)  /* SSP Control Register 0 */
-#define SSCR1		(0x04)  /* SSP Control Register 1 */
-#define SSSR		(0x08)  /* SSP Status Register */
-#define SSITR		(0x0C)  /* SSP Interrupt Test Register */
-#define SSDR		(0x10)  /* SSP Data Write/Data Read Register */
-
-#define SSTO		(0x28)  /* SSP Time Out Register */
-#define SSPSP		(0x2C)  /* SSP Programmable Serial Protocol */
-#define SSTSA		(0x30)  /* SSP Tx Timeslot Active */
-#define SSRSA		(0x34)  /* SSP Rx Timeslot Active */
-#define SSTSS		(0x38)  /* SSP Timeslot Status */
-#define SSACD		(0x3C)  /* SSP Audio Clock Divider */
-#define SSACDD		(0x40)	/* SSP Audio Clock Dither Divider */
-
-/* Common PXA2xx bits first */
-#define SSCR0_DSS	(0x0000000f)	/* Data Size Select (mask) */
-#define SSCR0_DataSize(x)  ((x) - 1)	/* Data Size Select [4..16] */
-#define SSCR0_FRF	(0x00000030)	/* FRame Format (mask) */
-#define SSCR0_Motorola	(0x0 << 4)	/* Motorola's Serial Peripheral Interface (SPI) */
-#define SSCR0_TI	(0x1 << 4)	/* Texas Instruments' Synchronous Serial Protocol (SSP) */
-#define SSCR0_National	(0x2 << 4)	/* National Microwire */
-#define SSCR0_ECS	(1 << 6)	/* External clock select */
-#define SSCR0_SSE	(1 << 7)	/* Synchronous Serial Port Enable */
-#define SSCR0_SCR(x)	((x) << 8)	/* Serial Clock Rate (mask) */
-
-/* PXA27x, PXA3xx */
-#define SSCR0_EDSS	(1 << 20)	/* Extended data size select */
-#define SSCR0_NCS	(1 << 21)	/* Network clock select */
-#define SSCR0_RIM	(1 << 22)	/* Receive FIFO overrrun interrupt mask */
-#define SSCR0_TUM	(1 << 23)	/* Transmit FIFO underrun interrupt mask */
-#define SSCR0_FRDC	(0x07000000)	/* Frame rate divider control (mask) */
-#define SSCR0_SlotsPerFrm(x) (((x) - 1) << 24)	/* Time slots per frame [1..8] */
-#define SSCR0_FPCKE	(1 << 29)	/* FIFO packing enable */
-#define SSCR0_ACS	(1 << 30)	/* Audio clock select */
-#define SSCR0_MOD	(1 << 31)	/* Mode (normal or network) */
-
-
-#define SSCR1_RIE	(1 << 0)	/* Receive FIFO Interrupt Enable */
-#define SSCR1_TIE	(1 << 1)	/* Transmit FIFO Interrupt Enable */
-#define SSCR1_LBM	(1 << 2)	/* Loop-Back Mode */
-#define SSCR1_SPO	(1 << 3)	/* Motorola SPI SSPSCLK polarity setting */
-#define SSCR1_SPH	(1 << 4)	/* Motorola SPI SSPSCLK phase setting */
-#define SSCR1_MWDS	(1 << 5)	/* Microwire Transmit Data Size */
-#define SSCR1_TFT	(0x000003c0)	/* Transmit FIFO Threshold (mask) */
-#define SSCR1_TxTresh(x) (((x) - 1) << 6) /* level [1..16] */
-#define SSCR1_RFT	(0x00003c00)	/* Receive FIFO Threshold (mask) */
-#define SSCR1_RxTresh(x) (((x) - 1) << 10) /* level [1..16] */
-
-#define SSSR_TNF	(1 << 2)	/* Transmit FIFO Not Full */
-#define SSSR_RNE	(1 << 3)	/* Receive FIFO Not Empty */
-#define SSSR_BSY	(1 << 4)	/* SSP Busy */
-#define SSSR_TFS	(1 << 5)	/* Transmit FIFO Service Request */
-#define SSSR_RFS	(1 << 6)	/* Receive FIFO Service Request */
-#define SSSR_ROR	(1 << 7)	/* Receive FIFO Overrun */
-
-
-/* extra bits in PXA255, PXA26x and PXA27x SSP ports */
-#define SSCR0_TISSP		(1 << 4)	/* TI Sync Serial Protocol */
-#define SSCR0_PSP		(3 << 4)	/* PSP - Programmable Serial Protocol */
-#define SSCR1_TTELP		(1 << 31)	/* TXD Tristate Enable Last Phase */
-#define SSCR1_TTE		(1 << 30)	/* TXD Tristate Enable */
-#define SSCR1_EBCEI		(1 << 29)	/* Enable Bit Count Error interrupt */
-#define SSCR1_SCFR		(1 << 28)	/* Slave Clock free Running */
-#define SSCR1_ECRA		(1 << 27)	/* Enable Clock Request A */
-#define SSCR1_ECRB		(1 << 26)	/* Enable Clock request B */
-#define SSCR1_SCLKDIR		(1 << 25)	/* Serial Bit Rate Clock Direction */
-#define SSCR1_SFRMDIR		(1 << 24)	/* Frame Direction */
-#define SSCR1_RWOT		(1 << 23)	/* Receive Without Transmit */
-#define SSCR1_TRAIL		(1 << 22)	/* Trailing Byte */
-#define SSCR1_TSRE		(1 << 21)	/* Transmit Service Request Enable */
-#define SSCR1_RSRE		(1 << 20)	/* Receive Service Request Enable */
-#define SSCR1_TINTE		(1 << 19)	/* Receiver Time-out Interrupt enable */
-#define SSCR1_PINTE		(1 << 18)	/* Peripheral Trailing Byte Interupt Enable */
-#define SSCR1_IFS		(1 << 16)	/* Invert Frame Signal */
-#define SSCR1_STRF		(1 << 15)	/* Select FIFO or EFWR */
-#define SSCR1_EFWR		(1 << 14)	/* Enable FIFO Write/Read */
-
-#define SSSR_BCE		(1 << 23)	/* Bit Count Error */
-#define SSSR_CSS		(1 << 22)	/* Clock Synchronisation Status */
-#define SSSR_TUR		(1 << 21)	/* Transmit FIFO Under Run */
-#define SSSR_EOC		(1 << 20)	/* End Of Chain */
-#define SSSR_TINT		(1 << 19)	/* Receiver Time-out Interrupt */
-#define SSSR_PINT		(1 << 18)	/* Peripheral Trailing Byte Interrupt */
-
-
-#define SSPSP_SCMODE(x)		((x) << 0)	/* Serial Bit Rate Clock Mode */
-#define SSPSP_SFRMP		(1 << 2)	/* Serial Frame Polarity */
-#define SSPSP_ETDS		(1 << 3)	/* End of Transfer data State */
-#define SSPSP_STRTDLY(x)	((x) << 4)	/* Start Delay */
-#define SSPSP_DMYSTRT(x)	((x) << 7)	/* Dummy Start */
-#define SSPSP_SFRMDLY(x)	((x) << 9)	/* Serial Frame Delay */
-#define SSPSP_SFRMWDTH(x)	((x) << 16)	/* Serial Frame Width */
-#define SSPSP_DMYSTOP(x)	((x) << 23)	/* Dummy Stop */
-#define SSPSP_FSRT		(1 << 25)	/* Frame Sync Relative Timing */
-
-/* PXA3xx */
-#define SSPSP_EDMYSTRT(x)	((x) << 26)     /* Extended Dummy Start */
-#define SSPSP_EDMYSTOP(x)	((x) << 28)     /* Extended Dummy Stop */
-#define SSPSP_TIMING_MASK	(0x7f8001f0)
-
-#define SSACD_SCDB		(1 << 3)	/* SSPSYSCLK Divider Bypass */
-#define SSACD_ACPS(x)		((x) << 4)	/* Audio clock PLL select */
-#define SSACD_ACDS(x)		((x) << 0)	/* Audio clock divider select */
-#define SSACD_SCDX8		(1 << 7)	/* SYSCLK division ratio select */
-
-enum pxa_ssp_type {
-	SSP_UNDEFINED = 0,
-	PXA25x_SSP,  /* pxa 210, 250, 255, 26x */
-	PXA25x_NSSP, /* pxa 255, 26x (including ASSP) */
-	PXA27x_SSP,
-	PXA168_SSP,
-};
-
-struct ssp_device {
-	struct platform_device *pdev;
-	struct list_head	node;
-
-	struct clk	*clk;
-	void __iomem	*mmio_base;
-	unsigned long	phys_base;
-
-	const char	*label;
-	int		port_id;
-	int		type;
-	int		use_count;
-	int		irq;
-	int		drcmr_rx;
-	int		drcmr_tx;
-};
-
-/**
- * pxa_ssp_write_reg - Write to a SSP register
- *
- * @dev: SSP device to access
- * @reg: Register to write to
- * @val: Value to be written.
- */
-static inline void pxa_ssp_write_reg(struct ssp_device *dev, u32 reg, u32 val)
-{
-	__raw_writel(val, dev->mmio_base + reg);
-}
-
-/**
- * pxa_ssp_read_reg - Read from a SSP register
- *
- * @dev: SSP device to access
- * @reg: Register to read from
- */
-static inline u32 pxa_ssp_read_reg(struct ssp_device *dev, u32 reg)
-{
-	return __raw_readl(dev->mmio_base + reg);
-}
-
-struct ssp_device *pxa_ssp_request(int port, const char *label);
-void pxa_ssp_free(struct ssp_device *);
-#endif /* __ASM_ARCH_SSP_H */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-pxa/Makefile linux-libre-2.6.38-gnu1/arch/arm/plat-pxa/Makefile
--- linux-libre-2.6.37-gnu1/arch/arm/plat-pxa/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-pxa/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -6,6 +6,7 @@ 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
 
 obj-$(CONFIG_HAVE_PWM)		+= pwm.o
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-pxa/mfp.c linux-libre-2.6.38-gnu1/arch/arm/plat-pxa/mfp.c
--- linux-libre-2.6.37-gnu1/arch/arm/plat-pxa/mfp.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-pxa/mfp.c	2011-03-14 21:20:32.000000000 -0400
@@ -139,10 +139,11 @@ static const unsigned long mfpr_edge[] =
 #define mfp_configured(p)	((p)->config != -1)
 
 /*
- * perform a read-back of any MFPR register to make sure the
+ * perform a read-back of any valid MFPR register to make sure the
  * previous writings are finished
  */
-#define mfpr_sync()	(void)__raw_readl(mfpr_mmio_base + 0)
+static unsigned long mfpr_off_readback;
+#define mfpr_sync()	(void)__raw_readl(mfpr_mmio_base + mfpr_off_readback)
 
 static inline void __mfp_config_run(struct mfp_pin *p)
 {
@@ -248,6 +249,9 @@ void __init mfp_init_addr(struct mfp_add
 
 	spin_lock_irqsave(&mfp_spin_lock, flags);
 
+	/* mfp offset for readback */
+	mfpr_off_readback = map[0].offset;
+
 	for (p = map; p->start != MFP_PIN_INVALID; p++) {
 		offset = p->offset;
 		i = p->start;
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-pxa/ssp.c linux-libre-2.6.38-gnu1/arch/arm/plat-pxa/ssp.c
--- linux-libre-2.6.37-gnu1/arch/arm/plat-pxa/ssp.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-pxa/ssp.c	2011-03-14 21:20:32.000000000 -0400
@@ -28,11 +28,11 @@
 #include <linux/clk.h>
 #include <linux/err.h>
 #include <linux/platform_device.h>
+#include <linux/spi/pxa2xx_spi.h>
 #include <linux/io.h>
 
 #include <asm/irq.h>
 #include <mach/hardware.h>
-#include <plat/ssp.h>
 
 static DEFINE_MUTEX(ssp_lock);
 static LIST_HEAD(ssp_list);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-s3c24xx/cpu-freq.c linux-libre-2.6.38-gnu1/arch/arm/plat-s3c24xx/cpu-freq.c
--- linux-libre-2.6.37-gnu1/arch/arm/plat-s3c24xx/cpu-freq.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-s3c24xx/cpu-freq.c	2011-03-14 21:20:32.000000000 -0400
@@ -21,7 +21,6 @@
 #include <linux/err.h>
 #include <linux/io.h>
 #include <linux/sysdev.h>
-#include <linux/kobject.h>
 #include <linux/sysfs.h>
 #include <linux/slab.h>
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-s3c24xx/devs.c linux-libre-2.6.38-gnu1/arch/arm/plat-s3c24xx/devs.c
--- linux-libre-2.6.37-gnu1/arch/arm/plat-s3c24xx/devs.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-s3c24xx/devs.c	2011-03-14 21:20:32.000000000 -0400
@@ -194,7 +194,6 @@ void __init s3c24xx_ts_set_platdata(stru
 	memcpy(&s3c2410ts_info, hard_s3c2410ts_info, sizeof(struct s3c2410_ts_mach_info));
 	s3c_device_ts.dev.platform_data = &s3c2410ts_info;
 }
-EXPORT_SYMBOL(s3c24xx_ts_set_platdata);
 
 /* USB Device (Gadget)*/
 
@@ -259,21 +258,6 @@ struct platform_device s3c_device_iis =
 
 EXPORT_SYMBOL(s3c_device_iis);
 
-/* ASoC PCM DMA */
-
-static u64 s3c_device_audio_dmamask = 0xffffffffUL;
-
-struct platform_device s3c_device_pcm = {
-	.name		  = "s3c24xx-pcm-audio",
-	.id		  = -1,
-	.dev              = {
-		.dma_mask = &s3c_device_audio_dmamask,
-		.coherent_dma_mask = 0xffffffffUL
-	}
-};
-
-EXPORT_SYMBOL(s3c_device_pcm);
-
 /* RTC */
 
 static struct resource s3c_rtc_resource[] = {
@@ -496,8 +480,10 @@ static struct resource s3c_ac97_resource
 	},
 };
 
+static u64 s3c_device_audio_dmamask = 0xffffffffUL;
+
 struct platform_device s3c_device_ac97 = {
-	.name		  = "s3c-ac97",
+	.name		  = "samsung-ac97",
 	.id		  = -1,
 	.num_resources	  = ARRAY_SIZE(s3c_ac97_resource),
 	.resource	  = s3c_ac97_resource,
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-s3c24xx/include/plat/irq.h linux-libre-2.6.38-gnu1/arch/arm/plat-s3c24xx/include/plat/irq.h
--- linux-libre-2.6.37-gnu1/arch/arm/plat-s3c24xx/include/plat/irq.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-s3c24xx/include/plat/irq.h	2011-03-14 21:20:32.000000000 -0400
@@ -107,9 +107,9 @@ s3c_irqsub_ack(unsigned int irqno, unsig
 /* exported for use in arch/arm/mach-s3c2410 */
 
 #ifdef CONFIG_PM
-extern int s3c_irq_wake(unsigned int irqno, unsigned int state);
+extern int s3c_irq_wake(struct irq_data *data, unsigned int state);
 #else
 #define s3c_irq_wake NULL
 #endif
 
-extern int s3c_irqext_type(unsigned int irq, unsigned int type);
+extern int s3c_irqext_type(struct irq_data *d, unsigned int type);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-s3c24xx/irq.c linux-libre-2.6.38-gnu1/arch/arm/plat-s3c24xx/irq.c
--- linux-libre-2.6.37-gnu1/arch/arm/plat-s3c24xx/irq.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-s3c24xx/irq.c	2011-03-14 21:20:32.000000000 -0400
@@ -34,30 +34,29 @@
 #include <plat/irq.h>
 
 static void
-s3c_irq_mask(unsigned int irqno)
+s3c_irq_mask(struct irq_data *data)
 {
+	unsigned int irqno = data->irq - IRQ_EINT0;
 	unsigned long mask;
 
-	irqno -= IRQ_EINT0;
-
 	mask = __raw_readl(S3C2410_INTMSK);
 	mask |= 1UL << irqno;
 	__raw_writel(mask, S3C2410_INTMSK);
 }
 
 static inline void
-s3c_irq_ack(unsigned int irqno)
+s3c_irq_ack(struct irq_data *data)
 {
-	unsigned long bitval = 1UL << (irqno - IRQ_EINT0);
+	unsigned long bitval = 1UL << (data->irq - IRQ_EINT0);
 
 	__raw_writel(bitval, S3C2410_SRCPND);
 	__raw_writel(bitval, S3C2410_INTPND);
 }
 
 static inline void
-s3c_irq_maskack(unsigned int irqno)
+s3c_irq_maskack(struct irq_data *data)
 {
-	unsigned long bitval = 1UL << (irqno - IRQ_EINT0);
+	unsigned long bitval = 1UL << (data->irq - IRQ_EINT0);
 	unsigned long mask;
 
 	mask = __raw_readl(S3C2410_INTMSK);
@@ -69,8 +68,9 @@ s3c_irq_maskack(unsigned int irqno)
 
 
 static void
-s3c_irq_unmask(unsigned int irqno)
+s3c_irq_unmask(struct irq_data *data)
 {
+	unsigned int irqno = data->irq;
 	unsigned long mask;
 
 	if (irqno != IRQ_TIMER4 && irqno != IRQ_EINT8t23)
@@ -85,40 +85,39 @@ s3c_irq_unmask(unsigned int irqno)
 
 struct irq_chip s3c_irq_level_chip = {
 	.name		= "s3c-level",
-	.ack		= s3c_irq_maskack,
-	.mask		= s3c_irq_mask,
-	.unmask		= s3c_irq_unmask,
-	.set_wake	= s3c_irq_wake
+	.irq_ack	= s3c_irq_maskack,
+	.irq_mask	= s3c_irq_mask,
+	.irq_unmask	= s3c_irq_unmask,
+	.irq_set_wake	= s3c_irq_wake
 };
 
 struct irq_chip s3c_irq_chip = {
 	.name		= "s3c",
-	.ack		= s3c_irq_ack,
-	.mask		= s3c_irq_mask,
-	.unmask		= s3c_irq_unmask,
-	.set_wake	= s3c_irq_wake
+	.irq_ack	= s3c_irq_ack,
+	.irq_mask	= s3c_irq_mask,
+	.irq_unmask	= s3c_irq_unmask,
+	.irq_set_wake	= s3c_irq_wake
 };
 
 static void
-s3c_irqext_mask(unsigned int irqno)
+s3c_irqext_mask(struct irq_data *data)
 {
+	unsigned int irqno = data->irq - EXTINT_OFF;
 	unsigned long mask;
 
-	irqno -= EXTINT_OFF;
-
 	mask = __raw_readl(S3C24XX_EINTMASK);
 	mask |= ( 1UL << irqno);
 	__raw_writel(mask, S3C24XX_EINTMASK);
 }
 
 static void
-s3c_irqext_ack(unsigned int irqno)
+s3c_irqext_ack(struct irq_data *data)
 {
 	unsigned long req;
 	unsigned long bit;
 	unsigned long mask;
 
-	bit = 1UL << (irqno - EXTINT_OFF);
+	bit = 1UL << (data->irq - EXTINT_OFF);
 
 	mask = __raw_readl(S3C24XX_EINTMASK);
 
@@ -129,64 +128,57 @@ s3c_irqext_ack(unsigned int irqno)
 
 	/* not sure if we should be acking the parent irq... */
 
-	if (irqno <= IRQ_EINT7 ) {
+	if (data->irq <= IRQ_EINT7) {
 		if ((req & 0xf0) == 0)
-			s3c_irq_ack(IRQ_EINT4t7);
+			s3c_irq_ack(irq_get_irq_data(IRQ_EINT4t7));
 	} else {
 		if ((req >> 8) == 0)
-			s3c_irq_ack(IRQ_EINT8t23);
+			s3c_irq_ack(irq_get_irq_data(IRQ_EINT8t23));
 	}
 }
 
 static void
-s3c_irqext_unmask(unsigned int irqno)
+s3c_irqext_unmask(struct irq_data *data)
 {
+	unsigned int irqno = data->irq - EXTINT_OFF;
 	unsigned long mask;
 
-	irqno -= EXTINT_OFF;
-
 	mask = __raw_readl(S3C24XX_EINTMASK);
-	mask &= ~( 1UL << irqno);
+	mask &= ~(1UL << irqno);
 	__raw_writel(mask, S3C24XX_EINTMASK);
 }
 
 int
-s3c_irqext_type(unsigned int irq, unsigned int type)
+s3c_irqext_type(struct irq_data *data, unsigned int type)
 {
 	void __iomem *extint_reg;
 	void __iomem *gpcon_reg;
 	unsigned long gpcon_offset, extint_offset;
 	unsigned long newvalue = 0, value;
 
-	if ((irq >= IRQ_EINT0) && (irq <= IRQ_EINT3))
-	{
+	if ((data->irq >= IRQ_EINT0) && (data->irq <= IRQ_EINT3)) {
 		gpcon_reg = S3C2410_GPFCON;
 		extint_reg = S3C24XX_EXTINT0;
-		gpcon_offset = (irq - IRQ_EINT0) * 2;
-		extint_offset = (irq - IRQ_EINT0) * 4;
-	}
-	else if ((irq >= IRQ_EINT4) && (irq <= IRQ_EINT7))
-	{
+		gpcon_offset = (data->irq - IRQ_EINT0) * 2;
+		extint_offset = (data->irq - IRQ_EINT0) * 4;
+	} else if ((data->irq >= IRQ_EINT4) && (data->irq <= IRQ_EINT7)) {
 		gpcon_reg = S3C2410_GPFCON;
 		extint_reg = S3C24XX_EXTINT0;
-		gpcon_offset = (irq - (EXTINT_OFF)) * 2;
-		extint_offset = (irq - (EXTINT_OFF)) * 4;
-	}
-	else if ((irq >= IRQ_EINT8) && (irq <= IRQ_EINT15))
-	{
+		gpcon_offset = (data->irq - (EXTINT_OFF)) * 2;
+		extint_offset = (data->irq - (EXTINT_OFF)) * 4;
+	} else if ((data->irq >= IRQ_EINT8) && (data->irq <= IRQ_EINT15)) {
 		gpcon_reg = S3C2410_GPGCON;
 		extint_reg = S3C24XX_EXTINT1;
-		gpcon_offset = (irq - IRQ_EINT8) * 2;
-		extint_offset = (irq - IRQ_EINT8) * 4;
-	}
-	else if ((irq >= IRQ_EINT16) && (irq <= IRQ_EINT23))
-	{
+		gpcon_offset = (data->irq - IRQ_EINT8) * 2;
+		extint_offset = (data->irq - IRQ_EINT8) * 4;
+	} else if ((data->irq >= IRQ_EINT16) && (data->irq <= IRQ_EINT23)) {
 		gpcon_reg = S3C2410_GPGCON;
 		extint_reg = S3C24XX_EXTINT2;
-		gpcon_offset = (irq - IRQ_EINT8) * 2;
-		extint_offset = (irq - IRQ_EINT16) * 4;
-	} else
+		gpcon_offset = (data->irq - IRQ_EINT8) * 2;
+		extint_offset = (data->irq - IRQ_EINT16) * 4;
+	} else {
 		return -1;
+	}
 
 	/* Set the GPIO to external interrupt mode */
 	value = __raw_readl(gpcon_reg);
@@ -234,20 +226,20 @@ s3c_irqext_type(unsigned int irq, unsign
 
 static struct irq_chip s3c_irqext_chip = {
 	.name		= "s3c-ext",
-	.mask		= s3c_irqext_mask,
-	.unmask		= s3c_irqext_unmask,
-	.ack		= s3c_irqext_ack,
-	.set_type	= s3c_irqext_type,
-	.set_wake	= s3c_irqext_wake
+	.irq_mask	= s3c_irqext_mask,
+	.irq_unmask	= s3c_irqext_unmask,
+	.irq_ack	= s3c_irqext_ack,
+	.irq_set_type	= s3c_irqext_type,
+	.irq_set_wake	= s3c_irqext_wake
 };
 
 static struct irq_chip s3c_irq_eint0t4 = {
 	.name		= "s3c-ext0",
-	.ack		= s3c_irq_ack,
-	.mask		= s3c_irq_mask,
-	.unmask		= s3c_irq_unmask,
-	.set_wake	= s3c_irq_wake,
-	.set_type	= s3c_irqext_type,
+	.irq_ack	= s3c_irq_ack,
+	.irq_mask	= s3c_irq_mask,
+	.irq_unmask	= s3c_irq_unmask,
+	.irq_set_wake	= s3c_irq_wake,
+	.irq_set_type	= s3c_irqext_type,
 };
 
 /* mask values for the parent registers for each of the interrupt types */
@@ -261,109 +253,109 @@ static struct irq_chip s3c_irq_eint0t4 =
 /* UART0 */
 
 static void
-s3c_irq_uart0_mask(unsigned int irqno)
+s3c_irq_uart0_mask(struct irq_data *data)
 {
-	s3c_irqsub_mask(irqno, INTMSK_UART0, 7);
+	s3c_irqsub_mask(data->irq, INTMSK_UART0, 7);
 }
 
 static void
-s3c_irq_uart0_unmask(unsigned int irqno)
+s3c_irq_uart0_unmask(struct irq_data *data)
 {
-	s3c_irqsub_unmask(irqno, INTMSK_UART0);
+	s3c_irqsub_unmask(data->irq, INTMSK_UART0);
 }
 
 static void
-s3c_irq_uart0_ack(unsigned int irqno)
+s3c_irq_uart0_ack(struct irq_data *data)
 {
-	s3c_irqsub_maskack(irqno, INTMSK_UART0, 7);
+	s3c_irqsub_maskack(data->irq, INTMSK_UART0, 7);
 }
 
 static struct irq_chip s3c_irq_uart0 = {
 	.name		= "s3c-uart0",
-	.mask		= s3c_irq_uart0_mask,
-	.unmask		= s3c_irq_uart0_unmask,
-	.ack		= s3c_irq_uart0_ack,
+	.irq_mask	= s3c_irq_uart0_mask,
+	.irq_unmask	= s3c_irq_uart0_unmask,
+	.irq_ack	= s3c_irq_uart0_ack,
 };
 
 /* UART1 */
 
 static void
-s3c_irq_uart1_mask(unsigned int irqno)
+s3c_irq_uart1_mask(struct irq_data *data)
 {
-	s3c_irqsub_mask(irqno, INTMSK_UART1, 7 << 3);
+	s3c_irqsub_mask(data->irq, INTMSK_UART1, 7 << 3);
 }
 
 static void
-s3c_irq_uart1_unmask(unsigned int irqno)
+s3c_irq_uart1_unmask(struct irq_data *data)
 {
-	s3c_irqsub_unmask(irqno, INTMSK_UART1);
+	s3c_irqsub_unmask(data->irq, INTMSK_UART1);
 }
 
 static void
-s3c_irq_uart1_ack(unsigned int irqno)
+s3c_irq_uart1_ack(struct irq_data *data)
 {
-	s3c_irqsub_maskack(irqno, INTMSK_UART1, 7 << 3);
+	s3c_irqsub_maskack(data->irq, INTMSK_UART1, 7 << 3);
 }
 
 static struct irq_chip s3c_irq_uart1 = {
 	.name		= "s3c-uart1",
-	.mask		= s3c_irq_uart1_mask,
-	.unmask		= s3c_irq_uart1_unmask,
-	.ack		= s3c_irq_uart1_ack,
+	.irq_mask	= s3c_irq_uart1_mask,
+	.irq_unmask	= s3c_irq_uart1_unmask,
+	.irq_ack	= s3c_irq_uart1_ack,
 };
 
 /* UART2 */
 
 static void
-s3c_irq_uart2_mask(unsigned int irqno)
+s3c_irq_uart2_mask(struct irq_data *data)
 {
-	s3c_irqsub_mask(irqno, INTMSK_UART2, 7 << 6);
+	s3c_irqsub_mask(data->irq, INTMSK_UART2, 7 << 6);
 }
 
 static void
-s3c_irq_uart2_unmask(unsigned int irqno)
+s3c_irq_uart2_unmask(struct irq_data *data)
 {
-	s3c_irqsub_unmask(irqno, INTMSK_UART2);
+	s3c_irqsub_unmask(data->irq, INTMSK_UART2);
 }
 
 static void
-s3c_irq_uart2_ack(unsigned int irqno)
+s3c_irq_uart2_ack(struct irq_data *data)
 {
-	s3c_irqsub_maskack(irqno, INTMSK_UART2, 7 << 6);
+	s3c_irqsub_maskack(data->irq, INTMSK_UART2, 7 << 6);
 }
 
 static struct irq_chip s3c_irq_uart2 = {
 	.name		= "s3c-uart2",
-	.mask		= s3c_irq_uart2_mask,
-	.unmask		= s3c_irq_uart2_unmask,
-	.ack		= s3c_irq_uart2_ack,
+	.irq_mask	= s3c_irq_uart2_mask,
+	.irq_unmask	= s3c_irq_uart2_unmask,
+	.irq_ack	= s3c_irq_uart2_ack,
 };
 
 /* ADC and Touchscreen */
 
 static void
-s3c_irq_adc_mask(unsigned int irqno)
+s3c_irq_adc_mask(struct irq_data *d)
 {
-	s3c_irqsub_mask(irqno, INTMSK_ADCPARENT, 3 << 9);
+	s3c_irqsub_mask(d->irq, INTMSK_ADCPARENT, 3 << 9);
 }
 
 static void
-s3c_irq_adc_unmask(unsigned int irqno)
+s3c_irq_adc_unmask(struct irq_data *d)
 {
-	s3c_irqsub_unmask(irqno, INTMSK_ADCPARENT);
+	s3c_irqsub_unmask(d->irq, INTMSK_ADCPARENT);
 }
 
 static void
-s3c_irq_adc_ack(unsigned int irqno)
+s3c_irq_adc_ack(struct irq_data *d)
 {
-	s3c_irqsub_ack(irqno, INTMSK_ADCPARENT, 3 << 9);
+	s3c_irqsub_ack(d->irq, INTMSK_ADCPARENT, 3 << 9);
 }
 
 static struct irq_chip s3c_irq_adc = {
 	.name		= "s3c-adc",
-	.mask		= s3c_irq_adc_mask,
-	.unmask		= s3c_irq_adc_unmask,
-	.ack		= s3c_irq_adc_ack,
+	.irq_mask	= s3c_irq_adc_mask,
+	.irq_unmask	= s3c_irq_adc_unmask,
+	.irq_ack	= s3c_irq_adc_ack,
 };
 
 /* irq demux for adc */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-s3c24xx/irq-pm.c linux-libre-2.6.38-gnu1/arch/arm/plat-s3c24xx/irq-pm.c
--- linux-libre-2.6.37-gnu1/arch/arm/plat-s3c24xx/irq-pm.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-s3c24xx/irq-pm.c	2011-03-14 21:20:32.000000000 -0400
@@ -15,11 +15,14 @@
 #include <linux/module.h>
 #include <linux/interrupt.h>
 #include <linux/sysdev.h>
+#include <linux/irq.h>
 
 #include <plat/cpu.h>
 #include <plat/pm.h>
 #include <plat/irq.h>
 
+#include <asm/irq.h>
+
 /* state for IRQs over sleep */
 
 /* default is to allow for EINT0..EINT15, and IRQ_RTC as wakeup sources
@@ -30,15 +33,15 @@
 unsigned long s3c_irqwake_intallow	= 1L << (IRQ_RTC - IRQ_EINT0) | 0xfL;
 unsigned long s3c_irqwake_eintallow	= 0x0000fff0L;
 
-int s3c_irq_wake(unsigned int irqno, unsigned int state)
+int s3c_irq_wake(struct irq_data *data, unsigned int state)
 {
-	unsigned long irqbit = 1 << (irqno - IRQ_EINT0);
+	unsigned long irqbit = 1 << (data->irq - IRQ_EINT0);
 
 	if (!(s3c_irqwake_intallow & irqbit))
 		return -ENOENT;
 
 	printk(KERN_INFO "wake %s for irq %d\n",
-	       state ? "enabled" : "disabled", irqno);
+	       state ? "enabled" : "disabled", data->irq);
 
 	if (!state)
 		s3c_irqwake_intmask |= irqbit;
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-s3c24xx/s3c2443-clock.c linux-libre-2.6.38-gnu1/arch/arm/plat-s3c24xx/s3c2443-clock.c
--- linux-libre-2.6.37-gnu1/arch/arm/plat-s3c24xx/s3c2443-clock.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-s3c24xx/s3c2443-clock.c	2011-03-14 21:20:32.000000000 -0400
@@ -271,7 +271,7 @@ static struct clk init_clocks[] = {
 		.ctrlbit	= S3C2443_HCLKCON_DMA5,
 	}, {
 		.name		= "hsmmc",
-		.id		= 0,
+		.id		= 1,
 		.parent		= &clk_h,
 		.enable		= s3c2443_clkcon_enable_h,
 		.ctrlbit	= S3C2443_HCLKCON_HSMMC,
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-s5p/cpu.c linux-libre-2.6.38-gnu1/arch/arm/plat-s5p/cpu.c
--- linux-libre-2.6.37-gnu1/arch/arm/plat-s5p/cpu.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-s5p/cpu.c	2011-03-14 21:20:32.000000000 -0400
@@ -108,6 +108,11 @@ static struct map_desc s5p_iodesc[] __in
 		.pfn		= __phys_to_pfn(S3C_PA_WDT),
 		.length		= SZ_4K,
 		.type		= MT_DEVICE,
+	}, {
+		.virtual	= (unsigned long)S5P_VA_SROMC,
+		.pfn		= __phys_to_pfn(S5P_PA_SROMC),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE,
 	},
 };
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-s5p/dev-csis0.c linux-libre-2.6.38-gnu1/arch/arm/plat-s5p/dev-csis0.c
--- linux-libre-2.6.37-gnu1/arch/arm/plat-s5p/dev-csis0.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-s5p/dev-csis0.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2010 Samsung Electronics
+ *
+ * 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-2.6.37-gnu1/arch/arm/plat-s5p/dev-csis1.c linux-libre-2.6.38-gnu1/arch/arm/plat-s5p/dev-csis1.c
--- linux-libre-2.6.37-gnu1/arch/arm/plat-s5p/dev-csis1.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-s5p/dev-csis1.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2010 Samsung Electronics
+ *
+ * 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-2.6.37-gnu1/arch/arm/plat-s5p/dev-uart.c linux-libre-2.6.38-gnu1/arch/arm/plat-s5p/dev-uart.c
--- linux-libre-2.6.37-gnu1/arch/arm/plat-s5p/dev-uart.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-s5p/dev-uart.c	2011-03-14 21:20:32.000000000 -0400
@@ -28,7 +28,7 @@
 static struct resource s5p_uart0_resource[] = {
 	[0] = {
 		.start	= S5P_PA_UART0,
-		.end	= S5P_PA_UART0 + S5P_SZ_UART,
+		.end	= S5P_PA_UART0 + S5P_SZ_UART - 1,
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
@@ -51,7 +51,7 @@ static struct resource s5p_uart0_resourc
 static struct resource s5p_uart1_resource[] = {
 	[0] = {
 		.start	= S5P_PA_UART1,
-		.end	= S5P_PA_UART1 + S5P_SZ_UART,
+		.end	= S5P_PA_UART1 + S5P_SZ_UART - 1,
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
@@ -74,7 +74,7 @@ static struct resource s5p_uart1_resourc
 static struct resource s5p_uart2_resource[] = {
 	[0] = {
 		.start	= S5P_PA_UART2,
-		.end	= S5P_PA_UART2 + S5P_SZ_UART,
+		.end	= S5P_PA_UART2 + S5P_SZ_UART - 1,
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
@@ -98,7 +98,7 @@ static struct resource s5p_uart3_resourc
 #if CONFIG_SERIAL_SAMSUNG_UARTS > 3
 	[0] = {
 		.start	= S5P_PA_UART3,
-		.end	= S5P_PA_UART3 + S5P_SZ_UART,
+		.end	= S5P_PA_UART3 + S5P_SZ_UART - 1,
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
@@ -123,7 +123,7 @@ static struct resource s5p_uart4_resourc
 #if CONFIG_SERIAL_SAMSUNG_UARTS > 4
 	[0] = {
 		.start	= S5P_PA_UART4,
-		.end	= S5P_PA_UART4 + S5P_SZ_UART,
+		.end	= S5P_PA_UART4 + S5P_SZ_UART - 1,
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
@@ -148,7 +148,7 @@ static struct resource s5p_uart5_resourc
 #if CONFIG_SERIAL_SAMSUNG_UARTS > 5
 	[0] = {
 		.start	= S5P_PA_UART5,
-		.end	= S5P_PA_UART5 + S5P_SZ_UART,
+		.end	= S5P_PA_UART5 + S5P_SZ_UART - 1,
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-s5p/include/plat/csis.h linux-libre-2.6.38-gnu1/arch/arm/plat-s5p/include/plat/csis.h
--- linux-libre-2.6.37-gnu1/arch/arm/plat-s5p/include/plat/csis.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-s5p/include/plat/csis.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2010 Samsung Electronics
+ *
+ * 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_CSIS_H_
+#define PLAT_S5P_CSIS_H_ __FILE__
+
+/**
+ * struct s5p_platform_mipi_csis - platform data for MIPI-CSIS
+ * @clk_rate: bus clock frequency
+ * @lanes: number of data lanes used
+ * @alignment: data alignment in bits
+ * @hs_settle: HS-RX settle time
+ */
+struct s5p_platform_mipi_csis {
+	unsigned long clk_rate;
+	u8 lanes;
+	u8 alignment;
+	u8 hs_settle;
+};
+
+#endif /* PLAT_S5P_CSIS_H_ */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-s5p/include/plat/map-s5p.h linux-libre-2.6.38-gnu1/arch/arm/plat-s5p/include/plat/map-s5p.h
--- linux-libre-2.6.37-gnu1/arch/arm/plat-s5p/include/plat/map-s5p.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-s5p/include/plat/map-s5p.h	2011-03-14 21:20:32.000000000 -0400
@@ -15,6 +15,7 @@
 
 #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)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-s5p/include/plat/regs-srom.h linux-libre-2.6.38-gnu1/arch/arm/plat-s5p/include/plat/regs-srom.h
--- linux-libre-2.6.37-gnu1/arch/arm/plat-s5p/include/plat/regs-srom.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-s5p/include/plat/regs-srom.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,54 @@
+/* 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-2.6.37-gnu1/arch/arm/plat-s5p/irq-eint.c linux-libre-2.6.38-gnu1/arch/arm/plat-s5p/irq-eint.c
--- linux-libre-2.6.37-gnu1/arch/arm/plat-s5p/irq-eint.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-s5p/irq-eint.c	2011-03-14 21:20:32.000000000 -0400
@@ -28,39 +28,40 @@
 #include <plat/gpio-cfg.h>
 #include <mach/regs-gpio.h>
 
-static inline void s5p_irq_eint_mask(unsigned int irq)
+static inline void s5p_irq_eint_mask(struct irq_data *data)
 {
 	u32 mask;
 
-	mask = __raw_readl(S5P_EINT_MASK(EINT_REG_NR(irq)));
-	mask |= eint_irq_to_bit(irq);
-	__raw_writel(mask, S5P_EINT_MASK(EINT_REG_NR(irq)));
+	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)));
 }
 
-static void s5p_irq_eint_unmask(unsigned int irq)
+static void s5p_irq_eint_unmask(struct irq_data *data)
 {
 	u32 mask;
 
-	mask = __raw_readl(S5P_EINT_MASK(EINT_REG_NR(irq)));
-	mask &= ~(eint_irq_to_bit(irq));
-	__raw_writel(mask, S5P_EINT_MASK(EINT_REG_NR(irq)));
+	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)));
 }
 
-static inline void s5p_irq_eint_ack(unsigned int irq)
+static inline void s5p_irq_eint_ack(struct irq_data *data)
 {
-	__raw_writel(eint_irq_to_bit(irq), S5P_EINT_PEND(EINT_REG_NR(irq)));
+	__raw_writel(eint_irq_to_bit(data->irq),
+		     S5P_EINT_PEND(EINT_REG_NR(data->irq)));
 }
 
-static void s5p_irq_eint_maskack(unsigned int irq)
+static void s5p_irq_eint_maskack(struct irq_data *data)
 {
 	/* compiler should in-line these */
-	s5p_irq_eint_mask(irq);
-	s5p_irq_eint_ack(irq);
+	s5p_irq_eint_mask(data);
+	s5p_irq_eint_ack(data);
 }
 
-static int s5p_irq_eint_set_type(unsigned int irq, unsigned int type)
+static int s5p_irq_eint_set_type(struct irq_data *data, unsigned int type)
 {
-	int offs = EINT_OFFSET(irq);
+	int offs = EINT_OFFSET(data->irq);
 	int shift;
 	u32 ctrl, mask;
 	u32 newvalue = 0;
@@ -94,10 +95,10 @@ static int s5p_irq_eint_set_type(unsigne
 	shift = (offs & 0x7) * 4;
 	mask = 0x7 << shift;
 
-	ctrl = __raw_readl(S5P_EINT_CON(EINT_REG_NR(irq)));
+	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(irq)));
+	__raw_writel(ctrl, S5P_EINT_CON(EINT_REG_NR(data->irq)));
 
 	if ((0 <= offs) && (offs < 8))
 		s3c_gpio_cfgpin(EINT_GPIO_0(offs & 0x7), EINT_MODE);
@@ -119,13 +120,13 @@ static int s5p_irq_eint_set_type(unsigne
 
 static struct irq_chip s5p_irq_eint = {
 	.name		= "s5p-eint",
-	.mask		= s5p_irq_eint_mask,
-	.unmask		= s5p_irq_eint_unmask,
-	.mask_ack	= s5p_irq_eint_maskack,
-	.ack		= s5p_irq_eint_ack,
-	.set_type	= s5p_irq_eint_set_type,
+	.irq_mask	= s5p_irq_eint_mask,
+	.irq_unmask	= s5p_irq_eint_unmask,
+	.irq_mask_ack	= s5p_irq_eint_maskack,
+	.irq_ack	= s5p_irq_eint_ack,
+	.irq_set_type	= s5p_irq_eint_set_type,
 #ifdef CONFIG_PM
-	.set_wake	= s3c_irqext_wake,
+	.irq_set_wake	= s3c_irqext_wake,
 #endif
 };
 
@@ -159,42 +160,43 @@ static void s5p_irq_demux_eint16_31(unsi
 	s5p_irq_demux_eint(IRQ_EINT(24));
 }
 
-static inline void s5p_irq_vic_eint_mask(unsigned int irq)
+static inline void s5p_irq_vic_eint_mask(struct irq_data *data)
 {
-	void __iomem *base = get_irq_chip_data(irq);
+	void __iomem *base = irq_data_get_irq_chip_data(data);
 
-	s5p_irq_eint_mask(irq);
-	writel(1 << EINT_OFFSET(irq), base + VIC_INT_ENABLE_CLEAR);
+	s5p_irq_eint_mask(data);
+	writel(1 << EINT_OFFSET(data->irq), base + VIC_INT_ENABLE_CLEAR);
 }
 
-static void s5p_irq_vic_eint_unmask(unsigned int irq)
+static void s5p_irq_vic_eint_unmask(struct irq_data *data)
 {
-	void __iomem *base = get_irq_chip_data(irq);
+	void __iomem *base = irq_data_get_irq_chip_data(data);
 
-	s5p_irq_eint_unmask(irq);
-	writel(1 << EINT_OFFSET(irq), base + VIC_INT_ENABLE);
+	s5p_irq_eint_unmask(data);
+	writel(1 << EINT_OFFSET(data->irq), base + VIC_INT_ENABLE);
 }
 
-static inline void s5p_irq_vic_eint_ack(unsigned int irq)
+static inline void s5p_irq_vic_eint_ack(struct irq_data *data)
 {
-	__raw_writel(eint_irq_to_bit(irq), S5P_EINT_PEND(EINT_REG_NR(irq)));
+	__raw_writel(eint_irq_to_bit(data->irq),
+		     S5P_EINT_PEND(EINT_REG_NR(data->irq)));
 }
 
-static void s5p_irq_vic_eint_maskack(unsigned int irq)
+static void s5p_irq_vic_eint_maskack(struct irq_data *data)
 {
-	s5p_irq_vic_eint_mask(irq);
-	s5p_irq_vic_eint_ack(irq);
+	s5p_irq_vic_eint_mask(data);
+	s5p_irq_vic_eint_ack(data);
 }
 
 static struct irq_chip s5p_irq_vic_eint = {
 	.name		= "s5p_vic_eint",
-	.mask		= s5p_irq_vic_eint_mask,
-	.unmask		= s5p_irq_vic_eint_unmask,
-	.mask_ack	= s5p_irq_vic_eint_maskack,
-	.ack		= s5p_irq_vic_eint_ack,
-	.set_type	= s5p_irq_eint_set_type,
+	.irq_mask	= s5p_irq_vic_eint_mask,
+	.irq_unmask	= s5p_irq_vic_eint_unmask,
+	.irq_mask_ack	= s5p_irq_vic_eint_maskack,
+	.irq_ack	= s5p_irq_vic_eint_ack,
+	.irq_set_type	= s5p_irq_eint_set_type,
 #ifdef CONFIG_PM
-	.set_wake	= s3c_irqext_wake,
+	.irq_set_wake	= s3c_irqext_wake,
 #endif
 };
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-s5p/irq-gpioint.c linux-libre-2.6.38-gnu1/arch/arm/plat-s5p/irq-gpioint.c
--- linux-libre-2.6.37-gnu1/arch/arm/plat-s5p/irq-gpioint.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-s5p/irq-gpioint.c	2011-03-14 21:20:32.000000000 -0400
@@ -30,9 +30,9 @@
 
 static struct s3c_gpio_chip *irq_chips[S5P_GPIOINT_GROUP_MAXNR];
 
-static int s5p_gpioint_get_group(unsigned int irq)
+static int s5p_gpioint_get_group(struct irq_data *data)
 {
-	struct gpio_chip *chip = get_irq_data(irq);
+	struct gpio_chip *chip = irq_data_get_irq_data(data);
 	struct s3c_gpio_chip *s3c_chip = container_of(chip,
 			struct s3c_gpio_chip, chip);
 	int group;
@@ -44,22 +44,22 @@ static int s5p_gpioint_get_group(unsigne
 	return group;
 }
 
-static int s5p_gpioint_get_offset(unsigned int irq)
+static int s5p_gpioint_get_offset(struct irq_data *data)
 {
-	struct gpio_chip *chip = get_irq_data(irq);
+	struct gpio_chip *chip = irq_data_get_irq_data(data);
 	struct s3c_gpio_chip *s3c_chip = container_of(chip,
 			struct s3c_gpio_chip, chip);
 
-	return irq - s3c_chip->irq_base;
+	return data->irq - s3c_chip->irq_base;
 }
 
-static void s5p_gpioint_ack(unsigned int irq)
+static void s5p_gpioint_ack(struct irq_data *data)
 {
 	int group, offset, pend_offset;
 	unsigned int value;
 
-	group = s5p_gpioint_get_group(irq);
-	offset = s5p_gpioint_get_offset(irq);
+	group = s5p_gpioint_get_group(data);
+	offset = s5p_gpioint_get_offset(data);
 	pend_offset = group << 2;
 
 	value = __raw_readl(S5P_GPIOREG(GPIOINT_PEND_OFFSET) + pend_offset);
@@ -67,13 +67,13 @@ static void s5p_gpioint_ack(unsigned int
 	__raw_writel(value, S5P_GPIOREG(GPIOINT_PEND_OFFSET) + pend_offset);
 }
 
-static void s5p_gpioint_mask(unsigned int irq)
+static void s5p_gpioint_mask(struct irq_data *data)
 {
 	int group, offset, mask_offset;
 	unsigned int value;
 
-	group = s5p_gpioint_get_group(irq);
-	offset = s5p_gpioint_get_offset(irq);
+	group = s5p_gpioint_get_group(data);
+	offset = s5p_gpioint_get_offset(data);
 	mask_offset = group << 2;
 
 	value = __raw_readl(S5P_GPIOREG(GPIOINT_MASK_OFFSET) + mask_offset);
@@ -81,13 +81,13 @@ static void s5p_gpioint_mask(unsigned in
 	__raw_writel(value, S5P_GPIOREG(GPIOINT_MASK_OFFSET) + mask_offset);
 }
 
-static void s5p_gpioint_unmask(unsigned int irq)
+static void s5p_gpioint_unmask(struct irq_data *data)
 {
 	int group, offset, mask_offset;
 	unsigned int value;
 
-	group = s5p_gpioint_get_group(irq);
-	offset = s5p_gpioint_get_offset(irq);
+	group = s5p_gpioint_get_group(data);
+	offset = s5p_gpioint_get_offset(data);
 	mask_offset = group << 2;
 
 	value = __raw_readl(S5P_GPIOREG(GPIOINT_MASK_OFFSET) + mask_offset);
@@ -95,19 +95,19 @@ static void s5p_gpioint_unmask(unsigned
 	__raw_writel(value, S5P_GPIOREG(GPIOINT_MASK_OFFSET) + mask_offset);
 }
 
-static void s5p_gpioint_mask_ack(unsigned int irq)
+static void s5p_gpioint_mask_ack(struct irq_data *data)
 {
-	s5p_gpioint_mask(irq);
-	s5p_gpioint_ack(irq);
+	s5p_gpioint_mask(data);
+	s5p_gpioint_ack(data);
 }
 
-static int s5p_gpioint_set_type(unsigned int irq, unsigned int type)
+static int s5p_gpioint_set_type(struct irq_data *data, unsigned int type)
 {
 	int group, offset, con_offset;
 	unsigned int value;
 
-	group = s5p_gpioint_get_group(irq);
-	offset = s5p_gpioint_get_offset(irq);
+	group = s5p_gpioint_get_group(data);
+	offset = s5p_gpioint_get_offset(data);
 	con_offset = group << 2;
 
 	switch (type) {
@@ -142,11 +142,11 @@ static int s5p_gpioint_set_type(unsigned
 
 struct irq_chip s5p_gpioint = {
 	.name		= "s5p_gpioint",
-	.ack		= s5p_gpioint_ack,
-	.mask		= s5p_gpioint_mask,
-	.mask_ack	= s5p_gpioint_mask_ack,
-	.unmask		= s5p_gpioint_unmask,
-	.set_type	= s5p_gpioint_set_type,
+	.irq_ack	= s5p_gpioint_ack,
+	.irq_mask	= s5p_gpioint_mask,
+	.irq_mask_ack	= s5p_gpioint_mask_ack,
+	.irq_unmask	= s5p_gpioint_unmask,
+	.irq_set_type	= s5p_gpioint_set_type,
 };
 
 static void s5p_gpioint_handler(unsigned int irq, struct irq_desc *desc)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-s5p/irq-pm.c linux-libre-2.6.38-gnu1/arch/arm/plat-s5p/irq-pm.c
--- linux-libre-2.6.37-gnu1/arch/arm/plat-s5p/irq-pm.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-s5p/irq-pm.c	2011-03-14 21:20:32.000000000 -0400
@@ -37,14 +37,14 @@
 unsigned long s3c_irqwake_intallow	= 0x00000006L;
 unsigned long s3c_irqwake_eintallow	= 0xffffffffL;
 
-int s3c_irq_wake(unsigned int irqno, unsigned int state)
+int s3c_irq_wake(struct irq_data *data, unsigned int state)
 {
 	unsigned long irqbit;
 
-	switch (irqno) {
+	switch (data->irq) {
 	case IRQ_RTC_TIC:
 	case IRQ_RTC_ALARM:
-		irqbit = 1 << (irqno + 1 - IRQ_RTC_ALARM);
+		irqbit = 1 << (data->irq + 1 - IRQ_RTC_ALARM);
 		if (!state)
 			s3c_irqwake_intmask |= irqbit;
 		else
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-s5p/Kconfig linux-libre-2.6.38-gnu1/arch/arm/plat-s5p/Kconfig
--- linux-libre-2.6.37-gnu1/arch/arm/plat-s5p/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-s5p/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -37,6 +37,14 @@ config S5P_GPIO_INT
 	help
 	  Common code for the GPIO interrupts (other than external interrupts.)
 
+comment "System MMU"
+
+config S5P_SYSTEM_MMU
+	bool "S5P SYSTEM MMU"
+	depends on ARCH_S5PV310
+	help
+	  Say Y here if you want to enable System MMU
+
 config S5P_DEV_FIMC0
 	bool
 	help
@@ -56,3 +64,13 @@ config S5P_DEV_ONENAND
 	bool
 	help
 	  Compile in platform device definition for OneNAND controller
+
+config S5P_DEV_CSIS0
+	bool
+	help
+	  Compile in platform device definitions for MIPI-CSIS channel 0
+
+config S5P_DEV_CSIS1
+	bool
+	help
+	  Compile in platform device definitions for MIPI-CSIS channel 1
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-s5p/Makefile linux-libre-2.6.38-gnu1/arch/arm/plat-s5p/Makefile
--- linux-libre-2.6.37-gnu1/arch/arm/plat-s5p/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-s5p/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -19,6 +19,7 @@ obj-y				+= clock.o
 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
 
@@ -28,3 +29,5 @@ obj-$(CONFIG_S5P_DEV_FIMC0)	+= dev-fimc0
 obj-$(CONFIG_S5P_DEV_FIMC1)	+= dev-fimc1.o
 obj-$(CONFIG_S5P_DEV_FIMC2)	+= dev-fimc2.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
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-s5p/sysmmu.c linux-libre-2.6.38-gnu1/arch/arm/plat-s5p/sysmmu.c
--- linux-libre-2.6.37-gnu1/arch/arm/plat-s5p/sysmmu.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-s5p/sysmmu.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,326 @@
+/* linux/arch/arm/plat-s5p/sysmmu.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/io.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+
+#include <mach/map.h>
+#include <mach/regs-sysmmu.h>
+#include <mach/sysmmu.h>
+
+struct sysmmu_controller s5p_sysmmu_cntlrs[S5P_SYSMMU_TOTAL_IPNUM];
+
+void s5p_sysmmu_register(struct sysmmu_controller *sysmmuconp)
+{
+	unsigned int reg_mmu_ctrl;
+	unsigned int reg_mmu_status;
+	unsigned int reg_pt_base_addr;
+	unsigned int reg_int_status;
+	unsigned int reg_page_ft_addr;
+
+	reg_int_status = __raw_readl(sysmmuconp->regs + S5P_INT_STATUS);
+	reg_mmu_ctrl = __raw_readl(sysmmuconp->regs + S5P_MMU_CTRL);
+	reg_mmu_status = __raw_readl(sysmmuconp->regs + S5P_MMU_STATUS);
+	reg_pt_base_addr = __raw_readl(sysmmuconp->regs + S5P_PT_BASE_ADDR);
+	reg_page_ft_addr = __raw_readl(sysmmuconp->regs + S5P_PAGE_FAULT_ADDR);
+
+	printk(KERN_INFO "%s: ips:%s\n", __func__, sysmmuconp->name);
+	printk(KERN_INFO "%s: MMU_CTRL:0x%X, ", __func__, reg_mmu_ctrl);
+	printk(KERN_INFO "MMU_STATUS:0x%X, PT_BASE_ADDR:0x%X\n", reg_mmu_status, reg_pt_base_addr);
+	printk(KERN_INFO "%s: INT_STATUS:0x%X, PAGE_FAULT_ADDR:0x%X\n", __func__, reg_int_status, reg_page_ft_addr);
+
+	switch (reg_int_status & 0xFF) {
+	case 0x1:
+		printk(KERN_INFO "%s: Page fault\n", __func__);
+		printk(KERN_INFO "%s: Virtual address causing last page fault or bus error : 0x%x\n", __func__ , reg_page_ft_addr);
+		break;
+	case 0x2:
+		printk(KERN_INFO "%s: AR multi-hit fault\n", __func__);
+		break;
+	case 0x4:
+		printk(KERN_INFO "%s: AW multi-hit fault\n", __func__);
+		break;
+	case 0x8:
+		printk(KERN_INFO "%s: Bus error\n", __func__);
+		break;
+	case 0x10:
+		printk(KERN_INFO "%s: AR Security protection fault\n", __func__);
+		break;
+	case 0x20:
+		printk(KERN_INFO "%s: AR Access protection fault\n", __func__);
+		break;
+	case 0x40:
+		printk(KERN_INFO "%s: AW Security protection fault\n", __func__);
+		break;
+	case 0x80:
+		printk(KERN_INFO "%s: AW Access protection fault\n", __func__);
+		break;
+	}
+}
+
+static irqreturn_t s5p_sysmmu_irq(int irq, void *dev_id)
+{
+	unsigned int i;
+	unsigned int reg_int_status;
+	struct sysmmu_controller *sysmmuconp;
+
+	for (i = 0; i < S5P_SYSMMU_TOTAL_IPNUM; i++) {
+		sysmmuconp = &s5p_sysmmu_cntlrs[i];
+
+		if (sysmmuconp->enable == true) {
+			reg_int_status = __raw_readl(sysmmuconp->regs + S5P_INT_STATUS);
+
+			if (reg_int_status & 0xFF)
+				s5p_sysmmu_register(sysmmuconp);
+		}
+	}
+	return IRQ_HANDLED;
+}
+
+int s5p_sysmmu_set_tablebase_pgd(sysmmu_ips ips, unsigned long pgd)
+{
+	struct sysmmu_controller *sysmmuconp = NULL;
+
+	sysmmuconp = &s5p_sysmmu_cntlrs[ips];
+
+	if (sysmmuconp == NULL) {
+		printk(KERN_ERR "failed to get ip's sysmmu info\n");
+		return 1;
+	}
+
+	/* Set sysmmu page table base address */
+	__raw_writel(pgd, sysmmuconp->regs + S5P_PT_BASE_ADDR);
+
+	if (s5p_sysmmu_tlb_invalidate(ips) != 0)
+		printk(KERN_ERR "failed s5p_sysmmu_tlb_invalidate\n");
+
+	return 0;
+}
+
+static int s5p_sysmmu_set_tablebase(sysmmu_ips ips)
+{
+	unsigned int pg;
+	struct sysmmu_controller *sysmmuconp;
+
+	sysmmuconp = &s5p_sysmmu_cntlrs[ips];
+
+	if (sysmmuconp == NULL) {
+		printk(KERN_ERR "failed to get ip's sysmmu info\n");
+		return 1;
+	}
+
+	__asm__("mrc	p15, 0, %0, c2, c0, 0"	\
+		: "=r" (pg) : : "cc");		\
+		pg &= ~0x3fff;
+
+	printk(KERN_INFO "%s: CP15 TTBR0 : 0x%x\n", __func__, pg);
+
+	/* Set sysmmu page table base address */
+	__raw_writel(pg, sysmmuconp->regs + S5P_PT_BASE_ADDR);
+
+	return 0;
+}
+
+int s5p_sysmmu_enable(sysmmu_ips ips)
+{
+	unsigned int reg;
+
+	struct sysmmu_controller *sysmmuconp;
+
+	sysmmuconp = &s5p_sysmmu_cntlrs[ips];
+
+	if (sysmmuconp == NULL) {
+		printk(KERN_ERR "failed to get ip's sysmmu info\n");
+		return 1;
+	}
+
+	s5p_sysmmu_set_tablebase(ips);
+
+	/* replacement policy : LRU */
+	reg = __raw_readl(sysmmuconp->regs + S5P_MMU_CFG);
+	reg |= 0x1;
+	__raw_writel(reg, sysmmuconp->regs + S5P_MMU_CFG);
+
+	/* Enable interrupt, Enable MMU */
+	reg = __raw_readl(sysmmuconp->regs + S5P_MMU_CTRL);
+	reg |= (0x1 << 2) | (0x1 << 0);
+
+	__raw_writel(reg, sysmmuconp->regs + S5P_MMU_CTRL);
+
+	sysmmuconp->enable = true;
+
+	return 0;
+}
+
+int s5p_sysmmu_disable(sysmmu_ips ips)
+{
+	unsigned int reg;
+
+	struct sysmmu_controller *sysmmuconp = NULL;
+
+	if (ips > S5P_SYSMMU_TOTAL_IPNUM)
+		printk(KERN_ERR "failed to get ips parameter\n");
+
+	sysmmuconp = &s5p_sysmmu_cntlrs[ips];
+
+	if (sysmmuconp == NULL) {
+		printk(KERN_ERR "failed to get ip's sysmmu info\n");
+		return 1;
+	}
+
+	reg = __raw_readl(sysmmuconp->regs + S5P_MMU_CFG);
+
+	/* replacement policy : LRU */
+	reg |= 0x1;
+	__raw_writel(reg, sysmmuconp->regs + S5P_MMU_CFG);
+
+	reg = __raw_readl(sysmmuconp->regs + S5P_MMU_CTRL);
+
+	/* Disable MMU */
+	reg &= ~0x1;
+	__raw_writel(reg, sysmmuconp->regs + S5P_MMU_CTRL);
+
+	sysmmuconp->enable = false;
+
+	return 0;
+}
+
+int s5p_sysmmu_tlb_invalidate(sysmmu_ips ips)
+{
+	unsigned int reg;
+	struct sysmmu_controller *sysmmuconp = NULL;
+
+	sysmmuconp = &s5p_sysmmu_cntlrs[ips];
+
+	if (sysmmuconp == NULL) {
+		printk(KERN_ERR "failed to get ip's sysmmu info\n");
+		return 1;
+	}
+
+	/* set Block MMU for flush TLB */
+	reg = __raw_readl(sysmmuconp->regs + S5P_MMU_CTRL);
+	reg |= 0x1 << 1;
+	__raw_writel(reg, sysmmuconp->regs + S5P_MMU_CTRL);
+
+	/* flush all TLB entry */
+	__raw_writel(0x1, sysmmuconp->regs + S5P_MMU_FLUSH);
+
+	/* set Un-block MMU after flush TLB */
+	reg = __raw_readl(sysmmuconp->regs + S5P_MMU_CTRL);
+	reg &= ~(0x1 << 1);
+	__raw_writel(reg, sysmmuconp->regs + S5P_MMU_CTRL);
+
+	return 0;
+}
+
+static int s5p_sysmmu_probe(struct platform_device *pdev)
+{
+	int i;
+	int ret;
+	struct resource *res;
+	struct sysmmu_controller *sysmmuconp;
+	sysmmu_ips ips;
+
+	for (i = 0; i < S5P_SYSMMU_TOTAL_IPNUM; i++) {
+		sysmmuconp = &s5p_sysmmu_cntlrs[i];
+		if (sysmmuconp == NULL) {
+			printk(KERN_ERR "failed to get ip's sysmmu info\n");
+			ret = -ENOENT;
+			goto err_res;
+		}
+
+		sysmmuconp->name = sysmmu_ips_name[i];
+
+		res = platform_get_resource(pdev, IORESOURCE_MEM, i);
+		if (!res) {
+			printk(KERN_ERR "failed to get sysmmu resource\n");
+			ret = -ENODEV;
+			goto err_res;
+		}
+
+		sysmmuconp->mem = request_mem_region(res->start,
+				((res->end) - (res->start)) + 1, pdev->name);
+		if (!sysmmuconp->mem) {
+			pr_err("failed to request sysmmu memory region\n");
+			ret = -EBUSY;
+			goto err_res;
+		}
+
+		sysmmuconp->regs = ioremap(res->start, res->end - res->start + 1);
+		if (!sysmmuconp->regs) {
+			pr_err("failed to sysmmu ioremap\n");
+			ret = -ENXIO;
+			goto err_reg;
+		}
+
+		sysmmuconp->irq = platform_get_irq(pdev, i);
+		if (sysmmuconp->irq <= 0) {
+			pr_err("failed to get sysmmu irq resource\n");
+			ret = -ENOENT;
+			goto err_map;
+		}
+
+		ret = request_irq(sysmmuconp->irq, s5p_sysmmu_irq, IRQF_DISABLED, pdev->name, sysmmuconp);
+		if (ret) {
+			pr_err("failed to request irq\n");
+			ret = -ENOENT;
+			goto err_map;
+		}
+
+		ips = (sysmmu_ips)i;
+
+		sysmmuconp->ips = ips;
+	}
+
+	return 0;
+
+err_reg:
+	release_mem_region((resource_size_t)sysmmuconp->mem, (resource_size_t)((res->end) - (res->start) + 1));
+err_map:
+	iounmap(sysmmuconp->regs);
+err_res:
+	return ret;
+}
+
+static int s5p_sysmmu_remove(struct platform_device *pdev)
+{
+	return 0;
+}
+int s5p_sysmmu_runtime_suspend(struct device *dev)
+{
+	return 0;
+}
+
+int s5p_sysmmu_runtime_resume(struct device *dev)
+{
+	return 0;
+}
+
+const struct dev_pm_ops s5p_sysmmu_pm_ops = {
+	.runtime_suspend	= s5p_sysmmu_runtime_suspend,
+	.runtime_resume		= s5p_sysmmu_runtime_resume,
+};
+
+static struct platform_driver s5p_sysmmu_driver = {
+	.probe		= s5p_sysmmu_probe,
+	.remove		= s5p_sysmmu_remove,
+	.driver		= {
+		.owner		= THIS_MODULE,
+		.name		= "s5p-sysmmu",
+		.pm		= &s5p_sysmmu_pm_ops,
+	}
+};
+
+static int __init s5p_sysmmu_init(void)
+{
+	return platform_driver_register(&s5p_sysmmu_driver);
+}
+arch_initcall(s5p_sysmmu_init);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-samsung/clock.c linux-libre-2.6.38-gnu1/arch/arm/plat-samsung/clock.c
--- linux-libre-2.6.37-gnu1/arch/arm/plat-samsung/clock.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-samsung/clock.c	2011-03-14 21:20:32.000000000 -0400
@@ -39,6 +39,9 @@
 #include <linux/clk.h>
 #include <linux/spinlock.h>
 #include <linux/io.h>
+#if defined(CONFIG_DEBUG_FS)
+#include <linux/debugfs.h>
+#endif
 
 #include <mach/hardware.h>
 #include <asm/irq.h>
@@ -447,3 +450,92 @@ int __init s3c24xx_register_baseclocks(u
 	return 0;
 }
 
+#if defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS)
+/* debugfs support to trace clock tree hierarchy and attributes */
+
+static struct dentry *clk_debugfs_root;
+
+static int clk_debugfs_register_one(struct clk *c)
+{
+	int err;
+	struct dentry *d, *child, *child_tmp;
+	struct clk *pa = c->parent;
+	char s[255];
+	char *p = s;
+
+	p += sprintf(p, "%s", c->name);
+
+	if (c->id >= 0)
+		sprintf(p, ":%d", c->id);
+
+	d = debugfs_create_dir(s, pa ? pa->dent : clk_debugfs_root);
+	if (!d)
+		return -ENOMEM;
+
+	c->dent = d;
+
+	d = debugfs_create_u8("usecount", S_IRUGO, c->dent, (u8 *)&c->usage);
+	if (!d) {
+		err = -ENOMEM;
+		goto err_out;
+	}
+
+	d = debugfs_create_u32("rate", S_IRUGO, c->dent, (u32 *)&c->rate);
+	if (!d) {
+		err = -ENOMEM;
+		goto err_out;
+	}
+	return 0;
+
+err_out:
+	d = c->dent;
+	list_for_each_entry_safe(child, child_tmp, &d->d_subdirs, d_u.d_child)
+		debugfs_remove(child);
+	debugfs_remove(c->dent);
+	return err;
+}
+
+static int clk_debugfs_register(struct clk *c)
+{
+	int err;
+	struct clk *pa = c->parent;
+
+	if (pa && !pa->dent) {
+		err = clk_debugfs_register(pa);
+		if (err)
+			return err;
+	}
+
+	if (!c->dent) {
+		err = clk_debugfs_register_one(c);
+		if (err)
+			return err;
+	}
+	return 0;
+}
+
+static int __init clk_debugfs_init(void)
+{
+	struct clk *c;
+	struct dentry *d;
+	int err;
+
+	d = debugfs_create_dir("clock", NULL);
+	if (!d)
+		return -ENOMEM;
+	clk_debugfs_root = d;
+
+	list_for_each_entry(c, &clocks, list) {
+		err = clk_debugfs_register(c);
+		if (err)
+			goto err_out;
+	}
+	return 0;
+
+err_out:
+	debugfs_remove_recursive(clk_debugfs_root);
+	return err;
+}
+late_initcall(clk_debugfs_init);
+
+#endif /* defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS) */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-samsung/dev-asocdma.c linux-libre-2.6.38-gnu1/arch/arm/plat-samsung/dev-asocdma.c
--- linux-libre-2.6.37-gnu1/arch/arm/plat-samsung/dev-asocdma.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-samsung/dev-asocdma.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,25 @@
+/* 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);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-samsung/dev-nand.c linux-libre-2.6.38-gnu1/arch/arm/plat-samsung/dev-nand.c
--- linux-libre-2.6.37-gnu1/arch/arm/plat-samsung/dev-nand.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-samsung/dev-nand.c	2011-03-14 21:20:32.000000000 -0400
@@ -126,5 +126,3 @@ void __init s3c_nand_set_platdata(struct
 
 	s3c_device_nand.dev.platform_data = npd;
 }
-
-EXPORT_SYMBOL_GPL(s3c_nand_set_platdata);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-samsung/dev-ts.c linux-libre-2.6.38-gnu1/arch/arm/plat-samsung/dev-ts.c
--- linux-libre-2.6.37-gnu1/arch/arm/plat-samsung/dev-ts.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-samsung/dev-ts.c	2011-03-14 21:20:32.000000000 -0400
@@ -58,4 +58,3 @@ void __init s3c24xx_ts_set_platdata(stru
 
 	s3c_device_ts.dev.platform_data = npd;
 }
-EXPORT_SYMBOL(s3c24xx_ts_set_platdata);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-samsung/dev-uart.c linux-libre-2.6.38-gnu1/arch/arm/plat-samsung/dev-uart.c
--- linux-libre-2.6.37-gnu1/arch/arm/plat-samsung/dev-uart.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-samsung/dev-uart.c	2011-03-14 21:20:32.000000000 -0400
@@ -15,6 +15,8 @@
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
 
+#include <plat/devs.h>
+
 /* uart devices */
 
 static struct platform_device s3c24xx_uart_device0 = {
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-samsung/gpio-config.c linux-libre-2.6.38-gnu1/arch/arm/plat-samsung/gpio-config.c
--- linux-libre-2.6.37-gnu1/arch/arm/plat-samsung/gpio-config.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-samsung/gpio-config.c	2011-03-14 21:20:32.000000000 -0400
@@ -278,6 +278,48 @@ s3c_gpio_pull_t s3c_gpio_getpull_updown(
 	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)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-samsung/gpiolib.c linux-libre-2.6.38-gnu1/arch/arm/plat-samsung/gpiolib.c
--- linux-libre-2.6.37-gnu1/arch/arm/plat-samsung/gpiolib.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-samsung/gpiolib.c	2011-03-14 21:20:32.000000000 -0400
@@ -197,3 +197,10 @@ void __init samsung_gpiolib_add_4bit2_ch
 		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-2.6.37-gnu1/arch/arm/plat-samsung/include/plat/audio.h linux-libre-2.6.38-gnu1/arch/arm/plat-samsung/include/plat/audio.h
--- linux-libre-2.6.37-gnu1/arch/arm/plat-samsung/include/plat/audio.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-samsung/include/plat/audio.h	2011-03-14 21:20:32.000000000 -0400
@@ -25,10 +25,34 @@ extern void s3c64xx_ac97_setup_gpio(int)
 #define S5PC100_SPDIF_GPG3 1
 extern void s5pc100_spdif_setup_gpio(int);
 
+struct samsung_i2s {
+/* If the Primary DAI has 5.1 Channels */
+#define QUIRK_PRI_6CHAN		(1 << 0)
+/* If the I2S block has a Stereo Overlay Channel */
+#define QUIRK_SEC_DAI		(1 << 1)
+/*
+ * If the I2S block has no internal prescalar or MUX (I2SMOD[10] bit)
+ * The Machine driver must provide suitably set clock to the I2S block.
+ */
+#define QUIRK_NO_MUXPSR		(1 << 2)
+#define QUIRK_NEED_RSTCLR	(1 << 3)
+	/* Quirks of the I2S controller */
+	u32 quirks;
+
+	/*
+	 * Array of clock names that can be used to generate I2S signals.
+	 * Also corresponds to clocks of I2SMOD[10]
+	 */
+	const char **src_clk;
+};
+
 /**
  * struct s3c_audio_pdata - common platform data for audio device drivers
  * @cfg_gpio: Callback function to setup mux'ed pins in I2S/PCM/AC97 mode
  */
 struct s3c_audio_pdata {
 	int (*cfg_gpio)(struct platform_device *);
+	union {
+		struct samsung_i2s i2s;
+	} type;
 };
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-samsung/include/plat/clock.h linux-libre-2.6.38-gnu1/arch/arm/plat-samsung/include/plat/clock.h
--- linux-libre-2.6.37-gnu1/arch/arm/plat-samsung/include/plat/clock.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-samsung/include/plat/clock.h	2011-03-14 21:20:32.000000000 -0400
@@ -47,6 +47,9 @@ struct clk {
 
 	struct clk_ops		*ops;
 	int		    (*enable)(struct clk *, int enable);
+#if defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS)
+	struct dentry		*dent;	/* For visible tree hierarchy */
+#endif
 };
 
 /* other clocks which may be registered by board support */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-samsung/include/plat/devs.h linux-libre-2.6.38-gnu1/arch/arm/plat-samsung/include/plat/devs.h
--- linux-libre-2.6.37-gnu1/arch/arm/plat-samsung/include/plat/devs.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-samsung/include/plat/devs.h	2011-03-14 21:20:32.000000000 -0400
@@ -32,7 +32,7 @@ extern struct platform_device s3c64xx_de
 extern struct platform_device s3c64xx_device_spi0;
 extern struct platform_device s3c64xx_device_spi1;
 
-extern struct platform_device s3c_device_pcm;
+extern struct platform_device samsung_asoc_dma;
 
 extern struct platform_device s3c64xx_device_pcm0;
 extern struct platform_device s3c64xx_device_pcm1;
@@ -96,6 +96,16 @@ extern struct platform_device s5pv210_de
 extern struct platform_device s5pv210_device_iis2;
 extern struct platform_device s5pv210_device_spdif;
 
+extern struct platform_device s5pv310_device_ac97;
+extern struct platform_device s5pv310_device_pcm0;
+extern struct platform_device s5pv310_device_pcm1;
+extern struct platform_device s5pv310_device_pcm2;
+extern struct platform_device s5pv310_device_i2s0;
+extern struct platform_device s5pv310_device_i2s1;
+extern struct platform_device s5pv310_device_i2s2;
+extern struct platform_device s5pv310_device_spdif;
+extern struct platform_device s5pv310_device_pd[];
+
 extern struct platform_device s5p6442_device_pcm0;
 extern struct platform_device s5p6442_device_pcm1;
 extern struct platform_device s5p6442_device_iis0;
@@ -106,6 +116,8 @@ extern struct platform_device s5p6440_de
 extern struct platform_device s5p6440_device_iis;
 
 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 s5pc100_device_ac97;
@@ -122,6 +134,11 @@ extern struct platform_device s5p_device
 extern struct platform_device s5p_device_fimc1;
 extern struct platform_device s5p_device_fimc2;
 
+extern struct platform_device s5p_device_mipi_csis0;
+extern struct platform_device s5p_device_mipi_csis1;
+
+extern struct platform_device s5pv310_device_sysmmu;
+
 /* s3c2440 specific devices */
 
 #ifdef CONFIG_CPU_S3C2440
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-samsung/include/plat/gpio-cfg-helpers.h linux-libre-2.6.38-gnu1/arch/arm/plat-samsung/include/plat/gpio-cfg-helpers.h
--- linux-libre-2.6.37-gnu1/arch/arm/plat-samsung/include/plat/gpio-cfg-helpers.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-samsung/include/plat/gpio-cfg-helpers.h	2011-03-14 21:20:32.000000000 -0400
@@ -244,7 +244,7 @@ extern int s3c_gpio_setpull_s3c2443(stru
  * 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.
 */
-extern s3c_gpio_pull_t s3c_gpio_getpull_s3c24xx(struct s3c_gpio_chip *chip,
+extern s3c_gpio_pull_t s3c_gpio_getpull_s3c2443(struct s3c_gpio_chip *chip,
 						unsigned int off);
 
 #endif /* __PLAT_GPIO_CFG_HELPERS_H */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-samsung/include/plat/gpio-core.h linux-libre-2.6.38-gnu1/arch/arm/plat-samsung/include/plat/gpio-core.h
--- linux-libre-2.6.37-gnu1/arch/arm/plat-samsung/include/plat/gpio-core.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-samsung/include/plat/gpio-core.h	2011-03-14 21:20:32.000000000 -0400
@@ -118,6 +118,8 @@ extern void samsung_gpiolib_add_4bit_chi
 					   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);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-samsung/include/plat/pd.h linux-libre-2.6.38-gnu1/arch/arm/plat-samsung/include/plat/pd.h
--- linux-libre-2.6.37-gnu1/arch/arm/plat-samsung/include/plat/pd.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-samsung/include/plat/pd.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,30 @@
+/* linux/arch/arm/plat-samsung/include/plat/pd.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_SAMSUNG_PD_H
+#define __ASM_PLAT_SAMSUNG_PD_H __FILE__
+
+struct samsung_pd_info {
+	int (*enable)(struct device *dev);
+	int (*disable)(struct device *dev);
+	void __iomem *base;
+};
+
+enum s5pv310_pd_block {
+	PD_MFC,
+	PD_G3D,
+	PD_LCD0,
+	PD_LCD1,
+	PD_TV,
+	PD_CAM,
+	PD_GPS
+};
+
+#endif /* __ASM_PLAT_SAMSUNG_PD_H */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-samsung/include/plat/pm.h linux-libre-2.6.38-gnu1/arch/arm/plat-samsung/include/plat/pm.h
--- linux-libre-2.6.37-gnu1/arch/arm/plat-samsung/include/plat/pm.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-samsung/include/plat/pm.h	2011-03-14 21:20:32.000000000 -0400
@@ -15,6 +15,10 @@
  * management
 */
 
+#include <linux/irq.h>
+
+struct sys_device;
+
 #ifdef CONFIG_PM
 
 extern __init int s3c_pm_init(void);
@@ -100,7 +104,7 @@ extern void s3c_pm_do_restore(struct sle
 extern void s3c_pm_do_restore_core(struct sleep_save *ptr, int count);
 
 #ifdef CONFIG_PM
-extern int s3c_irqext_wake(unsigned int irqno, unsigned int state);
+extern int s3c_irqext_wake(struct irq_data *data, unsigned int state);
 extern int s3c24xx_irq_suspend(struct sys_device *dev, pm_message_t state);
 extern int s3c24xx_irq_resume(struct sys_device *dev);
 #else
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-samsung/include/plat/sdhci.h linux-libre-2.6.38-gnu1/arch/arm/plat-samsung/include/plat/sdhci.h
--- linux-libre-2.6.37-gnu1/arch/arm/plat-samsung/include/plat/sdhci.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-samsung/include/plat/sdhci.h	2011-03-14 21:20:32.000000000 -0400
@@ -107,6 +107,8 @@ extern struct s3c_sdhci_platdata s3c_hsm
 
 /* Helper function availablity */
 
+extern void s3c2416_setup_sdhci0_cfg_gpio(struct platform_device *, int w);
+extern void s3c2416_setup_sdhci1_cfg_gpio(struct platform_device *, int w);
 extern void s3c64xx_setup_sdhci0_cfg_gpio(struct platform_device *, int w);
 extern void s3c64xx_setup_sdhci1_cfg_gpio(struct platform_device *, int w);
 extern void s5pc100_setup_sdhci0_cfg_gpio(struct platform_device *, int w);
@@ -122,6 +124,39 @@ extern void s5pv310_setup_sdhci1_cfg_gpi
 extern void s5pv310_setup_sdhci2_cfg_gpio(struct platform_device *, int w);
 extern void s5pv310_setup_sdhci3_cfg_gpio(struct platform_device *, int w);
 
+/* S3C2416 SDHCI setup */
+
+#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 */
+}
+
+static inline void s3c2416_default_sdhci1(void)
+{
+#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 */
+}
+
+#else
+static inline void s3c2416_default_sdhci0(void) { }
+static inline void s3c2416_default_sdhci1(void) { }
+
+#endif /* CONFIG_S3C2416_SETUP_SDHCI */
 /* S3C64XX SDHCI setup */
 
 #ifdef CONFIG_S3C64XX_SETUP_SDHCI
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-samsung/irq-uart.c linux-libre-2.6.38-gnu1/arch/arm/plat-samsung/irq-uart.c
--- linux-libre-2.6.37-gnu1/arch/arm/plat-samsung/irq-uart.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-samsung/irq-uart.c	2011-03-14 21:20:32.000000000 -0400
@@ -28,9 +28,9 @@
  * are consecutive when looking up the interrupt in the demux routines.
  */
 
-static inline void __iomem *s3c_irq_uart_base(unsigned int irq)
+static inline void __iomem *s3c_irq_uart_base(struct irq_data *data)
 {
-	struct s3c_uart_irq *uirq = get_irq_chip_data(irq);
+	struct s3c_uart_irq *uirq = irq_data_get_irq_chip_data(data);
 	return uirq->regs;
 }
 
@@ -39,10 +39,10 @@ static inline unsigned int s3c_irq_uart_
 	return irq & 3;
 }
 
-static void s3c_irq_uart_mask(unsigned int irq)
+static void s3c_irq_uart_mask(struct irq_data *data)
 {
-	void __iomem *regs = s3c_irq_uart_base(irq);
-	unsigned int bit = s3c_irq_uart_bit(irq);
+	void __iomem *regs = s3c_irq_uart_base(data);
+	unsigned int bit = s3c_irq_uart_bit(data->irq);
 	u32 reg;
 
 	reg = __raw_readl(regs + S3C64XX_UINTM);
@@ -50,10 +50,10 @@ static void s3c_irq_uart_mask(unsigned i
 	__raw_writel(reg, regs + S3C64XX_UINTM);
 }
 
-static void s3c_irq_uart_maskack(unsigned int irq)
+static void s3c_irq_uart_maskack(struct irq_data *data)
 {
-	void __iomem *regs = s3c_irq_uart_base(irq);
-	unsigned int bit = s3c_irq_uart_bit(irq);
+	void __iomem *regs = s3c_irq_uart_base(data);
+	unsigned int bit = s3c_irq_uart_bit(data->irq);
 	u32 reg;
 
 	reg = __raw_readl(regs + S3C64XX_UINTM);
@@ -62,10 +62,10 @@ static void s3c_irq_uart_maskack(unsigne
 	__raw_writel(1 << bit, regs + S3C64XX_UINTP);
 }
 
-static void s3c_irq_uart_unmask(unsigned int irq)
+static void s3c_irq_uart_unmask(struct irq_data *data)
 {
-	void __iomem *regs = s3c_irq_uart_base(irq);
-	unsigned int bit = s3c_irq_uart_bit(irq);
+	void __iomem *regs = s3c_irq_uart_base(data);
+	unsigned int bit = s3c_irq_uart_bit(data->irq);
 	u32 reg;
 
 	reg = __raw_readl(regs + S3C64XX_UINTM);
@@ -73,17 +73,17 @@ static void s3c_irq_uart_unmask(unsigned
 	__raw_writel(reg, regs + S3C64XX_UINTM);
 }
 
-static void s3c_irq_uart_ack(unsigned int irq)
+static void s3c_irq_uart_ack(struct irq_data *data)
 {
-	void __iomem *regs = s3c_irq_uart_base(irq);
-	unsigned int bit = s3c_irq_uart_bit(irq);
+	void __iomem *regs = s3c_irq_uart_base(data);
+	unsigned int bit = s3c_irq_uart_bit(data->irq);
 
 	__raw_writel(1 << bit, regs + S3C64XX_UINTP);
 }
 
 static void s3c_irq_demux_uart(unsigned int irq, struct irq_desc *desc)
 {
-	struct s3c_uart_irq *uirq = desc->handler_data;
+	struct s3c_uart_irq *uirq = desc->irq_data.handler_data;
 	u32 pend = __raw_readl(uirq->regs + S3C64XX_UINTP);
 	int base = uirq->base_irq;
 
@@ -99,10 +99,10 @@ static void s3c_irq_demux_uart(unsigned
 
 static struct irq_chip s3c_irq_uart = {
 	.name		= "s3c-uart",
-	.mask		= s3c_irq_uart_mask,
-	.unmask		= s3c_irq_uart_unmask,
-	.mask_ack	= s3c_irq_uart_maskack,
-	.ack		= s3c_irq_uart_ack,
+	.irq_mask	= s3c_irq_uart_mask,
+	.irq_unmask	= s3c_irq_uart_unmask,
+	.irq_mask_ack	= s3c_irq_uart_maskack,
+	.irq_ack	= s3c_irq_uart_ack,
 };
 
 static void __init s3c_init_uart_irq(struct s3c_uart_irq *uirq)
@@ -124,7 +124,7 @@ static void __init s3c_init_uart_irq(str
 		set_irq_flags(irq, IRQF_VALID);
 	}
 
-	desc->handler_data = uirq;
+	desc->irq_data.handler_data = uirq;
 	set_irq_chained_handler(uirq->parent_irq, s3c_irq_demux_uart);
 }
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-samsung/irq-vic-timer.c linux-libre-2.6.38-gnu1/arch/arm/plat-samsung/irq-vic-timer.c
--- linux-libre-2.6.37-gnu1/arch/arm/plat-samsung/irq-vic-timer.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-samsung/irq-vic-timer.c	2011-03-14 21:20:32.000000000 -0400
@@ -24,43 +24,46 @@
 
 static void s3c_irq_demux_vic_timer(unsigned int irq, struct irq_desc *desc)
 {
-	generic_handle_irq((int)desc->handler_data);
+	generic_handle_irq((int)desc->irq_data.handler_data);
 }
 
 /* We assume the IRQ_TIMER0..IRQ_TIMER4 range is continuous. */
 
-static void s3c_irq_timer_mask(unsigned int irq)
+static void s3c_irq_timer_mask(struct irq_data *data)
 {
 	u32 reg = __raw_readl(S3C64XX_TINT_CSTAT);
+	u32 mask = (u32)data->chip_data;
 
 	reg &= 0x1f;  /* mask out pending interrupts */
-	reg &= ~(1 << (irq - IRQ_TIMER0));
+	reg &= ~mask;
 	__raw_writel(reg, S3C64XX_TINT_CSTAT);
 }
 
-static void s3c_irq_timer_unmask(unsigned int irq)
+static void s3c_irq_timer_unmask(struct irq_data *data)
 {
 	u32 reg = __raw_readl(S3C64XX_TINT_CSTAT);
+	u32 mask = (u32)data->chip_data;
 
 	reg &= 0x1f;  /* mask out pending interrupts */
-	reg |= 1 << (irq - IRQ_TIMER0);
+	reg |= mask;
 	__raw_writel(reg, S3C64XX_TINT_CSTAT);
 }
 
-static void s3c_irq_timer_ack(unsigned int irq)
+static void s3c_irq_timer_ack(struct irq_data *data)
 {
 	u32 reg = __raw_readl(S3C64XX_TINT_CSTAT);
+	u32 mask = (u32)data->chip_data;
 
 	reg &= 0x1f;
-	reg |= (1 << 5) << (irq - IRQ_TIMER0);
+	reg |= mask << 5;
 	__raw_writel(reg, S3C64XX_TINT_CSTAT);
 }
 
 static struct irq_chip s3c_irq_timer = {
 	.name		= "s3c-timer",
-	.mask		= s3c_irq_timer_mask,
-	.unmask		= s3c_irq_timer_unmask,
-	.ack		= s3c_irq_timer_ack,
+	.irq_mask	= s3c_irq_timer_mask,
+	.irq_unmask	= s3c_irq_timer_unmask,
+	.irq_ack	= s3c_irq_timer_ack,
 };
 
 /**
@@ -79,8 +82,9 @@ void __init s3c_init_vic_timer_irq(unsig
 	set_irq_chained_handler(parent_irq, s3c_irq_demux_vic_timer);
 
 	set_irq_chip(timer_irq, &s3c_irq_timer);
+	set_irq_chip_data(timer_irq, (void *)(1 << (timer_irq - IRQ_TIMER0)));
 	set_irq_handler(timer_irq, handle_level_irq);
 	set_irq_flags(timer_irq, IRQF_VALID);
 
-	desc->handler_data = (void *)timer_irq;
+	desc->irq_data.handler_data = (void *)timer_irq;
 }
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-samsung/Kconfig linux-libre-2.6.38-gnu1/arch/arm/plat-samsung/Kconfig
--- linux-libre-2.6.37-gnu1/arch/arm/plat-samsung/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-samsung/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -95,6 +95,12 @@ config S3C_GPIO_PULL_UPDOWN
 	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
@@ -333,4 +339,12 @@ config SAMSUNG_WAKEMASK
 	  and above. This code allows a set of interrupt to wakeup-mask
 	  mappings. See <plat/wakeup-mask.h>
 
+comment "Power Domain"
+
+config SAMSUNG_PD
+	bool "Samsung Power Domain"
+	depends on PM_RUNTIME
+	help
+	  Say Y here if you want to control Power Domain by Runtime PM.
+
 endif
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-samsung/Makefile linux-libre-2.6.38-gnu1/arch/arm/plat-samsung/Makefile
--- linux-libre-2.6.37-gnu1/arch/arm/plat-samsung/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-samsung/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -17,6 +17,7 @@ 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_GPIOLIB_4BIT)	+= gpiolib.o
 obj-$(CONFIG_SAMSUNG_CLKSRC)	+= clock-clksrc.o
@@ -73,6 +74,10 @@ obj-$(CONFIG_SAMSUNG_PM_CHECK)	+= pm-che
 
 obj-$(CONFIG_SAMSUNG_WAKEMASK)	+= wakeup-mask.o
 
+# PD support
+
+obj-$(CONFIG_SAMSUNG_PD)	+= pd.o
+
 # PWM support
 
 obj-$(CONFIG_HAVE_PWM)		+= pwm.o
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-samsung/pd.c linux-libre-2.6.38-gnu1/arch/arm/plat-samsung/pd.c
--- linux-libre-2.6.37-gnu1/arch/arm/plat-samsung/pd.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-samsung/pd.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,95 @@
+/* linux/arch/arm/plat-samsung/pd.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Samsung 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/init.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <linux/pm_runtime.h>
+
+#include <plat/pd.h>
+
+static int samsung_pd_probe(struct platform_device *pdev)
+{
+	struct samsung_pd_info *pdata = pdev->dev.platform_data;
+	struct device *dev = &pdev->dev;
+
+	if (!pdata) {
+		dev_err(dev, "no device data specified\n");
+		return -ENOENT;
+	}
+
+	pm_runtime_set_active(dev);
+	pm_runtime_enable(dev);
+
+	dev_info(dev, "power domain registered\n");
+	return 0;
+}
+
+static int __devexit samsung_pd_remove(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+
+	pm_runtime_disable(dev);
+	return 0;
+}
+
+static int samsung_pd_runtime_suspend(struct device *dev)
+{
+	struct samsung_pd_info *pdata = dev->platform_data;
+	int ret = 0;
+
+	if (pdata->disable)
+		ret = pdata->disable(dev);
+
+	dev_dbg(dev, "suspended\n");
+	return ret;
+}
+
+static int samsung_pd_runtime_resume(struct device *dev)
+{
+	struct samsung_pd_info *pdata = dev->platform_data;
+	int ret = 0;
+
+	if (pdata->enable)
+		ret = pdata->enable(dev);
+
+	dev_dbg(dev, "resumed\n");
+	return ret;
+}
+
+static const struct dev_pm_ops samsung_pd_pm_ops = {
+	.runtime_suspend	= samsung_pd_runtime_suspend,
+	.runtime_resume		= samsung_pd_runtime_resume,
+};
+
+static struct platform_driver samsung_pd_driver = {
+	.driver		= {
+		.name		= "samsung-pd",
+		.owner		= THIS_MODULE,
+		.pm		= &samsung_pd_pm_ops,
+	},
+	.probe		= samsung_pd_probe,
+	.remove		= __devexit_p(samsung_pd_remove),
+};
+
+static int __init samsung_pd_init(void)
+{
+	int ret;
+
+	ret = platform_driver_register(&samsung_pd_driver);
+	if (ret)
+		printk(KERN_ERR "%s: failed to add PD driver\n", __func__);
+
+	return ret;
+}
+arch_initcall(samsung_pd_init);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-samsung/pm.c linux-libre-2.6.38-gnu1/arch/arm/plat-samsung/pm.c
--- linux-libre-2.6.37-gnu1/arch/arm/plat-samsung/pm.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-samsung/pm.c	2011-03-14 21:20:32.000000000 -0400
@@ -136,15 +136,15 @@ static void s3c_pm_restore_uarts(void) {
 unsigned long s3c_irqwake_intmask	= 0xffffffffL;
 unsigned long s3c_irqwake_eintmask	= 0xffffffffL;
 
-int s3c_irqext_wake(unsigned int irqno, unsigned int state)
+int s3c_irqext_wake(struct irq_data *data, unsigned int state)
 {
-	unsigned long bit = 1L << IRQ_EINT_BIT(irqno);
+	unsigned long bit = 1L << IRQ_EINT_BIT(data->irq);
 
 	if (!(s3c_irqwake_eintallow & bit))
 		return -ENOENT;
 
 	printk(KERN_INFO "wake %s for irq %d\n",
-	       state ? "enabled" : "disabled", irqno);
+	       state ? "enabled" : "disabled", data->irq);
 
 	if (!state)
 		s3c_irqwake_eintmask |= bit;
@@ -355,7 +355,7 @@ static void s3c_pm_finish(void)
 	s3c_pm_check_cleanup();
 }
 
-static struct platform_suspend_ops s3c_pm_ops = {
+static const struct platform_suspend_ops s3c_pm_ops = {
 	.enter		= s3c_pm_enter,
 	.prepare	= s3c_pm_prepare,
 	.finish		= s3c_pm_finish,
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-spear/include/plat/clock.h linux-libre-2.6.38-gnu1/arch/arm/plat-spear/include/plat/clock.h
--- linux-libre-2.6.37-gnu1/arch/arm/plat-spear/include/plat/clock.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-spear/include/plat/clock.h	2011-03-14 21:20:32.000000000 -0400
@@ -15,7 +15,7 @@
 #define __PLAT_CLOCK_H
 
 #include <linux/list.h>
-#include <asm/clkdev.h>
+#include <linux/clkdev.h>
 #include <linux/types.h>
 
 /* clk structure flags */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-spear/include/plat/keyboard.h linux-libre-2.6.38-gnu1/arch/arm/plat-spear/include/plat/keyboard.h
--- linux-libre-2.6.37-gnu1/arch/arm/plat-spear/include/plat/keyboard.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-spear/include/plat/keyboard.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2010 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 __PLAT_KEYBOARD_H
+#define __PLAT_KEYBOARD_H
+
+#include <linux/bitops.h>
+#include <linux/input.h>
+#include <linux/input/matrix_keypad.h>
+#include <linux/types.h>
+
+#define DECLARE_KEYMAP(_name) \
+int _name[] = { \
+	KEY(0, 0, KEY_ESC), \
+	KEY(0, 1, KEY_1), \
+	KEY(0, 2, KEY_2), \
+	KEY(0, 3, KEY_3), \
+	KEY(0, 4, KEY_4), \
+	KEY(0, 5, KEY_5), \
+	KEY(0, 6, KEY_6), \
+	KEY(0, 7, KEY_7), \
+	KEY(0, 8, KEY_8), \
+	KEY(1, 0, KEY_9), \
+	KEY(1, 1, KEY_MINUS), \
+	KEY(1, 2, KEY_EQUAL), \
+	KEY(1, 3, KEY_BACKSPACE), \
+	KEY(1, 4, KEY_TAB), \
+	KEY(1, 5, KEY_Q), \
+	KEY(1, 6, KEY_W), \
+	KEY(1, 7, KEY_E), \
+	KEY(1, 8, KEY_R), \
+	KEY(2, 0, KEY_T), \
+	KEY(2, 1, KEY_Y), \
+	KEY(2, 2, KEY_U), \
+	KEY(2, 3, KEY_I), \
+	KEY(2, 4, KEY_O), \
+	KEY(2, 5, KEY_P), \
+	KEY(2, 6, KEY_LEFTBRACE), \
+	KEY(2, 7, KEY_RIGHTBRACE), \
+	KEY(2, 8, KEY_ENTER), \
+	KEY(3, 0, KEY_LEFTCTRL), \
+	KEY(3, 1, KEY_A), \
+	KEY(3, 2, KEY_S), \
+	KEY(3, 3, KEY_D), \
+	KEY(3, 4, KEY_F), \
+	KEY(3, 5, KEY_G), \
+	KEY(3, 6, KEY_H), \
+	KEY(3, 7, KEY_J), \
+	KEY(3, 8, KEY_K), \
+	KEY(4, 0, KEY_L), \
+	KEY(4, 1, KEY_SEMICOLON), \
+	KEY(4, 2, KEY_APOSTROPHE), \
+	KEY(4, 3, KEY_GRAVE), \
+	KEY(4, 4, KEY_LEFTSHIFT), \
+	KEY(4, 5, KEY_BACKSLASH), \
+	KEY(4, 6, KEY_Z), \
+	KEY(4, 7, KEY_X), \
+	KEY(4, 8, KEY_C), \
+	KEY(4, 0, KEY_L), \
+	KEY(4, 1, KEY_SEMICOLON), \
+	KEY(4, 2, KEY_APOSTROPHE), \
+	KEY(4, 3, KEY_GRAVE), \
+	KEY(4, 4, KEY_LEFTSHIFT), \
+	KEY(4, 5, KEY_BACKSLASH), \
+	KEY(4, 6, KEY_Z), \
+	KEY(4, 7, KEY_X), \
+	KEY(4, 8, KEY_C), \
+	KEY(4, 0, KEY_L), \
+	KEY(4, 1, KEY_SEMICOLON), \
+	KEY(4, 2, KEY_APOSTROPHE), \
+	KEY(4, 3, KEY_GRAVE), \
+	KEY(4, 4, KEY_LEFTSHIFT), \
+	KEY(4, 5, KEY_BACKSLASH), \
+	KEY(4, 6, KEY_Z), \
+	KEY(4, 7, KEY_X), \
+	KEY(4, 8, KEY_C), \
+	KEY(5, 0, KEY_V), \
+	KEY(5, 1, KEY_B), \
+	KEY(5, 2, KEY_N), \
+	KEY(5, 3, KEY_M), \
+	KEY(5, 4, KEY_COMMA), \
+	KEY(5, 5, KEY_DOT), \
+	KEY(5, 6, KEY_SLASH), \
+	KEY(5, 7, KEY_RIGHTSHIFT), \
+	KEY(5, 8, KEY_KPASTERISK), \
+	KEY(6, 0, KEY_LEFTALT), \
+	KEY(6, 1, KEY_SPACE), \
+	KEY(6, 2, KEY_CAPSLOCK), \
+	KEY(6, 3, KEY_F1), \
+	KEY(6, 4, KEY_F2), \
+	KEY(6, 5, KEY_F3), \
+	KEY(6, 6, KEY_F4), \
+	KEY(6, 7, KEY_F5), \
+	KEY(6, 8, KEY_F6), \
+	KEY(7, 0, KEY_F7), \
+	KEY(7, 1, KEY_F8), \
+	KEY(7, 2, KEY_F9), \
+	KEY(7, 3, KEY_F10), \
+	KEY(7, 4, KEY_NUMLOCK), \
+	KEY(7, 5, KEY_SCROLLLOCK), \
+	KEY(7, 6, KEY_KP7), \
+	KEY(7, 7, KEY_KP8), \
+	KEY(7, 8, KEY_KP9), \
+	KEY(8, 0, KEY_KPMINUS), \
+	KEY(8, 1, KEY_KP4), \
+	KEY(8, 2, KEY_KP5), \
+	KEY(8, 3, KEY_KP6), \
+	KEY(8, 4, KEY_KPPLUS), \
+	KEY(8, 5, KEY_KP1), \
+	KEY(8, 6, KEY_KP2), \
+	KEY(8, 7, KEY_KP3), \
+	KEY(8, 8, KEY_KP0), \
+}
+
+/**
+ * struct kbd_platform_data - spear keyboard platform data
+ * keymap: pointer to keymap data (table and size)
+ * rep: enables key autorepeat
+ *
+ * This structure is supposed to be used by platform code to supply
+ * keymaps to drivers that implement keyboards.
+ */
+struct kbd_platform_data {
+	const struct matrix_keymap_data *keymap;
+	bool rep;
+};
+
+/* This function is used to set platform data field of pdev->dev */
+static inline void
+kbd_set_plat_data(struct platform_device *pdev, struct kbd_platform_data *data)
+{
+	pdev->dev.platform_data = data;
+}
+
+#endif /* __PLAT_KEYBOARD_H */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-spear/include/plat/uncompress.h linux-libre-2.6.38-gnu1/arch/arm/plat-spear/include/plat/uncompress.h
--- linux-libre-2.6.37-gnu1/arch/arm/plat-spear/include/plat/uncompress.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-spear/include/plat/uncompress.h	2011-03-14 21:20:32.000000000 -0400
@@ -24,10 +24,10 @@ static inline void putc(int c)
 {
 	void __iomem *base = (void __iomem *)SPEAR_DBG_UART_BASE;
 
-	while (readl(base + UART01x_FR) & UART01x_FR_TXFF)
+	while (readl_relaxed(base + UART01x_FR) & UART01x_FR_TXFF)
 		barrier();
 
-	writel(c, base + UART01x_DR);
+	writel_relaxed(c, base + UART01x_DR);
 }
 
 static inline void flush(void)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-spear/include/plat/vmalloc.h linux-libre-2.6.38-gnu1/arch/arm/plat-spear/include/plat/vmalloc.h
--- linux-libre-2.6.37-gnu1/arch/arm/plat-spear/include/plat/vmalloc.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-spear/include/plat/vmalloc.h	2011-03-14 21:20:32.000000000 -0400
@@ -14,6 +14,6 @@
 #ifndef __PLAT_VMALLOC_H
 #define __PLAT_VMALLOC_H
 
-#define VMALLOC_END		0xF0000000
+#define VMALLOC_END		0xF0000000UL
 
 #endif /* __PLAT_VMALLOC_H */
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-spear/shirq.c linux-libre-2.6.38-gnu1/arch/arm/plat-spear/shirq.c
--- linux-libre-2.6.37-gnu1/arch/arm/plat-spear/shirq.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-spear/shirq.c	2011-03-14 21:20:32.000000000 -0400
@@ -20,10 +20,10 @@
 struct spear_shirq *shirq;
 static DEFINE_SPINLOCK(lock);
 
-static void shirq_irq_mask(unsigned irq)
+static void shirq_irq_mask(struct irq_data *d)
 {
-	struct spear_shirq *shirq = get_irq_chip_data(irq);
-	u32 val, id = irq - shirq->dev_config[0].virq;
+	struct spear_shirq *shirq = irq_data_get_irq_chip_data(d);
+	u32 val, id = d->irq - shirq->dev_config[0].virq;
 	unsigned long flags;
 
 	if ((shirq->regs.enb_reg == -1) || shirq->dev_config[id].enb_mask == -1)
@@ -39,10 +39,10 @@ static void shirq_irq_mask(unsigned irq)
 	spin_unlock_irqrestore(&lock, flags);
 }
 
-static void shirq_irq_unmask(unsigned irq)
+static void shirq_irq_unmask(struct irq_data *d)
 {
-	struct spear_shirq *shirq = get_irq_chip_data(irq);
-	u32 val, id = irq - shirq->dev_config[0].virq;
+	struct spear_shirq *shirq = irq_data_get_irq_chip_data(d);
+	u32 val, id = d->irq - shirq->dev_config[0].virq;
 	unsigned long flags;
 
 	if ((shirq->regs.enb_reg == -1) || shirq->dev_config[id].enb_mask == -1)
@@ -60,9 +60,9 @@ static void shirq_irq_unmask(unsigned ir
 
 static struct irq_chip shirq_chip = {
 	.name		= "spear_shirq",
-	.ack		= shirq_irq_mask,
-	.mask		= shirq_irq_mask,
-	.unmask		= shirq_irq_unmask,
+	.irq_ack	= shirq_irq_mask,
+	.irq_mask	= shirq_irq_mask,
+	.irq_unmask	= shirq_irq_unmask,
 };
 
 static void shirq_handler(unsigned irq, struct irq_desc *desc)
@@ -70,7 +70,7 @@ static void shirq_handler(unsigned irq,
 	u32 i, val, mask;
 	struct spear_shirq *shirq = get_irq_data(irq);
 
-	desc->chip->ack(irq);
+	desc->irq_data.chip->irq_ack(&desc->irq_data);
 	while ((val = readl(shirq->regs.base + shirq->regs.status_reg) &
 				shirq->regs.status_reg_mask)) {
 		for (i = 0; (i < shirq->dev_count) && val; i++) {
@@ -92,7 +92,7 @@ static void shirq_handler(unsigned irq,
 			writel(mask, shirq->regs.base + shirq->regs.clear_reg);
 		}
 	}
-	desc->chip->unmask(irq);
+	desc->irq_data.chip->irq_unmask(&desc->irq_data);
 }
 
 int spear_shirq_register(struct spear_shirq *shirq)
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-spear/time.c linux-libre-2.6.38-gnu1/arch/arm/plat-spear/time.c
--- linux-libre-2.6.37-gnu1/arch/arm/plat-spear/time.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-spear/time.c	2011-03-14 21:20:32.000000000 -0400
@@ -81,8 +81,6 @@ static struct clocksource clksrc = {
 	.rating = 200,		/* its a pretty decent clock */
 	.read = clocksource_read_cycles,
 	.mask = 0xFFFF,		/* 16 bits */
-	.mult = 0,		/* to be computed */
-	.shift = 0,		/* to be computed */
 	.flags = CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
@@ -105,10 +103,8 @@ static void spear_clocksource_init(void)
 	val |= CTRL_ENABLE ;
 	writew(val, gpt_base + CR(CLKSRC));
 
-	clocksource_calc_mult_shift(&clksrc, tick_rate, SPEAR_MIN_RANGE);
-
 	/* register the clocksource */
-	clocksource_register(&clksrc);
+	clocksource_register_hz(&clksrc, tick_rate);
 }
 
 static struct clock_event_device clkevt = {
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-stmp3xxx/clock.c linux-libre-2.6.38-gnu1/arch/arm/plat-stmp3xxx/clock.c
--- linux-libre-2.6.37-gnu1/arch/arm/plat-stmp3xxx/clock.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-stmp3xxx/clock.c	2011-03-14 21:20:32.000000000 -0400
@@ -25,9 +25,9 @@
 #include <linux/err.h>
 #include <linux/delay.h>
 #include <linux/io.h>
+#include <linux/clkdev.h>
 
 #include <asm/mach-types.h>
-#include <asm/clkdev.h>
 #include <mach/platform.h>
 #include <mach/regs-clkctrl.h>
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-stmp3xxx/irq.c linux-libre-2.6.38-gnu1/arch/arm/plat-stmp3xxx/irq.c
--- linux-libre-2.6.37-gnu1/arch/arm/plat-stmp3xxx/irq.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-stmp3xxx/irq.c	2011-03-14 21:20:32.000000000 -0400
@@ -34,7 +34,7 @@ void __init stmp3xxx_init_irq(struct irq
 
 	/* Disable all interrupts initially */
 	for (i = 0; i < NR_REAL_IRQS; i++) {
-		chip->mask(i);
+		chip->irq_mask(irq_get_irq_data(i));
 		set_irq_chip(i, chip);
 		set_irq_handler(i, handle_level_irq);
 		set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-stmp3xxx/pinmux.c linux-libre-2.6.38-gnu1/arch/arm/plat-stmp3xxx/pinmux.c
--- linux-libre-2.6.37-gnu1/arch/arm/plat-stmp3xxx/pinmux.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-stmp3xxx/pinmux.c	2011-03-14 21:20:32.000000000 -0400
@@ -351,27 +351,27 @@ void stmp3xxx_release_pin_group(struct p
 }
 EXPORT_SYMBOL(stmp3xxx_release_pin_group);
 
-static int stmp3xxx_irq_to_gpio(int irq,
+static int stmp3xxx_irq_data_to_gpio(struct irq_data *d,
 	struct stmp3xxx_pinmux_bank **bank, unsigned *gpio)
 {
 	struct stmp3xxx_pinmux_bank *pm;
 
 	for (pm = pinmux_banks; pm < pinmux_banks + NR_BANKS; pm++)
-		if (pm->virq <= irq && irq < pm->virq + 32) {
+		if (pm->virq <= d->irq && d->irq < pm->virq + 32) {
 			*bank = pm;
-			*gpio = irq - pm->virq;
+			*gpio = d->irq - pm->virq;
 			return 0;
 		}
 	return -ENOENT;
 }
 
-static int stmp3xxx_set_irqtype(unsigned irq, unsigned type)
+static int stmp3xxx_set_irqtype(struct irq_data *d, unsigned type)
 {
 	struct stmp3xxx_pinmux_bank *pm;
 	unsigned gpio;
 	int l, p;
 
-	stmp3xxx_irq_to_gpio(irq, &pm, &gpio);
+	stmp3xxx_irq_data_to_gpio(d, &pm, &gpio);
 	switch (type) {
 	case IRQ_TYPE_EDGE_RISING:
 		l = 0; p = 1; break;
@@ -398,33 +398,33 @@ static int stmp3xxx_set_irqtype(unsigned
 	return 0;
 }
 
-static void stmp3xxx_pin_ack_irq(unsigned irq)
+static void stmp3xxx_pin_ack_irq(struct irq_data *d)
 {
 	u32 stat;
 	struct stmp3xxx_pinmux_bank *pm;
 	unsigned gpio;
 
-	stmp3xxx_irq_to_gpio(irq, &pm, &gpio);
+	stmp3xxx_irq_data_to_gpio(d, &pm, &gpio);
 	stat = __raw_readl(pm->irqstat) & (1 << gpio);
 	stmp3xxx_clearl(stat, pm->irqstat);
 }
 
-static void stmp3xxx_pin_mask_irq(unsigned irq)
+static void stmp3xxx_pin_mask_irq(struct irq_data *d)
 {
 	struct stmp3xxx_pinmux_bank *pm;
 	unsigned gpio;
 
-	stmp3xxx_irq_to_gpio(irq, &pm, &gpio);
+	stmp3xxx_irq_data_to_gpio(d, &pm, &gpio);
 	stmp3xxx_clearl(1 << gpio, pm->irqen);
 	stmp3xxx_clearl(1 << gpio, pm->pin2irq);
 }
 
-static void stmp3xxx_pin_unmask_irq(unsigned irq)
+static void stmp3xxx_pin_unmask_irq(struct irq_data *d)
 {
 	struct stmp3xxx_pinmux_bank *pm;
 	unsigned gpio;
 
-	stmp3xxx_irq_to_gpio(irq, &pm, &gpio);
+	stmp3xxx_irq_data_to_gpio(d, &pm, &gpio);
 	stmp3xxx_setl(1 << gpio, pm->irqen);
 	stmp3xxx_setl(1 << gpio, pm->pin2irq);
 }
@@ -503,10 +503,10 @@ static void stmp3xxx_gpio_irq(u32 irq, s
 }
 
 static struct irq_chip gpio_irq_chip = {
-	.ack	= stmp3xxx_pin_ack_irq,
-	.mask	= stmp3xxx_pin_mask_irq,
-	.unmask	= stmp3xxx_pin_unmask_irq,
-	.set_type = stmp3xxx_set_irqtype,
+	.irq_ack	= stmp3xxx_pin_ack_irq,
+	.irq_mask	= stmp3xxx_pin_mask_irq,
+	.irq_unmask	= stmp3xxx_pin_unmask_irq,
+	.irq_set_type	= stmp3xxx_set_irqtype,
 };
 
 int __init stmp3xxx_pinmux_init(int virtual_irq_start)
@@ -533,7 +533,7 @@ int __init stmp3xxx_pinmux_init(int virt
 		pm->virq = virtual_irq_start + b * 32;
 
 		for (virq = pm->virq; virq < pm->virq; virq++) {
-			gpio_irq_chip.mask(virq);
+			gpio_irq_chip.irq_mask(irq_get_irq_data(virq));
 			set_irq_chip(virq, &gpio_irq_chip);
 			set_irq_handler(virq, handle_level_irq);
 			set_irq_flags(virq, IRQF_VALID);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-stmp3xxx/timer.c linux-libre-2.6.38-gnu1/arch/arm/plat-stmp3xxx/timer.c
--- linux-libre-2.6.37-gnu1/arch/arm/plat-stmp3xxx/timer.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-stmp3xxx/timer.c	2011-03-14 21:20:32.000000000 -0400
@@ -89,7 +89,6 @@ static struct clocksource cksrc_stmp3xxx
 	.rating         = 250,
 	.read           = stmp3xxx_clock_read,
 	.mask           = CLOCKSOURCE_MASK(16),
-	.shift          = 10,
 	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
@@ -106,8 +105,6 @@ static struct irqaction stmp3xxx_timer_i
  */
 static void __init stmp3xxx_init_timer(void)
 {
-	cksrc_stmp3xxx.mult = clocksource_hz2mult(CLOCK_TICK_RATE,
-				cksrc_stmp3xxx.shift);
 	ckevt_timrot.mult = div_sc(CLOCK_TICK_RATE, NSEC_PER_SEC,
 				ckevt_timrot.shift);
 	ckevt_timrot.min_delta_ns = clockevent_delta2ns(2, &ckevt_timrot);
@@ -140,7 +137,7 @@ static void __init stmp3xxx_init_timer(v
 
 	setup_irq(IRQ_TIMER0, &stmp3xxx_timer_irq);
 
-	clocksource_register(&cksrc_stmp3xxx);
+	clocksource_register_hz(&cksrc_stmp3xxx, CLOCK_TICK_RATE);
 	clockevents_register_device(&ckevt_timrot);
 }
 
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-versatile/include/plat/sched_clock.h linux-libre-2.6.38-gnu1/arch/arm/plat-versatile/include/plat/sched_clock.h
--- linux-libre-2.6.37-gnu1/arch/arm/plat-versatile/include/plat/sched_clock.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-versatile/include/plat/sched_clock.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,6 @@
+#ifndef ARM_PLAT_SCHED_CLOCK_H
+#define ARM_PLAT_SCHED_CLOCK_H
+
+void versatile_sched_clock_init(void __iomem *, unsigned long);
+
+#endif
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-versatile/include/plat/timer-sp.h linux-libre-2.6.38-gnu1/arch/arm/plat-versatile/include/plat/timer-sp.h
--- linux-libre-2.6.37-gnu1/arch/arm/plat-versatile/include/plat/timer-sp.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-versatile/include/plat/timer-sp.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,2 +0,0 @@
-void sp804_clocksource_init(void __iomem *);
-void sp804_clockevents_init(void __iomem *, unsigned int);
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-versatile/Makefile linux-libre-2.6.38-gnu1/arch/arm/plat-versatile/Makefile
--- linux-libre-2.6.37-gnu1/arch/arm/plat-versatile/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-versatile/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -1,7 +1,7 @@
 obj-y	:= clock.o
-obj-$(CONFIG_ARM_TIMER_SP804) += timer-sp.o
-obj-$(CONFIG_ARCH_REALVIEW) += sched-clock.o
-obj-$(CONFIG_ARCH_VERSATILE) += sched-clock.o
+ifneq ($(CONFIG_ARCH_INTEGRATOR),y)
+obj-y	+= sched-clock.o
+endif
 ifeq ($(CONFIG_LEDS_CLASS),y)
 obj-$(CONFIG_ARCH_REALVIEW) += leds.o
 obj-$(CONFIG_ARCH_VERSATILE) += leds.o
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-versatile/sched-clock.c linux-libre-2.6.38-gnu1/arch/arm/plat-versatile/sched-clock.c
--- linux-libre-2.6.37-gnu1/arch/arm/plat-versatile/sched-clock.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-versatile/sched-clock.c	2011-03-14 21:20:32.000000000 -0400
@@ -18,36 +18,41 @@
  * 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/cnt32_to_63.h>
 #include <linux/io.h>
-#include <asm/div64.h>
-
-#include <mach/hardware.h>
-#include <mach/platform.h>
+#include <linux/sched.h>
 
-#ifdef VERSATILE_SYS_BASE
-#define REFCOUNTER	(__io_address(VERSATILE_SYS_BASE) + VERSATILE_SYS_24MHz_OFFSET)
-#endif
+#include <asm/sched_clock.h>
+#include <plat/sched_clock.h>
 
-#ifdef REALVIEW_SYS_BASE
-#define REFCOUNTER	(__io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_24MHz_OFFSET)
-#endif
+static DEFINE_CLOCK_DATA(cd);
+static void __iomem *ctr;
 
 /*
- * This is the Realview and Versatile sched_clock implementation.  This
- * has a resolution of 41.7ns, and a maximum value of about 35583 days.
- *
- * The return value is guaranteed to be monotonic in that range as
- * long as there is always less than 89 seconds between successive
- * calls to this function.
+ * Constants generated by clocks_calc_mult_shift(m, s, 24MHz, NSEC_PER_SEC, 60).
+ * This gives a resolution of about 41ns and a wrap period of about 178s.
  */
-unsigned long long sched_clock(void)
+#define SC_MULT		2796202667u
+#define SC_SHIFT	26
+
+unsigned long long notrace sched_clock(void)
 {
-	unsigned long long v = cnt32_to_63(readl(REFCOUNTER));
+	if (ctr) {
+		u32 cyc = readl(ctr);
+		return cyc_to_fixed_sched_clock(&cd, cyc, (u32)~0,
+						SC_MULT, SC_SHIFT);
+	} else
+		return 0;
+}
 
-	/* the <<1 gets rid of the cnt_32_to_63 top bit saving on a bic insn */
-	v *= 125<<1;
-	do_div(v, 3<<1);
+static void notrace versatile_update_sched_clock(void)
+{
+	u32 cyc = readl(ctr);
+	update_sched_clock(&cd, cyc, (u32)~0);
+}
 
-	return v;
+void __init versatile_sched_clock_init(void __iomem *reg, unsigned long rate)
+{
+	ctr = reg;
+	init_fixed_sched_clock(&cd, versatile_update_sched_clock,
+			       32, rate, SC_MULT, SC_SHIFT);
 }
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/plat-versatile/timer-sp.c linux-libre-2.6.38-gnu1/arch/arm/plat-versatile/timer-sp.c
--- linux-libre-2.6.37-gnu1/arch/arm/plat-versatile/timer-sp.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/plat-versatile/timer-sp.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,156 +0,0 @@
-/*
- *  linux/arch/arm/plat-versatile/timer-sp.c
- *
- *  Copyright (C) 1999 - 2003 ARM Limited
- *  Copyright (C) 2000 Deep Blue Solutions 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-#include <linux/clocksource.h>
-#include <linux/clockchips.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/io.h>
-
-#include <asm/hardware/arm_timer.h>
-
-#include <plat/timer-sp.h>
-
-/*
- * These timers are currently always setup to be clocked at 1MHz.
- */
-#define TIMER_FREQ_KHZ	(1000)
-#define TIMER_RELOAD	(TIMER_FREQ_KHZ * 1000 / HZ)
-
-static void __iomem *clksrc_base;
-
-static cycle_t sp804_read(struct clocksource *cs)
-{
-	return ~readl(clksrc_base + TIMER_VALUE);
-}
-
-static struct clocksource clocksource_sp804 = {
-	.name		= "timer3",
-	.rating		= 200,
-	.read		= sp804_read,
-	.mask		= CLOCKSOURCE_MASK(32),
-	.shift		= 20,
-	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
-};
-
-void __init sp804_clocksource_init(void __iomem *base)
-{
-	struct clocksource *cs = &clocksource_sp804;
-
-	clksrc_base = base;
-
-	/* setup timer 0 as free-running clocksource */
-	writel(0, clksrc_base + TIMER_CTRL);
-	writel(0xffffffff, clksrc_base + TIMER_LOAD);
-	writel(0xffffffff, clksrc_base + TIMER_VALUE);
-	writel(TIMER_CTRL_32BIT | TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC,
-		clksrc_base + TIMER_CTRL);
-
-	cs->mult = clocksource_khz2mult(TIMER_FREQ_KHZ, cs->shift);
-	clocksource_register(cs);
-}
-
-
-static void __iomem *clkevt_base;
-
-/*
- * IRQ handler for the timer
- */
-static irqreturn_t sp804_timer_interrupt(int irq, void *dev_id)
-{
-	struct clock_event_device *evt = dev_id;
-
-	/* clear the interrupt */
-	writel(1, clkevt_base + TIMER_INTCLR);
-
-	evt->event_handler(evt);
-
-	return IRQ_HANDLED;
-}
-
-static void sp804_set_mode(enum clock_event_mode mode,
-	struct clock_event_device *evt)
-{
-	unsigned long ctrl = TIMER_CTRL_32BIT | TIMER_CTRL_IE;
-
-	writel(ctrl, clkevt_base + TIMER_CTRL);
-
-	switch (mode) {
-	case CLOCK_EVT_MODE_PERIODIC:
-		writel(TIMER_RELOAD, clkevt_base + TIMER_LOAD);
-		ctrl |= TIMER_CTRL_PERIODIC | TIMER_CTRL_ENABLE;
-		break;
-
-	case CLOCK_EVT_MODE_ONESHOT:
-		/* period set, and timer enabled in 'next_event' hook */
-		ctrl |= TIMER_CTRL_ONESHOT;
-		break;
-
-	case CLOCK_EVT_MODE_UNUSED:
-	case CLOCK_EVT_MODE_SHUTDOWN:
-	default:
-		break;
-	}
-
-	writel(ctrl, clkevt_base + TIMER_CTRL);
-}
-
-static int sp804_set_next_event(unsigned long next,
-	struct clock_event_device *evt)
-{
-	unsigned long ctrl = readl(clkevt_base + TIMER_CTRL);
-
-	writel(next, clkevt_base + TIMER_LOAD);
-	writel(ctrl | TIMER_CTRL_ENABLE, clkevt_base + TIMER_CTRL);
-
-	return 0;
-}
-
-static struct clock_event_device sp804_clockevent = {
-	.name		= "timer0",
-	.shift		= 32,
-	.features       = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
-	.set_mode	= sp804_set_mode,
-	.set_next_event	= sp804_set_next_event,
-	.rating		= 300,
-	.cpumask	= cpu_all_mask,
-};
-
-static struct irqaction sp804_timer_irq = {
-	.name		= "timer",
-	.flags		= IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
-	.handler	= sp804_timer_interrupt,
-	.dev_id		= &sp804_clockevent,
-};
-
-void __init sp804_clockevents_init(void __iomem *base, unsigned int timer_irq)
-{
-	struct clock_event_device *evt = &sp804_clockevent;
-
-	clkevt_base = base;
-
-	evt->irq = timer_irq;
-	evt->mult = div_sc(TIMER_FREQ_KHZ, NSEC_PER_MSEC, evt->shift);
-	evt->max_delta_ns = clockevent_delta2ns(0xffffffff, evt);
-	evt->min_delta_ns = clockevent_delta2ns(0xf, evt);
-
-	setup_irq(timer_irq, &sp804_timer_irq);
-	clockevents_register_device(evt);
-}
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/tools/mach-types linux-libre-2.6.38-gnu1/arch/arm/tools/mach-types
--- linux-libre-2.6.37-gnu1/arch/arm/tools/mach-types	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/tools/mach-types	2011-03-14 21:20:32.000000000 -0400
@@ -12,7 +12,7 @@
 #
 #   http://www.arm.linux.org.uk/developer/machines/?action=new
 #
-# Last update: Sun Dec 12 23:24:27 2010
+# Last update: Mon Feb 7 08:59:27 2011
 #
 # machine_is_xxx	CONFIG_xxxx		MACH_TYPE_xxx		number
 #
@@ -2240,7 +2240,7 @@ arm_ultimator2		MACH_ARM_ULTIMATOR2	ARM_
 vs_v210			MACH_VS_V210		VS_V210			2252
 vs_v212			MACH_VS_V212		VS_V212			2253
 hmt			MACH_HMT		HMT			2254
-suen3			MACH_SUEN3		SUEN3			2255
+km_kirkwood		MACH_KM_KIRKWOOD	KM_KIRKWOOD		2255
 vesper			MACH_VESPER		VESPER			2256
 str9			MACH_STR9		STR9			2257
 omap3_wl_ff		MACH_OMAP3_WL_FF	OMAP3_WL_FF		2258
@@ -2987,7 +2987,7 @@ pxwnas_500_1000		MACH_PXWNAS_500_1000	PX
 ea20			MACH_EA20		EA20			3002
 awm2			MACH_AWM2		AWM2			3003
 ti8148evm		MACH_TI8148EVM		TI8148EVM		3004
-tegra_seaboard		MACH_TEGRA_SEABOARD	TEGRA_SEABOARD		3005
+seaboard		MACH_SEABOARD		SEABOARD		3005
 linkstation_chlv2	MACH_LINKSTATION_CHLV2	LINKSTATION_CHLV2	3006
 tera_pro2_rack		MACH_TERA_PRO2_RACK	TERA_PRO2_RACK		3007
 rubys			MACH_RUBYS		RUBYS			3008
@@ -3190,7 +3190,7 @@ synergy			MACH_SYNERGY		SYNERGY			3205
 ics_if_voip		MACH_ICS_IF_VOIP	ICS_IF_VOIP		3206
 wlf_cragg_6410		MACH_WLF_CRAGG_6410	WLF_CRAGG_6410		3207
 punica			MACH_PUNICA		PUNICA			3208
-sbc_nt250		MACH_SBC_NT250		SBC_NT250		3209
+trimslice		MACH_TRIMSLICE		TRIMSLICE		3209
 mx27_wmultra		MACH_MX27_WMULTRA	MX27_WMULTRA		3210
 mackerel		MACH_MACKEREL		MACKEREL		3211
 fa9x27			MACH_FA9X27		FA9X27			3213
@@ -3219,3 +3219,100 @@ pivicc			MACH_PIVICC		PIVICC			3235
 pcm048			MACH_PCM048		PCM048			3236
 dds			MACH_DDS		DDS			3237
 chalten_xa1		MACH_CHALTEN_XA1	CHALTEN_XA1		3238
+ts48xx			MACH_TS48XX		TS48XX			3239
+tonga2_tfttimer		MACH_TONGA2_TFTTIMER	TONGA2_TFTTIMER		3240
+whistler		MACH_WHISTLER		WHISTLER		3241
+asl_phoenix		MACH_ASL_PHOENIX	ASL_PHOENIX		3242
+at91sam9263otlite	MACH_AT91SAM9263OTLITE	AT91SAM9263OTLITE	3243
+ddplug			MACH_DDPLUG		DDPLUG			3244
+d2plug			MACH_D2PLUG		D2PLUG			3245
+kzm9d			MACH_KZM9D		KZM9D			3246
+verdi_lte		MACH_VERDI_LTE		VERDI_LTE		3247
+nanozoom		MACH_NANOZOOM		NANOZOOM		3248
+dm3730_som_lv		MACH_DM3730_SOM_LV	DM3730_SOM_LV		3249
+dm3730_torpedo		MACH_DM3730_TORPEDO	DM3730_TORPEDO		3250
+anchovy			MACH_ANCHOVY		ANCHOVY			3251
+re2rev20		MACH_RE2REV20		RE2REV20		3253
+re2rev21		MACH_RE2REV21		RE2REV21		3254
+cns21xx			MACH_CNS21XX		CNS21XX			3255
+rider			MACH_RIDER		RIDER			3257
+nsk330			MACH_NSK330		NSK330			3258
+cns2133evb		MACH_CNS2133EVB		CNS2133EVB		3259
+z3_816x_mod		MACH_Z3_816X_MOD	Z3_816X_MOD		3260
+z3_814x_mod		MACH_Z3_814X_MOD	Z3_814X_MOD		3261
+beect			MACH_BEECT		BEECT			3262
+dma_thunderbug		MACH_DMA_THUNDERBUG	DMA_THUNDERBUG		3263
+omn_at91sam9g20		MACH_OMN_AT91SAM9G20	OMN_AT91SAM9G20		3264
+mx25_e2s_uc		MACH_MX25_E2S_UC	MX25_E2S_UC		3265
+mione			MACH_MIONE		MIONE			3266
+top9000_tcu		MACH_TOP9000_TCU	TOP9000_TCU		3267
+top9000_bsl		MACH_TOP9000_BSL	TOP9000_BSL		3268
+kingdom			MACH_KINGDOM		KINGDOM			3269
+armadillo460		MACH_ARMADILLO460	ARMADILLO460		3270
+lq2			MACH_LQ2		LQ2			3271
+sweda_tms2		MACH_SWEDA_TMS2		SWEDA_TMS2		3272
+mx53_loco		MACH_MX53_LOCO		MX53_LOCO		3273
+acer_a8			MACH_ACER_A8		ACER_A8			3275
+acer_gauguin		MACH_ACER_GAUGUIN	ACER_GAUGUIN		3276
+guppy			MACH_GUPPY		GUPPY			3277
+mx61_ard		MACH_MX61_ARD		MX61_ARD		3278
+tx53			MACH_TX53		TX53			3279
+omapl138_case_a3	MACH_OMAPL138_CASE_A3	OMAPL138_CASE_A3	3280
+uemd			MACH_UEMD		UEMD			3281
+ccwmx51mut		MACH_CCWMX51MUT		CCWMX51MUT		3282
+rockhopper		MACH_ROCKHOPPER		ROCKHOPPER		3283
+nookcolor		MACH_NOOKCOLOR		NOOKCOLOR		3284
+hkdkc100		MACH_HKDKC100		HKDKC100		3285
+ts42xx			MACH_TS42XX		TS42XX			3286
+aebl			MACH_AEBL		AEBL			3287
+wario			MACH_WARIO		WARIO			3288
+gfs_spm			MACH_GFS_SPM		GFS_SPM			3289
+cm_t3730		MACH_CM_T3730		CM_T3730		3290
+isc3			MACH_ISC3		ISC3			3291
+rascal			MACH_RASCAL		RASCAL			3292
+hrefv60			MACH_HREFV60		HREFV60			3293
+tpt_2_0			MACH_TPT_2_0		TPT_2_0			3294
+pyramid_td		MACH_PYRAMID_TD		PYRAMID_TD		3295
+splendor		MACH_SPLENDOR		SPLENDOR		3296
+guf_planet		MACH_GUF_PLANET		GUF_PLANET		3297
+msm8x60_qt		MACH_MSM8X60_QT		MSM8X60_QT		3298
+htc_hd_mini		MACH_HTC_HD_MINI	HTC_HD_MINI		3299
+athene			MACH_ATHENE		ATHENE			3300
+deep_r_ek_1		MACH_DEEP_R_EK_1	DEEP_R_EK_1		3301
+vivow_ct		MACH_VIVOW_CT		VIVOW_CT		3302
+nery_1000		MACH_NERY_1000		NERY_1000		3303
+rfl109145_ssrv		MACH_RFL109145_SSRV	RFL109145_SSRV		3304
+nmh			MACH_NMH		NMH			3305
+wn802t			MACH_WN802T		WN802T			3306
+dragonet		MACH_DRAGONET		DRAGONET		3307
+geneva_b		MACH_GENEVA_B		GENEVA_B		3308
+at91sam9263desk16l	MACH_AT91SAM9263DESK16L	AT91SAM9263DESK16L	3309
+bcmhana_sv		MACH_BCMHANA_SV		BCMHANA_SV		3310
+bcmhana_tablet		MACH_BCMHANA_TABLET	BCMHANA_TABLET		3311
+koi			MACH_KOI		KOI			3312
+ts4800			MACH_TS4800		TS4800			3313
+tqma9263		MACH_TQMA9263		TQMA9263		3314
+holiday			MACH_HOLIDAY		HOLIDAY			3315
+dma_6410		MACH_DMA6410		DMA6410			3316
+pcats_overlay		MACH_PCATS_OVERLAY	PCATS_OVERLAY		3317
+hwgw6410		MACH_HWGW6410		HWGW6410		3318
+shenzhou		MACH_SHENZHOU		SHENZHOU		3319
+cwme9210		MACH_CWME9210		CWME9210		3320
+cwme9210js		MACH_CWME9210JS		CWME9210JS		3321
+pgs_v1			MACH_PGS_SITARA		PGS_SITARA		3322
+colibri_tegra2		MACH_COLIBRI_TEGRA2	COLIBRI_TEGRA2		3323
+w21			MACH_W21		W21			3324
+polysat1		MACH_POLYSAT1		POLYSAT1		3325
+dataway			MACH_DATAWAY		DATAWAY			3326
+cobral138		MACH_COBRAL138		COBRAL138		3327
+roverpcs8		MACH_ROVERPCS8		ROVERPCS8		3328
+marvelc			MACH_MARVELC		MARVELC			3329
+navefihid		MACH_NAVEFIHID		NAVEFIHID		3330
+dm365_cv100		MACH_DM365_CV100	DM365_CV100		3331
+able			MACH_ABLE		ABLE			3332
+legacy			MACH_LEGACY		LEGACY			3333
+icong			MACH_ICONG		ICONG			3334
+rover_g8		MACH_ROVER_G8		ROVER_G8		3335
+t5388p			MACH_T5388P		T5388P			3336
+dingo			MACH_DINGO		DINGO			3337
+goflexhome		MACH_GOFLEXHOME		GOFLEXHOME		3338
diff -druNp linux-libre-2.6.37-gnu1/arch/arm/vfp/vfpmodule.c linux-libre-2.6.38-gnu1/arch/arm/vfp/vfpmodule.c
--- linux-libre-2.6.37-gnu1/arch/arm/vfp/vfpmodule.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/arm/vfp/vfpmodule.c	2011-03-14 21:20:32.000000000 -0400
@@ -10,9 +10,12 @@
  */
 #include <linux/module.h>
 #include <linux/types.h>
+#include <linux/cpu.h>
 #include <linux/kernel.h>
+#include <linux/notifier.h>
 #include <linux/signal.h>
 #include <linux/sched.h>
+#include <linux/smp.h>
 #include <linux/init.h>
 
 #include <asm/cputype.h>
@@ -484,7 +487,24 @@ void vfp_flush_hwstate(struct thread_inf
 	put_cpu();
 }
 
-#include <linux/smp.h>
+/*
+ * VFP hardware can lose all context when a CPU goes offline.
+ * Safely clear our held state when a CPU has been killed, and
+ * re-enable access to VFP when the CPU comes back online.
+ *
+ * Both CPU_DYING and CPU_STARTING are called on the CPU which
+ * is being offlined/onlined.
+ */
+static int vfp_hotplug(struct notifier_block *b, unsigned long action,
+	void *hcpu)
+{
+	if (action == CPU_DYING || action == CPU_DYING_FROZEN) {
+		unsigned int cpu = (long)hcpu;
+		last_VFP_context[cpu] = NULL;
+	} else if (action == CPU_STARTING || action == CPU_STARTING_FROZEN)
+		vfp_enable(NULL);
+	return NOTIFY_OK;
+}
 
 /*
  * VFP support code initialisation.
@@ -514,6 +534,8 @@ static int __init vfp_init(void)
 	else if (vfpsid & FPSID_NODOUBLE) {
 		printk("no double precision support\n");
 	} else {
+		hotcpu_notifier(vfp_hotplug, 0);
+
 		smp_call_function(vfp_enable, NULL, 1);
 
 		VFP_arch = (vfpsid & FPSID_ARCH_MASK) >> FPSID_ARCH_BIT;  /* Extract the architecture version */
diff -druNp linux-libre-2.6.37-gnu1/arch/avr32/boards/atngw100/setup.c linux-libre-2.6.38-gnu1/arch/avr32/boards/atngw100/setup.c
--- linux-libre-2.6.37-gnu1/arch/avr32/boards/atngw100/setup.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/avr32/boards/atngw100/setup.c	2011-03-14 21:20:32.000000000 -0400
@@ -188,7 +188,7 @@ static void __init set_hw_addr(struct pl
 	 */
 	regs = (void __iomem __force *)res->start;
 	pclk = clk_get(&pdev->dev, "pclk");
-	if (!pclk)
+	if (IS_ERR(pclk))
 		return;
 
 	clk_enable(pclk);
diff -druNp linux-libre-2.6.37-gnu1/arch/avr32/boards/atstk1000/atstk1002.c linux-libre-2.6.38-gnu1/arch/avr32/boards/atstk1000/atstk1002.c
--- linux-libre-2.6.37-gnu1/arch/avr32/boards/atstk1000/atstk1002.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/avr32/boards/atstk1000/atstk1002.c	2011-03-14 21:20:32.000000000 -0400
@@ -203,7 +203,7 @@ static void __init set_hw_addr(struct pl
 	 */
 	regs = (void __iomem __force *)res->start;
 	pclk = clk_get(&pdev->dev, "pclk");
-	if (!pclk)
+	if (IS_ERR(pclk))
 		return;
 
 	clk_enable(pclk);
diff -druNp linux-libre-2.6.37-gnu1/arch/avr32/boards/favr-32/setup.c linux-libre-2.6.38-gnu1/arch/avr32/boards/favr-32/setup.c
--- linux-libre-2.6.37-gnu1/arch/avr32/boards/favr-32/setup.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/avr32/boards/favr-32/setup.c	2011-03-14 21:20:32.000000000 -0400
@@ -206,7 +206,7 @@ static void __init set_hw_addr(struct pl
 	 */
 	regs = (void __iomem __force *)res->start;
 	pclk = clk_get(&pdev->dev, "pclk");
-	if (!pclk)
+	if (IS_ERR(pclk))
 		return;
 
 	clk_enable(pclk);
diff -druNp linux-libre-2.6.37-gnu1/arch/avr32/boards/hammerhead/setup.c linux-libre-2.6.38-gnu1/arch/avr32/boards/hammerhead/setup.c
--- linux-libre-2.6.37-gnu1/arch/avr32/boards/hammerhead/setup.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/avr32/boards/hammerhead/setup.c	2011-03-14 21:20:32.000000000 -0400
@@ -150,7 +150,7 @@ static void __init set_hw_addr(struct pl
 	regs = (void __iomem __force *)res->start;
 	pclk = clk_get(&pdev->dev, "pclk");
 
-	if (!pclk)
+	if (IS_ERR(pclk))
 		return;
 
 	clk_enable(pclk);
diff -druNp linux-libre-2.6.37-gnu1/arch/avr32/boards/merisc/setup.c linux-libre-2.6.38-gnu1/arch/avr32/boards/merisc/setup.c
--- linux-libre-2.6.37-gnu1/arch/avr32/boards/merisc/setup.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/avr32/boards/merisc/setup.c	2011-03-14 21:20:32.000000000 -0400
@@ -134,7 +134,7 @@ static void __init set_hw_addr(struct pl
 
 	regs = (void __iomem __force *)res->start;
 	pclk = clk_get(&pdev->dev, "pclk");
-	if (!pclk)
+	if (IS_ERR(pclk))
 		return;
 
 	clk_enable(pclk);
diff -druNp linux-libre-2.6.37-gnu1/arch/avr32/boards/mimc200/setup.c linux-libre-2.6.38-gnu1/arch/avr32/boards/mimc200/setup.c
--- linux-libre-2.6.37-gnu1/arch/avr32/boards/mimc200/setup.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/avr32/boards/mimc200/setup.c	2011-03-14 21:20:32.000000000 -0400
@@ -162,7 +162,7 @@ static void __init set_hw_addr(struct pl
 	 */
 	regs = (void __iomem __force *)res->start;
 	pclk = clk_get(&pdev->dev, "pclk");
-	if (!pclk)
+	if (IS_ERR(pclk))
 		return;
 
 	clk_enable(pclk);
diff -druNp linux-libre-2.6.37-gnu1/arch/avr32/configs/atngw100_defconfig linux-libre-2.6.38-gnu1/arch/avr32/configs/atngw100_defconfig
--- linux-libre-2.6.37-gnu1/arch/avr32/configs/atngw100_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/avr32/configs/atngw100_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -2,20 +2,17 @@ CONFIG_EXPERIMENTAL=y
 # 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_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_RELAY=y
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_SYSCTL_SYSCALL is not set
 # CONFIG_BASE_FULL is not set
 # CONFIG_COMPAT_BRK is not set
 CONFIG_PROFILING=y
 CONFIG_OPROFILE=m
-CONFIG_KPROBES=y
+# CONFIG_KPROBES is not set
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
-CONFIG_MODULE_FORCE_UNLOAD=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_IOSCHED_DEADLINE is not set
 CONFIG_NO_HZ=y
@@ -29,6 +26,7 @@ CONFIG_CPU_FREQ=y
 CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
 CONFIG_CPU_FREQ_GOV_USERSPACE=y
 CONFIG_CPU_FREQ_AT32AP=y
+CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y
 CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
@@ -72,8 +70,8 @@ CONFIG_MTD_UBI=y
 CONFIG_BLK_DEV_LOOP=m
 CONFIG_BLK_DEV_NBD=m
 CONFIG_BLK_DEV_RAM=m
+CONFIG_MISC_DEVICES=y
 CONFIG_ATMEL_TCLIB=y
-CONFIG_EEPROM_AT24=m
 CONFIG_NETDEVICES=y
 CONFIG_TUN=m
 CONFIG_NET_ETHERNET=y
@@ -106,6 +104,7 @@ CONFIG_GPIO_SYSFS=y
 CONFIG_WATCHDOG=y
 CONFIG_AT32AP700X_WDT=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_VBUS_DRAW=350
 CONFIG_USB_ZERO=m
 CONFIG_USB_ETH=m
 CONFIG_USB_GADGETFS=m
@@ -115,14 +114,12 @@ CONFIG_USB_CDC_COMPOSITE=m
 CONFIG_MMC=y
 CONFIG_MMC_TEST=m
 CONFIG_MMC_ATMELMCI=y
-CONFIG_MMC_SPI=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_LEDS_TRIGGER_DEFAULT_ON=y
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_AT32AP700X=y
 CONFIG_DMADEVICES=y
@@ -130,21 +127,23 @@ CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
 # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
 # CONFIG_EXT3_FS_XATTR is not set
+CONFIG_EXT4_FS=y
+# CONFIG_EXT4_FS_XATTR is not set
 # CONFIG_DNOTIFY is not set
 CONFIG_FUSE_FS=m
 CONFIG_MSDOS_FS=m
 CONFIG_VFAT_FS=m
 CONFIG_FAT_DEFAULT_CODEPAGE=850
+CONFIG_PROC_KCORE=y
 CONFIG_TMPFS=y
-CONFIG_CONFIGFS_FS=m
+CONFIG_CONFIGFS_FS=y
 CONFIG_JFFS2_FS=y
-CONFIG_UFS_FS=y
+CONFIG_UBIFS_FS=y
 CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
 CONFIG_ROOT_NFS=y
 CONFIG_NFSD=m
 CONFIG_NFSD_V3=y
-CONFIG_SMB_FS=m
 CONFIG_CIFS=m
 CONFIG_NLS_CODEPAGE_437=m
 CONFIG_NLS_CODEPAGE_850=m
@@ -155,5 +154,3 @@ CONFIG_DEBUG_FS=y
 CONFIG_DEBUG_KERNEL=y
 CONFIG_DETECT_HUNG_TASK=y
 CONFIG_FRAME_POINTER=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
-CONFIG_CRYPTO_PCBC=m
diff -druNp linux-libre-2.6.37-gnu1/arch/avr32/configs/atngw100_evklcd100_defconfig linux-libre-2.6.38-gnu1/arch/avr32/configs/atngw100_evklcd100_defconfig
--- linux-libre-2.6.37-gnu1/arch/avr32/configs/atngw100_evklcd100_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/avr32/configs/atngw100_evklcd100_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -2,20 +2,17 @@ CONFIG_EXPERIMENTAL=y
 # 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_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_RELAY=y
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_SYSCTL_SYSCALL is not set
 # CONFIG_BASE_FULL is not set
 # CONFIG_COMPAT_BRK is not set
 CONFIG_PROFILING=y
 CONFIG_OPROFILE=m
-CONFIG_KPROBES=y
+# CONFIG_KPROBES is not set
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
-CONFIG_MODULE_FORCE_UNLOAD=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_IOSCHED_DEADLINE is not set
 CONFIG_NO_HZ=y
@@ -31,6 +28,7 @@ CONFIG_CPU_FREQ=y
 CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
 CONFIG_CPU_FREQ_GOV_USERSPACE=y
 CONFIG_CPU_FREQ_AT32AP=y
+CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y
 CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
@@ -74,8 +72,10 @@ CONFIG_MTD_UBI=y
 CONFIG_BLK_DEV_LOOP=m
 CONFIG_BLK_DEV_NBD=m
 CONFIG_BLK_DEV_RAM=m
+CONFIG_MISC_DEVICES=y
 CONFIG_ATMEL_TCLIB=y
 CONFIG_NETDEVICES=y
+CONFIG_TUN=m
 CONFIG_NET_ETHERNET=y
 CONFIG_MACB=y
 # CONFIG_NETDEV_1000 is not set
@@ -104,6 +104,7 @@ CONFIG_I2C_GPIO=m
 CONFIG_SPI=y
 CONFIG_SPI_ATMEL=y
 CONFIG_SPI_SPIDEV=m
+CONFIG_GPIO_SYSFS=y
 # CONFIG_HWMON is not set
 CONFIG_WATCHDOG=y
 CONFIG_AT32AP700X_WDT=y
@@ -127,6 +128,7 @@ CONFIG_USB_FILE_STORAGE=m
 CONFIG_USB_G_SERIAL=m
 CONFIG_USB_CDC_COMPOSITE=m
 CONFIG_MMC=y
+CONFIG_MMC_TEST=m
 CONFIG_MMC_ATMELMCI=y
 CONFIG_NEW_LEDS=y
 CONFIG_LEDS_CLASS=y
@@ -141,11 +143,14 @@ CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
 # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
 # CONFIG_EXT3_FS_XATTR is not set
+CONFIG_EXT4_FS=y
+# CONFIG_EXT4_FS_XATTR is not set
 # CONFIG_DNOTIFY is not set
 CONFIG_FUSE_FS=m
 CONFIG_MSDOS_FS=m
 CONFIG_VFAT_FS=m
 CONFIG_FAT_DEFAULT_CODEPAGE=850
+CONFIG_PROC_KCORE=y
 CONFIG_TMPFS=y
 CONFIG_CONFIGFS_FS=y
 CONFIG_JFFS2_FS=y
@@ -155,7 +160,6 @@ CONFIG_NFS_V3=y
 CONFIG_ROOT_NFS=y
 CONFIG_NFSD=m
 CONFIG_NFSD_V3=y
-CONFIG_SMB_FS=m
 CONFIG_CIFS=m
 CONFIG_NLS_CODEPAGE_437=m
 CONFIG_NLS_CODEPAGE_850=m
@@ -166,4 +170,3 @@ CONFIG_DEBUG_FS=y
 CONFIG_DEBUG_KERNEL=y
 CONFIG_DETECT_HUNG_TASK=y
 CONFIG_FRAME_POINTER=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/avr32/configs/atngw100_evklcd101_defconfig linux-libre-2.6.38-gnu1/arch/avr32/configs/atngw100_evklcd101_defconfig
--- linux-libre-2.6.37-gnu1/arch/avr32/configs/atngw100_evklcd101_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/avr32/configs/atngw100_evklcd101_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -2,20 +2,17 @@ CONFIG_EXPERIMENTAL=y
 # 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_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_RELAY=y
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_SYSCTL_SYSCALL is not set
 # CONFIG_BASE_FULL is not set
 # CONFIG_COMPAT_BRK is not set
 CONFIG_PROFILING=y
 CONFIG_OPROFILE=m
-CONFIG_KPROBES=y
+# CONFIG_KPROBES is not set
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
-CONFIG_MODULE_FORCE_UNLOAD=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_IOSCHED_DEADLINE is not set
 CONFIG_NO_HZ=y
@@ -30,6 +27,7 @@ CONFIG_CPU_FREQ=y
 CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
 CONFIG_CPU_FREQ_GOV_USERSPACE=y
 CONFIG_CPU_FREQ_AT32AP=y
+CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y
 CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
@@ -73,8 +71,10 @@ CONFIG_MTD_UBI=y
 CONFIG_BLK_DEV_LOOP=m
 CONFIG_BLK_DEV_NBD=m
 CONFIG_BLK_DEV_RAM=m
+CONFIG_MISC_DEVICES=y
 CONFIG_ATMEL_TCLIB=y
 CONFIG_NETDEVICES=y
+CONFIG_TUN=m
 CONFIG_NET_ETHERNET=y
 CONFIG_MACB=y
 # CONFIG_NETDEV_1000 is not set
@@ -103,6 +103,7 @@ CONFIG_I2C_GPIO=m
 CONFIG_SPI=y
 CONFIG_SPI_ATMEL=y
 CONFIG_SPI_SPIDEV=m
+CONFIG_GPIO_SYSFS=y
 # CONFIG_HWMON is not set
 CONFIG_WATCHDOG=y
 CONFIG_AT32AP700X_WDT=y
@@ -126,6 +127,7 @@ CONFIG_USB_FILE_STORAGE=m
 CONFIG_USB_G_SERIAL=m
 CONFIG_USB_CDC_COMPOSITE=m
 CONFIG_MMC=y
+CONFIG_MMC_TEST=m
 CONFIG_MMC_ATMELMCI=y
 CONFIG_NEW_LEDS=y
 CONFIG_LEDS_CLASS=y
@@ -140,11 +142,14 @@ CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
 # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
 # CONFIG_EXT3_FS_XATTR is not set
+CONFIG_EXT4_FS=y
+# CONFIG_EXT4_FS_XATTR is not set
 # CONFIG_DNOTIFY is not set
 CONFIG_FUSE_FS=m
 CONFIG_MSDOS_FS=m
 CONFIG_VFAT_FS=m
 CONFIG_FAT_DEFAULT_CODEPAGE=850
+CONFIG_PROC_KCORE=y
 CONFIG_TMPFS=y
 CONFIG_CONFIGFS_FS=y
 CONFIG_JFFS2_FS=y
@@ -154,7 +159,6 @@ CONFIG_NFS_V3=y
 CONFIG_ROOT_NFS=y
 CONFIG_NFSD=m
 CONFIG_NFSD_V3=y
-CONFIG_SMB_FS=m
 CONFIG_CIFS=m
 CONFIG_NLS_CODEPAGE_437=m
 CONFIG_NLS_CODEPAGE_850=m
@@ -165,4 +169,3 @@ CONFIG_DEBUG_FS=y
 CONFIG_DEBUG_KERNEL=y
 CONFIG_DETECT_HUNG_TASK=y
 CONFIG_FRAME_POINTER=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/avr32/configs/atngw100mkii_defconfig linux-libre-2.6.38-gnu1/arch/avr32/configs/atngw100mkii_defconfig
--- linux-libre-2.6.37-gnu1/arch/avr32/configs/atngw100mkii_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/avr32/configs/atngw100mkii_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -2,20 +2,17 @@ CONFIG_EXPERIMENTAL=y
 # 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_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_RELAY=y
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_SYSCTL_SYSCALL is not set
 # CONFIG_BASE_FULL is not set
 # CONFIG_COMPAT_BRK is not set
 CONFIG_PROFILING=y
 CONFIG_OPROFILE=m
-CONFIG_KPROBES=y
+# CONFIG_KPROBES is not set
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
-CONFIG_MODULE_FORCE_UNLOAD=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_IOSCHED_DEADLINE is not set
 CONFIG_NO_HZ=y
@@ -29,6 +26,7 @@ CONFIG_CPU_FREQ=y
 CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
 CONFIG_CPU_FREQ_GOV_USERSPACE=y
 CONFIG_CPU_FREQ_AT32AP=y
+CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y
 CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
@@ -74,6 +72,7 @@ CONFIG_MTD_UBI=y
 CONFIG_BLK_DEV_LOOP=m
 CONFIG_BLK_DEV_NBD=m
 CONFIG_BLK_DEV_RAM=m
+CONFIG_MISC_DEVICES=y
 CONFIG_ATMEL_TCLIB=y
 CONFIG_NETDEVICES=y
 CONFIG_TUN=m
@@ -107,6 +106,7 @@ CONFIG_GPIO_SYSFS=y
 CONFIG_WATCHDOG=y
 CONFIG_AT32AP700X_WDT=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_VBUS_DRAW=350
 CONFIG_USB_ZERO=m
 CONFIG_USB_ETH=m
 CONFIG_USB_GADGETFS=m
@@ -116,14 +116,12 @@ CONFIG_USB_CDC_COMPOSITE=m
 CONFIG_MMC=y
 CONFIG_MMC_TEST=m
 CONFIG_MMC_ATMELMCI=y
-CONFIG_MMC_SPI=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_LEDS_TRIGGER_DEFAULT_ON=y
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_AT32AP700X=y
 CONFIG_DMADEVICES=y
@@ -131,21 +129,23 @@ CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
 # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
 # CONFIG_EXT3_FS_XATTR is not set
+CONFIG_EXT4_FS=y
+# CONFIG_EXT4_FS_XATTR is not set
 # CONFIG_DNOTIFY is not set
 CONFIG_FUSE_FS=m
 CONFIG_MSDOS_FS=m
 CONFIG_VFAT_FS=m
 CONFIG_FAT_DEFAULT_CODEPAGE=850
+CONFIG_PROC_KCORE=y
 CONFIG_TMPFS=y
-CONFIG_CONFIGFS_FS=m
+CONFIG_CONFIGFS_FS=y
 CONFIG_JFFS2_FS=y
-CONFIG_UFS_FS=y
+CONFIG_UBIFS_FS=y
 CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
 CONFIG_ROOT_NFS=y
 CONFIG_NFSD=m
 CONFIG_NFSD_V3=y
-CONFIG_SMB_FS=m
 CONFIG_CIFS=m
 CONFIG_NLS_CODEPAGE_437=m
 CONFIG_NLS_CODEPAGE_850=m
@@ -156,5 +156,3 @@ CONFIG_DEBUG_FS=y
 CONFIG_DEBUG_KERNEL=y
 CONFIG_DETECT_HUNG_TASK=y
 CONFIG_FRAME_POINTER=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
-CONFIG_CRYPTO_PCBC=m
diff -druNp linux-libre-2.6.37-gnu1/arch/avr32/configs/atngw100mkii_evklcd100_defconfig linux-libre-2.6.38-gnu1/arch/avr32/configs/atngw100mkii_evklcd100_defconfig
--- linux-libre-2.6.37-gnu1/arch/avr32/configs/atngw100mkii_evklcd100_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/avr32/configs/atngw100mkii_evklcd100_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -2,20 +2,17 @@ CONFIG_EXPERIMENTAL=y
 # 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_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_RELAY=y
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_SYSCTL_SYSCALL is not set
 # CONFIG_BASE_FULL is not set
 # CONFIG_COMPAT_BRK is not set
 CONFIG_PROFILING=y
 CONFIG_OPROFILE=m
-CONFIG_KPROBES=y
+# CONFIG_KPROBES is not set
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
-CONFIG_MODULE_FORCE_UNLOAD=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_IOSCHED_DEADLINE is not set
 CONFIG_NO_HZ=y
@@ -32,6 +29,7 @@ CONFIG_CPU_FREQ=y
 CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
 CONFIG_CPU_FREQ_GOV_USERSPACE=y
 CONFIG_CPU_FREQ_AT32AP=y
+CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y
 CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
@@ -77,8 +75,10 @@ CONFIG_MTD_UBI=y
 CONFIG_BLK_DEV_LOOP=m
 CONFIG_BLK_DEV_NBD=m
 CONFIG_BLK_DEV_RAM=m
+CONFIG_MISC_DEVICES=y
 CONFIG_ATMEL_TCLIB=y
 CONFIG_NETDEVICES=y
+CONFIG_TUN=m
 CONFIG_NET_ETHERNET=y
 CONFIG_MACB=y
 # CONFIG_NETDEV_1000 is not set
@@ -107,6 +107,7 @@ CONFIG_I2C_GPIO=m
 CONFIG_SPI=y
 CONFIG_SPI_ATMEL=y
 CONFIG_SPI_SPIDEV=m
+CONFIG_GPIO_SYSFS=y
 # CONFIG_HWMON is not set
 CONFIG_WATCHDOG=y
 CONFIG_AT32AP700X_WDT=y
@@ -130,6 +131,7 @@ CONFIG_USB_FILE_STORAGE=m
 CONFIG_USB_G_SERIAL=m
 CONFIG_USB_CDC_COMPOSITE=m
 CONFIG_MMC=y
+CONFIG_MMC_TEST=m
 CONFIG_MMC_ATMELMCI=y
 CONFIG_NEW_LEDS=y
 CONFIG_LEDS_CLASS=y
@@ -144,11 +146,14 @@ CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
 # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
 # CONFIG_EXT3_FS_XATTR is not set
+CONFIG_EXT4_FS=y
+# CONFIG_EXT4_FS_XATTR is not set
 # CONFIG_DNOTIFY is not set
 CONFIG_FUSE_FS=m
 CONFIG_MSDOS_FS=m
 CONFIG_VFAT_FS=m
 CONFIG_FAT_DEFAULT_CODEPAGE=850
+CONFIG_PROC_KCORE=y
 CONFIG_TMPFS=y
 CONFIG_CONFIGFS_FS=y
 CONFIG_JFFS2_FS=y
@@ -158,7 +163,6 @@ CONFIG_NFS_V3=y
 CONFIG_ROOT_NFS=y
 CONFIG_NFSD=m
 CONFIG_NFSD_V3=y
-CONFIG_SMB_FS=m
 CONFIG_CIFS=m
 CONFIG_NLS_CODEPAGE_437=m
 CONFIG_NLS_CODEPAGE_850=m
@@ -169,4 +173,3 @@ CONFIG_DEBUG_FS=y
 CONFIG_DEBUG_KERNEL=y
 CONFIG_DETECT_HUNG_TASK=y
 CONFIG_FRAME_POINTER=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/avr32/configs/atngw100mkii_evklcd101_defconfig linux-libre-2.6.38-gnu1/arch/avr32/configs/atngw100mkii_evklcd101_defconfig
--- linux-libre-2.6.37-gnu1/arch/avr32/configs/atngw100mkii_evklcd101_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/avr32/configs/atngw100mkii_evklcd101_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -2,20 +2,17 @@ CONFIG_EXPERIMENTAL=y
 # 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_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_RELAY=y
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_SYSCTL_SYSCALL is not set
 # CONFIG_BASE_FULL is not set
 # CONFIG_COMPAT_BRK is not set
 CONFIG_PROFILING=y
 CONFIG_OPROFILE=m
-CONFIG_KPROBES=y
+# CONFIG_KPROBES is not set
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
-CONFIG_MODULE_FORCE_UNLOAD=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_IOSCHED_DEADLINE is not set
 CONFIG_NO_HZ=y
@@ -31,6 +28,7 @@ CONFIG_CPU_FREQ=y
 CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
 CONFIG_CPU_FREQ_GOV_USERSPACE=y
 CONFIG_CPU_FREQ_AT32AP=y
+CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y
 CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
@@ -76,8 +74,10 @@ CONFIG_MTD_UBI=y
 CONFIG_BLK_DEV_LOOP=m
 CONFIG_BLK_DEV_NBD=m
 CONFIG_BLK_DEV_RAM=m
+CONFIG_MISC_DEVICES=y
 CONFIG_ATMEL_TCLIB=y
 CONFIG_NETDEVICES=y
+CONFIG_TUN=m
 CONFIG_NET_ETHERNET=y
 CONFIG_MACB=y
 # CONFIG_NETDEV_1000 is not set
@@ -106,6 +106,7 @@ CONFIG_I2C_GPIO=m
 CONFIG_SPI=y
 CONFIG_SPI_ATMEL=y
 CONFIG_SPI_SPIDEV=m
+CONFIG_GPIO_SYSFS=y
 # CONFIG_HWMON is not set
 CONFIG_WATCHDOG=y
 CONFIG_AT32AP700X_WDT=y
@@ -129,6 +130,7 @@ CONFIG_USB_FILE_STORAGE=m
 CONFIG_USB_G_SERIAL=m
 CONFIG_USB_CDC_COMPOSITE=m
 CONFIG_MMC=y
+CONFIG_MMC_TEST=m
 CONFIG_MMC_ATMELMCI=y
 CONFIG_NEW_LEDS=y
 CONFIG_LEDS_CLASS=y
@@ -143,11 +145,14 @@ CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
 # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
 # CONFIG_EXT3_FS_XATTR is not set
+CONFIG_EXT4_FS=y
+# CONFIG_EXT4_FS_XATTR is not set
 # CONFIG_DNOTIFY is not set
 CONFIG_FUSE_FS=m
 CONFIG_MSDOS_FS=m
 CONFIG_VFAT_FS=m
 CONFIG_FAT_DEFAULT_CODEPAGE=850
+CONFIG_PROC_KCORE=y
 CONFIG_TMPFS=y
 CONFIG_CONFIGFS_FS=y
 CONFIG_JFFS2_FS=y
@@ -157,7 +162,6 @@ CONFIG_NFS_V3=y
 CONFIG_ROOT_NFS=y
 CONFIG_NFSD=m
 CONFIG_NFSD_V3=y
-CONFIG_SMB_FS=m
 CONFIG_CIFS=m
 CONFIG_NLS_CODEPAGE_437=m
 CONFIG_NLS_CODEPAGE_850=m
@@ -168,4 +172,3 @@ CONFIG_DEBUG_FS=y
 CONFIG_DEBUG_KERNEL=y
 CONFIG_DETECT_HUNG_TASK=y
 CONFIG_FRAME_POINTER=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/avr32/configs/atstk1002_defconfig linux-libre-2.6.38-gnu1/arch/avr32/configs/atstk1002_defconfig
--- linux-libre-2.6.37-gnu1/arch/avr32/configs/atstk1002_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/avr32/configs/atstk1002_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -3,7 +3,6 @@ CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
 CONFIG_RELAY=y
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_SYSCTL_SYSCALL is not set
@@ -11,7 +10,7 @@ CONFIG_BLK_DEV_INITRD=y
 # CONFIG_COMPAT_BRK is not set
 CONFIG_PROFILING=y
 CONFIG_OPROFILE=m
-CONFIG_KPROBES=y
+# CONFIG_KPROBES is not set
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_BLK_DEV_BSG is not set
@@ -26,6 +25,7 @@ CONFIG_CPU_FREQ=y
 CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
 CONFIG_CPU_FREQ_GOV_USERSPACE=y
 CONFIG_CPU_FREQ_AT32AP=y
+CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y
 CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
@@ -35,6 +35,7 @@ CONFIG_INET=y
 CONFIG_IP_PNP=y
 CONFIG_IP_PNP_DHCP=y
 CONFIG_NET_IPIP=m
+CONFIG_NET_IPGRE_DEMUX=m
 CONFIG_NET_IPGRE=m
 CONFIG_INET_AH=m
 CONFIG_INET_ESP=m
@@ -58,16 +59,14 @@ CONFIG_MTD_BLOCK=y
 CONFIG_MTD_CFI=y
 CONFIG_MTD_CFI_AMDSTD=y
 CONFIG_MTD_PHYSMAP=y
-CONFIG_MTD_DATAFLASH=m
-CONFIG_MTD_M25P80=m
 CONFIG_MTD_UBI=y
 CONFIG_BLK_DEV_LOOP=m
 CONFIG_BLK_DEV_NBD=m
 CONFIG_BLK_DEV_RAM=m
+CONFIG_MISC_DEVICES=y
 CONFIG_ATMEL_PWM=m
 CONFIG_ATMEL_TCLIB=y
 CONFIG_ATMEL_SSC=m
-CONFIG_EEPROM_AT24=m
 # CONFIG_SCSI_PROC_FS is not set
 CONFIG_BLK_DEV_SD=m
 CONFIG_BLK_DEV_SR=m
@@ -120,7 +119,6 @@ CONFIG_SND_MIXER_OSS=m
 CONFIG_SND_PCM_OSS=m
 # CONFIG_SND_SUPPORT_OLD_API is not set
 # CONFIG_SND_VERBOSE_PROCFS is not set
-# CONFIG_SND_DRIVERS is not set
 CONFIG_SND_AT73C213=m
 # CONFIG_HID_SUPPORT is not set
 CONFIG_USB_GADGET=y
@@ -131,16 +129,15 @@ CONFIG_USB_FILE_STORAGE=m
 CONFIG_USB_G_SERIAL=m
 CONFIG_USB_CDC_COMPOSITE=m
 CONFIG_MMC=y
+CONFIG_MMC_TEST=m
 CONFIG_MMC_ATMELMCI=y
-CONFIG_MMC_SPI=m
 CONFIG_NEW_LEDS=y
-CONFIG_LEDS_CLASS=m
+CONFIG_LEDS_CLASS=y
 CONFIG_LEDS_ATMEL_PWM=m
 CONFIG_LEDS_GPIO=m
 CONFIG_LEDS_TRIGGERS=y
 CONFIG_LEDS_TRIGGER_TIMER=m
 CONFIG_LEDS_TRIGGER_HEARTBEAT=m
-CONFIG_LEDS_TRIGGER_DEFAULT_ON=m
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_AT32AP700X=y
 CONFIG_DMADEVICES=y
@@ -149,20 +146,23 @@ CONFIG_EXT3_FS=y
 # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
 # CONFIG_EXT3_FS_XATTR is not set
 CONFIG_EXT4_FS=y
+# CONFIG_EXT4_FS_XATTR is not set
 # CONFIG_DNOTIFY is not set
 CONFIG_FUSE_FS=m
 CONFIG_MSDOS_FS=m
 CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=850
 CONFIG_PROC_KCORE=y
 CONFIG_TMPFS=y
+CONFIG_CONFIGFS_FS=y
 CONFIG_JFFS2_FS=y
-# CONFIG_JFFS2_FS_WRITEBUFFER is not set
 CONFIG_UBIFS_FS=y
-CONFIG_MINIX_FS=m
 CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
 CONFIG_ROOT_NFS=y
+CONFIG_CIFS=m
 CONFIG_NLS_CODEPAGE_437=m
+CONFIG_NLS_CODEPAGE_850=m
 CONFIG_NLS_ISO8859_1=m
 CONFIG_NLS_UTF8=m
 CONFIG_MAGIC_SYSRQ=y
@@ -170,6 +170,3 @@ CONFIG_DEBUG_FS=y
 CONFIG_DEBUG_KERNEL=y
 CONFIG_DETECT_HUNG_TASK=y
 CONFIG_FRAME_POINTER=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
-# CONFIG_CRYPTO_HW is not set
-CONFIG_CRC_T10DIF=m
diff -druNp linux-libre-2.6.37-gnu1/arch/avr32/configs/atstk1003_defconfig linux-libre-2.6.38-gnu1/arch/avr32/configs/atstk1003_defconfig
--- linux-libre-2.6.37-gnu1/arch/avr32/configs/atstk1003_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/avr32/configs/atstk1003_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -2,22 +2,15 @@ CONFIG_EXPERIMENTAL=y
 # 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_AUDIT=y
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
 CONFIG_RELAY=y
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_SYSCTL_SYSCALL is not set
 # CONFIG_BASE_FULL is not set
-# CONFIG_SLUB_DEBUG is not set
 # CONFIG_COMPAT_BRK is not set
 CONFIG_PROFILING=y
 CONFIG_OPROFILE=m
-CONFIG_KPROBES=y
+# CONFIG_KPROBES is not set
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_BLK_DEV_BSG is not set
@@ -33,6 +26,7 @@ CONFIG_CPU_FREQ=y
 CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
 CONFIG_CPU_FREQ_GOV_USERSPACE=y
 CONFIG_CPU_FREQ_AT32AP=y
+CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y
 CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
@@ -54,18 +48,18 @@ CONFIG_MTD_BLOCK=y
 CONFIG_MTD_CFI=y
 CONFIG_MTD_CFI_AMDSTD=y
 CONFIG_MTD_PHYSMAP=y
-CONFIG_MTD_DATAFLASH=m
-CONFIG_MTD_M25P80=m
+CONFIG_MTD_UBI=y
 CONFIG_BLK_DEV_LOOP=m
 CONFIG_BLK_DEV_NBD=m
 CONFIG_BLK_DEV_RAM=m
+CONFIG_MISC_DEVICES=y
 CONFIG_ATMEL_PWM=m
 CONFIG_ATMEL_TCLIB=y
 CONFIG_ATMEL_SSC=m
-CONFIG_EEPROM_AT24=m
 # CONFIG_SCSI_PROC_FS is not set
 CONFIG_BLK_DEV_SD=m
 CONFIG_BLK_DEV_SR=m
+# CONFIG_SCSI_LOWLEVEL is not set
 CONFIG_ATA=m
 # CONFIG_SATA_PMP is not set
 CONFIG_PATA_AT32=m
@@ -77,6 +71,7 @@ CONFIG_PPP_ASYNC=m
 CONFIG_PPP_DEFLATE=m
 CONFIG_PPP_BSDCOMP=m
 CONFIG_INPUT=m
+CONFIG_INPUT_EVDEV=m
 # CONFIG_KEYBOARD_ATKBD is not set
 CONFIG_KEYBOARD_GPIO=m
 # CONFIG_MOUSE_PS2 is not set
@@ -106,7 +101,6 @@ CONFIG_SND_PCM_OSS=m
 CONFIG_SND_AT73C213=m
 # CONFIG_HID_SUPPORT is not set
 CONFIG_USB_GADGET=y
-CONFIG_USB_GADGET_DEBUG_FS=y
 CONFIG_USB_ZERO=m
 CONFIG_USB_ETH=m
 CONFIG_USB_GADGETFS=m
@@ -116,36 +110,39 @@ CONFIG_USB_CDC_COMPOSITE=m
 CONFIG_MMC=y
 CONFIG_MMC_TEST=m
 CONFIG_MMC_ATMELMCI=y
-CONFIG_MMC_SPI=m
 CONFIG_NEW_LEDS=y
 CONFIG_LEDS_CLASS=y
 CONFIG_LEDS_ATMEL_PWM=m
-CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_GPIO=m
 CONFIG_LEDS_TRIGGERS=y
-CONFIG_LEDS_TRIGGER_TIMER=y
-CONFIG_LEDS_TRIGGER_HEARTBEAT=y
-CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
+CONFIG_LEDS_TRIGGER_TIMER=m
+CONFIG_LEDS_TRIGGER_HEARTBEAT=m
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_AT32AP700X=y
 CONFIG_DMADEVICES=y
-CONFIG_DW_DMAC=y
-CONFIG_EXT2_FS=m
-CONFIG_EXT3_FS=m
+CONFIG_EXT2_FS=y
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
 # CONFIG_EXT3_FS_XATTR is not set
+CONFIG_EXT4_FS=y
+# CONFIG_EXT4_FS_XATTR is not set
 # CONFIG_DNOTIFY is not set
 CONFIG_FUSE_FS=m
 CONFIG_MSDOS_FS=m
 CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=850
 CONFIG_PROC_KCORE=y
 CONFIG_TMPFS=y
-CONFIG_CONFIGFS_FS=m
+CONFIG_CONFIGFS_FS=y
 CONFIG_JFFS2_FS=y
+CONFIG_UBIFS_FS=y
 # CONFIG_NETWORK_FILESYSTEMS is not set
 CONFIG_NLS_CODEPAGE_437=m
+CONFIG_NLS_CODEPAGE_850=m
 CONFIG_NLS_ISO8859_1=m
 CONFIG_NLS_UTF8=m
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_DEBUG_FS=y
 CONFIG_DEBUG_KERNEL=y
+CONFIG_DETECT_HUNG_TASK=y
 CONFIG_FRAME_POINTER=y
-CONFIG_CRC_T10DIF=m
diff -druNp linux-libre-2.6.37-gnu1/arch/avr32/configs/atstk1004_defconfig linux-libre-2.6.38-gnu1/arch/avr32/configs/atstk1004_defconfig
--- linux-libre-2.6.37-gnu1/arch/avr32/configs/atstk1004_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/avr32/configs/atstk1004_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -1,19 +1,32 @@
 CONFIG_EXPERIMENTAL=y
 # CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_RELAY=y
+CONFIG_BLK_DEV_INITRD=y
 # CONFIG_SYSCTL_SYSCALL is not set
 # CONFIG_BASE_FULL is not set
-# CONFIG_FUTEX is not set
-# CONFIG_EPOLL is not set
-# CONFIG_SIGNALFD is not set
-# CONFIG_TIMERFD is not set
-# CONFIG_EVENTFD is not set
 # CONFIG_COMPAT_BRK is not set
-CONFIG_SLOB=y
-# CONFIG_BLOCK is not set
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=m
+# CONFIG_KPROBES is not set
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
 CONFIG_BOARD_ATSTK1004=y
 # CONFIG_OWNERSHIP_TRACE is not set
+CONFIG_NMI_DEBUGGING=y
+CONFIG_PM=y
+CONFIG_CPU_FREQ=y
+# CONFIG_CPU_FREQ_STAT is not set
+CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_AT32AP=y
+CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y
 CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
@@ -31,40 +44,104 @@ 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_AMDSTD=y
 CONFIG_MTD_PHYSMAP=y
-# CONFIG_MISC_DEVICES is not set
-# CONFIG_INPUT is not set
+CONFIG_MTD_UBI=y
+CONFIG_BLK_DEV_LOOP=m
+CONFIG_BLK_DEV_NBD=m
+CONFIG_BLK_DEV_RAM=m
+CONFIG_MISC_DEVICES=y
+CONFIG_ATMEL_PWM=m
+CONFIG_ATMEL_TCLIB=y
+CONFIG_ATMEL_SSC=m
+# CONFIG_SCSI_PROC_FS is not set
+CONFIG_BLK_DEV_SD=m
+CONFIG_BLK_DEV_SR=m
+# CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_ATA=m
+# CONFIG_SATA_PMP is not set
+CONFIG_PATA_AT32=m
+CONFIG_NETDEVICES=y
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+CONFIG_PPP=m
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_INPUT=m
+CONFIG_INPUT_EVDEV=m
+# CONFIG_KEYBOARD_ATKBD is not set
+CONFIG_KEYBOARD_GPIO=m
+# CONFIG_MOUSE_PS2 is not set
+CONFIG_MOUSE_GPIO=m
 # CONFIG_SERIO is not set
 # CONFIG_VT is not set
 # CONFIG_DEVKMEM is not set
 CONFIG_SERIAL_ATMEL=y
 CONFIG_SERIAL_ATMEL_CONSOLE=y
-# CONFIG_SERIAL_ATMEL_PDC is not set
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
+CONFIG_I2C=m
+CONFIG_I2C_CHARDEV=m
+CONFIG_I2C_GPIO=m
 CONFIG_SPI=y
 CONFIG_SPI_ATMEL=y
+CONFIG_SPI_SPIDEV=m
+CONFIG_GPIO_SYSFS=y
 # CONFIG_HWMON is not set
 CONFIG_WATCHDOG=y
 CONFIG_AT32AP700X_WDT=y
 CONFIG_FB=y
 CONFIG_FB_ATMEL=y
 CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_LCD_CLASS_DEVICE=y
 CONFIG_LCD_LTV350QV=y
 # CONFIG_BACKLIGHT_CLASS_DEVICE is not set
 CONFIG_USB_GADGET=y
-CONFIG_USB_ETH=y
-# CONFIG_USB_ETH_RNDIS is not set
+CONFIG_USB_ZERO=m
+CONFIG_USB_ETH=m
+CONFIG_USB_GADGETFS=m
+CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_G_SERIAL=m
+CONFIG_USB_CDC_COMPOSITE=m
+CONFIG_MMC=y
+CONFIG_MMC_TEST=m
+CONFIG_MMC_ATMELMCI=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_ATMEL_PWM=m
+CONFIG_LEDS_GPIO=m
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=m
+CONFIG_LEDS_TRIGGER_HEARTBEAT=m
 CONFIG_RTC_CLASS=y
-# CONFIG_RTC_INTF_PROC is not set
 CONFIG_RTC_DRV_AT32AP700X=y
+CONFIG_DMADEVICES=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_EXT4_FS=y
+# CONFIG_EXT4_FS_XATTR is not set
 # CONFIG_DNOTIFY is not set
+CONFIG_FUSE_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=850
 CONFIG_PROC_KCORE=y
-# CONFIG_PROC_PAGE_MONITOR is not set
 CONFIG_TMPFS=y
+CONFIG_CONFIGFS_FS=y
 CONFIG_JFFS2_FS=y
-# CONFIG_JFFS2_FS_WRITEBUFFER is not set
+CONFIG_UBIFS_FS=y
 # CONFIG_NETWORK_FILESYSTEMS is not set
+CONFIG_NLS_CODEPAGE_437=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_ISO8859_1=m
+CONFIG_NLS_UTF8=m
 CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_FS=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_DETECT_HUNG_TASK=y
+CONFIG_FRAME_POINTER=y
diff -druNp linux-libre-2.6.37-gnu1/arch/avr32/configs/atstk1006_defconfig linux-libre-2.6.38-gnu1/arch/avr32/configs/atstk1006_defconfig
--- linux-libre-2.6.37-gnu1/arch/avr32/configs/atstk1006_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/avr32/configs/atstk1006_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -3,7 +3,6 @@ CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
 CONFIG_RELAY=y
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_SYSCTL_SYSCALL is not set
@@ -11,7 +10,7 @@ CONFIG_BLK_DEV_INITRD=y
 # CONFIG_COMPAT_BRK is not set
 CONFIG_PROFILING=y
 CONFIG_OPROFILE=m
-CONFIG_KPROBES=y
+# CONFIG_KPROBES is not set
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_BLK_DEV_BSG is not set
@@ -37,6 +36,7 @@ CONFIG_INET=y
 CONFIG_IP_PNP=y
 CONFIG_IP_PNP_DHCP=y
 CONFIG_NET_IPIP=m
+CONFIG_NET_IPGRE_DEMUX=m
 CONFIG_NET_IPGRE=m
 CONFIG_INET_AH=m
 CONFIG_INET_ESP=m
@@ -60,15 +60,13 @@ CONFIG_MTD_BLOCK=y
 CONFIG_MTD_CFI=y
 CONFIG_MTD_CFI_AMDSTD=y
 CONFIG_MTD_PHYSMAP=y
-CONFIG_MTD_DATAFLASH=m
-CONFIG_MTD_DATAFLASH_OTP=y
-CONFIG_MTD_M25P80=m
 CONFIG_MTD_NAND=y
 CONFIG_MTD_NAND_ATMEL=y
 CONFIG_MTD_UBI=y
 CONFIG_BLK_DEV_LOOP=m
 CONFIG_BLK_DEV_NBD=m
 CONFIG_BLK_DEV_RAM=m
+CONFIG_MISC_DEVICES=y
 CONFIG_ATMEL_PWM=m
 CONFIG_ATMEL_TCLIB=y
 CONFIG_ATMEL_SSC=m
@@ -132,17 +130,17 @@ CONFIG_USB_ETH=m
 CONFIG_USB_GADGETFS=m
 CONFIG_USB_FILE_STORAGE=m
 CONFIG_USB_G_SERIAL=m
+CONFIG_USB_CDC_COMPOSITE=m
 CONFIG_MMC=y
+CONFIG_MMC_TEST=m
 CONFIG_MMC_ATMELMCI=y
-CONFIG_MMC_SPI=m
 CONFIG_NEW_LEDS=y
-CONFIG_LEDS_CLASS=m
+CONFIG_LEDS_CLASS=y
 CONFIG_LEDS_ATMEL_PWM=m
 CONFIG_LEDS_GPIO=m
 CONFIG_LEDS_TRIGGERS=y
 CONFIG_LEDS_TRIGGER_TIMER=m
 CONFIG_LEDS_TRIGGER_HEARTBEAT=m
-CONFIG_LEDS_TRIGGER_DEFAULT_ON=m
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_AT32AP700X=y
 CONFIG_DMADEVICES=y
@@ -156,15 +154,18 @@ CONFIG_EXT4_FS=y
 CONFIG_FUSE_FS=m
 CONFIG_MSDOS_FS=m
 CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=850
 CONFIG_PROC_KCORE=y
 CONFIG_TMPFS=y
+CONFIG_CONFIGFS_FS=y
 CONFIG_JFFS2_FS=y
 CONFIG_UBIFS_FS=y
-CONFIG_MINIX_FS=m
 CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
 CONFIG_ROOT_NFS=y
+CONFIG_CIFS=m
 CONFIG_NLS_CODEPAGE_437=m
+CONFIG_NLS_CODEPAGE_850=m
 CONFIG_NLS_ISO8859_1=m
 CONFIG_NLS_UTF8=m
 CONFIG_MAGIC_SYSRQ=y
@@ -172,7 +173,3 @@ CONFIG_DEBUG_FS=y
 CONFIG_DEBUG_KERNEL=y
 CONFIG_DETECT_HUNG_TASK=y
 CONFIG_FRAME_POINTER=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
-CONFIG_CRYPTO_FIPS=y
-# CONFIG_CRYPTO_HW is not set
-CONFIG_CRC_T10DIF=m
diff -druNp linux-libre-2.6.37-gnu1/arch/avr32/configs/favr-32_defconfig linux-libre-2.6.38-gnu1/arch/avr32/configs/favr-32_defconfig
--- linux-libre-2.6.37-gnu1/arch/avr32/configs/favr-32_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/avr32/configs/favr-32_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -11,7 +11,7 @@ CONFIG_BLK_DEV_INITRD=y
 # CONFIG_COMPAT_BRK is not set
 CONFIG_PROFILING=y
 CONFIG_OPROFILE=m
-CONFIG_KPROBES=y
+# CONFIG_KPROBES is not set
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_BLK_DEV_BSG is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/avr32/configs/hammerhead_defconfig linux-libre-2.6.38-gnu1/arch/avr32/configs/hammerhead_defconfig
--- linux-libre-2.6.37-gnu1/arch/avr32/configs/hammerhead_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/avr32/configs/hammerhead_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -12,7 +12,7 @@ CONFIG_BLK_DEV_INITRD=y
 # CONFIG_COMPAT_BRK is not set
 CONFIG_PROFILING=y
 CONFIG_OPROFILE=m
-CONFIG_KPROBES=y
+# CONFIG_KPROBES is not set
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 CONFIG_MODULE_FORCE_UNLOAD=y
diff -druNp linux-libre-2.6.37-gnu1/arch/avr32/include/asm/pgalloc.h linux-libre-2.6.38-gnu1/arch/avr32/include/asm/pgalloc.h
--- linux-libre-2.6.37-gnu1/arch/avr32/include/asm/pgalloc.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/avr32/include/asm/pgalloc.h	2011-03-14 21:20:32.000000000 -0400
@@ -8,6 +8,7 @@
 #ifndef __ASM_AVR32_PGALLOC_H
 #define __ASM_AVR32_PGALLOC_H
 
+#include <linux/mm.h>
 #include <linux/quicklist.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
diff -druNp linux-libre-2.6.37-gnu1/arch/avr32/include/asm/syscalls.h linux-libre-2.6.38-gnu1/arch/avr32/include/asm/syscalls.h
--- linux-libre-2.6.37-gnu1/arch/avr32/include/asm/syscalls.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/avr32/include/asm/syscalls.h	2011-03-14 21:20:32.000000000 -0400
@@ -15,20 +15,6 @@
 #include <linux/types.h>
 #include <linux/signal.h>
 
-/* kernel/process.c */
-asmlinkage int sys_fork(struct pt_regs *);
-asmlinkage int sys_clone(unsigned long, unsigned long,
-			 unsigned long, unsigned long,
-			 struct pt_regs *);
-asmlinkage int sys_vfork(struct pt_regs *);
-asmlinkage int sys_execve(const char __user *, char __user *__user *,
-			  char __user *__user *, struct pt_regs *);
-
-/* kernel/signal.c */
-asmlinkage int sys_sigaltstack(const stack_t __user *, stack_t __user *,
-			       struct pt_regs *);
-asmlinkage int sys_rt_sigreturn(struct pt_regs *);
-
 /* mm/cache.c */
 asmlinkage int sys_cacheflush(int, void __user *, size_t);
 
diff -druNp linux-libre-2.6.37-gnu1/arch/avr32/Kconfig linux-libre-2.6.38-gnu1/arch/avr32/Kconfig
--- linux-libre-2.6.37-gnu1/arch/avr32/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/avr32/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -1,8 +1,8 @@
 config AVR32
 	def_bool y
-	# With EMBEDDED=n, we get lots of stuff automatically selected
+	# With EXPERT=n, we get lots of stuff automatically selected
 	# that we usually don't need on AVR32.
-	select EMBEDDED
+	select EXPERT
 	select HAVE_CLK
 	select HAVE_OPROFILE
 	select HAVE_KPROBES
diff -druNp linux-libre-2.6.37-gnu1/arch/avr32/kernel/process.c linux-libre-2.6.38-gnu1/arch/avr32/kernel/process.c
--- linux-libre-2.6.37-gnu1/arch/avr32/kernel/process.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/avr32/kernel/process.c	2011-03-14 21:20:32.000000000 -0400
@@ -367,14 +367,13 @@ asmlinkage int sys_fork(struct pt_regs *
 }
 
 asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp,
-			 unsigned long parent_tidptr,
-			 unsigned long child_tidptr, struct pt_regs *regs)
+		void __user *parent_tidptr, void __user *child_tidptr,
+		struct pt_regs *regs)
 {
 	if (!newsp)
 		newsp = regs->sp;
-	return do_fork(clone_flags, newsp, regs, 0,
-		       (int __user *)parent_tidptr,
-		       (int __user *)child_tidptr);
+	return do_fork(clone_flags, newsp, regs, 0, parent_tidptr,
+			child_tidptr);
 }
 
 asmlinkage int sys_vfork(struct pt_regs *regs)
diff -druNp linux-libre-2.6.37-gnu1/arch/avr32/kernel/time.c linux-libre-2.6.38-gnu1/arch/avr32/kernel/time.c
--- linux-libre-2.6.37-gnu1/arch/avr32/kernel/time.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/avr32/kernel/time.c	2011-03-14 21:20:32.000000000 -0400
@@ -35,7 +35,6 @@ static struct clocksource counter = {
 	.rating		= 50,
 	.read		= read_cycle_count,
 	.mask		= CLOCKSOURCE_MASK(32),
-	.shift		= 16,
 	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
@@ -123,9 +122,7 @@ void __init time_init(void)
 
 	/* figure rate for counter */
 	counter_hz = clk_get_rate(boot_cpu_data.clk);
-	counter.mult = clocksource_hz2mult(counter_hz, counter.shift);
-
-	ret = clocksource_register(&counter);
+	ret = clocksource_register_hz(&counter, counter_hz);
 	if (ret)
 		pr_debug("timer: could not register clocksource: %d\n", ret);
 
diff -druNp linux-libre-2.6.37-gnu1/arch/avr32/mach-at32ap/pm.c linux-libre-2.6.38-gnu1/arch/avr32/mach-at32ap/pm.c
--- linux-libre-2.6.37-gnu1/arch/avr32/mach-at32ap/pm.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/avr32/mach-at32ap/pm.c	2011-03-14 21:20:32.000000000 -0400
@@ -176,7 +176,7 @@ out:
 	return 0;
 }
 
-static struct platform_suspend_ops avr32_pm_ops = {
+static const struct platform_suspend_ops avr32_pm_ops = {
 	.valid	= avr32_pm_valid_state,
 	.enter	= avr32_pm_enter,
 };
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/boot/Makefile linux-libre-2.6.38-gnu1/arch/blackfin/boot/Makefile
--- linux-libre-2.6.37-gnu1/arch/blackfin/boot/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/boot/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -17,7 +17,7 @@ UIMAGE_OPTS-$(CONFIG_ROMKERNEL) += -a $(
 
 quiet_cmd_uimage = UIMAGE  $@
       cmd_uimage = $(CONFIG_SHELL) $(MKIMAGE) -A $(ARCH) -O linux -T kernel \
-                   -C $(2) -n '$(MACHINE)-$(KERNELRELEASE)' \
+                   -C $(2) -n '$(CPU_REV)-$(KERNELRELEASE)' \
                    -e $(shell $(NM) vmlinux | awk '$$NF == "__start" {print $$1}') \
                    $(UIMAGE_OPTS-y) -d $< $@
 
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/configs/BF518F-EZBRD_defconfig linux-libre-2.6.38-gnu1/arch/blackfin/configs/BF518F-EZBRD_defconfig
--- linux-libre-2.6.37-gnu1/arch/blackfin/configs/BF518F-EZBRD_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/configs/BF518F-EZBRD_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@ CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_SYSCTL_SYSCALL is not set
 # CONFIG_ELF_CORE is not set
 # CONFIG_FUTEX is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/configs/BF526-EZBRD_defconfig linux-libre-2.6.38-gnu1/arch/blackfin/configs/BF526-EZBRD_defconfig
--- linux-libre-2.6.37-gnu1/arch/blackfin/configs/BF526-EZBRD_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/configs/BF526-EZBRD_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@ CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_SYSCTL_SYSCALL is not set
 # CONFIG_ELF_CORE is not set
 # CONFIG_FUTEX is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/configs/BF527-AD7160-EVAL_defconfig linux-libre-2.6.38-gnu1/arch/blackfin/configs/BF527-AD7160-EVAL_defconfig
--- linux-libre-2.6.37-gnu1/arch/blackfin/configs/BF527-AD7160-EVAL_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/configs/BF527-AD7160-EVAL_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@ CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_ELF_CORE is not set
 # CONFIG_AIO is not set
 CONFIG_SLAB=y
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/configs/BF527-EZKIT_defconfig linux-libre-2.6.38-gnu1/arch/blackfin/configs/BF527-EZKIT_defconfig
--- linux-libre-2.6.37-gnu1/arch/blackfin/configs/BF527-EZKIT_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/configs/BF527-EZKIT_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@ CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_SYSCTL_SYSCALL is not set
 # CONFIG_ELF_CORE is not set
 # CONFIG_FUTEX is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/configs/BF527-EZKIT-V2_defconfig linux-libre-2.6.38-gnu1/arch/blackfin/configs/BF527-EZKIT-V2_defconfig
--- linux-libre-2.6.37-gnu1/arch/blackfin/configs/BF527-EZKIT-V2_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/configs/BF527-EZKIT-V2_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@ CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_SYSCTL_SYSCALL is not set
 # CONFIG_ELF_CORE is not set
 # CONFIG_FUTEX is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/configs/BF527-TLL6527M_defconfig linux-libre-2.6.38-gnu1/arch/blackfin/configs/BF527-TLL6527M_defconfig
--- linux-libre-2.6.37-gnu1/arch/blackfin/configs/BF527-TLL6527M_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/configs/BF527-TLL6527M_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -6,7 +6,7 @@ CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_SYSCTL_SYSCALL is not set
 # CONFIG_ELF_CORE is not set
 # CONFIG_FUTEX is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/configs/BF533-EZKIT_defconfig linux-libre-2.6.38-gnu1/arch/blackfin/configs/BF533-EZKIT_defconfig
--- linux-libre-2.6.37-gnu1/arch/blackfin/configs/BF533-EZKIT_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/configs/BF533-EZKIT_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@ CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_SYSCTL_SYSCALL is not set
 # CONFIG_ELF_CORE is not set
 # CONFIG_FUTEX is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/configs/BF533-STAMP_defconfig linux-libre-2.6.38-gnu1/arch/blackfin/configs/BF533-STAMP_defconfig
--- linux-libre-2.6.37-gnu1/arch/blackfin/configs/BF533-STAMP_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/configs/BF533-STAMP_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@ CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_SYSCTL_SYSCALL is not set
 # CONFIG_ELF_CORE is not set
 # CONFIG_FUTEX is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/configs/BF537-STAMP_defconfig linux-libre-2.6.38-gnu1/arch/blackfin/configs/BF537-STAMP_defconfig
--- linux-libre-2.6.37-gnu1/arch/blackfin/configs/BF537-STAMP_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/configs/BF537-STAMP_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@ CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_SYSCTL_SYSCALL is not set
 # CONFIG_ELF_CORE is not set
 # CONFIG_FUTEX is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/configs/BF538-EZKIT_defconfig linux-libre-2.6.38-gnu1/arch/blackfin/configs/BF538-EZKIT_defconfig
--- linux-libre-2.6.37-gnu1/arch/blackfin/configs/BF538-EZKIT_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/configs/BF538-EZKIT_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@ CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_SYSCTL_SYSCALL is not set
 # CONFIG_ELF_CORE is not set
 # CONFIG_FUTEX is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/configs/BF548-EZKIT_defconfig linux-libre-2.6.38-gnu1/arch/blackfin/configs/BF548-EZKIT_defconfig
--- linux-libre-2.6.37-gnu1/arch/blackfin/configs/BF548-EZKIT_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/configs/BF548-EZKIT_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@ CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_SYSCTL_SYSCALL is not set
 # CONFIG_ELF_CORE is not set
 # CONFIG_FUTEX is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/configs/BF561-ACVILON_defconfig linux-libre-2.6.38-gnu1/arch/blackfin/configs/BF561-ACVILON_defconfig
--- linux-libre-2.6.37-gnu1/arch/blackfin/configs/BF561-ACVILON_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/configs/BF561-ACVILON_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@ CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_SYSFS_DEPRECATED_V2=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_SYSCTL_SYSCALL is not set
 # CONFIG_ELF_CORE is not set
 # CONFIG_FUTEX is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/configs/BF561-EZKIT_defconfig linux-libre-2.6.38-gnu1/arch/blackfin/configs/BF561-EZKIT_defconfig
--- linux-libre-2.6.37-gnu1/arch/blackfin/configs/BF561-EZKIT_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/configs/BF561-EZKIT_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@ CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_SYSCTL_SYSCALL is not set
 # CONFIG_ELF_CORE is not set
 # CONFIG_FUTEX is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/configs/BF561-EZKIT-SMP_defconfig linux-libre-2.6.38-gnu1/arch/blackfin/configs/BF561-EZKIT-SMP_defconfig
--- linux-libre-2.6.37-gnu1/arch/blackfin/configs/BF561-EZKIT-SMP_defconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/configs/BF561-EZKIT-SMP_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,113 @@
+CONFIG_EXPERIMENTAL=y
+CONFIG_SYSVIPC=y
+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
+# CONFIG_FUTEX is not set
+# CONFIG_SIGNALFD is not set
+# CONFIG_TIMERFD is not set
+# CONFIG_EVENTFD is not set
+# CONFIG_AIO is not set
+CONFIG_SLAB=y
+CONFIG_MMAP_ALLOW_UNINITIALIZED=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_PREEMPT_VOLUNTARY=y
+CONFIG_BF561=y
+CONFIG_SMP=y
+CONFIG_IRQ_TIMER0=10
+CONFIG_CLKIN_HZ=30000000
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_NOMMU_INITIAL_TRIM_EXCESS=0
+CONFIG_BFIN_GPTIMERS=m
+CONFIG_C_CDPRIO=y
+CONFIG_BANK_3=0xAAC2
+CONFIG_BINFMT_FLAT=y
+CONFIG_BINFMT_ZFLAT=y
+CONFIG_PM=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_PNP=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_IRDA=m
+CONFIG_IRLAN=m
+CONFIG_IRCOMM=m
+CONFIG_IRDA_CACHE_LAST_LSAP=y
+CONFIG_IRTTY_SIR=m
+# CONFIG_WIRELESS is not set
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+# CONFIG_FW_LOADER is not set
+CONFIG_MTD=y
+CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_CHAR=m
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_CFI=m
+CONFIG_MTD_CFI_AMDSTD=m
+CONFIG_MTD_RAM=y
+CONFIG_MTD_ROM=m
+CONFIG_MTD_PHYSMAP=m
+CONFIG_BLK_DEV_RAM=y
+CONFIG_NETDEVICES=y
+CONFIG_NET_ETHERNET=y
+CONFIG_SMC91X=y
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+# CONFIG_WLAN is not set
+CONFIG_INPUT=m
+# CONFIG_INPUT_MOUSEDEV is not set
+CONFIG_INPUT_EVDEV=m
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_SERIO is not set
+# CONFIG_VT is not set
+# CONFIG_DEVKMEM is not set
+CONFIG_BFIN_JTAG_COMM=m
+CONFIG_SERIAL_BFIN=y
+CONFIG_SERIAL_BFIN_CONSOLE=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_HW_RANDOM is not set
+CONFIG_SPI=y
+CONFIG_SPI_BFIN=y
+CONFIG_GPIOLIB=y
+CONFIG_GPIO_SYSFS=y
+# CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_BFIN_WDT=y
+# CONFIG_USB_SUPPORT is not set
+# CONFIG_DNOTIFY is not set
+CONFIG_JFFS2_FS=m
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3=y
+CONFIG_SMB_FS=m
+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
+CONFIG_EXACT_HWERR=y
+CONFIG_DEBUG_DOUBLEFAULT=y
+CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_CPLB_INFO=y
+CONFIG_CRYPTO=y
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/configs/BlackStamp_defconfig linux-libre-2.6.38-gnu1/arch/blackfin/configs/BlackStamp_defconfig
--- linux-libre-2.6.37-gnu1/arch/blackfin/configs/BlackStamp_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/configs/BlackStamp_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -6,7 +6,7 @@ CONFIG_LOG_BUF_SHIFT=14
 CONFIG_SYSFS_DEPRECATED_V2=y
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_SYSCTL_SYSCALL is not set
 # CONFIG_ELF_CORE is not set
 # CONFIG_FUTEX is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/configs/CM-BF527_defconfig linux-libre-2.6.38-gnu1/arch/blackfin/configs/CM-BF527_defconfig
--- linux-libre-2.6.37-gnu1/arch/blackfin/configs/CM-BF527_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/configs/CM-BF527_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -8,7 +8,7 @@ CONFIG_BLK_DEV_INITRD=y
 # CONFIG_RD_GZIP is not set
 CONFIG_RD_LZMA=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_SYSCTL_SYSCALL is not set
 # CONFIG_ELF_CORE is not set
 # CONFIG_FUTEX is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/configs/CM-BF533_defconfig linux-libre-2.6.38-gnu1/arch/blackfin/configs/CM-BF533_defconfig
--- linux-libre-2.6.37-gnu1/arch/blackfin/configs/CM-BF533_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/configs/CM-BF533_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -7,7 +7,7 @@ CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_RD_GZIP is not set
 CONFIG_RD_LZMA=y
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_UID16 is not set
 # CONFIG_SYSCTL_SYSCALL is not set
 # CONFIG_ELF_CORE is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/configs/CM-BF537E_defconfig linux-libre-2.6.38-gnu1/arch/blackfin/configs/CM-BF537E_defconfig
--- linux-libre-2.6.37-gnu1/arch/blackfin/configs/CM-BF537E_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/configs/CM-BF537E_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -8,7 +8,7 @@ CONFIG_BLK_DEV_INITRD=y
 # CONFIG_RD_GZIP is not set
 CONFIG_RD_LZMA=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_UID16 is not set
 # CONFIG_SYSCTL_SYSCALL is not set
 # CONFIG_ELF_CORE is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/configs/CM-BF537U_defconfig linux-libre-2.6.38-gnu1/arch/blackfin/configs/CM-BF537U_defconfig
--- linux-libre-2.6.37-gnu1/arch/blackfin/configs/CM-BF537U_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/configs/CM-BF537U_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -8,7 +8,7 @@ CONFIG_BLK_DEV_INITRD=y
 # CONFIG_RD_GZIP is not set
 CONFIG_RD_LZMA=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_UID16 is not set
 # CONFIG_SYSCTL_SYSCALL is not set
 # CONFIG_ELF_CORE is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/configs/CM-BF548_defconfig linux-libre-2.6.38-gnu1/arch/blackfin/configs/CM-BF548_defconfig
--- linux-libre-2.6.37-gnu1/arch/blackfin/configs/CM-BF548_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/configs/CM-BF548_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -8,7 +8,7 @@ CONFIG_BLK_DEV_INITRD=y
 # CONFIG_RD_GZIP is not set
 CONFIG_RD_LZMA=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_UID16 is not set
 # CONFIG_SYSCTL_SYSCALL is not set
 # CONFIG_ELF_CORE is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/configs/CM-BF561_defconfig linux-libre-2.6.38-gnu1/arch/blackfin/configs/CM-BF561_defconfig
--- linux-libre-2.6.37-gnu1/arch/blackfin/configs/CM-BF561_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/configs/CM-BF561_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -8,7 +8,7 @@ CONFIG_BLK_DEV_INITRD=y
 # CONFIG_RD_GZIP is not set
 CONFIG_RD_LZMA=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_UID16 is not set
 # CONFIG_SYSCTL_SYSCALL is not set
 # CONFIG_ELF_CORE is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/configs/DNP5370_defconfig linux-libre-2.6.38-gnu1/arch/blackfin/configs/DNP5370_defconfig
--- linux-libre-2.6.37-gnu1/arch/blackfin/configs/DNP5370_defconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/configs/DNP5370_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,121 @@
+CONFIG_EXPERIMENTAL=y
+CONFIG_LOCALVERSION="DNP5370"
+CONFIG_SYSVIPC=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_EXPERT=y
+CONFIG_SLOB=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_IOSCHED_CFQ is not set
+CONFIG_BF537=y
+CONFIG_BF_REV_0_3=y
+CONFIG_DNP5370=y
+CONFIG_IRQ_ERROR=7
+# CONFIG_CYCLES_CLOCKSOURCE is not set
+CONFIG_C_CDPRIO=y
+CONFIG_C_AMBEN_B0_B1_B2=y
+CONFIG_PM=y
+# CONFIG_SUSPEND is not set
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_RARP=y
+CONFIG_SYN_COOKIES=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_LLC2=y
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_MTD=y
+CONFIG_MTD_DEBUG=y
+CONFIG_MTD_DEBUG_VERBOSE=1
+CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+CONFIG_NFTL=y
+CONFIG_NFTL_RW=y
+CONFIG_MTD_CFI=y
+CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_MTD_ROM=y
+CONFIG_MTD_ABSENT=y
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_UCLINUX=y
+CONFIG_MTD_PLATRAM=y
+CONFIG_MTD_DATAFLASH=y
+CONFIG_MTD_BLOCK2MTD=y
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_PLATFORM=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+# CONFIG_MISC_DEVICES is not set
+CONFIG_NETDEVICES=y
+CONFIG_DAVICOM_PHY=y
+CONFIG_NET_ETHERNET=y
+CONFIG_BFIN_MAC=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_BFIN_DMA_INTERFACE is not set
+# CONFIG_VT is not set
+# CONFIG_DEVKMEM is not set
+CONFIG_BFIN_JTAG_COMM=y
+CONFIG_BFIN_JTAG_COMM_CONSOLE=y
+CONFIG_SERIAL_BFIN=y
+CONFIG_SERIAL_BFIN_CONSOLE=y
+CONFIG_SERIAL_BFIN_UART0=y
+CONFIG_LEGACY_PTY_COUNT=64
+# CONFIG_HW_RANDOM is not set
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_BLACKFIN_TWI=y
+CONFIG_SPI=y
+CONFIG_SPI_BFIN=y
+CONFIG_SPI_SPIDEV=y
+CONFIG_GPIOLIB=y
+CONFIG_GPIO_SYSFS=y
+CONFIG_SENSORS_LM75=y
+# CONFIG_USB_SUPPORT is not set
+CONFIG_MMC=y
+CONFIG_MMC_SPI=y
+CONFIG_DMADEVICES=y
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+# CONFIG_DNOTIFY is not set
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=850
+CONFIG_JFFS2_FS=y
+CONFIG_CRAMFS=y
+CONFIG_ROMFS_FS=y
+CONFIG_ROMFS_BACKED_BY_BOTH=y
+# CONFIG_NETWORK_FILESYSTEMS is not set
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_850=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_DEBUG_SHIRQ=y
+CONFIG_DETECT_HUNG_TASK=y
+CONFIG_DEBUG_OBJECTS=y
+CONFIG_DEBUG_LOCK_ALLOC=y
+CONFIG_DEBUG_KOBJECT=y
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_VM=y
+CONFIG_DEBUG_MEMORY_INIT=y
+CONFIG_DEBUG_LIST=y
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_PAGE_POISONING=y
+# CONFIG_FTRACE is not set
+CONFIG_DEBUG_DOUBLEFAULT=y
+CONFIG_CPLB_INFO=y
+CONFIG_CRC_CCITT=y
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/configs/H8606_defconfig linux-libre-2.6.38-gnu1/arch/blackfin/configs/H8606_defconfig
--- linux-libre-2.6.37-gnu1/arch/blackfin/configs/H8606_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/configs/H8606_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -2,7 +2,7 @@ CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_SYSCTL_SYSCALL is not set
 # CONFIG_ELF_CORE is not set
 # CONFIG_FUTEX is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/configs/IP0X_defconfig linux-libre-2.6.38-gnu1/arch/blackfin/configs/IP0X_defconfig
--- linux-libre-2.6.37-gnu1/arch/blackfin/configs/IP0X_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/configs/IP0X_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -3,7 +3,7 @@ CONFIG_SYSVIPC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_SYSCTL_SYSCALL is not set
 # CONFIG_HOTPLUG is not set
 # CONFIG_ELF_CORE is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/configs/PNAV-10_defconfig linux-libre-2.6.38-gnu1/arch/blackfin/configs/PNAV-10_defconfig
--- linux-libre-2.6.37-gnu1/arch/blackfin/configs/PNAV-10_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/configs/PNAV-10_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -2,7 +2,7 @@ CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_SYSCTL_SYSCALL is not set
 # CONFIG_ELF_CORE is not set
 # CONFIG_FUTEX is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/configs/SRV1_defconfig linux-libre-2.6.38-gnu1/arch/blackfin/configs/SRV1_defconfig
--- linux-libre-2.6.37-gnu1/arch/blackfin/configs/SRV1_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/configs/SRV1_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -3,7 +3,7 @@ CONFIG_SYSVIPC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_SYSCTL_SYSCALL is not set
 CONFIG_KALLSYMS_ALL=y
 # CONFIG_ELF_CORE is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/configs/TCM-BF518_defconfig linux-libre-2.6.38-gnu1/arch/blackfin/configs/TCM-BF518_defconfig
--- linux-libre-2.6.37-gnu1/arch/blackfin/configs/TCM-BF518_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/configs/TCM-BF518_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -7,7 +7,7 @@ CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_RD_GZIP is not set
 CONFIG_RD_LZMA=y
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_SYSCTL_SYSCALL is not set
 # CONFIG_ELF_CORE is not set
 # CONFIG_FUTEX is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/configs/TCM-BF537_defconfig linux-libre-2.6.38-gnu1/arch/blackfin/configs/TCM-BF537_defconfig
--- linux-libre-2.6.37-gnu1/arch/blackfin/configs/TCM-BF537_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/configs/TCM-BF537_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -8,7 +8,7 @@ CONFIG_BLK_DEV_INITRD=y
 # CONFIG_RD_GZIP is not set
 CONFIG_RD_LZMA=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_UID16 is not set
 # CONFIG_SYSCTL_SYSCALL is not set
 # CONFIG_ELF_CORE is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/include/asm/bfin_dma.h linux-libre-2.6.38-gnu1/arch/blackfin/include/asm/bfin_dma.h
--- linux-libre-2.6.37-gnu1/arch/blackfin/include/asm/bfin_dma.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/include/asm/bfin_dma.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,91 @@
+/*
+ * bfin_dma.h - Blackfin DMA defines/structures/etc...
+ *
+ * Copyright 2004-2010 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#ifndef __ASM_BFIN_DMA_H__
+#define __ASM_BFIN_DMA_H__
+
+#include <linux/types.h>
+
+/* DMA_CONFIG Masks */
+#define DMAEN			0x0001	/* DMA Channel Enable */
+#define WNR				0x0002	/* Channel Direction (W/R*) */
+#define WDSIZE_8		0x0000	/* Transfer Word Size = 8 */
+#define WDSIZE_16		0x0004	/* Transfer Word Size = 16 */
+#define WDSIZE_32		0x0008	/* Transfer Word Size = 32 */
+#define DMA2D			0x0010	/* DMA Mode (2D/1D*) */
+#define RESTART			0x0020	/* DMA Buffer Clear */
+#define DI_SEL			0x0040	/* Data Interrupt Timing Select */
+#define DI_EN			0x0080	/* Data Interrupt Enable */
+#define NDSIZE_0		0x0000	/* Next Descriptor Size = 0 (Stop/Autobuffer) */
+#define NDSIZE_1		0x0100	/* Next Descriptor Size = 1 */
+#define NDSIZE_2		0x0200	/* Next Descriptor Size = 2 */
+#define NDSIZE_3		0x0300	/* Next Descriptor Size = 3 */
+#define NDSIZE_4		0x0400	/* Next Descriptor Size = 4 */
+#define NDSIZE_5		0x0500	/* Next Descriptor Size = 5 */
+#define NDSIZE_6		0x0600	/* Next Descriptor Size = 6 */
+#define NDSIZE_7		0x0700	/* Next Descriptor Size = 7 */
+#define NDSIZE_8		0x0800	/* Next Descriptor Size = 8 */
+#define NDSIZE_9		0x0900	/* Next Descriptor Size = 9 */
+#define NDSIZE			0x0f00	/* Next Descriptor Size */
+#define DMAFLOW			0x7000	/* Flow Control */
+#define DMAFLOW_STOP	0x0000	/* Stop Mode */
+#define DMAFLOW_AUTO	0x1000	/* Autobuffer Mode */
+#define DMAFLOW_ARRAY	0x4000	/* Descriptor Array Mode */
+#define DMAFLOW_SMALL	0x6000	/* Small Model Descriptor List Mode */
+#define DMAFLOW_LARGE	0x7000	/* Large Model Descriptor List Mode */
+
+/* DMA_IRQ_STATUS Masks */
+#define DMA_DONE		0x0001	/* DMA Completion Interrupt Status */
+#define DMA_ERR			0x0002	/* DMA Error Interrupt Status */
+#define DFETCH			0x0004	/* DMA Descriptor Fetch Indicator */
+#define DMA_RUN			0x0008	/* DMA Channel Running Indicator */
+
+/*
+ * All Blackfin system MMRs are padded to 32bits even if the register
+ * itself is only 16bits.  So use a helper macro to streamline this.
+ */
+#define __BFP(m) u16 m; u16 __pad_##m
+
+/*
+ * bfin dma registers layout
+ */
+struct bfin_dma_regs {
+	u32 next_desc_ptr;
+	u32 start_addr;
+	__BFP(config);
+	u32 __pad0;
+	__BFP(x_count);
+	__BFP(x_modify);
+	__BFP(y_count);
+	__BFP(y_modify);
+	u32 curr_desc_ptr;
+	u32 curr_addr;
+	__BFP(irq_status);
+	__BFP(peripheral_map);
+	__BFP(curr_x_count);
+	u32 __pad1;
+	__BFP(curr_y_count);
+	u32 __pad2;
+};
+
+/*
+ * bfin handshake mdma registers layout
+ */
+struct bfin_hmdma_regs {
+	__BFP(control);
+	__BFP(ecinit);
+	__BFP(bcinit);
+	__BFP(ecurgent);
+	__BFP(ecoverflow);
+	__BFP(ecount);
+	__BFP(bcount);
+};
+
+#undef __BFP
+
+#endif
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/include/asm/bfin_serial.h linux-libre-2.6.38-gnu1/arch/blackfin/include/asm/bfin_serial.h
--- linux-libre-2.6.37-gnu1/arch/blackfin/include/asm/bfin_serial.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/include/asm/bfin_serial.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,277 @@
+/*
+ * bfin_serial.h - Blackfin UART/Serial definitions
+ *
+ * Copyright 2006-2010 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#ifndef __BFIN_ASM_SERIAL_H__
+#define __BFIN_ASM_SERIAL_H__
+
+#include <linux/serial_core.h>
+#include <linux/spinlock.h>
+#include <mach/anomaly.h>
+#include <mach/bfin_serial.h>
+
+#if defined(CONFIG_BFIN_UART0_CTSRTS) || \
+    defined(CONFIG_BFIN_UART1_CTSRTS) || \
+    defined(CONFIG_BFIN_UART2_CTSRTS) || \
+    defined(CONFIG_BFIN_UART3_CTSRTS)
+# ifdef BFIN_UART_BF54X_STYLE
+#  define CONFIG_SERIAL_BFIN_HARD_CTSRTS
+# else
+#  define CONFIG_SERIAL_BFIN_CTSRTS
+# endif
+#endif
+
+struct circ_buf;
+struct timer_list;
+struct work_struct;
+
+struct bfin_serial_port {
+	struct uart_port port;
+	unsigned int old_status;
+	int status_irq;
+#ifndef BFIN_UART_BF54X_STYLE
+	unsigned int lsr;
+#endif
+#ifdef CONFIG_SERIAL_BFIN_DMA
+	int tx_done;
+	int tx_count;
+	struct circ_buf rx_dma_buf;
+	struct timer_list rx_dma_timer;
+	int rx_dma_nrows;
+	spinlock_t rx_lock;
+	unsigned int tx_dma_channel;
+	unsigned int rx_dma_channel;
+	struct work_struct tx_dma_workqueue;
+#elif ANOMALY_05000363
+	unsigned int anomaly_threshold;
+#endif
+#ifdef CONFIG_SERIAL_BFIN_HARD_CTSRTS
+	int scts;
+#endif
+#if defined(CONFIG_SERIAL_BFIN_CTSRTS) || \
+	defined(CONFIG_SERIAL_BFIN_HARD_CTSRTS)
+	int cts_pin;
+	int rts_pin;
+#endif
+};
+
+/* UART_LCR Masks */
+#define WLS(x)                   (((x)-5) & 0x03)  /* Word Length Select */
+#define STB                      0x04  /* Stop Bits */
+#define PEN                      0x08  /* Parity Enable */
+#define EPS                      0x10  /* Even Parity Select */
+#define STP                      0x20  /* Stick Parity */
+#define SB                       0x40  /* Set Break */
+#define DLAB                     0x80  /* Divisor Latch Access */
+
+/* UART_LSR Masks */
+#define DR                       0x01  /* Data Ready */
+#define OE                       0x02  /* Overrun Error */
+#define PE                       0x04  /* Parity Error */
+#define FE                       0x08  /* Framing Error */
+#define BI                       0x10  /* Break Interrupt */
+#define THRE                     0x20  /* THR Empty */
+#define TEMT                     0x40  /* TSR and UART_THR Empty */
+#define TFI                      0x80  /* Transmission Finished Indicator */
+
+/* UART_IER Masks */
+#define ERBFI                    0x01  /* Enable Receive Buffer Full Interrupt */
+#define ETBEI                    0x02  /* Enable Transmit Buffer Empty Interrupt */
+#define ELSI                     0x04  /* Enable RX Status Interrupt */
+#define EDSSI                    0x08  /* Enable Modem Status Interrupt */
+#define EDTPTI                   0x10  /* Enable DMA Transmit PIRQ Interrupt */
+#define ETFI                     0x20  /* Enable Transmission Finished Interrupt */
+#define ERFCI                    0x40  /* Enable Receive FIFO Count Interrupt */
+
+/* UART_MCR Masks */
+#define XOFF                     0x01  /* Transmitter Off */
+#define MRTS                     0x02  /* Manual Request To Send */
+#define RFIT                     0x04  /* Receive FIFO IRQ Threshold */
+#define RFRT                     0x08  /* Receive FIFO RTS Threshold */
+#define LOOP_ENA                 0x10  /* Loopback Mode Enable */
+#define FCPOL                    0x20  /* Flow Control Pin Polarity */
+#define ARTS                     0x40  /* Automatic Request To Send */
+#define ACTS                     0x80  /* Automatic Clear To Send */
+
+/* UART_MSR Masks */
+#define SCTS                     0x01  /* Sticky CTS */
+#define CTS                      0x10  /* Clear To Send */
+#define RFCS                     0x20  /* Receive FIFO Count Status */
+
+/* UART_GCTL Masks */
+#define UCEN                     0x01  /* Enable UARTx Clocks */
+#define IREN                     0x02  /* Enable IrDA Mode */
+#define TPOLC                    0x04  /* IrDA TX Polarity Change */
+#define RPOLC                    0x08  /* IrDA RX Polarity Change */
+#define FPE                      0x10  /* Force Parity Error On Transmit */
+#define FFE                      0x20  /* Force Framing Error On Transmit */
+
+#ifdef BFIN_UART_BF54X_STYLE
+# define OFFSET_DLL              0x00  /* Divisor Latch (Low-Byte)        */
+# define OFFSET_DLH              0x04  /* Divisor Latch (High-Byte)       */
+# define OFFSET_GCTL             0x08  /* Global Control Register         */
+# define OFFSET_LCR              0x0C  /* Line Control Register           */
+# define OFFSET_MCR              0x10  /* Modem Control Register          */
+# define OFFSET_LSR              0x14  /* Line Status Register            */
+# define OFFSET_MSR              0x18  /* Modem Status Register           */
+# define OFFSET_SCR              0x1C  /* SCR Scratch Register            */
+# define OFFSET_IER_SET          0x20  /* Set Interrupt Enable Register   */
+# define OFFSET_IER_CLEAR        0x24  /* Clear Interrupt Enable Register */
+# define OFFSET_THR              0x28  /* Transmit Holding register       */
+# define OFFSET_RBR              0x2C  /* Receive Buffer register         */
+#else /* BF533 style */
+# define OFFSET_THR              0x00  /* Transmit Holding register         */
+# define OFFSET_RBR              0x00  /* Receive Buffer register           */
+# define OFFSET_DLL              0x00  /* Divisor Latch (Low-Byte)          */
+# define OFFSET_DLH              0x04  /* Divisor Latch (High-Byte)         */
+# define OFFSET_IER              0x04  /* Interrupt Enable Register         */
+# define OFFSET_IIR              0x08  /* Interrupt Identification Register */
+# define OFFSET_LCR              0x0C  /* Line Control Register             */
+# define OFFSET_MCR              0x10  /* Modem Control Register            */
+# define OFFSET_LSR              0x14  /* Line Status Register              */
+# define OFFSET_MSR              0x18  /* Modem Status Register             */
+# define OFFSET_SCR              0x1C  /* SCR Scratch Register              */
+# define OFFSET_GCTL             0x24  /* Global Control Register           */
+/* code should not need IIR, so force build error if they use it */
+# undef OFFSET_IIR
+#endif
+
+/*
+ * All Blackfin system MMRs are padded to 32bits even if the register
+ * itself is only 16bits.  So use a helper macro to streamline this.
+ */
+#define __BFP(m) u16 m; u16 __pad_##m
+struct bfin_uart_regs {
+#ifdef BFIN_UART_BF54X_STYLE
+	__BFP(dll);
+	__BFP(dlh);
+	__BFP(gctl);
+	__BFP(lcr);
+	__BFP(mcr);
+	__BFP(lsr);
+	__BFP(msr);
+	__BFP(scr);
+	__BFP(ier_set);
+	__BFP(ier_clear);
+	__BFP(thr);
+	__BFP(rbr);
+#else
+	union {
+		u16 dll;
+		u16 thr;
+		const u16 rbr;
+	};
+	const u16 __pad0;
+	union {
+		u16 dlh;
+		u16 ier;
+	};
+	const u16 __pad1;
+	const __BFP(iir);
+	__BFP(lcr);
+	__BFP(mcr);
+	__BFP(lsr);
+	__BFP(msr);
+	__BFP(scr);
+	const u32 __pad2;
+	__BFP(gctl);
+#endif
+};
+#undef __BFP
+
+#ifndef port_membase
+# define port_membase(p) (((struct bfin_serial_port *)(p))->port.membase)
+#endif
+
+#define UART_GET_CHAR(p)      bfin_read16(port_membase(p) + OFFSET_RBR)
+#define UART_GET_DLL(p)       bfin_read16(port_membase(p) + OFFSET_DLL)
+#define UART_GET_DLH(p)       bfin_read16(port_membase(p) + OFFSET_DLH)
+#define UART_GET_GCTL(p)      bfin_read16(port_membase(p) + OFFSET_GCTL)
+#define UART_GET_LCR(p)       bfin_read16(port_membase(p) + OFFSET_LCR)
+#define UART_GET_MCR(p)       bfin_read16(port_membase(p) + OFFSET_MCR)
+#define UART_GET_MSR(p)       bfin_read16(port_membase(p) + OFFSET_MSR)
+
+#define UART_PUT_CHAR(p, v)   bfin_write16(port_membase(p) + OFFSET_THR, v)
+#define UART_PUT_DLL(p, v)    bfin_write16(port_membase(p) + OFFSET_DLL, v)
+#define UART_PUT_DLH(p, v)    bfin_write16(port_membase(p) + OFFSET_DLH, v)
+#define UART_PUT_GCTL(p, v)   bfin_write16(port_membase(p) + OFFSET_GCTL, v)
+#define UART_PUT_LCR(p, v)    bfin_write16(port_membase(p) + OFFSET_LCR, v)
+#define UART_PUT_MCR(p, v)    bfin_write16(port_membase(p) + OFFSET_MCR, v)
+
+#ifdef BFIN_UART_BF54X_STYLE
+
+#define UART_CLEAR_IER(p, v)  bfin_write16(port_membase(p) + OFFSET_IER_CLEAR, v)
+#define UART_GET_IER(p)       bfin_read16(port_membase(p) + OFFSET_IER_SET)
+#define UART_SET_IER(p, v)    bfin_write16(port_membase(p) + OFFSET_IER_SET, v)
+
+#define UART_CLEAR_DLAB(p)    /* MMRs not muxed on BF54x */
+#define UART_SET_DLAB(p)      /* MMRs not muxed on BF54x */
+
+#define UART_CLEAR_LSR(p)     bfin_write16(port_membase(p) + OFFSET_LSR, -1)
+#define UART_GET_LSR(p)       bfin_read16(port_membase(p) + OFFSET_LSR)
+#define UART_PUT_LSR(p, v)    bfin_write16(port_membase(p) + OFFSET_LSR, v)
+
+/* This handles hard CTS/RTS */
+#define BFIN_UART_CTSRTS_HARD
+#define UART_CLEAR_SCTS(p)      bfin_write16((port_membase(p) + OFFSET_MSR), SCTS)
+#define UART_GET_CTS(x)         (UART_GET_MSR(x) & CTS)
+#define UART_DISABLE_RTS(x)     UART_PUT_MCR(x, UART_GET_MCR(x) & ~(ARTS | MRTS))
+#define UART_ENABLE_RTS(x)      UART_PUT_MCR(x, UART_GET_MCR(x) | MRTS | ARTS)
+#define UART_ENABLE_INTS(x, v)  UART_SET_IER(x, v)
+#define UART_DISABLE_INTS(x)    UART_CLEAR_IER(x, 0xF)
+
+#else /* BF533 style */
+
+#define UART_CLEAR_IER(p, v)  UART_PUT_IER(p, UART_GET_IER(p) & ~(v))
+#define UART_GET_IER(p)       bfin_read16(port_membase(p) + OFFSET_IER)
+#define UART_PUT_IER(p, v)    bfin_write16(port_membase(p) + OFFSET_IER, v)
+#define UART_SET_IER(p, v)    UART_PUT_IER(p, UART_GET_IER(p) | (v))
+
+#define UART_CLEAR_DLAB(p)    do { UART_PUT_LCR(p, UART_GET_LCR(p) & ~DLAB); SSYNC(); } while (0)
+#define UART_SET_DLAB(p)      do { UART_PUT_LCR(p, UART_GET_LCR(p) | DLAB); SSYNC(); } while (0)
+
+#ifndef put_lsr_cache
+# define put_lsr_cache(p, v) (((struct bfin_serial_port *)(p))->lsr = (v))
+#endif
+#ifndef get_lsr_cache
+# define get_lsr_cache(p)    (((struct bfin_serial_port *)(p))->lsr)
+#endif
+
+/* The hardware clears the LSR bits upon read, so we need to cache
+ * some of the more fun bits in software so they don't get lost
+ * when checking the LSR in other code paths (TX).
+ */
+static inline void UART_CLEAR_LSR(void *p)
+{
+	put_lsr_cache(p, 0);
+	bfin_write16(port_membase(p) + OFFSET_LSR, -1);
+}
+static inline unsigned int UART_GET_LSR(void *p)
+{
+	unsigned int lsr = bfin_read16(port_membase(p) + OFFSET_LSR);
+	put_lsr_cache(p, get_lsr_cache(p) | (lsr & (BI|FE|PE|OE)));
+	return lsr | get_lsr_cache(p);
+}
+static inline void UART_PUT_LSR(void *p, uint16_t val)
+{
+	put_lsr_cache(p, get_lsr_cache(p) & ~val);
+}
+
+/* This handles soft CTS/RTS */
+#define UART_GET_CTS(x)        gpio_get_value((x)->cts_pin)
+#define UART_DISABLE_RTS(x)    gpio_set_value((x)->rts_pin, 1)
+#define UART_ENABLE_RTS(x)     gpio_set_value((x)->rts_pin, 0)
+#define UART_ENABLE_INTS(x, v) UART_PUT_IER(x, v)
+#define UART_DISABLE_INTS(x)   UART_PUT_IER(x, 0)
+
+#endif
+
+#ifndef BFIN_UART_TX_FIFO_SIZE
+# define BFIN_UART_TX_FIFO_SIZE 2
+#endif
+
+#endif /* __BFIN_ASM_SERIAL_H__ */
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/include/asm/bitops.h linux-libre-2.6.38-gnu1/arch/blackfin/include/asm/bitops.h
--- linux-libre-2.6.37-gnu1/arch/blackfin/include/asm/bitops.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/include/asm/bitops.h	2011-03-14 21:20:32.000000000 -0400
@@ -108,7 +108,9 @@ static inline int test_and_change_bit(in
 #define smp_mb__before_clear_bit()	barrier()
 #define smp_mb__after_clear_bit()	barrier()
 
+#define test_bit __skip_test_bit
 #include <asm-generic/bitops/non-atomic.h>
+#undef test_bit
 
 #endif /* CONFIG_SMP */
 
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/include/asm/cacheflush.h linux-libre-2.6.38-gnu1/arch/blackfin/include/asm/cacheflush.h
--- linux-libre-2.6.37-gnu1/arch/blackfin/include/asm/cacheflush.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/include/asm/cacheflush.h	2011-03-14 21:20:32.000000000 -0400
@@ -11,6 +11,9 @@
 
 #include <asm/blackfin.h>	/* for SSYNC() */
 #include <asm/sections.h>	/* for _ramend */
+#ifdef CONFIG_SMP
+#include <asm/smp.h>
+#endif
 
 extern void blackfin_icache_flush_range(unsigned long start_address, unsigned long end_address);
 extern void blackfin_dcache_flush_range(unsigned long start_address, unsigned long end_address);
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/include/asm/cache.h linux-libre-2.6.38-gnu1/arch/blackfin/include/asm/cache.h
--- linux-libre-2.6.37-gnu1/arch/blackfin/include/asm/cache.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/include/asm/cache.h	2011-03-14 21:20:32.000000000 -0400
@@ -7,6 +7,8 @@
 #ifndef __ARCH_BLACKFIN_CACHE_H
 #define __ARCH_BLACKFIN_CACHE_H
 
+#include <linux/linkage.h>	/* for asmlinkage */
+
 /*
  * Bytes per L1 cache line
  * Blackfin loads 32 bytes for cache
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/include/asm/dma.h linux-libre-2.6.38-gnu1/arch/blackfin/include/asm/dma.h
--- linux-libre-2.6.37-gnu1/arch/blackfin/include/asm/dma.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/include/asm/dma.h	2011-03-14 21:20:32.000000000 -0400
@@ -14,40 +14,7 @@
 #include <asm/blackfin.h>
 #include <asm/page.h>
 #include <asm-generic/dma.h>
-
-/* DMA_CONFIG Masks */
-#define DMAEN			0x0001	/* DMA Channel Enable */
-#define WNR				0x0002	/* Channel Direction (W/R*) */
-#define WDSIZE_8		0x0000	/* Transfer Word Size = 8 */
-#define WDSIZE_16		0x0004	/* Transfer Word Size = 16 */
-#define WDSIZE_32		0x0008	/* Transfer Word Size = 32 */
-#define DMA2D			0x0010	/* DMA Mode (2D/1D*) */
-#define RESTART			0x0020	/* DMA Buffer Clear */
-#define DI_SEL			0x0040	/* Data Interrupt Timing Select */
-#define DI_EN			0x0080	/* Data Interrupt Enable */
-#define NDSIZE_0		0x0000	/* Next Descriptor Size = 0 (Stop/Autobuffer) */
-#define NDSIZE_1		0x0100	/* Next Descriptor Size = 1 */
-#define NDSIZE_2		0x0200	/* Next Descriptor Size = 2 */
-#define NDSIZE_3		0x0300	/* Next Descriptor Size = 3 */
-#define NDSIZE_4		0x0400	/* Next Descriptor Size = 4 */
-#define NDSIZE_5		0x0500	/* Next Descriptor Size = 5 */
-#define NDSIZE_6		0x0600	/* Next Descriptor Size = 6 */
-#define NDSIZE_7		0x0700	/* Next Descriptor Size = 7 */
-#define NDSIZE_8		0x0800	/* Next Descriptor Size = 8 */
-#define NDSIZE_9		0x0900	/* Next Descriptor Size = 9 */
-#define NDSIZE			0x0f00	/* Next Descriptor Size */
-#define DMAFLOW			0x7000	/* Flow Control */
-#define DMAFLOW_STOP	0x0000	/* Stop Mode */
-#define DMAFLOW_AUTO	0x1000	/* Autobuffer Mode */
-#define DMAFLOW_ARRAY	0x4000	/* Descriptor Array Mode */
-#define DMAFLOW_SMALL	0x6000	/* Small Model Descriptor List Mode */
-#define DMAFLOW_LARGE	0x7000	/* Large Model Descriptor List Mode */
-
-/* DMA_IRQ_STATUS Masks */
-#define DMA_DONE		0x0001	/* DMA Completion Interrupt Status */
-#define DMA_ERR			0x0002	/* DMA Error Interrupt Status */
-#define DFETCH			0x0004	/* DMA Descriptor Fetch Indicator */
-#define DMA_RUN			0x0008	/* DMA Channel Running Indicator */
+#include <asm/bfin_dma.h>
 
 /*-------------------------
  * config reg bits value
@@ -149,7 +116,7 @@ void blackfin_dma_resume(void);
 *	DMA API's
 *******************************************************************************/
 extern struct dma_channel dma_ch[MAX_DMA_CHANNELS];
-extern struct dma_register *dma_io_base_addr[MAX_DMA_CHANNELS];
+extern struct dma_register * const dma_io_base_addr[MAX_DMA_CHANNELS];
 extern int channel2irq(unsigned int channel);
 
 static inline void set_dma_start_addr(unsigned int channel, unsigned long addr)
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/include/asm/dpmc.h linux-libre-2.6.38-gnu1/arch/blackfin/include/asm/dpmc.h
--- linux-libre-2.6.37-gnu1/arch/blackfin/include/asm/dpmc.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/include/asm/dpmc.h	2011-03-14 21:20:32.000000000 -0400
@@ -9,6 +9,8 @@
 #ifndef _BLACKFIN_DPMC_H_
 #define _BLACKFIN_DPMC_H_
 
+#include <mach/pll.h>
+
 /* PLL_CTL Masks */
 #define DF			0x0001	/* 0: PLL = CLKIN, 1: PLL = CLKIN/2 */
 #define PLL_OFF			0x0002	/* PLL Not Powered */
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/include/asm/io.h linux-libre-2.6.38-gnu1/arch/blackfin/include/asm/io.h
--- linux-libre-2.6.37-gnu1/arch/blackfin/include/asm/io.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/include/asm/io.h	2011-03-14 21:20:32.000000000 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright 2004-2009 Analog Devices Inc.
+ * Copyright 2004-2010 Analog Devices Inc.
  *
  * Licensed under the GPL-2 or later.
  */
@@ -7,148 +7,48 @@
 #ifndef _BFIN_IO_H
 #define _BFIN_IO_H
 
-#ifdef __KERNEL__
-
-#ifndef __ASSEMBLY__
-#include <linux/types.h>
-#endif
 #include <linux/compiler.h>
+#include <linux/types.h>
+#include <asm/byteorder.h>
 
-/*
- * These are for ISA/PCI shared memory _only_ and should never be used
- * on any other type of memory, including Zorro memory. They are meant to
- * access the bus in the bus byte order which is little-endian!.
- *
- * readX/writeX() are used to access memory mapped devices. On some
- * architectures the memory mapped IO stuff needs to be accessed
- * differently. On the bfin architecture, we just read/write the
- * memory location directly.
- */
-#ifndef __ASSEMBLY__
-
-static inline unsigned char readb(const volatile void __iomem *addr)
-{
-	unsigned int val;
-	int tmp;
-
-	__asm__ __volatile__ (
-		"cli %1;"
-		"NOP; NOP; SSYNC;"
-		"%0 = b [%2] (z);"
-		"sti %1;"
-		: "=d"(val), "=d"(tmp)
-		: "a"(addr)
-	);
-
-	return (unsigned char) val;
-}
-
-static inline unsigned short readw(const volatile void __iomem *addr)
-{
-	unsigned int val;
-	int tmp;
-
-	__asm__ __volatile__ (
-		"cli %1;"
-		"NOP; NOP; SSYNC;"
-		"%0 = w [%2] (z);"
-		"sti %1;"
-		: "=d"(val), "=d"(tmp)
-		: "a"(addr)
-	);
-
-	return (unsigned short) val;
-}
-
-static inline unsigned int readl(const volatile void __iomem *addr)
-{
-	unsigned int val;
-	int tmp;
-
-	__asm__ __volatile__ (
-		"cli %1;"
-		"NOP; NOP; SSYNC;"
-		"%0 = [%2];"
-		"sti %1;"
-		: "=d"(val), "=d"(tmp)
-		: "a"(addr)
-	);
-
-	return val;
+#define DECLARE_BFIN_RAW_READX(size, type, asm, asm_sign) \
+static inline type __raw_read##size(const volatile void __iomem *addr) \
+{ \
+	unsigned int val; \
+	int tmp; \
+	__asm__ __volatile__ ( \
+		"cli %1;" \
+		"NOP; NOP; SSYNC;" \
+		"%0 = "#asm" [%2] "#asm_sign";" \
+		"sti %1;" \
+		: "=d"(val), "=d"(tmp) \
+		: "a"(addr) \
+	); \
+	return (type) val; \
 }
-
-#endif /*  __ASSEMBLY__ */
-
-#define writeb(b, addr) (void)((*(volatile unsigned char *) (addr)) = (b))
-#define writew(b, addr) (void)((*(volatile unsigned short *) (addr)) = (b))
-#define writel(b, addr) (void)((*(volatile unsigned int *) (addr)) = (b))
-
-#define __raw_readb readb
-#define __raw_readw readw
-#define __raw_readl readl
-#define __raw_writeb writeb
-#define __raw_writew writew
-#define __raw_writel writel
-#define memset_io(a, b, c)	memset((void *)(a), (b), (c))
-#define memcpy_fromio(a, b, c)	memcpy((a), (void *)(b), (c))
-#define memcpy_toio(a, b, c)	memcpy((void *)(a), (b), (c))
-
-/* Convert "I/O port addresses" to actual addresses.  i.e. ugly casts. */
-#define __io(port) ((void *)(unsigned long)(port))
-
-#define inb(port)    readb(__io(port))
-#define inw(port)    readw(__io(port))
-#define inl(port)    readl(__io(port))
-#define outb(x, port) writeb(x, __io(port))
-#define outw(x, port) writew(x, __io(port))
-#define outl(x, port) writel(x, __io(port))
-
-#define inb_p(port)    inb(__io(port))
-#define inw_p(port)    inw(__io(port))
-#define inl_p(port)    inl(__io(port))
-#define outb_p(x, port) outb(x, __io(port))
-#define outw_p(x, port) outw(x, __io(port))
-#define outl_p(x, port) outl(x, __io(port))
-
-#define ioread8_rep(a, d, c)	readsb(a, d, c)
-#define ioread16_rep(a, d, c)	readsw(a, d, c)
-#define ioread32_rep(a, d, c)	readsl(a, d, c)
-#define iowrite8_rep(a, s, c)	writesb(a, s, c)
-#define iowrite16_rep(a, s, c)	writesw(a, s, c)
-#define iowrite32_rep(a, s, c)	writesl(a, s, c)
-
-#define ioread8(x)			readb(x)
-#define ioread16(x)			readw(x)
-#define ioread32(x)			readl(x)
-#define iowrite8(val, x)		writeb(val, x)
-#define iowrite16(val, x)		writew(val, x)
-#define iowrite32(val, x)		writel(val, x)
-
-/**
- * I/O write barrier
- *
- * Ensure ordering of I/O space writes. This will make sure that writes
- * following the barrier will arrive after all previous writes.
- */
-#define mmiowb() do { SSYNC(); wmb(); } while (0)
-
-#define IO_SPACE_LIMIT 0xffffffff
-
-/* Values for nocacheflag and cmode */
-#define IOMAP_NOCACHE_SER		1
-
-#ifndef __ASSEMBLY__
+DECLARE_BFIN_RAW_READX(b, u8, b, (z))
+#define __raw_readb __raw_readb
+DECLARE_BFIN_RAW_READX(w, u16, w, (z))
+#define __raw_readw __raw_readw
+DECLARE_BFIN_RAW_READX(l, u32, , )
+#define __raw_readl __raw_readl
 
 extern void outsb(unsigned long port, const void *addr, unsigned long count);
 extern void outsw(unsigned long port, const void *addr, unsigned long count);
 extern void outsw_8(unsigned long port, const void *addr, unsigned long count);
 extern void outsl(unsigned long port, const void *addr, unsigned long count);
+#define outsb outsb
+#define outsw outsw
+#define outsl outsl
 
 extern void insb(unsigned long port, void *addr, unsigned long count);
 extern void insw(unsigned long port, void *addr, unsigned long count);
 extern void insw_8(unsigned long port, void *addr, unsigned long count);
 extern void insl(unsigned long port, void *addr, unsigned long count);
 extern void insl_16(unsigned long port, void *addr, unsigned long count);
+#define insb insb
+#define insw insw
+#define insl insl
 
 extern void dma_outsb(unsigned long port, const void *addr, unsigned short count);
 extern void dma_outsw(unsigned long port, const void *addr, unsigned short count);
@@ -158,108 +58,14 @@ extern void dma_insb(unsigned long port,
 extern void dma_insw(unsigned long port, void *addr, unsigned short count);
 extern void dma_insl(unsigned long port, void *addr, unsigned short count);
 
-static inline void readsl(const void __iomem *addr, void *buf, int len)
-{
-	insl((unsigned long)addr, buf, len);
-}
-
-static inline void readsw(const void __iomem *addr, void *buf, int len)
-{
-	insw((unsigned long)addr, buf, len);
-}
-
-static inline void readsb(const void __iomem *addr, void *buf, int len)
-{
-	insb((unsigned long)addr, buf, len);
-}
-
-static inline void writesl(const void __iomem *addr, const void *buf, int len)
-{
-	outsl((unsigned long)addr, buf, len);
-}
-
-static inline void writesw(const void __iomem *addr, const void *buf, int len)
-{
-	outsw((unsigned long)addr, buf, len);
-}
-
-static inline void writesb(const void __iomem *addr, const void *buf, int len)
-{
-	outsb((unsigned long)addr, buf, len);
-}
-
-/*
- * Map some physical address range into the kernel address space.
- */
-static inline void __iomem *__ioremap(unsigned long physaddr, unsigned long size,
-				int cacheflag)
-{
-	return (void __iomem *)physaddr;
-}
-
-/*
- * Unmap a ioremap()ed region again
- */
-static inline void iounmap(void *addr)
-{
-}
-
-/*
- * __iounmap unmaps nearly everything, so be careful
- * it doesn't free currently pointer/page tables anymore but it
- * wans't used anyway and might be added later.
- */
-static inline void __iounmap(void *addr, unsigned long size)
-{
-}
-
-/*
- * Set new cache mode for some kernel address space.
- * The caller must push data for that range itself, if such data may already
- * be in the cache.
+/**
+ * I/O write barrier
+ *
+ * Ensure ordering of I/O space writes. This will make sure that writes
+ * following the barrier will arrive after all previous writes.
  */
-static inline void kernel_set_cachemode(void *addr, unsigned long size,
-					int cmode)
-{
-}
-
-static inline void __iomem *ioremap(unsigned long physaddr, unsigned long size)
-{
-	return __ioremap(physaddr, size, IOMAP_NOCACHE_SER);
-}
-static inline void __iomem *ioremap_nocache(unsigned long physaddr,
-					    unsigned long size)
-{
-	return __ioremap(physaddr, size, IOMAP_NOCACHE_SER);
-}
+#define mmiowb() do { SSYNC(); wmb(); } while (0)
 
-extern void blkfin_inv_cache_all(void);
+#include <asm-generic/io.h>
 
 #endif
-
-#define	ioport_map(port, nr)		((void __iomem*)(port))
-#define	ioport_unmap(addr)
-
-/* Pages to physical address... */
-#define page_to_bus(page)       ((page - mem_map) << PAGE_SHIFT)
-
-#define phys_to_virt(vaddr)	((void *) (vaddr))
-#define virt_to_phys(vaddr)	((unsigned long) (vaddr))
-
-#define virt_to_bus virt_to_phys
-#define bus_to_virt phys_to_virt
-
-/*
- * Convert a physical pointer to a virtual kernel pointer for /dev/mem
- * access
- */
-#define xlate_dev_mem_ptr(p)	__va(p)
-
-/*
- * Convert a virtual cached pointer to an uncached pointer
- */
-#define xlate_dev_kmem_ptr(p)	p
-
-#endif				/* __KERNEL__ */
-
-#endif				/* _BFIN_IO_H */
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/include/asm/irqflags.h linux-libre-2.6.38-gnu1/arch/blackfin/include/asm/irqflags.h
--- linux-libre-2.6.37-gnu1/arch/blackfin/include/asm/irqflags.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/include/asm/irqflags.h	2011-03-14 21:20:32.000000000 -0400
@@ -13,9 +13,6 @@
 #ifdef CONFIG_SMP
 # include <asm/pda.h>
 # include <asm/processor.h>
-/* Forward decl needed due to cdef inter dependencies */
-static inline uint32_t __pure bfin_dspid(void);
-# define blackfin_core_id() (bfin_dspid() & 0xff)
 # define bfin_irq_flags cpu_pda[blackfin_core_id()].imask
 #else
 extern unsigned long bfin_irq_flags;
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/include/asm/processor.h linux-libre-2.6.38-gnu1/arch/blackfin/include/asm/processor.h
--- linux-libre-2.6.37-gnu1/arch/blackfin/include/asm/processor.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/include/asm/processor.h	2011-03-14 21:20:32.000000000 -0400
@@ -14,7 +14,7 @@
 #define current_text_addr() ({ __label__ _l; _l: &&_l;})
 
 #include <asm/ptrace.h>
-#include <asm/blackfin.h>
+#include <mach/blackfin.h>
 
 static inline unsigned long rdusp(void)
 {
@@ -134,6 +134,8 @@ static inline uint32_t __pure bfin_dspid
 	return bfin_read_DSPID();
 }
 
+#define blackfin_core_id() (bfin_dspid() & 0xff)
+
 static inline uint32_t __pure bfin_compiled_revid(void)
 {
 #if defined(CONFIG_BF_REV_0_0)
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/include/asm/spinlock.h linux-libre-2.6.38-gnu1/arch/blackfin/include/asm/spinlock.h
--- linux-libre-2.6.37-gnu1/arch/blackfin/include/asm/spinlock.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/include/asm/spinlock.h	2011-03-14 21:20:32.000000000 -0400
@@ -17,12 +17,12 @@ asmlinkage int __raw_spin_is_locked_asm(
 asmlinkage void __raw_spin_lock_asm(volatile int *ptr);
 asmlinkage int __raw_spin_trylock_asm(volatile int *ptr);
 asmlinkage void __raw_spin_unlock_asm(volatile int *ptr);
-asmlinkage void arch_read_lock_asm(volatile int *ptr);
-asmlinkage int arch_read_trylock_asm(volatile int *ptr);
-asmlinkage void arch_read_unlock_asm(volatile int *ptr);
-asmlinkage void arch_write_lock_asm(volatile int *ptr);
-asmlinkage int arch_write_trylock_asm(volatile int *ptr);
-asmlinkage void arch_write_unlock_asm(volatile int *ptr);
+asmlinkage void __raw_read_lock_asm(volatile int *ptr);
+asmlinkage int __raw_read_trylock_asm(volatile int *ptr);
+asmlinkage void __raw_read_unlock_asm(volatile int *ptr);
+asmlinkage void __raw_write_lock_asm(volatile int *ptr);
+asmlinkage int __raw_write_trylock_asm(volatile int *ptr);
+asmlinkage void __raw_write_unlock_asm(volatile int *ptr);
 
 static inline int arch_spin_is_locked(arch_spinlock_t *lock)
 {
@@ -64,32 +64,36 @@ static inline int arch_write_can_lock(ar
 
 static inline void arch_read_lock(arch_rwlock_t *rw)
 {
-	arch_read_lock_asm(&rw->lock);
+	__raw_read_lock_asm(&rw->lock);
 }
 
+#define arch_read_lock_flags(lock, flags) arch_read_lock(lock)
+
 static inline int arch_read_trylock(arch_rwlock_t *rw)
 {
-	return arch_read_trylock_asm(&rw->lock);
+	return __raw_read_trylock_asm(&rw->lock);
 }
 
 static inline void arch_read_unlock(arch_rwlock_t *rw)
 {
-	arch_read_unlock_asm(&rw->lock);
+	__raw_read_unlock_asm(&rw->lock);
 }
 
 static inline void arch_write_lock(arch_rwlock_t *rw)
 {
-	arch_write_lock_asm(&rw->lock);
+	__raw_write_lock_asm(&rw->lock);
 }
 
+#define arch_write_lock_flags(lock, flags) arch_write_lock(lock)
+
 static inline int arch_write_trylock(arch_rwlock_t *rw)
 {
-	return arch_write_trylock_asm(&rw->lock);
+	return __raw_write_trylock_asm(&rw->lock);
 }
 
 static inline void arch_write_unlock(arch_rwlock_t *rw)
 {
-	arch_write_unlock_asm(&rw->lock);
+	__raw_write_unlock_asm(&rw->lock);
 }
 
 #define arch_spin_relax(lock)  	cpu_relax()
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/include/mach-common/pll.h linux-libre-2.6.38-gnu1/arch/blackfin/include/mach-common/pll.h
--- linux-libre-2.6.37-gnu1/arch/blackfin/include/mach-common/pll.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/include/mach-common/pll.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2005-2010 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#ifndef _MACH_COMMON_PLL_H
+#define _MACH_COMMON_PLL_H
+
+#ifndef __ASSEMBLY__
+
+#include <asm/blackfin.h>
+#include <asm/irqflags.h>
+
+#ifndef bfin_iwr_restore
+static inline void
+bfin_iwr_restore(unsigned long iwr0, unsigned long iwr1, unsigned long iwr2)
+{
+#ifdef SIC_IWR
+	bfin_write_SIC_IWR(iwr0);
+#else
+	bfin_write_SIC_IWR0(iwr0);
+# ifdef SIC_IWR1
+	bfin_write_SIC_IWR1(iwr1);
+# endif
+# ifdef SIC_IWR2
+	bfin_write_SIC_IWR2(iwr2);
+# endif
+#endif
+}
+#endif
+
+#ifndef bfin_iwr_save
+static inline void
+bfin_iwr_save(unsigned long niwr0, unsigned long niwr1, unsigned long niwr2,
+              unsigned long *iwr0, unsigned long *iwr1, unsigned long *iwr2)
+{
+#ifdef SIC_IWR
+	*iwr0 = bfin_read_SIC_IWR();
+#else
+	*iwr0 = bfin_read_SIC_IWR0();
+# ifdef SIC_IWR1
+	*iwr1 = bfin_read_SIC_IWR1();
+# endif
+# ifdef SIC_IWR2
+	*iwr2 = bfin_read_SIC_IWR2();
+# endif
+#endif
+	bfin_iwr_restore(niwr0, niwr1, niwr2);
+}
+#endif
+
+static inline void _bfin_write_pll_relock(u32 addr, unsigned int val)
+{
+	unsigned long flags, iwr0, iwr1, iwr2;
+
+	if (val == bfin_read_PLL_CTL())
+		return;
+
+	flags = hard_local_irq_save();
+	/* Enable the PLL Wakeup bit in SIC IWR */
+	bfin_iwr_save(IWR_ENABLE(0), 0, 0, &iwr0, &iwr1, &iwr2);
+
+	bfin_write16(addr, val);
+	SSYNC();
+	asm("IDLE;");
+
+	bfin_iwr_restore(iwr0, iwr1, iwr2);
+	hard_local_irq_restore(flags);
+}
+
+/* Writing to PLL_CTL initiates a PLL relock sequence */
+static inline void bfin_write_PLL_CTL(unsigned int val)
+{
+	_bfin_write_pll_relock(PLL_CTL, val);
+}
+
+/* Writing to VR_CTL initiates a PLL relock sequence */
+static inline void bfin_write_VR_CTL(unsigned int val)
+{
+	_bfin_write_pll_relock(VR_CTL, val);
+}
+
+#endif
+
+#endif
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/include/mach-common/ports-a.h linux-libre-2.6.38-gnu1/arch/blackfin/include/mach-common/ports-a.h
--- linux-libre-2.6.37-gnu1/arch/blackfin/include/mach-common/ports-a.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/include/mach-common/ports-a.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,25 @@
+/*
+ * Port A Masks
+ */
+
+#ifndef __BFIN_PERIPHERAL_PORT_A__
+#define __BFIN_PERIPHERAL_PORT_A__
+
+#define PA0		(1 << 0)
+#define PA1		(1 << 1)
+#define PA2		(1 << 2)
+#define PA3		(1 << 3)
+#define PA4		(1 << 4)
+#define PA5		(1 << 5)
+#define PA6		(1 << 6)
+#define PA7		(1 << 7)
+#define PA8		(1 << 8)
+#define PA9		(1 << 9)
+#define PA10		(1 << 10)
+#define PA11		(1 << 11)
+#define PA12		(1 << 12)
+#define PA13		(1 << 13)
+#define PA14		(1 << 14)
+#define PA15		(1 << 15)
+
+#endif
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/include/mach-common/ports-b.h linux-libre-2.6.38-gnu1/arch/blackfin/include/mach-common/ports-b.h
--- linux-libre-2.6.37-gnu1/arch/blackfin/include/mach-common/ports-b.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/include/mach-common/ports-b.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,25 @@
+/*
+ * Port B Masks
+ */
+
+#ifndef __BFIN_PERIPHERAL_PORT_B__
+#define __BFIN_PERIPHERAL_PORT_B__
+
+#define PB0		(1 << 0)
+#define PB1		(1 << 1)
+#define PB2		(1 << 2)
+#define PB3		(1 << 3)
+#define PB4		(1 << 4)
+#define PB5		(1 << 5)
+#define PB6		(1 << 6)
+#define PB7		(1 << 7)
+#define PB8		(1 << 8)
+#define PB9		(1 << 9)
+#define PB10		(1 << 10)
+#define PB11		(1 << 11)
+#define PB12		(1 << 12)
+#define PB13		(1 << 13)
+#define PB14		(1 << 14)
+#define PB15		(1 << 15)
+
+#endif
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/include/mach-common/ports-c.h linux-libre-2.6.38-gnu1/arch/blackfin/include/mach-common/ports-c.h
--- linux-libre-2.6.37-gnu1/arch/blackfin/include/mach-common/ports-c.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/include/mach-common/ports-c.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,25 @@
+/*
+ * Port C Masks
+ */
+
+#ifndef __BFIN_PERIPHERAL_PORT_C__
+#define __BFIN_PERIPHERAL_PORT_C__
+
+#define PC0		(1 << 0)
+#define PC1		(1 << 1)
+#define PC2		(1 << 2)
+#define PC3		(1 << 3)
+#define PC4		(1 << 4)
+#define PC5		(1 << 5)
+#define PC6		(1 << 6)
+#define PC7		(1 << 7)
+#define PC8		(1 << 8)
+#define PC9		(1 << 9)
+#define PC10		(1 << 10)
+#define PC11		(1 << 11)
+#define PC12		(1 << 12)
+#define PC13		(1 << 13)
+#define PC14		(1 << 14)
+#define PC15		(1 << 15)
+
+#endif
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/include/mach-common/ports-d.h linux-libre-2.6.38-gnu1/arch/blackfin/include/mach-common/ports-d.h
--- linux-libre-2.6.37-gnu1/arch/blackfin/include/mach-common/ports-d.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/include/mach-common/ports-d.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,25 @@
+/*
+ * Port D Masks
+ */
+
+#ifndef __BFIN_PERIPHERAL_PORT_D__
+#define __BFIN_PERIPHERAL_PORT_D__
+
+#define PD0		(1 << 0)
+#define PD1		(1 << 1)
+#define PD2		(1 << 2)
+#define PD3		(1 << 3)
+#define PD4		(1 << 4)
+#define PD5		(1 << 5)
+#define PD6		(1 << 6)
+#define PD7		(1 << 7)
+#define PD8		(1 << 8)
+#define PD9		(1 << 9)
+#define PD10		(1 << 10)
+#define PD11		(1 << 11)
+#define PD12		(1 << 12)
+#define PD13		(1 << 13)
+#define PD14		(1 << 14)
+#define PD15		(1 << 15)
+
+#endif
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/include/mach-common/ports-e.h linux-libre-2.6.38-gnu1/arch/blackfin/include/mach-common/ports-e.h
--- linux-libre-2.6.37-gnu1/arch/blackfin/include/mach-common/ports-e.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/include/mach-common/ports-e.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,25 @@
+/*
+ * Port E Masks
+ */
+
+#ifndef __BFIN_PERIPHERAL_PORT_E__
+#define __BFIN_PERIPHERAL_PORT_E__
+
+#define PE0		(1 << 0)
+#define PE1		(1 << 1)
+#define PE2		(1 << 2)
+#define PE3		(1 << 3)
+#define PE4		(1 << 4)
+#define PE5		(1 << 5)
+#define PE6		(1 << 6)
+#define PE7		(1 << 7)
+#define PE8		(1 << 8)
+#define PE9		(1 << 9)
+#define PE10		(1 << 10)
+#define PE11		(1 << 11)
+#define PE12		(1 << 12)
+#define PE13		(1 << 13)
+#define PE14		(1 << 14)
+#define PE15		(1 << 15)
+
+#endif
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/include/mach-common/ports-f.h linux-libre-2.6.38-gnu1/arch/blackfin/include/mach-common/ports-f.h
--- linux-libre-2.6.37-gnu1/arch/blackfin/include/mach-common/ports-f.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/include/mach-common/ports-f.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,25 @@
+/*
+ * Port F Masks
+ */
+
+#ifndef __BFIN_PERIPHERAL_PORT_F__
+#define __BFIN_PERIPHERAL_PORT_F__
+
+#define PF0		(1 << 0)
+#define PF1		(1 << 1)
+#define PF2		(1 << 2)
+#define PF3		(1 << 3)
+#define PF4		(1 << 4)
+#define PF5		(1 << 5)
+#define PF6		(1 << 6)
+#define PF7		(1 << 7)
+#define PF8		(1 << 8)
+#define PF9		(1 << 9)
+#define PF10		(1 << 10)
+#define PF11		(1 << 11)
+#define PF12		(1 << 12)
+#define PF13		(1 << 13)
+#define PF14		(1 << 14)
+#define PF15		(1 << 15)
+
+#endif
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/include/mach-common/ports-g.h linux-libre-2.6.38-gnu1/arch/blackfin/include/mach-common/ports-g.h
--- linux-libre-2.6.37-gnu1/arch/blackfin/include/mach-common/ports-g.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/include/mach-common/ports-g.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,25 @@
+/*
+ * Port G Masks
+ */
+
+#ifndef __BFIN_PERIPHERAL_PORT_G__
+#define __BFIN_PERIPHERAL_PORT_G__
+
+#define PG0		(1 << 0)
+#define PG1		(1 << 1)
+#define PG2		(1 << 2)
+#define PG3		(1 << 3)
+#define PG4		(1 << 4)
+#define PG5		(1 << 5)
+#define PG6		(1 << 6)
+#define PG7		(1 << 7)
+#define PG8		(1 << 8)
+#define PG9		(1 << 9)
+#define PG10		(1 << 10)
+#define PG11		(1 << 11)
+#define PG12		(1 << 12)
+#define PG13		(1 << 13)
+#define PG14		(1 << 14)
+#define PG15		(1 << 15)
+
+#endif
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/include/mach-common/ports-h.h linux-libre-2.6.38-gnu1/arch/blackfin/include/mach-common/ports-h.h
--- linux-libre-2.6.37-gnu1/arch/blackfin/include/mach-common/ports-h.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/include/mach-common/ports-h.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,25 @@
+/*
+ * Port H Masks
+ */
+
+#ifndef __BFIN_PERIPHERAL_PORT_H__
+#define __BFIN_PERIPHERAL_PORT_H__
+
+#define PH0		(1 << 0)
+#define PH1		(1 << 1)
+#define PH2		(1 << 2)
+#define PH3		(1 << 3)
+#define PH4		(1 << 4)
+#define PH5		(1 << 5)
+#define PH6		(1 << 6)
+#define PH7		(1 << 7)
+#define PH8		(1 << 8)
+#define PH9		(1 << 9)
+#define PH10		(1 << 10)
+#define PH11		(1 << 11)
+#define PH12		(1 << 12)
+#define PH13		(1 << 13)
+#define PH14		(1 << 14)
+#define PH15		(1 << 15)
+
+#endif
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/include/mach-common/ports-i.h linux-libre-2.6.38-gnu1/arch/blackfin/include/mach-common/ports-i.h
--- linux-libre-2.6.37-gnu1/arch/blackfin/include/mach-common/ports-i.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/include/mach-common/ports-i.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,25 @@
+/*
+ * Port I Masks
+ */
+
+#ifndef __BFIN_PERIPHERAL_PORT_I__
+#define __BFIN_PERIPHERAL_PORT_I__
+
+#define PI0		(1 << 0)
+#define PI1		(1 << 1)
+#define PI2		(1 << 2)
+#define PI3		(1 << 3)
+#define PI4		(1 << 4)
+#define PI5		(1 << 5)
+#define PI6		(1 << 6)
+#define PI7		(1 << 7)
+#define PI8		(1 << 8)
+#define PI9		(1 << 9)
+#define PI10		(1 << 10)
+#define PI11		(1 << 11)
+#define PI12		(1 << 12)
+#define PI13		(1 << 13)
+#define PI14		(1 << 14)
+#define PI15		(1 << 15)
+
+#endif
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/include/mach-common/ports-j.h linux-libre-2.6.38-gnu1/arch/blackfin/include/mach-common/ports-j.h
--- linux-libre-2.6.37-gnu1/arch/blackfin/include/mach-common/ports-j.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/include/mach-common/ports-j.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,25 @@
+/*
+ * Port J Masks
+ */
+
+#ifndef __BFIN_PERIPHERAL_PORT_J__
+#define __BFIN_PERIPHERAL_PORT_J__
+
+#define PJ0		(1 << 0)
+#define PJ1		(1 << 1)
+#define PJ2		(1 << 2)
+#define PJ3		(1 << 3)
+#define PJ4		(1 << 4)
+#define PJ5		(1 << 5)
+#define PJ6		(1 << 6)
+#define PJ7		(1 << 7)
+#define PJ8		(1 << 8)
+#define PJ9		(1 << 9)
+#define PJ10		(1 << 10)
+#define PJ11		(1 << 11)
+#define PJ12		(1 << 12)
+#define PJ13		(1 << 13)
+#define PJ14		(1 << 14)
+#define PJ15		(1 << 15)
+
+#endif
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/Kconfig linux-libre-2.6.38-gnu1/arch/blackfin/Kconfig
--- linux-libre-2.6.37-gnu1/arch/blackfin/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -30,6 +30,9 @@ config BLACKFIN
 	select HAVE_KERNEL_LZO if RAMKERNEL
 	select HAVE_OPROFILE
 	select ARCH_WANT_OPTIONAL_GPIOLIB
+	select HAVE_GENERIC_HARDIRQS
+	select GENERIC_IRQ_PROBE
+	select IRQ_PER_CPU if SMP
 
 config GENERIC_CSUM
 	def_bool y
@@ -44,15 +47,6 @@ config ZONE_DMA
 config GENERIC_FIND_NEXT_BIT
 	def_bool y
 
-config GENERIC_HARDIRQS
-	def_bool y
-
-config GENERIC_IRQ_PROBE
-	def_bool y
-
-config GENERIC_HARDIRQS_NO__DO_IRQ
-	def_bool y
-
 config GENERIC_GPIO
 	def_bool y
 
@@ -254,11 +248,6 @@ config HOTPLUG_CPU
 	depends on SMP && HOTPLUG
 	default y
 
-config IRQ_PER_CPU
-	bool
-	depends on SMP
-	default y
-
 config HAVE_LEGACY_PER_CPU_AREA
 	def_bool y
 	depends on SMP
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/kernel/cplb-nompu/cplbinit.c linux-libre-2.6.38-gnu1/arch/blackfin/kernel/cplb-nompu/cplbinit.c
--- linux-libre-2.6.37-gnu1/arch/blackfin/kernel/cplb-nompu/cplbinit.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/kernel/cplb-nompu/cplbinit.c	2011-03-14 21:20:32.000000000 -0400
@@ -116,7 +116,7 @@ void __init generate_cplb_tables_all(voi
 	    ((_ramend - uncached_end) >= 1 * 1024 * 1024))
 		dcplb_bounds[i_d].eaddr = uncached_end;
 	else
-		dcplb_bounds[i_d].eaddr = uncached_end & ~(1 * 1024 * 1024);
+		dcplb_bounds[i_d].eaddr = uncached_end & ~(1 * 1024 * 1024 - 1);
 	dcplb_bounds[i_d++].data = SDRAM_DGENERIC;
 	/* DMA uncached region.  */
 	if (DMA_UNCACHED_REGION) {
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/kernel/kgdb.c linux-libre-2.6.38-gnu1/arch/blackfin/kernel/kgdb.c
--- linux-libre-2.6.37-gnu1/arch/blackfin/kernel/kgdb.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/kernel/kgdb.c	2011-03-14 21:20:32.000000000 -0400
@@ -345,6 +345,23 @@ void kgdb_roundup_cpu(int cpu, unsigned
 }
 #endif
 
+#ifdef CONFIG_IPIPE
+static unsigned long kgdb_arch_imask;
+#endif
+
+void kgdb_post_primary_code(struct pt_regs *regs, int e_vector, int err_code)
+{
+	if (kgdb_single_step)
+		preempt_enable();
+
+#ifdef CONFIG_IPIPE
+	if (kgdb_arch_imask) {
+		cpu_pda[raw_smp_processor_id()].ex_imask = kgdb_arch_imask;
+		kgdb_arch_imask = 0;
+	}
+#endif
+}
+
 int kgdb_arch_handle_exception(int vector, int signo,
 			       int err_code, char *remcom_in_buffer,
 			       char *remcom_out_buffer,
@@ -388,6 +405,12 @@ int kgdb_arch_handle_exception(int vecto
 			 * kgdb_single_step > 0 means in single step mode
 			 */
 			kgdb_single_step = i + 1;
+
+			preempt_disable();
+#ifdef CONFIG_IPIPE
+			kgdb_arch_imask = cpu_pda[raw_smp_processor_id()].ex_imask;
+			cpu_pda[raw_smp_processor_id()].ex_imask = 0;
+#endif
 		}
 
 		bfin_correct_hw_break();
@@ -448,6 +471,9 @@ void kgdb_arch_set_pc(struct pt_regs *re
 int kgdb_arch_init(void)
 {
 	kgdb_single_step = 0;
+#ifdef CONFIG_IPIPE
+	kgdb_arch_imask = 0;
+#endif
 
 	bfin_remove_all_hw_break();
 	return 0;
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/kernel/kgdb_test.c linux-libre-2.6.38-gnu1/arch/blackfin/kernel/kgdb_test.c
--- linux-libre-2.6.37-gnu1/arch/blackfin/kernel/kgdb_test.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/kernel/kgdb_test.c	2011-03-14 21:20:32.000000000 -0400
@@ -95,6 +95,10 @@ static int __init kgdbtest_init(void)
 {
 	struct proc_dir_entry *entry;
 
+#if L2_LENGTH
+	num2 = 0;
+#endif
+
 	entry = proc_create("kgdbtest", 0, NULL, &kgdb_test_proc_fops);
 	if (entry == NULL)
 		return -ENOMEM;
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/lib/outs.S linux-libre-2.6.38-gnu1/arch/blackfin/lib/outs.S
--- linux-libre-2.6.37-gnu1/arch/blackfin/lib/outs.S	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/lib/outs.S	2011-03-14 21:20:32.000000000 -0400
@@ -13,6 +13,8 @@
 .align 2
 
 ENTRY(_outsl)
+	CC = R2 == 0;
+	IF CC JUMP 1f;
 	P0 = R0;	/* P0 = port */
 	P1 = R1;	/* P1 = address */
 	P2 = R2;	/* P2 = count */
@@ -20,10 +22,12 @@ ENTRY(_outsl)
 	LSETUP( .Llong_loop_s, .Llong_loop_e) LC0 = P2;
 .Llong_loop_s: R0 = [P1++];
 .Llong_loop_e: [P0] = R0;
-	RTS;
+1:	RTS;
 ENDPROC(_outsl)
 
 ENTRY(_outsw)
+	CC = R2 == 0;
+	IF CC JUMP 1f;
 	P0 = R0;	/* P0 = port */
 	P1 = R1;	/* P1 = address */
 	P2 = R2;	/* P2 = count */
@@ -31,10 +35,12 @@ ENTRY(_outsw)
 	LSETUP( .Lword_loop_s, .Lword_loop_e) LC0 = P2;
 .Lword_loop_s: R0 = W[P1++];
 .Lword_loop_e: W[P0] = R0;
-	RTS;
+1:	RTS;
 ENDPROC(_outsw)
 
 ENTRY(_outsb)
+	CC = R2 == 0;
+	IF CC JUMP 1f;
 	P0 = R0;	/* P0 = port */
 	P1 = R1;	/* P1 = address */
 	P2 = R2;	/* P2 = count */
@@ -42,10 +48,12 @@ ENTRY(_outsb)
 	LSETUP( .Lbyte_loop_s, .Lbyte_loop_e) LC0 = P2;
 .Lbyte_loop_s: R0 = B[P1++];
 .Lbyte_loop_e: B[P0] = R0;
-	RTS;
+1:	RTS;
 ENDPROC(_outsb)
 
 ENTRY(_outsw_8)
+	CC = R2 == 0;
+	IF CC JUMP 1f;
 	P0 = R0;	/* P0 = port */
 	P1 = R1;	/* P1 = address */
 	P2 = R2;	/* P2 = count */
@@ -56,5 +64,5 @@ ENTRY(_outsw_8)
 		R0 = R0 << 8;
 		R0 = R0 + R1;
 .Lword8_loop_e: W[P0] = R0;
-	RTS;
+1:	RTS;
 ENDPROC(_outsw_8)
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf518/boards/ezbrd.c linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf518/boards/ezbrd.c
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf518/boards/ezbrd.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf518/boards/ezbrd.c	2011-03-14 21:20:32.000000000 -0400
@@ -104,24 +104,23 @@ static const unsigned short bfin_mac_per
 
 static struct bfin_phydev_platform_data bfin_phydev_data[] = {
 	{
-		.addr = 1,
-		.irq = IRQ_MAC_PHYINT,
-	},
-	{
-		.addr = 2,
-		.irq = IRQ_MAC_PHYINT,
-	},
-	{
+#if defined(CONFIG_NET_DSA_KSZ8893M) || defined(CONFIG_NET_DSA_KSZ8893M_MODULE)
 		.addr = 3,
+#else
+		.addr = 1,
+#endif
 		.irq = IRQ_MAC_PHYINT,
 	},
 };
 
 static struct bfin_mii_bus_platform_data bfin_mii_bus_data = {
-	.phydev_number = 3,
+	.phydev_number = 1,
 	.phydev_data = bfin_phydev_data,
 	.phy_mode = PHY_INTERFACE_MODE_MII,
 	.mac_peripherals = bfin_mac_peripherals,
+#if defined(CONFIG_NET_DSA_KSZ8893M) || defined(CONFIG_NET_DSA_KSZ8893M_MODULE)
+	.phy_mask = 0xfff7, /* Only probe the port phy connect to the on chip MAC */
+#endif
 };
 
 static struct platform_device bfin_mii_bus = {
@@ -453,7 +452,7 @@ static struct resource bfin_uart0_resour
 	},
 };
 
-unsigned short bfin_uart0_peripherals[] = {
+static unsigned short bfin_uart0_peripherals[] = {
 	P_UART0_TX, P_UART0_RX, 0
 };
 
@@ -496,7 +495,7 @@ static struct resource bfin_uart1_resour
 	},
 };
 
-unsigned short bfin_uart1_peripherals[] = {
+static unsigned short bfin_uart1_peripherals[] = {
 	P_UART1_TX, P_UART1_RX, 0
 };
 
@@ -636,9 +635,9 @@ static struct resource bfin_sport0_uart_
 	},
 };
 
-unsigned short bfin_sport0_peripherals[] = {
+static unsigned short bfin_sport0_peripherals[] = {
 	P_SPORT0_TFS, P_SPORT0_DTPRI, P_SPORT0_TSCLK, P_SPORT0_RFS,
-	P_SPORT0_DRPRI, P_SPORT0_RSCLK, P_SPORT0_DRSEC, P_SPORT0_DTSEC, 0
+	P_SPORT0_DRPRI, P_SPORT0_RSCLK, 0
 };
 
 static struct platform_device bfin_sport0_uart_device = {
@@ -670,9 +669,9 @@ static struct resource bfin_sport1_uart_
 	},
 };
 
-unsigned short bfin_sport1_peripherals[] = {
+static unsigned short bfin_sport1_peripherals[] = {
 	P_SPORT1_TFS, P_SPORT1_DTPRI, P_SPORT1_TSCLK, P_SPORT1_RFS,
-	P_SPORT1_DRPRI, P_SPORT1_RSCLK, P_SPORT1_DRSEC, P_SPORT1_DTSEC, 0
+	P_SPORT1_DRPRI, P_SPORT1_RSCLK, 0
 };
 
 static struct platform_device bfin_sport1_uart_device = {
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf518/boards/tcm-bf518.c linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf518/boards/tcm-bf518.c
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf518/boards/tcm-bf518.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf518/boards/tcm-bf518.c	2011-03-14 21:20:32.000000000 -0400
@@ -377,7 +377,7 @@ static struct resource bfin_uart0_resour
 	},
 };
 
-unsigned short bfin_uart0_peripherals[] = {
+static unsigned short bfin_uart0_peripherals[] = {
 	P_UART0_TX, P_UART0_RX, 0
 };
 
@@ -420,7 +420,7 @@ static struct resource bfin_uart1_resour
 	},
 };
 
-unsigned short bfin_uart1_peripherals[] = {
+static unsigned short bfin_uart1_peripherals[] = {
 	P_UART1_TX, P_UART1_RX, 0
 };
 
@@ -547,9 +547,9 @@ static struct resource bfin_sport0_uart_
 	},
 };
 
-unsigned short bfin_sport0_peripherals[] = {
+static unsigned short bfin_sport0_peripherals[] = {
 	P_SPORT0_TFS, P_SPORT0_DTPRI, P_SPORT0_TSCLK, P_SPORT0_RFS,
-	P_SPORT0_DRPRI, P_SPORT0_RSCLK, P_SPORT0_DRSEC, P_SPORT0_DTSEC, 0
+	P_SPORT0_DRPRI, P_SPORT0_RSCLK, 0
 };
 
 static struct platform_device bfin_sport0_uart_device = {
@@ -581,9 +581,9 @@ static struct resource bfin_sport1_uart_
 	},
 };
 
-unsigned short bfin_sport1_peripherals[] = {
+static unsigned short bfin_sport1_peripherals[] = {
 	P_SPORT1_TFS, P_SPORT1_DTPRI, P_SPORT1_TSCLK, P_SPORT1_RFS,
-	P_SPORT1_DRPRI, P_SPORT1_RSCLK, P_SPORT1_DRSEC, P_SPORT1_DTSEC, 0
+	P_SPORT1_DRPRI, P_SPORT1_RSCLK, 0
 };
 
 static struct platform_device bfin_sport1_uart_device = {
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf518/dma.c linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf518/dma.c
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf518/dma.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf518/dma.c	2011-03-14 21:20:32.000000000 -0400
@@ -11,7 +11,7 @@
 #include <asm/blackfin.h>
 #include <asm/dma.h>
 
-struct dma_register *dma_io_base_addr[MAX_DMA_CHANNELS] = {
+struct dma_register * const dma_io_base_addr[MAX_DMA_CHANNELS] = {
 	(struct dma_register *) DMA0_NEXT_DESC_PTR,
 	(struct dma_register *) DMA1_NEXT_DESC_PTR,
 	(struct dma_register *) DMA2_NEXT_DESC_PTR,
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf518/include/mach/bfin_serial_5xx.h linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf518/include/mach/bfin_serial_5xx.h
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf518/include/mach/bfin_serial_5xx.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf518/include/mach/bfin_serial_5xx.h	2011-03-14 21:20:32.000000000 -0400
@@ -4,36 +4,9 @@
  * Licensed under the GPL-2 or later
  */
 
-#include <linux/serial.h>
 #include <asm/dma.h>
 #include <asm/portmux.h>
 
-#define UART_GET_CHAR(uart)     bfin_read16(((uart)->port.membase + OFFSET_RBR))
-#define UART_GET_DLL(uart)	bfin_read16(((uart)->port.membase + OFFSET_DLL))
-#define UART_GET_IER(uart)      bfin_read16(((uart)->port.membase + OFFSET_IER))
-#define UART_GET_DLH(uart)	bfin_read16(((uart)->port.membase + OFFSET_DLH))
-#define UART_GET_IIR(uart)      bfin_read16(((uart)->port.membase + OFFSET_IIR))
-#define UART_GET_LCR(uart)      bfin_read16(((uart)->port.membase + OFFSET_LCR))
-#define UART_GET_GCTL(uart)     bfin_read16(((uart)->port.membase + OFFSET_GCTL))
-
-#define UART_PUT_CHAR(uart, v)   bfin_write16(((uart)->port.membase + OFFSET_THR), v)
-#define UART_PUT_DLL(uart, v)    bfin_write16(((uart)->port.membase + OFFSET_DLL), v)
-#define UART_PUT_IER(uart, v)    bfin_write16(((uart)->port.membase + OFFSET_IER), v)
-#define UART_SET_IER(uart, v)    UART_PUT_IER(uart, UART_GET_IER(uart) | (v))
-#define UART_CLEAR_IER(uart, v)  UART_PUT_IER(uart, UART_GET_IER(uart) & ~(v))
-#define UART_PUT_DLH(uart, v)    bfin_write16(((uart)->port.membase + OFFSET_DLH), v)
-#define UART_PUT_LCR(uart, v)    bfin_write16(((uart)->port.membase + OFFSET_LCR), v)
-#define UART_PUT_GCTL(uart, v)   bfin_write16(((uart)->port.membase + OFFSET_GCTL), v)
-
-#define UART_SET_DLAB(uart)     do { UART_PUT_LCR(uart, UART_GET_LCR(uart) | DLAB); SSYNC(); } while (0)
-#define UART_CLEAR_DLAB(uart)   do { UART_PUT_LCR(uart, UART_GET_LCR(uart) & ~DLAB); SSYNC(); } while (0)
-
-#define UART_GET_CTS(x) gpio_get_value(x->cts_pin)
-#define UART_DISABLE_RTS(x) gpio_set_value(x->rts_pin, 1)
-#define UART_ENABLE_RTS(x) gpio_set_value(x->rts_pin, 0)
-#define UART_ENABLE_INTS(x, v) UART_PUT_IER(x, v)
-#define UART_DISABLE_INTS(x) UART_PUT_IER(x, 0)
-
 #if defined(CONFIG_BFIN_UART0_CTSRTS) || defined(CONFIG_BFIN_UART1_CTSRTS)
 # define CONFIG_SERIAL_BFIN_CTSRTS
 
@@ -54,50 +27,6 @@
 # endif
 #endif
 
-#define BFIN_UART_TX_FIFO_SIZE	2
-
-/*
- * The pin configuration is different from schematic
- */
-struct bfin_serial_port {
-	struct uart_port port;
-	unsigned int old_status;
-	int status_irq;
-	unsigned int lsr;
-#ifdef CONFIG_SERIAL_BFIN_DMA
-	int tx_done;
-	int tx_count;
-	struct circ_buf rx_dma_buf;
-	struct timer_list rx_dma_timer;
-	int rx_dma_nrows;
-	unsigned int tx_dma_channel;
-	unsigned int rx_dma_channel;
-	struct work_struct tx_dma_workqueue;
-#endif
-#ifdef CONFIG_SERIAL_BFIN_CTSRTS
-	struct timer_list cts_timer;
-	int cts_pin;
-	int rts_pin;
-#endif
-};
-
-/* The hardware clears the LSR bits upon read, so we need to cache
- * some of the more fun bits in software so they don't get lost
- * when checking the LSR in other code paths (TX).
- */
-static inline unsigned int UART_GET_LSR(struct bfin_serial_port *uart)
-{
-	unsigned int lsr = bfin_read16(uart->port.membase + OFFSET_LSR);
-	uart->lsr |= (lsr & (BI|FE|PE|OE));
-	return lsr | uart->lsr;
-}
-
-static inline void UART_CLEAR_LSR(struct bfin_serial_port *uart)
-{
-	uart->lsr = 0;
-	bfin_write16(uart->port.membase + OFFSET_LSR, -1);
-}
-
 struct bfin_serial_res {
 	unsigned long uart_base_addr;
 	int uart_irq;
@@ -146,3 +75,5 @@ struct bfin_serial_res bfin_serial_resou
 };
 
 #define DRIVER_NAME "bfin-uart"
+
+#include <asm/bfin_serial.h>
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf518/include/mach/bfin_serial.h linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf518/include/mach/bfin_serial.h
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf518/include/mach/bfin_serial.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf518/include/mach/bfin_serial.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,14 @@
+/*
+ * mach/bfin_serial.h - Blackfin UART/Serial definitions
+ *
+ * Copyright 2006-2010 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#ifndef __BFIN_MACH_SERIAL_H__
+#define __BFIN_MACH_SERIAL_H__
+
+#define BFIN_UART_NR_PORTS	2
+
+#endif
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf518/include/mach/blackfin.h linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf518/include/mach/blackfin.h
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf518/include/mach/blackfin.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf518/include/mach/blackfin.h	2011-03-14 21:20:32.000000000 -0400
@@ -1,61 +1,43 @@
 /*
- * Copyright 2008-2009 Analog Devices Inc.
+ * Copyright 2008-2010 Analog Devices Inc.
  *
- * Licensed under the GPL-2 or later
+ * Licensed under the GPL-2 or later.
  */
 
 #ifndef _MACH_BLACKFIN_H_
 #define _MACH_BLACKFIN_H_
 
 #include "bf518.h"
-#include "defBF512.h"
 #include "anomaly.h"
 
-#if defined(CONFIG_BF518)
-#include "defBF518.h"
-#endif
-
-#if defined(CONFIG_BF516)
-#include "defBF516.h"
-#endif
-
-#if defined(CONFIG_BF514)
-#include "defBF514.h"
+#include <asm/def_LPBlackfin.h>
+#ifdef CONFIG_BF512
+# include "defBF512.h"
 #endif
-
-#if defined(CONFIG_BF512)
-#include "defBF512.h"
+#ifdef CONFIG_BF514
+# include "defBF514.h"
 #endif
-
-#if !defined(__ASSEMBLY__)
-#include "cdefBF512.h"
-
-#if defined(CONFIG_BF518)
-#include "cdefBF518.h"
+#ifdef CONFIG_BF516
+# include "defBF516.h"
 #endif
-
-#if defined(CONFIG_BF516)
-#include "cdefBF516.h"
+#ifdef CONFIG_BF518
+# include "defBF518.h"
 #endif
 
-#if defined(CONFIG_BF514)
-#include "cdefBF514.h"
-#endif
+#ifndef __ASSEMBLY__
+# include <asm/cdef_LPBlackfin.h>
+# ifdef CONFIG_BF512
+#  include "cdefBF512.h"
+# endif
+# ifdef CONFIG_BF514
+#  include "cdefBF514.h"
+# endif
+# ifdef CONFIG_BF516
+#  include "cdefBF516.h"
+# endif
+# ifdef CONFIG_BF518
+#  include "cdefBF518.h"
+# endif
 #endif
 
-#define BFIN_UART_NR_PORTS	2
-
-#define OFFSET_THR              0x00	/* Transmit Holding register            */
-#define OFFSET_RBR              0x00	/* Receive Buffer register              */
-#define OFFSET_DLL              0x00	/* Divisor Latch (Low-Byte)             */
-#define OFFSET_IER              0x04	/* Interrupt Enable Register            */
-#define OFFSET_DLH              0x04	/* Divisor Latch (High-Byte)            */
-#define OFFSET_IIR              0x08	/* Interrupt Identification Register    */
-#define OFFSET_LCR              0x0C	/* Line Control Register                */
-#define OFFSET_MCR              0x10	/* Modem Control Register               */
-#define OFFSET_LSR              0x14	/* Line Status Register                 */
-#define OFFSET_MSR              0x18	/* Modem Status Register                */
-#define OFFSET_SCR              0x1C	/* SCR Scratch Register                 */
-#define OFFSET_GCTL             0x24	/* Global Control Register              */
-
 #endif
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf518/include/mach/cdefBF512.h linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf518/include/mach/cdefBF512.h
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf518/include/mach/cdefBF512.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf518/include/mach/cdefBF512.h	2011-03-14 21:20:32.000000000 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright 2008-2009 Analog Devices Inc.
+ * Copyright 2008-2010 Analog Devices Inc.
  *
  * Licensed under the ADI BSD license or the GPL-2 (or later)
  */
@@ -7,15 +7,1037 @@
 #ifndef _CDEF_BF512_H
 #define _CDEF_BF512_H
 
-/* include all Core registers and bit definitions */
-#include "defBF512.h"
+/* Clock and System Control	(0xFFC00000 - 0xFFC000FF)								*/
+#define bfin_read_PLL_CTL()			bfin_read16(PLL_CTL)
+#define bfin_read_PLL_DIV()			bfin_read16(PLL_DIV)
+#define bfin_write_PLL_DIV(val)			bfin_write16(PLL_DIV, val)
+#define bfin_read_VR_CTL()			bfin_read16(VR_CTL)
+#define bfin_read_PLL_STAT()			bfin_read16(PLL_STAT)
+#define bfin_write_PLL_STAT(val)		bfin_write16(PLL_STAT, val)
+#define bfin_read_PLL_LOCKCNT()			bfin_read16(PLL_LOCKCNT)
+#define bfin_write_PLL_LOCKCNT(val)		bfin_write16(PLL_LOCKCNT, val)
+#define bfin_read_CHIPID()			bfin_read32(CHIPID)
+#define bfin_write_CHIPID(val)			bfin_write32(CHIPID, val)
 
-/* include core specific register pointer definitions */
-#include <asm/cdef_LPBlackfin.h>
 
-/* SYSTEM & MMR ADDRESS DEFINITIONS FOR ADSP-BF512 */
+/* System Interrupt Controller (0xFFC00100 - 0xFFC001FF)							*/
+#define bfin_read_SWRST()			bfin_read16(SWRST)
+#define bfin_write_SWRST(val)			bfin_write16(SWRST, val)
+#define bfin_read_SYSCR()			bfin_read16(SYSCR)
+#define bfin_write_SYSCR(val)			bfin_write16(SYSCR, val)
 
-/* include cdefBF51x_base.h for the set of #defines that are common to all ADSP-BF51x processors */
-#include "cdefBF51x_base.h"
+#define bfin_read_SIC_RVECT()			bfin_read32(SIC_RVECT)
+#define bfin_write_SIC_RVECT(val)		bfin_write32(SIC_RVECT, val)
+#define bfin_read_SIC_IMASK0()			bfin_read32(SIC_IMASK0)
+#define bfin_write_SIC_IMASK0(val)		bfin_write32(SIC_IMASK0, val)
+#define bfin_read_SIC_IMASK(x)			bfin_read32(SIC_IMASK0 + (x << 6))
+#define bfin_write_SIC_IMASK(x, val)		bfin_write32((SIC_IMASK0 + (x << 6)), val)
+
+#define bfin_read_SIC_IAR0()			bfin_read32(SIC_IAR0)
+#define bfin_write_SIC_IAR0(val)		bfin_write32(SIC_IAR0, val)
+#define bfin_read_SIC_IAR1()			bfin_read32(SIC_IAR1)
+#define bfin_write_SIC_IAR1(val)		bfin_write32(SIC_IAR1, val)
+#define bfin_read_SIC_IAR2()			bfin_read32(SIC_IAR2)
+#define bfin_write_SIC_IAR2(val)		bfin_write32(SIC_IAR2, val)
+#define bfin_read_SIC_IAR3()			bfin_read32(SIC_IAR3)
+#define bfin_write_SIC_IAR3(val)		bfin_write32(SIC_IAR3, val)
+
+#define bfin_read_SIC_ISR0()			bfin_read32(SIC_ISR0)
+#define bfin_write_SIC_ISR0(val)		bfin_write32(SIC_ISR0, val)
+#define bfin_read_SIC_ISR(x)			bfin_read32(SIC_ISR0 + (x << 6))
+#define bfin_write_SIC_ISR(x, val)		bfin_write32((SIC_ISR0 + (x << 6)), val)
+
+#define bfin_read_SIC_IWR0()			bfin_read32(SIC_IWR0)
+#define bfin_write_SIC_IWR0(val)		bfin_write32(SIC_IWR0, val)
+#define bfin_read_SIC_IWR(x)			bfin_read32(SIC_IWR0 + (x << 6))
+#define bfin_write_SIC_IWR(x, val)		bfin_write32((SIC_IWR0 + (x << 6)), val)
+
+/* SIC Additions to ADSP-BF51x (0xFFC0014C - 0xFFC00162) */
+
+#define bfin_read_SIC_IMASK1()			bfin_read32(SIC_IMASK1)
+#define bfin_write_SIC_IMASK1(val)		bfin_write32(SIC_IMASK1, val)
+#define bfin_read_SIC_IAR4()			bfin_read32(SIC_IAR4)
+#define bfin_write_SIC_IAR4(val)		bfin_write32(SIC_IAR4, val)
+#define bfin_read_SIC_IAR5()			bfin_read32(SIC_IAR5)
+#define bfin_write_SIC_IAR5(val)		bfin_write32(SIC_IAR5, val)
+#define bfin_read_SIC_IAR6()			bfin_read32(SIC_IAR6)
+#define bfin_write_SIC_IAR6(val)		bfin_write32(SIC_IAR6, val)
+#define bfin_read_SIC_IAR7()			bfin_read32(SIC_IAR7)
+#define bfin_write_SIC_IAR7(val)		bfin_write32(SIC_IAR7, val)
+#define bfin_read_SIC_ISR1()			bfin_read32(SIC_ISR1)
+#define bfin_write_SIC_ISR1(val)		bfin_write32(SIC_ISR1, val)
+#define bfin_read_SIC_IWR1()			bfin_read32(SIC_IWR1)
+#define bfin_write_SIC_IWR1(val)		bfin_write32(SIC_IWR1, val)
+
+/* Watchdog Timer		(0xFFC00200 - 0xFFC002FF)									*/
+#define bfin_read_WDOG_CTL()			bfin_read16(WDOG_CTL)
+#define bfin_write_WDOG_CTL(val)		bfin_write16(WDOG_CTL, val)
+#define bfin_read_WDOG_CNT()			bfin_read32(WDOG_CNT)
+#define bfin_write_WDOG_CNT(val)		bfin_write32(WDOG_CNT, val)
+#define bfin_read_WDOG_STAT()			bfin_read32(WDOG_STAT)
+#define bfin_write_WDOG_STAT(val)		bfin_write32(WDOG_STAT, val)
+
+
+/* Real Time Clock		(0xFFC00300 - 0xFFC003FF)									*/
+#define bfin_read_RTC_STAT()			bfin_read32(RTC_STAT)
+#define bfin_write_RTC_STAT(val)		bfin_write32(RTC_STAT, val)
+#define bfin_read_RTC_ICTL()			bfin_read16(RTC_ICTL)
+#define bfin_write_RTC_ICTL(val)		bfin_write16(RTC_ICTL, val)
+#define bfin_read_RTC_ISTAT()			bfin_read16(RTC_ISTAT)
+#define bfin_write_RTC_ISTAT(val)		bfin_write16(RTC_ISTAT, val)
+#define bfin_read_RTC_SWCNT()			bfin_read16(RTC_SWCNT)
+#define bfin_write_RTC_SWCNT(val)		bfin_write16(RTC_SWCNT, val)
+#define bfin_read_RTC_ALARM()			bfin_read32(RTC_ALARM)
+#define bfin_write_RTC_ALARM(val)		bfin_write32(RTC_ALARM, val)
+#define bfin_read_RTC_FAST()			bfin_read16(RTC_FAST)
+#define bfin_write_RTC_FAST(val)		bfin_write16(RTC_FAST, val)
+#define bfin_read_RTC_PREN()			bfin_read16(RTC_PREN)
+#define bfin_write_RTC_PREN(val)		bfin_write16(RTC_PREN, val)
+
+
+/* UART0 Controller		(0xFFC00400 - 0xFFC004FF)									*/
+#define bfin_read_UART0_THR()			bfin_read16(UART0_THR)
+#define bfin_write_UART0_THR(val)		bfin_write16(UART0_THR, val)
+#define bfin_read_UART0_RBR()			bfin_read16(UART0_RBR)
+#define bfin_write_UART0_RBR(val)		bfin_write16(UART0_RBR, val)
+#define bfin_read_UART0_DLL()			bfin_read16(UART0_DLL)
+#define bfin_write_UART0_DLL(val)		bfin_write16(UART0_DLL, val)
+#define bfin_read_UART0_IER()			bfin_read16(UART0_IER)
+#define bfin_write_UART0_IER(val)		bfin_write16(UART0_IER, val)
+#define bfin_read_UART0_DLH()			bfin_read16(UART0_DLH)
+#define bfin_write_UART0_DLH(val)		bfin_write16(UART0_DLH, val)
+#define bfin_read_UART0_IIR()			bfin_read16(UART0_IIR)
+#define bfin_write_UART0_IIR(val)		bfin_write16(UART0_IIR, val)
+#define bfin_read_UART0_LCR()			bfin_read16(UART0_LCR)
+#define bfin_write_UART0_LCR(val)		bfin_write16(UART0_LCR, val)
+#define bfin_read_UART0_MCR()			bfin_read16(UART0_MCR)
+#define bfin_write_UART0_MCR(val)		bfin_write16(UART0_MCR, val)
+#define bfin_read_UART0_LSR()			bfin_read16(UART0_LSR)
+#define bfin_write_UART0_LSR(val)		bfin_write16(UART0_LSR, val)
+#define bfin_read_UART0_MSR()			bfin_read16(UART0_MSR)
+#define bfin_write_UART0_MSR(val)		bfin_write16(UART0_MSR, val)
+#define bfin_read_UART0_SCR()			bfin_read16(UART0_SCR)
+#define bfin_write_UART0_SCR(val)		bfin_write16(UART0_SCR, val)
+#define bfin_read_UART0_GCTL()			bfin_read16(UART0_GCTL)
+#define bfin_write_UART0_GCTL(val)		bfin_write16(UART0_GCTL, val)
+
+
+/* TIMER0-7 Registers		(0xFFC00600 - 0xFFC006FF)								*/
+#define bfin_read_TIMER0_CONFIG()		bfin_read16(TIMER0_CONFIG)
+#define bfin_write_TIMER0_CONFIG(val)		bfin_write16(TIMER0_CONFIG, val)
+#define bfin_read_TIMER0_COUNTER()		bfin_read32(TIMER0_COUNTER)
+#define bfin_write_TIMER0_COUNTER(val)		bfin_write32(TIMER0_COUNTER, val)
+#define bfin_read_TIMER0_PERIOD()		bfin_read32(TIMER0_PERIOD)
+#define bfin_write_TIMER0_PERIOD(val)		bfin_write32(TIMER0_PERIOD, val)
+#define bfin_read_TIMER0_WIDTH()		bfin_read32(TIMER0_WIDTH)
+#define bfin_write_TIMER0_WIDTH(val)		bfin_write32(TIMER0_WIDTH, val)
+
+#define bfin_read_TIMER1_CONFIG()		bfin_read16(TIMER1_CONFIG)
+#define bfin_write_TIMER1_CONFIG(val)		bfin_write16(TIMER1_CONFIG, val)
+#define bfin_read_TIMER1_COUNTER()		bfin_read32(TIMER1_COUNTER)
+#define bfin_write_TIMER1_COUNTER(val)		bfin_write32(TIMER1_COUNTER, val)
+#define bfin_read_TIMER1_PERIOD()		bfin_read32(TIMER1_PERIOD)
+#define bfin_write_TIMER1_PERIOD(val)		bfin_write32(TIMER1_PERIOD, val)
+#define bfin_read_TIMER1_WIDTH()		bfin_read32(TIMER1_WIDTH)
+#define bfin_write_TIMER1_WIDTH(val)		bfin_write32(TIMER1_WIDTH, val)
+
+#define bfin_read_TIMER2_CONFIG()		bfin_read16(TIMER2_CONFIG)
+#define bfin_write_TIMER2_CONFIG(val)		bfin_write16(TIMER2_CONFIG, val)
+#define bfin_read_TIMER2_COUNTER()		bfin_read32(TIMER2_COUNTER)
+#define bfin_write_TIMER2_COUNTER(val)		bfin_write32(TIMER2_COUNTER, val)
+#define bfin_read_TIMER2_PERIOD()		bfin_read32(TIMER2_PERIOD)
+#define bfin_write_TIMER2_PERIOD(val)		bfin_write32(TIMER2_PERIOD, val)
+#define bfin_read_TIMER2_WIDTH()		bfin_read32(TIMER2_WIDTH)
+#define bfin_write_TIMER2_WIDTH(val)		bfin_write32(TIMER2_WIDTH, val)
+
+#define bfin_read_TIMER3_CONFIG()		bfin_read16(TIMER3_CONFIG)
+#define bfin_write_TIMER3_CONFIG(val)		bfin_write16(TIMER3_CONFIG, val)
+#define bfin_read_TIMER3_COUNTER()		bfin_read32(TIMER3_COUNTER)
+#define bfin_write_TIMER3_COUNTER(val)		bfin_write32(TIMER3_COUNTER, val)
+#define bfin_read_TIMER3_PERIOD()		bfin_read32(TIMER3_PERIOD)
+#define bfin_write_TIMER3_PERIOD(val)		bfin_write32(TIMER3_PERIOD, val)
+#define bfin_read_TIMER3_WIDTH()		bfin_read32(TIMER3_WIDTH)
+#define bfin_write_TIMER3_WIDTH(val)		bfin_write32(TIMER3_WIDTH, val)
+
+#define bfin_read_TIMER4_CONFIG()		bfin_read16(TIMER4_CONFIG)
+#define bfin_write_TIMER4_CONFIG(val)		bfin_write16(TIMER4_CONFIG, val)
+#define bfin_read_TIMER4_COUNTER()		bfin_read32(TIMER4_COUNTER)
+#define bfin_write_TIMER4_COUNTER(val)		bfin_write32(TIMER4_COUNTER, val)
+#define bfin_read_TIMER4_PERIOD()		bfin_read32(TIMER4_PERIOD)
+#define bfin_write_TIMER4_PERIOD(val)		bfin_write32(TIMER4_PERIOD, val)
+#define bfin_read_TIMER4_WIDTH()		bfin_read32(TIMER4_WIDTH)
+#define bfin_write_TIMER4_WIDTH(val)		bfin_write32(TIMER4_WIDTH, val)
+
+#define bfin_read_TIMER5_CONFIG()		bfin_read16(TIMER5_CONFIG)
+#define bfin_write_TIMER5_CONFIG(val)		bfin_write16(TIMER5_CONFIG, val)
+#define bfin_read_TIMER5_COUNTER()		bfin_read32(TIMER5_COUNTER)
+#define bfin_write_TIMER5_COUNTER(val)		bfin_write32(TIMER5_COUNTER, val)
+#define bfin_read_TIMER5_PERIOD()		bfin_read32(TIMER5_PERIOD)
+#define bfin_write_TIMER5_PERIOD(val)		bfin_write32(TIMER5_PERIOD, val)
+#define bfin_read_TIMER5_WIDTH()		bfin_read32(TIMER5_WIDTH)
+#define bfin_write_TIMER5_WIDTH(val)		bfin_write32(TIMER5_WIDTH, val)
+
+#define bfin_read_TIMER6_CONFIG()		bfin_read16(TIMER6_CONFIG)
+#define bfin_write_TIMER6_CONFIG(val)		bfin_write16(TIMER6_CONFIG, val)
+#define bfin_read_TIMER6_COUNTER()		bfin_read32(TIMER6_COUNTER)
+#define bfin_write_TIMER6_COUNTER(val)		bfin_write32(TIMER6_COUNTER, val)
+#define bfin_read_TIMER6_PERIOD()		bfin_read32(TIMER6_PERIOD)
+#define bfin_write_TIMER6_PERIOD(val)		bfin_write32(TIMER6_PERIOD, val)
+#define bfin_read_TIMER6_WIDTH()		bfin_read32(TIMER6_WIDTH)
+#define bfin_write_TIMER6_WIDTH(val)		bfin_write32(TIMER6_WIDTH, val)
+
+#define bfin_read_TIMER7_CONFIG()		bfin_read16(TIMER7_CONFIG)
+#define bfin_write_TIMER7_CONFIG(val)		bfin_write16(TIMER7_CONFIG, val)
+#define bfin_read_TIMER7_COUNTER()		bfin_read32(TIMER7_COUNTER)
+#define bfin_write_TIMER7_COUNTER(val)		bfin_write32(TIMER7_COUNTER, val)
+#define bfin_read_TIMER7_PERIOD()		bfin_read32(TIMER7_PERIOD)
+#define bfin_write_TIMER7_PERIOD(val)		bfin_write32(TIMER7_PERIOD, val)
+#define bfin_read_TIMER7_WIDTH()		bfin_read32(TIMER7_WIDTH)
+#define bfin_write_TIMER7_WIDTH(val)		bfin_write32(TIMER7_WIDTH, val)
+
+#define bfin_read_TIMER_ENABLE()		bfin_read16(TIMER_ENABLE)
+#define bfin_write_TIMER_ENABLE(val)		bfin_write16(TIMER_ENABLE, val)
+#define bfin_read_TIMER_DISABLE()		bfin_read16(TIMER_DISABLE)
+#define bfin_write_TIMER_DISABLE(val)		bfin_write16(TIMER_DISABLE, val)
+#define bfin_read_TIMER_STATUS()		bfin_read32(TIMER_STATUS)
+#define bfin_write_TIMER_STATUS(val)		bfin_write32(TIMER_STATUS, val)
+
+
+/* General Purpose I/O Port F (0xFFC00700 - 0xFFC007FF)								*/
+#define bfin_read_PORTFIO()			bfin_read16(PORTFIO)
+#define bfin_write_PORTFIO(val)			bfin_write16(PORTFIO, val)
+#define bfin_read_PORTFIO_CLEAR()		bfin_read16(PORTFIO_CLEAR)
+#define bfin_write_PORTFIO_CLEAR(val)		bfin_write16(PORTFIO_CLEAR, val)
+#define bfin_read_PORTFIO_SET()			bfin_read16(PORTFIO_SET)
+#define bfin_write_PORTFIO_SET(val)		bfin_write16(PORTFIO_SET, val)
+#define bfin_read_PORTFIO_TOGGLE()		bfin_read16(PORTFIO_TOGGLE)
+#define bfin_write_PORTFIO_TOGGLE(val)		bfin_write16(PORTFIO_TOGGLE, val)
+#define bfin_read_PORTFIO_MASKA()		bfin_read16(PORTFIO_MASKA)
+#define bfin_write_PORTFIO_MASKA(val)		bfin_write16(PORTFIO_MASKA, val)
+#define bfin_read_PORTFIO_MASKA_CLEAR()		bfin_read16(PORTFIO_MASKA_CLEAR)
+#define bfin_write_PORTFIO_MASKA_CLEAR(val)	bfin_write16(PORTFIO_MASKA_CLEAR, val)
+#define bfin_read_PORTFIO_MASKA_SET()		bfin_read16(PORTFIO_MASKA_SET)
+#define bfin_write_PORTFIO_MASKA_SET(val)	bfin_write16(PORTFIO_MASKA_SET, val)
+#define bfin_read_PORTFIO_MASKA_TOGGLE()	bfin_read16(PORTFIO_MASKA_TOGGLE)
+#define bfin_write_PORTFIO_MASKA_TOGGLE(val)	bfin_write16(PORTFIO_MASKA_TOGGLE, val)
+#define bfin_read_PORTFIO_MASKB()		bfin_read16(PORTFIO_MASKB)
+#define bfin_write_PORTFIO_MASKB(val)		bfin_write16(PORTFIO_MASKB, val)
+#define bfin_read_PORTFIO_MASKB_CLEAR()		bfin_read16(PORTFIO_MASKB_CLEAR)
+#define bfin_write_PORTFIO_MASKB_CLEAR(val)	bfin_write16(PORTFIO_MASKB_CLEAR, val)
+#define bfin_read_PORTFIO_MASKB_SET()		bfin_read16(PORTFIO_MASKB_SET)
+#define bfin_write_PORTFIO_MASKB_SET(val)	bfin_write16(PORTFIO_MASKB_SET, val)
+#define bfin_read_PORTFIO_MASKB_TOGGLE()	bfin_read16(PORTFIO_MASKB_TOGGLE)
+#define bfin_write_PORTFIO_MASKB_TOGGLE(val)	bfin_write16(PORTFIO_MASKB_TOGGLE, val)
+#define bfin_read_PORTFIO_DIR()			bfin_read16(PORTFIO_DIR)
+#define bfin_write_PORTFIO_DIR(val)		bfin_write16(PORTFIO_DIR, val)
+#define bfin_read_PORTFIO_POLAR()		bfin_read16(PORTFIO_POLAR)
+#define bfin_write_PORTFIO_POLAR(val)		bfin_write16(PORTFIO_POLAR, val)
+#define bfin_read_PORTFIO_EDGE()		bfin_read16(PORTFIO_EDGE)
+#define bfin_write_PORTFIO_EDGE(val)		bfin_write16(PORTFIO_EDGE, val)
+#define bfin_read_PORTFIO_BOTH()		bfin_read16(PORTFIO_BOTH)
+#define bfin_write_PORTFIO_BOTH(val)		bfin_write16(PORTFIO_BOTH, val)
+#define bfin_read_PORTFIO_INEN()		bfin_read16(PORTFIO_INEN)
+#define bfin_write_PORTFIO_INEN(val)		bfin_write16(PORTFIO_INEN, val)
+
+
+/* SPORT0 Controller		(0xFFC00800 - 0xFFC008FF)								*/
+#define bfin_read_SPORT0_TCR1()			bfin_read16(SPORT0_TCR1)
+#define bfin_write_SPORT0_TCR1(val)		bfin_write16(SPORT0_TCR1, val)
+#define bfin_read_SPORT0_TCR2()			bfin_read16(SPORT0_TCR2)
+#define bfin_write_SPORT0_TCR2(val)		bfin_write16(SPORT0_TCR2, val)
+#define bfin_read_SPORT0_TCLKDIV()		bfin_read16(SPORT0_TCLKDIV)
+#define bfin_write_SPORT0_TCLKDIV(val)		bfin_write16(SPORT0_TCLKDIV, val)
+#define bfin_read_SPORT0_TFSDIV()		bfin_read16(SPORT0_TFSDIV)
+#define bfin_write_SPORT0_TFSDIV(val)		bfin_write16(SPORT0_TFSDIV, val)
+#define bfin_read_SPORT0_TX()			bfin_read32(SPORT0_TX)
+#define bfin_write_SPORT0_TX(val)		bfin_write32(SPORT0_TX, val)
+#define bfin_read_SPORT0_RX()			bfin_read32(SPORT0_RX)
+#define bfin_write_SPORT0_RX(val)		bfin_write32(SPORT0_RX, val)
+#define bfin_read_SPORT0_TX32()			bfin_read32(SPORT0_TX)
+#define bfin_write_SPORT0_TX32(val)		bfin_write32(SPORT0_TX, val)
+#define bfin_read_SPORT0_RX32()			bfin_read32(SPORT0_RX)
+#define bfin_write_SPORT0_RX32(val)		bfin_write32(SPORT0_RX, val)
+#define bfin_read_SPORT0_TX16()			bfin_read16(SPORT0_TX)
+#define bfin_write_SPORT0_TX16(val)		bfin_write16(SPORT0_TX, val)
+#define bfin_read_SPORT0_RX16()			bfin_read16(SPORT0_RX)
+#define bfin_write_SPORT0_RX16(val)		bfin_write16(SPORT0_RX, val)
+#define bfin_read_SPORT0_RCR1()			bfin_read16(SPORT0_RCR1)
+#define bfin_write_SPORT0_RCR1(val)		bfin_write16(SPORT0_RCR1, val)
+#define bfin_read_SPORT0_RCR2()			bfin_read16(SPORT0_RCR2)
+#define bfin_write_SPORT0_RCR2(val)		bfin_write16(SPORT0_RCR2, val)
+#define bfin_read_SPORT0_RCLKDIV()		bfin_read16(SPORT0_RCLKDIV)
+#define bfin_write_SPORT0_RCLKDIV(val)		bfin_write16(SPORT0_RCLKDIV, val)
+#define bfin_read_SPORT0_RFSDIV()		bfin_read16(SPORT0_RFSDIV)
+#define bfin_write_SPORT0_RFSDIV(val)		bfin_write16(SPORT0_RFSDIV, val)
+#define bfin_read_SPORT0_STAT()			bfin_read16(SPORT0_STAT)
+#define bfin_write_SPORT0_STAT(val)		bfin_write16(SPORT0_STAT, val)
+#define bfin_read_SPORT0_CHNL()			bfin_read16(SPORT0_CHNL)
+#define bfin_write_SPORT0_CHNL(val)		bfin_write16(SPORT0_CHNL, val)
+#define bfin_read_SPORT0_MCMC1()		bfin_read16(SPORT0_MCMC1)
+#define bfin_write_SPORT0_MCMC1(val)		bfin_write16(SPORT0_MCMC1, val)
+#define bfin_read_SPORT0_MCMC2()		bfin_read16(SPORT0_MCMC2)
+#define bfin_write_SPORT0_MCMC2(val)		bfin_write16(SPORT0_MCMC2, val)
+#define bfin_read_SPORT0_MTCS0()		bfin_read32(SPORT0_MTCS0)
+#define bfin_write_SPORT0_MTCS0(val)		bfin_write32(SPORT0_MTCS0, val)
+#define bfin_read_SPORT0_MTCS1()		bfin_read32(SPORT0_MTCS1)
+#define bfin_write_SPORT0_MTCS1(val)		bfin_write32(SPORT0_MTCS1, val)
+#define bfin_read_SPORT0_MTCS2()		bfin_read32(SPORT0_MTCS2)
+#define bfin_write_SPORT0_MTCS2(val)		bfin_write32(SPORT0_MTCS2, val)
+#define bfin_read_SPORT0_MTCS3()		bfin_read32(SPORT0_MTCS3)
+#define bfin_write_SPORT0_MTCS3(val)		bfin_write32(SPORT0_MTCS3, val)
+#define bfin_read_SPORT0_MRCS0()		bfin_read32(SPORT0_MRCS0)
+#define bfin_write_SPORT0_MRCS0(val)		bfin_write32(SPORT0_MRCS0, val)
+#define bfin_read_SPORT0_MRCS1()		bfin_read32(SPORT0_MRCS1)
+#define bfin_write_SPORT0_MRCS1(val)		bfin_write32(SPORT0_MRCS1, val)
+#define bfin_read_SPORT0_MRCS2()		bfin_read32(SPORT0_MRCS2)
+#define bfin_write_SPORT0_MRCS2(val)		bfin_write32(SPORT0_MRCS2, val)
+#define bfin_read_SPORT0_MRCS3()		bfin_read32(SPORT0_MRCS3)
+#define bfin_write_SPORT0_MRCS3(val)		bfin_write32(SPORT0_MRCS3, val)
+
+
+/* SPORT1 Controller		(0xFFC00900 - 0xFFC009FF)								*/
+#define bfin_read_SPORT1_TCR1()			bfin_read16(SPORT1_TCR1)
+#define bfin_write_SPORT1_TCR1(val)		bfin_write16(SPORT1_TCR1, val)
+#define bfin_read_SPORT1_TCR2()			bfin_read16(SPORT1_TCR2)
+#define bfin_write_SPORT1_TCR2(val)		bfin_write16(SPORT1_TCR2, val)
+#define bfin_read_SPORT1_TCLKDIV()		bfin_read16(SPORT1_TCLKDIV)
+#define bfin_write_SPORT1_TCLKDIV(val)		bfin_write16(SPORT1_TCLKDIV, val)
+#define bfin_read_SPORT1_TFSDIV()		bfin_read16(SPORT1_TFSDIV)
+#define bfin_write_SPORT1_TFSDIV(val)		bfin_write16(SPORT1_TFSDIV, val)
+#define bfin_read_SPORT1_TX()			bfin_read32(SPORT1_TX)
+#define bfin_write_SPORT1_TX(val)		bfin_write32(SPORT1_TX, val)
+#define bfin_read_SPORT1_RX()			bfin_read32(SPORT1_RX)
+#define bfin_write_SPORT1_RX(val)		bfin_write32(SPORT1_RX, val)
+#define bfin_read_SPORT1_TX32()			bfin_read32(SPORT1_TX)
+#define bfin_write_SPORT1_TX32(val)		bfin_write32(SPORT1_TX, val)
+#define bfin_read_SPORT1_RX32()			bfin_read32(SPORT1_RX)
+#define bfin_write_SPORT1_RX32(val)		bfin_write32(SPORT1_RX, val)
+#define bfin_read_SPORT1_TX16()			bfin_read16(SPORT1_TX)
+#define bfin_write_SPORT1_TX16(val)		bfin_write16(SPORT1_TX, val)
+#define bfin_read_SPORT1_RX16()			bfin_read16(SPORT1_RX)
+#define bfin_write_SPORT1_RX16(val)		bfin_write16(SPORT1_RX, val)
+#define bfin_read_SPORT1_RCR1()			bfin_read16(SPORT1_RCR1)
+#define bfin_write_SPORT1_RCR1(val)		bfin_write16(SPORT1_RCR1, val)
+#define bfin_read_SPORT1_RCR2()			bfin_read16(SPORT1_RCR2)
+#define bfin_write_SPORT1_RCR2(val)		bfin_write16(SPORT1_RCR2, val)
+#define bfin_read_SPORT1_RCLKDIV()		bfin_read16(SPORT1_RCLKDIV)
+#define bfin_write_SPORT1_RCLKDIV(val)		bfin_write16(SPORT1_RCLKDIV, val)
+#define bfin_read_SPORT1_RFSDIV()		bfin_read16(SPORT1_RFSDIV)
+#define bfin_write_SPORT1_RFSDIV(val)		bfin_write16(SPORT1_RFSDIV, val)
+#define bfin_read_SPORT1_STAT()			bfin_read16(SPORT1_STAT)
+#define bfin_write_SPORT1_STAT(val)		bfin_write16(SPORT1_STAT, val)
+#define bfin_read_SPORT1_CHNL()			bfin_read16(SPORT1_CHNL)
+#define bfin_write_SPORT1_CHNL(val)		bfin_write16(SPORT1_CHNL, val)
+#define bfin_read_SPORT1_MCMC1()		bfin_read16(SPORT1_MCMC1)
+#define bfin_write_SPORT1_MCMC1(val)		bfin_write16(SPORT1_MCMC1, val)
+#define bfin_read_SPORT1_MCMC2()		bfin_read16(SPORT1_MCMC2)
+#define bfin_write_SPORT1_MCMC2(val)		bfin_write16(SPORT1_MCMC2, val)
+#define bfin_read_SPORT1_MTCS0()		bfin_read32(SPORT1_MTCS0)
+#define bfin_write_SPORT1_MTCS0(val)		bfin_write32(SPORT1_MTCS0, val)
+#define bfin_read_SPORT1_MTCS1()		bfin_read32(SPORT1_MTCS1)
+#define bfin_write_SPORT1_MTCS1(val)		bfin_write32(SPORT1_MTCS1, val)
+#define bfin_read_SPORT1_MTCS2()		bfin_read32(SPORT1_MTCS2)
+#define bfin_write_SPORT1_MTCS2(val)		bfin_write32(SPORT1_MTCS2, val)
+#define bfin_read_SPORT1_MTCS3()		bfin_read32(SPORT1_MTCS3)
+#define bfin_write_SPORT1_MTCS3(val)		bfin_write32(SPORT1_MTCS3, val)
+#define bfin_read_SPORT1_MRCS0()		bfin_read32(SPORT1_MRCS0)
+#define bfin_write_SPORT1_MRCS0(val)		bfin_write32(SPORT1_MRCS0, val)
+#define bfin_read_SPORT1_MRCS1()		bfin_read32(SPORT1_MRCS1)
+#define bfin_write_SPORT1_MRCS1(val)		bfin_write32(SPORT1_MRCS1, val)
+#define bfin_read_SPORT1_MRCS2()		bfin_read32(SPORT1_MRCS2)
+#define bfin_write_SPORT1_MRCS2(val)		bfin_write32(SPORT1_MRCS2, val)
+#define bfin_read_SPORT1_MRCS3()		bfin_read32(SPORT1_MRCS3)
+#define bfin_write_SPORT1_MRCS3(val)		bfin_write32(SPORT1_MRCS3, val)
+
+
+/* External Bus Interface Unit (0xFFC00A00 - 0xFFC00AFF)							*/
+#define bfin_read_EBIU_AMGCTL()			bfin_read16(EBIU_AMGCTL)
+#define bfin_write_EBIU_AMGCTL(val)		bfin_write16(EBIU_AMGCTL, val)
+#define bfin_read_EBIU_AMBCTL0()		bfin_read32(EBIU_AMBCTL0)
+#define bfin_write_EBIU_AMBCTL0(val)		bfin_write32(EBIU_AMBCTL0, val)
+#define bfin_read_EBIU_AMBCTL1()		bfin_read32(EBIU_AMBCTL1)
+#define bfin_write_EBIU_AMBCTL1(val)		bfin_write32(EBIU_AMBCTL1, val)
+#define bfin_read_EBIU_SDGCTL()			bfin_read32(EBIU_SDGCTL)
+#define bfin_write_EBIU_SDGCTL(val)		bfin_write32(EBIU_SDGCTL, val)
+#define bfin_read_EBIU_SDBCTL()			bfin_read16(EBIU_SDBCTL)
+#define bfin_write_EBIU_SDBCTL(val)		bfin_write16(EBIU_SDBCTL, val)
+#define bfin_read_EBIU_SDRRC()			bfin_read16(EBIU_SDRRC)
+#define bfin_write_EBIU_SDRRC(val)		bfin_write16(EBIU_SDRRC, val)
+#define bfin_read_EBIU_SDSTAT()			bfin_read16(EBIU_SDSTAT)
+#define bfin_write_EBIU_SDSTAT(val)		bfin_write16(EBIU_SDSTAT, val)
+
+
+/* DMA Traffic Control Registers													*/
+#define bfin_read_DMAC_TC_PER()			bfin_read16(DMAC_TC_PER)
+#define bfin_write_DMAC_TC_PER(val)		bfin_write16(DMAC_TC_PER, val)
+#define bfin_read_DMAC_TC_CNT()			bfin_read16(DMAC_TC_CNT)
+#define bfin_write_DMAC_TC_CNT(val)		bfin_write16(DMAC_TC_CNT, val)
+
+/* DMA Controller																	*/
+#define bfin_read_DMA0_CONFIG()			bfin_read16(DMA0_CONFIG)
+#define bfin_write_DMA0_CONFIG(val)		bfin_write16(DMA0_CONFIG, val)
+#define bfin_read_DMA0_NEXT_DESC_PTR()		bfin_read32(DMA0_NEXT_DESC_PTR)
+#define bfin_write_DMA0_NEXT_DESC_PTR(val)	bfin_write32(DMA0_NEXT_DESC_PTR, val)
+#define bfin_read_DMA0_START_ADDR()		bfin_read32(DMA0_START_ADDR)
+#define bfin_write_DMA0_START_ADDR(val)		bfin_write32(DMA0_START_ADDR, val)
+#define bfin_read_DMA0_X_COUNT()		bfin_read16(DMA0_X_COUNT)
+#define bfin_write_DMA0_X_COUNT(val)		bfin_write16(DMA0_X_COUNT, val)
+#define bfin_read_DMA0_Y_COUNT()		bfin_read16(DMA0_Y_COUNT)
+#define bfin_write_DMA0_Y_COUNT(val)		bfin_write16(DMA0_Y_COUNT, val)
+#define bfin_read_DMA0_X_MODIFY()		bfin_read16(DMA0_X_MODIFY)
+#define bfin_write_DMA0_X_MODIFY(val)		bfin_write16(DMA0_X_MODIFY, val)
+#define bfin_read_DMA0_Y_MODIFY()		bfin_read16(DMA0_Y_MODIFY)
+#define bfin_write_DMA0_Y_MODIFY(val)		bfin_write16(DMA0_Y_MODIFY, val)
+#define bfin_read_DMA0_CURR_DESC_PTR()		bfin_read32(DMA0_CURR_DESC_PTR)
+#define bfin_write_DMA0_CURR_DESC_PTR(val)	bfin_write32(DMA0_CURR_DESC_PTR, val)
+#define bfin_read_DMA0_CURR_ADDR()		bfin_read32(DMA0_CURR_ADDR)
+#define bfin_write_DMA0_CURR_ADDR(val)		bfin_write32(DMA0_CURR_ADDR, val)
+#define bfin_read_DMA0_CURR_X_COUNT()		bfin_read16(DMA0_CURR_X_COUNT)
+#define bfin_write_DMA0_CURR_X_COUNT(val)	bfin_write16(DMA0_CURR_X_COUNT, val)
+#define bfin_read_DMA0_CURR_Y_COUNT()		bfin_read16(DMA0_CURR_Y_COUNT)
+#define bfin_write_DMA0_CURR_Y_COUNT(val)	bfin_write16(DMA0_CURR_Y_COUNT, val)
+#define bfin_read_DMA0_IRQ_STATUS()		bfin_read16(DMA0_IRQ_STATUS)
+#define bfin_write_DMA0_IRQ_STATUS(val)		bfin_write16(DMA0_IRQ_STATUS, val)
+#define bfin_read_DMA0_PERIPHERAL_MAP()		bfin_read16(DMA0_PERIPHERAL_MAP)
+#define bfin_write_DMA0_PERIPHERAL_MAP(val)	bfin_write16(DMA0_PERIPHERAL_MAP, val)
+
+#define bfin_read_DMA1_CONFIG()			bfin_read16(DMA1_CONFIG)
+#define bfin_write_DMA1_CONFIG(val)		bfin_write16(DMA1_CONFIG, val)
+#define bfin_read_DMA1_NEXT_DESC_PTR()		bfin_read32(DMA1_NEXT_DESC_PTR)
+#define bfin_write_DMA1_NEXT_DESC_PTR(val)	bfin_write32(DMA1_NEXT_DESC_PTR, val)
+#define bfin_read_DMA1_START_ADDR()		bfin_read32(DMA1_START_ADDR)
+#define bfin_write_DMA1_START_ADDR(val)		bfin_write32(DMA1_START_ADDR, val)
+#define bfin_read_DMA1_X_COUNT()		bfin_read16(DMA1_X_COUNT)
+#define bfin_write_DMA1_X_COUNT(val)		bfin_write16(DMA1_X_COUNT, val)
+#define bfin_read_DMA1_Y_COUNT()		bfin_read16(DMA1_Y_COUNT)
+#define bfin_write_DMA1_Y_COUNT(val)		bfin_write16(DMA1_Y_COUNT, val)
+#define bfin_read_DMA1_X_MODIFY()		bfin_read16(DMA1_X_MODIFY)
+#define bfin_write_DMA1_X_MODIFY(val)		bfin_write16(DMA1_X_MODIFY, val)
+#define bfin_read_DMA1_Y_MODIFY()		bfin_read16(DMA1_Y_MODIFY)
+#define bfin_write_DMA1_Y_MODIFY(val)		bfin_write16(DMA1_Y_MODIFY, val)
+#define bfin_read_DMA1_CURR_DESC_PTR()		bfin_read32(DMA1_CURR_DESC_PTR)
+#define bfin_write_DMA1_CURR_DESC_PTR(val)	bfin_write32(DMA1_CURR_DESC_PTR, val)
+#define bfin_read_DMA1_CURR_ADDR()		bfin_read32(DMA1_CURR_ADDR)
+#define bfin_write_DMA1_CURR_ADDR(val)		bfin_write32(DMA1_CURR_ADDR, val)
+#define bfin_read_DMA1_CURR_X_COUNT()		bfin_read16(DMA1_CURR_X_COUNT)
+#define bfin_write_DMA1_CURR_X_COUNT(val)	bfin_write16(DMA1_CURR_X_COUNT, val)
+#define bfin_read_DMA1_CURR_Y_COUNT()		bfin_read16(DMA1_CURR_Y_COUNT)
+#define bfin_write_DMA1_CURR_Y_COUNT(val)	bfin_write16(DMA1_CURR_Y_COUNT, val)
+#define bfin_read_DMA1_IRQ_STATUS()		bfin_read16(DMA1_IRQ_STATUS)
+#define bfin_write_DMA1_IRQ_STATUS(val)		bfin_write16(DMA1_IRQ_STATUS, val)
+#define bfin_read_DMA1_PERIPHERAL_MAP()		bfin_read16(DMA1_PERIPHERAL_MAP)
+#define bfin_write_DMA1_PERIPHERAL_MAP(val)	bfin_write16(DMA1_PERIPHERAL_MAP, val)
+
+#define bfin_read_DMA2_CONFIG()			bfin_read16(DMA2_CONFIG)
+#define bfin_write_DMA2_CONFIG(val)		bfin_write16(DMA2_CONFIG, val)
+#define bfin_read_DMA2_NEXT_DESC_PTR()		bfin_read32(DMA2_NEXT_DESC_PTR)
+#define bfin_write_DMA2_NEXT_DESC_PTR(val)	bfin_write32(DMA2_NEXT_DESC_PTR, val)
+#define bfin_read_DMA2_START_ADDR()		bfin_read32(DMA2_START_ADDR)
+#define bfin_write_DMA2_START_ADDR(val)		bfin_write32(DMA2_START_ADDR, val)
+#define bfin_read_DMA2_X_COUNT()		bfin_read16(DMA2_X_COUNT)
+#define bfin_write_DMA2_X_COUNT(val)		bfin_write16(DMA2_X_COUNT, val)
+#define bfin_read_DMA2_Y_COUNT()		bfin_read16(DMA2_Y_COUNT)
+#define bfin_write_DMA2_Y_COUNT(val)		bfin_write16(DMA2_Y_COUNT, val)
+#define bfin_read_DMA2_X_MODIFY()		bfin_read16(DMA2_X_MODIFY)
+#define bfin_write_DMA2_X_MODIFY(val)		bfin_write16(DMA2_X_MODIFY, val)
+#define bfin_read_DMA2_Y_MODIFY()		bfin_read16(DMA2_Y_MODIFY)
+#define bfin_write_DMA2_Y_MODIFY(val)		bfin_write16(DMA2_Y_MODIFY, val)
+#define bfin_read_DMA2_CURR_DESC_PTR()		bfin_read32(DMA2_CURR_DESC_PTR)
+#define bfin_write_DMA2_CURR_DESC_PTR(val)	bfin_write32(DMA2_CURR_DESC_PTR, val)
+#define bfin_read_DMA2_CURR_ADDR()		bfin_read32(DMA2_CURR_ADDR)
+#define bfin_write_DMA2_CURR_ADDR(val)		bfin_write32(DMA2_CURR_ADDR, val)
+#define bfin_read_DMA2_CURR_X_COUNT()		bfin_read16(DMA2_CURR_X_COUNT)
+#define bfin_write_DMA2_CURR_X_COUNT(val)	bfin_write16(DMA2_CURR_X_COUNT, val)
+#define bfin_read_DMA2_CURR_Y_COUNT()		bfin_read16(DMA2_CURR_Y_COUNT)
+#define bfin_write_DMA2_CURR_Y_COUNT(val)	bfin_write16(DMA2_CURR_Y_COUNT, val)
+#define bfin_read_DMA2_IRQ_STATUS()		bfin_read16(DMA2_IRQ_STATUS)
+#define bfin_write_DMA2_IRQ_STATUS(val)		bfin_write16(DMA2_IRQ_STATUS, val)
+#define bfin_read_DMA2_PERIPHERAL_MAP()		bfin_read16(DMA2_PERIPHERAL_MAP)
+#define bfin_write_DMA2_PERIPHERAL_MAP(val)	bfin_write16(DMA2_PERIPHERAL_MAP, val)
+
+#define bfin_read_DMA3_CONFIG()			bfin_read16(DMA3_CONFIG)
+#define bfin_write_DMA3_CONFIG(val)		bfin_write16(DMA3_CONFIG, val)
+#define bfin_read_DMA3_NEXT_DESC_PTR()		bfin_read32(DMA3_NEXT_DESC_PTR)
+#define bfin_write_DMA3_NEXT_DESC_PTR(val)	bfin_write32(DMA3_NEXT_DESC_PTR, val)
+#define bfin_read_DMA3_START_ADDR()		bfin_read32(DMA3_START_ADDR)
+#define bfin_write_DMA3_START_ADDR(val)		bfin_write32(DMA3_START_ADDR, val)
+#define bfin_read_DMA3_X_COUNT()		bfin_read16(DMA3_X_COUNT)
+#define bfin_write_DMA3_X_COUNT(val)		bfin_write16(DMA3_X_COUNT, val)
+#define bfin_read_DMA3_Y_COUNT()		bfin_read16(DMA3_Y_COUNT)
+#define bfin_write_DMA3_Y_COUNT(val)		bfin_write16(DMA3_Y_COUNT, val)
+#define bfin_read_DMA3_X_MODIFY()		bfin_read16(DMA3_X_MODIFY)
+#define bfin_write_DMA3_X_MODIFY(val)		bfin_write16(DMA3_X_MODIFY, val)
+#define bfin_read_DMA3_Y_MODIFY()		bfin_read16(DMA3_Y_MODIFY)
+#define bfin_write_DMA3_Y_MODIFY(val)		bfin_write16(DMA3_Y_MODIFY, val)
+#define bfin_read_DMA3_CURR_DESC_PTR()		bfin_read32(DMA3_CURR_DESC_PTR)
+#define bfin_write_DMA3_CURR_DESC_PTR(val)	bfin_write32(DMA3_CURR_DESC_PTR, val)
+#define bfin_read_DMA3_CURR_ADDR()		bfin_read32(DMA3_CURR_ADDR)
+#define bfin_write_DMA3_CURR_ADDR(val)		bfin_write32(DMA3_CURR_ADDR, val)
+#define bfin_read_DMA3_CURR_X_COUNT()		bfin_read16(DMA3_CURR_X_COUNT)
+#define bfin_write_DMA3_CURR_X_COUNT(val)	bfin_write16(DMA3_CURR_X_COUNT, val)
+#define bfin_read_DMA3_CURR_Y_COUNT()		bfin_read16(DMA3_CURR_Y_COUNT)
+#define bfin_write_DMA3_CURR_Y_COUNT(val)	bfin_write16(DMA3_CURR_Y_COUNT, val)
+#define bfin_read_DMA3_IRQ_STATUS()		bfin_read16(DMA3_IRQ_STATUS)
+#define bfin_write_DMA3_IRQ_STATUS(val)		bfin_write16(DMA3_IRQ_STATUS, val)
+#define bfin_read_DMA3_PERIPHERAL_MAP()		bfin_read16(DMA3_PERIPHERAL_MAP)
+#define bfin_write_DMA3_PERIPHERAL_MAP(val)	bfin_write16(DMA3_PERIPHERAL_MAP, val)
+
+#define bfin_read_DMA4_CONFIG()			bfin_read16(DMA4_CONFIG)
+#define bfin_write_DMA4_CONFIG(val)		bfin_write16(DMA4_CONFIG, val)
+#define bfin_read_DMA4_NEXT_DESC_PTR()		bfin_read32(DMA4_NEXT_DESC_PTR)
+#define bfin_write_DMA4_NEXT_DESC_PTR(val)	bfin_write32(DMA4_NEXT_DESC_PTR, val)
+#define bfin_read_DMA4_START_ADDR()		bfin_read32(DMA4_START_ADDR)
+#define bfin_write_DMA4_START_ADDR(val)		bfin_write32(DMA4_START_ADDR, val)
+#define bfin_read_DMA4_X_COUNT()		bfin_read16(DMA4_X_COUNT)
+#define bfin_write_DMA4_X_COUNT(val)		bfin_write16(DMA4_X_COUNT, val)
+#define bfin_read_DMA4_Y_COUNT()		bfin_read16(DMA4_Y_COUNT)
+#define bfin_write_DMA4_Y_COUNT(val)		bfin_write16(DMA4_Y_COUNT, val)
+#define bfin_read_DMA4_X_MODIFY()		bfin_read16(DMA4_X_MODIFY)
+#define bfin_write_DMA4_X_MODIFY(val)		bfin_write16(DMA4_X_MODIFY, val)
+#define bfin_read_DMA4_Y_MODIFY()		bfin_read16(DMA4_Y_MODIFY)
+#define bfin_write_DMA4_Y_MODIFY(val)		bfin_write16(DMA4_Y_MODIFY, val)
+#define bfin_read_DMA4_CURR_DESC_PTR()		bfin_read32(DMA4_CURR_DESC_PTR)
+#define bfin_write_DMA4_CURR_DESC_PTR(val)	bfin_write32(DMA4_CURR_DESC_PTR, val)
+#define bfin_read_DMA4_CURR_ADDR()		bfin_read32(DMA4_CURR_ADDR)
+#define bfin_write_DMA4_CURR_ADDR(val)		bfin_write32(DMA4_CURR_ADDR, val)
+#define bfin_read_DMA4_CURR_X_COUNT()		bfin_read16(DMA4_CURR_X_COUNT)
+#define bfin_write_DMA4_CURR_X_COUNT(val)	bfin_write16(DMA4_CURR_X_COUNT, val)
+#define bfin_read_DMA4_CURR_Y_COUNT()		bfin_read16(DMA4_CURR_Y_COUNT)
+#define bfin_write_DMA4_CURR_Y_COUNT(val)	bfin_write16(DMA4_CURR_Y_COUNT, val)
+#define bfin_read_DMA4_IRQ_STATUS()		bfin_read16(DMA4_IRQ_STATUS)
+#define bfin_write_DMA4_IRQ_STATUS(val)		bfin_write16(DMA4_IRQ_STATUS, val)
+#define bfin_read_DMA4_PERIPHERAL_MAP()		bfin_read16(DMA4_PERIPHERAL_MAP)
+#define bfin_write_DMA4_PERIPHERAL_MAP(val)	bfin_write16(DMA4_PERIPHERAL_MAP, val)
+
+#define bfin_read_DMA5_CONFIG()			bfin_read16(DMA5_CONFIG)
+#define bfin_write_DMA5_CONFIG(val)		bfin_write16(DMA5_CONFIG, val)
+#define bfin_read_DMA5_NEXT_DESC_PTR()		bfin_read32(DMA5_NEXT_DESC_PTR)
+#define bfin_write_DMA5_NEXT_DESC_PTR(val)	bfin_write32(DMA5_NEXT_DESC_PTR, val)
+#define bfin_read_DMA5_START_ADDR()		bfin_read32(DMA5_START_ADDR)
+#define bfin_write_DMA5_START_ADDR(val)		bfin_write32(DMA5_START_ADDR, val)
+#define bfin_read_DMA5_X_COUNT()		bfin_read16(DMA5_X_COUNT)
+#define bfin_write_DMA5_X_COUNT(val)		bfin_write16(DMA5_X_COUNT, val)
+#define bfin_read_DMA5_Y_COUNT()		bfin_read16(DMA5_Y_COUNT)
+#define bfin_write_DMA5_Y_COUNT(val)		bfin_write16(DMA5_Y_COUNT, val)
+#define bfin_read_DMA5_X_MODIFY()		bfin_read16(DMA5_X_MODIFY)
+#define bfin_write_DMA5_X_MODIFY(val)		bfin_write16(DMA5_X_MODIFY, val)
+#define bfin_read_DMA5_Y_MODIFY()		bfin_read16(DMA5_Y_MODIFY)
+#define bfin_write_DMA5_Y_MODIFY(val)		bfin_write16(DMA5_Y_MODIFY, val)
+#define bfin_read_DMA5_CURR_DESC_PTR()		bfin_read32(DMA5_CURR_DESC_PTR)
+#define bfin_write_DMA5_CURR_DESC_PTR(val)	bfin_write32(DMA5_CURR_DESC_PTR, val)
+#define bfin_read_DMA5_CURR_ADDR()		bfin_read32(DMA5_CURR_ADDR)
+#define bfin_write_DMA5_CURR_ADDR(val)		bfin_write32(DMA5_CURR_ADDR, val)
+#define bfin_read_DMA5_CURR_X_COUNT()		bfin_read16(DMA5_CURR_X_COUNT)
+#define bfin_write_DMA5_CURR_X_COUNT(val)	bfin_write16(DMA5_CURR_X_COUNT, val)
+#define bfin_read_DMA5_CURR_Y_COUNT()		bfin_read16(DMA5_CURR_Y_COUNT)
+#define bfin_write_DMA5_CURR_Y_COUNT(val)	bfin_write16(DMA5_CURR_Y_COUNT, val)
+#define bfin_read_DMA5_IRQ_STATUS()		bfin_read16(DMA5_IRQ_STATUS)
+#define bfin_write_DMA5_IRQ_STATUS(val)		bfin_write16(DMA5_IRQ_STATUS, val)
+#define bfin_read_DMA5_PERIPHERAL_MAP()		bfin_read16(DMA5_PERIPHERAL_MAP)
+#define bfin_write_DMA5_PERIPHERAL_MAP(val)	bfin_write16(DMA5_PERIPHERAL_MAP, val)
+
+#define bfin_read_DMA6_CONFIG()			bfin_read16(DMA6_CONFIG)
+#define bfin_write_DMA6_CONFIG(val)		bfin_write16(DMA6_CONFIG, val)
+#define bfin_read_DMA6_NEXT_DESC_PTR()		bfin_read32(DMA6_NEXT_DESC_PTR)
+#define bfin_write_DMA6_NEXT_DESC_PTR(val)	bfin_write32(DMA6_NEXT_DESC_PTR, val)
+#define bfin_read_DMA6_START_ADDR()		bfin_read32(DMA6_START_ADDR)
+#define bfin_write_DMA6_START_ADDR(val)		bfin_write32(DMA6_START_ADDR, val)
+#define bfin_read_DMA6_X_COUNT()		bfin_read16(DMA6_X_COUNT)
+#define bfin_write_DMA6_X_COUNT(val)		bfin_write16(DMA6_X_COUNT, val)
+#define bfin_read_DMA6_Y_COUNT()		bfin_read16(DMA6_Y_COUNT)
+#define bfin_write_DMA6_Y_COUNT(val)		bfin_write16(DMA6_Y_COUNT, val)
+#define bfin_read_DMA6_X_MODIFY()		bfin_read16(DMA6_X_MODIFY)
+#define bfin_write_DMA6_X_MODIFY(val)		bfin_write16(DMA6_X_MODIFY, val)
+#define bfin_read_DMA6_Y_MODIFY()		bfin_read16(DMA6_Y_MODIFY)
+#define bfin_write_DMA6_Y_MODIFY(val)		bfin_write16(DMA6_Y_MODIFY, val)
+#define bfin_read_DMA6_CURR_DESC_PTR()		bfin_read32(DMA6_CURR_DESC_PTR)
+#define bfin_write_DMA6_CURR_DESC_PTR(val)	bfin_write32(DMA6_CURR_DESC_PTR, val)
+#define bfin_read_DMA6_CURR_ADDR()		bfin_read32(DMA6_CURR_ADDR)
+#define bfin_write_DMA6_CURR_ADDR(val)		bfin_write32(DMA6_CURR_ADDR, val)
+#define bfin_read_DMA6_CURR_X_COUNT()		bfin_read16(DMA6_CURR_X_COUNT)
+#define bfin_write_DMA6_CURR_X_COUNT(val)	bfin_write16(DMA6_CURR_X_COUNT, val)
+#define bfin_read_DMA6_CURR_Y_COUNT()		bfin_read16(DMA6_CURR_Y_COUNT)
+#define bfin_write_DMA6_CURR_Y_COUNT(val)	bfin_write16(DMA6_CURR_Y_COUNT, val)
+#define bfin_read_DMA6_IRQ_STATUS()		bfin_read16(DMA6_IRQ_STATUS)
+#define bfin_write_DMA6_IRQ_STATUS(val)		bfin_write16(DMA6_IRQ_STATUS, val)
+#define bfin_read_DMA6_PERIPHERAL_MAP()		bfin_read16(DMA6_PERIPHERAL_MAP)
+#define bfin_write_DMA6_PERIPHERAL_MAP(val)	bfin_write16(DMA6_PERIPHERAL_MAP, val)
+
+#define bfin_read_DMA7_CONFIG()			bfin_read16(DMA7_CONFIG)
+#define bfin_write_DMA7_CONFIG(val)		bfin_write16(DMA7_CONFIG, val)
+#define bfin_read_DMA7_NEXT_DESC_PTR()		bfin_read32(DMA7_NEXT_DESC_PTR)
+#define bfin_write_DMA7_NEXT_DESC_PTR(val)	bfin_write32(DMA7_NEXT_DESC_PTR, val)
+#define bfin_read_DMA7_START_ADDR()		bfin_read32(DMA7_START_ADDR)
+#define bfin_write_DMA7_START_ADDR(val)		bfin_write32(DMA7_START_ADDR, val)
+#define bfin_read_DMA7_X_COUNT()		bfin_read16(DMA7_X_COUNT)
+#define bfin_write_DMA7_X_COUNT(val)		bfin_write16(DMA7_X_COUNT, val)
+#define bfin_read_DMA7_Y_COUNT()		bfin_read16(DMA7_Y_COUNT)
+#define bfin_write_DMA7_Y_COUNT(val)		bfin_write16(DMA7_Y_COUNT, val)
+#define bfin_read_DMA7_X_MODIFY()		bfin_read16(DMA7_X_MODIFY)
+#define bfin_write_DMA7_X_MODIFY(val)		bfin_write16(DMA7_X_MODIFY, val)
+#define bfin_read_DMA7_Y_MODIFY()		bfin_read16(DMA7_Y_MODIFY)
+#define bfin_write_DMA7_Y_MODIFY(val)		bfin_write16(DMA7_Y_MODIFY, val)
+#define bfin_read_DMA7_CURR_DESC_PTR()		bfin_read32(DMA7_CURR_DESC_PTR)
+#define bfin_write_DMA7_CURR_DESC_PTR(val)	bfin_write32(DMA7_CURR_DESC_PTR, val)
+#define bfin_read_DMA7_CURR_ADDR()		bfin_read32(DMA7_CURR_ADDR)
+#define bfin_write_DMA7_CURR_ADDR(val)		bfin_write32(DMA7_CURR_ADDR, val)
+#define bfin_read_DMA7_CURR_X_COUNT()		bfin_read16(DMA7_CURR_X_COUNT)
+#define bfin_write_DMA7_CURR_X_COUNT(val)	bfin_write16(DMA7_CURR_X_COUNT, val)
+#define bfin_read_DMA7_CURR_Y_COUNT()		bfin_read16(DMA7_CURR_Y_COUNT)
+#define bfin_write_DMA7_CURR_Y_COUNT(val)	bfin_write16(DMA7_CURR_Y_COUNT, val)
+#define bfin_read_DMA7_IRQ_STATUS()		bfin_read16(DMA7_IRQ_STATUS)
+#define bfin_write_DMA7_IRQ_STATUS(val)		bfin_write16(DMA7_IRQ_STATUS, val)
+#define bfin_read_DMA7_PERIPHERAL_MAP()		bfin_read16(DMA7_PERIPHERAL_MAP)
+#define bfin_write_DMA7_PERIPHERAL_MAP(val)	bfin_write16(DMA7_PERIPHERAL_MAP, val)
+
+#define bfin_read_DMA8_CONFIG()			bfin_read16(DMA8_CONFIG)
+#define bfin_write_DMA8_CONFIG(val)		bfin_write16(DMA8_CONFIG, val)
+#define bfin_read_DMA8_NEXT_DESC_PTR()		bfin_read32(DMA8_NEXT_DESC_PTR)
+#define bfin_write_DMA8_NEXT_DESC_PTR(val)	bfin_write32(DMA8_NEXT_DESC_PTR, val)
+#define bfin_read_DMA8_START_ADDR()		bfin_read32(DMA8_START_ADDR)
+#define bfin_write_DMA8_START_ADDR(val)		bfin_write32(DMA8_START_ADDR, val)
+#define bfin_read_DMA8_X_COUNT()		bfin_read16(DMA8_X_COUNT)
+#define bfin_write_DMA8_X_COUNT(val)		bfin_write16(DMA8_X_COUNT, val)
+#define bfin_read_DMA8_Y_COUNT()		bfin_read16(DMA8_Y_COUNT)
+#define bfin_write_DMA8_Y_COUNT(val)		bfin_write16(DMA8_Y_COUNT, val)
+#define bfin_read_DMA8_X_MODIFY()		bfin_read16(DMA8_X_MODIFY)
+#define bfin_write_DMA8_X_MODIFY(val)		bfin_write16(DMA8_X_MODIFY, val)
+#define bfin_read_DMA8_Y_MODIFY()		bfin_read16(DMA8_Y_MODIFY)
+#define bfin_write_DMA8_Y_MODIFY(val)		bfin_write16(DMA8_Y_MODIFY, val)
+#define bfin_read_DMA8_CURR_DESC_PTR()		bfin_read32(DMA8_CURR_DESC_PTR)
+#define bfin_write_DMA8_CURR_DESC_PTR(val)	bfin_write32(DMA8_CURR_DESC_PTR, val)
+#define bfin_read_DMA8_CURR_ADDR()		bfin_read32(DMA8_CURR_ADDR)
+#define bfin_write_DMA8_CURR_ADDR(val)		bfin_write32(DMA8_CURR_ADDR, val)
+#define bfin_read_DMA8_CURR_X_COUNT()		bfin_read16(DMA8_CURR_X_COUNT)
+#define bfin_write_DMA8_CURR_X_COUNT(val)	bfin_write16(DMA8_CURR_X_COUNT, val)
+#define bfin_read_DMA8_CURR_Y_COUNT()		bfin_read16(DMA8_CURR_Y_COUNT)
+#define bfin_write_DMA8_CURR_Y_COUNT(val)	bfin_write16(DMA8_CURR_Y_COUNT, val)
+#define bfin_read_DMA8_IRQ_STATUS()		bfin_read16(DMA8_IRQ_STATUS)
+#define bfin_write_DMA8_IRQ_STATUS(val)		bfin_write16(DMA8_IRQ_STATUS, val)
+#define bfin_read_DMA8_PERIPHERAL_MAP()		bfin_read16(DMA8_PERIPHERAL_MAP)
+#define bfin_write_DMA8_PERIPHERAL_MAP(val)	bfin_write16(DMA8_PERIPHERAL_MAP, val)
+
+#define bfin_read_DMA9_CONFIG()			bfin_read16(DMA9_CONFIG)
+#define bfin_write_DMA9_CONFIG(val)		bfin_write16(DMA9_CONFIG, val)
+#define bfin_read_DMA9_NEXT_DESC_PTR()		bfin_read32(DMA9_NEXT_DESC_PTR)
+#define bfin_write_DMA9_NEXT_DESC_PTR(val)	bfin_write32(DMA9_NEXT_DESC_PTR, val)
+#define bfin_read_DMA9_START_ADDR()		bfin_read32(DMA9_START_ADDR)
+#define bfin_write_DMA9_START_ADDR(val)		bfin_write32(DMA9_START_ADDR, val)
+#define bfin_read_DMA9_X_COUNT()		bfin_read16(DMA9_X_COUNT)
+#define bfin_write_DMA9_X_COUNT(val)		bfin_write16(DMA9_X_COUNT, val)
+#define bfin_read_DMA9_Y_COUNT()		bfin_read16(DMA9_Y_COUNT)
+#define bfin_write_DMA9_Y_COUNT(val)		bfin_write16(DMA9_Y_COUNT, val)
+#define bfin_read_DMA9_X_MODIFY()		bfin_read16(DMA9_X_MODIFY)
+#define bfin_write_DMA9_X_MODIFY(val)		bfin_write16(DMA9_X_MODIFY, val)
+#define bfin_read_DMA9_Y_MODIFY()		bfin_read16(DMA9_Y_MODIFY)
+#define bfin_write_DMA9_Y_MODIFY(val)		bfin_write16(DMA9_Y_MODIFY, val)
+#define bfin_read_DMA9_CURR_DESC_PTR()		bfin_read32(DMA9_CURR_DESC_PTR)
+#define bfin_write_DMA9_CURR_DESC_PTR(val)	bfin_write32(DMA9_CURR_DESC_PTR, val)
+#define bfin_read_DMA9_CURR_ADDR()		bfin_read32(DMA9_CURR_ADDR)
+#define bfin_write_DMA9_CURR_ADDR(val)		bfin_write32(DMA9_CURR_ADDR, val)
+#define bfin_read_DMA9_CURR_X_COUNT()		bfin_read16(DMA9_CURR_X_COUNT)
+#define bfin_write_DMA9_CURR_X_COUNT(val)	bfin_write16(DMA9_CURR_X_COUNT, val)
+#define bfin_read_DMA9_CURR_Y_COUNT()		bfin_read16(DMA9_CURR_Y_COUNT)
+#define bfin_write_DMA9_CURR_Y_COUNT(val)	bfin_write16(DMA9_CURR_Y_COUNT, val)
+#define bfin_read_DMA9_IRQ_STATUS()		bfin_read16(DMA9_IRQ_STATUS)
+#define bfin_write_DMA9_IRQ_STATUS(val)		bfin_write16(DMA9_IRQ_STATUS, val)
+#define bfin_read_DMA9_PERIPHERAL_MAP()		bfin_read16(DMA9_PERIPHERAL_MAP)
+#define bfin_write_DMA9_PERIPHERAL_MAP(val)	bfin_write16(DMA9_PERIPHERAL_MAP, val)
+
+#define bfin_read_DMA10_CONFIG()		bfin_read16(DMA10_CONFIG)
+#define bfin_write_DMA10_CONFIG(val)		bfin_write16(DMA10_CONFIG, val)
+#define bfin_read_DMA10_NEXT_DESC_PTR()		bfin_read32(DMA10_NEXT_DESC_PTR)
+#define bfin_write_DMA10_NEXT_DESC_PTR(val)	bfin_write32(DMA10_NEXT_DESC_PTR, val)
+#define bfin_read_DMA10_START_ADDR()		bfin_read32(DMA10_START_ADDR)
+#define bfin_write_DMA10_START_ADDR(val)	bfin_write32(DMA10_START_ADDR, val)
+#define bfin_read_DMA10_X_COUNT()		bfin_read16(DMA10_X_COUNT)
+#define bfin_write_DMA10_X_COUNT(val)		bfin_write16(DMA10_X_COUNT, val)
+#define bfin_read_DMA10_Y_COUNT()		bfin_read16(DMA10_Y_COUNT)
+#define bfin_write_DMA10_Y_COUNT(val)		bfin_write16(DMA10_Y_COUNT, val)
+#define bfin_read_DMA10_X_MODIFY()		bfin_read16(DMA10_X_MODIFY)
+#define bfin_write_DMA10_X_MODIFY(val)		bfin_write16(DMA10_X_MODIFY, val)
+#define bfin_read_DMA10_Y_MODIFY()		bfin_read16(DMA10_Y_MODIFY)
+#define bfin_write_DMA10_Y_MODIFY(val)		bfin_write16(DMA10_Y_MODIFY, val)
+#define bfin_read_DMA10_CURR_DESC_PTR()		bfin_read32(DMA10_CURR_DESC_PTR)
+#define bfin_write_DMA10_CURR_DESC_PTR(val)	bfin_write32(DMA10_CURR_DESC_PTR, val)
+#define bfin_read_DMA10_CURR_ADDR()		bfin_read32(DMA10_CURR_ADDR)
+#define bfin_write_DMA10_CURR_ADDR(val)		bfin_write32(DMA10_CURR_ADDR, val)
+#define bfin_read_DMA10_CURR_X_COUNT()		bfin_read16(DMA10_CURR_X_COUNT)
+#define bfin_write_DMA10_CURR_X_COUNT(val)	bfin_write16(DMA10_CURR_X_COUNT, val)
+#define bfin_read_DMA10_CURR_Y_COUNT()		bfin_read16(DMA10_CURR_Y_COUNT)
+#define bfin_write_DMA10_CURR_Y_COUNT(val)	bfin_write16(DMA10_CURR_Y_COUNT, val)
+#define bfin_read_DMA10_IRQ_STATUS()		bfin_read16(DMA10_IRQ_STATUS)
+#define bfin_write_DMA10_IRQ_STATUS(val)	bfin_write16(DMA10_IRQ_STATUS, val)
+#define bfin_read_DMA10_PERIPHERAL_MAP()	bfin_read16(DMA10_PERIPHERAL_MAP)
+#define bfin_write_DMA10_PERIPHERAL_MAP(val)	bfin_write16(DMA10_PERIPHERAL_MAP, val)
+
+#define bfin_read_DMA11_CONFIG()		bfin_read16(DMA11_CONFIG)
+#define bfin_write_DMA11_CONFIG(val)		bfin_write16(DMA11_CONFIG, val)
+#define bfin_read_DMA11_NEXT_DESC_PTR()		bfin_read32(DMA11_NEXT_DESC_PTR)
+#define bfin_write_DMA11_NEXT_DESC_PTR(val)	bfin_write32(DMA11_NEXT_DESC_PTR, val)
+#define bfin_read_DMA11_START_ADDR()		bfin_read32(DMA11_START_ADDR)
+#define bfin_write_DMA11_START_ADDR(val)	bfin_write32(DMA11_START_ADDR, val)
+#define bfin_read_DMA11_X_COUNT()		bfin_read16(DMA11_X_COUNT)
+#define bfin_write_DMA11_X_COUNT(val)		bfin_write16(DMA11_X_COUNT, val)
+#define bfin_read_DMA11_Y_COUNT()		bfin_read16(DMA11_Y_COUNT)
+#define bfin_write_DMA11_Y_COUNT(val)		bfin_write16(DMA11_Y_COUNT, val)
+#define bfin_read_DMA11_X_MODIFY()		bfin_read16(DMA11_X_MODIFY)
+#define bfin_write_DMA11_X_MODIFY(val)		bfin_write16(DMA11_X_MODIFY, val)
+#define bfin_read_DMA11_Y_MODIFY()		bfin_read16(DMA11_Y_MODIFY)
+#define bfin_write_DMA11_Y_MODIFY(val)		bfin_write16(DMA11_Y_MODIFY, val)
+#define bfin_read_DMA11_CURR_DESC_PTR()		bfin_read32(DMA11_CURR_DESC_PTR)
+#define bfin_write_DMA11_CURR_DESC_PTR(val)	bfin_write32(DMA11_CURR_DESC_PTR, val)
+#define bfin_read_DMA11_CURR_ADDR()		bfin_read32(DMA11_CURR_ADDR)
+#define bfin_write_DMA11_CURR_ADDR(val)		bfin_write32(DMA11_CURR_ADDR, val)
+#define bfin_read_DMA11_CURR_X_COUNT()		bfin_read16(DMA11_CURR_X_COUNT)
+#define bfin_write_DMA11_CURR_X_COUNT(val)	bfin_write16(DMA11_CURR_X_COUNT, val)
+#define bfin_read_DMA11_CURR_Y_COUNT()		bfin_read16(DMA11_CURR_Y_COUNT)
+#define bfin_write_DMA11_CURR_Y_COUNT(val)	bfin_write16(DMA11_CURR_Y_COUNT, val)
+#define bfin_read_DMA11_IRQ_STATUS()		bfin_read16(DMA11_IRQ_STATUS)
+#define bfin_write_DMA11_IRQ_STATUS(val)	bfin_write16(DMA11_IRQ_STATUS, val)
+#define bfin_read_DMA11_PERIPHERAL_MAP()	bfin_read16(DMA11_PERIPHERAL_MAP)
+#define bfin_write_DMA11_PERIPHERAL_MAP(val)	bfin_write16(DMA11_PERIPHERAL_MAP, val)
+
+#define bfin_read_MDMA_D0_CONFIG()		bfin_read16(MDMA_D0_CONFIG)
+#define bfin_write_MDMA_D0_CONFIG(val)		bfin_write16(MDMA_D0_CONFIG, val)
+#define bfin_read_MDMA_D0_NEXT_DESC_PTR()	bfin_read32(MDMA_D0_NEXT_DESC_PTR)
+#define bfin_write_MDMA_D0_NEXT_DESC_PTR(val)	bfin_write32(MDMA_D0_NEXT_DESC_PTR, val)
+#define bfin_read_MDMA_D0_START_ADDR()		bfin_read32(MDMA_D0_START_ADDR)
+#define bfin_write_MDMA_D0_START_ADDR(val)	bfin_write32(MDMA_D0_START_ADDR, val)
+#define bfin_read_MDMA_D0_X_COUNT()		bfin_read16(MDMA_D0_X_COUNT)
+#define bfin_write_MDMA_D0_X_COUNT(val)		bfin_write16(MDMA_D0_X_COUNT, val)
+#define bfin_read_MDMA_D0_Y_COUNT()		bfin_read16(MDMA_D0_Y_COUNT)
+#define bfin_write_MDMA_D0_Y_COUNT(val)		bfin_write16(MDMA_D0_Y_COUNT, val)
+#define bfin_read_MDMA_D0_X_MODIFY()		bfin_read16(MDMA_D0_X_MODIFY)
+#define bfin_write_MDMA_D0_X_MODIFY(val)	bfin_write16(MDMA_D0_X_MODIFY, val)
+#define bfin_read_MDMA_D0_Y_MODIFY()		bfin_read16(MDMA_D0_Y_MODIFY)
+#define bfin_write_MDMA_D0_Y_MODIFY(val)	bfin_write16(MDMA_D0_Y_MODIFY, val)
+#define bfin_read_MDMA_D0_CURR_DESC_PTR()	bfin_read32(MDMA_D0_CURR_DESC_PTR)
+#define bfin_write_MDMA_D0_CURR_DESC_PTR(val)	bfin_write32(MDMA_D0_CURR_DESC_PTR, val)
+#define bfin_read_MDMA_D0_CURR_ADDR()		bfin_read32(MDMA_D0_CURR_ADDR)
+#define bfin_write_MDMA_D0_CURR_ADDR(val)	bfin_write32(MDMA_D0_CURR_ADDR, val)
+#define bfin_read_MDMA_D0_CURR_X_COUNT()	bfin_read16(MDMA_D0_CURR_X_COUNT)
+#define bfin_write_MDMA_D0_CURR_X_COUNT(val)	bfin_write16(MDMA_D0_CURR_X_COUNT, val)
+#define bfin_read_MDMA_D0_CURR_Y_COUNT()	bfin_read16(MDMA_D0_CURR_Y_COUNT)
+#define bfin_write_MDMA_D0_CURR_Y_COUNT(val)	bfin_write16(MDMA_D0_CURR_Y_COUNT, val)
+#define bfin_read_MDMA_D0_IRQ_STATUS()		bfin_read16(MDMA_D0_IRQ_STATUS)
+#define bfin_write_MDMA_D0_IRQ_STATUS(val)	bfin_write16(MDMA_D0_IRQ_STATUS, val)
+#define bfin_read_MDMA_D0_PERIPHERAL_MAP()	bfin_read16(MDMA_D0_PERIPHERAL_MAP)
+#define bfin_write_MDMA_D0_PERIPHERAL_MAP(val)	bfin_write16(MDMA_D0_PERIPHERAL_MAP, val)
+
+#define bfin_read_MDMA_S0_CONFIG()		bfin_read16(MDMA_S0_CONFIG)
+#define bfin_write_MDMA_S0_CONFIG(val)		bfin_write16(MDMA_S0_CONFIG, val)
+#define bfin_read_MDMA_S0_NEXT_DESC_PTR()	bfin_read32(MDMA_S0_NEXT_DESC_PTR)
+#define bfin_write_MDMA_S0_NEXT_DESC_PTR(val)	bfin_write32(MDMA_S0_NEXT_DESC_PTR, val)
+#define bfin_read_MDMA_S0_START_ADDR()		bfin_read32(MDMA_S0_START_ADDR)
+#define bfin_write_MDMA_S0_START_ADDR(val)	bfin_write32(MDMA_S0_START_ADDR, val)
+#define bfin_read_MDMA_S0_X_COUNT()		bfin_read16(MDMA_S0_X_COUNT)
+#define bfin_write_MDMA_S0_X_COUNT(val)		bfin_write16(MDMA_S0_X_COUNT, val)
+#define bfin_read_MDMA_S0_Y_COUNT()		bfin_read16(MDMA_S0_Y_COUNT)
+#define bfin_write_MDMA_S0_Y_COUNT(val)		bfin_write16(MDMA_S0_Y_COUNT, val)
+#define bfin_read_MDMA_S0_X_MODIFY()		bfin_read16(MDMA_S0_X_MODIFY)
+#define bfin_write_MDMA_S0_X_MODIFY(val)	bfin_write16(MDMA_S0_X_MODIFY, val)
+#define bfin_read_MDMA_S0_Y_MODIFY()		bfin_read16(MDMA_S0_Y_MODIFY)
+#define bfin_write_MDMA_S0_Y_MODIFY(val)	bfin_write16(MDMA_S0_Y_MODIFY, val)
+#define bfin_read_MDMA_S0_CURR_DESC_PTR()	bfin_read32(MDMA_S0_CURR_DESC_PTR)
+#define bfin_write_MDMA_S0_CURR_DESC_PTR(val)	bfin_write32(MDMA_S0_CURR_DESC_PTR, val)
+#define bfin_read_MDMA_S0_CURR_ADDR()		bfin_read32(MDMA_S0_CURR_ADDR)
+#define bfin_write_MDMA_S0_CURR_ADDR(val)	bfin_write32(MDMA_S0_CURR_ADDR, val)
+#define bfin_read_MDMA_S0_CURR_X_COUNT()	bfin_read16(MDMA_S0_CURR_X_COUNT)
+#define bfin_write_MDMA_S0_CURR_X_COUNT(val)	bfin_write16(MDMA_S0_CURR_X_COUNT, val)
+#define bfin_read_MDMA_S0_CURR_Y_COUNT()	bfin_read16(MDMA_S0_CURR_Y_COUNT)
+#define bfin_write_MDMA_S0_CURR_Y_COUNT(val)	bfin_write16(MDMA_S0_CURR_Y_COUNT, val)
+#define bfin_read_MDMA_S0_IRQ_STATUS()		bfin_read16(MDMA_S0_IRQ_STATUS)
+#define bfin_write_MDMA_S0_IRQ_STATUS(val)	bfin_write16(MDMA_S0_IRQ_STATUS, val)
+#define bfin_read_MDMA_S0_PERIPHERAL_MAP()	bfin_read16(MDMA_S0_PERIPHERAL_MAP)
+#define bfin_write_MDMA_S0_PERIPHERAL_MAP(val)	bfin_write16(MDMA_S0_PERIPHERAL_MAP, val)
+
+#define bfin_read_MDMA_D1_CONFIG()		bfin_read16(MDMA_D1_CONFIG)
+#define bfin_write_MDMA_D1_CONFIG(val)		bfin_write16(MDMA_D1_CONFIG, val)
+#define bfin_read_MDMA_D1_NEXT_DESC_PTR()	bfin_read32(MDMA_D1_NEXT_DESC_PTR)
+#define bfin_write_MDMA_D1_NEXT_DESC_PTR(val)	bfin_write32(MDMA_D1_NEXT_DESC_PTR, val)
+#define bfin_read_MDMA_D1_START_ADDR()		bfin_read32(MDMA_D1_START_ADDR)
+#define bfin_write_MDMA_D1_START_ADDR(val)	bfin_write32(MDMA_D1_START_ADDR, val)
+#define bfin_read_MDMA_D1_X_COUNT()		bfin_read16(MDMA_D1_X_COUNT)
+#define bfin_write_MDMA_D1_X_COUNT(val)		bfin_write16(MDMA_D1_X_COUNT, val)
+#define bfin_read_MDMA_D1_Y_COUNT()		bfin_read16(MDMA_D1_Y_COUNT)
+#define bfin_write_MDMA_D1_Y_COUNT(val)		bfin_write16(MDMA_D1_Y_COUNT, val)
+#define bfin_read_MDMA_D1_X_MODIFY()		bfin_read16(MDMA_D1_X_MODIFY)
+#define bfin_write_MDMA_D1_X_MODIFY(val)	bfin_write16(MDMA_D1_X_MODIFY, val)
+#define bfin_read_MDMA_D1_Y_MODIFY()		bfin_read16(MDMA_D1_Y_MODIFY)
+#define bfin_write_MDMA_D1_Y_MODIFY(val)	bfin_write16(MDMA_D1_Y_MODIFY, val)
+#define bfin_read_MDMA_D1_CURR_DESC_PTR()	bfin_read32(MDMA_D1_CURR_DESC_PTR)
+#define bfin_write_MDMA_D1_CURR_DESC_PTR(val)	bfin_write32(MDMA_D1_CURR_DESC_PTR, val)
+#define bfin_read_MDMA_D1_CURR_ADDR()		bfin_read32(MDMA_D1_CURR_ADDR)
+#define bfin_write_MDMA_D1_CURR_ADDR(val)	bfin_write32(MDMA_D1_CURR_ADDR, val)
+#define bfin_read_MDMA_D1_CURR_X_COUNT()	bfin_read16(MDMA_D1_CURR_X_COUNT)
+#define bfin_write_MDMA_D1_CURR_X_COUNT(val)	bfin_write16(MDMA_D1_CURR_X_COUNT, val)
+#define bfin_read_MDMA_D1_CURR_Y_COUNT()	bfin_read16(MDMA_D1_CURR_Y_COUNT)
+#define bfin_write_MDMA_D1_CURR_Y_COUNT(val)	bfin_write16(MDMA_D1_CURR_Y_COUNT, val)
+#define bfin_read_MDMA_D1_IRQ_STATUS()		bfin_read16(MDMA_D1_IRQ_STATUS)
+#define bfin_write_MDMA_D1_IRQ_STATUS(val)	bfin_write16(MDMA_D1_IRQ_STATUS, val)
+#define bfin_read_MDMA_D1_PERIPHERAL_MAP()	bfin_read16(MDMA_D1_PERIPHERAL_MAP)
+#define bfin_write_MDMA_D1_PERIPHERAL_MAP(val)	bfin_write16(MDMA_D1_PERIPHERAL_MAP, val)
+
+#define bfin_read_MDMA_S1_CONFIG()		bfin_read16(MDMA_S1_CONFIG)
+#define bfin_write_MDMA_S1_CONFIG(val)		bfin_write16(MDMA_S1_CONFIG, val)
+#define bfin_read_MDMA_S1_NEXT_DESC_PTR()	bfin_read32(MDMA_S1_NEXT_DESC_PTR)
+#define bfin_write_MDMA_S1_NEXT_DESC_PTR(val)	bfin_write32(MDMA_S1_NEXT_DESC_PTR, val)
+#define bfin_read_MDMA_S1_START_ADDR()		bfin_read32(MDMA_S1_START_ADDR)
+#define bfin_write_MDMA_S1_START_ADDR(val)	bfin_write32(MDMA_S1_START_ADDR, val)
+#define bfin_read_MDMA_S1_X_COUNT()		bfin_read16(MDMA_S1_X_COUNT)
+#define bfin_write_MDMA_S1_X_COUNT(val)		bfin_write16(MDMA_S1_X_COUNT, val)
+#define bfin_read_MDMA_S1_Y_COUNT()		bfin_read16(MDMA_S1_Y_COUNT)
+#define bfin_write_MDMA_S1_Y_COUNT(val)		bfin_write16(MDMA_S1_Y_COUNT, val)
+#define bfin_read_MDMA_S1_X_MODIFY()		bfin_read16(MDMA_S1_X_MODIFY)
+#define bfin_write_MDMA_S1_X_MODIFY(val)	bfin_write16(MDMA_S1_X_MODIFY, val)
+#define bfin_read_MDMA_S1_Y_MODIFY()		bfin_read16(MDMA_S1_Y_MODIFY)
+#define bfin_write_MDMA_S1_Y_MODIFY(val)	bfin_write16(MDMA_S1_Y_MODIFY, val)
+#define bfin_read_MDMA_S1_CURR_DESC_PTR()	bfin_read32(MDMA_S1_CURR_DESC_PTR)
+#define bfin_write_MDMA_S1_CURR_DESC_PTR(val)	bfin_write32(MDMA_S1_CURR_DESC_PTR, val)
+#define bfin_read_MDMA_S1_CURR_ADDR()		bfin_read32(MDMA_S1_CURR_ADDR)
+#define bfin_write_MDMA_S1_CURR_ADDR(val)	bfin_write32(MDMA_S1_CURR_ADDR, val)
+#define bfin_read_MDMA_S1_CURR_X_COUNT()	bfin_read16(MDMA_S1_CURR_X_COUNT)
+#define bfin_write_MDMA_S1_CURR_X_COUNT(val)	bfin_write16(MDMA_S1_CURR_X_COUNT, val)
+#define bfin_read_MDMA_S1_CURR_Y_COUNT()	bfin_read16(MDMA_S1_CURR_Y_COUNT)
+#define bfin_write_MDMA_S1_CURR_Y_COUNT(val)	bfin_write16(MDMA_S1_CURR_Y_COUNT, val)
+#define bfin_read_MDMA_S1_IRQ_STATUS()		bfin_read16(MDMA_S1_IRQ_STATUS)
+#define bfin_write_MDMA_S1_IRQ_STATUS(val)	bfin_write16(MDMA_S1_IRQ_STATUS, val)
+#define bfin_read_MDMA_S1_PERIPHERAL_MAP()	bfin_read16(MDMA_S1_PERIPHERAL_MAP)
+#define bfin_write_MDMA_S1_PERIPHERAL_MAP(val)	bfin_write16(MDMA_S1_PERIPHERAL_MAP, val)
+
+
+/* Parallel Peripheral Interface (0xFFC01000 - 0xFFC010FF)							*/
+#define bfin_read_PPI_CONTROL()			bfin_read16(PPI_CONTROL)
+#define bfin_write_PPI_CONTROL(val)		bfin_write16(PPI_CONTROL, val)
+#define bfin_read_PPI_STATUS()			bfin_read16(PPI_STATUS)
+#define bfin_write_PPI_STATUS(val)		bfin_write16(PPI_STATUS, val)
+#define bfin_clear_PPI_STATUS()			bfin_write_PPI_STATUS(0xFFFF)
+#define bfin_read_PPI_DELAY()			bfin_read16(PPI_DELAY)
+#define bfin_write_PPI_DELAY(val)		bfin_write16(PPI_DELAY, val)
+#define bfin_read_PPI_COUNT()			bfin_read16(PPI_COUNT)
+#define bfin_write_PPI_COUNT(val)		bfin_write16(PPI_COUNT, val)
+#define bfin_read_PPI_FRAME()			bfin_read16(PPI_FRAME)
+#define bfin_write_PPI_FRAME(val)		bfin_write16(PPI_FRAME, val)
+
+
+/* Two-Wire Interface		(0xFFC01400 - 0xFFC014FF)								*/
+
+/* General Purpose I/O Port G (0xFFC01500 - 0xFFC015FF)								*/
+#define bfin_read_PORTGIO()			bfin_read16(PORTGIO)
+#define bfin_write_PORTGIO(val)			bfin_write16(PORTGIO, val)
+#define bfin_read_PORTGIO_CLEAR()		bfin_read16(PORTGIO_CLEAR)
+#define bfin_write_PORTGIO_CLEAR(val)		bfin_write16(PORTGIO_CLEAR, val)
+#define bfin_read_PORTGIO_SET()			bfin_read16(PORTGIO_SET)
+#define bfin_write_PORTGIO_SET(val)		bfin_write16(PORTGIO_SET, val)
+#define bfin_read_PORTGIO_TOGGLE()		bfin_read16(PORTGIO_TOGGLE)
+#define bfin_write_PORTGIO_TOGGLE(val)		bfin_write16(PORTGIO_TOGGLE, val)
+#define bfin_read_PORTGIO_MASKA()		bfin_read16(PORTGIO_MASKA)
+#define bfin_write_PORTGIO_MASKA(val)		bfin_write16(PORTGIO_MASKA, val)
+#define bfin_read_PORTGIO_MASKA_CLEAR()		bfin_read16(PORTGIO_MASKA_CLEAR)
+#define bfin_write_PORTGIO_MASKA_CLEAR(val)	bfin_write16(PORTGIO_MASKA_CLEAR, val)
+#define bfin_read_PORTGIO_MASKA_SET()		bfin_read16(PORTGIO_MASKA_SET)
+#define bfin_write_PORTGIO_MASKA_SET(val)	bfin_write16(PORTGIO_MASKA_SET, val)
+#define bfin_read_PORTGIO_MASKA_TOGGLE()	bfin_read16(PORTGIO_MASKA_TOGGLE)
+#define bfin_write_PORTGIO_MASKA_TOGGLE(val)	bfin_write16(PORTGIO_MASKA_TOGGLE, val)
+#define bfin_read_PORTGIO_MASKB()		bfin_read16(PORTGIO_MASKB)
+#define bfin_write_PORTGIO_MASKB(val)		bfin_write16(PORTGIO_MASKB, val)
+#define bfin_read_PORTGIO_MASKB_CLEAR()		bfin_read16(PORTGIO_MASKB_CLEAR)
+#define bfin_write_PORTGIO_MASKB_CLEAR(val)	bfin_write16(PORTGIO_MASKB_CLEAR, val)
+#define bfin_read_PORTGIO_MASKB_SET()		bfin_read16(PORTGIO_MASKB_SET)
+#define bfin_write_PORTGIO_MASKB_SET(val)	bfin_write16(PORTGIO_MASKB_SET, val)
+#define bfin_read_PORTGIO_MASKB_TOGGLE()	bfin_read16(PORTGIO_MASKB_TOGGLE)
+#define bfin_write_PORTGIO_MASKB_TOGGLE(val)	bfin_write16(PORTGIO_MASKB_TOGGLE, val)
+#define bfin_read_PORTGIO_DIR()			bfin_read16(PORTGIO_DIR)
+#define bfin_write_PORTGIO_DIR(val)		bfin_write16(PORTGIO_DIR, val)
+#define bfin_read_PORTGIO_POLAR()		bfin_read16(PORTGIO_POLAR)
+#define bfin_write_PORTGIO_POLAR(val)		bfin_write16(PORTGIO_POLAR, val)
+#define bfin_read_PORTGIO_EDGE()		bfin_read16(PORTGIO_EDGE)
+#define bfin_write_PORTGIO_EDGE(val)		bfin_write16(PORTGIO_EDGE, val)
+#define bfin_read_PORTGIO_BOTH()		bfin_read16(PORTGIO_BOTH)
+#define bfin_write_PORTGIO_BOTH(val)		bfin_write16(PORTGIO_BOTH, val)
+#define bfin_read_PORTGIO_INEN()		bfin_read16(PORTGIO_INEN)
+#define bfin_write_PORTGIO_INEN(val)		bfin_write16(PORTGIO_INEN, val)
+
+
+/* General Purpose I/O Port H (0xFFC01700 - 0xFFC017FF)								*/
+#define bfin_read_PORTHIO()			bfin_read16(PORTHIO)
+#define bfin_write_PORTHIO(val)			bfin_write16(PORTHIO, val)
+#define bfin_read_PORTHIO_CLEAR()		bfin_read16(PORTHIO_CLEAR)
+#define bfin_write_PORTHIO_CLEAR(val)		bfin_write16(PORTHIO_CLEAR, val)
+#define bfin_read_PORTHIO_SET()			bfin_read16(PORTHIO_SET)
+#define bfin_write_PORTHIO_SET(val)		bfin_write16(PORTHIO_SET, val)
+#define bfin_read_PORTHIO_TOGGLE()		bfin_read16(PORTHIO_TOGGLE)
+#define bfin_write_PORTHIO_TOGGLE(val)		bfin_write16(PORTHIO_TOGGLE, val)
+#define bfin_read_PORTHIO_MASKA()		bfin_read16(PORTHIO_MASKA)
+#define bfin_write_PORTHIO_MASKA(val)		bfin_write16(PORTHIO_MASKA, val)
+#define bfin_read_PORTHIO_MASKA_CLEAR()		bfin_read16(PORTHIO_MASKA_CLEAR)
+#define bfin_write_PORTHIO_MASKA_CLEAR(val)	bfin_write16(PORTHIO_MASKA_CLEAR, val)
+#define bfin_read_PORTHIO_MASKA_SET()		bfin_read16(PORTHIO_MASKA_SET)
+#define bfin_write_PORTHIO_MASKA_SET(val)	bfin_write16(PORTHIO_MASKA_SET, val)
+#define bfin_read_PORTHIO_MASKA_TOGGLE()	bfin_read16(PORTHIO_MASKA_TOGGLE)
+#define bfin_write_PORTHIO_MASKA_TOGGLE(val)	bfin_write16(PORTHIO_MASKA_TOGGLE, val)
+#define bfin_read_PORTHIO_MASKB()		bfin_read16(PORTHIO_MASKB)
+#define bfin_write_PORTHIO_MASKB(val)		bfin_write16(PORTHIO_MASKB, val)
+#define bfin_read_PORTHIO_MASKB_CLEAR()		bfin_read16(PORTHIO_MASKB_CLEAR)
+#define bfin_write_PORTHIO_MASKB_CLEAR(val)	bfin_write16(PORTHIO_MASKB_CLEAR, val)
+#define bfin_read_PORTHIO_MASKB_SET()		bfin_read16(PORTHIO_MASKB_SET)
+#define bfin_write_PORTHIO_MASKB_SET(val)	bfin_write16(PORTHIO_MASKB_SET, val)
+#define bfin_read_PORTHIO_MASKB_TOGGLE()	bfin_read16(PORTHIO_MASKB_TOGGLE)
+#define bfin_write_PORTHIO_MASKB_TOGGLE(val)	bfin_write16(PORTHIO_MASKB_TOGGLE, val)
+#define bfin_read_PORTHIO_DIR()			bfin_read16(PORTHIO_DIR)
+#define bfin_write_PORTHIO_DIR(val)		bfin_write16(PORTHIO_DIR, val)
+#define bfin_read_PORTHIO_POLAR()		bfin_read16(PORTHIO_POLAR)
+#define bfin_write_PORTHIO_POLAR(val)		bfin_write16(PORTHIO_POLAR, val)
+#define bfin_read_PORTHIO_EDGE()		bfin_read16(PORTHIO_EDGE)
+#define bfin_write_PORTHIO_EDGE(val)		bfin_write16(PORTHIO_EDGE, val)
+#define bfin_read_PORTHIO_BOTH()		bfin_read16(PORTHIO_BOTH)
+#define bfin_write_PORTHIO_BOTH(val)		bfin_write16(PORTHIO_BOTH, val)
+#define bfin_read_PORTHIO_INEN()		bfin_read16(PORTHIO_INEN)
+#define bfin_write_PORTHIO_INEN(val)		bfin_write16(PORTHIO_INEN, val)
+
+
+/* UART1 Controller		(0xFFC02000 - 0xFFC020FF)								*/
+#define bfin_read_UART1_THR()			bfin_read16(UART1_THR)
+#define bfin_write_UART1_THR(val)		bfin_write16(UART1_THR, val)
+#define bfin_read_UART1_RBR()			bfin_read16(UART1_RBR)
+#define bfin_write_UART1_RBR(val)		bfin_write16(UART1_RBR, val)
+#define bfin_read_UART1_DLL()			bfin_read16(UART1_DLL)
+#define bfin_write_UART1_DLL(val)		bfin_write16(UART1_DLL, val)
+#define bfin_read_UART1_IER()			bfin_read16(UART1_IER)
+#define bfin_write_UART1_IER(val)		bfin_write16(UART1_IER, val)
+#define bfin_read_UART1_DLH()			bfin_read16(UART1_DLH)
+#define bfin_write_UART1_DLH(val)		bfin_write16(UART1_DLH, val)
+#define bfin_read_UART1_IIR()			bfin_read16(UART1_IIR)
+#define bfin_write_UART1_IIR(val)		bfin_write16(UART1_IIR, val)
+#define bfin_read_UART1_LCR()			bfin_read16(UART1_LCR)
+#define bfin_write_UART1_LCR(val)		bfin_write16(UART1_LCR, val)
+#define bfin_read_UART1_MCR()			bfin_read16(UART1_MCR)
+#define bfin_write_UART1_MCR(val)		bfin_write16(UART1_MCR, val)
+#define bfin_read_UART1_LSR()			bfin_read16(UART1_LSR)
+#define bfin_write_UART1_LSR(val)		bfin_write16(UART1_LSR, val)
+#define bfin_read_UART1_MSR()			bfin_read16(UART1_MSR)
+#define bfin_write_UART1_MSR(val)		bfin_write16(UART1_MSR, val)
+#define bfin_read_UART1_SCR()			bfin_read16(UART1_SCR)
+#define bfin_write_UART1_SCR(val)		bfin_write16(UART1_SCR, val)
+#define bfin_read_UART1_GCTL()			bfin_read16(UART1_GCTL)
+#define bfin_write_UART1_GCTL(val)		bfin_write16(UART1_GCTL, val)
+
+/* Omit CAN register sets from the cdefBF534.h (CAN is not in the ADSP-BF51x processor) */
+
+/* Pin Control Registers	(0xFFC03200 - 0xFFC032FF)								*/
+#define bfin_read_PORTF_FER()			bfin_read16(PORTF_FER)
+#define bfin_write_PORTF_FER(val)		bfin_write16(PORTF_FER, val)
+#define bfin_read_PORTG_FER()			bfin_read16(PORTG_FER)
+#define bfin_write_PORTG_FER(val)		bfin_write16(PORTG_FER, val)
+#define bfin_read_PORTH_FER()			bfin_read16(PORTH_FER)
+#define bfin_write_PORTH_FER(val)		bfin_write16(PORTH_FER, val)
+#define bfin_read_PORT_MUX()			bfin_read16(PORT_MUX)
+#define bfin_write_PORT_MUX(val)		bfin_write16(PORT_MUX, val)
+
+
+/* Handshake MDMA Registers	(0xFFC03300 - 0xFFC033FF)								*/
+#define bfin_read_HMDMA0_CONTROL()		bfin_read16(HMDMA0_CONTROL)
+#define bfin_write_HMDMA0_CONTROL(val)		bfin_write16(HMDMA0_CONTROL, val)
+#define bfin_read_HMDMA0_ECINIT()		bfin_read16(HMDMA0_ECINIT)
+#define bfin_write_HMDMA0_ECINIT(val)		bfin_write16(HMDMA0_ECINIT, val)
+#define bfin_read_HMDMA0_BCINIT()		bfin_read16(HMDMA0_BCINIT)
+#define bfin_write_HMDMA0_BCINIT(val)		bfin_write16(HMDMA0_BCINIT, val)
+#define bfin_read_HMDMA0_ECURGENT()		bfin_read16(HMDMA0_ECURGENT)
+#define bfin_write_HMDMA0_ECURGENT(val)		bfin_write16(HMDMA0_ECURGENT, val)
+#define bfin_read_HMDMA0_ECOVERFLOW()		bfin_read16(HMDMA0_ECOVERFLOW)
+#define bfin_write_HMDMA0_ECOVERFLOW(val)	bfin_write16(HMDMA0_ECOVERFLOW, val)
+#define bfin_read_HMDMA0_ECOUNT()		bfin_read16(HMDMA0_ECOUNT)
+#define bfin_write_HMDMA0_ECOUNT(val)		bfin_write16(HMDMA0_ECOUNT, val)
+#define bfin_read_HMDMA0_BCOUNT()		bfin_read16(HMDMA0_BCOUNT)
+#define bfin_write_HMDMA0_BCOUNT(val)		bfin_write16(HMDMA0_BCOUNT, val)
+
+#define bfin_read_HMDMA1_CONTROL()		bfin_read16(HMDMA1_CONTROL)
+#define bfin_write_HMDMA1_CONTROL(val)		bfin_write16(HMDMA1_CONTROL, val)
+#define bfin_read_HMDMA1_ECINIT()		bfin_read16(HMDMA1_ECINIT)
+#define bfin_write_HMDMA1_ECINIT(val)		bfin_write16(HMDMA1_ECINIT, val)
+#define bfin_read_HMDMA1_BCINIT()		bfin_read16(HMDMA1_BCINIT)
+#define bfin_write_HMDMA1_BCINIT(val)		bfin_write16(HMDMA1_BCINIT, val)
+#define bfin_read_HMDMA1_ECURGENT()		bfin_read16(HMDMA1_ECURGENT)
+#define bfin_write_HMDMA1_ECURGENT(val)		bfin_write16(HMDMA1_ECURGENT, val)
+#define bfin_read_HMDMA1_ECOVERFLOW()		bfin_read16(HMDMA1_ECOVERFLOW)
+#define bfin_write_HMDMA1_ECOVERFLOW(val)	bfin_write16(HMDMA1_ECOVERFLOW, val)
+#define bfin_read_HMDMA1_ECOUNT()		bfin_read16(HMDMA1_ECOUNT)
+#define bfin_write_HMDMA1_ECOUNT(val)		bfin_write16(HMDMA1_ECOUNT, val)
+#define bfin_read_HMDMA1_BCOUNT()		bfin_read16(HMDMA1_BCOUNT)
+#define bfin_write_HMDMA1_BCOUNT(val)		bfin_write16(HMDMA1_BCOUNT, val)
+
+/* ==== end from cdefBF534.h ==== */
+
+/* GPIO PIN mux (0xFFC03210 - OxFFC03288) */
+
+#define bfin_read_PORTF_MUX()			bfin_read16(PORTF_MUX)
+#define bfin_write_PORTF_MUX(val)		bfin_write16(PORTF_MUX, val)
+#define bfin_read_PORTG_MUX()			bfin_read16(PORTG_MUX)
+#define bfin_write_PORTG_MUX(val)		bfin_write16(PORTG_MUX, val)
+#define bfin_read_PORTH_MUX()			bfin_read16(PORTH_MUX)
+#define bfin_write_PORTH_MUX(val)		bfin_write16(PORTH_MUX, val)
+
+#define bfin_read_PORTF_DRIVE()			bfin_read16(PORTF_DRIVE)
+#define bfin_write_PORTF_DRIVE(val)		bfin_write16(PORTF_DRIVE, val)
+#define bfin_read_PORTG_DRIVE()			bfin_read16(PORTG_DRIVE)
+#define bfin_write_PORTG_DRIVE(val)		bfin_write16(PORTG_DRIVE, val)
+#define bfin_read_PORTH_DRIVE()			bfin_read16(PORTH_DRIVE)
+#define bfin_write_PORTH_DRIVE(val)		bfin_write16(PORTH_DRIVE, val)
+#define bfin_read_PORTF_SLEW()			bfin_read16(PORTF_SLEW)
+#define bfin_write_PORTF_SLEW(val)		bfin_write16(PORTF_SLEW, val)
+#define bfin_read_PORTG_SLEW()			bfin_read16(PORTG_SLEW)
+#define bfin_write_PORTG_SLEW(val)		bfin_write16(PORTG_SLEW, val)
+#define bfin_read_PORTH_SLEW()			bfin_read16(PORTH_SLEW)
+#define bfin_write_PORTH_SLEW(val)		bfin_write16(PORTH_SLEW, val)
+#define bfin_read_PORTF_HYSTERISIS()		bfin_read16(PORTF_HYSTERISIS)
+#define bfin_write_PORTF_HYSTERISIS(val)	bfin_write16(PORTF_HYSTERISIS, val)
+#define bfin_read_PORTG_HYSTERISIS()		bfin_read16(PORTG_HYSTERISIS)
+#define bfin_write_PORTG_HYSTERISIS(val)	bfin_write16(PORTG_HYSTERISIS, val)
+#define bfin_read_PORTH_HYSTERISIS()		bfin_read16(PORTH_HYSTERISIS)
+#define bfin_write_PORTH_HYSTERISIS(val)	bfin_write16(PORTH_HYSTERISIS, val)
+#define bfin_read_MISCPORT_DRIVE()		bfin_read16(MISCPORT_DRIVE)
+#define bfin_write_MISCPORT_DRIVE(val)		bfin_write16(MISCPORT_DRIVE, val)
+#define bfin_read_MISCPORT_SLEW()		bfin_read16(MISCPORT_SLEW)
+#define bfin_write_MISCPORT_SLEW(val)		bfin_write16(MISCPORT_SLEW, val)
+#define bfin_read_MISCPORT_HYSTERISIS()		bfin_read16(MISCPORT_HYSTERISIS)
+#define bfin_write_MISCPORT_HYSTERISIS(val)	bfin_write16(MISCPORT_HYSTERISIS, val)
+
+/* HOST Port Registers */
+
+#define bfin_read_HOST_CONTROL()		bfin_read16(HOST_CONTROL)
+#define bfin_write_HOST_CONTROL(val)		bfin_write16(HOST_CONTROL, val)
+#define bfin_read_HOST_STATUS()			bfin_read16(HOST_STATUS)
+#define bfin_write_HOST_STATUS(val)		bfin_write16(HOST_STATUS, val)
+#define bfin_read_HOST_TIMEOUT()		bfin_read16(HOST_TIMEOUT)
+#define bfin_write_HOST_TIMEOUT(val)		bfin_write16(HOST_TIMEOUT, val)
+
+/* Counter Registers */
+
+#define bfin_read_CNT_CONFIG()			bfin_read16(CNT_CONFIG)
+#define bfin_write_CNT_CONFIG(val)		bfin_write16(CNT_CONFIG, val)
+#define bfin_read_CNT_IMASK()			bfin_read16(CNT_IMASK)
+#define bfin_write_CNT_IMASK(val)		bfin_write16(CNT_IMASK, val)
+#define bfin_read_CNT_STATUS()			bfin_read16(CNT_STATUS)
+#define bfin_write_CNT_STATUS(val)		bfin_write16(CNT_STATUS, val)
+#define bfin_read_CNT_COMMAND()			bfin_read16(CNT_COMMAND)
+#define bfin_write_CNT_COMMAND(val)		bfin_write16(CNT_COMMAND, val)
+#define bfin_read_CNT_DEBOUNCE()		bfin_read16(CNT_DEBOUNCE)
+#define bfin_write_CNT_DEBOUNCE(val)		bfin_write16(CNT_DEBOUNCE, val)
+#define bfin_read_CNT_COUNTER()			bfin_read32(CNT_COUNTER)
+#define bfin_write_CNT_COUNTER(val)		bfin_write32(CNT_COUNTER, val)
+#define bfin_read_CNT_MAX()			bfin_read32(CNT_MAX)
+#define bfin_write_CNT_MAX(val)			bfin_write32(CNT_MAX, val)
+#define bfin_read_CNT_MIN()			bfin_read32(CNT_MIN)
+#define bfin_write_CNT_MIN(val)			bfin_write32(CNT_MIN, val)
+
+/* Security Registers */
+
+#define bfin_read_SECURE_SYSSWT()		bfin_read32(SECURE_SYSSWT)
+#define bfin_write_SECURE_SYSSWT(val)		bfin_write32(SECURE_SYSSWT, val)
+#define bfin_read_SECURE_CONTROL()		bfin_read16(SECURE_CONTROL)
+#define bfin_write_SECURE_CONTROL(val)		bfin_write16(SECURE_CONTROL, val)
+#define bfin_read_SECURE_STATUS()		bfin_read16(SECURE_STATUS)
+#define bfin_write_SECURE_STATUS(val)		bfin_write16(SECURE_STATUS, val)
 
 #endif /* _CDEF_BF512_H */
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf518/include/mach/cdefBF514.h linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf518/include/mach/cdefBF514.h
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf518/include/mach/cdefBF514.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf518/include/mach/cdefBF514.h	2011-03-14 21:20:32.000000000 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright 2008-2009 Analog Devices Inc.
+ * Copyright 2008-2010 Analog Devices Inc.
  *
  * Licensed under the ADI BSD license or the GPL-2 (or later)
  */
@@ -7,9 +7,6 @@
 #ifndef _CDEF_BF514_H
 #define _CDEF_BF514_H
 
-/* include all Core registers and bit definitions */
-#include "defBF514.h"
-
 /* BF514 is BF512 + RSI */
 #include "cdefBF512.h"
 
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf518/include/mach/cdefBF516.h linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf518/include/mach/cdefBF516.h
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf518/include/mach/cdefBF516.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf518/include/mach/cdefBF516.h	2011-03-14 21:20:32.000000000 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright 2008-2009 Analog Devices Inc.
+ * Copyright 2008-2010 Analog Devices Inc.
  *
  * Licensed under the ADI BSD license or the GPL-2 (or later)
  */
@@ -7,9 +7,6 @@
 #ifndef _CDEF_BF516_H
 #define _CDEF_BF516_H
 
-/* include all Core registers and bit definitions */
-#include "defBF516.h"
-
 /* BF516 is BF514 + EMAC */
 #include "cdefBF514.h"
 
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf518/include/mach/cdefBF518.h linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf518/include/mach/cdefBF518.h
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf518/include/mach/cdefBF518.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf518/include/mach/cdefBF518.h	2011-03-14 21:20:32.000000000 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright 2008-2009 Analog Devices Inc.
+ * Copyright 2008-2010 Analog Devices Inc.
  *
  * Licensed under the ADI BSD license or the GPL-2 (or later)
  */
@@ -7,9 +7,6 @@
 #ifndef _CDEF_BF518_H
 #define _CDEF_BF518_H
 
-/* include all Core registers and bit definitions */
-#include "defBF518.h"
-
 /* BF518 is BF516 + IEEE-1588 */
 #include "cdefBF516.h"
 
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf518/include/mach/cdefBF51x_base.h linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf518/include/mach/cdefBF51x_base.h
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf518/include/mach/cdefBF51x_base.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf518/include/mach/cdefBF51x_base.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,1061 +0,0 @@
-/*
- * Copyright 2008 Analog Devices Inc.
- *
- * Licensed under the GPL-2 or later
- */
-
-#ifndef _CDEF_BF52X_H
-#define _CDEF_BF52X_H
-
-#include <asm/blackfin.h>
-
-#include "defBF51x_base.h"
-
-/* Include core specific register pointer definitions 								*/
-#include <asm/cdef_LPBlackfin.h>
-
-/* ==== begin from cdefBF534.h ==== */
-
-/* Clock and System Control	(0xFFC00000 - 0xFFC000FF)								*/
-#define bfin_read_PLL_CTL()			bfin_read16(PLL_CTL)
-#define bfin_read_PLL_DIV()			bfin_read16(PLL_DIV)
-#define bfin_write_PLL_DIV(val)			bfin_write16(PLL_DIV, val)
-#define bfin_read_VR_CTL()			bfin_read16(VR_CTL)
-#define bfin_read_PLL_STAT()			bfin_read16(PLL_STAT)
-#define bfin_write_PLL_STAT(val)		bfin_write16(PLL_STAT, val)
-#define bfin_read_PLL_LOCKCNT()			bfin_read16(PLL_LOCKCNT)
-#define bfin_write_PLL_LOCKCNT(val)		bfin_write16(PLL_LOCKCNT, val)
-#define bfin_read_CHIPID()			bfin_read32(CHIPID)
-#define bfin_write_CHIPID(val)			bfin_write32(CHIPID, val)
-
-
-/* System Interrupt Controller (0xFFC00100 - 0xFFC001FF)							*/
-#define bfin_read_SWRST()			bfin_read16(SWRST)
-#define bfin_write_SWRST(val)			bfin_write16(SWRST, val)
-#define bfin_read_SYSCR()			bfin_read16(SYSCR)
-#define bfin_write_SYSCR(val)			bfin_write16(SYSCR, val)
-
-#define bfin_read_SIC_RVECT()			bfin_read32(SIC_RVECT)
-#define bfin_write_SIC_RVECT(val)		bfin_write32(SIC_RVECT, val)
-#define bfin_read_SIC_IMASK0()			bfin_read32(SIC_IMASK0)
-#define bfin_write_SIC_IMASK0(val)		bfin_write32(SIC_IMASK0, val)
-#define bfin_read_SIC_IMASK(x)			bfin_read32(SIC_IMASK0 + (x << 6))
-#define bfin_write_SIC_IMASK(x, val)		bfin_write32((SIC_IMASK0 + (x << 6)), val)
-
-#define bfin_read_SIC_IAR0()			bfin_read32(SIC_IAR0)
-#define bfin_write_SIC_IAR0(val)		bfin_write32(SIC_IAR0, val)
-#define bfin_read_SIC_IAR1()			bfin_read32(SIC_IAR1)
-#define bfin_write_SIC_IAR1(val)		bfin_write32(SIC_IAR1, val)
-#define bfin_read_SIC_IAR2()			bfin_read32(SIC_IAR2)
-#define bfin_write_SIC_IAR2(val)		bfin_write32(SIC_IAR2, val)
-#define bfin_read_SIC_IAR3()			bfin_read32(SIC_IAR3)
-#define bfin_write_SIC_IAR3(val)		bfin_write32(SIC_IAR3, val)
-
-#define bfin_read_SIC_ISR0()			bfin_read32(SIC_ISR0)
-#define bfin_write_SIC_ISR0(val)		bfin_write32(SIC_ISR0, val)
-#define bfin_read_SIC_ISR(x)			bfin_read32(SIC_ISR0 + (x << 6))
-#define bfin_write_SIC_ISR(x, val)		bfin_write32((SIC_ISR0 + (x << 6)), val)
-
-#define bfin_read_SIC_IWR0()			bfin_read32(SIC_IWR0)
-#define bfin_write_SIC_IWR0(val)		bfin_write32(SIC_IWR0, val)
-#define bfin_read_SIC_IWR(x)			bfin_read32(SIC_IWR0 + (x << 6))
-#define bfin_write_SIC_IWR(x, val)		bfin_write32((SIC_IWR0 + (x << 6)), val)
-
-/* SIC Additions to ADSP-BF51x (0xFFC0014C - 0xFFC00162) */
-
-#define bfin_read_SIC_IMASK1()			bfin_read32(SIC_IMASK1)
-#define bfin_write_SIC_IMASK1(val)		bfin_write32(SIC_IMASK1, val)
-#define bfin_read_SIC_IAR4()			bfin_read32(SIC_IAR4)
-#define bfin_write_SIC_IAR4(val)		bfin_write32(SIC_IAR4, val)
-#define bfin_read_SIC_IAR5()			bfin_read32(SIC_IAR5)
-#define bfin_write_SIC_IAR5(val)		bfin_write32(SIC_IAR5, val)
-#define bfin_read_SIC_IAR6()			bfin_read32(SIC_IAR6)
-#define bfin_write_SIC_IAR6(val)		bfin_write32(SIC_IAR6, val)
-#define bfin_read_SIC_IAR7()			bfin_read32(SIC_IAR7)
-#define bfin_write_SIC_IAR7(val)		bfin_write32(SIC_IAR7, val)
-#define bfin_read_SIC_ISR1()			bfin_read32(SIC_ISR1)
-#define bfin_write_SIC_ISR1(val)		bfin_write32(SIC_ISR1, val)
-#define bfin_read_SIC_IWR1()			bfin_read32(SIC_IWR1)
-#define bfin_write_SIC_IWR1(val)		bfin_write32(SIC_IWR1, val)
-
-/* Watchdog Timer		(0xFFC00200 - 0xFFC002FF)									*/
-#define bfin_read_WDOG_CTL()			bfin_read16(WDOG_CTL)
-#define bfin_write_WDOG_CTL(val)		bfin_write16(WDOG_CTL, val)
-#define bfin_read_WDOG_CNT()			bfin_read32(WDOG_CNT)
-#define bfin_write_WDOG_CNT(val)		bfin_write32(WDOG_CNT, val)
-#define bfin_read_WDOG_STAT()			bfin_read32(WDOG_STAT)
-#define bfin_write_WDOG_STAT(val)		bfin_write32(WDOG_STAT, val)
-
-
-/* Real Time Clock		(0xFFC00300 - 0xFFC003FF)									*/
-#define bfin_read_RTC_STAT()			bfin_read32(RTC_STAT)
-#define bfin_write_RTC_STAT(val)		bfin_write32(RTC_STAT, val)
-#define bfin_read_RTC_ICTL()			bfin_read16(RTC_ICTL)
-#define bfin_write_RTC_ICTL(val)		bfin_write16(RTC_ICTL, val)
-#define bfin_read_RTC_ISTAT()			bfin_read16(RTC_ISTAT)
-#define bfin_write_RTC_ISTAT(val)		bfin_write16(RTC_ISTAT, val)
-#define bfin_read_RTC_SWCNT()			bfin_read16(RTC_SWCNT)
-#define bfin_write_RTC_SWCNT(val)		bfin_write16(RTC_SWCNT, val)
-#define bfin_read_RTC_ALARM()			bfin_read32(RTC_ALARM)
-#define bfin_write_RTC_ALARM(val)		bfin_write32(RTC_ALARM, val)
-#define bfin_read_RTC_FAST()			bfin_read16(RTC_FAST)
-#define bfin_write_RTC_FAST(val)		bfin_write16(RTC_FAST, val)
-#define bfin_read_RTC_PREN()			bfin_read16(RTC_PREN)
-#define bfin_write_RTC_PREN(val)		bfin_write16(RTC_PREN, val)
-
-
-/* UART0 Controller		(0xFFC00400 - 0xFFC004FF)									*/
-#define bfin_read_UART0_THR()			bfin_read16(UART0_THR)
-#define bfin_write_UART0_THR(val)		bfin_write16(UART0_THR, val)
-#define bfin_read_UART0_RBR()			bfin_read16(UART0_RBR)
-#define bfin_write_UART0_RBR(val)		bfin_write16(UART0_RBR, val)
-#define bfin_read_UART0_DLL()			bfin_read16(UART0_DLL)
-#define bfin_write_UART0_DLL(val)		bfin_write16(UART0_DLL, val)
-#define bfin_read_UART0_IER()			bfin_read16(UART0_IER)
-#define bfin_write_UART0_IER(val)		bfin_write16(UART0_IER, val)
-#define bfin_read_UART0_DLH()			bfin_read16(UART0_DLH)
-#define bfin_write_UART0_DLH(val)		bfin_write16(UART0_DLH, val)
-#define bfin_read_UART0_IIR()			bfin_read16(UART0_IIR)
-#define bfin_write_UART0_IIR(val)		bfin_write16(UART0_IIR, val)
-#define bfin_read_UART0_LCR()			bfin_read16(UART0_LCR)
-#define bfin_write_UART0_LCR(val)		bfin_write16(UART0_LCR, val)
-#define bfin_read_UART0_MCR()			bfin_read16(UART0_MCR)
-#define bfin_write_UART0_MCR(val)		bfin_write16(UART0_MCR, val)
-#define bfin_read_UART0_LSR()			bfin_read16(UART0_LSR)
-#define bfin_write_UART0_LSR(val)		bfin_write16(UART0_LSR, val)
-#define bfin_read_UART0_MSR()			bfin_read16(UART0_MSR)
-#define bfin_write_UART0_MSR(val)		bfin_write16(UART0_MSR, val)
-#define bfin_read_UART0_SCR()			bfin_read16(UART0_SCR)
-#define bfin_write_UART0_SCR(val)		bfin_write16(UART0_SCR, val)
-#define bfin_read_UART0_GCTL()			bfin_read16(UART0_GCTL)
-#define bfin_write_UART0_GCTL(val)		bfin_write16(UART0_GCTL, val)
-
-
-/* TIMER0-7 Registers		(0xFFC00600 - 0xFFC006FF)								*/
-#define bfin_read_TIMER0_CONFIG()		bfin_read16(TIMER0_CONFIG)
-#define bfin_write_TIMER0_CONFIG(val)		bfin_write16(TIMER0_CONFIG, val)
-#define bfin_read_TIMER0_COUNTER()		bfin_read32(TIMER0_COUNTER)
-#define bfin_write_TIMER0_COUNTER(val)		bfin_write32(TIMER0_COUNTER, val)
-#define bfin_read_TIMER0_PERIOD()		bfin_read32(TIMER0_PERIOD)
-#define bfin_write_TIMER0_PERIOD(val)		bfin_write32(TIMER0_PERIOD, val)
-#define bfin_read_TIMER0_WIDTH()		bfin_read32(TIMER0_WIDTH)
-#define bfin_write_TIMER0_WIDTH(val)		bfin_write32(TIMER0_WIDTH, val)
-
-#define bfin_read_TIMER1_CONFIG()		bfin_read16(TIMER1_CONFIG)
-#define bfin_write_TIMER1_CONFIG(val)		bfin_write16(TIMER1_CONFIG, val)
-#define bfin_read_TIMER1_COUNTER()		bfin_read32(TIMER1_COUNTER)
-#define bfin_write_TIMER1_COUNTER(val)		bfin_write32(TIMER1_COUNTER, val)
-#define bfin_read_TIMER1_PERIOD()		bfin_read32(TIMER1_PERIOD)
-#define bfin_write_TIMER1_PERIOD(val)		bfin_write32(TIMER1_PERIOD, val)
-#define bfin_read_TIMER1_WIDTH()		bfin_read32(TIMER1_WIDTH)
-#define bfin_write_TIMER1_WIDTH(val)		bfin_write32(TIMER1_WIDTH, val)
-
-#define bfin_read_TIMER2_CONFIG()		bfin_read16(TIMER2_CONFIG)
-#define bfin_write_TIMER2_CONFIG(val)		bfin_write16(TIMER2_CONFIG, val)
-#define bfin_read_TIMER2_COUNTER()		bfin_read32(TIMER2_COUNTER)
-#define bfin_write_TIMER2_COUNTER(val)		bfin_write32(TIMER2_COUNTER, val)
-#define bfin_read_TIMER2_PERIOD()		bfin_read32(TIMER2_PERIOD)
-#define bfin_write_TIMER2_PERIOD(val)		bfin_write32(TIMER2_PERIOD, val)
-#define bfin_read_TIMER2_WIDTH()		bfin_read32(TIMER2_WIDTH)
-#define bfin_write_TIMER2_WIDTH(val)		bfin_write32(TIMER2_WIDTH, val)
-
-#define bfin_read_TIMER3_CONFIG()		bfin_read16(TIMER3_CONFIG)
-#define bfin_write_TIMER3_CONFIG(val)		bfin_write16(TIMER3_CONFIG, val)
-#define bfin_read_TIMER3_COUNTER()		bfin_read32(TIMER3_COUNTER)
-#define bfin_write_TIMER3_COUNTER(val)		bfin_write32(TIMER3_COUNTER, val)
-#define bfin_read_TIMER3_PERIOD()		bfin_read32(TIMER3_PERIOD)
-#define bfin_write_TIMER3_PERIOD(val)		bfin_write32(TIMER3_PERIOD, val)
-#define bfin_read_TIMER3_WIDTH()		bfin_read32(TIMER3_WIDTH)
-#define bfin_write_TIMER3_WIDTH(val)		bfin_write32(TIMER3_WIDTH, val)
-
-#define bfin_read_TIMER4_CONFIG()		bfin_read16(TIMER4_CONFIG)
-#define bfin_write_TIMER4_CONFIG(val)		bfin_write16(TIMER4_CONFIG, val)
-#define bfin_read_TIMER4_COUNTER()		bfin_read32(TIMER4_COUNTER)
-#define bfin_write_TIMER4_COUNTER(val)		bfin_write32(TIMER4_COUNTER, val)
-#define bfin_read_TIMER4_PERIOD()		bfin_read32(TIMER4_PERIOD)
-#define bfin_write_TIMER4_PERIOD(val)		bfin_write32(TIMER4_PERIOD, val)
-#define bfin_read_TIMER4_WIDTH()		bfin_read32(TIMER4_WIDTH)
-#define bfin_write_TIMER4_WIDTH(val)		bfin_write32(TIMER4_WIDTH, val)
-
-#define bfin_read_TIMER5_CONFIG()		bfin_read16(TIMER5_CONFIG)
-#define bfin_write_TIMER5_CONFIG(val)		bfin_write16(TIMER5_CONFIG, val)
-#define bfin_read_TIMER5_COUNTER()		bfin_read32(TIMER5_COUNTER)
-#define bfin_write_TIMER5_COUNTER(val)		bfin_write32(TIMER5_COUNTER, val)
-#define bfin_read_TIMER5_PERIOD()		bfin_read32(TIMER5_PERIOD)
-#define bfin_write_TIMER5_PERIOD(val)		bfin_write32(TIMER5_PERIOD, val)
-#define bfin_read_TIMER5_WIDTH()		bfin_read32(TIMER5_WIDTH)
-#define bfin_write_TIMER5_WIDTH(val)		bfin_write32(TIMER5_WIDTH, val)
-
-#define bfin_read_TIMER6_CONFIG()		bfin_read16(TIMER6_CONFIG)
-#define bfin_write_TIMER6_CONFIG(val)		bfin_write16(TIMER6_CONFIG, val)
-#define bfin_read_TIMER6_COUNTER()		bfin_read32(TIMER6_COUNTER)
-#define bfin_write_TIMER6_COUNTER(val)		bfin_write32(TIMER6_COUNTER, val)
-#define bfin_read_TIMER6_PERIOD()		bfin_read32(TIMER6_PERIOD)
-#define bfin_write_TIMER6_PERIOD(val)		bfin_write32(TIMER6_PERIOD, val)
-#define bfin_read_TIMER6_WIDTH()		bfin_read32(TIMER6_WIDTH)
-#define bfin_write_TIMER6_WIDTH(val)		bfin_write32(TIMER6_WIDTH, val)
-
-#define bfin_read_TIMER7_CONFIG()		bfin_read16(TIMER7_CONFIG)
-#define bfin_write_TIMER7_CONFIG(val)		bfin_write16(TIMER7_CONFIG, val)
-#define bfin_read_TIMER7_COUNTER()		bfin_read32(TIMER7_COUNTER)
-#define bfin_write_TIMER7_COUNTER(val)		bfin_write32(TIMER7_COUNTER, val)
-#define bfin_read_TIMER7_PERIOD()		bfin_read32(TIMER7_PERIOD)
-#define bfin_write_TIMER7_PERIOD(val)		bfin_write32(TIMER7_PERIOD, val)
-#define bfin_read_TIMER7_WIDTH()		bfin_read32(TIMER7_WIDTH)
-#define bfin_write_TIMER7_WIDTH(val)		bfin_write32(TIMER7_WIDTH, val)
-
-#define bfin_read_TIMER_ENABLE()		bfin_read16(TIMER_ENABLE)
-#define bfin_write_TIMER_ENABLE(val)		bfin_write16(TIMER_ENABLE, val)
-#define bfin_read_TIMER_DISABLE()		bfin_read16(TIMER_DISABLE)
-#define bfin_write_TIMER_DISABLE(val)		bfin_write16(TIMER_DISABLE, val)
-#define bfin_read_TIMER_STATUS()		bfin_read32(TIMER_STATUS)
-#define bfin_write_TIMER_STATUS(val)		bfin_write32(TIMER_STATUS, val)
-
-
-/* General Purpose I/O Port F (0xFFC00700 - 0xFFC007FF)								*/
-#define bfin_read_PORTFIO()			bfin_read16(PORTFIO)
-#define bfin_write_PORTFIO(val)			bfin_write16(PORTFIO, val)
-#define bfin_read_PORTFIO_CLEAR()		bfin_read16(PORTFIO_CLEAR)
-#define bfin_write_PORTFIO_CLEAR(val)		bfin_write16(PORTFIO_CLEAR, val)
-#define bfin_read_PORTFIO_SET()			bfin_read16(PORTFIO_SET)
-#define bfin_write_PORTFIO_SET(val)		bfin_write16(PORTFIO_SET, val)
-#define bfin_read_PORTFIO_TOGGLE()		bfin_read16(PORTFIO_TOGGLE)
-#define bfin_write_PORTFIO_TOGGLE(val)		bfin_write16(PORTFIO_TOGGLE, val)
-#define bfin_read_PORTFIO_MASKA()		bfin_read16(PORTFIO_MASKA)
-#define bfin_write_PORTFIO_MASKA(val)		bfin_write16(PORTFIO_MASKA, val)
-#define bfin_read_PORTFIO_MASKA_CLEAR()		bfin_read16(PORTFIO_MASKA_CLEAR)
-#define bfin_write_PORTFIO_MASKA_CLEAR(val)	bfin_write16(PORTFIO_MASKA_CLEAR, val)
-#define bfin_read_PORTFIO_MASKA_SET()		bfin_read16(PORTFIO_MASKA_SET)
-#define bfin_write_PORTFIO_MASKA_SET(val)	bfin_write16(PORTFIO_MASKA_SET, val)
-#define bfin_read_PORTFIO_MASKA_TOGGLE()	bfin_read16(PORTFIO_MASKA_TOGGLE)
-#define bfin_write_PORTFIO_MASKA_TOGGLE(val)	bfin_write16(PORTFIO_MASKA_TOGGLE, val)
-#define bfin_read_PORTFIO_MASKB()		bfin_read16(PORTFIO_MASKB)
-#define bfin_write_PORTFIO_MASKB(val)		bfin_write16(PORTFIO_MASKB, val)
-#define bfin_read_PORTFIO_MASKB_CLEAR()		bfin_read16(PORTFIO_MASKB_CLEAR)
-#define bfin_write_PORTFIO_MASKB_CLEAR(val)	bfin_write16(PORTFIO_MASKB_CLEAR, val)
-#define bfin_read_PORTFIO_MASKB_SET()		bfin_read16(PORTFIO_MASKB_SET)
-#define bfin_write_PORTFIO_MASKB_SET(val)	bfin_write16(PORTFIO_MASKB_SET, val)
-#define bfin_read_PORTFIO_MASKB_TOGGLE()	bfin_read16(PORTFIO_MASKB_TOGGLE)
-#define bfin_write_PORTFIO_MASKB_TOGGLE(val)	bfin_write16(PORTFIO_MASKB_TOGGLE, val)
-#define bfin_read_PORTFIO_DIR()			bfin_read16(PORTFIO_DIR)
-#define bfin_write_PORTFIO_DIR(val)		bfin_write16(PORTFIO_DIR, val)
-#define bfin_read_PORTFIO_POLAR()		bfin_read16(PORTFIO_POLAR)
-#define bfin_write_PORTFIO_POLAR(val)		bfin_write16(PORTFIO_POLAR, val)
-#define bfin_read_PORTFIO_EDGE()		bfin_read16(PORTFIO_EDGE)
-#define bfin_write_PORTFIO_EDGE(val)		bfin_write16(PORTFIO_EDGE, val)
-#define bfin_read_PORTFIO_BOTH()		bfin_read16(PORTFIO_BOTH)
-#define bfin_write_PORTFIO_BOTH(val)		bfin_write16(PORTFIO_BOTH, val)
-#define bfin_read_PORTFIO_INEN()		bfin_read16(PORTFIO_INEN)
-#define bfin_write_PORTFIO_INEN(val)		bfin_write16(PORTFIO_INEN, val)
-
-
-/* SPORT0 Controller		(0xFFC00800 - 0xFFC008FF)								*/
-#define bfin_read_SPORT0_TCR1()			bfin_read16(SPORT0_TCR1)
-#define bfin_write_SPORT0_TCR1(val)		bfin_write16(SPORT0_TCR1, val)
-#define bfin_read_SPORT0_TCR2()			bfin_read16(SPORT0_TCR2)
-#define bfin_write_SPORT0_TCR2(val)		bfin_write16(SPORT0_TCR2, val)
-#define bfin_read_SPORT0_TCLKDIV()		bfin_read16(SPORT0_TCLKDIV)
-#define bfin_write_SPORT0_TCLKDIV(val)		bfin_write16(SPORT0_TCLKDIV, val)
-#define bfin_read_SPORT0_TFSDIV()		bfin_read16(SPORT0_TFSDIV)
-#define bfin_write_SPORT0_TFSDIV(val)		bfin_write16(SPORT0_TFSDIV, val)
-#define bfin_read_SPORT0_TX()			bfin_read32(SPORT0_TX)
-#define bfin_write_SPORT0_TX(val)		bfin_write32(SPORT0_TX, val)
-#define bfin_read_SPORT0_RX()			bfin_read32(SPORT0_RX)
-#define bfin_write_SPORT0_RX(val)		bfin_write32(SPORT0_RX, val)
-#define bfin_read_SPORT0_TX32()			bfin_read32(SPORT0_TX)
-#define bfin_write_SPORT0_TX32(val)		bfin_write32(SPORT0_TX, val)
-#define bfin_read_SPORT0_RX32()			bfin_read32(SPORT0_RX)
-#define bfin_write_SPORT0_RX32(val)		bfin_write32(SPORT0_RX, val)
-#define bfin_read_SPORT0_TX16()			bfin_read16(SPORT0_TX)
-#define bfin_write_SPORT0_TX16(val)		bfin_write16(SPORT0_TX, val)
-#define bfin_read_SPORT0_RX16()			bfin_read16(SPORT0_RX)
-#define bfin_write_SPORT0_RX16(val)		bfin_write16(SPORT0_RX, val)
-#define bfin_read_SPORT0_RCR1()			bfin_read16(SPORT0_RCR1)
-#define bfin_write_SPORT0_RCR1(val)		bfin_write16(SPORT0_RCR1, val)
-#define bfin_read_SPORT0_RCR2()			bfin_read16(SPORT0_RCR2)
-#define bfin_write_SPORT0_RCR2(val)		bfin_write16(SPORT0_RCR2, val)
-#define bfin_read_SPORT0_RCLKDIV()		bfin_read16(SPORT0_RCLKDIV)
-#define bfin_write_SPORT0_RCLKDIV(val)		bfin_write16(SPORT0_RCLKDIV, val)
-#define bfin_read_SPORT0_RFSDIV()		bfin_read16(SPORT0_RFSDIV)
-#define bfin_write_SPORT0_RFSDIV(val)		bfin_write16(SPORT0_RFSDIV, val)
-#define bfin_read_SPORT0_STAT()			bfin_read16(SPORT0_STAT)
-#define bfin_write_SPORT0_STAT(val)		bfin_write16(SPORT0_STAT, val)
-#define bfin_read_SPORT0_CHNL()			bfin_read16(SPORT0_CHNL)
-#define bfin_write_SPORT0_CHNL(val)		bfin_write16(SPORT0_CHNL, val)
-#define bfin_read_SPORT0_MCMC1()		bfin_read16(SPORT0_MCMC1)
-#define bfin_write_SPORT0_MCMC1(val)		bfin_write16(SPORT0_MCMC1, val)
-#define bfin_read_SPORT0_MCMC2()		bfin_read16(SPORT0_MCMC2)
-#define bfin_write_SPORT0_MCMC2(val)		bfin_write16(SPORT0_MCMC2, val)
-#define bfin_read_SPORT0_MTCS0()		bfin_read32(SPORT0_MTCS0)
-#define bfin_write_SPORT0_MTCS0(val)		bfin_write32(SPORT0_MTCS0, val)
-#define bfin_read_SPORT0_MTCS1()		bfin_read32(SPORT0_MTCS1)
-#define bfin_write_SPORT0_MTCS1(val)		bfin_write32(SPORT0_MTCS1, val)
-#define bfin_read_SPORT0_MTCS2()		bfin_read32(SPORT0_MTCS2)
-#define bfin_write_SPORT0_MTCS2(val)		bfin_write32(SPORT0_MTCS2, val)
-#define bfin_read_SPORT0_MTCS3()		bfin_read32(SPORT0_MTCS3)
-#define bfin_write_SPORT0_MTCS3(val)		bfin_write32(SPORT0_MTCS3, val)
-#define bfin_read_SPORT0_MRCS0()		bfin_read32(SPORT0_MRCS0)
-#define bfin_write_SPORT0_MRCS0(val)		bfin_write32(SPORT0_MRCS0, val)
-#define bfin_read_SPORT0_MRCS1()		bfin_read32(SPORT0_MRCS1)
-#define bfin_write_SPORT0_MRCS1(val)		bfin_write32(SPORT0_MRCS1, val)
-#define bfin_read_SPORT0_MRCS2()		bfin_read32(SPORT0_MRCS2)
-#define bfin_write_SPORT0_MRCS2(val)		bfin_write32(SPORT0_MRCS2, val)
-#define bfin_read_SPORT0_MRCS3()		bfin_read32(SPORT0_MRCS3)
-#define bfin_write_SPORT0_MRCS3(val)		bfin_write32(SPORT0_MRCS3, val)
-
-
-/* SPORT1 Controller		(0xFFC00900 - 0xFFC009FF)								*/
-#define bfin_read_SPORT1_TCR1()			bfin_read16(SPORT1_TCR1)
-#define bfin_write_SPORT1_TCR1(val)		bfin_write16(SPORT1_TCR1, val)
-#define bfin_read_SPORT1_TCR2()			bfin_read16(SPORT1_TCR2)
-#define bfin_write_SPORT1_TCR2(val)		bfin_write16(SPORT1_TCR2, val)
-#define bfin_read_SPORT1_TCLKDIV()		bfin_read16(SPORT1_TCLKDIV)
-#define bfin_write_SPORT1_TCLKDIV(val)		bfin_write16(SPORT1_TCLKDIV, val)
-#define bfin_read_SPORT1_TFSDIV()		bfin_read16(SPORT1_TFSDIV)
-#define bfin_write_SPORT1_TFSDIV(val)		bfin_write16(SPORT1_TFSDIV, val)
-#define bfin_read_SPORT1_TX()			bfin_read32(SPORT1_TX)
-#define bfin_write_SPORT1_TX(val)		bfin_write32(SPORT1_TX, val)
-#define bfin_read_SPORT1_RX()			bfin_read32(SPORT1_RX)
-#define bfin_write_SPORT1_RX(val)		bfin_write32(SPORT1_RX, val)
-#define bfin_read_SPORT1_TX32()			bfin_read32(SPORT1_TX)
-#define bfin_write_SPORT1_TX32(val)		bfin_write32(SPORT1_TX, val)
-#define bfin_read_SPORT1_RX32()			bfin_read32(SPORT1_RX)
-#define bfin_write_SPORT1_RX32(val)		bfin_write32(SPORT1_RX, val)
-#define bfin_read_SPORT1_TX16()			bfin_read16(SPORT1_TX)
-#define bfin_write_SPORT1_TX16(val)		bfin_write16(SPORT1_TX, val)
-#define bfin_read_SPORT1_RX16()			bfin_read16(SPORT1_RX)
-#define bfin_write_SPORT1_RX16(val)		bfin_write16(SPORT1_RX, val)
-#define bfin_read_SPORT1_RCR1()			bfin_read16(SPORT1_RCR1)
-#define bfin_write_SPORT1_RCR1(val)		bfin_write16(SPORT1_RCR1, val)
-#define bfin_read_SPORT1_RCR2()			bfin_read16(SPORT1_RCR2)
-#define bfin_write_SPORT1_RCR2(val)		bfin_write16(SPORT1_RCR2, val)
-#define bfin_read_SPORT1_RCLKDIV()		bfin_read16(SPORT1_RCLKDIV)
-#define bfin_write_SPORT1_RCLKDIV(val)		bfin_write16(SPORT1_RCLKDIV, val)
-#define bfin_read_SPORT1_RFSDIV()		bfin_read16(SPORT1_RFSDIV)
-#define bfin_write_SPORT1_RFSDIV(val)		bfin_write16(SPORT1_RFSDIV, val)
-#define bfin_read_SPORT1_STAT()			bfin_read16(SPORT1_STAT)
-#define bfin_write_SPORT1_STAT(val)		bfin_write16(SPORT1_STAT, val)
-#define bfin_read_SPORT1_CHNL()			bfin_read16(SPORT1_CHNL)
-#define bfin_write_SPORT1_CHNL(val)		bfin_write16(SPORT1_CHNL, val)
-#define bfin_read_SPORT1_MCMC1()		bfin_read16(SPORT1_MCMC1)
-#define bfin_write_SPORT1_MCMC1(val)		bfin_write16(SPORT1_MCMC1, val)
-#define bfin_read_SPORT1_MCMC2()		bfin_read16(SPORT1_MCMC2)
-#define bfin_write_SPORT1_MCMC2(val)		bfin_write16(SPORT1_MCMC2, val)
-#define bfin_read_SPORT1_MTCS0()		bfin_read32(SPORT1_MTCS0)
-#define bfin_write_SPORT1_MTCS0(val)		bfin_write32(SPORT1_MTCS0, val)
-#define bfin_read_SPORT1_MTCS1()		bfin_read32(SPORT1_MTCS1)
-#define bfin_write_SPORT1_MTCS1(val)		bfin_write32(SPORT1_MTCS1, val)
-#define bfin_read_SPORT1_MTCS2()		bfin_read32(SPORT1_MTCS2)
-#define bfin_write_SPORT1_MTCS2(val)		bfin_write32(SPORT1_MTCS2, val)
-#define bfin_read_SPORT1_MTCS3()		bfin_read32(SPORT1_MTCS3)
-#define bfin_write_SPORT1_MTCS3(val)		bfin_write32(SPORT1_MTCS3, val)
-#define bfin_read_SPORT1_MRCS0()		bfin_read32(SPORT1_MRCS0)
-#define bfin_write_SPORT1_MRCS0(val)		bfin_write32(SPORT1_MRCS0, val)
-#define bfin_read_SPORT1_MRCS1()		bfin_read32(SPORT1_MRCS1)
-#define bfin_write_SPORT1_MRCS1(val)		bfin_write32(SPORT1_MRCS1, val)
-#define bfin_read_SPORT1_MRCS2()		bfin_read32(SPORT1_MRCS2)
-#define bfin_write_SPORT1_MRCS2(val)		bfin_write32(SPORT1_MRCS2, val)
-#define bfin_read_SPORT1_MRCS3()		bfin_read32(SPORT1_MRCS3)
-#define bfin_write_SPORT1_MRCS3(val)		bfin_write32(SPORT1_MRCS3, val)
-
-
-/* External Bus Interface Unit (0xFFC00A00 - 0xFFC00AFF)							*/
-#define bfin_read_EBIU_AMGCTL()			bfin_read16(EBIU_AMGCTL)
-#define bfin_write_EBIU_AMGCTL(val)		bfin_write16(EBIU_AMGCTL, val)
-#define bfin_read_EBIU_AMBCTL0()		bfin_read32(EBIU_AMBCTL0)
-#define bfin_write_EBIU_AMBCTL0(val)		bfin_write32(EBIU_AMBCTL0, val)
-#define bfin_read_EBIU_AMBCTL1()		bfin_read32(EBIU_AMBCTL1)
-#define bfin_write_EBIU_AMBCTL1(val)		bfin_write32(EBIU_AMBCTL1, val)
-#define bfin_read_EBIU_SDGCTL()			bfin_read32(EBIU_SDGCTL)
-#define bfin_write_EBIU_SDGCTL(val)		bfin_write32(EBIU_SDGCTL, val)
-#define bfin_read_EBIU_SDBCTL()			bfin_read16(EBIU_SDBCTL)
-#define bfin_write_EBIU_SDBCTL(val)		bfin_write16(EBIU_SDBCTL, val)
-#define bfin_read_EBIU_SDRRC()			bfin_read16(EBIU_SDRRC)
-#define bfin_write_EBIU_SDRRC(val)		bfin_write16(EBIU_SDRRC, val)
-#define bfin_read_EBIU_SDSTAT()			bfin_read16(EBIU_SDSTAT)
-#define bfin_write_EBIU_SDSTAT(val)		bfin_write16(EBIU_SDSTAT, val)
-
-
-/* DMA Traffic Control Registers													*/
-#define bfin_read_DMA_TC_PER()			bfin_read16(DMA_TC_PER)
-#define bfin_write_DMA_TC_PER(val)		bfin_write16(DMA_TC_PER, val)
-#define bfin_read_DMA_TC_CNT()			bfin_read16(DMA_TC_CNT)
-#define bfin_write_DMA_TC_CNT(val)		bfin_write16(DMA_TC_CNT, val)
-
-/* Alternate deprecated register names (below) provided for backwards code compatibility */
-#define bfin_read_DMA_TCPER()			bfin_read16(DMA_TCPER)
-#define bfin_write_DMA_TCPER(val)		bfin_write16(DMA_TCPER, val)
-#define bfin_read_DMA_TCCNT()			bfin_read16(DMA_TCCNT)
-#define bfin_write_DMA_TCCNT(val)		bfin_write16(DMA_TCCNT, val)
-
-/* DMA Controller																	*/
-#define bfin_read_DMA0_CONFIG()			bfin_read16(DMA0_CONFIG)
-#define bfin_write_DMA0_CONFIG(val)		bfin_write16(DMA0_CONFIG, val)
-#define bfin_read_DMA0_NEXT_DESC_PTR()		bfin_read32(DMA0_NEXT_DESC_PTR)
-#define bfin_write_DMA0_NEXT_DESC_PTR(val)	bfin_write32(DMA0_NEXT_DESC_PTR, val)
-#define bfin_read_DMA0_START_ADDR()		bfin_read32(DMA0_START_ADDR)
-#define bfin_write_DMA0_START_ADDR(val)		bfin_write32(DMA0_START_ADDR, val)
-#define bfin_read_DMA0_X_COUNT()		bfin_read16(DMA0_X_COUNT)
-#define bfin_write_DMA0_X_COUNT(val)		bfin_write16(DMA0_X_COUNT, val)
-#define bfin_read_DMA0_Y_COUNT()		bfin_read16(DMA0_Y_COUNT)
-#define bfin_write_DMA0_Y_COUNT(val)		bfin_write16(DMA0_Y_COUNT, val)
-#define bfin_read_DMA0_X_MODIFY()		bfin_read16(DMA0_X_MODIFY)
-#define bfin_write_DMA0_X_MODIFY(val)		bfin_write16(DMA0_X_MODIFY, val)
-#define bfin_read_DMA0_Y_MODIFY()		bfin_read16(DMA0_Y_MODIFY)
-#define bfin_write_DMA0_Y_MODIFY(val)		bfin_write16(DMA0_Y_MODIFY, val)
-#define bfin_read_DMA0_CURR_DESC_PTR()		bfin_read32(DMA0_CURR_DESC_PTR)
-#define bfin_write_DMA0_CURR_DESC_PTR(val)	bfin_write32(DMA0_CURR_DESC_PTR, val)
-#define bfin_read_DMA0_CURR_ADDR()		bfin_read32(DMA0_CURR_ADDR)
-#define bfin_write_DMA0_CURR_ADDR(val)		bfin_write32(DMA0_CURR_ADDR, val)
-#define bfin_read_DMA0_CURR_X_COUNT()		bfin_read16(DMA0_CURR_X_COUNT)
-#define bfin_write_DMA0_CURR_X_COUNT(val)	bfin_write16(DMA0_CURR_X_COUNT, val)
-#define bfin_read_DMA0_CURR_Y_COUNT()		bfin_read16(DMA0_CURR_Y_COUNT)
-#define bfin_write_DMA0_CURR_Y_COUNT(val)	bfin_write16(DMA0_CURR_Y_COUNT, val)
-#define bfin_read_DMA0_IRQ_STATUS()		bfin_read16(DMA0_IRQ_STATUS)
-#define bfin_write_DMA0_IRQ_STATUS(val)		bfin_write16(DMA0_IRQ_STATUS, val)
-#define bfin_read_DMA0_PERIPHERAL_MAP()		bfin_read16(DMA0_PERIPHERAL_MAP)
-#define bfin_write_DMA0_PERIPHERAL_MAP(val)	bfin_write16(DMA0_PERIPHERAL_MAP, val)
-
-#define bfin_read_DMA1_CONFIG()			bfin_read16(DMA1_CONFIG)
-#define bfin_write_DMA1_CONFIG(val)		bfin_write16(DMA1_CONFIG, val)
-#define bfin_read_DMA1_NEXT_DESC_PTR()		bfin_read32(DMA1_NEXT_DESC_PTR)
-#define bfin_write_DMA1_NEXT_DESC_PTR(val)	bfin_write32(DMA1_NEXT_DESC_PTR, val)
-#define bfin_read_DMA1_START_ADDR()		bfin_read32(DMA1_START_ADDR)
-#define bfin_write_DMA1_START_ADDR(val)		bfin_write32(DMA1_START_ADDR, val)
-#define bfin_read_DMA1_X_COUNT()		bfin_read16(DMA1_X_COUNT)
-#define bfin_write_DMA1_X_COUNT(val)		bfin_write16(DMA1_X_COUNT, val)
-#define bfin_read_DMA1_Y_COUNT()		bfin_read16(DMA1_Y_COUNT)
-#define bfin_write_DMA1_Y_COUNT(val)		bfin_write16(DMA1_Y_COUNT, val)
-#define bfin_read_DMA1_X_MODIFY()		bfin_read16(DMA1_X_MODIFY)
-#define bfin_write_DMA1_X_MODIFY(val)		bfin_write16(DMA1_X_MODIFY, val)
-#define bfin_read_DMA1_Y_MODIFY()		bfin_read16(DMA1_Y_MODIFY)
-#define bfin_write_DMA1_Y_MODIFY(val)		bfin_write16(DMA1_Y_MODIFY, val)
-#define bfin_read_DMA1_CURR_DESC_PTR()		bfin_read32(DMA1_CURR_DESC_PTR)
-#define bfin_write_DMA1_CURR_DESC_PTR(val)	bfin_write32(DMA1_CURR_DESC_PTR, val)
-#define bfin_read_DMA1_CURR_ADDR()		bfin_read32(DMA1_CURR_ADDR)
-#define bfin_write_DMA1_CURR_ADDR(val)		bfin_write32(DMA1_CURR_ADDR, val)
-#define bfin_read_DMA1_CURR_X_COUNT()		bfin_read16(DMA1_CURR_X_COUNT)
-#define bfin_write_DMA1_CURR_X_COUNT(val)	bfin_write16(DMA1_CURR_X_COUNT, val)
-#define bfin_read_DMA1_CURR_Y_COUNT()		bfin_read16(DMA1_CURR_Y_COUNT)
-#define bfin_write_DMA1_CURR_Y_COUNT(val)	bfin_write16(DMA1_CURR_Y_COUNT, val)
-#define bfin_read_DMA1_IRQ_STATUS()		bfin_read16(DMA1_IRQ_STATUS)
-#define bfin_write_DMA1_IRQ_STATUS(val)		bfin_write16(DMA1_IRQ_STATUS, val)
-#define bfin_read_DMA1_PERIPHERAL_MAP()		bfin_read16(DMA1_PERIPHERAL_MAP)
-#define bfin_write_DMA1_PERIPHERAL_MAP(val)	bfin_write16(DMA1_PERIPHERAL_MAP, val)
-
-#define bfin_read_DMA2_CONFIG()			bfin_read16(DMA2_CONFIG)
-#define bfin_write_DMA2_CONFIG(val)		bfin_write16(DMA2_CONFIG, val)
-#define bfin_read_DMA2_NEXT_DESC_PTR()		bfin_read32(DMA2_NEXT_DESC_PTR)
-#define bfin_write_DMA2_NEXT_DESC_PTR(val)	bfin_write32(DMA2_NEXT_DESC_PTR, val)
-#define bfin_read_DMA2_START_ADDR()		bfin_read32(DMA2_START_ADDR)
-#define bfin_write_DMA2_START_ADDR(val)		bfin_write32(DMA2_START_ADDR, val)
-#define bfin_read_DMA2_X_COUNT()		bfin_read16(DMA2_X_COUNT)
-#define bfin_write_DMA2_X_COUNT(val)		bfin_write16(DMA2_X_COUNT, val)
-#define bfin_read_DMA2_Y_COUNT()		bfin_read16(DMA2_Y_COUNT)
-#define bfin_write_DMA2_Y_COUNT(val)		bfin_write16(DMA2_Y_COUNT, val)
-#define bfin_read_DMA2_X_MODIFY()		bfin_read16(DMA2_X_MODIFY)
-#define bfin_write_DMA2_X_MODIFY(val)		bfin_write16(DMA2_X_MODIFY, val)
-#define bfin_read_DMA2_Y_MODIFY()		bfin_read16(DMA2_Y_MODIFY)
-#define bfin_write_DMA2_Y_MODIFY(val)		bfin_write16(DMA2_Y_MODIFY, val)
-#define bfin_read_DMA2_CURR_DESC_PTR()		bfin_read32(DMA2_CURR_DESC_PTR)
-#define bfin_write_DMA2_CURR_DESC_PTR(val)	bfin_write32(DMA2_CURR_DESC_PTR, val)
-#define bfin_read_DMA2_CURR_ADDR()		bfin_read32(DMA2_CURR_ADDR)
-#define bfin_write_DMA2_CURR_ADDR(val)		bfin_write32(DMA2_CURR_ADDR, val)
-#define bfin_read_DMA2_CURR_X_COUNT()		bfin_read16(DMA2_CURR_X_COUNT)
-#define bfin_write_DMA2_CURR_X_COUNT(val)	bfin_write16(DMA2_CURR_X_COUNT, val)
-#define bfin_read_DMA2_CURR_Y_COUNT()		bfin_read16(DMA2_CURR_Y_COUNT)
-#define bfin_write_DMA2_CURR_Y_COUNT(val)	bfin_write16(DMA2_CURR_Y_COUNT, val)
-#define bfin_read_DMA2_IRQ_STATUS()		bfin_read16(DMA2_IRQ_STATUS)
-#define bfin_write_DMA2_IRQ_STATUS(val)		bfin_write16(DMA2_IRQ_STATUS, val)
-#define bfin_read_DMA2_PERIPHERAL_MAP()		bfin_read16(DMA2_PERIPHERAL_MAP)
-#define bfin_write_DMA2_PERIPHERAL_MAP(val)	bfin_write16(DMA2_PERIPHERAL_MAP, val)
-
-#define bfin_read_DMA3_CONFIG()			bfin_read16(DMA3_CONFIG)
-#define bfin_write_DMA3_CONFIG(val)		bfin_write16(DMA3_CONFIG, val)
-#define bfin_read_DMA3_NEXT_DESC_PTR()		bfin_read32(DMA3_NEXT_DESC_PTR)
-#define bfin_write_DMA3_NEXT_DESC_PTR(val)	bfin_write32(DMA3_NEXT_DESC_PTR, val)
-#define bfin_read_DMA3_START_ADDR()		bfin_read32(DMA3_START_ADDR)
-#define bfin_write_DMA3_START_ADDR(val)		bfin_write32(DMA3_START_ADDR, val)
-#define bfin_read_DMA3_X_COUNT()		bfin_read16(DMA3_X_COUNT)
-#define bfin_write_DMA3_X_COUNT(val)		bfin_write16(DMA3_X_COUNT, val)
-#define bfin_read_DMA3_Y_COUNT()		bfin_read16(DMA3_Y_COUNT)
-#define bfin_write_DMA3_Y_COUNT(val)		bfin_write16(DMA3_Y_COUNT, val)
-#define bfin_read_DMA3_X_MODIFY()		bfin_read16(DMA3_X_MODIFY)
-#define bfin_write_DMA3_X_MODIFY(val)		bfin_write16(DMA3_X_MODIFY, val)
-#define bfin_read_DMA3_Y_MODIFY()		bfin_read16(DMA3_Y_MODIFY)
-#define bfin_write_DMA3_Y_MODIFY(val)		bfin_write16(DMA3_Y_MODIFY, val)
-#define bfin_read_DMA3_CURR_DESC_PTR()		bfin_read32(DMA3_CURR_DESC_PTR)
-#define bfin_write_DMA3_CURR_DESC_PTR(val)	bfin_write32(DMA3_CURR_DESC_PTR, val)
-#define bfin_read_DMA3_CURR_ADDR()		bfin_read32(DMA3_CURR_ADDR)
-#define bfin_write_DMA3_CURR_ADDR(val)		bfin_write32(DMA3_CURR_ADDR, val)
-#define bfin_read_DMA3_CURR_X_COUNT()		bfin_read16(DMA3_CURR_X_COUNT)
-#define bfin_write_DMA3_CURR_X_COUNT(val)	bfin_write16(DMA3_CURR_X_COUNT, val)
-#define bfin_read_DMA3_CURR_Y_COUNT()		bfin_read16(DMA3_CURR_Y_COUNT)
-#define bfin_write_DMA3_CURR_Y_COUNT(val)	bfin_write16(DMA3_CURR_Y_COUNT, val)
-#define bfin_read_DMA3_IRQ_STATUS()		bfin_read16(DMA3_IRQ_STATUS)
-#define bfin_write_DMA3_IRQ_STATUS(val)		bfin_write16(DMA3_IRQ_STATUS, val)
-#define bfin_read_DMA3_PERIPHERAL_MAP()		bfin_read16(DMA3_PERIPHERAL_MAP)
-#define bfin_write_DMA3_PERIPHERAL_MAP(val)	bfin_write16(DMA3_PERIPHERAL_MAP, val)
-
-#define bfin_read_DMA4_CONFIG()			bfin_read16(DMA4_CONFIG)
-#define bfin_write_DMA4_CONFIG(val)		bfin_write16(DMA4_CONFIG, val)
-#define bfin_read_DMA4_NEXT_DESC_PTR()		bfin_read32(DMA4_NEXT_DESC_PTR)
-#define bfin_write_DMA4_NEXT_DESC_PTR(val)	bfin_write32(DMA4_NEXT_DESC_PTR, val)
-#define bfin_read_DMA4_START_ADDR()		bfin_read32(DMA4_START_ADDR)
-#define bfin_write_DMA4_START_ADDR(val)		bfin_write32(DMA4_START_ADDR, val)
-#define bfin_read_DMA4_X_COUNT()		bfin_read16(DMA4_X_COUNT)
-#define bfin_write_DMA4_X_COUNT(val)		bfin_write16(DMA4_X_COUNT, val)
-#define bfin_read_DMA4_Y_COUNT()		bfin_read16(DMA4_Y_COUNT)
-#define bfin_write_DMA4_Y_COUNT(val)		bfin_write16(DMA4_Y_COUNT, val)
-#define bfin_read_DMA4_X_MODIFY()		bfin_read16(DMA4_X_MODIFY)
-#define bfin_write_DMA4_X_MODIFY(val)		bfin_write16(DMA4_X_MODIFY, val)
-#define bfin_read_DMA4_Y_MODIFY()		bfin_read16(DMA4_Y_MODIFY)
-#define bfin_write_DMA4_Y_MODIFY(val)		bfin_write16(DMA4_Y_MODIFY, val)
-#define bfin_read_DMA4_CURR_DESC_PTR()		bfin_read32(DMA4_CURR_DESC_PTR)
-#define bfin_write_DMA4_CURR_DESC_PTR(val)	bfin_write32(DMA4_CURR_DESC_PTR, val)
-#define bfin_read_DMA4_CURR_ADDR()		bfin_read32(DMA4_CURR_ADDR)
-#define bfin_write_DMA4_CURR_ADDR(val)		bfin_write32(DMA4_CURR_ADDR, val)
-#define bfin_read_DMA4_CURR_X_COUNT()		bfin_read16(DMA4_CURR_X_COUNT)
-#define bfin_write_DMA4_CURR_X_COUNT(val)	bfin_write16(DMA4_CURR_X_COUNT, val)
-#define bfin_read_DMA4_CURR_Y_COUNT()		bfin_read16(DMA4_CURR_Y_COUNT)
-#define bfin_write_DMA4_CURR_Y_COUNT(val)	bfin_write16(DMA4_CURR_Y_COUNT, val)
-#define bfin_read_DMA4_IRQ_STATUS()		bfin_read16(DMA4_IRQ_STATUS)
-#define bfin_write_DMA4_IRQ_STATUS(val)		bfin_write16(DMA4_IRQ_STATUS, val)
-#define bfin_read_DMA4_PERIPHERAL_MAP()		bfin_read16(DMA4_PERIPHERAL_MAP)
-#define bfin_write_DMA4_PERIPHERAL_MAP(val)	bfin_write16(DMA4_PERIPHERAL_MAP, val)
-
-#define bfin_read_DMA5_CONFIG()			bfin_read16(DMA5_CONFIG)
-#define bfin_write_DMA5_CONFIG(val)		bfin_write16(DMA5_CONFIG, val)
-#define bfin_read_DMA5_NEXT_DESC_PTR()		bfin_read32(DMA5_NEXT_DESC_PTR)
-#define bfin_write_DMA5_NEXT_DESC_PTR(val)	bfin_write32(DMA5_NEXT_DESC_PTR, val)
-#define bfin_read_DMA5_START_ADDR()		bfin_read32(DMA5_START_ADDR)
-#define bfin_write_DMA5_START_ADDR(val)		bfin_write32(DMA5_START_ADDR, val)
-#define bfin_read_DMA5_X_COUNT()		bfin_read16(DMA5_X_COUNT)
-#define bfin_write_DMA5_X_COUNT(val)		bfin_write16(DMA5_X_COUNT, val)
-#define bfin_read_DMA5_Y_COUNT()		bfin_read16(DMA5_Y_COUNT)
-#define bfin_write_DMA5_Y_COUNT(val)		bfin_write16(DMA5_Y_COUNT, val)
-#define bfin_read_DMA5_X_MODIFY()		bfin_read16(DMA5_X_MODIFY)
-#define bfin_write_DMA5_X_MODIFY(val)		bfin_write16(DMA5_X_MODIFY, val)
-#define bfin_read_DMA5_Y_MODIFY()		bfin_read16(DMA5_Y_MODIFY)
-#define bfin_write_DMA5_Y_MODIFY(val)		bfin_write16(DMA5_Y_MODIFY, val)
-#define bfin_read_DMA5_CURR_DESC_PTR()		bfin_read32(DMA5_CURR_DESC_PTR)
-#define bfin_write_DMA5_CURR_DESC_PTR(val)	bfin_write32(DMA5_CURR_DESC_PTR, val)
-#define bfin_read_DMA5_CURR_ADDR()		bfin_read32(DMA5_CURR_ADDR)
-#define bfin_write_DMA5_CURR_ADDR(val)		bfin_write32(DMA5_CURR_ADDR, val)
-#define bfin_read_DMA5_CURR_X_COUNT()		bfin_read16(DMA5_CURR_X_COUNT)
-#define bfin_write_DMA5_CURR_X_COUNT(val)	bfin_write16(DMA5_CURR_X_COUNT, val)
-#define bfin_read_DMA5_CURR_Y_COUNT()		bfin_read16(DMA5_CURR_Y_COUNT)
-#define bfin_write_DMA5_CURR_Y_COUNT(val)	bfin_write16(DMA5_CURR_Y_COUNT, val)
-#define bfin_read_DMA5_IRQ_STATUS()		bfin_read16(DMA5_IRQ_STATUS)
-#define bfin_write_DMA5_IRQ_STATUS(val)		bfin_write16(DMA5_IRQ_STATUS, val)
-#define bfin_read_DMA5_PERIPHERAL_MAP()		bfin_read16(DMA5_PERIPHERAL_MAP)
-#define bfin_write_DMA5_PERIPHERAL_MAP(val)	bfin_write16(DMA5_PERIPHERAL_MAP, val)
-
-#define bfin_read_DMA6_CONFIG()			bfin_read16(DMA6_CONFIG)
-#define bfin_write_DMA6_CONFIG(val)		bfin_write16(DMA6_CONFIG, val)
-#define bfin_read_DMA6_NEXT_DESC_PTR()		bfin_read32(DMA6_NEXT_DESC_PTR)
-#define bfin_write_DMA6_NEXT_DESC_PTR(val)	bfin_write32(DMA6_NEXT_DESC_PTR, val)
-#define bfin_read_DMA6_START_ADDR()		bfin_read32(DMA6_START_ADDR)
-#define bfin_write_DMA6_START_ADDR(val)		bfin_write32(DMA6_START_ADDR, val)
-#define bfin_read_DMA6_X_COUNT()		bfin_read16(DMA6_X_COUNT)
-#define bfin_write_DMA6_X_COUNT(val)		bfin_write16(DMA6_X_COUNT, val)
-#define bfin_read_DMA6_Y_COUNT()		bfin_read16(DMA6_Y_COUNT)
-#define bfin_write_DMA6_Y_COUNT(val)		bfin_write16(DMA6_Y_COUNT, val)
-#define bfin_read_DMA6_X_MODIFY()		bfin_read16(DMA6_X_MODIFY)
-#define bfin_write_DMA6_X_MODIFY(val)		bfin_write16(DMA6_X_MODIFY, val)
-#define bfin_read_DMA6_Y_MODIFY()		bfin_read16(DMA6_Y_MODIFY)
-#define bfin_write_DMA6_Y_MODIFY(val)		bfin_write16(DMA6_Y_MODIFY, val)
-#define bfin_read_DMA6_CURR_DESC_PTR()		bfin_read32(DMA6_CURR_DESC_PTR)
-#define bfin_write_DMA6_CURR_DESC_PTR(val)	bfin_write32(DMA6_CURR_DESC_PTR, val)
-#define bfin_read_DMA6_CURR_ADDR()		bfin_read32(DMA6_CURR_ADDR)
-#define bfin_write_DMA6_CURR_ADDR(val)		bfin_write32(DMA6_CURR_ADDR, val)
-#define bfin_read_DMA6_CURR_X_COUNT()		bfin_read16(DMA6_CURR_X_COUNT)
-#define bfin_write_DMA6_CURR_X_COUNT(val)	bfin_write16(DMA6_CURR_X_COUNT, val)
-#define bfin_read_DMA6_CURR_Y_COUNT()		bfin_read16(DMA6_CURR_Y_COUNT)
-#define bfin_write_DMA6_CURR_Y_COUNT(val)	bfin_write16(DMA6_CURR_Y_COUNT, val)
-#define bfin_read_DMA6_IRQ_STATUS()		bfin_read16(DMA6_IRQ_STATUS)
-#define bfin_write_DMA6_IRQ_STATUS(val)		bfin_write16(DMA6_IRQ_STATUS, val)
-#define bfin_read_DMA6_PERIPHERAL_MAP()		bfin_read16(DMA6_PERIPHERAL_MAP)
-#define bfin_write_DMA6_PERIPHERAL_MAP(val)	bfin_write16(DMA6_PERIPHERAL_MAP, val)
-
-#define bfin_read_DMA7_CONFIG()			bfin_read16(DMA7_CONFIG)
-#define bfin_write_DMA7_CONFIG(val)		bfin_write16(DMA7_CONFIG, val)
-#define bfin_read_DMA7_NEXT_DESC_PTR()		bfin_read32(DMA7_NEXT_DESC_PTR)
-#define bfin_write_DMA7_NEXT_DESC_PTR(val)	bfin_write32(DMA7_NEXT_DESC_PTR, val)
-#define bfin_read_DMA7_START_ADDR()		bfin_read32(DMA7_START_ADDR)
-#define bfin_write_DMA7_START_ADDR(val)		bfin_write32(DMA7_START_ADDR, val)
-#define bfin_read_DMA7_X_COUNT()		bfin_read16(DMA7_X_COUNT)
-#define bfin_write_DMA7_X_COUNT(val)		bfin_write16(DMA7_X_COUNT, val)
-#define bfin_read_DMA7_Y_COUNT()		bfin_read16(DMA7_Y_COUNT)
-#define bfin_write_DMA7_Y_COUNT(val)		bfin_write16(DMA7_Y_COUNT, val)
-#define bfin_read_DMA7_X_MODIFY()		bfin_read16(DMA7_X_MODIFY)
-#define bfin_write_DMA7_X_MODIFY(val)		bfin_write16(DMA7_X_MODIFY, val)
-#define bfin_read_DMA7_Y_MODIFY()		bfin_read16(DMA7_Y_MODIFY)
-#define bfin_write_DMA7_Y_MODIFY(val)		bfin_write16(DMA7_Y_MODIFY, val)
-#define bfin_read_DMA7_CURR_DESC_PTR()		bfin_read32(DMA7_CURR_DESC_PTR)
-#define bfin_write_DMA7_CURR_DESC_PTR(val)	bfin_write32(DMA7_CURR_DESC_PTR, val)
-#define bfin_read_DMA7_CURR_ADDR()		bfin_read32(DMA7_CURR_ADDR)
-#define bfin_write_DMA7_CURR_ADDR(val)		bfin_write32(DMA7_CURR_ADDR, val)
-#define bfin_read_DMA7_CURR_X_COUNT()		bfin_read16(DMA7_CURR_X_COUNT)
-#define bfin_write_DMA7_CURR_X_COUNT(val)	bfin_write16(DMA7_CURR_X_COUNT, val)
-#define bfin_read_DMA7_CURR_Y_COUNT()		bfin_read16(DMA7_CURR_Y_COUNT)
-#define bfin_write_DMA7_CURR_Y_COUNT(val)	bfin_write16(DMA7_CURR_Y_COUNT, val)
-#define bfin_read_DMA7_IRQ_STATUS()		bfin_read16(DMA7_IRQ_STATUS)
-#define bfin_write_DMA7_IRQ_STATUS(val)		bfin_write16(DMA7_IRQ_STATUS, val)
-#define bfin_read_DMA7_PERIPHERAL_MAP()		bfin_read16(DMA7_PERIPHERAL_MAP)
-#define bfin_write_DMA7_PERIPHERAL_MAP(val)	bfin_write16(DMA7_PERIPHERAL_MAP, val)
-
-#define bfin_read_DMA8_CONFIG()			bfin_read16(DMA8_CONFIG)
-#define bfin_write_DMA8_CONFIG(val)		bfin_write16(DMA8_CONFIG, val)
-#define bfin_read_DMA8_NEXT_DESC_PTR()		bfin_read32(DMA8_NEXT_DESC_PTR)
-#define bfin_write_DMA8_NEXT_DESC_PTR(val)	bfin_write32(DMA8_NEXT_DESC_PTR, val)
-#define bfin_read_DMA8_START_ADDR()		bfin_read32(DMA8_START_ADDR)
-#define bfin_write_DMA8_START_ADDR(val)		bfin_write32(DMA8_START_ADDR, val)
-#define bfin_read_DMA8_X_COUNT()		bfin_read16(DMA8_X_COUNT)
-#define bfin_write_DMA8_X_COUNT(val)		bfin_write16(DMA8_X_COUNT, val)
-#define bfin_read_DMA8_Y_COUNT()		bfin_read16(DMA8_Y_COUNT)
-#define bfin_write_DMA8_Y_COUNT(val)		bfin_write16(DMA8_Y_COUNT, val)
-#define bfin_read_DMA8_X_MODIFY()		bfin_read16(DMA8_X_MODIFY)
-#define bfin_write_DMA8_X_MODIFY(val)		bfin_write16(DMA8_X_MODIFY, val)
-#define bfin_read_DMA8_Y_MODIFY()		bfin_read16(DMA8_Y_MODIFY)
-#define bfin_write_DMA8_Y_MODIFY(val)		bfin_write16(DMA8_Y_MODIFY, val)
-#define bfin_read_DMA8_CURR_DESC_PTR()		bfin_read32(DMA8_CURR_DESC_PTR)
-#define bfin_write_DMA8_CURR_DESC_PTR(val)	bfin_write32(DMA8_CURR_DESC_PTR, val)
-#define bfin_read_DMA8_CURR_ADDR()		bfin_read32(DMA8_CURR_ADDR)
-#define bfin_write_DMA8_CURR_ADDR(val)		bfin_write32(DMA8_CURR_ADDR, val)
-#define bfin_read_DMA8_CURR_X_COUNT()		bfin_read16(DMA8_CURR_X_COUNT)
-#define bfin_write_DMA8_CURR_X_COUNT(val)	bfin_write16(DMA8_CURR_X_COUNT, val)
-#define bfin_read_DMA8_CURR_Y_COUNT()		bfin_read16(DMA8_CURR_Y_COUNT)
-#define bfin_write_DMA8_CURR_Y_COUNT(val)	bfin_write16(DMA8_CURR_Y_COUNT, val)
-#define bfin_read_DMA8_IRQ_STATUS()		bfin_read16(DMA8_IRQ_STATUS)
-#define bfin_write_DMA8_IRQ_STATUS(val)		bfin_write16(DMA8_IRQ_STATUS, val)
-#define bfin_read_DMA8_PERIPHERAL_MAP()		bfin_read16(DMA8_PERIPHERAL_MAP)
-#define bfin_write_DMA8_PERIPHERAL_MAP(val)	bfin_write16(DMA8_PERIPHERAL_MAP, val)
-
-#define bfin_read_DMA9_CONFIG()			bfin_read16(DMA9_CONFIG)
-#define bfin_write_DMA9_CONFIG(val)		bfin_write16(DMA9_CONFIG, val)
-#define bfin_read_DMA9_NEXT_DESC_PTR()		bfin_read32(DMA9_NEXT_DESC_PTR)
-#define bfin_write_DMA9_NEXT_DESC_PTR(val)	bfin_write32(DMA9_NEXT_DESC_PTR, val)
-#define bfin_read_DMA9_START_ADDR()		bfin_read32(DMA9_START_ADDR)
-#define bfin_write_DMA9_START_ADDR(val)		bfin_write32(DMA9_START_ADDR, val)
-#define bfin_read_DMA9_X_COUNT()		bfin_read16(DMA9_X_COUNT)
-#define bfin_write_DMA9_X_COUNT(val)		bfin_write16(DMA9_X_COUNT, val)
-#define bfin_read_DMA9_Y_COUNT()		bfin_read16(DMA9_Y_COUNT)
-#define bfin_write_DMA9_Y_COUNT(val)		bfin_write16(DMA9_Y_COUNT, val)
-#define bfin_read_DMA9_X_MODIFY()		bfin_read16(DMA9_X_MODIFY)
-#define bfin_write_DMA9_X_MODIFY(val)		bfin_write16(DMA9_X_MODIFY, val)
-#define bfin_read_DMA9_Y_MODIFY()		bfin_read16(DMA9_Y_MODIFY)
-#define bfin_write_DMA9_Y_MODIFY(val)		bfin_write16(DMA9_Y_MODIFY, val)
-#define bfin_read_DMA9_CURR_DESC_PTR()		bfin_read32(DMA9_CURR_DESC_PTR)
-#define bfin_write_DMA9_CURR_DESC_PTR(val)	bfin_write32(DMA9_CURR_DESC_PTR, val)
-#define bfin_read_DMA9_CURR_ADDR()		bfin_read32(DMA9_CURR_ADDR)
-#define bfin_write_DMA9_CURR_ADDR(val)		bfin_write32(DMA9_CURR_ADDR, val)
-#define bfin_read_DMA9_CURR_X_COUNT()		bfin_read16(DMA9_CURR_X_COUNT)
-#define bfin_write_DMA9_CURR_X_COUNT(val)	bfin_write16(DMA9_CURR_X_COUNT, val)
-#define bfin_read_DMA9_CURR_Y_COUNT()		bfin_read16(DMA9_CURR_Y_COUNT)
-#define bfin_write_DMA9_CURR_Y_COUNT(val)	bfin_write16(DMA9_CURR_Y_COUNT, val)
-#define bfin_read_DMA9_IRQ_STATUS()		bfin_read16(DMA9_IRQ_STATUS)
-#define bfin_write_DMA9_IRQ_STATUS(val)		bfin_write16(DMA9_IRQ_STATUS, val)
-#define bfin_read_DMA9_PERIPHERAL_MAP()		bfin_read16(DMA9_PERIPHERAL_MAP)
-#define bfin_write_DMA9_PERIPHERAL_MAP(val)	bfin_write16(DMA9_PERIPHERAL_MAP, val)
-
-#define bfin_read_DMA10_CONFIG()		bfin_read16(DMA10_CONFIG)
-#define bfin_write_DMA10_CONFIG(val)		bfin_write16(DMA10_CONFIG, val)
-#define bfin_read_DMA10_NEXT_DESC_PTR()		bfin_read32(DMA10_NEXT_DESC_PTR)
-#define bfin_write_DMA10_NEXT_DESC_PTR(val)	bfin_write32(DMA10_NEXT_DESC_PTR, val)
-#define bfin_read_DMA10_START_ADDR()		bfin_read32(DMA10_START_ADDR)
-#define bfin_write_DMA10_START_ADDR(val)	bfin_write32(DMA10_START_ADDR, val)
-#define bfin_read_DMA10_X_COUNT()		bfin_read16(DMA10_X_COUNT)
-#define bfin_write_DMA10_X_COUNT(val)		bfin_write16(DMA10_X_COUNT, val)
-#define bfin_read_DMA10_Y_COUNT()		bfin_read16(DMA10_Y_COUNT)
-#define bfin_write_DMA10_Y_COUNT(val)		bfin_write16(DMA10_Y_COUNT, val)
-#define bfin_read_DMA10_X_MODIFY()		bfin_read16(DMA10_X_MODIFY)
-#define bfin_write_DMA10_X_MODIFY(val)		bfin_write16(DMA10_X_MODIFY, val)
-#define bfin_read_DMA10_Y_MODIFY()		bfin_read16(DMA10_Y_MODIFY)
-#define bfin_write_DMA10_Y_MODIFY(val)		bfin_write16(DMA10_Y_MODIFY, val)
-#define bfin_read_DMA10_CURR_DESC_PTR()		bfin_read32(DMA10_CURR_DESC_PTR)
-#define bfin_write_DMA10_CURR_DESC_PTR(val)	bfin_write32(DMA10_CURR_DESC_PTR, val)
-#define bfin_read_DMA10_CURR_ADDR()		bfin_read32(DMA10_CURR_ADDR)
-#define bfin_write_DMA10_CURR_ADDR(val)		bfin_write32(DMA10_CURR_ADDR, val)
-#define bfin_read_DMA10_CURR_X_COUNT()		bfin_read16(DMA10_CURR_X_COUNT)
-#define bfin_write_DMA10_CURR_X_COUNT(val)	bfin_write16(DMA10_CURR_X_COUNT, val)
-#define bfin_read_DMA10_CURR_Y_COUNT()		bfin_read16(DMA10_CURR_Y_COUNT)
-#define bfin_write_DMA10_CURR_Y_COUNT(val)	bfin_write16(DMA10_CURR_Y_COUNT, val)
-#define bfin_read_DMA10_IRQ_STATUS()		bfin_read16(DMA10_IRQ_STATUS)
-#define bfin_write_DMA10_IRQ_STATUS(val)	bfin_write16(DMA10_IRQ_STATUS, val)
-#define bfin_read_DMA10_PERIPHERAL_MAP()	bfin_read16(DMA10_PERIPHERAL_MAP)
-#define bfin_write_DMA10_PERIPHERAL_MAP(val)	bfin_write16(DMA10_PERIPHERAL_MAP, val)
-
-#define bfin_read_DMA11_CONFIG()		bfin_read16(DMA11_CONFIG)
-#define bfin_write_DMA11_CONFIG(val)		bfin_write16(DMA11_CONFIG, val)
-#define bfin_read_DMA11_NEXT_DESC_PTR()		bfin_read32(DMA11_NEXT_DESC_PTR)
-#define bfin_write_DMA11_NEXT_DESC_PTR(val)	bfin_write32(DMA11_NEXT_DESC_PTR, val)
-#define bfin_read_DMA11_START_ADDR()		bfin_read32(DMA11_START_ADDR)
-#define bfin_write_DMA11_START_ADDR(val)	bfin_write32(DMA11_START_ADDR, val)
-#define bfin_read_DMA11_X_COUNT()		bfin_read16(DMA11_X_COUNT)
-#define bfin_write_DMA11_X_COUNT(val)		bfin_write16(DMA11_X_COUNT, val)
-#define bfin_read_DMA11_Y_COUNT()		bfin_read16(DMA11_Y_COUNT)
-#define bfin_write_DMA11_Y_COUNT(val)		bfin_write16(DMA11_Y_COUNT, val)
-#define bfin_read_DMA11_X_MODIFY()		bfin_read16(DMA11_X_MODIFY)
-#define bfin_write_DMA11_X_MODIFY(val)		bfin_write16(DMA11_X_MODIFY, val)
-#define bfin_read_DMA11_Y_MODIFY()		bfin_read16(DMA11_Y_MODIFY)
-#define bfin_write_DMA11_Y_MODIFY(val)		bfin_write16(DMA11_Y_MODIFY, val)
-#define bfin_read_DMA11_CURR_DESC_PTR()		bfin_read32(DMA11_CURR_DESC_PTR)
-#define bfin_write_DMA11_CURR_DESC_PTR(val)	bfin_write32(DMA11_CURR_DESC_PTR, val)
-#define bfin_read_DMA11_CURR_ADDR()		bfin_read32(DMA11_CURR_ADDR)
-#define bfin_write_DMA11_CURR_ADDR(val)		bfin_write32(DMA11_CURR_ADDR, val)
-#define bfin_read_DMA11_CURR_X_COUNT()		bfin_read16(DMA11_CURR_X_COUNT)
-#define bfin_write_DMA11_CURR_X_COUNT(val)	bfin_write16(DMA11_CURR_X_COUNT, val)
-#define bfin_read_DMA11_CURR_Y_COUNT()		bfin_read16(DMA11_CURR_Y_COUNT)
-#define bfin_write_DMA11_CURR_Y_COUNT(val)	bfin_write16(DMA11_CURR_Y_COUNT, val)
-#define bfin_read_DMA11_IRQ_STATUS()		bfin_read16(DMA11_IRQ_STATUS)
-#define bfin_write_DMA11_IRQ_STATUS(val)	bfin_write16(DMA11_IRQ_STATUS, val)
-#define bfin_read_DMA11_PERIPHERAL_MAP()	bfin_read16(DMA11_PERIPHERAL_MAP)
-#define bfin_write_DMA11_PERIPHERAL_MAP(val)	bfin_write16(DMA11_PERIPHERAL_MAP, val)
-
-#define bfin_read_MDMA_D0_CONFIG()		bfin_read16(MDMA_D0_CONFIG)
-#define bfin_write_MDMA_D0_CONFIG(val)		bfin_write16(MDMA_D0_CONFIG, val)
-#define bfin_read_MDMA_D0_NEXT_DESC_PTR()	bfin_read32(MDMA_D0_NEXT_DESC_PTR)
-#define bfin_write_MDMA_D0_NEXT_DESC_PTR(val)	bfin_write32(MDMA_D0_NEXT_DESC_PTR, val)
-#define bfin_read_MDMA_D0_START_ADDR()		bfin_read32(MDMA_D0_START_ADDR)
-#define bfin_write_MDMA_D0_START_ADDR(val)	bfin_write32(MDMA_D0_START_ADDR, val)
-#define bfin_read_MDMA_D0_X_COUNT()		bfin_read16(MDMA_D0_X_COUNT)
-#define bfin_write_MDMA_D0_X_COUNT(val)		bfin_write16(MDMA_D0_X_COUNT, val)
-#define bfin_read_MDMA_D0_Y_COUNT()		bfin_read16(MDMA_D0_Y_COUNT)
-#define bfin_write_MDMA_D0_Y_COUNT(val)		bfin_write16(MDMA_D0_Y_COUNT, val)
-#define bfin_read_MDMA_D0_X_MODIFY()		bfin_read16(MDMA_D0_X_MODIFY)
-#define bfin_write_MDMA_D0_X_MODIFY(val)	bfin_write16(MDMA_D0_X_MODIFY, val)
-#define bfin_read_MDMA_D0_Y_MODIFY()		bfin_read16(MDMA_D0_Y_MODIFY)
-#define bfin_write_MDMA_D0_Y_MODIFY(val)	bfin_write16(MDMA_D0_Y_MODIFY, val)
-#define bfin_read_MDMA_D0_CURR_DESC_PTR()	bfin_read32(MDMA_D0_CURR_DESC_PTR)
-#define bfin_write_MDMA_D0_CURR_DESC_PTR(val)	bfin_write32(MDMA_D0_CURR_DESC_PTR, val)
-#define bfin_read_MDMA_D0_CURR_ADDR()		bfin_read32(MDMA_D0_CURR_ADDR)
-#define bfin_write_MDMA_D0_CURR_ADDR(val)	bfin_write32(MDMA_D0_CURR_ADDR, val)
-#define bfin_read_MDMA_D0_CURR_X_COUNT()	bfin_read16(MDMA_D0_CURR_X_COUNT)
-#define bfin_write_MDMA_D0_CURR_X_COUNT(val)	bfin_write16(MDMA_D0_CURR_X_COUNT, val)
-#define bfin_read_MDMA_D0_CURR_Y_COUNT()	bfin_read16(MDMA_D0_CURR_Y_COUNT)
-#define bfin_write_MDMA_D0_CURR_Y_COUNT(val)	bfin_write16(MDMA_D0_CURR_Y_COUNT, val)
-#define bfin_read_MDMA_D0_IRQ_STATUS()		bfin_read16(MDMA_D0_IRQ_STATUS)
-#define bfin_write_MDMA_D0_IRQ_STATUS(val)	bfin_write16(MDMA_D0_IRQ_STATUS, val)
-#define bfin_read_MDMA_D0_PERIPHERAL_MAP()	bfin_read16(MDMA_D0_PERIPHERAL_MAP)
-#define bfin_write_MDMA_D0_PERIPHERAL_MAP(val)	bfin_write16(MDMA_D0_PERIPHERAL_MAP, val)
-
-#define bfin_read_MDMA_S0_CONFIG()		bfin_read16(MDMA_S0_CONFIG)
-#define bfin_write_MDMA_S0_CONFIG(val)		bfin_write16(MDMA_S0_CONFIG, val)
-#define bfin_read_MDMA_S0_NEXT_DESC_PTR()	bfin_read32(MDMA_S0_NEXT_DESC_PTR)
-#define bfin_write_MDMA_S0_NEXT_DESC_PTR(val)	bfin_write32(MDMA_S0_NEXT_DESC_PTR, val)
-#define bfin_read_MDMA_S0_START_ADDR()		bfin_read32(MDMA_S0_START_ADDR)
-#define bfin_write_MDMA_S0_START_ADDR(val)	bfin_write32(MDMA_S0_START_ADDR, val)
-#define bfin_read_MDMA_S0_X_COUNT()		bfin_read16(MDMA_S0_X_COUNT)
-#define bfin_write_MDMA_S0_X_COUNT(val)		bfin_write16(MDMA_S0_X_COUNT, val)
-#define bfin_read_MDMA_S0_Y_COUNT()		bfin_read16(MDMA_S0_Y_COUNT)
-#define bfin_write_MDMA_S0_Y_COUNT(val)		bfin_write16(MDMA_S0_Y_COUNT, val)
-#define bfin_read_MDMA_S0_X_MODIFY()		bfin_read16(MDMA_S0_X_MODIFY)
-#define bfin_write_MDMA_S0_X_MODIFY(val)	bfin_write16(MDMA_S0_X_MODIFY, val)
-#define bfin_read_MDMA_S0_Y_MODIFY()		bfin_read16(MDMA_S0_Y_MODIFY)
-#define bfin_write_MDMA_S0_Y_MODIFY(val)	bfin_write16(MDMA_S0_Y_MODIFY, val)
-#define bfin_read_MDMA_S0_CURR_DESC_PTR()	bfin_read32(MDMA_S0_CURR_DESC_PTR)
-#define bfin_write_MDMA_S0_CURR_DESC_PTR(val)	bfin_write32(MDMA_S0_CURR_DESC_PTR, val)
-#define bfin_read_MDMA_S0_CURR_ADDR()		bfin_read32(MDMA_S0_CURR_ADDR)
-#define bfin_write_MDMA_S0_CURR_ADDR(val)	bfin_write32(MDMA_S0_CURR_ADDR, val)
-#define bfin_read_MDMA_S0_CURR_X_COUNT()	bfin_read16(MDMA_S0_CURR_X_COUNT)
-#define bfin_write_MDMA_S0_CURR_X_COUNT(val)	bfin_write16(MDMA_S0_CURR_X_COUNT, val)
-#define bfin_read_MDMA_S0_CURR_Y_COUNT()	bfin_read16(MDMA_S0_CURR_Y_COUNT)
-#define bfin_write_MDMA_S0_CURR_Y_COUNT(val)	bfin_write16(MDMA_S0_CURR_Y_COUNT, val)
-#define bfin_read_MDMA_S0_IRQ_STATUS()		bfin_read16(MDMA_S0_IRQ_STATUS)
-#define bfin_write_MDMA_S0_IRQ_STATUS(val)	bfin_write16(MDMA_S0_IRQ_STATUS, val)
-#define bfin_read_MDMA_S0_PERIPHERAL_MAP()	bfin_read16(MDMA_S0_PERIPHERAL_MAP)
-#define bfin_write_MDMA_S0_PERIPHERAL_MAP(val)	bfin_write16(MDMA_S0_PERIPHERAL_MAP, val)
-
-#define bfin_read_MDMA_D1_CONFIG()		bfin_read16(MDMA_D1_CONFIG)
-#define bfin_write_MDMA_D1_CONFIG(val)		bfin_write16(MDMA_D1_CONFIG, val)
-#define bfin_read_MDMA_D1_NEXT_DESC_PTR()	bfin_read32(MDMA_D1_NEXT_DESC_PTR)
-#define bfin_write_MDMA_D1_NEXT_DESC_PTR(val)	bfin_write32(MDMA_D1_NEXT_DESC_PTR, val)
-#define bfin_read_MDMA_D1_START_ADDR()		bfin_read32(MDMA_D1_START_ADDR)
-#define bfin_write_MDMA_D1_START_ADDR(val)	bfin_write32(MDMA_D1_START_ADDR, val)
-#define bfin_read_MDMA_D1_X_COUNT()		bfin_read16(MDMA_D1_X_COUNT)
-#define bfin_write_MDMA_D1_X_COUNT(val)		bfin_write16(MDMA_D1_X_COUNT, val)
-#define bfin_read_MDMA_D1_Y_COUNT()		bfin_read16(MDMA_D1_Y_COUNT)
-#define bfin_write_MDMA_D1_Y_COUNT(val)		bfin_write16(MDMA_D1_Y_COUNT, val)
-#define bfin_read_MDMA_D1_X_MODIFY()		bfin_read16(MDMA_D1_X_MODIFY)
-#define bfin_write_MDMA_D1_X_MODIFY(val)	bfin_write16(MDMA_D1_X_MODIFY, val)
-#define bfin_read_MDMA_D1_Y_MODIFY()		bfin_read16(MDMA_D1_Y_MODIFY)
-#define bfin_write_MDMA_D1_Y_MODIFY(val)	bfin_write16(MDMA_D1_Y_MODIFY, val)
-#define bfin_read_MDMA_D1_CURR_DESC_PTR()	bfin_read32(MDMA_D1_CURR_DESC_PTR)
-#define bfin_write_MDMA_D1_CURR_DESC_PTR(val)	bfin_write32(MDMA_D1_CURR_DESC_PTR, val)
-#define bfin_read_MDMA_D1_CURR_ADDR()		bfin_read32(MDMA_D1_CURR_ADDR)
-#define bfin_write_MDMA_D1_CURR_ADDR(val)	bfin_write32(MDMA_D1_CURR_ADDR, val)
-#define bfin_read_MDMA_D1_CURR_X_COUNT()	bfin_read16(MDMA_D1_CURR_X_COUNT)
-#define bfin_write_MDMA_D1_CURR_X_COUNT(val)	bfin_write16(MDMA_D1_CURR_X_COUNT, val)
-#define bfin_read_MDMA_D1_CURR_Y_COUNT()	bfin_read16(MDMA_D1_CURR_Y_COUNT)
-#define bfin_write_MDMA_D1_CURR_Y_COUNT(val)	bfin_write16(MDMA_D1_CURR_Y_COUNT, val)
-#define bfin_read_MDMA_D1_IRQ_STATUS()		bfin_read16(MDMA_D1_IRQ_STATUS)
-#define bfin_write_MDMA_D1_IRQ_STATUS(val)	bfin_write16(MDMA_D1_IRQ_STATUS, val)
-#define bfin_read_MDMA_D1_PERIPHERAL_MAP()	bfin_read16(MDMA_D1_PERIPHERAL_MAP)
-#define bfin_write_MDMA_D1_PERIPHERAL_MAP(val)	bfin_write16(MDMA_D1_PERIPHERAL_MAP, val)
-
-#define bfin_read_MDMA_S1_CONFIG()		bfin_read16(MDMA_S1_CONFIG)
-#define bfin_write_MDMA_S1_CONFIG(val)		bfin_write16(MDMA_S1_CONFIG, val)
-#define bfin_read_MDMA_S1_NEXT_DESC_PTR()	bfin_read32(MDMA_S1_NEXT_DESC_PTR)
-#define bfin_write_MDMA_S1_NEXT_DESC_PTR(val)	bfin_write32(MDMA_S1_NEXT_DESC_PTR, val)
-#define bfin_read_MDMA_S1_START_ADDR()		bfin_read32(MDMA_S1_START_ADDR)
-#define bfin_write_MDMA_S1_START_ADDR(val)	bfin_write32(MDMA_S1_START_ADDR, val)
-#define bfin_read_MDMA_S1_X_COUNT()		bfin_read16(MDMA_S1_X_COUNT)
-#define bfin_write_MDMA_S1_X_COUNT(val)		bfin_write16(MDMA_S1_X_COUNT, val)
-#define bfin_read_MDMA_S1_Y_COUNT()		bfin_read16(MDMA_S1_Y_COUNT)
-#define bfin_write_MDMA_S1_Y_COUNT(val)		bfin_write16(MDMA_S1_Y_COUNT, val)
-#define bfin_read_MDMA_S1_X_MODIFY()		bfin_read16(MDMA_S1_X_MODIFY)
-#define bfin_write_MDMA_S1_X_MODIFY(val)	bfin_write16(MDMA_S1_X_MODIFY, val)
-#define bfin_read_MDMA_S1_Y_MODIFY()		bfin_read16(MDMA_S1_Y_MODIFY)
-#define bfin_write_MDMA_S1_Y_MODIFY(val)	bfin_write16(MDMA_S1_Y_MODIFY, val)
-#define bfin_read_MDMA_S1_CURR_DESC_PTR()	bfin_read32(MDMA_S1_CURR_DESC_PTR)
-#define bfin_write_MDMA_S1_CURR_DESC_PTR(val)	bfin_write32(MDMA_S1_CURR_DESC_PTR, val)
-#define bfin_read_MDMA_S1_CURR_ADDR()		bfin_read32(MDMA_S1_CURR_ADDR)
-#define bfin_write_MDMA_S1_CURR_ADDR(val)	bfin_write32(MDMA_S1_CURR_ADDR, val)
-#define bfin_read_MDMA_S1_CURR_X_COUNT()	bfin_read16(MDMA_S1_CURR_X_COUNT)
-#define bfin_write_MDMA_S1_CURR_X_COUNT(val)	bfin_write16(MDMA_S1_CURR_X_COUNT, val)
-#define bfin_read_MDMA_S1_CURR_Y_COUNT()	bfin_read16(MDMA_S1_CURR_Y_COUNT)
-#define bfin_write_MDMA_S1_CURR_Y_COUNT(val)	bfin_write16(MDMA_S1_CURR_Y_COUNT, val)
-#define bfin_read_MDMA_S1_IRQ_STATUS()		bfin_read16(MDMA_S1_IRQ_STATUS)
-#define bfin_write_MDMA_S1_IRQ_STATUS(val)	bfin_write16(MDMA_S1_IRQ_STATUS, val)
-#define bfin_read_MDMA_S1_PERIPHERAL_MAP()	bfin_read16(MDMA_S1_PERIPHERAL_MAP)
-#define bfin_write_MDMA_S1_PERIPHERAL_MAP(val)	bfin_write16(MDMA_S1_PERIPHERAL_MAP, val)
-
-
-/* Parallel Peripheral Interface (0xFFC01000 - 0xFFC010FF)							*/
-#define bfin_read_PPI_CONTROL()			bfin_read16(PPI_CONTROL)
-#define bfin_write_PPI_CONTROL(val)		bfin_write16(PPI_CONTROL, val)
-#define bfin_read_PPI_STATUS()			bfin_read16(PPI_STATUS)
-#define bfin_write_PPI_STATUS(val)		bfin_write16(PPI_STATUS, val)
-#define bfin_clear_PPI_STATUS()			bfin_write_PPI_STATUS(0xFFFF)
-#define bfin_read_PPI_DELAY()			bfin_read16(PPI_DELAY)
-#define bfin_write_PPI_DELAY(val)		bfin_write16(PPI_DELAY, val)
-#define bfin_read_PPI_COUNT()			bfin_read16(PPI_COUNT)
-#define bfin_write_PPI_COUNT(val)		bfin_write16(PPI_COUNT, val)
-#define bfin_read_PPI_FRAME()			bfin_read16(PPI_FRAME)
-#define bfin_write_PPI_FRAME(val)		bfin_write16(PPI_FRAME, val)
-
-
-/* Two-Wire Interface		(0xFFC01400 - 0xFFC014FF)								*/
-
-/* General Purpose I/O Port G (0xFFC01500 - 0xFFC015FF)								*/
-#define bfin_read_PORTGIO()			bfin_read16(PORTGIO)
-#define bfin_write_PORTGIO(val)			bfin_write16(PORTGIO, val)
-#define bfin_read_PORTGIO_CLEAR()		bfin_read16(PORTGIO_CLEAR)
-#define bfin_write_PORTGIO_CLEAR(val)		bfin_write16(PORTGIO_CLEAR, val)
-#define bfin_read_PORTGIO_SET()			bfin_read16(PORTGIO_SET)
-#define bfin_write_PORTGIO_SET(val)		bfin_write16(PORTGIO_SET, val)
-#define bfin_read_PORTGIO_TOGGLE()		bfin_read16(PORTGIO_TOGGLE)
-#define bfin_write_PORTGIO_TOGGLE(val)		bfin_write16(PORTGIO_TOGGLE, val)
-#define bfin_read_PORTGIO_MASKA()		bfin_read16(PORTGIO_MASKA)
-#define bfin_write_PORTGIO_MASKA(val)		bfin_write16(PORTGIO_MASKA, val)
-#define bfin_read_PORTGIO_MASKA_CLEAR()		bfin_read16(PORTGIO_MASKA_CLEAR)
-#define bfin_write_PORTGIO_MASKA_CLEAR(val)	bfin_write16(PORTGIO_MASKA_CLEAR, val)
-#define bfin_read_PORTGIO_MASKA_SET()		bfin_read16(PORTGIO_MASKA_SET)
-#define bfin_write_PORTGIO_MASKA_SET(val)	bfin_write16(PORTGIO_MASKA_SET, val)
-#define bfin_read_PORTGIO_MASKA_TOGGLE()	bfin_read16(PORTGIO_MASKA_TOGGLE)
-#define bfin_write_PORTGIO_MASKA_TOGGLE(val)	bfin_write16(PORTGIO_MASKA_TOGGLE, val)
-#define bfin_read_PORTGIO_MASKB()		bfin_read16(PORTGIO_MASKB)
-#define bfin_write_PORTGIO_MASKB(val)		bfin_write16(PORTGIO_MASKB, val)
-#define bfin_read_PORTGIO_MASKB_CLEAR()		bfin_read16(PORTGIO_MASKB_CLEAR)
-#define bfin_write_PORTGIO_MASKB_CLEAR(val)	bfin_write16(PORTGIO_MASKB_CLEAR, val)
-#define bfin_read_PORTGIO_MASKB_SET()		bfin_read16(PORTGIO_MASKB_SET)
-#define bfin_write_PORTGIO_MASKB_SET(val)	bfin_write16(PORTGIO_MASKB_SET, val)
-#define bfin_read_PORTGIO_MASKB_TOGGLE()	bfin_read16(PORTGIO_MASKB_TOGGLE)
-#define bfin_write_PORTGIO_MASKB_TOGGLE(val)	bfin_write16(PORTGIO_MASKB_TOGGLE, val)
-#define bfin_read_PORTGIO_DIR()			bfin_read16(PORTGIO_DIR)
-#define bfin_write_PORTGIO_DIR(val)		bfin_write16(PORTGIO_DIR, val)
-#define bfin_read_PORTGIO_POLAR()		bfin_read16(PORTGIO_POLAR)
-#define bfin_write_PORTGIO_POLAR(val)		bfin_write16(PORTGIO_POLAR, val)
-#define bfin_read_PORTGIO_EDGE()		bfin_read16(PORTGIO_EDGE)
-#define bfin_write_PORTGIO_EDGE(val)		bfin_write16(PORTGIO_EDGE, val)
-#define bfin_read_PORTGIO_BOTH()		bfin_read16(PORTGIO_BOTH)
-#define bfin_write_PORTGIO_BOTH(val)		bfin_write16(PORTGIO_BOTH, val)
-#define bfin_read_PORTGIO_INEN()		bfin_read16(PORTGIO_INEN)
-#define bfin_write_PORTGIO_INEN(val)		bfin_write16(PORTGIO_INEN, val)
-
-
-/* General Purpose I/O Port H (0xFFC01700 - 0xFFC017FF)								*/
-#define bfin_read_PORTHIO()			bfin_read16(PORTHIO)
-#define bfin_write_PORTHIO(val)			bfin_write16(PORTHIO, val)
-#define bfin_read_PORTHIO_CLEAR()		bfin_read16(PORTHIO_CLEAR)
-#define bfin_write_PORTHIO_CLEAR(val)		bfin_write16(PORTHIO_CLEAR, val)
-#define bfin_read_PORTHIO_SET()			bfin_read16(PORTHIO_SET)
-#define bfin_write_PORTHIO_SET(val)		bfin_write16(PORTHIO_SET, val)
-#define bfin_read_PORTHIO_TOGGLE()		bfin_read16(PORTHIO_TOGGLE)
-#define bfin_write_PORTHIO_TOGGLE(val)		bfin_write16(PORTHIO_TOGGLE, val)
-#define bfin_read_PORTHIO_MASKA()		bfin_read16(PORTHIO_MASKA)
-#define bfin_write_PORTHIO_MASKA(val)		bfin_write16(PORTHIO_MASKA, val)
-#define bfin_read_PORTHIO_MASKA_CLEAR()		bfin_read16(PORTHIO_MASKA_CLEAR)
-#define bfin_write_PORTHIO_MASKA_CLEAR(val)	bfin_write16(PORTHIO_MASKA_CLEAR, val)
-#define bfin_read_PORTHIO_MASKA_SET()		bfin_read16(PORTHIO_MASKA_SET)
-#define bfin_write_PORTHIO_MASKA_SET(val)	bfin_write16(PORTHIO_MASKA_SET, val)
-#define bfin_read_PORTHIO_MASKA_TOGGLE()	bfin_read16(PORTHIO_MASKA_TOGGLE)
-#define bfin_write_PORTHIO_MASKA_TOGGLE(val)	bfin_write16(PORTHIO_MASKA_TOGGLE, val)
-#define bfin_read_PORTHIO_MASKB()		bfin_read16(PORTHIO_MASKB)
-#define bfin_write_PORTHIO_MASKB(val)		bfin_write16(PORTHIO_MASKB, val)
-#define bfin_read_PORTHIO_MASKB_CLEAR()		bfin_read16(PORTHIO_MASKB_CLEAR)
-#define bfin_write_PORTHIO_MASKB_CLEAR(val)	bfin_write16(PORTHIO_MASKB_CLEAR, val)
-#define bfin_read_PORTHIO_MASKB_SET()		bfin_read16(PORTHIO_MASKB_SET)
-#define bfin_write_PORTHIO_MASKB_SET(val)	bfin_write16(PORTHIO_MASKB_SET, val)
-#define bfin_read_PORTHIO_MASKB_TOGGLE()	bfin_read16(PORTHIO_MASKB_TOGGLE)
-#define bfin_write_PORTHIO_MASKB_TOGGLE(val)	bfin_write16(PORTHIO_MASKB_TOGGLE, val)
-#define bfin_read_PORTHIO_DIR()			bfin_read16(PORTHIO_DIR)
-#define bfin_write_PORTHIO_DIR(val)		bfin_write16(PORTHIO_DIR, val)
-#define bfin_read_PORTHIO_POLAR()		bfin_read16(PORTHIO_POLAR)
-#define bfin_write_PORTHIO_POLAR(val)		bfin_write16(PORTHIO_POLAR, val)
-#define bfin_read_PORTHIO_EDGE()		bfin_read16(PORTHIO_EDGE)
-#define bfin_write_PORTHIO_EDGE(val)		bfin_write16(PORTHIO_EDGE, val)
-#define bfin_read_PORTHIO_BOTH()		bfin_read16(PORTHIO_BOTH)
-#define bfin_write_PORTHIO_BOTH(val)		bfin_write16(PORTHIO_BOTH, val)
-#define bfin_read_PORTHIO_INEN()		bfin_read16(PORTHIO_INEN)
-#define bfin_write_PORTHIO_INEN(val)		bfin_write16(PORTHIO_INEN, val)
-
-
-/* UART1 Controller		(0xFFC02000 - 0xFFC020FF)								*/
-#define bfin_read_UART1_THR()			bfin_read16(UART1_THR)
-#define bfin_write_UART1_THR(val)		bfin_write16(UART1_THR, val)
-#define bfin_read_UART1_RBR()			bfin_read16(UART1_RBR)
-#define bfin_write_UART1_RBR(val)		bfin_write16(UART1_RBR, val)
-#define bfin_read_UART1_DLL()			bfin_read16(UART1_DLL)
-#define bfin_write_UART1_DLL(val)		bfin_write16(UART1_DLL, val)
-#define bfin_read_UART1_IER()			bfin_read16(UART1_IER)
-#define bfin_write_UART1_IER(val)		bfin_write16(UART1_IER, val)
-#define bfin_read_UART1_DLH()			bfin_read16(UART1_DLH)
-#define bfin_write_UART1_DLH(val)		bfin_write16(UART1_DLH, val)
-#define bfin_read_UART1_IIR()			bfin_read16(UART1_IIR)
-#define bfin_write_UART1_IIR(val)		bfin_write16(UART1_IIR, val)
-#define bfin_read_UART1_LCR()			bfin_read16(UART1_LCR)
-#define bfin_write_UART1_LCR(val)		bfin_write16(UART1_LCR, val)
-#define bfin_read_UART1_MCR()			bfin_read16(UART1_MCR)
-#define bfin_write_UART1_MCR(val)		bfin_write16(UART1_MCR, val)
-#define bfin_read_UART1_LSR()			bfin_read16(UART1_LSR)
-#define bfin_write_UART1_LSR(val)		bfin_write16(UART1_LSR, val)
-#define bfin_read_UART1_MSR()			bfin_read16(UART1_MSR)
-#define bfin_write_UART1_MSR(val)		bfin_write16(UART1_MSR, val)
-#define bfin_read_UART1_SCR()			bfin_read16(UART1_SCR)
-#define bfin_write_UART1_SCR(val)		bfin_write16(UART1_SCR, val)
-#define bfin_read_UART1_GCTL()			bfin_read16(UART1_GCTL)
-#define bfin_write_UART1_GCTL(val)		bfin_write16(UART1_GCTL, val)
-
-/* Omit CAN register sets from the cdefBF534.h (CAN is not in the ADSP-BF51x processor) */
-
-/* Pin Control Registers	(0xFFC03200 - 0xFFC032FF)								*/
-#define bfin_read_PORTF_FER()			bfin_read16(PORTF_FER)
-#define bfin_write_PORTF_FER(val)		bfin_write16(PORTF_FER, val)
-#define bfin_read_PORTG_FER()			bfin_read16(PORTG_FER)
-#define bfin_write_PORTG_FER(val)		bfin_write16(PORTG_FER, val)
-#define bfin_read_PORTH_FER()			bfin_read16(PORTH_FER)
-#define bfin_write_PORTH_FER(val)		bfin_write16(PORTH_FER, val)
-#define bfin_read_PORT_MUX()			bfin_read16(PORT_MUX)
-#define bfin_write_PORT_MUX(val)		bfin_write16(PORT_MUX, val)
-
-
-/* Handshake MDMA Registers	(0xFFC03300 - 0xFFC033FF)								*/
-#define bfin_read_HMDMA0_CONTROL()		bfin_read16(HMDMA0_CONTROL)
-#define bfin_write_HMDMA0_CONTROL(val)		bfin_write16(HMDMA0_CONTROL, val)
-#define bfin_read_HMDMA0_ECINIT()		bfin_read16(HMDMA0_ECINIT)
-#define bfin_write_HMDMA0_ECINIT(val)		bfin_write16(HMDMA0_ECINIT, val)
-#define bfin_read_HMDMA0_BCINIT()		bfin_read16(HMDMA0_BCINIT)
-#define bfin_write_HMDMA0_BCINIT(val)		bfin_write16(HMDMA0_BCINIT, val)
-#define bfin_read_HMDMA0_ECURGENT()		bfin_read16(HMDMA0_ECURGENT)
-#define bfin_write_HMDMA0_ECURGENT(val)		bfin_write16(HMDMA0_ECURGENT, val)
-#define bfin_read_HMDMA0_ECOVERFLOW()		bfin_read16(HMDMA0_ECOVERFLOW)
-#define bfin_write_HMDMA0_ECOVERFLOW(val)	bfin_write16(HMDMA0_ECOVERFLOW, val)
-#define bfin_read_HMDMA0_ECOUNT()		bfin_read16(HMDMA0_ECOUNT)
-#define bfin_write_HMDMA0_ECOUNT(val)		bfin_write16(HMDMA0_ECOUNT, val)
-#define bfin_read_HMDMA0_BCOUNT()		bfin_read16(HMDMA0_BCOUNT)
-#define bfin_write_HMDMA0_BCOUNT(val)		bfin_write16(HMDMA0_BCOUNT, val)
-
-#define bfin_read_HMDMA1_CONTROL()		bfin_read16(HMDMA1_CONTROL)
-#define bfin_write_HMDMA1_CONTROL(val)		bfin_write16(HMDMA1_CONTROL, val)
-#define bfin_read_HMDMA1_ECINIT()		bfin_read16(HMDMA1_ECINIT)
-#define bfin_write_HMDMA1_ECINIT(val)		bfin_write16(HMDMA1_ECINIT, val)
-#define bfin_read_HMDMA1_BCINIT()		bfin_read16(HMDMA1_BCINIT)
-#define bfin_write_HMDMA1_BCINIT(val)		bfin_write16(HMDMA1_BCINIT, val)
-#define bfin_read_HMDMA1_ECURGENT()		bfin_read16(HMDMA1_ECURGENT)
-#define bfin_write_HMDMA1_ECURGENT(val)		bfin_write16(HMDMA1_ECURGENT, val)
-#define bfin_read_HMDMA1_ECOVERFLOW()		bfin_read16(HMDMA1_ECOVERFLOW)
-#define bfin_write_HMDMA1_ECOVERFLOW(val)	bfin_write16(HMDMA1_ECOVERFLOW, val)
-#define bfin_read_HMDMA1_ECOUNT()		bfin_read16(HMDMA1_ECOUNT)
-#define bfin_write_HMDMA1_ECOUNT(val)		bfin_write16(HMDMA1_ECOUNT, val)
-#define bfin_read_HMDMA1_BCOUNT()		bfin_read16(HMDMA1_BCOUNT)
-#define bfin_write_HMDMA1_BCOUNT(val)		bfin_write16(HMDMA1_BCOUNT, val)
-
-/* ==== end from cdefBF534.h ==== */
-
-/* GPIO PIN mux (0xFFC03210 - OxFFC03288) */
-
-#define bfin_read_PORTF_MUX()			bfin_read16(PORTF_MUX)
-#define bfin_write_PORTF_MUX(val)		bfin_write16(PORTF_MUX, val)
-#define bfin_read_PORTG_MUX()			bfin_read16(PORTG_MUX)
-#define bfin_write_PORTG_MUX(val)		bfin_write16(PORTG_MUX, val)
-#define bfin_read_PORTH_MUX()			bfin_read16(PORTH_MUX)
-#define bfin_write_PORTH_MUX(val)		bfin_write16(PORTH_MUX, val)
-
-#define bfin_read_PORTF_DRIVE()			bfin_read16(PORTF_DRIVE)
-#define bfin_write_PORTF_DRIVE(val)		bfin_write16(PORTF_DRIVE, val)
-#define bfin_read_PORTG_DRIVE()			bfin_read16(PORTG_DRIVE)
-#define bfin_write_PORTG_DRIVE(val)		bfin_write16(PORTG_DRIVE, val)
-#define bfin_read_PORTH_DRIVE()			bfin_read16(PORTH_DRIVE)
-#define bfin_write_PORTH_DRIVE(val)		bfin_write16(PORTH_DRIVE, val)
-#define bfin_read_PORTF_SLEW()			bfin_read16(PORTF_SLEW)
-#define bfin_write_PORTF_SLEW(val)		bfin_write16(PORTF_SLEW, val)
-#define bfin_read_PORTG_SLEW()			bfin_read16(PORTG_SLEW)
-#define bfin_write_PORTG_SLEW(val)		bfin_write16(PORTG_SLEW, val)
-#define bfin_read_PORTH_SLEW()			bfin_read16(PORTH_SLEW)
-#define bfin_write_PORTH_SLEW(val)		bfin_write16(PORTH_SLEW, val)
-#define bfin_read_PORTF_HYSTERISIS()		bfin_read16(PORTF_HYSTERISIS)
-#define bfin_write_PORTF_HYSTERISIS(val)	bfin_write16(PORTF_HYSTERISIS, val)
-#define bfin_read_PORTG_HYSTERISIS()		bfin_read16(PORTG_HYSTERISIS)
-#define bfin_write_PORTG_HYSTERISIS(val)	bfin_write16(PORTG_HYSTERISIS, val)
-#define bfin_read_PORTH_HYSTERISIS()		bfin_read16(PORTH_HYSTERISIS)
-#define bfin_write_PORTH_HYSTERISIS(val)	bfin_write16(PORTH_HYSTERISIS, val)
-#define bfin_read_MISCPORT_DRIVE()		bfin_read16(MISCPORT_DRIVE)
-#define bfin_write_MISCPORT_DRIVE(val)		bfin_write16(MISCPORT_DRIVE, val)
-#define bfin_read_MISCPORT_SLEW()		bfin_read16(MISCPORT_SLEW)
-#define bfin_write_MISCPORT_SLEW(val)		bfin_write16(MISCPORT_SLEW, val)
-#define bfin_read_MISCPORT_HYSTERISIS()		bfin_read16(MISCPORT_HYSTERISIS)
-#define bfin_write_MISCPORT_HYSTERISIS(val)	bfin_write16(MISCPORT_HYSTERISIS, val)
-
-/* HOST Port Registers */
-
-#define bfin_read_HOST_CONTROL()		bfin_read16(HOST_CONTROL)
-#define bfin_write_HOST_CONTROL(val)		bfin_write16(HOST_CONTROL, val)
-#define bfin_read_HOST_STATUS()			bfin_read16(HOST_STATUS)
-#define bfin_write_HOST_STATUS(val)		bfin_write16(HOST_STATUS, val)
-#define bfin_read_HOST_TIMEOUT()		bfin_read16(HOST_TIMEOUT)
-#define bfin_write_HOST_TIMEOUT(val)		bfin_write16(HOST_TIMEOUT, val)
-
-/* Counter Registers */
-
-#define bfin_read_CNT_CONFIG()			bfin_read16(CNT_CONFIG)
-#define bfin_write_CNT_CONFIG(val)		bfin_write16(CNT_CONFIG, val)
-#define bfin_read_CNT_IMASK()			bfin_read16(CNT_IMASK)
-#define bfin_write_CNT_IMASK(val)		bfin_write16(CNT_IMASK, val)
-#define bfin_read_CNT_STATUS()			bfin_read16(CNT_STATUS)
-#define bfin_write_CNT_STATUS(val)		bfin_write16(CNT_STATUS, val)
-#define bfin_read_CNT_COMMAND()			bfin_read16(CNT_COMMAND)
-#define bfin_write_CNT_COMMAND(val)		bfin_write16(CNT_COMMAND, val)
-#define bfin_read_CNT_DEBOUNCE()		bfin_read16(CNT_DEBOUNCE)
-#define bfin_write_CNT_DEBOUNCE(val)		bfin_write16(CNT_DEBOUNCE, val)
-#define bfin_read_CNT_COUNTER()			bfin_read32(CNT_COUNTER)
-#define bfin_write_CNT_COUNTER(val)		bfin_write32(CNT_COUNTER, val)
-#define bfin_read_CNT_MAX()			bfin_read32(CNT_MAX)
-#define bfin_write_CNT_MAX(val)			bfin_write32(CNT_MAX, val)
-#define bfin_read_CNT_MIN()			bfin_read32(CNT_MIN)
-#define bfin_write_CNT_MIN(val)			bfin_write32(CNT_MIN, val)
-
-/* Security Registers */
-
-#define bfin_read_SECURE_SYSSWT()		bfin_read32(SECURE_SYSSWT)
-#define bfin_write_SECURE_SYSSWT(val)		bfin_write32(SECURE_SYSSWT, val)
-#define bfin_read_SECURE_CONTROL()		bfin_read16(SECURE_CONTROL)
-#define bfin_write_SECURE_CONTROL(val)		bfin_write16(SECURE_CONTROL, val)
-#define bfin_read_SECURE_STATUS()		bfin_read16(SECURE_STATUS)
-#define bfin_write_SECURE_STATUS(val)		bfin_write16(SECURE_STATUS, val)
-
-/* These need to be last due to the cdef/linux inter-dependencies */
-#include <asm/irq.h>
-
-#endif /* _CDEF_BF52X_H */
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf518/include/mach/defBF512.h linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf518/include/mach/defBF512.h
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf518/include/mach/defBF512.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf518/include/mach/defBF512.h	2011-03-14 21:20:32.000000000 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright 2008 Analog Devices Inc.
+ * Copyright 2008-2010 Analog Devices Inc.
  *
  * Licensed under the ADI BSD license or the GPL-2 (or later)
  */
@@ -7,12 +7,1388 @@
 #ifndef _DEF_BF512_H
 #define _DEF_BF512_H
 
-/* Include all Core registers and bit definitions */
-#include <asm/def_LPBlackfin.h>
+/* ************************************************************** */
+/*   SYSTEM & MMR ADDRESS DEFINITIONS COMMON TO ALL ADSP-BF51x    */
+/* ************************************************************** */
 
-/* SYSTEM & MMR ADDRESS DEFINITIONS FOR ADSP-BF512 */
+/* Clock and System Control	(0xFFC00000 - 0xFFC000FF)								*/
+#define PLL_CTL				0xFFC00000	/* PLL Control Register						*/
+#define PLL_DIV				0xFFC00004	/* PLL Divide Register						*/
+#define VR_CTL				0xFFC00008	/* Voltage Regulator Control Register				*/
+#define PLL_STAT			0xFFC0000C	/* PLL Status Register						*/
+#define PLL_LOCKCNT			0xFFC00010	/* PLL Lock Count Register					*/
+#define CHIPID				0xFFC00014	/* Device ID Register */
 
-/* Include defBF51x_base.h for the set of #defines that are common to all ADSP-BF51x processors */
-#include "defBF51x_base.h"
+/* System Interrupt Controller (0xFFC00100 - 0xFFC001FF)								*/
+#define SWRST				0xFFC00100	/* Software Reset Register					*/
+#define SYSCR				0xFFC00104	/* System Configuration Register				*/
+#define SIC_RVECT			0xFFC00108	/* Interrupt Reset Vector Address Register			*/
+
+#define SIC_IMASK0			0xFFC0010C	/* Interrupt Mask Register					*/
+#define SIC_IAR0			0xFFC00110	/* Interrupt Assignment Register 0				*/
+#define SIC_IAR1			0xFFC00114	/* Interrupt Assignment Register 1				*/
+#define SIC_IAR2			0xFFC00118	/* Interrupt Assignment Register 2				*/
+#define SIC_IAR3			0xFFC0011C	/* Interrupt Assignment Register 3				*/
+#define SIC_ISR0			0xFFC00120	/* Interrupt Status Register					*/
+#define SIC_IWR0			0xFFC00124	/* Interrupt Wakeup Register					*/
+
+/* SIC Additions to ADSP-BF51x (0xFFC0014C - 0xFFC00162) */
+#define SIC_IMASK1                      0xFFC0014C     /* Interrupt Mask register of SIC2 */
+#define SIC_IAR4                        0xFFC00150     /* Interrupt Assignment register4 */
+#define SIC_IAR5                        0xFFC00154     /* Interrupt Assignment register5 */
+#define SIC_IAR6                        0xFFC00158     /* Interrupt Assignment register6 */
+#define SIC_IAR7                        0xFFC0015C     /* Interrupt Assignment register7 */
+#define SIC_ISR1                        0xFFC00160     /* Interrupt Statur register */
+#define SIC_IWR1                        0xFFC00164     /* Interrupt Wakeup register */
+
+
+/* Watchdog Timer			(0xFFC00200 - 0xFFC002FF)								*/
+#define WDOG_CTL			0xFFC00200	/* Watchdog Control Register				*/
+#define WDOG_CNT			0xFFC00204	/* Watchdog Count Register					*/
+#define WDOG_STAT			0xFFC00208	/* Watchdog Status Register					*/
+
+
+/* Real Time Clock		(0xFFC00300 - 0xFFC003FF)									*/
+#define RTC_STAT			0xFFC00300	/* RTC Status Register						*/
+#define RTC_ICTL			0xFFC00304	/* RTC Interrupt Control Register			*/
+#define RTC_ISTAT			0xFFC00308	/* RTC Interrupt Status Register			*/
+#define RTC_SWCNT			0xFFC0030C	/* RTC Stopwatch Count Register				*/
+#define RTC_ALARM			0xFFC00310	/* RTC Alarm Time Register					*/
+#define RTC_FAST			0xFFC00314	/* RTC Prescaler Enable Register			*/
+#define RTC_PREN			0xFFC00314	/* RTC Prescaler Enable Alternate Macro		*/
+
+
+/* UART0 Controller		(0xFFC00400 - 0xFFC004FF)									*/
+#define UART0_THR			0xFFC00400	/* Transmit Holding register				*/
+#define UART0_RBR			0xFFC00400	/* Receive Buffer register					*/
+#define UART0_DLL			0xFFC00400	/* Divisor Latch (Low-Byte)					*/
+#define UART0_IER			0xFFC00404	/* Interrupt Enable Register				*/
+#define UART0_DLH			0xFFC00404	/* Divisor Latch (High-Byte)				*/
+#define UART0_IIR			0xFFC00408	/* Interrupt Identification Register		*/
+#define UART0_LCR			0xFFC0040C	/* Line Control Register					*/
+#define UART0_MCR			0xFFC00410	/* Modem Control Register					*/
+#define UART0_LSR			0xFFC00414	/* Line Status Register						*/
+#define UART0_MSR			0xFFC00418	/* Modem Status Register					*/
+#define UART0_SCR			0xFFC0041C	/* SCR Scratch Register						*/
+#define UART0_GCTL			0xFFC00424	/* Global Control Register					*/
+
+/* SPI0 Controller			(0xFFC00500 - 0xFFC005FF)							*/
+#define SPI0_REGBASE			0xFFC00500
+#define SPI0_CTL			0xFFC00500	/* SPI Control Register						*/
+#define SPI0_FLG			0xFFC00504	/* SPI Flag register						*/
+#define SPI0_STAT			0xFFC00508	/* SPI Status register						*/
+#define SPI0_TDBR			0xFFC0050C	/* SPI Transmit Data Buffer Register				*/
+#define SPI0_RDBR			0xFFC00510	/* SPI Receive Data Buffer Register				*/
+#define SPI0_BAUD			0xFFC00514	/* SPI Baud rate Register					*/
+#define SPI0_SHADOW			0xFFC00518	/* SPI_RDBR Shadow Register					*/
+
+/* SPI1 Controller			(0xFFC03400 - 0xFFC034FF)							*/
+#define SPI1_REGBASE			0xFFC03400
+#define SPI1_CTL			0xFFC03400	/* SPI Control Register						*/
+#define SPI1_FLG			0xFFC03404	/* SPI Flag register						*/
+#define SPI1_STAT			0xFFC03408	/* SPI Status register						*/
+#define SPI1_TDBR			0xFFC0340C	/* SPI Transmit Data Buffer Register				*/
+#define SPI1_RDBR			0xFFC03410	/* SPI Receive Data Buffer Register				*/
+#define SPI1_BAUD			0xFFC03414	/* SPI Baud rate Register					*/
+#define SPI1_SHADOW			0xFFC03418	/* SPI_RDBR Shadow Register					*/
+
+/* TIMER0-7 Registers		(0xFFC00600 - 0xFFC006FF)								*/
+#define TIMER0_CONFIG		0xFFC00600	/* Timer 0 Configuration Register			*/
+#define TIMER0_COUNTER		0xFFC00604	/* Timer 0 Counter Register					*/
+#define TIMER0_PERIOD		0xFFC00608	/* Timer 0 Period Register					*/
+#define TIMER0_WIDTH		0xFFC0060C	/* Timer 0 Width Register					*/
+
+#define TIMER1_CONFIG		0xFFC00610	/* Timer 1 Configuration Register  			*/
+#define TIMER1_COUNTER		0xFFC00614	/* Timer 1 Counter Register        			*/
+#define TIMER1_PERIOD		0xFFC00618	/* Timer 1 Period Register         			*/
+#define TIMER1_WIDTH		0xFFC0061C	/* Timer 1 Width Register          			*/
+
+#define TIMER2_CONFIG		0xFFC00620	/* Timer 2 Configuration Register  			*/
+#define TIMER2_COUNTER		0xFFC00624	/* Timer 2 Counter Register        			*/
+#define TIMER2_PERIOD		0xFFC00628	/* Timer 2 Period Register         			*/
+#define TIMER2_WIDTH		0xFFC0062C	/* Timer 2 Width Register          			*/
+
+#define TIMER3_CONFIG		0xFFC00630	/* Timer 3 Configuration Register			*/
+#define TIMER3_COUNTER		0xFFC00634	/* Timer 3 Counter Register					*/
+#define TIMER3_PERIOD		0xFFC00638	/* Timer 3 Period Register					*/
+#define TIMER3_WIDTH		0xFFC0063C	/* Timer 3 Width Register					*/
+
+#define TIMER4_CONFIG		0xFFC00640	/* Timer 4 Configuration Register  			*/
+#define TIMER4_COUNTER		0xFFC00644	/* Timer 4 Counter Register        			*/
+#define TIMER4_PERIOD		0xFFC00648	/* Timer 4 Period Register         			*/
+#define TIMER4_WIDTH		0xFFC0064C	/* Timer 4 Width Register          			*/
+
+#define TIMER5_CONFIG		0xFFC00650	/* Timer 5 Configuration Register  			*/
+#define TIMER5_COUNTER		0xFFC00654	/* Timer 5 Counter Register        			*/
+#define TIMER5_PERIOD		0xFFC00658	/* Timer 5 Period Register         			*/
+#define TIMER5_WIDTH		0xFFC0065C	/* Timer 5 Width Register          			*/
+
+#define TIMER6_CONFIG		0xFFC00660	/* Timer 6 Configuration Register  			*/
+#define TIMER6_COUNTER		0xFFC00664	/* Timer 6 Counter Register        			*/
+#define TIMER6_PERIOD		0xFFC00668	/* Timer 6 Period Register         			*/
+#define TIMER6_WIDTH		0xFFC0066C	/* Timer 6 Width Register          			*/
+
+#define TIMER7_CONFIG		0xFFC00670	/* Timer 7 Configuration Register  			*/
+#define TIMER7_COUNTER		0xFFC00674	/* Timer 7 Counter Register        			*/
+#define TIMER7_PERIOD		0xFFC00678	/* Timer 7 Period Register         			*/
+#define TIMER7_WIDTH		0xFFC0067C	/* Timer 7 Width Register       			*/
+
+#define TIMER_ENABLE		0xFFC00680	/* Timer Enable Register					*/
+#define TIMER_DISABLE		0xFFC00684	/* Timer Disable Register					*/
+#define TIMER_STATUS		0xFFC00688	/* Timer Status Register					*/
+
+/* General Purpose I/O Port F (0xFFC00700 - 0xFFC007FF)												*/
+#define PORTFIO					0xFFC00700	/* Port F I/O Pin State Specify Register				*/
+#define PORTFIO_CLEAR			0xFFC00704	/* Port F I/O Peripheral Interrupt Clear Register		*/
+#define PORTFIO_SET				0xFFC00708	/* Port F I/O Peripheral Interrupt Set Register			*/
+#define PORTFIO_TOGGLE			0xFFC0070C	/* Port F I/O Pin State Toggle Register					*/
+#define PORTFIO_MASKA			0xFFC00710	/* Port F I/O Mask State Specify Interrupt A Register	*/
+#define PORTFIO_MASKA_CLEAR		0xFFC00714	/* Port F I/O Mask Disable Interrupt A Register			*/
+#define PORTFIO_MASKA_SET		0xFFC00718	/* Port F I/O Mask Enable Interrupt A Register			*/
+#define PORTFIO_MASKA_TOGGLE	0xFFC0071C	/* Port F I/O Mask Toggle Enable Interrupt A Register	*/
+#define PORTFIO_MASKB			0xFFC00720	/* Port F I/O Mask State Specify Interrupt B Register	*/
+#define PORTFIO_MASKB_CLEAR		0xFFC00724	/* Port F I/O Mask Disable Interrupt B Register			*/
+#define PORTFIO_MASKB_SET		0xFFC00728	/* Port F I/O Mask Enable Interrupt B Register			*/
+#define PORTFIO_MASKB_TOGGLE	0xFFC0072C	/* Port F I/O Mask Toggle Enable Interrupt B Register	*/
+#define PORTFIO_DIR				0xFFC00730	/* Port F I/O Direction Register						*/
+#define PORTFIO_POLAR			0xFFC00734	/* Port F I/O Source Polarity Register					*/
+#define PORTFIO_EDGE			0xFFC00738	/* Port F I/O Source Sensitivity Register				*/
+#define PORTFIO_BOTH			0xFFC0073C	/* Port F I/O Set on BOTH Edges Register				*/
+#define PORTFIO_INEN			0xFFC00740	/* Port F I/O Input Enable Register 					*/
+
+/* SPORT0 Controller		(0xFFC00800 - 0xFFC008FF)										*/
+#define SPORT0_TCR1			0xFFC00800	/* SPORT0 Transmit Configuration 1 Register			*/
+#define SPORT0_TCR2			0xFFC00804	/* SPORT0 Transmit Configuration 2 Register			*/
+#define SPORT0_TCLKDIV		0xFFC00808	/* SPORT0 Transmit Clock Divider					*/
+#define SPORT0_TFSDIV		0xFFC0080C	/* SPORT0 Transmit Frame Sync Divider				*/
+#define SPORT0_TX			0xFFC00810	/* SPORT0 TX Data Register							*/
+#define SPORT0_RX			0xFFC00818	/* SPORT0 RX Data Register							*/
+#define SPORT0_RCR1			0xFFC00820	/* SPORT0 Transmit Configuration 1 Register			*/
+#define SPORT0_RCR2			0xFFC00824	/* SPORT0 Transmit Configuration 2 Register			*/
+#define SPORT0_RCLKDIV		0xFFC00828	/* SPORT0 Receive Clock Divider						*/
+#define SPORT0_RFSDIV		0xFFC0082C	/* SPORT0 Receive Frame Sync Divider				*/
+#define SPORT0_STAT			0xFFC00830	/* SPORT0 Status Register							*/
+#define SPORT0_CHNL			0xFFC00834	/* SPORT0 Current Channel Register					*/
+#define SPORT0_MCMC1		0xFFC00838	/* SPORT0 Multi-Channel Configuration Register 1	*/
+#define SPORT0_MCMC2		0xFFC0083C	/* SPORT0 Multi-Channel Configuration Register 2	*/
+#define SPORT0_MTCS0		0xFFC00840	/* SPORT0 Multi-Channel Transmit Select Register 0	*/
+#define SPORT0_MTCS1		0xFFC00844	/* SPORT0 Multi-Channel Transmit Select Register 1	*/
+#define SPORT0_MTCS2		0xFFC00848	/* SPORT0 Multi-Channel Transmit Select Register 2	*/
+#define SPORT0_MTCS3		0xFFC0084C	/* SPORT0 Multi-Channel Transmit Select Register 3	*/
+#define SPORT0_MRCS0		0xFFC00850	/* SPORT0 Multi-Channel Receive Select Register 0	*/
+#define SPORT0_MRCS1		0xFFC00854	/* SPORT0 Multi-Channel Receive Select Register 1	*/
+#define SPORT0_MRCS2		0xFFC00858	/* SPORT0 Multi-Channel Receive Select Register 2	*/
+#define SPORT0_MRCS3		0xFFC0085C	/* SPORT0 Multi-Channel Receive Select Register 3	*/
+
+/* SPORT1 Controller		(0xFFC00900 - 0xFFC009FF)										*/
+#define SPORT1_TCR1			0xFFC00900	/* SPORT1 Transmit Configuration 1 Register			*/
+#define SPORT1_TCR2			0xFFC00904	/* SPORT1 Transmit Configuration 2 Register			*/
+#define SPORT1_TCLKDIV		0xFFC00908	/* SPORT1 Transmit Clock Divider					*/
+#define SPORT1_TFSDIV		0xFFC0090C	/* SPORT1 Transmit Frame Sync Divider				*/
+#define SPORT1_TX			0xFFC00910	/* SPORT1 TX Data Register							*/
+#define SPORT1_RX			0xFFC00918	/* SPORT1 RX Data Register							*/
+#define SPORT1_RCR1			0xFFC00920	/* SPORT1 Transmit Configuration 1 Register			*/
+#define SPORT1_RCR2			0xFFC00924	/* SPORT1 Transmit Configuration 2 Register			*/
+#define SPORT1_RCLKDIV		0xFFC00928	/* SPORT1 Receive Clock Divider						*/
+#define SPORT1_RFSDIV		0xFFC0092C	/* SPORT1 Receive Frame Sync Divider				*/
+#define SPORT1_STAT			0xFFC00930	/* SPORT1 Status Register							*/
+#define SPORT1_CHNL			0xFFC00934	/* SPORT1 Current Channel Register					*/
+#define SPORT1_MCMC1		0xFFC00938	/* SPORT1 Multi-Channel Configuration Register 1	*/
+#define SPORT1_MCMC2		0xFFC0093C	/* SPORT1 Multi-Channel Configuration Register 2	*/
+#define SPORT1_MTCS0		0xFFC00940	/* SPORT1 Multi-Channel Transmit Select Register 0	*/
+#define SPORT1_MTCS1		0xFFC00944	/* SPORT1 Multi-Channel Transmit Select Register 1	*/
+#define SPORT1_MTCS2		0xFFC00948	/* SPORT1 Multi-Channel Transmit Select Register 2	*/
+#define SPORT1_MTCS3		0xFFC0094C	/* SPORT1 Multi-Channel Transmit Select Register 3	*/
+#define SPORT1_MRCS0		0xFFC00950	/* SPORT1 Multi-Channel Receive Select Register 0	*/
+#define SPORT1_MRCS1		0xFFC00954	/* SPORT1 Multi-Channel Receive Select Register 1	*/
+#define SPORT1_MRCS2		0xFFC00958	/* SPORT1 Multi-Channel Receive Select Register 2	*/
+#define SPORT1_MRCS3		0xFFC0095C	/* SPORT1 Multi-Channel Receive Select Register 3	*/
+
+/* External Bus Interface Unit (0xFFC00A00 - 0xFFC00AFF)								*/
+#define EBIU_AMGCTL			0xFFC00A00	/* Asynchronous Memory Global Control Register	*/
+#define EBIU_AMBCTL0		0xFFC00A04	/* Asynchronous Memory Bank Control Register 0	*/
+#define EBIU_AMBCTL1		0xFFC00A08	/* Asynchronous Memory Bank Control Register 1	*/
+#define EBIU_SDGCTL			0xFFC00A10	/* SDRAM Global Control Register				*/
+#define EBIU_SDBCTL			0xFFC00A14	/* SDRAM Bank Control Register					*/
+#define EBIU_SDRRC			0xFFC00A18	/* SDRAM Refresh Rate Control Register			*/
+#define EBIU_SDSTAT			0xFFC00A1C	/* SDRAM Status Register						*/
+
+/* DMA Traffic Control Registers													*/
+#define DMAC_TC_PER			0xFFC00B0C	/* Traffic Control Periods Register			*/
+#define DMAC_TC_CNT			0xFFC00B10	/* Traffic Control Current Counts Register	*/
+
+/* DMA Controller (0xFFC00C00 - 0xFFC00FFF)															*/
+#define DMA0_NEXT_DESC_PTR		0xFFC00C00	/* DMA Channel 0 Next Descriptor Pointer Register		*/
+#define DMA0_START_ADDR			0xFFC00C04	/* DMA Channel 0 Start Address Register					*/
+#define DMA0_CONFIG				0xFFC00C08	/* DMA Channel 0 Configuration Register					*/
+#define DMA0_X_COUNT			0xFFC00C10	/* DMA Channel 0 X Count Register						*/
+#define DMA0_X_MODIFY			0xFFC00C14	/* DMA Channel 0 X Modify Register						*/
+#define DMA0_Y_COUNT			0xFFC00C18	/* DMA Channel 0 Y Count Register						*/
+#define DMA0_Y_MODIFY			0xFFC00C1C	/* DMA Channel 0 Y Modify Register						*/
+#define DMA0_CURR_DESC_PTR		0xFFC00C20	/* DMA Channel 0 Current Descriptor Pointer Register	*/
+#define DMA0_CURR_ADDR			0xFFC00C24	/* DMA Channel 0 Current Address Register				*/
+#define DMA0_IRQ_STATUS			0xFFC00C28	/* DMA Channel 0 Interrupt/Status Register				*/
+#define DMA0_PERIPHERAL_MAP		0xFFC00C2C	/* DMA Channel 0 Peripheral Map Register				*/
+#define DMA0_CURR_X_COUNT		0xFFC00C30	/* DMA Channel 0 Current X Count Register				*/
+#define DMA0_CURR_Y_COUNT		0xFFC00C38	/* DMA Channel 0 Current Y Count Register				*/
+
+#define DMA1_NEXT_DESC_PTR		0xFFC00C40	/* DMA Channel 1 Next Descriptor Pointer Register		*/
+#define DMA1_START_ADDR			0xFFC00C44	/* DMA Channel 1 Start Address Register					*/
+#define DMA1_CONFIG				0xFFC00C48	/* DMA Channel 1 Configuration Register					*/
+#define DMA1_X_COUNT			0xFFC00C50	/* DMA Channel 1 X Count Register						*/
+#define DMA1_X_MODIFY			0xFFC00C54	/* DMA Channel 1 X Modify Register						*/
+#define DMA1_Y_COUNT			0xFFC00C58	/* DMA Channel 1 Y Count Register						*/
+#define DMA1_Y_MODIFY			0xFFC00C5C	/* DMA Channel 1 Y Modify Register						*/
+#define DMA1_CURR_DESC_PTR		0xFFC00C60	/* DMA Channel 1 Current Descriptor Pointer Register	*/
+#define DMA1_CURR_ADDR			0xFFC00C64	/* DMA Channel 1 Current Address Register				*/
+#define DMA1_IRQ_STATUS			0xFFC00C68	/* DMA Channel 1 Interrupt/Status Register				*/
+#define DMA1_PERIPHERAL_MAP		0xFFC00C6C	/* DMA Channel 1 Peripheral Map Register				*/
+#define DMA1_CURR_X_COUNT		0xFFC00C70	/* DMA Channel 1 Current X Count Register				*/
+#define DMA1_CURR_Y_COUNT		0xFFC00C78	/* DMA Channel 1 Current Y Count Register				*/
+
+#define DMA2_NEXT_DESC_PTR		0xFFC00C80	/* DMA Channel 2 Next Descriptor Pointer Register		*/
+#define DMA2_START_ADDR			0xFFC00C84	/* DMA Channel 2 Start Address Register					*/
+#define DMA2_CONFIG				0xFFC00C88	/* DMA Channel 2 Configuration Register					*/
+#define DMA2_X_COUNT			0xFFC00C90	/* DMA Channel 2 X Count Register						*/
+#define DMA2_X_MODIFY			0xFFC00C94	/* DMA Channel 2 X Modify Register						*/
+#define DMA2_Y_COUNT			0xFFC00C98	/* DMA Channel 2 Y Count Register						*/
+#define DMA2_Y_MODIFY			0xFFC00C9C	/* DMA Channel 2 Y Modify Register						*/
+#define DMA2_CURR_DESC_PTR		0xFFC00CA0	/* DMA Channel 2 Current Descriptor Pointer Register	*/
+#define DMA2_CURR_ADDR			0xFFC00CA4	/* DMA Channel 2 Current Address Register				*/
+#define DMA2_IRQ_STATUS			0xFFC00CA8	/* DMA Channel 2 Interrupt/Status Register				*/
+#define DMA2_PERIPHERAL_MAP		0xFFC00CAC	/* DMA Channel 2 Peripheral Map Register				*/
+#define DMA2_CURR_X_COUNT		0xFFC00CB0	/* DMA Channel 2 Current X Count Register				*/
+#define DMA2_CURR_Y_COUNT		0xFFC00CB8	/* DMA Channel 2 Current Y Count Register				*/
+
+#define DMA3_NEXT_DESC_PTR		0xFFC00CC0	/* DMA Channel 3 Next Descriptor Pointer Register		*/
+#define DMA3_START_ADDR			0xFFC00CC4	/* DMA Channel 3 Start Address Register					*/
+#define DMA3_CONFIG				0xFFC00CC8	/* DMA Channel 3 Configuration Register					*/
+#define DMA3_X_COUNT			0xFFC00CD0	/* DMA Channel 3 X Count Register						*/
+#define DMA3_X_MODIFY			0xFFC00CD4	/* DMA Channel 3 X Modify Register						*/
+#define DMA3_Y_COUNT			0xFFC00CD8	/* DMA Channel 3 Y Count Register						*/
+#define DMA3_Y_MODIFY			0xFFC00CDC	/* DMA Channel 3 Y Modify Register						*/
+#define DMA3_CURR_DESC_PTR		0xFFC00CE0	/* DMA Channel 3 Current Descriptor Pointer Register	*/
+#define DMA3_CURR_ADDR			0xFFC00CE4	/* DMA Channel 3 Current Address Register				*/
+#define DMA3_IRQ_STATUS			0xFFC00CE8	/* DMA Channel 3 Interrupt/Status Register				*/
+#define DMA3_PERIPHERAL_MAP		0xFFC00CEC	/* DMA Channel 3 Peripheral Map Register				*/
+#define DMA3_CURR_X_COUNT		0xFFC00CF0	/* DMA Channel 3 Current X Count Register				*/
+#define DMA3_CURR_Y_COUNT		0xFFC00CF8	/* DMA Channel 3 Current Y Count Register				*/
+
+#define DMA4_NEXT_DESC_PTR		0xFFC00D00	/* DMA Channel 4 Next Descriptor Pointer Register		*/
+#define DMA4_START_ADDR			0xFFC00D04	/* DMA Channel 4 Start Address Register					*/
+#define DMA4_CONFIG				0xFFC00D08	/* DMA Channel 4 Configuration Register					*/
+#define DMA4_X_COUNT			0xFFC00D10	/* DMA Channel 4 X Count Register						*/
+#define DMA4_X_MODIFY			0xFFC00D14	/* DMA Channel 4 X Modify Register						*/
+#define DMA4_Y_COUNT			0xFFC00D18	/* DMA Channel 4 Y Count Register						*/
+#define DMA4_Y_MODIFY			0xFFC00D1C	/* DMA Channel 4 Y Modify Register						*/
+#define DMA4_CURR_DESC_PTR		0xFFC00D20	/* DMA Channel 4 Current Descriptor Pointer Register	*/
+#define DMA4_CURR_ADDR			0xFFC00D24	/* DMA Channel 4 Current Address Register				*/
+#define DMA4_IRQ_STATUS			0xFFC00D28	/* DMA Channel 4 Interrupt/Status Register				*/
+#define DMA4_PERIPHERAL_MAP		0xFFC00D2C	/* DMA Channel 4 Peripheral Map Register				*/
+#define DMA4_CURR_X_COUNT		0xFFC00D30	/* DMA Channel 4 Current X Count Register				*/
+#define DMA4_CURR_Y_COUNT		0xFFC00D38	/* DMA Channel 4 Current Y Count Register				*/
+
+#define DMA5_NEXT_DESC_PTR		0xFFC00D40	/* DMA Channel 5 Next Descriptor Pointer Register		*/
+#define DMA5_START_ADDR			0xFFC00D44	/* DMA Channel 5 Start Address Register					*/
+#define DMA5_CONFIG				0xFFC00D48	/* DMA Channel 5 Configuration Register					*/
+#define DMA5_X_COUNT			0xFFC00D50	/* DMA Channel 5 X Count Register						*/
+#define DMA5_X_MODIFY			0xFFC00D54	/* DMA Channel 5 X Modify Register						*/
+#define DMA5_Y_COUNT			0xFFC00D58	/* DMA Channel 5 Y Count Register						*/
+#define DMA5_Y_MODIFY			0xFFC00D5C	/* DMA Channel 5 Y Modify Register						*/
+#define DMA5_CURR_DESC_PTR		0xFFC00D60	/* DMA Channel 5 Current Descriptor Pointer Register	*/
+#define DMA5_CURR_ADDR			0xFFC00D64	/* DMA Channel 5 Current Address Register				*/
+#define DMA5_IRQ_STATUS			0xFFC00D68	/* DMA Channel 5 Interrupt/Status Register				*/
+#define DMA5_PERIPHERAL_MAP		0xFFC00D6C	/* DMA Channel 5 Peripheral Map Register				*/
+#define DMA5_CURR_X_COUNT		0xFFC00D70	/* DMA Channel 5 Current X Count Register				*/
+#define DMA5_CURR_Y_COUNT		0xFFC00D78	/* DMA Channel 5 Current Y Count Register				*/
+
+#define DMA6_NEXT_DESC_PTR		0xFFC00D80	/* DMA Channel 6 Next Descriptor Pointer Register		*/
+#define DMA6_START_ADDR			0xFFC00D84	/* DMA Channel 6 Start Address Register					*/
+#define DMA6_CONFIG				0xFFC00D88	/* DMA Channel 6 Configuration Register					*/
+#define DMA6_X_COUNT			0xFFC00D90	/* DMA Channel 6 X Count Register						*/
+#define DMA6_X_MODIFY			0xFFC00D94	/* DMA Channel 6 X Modify Register						*/
+#define DMA6_Y_COUNT			0xFFC00D98	/* DMA Channel 6 Y Count Register						*/
+#define DMA6_Y_MODIFY			0xFFC00D9C	/* DMA Channel 6 Y Modify Register						*/
+#define DMA6_CURR_DESC_PTR		0xFFC00DA0	/* DMA Channel 6 Current Descriptor Pointer Register	*/
+#define DMA6_CURR_ADDR			0xFFC00DA4	/* DMA Channel 6 Current Address Register				*/
+#define DMA6_IRQ_STATUS			0xFFC00DA8	/* DMA Channel 6 Interrupt/Status Register				*/
+#define DMA6_PERIPHERAL_MAP		0xFFC00DAC	/* DMA Channel 6 Peripheral Map Register				*/
+#define DMA6_CURR_X_COUNT		0xFFC00DB0	/* DMA Channel 6 Current X Count Register				*/
+#define DMA6_CURR_Y_COUNT		0xFFC00DB8	/* DMA Channel 6 Current Y Count Register				*/
+
+#define DMA7_NEXT_DESC_PTR		0xFFC00DC0	/* DMA Channel 7 Next Descriptor Pointer Register		*/
+#define DMA7_START_ADDR			0xFFC00DC4	/* DMA Channel 7 Start Address Register					*/
+#define DMA7_CONFIG				0xFFC00DC8	/* DMA Channel 7 Configuration Register					*/
+#define DMA7_X_COUNT			0xFFC00DD0	/* DMA Channel 7 X Count Register						*/
+#define DMA7_X_MODIFY			0xFFC00DD4	/* DMA Channel 7 X Modify Register						*/
+#define DMA7_Y_COUNT			0xFFC00DD8	/* DMA Channel 7 Y Count Register						*/
+#define DMA7_Y_MODIFY			0xFFC00DDC	/* DMA Channel 7 Y Modify Register						*/
+#define DMA7_CURR_DESC_PTR		0xFFC00DE0	/* DMA Channel 7 Current Descriptor Pointer Register	*/
+#define DMA7_CURR_ADDR			0xFFC00DE4	/* DMA Channel 7 Current Address Register				*/
+#define DMA7_IRQ_STATUS			0xFFC00DE8	/* DMA Channel 7 Interrupt/Status Register				*/
+#define DMA7_PERIPHERAL_MAP		0xFFC00DEC	/* DMA Channel 7 Peripheral Map Register				*/
+#define DMA7_CURR_X_COUNT		0xFFC00DF0	/* DMA Channel 7 Current X Count Register				*/
+#define DMA7_CURR_Y_COUNT		0xFFC00DF8	/* DMA Channel 7 Current Y Count Register				*/
+
+#define DMA8_NEXT_DESC_PTR		0xFFC00E00	/* DMA Channel 8 Next Descriptor Pointer Register		*/
+#define DMA8_START_ADDR			0xFFC00E04	/* DMA Channel 8 Start Address Register					*/
+#define DMA8_CONFIG				0xFFC00E08	/* DMA Channel 8 Configuration Register					*/
+#define DMA8_X_COUNT			0xFFC00E10	/* DMA Channel 8 X Count Register						*/
+#define DMA8_X_MODIFY			0xFFC00E14	/* DMA Channel 8 X Modify Register						*/
+#define DMA8_Y_COUNT			0xFFC00E18	/* DMA Channel 8 Y Count Register						*/
+#define DMA8_Y_MODIFY			0xFFC00E1C	/* DMA Channel 8 Y Modify Register						*/
+#define DMA8_CURR_DESC_PTR		0xFFC00E20	/* DMA Channel 8 Current Descriptor Pointer Register	*/
+#define DMA8_CURR_ADDR			0xFFC00E24	/* DMA Channel 8 Current Address Register				*/
+#define DMA8_IRQ_STATUS			0xFFC00E28	/* DMA Channel 8 Interrupt/Status Register				*/
+#define DMA8_PERIPHERAL_MAP		0xFFC00E2C	/* DMA Channel 8 Peripheral Map Register				*/
+#define DMA8_CURR_X_COUNT		0xFFC00E30	/* DMA Channel 8 Current X Count Register				*/
+#define DMA8_CURR_Y_COUNT		0xFFC00E38	/* DMA Channel 8 Current Y Count Register				*/
+
+#define DMA9_NEXT_DESC_PTR		0xFFC00E40	/* DMA Channel 9 Next Descriptor Pointer Register		*/
+#define DMA9_START_ADDR			0xFFC00E44	/* DMA Channel 9 Start Address Register					*/
+#define DMA9_CONFIG				0xFFC00E48	/* DMA Channel 9 Configuration Register					*/
+#define DMA9_X_COUNT			0xFFC00E50	/* DMA Channel 9 X Count Register						*/
+#define DMA9_X_MODIFY			0xFFC00E54	/* DMA Channel 9 X Modify Register						*/
+#define DMA9_Y_COUNT			0xFFC00E58	/* DMA Channel 9 Y Count Register						*/
+#define DMA9_Y_MODIFY			0xFFC00E5C	/* DMA Channel 9 Y Modify Register						*/
+#define DMA9_CURR_DESC_PTR		0xFFC00E60	/* DMA Channel 9 Current Descriptor Pointer Register	*/
+#define DMA9_CURR_ADDR			0xFFC00E64	/* DMA Channel 9 Current Address Register				*/
+#define DMA9_IRQ_STATUS			0xFFC00E68	/* DMA Channel 9 Interrupt/Status Register				*/
+#define DMA9_PERIPHERAL_MAP		0xFFC00E6C	/* DMA Channel 9 Peripheral Map Register				*/
+#define DMA9_CURR_X_COUNT		0xFFC00E70	/* DMA Channel 9 Current X Count Register				*/
+#define DMA9_CURR_Y_COUNT		0xFFC00E78	/* DMA Channel 9 Current Y Count Register				*/
+
+#define DMA10_NEXT_DESC_PTR		0xFFC00E80	/* DMA Channel 10 Next Descriptor Pointer Register		*/
+#define DMA10_START_ADDR		0xFFC00E84	/* DMA Channel 10 Start Address Register				*/
+#define DMA10_CONFIG			0xFFC00E88	/* DMA Channel 10 Configuration Register				*/
+#define DMA10_X_COUNT			0xFFC00E90	/* DMA Channel 10 X Count Register						*/
+#define DMA10_X_MODIFY			0xFFC00E94	/* DMA Channel 10 X Modify Register						*/
+#define DMA10_Y_COUNT			0xFFC00E98	/* DMA Channel 10 Y Count Register						*/
+#define DMA10_Y_MODIFY			0xFFC00E9C	/* DMA Channel 10 Y Modify Register						*/
+#define DMA10_CURR_DESC_PTR		0xFFC00EA0	/* DMA Channel 10 Current Descriptor Pointer Register	*/
+#define DMA10_CURR_ADDR			0xFFC00EA4	/* DMA Channel 10 Current Address Register				*/
+#define DMA10_IRQ_STATUS		0xFFC00EA8	/* DMA Channel 10 Interrupt/Status Register				*/
+#define DMA10_PERIPHERAL_MAP	0xFFC00EAC	/* DMA Channel 10 Peripheral Map Register				*/
+#define DMA10_CURR_X_COUNT		0xFFC00EB0	/* DMA Channel 10 Current X Count Register				*/
+#define DMA10_CURR_Y_COUNT		0xFFC00EB8	/* DMA Channel 10 Current Y Count Register				*/
+
+#define DMA11_NEXT_DESC_PTR		0xFFC00EC0	/* DMA Channel 11 Next Descriptor Pointer Register		*/
+#define DMA11_START_ADDR		0xFFC00EC4	/* DMA Channel 11 Start Address Register				*/
+#define DMA11_CONFIG			0xFFC00EC8	/* DMA Channel 11 Configuration Register				*/
+#define DMA11_X_COUNT			0xFFC00ED0	/* DMA Channel 11 X Count Register						*/
+#define DMA11_X_MODIFY			0xFFC00ED4	/* DMA Channel 11 X Modify Register						*/
+#define DMA11_Y_COUNT			0xFFC00ED8	/* DMA Channel 11 Y Count Register						*/
+#define DMA11_Y_MODIFY			0xFFC00EDC	/* DMA Channel 11 Y Modify Register						*/
+#define DMA11_CURR_DESC_PTR		0xFFC00EE0	/* DMA Channel 11 Current Descriptor Pointer Register	*/
+#define DMA11_CURR_ADDR			0xFFC00EE4	/* DMA Channel 11 Current Address Register				*/
+#define DMA11_IRQ_STATUS		0xFFC00EE8	/* DMA Channel 11 Interrupt/Status Register				*/
+#define DMA11_PERIPHERAL_MAP	0xFFC00EEC	/* DMA Channel 11 Peripheral Map Register				*/
+#define DMA11_CURR_X_COUNT		0xFFC00EF0	/* DMA Channel 11 Current X Count Register				*/
+#define DMA11_CURR_Y_COUNT		0xFFC00EF8	/* DMA Channel 11 Current Y Count Register				*/
+
+#define MDMA_D0_NEXT_DESC_PTR	0xFFC00F00	/* MemDMA Stream 0 Destination Next Descriptor Pointer Register		*/
+#define MDMA_D0_START_ADDR		0xFFC00F04	/* MemDMA Stream 0 Destination Start Address Register				*/
+#define MDMA_D0_CONFIG			0xFFC00F08	/* MemDMA Stream 0 Destination Configuration Register				*/
+#define MDMA_D0_X_COUNT			0xFFC00F10	/* MemDMA Stream 0 Destination X Count Register						*/
+#define MDMA_D0_X_MODIFY		0xFFC00F14	/* MemDMA Stream 0 Destination X Modify Register					*/
+#define MDMA_D0_Y_COUNT			0xFFC00F18	/* MemDMA Stream 0 Destination Y Count Register						*/
+#define MDMA_D0_Y_MODIFY		0xFFC00F1C	/* MemDMA Stream 0 Destination Y Modify Register					*/
+#define MDMA_D0_CURR_DESC_PTR	0xFFC00F20	/* MemDMA Stream 0 Destination Current Descriptor Pointer Register	*/
+#define MDMA_D0_CURR_ADDR		0xFFC00F24	/* MemDMA Stream 0 Destination Current Address Register				*/
+#define MDMA_D0_IRQ_STATUS		0xFFC00F28	/* MemDMA Stream 0 Destination Interrupt/Status Register			*/
+#define MDMA_D0_PERIPHERAL_MAP	0xFFC00F2C	/* MemDMA Stream 0 Destination Peripheral Map Register				*/
+#define MDMA_D0_CURR_X_COUNT	0xFFC00F30	/* MemDMA Stream 0 Destination Current X Count Register				*/
+#define MDMA_D0_CURR_Y_COUNT	0xFFC00F38	/* MemDMA Stream 0 Destination Current Y Count Register				*/
+
+#define MDMA_S0_NEXT_DESC_PTR	0xFFC00F40	/* MemDMA Stream 0 Source Next Descriptor Pointer Register			*/
+#define MDMA_S0_START_ADDR		0xFFC00F44	/* MemDMA Stream 0 Source Start Address Register					*/
+#define MDMA_S0_CONFIG			0xFFC00F48	/* MemDMA Stream 0 Source Configuration Register					*/
+#define MDMA_S0_X_COUNT			0xFFC00F50	/* MemDMA Stream 0 Source X Count Register							*/
+#define MDMA_S0_X_MODIFY		0xFFC00F54	/* MemDMA Stream 0 Source X Modify Register							*/
+#define MDMA_S0_Y_COUNT			0xFFC00F58	/* MemDMA Stream 0 Source Y Count Register							*/
+#define MDMA_S0_Y_MODIFY		0xFFC00F5C	/* MemDMA Stream 0 Source Y Modify Register							*/
+#define MDMA_S0_CURR_DESC_PTR	0xFFC00F60	/* MemDMA Stream 0 Source Current Descriptor Pointer Register		*/
+#define MDMA_S0_CURR_ADDR		0xFFC00F64	/* MemDMA Stream 0 Source Current Address Register					*/
+#define MDMA_S0_IRQ_STATUS		0xFFC00F68	/* MemDMA Stream 0 Source Interrupt/Status Register					*/
+#define MDMA_S0_PERIPHERAL_MAP	0xFFC00F6C	/* MemDMA Stream 0 Source Peripheral Map Register					*/
+#define MDMA_S0_CURR_X_COUNT	0xFFC00F70	/* MemDMA Stream 0 Source Current X Count Register					*/
+#define MDMA_S0_CURR_Y_COUNT	0xFFC00F78	/* MemDMA Stream 0 Source Current Y Count Register					*/
+
+#define MDMA_D1_NEXT_DESC_PTR	0xFFC00F80	/* MemDMA Stream 1 Destination Next Descriptor Pointer Register		*/
+#define MDMA_D1_START_ADDR		0xFFC00F84	/* MemDMA Stream 1 Destination Start Address Register				*/
+#define MDMA_D1_CONFIG			0xFFC00F88	/* MemDMA Stream 1 Destination Configuration Register				*/
+#define MDMA_D1_X_COUNT			0xFFC00F90	/* MemDMA Stream 1 Destination X Count Register						*/
+#define MDMA_D1_X_MODIFY		0xFFC00F94	/* MemDMA Stream 1 Destination X Modify Register					*/
+#define MDMA_D1_Y_COUNT			0xFFC00F98	/* MemDMA Stream 1 Destination Y Count Register						*/
+#define MDMA_D1_Y_MODIFY		0xFFC00F9C	/* MemDMA Stream 1 Destination Y Modify Register					*/
+#define MDMA_D1_CURR_DESC_PTR	0xFFC00FA0	/* MemDMA Stream 1 Destination Current Descriptor Pointer Register	*/
+#define MDMA_D1_CURR_ADDR		0xFFC00FA4	/* MemDMA Stream 1 Destination Current Address Register				*/
+#define MDMA_D1_IRQ_STATUS		0xFFC00FA8	/* MemDMA Stream 1 Destination Interrupt/Status Register			*/
+#define MDMA_D1_PERIPHERAL_MAP	0xFFC00FAC	/* MemDMA Stream 1 Destination Peripheral Map Register				*/
+#define MDMA_D1_CURR_X_COUNT	0xFFC00FB0	/* MemDMA Stream 1 Destination Current X Count Register				*/
+#define MDMA_D1_CURR_Y_COUNT	0xFFC00FB8	/* MemDMA Stream 1 Destination Current Y Count Register				*/
+
+#define MDMA_S1_NEXT_DESC_PTR	0xFFC00FC0	/* MemDMA Stream 1 Source Next Descriptor Pointer Register			*/
+#define MDMA_S1_START_ADDR		0xFFC00FC4	/* MemDMA Stream 1 Source Start Address Register					*/
+#define MDMA_S1_CONFIG			0xFFC00FC8	/* MemDMA Stream 1 Source Configuration Register					*/
+#define MDMA_S1_X_COUNT			0xFFC00FD0	/* MemDMA Stream 1 Source X Count Register							*/
+#define MDMA_S1_X_MODIFY		0xFFC00FD4	/* MemDMA Stream 1 Source X Modify Register							*/
+#define MDMA_S1_Y_COUNT			0xFFC00FD8	/* MemDMA Stream 1 Source Y Count Register							*/
+#define MDMA_S1_Y_MODIFY		0xFFC00FDC	/* MemDMA Stream 1 Source Y Modify Register							*/
+#define MDMA_S1_CURR_DESC_PTR	0xFFC00FE0	/* MemDMA Stream 1 Source Current Descriptor Pointer Register		*/
+#define MDMA_S1_CURR_ADDR		0xFFC00FE4	/* MemDMA Stream 1 Source Current Address Register					*/
+#define MDMA_S1_IRQ_STATUS		0xFFC00FE8	/* MemDMA Stream 1 Source Interrupt/Status Register					*/
+#define MDMA_S1_PERIPHERAL_MAP	0xFFC00FEC	/* MemDMA Stream 1 Source Peripheral Map Register					*/
+#define MDMA_S1_CURR_X_COUNT	0xFFC00FF0	/* MemDMA Stream 1 Source Current X Count Register					*/
+#define MDMA_S1_CURR_Y_COUNT	0xFFC00FF8	/* MemDMA Stream 1 Source Current Y Count Register					*/
+
+
+/* Parallel Peripheral Interface (0xFFC01000 - 0xFFC010FF)				*/
+#define PPI_CONTROL			0xFFC01000	/* PPI Control Register			*/
+#define PPI_STATUS			0xFFC01004	/* PPI Status Register			*/
+#define PPI_COUNT			0xFFC01008	/* PPI Transfer Count Register	*/
+#define PPI_DELAY			0xFFC0100C	/* PPI Delay Count Register		*/
+#define PPI_FRAME			0xFFC01010	/* PPI Frame Length Register	*/
+
+
+/* Two-Wire Interface		(0xFFC01400 - 0xFFC014FF)								*/
+#define TWI0_REGBASE			0xFFC01400
+#define TWI0_CLKDIV			0xFFC01400	/* Serial Clock Divider Register			*/
+#define TWI0_CONTROL			0xFFC01404	/* TWI Control Register						*/
+#define TWI0_SLAVE_CTL		0xFFC01408	/* Slave Mode Control Register				*/
+#define TWI0_SLAVE_STAT		0xFFC0140C	/* Slave Mode Status Register				*/
+#define TWI0_SLAVE_ADDR		0xFFC01410	/* Slave Mode Address Register				*/
+#define TWI0_MASTER_CTL		0xFFC01414	/* Master Mode Control Register				*/
+#define TWI0_MASTER_STAT		0xFFC01418	/* Master Mode Status Register				*/
+#define TWI0_MASTER_ADDR		0xFFC0141C	/* Master Mode Address Register				*/
+#define TWI0_INT_STAT		0xFFC01420	/* TWI Interrupt Status Register			*/
+#define TWI0_INT_MASK		0xFFC01424	/* TWI Master Interrupt Mask Register		*/
+#define TWI0_FIFO_CTL		0xFFC01428	/* FIFO Control Register					*/
+#define TWI0_FIFO_STAT		0xFFC0142C	/* FIFO Status Register						*/
+#define TWI0_XMT_DATA8		0xFFC01480	/* FIFO Transmit Data Single Byte Register	*/
+#define TWI0_XMT_DATA16		0xFFC01484	/* FIFO Transmit Data Double Byte Register	*/
+#define TWI0_RCV_DATA8		0xFFC01488	/* FIFO Receive Data Single Byte Register	*/
+#define TWI0_RCV_DATA16		0xFFC0148C	/* FIFO Receive Data Double Byte Register	*/
+
+
+/* General Purpose I/O Port G (0xFFC01500 - 0xFFC015FF)												*/
+#define PORTGIO					0xFFC01500	/* Port G I/O Pin State Specify Register				*/
+#define PORTGIO_CLEAR			0xFFC01504	/* Port G I/O Peripheral Interrupt Clear Register		*/
+#define PORTGIO_SET				0xFFC01508	/* Port G I/O Peripheral Interrupt Set Register			*/
+#define PORTGIO_TOGGLE			0xFFC0150C	/* Port G I/O Pin State Toggle Register					*/
+#define PORTGIO_MASKA			0xFFC01510	/* Port G I/O Mask State Specify Interrupt A Register	*/
+#define PORTGIO_MASKA_CLEAR		0xFFC01514	/* Port G I/O Mask Disable Interrupt A Register			*/
+#define PORTGIO_MASKA_SET		0xFFC01518	/* Port G I/O Mask Enable Interrupt A Register			*/
+#define PORTGIO_MASKA_TOGGLE	0xFFC0151C	/* Port G I/O Mask Toggle Enable Interrupt A Register	*/
+#define PORTGIO_MASKB			0xFFC01520	/* Port G I/O Mask State Specify Interrupt B Register	*/
+#define PORTGIO_MASKB_CLEAR		0xFFC01524	/* Port G I/O Mask Disable Interrupt B Register			*/
+#define PORTGIO_MASKB_SET		0xFFC01528	/* Port G I/O Mask Enable Interrupt B Register			*/
+#define PORTGIO_MASKB_TOGGLE	0xFFC0152C	/* Port G I/O Mask Toggle Enable Interrupt B Register	*/
+#define PORTGIO_DIR				0xFFC01530	/* Port G I/O Direction Register						*/
+#define PORTGIO_POLAR			0xFFC01534	/* Port G I/O Source Polarity Register					*/
+#define PORTGIO_EDGE			0xFFC01538	/* Port G I/O Source Sensitivity Register				*/
+#define PORTGIO_BOTH			0xFFC0153C	/* Port G I/O Set on BOTH Edges Register				*/
+#define PORTGIO_INEN			0xFFC01540	/* Port G I/O Input Enable Register						*/
+
+
+/* General Purpose I/O Port H (0xFFC01700 - 0xFFC017FF)												*/
+#define PORTHIO					0xFFC01700	/* Port H I/O Pin State Specify Register				*/
+#define PORTHIO_CLEAR			0xFFC01704	/* Port H I/O Peripheral Interrupt Clear Register		*/
+#define PORTHIO_SET				0xFFC01708	/* Port H I/O Peripheral Interrupt Set Register			*/
+#define PORTHIO_TOGGLE			0xFFC0170C	/* Port H I/O Pin State Toggle Register					*/
+#define PORTHIO_MASKA			0xFFC01710	/* Port H I/O Mask State Specify Interrupt A Register	*/
+#define PORTHIO_MASKA_CLEAR		0xFFC01714	/* Port H I/O Mask Disable Interrupt A Register			*/
+#define PORTHIO_MASKA_SET		0xFFC01718	/* Port H I/O Mask Enable Interrupt A Register			*/
+#define PORTHIO_MASKA_TOGGLE	0xFFC0171C	/* Port H I/O Mask Toggle Enable Interrupt A Register	*/
+#define PORTHIO_MASKB			0xFFC01720	/* Port H I/O Mask State Specify Interrupt B Register	*/
+#define PORTHIO_MASKB_CLEAR		0xFFC01724	/* Port H I/O Mask Disable Interrupt B Register			*/
+#define PORTHIO_MASKB_SET		0xFFC01728	/* Port H I/O Mask Enable Interrupt B Register			*/
+#define PORTHIO_MASKB_TOGGLE	0xFFC0172C	/* Port H I/O Mask Toggle Enable Interrupt B Register	*/
+#define PORTHIO_DIR				0xFFC01730	/* Port H I/O Direction Register						*/
+#define PORTHIO_POLAR			0xFFC01734	/* Port H I/O Source Polarity Register					*/
+#define PORTHIO_EDGE			0xFFC01738	/* Port H I/O Source Sensitivity Register				*/
+#define PORTHIO_BOTH			0xFFC0173C	/* Port H I/O Set on BOTH Edges Register				*/
+#define PORTHIO_INEN			0xFFC01740	/* Port H I/O Input Enable Register						*/
+
+
+/* UART1 Controller		(0xFFC02000 - 0xFFC020FF)								*/
+#define UART1_THR			0xFFC02000	/* Transmit Holding register			*/
+#define UART1_RBR			0xFFC02000	/* Receive Buffer register				*/
+#define UART1_DLL			0xFFC02000	/* Divisor Latch (Low-Byte)				*/
+#define UART1_IER			0xFFC02004	/* Interrupt Enable Register			*/
+#define UART1_DLH			0xFFC02004	/* Divisor Latch (High-Byte)			*/
+#define UART1_IIR			0xFFC02008	/* Interrupt Identification Register	*/
+#define UART1_LCR			0xFFC0200C	/* Line Control Register				*/
+#define UART1_MCR			0xFFC02010	/* Modem Control Register				*/
+#define UART1_LSR			0xFFC02014	/* Line Status Register					*/
+#define UART1_MSR			0xFFC02018	/* Modem Status Register				*/
+#define UART1_SCR			0xFFC0201C	/* SCR Scratch Register					*/
+#define UART1_GCTL			0xFFC02024	/* Global Control Register				*/
+
+
+/* Pin Control Registers	(0xFFC03200 - 0xFFC032FF)											*/
+#define PORTF_FER			0xFFC03200	/* Port F Function Enable Register (Alternate/Flag*)	*/
+#define PORTG_FER			0xFFC03204	/* Port G Function Enable Register (Alternate/Flag*)	*/
+#define PORTH_FER			0xFFC03208	/* Port H Function Enable Register (Alternate/Flag*)	*/
+#define BFIN_PORT_MUX			0xFFC0320C	/* Port Multiplexer Control Register					*/
+
+
+/* Handshake MDMA Registers	(0xFFC03300 - 0xFFC033FF)										*/
+#define HMDMA0_CONTROL		0xFFC03300	/* Handshake MDMA0 Control Register					*/
+#define HMDMA0_ECINIT		0xFFC03304	/* HMDMA0 Initial Edge Count Register				*/
+#define HMDMA0_BCINIT		0xFFC03308	/* HMDMA0 Initial Block Count Register				*/
+#define HMDMA0_ECURGENT		0xFFC0330C	/* HMDMA0 Urgent Edge Count Threshold Register		*/
+#define HMDMA0_ECOVERFLOW	0xFFC03310	/* HMDMA0 Edge Count Overflow Interrupt Register	*/
+#define HMDMA0_ECOUNT		0xFFC03314	/* HMDMA0 Current Edge Count Register				*/
+#define HMDMA0_BCOUNT		0xFFC03318	/* HMDMA0 Current Block Count Register				*/
+
+#define HMDMA1_CONTROL		0xFFC03340	/* Handshake MDMA1 Control Register					*/
+#define HMDMA1_ECINIT		0xFFC03344	/* HMDMA1 Initial Edge Count Register				*/
+#define HMDMA1_BCINIT		0xFFC03348	/* HMDMA1 Initial Block Count Register				*/
+#define HMDMA1_ECURGENT		0xFFC0334C	/* HMDMA1 Urgent Edge Count Threshold Register		*/
+#define HMDMA1_ECOVERFLOW	0xFFC03350	/* HMDMA1 Edge Count Overflow Interrupt Register	*/
+#define HMDMA1_ECOUNT		0xFFC03354	/* HMDMA1 Current Edge Count Register				*/
+#define HMDMA1_BCOUNT		0xFFC03358	/* HMDMA1 Current Block Count Register				*/
+
+
+/* GPIO PIN mux (0xFFC03210 - OxFFC03288) */
+#define PORTF_MUX               0xFFC03210      /* Port F mux control */
+#define PORTG_MUX               0xFFC03214      /* Port G mux control */
+#define PORTH_MUX               0xFFC03218      /* Port H mux control */
+#define PORTF_DRIVE             0xFFC03220      /* Port F drive strength control */
+#define PORTG_DRIVE             0xFFC03224      /* Port G drive strength control */
+#define PORTH_DRIVE             0xFFC03228      /* Port H drive strength control */
+#define PORTF_SLEW              0xFFC03230      /* Port F slew control */
+#define PORTG_SLEW              0xFFC03234      /* Port G slew control */
+#define PORTH_SLEW              0xFFC03238      /* Port H slew control */
+#define PORTF_HYSTERISIS        0xFFC03240      /* Port F Schmitt trigger control */
+#define PORTG_HYSTERISIS        0xFFC03244      /* Port G Schmitt trigger control */
+#define PORTH_HYSTERISIS        0xFFC03248      /* Port H Schmitt trigger control */
+#define MISCPORT_DRIVE          0xFFC03280      /* Misc Port drive strength control */
+#define MISCPORT_SLEW           0xFFC03284      /* Misc Port slew control */
+#define MISCPORT_HYSTERISIS     0xFFC03288      /* Misc Port Schmitt trigger control */
+
+
+/***********************************************************************************
+** System MMR Register Bits And Macros
+**
+** Disclaimer:	All macros are intended to make C and Assembly code more readable.
+**				Use these macros carefully, as any that do left shifts for field
+**				depositing will result in the lower order bits being destroyed.  Any
+**				macro that shifts left to properly position the bit-field should be
+**				used as part of an OR to initialize a register and NOT as a dynamic
+**				modifier UNLESS the lower order bits are saved and ORed back in when
+**				the macro is used.
+*************************************************************************************/
+
+/* CHIPID Masks */
+#define CHIPID_VERSION         0xF0000000
+#define CHIPID_FAMILY          0x0FFFF000
+#define CHIPID_MANUFACTURE     0x00000FFE
+
+/* SWRST Masks																		*/
+#define SYSTEM_RESET		0x0007	/* Initiates A System Software Reset			*/
+#define	DOUBLE_FAULT		0x0008	/* Core Double Fault Causes Reset				*/
+#define RESET_DOUBLE		0x2000	/* SW Reset Generated By Core Double-Fault		*/
+#define RESET_WDOG			0x4000	/* SW Reset Generated By Watchdog Timer			*/
+#define RESET_SOFTWARE		0x8000	/* SW Reset Occurred Since Last Read Of SWRST	*/
+
+/* SYSCR Masks																				*/
+#define BMODE				0x0007	/* Boot Mode - Latched During HW Reset From Mode Pins	*/
+#define	NOBOOT				0x0010	/* Execute From L1 or ASYNC Bank 0 When BMODE = 0		*/
+
+
+/* *************  SYSTEM INTERRUPT CONTROLLER MASKS *************************************/
+/* Peripheral Masks For SIC_ISR, SIC_IWR, SIC_IMASK										*/
+
+#if 0
+#define IRQ_PLL_WAKEUP	0x00000001	/* PLL Wakeup Interrupt			 					*/
+
+#define IRQ_ERROR1      0x00000002  /* Error Interrupt (DMA, DMARx Block, DMARx Overflow) */
+#define IRQ_ERROR2      0x00000004  /* Error Interrupt (CAN, Ethernet, SPORTx, PPI, SPI, UARTx) */
+#define IRQ_RTC			0x00000008	/* Real Time Clock Interrupt 						*/
+#define IRQ_DMA0		0x00000010	/* DMA Channel 0 (PPI) Interrupt 					*/
+#define IRQ_DMA3		0x00000020	/* DMA Channel 3 (SPORT0 RX) Interrupt 				*/
+#define IRQ_DMA4		0x00000040	/* DMA Channel 4 (SPORT0 TX) Interrupt 				*/
+#define IRQ_DMA5		0x00000080	/* DMA Channel 5 (SPORT1 RX) Interrupt 				*/
+
+#define IRQ_DMA6		0x00000100	/* DMA Channel 6 (SPORT1 TX) Interrupt 		 		*/
+#define IRQ_TWI			0x00000200	/* TWI Interrupt									*/
+#define IRQ_DMA7		0x00000400	/* DMA Channel 7 (SPI) Interrupt 					*/
+#define IRQ_DMA8		0x00000800	/* DMA Channel 8 (UART0 RX) Interrupt 				*/
+#define IRQ_DMA9		0x00001000	/* DMA Channel 9 (UART0 TX) Interrupt 				*/
+#define IRQ_DMA10		0x00002000	/* DMA Channel 10 (UART1 RX) Interrupt 				*/
+#define IRQ_DMA11		0x00004000	/* DMA Channel 11 (UART1 TX) Interrupt 				*/
+#define IRQ_CAN_RX		0x00008000	/* CAN Receive Interrupt 							*/
+
+#define IRQ_CAN_TX		0x00010000	/* CAN Transmit Interrupt  							*/
+#define IRQ_DMA1		0x00020000	/* DMA Channel 1 (Ethernet RX) Interrupt 			*/
+#define IRQ_PFA_PORTH	0x00020000	/* PF Port H (PF47:32) Interrupt A 					*/
+#define IRQ_DMA2		0x00040000	/* DMA Channel 2 (Ethernet TX) Interrupt 			*/
+#define IRQ_PFB_PORTH	0x00040000	/* PF Port H (PF47:32) Interrupt B 					*/
+#define IRQ_TIMER0		0x00080000	/* Timer 0 Interrupt								*/
+#define IRQ_TIMER1		0x00100000	/* Timer 1 Interrupt 								*/
+#define IRQ_TIMER2		0x00200000	/* Timer 2 Interrupt 								*/
+#define IRQ_TIMER3		0x00400000	/* Timer 3 Interrupt 								*/
+#define IRQ_TIMER4		0x00800000	/* Timer 4 Interrupt 								*/
+
+#define IRQ_TIMER5		0x01000000	/* Timer 5 Interrupt 								*/
+#define IRQ_TIMER6		0x02000000	/* Timer 6 Interrupt 								*/
+#define IRQ_TIMER7		0x04000000	/* Timer 7 Interrupt 								*/
+#define IRQ_PFA_PORTFG	0x08000000	/* PF Ports F&G (PF31:0) Interrupt A 				*/
+#define IRQ_PFB_PORTF	0x80000000	/* PF Port F (PF15:0) Interrupt B 					*/
+#define IRQ_DMA12		0x20000000	/* DMA Channels 12 (MDMA1 Source) RX Interrupt 		*/
+#define IRQ_DMA13		0x20000000	/* DMA Channels 13 (MDMA1 Destination) TX Interrupt */
+#define IRQ_DMA14		0x40000000	/* DMA Channels 14 (MDMA0 Source) RX Interrupt 		*/
+#define IRQ_DMA15		0x40000000	/* DMA Channels 15 (MDMA0 Destination) TX Interrupt */
+#define IRQ_WDOG		0x80000000	/* Software Watchdog Timer Interrupt 				*/
+#define IRQ_PFB_PORTG	0x10000000	/* PF Port G (PF31:16) Interrupt B 					*/
+#endif
+
+/* SIC_IAR0 Macros															*/
+#define P0_IVG(x)		(((x)&0xF)-7)			/* Peripheral #0 assigned IVG #x 	*/
+#define P1_IVG(x)		(((x)&0xF)-7) << 0x4	/* Peripheral #1 assigned IVG #x 	*/
+#define P2_IVG(x)		(((x)&0xF)-7) << 0x8	/* Peripheral #2 assigned IVG #x 	*/
+#define P3_IVG(x)		(((x)&0xF)-7) << 0xC	/* Peripheral #3 assigned IVG #x	*/
+#define P4_IVG(x)		(((x)&0xF)-7) << 0x10	/* Peripheral #4 assigned IVG #x	*/
+#define P5_IVG(x)		(((x)&0xF)-7) << 0x14	/* Peripheral #5 assigned IVG #x	*/
+#define P6_IVG(x)		(((x)&0xF)-7) << 0x18	/* Peripheral #6 assigned IVG #x	*/
+#define P7_IVG(x)		(((x)&0xF)-7) << 0x1C	/* Peripheral #7 assigned IVG #x	*/
+
+/* SIC_IAR1 Macros															*/
+#define P8_IVG(x)		(((x)&0xF)-7)			/* Peripheral #8 assigned IVG #x 	*/
+#define P9_IVG(x)		(((x)&0xF)-7) << 0x4	/* Peripheral #9 assigned IVG #x 	*/
+#define P10_IVG(x)		(((x)&0xF)-7) << 0x8	/* Peripheral #10 assigned IVG #x	*/
+#define P11_IVG(x)		(((x)&0xF)-7) << 0xC	/* Peripheral #11 assigned IVG #x 	*/
+#define P12_IVG(x)		(((x)&0xF)-7) << 0x10	/* Peripheral #12 assigned IVG #x	*/
+#define P13_IVG(x)		(((x)&0xF)-7) << 0x14	/* Peripheral #13 assigned IVG #x	*/
+#define P14_IVG(x)		(((x)&0xF)-7) << 0x18	/* Peripheral #14 assigned IVG #x	*/
+#define P15_IVG(x)		(((x)&0xF)-7) << 0x1C	/* Peripheral #15 assigned IVG #x	*/
+
+/* SIC_IAR2 Macros															*/
+#define P16_IVG(x)		(((x)&0xF)-7)			/* Peripheral #16 assigned IVG #x	*/
+#define P17_IVG(x)		(((x)&0xF)-7) << 0x4	/* Peripheral #17 assigned IVG #x	*/
+#define P18_IVG(x)		(((x)&0xF)-7) << 0x8	/* Peripheral #18 assigned IVG #x	*/
+#define P19_IVG(x)		(((x)&0xF)-7) << 0xC	/* Peripheral #19 assigned IVG #x	*/
+#define P20_IVG(x)		(((x)&0xF)-7) << 0x10	/* Peripheral #20 assigned IVG #x	*/
+#define P21_IVG(x)		(((x)&0xF)-7) << 0x14	/* Peripheral #21 assigned IVG #x	*/
+#define P22_IVG(x)		(((x)&0xF)-7) << 0x18	/* Peripheral #22 assigned IVG #x	*/
+#define P23_IVG(x)		(((x)&0xF)-7) << 0x1C	/* Peripheral #23 assigned IVG #x	*/
+
+/* SIC_IAR3 Macros															*/
+#define P24_IVG(x)		(((x)&0xF)-7)			/* Peripheral #24 assigned IVG #x	*/
+#define P25_IVG(x)		(((x)&0xF)-7) << 0x4	/* Peripheral #25 assigned IVG #x	*/
+#define P26_IVG(x)		(((x)&0xF)-7) << 0x8	/* Peripheral #26 assigned IVG #x	*/
+#define P27_IVG(x)		(((x)&0xF)-7) << 0xC	/* Peripheral #27 assigned IVG #x	*/
+#define P28_IVG(x)		(((x)&0xF)-7) << 0x10	/* Peripheral #28 assigned IVG #x	*/
+#define P29_IVG(x)		(((x)&0xF)-7) << 0x14	/* Peripheral #29 assigned IVG #x	*/
+#define P30_IVG(x)		(((x)&0xF)-7) << 0x18	/* Peripheral #30 assigned IVG #x	*/
+#define P31_IVG(x)		(((x)&0xF)-7) << 0x1C	/* Peripheral #31 assigned IVG #x	*/
+
+
+/* SIC_IMASK Masks																		*/
+#define SIC_UNMASK_ALL	0x00000000					/* Unmask all peripheral interrupts	*/
+#define SIC_MASK_ALL	0xFFFFFFFF					/* Mask all peripheral interrupts	*/
+#define SIC_MASK(x)		(1 << ((x)&0x1F))					/* Mask Peripheral #x interrupt		*/
+#define SIC_UNMASK(x)	(0xFFFFFFFF ^ (1 << ((x)&0x1F)))	/* Unmask Peripheral #x interrupt	*/
+
+/* SIC_IWR Masks																		*/
+#define IWR_DISABLE_ALL	0x00000000					/* Wakeup Disable all peripherals	*/
+#define IWR_ENABLE_ALL	0xFFFFFFFF					/* Wakeup Enable all peripherals	*/
+#define IWR_ENABLE(x)	(1 << ((x)&0x1F))					/* Wakeup Enable Peripheral #x		*/
+#define IWR_DISABLE(x)	(0xFFFFFFFF ^ (1 << ((x)&0x1F))) 	/* Wakeup Disable Peripheral #x		*/
+
+/*  ****************  GENERAL PURPOSE TIMER MASKS  **********************/
+/* TIMER_ENABLE Masks													*/
+#define TIMEN0			0x0001		/* Enable Timer 0					*/
+#define TIMEN1			0x0002		/* Enable Timer 1					*/
+#define TIMEN2			0x0004		/* Enable Timer 2					*/
+#define TIMEN3			0x0008		/* Enable Timer 3					*/
+#define TIMEN4			0x0010		/* Enable Timer 4					*/
+#define TIMEN5			0x0020		/* Enable Timer 5					*/
+#define TIMEN6			0x0040		/* Enable Timer 6					*/
+#define TIMEN7			0x0080		/* Enable Timer 7					*/
+
+/* TIMER_DISABLE Masks													*/
+#define TIMDIS0			TIMEN0		/* Disable Timer 0					*/
+#define TIMDIS1			TIMEN1		/* Disable Timer 1					*/
+#define TIMDIS2			TIMEN2		/* Disable Timer 2					*/
+#define TIMDIS3			TIMEN3		/* Disable Timer 3					*/
+#define TIMDIS4			TIMEN4		/* Disable Timer 4					*/
+#define TIMDIS5			TIMEN5		/* Disable Timer 5					*/
+#define TIMDIS6			TIMEN6		/* Disable Timer 6					*/
+#define TIMDIS7			TIMEN7		/* Disable Timer 7					*/
+
+/* TIMER_STATUS Masks													*/
+#define TIMIL0			0x00000001	/* Timer 0 Interrupt				*/
+#define TIMIL1			0x00000002	/* Timer 1 Interrupt				*/
+#define TIMIL2			0x00000004	/* Timer 2 Interrupt				*/
+#define TIMIL3			0x00000008	/* Timer 3 Interrupt				*/
+#define TOVF_ERR0		0x00000010	/* Timer 0 Counter Overflow			*/
+#define TOVF_ERR1		0x00000020	/* Timer 1 Counter Overflow			*/
+#define TOVF_ERR2		0x00000040	/* Timer 2 Counter Overflow			*/
+#define TOVF_ERR3		0x00000080	/* Timer 3 Counter Overflow			*/
+#define TRUN0			0x00001000	/* Timer 0 Slave Enable Status		*/
+#define TRUN1			0x00002000	/* Timer 1 Slave Enable Status		*/
+#define TRUN2			0x00004000	/* Timer 2 Slave Enable Status		*/
+#define TRUN3			0x00008000	/* Timer 3 Slave Enable Status		*/
+#define TIMIL4			0x00010000	/* Timer 4 Interrupt				*/
+#define TIMIL5			0x00020000	/* Timer 5 Interrupt				*/
+#define TIMIL6			0x00040000	/* Timer 6 Interrupt				*/
+#define TIMIL7			0x00080000	/* Timer 7 Interrupt				*/
+#define TOVF_ERR4		0x00100000	/* Timer 4 Counter Overflow			*/
+#define TOVF_ERR5		0x00200000	/* Timer 5 Counter Overflow			*/
+#define TOVF_ERR6		0x00400000	/* Timer 6 Counter Overflow			*/
+#define TOVF_ERR7		0x00800000	/* Timer 7 Counter Overflow			*/
+#define TRUN4			0x10000000	/* Timer 4 Slave Enable Status		*/
+#define TRUN5			0x20000000	/* Timer 5 Slave Enable Status		*/
+#define TRUN6			0x40000000	/* Timer 6 Slave Enable Status		*/
+#define TRUN7			0x80000000	/* Timer 7 Slave Enable Status		*/
+
+/* Alternate Deprecated Macros Provided For Backwards Code Compatibility */
+#define TOVL_ERR0 TOVF_ERR0
+#define TOVL_ERR1 TOVF_ERR1
+#define TOVL_ERR2 TOVF_ERR2
+#define TOVL_ERR3 TOVF_ERR3
+#define TOVL_ERR4 TOVF_ERR4
+#define TOVL_ERR5 TOVF_ERR5
+#define TOVL_ERR6 TOVF_ERR6
+#define TOVL_ERR7 TOVF_ERR7
+
+/* TIMERx_CONFIG Masks													*/
+#define PWM_OUT			0x0001	/* Pulse-Width Modulation Output Mode	*/
+#define WDTH_CAP		0x0002	/* Width Capture Input Mode				*/
+#define EXT_CLK			0x0003	/* External Clock Mode					*/
+#define PULSE_HI		0x0004	/* Action Pulse (Positive/Negative*)	*/
+#define PERIOD_CNT		0x0008	/* Period Count							*/
+#define IRQ_ENA			0x0010	/* Interrupt Request Enable				*/
+#define TIN_SEL			0x0020	/* Timer Input Select					*/
+#define OUT_DIS			0x0040	/* Output Pad Disable					*/
+#define CLK_SEL			0x0080	/* Timer Clock Select					*/
+#define TOGGLE_HI		0x0100	/* PWM_OUT PULSE_HI Toggle Mode			*/
+#define EMU_RUN			0x0200	/* Emulation Behavior Select			*/
+#define ERR_TYP			0xC000	/* Error Type							*/
+
+/* *********************  ASYNCHRONOUS MEMORY CONTROLLER MASKS  *************************/
+/* EBIU_AMGCTL Masks																	*/
+#define AMCKEN			0x0001		/* Enable CLKOUT									*/
+#define	AMBEN_NONE		0x0000		/* All Banks Disabled								*/
+#define AMBEN_B0		0x0002		/* Enable Async Memory Bank 0 only					*/
+#define AMBEN_B0_B1		0x0004		/* Enable Async Memory Banks 0 & 1 only				*/
+#define AMBEN_B0_B1_B2	0x0006		/* Enable Async Memory Banks 0, 1, and 2			*/
+#define AMBEN_ALL		0x0008		/* Enable Async Memory Banks (all) 0, 1, 2, and 3	*/
+
+/* EBIU_AMBCTL0 Masks																	*/
+#define B0RDYEN			0x00000001  /* Bank 0 (B0) RDY Enable							*/
+#define B0RDYPOL		0x00000002  /* B0 RDY Active High								*/
+#define B0TT_1			0x00000004  /* B0 Transition Time (Read to Write) = 1 cycle		*/
+#define B0TT_2			0x00000008  /* B0 Transition Time (Read to Write) = 2 cycles	*/
+#define B0TT_3			0x0000000C  /* B0 Transition Time (Read to Write) = 3 cycles	*/
+#define B0TT_4			0x00000000  /* B0 Transition Time (Read to Write) = 4 cycles	*/
+#define B0ST_1			0x00000010  /* B0 Setup Time (AOE to Read/Write) = 1 cycle		*/
+#define B0ST_2			0x00000020  /* B0 Setup Time (AOE to Read/Write) = 2 cycles		*/
+#define B0ST_3			0x00000030  /* B0 Setup Time (AOE to Read/Write) = 3 cycles		*/
+#define B0ST_4			0x00000000  /* B0 Setup Time (AOE to Read/Write) = 4 cycles		*/
+#define B0HT_1			0x00000040  /* B0 Hold Time (~Read/Write to ~AOE) = 1 cycle		*/
+#define B0HT_2			0x00000080  /* B0 Hold Time (~Read/Write to ~AOE) = 2 cycles	*/
+#define B0HT_3			0x000000C0  /* B0 Hold Time (~Read/Write to ~AOE) = 3 cycles	*/
+#define B0HT_0			0x00000000  /* B0 Hold Time (~Read/Write to ~AOE) = 0 cycles	*/
+#define B0RAT_1			0x00000100  /* B0 Read Access Time = 1 cycle					*/
+#define B0RAT_2			0x00000200  /* B0 Read Access Time = 2 cycles					*/
+#define B0RAT_3			0x00000300  /* B0 Read Access Time = 3 cycles					*/
+#define B0RAT_4			0x00000400  /* B0 Read Access Time = 4 cycles					*/
+#define B0RAT_5			0x00000500  /* B0 Read Access Time = 5 cycles					*/
+#define B0RAT_6			0x00000600  /* B0 Read Access Time = 6 cycles					*/
+#define B0RAT_7			0x00000700  /* B0 Read Access Time = 7 cycles					*/
+#define B0RAT_8			0x00000800  /* B0 Read Access Time = 8 cycles					*/
+#define B0RAT_9			0x00000900  /* B0 Read Access Time = 9 cycles					*/
+#define B0RAT_10		0x00000A00  /* B0 Read Access Time = 10 cycles					*/
+#define B0RAT_11		0x00000B00  /* B0 Read Access Time = 11 cycles					*/
+#define B0RAT_12		0x00000C00  /* B0 Read Access Time = 12 cycles					*/
+#define B0RAT_13		0x00000D00  /* B0 Read Access Time = 13 cycles					*/
+#define B0RAT_14		0x00000E00  /* B0 Read Access Time = 14 cycles					*/
+#define B0RAT_15		0x00000F00  /* B0 Read Access Time = 15 cycles					*/
+#define B0WAT_1			0x00001000  /* B0 Write Access Time = 1 cycle					*/
+#define B0WAT_2			0x00002000  /* B0 Write Access Time = 2 cycles					*/
+#define B0WAT_3			0x00003000  /* B0 Write Access Time = 3 cycles					*/
+#define B0WAT_4			0x00004000  /* B0 Write Access Time = 4 cycles					*/
+#define B0WAT_5			0x00005000  /* B0 Write Access Time = 5 cycles					*/
+#define B0WAT_6			0x00006000  /* B0 Write Access Time = 6 cycles					*/
+#define B0WAT_7			0x00007000  /* B0 Write Access Time = 7 cycles					*/
+#define B0WAT_8			0x00008000  /* B0 Write Access Time = 8 cycles					*/
+#define B0WAT_9			0x00009000  /* B0 Write Access Time = 9 cycles					*/
+#define B0WAT_10		0x0000A000  /* B0 Write Access Time = 10 cycles					*/
+#define B0WAT_11		0x0000B000  /* B0 Write Access Time = 11 cycles					*/
+#define B0WAT_12		0x0000C000  /* B0 Write Access Time = 12 cycles					*/
+#define B0WAT_13		0x0000D000  /* B0 Write Access Time = 13 cycles					*/
+#define B0WAT_14		0x0000E000  /* B0 Write Access Time = 14 cycles					*/
+#define B0WAT_15		0x0000F000  /* B0 Write Access Time = 15 cycles					*/
+
+#define B1RDYEN			0x00010000  /* Bank 1 (B1) RDY Enable                       	*/
+#define B1RDYPOL		0x00020000  /* B1 RDY Active High                           	*/
+#define B1TT_1			0x00040000  /* B1 Transition Time (Read to Write) = 1 cycle 	*/
+#define B1TT_2			0x00080000  /* B1 Transition Time (Read to Write) = 2 cycles	*/
+#define B1TT_3			0x000C0000  /* B1 Transition Time (Read to Write) = 3 cycles	*/
+#define B1TT_4			0x00000000  /* B1 Transition Time (Read to Write) = 4 cycles	*/
+#define B1ST_1			0x00100000  /* B1 Setup Time (AOE to Read/Write) = 1 cycle  	*/
+#define B1ST_2			0x00200000  /* B1 Setup Time (AOE to Read/Write) = 2 cycles 	*/
+#define B1ST_3			0x00300000  /* B1 Setup Time (AOE to Read/Write) = 3 cycles 	*/
+#define B1ST_4			0x00000000  /* B1 Setup Time (AOE to Read/Write) = 4 cycles 	*/
+#define B1HT_1			0x00400000  /* B1 Hold Time (~Read/Write to ~AOE) = 1 cycle 	*/
+#define B1HT_2			0x00800000  /* B1 Hold Time (~Read/Write to ~AOE) = 2 cycles	*/
+#define B1HT_3			0x00C00000  /* B1 Hold Time (~Read/Write to ~AOE) = 3 cycles	*/
+#define B1HT_0			0x00000000  /* B1 Hold Time (~Read/Write to ~AOE) = 0 cycles	*/
+#define B1RAT_1			0x01000000  /* B1 Read Access Time = 1 cycle					*/
+#define B1RAT_2			0x02000000  /* B1 Read Access Time = 2 cycles					*/
+#define B1RAT_3			0x03000000  /* B1 Read Access Time = 3 cycles					*/
+#define B1RAT_4			0x04000000  /* B1 Read Access Time = 4 cycles					*/
+#define B1RAT_5			0x05000000  /* B1 Read Access Time = 5 cycles					*/
+#define B1RAT_6			0x06000000  /* B1 Read Access Time = 6 cycles					*/
+#define B1RAT_7			0x07000000  /* B1 Read Access Time = 7 cycles					*/
+#define B1RAT_8			0x08000000  /* B1 Read Access Time = 8 cycles					*/
+#define B1RAT_9			0x09000000  /* B1 Read Access Time = 9 cycles					*/
+#define B1RAT_10		0x0A000000  /* B1 Read Access Time = 10 cycles					*/
+#define B1RAT_11		0x0B000000  /* B1 Read Access Time = 11 cycles					*/
+#define B1RAT_12		0x0C000000  /* B1 Read Access Time = 12 cycles					*/
+#define B1RAT_13		0x0D000000  /* B1 Read Access Time = 13 cycles					*/
+#define B1RAT_14		0x0E000000  /* B1 Read Access Time = 14 cycles					*/
+#define B1RAT_15		0x0F000000  /* B1 Read Access Time = 15 cycles					*/
+#define B1WAT_1			0x10000000  /* B1 Write Access Time = 1 cycle					*/
+#define B1WAT_2			0x20000000  /* B1 Write Access Time = 2 cycles					*/
+#define B1WAT_3			0x30000000  /* B1 Write Access Time = 3 cycles					*/
+#define B1WAT_4			0x40000000  /* B1 Write Access Time = 4 cycles					*/
+#define B1WAT_5			0x50000000  /* B1 Write Access Time = 5 cycles					*/
+#define B1WAT_6			0x60000000  /* B1 Write Access Time = 6 cycles					*/
+#define B1WAT_7			0x70000000  /* B1 Write Access Time = 7 cycles					*/
+#define B1WAT_8			0x80000000  /* B1 Write Access Time = 8 cycles					*/
+#define B1WAT_9			0x90000000  /* B1 Write Access Time = 9 cycles					*/
+#define B1WAT_10		0xA0000000  /* B1 Write Access Time = 10 cycles					*/
+#define B1WAT_11		0xB0000000  /* B1 Write Access Time = 11 cycles					*/
+#define B1WAT_12		0xC0000000  /* B1 Write Access Time = 12 cycles					*/
+#define B1WAT_13		0xD0000000  /* B1 Write Access Time = 13 cycles					*/
+#define B1WAT_14		0xE0000000  /* B1 Write Access Time = 14 cycles					*/
+#define B1WAT_15		0xF0000000  /* B1 Write Access Time = 15 cycles					*/
+
+/* EBIU_AMBCTL1 Masks																	*/
+#define B2RDYEN			0x00000001  /* Bank 2 (B2) RDY Enable							*/
+#define B2RDYPOL		0x00000002  /* B2 RDY Active High								*/
+#define B2TT_1			0x00000004  /* B2 Transition Time (Read to Write) = 1 cycle		*/
+#define B2TT_2			0x00000008  /* B2 Transition Time (Read to Write) = 2 cycles	*/
+#define B2TT_3			0x0000000C  /* B2 Transition Time (Read to Write) = 3 cycles	*/
+#define B2TT_4			0x00000000  /* B2 Transition Time (Read to Write) = 4 cycles	*/
+#define B2ST_1			0x00000010  /* B2 Setup Time (AOE to Read/Write) = 1 cycle		*/
+#define B2ST_2			0x00000020  /* B2 Setup Time (AOE to Read/Write) = 2 cycles		*/
+#define B2ST_3			0x00000030  /* B2 Setup Time (AOE to Read/Write) = 3 cycles		*/
+#define B2ST_4			0x00000000  /* B2 Setup Time (AOE to Read/Write) = 4 cycles		*/
+#define B2HT_1			0x00000040  /* B2 Hold Time (~Read/Write to ~AOE) = 1 cycle		*/
+#define B2HT_2			0x00000080  /* B2 Hold Time (~Read/Write to ~AOE) = 2 cycles	*/
+#define B2HT_3			0x000000C0  /* B2 Hold Time (~Read/Write to ~AOE) = 3 cycles	*/
+#define B2HT_0			0x00000000  /* B2 Hold Time (~Read/Write to ~AOE) = 0 cycles	*/
+#define B2RAT_1			0x00000100  /* B2 Read Access Time = 1 cycle					*/
+#define B2RAT_2			0x00000200  /* B2 Read Access Time = 2 cycles					*/
+#define B2RAT_3			0x00000300  /* B2 Read Access Time = 3 cycles					*/
+#define B2RAT_4			0x00000400  /* B2 Read Access Time = 4 cycles					*/
+#define B2RAT_5			0x00000500  /* B2 Read Access Time = 5 cycles					*/
+#define B2RAT_6			0x00000600  /* B2 Read Access Time = 6 cycles					*/
+#define B2RAT_7			0x00000700  /* B2 Read Access Time = 7 cycles					*/
+#define B2RAT_8			0x00000800  /* B2 Read Access Time = 8 cycles					*/
+#define B2RAT_9			0x00000900  /* B2 Read Access Time = 9 cycles					*/
+#define B2RAT_10		0x00000A00  /* B2 Read Access Time = 10 cycles					*/
+#define B2RAT_11		0x00000B00  /* B2 Read Access Time = 11 cycles					*/
+#define B2RAT_12		0x00000C00  /* B2 Read Access Time = 12 cycles					*/
+#define B2RAT_13		0x00000D00  /* B2 Read Access Time = 13 cycles					*/
+#define B2RAT_14		0x00000E00  /* B2 Read Access Time = 14 cycles					*/
+#define B2RAT_15		0x00000F00  /* B2 Read Access Time = 15 cycles					*/
+#define B2WAT_1			0x00001000  /* B2 Write Access Time = 1 cycle					*/
+#define B2WAT_2			0x00002000  /* B2 Write Access Time = 2 cycles					*/
+#define B2WAT_3			0x00003000  /* B2 Write Access Time = 3 cycles					*/
+#define B2WAT_4			0x00004000  /* B2 Write Access Time = 4 cycles					*/
+#define B2WAT_5			0x00005000  /* B2 Write Access Time = 5 cycles					*/
+#define B2WAT_6			0x00006000  /* B2 Write Access Time = 6 cycles					*/
+#define B2WAT_7			0x00007000  /* B2 Write Access Time = 7 cycles					*/
+#define B2WAT_8			0x00008000  /* B2 Write Access Time = 8 cycles					*/
+#define B2WAT_9			0x00009000  /* B2 Write Access Time = 9 cycles					*/
+#define B2WAT_10		0x0000A000  /* B2 Write Access Time = 10 cycles					*/
+#define B2WAT_11		0x0000B000  /* B2 Write Access Time = 11 cycles					*/
+#define B2WAT_12		0x0000C000  /* B2 Write Access Time = 12 cycles					*/
+#define B2WAT_13		0x0000D000  /* B2 Write Access Time = 13 cycles					*/
+#define B2WAT_14		0x0000E000  /* B2 Write Access Time = 14 cycles					*/
+#define B2WAT_15		0x0000F000  /* B2 Write Access Time = 15 cycles					*/
+
+#define B3RDYEN			0x00010000  /* Bank 3 (B3) RDY Enable							*/
+#define B3RDYPOL		0x00020000  /* B3 RDY Active High								*/
+#define B3TT_1			0x00040000  /* B3 Transition Time (Read to Write) = 1 cycle		*/
+#define B3TT_2			0x00080000  /* B3 Transition Time (Read to Write) = 2 cycles	*/
+#define B3TT_3			0x000C0000  /* B3 Transition Time (Read to Write) = 3 cycles	*/
+#define B3TT_4			0x00000000  /* B3 Transition Time (Read to Write) = 4 cycles	*/
+#define B3ST_1			0x00100000  /* B3 Setup Time (AOE to Read/Write) = 1 cycle		*/
+#define B3ST_2			0x00200000  /* B3 Setup Time (AOE to Read/Write) = 2 cycles		*/
+#define B3ST_3			0x00300000  /* B3 Setup Time (AOE to Read/Write) = 3 cycles		*/
+#define B3ST_4			0x00000000  /* B3 Setup Time (AOE to Read/Write) = 4 cycles		*/
+#define B3HT_1			0x00400000  /* B3 Hold Time (~Read/Write to ~AOE) = 1 cycle		*/
+#define B3HT_2			0x00800000  /* B3 Hold Time (~Read/Write to ~AOE) = 2 cycles	*/
+#define B3HT_3			0x00C00000  /* B3 Hold Time (~Read/Write to ~AOE) = 3 cycles	*/
+#define B3HT_0			0x00000000  /* B3 Hold Time (~Read/Write to ~AOE) = 0 cycles	*/
+#define B3RAT_1			0x01000000  /* B3 Read Access Time = 1 cycle					*/
+#define B3RAT_2			0x02000000  /* B3 Read Access Time = 2 cycles					*/
+#define B3RAT_3			0x03000000  /* B3 Read Access Time = 3 cycles					*/
+#define B3RAT_4			0x04000000  /* B3 Read Access Time = 4 cycles					*/
+#define B3RAT_5			0x05000000  /* B3 Read Access Time = 5 cycles					*/
+#define B3RAT_6			0x06000000  /* B3 Read Access Time = 6 cycles					*/
+#define B3RAT_7			0x07000000  /* B3 Read Access Time = 7 cycles					*/
+#define B3RAT_8			0x08000000  /* B3 Read Access Time = 8 cycles					*/
+#define B3RAT_9			0x09000000  /* B3 Read Access Time = 9 cycles					*/
+#define B3RAT_10		0x0A000000  /* B3 Read Access Time = 10 cycles					*/
+#define B3RAT_11		0x0B000000  /* B3 Read Access Time = 11 cycles					*/
+#define B3RAT_12		0x0C000000  /* B3 Read Access Time = 12 cycles					*/
+#define B3RAT_13		0x0D000000  /* B3 Read Access Time = 13 cycles					*/
+#define B3RAT_14		0x0E000000  /* B3 Read Access Time = 14 cycles					*/
+#define B3RAT_15		0x0F000000  /* B3 Read Access Time = 15 cycles					*/
+#define B3WAT_1			0x10000000  /* B3 Write Access Time = 1 cycle					*/
+#define B3WAT_2			0x20000000  /* B3 Write Access Time = 2 cycles					*/
+#define B3WAT_3			0x30000000  /* B3 Write Access Time = 3 cycles					*/
+#define B3WAT_4			0x40000000  /* B3 Write Access Time = 4 cycles					*/
+#define B3WAT_5			0x50000000  /* B3 Write Access Time = 5 cycles					*/
+#define B3WAT_6			0x60000000  /* B3 Write Access Time = 6 cycles					*/
+#define B3WAT_7			0x70000000  /* B3 Write Access Time = 7 cycles					*/
+#define B3WAT_8			0x80000000  /* B3 Write Access Time = 8 cycles					*/
+#define B3WAT_9			0x90000000  /* B3 Write Access Time = 9 cycles					*/
+#define B3WAT_10		0xA0000000  /* B3 Write Access Time = 10 cycles					*/
+#define B3WAT_11		0xB0000000  /* B3 Write Access Time = 11 cycles					*/
+#define B3WAT_12		0xC0000000  /* B3 Write Access Time = 12 cycles					*/
+#define B3WAT_13		0xD0000000  /* B3 Write Access Time = 13 cycles					*/
+#define B3WAT_14		0xE0000000  /* B3 Write Access Time = 14 cycles					*/
+#define B3WAT_15		0xF0000000  /* B3 Write Access Time = 15 cycles					*/
+
+
+/* **********************  SDRAM CONTROLLER MASKS  **********************************************/
+/* EBIU_SDGCTL Masks																			*/
+#define SCTLE			0x00000001	/* Enable SDRAM Signals										*/
+#define CL_2			0x00000008	/* SDRAM CAS Latency = 2 cycles								*/
+#define CL_3			0x0000000C	/* SDRAM CAS Latency = 3 cycles								*/
+#define PASR_ALL		0x00000000	/* All 4 SDRAM Banks Refreshed In Self-Refresh				*/
+#define PASR_B0_B1		0x00000010	/* SDRAM Banks 0 and 1 Are Refreshed In Self-Refresh		*/
+#define PASR_B0			0x00000020	/* Only SDRAM Bank 0 Is Refreshed In Self-Refresh			*/
+#define TRAS_1			0x00000040	/* SDRAM tRAS = 1 cycle										*/
+#define TRAS_2			0x00000080	/* SDRAM tRAS = 2 cycles									*/
+#define TRAS_3			0x000000C0	/* SDRAM tRAS = 3 cycles									*/
+#define TRAS_4			0x00000100	/* SDRAM tRAS = 4 cycles									*/
+#define TRAS_5			0x00000140	/* SDRAM tRAS = 5 cycles									*/
+#define TRAS_6			0x00000180	/* SDRAM tRAS = 6 cycles									*/
+#define TRAS_7			0x000001C0	/* SDRAM tRAS = 7 cycles									*/
+#define TRAS_8			0x00000200	/* SDRAM tRAS = 8 cycles									*/
+#define TRAS_9			0x00000240	/* SDRAM tRAS = 9 cycles									*/
+#define TRAS_10			0x00000280	/* SDRAM tRAS = 10 cycles									*/
+#define TRAS_11			0x000002C0	/* SDRAM tRAS = 11 cycles									*/
+#define TRAS_12			0x00000300	/* SDRAM tRAS = 12 cycles									*/
+#define TRAS_13			0x00000340	/* SDRAM tRAS = 13 cycles									*/
+#define TRAS_14			0x00000380	/* SDRAM tRAS = 14 cycles									*/
+#define TRAS_15			0x000003C0	/* SDRAM tRAS = 15 cycles									*/
+#define TRP_1			0x00000800	/* SDRAM tRP = 1 cycle										*/
+#define TRP_2			0x00001000	/* SDRAM tRP = 2 cycles										*/
+#define TRP_3			0x00001800	/* SDRAM tRP = 3 cycles										*/
+#define TRP_4			0x00002000	/* SDRAM tRP = 4 cycles										*/
+#define TRP_5			0x00002800	/* SDRAM tRP = 5 cycles										*/
+#define TRP_6			0x00003000	/* SDRAM tRP = 6 cycles										*/
+#define TRP_7			0x00003800	/* SDRAM tRP = 7 cycles										*/
+#define TRCD_1			0x00008000	/* SDRAM tRCD = 1 cycle										*/
+#define TRCD_2			0x00010000	/* SDRAM tRCD = 2 cycles									*/
+#define TRCD_3			0x00018000	/* SDRAM tRCD = 3 cycles									*/
+#define TRCD_4			0x00020000	/* SDRAM tRCD = 4 cycles									*/
+#define TRCD_5			0x00028000	/* SDRAM tRCD = 5 cycles									*/
+#define TRCD_6			0x00030000	/* SDRAM tRCD = 6 cycles									*/
+#define TRCD_7			0x00038000	/* SDRAM tRCD = 7 cycles									*/
+#define TWR_1			0x00080000	/* SDRAM tWR = 1 cycle										*/
+#define TWR_2			0x00100000	/* SDRAM tWR = 2 cycles										*/
+#define TWR_3			0x00180000	/* SDRAM tWR = 3 cycles										*/
+#define PUPSD			0x00200000	/* Power-Up Start Delay (15 SCLK Cycles Delay)				*/
+#define PSM				0x00400000	/* Power-Up Sequence (Mode Register Before/After* Refresh)	*/
+#define PSS				0x00800000	/* Enable Power-Up Sequence on Next SDRAM Access			*/
+#define SRFS			0x01000000	/* Enable SDRAM Self-Refresh Mode							*/
+#define EBUFE			0x02000000	/* Enable External Buffering Timing							*/
+#define FBBRW			0x04000000	/* Enable Fast Back-To-Back Read To Write					*/
+#define EMREN			0x10000000	/* Extended Mode Register Enable							*/
+#define TCSR			0x20000000	/* Temp-Compensated Self-Refresh Value (85/45* Deg C)		*/
+#define CDDBG			0x40000000	/* Tristate SDRAM Controls During Bus Grant					*/
+
+/* EBIU_SDBCTL Masks																		*/
+#define EBE				0x0001		/* Enable SDRAM External Bank							*/
+#define EBSZ_16			0x0000		/* SDRAM External Bank Size = 16MB	*/
+#define EBSZ_32			0x0002		/* SDRAM External Bank Size = 32MB	*/
+#define EBSZ_64			0x0004		/* SDRAM External Bank Size = 64MB	*/
+#define EBSZ_128		0x0006		/* SDRAM External Bank Size = 128MB		*/
+#define EBSZ_256		0x0008		/* SDRAM External Bank Size = 256MB 	*/
+#define EBSZ_512		0x000A		/* SDRAM External Bank Size = 512MB		*/
+#define EBCAW_8			0x0000		/* SDRAM External Bank Column Address Width = 8 Bits	*/
+#define EBCAW_9			0x0010		/* SDRAM External Bank Column Address Width = 9 Bits	*/
+#define EBCAW_10		0x0020		/* SDRAM External Bank Column Address Width = 10 Bits	*/
+#define EBCAW_11		0x0030		/* SDRAM External Bank Column Address Width = 11 Bits	*/
+
+/* EBIU_SDSTAT Masks														*/
+#define SDCI			0x0001		/* SDRAM Controller Idle 				*/
+#define SDSRA			0x0002		/* SDRAM Self-Refresh Active			*/
+#define SDPUA			0x0004		/* SDRAM Power-Up Active 				*/
+#define SDRS			0x0008		/* SDRAM Will Power-Up On Next Access	*/
+#define SDEASE			0x0010		/* SDRAM EAB Sticky Error Status		*/
+#define BGSTAT			0x0020		/* Bus Grant Status						*/
+
+
+/* **************************  DMA CONTROLLER MASKS  ********************************/
+
+/* DMAx_PERIPHERAL_MAP, MDMA_yy_PERIPHERAL_MAP Masks								*/
+#define CTYPE			0x0040	/* DMA Channel Type Indicator (Memory/Peripheral*)	*/
+#define PMAP			0xF000	/* Peripheral Mapped To This Channel				*/
+#define PMAP_PPI		0x0000	/* 		PPI Port DMA								*/
+#define	PMAP_EMACRX		0x1000	/* 		Ethernet Receive DMA						*/
+#define PMAP_EMACTX		0x2000	/* 		Ethernet Transmit DMA						*/
+#define PMAP_SPORT0RX	0x3000	/* 		SPORT0 Receive DMA							*/
+#define PMAP_SPORT0TX	0x4000	/* 		SPORT0 Transmit DMA							*/
+#define PMAP_SPORT1RX	0x5000	/* 		SPORT1 Receive DMA							*/
+#define PMAP_SPORT1TX	0x6000	/* 		SPORT1 Transmit DMA							*/
+#define PMAP_SPI		0x7000	/* 		SPI Port DMA								*/
+#define PMAP_UART0RX	0x8000	/* 		UART0 Port Receive DMA						*/
+#define PMAP_UART0TX	0x9000	/* 		UART0 Port Transmit DMA						*/
+#define	PMAP_UART1RX	0xA000	/* 		UART1 Port Receive DMA						*/
+#define	PMAP_UART1TX	0xB000	/* 		UART1 Port Transmit DMA						*/
+
+/*  ************  PARALLEL PERIPHERAL INTERFACE (PPI) MASKS *************/
+/*  PPI_CONTROL Masks													*/
+#define PORT_EN			0x0001		/* PPI Port Enable					*/
+#define PORT_DIR		0x0002		/* PPI Port Direction				*/
+#define XFR_TYPE		0x000C		/* PPI Transfer Type				*/
+#define PORT_CFG		0x0030		/* PPI Port Configuration			*/
+#define FLD_SEL			0x0040		/* PPI Active Field Select			*/
+#define PACK_EN			0x0080		/* PPI Packing Mode					*/
+#define DMA32			0x0100		/* PPI 32-bit DMA Enable			*/
+#define SKIP_EN			0x0200		/* PPI Skip Element Enable			*/
+#define SKIP_EO			0x0400		/* PPI Skip Even/Odd Elements		*/
+#define DLEN_8			0x0000		/* Data Length = 8 Bits				*/
+#define DLEN_10			0x0800		/* Data Length = 10 Bits			*/
+#define DLEN_11			0x1000		/* Data Length = 11 Bits			*/
+#define DLEN_12			0x1800		/* Data Length = 12 Bits			*/
+#define DLEN_13			0x2000		/* Data Length = 13 Bits			*/
+#define DLEN_14			0x2800		/* Data Length = 14 Bits			*/
+#define DLEN_15			0x3000		/* Data Length = 15 Bits			*/
+#define DLEN_16			0x3800		/* Data Length = 16 Bits			*/
+#define DLENGTH			0x3800		/* PPI Data Length  */
+#define POLC			0x4000		/* PPI Clock Polarity				*/
+#define POLS			0x8000		/* PPI Frame Sync Polarity			*/
+
+/* PPI_STATUS Masks														*/
+#define FLD				0x0400		/* Field Indicator					*/
+#define FT_ERR			0x0800		/* Frame Track Error				*/
+#define OVR				0x1000		/* FIFO Overflow Error				*/
+#define UNDR			0x2000		/* FIFO Underrun Error				*/
+#define ERR_DET			0x4000		/* Error Detected Indicator			*/
+#define ERR_NCOR		0x8000		/* Error Not Corrected Indicator	*/
+
+
+/*  ********************  TWO-WIRE INTERFACE (TWI) MASKS  ***********************/
+/* TWI_CLKDIV Macros (Use: *pTWI_CLKDIV = CLKLOW(x)|CLKHI(y);  )				*/
+#define	CLKLOW(x)	((x) & 0xFF)		/* Periods Clock Is Held Low			*/
+#define CLKHI(y)	(((y)&0xFF)<<0x8)	/* Periods Before New Clock Low			*/
+
+/* TWI_PRESCALE Masks															*/
+#define	PRESCALE	0x007F		/* SCLKs Per Internal Time Reference (10MHz)	*/
+#define	TWI_ENA		0x0080		/* TWI Enable									*/
+#define	SCCB		0x0200		/* SCCB Compatibility Enable					*/
+
+/* TWI_SLAVE_CTL Masks															*/
+#define	SEN			0x0001		/* Slave Enable									*/
+#define	SADD_LEN	0x0002		/* Slave Address Length							*/
+#define	STDVAL		0x0004		/* Slave Transmit Data Valid					*/
+#define	NAK			0x0008		/* NAK/ACK* Generated At Conclusion Of Transfer */
+#define	GEN			0x0010		/* General Call Adrress Matching Enabled		*/
+
+/* TWI_SLAVE_STAT Masks															*/
+#define	SDIR		0x0001		/* Slave Transfer Direction (Transmit/Receive*)	*/
+#define GCALL		0x0002		/* General Call Indicator						*/
+
+/* TWI_MASTER_CTL Masks													*/
+#define	MEN			0x0001		/* Master Mode Enable						*/
+#define	MADD_LEN	0x0002		/* Master Address Length					*/
+#define	MDIR		0x0004		/* Master Transmit Direction (RX/TX*)		*/
+#define	FAST		0x0008		/* Use Fast Mode Timing Specs				*/
+#define	STOP		0x0010		/* Issue Stop Condition						*/
+#define	RSTART		0x0020		/* Repeat Start or Stop* At End Of Transfer	*/
+#define	DCNT		0x3FC0		/* Data Bytes To Transfer					*/
+#define	SDAOVR		0x4000		/* Serial Data Override						*/
+#define	SCLOVR		0x8000		/* Serial Clock Override					*/
+
+/* TWI_MASTER_STAT Masks														*/
+#define	MPROG		0x0001		/* Master Transfer In Progress					*/
+#define	LOSTARB		0x0002		/* Lost Arbitration Indicator (Xfer Aborted)	*/
+#define	ANAK		0x0004		/* Address Not Acknowledged						*/
+#define	DNAK		0x0008		/* Data Not Acknowledged						*/
+#define	BUFRDERR	0x0010		/* Buffer Read Error							*/
+#define	BUFWRERR	0x0020		/* Buffer Write Error							*/
+#define	SDASEN		0x0040		/* Serial Data Sense							*/
+#define	SCLSEN		0x0080		/* Serial Clock Sense							*/
+#define	BUSBUSY		0x0100		/* Bus Busy Indicator							*/
+
+/* TWI_INT_SRC and TWI_INT_ENABLE Masks						*/
+#define	SINIT		0x0001		/* Slave Transfer Initiated	*/
+#define	SCOMP		0x0002		/* Slave Transfer Complete	*/
+#define	SERR		0x0004		/* Slave Transfer Error		*/
+#define	SOVF		0x0008		/* Slave Overflow			*/
+#define	MCOMP		0x0010		/* Master Transfer Complete	*/
+#define	MERR		0x0020		/* Master Transfer Error	*/
+#define	XMTSERV		0x0040		/* Transmit FIFO Service	*/
+#define	RCVSERV		0x0080		/* Receive FIFO Service		*/
+
+/* TWI_FIFO_CTRL Masks												*/
+#define	XMTFLUSH	0x0001		/* Transmit Buffer Flush			*/
+#define	RCVFLUSH	0x0002		/* Receive Buffer Flush				*/
+#define	XMTINTLEN	0x0004		/* Transmit Buffer Interrupt Length	*/
+#define	RCVINTLEN	0x0008		/* Receive Buffer Interrupt Length	*/
+
+/* TWI_FIFO_STAT Masks															*/
+#define	XMTSTAT		0x0003		/* Transmit FIFO Status							*/
+#define	XMT_EMPTY	0x0000		/* 		Transmit FIFO Empty						*/
+#define	XMT_HALF	0x0001		/* 		Transmit FIFO Has 1 Byte To Write		*/
+#define	XMT_FULL	0x0003		/* 		Transmit FIFO Full (2 Bytes To Write)	*/
+
+#define	RCVSTAT		0x000C		/* Receive FIFO Status							*/
+#define	RCV_EMPTY	0x0000		/* 		Receive FIFO Empty						*/
+#define	RCV_HALF	0x0004		/* 		Receive FIFO Has 1 Byte To Read			*/
+#define	RCV_FULL	0x000C		/* 		Receive FIFO Full (2 Bytes To Read)		*/
+
+
+/*  *******************  PIN CONTROL REGISTER MASKS  ************************/
+/* PORT_MUX Masks															*/
+#define	PJSE			0x0001			/* Port J SPI/SPORT Enable			*/
+#define	PJSE_SPORT		0x0000			/* 		Enable TFS0/DT0PRI			*/
+#define	PJSE_SPI		0x0001			/* 		Enable SPI_SSEL3:2			*/
+
+#define	PJCE(x)			(((x)&0x3)<<1)	/* Port J CAN/SPI/SPORT Enable		*/
+#define	PJCE_SPORT		0x0000			/* 		Enable DR0SEC/DT0SEC		*/
+#define	PJCE_CAN		0x0002			/* 		Enable CAN RX/TX			*/
+#define	PJCE_SPI		0x0004			/* 		Enable SPI_SSEL7			*/
+
+#define	PFDE			0x0008			/* Port F DMA Request Enable		*/
+#define	PFDE_UART		0x0000			/* 		Enable UART0 RX/TX			*/
+#define	PFDE_DMA		0x0008			/* 		Enable DMAR1:0				*/
+
+#define	PFTE			0x0010			/* Port F Timer Enable				*/
+#define	PFTE_UART		0x0000			/*		Enable UART1 RX/TX			*/
+#define	PFTE_TIMER		0x0010			/* 		Enable TMR7:6				*/
+
+#define	PFS6E			0x0020			/* Port F SPI SSEL 6 Enable			*/
+#define	PFS6E_TIMER		0x0000			/*		Enable TMR5					*/
+#define	PFS6E_SPI		0x0020			/* 		Enable SPI_SSEL6			*/
+
+#define	PFS5E			0x0040			/* Port F SPI SSEL 5 Enable			*/
+#define	PFS5E_TIMER		0x0000			/*		Enable TMR4					*/
+#define	PFS5E_SPI		0x0040			/* 		Enable SPI_SSEL5			*/
+
+#define	PFS4E			0x0080			/* Port F SPI SSEL 4 Enable			*/
+#define	PFS4E_TIMER		0x0000			/*		Enable TMR3					*/
+#define	PFS4E_SPI		0x0080			/* 		Enable SPI_SSEL4			*/
+
+#define	PFFE			0x0100			/* Port F PPI Frame Sync Enable		*/
+#define	PFFE_TIMER		0x0000			/* 		Enable TMR2					*/
+#define	PFFE_PPI		0x0100			/* 		Enable PPI FS3				*/
+
+#define	PGSE			0x0200			/* Port G SPORT1 Secondary Enable	*/
+#define	PGSE_PPI		0x0000			/* 		Enable PPI D9:8				*/
+#define	PGSE_SPORT		0x0200			/* 		Enable DR1SEC/DT1SEC		*/
+
+#define	PGRE			0x0400			/* Port G SPORT1 Receive Enable		*/
+#define	PGRE_PPI		0x0000			/* 		Enable PPI D12:10			*/
+#define	PGRE_SPORT		0x0400			/* 		Enable DR1PRI/RFS1/RSCLK1	*/
+
+#define	PGTE			0x0800			/* Port G SPORT1 Transmit Enable	*/
+#define	PGTE_PPI		0x0000			/* 		Enable PPI D15:13			*/
+#define	PGTE_SPORT		0x0800			/* 		Enable DT1PRI/TFS1/TSCLK1	*/
+
+
+/*  ******************  HANDSHAKE DMA (HDMA) MASKS  *********************/
+/* HDMAx_CTL Masks														*/
+#define	HMDMAEN		0x0001	/* Enable Handshake DMA 0/1					*/
+#define	REP			0x0002	/* HDMA Request Polarity					*/
+#define	UTE			0x0004	/* Urgency Threshold Enable					*/
+#define	OIE			0x0010	/* Overflow Interrupt Enable				*/
+#define	BDIE		0x0020	/* Block Done Interrupt Enable				*/
+#define	MBDI		0x0040	/* Mask Block Done IRQ If Pending ECNT		*/
+#define	DRQ			0x0300	/* HDMA Request Type						*/
+#define	DRQ_NONE	0x0000	/* 		No Request							*/
+#define	DRQ_SINGLE	0x0100	/* 		Channels Request Single				*/
+#define	DRQ_MULTI	0x0200	/* 		Channels Request Multi (Default)	*/
+#define	DRQ_URGENT	0x0300	/* 		Channels Request Multi Urgent		*/
+#define	RBC			0x1000	/* Reload BCNT With IBCNT					*/
+#define	PS			0x2000	/* HDMA Pin Status							*/
+#define	OI			0x4000	/* Overflow Interrupt Generated				*/
+#define	BDI			0x8000	/* Block Done Interrupt Generated			*/
+
+/* entry addresses of the user-callable Boot ROM functions */
+
+#define _BOOTROM_RESET 0xEF000000
+#define _BOOTROM_FINAL_INIT 0xEF000002
+#define _BOOTROM_DO_MEMORY_DMA 0xEF000006
+#define _BOOTROM_BOOT_DXE_FLASH 0xEF000008
+#define _BOOTROM_BOOT_DXE_SPI 0xEF00000A
+#define _BOOTROM_BOOT_DXE_TWI 0xEF00000C
+#define _BOOTROM_GET_DXE_ADDRESS_FLASH 0xEF000010
+#define _BOOTROM_GET_DXE_ADDRESS_SPI 0xEF000012
+#define _BOOTROM_GET_DXE_ADDRESS_TWI 0xEF000014
+
+/* Alternate Deprecated Macros Provided For Backwards Code Compatibility */
+#define	PGDE_UART   PFDE_UART
+#define	PGDE_DMA    PFDE_DMA
+#define	CKELOW		SCKELOW
+
+/* HOST Port Registers */
+
+#define                     HOST_CONTROL  0xffc03400   /* HOST Control Register */
+#define                      HOST_STATUS  0xffc03404   /* HOST Status Register */
+#define                     HOST_TIMEOUT  0xffc03408   /* HOST Acknowledge Mode Timeout Register */
+
+/* Counter Registers */
+
+#define                       CNT_CONFIG  0xffc03500   /* Configuration Register */
+#define                        CNT_IMASK  0xffc03504   /* Interrupt Mask Register */
+#define                       CNT_STATUS  0xffc03508   /* Status Register */
+#define                      CNT_COMMAND  0xffc0350c   /* Command Register */
+#define                     CNT_DEBOUNCE  0xffc03510   /* Debounce Register */
+#define                      CNT_COUNTER  0xffc03514   /* Counter Register */
+#define                          CNT_MAX  0xffc03518   /* Maximal Count Register */
+#define                          CNT_MIN  0xffc0351c   /* Minimal Count Register */
+
+/* OTP/FUSE Registers */
+
+#define                      OTP_CONTROL  0xffc03600   /* OTP/Fuse Control Register */
+#define                          OTP_BEN  0xffc03604   /* OTP/Fuse Byte Enable */
+#define                       OTP_STATUS  0xffc03608   /* OTP/Fuse Status */
+#define                       OTP_TIMING  0xffc0360c   /* OTP/Fuse Access Timing */
+
+/* Security Registers */
+
+#define                    SECURE_SYSSWT  0xffc03620   /* Secure System Switches */
+#define                   SECURE_CONTROL  0xffc03624   /* Secure Control */
+#define                    SECURE_STATUS  0xffc03628   /* Secure Status */
+
+/* OTP Read/Write Data Buffer Registers */
+
+#define                        OTP_DATA0  0xffc03680   /* OTP/Fuse Data (OTP_DATA0-3) accesses the fuse read write buffer */
+#define                        OTP_DATA1  0xffc03684   /* OTP/Fuse Data (OTP_DATA0-3) accesses the fuse read write buffer */
+#define                        OTP_DATA2  0xffc03688   /* OTP/Fuse Data (OTP_DATA0-3) accesses the fuse read write buffer */
+#define                        OTP_DATA3  0xffc0368c   /* OTP/Fuse Data (OTP_DATA0-3) accesses the fuse read write buffer */
+
+/* Motor Control PWM Registers */
+
+#define                         PWM_CTRL  0xffc03700   /* PWM Control Register */
+#define                         PWM_STAT  0xffc03704   /* PWM Status Register */
+#define                           PWM_TM  0xffc03708   /* PWM Period Register */
+#define                           PWM_DT  0xffc0370c   /* PWM Dead Time Register */
+#define                         PWM_GATE  0xffc03710   /* PWM Chopping Control */
+#define                          PWM_CHA  0xffc03714   /* PWM Channel A Duty Control */
+#define                          PWM_CHB  0xffc03718   /* PWM Channel B Duty Control */
+#define                          PWM_CHC  0xffc0371c   /* PWM Channel C Duty Control */
+#define                          PWM_SEG  0xffc03720   /* PWM Crossover and Output Enable */
+#define                       PWM_SYNCWT  0xffc03724   /* PWM Sync Pluse Width Control */
+#define                         PWM_CHAL  0xffc03728   /* PWM Channel AL Duty Control (SR mode only) */
+#define                         PWM_CHBL  0xffc0372c   /* PWM Channel BL Duty Control (SR mode only) */
+#define                         PWM_CHCL  0xffc03730   /* PWM Channel CL Duty Control (SR mode only) */
+#define                          PWM_LSI  0xffc03734   /* PWM Low Side Invert (SR mode only) */
+#define                        PWM_STAT2  0xffc03738   /* PWM Status Register 2 */
+
+
+/* ********************************************************** */
+/*     SINGLE BIT MACRO PAIRS (bit mask and negated one)      */
+/*     and MULTI BIT READ MACROS                              */
+/* ********************************************************** */
+
+/* Bit masks for HOST_CONTROL */
+
+#define                   HOST_CNTR_HOST_EN  0x1        /* Host Enable */
+#define                  HOST_CNTR_nHOST_EN  0x0
+#define                  HOST_CNTR_HOST_END  0x2        /* Host Endianess */
+#define                 HOST_CNTR_nHOST_END  0x0
+#define                 HOST_CNTR_DATA_SIZE  0x4        /* Data Size */
+#define                HOST_CNTR_nDATA_SIZE  0x0
+#define                  HOST_CNTR_HOST_RST  0x8        /* Host Reset */
+#define                 HOST_CNTR_nHOST_RST  0x0
+#define                  HOST_CNTR_HRDY_OVR  0x20       /* Host Ready Override */
+#define                 HOST_CNTR_nHRDY_OVR  0x0
+#define                  HOST_CNTR_INT_MODE  0x40       /* Interrupt Mode */
+#define                 HOST_CNTR_nINT_MODE  0x0
+#define                     HOST_CNTR_BT_EN  0x80       /* Bus Timeout Enable */
+#define                   HOST_CNTR_ nBT_EN  0x0
+#define                       HOST_CNTR_EHW  0x100      /* Enable Host Write */
+#define                      HOST_CNTR_nEHW  0x0
+#define                       HOST_CNTR_EHR  0x200      /* Enable Host Read */
+#define                      HOST_CNTR_nEHR  0x0
+#define                       HOST_CNTR_BDR  0x400      /* Burst DMA Requests */
+#define                      HOST_CNTR_nBDR  0x0
+
+/* Bit masks for HOST_STATUS */
+
+#define                     HOST_STAT_READY  0x1        /* DMA Ready */
+#define                    HOST_STAT_nREADY  0x0
+#define                  HOST_STAT_FIFOFULL  0x2        /* FIFO Full */
+#define                 HOST_STAT_nFIFOFULL  0x0
+#define                 HOST_STAT_FIFOEMPTY  0x4        /* FIFO Empty */
+#define                HOST_STAT_nFIFOEMPTY  0x0
+#define                  HOST_STAT_COMPLETE  0x8        /* DMA Complete */
+#define                 HOST_STAT_nCOMPLETE  0x0
+#define                      HOST_STAT_HSHK  0x10       /* Host Handshake */
+#define                     HOST_STAT_nHSHK  0x0
+#define                   HOST_STAT_TIMEOUT  0x20       /* Host Timeout */
+#define                  HOST_STAT_nTIMEOUT  0x0
+#define                      HOST_STAT_HIRQ  0x40       /* Host Interrupt Request */
+#define                     HOST_STAT_nHIRQ  0x0
+#define                HOST_STAT_ALLOW_CNFG  0x80       /* Allow New Configuration */
+#define               HOST_STAT_nALLOW_CNFG  0x0
+#define                   HOST_STAT_DMA_DIR  0x100      /* DMA Direction */
+#define                  HOST_STAT_nDMA_DIR  0x0
+#define                       HOST_STAT_BTE  0x200      /* Bus Timeout Enabled */
+#define                      HOST_STAT_nBTE  0x0
+#define               HOST_STAT_HOSTRD_DONE  0x8000     /* Host Read Completion Interrupt */
+#define              HOST_STAT_nHOSTRD_DONE  0x0
+
+/* Bit masks for HOST_TIMEOUT */
+
+#define             HOST_COUNT_TIMEOUT  0x7ff      /* Host Timeout count */
+
+/* Bit masks for SECURE_SYSSWT */
+
+#define                   EMUDABL  0x1        /* Emulation Disable. */
+#define                  nEMUDABL  0x0
+#define                   RSTDABL  0x2        /* Reset Disable */
+#define                  nRSTDABL  0x0
+#define                   L1IDABL  0x1c       /* L1 Instruction Memory Disable. */
+#define                  L1DADABL  0xe0       /* L1 Data Bank A Memory Disable. */
+#define                  L1DBDABL  0x700      /* L1 Data Bank B Memory Disable. */
+#define                   DMA0OVR  0x800      /* DMA0 Memory Access Override */
+#define                  nDMA0OVR  0x0
+#define                   DMA1OVR  0x1000     /* DMA1 Memory Access Override */
+#define                  nDMA1OVR  0x0
+#define                    EMUOVR  0x4000     /* Emulation Override */
+#define                   nEMUOVR  0x0
+#define                    OTPSEN  0x8000     /* OTP Secrets Enable. */
+#define                   nOTPSEN  0x0
+#define                    L2DABL  0x70000    /* L2 Memory Disable. */
+
+/* Bit masks for SECURE_CONTROL */
+
+#define                   SECURE0  0x1        /* SECURE 0 */
+#define                  nSECURE0  0x0
+#define                   SECURE1  0x2        /* SECURE 1 */
+#define                  nSECURE1  0x0
+#define                   SECURE2  0x4        /* SECURE 2 */
+#define                  nSECURE2  0x0
+#define                   SECURE3  0x8        /* SECURE 3 */
+#define                  nSECURE3  0x0
+
+/* Bit masks for SECURE_STATUS */
+
+#define                   SECMODE  0x3        /* Secured Mode Control State */
+#define                       NMI  0x4        /* Non Maskable Interrupt */
+#define                      nNMI  0x0
+#define                   AFVALID  0x8        /* Authentication Firmware Valid */
+#define                  nAFVALID  0x0
+#define                    AFEXIT  0x10       /* Authentication Firmware Exit */
+#define                   nAFEXIT  0x0
+#define                   SECSTAT  0xe0       /* Secure Status */
 
 #endif /* _DEF_BF512_H */
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf518/include/mach/defBF51x_base.h linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf518/include/mach/defBF51x_base.h
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf518/include/mach/defBF51x_base.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf518/include/mach/defBF51x_base.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,1495 +0,0 @@
-/*
- * Copyright 2008 Analog Devices Inc.
- *
- * Licensed under the ADI BSD license or the GPL-2 (or later)
- */
-
-#ifndef _DEF_BF51X_H
-#define _DEF_BF51X_H
-
-
-/* ************************************************************** */
-/*   SYSTEM & MMR ADDRESS DEFINITIONS COMMON TO ALL ADSP-BF51x    */
-/* ************************************************************** */
-
-/* Clock and System Control	(0xFFC00000 - 0xFFC000FF)								*/
-#define PLL_CTL				0xFFC00000	/* PLL Control Register						*/
-#define PLL_DIV				0xFFC00004	/* PLL Divide Register						*/
-#define VR_CTL				0xFFC00008	/* Voltage Regulator Control Register				*/
-#define PLL_STAT			0xFFC0000C	/* PLL Status Register						*/
-#define PLL_LOCKCNT			0xFFC00010	/* PLL Lock Count Register					*/
-#define CHIPID				0xFFC00014	/* Device ID Register */
-
-/* System Interrupt Controller (0xFFC00100 - 0xFFC001FF)								*/
-#define SWRST				0xFFC00100	/* Software Reset Register					*/
-#define SYSCR				0xFFC00104	/* System Configuration Register				*/
-#define SIC_RVECT			0xFFC00108	/* Interrupt Reset Vector Address Register			*/
-
-#define SIC_IMASK0			0xFFC0010C	/* Interrupt Mask Register					*/
-#define SIC_IAR0			0xFFC00110	/* Interrupt Assignment Register 0				*/
-#define SIC_IAR1			0xFFC00114	/* Interrupt Assignment Register 1				*/
-#define SIC_IAR2			0xFFC00118	/* Interrupt Assignment Register 2				*/
-#define SIC_IAR3			0xFFC0011C	/* Interrupt Assignment Register 3				*/
-#define SIC_ISR0			0xFFC00120	/* Interrupt Status Register					*/
-#define SIC_IWR0			0xFFC00124	/* Interrupt Wakeup Register					*/
-
-/* SIC Additions to ADSP-BF51x (0xFFC0014C - 0xFFC00162) */
-#define SIC_IMASK1                      0xFFC0014C     /* Interrupt Mask register of SIC2 */
-#define SIC_IAR4                        0xFFC00150     /* Interrupt Assignment register4 */
-#define SIC_IAR5                        0xFFC00154     /* Interrupt Assignment register5 */
-#define SIC_IAR6                        0xFFC00158     /* Interrupt Assignment register6 */
-#define SIC_IAR7                        0xFFC0015C     /* Interrupt Assignment register7 */
-#define SIC_ISR1                        0xFFC00160     /* Interrupt Statur register */
-#define SIC_IWR1                        0xFFC00164     /* Interrupt Wakeup register */
-
-
-/* Watchdog Timer			(0xFFC00200 - 0xFFC002FF)								*/
-#define WDOG_CTL			0xFFC00200	/* Watchdog Control Register				*/
-#define WDOG_CNT			0xFFC00204	/* Watchdog Count Register					*/
-#define WDOG_STAT			0xFFC00208	/* Watchdog Status Register					*/
-
-
-/* Real Time Clock		(0xFFC00300 - 0xFFC003FF)									*/
-#define RTC_STAT			0xFFC00300	/* RTC Status Register						*/
-#define RTC_ICTL			0xFFC00304	/* RTC Interrupt Control Register			*/
-#define RTC_ISTAT			0xFFC00308	/* RTC Interrupt Status Register			*/
-#define RTC_SWCNT			0xFFC0030C	/* RTC Stopwatch Count Register				*/
-#define RTC_ALARM			0xFFC00310	/* RTC Alarm Time Register					*/
-#define RTC_FAST			0xFFC00314	/* RTC Prescaler Enable Register			*/
-#define RTC_PREN			0xFFC00314	/* RTC Prescaler Enable Alternate Macro		*/
-
-
-/* UART0 Controller		(0xFFC00400 - 0xFFC004FF)									*/
-#define UART0_THR			0xFFC00400	/* Transmit Holding register				*/
-#define UART0_RBR			0xFFC00400	/* Receive Buffer register					*/
-#define UART0_DLL			0xFFC00400	/* Divisor Latch (Low-Byte)					*/
-#define UART0_IER			0xFFC00404	/* Interrupt Enable Register				*/
-#define UART0_DLH			0xFFC00404	/* Divisor Latch (High-Byte)				*/
-#define UART0_IIR			0xFFC00408	/* Interrupt Identification Register		*/
-#define UART0_LCR			0xFFC0040C	/* Line Control Register					*/
-#define UART0_MCR			0xFFC00410	/* Modem Control Register					*/
-#define UART0_LSR			0xFFC00414	/* Line Status Register						*/
-#define UART0_MSR			0xFFC00418	/* Modem Status Register					*/
-#define UART0_SCR			0xFFC0041C	/* SCR Scratch Register						*/
-#define UART0_GCTL			0xFFC00424	/* Global Control Register					*/
-
-/* SPI0 Controller			(0xFFC00500 - 0xFFC005FF)							*/
-#define SPI0_REGBASE			0xFFC00500
-#define SPI0_CTL			0xFFC00500	/* SPI Control Register						*/
-#define SPI0_FLG			0xFFC00504	/* SPI Flag register						*/
-#define SPI0_STAT			0xFFC00508	/* SPI Status register						*/
-#define SPI0_TDBR			0xFFC0050C	/* SPI Transmit Data Buffer Register				*/
-#define SPI0_RDBR			0xFFC00510	/* SPI Receive Data Buffer Register				*/
-#define SPI0_BAUD			0xFFC00514	/* SPI Baud rate Register					*/
-#define SPI0_SHADOW			0xFFC00518	/* SPI_RDBR Shadow Register					*/
-
-/* SPI1 Controller			(0xFFC03400 - 0xFFC034FF)							*/
-#define SPI1_REGBASE			0xFFC03400
-#define SPI1_CTL			0xFFC03400	/* SPI Control Register						*/
-#define SPI1_FLG			0xFFC03404	/* SPI Flag register						*/
-#define SPI1_STAT			0xFFC03408	/* SPI Status register						*/
-#define SPI1_TDBR			0xFFC0340C	/* SPI Transmit Data Buffer Register				*/
-#define SPI1_RDBR			0xFFC03410	/* SPI Receive Data Buffer Register				*/
-#define SPI1_BAUD			0xFFC03414	/* SPI Baud rate Register					*/
-#define SPI1_SHADOW			0xFFC03418	/* SPI_RDBR Shadow Register					*/
-
-/* TIMER0-7 Registers		(0xFFC00600 - 0xFFC006FF)								*/
-#define TIMER0_CONFIG		0xFFC00600	/* Timer 0 Configuration Register			*/
-#define TIMER0_COUNTER		0xFFC00604	/* Timer 0 Counter Register					*/
-#define TIMER0_PERIOD		0xFFC00608	/* Timer 0 Period Register					*/
-#define TIMER0_WIDTH		0xFFC0060C	/* Timer 0 Width Register					*/
-
-#define TIMER1_CONFIG		0xFFC00610	/* Timer 1 Configuration Register  			*/
-#define TIMER1_COUNTER		0xFFC00614	/* Timer 1 Counter Register        			*/
-#define TIMER1_PERIOD		0xFFC00618	/* Timer 1 Period Register         			*/
-#define TIMER1_WIDTH		0xFFC0061C	/* Timer 1 Width Register          			*/
-
-#define TIMER2_CONFIG		0xFFC00620	/* Timer 2 Configuration Register  			*/
-#define TIMER2_COUNTER		0xFFC00624	/* Timer 2 Counter Register        			*/
-#define TIMER2_PERIOD		0xFFC00628	/* Timer 2 Period Register         			*/
-#define TIMER2_WIDTH		0xFFC0062C	/* Timer 2 Width Register          			*/
-
-#define TIMER3_CONFIG		0xFFC00630	/* Timer 3 Configuration Register			*/
-#define TIMER3_COUNTER		0xFFC00634	/* Timer 3 Counter Register					*/
-#define TIMER3_PERIOD		0xFFC00638	/* Timer 3 Period Register					*/
-#define TIMER3_WIDTH		0xFFC0063C	/* Timer 3 Width Register					*/
-
-#define TIMER4_CONFIG		0xFFC00640	/* Timer 4 Configuration Register  			*/
-#define TIMER4_COUNTER		0xFFC00644	/* Timer 4 Counter Register        			*/
-#define TIMER4_PERIOD		0xFFC00648	/* Timer 4 Period Register         			*/
-#define TIMER4_WIDTH		0xFFC0064C	/* Timer 4 Width Register          			*/
-
-#define TIMER5_CONFIG		0xFFC00650	/* Timer 5 Configuration Register  			*/
-#define TIMER5_COUNTER		0xFFC00654	/* Timer 5 Counter Register        			*/
-#define TIMER5_PERIOD		0xFFC00658	/* Timer 5 Period Register         			*/
-#define TIMER5_WIDTH		0xFFC0065C	/* Timer 5 Width Register          			*/
-
-#define TIMER6_CONFIG		0xFFC00660	/* Timer 6 Configuration Register  			*/
-#define TIMER6_COUNTER		0xFFC00664	/* Timer 6 Counter Register        			*/
-#define TIMER6_PERIOD		0xFFC00668	/* Timer 6 Period Register         			*/
-#define TIMER6_WIDTH		0xFFC0066C	/* Timer 6 Width Register          			*/
-
-#define TIMER7_CONFIG		0xFFC00670	/* Timer 7 Configuration Register  			*/
-#define TIMER7_COUNTER		0xFFC00674	/* Timer 7 Counter Register        			*/
-#define TIMER7_PERIOD		0xFFC00678	/* Timer 7 Period Register         			*/
-#define TIMER7_WIDTH		0xFFC0067C	/* Timer 7 Width Register       			*/
-
-#define TIMER_ENABLE		0xFFC00680	/* Timer Enable Register					*/
-#define TIMER_DISABLE		0xFFC00684	/* Timer Disable Register					*/
-#define TIMER_STATUS		0xFFC00688	/* Timer Status Register					*/
-
-/* General Purpose I/O Port F (0xFFC00700 - 0xFFC007FF)												*/
-#define PORTFIO					0xFFC00700	/* Port F I/O Pin State Specify Register				*/
-#define PORTFIO_CLEAR			0xFFC00704	/* Port F I/O Peripheral Interrupt Clear Register		*/
-#define PORTFIO_SET				0xFFC00708	/* Port F I/O Peripheral Interrupt Set Register			*/
-#define PORTFIO_TOGGLE			0xFFC0070C	/* Port F I/O Pin State Toggle Register					*/
-#define PORTFIO_MASKA			0xFFC00710	/* Port F I/O Mask State Specify Interrupt A Register	*/
-#define PORTFIO_MASKA_CLEAR		0xFFC00714	/* Port F I/O Mask Disable Interrupt A Register			*/
-#define PORTFIO_MASKA_SET		0xFFC00718	/* Port F I/O Mask Enable Interrupt A Register			*/
-#define PORTFIO_MASKA_TOGGLE	0xFFC0071C	/* Port F I/O Mask Toggle Enable Interrupt A Register	*/
-#define PORTFIO_MASKB			0xFFC00720	/* Port F I/O Mask State Specify Interrupt B Register	*/
-#define PORTFIO_MASKB_CLEAR		0xFFC00724	/* Port F I/O Mask Disable Interrupt B Register			*/
-#define PORTFIO_MASKB_SET		0xFFC00728	/* Port F I/O Mask Enable Interrupt B Register			*/
-#define PORTFIO_MASKB_TOGGLE	0xFFC0072C	/* Port F I/O Mask Toggle Enable Interrupt B Register	*/
-#define PORTFIO_DIR				0xFFC00730	/* Port F I/O Direction Register						*/
-#define PORTFIO_POLAR			0xFFC00734	/* Port F I/O Source Polarity Register					*/
-#define PORTFIO_EDGE			0xFFC00738	/* Port F I/O Source Sensitivity Register				*/
-#define PORTFIO_BOTH			0xFFC0073C	/* Port F I/O Set on BOTH Edges Register				*/
-#define PORTFIO_INEN			0xFFC00740	/* Port F I/O Input Enable Register 					*/
-
-/* SPORT0 Controller		(0xFFC00800 - 0xFFC008FF)										*/
-#define SPORT0_TCR1			0xFFC00800	/* SPORT0 Transmit Configuration 1 Register			*/
-#define SPORT0_TCR2			0xFFC00804	/* SPORT0 Transmit Configuration 2 Register			*/
-#define SPORT0_TCLKDIV		0xFFC00808	/* SPORT0 Transmit Clock Divider					*/
-#define SPORT0_TFSDIV		0xFFC0080C	/* SPORT0 Transmit Frame Sync Divider				*/
-#define SPORT0_TX			0xFFC00810	/* SPORT0 TX Data Register							*/
-#define SPORT0_RX			0xFFC00818	/* SPORT0 RX Data Register							*/
-#define SPORT0_RCR1			0xFFC00820	/* SPORT0 Transmit Configuration 1 Register			*/
-#define SPORT0_RCR2			0xFFC00824	/* SPORT0 Transmit Configuration 2 Register			*/
-#define SPORT0_RCLKDIV		0xFFC00828	/* SPORT0 Receive Clock Divider						*/
-#define SPORT0_RFSDIV		0xFFC0082C	/* SPORT0 Receive Frame Sync Divider				*/
-#define SPORT0_STAT			0xFFC00830	/* SPORT0 Status Register							*/
-#define SPORT0_CHNL			0xFFC00834	/* SPORT0 Current Channel Register					*/
-#define SPORT0_MCMC1		0xFFC00838	/* SPORT0 Multi-Channel Configuration Register 1	*/
-#define SPORT0_MCMC2		0xFFC0083C	/* SPORT0 Multi-Channel Configuration Register 2	*/
-#define SPORT0_MTCS0		0xFFC00840	/* SPORT0 Multi-Channel Transmit Select Register 0	*/
-#define SPORT0_MTCS1		0xFFC00844	/* SPORT0 Multi-Channel Transmit Select Register 1	*/
-#define SPORT0_MTCS2		0xFFC00848	/* SPORT0 Multi-Channel Transmit Select Register 2	*/
-#define SPORT0_MTCS3		0xFFC0084C	/* SPORT0 Multi-Channel Transmit Select Register 3	*/
-#define SPORT0_MRCS0		0xFFC00850	/* SPORT0 Multi-Channel Receive Select Register 0	*/
-#define SPORT0_MRCS1		0xFFC00854	/* SPORT0 Multi-Channel Receive Select Register 1	*/
-#define SPORT0_MRCS2		0xFFC00858	/* SPORT0 Multi-Channel Receive Select Register 2	*/
-#define SPORT0_MRCS3		0xFFC0085C	/* SPORT0 Multi-Channel Receive Select Register 3	*/
-
-/* SPORT1 Controller		(0xFFC00900 - 0xFFC009FF)										*/
-#define SPORT1_TCR1			0xFFC00900	/* SPORT1 Transmit Configuration 1 Register			*/
-#define SPORT1_TCR2			0xFFC00904	/* SPORT1 Transmit Configuration 2 Register			*/
-#define SPORT1_TCLKDIV		0xFFC00908	/* SPORT1 Transmit Clock Divider					*/
-#define SPORT1_TFSDIV		0xFFC0090C	/* SPORT1 Transmit Frame Sync Divider				*/
-#define SPORT1_TX			0xFFC00910	/* SPORT1 TX Data Register							*/
-#define SPORT1_RX			0xFFC00918	/* SPORT1 RX Data Register							*/
-#define SPORT1_RCR1			0xFFC00920	/* SPORT1 Transmit Configuration 1 Register			*/
-#define SPORT1_RCR2			0xFFC00924	/* SPORT1 Transmit Configuration 2 Register			*/
-#define SPORT1_RCLKDIV		0xFFC00928	/* SPORT1 Receive Clock Divider						*/
-#define SPORT1_RFSDIV		0xFFC0092C	/* SPORT1 Receive Frame Sync Divider				*/
-#define SPORT1_STAT			0xFFC00930	/* SPORT1 Status Register							*/
-#define SPORT1_CHNL			0xFFC00934	/* SPORT1 Current Channel Register					*/
-#define SPORT1_MCMC1		0xFFC00938	/* SPORT1 Multi-Channel Configuration Register 1	*/
-#define SPORT1_MCMC2		0xFFC0093C	/* SPORT1 Multi-Channel Configuration Register 2	*/
-#define SPORT1_MTCS0		0xFFC00940	/* SPORT1 Multi-Channel Transmit Select Register 0	*/
-#define SPORT1_MTCS1		0xFFC00944	/* SPORT1 Multi-Channel Transmit Select Register 1	*/
-#define SPORT1_MTCS2		0xFFC00948	/* SPORT1 Multi-Channel Transmit Select Register 2	*/
-#define SPORT1_MTCS3		0xFFC0094C	/* SPORT1 Multi-Channel Transmit Select Register 3	*/
-#define SPORT1_MRCS0		0xFFC00950	/* SPORT1 Multi-Channel Receive Select Register 0	*/
-#define SPORT1_MRCS1		0xFFC00954	/* SPORT1 Multi-Channel Receive Select Register 1	*/
-#define SPORT1_MRCS2		0xFFC00958	/* SPORT1 Multi-Channel Receive Select Register 2	*/
-#define SPORT1_MRCS3		0xFFC0095C	/* SPORT1 Multi-Channel Receive Select Register 3	*/
-
-/* External Bus Interface Unit (0xFFC00A00 - 0xFFC00AFF)								*/
-#define EBIU_AMGCTL			0xFFC00A00	/* Asynchronous Memory Global Control Register	*/
-#define EBIU_AMBCTL0		0xFFC00A04	/* Asynchronous Memory Bank Control Register 0	*/
-#define EBIU_AMBCTL1		0xFFC00A08	/* Asynchronous Memory Bank Control Register 1	*/
-#define EBIU_SDGCTL			0xFFC00A10	/* SDRAM Global Control Register				*/
-#define EBIU_SDBCTL			0xFFC00A14	/* SDRAM Bank Control Register					*/
-#define EBIU_SDRRC			0xFFC00A18	/* SDRAM Refresh Rate Control Register			*/
-#define EBIU_SDSTAT			0xFFC00A1C	/* SDRAM Status Register						*/
-
-/* DMA Traffic Control Registers													*/
-#define DMA_TC_PER			0xFFC00B0C	/* Traffic Control Periods Register			*/
-#define DMA_TC_CNT			0xFFC00B10	/* Traffic Control Current Counts Register	*/
-
-/* Alternate deprecated register names (below) provided for backwards code compatibility */
-#define DMA_TCPER			0xFFC00B0C	/* Traffic Control Periods Register			*/
-#define DMA_TCCNT			0xFFC00B10	/* Traffic Control Current Counts Register	*/
-
-/* DMA Controller (0xFFC00C00 - 0xFFC00FFF)															*/
-#define DMA0_NEXT_DESC_PTR		0xFFC00C00	/* DMA Channel 0 Next Descriptor Pointer Register		*/
-#define DMA0_START_ADDR			0xFFC00C04	/* DMA Channel 0 Start Address Register					*/
-#define DMA0_CONFIG				0xFFC00C08	/* DMA Channel 0 Configuration Register					*/
-#define DMA0_X_COUNT			0xFFC00C10	/* DMA Channel 0 X Count Register						*/
-#define DMA0_X_MODIFY			0xFFC00C14	/* DMA Channel 0 X Modify Register						*/
-#define DMA0_Y_COUNT			0xFFC00C18	/* DMA Channel 0 Y Count Register						*/
-#define DMA0_Y_MODIFY			0xFFC00C1C	/* DMA Channel 0 Y Modify Register						*/
-#define DMA0_CURR_DESC_PTR		0xFFC00C20	/* DMA Channel 0 Current Descriptor Pointer Register	*/
-#define DMA0_CURR_ADDR			0xFFC00C24	/* DMA Channel 0 Current Address Register				*/
-#define DMA0_IRQ_STATUS			0xFFC00C28	/* DMA Channel 0 Interrupt/Status Register				*/
-#define DMA0_PERIPHERAL_MAP		0xFFC00C2C	/* DMA Channel 0 Peripheral Map Register				*/
-#define DMA0_CURR_X_COUNT		0xFFC00C30	/* DMA Channel 0 Current X Count Register				*/
-#define DMA0_CURR_Y_COUNT		0xFFC00C38	/* DMA Channel 0 Current Y Count Register				*/
-
-#define DMA1_NEXT_DESC_PTR		0xFFC00C40	/* DMA Channel 1 Next Descriptor Pointer Register		*/
-#define DMA1_START_ADDR			0xFFC00C44	/* DMA Channel 1 Start Address Register					*/
-#define DMA1_CONFIG				0xFFC00C48	/* DMA Channel 1 Configuration Register					*/
-#define DMA1_X_COUNT			0xFFC00C50	/* DMA Channel 1 X Count Register						*/
-#define DMA1_X_MODIFY			0xFFC00C54	/* DMA Channel 1 X Modify Register						*/
-#define DMA1_Y_COUNT			0xFFC00C58	/* DMA Channel 1 Y Count Register						*/
-#define DMA1_Y_MODIFY			0xFFC00C5C	/* DMA Channel 1 Y Modify Register						*/
-#define DMA1_CURR_DESC_PTR		0xFFC00C60	/* DMA Channel 1 Current Descriptor Pointer Register	*/
-#define DMA1_CURR_ADDR			0xFFC00C64	/* DMA Channel 1 Current Address Register				*/
-#define DMA1_IRQ_STATUS			0xFFC00C68	/* DMA Channel 1 Interrupt/Status Register				*/
-#define DMA1_PERIPHERAL_MAP		0xFFC00C6C	/* DMA Channel 1 Peripheral Map Register				*/
-#define DMA1_CURR_X_COUNT		0xFFC00C70	/* DMA Channel 1 Current X Count Register				*/
-#define DMA1_CURR_Y_COUNT		0xFFC00C78	/* DMA Channel 1 Current Y Count Register				*/
-
-#define DMA2_NEXT_DESC_PTR		0xFFC00C80	/* DMA Channel 2 Next Descriptor Pointer Register		*/
-#define DMA2_START_ADDR			0xFFC00C84	/* DMA Channel 2 Start Address Register					*/
-#define DMA2_CONFIG				0xFFC00C88	/* DMA Channel 2 Configuration Register					*/
-#define DMA2_X_COUNT			0xFFC00C90	/* DMA Channel 2 X Count Register						*/
-#define DMA2_X_MODIFY			0xFFC00C94	/* DMA Channel 2 X Modify Register						*/
-#define DMA2_Y_COUNT			0xFFC00C98	/* DMA Channel 2 Y Count Register						*/
-#define DMA2_Y_MODIFY			0xFFC00C9C	/* DMA Channel 2 Y Modify Register						*/
-#define DMA2_CURR_DESC_PTR		0xFFC00CA0	/* DMA Channel 2 Current Descriptor Pointer Register	*/
-#define DMA2_CURR_ADDR			0xFFC00CA4	/* DMA Channel 2 Current Address Register				*/
-#define DMA2_IRQ_STATUS			0xFFC00CA8	/* DMA Channel 2 Interrupt/Status Register				*/
-#define DMA2_PERIPHERAL_MAP		0xFFC00CAC	/* DMA Channel 2 Peripheral Map Register				*/
-#define DMA2_CURR_X_COUNT		0xFFC00CB0	/* DMA Channel 2 Current X Count Register				*/
-#define DMA2_CURR_Y_COUNT		0xFFC00CB8	/* DMA Channel 2 Current Y Count Register				*/
-
-#define DMA3_NEXT_DESC_PTR		0xFFC00CC0	/* DMA Channel 3 Next Descriptor Pointer Register		*/
-#define DMA3_START_ADDR			0xFFC00CC4	/* DMA Channel 3 Start Address Register					*/
-#define DMA3_CONFIG				0xFFC00CC8	/* DMA Channel 3 Configuration Register					*/
-#define DMA3_X_COUNT			0xFFC00CD0	/* DMA Channel 3 X Count Register						*/
-#define DMA3_X_MODIFY			0xFFC00CD4	/* DMA Channel 3 X Modify Register						*/
-#define DMA3_Y_COUNT			0xFFC00CD8	/* DMA Channel 3 Y Count Register						*/
-#define DMA3_Y_MODIFY			0xFFC00CDC	/* DMA Channel 3 Y Modify Register						*/
-#define DMA3_CURR_DESC_PTR		0xFFC00CE0	/* DMA Channel 3 Current Descriptor Pointer Register	*/
-#define DMA3_CURR_ADDR			0xFFC00CE4	/* DMA Channel 3 Current Address Register				*/
-#define DMA3_IRQ_STATUS			0xFFC00CE8	/* DMA Channel 3 Interrupt/Status Register				*/
-#define DMA3_PERIPHERAL_MAP		0xFFC00CEC	/* DMA Channel 3 Peripheral Map Register				*/
-#define DMA3_CURR_X_COUNT		0xFFC00CF0	/* DMA Channel 3 Current X Count Register				*/
-#define DMA3_CURR_Y_COUNT		0xFFC00CF8	/* DMA Channel 3 Current Y Count Register				*/
-
-#define DMA4_NEXT_DESC_PTR		0xFFC00D00	/* DMA Channel 4 Next Descriptor Pointer Register		*/
-#define DMA4_START_ADDR			0xFFC00D04	/* DMA Channel 4 Start Address Register					*/
-#define DMA4_CONFIG				0xFFC00D08	/* DMA Channel 4 Configuration Register					*/
-#define DMA4_X_COUNT			0xFFC00D10	/* DMA Channel 4 X Count Register						*/
-#define DMA4_X_MODIFY			0xFFC00D14	/* DMA Channel 4 X Modify Register						*/
-#define DMA4_Y_COUNT			0xFFC00D18	/* DMA Channel 4 Y Count Register						*/
-#define DMA4_Y_MODIFY			0xFFC00D1C	/* DMA Channel 4 Y Modify Register						*/
-#define DMA4_CURR_DESC_PTR		0xFFC00D20	/* DMA Channel 4 Current Descriptor Pointer Register	*/
-#define DMA4_CURR_ADDR			0xFFC00D24	/* DMA Channel 4 Current Address Register				*/
-#define DMA4_IRQ_STATUS			0xFFC00D28	/* DMA Channel 4 Interrupt/Status Register				*/
-#define DMA4_PERIPHERAL_MAP		0xFFC00D2C	/* DMA Channel 4 Peripheral Map Register				*/
-#define DMA4_CURR_X_COUNT		0xFFC00D30	/* DMA Channel 4 Current X Count Register				*/
-#define DMA4_CURR_Y_COUNT		0xFFC00D38	/* DMA Channel 4 Current Y Count Register				*/
-
-#define DMA5_NEXT_DESC_PTR		0xFFC00D40	/* DMA Channel 5 Next Descriptor Pointer Register		*/
-#define DMA5_START_ADDR			0xFFC00D44	/* DMA Channel 5 Start Address Register					*/
-#define DMA5_CONFIG				0xFFC00D48	/* DMA Channel 5 Configuration Register					*/
-#define DMA5_X_COUNT			0xFFC00D50	/* DMA Channel 5 X Count Register						*/
-#define DMA5_X_MODIFY			0xFFC00D54	/* DMA Channel 5 X Modify Register						*/
-#define DMA5_Y_COUNT			0xFFC00D58	/* DMA Channel 5 Y Count Register						*/
-#define DMA5_Y_MODIFY			0xFFC00D5C	/* DMA Channel 5 Y Modify Register						*/
-#define DMA5_CURR_DESC_PTR		0xFFC00D60	/* DMA Channel 5 Current Descriptor Pointer Register	*/
-#define DMA5_CURR_ADDR			0xFFC00D64	/* DMA Channel 5 Current Address Register				*/
-#define DMA5_IRQ_STATUS			0xFFC00D68	/* DMA Channel 5 Interrupt/Status Register				*/
-#define DMA5_PERIPHERAL_MAP		0xFFC00D6C	/* DMA Channel 5 Peripheral Map Register				*/
-#define DMA5_CURR_X_COUNT		0xFFC00D70	/* DMA Channel 5 Current X Count Register				*/
-#define DMA5_CURR_Y_COUNT		0xFFC00D78	/* DMA Channel 5 Current Y Count Register				*/
-
-#define DMA6_NEXT_DESC_PTR		0xFFC00D80	/* DMA Channel 6 Next Descriptor Pointer Register		*/
-#define DMA6_START_ADDR			0xFFC00D84	/* DMA Channel 6 Start Address Register					*/
-#define DMA6_CONFIG				0xFFC00D88	/* DMA Channel 6 Configuration Register					*/
-#define DMA6_X_COUNT			0xFFC00D90	/* DMA Channel 6 X Count Register						*/
-#define DMA6_X_MODIFY			0xFFC00D94	/* DMA Channel 6 X Modify Register						*/
-#define DMA6_Y_COUNT			0xFFC00D98	/* DMA Channel 6 Y Count Register						*/
-#define DMA6_Y_MODIFY			0xFFC00D9C	/* DMA Channel 6 Y Modify Register						*/
-#define DMA6_CURR_DESC_PTR		0xFFC00DA0	/* DMA Channel 6 Current Descriptor Pointer Register	*/
-#define DMA6_CURR_ADDR			0xFFC00DA4	/* DMA Channel 6 Current Address Register				*/
-#define DMA6_IRQ_STATUS			0xFFC00DA8	/* DMA Channel 6 Interrupt/Status Register				*/
-#define DMA6_PERIPHERAL_MAP		0xFFC00DAC	/* DMA Channel 6 Peripheral Map Register				*/
-#define DMA6_CURR_X_COUNT		0xFFC00DB0	/* DMA Channel 6 Current X Count Register				*/
-#define DMA6_CURR_Y_COUNT		0xFFC00DB8	/* DMA Channel 6 Current Y Count Register				*/
-
-#define DMA7_NEXT_DESC_PTR		0xFFC00DC0	/* DMA Channel 7 Next Descriptor Pointer Register		*/
-#define DMA7_START_ADDR			0xFFC00DC4	/* DMA Channel 7 Start Address Register					*/
-#define DMA7_CONFIG				0xFFC00DC8	/* DMA Channel 7 Configuration Register					*/
-#define DMA7_X_COUNT			0xFFC00DD0	/* DMA Channel 7 X Count Register						*/
-#define DMA7_X_MODIFY			0xFFC00DD4	/* DMA Channel 7 X Modify Register						*/
-#define DMA7_Y_COUNT			0xFFC00DD8	/* DMA Channel 7 Y Count Register						*/
-#define DMA7_Y_MODIFY			0xFFC00DDC	/* DMA Channel 7 Y Modify Register						*/
-#define DMA7_CURR_DESC_PTR		0xFFC00DE0	/* DMA Channel 7 Current Descriptor Pointer Register	*/
-#define DMA7_CURR_ADDR			0xFFC00DE4	/* DMA Channel 7 Current Address Register				*/
-#define DMA7_IRQ_STATUS			0xFFC00DE8	/* DMA Channel 7 Interrupt/Status Register				*/
-#define DMA7_PERIPHERAL_MAP		0xFFC00DEC	/* DMA Channel 7 Peripheral Map Register				*/
-#define DMA7_CURR_X_COUNT		0xFFC00DF0	/* DMA Channel 7 Current X Count Register				*/
-#define DMA7_CURR_Y_COUNT		0xFFC00DF8	/* DMA Channel 7 Current Y Count Register				*/
-
-#define DMA8_NEXT_DESC_PTR		0xFFC00E00	/* DMA Channel 8 Next Descriptor Pointer Register		*/
-#define DMA8_START_ADDR			0xFFC00E04	/* DMA Channel 8 Start Address Register					*/
-#define DMA8_CONFIG				0xFFC00E08	/* DMA Channel 8 Configuration Register					*/
-#define DMA8_X_COUNT			0xFFC00E10	/* DMA Channel 8 X Count Register						*/
-#define DMA8_X_MODIFY			0xFFC00E14	/* DMA Channel 8 X Modify Register						*/
-#define DMA8_Y_COUNT			0xFFC00E18	/* DMA Channel 8 Y Count Register						*/
-#define DMA8_Y_MODIFY			0xFFC00E1C	/* DMA Channel 8 Y Modify Register						*/
-#define DMA8_CURR_DESC_PTR		0xFFC00E20	/* DMA Channel 8 Current Descriptor Pointer Register	*/
-#define DMA8_CURR_ADDR			0xFFC00E24	/* DMA Channel 8 Current Address Register				*/
-#define DMA8_IRQ_STATUS			0xFFC00E28	/* DMA Channel 8 Interrupt/Status Register				*/
-#define DMA8_PERIPHERAL_MAP		0xFFC00E2C	/* DMA Channel 8 Peripheral Map Register				*/
-#define DMA8_CURR_X_COUNT		0xFFC00E30	/* DMA Channel 8 Current X Count Register				*/
-#define DMA8_CURR_Y_COUNT		0xFFC00E38	/* DMA Channel 8 Current Y Count Register				*/
-
-#define DMA9_NEXT_DESC_PTR		0xFFC00E40	/* DMA Channel 9 Next Descriptor Pointer Register		*/
-#define DMA9_START_ADDR			0xFFC00E44	/* DMA Channel 9 Start Address Register					*/
-#define DMA9_CONFIG				0xFFC00E48	/* DMA Channel 9 Configuration Register					*/
-#define DMA9_X_COUNT			0xFFC00E50	/* DMA Channel 9 X Count Register						*/
-#define DMA9_X_MODIFY			0xFFC00E54	/* DMA Channel 9 X Modify Register						*/
-#define DMA9_Y_COUNT			0xFFC00E58	/* DMA Channel 9 Y Count Register						*/
-#define DMA9_Y_MODIFY			0xFFC00E5C	/* DMA Channel 9 Y Modify Register						*/
-#define DMA9_CURR_DESC_PTR		0xFFC00E60	/* DMA Channel 9 Current Descriptor Pointer Register	*/
-#define DMA9_CURR_ADDR			0xFFC00E64	/* DMA Channel 9 Current Address Register				*/
-#define DMA9_IRQ_STATUS			0xFFC00E68	/* DMA Channel 9 Interrupt/Status Register				*/
-#define DMA9_PERIPHERAL_MAP		0xFFC00E6C	/* DMA Channel 9 Peripheral Map Register				*/
-#define DMA9_CURR_X_COUNT		0xFFC00E70	/* DMA Channel 9 Current X Count Register				*/
-#define DMA9_CURR_Y_COUNT		0xFFC00E78	/* DMA Channel 9 Current Y Count Register				*/
-
-#define DMA10_NEXT_DESC_PTR		0xFFC00E80	/* DMA Channel 10 Next Descriptor Pointer Register		*/
-#define DMA10_START_ADDR		0xFFC00E84	/* DMA Channel 10 Start Address Register				*/
-#define DMA10_CONFIG			0xFFC00E88	/* DMA Channel 10 Configuration Register				*/
-#define DMA10_X_COUNT			0xFFC00E90	/* DMA Channel 10 X Count Register						*/
-#define DMA10_X_MODIFY			0xFFC00E94	/* DMA Channel 10 X Modify Register						*/
-#define DMA10_Y_COUNT			0xFFC00E98	/* DMA Channel 10 Y Count Register						*/
-#define DMA10_Y_MODIFY			0xFFC00E9C	/* DMA Channel 10 Y Modify Register						*/
-#define DMA10_CURR_DESC_PTR		0xFFC00EA0	/* DMA Channel 10 Current Descriptor Pointer Register	*/
-#define DMA10_CURR_ADDR			0xFFC00EA4	/* DMA Channel 10 Current Address Register				*/
-#define DMA10_IRQ_STATUS		0xFFC00EA8	/* DMA Channel 10 Interrupt/Status Register				*/
-#define DMA10_PERIPHERAL_MAP	0xFFC00EAC	/* DMA Channel 10 Peripheral Map Register				*/
-#define DMA10_CURR_X_COUNT		0xFFC00EB0	/* DMA Channel 10 Current X Count Register				*/
-#define DMA10_CURR_Y_COUNT		0xFFC00EB8	/* DMA Channel 10 Current Y Count Register				*/
-
-#define DMA11_NEXT_DESC_PTR		0xFFC00EC0	/* DMA Channel 11 Next Descriptor Pointer Register		*/
-#define DMA11_START_ADDR		0xFFC00EC4	/* DMA Channel 11 Start Address Register				*/
-#define DMA11_CONFIG			0xFFC00EC8	/* DMA Channel 11 Configuration Register				*/
-#define DMA11_X_COUNT			0xFFC00ED0	/* DMA Channel 11 X Count Register						*/
-#define DMA11_X_MODIFY			0xFFC00ED4	/* DMA Channel 11 X Modify Register						*/
-#define DMA11_Y_COUNT			0xFFC00ED8	/* DMA Channel 11 Y Count Register						*/
-#define DMA11_Y_MODIFY			0xFFC00EDC	/* DMA Channel 11 Y Modify Register						*/
-#define DMA11_CURR_DESC_PTR		0xFFC00EE0	/* DMA Channel 11 Current Descriptor Pointer Register	*/
-#define DMA11_CURR_ADDR			0xFFC00EE4	/* DMA Channel 11 Current Address Register				*/
-#define DMA11_IRQ_STATUS		0xFFC00EE8	/* DMA Channel 11 Interrupt/Status Register				*/
-#define DMA11_PERIPHERAL_MAP	0xFFC00EEC	/* DMA Channel 11 Peripheral Map Register				*/
-#define DMA11_CURR_X_COUNT		0xFFC00EF0	/* DMA Channel 11 Current X Count Register				*/
-#define DMA11_CURR_Y_COUNT		0xFFC00EF8	/* DMA Channel 11 Current Y Count Register				*/
-
-#define MDMA_D0_NEXT_DESC_PTR	0xFFC00F00	/* MemDMA Stream 0 Destination Next Descriptor Pointer Register		*/
-#define MDMA_D0_START_ADDR		0xFFC00F04	/* MemDMA Stream 0 Destination Start Address Register				*/
-#define MDMA_D0_CONFIG			0xFFC00F08	/* MemDMA Stream 0 Destination Configuration Register				*/
-#define MDMA_D0_X_COUNT			0xFFC00F10	/* MemDMA Stream 0 Destination X Count Register						*/
-#define MDMA_D0_X_MODIFY		0xFFC00F14	/* MemDMA Stream 0 Destination X Modify Register					*/
-#define MDMA_D0_Y_COUNT			0xFFC00F18	/* MemDMA Stream 0 Destination Y Count Register						*/
-#define MDMA_D0_Y_MODIFY		0xFFC00F1C	/* MemDMA Stream 0 Destination Y Modify Register					*/
-#define MDMA_D0_CURR_DESC_PTR	0xFFC00F20	/* MemDMA Stream 0 Destination Current Descriptor Pointer Register	*/
-#define MDMA_D0_CURR_ADDR		0xFFC00F24	/* MemDMA Stream 0 Destination Current Address Register				*/
-#define MDMA_D0_IRQ_STATUS		0xFFC00F28	/* MemDMA Stream 0 Destination Interrupt/Status Register			*/
-#define MDMA_D0_PERIPHERAL_MAP	0xFFC00F2C	/* MemDMA Stream 0 Destination Peripheral Map Register				*/
-#define MDMA_D0_CURR_X_COUNT	0xFFC00F30	/* MemDMA Stream 0 Destination Current X Count Register				*/
-#define MDMA_D0_CURR_Y_COUNT	0xFFC00F38	/* MemDMA Stream 0 Destination Current Y Count Register				*/
-
-#define MDMA_S0_NEXT_DESC_PTR	0xFFC00F40	/* MemDMA Stream 0 Source Next Descriptor Pointer Register			*/
-#define MDMA_S0_START_ADDR		0xFFC00F44	/* MemDMA Stream 0 Source Start Address Register					*/
-#define MDMA_S0_CONFIG			0xFFC00F48	/* MemDMA Stream 0 Source Configuration Register					*/
-#define MDMA_S0_X_COUNT			0xFFC00F50	/* MemDMA Stream 0 Source X Count Register							*/
-#define MDMA_S0_X_MODIFY		0xFFC00F54	/* MemDMA Stream 0 Source X Modify Register							*/
-#define MDMA_S0_Y_COUNT			0xFFC00F58	/* MemDMA Stream 0 Source Y Count Register							*/
-#define MDMA_S0_Y_MODIFY		0xFFC00F5C	/* MemDMA Stream 0 Source Y Modify Register							*/
-#define MDMA_S0_CURR_DESC_PTR	0xFFC00F60	/* MemDMA Stream 0 Source Current Descriptor Pointer Register		*/
-#define MDMA_S0_CURR_ADDR		0xFFC00F64	/* MemDMA Stream 0 Source Current Address Register					*/
-#define MDMA_S0_IRQ_STATUS		0xFFC00F68	/* MemDMA Stream 0 Source Interrupt/Status Register					*/
-#define MDMA_S0_PERIPHERAL_MAP	0xFFC00F6C	/* MemDMA Stream 0 Source Peripheral Map Register					*/
-#define MDMA_S0_CURR_X_COUNT	0xFFC00F70	/* MemDMA Stream 0 Source Current X Count Register					*/
-#define MDMA_S0_CURR_Y_COUNT	0xFFC00F78	/* MemDMA Stream 0 Source Current Y Count Register					*/
-
-#define MDMA_D1_NEXT_DESC_PTR	0xFFC00F80	/* MemDMA Stream 1 Destination Next Descriptor Pointer Register		*/
-#define MDMA_D1_START_ADDR		0xFFC00F84	/* MemDMA Stream 1 Destination Start Address Register				*/
-#define MDMA_D1_CONFIG			0xFFC00F88	/* MemDMA Stream 1 Destination Configuration Register				*/
-#define MDMA_D1_X_COUNT			0xFFC00F90	/* MemDMA Stream 1 Destination X Count Register						*/
-#define MDMA_D1_X_MODIFY		0xFFC00F94	/* MemDMA Stream 1 Destination X Modify Register					*/
-#define MDMA_D1_Y_COUNT			0xFFC00F98	/* MemDMA Stream 1 Destination Y Count Register						*/
-#define MDMA_D1_Y_MODIFY		0xFFC00F9C	/* MemDMA Stream 1 Destination Y Modify Register					*/
-#define MDMA_D1_CURR_DESC_PTR	0xFFC00FA0	/* MemDMA Stream 1 Destination Current Descriptor Pointer Register	*/
-#define MDMA_D1_CURR_ADDR		0xFFC00FA4	/* MemDMA Stream 1 Destination Current Address Register				*/
-#define MDMA_D1_IRQ_STATUS		0xFFC00FA8	/* MemDMA Stream 1 Destination Interrupt/Status Register			*/
-#define MDMA_D1_PERIPHERAL_MAP	0xFFC00FAC	/* MemDMA Stream 1 Destination Peripheral Map Register				*/
-#define MDMA_D1_CURR_X_COUNT	0xFFC00FB0	/* MemDMA Stream 1 Destination Current X Count Register				*/
-#define MDMA_D1_CURR_Y_COUNT	0xFFC00FB8	/* MemDMA Stream 1 Destination Current Y Count Register				*/
-
-#define MDMA_S1_NEXT_DESC_PTR	0xFFC00FC0	/* MemDMA Stream 1 Source Next Descriptor Pointer Register			*/
-#define MDMA_S1_START_ADDR		0xFFC00FC4	/* MemDMA Stream 1 Source Start Address Register					*/
-#define MDMA_S1_CONFIG			0xFFC00FC8	/* MemDMA Stream 1 Source Configuration Register					*/
-#define MDMA_S1_X_COUNT			0xFFC00FD0	/* MemDMA Stream 1 Source X Count Register							*/
-#define MDMA_S1_X_MODIFY		0xFFC00FD4	/* MemDMA Stream 1 Source X Modify Register							*/
-#define MDMA_S1_Y_COUNT			0xFFC00FD8	/* MemDMA Stream 1 Source Y Count Register							*/
-#define MDMA_S1_Y_MODIFY		0xFFC00FDC	/* MemDMA Stream 1 Source Y Modify Register							*/
-#define MDMA_S1_CURR_DESC_PTR	0xFFC00FE0	/* MemDMA Stream 1 Source Current Descriptor Pointer Register		*/
-#define MDMA_S1_CURR_ADDR		0xFFC00FE4	/* MemDMA Stream 1 Source Current Address Register					*/
-#define MDMA_S1_IRQ_STATUS		0xFFC00FE8	/* MemDMA Stream 1 Source Interrupt/Status Register					*/
-#define MDMA_S1_PERIPHERAL_MAP	0xFFC00FEC	/* MemDMA Stream 1 Source Peripheral Map Register					*/
-#define MDMA_S1_CURR_X_COUNT	0xFFC00FF0	/* MemDMA Stream 1 Source Current X Count Register					*/
-#define MDMA_S1_CURR_Y_COUNT	0xFFC00FF8	/* MemDMA Stream 1 Source Current Y Count Register					*/
-
-
-/* Parallel Peripheral Interface (0xFFC01000 - 0xFFC010FF)				*/
-#define PPI_CONTROL			0xFFC01000	/* PPI Control Register			*/
-#define PPI_STATUS			0xFFC01004	/* PPI Status Register			*/
-#define PPI_COUNT			0xFFC01008	/* PPI Transfer Count Register	*/
-#define PPI_DELAY			0xFFC0100C	/* PPI Delay Count Register		*/
-#define PPI_FRAME			0xFFC01010	/* PPI Frame Length Register	*/
-
-
-/* Two-Wire Interface		(0xFFC01400 - 0xFFC014FF)								*/
-#define TWI0_REGBASE			0xFFC01400
-#define TWI0_CLKDIV			0xFFC01400	/* Serial Clock Divider Register			*/
-#define TWI0_CONTROL			0xFFC01404	/* TWI Control Register						*/
-#define TWI0_SLAVE_CTL		0xFFC01408	/* Slave Mode Control Register				*/
-#define TWI0_SLAVE_STAT		0xFFC0140C	/* Slave Mode Status Register				*/
-#define TWI0_SLAVE_ADDR		0xFFC01410	/* Slave Mode Address Register				*/
-#define TWI0_MASTER_CTL		0xFFC01414	/* Master Mode Control Register				*/
-#define TWI0_MASTER_STAT		0xFFC01418	/* Master Mode Status Register				*/
-#define TWI0_MASTER_ADDR		0xFFC0141C	/* Master Mode Address Register				*/
-#define TWI0_INT_STAT		0xFFC01420	/* TWI Interrupt Status Register			*/
-#define TWI0_INT_MASK		0xFFC01424	/* TWI Master Interrupt Mask Register		*/
-#define TWI0_FIFO_CTL		0xFFC01428	/* FIFO Control Register					*/
-#define TWI0_FIFO_STAT		0xFFC0142C	/* FIFO Status Register						*/
-#define TWI0_XMT_DATA8		0xFFC01480	/* FIFO Transmit Data Single Byte Register	*/
-#define TWI0_XMT_DATA16		0xFFC01484	/* FIFO Transmit Data Double Byte Register	*/
-#define TWI0_RCV_DATA8		0xFFC01488	/* FIFO Receive Data Single Byte Register	*/
-#define TWI0_RCV_DATA16		0xFFC0148C	/* FIFO Receive Data Double Byte Register	*/
-
-
-/* General Purpose I/O Port G (0xFFC01500 - 0xFFC015FF)												*/
-#define PORTGIO					0xFFC01500	/* Port G I/O Pin State Specify Register				*/
-#define PORTGIO_CLEAR			0xFFC01504	/* Port G I/O Peripheral Interrupt Clear Register		*/
-#define PORTGIO_SET				0xFFC01508	/* Port G I/O Peripheral Interrupt Set Register			*/
-#define PORTGIO_TOGGLE			0xFFC0150C	/* Port G I/O Pin State Toggle Register					*/
-#define PORTGIO_MASKA			0xFFC01510	/* Port G I/O Mask State Specify Interrupt A Register	*/
-#define PORTGIO_MASKA_CLEAR		0xFFC01514	/* Port G I/O Mask Disable Interrupt A Register			*/
-#define PORTGIO_MASKA_SET		0xFFC01518	/* Port G I/O Mask Enable Interrupt A Register			*/
-#define PORTGIO_MASKA_TOGGLE	0xFFC0151C	/* Port G I/O Mask Toggle Enable Interrupt A Register	*/
-#define PORTGIO_MASKB			0xFFC01520	/* Port G I/O Mask State Specify Interrupt B Register	*/
-#define PORTGIO_MASKB_CLEAR		0xFFC01524	/* Port G I/O Mask Disable Interrupt B Register			*/
-#define PORTGIO_MASKB_SET		0xFFC01528	/* Port G I/O Mask Enable Interrupt B Register			*/
-#define PORTGIO_MASKB_TOGGLE	0xFFC0152C	/* Port G I/O Mask Toggle Enable Interrupt B Register	*/
-#define PORTGIO_DIR				0xFFC01530	/* Port G I/O Direction Register						*/
-#define PORTGIO_POLAR			0xFFC01534	/* Port G I/O Source Polarity Register					*/
-#define PORTGIO_EDGE			0xFFC01538	/* Port G I/O Source Sensitivity Register				*/
-#define PORTGIO_BOTH			0xFFC0153C	/* Port G I/O Set on BOTH Edges Register				*/
-#define PORTGIO_INEN			0xFFC01540	/* Port G I/O Input Enable Register						*/
-
-
-/* General Purpose I/O Port H (0xFFC01700 - 0xFFC017FF)												*/
-#define PORTHIO					0xFFC01700	/* Port H I/O Pin State Specify Register				*/
-#define PORTHIO_CLEAR			0xFFC01704	/* Port H I/O Peripheral Interrupt Clear Register		*/
-#define PORTHIO_SET				0xFFC01708	/* Port H I/O Peripheral Interrupt Set Register			*/
-#define PORTHIO_TOGGLE			0xFFC0170C	/* Port H I/O Pin State Toggle Register					*/
-#define PORTHIO_MASKA			0xFFC01710	/* Port H I/O Mask State Specify Interrupt A Register	*/
-#define PORTHIO_MASKA_CLEAR		0xFFC01714	/* Port H I/O Mask Disable Interrupt A Register			*/
-#define PORTHIO_MASKA_SET		0xFFC01718	/* Port H I/O Mask Enable Interrupt A Register			*/
-#define PORTHIO_MASKA_TOGGLE	0xFFC0171C	/* Port H I/O Mask Toggle Enable Interrupt A Register	*/
-#define PORTHIO_MASKB			0xFFC01720	/* Port H I/O Mask State Specify Interrupt B Register	*/
-#define PORTHIO_MASKB_CLEAR		0xFFC01724	/* Port H I/O Mask Disable Interrupt B Register			*/
-#define PORTHIO_MASKB_SET		0xFFC01728	/* Port H I/O Mask Enable Interrupt B Register			*/
-#define PORTHIO_MASKB_TOGGLE	0xFFC0172C	/* Port H I/O Mask Toggle Enable Interrupt B Register	*/
-#define PORTHIO_DIR				0xFFC01730	/* Port H I/O Direction Register						*/
-#define PORTHIO_POLAR			0xFFC01734	/* Port H I/O Source Polarity Register					*/
-#define PORTHIO_EDGE			0xFFC01738	/* Port H I/O Source Sensitivity Register				*/
-#define PORTHIO_BOTH			0xFFC0173C	/* Port H I/O Set on BOTH Edges Register				*/
-#define PORTHIO_INEN			0xFFC01740	/* Port H I/O Input Enable Register						*/
-
-
-/* UART1 Controller		(0xFFC02000 - 0xFFC020FF)								*/
-#define UART1_THR			0xFFC02000	/* Transmit Holding register			*/
-#define UART1_RBR			0xFFC02000	/* Receive Buffer register				*/
-#define UART1_DLL			0xFFC02000	/* Divisor Latch (Low-Byte)				*/
-#define UART1_IER			0xFFC02004	/* Interrupt Enable Register			*/
-#define UART1_DLH			0xFFC02004	/* Divisor Latch (High-Byte)			*/
-#define UART1_IIR			0xFFC02008	/* Interrupt Identification Register	*/
-#define UART1_LCR			0xFFC0200C	/* Line Control Register				*/
-#define UART1_MCR			0xFFC02010	/* Modem Control Register				*/
-#define UART1_LSR			0xFFC02014	/* Line Status Register					*/
-#define UART1_MSR			0xFFC02018	/* Modem Status Register				*/
-#define UART1_SCR			0xFFC0201C	/* SCR Scratch Register					*/
-#define UART1_GCTL			0xFFC02024	/* Global Control Register				*/
-
-
-/* Pin Control Registers	(0xFFC03200 - 0xFFC032FF)											*/
-#define PORTF_FER			0xFFC03200	/* Port F Function Enable Register (Alternate/Flag*)	*/
-#define PORTG_FER			0xFFC03204	/* Port G Function Enable Register (Alternate/Flag*)	*/
-#define PORTH_FER			0xFFC03208	/* Port H Function Enable Register (Alternate/Flag*)	*/
-#define BFIN_PORT_MUX			0xFFC0320C	/* Port Multiplexer Control Register					*/
-
-
-/* Handshake MDMA Registers	(0xFFC03300 - 0xFFC033FF)										*/
-#define HMDMA0_CONTROL		0xFFC03300	/* Handshake MDMA0 Control Register					*/
-#define HMDMA0_ECINIT		0xFFC03304	/* HMDMA0 Initial Edge Count Register				*/
-#define HMDMA0_BCINIT		0xFFC03308	/* HMDMA0 Initial Block Count Register				*/
-#define HMDMA0_ECURGENT		0xFFC0330C	/* HMDMA0 Urgent Edge Count Threshold Register		*/
-#define HMDMA0_ECOVERFLOW	0xFFC03310	/* HMDMA0 Edge Count Overflow Interrupt Register	*/
-#define HMDMA0_ECOUNT		0xFFC03314	/* HMDMA0 Current Edge Count Register				*/
-#define HMDMA0_BCOUNT		0xFFC03318	/* HMDMA0 Current Block Count Register				*/
-
-#define HMDMA1_CONTROL		0xFFC03340	/* Handshake MDMA1 Control Register					*/
-#define HMDMA1_ECINIT		0xFFC03344	/* HMDMA1 Initial Edge Count Register				*/
-#define HMDMA1_BCINIT		0xFFC03348	/* HMDMA1 Initial Block Count Register				*/
-#define HMDMA1_ECURGENT		0xFFC0334C	/* HMDMA1 Urgent Edge Count Threshold Register		*/
-#define HMDMA1_ECOVERFLOW	0xFFC03350	/* HMDMA1 Edge Count Overflow Interrupt Register	*/
-#define HMDMA1_ECOUNT		0xFFC03354	/* HMDMA1 Current Edge Count Register				*/
-#define HMDMA1_BCOUNT		0xFFC03358	/* HMDMA1 Current Block Count Register				*/
-
-
-/* GPIO PIN mux (0xFFC03210 - OxFFC03288) */
-#define PORTF_MUX               0xFFC03210      /* Port F mux control */
-#define PORTG_MUX               0xFFC03214      /* Port G mux control */
-#define PORTH_MUX               0xFFC03218      /* Port H mux control */
-#define PORTF_DRIVE             0xFFC03220      /* Port F drive strength control */
-#define PORTG_DRIVE             0xFFC03224      /* Port G drive strength control */
-#define PORTH_DRIVE             0xFFC03228      /* Port H drive strength control */
-#define PORTF_SLEW              0xFFC03230      /* Port F slew control */
-#define PORTG_SLEW              0xFFC03234      /* Port G slew control */
-#define PORTH_SLEW              0xFFC03238      /* Port H slew control */
-#define PORTF_HYSTERISIS        0xFFC03240      /* Port F Schmitt trigger control */
-#define PORTG_HYSTERISIS        0xFFC03244      /* Port G Schmitt trigger control */
-#define PORTH_HYSTERISIS        0xFFC03248      /* Port H Schmitt trigger control */
-#define MISCPORT_DRIVE          0xFFC03280      /* Misc Port drive strength control */
-#define MISCPORT_SLEW           0xFFC03284      /* Misc Port slew control */
-#define MISCPORT_HYSTERISIS     0xFFC03288      /* Misc Port Schmitt trigger control */
-
-
-/***********************************************************************************
-** System MMR Register Bits And Macros
-**
-** Disclaimer:	All macros are intended to make C and Assembly code more readable.
-**				Use these macros carefully, as any that do left shifts for field
-**				depositing will result in the lower order bits being destroyed.  Any
-**				macro that shifts left to properly position the bit-field should be
-**				used as part of an OR to initialize a register and NOT as a dynamic
-**				modifier UNLESS the lower order bits are saved and ORed back in when
-**				the macro is used.
-*************************************************************************************/
-
-/* CHIPID Masks */
-#define CHIPID_VERSION         0xF0000000
-#define CHIPID_FAMILY          0x0FFFF000
-#define CHIPID_MANUFACTURE     0x00000FFE
-
-/* SWRST Masks																		*/
-#define SYSTEM_RESET		0x0007	/* Initiates A System Software Reset			*/
-#define	DOUBLE_FAULT		0x0008	/* Core Double Fault Causes Reset				*/
-#define RESET_DOUBLE		0x2000	/* SW Reset Generated By Core Double-Fault		*/
-#define RESET_WDOG			0x4000	/* SW Reset Generated By Watchdog Timer			*/
-#define RESET_SOFTWARE		0x8000	/* SW Reset Occurred Since Last Read Of SWRST	*/
-
-/* SYSCR Masks																				*/
-#define BMODE				0x0007	/* Boot Mode - Latched During HW Reset From Mode Pins	*/
-#define	NOBOOT				0x0010	/* Execute From L1 or ASYNC Bank 0 When BMODE = 0		*/
-
-
-/* *************  SYSTEM INTERRUPT CONTROLLER MASKS *************************************/
-/* Peripheral Masks For SIC_ISR, SIC_IWR, SIC_IMASK										*/
-
-#if 0
-#define IRQ_PLL_WAKEUP	0x00000001	/* PLL Wakeup Interrupt			 					*/
-
-#define IRQ_ERROR1      0x00000002  /* Error Interrupt (DMA, DMARx Block, DMARx Overflow) */
-#define IRQ_ERROR2      0x00000004  /* Error Interrupt (CAN, Ethernet, SPORTx, PPI, SPI, UARTx) */
-#define IRQ_RTC			0x00000008	/* Real Time Clock Interrupt 						*/
-#define IRQ_DMA0		0x00000010	/* DMA Channel 0 (PPI) Interrupt 					*/
-#define IRQ_DMA3		0x00000020	/* DMA Channel 3 (SPORT0 RX) Interrupt 				*/
-#define IRQ_DMA4		0x00000040	/* DMA Channel 4 (SPORT0 TX) Interrupt 				*/
-#define IRQ_DMA5		0x00000080	/* DMA Channel 5 (SPORT1 RX) Interrupt 				*/
-
-#define IRQ_DMA6		0x00000100	/* DMA Channel 6 (SPORT1 TX) Interrupt 		 		*/
-#define IRQ_TWI			0x00000200	/* TWI Interrupt									*/
-#define IRQ_DMA7		0x00000400	/* DMA Channel 7 (SPI) Interrupt 					*/
-#define IRQ_DMA8		0x00000800	/* DMA Channel 8 (UART0 RX) Interrupt 				*/
-#define IRQ_DMA9		0x00001000	/* DMA Channel 9 (UART0 TX) Interrupt 				*/
-#define IRQ_DMA10		0x00002000	/* DMA Channel 10 (UART1 RX) Interrupt 				*/
-#define IRQ_DMA11		0x00004000	/* DMA Channel 11 (UART1 TX) Interrupt 				*/
-#define IRQ_CAN_RX		0x00008000	/* CAN Receive Interrupt 							*/
-
-#define IRQ_CAN_TX		0x00010000	/* CAN Transmit Interrupt  							*/
-#define IRQ_DMA1		0x00020000	/* DMA Channel 1 (Ethernet RX) Interrupt 			*/
-#define IRQ_PFA_PORTH	0x00020000	/* PF Port H (PF47:32) Interrupt A 					*/
-#define IRQ_DMA2		0x00040000	/* DMA Channel 2 (Ethernet TX) Interrupt 			*/
-#define IRQ_PFB_PORTH	0x00040000	/* PF Port H (PF47:32) Interrupt B 					*/
-#define IRQ_TIMER0		0x00080000	/* Timer 0 Interrupt								*/
-#define IRQ_TIMER1		0x00100000	/* Timer 1 Interrupt 								*/
-#define IRQ_TIMER2		0x00200000	/* Timer 2 Interrupt 								*/
-#define IRQ_TIMER3		0x00400000	/* Timer 3 Interrupt 								*/
-#define IRQ_TIMER4		0x00800000	/* Timer 4 Interrupt 								*/
-
-#define IRQ_TIMER5		0x01000000	/* Timer 5 Interrupt 								*/
-#define IRQ_TIMER6		0x02000000	/* Timer 6 Interrupt 								*/
-#define IRQ_TIMER7		0x04000000	/* Timer 7 Interrupt 								*/
-#define IRQ_PFA_PORTFG	0x08000000	/* PF Ports F&G (PF31:0) Interrupt A 				*/
-#define IRQ_PFB_PORTF	0x80000000	/* PF Port F (PF15:0) Interrupt B 					*/
-#define IRQ_DMA12		0x20000000	/* DMA Channels 12 (MDMA1 Source) RX Interrupt 		*/
-#define IRQ_DMA13		0x20000000	/* DMA Channels 13 (MDMA1 Destination) TX Interrupt */
-#define IRQ_DMA14		0x40000000	/* DMA Channels 14 (MDMA0 Source) RX Interrupt 		*/
-#define IRQ_DMA15		0x40000000	/* DMA Channels 15 (MDMA0 Destination) TX Interrupt */
-#define IRQ_WDOG		0x80000000	/* Software Watchdog Timer Interrupt 				*/
-#define IRQ_PFB_PORTG	0x10000000	/* PF Port G (PF31:16) Interrupt B 					*/
-#endif
-
-/* SIC_IAR0 Macros															*/
-#define P0_IVG(x)		(((x)&0xF)-7)			/* Peripheral #0 assigned IVG #x 	*/
-#define P1_IVG(x)		(((x)&0xF)-7) << 0x4	/* Peripheral #1 assigned IVG #x 	*/
-#define P2_IVG(x)		(((x)&0xF)-7) << 0x8	/* Peripheral #2 assigned IVG #x 	*/
-#define P3_IVG(x)		(((x)&0xF)-7) << 0xC	/* Peripheral #3 assigned IVG #x	*/
-#define P4_IVG(x)		(((x)&0xF)-7) << 0x10	/* Peripheral #4 assigned IVG #x	*/
-#define P5_IVG(x)		(((x)&0xF)-7) << 0x14	/* Peripheral #5 assigned IVG #x	*/
-#define P6_IVG(x)		(((x)&0xF)-7) << 0x18	/* Peripheral #6 assigned IVG #x	*/
-#define P7_IVG(x)		(((x)&0xF)-7) << 0x1C	/* Peripheral #7 assigned IVG #x	*/
-
-/* SIC_IAR1 Macros															*/
-#define P8_IVG(x)		(((x)&0xF)-7)			/* Peripheral #8 assigned IVG #x 	*/
-#define P9_IVG(x)		(((x)&0xF)-7) << 0x4	/* Peripheral #9 assigned IVG #x 	*/
-#define P10_IVG(x)		(((x)&0xF)-7) << 0x8	/* Peripheral #10 assigned IVG #x	*/
-#define P11_IVG(x)		(((x)&0xF)-7) << 0xC	/* Peripheral #11 assigned IVG #x 	*/
-#define P12_IVG(x)		(((x)&0xF)-7) << 0x10	/* Peripheral #12 assigned IVG #x	*/
-#define P13_IVG(x)		(((x)&0xF)-7) << 0x14	/* Peripheral #13 assigned IVG #x	*/
-#define P14_IVG(x)		(((x)&0xF)-7) << 0x18	/* Peripheral #14 assigned IVG #x	*/
-#define P15_IVG(x)		(((x)&0xF)-7) << 0x1C	/* Peripheral #15 assigned IVG #x	*/
-
-/* SIC_IAR2 Macros															*/
-#define P16_IVG(x)		(((x)&0xF)-7)			/* Peripheral #16 assigned IVG #x	*/
-#define P17_IVG(x)		(((x)&0xF)-7) << 0x4	/* Peripheral #17 assigned IVG #x	*/
-#define P18_IVG(x)		(((x)&0xF)-7) << 0x8	/* Peripheral #18 assigned IVG #x	*/
-#define P19_IVG(x)		(((x)&0xF)-7) << 0xC	/* Peripheral #19 assigned IVG #x	*/
-#define P20_IVG(x)		(((x)&0xF)-7) << 0x10	/* Peripheral #20 assigned IVG #x	*/
-#define P21_IVG(x)		(((x)&0xF)-7) << 0x14	/* Peripheral #21 assigned IVG #x	*/
-#define P22_IVG(x)		(((x)&0xF)-7) << 0x18	/* Peripheral #22 assigned IVG #x	*/
-#define P23_IVG(x)		(((x)&0xF)-7) << 0x1C	/* Peripheral #23 assigned IVG #x	*/
-
-/* SIC_IAR3 Macros															*/
-#define P24_IVG(x)		(((x)&0xF)-7)			/* Peripheral #24 assigned IVG #x	*/
-#define P25_IVG(x)		(((x)&0xF)-7) << 0x4	/* Peripheral #25 assigned IVG #x	*/
-#define P26_IVG(x)		(((x)&0xF)-7) << 0x8	/* Peripheral #26 assigned IVG #x	*/
-#define P27_IVG(x)		(((x)&0xF)-7) << 0xC	/* Peripheral #27 assigned IVG #x	*/
-#define P28_IVG(x)		(((x)&0xF)-7) << 0x10	/* Peripheral #28 assigned IVG #x	*/
-#define P29_IVG(x)		(((x)&0xF)-7) << 0x14	/* Peripheral #29 assigned IVG #x	*/
-#define P30_IVG(x)		(((x)&0xF)-7) << 0x18	/* Peripheral #30 assigned IVG #x	*/
-#define P31_IVG(x)		(((x)&0xF)-7) << 0x1C	/* Peripheral #31 assigned IVG #x	*/
-
-
-/* SIC_IMASK Masks																		*/
-#define SIC_UNMASK_ALL	0x00000000					/* Unmask all peripheral interrupts	*/
-#define SIC_MASK_ALL	0xFFFFFFFF					/* Mask all peripheral interrupts	*/
-#define SIC_MASK(x)		(1 << ((x)&0x1F))					/* Mask Peripheral #x interrupt		*/
-#define SIC_UNMASK(x)	(0xFFFFFFFF ^ (1 << ((x)&0x1F)))	/* Unmask Peripheral #x interrupt	*/
-
-/* SIC_IWR Masks																		*/
-#define IWR_DISABLE_ALL	0x00000000					/* Wakeup Disable all peripherals	*/
-#define IWR_ENABLE_ALL	0xFFFFFFFF					/* Wakeup Enable all peripherals	*/
-#define IWR_ENABLE(x)	(1 << ((x)&0x1F))					/* Wakeup Enable Peripheral #x		*/
-#define IWR_DISABLE(x)	(0xFFFFFFFF ^ (1 << ((x)&0x1F))) 	/* Wakeup Disable Peripheral #x		*/
-
-
-/* ************** UART CONTROLLER MASKS *************************/
-/* UARTx_LCR Masks												*/
-#define WLS(x)		(((x)-5) & 0x03)	/* Word Length Select */
-#define STB			0x04				/* Stop Bits			*/
-#define PEN			0x08				/* Parity Enable		*/
-#define EPS			0x10				/* Even Parity Select	*/
-#define STP			0x20				/* Stick Parity			*/
-#define SB			0x40				/* Set Break			*/
-#define DLAB		0x80				/* Divisor Latch Access	*/
-
-/* UARTx_MCR Mask										*/
-#define LOOP_ENA	0x10	/* Loopback Mode Enable */
-#define LOOP_ENA_P	0x04
-
-/* UARTx_LSR Masks										*/
-#define DR			0x01	/* Data Ready				*/
-#define OE			0x02	/* Overrun Error			*/
-#define PE			0x04	/* Parity Error				*/
-#define FE			0x08	/* Framing Error			*/
-#define BI			0x10	/* Break Interrupt			*/
-#define THRE		0x20	/* THR Empty				*/
-#define TEMT		0x40	/* TSR and UART_THR Empty	*/
-
-/* UARTx_IER Masks															*/
-#define ERBFI		0x01		/* Enable Receive Buffer Full Interrupt		*/
-#define ETBEI		0x02		/* Enable Transmit Buffer Empty Interrupt	*/
-#define ELSI		0x04		/* Enable RX Status Interrupt				*/
-
-/* UARTx_IIR Masks														*/
-#define NINT		0x01		/* Pending Interrupt					*/
-#define IIR_TX_READY    0x02		/* UART_THR empty                               */
-#define IIR_RX_READY    0x04		/* Receive data ready                           */
-#define IIR_LINE_CHANGE 0x06		/* Receive line status    			*/
-#define IIR_STATUS	0x06		/* Highest Priority Pending Interrupt	*/
-
-/* UARTx_GCTL Masks													*/
-#define UCEN		0x01		/* Enable UARTx Clocks				*/
-#define IREN		0x02		/* Enable IrDA Mode					*/
-#define TPOLC		0x04		/* IrDA TX Polarity Change			*/
-#define RPOLC		0x08		/* IrDA RX Polarity Change			*/
-#define FPE			0x10		/* Force Parity Error On Transmit	*/
-#define FFE			0x20		/* Force Framing Error On Transmit	*/
-
-
-/*  ****************  GENERAL PURPOSE TIMER MASKS  **********************/
-/* TIMER_ENABLE Masks													*/
-#define TIMEN0			0x0001		/* Enable Timer 0					*/
-#define TIMEN1			0x0002		/* Enable Timer 1					*/
-#define TIMEN2			0x0004		/* Enable Timer 2					*/
-#define TIMEN3			0x0008		/* Enable Timer 3					*/
-#define TIMEN4			0x0010		/* Enable Timer 4					*/
-#define TIMEN5			0x0020		/* Enable Timer 5					*/
-#define TIMEN6			0x0040		/* Enable Timer 6					*/
-#define TIMEN7			0x0080		/* Enable Timer 7					*/
-
-/* TIMER_DISABLE Masks													*/
-#define TIMDIS0			TIMEN0		/* Disable Timer 0					*/
-#define TIMDIS1			TIMEN1		/* Disable Timer 1					*/
-#define TIMDIS2			TIMEN2		/* Disable Timer 2					*/
-#define TIMDIS3			TIMEN3		/* Disable Timer 3					*/
-#define TIMDIS4			TIMEN4		/* Disable Timer 4					*/
-#define TIMDIS5			TIMEN5		/* Disable Timer 5					*/
-#define TIMDIS6			TIMEN6		/* Disable Timer 6					*/
-#define TIMDIS7			TIMEN7		/* Disable Timer 7					*/
-
-/* TIMER_STATUS Masks													*/
-#define TIMIL0			0x00000001	/* Timer 0 Interrupt				*/
-#define TIMIL1			0x00000002	/* Timer 1 Interrupt				*/
-#define TIMIL2			0x00000004	/* Timer 2 Interrupt				*/
-#define TIMIL3			0x00000008	/* Timer 3 Interrupt				*/
-#define TOVF_ERR0		0x00000010	/* Timer 0 Counter Overflow			*/
-#define TOVF_ERR1		0x00000020	/* Timer 1 Counter Overflow			*/
-#define TOVF_ERR2		0x00000040	/* Timer 2 Counter Overflow			*/
-#define TOVF_ERR3		0x00000080	/* Timer 3 Counter Overflow			*/
-#define TRUN0			0x00001000	/* Timer 0 Slave Enable Status		*/
-#define TRUN1			0x00002000	/* Timer 1 Slave Enable Status		*/
-#define TRUN2			0x00004000	/* Timer 2 Slave Enable Status		*/
-#define TRUN3			0x00008000	/* Timer 3 Slave Enable Status		*/
-#define TIMIL4			0x00010000	/* Timer 4 Interrupt				*/
-#define TIMIL5			0x00020000	/* Timer 5 Interrupt				*/
-#define TIMIL6			0x00040000	/* Timer 6 Interrupt				*/
-#define TIMIL7			0x00080000	/* Timer 7 Interrupt				*/
-#define TOVF_ERR4		0x00100000	/* Timer 4 Counter Overflow			*/
-#define TOVF_ERR5		0x00200000	/* Timer 5 Counter Overflow			*/
-#define TOVF_ERR6		0x00400000	/* Timer 6 Counter Overflow			*/
-#define TOVF_ERR7		0x00800000	/* Timer 7 Counter Overflow			*/
-#define TRUN4			0x10000000	/* Timer 4 Slave Enable Status		*/
-#define TRUN5			0x20000000	/* Timer 5 Slave Enable Status		*/
-#define TRUN6			0x40000000	/* Timer 6 Slave Enable Status		*/
-#define TRUN7			0x80000000	/* Timer 7 Slave Enable Status		*/
-
-/* Alternate Deprecated Macros Provided For Backwards Code Compatibility */
-#define TOVL_ERR0 TOVF_ERR0
-#define TOVL_ERR1 TOVF_ERR1
-#define TOVL_ERR2 TOVF_ERR2
-#define TOVL_ERR3 TOVF_ERR3
-#define TOVL_ERR4 TOVF_ERR4
-#define TOVL_ERR5 TOVF_ERR5
-#define TOVL_ERR6 TOVF_ERR6
-#define TOVL_ERR7 TOVF_ERR7
-
-/* TIMERx_CONFIG Masks													*/
-#define PWM_OUT			0x0001	/* Pulse-Width Modulation Output Mode	*/
-#define WDTH_CAP		0x0002	/* Width Capture Input Mode				*/
-#define EXT_CLK			0x0003	/* External Clock Mode					*/
-#define PULSE_HI		0x0004	/* Action Pulse (Positive/Negative*)	*/
-#define PERIOD_CNT		0x0008	/* Period Count							*/
-#define IRQ_ENA			0x0010	/* Interrupt Request Enable				*/
-#define TIN_SEL			0x0020	/* Timer Input Select					*/
-#define OUT_DIS			0x0040	/* Output Pad Disable					*/
-#define CLK_SEL			0x0080	/* Timer Clock Select					*/
-#define TOGGLE_HI		0x0100	/* PWM_OUT PULSE_HI Toggle Mode			*/
-#define EMU_RUN			0x0200	/* Emulation Behavior Select			*/
-#define ERR_TYP			0xC000	/* Error Type							*/
-
-
-/* ******************   GPIO PORTS F, G, H MASKS  ***********************/
-/*  General Purpose IO (0xFFC00700 - 0xFFC007FF)  Masks 				*/
-/* Port F Masks 														*/
-#define PF0		0x0001
-#define PF1		0x0002
-#define PF2		0x0004
-#define PF3		0x0008
-#define PF4		0x0010
-#define PF5		0x0020
-#define PF6		0x0040
-#define PF7		0x0080
-#define PF8		0x0100
-#define PF9		0x0200
-#define PF10	0x0400
-#define PF11	0x0800
-#define PF12	0x1000
-#define PF13	0x2000
-#define PF14	0x4000
-#define PF15	0x8000
-
-/* Port G Masks															*/
-#define PG0		0x0001
-#define PG1		0x0002
-#define PG2		0x0004
-#define PG3		0x0008
-#define PG4		0x0010
-#define PG5		0x0020
-#define PG6		0x0040
-#define PG7		0x0080
-#define PG8		0x0100
-#define PG9		0x0200
-#define PG10	0x0400
-#define PG11	0x0800
-#define PG12	0x1000
-#define PG13	0x2000
-#define PG14	0x4000
-#define PG15	0x8000
-
-/* Port H Masks															*/
-#define PH0		0x0001
-#define PH1		0x0002
-#define PH2		0x0004
-#define PH3		0x0008
-#define PH4		0x0010
-#define PH5		0x0020
-#define PH6		0x0040
-#define PH7		0x0080
-
-/* *********************  ASYNCHRONOUS MEMORY CONTROLLER MASKS  *************************/
-/* EBIU_AMGCTL Masks																	*/
-#define AMCKEN			0x0001		/* Enable CLKOUT									*/
-#define	AMBEN_NONE		0x0000		/* All Banks Disabled								*/
-#define AMBEN_B0		0x0002		/* Enable Async Memory Bank 0 only					*/
-#define AMBEN_B0_B1		0x0004		/* Enable Async Memory Banks 0 & 1 only				*/
-#define AMBEN_B0_B1_B2	0x0006		/* Enable Async Memory Banks 0, 1, and 2			*/
-#define AMBEN_ALL		0x0008		/* Enable Async Memory Banks (all) 0, 1, 2, and 3	*/
-
-/* EBIU_AMBCTL0 Masks																	*/
-#define B0RDYEN			0x00000001  /* Bank 0 (B0) RDY Enable							*/
-#define B0RDYPOL		0x00000002  /* B0 RDY Active High								*/
-#define B0TT_1			0x00000004  /* B0 Transition Time (Read to Write) = 1 cycle		*/
-#define B0TT_2			0x00000008  /* B0 Transition Time (Read to Write) = 2 cycles	*/
-#define B0TT_3			0x0000000C  /* B0 Transition Time (Read to Write) = 3 cycles	*/
-#define B0TT_4			0x00000000  /* B0 Transition Time (Read to Write) = 4 cycles	*/
-#define B0ST_1			0x00000010  /* B0 Setup Time (AOE to Read/Write) = 1 cycle		*/
-#define B0ST_2			0x00000020  /* B0 Setup Time (AOE to Read/Write) = 2 cycles		*/
-#define B0ST_3			0x00000030  /* B0 Setup Time (AOE to Read/Write) = 3 cycles		*/
-#define B0ST_4			0x00000000  /* B0 Setup Time (AOE to Read/Write) = 4 cycles		*/
-#define B0HT_1			0x00000040  /* B0 Hold Time (~Read/Write to ~AOE) = 1 cycle		*/
-#define B0HT_2			0x00000080  /* B0 Hold Time (~Read/Write to ~AOE) = 2 cycles	*/
-#define B0HT_3			0x000000C0  /* B0 Hold Time (~Read/Write to ~AOE) = 3 cycles	*/
-#define B0HT_0			0x00000000  /* B0 Hold Time (~Read/Write to ~AOE) = 0 cycles	*/
-#define B0RAT_1			0x00000100  /* B0 Read Access Time = 1 cycle					*/
-#define B0RAT_2			0x00000200  /* B0 Read Access Time = 2 cycles					*/
-#define B0RAT_3			0x00000300  /* B0 Read Access Time = 3 cycles					*/
-#define B0RAT_4			0x00000400  /* B0 Read Access Time = 4 cycles					*/
-#define B0RAT_5			0x00000500  /* B0 Read Access Time = 5 cycles					*/
-#define B0RAT_6			0x00000600  /* B0 Read Access Time = 6 cycles					*/
-#define B0RAT_7			0x00000700  /* B0 Read Access Time = 7 cycles					*/
-#define B0RAT_8			0x00000800  /* B0 Read Access Time = 8 cycles					*/
-#define B0RAT_9			0x00000900  /* B0 Read Access Time = 9 cycles					*/
-#define B0RAT_10		0x00000A00  /* B0 Read Access Time = 10 cycles					*/
-#define B0RAT_11		0x00000B00  /* B0 Read Access Time = 11 cycles					*/
-#define B0RAT_12		0x00000C00  /* B0 Read Access Time = 12 cycles					*/
-#define B0RAT_13		0x00000D00  /* B0 Read Access Time = 13 cycles					*/
-#define B0RAT_14		0x00000E00  /* B0 Read Access Time = 14 cycles					*/
-#define B0RAT_15		0x00000F00  /* B0 Read Access Time = 15 cycles					*/
-#define B0WAT_1			0x00001000  /* B0 Write Access Time = 1 cycle					*/
-#define B0WAT_2			0x00002000  /* B0 Write Access Time = 2 cycles					*/
-#define B0WAT_3			0x00003000  /* B0 Write Access Time = 3 cycles					*/
-#define B0WAT_4			0x00004000  /* B0 Write Access Time = 4 cycles					*/
-#define B0WAT_5			0x00005000  /* B0 Write Access Time = 5 cycles					*/
-#define B0WAT_6			0x00006000  /* B0 Write Access Time = 6 cycles					*/
-#define B0WAT_7			0x00007000  /* B0 Write Access Time = 7 cycles					*/
-#define B0WAT_8			0x00008000  /* B0 Write Access Time = 8 cycles					*/
-#define B0WAT_9			0x00009000  /* B0 Write Access Time = 9 cycles					*/
-#define B0WAT_10		0x0000A000  /* B0 Write Access Time = 10 cycles					*/
-#define B0WAT_11		0x0000B000  /* B0 Write Access Time = 11 cycles					*/
-#define B0WAT_12		0x0000C000  /* B0 Write Access Time = 12 cycles					*/
-#define B0WAT_13		0x0000D000  /* B0 Write Access Time = 13 cycles					*/
-#define B0WAT_14		0x0000E000  /* B0 Write Access Time = 14 cycles					*/
-#define B0WAT_15		0x0000F000  /* B0 Write Access Time = 15 cycles					*/
-
-#define B1RDYEN			0x00010000  /* Bank 1 (B1) RDY Enable                       	*/
-#define B1RDYPOL		0x00020000  /* B1 RDY Active High                           	*/
-#define B1TT_1			0x00040000  /* B1 Transition Time (Read to Write) = 1 cycle 	*/
-#define B1TT_2			0x00080000  /* B1 Transition Time (Read to Write) = 2 cycles	*/
-#define B1TT_3			0x000C0000  /* B1 Transition Time (Read to Write) = 3 cycles	*/
-#define B1TT_4			0x00000000  /* B1 Transition Time (Read to Write) = 4 cycles	*/
-#define B1ST_1			0x00100000  /* B1 Setup Time (AOE to Read/Write) = 1 cycle  	*/
-#define B1ST_2			0x00200000  /* B1 Setup Time (AOE to Read/Write) = 2 cycles 	*/
-#define B1ST_3			0x00300000  /* B1 Setup Time (AOE to Read/Write) = 3 cycles 	*/
-#define B1ST_4			0x00000000  /* B1 Setup Time (AOE to Read/Write) = 4 cycles 	*/
-#define B1HT_1			0x00400000  /* B1 Hold Time (~Read/Write to ~AOE) = 1 cycle 	*/
-#define B1HT_2			0x00800000  /* B1 Hold Time (~Read/Write to ~AOE) = 2 cycles	*/
-#define B1HT_3			0x00C00000  /* B1 Hold Time (~Read/Write to ~AOE) = 3 cycles	*/
-#define B1HT_0			0x00000000  /* B1 Hold Time (~Read/Write to ~AOE) = 0 cycles	*/
-#define B1RAT_1			0x01000000  /* B1 Read Access Time = 1 cycle					*/
-#define B1RAT_2			0x02000000  /* B1 Read Access Time = 2 cycles					*/
-#define B1RAT_3			0x03000000  /* B1 Read Access Time = 3 cycles					*/
-#define B1RAT_4			0x04000000  /* B1 Read Access Time = 4 cycles					*/
-#define B1RAT_5			0x05000000  /* B1 Read Access Time = 5 cycles					*/
-#define B1RAT_6			0x06000000  /* B1 Read Access Time = 6 cycles					*/
-#define B1RAT_7			0x07000000  /* B1 Read Access Time = 7 cycles					*/
-#define B1RAT_8			0x08000000  /* B1 Read Access Time = 8 cycles					*/
-#define B1RAT_9			0x09000000  /* B1 Read Access Time = 9 cycles					*/
-#define B1RAT_10		0x0A000000  /* B1 Read Access Time = 10 cycles					*/
-#define B1RAT_11		0x0B000000  /* B1 Read Access Time = 11 cycles					*/
-#define B1RAT_12		0x0C000000  /* B1 Read Access Time = 12 cycles					*/
-#define B1RAT_13		0x0D000000  /* B1 Read Access Time = 13 cycles					*/
-#define B1RAT_14		0x0E000000  /* B1 Read Access Time = 14 cycles					*/
-#define B1RAT_15		0x0F000000  /* B1 Read Access Time = 15 cycles					*/
-#define B1WAT_1			0x10000000  /* B1 Write Access Time = 1 cycle					*/
-#define B1WAT_2			0x20000000  /* B1 Write Access Time = 2 cycles					*/
-#define B1WAT_3			0x30000000  /* B1 Write Access Time = 3 cycles					*/
-#define B1WAT_4			0x40000000  /* B1 Write Access Time = 4 cycles					*/
-#define B1WAT_5			0x50000000  /* B1 Write Access Time = 5 cycles					*/
-#define B1WAT_6			0x60000000  /* B1 Write Access Time = 6 cycles					*/
-#define B1WAT_7			0x70000000  /* B1 Write Access Time = 7 cycles					*/
-#define B1WAT_8			0x80000000  /* B1 Write Access Time = 8 cycles					*/
-#define B1WAT_9			0x90000000  /* B1 Write Access Time = 9 cycles					*/
-#define B1WAT_10		0xA0000000  /* B1 Write Access Time = 10 cycles					*/
-#define B1WAT_11		0xB0000000  /* B1 Write Access Time = 11 cycles					*/
-#define B1WAT_12		0xC0000000  /* B1 Write Access Time = 12 cycles					*/
-#define B1WAT_13		0xD0000000  /* B1 Write Access Time = 13 cycles					*/
-#define B1WAT_14		0xE0000000  /* B1 Write Access Time = 14 cycles					*/
-#define B1WAT_15		0xF0000000  /* B1 Write Access Time = 15 cycles					*/
-
-/* EBIU_AMBCTL1 Masks																	*/
-#define B2RDYEN			0x00000001  /* Bank 2 (B2) RDY Enable							*/
-#define B2RDYPOL		0x00000002  /* B2 RDY Active High								*/
-#define B2TT_1			0x00000004  /* B2 Transition Time (Read to Write) = 1 cycle		*/
-#define B2TT_2			0x00000008  /* B2 Transition Time (Read to Write) = 2 cycles	*/
-#define B2TT_3			0x0000000C  /* B2 Transition Time (Read to Write) = 3 cycles	*/
-#define B2TT_4			0x00000000  /* B2 Transition Time (Read to Write) = 4 cycles	*/
-#define B2ST_1			0x00000010  /* B2 Setup Time (AOE to Read/Write) = 1 cycle		*/
-#define B2ST_2			0x00000020  /* B2 Setup Time (AOE to Read/Write) = 2 cycles		*/
-#define B2ST_3			0x00000030  /* B2 Setup Time (AOE to Read/Write) = 3 cycles		*/
-#define B2ST_4			0x00000000  /* B2 Setup Time (AOE to Read/Write) = 4 cycles		*/
-#define B2HT_1			0x00000040  /* B2 Hold Time (~Read/Write to ~AOE) = 1 cycle		*/
-#define B2HT_2			0x00000080  /* B2 Hold Time (~Read/Write to ~AOE) = 2 cycles	*/
-#define B2HT_3			0x000000C0  /* B2 Hold Time (~Read/Write to ~AOE) = 3 cycles	*/
-#define B2HT_0			0x00000000  /* B2 Hold Time (~Read/Write to ~AOE) = 0 cycles	*/
-#define B2RAT_1			0x00000100  /* B2 Read Access Time = 1 cycle					*/
-#define B2RAT_2			0x00000200  /* B2 Read Access Time = 2 cycles					*/
-#define B2RAT_3			0x00000300  /* B2 Read Access Time = 3 cycles					*/
-#define B2RAT_4			0x00000400  /* B2 Read Access Time = 4 cycles					*/
-#define B2RAT_5			0x00000500  /* B2 Read Access Time = 5 cycles					*/
-#define B2RAT_6			0x00000600  /* B2 Read Access Time = 6 cycles					*/
-#define B2RAT_7			0x00000700  /* B2 Read Access Time = 7 cycles					*/
-#define B2RAT_8			0x00000800  /* B2 Read Access Time = 8 cycles					*/
-#define B2RAT_9			0x00000900  /* B2 Read Access Time = 9 cycles					*/
-#define B2RAT_10		0x00000A00  /* B2 Read Access Time = 10 cycles					*/
-#define B2RAT_11		0x00000B00  /* B2 Read Access Time = 11 cycles					*/
-#define B2RAT_12		0x00000C00  /* B2 Read Access Time = 12 cycles					*/
-#define B2RAT_13		0x00000D00  /* B2 Read Access Time = 13 cycles					*/
-#define B2RAT_14		0x00000E00  /* B2 Read Access Time = 14 cycles					*/
-#define B2RAT_15		0x00000F00  /* B2 Read Access Time = 15 cycles					*/
-#define B2WAT_1			0x00001000  /* B2 Write Access Time = 1 cycle					*/
-#define B2WAT_2			0x00002000  /* B2 Write Access Time = 2 cycles					*/
-#define B2WAT_3			0x00003000  /* B2 Write Access Time = 3 cycles					*/
-#define B2WAT_4			0x00004000  /* B2 Write Access Time = 4 cycles					*/
-#define B2WAT_5			0x00005000  /* B2 Write Access Time = 5 cycles					*/
-#define B2WAT_6			0x00006000  /* B2 Write Access Time = 6 cycles					*/
-#define B2WAT_7			0x00007000  /* B2 Write Access Time = 7 cycles					*/
-#define B2WAT_8			0x00008000  /* B2 Write Access Time = 8 cycles					*/
-#define B2WAT_9			0x00009000  /* B2 Write Access Time = 9 cycles					*/
-#define B2WAT_10		0x0000A000  /* B2 Write Access Time = 10 cycles					*/
-#define B2WAT_11		0x0000B000  /* B2 Write Access Time = 11 cycles					*/
-#define B2WAT_12		0x0000C000  /* B2 Write Access Time = 12 cycles					*/
-#define B2WAT_13		0x0000D000  /* B2 Write Access Time = 13 cycles					*/
-#define B2WAT_14		0x0000E000  /* B2 Write Access Time = 14 cycles					*/
-#define B2WAT_15		0x0000F000  /* B2 Write Access Time = 15 cycles					*/
-
-#define B3RDYEN			0x00010000  /* Bank 3 (B3) RDY Enable							*/
-#define B3RDYPOL		0x00020000  /* B3 RDY Active High								*/
-#define B3TT_1			0x00040000  /* B3 Transition Time (Read to Write) = 1 cycle		*/
-#define B3TT_2			0x00080000  /* B3 Transition Time (Read to Write) = 2 cycles	*/
-#define B3TT_3			0x000C0000  /* B3 Transition Time (Read to Write) = 3 cycles	*/
-#define B3TT_4			0x00000000  /* B3 Transition Time (Read to Write) = 4 cycles	*/
-#define B3ST_1			0x00100000  /* B3 Setup Time (AOE to Read/Write) = 1 cycle		*/
-#define B3ST_2			0x00200000  /* B3 Setup Time (AOE to Read/Write) = 2 cycles		*/
-#define B3ST_3			0x00300000  /* B3 Setup Time (AOE to Read/Write) = 3 cycles		*/
-#define B3ST_4			0x00000000  /* B3 Setup Time (AOE to Read/Write) = 4 cycles		*/
-#define B3HT_1			0x00400000  /* B3 Hold Time (~Read/Write to ~AOE) = 1 cycle		*/
-#define B3HT_2			0x00800000  /* B3 Hold Time (~Read/Write to ~AOE) = 2 cycles	*/
-#define B3HT_3			0x00C00000  /* B3 Hold Time (~Read/Write to ~AOE) = 3 cycles	*/
-#define B3HT_0			0x00000000  /* B3 Hold Time (~Read/Write to ~AOE) = 0 cycles	*/
-#define B3RAT_1			0x01000000  /* B3 Read Access Time = 1 cycle					*/
-#define B3RAT_2			0x02000000  /* B3 Read Access Time = 2 cycles					*/
-#define B3RAT_3			0x03000000  /* B3 Read Access Time = 3 cycles					*/
-#define B3RAT_4			0x04000000  /* B3 Read Access Time = 4 cycles					*/
-#define B3RAT_5			0x05000000  /* B3 Read Access Time = 5 cycles					*/
-#define B3RAT_6			0x06000000  /* B3 Read Access Time = 6 cycles					*/
-#define B3RAT_7			0x07000000  /* B3 Read Access Time = 7 cycles					*/
-#define B3RAT_8			0x08000000  /* B3 Read Access Time = 8 cycles					*/
-#define B3RAT_9			0x09000000  /* B3 Read Access Time = 9 cycles					*/
-#define B3RAT_10		0x0A000000  /* B3 Read Access Time = 10 cycles					*/
-#define B3RAT_11		0x0B000000  /* B3 Read Access Time = 11 cycles					*/
-#define B3RAT_12		0x0C000000  /* B3 Read Access Time = 12 cycles					*/
-#define B3RAT_13		0x0D000000  /* B3 Read Access Time = 13 cycles					*/
-#define B3RAT_14		0x0E000000  /* B3 Read Access Time = 14 cycles					*/
-#define B3RAT_15		0x0F000000  /* B3 Read Access Time = 15 cycles					*/
-#define B3WAT_1			0x10000000  /* B3 Write Access Time = 1 cycle					*/
-#define B3WAT_2			0x20000000  /* B3 Write Access Time = 2 cycles					*/
-#define B3WAT_3			0x30000000  /* B3 Write Access Time = 3 cycles					*/
-#define B3WAT_4			0x40000000  /* B3 Write Access Time = 4 cycles					*/
-#define B3WAT_5			0x50000000  /* B3 Write Access Time = 5 cycles					*/
-#define B3WAT_6			0x60000000  /* B3 Write Access Time = 6 cycles					*/
-#define B3WAT_7			0x70000000  /* B3 Write Access Time = 7 cycles					*/
-#define B3WAT_8			0x80000000  /* B3 Write Access Time = 8 cycles					*/
-#define B3WAT_9			0x90000000  /* B3 Write Access Time = 9 cycles					*/
-#define B3WAT_10		0xA0000000  /* B3 Write Access Time = 10 cycles					*/
-#define B3WAT_11		0xB0000000  /* B3 Write Access Time = 11 cycles					*/
-#define B3WAT_12		0xC0000000  /* B3 Write Access Time = 12 cycles					*/
-#define B3WAT_13		0xD0000000  /* B3 Write Access Time = 13 cycles					*/
-#define B3WAT_14		0xE0000000  /* B3 Write Access Time = 14 cycles					*/
-#define B3WAT_15		0xF0000000  /* B3 Write Access Time = 15 cycles					*/
-
-
-/* **********************  SDRAM CONTROLLER MASKS  **********************************************/
-/* EBIU_SDGCTL Masks																			*/
-#define SCTLE			0x00000001	/* Enable SDRAM Signals										*/
-#define CL_2			0x00000008	/* SDRAM CAS Latency = 2 cycles								*/
-#define CL_3			0x0000000C	/* SDRAM CAS Latency = 3 cycles								*/
-#define PASR_ALL		0x00000000	/* All 4 SDRAM Banks Refreshed In Self-Refresh				*/
-#define PASR_B0_B1		0x00000010	/* SDRAM Banks 0 and 1 Are Refreshed In Self-Refresh		*/
-#define PASR_B0			0x00000020	/* Only SDRAM Bank 0 Is Refreshed In Self-Refresh			*/
-#define TRAS_1			0x00000040	/* SDRAM tRAS = 1 cycle										*/
-#define TRAS_2			0x00000080	/* SDRAM tRAS = 2 cycles									*/
-#define TRAS_3			0x000000C0	/* SDRAM tRAS = 3 cycles									*/
-#define TRAS_4			0x00000100	/* SDRAM tRAS = 4 cycles									*/
-#define TRAS_5			0x00000140	/* SDRAM tRAS = 5 cycles									*/
-#define TRAS_6			0x00000180	/* SDRAM tRAS = 6 cycles									*/
-#define TRAS_7			0x000001C0	/* SDRAM tRAS = 7 cycles									*/
-#define TRAS_8			0x00000200	/* SDRAM tRAS = 8 cycles									*/
-#define TRAS_9			0x00000240	/* SDRAM tRAS = 9 cycles									*/
-#define TRAS_10			0x00000280	/* SDRAM tRAS = 10 cycles									*/
-#define TRAS_11			0x000002C0	/* SDRAM tRAS = 11 cycles									*/
-#define TRAS_12			0x00000300	/* SDRAM tRAS = 12 cycles									*/
-#define TRAS_13			0x00000340	/* SDRAM tRAS = 13 cycles									*/
-#define TRAS_14			0x00000380	/* SDRAM tRAS = 14 cycles									*/
-#define TRAS_15			0x000003C0	/* SDRAM tRAS = 15 cycles									*/
-#define TRP_1			0x00000800	/* SDRAM tRP = 1 cycle										*/
-#define TRP_2			0x00001000	/* SDRAM tRP = 2 cycles										*/
-#define TRP_3			0x00001800	/* SDRAM tRP = 3 cycles										*/
-#define TRP_4			0x00002000	/* SDRAM tRP = 4 cycles										*/
-#define TRP_5			0x00002800	/* SDRAM tRP = 5 cycles										*/
-#define TRP_6			0x00003000	/* SDRAM tRP = 6 cycles										*/
-#define TRP_7			0x00003800	/* SDRAM tRP = 7 cycles										*/
-#define TRCD_1			0x00008000	/* SDRAM tRCD = 1 cycle										*/
-#define TRCD_2			0x00010000	/* SDRAM tRCD = 2 cycles									*/
-#define TRCD_3			0x00018000	/* SDRAM tRCD = 3 cycles									*/
-#define TRCD_4			0x00020000	/* SDRAM tRCD = 4 cycles									*/
-#define TRCD_5			0x00028000	/* SDRAM tRCD = 5 cycles									*/
-#define TRCD_6			0x00030000	/* SDRAM tRCD = 6 cycles									*/
-#define TRCD_7			0x00038000	/* SDRAM tRCD = 7 cycles									*/
-#define TWR_1			0x00080000	/* SDRAM tWR = 1 cycle										*/
-#define TWR_2			0x00100000	/* SDRAM tWR = 2 cycles										*/
-#define TWR_3			0x00180000	/* SDRAM tWR = 3 cycles										*/
-#define PUPSD			0x00200000	/* Power-Up Start Delay (15 SCLK Cycles Delay)				*/
-#define PSM				0x00400000	/* Power-Up Sequence (Mode Register Before/After* Refresh)	*/
-#define PSS				0x00800000	/* Enable Power-Up Sequence on Next SDRAM Access			*/
-#define SRFS			0x01000000	/* Enable SDRAM Self-Refresh Mode							*/
-#define EBUFE			0x02000000	/* Enable External Buffering Timing							*/
-#define FBBRW			0x04000000	/* Enable Fast Back-To-Back Read To Write					*/
-#define EMREN			0x10000000	/* Extended Mode Register Enable							*/
-#define TCSR			0x20000000	/* Temp-Compensated Self-Refresh Value (85/45* Deg C)		*/
-#define CDDBG			0x40000000	/* Tristate SDRAM Controls During Bus Grant					*/
-
-/* EBIU_SDBCTL Masks																		*/
-#define EBE				0x0001		/* Enable SDRAM External Bank							*/
-#define EBSZ_16			0x0000		/* SDRAM External Bank Size = 16MB	*/
-#define EBSZ_32			0x0002		/* SDRAM External Bank Size = 32MB	*/
-#define EBSZ_64			0x0004		/* SDRAM External Bank Size = 64MB	*/
-#define EBSZ_128		0x0006		/* SDRAM External Bank Size = 128MB		*/
-#define EBSZ_256		0x0008		/* SDRAM External Bank Size = 256MB 	*/
-#define EBSZ_512		0x000A		/* SDRAM External Bank Size = 512MB		*/
-#define EBCAW_8			0x0000		/* SDRAM External Bank Column Address Width = 8 Bits	*/
-#define EBCAW_9			0x0010		/* SDRAM External Bank Column Address Width = 9 Bits	*/
-#define EBCAW_10		0x0020		/* SDRAM External Bank Column Address Width = 10 Bits	*/
-#define EBCAW_11		0x0030		/* SDRAM External Bank Column Address Width = 11 Bits	*/
-
-/* EBIU_SDSTAT Masks														*/
-#define SDCI			0x0001		/* SDRAM Controller Idle 				*/
-#define SDSRA			0x0002		/* SDRAM Self-Refresh Active			*/
-#define SDPUA			0x0004		/* SDRAM Power-Up Active 				*/
-#define SDRS			0x0008		/* SDRAM Will Power-Up On Next Access	*/
-#define SDEASE			0x0010		/* SDRAM EAB Sticky Error Status		*/
-#define BGSTAT			0x0020		/* Bus Grant Status						*/
-
-
-/* **************************  DMA CONTROLLER MASKS  ********************************/
-
-/* DMAx_PERIPHERAL_MAP, MDMA_yy_PERIPHERAL_MAP Masks								*/
-#define CTYPE			0x0040	/* DMA Channel Type Indicator (Memory/Peripheral*)	*/
-#define PMAP			0xF000	/* Peripheral Mapped To This Channel				*/
-#define PMAP_PPI		0x0000	/* 		PPI Port DMA								*/
-#define	PMAP_EMACRX		0x1000	/* 		Ethernet Receive DMA						*/
-#define PMAP_EMACTX		0x2000	/* 		Ethernet Transmit DMA						*/
-#define PMAP_SPORT0RX	0x3000	/* 		SPORT0 Receive DMA							*/
-#define PMAP_SPORT0TX	0x4000	/* 		SPORT0 Transmit DMA							*/
-#define PMAP_SPORT1RX	0x5000	/* 		SPORT1 Receive DMA							*/
-#define PMAP_SPORT1TX	0x6000	/* 		SPORT1 Transmit DMA							*/
-#define PMAP_SPI		0x7000	/* 		SPI Port DMA								*/
-#define PMAP_UART0RX	0x8000	/* 		UART0 Port Receive DMA						*/
-#define PMAP_UART0TX	0x9000	/* 		UART0 Port Transmit DMA						*/
-#define	PMAP_UART1RX	0xA000	/* 		UART1 Port Receive DMA						*/
-#define	PMAP_UART1TX	0xB000	/* 		UART1 Port Transmit DMA						*/
-
-/*  ************  PARALLEL PERIPHERAL INTERFACE (PPI) MASKS *************/
-/*  PPI_CONTROL Masks													*/
-#define PORT_EN			0x0001		/* PPI Port Enable					*/
-#define PORT_DIR		0x0002		/* PPI Port Direction				*/
-#define XFR_TYPE		0x000C		/* PPI Transfer Type				*/
-#define PORT_CFG		0x0030		/* PPI Port Configuration			*/
-#define FLD_SEL			0x0040		/* PPI Active Field Select			*/
-#define PACK_EN			0x0080		/* PPI Packing Mode					*/
-#define DMA32			0x0100		/* PPI 32-bit DMA Enable			*/
-#define SKIP_EN			0x0200		/* PPI Skip Element Enable			*/
-#define SKIP_EO			0x0400		/* PPI Skip Even/Odd Elements		*/
-#define DLEN_8			0x0000		/* Data Length = 8 Bits				*/
-#define DLEN_10			0x0800		/* Data Length = 10 Bits			*/
-#define DLEN_11			0x1000		/* Data Length = 11 Bits			*/
-#define DLEN_12			0x1800		/* Data Length = 12 Bits			*/
-#define DLEN_13			0x2000		/* Data Length = 13 Bits			*/
-#define DLEN_14			0x2800		/* Data Length = 14 Bits			*/
-#define DLEN_15			0x3000		/* Data Length = 15 Bits			*/
-#define DLEN_16			0x3800		/* Data Length = 16 Bits			*/
-#define DLENGTH			0x3800		/* PPI Data Length  */
-#define POLC			0x4000		/* PPI Clock Polarity				*/
-#define POLS			0x8000		/* PPI Frame Sync Polarity			*/
-
-/* PPI_STATUS Masks														*/
-#define FLD				0x0400		/* Field Indicator					*/
-#define FT_ERR			0x0800		/* Frame Track Error				*/
-#define OVR				0x1000		/* FIFO Overflow Error				*/
-#define UNDR			0x2000		/* FIFO Underrun Error				*/
-#define ERR_DET			0x4000		/* Error Detected Indicator			*/
-#define ERR_NCOR		0x8000		/* Error Not Corrected Indicator	*/
-
-
-/*  ********************  TWO-WIRE INTERFACE (TWI) MASKS  ***********************/
-/* TWI_CLKDIV Macros (Use: *pTWI_CLKDIV = CLKLOW(x)|CLKHI(y);  )				*/
-#define	CLKLOW(x)	((x) & 0xFF)		/* Periods Clock Is Held Low			*/
-#define CLKHI(y)	(((y)&0xFF)<<0x8)	/* Periods Before New Clock Low			*/
-
-/* TWI_PRESCALE Masks															*/
-#define	PRESCALE	0x007F		/* SCLKs Per Internal Time Reference (10MHz)	*/
-#define	TWI_ENA		0x0080		/* TWI Enable									*/
-#define	SCCB		0x0200		/* SCCB Compatibility Enable					*/
-
-/* TWI_SLAVE_CTL Masks															*/
-#define	SEN			0x0001		/* Slave Enable									*/
-#define	SADD_LEN	0x0002		/* Slave Address Length							*/
-#define	STDVAL		0x0004		/* Slave Transmit Data Valid					*/
-#define	NAK			0x0008		/* NAK/ACK* Generated At Conclusion Of Transfer */
-#define	GEN			0x0010		/* General Call Adrress Matching Enabled		*/
-
-/* TWI_SLAVE_STAT Masks															*/
-#define	SDIR		0x0001		/* Slave Transfer Direction (Transmit/Receive*)	*/
-#define GCALL		0x0002		/* General Call Indicator						*/
-
-/* TWI_MASTER_CTL Masks													*/
-#define	MEN			0x0001		/* Master Mode Enable						*/
-#define	MADD_LEN	0x0002		/* Master Address Length					*/
-#define	MDIR		0x0004		/* Master Transmit Direction (RX/TX*)		*/
-#define	FAST		0x0008		/* Use Fast Mode Timing Specs				*/
-#define	STOP		0x0010		/* Issue Stop Condition						*/
-#define	RSTART		0x0020		/* Repeat Start or Stop* At End Of Transfer	*/
-#define	DCNT		0x3FC0		/* Data Bytes To Transfer					*/
-#define	SDAOVR		0x4000		/* Serial Data Override						*/
-#define	SCLOVR		0x8000		/* Serial Clock Override					*/
-
-/* TWI_MASTER_STAT Masks														*/
-#define	MPROG		0x0001		/* Master Transfer In Progress					*/
-#define	LOSTARB		0x0002		/* Lost Arbitration Indicator (Xfer Aborted)	*/
-#define	ANAK		0x0004		/* Address Not Acknowledged						*/
-#define	DNAK		0x0008		/* Data Not Acknowledged						*/
-#define	BUFRDERR	0x0010		/* Buffer Read Error							*/
-#define	BUFWRERR	0x0020		/* Buffer Write Error							*/
-#define	SDASEN		0x0040		/* Serial Data Sense							*/
-#define	SCLSEN		0x0080		/* Serial Clock Sense							*/
-#define	BUSBUSY		0x0100		/* Bus Busy Indicator							*/
-
-/* TWI_INT_SRC and TWI_INT_ENABLE Masks						*/
-#define	SINIT		0x0001		/* Slave Transfer Initiated	*/
-#define	SCOMP		0x0002		/* Slave Transfer Complete	*/
-#define	SERR		0x0004		/* Slave Transfer Error		*/
-#define	SOVF		0x0008		/* Slave Overflow			*/
-#define	MCOMP		0x0010		/* Master Transfer Complete	*/
-#define	MERR		0x0020		/* Master Transfer Error	*/
-#define	XMTSERV		0x0040		/* Transmit FIFO Service	*/
-#define	RCVSERV		0x0080		/* Receive FIFO Service		*/
-
-/* TWI_FIFO_CTRL Masks												*/
-#define	XMTFLUSH	0x0001		/* Transmit Buffer Flush			*/
-#define	RCVFLUSH	0x0002		/* Receive Buffer Flush				*/
-#define	XMTINTLEN	0x0004		/* Transmit Buffer Interrupt Length	*/
-#define	RCVINTLEN	0x0008		/* Receive Buffer Interrupt Length	*/
-
-/* TWI_FIFO_STAT Masks															*/
-#define	XMTSTAT		0x0003		/* Transmit FIFO Status							*/
-#define	XMT_EMPTY	0x0000		/* 		Transmit FIFO Empty						*/
-#define	XMT_HALF	0x0001		/* 		Transmit FIFO Has 1 Byte To Write		*/
-#define	XMT_FULL	0x0003		/* 		Transmit FIFO Full (2 Bytes To Write)	*/
-
-#define	RCVSTAT		0x000C		/* Receive FIFO Status							*/
-#define	RCV_EMPTY	0x0000		/* 		Receive FIFO Empty						*/
-#define	RCV_HALF	0x0004		/* 		Receive FIFO Has 1 Byte To Read			*/
-#define	RCV_FULL	0x000C		/* 		Receive FIFO Full (2 Bytes To Read)		*/
-
-
-/*  *******************  PIN CONTROL REGISTER MASKS  ************************/
-/* PORT_MUX Masks															*/
-#define	PJSE			0x0001			/* Port J SPI/SPORT Enable			*/
-#define	PJSE_SPORT		0x0000			/* 		Enable TFS0/DT0PRI			*/
-#define	PJSE_SPI		0x0001			/* 		Enable SPI_SSEL3:2			*/
-
-#define	PJCE(x)			(((x)&0x3)<<1)	/* Port J CAN/SPI/SPORT Enable		*/
-#define	PJCE_SPORT		0x0000			/* 		Enable DR0SEC/DT0SEC		*/
-#define	PJCE_CAN		0x0002			/* 		Enable CAN RX/TX			*/
-#define	PJCE_SPI		0x0004			/* 		Enable SPI_SSEL7			*/
-
-#define	PFDE			0x0008			/* Port F DMA Request Enable		*/
-#define	PFDE_UART		0x0000			/* 		Enable UART0 RX/TX			*/
-#define	PFDE_DMA		0x0008			/* 		Enable DMAR1:0				*/
-
-#define	PFTE			0x0010			/* Port F Timer Enable				*/
-#define	PFTE_UART		0x0000			/*		Enable UART1 RX/TX			*/
-#define	PFTE_TIMER		0x0010			/* 		Enable TMR7:6				*/
-
-#define	PFS6E			0x0020			/* Port F SPI SSEL 6 Enable			*/
-#define	PFS6E_TIMER		0x0000			/*		Enable TMR5					*/
-#define	PFS6E_SPI		0x0020			/* 		Enable SPI_SSEL6			*/
-
-#define	PFS5E			0x0040			/* Port F SPI SSEL 5 Enable			*/
-#define	PFS5E_TIMER		0x0000			/*		Enable TMR4					*/
-#define	PFS5E_SPI		0x0040			/* 		Enable SPI_SSEL5			*/
-
-#define	PFS4E			0x0080			/* Port F SPI SSEL 4 Enable			*/
-#define	PFS4E_TIMER		0x0000			/*		Enable TMR3					*/
-#define	PFS4E_SPI		0x0080			/* 		Enable SPI_SSEL4			*/
-
-#define	PFFE			0x0100			/* Port F PPI Frame Sync Enable		*/
-#define	PFFE_TIMER		0x0000			/* 		Enable TMR2					*/
-#define	PFFE_PPI		0x0100			/* 		Enable PPI FS3				*/
-
-#define	PGSE			0x0200			/* Port G SPORT1 Secondary Enable	*/
-#define	PGSE_PPI		0x0000			/* 		Enable PPI D9:8				*/
-#define	PGSE_SPORT		0x0200			/* 		Enable DR1SEC/DT1SEC		*/
-
-#define	PGRE			0x0400			/* Port G SPORT1 Receive Enable		*/
-#define	PGRE_PPI		0x0000			/* 		Enable PPI D12:10			*/
-#define	PGRE_SPORT		0x0400			/* 		Enable DR1PRI/RFS1/RSCLK1	*/
-
-#define	PGTE			0x0800			/* Port G SPORT1 Transmit Enable	*/
-#define	PGTE_PPI		0x0000			/* 		Enable PPI D15:13			*/
-#define	PGTE_SPORT		0x0800			/* 		Enable DT1PRI/TFS1/TSCLK1	*/
-
-
-/*  ******************  HANDSHAKE DMA (HDMA) MASKS  *********************/
-/* HDMAx_CTL Masks														*/
-#define	HMDMAEN		0x0001	/* Enable Handshake DMA 0/1					*/
-#define	REP			0x0002	/* HDMA Request Polarity					*/
-#define	UTE			0x0004	/* Urgency Threshold Enable					*/
-#define	OIE			0x0010	/* Overflow Interrupt Enable				*/
-#define	BDIE		0x0020	/* Block Done Interrupt Enable				*/
-#define	MBDI		0x0040	/* Mask Block Done IRQ If Pending ECNT		*/
-#define	DRQ			0x0300	/* HDMA Request Type						*/
-#define	DRQ_NONE	0x0000	/* 		No Request							*/
-#define	DRQ_SINGLE	0x0100	/* 		Channels Request Single				*/
-#define	DRQ_MULTI	0x0200	/* 		Channels Request Multi (Default)	*/
-#define	DRQ_URGENT	0x0300	/* 		Channels Request Multi Urgent		*/
-#define	RBC			0x1000	/* Reload BCNT With IBCNT					*/
-#define	PS			0x2000	/* HDMA Pin Status							*/
-#define	OI			0x4000	/* Overflow Interrupt Generated				*/
-#define	BDI			0x8000	/* Block Done Interrupt Generated			*/
-
-/* entry addresses of the user-callable Boot ROM functions */
-
-#define _BOOTROM_RESET 0xEF000000
-#define _BOOTROM_FINAL_INIT 0xEF000002
-#define _BOOTROM_DO_MEMORY_DMA 0xEF000006
-#define _BOOTROM_BOOT_DXE_FLASH 0xEF000008
-#define _BOOTROM_BOOT_DXE_SPI 0xEF00000A
-#define _BOOTROM_BOOT_DXE_TWI 0xEF00000C
-#define _BOOTROM_GET_DXE_ADDRESS_FLASH 0xEF000010
-#define _BOOTROM_GET_DXE_ADDRESS_SPI 0xEF000012
-#define _BOOTROM_GET_DXE_ADDRESS_TWI 0xEF000014
-
-/* Alternate Deprecated Macros Provided For Backwards Code Compatibility */
-#define	PGDE_UART   PFDE_UART
-#define	PGDE_DMA    PFDE_DMA
-#define	CKELOW		SCKELOW
-
-/* HOST Port Registers */
-
-#define                     HOST_CONTROL  0xffc03400   /* HOST Control Register */
-#define                      HOST_STATUS  0xffc03404   /* HOST Status Register */
-#define                     HOST_TIMEOUT  0xffc03408   /* HOST Acknowledge Mode Timeout Register */
-
-/* Counter Registers */
-
-#define                       CNT_CONFIG  0xffc03500   /* Configuration Register */
-#define                        CNT_IMASK  0xffc03504   /* Interrupt Mask Register */
-#define                       CNT_STATUS  0xffc03508   /* Status Register */
-#define                      CNT_COMMAND  0xffc0350c   /* Command Register */
-#define                     CNT_DEBOUNCE  0xffc03510   /* Debounce Register */
-#define                      CNT_COUNTER  0xffc03514   /* Counter Register */
-#define                          CNT_MAX  0xffc03518   /* Maximal Count Register */
-#define                          CNT_MIN  0xffc0351c   /* Minimal Count Register */
-
-/* OTP/FUSE Registers */
-
-#define                      OTP_CONTROL  0xffc03600   /* OTP/Fuse Control Register */
-#define                          OTP_BEN  0xffc03604   /* OTP/Fuse Byte Enable */
-#define                       OTP_STATUS  0xffc03608   /* OTP/Fuse Status */
-#define                       OTP_TIMING  0xffc0360c   /* OTP/Fuse Access Timing */
-
-/* Security Registers */
-
-#define                    SECURE_SYSSWT  0xffc03620   /* Secure System Switches */
-#define                   SECURE_CONTROL  0xffc03624   /* Secure Control */
-#define                    SECURE_STATUS  0xffc03628   /* Secure Status */
-
-/* OTP Read/Write Data Buffer Registers */
-
-#define                        OTP_DATA0  0xffc03680   /* OTP/Fuse Data (OTP_DATA0-3) accesses the fuse read write buffer */
-#define                        OTP_DATA1  0xffc03684   /* OTP/Fuse Data (OTP_DATA0-3) accesses the fuse read write buffer */
-#define                        OTP_DATA2  0xffc03688   /* OTP/Fuse Data (OTP_DATA0-3) accesses the fuse read write buffer */
-#define                        OTP_DATA3  0xffc0368c   /* OTP/Fuse Data (OTP_DATA0-3) accesses the fuse read write buffer */
-
-/* Motor Control PWM Registers */
-
-#define                         PWM_CTRL  0xffc03700   /* PWM Control Register */
-#define                         PWM_STAT  0xffc03704   /* PWM Status Register */
-#define                           PWM_TM  0xffc03708   /* PWM Period Register */
-#define                           PWM_DT  0xffc0370c   /* PWM Dead Time Register */
-#define                         PWM_GATE  0xffc03710   /* PWM Chopping Control */
-#define                          PWM_CHA  0xffc03714   /* PWM Channel A Duty Control */
-#define                          PWM_CHB  0xffc03718   /* PWM Channel B Duty Control */
-#define                          PWM_CHC  0xffc0371c   /* PWM Channel C Duty Control */
-#define                          PWM_SEG  0xffc03720   /* PWM Crossover and Output Enable */
-#define                       PWM_SYNCWT  0xffc03724   /* PWM Sync Pluse Width Control */
-#define                         PWM_CHAL  0xffc03728   /* PWM Channel AL Duty Control (SR mode only) */
-#define                         PWM_CHBL  0xffc0372c   /* PWM Channel BL Duty Control (SR mode only) */
-#define                         PWM_CHCL  0xffc03730   /* PWM Channel CL Duty Control (SR mode only) */
-#define                          PWM_LSI  0xffc03734   /* PWM Low Side Invert (SR mode only) */
-#define                        PWM_STAT2  0xffc03738   /* PWM Status Register 2 */
-
-
-/* ********************************************************** */
-/*     SINGLE BIT MACRO PAIRS (bit mask and negated one)      */
-/*     and MULTI BIT READ MACROS                              */
-/* ********************************************************** */
-
-/* Bit masks for HOST_CONTROL */
-
-#define                   HOST_CNTR_HOST_EN  0x1        /* Host Enable */
-#define                  HOST_CNTR_nHOST_EN  0x0
-#define                  HOST_CNTR_HOST_END  0x2        /* Host Endianess */
-#define                 HOST_CNTR_nHOST_END  0x0
-#define                 HOST_CNTR_DATA_SIZE  0x4        /* Data Size */
-#define                HOST_CNTR_nDATA_SIZE  0x0
-#define                  HOST_CNTR_HOST_RST  0x8        /* Host Reset */
-#define                 HOST_CNTR_nHOST_RST  0x0
-#define                  HOST_CNTR_HRDY_OVR  0x20       /* Host Ready Override */
-#define                 HOST_CNTR_nHRDY_OVR  0x0
-#define                  HOST_CNTR_INT_MODE  0x40       /* Interrupt Mode */
-#define                 HOST_CNTR_nINT_MODE  0x0
-#define                     HOST_CNTR_BT_EN  0x80       /* Bus Timeout Enable */
-#define                   HOST_CNTR_ nBT_EN  0x0
-#define                       HOST_CNTR_EHW  0x100      /* Enable Host Write */
-#define                      HOST_CNTR_nEHW  0x0
-#define                       HOST_CNTR_EHR  0x200      /* Enable Host Read */
-#define                      HOST_CNTR_nEHR  0x0
-#define                       HOST_CNTR_BDR  0x400      /* Burst DMA Requests */
-#define                      HOST_CNTR_nBDR  0x0
-
-/* Bit masks for HOST_STATUS */
-
-#define                     HOST_STAT_READY  0x1        /* DMA Ready */
-#define                    HOST_STAT_nREADY  0x0
-#define                  HOST_STAT_FIFOFULL  0x2        /* FIFO Full */
-#define                 HOST_STAT_nFIFOFULL  0x0
-#define                 HOST_STAT_FIFOEMPTY  0x4        /* FIFO Empty */
-#define                HOST_STAT_nFIFOEMPTY  0x0
-#define                  HOST_STAT_COMPLETE  0x8        /* DMA Complete */
-#define                 HOST_STAT_nCOMPLETE  0x0
-#define                      HOST_STAT_HSHK  0x10       /* Host Handshake */
-#define                     HOST_STAT_nHSHK  0x0
-#define                   HOST_STAT_TIMEOUT  0x20       /* Host Timeout */
-#define                  HOST_STAT_nTIMEOUT  0x0
-#define                      HOST_STAT_HIRQ  0x40       /* Host Interrupt Request */
-#define                     HOST_STAT_nHIRQ  0x0
-#define                HOST_STAT_ALLOW_CNFG  0x80       /* Allow New Configuration */
-#define               HOST_STAT_nALLOW_CNFG  0x0
-#define                   HOST_STAT_DMA_DIR  0x100      /* DMA Direction */
-#define                  HOST_STAT_nDMA_DIR  0x0
-#define                       HOST_STAT_BTE  0x200      /* Bus Timeout Enabled */
-#define                      HOST_STAT_nBTE  0x0
-#define               HOST_STAT_HOSTRD_DONE  0x8000     /* Host Read Completion Interrupt */
-#define              HOST_STAT_nHOSTRD_DONE  0x0
-
-/* Bit masks for HOST_TIMEOUT */
-
-#define             HOST_COUNT_TIMEOUT  0x7ff      /* Host Timeout count */
-
-/* Bit masks for SECURE_SYSSWT */
-
-#define                   EMUDABL  0x1        /* Emulation Disable. */
-#define                  nEMUDABL  0x0
-#define                   RSTDABL  0x2        /* Reset Disable */
-#define                  nRSTDABL  0x0
-#define                   L1IDABL  0x1c       /* L1 Instruction Memory Disable. */
-#define                  L1DADABL  0xe0       /* L1 Data Bank A Memory Disable. */
-#define                  L1DBDABL  0x700      /* L1 Data Bank B Memory Disable. */
-#define                   DMA0OVR  0x800      /* DMA0 Memory Access Override */
-#define                  nDMA0OVR  0x0
-#define                   DMA1OVR  0x1000     /* DMA1 Memory Access Override */
-#define                  nDMA1OVR  0x0
-#define                    EMUOVR  0x4000     /* Emulation Override */
-#define                   nEMUOVR  0x0
-#define                    OTPSEN  0x8000     /* OTP Secrets Enable. */
-#define                   nOTPSEN  0x0
-#define                    L2DABL  0x70000    /* L2 Memory Disable. */
-
-/* Bit masks for SECURE_CONTROL */
-
-#define                   SECURE0  0x1        /* SECURE 0 */
-#define                  nSECURE0  0x0
-#define                   SECURE1  0x2        /* SECURE 1 */
-#define                  nSECURE1  0x0
-#define                   SECURE2  0x4        /* SECURE 2 */
-#define                  nSECURE2  0x0
-#define                   SECURE3  0x8        /* SECURE 3 */
-#define                  nSECURE3  0x0
-
-/* Bit masks for SECURE_STATUS */
-
-#define                   SECMODE  0x3        /* Secured Mode Control State */
-#define                       NMI  0x4        /* Non Maskable Interrupt */
-#define                      nNMI  0x0
-#define                   AFVALID  0x8        /* Authentication Firmware Valid */
-#define                  nAFVALID  0x0
-#define                    AFEXIT  0x10       /* Authentication Firmware Exit */
-#define                   nAFEXIT  0x0
-#define                   SECSTAT  0xe0       /* Secure Status */
-
-
-
-#endif /* _DEF_BF51X_H */
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf518/include/mach/gpio.h linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf518/include/mach/gpio.h
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf518/include/mach/gpio.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf518/include/mach/gpio.h	2011-03-14 21:20:32.000000000 -0400
@@ -55,4 +55,8 @@
 #define PORT_G GPIO_PG0
 #define PORT_H GPIO_PH0
 
+#include <mach-common/ports-f.h>
+#include <mach-common/ports-g.h>
+#include <mach-common/ports-h.h>
+
 #endif /* _MACH_GPIO_H_ */
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf518/include/mach/pll.h linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf518/include/mach/pll.h
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf518/include/mach/pll.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf518/include/mach/pll.h	2011-03-14 21:20:32.000000000 -0400
@@ -1,63 +1 @@
-/*
- * Copyright 2008 Analog Devices Inc.
- *
- * Licensed under the GPL-2 or later
- */
-
-#ifndef _MACH_PLL_H
-#define _MACH_PLL_H
-
-#include <asm/blackfin.h>
-#include <asm/irqflags.h>
-
-/* Writing to PLL_CTL initiates a PLL relock sequence. */
-static __inline__ void bfin_write_PLL_CTL(unsigned int val)
-{
-	unsigned long flags, iwr0, iwr1;
-
-	if (val == bfin_read_PLL_CTL())
-		return;
-
-	flags = hard_local_irq_save();
-	/* Enable the PLL Wakeup bit in SIC IWR */
-	iwr0 = bfin_read32(SIC_IWR0);
-	iwr1 = bfin_read32(SIC_IWR1);
-	/* Only allow PPL Wakeup) */
-	bfin_write32(SIC_IWR0, IWR_ENABLE(0));
-	bfin_write32(SIC_IWR1, 0);
-
-	bfin_write16(PLL_CTL, val);
-	SSYNC();
-	asm("IDLE;");
-
-	bfin_write32(SIC_IWR0, iwr0);
-	bfin_write32(SIC_IWR1, iwr1);
-	hard_local_irq_restore(flags);
-}
-
-/* Writing to VR_CTL initiates a PLL relock sequence. */
-static __inline__ void bfin_write_VR_CTL(unsigned int val)
-{
-	unsigned long flags, iwr0, iwr1;
-
-	if (val == bfin_read_VR_CTL())
-		return;
-
-	flags = hard_local_irq_save();
-	/* Enable the PLL Wakeup bit in SIC IWR */
-	iwr0 = bfin_read32(SIC_IWR0);
-	iwr1 = bfin_read32(SIC_IWR1);
-	/* Only allow PPL Wakeup) */
-	bfin_write32(SIC_IWR0, IWR_ENABLE(0));
-	bfin_write32(SIC_IWR1, 0);
-
-	bfin_write16(VR_CTL, val);
-	SSYNC();
-	asm("IDLE;");
-
-	bfin_write32(SIC_IWR0, iwr0);
-	bfin_write32(SIC_IWR1, iwr1);
-	hard_local_irq_restore(flags);
-}
-
-#endif /* _MACH_PLL_H */
+#include <mach-common/pll.h>
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf527/boards/ad7160eval.c linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf527/boards/ad7160eval.c
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf527/boards/ad7160eval.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf527/boards/ad7160eval.c	2011-03-14 21:20:32.000000000 -0400
@@ -67,6 +67,7 @@ static struct musb_hdrc_config musb_conf
 	 * if it is the case.
 	 */
 	.gpio_vrsel_active	= 1,
+	.clkin          = 24,           /* musb CLKIN in MHZ */
 };
 
 static struct musb_hdrc_platform_data musb_plat = {
@@ -83,7 +84,7 @@ static struct musb_hdrc_platform_data mu
 static u64 musb_dmamask = ~(u32)0;
 
 static struct platform_device musb_device = {
-	.name		= "musb_hdrc",
+	.name		= "musb-blackfin",
 	.id		= 0,
 	.dev = {
 		.dma_mask		= &musb_dmamask,
@@ -419,7 +420,7 @@ static struct resource bfin_uart0_resour
 	},
 };
 
-unsigned short bfin_uart0_peripherals[] = {
+static unsigned short bfin_uart0_peripherals[] = {
 	P_UART0_TX, P_UART0_RX, 0
 };
 
@@ -474,7 +475,7 @@ static struct resource bfin_uart1_resour
 #endif
 };
 
-unsigned short bfin_uart1_peripherals[] = {
+static unsigned short bfin_uart1_peripherals[] = {
 	P_UART1_TX, P_UART1_RX, 0
 };
 
@@ -627,9 +628,9 @@ static struct resource bfin_sport0_uart_
 	},
 };
 
-unsigned short bfin_sport0_peripherals[] = {
+static unsigned short bfin_sport0_peripherals[] = {
 	P_SPORT0_TFS, P_SPORT0_DTPRI, P_SPORT0_TSCLK, P_SPORT0_RFS,
-	P_SPORT0_DRPRI, P_SPORT0_RSCLK, P_SPORT0_DRSEC, P_SPORT0_DTSEC, 0
+	P_SPORT0_DRPRI, P_SPORT0_RSCLK, 0
 };
 
 static struct platform_device bfin_sport0_uart_device = {
@@ -661,9 +662,9 @@ static struct resource bfin_sport1_uart_
 	},
 };
 
-unsigned short bfin_sport1_peripherals[] = {
+static unsigned short bfin_sport1_peripherals[] = {
 	P_SPORT1_TFS, P_SPORT1_DTPRI, P_SPORT1_TSCLK, P_SPORT1_RFS,
-	P_SPORT1_DRPRI, P_SPORT1_RSCLK, P_SPORT1_DRSEC, P_SPORT1_DTSEC, 0
+	P_SPORT1_DRPRI, P_SPORT1_RSCLK, 0
 };
 
 static struct platform_device bfin_sport1_uart_device = {
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf527/boards/cm_bf527.c linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf527/boards/cm_bf527.c
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf527/boards/cm_bf527.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf527/boards/cm_bf527.c	2011-03-14 21:20:32.000000000 -0400
@@ -82,11 +82,13 @@ static struct resource musb_resources[]
 		.start	= IRQ_USB_INT0,
 		.end	= IRQ_USB_INT0,
 		.flags	= IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
+		.name	= "mc"
 	},
 	[2] = {	/* DMA IRQ */
 		.start	= IRQ_USB_DMA,
 		.end	= IRQ_USB_DMA,
 		.flags	= IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
+		.name	= "dma"
 	},
 };
 
@@ -102,6 +104,7 @@ static struct musb_hdrc_config musb_conf
 	 * if it is the case.
 	 */
 	.gpio_vrsel_active	= 1,
+	.clkin          = 24,           /* musb CLKIN in MHZ */
 };
 
 static struct musb_hdrc_platform_data musb_plat = {
@@ -118,7 +121,7 @@ static struct musb_hdrc_platform_data mu
 static u64 musb_dmamask = ~(u32)0;
 
 static struct platform_device musb_device = {
-	.name		= "musb_hdrc",
+	.name		= "musb-blackfin",
 	.id		= 0,
 	.dev = {
 		.dma_mask		= &musb_dmamask,
@@ -612,7 +615,7 @@ static struct resource bfin_uart0_resour
 	},
 };
 
-unsigned short bfin_uart0_peripherals[] = {
+static unsigned short bfin_uart0_peripherals[] = {
 	P_UART0_TX, P_UART0_RX, 0
 };
 
@@ -667,7 +670,7 @@ static struct resource bfin_uart1_resour
 #endif
 };
 
-unsigned short bfin_uart1_peripherals[] = {
+static unsigned short bfin_uart1_peripherals[] = {
 	P_UART1_TX, P_UART1_RX, 0
 };
 
@@ -799,9 +802,9 @@ static struct resource bfin_sport0_uart_
 	},
 };
 
-unsigned short bfin_sport0_peripherals[] = {
+static unsigned short bfin_sport0_peripherals[] = {
 	P_SPORT0_TFS, P_SPORT0_DTPRI, P_SPORT0_TSCLK, P_SPORT0_RFS,
-	P_SPORT0_DRPRI, P_SPORT0_RSCLK, P_SPORT0_DRSEC, P_SPORT0_DTSEC, 0
+	P_SPORT0_DRPRI, P_SPORT0_RSCLK, 0
 };
 
 static struct platform_device bfin_sport0_uart_device = {
@@ -833,9 +836,9 @@ static struct resource bfin_sport1_uart_
 	},
 };
 
-unsigned short bfin_sport1_peripherals[] = {
+static unsigned short bfin_sport1_peripherals[] = {
 	P_SPORT1_TFS, P_SPORT1_DTPRI, P_SPORT1_TSCLK, P_SPORT1_RFS,
-	P_SPORT1_DRPRI, P_SPORT1_RSCLK, P_SPORT1_DRSEC, P_SPORT1_DTSEC, 0
+	P_SPORT1_DRPRI, P_SPORT1_RSCLK, 0
 };
 
 static struct platform_device bfin_sport1_uart_device = {
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf527/boards/ezbrd.c linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf527/boards/ezbrd.c
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf527/boards/ezbrd.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf527/boards/ezbrd.c	2011-03-14 21:20:32.000000000 -0400
@@ -46,11 +46,13 @@ static struct resource musb_resources[]
 		.start	= IRQ_USB_INT0,
 		.end	= IRQ_USB_INT0,
 		.flags	= IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
+		.name	= "mc"
 	},
 	[2] = {	/* DMA IRQ */
 		.start	= IRQ_USB_DMA,
 		.end	= IRQ_USB_DMA,
 		.flags	= IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
+		.name	= "dma"
 	},
 };
 
@@ -66,6 +68,7 @@ static struct musb_hdrc_config musb_conf
 	 * if it is the case.
 	 */
 	.gpio_vrsel_active	= 1,
+	.clkin          = 24,           /* musb CLKIN in MHZ */
 };
 
 static struct musb_hdrc_platform_data musb_plat = {
@@ -82,7 +85,7 @@ static struct musb_hdrc_platform_data mu
 static u64 musb_dmamask = ~(u32)0;
 
 static struct platform_device musb_device = {
-	.name		= "musb_hdrc",
+	.name		= "musb-blackfin",
 	.id		= 0,
 	.dev = {
 		.dma_mask		= &musb_dmamask,
@@ -497,7 +500,7 @@ static struct resource bfin_uart0_resour
 	},
 };
 
-unsigned short bfin_uart0_peripherals[] = {
+static unsigned short bfin_uart0_peripherals[] = {
 	P_UART0_TX, P_UART0_RX, 0
 };
 
@@ -552,7 +555,7 @@ static struct resource bfin_uart1_resour
 #endif
 };
 
-unsigned short bfin_uart1_peripherals[] = {
+static unsigned short bfin_uart1_peripherals[] = {
 	P_UART1_TX, P_UART1_RX, 0
 };
 
@@ -679,9 +682,9 @@ static struct resource bfin_sport0_uart_
 	},
 };
 
-unsigned short bfin_sport0_peripherals[] = {
+static unsigned short bfin_sport0_peripherals[] = {
 	P_SPORT0_TFS, P_SPORT0_DTPRI, P_SPORT0_TSCLK, P_SPORT0_RFS,
-	P_SPORT0_DRPRI, P_SPORT0_RSCLK, P_SPORT0_DRSEC, P_SPORT0_DTSEC, 0
+	P_SPORT0_DRPRI, P_SPORT0_RSCLK, 0
 };
 
 static struct platform_device bfin_sport0_uart_device = {
@@ -713,9 +716,9 @@ static struct resource bfin_sport1_uart_
 	},
 };
 
-unsigned short bfin_sport1_peripherals[] = {
+static unsigned short bfin_sport1_peripherals[] = {
 	P_SPORT1_TFS, P_SPORT1_DTPRI, P_SPORT1_TSCLK, P_SPORT1_RFS,
-	P_SPORT1_DRPRI, P_SPORT1_RSCLK, P_SPORT1_DRSEC, P_SPORT1_DTSEC, 0
+	P_SPORT1_DRPRI, P_SPORT1_RSCLK, 0
 };
 
 static struct platform_device bfin_sport1_uart_device = {
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf527/boards/ezkit.c linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf527/boards/ezkit.c
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf527/boards/ezkit.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf527/boards/ezkit.c	2011-03-14 21:20:32.000000000 -0400
@@ -86,11 +86,13 @@ static struct resource musb_resources[]
 		.start	= IRQ_USB_INT0,
 		.end	= IRQ_USB_INT0,
 		.flags	= IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
+		.name	= "mc"
 	},
 	[2] = {	/* DMA IRQ */
 		.start	= IRQ_USB_DMA,
 		.end	= IRQ_USB_DMA,
 		.flags	= IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
+		.name	= "dma"
 	},
 };
 
@@ -106,6 +108,7 @@ static struct musb_hdrc_config musb_conf
 	 * if it is the case.
 	 */
 	.gpio_vrsel_active	= 1,
+	.clkin          = 24,           /* musb CLKIN in MHZ */
 };
 
 static struct musb_hdrc_platform_data musb_plat = {
@@ -122,7 +125,7 @@ static struct musb_hdrc_platform_data mu
 static u64 musb_dmamask = ~(u32)0;
 
 static struct platform_device musb_device = {
-	.name		= "musb_hdrc",
+	.name		= "musb-blackfin",
 	.id		= 0,
 	.dev = {
 		.dma_mask		= &musb_dmamask,
@@ -706,7 +709,7 @@ static struct resource bfin_uart0_resour
 	},
 };
 
-unsigned short bfin_uart0_peripherals[] = {
+static unsigned short bfin_uart0_peripherals[] = {
 	P_UART0_TX, P_UART0_RX, 0
 };
 
@@ -761,7 +764,7 @@ static struct resource bfin_uart1_resour
 #endif
 };
 
-unsigned short bfin_uart1_peripherals[] = {
+static unsigned short bfin_uart1_peripherals[] = {
 	P_UART1_TX, P_UART1_RX, 0
 };
 
@@ -960,6 +963,11 @@ static struct i2c_board_info __initdata
 		I2C_BOARD_INFO("ad5252", 0x2f),
 	},
 #endif
+#if defined(CONFIG_SND_SOC_ADAU1373) || defined(CONFIG_SND_SOC_ADAU1373_MODULE)
+	{
+		I2C_BOARD_INFO("adau1373", 0x1A),
+	},
+#endif
 };
 
 #if defined(CONFIG_SERIAL_BFIN_SPORT) || defined(CONFIG_SERIAL_BFIN_SPORT_MODULE)
@@ -982,9 +990,9 @@ static struct resource bfin_sport0_uart_
 	},
 };
 
-unsigned short bfin_sport0_peripherals[] = {
+static unsigned short bfin_sport0_peripherals[] = {
 	P_SPORT0_TFS, P_SPORT0_DTPRI, P_SPORT0_TSCLK, P_SPORT0_RFS,
-	P_SPORT0_DRPRI, P_SPORT0_RSCLK, P_SPORT0_DRSEC, P_SPORT0_DTSEC, 0
+	P_SPORT0_DRPRI, P_SPORT0_RSCLK, 0
 };
 
 static struct platform_device bfin_sport0_uart_device = {
@@ -1016,9 +1024,9 @@ static struct resource bfin_sport1_uart_
 	},
 };
 
-unsigned short bfin_sport1_peripherals[] = {
+static unsigned short bfin_sport1_peripherals[] = {
 	P_SPORT1_TFS, P_SPORT1_DTPRI, P_SPORT1_TSCLK, P_SPORT1_RFS,
-	P_SPORT1_DRPRI, P_SPORT1_RSCLK, P_SPORT1_DRSEC, P_SPORT1_DTSEC, 0
+	P_SPORT1_DRPRI, P_SPORT1_RSCLK, 0
 };
 
 static struct platform_device bfin_sport1_uart_device = {
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf527/boards/tll6527m.c linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf527/boards/tll6527m.c
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf527/boards/tll6527m.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf527/boards/tll6527m.c	2011-03-14 21:20:32.000000000 -0400
@@ -91,7 +91,7 @@ static struct musb_hdrc_platform_data mu
 static u64 musb_dmamask = ~(u32)0;
 
 static struct platform_device musb_device = {
-	.name		= "musb_hdrc",
+	.name		= "musb-blackfin",
 	.id		= 0,
 	.dev = {
 		.dma_mask		= &musb_dmamask,
@@ -193,7 +193,7 @@ static unsigned gpio_addr_inputs[] = {
 	GPIO_PG1, GPIO_PH9, GPIO_PH10
 };
 
-static struct gpio_decoder_platfrom_data spi_decoded_cs = {
+static struct gpio_decoder_platform_data spi_decoded_cs = {
 	.base		= EXP_GPIO_SPISEL_BASE,
 	.input_addrs	= gpio_addr_inputs,
 	.nr_input_addrs = ARRAY_SIZE(gpio_addr_inputs),
@@ -586,7 +586,7 @@ static struct resource bfin_uart0_resour
 	},
 };
 
-unsigned short bfin_uart0_peripherals[] = {
+static unsigned short bfin_uart0_peripherals[] = {
 	P_UART0_TX, P_UART0_RX, 0
 };
 
@@ -642,7 +642,7 @@ static struct resource bfin_uart1_resour
 #endif
 };
 
-unsigned short bfin_uart1_peripherals[] = {
+static unsigned short bfin_uart1_peripherals[] = {
 	P_UART1_TX, P_UART1_RX, 0
 };
 
@@ -799,9 +799,9 @@ static struct resource bfin_sport0_uart_
 	},
 };
 
-unsigned short bfin_sport0_peripherals[] = {
+static unsigned short bfin_sport0_peripherals[] = {
 	P_SPORT0_TFS, P_SPORT0_DTPRI, P_SPORT0_TSCLK, P_SPORT0_RFS,
-	P_SPORT0_DRPRI, P_SPORT0_RSCLK, P_SPORT0_DRSEC, P_SPORT0_DTSEC, 0
+	P_SPORT0_DRPRI, P_SPORT0_RSCLK, 0
 };
 
 static struct platform_device bfin_sport0_uart_device = {
@@ -834,9 +834,9 @@ static struct resource bfin_sport1_uart_
 	},
 };
 
-unsigned short bfin_sport1_peripherals[] = {
+static unsigned short bfin_sport1_peripherals[] = {
 	P_SPORT1_TFS, P_SPORT1_DTPRI, P_SPORT1_TSCLK, P_SPORT1_RFS,
-	P_SPORT1_DRPRI, P_SPORT1_RSCLK, P_SPORT1_DRSEC, P_SPORT1_DTSEC, 0
+	P_SPORT1_DRPRI, P_SPORT1_RSCLK, 0
 };
 
 static struct platform_device bfin_sport1_uart_device = {
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf527/dma.c linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf527/dma.c
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf527/dma.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf527/dma.c	2011-03-14 21:20:32.000000000 -0400
@@ -11,7 +11,7 @@
 #include <asm/blackfin.h>
 #include <asm/dma.h>
 
-struct dma_register *dma_io_base_addr[MAX_DMA_CHANNELS] = {
+struct dma_register * const dma_io_base_addr[MAX_DMA_CHANNELS] = {
 	(struct dma_register *) DMA0_NEXT_DESC_PTR,
 	(struct dma_register *) DMA1_NEXT_DESC_PTR,
 	(struct dma_register *) DMA2_NEXT_DESC_PTR,
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf527/include/mach/bfin_serial_5xx.h linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf527/include/mach/bfin_serial_5xx.h
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf527/include/mach/bfin_serial_5xx.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf527/include/mach/bfin_serial_5xx.h	2011-03-14 21:20:32.000000000 -0400
@@ -4,36 +4,9 @@
  * Licensed under the GPL-2 or later
  */
 
-#include <linux/serial.h>
 #include <asm/dma.h>
 #include <asm/portmux.h>
 
-#define UART_GET_CHAR(uart)     bfin_read16(((uart)->port.membase + OFFSET_RBR))
-#define UART_GET_DLL(uart)	bfin_read16(((uart)->port.membase + OFFSET_DLL))
-#define UART_GET_IER(uart)      bfin_read16(((uart)->port.membase + OFFSET_IER))
-#define UART_GET_DLH(uart)	bfin_read16(((uart)->port.membase + OFFSET_DLH))
-#define UART_GET_IIR(uart)      bfin_read16(((uart)->port.membase + OFFSET_IIR))
-#define UART_GET_LCR(uart)      bfin_read16(((uart)->port.membase + OFFSET_LCR))
-#define UART_GET_GCTL(uart)     bfin_read16(((uart)->port.membase + OFFSET_GCTL))
-
-#define UART_PUT_CHAR(uart, v)   bfin_write16(((uart)->port.membase + OFFSET_THR), v)
-#define UART_PUT_DLL(uart, v)    bfin_write16(((uart)->port.membase + OFFSET_DLL), v)
-#define UART_PUT_IER(uart, v)    bfin_write16(((uart)->port.membase + OFFSET_IER), v)
-#define UART_SET_IER(uart, v)    UART_PUT_IER(uart, UART_GET_IER(uart) | (v))
-#define UART_CLEAR_IER(uart, v)  UART_PUT_IER(uart, UART_GET_IER(uart) & ~(v))
-#define UART_PUT_DLH(uart, v)    bfin_write16(((uart)->port.membase + OFFSET_DLH), v)
-#define UART_PUT_LCR(uart, v)    bfin_write16(((uart)->port.membase + OFFSET_LCR), v)
-#define UART_PUT_GCTL(uart, v)   bfin_write16(((uart)->port.membase + OFFSET_GCTL), v)
-
-#define UART_SET_DLAB(uart)     do { UART_PUT_LCR(uart, UART_GET_LCR(uart) | DLAB); SSYNC(); } while (0)
-#define UART_CLEAR_DLAB(uart)   do { UART_PUT_LCR(uart, UART_GET_LCR(uart) & ~DLAB); SSYNC(); } while (0)
-
-#define UART_GET_CTS(x) gpio_get_value(x->cts_pin)
-#define UART_DISABLE_RTS(x) gpio_set_value(x->rts_pin, 1)
-#define UART_ENABLE_RTS(x) gpio_set_value(x->rts_pin, 0)
-#define UART_ENABLE_INTS(x, v) UART_PUT_IER(x, v)
-#define UART_DISABLE_INTS(x) UART_PUT_IER(x, 0)
-
 #if defined(CONFIG_BFIN_UART0_CTSRTS) || defined(CONFIG_BFIN_UART1_CTSRTS)
 # define CONFIG_SERIAL_BFIN_CTSRTS
 
@@ -54,50 +27,6 @@
 # endif
 #endif
 
-#define BFIN_UART_TX_FIFO_SIZE	2
-
-/*
- * The pin configuration is different from schematic
- */
-struct bfin_serial_port {
-	struct uart_port port;
-	unsigned int old_status;
-	int status_irq;
-	unsigned int lsr;
-#ifdef CONFIG_SERIAL_BFIN_DMA
-	int tx_done;
-	int tx_count;
-	struct circ_buf rx_dma_buf;
-	struct timer_list rx_dma_timer;
-	int rx_dma_nrows;
-	unsigned int tx_dma_channel;
-	unsigned int rx_dma_channel;
-	struct work_struct tx_dma_workqueue;
-#endif
-#ifdef CONFIG_SERIAL_BFIN_CTSRTS
-	struct timer_list cts_timer;
-	int cts_pin;
-	int rts_pin;
-#endif
-};
-
-/* The hardware clears the LSR bits upon read, so we need to cache
- * some of the more fun bits in software so they don't get lost
- * when checking the LSR in other code paths (TX).
- */
-static inline unsigned int UART_GET_LSR(struct bfin_serial_port *uart)
-{
-	unsigned int lsr = bfin_read16(uart->port.membase + OFFSET_LSR);
-	uart->lsr |= (lsr & (BI|FE|PE|OE));
-	return lsr | uart->lsr;
-}
-
-static inline void UART_CLEAR_LSR(struct bfin_serial_port *uart)
-{
-	uart->lsr = 0;
-	bfin_write16(uart->port.membase + OFFSET_LSR, -1);
-}
-
 struct bfin_serial_res {
 	unsigned long uart_base_addr;
 	int uart_irq;
@@ -146,3 +75,5 @@ struct bfin_serial_res bfin_serial_resou
 };
 
 #define DRIVER_NAME "bfin-uart"
+
+#include <asm/bfin_serial.h>
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf527/include/mach/bfin_serial.h linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf527/include/mach/bfin_serial.h
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf527/include/mach/bfin_serial.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf527/include/mach/bfin_serial.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,14 @@
+/*
+ * mach/bfin_serial.h - Blackfin UART/Serial definitions
+ *
+ * Copyright 2006-2010 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#ifndef __BFIN_MACH_SERIAL_H__
+#define __BFIN_MACH_SERIAL_H__
+
+#define BFIN_UART_NR_PORTS	2
+
+#endif
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf527/include/mach/blackfin.h linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf527/include/mach/blackfin.h
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf527/include/mach/blackfin.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf527/include/mach/blackfin.h	2011-03-14 21:20:32.000000000 -0400
@@ -1,49 +1,37 @@
 /*
- * Copyright 2007-2009 Analog Devices Inc.
+ * Copyright 2007-2010 Analog Devices Inc.
  *
- * Licensed under the GPL-2 or later
+ * Licensed under the GPL-2 or later.
  */
 
 #ifndef _MACH_BLACKFIN_H_
 #define _MACH_BLACKFIN_H_
 
 #include "bf527.h"
-#include "defBF522.h"
 #include "anomaly.h"
 
-#if defined(CONFIG_BF527) || defined(CONFIG_BF526)
-#include "defBF527.h"
+#include <asm/def_LPBlackfin.h>
+#if defined(CONFIG_BF523) || defined(CONFIG_BF522)
+# include "defBF522.h"
 #endif
-
 #if defined(CONFIG_BF525) || defined(CONFIG_BF524)
-#include "defBF525.h"
+# include "defBF525.h"
 #endif
-
-#if !defined(__ASSEMBLY__)
-#include "cdefBF522.h"
-
 #if defined(CONFIG_BF527) || defined(CONFIG_BF526)
-#include "cdefBF527.h"
+# include "defBF527.h"
 #endif
 
-#if defined(CONFIG_BF525) || defined(CONFIG_BF524)
-#include "cdefBF525.h"
-#endif
+#if !defined(__ASSEMBLY__)
+# include <asm/cdef_LPBlackfin.h>
+# if defined(CONFIG_BF523) || defined(CONFIG_BF522)
+#  include "cdefBF522.h"
+# endif
+# if defined(CONFIG_BF525) || defined(CONFIG_BF524)
+#  include "cdefBF525.h"
+# endif
+# if defined(CONFIG_BF527) || defined(CONFIG_BF526)
+#  include "cdefBF527.h"
+# endif
 #endif
 
-#define BFIN_UART_NR_PORTS	2
-
-#define OFFSET_THR              0x00	/* Transmit Holding register            */
-#define OFFSET_RBR              0x00	/* Receive Buffer register              */
-#define OFFSET_DLL              0x00	/* Divisor Latch (Low-Byte)             */
-#define OFFSET_IER              0x04	/* Interrupt Enable Register            */
-#define OFFSET_DLH              0x04	/* Divisor Latch (High-Byte)            */
-#define OFFSET_IIR              0x08	/* Interrupt Identification Register    */
-#define OFFSET_LCR              0x0C	/* Line Control Register                */
-#define OFFSET_MCR              0x10	/* Modem Control Register               */
-#define OFFSET_LSR              0x14	/* Line Status Register                 */
-#define OFFSET_MSR              0x18	/* Modem Status Register                */
-#define OFFSET_SCR              0x1C	/* SCR Scratch Register                 */
-#define OFFSET_GCTL             0x24	/* Global Control Register              */
-
 #endif
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf527/include/mach/cdefBF522.h linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf527/include/mach/cdefBF522.h
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf527/include/mach/cdefBF522.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf527/include/mach/cdefBF522.h	2011-03-14 21:20:32.000000000 -0400
@@ -1,21 +1,1095 @@
 /*
- * Copyright 2007-2008 Analog Devices Inc.
+ * Copyright 2007-2010 Analog Devices Inc.
  *
- * Licensed under the GPL-2 or later
+ * Licensed under the GPL-2 or later.
  */
 
 #ifndef _CDEF_BF522_H
 #define _CDEF_BF522_H
 
-/* include all Core registers and bit definitions */
-#include "defBF522.h"
+/* Clock and System Control	(0xFFC00000 - 0xFFC000FF)								*/
+#define bfin_read_PLL_CTL()			bfin_read16(PLL_CTL)
+#define bfin_read_PLL_DIV()			bfin_read16(PLL_DIV)
+#define bfin_write_PLL_DIV(val)			bfin_write16(PLL_DIV, val)
+#define bfin_read_VR_CTL()			bfin_read16(VR_CTL)
+#define bfin_read_PLL_STAT()			bfin_read16(PLL_STAT)
+#define bfin_write_PLL_STAT(val)		bfin_write16(PLL_STAT, val)
+#define bfin_read_PLL_LOCKCNT()			bfin_read16(PLL_LOCKCNT)
+#define bfin_write_PLL_LOCKCNT(val)		bfin_write16(PLL_LOCKCNT, val)
+#define bfin_read_CHIPID()			bfin_read32(CHIPID)
+#define bfin_write_CHIPID(val)			bfin_write32(CHIPID, val)
 
-/* include core specific register pointer definitions */
-#include <asm/cdef_LPBlackfin.h>
 
-/* SYSTEM & MMR ADDRESS DEFINITIONS FOR ADSP-BF522 */
+/* System Interrupt Controller (0xFFC00100 - 0xFFC001FF)							*/
+#define bfin_read_SWRST()			bfin_read16(SWRST)
+#define bfin_write_SWRST(val)			bfin_write16(SWRST, val)
+#define bfin_read_SYSCR()			bfin_read16(SYSCR)
+#define bfin_write_SYSCR(val)			bfin_write16(SYSCR, val)
 
-/* include cdefBF52x_base.h for the set of #defines that are common to all ADSP-BF52x processors */
-#include "cdefBF52x_base.h"
+#define bfin_read_SIC_RVECT()			bfin_read32(SIC_RVECT)
+#define bfin_write_SIC_RVECT(val)		bfin_write32(SIC_RVECT, val)
+#define bfin_read_SIC_IMASK0()			bfin_read32(SIC_IMASK0)
+#define bfin_write_SIC_IMASK0(val)		bfin_write32(SIC_IMASK0, val)
+#define bfin_read_SIC_IMASK(x)			bfin_read32(SIC_IMASK0 + (x << 6))
+#define bfin_write_SIC_IMASK(x, val)		bfin_write32((SIC_IMASK0 + (x << 6)), val)
+
+#define bfin_read_SIC_IAR0()			bfin_read32(SIC_IAR0)
+#define bfin_write_SIC_IAR0(val)		bfin_write32(SIC_IAR0, val)
+#define bfin_read_SIC_IAR1()			bfin_read32(SIC_IAR1)
+#define bfin_write_SIC_IAR1(val)		bfin_write32(SIC_IAR1, val)
+#define bfin_read_SIC_IAR2()			bfin_read32(SIC_IAR2)
+#define bfin_write_SIC_IAR2(val)		bfin_write32(SIC_IAR2, val)
+#define bfin_read_SIC_IAR3()			bfin_read32(SIC_IAR3)
+#define bfin_write_SIC_IAR3(val)		bfin_write32(SIC_IAR3, val)
+
+#define bfin_read_SIC_ISR0()			bfin_read32(SIC_ISR0)
+#define bfin_write_SIC_ISR0(val)		bfin_write32(SIC_ISR0, val)
+#define bfin_read_SIC_ISR(x)			bfin_read32(SIC_ISR0 + (x << 6))
+#define bfin_write_SIC_ISR(x, val)		bfin_write32((SIC_ISR0 + (x << 6)), val)
+
+#define bfin_read_SIC_IWR0()			bfin_read32(SIC_IWR0)
+#define bfin_write_SIC_IWR0(val)		bfin_write32(SIC_IWR0, val)
+#define bfin_read_SIC_IWR(x)			bfin_read32(SIC_IWR0 + (x << 6))
+#define bfin_write_SIC_IWR(x, val)		bfin_write32((SIC_IWR0 + (x << 6)), val)
+
+/* SIC Additions to ADSP-BF52x (0xFFC0014C - 0xFFC00162) */
+
+#define bfin_read_SIC_IMASK1()			bfin_read32(SIC_IMASK1)
+#define bfin_write_SIC_IMASK1(val)		bfin_write32(SIC_IMASK1, val)
+#define bfin_read_SIC_IAR4()			bfin_read32(SIC_IAR4)
+#define bfin_write_SIC_IAR4(val)		bfin_write32(SIC_IAR4, val)
+#define bfin_read_SIC_IAR5()			bfin_read32(SIC_IAR5)
+#define bfin_write_SIC_IAR5(val)		bfin_write32(SIC_IAR5, val)
+#define bfin_read_SIC_IAR6()			bfin_read32(SIC_IAR6)
+#define bfin_write_SIC_IAR6(val)		bfin_write32(SIC_IAR6, val)
+#define bfin_read_SIC_IAR7()			bfin_read32(SIC_IAR7)
+#define bfin_write_SIC_IAR7(val)		bfin_write32(SIC_IAR7, val)
+#define bfin_read_SIC_ISR1()			bfin_read32(SIC_ISR1)
+#define bfin_write_SIC_ISR1(val)		bfin_write32(SIC_ISR1, val)
+#define bfin_read_SIC_IWR1()			bfin_read32(SIC_IWR1)
+#define bfin_write_SIC_IWR1(val)		bfin_write32(SIC_IWR1, val)
+
+/* Watchdog Timer		(0xFFC00200 - 0xFFC002FF)									*/
+#define bfin_read_WDOG_CTL()			bfin_read16(WDOG_CTL)
+#define bfin_write_WDOG_CTL(val)		bfin_write16(WDOG_CTL, val)
+#define bfin_read_WDOG_CNT()			bfin_read32(WDOG_CNT)
+#define bfin_write_WDOG_CNT(val)		bfin_write32(WDOG_CNT, val)
+#define bfin_read_WDOG_STAT()			bfin_read32(WDOG_STAT)
+#define bfin_write_WDOG_STAT(val)		bfin_write32(WDOG_STAT, val)
+
+
+/* Real Time Clock		(0xFFC00300 - 0xFFC003FF)									*/
+#define bfin_read_RTC_STAT()			bfin_read32(RTC_STAT)
+#define bfin_write_RTC_STAT(val)		bfin_write32(RTC_STAT, val)
+#define bfin_read_RTC_ICTL()			bfin_read16(RTC_ICTL)
+#define bfin_write_RTC_ICTL(val)		bfin_write16(RTC_ICTL, val)
+#define bfin_read_RTC_ISTAT()			bfin_read16(RTC_ISTAT)
+#define bfin_write_RTC_ISTAT(val)		bfin_write16(RTC_ISTAT, val)
+#define bfin_read_RTC_SWCNT()			bfin_read16(RTC_SWCNT)
+#define bfin_write_RTC_SWCNT(val)		bfin_write16(RTC_SWCNT, val)
+#define bfin_read_RTC_ALARM()			bfin_read32(RTC_ALARM)
+#define bfin_write_RTC_ALARM(val)		bfin_write32(RTC_ALARM, val)
+#define bfin_read_RTC_FAST()			bfin_read16(RTC_FAST)
+#define bfin_write_RTC_FAST(val)		bfin_write16(RTC_FAST, val)
+#define bfin_read_RTC_PREN()			bfin_read16(RTC_PREN)
+#define bfin_write_RTC_PREN(val)		bfin_write16(RTC_PREN, val)
+
+
+/* UART0 Controller		(0xFFC00400 - 0xFFC004FF)									*/
+#define bfin_read_UART0_THR()			bfin_read16(UART0_THR)
+#define bfin_write_UART0_THR(val)		bfin_write16(UART0_THR, val)
+#define bfin_read_UART0_RBR()			bfin_read16(UART0_RBR)
+#define bfin_write_UART0_RBR(val)		bfin_write16(UART0_RBR, val)
+#define bfin_read_UART0_DLL()			bfin_read16(UART0_DLL)
+#define bfin_write_UART0_DLL(val)		bfin_write16(UART0_DLL, val)
+#define bfin_read_UART0_IER()			bfin_read16(UART0_IER)
+#define bfin_write_UART0_IER(val)		bfin_write16(UART0_IER, val)
+#define bfin_read_UART0_DLH()			bfin_read16(UART0_DLH)
+#define bfin_write_UART0_DLH(val)		bfin_write16(UART0_DLH, val)
+#define bfin_read_UART0_IIR()			bfin_read16(UART0_IIR)
+#define bfin_write_UART0_IIR(val)		bfin_write16(UART0_IIR, val)
+#define bfin_read_UART0_LCR()			bfin_read16(UART0_LCR)
+#define bfin_write_UART0_LCR(val)		bfin_write16(UART0_LCR, val)
+#define bfin_read_UART0_MCR()			bfin_read16(UART0_MCR)
+#define bfin_write_UART0_MCR(val)		bfin_write16(UART0_MCR, val)
+#define bfin_read_UART0_LSR()			bfin_read16(UART0_LSR)
+#define bfin_write_UART0_LSR(val)		bfin_write16(UART0_LSR, val)
+#define bfin_read_UART0_MSR()			bfin_read16(UART0_MSR)
+#define bfin_write_UART0_MSR(val)		bfin_write16(UART0_MSR, val)
+#define bfin_read_UART0_SCR()			bfin_read16(UART0_SCR)
+#define bfin_write_UART0_SCR(val)		bfin_write16(UART0_SCR, val)
+#define bfin_read_UART0_GCTL()			bfin_read16(UART0_GCTL)
+#define bfin_write_UART0_GCTL(val)		bfin_write16(UART0_GCTL, val)
+
+
+/* SPI Controller		(0xFFC00500 - 0xFFC005FF)									*/
+#define bfin_read_SPI_CTL()			bfin_read16(SPI_CTL)
+#define bfin_write_SPI_CTL(val)			bfin_write16(SPI_CTL, val)
+#define bfin_read_SPI_FLG()			bfin_read16(SPI_FLG)
+#define bfin_write_SPI_FLG(val)			bfin_write16(SPI_FLG, val)
+#define bfin_read_SPI_STAT()			bfin_read16(SPI_STAT)
+#define bfin_write_SPI_STAT(val)		bfin_write16(SPI_STAT, val)
+#define bfin_read_SPI_TDBR()			bfin_read16(SPI_TDBR)
+#define bfin_write_SPI_TDBR(val)		bfin_write16(SPI_TDBR, val)
+#define bfin_read_SPI_RDBR()			bfin_read16(SPI_RDBR)
+#define bfin_write_SPI_RDBR(val)		bfin_write16(SPI_RDBR, val)
+#define bfin_read_SPI_BAUD()			bfin_read16(SPI_BAUD)
+#define bfin_write_SPI_BAUD(val)		bfin_write16(SPI_BAUD, val)
+#define bfin_read_SPI_SHADOW()			bfin_read16(SPI_SHADOW)
+#define bfin_write_SPI_SHADOW(val)		bfin_write16(SPI_SHADOW, val)
+
+
+/* TIMER0-7 Registers		(0xFFC00600 - 0xFFC006FF)								*/
+#define bfin_read_TIMER0_CONFIG()		bfin_read16(TIMER0_CONFIG)
+#define bfin_write_TIMER0_CONFIG(val)		bfin_write16(TIMER0_CONFIG, val)
+#define bfin_read_TIMER0_COUNTER()		bfin_read32(TIMER0_COUNTER)
+#define bfin_write_TIMER0_COUNTER(val)		bfin_write32(TIMER0_COUNTER, val)
+#define bfin_read_TIMER0_PERIOD()		bfin_read32(TIMER0_PERIOD)
+#define bfin_write_TIMER0_PERIOD(val)		bfin_write32(TIMER0_PERIOD, val)
+#define bfin_read_TIMER0_WIDTH()		bfin_read32(TIMER0_WIDTH)
+#define bfin_write_TIMER0_WIDTH(val)		bfin_write32(TIMER0_WIDTH, val)
+
+#define bfin_read_TIMER1_CONFIG()		bfin_read16(TIMER1_CONFIG)
+#define bfin_write_TIMER1_CONFIG(val)		bfin_write16(TIMER1_CONFIG, val)
+#define bfin_read_TIMER1_COUNTER()		bfin_read32(TIMER1_COUNTER)
+#define bfin_write_TIMER1_COUNTER(val)		bfin_write32(TIMER1_COUNTER, val)
+#define bfin_read_TIMER1_PERIOD()		bfin_read32(TIMER1_PERIOD)
+#define bfin_write_TIMER1_PERIOD(val)		bfin_write32(TIMER1_PERIOD, val)
+#define bfin_read_TIMER1_WIDTH()		bfin_read32(TIMER1_WIDTH)
+#define bfin_write_TIMER1_WIDTH(val)		bfin_write32(TIMER1_WIDTH, val)
+
+#define bfin_read_TIMER2_CONFIG()		bfin_read16(TIMER2_CONFIG)
+#define bfin_write_TIMER2_CONFIG(val)		bfin_write16(TIMER2_CONFIG, val)
+#define bfin_read_TIMER2_COUNTER()		bfin_read32(TIMER2_COUNTER)
+#define bfin_write_TIMER2_COUNTER(val)		bfin_write32(TIMER2_COUNTER, val)
+#define bfin_read_TIMER2_PERIOD()		bfin_read32(TIMER2_PERIOD)
+#define bfin_write_TIMER2_PERIOD(val)		bfin_write32(TIMER2_PERIOD, val)
+#define bfin_read_TIMER2_WIDTH()		bfin_read32(TIMER2_WIDTH)
+#define bfin_write_TIMER2_WIDTH(val)		bfin_write32(TIMER2_WIDTH, val)
+
+#define bfin_read_TIMER3_CONFIG()		bfin_read16(TIMER3_CONFIG)
+#define bfin_write_TIMER3_CONFIG(val)		bfin_write16(TIMER3_CONFIG, val)
+#define bfin_read_TIMER3_COUNTER()		bfin_read32(TIMER3_COUNTER)
+#define bfin_write_TIMER3_COUNTER(val)		bfin_write32(TIMER3_COUNTER, val)
+#define bfin_read_TIMER3_PERIOD()		bfin_read32(TIMER3_PERIOD)
+#define bfin_write_TIMER3_PERIOD(val)		bfin_write32(TIMER3_PERIOD, val)
+#define bfin_read_TIMER3_WIDTH()		bfin_read32(TIMER3_WIDTH)
+#define bfin_write_TIMER3_WIDTH(val)		bfin_write32(TIMER3_WIDTH, val)
+
+#define bfin_read_TIMER4_CONFIG()		bfin_read16(TIMER4_CONFIG)
+#define bfin_write_TIMER4_CONFIG(val)		bfin_write16(TIMER4_CONFIG, val)
+#define bfin_read_TIMER4_COUNTER()		bfin_read32(TIMER4_COUNTER)
+#define bfin_write_TIMER4_COUNTER(val)		bfin_write32(TIMER4_COUNTER, val)
+#define bfin_read_TIMER4_PERIOD()		bfin_read32(TIMER4_PERIOD)
+#define bfin_write_TIMER4_PERIOD(val)		bfin_write32(TIMER4_PERIOD, val)
+#define bfin_read_TIMER4_WIDTH()		bfin_read32(TIMER4_WIDTH)
+#define bfin_write_TIMER4_WIDTH(val)		bfin_write32(TIMER4_WIDTH, val)
+
+#define bfin_read_TIMER5_CONFIG()		bfin_read16(TIMER5_CONFIG)
+#define bfin_write_TIMER5_CONFIG(val)		bfin_write16(TIMER5_CONFIG, val)
+#define bfin_read_TIMER5_COUNTER()		bfin_read32(TIMER5_COUNTER)
+#define bfin_write_TIMER5_COUNTER(val)		bfin_write32(TIMER5_COUNTER, val)
+#define bfin_read_TIMER5_PERIOD()		bfin_read32(TIMER5_PERIOD)
+#define bfin_write_TIMER5_PERIOD(val)		bfin_write32(TIMER5_PERIOD, val)
+#define bfin_read_TIMER5_WIDTH()		bfin_read32(TIMER5_WIDTH)
+#define bfin_write_TIMER5_WIDTH(val)		bfin_write32(TIMER5_WIDTH, val)
+
+#define bfin_read_TIMER6_CONFIG()		bfin_read16(TIMER6_CONFIG)
+#define bfin_write_TIMER6_CONFIG(val)		bfin_write16(TIMER6_CONFIG, val)
+#define bfin_read_TIMER6_COUNTER()		bfin_read32(TIMER6_COUNTER)
+#define bfin_write_TIMER6_COUNTER(val)		bfin_write32(TIMER6_COUNTER, val)
+#define bfin_read_TIMER6_PERIOD()		bfin_read32(TIMER6_PERIOD)
+#define bfin_write_TIMER6_PERIOD(val)		bfin_write32(TIMER6_PERIOD, val)
+#define bfin_read_TIMER6_WIDTH()		bfin_read32(TIMER6_WIDTH)
+#define bfin_write_TIMER6_WIDTH(val)		bfin_write32(TIMER6_WIDTH, val)
+
+#define bfin_read_TIMER7_CONFIG()		bfin_read16(TIMER7_CONFIG)
+#define bfin_write_TIMER7_CONFIG(val)		bfin_write16(TIMER7_CONFIG, val)
+#define bfin_read_TIMER7_COUNTER()		bfin_read32(TIMER7_COUNTER)
+#define bfin_write_TIMER7_COUNTER(val)		bfin_write32(TIMER7_COUNTER, val)
+#define bfin_read_TIMER7_PERIOD()		bfin_read32(TIMER7_PERIOD)
+#define bfin_write_TIMER7_PERIOD(val)		bfin_write32(TIMER7_PERIOD, val)
+#define bfin_read_TIMER7_WIDTH()		bfin_read32(TIMER7_WIDTH)
+#define bfin_write_TIMER7_WIDTH(val)		bfin_write32(TIMER7_WIDTH, val)
+
+#define bfin_read_TIMER_ENABLE()		bfin_read16(TIMER_ENABLE)
+#define bfin_write_TIMER_ENABLE(val)		bfin_write16(TIMER_ENABLE, val)
+#define bfin_read_TIMER_DISABLE()		bfin_read16(TIMER_DISABLE)
+#define bfin_write_TIMER_DISABLE(val)		bfin_write16(TIMER_DISABLE, val)
+#define bfin_read_TIMER_STATUS()		bfin_read32(TIMER_STATUS)
+#define bfin_write_TIMER_STATUS(val)		bfin_write32(TIMER_STATUS, val)
+
+
+/* General Purpose I/O Port F (0xFFC00700 - 0xFFC007FF)								*/
+#define bfin_read_PORTFIO()			bfin_read16(PORTFIO)
+#define bfin_write_PORTFIO(val)			bfin_write16(PORTFIO, val)
+#define bfin_read_PORTFIO_CLEAR()		bfin_read16(PORTFIO_CLEAR)
+#define bfin_write_PORTFIO_CLEAR(val)		bfin_write16(PORTFIO_CLEAR, val)
+#define bfin_read_PORTFIO_SET()			bfin_read16(PORTFIO_SET)
+#define bfin_write_PORTFIO_SET(val)		bfin_write16(PORTFIO_SET, val)
+#define bfin_read_PORTFIO_TOGGLE()		bfin_read16(PORTFIO_TOGGLE)
+#define bfin_write_PORTFIO_TOGGLE(val)		bfin_write16(PORTFIO_TOGGLE, val)
+#define bfin_read_PORTFIO_MASKA()		bfin_read16(PORTFIO_MASKA)
+#define bfin_write_PORTFIO_MASKA(val)		bfin_write16(PORTFIO_MASKA, val)
+#define bfin_read_PORTFIO_MASKA_CLEAR()		bfin_read16(PORTFIO_MASKA_CLEAR)
+#define bfin_write_PORTFIO_MASKA_CLEAR(val)	bfin_write16(PORTFIO_MASKA_CLEAR, val)
+#define bfin_read_PORTFIO_MASKA_SET()		bfin_read16(PORTFIO_MASKA_SET)
+#define bfin_write_PORTFIO_MASKA_SET(val)	bfin_write16(PORTFIO_MASKA_SET, val)
+#define bfin_read_PORTFIO_MASKA_TOGGLE()	bfin_read16(PORTFIO_MASKA_TOGGLE)
+#define bfin_write_PORTFIO_MASKA_TOGGLE(val)	bfin_write16(PORTFIO_MASKA_TOGGLE, val)
+#define bfin_read_PORTFIO_MASKB()		bfin_read16(PORTFIO_MASKB)
+#define bfin_write_PORTFIO_MASKB(val)		bfin_write16(PORTFIO_MASKB, val)
+#define bfin_read_PORTFIO_MASKB_CLEAR()		bfin_read16(PORTFIO_MASKB_CLEAR)
+#define bfin_write_PORTFIO_MASKB_CLEAR(val)	bfin_write16(PORTFIO_MASKB_CLEAR, val)
+#define bfin_read_PORTFIO_MASKB_SET()		bfin_read16(PORTFIO_MASKB_SET)
+#define bfin_write_PORTFIO_MASKB_SET(val)	bfin_write16(PORTFIO_MASKB_SET, val)
+#define bfin_read_PORTFIO_MASKB_TOGGLE()	bfin_read16(PORTFIO_MASKB_TOGGLE)
+#define bfin_write_PORTFIO_MASKB_TOGGLE(val)	bfin_write16(PORTFIO_MASKB_TOGGLE, val)
+#define bfin_read_PORTFIO_DIR()			bfin_read16(PORTFIO_DIR)
+#define bfin_write_PORTFIO_DIR(val)		bfin_write16(PORTFIO_DIR, val)
+#define bfin_read_PORTFIO_POLAR()		bfin_read16(PORTFIO_POLAR)
+#define bfin_write_PORTFIO_POLAR(val)		bfin_write16(PORTFIO_POLAR, val)
+#define bfin_read_PORTFIO_EDGE()		bfin_read16(PORTFIO_EDGE)
+#define bfin_write_PORTFIO_EDGE(val)		bfin_write16(PORTFIO_EDGE, val)
+#define bfin_read_PORTFIO_BOTH()		bfin_read16(PORTFIO_BOTH)
+#define bfin_write_PORTFIO_BOTH(val)		bfin_write16(PORTFIO_BOTH, val)
+#define bfin_read_PORTFIO_INEN()		bfin_read16(PORTFIO_INEN)
+#define bfin_write_PORTFIO_INEN(val)		bfin_write16(PORTFIO_INEN, val)
+
+
+/* SPORT0 Controller		(0xFFC00800 - 0xFFC008FF)								*/
+#define bfin_read_SPORT0_TCR1()			bfin_read16(SPORT0_TCR1)
+#define bfin_write_SPORT0_TCR1(val)		bfin_write16(SPORT0_TCR1, val)
+#define bfin_read_SPORT0_TCR2()			bfin_read16(SPORT0_TCR2)
+#define bfin_write_SPORT0_TCR2(val)		bfin_write16(SPORT0_TCR2, val)
+#define bfin_read_SPORT0_TCLKDIV()		bfin_read16(SPORT0_TCLKDIV)
+#define bfin_write_SPORT0_TCLKDIV(val)		bfin_write16(SPORT0_TCLKDIV, val)
+#define bfin_read_SPORT0_TFSDIV()		bfin_read16(SPORT0_TFSDIV)
+#define bfin_write_SPORT0_TFSDIV(val)		bfin_write16(SPORT0_TFSDIV, val)
+#define bfin_read_SPORT0_TX()			bfin_read32(SPORT0_TX)
+#define bfin_write_SPORT0_TX(val)		bfin_write32(SPORT0_TX, val)
+#define bfin_read_SPORT0_RX()			bfin_read32(SPORT0_RX)
+#define bfin_write_SPORT0_RX(val)		bfin_write32(SPORT0_RX, val)
+#define bfin_read_SPORT0_TX32()			bfin_read32(SPORT0_TX)
+#define bfin_write_SPORT0_TX32(val)		bfin_write32(SPORT0_TX, val)
+#define bfin_read_SPORT0_RX32()			bfin_read32(SPORT0_RX)
+#define bfin_write_SPORT0_RX32(val)		bfin_write32(SPORT0_RX, val)
+#define bfin_read_SPORT0_TX16()			bfin_read16(SPORT0_TX)
+#define bfin_write_SPORT0_TX16(val)		bfin_write16(SPORT0_TX, val)
+#define bfin_read_SPORT0_RX16()			bfin_read16(SPORT0_RX)
+#define bfin_write_SPORT0_RX16(val)		bfin_write16(SPORT0_RX, val)
+#define bfin_read_SPORT0_RCR1()			bfin_read16(SPORT0_RCR1)
+#define bfin_write_SPORT0_RCR1(val)		bfin_write16(SPORT0_RCR1, val)
+#define bfin_read_SPORT0_RCR2()			bfin_read16(SPORT0_RCR2)
+#define bfin_write_SPORT0_RCR2(val)		bfin_write16(SPORT0_RCR2, val)
+#define bfin_read_SPORT0_RCLKDIV()		bfin_read16(SPORT0_RCLKDIV)
+#define bfin_write_SPORT0_RCLKDIV(val)		bfin_write16(SPORT0_RCLKDIV, val)
+#define bfin_read_SPORT0_RFSDIV()		bfin_read16(SPORT0_RFSDIV)
+#define bfin_write_SPORT0_RFSDIV(val)		bfin_write16(SPORT0_RFSDIV, val)
+#define bfin_read_SPORT0_STAT()			bfin_read16(SPORT0_STAT)
+#define bfin_write_SPORT0_STAT(val)		bfin_write16(SPORT0_STAT, val)
+#define bfin_read_SPORT0_CHNL()			bfin_read16(SPORT0_CHNL)
+#define bfin_write_SPORT0_CHNL(val)		bfin_write16(SPORT0_CHNL, val)
+#define bfin_read_SPORT0_MCMC1()		bfin_read16(SPORT0_MCMC1)
+#define bfin_write_SPORT0_MCMC1(val)		bfin_write16(SPORT0_MCMC1, val)
+#define bfin_read_SPORT0_MCMC2()		bfin_read16(SPORT0_MCMC2)
+#define bfin_write_SPORT0_MCMC2(val)		bfin_write16(SPORT0_MCMC2, val)
+#define bfin_read_SPORT0_MTCS0()		bfin_read32(SPORT0_MTCS0)
+#define bfin_write_SPORT0_MTCS0(val)		bfin_write32(SPORT0_MTCS0, val)
+#define bfin_read_SPORT0_MTCS1()		bfin_read32(SPORT0_MTCS1)
+#define bfin_write_SPORT0_MTCS1(val)		bfin_write32(SPORT0_MTCS1, val)
+#define bfin_read_SPORT0_MTCS2()		bfin_read32(SPORT0_MTCS2)
+#define bfin_write_SPORT0_MTCS2(val)		bfin_write32(SPORT0_MTCS2, val)
+#define bfin_read_SPORT0_MTCS3()		bfin_read32(SPORT0_MTCS3)
+#define bfin_write_SPORT0_MTCS3(val)		bfin_write32(SPORT0_MTCS3, val)
+#define bfin_read_SPORT0_MRCS0()		bfin_read32(SPORT0_MRCS0)
+#define bfin_write_SPORT0_MRCS0(val)		bfin_write32(SPORT0_MRCS0, val)
+#define bfin_read_SPORT0_MRCS1()		bfin_read32(SPORT0_MRCS1)
+#define bfin_write_SPORT0_MRCS1(val)		bfin_write32(SPORT0_MRCS1, val)
+#define bfin_read_SPORT0_MRCS2()		bfin_read32(SPORT0_MRCS2)
+#define bfin_write_SPORT0_MRCS2(val)		bfin_write32(SPORT0_MRCS2, val)
+#define bfin_read_SPORT0_MRCS3()		bfin_read32(SPORT0_MRCS3)
+#define bfin_write_SPORT0_MRCS3(val)		bfin_write32(SPORT0_MRCS3, val)
+
+
+/* SPORT1 Controller		(0xFFC00900 - 0xFFC009FF)								*/
+#define bfin_read_SPORT1_TCR1()			bfin_read16(SPORT1_TCR1)
+#define bfin_write_SPORT1_TCR1(val)		bfin_write16(SPORT1_TCR1, val)
+#define bfin_read_SPORT1_TCR2()			bfin_read16(SPORT1_TCR2)
+#define bfin_write_SPORT1_TCR2(val)		bfin_write16(SPORT1_TCR2, val)
+#define bfin_read_SPORT1_TCLKDIV()		bfin_read16(SPORT1_TCLKDIV)
+#define bfin_write_SPORT1_TCLKDIV(val)		bfin_write16(SPORT1_TCLKDIV, val)
+#define bfin_read_SPORT1_TFSDIV()		bfin_read16(SPORT1_TFSDIV)
+#define bfin_write_SPORT1_TFSDIV(val)		bfin_write16(SPORT1_TFSDIV, val)
+#define bfin_read_SPORT1_TX()			bfin_read32(SPORT1_TX)
+#define bfin_write_SPORT1_TX(val)		bfin_write32(SPORT1_TX, val)
+#define bfin_read_SPORT1_RX()			bfin_read32(SPORT1_RX)
+#define bfin_write_SPORT1_RX(val)		bfin_write32(SPORT1_RX, val)
+#define bfin_read_SPORT1_TX32()			bfin_read32(SPORT1_TX)
+#define bfin_write_SPORT1_TX32(val)		bfin_write32(SPORT1_TX, val)
+#define bfin_read_SPORT1_RX32()			bfin_read32(SPORT1_RX)
+#define bfin_write_SPORT1_RX32(val)		bfin_write32(SPORT1_RX, val)
+#define bfin_read_SPORT1_TX16()			bfin_read16(SPORT1_TX)
+#define bfin_write_SPORT1_TX16(val)		bfin_write16(SPORT1_TX, val)
+#define bfin_read_SPORT1_RX16()			bfin_read16(SPORT1_RX)
+#define bfin_write_SPORT1_RX16(val)		bfin_write16(SPORT1_RX, val)
+#define bfin_read_SPORT1_RCR1()			bfin_read16(SPORT1_RCR1)
+#define bfin_write_SPORT1_RCR1(val)		bfin_write16(SPORT1_RCR1, val)
+#define bfin_read_SPORT1_RCR2()			bfin_read16(SPORT1_RCR2)
+#define bfin_write_SPORT1_RCR2(val)		bfin_write16(SPORT1_RCR2, val)
+#define bfin_read_SPORT1_RCLKDIV()		bfin_read16(SPORT1_RCLKDIV)
+#define bfin_write_SPORT1_RCLKDIV(val)		bfin_write16(SPORT1_RCLKDIV, val)
+#define bfin_read_SPORT1_RFSDIV()		bfin_read16(SPORT1_RFSDIV)
+#define bfin_write_SPORT1_RFSDIV(val)		bfin_write16(SPORT1_RFSDIV, val)
+#define bfin_read_SPORT1_STAT()			bfin_read16(SPORT1_STAT)
+#define bfin_write_SPORT1_STAT(val)		bfin_write16(SPORT1_STAT, val)
+#define bfin_read_SPORT1_CHNL()			bfin_read16(SPORT1_CHNL)
+#define bfin_write_SPORT1_CHNL(val)		bfin_write16(SPORT1_CHNL, val)
+#define bfin_read_SPORT1_MCMC1()		bfin_read16(SPORT1_MCMC1)
+#define bfin_write_SPORT1_MCMC1(val)		bfin_write16(SPORT1_MCMC1, val)
+#define bfin_read_SPORT1_MCMC2()		bfin_read16(SPORT1_MCMC2)
+#define bfin_write_SPORT1_MCMC2(val)		bfin_write16(SPORT1_MCMC2, val)
+#define bfin_read_SPORT1_MTCS0()		bfin_read32(SPORT1_MTCS0)
+#define bfin_write_SPORT1_MTCS0(val)		bfin_write32(SPORT1_MTCS0, val)
+#define bfin_read_SPORT1_MTCS1()		bfin_read32(SPORT1_MTCS1)
+#define bfin_write_SPORT1_MTCS1(val)		bfin_write32(SPORT1_MTCS1, val)
+#define bfin_read_SPORT1_MTCS2()		bfin_read32(SPORT1_MTCS2)
+#define bfin_write_SPORT1_MTCS2(val)		bfin_write32(SPORT1_MTCS2, val)
+#define bfin_read_SPORT1_MTCS3()		bfin_read32(SPORT1_MTCS3)
+#define bfin_write_SPORT1_MTCS3(val)		bfin_write32(SPORT1_MTCS3, val)
+#define bfin_read_SPORT1_MRCS0()		bfin_read32(SPORT1_MRCS0)
+#define bfin_write_SPORT1_MRCS0(val)		bfin_write32(SPORT1_MRCS0, val)
+#define bfin_read_SPORT1_MRCS1()		bfin_read32(SPORT1_MRCS1)
+#define bfin_write_SPORT1_MRCS1(val)		bfin_write32(SPORT1_MRCS1, val)
+#define bfin_read_SPORT1_MRCS2()		bfin_read32(SPORT1_MRCS2)
+#define bfin_write_SPORT1_MRCS2(val)		bfin_write32(SPORT1_MRCS2, val)
+#define bfin_read_SPORT1_MRCS3()		bfin_read32(SPORT1_MRCS3)
+#define bfin_write_SPORT1_MRCS3(val)		bfin_write32(SPORT1_MRCS3, val)
+
+
+/* External Bus Interface Unit (0xFFC00A00 - 0xFFC00AFF)							*/
+#define bfin_read_EBIU_AMGCTL()			bfin_read16(EBIU_AMGCTL)
+#define bfin_write_EBIU_AMGCTL(val)		bfin_write16(EBIU_AMGCTL, val)
+#define bfin_read_EBIU_AMBCTL0()		bfin_read32(EBIU_AMBCTL0)
+#define bfin_write_EBIU_AMBCTL0(val)		bfin_write32(EBIU_AMBCTL0, val)
+#define bfin_read_EBIU_AMBCTL1()		bfin_read32(EBIU_AMBCTL1)
+#define bfin_write_EBIU_AMBCTL1(val)		bfin_write32(EBIU_AMBCTL1, val)
+#define bfin_read_EBIU_SDGCTL()			bfin_read32(EBIU_SDGCTL)
+#define bfin_write_EBIU_SDGCTL(val)		bfin_write32(EBIU_SDGCTL, val)
+#define bfin_read_EBIU_SDBCTL()			bfin_read16(EBIU_SDBCTL)
+#define bfin_write_EBIU_SDBCTL(val)		bfin_write16(EBIU_SDBCTL, val)
+#define bfin_read_EBIU_SDRRC()			bfin_read16(EBIU_SDRRC)
+#define bfin_write_EBIU_SDRRC(val)		bfin_write16(EBIU_SDRRC, val)
+#define bfin_read_EBIU_SDSTAT()			bfin_read16(EBIU_SDSTAT)
+#define bfin_write_EBIU_SDSTAT(val)		bfin_write16(EBIU_SDSTAT, val)
+
+
+/* DMA Traffic Control Registers													*/
+#define bfin_read_DMAC_TC_PER()			bfin_read16(DMAC_TC_PER)
+#define bfin_write_DMAC_TC_PER(val)		bfin_write16(DMAC_TC_PER, val)
+#define bfin_read_DMAC_TC_CNT()			bfin_read16(DMAC_TC_CNT)
+#define bfin_write_DMAC_TC_CNT(val)		bfin_write16(DMAC_TC_CNT, val)
+
+/* DMA Controller																	*/
+#define bfin_read_DMA0_CONFIG()			bfin_read16(DMA0_CONFIG)
+#define bfin_write_DMA0_CONFIG(val)		bfin_write16(DMA0_CONFIG, val)
+#define bfin_read_DMA0_NEXT_DESC_PTR()		bfin_read32(DMA0_NEXT_DESC_PTR)
+#define bfin_write_DMA0_NEXT_DESC_PTR(val)	bfin_write32(DMA0_NEXT_DESC_PTR, val)
+#define bfin_read_DMA0_START_ADDR()		bfin_read32(DMA0_START_ADDR)
+#define bfin_write_DMA0_START_ADDR(val)		bfin_write32(DMA0_START_ADDR, val)
+#define bfin_read_DMA0_X_COUNT()		bfin_read16(DMA0_X_COUNT)
+#define bfin_write_DMA0_X_COUNT(val)		bfin_write16(DMA0_X_COUNT, val)
+#define bfin_read_DMA0_Y_COUNT()		bfin_read16(DMA0_Y_COUNT)
+#define bfin_write_DMA0_Y_COUNT(val)		bfin_write16(DMA0_Y_COUNT, val)
+#define bfin_read_DMA0_X_MODIFY()		bfin_read16(DMA0_X_MODIFY)
+#define bfin_write_DMA0_X_MODIFY(val)		bfin_write16(DMA0_X_MODIFY, val)
+#define bfin_read_DMA0_Y_MODIFY()		bfin_read16(DMA0_Y_MODIFY)
+#define bfin_write_DMA0_Y_MODIFY(val)		bfin_write16(DMA0_Y_MODIFY, val)
+#define bfin_read_DMA0_CURR_DESC_PTR()		bfin_read32(DMA0_CURR_DESC_PTR)
+#define bfin_write_DMA0_CURR_DESC_PTR(val)	bfin_write32(DMA0_CURR_DESC_PTR, val)
+#define bfin_read_DMA0_CURR_ADDR()		bfin_read32(DMA0_CURR_ADDR)
+#define bfin_write_DMA0_CURR_ADDR(val)		bfin_write32(DMA0_CURR_ADDR, val)
+#define bfin_read_DMA0_CURR_X_COUNT()		bfin_read16(DMA0_CURR_X_COUNT)
+#define bfin_write_DMA0_CURR_X_COUNT(val)	bfin_write16(DMA0_CURR_X_COUNT, val)
+#define bfin_read_DMA0_CURR_Y_COUNT()		bfin_read16(DMA0_CURR_Y_COUNT)
+#define bfin_write_DMA0_CURR_Y_COUNT(val)	bfin_write16(DMA0_CURR_Y_COUNT, val)
+#define bfin_read_DMA0_IRQ_STATUS()		bfin_read16(DMA0_IRQ_STATUS)
+#define bfin_write_DMA0_IRQ_STATUS(val)		bfin_write16(DMA0_IRQ_STATUS, val)
+#define bfin_read_DMA0_PERIPHERAL_MAP()		bfin_read16(DMA0_PERIPHERAL_MAP)
+#define bfin_write_DMA0_PERIPHERAL_MAP(val)	bfin_write16(DMA0_PERIPHERAL_MAP, val)
+
+#define bfin_read_DMA1_CONFIG()			bfin_read16(DMA1_CONFIG)
+#define bfin_write_DMA1_CONFIG(val)		bfin_write16(DMA1_CONFIG, val)
+#define bfin_read_DMA1_NEXT_DESC_PTR()		bfin_read32(DMA1_NEXT_DESC_PTR)
+#define bfin_write_DMA1_NEXT_DESC_PTR(val)	bfin_write32(DMA1_NEXT_DESC_PTR, val)
+#define bfin_read_DMA1_START_ADDR()		bfin_read32(DMA1_START_ADDR)
+#define bfin_write_DMA1_START_ADDR(val)		bfin_write32(DMA1_START_ADDR, val)
+#define bfin_read_DMA1_X_COUNT()		bfin_read16(DMA1_X_COUNT)
+#define bfin_write_DMA1_X_COUNT(val)		bfin_write16(DMA1_X_COUNT, val)
+#define bfin_read_DMA1_Y_COUNT()		bfin_read16(DMA1_Y_COUNT)
+#define bfin_write_DMA1_Y_COUNT(val)		bfin_write16(DMA1_Y_COUNT, val)
+#define bfin_read_DMA1_X_MODIFY()		bfin_read16(DMA1_X_MODIFY)
+#define bfin_write_DMA1_X_MODIFY(val)		bfin_write16(DMA1_X_MODIFY, val)
+#define bfin_read_DMA1_Y_MODIFY()		bfin_read16(DMA1_Y_MODIFY)
+#define bfin_write_DMA1_Y_MODIFY(val)		bfin_write16(DMA1_Y_MODIFY, val)
+#define bfin_read_DMA1_CURR_DESC_PTR()		bfin_read32(DMA1_CURR_DESC_PTR)
+#define bfin_write_DMA1_CURR_DESC_PTR(val)	bfin_write32(DMA1_CURR_DESC_PTR, val)
+#define bfin_read_DMA1_CURR_ADDR()		bfin_read32(DMA1_CURR_ADDR)
+#define bfin_write_DMA1_CURR_ADDR(val)		bfin_write32(DMA1_CURR_ADDR, val)
+#define bfin_read_DMA1_CURR_X_COUNT()		bfin_read16(DMA1_CURR_X_COUNT)
+#define bfin_write_DMA1_CURR_X_COUNT(val)	bfin_write16(DMA1_CURR_X_COUNT, val)
+#define bfin_read_DMA1_CURR_Y_COUNT()		bfin_read16(DMA1_CURR_Y_COUNT)
+#define bfin_write_DMA1_CURR_Y_COUNT(val)	bfin_write16(DMA1_CURR_Y_COUNT, val)
+#define bfin_read_DMA1_IRQ_STATUS()		bfin_read16(DMA1_IRQ_STATUS)
+#define bfin_write_DMA1_IRQ_STATUS(val)		bfin_write16(DMA1_IRQ_STATUS, val)
+#define bfin_read_DMA1_PERIPHERAL_MAP()		bfin_read16(DMA1_PERIPHERAL_MAP)
+#define bfin_write_DMA1_PERIPHERAL_MAP(val)	bfin_write16(DMA1_PERIPHERAL_MAP, val)
+
+#define bfin_read_DMA2_CONFIG()			bfin_read16(DMA2_CONFIG)
+#define bfin_write_DMA2_CONFIG(val)		bfin_write16(DMA2_CONFIG, val)
+#define bfin_read_DMA2_NEXT_DESC_PTR()		bfin_read32(DMA2_NEXT_DESC_PTR)
+#define bfin_write_DMA2_NEXT_DESC_PTR(val)	bfin_write32(DMA2_NEXT_DESC_PTR, val)
+#define bfin_read_DMA2_START_ADDR()		bfin_read32(DMA2_START_ADDR)
+#define bfin_write_DMA2_START_ADDR(val)		bfin_write32(DMA2_START_ADDR, val)
+#define bfin_read_DMA2_X_COUNT()		bfin_read16(DMA2_X_COUNT)
+#define bfin_write_DMA2_X_COUNT(val)		bfin_write16(DMA2_X_COUNT, val)
+#define bfin_read_DMA2_Y_COUNT()		bfin_read16(DMA2_Y_COUNT)
+#define bfin_write_DMA2_Y_COUNT(val)		bfin_write16(DMA2_Y_COUNT, val)
+#define bfin_read_DMA2_X_MODIFY()		bfin_read16(DMA2_X_MODIFY)
+#define bfin_write_DMA2_X_MODIFY(val)		bfin_write16(DMA2_X_MODIFY, val)
+#define bfin_read_DMA2_Y_MODIFY()		bfin_read16(DMA2_Y_MODIFY)
+#define bfin_write_DMA2_Y_MODIFY(val)		bfin_write16(DMA2_Y_MODIFY, val)
+#define bfin_read_DMA2_CURR_DESC_PTR()		bfin_read32(DMA2_CURR_DESC_PTR)
+#define bfin_write_DMA2_CURR_DESC_PTR(val)	bfin_write32(DMA2_CURR_DESC_PTR, val)
+#define bfin_read_DMA2_CURR_ADDR()		bfin_read32(DMA2_CURR_ADDR)
+#define bfin_write_DMA2_CURR_ADDR(val)		bfin_write32(DMA2_CURR_ADDR, val)
+#define bfin_read_DMA2_CURR_X_COUNT()		bfin_read16(DMA2_CURR_X_COUNT)
+#define bfin_write_DMA2_CURR_X_COUNT(val)	bfin_write16(DMA2_CURR_X_COUNT, val)
+#define bfin_read_DMA2_CURR_Y_COUNT()		bfin_read16(DMA2_CURR_Y_COUNT)
+#define bfin_write_DMA2_CURR_Y_COUNT(val)	bfin_write16(DMA2_CURR_Y_COUNT, val)
+#define bfin_read_DMA2_IRQ_STATUS()		bfin_read16(DMA2_IRQ_STATUS)
+#define bfin_write_DMA2_IRQ_STATUS(val)		bfin_write16(DMA2_IRQ_STATUS, val)
+#define bfin_read_DMA2_PERIPHERAL_MAP()		bfin_read16(DMA2_PERIPHERAL_MAP)
+#define bfin_write_DMA2_PERIPHERAL_MAP(val)	bfin_write16(DMA2_PERIPHERAL_MAP, val)
+
+#define bfin_read_DMA3_CONFIG()			bfin_read16(DMA3_CONFIG)
+#define bfin_write_DMA3_CONFIG(val)		bfin_write16(DMA3_CONFIG, val)
+#define bfin_read_DMA3_NEXT_DESC_PTR()		bfin_read32(DMA3_NEXT_DESC_PTR)
+#define bfin_write_DMA3_NEXT_DESC_PTR(val)	bfin_write32(DMA3_NEXT_DESC_PTR, val)
+#define bfin_read_DMA3_START_ADDR()		bfin_read32(DMA3_START_ADDR)
+#define bfin_write_DMA3_START_ADDR(val)		bfin_write32(DMA3_START_ADDR, val)
+#define bfin_read_DMA3_X_COUNT()		bfin_read16(DMA3_X_COUNT)
+#define bfin_write_DMA3_X_COUNT(val)		bfin_write16(DMA3_X_COUNT, val)
+#define bfin_read_DMA3_Y_COUNT()		bfin_read16(DMA3_Y_COUNT)
+#define bfin_write_DMA3_Y_COUNT(val)		bfin_write16(DMA3_Y_COUNT, val)
+#define bfin_read_DMA3_X_MODIFY()		bfin_read16(DMA3_X_MODIFY)
+#define bfin_write_DMA3_X_MODIFY(val)		bfin_write16(DMA3_X_MODIFY, val)
+#define bfin_read_DMA3_Y_MODIFY()		bfin_read16(DMA3_Y_MODIFY)
+#define bfin_write_DMA3_Y_MODIFY(val)		bfin_write16(DMA3_Y_MODIFY, val)
+#define bfin_read_DMA3_CURR_DESC_PTR()		bfin_read32(DMA3_CURR_DESC_PTR)
+#define bfin_write_DMA3_CURR_DESC_PTR(val)	bfin_write32(DMA3_CURR_DESC_PTR, val)
+#define bfin_read_DMA3_CURR_ADDR()		bfin_read32(DMA3_CURR_ADDR)
+#define bfin_write_DMA3_CURR_ADDR(val)		bfin_write32(DMA3_CURR_ADDR, val)
+#define bfin_read_DMA3_CURR_X_COUNT()		bfin_read16(DMA3_CURR_X_COUNT)
+#define bfin_write_DMA3_CURR_X_COUNT(val)	bfin_write16(DMA3_CURR_X_COUNT, val)
+#define bfin_read_DMA3_CURR_Y_COUNT()		bfin_read16(DMA3_CURR_Y_COUNT)
+#define bfin_write_DMA3_CURR_Y_COUNT(val)	bfin_write16(DMA3_CURR_Y_COUNT, val)
+#define bfin_read_DMA3_IRQ_STATUS()		bfin_read16(DMA3_IRQ_STATUS)
+#define bfin_write_DMA3_IRQ_STATUS(val)		bfin_write16(DMA3_IRQ_STATUS, val)
+#define bfin_read_DMA3_PERIPHERAL_MAP()		bfin_read16(DMA3_PERIPHERAL_MAP)
+#define bfin_write_DMA3_PERIPHERAL_MAP(val)	bfin_write16(DMA3_PERIPHERAL_MAP, val)
+
+#define bfin_read_DMA4_CONFIG()			bfin_read16(DMA4_CONFIG)
+#define bfin_write_DMA4_CONFIG(val)		bfin_write16(DMA4_CONFIG, val)
+#define bfin_read_DMA4_NEXT_DESC_PTR()		bfin_read32(DMA4_NEXT_DESC_PTR)
+#define bfin_write_DMA4_NEXT_DESC_PTR(val)	bfin_write32(DMA4_NEXT_DESC_PTR, val)
+#define bfin_read_DMA4_START_ADDR()		bfin_read32(DMA4_START_ADDR)
+#define bfin_write_DMA4_START_ADDR(val)		bfin_write32(DMA4_START_ADDR, val)
+#define bfin_read_DMA4_X_COUNT()		bfin_read16(DMA4_X_COUNT)
+#define bfin_write_DMA4_X_COUNT(val)		bfin_write16(DMA4_X_COUNT, val)
+#define bfin_read_DMA4_Y_COUNT()		bfin_read16(DMA4_Y_COUNT)
+#define bfin_write_DMA4_Y_COUNT(val)		bfin_write16(DMA4_Y_COUNT, val)
+#define bfin_read_DMA4_X_MODIFY()		bfin_read16(DMA4_X_MODIFY)
+#define bfin_write_DMA4_X_MODIFY(val)		bfin_write16(DMA4_X_MODIFY, val)
+#define bfin_read_DMA4_Y_MODIFY()		bfin_read16(DMA4_Y_MODIFY)
+#define bfin_write_DMA4_Y_MODIFY(val)		bfin_write16(DMA4_Y_MODIFY, val)
+#define bfin_read_DMA4_CURR_DESC_PTR()		bfin_read32(DMA4_CURR_DESC_PTR)
+#define bfin_write_DMA4_CURR_DESC_PTR(val)	bfin_write32(DMA4_CURR_DESC_PTR, val)
+#define bfin_read_DMA4_CURR_ADDR()		bfin_read32(DMA4_CURR_ADDR)
+#define bfin_write_DMA4_CURR_ADDR(val)		bfin_write32(DMA4_CURR_ADDR, val)
+#define bfin_read_DMA4_CURR_X_COUNT()		bfin_read16(DMA4_CURR_X_COUNT)
+#define bfin_write_DMA4_CURR_X_COUNT(val)	bfin_write16(DMA4_CURR_X_COUNT, val)
+#define bfin_read_DMA4_CURR_Y_COUNT()		bfin_read16(DMA4_CURR_Y_COUNT)
+#define bfin_write_DMA4_CURR_Y_COUNT(val)	bfin_write16(DMA4_CURR_Y_COUNT, val)
+#define bfin_read_DMA4_IRQ_STATUS()		bfin_read16(DMA4_IRQ_STATUS)
+#define bfin_write_DMA4_IRQ_STATUS(val)		bfin_write16(DMA4_IRQ_STATUS, val)
+#define bfin_read_DMA4_PERIPHERAL_MAP()		bfin_read16(DMA4_PERIPHERAL_MAP)
+#define bfin_write_DMA4_PERIPHERAL_MAP(val)	bfin_write16(DMA4_PERIPHERAL_MAP, val)
+
+#define bfin_read_DMA5_CONFIG()			bfin_read16(DMA5_CONFIG)
+#define bfin_write_DMA5_CONFIG(val)		bfin_write16(DMA5_CONFIG, val)
+#define bfin_read_DMA5_NEXT_DESC_PTR()		bfin_read32(DMA5_NEXT_DESC_PTR)
+#define bfin_write_DMA5_NEXT_DESC_PTR(val)	bfin_write32(DMA5_NEXT_DESC_PTR, val)
+#define bfin_read_DMA5_START_ADDR()		bfin_read32(DMA5_START_ADDR)
+#define bfin_write_DMA5_START_ADDR(val)		bfin_write32(DMA5_START_ADDR, val)
+#define bfin_read_DMA5_X_COUNT()		bfin_read16(DMA5_X_COUNT)
+#define bfin_write_DMA5_X_COUNT(val)		bfin_write16(DMA5_X_COUNT, val)
+#define bfin_read_DMA5_Y_COUNT()		bfin_read16(DMA5_Y_COUNT)
+#define bfin_write_DMA5_Y_COUNT(val)		bfin_write16(DMA5_Y_COUNT, val)
+#define bfin_read_DMA5_X_MODIFY()		bfin_read16(DMA5_X_MODIFY)
+#define bfin_write_DMA5_X_MODIFY(val)		bfin_write16(DMA5_X_MODIFY, val)
+#define bfin_read_DMA5_Y_MODIFY()		bfin_read16(DMA5_Y_MODIFY)
+#define bfin_write_DMA5_Y_MODIFY(val)		bfin_write16(DMA5_Y_MODIFY, val)
+#define bfin_read_DMA5_CURR_DESC_PTR()		bfin_read32(DMA5_CURR_DESC_PTR)
+#define bfin_write_DMA5_CURR_DESC_PTR(val)	bfin_write32(DMA5_CURR_DESC_PTR, val)
+#define bfin_read_DMA5_CURR_ADDR()		bfin_read32(DMA5_CURR_ADDR)
+#define bfin_write_DMA5_CURR_ADDR(val)		bfin_write32(DMA5_CURR_ADDR, val)
+#define bfin_read_DMA5_CURR_X_COUNT()		bfin_read16(DMA5_CURR_X_COUNT)
+#define bfin_write_DMA5_CURR_X_COUNT(val)	bfin_write16(DMA5_CURR_X_COUNT, val)
+#define bfin_read_DMA5_CURR_Y_COUNT()		bfin_read16(DMA5_CURR_Y_COUNT)
+#define bfin_write_DMA5_CURR_Y_COUNT(val)	bfin_write16(DMA5_CURR_Y_COUNT, val)
+#define bfin_read_DMA5_IRQ_STATUS()		bfin_read16(DMA5_IRQ_STATUS)
+#define bfin_write_DMA5_IRQ_STATUS(val)		bfin_write16(DMA5_IRQ_STATUS, val)
+#define bfin_read_DMA5_PERIPHERAL_MAP()		bfin_read16(DMA5_PERIPHERAL_MAP)
+#define bfin_write_DMA5_PERIPHERAL_MAP(val)	bfin_write16(DMA5_PERIPHERAL_MAP, val)
+
+#define bfin_read_DMA6_CONFIG()			bfin_read16(DMA6_CONFIG)
+#define bfin_write_DMA6_CONFIG(val)		bfin_write16(DMA6_CONFIG, val)
+#define bfin_read_DMA6_NEXT_DESC_PTR()		bfin_read32(DMA6_NEXT_DESC_PTR)
+#define bfin_write_DMA6_NEXT_DESC_PTR(val)	bfin_write32(DMA6_NEXT_DESC_PTR, val)
+#define bfin_read_DMA6_START_ADDR()		bfin_read32(DMA6_START_ADDR)
+#define bfin_write_DMA6_START_ADDR(val)		bfin_write32(DMA6_START_ADDR, val)
+#define bfin_read_DMA6_X_COUNT()		bfin_read16(DMA6_X_COUNT)
+#define bfin_write_DMA6_X_COUNT(val)		bfin_write16(DMA6_X_COUNT, val)
+#define bfin_read_DMA6_Y_COUNT()		bfin_read16(DMA6_Y_COUNT)
+#define bfin_write_DMA6_Y_COUNT(val)		bfin_write16(DMA6_Y_COUNT, val)
+#define bfin_read_DMA6_X_MODIFY()		bfin_read16(DMA6_X_MODIFY)
+#define bfin_write_DMA6_X_MODIFY(val)		bfin_write16(DMA6_X_MODIFY, val)
+#define bfin_read_DMA6_Y_MODIFY()		bfin_read16(DMA6_Y_MODIFY)
+#define bfin_write_DMA6_Y_MODIFY(val)		bfin_write16(DMA6_Y_MODIFY, val)
+#define bfin_read_DMA6_CURR_DESC_PTR()		bfin_read32(DMA6_CURR_DESC_PTR)
+#define bfin_write_DMA6_CURR_DESC_PTR(val)	bfin_write32(DMA6_CURR_DESC_PTR, val)
+#define bfin_read_DMA6_CURR_ADDR()		bfin_read32(DMA6_CURR_ADDR)
+#define bfin_write_DMA6_CURR_ADDR(val)		bfin_write32(DMA6_CURR_ADDR, val)
+#define bfin_read_DMA6_CURR_X_COUNT()		bfin_read16(DMA6_CURR_X_COUNT)
+#define bfin_write_DMA6_CURR_X_COUNT(val)	bfin_write16(DMA6_CURR_X_COUNT, val)
+#define bfin_read_DMA6_CURR_Y_COUNT()		bfin_read16(DMA6_CURR_Y_COUNT)
+#define bfin_write_DMA6_CURR_Y_COUNT(val)	bfin_write16(DMA6_CURR_Y_COUNT, val)
+#define bfin_read_DMA6_IRQ_STATUS()		bfin_read16(DMA6_IRQ_STATUS)
+#define bfin_write_DMA6_IRQ_STATUS(val)		bfin_write16(DMA6_IRQ_STATUS, val)
+#define bfin_read_DMA6_PERIPHERAL_MAP()		bfin_read16(DMA6_PERIPHERAL_MAP)
+#define bfin_write_DMA6_PERIPHERAL_MAP(val)	bfin_write16(DMA6_PERIPHERAL_MAP, val)
+
+#define bfin_read_DMA7_CONFIG()			bfin_read16(DMA7_CONFIG)
+#define bfin_write_DMA7_CONFIG(val)		bfin_write16(DMA7_CONFIG, val)
+#define bfin_read_DMA7_NEXT_DESC_PTR()		bfin_read32(DMA7_NEXT_DESC_PTR)
+#define bfin_write_DMA7_NEXT_DESC_PTR(val)	bfin_write32(DMA7_NEXT_DESC_PTR, val)
+#define bfin_read_DMA7_START_ADDR()		bfin_read32(DMA7_START_ADDR)
+#define bfin_write_DMA7_START_ADDR(val)		bfin_write32(DMA7_START_ADDR, val)
+#define bfin_read_DMA7_X_COUNT()		bfin_read16(DMA7_X_COUNT)
+#define bfin_write_DMA7_X_COUNT(val)		bfin_write16(DMA7_X_COUNT, val)
+#define bfin_read_DMA7_Y_COUNT()		bfin_read16(DMA7_Y_COUNT)
+#define bfin_write_DMA7_Y_COUNT(val)		bfin_write16(DMA7_Y_COUNT, val)
+#define bfin_read_DMA7_X_MODIFY()		bfin_read16(DMA7_X_MODIFY)
+#define bfin_write_DMA7_X_MODIFY(val)		bfin_write16(DMA7_X_MODIFY, val)
+#define bfin_read_DMA7_Y_MODIFY()		bfin_read16(DMA7_Y_MODIFY)
+#define bfin_write_DMA7_Y_MODIFY(val)		bfin_write16(DMA7_Y_MODIFY, val)
+#define bfin_read_DMA7_CURR_DESC_PTR()		bfin_read32(DMA7_CURR_DESC_PTR)
+#define bfin_write_DMA7_CURR_DESC_PTR(val)	bfin_write32(DMA7_CURR_DESC_PTR, val)
+#define bfin_read_DMA7_CURR_ADDR()		bfin_read32(DMA7_CURR_ADDR)
+#define bfin_write_DMA7_CURR_ADDR(val)		bfin_write32(DMA7_CURR_ADDR, val)
+#define bfin_read_DMA7_CURR_X_COUNT()		bfin_read16(DMA7_CURR_X_COUNT)
+#define bfin_write_DMA7_CURR_X_COUNT(val)	bfin_write16(DMA7_CURR_X_COUNT, val)
+#define bfin_read_DMA7_CURR_Y_COUNT()		bfin_read16(DMA7_CURR_Y_COUNT)
+#define bfin_write_DMA7_CURR_Y_COUNT(val)	bfin_write16(DMA7_CURR_Y_COUNT, val)
+#define bfin_read_DMA7_IRQ_STATUS()		bfin_read16(DMA7_IRQ_STATUS)
+#define bfin_write_DMA7_IRQ_STATUS(val)		bfin_write16(DMA7_IRQ_STATUS, val)
+#define bfin_read_DMA7_PERIPHERAL_MAP()		bfin_read16(DMA7_PERIPHERAL_MAP)
+#define bfin_write_DMA7_PERIPHERAL_MAP(val)	bfin_write16(DMA7_PERIPHERAL_MAP, val)
+
+#define bfin_read_DMA8_CONFIG()			bfin_read16(DMA8_CONFIG)
+#define bfin_write_DMA8_CONFIG(val)		bfin_write16(DMA8_CONFIG, val)
+#define bfin_read_DMA8_NEXT_DESC_PTR()		bfin_read32(DMA8_NEXT_DESC_PTR)
+#define bfin_write_DMA8_NEXT_DESC_PTR(val)	bfin_write32(DMA8_NEXT_DESC_PTR, val)
+#define bfin_read_DMA8_START_ADDR()		bfin_read32(DMA8_START_ADDR)
+#define bfin_write_DMA8_START_ADDR(val)		bfin_write32(DMA8_START_ADDR, val)
+#define bfin_read_DMA8_X_COUNT()		bfin_read16(DMA8_X_COUNT)
+#define bfin_write_DMA8_X_COUNT(val)		bfin_write16(DMA8_X_COUNT, val)
+#define bfin_read_DMA8_Y_COUNT()		bfin_read16(DMA8_Y_COUNT)
+#define bfin_write_DMA8_Y_COUNT(val)		bfin_write16(DMA8_Y_COUNT, val)
+#define bfin_read_DMA8_X_MODIFY()		bfin_read16(DMA8_X_MODIFY)
+#define bfin_write_DMA8_X_MODIFY(val)		bfin_write16(DMA8_X_MODIFY, val)
+#define bfin_read_DMA8_Y_MODIFY()		bfin_read16(DMA8_Y_MODIFY)
+#define bfin_write_DMA8_Y_MODIFY(val)		bfin_write16(DMA8_Y_MODIFY, val)
+#define bfin_read_DMA8_CURR_DESC_PTR()		bfin_read32(DMA8_CURR_DESC_PTR)
+#define bfin_write_DMA8_CURR_DESC_PTR(val)	bfin_write32(DMA8_CURR_DESC_PTR, val)
+#define bfin_read_DMA8_CURR_ADDR()		bfin_read32(DMA8_CURR_ADDR)
+#define bfin_write_DMA8_CURR_ADDR(val)		bfin_write32(DMA8_CURR_ADDR, val)
+#define bfin_read_DMA8_CURR_X_COUNT()		bfin_read16(DMA8_CURR_X_COUNT)
+#define bfin_write_DMA8_CURR_X_COUNT(val)	bfin_write16(DMA8_CURR_X_COUNT, val)
+#define bfin_read_DMA8_CURR_Y_COUNT()		bfin_read16(DMA8_CURR_Y_COUNT)
+#define bfin_write_DMA8_CURR_Y_COUNT(val)	bfin_write16(DMA8_CURR_Y_COUNT, val)
+#define bfin_read_DMA8_IRQ_STATUS()		bfin_read16(DMA8_IRQ_STATUS)
+#define bfin_write_DMA8_IRQ_STATUS(val)		bfin_write16(DMA8_IRQ_STATUS, val)
+#define bfin_read_DMA8_PERIPHERAL_MAP()		bfin_read16(DMA8_PERIPHERAL_MAP)
+#define bfin_write_DMA8_PERIPHERAL_MAP(val)	bfin_write16(DMA8_PERIPHERAL_MAP, val)
+
+#define bfin_read_DMA9_CONFIG()			bfin_read16(DMA9_CONFIG)
+#define bfin_write_DMA9_CONFIG(val)		bfin_write16(DMA9_CONFIG, val)
+#define bfin_read_DMA9_NEXT_DESC_PTR()		bfin_read32(DMA9_NEXT_DESC_PTR)
+#define bfin_write_DMA9_NEXT_DESC_PTR(val)	bfin_write32(DMA9_NEXT_DESC_PTR, val)
+#define bfin_read_DMA9_START_ADDR()		bfin_read32(DMA9_START_ADDR)
+#define bfin_write_DMA9_START_ADDR(val)		bfin_write32(DMA9_START_ADDR, val)
+#define bfin_read_DMA9_X_COUNT()		bfin_read16(DMA9_X_COUNT)
+#define bfin_write_DMA9_X_COUNT(val)		bfin_write16(DMA9_X_COUNT, val)
+#define bfin_read_DMA9_Y_COUNT()		bfin_read16(DMA9_Y_COUNT)
+#define bfin_write_DMA9_Y_COUNT(val)		bfin_write16(DMA9_Y_COUNT, val)
+#define bfin_read_DMA9_X_MODIFY()		bfin_read16(DMA9_X_MODIFY)
+#define bfin_write_DMA9_X_MODIFY(val)		bfin_write16(DMA9_X_MODIFY, val)
+#define bfin_read_DMA9_Y_MODIFY()		bfin_read16(DMA9_Y_MODIFY)
+#define bfin_write_DMA9_Y_MODIFY(val)		bfin_write16(DMA9_Y_MODIFY, val)
+#define bfin_read_DMA9_CURR_DESC_PTR()		bfin_read32(DMA9_CURR_DESC_PTR)
+#define bfin_write_DMA9_CURR_DESC_PTR(val)	bfin_write32(DMA9_CURR_DESC_PTR, val)
+#define bfin_read_DMA9_CURR_ADDR()		bfin_read32(DMA9_CURR_ADDR)
+#define bfin_write_DMA9_CURR_ADDR(val)		bfin_write32(DMA9_CURR_ADDR, val)
+#define bfin_read_DMA9_CURR_X_COUNT()		bfin_read16(DMA9_CURR_X_COUNT)
+#define bfin_write_DMA9_CURR_X_COUNT(val)	bfin_write16(DMA9_CURR_X_COUNT, val)
+#define bfin_read_DMA9_CURR_Y_COUNT()		bfin_read16(DMA9_CURR_Y_COUNT)
+#define bfin_write_DMA9_CURR_Y_COUNT(val)	bfin_write16(DMA9_CURR_Y_COUNT, val)
+#define bfin_read_DMA9_IRQ_STATUS()		bfin_read16(DMA9_IRQ_STATUS)
+#define bfin_write_DMA9_IRQ_STATUS(val)		bfin_write16(DMA9_IRQ_STATUS, val)
+#define bfin_read_DMA9_PERIPHERAL_MAP()		bfin_read16(DMA9_PERIPHERAL_MAP)
+#define bfin_write_DMA9_PERIPHERAL_MAP(val)	bfin_write16(DMA9_PERIPHERAL_MAP, val)
+
+#define bfin_read_DMA10_CONFIG()		bfin_read16(DMA10_CONFIG)
+#define bfin_write_DMA10_CONFIG(val)		bfin_write16(DMA10_CONFIG, val)
+#define bfin_read_DMA10_NEXT_DESC_PTR()		bfin_read32(DMA10_NEXT_DESC_PTR)
+#define bfin_write_DMA10_NEXT_DESC_PTR(val)	bfin_write32(DMA10_NEXT_DESC_PTR, val)
+#define bfin_read_DMA10_START_ADDR()		bfin_read32(DMA10_START_ADDR)
+#define bfin_write_DMA10_START_ADDR(val)	bfin_write32(DMA10_START_ADDR, val)
+#define bfin_read_DMA10_X_COUNT()		bfin_read16(DMA10_X_COUNT)
+#define bfin_write_DMA10_X_COUNT(val)		bfin_write16(DMA10_X_COUNT, val)
+#define bfin_read_DMA10_Y_COUNT()		bfin_read16(DMA10_Y_COUNT)
+#define bfin_write_DMA10_Y_COUNT(val)		bfin_write16(DMA10_Y_COUNT, val)
+#define bfin_read_DMA10_X_MODIFY()		bfin_read16(DMA10_X_MODIFY)
+#define bfin_write_DMA10_X_MODIFY(val)		bfin_write16(DMA10_X_MODIFY, val)
+#define bfin_read_DMA10_Y_MODIFY()		bfin_read16(DMA10_Y_MODIFY)
+#define bfin_write_DMA10_Y_MODIFY(val)		bfin_write16(DMA10_Y_MODIFY, val)
+#define bfin_read_DMA10_CURR_DESC_PTR()		bfin_read32(DMA10_CURR_DESC_PTR)
+#define bfin_write_DMA10_CURR_DESC_PTR(val)	bfin_write32(DMA10_CURR_DESC_PTR, val)
+#define bfin_read_DMA10_CURR_ADDR()		bfin_read32(DMA10_CURR_ADDR)
+#define bfin_write_DMA10_CURR_ADDR(val)		bfin_write32(DMA10_CURR_ADDR, val)
+#define bfin_read_DMA10_CURR_X_COUNT()		bfin_read16(DMA10_CURR_X_COUNT)
+#define bfin_write_DMA10_CURR_X_COUNT(val)	bfin_write16(DMA10_CURR_X_COUNT, val)
+#define bfin_read_DMA10_CURR_Y_COUNT()		bfin_read16(DMA10_CURR_Y_COUNT)
+#define bfin_write_DMA10_CURR_Y_COUNT(val)	bfin_write16(DMA10_CURR_Y_COUNT, val)
+#define bfin_read_DMA10_IRQ_STATUS()		bfin_read16(DMA10_IRQ_STATUS)
+#define bfin_write_DMA10_IRQ_STATUS(val)	bfin_write16(DMA10_IRQ_STATUS, val)
+#define bfin_read_DMA10_PERIPHERAL_MAP()	bfin_read16(DMA10_PERIPHERAL_MAP)
+#define bfin_write_DMA10_PERIPHERAL_MAP(val)	bfin_write16(DMA10_PERIPHERAL_MAP, val)
+
+#define bfin_read_DMA11_CONFIG()		bfin_read16(DMA11_CONFIG)
+#define bfin_write_DMA11_CONFIG(val)		bfin_write16(DMA11_CONFIG, val)
+#define bfin_read_DMA11_NEXT_DESC_PTR()		bfin_read32(DMA11_NEXT_DESC_PTR)
+#define bfin_write_DMA11_NEXT_DESC_PTR(val)	bfin_write32(DMA11_NEXT_DESC_PTR, val)
+#define bfin_read_DMA11_START_ADDR()		bfin_read32(DMA11_START_ADDR)
+#define bfin_write_DMA11_START_ADDR(val)	bfin_write32(DMA11_START_ADDR, val)
+#define bfin_read_DMA11_X_COUNT()		bfin_read16(DMA11_X_COUNT)
+#define bfin_write_DMA11_X_COUNT(val)		bfin_write16(DMA11_X_COUNT, val)
+#define bfin_read_DMA11_Y_COUNT()		bfin_read16(DMA11_Y_COUNT)
+#define bfin_write_DMA11_Y_COUNT(val)		bfin_write16(DMA11_Y_COUNT, val)
+#define bfin_read_DMA11_X_MODIFY()		bfin_read16(DMA11_X_MODIFY)
+#define bfin_write_DMA11_X_MODIFY(val)		bfin_write16(DMA11_X_MODIFY, val)
+#define bfin_read_DMA11_Y_MODIFY()		bfin_read16(DMA11_Y_MODIFY)
+#define bfin_write_DMA11_Y_MODIFY(val)		bfin_write16(DMA11_Y_MODIFY, val)
+#define bfin_read_DMA11_CURR_DESC_PTR()		bfin_read32(DMA11_CURR_DESC_PTR)
+#define bfin_write_DMA11_CURR_DESC_PTR(val)	bfin_write32(DMA11_CURR_DESC_PTR, val)
+#define bfin_read_DMA11_CURR_ADDR()		bfin_read32(DMA11_CURR_ADDR)
+#define bfin_write_DMA11_CURR_ADDR(val)		bfin_write32(DMA11_CURR_ADDR, val)
+#define bfin_read_DMA11_CURR_X_COUNT()		bfin_read16(DMA11_CURR_X_COUNT)
+#define bfin_write_DMA11_CURR_X_COUNT(val)	bfin_write16(DMA11_CURR_X_COUNT, val)
+#define bfin_read_DMA11_CURR_Y_COUNT()		bfin_read16(DMA11_CURR_Y_COUNT)
+#define bfin_write_DMA11_CURR_Y_COUNT(val)	bfin_write16(DMA11_CURR_Y_COUNT, val)
+#define bfin_read_DMA11_IRQ_STATUS()		bfin_read16(DMA11_IRQ_STATUS)
+#define bfin_write_DMA11_IRQ_STATUS(val)	bfin_write16(DMA11_IRQ_STATUS, val)
+#define bfin_read_DMA11_PERIPHERAL_MAP()	bfin_read16(DMA11_PERIPHERAL_MAP)
+#define bfin_write_DMA11_PERIPHERAL_MAP(val)	bfin_write16(DMA11_PERIPHERAL_MAP, val)
+
+#define bfin_read_MDMA_D0_CONFIG()		bfin_read16(MDMA_D0_CONFIG)
+#define bfin_write_MDMA_D0_CONFIG(val)		bfin_write16(MDMA_D0_CONFIG, val)
+#define bfin_read_MDMA_D0_NEXT_DESC_PTR()	bfin_read32(MDMA_D0_NEXT_DESC_PTR)
+#define bfin_write_MDMA_D0_NEXT_DESC_PTR(val)	bfin_write32(MDMA_D0_NEXT_DESC_PTR, val)
+#define bfin_read_MDMA_D0_START_ADDR()		bfin_read32(MDMA_D0_START_ADDR)
+#define bfin_write_MDMA_D0_START_ADDR(val)	bfin_write32(MDMA_D0_START_ADDR, val)
+#define bfin_read_MDMA_D0_X_COUNT()		bfin_read16(MDMA_D0_X_COUNT)
+#define bfin_write_MDMA_D0_X_COUNT(val)		bfin_write16(MDMA_D0_X_COUNT, val)
+#define bfin_read_MDMA_D0_Y_COUNT()		bfin_read16(MDMA_D0_Y_COUNT)
+#define bfin_write_MDMA_D0_Y_COUNT(val)		bfin_write16(MDMA_D0_Y_COUNT, val)
+#define bfin_read_MDMA_D0_X_MODIFY()		bfin_read16(MDMA_D0_X_MODIFY)
+#define bfin_write_MDMA_D0_X_MODIFY(val)	bfin_write16(MDMA_D0_X_MODIFY, val)
+#define bfin_read_MDMA_D0_Y_MODIFY()		bfin_read16(MDMA_D0_Y_MODIFY)
+#define bfin_write_MDMA_D0_Y_MODIFY(val)	bfin_write16(MDMA_D0_Y_MODIFY, val)
+#define bfin_read_MDMA_D0_CURR_DESC_PTR()	bfin_read32(MDMA_D0_CURR_DESC_PTR)
+#define bfin_write_MDMA_D0_CURR_DESC_PTR(val)	bfin_write32(MDMA_D0_CURR_DESC_PTR, val)
+#define bfin_read_MDMA_D0_CURR_ADDR()		bfin_read32(MDMA_D0_CURR_ADDR)
+#define bfin_write_MDMA_D0_CURR_ADDR(val)	bfin_write32(MDMA_D0_CURR_ADDR, val)
+#define bfin_read_MDMA_D0_CURR_X_COUNT()	bfin_read16(MDMA_D0_CURR_X_COUNT)
+#define bfin_write_MDMA_D0_CURR_X_COUNT(val)	bfin_write16(MDMA_D0_CURR_X_COUNT, val)
+#define bfin_read_MDMA_D0_CURR_Y_COUNT()	bfin_read16(MDMA_D0_CURR_Y_COUNT)
+#define bfin_write_MDMA_D0_CURR_Y_COUNT(val)	bfin_write16(MDMA_D0_CURR_Y_COUNT, val)
+#define bfin_read_MDMA_D0_IRQ_STATUS()		bfin_read16(MDMA_D0_IRQ_STATUS)
+#define bfin_write_MDMA_D0_IRQ_STATUS(val)	bfin_write16(MDMA_D0_IRQ_STATUS, val)
+#define bfin_read_MDMA_D0_PERIPHERAL_MAP()	bfin_read16(MDMA_D0_PERIPHERAL_MAP)
+#define bfin_write_MDMA_D0_PERIPHERAL_MAP(val)	bfin_write16(MDMA_D0_PERIPHERAL_MAP, val)
+
+#define bfin_read_MDMA_S0_CONFIG()		bfin_read16(MDMA_S0_CONFIG)
+#define bfin_write_MDMA_S0_CONFIG(val)		bfin_write16(MDMA_S0_CONFIG, val)
+#define bfin_read_MDMA_S0_NEXT_DESC_PTR()	bfin_read32(MDMA_S0_NEXT_DESC_PTR)
+#define bfin_write_MDMA_S0_NEXT_DESC_PTR(val)	bfin_write32(MDMA_S0_NEXT_DESC_PTR, val)
+#define bfin_read_MDMA_S0_START_ADDR()		bfin_read32(MDMA_S0_START_ADDR)
+#define bfin_write_MDMA_S0_START_ADDR(val)	bfin_write32(MDMA_S0_START_ADDR, val)
+#define bfin_read_MDMA_S0_X_COUNT()		bfin_read16(MDMA_S0_X_COUNT)
+#define bfin_write_MDMA_S0_X_COUNT(val)		bfin_write16(MDMA_S0_X_COUNT, val)
+#define bfin_read_MDMA_S0_Y_COUNT()		bfin_read16(MDMA_S0_Y_COUNT)
+#define bfin_write_MDMA_S0_Y_COUNT(val)		bfin_write16(MDMA_S0_Y_COUNT, val)
+#define bfin_read_MDMA_S0_X_MODIFY()		bfin_read16(MDMA_S0_X_MODIFY)
+#define bfin_write_MDMA_S0_X_MODIFY(val)	bfin_write16(MDMA_S0_X_MODIFY, val)
+#define bfin_read_MDMA_S0_Y_MODIFY()		bfin_read16(MDMA_S0_Y_MODIFY)
+#define bfin_write_MDMA_S0_Y_MODIFY(val)	bfin_write16(MDMA_S0_Y_MODIFY, val)
+#define bfin_read_MDMA_S0_CURR_DESC_PTR()	bfin_read32(MDMA_S0_CURR_DESC_PTR)
+#define bfin_write_MDMA_S0_CURR_DESC_PTR(val)	bfin_write32(MDMA_S0_CURR_DESC_PTR, val)
+#define bfin_read_MDMA_S0_CURR_ADDR()		bfin_read32(MDMA_S0_CURR_ADDR)
+#define bfin_write_MDMA_S0_CURR_ADDR(val)	bfin_write32(MDMA_S0_CURR_ADDR, val)
+#define bfin_read_MDMA_S0_CURR_X_COUNT()	bfin_read16(MDMA_S0_CURR_X_COUNT)
+#define bfin_write_MDMA_S0_CURR_X_COUNT(val)	bfin_write16(MDMA_S0_CURR_X_COUNT, val)
+#define bfin_read_MDMA_S0_CURR_Y_COUNT()	bfin_read16(MDMA_S0_CURR_Y_COUNT)
+#define bfin_write_MDMA_S0_CURR_Y_COUNT(val)	bfin_write16(MDMA_S0_CURR_Y_COUNT, val)
+#define bfin_read_MDMA_S0_IRQ_STATUS()		bfin_read16(MDMA_S0_IRQ_STATUS)
+#define bfin_write_MDMA_S0_IRQ_STATUS(val)	bfin_write16(MDMA_S0_IRQ_STATUS, val)
+#define bfin_read_MDMA_S0_PERIPHERAL_MAP()	bfin_read16(MDMA_S0_PERIPHERAL_MAP)
+#define bfin_write_MDMA_S0_PERIPHERAL_MAP(val)	bfin_write16(MDMA_S0_PERIPHERAL_MAP, val)
+
+#define bfin_read_MDMA_D1_CONFIG()		bfin_read16(MDMA_D1_CONFIG)
+#define bfin_write_MDMA_D1_CONFIG(val)		bfin_write16(MDMA_D1_CONFIG, val)
+#define bfin_read_MDMA_D1_NEXT_DESC_PTR()	bfin_read32(MDMA_D1_NEXT_DESC_PTR)
+#define bfin_write_MDMA_D1_NEXT_DESC_PTR(val)	bfin_write32(MDMA_D1_NEXT_DESC_PTR, val)
+#define bfin_read_MDMA_D1_START_ADDR()		bfin_read32(MDMA_D1_START_ADDR)
+#define bfin_write_MDMA_D1_START_ADDR(val)	bfin_write32(MDMA_D1_START_ADDR, val)
+#define bfin_read_MDMA_D1_X_COUNT()		bfin_read16(MDMA_D1_X_COUNT)
+#define bfin_write_MDMA_D1_X_COUNT(val)		bfin_write16(MDMA_D1_X_COUNT, val)
+#define bfin_read_MDMA_D1_Y_COUNT()		bfin_read16(MDMA_D1_Y_COUNT)
+#define bfin_write_MDMA_D1_Y_COUNT(val)		bfin_write16(MDMA_D1_Y_COUNT, val)
+#define bfin_read_MDMA_D1_X_MODIFY()		bfin_read16(MDMA_D1_X_MODIFY)
+#define bfin_write_MDMA_D1_X_MODIFY(val)	bfin_write16(MDMA_D1_X_MODIFY, val)
+#define bfin_read_MDMA_D1_Y_MODIFY()		bfin_read16(MDMA_D1_Y_MODIFY)
+#define bfin_write_MDMA_D1_Y_MODIFY(val)	bfin_write16(MDMA_D1_Y_MODIFY, val)
+#define bfin_read_MDMA_D1_CURR_DESC_PTR()	bfin_read32(MDMA_D1_CURR_DESC_PTR)
+#define bfin_write_MDMA_D1_CURR_DESC_PTR(val)	bfin_write32(MDMA_D1_CURR_DESC_PTR, val)
+#define bfin_read_MDMA_D1_CURR_ADDR()		bfin_read32(MDMA_D1_CURR_ADDR)
+#define bfin_write_MDMA_D1_CURR_ADDR(val)	bfin_write32(MDMA_D1_CURR_ADDR, val)
+#define bfin_read_MDMA_D1_CURR_X_COUNT()	bfin_read16(MDMA_D1_CURR_X_COUNT)
+#define bfin_write_MDMA_D1_CURR_X_COUNT(val)	bfin_write16(MDMA_D1_CURR_X_COUNT, val)
+#define bfin_read_MDMA_D1_CURR_Y_COUNT()	bfin_read16(MDMA_D1_CURR_Y_COUNT)
+#define bfin_write_MDMA_D1_CURR_Y_COUNT(val)	bfin_write16(MDMA_D1_CURR_Y_COUNT, val)
+#define bfin_read_MDMA_D1_IRQ_STATUS()		bfin_read16(MDMA_D1_IRQ_STATUS)
+#define bfin_write_MDMA_D1_IRQ_STATUS(val)	bfin_write16(MDMA_D1_IRQ_STATUS, val)
+#define bfin_read_MDMA_D1_PERIPHERAL_MAP()	bfin_read16(MDMA_D1_PERIPHERAL_MAP)
+#define bfin_write_MDMA_D1_PERIPHERAL_MAP(val)	bfin_write16(MDMA_D1_PERIPHERAL_MAP, val)
+
+#define bfin_read_MDMA_S1_CONFIG()		bfin_read16(MDMA_S1_CONFIG)
+#define bfin_write_MDMA_S1_CONFIG(val)		bfin_write16(MDMA_S1_CONFIG, val)
+#define bfin_read_MDMA_S1_NEXT_DESC_PTR()	bfin_read32(MDMA_S1_NEXT_DESC_PTR)
+#define bfin_write_MDMA_S1_NEXT_DESC_PTR(val)	bfin_write32(MDMA_S1_NEXT_DESC_PTR, val)
+#define bfin_read_MDMA_S1_START_ADDR()		bfin_read32(MDMA_S1_START_ADDR)
+#define bfin_write_MDMA_S1_START_ADDR(val)	bfin_write32(MDMA_S1_START_ADDR, val)
+#define bfin_read_MDMA_S1_X_COUNT()		bfin_read16(MDMA_S1_X_COUNT)
+#define bfin_write_MDMA_S1_X_COUNT(val)		bfin_write16(MDMA_S1_X_COUNT, val)
+#define bfin_read_MDMA_S1_Y_COUNT()		bfin_read16(MDMA_S1_Y_COUNT)
+#define bfin_write_MDMA_S1_Y_COUNT(val)		bfin_write16(MDMA_S1_Y_COUNT, val)
+#define bfin_read_MDMA_S1_X_MODIFY()		bfin_read16(MDMA_S1_X_MODIFY)
+#define bfin_write_MDMA_S1_X_MODIFY(val)	bfin_write16(MDMA_S1_X_MODIFY, val)
+#define bfin_read_MDMA_S1_Y_MODIFY()		bfin_read16(MDMA_S1_Y_MODIFY)
+#define bfin_write_MDMA_S1_Y_MODIFY(val)	bfin_write16(MDMA_S1_Y_MODIFY, val)
+#define bfin_read_MDMA_S1_CURR_DESC_PTR()	bfin_read32(MDMA_S1_CURR_DESC_PTR)
+#define bfin_write_MDMA_S1_CURR_DESC_PTR(val)	bfin_write32(MDMA_S1_CURR_DESC_PTR, val)
+#define bfin_read_MDMA_S1_CURR_ADDR()		bfin_read32(MDMA_S1_CURR_ADDR)
+#define bfin_write_MDMA_S1_CURR_ADDR(val)	bfin_write32(MDMA_S1_CURR_ADDR, val)
+#define bfin_read_MDMA_S1_CURR_X_COUNT()	bfin_read16(MDMA_S1_CURR_X_COUNT)
+#define bfin_write_MDMA_S1_CURR_X_COUNT(val)	bfin_write16(MDMA_S1_CURR_X_COUNT, val)
+#define bfin_read_MDMA_S1_CURR_Y_COUNT()	bfin_read16(MDMA_S1_CURR_Y_COUNT)
+#define bfin_write_MDMA_S1_CURR_Y_COUNT(val)	bfin_write16(MDMA_S1_CURR_Y_COUNT, val)
+#define bfin_read_MDMA_S1_IRQ_STATUS()		bfin_read16(MDMA_S1_IRQ_STATUS)
+#define bfin_write_MDMA_S1_IRQ_STATUS(val)	bfin_write16(MDMA_S1_IRQ_STATUS, val)
+#define bfin_read_MDMA_S1_PERIPHERAL_MAP()	bfin_read16(MDMA_S1_PERIPHERAL_MAP)
+#define bfin_write_MDMA_S1_PERIPHERAL_MAP(val)	bfin_write16(MDMA_S1_PERIPHERAL_MAP, val)
+
+
+/* Parallel Peripheral Interface (0xFFC01000 - 0xFFC010FF)							*/
+#define bfin_read_PPI_CONTROL()			bfin_read16(PPI_CONTROL)
+#define bfin_write_PPI_CONTROL(val)		bfin_write16(PPI_CONTROL, val)
+#define bfin_read_PPI_STATUS()			bfin_read16(PPI_STATUS)
+#define bfin_write_PPI_STATUS(val)		bfin_write16(PPI_STATUS, val)
+#define bfin_clear_PPI_STATUS()			bfin_write_PPI_STATUS(0xFFFF)
+#define bfin_read_PPI_DELAY()			bfin_read16(PPI_DELAY)
+#define bfin_write_PPI_DELAY(val)		bfin_write16(PPI_DELAY, val)
+#define bfin_read_PPI_COUNT()			bfin_read16(PPI_COUNT)
+#define bfin_write_PPI_COUNT(val)		bfin_write16(PPI_COUNT, val)
+#define bfin_read_PPI_FRAME()			bfin_read16(PPI_FRAME)
+#define bfin_write_PPI_FRAME(val)		bfin_write16(PPI_FRAME, val)
+
+
+/* Two-Wire Interface		(0xFFC01400 - 0xFFC014FF)								*/
+
+/* General Purpose I/O Port G (0xFFC01500 - 0xFFC015FF)								*/
+#define bfin_read_PORTGIO()			bfin_read16(PORTGIO)
+#define bfin_write_PORTGIO(val)			bfin_write16(PORTGIO, val)
+#define bfin_read_PORTGIO_CLEAR()		bfin_read16(PORTGIO_CLEAR)
+#define bfin_write_PORTGIO_CLEAR(val)		bfin_write16(PORTGIO_CLEAR, val)
+#define bfin_read_PORTGIO_SET()			bfin_read16(PORTGIO_SET)
+#define bfin_write_PORTGIO_SET(val)		bfin_write16(PORTGIO_SET, val)
+#define bfin_read_PORTGIO_TOGGLE()		bfin_read16(PORTGIO_TOGGLE)
+#define bfin_write_PORTGIO_TOGGLE(val)		bfin_write16(PORTGIO_TOGGLE, val)
+#define bfin_read_PORTGIO_MASKA()		bfin_read16(PORTGIO_MASKA)
+#define bfin_write_PORTGIO_MASKA(val)		bfin_write16(PORTGIO_MASKA, val)
+#define bfin_read_PORTGIO_MASKA_CLEAR()		bfin_read16(PORTGIO_MASKA_CLEAR)
+#define bfin_write_PORTGIO_MASKA_CLEAR(val)	bfin_write16(PORTGIO_MASKA_CLEAR, val)
+#define bfin_read_PORTGIO_MASKA_SET()		bfin_read16(PORTGIO_MASKA_SET)
+#define bfin_write_PORTGIO_MASKA_SET(val)	bfin_write16(PORTGIO_MASKA_SET, val)
+#define bfin_read_PORTGIO_MASKA_TOGGLE()	bfin_read16(PORTGIO_MASKA_TOGGLE)
+#define bfin_write_PORTGIO_MASKA_TOGGLE(val)	bfin_write16(PORTGIO_MASKA_TOGGLE, val)
+#define bfin_read_PORTGIO_MASKB()		bfin_read16(PORTGIO_MASKB)
+#define bfin_write_PORTGIO_MASKB(val)		bfin_write16(PORTGIO_MASKB, val)
+#define bfin_read_PORTGIO_MASKB_CLEAR()		bfin_read16(PORTGIO_MASKB_CLEAR)
+#define bfin_write_PORTGIO_MASKB_CLEAR(val)	bfin_write16(PORTGIO_MASKB_CLEAR, val)
+#define bfin_read_PORTGIO_MASKB_SET()		bfin_read16(PORTGIO_MASKB_SET)
+#define bfin_write_PORTGIO_MASKB_SET(val)	bfin_write16(PORTGIO_MASKB_SET, val)
+#define bfin_read_PORTGIO_MASKB_TOGGLE()	bfin_read16(PORTGIO_MASKB_TOGGLE)
+#define bfin_write_PORTGIO_MASKB_TOGGLE(val)	bfin_write16(PORTGIO_MASKB_TOGGLE, val)
+#define bfin_read_PORTGIO_DIR()			bfin_read16(PORTGIO_DIR)
+#define bfin_write_PORTGIO_DIR(val)		bfin_write16(PORTGIO_DIR, val)
+#define bfin_read_PORTGIO_POLAR()		bfin_read16(PORTGIO_POLAR)
+#define bfin_write_PORTGIO_POLAR(val)		bfin_write16(PORTGIO_POLAR, val)
+#define bfin_read_PORTGIO_EDGE()		bfin_read16(PORTGIO_EDGE)
+#define bfin_write_PORTGIO_EDGE(val)		bfin_write16(PORTGIO_EDGE, val)
+#define bfin_read_PORTGIO_BOTH()		bfin_read16(PORTGIO_BOTH)
+#define bfin_write_PORTGIO_BOTH(val)		bfin_write16(PORTGIO_BOTH, val)
+#define bfin_read_PORTGIO_INEN()		bfin_read16(PORTGIO_INEN)
+#define bfin_write_PORTGIO_INEN(val)		bfin_write16(PORTGIO_INEN, val)
+
+
+/* General Purpose I/O Port H (0xFFC01700 - 0xFFC017FF)								*/
+#define bfin_read_PORTHIO()			bfin_read16(PORTHIO)
+#define bfin_write_PORTHIO(val)			bfin_write16(PORTHIO, val)
+#define bfin_read_PORTHIO_CLEAR()		bfin_read16(PORTHIO_CLEAR)
+#define bfin_write_PORTHIO_CLEAR(val)		bfin_write16(PORTHIO_CLEAR, val)
+#define bfin_read_PORTHIO_SET()			bfin_read16(PORTHIO_SET)
+#define bfin_write_PORTHIO_SET(val)		bfin_write16(PORTHIO_SET, val)
+#define bfin_read_PORTHIO_TOGGLE()		bfin_read16(PORTHIO_TOGGLE)
+#define bfin_write_PORTHIO_TOGGLE(val)		bfin_write16(PORTHIO_TOGGLE, val)
+#define bfin_read_PORTHIO_MASKA()		bfin_read16(PORTHIO_MASKA)
+#define bfin_write_PORTHIO_MASKA(val)		bfin_write16(PORTHIO_MASKA, val)
+#define bfin_read_PORTHIO_MASKA_CLEAR()		bfin_read16(PORTHIO_MASKA_CLEAR)
+#define bfin_write_PORTHIO_MASKA_CLEAR(val)	bfin_write16(PORTHIO_MASKA_CLEAR, val)
+#define bfin_read_PORTHIO_MASKA_SET()		bfin_read16(PORTHIO_MASKA_SET)
+#define bfin_write_PORTHIO_MASKA_SET(val)	bfin_write16(PORTHIO_MASKA_SET, val)
+#define bfin_read_PORTHIO_MASKA_TOGGLE()	bfin_read16(PORTHIO_MASKA_TOGGLE)
+#define bfin_write_PORTHIO_MASKA_TOGGLE(val)	bfin_write16(PORTHIO_MASKA_TOGGLE, val)
+#define bfin_read_PORTHIO_MASKB()		bfin_read16(PORTHIO_MASKB)
+#define bfin_write_PORTHIO_MASKB(val)		bfin_write16(PORTHIO_MASKB, val)
+#define bfin_read_PORTHIO_MASKB_CLEAR()		bfin_read16(PORTHIO_MASKB_CLEAR)
+#define bfin_write_PORTHIO_MASKB_CLEAR(val)	bfin_write16(PORTHIO_MASKB_CLEAR, val)
+#define bfin_read_PORTHIO_MASKB_SET()		bfin_read16(PORTHIO_MASKB_SET)
+#define bfin_write_PORTHIO_MASKB_SET(val)	bfin_write16(PORTHIO_MASKB_SET, val)
+#define bfin_read_PORTHIO_MASKB_TOGGLE()	bfin_read16(PORTHIO_MASKB_TOGGLE)
+#define bfin_write_PORTHIO_MASKB_TOGGLE(val)	bfin_write16(PORTHIO_MASKB_TOGGLE, val)
+#define bfin_read_PORTHIO_DIR()			bfin_read16(PORTHIO_DIR)
+#define bfin_write_PORTHIO_DIR(val)		bfin_write16(PORTHIO_DIR, val)
+#define bfin_read_PORTHIO_POLAR()		bfin_read16(PORTHIO_POLAR)
+#define bfin_write_PORTHIO_POLAR(val)		bfin_write16(PORTHIO_POLAR, val)
+#define bfin_read_PORTHIO_EDGE()		bfin_read16(PORTHIO_EDGE)
+#define bfin_write_PORTHIO_EDGE(val)		bfin_write16(PORTHIO_EDGE, val)
+#define bfin_read_PORTHIO_BOTH()		bfin_read16(PORTHIO_BOTH)
+#define bfin_write_PORTHIO_BOTH(val)		bfin_write16(PORTHIO_BOTH, val)
+#define bfin_read_PORTHIO_INEN()		bfin_read16(PORTHIO_INEN)
+#define bfin_write_PORTHIO_INEN(val)		bfin_write16(PORTHIO_INEN, val)
+
+
+/* UART1 Controller		(0xFFC02000 - 0xFFC020FF)								*/
+#define bfin_read_UART1_THR()			bfin_read16(UART1_THR)
+#define bfin_write_UART1_THR(val)		bfin_write16(UART1_THR, val)
+#define bfin_read_UART1_RBR()			bfin_read16(UART1_RBR)
+#define bfin_write_UART1_RBR(val)		bfin_write16(UART1_RBR, val)
+#define bfin_read_UART1_DLL()			bfin_read16(UART1_DLL)
+#define bfin_write_UART1_DLL(val)		bfin_write16(UART1_DLL, val)
+#define bfin_read_UART1_IER()			bfin_read16(UART1_IER)
+#define bfin_write_UART1_IER(val)		bfin_write16(UART1_IER, val)
+#define bfin_read_UART1_DLH()			bfin_read16(UART1_DLH)
+#define bfin_write_UART1_DLH(val)		bfin_write16(UART1_DLH, val)
+#define bfin_read_UART1_IIR()			bfin_read16(UART1_IIR)
+#define bfin_write_UART1_IIR(val)		bfin_write16(UART1_IIR, val)
+#define bfin_read_UART1_LCR()			bfin_read16(UART1_LCR)
+#define bfin_write_UART1_LCR(val)		bfin_write16(UART1_LCR, val)
+#define bfin_read_UART1_MCR()			bfin_read16(UART1_MCR)
+#define bfin_write_UART1_MCR(val)		bfin_write16(UART1_MCR, val)
+#define bfin_read_UART1_LSR()			bfin_read16(UART1_LSR)
+#define bfin_write_UART1_LSR(val)		bfin_write16(UART1_LSR, val)
+#define bfin_read_UART1_MSR()			bfin_read16(UART1_MSR)
+#define bfin_write_UART1_MSR(val)		bfin_write16(UART1_MSR, val)
+#define bfin_read_UART1_SCR()			bfin_read16(UART1_SCR)
+#define bfin_write_UART1_SCR(val)		bfin_write16(UART1_SCR, val)
+#define bfin_read_UART1_GCTL()			bfin_read16(UART1_GCTL)
+#define bfin_write_UART1_GCTL(val)		bfin_write16(UART1_GCTL, val)
+
+/* Omit CAN register sets from the cdefBF534.h (CAN is not in the ADSP-BF52x processor) */
+
+/* Pin Control Registers	(0xFFC03200 - 0xFFC032FF)								*/
+#define bfin_read_PORTF_FER()			bfin_read16(PORTF_FER)
+#define bfin_write_PORTF_FER(val)		bfin_write16(PORTF_FER, val)
+#define bfin_read_PORTG_FER()			bfin_read16(PORTG_FER)
+#define bfin_write_PORTG_FER(val)		bfin_write16(PORTG_FER, val)
+#define bfin_read_PORTH_FER()			bfin_read16(PORTH_FER)
+#define bfin_write_PORTH_FER(val)		bfin_write16(PORTH_FER, val)
+#define bfin_read_PORT_MUX()			bfin_read16(PORT_MUX)
+#define bfin_write_PORT_MUX(val)		bfin_write16(PORT_MUX, val)
+
+
+/* Handshake MDMA Registers	(0xFFC03300 - 0xFFC033FF)								*/
+#define bfin_read_HMDMA0_CONTROL()		bfin_read16(HMDMA0_CONTROL)
+#define bfin_write_HMDMA0_CONTROL(val)		bfin_write16(HMDMA0_CONTROL, val)
+#define bfin_read_HMDMA0_ECINIT()		bfin_read16(HMDMA0_ECINIT)
+#define bfin_write_HMDMA0_ECINIT(val)		bfin_write16(HMDMA0_ECINIT, val)
+#define bfin_read_HMDMA0_BCINIT()		bfin_read16(HMDMA0_BCINIT)
+#define bfin_write_HMDMA0_BCINIT(val)		bfin_write16(HMDMA0_BCINIT, val)
+#define bfin_read_HMDMA0_ECURGENT()		bfin_read16(HMDMA0_ECURGENT)
+#define bfin_write_HMDMA0_ECURGENT(val)		bfin_write16(HMDMA0_ECURGENT, val)
+#define bfin_read_HMDMA0_ECOVERFLOW()		bfin_read16(HMDMA0_ECOVERFLOW)
+#define bfin_write_HMDMA0_ECOVERFLOW(val)	bfin_write16(HMDMA0_ECOVERFLOW, val)
+#define bfin_read_HMDMA0_ECOUNT()		bfin_read16(HMDMA0_ECOUNT)
+#define bfin_write_HMDMA0_ECOUNT(val)		bfin_write16(HMDMA0_ECOUNT, val)
+#define bfin_read_HMDMA0_BCOUNT()		bfin_read16(HMDMA0_BCOUNT)
+#define bfin_write_HMDMA0_BCOUNT(val)		bfin_write16(HMDMA0_BCOUNT, val)
+
+#define bfin_read_HMDMA1_CONTROL()		bfin_read16(HMDMA1_CONTROL)
+#define bfin_write_HMDMA1_CONTROL(val)		bfin_write16(HMDMA1_CONTROL, val)
+#define bfin_read_HMDMA1_ECINIT()		bfin_read16(HMDMA1_ECINIT)
+#define bfin_write_HMDMA1_ECINIT(val)		bfin_write16(HMDMA1_ECINIT, val)
+#define bfin_read_HMDMA1_BCINIT()		bfin_read16(HMDMA1_BCINIT)
+#define bfin_write_HMDMA1_BCINIT(val)		bfin_write16(HMDMA1_BCINIT, val)
+#define bfin_read_HMDMA1_ECURGENT()		bfin_read16(HMDMA1_ECURGENT)
+#define bfin_write_HMDMA1_ECURGENT(val)		bfin_write16(HMDMA1_ECURGENT, val)
+#define bfin_read_HMDMA1_ECOVERFLOW()		bfin_read16(HMDMA1_ECOVERFLOW)
+#define bfin_write_HMDMA1_ECOVERFLOW(val)	bfin_write16(HMDMA1_ECOVERFLOW, val)
+#define bfin_read_HMDMA1_ECOUNT()		bfin_read16(HMDMA1_ECOUNT)
+#define bfin_write_HMDMA1_ECOUNT(val)		bfin_write16(HMDMA1_ECOUNT, val)
+#define bfin_read_HMDMA1_BCOUNT()		bfin_read16(HMDMA1_BCOUNT)
+#define bfin_write_HMDMA1_BCOUNT(val)		bfin_write16(HMDMA1_BCOUNT, val)
+
+/* ==== end from cdefBF534.h ==== */
+
+/* GPIO PIN mux (0xFFC03210 - OxFFC03288) */
+
+#define bfin_read_PORTF_MUX()			bfin_read16(PORTF_MUX)
+#define bfin_write_PORTF_MUX(val)		bfin_write16(PORTF_MUX, val)
+#define bfin_read_PORTG_MUX()			bfin_read16(PORTG_MUX)
+#define bfin_write_PORTG_MUX(val)		bfin_write16(PORTG_MUX, val)
+#define bfin_read_PORTH_MUX()			bfin_read16(PORTH_MUX)
+#define bfin_write_PORTH_MUX(val)		bfin_write16(PORTH_MUX, val)
+
+#define bfin_read_PORTF_DRIVE()			bfin_read16(PORTF_DRIVE)
+#define bfin_write_PORTF_DRIVE(val)		bfin_write16(PORTF_DRIVE, val)
+#define bfin_read_PORTG_DRIVE()			bfin_read16(PORTG_DRIVE)
+#define bfin_write_PORTG_DRIVE(val)		bfin_write16(PORTG_DRIVE, val)
+#define bfin_read_PORTH_DRIVE()			bfin_read16(PORTH_DRIVE)
+#define bfin_write_PORTH_DRIVE(val)		bfin_write16(PORTH_DRIVE, val)
+#define bfin_read_PORTF_SLEW()			bfin_read16(PORTF_SLEW)
+#define bfin_write_PORTF_SLEW(val)		bfin_write16(PORTF_SLEW, val)
+#define bfin_read_PORTG_SLEW()			bfin_read16(PORTG_SLEW)
+#define bfin_write_PORTG_SLEW(val)		bfin_write16(PORTG_SLEW, val)
+#define bfin_read_PORTH_SLEW()			bfin_read16(PORTH_SLEW)
+#define bfin_write_PORTH_SLEW(val)		bfin_write16(PORTH_SLEW, val)
+#define bfin_read_PORTF_HYSTERISIS()		bfin_read16(PORTF_HYSTERISIS)
+#define bfin_write_PORTF_HYSTERISIS(val)	bfin_write16(PORTF_HYSTERISIS, val)
+#define bfin_read_PORTG_HYSTERISIS()		bfin_read16(PORTG_HYSTERISIS)
+#define bfin_write_PORTG_HYSTERISIS(val)	bfin_write16(PORTG_HYSTERISIS, val)
+#define bfin_read_PORTH_HYSTERISIS()		bfin_read16(PORTH_HYSTERISIS)
+#define bfin_write_PORTH_HYSTERISIS(val)	bfin_write16(PORTH_HYSTERISIS, val)
+#define bfin_read_MISCPORT_DRIVE()		bfin_read16(MISCPORT_DRIVE)
+#define bfin_write_MISCPORT_DRIVE(val)		bfin_write16(MISCPORT_DRIVE, val)
+#define bfin_read_MISCPORT_SLEW()		bfin_read16(MISCPORT_SLEW)
+#define bfin_write_MISCPORT_SLEW(val)		bfin_write16(MISCPORT_SLEW, val)
+#define bfin_read_MISCPORT_HYSTERISIS()		bfin_read16(MISCPORT_HYSTERISIS)
+#define bfin_write_MISCPORT_HYSTERISIS(val)	bfin_write16(MISCPORT_HYSTERISIS, val)
+
+/* HOST Port Registers */
+
+#define bfin_read_HOST_CONTROL()		bfin_read16(HOST_CONTROL)
+#define bfin_write_HOST_CONTROL(val)		bfin_write16(HOST_CONTROL, val)
+#define bfin_read_HOST_STATUS()			bfin_read16(HOST_STATUS)
+#define bfin_write_HOST_STATUS(val)		bfin_write16(HOST_STATUS, val)
+#define bfin_read_HOST_TIMEOUT()		bfin_read16(HOST_TIMEOUT)
+#define bfin_write_HOST_TIMEOUT(val)		bfin_write16(HOST_TIMEOUT, val)
+
+/* Counter Registers */
+
+#define bfin_read_CNT_CONFIG()			bfin_read16(CNT_CONFIG)
+#define bfin_write_CNT_CONFIG(val)		bfin_write16(CNT_CONFIG, val)
+#define bfin_read_CNT_IMASK()			bfin_read16(CNT_IMASK)
+#define bfin_write_CNT_IMASK(val)		bfin_write16(CNT_IMASK, val)
+#define bfin_read_CNT_STATUS()			bfin_read16(CNT_STATUS)
+#define bfin_write_CNT_STATUS(val)		bfin_write16(CNT_STATUS, val)
+#define bfin_read_CNT_COMMAND()			bfin_read16(CNT_COMMAND)
+#define bfin_write_CNT_COMMAND(val)		bfin_write16(CNT_COMMAND, val)
+#define bfin_read_CNT_DEBOUNCE()		bfin_read16(CNT_DEBOUNCE)
+#define bfin_write_CNT_DEBOUNCE(val)		bfin_write16(CNT_DEBOUNCE, val)
+#define bfin_read_CNT_COUNTER()			bfin_read32(CNT_COUNTER)
+#define bfin_write_CNT_COUNTER(val)		bfin_write32(CNT_COUNTER, val)
+#define bfin_read_CNT_MAX()			bfin_read32(CNT_MAX)
+#define bfin_write_CNT_MAX(val)			bfin_write32(CNT_MAX, val)
+#define bfin_read_CNT_MIN()			bfin_read32(CNT_MIN)
+#define bfin_write_CNT_MIN(val)			bfin_write32(CNT_MIN, val)
+
+/* Security Registers */
+
+#define bfin_read_SECURE_SYSSWT()		bfin_read32(SECURE_SYSSWT)
+#define bfin_write_SECURE_SYSSWT(val)		bfin_write32(SECURE_SYSSWT, val)
+#define bfin_read_SECURE_CONTROL()		bfin_read16(SECURE_CONTROL)
+#define bfin_write_SECURE_CONTROL(val)		bfin_write16(SECURE_CONTROL, val)
+#define bfin_read_SECURE_STATUS()		bfin_read16(SECURE_STATUS)
+#define bfin_write_SECURE_STATUS(val)		bfin_write16(SECURE_STATUS, val)
+
+/* NFC Registers */
+
+#define bfin_read_NFC_CTL()			bfin_read16(NFC_CTL)
+#define bfin_write_NFC_CTL(val)			bfin_write16(NFC_CTL, val)
+#define bfin_read_NFC_STAT()			bfin_read16(NFC_STAT)
+#define bfin_write_NFC_STAT(val)		bfin_write16(NFC_STAT, val)
+#define bfin_read_NFC_IRQSTAT()			bfin_read16(NFC_IRQSTAT)
+#define bfin_write_NFC_IRQSTAT(val)		bfin_write16(NFC_IRQSTAT, val)
+#define bfin_read_NFC_IRQMASK()			bfin_read16(NFC_IRQMASK)
+#define bfin_write_NFC_IRQMASK(val)		bfin_write16(NFC_IRQMASK, val)
+#define bfin_read_NFC_ECC0()			bfin_read16(NFC_ECC0)
+#define bfin_write_NFC_ECC0(val)		bfin_write16(NFC_ECC0, val)
+#define bfin_read_NFC_ECC1()			bfin_read16(NFC_ECC1)
+#define bfin_write_NFC_ECC1(val)		bfin_write16(NFC_ECC1, val)
+#define bfin_read_NFC_ECC2()			bfin_read16(NFC_ECC2)
+#define bfin_write_NFC_ECC2(val)		bfin_write16(NFC_ECC2, val)
+#define bfin_read_NFC_ECC3()			bfin_read16(NFC_ECC3)
+#define bfin_write_NFC_ECC3(val)		bfin_write16(NFC_ECC3, val)
+#define bfin_read_NFC_COUNT()			bfin_read16(NFC_COUNT)
+#define bfin_write_NFC_COUNT(val)		bfin_write16(NFC_COUNT, val)
+#define bfin_read_NFC_RST()			bfin_read16(NFC_RST)
+#define bfin_write_NFC_RST(val)			bfin_write16(NFC_RST, val)
+#define bfin_read_NFC_PGCTL()			bfin_read16(NFC_PGCTL)
+#define bfin_write_NFC_PGCTL(val)		bfin_write16(NFC_PGCTL, val)
+#define bfin_read_NFC_READ()			bfin_read16(NFC_READ)
+#define bfin_write_NFC_READ(val)		bfin_write16(NFC_READ, val)
+#define bfin_read_NFC_ADDR()			bfin_read16(NFC_ADDR)
+#define bfin_write_NFC_ADDR(val)		bfin_write16(NFC_ADDR, val)
+#define bfin_read_NFC_CMD()			bfin_read16(NFC_CMD)
+#define bfin_write_NFC_CMD(val)			bfin_write16(NFC_CMD, val)
+#define bfin_read_NFC_DATA_WR()			bfin_read16(NFC_DATA_WR)
+#define bfin_write_NFC_DATA_WR(val)		bfin_write16(NFC_DATA_WR, val)
+#define bfin_read_NFC_DATA_RD()			bfin_read16(NFC_DATA_RD)
+#define bfin_write_NFC_DATA_RD(val)		bfin_write16(NFC_DATA_RD, val)
 
 #endif /* _CDEF_BF522_H */
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf527/include/mach/cdefBF525.h linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf527/include/mach/cdefBF525.h
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf527/include/mach/cdefBF525.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf527/include/mach/cdefBF525.h	2011-03-14 21:20:32.000000000 -0400
@@ -1,15 +1,12 @@
 /*
- * Copyright 2007-2008 Analog Devices Inc.
+ * Copyright 2007-2010 Analog Devices Inc.
  *
- * Licensed under the GPL-2 or later
+ * Licensed under the GPL-2 or later.
  */
 
 #ifndef _CDEF_BF525_H
 #define _CDEF_BF525_H
 
-/* include all Core registers and bit definitions */
-#include "defBF525.h"
-
 /* BF525 is BF522 + USB */
 #include "cdefBF522.h"
 
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf527/include/mach/cdefBF527.h linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf527/include/mach/cdefBF527.h
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf527/include/mach/cdefBF527.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf527/include/mach/cdefBF527.h	2011-03-14 21:20:32.000000000 -0400
@@ -1,15 +1,12 @@
 /*
- * Copyright 2007-2008 Analog Devices Inc.
+ * Copyright 2007-2010 Analog Devices Inc.
  *
- * Licensed under the GPL-2 or later
+ * Licensed under the GPL-2 or later.
  */
 
 #ifndef _CDEF_BF527_H
 #define _CDEF_BF527_H
 
-/* include all Core registers and bit definitions */
-#include "defBF527.h"
-
 /* BF527 is BF525 + EMAC */
 #include "cdefBF525.h"
 
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf527/include/mach/cdefBF52x_base.h linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf527/include/mach/cdefBF52x_base.h
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf527/include/mach/cdefBF52x_base.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf527/include/mach/cdefBF52x_base.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,1113 +0,0 @@
-/*
- * Copyright 2007-2008 Analog Devices Inc.
- *
- * Licensed under the GPL-2 or later
- */
-
-#ifndef _CDEF_BF52X_H
-#define _CDEF_BF52X_H
-
-#include <asm/blackfin.h>
-
-#include "defBF52x_base.h"
-
-/* Include core specific register pointer definitions 								*/
-#include <asm/cdef_LPBlackfin.h>
-
-/* ==== begin from cdefBF534.h ==== */
-
-/* Clock and System Control	(0xFFC00000 - 0xFFC000FF)								*/
-#define bfin_read_PLL_CTL()			bfin_read16(PLL_CTL)
-#define bfin_read_PLL_DIV()			bfin_read16(PLL_DIV)
-#define bfin_write_PLL_DIV(val)			bfin_write16(PLL_DIV, val)
-#define bfin_read_VR_CTL()			bfin_read16(VR_CTL)
-#define bfin_read_PLL_STAT()			bfin_read16(PLL_STAT)
-#define bfin_write_PLL_STAT(val)		bfin_write16(PLL_STAT, val)
-#define bfin_read_PLL_LOCKCNT()			bfin_read16(PLL_LOCKCNT)
-#define bfin_write_PLL_LOCKCNT(val)		bfin_write16(PLL_LOCKCNT, val)
-#define bfin_read_CHIPID()			bfin_read32(CHIPID)
-#define bfin_write_CHIPID(val)			bfin_write32(CHIPID, val)
-
-
-/* System Interrupt Controller (0xFFC00100 - 0xFFC001FF)							*/
-#define bfin_read_SWRST()			bfin_read16(SWRST)
-#define bfin_write_SWRST(val)			bfin_write16(SWRST, val)
-#define bfin_read_SYSCR()			bfin_read16(SYSCR)
-#define bfin_write_SYSCR(val)			bfin_write16(SYSCR, val)
-
-#define bfin_read_SIC_RVECT()			bfin_read32(SIC_RVECT)
-#define bfin_write_SIC_RVECT(val)		bfin_write32(SIC_RVECT, val)
-#define bfin_read_SIC_IMASK0()			bfin_read32(SIC_IMASK0)
-#define bfin_write_SIC_IMASK0(val)		bfin_write32(SIC_IMASK0, val)
-#define bfin_read_SIC_IMASK(x)			bfin_read32(SIC_IMASK0 + (x << 6))
-#define bfin_write_SIC_IMASK(x, val)		bfin_write32((SIC_IMASK0 + (x << 6)), val)
-
-#define bfin_read_SIC_IAR0()			bfin_read32(SIC_IAR0)
-#define bfin_write_SIC_IAR0(val)		bfin_write32(SIC_IAR0, val)
-#define bfin_read_SIC_IAR1()			bfin_read32(SIC_IAR1)
-#define bfin_write_SIC_IAR1(val)		bfin_write32(SIC_IAR1, val)
-#define bfin_read_SIC_IAR2()			bfin_read32(SIC_IAR2)
-#define bfin_write_SIC_IAR2(val)		bfin_write32(SIC_IAR2, val)
-#define bfin_read_SIC_IAR3()			bfin_read32(SIC_IAR3)
-#define bfin_write_SIC_IAR3(val)		bfin_write32(SIC_IAR3, val)
-
-#define bfin_read_SIC_ISR0()			bfin_read32(SIC_ISR0)
-#define bfin_write_SIC_ISR0(val)		bfin_write32(SIC_ISR0, val)
-#define bfin_read_SIC_ISR(x)			bfin_read32(SIC_ISR0 + (x << 6))
-#define bfin_write_SIC_ISR(x, val)		bfin_write32((SIC_ISR0 + (x << 6)), val)
-
-#define bfin_read_SIC_IWR0()			bfin_read32(SIC_IWR0)
-#define bfin_write_SIC_IWR0(val)		bfin_write32(SIC_IWR0, val)
-#define bfin_read_SIC_IWR(x)			bfin_read32(SIC_IWR0 + (x << 6))
-#define bfin_write_SIC_IWR(x, val)		bfin_write32((SIC_IWR0 + (x << 6)), val)
-
-/* SIC Additions to ADSP-BF52x (0xFFC0014C - 0xFFC00162) */
-
-#define bfin_read_SIC_IMASK1()			bfin_read32(SIC_IMASK1)
-#define bfin_write_SIC_IMASK1(val)		bfin_write32(SIC_IMASK1, val)
-#define bfin_read_SIC_IAR4()			bfin_read32(SIC_IAR4)
-#define bfin_write_SIC_IAR4(val)		bfin_write32(SIC_IAR4, val)
-#define bfin_read_SIC_IAR5()			bfin_read32(SIC_IAR5)
-#define bfin_write_SIC_IAR5(val)		bfin_write32(SIC_IAR5, val)
-#define bfin_read_SIC_IAR6()			bfin_read32(SIC_IAR6)
-#define bfin_write_SIC_IAR6(val)		bfin_write32(SIC_IAR6, val)
-#define bfin_read_SIC_IAR7()			bfin_read32(SIC_IAR7)
-#define bfin_write_SIC_IAR7(val)		bfin_write32(SIC_IAR7, val)
-#define bfin_read_SIC_ISR1()			bfin_read32(SIC_ISR1)
-#define bfin_write_SIC_ISR1(val)		bfin_write32(SIC_ISR1, val)
-#define bfin_read_SIC_IWR1()			bfin_read32(SIC_IWR1)
-#define bfin_write_SIC_IWR1(val)		bfin_write32(SIC_IWR1, val)
-
-/* Watchdog Timer		(0xFFC00200 - 0xFFC002FF)									*/
-#define bfin_read_WDOG_CTL()			bfin_read16(WDOG_CTL)
-#define bfin_write_WDOG_CTL(val)		bfin_write16(WDOG_CTL, val)
-#define bfin_read_WDOG_CNT()			bfin_read32(WDOG_CNT)
-#define bfin_write_WDOG_CNT(val)		bfin_write32(WDOG_CNT, val)
-#define bfin_read_WDOG_STAT()			bfin_read32(WDOG_STAT)
-#define bfin_write_WDOG_STAT(val)		bfin_write32(WDOG_STAT, val)
-
-
-/* Real Time Clock		(0xFFC00300 - 0xFFC003FF)									*/
-#define bfin_read_RTC_STAT()			bfin_read32(RTC_STAT)
-#define bfin_write_RTC_STAT(val)		bfin_write32(RTC_STAT, val)
-#define bfin_read_RTC_ICTL()			bfin_read16(RTC_ICTL)
-#define bfin_write_RTC_ICTL(val)		bfin_write16(RTC_ICTL, val)
-#define bfin_read_RTC_ISTAT()			bfin_read16(RTC_ISTAT)
-#define bfin_write_RTC_ISTAT(val)		bfin_write16(RTC_ISTAT, val)
-#define bfin_read_RTC_SWCNT()			bfin_read16(RTC_SWCNT)
-#define bfin_write_RTC_SWCNT(val)		bfin_write16(RTC_SWCNT, val)
-#define bfin_read_RTC_ALARM()			bfin_read32(RTC_ALARM)
-#define bfin_write_RTC_ALARM(val)		bfin_write32(RTC_ALARM, val)
-#define bfin_read_RTC_FAST()			bfin_read16(RTC_FAST)
-#define bfin_write_RTC_FAST(val)		bfin_write16(RTC_FAST, val)
-#define bfin_read_RTC_PREN()			bfin_read16(RTC_PREN)
-#define bfin_write_RTC_PREN(val)		bfin_write16(RTC_PREN, val)
-
-
-/* UART0 Controller		(0xFFC00400 - 0xFFC004FF)									*/
-#define bfin_read_UART0_THR()			bfin_read16(UART0_THR)
-#define bfin_write_UART0_THR(val)		bfin_write16(UART0_THR, val)
-#define bfin_read_UART0_RBR()			bfin_read16(UART0_RBR)
-#define bfin_write_UART0_RBR(val)		bfin_write16(UART0_RBR, val)
-#define bfin_read_UART0_DLL()			bfin_read16(UART0_DLL)
-#define bfin_write_UART0_DLL(val)		bfin_write16(UART0_DLL, val)
-#define bfin_read_UART0_IER()			bfin_read16(UART0_IER)
-#define bfin_write_UART0_IER(val)		bfin_write16(UART0_IER, val)
-#define bfin_read_UART0_DLH()			bfin_read16(UART0_DLH)
-#define bfin_write_UART0_DLH(val)		bfin_write16(UART0_DLH, val)
-#define bfin_read_UART0_IIR()			bfin_read16(UART0_IIR)
-#define bfin_write_UART0_IIR(val)		bfin_write16(UART0_IIR, val)
-#define bfin_read_UART0_LCR()			bfin_read16(UART0_LCR)
-#define bfin_write_UART0_LCR(val)		bfin_write16(UART0_LCR, val)
-#define bfin_read_UART0_MCR()			bfin_read16(UART0_MCR)
-#define bfin_write_UART0_MCR(val)		bfin_write16(UART0_MCR, val)
-#define bfin_read_UART0_LSR()			bfin_read16(UART0_LSR)
-#define bfin_write_UART0_LSR(val)		bfin_write16(UART0_LSR, val)
-#define bfin_read_UART0_MSR()			bfin_read16(UART0_MSR)
-#define bfin_write_UART0_MSR(val)		bfin_write16(UART0_MSR, val)
-#define bfin_read_UART0_SCR()			bfin_read16(UART0_SCR)
-#define bfin_write_UART0_SCR(val)		bfin_write16(UART0_SCR, val)
-#define bfin_read_UART0_GCTL()			bfin_read16(UART0_GCTL)
-#define bfin_write_UART0_GCTL(val)		bfin_write16(UART0_GCTL, val)
-
-
-/* SPI Controller		(0xFFC00500 - 0xFFC005FF)									*/
-#define bfin_read_SPI_CTL()			bfin_read16(SPI_CTL)
-#define bfin_write_SPI_CTL(val)			bfin_write16(SPI_CTL, val)
-#define bfin_read_SPI_FLG()			bfin_read16(SPI_FLG)
-#define bfin_write_SPI_FLG(val)			bfin_write16(SPI_FLG, val)
-#define bfin_read_SPI_STAT()			bfin_read16(SPI_STAT)
-#define bfin_write_SPI_STAT(val)		bfin_write16(SPI_STAT, val)
-#define bfin_read_SPI_TDBR()			bfin_read16(SPI_TDBR)
-#define bfin_write_SPI_TDBR(val)		bfin_write16(SPI_TDBR, val)
-#define bfin_read_SPI_RDBR()			bfin_read16(SPI_RDBR)
-#define bfin_write_SPI_RDBR(val)		bfin_write16(SPI_RDBR, val)
-#define bfin_read_SPI_BAUD()			bfin_read16(SPI_BAUD)
-#define bfin_write_SPI_BAUD(val)		bfin_write16(SPI_BAUD, val)
-#define bfin_read_SPI_SHADOW()			bfin_read16(SPI_SHADOW)
-#define bfin_write_SPI_SHADOW(val)		bfin_write16(SPI_SHADOW, val)
-
-
-/* TIMER0-7 Registers		(0xFFC00600 - 0xFFC006FF)								*/
-#define bfin_read_TIMER0_CONFIG()		bfin_read16(TIMER0_CONFIG)
-#define bfin_write_TIMER0_CONFIG(val)		bfin_write16(TIMER0_CONFIG, val)
-#define bfin_read_TIMER0_COUNTER()		bfin_read32(TIMER0_COUNTER)
-#define bfin_write_TIMER0_COUNTER(val)		bfin_write32(TIMER0_COUNTER, val)
-#define bfin_read_TIMER0_PERIOD()		bfin_read32(TIMER0_PERIOD)
-#define bfin_write_TIMER0_PERIOD(val)		bfin_write32(TIMER0_PERIOD, val)
-#define bfin_read_TIMER0_WIDTH()		bfin_read32(TIMER0_WIDTH)
-#define bfin_write_TIMER0_WIDTH(val)		bfin_write32(TIMER0_WIDTH, val)
-
-#define bfin_read_TIMER1_CONFIG()		bfin_read16(TIMER1_CONFIG)
-#define bfin_write_TIMER1_CONFIG(val)		bfin_write16(TIMER1_CONFIG, val)
-#define bfin_read_TIMER1_COUNTER()		bfin_read32(TIMER1_COUNTER)
-#define bfin_write_TIMER1_COUNTER(val)		bfin_write32(TIMER1_COUNTER, val)
-#define bfin_read_TIMER1_PERIOD()		bfin_read32(TIMER1_PERIOD)
-#define bfin_write_TIMER1_PERIOD(val)		bfin_write32(TIMER1_PERIOD, val)
-#define bfin_read_TIMER1_WIDTH()		bfin_read32(TIMER1_WIDTH)
-#define bfin_write_TIMER1_WIDTH(val)		bfin_write32(TIMER1_WIDTH, val)
-
-#define bfin_read_TIMER2_CONFIG()		bfin_read16(TIMER2_CONFIG)
-#define bfin_write_TIMER2_CONFIG(val)		bfin_write16(TIMER2_CONFIG, val)
-#define bfin_read_TIMER2_COUNTER()		bfin_read32(TIMER2_COUNTER)
-#define bfin_write_TIMER2_COUNTER(val)		bfin_write32(TIMER2_COUNTER, val)
-#define bfin_read_TIMER2_PERIOD()		bfin_read32(TIMER2_PERIOD)
-#define bfin_write_TIMER2_PERIOD(val)		bfin_write32(TIMER2_PERIOD, val)
-#define bfin_read_TIMER2_WIDTH()		bfin_read32(TIMER2_WIDTH)
-#define bfin_write_TIMER2_WIDTH(val)		bfin_write32(TIMER2_WIDTH, val)
-
-#define bfin_read_TIMER3_CONFIG()		bfin_read16(TIMER3_CONFIG)
-#define bfin_write_TIMER3_CONFIG(val)		bfin_write16(TIMER3_CONFIG, val)
-#define bfin_read_TIMER3_COUNTER()		bfin_read32(TIMER3_COUNTER)
-#define bfin_write_TIMER3_COUNTER(val)		bfin_write32(TIMER3_COUNTER, val)
-#define bfin_read_TIMER3_PERIOD()		bfin_read32(TIMER3_PERIOD)
-#define bfin_write_TIMER3_PERIOD(val)		bfin_write32(TIMER3_PERIOD, val)
-#define bfin_read_TIMER3_WIDTH()		bfin_read32(TIMER3_WIDTH)
-#define bfin_write_TIMER3_WIDTH(val)		bfin_write32(TIMER3_WIDTH, val)
-
-#define bfin_read_TIMER4_CONFIG()		bfin_read16(TIMER4_CONFIG)
-#define bfin_write_TIMER4_CONFIG(val)		bfin_write16(TIMER4_CONFIG, val)
-#define bfin_read_TIMER4_COUNTER()		bfin_read32(TIMER4_COUNTER)
-#define bfin_write_TIMER4_COUNTER(val)		bfin_write32(TIMER4_COUNTER, val)
-#define bfin_read_TIMER4_PERIOD()		bfin_read32(TIMER4_PERIOD)
-#define bfin_write_TIMER4_PERIOD(val)		bfin_write32(TIMER4_PERIOD, val)
-#define bfin_read_TIMER4_WIDTH()		bfin_read32(TIMER4_WIDTH)
-#define bfin_write_TIMER4_WIDTH(val)		bfin_write32(TIMER4_WIDTH, val)
-
-#define bfin_read_TIMER5_CONFIG()		bfin_read16(TIMER5_CONFIG)
-#define bfin_write_TIMER5_CONFIG(val)		bfin_write16(TIMER5_CONFIG, val)
-#define bfin_read_TIMER5_COUNTER()		bfin_read32(TIMER5_COUNTER)
-#define bfin_write_TIMER5_COUNTER(val)		bfin_write32(TIMER5_COUNTER, val)
-#define bfin_read_TIMER5_PERIOD()		bfin_read32(TIMER5_PERIOD)
-#define bfin_write_TIMER5_PERIOD(val)		bfin_write32(TIMER5_PERIOD, val)
-#define bfin_read_TIMER5_WIDTH()		bfin_read32(TIMER5_WIDTH)
-#define bfin_write_TIMER5_WIDTH(val)		bfin_write32(TIMER5_WIDTH, val)
-
-#define bfin_read_TIMER6_CONFIG()		bfin_read16(TIMER6_CONFIG)
-#define bfin_write_TIMER6_CONFIG(val)		bfin_write16(TIMER6_CONFIG, val)
-#define bfin_read_TIMER6_COUNTER()		bfin_read32(TIMER6_COUNTER)
-#define bfin_write_TIMER6_COUNTER(val)		bfin_write32(TIMER6_COUNTER, val)
-#define bfin_read_TIMER6_PERIOD()		bfin_read32(TIMER6_PERIOD)
-#define bfin_write_TIMER6_PERIOD(val)		bfin_write32(TIMER6_PERIOD, val)
-#define bfin_read_TIMER6_WIDTH()		bfin_read32(TIMER6_WIDTH)
-#define bfin_write_TIMER6_WIDTH(val)		bfin_write32(TIMER6_WIDTH, val)
-
-#define bfin_read_TIMER7_CONFIG()		bfin_read16(TIMER7_CONFIG)
-#define bfin_write_TIMER7_CONFIG(val)		bfin_write16(TIMER7_CONFIG, val)
-#define bfin_read_TIMER7_COUNTER()		bfin_read32(TIMER7_COUNTER)
-#define bfin_write_TIMER7_COUNTER(val)		bfin_write32(TIMER7_COUNTER, val)
-#define bfin_read_TIMER7_PERIOD()		bfin_read32(TIMER7_PERIOD)
-#define bfin_write_TIMER7_PERIOD(val)		bfin_write32(TIMER7_PERIOD, val)
-#define bfin_read_TIMER7_WIDTH()		bfin_read32(TIMER7_WIDTH)
-#define bfin_write_TIMER7_WIDTH(val)		bfin_write32(TIMER7_WIDTH, val)
-
-#define bfin_read_TIMER_ENABLE()		bfin_read16(TIMER_ENABLE)
-#define bfin_write_TIMER_ENABLE(val)		bfin_write16(TIMER_ENABLE, val)
-#define bfin_read_TIMER_DISABLE()		bfin_read16(TIMER_DISABLE)
-#define bfin_write_TIMER_DISABLE(val)		bfin_write16(TIMER_DISABLE, val)
-#define bfin_read_TIMER_STATUS()		bfin_read32(TIMER_STATUS)
-#define bfin_write_TIMER_STATUS(val)		bfin_write32(TIMER_STATUS, val)
-
-
-/* General Purpose I/O Port F (0xFFC00700 - 0xFFC007FF)								*/
-#define bfin_read_PORTFIO()			bfin_read16(PORTFIO)
-#define bfin_write_PORTFIO(val)			bfin_write16(PORTFIO, val)
-#define bfin_read_PORTFIO_CLEAR()		bfin_read16(PORTFIO_CLEAR)
-#define bfin_write_PORTFIO_CLEAR(val)		bfin_write16(PORTFIO_CLEAR, val)
-#define bfin_read_PORTFIO_SET()			bfin_read16(PORTFIO_SET)
-#define bfin_write_PORTFIO_SET(val)		bfin_write16(PORTFIO_SET, val)
-#define bfin_read_PORTFIO_TOGGLE()		bfin_read16(PORTFIO_TOGGLE)
-#define bfin_write_PORTFIO_TOGGLE(val)		bfin_write16(PORTFIO_TOGGLE, val)
-#define bfin_read_PORTFIO_MASKA()		bfin_read16(PORTFIO_MASKA)
-#define bfin_write_PORTFIO_MASKA(val)		bfin_write16(PORTFIO_MASKA, val)
-#define bfin_read_PORTFIO_MASKA_CLEAR()		bfin_read16(PORTFIO_MASKA_CLEAR)
-#define bfin_write_PORTFIO_MASKA_CLEAR(val)	bfin_write16(PORTFIO_MASKA_CLEAR, val)
-#define bfin_read_PORTFIO_MASKA_SET()		bfin_read16(PORTFIO_MASKA_SET)
-#define bfin_write_PORTFIO_MASKA_SET(val)	bfin_write16(PORTFIO_MASKA_SET, val)
-#define bfin_read_PORTFIO_MASKA_TOGGLE()	bfin_read16(PORTFIO_MASKA_TOGGLE)
-#define bfin_write_PORTFIO_MASKA_TOGGLE(val)	bfin_write16(PORTFIO_MASKA_TOGGLE, val)
-#define bfin_read_PORTFIO_MASKB()		bfin_read16(PORTFIO_MASKB)
-#define bfin_write_PORTFIO_MASKB(val)		bfin_write16(PORTFIO_MASKB, val)
-#define bfin_read_PORTFIO_MASKB_CLEAR()		bfin_read16(PORTFIO_MASKB_CLEAR)
-#define bfin_write_PORTFIO_MASKB_CLEAR(val)	bfin_write16(PORTFIO_MASKB_CLEAR, val)
-#define bfin_read_PORTFIO_MASKB_SET()		bfin_read16(PORTFIO_MASKB_SET)
-#define bfin_write_PORTFIO_MASKB_SET(val)	bfin_write16(PORTFIO_MASKB_SET, val)
-#define bfin_read_PORTFIO_MASKB_TOGGLE()	bfin_read16(PORTFIO_MASKB_TOGGLE)
-#define bfin_write_PORTFIO_MASKB_TOGGLE(val)	bfin_write16(PORTFIO_MASKB_TOGGLE, val)
-#define bfin_read_PORTFIO_DIR()			bfin_read16(PORTFIO_DIR)
-#define bfin_write_PORTFIO_DIR(val)		bfin_write16(PORTFIO_DIR, val)
-#define bfin_read_PORTFIO_POLAR()		bfin_read16(PORTFIO_POLAR)
-#define bfin_write_PORTFIO_POLAR(val)		bfin_write16(PORTFIO_POLAR, val)
-#define bfin_read_PORTFIO_EDGE()		bfin_read16(PORTFIO_EDGE)
-#define bfin_write_PORTFIO_EDGE(val)		bfin_write16(PORTFIO_EDGE, val)
-#define bfin_read_PORTFIO_BOTH()		bfin_read16(PORTFIO_BOTH)
-#define bfin_write_PORTFIO_BOTH(val)		bfin_write16(PORTFIO_BOTH, val)
-#define bfin_read_PORTFIO_INEN()		bfin_read16(PORTFIO_INEN)
-#define bfin_write_PORTFIO_INEN(val)		bfin_write16(PORTFIO_INEN, val)
-
-
-/* SPORT0 Controller		(0xFFC00800 - 0xFFC008FF)								*/
-#define bfin_read_SPORT0_TCR1()			bfin_read16(SPORT0_TCR1)
-#define bfin_write_SPORT0_TCR1(val)		bfin_write16(SPORT0_TCR1, val)
-#define bfin_read_SPORT0_TCR2()			bfin_read16(SPORT0_TCR2)
-#define bfin_write_SPORT0_TCR2(val)		bfin_write16(SPORT0_TCR2, val)
-#define bfin_read_SPORT0_TCLKDIV()		bfin_read16(SPORT0_TCLKDIV)
-#define bfin_write_SPORT0_TCLKDIV(val)		bfin_write16(SPORT0_TCLKDIV, val)
-#define bfin_read_SPORT0_TFSDIV()		bfin_read16(SPORT0_TFSDIV)
-#define bfin_write_SPORT0_TFSDIV(val)		bfin_write16(SPORT0_TFSDIV, val)
-#define bfin_read_SPORT0_TX()			bfin_read32(SPORT0_TX)
-#define bfin_write_SPORT0_TX(val)		bfin_write32(SPORT0_TX, val)
-#define bfin_read_SPORT0_RX()			bfin_read32(SPORT0_RX)
-#define bfin_write_SPORT0_RX(val)		bfin_write32(SPORT0_RX, val)
-#define bfin_read_SPORT0_TX32()			bfin_read32(SPORT0_TX)
-#define bfin_write_SPORT0_TX32(val)		bfin_write32(SPORT0_TX, val)
-#define bfin_read_SPORT0_RX32()			bfin_read32(SPORT0_RX)
-#define bfin_write_SPORT0_RX32(val)		bfin_write32(SPORT0_RX, val)
-#define bfin_read_SPORT0_TX16()			bfin_read16(SPORT0_TX)
-#define bfin_write_SPORT0_TX16(val)		bfin_write16(SPORT0_TX, val)
-#define bfin_read_SPORT0_RX16()			bfin_read16(SPORT0_RX)
-#define bfin_write_SPORT0_RX16(val)		bfin_write16(SPORT0_RX, val)
-#define bfin_read_SPORT0_RCR1()			bfin_read16(SPORT0_RCR1)
-#define bfin_write_SPORT0_RCR1(val)		bfin_write16(SPORT0_RCR1, val)
-#define bfin_read_SPORT0_RCR2()			bfin_read16(SPORT0_RCR2)
-#define bfin_write_SPORT0_RCR2(val)		bfin_write16(SPORT0_RCR2, val)
-#define bfin_read_SPORT0_RCLKDIV()		bfin_read16(SPORT0_RCLKDIV)
-#define bfin_write_SPORT0_RCLKDIV(val)		bfin_write16(SPORT0_RCLKDIV, val)
-#define bfin_read_SPORT0_RFSDIV()		bfin_read16(SPORT0_RFSDIV)
-#define bfin_write_SPORT0_RFSDIV(val)		bfin_write16(SPORT0_RFSDIV, val)
-#define bfin_read_SPORT0_STAT()			bfin_read16(SPORT0_STAT)
-#define bfin_write_SPORT0_STAT(val)		bfin_write16(SPORT0_STAT, val)
-#define bfin_read_SPORT0_CHNL()			bfin_read16(SPORT0_CHNL)
-#define bfin_write_SPORT0_CHNL(val)		bfin_write16(SPORT0_CHNL, val)
-#define bfin_read_SPORT0_MCMC1()		bfin_read16(SPORT0_MCMC1)
-#define bfin_write_SPORT0_MCMC1(val)		bfin_write16(SPORT0_MCMC1, val)
-#define bfin_read_SPORT0_MCMC2()		bfin_read16(SPORT0_MCMC2)
-#define bfin_write_SPORT0_MCMC2(val)		bfin_write16(SPORT0_MCMC2, val)
-#define bfin_read_SPORT0_MTCS0()		bfin_read32(SPORT0_MTCS0)
-#define bfin_write_SPORT0_MTCS0(val)		bfin_write32(SPORT0_MTCS0, val)
-#define bfin_read_SPORT0_MTCS1()		bfin_read32(SPORT0_MTCS1)
-#define bfin_write_SPORT0_MTCS1(val)		bfin_write32(SPORT0_MTCS1, val)
-#define bfin_read_SPORT0_MTCS2()		bfin_read32(SPORT0_MTCS2)
-#define bfin_write_SPORT0_MTCS2(val)		bfin_write32(SPORT0_MTCS2, val)
-#define bfin_read_SPORT0_MTCS3()		bfin_read32(SPORT0_MTCS3)
-#define bfin_write_SPORT0_MTCS3(val)		bfin_write32(SPORT0_MTCS3, val)
-#define bfin_read_SPORT0_MRCS0()		bfin_read32(SPORT0_MRCS0)
-#define bfin_write_SPORT0_MRCS0(val)		bfin_write32(SPORT0_MRCS0, val)
-#define bfin_read_SPORT0_MRCS1()		bfin_read32(SPORT0_MRCS1)
-#define bfin_write_SPORT0_MRCS1(val)		bfin_write32(SPORT0_MRCS1, val)
-#define bfin_read_SPORT0_MRCS2()		bfin_read32(SPORT0_MRCS2)
-#define bfin_write_SPORT0_MRCS2(val)		bfin_write32(SPORT0_MRCS2, val)
-#define bfin_read_SPORT0_MRCS3()		bfin_read32(SPORT0_MRCS3)
-#define bfin_write_SPORT0_MRCS3(val)		bfin_write32(SPORT0_MRCS3, val)
-
-
-/* SPORT1 Controller		(0xFFC00900 - 0xFFC009FF)								*/
-#define bfin_read_SPORT1_TCR1()			bfin_read16(SPORT1_TCR1)
-#define bfin_write_SPORT1_TCR1(val)		bfin_write16(SPORT1_TCR1, val)
-#define bfin_read_SPORT1_TCR2()			bfin_read16(SPORT1_TCR2)
-#define bfin_write_SPORT1_TCR2(val)		bfin_write16(SPORT1_TCR2, val)
-#define bfin_read_SPORT1_TCLKDIV()		bfin_read16(SPORT1_TCLKDIV)
-#define bfin_write_SPORT1_TCLKDIV(val)		bfin_write16(SPORT1_TCLKDIV, val)
-#define bfin_read_SPORT1_TFSDIV()		bfin_read16(SPORT1_TFSDIV)
-#define bfin_write_SPORT1_TFSDIV(val)		bfin_write16(SPORT1_TFSDIV, val)
-#define bfin_read_SPORT1_TX()			bfin_read32(SPORT1_TX)
-#define bfin_write_SPORT1_TX(val)		bfin_write32(SPORT1_TX, val)
-#define bfin_read_SPORT1_RX()			bfin_read32(SPORT1_RX)
-#define bfin_write_SPORT1_RX(val)		bfin_write32(SPORT1_RX, val)
-#define bfin_read_SPORT1_TX32()			bfin_read32(SPORT1_TX)
-#define bfin_write_SPORT1_TX32(val)		bfin_write32(SPORT1_TX, val)
-#define bfin_read_SPORT1_RX32()			bfin_read32(SPORT1_RX)
-#define bfin_write_SPORT1_RX32(val)		bfin_write32(SPORT1_RX, val)
-#define bfin_read_SPORT1_TX16()			bfin_read16(SPORT1_TX)
-#define bfin_write_SPORT1_TX16(val)		bfin_write16(SPORT1_TX, val)
-#define bfin_read_SPORT1_RX16()			bfin_read16(SPORT1_RX)
-#define bfin_write_SPORT1_RX16(val)		bfin_write16(SPORT1_RX, val)
-#define bfin_read_SPORT1_RCR1()			bfin_read16(SPORT1_RCR1)
-#define bfin_write_SPORT1_RCR1(val)		bfin_write16(SPORT1_RCR1, val)
-#define bfin_read_SPORT1_RCR2()			bfin_read16(SPORT1_RCR2)
-#define bfin_write_SPORT1_RCR2(val)		bfin_write16(SPORT1_RCR2, val)
-#define bfin_read_SPORT1_RCLKDIV()		bfin_read16(SPORT1_RCLKDIV)
-#define bfin_write_SPORT1_RCLKDIV(val)		bfin_write16(SPORT1_RCLKDIV, val)
-#define bfin_read_SPORT1_RFSDIV()		bfin_read16(SPORT1_RFSDIV)
-#define bfin_write_SPORT1_RFSDIV(val)		bfin_write16(SPORT1_RFSDIV, val)
-#define bfin_read_SPORT1_STAT()			bfin_read16(SPORT1_STAT)
-#define bfin_write_SPORT1_STAT(val)		bfin_write16(SPORT1_STAT, val)
-#define bfin_read_SPORT1_CHNL()			bfin_read16(SPORT1_CHNL)
-#define bfin_write_SPORT1_CHNL(val)		bfin_write16(SPORT1_CHNL, val)
-#define bfin_read_SPORT1_MCMC1()		bfin_read16(SPORT1_MCMC1)
-#define bfin_write_SPORT1_MCMC1(val)		bfin_write16(SPORT1_MCMC1, val)
-#define bfin_read_SPORT1_MCMC2()		bfin_read16(SPORT1_MCMC2)
-#define bfin_write_SPORT1_MCMC2(val)		bfin_write16(SPORT1_MCMC2, val)
-#define bfin_read_SPORT1_MTCS0()		bfin_read32(SPORT1_MTCS0)
-#define bfin_write_SPORT1_MTCS0(val)		bfin_write32(SPORT1_MTCS0, val)
-#define bfin_read_SPORT1_MTCS1()		bfin_read32(SPORT1_MTCS1)
-#define bfin_write_SPORT1_MTCS1(val)		bfin_write32(SPORT1_MTCS1, val)
-#define bfin_read_SPORT1_MTCS2()		bfin_read32(SPORT1_MTCS2)
-#define bfin_write_SPORT1_MTCS2(val)		bfin_write32(SPORT1_MTCS2, val)
-#define bfin_read_SPORT1_MTCS3()		bfin_read32(SPORT1_MTCS3)
-#define bfin_write_SPORT1_MTCS3(val)		bfin_write32(SPORT1_MTCS3, val)
-#define bfin_read_SPORT1_MRCS0()		bfin_read32(SPORT1_MRCS0)
-#define bfin_write_SPORT1_MRCS0(val)		bfin_write32(SPORT1_MRCS0, val)
-#define bfin_read_SPORT1_MRCS1()		bfin_read32(SPORT1_MRCS1)
-#define bfin_write_SPORT1_MRCS1(val)		bfin_write32(SPORT1_MRCS1, val)
-#define bfin_read_SPORT1_MRCS2()		bfin_read32(SPORT1_MRCS2)
-#define bfin_write_SPORT1_MRCS2(val)		bfin_write32(SPORT1_MRCS2, val)
-#define bfin_read_SPORT1_MRCS3()		bfin_read32(SPORT1_MRCS3)
-#define bfin_write_SPORT1_MRCS3(val)		bfin_write32(SPORT1_MRCS3, val)
-
-
-/* External Bus Interface Unit (0xFFC00A00 - 0xFFC00AFF)							*/
-#define bfin_read_EBIU_AMGCTL()			bfin_read16(EBIU_AMGCTL)
-#define bfin_write_EBIU_AMGCTL(val)		bfin_write16(EBIU_AMGCTL, val)
-#define bfin_read_EBIU_AMBCTL0()		bfin_read32(EBIU_AMBCTL0)
-#define bfin_write_EBIU_AMBCTL0(val)		bfin_write32(EBIU_AMBCTL0, val)
-#define bfin_read_EBIU_AMBCTL1()		bfin_read32(EBIU_AMBCTL1)
-#define bfin_write_EBIU_AMBCTL1(val)		bfin_write32(EBIU_AMBCTL1, val)
-#define bfin_read_EBIU_SDGCTL()			bfin_read32(EBIU_SDGCTL)
-#define bfin_write_EBIU_SDGCTL(val)		bfin_write32(EBIU_SDGCTL, val)
-#define bfin_read_EBIU_SDBCTL()			bfin_read16(EBIU_SDBCTL)
-#define bfin_write_EBIU_SDBCTL(val)		bfin_write16(EBIU_SDBCTL, val)
-#define bfin_read_EBIU_SDRRC()			bfin_read16(EBIU_SDRRC)
-#define bfin_write_EBIU_SDRRC(val)		bfin_write16(EBIU_SDRRC, val)
-#define bfin_read_EBIU_SDSTAT()			bfin_read16(EBIU_SDSTAT)
-#define bfin_write_EBIU_SDSTAT(val)		bfin_write16(EBIU_SDSTAT, val)
-
-
-/* DMA Traffic Control Registers													*/
-#define bfin_read_DMA_TC_PER()			bfin_read16(DMA_TC_PER)
-#define bfin_write_DMA_TC_PER(val)		bfin_write16(DMA_TC_PER, val)
-#define bfin_read_DMA_TC_CNT()			bfin_read16(DMA_TC_CNT)
-#define bfin_write_DMA_TC_CNT(val)		bfin_write16(DMA_TC_CNT, val)
-
-/* Alternate deprecated register names (below) provided for backwards code compatibility */
-#define bfin_read_DMA_TCPER()			bfin_read16(DMA_TCPER)
-#define bfin_write_DMA_TCPER(val)		bfin_write16(DMA_TCPER, val)
-#define bfin_read_DMA_TCCNT()			bfin_read16(DMA_TCCNT)
-#define bfin_write_DMA_TCCNT(val)		bfin_write16(DMA_TCCNT, val)
-
-/* DMA Controller																	*/
-#define bfin_read_DMA0_CONFIG()			bfin_read16(DMA0_CONFIG)
-#define bfin_write_DMA0_CONFIG(val)		bfin_write16(DMA0_CONFIG, val)
-#define bfin_read_DMA0_NEXT_DESC_PTR()		bfin_read32(DMA0_NEXT_DESC_PTR)
-#define bfin_write_DMA0_NEXT_DESC_PTR(val)	bfin_write32(DMA0_NEXT_DESC_PTR, val)
-#define bfin_read_DMA0_START_ADDR()		bfin_read32(DMA0_START_ADDR)
-#define bfin_write_DMA0_START_ADDR(val)		bfin_write32(DMA0_START_ADDR, val)
-#define bfin_read_DMA0_X_COUNT()		bfin_read16(DMA0_X_COUNT)
-#define bfin_write_DMA0_X_COUNT(val)		bfin_write16(DMA0_X_COUNT, val)
-#define bfin_read_DMA0_Y_COUNT()		bfin_read16(DMA0_Y_COUNT)
-#define bfin_write_DMA0_Y_COUNT(val)		bfin_write16(DMA0_Y_COUNT, val)
-#define bfin_read_DMA0_X_MODIFY()		bfin_read16(DMA0_X_MODIFY)
-#define bfin_write_DMA0_X_MODIFY(val)		bfin_write16(DMA0_X_MODIFY, val)
-#define bfin_read_DMA0_Y_MODIFY()		bfin_read16(DMA0_Y_MODIFY)
-#define bfin_write_DMA0_Y_MODIFY(val)		bfin_write16(DMA0_Y_MODIFY, val)
-#define bfin_read_DMA0_CURR_DESC_PTR()		bfin_read32(DMA0_CURR_DESC_PTR)
-#define bfin_write_DMA0_CURR_DESC_PTR(val)	bfin_write32(DMA0_CURR_DESC_PTR, val)
-#define bfin_read_DMA0_CURR_ADDR()		bfin_read32(DMA0_CURR_ADDR)
-#define bfin_write_DMA0_CURR_ADDR(val)		bfin_write32(DMA0_CURR_ADDR, val)
-#define bfin_read_DMA0_CURR_X_COUNT()		bfin_read16(DMA0_CURR_X_COUNT)
-#define bfin_write_DMA0_CURR_X_COUNT(val)	bfin_write16(DMA0_CURR_X_COUNT, val)
-#define bfin_read_DMA0_CURR_Y_COUNT()		bfin_read16(DMA0_CURR_Y_COUNT)
-#define bfin_write_DMA0_CURR_Y_COUNT(val)	bfin_write16(DMA0_CURR_Y_COUNT, val)
-#define bfin_read_DMA0_IRQ_STATUS()		bfin_read16(DMA0_IRQ_STATUS)
-#define bfin_write_DMA0_IRQ_STATUS(val)		bfin_write16(DMA0_IRQ_STATUS, val)
-#define bfin_read_DMA0_PERIPHERAL_MAP()		bfin_read16(DMA0_PERIPHERAL_MAP)
-#define bfin_write_DMA0_PERIPHERAL_MAP(val)	bfin_write16(DMA0_PERIPHERAL_MAP, val)
-
-#define bfin_read_DMA1_CONFIG()			bfin_read16(DMA1_CONFIG)
-#define bfin_write_DMA1_CONFIG(val)		bfin_write16(DMA1_CONFIG, val)
-#define bfin_read_DMA1_NEXT_DESC_PTR()		bfin_read32(DMA1_NEXT_DESC_PTR)
-#define bfin_write_DMA1_NEXT_DESC_PTR(val)	bfin_write32(DMA1_NEXT_DESC_PTR, val)
-#define bfin_read_DMA1_START_ADDR()		bfin_read32(DMA1_START_ADDR)
-#define bfin_write_DMA1_START_ADDR(val)		bfin_write32(DMA1_START_ADDR, val)
-#define bfin_read_DMA1_X_COUNT()		bfin_read16(DMA1_X_COUNT)
-#define bfin_write_DMA1_X_COUNT(val)		bfin_write16(DMA1_X_COUNT, val)
-#define bfin_read_DMA1_Y_COUNT()		bfin_read16(DMA1_Y_COUNT)
-#define bfin_write_DMA1_Y_COUNT(val)		bfin_write16(DMA1_Y_COUNT, val)
-#define bfin_read_DMA1_X_MODIFY()		bfin_read16(DMA1_X_MODIFY)
-#define bfin_write_DMA1_X_MODIFY(val)		bfin_write16(DMA1_X_MODIFY, val)
-#define bfin_read_DMA1_Y_MODIFY()		bfin_read16(DMA1_Y_MODIFY)
-#define bfin_write_DMA1_Y_MODIFY(val)		bfin_write16(DMA1_Y_MODIFY, val)
-#define bfin_read_DMA1_CURR_DESC_PTR()		bfin_read32(DMA1_CURR_DESC_PTR)
-#define bfin_write_DMA1_CURR_DESC_PTR(val)	bfin_write32(DMA1_CURR_DESC_PTR, val)
-#define bfin_read_DMA1_CURR_ADDR()		bfin_read32(DMA1_CURR_ADDR)
-#define bfin_write_DMA1_CURR_ADDR(val)		bfin_write32(DMA1_CURR_ADDR, val)
-#define bfin_read_DMA1_CURR_X_COUNT()		bfin_read16(DMA1_CURR_X_COUNT)
-#define bfin_write_DMA1_CURR_X_COUNT(val)	bfin_write16(DMA1_CURR_X_COUNT, val)
-#define bfin_read_DMA1_CURR_Y_COUNT()		bfin_read16(DMA1_CURR_Y_COUNT)
-#define bfin_write_DMA1_CURR_Y_COUNT(val)	bfin_write16(DMA1_CURR_Y_COUNT, val)
-#define bfin_read_DMA1_IRQ_STATUS()		bfin_read16(DMA1_IRQ_STATUS)
-#define bfin_write_DMA1_IRQ_STATUS(val)		bfin_write16(DMA1_IRQ_STATUS, val)
-#define bfin_read_DMA1_PERIPHERAL_MAP()		bfin_read16(DMA1_PERIPHERAL_MAP)
-#define bfin_write_DMA1_PERIPHERAL_MAP(val)	bfin_write16(DMA1_PERIPHERAL_MAP, val)
-
-#define bfin_read_DMA2_CONFIG()			bfin_read16(DMA2_CONFIG)
-#define bfin_write_DMA2_CONFIG(val)		bfin_write16(DMA2_CONFIG, val)
-#define bfin_read_DMA2_NEXT_DESC_PTR()		bfin_read32(DMA2_NEXT_DESC_PTR)
-#define bfin_write_DMA2_NEXT_DESC_PTR(val)	bfin_write32(DMA2_NEXT_DESC_PTR, val)
-#define bfin_read_DMA2_START_ADDR()		bfin_read32(DMA2_START_ADDR)
-#define bfin_write_DMA2_START_ADDR(val)		bfin_write32(DMA2_START_ADDR, val)
-#define bfin_read_DMA2_X_COUNT()		bfin_read16(DMA2_X_COUNT)
-#define bfin_write_DMA2_X_COUNT(val)		bfin_write16(DMA2_X_COUNT, val)
-#define bfin_read_DMA2_Y_COUNT()		bfin_read16(DMA2_Y_COUNT)
-#define bfin_write_DMA2_Y_COUNT(val)		bfin_write16(DMA2_Y_COUNT, val)
-#define bfin_read_DMA2_X_MODIFY()		bfin_read16(DMA2_X_MODIFY)
-#define bfin_write_DMA2_X_MODIFY(val)		bfin_write16(DMA2_X_MODIFY, val)
-#define bfin_read_DMA2_Y_MODIFY()		bfin_read16(DMA2_Y_MODIFY)
-#define bfin_write_DMA2_Y_MODIFY(val)		bfin_write16(DMA2_Y_MODIFY, val)
-#define bfin_read_DMA2_CURR_DESC_PTR()		bfin_read32(DMA2_CURR_DESC_PTR)
-#define bfin_write_DMA2_CURR_DESC_PTR(val)	bfin_write32(DMA2_CURR_DESC_PTR, val)
-#define bfin_read_DMA2_CURR_ADDR()		bfin_read32(DMA2_CURR_ADDR)
-#define bfin_write_DMA2_CURR_ADDR(val)		bfin_write32(DMA2_CURR_ADDR, val)
-#define bfin_read_DMA2_CURR_X_COUNT()		bfin_read16(DMA2_CURR_X_COUNT)
-#define bfin_write_DMA2_CURR_X_COUNT(val)	bfin_write16(DMA2_CURR_X_COUNT, val)
-#define bfin_read_DMA2_CURR_Y_COUNT()		bfin_read16(DMA2_CURR_Y_COUNT)
-#define bfin_write_DMA2_CURR_Y_COUNT(val)	bfin_write16(DMA2_CURR_Y_COUNT, val)
-#define bfin_read_DMA2_IRQ_STATUS()		bfin_read16(DMA2_IRQ_STATUS)
-#define bfin_write_DMA2_IRQ_STATUS(val)		bfin_write16(DMA2_IRQ_STATUS, val)
-#define bfin_read_DMA2_PERIPHERAL_MAP()		bfin_read16(DMA2_PERIPHERAL_MAP)
-#define bfin_write_DMA2_PERIPHERAL_MAP(val)	bfin_write16(DMA2_PERIPHERAL_MAP, val)
-
-#define bfin_read_DMA3_CONFIG()			bfin_read16(DMA3_CONFIG)
-#define bfin_write_DMA3_CONFIG(val)		bfin_write16(DMA3_CONFIG, val)
-#define bfin_read_DMA3_NEXT_DESC_PTR()		bfin_read32(DMA3_NEXT_DESC_PTR)
-#define bfin_write_DMA3_NEXT_DESC_PTR(val)	bfin_write32(DMA3_NEXT_DESC_PTR, val)
-#define bfin_read_DMA3_START_ADDR()		bfin_read32(DMA3_START_ADDR)
-#define bfin_write_DMA3_START_ADDR(val)		bfin_write32(DMA3_START_ADDR, val)
-#define bfin_read_DMA3_X_COUNT()		bfin_read16(DMA3_X_COUNT)
-#define bfin_write_DMA3_X_COUNT(val)		bfin_write16(DMA3_X_COUNT, val)
-#define bfin_read_DMA3_Y_COUNT()		bfin_read16(DMA3_Y_COUNT)
-#define bfin_write_DMA3_Y_COUNT(val)		bfin_write16(DMA3_Y_COUNT, val)
-#define bfin_read_DMA3_X_MODIFY()		bfin_read16(DMA3_X_MODIFY)
-#define bfin_write_DMA3_X_MODIFY(val)		bfin_write16(DMA3_X_MODIFY, val)
-#define bfin_read_DMA3_Y_MODIFY()		bfin_read16(DMA3_Y_MODIFY)
-#define bfin_write_DMA3_Y_MODIFY(val)		bfin_write16(DMA3_Y_MODIFY, val)
-#define bfin_read_DMA3_CURR_DESC_PTR()		bfin_read32(DMA3_CURR_DESC_PTR)
-#define bfin_write_DMA3_CURR_DESC_PTR(val)	bfin_write32(DMA3_CURR_DESC_PTR, val)
-#define bfin_read_DMA3_CURR_ADDR()		bfin_read32(DMA3_CURR_ADDR)
-#define bfin_write_DMA3_CURR_ADDR(val)		bfin_write32(DMA3_CURR_ADDR, val)
-#define bfin_read_DMA3_CURR_X_COUNT()		bfin_read16(DMA3_CURR_X_COUNT)
-#define bfin_write_DMA3_CURR_X_COUNT(val)	bfin_write16(DMA3_CURR_X_COUNT, val)
-#define bfin_read_DMA3_CURR_Y_COUNT()		bfin_read16(DMA3_CURR_Y_COUNT)
-#define bfin_write_DMA3_CURR_Y_COUNT(val)	bfin_write16(DMA3_CURR_Y_COUNT, val)
-#define bfin_read_DMA3_IRQ_STATUS()		bfin_read16(DMA3_IRQ_STATUS)
-#define bfin_write_DMA3_IRQ_STATUS(val)		bfin_write16(DMA3_IRQ_STATUS, val)
-#define bfin_read_DMA3_PERIPHERAL_MAP()		bfin_read16(DMA3_PERIPHERAL_MAP)
-#define bfin_write_DMA3_PERIPHERAL_MAP(val)	bfin_write16(DMA3_PERIPHERAL_MAP, val)
-
-#define bfin_read_DMA4_CONFIG()			bfin_read16(DMA4_CONFIG)
-#define bfin_write_DMA4_CONFIG(val)		bfin_write16(DMA4_CONFIG, val)
-#define bfin_read_DMA4_NEXT_DESC_PTR()		bfin_read32(DMA4_NEXT_DESC_PTR)
-#define bfin_write_DMA4_NEXT_DESC_PTR(val)	bfin_write32(DMA4_NEXT_DESC_PTR, val)
-#define bfin_read_DMA4_START_ADDR()		bfin_read32(DMA4_START_ADDR)
-#define bfin_write_DMA4_START_ADDR(val)		bfin_write32(DMA4_START_ADDR, val)
-#define bfin_read_DMA4_X_COUNT()		bfin_read16(DMA4_X_COUNT)
-#define bfin_write_DMA4_X_COUNT(val)		bfin_write16(DMA4_X_COUNT, val)
-#define bfin_read_DMA4_Y_COUNT()		bfin_read16(DMA4_Y_COUNT)
-#define bfin_write_DMA4_Y_COUNT(val)		bfin_write16(DMA4_Y_COUNT, val)
-#define bfin_read_DMA4_X_MODIFY()		bfin_read16(DMA4_X_MODIFY)
-#define bfin_write_DMA4_X_MODIFY(val)		bfin_write16(DMA4_X_MODIFY, val)
-#define bfin_read_DMA4_Y_MODIFY()		bfin_read16(DMA4_Y_MODIFY)
-#define bfin_write_DMA4_Y_MODIFY(val)		bfin_write16(DMA4_Y_MODIFY, val)
-#define bfin_read_DMA4_CURR_DESC_PTR()		bfin_read32(DMA4_CURR_DESC_PTR)
-#define bfin_write_DMA4_CURR_DESC_PTR(val)	bfin_write32(DMA4_CURR_DESC_PTR, val)
-#define bfin_read_DMA4_CURR_ADDR()		bfin_read32(DMA4_CURR_ADDR)
-#define bfin_write_DMA4_CURR_ADDR(val)		bfin_write32(DMA4_CURR_ADDR, val)
-#define bfin_read_DMA4_CURR_X_COUNT()		bfin_read16(DMA4_CURR_X_COUNT)
-#define bfin_write_DMA4_CURR_X_COUNT(val)	bfin_write16(DMA4_CURR_X_COUNT, val)
-#define bfin_read_DMA4_CURR_Y_COUNT()		bfin_read16(DMA4_CURR_Y_COUNT)
-#define bfin_write_DMA4_CURR_Y_COUNT(val)	bfin_write16(DMA4_CURR_Y_COUNT, val)
-#define bfin_read_DMA4_IRQ_STATUS()		bfin_read16(DMA4_IRQ_STATUS)
-#define bfin_write_DMA4_IRQ_STATUS(val)		bfin_write16(DMA4_IRQ_STATUS, val)
-#define bfin_read_DMA4_PERIPHERAL_MAP()		bfin_read16(DMA4_PERIPHERAL_MAP)
-#define bfin_write_DMA4_PERIPHERAL_MAP(val)	bfin_write16(DMA4_PERIPHERAL_MAP, val)
-
-#define bfin_read_DMA5_CONFIG()			bfin_read16(DMA5_CONFIG)
-#define bfin_write_DMA5_CONFIG(val)		bfin_write16(DMA5_CONFIG, val)
-#define bfin_read_DMA5_NEXT_DESC_PTR()		bfin_read32(DMA5_NEXT_DESC_PTR)
-#define bfin_write_DMA5_NEXT_DESC_PTR(val)	bfin_write32(DMA5_NEXT_DESC_PTR, val)
-#define bfin_read_DMA5_START_ADDR()		bfin_read32(DMA5_START_ADDR)
-#define bfin_write_DMA5_START_ADDR(val)		bfin_write32(DMA5_START_ADDR, val)
-#define bfin_read_DMA5_X_COUNT()		bfin_read16(DMA5_X_COUNT)
-#define bfin_write_DMA5_X_COUNT(val)		bfin_write16(DMA5_X_COUNT, val)
-#define bfin_read_DMA5_Y_COUNT()		bfin_read16(DMA5_Y_COUNT)
-#define bfin_write_DMA5_Y_COUNT(val)		bfin_write16(DMA5_Y_COUNT, val)
-#define bfin_read_DMA5_X_MODIFY()		bfin_read16(DMA5_X_MODIFY)
-#define bfin_write_DMA5_X_MODIFY(val)		bfin_write16(DMA5_X_MODIFY, val)
-#define bfin_read_DMA5_Y_MODIFY()		bfin_read16(DMA5_Y_MODIFY)
-#define bfin_write_DMA5_Y_MODIFY(val)		bfin_write16(DMA5_Y_MODIFY, val)
-#define bfin_read_DMA5_CURR_DESC_PTR()		bfin_read32(DMA5_CURR_DESC_PTR)
-#define bfin_write_DMA5_CURR_DESC_PTR(val)	bfin_write32(DMA5_CURR_DESC_PTR, val)
-#define bfin_read_DMA5_CURR_ADDR()		bfin_read32(DMA5_CURR_ADDR)
-#define bfin_write_DMA5_CURR_ADDR(val)		bfin_write32(DMA5_CURR_ADDR, val)
-#define bfin_read_DMA5_CURR_X_COUNT()		bfin_read16(DMA5_CURR_X_COUNT)
-#define bfin_write_DMA5_CURR_X_COUNT(val)	bfin_write16(DMA5_CURR_X_COUNT, val)
-#define bfin_read_DMA5_CURR_Y_COUNT()		bfin_read16(DMA5_CURR_Y_COUNT)
-#define bfin_write_DMA5_CURR_Y_COUNT(val)	bfin_write16(DMA5_CURR_Y_COUNT, val)
-#define bfin_read_DMA5_IRQ_STATUS()		bfin_read16(DMA5_IRQ_STATUS)
-#define bfin_write_DMA5_IRQ_STATUS(val)		bfin_write16(DMA5_IRQ_STATUS, val)
-#define bfin_read_DMA5_PERIPHERAL_MAP()		bfin_read16(DMA5_PERIPHERAL_MAP)
-#define bfin_write_DMA5_PERIPHERAL_MAP(val)	bfin_write16(DMA5_PERIPHERAL_MAP, val)
-
-#define bfin_read_DMA6_CONFIG()			bfin_read16(DMA6_CONFIG)
-#define bfin_write_DMA6_CONFIG(val)		bfin_write16(DMA6_CONFIG, val)
-#define bfin_read_DMA6_NEXT_DESC_PTR()		bfin_read32(DMA6_NEXT_DESC_PTR)
-#define bfin_write_DMA6_NEXT_DESC_PTR(val)	bfin_write32(DMA6_NEXT_DESC_PTR, val)
-#define bfin_read_DMA6_START_ADDR()		bfin_read32(DMA6_START_ADDR)
-#define bfin_write_DMA6_START_ADDR(val)		bfin_write32(DMA6_START_ADDR, val)
-#define bfin_read_DMA6_X_COUNT()		bfin_read16(DMA6_X_COUNT)
-#define bfin_write_DMA6_X_COUNT(val)		bfin_write16(DMA6_X_COUNT, val)
-#define bfin_read_DMA6_Y_COUNT()		bfin_read16(DMA6_Y_COUNT)
-#define bfin_write_DMA6_Y_COUNT(val)		bfin_write16(DMA6_Y_COUNT, val)
-#define bfin_read_DMA6_X_MODIFY()		bfin_read16(DMA6_X_MODIFY)
-#define bfin_write_DMA6_X_MODIFY(val)		bfin_write16(DMA6_X_MODIFY, val)
-#define bfin_read_DMA6_Y_MODIFY()		bfin_read16(DMA6_Y_MODIFY)
-#define bfin_write_DMA6_Y_MODIFY(val)		bfin_write16(DMA6_Y_MODIFY, val)
-#define bfin_read_DMA6_CURR_DESC_PTR()		bfin_read32(DMA6_CURR_DESC_PTR)
-#define bfin_write_DMA6_CURR_DESC_PTR(val)	bfin_write32(DMA6_CURR_DESC_PTR, val)
-#define bfin_read_DMA6_CURR_ADDR()		bfin_read32(DMA6_CURR_ADDR)
-#define bfin_write_DMA6_CURR_ADDR(val)		bfin_write32(DMA6_CURR_ADDR, val)
-#define bfin_read_DMA6_CURR_X_COUNT()		bfin_read16(DMA6_CURR_X_COUNT)
-#define bfin_write_DMA6_CURR_X_COUNT(val)	bfin_write16(DMA6_CURR_X_COUNT, val)
-#define bfin_read_DMA6_CURR_Y_COUNT()		bfin_read16(DMA6_CURR_Y_COUNT)
-#define bfin_write_DMA6_CURR_Y_COUNT(val)	bfin_write16(DMA6_CURR_Y_COUNT, val)
-#define bfin_read_DMA6_IRQ_STATUS()		bfin_read16(DMA6_IRQ_STATUS)
-#define bfin_write_DMA6_IRQ_STATUS(val)		bfin_write16(DMA6_IRQ_STATUS, val)
-#define bfin_read_DMA6_PERIPHERAL_MAP()		bfin_read16(DMA6_PERIPHERAL_MAP)
-#define bfin_write_DMA6_PERIPHERAL_MAP(val)	bfin_write16(DMA6_PERIPHERAL_MAP, val)
-
-#define bfin_read_DMA7_CONFIG()			bfin_read16(DMA7_CONFIG)
-#define bfin_write_DMA7_CONFIG(val)		bfin_write16(DMA7_CONFIG, val)
-#define bfin_read_DMA7_NEXT_DESC_PTR()		bfin_read32(DMA7_NEXT_DESC_PTR)
-#define bfin_write_DMA7_NEXT_DESC_PTR(val)	bfin_write32(DMA7_NEXT_DESC_PTR, val)
-#define bfin_read_DMA7_START_ADDR()		bfin_read32(DMA7_START_ADDR)
-#define bfin_write_DMA7_START_ADDR(val)		bfin_write32(DMA7_START_ADDR, val)
-#define bfin_read_DMA7_X_COUNT()		bfin_read16(DMA7_X_COUNT)
-#define bfin_write_DMA7_X_COUNT(val)		bfin_write16(DMA7_X_COUNT, val)
-#define bfin_read_DMA7_Y_COUNT()		bfin_read16(DMA7_Y_COUNT)
-#define bfin_write_DMA7_Y_COUNT(val)		bfin_write16(DMA7_Y_COUNT, val)
-#define bfin_read_DMA7_X_MODIFY()		bfin_read16(DMA7_X_MODIFY)
-#define bfin_write_DMA7_X_MODIFY(val)		bfin_write16(DMA7_X_MODIFY, val)
-#define bfin_read_DMA7_Y_MODIFY()		bfin_read16(DMA7_Y_MODIFY)
-#define bfin_write_DMA7_Y_MODIFY(val)		bfin_write16(DMA7_Y_MODIFY, val)
-#define bfin_read_DMA7_CURR_DESC_PTR()		bfin_read32(DMA7_CURR_DESC_PTR)
-#define bfin_write_DMA7_CURR_DESC_PTR(val)	bfin_write32(DMA7_CURR_DESC_PTR, val)
-#define bfin_read_DMA7_CURR_ADDR()		bfin_read32(DMA7_CURR_ADDR)
-#define bfin_write_DMA7_CURR_ADDR(val)		bfin_write32(DMA7_CURR_ADDR, val)
-#define bfin_read_DMA7_CURR_X_COUNT()		bfin_read16(DMA7_CURR_X_COUNT)
-#define bfin_write_DMA7_CURR_X_COUNT(val)	bfin_write16(DMA7_CURR_X_COUNT, val)
-#define bfin_read_DMA7_CURR_Y_COUNT()		bfin_read16(DMA7_CURR_Y_COUNT)
-#define bfin_write_DMA7_CURR_Y_COUNT(val)	bfin_write16(DMA7_CURR_Y_COUNT, val)
-#define bfin_read_DMA7_IRQ_STATUS()		bfin_read16(DMA7_IRQ_STATUS)
-#define bfin_write_DMA7_IRQ_STATUS(val)		bfin_write16(DMA7_IRQ_STATUS, val)
-#define bfin_read_DMA7_PERIPHERAL_MAP()		bfin_read16(DMA7_PERIPHERAL_MAP)
-#define bfin_write_DMA7_PERIPHERAL_MAP(val)	bfin_write16(DMA7_PERIPHERAL_MAP, val)
-
-#define bfin_read_DMA8_CONFIG()			bfin_read16(DMA8_CONFIG)
-#define bfin_write_DMA8_CONFIG(val)		bfin_write16(DMA8_CONFIG, val)
-#define bfin_read_DMA8_NEXT_DESC_PTR()		bfin_read32(DMA8_NEXT_DESC_PTR)
-#define bfin_write_DMA8_NEXT_DESC_PTR(val)	bfin_write32(DMA8_NEXT_DESC_PTR, val)
-#define bfin_read_DMA8_START_ADDR()		bfin_read32(DMA8_START_ADDR)
-#define bfin_write_DMA8_START_ADDR(val)		bfin_write32(DMA8_START_ADDR, val)
-#define bfin_read_DMA8_X_COUNT()		bfin_read16(DMA8_X_COUNT)
-#define bfin_write_DMA8_X_COUNT(val)		bfin_write16(DMA8_X_COUNT, val)
-#define bfin_read_DMA8_Y_COUNT()		bfin_read16(DMA8_Y_COUNT)
-#define bfin_write_DMA8_Y_COUNT(val)		bfin_write16(DMA8_Y_COUNT, val)
-#define bfin_read_DMA8_X_MODIFY()		bfin_read16(DMA8_X_MODIFY)
-#define bfin_write_DMA8_X_MODIFY(val)		bfin_write16(DMA8_X_MODIFY, val)
-#define bfin_read_DMA8_Y_MODIFY()		bfin_read16(DMA8_Y_MODIFY)
-#define bfin_write_DMA8_Y_MODIFY(val)		bfin_write16(DMA8_Y_MODIFY, val)
-#define bfin_read_DMA8_CURR_DESC_PTR()		bfin_read32(DMA8_CURR_DESC_PTR)
-#define bfin_write_DMA8_CURR_DESC_PTR(val)	bfin_write32(DMA8_CURR_DESC_PTR, val)
-#define bfin_read_DMA8_CURR_ADDR()		bfin_read32(DMA8_CURR_ADDR)
-#define bfin_write_DMA8_CURR_ADDR(val)		bfin_write32(DMA8_CURR_ADDR, val)
-#define bfin_read_DMA8_CURR_X_COUNT()		bfin_read16(DMA8_CURR_X_COUNT)
-#define bfin_write_DMA8_CURR_X_COUNT(val)	bfin_write16(DMA8_CURR_X_COUNT, val)
-#define bfin_read_DMA8_CURR_Y_COUNT()		bfin_read16(DMA8_CURR_Y_COUNT)
-#define bfin_write_DMA8_CURR_Y_COUNT(val)	bfin_write16(DMA8_CURR_Y_COUNT, val)
-#define bfin_read_DMA8_IRQ_STATUS()		bfin_read16(DMA8_IRQ_STATUS)
-#define bfin_write_DMA8_IRQ_STATUS(val)		bfin_write16(DMA8_IRQ_STATUS, val)
-#define bfin_read_DMA8_PERIPHERAL_MAP()		bfin_read16(DMA8_PERIPHERAL_MAP)
-#define bfin_write_DMA8_PERIPHERAL_MAP(val)	bfin_write16(DMA8_PERIPHERAL_MAP, val)
-
-#define bfin_read_DMA9_CONFIG()			bfin_read16(DMA9_CONFIG)
-#define bfin_write_DMA9_CONFIG(val)		bfin_write16(DMA9_CONFIG, val)
-#define bfin_read_DMA9_NEXT_DESC_PTR()		bfin_read32(DMA9_NEXT_DESC_PTR)
-#define bfin_write_DMA9_NEXT_DESC_PTR(val)	bfin_write32(DMA9_NEXT_DESC_PTR, val)
-#define bfin_read_DMA9_START_ADDR()		bfin_read32(DMA9_START_ADDR)
-#define bfin_write_DMA9_START_ADDR(val)		bfin_write32(DMA9_START_ADDR, val)
-#define bfin_read_DMA9_X_COUNT()		bfin_read16(DMA9_X_COUNT)
-#define bfin_write_DMA9_X_COUNT(val)		bfin_write16(DMA9_X_COUNT, val)
-#define bfin_read_DMA9_Y_COUNT()		bfin_read16(DMA9_Y_COUNT)
-#define bfin_write_DMA9_Y_COUNT(val)		bfin_write16(DMA9_Y_COUNT, val)
-#define bfin_read_DMA9_X_MODIFY()		bfin_read16(DMA9_X_MODIFY)
-#define bfin_write_DMA9_X_MODIFY(val)		bfin_write16(DMA9_X_MODIFY, val)
-#define bfin_read_DMA9_Y_MODIFY()		bfin_read16(DMA9_Y_MODIFY)
-#define bfin_write_DMA9_Y_MODIFY(val)		bfin_write16(DMA9_Y_MODIFY, val)
-#define bfin_read_DMA9_CURR_DESC_PTR()		bfin_read32(DMA9_CURR_DESC_PTR)
-#define bfin_write_DMA9_CURR_DESC_PTR(val)	bfin_write32(DMA9_CURR_DESC_PTR, val)
-#define bfin_read_DMA9_CURR_ADDR()		bfin_read32(DMA9_CURR_ADDR)
-#define bfin_write_DMA9_CURR_ADDR(val)		bfin_write32(DMA9_CURR_ADDR, val)
-#define bfin_read_DMA9_CURR_X_COUNT()		bfin_read16(DMA9_CURR_X_COUNT)
-#define bfin_write_DMA9_CURR_X_COUNT(val)	bfin_write16(DMA9_CURR_X_COUNT, val)
-#define bfin_read_DMA9_CURR_Y_COUNT()		bfin_read16(DMA9_CURR_Y_COUNT)
-#define bfin_write_DMA9_CURR_Y_COUNT(val)	bfin_write16(DMA9_CURR_Y_COUNT, val)
-#define bfin_read_DMA9_IRQ_STATUS()		bfin_read16(DMA9_IRQ_STATUS)
-#define bfin_write_DMA9_IRQ_STATUS(val)		bfin_write16(DMA9_IRQ_STATUS, val)
-#define bfin_read_DMA9_PERIPHERAL_MAP()		bfin_read16(DMA9_PERIPHERAL_MAP)
-#define bfin_write_DMA9_PERIPHERAL_MAP(val)	bfin_write16(DMA9_PERIPHERAL_MAP, val)
-
-#define bfin_read_DMA10_CONFIG()		bfin_read16(DMA10_CONFIG)
-#define bfin_write_DMA10_CONFIG(val)		bfin_write16(DMA10_CONFIG, val)
-#define bfin_read_DMA10_NEXT_DESC_PTR()		bfin_read32(DMA10_NEXT_DESC_PTR)
-#define bfin_write_DMA10_NEXT_DESC_PTR(val)	bfin_write32(DMA10_NEXT_DESC_PTR, val)
-#define bfin_read_DMA10_START_ADDR()		bfin_read32(DMA10_START_ADDR)
-#define bfin_write_DMA10_START_ADDR(val)	bfin_write32(DMA10_START_ADDR, val)
-#define bfin_read_DMA10_X_COUNT()		bfin_read16(DMA10_X_COUNT)
-#define bfin_write_DMA10_X_COUNT(val)		bfin_write16(DMA10_X_COUNT, val)
-#define bfin_read_DMA10_Y_COUNT()		bfin_read16(DMA10_Y_COUNT)
-#define bfin_write_DMA10_Y_COUNT(val)		bfin_write16(DMA10_Y_COUNT, val)
-#define bfin_read_DMA10_X_MODIFY()		bfin_read16(DMA10_X_MODIFY)
-#define bfin_write_DMA10_X_MODIFY(val)		bfin_write16(DMA10_X_MODIFY, val)
-#define bfin_read_DMA10_Y_MODIFY()		bfin_read16(DMA10_Y_MODIFY)
-#define bfin_write_DMA10_Y_MODIFY(val)		bfin_write16(DMA10_Y_MODIFY, val)
-#define bfin_read_DMA10_CURR_DESC_PTR()		bfin_read32(DMA10_CURR_DESC_PTR)
-#define bfin_write_DMA10_CURR_DESC_PTR(val)	bfin_write32(DMA10_CURR_DESC_PTR, val)
-#define bfin_read_DMA10_CURR_ADDR()		bfin_read32(DMA10_CURR_ADDR)
-#define bfin_write_DMA10_CURR_ADDR(val)		bfin_write32(DMA10_CURR_ADDR, val)
-#define bfin_read_DMA10_CURR_X_COUNT()		bfin_read16(DMA10_CURR_X_COUNT)
-#define bfin_write_DMA10_CURR_X_COUNT(val)	bfin_write16(DMA10_CURR_X_COUNT, val)
-#define bfin_read_DMA10_CURR_Y_COUNT()		bfin_read16(DMA10_CURR_Y_COUNT)
-#define bfin_write_DMA10_CURR_Y_COUNT(val)	bfin_write16(DMA10_CURR_Y_COUNT, val)
-#define bfin_read_DMA10_IRQ_STATUS()		bfin_read16(DMA10_IRQ_STATUS)
-#define bfin_write_DMA10_IRQ_STATUS(val)	bfin_write16(DMA10_IRQ_STATUS, val)
-#define bfin_read_DMA10_PERIPHERAL_MAP()	bfin_read16(DMA10_PERIPHERAL_MAP)
-#define bfin_write_DMA10_PERIPHERAL_MAP(val)	bfin_write16(DMA10_PERIPHERAL_MAP, val)
-
-#define bfin_read_DMA11_CONFIG()		bfin_read16(DMA11_CONFIG)
-#define bfin_write_DMA11_CONFIG(val)		bfin_write16(DMA11_CONFIG, val)
-#define bfin_read_DMA11_NEXT_DESC_PTR()		bfin_read32(DMA11_NEXT_DESC_PTR)
-#define bfin_write_DMA11_NEXT_DESC_PTR(val)	bfin_write32(DMA11_NEXT_DESC_PTR, val)
-#define bfin_read_DMA11_START_ADDR()		bfin_read32(DMA11_START_ADDR)
-#define bfin_write_DMA11_START_ADDR(val)	bfin_write32(DMA11_START_ADDR, val)
-#define bfin_read_DMA11_X_COUNT()		bfin_read16(DMA11_X_COUNT)
-#define bfin_write_DMA11_X_COUNT(val)		bfin_write16(DMA11_X_COUNT, val)
-#define bfin_read_DMA11_Y_COUNT()		bfin_read16(DMA11_Y_COUNT)
-#define bfin_write_DMA11_Y_COUNT(val)		bfin_write16(DMA11_Y_COUNT, val)
-#define bfin_read_DMA11_X_MODIFY()		bfin_read16(DMA11_X_MODIFY)
-#define bfin_write_DMA11_X_MODIFY(val)		bfin_write16(DMA11_X_MODIFY, val)
-#define bfin_read_DMA11_Y_MODIFY()		bfin_read16(DMA11_Y_MODIFY)
-#define bfin_write_DMA11_Y_MODIFY(val)		bfin_write16(DMA11_Y_MODIFY, val)
-#define bfin_read_DMA11_CURR_DESC_PTR()		bfin_read32(DMA11_CURR_DESC_PTR)
-#define bfin_write_DMA11_CURR_DESC_PTR(val)	bfin_write32(DMA11_CURR_DESC_PTR, val)
-#define bfin_read_DMA11_CURR_ADDR()		bfin_read32(DMA11_CURR_ADDR)
-#define bfin_write_DMA11_CURR_ADDR(val)		bfin_write32(DMA11_CURR_ADDR, val)
-#define bfin_read_DMA11_CURR_X_COUNT()		bfin_read16(DMA11_CURR_X_COUNT)
-#define bfin_write_DMA11_CURR_X_COUNT(val)	bfin_write16(DMA11_CURR_X_COUNT, val)
-#define bfin_read_DMA11_CURR_Y_COUNT()		bfin_read16(DMA11_CURR_Y_COUNT)
-#define bfin_write_DMA11_CURR_Y_COUNT(val)	bfin_write16(DMA11_CURR_Y_COUNT, val)
-#define bfin_read_DMA11_IRQ_STATUS()		bfin_read16(DMA11_IRQ_STATUS)
-#define bfin_write_DMA11_IRQ_STATUS(val)	bfin_write16(DMA11_IRQ_STATUS, val)
-#define bfin_read_DMA11_PERIPHERAL_MAP()	bfin_read16(DMA11_PERIPHERAL_MAP)
-#define bfin_write_DMA11_PERIPHERAL_MAP(val)	bfin_write16(DMA11_PERIPHERAL_MAP, val)
-
-#define bfin_read_MDMA_D0_CONFIG()		bfin_read16(MDMA_D0_CONFIG)
-#define bfin_write_MDMA_D0_CONFIG(val)		bfin_write16(MDMA_D0_CONFIG, val)
-#define bfin_read_MDMA_D0_NEXT_DESC_PTR()	bfin_read32(MDMA_D0_NEXT_DESC_PTR)
-#define bfin_write_MDMA_D0_NEXT_DESC_PTR(val)	bfin_write32(MDMA_D0_NEXT_DESC_PTR, val)
-#define bfin_read_MDMA_D0_START_ADDR()		bfin_read32(MDMA_D0_START_ADDR)
-#define bfin_write_MDMA_D0_START_ADDR(val)	bfin_write32(MDMA_D0_START_ADDR, val)
-#define bfin_read_MDMA_D0_X_COUNT()		bfin_read16(MDMA_D0_X_COUNT)
-#define bfin_write_MDMA_D0_X_COUNT(val)		bfin_write16(MDMA_D0_X_COUNT, val)
-#define bfin_read_MDMA_D0_Y_COUNT()		bfin_read16(MDMA_D0_Y_COUNT)
-#define bfin_write_MDMA_D0_Y_COUNT(val)		bfin_write16(MDMA_D0_Y_COUNT, val)
-#define bfin_read_MDMA_D0_X_MODIFY()		bfin_read16(MDMA_D0_X_MODIFY)
-#define bfin_write_MDMA_D0_X_MODIFY(val)	bfin_write16(MDMA_D0_X_MODIFY, val)
-#define bfin_read_MDMA_D0_Y_MODIFY()		bfin_read16(MDMA_D0_Y_MODIFY)
-#define bfin_write_MDMA_D0_Y_MODIFY(val)	bfin_write16(MDMA_D0_Y_MODIFY, val)
-#define bfin_read_MDMA_D0_CURR_DESC_PTR()	bfin_read32(MDMA_D0_CURR_DESC_PTR)
-#define bfin_write_MDMA_D0_CURR_DESC_PTR(val)	bfin_write32(MDMA_D0_CURR_DESC_PTR, val)
-#define bfin_read_MDMA_D0_CURR_ADDR()		bfin_read32(MDMA_D0_CURR_ADDR)
-#define bfin_write_MDMA_D0_CURR_ADDR(val)	bfin_write32(MDMA_D0_CURR_ADDR, val)
-#define bfin_read_MDMA_D0_CURR_X_COUNT()	bfin_read16(MDMA_D0_CURR_X_COUNT)
-#define bfin_write_MDMA_D0_CURR_X_COUNT(val)	bfin_write16(MDMA_D0_CURR_X_COUNT, val)
-#define bfin_read_MDMA_D0_CURR_Y_COUNT()	bfin_read16(MDMA_D0_CURR_Y_COUNT)
-#define bfin_write_MDMA_D0_CURR_Y_COUNT(val)	bfin_write16(MDMA_D0_CURR_Y_COUNT, val)
-#define bfin_read_MDMA_D0_IRQ_STATUS()		bfin_read16(MDMA_D0_IRQ_STATUS)
-#define bfin_write_MDMA_D0_IRQ_STATUS(val)	bfin_write16(MDMA_D0_IRQ_STATUS, val)
-#define bfin_read_MDMA_D0_PERIPHERAL_MAP()	bfin_read16(MDMA_D0_PERIPHERAL_MAP)
-#define bfin_write_MDMA_D0_PERIPHERAL_MAP(val)	bfin_write16(MDMA_D0_PERIPHERAL_MAP, val)
-
-#define bfin_read_MDMA_S0_CONFIG()		bfin_read16(MDMA_S0_CONFIG)
-#define bfin_write_MDMA_S0_CONFIG(val)		bfin_write16(MDMA_S0_CONFIG, val)
-#define bfin_read_MDMA_S0_NEXT_DESC_PTR()	bfin_read32(MDMA_S0_NEXT_DESC_PTR)
-#define bfin_write_MDMA_S0_NEXT_DESC_PTR(val)	bfin_write32(MDMA_S0_NEXT_DESC_PTR, val)
-#define bfin_read_MDMA_S0_START_ADDR()		bfin_read32(MDMA_S0_START_ADDR)
-#define bfin_write_MDMA_S0_START_ADDR(val)	bfin_write32(MDMA_S0_START_ADDR, val)
-#define bfin_read_MDMA_S0_X_COUNT()		bfin_read16(MDMA_S0_X_COUNT)
-#define bfin_write_MDMA_S0_X_COUNT(val)		bfin_write16(MDMA_S0_X_COUNT, val)
-#define bfin_read_MDMA_S0_Y_COUNT()		bfin_read16(MDMA_S0_Y_COUNT)
-#define bfin_write_MDMA_S0_Y_COUNT(val)		bfin_write16(MDMA_S0_Y_COUNT, val)
-#define bfin_read_MDMA_S0_X_MODIFY()		bfin_read16(MDMA_S0_X_MODIFY)
-#define bfin_write_MDMA_S0_X_MODIFY(val)	bfin_write16(MDMA_S0_X_MODIFY, val)
-#define bfin_read_MDMA_S0_Y_MODIFY()		bfin_read16(MDMA_S0_Y_MODIFY)
-#define bfin_write_MDMA_S0_Y_MODIFY(val)	bfin_write16(MDMA_S0_Y_MODIFY, val)
-#define bfin_read_MDMA_S0_CURR_DESC_PTR()	bfin_read32(MDMA_S0_CURR_DESC_PTR)
-#define bfin_write_MDMA_S0_CURR_DESC_PTR(val)	bfin_write32(MDMA_S0_CURR_DESC_PTR, val)
-#define bfin_read_MDMA_S0_CURR_ADDR()		bfin_read32(MDMA_S0_CURR_ADDR)
-#define bfin_write_MDMA_S0_CURR_ADDR(val)	bfin_write32(MDMA_S0_CURR_ADDR, val)
-#define bfin_read_MDMA_S0_CURR_X_COUNT()	bfin_read16(MDMA_S0_CURR_X_COUNT)
-#define bfin_write_MDMA_S0_CURR_X_COUNT(val)	bfin_write16(MDMA_S0_CURR_X_COUNT, val)
-#define bfin_read_MDMA_S0_CURR_Y_COUNT()	bfin_read16(MDMA_S0_CURR_Y_COUNT)
-#define bfin_write_MDMA_S0_CURR_Y_COUNT(val)	bfin_write16(MDMA_S0_CURR_Y_COUNT, val)
-#define bfin_read_MDMA_S0_IRQ_STATUS()		bfin_read16(MDMA_S0_IRQ_STATUS)
-#define bfin_write_MDMA_S0_IRQ_STATUS(val)	bfin_write16(MDMA_S0_IRQ_STATUS, val)
-#define bfin_read_MDMA_S0_PERIPHERAL_MAP()	bfin_read16(MDMA_S0_PERIPHERAL_MAP)
-#define bfin_write_MDMA_S0_PERIPHERAL_MAP(val)	bfin_write16(MDMA_S0_PERIPHERAL_MAP, val)
-
-#define bfin_read_MDMA_D1_CONFIG()		bfin_read16(MDMA_D1_CONFIG)
-#define bfin_write_MDMA_D1_CONFIG(val)		bfin_write16(MDMA_D1_CONFIG, val)
-#define bfin_read_MDMA_D1_NEXT_DESC_PTR()	bfin_read32(MDMA_D1_NEXT_DESC_PTR)
-#define bfin_write_MDMA_D1_NEXT_DESC_PTR(val)	bfin_write32(MDMA_D1_NEXT_DESC_PTR, val)
-#define bfin_read_MDMA_D1_START_ADDR()		bfin_read32(MDMA_D1_START_ADDR)
-#define bfin_write_MDMA_D1_START_ADDR(val)	bfin_write32(MDMA_D1_START_ADDR, val)
-#define bfin_read_MDMA_D1_X_COUNT()		bfin_read16(MDMA_D1_X_COUNT)
-#define bfin_write_MDMA_D1_X_COUNT(val)		bfin_write16(MDMA_D1_X_COUNT, val)
-#define bfin_read_MDMA_D1_Y_COUNT()		bfin_read16(MDMA_D1_Y_COUNT)
-#define bfin_write_MDMA_D1_Y_COUNT(val)		bfin_write16(MDMA_D1_Y_COUNT, val)
-#define bfin_read_MDMA_D1_X_MODIFY()		bfin_read16(MDMA_D1_X_MODIFY)
-#define bfin_write_MDMA_D1_X_MODIFY(val)	bfin_write16(MDMA_D1_X_MODIFY, val)
-#define bfin_read_MDMA_D1_Y_MODIFY()		bfin_read16(MDMA_D1_Y_MODIFY)
-#define bfin_write_MDMA_D1_Y_MODIFY(val)	bfin_write16(MDMA_D1_Y_MODIFY, val)
-#define bfin_read_MDMA_D1_CURR_DESC_PTR()	bfin_read32(MDMA_D1_CURR_DESC_PTR)
-#define bfin_write_MDMA_D1_CURR_DESC_PTR(val)	bfin_write32(MDMA_D1_CURR_DESC_PTR, val)
-#define bfin_read_MDMA_D1_CURR_ADDR()		bfin_read32(MDMA_D1_CURR_ADDR)
-#define bfin_write_MDMA_D1_CURR_ADDR(val)	bfin_write32(MDMA_D1_CURR_ADDR, val)
-#define bfin_read_MDMA_D1_CURR_X_COUNT()	bfin_read16(MDMA_D1_CURR_X_COUNT)
-#define bfin_write_MDMA_D1_CURR_X_COUNT(val)	bfin_write16(MDMA_D1_CURR_X_COUNT, val)
-#define bfin_read_MDMA_D1_CURR_Y_COUNT()	bfin_read16(MDMA_D1_CURR_Y_COUNT)
-#define bfin_write_MDMA_D1_CURR_Y_COUNT(val)	bfin_write16(MDMA_D1_CURR_Y_COUNT, val)
-#define bfin_read_MDMA_D1_IRQ_STATUS()		bfin_read16(MDMA_D1_IRQ_STATUS)
-#define bfin_write_MDMA_D1_IRQ_STATUS(val)	bfin_write16(MDMA_D1_IRQ_STATUS, val)
-#define bfin_read_MDMA_D1_PERIPHERAL_MAP()	bfin_read16(MDMA_D1_PERIPHERAL_MAP)
-#define bfin_write_MDMA_D1_PERIPHERAL_MAP(val)	bfin_write16(MDMA_D1_PERIPHERAL_MAP, val)
-
-#define bfin_read_MDMA_S1_CONFIG()		bfin_read16(MDMA_S1_CONFIG)
-#define bfin_write_MDMA_S1_CONFIG(val)		bfin_write16(MDMA_S1_CONFIG, val)
-#define bfin_read_MDMA_S1_NEXT_DESC_PTR()	bfin_read32(MDMA_S1_NEXT_DESC_PTR)
-#define bfin_write_MDMA_S1_NEXT_DESC_PTR(val)	bfin_write32(MDMA_S1_NEXT_DESC_PTR, val)
-#define bfin_read_MDMA_S1_START_ADDR()		bfin_read32(MDMA_S1_START_ADDR)
-#define bfin_write_MDMA_S1_START_ADDR(val)	bfin_write32(MDMA_S1_START_ADDR, val)
-#define bfin_read_MDMA_S1_X_COUNT()		bfin_read16(MDMA_S1_X_COUNT)
-#define bfin_write_MDMA_S1_X_COUNT(val)		bfin_write16(MDMA_S1_X_COUNT, val)
-#define bfin_read_MDMA_S1_Y_COUNT()		bfin_read16(MDMA_S1_Y_COUNT)
-#define bfin_write_MDMA_S1_Y_COUNT(val)		bfin_write16(MDMA_S1_Y_COUNT, val)
-#define bfin_read_MDMA_S1_X_MODIFY()		bfin_read16(MDMA_S1_X_MODIFY)
-#define bfin_write_MDMA_S1_X_MODIFY(val)	bfin_write16(MDMA_S1_X_MODIFY, val)
-#define bfin_read_MDMA_S1_Y_MODIFY()		bfin_read16(MDMA_S1_Y_MODIFY)
-#define bfin_write_MDMA_S1_Y_MODIFY(val)	bfin_write16(MDMA_S1_Y_MODIFY, val)
-#define bfin_read_MDMA_S1_CURR_DESC_PTR()	bfin_read32(MDMA_S1_CURR_DESC_PTR)
-#define bfin_write_MDMA_S1_CURR_DESC_PTR(val)	bfin_write32(MDMA_S1_CURR_DESC_PTR, val)
-#define bfin_read_MDMA_S1_CURR_ADDR()		bfin_read32(MDMA_S1_CURR_ADDR)
-#define bfin_write_MDMA_S1_CURR_ADDR(val)	bfin_write32(MDMA_S1_CURR_ADDR, val)
-#define bfin_read_MDMA_S1_CURR_X_COUNT()	bfin_read16(MDMA_S1_CURR_X_COUNT)
-#define bfin_write_MDMA_S1_CURR_X_COUNT(val)	bfin_write16(MDMA_S1_CURR_X_COUNT, val)
-#define bfin_read_MDMA_S1_CURR_Y_COUNT()	bfin_read16(MDMA_S1_CURR_Y_COUNT)
-#define bfin_write_MDMA_S1_CURR_Y_COUNT(val)	bfin_write16(MDMA_S1_CURR_Y_COUNT, val)
-#define bfin_read_MDMA_S1_IRQ_STATUS()		bfin_read16(MDMA_S1_IRQ_STATUS)
-#define bfin_write_MDMA_S1_IRQ_STATUS(val)	bfin_write16(MDMA_S1_IRQ_STATUS, val)
-#define bfin_read_MDMA_S1_PERIPHERAL_MAP()	bfin_read16(MDMA_S1_PERIPHERAL_MAP)
-#define bfin_write_MDMA_S1_PERIPHERAL_MAP(val)	bfin_write16(MDMA_S1_PERIPHERAL_MAP, val)
-
-
-/* Parallel Peripheral Interface (0xFFC01000 - 0xFFC010FF)							*/
-#define bfin_read_PPI_CONTROL()			bfin_read16(PPI_CONTROL)
-#define bfin_write_PPI_CONTROL(val)		bfin_write16(PPI_CONTROL, val)
-#define bfin_read_PPI_STATUS()			bfin_read16(PPI_STATUS)
-#define bfin_write_PPI_STATUS(val)		bfin_write16(PPI_STATUS, val)
-#define bfin_clear_PPI_STATUS()			bfin_write_PPI_STATUS(0xFFFF)
-#define bfin_read_PPI_DELAY()			bfin_read16(PPI_DELAY)
-#define bfin_write_PPI_DELAY(val)		bfin_write16(PPI_DELAY, val)
-#define bfin_read_PPI_COUNT()			bfin_read16(PPI_COUNT)
-#define bfin_write_PPI_COUNT(val)		bfin_write16(PPI_COUNT, val)
-#define bfin_read_PPI_FRAME()			bfin_read16(PPI_FRAME)
-#define bfin_write_PPI_FRAME(val)		bfin_write16(PPI_FRAME, val)
-
-
-/* Two-Wire Interface		(0xFFC01400 - 0xFFC014FF)								*/
-
-/* General Purpose I/O Port G (0xFFC01500 - 0xFFC015FF)								*/
-#define bfin_read_PORTGIO()			bfin_read16(PORTGIO)
-#define bfin_write_PORTGIO(val)			bfin_write16(PORTGIO, val)
-#define bfin_read_PORTGIO_CLEAR()		bfin_read16(PORTGIO_CLEAR)
-#define bfin_write_PORTGIO_CLEAR(val)		bfin_write16(PORTGIO_CLEAR, val)
-#define bfin_read_PORTGIO_SET()			bfin_read16(PORTGIO_SET)
-#define bfin_write_PORTGIO_SET(val)		bfin_write16(PORTGIO_SET, val)
-#define bfin_read_PORTGIO_TOGGLE()		bfin_read16(PORTGIO_TOGGLE)
-#define bfin_write_PORTGIO_TOGGLE(val)		bfin_write16(PORTGIO_TOGGLE, val)
-#define bfin_read_PORTGIO_MASKA()		bfin_read16(PORTGIO_MASKA)
-#define bfin_write_PORTGIO_MASKA(val)		bfin_write16(PORTGIO_MASKA, val)
-#define bfin_read_PORTGIO_MASKA_CLEAR()		bfin_read16(PORTGIO_MASKA_CLEAR)
-#define bfin_write_PORTGIO_MASKA_CLEAR(val)	bfin_write16(PORTGIO_MASKA_CLEAR, val)
-#define bfin_read_PORTGIO_MASKA_SET()		bfin_read16(PORTGIO_MASKA_SET)
-#define bfin_write_PORTGIO_MASKA_SET(val)	bfin_write16(PORTGIO_MASKA_SET, val)
-#define bfin_read_PORTGIO_MASKA_TOGGLE()	bfin_read16(PORTGIO_MASKA_TOGGLE)
-#define bfin_write_PORTGIO_MASKA_TOGGLE(val)	bfin_write16(PORTGIO_MASKA_TOGGLE, val)
-#define bfin_read_PORTGIO_MASKB()		bfin_read16(PORTGIO_MASKB)
-#define bfin_write_PORTGIO_MASKB(val)		bfin_write16(PORTGIO_MASKB, val)
-#define bfin_read_PORTGIO_MASKB_CLEAR()		bfin_read16(PORTGIO_MASKB_CLEAR)
-#define bfin_write_PORTGIO_MASKB_CLEAR(val)	bfin_write16(PORTGIO_MASKB_CLEAR, val)
-#define bfin_read_PORTGIO_MASKB_SET()		bfin_read16(PORTGIO_MASKB_SET)
-#define bfin_write_PORTGIO_MASKB_SET(val)	bfin_write16(PORTGIO_MASKB_SET, val)
-#define bfin_read_PORTGIO_MASKB_TOGGLE()	bfin_read16(PORTGIO_MASKB_TOGGLE)
-#define bfin_write_PORTGIO_MASKB_TOGGLE(val)	bfin_write16(PORTGIO_MASKB_TOGGLE, val)
-#define bfin_read_PORTGIO_DIR()			bfin_read16(PORTGIO_DIR)
-#define bfin_write_PORTGIO_DIR(val)		bfin_write16(PORTGIO_DIR, val)
-#define bfin_read_PORTGIO_POLAR()		bfin_read16(PORTGIO_POLAR)
-#define bfin_write_PORTGIO_POLAR(val)		bfin_write16(PORTGIO_POLAR, val)
-#define bfin_read_PORTGIO_EDGE()		bfin_read16(PORTGIO_EDGE)
-#define bfin_write_PORTGIO_EDGE(val)		bfin_write16(PORTGIO_EDGE, val)
-#define bfin_read_PORTGIO_BOTH()		bfin_read16(PORTGIO_BOTH)
-#define bfin_write_PORTGIO_BOTH(val)		bfin_write16(PORTGIO_BOTH, val)
-#define bfin_read_PORTGIO_INEN()		bfin_read16(PORTGIO_INEN)
-#define bfin_write_PORTGIO_INEN(val)		bfin_write16(PORTGIO_INEN, val)
-
-
-/* General Purpose I/O Port H (0xFFC01700 - 0xFFC017FF)								*/
-#define bfin_read_PORTHIO()			bfin_read16(PORTHIO)
-#define bfin_write_PORTHIO(val)			bfin_write16(PORTHIO, val)
-#define bfin_read_PORTHIO_CLEAR()		bfin_read16(PORTHIO_CLEAR)
-#define bfin_write_PORTHIO_CLEAR(val)		bfin_write16(PORTHIO_CLEAR, val)
-#define bfin_read_PORTHIO_SET()			bfin_read16(PORTHIO_SET)
-#define bfin_write_PORTHIO_SET(val)		bfin_write16(PORTHIO_SET, val)
-#define bfin_read_PORTHIO_TOGGLE()		bfin_read16(PORTHIO_TOGGLE)
-#define bfin_write_PORTHIO_TOGGLE(val)		bfin_write16(PORTHIO_TOGGLE, val)
-#define bfin_read_PORTHIO_MASKA()		bfin_read16(PORTHIO_MASKA)
-#define bfin_write_PORTHIO_MASKA(val)		bfin_write16(PORTHIO_MASKA, val)
-#define bfin_read_PORTHIO_MASKA_CLEAR()		bfin_read16(PORTHIO_MASKA_CLEAR)
-#define bfin_write_PORTHIO_MASKA_CLEAR(val)	bfin_write16(PORTHIO_MASKA_CLEAR, val)
-#define bfin_read_PORTHIO_MASKA_SET()		bfin_read16(PORTHIO_MASKA_SET)
-#define bfin_write_PORTHIO_MASKA_SET(val)	bfin_write16(PORTHIO_MASKA_SET, val)
-#define bfin_read_PORTHIO_MASKA_TOGGLE()	bfin_read16(PORTHIO_MASKA_TOGGLE)
-#define bfin_write_PORTHIO_MASKA_TOGGLE(val)	bfin_write16(PORTHIO_MASKA_TOGGLE, val)
-#define bfin_read_PORTHIO_MASKB()		bfin_read16(PORTHIO_MASKB)
-#define bfin_write_PORTHIO_MASKB(val)		bfin_write16(PORTHIO_MASKB, val)
-#define bfin_read_PORTHIO_MASKB_CLEAR()		bfin_read16(PORTHIO_MASKB_CLEAR)
-#define bfin_write_PORTHIO_MASKB_CLEAR(val)	bfin_write16(PORTHIO_MASKB_CLEAR, val)
-#define bfin_read_PORTHIO_MASKB_SET()		bfin_read16(PORTHIO_MASKB_SET)
-#define bfin_write_PORTHIO_MASKB_SET(val)	bfin_write16(PORTHIO_MASKB_SET, val)
-#define bfin_read_PORTHIO_MASKB_TOGGLE()	bfin_read16(PORTHIO_MASKB_TOGGLE)
-#define bfin_write_PORTHIO_MASKB_TOGGLE(val)	bfin_write16(PORTHIO_MASKB_TOGGLE, val)
-#define bfin_read_PORTHIO_DIR()			bfin_read16(PORTHIO_DIR)
-#define bfin_write_PORTHIO_DIR(val)		bfin_write16(PORTHIO_DIR, val)
-#define bfin_read_PORTHIO_POLAR()		bfin_read16(PORTHIO_POLAR)
-#define bfin_write_PORTHIO_POLAR(val)		bfin_write16(PORTHIO_POLAR, val)
-#define bfin_read_PORTHIO_EDGE()		bfin_read16(PORTHIO_EDGE)
-#define bfin_write_PORTHIO_EDGE(val)		bfin_write16(PORTHIO_EDGE, val)
-#define bfin_read_PORTHIO_BOTH()		bfin_read16(PORTHIO_BOTH)
-#define bfin_write_PORTHIO_BOTH(val)		bfin_write16(PORTHIO_BOTH, val)
-#define bfin_read_PORTHIO_INEN()		bfin_read16(PORTHIO_INEN)
-#define bfin_write_PORTHIO_INEN(val)		bfin_write16(PORTHIO_INEN, val)
-
-
-/* UART1 Controller		(0xFFC02000 - 0xFFC020FF)								*/
-#define bfin_read_UART1_THR()			bfin_read16(UART1_THR)
-#define bfin_write_UART1_THR(val)		bfin_write16(UART1_THR, val)
-#define bfin_read_UART1_RBR()			bfin_read16(UART1_RBR)
-#define bfin_write_UART1_RBR(val)		bfin_write16(UART1_RBR, val)
-#define bfin_read_UART1_DLL()			bfin_read16(UART1_DLL)
-#define bfin_write_UART1_DLL(val)		bfin_write16(UART1_DLL, val)
-#define bfin_read_UART1_IER()			bfin_read16(UART1_IER)
-#define bfin_write_UART1_IER(val)		bfin_write16(UART1_IER, val)
-#define bfin_read_UART1_DLH()			bfin_read16(UART1_DLH)
-#define bfin_write_UART1_DLH(val)		bfin_write16(UART1_DLH, val)
-#define bfin_read_UART1_IIR()			bfin_read16(UART1_IIR)
-#define bfin_write_UART1_IIR(val)		bfin_write16(UART1_IIR, val)
-#define bfin_read_UART1_LCR()			bfin_read16(UART1_LCR)
-#define bfin_write_UART1_LCR(val)		bfin_write16(UART1_LCR, val)
-#define bfin_read_UART1_MCR()			bfin_read16(UART1_MCR)
-#define bfin_write_UART1_MCR(val)		bfin_write16(UART1_MCR, val)
-#define bfin_read_UART1_LSR()			bfin_read16(UART1_LSR)
-#define bfin_write_UART1_LSR(val)		bfin_write16(UART1_LSR, val)
-#define bfin_read_UART1_MSR()			bfin_read16(UART1_MSR)
-#define bfin_write_UART1_MSR(val)		bfin_write16(UART1_MSR, val)
-#define bfin_read_UART1_SCR()			bfin_read16(UART1_SCR)
-#define bfin_write_UART1_SCR(val)		bfin_write16(UART1_SCR, val)
-#define bfin_read_UART1_GCTL()			bfin_read16(UART1_GCTL)
-#define bfin_write_UART1_GCTL(val)		bfin_write16(UART1_GCTL, val)
-
-/* Omit CAN register sets from the cdefBF534.h (CAN is not in the ADSP-BF52x processor) */
-
-/* Pin Control Registers	(0xFFC03200 - 0xFFC032FF)								*/
-#define bfin_read_PORTF_FER()			bfin_read16(PORTF_FER)
-#define bfin_write_PORTF_FER(val)		bfin_write16(PORTF_FER, val)
-#define bfin_read_PORTG_FER()			bfin_read16(PORTG_FER)
-#define bfin_write_PORTG_FER(val)		bfin_write16(PORTG_FER, val)
-#define bfin_read_PORTH_FER()			bfin_read16(PORTH_FER)
-#define bfin_write_PORTH_FER(val)		bfin_write16(PORTH_FER, val)
-#define bfin_read_PORT_MUX()			bfin_read16(PORT_MUX)
-#define bfin_write_PORT_MUX(val)		bfin_write16(PORT_MUX, val)
-
-
-/* Handshake MDMA Registers	(0xFFC03300 - 0xFFC033FF)								*/
-#define bfin_read_HMDMA0_CONTROL()		bfin_read16(HMDMA0_CONTROL)
-#define bfin_write_HMDMA0_CONTROL(val)		bfin_write16(HMDMA0_CONTROL, val)
-#define bfin_read_HMDMA0_ECINIT()		bfin_read16(HMDMA0_ECINIT)
-#define bfin_write_HMDMA0_ECINIT(val)		bfin_write16(HMDMA0_ECINIT, val)
-#define bfin_read_HMDMA0_BCINIT()		bfin_read16(HMDMA0_BCINIT)
-#define bfin_write_HMDMA0_BCINIT(val)		bfin_write16(HMDMA0_BCINIT, val)
-#define bfin_read_HMDMA0_ECURGENT()		bfin_read16(HMDMA0_ECURGENT)
-#define bfin_write_HMDMA0_ECURGENT(val)		bfin_write16(HMDMA0_ECURGENT, val)
-#define bfin_read_HMDMA0_ECOVERFLOW()		bfin_read16(HMDMA0_ECOVERFLOW)
-#define bfin_write_HMDMA0_ECOVERFLOW(val)	bfin_write16(HMDMA0_ECOVERFLOW, val)
-#define bfin_read_HMDMA0_ECOUNT()		bfin_read16(HMDMA0_ECOUNT)
-#define bfin_write_HMDMA0_ECOUNT(val)		bfin_write16(HMDMA0_ECOUNT, val)
-#define bfin_read_HMDMA0_BCOUNT()		bfin_read16(HMDMA0_BCOUNT)
-#define bfin_write_HMDMA0_BCOUNT(val)		bfin_write16(HMDMA0_BCOUNT, val)
-
-#define bfin_read_HMDMA1_CONTROL()		bfin_read16(HMDMA1_CONTROL)
-#define bfin_write_HMDMA1_CONTROL(val)		bfin_write16(HMDMA1_CONTROL, val)
-#define bfin_read_HMDMA1_ECINIT()		bfin_read16(HMDMA1_ECINIT)
-#define bfin_write_HMDMA1_ECINIT(val)		bfin_write16(HMDMA1_ECINIT, val)
-#define bfin_read_HMDMA1_BCINIT()		bfin_read16(HMDMA1_BCINIT)
-#define bfin_write_HMDMA1_BCINIT(val)		bfin_write16(HMDMA1_BCINIT, val)
-#define bfin_read_HMDMA1_ECURGENT()		bfin_read16(HMDMA1_ECURGENT)
-#define bfin_write_HMDMA1_ECURGENT(val)		bfin_write16(HMDMA1_ECURGENT, val)
-#define bfin_read_HMDMA1_ECOVERFLOW()		bfin_read16(HMDMA1_ECOVERFLOW)
-#define bfin_write_HMDMA1_ECOVERFLOW(val)	bfin_write16(HMDMA1_ECOVERFLOW, val)
-#define bfin_read_HMDMA1_ECOUNT()		bfin_read16(HMDMA1_ECOUNT)
-#define bfin_write_HMDMA1_ECOUNT(val)		bfin_write16(HMDMA1_ECOUNT, val)
-#define bfin_read_HMDMA1_BCOUNT()		bfin_read16(HMDMA1_BCOUNT)
-#define bfin_write_HMDMA1_BCOUNT(val)		bfin_write16(HMDMA1_BCOUNT, val)
-
-/* ==== end from cdefBF534.h ==== */
-
-/* GPIO PIN mux (0xFFC03210 - OxFFC03288) */
-
-#define bfin_read_PORTF_MUX()			bfin_read16(PORTF_MUX)
-#define bfin_write_PORTF_MUX(val)		bfin_write16(PORTF_MUX, val)
-#define bfin_read_PORTG_MUX()			bfin_read16(PORTG_MUX)
-#define bfin_write_PORTG_MUX(val)		bfin_write16(PORTG_MUX, val)
-#define bfin_read_PORTH_MUX()			bfin_read16(PORTH_MUX)
-#define bfin_write_PORTH_MUX(val)		bfin_write16(PORTH_MUX, val)
-
-#define bfin_read_PORTF_DRIVE()			bfin_read16(PORTF_DRIVE)
-#define bfin_write_PORTF_DRIVE(val)		bfin_write16(PORTF_DRIVE, val)
-#define bfin_read_PORTG_DRIVE()			bfin_read16(PORTG_DRIVE)
-#define bfin_write_PORTG_DRIVE(val)		bfin_write16(PORTG_DRIVE, val)
-#define bfin_read_PORTH_DRIVE()			bfin_read16(PORTH_DRIVE)
-#define bfin_write_PORTH_DRIVE(val)		bfin_write16(PORTH_DRIVE, val)
-#define bfin_read_PORTF_SLEW()			bfin_read16(PORTF_SLEW)
-#define bfin_write_PORTF_SLEW(val)		bfin_write16(PORTF_SLEW, val)
-#define bfin_read_PORTG_SLEW()			bfin_read16(PORTG_SLEW)
-#define bfin_write_PORTG_SLEW(val)		bfin_write16(PORTG_SLEW, val)
-#define bfin_read_PORTH_SLEW()			bfin_read16(PORTH_SLEW)
-#define bfin_write_PORTH_SLEW(val)		bfin_write16(PORTH_SLEW, val)
-#define bfin_read_PORTF_HYSTERISIS()		bfin_read16(PORTF_HYSTERISIS)
-#define bfin_write_PORTF_HYSTERISIS(val)	bfin_write16(PORTF_HYSTERISIS, val)
-#define bfin_read_PORTG_HYSTERISIS()		bfin_read16(PORTG_HYSTERISIS)
-#define bfin_write_PORTG_HYSTERISIS(val)	bfin_write16(PORTG_HYSTERISIS, val)
-#define bfin_read_PORTH_HYSTERISIS()		bfin_read16(PORTH_HYSTERISIS)
-#define bfin_write_PORTH_HYSTERISIS(val)	bfin_write16(PORTH_HYSTERISIS, val)
-#define bfin_read_MISCPORT_DRIVE()		bfin_read16(MISCPORT_DRIVE)
-#define bfin_write_MISCPORT_DRIVE(val)		bfin_write16(MISCPORT_DRIVE, val)
-#define bfin_read_MISCPORT_SLEW()		bfin_read16(MISCPORT_SLEW)
-#define bfin_write_MISCPORT_SLEW(val)		bfin_write16(MISCPORT_SLEW, val)
-#define bfin_read_MISCPORT_HYSTERISIS()		bfin_read16(MISCPORT_HYSTERISIS)
-#define bfin_write_MISCPORT_HYSTERISIS(val)	bfin_write16(MISCPORT_HYSTERISIS, val)
-
-/* HOST Port Registers */
-
-#define bfin_read_HOST_CONTROL()		bfin_read16(HOST_CONTROL)
-#define bfin_write_HOST_CONTROL(val)		bfin_write16(HOST_CONTROL, val)
-#define bfin_read_HOST_STATUS()			bfin_read16(HOST_STATUS)
-#define bfin_write_HOST_STATUS(val)		bfin_write16(HOST_STATUS, val)
-#define bfin_read_HOST_TIMEOUT()		bfin_read16(HOST_TIMEOUT)
-#define bfin_write_HOST_TIMEOUT(val)		bfin_write16(HOST_TIMEOUT, val)
-
-/* Counter Registers */
-
-#define bfin_read_CNT_CONFIG()			bfin_read16(CNT_CONFIG)
-#define bfin_write_CNT_CONFIG(val)		bfin_write16(CNT_CONFIG, val)
-#define bfin_read_CNT_IMASK()			bfin_read16(CNT_IMASK)
-#define bfin_write_CNT_IMASK(val)		bfin_write16(CNT_IMASK, val)
-#define bfin_read_CNT_STATUS()			bfin_read16(CNT_STATUS)
-#define bfin_write_CNT_STATUS(val)		bfin_write16(CNT_STATUS, val)
-#define bfin_read_CNT_COMMAND()			bfin_read16(CNT_COMMAND)
-#define bfin_write_CNT_COMMAND(val)		bfin_write16(CNT_COMMAND, val)
-#define bfin_read_CNT_DEBOUNCE()		bfin_read16(CNT_DEBOUNCE)
-#define bfin_write_CNT_DEBOUNCE(val)		bfin_write16(CNT_DEBOUNCE, val)
-#define bfin_read_CNT_COUNTER()			bfin_read32(CNT_COUNTER)
-#define bfin_write_CNT_COUNTER(val)		bfin_write32(CNT_COUNTER, val)
-#define bfin_read_CNT_MAX()			bfin_read32(CNT_MAX)
-#define bfin_write_CNT_MAX(val)			bfin_write32(CNT_MAX, val)
-#define bfin_read_CNT_MIN()			bfin_read32(CNT_MIN)
-#define bfin_write_CNT_MIN(val)			bfin_write32(CNT_MIN, val)
-
-/* Security Registers */
-
-#define bfin_read_SECURE_SYSSWT()		bfin_read32(SECURE_SYSSWT)
-#define bfin_write_SECURE_SYSSWT(val)		bfin_write32(SECURE_SYSSWT, val)
-#define bfin_read_SECURE_CONTROL()		bfin_read16(SECURE_CONTROL)
-#define bfin_write_SECURE_CONTROL(val)		bfin_write16(SECURE_CONTROL, val)
-#define bfin_read_SECURE_STATUS()		bfin_read16(SECURE_STATUS)
-#define bfin_write_SECURE_STATUS(val)		bfin_write16(SECURE_STATUS, val)
-
-/* NFC Registers */
-
-#define bfin_read_NFC_CTL()			bfin_read16(NFC_CTL)
-#define bfin_write_NFC_CTL(val)			bfin_write16(NFC_CTL, val)
-#define bfin_read_NFC_STAT()			bfin_read16(NFC_STAT)
-#define bfin_write_NFC_STAT(val)		bfin_write16(NFC_STAT, val)
-#define bfin_read_NFC_IRQSTAT()			bfin_read16(NFC_IRQSTAT)
-#define bfin_write_NFC_IRQSTAT(val)		bfin_write16(NFC_IRQSTAT, val)
-#define bfin_read_NFC_IRQMASK()			bfin_read16(NFC_IRQMASK)
-#define bfin_write_NFC_IRQMASK(val)		bfin_write16(NFC_IRQMASK, val)
-#define bfin_read_NFC_ECC0()			bfin_read16(NFC_ECC0)
-#define bfin_write_NFC_ECC0(val)		bfin_write16(NFC_ECC0, val)
-#define bfin_read_NFC_ECC1()			bfin_read16(NFC_ECC1)
-#define bfin_write_NFC_ECC1(val)		bfin_write16(NFC_ECC1, val)
-#define bfin_read_NFC_ECC2()			bfin_read16(NFC_ECC2)
-#define bfin_write_NFC_ECC2(val)		bfin_write16(NFC_ECC2, val)
-#define bfin_read_NFC_ECC3()			bfin_read16(NFC_ECC3)
-#define bfin_write_NFC_ECC3(val)		bfin_write16(NFC_ECC3, val)
-#define bfin_read_NFC_COUNT()			bfin_read16(NFC_COUNT)
-#define bfin_write_NFC_COUNT(val)		bfin_write16(NFC_COUNT, val)
-#define bfin_read_NFC_RST()			bfin_read16(NFC_RST)
-#define bfin_write_NFC_RST(val)			bfin_write16(NFC_RST, val)
-#define bfin_read_NFC_PGCTL()			bfin_read16(NFC_PGCTL)
-#define bfin_write_NFC_PGCTL(val)		bfin_write16(NFC_PGCTL, val)
-#define bfin_read_NFC_READ()			bfin_read16(NFC_READ)
-#define bfin_write_NFC_READ(val)		bfin_write16(NFC_READ, val)
-#define bfin_read_NFC_ADDR()			bfin_read16(NFC_ADDR)
-#define bfin_write_NFC_ADDR(val)		bfin_write16(NFC_ADDR, val)
-#define bfin_read_NFC_CMD()			bfin_read16(NFC_CMD)
-#define bfin_write_NFC_CMD(val)			bfin_write16(NFC_CMD, val)
-#define bfin_read_NFC_DATA_WR()			bfin_read16(NFC_DATA_WR)
-#define bfin_write_NFC_DATA_WR(val)		bfin_write16(NFC_DATA_WR, val)
-#define bfin_read_NFC_DATA_RD()			bfin_read16(NFC_DATA_RD)
-#define bfin_write_NFC_DATA_RD(val)		bfin_write16(NFC_DATA_RD, val)
-
-/* These need to be last due to the cdef/linux inter-dependencies */
-#include <asm/irq.h>
-
-#endif /* _CDEF_BF52X_H */
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf527/include/mach/defBF522.h linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf527/include/mach/defBF522.h
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf527/include/mach/defBF522.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf527/include/mach/defBF522.h	2011-03-14 21:20:32.000000000 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright 2007-2008 Analog Devices Inc.
+ * Copyright 2007-2010 Analog Devices Inc.
  *
  * Licensed under the ADI BSD license or the GPL-2 (or later)
  */
@@ -7,12 +7,1393 @@
 #ifndef _DEF_BF522_H
 #define _DEF_BF522_H
 
-/* Include all Core registers and bit definitions */
-#include <asm/def_LPBlackfin.h>
+/* ************************************************************** */
+/*   SYSTEM & MMR ADDRESS DEFINITIONS COMMON TO ALL ADSP-BF52x    */
+/* ************************************************************** */
 
-/* SYSTEM & MMR ADDRESS DEFINITIONS FOR ADSP-BF522 */
+/* ==== begin from defBF534.h ==== */
 
-/* Include defBF52x_base.h for the set of #defines that are common to all ADSP-BF52x processors */
-#include "defBF52x_base.h"
+/* Clock and System Control	(0xFFC00000 - 0xFFC000FF)								*/
+#define PLL_CTL				0xFFC00000	/* PLL Control Register						*/
+#define PLL_DIV				0xFFC00004	/* PLL Divide Register						*/
+#define VR_CTL				0xFFC00008	/* Voltage Regulator Control Register		*/
+#define PLL_STAT			0xFFC0000C	/* PLL Status Register						*/
+#define PLL_LOCKCNT			0xFFC00010	/* PLL Lock Count Register					*/
+#define CHIPID        0xFFC00014  /* Device ID Register */
+
+
+/* System Interrupt Controller (0xFFC00100 - 0xFFC001FF)							*/
+#define SWRST				0xFFC00100	/* Software Reset Register					*/
+#define SYSCR				0xFFC00104	/* System Configuration Register			*/
+#define SIC_RVECT			0xFFC00108	/* Interrupt Reset Vector Address Register	*/
+
+#define SIC_IMASK0			0xFFC0010C	/* Interrupt Mask Register					*/
+#define SIC_IAR0			0xFFC00110	/* Interrupt Assignment Register 0			*/
+#define SIC_IAR1			0xFFC00114	/* Interrupt Assignment Register 1			*/
+#define SIC_IAR2			0xFFC00118	/* Interrupt Assignment Register 2			*/
+#define SIC_IAR3			0xFFC0011C	/* Interrupt Assignment Register 3			*/
+#define SIC_ISR0				0xFFC00120	/* Interrupt Status Register				*/
+#define SIC_IWR0				0xFFC00124	/* Interrupt Wakeup Register				*/
+
+/* SIC Additions to ADSP-BF52x (0xFFC0014C - 0xFFC00162) */
+#define SIC_IMASK1                      0xFFC0014C     /* Interrupt Mask register of SIC2 */
+#define SIC_IAR4                        0xFFC00150     /* Interrupt Assignment register4 */
+#define SIC_IAR5                        0xFFC00154     /* Interrupt Assignment register5 */
+#define SIC_IAR6                        0xFFC00158     /* Interrupt Assignment register6 */
+#define SIC_IAR7                        0xFFC0015C     /* Interrupt Assignment register7 */
+#define SIC_ISR1                        0xFFC00160     /* Interrupt Statur register */
+#define SIC_IWR1                        0xFFC00164     /* Interrupt Wakeup register */
+
+
+/* Watchdog Timer			(0xFFC00200 - 0xFFC002FF)								*/
+#define WDOG_CTL			0xFFC00200	/* Watchdog Control Register				*/
+#define WDOG_CNT			0xFFC00204	/* Watchdog Count Register					*/
+#define WDOG_STAT			0xFFC00208	/* Watchdog Status Register					*/
+
+
+/* Real Time Clock		(0xFFC00300 - 0xFFC003FF)									*/
+#define RTC_STAT			0xFFC00300	/* RTC Status Register						*/
+#define RTC_ICTL			0xFFC00304	/* RTC Interrupt Control Register			*/
+#define RTC_ISTAT			0xFFC00308	/* RTC Interrupt Status Register			*/
+#define RTC_SWCNT			0xFFC0030C	/* RTC Stopwatch Count Register				*/
+#define RTC_ALARM			0xFFC00310	/* RTC Alarm Time Register					*/
+#define RTC_FAST			0xFFC00314	/* RTC Prescaler Enable Register			*/
+#define RTC_PREN			0xFFC00314	/* RTC Prescaler Enable Alternate Macro		*/
+
+
+/* UART0 Controller		(0xFFC00400 - 0xFFC004FF)									*/
+#define UART0_THR			0xFFC00400	/* Transmit Holding register				*/
+#define UART0_RBR			0xFFC00400	/* Receive Buffer register					*/
+#define UART0_DLL			0xFFC00400	/* Divisor Latch (Low-Byte)					*/
+#define UART0_IER			0xFFC00404	/* Interrupt Enable Register				*/
+#define UART0_DLH			0xFFC00404	/* Divisor Latch (High-Byte)				*/
+#define UART0_IIR			0xFFC00408	/* Interrupt Identification Register		*/
+#define UART0_LCR			0xFFC0040C	/* Line Control Register					*/
+#define UART0_MCR			0xFFC00410	/* Modem Control Register					*/
+#define UART0_LSR			0xFFC00414	/* Line Status Register						*/
+#define UART0_MSR			0xFFC00418	/* Modem Status Register					*/
+#define UART0_SCR			0xFFC0041C	/* SCR Scratch Register						*/
+#define UART0_GCTL			0xFFC00424	/* Global Control Register					*/
+
+
+/* SPI Controller			(0xFFC00500 - 0xFFC005FF)								*/
+#define SPI0_REGBASE			0xFFC00500
+#define SPI_CTL				0xFFC00500	/* SPI Control Register						*/
+#define SPI_FLG				0xFFC00504	/* SPI Flag register						*/
+#define SPI_STAT			0xFFC00508	/* SPI Status register						*/
+#define SPI_TDBR			0xFFC0050C	/* SPI Transmit Data Buffer Register		*/
+#define SPI_RDBR			0xFFC00510	/* SPI Receive Data Buffer Register			*/
+#define SPI_BAUD			0xFFC00514	/* SPI Baud rate Register					*/
+#define SPI_SHADOW			0xFFC00518	/* SPI_RDBR Shadow Register					*/
+
+
+/* TIMER0-7 Registers		(0xFFC00600 - 0xFFC006FF)								*/
+#define TIMER0_CONFIG		0xFFC00600	/* Timer 0 Configuration Register			*/
+#define TIMER0_COUNTER		0xFFC00604	/* Timer 0 Counter Register					*/
+#define TIMER0_PERIOD		0xFFC00608	/* Timer 0 Period Register					*/
+#define TIMER0_WIDTH		0xFFC0060C	/* Timer 0 Width Register					*/
+
+#define TIMER1_CONFIG		0xFFC00610	/* Timer 1 Configuration Register  			*/
+#define TIMER1_COUNTER		0xFFC00614	/* Timer 1 Counter Register        			*/
+#define TIMER1_PERIOD		0xFFC00618	/* Timer 1 Period Register         			*/
+#define TIMER1_WIDTH		0xFFC0061C	/* Timer 1 Width Register          			*/
+
+#define TIMER2_CONFIG		0xFFC00620	/* Timer 2 Configuration Register  			*/
+#define TIMER2_COUNTER		0xFFC00624	/* Timer 2 Counter Register        			*/
+#define TIMER2_PERIOD		0xFFC00628	/* Timer 2 Period Register         			*/
+#define TIMER2_WIDTH		0xFFC0062C	/* Timer 2 Width Register          			*/
+
+#define TIMER3_CONFIG		0xFFC00630	/* Timer 3 Configuration Register			*/
+#define TIMER3_COUNTER		0xFFC00634	/* Timer 3 Counter Register					*/
+#define TIMER3_PERIOD		0xFFC00638	/* Timer 3 Period Register					*/
+#define TIMER3_WIDTH		0xFFC0063C	/* Timer 3 Width Register					*/
+
+#define TIMER4_CONFIG		0xFFC00640	/* Timer 4 Configuration Register  			*/
+#define TIMER4_COUNTER		0xFFC00644	/* Timer 4 Counter Register        			*/
+#define TIMER4_PERIOD		0xFFC00648	/* Timer 4 Period Register         			*/
+#define TIMER4_WIDTH		0xFFC0064C	/* Timer 4 Width Register          			*/
+
+#define TIMER5_CONFIG		0xFFC00650	/* Timer 5 Configuration Register  			*/
+#define TIMER5_COUNTER		0xFFC00654	/* Timer 5 Counter Register        			*/
+#define TIMER5_PERIOD		0xFFC00658	/* Timer 5 Period Register         			*/
+#define TIMER5_WIDTH		0xFFC0065C	/* Timer 5 Width Register          			*/
+
+#define TIMER6_CONFIG		0xFFC00660	/* Timer 6 Configuration Register  			*/
+#define TIMER6_COUNTER		0xFFC00664	/* Timer 6 Counter Register        			*/
+#define TIMER6_PERIOD		0xFFC00668	/* Timer 6 Period Register         			*/
+#define TIMER6_WIDTH		0xFFC0066C	/* Timer 6 Width Register          			*/
+
+#define TIMER7_CONFIG		0xFFC00670	/* Timer 7 Configuration Register  			*/
+#define TIMER7_COUNTER		0xFFC00674	/* Timer 7 Counter Register        			*/
+#define TIMER7_PERIOD		0xFFC00678	/* Timer 7 Period Register         			*/
+#define TIMER7_WIDTH		0xFFC0067C	/* Timer 7 Width Register       			*/
+
+#define TIMER_ENABLE		0xFFC00680	/* Timer Enable Register					*/
+#define TIMER_DISABLE		0xFFC00684	/* Timer Disable Register					*/
+#define TIMER_STATUS		0xFFC00688	/* Timer Status Register					*/
+
+
+/* General Purpose I/O Port F (0xFFC00700 - 0xFFC007FF)												*/
+#define PORTFIO					0xFFC00700	/* Port F I/O Pin State Specify Register				*/
+#define PORTFIO_CLEAR			0xFFC00704	/* Port F I/O Peripheral Interrupt Clear Register		*/
+#define PORTFIO_SET				0xFFC00708	/* Port F I/O Peripheral Interrupt Set Register			*/
+#define PORTFIO_TOGGLE			0xFFC0070C	/* Port F I/O Pin State Toggle Register					*/
+#define PORTFIO_MASKA			0xFFC00710	/* Port F I/O Mask State Specify Interrupt A Register	*/
+#define PORTFIO_MASKA_CLEAR		0xFFC00714	/* Port F I/O Mask Disable Interrupt A Register			*/
+#define PORTFIO_MASKA_SET		0xFFC00718	/* Port F I/O Mask Enable Interrupt A Register			*/
+#define PORTFIO_MASKA_TOGGLE	0xFFC0071C	/* Port F I/O Mask Toggle Enable Interrupt A Register	*/
+#define PORTFIO_MASKB			0xFFC00720	/* Port F I/O Mask State Specify Interrupt B Register	*/
+#define PORTFIO_MASKB_CLEAR		0xFFC00724	/* Port F I/O Mask Disable Interrupt B Register			*/
+#define PORTFIO_MASKB_SET		0xFFC00728	/* Port F I/O Mask Enable Interrupt B Register			*/
+#define PORTFIO_MASKB_TOGGLE	0xFFC0072C	/* Port F I/O Mask Toggle Enable Interrupt B Register	*/
+#define PORTFIO_DIR				0xFFC00730	/* Port F I/O Direction Register						*/
+#define PORTFIO_POLAR			0xFFC00734	/* Port F I/O Source Polarity Register					*/
+#define PORTFIO_EDGE			0xFFC00738	/* Port F I/O Source Sensitivity Register				*/
+#define PORTFIO_BOTH			0xFFC0073C	/* Port F I/O Set on BOTH Edges Register				*/
+#define PORTFIO_INEN			0xFFC00740	/* Port F I/O Input Enable Register 					*/
+
+
+/* SPORT0 Controller		(0xFFC00800 - 0xFFC008FF)										*/
+#define SPORT0_TCR1			0xFFC00800	/* SPORT0 Transmit Configuration 1 Register			*/
+#define SPORT0_TCR2			0xFFC00804	/* SPORT0 Transmit Configuration 2 Register			*/
+#define SPORT0_TCLKDIV		0xFFC00808	/* SPORT0 Transmit Clock Divider					*/
+#define SPORT0_TFSDIV		0xFFC0080C	/* SPORT0 Transmit Frame Sync Divider				*/
+#define SPORT0_TX			0xFFC00810	/* SPORT0 TX Data Register							*/
+#define SPORT0_RX			0xFFC00818	/* SPORT0 RX Data Register							*/
+#define SPORT0_RCR1			0xFFC00820	/* SPORT0 Transmit Configuration 1 Register			*/
+#define SPORT0_RCR2			0xFFC00824	/* SPORT0 Transmit Configuration 2 Register			*/
+#define SPORT0_RCLKDIV		0xFFC00828	/* SPORT0 Receive Clock Divider						*/
+#define SPORT0_RFSDIV		0xFFC0082C	/* SPORT0 Receive Frame Sync Divider				*/
+#define SPORT0_STAT			0xFFC00830	/* SPORT0 Status Register							*/
+#define SPORT0_CHNL			0xFFC00834	/* SPORT0 Current Channel Register					*/
+#define SPORT0_MCMC1		0xFFC00838	/* SPORT0 Multi-Channel Configuration Register 1	*/
+#define SPORT0_MCMC2		0xFFC0083C	/* SPORT0 Multi-Channel Configuration Register 2	*/
+#define SPORT0_MTCS0		0xFFC00840	/* SPORT0 Multi-Channel Transmit Select Register 0	*/
+#define SPORT0_MTCS1		0xFFC00844	/* SPORT0 Multi-Channel Transmit Select Register 1	*/
+#define SPORT0_MTCS2		0xFFC00848	/* SPORT0 Multi-Channel Transmit Select Register 2	*/
+#define SPORT0_MTCS3		0xFFC0084C	/* SPORT0 Multi-Channel Transmit Select Register 3	*/
+#define SPORT0_MRCS0		0xFFC00850	/* SPORT0 Multi-Channel Receive Select Register 0	*/
+#define SPORT0_MRCS1		0xFFC00854	/* SPORT0 Multi-Channel Receive Select Register 1	*/
+#define SPORT0_MRCS2		0xFFC00858	/* SPORT0 Multi-Channel Receive Select Register 2	*/
+#define SPORT0_MRCS3		0xFFC0085C	/* SPORT0 Multi-Channel Receive Select Register 3	*/
+
+
+/* SPORT1 Controller		(0xFFC00900 - 0xFFC009FF)										*/
+#define SPORT1_TCR1			0xFFC00900	/* SPORT1 Transmit Configuration 1 Register			*/
+#define SPORT1_TCR2			0xFFC00904	/* SPORT1 Transmit Configuration 2 Register			*/
+#define SPORT1_TCLKDIV		0xFFC00908	/* SPORT1 Transmit Clock Divider					*/
+#define SPORT1_TFSDIV		0xFFC0090C	/* SPORT1 Transmit Frame Sync Divider				*/
+#define SPORT1_TX			0xFFC00910	/* SPORT1 TX Data Register							*/
+#define SPORT1_RX			0xFFC00918	/* SPORT1 RX Data Register							*/
+#define SPORT1_RCR1			0xFFC00920	/* SPORT1 Transmit Configuration 1 Register			*/
+#define SPORT1_RCR2			0xFFC00924	/* SPORT1 Transmit Configuration 2 Register			*/
+#define SPORT1_RCLKDIV		0xFFC00928	/* SPORT1 Receive Clock Divider						*/
+#define SPORT1_RFSDIV		0xFFC0092C	/* SPORT1 Receive Frame Sync Divider				*/
+#define SPORT1_STAT			0xFFC00930	/* SPORT1 Status Register							*/
+#define SPORT1_CHNL			0xFFC00934	/* SPORT1 Current Channel Register					*/
+#define SPORT1_MCMC1		0xFFC00938	/* SPORT1 Multi-Channel Configuration Register 1	*/
+#define SPORT1_MCMC2		0xFFC0093C	/* SPORT1 Multi-Channel Configuration Register 2	*/
+#define SPORT1_MTCS0		0xFFC00940	/* SPORT1 Multi-Channel Transmit Select Register 0	*/
+#define SPORT1_MTCS1		0xFFC00944	/* SPORT1 Multi-Channel Transmit Select Register 1	*/
+#define SPORT1_MTCS2		0xFFC00948	/* SPORT1 Multi-Channel Transmit Select Register 2	*/
+#define SPORT1_MTCS3		0xFFC0094C	/* SPORT1 Multi-Channel Transmit Select Register 3	*/
+#define SPORT1_MRCS0		0xFFC00950	/* SPORT1 Multi-Channel Receive Select Register 0	*/
+#define SPORT1_MRCS1		0xFFC00954	/* SPORT1 Multi-Channel Receive Select Register 1	*/
+#define SPORT1_MRCS2		0xFFC00958	/* SPORT1 Multi-Channel Receive Select Register 2	*/
+#define SPORT1_MRCS3		0xFFC0095C	/* SPORT1 Multi-Channel Receive Select Register 3	*/
+
+
+/* External Bus Interface Unit (0xFFC00A00 - 0xFFC00AFF)								*/
+#define EBIU_AMGCTL			0xFFC00A00	/* Asynchronous Memory Global Control Register	*/
+#define EBIU_AMBCTL0		0xFFC00A04	/* Asynchronous Memory Bank Control Register 0	*/
+#define EBIU_AMBCTL1		0xFFC00A08	/* Asynchronous Memory Bank Control Register 1	*/
+#define EBIU_SDGCTL			0xFFC00A10	/* SDRAM Global Control Register				*/
+#define EBIU_SDBCTL			0xFFC00A14	/* SDRAM Bank Control Register					*/
+#define EBIU_SDRRC			0xFFC00A18	/* SDRAM Refresh Rate Control Register			*/
+#define EBIU_SDSTAT			0xFFC00A1C	/* SDRAM Status Register						*/
+
+
+/* DMA Traffic Control Registers													*/
+#define DMAC_TC_PER			0xFFC00B0C	/* Traffic Control Periods Register			*/
+#define DMAC_TC_CNT			0xFFC00B10	/* Traffic Control Current Counts Register	*/
+
+/* DMA Controller (0xFFC00C00 - 0xFFC00FFF)															*/
+#define DMA0_NEXT_DESC_PTR		0xFFC00C00	/* DMA Channel 0 Next Descriptor Pointer Register		*/
+#define DMA0_START_ADDR			0xFFC00C04	/* DMA Channel 0 Start Address Register					*/
+#define DMA0_CONFIG				0xFFC00C08	/* DMA Channel 0 Configuration Register					*/
+#define DMA0_X_COUNT			0xFFC00C10	/* DMA Channel 0 X Count Register						*/
+#define DMA0_X_MODIFY			0xFFC00C14	/* DMA Channel 0 X Modify Register						*/
+#define DMA0_Y_COUNT			0xFFC00C18	/* DMA Channel 0 Y Count Register						*/
+#define DMA0_Y_MODIFY			0xFFC00C1C	/* DMA Channel 0 Y Modify Register						*/
+#define DMA0_CURR_DESC_PTR		0xFFC00C20	/* DMA Channel 0 Current Descriptor Pointer Register	*/
+#define DMA0_CURR_ADDR			0xFFC00C24	/* DMA Channel 0 Current Address Register				*/
+#define DMA0_IRQ_STATUS			0xFFC00C28	/* DMA Channel 0 Interrupt/Status Register				*/
+#define DMA0_PERIPHERAL_MAP		0xFFC00C2C	/* DMA Channel 0 Peripheral Map Register				*/
+#define DMA0_CURR_X_COUNT		0xFFC00C30	/* DMA Channel 0 Current X Count Register				*/
+#define DMA0_CURR_Y_COUNT		0xFFC00C38	/* DMA Channel 0 Current Y Count Register				*/
+
+#define DMA1_NEXT_DESC_PTR		0xFFC00C40	/* DMA Channel 1 Next Descriptor Pointer Register		*/
+#define DMA1_START_ADDR			0xFFC00C44	/* DMA Channel 1 Start Address Register					*/
+#define DMA1_CONFIG				0xFFC00C48	/* DMA Channel 1 Configuration Register					*/
+#define DMA1_X_COUNT			0xFFC00C50	/* DMA Channel 1 X Count Register						*/
+#define DMA1_X_MODIFY			0xFFC00C54	/* DMA Channel 1 X Modify Register						*/
+#define DMA1_Y_COUNT			0xFFC00C58	/* DMA Channel 1 Y Count Register						*/
+#define DMA1_Y_MODIFY			0xFFC00C5C	/* DMA Channel 1 Y Modify Register						*/
+#define DMA1_CURR_DESC_PTR		0xFFC00C60	/* DMA Channel 1 Current Descriptor Pointer Register	*/
+#define DMA1_CURR_ADDR			0xFFC00C64	/* DMA Channel 1 Current Address Register				*/
+#define DMA1_IRQ_STATUS			0xFFC00C68	/* DMA Channel 1 Interrupt/Status Register				*/
+#define DMA1_PERIPHERAL_MAP		0xFFC00C6C	/* DMA Channel 1 Peripheral Map Register				*/
+#define DMA1_CURR_X_COUNT		0xFFC00C70	/* DMA Channel 1 Current X Count Register				*/
+#define DMA1_CURR_Y_COUNT		0xFFC00C78	/* DMA Channel 1 Current Y Count Register				*/
+
+#define DMA2_NEXT_DESC_PTR		0xFFC00C80	/* DMA Channel 2 Next Descriptor Pointer Register		*/
+#define DMA2_START_ADDR			0xFFC00C84	/* DMA Channel 2 Start Address Register					*/
+#define DMA2_CONFIG				0xFFC00C88	/* DMA Channel 2 Configuration Register					*/
+#define DMA2_X_COUNT			0xFFC00C90	/* DMA Channel 2 X Count Register						*/
+#define DMA2_X_MODIFY			0xFFC00C94	/* DMA Channel 2 X Modify Register						*/
+#define DMA2_Y_COUNT			0xFFC00C98	/* DMA Channel 2 Y Count Register						*/
+#define DMA2_Y_MODIFY			0xFFC00C9C	/* DMA Channel 2 Y Modify Register						*/
+#define DMA2_CURR_DESC_PTR		0xFFC00CA0	/* DMA Channel 2 Current Descriptor Pointer Register	*/
+#define DMA2_CURR_ADDR			0xFFC00CA4	/* DMA Channel 2 Current Address Register				*/
+#define DMA2_IRQ_STATUS			0xFFC00CA8	/* DMA Channel 2 Interrupt/Status Register				*/
+#define DMA2_PERIPHERAL_MAP		0xFFC00CAC	/* DMA Channel 2 Peripheral Map Register				*/
+#define DMA2_CURR_X_COUNT		0xFFC00CB0	/* DMA Channel 2 Current X Count Register				*/
+#define DMA2_CURR_Y_COUNT		0xFFC00CB8	/* DMA Channel 2 Current Y Count Register				*/
+
+#define DMA3_NEXT_DESC_PTR		0xFFC00CC0	/* DMA Channel 3 Next Descriptor Pointer Register		*/
+#define DMA3_START_ADDR			0xFFC00CC4	/* DMA Channel 3 Start Address Register					*/
+#define DMA3_CONFIG				0xFFC00CC8	/* DMA Channel 3 Configuration Register					*/
+#define DMA3_X_COUNT			0xFFC00CD0	/* DMA Channel 3 X Count Register						*/
+#define DMA3_X_MODIFY			0xFFC00CD4	/* DMA Channel 3 X Modify Register						*/
+#define DMA3_Y_COUNT			0xFFC00CD8	/* DMA Channel 3 Y Count Register						*/
+#define DMA3_Y_MODIFY			0xFFC00CDC	/* DMA Channel 3 Y Modify Register						*/
+#define DMA3_CURR_DESC_PTR		0xFFC00CE0	/* DMA Channel 3 Current Descriptor Pointer Register	*/
+#define DMA3_CURR_ADDR			0xFFC00CE4	/* DMA Channel 3 Current Address Register				*/
+#define DMA3_IRQ_STATUS			0xFFC00CE8	/* DMA Channel 3 Interrupt/Status Register				*/
+#define DMA3_PERIPHERAL_MAP		0xFFC00CEC	/* DMA Channel 3 Peripheral Map Register				*/
+#define DMA3_CURR_X_COUNT		0xFFC00CF0	/* DMA Channel 3 Current X Count Register				*/
+#define DMA3_CURR_Y_COUNT		0xFFC00CF8	/* DMA Channel 3 Current Y Count Register				*/
+
+#define DMA4_NEXT_DESC_PTR		0xFFC00D00	/* DMA Channel 4 Next Descriptor Pointer Register		*/
+#define DMA4_START_ADDR			0xFFC00D04	/* DMA Channel 4 Start Address Register					*/
+#define DMA4_CONFIG				0xFFC00D08	/* DMA Channel 4 Configuration Register					*/
+#define DMA4_X_COUNT			0xFFC00D10	/* DMA Channel 4 X Count Register						*/
+#define DMA4_X_MODIFY			0xFFC00D14	/* DMA Channel 4 X Modify Register						*/
+#define DMA4_Y_COUNT			0xFFC00D18	/* DMA Channel 4 Y Count Register						*/
+#define DMA4_Y_MODIFY			0xFFC00D1C	/* DMA Channel 4 Y Modify Register						*/
+#define DMA4_CURR_DESC_PTR		0xFFC00D20	/* DMA Channel 4 Current Descriptor Pointer Register	*/
+#define DMA4_CURR_ADDR			0xFFC00D24	/* DMA Channel 4 Current Address Register				*/
+#define DMA4_IRQ_STATUS			0xFFC00D28	/* DMA Channel 4 Interrupt/Status Register				*/
+#define DMA4_PERIPHERAL_MAP		0xFFC00D2C	/* DMA Channel 4 Peripheral Map Register				*/
+#define DMA4_CURR_X_COUNT		0xFFC00D30	/* DMA Channel 4 Current X Count Register				*/
+#define DMA4_CURR_Y_COUNT		0xFFC00D38	/* DMA Channel 4 Current Y Count Register				*/
+
+#define DMA5_NEXT_DESC_PTR		0xFFC00D40	/* DMA Channel 5 Next Descriptor Pointer Register		*/
+#define DMA5_START_ADDR			0xFFC00D44	/* DMA Channel 5 Start Address Register					*/
+#define DMA5_CONFIG				0xFFC00D48	/* DMA Channel 5 Configuration Register					*/
+#define DMA5_X_COUNT			0xFFC00D50	/* DMA Channel 5 X Count Register						*/
+#define DMA5_X_MODIFY			0xFFC00D54	/* DMA Channel 5 X Modify Register						*/
+#define DMA5_Y_COUNT			0xFFC00D58	/* DMA Channel 5 Y Count Register						*/
+#define DMA5_Y_MODIFY			0xFFC00D5C	/* DMA Channel 5 Y Modify Register						*/
+#define DMA5_CURR_DESC_PTR		0xFFC00D60	/* DMA Channel 5 Current Descriptor Pointer Register	*/
+#define DMA5_CURR_ADDR			0xFFC00D64	/* DMA Channel 5 Current Address Register				*/
+#define DMA5_IRQ_STATUS			0xFFC00D68	/* DMA Channel 5 Interrupt/Status Register				*/
+#define DMA5_PERIPHERAL_MAP		0xFFC00D6C	/* DMA Channel 5 Peripheral Map Register				*/
+#define DMA5_CURR_X_COUNT		0xFFC00D70	/* DMA Channel 5 Current X Count Register				*/
+#define DMA5_CURR_Y_COUNT		0xFFC00D78	/* DMA Channel 5 Current Y Count Register				*/
+
+#define DMA6_NEXT_DESC_PTR		0xFFC00D80	/* DMA Channel 6 Next Descriptor Pointer Register		*/
+#define DMA6_START_ADDR			0xFFC00D84	/* DMA Channel 6 Start Address Register					*/
+#define DMA6_CONFIG				0xFFC00D88	/* DMA Channel 6 Configuration Register					*/
+#define DMA6_X_COUNT			0xFFC00D90	/* DMA Channel 6 X Count Register						*/
+#define DMA6_X_MODIFY			0xFFC00D94	/* DMA Channel 6 X Modify Register						*/
+#define DMA6_Y_COUNT			0xFFC00D98	/* DMA Channel 6 Y Count Register						*/
+#define DMA6_Y_MODIFY			0xFFC00D9C	/* DMA Channel 6 Y Modify Register						*/
+#define DMA6_CURR_DESC_PTR		0xFFC00DA0	/* DMA Channel 6 Current Descriptor Pointer Register	*/
+#define DMA6_CURR_ADDR			0xFFC00DA4	/* DMA Channel 6 Current Address Register				*/
+#define DMA6_IRQ_STATUS			0xFFC00DA8	/* DMA Channel 6 Interrupt/Status Register				*/
+#define DMA6_PERIPHERAL_MAP		0xFFC00DAC	/* DMA Channel 6 Peripheral Map Register				*/
+#define DMA6_CURR_X_COUNT		0xFFC00DB0	/* DMA Channel 6 Current X Count Register				*/
+#define DMA6_CURR_Y_COUNT		0xFFC00DB8	/* DMA Channel 6 Current Y Count Register				*/
+
+#define DMA7_NEXT_DESC_PTR		0xFFC00DC0	/* DMA Channel 7 Next Descriptor Pointer Register		*/
+#define DMA7_START_ADDR			0xFFC00DC4	/* DMA Channel 7 Start Address Register					*/
+#define DMA7_CONFIG				0xFFC00DC8	/* DMA Channel 7 Configuration Register					*/
+#define DMA7_X_COUNT			0xFFC00DD0	/* DMA Channel 7 X Count Register						*/
+#define DMA7_X_MODIFY			0xFFC00DD4	/* DMA Channel 7 X Modify Register						*/
+#define DMA7_Y_COUNT			0xFFC00DD8	/* DMA Channel 7 Y Count Register						*/
+#define DMA7_Y_MODIFY			0xFFC00DDC	/* DMA Channel 7 Y Modify Register						*/
+#define DMA7_CURR_DESC_PTR		0xFFC00DE0	/* DMA Channel 7 Current Descriptor Pointer Register	*/
+#define DMA7_CURR_ADDR			0xFFC00DE4	/* DMA Channel 7 Current Address Register				*/
+#define DMA7_IRQ_STATUS			0xFFC00DE8	/* DMA Channel 7 Interrupt/Status Register				*/
+#define DMA7_PERIPHERAL_MAP		0xFFC00DEC	/* DMA Channel 7 Peripheral Map Register				*/
+#define DMA7_CURR_X_COUNT		0xFFC00DF0	/* DMA Channel 7 Current X Count Register				*/
+#define DMA7_CURR_Y_COUNT		0xFFC00DF8	/* DMA Channel 7 Current Y Count Register				*/
+
+#define DMA8_NEXT_DESC_PTR		0xFFC00E00	/* DMA Channel 8 Next Descriptor Pointer Register		*/
+#define DMA8_START_ADDR			0xFFC00E04	/* DMA Channel 8 Start Address Register					*/
+#define DMA8_CONFIG				0xFFC00E08	/* DMA Channel 8 Configuration Register					*/
+#define DMA8_X_COUNT			0xFFC00E10	/* DMA Channel 8 X Count Register						*/
+#define DMA8_X_MODIFY			0xFFC00E14	/* DMA Channel 8 X Modify Register						*/
+#define DMA8_Y_COUNT			0xFFC00E18	/* DMA Channel 8 Y Count Register						*/
+#define DMA8_Y_MODIFY			0xFFC00E1C	/* DMA Channel 8 Y Modify Register						*/
+#define DMA8_CURR_DESC_PTR		0xFFC00E20	/* DMA Channel 8 Current Descriptor Pointer Register	*/
+#define DMA8_CURR_ADDR			0xFFC00E24	/* DMA Channel 8 Current Address Register				*/
+#define DMA8_IRQ_STATUS			0xFFC00E28	/* DMA Channel 8 Interrupt/Status Register				*/
+#define DMA8_PERIPHERAL_MAP		0xFFC00E2C	/* DMA Channel 8 Peripheral Map Register				*/
+#define DMA8_CURR_X_COUNT		0xFFC00E30	/* DMA Channel 8 Current X Count Register				*/
+#define DMA8_CURR_Y_COUNT		0xFFC00E38	/* DMA Channel 8 Current Y Count Register				*/
+
+#define DMA9_NEXT_DESC_PTR		0xFFC00E40	/* DMA Channel 9 Next Descriptor Pointer Register		*/
+#define DMA9_START_ADDR			0xFFC00E44	/* DMA Channel 9 Start Address Register					*/
+#define DMA9_CONFIG				0xFFC00E48	/* DMA Channel 9 Configuration Register					*/
+#define DMA9_X_COUNT			0xFFC00E50	/* DMA Channel 9 X Count Register						*/
+#define DMA9_X_MODIFY			0xFFC00E54	/* DMA Channel 9 X Modify Register						*/
+#define DMA9_Y_COUNT			0xFFC00E58	/* DMA Channel 9 Y Count Register						*/
+#define DMA9_Y_MODIFY			0xFFC00E5C	/* DMA Channel 9 Y Modify Register						*/
+#define DMA9_CURR_DESC_PTR		0xFFC00E60	/* DMA Channel 9 Current Descriptor Pointer Register	*/
+#define DMA9_CURR_ADDR			0xFFC00E64	/* DMA Channel 9 Current Address Register				*/
+#define DMA9_IRQ_STATUS			0xFFC00E68	/* DMA Channel 9 Interrupt/Status Register				*/
+#define DMA9_PERIPHERAL_MAP		0xFFC00E6C	/* DMA Channel 9 Peripheral Map Register				*/
+#define DMA9_CURR_X_COUNT		0xFFC00E70	/* DMA Channel 9 Current X Count Register				*/
+#define DMA9_CURR_Y_COUNT		0xFFC00E78	/* DMA Channel 9 Current Y Count Register				*/
+
+#define DMA10_NEXT_DESC_PTR		0xFFC00E80	/* DMA Channel 10 Next Descriptor Pointer Register		*/
+#define DMA10_START_ADDR		0xFFC00E84	/* DMA Channel 10 Start Address Register				*/
+#define DMA10_CONFIG			0xFFC00E88	/* DMA Channel 10 Configuration Register				*/
+#define DMA10_X_COUNT			0xFFC00E90	/* DMA Channel 10 X Count Register						*/
+#define DMA10_X_MODIFY			0xFFC00E94	/* DMA Channel 10 X Modify Register						*/
+#define DMA10_Y_COUNT			0xFFC00E98	/* DMA Channel 10 Y Count Register						*/
+#define DMA10_Y_MODIFY			0xFFC00E9C	/* DMA Channel 10 Y Modify Register						*/
+#define DMA10_CURR_DESC_PTR		0xFFC00EA0	/* DMA Channel 10 Current Descriptor Pointer Register	*/
+#define DMA10_CURR_ADDR			0xFFC00EA4	/* DMA Channel 10 Current Address Register				*/
+#define DMA10_IRQ_STATUS		0xFFC00EA8	/* DMA Channel 10 Interrupt/Status Register				*/
+#define DMA10_PERIPHERAL_MAP	0xFFC00EAC	/* DMA Channel 10 Peripheral Map Register				*/
+#define DMA10_CURR_X_COUNT		0xFFC00EB0	/* DMA Channel 10 Current X Count Register				*/
+#define DMA10_CURR_Y_COUNT		0xFFC00EB8	/* DMA Channel 10 Current Y Count Register				*/
+
+#define DMA11_NEXT_DESC_PTR		0xFFC00EC0	/* DMA Channel 11 Next Descriptor Pointer Register		*/
+#define DMA11_START_ADDR		0xFFC00EC4	/* DMA Channel 11 Start Address Register				*/
+#define DMA11_CONFIG			0xFFC00EC8	/* DMA Channel 11 Configuration Register				*/
+#define DMA11_X_COUNT			0xFFC00ED0	/* DMA Channel 11 X Count Register						*/
+#define DMA11_X_MODIFY			0xFFC00ED4	/* DMA Channel 11 X Modify Register						*/
+#define DMA11_Y_COUNT			0xFFC00ED8	/* DMA Channel 11 Y Count Register						*/
+#define DMA11_Y_MODIFY			0xFFC00EDC	/* DMA Channel 11 Y Modify Register						*/
+#define DMA11_CURR_DESC_PTR		0xFFC00EE0	/* DMA Channel 11 Current Descriptor Pointer Register	*/
+#define DMA11_CURR_ADDR			0xFFC00EE4	/* DMA Channel 11 Current Address Register				*/
+#define DMA11_IRQ_STATUS		0xFFC00EE8	/* DMA Channel 11 Interrupt/Status Register				*/
+#define DMA11_PERIPHERAL_MAP	0xFFC00EEC	/* DMA Channel 11 Peripheral Map Register				*/
+#define DMA11_CURR_X_COUNT		0xFFC00EF0	/* DMA Channel 11 Current X Count Register				*/
+#define DMA11_CURR_Y_COUNT		0xFFC00EF8	/* DMA Channel 11 Current Y Count Register				*/
+
+#define MDMA_D0_NEXT_DESC_PTR	0xFFC00F00	/* MemDMA Stream 0 Destination Next Descriptor Pointer Register		*/
+#define MDMA_D0_START_ADDR		0xFFC00F04	/* MemDMA Stream 0 Destination Start Address Register				*/
+#define MDMA_D0_CONFIG			0xFFC00F08	/* MemDMA Stream 0 Destination Configuration Register				*/
+#define MDMA_D0_X_COUNT			0xFFC00F10	/* MemDMA Stream 0 Destination X Count Register						*/
+#define MDMA_D0_X_MODIFY		0xFFC00F14	/* MemDMA Stream 0 Destination X Modify Register					*/
+#define MDMA_D0_Y_COUNT			0xFFC00F18	/* MemDMA Stream 0 Destination Y Count Register						*/
+#define MDMA_D0_Y_MODIFY		0xFFC00F1C	/* MemDMA Stream 0 Destination Y Modify Register					*/
+#define MDMA_D0_CURR_DESC_PTR	0xFFC00F20	/* MemDMA Stream 0 Destination Current Descriptor Pointer Register	*/
+#define MDMA_D0_CURR_ADDR		0xFFC00F24	/* MemDMA Stream 0 Destination Current Address Register				*/
+#define MDMA_D0_IRQ_STATUS		0xFFC00F28	/* MemDMA Stream 0 Destination Interrupt/Status Register			*/
+#define MDMA_D0_PERIPHERAL_MAP	0xFFC00F2C	/* MemDMA Stream 0 Destination Peripheral Map Register				*/
+#define MDMA_D0_CURR_X_COUNT	0xFFC00F30	/* MemDMA Stream 0 Destination Current X Count Register				*/
+#define MDMA_D0_CURR_Y_COUNT	0xFFC00F38	/* MemDMA Stream 0 Destination Current Y Count Register				*/
+
+#define MDMA_S0_NEXT_DESC_PTR	0xFFC00F40	/* MemDMA Stream 0 Source Next Descriptor Pointer Register			*/
+#define MDMA_S0_START_ADDR		0xFFC00F44	/* MemDMA Stream 0 Source Start Address Register					*/
+#define MDMA_S0_CONFIG			0xFFC00F48	/* MemDMA Stream 0 Source Configuration Register					*/
+#define MDMA_S0_X_COUNT			0xFFC00F50	/* MemDMA Stream 0 Source X Count Register							*/
+#define MDMA_S0_X_MODIFY		0xFFC00F54	/* MemDMA Stream 0 Source X Modify Register							*/
+#define MDMA_S0_Y_COUNT			0xFFC00F58	/* MemDMA Stream 0 Source Y Count Register							*/
+#define MDMA_S0_Y_MODIFY		0xFFC00F5C	/* MemDMA Stream 0 Source Y Modify Register							*/
+#define MDMA_S0_CURR_DESC_PTR	0xFFC00F60	/* MemDMA Stream 0 Source Current Descriptor Pointer Register		*/
+#define MDMA_S0_CURR_ADDR		0xFFC00F64	/* MemDMA Stream 0 Source Current Address Register					*/
+#define MDMA_S0_IRQ_STATUS		0xFFC00F68	/* MemDMA Stream 0 Source Interrupt/Status Register					*/
+#define MDMA_S0_PERIPHERAL_MAP	0xFFC00F6C	/* MemDMA Stream 0 Source Peripheral Map Register					*/
+#define MDMA_S0_CURR_X_COUNT	0xFFC00F70	/* MemDMA Stream 0 Source Current X Count Register					*/
+#define MDMA_S0_CURR_Y_COUNT	0xFFC00F78	/* MemDMA Stream 0 Source Current Y Count Register					*/
+
+#define MDMA_D1_NEXT_DESC_PTR	0xFFC00F80	/* MemDMA Stream 1 Destination Next Descriptor Pointer Register		*/
+#define MDMA_D1_START_ADDR		0xFFC00F84	/* MemDMA Stream 1 Destination Start Address Register				*/
+#define MDMA_D1_CONFIG			0xFFC00F88	/* MemDMA Stream 1 Destination Configuration Register				*/
+#define MDMA_D1_X_COUNT			0xFFC00F90	/* MemDMA Stream 1 Destination X Count Register						*/
+#define MDMA_D1_X_MODIFY		0xFFC00F94	/* MemDMA Stream 1 Destination X Modify Register					*/
+#define MDMA_D1_Y_COUNT			0xFFC00F98	/* MemDMA Stream 1 Destination Y Count Register						*/
+#define MDMA_D1_Y_MODIFY		0xFFC00F9C	/* MemDMA Stream 1 Destination Y Modify Register					*/
+#define MDMA_D1_CURR_DESC_PTR	0xFFC00FA0	/* MemDMA Stream 1 Destination Current Descriptor Pointer Register	*/
+#define MDMA_D1_CURR_ADDR		0xFFC00FA4	/* MemDMA Stream 1 Destination Current Address Register				*/
+#define MDMA_D1_IRQ_STATUS		0xFFC00FA8	/* MemDMA Stream 1 Destination Interrupt/Status Register			*/
+#define MDMA_D1_PERIPHERAL_MAP	0xFFC00FAC	/* MemDMA Stream 1 Destination Peripheral Map Register				*/
+#define MDMA_D1_CURR_X_COUNT	0xFFC00FB0	/* MemDMA Stream 1 Destination Current X Count Register				*/
+#define MDMA_D1_CURR_Y_COUNT	0xFFC00FB8	/* MemDMA Stream 1 Destination Current Y Count Register				*/
+
+#define MDMA_S1_NEXT_DESC_PTR	0xFFC00FC0	/* MemDMA Stream 1 Source Next Descriptor Pointer Register			*/
+#define MDMA_S1_START_ADDR		0xFFC00FC4	/* MemDMA Stream 1 Source Start Address Register					*/
+#define MDMA_S1_CONFIG			0xFFC00FC8	/* MemDMA Stream 1 Source Configuration Register					*/
+#define MDMA_S1_X_COUNT			0xFFC00FD0	/* MemDMA Stream 1 Source X Count Register							*/
+#define MDMA_S1_X_MODIFY		0xFFC00FD4	/* MemDMA Stream 1 Source X Modify Register							*/
+#define MDMA_S1_Y_COUNT			0xFFC00FD8	/* MemDMA Stream 1 Source Y Count Register							*/
+#define MDMA_S1_Y_MODIFY		0xFFC00FDC	/* MemDMA Stream 1 Source Y Modify Register							*/
+#define MDMA_S1_CURR_DESC_PTR	0xFFC00FE0	/* MemDMA Stream 1 Source Current Descriptor Pointer Register		*/
+#define MDMA_S1_CURR_ADDR		0xFFC00FE4	/* MemDMA Stream 1 Source Current Address Register					*/
+#define MDMA_S1_IRQ_STATUS		0xFFC00FE8	/* MemDMA Stream 1 Source Interrupt/Status Register					*/
+#define MDMA_S1_PERIPHERAL_MAP	0xFFC00FEC	/* MemDMA Stream 1 Source Peripheral Map Register					*/
+#define MDMA_S1_CURR_X_COUNT	0xFFC00FF0	/* MemDMA Stream 1 Source Current X Count Register					*/
+#define MDMA_S1_CURR_Y_COUNT	0xFFC00FF8	/* MemDMA Stream 1 Source Current Y Count Register					*/
+
+
+/* Parallel Peripheral Interface (0xFFC01000 - 0xFFC010FF)				*/
+#define PPI_CONTROL			0xFFC01000	/* PPI Control Register			*/
+#define PPI_STATUS			0xFFC01004	/* PPI Status Register			*/
+#define PPI_COUNT			0xFFC01008	/* PPI Transfer Count Register	*/
+#define PPI_DELAY			0xFFC0100C	/* PPI Delay Count Register		*/
+#define PPI_FRAME			0xFFC01010	/* PPI Frame Length Register	*/
+
+
+/* Two-Wire Interface		(0xFFC01400 - 0xFFC014FF)								*/
+#define TWI0_REGBASE			0xFFC01400
+#define TWI0_CLKDIV			0xFFC01400	/* Serial Clock Divider Register			*/
+#define TWI0_CONTROL			0xFFC01404	/* TWI Control Register						*/
+#define TWI0_SLAVE_CTL		0xFFC01408	/* Slave Mode Control Register				*/
+#define TWI0_SLAVE_STAT		0xFFC0140C	/* Slave Mode Status Register				*/
+#define TWI0_SLAVE_ADDR		0xFFC01410	/* Slave Mode Address Register				*/
+#define TWI0_MASTER_CTL		0xFFC01414	/* Master Mode Control Register				*/
+#define TWI0_MASTER_STAT		0xFFC01418	/* Master Mode Status Register				*/
+#define TWI0_MASTER_ADDR		0xFFC0141C	/* Master Mode Address Register				*/
+#define TWI0_INT_STAT		0xFFC01420	/* TWI Interrupt Status Register			*/
+#define TWI0_INT_MASK		0xFFC01424	/* TWI Master Interrupt Mask Register		*/
+#define TWI0_FIFO_CTL		0xFFC01428	/* FIFO Control Register					*/
+#define TWI0_FIFO_STAT		0xFFC0142C	/* FIFO Status Register						*/
+#define TWI0_XMT_DATA8		0xFFC01480	/* FIFO Transmit Data Single Byte Register	*/
+#define TWI0_XMT_DATA16		0xFFC01484	/* FIFO Transmit Data Double Byte Register	*/
+#define TWI0_RCV_DATA8		0xFFC01488	/* FIFO Receive Data Single Byte Register	*/
+#define TWI0_RCV_DATA16		0xFFC0148C	/* FIFO Receive Data Double Byte Register	*/
+
+
+/* General Purpose I/O Port G (0xFFC01500 - 0xFFC015FF)												*/
+#define PORTGIO					0xFFC01500	/* Port G I/O Pin State Specify Register				*/
+#define PORTGIO_CLEAR			0xFFC01504	/* Port G I/O Peripheral Interrupt Clear Register		*/
+#define PORTGIO_SET				0xFFC01508	/* Port G I/O Peripheral Interrupt Set Register			*/
+#define PORTGIO_TOGGLE			0xFFC0150C	/* Port G I/O Pin State Toggle Register					*/
+#define PORTGIO_MASKA			0xFFC01510	/* Port G I/O Mask State Specify Interrupt A Register	*/
+#define PORTGIO_MASKA_CLEAR		0xFFC01514	/* Port G I/O Mask Disable Interrupt A Register			*/
+#define PORTGIO_MASKA_SET		0xFFC01518	/* Port G I/O Mask Enable Interrupt A Register			*/
+#define PORTGIO_MASKA_TOGGLE	0xFFC0151C	/* Port G I/O Mask Toggle Enable Interrupt A Register	*/
+#define PORTGIO_MASKB			0xFFC01520	/* Port G I/O Mask State Specify Interrupt B Register	*/
+#define PORTGIO_MASKB_CLEAR		0xFFC01524	/* Port G I/O Mask Disable Interrupt B Register			*/
+#define PORTGIO_MASKB_SET		0xFFC01528	/* Port G I/O Mask Enable Interrupt B Register			*/
+#define PORTGIO_MASKB_TOGGLE	0xFFC0152C	/* Port G I/O Mask Toggle Enable Interrupt B Register	*/
+#define PORTGIO_DIR				0xFFC01530	/* Port G I/O Direction Register						*/
+#define PORTGIO_POLAR			0xFFC01534	/* Port G I/O Source Polarity Register					*/
+#define PORTGIO_EDGE			0xFFC01538	/* Port G I/O Source Sensitivity Register				*/
+#define PORTGIO_BOTH			0xFFC0153C	/* Port G I/O Set on BOTH Edges Register				*/
+#define PORTGIO_INEN			0xFFC01540	/* Port G I/O Input Enable Register						*/
+
+
+/* General Purpose I/O Port H (0xFFC01700 - 0xFFC017FF)												*/
+#define PORTHIO					0xFFC01700	/* Port H I/O Pin State Specify Register				*/
+#define PORTHIO_CLEAR			0xFFC01704	/* Port H I/O Peripheral Interrupt Clear Register		*/
+#define PORTHIO_SET				0xFFC01708	/* Port H I/O Peripheral Interrupt Set Register			*/
+#define PORTHIO_TOGGLE			0xFFC0170C	/* Port H I/O Pin State Toggle Register					*/
+#define PORTHIO_MASKA			0xFFC01710	/* Port H I/O Mask State Specify Interrupt A Register	*/
+#define PORTHIO_MASKA_CLEAR		0xFFC01714	/* Port H I/O Mask Disable Interrupt A Register			*/
+#define PORTHIO_MASKA_SET		0xFFC01718	/* Port H I/O Mask Enable Interrupt A Register			*/
+#define PORTHIO_MASKA_TOGGLE	0xFFC0171C	/* Port H I/O Mask Toggle Enable Interrupt A Register	*/
+#define PORTHIO_MASKB			0xFFC01720	/* Port H I/O Mask State Specify Interrupt B Register	*/
+#define PORTHIO_MASKB_CLEAR		0xFFC01724	/* Port H I/O Mask Disable Interrupt B Register			*/
+#define PORTHIO_MASKB_SET		0xFFC01728	/* Port H I/O Mask Enable Interrupt B Register			*/
+#define PORTHIO_MASKB_TOGGLE	0xFFC0172C	/* Port H I/O Mask Toggle Enable Interrupt B Register	*/
+#define PORTHIO_DIR				0xFFC01730	/* Port H I/O Direction Register						*/
+#define PORTHIO_POLAR			0xFFC01734	/* Port H I/O Source Polarity Register					*/
+#define PORTHIO_EDGE			0xFFC01738	/* Port H I/O Source Sensitivity Register				*/
+#define PORTHIO_BOTH			0xFFC0173C	/* Port H I/O Set on BOTH Edges Register				*/
+#define PORTHIO_INEN			0xFFC01740	/* Port H I/O Input Enable Register						*/
+
+
+/* UART1 Controller		(0xFFC02000 - 0xFFC020FF)								*/
+#define UART1_THR			0xFFC02000	/* Transmit Holding register			*/
+#define UART1_RBR			0xFFC02000	/* Receive Buffer register				*/
+#define UART1_DLL			0xFFC02000	/* Divisor Latch (Low-Byte)				*/
+#define UART1_IER			0xFFC02004	/* Interrupt Enable Register			*/
+#define UART1_DLH			0xFFC02004	/* Divisor Latch (High-Byte)			*/
+#define UART1_IIR			0xFFC02008	/* Interrupt Identification Register	*/
+#define UART1_LCR			0xFFC0200C	/* Line Control Register				*/
+#define UART1_MCR			0xFFC02010	/* Modem Control Register				*/
+#define UART1_LSR			0xFFC02014	/* Line Status Register					*/
+#define UART1_MSR			0xFFC02018	/* Modem Status Register				*/
+#define UART1_SCR			0xFFC0201C	/* SCR Scratch Register					*/
+#define UART1_GCTL			0xFFC02024	/* Global Control Register				*/
+
+
+/* Omit CAN register sets from the defBF534.h (CAN is not in the ADSP-BF52x processor) */
+
+/* Pin Control Registers	(0xFFC03200 - 0xFFC032FF)											*/
+#define PORTF_FER			0xFFC03200	/* Port F Function Enable Register (Alternate/Flag*)	*/
+#define PORTG_FER			0xFFC03204	/* Port G Function Enable Register (Alternate/Flag*)	*/
+#define PORTH_FER			0xFFC03208	/* Port H Function Enable Register (Alternate/Flag*)	*/
+#define BFIN_PORT_MUX			0xFFC0320C	/* Port Multiplexer Control Register					*/
+
+
+/* Handshake MDMA Registers	(0xFFC03300 - 0xFFC033FF)										*/
+#define HMDMA0_CONTROL		0xFFC03300	/* Handshake MDMA0 Control Register					*/
+#define HMDMA0_ECINIT		0xFFC03304	/* HMDMA0 Initial Edge Count Register				*/
+#define HMDMA0_BCINIT		0xFFC03308	/* HMDMA0 Initial Block Count Register				*/
+#define HMDMA0_ECURGENT		0xFFC0330C	/* HMDMA0 Urgent Edge Count Threshold Register		*/
+#define HMDMA0_ECOVERFLOW	0xFFC03310	/* HMDMA0 Edge Count Overflow Interrupt Register	*/
+#define HMDMA0_ECOUNT		0xFFC03314	/* HMDMA0 Current Edge Count Register				*/
+#define HMDMA0_BCOUNT		0xFFC03318	/* HMDMA0 Current Block Count Register				*/
+
+#define HMDMA1_CONTROL		0xFFC03340	/* Handshake MDMA1 Control Register					*/
+#define HMDMA1_ECINIT		0xFFC03344	/* HMDMA1 Initial Edge Count Register				*/
+#define HMDMA1_BCINIT		0xFFC03348	/* HMDMA1 Initial Block Count Register				*/
+#define HMDMA1_ECURGENT		0xFFC0334C	/* HMDMA1 Urgent Edge Count Threshold Register		*/
+#define HMDMA1_ECOVERFLOW	0xFFC03350	/* HMDMA1 Edge Count Overflow Interrupt Register	*/
+#define HMDMA1_ECOUNT		0xFFC03354	/* HMDMA1 Current Edge Count Register				*/
+#define HMDMA1_BCOUNT		0xFFC03358	/* HMDMA1 Current Block Count Register				*/
+
+/* GPIO PIN mux (0xFFC03210 - OxFFC03288) */
+#define PORTF_MUX               0xFFC03210      /* Port F mux control */
+#define PORTG_MUX               0xFFC03214      /* Port G mux control */
+#define PORTH_MUX               0xFFC03218      /* Port H mux control */
+#define PORTF_DRIVE             0xFFC03220      /* Port F drive strength control */
+#define PORTG_DRIVE             0xFFC03224      /* Port G drive strength control */
+#define PORTH_DRIVE             0xFFC03228      /* Port H drive strength control */
+#define PORTF_SLEW              0xFFC03230      /* Port F slew control */
+#define PORTG_SLEW              0xFFC03234      /* Port G slew control */
+#define PORTH_SLEW              0xFFC03238      /* Port H slew control */
+#define PORTF_HYSTERISIS        0xFFC03240      /* Port F Schmitt trigger control */
+#define PORTG_HYSTERISIS        0xFFC03244      /* Port G Schmitt trigger control */
+#define PORTH_HYSTERISIS        0xFFC03248      /* Port H Schmitt trigger control */
+#define MISCPORT_DRIVE          0xFFC03280      /* Misc Port drive strength control */
+#define MISCPORT_SLEW           0xFFC03284      /* Misc Port slew control */
+#define MISCPORT_HYSTERISIS     0xFFC03288      /* Misc Port Schmitt trigger control */
+
+
+/***********************************************************************************
+** System MMR Register Bits And Macros
+**
+** Disclaimer:	All macros are intended to make C and Assembly code more readable.
+**				Use these macros carefully, as any that do left shifts for field
+**				depositing will result in the lower order bits being destroyed.  Any
+**				macro that shifts left to properly position the bit-field should be
+**				used as part of an OR to initialize a register and NOT as a dynamic
+**				modifier UNLESS the lower order bits are saved and ORed back in when
+**				the macro is used.
+*************************************************************************************/
+
+/* CHIPID Masks */
+#define CHIPID_VERSION         0xF0000000
+#define CHIPID_FAMILY          0x0FFFF000
+#define CHIPID_MANUFACTURE     0x00000FFE
+
+/* SWRST Masks																		*/
+#define SYSTEM_RESET		0x0007	/* Initiates A System Software Reset			*/
+#define	DOUBLE_FAULT		0x0008	/* Core Double Fault Causes Reset				*/
+#define RESET_DOUBLE		0x2000	/* SW Reset Generated By Core Double-Fault		*/
+#define RESET_WDOG			0x4000	/* SW Reset Generated By Watchdog Timer			*/
+#define RESET_SOFTWARE		0x8000	/* SW Reset Occurred Since Last Read Of SWRST	*/
+
+/* SYSCR Masks																				*/
+#define BMODE				0x0007	/* Boot Mode - Latched During HW Reset From Mode Pins	*/
+#define	NOBOOT				0x0010	/* Execute From L1 or ASYNC Bank 0 When BMODE = 0		*/
+
+
+/* *************  SYSTEM INTERRUPT CONTROLLER MASKS *************************************/
+/* Peripheral Masks For SIC_ISR, SIC_IWR, SIC_IMASK										*/
+
+#if 0
+#define IRQ_PLL_WAKEUP	0x00000001	/* PLL Wakeup Interrupt			 					*/
+
+#define IRQ_ERROR1      0x00000002  /* Error Interrupt (DMA, DMARx Block, DMARx Overflow) */
+#define IRQ_ERROR2      0x00000004  /* Error Interrupt (CAN, Ethernet, SPORTx, PPI, SPI, UARTx) */
+#define IRQ_RTC			0x00000008	/* Real Time Clock Interrupt 						*/
+#define IRQ_DMA0		0x00000010	/* DMA Channel 0 (PPI) Interrupt 					*/
+#define IRQ_DMA3		0x00000020	/* DMA Channel 3 (SPORT0 RX) Interrupt 				*/
+#define IRQ_DMA4		0x00000040	/* DMA Channel 4 (SPORT0 TX) Interrupt 				*/
+#define IRQ_DMA5		0x00000080	/* DMA Channel 5 (SPORT1 RX) Interrupt 				*/
+
+#define IRQ_DMA6		0x00000100	/* DMA Channel 6 (SPORT1 TX) Interrupt 		 		*/
+#define IRQ_TWI			0x00000200	/* TWI Interrupt									*/
+#define IRQ_DMA7		0x00000400	/* DMA Channel 7 (SPI) Interrupt 					*/
+#define IRQ_DMA8		0x00000800	/* DMA Channel 8 (UART0 RX) Interrupt 				*/
+#define IRQ_DMA9		0x00001000	/* DMA Channel 9 (UART0 TX) Interrupt 				*/
+#define IRQ_DMA10		0x00002000	/* DMA Channel 10 (UART1 RX) Interrupt 				*/
+#define IRQ_DMA11		0x00004000	/* DMA Channel 11 (UART1 TX) Interrupt 				*/
+#define IRQ_CAN_RX		0x00008000	/* CAN Receive Interrupt 							*/
+
+#define IRQ_CAN_TX		0x00010000	/* CAN Transmit Interrupt  							*/
+#define IRQ_DMA1		0x00020000	/* DMA Channel 1 (Ethernet RX) Interrupt 			*/
+#define IRQ_PFA_PORTH	0x00020000	/* PF Port H (PF47:32) Interrupt A 					*/
+#define IRQ_DMA2		0x00040000	/* DMA Channel 2 (Ethernet TX) Interrupt 			*/
+#define IRQ_PFB_PORTH	0x00040000	/* PF Port H (PF47:32) Interrupt B 					*/
+#define IRQ_TIMER0		0x00080000	/* Timer 0 Interrupt								*/
+#define IRQ_TIMER1		0x00100000	/* Timer 1 Interrupt 								*/
+#define IRQ_TIMER2		0x00200000	/* Timer 2 Interrupt 								*/
+#define IRQ_TIMER3		0x00400000	/* Timer 3 Interrupt 								*/
+#define IRQ_TIMER4		0x00800000	/* Timer 4 Interrupt 								*/
+
+#define IRQ_TIMER5		0x01000000	/* Timer 5 Interrupt 								*/
+#define IRQ_TIMER6		0x02000000	/* Timer 6 Interrupt 								*/
+#define IRQ_TIMER7		0x04000000	/* Timer 7 Interrupt 								*/
+#define IRQ_PFA_PORTFG	0x08000000	/* PF Ports F&G (PF31:0) Interrupt A 				*/
+#define IRQ_PFB_PORTF	0x80000000	/* PF Port F (PF15:0) Interrupt B 					*/
+#define IRQ_DMA12		0x20000000	/* DMA Channels 12 (MDMA1 Source) RX Interrupt 		*/
+#define IRQ_DMA13		0x20000000	/* DMA Channels 13 (MDMA1 Destination) TX Interrupt */
+#define IRQ_DMA14		0x40000000	/* DMA Channels 14 (MDMA0 Source) RX Interrupt 		*/
+#define IRQ_DMA15		0x40000000	/* DMA Channels 15 (MDMA0 Destination) TX Interrupt */
+#define IRQ_WDOG		0x80000000	/* Software Watchdog Timer Interrupt 				*/
+#define IRQ_PFB_PORTG	0x10000000	/* PF Port G (PF31:16) Interrupt B 					*/
+#endif
+
+/* SIC_IAR0 Macros															*/
+#define P0_IVG(x)		(((x)&0xF)-7)			/* Peripheral #0 assigned IVG #x 	*/
+#define P1_IVG(x)		(((x)&0xF)-7) << 0x4	/* Peripheral #1 assigned IVG #x 	*/
+#define P2_IVG(x)		(((x)&0xF)-7) << 0x8	/* Peripheral #2 assigned IVG #x 	*/
+#define P3_IVG(x)		(((x)&0xF)-7) << 0xC	/* Peripheral #3 assigned IVG #x	*/
+#define P4_IVG(x)		(((x)&0xF)-7) << 0x10	/* Peripheral #4 assigned IVG #x	*/
+#define P5_IVG(x)		(((x)&0xF)-7) << 0x14	/* Peripheral #5 assigned IVG #x	*/
+#define P6_IVG(x)		(((x)&0xF)-7) << 0x18	/* Peripheral #6 assigned IVG #x	*/
+#define P7_IVG(x)		(((x)&0xF)-7) << 0x1C	/* Peripheral #7 assigned IVG #x	*/
+
+/* SIC_IAR1 Macros															*/
+#define P8_IVG(x)		(((x)&0xF)-7)			/* Peripheral #8 assigned IVG #x 	*/
+#define P9_IVG(x)		(((x)&0xF)-7) << 0x4	/* Peripheral #9 assigned IVG #x 	*/
+#define P10_IVG(x)		(((x)&0xF)-7) << 0x8	/* Peripheral #10 assigned IVG #x	*/
+#define P11_IVG(x)		(((x)&0xF)-7) << 0xC	/* Peripheral #11 assigned IVG #x 	*/
+#define P12_IVG(x)		(((x)&0xF)-7) << 0x10	/* Peripheral #12 assigned IVG #x	*/
+#define P13_IVG(x)		(((x)&0xF)-7) << 0x14	/* Peripheral #13 assigned IVG #x	*/
+#define P14_IVG(x)		(((x)&0xF)-7) << 0x18	/* Peripheral #14 assigned IVG #x	*/
+#define P15_IVG(x)		(((x)&0xF)-7) << 0x1C	/* Peripheral #15 assigned IVG #x	*/
+
+/* SIC_IAR2 Macros															*/
+#define P16_IVG(x)		(((x)&0xF)-7)			/* Peripheral #16 assigned IVG #x	*/
+#define P17_IVG(x)		(((x)&0xF)-7) << 0x4	/* Peripheral #17 assigned IVG #x	*/
+#define P18_IVG(x)		(((x)&0xF)-7) << 0x8	/* Peripheral #18 assigned IVG #x	*/
+#define P19_IVG(x)		(((x)&0xF)-7) << 0xC	/* Peripheral #19 assigned IVG #x	*/
+#define P20_IVG(x)		(((x)&0xF)-7) << 0x10	/* Peripheral #20 assigned IVG #x	*/
+#define P21_IVG(x)		(((x)&0xF)-7) << 0x14	/* Peripheral #21 assigned IVG #x	*/
+#define P22_IVG(x)		(((x)&0xF)-7) << 0x18	/* Peripheral #22 assigned IVG #x	*/
+#define P23_IVG(x)		(((x)&0xF)-7) << 0x1C	/* Peripheral #23 assigned IVG #x	*/
+
+/* SIC_IAR3 Macros															*/
+#define P24_IVG(x)		(((x)&0xF)-7)			/* Peripheral #24 assigned IVG #x	*/
+#define P25_IVG(x)		(((x)&0xF)-7) << 0x4	/* Peripheral #25 assigned IVG #x	*/
+#define P26_IVG(x)		(((x)&0xF)-7) << 0x8	/* Peripheral #26 assigned IVG #x	*/
+#define P27_IVG(x)		(((x)&0xF)-7) << 0xC	/* Peripheral #27 assigned IVG #x	*/
+#define P28_IVG(x)		(((x)&0xF)-7) << 0x10	/* Peripheral #28 assigned IVG #x	*/
+#define P29_IVG(x)		(((x)&0xF)-7) << 0x14	/* Peripheral #29 assigned IVG #x	*/
+#define P30_IVG(x)		(((x)&0xF)-7) << 0x18	/* Peripheral #30 assigned IVG #x	*/
+#define P31_IVG(x)		(((x)&0xF)-7) << 0x1C	/* Peripheral #31 assigned IVG #x	*/
+
+
+/* SIC_IMASK Masks																		*/
+#define SIC_UNMASK_ALL	0x00000000					/* Unmask all peripheral interrupts	*/
+#define SIC_MASK_ALL	0xFFFFFFFF					/* Mask all peripheral interrupts	*/
+#define SIC_MASK(x)		(1 << ((x)&0x1F))					/* Mask Peripheral #x interrupt		*/
+#define SIC_UNMASK(x)	(0xFFFFFFFF ^ (1 << ((x)&0x1F)))	/* Unmask Peripheral #x interrupt	*/
+
+/* SIC_IWR Masks																		*/
+#define IWR_DISABLE_ALL	0x00000000					/* Wakeup Disable all peripherals	*/
+#define IWR_ENABLE_ALL	0xFFFFFFFF					/* Wakeup Enable all peripherals	*/
+#define IWR_ENABLE(x)	(1 << ((x)&0x1F))					/* Wakeup Enable Peripheral #x		*/
+#define IWR_DISABLE(x)	(0xFFFFFFFF ^ (1 << ((x)&0x1F))) 	/* Wakeup Disable Peripheral #x		*/
+
+/*  ****************  GENERAL PURPOSE TIMER MASKS  **********************/
+/* TIMER_ENABLE Masks													*/
+#define TIMEN0			0x0001		/* Enable Timer 0					*/
+#define TIMEN1			0x0002		/* Enable Timer 1					*/
+#define TIMEN2			0x0004		/* Enable Timer 2					*/
+#define TIMEN3			0x0008		/* Enable Timer 3					*/
+#define TIMEN4			0x0010		/* Enable Timer 4					*/
+#define TIMEN5			0x0020		/* Enable Timer 5					*/
+#define TIMEN6			0x0040		/* Enable Timer 6					*/
+#define TIMEN7			0x0080		/* Enable Timer 7					*/
+
+/* TIMER_DISABLE Masks													*/
+#define TIMDIS0			TIMEN0		/* Disable Timer 0					*/
+#define TIMDIS1			TIMEN1		/* Disable Timer 1					*/
+#define TIMDIS2			TIMEN2		/* Disable Timer 2					*/
+#define TIMDIS3			TIMEN3		/* Disable Timer 3					*/
+#define TIMDIS4			TIMEN4		/* Disable Timer 4					*/
+#define TIMDIS5			TIMEN5		/* Disable Timer 5					*/
+#define TIMDIS6			TIMEN6		/* Disable Timer 6					*/
+#define TIMDIS7			TIMEN7		/* Disable Timer 7					*/
+
+/* TIMER_STATUS Masks													*/
+#define TIMIL0			0x00000001	/* Timer 0 Interrupt				*/
+#define TIMIL1			0x00000002	/* Timer 1 Interrupt				*/
+#define TIMIL2			0x00000004	/* Timer 2 Interrupt				*/
+#define TIMIL3			0x00000008	/* Timer 3 Interrupt				*/
+#define TOVF_ERR0		0x00000010	/* Timer 0 Counter Overflow			*/
+#define TOVF_ERR1		0x00000020	/* Timer 1 Counter Overflow			*/
+#define TOVF_ERR2		0x00000040	/* Timer 2 Counter Overflow			*/
+#define TOVF_ERR3		0x00000080	/* Timer 3 Counter Overflow			*/
+#define TRUN0			0x00001000	/* Timer 0 Slave Enable Status		*/
+#define TRUN1			0x00002000	/* Timer 1 Slave Enable Status		*/
+#define TRUN2			0x00004000	/* Timer 2 Slave Enable Status		*/
+#define TRUN3			0x00008000	/* Timer 3 Slave Enable Status		*/
+#define TIMIL4			0x00010000	/* Timer 4 Interrupt				*/
+#define TIMIL5			0x00020000	/* Timer 5 Interrupt				*/
+#define TIMIL6			0x00040000	/* Timer 6 Interrupt				*/
+#define TIMIL7			0x00080000	/* Timer 7 Interrupt				*/
+#define TOVF_ERR4		0x00100000	/* Timer 4 Counter Overflow			*/
+#define TOVF_ERR5		0x00200000	/* Timer 5 Counter Overflow			*/
+#define TOVF_ERR6		0x00400000	/* Timer 6 Counter Overflow			*/
+#define TOVF_ERR7		0x00800000	/* Timer 7 Counter Overflow			*/
+#define TRUN4			0x10000000	/* Timer 4 Slave Enable Status		*/
+#define TRUN5			0x20000000	/* Timer 5 Slave Enable Status		*/
+#define TRUN6			0x40000000	/* Timer 6 Slave Enable Status		*/
+#define TRUN7			0x80000000	/* Timer 7 Slave Enable Status		*/
+
+/* Alternate Deprecated Macros Provided For Backwards Code Compatibility */
+#define TOVL_ERR0 TOVF_ERR0
+#define TOVL_ERR1 TOVF_ERR1
+#define TOVL_ERR2 TOVF_ERR2
+#define TOVL_ERR3 TOVF_ERR3
+#define TOVL_ERR4 TOVF_ERR4
+#define TOVL_ERR5 TOVF_ERR5
+#define TOVL_ERR6 TOVF_ERR6
+#define TOVL_ERR7 TOVF_ERR7
+
+/* TIMERx_CONFIG Masks													*/
+#define PWM_OUT			0x0001	/* Pulse-Width Modulation Output Mode	*/
+#define WDTH_CAP		0x0002	/* Width Capture Input Mode				*/
+#define EXT_CLK			0x0003	/* External Clock Mode					*/
+#define PULSE_HI		0x0004	/* Action Pulse (Positive/Negative*)	*/
+#define PERIOD_CNT		0x0008	/* Period Count							*/
+#define IRQ_ENA			0x0010	/* Interrupt Request Enable				*/
+#define TIN_SEL			0x0020	/* Timer Input Select					*/
+#define OUT_DIS			0x0040	/* Output Pad Disable					*/
+#define CLK_SEL			0x0080	/* Timer Clock Select					*/
+#define TOGGLE_HI		0x0100	/* PWM_OUT PULSE_HI Toggle Mode			*/
+#define EMU_RUN			0x0200	/* Emulation Behavior Select			*/
+#define ERR_TYP			0xC000	/* Error Type							*/
+
+/* *********************  ASYNCHRONOUS MEMORY CONTROLLER MASKS  *************************/
+/* EBIU_AMGCTL Masks																	*/
+#define AMCKEN			0x0001		/* Enable CLKOUT									*/
+#define	AMBEN_NONE		0x0000		/* All Banks Disabled								*/
+#define AMBEN_B0		0x0002		/* Enable Async Memory Bank 0 only					*/
+#define AMBEN_B0_B1		0x0004		/* Enable Async Memory Banks 0 & 1 only				*/
+#define AMBEN_B0_B1_B2	0x0006		/* Enable Async Memory Banks 0, 1, and 2			*/
+#define AMBEN_ALL		0x0008		/* Enable Async Memory Banks (all) 0, 1, 2, and 3	*/
+
+/* EBIU_AMBCTL0 Masks																	*/
+#define B0RDYEN			0x00000001  /* Bank 0 (B0) RDY Enable							*/
+#define B0RDYPOL		0x00000002  /* B0 RDY Active High								*/
+#define B0TT_1			0x00000004  /* B0 Transition Time (Read to Write) = 1 cycle		*/
+#define B0TT_2			0x00000008  /* B0 Transition Time (Read to Write) = 2 cycles	*/
+#define B0TT_3			0x0000000C  /* B0 Transition Time (Read to Write) = 3 cycles	*/
+#define B0TT_4			0x00000000  /* B0 Transition Time (Read to Write) = 4 cycles	*/
+#define B0ST_1			0x00000010  /* B0 Setup Time (AOE to Read/Write) = 1 cycle		*/
+#define B0ST_2			0x00000020  /* B0 Setup Time (AOE to Read/Write) = 2 cycles		*/
+#define B0ST_3			0x00000030  /* B0 Setup Time (AOE to Read/Write) = 3 cycles		*/
+#define B0ST_4			0x00000000  /* B0 Setup Time (AOE to Read/Write) = 4 cycles		*/
+#define B0HT_1			0x00000040  /* B0 Hold Time (~Read/Write to ~AOE) = 1 cycle		*/
+#define B0HT_2			0x00000080  /* B0 Hold Time (~Read/Write to ~AOE) = 2 cycles	*/
+#define B0HT_3			0x000000C0  /* B0 Hold Time (~Read/Write to ~AOE) = 3 cycles	*/
+#define B0HT_0			0x00000000  /* B0 Hold Time (~Read/Write to ~AOE) = 0 cycles	*/
+#define B0RAT_1			0x00000100  /* B0 Read Access Time = 1 cycle					*/
+#define B0RAT_2			0x00000200  /* B0 Read Access Time = 2 cycles					*/
+#define B0RAT_3			0x00000300  /* B0 Read Access Time = 3 cycles					*/
+#define B0RAT_4			0x00000400  /* B0 Read Access Time = 4 cycles					*/
+#define B0RAT_5			0x00000500  /* B0 Read Access Time = 5 cycles					*/
+#define B0RAT_6			0x00000600  /* B0 Read Access Time = 6 cycles					*/
+#define B0RAT_7			0x00000700  /* B0 Read Access Time = 7 cycles					*/
+#define B0RAT_8			0x00000800  /* B0 Read Access Time = 8 cycles					*/
+#define B0RAT_9			0x00000900  /* B0 Read Access Time = 9 cycles					*/
+#define B0RAT_10		0x00000A00  /* B0 Read Access Time = 10 cycles					*/
+#define B0RAT_11		0x00000B00  /* B0 Read Access Time = 11 cycles					*/
+#define B0RAT_12		0x00000C00  /* B0 Read Access Time = 12 cycles					*/
+#define B0RAT_13		0x00000D00  /* B0 Read Access Time = 13 cycles					*/
+#define B0RAT_14		0x00000E00  /* B0 Read Access Time = 14 cycles					*/
+#define B0RAT_15		0x00000F00  /* B0 Read Access Time = 15 cycles					*/
+#define B0WAT_1			0x00001000  /* B0 Write Access Time = 1 cycle					*/
+#define B0WAT_2			0x00002000  /* B0 Write Access Time = 2 cycles					*/
+#define B0WAT_3			0x00003000  /* B0 Write Access Time = 3 cycles					*/
+#define B0WAT_4			0x00004000  /* B0 Write Access Time = 4 cycles					*/
+#define B0WAT_5			0x00005000  /* B0 Write Access Time = 5 cycles					*/
+#define B0WAT_6			0x00006000  /* B0 Write Access Time = 6 cycles					*/
+#define B0WAT_7			0x00007000  /* B0 Write Access Time = 7 cycles					*/
+#define B0WAT_8			0x00008000  /* B0 Write Access Time = 8 cycles					*/
+#define B0WAT_9			0x00009000  /* B0 Write Access Time = 9 cycles					*/
+#define B0WAT_10		0x0000A000  /* B0 Write Access Time = 10 cycles					*/
+#define B0WAT_11		0x0000B000  /* B0 Write Access Time = 11 cycles					*/
+#define B0WAT_12		0x0000C000  /* B0 Write Access Time = 12 cycles					*/
+#define B0WAT_13		0x0000D000  /* B0 Write Access Time = 13 cycles					*/
+#define B0WAT_14		0x0000E000  /* B0 Write Access Time = 14 cycles					*/
+#define B0WAT_15		0x0000F000  /* B0 Write Access Time = 15 cycles					*/
+
+#define B1RDYEN			0x00010000  /* Bank 1 (B1) RDY Enable                       	*/
+#define B1RDYPOL		0x00020000  /* B1 RDY Active High                           	*/
+#define B1TT_1			0x00040000  /* B1 Transition Time (Read to Write) = 1 cycle 	*/
+#define B1TT_2			0x00080000  /* B1 Transition Time (Read to Write) = 2 cycles	*/
+#define B1TT_3			0x000C0000  /* B1 Transition Time (Read to Write) = 3 cycles	*/
+#define B1TT_4			0x00000000  /* B1 Transition Time (Read to Write) = 4 cycles	*/
+#define B1ST_1			0x00100000  /* B1 Setup Time (AOE to Read/Write) = 1 cycle  	*/
+#define B1ST_2			0x00200000  /* B1 Setup Time (AOE to Read/Write) = 2 cycles 	*/
+#define B1ST_3			0x00300000  /* B1 Setup Time (AOE to Read/Write) = 3 cycles 	*/
+#define B1ST_4			0x00000000  /* B1 Setup Time (AOE to Read/Write) = 4 cycles 	*/
+#define B1HT_1			0x00400000  /* B1 Hold Time (~Read/Write to ~AOE) = 1 cycle 	*/
+#define B1HT_2			0x00800000  /* B1 Hold Time (~Read/Write to ~AOE) = 2 cycles	*/
+#define B1HT_3			0x00C00000  /* B1 Hold Time (~Read/Write to ~AOE) = 3 cycles	*/
+#define B1HT_0			0x00000000  /* B1 Hold Time (~Read/Write to ~AOE) = 0 cycles	*/
+#define B1RAT_1			0x01000000  /* B1 Read Access Time = 1 cycle					*/
+#define B1RAT_2			0x02000000  /* B1 Read Access Time = 2 cycles					*/
+#define B1RAT_3			0x03000000  /* B1 Read Access Time = 3 cycles					*/
+#define B1RAT_4			0x04000000  /* B1 Read Access Time = 4 cycles					*/
+#define B1RAT_5			0x05000000  /* B1 Read Access Time = 5 cycles					*/
+#define B1RAT_6			0x06000000  /* B1 Read Access Time = 6 cycles					*/
+#define B1RAT_7			0x07000000  /* B1 Read Access Time = 7 cycles					*/
+#define B1RAT_8			0x08000000  /* B1 Read Access Time = 8 cycles					*/
+#define B1RAT_9			0x09000000  /* B1 Read Access Time = 9 cycles					*/
+#define B1RAT_10		0x0A000000  /* B1 Read Access Time = 10 cycles					*/
+#define B1RAT_11		0x0B000000  /* B1 Read Access Time = 11 cycles					*/
+#define B1RAT_12		0x0C000000  /* B1 Read Access Time = 12 cycles					*/
+#define B1RAT_13		0x0D000000  /* B1 Read Access Time = 13 cycles					*/
+#define B1RAT_14		0x0E000000  /* B1 Read Access Time = 14 cycles					*/
+#define B1RAT_15		0x0F000000  /* B1 Read Access Time = 15 cycles					*/
+#define B1WAT_1			0x10000000  /* B1 Write Access Time = 1 cycle					*/
+#define B1WAT_2			0x20000000  /* B1 Write Access Time = 2 cycles					*/
+#define B1WAT_3			0x30000000  /* B1 Write Access Time = 3 cycles					*/
+#define B1WAT_4			0x40000000  /* B1 Write Access Time = 4 cycles					*/
+#define B1WAT_5			0x50000000  /* B1 Write Access Time = 5 cycles					*/
+#define B1WAT_6			0x60000000  /* B1 Write Access Time = 6 cycles					*/
+#define B1WAT_7			0x70000000  /* B1 Write Access Time = 7 cycles					*/
+#define B1WAT_8			0x80000000  /* B1 Write Access Time = 8 cycles					*/
+#define B1WAT_9			0x90000000  /* B1 Write Access Time = 9 cycles					*/
+#define B1WAT_10		0xA0000000  /* B1 Write Access Time = 10 cycles					*/
+#define B1WAT_11		0xB0000000  /* B1 Write Access Time = 11 cycles					*/
+#define B1WAT_12		0xC0000000  /* B1 Write Access Time = 12 cycles					*/
+#define B1WAT_13		0xD0000000  /* B1 Write Access Time = 13 cycles					*/
+#define B1WAT_14		0xE0000000  /* B1 Write Access Time = 14 cycles					*/
+#define B1WAT_15		0xF0000000  /* B1 Write Access Time = 15 cycles					*/
+
+/* EBIU_AMBCTL1 Masks																	*/
+#define B2RDYEN			0x00000001  /* Bank 2 (B2) RDY Enable							*/
+#define B2RDYPOL		0x00000002  /* B2 RDY Active High								*/
+#define B2TT_1			0x00000004  /* B2 Transition Time (Read to Write) = 1 cycle		*/
+#define B2TT_2			0x00000008  /* B2 Transition Time (Read to Write) = 2 cycles	*/
+#define B2TT_3			0x0000000C  /* B2 Transition Time (Read to Write) = 3 cycles	*/
+#define B2TT_4			0x00000000  /* B2 Transition Time (Read to Write) = 4 cycles	*/
+#define B2ST_1			0x00000010  /* B2 Setup Time (AOE to Read/Write) = 1 cycle		*/
+#define B2ST_2			0x00000020  /* B2 Setup Time (AOE to Read/Write) = 2 cycles		*/
+#define B2ST_3			0x00000030  /* B2 Setup Time (AOE to Read/Write) = 3 cycles		*/
+#define B2ST_4			0x00000000  /* B2 Setup Time (AOE to Read/Write) = 4 cycles		*/
+#define B2HT_1			0x00000040  /* B2 Hold Time (~Read/Write to ~AOE) = 1 cycle		*/
+#define B2HT_2			0x00000080  /* B2 Hold Time (~Read/Write to ~AOE) = 2 cycles	*/
+#define B2HT_3			0x000000C0  /* B2 Hold Time (~Read/Write to ~AOE) = 3 cycles	*/
+#define B2HT_0			0x00000000  /* B2 Hold Time (~Read/Write to ~AOE) = 0 cycles	*/
+#define B2RAT_1			0x00000100  /* B2 Read Access Time = 1 cycle					*/
+#define B2RAT_2			0x00000200  /* B2 Read Access Time = 2 cycles					*/
+#define B2RAT_3			0x00000300  /* B2 Read Access Time = 3 cycles					*/
+#define B2RAT_4			0x00000400  /* B2 Read Access Time = 4 cycles					*/
+#define B2RAT_5			0x00000500  /* B2 Read Access Time = 5 cycles					*/
+#define B2RAT_6			0x00000600  /* B2 Read Access Time = 6 cycles					*/
+#define B2RAT_7			0x00000700  /* B2 Read Access Time = 7 cycles					*/
+#define B2RAT_8			0x00000800  /* B2 Read Access Time = 8 cycles					*/
+#define B2RAT_9			0x00000900  /* B2 Read Access Time = 9 cycles					*/
+#define B2RAT_10		0x00000A00  /* B2 Read Access Time = 10 cycles					*/
+#define B2RAT_11		0x00000B00  /* B2 Read Access Time = 11 cycles					*/
+#define B2RAT_12		0x00000C00  /* B2 Read Access Time = 12 cycles					*/
+#define B2RAT_13		0x00000D00  /* B2 Read Access Time = 13 cycles					*/
+#define B2RAT_14		0x00000E00  /* B2 Read Access Time = 14 cycles					*/
+#define B2RAT_15		0x00000F00  /* B2 Read Access Time = 15 cycles					*/
+#define B2WAT_1			0x00001000  /* B2 Write Access Time = 1 cycle					*/
+#define B2WAT_2			0x00002000  /* B2 Write Access Time = 2 cycles					*/
+#define B2WAT_3			0x00003000  /* B2 Write Access Time = 3 cycles					*/
+#define B2WAT_4			0x00004000  /* B2 Write Access Time = 4 cycles					*/
+#define B2WAT_5			0x00005000  /* B2 Write Access Time = 5 cycles					*/
+#define B2WAT_6			0x00006000  /* B2 Write Access Time = 6 cycles					*/
+#define B2WAT_7			0x00007000  /* B2 Write Access Time = 7 cycles					*/
+#define B2WAT_8			0x00008000  /* B2 Write Access Time = 8 cycles					*/
+#define B2WAT_9			0x00009000  /* B2 Write Access Time = 9 cycles					*/
+#define B2WAT_10		0x0000A000  /* B2 Write Access Time = 10 cycles					*/
+#define B2WAT_11		0x0000B000  /* B2 Write Access Time = 11 cycles					*/
+#define B2WAT_12		0x0000C000  /* B2 Write Access Time = 12 cycles					*/
+#define B2WAT_13		0x0000D000  /* B2 Write Access Time = 13 cycles					*/
+#define B2WAT_14		0x0000E000  /* B2 Write Access Time = 14 cycles					*/
+#define B2WAT_15		0x0000F000  /* B2 Write Access Time = 15 cycles					*/
+
+#define B3RDYEN			0x00010000  /* Bank 3 (B3) RDY Enable							*/
+#define B3RDYPOL		0x00020000  /* B3 RDY Active High								*/
+#define B3TT_1			0x00040000  /* B3 Transition Time (Read to Write) = 1 cycle		*/
+#define B3TT_2			0x00080000  /* B3 Transition Time (Read to Write) = 2 cycles	*/
+#define B3TT_3			0x000C0000  /* B3 Transition Time (Read to Write) = 3 cycles	*/
+#define B3TT_4			0x00000000  /* B3 Transition Time (Read to Write) = 4 cycles	*/
+#define B3ST_1			0x00100000  /* B3 Setup Time (AOE to Read/Write) = 1 cycle		*/
+#define B3ST_2			0x00200000  /* B3 Setup Time (AOE to Read/Write) = 2 cycles		*/
+#define B3ST_3			0x00300000  /* B3 Setup Time (AOE to Read/Write) = 3 cycles		*/
+#define B3ST_4			0x00000000  /* B3 Setup Time (AOE to Read/Write) = 4 cycles		*/
+#define B3HT_1			0x00400000  /* B3 Hold Time (~Read/Write to ~AOE) = 1 cycle		*/
+#define B3HT_2			0x00800000  /* B3 Hold Time (~Read/Write to ~AOE) = 2 cycles	*/
+#define B3HT_3			0x00C00000  /* B3 Hold Time (~Read/Write to ~AOE) = 3 cycles	*/
+#define B3HT_0			0x00000000  /* B3 Hold Time (~Read/Write to ~AOE) = 0 cycles	*/
+#define B3RAT_1			0x01000000  /* B3 Read Access Time = 1 cycle					*/
+#define B3RAT_2			0x02000000  /* B3 Read Access Time = 2 cycles					*/
+#define B3RAT_3			0x03000000  /* B3 Read Access Time = 3 cycles					*/
+#define B3RAT_4			0x04000000  /* B3 Read Access Time = 4 cycles					*/
+#define B3RAT_5			0x05000000  /* B3 Read Access Time = 5 cycles					*/
+#define B3RAT_6			0x06000000  /* B3 Read Access Time = 6 cycles					*/
+#define B3RAT_7			0x07000000  /* B3 Read Access Time = 7 cycles					*/
+#define B3RAT_8			0x08000000  /* B3 Read Access Time = 8 cycles					*/
+#define B3RAT_9			0x09000000  /* B3 Read Access Time = 9 cycles					*/
+#define B3RAT_10		0x0A000000  /* B3 Read Access Time = 10 cycles					*/
+#define B3RAT_11		0x0B000000  /* B3 Read Access Time = 11 cycles					*/
+#define B3RAT_12		0x0C000000  /* B3 Read Access Time = 12 cycles					*/
+#define B3RAT_13		0x0D000000  /* B3 Read Access Time = 13 cycles					*/
+#define B3RAT_14		0x0E000000  /* B3 Read Access Time = 14 cycles					*/
+#define B3RAT_15		0x0F000000  /* B3 Read Access Time = 15 cycles					*/
+#define B3WAT_1			0x10000000  /* B3 Write Access Time = 1 cycle					*/
+#define B3WAT_2			0x20000000  /* B3 Write Access Time = 2 cycles					*/
+#define B3WAT_3			0x30000000  /* B3 Write Access Time = 3 cycles					*/
+#define B3WAT_4			0x40000000  /* B3 Write Access Time = 4 cycles					*/
+#define B3WAT_5			0x50000000  /* B3 Write Access Time = 5 cycles					*/
+#define B3WAT_6			0x60000000  /* B3 Write Access Time = 6 cycles					*/
+#define B3WAT_7			0x70000000  /* B3 Write Access Time = 7 cycles					*/
+#define B3WAT_8			0x80000000  /* B3 Write Access Time = 8 cycles					*/
+#define B3WAT_9			0x90000000  /* B3 Write Access Time = 9 cycles					*/
+#define B3WAT_10		0xA0000000  /* B3 Write Access Time = 10 cycles					*/
+#define B3WAT_11		0xB0000000  /* B3 Write Access Time = 11 cycles					*/
+#define B3WAT_12		0xC0000000  /* B3 Write Access Time = 12 cycles					*/
+#define B3WAT_13		0xD0000000  /* B3 Write Access Time = 13 cycles					*/
+#define B3WAT_14		0xE0000000  /* B3 Write Access Time = 14 cycles					*/
+#define B3WAT_15		0xF0000000  /* B3 Write Access Time = 15 cycles					*/
+
+
+/* **********************  SDRAM CONTROLLER MASKS  **********************************************/
+/* EBIU_SDGCTL Masks																			*/
+#define SCTLE			0x00000001	/* Enable SDRAM Signals										*/
+#define CL_2			0x00000008	/* SDRAM CAS Latency = 2 cycles								*/
+#define CL_3			0x0000000C	/* SDRAM CAS Latency = 3 cycles								*/
+#define PASR_ALL		0x00000000	/* All 4 SDRAM Banks Refreshed In Self-Refresh				*/
+#define PASR_B0_B1		0x00000010	/* SDRAM Banks 0 and 1 Are Refreshed In Self-Refresh		*/
+#define PASR_B0			0x00000020	/* Only SDRAM Bank 0 Is Refreshed In Self-Refresh			*/
+#define TRAS_1			0x00000040	/* SDRAM tRAS = 1 cycle										*/
+#define TRAS_2			0x00000080	/* SDRAM tRAS = 2 cycles									*/
+#define TRAS_3			0x000000C0	/* SDRAM tRAS = 3 cycles									*/
+#define TRAS_4			0x00000100	/* SDRAM tRAS = 4 cycles									*/
+#define TRAS_5			0x00000140	/* SDRAM tRAS = 5 cycles									*/
+#define TRAS_6			0x00000180	/* SDRAM tRAS = 6 cycles									*/
+#define TRAS_7			0x000001C0	/* SDRAM tRAS = 7 cycles									*/
+#define TRAS_8			0x00000200	/* SDRAM tRAS = 8 cycles									*/
+#define TRAS_9			0x00000240	/* SDRAM tRAS = 9 cycles									*/
+#define TRAS_10			0x00000280	/* SDRAM tRAS = 10 cycles									*/
+#define TRAS_11			0x000002C0	/* SDRAM tRAS = 11 cycles									*/
+#define TRAS_12			0x00000300	/* SDRAM tRAS = 12 cycles									*/
+#define TRAS_13			0x00000340	/* SDRAM tRAS = 13 cycles									*/
+#define TRAS_14			0x00000380	/* SDRAM tRAS = 14 cycles									*/
+#define TRAS_15			0x000003C0	/* SDRAM tRAS = 15 cycles									*/
+#define TRP_1			0x00000800	/* SDRAM tRP = 1 cycle										*/
+#define TRP_2			0x00001000	/* SDRAM tRP = 2 cycles										*/
+#define TRP_3			0x00001800	/* SDRAM tRP = 3 cycles										*/
+#define TRP_4			0x00002000	/* SDRAM tRP = 4 cycles										*/
+#define TRP_5			0x00002800	/* SDRAM tRP = 5 cycles										*/
+#define TRP_6			0x00003000	/* SDRAM tRP = 6 cycles										*/
+#define TRP_7			0x00003800	/* SDRAM tRP = 7 cycles										*/
+#define TRCD_1			0x00008000	/* SDRAM tRCD = 1 cycle										*/
+#define TRCD_2			0x00010000	/* SDRAM tRCD = 2 cycles									*/
+#define TRCD_3			0x00018000	/* SDRAM tRCD = 3 cycles									*/
+#define TRCD_4			0x00020000	/* SDRAM tRCD = 4 cycles									*/
+#define TRCD_5			0x00028000	/* SDRAM tRCD = 5 cycles									*/
+#define TRCD_6			0x00030000	/* SDRAM tRCD = 6 cycles									*/
+#define TRCD_7			0x00038000	/* SDRAM tRCD = 7 cycles									*/
+#define TWR_1			0x00080000	/* SDRAM tWR = 1 cycle										*/
+#define TWR_2			0x00100000	/* SDRAM tWR = 2 cycles										*/
+#define TWR_3			0x00180000	/* SDRAM tWR = 3 cycles										*/
+#define PUPSD			0x00200000	/* Power-Up Start Delay (15 SCLK Cycles Delay)				*/
+#define PSM				0x00400000	/* Power-Up Sequence (Mode Register Before/After* Refresh)	*/
+#define PSS				0x00800000	/* Enable Power-Up Sequence on Next SDRAM Access			*/
+#define SRFS			0x01000000	/* Enable SDRAM Self-Refresh Mode							*/
+#define EBUFE			0x02000000	/* Enable External Buffering Timing							*/
+#define FBBRW			0x04000000	/* Enable Fast Back-To-Back Read To Write					*/
+#define EMREN			0x10000000	/* Extended Mode Register Enable							*/
+#define TCSR			0x20000000	/* Temp-Compensated Self-Refresh Value (85/45* Deg C)		*/
+#define CDDBG			0x40000000	/* Tristate SDRAM Controls During Bus Grant					*/
+
+/* EBIU_SDBCTL Masks																		*/
+#define EBE				0x0001		/* Enable SDRAM External Bank							*/
+#define EBSZ_16			0x0000		/* SDRAM External Bank Size = 16MB	*/
+#define EBSZ_32			0x0002		/* SDRAM External Bank Size = 32MB	*/
+#define EBSZ_64			0x0004		/* SDRAM External Bank Size = 64MB	*/
+#define EBSZ_128		0x0006		/* SDRAM External Bank Size = 128MB		*/
+#define EBSZ_256		0x0008		/* SDRAM External Bank Size = 256MB 	*/
+#define EBSZ_512		0x000A		/* SDRAM External Bank Size = 512MB		*/
+#define EBCAW_8			0x0000		/* SDRAM External Bank Column Address Width = 8 Bits	*/
+#define EBCAW_9			0x0010		/* SDRAM External Bank Column Address Width = 9 Bits	*/
+#define EBCAW_10		0x0020		/* SDRAM External Bank Column Address Width = 10 Bits	*/
+#define EBCAW_11		0x0030		/* SDRAM External Bank Column Address Width = 11 Bits	*/
+
+/* EBIU_SDSTAT Masks														*/
+#define SDCI			0x0001		/* SDRAM Controller Idle 				*/
+#define SDSRA			0x0002		/* SDRAM Self-Refresh Active			*/
+#define SDPUA			0x0004		/* SDRAM Power-Up Active 				*/
+#define SDRS			0x0008		/* SDRAM Will Power-Up On Next Access	*/
+#define SDEASE			0x0010		/* SDRAM EAB Sticky Error Status		*/
+#define BGSTAT			0x0020		/* Bus Grant Status						*/
+
+
+/* **************************  DMA CONTROLLER MASKS  ********************************/
+
+/* DMAx_PERIPHERAL_MAP, MDMA_yy_PERIPHERAL_MAP Masks								*/
+#define CTYPE			0x0040	/* DMA Channel Type Indicator (Memory/Peripheral*)	*/
+#define PMAP			0xF000	/* Peripheral Mapped To This Channel				*/
+#define PMAP_PPI		0x0000	/* 		PPI Port DMA								*/
+#define	PMAP_EMACRX		0x1000	/* 		Ethernet Receive DMA						*/
+#define PMAP_EMACTX		0x2000	/* 		Ethernet Transmit DMA						*/
+#define PMAP_SPORT0RX	0x3000	/* 		SPORT0 Receive DMA							*/
+#define PMAP_SPORT0TX	0x4000	/* 		SPORT0 Transmit DMA							*/
+#define PMAP_SPORT1RX	0x5000	/* 		SPORT1 Receive DMA							*/
+#define PMAP_SPORT1TX	0x6000	/* 		SPORT1 Transmit DMA							*/
+#define PMAP_SPI		0x7000	/* 		SPI Port DMA								*/
+#define PMAP_UART0RX	0x8000	/* 		UART0 Port Receive DMA						*/
+#define PMAP_UART0TX	0x9000	/* 		UART0 Port Transmit DMA						*/
+#define	PMAP_UART1RX	0xA000	/* 		UART1 Port Receive DMA						*/
+#define	PMAP_UART1TX	0xB000	/* 		UART1 Port Transmit DMA						*/
+
+/*  ************  PARALLEL PERIPHERAL INTERFACE (PPI) MASKS *************/
+/*  PPI_CONTROL Masks													*/
+#define PORT_EN			0x0001		/* PPI Port Enable					*/
+#define PORT_DIR		0x0002		/* PPI Port Direction				*/
+#define XFR_TYPE		0x000C		/* PPI Transfer Type				*/
+#define PORT_CFG		0x0030		/* PPI Port Configuration			*/
+#define FLD_SEL			0x0040		/* PPI Active Field Select			*/
+#define PACK_EN			0x0080		/* PPI Packing Mode					*/
+#define DMA32			0x0100		/* PPI 32-bit DMA Enable			*/
+#define SKIP_EN			0x0200		/* PPI Skip Element Enable			*/
+#define SKIP_EO			0x0400		/* PPI Skip Even/Odd Elements		*/
+#define DLEN_8			0x0000		/* Data Length = 8 Bits				*/
+#define DLEN_10			0x0800		/* Data Length = 10 Bits			*/
+#define DLEN_11			0x1000		/* Data Length = 11 Bits			*/
+#define DLEN_12			0x1800		/* Data Length = 12 Bits			*/
+#define DLEN_13			0x2000		/* Data Length = 13 Bits			*/
+#define DLEN_14			0x2800		/* Data Length = 14 Bits			*/
+#define DLEN_15			0x3000		/* Data Length = 15 Bits			*/
+#define DLEN_16			0x3800		/* Data Length = 16 Bits			*/
+#define DLENGTH			0x3800		/* PPI Data Length  */
+#define POLC			0x4000		/* PPI Clock Polarity				*/
+#define POLS			0x8000		/* PPI Frame Sync Polarity			*/
+
+/* PPI_STATUS Masks														*/
+#define FLD				0x0400		/* Field Indicator					*/
+#define FT_ERR			0x0800		/* Frame Track Error				*/
+#define OVR				0x1000		/* FIFO Overflow Error				*/
+#define UNDR			0x2000		/* FIFO Underrun Error				*/
+#define ERR_DET			0x4000		/* Error Detected Indicator			*/
+#define ERR_NCOR		0x8000		/* Error Not Corrected Indicator	*/
+
+
+/*  ********************  TWO-WIRE INTERFACE (TWI) MASKS  ***********************/
+/* TWI_CLKDIV Macros (Use: *pTWI_CLKDIV = CLKLOW(x)|CLKHI(y);  )				*/
+#define	CLKLOW(x)	((x) & 0xFF)		/* Periods Clock Is Held Low			*/
+#define CLKHI(y)	(((y)&0xFF)<<0x8)	/* Periods Before New Clock Low			*/
+
+/* TWI_PRESCALE Masks															*/
+#define	PRESCALE	0x007F		/* SCLKs Per Internal Time Reference (10MHz)	*/
+#define	TWI_ENA		0x0080		/* TWI Enable									*/
+#define	SCCB		0x0200		/* SCCB Compatibility Enable					*/
+
+/* TWI_SLAVE_CTL Masks															*/
+#define	SEN			0x0001		/* Slave Enable									*/
+#define	SADD_LEN	0x0002		/* Slave Address Length							*/
+#define	STDVAL		0x0004		/* Slave Transmit Data Valid					*/
+#define	NAK			0x0008		/* NAK/ACK* Generated At Conclusion Of Transfer */
+#define	GEN			0x0010		/* General Call Adrress Matching Enabled		*/
+
+/* TWI_SLAVE_STAT Masks															*/
+#define	SDIR		0x0001		/* Slave Transfer Direction (Transmit/Receive*)	*/
+#define GCALL		0x0002		/* General Call Indicator						*/
+
+/* TWI_MASTER_CTL Masks													*/
+#define	MEN			0x0001		/* Master Mode Enable						*/
+#define	MADD_LEN	0x0002		/* Master Address Length					*/
+#define	MDIR		0x0004		/* Master Transmit Direction (RX/TX*)		*/
+#define	FAST		0x0008		/* Use Fast Mode Timing Specs				*/
+#define	STOP		0x0010		/* Issue Stop Condition						*/
+#define	RSTART		0x0020		/* Repeat Start or Stop* At End Of Transfer	*/
+#define	DCNT		0x3FC0		/* Data Bytes To Transfer					*/
+#define	SDAOVR		0x4000		/* Serial Data Override						*/
+#define	SCLOVR		0x8000		/* Serial Clock Override					*/
+
+/* TWI_MASTER_STAT Masks														*/
+#define	MPROG		0x0001		/* Master Transfer In Progress					*/
+#define	LOSTARB		0x0002		/* Lost Arbitration Indicator (Xfer Aborted)	*/
+#define	ANAK		0x0004		/* Address Not Acknowledged						*/
+#define	DNAK		0x0008		/* Data Not Acknowledged						*/
+#define	BUFRDERR	0x0010		/* Buffer Read Error							*/
+#define	BUFWRERR	0x0020		/* Buffer Write Error							*/
+#define	SDASEN		0x0040		/* Serial Data Sense							*/
+#define	SCLSEN		0x0080		/* Serial Clock Sense							*/
+#define	BUSBUSY		0x0100		/* Bus Busy Indicator							*/
+
+/* TWI_INT_SRC and TWI_INT_ENABLE Masks						*/
+#define	SINIT		0x0001		/* Slave Transfer Initiated	*/
+#define	SCOMP		0x0002		/* Slave Transfer Complete	*/
+#define	SERR		0x0004		/* Slave Transfer Error		*/
+#define	SOVF		0x0008		/* Slave Overflow			*/
+#define	MCOMP		0x0010		/* Master Transfer Complete	*/
+#define	MERR		0x0020		/* Master Transfer Error	*/
+#define	XMTSERV		0x0040		/* Transmit FIFO Service	*/
+#define	RCVSERV		0x0080		/* Receive FIFO Service		*/
+
+/* TWI_FIFO_CTRL Masks												*/
+#define	XMTFLUSH	0x0001		/* Transmit Buffer Flush			*/
+#define	RCVFLUSH	0x0002		/* Receive Buffer Flush				*/
+#define	XMTINTLEN	0x0004		/* Transmit Buffer Interrupt Length	*/
+#define	RCVINTLEN	0x0008		/* Receive Buffer Interrupt Length	*/
+
+/* TWI_FIFO_STAT Masks															*/
+#define	XMTSTAT		0x0003		/* Transmit FIFO Status							*/
+#define	XMT_EMPTY	0x0000		/* 		Transmit FIFO Empty						*/
+#define	XMT_HALF	0x0001		/* 		Transmit FIFO Has 1 Byte To Write		*/
+#define	XMT_FULL	0x0003		/* 		Transmit FIFO Full (2 Bytes To Write)	*/
+
+#define	RCVSTAT		0x000C		/* Receive FIFO Status							*/
+#define	RCV_EMPTY	0x0000		/* 		Receive FIFO Empty						*/
+#define	RCV_HALF	0x0004		/* 		Receive FIFO Has 1 Byte To Read			*/
+#define	RCV_FULL	0x000C		/* 		Receive FIFO Full (2 Bytes To Read)		*/
+
+
+/* Omit CAN masks from defBF534.h */
+
+/*  *******************  PIN CONTROL REGISTER MASKS  ************************/
+/* PORT_MUX Masks															*/
+#define	PJSE			0x0001			/* Port J SPI/SPORT Enable			*/
+#define	PJSE_SPORT		0x0000			/* 		Enable TFS0/DT0PRI			*/
+#define	PJSE_SPI		0x0001			/* 		Enable SPI_SSEL3:2			*/
+
+#define	PJCE(x)			(((x)&0x3)<<1)	/* Port J CAN/SPI/SPORT Enable		*/
+#define	PJCE_SPORT		0x0000			/* 		Enable DR0SEC/DT0SEC		*/
+#define	PJCE_CAN		0x0002			/* 		Enable CAN RX/TX			*/
+#define	PJCE_SPI		0x0004			/* 		Enable SPI_SSEL7			*/
+
+#define	PFDE			0x0008			/* Port F DMA Request Enable		*/
+#define	PFDE_UART		0x0000			/* 		Enable UART0 RX/TX			*/
+#define	PFDE_DMA		0x0008			/* 		Enable DMAR1:0				*/
+
+#define	PFTE			0x0010			/* Port F Timer Enable				*/
+#define	PFTE_UART		0x0000			/*		Enable UART1 RX/TX			*/
+#define	PFTE_TIMER		0x0010			/* 		Enable TMR7:6				*/
+
+#define	PFS6E			0x0020			/* Port F SPI SSEL 6 Enable			*/
+#define	PFS6E_TIMER		0x0000			/*		Enable TMR5					*/
+#define	PFS6E_SPI		0x0020			/* 		Enable SPI_SSEL6			*/
+
+#define	PFS5E			0x0040			/* Port F SPI SSEL 5 Enable			*/
+#define	PFS5E_TIMER		0x0000			/*		Enable TMR4					*/
+#define	PFS5E_SPI		0x0040			/* 		Enable SPI_SSEL5			*/
+
+#define	PFS4E			0x0080			/* Port F SPI SSEL 4 Enable			*/
+#define	PFS4E_TIMER		0x0000			/*		Enable TMR3					*/
+#define	PFS4E_SPI		0x0080			/* 		Enable SPI_SSEL4			*/
+
+#define	PFFE			0x0100			/* Port F PPI Frame Sync Enable		*/
+#define	PFFE_TIMER		0x0000			/* 		Enable TMR2					*/
+#define	PFFE_PPI		0x0100			/* 		Enable PPI FS3				*/
+
+#define	PGSE			0x0200			/* Port G SPORT1 Secondary Enable	*/
+#define	PGSE_PPI		0x0000			/* 		Enable PPI D9:8				*/
+#define	PGSE_SPORT		0x0200			/* 		Enable DR1SEC/DT1SEC		*/
+
+#define	PGRE			0x0400			/* Port G SPORT1 Receive Enable		*/
+#define	PGRE_PPI		0x0000			/* 		Enable PPI D12:10			*/
+#define	PGRE_SPORT		0x0400			/* 		Enable DR1PRI/RFS1/RSCLK1	*/
+
+#define	PGTE			0x0800			/* Port G SPORT1 Transmit Enable	*/
+#define	PGTE_PPI		0x0000			/* 		Enable PPI D15:13			*/
+#define	PGTE_SPORT		0x0800			/* 		Enable DT1PRI/TFS1/TSCLK1	*/
+
+
+/*  ******************  HANDSHAKE DMA (HDMA) MASKS  *********************/
+/* HDMAx_CTL Masks														*/
+#define	HMDMAEN		0x0001	/* Enable Handshake DMA 0/1					*/
+#define	REP			0x0002	/* HDMA Request Polarity					*/
+#define	UTE			0x0004	/* Urgency Threshold Enable					*/
+#define	OIE			0x0010	/* Overflow Interrupt Enable				*/
+#define	BDIE		0x0020	/* Block Done Interrupt Enable				*/
+#define	MBDI		0x0040	/* Mask Block Done IRQ If Pending ECNT		*/
+#define	DRQ			0x0300	/* HDMA Request Type						*/
+#define	DRQ_NONE	0x0000	/* 		No Request							*/
+#define	DRQ_SINGLE	0x0100	/* 		Channels Request Single				*/
+#define	DRQ_MULTI	0x0200	/* 		Channels Request Multi (Default)	*/
+#define	DRQ_URGENT	0x0300	/* 		Channels Request Multi Urgent		*/
+#define	RBC			0x1000	/* Reload BCNT With IBCNT					*/
+#define	PS			0x2000	/* HDMA Pin Status							*/
+#define	OI			0x4000	/* Overflow Interrupt Generated				*/
+#define	BDI			0x8000	/* Block Done Interrupt Generated			*/
+
+/* entry addresses of the user-callable Boot ROM functions */
+
+#define _BOOTROM_RESET 0xEF000000
+#define _BOOTROM_FINAL_INIT 0xEF000002
+#define _BOOTROM_DO_MEMORY_DMA 0xEF000006
+#define _BOOTROM_BOOT_DXE_FLASH 0xEF000008
+#define _BOOTROM_BOOT_DXE_SPI 0xEF00000A
+#define _BOOTROM_BOOT_DXE_TWI 0xEF00000C
+#define _BOOTROM_GET_DXE_ADDRESS_FLASH 0xEF000010
+#define _BOOTROM_GET_DXE_ADDRESS_SPI 0xEF000012
+#define _BOOTROM_GET_DXE_ADDRESS_TWI 0xEF000014
+
+/* Alternate Deprecated Macros Provided For Backwards Code Compatibility */
+#define	PGDE_UART   PFDE_UART
+#define	PGDE_DMA    PFDE_DMA
+#define	CKELOW		SCKELOW
+
+/* ==== end from defBF534.h ==== */
+
+/* HOST Port Registers */
+
+#define                     HOST_CONTROL  0xffc03400   /* HOST Control Register */
+#define                      HOST_STATUS  0xffc03404   /* HOST Status Register */
+#define                     HOST_TIMEOUT  0xffc03408   /* HOST Acknowledge Mode Timeout Register */
+
+/* Counter Registers */
+
+#define                       CNT_CONFIG  0xffc03500   /* Configuration Register */
+#define                        CNT_IMASK  0xffc03504   /* Interrupt Mask Register */
+#define                       CNT_STATUS  0xffc03508   /* Status Register */
+#define                      CNT_COMMAND  0xffc0350c   /* Command Register */
+#define                     CNT_DEBOUNCE  0xffc03510   /* Debounce Register */
+#define                      CNT_COUNTER  0xffc03514   /* Counter Register */
+#define                          CNT_MAX  0xffc03518   /* Maximal Count Register */
+#define                          CNT_MIN  0xffc0351c   /* Minimal Count Register */
+
+/* OTP/FUSE Registers */
+
+#define                      OTP_CONTROL  0xffc03600   /* OTP/Fuse Control Register */
+#define                          OTP_BEN  0xffc03604   /* OTP/Fuse Byte Enable */
+#define                       OTP_STATUS  0xffc03608   /* OTP/Fuse Status */
+#define                       OTP_TIMING  0xffc0360c   /* OTP/Fuse Access Timing */
+
+/* Security Registers */
+
+#define                    SECURE_SYSSWT  0xffc03620   /* Secure System Switches */
+#define                   SECURE_CONTROL  0xffc03624   /* Secure Control */
+#define                    SECURE_STATUS  0xffc03628   /* Secure Status */
+
+/* OTP Read/Write Data Buffer Registers */
+
+#define                        OTP_DATA0  0xffc03680   /* OTP/Fuse Data (OTP_DATA0-3) accesses the fuse read write buffer */
+#define                        OTP_DATA1  0xffc03684   /* OTP/Fuse Data (OTP_DATA0-3) accesses the fuse read write buffer */
+#define                        OTP_DATA2  0xffc03688   /* OTP/Fuse Data (OTP_DATA0-3) accesses the fuse read write buffer */
+#define                        OTP_DATA3  0xffc0368c   /* OTP/Fuse Data (OTP_DATA0-3) accesses the fuse read write buffer */
+
+/* NFC Registers */
+
+#define                          NFC_CTL  0xffc03700   /* NAND Control Register */
+#define                         NFC_STAT  0xffc03704   /* NAND Status Register */
+#define                      NFC_IRQSTAT  0xffc03708   /* NAND Interrupt Status Register */
+#define                      NFC_IRQMASK  0xffc0370c   /* NAND Interrupt Mask Register */
+#define                         NFC_ECC0  0xffc03710   /* NAND ECC Register 0 */
+#define                         NFC_ECC1  0xffc03714   /* NAND ECC Register 1 */
+#define                         NFC_ECC2  0xffc03718   /* NAND ECC Register 2 */
+#define                         NFC_ECC3  0xffc0371c   /* NAND ECC Register 3 */
+#define                        NFC_COUNT  0xffc03720   /* NAND ECC Count Register */
+#define                          NFC_RST  0xffc03724   /* NAND ECC Reset Register */
+#define                        NFC_PGCTL  0xffc03728   /* NAND Page Control Register */
+#define                         NFC_READ  0xffc0372c   /* NAND Read Data Register */
+#define                         NFC_ADDR  0xffc03740   /* NAND Address Register */
+#define                          NFC_CMD  0xffc03744   /* NAND Command Register */
+#define                      NFC_DATA_WR  0xffc03748   /* NAND Data Write Register */
+#define                      NFC_DATA_RD  0xffc0374c   /* NAND Data Read Register */
+
+/* ********************************************************** */
+/*     SINGLE BIT MACRO PAIRS (bit mask and negated one)      */
+/*     and MULTI BIT READ MACROS                              */
+/* ********************************************************** */
+
+/* Bit masks for HOST_CONTROL */
+
+#define                   HOST_CNTR_HOST_EN  0x1        /* Host Enable */
+#define                  HOST_CNTR_nHOST_EN  0x0
+#define                  HOST_CNTR_HOST_END  0x2        /* Host Endianess */
+#define                 HOST_CNTR_nHOST_END  0x0
+#define                 HOST_CNTR_DATA_SIZE  0x4        /* Data Size */
+#define                HOST_CNTR_nDATA_SIZE  0x0
+#define                  HOST_CNTR_HOST_RST  0x8        /* Host Reset */
+#define                 HOST_CNTR_nHOST_RST  0x0
+#define                  HOST_CNTR_HRDY_OVR  0x20       /* Host Ready Override */
+#define                 HOST_CNTR_nHRDY_OVR  0x0
+#define                  HOST_CNTR_INT_MODE  0x40       /* Interrupt Mode */
+#define                 HOST_CNTR_nINT_MODE  0x0
+#define                     HOST_CNTR_BT_EN  0x80       /* Bus Timeout Enable */
+#define                   HOST_CNTR_ nBT_EN  0x0
+#define                       HOST_CNTR_EHW  0x100      /* Enable Host Write */
+#define                      HOST_CNTR_nEHW  0x0
+#define                       HOST_CNTR_EHR  0x200      /* Enable Host Read */
+#define                      HOST_CNTR_nEHR  0x0
+#define                       HOST_CNTR_BDR  0x400      /* Burst DMA Requests */
+#define                      HOST_CNTR_nBDR  0x0
+
+/* Bit masks for HOST_STATUS */
+
+#define                     HOST_STAT_READY  0x1        /* DMA Ready */
+#define                    HOST_STAT_nREADY  0x0
+#define                  HOST_STAT_FIFOFULL  0x2        /* FIFO Full */
+#define                 HOST_STAT_nFIFOFULL  0x0
+#define                 HOST_STAT_FIFOEMPTY  0x4        /* FIFO Empty */
+#define                HOST_STAT_nFIFOEMPTY  0x0
+#define                  HOST_STAT_COMPLETE  0x8        /* DMA Complete */
+#define                 HOST_STAT_nCOMPLETE  0x0
+#define                      HOST_STAT_HSHK  0x10       /* Host Handshake */
+#define                     HOST_STAT_nHSHK  0x0
+#define                   HOST_STAT_TIMEOUT  0x20       /* Host Timeout */
+#define                  HOST_STAT_nTIMEOUT  0x0
+#define                      HOST_STAT_HIRQ  0x40       /* Host Interrupt Request */
+#define                     HOST_STAT_nHIRQ  0x0
+#define                HOST_STAT_ALLOW_CNFG  0x80       /* Allow New Configuration */
+#define               HOST_STAT_nALLOW_CNFG  0x0
+#define                   HOST_STAT_DMA_DIR  0x100      /* DMA Direction */
+#define                  HOST_STAT_nDMA_DIR  0x0
+#define                       HOST_STAT_BTE  0x200      /* Bus Timeout Enabled */
+#define                      HOST_STAT_nBTE  0x0
+#define               HOST_STAT_HOSTRD_DONE  0x8000     /* Host Read Completion Interrupt */
+#define              HOST_STAT_nHOSTRD_DONE  0x0
+
+/* Bit masks for HOST_TIMEOUT */
+
+#define             HOST_COUNT_TIMEOUT  0x7ff      /* Host Timeout count */
+
+/* Bit masks for SECURE_SYSSWT */
+
+#define                   EMUDABL  0x1        /* Emulation Disable. */
+#define                  nEMUDABL  0x0
+#define                   RSTDABL  0x2        /* Reset Disable */
+#define                  nRSTDABL  0x0
+#define                   L1IDABL  0x1c       /* L1 Instruction Memory Disable. */
+#define                  L1DADABL  0xe0       /* L1 Data Bank A Memory Disable. */
+#define                  L1DBDABL  0x700      /* L1 Data Bank B Memory Disable. */
+#define                   DMA0OVR  0x800      /* DMA0 Memory Access Override */
+#define                  nDMA0OVR  0x0
+#define                   DMA1OVR  0x1000     /* DMA1 Memory Access Override */
+#define                  nDMA1OVR  0x0
+#define                    EMUOVR  0x4000     /* Emulation Override */
+#define                   nEMUOVR  0x0
+#define                    OTPSEN  0x8000     /* OTP Secrets Enable. */
+#define                   nOTPSEN  0x0
+#define                    L2DABL  0x70000    /* L2 Memory Disable. */
+
+/* Bit masks for SECURE_CONTROL */
+
+#define                   SECURE0  0x1        /* SECURE 0 */
+#define                  nSECURE0  0x0
+#define                   SECURE1  0x2        /* SECURE 1 */
+#define                  nSECURE1  0x0
+#define                   SECURE2  0x4        /* SECURE 2 */
+#define                  nSECURE2  0x0
+#define                   SECURE3  0x8        /* SECURE 3 */
+#define                  nSECURE3  0x0
+
+/* Bit masks for SECURE_STATUS */
+
+#define                   SECMODE  0x3        /* Secured Mode Control State */
+#define                       NMI  0x4        /* Non Maskable Interrupt */
+#define                      nNMI  0x0
+#define                   AFVALID  0x8        /* Authentication Firmware Valid */
+#define                  nAFVALID  0x0
+#define                    AFEXIT  0x10       /* Authentication Firmware Exit */
+#define                   nAFEXIT  0x0
+#define                   SECSTAT  0xe0       /* Secure Status */
 
 #endif /* _DEF_BF522_H */
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf527/include/mach/defBF525.h linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf527/include/mach/defBF525.h
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf527/include/mach/defBF525.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf527/include/mach/defBF525.h	2011-03-14 21:20:32.000000000 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright 2007-2008 Analog Devices Inc.
+ * Copyright 2007-2010 Analog Devices Inc.
  *
  * Licensed under the ADI BSD license or the GPL-2 (or later)
  */
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf527/include/mach/defBF527.h linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf527/include/mach/defBF527.h
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf527/include/mach/defBF527.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf527/include/mach/defBF527.h	2011-03-14 21:20:32.000000000 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright 2007-2008 Analog Devices Inc.
+ * Copyright 2007-2010 Analog Devices Inc.
  *
  * Licensed under the ADI BSD license or the GPL-2 (or later)
  */
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf527/include/mach/defBF52x_base.h linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf527/include/mach/defBF52x_base.h
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf527/include/mach/defBF52x_base.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf527/include/mach/defBF52x_base.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,1506 +0,0 @@
-/*
- * Copyright 2007-2008 Analog Devices Inc.
- *
- * Licensed under the ADI BSD license or the GPL-2 (or later)
- */
-
-#ifndef _DEF_BF52X_H
-#define _DEF_BF52X_H
-
-
-/* ************************************************************** */
-/*   SYSTEM & MMR ADDRESS DEFINITIONS COMMON TO ALL ADSP-BF52x    */
-/* ************************************************************** */
-
-/* ==== begin from defBF534.h ==== */
-
-/* Clock and System Control	(0xFFC00000 - 0xFFC000FF)								*/
-#define PLL_CTL				0xFFC00000	/* PLL Control Register						*/
-#define PLL_DIV				0xFFC00004	/* PLL Divide Register						*/
-#define VR_CTL				0xFFC00008	/* Voltage Regulator Control Register		*/
-#define PLL_STAT			0xFFC0000C	/* PLL Status Register						*/
-#define PLL_LOCKCNT			0xFFC00010	/* PLL Lock Count Register					*/
-#define CHIPID        0xFFC00014  /* Device ID Register */
-
-
-/* System Interrupt Controller (0xFFC00100 - 0xFFC001FF)							*/
-#define SWRST				0xFFC00100	/* Software Reset Register					*/
-#define SYSCR				0xFFC00104	/* System Configuration Register			*/
-#define SIC_RVECT			0xFFC00108	/* Interrupt Reset Vector Address Register	*/
-
-#define SIC_IMASK0			0xFFC0010C	/* Interrupt Mask Register					*/
-#define SIC_IAR0			0xFFC00110	/* Interrupt Assignment Register 0			*/
-#define SIC_IAR1			0xFFC00114	/* Interrupt Assignment Register 1			*/
-#define SIC_IAR2			0xFFC00118	/* Interrupt Assignment Register 2			*/
-#define SIC_IAR3			0xFFC0011C	/* Interrupt Assignment Register 3			*/
-#define SIC_ISR0				0xFFC00120	/* Interrupt Status Register				*/
-#define SIC_IWR0				0xFFC00124	/* Interrupt Wakeup Register				*/
-
-/* SIC Additions to ADSP-BF52x (0xFFC0014C - 0xFFC00162) */
-#define SIC_IMASK1                      0xFFC0014C     /* Interrupt Mask register of SIC2 */
-#define SIC_IAR4                        0xFFC00150     /* Interrupt Assignment register4 */
-#define SIC_IAR5                        0xFFC00154     /* Interrupt Assignment register5 */
-#define SIC_IAR6                        0xFFC00158     /* Interrupt Assignment register6 */
-#define SIC_IAR7                        0xFFC0015C     /* Interrupt Assignment register7 */
-#define SIC_ISR1                        0xFFC00160     /* Interrupt Statur register */
-#define SIC_IWR1                        0xFFC00164     /* Interrupt Wakeup register */
-
-
-/* Watchdog Timer			(0xFFC00200 - 0xFFC002FF)								*/
-#define WDOG_CTL			0xFFC00200	/* Watchdog Control Register				*/
-#define WDOG_CNT			0xFFC00204	/* Watchdog Count Register					*/
-#define WDOG_STAT			0xFFC00208	/* Watchdog Status Register					*/
-
-
-/* Real Time Clock		(0xFFC00300 - 0xFFC003FF)									*/
-#define RTC_STAT			0xFFC00300	/* RTC Status Register						*/
-#define RTC_ICTL			0xFFC00304	/* RTC Interrupt Control Register			*/
-#define RTC_ISTAT			0xFFC00308	/* RTC Interrupt Status Register			*/
-#define RTC_SWCNT			0xFFC0030C	/* RTC Stopwatch Count Register				*/
-#define RTC_ALARM			0xFFC00310	/* RTC Alarm Time Register					*/
-#define RTC_FAST			0xFFC00314	/* RTC Prescaler Enable Register			*/
-#define RTC_PREN			0xFFC00314	/* RTC Prescaler Enable Alternate Macro		*/
-
-
-/* UART0 Controller		(0xFFC00400 - 0xFFC004FF)									*/
-#define UART0_THR			0xFFC00400	/* Transmit Holding register				*/
-#define UART0_RBR			0xFFC00400	/* Receive Buffer register					*/
-#define UART0_DLL			0xFFC00400	/* Divisor Latch (Low-Byte)					*/
-#define UART0_IER			0xFFC00404	/* Interrupt Enable Register				*/
-#define UART0_DLH			0xFFC00404	/* Divisor Latch (High-Byte)				*/
-#define UART0_IIR			0xFFC00408	/* Interrupt Identification Register		*/
-#define UART0_LCR			0xFFC0040C	/* Line Control Register					*/
-#define UART0_MCR			0xFFC00410	/* Modem Control Register					*/
-#define UART0_LSR			0xFFC00414	/* Line Status Register						*/
-#define UART0_MSR			0xFFC00418	/* Modem Status Register					*/
-#define UART0_SCR			0xFFC0041C	/* SCR Scratch Register						*/
-#define UART0_GCTL			0xFFC00424	/* Global Control Register					*/
-
-
-/* SPI Controller			(0xFFC00500 - 0xFFC005FF)								*/
-#define SPI0_REGBASE			0xFFC00500
-#define SPI_CTL				0xFFC00500	/* SPI Control Register						*/
-#define SPI_FLG				0xFFC00504	/* SPI Flag register						*/
-#define SPI_STAT			0xFFC00508	/* SPI Status register						*/
-#define SPI_TDBR			0xFFC0050C	/* SPI Transmit Data Buffer Register		*/
-#define SPI_RDBR			0xFFC00510	/* SPI Receive Data Buffer Register			*/
-#define SPI_BAUD			0xFFC00514	/* SPI Baud rate Register					*/
-#define SPI_SHADOW			0xFFC00518	/* SPI_RDBR Shadow Register					*/
-
-
-/* TIMER0-7 Registers		(0xFFC00600 - 0xFFC006FF)								*/
-#define TIMER0_CONFIG		0xFFC00600	/* Timer 0 Configuration Register			*/
-#define TIMER0_COUNTER		0xFFC00604	/* Timer 0 Counter Register					*/
-#define TIMER0_PERIOD		0xFFC00608	/* Timer 0 Period Register					*/
-#define TIMER0_WIDTH		0xFFC0060C	/* Timer 0 Width Register					*/
-
-#define TIMER1_CONFIG		0xFFC00610	/* Timer 1 Configuration Register  			*/
-#define TIMER1_COUNTER		0xFFC00614	/* Timer 1 Counter Register        			*/
-#define TIMER1_PERIOD		0xFFC00618	/* Timer 1 Period Register         			*/
-#define TIMER1_WIDTH		0xFFC0061C	/* Timer 1 Width Register          			*/
-
-#define TIMER2_CONFIG		0xFFC00620	/* Timer 2 Configuration Register  			*/
-#define TIMER2_COUNTER		0xFFC00624	/* Timer 2 Counter Register        			*/
-#define TIMER2_PERIOD		0xFFC00628	/* Timer 2 Period Register         			*/
-#define TIMER2_WIDTH		0xFFC0062C	/* Timer 2 Width Register          			*/
-
-#define TIMER3_CONFIG		0xFFC00630	/* Timer 3 Configuration Register			*/
-#define TIMER3_COUNTER		0xFFC00634	/* Timer 3 Counter Register					*/
-#define TIMER3_PERIOD		0xFFC00638	/* Timer 3 Period Register					*/
-#define TIMER3_WIDTH		0xFFC0063C	/* Timer 3 Width Register					*/
-
-#define TIMER4_CONFIG		0xFFC00640	/* Timer 4 Configuration Register  			*/
-#define TIMER4_COUNTER		0xFFC00644	/* Timer 4 Counter Register        			*/
-#define TIMER4_PERIOD		0xFFC00648	/* Timer 4 Period Register         			*/
-#define TIMER4_WIDTH		0xFFC0064C	/* Timer 4 Width Register          			*/
-
-#define TIMER5_CONFIG		0xFFC00650	/* Timer 5 Configuration Register  			*/
-#define TIMER5_COUNTER		0xFFC00654	/* Timer 5 Counter Register        			*/
-#define TIMER5_PERIOD		0xFFC00658	/* Timer 5 Period Register         			*/
-#define TIMER5_WIDTH		0xFFC0065C	/* Timer 5 Width Register          			*/
-
-#define TIMER6_CONFIG		0xFFC00660	/* Timer 6 Configuration Register  			*/
-#define TIMER6_COUNTER		0xFFC00664	/* Timer 6 Counter Register        			*/
-#define TIMER6_PERIOD		0xFFC00668	/* Timer 6 Period Register         			*/
-#define TIMER6_WIDTH		0xFFC0066C	/* Timer 6 Width Register          			*/
-
-#define TIMER7_CONFIG		0xFFC00670	/* Timer 7 Configuration Register  			*/
-#define TIMER7_COUNTER		0xFFC00674	/* Timer 7 Counter Register        			*/
-#define TIMER7_PERIOD		0xFFC00678	/* Timer 7 Period Register         			*/
-#define TIMER7_WIDTH		0xFFC0067C	/* Timer 7 Width Register       			*/
-
-#define TIMER_ENABLE		0xFFC00680	/* Timer Enable Register					*/
-#define TIMER_DISABLE		0xFFC00684	/* Timer Disable Register					*/
-#define TIMER_STATUS		0xFFC00688	/* Timer Status Register					*/
-
-
-/* General Purpose I/O Port F (0xFFC00700 - 0xFFC007FF)												*/
-#define PORTFIO					0xFFC00700	/* Port F I/O Pin State Specify Register				*/
-#define PORTFIO_CLEAR			0xFFC00704	/* Port F I/O Peripheral Interrupt Clear Register		*/
-#define PORTFIO_SET				0xFFC00708	/* Port F I/O Peripheral Interrupt Set Register			*/
-#define PORTFIO_TOGGLE			0xFFC0070C	/* Port F I/O Pin State Toggle Register					*/
-#define PORTFIO_MASKA			0xFFC00710	/* Port F I/O Mask State Specify Interrupt A Register	*/
-#define PORTFIO_MASKA_CLEAR		0xFFC00714	/* Port F I/O Mask Disable Interrupt A Register			*/
-#define PORTFIO_MASKA_SET		0xFFC00718	/* Port F I/O Mask Enable Interrupt A Register			*/
-#define PORTFIO_MASKA_TOGGLE	0xFFC0071C	/* Port F I/O Mask Toggle Enable Interrupt A Register	*/
-#define PORTFIO_MASKB			0xFFC00720	/* Port F I/O Mask State Specify Interrupt B Register	*/
-#define PORTFIO_MASKB_CLEAR		0xFFC00724	/* Port F I/O Mask Disable Interrupt B Register			*/
-#define PORTFIO_MASKB_SET		0xFFC00728	/* Port F I/O Mask Enable Interrupt B Register			*/
-#define PORTFIO_MASKB_TOGGLE	0xFFC0072C	/* Port F I/O Mask Toggle Enable Interrupt B Register	*/
-#define PORTFIO_DIR				0xFFC00730	/* Port F I/O Direction Register						*/
-#define PORTFIO_POLAR			0xFFC00734	/* Port F I/O Source Polarity Register					*/
-#define PORTFIO_EDGE			0xFFC00738	/* Port F I/O Source Sensitivity Register				*/
-#define PORTFIO_BOTH			0xFFC0073C	/* Port F I/O Set on BOTH Edges Register				*/
-#define PORTFIO_INEN			0xFFC00740	/* Port F I/O Input Enable Register 					*/
-
-
-/* SPORT0 Controller		(0xFFC00800 - 0xFFC008FF)										*/
-#define SPORT0_TCR1			0xFFC00800	/* SPORT0 Transmit Configuration 1 Register			*/
-#define SPORT0_TCR2			0xFFC00804	/* SPORT0 Transmit Configuration 2 Register			*/
-#define SPORT0_TCLKDIV		0xFFC00808	/* SPORT0 Transmit Clock Divider					*/
-#define SPORT0_TFSDIV		0xFFC0080C	/* SPORT0 Transmit Frame Sync Divider				*/
-#define SPORT0_TX			0xFFC00810	/* SPORT0 TX Data Register							*/
-#define SPORT0_RX			0xFFC00818	/* SPORT0 RX Data Register							*/
-#define SPORT0_RCR1			0xFFC00820	/* SPORT0 Transmit Configuration 1 Register			*/
-#define SPORT0_RCR2			0xFFC00824	/* SPORT0 Transmit Configuration 2 Register			*/
-#define SPORT0_RCLKDIV		0xFFC00828	/* SPORT0 Receive Clock Divider						*/
-#define SPORT0_RFSDIV		0xFFC0082C	/* SPORT0 Receive Frame Sync Divider				*/
-#define SPORT0_STAT			0xFFC00830	/* SPORT0 Status Register							*/
-#define SPORT0_CHNL			0xFFC00834	/* SPORT0 Current Channel Register					*/
-#define SPORT0_MCMC1		0xFFC00838	/* SPORT0 Multi-Channel Configuration Register 1	*/
-#define SPORT0_MCMC2		0xFFC0083C	/* SPORT0 Multi-Channel Configuration Register 2	*/
-#define SPORT0_MTCS0		0xFFC00840	/* SPORT0 Multi-Channel Transmit Select Register 0	*/
-#define SPORT0_MTCS1		0xFFC00844	/* SPORT0 Multi-Channel Transmit Select Register 1	*/
-#define SPORT0_MTCS2		0xFFC00848	/* SPORT0 Multi-Channel Transmit Select Register 2	*/
-#define SPORT0_MTCS3		0xFFC0084C	/* SPORT0 Multi-Channel Transmit Select Register 3	*/
-#define SPORT0_MRCS0		0xFFC00850	/* SPORT0 Multi-Channel Receive Select Register 0	*/
-#define SPORT0_MRCS1		0xFFC00854	/* SPORT0 Multi-Channel Receive Select Register 1	*/
-#define SPORT0_MRCS2		0xFFC00858	/* SPORT0 Multi-Channel Receive Select Register 2	*/
-#define SPORT0_MRCS3		0xFFC0085C	/* SPORT0 Multi-Channel Receive Select Register 3	*/
-
-
-/* SPORT1 Controller		(0xFFC00900 - 0xFFC009FF)										*/
-#define SPORT1_TCR1			0xFFC00900	/* SPORT1 Transmit Configuration 1 Register			*/
-#define SPORT1_TCR2			0xFFC00904	/* SPORT1 Transmit Configuration 2 Register			*/
-#define SPORT1_TCLKDIV		0xFFC00908	/* SPORT1 Transmit Clock Divider					*/
-#define SPORT1_TFSDIV		0xFFC0090C	/* SPORT1 Transmit Frame Sync Divider				*/
-#define SPORT1_TX			0xFFC00910	/* SPORT1 TX Data Register							*/
-#define SPORT1_RX			0xFFC00918	/* SPORT1 RX Data Register							*/
-#define SPORT1_RCR1			0xFFC00920	/* SPORT1 Transmit Configuration 1 Register			*/
-#define SPORT1_RCR2			0xFFC00924	/* SPORT1 Transmit Configuration 2 Register			*/
-#define SPORT1_RCLKDIV		0xFFC00928	/* SPORT1 Receive Clock Divider						*/
-#define SPORT1_RFSDIV		0xFFC0092C	/* SPORT1 Receive Frame Sync Divider				*/
-#define SPORT1_STAT			0xFFC00930	/* SPORT1 Status Register							*/
-#define SPORT1_CHNL			0xFFC00934	/* SPORT1 Current Channel Register					*/
-#define SPORT1_MCMC1		0xFFC00938	/* SPORT1 Multi-Channel Configuration Register 1	*/
-#define SPORT1_MCMC2		0xFFC0093C	/* SPORT1 Multi-Channel Configuration Register 2	*/
-#define SPORT1_MTCS0		0xFFC00940	/* SPORT1 Multi-Channel Transmit Select Register 0	*/
-#define SPORT1_MTCS1		0xFFC00944	/* SPORT1 Multi-Channel Transmit Select Register 1	*/
-#define SPORT1_MTCS2		0xFFC00948	/* SPORT1 Multi-Channel Transmit Select Register 2	*/
-#define SPORT1_MTCS3		0xFFC0094C	/* SPORT1 Multi-Channel Transmit Select Register 3	*/
-#define SPORT1_MRCS0		0xFFC00950	/* SPORT1 Multi-Channel Receive Select Register 0	*/
-#define SPORT1_MRCS1		0xFFC00954	/* SPORT1 Multi-Channel Receive Select Register 1	*/
-#define SPORT1_MRCS2		0xFFC00958	/* SPORT1 Multi-Channel Receive Select Register 2	*/
-#define SPORT1_MRCS3		0xFFC0095C	/* SPORT1 Multi-Channel Receive Select Register 3	*/
-
-
-/* External Bus Interface Unit (0xFFC00A00 - 0xFFC00AFF)								*/
-#define EBIU_AMGCTL			0xFFC00A00	/* Asynchronous Memory Global Control Register	*/
-#define EBIU_AMBCTL0		0xFFC00A04	/* Asynchronous Memory Bank Control Register 0	*/
-#define EBIU_AMBCTL1		0xFFC00A08	/* Asynchronous Memory Bank Control Register 1	*/
-#define EBIU_SDGCTL			0xFFC00A10	/* SDRAM Global Control Register				*/
-#define EBIU_SDBCTL			0xFFC00A14	/* SDRAM Bank Control Register					*/
-#define EBIU_SDRRC			0xFFC00A18	/* SDRAM Refresh Rate Control Register			*/
-#define EBIU_SDSTAT			0xFFC00A1C	/* SDRAM Status Register						*/
-
-
-/* DMA Traffic Control Registers													*/
-#define DMA_TC_PER			0xFFC00B0C	/* Traffic Control Periods Register			*/
-#define DMA_TC_CNT			0xFFC00B10	/* Traffic Control Current Counts Register	*/
-
-/* Alternate deprecated register names (below) provided for backwards code compatibility */
-#define DMA_TCPER			0xFFC00B0C	/* Traffic Control Periods Register			*/
-#define DMA_TCCNT			0xFFC00B10	/* Traffic Control Current Counts Register	*/
-
-/* DMA Controller (0xFFC00C00 - 0xFFC00FFF)															*/
-#define DMA0_NEXT_DESC_PTR		0xFFC00C00	/* DMA Channel 0 Next Descriptor Pointer Register		*/
-#define DMA0_START_ADDR			0xFFC00C04	/* DMA Channel 0 Start Address Register					*/
-#define DMA0_CONFIG				0xFFC00C08	/* DMA Channel 0 Configuration Register					*/
-#define DMA0_X_COUNT			0xFFC00C10	/* DMA Channel 0 X Count Register						*/
-#define DMA0_X_MODIFY			0xFFC00C14	/* DMA Channel 0 X Modify Register						*/
-#define DMA0_Y_COUNT			0xFFC00C18	/* DMA Channel 0 Y Count Register						*/
-#define DMA0_Y_MODIFY			0xFFC00C1C	/* DMA Channel 0 Y Modify Register						*/
-#define DMA0_CURR_DESC_PTR		0xFFC00C20	/* DMA Channel 0 Current Descriptor Pointer Register	*/
-#define DMA0_CURR_ADDR			0xFFC00C24	/* DMA Channel 0 Current Address Register				*/
-#define DMA0_IRQ_STATUS			0xFFC00C28	/* DMA Channel 0 Interrupt/Status Register				*/
-#define DMA0_PERIPHERAL_MAP		0xFFC00C2C	/* DMA Channel 0 Peripheral Map Register				*/
-#define DMA0_CURR_X_COUNT		0xFFC00C30	/* DMA Channel 0 Current X Count Register				*/
-#define DMA0_CURR_Y_COUNT		0xFFC00C38	/* DMA Channel 0 Current Y Count Register				*/
-
-#define DMA1_NEXT_DESC_PTR		0xFFC00C40	/* DMA Channel 1 Next Descriptor Pointer Register		*/
-#define DMA1_START_ADDR			0xFFC00C44	/* DMA Channel 1 Start Address Register					*/
-#define DMA1_CONFIG				0xFFC00C48	/* DMA Channel 1 Configuration Register					*/
-#define DMA1_X_COUNT			0xFFC00C50	/* DMA Channel 1 X Count Register						*/
-#define DMA1_X_MODIFY			0xFFC00C54	/* DMA Channel 1 X Modify Register						*/
-#define DMA1_Y_COUNT			0xFFC00C58	/* DMA Channel 1 Y Count Register						*/
-#define DMA1_Y_MODIFY			0xFFC00C5C	/* DMA Channel 1 Y Modify Register						*/
-#define DMA1_CURR_DESC_PTR		0xFFC00C60	/* DMA Channel 1 Current Descriptor Pointer Register	*/
-#define DMA1_CURR_ADDR			0xFFC00C64	/* DMA Channel 1 Current Address Register				*/
-#define DMA1_IRQ_STATUS			0xFFC00C68	/* DMA Channel 1 Interrupt/Status Register				*/
-#define DMA1_PERIPHERAL_MAP		0xFFC00C6C	/* DMA Channel 1 Peripheral Map Register				*/
-#define DMA1_CURR_X_COUNT		0xFFC00C70	/* DMA Channel 1 Current X Count Register				*/
-#define DMA1_CURR_Y_COUNT		0xFFC00C78	/* DMA Channel 1 Current Y Count Register				*/
-
-#define DMA2_NEXT_DESC_PTR		0xFFC00C80	/* DMA Channel 2 Next Descriptor Pointer Register		*/
-#define DMA2_START_ADDR			0xFFC00C84	/* DMA Channel 2 Start Address Register					*/
-#define DMA2_CONFIG				0xFFC00C88	/* DMA Channel 2 Configuration Register					*/
-#define DMA2_X_COUNT			0xFFC00C90	/* DMA Channel 2 X Count Register						*/
-#define DMA2_X_MODIFY			0xFFC00C94	/* DMA Channel 2 X Modify Register						*/
-#define DMA2_Y_COUNT			0xFFC00C98	/* DMA Channel 2 Y Count Register						*/
-#define DMA2_Y_MODIFY			0xFFC00C9C	/* DMA Channel 2 Y Modify Register						*/
-#define DMA2_CURR_DESC_PTR		0xFFC00CA0	/* DMA Channel 2 Current Descriptor Pointer Register	*/
-#define DMA2_CURR_ADDR			0xFFC00CA4	/* DMA Channel 2 Current Address Register				*/
-#define DMA2_IRQ_STATUS			0xFFC00CA8	/* DMA Channel 2 Interrupt/Status Register				*/
-#define DMA2_PERIPHERAL_MAP		0xFFC00CAC	/* DMA Channel 2 Peripheral Map Register				*/
-#define DMA2_CURR_X_COUNT		0xFFC00CB0	/* DMA Channel 2 Current X Count Register				*/
-#define DMA2_CURR_Y_COUNT		0xFFC00CB8	/* DMA Channel 2 Current Y Count Register				*/
-
-#define DMA3_NEXT_DESC_PTR		0xFFC00CC0	/* DMA Channel 3 Next Descriptor Pointer Register		*/
-#define DMA3_START_ADDR			0xFFC00CC4	/* DMA Channel 3 Start Address Register					*/
-#define DMA3_CONFIG				0xFFC00CC8	/* DMA Channel 3 Configuration Register					*/
-#define DMA3_X_COUNT			0xFFC00CD0	/* DMA Channel 3 X Count Register						*/
-#define DMA3_X_MODIFY			0xFFC00CD4	/* DMA Channel 3 X Modify Register						*/
-#define DMA3_Y_COUNT			0xFFC00CD8	/* DMA Channel 3 Y Count Register						*/
-#define DMA3_Y_MODIFY			0xFFC00CDC	/* DMA Channel 3 Y Modify Register						*/
-#define DMA3_CURR_DESC_PTR		0xFFC00CE0	/* DMA Channel 3 Current Descriptor Pointer Register	*/
-#define DMA3_CURR_ADDR			0xFFC00CE4	/* DMA Channel 3 Current Address Register				*/
-#define DMA3_IRQ_STATUS			0xFFC00CE8	/* DMA Channel 3 Interrupt/Status Register				*/
-#define DMA3_PERIPHERAL_MAP		0xFFC00CEC	/* DMA Channel 3 Peripheral Map Register				*/
-#define DMA3_CURR_X_COUNT		0xFFC00CF0	/* DMA Channel 3 Current X Count Register				*/
-#define DMA3_CURR_Y_COUNT		0xFFC00CF8	/* DMA Channel 3 Current Y Count Register				*/
-
-#define DMA4_NEXT_DESC_PTR		0xFFC00D00	/* DMA Channel 4 Next Descriptor Pointer Register		*/
-#define DMA4_START_ADDR			0xFFC00D04	/* DMA Channel 4 Start Address Register					*/
-#define DMA4_CONFIG				0xFFC00D08	/* DMA Channel 4 Configuration Register					*/
-#define DMA4_X_COUNT			0xFFC00D10	/* DMA Channel 4 X Count Register						*/
-#define DMA4_X_MODIFY			0xFFC00D14	/* DMA Channel 4 X Modify Register						*/
-#define DMA4_Y_COUNT			0xFFC00D18	/* DMA Channel 4 Y Count Register						*/
-#define DMA4_Y_MODIFY			0xFFC00D1C	/* DMA Channel 4 Y Modify Register						*/
-#define DMA4_CURR_DESC_PTR		0xFFC00D20	/* DMA Channel 4 Current Descriptor Pointer Register	*/
-#define DMA4_CURR_ADDR			0xFFC00D24	/* DMA Channel 4 Current Address Register				*/
-#define DMA4_IRQ_STATUS			0xFFC00D28	/* DMA Channel 4 Interrupt/Status Register				*/
-#define DMA4_PERIPHERAL_MAP		0xFFC00D2C	/* DMA Channel 4 Peripheral Map Register				*/
-#define DMA4_CURR_X_COUNT		0xFFC00D30	/* DMA Channel 4 Current X Count Register				*/
-#define DMA4_CURR_Y_COUNT		0xFFC00D38	/* DMA Channel 4 Current Y Count Register				*/
-
-#define DMA5_NEXT_DESC_PTR		0xFFC00D40	/* DMA Channel 5 Next Descriptor Pointer Register		*/
-#define DMA5_START_ADDR			0xFFC00D44	/* DMA Channel 5 Start Address Register					*/
-#define DMA5_CONFIG				0xFFC00D48	/* DMA Channel 5 Configuration Register					*/
-#define DMA5_X_COUNT			0xFFC00D50	/* DMA Channel 5 X Count Register						*/
-#define DMA5_X_MODIFY			0xFFC00D54	/* DMA Channel 5 X Modify Register						*/
-#define DMA5_Y_COUNT			0xFFC00D58	/* DMA Channel 5 Y Count Register						*/
-#define DMA5_Y_MODIFY			0xFFC00D5C	/* DMA Channel 5 Y Modify Register						*/
-#define DMA5_CURR_DESC_PTR		0xFFC00D60	/* DMA Channel 5 Current Descriptor Pointer Register	*/
-#define DMA5_CURR_ADDR			0xFFC00D64	/* DMA Channel 5 Current Address Register				*/
-#define DMA5_IRQ_STATUS			0xFFC00D68	/* DMA Channel 5 Interrupt/Status Register				*/
-#define DMA5_PERIPHERAL_MAP		0xFFC00D6C	/* DMA Channel 5 Peripheral Map Register				*/
-#define DMA5_CURR_X_COUNT		0xFFC00D70	/* DMA Channel 5 Current X Count Register				*/
-#define DMA5_CURR_Y_COUNT		0xFFC00D78	/* DMA Channel 5 Current Y Count Register				*/
-
-#define DMA6_NEXT_DESC_PTR		0xFFC00D80	/* DMA Channel 6 Next Descriptor Pointer Register		*/
-#define DMA6_START_ADDR			0xFFC00D84	/* DMA Channel 6 Start Address Register					*/
-#define DMA6_CONFIG				0xFFC00D88	/* DMA Channel 6 Configuration Register					*/
-#define DMA6_X_COUNT			0xFFC00D90	/* DMA Channel 6 X Count Register						*/
-#define DMA6_X_MODIFY			0xFFC00D94	/* DMA Channel 6 X Modify Register						*/
-#define DMA6_Y_COUNT			0xFFC00D98	/* DMA Channel 6 Y Count Register						*/
-#define DMA6_Y_MODIFY			0xFFC00D9C	/* DMA Channel 6 Y Modify Register						*/
-#define DMA6_CURR_DESC_PTR		0xFFC00DA0	/* DMA Channel 6 Current Descriptor Pointer Register	*/
-#define DMA6_CURR_ADDR			0xFFC00DA4	/* DMA Channel 6 Current Address Register				*/
-#define DMA6_IRQ_STATUS			0xFFC00DA8	/* DMA Channel 6 Interrupt/Status Register				*/
-#define DMA6_PERIPHERAL_MAP		0xFFC00DAC	/* DMA Channel 6 Peripheral Map Register				*/
-#define DMA6_CURR_X_COUNT		0xFFC00DB0	/* DMA Channel 6 Current X Count Register				*/
-#define DMA6_CURR_Y_COUNT		0xFFC00DB8	/* DMA Channel 6 Current Y Count Register				*/
-
-#define DMA7_NEXT_DESC_PTR		0xFFC00DC0	/* DMA Channel 7 Next Descriptor Pointer Register		*/
-#define DMA7_START_ADDR			0xFFC00DC4	/* DMA Channel 7 Start Address Register					*/
-#define DMA7_CONFIG				0xFFC00DC8	/* DMA Channel 7 Configuration Register					*/
-#define DMA7_X_COUNT			0xFFC00DD0	/* DMA Channel 7 X Count Register						*/
-#define DMA7_X_MODIFY			0xFFC00DD4	/* DMA Channel 7 X Modify Register						*/
-#define DMA7_Y_COUNT			0xFFC00DD8	/* DMA Channel 7 Y Count Register						*/
-#define DMA7_Y_MODIFY			0xFFC00DDC	/* DMA Channel 7 Y Modify Register						*/
-#define DMA7_CURR_DESC_PTR		0xFFC00DE0	/* DMA Channel 7 Current Descriptor Pointer Register	*/
-#define DMA7_CURR_ADDR			0xFFC00DE4	/* DMA Channel 7 Current Address Register				*/
-#define DMA7_IRQ_STATUS			0xFFC00DE8	/* DMA Channel 7 Interrupt/Status Register				*/
-#define DMA7_PERIPHERAL_MAP		0xFFC00DEC	/* DMA Channel 7 Peripheral Map Register				*/
-#define DMA7_CURR_X_COUNT		0xFFC00DF0	/* DMA Channel 7 Current X Count Register				*/
-#define DMA7_CURR_Y_COUNT		0xFFC00DF8	/* DMA Channel 7 Current Y Count Register				*/
-
-#define DMA8_NEXT_DESC_PTR		0xFFC00E00	/* DMA Channel 8 Next Descriptor Pointer Register		*/
-#define DMA8_START_ADDR			0xFFC00E04	/* DMA Channel 8 Start Address Register					*/
-#define DMA8_CONFIG				0xFFC00E08	/* DMA Channel 8 Configuration Register					*/
-#define DMA8_X_COUNT			0xFFC00E10	/* DMA Channel 8 X Count Register						*/
-#define DMA8_X_MODIFY			0xFFC00E14	/* DMA Channel 8 X Modify Register						*/
-#define DMA8_Y_COUNT			0xFFC00E18	/* DMA Channel 8 Y Count Register						*/
-#define DMA8_Y_MODIFY			0xFFC00E1C	/* DMA Channel 8 Y Modify Register						*/
-#define DMA8_CURR_DESC_PTR		0xFFC00E20	/* DMA Channel 8 Current Descriptor Pointer Register	*/
-#define DMA8_CURR_ADDR			0xFFC00E24	/* DMA Channel 8 Current Address Register				*/
-#define DMA8_IRQ_STATUS			0xFFC00E28	/* DMA Channel 8 Interrupt/Status Register				*/
-#define DMA8_PERIPHERAL_MAP		0xFFC00E2C	/* DMA Channel 8 Peripheral Map Register				*/
-#define DMA8_CURR_X_COUNT		0xFFC00E30	/* DMA Channel 8 Current X Count Register				*/
-#define DMA8_CURR_Y_COUNT		0xFFC00E38	/* DMA Channel 8 Current Y Count Register				*/
-
-#define DMA9_NEXT_DESC_PTR		0xFFC00E40	/* DMA Channel 9 Next Descriptor Pointer Register		*/
-#define DMA9_START_ADDR			0xFFC00E44	/* DMA Channel 9 Start Address Register					*/
-#define DMA9_CONFIG				0xFFC00E48	/* DMA Channel 9 Configuration Register					*/
-#define DMA9_X_COUNT			0xFFC00E50	/* DMA Channel 9 X Count Register						*/
-#define DMA9_X_MODIFY			0xFFC00E54	/* DMA Channel 9 X Modify Register						*/
-#define DMA9_Y_COUNT			0xFFC00E58	/* DMA Channel 9 Y Count Register						*/
-#define DMA9_Y_MODIFY			0xFFC00E5C	/* DMA Channel 9 Y Modify Register						*/
-#define DMA9_CURR_DESC_PTR		0xFFC00E60	/* DMA Channel 9 Current Descriptor Pointer Register	*/
-#define DMA9_CURR_ADDR			0xFFC00E64	/* DMA Channel 9 Current Address Register				*/
-#define DMA9_IRQ_STATUS			0xFFC00E68	/* DMA Channel 9 Interrupt/Status Register				*/
-#define DMA9_PERIPHERAL_MAP		0xFFC00E6C	/* DMA Channel 9 Peripheral Map Register				*/
-#define DMA9_CURR_X_COUNT		0xFFC00E70	/* DMA Channel 9 Current X Count Register				*/
-#define DMA9_CURR_Y_COUNT		0xFFC00E78	/* DMA Channel 9 Current Y Count Register				*/
-
-#define DMA10_NEXT_DESC_PTR		0xFFC00E80	/* DMA Channel 10 Next Descriptor Pointer Register		*/
-#define DMA10_START_ADDR		0xFFC00E84	/* DMA Channel 10 Start Address Register				*/
-#define DMA10_CONFIG			0xFFC00E88	/* DMA Channel 10 Configuration Register				*/
-#define DMA10_X_COUNT			0xFFC00E90	/* DMA Channel 10 X Count Register						*/
-#define DMA10_X_MODIFY			0xFFC00E94	/* DMA Channel 10 X Modify Register						*/
-#define DMA10_Y_COUNT			0xFFC00E98	/* DMA Channel 10 Y Count Register						*/
-#define DMA10_Y_MODIFY			0xFFC00E9C	/* DMA Channel 10 Y Modify Register						*/
-#define DMA10_CURR_DESC_PTR		0xFFC00EA0	/* DMA Channel 10 Current Descriptor Pointer Register	*/
-#define DMA10_CURR_ADDR			0xFFC00EA4	/* DMA Channel 10 Current Address Register				*/
-#define DMA10_IRQ_STATUS		0xFFC00EA8	/* DMA Channel 10 Interrupt/Status Register				*/
-#define DMA10_PERIPHERAL_MAP	0xFFC00EAC	/* DMA Channel 10 Peripheral Map Register				*/
-#define DMA10_CURR_X_COUNT		0xFFC00EB0	/* DMA Channel 10 Current X Count Register				*/
-#define DMA10_CURR_Y_COUNT		0xFFC00EB8	/* DMA Channel 10 Current Y Count Register				*/
-
-#define DMA11_NEXT_DESC_PTR		0xFFC00EC0	/* DMA Channel 11 Next Descriptor Pointer Register		*/
-#define DMA11_START_ADDR		0xFFC00EC4	/* DMA Channel 11 Start Address Register				*/
-#define DMA11_CONFIG			0xFFC00EC8	/* DMA Channel 11 Configuration Register				*/
-#define DMA11_X_COUNT			0xFFC00ED0	/* DMA Channel 11 X Count Register						*/
-#define DMA11_X_MODIFY			0xFFC00ED4	/* DMA Channel 11 X Modify Register						*/
-#define DMA11_Y_COUNT			0xFFC00ED8	/* DMA Channel 11 Y Count Register						*/
-#define DMA11_Y_MODIFY			0xFFC00EDC	/* DMA Channel 11 Y Modify Register						*/
-#define DMA11_CURR_DESC_PTR		0xFFC00EE0	/* DMA Channel 11 Current Descriptor Pointer Register	*/
-#define DMA11_CURR_ADDR			0xFFC00EE4	/* DMA Channel 11 Current Address Register				*/
-#define DMA11_IRQ_STATUS		0xFFC00EE8	/* DMA Channel 11 Interrupt/Status Register				*/
-#define DMA11_PERIPHERAL_MAP	0xFFC00EEC	/* DMA Channel 11 Peripheral Map Register				*/
-#define DMA11_CURR_X_COUNT		0xFFC00EF0	/* DMA Channel 11 Current X Count Register				*/
-#define DMA11_CURR_Y_COUNT		0xFFC00EF8	/* DMA Channel 11 Current Y Count Register				*/
-
-#define MDMA_D0_NEXT_DESC_PTR	0xFFC00F00	/* MemDMA Stream 0 Destination Next Descriptor Pointer Register		*/
-#define MDMA_D0_START_ADDR		0xFFC00F04	/* MemDMA Stream 0 Destination Start Address Register				*/
-#define MDMA_D0_CONFIG			0xFFC00F08	/* MemDMA Stream 0 Destination Configuration Register				*/
-#define MDMA_D0_X_COUNT			0xFFC00F10	/* MemDMA Stream 0 Destination X Count Register						*/
-#define MDMA_D0_X_MODIFY		0xFFC00F14	/* MemDMA Stream 0 Destination X Modify Register					*/
-#define MDMA_D0_Y_COUNT			0xFFC00F18	/* MemDMA Stream 0 Destination Y Count Register						*/
-#define MDMA_D0_Y_MODIFY		0xFFC00F1C	/* MemDMA Stream 0 Destination Y Modify Register					*/
-#define MDMA_D0_CURR_DESC_PTR	0xFFC00F20	/* MemDMA Stream 0 Destination Current Descriptor Pointer Register	*/
-#define MDMA_D0_CURR_ADDR		0xFFC00F24	/* MemDMA Stream 0 Destination Current Address Register				*/
-#define MDMA_D0_IRQ_STATUS		0xFFC00F28	/* MemDMA Stream 0 Destination Interrupt/Status Register			*/
-#define MDMA_D0_PERIPHERAL_MAP	0xFFC00F2C	/* MemDMA Stream 0 Destination Peripheral Map Register				*/
-#define MDMA_D0_CURR_X_COUNT	0xFFC00F30	/* MemDMA Stream 0 Destination Current X Count Register				*/
-#define MDMA_D0_CURR_Y_COUNT	0xFFC00F38	/* MemDMA Stream 0 Destination Current Y Count Register				*/
-
-#define MDMA_S0_NEXT_DESC_PTR	0xFFC00F40	/* MemDMA Stream 0 Source Next Descriptor Pointer Register			*/
-#define MDMA_S0_START_ADDR		0xFFC00F44	/* MemDMA Stream 0 Source Start Address Register					*/
-#define MDMA_S0_CONFIG			0xFFC00F48	/* MemDMA Stream 0 Source Configuration Register					*/
-#define MDMA_S0_X_COUNT			0xFFC00F50	/* MemDMA Stream 0 Source X Count Register							*/
-#define MDMA_S0_X_MODIFY		0xFFC00F54	/* MemDMA Stream 0 Source X Modify Register							*/
-#define MDMA_S0_Y_COUNT			0xFFC00F58	/* MemDMA Stream 0 Source Y Count Register							*/
-#define MDMA_S0_Y_MODIFY		0xFFC00F5C	/* MemDMA Stream 0 Source Y Modify Register							*/
-#define MDMA_S0_CURR_DESC_PTR	0xFFC00F60	/* MemDMA Stream 0 Source Current Descriptor Pointer Register		*/
-#define MDMA_S0_CURR_ADDR		0xFFC00F64	/* MemDMA Stream 0 Source Current Address Register					*/
-#define MDMA_S0_IRQ_STATUS		0xFFC00F68	/* MemDMA Stream 0 Source Interrupt/Status Register					*/
-#define MDMA_S0_PERIPHERAL_MAP	0xFFC00F6C	/* MemDMA Stream 0 Source Peripheral Map Register					*/
-#define MDMA_S0_CURR_X_COUNT	0xFFC00F70	/* MemDMA Stream 0 Source Current X Count Register					*/
-#define MDMA_S0_CURR_Y_COUNT	0xFFC00F78	/* MemDMA Stream 0 Source Current Y Count Register					*/
-
-#define MDMA_D1_NEXT_DESC_PTR	0xFFC00F80	/* MemDMA Stream 1 Destination Next Descriptor Pointer Register		*/
-#define MDMA_D1_START_ADDR		0xFFC00F84	/* MemDMA Stream 1 Destination Start Address Register				*/
-#define MDMA_D1_CONFIG			0xFFC00F88	/* MemDMA Stream 1 Destination Configuration Register				*/
-#define MDMA_D1_X_COUNT			0xFFC00F90	/* MemDMA Stream 1 Destination X Count Register						*/
-#define MDMA_D1_X_MODIFY		0xFFC00F94	/* MemDMA Stream 1 Destination X Modify Register					*/
-#define MDMA_D1_Y_COUNT			0xFFC00F98	/* MemDMA Stream 1 Destination Y Count Register						*/
-#define MDMA_D1_Y_MODIFY		0xFFC00F9C	/* MemDMA Stream 1 Destination Y Modify Register					*/
-#define MDMA_D1_CURR_DESC_PTR	0xFFC00FA0	/* MemDMA Stream 1 Destination Current Descriptor Pointer Register	*/
-#define MDMA_D1_CURR_ADDR		0xFFC00FA4	/* MemDMA Stream 1 Destination Current Address Register				*/
-#define MDMA_D1_IRQ_STATUS		0xFFC00FA8	/* MemDMA Stream 1 Destination Interrupt/Status Register			*/
-#define MDMA_D1_PERIPHERAL_MAP	0xFFC00FAC	/* MemDMA Stream 1 Destination Peripheral Map Register				*/
-#define MDMA_D1_CURR_X_COUNT	0xFFC00FB0	/* MemDMA Stream 1 Destination Current X Count Register				*/
-#define MDMA_D1_CURR_Y_COUNT	0xFFC00FB8	/* MemDMA Stream 1 Destination Current Y Count Register				*/
-
-#define MDMA_S1_NEXT_DESC_PTR	0xFFC00FC0	/* MemDMA Stream 1 Source Next Descriptor Pointer Register			*/
-#define MDMA_S1_START_ADDR		0xFFC00FC4	/* MemDMA Stream 1 Source Start Address Register					*/
-#define MDMA_S1_CONFIG			0xFFC00FC8	/* MemDMA Stream 1 Source Configuration Register					*/
-#define MDMA_S1_X_COUNT			0xFFC00FD0	/* MemDMA Stream 1 Source X Count Register							*/
-#define MDMA_S1_X_MODIFY		0xFFC00FD4	/* MemDMA Stream 1 Source X Modify Register							*/
-#define MDMA_S1_Y_COUNT			0xFFC00FD8	/* MemDMA Stream 1 Source Y Count Register							*/
-#define MDMA_S1_Y_MODIFY		0xFFC00FDC	/* MemDMA Stream 1 Source Y Modify Register							*/
-#define MDMA_S1_CURR_DESC_PTR	0xFFC00FE0	/* MemDMA Stream 1 Source Current Descriptor Pointer Register		*/
-#define MDMA_S1_CURR_ADDR		0xFFC00FE4	/* MemDMA Stream 1 Source Current Address Register					*/
-#define MDMA_S1_IRQ_STATUS		0xFFC00FE8	/* MemDMA Stream 1 Source Interrupt/Status Register					*/
-#define MDMA_S1_PERIPHERAL_MAP	0xFFC00FEC	/* MemDMA Stream 1 Source Peripheral Map Register					*/
-#define MDMA_S1_CURR_X_COUNT	0xFFC00FF0	/* MemDMA Stream 1 Source Current X Count Register					*/
-#define MDMA_S1_CURR_Y_COUNT	0xFFC00FF8	/* MemDMA Stream 1 Source Current Y Count Register					*/
-
-
-/* Parallel Peripheral Interface (0xFFC01000 - 0xFFC010FF)				*/
-#define PPI_CONTROL			0xFFC01000	/* PPI Control Register			*/
-#define PPI_STATUS			0xFFC01004	/* PPI Status Register			*/
-#define PPI_COUNT			0xFFC01008	/* PPI Transfer Count Register	*/
-#define PPI_DELAY			0xFFC0100C	/* PPI Delay Count Register		*/
-#define PPI_FRAME			0xFFC01010	/* PPI Frame Length Register	*/
-
-
-/* Two-Wire Interface		(0xFFC01400 - 0xFFC014FF)								*/
-#define TWI0_REGBASE			0xFFC01400
-#define TWI0_CLKDIV			0xFFC01400	/* Serial Clock Divider Register			*/
-#define TWI0_CONTROL			0xFFC01404	/* TWI Control Register						*/
-#define TWI0_SLAVE_CTL		0xFFC01408	/* Slave Mode Control Register				*/
-#define TWI0_SLAVE_STAT		0xFFC0140C	/* Slave Mode Status Register				*/
-#define TWI0_SLAVE_ADDR		0xFFC01410	/* Slave Mode Address Register				*/
-#define TWI0_MASTER_CTL		0xFFC01414	/* Master Mode Control Register				*/
-#define TWI0_MASTER_STAT		0xFFC01418	/* Master Mode Status Register				*/
-#define TWI0_MASTER_ADDR		0xFFC0141C	/* Master Mode Address Register				*/
-#define TWI0_INT_STAT		0xFFC01420	/* TWI Interrupt Status Register			*/
-#define TWI0_INT_MASK		0xFFC01424	/* TWI Master Interrupt Mask Register		*/
-#define TWI0_FIFO_CTL		0xFFC01428	/* FIFO Control Register					*/
-#define TWI0_FIFO_STAT		0xFFC0142C	/* FIFO Status Register						*/
-#define TWI0_XMT_DATA8		0xFFC01480	/* FIFO Transmit Data Single Byte Register	*/
-#define TWI0_XMT_DATA16		0xFFC01484	/* FIFO Transmit Data Double Byte Register	*/
-#define TWI0_RCV_DATA8		0xFFC01488	/* FIFO Receive Data Single Byte Register	*/
-#define TWI0_RCV_DATA16		0xFFC0148C	/* FIFO Receive Data Double Byte Register	*/
-
-
-/* General Purpose I/O Port G (0xFFC01500 - 0xFFC015FF)												*/
-#define PORTGIO					0xFFC01500	/* Port G I/O Pin State Specify Register				*/
-#define PORTGIO_CLEAR			0xFFC01504	/* Port G I/O Peripheral Interrupt Clear Register		*/
-#define PORTGIO_SET				0xFFC01508	/* Port G I/O Peripheral Interrupt Set Register			*/
-#define PORTGIO_TOGGLE			0xFFC0150C	/* Port G I/O Pin State Toggle Register					*/
-#define PORTGIO_MASKA			0xFFC01510	/* Port G I/O Mask State Specify Interrupt A Register	*/
-#define PORTGIO_MASKA_CLEAR		0xFFC01514	/* Port G I/O Mask Disable Interrupt A Register			*/
-#define PORTGIO_MASKA_SET		0xFFC01518	/* Port G I/O Mask Enable Interrupt A Register			*/
-#define PORTGIO_MASKA_TOGGLE	0xFFC0151C	/* Port G I/O Mask Toggle Enable Interrupt A Register	*/
-#define PORTGIO_MASKB			0xFFC01520	/* Port G I/O Mask State Specify Interrupt B Register	*/
-#define PORTGIO_MASKB_CLEAR		0xFFC01524	/* Port G I/O Mask Disable Interrupt B Register			*/
-#define PORTGIO_MASKB_SET		0xFFC01528	/* Port G I/O Mask Enable Interrupt B Register			*/
-#define PORTGIO_MASKB_TOGGLE	0xFFC0152C	/* Port G I/O Mask Toggle Enable Interrupt B Register	*/
-#define PORTGIO_DIR				0xFFC01530	/* Port G I/O Direction Register						*/
-#define PORTGIO_POLAR			0xFFC01534	/* Port G I/O Source Polarity Register					*/
-#define PORTGIO_EDGE			0xFFC01538	/* Port G I/O Source Sensitivity Register				*/
-#define PORTGIO_BOTH			0xFFC0153C	/* Port G I/O Set on BOTH Edges Register				*/
-#define PORTGIO_INEN			0xFFC01540	/* Port G I/O Input Enable Register						*/
-
-
-/* General Purpose I/O Port H (0xFFC01700 - 0xFFC017FF)												*/
-#define PORTHIO					0xFFC01700	/* Port H I/O Pin State Specify Register				*/
-#define PORTHIO_CLEAR			0xFFC01704	/* Port H I/O Peripheral Interrupt Clear Register		*/
-#define PORTHIO_SET				0xFFC01708	/* Port H I/O Peripheral Interrupt Set Register			*/
-#define PORTHIO_TOGGLE			0xFFC0170C	/* Port H I/O Pin State Toggle Register					*/
-#define PORTHIO_MASKA			0xFFC01710	/* Port H I/O Mask State Specify Interrupt A Register	*/
-#define PORTHIO_MASKA_CLEAR		0xFFC01714	/* Port H I/O Mask Disable Interrupt A Register			*/
-#define PORTHIO_MASKA_SET		0xFFC01718	/* Port H I/O Mask Enable Interrupt A Register			*/
-#define PORTHIO_MASKA_TOGGLE	0xFFC0171C	/* Port H I/O Mask Toggle Enable Interrupt A Register	*/
-#define PORTHIO_MASKB			0xFFC01720	/* Port H I/O Mask State Specify Interrupt B Register	*/
-#define PORTHIO_MASKB_CLEAR		0xFFC01724	/* Port H I/O Mask Disable Interrupt B Register			*/
-#define PORTHIO_MASKB_SET		0xFFC01728	/* Port H I/O Mask Enable Interrupt B Register			*/
-#define PORTHIO_MASKB_TOGGLE	0xFFC0172C	/* Port H I/O Mask Toggle Enable Interrupt B Register	*/
-#define PORTHIO_DIR				0xFFC01730	/* Port H I/O Direction Register						*/
-#define PORTHIO_POLAR			0xFFC01734	/* Port H I/O Source Polarity Register					*/
-#define PORTHIO_EDGE			0xFFC01738	/* Port H I/O Source Sensitivity Register				*/
-#define PORTHIO_BOTH			0xFFC0173C	/* Port H I/O Set on BOTH Edges Register				*/
-#define PORTHIO_INEN			0xFFC01740	/* Port H I/O Input Enable Register						*/
-
-
-/* UART1 Controller		(0xFFC02000 - 0xFFC020FF)								*/
-#define UART1_THR			0xFFC02000	/* Transmit Holding register			*/
-#define UART1_RBR			0xFFC02000	/* Receive Buffer register				*/
-#define UART1_DLL			0xFFC02000	/* Divisor Latch (Low-Byte)				*/
-#define UART1_IER			0xFFC02004	/* Interrupt Enable Register			*/
-#define UART1_DLH			0xFFC02004	/* Divisor Latch (High-Byte)			*/
-#define UART1_IIR			0xFFC02008	/* Interrupt Identification Register	*/
-#define UART1_LCR			0xFFC0200C	/* Line Control Register				*/
-#define UART1_MCR			0xFFC02010	/* Modem Control Register				*/
-#define UART1_LSR			0xFFC02014	/* Line Status Register					*/
-#define UART1_MSR			0xFFC02018	/* Modem Status Register				*/
-#define UART1_SCR			0xFFC0201C	/* SCR Scratch Register					*/
-#define UART1_GCTL			0xFFC02024	/* Global Control Register				*/
-
-
-/* Omit CAN register sets from the defBF534.h (CAN is not in the ADSP-BF52x processor) */
-
-/* Pin Control Registers	(0xFFC03200 - 0xFFC032FF)											*/
-#define PORTF_FER			0xFFC03200	/* Port F Function Enable Register (Alternate/Flag*)	*/
-#define PORTG_FER			0xFFC03204	/* Port G Function Enable Register (Alternate/Flag*)	*/
-#define PORTH_FER			0xFFC03208	/* Port H Function Enable Register (Alternate/Flag*)	*/
-#define BFIN_PORT_MUX			0xFFC0320C	/* Port Multiplexer Control Register					*/
-
-
-/* Handshake MDMA Registers	(0xFFC03300 - 0xFFC033FF)										*/
-#define HMDMA0_CONTROL		0xFFC03300	/* Handshake MDMA0 Control Register					*/
-#define HMDMA0_ECINIT		0xFFC03304	/* HMDMA0 Initial Edge Count Register				*/
-#define HMDMA0_BCINIT		0xFFC03308	/* HMDMA0 Initial Block Count Register				*/
-#define HMDMA0_ECURGENT		0xFFC0330C	/* HMDMA0 Urgent Edge Count Threshold Register		*/
-#define HMDMA0_ECOVERFLOW	0xFFC03310	/* HMDMA0 Edge Count Overflow Interrupt Register	*/
-#define HMDMA0_ECOUNT		0xFFC03314	/* HMDMA0 Current Edge Count Register				*/
-#define HMDMA0_BCOUNT		0xFFC03318	/* HMDMA0 Current Block Count Register				*/
-
-#define HMDMA1_CONTROL		0xFFC03340	/* Handshake MDMA1 Control Register					*/
-#define HMDMA1_ECINIT		0xFFC03344	/* HMDMA1 Initial Edge Count Register				*/
-#define HMDMA1_BCINIT		0xFFC03348	/* HMDMA1 Initial Block Count Register				*/
-#define HMDMA1_ECURGENT		0xFFC0334C	/* HMDMA1 Urgent Edge Count Threshold Register		*/
-#define HMDMA1_ECOVERFLOW	0xFFC03350	/* HMDMA1 Edge Count Overflow Interrupt Register	*/
-#define HMDMA1_ECOUNT		0xFFC03354	/* HMDMA1 Current Edge Count Register				*/
-#define HMDMA1_BCOUNT		0xFFC03358	/* HMDMA1 Current Block Count Register				*/
-
-/* GPIO PIN mux (0xFFC03210 - OxFFC03288) */
-#define PORTF_MUX               0xFFC03210      /* Port F mux control */
-#define PORTG_MUX               0xFFC03214      /* Port G mux control */
-#define PORTH_MUX               0xFFC03218      /* Port H mux control */
-#define PORTF_DRIVE             0xFFC03220      /* Port F drive strength control */
-#define PORTG_DRIVE             0xFFC03224      /* Port G drive strength control */
-#define PORTH_DRIVE             0xFFC03228      /* Port H drive strength control */
-#define PORTF_SLEW              0xFFC03230      /* Port F slew control */
-#define PORTG_SLEW              0xFFC03234      /* Port G slew control */
-#define PORTH_SLEW              0xFFC03238      /* Port H slew control */
-#define PORTF_HYSTERISIS        0xFFC03240      /* Port F Schmitt trigger control */
-#define PORTG_HYSTERISIS        0xFFC03244      /* Port G Schmitt trigger control */
-#define PORTH_HYSTERISIS        0xFFC03248      /* Port H Schmitt trigger control */
-#define MISCPORT_DRIVE          0xFFC03280      /* Misc Port drive strength control */
-#define MISCPORT_SLEW           0xFFC03284      /* Misc Port slew control */
-#define MISCPORT_HYSTERISIS     0xFFC03288      /* Misc Port Schmitt trigger control */
-
-
-/***********************************************************************************
-** System MMR Register Bits And Macros
-**
-** Disclaimer:	All macros are intended to make C and Assembly code more readable.
-**				Use these macros carefully, as any that do left shifts for field
-**				depositing will result in the lower order bits being destroyed.  Any
-**				macro that shifts left to properly position the bit-field should be
-**				used as part of an OR to initialize a register and NOT as a dynamic
-**				modifier UNLESS the lower order bits are saved and ORed back in when
-**				the macro is used.
-*************************************************************************************/
-
-/* CHIPID Masks */
-#define CHIPID_VERSION         0xF0000000
-#define CHIPID_FAMILY          0x0FFFF000
-#define CHIPID_MANUFACTURE     0x00000FFE
-
-/* SWRST Masks																		*/
-#define SYSTEM_RESET		0x0007	/* Initiates A System Software Reset			*/
-#define	DOUBLE_FAULT		0x0008	/* Core Double Fault Causes Reset				*/
-#define RESET_DOUBLE		0x2000	/* SW Reset Generated By Core Double-Fault		*/
-#define RESET_WDOG			0x4000	/* SW Reset Generated By Watchdog Timer			*/
-#define RESET_SOFTWARE		0x8000	/* SW Reset Occurred Since Last Read Of SWRST	*/
-
-/* SYSCR Masks																				*/
-#define BMODE				0x0007	/* Boot Mode - Latched During HW Reset From Mode Pins	*/
-#define	NOBOOT				0x0010	/* Execute From L1 or ASYNC Bank 0 When BMODE = 0		*/
-
-
-/* *************  SYSTEM INTERRUPT CONTROLLER MASKS *************************************/
-/* Peripheral Masks For SIC_ISR, SIC_IWR, SIC_IMASK										*/
-
-#if 0
-#define IRQ_PLL_WAKEUP	0x00000001	/* PLL Wakeup Interrupt			 					*/
-
-#define IRQ_ERROR1      0x00000002  /* Error Interrupt (DMA, DMARx Block, DMARx Overflow) */
-#define IRQ_ERROR2      0x00000004  /* Error Interrupt (CAN, Ethernet, SPORTx, PPI, SPI, UARTx) */
-#define IRQ_RTC			0x00000008	/* Real Time Clock Interrupt 						*/
-#define IRQ_DMA0		0x00000010	/* DMA Channel 0 (PPI) Interrupt 					*/
-#define IRQ_DMA3		0x00000020	/* DMA Channel 3 (SPORT0 RX) Interrupt 				*/
-#define IRQ_DMA4		0x00000040	/* DMA Channel 4 (SPORT0 TX) Interrupt 				*/
-#define IRQ_DMA5		0x00000080	/* DMA Channel 5 (SPORT1 RX) Interrupt 				*/
-
-#define IRQ_DMA6		0x00000100	/* DMA Channel 6 (SPORT1 TX) Interrupt 		 		*/
-#define IRQ_TWI			0x00000200	/* TWI Interrupt									*/
-#define IRQ_DMA7		0x00000400	/* DMA Channel 7 (SPI) Interrupt 					*/
-#define IRQ_DMA8		0x00000800	/* DMA Channel 8 (UART0 RX) Interrupt 				*/
-#define IRQ_DMA9		0x00001000	/* DMA Channel 9 (UART0 TX) Interrupt 				*/
-#define IRQ_DMA10		0x00002000	/* DMA Channel 10 (UART1 RX) Interrupt 				*/
-#define IRQ_DMA11		0x00004000	/* DMA Channel 11 (UART1 TX) Interrupt 				*/
-#define IRQ_CAN_RX		0x00008000	/* CAN Receive Interrupt 							*/
-
-#define IRQ_CAN_TX		0x00010000	/* CAN Transmit Interrupt  							*/
-#define IRQ_DMA1		0x00020000	/* DMA Channel 1 (Ethernet RX) Interrupt 			*/
-#define IRQ_PFA_PORTH	0x00020000	/* PF Port H (PF47:32) Interrupt A 					*/
-#define IRQ_DMA2		0x00040000	/* DMA Channel 2 (Ethernet TX) Interrupt 			*/
-#define IRQ_PFB_PORTH	0x00040000	/* PF Port H (PF47:32) Interrupt B 					*/
-#define IRQ_TIMER0		0x00080000	/* Timer 0 Interrupt								*/
-#define IRQ_TIMER1		0x00100000	/* Timer 1 Interrupt 								*/
-#define IRQ_TIMER2		0x00200000	/* Timer 2 Interrupt 								*/
-#define IRQ_TIMER3		0x00400000	/* Timer 3 Interrupt 								*/
-#define IRQ_TIMER4		0x00800000	/* Timer 4 Interrupt 								*/
-
-#define IRQ_TIMER5		0x01000000	/* Timer 5 Interrupt 								*/
-#define IRQ_TIMER6		0x02000000	/* Timer 6 Interrupt 								*/
-#define IRQ_TIMER7		0x04000000	/* Timer 7 Interrupt 								*/
-#define IRQ_PFA_PORTFG	0x08000000	/* PF Ports F&G (PF31:0) Interrupt A 				*/
-#define IRQ_PFB_PORTF	0x80000000	/* PF Port F (PF15:0) Interrupt B 					*/
-#define IRQ_DMA12		0x20000000	/* DMA Channels 12 (MDMA1 Source) RX Interrupt 		*/
-#define IRQ_DMA13		0x20000000	/* DMA Channels 13 (MDMA1 Destination) TX Interrupt */
-#define IRQ_DMA14		0x40000000	/* DMA Channels 14 (MDMA0 Source) RX Interrupt 		*/
-#define IRQ_DMA15		0x40000000	/* DMA Channels 15 (MDMA0 Destination) TX Interrupt */
-#define IRQ_WDOG		0x80000000	/* Software Watchdog Timer Interrupt 				*/
-#define IRQ_PFB_PORTG	0x10000000	/* PF Port G (PF31:16) Interrupt B 					*/
-#endif
-
-/* SIC_IAR0 Macros															*/
-#define P0_IVG(x)		(((x)&0xF)-7)			/* Peripheral #0 assigned IVG #x 	*/
-#define P1_IVG(x)		(((x)&0xF)-7) << 0x4	/* Peripheral #1 assigned IVG #x 	*/
-#define P2_IVG(x)		(((x)&0xF)-7) << 0x8	/* Peripheral #2 assigned IVG #x 	*/
-#define P3_IVG(x)		(((x)&0xF)-7) << 0xC	/* Peripheral #3 assigned IVG #x	*/
-#define P4_IVG(x)		(((x)&0xF)-7) << 0x10	/* Peripheral #4 assigned IVG #x	*/
-#define P5_IVG(x)		(((x)&0xF)-7) << 0x14	/* Peripheral #5 assigned IVG #x	*/
-#define P6_IVG(x)		(((x)&0xF)-7) << 0x18	/* Peripheral #6 assigned IVG #x	*/
-#define P7_IVG(x)		(((x)&0xF)-7) << 0x1C	/* Peripheral #7 assigned IVG #x	*/
-
-/* SIC_IAR1 Macros															*/
-#define P8_IVG(x)		(((x)&0xF)-7)			/* Peripheral #8 assigned IVG #x 	*/
-#define P9_IVG(x)		(((x)&0xF)-7) << 0x4	/* Peripheral #9 assigned IVG #x 	*/
-#define P10_IVG(x)		(((x)&0xF)-7) << 0x8	/* Peripheral #10 assigned IVG #x	*/
-#define P11_IVG(x)		(((x)&0xF)-7) << 0xC	/* Peripheral #11 assigned IVG #x 	*/
-#define P12_IVG(x)		(((x)&0xF)-7) << 0x10	/* Peripheral #12 assigned IVG #x	*/
-#define P13_IVG(x)		(((x)&0xF)-7) << 0x14	/* Peripheral #13 assigned IVG #x	*/
-#define P14_IVG(x)		(((x)&0xF)-7) << 0x18	/* Peripheral #14 assigned IVG #x	*/
-#define P15_IVG(x)		(((x)&0xF)-7) << 0x1C	/* Peripheral #15 assigned IVG #x	*/
-
-/* SIC_IAR2 Macros															*/
-#define P16_IVG(x)		(((x)&0xF)-7)			/* Peripheral #16 assigned IVG #x	*/
-#define P17_IVG(x)		(((x)&0xF)-7) << 0x4	/* Peripheral #17 assigned IVG #x	*/
-#define P18_IVG(x)		(((x)&0xF)-7) << 0x8	/* Peripheral #18 assigned IVG #x	*/
-#define P19_IVG(x)		(((x)&0xF)-7) << 0xC	/* Peripheral #19 assigned IVG #x	*/
-#define P20_IVG(x)		(((x)&0xF)-7) << 0x10	/* Peripheral #20 assigned IVG #x	*/
-#define P21_IVG(x)		(((x)&0xF)-7) << 0x14	/* Peripheral #21 assigned IVG #x	*/
-#define P22_IVG(x)		(((x)&0xF)-7) << 0x18	/* Peripheral #22 assigned IVG #x	*/
-#define P23_IVG(x)		(((x)&0xF)-7) << 0x1C	/* Peripheral #23 assigned IVG #x	*/
-
-/* SIC_IAR3 Macros															*/
-#define P24_IVG(x)		(((x)&0xF)-7)			/* Peripheral #24 assigned IVG #x	*/
-#define P25_IVG(x)		(((x)&0xF)-7) << 0x4	/* Peripheral #25 assigned IVG #x	*/
-#define P26_IVG(x)		(((x)&0xF)-7) << 0x8	/* Peripheral #26 assigned IVG #x	*/
-#define P27_IVG(x)		(((x)&0xF)-7) << 0xC	/* Peripheral #27 assigned IVG #x	*/
-#define P28_IVG(x)		(((x)&0xF)-7) << 0x10	/* Peripheral #28 assigned IVG #x	*/
-#define P29_IVG(x)		(((x)&0xF)-7) << 0x14	/* Peripheral #29 assigned IVG #x	*/
-#define P30_IVG(x)		(((x)&0xF)-7) << 0x18	/* Peripheral #30 assigned IVG #x	*/
-#define P31_IVG(x)		(((x)&0xF)-7) << 0x1C	/* Peripheral #31 assigned IVG #x	*/
-
-
-/* SIC_IMASK Masks																		*/
-#define SIC_UNMASK_ALL	0x00000000					/* Unmask all peripheral interrupts	*/
-#define SIC_MASK_ALL	0xFFFFFFFF					/* Mask all peripheral interrupts	*/
-#define SIC_MASK(x)		(1 << ((x)&0x1F))					/* Mask Peripheral #x interrupt		*/
-#define SIC_UNMASK(x)	(0xFFFFFFFF ^ (1 << ((x)&0x1F)))	/* Unmask Peripheral #x interrupt	*/
-
-/* SIC_IWR Masks																		*/
-#define IWR_DISABLE_ALL	0x00000000					/* Wakeup Disable all peripherals	*/
-#define IWR_ENABLE_ALL	0xFFFFFFFF					/* Wakeup Enable all peripherals	*/
-#define IWR_ENABLE(x)	(1 << ((x)&0x1F))					/* Wakeup Enable Peripheral #x		*/
-#define IWR_DISABLE(x)	(0xFFFFFFFF ^ (1 << ((x)&0x1F))) 	/* Wakeup Disable Peripheral #x		*/
-
-
-/* ************** UART CONTROLLER MASKS *************************/
-/* UARTx_LCR Masks												*/
-#define WLS(x)		(((x)-5) & 0x03)	/* Word Length Select */
-#define STB			0x04				/* Stop Bits			*/
-#define PEN			0x08				/* Parity Enable		*/
-#define EPS			0x10				/* Even Parity Select	*/
-#define STP			0x20				/* Stick Parity			*/
-#define SB			0x40				/* Set Break			*/
-#define DLAB		0x80				/* Divisor Latch Access	*/
-
-/* UARTx_MCR Mask										*/
-#define LOOP_ENA	0x10	/* Loopback Mode Enable */
-#define LOOP_ENA_P	0x04
-
-/* UARTx_LSR Masks										*/
-#define DR			0x01	/* Data Ready				*/
-#define OE			0x02	/* Overrun Error			*/
-#define PE			0x04	/* Parity Error				*/
-#define FE			0x08	/* Framing Error			*/
-#define BI			0x10	/* Break Interrupt			*/
-#define THRE		0x20	/* THR Empty				*/
-#define TEMT		0x40	/* TSR and UART_THR Empty	*/
-
-/* UARTx_IER Masks															*/
-#define ERBFI		0x01		/* Enable Receive Buffer Full Interrupt		*/
-#define ETBEI		0x02		/* Enable Transmit Buffer Empty Interrupt	*/
-#define ELSI		0x04		/* Enable RX Status Interrupt				*/
-
-/* UARTx_IIR Masks														*/
-#define NINT		0x01		/* Pending Interrupt					*/
-#define IIR_TX_READY    0x02		/* UART_THR empty                               */
-#define IIR_RX_READY    0x04		/* Receive data ready                           */
-#define IIR_LINE_CHANGE 0x06		/* Receive line status    			*/
-#define IIR_STATUS	0x06		/* Highest Priority Pending Interrupt	*/
-
-/* UARTx_GCTL Masks													*/
-#define UCEN		0x01		/* Enable UARTx Clocks				*/
-#define IREN		0x02		/* Enable IrDA Mode					*/
-#define TPOLC		0x04		/* IrDA TX Polarity Change			*/
-#define RPOLC		0x08		/* IrDA RX Polarity Change			*/
-#define FPE			0x10		/* Force Parity Error On Transmit	*/
-#define FFE			0x20		/* Force Framing Error On Transmit	*/
-
-
-/*  ****************  GENERAL PURPOSE TIMER MASKS  **********************/
-/* TIMER_ENABLE Masks													*/
-#define TIMEN0			0x0001		/* Enable Timer 0					*/
-#define TIMEN1			0x0002		/* Enable Timer 1					*/
-#define TIMEN2			0x0004		/* Enable Timer 2					*/
-#define TIMEN3			0x0008		/* Enable Timer 3					*/
-#define TIMEN4			0x0010		/* Enable Timer 4					*/
-#define TIMEN5			0x0020		/* Enable Timer 5					*/
-#define TIMEN6			0x0040		/* Enable Timer 6					*/
-#define TIMEN7			0x0080		/* Enable Timer 7					*/
-
-/* TIMER_DISABLE Masks													*/
-#define TIMDIS0			TIMEN0		/* Disable Timer 0					*/
-#define TIMDIS1			TIMEN1		/* Disable Timer 1					*/
-#define TIMDIS2			TIMEN2		/* Disable Timer 2					*/
-#define TIMDIS3			TIMEN3		/* Disable Timer 3					*/
-#define TIMDIS4			TIMEN4		/* Disable Timer 4					*/
-#define TIMDIS5			TIMEN5		/* Disable Timer 5					*/
-#define TIMDIS6			TIMEN6		/* Disable Timer 6					*/
-#define TIMDIS7			TIMEN7		/* Disable Timer 7					*/
-
-/* TIMER_STATUS Masks													*/
-#define TIMIL0			0x00000001	/* Timer 0 Interrupt				*/
-#define TIMIL1			0x00000002	/* Timer 1 Interrupt				*/
-#define TIMIL2			0x00000004	/* Timer 2 Interrupt				*/
-#define TIMIL3			0x00000008	/* Timer 3 Interrupt				*/
-#define TOVF_ERR0		0x00000010	/* Timer 0 Counter Overflow			*/
-#define TOVF_ERR1		0x00000020	/* Timer 1 Counter Overflow			*/
-#define TOVF_ERR2		0x00000040	/* Timer 2 Counter Overflow			*/
-#define TOVF_ERR3		0x00000080	/* Timer 3 Counter Overflow			*/
-#define TRUN0			0x00001000	/* Timer 0 Slave Enable Status		*/
-#define TRUN1			0x00002000	/* Timer 1 Slave Enable Status		*/
-#define TRUN2			0x00004000	/* Timer 2 Slave Enable Status		*/
-#define TRUN3			0x00008000	/* Timer 3 Slave Enable Status		*/
-#define TIMIL4			0x00010000	/* Timer 4 Interrupt				*/
-#define TIMIL5			0x00020000	/* Timer 5 Interrupt				*/
-#define TIMIL6			0x00040000	/* Timer 6 Interrupt				*/
-#define TIMIL7			0x00080000	/* Timer 7 Interrupt				*/
-#define TOVF_ERR4		0x00100000	/* Timer 4 Counter Overflow			*/
-#define TOVF_ERR5		0x00200000	/* Timer 5 Counter Overflow			*/
-#define TOVF_ERR6		0x00400000	/* Timer 6 Counter Overflow			*/
-#define TOVF_ERR7		0x00800000	/* Timer 7 Counter Overflow			*/
-#define TRUN4			0x10000000	/* Timer 4 Slave Enable Status		*/
-#define TRUN5			0x20000000	/* Timer 5 Slave Enable Status		*/
-#define TRUN6			0x40000000	/* Timer 6 Slave Enable Status		*/
-#define TRUN7			0x80000000	/* Timer 7 Slave Enable Status		*/
-
-/* Alternate Deprecated Macros Provided For Backwards Code Compatibility */
-#define TOVL_ERR0 TOVF_ERR0
-#define TOVL_ERR1 TOVF_ERR1
-#define TOVL_ERR2 TOVF_ERR2
-#define TOVL_ERR3 TOVF_ERR3
-#define TOVL_ERR4 TOVF_ERR4
-#define TOVL_ERR5 TOVF_ERR5
-#define TOVL_ERR6 TOVF_ERR6
-#define TOVL_ERR7 TOVF_ERR7
-
-/* TIMERx_CONFIG Masks													*/
-#define PWM_OUT			0x0001	/* Pulse-Width Modulation Output Mode	*/
-#define WDTH_CAP		0x0002	/* Width Capture Input Mode				*/
-#define EXT_CLK			0x0003	/* External Clock Mode					*/
-#define PULSE_HI		0x0004	/* Action Pulse (Positive/Negative*)	*/
-#define PERIOD_CNT		0x0008	/* Period Count							*/
-#define IRQ_ENA			0x0010	/* Interrupt Request Enable				*/
-#define TIN_SEL			0x0020	/* Timer Input Select					*/
-#define OUT_DIS			0x0040	/* Output Pad Disable					*/
-#define CLK_SEL			0x0080	/* Timer Clock Select					*/
-#define TOGGLE_HI		0x0100	/* PWM_OUT PULSE_HI Toggle Mode			*/
-#define EMU_RUN			0x0200	/* Emulation Behavior Select			*/
-#define ERR_TYP			0xC000	/* Error Type							*/
-
-
-/* ******************   GPIO PORTS F, G, H MASKS  ***********************/
-/*  General Purpose IO (0xFFC00700 - 0xFFC007FF)  Masks 				*/
-/* Port F Masks 														*/
-#define PF0		0x0001
-#define PF1		0x0002
-#define PF2		0x0004
-#define PF3		0x0008
-#define PF4		0x0010
-#define PF5		0x0020
-#define PF6		0x0040
-#define PF7		0x0080
-#define PF8		0x0100
-#define PF9		0x0200
-#define PF10	0x0400
-#define PF11	0x0800
-#define PF12	0x1000
-#define PF13	0x2000
-#define PF14	0x4000
-#define PF15	0x8000
-
-/* Port G Masks															*/
-#define PG0		0x0001
-#define PG1		0x0002
-#define PG2		0x0004
-#define PG3		0x0008
-#define PG4		0x0010
-#define PG5		0x0020
-#define PG6		0x0040
-#define PG7		0x0080
-#define PG8		0x0100
-#define PG9		0x0200
-#define PG10	0x0400
-#define PG11	0x0800
-#define PG12	0x1000
-#define PG13	0x2000
-#define PG14	0x4000
-#define PG15	0x8000
-
-/* Port H Masks															*/
-#define PH0		0x0001
-#define PH1		0x0002
-#define PH2		0x0004
-#define PH3		0x0008
-#define PH4		0x0010
-#define PH5		0x0020
-#define PH6		0x0040
-#define PH7		0x0080
-#define PH8		0x0100
-#define PH9		0x0200
-#define PH10	0x0400
-#define PH11	0x0800
-#define PH12	0x1000
-#define PH13	0x2000
-#define PH14	0x4000
-#define PH15	0x8000
-
-/* *********************  ASYNCHRONOUS MEMORY CONTROLLER MASKS  *************************/
-/* EBIU_AMGCTL Masks																	*/
-#define AMCKEN			0x0001		/* Enable CLKOUT									*/
-#define	AMBEN_NONE		0x0000		/* All Banks Disabled								*/
-#define AMBEN_B0		0x0002		/* Enable Async Memory Bank 0 only					*/
-#define AMBEN_B0_B1		0x0004		/* Enable Async Memory Banks 0 & 1 only				*/
-#define AMBEN_B0_B1_B2	0x0006		/* Enable Async Memory Banks 0, 1, and 2			*/
-#define AMBEN_ALL		0x0008		/* Enable Async Memory Banks (all) 0, 1, 2, and 3	*/
-
-/* EBIU_AMBCTL0 Masks																	*/
-#define B0RDYEN			0x00000001  /* Bank 0 (B0) RDY Enable							*/
-#define B0RDYPOL		0x00000002  /* B0 RDY Active High								*/
-#define B0TT_1			0x00000004  /* B0 Transition Time (Read to Write) = 1 cycle		*/
-#define B0TT_2			0x00000008  /* B0 Transition Time (Read to Write) = 2 cycles	*/
-#define B0TT_3			0x0000000C  /* B0 Transition Time (Read to Write) = 3 cycles	*/
-#define B0TT_4			0x00000000  /* B0 Transition Time (Read to Write) = 4 cycles	*/
-#define B0ST_1			0x00000010  /* B0 Setup Time (AOE to Read/Write) = 1 cycle		*/
-#define B0ST_2			0x00000020  /* B0 Setup Time (AOE to Read/Write) = 2 cycles		*/
-#define B0ST_3			0x00000030  /* B0 Setup Time (AOE to Read/Write) = 3 cycles		*/
-#define B0ST_4			0x00000000  /* B0 Setup Time (AOE to Read/Write) = 4 cycles		*/
-#define B0HT_1			0x00000040  /* B0 Hold Time (~Read/Write to ~AOE) = 1 cycle		*/
-#define B0HT_2			0x00000080  /* B0 Hold Time (~Read/Write to ~AOE) = 2 cycles	*/
-#define B0HT_3			0x000000C0  /* B0 Hold Time (~Read/Write to ~AOE) = 3 cycles	*/
-#define B0HT_0			0x00000000  /* B0 Hold Time (~Read/Write to ~AOE) = 0 cycles	*/
-#define B0RAT_1			0x00000100  /* B0 Read Access Time = 1 cycle					*/
-#define B0RAT_2			0x00000200  /* B0 Read Access Time = 2 cycles					*/
-#define B0RAT_3			0x00000300  /* B0 Read Access Time = 3 cycles					*/
-#define B0RAT_4			0x00000400  /* B0 Read Access Time = 4 cycles					*/
-#define B0RAT_5			0x00000500  /* B0 Read Access Time = 5 cycles					*/
-#define B0RAT_6			0x00000600  /* B0 Read Access Time = 6 cycles					*/
-#define B0RAT_7			0x00000700  /* B0 Read Access Time = 7 cycles					*/
-#define B0RAT_8			0x00000800  /* B0 Read Access Time = 8 cycles					*/
-#define B0RAT_9			0x00000900  /* B0 Read Access Time = 9 cycles					*/
-#define B0RAT_10		0x00000A00  /* B0 Read Access Time = 10 cycles					*/
-#define B0RAT_11		0x00000B00  /* B0 Read Access Time = 11 cycles					*/
-#define B0RAT_12		0x00000C00  /* B0 Read Access Time = 12 cycles					*/
-#define B0RAT_13		0x00000D00  /* B0 Read Access Time = 13 cycles					*/
-#define B0RAT_14		0x00000E00  /* B0 Read Access Time = 14 cycles					*/
-#define B0RAT_15		0x00000F00  /* B0 Read Access Time = 15 cycles					*/
-#define B0WAT_1			0x00001000  /* B0 Write Access Time = 1 cycle					*/
-#define B0WAT_2			0x00002000  /* B0 Write Access Time = 2 cycles					*/
-#define B0WAT_3			0x00003000  /* B0 Write Access Time = 3 cycles					*/
-#define B0WAT_4			0x00004000  /* B0 Write Access Time = 4 cycles					*/
-#define B0WAT_5			0x00005000  /* B0 Write Access Time = 5 cycles					*/
-#define B0WAT_6			0x00006000  /* B0 Write Access Time = 6 cycles					*/
-#define B0WAT_7			0x00007000  /* B0 Write Access Time = 7 cycles					*/
-#define B0WAT_8			0x00008000  /* B0 Write Access Time = 8 cycles					*/
-#define B0WAT_9			0x00009000  /* B0 Write Access Time = 9 cycles					*/
-#define B0WAT_10		0x0000A000  /* B0 Write Access Time = 10 cycles					*/
-#define B0WAT_11		0x0000B000  /* B0 Write Access Time = 11 cycles					*/
-#define B0WAT_12		0x0000C000  /* B0 Write Access Time = 12 cycles					*/
-#define B0WAT_13		0x0000D000  /* B0 Write Access Time = 13 cycles					*/
-#define B0WAT_14		0x0000E000  /* B0 Write Access Time = 14 cycles					*/
-#define B0WAT_15		0x0000F000  /* B0 Write Access Time = 15 cycles					*/
-
-#define B1RDYEN			0x00010000  /* Bank 1 (B1) RDY Enable                       	*/
-#define B1RDYPOL		0x00020000  /* B1 RDY Active High                           	*/
-#define B1TT_1			0x00040000  /* B1 Transition Time (Read to Write) = 1 cycle 	*/
-#define B1TT_2			0x00080000  /* B1 Transition Time (Read to Write) = 2 cycles	*/
-#define B1TT_3			0x000C0000  /* B1 Transition Time (Read to Write) = 3 cycles	*/
-#define B1TT_4			0x00000000  /* B1 Transition Time (Read to Write) = 4 cycles	*/
-#define B1ST_1			0x00100000  /* B1 Setup Time (AOE to Read/Write) = 1 cycle  	*/
-#define B1ST_2			0x00200000  /* B1 Setup Time (AOE to Read/Write) = 2 cycles 	*/
-#define B1ST_3			0x00300000  /* B1 Setup Time (AOE to Read/Write) = 3 cycles 	*/
-#define B1ST_4			0x00000000  /* B1 Setup Time (AOE to Read/Write) = 4 cycles 	*/
-#define B1HT_1			0x00400000  /* B1 Hold Time (~Read/Write to ~AOE) = 1 cycle 	*/
-#define B1HT_2			0x00800000  /* B1 Hold Time (~Read/Write to ~AOE) = 2 cycles	*/
-#define B1HT_3			0x00C00000  /* B1 Hold Time (~Read/Write to ~AOE) = 3 cycles	*/
-#define B1HT_0			0x00000000  /* B1 Hold Time (~Read/Write to ~AOE) = 0 cycles	*/
-#define B1RAT_1			0x01000000  /* B1 Read Access Time = 1 cycle					*/
-#define B1RAT_2			0x02000000  /* B1 Read Access Time = 2 cycles					*/
-#define B1RAT_3			0x03000000  /* B1 Read Access Time = 3 cycles					*/
-#define B1RAT_4			0x04000000  /* B1 Read Access Time = 4 cycles					*/
-#define B1RAT_5			0x05000000  /* B1 Read Access Time = 5 cycles					*/
-#define B1RAT_6			0x06000000  /* B1 Read Access Time = 6 cycles					*/
-#define B1RAT_7			0x07000000  /* B1 Read Access Time = 7 cycles					*/
-#define B1RAT_8			0x08000000  /* B1 Read Access Time = 8 cycles					*/
-#define B1RAT_9			0x09000000  /* B1 Read Access Time = 9 cycles					*/
-#define B1RAT_10		0x0A000000  /* B1 Read Access Time = 10 cycles					*/
-#define B1RAT_11		0x0B000000  /* B1 Read Access Time = 11 cycles					*/
-#define B1RAT_12		0x0C000000  /* B1 Read Access Time = 12 cycles					*/
-#define B1RAT_13		0x0D000000  /* B1 Read Access Time = 13 cycles					*/
-#define B1RAT_14		0x0E000000  /* B1 Read Access Time = 14 cycles					*/
-#define B1RAT_15		0x0F000000  /* B1 Read Access Time = 15 cycles					*/
-#define B1WAT_1			0x10000000  /* B1 Write Access Time = 1 cycle					*/
-#define B1WAT_2			0x20000000  /* B1 Write Access Time = 2 cycles					*/
-#define B1WAT_3			0x30000000  /* B1 Write Access Time = 3 cycles					*/
-#define B1WAT_4			0x40000000  /* B1 Write Access Time = 4 cycles					*/
-#define B1WAT_5			0x50000000  /* B1 Write Access Time = 5 cycles					*/
-#define B1WAT_6			0x60000000  /* B1 Write Access Time = 6 cycles					*/
-#define B1WAT_7			0x70000000  /* B1 Write Access Time = 7 cycles					*/
-#define B1WAT_8			0x80000000  /* B1 Write Access Time = 8 cycles					*/
-#define B1WAT_9			0x90000000  /* B1 Write Access Time = 9 cycles					*/
-#define B1WAT_10		0xA0000000  /* B1 Write Access Time = 10 cycles					*/
-#define B1WAT_11		0xB0000000  /* B1 Write Access Time = 11 cycles					*/
-#define B1WAT_12		0xC0000000  /* B1 Write Access Time = 12 cycles					*/
-#define B1WAT_13		0xD0000000  /* B1 Write Access Time = 13 cycles					*/
-#define B1WAT_14		0xE0000000  /* B1 Write Access Time = 14 cycles					*/
-#define B1WAT_15		0xF0000000  /* B1 Write Access Time = 15 cycles					*/
-
-/* EBIU_AMBCTL1 Masks																	*/
-#define B2RDYEN			0x00000001  /* Bank 2 (B2) RDY Enable							*/
-#define B2RDYPOL		0x00000002  /* B2 RDY Active High								*/
-#define B2TT_1			0x00000004  /* B2 Transition Time (Read to Write) = 1 cycle		*/
-#define B2TT_2			0x00000008  /* B2 Transition Time (Read to Write) = 2 cycles	*/
-#define B2TT_3			0x0000000C  /* B2 Transition Time (Read to Write) = 3 cycles	*/
-#define B2TT_4			0x00000000  /* B2 Transition Time (Read to Write) = 4 cycles	*/
-#define B2ST_1			0x00000010  /* B2 Setup Time (AOE to Read/Write) = 1 cycle		*/
-#define B2ST_2			0x00000020  /* B2 Setup Time (AOE to Read/Write) = 2 cycles		*/
-#define B2ST_3			0x00000030  /* B2 Setup Time (AOE to Read/Write) = 3 cycles		*/
-#define B2ST_4			0x00000000  /* B2 Setup Time (AOE to Read/Write) = 4 cycles		*/
-#define B2HT_1			0x00000040  /* B2 Hold Time (~Read/Write to ~AOE) = 1 cycle		*/
-#define B2HT_2			0x00000080  /* B2 Hold Time (~Read/Write to ~AOE) = 2 cycles	*/
-#define B2HT_3			0x000000C0  /* B2 Hold Time (~Read/Write to ~AOE) = 3 cycles	*/
-#define B2HT_0			0x00000000  /* B2 Hold Time (~Read/Write to ~AOE) = 0 cycles	*/
-#define B2RAT_1			0x00000100  /* B2 Read Access Time = 1 cycle					*/
-#define B2RAT_2			0x00000200  /* B2 Read Access Time = 2 cycles					*/
-#define B2RAT_3			0x00000300  /* B2 Read Access Time = 3 cycles					*/
-#define B2RAT_4			0x00000400  /* B2 Read Access Time = 4 cycles					*/
-#define B2RAT_5			0x00000500  /* B2 Read Access Time = 5 cycles					*/
-#define B2RAT_6			0x00000600  /* B2 Read Access Time = 6 cycles					*/
-#define B2RAT_7			0x00000700  /* B2 Read Access Time = 7 cycles					*/
-#define B2RAT_8			0x00000800  /* B2 Read Access Time = 8 cycles					*/
-#define B2RAT_9			0x00000900  /* B2 Read Access Time = 9 cycles					*/
-#define B2RAT_10		0x00000A00  /* B2 Read Access Time = 10 cycles					*/
-#define B2RAT_11		0x00000B00  /* B2 Read Access Time = 11 cycles					*/
-#define B2RAT_12		0x00000C00  /* B2 Read Access Time = 12 cycles					*/
-#define B2RAT_13		0x00000D00  /* B2 Read Access Time = 13 cycles					*/
-#define B2RAT_14		0x00000E00  /* B2 Read Access Time = 14 cycles					*/
-#define B2RAT_15		0x00000F00  /* B2 Read Access Time = 15 cycles					*/
-#define B2WAT_1			0x00001000  /* B2 Write Access Time = 1 cycle					*/
-#define B2WAT_2			0x00002000  /* B2 Write Access Time = 2 cycles					*/
-#define B2WAT_3			0x00003000  /* B2 Write Access Time = 3 cycles					*/
-#define B2WAT_4			0x00004000  /* B2 Write Access Time = 4 cycles					*/
-#define B2WAT_5			0x00005000  /* B2 Write Access Time = 5 cycles					*/
-#define B2WAT_6			0x00006000  /* B2 Write Access Time = 6 cycles					*/
-#define B2WAT_7			0x00007000  /* B2 Write Access Time = 7 cycles					*/
-#define B2WAT_8			0x00008000  /* B2 Write Access Time = 8 cycles					*/
-#define B2WAT_9			0x00009000  /* B2 Write Access Time = 9 cycles					*/
-#define B2WAT_10		0x0000A000  /* B2 Write Access Time = 10 cycles					*/
-#define B2WAT_11		0x0000B000  /* B2 Write Access Time = 11 cycles					*/
-#define B2WAT_12		0x0000C000  /* B2 Write Access Time = 12 cycles					*/
-#define B2WAT_13		0x0000D000  /* B2 Write Access Time = 13 cycles					*/
-#define B2WAT_14		0x0000E000  /* B2 Write Access Time = 14 cycles					*/
-#define B2WAT_15		0x0000F000  /* B2 Write Access Time = 15 cycles					*/
-
-#define B3RDYEN			0x00010000  /* Bank 3 (B3) RDY Enable							*/
-#define B3RDYPOL		0x00020000  /* B3 RDY Active High								*/
-#define B3TT_1			0x00040000  /* B3 Transition Time (Read to Write) = 1 cycle		*/
-#define B3TT_2			0x00080000  /* B3 Transition Time (Read to Write) = 2 cycles	*/
-#define B3TT_3			0x000C0000  /* B3 Transition Time (Read to Write) = 3 cycles	*/
-#define B3TT_4			0x00000000  /* B3 Transition Time (Read to Write) = 4 cycles	*/
-#define B3ST_1			0x00100000  /* B3 Setup Time (AOE to Read/Write) = 1 cycle		*/
-#define B3ST_2			0x00200000  /* B3 Setup Time (AOE to Read/Write) = 2 cycles		*/
-#define B3ST_3			0x00300000  /* B3 Setup Time (AOE to Read/Write) = 3 cycles		*/
-#define B3ST_4			0x00000000  /* B3 Setup Time (AOE to Read/Write) = 4 cycles		*/
-#define B3HT_1			0x00400000  /* B3 Hold Time (~Read/Write to ~AOE) = 1 cycle		*/
-#define B3HT_2			0x00800000  /* B3 Hold Time (~Read/Write to ~AOE) = 2 cycles	*/
-#define B3HT_3			0x00C00000  /* B3 Hold Time (~Read/Write to ~AOE) = 3 cycles	*/
-#define B3HT_0			0x00000000  /* B3 Hold Time (~Read/Write to ~AOE) = 0 cycles	*/
-#define B3RAT_1			0x01000000  /* B3 Read Access Time = 1 cycle					*/
-#define B3RAT_2			0x02000000  /* B3 Read Access Time = 2 cycles					*/
-#define B3RAT_3			0x03000000  /* B3 Read Access Time = 3 cycles					*/
-#define B3RAT_4			0x04000000  /* B3 Read Access Time = 4 cycles					*/
-#define B3RAT_5			0x05000000  /* B3 Read Access Time = 5 cycles					*/
-#define B3RAT_6			0x06000000  /* B3 Read Access Time = 6 cycles					*/
-#define B3RAT_7			0x07000000  /* B3 Read Access Time = 7 cycles					*/
-#define B3RAT_8			0x08000000  /* B3 Read Access Time = 8 cycles					*/
-#define B3RAT_9			0x09000000  /* B3 Read Access Time = 9 cycles					*/
-#define B3RAT_10		0x0A000000  /* B3 Read Access Time = 10 cycles					*/
-#define B3RAT_11		0x0B000000  /* B3 Read Access Time = 11 cycles					*/
-#define B3RAT_12		0x0C000000  /* B3 Read Access Time = 12 cycles					*/
-#define B3RAT_13		0x0D000000  /* B3 Read Access Time = 13 cycles					*/
-#define B3RAT_14		0x0E000000  /* B3 Read Access Time = 14 cycles					*/
-#define B3RAT_15		0x0F000000  /* B3 Read Access Time = 15 cycles					*/
-#define B3WAT_1			0x10000000  /* B3 Write Access Time = 1 cycle					*/
-#define B3WAT_2			0x20000000  /* B3 Write Access Time = 2 cycles					*/
-#define B3WAT_3			0x30000000  /* B3 Write Access Time = 3 cycles					*/
-#define B3WAT_4			0x40000000  /* B3 Write Access Time = 4 cycles					*/
-#define B3WAT_5			0x50000000  /* B3 Write Access Time = 5 cycles					*/
-#define B3WAT_6			0x60000000  /* B3 Write Access Time = 6 cycles					*/
-#define B3WAT_7			0x70000000  /* B3 Write Access Time = 7 cycles					*/
-#define B3WAT_8			0x80000000  /* B3 Write Access Time = 8 cycles					*/
-#define B3WAT_9			0x90000000  /* B3 Write Access Time = 9 cycles					*/
-#define B3WAT_10		0xA0000000  /* B3 Write Access Time = 10 cycles					*/
-#define B3WAT_11		0xB0000000  /* B3 Write Access Time = 11 cycles					*/
-#define B3WAT_12		0xC0000000  /* B3 Write Access Time = 12 cycles					*/
-#define B3WAT_13		0xD0000000  /* B3 Write Access Time = 13 cycles					*/
-#define B3WAT_14		0xE0000000  /* B3 Write Access Time = 14 cycles					*/
-#define B3WAT_15		0xF0000000  /* B3 Write Access Time = 15 cycles					*/
-
-
-/* **********************  SDRAM CONTROLLER MASKS  **********************************************/
-/* EBIU_SDGCTL Masks																			*/
-#define SCTLE			0x00000001	/* Enable SDRAM Signals										*/
-#define CL_2			0x00000008	/* SDRAM CAS Latency = 2 cycles								*/
-#define CL_3			0x0000000C	/* SDRAM CAS Latency = 3 cycles								*/
-#define PASR_ALL		0x00000000	/* All 4 SDRAM Banks Refreshed In Self-Refresh				*/
-#define PASR_B0_B1		0x00000010	/* SDRAM Banks 0 and 1 Are Refreshed In Self-Refresh		*/
-#define PASR_B0			0x00000020	/* Only SDRAM Bank 0 Is Refreshed In Self-Refresh			*/
-#define TRAS_1			0x00000040	/* SDRAM tRAS = 1 cycle										*/
-#define TRAS_2			0x00000080	/* SDRAM tRAS = 2 cycles									*/
-#define TRAS_3			0x000000C0	/* SDRAM tRAS = 3 cycles									*/
-#define TRAS_4			0x00000100	/* SDRAM tRAS = 4 cycles									*/
-#define TRAS_5			0x00000140	/* SDRAM tRAS = 5 cycles									*/
-#define TRAS_6			0x00000180	/* SDRAM tRAS = 6 cycles									*/
-#define TRAS_7			0x000001C0	/* SDRAM tRAS = 7 cycles									*/
-#define TRAS_8			0x00000200	/* SDRAM tRAS = 8 cycles									*/
-#define TRAS_9			0x00000240	/* SDRAM tRAS = 9 cycles									*/
-#define TRAS_10			0x00000280	/* SDRAM tRAS = 10 cycles									*/
-#define TRAS_11			0x000002C0	/* SDRAM tRAS = 11 cycles									*/
-#define TRAS_12			0x00000300	/* SDRAM tRAS = 12 cycles									*/
-#define TRAS_13			0x00000340	/* SDRAM tRAS = 13 cycles									*/
-#define TRAS_14			0x00000380	/* SDRAM tRAS = 14 cycles									*/
-#define TRAS_15			0x000003C0	/* SDRAM tRAS = 15 cycles									*/
-#define TRP_1			0x00000800	/* SDRAM tRP = 1 cycle										*/
-#define TRP_2			0x00001000	/* SDRAM tRP = 2 cycles										*/
-#define TRP_3			0x00001800	/* SDRAM tRP = 3 cycles										*/
-#define TRP_4			0x00002000	/* SDRAM tRP = 4 cycles										*/
-#define TRP_5			0x00002800	/* SDRAM tRP = 5 cycles										*/
-#define TRP_6			0x00003000	/* SDRAM tRP = 6 cycles										*/
-#define TRP_7			0x00003800	/* SDRAM tRP = 7 cycles										*/
-#define TRCD_1			0x00008000	/* SDRAM tRCD = 1 cycle										*/
-#define TRCD_2			0x00010000	/* SDRAM tRCD = 2 cycles									*/
-#define TRCD_3			0x00018000	/* SDRAM tRCD = 3 cycles									*/
-#define TRCD_4			0x00020000	/* SDRAM tRCD = 4 cycles									*/
-#define TRCD_5			0x00028000	/* SDRAM tRCD = 5 cycles									*/
-#define TRCD_6			0x00030000	/* SDRAM tRCD = 6 cycles									*/
-#define TRCD_7			0x00038000	/* SDRAM tRCD = 7 cycles									*/
-#define TWR_1			0x00080000	/* SDRAM tWR = 1 cycle										*/
-#define TWR_2			0x00100000	/* SDRAM tWR = 2 cycles										*/
-#define TWR_3			0x00180000	/* SDRAM tWR = 3 cycles										*/
-#define PUPSD			0x00200000	/* Power-Up Start Delay (15 SCLK Cycles Delay)				*/
-#define PSM				0x00400000	/* Power-Up Sequence (Mode Register Before/After* Refresh)	*/
-#define PSS				0x00800000	/* Enable Power-Up Sequence on Next SDRAM Access			*/
-#define SRFS			0x01000000	/* Enable SDRAM Self-Refresh Mode							*/
-#define EBUFE			0x02000000	/* Enable External Buffering Timing							*/
-#define FBBRW			0x04000000	/* Enable Fast Back-To-Back Read To Write					*/
-#define EMREN			0x10000000	/* Extended Mode Register Enable							*/
-#define TCSR			0x20000000	/* Temp-Compensated Self-Refresh Value (85/45* Deg C)		*/
-#define CDDBG			0x40000000	/* Tristate SDRAM Controls During Bus Grant					*/
-
-/* EBIU_SDBCTL Masks																		*/
-#define EBE				0x0001		/* Enable SDRAM External Bank							*/
-#define EBSZ_16			0x0000		/* SDRAM External Bank Size = 16MB	*/
-#define EBSZ_32			0x0002		/* SDRAM External Bank Size = 32MB	*/
-#define EBSZ_64			0x0004		/* SDRAM External Bank Size = 64MB	*/
-#define EBSZ_128		0x0006		/* SDRAM External Bank Size = 128MB		*/
-#define EBSZ_256		0x0008		/* SDRAM External Bank Size = 256MB 	*/
-#define EBSZ_512		0x000A		/* SDRAM External Bank Size = 512MB		*/
-#define EBCAW_8			0x0000		/* SDRAM External Bank Column Address Width = 8 Bits	*/
-#define EBCAW_9			0x0010		/* SDRAM External Bank Column Address Width = 9 Bits	*/
-#define EBCAW_10		0x0020		/* SDRAM External Bank Column Address Width = 10 Bits	*/
-#define EBCAW_11		0x0030		/* SDRAM External Bank Column Address Width = 11 Bits	*/
-
-/* EBIU_SDSTAT Masks														*/
-#define SDCI			0x0001		/* SDRAM Controller Idle 				*/
-#define SDSRA			0x0002		/* SDRAM Self-Refresh Active			*/
-#define SDPUA			0x0004		/* SDRAM Power-Up Active 				*/
-#define SDRS			0x0008		/* SDRAM Will Power-Up On Next Access	*/
-#define SDEASE			0x0010		/* SDRAM EAB Sticky Error Status		*/
-#define BGSTAT			0x0020		/* Bus Grant Status						*/
-
-
-/* **************************  DMA CONTROLLER MASKS  ********************************/
-
-/* DMAx_PERIPHERAL_MAP, MDMA_yy_PERIPHERAL_MAP Masks								*/
-#define CTYPE			0x0040	/* DMA Channel Type Indicator (Memory/Peripheral*)	*/
-#define PMAP			0xF000	/* Peripheral Mapped To This Channel				*/
-#define PMAP_PPI		0x0000	/* 		PPI Port DMA								*/
-#define	PMAP_EMACRX		0x1000	/* 		Ethernet Receive DMA						*/
-#define PMAP_EMACTX		0x2000	/* 		Ethernet Transmit DMA						*/
-#define PMAP_SPORT0RX	0x3000	/* 		SPORT0 Receive DMA							*/
-#define PMAP_SPORT0TX	0x4000	/* 		SPORT0 Transmit DMA							*/
-#define PMAP_SPORT1RX	0x5000	/* 		SPORT1 Receive DMA							*/
-#define PMAP_SPORT1TX	0x6000	/* 		SPORT1 Transmit DMA							*/
-#define PMAP_SPI		0x7000	/* 		SPI Port DMA								*/
-#define PMAP_UART0RX	0x8000	/* 		UART0 Port Receive DMA						*/
-#define PMAP_UART0TX	0x9000	/* 		UART0 Port Transmit DMA						*/
-#define	PMAP_UART1RX	0xA000	/* 		UART1 Port Receive DMA						*/
-#define	PMAP_UART1TX	0xB000	/* 		UART1 Port Transmit DMA						*/
-
-/*  ************  PARALLEL PERIPHERAL INTERFACE (PPI) MASKS *************/
-/*  PPI_CONTROL Masks													*/
-#define PORT_EN			0x0001		/* PPI Port Enable					*/
-#define PORT_DIR		0x0002		/* PPI Port Direction				*/
-#define XFR_TYPE		0x000C		/* PPI Transfer Type				*/
-#define PORT_CFG		0x0030		/* PPI Port Configuration			*/
-#define FLD_SEL			0x0040		/* PPI Active Field Select			*/
-#define PACK_EN			0x0080		/* PPI Packing Mode					*/
-#define DMA32			0x0100		/* PPI 32-bit DMA Enable			*/
-#define SKIP_EN			0x0200		/* PPI Skip Element Enable			*/
-#define SKIP_EO			0x0400		/* PPI Skip Even/Odd Elements		*/
-#define DLEN_8			0x0000		/* Data Length = 8 Bits				*/
-#define DLEN_10			0x0800		/* Data Length = 10 Bits			*/
-#define DLEN_11			0x1000		/* Data Length = 11 Bits			*/
-#define DLEN_12			0x1800		/* Data Length = 12 Bits			*/
-#define DLEN_13			0x2000		/* Data Length = 13 Bits			*/
-#define DLEN_14			0x2800		/* Data Length = 14 Bits			*/
-#define DLEN_15			0x3000		/* Data Length = 15 Bits			*/
-#define DLEN_16			0x3800		/* Data Length = 16 Bits			*/
-#define DLENGTH			0x3800		/* PPI Data Length  */
-#define POLC			0x4000		/* PPI Clock Polarity				*/
-#define POLS			0x8000		/* PPI Frame Sync Polarity			*/
-
-/* PPI_STATUS Masks														*/
-#define FLD				0x0400		/* Field Indicator					*/
-#define FT_ERR			0x0800		/* Frame Track Error				*/
-#define OVR				0x1000		/* FIFO Overflow Error				*/
-#define UNDR			0x2000		/* FIFO Underrun Error				*/
-#define ERR_DET			0x4000		/* Error Detected Indicator			*/
-#define ERR_NCOR		0x8000		/* Error Not Corrected Indicator	*/
-
-
-/*  ********************  TWO-WIRE INTERFACE (TWI) MASKS  ***********************/
-/* TWI_CLKDIV Macros (Use: *pTWI_CLKDIV = CLKLOW(x)|CLKHI(y);  )				*/
-#define	CLKLOW(x)	((x) & 0xFF)		/* Periods Clock Is Held Low			*/
-#define CLKHI(y)	(((y)&0xFF)<<0x8)	/* Periods Before New Clock Low			*/
-
-/* TWI_PRESCALE Masks															*/
-#define	PRESCALE	0x007F		/* SCLKs Per Internal Time Reference (10MHz)	*/
-#define	TWI_ENA		0x0080		/* TWI Enable									*/
-#define	SCCB		0x0200		/* SCCB Compatibility Enable					*/
-
-/* TWI_SLAVE_CTL Masks															*/
-#define	SEN			0x0001		/* Slave Enable									*/
-#define	SADD_LEN	0x0002		/* Slave Address Length							*/
-#define	STDVAL		0x0004		/* Slave Transmit Data Valid					*/
-#define	NAK			0x0008		/* NAK/ACK* Generated At Conclusion Of Transfer */
-#define	GEN			0x0010		/* General Call Adrress Matching Enabled		*/
-
-/* TWI_SLAVE_STAT Masks															*/
-#define	SDIR		0x0001		/* Slave Transfer Direction (Transmit/Receive*)	*/
-#define GCALL		0x0002		/* General Call Indicator						*/
-
-/* TWI_MASTER_CTL Masks													*/
-#define	MEN			0x0001		/* Master Mode Enable						*/
-#define	MADD_LEN	0x0002		/* Master Address Length					*/
-#define	MDIR		0x0004		/* Master Transmit Direction (RX/TX*)		*/
-#define	FAST		0x0008		/* Use Fast Mode Timing Specs				*/
-#define	STOP		0x0010		/* Issue Stop Condition						*/
-#define	RSTART		0x0020		/* Repeat Start or Stop* At End Of Transfer	*/
-#define	DCNT		0x3FC0		/* Data Bytes To Transfer					*/
-#define	SDAOVR		0x4000		/* Serial Data Override						*/
-#define	SCLOVR		0x8000		/* Serial Clock Override					*/
-
-/* TWI_MASTER_STAT Masks														*/
-#define	MPROG		0x0001		/* Master Transfer In Progress					*/
-#define	LOSTARB		0x0002		/* Lost Arbitration Indicator (Xfer Aborted)	*/
-#define	ANAK		0x0004		/* Address Not Acknowledged						*/
-#define	DNAK		0x0008		/* Data Not Acknowledged						*/
-#define	BUFRDERR	0x0010		/* Buffer Read Error							*/
-#define	BUFWRERR	0x0020		/* Buffer Write Error							*/
-#define	SDASEN		0x0040		/* Serial Data Sense							*/
-#define	SCLSEN		0x0080		/* Serial Clock Sense							*/
-#define	BUSBUSY		0x0100		/* Bus Busy Indicator							*/
-
-/* TWI_INT_SRC and TWI_INT_ENABLE Masks						*/
-#define	SINIT		0x0001		/* Slave Transfer Initiated	*/
-#define	SCOMP		0x0002		/* Slave Transfer Complete	*/
-#define	SERR		0x0004		/* Slave Transfer Error		*/
-#define	SOVF		0x0008		/* Slave Overflow			*/
-#define	MCOMP		0x0010		/* Master Transfer Complete	*/
-#define	MERR		0x0020		/* Master Transfer Error	*/
-#define	XMTSERV		0x0040		/* Transmit FIFO Service	*/
-#define	RCVSERV		0x0080		/* Receive FIFO Service		*/
-
-/* TWI_FIFO_CTRL Masks												*/
-#define	XMTFLUSH	0x0001		/* Transmit Buffer Flush			*/
-#define	RCVFLUSH	0x0002		/* Receive Buffer Flush				*/
-#define	XMTINTLEN	0x0004		/* Transmit Buffer Interrupt Length	*/
-#define	RCVINTLEN	0x0008		/* Receive Buffer Interrupt Length	*/
-
-/* TWI_FIFO_STAT Masks															*/
-#define	XMTSTAT		0x0003		/* Transmit FIFO Status							*/
-#define	XMT_EMPTY	0x0000		/* 		Transmit FIFO Empty						*/
-#define	XMT_HALF	0x0001		/* 		Transmit FIFO Has 1 Byte To Write		*/
-#define	XMT_FULL	0x0003		/* 		Transmit FIFO Full (2 Bytes To Write)	*/
-
-#define	RCVSTAT		0x000C		/* Receive FIFO Status							*/
-#define	RCV_EMPTY	0x0000		/* 		Receive FIFO Empty						*/
-#define	RCV_HALF	0x0004		/* 		Receive FIFO Has 1 Byte To Read			*/
-#define	RCV_FULL	0x000C		/* 		Receive FIFO Full (2 Bytes To Read)		*/
-
-
-/* Omit CAN masks from defBF534.h */
-
-/*  *******************  PIN CONTROL REGISTER MASKS  ************************/
-/* PORT_MUX Masks															*/
-#define	PJSE			0x0001			/* Port J SPI/SPORT Enable			*/
-#define	PJSE_SPORT		0x0000			/* 		Enable TFS0/DT0PRI			*/
-#define	PJSE_SPI		0x0001			/* 		Enable SPI_SSEL3:2			*/
-
-#define	PJCE(x)			(((x)&0x3)<<1)	/* Port J CAN/SPI/SPORT Enable		*/
-#define	PJCE_SPORT		0x0000			/* 		Enable DR0SEC/DT0SEC		*/
-#define	PJCE_CAN		0x0002			/* 		Enable CAN RX/TX			*/
-#define	PJCE_SPI		0x0004			/* 		Enable SPI_SSEL7			*/
-
-#define	PFDE			0x0008			/* Port F DMA Request Enable		*/
-#define	PFDE_UART		0x0000			/* 		Enable UART0 RX/TX			*/
-#define	PFDE_DMA		0x0008			/* 		Enable DMAR1:0				*/
-
-#define	PFTE			0x0010			/* Port F Timer Enable				*/
-#define	PFTE_UART		0x0000			/*		Enable UART1 RX/TX			*/
-#define	PFTE_TIMER		0x0010			/* 		Enable TMR7:6				*/
-
-#define	PFS6E			0x0020			/* Port F SPI SSEL 6 Enable			*/
-#define	PFS6E_TIMER		0x0000			/*		Enable TMR5					*/
-#define	PFS6E_SPI		0x0020			/* 		Enable SPI_SSEL6			*/
-
-#define	PFS5E			0x0040			/* Port F SPI SSEL 5 Enable			*/
-#define	PFS5E_TIMER		0x0000			/*		Enable TMR4					*/
-#define	PFS5E_SPI		0x0040			/* 		Enable SPI_SSEL5			*/
-
-#define	PFS4E			0x0080			/* Port F SPI SSEL 4 Enable			*/
-#define	PFS4E_TIMER		0x0000			/*		Enable TMR3					*/
-#define	PFS4E_SPI		0x0080			/* 		Enable SPI_SSEL4			*/
-
-#define	PFFE			0x0100			/* Port F PPI Frame Sync Enable		*/
-#define	PFFE_TIMER		0x0000			/* 		Enable TMR2					*/
-#define	PFFE_PPI		0x0100			/* 		Enable PPI FS3				*/
-
-#define	PGSE			0x0200			/* Port G SPORT1 Secondary Enable	*/
-#define	PGSE_PPI		0x0000			/* 		Enable PPI D9:8				*/
-#define	PGSE_SPORT		0x0200			/* 		Enable DR1SEC/DT1SEC		*/
-
-#define	PGRE			0x0400			/* Port G SPORT1 Receive Enable		*/
-#define	PGRE_PPI		0x0000			/* 		Enable PPI D12:10			*/
-#define	PGRE_SPORT		0x0400			/* 		Enable DR1PRI/RFS1/RSCLK1	*/
-
-#define	PGTE			0x0800			/* Port G SPORT1 Transmit Enable	*/
-#define	PGTE_PPI		0x0000			/* 		Enable PPI D15:13			*/
-#define	PGTE_SPORT		0x0800			/* 		Enable DT1PRI/TFS1/TSCLK1	*/
-
-
-/*  ******************  HANDSHAKE DMA (HDMA) MASKS  *********************/
-/* HDMAx_CTL Masks														*/
-#define	HMDMAEN		0x0001	/* Enable Handshake DMA 0/1					*/
-#define	REP			0x0002	/* HDMA Request Polarity					*/
-#define	UTE			0x0004	/* Urgency Threshold Enable					*/
-#define	OIE			0x0010	/* Overflow Interrupt Enable				*/
-#define	BDIE		0x0020	/* Block Done Interrupt Enable				*/
-#define	MBDI		0x0040	/* Mask Block Done IRQ If Pending ECNT		*/
-#define	DRQ			0x0300	/* HDMA Request Type						*/
-#define	DRQ_NONE	0x0000	/* 		No Request							*/
-#define	DRQ_SINGLE	0x0100	/* 		Channels Request Single				*/
-#define	DRQ_MULTI	0x0200	/* 		Channels Request Multi (Default)	*/
-#define	DRQ_URGENT	0x0300	/* 		Channels Request Multi Urgent		*/
-#define	RBC			0x1000	/* Reload BCNT With IBCNT					*/
-#define	PS			0x2000	/* HDMA Pin Status							*/
-#define	OI			0x4000	/* Overflow Interrupt Generated				*/
-#define	BDI			0x8000	/* Block Done Interrupt Generated			*/
-
-/* entry addresses of the user-callable Boot ROM functions */
-
-#define _BOOTROM_RESET 0xEF000000
-#define _BOOTROM_FINAL_INIT 0xEF000002
-#define _BOOTROM_DO_MEMORY_DMA 0xEF000006
-#define _BOOTROM_BOOT_DXE_FLASH 0xEF000008
-#define _BOOTROM_BOOT_DXE_SPI 0xEF00000A
-#define _BOOTROM_BOOT_DXE_TWI 0xEF00000C
-#define _BOOTROM_GET_DXE_ADDRESS_FLASH 0xEF000010
-#define _BOOTROM_GET_DXE_ADDRESS_SPI 0xEF000012
-#define _BOOTROM_GET_DXE_ADDRESS_TWI 0xEF000014
-
-/* Alternate Deprecated Macros Provided For Backwards Code Compatibility */
-#define	PGDE_UART   PFDE_UART
-#define	PGDE_DMA    PFDE_DMA
-#define	CKELOW		SCKELOW
-
-/* ==== end from defBF534.h ==== */
-
-/* HOST Port Registers */
-
-#define                     HOST_CONTROL  0xffc03400   /* HOST Control Register */
-#define                      HOST_STATUS  0xffc03404   /* HOST Status Register */
-#define                     HOST_TIMEOUT  0xffc03408   /* HOST Acknowledge Mode Timeout Register */
-
-/* Counter Registers */
-
-#define                       CNT_CONFIG  0xffc03500   /* Configuration Register */
-#define                        CNT_IMASK  0xffc03504   /* Interrupt Mask Register */
-#define                       CNT_STATUS  0xffc03508   /* Status Register */
-#define                      CNT_COMMAND  0xffc0350c   /* Command Register */
-#define                     CNT_DEBOUNCE  0xffc03510   /* Debounce Register */
-#define                      CNT_COUNTER  0xffc03514   /* Counter Register */
-#define                          CNT_MAX  0xffc03518   /* Maximal Count Register */
-#define                          CNT_MIN  0xffc0351c   /* Minimal Count Register */
-
-/* OTP/FUSE Registers */
-
-#define                      OTP_CONTROL  0xffc03600   /* OTP/Fuse Control Register */
-#define                          OTP_BEN  0xffc03604   /* OTP/Fuse Byte Enable */
-#define                       OTP_STATUS  0xffc03608   /* OTP/Fuse Status */
-#define                       OTP_TIMING  0xffc0360c   /* OTP/Fuse Access Timing */
-
-/* Security Registers */
-
-#define                    SECURE_SYSSWT  0xffc03620   /* Secure System Switches */
-#define                   SECURE_CONTROL  0xffc03624   /* Secure Control */
-#define                    SECURE_STATUS  0xffc03628   /* Secure Status */
-
-/* OTP Read/Write Data Buffer Registers */
-
-#define                        OTP_DATA0  0xffc03680   /* OTP/Fuse Data (OTP_DATA0-3) accesses the fuse read write buffer */
-#define                        OTP_DATA1  0xffc03684   /* OTP/Fuse Data (OTP_DATA0-3) accesses the fuse read write buffer */
-#define                        OTP_DATA2  0xffc03688   /* OTP/Fuse Data (OTP_DATA0-3) accesses the fuse read write buffer */
-#define                        OTP_DATA3  0xffc0368c   /* OTP/Fuse Data (OTP_DATA0-3) accesses the fuse read write buffer */
-
-/* NFC Registers */
-
-#define                          NFC_CTL  0xffc03700   /* NAND Control Register */
-#define                         NFC_STAT  0xffc03704   /* NAND Status Register */
-#define                      NFC_IRQSTAT  0xffc03708   /* NAND Interrupt Status Register */
-#define                      NFC_IRQMASK  0xffc0370c   /* NAND Interrupt Mask Register */
-#define                         NFC_ECC0  0xffc03710   /* NAND ECC Register 0 */
-#define                         NFC_ECC1  0xffc03714   /* NAND ECC Register 1 */
-#define                         NFC_ECC2  0xffc03718   /* NAND ECC Register 2 */
-#define                         NFC_ECC3  0xffc0371c   /* NAND ECC Register 3 */
-#define                        NFC_COUNT  0xffc03720   /* NAND ECC Count Register */
-#define                          NFC_RST  0xffc03724   /* NAND ECC Reset Register */
-#define                        NFC_PGCTL  0xffc03728   /* NAND Page Control Register */
-#define                         NFC_READ  0xffc0372c   /* NAND Read Data Register */
-#define                         NFC_ADDR  0xffc03740   /* NAND Address Register */
-#define                          NFC_CMD  0xffc03744   /* NAND Command Register */
-#define                      NFC_DATA_WR  0xffc03748   /* NAND Data Write Register */
-#define                      NFC_DATA_RD  0xffc0374c   /* NAND Data Read Register */
-
-/* ********************************************************** */
-/*     SINGLE BIT MACRO PAIRS (bit mask and negated one)      */
-/*     and MULTI BIT READ MACROS                              */
-/* ********************************************************** */
-
-/* Bit masks for HOST_CONTROL */
-
-#define                   HOST_CNTR_HOST_EN  0x1        /* Host Enable */
-#define                  HOST_CNTR_nHOST_EN  0x0
-#define                  HOST_CNTR_HOST_END  0x2        /* Host Endianess */
-#define                 HOST_CNTR_nHOST_END  0x0
-#define                 HOST_CNTR_DATA_SIZE  0x4        /* Data Size */
-#define                HOST_CNTR_nDATA_SIZE  0x0
-#define                  HOST_CNTR_HOST_RST  0x8        /* Host Reset */
-#define                 HOST_CNTR_nHOST_RST  0x0
-#define                  HOST_CNTR_HRDY_OVR  0x20       /* Host Ready Override */
-#define                 HOST_CNTR_nHRDY_OVR  0x0
-#define                  HOST_CNTR_INT_MODE  0x40       /* Interrupt Mode */
-#define                 HOST_CNTR_nINT_MODE  0x0
-#define                     HOST_CNTR_BT_EN  0x80       /* Bus Timeout Enable */
-#define                   HOST_CNTR_ nBT_EN  0x0
-#define                       HOST_CNTR_EHW  0x100      /* Enable Host Write */
-#define                      HOST_CNTR_nEHW  0x0
-#define                       HOST_CNTR_EHR  0x200      /* Enable Host Read */
-#define                      HOST_CNTR_nEHR  0x0
-#define                       HOST_CNTR_BDR  0x400      /* Burst DMA Requests */
-#define                      HOST_CNTR_nBDR  0x0
-
-/* Bit masks for HOST_STATUS */
-
-#define                     HOST_STAT_READY  0x1        /* DMA Ready */
-#define                    HOST_STAT_nREADY  0x0
-#define                  HOST_STAT_FIFOFULL  0x2        /* FIFO Full */
-#define                 HOST_STAT_nFIFOFULL  0x0
-#define                 HOST_STAT_FIFOEMPTY  0x4        /* FIFO Empty */
-#define                HOST_STAT_nFIFOEMPTY  0x0
-#define                  HOST_STAT_COMPLETE  0x8        /* DMA Complete */
-#define                 HOST_STAT_nCOMPLETE  0x0
-#define                      HOST_STAT_HSHK  0x10       /* Host Handshake */
-#define                     HOST_STAT_nHSHK  0x0
-#define                   HOST_STAT_TIMEOUT  0x20       /* Host Timeout */
-#define                  HOST_STAT_nTIMEOUT  0x0
-#define                      HOST_STAT_HIRQ  0x40       /* Host Interrupt Request */
-#define                     HOST_STAT_nHIRQ  0x0
-#define                HOST_STAT_ALLOW_CNFG  0x80       /* Allow New Configuration */
-#define               HOST_STAT_nALLOW_CNFG  0x0
-#define                   HOST_STAT_DMA_DIR  0x100      /* DMA Direction */
-#define                  HOST_STAT_nDMA_DIR  0x0
-#define                       HOST_STAT_BTE  0x200      /* Bus Timeout Enabled */
-#define                      HOST_STAT_nBTE  0x0
-#define               HOST_STAT_HOSTRD_DONE  0x8000     /* Host Read Completion Interrupt */
-#define              HOST_STAT_nHOSTRD_DONE  0x0
-
-/* Bit masks for HOST_TIMEOUT */
-
-#define             HOST_COUNT_TIMEOUT  0x7ff      /* Host Timeout count */
-
-/* Bit masks for SECURE_SYSSWT */
-
-#define                   EMUDABL  0x1        /* Emulation Disable. */
-#define                  nEMUDABL  0x0
-#define                   RSTDABL  0x2        /* Reset Disable */
-#define                  nRSTDABL  0x0
-#define                   L1IDABL  0x1c       /* L1 Instruction Memory Disable. */
-#define                  L1DADABL  0xe0       /* L1 Data Bank A Memory Disable. */
-#define                  L1DBDABL  0x700      /* L1 Data Bank B Memory Disable. */
-#define                   DMA0OVR  0x800      /* DMA0 Memory Access Override */
-#define                  nDMA0OVR  0x0
-#define                   DMA1OVR  0x1000     /* DMA1 Memory Access Override */
-#define                  nDMA1OVR  0x0
-#define                    EMUOVR  0x4000     /* Emulation Override */
-#define                   nEMUOVR  0x0
-#define                    OTPSEN  0x8000     /* OTP Secrets Enable. */
-#define                   nOTPSEN  0x0
-#define                    L2DABL  0x70000    /* L2 Memory Disable. */
-
-/* Bit masks for SECURE_CONTROL */
-
-#define                   SECURE0  0x1        /* SECURE 0 */
-#define                  nSECURE0  0x0
-#define                   SECURE1  0x2        /* SECURE 1 */
-#define                  nSECURE1  0x0
-#define                   SECURE2  0x4        /* SECURE 2 */
-#define                  nSECURE2  0x0
-#define                   SECURE3  0x8        /* SECURE 3 */
-#define                  nSECURE3  0x0
-
-/* Bit masks for SECURE_STATUS */
-
-#define                   SECMODE  0x3        /* Secured Mode Control State */
-#define                       NMI  0x4        /* Non Maskable Interrupt */
-#define                      nNMI  0x0
-#define                   AFVALID  0x8        /* Authentication Firmware Valid */
-#define                  nAFVALID  0x0
-#define                    AFEXIT  0x10       /* Authentication Firmware Exit */
-#define                   nAFEXIT  0x0
-#define                   SECSTAT  0xe0       /* Secure Status */
-
-#endif /* _DEF_BF52X_H */
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf527/include/mach/gpio.h linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf527/include/mach/gpio.h
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf527/include/mach/gpio.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf527/include/mach/gpio.h	2011-03-14 21:20:32.000000000 -0400
@@ -62,4 +62,8 @@
 #define PORT_G GPIO_PG0
 #define PORT_H GPIO_PH0
 
+#include <mach-common/ports-f.h>
+#include <mach-common/ports-g.h>
+#include <mach-common/ports-h.h>
+
 #endif /* _MACH_GPIO_H_ */
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf527/include/mach/pll.h linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf527/include/mach/pll.h
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf527/include/mach/pll.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf527/include/mach/pll.h	2011-03-14 21:20:32.000000000 -0400
@@ -1,63 +1 @@
-/*
- * Copyright 2007-2008 Analog Devices Inc.
- *
- * Licensed under the GPL-2 or later
- */
-
-#ifndef _MACH_PLL_H
-#define _MACH_PLL_H
-
-#include <asm/blackfin.h>
-#include <asm/irqflags.h>
-
-/* Writing to PLL_CTL initiates a PLL relock sequence. */
-static __inline__ void bfin_write_PLL_CTL(unsigned int val)
-{
-	unsigned long flags, iwr0, iwr1;
-
-	if (val == bfin_read_PLL_CTL())
-		return;
-
-	flags = hard_local_irq_save();
-	/* Enable the PLL Wakeup bit in SIC IWR */
-	iwr0 = bfin_read32(SIC_IWR0);
-	iwr1 = bfin_read32(SIC_IWR1);
-	/* Only allow PPL Wakeup) */
-	bfin_write32(SIC_IWR0, IWR_ENABLE(0));
-	bfin_write32(SIC_IWR1, 0);
-
-	bfin_write16(PLL_CTL, val);
-	SSYNC();
-	asm("IDLE;");
-
-	bfin_write32(SIC_IWR0, iwr0);
-	bfin_write32(SIC_IWR1, iwr1);
-	hard_local_irq_restore(flags);
-}
-
-/* Writing to VR_CTL initiates a PLL relock sequence. */
-static __inline__ void bfin_write_VR_CTL(unsigned int val)
-{
-	unsigned long flags, iwr0, iwr1;
-
-	if (val == bfin_read_VR_CTL())
-		return;
-
-	flags = hard_local_irq_save();
-	/* Enable the PLL Wakeup bit in SIC IWR */
-	iwr0 = bfin_read32(SIC_IWR0);
-	iwr1 = bfin_read32(SIC_IWR1);
-	/* Only allow PPL Wakeup) */
-	bfin_write32(SIC_IWR0, IWR_ENABLE(0));
-	bfin_write32(SIC_IWR1, 0);
-
-	bfin_write16(VR_CTL, val);
-	SSYNC();
-	asm("IDLE;");
-
-	bfin_write32(SIC_IWR0, iwr0);
-	bfin_write32(SIC_IWR1, iwr1);
-	hard_local_irq_restore(flags);
-}
-
-#endif /* _MACH_PLL_H */
+#include <mach-common/pll.h>
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf533/boards/blackstamp.c linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf533/boards/blackstamp.c
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf533/boards/blackstamp.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf533/boards/blackstamp.c	2011-03-14 21:20:32.000000000 -0400
@@ -25,7 +25,6 @@
 #include <asm/bfin5xx_spi.h>
 #include <asm/portmux.h>
 #include <asm/dpmc.h>
-#include <mach/fio_flag.h>
 
 /*
  * Name the Board for the /proc/cpuinfo
@@ -225,7 +224,7 @@ static struct resource bfin_uart0_resour
 	},
 };
 
-unsigned short bfin_uart0_peripherals[] = {
+static unsigned short bfin_uart0_peripherals[] = {
 	P_UART0_TX, P_UART0_RX, 0
 };
 
@@ -290,9 +289,9 @@ static struct resource bfin_sport0_uart_
 	},
 };
 
-unsigned short bfin_sport0_peripherals[] = {
+static unsigned short bfin_sport0_peripherals[] = {
 	P_SPORT0_TFS, P_SPORT0_DTPRI, P_SPORT0_TSCLK, P_SPORT0_RFS,
-	P_SPORT0_DRPRI, P_SPORT0_RSCLK, P_SPORT0_DRSEC, P_SPORT0_DTSEC, 0
+	P_SPORT0_DRPRI, P_SPORT0_RSCLK, 0
 };
 
 static struct platform_device bfin_sport0_uart_device = {
@@ -324,9 +323,9 @@ static struct resource bfin_sport1_uart_
 	},
 };
 
-unsigned short bfin_sport1_peripherals[] = {
+static unsigned short bfin_sport1_peripherals[] = {
 	P_SPORT1_TFS, P_SPORT1_DTPRI, P_SPORT1_TSCLK, P_SPORT1_RFS,
-	P_SPORT1_DRPRI, P_SPORT1_RSCLK, P_SPORT1_DRSEC, P_SPORT1_DTSEC, 0
+	P_SPORT1_DRPRI, P_SPORT1_RSCLK, 0
 };
 
 static struct platform_device bfin_sport1_uart_device = {
@@ -476,10 +475,16 @@ static int __init blackstamp_init(void)
 		return ret;
 
 #if defined(CONFIG_SMC91X) || defined(CONFIG_SMC91X_MODULE)
-	/* setup BF533_STAMP CPLD to route AMS3 to Ethernet MAC */
-	bfin_write_FIO_DIR(bfin_read_FIO_DIR() | PF0);
-	bfin_write_FIO_FLAG_S(PF0);
-	SSYNC();
+	/*
+	 * setup BF533_STAMP CPLD to route AMS3 to Ethernet MAC.
+	 * the bfin-async-map driver takes care of flipping between
+	 * flash and ethernet when necessary.
+	 */
+	ret = gpio_request(GPIO_PF0, "enet_cpld");
+	if (!ret) {
+		gpio_direction_output(GPIO_PF0, 1);
+		gpio_free(GPIO_PF0);
+	}
 #endif
 
 	spi_register_board_info(bfin_spi_board_info, ARRAY_SIZE(bfin_spi_board_info));
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf533/boards/cm_bf533.c linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf533/boards/cm_bf533.c
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf533/boards/cm_bf533.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf533/boards/cm_bf533.c	2011-03-14 21:20:32.000000000 -0400
@@ -271,7 +271,7 @@ static struct resource bfin_uart0_resour
 	},
 };
 
-unsigned short bfin_uart0_peripherals[] = {
+static unsigned short bfin_uart0_peripherals[] = {
 	P_UART0_TX, P_UART0_RX, 0
 };
 
@@ -336,9 +336,9 @@ static struct resource bfin_sport0_uart_
 	},
 };
 
-unsigned short bfin_sport0_peripherals[] = {
+static unsigned short bfin_sport0_peripherals[] = {
 	P_SPORT0_TFS, P_SPORT0_DTPRI, P_SPORT0_TSCLK, P_SPORT0_RFS,
-	P_SPORT0_DRPRI, P_SPORT0_RSCLK, P_SPORT0_DRSEC, P_SPORT0_DTSEC, 0
+	P_SPORT0_DRPRI, P_SPORT0_RSCLK, 0
 };
 
 static struct platform_device bfin_sport0_uart_device = {
@@ -370,9 +370,9 @@ static struct resource bfin_sport1_uart_
 	},
 };
 
-unsigned short bfin_sport1_peripherals[] = {
+static unsigned short bfin_sport1_peripherals[] = {
 	P_SPORT1_TFS, P_SPORT1_DTPRI, P_SPORT1_TSCLK, P_SPORT1_RFS,
-	P_SPORT1_DRPRI, P_SPORT1_RSCLK, P_SPORT1_DRSEC, P_SPORT1_DTSEC, 0
+	P_SPORT1_DRPRI, P_SPORT1_RSCLK, 0
 };
 
 static struct platform_device bfin_sport1_uart_device = {
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf533/boards/ezkit.c linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf533/boards/ezkit.c
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf533/boards/ezkit.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf533/boards/ezkit.c	2011-03-14 21:20:32.000000000 -0400
@@ -349,7 +349,7 @@ static struct resource bfin_uart0_resour
 	},
 };
 
-unsigned short bfin_uart0_peripherals[] = {
+static unsigned short bfin_uart0_peripherals[] = {
 	P_UART0_TX, P_UART0_RX, 0
 };
 
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf533/boards/H8606.c linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf533/boards/H8606.c
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf533/boards/H8606.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf533/boards/H8606.c	2011-03-14 21:20:32.000000000 -0400
@@ -286,7 +286,7 @@ static struct resource bfin_uart0_resour
 	},
 };
 
-unsigned short bfin_uart0_peripherals[] = {
+static unsigned short bfin_uart0_peripherals[] = {
 	P_UART0_TX, P_UART0_RX, 0
 };
 
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf533/boards/ip0x.c linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf533/boards/ip0x.c
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf533/boards/ip0x.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf533/boards/ip0x.c	2011-03-14 21:20:32.000000000 -0400
@@ -22,7 +22,6 @@
 #include <asm/dma.h>
 #include <asm/bfin5xx_spi.h>
 #include <asm/portmux.h>
-#include <mach/fio_flag.h>
 
 /*
  * Name the Board for the /proc/cpuinfo
@@ -174,7 +173,7 @@ static struct resource bfin_uart0_resour
 	},
 };
 
-unsigned short bfin_uart0_peripherals[] = {
+static unsigned short bfin_uart0_peripherals[] = {
 	P_UART0_TX, P_UART0_RX, 0
 };
 
@@ -295,15 +294,7 @@ static int __init ip0x_init(void)
 	printk(KERN_INFO "%s(): registering device resources\n", __func__);
 	platform_add_devices(ip0x_devices, ARRAY_SIZE(ip0x_devices));
 
-#if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
-	for (i = 0; i < ARRAY_SIZE(bfin_spi_board_info); ++i) {
-		int j = 1 << bfin_spi_board_info[i].chip_select;
-		/* set spi cs to 1 */
-		bfin_write_FIO_DIR(bfin_read_FIO_DIR() | j);
-		bfin_write_FIO_FLAG_S(j);
-	}
 	spi_register_board_info(bfin_spi_board_info, ARRAY_SIZE(bfin_spi_board_info));
-#endif
 
 	return 0;
 }
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf533/boards/stamp.c linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf533/boards/stamp.c
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf533/boards/stamp.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf533/boards/stamp.c	2011-03-14 21:20:32.000000000 -0400
@@ -24,7 +24,6 @@
 #include <asm/reboot.h>
 #include <asm/portmux.h>
 #include <asm/dpmc.h>
-#include <mach/fio_flag.h>
 
 /*
  * Name the Board for the /proc/cpuinfo
@@ -354,7 +353,7 @@ static struct resource bfin_uart0_resour
 	},
 };
 
-unsigned short bfin_uart0_peripherals[] = {
+static unsigned short bfin_uart0_peripherals[] = {
 	P_UART0_TX, P_UART0_RX, 0
 };
 
@@ -419,9 +418,9 @@ static struct resource bfin_sport0_uart_
 	},
 };
 
-unsigned short bfin_sport0_peripherals[] = {
+static unsigned short bfin_sport0_peripherals[] = {
 	P_SPORT0_TFS, P_SPORT0_DTPRI, P_SPORT0_TSCLK, P_SPORT0_RFS,
-	P_SPORT0_DRPRI, P_SPORT0_RSCLK, P_SPORT0_DRSEC, P_SPORT0_DTSEC, 0
+	P_SPORT0_DRPRI, P_SPORT0_RSCLK, 0
 };
 
 static struct platform_device bfin_sport0_uart_device = {
@@ -453,9 +452,9 @@ static struct resource bfin_sport1_uart_
 	},
 };
 
-unsigned short bfin_sport1_peripherals[] = {
+static unsigned short bfin_sport1_peripherals[] = {
 	P_SPORT1_TFS, P_SPORT1_DTPRI, P_SPORT1_TSCLK, P_SPORT1_RFS,
-	P_SPORT1_DRPRI, P_SPORT1_RSCLK, P_SPORT1_DRSEC, P_SPORT1_DTSEC, 0
+	P_SPORT1_DRPRI, P_SPORT1_RSCLK, 0
 };
 
 static struct platform_device bfin_sport1_uart_device = {
@@ -674,10 +673,16 @@ static int __init stamp_init(void)
 		return ret;
 
 #if defined(CONFIG_SMC91X) || defined(CONFIG_SMC91X_MODULE)
-	/* setup BF533_STAMP CPLD to route AMS3 to Ethernet MAC */
-	bfin_write_FIO_DIR(bfin_read_FIO_DIR() | PF0);
-	bfin_write_FIO_FLAG_S(PF0);
-	SSYNC();
+	/*
+	 * setup BF533_STAMP CPLD to route AMS3 to Ethernet MAC.
+	 * the bfin-async-map driver takes care of flipping between
+	 * flash and ethernet when necessary.
+	 */
+	ret = gpio_request(GPIO_PF0, "enet_cpld");
+	if (!ret) {
+		gpio_direction_output(GPIO_PF0, 1);
+		gpio_free(GPIO_PF0);
+	}
 #endif
 
 	spi_register_board_info(bfin_spi_board_info, ARRAY_SIZE(bfin_spi_board_info));
@@ -713,7 +718,6 @@ void __init native_machine_early_platfor
 void native_machine_restart(char *cmd)
 {
 	/* workaround pull up on cpld / flash pin not being strong enough */
-	bfin_write_FIO_INEN(~PF0);
-	bfin_write_FIO_DIR(PF0);
-	bfin_write_FIO_FLAG_C(PF0);
+	gpio_request(GPIO_PF0, "flash_cpld");
+	gpio_direction_output(GPIO_PF0, 0);
 }
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf533/dma.c linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf533/dma.c
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf533/dma.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf533/dma.c	2011-03-14 21:20:32.000000000 -0400
@@ -11,7 +11,7 @@
 #include <asm/blackfin.h>
 #include <asm/dma.h>
 
-struct dma_register *dma_io_base_addr[MAX_DMA_CHANNELS] = {
+struct dma_register * const dma_io_base_addr[MAX_DMA_CHANNELS] = {
 	(struct dma_register *) DMA0_NEXT_DESC_PTR,
 	(struct dma_register *) DMA1_NEXT_DESC_PTR,
 	(struct dma_register *) DMA2_NEXT_DESC_PTR,
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf533/include/mach/bfin_serial_5xx.h linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf533/include/mach/bfin_serial_5xx.h
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf533/include/mach/bfin_serial_5xx.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf533/include/mach/bfin_serial_5xx.h	2011-03-14 21:20:32.000000000 -0400
@@ -4,36 +4,9 @@
  * Licensed under the GPL-2 or later
  */
 
-#include <linux/serial.h>
 #include <asm/dma.h>
 #include <asm/portmux.h>
 
-#define UART_GET_CHAR(uart)     bfin_read16(((uart)->port.membase + OFFSET_RBR))
-#define UART_GET_DLL(uart)	bfin_read16(((uart)->port.membase + OFFSET_DLL))
-#define UART_GET_IER(uart)      bfin_read16(((uart)->port.membase + OFFSET_IER))
-#define UART_GET_DLH(uart)	bfin_read16(((uart)->port.membase + OFFSET_DLH))
-#define UART_GET_IIR(uart)      bfin_read16(((uart)->port.membase + OFFSET_IIR))
-#define UART_GET_LCR(uart)      bfin_read16(((uart)->port.membase + OFFSET_LCR))
-#define UART_GET_GCTL(uart)     bfin_read16(((uart)->port.membase + OFFSET_GCTL))
-
-#define UART_PUT_CHAR(uart,v)   bfin_write16(((uart)->port.membase + OFFSET_THR),v)
-#define UART_PUT_DLL(uart,v)    bfin_write16(((uart)->port.membase + OFFSET_DLL),v)
-#define UART_PUT_IER(uart,v)    bfin_write16(((uart)->port.membase + OFFSET_IER),v)
-#define UART_SET_IER(uart,v)    UART_PUT_IER(uart, UART_GET_IER(uart) | (v))
-#define UART_CLEAR_IER(uart,v)  UART_PUT_IER(uart, UART_GET_IER(uart) & ~(v))
-#define UART_PUT_DLH(uart,v)    bfin_write16(((uart)->port.membase + OFFSET_DLH),v)
-#define UART_PUT_LCR(uart,v)    bfin_write16(((uart)->port.membase + OFFSET_LCR),v)
-#define UART_PUT_GCTL(uart,v)   bfin_write16(((uart)->port.membase + OFFSET_GCTL),v)
-
-#define UART_SET_DLAB(uart)     do { UART_PUT_LCR(uart, UART_GET_LCR(uart) | DLAB); SSYNC(); } while (0)
-#define UART_CLEAR_DLAB(uart)   do { UART_PUT_LCR(uart, UART_GET_LCR(uart) & ~DLAB); SSYNC(); } while (0)
-
-#define UART_GET_CTS(x) gpio_get_value(x->cts_pin)
-#define UART_DISABLE_RTS(x) gpio_set_value(x->rts_pin, 1)
-#define UART_ENABLE_RTS(x) gpio_set_value(x->rts_pin, 0)
-#define UART_ENABLE_INTS(x, v) UART_PUT_IER(x, v)
-#define UART_DISABLE_INTS(x) UART_PUT_IER(x, 0)
-
 #ifdef CONFIG_BFIN_UART0_CTSRTS
 # define CONFIG_SERIAL_BFIN_CTSRTS
 # ifndef CONFIG_UART0_CTS_PIN
@@ -44,51 +17,6 @@
 # endif
 #endif
 
-#define BFIN_UART_TX_FIFO_SIZE	2
-
-struct bfin_serial_port {
-        struct uart_port        port;
-        unsigned int            old_status;
-	int			status_irq;
-	unsigned int lsr;
-#ifdef CONFIG_SERIAL_BFIN_DMA
-	int			tx_done;
-	int			tx_count;
-	struct circ_buf		rx_dma_buf;
-	struct timer_list       rx_dma_timer;
-	int			rx_dma_nrows;
-	unsigned int		tx_dma_channel;
-	unsigned int		rx_dma_channel;
-	struct work_struct	tx_dma_workqueue;
-#else
-# if ANOMALY_05000363
-	unsigned int anomaly_threshold;
-# endif
-#endif
-#ifdef CONFIG_SERIAL_BFIN_CTSRTS
-	struct timer_list       cts_timer;
-	int			cts_pin;
-	int			rts_pin;
-#endif
-};
-
-/* The hardware clears the LSR bits upon read, so we need to cache
- * some of the more fun bits in software so they don't get lost
- * when checking the LSR in other code paths (TX).
- */
-static inline unsigned int UART_GET_LSR(struct bfin_serial_port *uart)
-{
-	unsigned int lsr = bfin_read16(uart->port.membase + OFFSET_LSR);
-	uart->lsr |= (lsr & (BI|FE|PE|OE));
-	return lsr | uart->lsr;
-}
-
-static inline void UART_CLEAR_LSR(struct bfin_serial_port *uart)
-{
-	uart->lsr = 0;
-	bfin_write16(uart->port.membase + OFFSET_LSR, -1);
-}
-
 struct bfin_serial_res {
 	unsigned long	uart_base_addr;
 	int		uart_irq;
@@ -120,3 +48,5 @@ struct bfin_serial_res bfin_serial_resou
 };
 
 #define DRIVER_NAME "bfin-uart"
+
+#include <asm/bfin_serial.h>
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf533/include/mach/bfin_serial.h linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf533/include/mach/bfin_serial.h
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf533/include/mach/bfin_serial.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf533/include/mach/bfin_serial.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,14 @@
+/*
+ * mach/bfin_serial.h - Blackfin UART/Serial definitions
+ *
+ * Copyright 2006-2010 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#ifndef __BFIN_MACH_SERIAL_H__
+#define __BFIN_MACH_SERIAL_H__
+
+#define BFIN_UART_NR_PORTS	1
+
+#endif
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf533/include/mach/blackfin.h linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf533/include/mach/blackfin.h
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf533/include/mach/blackfin.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf533/include/mach/blackfin.h	2011-03-14 21:20:32.000000000 -0400
@@ -1,7 +1,7 @@
 /*
- * Copyright 2005-2009 Analog Devices Inc.
+ * Copyright 2005-2010 Analog Devices Inc.
  *
- * Licensed under the GPL-2 or later
+ * Licensed under the GPL-2 or later.
  */
 
 #ifndef _MACH_BLACKFIN_H_
@@ -10,26 +10,14 @@
 #define BF533_FAMILY
 
 #include "bf533.h"
-#include "defBF532.h"
 #include "anomaly.h"
 
-#if !defined(__ASSEMBLY__)
-#include "cdefBF532.h"
-#endif
-
-#define BFIN_UART_NR_PORTS      1
+#include <asm/def_LPBlackfin.h>
+#include "defBF532.h"
 
-#define OFFSET_THR              0x00	/* Transmit Holding register            */
-#define OFFSET_RBR              0x00	/* Receive Buffer register              */
-#define OFFSET_DLL              0x00	/* Divisor Latch (Low-Byte)             */
-#define OFFSET_IER              0x04	/* Interrupt Enable Register            */
-#define OFFSET_DLH              0x04	/* Divisor Latch (High-Byte)            */
-#define OFFSET_IIR              0x08	/* Interrupt Identification Register    */
-#define OFFSET_LCR              0x0C	/* Line Control Register                */
-#define OFFSET_MCR              0x10	/* Modem Control Register               */
-#define OFFSET_LSR              0x14	/* Line Status Register                 */
-#define OFFSET_MSR              0x18	/* Modem Status Register                */
-#define OFFSET_SCR              0x1C	/* SCR Scratch Register                 */
-#define OFFSET_GCTL             0x24	/* Global Control Register              */
+#ifndef __ASSEMBLY__
+# include <asm/cdef_LPBlackfin.h>
+# include "cdefBF532.h"
+#endif
 
-#endif				/* _MACH_BLACKFIN_H_ */
+#endif
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf533/include/mach/cdefBF532.h linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf533/include/mach/cdefBF532.h
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf533/include/mach/cdefBF532.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf533/include/mach/cdefBF532.h	2011-03-14 21:20:32.000000000 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright 2005-2008 Analog Devices Inc.
+ * Copyright 2005-2010 Analog Devices Inc.
  *
  * Licensed under the GPL-2 or later
  */
@@ -7,9 +7,6 @@
 #ifndef _CDEF_BF532_H
 #define _CDEF_BF532_H
 
-/*include core specific register pointer definitions*/
-#include <asm/cdef_LPBlackfin.h>
-
 /* Clock and System Control (0xFFC0 0400-0xFFC0 07FF) */
 #define bfin_read_PLL_CTL()                  bfin_read16(PLL_CTL)
 #define bfin_read_PLL_STAT()                 bfin_read16(PLL_STAT)
@@ -66,16 +63,10 @@
 #define bfin_write_RTC_PREN(val)             bfin_write16(RTC_PREN,val)
 
 /* DMA Traffic controls */
-#define bfin_read_DMA_TCPER()                bfin_read16(DMA_TCPER)
-#define bfin_write_DMA_TCPER(val)            bfin_write16(DMA_TCPER,val)
-#define bfin_read_DMA_TCCNT()                bfin_read16(DMA_TCCNT)
-#define bfin_write_DMA_TCCNT(val)            bfin_write16(DMA_TCCNT,val)
-
-/* Alternate deprecated register names (below) provided for backwards code compatibility */
-#define bfin_read_DMA_TC_PER()               bfin_read16(DMA_TC_PER)
-#define bfin_write_DMA_TC_PER(val)           bfin_write16(DMA_TC_PER,val)
-#define bfin_read_DMA_TC_CNT()               bfin_read16(DMA_TC_CNT)
-#define bfin_write_DMA_TC_CNT(val)           bfin_write16(DMA_TC_CNT,val)
+#define bfin_read_DMAC_TC_PER()              bfin_read16(DMAC_TC_PER)
+#define bfin_write_DMAC_TC_PER(val)          bfin_write16(DMAC_TC_PER,val)
+#define bfin_read_DMAC_TC_CNT()              bfin_read16(DMAC_TC_CNT)
+#define bfin_write_DMAC_TC_CNT(val)          bfin_write16(DMAC_TC_CNT,val)
 
 /* General Purpose IO (0xFFC0 2400-0xFFC0 27FF) */
 #define bfin_read_FIO_DIR()                  bfin_read16(FIO_DIR)
@@ -105,6 +96,47 @@
 #define bfin_read_FIO_MASKB_T()              bfin_read16(FIO_MASKB_T)
 #define bfin_write_FIO_MASKB_T(val)          bfin_write16(FIO_MASKB_T,val)
 
+#if ANOMALY_05000311
+/* Keep at the CPP expansion to avoid circular header dependency loops */
+#define BFIN_WRITE_FIO_FLAG(name, val) \
+	do { \
+		unsigned long __flags; \
+		__flags = hard_local_irq_save(); \
+		bfin_write16(FIO_FLAG_##name, val); \
+		bfin_read_CHIPID(); \
+		hard_local_irq_restore(__flags); \
+	} while (0)
+#define bfin_write_FIO_FLAG_D(val)           BFIN_WRITE_FIO_FLAG(D, val)
+#define bfin_write_FIO_FLAG_C(val)           BFIN_WRITE_FIO_FLAG(C, val)
+#define bfin_write_FIO_FLAG_S(val)           BFIN_WRITE_FIO_FLAG(S, val)
+#define bfin_write_FIO_FLAG_T(val)           BFIN_WRITE_FIO_FLAG(T, val)
+
+#define BFIN_READ_FIO_FLAG(name) \
+	({ \
+		unsigned long __flags; \
+		u16 __ret; \
+		__flags = hard_local_irq_save(); \
+		__ret = bfin_read16(FIO_FLAG_##name); \
+		bfin_read_CHIPID(); \
+		hard_local_irq_restore(__flags); \
+		__ret; \
+	})
+#define bfin_read_FIO_FLAG_D()               BFIN_READ_FIO_FLAG(D)
+#define bfin_read_FIO_FLAG_C()               BFIN_READ_FIO_FLAG(C)
+#define bfin_read_FIO_FLAG_S()               BFIN_READ_FIO_FLAG(S)
+#define bfin_read_FIO_FLAG_T()               BFIN_READ_FIO_FLAG(T)
+
+#else
+#define bfin_write_FIO_FLAG_D(val)           bfin_write16(FIO_FLAG_D, val)
+#define bfin_write_FIO_FLAG_C(val)           bfin_write16(FIO_FLAG_C, val)
+#define bfin_write_FIO_FLAG_S(val)           bfin_write16(FIO_FLAG_S, val)
+#define bfin_write_FIO_FLAG_T(val)           bfin_write16(FIO_FLAG_T, val)
+#define bfin_read_FIO_FLAG_D()               bfin_read16(FIO_FLAG_D)
+#define bfin_read_FIO_FLAG_C()               bfin_read16(FIO_FLAG_C)
+#define bfin_read_FIO_FLAG_S()               bfin_read16(FIO_FLAG_S)
+#define bfin_read_FIO_FLAG_T()               bfin_read16(FIO_FLAG_T)
+#endif
+
 /* DMA Controller */
 #define bfin_read_DMA0_CONFIG()              bfin_read16(DMA0_CONFIG)
 #define bfin_write_DMA0_CONFIG(val)          bfin_write16(DMA0_CONFIG,val)
@@ -647,7 +679,4 @@
 #define bfin_read_PPI_FRAME()                bfin_read16(PPI_FRAME)
 #define bfin_write_PPI_FRAME(val)            bfin_write16(PPI_FRAME,val)
 
-/* These need to be last due to the cdef/linux inter-dependencies */
-#include <asm/irq.h>
-
 #endif				/* _CDEF_BF532_H */
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf533/include/mach/defBF532.h linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf533/include/mach/defBF532.h
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf533/include/mach/defBF532.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf533/include/mach/defBF532.h	2011-03-14 21:20:32.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  * System & MMR bit and Address definitions for ADSP-BF532
  *
- * Copyright 2005-2008 Analog Devices Inc.
+ * Copyright 2005-2010 Analog Devices Inc.
  *
  * Licensed under the ADI BSD license or the GPL-2 (or later)
  */
@@ -9,9 +9,6 @@
 #ifndef _DEF_BF532_H
 #define _DEF_BF532_H
 
-/* include all Core registers and bit definitions */
-#include <asm/def_LPBlackfin.h>
-
 /*********************************************************************************** */
 /* System MMR Register Map */
 /*********************************************************************************** */
@@ -182,12 +179,8 @@
 #define EBIU_SDSTAT			0xFFC00A1C	/* SDRAM Status Register */
 
 /* DMA Traffic controls */
-#define DMA_TC_PER 0xFFC00B0C	/* Traffic Control Periods Register */
-#define DMA_TC_CNT 0xFFC00B10	/* Traffic Control Current Counts Register */
-
-/* Alternate deprecated register names (below) provided for backwards code compatibility */
-#define DMA_TCPER 0xFFC00B0C	/* Traffic Control Periods Register */
-#define DMA_TCCNT 0xFFC00B10	/* Traffic Control Current Counts Register */
+#define DMAC_TC_PER 0xFFC00B0C	/* Traffic Control Periods Register */
+#define DMAC_TC_CNT 0xFFC00B10	/* Traffic Control Current Counts Register */
 
 /* DMA Controller (0xFFC00C00 - 0xFFC00FFF) */
 #define DMA0_CONFIG		0xFFC00C08	/* DMA Channel 0 Configuration Register */
@@ -432,83 +425,6 @@
 #define IWR_ENABLE(x)	       (1 << (x))	/* Wakeup Enable Peripheral #x */
 #define IWR_DISABLE(x) (0xFFFFFFFF ^ (1 << (x)))	/* Wakeup Disable Peripheral #x */
 
-/* ***************************** UART CONTROLLER MASKS ********************** */
-
-/* UART_LCR Register */
-
-#define DLAB	0x80
-#define SB      0x40
-#define STP      0x20
-#define EPS     0x10
-#define PEN	0x08
-#define STB	0x04
-#define WLS(x)	((x-5) & 0x03)
-
-#define DLAB_P	0x07
-#define SB_P	0x06
-#define STP_P	0x05
-#define EPS_P	0x04
-#define PEN_P	0x03
-#define STB_P	0x02
-#define WLS_P1	0x01
-#define WLS_P0	0x00
-
-/* UART_MCR Register */
-#define LOOP_ENA	0x10
-#define LOOP_ENA_P	0x04
-
-/* UART_LSR Register */
-#define TEMT	0x40
-#define THRE	0x20
-#define BI	0x10
-#define FE	0x08
-#define PE	0x04
-#define OE	0x02
-#define DR	0x01
-
-#define TEMP_P	0x06
-#define THRE_P	0x05
-#define BI_P	0x04
-#define FE_P	0x03
-#define PE_P	0x02
-#define OE_P	0x01
-#define DR_P	0x00
-
-/* UART_IER Register */
-#define ELSI	0x04
-#define ETBEI	0x02
-#define ERBFI	0x01
-
-#define ELSI_P	0x02
-#define ETBEI_P	0x01
-#define ERBFI_P	0x00
-
-/* UART_IIR Register */
-#define STATUS(x)	((x << 1) & 0x06)
-#define NINT		0x01
-#define STATUS_P1	0x02
-#define STATUS_P0	0x01
-#define NINT_P		0x00
-#define IIR_TX_READY    0x02	/* UART_THR empty                               */
-#define IIR_RX_READY    0x04	/* Receive data ready                           */
-#define IIR_LINE_CHANGE 0x06	/* Receive line status                          */
-#define IIR_STATUS	0x06
-
-/* UART_GCTL Register */
-#define FFE	0x20
-#define FPE	0x10
-#define RPOLC	0x08
-#define TPOLC	0x04
-#define IREN	0x02
-#define UCEN	0x01
-
-#define FFE_P	0x05
-#define FPE_P	0x04
-#define RPOLC_P	0x03
-#define TPOLC_P	0x02
-#define IREN_P	0x01
-#define UCEN_P	0x00
-
 /*  *********  PARALLEL PERIPHERAL INTERFACE (PPI) MASKS ****************   */
 
 /*  PPI_CONTROL Masks         */
@@ -643,44 +559,6 @@
 #define ERR_TYP_P0		0x0E
 #define ERR_TYP_P1		0x0F
 
-/*/ ******************   PROGRAMMABLE FLAG MASKS  ********************* */
-
-/*  General Purpose IO (0xFFC00700 - 0xFFC007FF)  Masks */
-#define PF0         0x0001
-#define PF1         0x0002
-#define PF2         0x0004
-#define PF3         0x0008
-#define PF4         0x0010
-#define PF5         0x0020
-#define PF6         0x0040
-#define PF7         0x0080
-#define PF8         0x0100
-#define PF9         0x0200
-#define PF10        0x0400
-#define PF11        0x0800
-#define PF12        0x1000
-#define PF13        0x2000
-#define PF14        0x4000
-#define PF15        0x8000
-
-/*  General Purpose IO (0xFFC00700 - 0xFFC007FF)  BIT POSITIONS */
-#define PF0_P         0
-#define PF1_P         1
-#define PF2_P         2
-#define PF3_P         3
-#define PF4_P         4
-#define PF5_P         5
-#define PF6_P         6
-#define PF7_P         7
-#define PF8_P         8
-#define PF9_P         9
-#define PF10_P        10
-#define PF11_P        11
-#define PF12_P        12
-#define PF13_P        13
-#define PF14_P        14
-#define PF15_P        15
-
 /* *********************  ASYNCHRONOUS MEMORY CONTROLLER MASKS  ************* */
 
 /* AMGCTL Masks */
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf533/include/mach/fio_flag.h linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf533/include/mach/fio_flag.h
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf533/include/mach/fio_flag.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf533/include/mach/fio_flag.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,55 +0,0 @@
-/*
- * Copyright 2005-2008 Analog Devices Inc.
- *
- * Licensed under the GPL-2 or later
- */
-
-#ifndef _MACH_FIO_FLAG_H
-#define _MACH_FIO_FLAG_H
-
-#include <asm/blackfin.h>
-#include <asm/irqflags.h>
-
-#if ANOMALY_05000311
-#define BFIN_WRITE_FIO_FLAG(name) \
-static inline void bfin_write_FIO_FLAG_##name(unsigned short val) \
-{ \
-	unsigned long flags; \
-	flags = hard_local_irq_save(); \
-	bfin_write16(FIO_FLAG_##name, val); \
-	bfin_read_CHIPID(); \
-	hard_local_irq_restore(flags); \
-}
-BFIN_WRITE_FIO_FLAG(D)
-BFIN_WRITE_FIO_FLAG(C)
-BFIN_WRITE_FIO_FLAG(S)
-BFIN_WRITE_FIO_FLAG(T)
-
-#define BFIN_READ_FIO_FLAG(name) \
-static inline u16 bfin_read_FIO_FLAG_##name(void) \
-{ \
-	unsigned long flags; \
-	u16 ret; \
-	flags = hard_local_irq_save(); \
-	ret = bfin_read16(FIO_FLAG_##name); \
-	bfin_read_CHIPID(); \
-	hard_local_irq_restore(flags); \
-	return ret; \
-}
-BFIN_READ_FIO_FLAG(D)
-BFIN_READ_FIO_FLAG(C)
-BFIN_READ_FIO_FLAG(S)
-BFIN_READ_FIO_FLAG(T)
-
-#else
-#define bfin_write_FIO_FLAG_D(val)           bfin_write16(FIO_FLAG_D, val)
-#define bfin_write_FIO_FLAG_C(val)           bfin_write16(FIO_FLAG_C, val)
-#define bfin_write_FIO_FLAG_S(val)           bfin_write16(FIO_FLAG_S, val)
-#define bfin_write_FIO_FLAG_T(val)           bfin_write16(FIO_FLAG_T, val)
-#define bfin_read_FIO_FLAG_T()               bfin_read16(FIO_FLAG_T)
-#define bfin_read_FIO_FLAG_C()               bfin_read16(FIO_FLAG_C)
-#define bfin_read_FIO_FLAG_S()               bfin_read16(FIO_FLAG_S)
-#define bfin_read_FIO_FLAG_D()               bfin_read16(FIO_FLAG_D)
-#endif
-
-#endif /* _MACH_FIO_FLAG_H */
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf533/include/mach/gpio.h linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf533/include/mach/gpio.h
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf533/include/mach/gpio.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf533/include/mach/gpio.h	2011-03-14 21:20:32.000000000 -0400
@@ -28,4 +28,6 @@
 
 #define PORT_F GPIO_PF0
 
+#include <mach-common/ports-f.h>
+
 #endif /* _MACH_GPIO_H_ */
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf533/include/mach/pll.h linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf533/include/mach/pll.h
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf533/include/mach/pll.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf533/include/mach/pll.h	2011-03-14 21:20:32.000000000 -0400
@@ -1,57 +1 @@
-/*
- * Copyright 2005-2008 Analog Devices Inc.
- *
- * Licensed under the GPL-2 or later
- */
-
-#ifndef _MACH_PLL_H
-#define _MACH_PLL_H
-
-#include <asm/blackfin.h>
-#include <asm/irqflags.h>
-
-/* Writing to PLL_CTL initiates a PLL relock sequence. */
-static __inline__ void bfin_write_PLL_CTL(unsigned int val)
-{
-	unsigned long flags, iwr;
-
-	if (val == bfin_read_PLL_CTL())
-		return;
-
-	flags = hard_local_irq_save();
-	/* Enable the PLL Wakeup bit in SIC IWR */
-	iwr = bfin_read32(SIC_IWR);
-	/* Only allow PPL Wakeup) */
-	bfin_write32(SIC_IWR, IWR_ENABLE(0));
-
-	bfin_write16(PLL_CTL, val);
-	SSYNC();
-	asm("IDLE;");
-
-	bfin_write32(SIC_IWR, iwr);
-	hard_local_irq_restore(flags);
-}
-
-/* Writing to VR_CTL initiates a PLL relock sequence. */
-static __inline__ void bfin_write_VR_CTL(unsigned int val)
-{
-	unsigned long flags, iwr;
-
-	if (val == bfin_read_VR_CTL())
-		return;
-
-	flags = hard_local_irq_save();
-	/* Enable the PLL Wakeup bit in SIC IWR */
-	iwr = bfin_read32(SIC_IWR);
-	/* Only allow PPL Wakeup) */
-	bfin_write32(SIC_IWR, IWR_ENABLE(0));
-
-	bfin_write16(VR_CTL, val);
-	SSYNC();
-	asm("IDLE;");
-
-	bfin_write32(SIC_IWR, iwr);
-	hard_local_irq_restore(flags);
-}
-
-#endif /* _MACH_PLL_H */
+#include <mach-common/pll.h>
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf537/boards/cm_bf537e.c linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf537/boards/cm_bf537e.c
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf537/boards/cm_bf537e.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf537/boards/cm_bf537e.c	2011-03-14 21:20:32.000000000 -0400
@@ -373,7 +373,7 @@ static struct resource bfin_uart0_resour
 #endif
 };
 
-unsigned short bfin_uart0_peripherals[] = {
+static unsigned short bfin_uart0_peripherals[] = {
 	P_UART0_TX, P_UART0_RX, 0
 };
 
@@ -434,7 +434,7 @@ static struct resource bfin_uart1_resour
 #endif
 };
 
-unsigned short bfin_uart1_peripherals[] = {
+static unsigned short bfin_uart1_peripherals[] = {
 	P_UART1_TX, P_UART1_RX, 0
 };
 
@@ -545,9 +545,9 @@ static struct resource bfin_sport0_uart_
 	},
 };
 
-unsigned short bfin_sport0_peripherals[] = {
+static unsigned short bfin_sport0_peripherals[] = {
 	P_SPORT0_TFS, P_SPORT0_DTPRI, P_SPORT0_TSCLK, P_SPORT0_RFS,
-	P_SPORT0_DRPRI, P_SPORT0_RSCLK, P_SPORT0_DRSEC, P_SPORT0_DTSEC, 0
+	P_SPORT0_DRPRI, P_SPORT0_RSCLK, 0
 };
 
 static struct platform_device bfin_sport0_uart_device = {
@@ -579,9 +579,9 @@ static struct resource bfin_sport1_uart_
 	},
 };
 
-unsigned short bfin_sport1_peripherals[] = {
+static unsigned short bfin_sport1_peripherals[] = {
 	P_SPORT1_TFS, P_SPORT1_DTPRI, P_SPORT1_TSCLK, P_SPORT1_RFS,
-	P_SPORT1_DRPRI, P_SPORT1_RSCLK, P_SPORT1_DRSEC, P_SPORT1_DTSEC, 0
+	P_SPORT1_DRPRI, P_SPORT1_RSCLK, 0
 };
 
 static struct platform_device bfin_sport1_uart_device = {
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf537/boards/cm_bf537u.c linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf537/boards/cm_bf537u.c
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf537/boards/cm_bf537u.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf537/boards/cm_bf537u.c	2011-03-14 21:20:32.000000000 -0400
@@ -356,7 +356,7 @@ static struct resource bfin_uart0_resour
 	},
 };
 
-unsigned short bfin_uart0_peripherals[] = {
+static unsigned short bfin_uart0_peripherals[] = {
 	P_UART0_TX, P_UART0_RX, 0
 };
 
@@ -399,7 +399,7 @@ static struct resource bfin_uart1_resour
 	},
 };
 
-unsigned short bfin_uart1_peripherals[] = {
+static unsigned short bfin_uart1_peripherals[] = {
 	P_UART1_TX, P_UART1_RX, 0
 };
 
@@ -510,9 +510,9 @@ static struct resource bfin_sport0_uart_
 	},
 };
 
-unsigned short bfin_sport0_peripherals[] = {
+static unsigned short bfin_sport0_peripherals[] = {
 	P_SPORT0_TFS, P_SPORT0_DTPRI, P_SPORT0_TSCLK, P_SPORT0_RFS,
-	P_SPORT0_DRPRI, P_SPORT0_RSCLK, P_SPORT0_DRSEC, P_SPORT0_DTSEC, 0
+	P_SPORT0_DRPRI, P_SPORT0_RSCLK, 0
 };
 
 static struct platform_device bfin_sport0_uart_device = {
@@ -544,9 +544,9 @@ static struct resource bfin_sport1_uart_
 	},
 };
 
-unsigned short bfin_sport1_peripherals[] = {
+static unsigned short bfin_sport1_peripherals[] = {
 	P_SPORT1_TFS, P_SPORT1_DTPRI, P_SPORT1_TSCLK, P_SPORT1_RFS,
-	P_SPORT1_DRPRI, P_SPORT1_RSCLK, P_SPORT1_DRSEC, P_SPORT1_DTSEC, 0
+	P_SPORT1_DRPRI, P_SPORT1_RSCLK, 0
 };
 
 static struct platform_device bfin_sport1_uart_device = {
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf537/boards/dnp5370.c linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf537/boards/dnp5370.c
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf537/boards/dnp5370.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf537/boards/dnp5370.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,418 @@
+/*
+ * This is the configuration for SSV Dil/NetPC DNP/5370 board.
+ *
+ * DIL module:         http://www.dilnetpc.com/dnp0086.htm
+ * SK28 (starter kit): http://www.dilnetpc.com/dnp0088.htm
+ *
+ * Copyright 2010 3ality Digital Systems
+ * Copyright 2005 National ICT Australia (NICTA)
+ * Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/plat-ram.h>
+#include <linux/mtd/physmap.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/flash.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/i2c.h>
+#include <linux/spi/mmc_spi.h>
+#include <linux/phy.h>
+#include <asm/dma.h>
+#include <asm/bfin5xx_spi.h>
+#include <asm/reboot.h>
+#include <asm/portmux.h>
+#include <asm/dpmc.h>
+
+/*
+ * Name the Board for the /proc/cpuinfo
+ */
+const char bfin_board_name[] = "DNP/5370";
+#define FLASH_MAC               0x202f0000
+#define CONFIG_MTD_PHYSMAP_LEN  0x300000
+
+#if defined(CONFIG_RTC_DRV_BFIN) || defined(CONFIG_RTC_DRV_BFIN_MODULE)
+static struct platform_device rtc_device = {
+	.name = "rtc-bfin",
+	.id   = -1,
+};
+#endif
+
+#if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
+#include <linux/bfin_mac.h>
+static const unsigned short bfin_mac_peripherals[] = P_RMII0;
+
+static struct bfin_phydev_platform_data bfin_phydev_data[] = {
+	{
+		.addr = 1,
+		.irq = PHY_POLL, /* IRQ_MAC_PHYINT */
+	},
+};
+
+static struct bfin_mii_bus_platform_data bfin_mii_bus_data = {
+	.phydev_number   = 1,
+	.phydev_data     = bfin_phydev_data,
+	.phy_mode        = PHY_INTERFACE_MODE_RMII,
+	.mac_peripherals = bfin_mac_peripherals,
+};
+
+static struct platform_device bfin_mii_bus = {
+	.name = "bfin_mii_bus",
+	.dev = {
+		.platform_data = &bfin_mii_bus_data,
+	}
+};
+
+static struct platform_device bfin_mac_device = {
+	.name = "bfin_mac",
+	.dev = {
+		.platform_data = &bfin_mii_bus,
+	}
+};
+#endif
+
+#if defined(CONFIG_MTD_PHYSMAP) || defined(CONFIG_MTD_PHYSMAP_MODULE)
+static struct mtd_partition asmb_flash_partitions[] = {
+	{
+		.name       = "bootloader(nor)",
+		.size       = 0x30000,
+		.offset     = 0,
+	}, {
+		.name       = "linux kernel and rootfs(nor)",
+		.size       = 0x300000 - 0x30000 - 0x10000,
+		.offset     = MTDPART_OFS_APPEND,
+	}, {
+		.name       = "MAC address(nor)",
+		.size       = 0x10000,
+		.offset     = MTDPART_OFS_APPEND,
+		.mask_flags = MTD_WRITEABLE,
+	}
+};
+
+static struct physmap_flash_data asmb_flash_data = {
+	.width      = 1,
+	.parts      = asmb_flash_partitions,
+	.nr_parts   = ARRAY_SIZE(asmb_flash_partitions),
+};
+
+static struct resource asmb_flash_resource = {
+	.start = 0x20000000,
+	.end   = 0x202fffff,
+	.flags = IORESOURCE_MEM,
+};
+
+/* 4 MB NOR flash attached to async memory banks 0-2,
+ * therefore only 3 MB visible.
+ */
+static struct platform_device asmb_flash_device = {
+	.name	  = "physmap-flash",
+	.id	  = 0,
+	.dev = {
+		.platform_data = &asmb_flash_data,
+	},
+	.num_resources = 1,
+	.resource      = &asmb_flash_resource,
+};
+#endif
+
+#if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
+
+#if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE)
+
+#define MMC_SPI_CARD_DETECT_INT IRQ_PF5
+
+static int bfin_mmc_spi_init(struct device *dev,
+	irqreturn_t (*detect_int)(int, void *), void *data)
+{
+	return request_irq(MMC_SPI_CARD_DETECT_INT, detect_int,
+		IRQF_TRIGGER_FALLING, "mmc-spi-detect", data);
+}
+
+static void bfin_mmc_spi_exit(struct device *dev, void *data)
+{
+	free_irq(MMC_SPI_CARD_DETECT_INT, data);
+}
+
+static struct bfin5xx_spi_chip mmc_spi_chip_info = {
+	.enable_dma    = 0,	 /* use no dma transfer with this chip*/
+	.bits_per_word = 8,
+};
+
+static struct mmc_spi_platform_data bfin_mmc_spi_pdata = {
+	.init = bfin_mmc_spi_init,
+	.exit = bfin_mmc_spi_exit,
+	.detect_delay = 100, /* msecs */
+};
+#endif
+
+#if defined(CONFIG_MTD_DATAFLASH) || defined(CONFIG_MTD_DATAFLASH_MODULE)
+/* This mapping is for at45db642 it has 1056 page size,
+ * partition size and offset should be page aligned
+ */
+static struct mtd_partition bfin_spi_dataflash_partitions[] = {
+	{
+		.name   = "JFFS2 dataflash(nor)",
+#ifdef CONFIG_MTD_PAGESIZE_1024
+		.offset = 0x40000,
+		.size   = 0x7C0000,
+#else
+		.offset = 0x0,
+		.size   = 0x840000,
+#endif
+	}
+};
+
+static struct flash_platform_data bfin_spi_dataflash_data = {
+	.name     = "mtd_dataflash",
+	.parts    = bfin_spi_dataflash_partitions,
+	.nr_parts = ARRAY_SIZE(bfin_spi_dataflash_partitions),
+	.type     = "mtd_dataflash",
+};
+
+static struct bfin5xx_spi_chip spi_dataflash_chip_info = {
+	.enable_dma    = 0,	 /* use no dma transfer with this chip*/
+	.bits_per_word = 8,
+};
+#endif
+
+static struct spi_board_info bfin_spi_board_info[] __initdata = {
+/* SD/MMC card reader at SPI bus */
+#if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE)
+	{
+		.modalias	 = "mmc_spi",
+		.max_speed_hz    = 20000000,
+		.bus_num	 = 0,
+		.chip_select     = 1,
+		.platform_data   = &bfin_mmc_spi_pdata,
+		.controller_data = &mmc_spi_chip_info,
+		.mode	         = SPI_MODE_3,
+	},
+#endif
+
+/* 8 Megabyte Atmel NOR flash chip at SPI bus */
+#if defined(CONFIG_MTD_DATAFLASH) || defined(CONFIG_MTD_DATAFLASH_MODULE)
+	{
+	.modalias        = "mtd_dataflash",
+	.max_speed_hz    = 16700000,
+	.bus_num         = 0,
+	.chip_select     = 2,
+	.platform_data   = &bfin_spi_dataflash_data,
+	.controller_data = &spi_dataflash_chip_info,
+	.mode            = SPI_MODE_3, /* SPI_CPHA and SPI_CPOL */
+	},
+#endif
+};
+
+/* SPI controller data */
+/* SPI (0) */
+static struct resource bfin_spi0_resource[] = {
+	[0] = {
+		.start = SPI0_REGBASE,
+		.end   = SPI0_REGBASE + 0xFF,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = CH_SPI,
+		.end   = CH_SPI,
+		.flags = IORESOURCE_DMA,
+	},
+	[2] = {
+		.start = IRQ_SPI,
+		.end   = IRQ_SPI,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+static struct bfin5xx_spi_master spi_bfin_master_info = {
+	.num_chipselect = 8,
+	.enable_dma     = 1,  /* master has the ability to do dma transfer */
+	.pin_req        = {P_SPI0_SCK, P_SPI0_MISO, P_SPI0_MOSI, 0},
+};
+
+static struct platform_device spi_bfin_master_device = {
+	.name          = "bfin-spi",
+	.id            = 0, /* Bus number */
+	.num_resources = ARRAY_SIZE(bfin_spi0_resource),
+	.resource      = bfin_spi0_resource,
+	.dev           = {
+		.platform_data = &spi_bfin_master_info, /* Passed to driver */
+	},
+};
+#endif
+
+#if defined(CONFIG_SERIAL_BFIN) || defined(CONFIG_SERIAL_BFIN_MODULE)
+#ifdef CONFIG_SERIAL_BFIN_UART0
+static struct resource bfin_uart0_resources[] = {
+	{
+		.start = UART0_THR,
+		.end = UART0_GCTL+2,
+		.flags = IORESOURCE_MEM,
+	},
+	{
+		.start = IRQ_UART0_RX,
+		.end = IRQ_UART0_RX+1,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
+		.start = IRQ_UART0_ERROR,
+		.end = IRQ_UART0_ERROR,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
+		.start = CH_UART0_TX,
+		.end = CH_UART0_TX,
+		.flags = IORESOURCE_DMA,
+	},
+	{
+		.start = CH_UART0_RX,
+		.end = CH_UART0_RX,
+		.flags = IORESOURCE_DMA,
+	},
+};
+
+static unsigned short bfin_uart0_peripherals[] = {
+	P_UART0_TX, P_UART0_RX, 0
+};
+
+static struct platform_device bfin_uart0_device = {
+	.name = "bfin-uart",
+	.id = 0,
+	.num_resources = ARRAY_SIZE(bfin_uart0_resources),
+	.resource = bfin_uart0_resources,
+	.dev = {
+		.platform_data = &bfin_uart0_peripherals, /* Passed to driver */
+	},
+};
+#endif
+
+#ifdef CONFIG_SERIAL_BFIN_UART1
+static struct resource bfin_uart1_resources[] = {
+	{
+		.start = UART1_THR,
+		.end   = UART1_GCTL+2,
+		.flags = IORESOURCE_MEM,
+	},
+	{
+		.start = IRQ_UART1_RX,
+		.end   = IRQ_UART1_RX+1,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
+		.start = IRQ_UART1_ERROR,
+		.end   = IRQ_UART1_ERROR,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
+		.start = CH_UART1_TX,
+		.end   = CH_UART1_TX,
+		.flags = IORESOURCE_DMA,
+	},
+	{
+		.start = CH_UART1_RX,
+		.end   = CH_UART1_RX,
+		.flags = IORESOURCE_DMA,
+	},
+};
+
+static unsigned short bfin_uart1_peripherals[] = {
+	P_UART1_TX, P_UART1_RX, 0
+};
+
+static struct platform_device bfin_uart1_device = {
+	.name          = "bfin-uart",
+	.id            = 1,
+	.num_resources = ARRAY_SIZE(bfin_uart1_resources),
+	.resource      = bfin_uart1_resources,
+	.dev = {
+		.platform_data = &bfin_uart1_peripherals, /* Passed to driver */
+	},
+};
+#endif
+#endif
+
+#if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
+static struct resource bfin_twi0_resource[] = {
+	[0] = {
+		.start = TWI0_REGBASE,
+		.end   = TWI0_REGBASE + 0xff,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = IRQ_TWI,
+		.end   = IRQ_TWI,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device i2c_bfin_twi_device = {
+	.name          = "i2c-bfin-twi",
+	.id            = 0,
+	.num_resources = ARRAY_SIZE(bfin_twi0_resource),
+	.resource      = bfin_twi0_resource,
+};
+#endif
+
+static struct platform_device *dnp5370_devices[] __initdata = {
+
+#if defined(CONFIG_SERIAL_BFIN) || defined(CONFIG_SERIAL_BFIN_MODULE)
+#ifdef CONFIG_SERIAL_BFIN_UART0
+	&bfin_uart0_device,
+#endif
+#ifdef CONFIG_SERIAL_BFIN_UART1
+	&bfin_uart1_device,
+#endif
+#endif
+
+#if defined(CONFIG_MTD_PHYSMAP) || defined(CONFIG_MTD_PHYSMAP_MODULE)
+	&asmb_flash_device,
+#endif
+
+#if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
+	&bfin_mii_bus,
+	&bfin_mac_device,
+#endif
+
+#if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
+	&spi_bfin_master_device,
+#endif
+
+#if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
+	&i2c_bfin_twi_device,
+#endif
+
+#if defined(CONFIG_RTC_DRV_BFIN) || defined(CONFIG_RTC_DRV_BFIN_MODULE)
+	&rtc_device,
+#endif
+
+};
+
+static int __init dnp5370_init(void)
+{
+	printk(KERN_INFO "DNP/5370: registering device resources\n");
+	platform_add_devices(dnp5370_devices, ARRAY_SIZE(dnp5370_devices));
+	printk(KERN_INFO "DNP/5370: registering %zu SPI slave devices\n",
+	       ARRAY_SIZE(bfin_spi_board_info));
+	spi_register_board_info(bfin_spi_board_info, ARRAY_SIZE(bfin_spi_board_info));
+	printk(KERN_INFO "DNP/5370: MAC %pM\n", (void *)FLASH_MAC);
+	return 0;
+}
+arch_initcall(dnp5370_init);
+
+/*
+ * Currently the MAC address is saved in Flash by U-Boot
+ */
+void bfin_get_ether_addr(char *addr)
+{
+	*(u32 *)(&(addr[0])) = bfin_read32(FLASH_MAC);
+	*(u16 *)(&(addr[4])) = bfin_read16(FLASH_MAC + 4);
+}
+EXPORT_SYMBOL(bfin_get_ether_addr);
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf537/boards/Kconfig linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf537/boards/Kconfig
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf537/boards/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf537/boards/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -39,4 +39,10 @@ config CAMSIG_MINOTAUR
 	help
 	  Board supply package for CSP Minotaur
 
+config DNP5370
+	bool "SSV Dil/NetPC DNP/5370"
+	depends on (BF537)
+	help
+	  Board supply package for DNP/5370 DIL64 module
+
 endchoice
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf537/boards/Makefile linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf537/boards/Makefile
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf537/boards/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf537/boards/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -8,3 +8,4 @@ obj-$(CONFIG_BFIN537_BLUETECHNIX_CM_U) +
 obj-$(CONFIG_BFIN537_BLUETECHNIX_TCM)  += tcm_bf537.o
 obj-$(CONFIG_PNAV10)                   += pnav10.o
 obj-$(CONFIG_CAMSIG_MINOTAUR)          += minotaur.o
+obj-$(CONFIG_DNP5370)                  += dnp5370.o
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf537/boards/minotaur.c linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf537/boards/minotaur.c
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf537/boards/minotaur.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf537/boards/minotaur.c	2011-03-14 21:20:32.000000000 -0400
@@ -263,7 +263,7 @@ static struct resource bfin_uart0_resour
 	},
 };
 
-unsigned short bfin_uart0_peripherals[] = {
+static unsigned short bfin_uart0_peripherals[] = {
 	P_UART0_TX, P_UART0_RX, 0
 };
 
@@ -306,7 +306,7 @@ static struct resource bfin_uart1_resour
 	},
 };
 
-unsigned short bfin_uart1_peripherals[] = {
+static unsigned short bfin_uart1_peripherals[] = {
 	P_UART1_TX, P_UART1_RX, 0
 };
 
@@ -419,9 +419,9 @@ static struct resource bfin_sport0_uart_
 	},
 };
 
-unsigned short bfin_sport0_peripherals[] = {
+static unsigned short bfin_sport0_peripherals[] = {
 	P_SPORT0_TFS, P_SPORT0_DTPRI, P_SPORT0_TSCLK, P_SPORT0_RFS,
-	P_SPORT0_DRPRI, P_SPORT0_RSCLK, P_SPORT0_DRSEC, P_SPORT0_DTSEC, 0
+	P_SPORT0_DRPRI, P_SPORT0_RSCLK, 0
 };
 
 static struct platform_device bfin_sport0_uart_device = {
@@ -453,9 +453,9 @@ static struct resource bfin_sport1_uart_
 	},
 };
 
-unsigned short bfin_sport1_peripherals[] = {
+static unsigned short bfin_sport1_peripherals[] = {
 	P_SPORT1_TFS, P_SPORT1_DTPRI, P_SPORT1_TSCLK, P_SPORT1_RFS,
-	P_SPORT1_DRPRI, P_SPORT1_RSCLK, P_SPORT1_DRSEC, P_SPORT1_DTSEC, 0
+	P_SPORT1_DRPRI, P_SPORT1_RSCLK, 0
 };
 
 static struct platform_device bfin_sport1_uart_device = {
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf537/boards/pnav10.c linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf537/boards/pnav10.c
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf537/boards/pnav10.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf537/boards/pnav10.c	2011-03-14 21:20:32.000000000 -0400
@@ -367,7 +367,7 @@ static struct resource bfin_uart0_resour
 	},
 };
 
-unsigned short bfin_uart0_peripherals[] = {
+static unsigned short bfin_uart0_peripherals[] = {
 	P_UART0_TX, P_UART0_RX, 0
 };
 
@@ -410,7 +410,7 @@ static struct resource bfin_uart1_resour
 	},
 };
 
-unsigned short bfin_uart1_peripherals[] = {
+static unsigned short bfin_uart1_peripherals[] = {
 	P_UART1_TX, P_UART1_RX, 0
 };
 
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf537/boards/stamp.c linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf537/boards/stamp.c
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf537/boards/stamp.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf537/boards/stamp.c	2011-03-14 21:20:32.000000000 -0400
@@ -289,7 +289,7 @@ static struct platform_device isp1362_hc
 #endif
 
 #if defined(CONFIG_CAN_BFIN) || defined(CONFIG_CAN_BFIN_MODULE)
-unsigned short bfin_can_peripherals[] = {
+static unsigned short bfin_can_peripherals[] = {
 	P_CAN0_RX, P_CAN0_TX, 0
 };
 
@@ -693,7 +693,7 @@ static struct bfin5xx_spi_chip ad2s90_sp
 #endif
 
 #if defined(CONFIG_AD2S120X) || defined(CONFIG_AD2S120X_MODULE)
-unsigned short ad2s120x_platform_data[] = {
+static unsigned short ad2s120x_platform_data[] = {
 	/* used as SAMPLE and RDVEL */
 	GPIO_PF5, GPIO_PF6, 0
 };
@@ -705,7 +705,7 @@ static struct bfin5xx_spi_chip ad2s120x_
 #endif
 
 #if defined(CONFIG_AD2S1210) || defined(CONFIG_AD2S1210_MODULE)
-unsigned short ad2s1210_platform_data[] = {
+static unsigned short ad2s1210_platform_data[] = {
 	/* use as SAMPLE, A0, A1 */
 	GPIO_PF7, GPIO_PF8, GPIO_PF9,
 # if defined(CONFIG_AD2S1210_GPIO_INPUT) || defined(CONFIG_AD2S1210_GPIO_OUTPUT)
@@ -1717,7 +1717,7 @@ static struct resource bfin_uart0_resour
 #endif
 };
 
-unsigned short bfin_uart0_peripherals[] = {
+static unsigned short bfin_uart0_peripherals[] = {
 	P_UART0_TX, P_UART0_RX, 0
 };
 
@@ -1760,7 +1760,7 @@ static struct resource bfin_uart1_resour
 	},
 };
 
-unsigned short bfin_uart1_peripherals[] = {
+static unsigned short bfin_uart1_peripherals[] = {
 	P_UART1_TX, P_UART1_RX, 0
 };
 
@@ -2447,9 +2447,9 @@ static struct resource bfin_sport0_uart_
 	},
 };
 
-unsigned short bfin_sport0_peripherals[] = {
+static unsigned short bfin_sport0_peripherals[] = {
 	P_SPORT0_TFS, P_SPORT0_DTPRI, P_SPORT0_TSCLK, P_SPORT0_RFS,
-	P_SPORT0_DRPRI, P_SPORT0_RSCLK, P_SPORT0_DRSEC, P_SPORT0_DTSEC, 0
+	P_SPORT0_DRPRI, P_SPORT0_RSCLK, 0
 };
 
 static struct platform_device bfin_sport0_uart_device = {
@@ -2481,9 +2481,9 @@ static struct resource bfin_sport1_uart_
 	},
 };
 
-unsigned short bfin_sport1_peripherals[] = {
+static unsigned short bfin_sport1_peripherals[] = {
 	P_SPORT1_TFS, P_SPORT1_DTPRI, P_SPORT1_TSCLK, P_SPORT1_RFS,
-	P_SPORT1_DRPRI, P_SPORT1_RSCLK, P_SPORT1_DRSEC, P_SPORT1_DTSEC, 0
+	P_SPORT1_DRPRI, P_SPORT1_RSCLK, 0
 };
 
 static struct platform_device bfin_sport1_uart_device = {
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf537/boards/tcm_bf537.c linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf537/boards/tcm_bf537.c
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf537/boards/tcm_bf537.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf537/boards/tcm_bf537.c	2011-03-14 21:20:32.000000000 -0400
@@ -356,7 +356,7 @@ static struct resource bfin_uart0_resour
 	},
 };
 
-unsigned short bfin_uart0_peripherals[] = {
+static unsigned short bfin_uart0_peripherals[] = {
 	P_UART0_TX, P_UART0_RX, 0
 };
 
@@ -399,7 +399,7 @@ static struct resource bfin_uart1_resour
 	},
 };
 
-unsigned short bfin_uart1_peripherals[] = {
+static unsigned short bfin_uart1_peripherals[] = {
 	P_UART1_TX, P_UART1_RX, 0
 };
 
@@ -512,9 +512,9 @@ static struct resource bfin_sport0_uart_
 	},
 };
 
-unsigned short bfin_sport0_peripherals[] = {
+static unsigned short bfin_sport0_peripherals[] = {
 	P_SPORT0_TFS, P_SPORT0_DTPRI, P_SPORT0_TSCLK, P_SPORT0_RFS,
-	P_SPORT0_DRPRI, P_SPORT0_RSCLK, P_SPORT0_DRSEC, P_SPORT0_DTSEC, 0
+	P_SPORT0_DRPRI, P_SPORT0_RSCLK, 0
 };
 
 static struct platform_device bfin_sport0_uart_device = {
@@ -546,9 +546,9 @@ static struct resource bfin_sport1_uart_
 	},
 };
 
-unsigned short bfin_sport1_peripherals[] = {
+static unsigned short bfin_sport1_peripherals[] = {
 	P_SPORT1_TFS, P_SPORT1_DTPRI, P_SPORT1_TSCLK, P_SPORT1_RFS,
-	P_SPORT1_DRPRI, P_SPORT1_RSCLK, P_SPORT1_DRSEC, P_SPORT1_DTSEC, 0
+	P_SPORT1_DRPRI, P_SPORT1_RSCLK, 0
 };
 
 static struct platform_device bfin_sport1_uart_device = {
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf537/dma.c linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf537/dma.c
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf537/dma.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf537/dma.c	2011-03-14 21:20:32.000000000 -0400
@@ -11,7 +11,7 @@
 #include <asm/blackfin.h>
 #include <asm/dma.h>
 
-struct dma_register *dma_io_base_addr[MAX_DMA_CHANNELS] = {
+struct dma_register * const dma_io_base_addr[MAX_DMA_CHANNELS] = {
 	(struct dma_register *) DMA0_NEXT_DESC_PTR,
 	(struct dma_register *) DMA1_NEXT_DESC_PTR,
 	(struct dma_register *) DMA2_NEXT_DESC_PTR,
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf537/include/mach/bfin_serial_5xx.h linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf537/include/mach/bfin_serial_5xx.h
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf537/include/mach/bfin_serial_5xx.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf537/include/mach/bfin_serial_5xx.h	2011-03-14 21:20:32.000000000 -0400
@@ -4,36 +4,9 @@
  * Licensed under the GPL-2 or later
  */
 
-#include <linux/serial.h>
 #include <asm/dma.h>
 #include <asm/portmux.h>
 
-#define UART_GET_CHAR(uart)     bfin_read16(((uart)->port.membase + OFFSET_RBR))
-#define UART_GET_DLL(uart)	bfin_read16(((uart)->port.membase + OFFSET_DLL))
-#define UART_GET_IER(uart)      bfin_read16(((uart)->port.membase + OFFSET_IER))
-#define UART_GET_DLH(uart)	bfin_read16(((uart)->port.membase + OFFSET_DLH))
-#define UART_GET_IIR(uart)      bfin_read16(((uart)->port.membase + OFFSET_IIR))
-#define UART_GET_LCR(uart)      bfin_read16(((uart)->port.membase + OFFSET_LCR))
-#define UART_GET_GCTL(uart)     bfin_read16(((uart)->port.membase + OFFSET_GCTL))
-
-#define UART_PUT_CHAR(uart,v)   bfin_write16(((uart)->port.membase + OFFSET_THR),v)
-#define UART_PUT_DLL(uart,v)    bfin_write16(((uart)->port.membase + OFFSET_DLL),v)
-#define UART_PUT_IER(uart,v)    bfin_write16(((uart)->port.membase + OFFSET_IER),v)
-#define UART_SET_IER(uart,v)    UART_PUT_IER(uart, UART_GET_IER(uart) | (v))
-#define UART_CLEAR_IER(uart,v)  UART_PUT_IER(uart, UART_GET_IER(uart) & ~(v))
-#define UART_PUT_DLH(uart,v)    bfin_write16(((uart)->port.membase + OFFSET_DLH),v)
-#define UART_PUT_LCR(uart,v)    bfin_write16(((uart)->port.membase + OFFSET_LCR),v)
-#define UART_PUT_GCTL(uart,v)   bfin_write16(((uart)->port.membase + OFFSET_GCTL),v)
-
-#define UART_SET_DLAB(uart)     do { UART_PUT_LCR(uart, UART_GET_LCR(uart) | DLAB); SSYNC(); } while (0)
-#define UART_CLEAR_DLAB(uart)   do { UART_PUT_LCR(uart, UART_GET_LCR(uart) & ~DLAB); SSYNC(); } while (0)
-
-#define UART_GET_CTS(x) gpio_get_value(x->cts_pin)
-#define UART_DISABLE_RTS(x) gpio_set_value(x->rts_pin, 1)
-#define UART_ENABLE_RTS(x) gpio_set_value(x->rts_pin, 0)
-#define UART_ENABLE_INTS(x, v) UART_PUT_IER(x, v)
-#define UART_DISABLE_INTS(x) UART_PUT_IER(x, 0)
-
 #if defined(CONFIG_BFIN_UART0_CTSRTS) || defined(CONFIG_BFIN_UART1_CTSRTS)
 # define CONFIG_SERIAL_BFIN_CTSRTS
 
@@ -54,49 +27,6 @@
 # endif
 #endif
 
-#define BFIN_UART_TX_FIFO_SIZE	2
-
-/*
- * The pin configuration is different from schematic
- */
-struct bfin_serial_port {
-        struct uart_port        port;
-        unsigned int            old_status;
-	int			status_irq;
-	unsigned int lsr;
-#ifdef CONFIG_SERIAL_BFIN_DMA
-	int			tx_done;
-	int			tx_count;
-	struct circ_buf		rx_dma_buf;
-	struct timer_list       rx_dma_timer;
-	int			rx_dma_nrows;
-	unsigned int		tx_dma_channel;
-	unsigned int		rx_dma_channel;
-	struct work_struct	tx_dma_workqueue;
-#endif
-#ifdef CONFIG_SERIAL_BFIN_CTSRTS
-	int		cts_pin;
-	int 		rts_pin;
-#endif
-};
-
-/* The hardware clears the LSR bits upon read, so we need to cache
- * some of the more fun bits in software so they don't get lost
- * when checking the LSR in other code paths (TX).
- */
-static inline unsigned int UART_GET_LSR(struct bfin_serial_port *uart)
-{
-	unsigned int lsr = bfin_read16(uart->port.membase + OFFSET_LSR);
-	uart->lsr |= (lsr & (BI|FE|PE|OE));
-	return lsr | uart->lsr;
-}
-
-static inline void UART_CLEAR_LSR(struct bfin_serial_port *uart)
-{
-	uart->lsr = 0;
-	bfin_write16(uart->port.membase + OFFSET_LSR, -1);
-}
-
 struct bfin_serial_res {
 	unsigned long	uart_base_addr;
 	int		uart_irq;
@@ -145,3 +75,5 @@ struct bfin_serial_res bfin_serial_resou
 };
 
 #define DRIVER_NAME "bfin-uart"
+
+#include <asm/bfin_serial.h>
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf537/include/mach/bfin_serial.h linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf537/include/mach/bfin_serial.h
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf537/include/mach/bfin_serial.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf537/include/mach/bfin_serial.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,14 @@
+/*
+ * mach/bfin_serial.h - Blackfin UART/Serial definitions
+ *
+ * Copyright 2006-2010 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#ifndef __BFIN_MACH_SERIAL_H__
+#define __BFIN_MACH_SERIAL_H__
+
+#define BFIN_UART_NR_PORTS	2
+
+#endif
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf537/include/mach/blackfin.h linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf537/include/mach/blackfin.h
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf537/include/mach/blackfin.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf537/include/mach/blackfin.h	2011-03-14 21:20:32.000000000 -0400
@@ -1,7 +1,7 @@
 /*
- * Copyright 2005-2009 Analog Devices Inc.
+ * Copyright 2005-2010 Analog Devices Inc.
  *
- * Licensed under the GPL-2 or later
+ * Licensed under the GPL-2 or later.
  */
 
 #ifndef _MACH_BLACKFIN_H_
@@ -10,34 +10,24 @@
 #define BF537_FAMILY
 
 #include "bf537.h"
-#include "defBF534.h"
 #include "anomaly.h"
 
+#include <asm/def_LPBlackfin.h>
+#ifdef CONFIG_BF534
+# include "defBF534.h"
+#endif
 #if defined(CONFIG_BF537) || defined(CONFIG_BF536)
-#include "defBF537.h"
+# include "defBF537.h"
 #endif
 
 #if !defined(__ASSEMBLY__)
-#include "cdefBF534.h"
-
-#if defined(CONFIG_BF537) || defined(CONFIG_BF536)
-#include "cdefBF537.h"
-#endif
+# include <asm/cdef_LPBlackfin.h>
+# ifdef CONFIG_BF534
+#  include "cdefBF534.h"
+# endif
+# if defined(CONFIG_BF537) || defined(CONFIG_BF536)
+#  include "cdefBF537.h"
+# endif
 #endif
 
-#define BFIN_UART_NR_PORTS	2
-
-#define OFFSET_THR              0x00	/* Transmit Holding register            */
-#define OFFSET_RBR              0x00	/* Receive Buffer register              */
-#define OFFSET_DLL              0x00	/* Divisor Latch (Low-Byte)             */
-#define OFFSET_IER              0x04	/* Interrupt Enable Register            */
-#define OFFSET_DLH              0x04	/* Divisor Latch (High-Byte)            */
-#define OFFSET_IIR              0x08	/* Interrupt Identification Register    */
-#define OFFSET_LCR              0x0C	/* Line Control Register                */
-#define OFFSET_MCR              0x10	/* Modem Control Register               */
-#define OFFSET_LSR              0x14	/* Line Status Register                 */
-#define OFFSET_MSR              0x18	/* Modem Status Register                */
-#define OFFSET_SCR              0x1C	/* SCR Scratch Register                 */
-#define OFFSET_GCTL             0x24	/* Global Control Register              */
-
 #endif
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf537/include/mach/cdefBF534.h linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf537/include/mach/cdefBF534.h
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf537/include/mach/cdefBF534.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf537/include/mach/cdefBF534.h	2011-03-14 21:20:32.000000000 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright 2005-2008 Analog Devices Inc.
+ * Copyright 2005-2010 Analog Devices Inc.
  *
  * Licensed under the GPL-2 or later
  */
@@ -7,14 +7,6 @@
 #ifndef _CDEF_BF534_H
 #define _CDEF_BF534_H
 
-#include <asm/blackfin.h>
-
-/* Include all Core registers and bit definitions 									*/
-#include "defBF534.h"
-
-/* Include core specific register pointer definitions 								*/
-#include <asm/cdef_LPBlackfin.h>
-
 /* Clock and System Control	(0xFFC00000 - 0xFFC000FF)								*/
 #define bfin_read_PLL_CTL()                  bfin_read16(PLL_CTL)
 #define bfin_read_PLL_DIV()                  bfin_read16(PLL_DIV)
@@ -355,16 +347,10 @@
 #define bfin_write_EBIU_SDSTAT(val)          bfin_write16(EBIU_SDSTAT,val)
 
 /* DMA Traffic Control Registers													*/
-#define bfin_read_DMA_TC_PER()                bfin_read16(DMA_TC_PER)
-#define bfin_write_DMA_TC_PER(val)            bfin_write16(DMA_TC_PER,val)
-#define bfin_read_DMA_TC_CNT()                bfin_read16(DMA_TC_CNT)
-#define bfin_write_DMA_TC_CNT(val)            bfin_write16(DMA_TC_CNT,val)
-
-/* Alternate deprecated register names (below) provided for backwards code compatibility */
-#define bfin_read_DMA_TCPER()                bfin_read16(DMA_TCPER)
-#define bfin_write_DMA_TCPER(val)            bfin_write16(DMA_TCPER,val)
-#define bfin_read_DMA_TCCNT()                bfin_read16(DMA_TCCNT)
-#define bfin_write_DMA_TCCNT(val)            bfin_write16(DMA_TCCNT,val)
+#define bfin_read_DMAC_TC_PER()              bfin_read16(DMAC_TC_PER)
+#define bfin_write_DMAC_TC_PER(val)          bfin_write16(DMAC_TC_PER,val)
+#define bfin_read_DMAC_TC_CNT()              bfin_read16(DMAC_TC_CNT)
+#define bfin_write_DMAC_TC_CNT(val)          bfin_write16(DMAC_TC_CNT,val)
 
 /* DMA Controller																	*/
 #define bfin_read_DMA0_CONFIG()              bfin_read16(DMA0_CONFIG)
@@ -1747,7 +1733,4 @@
 #define bfin_read_HMDMA1_BCOUNT()            bfin_read16(HMDMA1_BCOUNT)
 #define bfin_write_HMDMA1_BCOUNT(val)        bfin_write16(HMDMA1_BCOUNT,val)
 
-/* These need to be last due to the cdef/linux inter-dependencies */
-#include <asm/irq.h>
-
 #endif				/* _CDEF_BF534_H */
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf537/include/mach/cdefBF537.h linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf537/include/mach/cdefBF537.h
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf537/include/mach/cdefBF537.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf537/include/mach/cdefBF537.h	2011-03-14 21:20:32.000000000 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright 2005-2008 Analog Devices Inc.
+ * Copyright 2005-2010 Analog Devices Inc.
  *
  * Licensed under the GPL-2 or later
  */
@@ -10,9 +10,6 @@
 /* Include MMRs Common to BF534 								*/
 #include "cdefBF534.h"
 
-/* Include all Core registers and bit definitions 									*/
-#include "defBF537.h"
-
 /* Include Macro "Defines" For EMAC (Unique to BF536/BF537		*/
 /* 10/100 Ethernet Controller	(0xFFC03000 - 0xFFC031FF) 						*/
 #define bfin_read_EMAC_OPMODE()              bfin_read32(EMAC_OPMODE)
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf537/include/mach/defBF534.h linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf537/include/mach/defBF534.h
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf537/include/mach/defBF534.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf537/include/mach/defBF534.h	2011-03-14 21:20:32.000000000 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright 2005-2008 Analog Devices Inc.
+ * Copyright 2005-2010 Analog Devices Inc.
  *
  * Licensed under the ADI BSD license or the GPL-2 (or later)
  */
@@ -7,9 +7,6 @@
 #ifndef _DEF_BF534_H
 #define _DEF_BF534_H
 
-/* Include all Core registers and bit definitions */
-#include <asm/def_LPBlackfin.h>
-
 /************************************************************************************
 ** System MMR Register Map
 *************************************************************************************/
@@ -193,12 +190,8 @@
 #define EBIU_SDSTAT			0xFFC00A1C	/* SDRAM Status Register                                                */
 
 /* DMA Traffic Control Registers													*/
-#define DMA_TC_PER			0xFFC00B0C	/* Traffic Control Periods Register			*/
-#define DMA_TC_CNT			0xFFC00B10	/* Traffic Control Current Counts Register	*/
-
-/* Alternate deprecated register names (below) provided for backwards code compatibility */
-#define DMA_TCPER			0xFFC00B0C	/* Traffic Control Periods Register			*/
-#define DMA_TCCNT			0xFFC00B10	/* Traffic Control Current Counts Register	*/
+#define DMAC_TC_PER			0xFFC00B0C	/* Traffic Control Periods Register			*/
+#define DMAC_TC_CNT			0xFFC00B10	/* Traffic Control Current Counts Register	*/
 
 /* DMA Controller (0xFFC00C00 - 0xFFC00FFF)															*/
 #define DMA0_NEXT_DESC_PTR		0xFFC00C00	/* DMA Channel 0 Next Descriptor Pointer Register               */
@@ -1029,48 +1022,6 @@
 #define IWR_ENABLE(x)	(1 << ((x)&0x1F))	/* Wakeup Enable Peripheral #x          */
 #define IWR_DISABLE(x)	(0xFFFFFFFF ^ (1 << ((x)&0x1F)))	/* Wakeup Disable Peripheral #x         */
 
-/* ************** UART CONTROLLER MASKS *************************/
-/* UARTx_LCR Masks												*/
-#define WLS(x)		(((x)-5) & 0x03)	/* Word Length Select   */
-#define STB			0x04	/* Stop Bits                    */
-#define PEN			0x08	/* Parity Enable                */
-#define EPS			0x10	/* Even Parity Select   */
-#define STP			0x20	/* Stick Parity                 */
-#define SB			0x40	/* Set Break                    */
-#define DLAB		0x80	/* Divisor Latch Access */
-
-/* UARTx_MCR Mask										*/
-#define LOOP_ENA		0x10	/* Loopback Mode Enable         */
-#define LOOP_ENA_P	0x04
-/* UARTx_LSR Masks										*/
-#define DR			0x01	/* Data Ready                           */
-#define OE			0x02	/* Overrun Error                        */
-#define PE			0x04	/* Parity Error                         */
-#define FE			0x08	/* Framing Error                        */
-#define BI			0x10	/* Break Interrupt                      */
-#define THRE		0x20	/* THR Empty                            */
-#define TEMT		0x40	/* TSR and UART_THR Empty       */
-
-/* UARTx_IER Masks															*/
-#define ERBFI		0x01	/* Enable Receive Buffer Full Interrupt         */
-#define ETBEI		0x02	/* Enable Transmit Buffer Empty Interrupt       */
-#define ELSI		0x04	/* Enable RX Status Interrupt                           */
-
-/* UARTx_IIR Masks														*/
-#define NINT		0x01	/* Pending Interrupt                                    */
-#define IIR_TX_READY    0x02	/* UART_THR empty                               */
-#define IIR_RX_READY    0x04	/* Receive data ready                           */
-#define IIR_LINE_CHANGE 0x06	/* Receive line status                          */
-#define IIR_STATUS	0x06
-
-/* UARTx_GCTL Masks													*/
-#define UCEN		0x01	/* Enable UARTx Clocks                          */
-#define IREN		0x02	/* Enable IrDA Mode                                     */
-#define TPOLC		0x04	/* IrDA TX Polarity Change                      */
-#define RPOLC		0x08	/* IrDA RX Polarity Change                      */
-#define FPE			0x10	/* Force Parity Error On Transmit       */
-#define FFE			0x20	/* Force Framing Error On Transmit      */
-
 /*  ****************  GENERAL PURPOSE TIMER MASKS  **********************/
 /* TIMER_ENABLE Masks													*/
 #define TIMEN0			0x0001	/* Enable Timer 0                                       */
@@ -1141,62 +1092,6 @@
 #define EMU_RUN			0x0200	/* Emulation Behavior Select                    */
 #define ERR_TYP			0xC000	/* Error Type                                                   */
 
-/* ******************   GPIO PORTS F, G, H MASKS  ***********************/
-/*  General Purpose IO (0xFFC00700 - 0xFFC007FF)  Masks 				*/
-/* Port F Masks 														*/
-#define PF0		0x0001
-#define PF1		0x0002
-#define PF2		0x0004
-#define PF3		0x0008
-#define PF4		0x0010
-#define PF5		0x0020
-#define PF6		0x0040
-#define PF7		0x0080
-#define PF8		0x0100
-#define PF9		0x0200
-#define PF10	0x0400
-#define PF11	0x0800
-#define PF12	0x1000
-#define PF13	0x2000
-#define PF14	0x4000
-#define PF15	0x8000
-
-/* Port G Masks															*/
-#define PG0		0x0001
-#define PG1		0x0002
-#define PG2		0x0004
-#define PG3		0x0008
-#define PG4		0x0010
-#define PG5		0x0020
-#define PG6		0x0040
-#define PG7		0x0080
-#define PG8		0x0100
-#define PG9		0x0200
-#define PG10	0x0400
-#define PG11	0x0800
-#define PG12	0x1000
-#define PG13	0x2000
-#define PG14	0x4000
-#define PG15	0x8000
-
-/* Port H Masks															*/
-#define PH0		0x0001
-#define PH1		0x0002
-#define PH2		0x0004
-#define PH3		0x0008
-#define PH4		0x0010
-#define PH5		0x0020
-#define PH6		0x0040
-#define PH7		0x0080
-#define PH8		0x0100
-#define PH9		0x0200
-#define PH10	0x0400
-#define PH11	0x0800
-#define PH12	0x1000
-#define PH13	0x2000
-#define PH14	0x4000
-#define PH15	0x8000
-
 /* *********************  ASYNCHRONOUS MEMORY CONTROLLER MASKS  *************************/
 /* EBIU_AMGCTL Masks																	*/
 #define AMCKEN			0x0001	/* Enable CLKOUT                                                                        */
@@ -1523,7 +1418,7 @@
 #define	SADD_LEN	0x0002	/* Slave Address Length                                                 */
 #define	STDVAL		0x0004	/* Slave Transmit Data Valid                                    */
 #define	NAK			0x0008	/* NAK/ACK* Generated At Conclusion Of Transfer */
-#define	GEN			0x0010	/* General Call Adrress Matching Enabled                */
+#define	GEN			0x0010	/* General Call Address Matching Enabled                */
 
 /* TWI_SLAVE_STAT Masks															*/
 #define	SDIR		0x0001	/* Slave Transfer Direction (Transmit/Receive*) */
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf537/include/mach/defBF537.h linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf537/include/mach/defBF537.h
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf537/include/mach/defBF537.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf537/include/mach/defBF537.h	2011-03-14 21:20:32.000000000 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright 2005-2008 Analog Devices Inc.
+ * Copyright 2005-2010 Analog Devices Inc.
  *
  * Licensed under the ADI BSD license or the GPL-2 (or later)
  */
@@ -7,9 +7,6 @@
 #ifndef _DEF_BF537_H
 #define _DEF_BF537_H
 
-/* Include all Core registers and bit definitions*/
-#include <asm/cdef_LPBlackfin.h>
-
 /* Include all MMR and bit defines common to BF534 */
 #include "defBF534.h"
 
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf537/include/mach/gpio.h linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf537/include/mach/gpio.h
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf537/include/mach/gpio.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf537/include/mach/gpio.h	2011-03-14 21:20:32.000000000 -0400
@@ -62,4 +62,8 @@
 #define PORT_G GPIO_PG0
 #define PORT_H GPIO_PH0
 
+#include <mach-common/ports-f.h>
+#include <mach-common/ports-g.h>
+#include <mach-common/ports-h.h>
+
 #endif /* _MACH_GPIO_H_ */
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf537/include/mach/pll.h linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf537/include/mach/pll.h
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf537/include/mach/pll.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf537/include/mach/pll.h	2011-03-14 21:20:32.000000000 -0400
@@ -1,57 +1 @@
-/*
- * Copyright 2005-2008 Analog Devices Inc.
- *
- * Licensed under the GPL-2 or later
- */
-
-#ifndef _MACH_PLL_H
-#define _MACH_PLL_H
-
-#include <asm/blackfin.h>
-#include <asm/irqflags.h>
-
-/* Writing to PLL_CTL initiates a PLL relock sequence. */
-static __inline__ void bfin_write_PLL_CTL(unsigned int val)
-{
-	unsigned long flags, iwr;
-
-	if (val == bfin_read_PLL_CTL())
-		return;
-
-	flags = hard_local_irq_save();
-	/* Enable the PLL Wakeup bit in SIC IWR */
-	iwr = bfin_read32(SIC_IWR);
-	/* Only allow PPL Wakeup) */
-	bfin_write32(SIC_IWR, IWR_ENABLE(0));
-
-	bfin_write16(PLL_CTL, val);
-	SSYNC();
-	asm("IDLE;");
-
-	bfin_write32(SIC_IWR, iwr);
-	hard_local_irq_restore(flags);
-}
-
-/* Writing to VR_CTL initiates a PLL relock sequence. */
-static __inline__ void bfin_write_VR_CTL(unsigned int val)
-{
-	unsigned long flags, iwr;
-
-	if (val == bfin_read_VR_CTL())
-		return;
-
-	flags = hard_local_irq_save();
-	/* Enable the PLL Wakeup bit in SIC IWR */
-	iwr = bfin_read32(SIC_IWR);
-	/* Only allow PPL Wakeup) */
-	bfin_write32(SIC_IWR, IWR_ENABLE(0));
-
-	bfin_write16(VR_CTL, val);
-	SSYNC();
-	asm("IDLE;");
-
-	bfin_write32(SIC_IWR, iwr);
-	hard_local_irq_restore(flags);
-}
-
-#endif /* _MACH_PLL_H */
+#include <mach-common/pll.h>
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf538/boards/ezkit.c linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf538/boards/ezkit.c
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf538/boards/ezkit.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf538/boards/ezkit.c	2011-03-14 21:20:32.000000000 -0400
@@ -82,7 +82,7 @@ static struct resource bfin_uart0_resour
 #endif
 };
 
-unsigned short bfin_uart0_peripherals[] = {
+static unsigned short bfin_uart0_peripherals[] = {
 	P_UART0_TX, P_UART0_RX, 0
 };
 
@@ -125,7 +125,7 @@ static struct resource bfin_uart1_resour
 	},
 };
 
-unsigned short bfin_uart1_peripherals[] = {
+static unsigned short bfin_uart1_peripherals[] = {
 	P_UART1_TX, P_UART1_RX, 0
 };
 
@@ -168,7 +168,7 @@ static struct resource bfin_uart2_resour
 	},
 };
 
-unsigned short bfin_uart2_peripherals[] = {
+static unsigned short bfin_uart2_peripherals[] = {
 	P_UART2_TX, P_UART2_RX, 0
 };
 
@@ -282,9 +282,9 @@ static struct resource bfin_sport0_uart_
 	},
 };
 
-unsigned short bfin_sport0_peripherals[] = {
+static unsigned short bfin_sport0_peripherals[] = {
 	P_SPORT0_TFS, P_SPORT0_DTPRI, P_SPORT0_TSCLK, P_SPORT0_RFS,
-	P_SPORT0_DRPRI, P_SPORT0_RSCLK, P_SPORT0_DRSEC, P_SPORT0_DTSEC, 0
+	P_SPORT0_DRPRI, P_SPORT0_RSCLK, 0
 };
 
 static struct platform_device bfin_sport0_uart_device = {
@@ -316,9 +316,9 @@ static struct resource bfin_sport1_uart_
 	},
 };
 
-unsigned short bfin_sport1_peripherals[] = {
+static unsigned short bfin_sport1_peripherals[] = {
 	P_SPORT1_TFS, P_SPORT1_DTPRI, P_SPORT1_TSCLK, P_SPORT1_RFS,
-	P_SPORT1_DRPRI, P_SPORT1_RSCLK, P_SPORT1_DRSEC, P_SPORT1_DTSEC, 0
+	P_SPORT1_DRPRI, P_SPORT1_RSCLK, 0
 };
 
 static struct platform_device bfin_sport1_uart_device = {
@@ -350,7 +350,7 @@ static struct resource bfin_sport2_uart_
 	},
 };
 
-unsigned short bfin_sport2_peripherals[] = {
+static unsigned short bfin_sport2_peripherals[] = {
 	P_SPORT2_TFS, P_SPORT2_DTPRI, P_SPORT2_TSCLK, P_SPORT2_RFS,
 	P_SPORT2_DRPRI, P_SPORT2_RSCLK, P_SPORT2_DRSEC, P_SPORT2_DTSEC, 0
 };
@@ -384,7 +384,7 @@ static struct resource bfin_sport3_uart_
 	},
 };
 
-unsigned short bfin_sport3_peripherals[] = {
+static unsigned short bfin_sport3_peripherals[] = {
 	P_SPORT3_TFS, P_SPORT3_DTPRI, P_SPORT3_TSCLK, P_SPORT3_RFS,
 	P_SPORT3_DRPRI, P_SPORT3_RSCLK, P_SPORT3_DRSEC, P_SPORT3_DTSEC, 0
 };
@@ -402,7 +402,7 @@ static struct platform_device bfin_sport
 #endif
 
 #if defined(CONFIG_CAN_BFIN) || defined(CONFIG_CAN_BFIN_MODULE)
-unsigned short bfin_can_peripherals[] = {
+static unsigned short bfin_can_peripherals[] = {
 	P_CAN0_RX, P_CAN0_TX, 0
 };
 
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf538/dma.c linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf538/dma.c
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf538/dma.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf538/dma.c	2011-03-14 21:20:32.000000000 -0400
@@ -11,7 +11,7 @@
 #include <asm/blackfin.h>
 #include <asm/dma.h>
 
-struct dma_register *dma_io_base_addr[MAX_DMA_CHANNELS] = {
+struct dma_register * const dma_io_base_addr[MAX_DMA_CHANNELS] = {
 	(struct dma_register *) DMA0_NEXT_DESC_PTR,
 	(struct dma_register *) DMA1_NEXT_DESC_PTR,
 	(struct dma_register *) DMA2_NEXT_DESC_PTR,
@@ -32,14 +32,14 @@ struct dma_register *dma_io_base_addr[MA
 	(struct dma_register *) DMA17_NEXT_DESC_PTR,
 	(struct dma_register *) DMA18_NEXT_DESC_PTR,
 	(struct dma_register *) DMA19_NEXT_DESC_PTR,
-	(struct dma_register *) MDMA0_D0_NEXT_DESC_PTR,
-	(struct dma_register *) MDMA0_S0_NEXT_DESC_PTR,
-	(struct dma_register *) MDMA0_D1_NEXT_DESC_PTR,
-	(struct dma_register *) MDMA0_S1_NEXT_DESC_PTR,
-	(struct dma_register *) MDMA1_D0_NEXT_DESC_PTR,
-	(struct dma_register *) MDMA1_S0_NEXT_DESC_PTR,
-	(struct dma_register *) MDMA1_D1_NEXT_DESC_PTR,
-	(struct dma_register *) MDMA1_S1_NEXT_DESC_PTR,
+	(struct dma_register *) MDMA_D0_NEXT_DESC_PTR,
+	(struct dma_register *) MDMA_S0_NEXT_DESC_PTR,
+	(struct dma_register *) MDMA_D1_NEXT_DESC_PTR,
+	(struct dma_register *) MDMA_S1_NEXT_DESC_PTR,
+	(struct dma_register *) MDMA_D2_NEXT_DESC_PTR,
+	(struct dma_register *) MDMA_S2_NEXT_DESC_PTR,
+	(struct dma_register *) MDMA_D3_NEXT_DESC_PTR,
+	(struct dma_register *) MDMA_S3_NEXT_DESC_PTR,
 };
 EXPORT_SYMBOL(dma_io_base_addr);
 
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf538/include/mach/bfin_serial_5xx.h linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf538/include/mach/bfin_serial_5xx.h
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf538/include/mach/bfin_serial_5xx.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf538/include/mach/bfin_serial_5xx.h	2011-03-14 21:20:32.000000000 -0400
@@ -4,36 +4,9 @@
  * Licensed under the GPL-2 or later.
  */
 
-#include <linux/serial.h>
 #include <asm/dma.h>
 #include <asm/portmux.h>
 
-#define UART_GET_CHAR(uart)     bfin_read16(((uart)->port.membase + OFFSET_RBR))
-#define UART_GET_DLL(uart)	bfin_read16(((uart)->port.membase + OFFSET_DLL))
-#define UART_GET_IER(uart)      bfin_read16(((uart)->port.membase + OFFSET_IER))
-#define UART_GET_DLH(uart)	bfin_read16(((uart)->port.membase + OFFSET_DLH))
-#define UART_GET_IIR(uart)      bfin_read16(((uart)->port.membase + OFFSET_IIR))
-#define UART_GET_LCR(uart)      bfin_read16(((uart)->port.membase + OFFSET_LCR))
-#define UART_GET_GCTL(uart)     bfin_read16(((uart)->port.membase + OFFSET_GCTL))
-
-#define UART_PUT_CHAR(uart, v)   bfin_write16(((uart)->port.membase + OFFSET_THR), v)
-#define UART_PUT_DLL(uart, v)    bfin_write16(((uart)->port.membase + OFFSET_DLL), v)
-#define UART_PUT_IER(uart, v)    bfin_write16(((uart)->port.membase + OFFSET_IER), v)
-#define UART_SET_IER(uart, v)    UART_PUT_IER(uart, UART_GET_IER(uart) | (v))
-#define UART_CLEAR_IER(uart, v)  UART_PUT_IER(uart, UART_GET_IER(uart) & ~(v))
-#define UART_PUT_DLH(uart, v)    bfin_write16(((uart)->port.membase + OFFSET_DLH), v)
-#define UART_PUT_LCR(uart, v)    bfin_write16(((uart)->port.membase + OFFSET_LCR), v)
-#define UART_PUT_GCTL(uart, v)   bfin_write16(((uart)->port.membase + OFFSET_GCTL), v)
-
-#define UART_SET_DLAB(uart)     do { UART_PUT_LCR(uart, UART_GET_LCR(uart) | DLAB); SSYNC(); } while (0)
-#define UART_CLEAR_DLAB(uart)   do { UART_PUT_LCR(uart, UART_GET_LCR(uart) & ~DLAB); SSYNC(); } while (0)
-
-#define UART_GET_CTS(x) gpio_get_value(x->cts_pin)
-#define UART_DISABLE_RTS(x) gpio_set_value(x->rts_pin, 1)
-#define UART_ENABLE_RTS(x) gpio_set_value(x->rts_pin, 0)
-#define UART_ENABLE_INTS(x, v) UART_PUT_IER(x, v)
-#define UART_DISABLE_INTS(x) UART_PUT_IER(x, 0)
-
 #if defined(CONFIG_BFIN_UART0_CTSRTS) || defined(CONFIG_BFIN_UART1_CTSRTS)
 # define CONFIG_SERIAL_BFIN_CTSRTS
 
@@ -54,50 +27,6 @@
 # endif
 #endif
 
-#define BFIN_UART_TX_FIFO_SIZE	2
-
-/*
- * The pin configuration is different from schematic
- */
-struct bfin_serial_port {
-	struct uart_port	port;
-	unsigned int		old_status;
-	int			status_irq;
-	unsigned int lsr;
-#ifdef CONFIG_SERIAL_BFIN_DMA
-	int			tx_done;
-	int			tx_count;
-	struct circ_buf		rx_dma_buf;
-	struct timer_list       rx_dma_timer;
-	int			rx_dma_nrows;
-	unsigned int		tx_dma_channel;
-	unsigned int		rx_dma_channel;
-	struct work_struct	tx_dma_workqueue;
-#endif
-#ifdef CONFIG_SERIAL_BFIN_CTSRTS
-	struct timer_list	cts_timer;
-	int		cts_pin;
-	int		rts_pin;
-#endif
-};
-
-/* The hardware clears the LSR bits upon read, so we need to cache
- * some of the more fun bits in software so they don't get lost
- * when checking the LSR in other code paths (TX).
- */
-static inline unsigned int UART_GET_LSR(struct bfin_serial_port *uart)
-{
-	unsigned int lsr = bfin_read16(uart->port.membase + OFFSET_LSR);
-	uart->lsr |= (lsr & (BI|FE|PE|OE));
-	return lsr | uart->lsr;
-}
-
-static inline void UART_CLEAR_LSR(struct bfin_serial_port *uart)
-{
-	uart->lsr = 0;
-	bfin_write16(uart->port.membase + OFFSET_LSR, -1);
-}
-
 struct bfin_serial_res {
 	unsigned long	uart_base_addr;
 	int		uart_irq;
@@ -160,3 +89,5 @@ struct bfin_serial_res bfin_serial_resou
 };
 
 #define DRIVER_NAME "bfin-uart"
+
+#include <asm/bfin_serial.h>
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf538/include/mach/bfin_serial.h linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf538/include/mach/bfin_serial.h
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf538/include/mach/bfin_serial.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf538/include/mach/bfin_serial.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,14 @@
+/*
+ * mach/bfin_serial.h - Blackfin UART/Serial definitions
+ *
+ * Copyright 2006-2010 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#ifndef __BFIN_MACH_SERIAL_H__
+#define __BFIN_MACH_SERIAL_H__
+
+#define BFIN_UART_NR_PORTS	3
+
+#endif
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf538/include/mach/blackfin.h linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf538/include/mach/blackfin.h
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf538/include/mach/blackfin.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf538/include/mach/blackfin.h	2011-03-14 21:20:32.000000000 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright 2008-2009 Analog Devices Inc.
+ * Copyright 2008-2010 Analog Devices Inc.
  *
  * Licensed under the GPL-2 or later.
  */
@@ -10,31 +10,24 @@
 #define BF538_FAMILY
 
 #include "bf538.h"
-#include "defBF539.h"
 #include "anomaly.h"
 
-
-#if !defined(__ASSEMBLY__)
-#include "cdefBF538.h"
-
-#if defined(CONFIG_BF539)
-#include "cdefBF539.h"
+#include <asm/def_LPBlackfin.h>
+#ifdef CONFIG_BF538
+# include "defBF538.h"
 #endif
+#ifdef CONFIG_BF539
+# include "defBF539.h"
 #endif
 
-#define BFIN_UART_NR_PORTS	3
-
-#define OFFSET_THR              0x00	/* Transmit Holding register            */
-#define OFFSET_RBR              0x00	/* Receive Buffer register              */
-#define OFFSET_DLL              0x00	/* Divisor Latch (Low-Byte)             */
-#define OFFSET_IER              0x04	/* Interrupt Enable Register            */
-#define OFFSET_DLH              0x04	/* Divisor Latch (High-Byte)            */
-#define OFFSET_IIR              0x08	/* Interrupt Identification Register    */
-#define OFFSET_LCR              0x0C	/* Line Control Register                */
-#define OFFSET_MCR              0x10	/* Modem Control Register               */
-#define OFFSET_LSR              0x14	/* Line Status Register                 */
-#define OFFSET_MSR              0x18	/* Modem Status Register                */
-#define OFFSET_SCR              0x1C	/* SCR Scratch Register                 */
-#define OFFSET_GCTL             0x24	/* Global Control Register              */
+#ifndef __ASSEMBLY__
+# include <asm/cdef_LPBlackfin.h>
+# ifdef CONFIG_BF538
+#  include "cdefBF538.h"
+# endif
+# ifdef CONFIG_BF539
+#  include "cdefBF539.h"
+# endif
+#endif
 
 #endif
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf538/include/mach/cdefBF538.h linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf538/include/mach/cdefBF538.h
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf538/include/mach/cdefBF538.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf538/include/mach/cdefBF538.h	2011-03-14 21:20:32.000000000 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright 2008-2009 Analog Devices Inc.
+ * Copyright 2008-2010 Analog Devices Inc.
  *
  * Licensed under the GPL-2 or later.
  */
@@ -7,14 +7,6 @@
 #ifndef _CDEF_BF538_H
 #define _CDEF_BF538_H
 
-#include <asm/blackfin.h>
-
-/*include all Core registers and bit definitions*/
-#include "defBF539.h"
-
-/*include core specific register pointer definitions*/
-#include <asm/cdef_LPBlackfin.h>
-
 #define bfin_writePTR(addr, val) bfin_write32(addr, val)
 
 #define bfin_read_PLL_CTL()            bfin_read16(PLL_CTL)
@@ -487,10 +479,10 @@
 #define bfin_write_EBIU_SDRRC(val)     bfin_write16(EBIU_SDRRC, val)
 #define bfin_read_EBIU_SDSTAT()        bfin_read16(EBIU_SDSTAT)
 #define bfin_write_EBIU_SDSTAT(val)    bfin_write16(EBIU_SDSTAT, val)
-#define bfin_read_DMA0_TC_PER()        bfin_read16(DMA0_TC_PER)
-#define bfin_write_DMA0_TC_PER(val)    bfin_write16(DMA0_TC_PER, val)
-#define bfin_read_DMA0_TC_CNT()        bfin_read16(DMA0_TC_CNT)
-#define bfin_write_DMA0_TC_CNT(val)    bfin_write16(DMA0_TC_CNT, val)
+#define bfin_read_DMAC0_TC_PER()       bfin_read16(DMAC0_TC_PER)
+#define bfin_write_DMAC0_TC_PER(val)   bfin_write16(DMAC0_TC_PER, val)
+#define bfin_read_DMAC0_TC_CNT()       bfin_read16(DMAC0_TC_CNT)
+#define bfin_write_DMAC0_TC_CNT(val)   bfin_write16(DMAC0_TC_CNT, val)
 #define bfin_read_DMA0_NEXT_DESC_PTR() bfin_readPTR(DMA0_NEXT_DESC_PTR)
 #define bfin_write_DMA0_NEXT_DESC_PTR(val) bfin_writePTR(DMA0_NEXT_DESC_PTR, val)
 #define bfin_read_DMA0_START_ADDR()    bfin_readPTR(DMA0_START_ADDR)
@@ -699,10 +691,10 @@
 #define bfin_write_DMA7_CURR_X_COUNT(val) bfin_write16(DMA7_CURR_X_COUNT, val)
 #define bfin_read_DMA7_CURR_Y_COUNT()  bfin_read16(DMA7_CURR_Y_COUNT)
 #define bfin_write_DMA7_CURR_Y_COUNT(val) bfin_write16(DMA7_CURR_Y_COUNT, val)
-#define bfin_read_DMA1_TC_PER()        bfin_read16(DMA1_TC_PER)
-#define bfin_write_DMA1_TC_PER(val)    bfin_write16(DMA1_TC_PER, val)
-#define bfin_read_DMA1_TC_CNT()        bfin_read16(DMA1_TC_CNT)
-#define bfin_write_DMA1_TC_CNT(val)    bfin_write16(DMA1_TC_CNT, val)
+#define bfin_read_DMAC1_TC_PER()       bfin_read16(DMAC1_TC_PER)
+#define bfin_write_DMAC1_TC_PER(val)   bfin_write16(DMAC1_TC_PER, val)
+#define bfin_read_DMAC1_TC_CNT()       bfin_read16(DMAC1_TC_CNT)
+#define bfin_write_DMAC1_TC_CNT(val)   bfin_write16(DMAC1_TC_CNT, val)
 #define bfin_read_DMA8_NEXT_DESC_PTR() bfin_readPTR(DMA8_NEXT_DESC_PTR)
 #define bfin_write_DMA8_NEXT_DESC_PTR(val) bfin_writePTR(DMA8_NEXT_DESC_PTR, val)
 #define bfin_read_DMA8_START_ADDR()    bfin_readPTR(DMA8_START_ADDR)
@@ -1015,273 +1007,214 @@
 #define bfin_write_DMA19_CURR_X_COUNT(val) bfin_write16(DMA19_CURR_X_COUNT, val)
 #define bfin_read_DMA19_CURR_Y_COUNT() bfin_read16(DMA19_CURR_Y_COUNT)
 #define bfin_write_DMA19_CURR_Y_COUNT(val) bfin_write16(DMA19_CURR_Y_COUNT, val)
-#define bfin_read_MDMA0_D0_NEXT_DESC_PTR() bfin_readPTR(MDMA0_D0_NEXT_DESC_PTR)
-#define bfin_write_MDMA0_D0_NEXT_DESC_PTR(val) bfin_writePTR(MDMA0_D0_NEXT_DESC_PTR, val)
-#define bfin_read_MDMA0_D0_START_ADDR() bfin_readPTR(MDMA0_D0_START_ADDR)
-#define bfin_write_MDMA0_D0_START_ADDR(val) bfin_writePTR(MDMA0_D0_START_ADDR, val)
-#define bfin_read_MDMA0_D0_CONFIG()    bfin_read16(MDMA0_D0_CONFIG)
-#define bfin_write_MDMA0_D0_CONFIG(val) bfin_write16(MDMA0_D0_CONFIG, val)
-#define bfin_read_MDMA0_D0_X_COUNT()   bfin_read16(MDMA0_D0_X_COUNT)
-#define bfin_write_MDMA0_D0_X_COUNT(val) bfin_write16(MDMA0_D0_X_COUNT, val)
-#define bfin_read_MDMA0_D0_X_MODIFY()  bfin_read16(MDMA0_D0_X_MODIFY)
-#define bfin_write_MDMA0_D0_X_MODIFY(val) bfin_write16(MDMA0_D0_X_MODIFY, val)
-#define bfin_read_MDMA0_D0_Y_COUNT()   bfin_read16(MDMA0_D0_Y_COUNT)
-#define bfin_write_MDMA0_D0_Y_COUNT(val) bfin_write16(MDMA0_D0_Y_COUNT, val)
-#define bfin_read_MDMA0_D0_Y_MODIFY()  bfin_read16(MDMA0_D0_Y_MODIFY)
-#define bfin_write_MDMA0_D0_Y_MODIFY(val) bfin_write16(MDMA0_D0_Y_MODIFY, val)
-#define bfin_read_MDMA0_D0_CURR_DESC_PTR() bfin_readPTR(MDMA0_D0_CURR_DESC_PTR)
-#define bfin_write_MDMA0_D0_CURR_DESC_PTR(val) bfin_writePTR(MDMA0_D0_CURR_DESC_PTR, val)
-#define bfin_read_MDMA0_D0_CURR_ADDR() bfin_readPTR(MDMA0_D0_CURR_ADDR)
-#define bfin_write_MDMA0_D0_CURR_ADDR(val) bfin_writePTR(MDMA0_D0_CURR_ADDR, val)
-#define bfin_read_MDMA0_D0_IRQ_STATUS() bfin_read16(MDMA0_D0_IRQ_STATUS)
-#define bfin_write_MDMA0_D0_IRQ_STATUS(val) bfin_write16(MDMA0_D0_IRQ_STATUS, val)
-#define bfin_read_MDMA0_D0_PERIPHERAL_MAP() bfin_read16(MDMA0_D0_PERIPHERAL_MAP)
-#define bfin_write_MDMA0_D0_PERIPHERAL_MAP(val) bfin_write16(MDMA0_D0_PERIPHERAL_MAP, val)
-#define bfin_read_MDMA0_D0_CURR_X_COUNT() bfin_read16(MDMA0_D0_CURR_X_COUNT)
-#define bfin_write_MDMA0_D0_CURR_X_COUNT(val) bfin_write16(MDMA0_D0_CURR_X_COUNT, val)
-#define bfin_read_MDMA0_D0_CURR_Y_COUNT() bfin_read16(MDMA0_D0_CURR_Y_COUNT)
-#define bfin_write_MDMA0_D0_CURR_Y_COUNT(val) bfin_write16(MDMA0_D0_CURR_Y_COUNT, val)
-#define bfin_read_MDMA0_S0_NEXT_DESC_PTR() bfin_readPTR(MDMA0_S0_NEXT_DESC_PTR)
-#define bfin_write_MDMA0_S0_NEXT_DESC_PTR(val) bfin_writePTR(MDMA0_S0_NEXT_DESC_PTR, val)
-#define bfin_read_MDMA0_S0_START_ADDR() bfin_readPTR(MDMA0_S0_START_ADDR)
-#define bfin_write_MDMA0_S0_START_ADDR(val) bfin_writePTR(MDMA0_S0_START_ADDR, val)
-#define bfin_read_MDMA0_S0_CONFIG()    bfin_read16(MDMA0_S0_CONFIG)
-#define bfin_write_MDMA0_S0_CONFIG(val) bfin_write16(MDMA0_S0_CONFIG, val)
-#define bfin_read_MDMA0_S0_X_COUNT()   bfin_read16(MDMA0_S0_X_COUNT)
-#define bfin_write_MDMA0_S0_X_COUNT(val) bfin_write16(MDMA0_S0_X_COUNT, val)
-#define bfin_read_MDMA0_S0_X_MODIFY()  bfin_read16(MDMA0_S0_X_MODIFY)
-#define bfin_write_MDMA0_S0_X_MODIFY(val) bfin_write16(MDMA0_S0_X_MODIFY, val)
-#define bfin_read_MDMA0_S0_Y_COUNT()   bfin_read16(MDMA0_S0_Y_COUNT)
-#define bfin_write_MDMA0_S0_Y_COUNT(val) bfin_write16(MDMA0_S0_Y_COUNT, val)
-#define bfin_read_MDMA0_S0_Y_MODIFY()  bfin_read16(MDMA0_S0_Y_MODIFY)
-#define bfin_write_MDMA0_S0_Y_MODIFY(val) bfin_write16(MDMA0_S0_Y_MODIFY, val)
-#define bfin_read_MDMA0_S0_CURR_DESC_PTR() bfin_readPTR(MDMA0_S0_CURR_DESC_PTR)
-#define bfin_write_MDMA0_S0_CURR_DESC_PTR(val) bfin_writePTR(MDMA0_S0_CURR_DESC_PTR, val)
-#define bfin_read_MDMA0_S0_CURR_ADDR() bfin_readPTR(MDMA0_S0_CURR_ADDR)
-#define bfin_write_MDMA0_S0_CURR_ADDR(val) bfin_writePTR(MDMA0_S0_CURR_ADDR, val)
-#define bfin_read_MDMA0_S0_IRQ_STATUS() bfin_read16(MDMA0_S0_IRQ_STATUS)
-#define bfin_write_MDMA0_S0_IRQ_STATUS(val) bfin_write16(MDMA0_S0_IRQ_STATUS, val)
-#define bfin_read_MDMA0_S0_PERIPHERAL_MAP() bfin_read16(MDMA0_S0_PERIPHERAL_MAP)
-#define bfin_write_MDMA0_S0_PERIPHERAL_MAP(val) bfin_write16(MDMA0_S0_PERIPHERAL_MAP, val)
-#define bfin_read_MDMA0_S0_CURR_X_COUNT() bfin_read16(MDMA0_S0_CURR_X_COUNT)
-#define bfin_write_MDMA0_S0_CURR_X_COUNT(val) bfin_write16(MDMA0_S0_CURR_X_COUNT, val)
-#define bfin_read_MDMA0_S0_CURR_Y_COUNT() bfin_read16(MDMA0_S0_CURR_Y_COUNT)
-#define bfin_write_MDMA0_S0_CURR_Y_COUNT(val) bfin_write16(MDMA0_S0_CURR_Y_COUNT, val)
-#define bfin_read_MDMA0_D1_NEXT_DESC_PTR() bfin_readPTR(MDMA0_D1_NEXT_DESC_PTR)
-#define bfin_write_MDMA0_D1_NEXT_DESC_PTR(val) bfin_writePTR(MDMA0_D1_NEXT_DESC_PTR, val)
-#define bfin_read_MDMA0_D1_START_ADDR() bfin_readPTR(MDMA0_D1_START_ADDR)
-#define bfin_write_MDMA0_D1_START_ADDR(val) bfin_writePTR(MDMA0_D1_START_ADDR, val)
-#define bfin_read_MDMA0_D1_CONFIG()    bfin_read16(MDMA0_D1_CONFIG)
-#define bfin_write_MDMA0_D1_CONFIG(val) bfin_write16(MDMA0_D1_CONFIG, val)
-#define bfin_read_MDMA0_D1_X_COUNT()   bfin_read16(MDMA0_D1_X_COUNT)
-#define bfin_write_MDMA0_D1_X_COUNT(val) bfin_write16(MDMA0_D1_X_COUNT, val)
-#define bfin_read_MDMA0_D1_X_MODIFY()  bfin_read16(MDMA0_D1_X_MODIFY)
-#define bfin_write_MDMA0_D1_X_MODIFY(val) bfin_write16(MDMA0_D1_X_MODIFY, val)
-#define bfin_read_MDMA0_D1_Y_COUNT()   bfin_read16(MDMA0_D1_Y_COUNT)
-#define bfin_write_MDMA0_D1_Y_COUNT(val) bfin_write16(MDMA0_D1_Y_COUNT, val)
-#define bfin_read_MDMA0_D1_Y_MODIFY()  bfin_read16(MDMA0_D1_Y_MODIFY)
-#define bfin_write_MDMA0_D1_Y_MODIFY(val) bfin_write16(MDMA0_D1_Y_MODIFY, val)
-#define bfin_read_MDMA0_D1_CURR_DESC_PTR() bfin_readPTR(MDMA0_D1_CURR_DESC_PTR)
-#define bfin_write_MDMA0_D1_CURR_DESC_PTR(val) bfin_writePTR(MDMA0_D1_CURR_DESC_PTR, val)
-#define bfin_read_MDMA0_D1_CURR_ADDR() bfin_readPTR(MDMA0_D1_CURR_ADDR)
-#define bfin_write_MDMA0_D1_CURR_ADDR(val) bfin_writePTR(MDMA0_D1_CURR_ADDR, val)
-#define bfin_read_MDMA0_D1_IRQ_STATUS() bfin_read16(MDMA0_D1_IRQ_STATUS)
-#define bfin_write_MDMA0_D1_IRQ_STATUS(val) bfin_write16(MDMA0_D1_IRQ_STATUS, val)
-#define bfin_read_MDMA0_D1_PERIPHERAL_MAP() bfin_read16(MDMA0_D1_PERIPHERAL_MAP)
-#define bfin_write_MDMA0_D1_PERIPHERAL_MAP(val) bfin_write16(MDMA0_D1_PERIPHERAL_MAP, val)
-#define bfin_read_MDMA0_D1_CURR_X_COUNT() bfin_read16(MDMA0_D1_CURR_X_COUNT)
-#define bfin_write_MDMA0_D1_CURR_X_COUNT(val) bfin_write16(MDMA0_D1_CURR_X_COUNT, val)
-#define bfin_read_MDMA0_D1_CURR_Y_COUNT() bfin_read16(MDMA0_D1_CURR_Y_COUNT)
-#define bfin_write_MDMA0_D1_CURR_Y_COUNT(val) bfin_write16(MDMA0_D1_CURR_Y_COUNT, val)
-#define bfin_read_MDMA0_S1_NEXT_DESC_PTR() bfin_readPTR(MDMA0_S1_NEXT_DESC_PTR)
-#define bfin_write_MDMA0_S1_NEXT_DESC_PTR(val) bfin_writePTR(MDMA0_S1_NEXT_DESC_PTR, val)
-#define bfin_read_MDMA0_S1_START_ADDR() bfin_readPTR(MDMA0_S1_START_ADDR)
-#define bfin_write_MDMA0_S1_START_ADDR(val) bfin_writePTR(MDMA0_S1_START_ADDR, val)
-#define bfin_read_MDMA0_S1_CONFIG()    bfin_read16(MDMA0_S1_CONFIG)
-#define bfin_write_MDMA0_S1_CONFIG(val) bfin_write16(MDMA0_S1_CONFIG, val)
-#define bfin_read_MDMA0_S1_X_COUNT()   bfin_read16(MDMA0_S1_X_COUNT)
-#define bfin_write_MDMA0_S1_X_COUNT(val) bfin_write16(MDMA0_S1_X_COUNT, val)
-#define bfin_read_MDMA0_S1_X_MODIFY()  bfin_read16(MDMA0_S1_X_MODIFY)
-#define bfin_write_MDMA0_S1_X_MODIFY(val) bfin_write16(MDMA0_S1_X_MODIFY, val)
-#define bfin_read_MDMA0_S1_Y_COUNT()   bfin_read16(MDMA0_S1_Y_COUNT)
-#define bfin_write_MDMA0_S1_Y_COUNT(val) bfin_write16(MDMA0_S1_Y_COUNT, val)
-#define bfin_read_MDMA0_S1_Y_MODIFY()  bfin_read16(MDMA0_S1_Y_MODIFY)
-#define bfin_write_MDMA0_S1_Y_MODIFY(val) bfin_write16(MDMA0_S1_Y_MODIFY, val)
-#define bfin_read_MDMA0_S1_CURR_DESC_PTR() bfin_readPTR(MDMA0_S1_CURR_DESC_PTR)
-#define bfin_write_MDMA0_S1_CURR_DESC_PTR(val) bfin_writePTR(MDMA0_S1_CURR_DESC_PTR, val)
-#define bfin_read_MDMA0_S1_CURR_ADDR() bfin_readPTR(MDMA0_S1_CURR_ADDR)
-#define bfin_write_MDMA0_S1_CURR_ADDR(val) bfin_writePTR(MDMA0_S1_CURR_ADDR, val)
-#define bfin_read_MDMA0_S1_IRQ_STATUS() bfin_read16(MDMA0_S1_IRQ_STATUS)
-#define bfin_write_MDMA0_S1_IRQ_STATUS(val) bfin_write16(MDMA0_S1_IRQ_STATUS, val)
-#define bfin_read_MDMA0_S1_PERIPHERAL_MAP() bfin_read16(MDMA0_S1_PERIPHERAL_MAP)
-#define bfin_write_MDMA0_S1_PERIPHERAL_MAP(val) bfin_write16(MDMA0_S1_PERIPHERAL_MAP, val)
-#define bfin_read_MDMA0_S1_CURR_X_COUNT() bfin_read16(MDMA0_S1_CURR_X_COUNT)
-#define bfin_write_MDMA0_S1_CURR_X_COUNT(val) bfin_write16(MDMA0_S1_CURR_X_COUNT, val)
-#define bfin_read_MDMA0_S1_CURR_Y_COUNT() bfin_read16(MDMA0_S1_CURR_Y_COUNT)
-#define bfin_write_MDMA0_S1_CURR_Y_COUNT(val) bfin_write16(MDMA0_S1_CURR_Y_COUNT, val)
-#define bfin_read_MDMA1_D0_NEXT_DESC_PTR() bfin_readPTR(MDMA1_D0_NEXT_DESC_PTR)
-#define bfin_write_MDMA1_D0_NEXT_DESC_PTR(val) bfin_writePTR(MDMA1_D0_NEXT_DESC_PTR, val)
-#define bfin_read_MDMA1_D0_START_ADDR() bfin_readPTR(MDMA1_D0_START_ADDR)
-#define bfin_write_MDMA1_D0_START_ADDR(val) bfin_writePTR(MDMA1_D0_START_ADDR, val)
-#define bfin_read_MDMA1_D0_CONFIG()    bfin_read16(MDMA1_D0_CONFIG)
-#define bfin_write_MDMA1_D0_CONFIG(val) bfin_write16(MDMA1_D0_CONFIG, val)
-#define bfin_read_MDMA1_D0_X_COUNT()   bfin_read16(MDMA1_D0_X_COUNT)
-#define bfin_write_MDMA1_D0_X_COUNT(val) bfin_write16(MDMA1_D0_X_COUNT, val)
-#define bfin_read_MDMA1_D0_X_MODIFY()  bfin_read16(MDMA1_D0_X_MODIFY)
-#define bfin_write_MDMA1_D0_X_MODIFY(val) bfin_write16(MDMA1_D0_X_MODIFY, val)
-#define bfin_read_MDMA1_D0_Y_COUNT()   bfin_read16(MDMA1_D0_Y_COUNT)
-#define bfin_write_MDMA1_D0_Y_COUNT(val) bfin_write16(MDMA1_D0_Y_COUNT, val)
-#define bfin_read_MDMA1_D0_Y_MODIFY()  bfin_read16(MDMA1_D0_Y_MODIFY)
-#define bfin_write_MDMA1_D0_Y_MODIFY(val) bfin_write16(MDMA1_D0_Y_MODIFY, val)
-#define bfin_read_MDMA1_D0_CURR_DESC_PTR() bfin_readPTR(MDMA1_D0_CURR_DESC_PTR)
-#define bfin_write_MDMA1_D0_CURR_DESC_PTR(val) bfin_writePTR(MDMA1_D0_CURR_DESC_PTR, val)
-#define bfin_read_MDMA1_D0_CURR_ADDR() bfin_readPTR(MDMA1_D0_CURR_ADDR)
-#define bfin_write_MDMA1_D0_CURR_ADDR(val) bfin_writePTR(MDMA1_D0_CURR_ADDR, val)
-#define bfin_read_MDMA1_D0_IRQ_STATUS() bfin_read16(MDMA1_D0_IRQ_STATUS)
-#define bfin_write_MDMA1_D0_IRQ_STATUS(val) bfin_write16(MDMA1_D0_IRQ_STATUS, val)
-#define bfin_read_MDMA1_D0_PERIPHERAL_MAP() bfin_read16(MDMA1_D0_PERIPHERAL_MAP)
-#define bfin_write_MDMA1_D0_PERIPHERAL_MAP(val) bfin_write16(MDMA1_D0_PERIPHERAL_MAP, val)
-#define bfin_read_MDMA1_D0_CURR_X_COUNT() bfin_read16(MDMA1_D0_CURR_X_COUNT)
-#define bfin_write_MDMA1_D0_CURR_X_COUNT(val) bfin_write16(MDMA1_D0_CURR_X_COUNT, val)
-#define bfin_read_MDMA1_D0_CURR_Y_COUNT() bfin_read16(MDMA1_D0_CURR_Y_COUNT)
-#define bfin_write_MDMA1_D0_CURR_Y_COUNT(val) bfin_write16(MDMA1_D0_CURR_Y_COUNT, val)
-#define bfin_read_MDMA1_S0_NEXT_DESC_PTR() bfin_readPTR(MDMA1_S0_NEXT_DESC_PTR)
-#define bfin_write_MDMA1_S0_NEXT_DESC_PTR(val) bfin_writePTR(MDMA1_S0_NEXT_DESC_PTR, val)
-#define bfin_read_MDMA1_S0_START_ADDR() bfin_readPTR(MDMA1_S0_START_ADDR)
-#define bfin_write_MDMA1_S0_START_ADDR(val) bfin_writePTR(MDMA1_S0_START_ADDR, val)
-#define bfin_read_MDMA1_S0_CONFIG()    bfin_read16(MDMA1_S0_CONFIG)
-#define bfin_write_MDMA1_S0_CONFIG(val) bfin_write16(MDMA1_S0_CONFIG, val)
-#define bfin_read_MDMA1_S0_X_COUNT()   bfin_read16(MDMA1_S0_X_COUNT)
-#define bfin_write_MDMA1_S0_X_COUNT(val) bfin_write16(MDMA1_S0_X_COUNT, val)
-#define bfin_read_MDMA1_S0_X_MODIFY()  bfin_read16(MDMA1_S0_X_MODIFY)
-#define bfin_write_MDMA1_S0_X_MODIFY(val) bfin_write16(MDMA1_S0_X_MODIFY, val)
-#define bfin_read_MDMA1_S0_Y_COUNT()   bfin_read16(MDMA1_S0_Y_COUNT)
-#define bfin_write_MDMA1_S0_Y_COUNT(val) bfin_write16(MDMA1_S0_Y_COUNT, val)
-#define bfin_read_MDMA1_S0_Y_MODIFY()  bfin_read16(MDMA1_S0_Y_MODIFY)
-#define bfin_write_MDMA1_S0_Y_MODIFY(val) bfin_write16(MDMA1_S0_Y_MODIFY, val)
-#define bfin_read_MDMA1_S0_CURR_DESC_PTR() bfin_readPTR(MDMA1_S0_CURR_DESC_PTR)
-#define bfin_write_MDMA1_S0_CURR_DESC_PTR(val) bfin_writePTR(MDMA1_S0_CURR_DESC_PTR, val)
-#define bfin_read_MDMA1_S0_CURR_ADDR() bfin_readPTR(MDMA1_S0_CURR_ADDR)
-#define bfin_write_MDMA1_S0_CURR_ADDR(val) bfin_writePTR(MDMA1_S0_CURR_ADDR, val)
-#define bfin_read_MDMA1_S0_IRQ_STATUS() bfin_read16(MDMA1_S0_IRQ_STATUS)
-#define bfin_write_MDMA1_S0_IRQ_STATUS(val) bfin_write16(MDMA1_S0_IRQ_STATUS, val)
-#define bfin_read_MDMA1_S0_PERIPHERAL_MAP() bfin_read16(MDMA1_S0_PERIPHERAL_MAP)
-#define bfin_write_MDMA1_S0_PERIPHERAL_MAP(val) bfin_write16(MDMA1_S0_PERIPHERAL_MAP, val)
-#define bfin_read_MDMA1_S0_CURR_X_COUNT() bfin_read16(MDMA1_S0_CURR_X_COUNT)
-#define bfin_write_MDMA1_S0_CURR_X_COUNT(val) bfin_write16(MDMA1_S0_CURR_X_COUNT, val)
-#define bfin_read_MDMA1_S0_CURR_Y_COUNT() bfin_read16(MDMA1_S0_CURR_Y_COUNT)
-#define bfin_write_MDMA1_S0_CURR_Y_COUNT(val) bfin_write16(MDMA1_S0_CURR_Y_COUNT, val)
-#define bfin_read_MDMA1_D1_NEXT_DESC_PTR() bfin_readPTR(MDMA1_D1_NEXT_DESC_PTR)
-#define bfin_write_MDMA1_D1_NEXT_DESC_PTR(val) bfin_writePTR(MDMA1_D1_NEXT_DESC_PTR, val)
-#define bfin_read_MDMA1_D1_START_ADDR() bfin_readPTR(MDMA1_D1_START_ADDR)
-#define bfin_write_MDMA1_D1_START_ADDR(val) bfin_writePTR(MDMA1_D1_START_ADDR, val)
-#define bfin_read_MDMA1_D1_CONFIG()    bfin_read16(MDMA1_D1_CONFIG)
-#define bfin_write_MDMA1_D1_CONFIG(val) bfin_write16(MDMA1_D1_CONFIG, val)
-#define bfin_read_MDMA1_D1_X_COUNT()   bfin_read16(MDMA1_D1_X_COUNT)
-#define bfin_write_MDMA1_D1_X_COUNT(val) bfin_write16(MDMA1_D1_X_COUNT, val)
-#define bfin_read_MDMA1_D1_X_MODIFY()  bfin_read16(MDMA1_D1_X_MODIFY)
-#define bfin_write_MDMA1_D1_X_MODIFY(val) bfin_write16(MDMA1_D1_X_MODIFY, val)
-#define bfin_read_MDMA1_D1_Y_COUNT()   bfin_read16(MDMA1_D1_Y_COUNT)
-#define bfin_write_MDMA1_D1_Y_COUNT(val) bfin_write16(MDMA1_D1_Y_COUNT, val)
-#define bfin_read_MDMA1_D1_Y_MODIFY()  bfin_read16(MDMA1_D1_Y_MODIFY)
-#define bfin_write_MDMA1_D1_Y_MODIFY(val) bfin_write16(MDMA1_D1_Y_MODIFY, val)
-#define bfin_read_MDMA1_D1_CURR_DESC_PTR() bfin_readPTR(MDMA1_D1_CURR_DESC_PTR)
-#define bfin_write_MDMA1_D1_CURR_DESC_PTR(val) bfin_writePTR(MDMA1_D1_CURR_DESC_PTR, val)
-#define bfin_read_MDMA1_D1_CURR_ADDR() bfin_readPTR(MDMA1_D1_CURR_ADDR)
-#define bfin_write_MDMA1_D1_CURR_ADDR(val) bfin_writePTR(MDMA1_D1_CURR_ADDR, val)
-#define bfin_read_MDMA1_D1_IRQ_STATUS() bfin_read16(MDMA1_D1_IRQ_STATUS)
-#define bfin_write_MDMA1_D1_IRQ_STATUS(val) bfin_write16(MDMA1_D1_IRQ_STATUS, val)
-#define bfin_read_MDMA1_D1_PERIPHERAL_MAP() bfin_read16(MDMA1_D1_PERIPHERAL_MAP)
-#define bfin_write_MDMA1_D1_PERIPHERAL_MAP(val) bfin_write16(MDMA1_D1_PERIPHERAL_MAP, val)
-#define bfin_read_MDMA1_D1_CURR_X_COUNT() bfin_read16(MDMA1_D1_CURR_X_COUNT)
-#define bfin_write_MDMA1_D1_CURR_X_COUNT(val) bfin_write16(MDMA1_D1_CURR_X_COUNT, val)
-#define bfin_read_MDMA1_D1_CURR_Y_COUNT() bfin_read16(MDMA1_D1_CURR_Y_COUNT)
-#define bfin_write_MDMA1_D1_CURR_Y_COUNT(val) bfin_write16(MDMA1_D1_CURR_Y_COUNT, val)
-#define bfin_read_MDMA1_S1_NEXT_DESC_PTR() bfin_readPTR(MDMA1_S1_NEXT_DESC_PTR)
-#define bfin_write_MDMA1_S1_NEXT_DESC_PTR(val) bfin_writePTR(MDMA1_S1_NEXT_DESC_PTR, val)
-#define bfin_read_MDMA1_S1_START_ADDR() bfin_readPTR(MDMA1_S1_START_ADDR)
-#define bfin_write_MDMA1_S1_START_ADDR(val) bfin_writePTR(MDMA1_S1_START_ADDR, val)
-#define bfin_read_MDMA1_S1_CONFIG()    bfin_read16(MDMA1_S1_CONFIG)
-#define bfin_write_MDMA1_S1_CONFIG(val) bfin_write16(MDMA1_S1_CONFIG, val)
-#define bfin_read_MDMA1_S1_X_COUNT()   bfin_read16(MDMA1_S1_X_COUNT)
-#define bfin_write_MDMA1_S1_X_COUNT(val) bfin_write16(MDMA1_S1_X_COUNT, val)
-#define bfin_read_MDMA1_S1_X_MODIFY()  bfin_read16(MDMA1_S1_X_MODIFY)
-#define bfin_write_MDMA1_S1_X_MODIFY(val) bfin_write16(MDMA1_S1_X_MODIFY, val)
-#define bfin_read_MDMA1_S1_Y_COUNT()   bfin_read16(MDMA1_S1_Y_COUNT)
-#define bfin_write_MDMA1_S1_Y_COUNT(val) bfin_write16(MDMA1_S1_Y_COUNT, val)
-#define bfin_read_MDMA1_S1_Y_MODIFY()  bfin_read16(MDMA1_S1_Y_MODIFY)
-#define bfin_write_MDMA1_S1_Y_MODIFY(val) bfin_write16(MDMA1_S1_Y_MODIFY, val)
-#define bfin_read_MDMA1_S1_CURR_DESC_PTR() bfin_readPTR(MDMA1_S1_CURR_DESC_PTR)
-#define bfin_write_MDMA1_S1_CURR_DESC_PTR(val) bfin_writePTR(MDMA1_S1_CURR_DESC_PTR, val)
-#define bfin_read_MDMA1_S1_CURR_ADDR() bfin_readPTR(MDMA1_S1_CURR_ADDR)
-#define bfin_write_MDMA1_S1_CURR_ADDR(val) bfin_writePTR(MDMA1_S1_CURR_ADDR, val)
-#define bfin_read_MDMA1_S1_IRQ_STATUS() bfin_read16(MDMA1_S1_IRQ_STATUS)
-#define bfin_write_MDMA1_S1_IRQ_STATUS(val) bfin_write16(MDMA1_S1_IRQ_STATUS, val)
-#define bfin_read_MDMA1_S1_PERIPHERAL_MAP() bfin_read16(MDMA1_S1_PERIPHERAL_MAP)
-#define bfin_write_MDMA1_S1_PERIPHERAL_MAP(val) bfin_write16(MDMA1_S1_PERIPHERAL_MAP, val)
-#define bfin_read_MDMA1_S1_CURR_X_COUNT() bfin_read16(MDMA1_S1_CURR_X_COUNT)
-#define bfin_write_MDMA1_S1_CURR_X_COUNT(val) bfin_write16(MDMA1_S1_CURR_X_COUNT, val)
-#define bfin_read_MDMA1_S1_CURR_Y_COUNT() bfin_read16(MDMA1_S1_CURR_Y_COUNT)
-#define bfin_write_MDMA1_S1_CURR_Y_COUNT(val) bfin_write16(MDMA1_S1_CURR_Y_COUNT, val)
-
-#define bfin_read_MDMA_S0_CONFIG()  bfin_read_MDMA0_S0_CONFIG()
-#define bfin_write_MDMA_S0_CONFIG(val) bfin_write_MDMA0_S0_CONFIG(val)
-#define bfin_read_MDMA_S0_IRQ_STATUS()  bfin_read_MDMA0_S0_IRQ_STATUS()
-#define bfin_write_MDMA_S0_IRQ_STATUS(val) bfin_write_MDMA0_S0_IRQ_STATUS(val)
-#define bfin_read_MDMA_S0_X_MODIFY()  bfin_read_MDMA0_S0_X_MODIFY()
-#define bfin_write_MDMA_S0_X_MODIFY(val) bfin_write_MDMA0_S0_X_MODIFY(val)
-#define bfin_read_MDMA_S0_Y_MODIFY()  bfin_read_MDMA0_S0_Y_MODIFY()
-#define bfin_write_MDMA_S0_Y_MODIFY(val) bfin_write_MDMA0_S0_Y_MODIFY(val)
-#define bfin_read_MDMA_S0_X_COUNT()  bfin_read_MDMA0_S0_X_COUNT()
-#define bfin_write_MDMA_S0_X_COUNT(val) bfin_write_MDMA0_S0_X_COUNT(val)
-#define bfin_read_MDMA_S0_Y_COUNT()  bfin_read_MDMA0_S0_Y_COUNT()
-#define bfin_write_MDMA_S0_Y_COUNT(val) bfin_write_MDMA0_S0_Y_COUNT(val)
-#define bfin_read_MDMA_S0_START_ADDR()  bfin_read_MDMA0_S0_START_ADDR()
-#define bfin_write_MDMA_S0_START_ADDR(val) bfin_write_MDMA0_S0_START_ADDR(val)
-#define bfin_read_MDMA_D0_CONFIG()  bfin_read_MDMA0_D0_CONFIG()
-#define bfin_write_MDMA_D0_CONFIG(val) bfin_write_MDMA0_D0_CONFIG(val)
-#define bfin_read_MDMA_D0_IRQ_STATUS()  bfin_read_MDMA0_D0_IRQ_STATUS()
-#define bfin_write_MDMA_D0_IRQ_STATUS(val) bfin_write_MDMA0_D0_IRQ_STATUS(val)
-#define bfin_read_MDMA_D0_X_MODIFY()  bfin_read_MDMA0_D0_X_MODIFY()
-#define bfin_write_MDMA_D0_X_MODIFY(val) bfin_write_MDMA0_D0_X_MODIFY(val)
-#define bfin_read_MDMA_D0_Y_MODIFY()  bfin_read_MDMA0_D0_Y_MODIFY()
-#define bfin_write_MDMA_D0_Y_MODIFY(val) bfin_write_MDMA0_D0_Y_MODIFY(val)
-#define bfin_read_MDMA_D0_X_COUNT()  bfin_read_MDMA0_D0_X_COUNT()
-#define bfin_write_MDMA_D0_X_COUNT(val) bfin_write_MDMA0_D0_X_COUNT(val)
-#define bfin_read_MDMA_D0_Y_COUNT()  bfin_read_MDMA0_D0_Y_COUNT()
-#define bfin_write_MDMA_D0_Y_COUNT(val) bfin_write_MDMA0_D0_Y_COUNT(val)
-#define bfin_read_MDMA_D0_START_ADDR()  bfin_read_MDMA0_D0_START_ADDR()
-#define bfin_write_MDMA_D0_START_ADDR(val) bfin_write_MDMA0_D0_START_ADDR(val)
-
-#define bfin_read_MDMA_S1_CONFIG()  bfin_read_MDMA0_S1_CONFIG()
-#define bfin_write_MDMA_S1_CONFIG(val) bfin_write_MDMA0_S1_CONFIG(val)
-#define bfin_read_MDMA_S1_IRQ_STATUS()  bfin_read_MDMA0_S1_IRQ_STATUS()
-#define bfin_write_MDMA_S1_IRQ_STATUS(val) bfin_write_MDMA0_S1_IRQ_STATUS(val)
-#define bfin_read_MDMA_S1_X_MODIFY()  bfin_read_MDMA0_S1_X_MODIFY()
-#define bfin_write_MDMA_S1_X_MODIFY(val) bfin_write_MDMA0_S1_X_MODIFY(val)
-#define bfin_read_MDMA_S1_Y_MODIFY()  bfin_read_MDMA0_S1_Y_MODIFY()
-#define bfin_write_MDMA_S1_Y_MODIFY(val) bfin_write_MDMA0_S1_Y_MODIFY(val)
-#define bfin_read_MDMA_S1_X_COUNT()  bfin_read_MDMA0_S1_X_COUNT()
-#define bfin_write_MDMA_S1_X_COUNT(val) bfin_write_MDMA0_S1_X_COUNT(val)
-#define bfin_read_MDMA_S1_Y_COUNT()  bfin_read_MDMA0_S1_Y_COUNT()
-#define bfin_write_MDMA_S1_Y_COUNT(val) bfin_write_MDMA0_S1_Y_COUNT(val)
-#define bfin_read_MDMA_S1_START_ADDR()  bfin_read_MDMA0_S1_START_ADDR()
-#define bfin_write_MDMA_S1_START_ADDR(val) bfin_write_MDMA0_S1_START_ADDR(val)
-#define bfin_read_MDMA_D1_CONFIG()  bfin_read_MDMA0_D1_CONFIG()
-#define bfin_write_MDMA_D1_CONFIG(val) bfin_write_MDMA0_D1_CONFIG(val)
-#define bfin_read_MDMA_D1_IRQ_STATUS()  bfin_read_MDMA0_D1_IRQ_STATUS()
-#define bfin_write_MDMA_D1_IRQ_STATUS(val) bfin_write_MDMA0_D1_IRQ_STATUS(val)
-#define bfin_read_MDMA_D1_X_MODIFY()  bfin_read_MDMA0_D1_X_MODIFY()
-#define bfin_write_MDMA_D1_X_MODIFY(val) bfin_write_MDMA0_D1_X_MODIFY(val)
-#define bfin_read_MDMA_D1_Y_MODIFY()  bfin_read_MDMA0_D1_Y_MODIFY()
-#define bfin_write_MDMA_D1_Y_MODIFY(val) bfin_write_MDMA0_D1_Y_MODIFY(val)
-#define bfin_read_MDMA_D1_X_COUNT()  bfin_read_MDMA0_D1_X_COUNT()
-#define bfin_write_MDMA_D1_X_COUNT(val) bfin_write_MDMA0_D1_X_COUNT(val)
-#define bfin_read_MDMA_D1_Y_COUNT()  bfin_read_MDMA0_D1_Y_COUNT()
-#define bfin_write_MDMA_D1_Y_COUNT(val) bfin_write_MDMA0_D1_Y_COUNT(val)
-#define bfin_read_MDMA_D1_START_ADDR()  bfin_read_MDMA0_D1_START_ADDR()
-#define bfin_write_MDMA_D1_START_ADDR(val) bfin_write_MDMA0_D1_START_ADDR(val)
-
+#define bfin_read_MDMA_D0_NEXT_DESC_PTR() bfin_readPTR(MDMA_D0_NEXT_DESC_PTR)
+#define bfin_write_MDMA_D0_NEXT_DESC_PTR(val) bfin_writePTR(MDMA_D0_NEXT_DESC_PTR, val)
+#define bfin_read_MDMA_D0_START_ADDR() bfin_readPTR(MDMA_D0_START_ADDR)
+#define bfin_write_MDMA_D0_START_ADDR(val) bfin_writePTR(MDMA_D0_START_ADDR, val)
+#define bfin_read_MDMA_D0_CONFIG()    bfin_read16(MDMA_D0_CONFIG)
+#define bfin_write_MDMA_D0_CONFIG(val) bfin_write16(MDMA_D0_CONFIG, val)
+#define bfin_read_MDMA_D0_X_COUNT()   bfin_read16(MDMA_D0_X_COUNT)
+#define bfin_write_MDMA_D0_X_COUNT(val) bfin_write16(MDMA_D0_X_COUNT, val)
+#define bfin_read_MDMA_D0_X_MODIFY()  bfin_read16(MDMA_D0_X_MODIFY)
+#define bfin_write_MDMA_D0_X_MODIFY(val) bfin_write16(MDMA_D0_X_MODIFY, val)
+#define bfin_read_MDMA_D0_Y_COUNT()   bfin_read16(MDMA_D0_Y_COUNT)
+#define bfin_write_MDMA_D0_Y_COUNT(val) bfin_write16(MDMA_D0_Y_COUNT, val)
+#define bfin_read_MDMA_D0_Y_MODIFY()  bfin_read16(MDMA_D0_Y_MODIFY)
+#define bfin_write_MDMA_D0_Y_MODIFY(val) bfin_write16(MDMA_D0_Y_MODIFY, val)
+#define bfin_read_MDMA_D0_CURR_DESC_PTR() bfin_readPTR(MDMA_D0_CURR_DESC_PTR)
+#define bfin_write_MDMA_D0_CURR_DESC_PTR(val) bfin_writePTR(MDMA_D0_CURR_DESC_PTR, val)
+#define bfin_read_MDMA_D0_CURR_ADDR() bfin_readPTR(MDMA_D0_CURR_ADDR)
+#define bfin_write_MDMA_D0_CURR_ADDR(val) bfin_writePTR(MDMA_D0_CURR_ADDR, val)
+#define bfin_read_MDMA_D0_IRQ_STATUS() bfin_read16(MDMA_D0_IRQ_STATUS)
+#define bfin_write_MDMA_D0_IRQ_STATUS(val) bfin_write16(MDMA_D0_IRQ_STATUS, val)
+#define bfin_read_MDMA_D0_PERIPHERAL_MAP() bfin_read16(MDMA_D0_PERIPHERAL_MAP)
+#define bfin_write_MDMA_D0_PERIPHERAL_MAP(val) bfin_write16(MDMA_D0_PERIPHERAL_MAP, val)
+#define bfin_read_MDMA_D0_CURR_X_COUNT() bfin_read16(MDMA_D0_CURR_X_COUNT)
+#define bfin_write_MDMA_D0_CURR_X_COUNT(val) bfin_write16(MDMA_D0_CURR_X_COUNT, val)
+#define bfin_read_MDMA_D0_CURR_Y_COUNT() bfin_read16(MDMA_D0_CURR_Y_COUNT)
+#define bfin_write_MDMA_D0_CURR_Y_COUNT(val) bfin_write16(MDMA_D0_CURR_Y_COUNT, val)
+#define bfin_read_MDMA_S0_NEXT_DESC_PTR() bfin_readPTR(MDMA_S0_NEXT_DESC_PTR)
+#define bfin_write_MDMA_S0_NEXT_DESC_PTR(val) bfin_writePTR(MDMA_S0_NEXT_DESC_PTR, val)
+#define bfin_read_MDMA_S0_START_ADDR() bfin_readPTR(MDMA_S0_START_ADDR)
+#define bfin_write_MDMA_S0_START_ADDR(val) bfin_writePTR(MDMA_S0_START_ADDR, val)
+#define bfin_read_MDMA_S0_CONFIG()    bfin_read16(MDMA_S0_CONFIG)
+#define bfin_write_MDMA_S0_CONFIG(val) bfin_write16(MDMA_S0_CONFIG, val)
+#define bfin_read_MDMA_S0_X_COUNT()   bfin_read16(MDMA_S0_X_COUNT)
+#define bfin_write_MDMA_S0_X_COUNT(val) bfin_write16(MDMA_S0_X_COUNT, val)
+#define bfin_read_MDMA_S0_X_MODIFY()  bfin_read16(MDMA_S0_X_MODIFY)
+#define bfin_write_MDMA_S0_X_MODIFY(val) bfin_write16(MDMA_S0_X_MODIFY, val)
+#define bfin_read_MDMA_S0_Y_COUNT()   bfin_read16(MDMA_S0_Y_COUNT)
+#define bfin_write_MDMA_S0_Y_COUNT(val) bfin_write16(MDMA_S0_Y_COUNT, val)
+#define bfin_read_MDMA_S0_Y_MODIFY()  bfin_read16(MDMA_S0_Y_MODIFY)
+#define bfin_write_MDMA_S0_Y_MODIFY(val) bfin_write16(MDMA_S0_Y_MODIFY, val)
+#define bfin_read_MDMA_S0_CURR_DESC_PTR() bfin_readPTR(MDMA_S0_CURR_DESC_PTR)
+#define bfin_write_MDMA_S0_CURR_DESC_PTR(val) bfin_writePTR(MDMA_S0_CURR_DESC_PTR, val)
+#define bfin_read_MDMA_S0_CURR_ADDR() bfin_readPTR(MDMA_S0_CURR_ADDR)
+#define bfin_write_MDMA_S0_CURR_ADDR(val) bfin_writePTR(MDMA_S0_CURR_ADDR, val)
+#define bfin_read_MDMA_S0_IRQ_STATUS() bfin_read16(MDMA_S0_IRQ_STATUS)
+#define bfin_write_MDMA_S0_IRQ_STATUS(val) bfin_write16(MDMA_S0_IRQ_STATUS, val)
+#define bfin_read_MDMA_S0_PERIPHERAL_MAP() bfin_read16(MDMA_S0_PERIPHERAL_MAP)
+#define bfin_write_MDMA_S0_PERIPHERAL_MAP(val) bfin_write16(MDMA_S0_PERIPHERAL_MAP, val)
+#define bfin_read_MDMA_S0_CURR_X_COUNT() bfin_read16(MDMA_S0_CURR_X_COUNT)
+#define bfin_write_MDMA_S0_CURR_X_COUNT(val) bfin_write16(MDMA_S0_CURR_X_COUNT, val)
+#define bfin_read_MDMA_S0_CURR_Y_COUNT() bfin_read16(MDMA_S0_CURR_Y_COUNT)
+#define bfin_write_MDMA_S0_CURR_Y_COUNT(val) bfin_write16(MDMA_S0_CURR_Y_COUNT, val)
+#define bfin_read_MDMA_D1_NEXT_DESC_PTR() bfin_readPTR(MDMA_D1_NEXT_DESC_PTR)
+#define bfin_write_MDMA_D1_NEXT_DESC_PTR(val) bfin_writePTR(MDMA_D1_NEXT_DESC_PTR, val)
+#define bfin_read_MDMA_D1_START_ADDR() bfin_readPTR(MDMA_D1_START_ADDR)
+#define bfin_write_MDMA_D1_START_ADDR(val) bfin_writePTR(MDMA_D1_START_ADDR, val)
+#define bfin_read_MDMA_D1_CONFIG()    bfin_read16(MDMA_D1_CONFIG)
+#define bfin_write_MDMA_D1_CONFIG(val) bfin_write16(MDMA_D1_CONFIG, val)
+#define bfin_read_MDMA_D1_X_COUNT()   bfin_read16(MDMA_D1_X_COUNT)
+#define bfin_write_MDMA_D1_X_COUNT(val) bfin_write16(MDMA_D1_X_COUNT, val)
+#define bfin_read_MDMA_D1_X_MODIFY()  bfin_read16(MDMA_D1_X_MODIFY)
+#define bfin_write_MDMA_D1_X_MODIFY(val) bfin_write16(MDMA_D1_X_MODIFY, val)
+#define bfin_read_MDMA_D1_Y_COUNT()   bfin_read16(MDMA_D1_Y_COUNT)
+#define bfin_write_MDMA_D1_Y_COUNT(val) bfin_write16(MDMA_D1_Y_COUNT, val)
+#define bfin_read_MDMA_D1_Y_MODIFY()  bfin_read16(MDMA_D1_Y_MODIFY)
+#define bfin_write_MDMA_D1_Y_MODIFY(val) bfin_write16(MDMA_D1_Y_MODIFY, val)
+#define bfin_read_MDMA_D1_CURR_DESC_PTR() bfin_readPTR(MDMA_D1_CURR_DESC_PTR)
+#define bfin_write_MDMA_D1_CURR_DESC_PTR(val) bfin_writePTR(MDMA_D1_CURR_DESC_PTR, val)
+#define bfin_read_MDMA_D1_CURR_ADDR() bfin_readPTR(MDMA_D1_CURR_ADDR)
+#define bfin_write_MDMA_D1_CURR_ADDR(val) bfin_writePTR(MDMA_D1_CURR_ADDR, val)
+#define bfin_read_MDMA_D1_IRQ_STATUS() bfin_read16(MDMA_D1_IRQ_STATUS)
+#define bfin_write_MDMA_D1_IRQ_STATUS(val) bfin_write16(MDMA_D1_IRQ_STATUS, val)
+#define bfin_read_MDMA_D1_PERIPHERAL_MAP() bfin_read16(MDMA_D1_PERIPHERAL_MAP)
+#define bfin_write_MDMA_D1_PERIPHERAL_MAP(val) bfin_write16(MDMA_D1_PERIPHERAL_MAP, val)
+#define bfin_read_MDMA_D1_CURR_X_COUNT() bfin_read16(MDMA_D1_CURR_X_COUNT)
+#define bfin_write_MDMA_D1_CURR_X_COUNT(val) bfin_write16(MDMA_D1_CURR_X_COUNT, val)
+#define bfin_read_MDMA_D1_CURR_Y_COUNT() bfin_read16(MDMA_D1_CURR_Y_COUNT)
+#define bfin_write_MDMA_D1_CURR_Y_COUNT(val) bfin_write16(MDMA_D1_CURR_Y_COUNT, val)
+#define bfin_read_MDMA_S1_NEXT_DESC_PTR() bfin_readPTR(MDMA_S1_NEXT_DESC_PTR)
+#define bfin_write_MDMA_S1_NEXT_DESC_PTR(val) bfin_writePTR(MDMA_S1_NEXT_DESC_PTR, val)
+#define bfin_read_MDMA_S1_START_ADDR() bfin_readPTR(MDMA_S1_START_ADDR)
+#define bfin_write_MDMA_S1_START_ADDR(val) bfin_writePTR(MDMA_S1_START_ADDR, val)
+#define bfin_read_MDMA_S1_CONFIG()    bfin_read16(MDMA_S1_CONFIG)
+#define bfin_write_MDMA_S1_CONFIG(val) bfin_write16(MDMA_S1_CONFIG, val)
+#define bfin_read_MDMA_S1_X_COUNT()   bfin_read16(MDMA_S1_X_COUNT)
+#define bfin_write_MDMA_S1_X_COUNT(val) bfin_write16(MDMA_S1_X_COUNT, val)
+#define bfin_read_MDMA_S1_X_MODIFY()  bfin_read16(MDMA_S1_X_MODIFY)
+#define bfin_write_MDMA_S1_X_MODIFY(val) bfin_write16(MDMA_S1_X_MODIFY, val)
+#define bfin_read_MDMA_S1_Y_COUNT()   bfin_read16(MDMA_S1_Y_COUNT)
+#define bfin_write_MDMA_S1_Y_COUNT(val) bfin_write16(MDMA_S1_Y_COUNT, val)
+#define bfin_read_MDMA_S1_Y_MODIFY()  bfin_read16(MDMA_S1_Y_MODIFY)
+#define bfin_write_MDMA_S1_Y_MODIFY(val) bfin_write16(MDMA_S1_Y_MODIFY, val)
+#define bfin_read_MDMA_S1_CURR_DESC_PTR() bfin_readPTR(MDMA_S1_CURR_DESC_PTR)
+#define bfin_write_MDMA_S1_CURR_DESC_PTR(val) bfin_writePTR(MDMA_S1_CURR_DESC_PTR, val)
+#define bfin_read_MDMA_S1_CURR_ADDR() bfin_readPTR(MDMA_S1_CURR_ADDR)
+#define bfin_write_MDMA_S1_CURR_ADDR(val) bfin_writePTR(MDMA_S1_CURR_ADDR, val)
+#define bfin_read_MDMA_S1_IRQ_STATUS() bfin_read16(MDMA_S1_IRQ_STATUS)
+#define bfin_write_MDMA_S1_IRQ_STATUS(val) bfin_write16(MDMA_S1_IRQ_STATUS, val)
+#define bfin_read_MDMA_S1_PERIPHERAL_MAP() bfin_read16(MDMA_S1_PERIPHERAL_MAP)
+#define bfin_write_MDMA_S1_PERIPHERAL_MAP(val) bfin_write16(MDMA_S1_PERIPHERAL_MAP, val)
+#define bfin_read_MDMA_S1_CURR_X_COUNT() bfin_read16(MDMA_S1_CURR_X_COUNT)
+#define bfin_write_MDMA_S1_CURR_X_COUNT(val) bfin_write16(MDMA_S1_CURR_X_COUNT, val)
+#define bfin_read_MDMA_S1_CURR_Y_COUNT() bfin_read16(MDMA_S1_CURR_Y_COUNT)
+#define bfin_write_MDMA_S1_CURR_Y_COUNT(val) bfin_write16(MDMA_S1_CURR_Y_COUNT, val)
+#define bfin_read_MDMA_D2_NEXT_DESC_PTR() bfin_readPTR(MDMA_D2_NEXT_DESC_PTR)
+#define bfin_write_MDMA_D2_NEXT_DESC_PTR(val) bfin_writePTR(MDMA_D2_NEXT_DESC_PTR, val)
+#define bfin_read_MDMA_D2_START_ADDR() bfin_readPTR(MDMA_D2_START_ADDR)
+#define bfin_write_MDMA_D2_START_ADDR(val) bfin_writePTR(MDMA_D2_START_ADDR, val)
+#define bfin_read_MDMA_D2_CONFIG()    bfin_read16(MDMA_D2_CONFIG)
+#define bfin_write_MDMA_D2_CONFIG(val) bfin_write16(MDMA_D2_CONFIG, val)
+#define bfin_read_MDMA_D2_X_COUNT()   bfin_read16(MDMA_D2_X_COUNT)
+#define bfin_write_MDMA_D2_X_COUNT(val) bfin_write16(MDMA_D2_X_COUNT, val)
+#define bfin_read_MDMA_D2_X_MODIFY()  bfin_read16(MDMA_D2_X_MODIFY)
+#define bfin_write_MDMA_D2_X_MODIFY(val) bfin_write16(MDMA_D2_X_MODIFY, val)
+#define bfin_read_MDMA_D2_Y_COUNT()   bfin_read16(MDMA_D2_Y_COUNT)
+#define bfin_write_MDMA_D2_Y_COUNT(val) bfin_write16(MDMA_D2_Y_COUNT, val)
+#define bfin_read_MDMA_D2_Y_MODIFY()  bfin_read16(MDMA_D2_Y_MODIFY)
+#define bfin_write_MDMA_D2_Y_MODIFY(val) bfin_write16(MDMA_D2_Y_MODIFY, val)
+#define bfin_read_MDMA_D2_CURR_DESC_PTR() bfin_readPTR(MDMA_D2_CURR_DESC_PTR)
+#define bfin_write_MDMA_D2_CURR_DESC_PTR(val) bfin_writePTR(MDMA_D2_CURR_DESC_PTR, val)
+#define bfin_read_MDMA_D2_CURR_ADDR() bfin_readPTR(MDMA_D2_CURR_ADDR)
+#define bfin_write_MDMA_D2_CURR_ADDR(val) bfin_writePTR(MDMA_D2_CURR_ADDR, val)
+#define bfin_read_MDMA_D2_IRQ_STATUS() bfin_read16(MDMA_D2_IRQ_STATUS)
+#define bfin_write_MDMA_D2_IRQ_STATUS(val) bfin_write16(MDMA_D2_IRQ_STATUS, val)
+#define bfin_read_MDMA_D2_PERIPHERAL_MAP() bfin_read16(MDMA_D2_PERIPHERAL_MAP)
+#define bfin_write_MDMA_D2_PERIPHERAL_MAP(val) bfin_write16(MDMA_D2_PERIPHERAL_MAP, val)
+#define bfin_read_MDMA_D2_CURR_X_COUNT() bfin_read16(MDMA_D2_CURR_X_COUNT)
+#define bfin_write_MDMA_D2_CURR_X_COUNT(val) bfin_write16(MDMA_D2_CURR_X_COUNT, val)
+#define bfin_read_MDMA_D2_CURR_Y_COUNT() bfin_read16(MDMA_D2_CURR_Y_COUNT)
+#define bfin_write_MDMA_D2_CURR_Y_COUNT(val) bfin_write16(MDMA_D2_CURR_Y_COUNT, val)
+#define bfin_read_MDMA_S2_NEXT_DESC_PTR() bfin_readPTR(MDMA_S2_NEXT_DESC_PTR)
+#define bfin_write_MDMA_S2_NEXT_DESC_PTR(val) bfin_writePTR(MDMA_S2_NEXT_DESC_PTR, val)
+#define bfin_read_MDMA_S2_START_ADDR() bfin_readPTR(MDMA_S2_START_ADDR)
+#define bfin_write_MDMA_S2_START_ADDR(val) bfin_writePTR(MDMA_S2_START_ADDR, val)
+#define bfin_read_MDMA_S2_CONFIG()    bfin_read16(MDMA_S2_CONFIG)
+#define bfin_write_MDMA_S2_CONFIG(val) bfin_write16(MDMA_S2_CONFIG, val)
+#define bfin_read_MDMA_S2_X_COUNT()   bfin_read16(MDMA_S2_X_COUNT)
+#define bfin_write_MDMA_S2_X_COUNT(val) bfin_write16(MDMA_S2_X_COUNT, val)
+#define bfin_read_MDMA_S2_X_MODIFY()  bfin_read16(MDMA_S2_X_MODIFY)
+#define bfin_write_MDMA_S2_X_MODIFY(val) bfin_write16(MDMA_S2_X_MODIFY, val)
+#define bfin_read_MDMA_S2_Y_COUNT()   bfin_read16(MDMA_S2_Y_COUNT)
+#define bfin_write_MDMA_S2_Y_COUNT(val) bfin_write16(MDMA_S2_Y_COUNT, val)
+#define bfin_read_MDMA_S2_Y_MODIFY()  bfin_read16(MDMA_S2_Y_MODIFY)
+#define bfin_write_MDMA_S2_Y_MODIFY(val) bfin_write16(MDMA_S2_Y_MODIFY, val)
+#define bfin_read_MDMA_S2_CURR_DESC_PTR() bfin_readPTR(MDMA_S2_CURR_DESC_PTR)
+#define bfin_write_MDMA_S2_CURR_DESC_PTR(val) bfin_writePTR(MDMA_S2_CURR_DESC_PTR, val)
+#define bfin_read_MDMA_S2_CURR_ADDR() bfin_readPTR(MDMA_S2_CURR_ADDR)
+#define bfin_write_MDMA_S2_CURR_ADDR(val) bfin_writePTR(MDMA_S2_CURR_ADDR, val)
+#define bfin_read_MDMA_S2_IRQ_STATUS() bfin_read16(MDMA_S2_IRQ_STATUS)
+#define bfin_write_MDMA_S2_IRQ_STATUS(val) bfin_write16(MDMA_S2_IRQ_STATUS, val)
+#define bfin_read_MDMA_S2_PERIPHERAL_MAP() bfin_read16(MDMA_S2_PERIPHERAL_MAP)
+#define bfin_write_MDMA_S2_PERIPHERAL_MAP(val) bfin_write16(MDMA_S2_PERIPHERAL_MAP, val)
+#define bfin_read_MDMA_S2_CURR_X_COUNT() bfin_read16(MDMA_S2_CURR_X_COUNT)
+#define bfin_write_MDMA_S2_CURR_X_COUNT(val) bfin_write16(MDMA_S2_CURR_X_COUNT, val)
+#define bfin_read_MDMA_S2_CURR_Y_COUNT() bfin_read16(MDMA_S2_CURR_Y_COUNT)
+#define bfin_write_MDMA_S2_CURR_Y_COUNT(val) bfin_write16(MDMA_S2_CURR_Y_COUNT, val)
+#define bfin_read_MDMA_D3_NEXT_DESC_PTR() bfin_readPTR(MDMA_D3_NEXT_DESC_PTR)
+#define bfin_write_MDMA_D3_NEXT_DESC_PTR(val) bfin_writePTR(MDMA_D3_NEXT_DESC_PTR, val)
+#define bfin_read_MDMA_D3_START_ADDR() bfin_readPTR(MDMA_D3_START_ADDR)
+#define bfin_write_MDMA_D3_START_ADDR(val) bfin_writePTR(MDMA_D3_START_ADDR, val)
+#define bfin_read_MDMA_D3_CONFIG()    bfin_read16(MDMA_D3_CONFIG)
+#define bfin_write_MDMA_D3_CONFIG(val) bfin_write16(MDMA_D3_CONFIG, val)
+#define bfin_read_MDMA_D3_X_COUNT()   bfin_read16(MDMA_D3_X_COUNT)
+#define bfin_write_MDMA_D3_X_COUNT(val) bfin_write16(MDMA_D3_X_COUNT, val)
+#define bfin_read_MDMA_D3_X_MODIFY()  bfin_read16(MDMA_D3_X_MODIFY)
+#define bfin_write_MDMA_D3_X_MODIFY(val) bfin_write16(MDMA_D3_X_MODIFY, val)
+#define bfin_read_MDMA_D3_Y_COUNT()   bfin_read16(MDMA_D3_Y_COUNT)
+#define bfin_write_MDMA_D3_Y_COUNT(val) bfin_write16(MDMA_D3_Y_COUNT, val)
+#define bfin_read_MDMA_D3_Y_MODIFY()  bfin_read16(MDMA_D3_Y_MODIFY)
+#define bfin_write_MDMA_D3_Y_MODIFY(val) bfin_write16(MDMA_D3_Y_MODIFY, val)
+#define bfin_read_MDMA_D3_CURR_DESC_PTR() bfin_readPTR(MDMA_D3_CURR_DESC_PTR)
+#define bfin_write_MDMA_D3_CURR_DESC_PTR(val) bfin_writePTR(MDMA_D3_CURR_DESC_PTR, val)
+#define bfin_read_MDMA_D3_CURR_ADDR() bfin_readPTR(MDMA_D3_CURR_ADDR)
+#define bfin_write_MDMA_D3_CURR_ADDR(val) bfin_writePTR(MDMA_D3_CURR_ADDR, val)
+#define bfin_read_MDMA_D3_IRQ_STATUS() bfin_read16(MDMA_D3_IRQ_STATUS)
+#define bfin_write_MDMA_D3_IRQ_STATUS(val) bfin_write16(MDMA_D3_IRQ_STATUS, val)
+#define bfin_read_MDMA_D3_PERIPHERAL_MAP() bfin_read16(MDMA_D3_PERIPHERAL_MAP)
+#define bfin_write_MDMA_D3_PERIPHERAL_MAP(val) bfin_write16(MDMA_D3_PERIPHERAL_MAP, val)
+#define bfin_read_MDMA_D3_CURR_X_COUNT() bfin_read16(MDMA_D3_CURR_X_COUNT)
+#define bfin_write_MDMA_D3_CURR_X_COUNT(val) bfin_write16(MDMA_D3_CURR_X_COUNT, val)
+#define bfin_read_MDMA_D3_CURR_Y_COUNT() bfin_read16(MDMA_D3_CURR_Y_COUNT)
+#define bfin_write_MDMA_D3_CURR_Y_COUNT(val) bfin_write16(MDMA_D3_CURR_Y_COUNT, val)
+#define bfin_read_MDMA_S3_NEXT_DESC_PTR() bfin_readPTR(MDMA_S3_NEXT_DESC_PTR)
+#define bfin_write_MDMA_S3_NEXT_DESC_PTR(val) bfin_writePTR(MDMA_S3_NEXT_DESC_PTR, val)
+#define bfin_read_MDMA_S3_START_ADDR() bfin_readPTR(MDMA_S3_START_ADDR)
+#define bfin_write_MDMA_S3_START_ADDR(val) bfin_writePTR(MDMA_S3_START_ADDR, val)
+#define bfin_read_MDMA_S3_CONFIG()    bfin_read16(MDMA_S3_CONFIG)
+#define bfin_write_MDMA_S3_CONFIG(val) bfin_write16(MDMA_S3_CONFIG, val)
+#define bfin_read_MDMA_S3_X_COUNT()   bfin_read16(MDMA_S3_X_COUNT)
+#define bfin_write_MDMA_S3_X_COUNT(val) bfin_write16(MDMA_S3_X_COUNT, val)
+#define bfin_read_MDMA_S3_X_MODIFY()  bfin_read16(MDMA_S3_X_MODIFY)
+#define bfin_write_MDMA_S3_X_MODIFY(val) bfin_write16(MDMA_S3_X_MODIFY, val)
+#define bfin_read_MDMA_S3_Y_COUNT()   bfin_read16(MDMA_S3_Y_COUNT)
+#define bfin_write_MDMA_S3_Y_COUNT(val) bfin_write16(MDMA_S3_Y_COUNT, val)
+#define bfin_read_MDMA_S3_Y_MODIFY()  bfin_read16(MDMA_S3_Y_MODIFY)
+#define bfin_write_MDMA_S3_Y_MODIFY(val) bfin_write16(MDMA_S3_Y_MODIFY, val)
+#define bfin_read_MDMA_S3_CURR_DESC_PTR() bfin_readPTR(MDMA_S3_CURR_DESC_PTR)
+#define bfin_write_MDMA_S3_CURR_DESC_PTR(val) bfin_writePTR(MDMA_S3_CURR_DESC_PTR, val)
+#define bfin_read_MDMA_S3_CURR_ADDR() bfin_readPTR(MDMA_S3_CURR_ADDR)
+#define bfin_write_MDMA_S3_CURR_ADDR(val) bfin_writePTR(MDMA_S3_CURR_ADDR, val)
+#define bfin_read_MDMA_S3_IRQ_STATUS() bfin_read16(MDMA_S3_IRQ_STATUS)
+#define bfin_write_MDMA_S3_IRQ_STATUS(val) bfin_write16(MDMA_S3_IRQ_STATUS, val)
+#define bfin_read_MDMA_S3_PERIPHERAL_MAP() bfin_read16(MDMA_S3_PERIPHERAL_MAP)
+#define bfin_write_MDMA_S3_PERIPHERAL_MAP(val) bfin_write16(MDMA_S3_PERIPHERAL_MAP, val)
+#define bfin_read_MDMA_S3_CURR_X_COUNT() bfin_read16(MDMA_S3_CURR_X_COUNT)
+#define bfin_write_MDMA_S3_CURR_X_COUNT(val) bfin_write16(MDMA_S3_CURR_X_COUNT, val)
+#define bfin_read_MDMA_S3_CURR_Y_COUNT() bfin_read16(MDMA_S3_CURR_Y_COUNT)
+#define bfin_write_MDMA_S3_CURR_Y_COUNT(val) bfin_write16(MDMA_S3_CURR_Y_COUNT, val)
 #define bfin_read_PPI_CONTROL()        bfin_read16(PPI_CONTROL)
 #define bfin_write_PPI_CONTROL(val)    bfin_write16(PPI_CONTROL, val)
 #define bfin_read_PPI_STATUS()         bfin_read16(PPI_STATUS)
@@ -2024,7 +1957,4 @@
 #define bfin_read_CAN_MB31_ID1()       bfin_read16(CAN_MB31_ID1)
 #define bfin_write_CAN_MB31_ID1(val)   bfin_write16(CAN_MB31_ID1, val)
 
-/* These need to be last due to the cdef/linux inter-dependencies */
-#include <asm/irq.h>
-
 #endif
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf538/include/mach/cdefBF539.h linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf538/include/mach/cdefBF539.h
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf538/include/mach/cdefBF539.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf538/include/mach/cdefBF539.h	2011-03-14 21:20:32.000000000 -0400
@@ -1,6 +1,7 @@
-/* DO NOT EDIT THIS FILE
- * Automatically generated by generate-cdef-headers.xsl
- * DO NOT EDIT THIS FILE
+/*
+ * Copyright 2008-2010 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
  */
 
 #ifndef _CDEF_BF539_H
@@ -9,7 +10,6 @@
 /* Include MMRs Common to BF538 								*/
 #include "cdefBF538.h"
 
-
 #define bfin_read_MXVR_CONFIG()        bfin_read16(MXVR_CONFIG)
 #define bfin_write_MXVR_CONFIG(val)    bfin_write16(MXVR_CONFIG, val)
 #define bfin_read_MXVR_PLL_CTL_0()     bfin_read32(MXVR_PLL_CTL_0)
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf538/include/mach/defBF538.h linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf538/include/mach/defBF538.h
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf538/include/mach/defBF538.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf538/include/mach/defBF538.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,1825 @@
+/*
+ * Copyright 2008-2010 Analog Devices Inc.
+ *
+ * Licensed under the ADI BSD license or the GPL-2 (or later)
+ */
+
+#ifndef _DEF_BF538_H
+#define _DEF_BF538_H
+
+/* Clock/Regulator Control (0xFFC00000 - 0xFFC000FF) */
+#define	PLL_CTL			0xFFC00000	/* PLL Control register (16-bit) */
+#define	PLL_DIV			0xFFC00004	/* PLL Divide Register (16-bit) */
+#define	VR_CTL			0xFFC00008	/* Voltage Regulator Control Register (16-bit) */
+#define	PLL_STAT		0xFFC0000C	/* PLL Status register (16-bit) */
+#define	PLL_LOCKCNT		0xFFC00010	/* PLL Lock	Count register (16-bit) */
+#define	CHIPID			0xFFC00014	/* Chip	ID Register */
+
+/* CHIPID Masks */
+#define CHIPID_VERSION         0xF0000000
+#define CHIPID_FAMILY          0x0FFFF000
+#define CHIPID_MANUFACTURE     0x00000FFE
+
+/* System Interrupt Controller (0xFFC00100 - 0xFFC001FF) */
+#define	SWRST			0xFFC00100  /* Software	Reset Register (16-bit) */
+#define	SYSCR			0xFFC00104  /* System Configuration registe */
+#define	SIC_RVECT		0xFFC00108
+#define	SIC_IMASK0		0xFFC0010C  /* Interrupt Mask Register */
+#define	SIC_IAR0		0xFFC00110  /* Interrupt Assignment Register 0 */
+#define	SIC_IAR1		0xFFC00114  /* Interrupt Assignment Register 1 */
+#define	SIC_IAR2		0xFFC00118  /* Interrupt Assignment Register 2 */
+#define	SIC_IAR3			0xFFC0011C	/* Interrupt Assignment	Register 3 */
+#define	SIC_ISR0			0xFFC00120  /* Interrupt Status	Register */
+#define	SIC_IWR0			0xFFC00124  /* Interrupt Wakeup	Register */
+#define	SIC_IMASK1			0xFFC00128	/* Interrupt Mask Register 1 */
+#define	SIC_ISR1			0xFFC0012C	/* Interrupt Status Register 1 */
+#define	SIC_IWR1			0xFFC00130	/* Interrupt Wakeup Register 1 */
+#define	SIC_IAR4			0xFFC00134	/* Interrupt Assignment	Register 4 */
+#define	SIC_IAR5			0xFFC00138	/* Interrupt Assignment	Register 5 */
+#define	SIC_IAR6			0xFFC0013C	/* Interrupt Assignment	Register 6 */
+
+
+/* Watchdog Timer (0xFFC00200 -	0xFFC002FF) */
+#define	WDOG_CTL	0xFFC00200  /* Watchdog	Control	Register */
+#define	WDOG_CNT	0xFFC00204  /* Watchdog	Count Register */
+#define	WDOG_STAT	0xFFC00208  /* Watchdog	Status Register */
+
+
+/* Real	Time Clock (0xFFC00300 - 0xFFC003FF) */
+#define	RTC_STAT	0xFFC00300  /* RTC Status Register */
+#define	RTC_ICTL	0xFFC00304  /* RTC Interrupt Control Register */
+#define	RTC_ISTAT	0xFFC00308  /* RTC Interrupt Status Register */
+#define	RTC_SWCNT	0xFFC0030C  /* RTC Stopwatch Count Register */
+#define	RTC_ALARM	0xFFC00310  /* RTC Alarm Time Register */
+#define	RTC_FAST	0xFFC00314  /* RTC Prescaler Enable Register */
+#define	RTC_PREN		0xFFC00314  /* RTC Prescaler Enable Register (alternate	macro) */
+
+
+/* UART0 Controller (0xFFC00400	- 0xFFC004FF) */
+#define	UART0_THR	      0xFFC00400  /* Transmit Holding register */
+#define	UART0_RBR	      0xFFC00400  /* Receive Buffer register */
+#define	UART0_DLL	      0xFFC00400  /* Divisor Latch (Low-Byte) */
+#define	UART0_IER	      0xFFC00404  /* Interrupt Enable Register */
+#define	UART0_DLH	      0xFFC00404  /* Divisor Latch (High-Byte) */
+#define	UART0_IIR	      0xFFC00408  /* Interrupt Identification Register */
+#define	UART0_LCR	      0xFFC0040C  /* Line Control Register */
+#define	UART0_MCR			 0xFFC00410  /*	Modem Control Register */
+#define	UART0_LSR	      0xFFC00414  /* Line Status Register */
+#define	UART0_SCR	      0xFFC0041C  /* SCR Scratch Register */
+#define	UART0_GCTL		     0xFFC00424	 /* Global Control Register */
+
+
+/* SPI0	Controller (0xFFC00500 - 0xFFC005FF) */
+
+#define	SPI0_CTL			0xFFC00500  /* SPI0 Control Register */
+#define	SPI0_FLG			0xFFC00504  /* SPI0 Flag register */
+#define	SPI0_STAT			0xFFC00508  /* SPI0 Status register */
+#define	SPI0_TDBR			0xFFC0050C  /* SPI0 Transmit Data Buffer Register */
+#define	SPI0_RDBR			0xFFC00510  /* SPI0 Receive Data Buffer	Register */
+#define	SPI0_BAUD			0xFFC00514  /* SPI0 Baud rate Register */
+#define	SPI0_SHADOW			0xFFC00518  /* SPI0_RDBR Shadow	Register */
+#define SPI0_REGBASE			SPI0_CTL
+
+
+/* TIMER 0, 1, 2 Registers (0xFFC00600 - 0xFFC006FF) */
+#define	TIMER0_CONFIG			0xFFC00600     /* Timer	0 Configuration	Register */
+#define	TIMER0_COUNTER				0xFFC00604     /* Timer	0 Counter Register */
+#define	TIMER0_PERIOD			0xFFC00608     /* Timer	0 Period Register */
+#define	TIMER0_WIDTH			0xFFC0060C     /* Timer	0 Width	Register */
+
+#define	TIMER1_CONFIG			0xFFC00610	/*  Timer 1 Configuration Register   */
+#define	TIMER1_COUNTER			0xFFC00614	/*  Timer 1 Counter Register	     */
+#define	TIMER1_PERIOD			0xFFC00618	/*  Timer 1 Period Register	     */
+#define	TIMER1_WIDTH			0xFFC0061C	/*  Timer 1 Width Register	     */
+
+#define	TIMER2_CONFIG			0xFFC00620	/* Timer 2 Configuration Register   */
+#define	TIMER2_COUNTER			0xFFC00624	/* Timer 2 Counter Register	    */
+#define	TIMER2_PERIOD			0xFFC00628	/* Timer 2 Period Register	    */
+#define	TIMER2_WIDTH			0xFFC0062C	/* Timer 2 Width Register	    */
+
+#define	TIMER_ENABLE				0xFFC00640	/* Timer Enable	Register */
+#define	TIMER_DISABLE				0xFFC00644	/* Timer Disable Register */
+#define	TIMER_STATUS				0xFFC00648	/* Timer Status	Register */
+
+
+/* Programmable	Flags (0xFFC00700 - 0xFFC007FF) */
+#define	FIO_FLAG_D				0xFFC00700  /* Flag Mask to directly specify state of pins */
+#define	FIO_FLAG_C			0xFFC00704  /* Peripheral Interrupt Flag Register (clear) */
+#define	FIO_FLAG_S			0xFFC00708  /* Peripheral Interrupt Flag Register (set) */
+#define	FIO_FLAG_T					0xFFC0070C  /* Flag Mask to directly toggle state of pins */
+#define	FIO_MASKA_D			0xFFC00710  /* Flag Mask Interrupt A Register (set directly) */
+#define	FIO_MASKA_C			0xFFC00714  /* Flag Mask Interrupt A Register (clear) */
+#define	FIO_MASKA_S			0xFFC00718  /* Flag Mask Interrupt A Register (set) */
+#define	FIO_MASKA_T			0xFFC0071C  /* Flag Mask Interrupt A Register (toggle) */
+#define	FIO_MASKB_D			0xFFC00720  /* Flag Mask Interrupt B Register (set directly) */
+#define	FIO_MASKB_C			0xFFC00724  /* Flag Mask Interrupt B Register (clear) */
+#define	FIO_MASKB_S			0xFFC00728  /* Flag Mask Interrupt B Register (set) */
+#define	FIO_MASKB_T			0xFFC0072C  /* Flag Mask Interrupt B Register (toggle) */
+#define	FIO_DIR				0xFFC00730  /* Peripheral Flag Direction Register */
+#define	FIO_POLAR			0xFFC00734  /* Flag Source Polarity Register */
+#define	FIO_EDGE			0xFFC00738  /* Flag Source Sensitivity Register */
+#define	FIO_BOTH			0xFFC0073C  /* Flag Set	on BOTH	Edges Register */
+#define	FIO_INEN					0xFFC00740  /* Flag Input Enable Register  */
+
+
+/* SPORT0 Controller (0xFFC00800 - 0xFFC008FF) */
+#define	SPORT0_TCR1				0xFFC00800  /* SPORT0 Transmit Configuration 1 Register */
+#define	SPORT0_TCR2				0xFFC00804  /* SPORT0 Transmit Configuration 2 Register */
+#define	SPORT0_TCLKDIV			0xFFC00808  /* SPORT0 Transmit Clock Divider */
+#define	SPORT0_TFSDIV			0xFFC0080C  /* SPORT0 Transmit Frame Sync Divider */
+#define	SPORT0_TX			0xFFC00810  /* SPORT0 TX Data Register */
+#define	SPORT0_RX			0xFFC00818  /* SPORT0 RX Data Register */
+#define	SPORT0_RCR1				0xFFC00820  /* SPORT0 Transmit Configuration 1 Register */
+#define	SPORT0_RCR2				0xFFC00824  /* SPORT0 Transmit Configuration 2 Register */
+#define	SPORT0_RCLKDIV			0xFFC00828  /* SPORT0 Receive Clock Divider */
+#define	SPORT0_RFSDIV			0xFFC0082C  /* SPORT0 Receive Frame Sync Divider */
+#define	SPORT0_STAT			0xFFC00830  /* SPORT0 Status Register */
+#define	SPORT0_CHNL			0xFFC00834  /* SPORT0 Current Channel Register */
+#define	SPORT0_MCMC1			0xFFC00838  /* SPORT0 Multi-Channel Configuration Register 1 */
+#define	SPORT0_MCMC2			0xFFC0083C  /* SPORT0 Multi-Channel Configuration Register 2 */
+#define	SPORT0_MTCS0			0xFFC00840  /* SPORT0 Multi-Channel Transmit Select Register 0 */
+#define	SPORT0_MTCS1			0xFFC00844  /* SPORT0 Multi-Channel Transmit Select Register 1 */
+#define	SPORT0_MTCS2			0xFFC00848  /* SPORT0 Multi-Channel Transmit Select Register 2 */
+#define	SPORT0_MTCS3			0xFFC0084C  /* SPORT0 Multi-Channel Transmit Select Register 3 */
+#define	SPORT0_MRCS0			0xFFC00850  /* SPORT0 Multi-Channel Receive Select Register 0 */
+#define	SPORT0_MRCS1			0xFFC00854  /* SPORT0 Multi-Channel Receive Select Register 1 */
+#define	SPORT0_MRCS2			0xFFC00858  /* SPORT0 Multi-Channel Receive Select Register 2 */
+#define	SPORT0_MRCS3			0xFFC0085C  /* SPORT0 Multi-Channel Receive Select Register 3 */
+
+
+/* SPORT1 Controller (0xFFC00900 - 0xFFC009FF) */
+#define	SPORT1_TCR1				0xFFC00900  /* SPORT1 Transmit Configuration 1 Register */
+#define	SPORT1_TCR2				0xFFC00904  /* SPORT1 Transmit Configuration 2 Register */
+#define	SPORT1_TCLKDIV			0xFFC00908  /* SPORT1 Transmit Clock Divider */
+#define	SPORT1_TFSDIV			0xFFC0090C  /* SPORT1 Transmit Frame Sync Divider */
+#define	SPORT1_TX			0xFFC00910  /* SPORT1 TX Data Register */
+#define	SPORT1_RX			0xFFC00918  /* SPORT1 RX Data Register */
+#define	SPORT1_RCR1				0xFFC00920  /* SPORT1 Transmit Configuration 1 Register */
+#define	SPORT1_RCR2				0xFFC00924  /* SPORT1 Transmit Configuration 2 Register */
+#define	SPORT1_RCLKDIV			0xFFC00928  /* SPORT1 Receive Clock Divider */
+#define	SPORT1_RFSDIV			0xFFC0092C  /* SPORT1 Receive Frame Sync Divider */
+#define	SPORT1_STAT			0xFFC00930  /* SPORT1 Status Register */
+#define	SPORT1_CHNL			0xFFC00934  /* SPORT1 Current Channel Register */
+#define	SPORT1_MCMC1			0xFFC00938  /* SPORT1 Multi-Channel Configuration Register 1 */
+#define	SPORT1_MCMC2			0xFFC0093C  /* SPORT1 Multi-Channel Configuration Register 2 */
+#define	SPORT1_MTCS0			0xFFC00940  /* SPORT1 Multi-Channel Transmit Select Register 0 */
+#define	SPORT1_MTCS1			0xFFC00944  /* SPORT1 Multi-Channel Transmit Select Register 1 */
+#define	SPORT1_MTCS2			0xFFC00948  /* SPORT1 Multi-Channel Transmit Select Register 2 */
+#define	SPORT1_MTCS3			0xFFC0094C  /* SPORT1 Multi-Channel Transmit Select Register 3 */
+#define	SPORT1_MRCS0			0xFFC00950  /* SPORT1 Multi-Channel Receive Select Register 0 */
+#define	SPORT1_MRCS1			0xFFC00954  /* SPORT1 Multi-Channel Receive Select Register 1 */
+#define	SPORT1_MRCS2			0xFFC00958  /* SPORT1 Multi-Channel Receive Select Register 2 */
+#define	SPORT1_MRCS3			0xFFC0095C  /* SPORT1 Multi-Channel Receive Select Register 3 */
+
+
+/* External Bus	Interface Unit (0xFFC00A00 - 0xFFC00AFF) */
+/* Asynchronous	Memory Controller  */
+#define	EBIU_AMGCTL			0xFFC00A00  /* Asynchronous Memory Global Control Register */
+#define	EBIU_AMBCTL0		0xFFC00A04  /* Asynchronous Memory Bank	Control	Register 0 */
+#define	EBIU_AMBCTL1		0xFFC00A08  /* Asynchronous Memory Bank	Control	Register 1 */
+
+/* SDRAM Controller */
+#define	EBIU_SDGCTL			0xFFC00A10  /* SDRAM Global Control Register */
+#define	EBIU_SDBCTL			0xFFC00A14  /* SDRAM Bank Control Register */
+#define	EBIU_SDRRC			0xFFC00A18  /* SDRAM Refresh Rate Control Register */
+#define	EBIU_SDSTAT			0xFFC00A1C  /* SDRAM Status Register */
+
+
+
+/* DMA Controller 0 Traffic Control Registers (0xFFC00B00 - 0xFFC00BFF) */
+
+#define	DMAC0_TC_PER			0xFFC00B0C	/* DMA Controller 0 Traffic Control Periods Register */
+#define	DMAC0_TC_CNT			0xFFC00B10	/* DMA Controller 0 Traffic Control Current Counts Register */
+
+
+
+/* DMA Controller 0 (0xFFC00C00	- 0xFFC00FFF)							 */
+
+#define	DMA0_NEXT_DESC_PTR		0xFFC00C00	/* DMA Channel 0 Next Descriptor Pointer Register */
+#define	DMA0_START_ADDR			0xFFC00C04	/* DMA Channel 0 Start Address Register */
+#define	DMA0_CONFIG				0xFFC00C08	/* DMA Channel 0 Configuration Register */
+#define	DMA0_X_COUNT			0xFFC00C10	/* DMA Channel 0 X Count Register */
+#define	DMA0_X_MODIFY			0xFFC00C14	/* DMA Channel 0 X Modify Register */
+#define	DMA0_Y_COUNT			0xFFC00C18	/* DMA Channel 0 Y Count Register */
+#define	DMA0_Y_MODIFY			0xFFC00C1C	/* DMA Channel 0 Y Modify Register */
+#define	DMA0_CURR_DESC_PTR		0xFFC00C20	/* DMA Channel 0 Current Descriptor Pointer Register */
+#define	DMA0_CURR_ADDR			0xFFC00C24	/* DMA Channel 0 Current Address Register */
+#define	DMA0_IRQ_STATUS			0xFFC00C28	/* DMA Channel 0 Interrupt/Status Register */
+#define	DMA0_PERIPHERAL_MAP		0xFFC00C2C	/* DMA Channel 0 Peripheral Map	Register */
+#define	DMA0_CURR_X_COUNT		0xFFC00C30	/* DMA Channel 0 Current X Count Register */
+#define	DMA0_CURR_Y_COUNT		0xFFC00C38	/* DMA Channel 0 Current Y Count Register */
+
+#define	DMA1_NEXT_DESC_PTR		0xFFC00C40	/* DMA Channel 1 Next Descriptor Pointer Register */
+#define	DMA1_START_ADDR			0xFFC00C44	/* DMA Channel 1 Start Address Register */
+#define	DMA1_CONFIG				0xFFC00C48	/* DMA Channel 1 Configuration Register */
+#define	DMA1_X_COUNT			0xFFC00C50	/* DMA Channel 1 X Count Register */
+#define	DMA1_X_MODIFY			0xFFC00C54	/* DMA Channel 1 X Modify Register */
+#define	DMA1_Y_COUNT			0xFFC00C58	/* DMA Channel 1 Y Count Register */
+#define	DMA1_Y_MODIFY			0xFFC00C5C	/* DMA Channel 1 Y Modify Register */
+#define	DMA1_CURR_DESC_PTR		0xFFC00C60	/* DMA Channel 1 Current Descriptor Pointer Register */
+#define	DMA1_CURR_ADDR			0xFFC00C64	/* DMA Channel 1 Current Address Register */
+#define	DMA1_IRQ_STATUS			0xFFC00C68	/* DMA Channel 1 Interrupt/Status Register */
+#define	DMA1_PERIPHERAL_MAP		0xFFC00C6C	/* DMA Channel 1 Peripheral Map	Register */
+#define	DMA1_CURR_X_COUNT		0xFFC00C70	/* DMA Channel 1 Current X Count Register */
+#define	DMA1_CURR_Y_COUNT		0xFFC00C78	/* DMA Channel 1 Current Y Count Register */
+
+#define	DMA2_NEXT_DESC_PTR		0xFFC00C80	/* DMA Channel 2 Next Descriptor Pointer Register */
+#define	DMA2_START_ADDR			0xFFC00C84	/* DMA Channel 2 Start Address Register */
+#define	DMA2_CONFIG				0xFFC00C88	/* DMA Channel 2 Configuration Register */
+#define	DMA2_X_COUNT			0xFFC00C90	/* DMA Channel 2 X Count Register */
+#define	DMA2_X_MODIFY			0xFFC00C94	/* DMA Channel 2 X Modify Register */
+#define	DMA2_Y_COUNT			0xFFC00C98	/* DMA Channel 2 Y Count Register */
+#define	DMA2_Y_MODIFY			0xFFC00C9C	/* DMA Channel 2 Y Modify Register */
+#define	DMA2_CURR_DESC_PTR		0xFFC00CA0	/* DMA Channel 2 Current Descriptor Pointer Register */
+#define	DMA2_CURR_ADDR			0xFFC00CA4	/* DMA Channel 2 Current Address Register */
+#define	DMA2_IRQ_STATUS			0xFFC00CA8	/* DMA Channel 2 Interrupt/Status Register */
+#define	DMA2_PERIPHERAL_MAP		0xFFC00CAC	/* DMA Channel 2 Peripheral Map	Register */
+#define	DMA2_CURR_X_COUNT		0xFFC00CB0	/* DMA Channel 2 Current X Count Register */
+#define	DMA2_CURR_Y_COUNT		0xFFC00CB8	/* DMA Channel 2 Current Y Count Register */
+
+#define	DMA3_NEXT_DESC_PTR		0xFFC00CC0	/* DMA Channel 3 Next Descriptor Pointer Register */
+#define	DMA3_START_ADDR			0xFFC00CC4	/* DMA Channel 3 Start Address Register */
+#define	DMA3_CONFIG				0xFFC00CC8	/* DMA Channel 3 Configuration Register */
+#define	DMA3_X_COUNT			0xFFC00CD0	/* DMA Channel 3 X Count Register */
+#define	DMA3_X_MODIFY			0xFFC00CD4	/* DMA Channel 3 X Modify Register */
+#define	DMA3_Y_COUNT			0xFFC00CD8	/* DMA Channel 3 Y Count Register */
+#define	DMA3_Y_MODIFY			0xFFC00CDC	/* DMA Channel 3 Y Modify Register */
+#define	DMA3_CURR_DESC_PTR		0xFFC00CE0	/* DMA Channel 3 Current Descriptor Pointer Register */
+#define	DMA3_CURR_ADDR			0xFFC00CE4	/* DMA Channel 3 Current Address Register */
+#define	DMA3_IRQ_STATUS			0xFFC00CE8	/* DMA Channel 3 Interrupt/Status Register */
+#define	DMA3_PERIPHERAL_MAP		0xFFC00CEC	/* DMA Channel 3 Peripheral Map	Register */
+#define	DMA3_CURR_X_COUNT		0xFFC00CF0	/* DMA Channel 3 Current X Count Register */
+#define	DMA3_CURR_Y_COUNT		0xFFC00CF8	/* DMA Channel 3 Current Y Count Register */
+
+#define	DMA4_NEXT_DESC_PTR		0xFFC00D00	/* DMA Channel 4 Next Descriptor Pointer Register */
+#define	DMA4_START_ADDR			0xFFC00D04	/* DMA Channel 4 Start Address Register */
+#define	DMA4_CONFIG				0xFFC00D08	/* DMA Channel 4 Configuration Register */
+#define	DMA4_X_COUNT			0xFFC00D10	/* DMA Channel 4 X Count Register */
+#define	DMA4_X_MODIFY			0xFFC00D14	/* DMA Channel 4 X Modify Register */
+#define	DMA4_Y_COUNT			0xFFC00D18	/* DMA Channel 4 Y Count Register */
+#define	DMA4_Y_MODIFY			0xFFC00D1C	/* DMA Channel 4 Y Modify Register */
+#define	DMA4_CURR_DESC_PTR		0xFFC00D20	/* DMA Channel 4 Current Descriptor Pointer Register */
+#define	DMA4_CURR_ADDR			0xFFC00D24	/* DMA Channel 4 Current Address Register */
+#define	DMA4_IRQ_STATUS			0xFFC00D28	/* DMA Channel 4 Interrupt/Status Register */
+#define	DMA4_PERIPHERAL_MAP		0xFFC00D2C	/* DMA Channel 4 Peripheral Map	Register */
+#define	DMA4_CURR_X_COUNT		0xFFC00D30	/* DMA Channel 4 Current X Count Register */
+#define	DMA4_CURR_Y_COUNT		0xFFC00D38	/* DMA Channel 4 Current Y Count Register */
+
+#define	DMA5_NEXT_DESC_PTR		0xFFC00D40	/* DMA Channel 5 Next Descriptor Pointer Register */
+#define	DMA5_START_ADDR			0xFFC00D44	/* DMA Channel 5 Start Address Register */
+#define	DMA5_CONFIG				0xFFC00D48	/* DMA Channel 5 Configuration Register */
+#define	DMA5_X_COUNT			0xFFC00D50	/* DMA Channel 5 X Count Register */
+#define	DMA5_X_MODIFY			0xFFC00D54	/* DMA Channel 5 X Modify Register */
+#define	DMA5_Y_COUNT			0xFFC00D58	/* DMA Channel 5 Y Count Register */
+#define	DMA5_Y_MODIFY			0xFFC00D5C	/* DMA Channel 5 Y Modify Register */
+#define	DMA5_CURR_DESC_PTR		0xFFC00D60	/* DMA Channel 5 Current Descriptor Pointer Register */
+#define	DMA5_CURR_ADDR			0xFFC00D64	/* DMA Channel 5 Current Address Register */
+#define	DMA5_IRQ_STATUS			0xFFC00D68	/* DMA Channel 5 Interrupt/Status Register */
+#define	DMA5_PERIPHERAL_MAP		0xFFC00D6C	/* DMA Channel 5 Peripheral Map	Register */
+#define	DMA5_CURR_X_COUNT		0xFFC00D70	/* DMA Channel 5 Current X Count Register */
+#define	DMA5_CURR_Y_COUNT		0xFFC00D78	/* DMA Channel 5 Current Y Count Register */
+
+#define	DMA6_NEXT_DESC_PTR		0xFFC00D80	/* DMA Channel 6 Next Descriptor Pointer Register */
+#define	DMA6_START_ADDR			0xFFC00D84	/* DMA Channel 6 Start Address Register */
+#define	DMA6_CONFIG				0xFFC00D88	/* DMA Channel 6 Configuration Register */
+#define	DMA6_X_COUNT			0xFFC00D90	/* DMA Channel 6 X Count Register */
+#define	DMA6_X_MODIFY			0xFFC00D94	/* DMA Channel 6 X Modify Register */
+#define	DMA6_Y_COUNT			0xFFC00D98	/* DMA Channel 6 Y Count Register */
+#define	DMA6_Y_MODIFY			0xFFC00D9C	/* DMA Channel 6 Y Modify Register */
+#define	DMA6_CURR_DESC_PTR		0xFFC00DA0	/* DMA Channel 6 Current Descriptor Pointer Register */
+#define	DMA6_CURR_ADDR			0xFFC00DA4	/* DMA Channel 6 Current Address Register */
+#define	DMA6_IRQ_STATUS			0xFFC00DA8	/* DMA Channel 6 Interrupt/Status Register */
+#define	DMA6_PERIPHERAL_MAP		0xFFC00DAC	/* DMA Channel 6 Peripheral Map	Register */
+#define	DMA6_CURR_X_COUNT		0xFFC00DB0	/* DMA Channel 6 Current X Count Register */
+#define	DMA6_CURR_Y_COUNT		0xFFC00DB8	/* DMA Channel 6 Current Y Count Register */
+
+#define	DMA7_NEXT_DESC_PTR		0xFFC00DC0	/* DMA Channel 7 Next Descriptor Pointer Register */
+#define	DMA7_START_ADDR			0xFFC00DC4	/* DMA Channel 7 Start Address Register */
+#define	DMA7_CONFIG				0xFFC00DC8	/* DMA Channel 7 Configuration Register */
+#define	DMA7_X_COUNT			0xFFC00DD0	/* DMA Channel 7 X Count Register */
+#define	DMA7_X_MODIFY			0xFFC00DD4	/* DMA Channel 7 X Modify Register */
+#define	DMA7_Y_COUNT			0xFFC00DD8	/* DMA Channel 7 Y Count Register */
+#define	DMA7_Y_MODIFY			0xFFC00DDC	/* DMA Channel 7 Y Modify Register */
+#define	DMA7_CURR_DESC_PTR		0xFFC00DE0	/* DMA Channel 7 Current Descriptor Pointer Register */
+#define	DMA7_CURR_ADDR			0xFFC00DE4	/* DMA Channel 7 Current Address Register */
+#define	DMA7_IRQ_STATUS			0xFFC00DE8	/* DMA Channel 7 Interrupt/Status Register */
+#define	DMA7_PERIPHERAL_MAP		0xFFC00DEC	/* DMA Channel 7 Peripheral Map	Register */
+#define	DMA7_CURR_X_COUNT		0xFFC00DF0	/* DMA Channel 7 Current X Count Register */
+#define	DMA7_CURR_Y_COUNT		0xFFC00DF8	/* DMA Channel 7 Current Y Count Register */
+
+#define	MDMA_D0_NEXT_DESC_PTR	0xFFC00E00	/* MemDMA0 Stream 0 Destination	Next Descriptor	Pointer	Register */
+#define	MDMA_D0_START_ADDR		0xFFC00E04	/* MemDMA0 Stream 0 Destination	Start Address Register */
+#define	MDMA_D0_CONFIG			0xFFC00E08	/* MemDMA0 Stream 0 Destination	Configuration Register */
+#define	MDMA_D0_X_COUNT		0xFFC00E10	/* MemDMA0 Stream 0 Destination	X Count	Register */
+#define	MDMA_D0_X_MODIFY		0xFFC00E14	/* MemDMA0 Stream 0 Destination	X Modify Register */
+#define	MDMA_D0_Y_COUNT		0xFFC00E18	/* MemDMA0 Stream 0 Destination	Y Count	Register */
+#define	MDMA_D0_Y_MODIFY		0xFFC00E1C	/* MemDMA0 Stream 0 Destination	Y Modify Register */
+#define	MDMA_D0_CURR_DESC_PTR	0xFFC00E20	/* MemDMA0 Stream 0 Destination	Current	Descriptor Pointer Register */
+#define	MDMA_D0_CURR_ADDR		0xFFC00E24	/* MemDMA0 Stream 0 Destination	Current	Address	Register */
+#define	MDMA_D0_IRQ_STATUS		0xFFC00E28	/* MemDMA0 Stream 0 Destination	Interrupt/Status Register */
+#define	MDMA_D0_PERIPHERAL_MAP	0xFFC00E2C	/* MemDMA0 Stream 0 Destination	Peripheral Map Register */
+#define	MDMA_D0_CURR_X_COUNT	0xFFC00E30	/* MemDMA0 Stream 0 Destination	Current	X Count	Register */
+#define	MDMA_D0_CURR_Y_COUNT	0xFFC00E38	/* MemDMA0 Stream 0 Destination	Current	Y Count	Register */
+
+#define	MDMA_S0_NEXT_DESC_PTR	0xFFC00E40	/* MemDMA0 Stream 0 Source Next	Descriptor Pointer Register */
+#define	MDMA_S0_START_ADDR		0xFFC00E44	/* MemDMA0 Stream 0 Source Start Address Register */
+#define	MDMA_S0_CONFIG			0xFFC00E48	/* MemDMA0 Stream 0 Source Configuration Register */
+#define	MDMA_S0_X_COUNT		0xFFC00E50	/* MemDMA0 Stream 0 Source X Count Register */
+#define	MDMA_S0_X_MODIFY		0xFFC00E54	/* MemDMA0 Stream 0 Source X Modify Register */
+#define	MDMA_S0_Y_COUNT		0xFFC00E58	/* MemDMA0 Stream 0 Source Y Count Register */
+#define	MDMA_S0_Y_MODIFY		0xFFC00E5C	/* MemDMA0 Stream 0 Source Y Modify Register */
+#define	MDMA_S0_CURR_DESC_PTR	0xFFC00E60	/* MemDMA0 Stream 0 Source Current Descriptor Pointer Register */
+#define	MDMA_S0_CURR_ADDR		0xFFC00E64	/* MemDMA0 Stream 0 Source Current Address Register */
+#define	MDMA_S0_IRQ_STATUS		0xFFC00E68	/* MemDMA0 Stream 0 Source Interrupt/Status Register */
+#define	MDMA_S0_PERIPHERAL_MAP	0xFFC00E6C	/* MemDMA0 Stream 0 Source Peripheral Map Register */
+#define	MDMA_S0_CURR_X_COUNT	0xFFC00E70	/* MemDMA0 Stream 0 Source Current X Count Register */
+#define	MDMA_S0_CURR_Y_COUNT	0xFFC00E78	/* MemDMA0 Stream 0 Source Current Y Count Register */
+
+#define	MDMA_D1_NEXT_DESC_PTR	0xFFC00E80	/* MemDMA0 Stream 1 Destination	Next Descriptor	Pointer	Register */
+#define	MDMA_D1_START_ADDR		0xFFC00E84	/* MemDMA0 Stream 1 Destination	Start Address Register */
+#define	MDMA_D1_CONFIG			0xFFC00E88	/* MemDMA0 Stream 1 Destination	Configuration Register */
+#define	MDMA_D1_X_COUNT		0xFFC00E90	/* MemDMA0 Stream 1 Destination	X Count	Register */
+#define	MDMA_D1_X_MODIFY		0xFFC00E94	/* MemDMA0 Stream 1 Destination	X Modify Register */
+#define	MDMA_D1_Y_COUNT		0xFFC00E98	/* MemDMA0 Stream 1 Destination	Y Count	Register */
+#define	MDMA_D1_Y_MODIFY		0xFFC00E9C	/* MemDMA0 Stream 1 Destination	Y Modify Register */
+#define	MDMA_D1_CURR_DESC_PTR	0xFFC00EA0	/* MemDMA0 Stream 1 Destination	Current	Descriptor Pointer Register */
+#define	MDMA_D1_CURR_ADDR		0xFFC00EA4	/* MemDMA0 Stream 1 Destination	Current	Address	Register */
+#define	MDMA_D1_IRQ_STATUS		0xFFC00EA8	/* MemDMA0 Stream 1 Destination	Interrupt/Status Register */
+#define	MDMA_D1_PERIPHERAL_MAP	0xFFC00EAC	/* MemDMA0 Stream 1 Destination	Peripheral Map Register */
+#define	MDMA_D1_CURR_X_COUNT	0xFFC00EB0	/* MemDMA0 Stream 1 Destination	Current	X Count	Register */
+#define	MDMA_D1_CURR_Y_COUNT	0xFFC00EB8	/* MemDMA0 Stream 1 Destination	Current	Y Count	Register */
+
+#define	MDMA_S1_NEXT_DESC_PTR	0xFFC00EC0	/* MemDMA0 Stream 1 Source Next	Descriptor Pointer Register */
+#define	MDMA_S1_START_ADDR		0xFFC00EC4	/* MemDMA0 Stream 1 Source Start Address Register */
+#define	MDMA_S1_CONFIG			0xFFC00EC8	/* MemDMA0 Stream 1 Source Configuration Register */
+#define	MDMA_S1_X_COUNT		0xFFC00ED0	/* MemDMA0 Stream 1 Source X Count Register */
+#define	MDMA_S1_X_MODIFY		0xFFC00ED4	/* MemDMA0 Stream 1 Source X Modify Register */
+#define	MDMA_S1_Y_COUNT		0xFFC00ED8	/* MemDMA0 Stream 1 Source Y Count Register */
+#define	MDMA_S1_Y_MODIFY		0xFFC00EDC	/* MemDMA0 Stream 1 Source Y Modify Register */
+#define	MDMA_S1_CURR_DESC_PTR	0xFFC00EE0	/* MemDMA0 Stream 1 Source Current Descriptor Pointer Register */
+#define	MDMA_S1_CURR_ADDR		0xFFC00EE4	/* MemDMA0 Stream 1 Source Current Address Register */
+#define	MDMA_S1_IRQ_STATUS		0xFFC00EE8	/* MemDMA0 Stream 1 Source Interrupt/Status Register */
+#define	MDMA_S1_PERIPHERAL_MAP	0xFFC00EEC	/* MemDMA0 Stream 1 Source Peripheral Map Register */
+#define	MDMA_S1_CURR_X_COUNT	0xFFC00EF0	/* MemDMA0 Stream 1 Source Current X Count Register */
+#define	MDMA_S1_CURR_Y_COUNT	0xFFC00EF8	/* MemDMA0 Stream 1 Source Current Y Count Register */
+
+
+/* Parallel Peripheral Interface (PPI) (0xFFC01000 - 0xFFC010FF) */
+#define	PPI_CONTROL			0xFFC01000	/* PPI Control Register */
+#define	PPI_STATUS			0xFFC01004	/* PPI Status Register */
+#define	PPI_COUNT			0xFFC01008	/* PPI Transfer	Count Register */
+#define	PPI_DELAY			0xFFC0100C	/* PPI Delay Count Register */
+#define	PPI_FRAME			0xFFC01010	/* PPI Frame Length Register */
+
+
+/* Two-Wire Interface 0	(0xFFC01400 - 0xFFC014FF)			 */
+#define	TWI0_CLKDIV			0xFFC01400	/* Serial Clock	Divider	Register */
+#define	TWI0_CONTROL		0xFFC01404	/* TWI0	Master Internal	Time Reference Register */
+#define	TWI0_SLAVE_CTL		0xFFC01408	/* Slave Mode Control Register */
+#define	TWI0_SLAVE_STAT		0xFFC0140C	/* Slave Mode Status Register */
+#define	TWI0_SLAVE_ADDR		0xFFC01410	/* Slave Mode Address Register */
+#define	TWI0_MASTER_CTL	0xFFC01414	/* Master Mode Control Register */
+#define	TWI0_MASTER_STAT	0xFFC01418	/* Master Mode Status Register */
+#define	TWI0_MASTER_ADDR	0xFFC0141C	/* Master Mode Address Register */
+#define	TWI0_INT_STAT		0xFFC01420	/* TWI0	Master Interrupt Register */
+#define	TWI0_INT_MASK		0xFFC01424	/* TWI0	Master Interrupt Mask Register */
+#define	TWI0_FIFO_CTL		0xFFC01428	/* FIFO	Control	Register */
+#define	TWI0_FIFO_STAT		0xFFC0142C	/* FIFO	Status Register */
+#define	TWI0_XMT_DATA8		0xFFC01480	/* FIFO	Transmit Data Single Byte Register */
+#define	TWI0_XMT_DATA16		0xFFC01484	/* FIFO	Transmit Data Double Byte Register */
+#define	TWI0_RCV_DATA8		0xFFC01488	/* FIFO	Receive	Data Single Byte Register */
+#define	TWI0_RCV_DATA16		0xFFC0148C	/* FIFO	Receive	Data Double Byte Register */
+
+#define TWI0_REGBASE		TWI0_CLKDIV
+
+/* the following are for backwards compatibility */
+#define	TWI0_PRESCALE	 TWI0_CONTROL
+#define	TWI0_INT_SRC	 TWI0_INT_STAT
+#define	TWI0_INT_ENABLE	 TWI0_INT_MASK
+
+
+/* General-Purpose Ports  (0xFFC01500 -	0xFFC015FF)	 */
+
+/* GPIO	Port C Register	Names */
+#define PORTCIO_FER			0xFFC01500	/* GPIO	Pin Port C Configuration Register */
+#define PORTCIO				0xFFC01510	/* GPIO	Pin Port C Data	Register */
+#define PORTCIO_CLEAR			0xFFC01520	/* Clear GPIO Pin Port C Register */
+#define PORTCIO_SET			0xFFC01530	/* Set GPIO Pin	Port C Register */
+#define PORTCIO_TOGGLE			0xFFC01540	/* Toggle GPIO Pin Port	C Register */
+#define PORTCIO_DIR			0xFFC01550	/* GPIO	Pin Port C Direction Register */
+#define PORTCIO_INEN			0xFFC01560	/* GPIO	Pin Port C Input Enable	Register */
+
+/* GPIO	Port D Register	Names */
+#define PORTDIO_FER			0xFFC01504	/* GPIO	Pin Port D Configuration Register */
+#define PORTDIO				0xFFC01514	/* GPIO	Pin Port D Data	Register */
+#define PORTDIO_CLEAR			0xFFC01524	/* Clear GPIO Pin Port D Register */
+#define PORTDIO_SET			0xFFC01534	/* Set GPIO Pin	Port D Register */
+#define PORTDIO_TOGGLE			0xFFC01544	/* Toggle GPIO Pin Port	D Register */
+#define PORTDIO_DIR			0xFFC01554	/* GPIO	Pin Port D Direction Register */
+#define PORTDIO_INEN			0xFFC01564	/* GPIO	Pin Port D Input Enable	Register */
+
+/* GPIO	Port E Register	Names */
+#define PORTEIO_FER			0xFFC01508	/* GPIO	Pin Port E Configuration Register */
+#define PORTEIO				0xFFC01518	/* GPIO	Pin Port E Data	Register */
+#define PORTEIO_CLEAR			0xFFC01528	/* Clear GPIO Pin Port E Register */
+#define PORTEIO_SET			0xFFC01538	/* Set GPIO Pin	Port E Register */
+#define PORTEIO_TOGGLE			0xFFC01548	/* Toggle GPIO Pin Port	E Register */
+#define PORTEIO_DIR			0xFFC01558	/* GPIO	Pin Port E Direction Register */
+#define PORTEIO_INEN			0xFFC01568	/* GPIO	Pin Port E Input Enable	Register */
+
+/* DMA Controller 1 Traffic Control Registers (0xFFC01B00 - 0xFFC01BFF) */
+
+#define	DMAC1_TC_PER			0xFFC01B0C	/* DMA Controller 1 Traffic Control Periods Register */
+#define	DMAC1_TC_CNT			0xFFC01B10	/* DMA Controller 1 Traffic Control Current Counts Register */
+
+
+
+/* DMA Controller 1 (0xFFC01C00	- 0xFFC01FFF)							 */
+#define	DMA8_NEXT_DESC_PTR		0xFFC01C00	/* DMA Channel 8 Next Descriptor Pointer Register */
+#define	DMA8_START_ADDR			0xFFC01C04	/* DMA Channel 8 Start Address Register */
+#define	DMA8_CONFIG				0xFFC01C08	/* DMA Channel 8 Configuration Register */
+#define	DMA8_X_COUNT			0xFFC01C10	/* DMA Channel 8 X Count Register */
+#define	DMA8_X_MODIFY			0xFFC01C14	/* DMA Channel 8 X Modify Register */
+#define	DMA8_Y_COUNT			0xFFC01C18	/* DMA Channel 8 Y Count Register */
+#define	DMA8_Y_MODIFY			0xFFC01C1C	/* DMA Channel 8 Y Modify Register */
+#define	DMA8_CURR_DESC_PTR		0xFFC01C20	/* DMA Channel 8 Current Descriptor Pointer Register */
+#define	DMA8_CURR_ADDR			0xFFC01C24	/* DMA Channel 8 Current Address Register */
+#define	DMA8_IRQ_STATUS			0xFFC01C28	/* DMA Channel 8 Interrupt/Status Register */
+#define	DMA8_PERIPHERAL_MAP		0xFFC01C2C	/* DMA Channel 8 Peripheral Map	Register */
+#define	DMA8_CURR_X_COUNT		0xFFC01C30	/* DMA Channel 8 Current X Count Register */
+#define	DMA8_CURR_Y_COUNT		0xFFC01C38	/* DMA Channel 8 Current Y Count Register */
+
+#define	DMA9_NEXT_DESC_PTR		0xFFC01C40	/* DMA Channel 9 Next Descriptor Pointer Register */
+#define	DMA9_START_ADDR			0xFFC01C44	/* DMA Channel 9 Start Address Register */
+#define	DMA9_CONFIG				0xFFC01C48	/* DMA Channel 9 Configuration Register */
+#define	DMA9_X_COUNT			0xFFC01C50	/* DMA Channel 9 X Count Register */
+#define	DMA9_X_MODIFY			0xFFC01C54	/* DMA Channel 9 X Modify Register */
+#define	DMA9_Y_COUNT			0xFFC01C58	/* DMA Channel 9 Y Count Register */
+#define	DMA9_Y_MODIFY			0xFFC01C5C	/* DMA Channel 9 Y Modify Register */
+#define	DMA9_CURR_DESC_PTR		0xFFC01C60	/* DMA Channel 9 Current Descriptor Pointer Register */
+#define	DMA9_CURR_ADDR			0xFFC01C64	/* DMA Channel 9 Current Address Register */
+#define	DMA9_IRQ_STATUS			0xFFC01C68	/* DMA Channel 9 Interrupt/Status Register */
+#define	DMA9_PERIPHERAL_MAP		0xFFC01C6C	/* DMA Channel 9 Peripheral Map	Register */
+#define	DMA9_CURR_X_COUNT		0xFFC01C70	/* DMA Channel 9 Current X Count Register */
+#define	DMA9_CURR_Y_COUNT		0xFFC01C78	/* DMA Channel 9 Current Y Count Register */
+
+#define	DMA10_NEXT_DESC_PTR		0xFFC01C80	/* DMA Channel 10 Next Descriptor Pointer Register */
+#define	DMA10_START_ADDR		0xFFC01C84	/* DMA Channel 10 Start	Address	Register */
+#define	DMA10_CONFIG			0xFFC01C88	/* DMA Channel 10 Configuration	Register */
+#define	DMA10_X_COUNT			0xFFC01C90	/* DMA Channel 10 X Count Register */
+#define	DMA10_X_MODIFY			0xFFC01C94	/* DMA Channel 10 X Modify Register */
+#define	DMA10_Y_COUNT			0xFFC01C98	/* DMA Channel 10 Y Count Register */
+#define	DMA10_Y_MODIFY			0xFFC01C9C	/* DMA Channel 10 Y Modify Register */
+#define	DMA10_CURR_DESC_PTR		0xFFC01CA0	/* DMA Channel 10 Current Descriptor Pointer Register */
+#define	DMA10_CURR_ADDR			0xFFC01CA4	/* DMA Channel 10 Current Address Register */
+#define	DMA10_IRQ_STATUS		0xFFC01CA8	/* DMA Channel 10 Interrupt/Status Register */
+#define	DMA10_PERIPHERAL_MAP	0xFFC01CAC	/* DMA Channel 10 Peripheral Map Register */
+#define	DMA10_CURR_X_COUNT		0xFFC01CB0	/* DMA Channel 10 Current X Count Register */
+#define	DMA10_CURR_Y_COUNT		0xFFC01CB8	/* DMA Channel 10 Current Y Count Register */
+
+#define	DMA11_NEXT_DESC_PTR		0xFFC01CC0	/* DMA Channel 11 Next Descriptor Pointer Register */
+#define	DMA11_START_ADDR		0xFFC01CC4	/* DMA Channel 11 Start	Address	Register */
+#define	DMA11_CONFIG			0xFFC01CC8	/* DMA Channel 11 Configuration	Register */
+#define	DMA11_X_COUNT			0xFFC01CD0	/* DMA Channel 11 X Count Register */
+#define	DMA11_X_MODIFY			0xFFC01CD4	/* DMA Channel 11 X Modify Register */
+#define	DMA11_Y_COUNT			0xFFC01CD8	/* DMA Channel 11 Y Count Register */
+#define	DMA11_Y_MODIFY			0xFFC01CDC	/* DMA Channel 11 Y Modify Register */
+#define	DMA11_CURR_DESC_PTR		0xFFC01CE0	/* DMA Channel 11 Current Descriptor Pointer Register */
+#define	DMA11_CURR_ADDR			0xFFC01CE4	/* DMA Channel 11 Current Address Register */
+#define	DMA11_IRQ_STATUS		0xFFC01CE8	/* DMA Channel 11 Interrupt/Status Register */
+#define	DMA11_PERIPHERAL_MAP	0xFFC01CEC	/* DMA Channel 11 Peripheral Map Register */
+#define	DMA11_CURR_X_COUNT		0xFFC01CF0	/* DMA Channel 11 Current X Count Register */
+#define	DMA11_CURR_Y_COUNT		0xFFC01CF8	/* DMA Channel 11 Current Y Count Register */
+
+#define	DMA12_NEXT_DESC_PTR		0xFFC01D00	/* DMA Channel 12 Next Descriptor Pointer Register */
+#define	DMA12_START_ADDR		0xFFC01D04	/* DMA Channel 12 Start	Address	Register */
+#define	DMA12_CONFIG			0xFFC01D08	/* DMA Channel 12 Configuration	Register */
+#define	DMA12_X_COUNT			0xFFC01D10	/* DMA Channel 12 X Count Register */
+#define	DMA12_X_MODIFY			0xFFC01D14	/* DMA Channel 12 X Modify Register */
+#define	DMA12_Y_COUNT			0xFFC01D18	/* DMA Channel 12 Y Count Register */
+#define	DMA12_Y_MODIFY			0xFFC01D1C	/* DMA Channel 12 Y Modify Register */
+#define	DMA12_CURR_DESC_PTR		0xFFC01D20	/* DMA Channel 12 Current Descriptor Pointer Register */
+#define	DMA12_CURR_ADDR			0xFFC01D24	/* DMA Channel 12 Current Address Register */
+#define	DMA12_IRQ_STATUS		0xFFC01D28	/* DMA Channel 12 Interrupt/Status Register */
+#define	DMA12_PERIPHERAL_MAP	0xFFC01D2C	/* DMA Channel 12 Peripheral Map Register */
+#define	DMA12_CURR_X_COUNT		0xFFC01D30	/* DMA Channel 12 Current X Count Register */
+#define	DMA12_CURR_Y_COUNT		0xFFC01D38	/* DMA Channel 12 Current Y Count Register */
+
+#define	DMA13_NEXT_DESC_PTR		0xFFC01D40	/* DMA Channel 13 Next Descriptor Pointer Register */
+#define	DMA13_START_ADDR		0xFFC01D44	/* DMA Channel 13 Start	Address	Register */
+#define	DMA13_CONFIG			0xFFC01D48	/* DMA Channel 13 Configuration	Register */
+#define	DMA13_X_COUNT			0xFFC01D50	/* DMA Channel 13 X Count Register */
+#define	DMA13_X_MODIFY			0xFFC01D54	/* DMA Channel 13 X Modify Register */
+#define	DMA13_Y_COUNT			0xFFC01D58	/* DMA Channel 13 Y Count Register */
+#define	DMA13_Y_MODIFY			0xFFC01D5C	/* DMA Channel 13 Y Modify Register */
+#define	DMA13_CURR_DESC_PTR		0xFFC01D60	/* DMA Channel 13 Current Descriptor Pointer Register */
+#define	DMA13_CURR_ADDR			0xFFC01D64	/* DMA Channel 13 Current Address Register */
+#define	DMA13_IRQ_STATUS		0xFFC01D68	/* DMA Channel 13 Interrupt/Status Register */
+#define	DMA13_PERIPHERAL_MAP	0xFFC01D6C	/* DMA Channel 13 Peripheral Map Register */
+#define	DMA13_CURR_X_COUNT		0xFFC01D70	/* DMA Channel 13 Current X Count Register */
+#define	DMA13_CURR_Y_COUNT		0xFFC01D78	/* DMA Channel 13 Current Y Count Register */
+
+#define	DMA14_NEXT_DESC_PTR		0xFFC01D80	/* DMA Channel 14 Next Descriptor Pointer Register */
+#define	DMA14_START_ADDR		0xFFC01D84	/* DMA Channel 14 Start	Address	Register */
+#define	DMA14_CONFIG			0xFFC01D88	/* DMA Channel 14 Configuration	Register */
+#define	DMA14_X_COUNT			0xFFC01D90	/* DMA Channel 14 X Count Register */
+#define	DMA14_X_MODIFY			0xFFC01D94	/* DMA Channel 14 X Modify Register */
+#define	DMA14_Y_COUNT			0xFFC01D98	/* DMA Channel 14 Y Count Register */
+#define	DMA14_Y_MODIFY			0xFFC01D9C	/* DMA Channel 14 Y Modify Register */
+#define	DMA14_CURR_DESC_PTR		0xFFC01DA0	/* DMA Channel 14 Current Descriptor Pointer Register */
+#define	DMA14_CURR_ADDR			0xFFC01DA4	/* DMA Channel 14 Current Address Register */
+#define	DMA14_IRQ_STATUS		0xFFC01DA8	/* DMA Channel 14 Interrupt/Status Register */
+#define	DMA14_PERIPHERAL_MAP	0xFFC01DAC	/* DMA Channel 14 Peripheral Map Register */
+#define	DMA14_CURR_X_COUNT		0xFFC01DB0	/* DMA Channel 14 Current X Count Register */
+#define	DMA14_CURR_Y_COUNT		0xFFC01DB8	/* DMA Channel 14 Current Y Count Register */
+
+#define	DMA15_NEXT_DESC_PTR		0xFFC01DC0	/* DMA Channel 15 Next Descriptor Pointer Register */
+#define	DMA15_START_ADDR		0xFFC01DC4	/* DMA Channel 15 Start	Address	Register */
+#define	DMA15_CONFIG			0xFFC01DC8	/* DMA Channel 15 Configuration	Register */
+#define	DMA15_X_COUNT			0xFFC01DD0	/* DMA Channel 15 X Count Register */
+#define	DMA15_X_MODIFY			0xFFC01DD4	/* DMA Channel 15 X Modify Register */
+#define	DMA15_Y_COUNT			0xFFC01DD8	/* DMA Channel 15 Y Count Register */
+#define	DMA15_Y_MODIFY			0xFFC01DDC	/* DMA Channel 15 Y Modify Register */
+#define	DMA15_CURR_DESC_PTR		0xFFC01DE0	/* DMA Channel 15 Current Descriptor Pointer Register */
+#define	DMA15_CURR_ADDR			0xFFC01DE4	/* DMA Channel 15 Current Address Register */
+#define	DMA15_IRQ_STATUS		0xFFC01DE8	/* DMA Channel 15 Interrupt/Status Register */
+#define	DMA15_PERIPHERAL_MAP	0xFFC01DEC	/* DMA Channel 15 Peripheral Map Register */
+#define	DMA15_CURR_X_COUNT		0xFFC01DF0	/* DMA Channel 15 Current X Count Register */
+#define	DMA15_CURR_Y_COUNT		0xFFC01DF8	/* DMA Channel 15 Current Y Count Register */
+
+#define	DMA16_NEXT_DESC_PTR		0xFFC01E00	/* DMA Channel 16 Next Descriptor Pointer Register */
+#define	DMA16_START_ADDR		0xFFC01E04	/* DMA Channel 16 Start	Address	Register */
+#define	DMA16_CONFIG			0xFFC01E08	/* DMA Channel 16 Configuration	Register */
+#define	DMA16_X_COUNT			0xFFC01E10	/* DMA Channel 16 X Count Register */
+#define	DMA16_X_MODIFY			0xFFC01E14	/* DMA Channel 16 X Modify Register */
+#define	DMA16_Y_COUNT			0xFFC01E18	/* DMA Channel 16 Y Count Register */
+#define	DMA16_Y_MODIFY			0xFFC01E1C	/* DMA Channel 16 Y Modify Register */
+#define	DMA16_CURR_DESC_PTR		0xFFC01E20	/* DMA Channel 16 Current Descriptor Pointer Register */
+#define	DMA16_CURR_ADDR			0xFFC01E24	/* DMA Channel 16 Current Address Register */
+#define	DMA16_IRQ_STATUS		0xFFC01E28	/* DMA Channel 16 Interrupt/Status Register */
+#define	DMA16_PERIPHERAL_MAP	0xFFC01E2C	/* DMA Channel 16 Peripheral Map Register */
+#define	DMA16_CURR_X_COUNT		0xFFC01E30	/* DMA Channel 16 Current X Count Register */
+#define	DMA16_CURR_Y_COUNT		0xFFC01E38	/* DMA Channel 16 Current Y Count Register */
+
+#define	DMA17_NEXT_DESC_PTR		0xFFC01E40	/* DMA Channel 17 Next Descriptor Pointer Register */
+#define	DMA17_START_ADDR		0xFFC01E44	/* DMA Channel 17 Start	Address	Register */
+#define	DMA17_CONFIG			0xFFC01E48	/* DMA Channel 17 Configuration	Register */
+#define	DMA17_X_COUNT			0xFFC01E50	/* DMA Channel 17 X Count Register */
+#define	DMA17_X_MODIFY			0xFFC01E54	/* DMA Channel 17 X Modify Register */
+#define	DMA17_Y_COUNT			0xFFC01E58	/* DMA Channel 17 Y Count Register */
+#define	DMA17_Y_MODIFY			0xFFC01E5C	/* DMA Channel 17 Y Modify Register */
+#define	DMA17_CURR_DESC_PTR		0xFFC01E60	/* DMA Channel 17 Current Descriptor Pointer Register */
+#define	DMA17_CURR_ADDR			0xFFC01E64	/* DMA Channel 17 Current Address Register */
+#define	DMA17_IRQ_STATUS		0xFFC01E68	/* DMA Channel 17 Interrupt/Status Register */
+#define	DMA17_PERIPHERAL_MAP	0xFFC01E6C	/* DMA Channel 17 Peripheral Map Register */
+#define	DMA17_CURR_X_COUNT		0xFFC01E70	/* DMA Channel 17 Current X Count Register */
+#define	DMA17_CURR_Y_COUNT		0xFFC01E78	/* DMA Channel 17 Current Y Count Register */
+
+#define	DMA18_NEXT_DESC_PTR		0xFFC01E80	/* DMA Channel 18 Next Descriptor Pointer Register */
+#define	DMA18_START_ADDR		0xFFC01E84	/* DMA Channel 18 Start	Address	Register */
+#define	DMA18_CONFIG			0xFFC01E88	/* DMA Channel 18 Configuration	Register */
+#define	DMA18_X_COUNT			0xFFC01E90	/* DMA Channel 18 X Count Register */
+#define	DMA18_X_MODIFY			0xFFC01E94	/* DMA Channel 18 X Modify Register */
+#define	DMA18_Y_COUNT			0xFFC01E98	/* DMA Channel 18 Y Count Register */
+#define	DMA18_Y_MODIFY			0xFFC01E9C	/* DMA Channel 18 Y Modify Register */
+#define	DMA18_CURR_DESC_PTR		0xFFC01EA0	/* DMA Channel 18 Current Descriptor Pointer Register */
+#define	DMA18_CURR_ADDR			0xFFC01EA4	/* DMA Channel 18 Current Address Register */
+#define	DMA18_IRQ_STATUS		0xFFC01EA8	/* DMA Channel 18 Interrupt/Status Register */
+#define	DMA18_PERIPHERAL_MAP	0xFFC01EAC	/* DMA Channel 18 Peripheral Map Register */
+#define	DMA18_CURR_X_COUNT		0xFFC01EB0	/* DMA Channel 18 Current X Count Register */
+#define	DMA18_CURR_Y_COUNT		0xFFC01EB8	/* DMA Channel 18 Current Y Count Register */
+
+#define	DMA19_NEXT_DESC_PTR		0xFFC01EC0	/* DMA Channel 19 Next Descriptor Pointer Register */
+#define	DMA19_START_ADDR		0xFFC01EC4	/* DMA Channel 19 Start	Address	Register */
+#define	DMA19_CONFIG			0xFFC01EC8	/* DMA Channel 19 Configuration	Register */
+#define	DMA19_X_COUNT			0xFFC01ED0	/* DMA Channel 19 X Count Register */
+#define	DMA19_X_MODIFY			0xFFC01ED4	/* DMA Channel 19 X Modify Register */
+#define	DMA19_Y_COUNT			0xFFC01ED8	/* DMA Channel 19 Y Count Register */
+#define	DMA19_Y_MODIFY			0xFFC01EDC	/* DMA Channel 19 Y Modify Register */
+#define	DMA19_CURR_DESC_PTR		0xFFC01EE0	/* DMA Channel 19 Current Descriptor Pointer Register */
+#define	DMA19_CURR_ADDR			0xFFC01EE4	/* DMA Channel 19 Current Address Register */
+#define	DMA19_IRQ_STATUS		0xFFC01EE8	/* DMA Channel 19 Interrupt/Status Register */
+#define	DMA19_PERIPHERAL_MAP	0xFFC01EEC	/* DMA Channel 19 Peripheral Map Register */
+#define	DMA19_CURR_X_COUNT		0xFFC01EF0	/* DMA Channel 19 Current X Count Register */
+#define	DMA19_CURR_Y_COUNT		0xFFC01EF8	/* DMA Channel 19 Current Y Count Register */
+
+#define	MDMA_D2_NEXT_DESC_PTR	0xFFC01F00	/* MemDMA1 Stream 0 Destination	Next Descriptor	Pointer	Register */
+#define	MDMA_D2_START_ADDR		0xFFC01F04	/* MemDMA1 Stream 0 Destination	Start Address Register */
+#define	MDMA_D2_CONFIG			0xFFC01F08	/* MemDMA1 Stream 0 Destination	Configuration Register */
+#define	MDMA_D2_X_COUNT		0xFFC01F10	/* MemDMA1 Stream 0 Destination	X Count	Register */
+#define	MDMA_D2_X_MODIFY		0xFFC01F14	/* MemDMA1 Stream 0 Destination	X Modify Register */
+#define	MDMA_D2_Y_COUNT		0xFFC01F18	/* MemDMA1 Stream 0 Destination	Y Count	Register */
+#define	MDMA_D2_Y_MODIFY		0xFFC01F1C	/* MemDMA1 Stream 0 Destination	Y Modify Register */
+#define	MDMA_D2_CURR_DESC_PTR	0xFFC01F20	/* MemDMA1 Stream 0 Destination	Current	Descriptor Pointer Register */
+#define	MDMA_D2_CURR_ADDR		0xFFC01F24	/* MemDMA1 Stream 0 Destination	Current	Address	Register */
+#define	MDMA_D2_IRQ_STATUS		0xFFC01F28	/* MemDMA1 Stream 0 Destination	Interrupt/Status Register */
+#define	MDMA_D2_PERIPHERAL_MAP	0xFFC01F2C	/* MemDMA1 Stream 0 Destination	Peripheral Map Register */
+#define	MDMA_D2_CURR_X_COUNT	0xFFC01F30	/* MemDMA1 Stream 0 Destination	Current	X Count	Register */
+#define	MDMA_D2_CURR_Y_COUNT	0xFFC01F38	/* MemDMA1 Stream 0 Destination	Current	Y Count	Register */
+
+#define	MDMA_S2_NEXT_DESC_PTR	0xFFC01F40	/* MemDMA1 Stream 0 Source Next	Descriptor Pointer Register */
+#define	MDMA_S2_START_ADDR		0xFFC01F44	/* MemDMA1 Stream 0 Source Start Address Register */
+#define	MDMA_S2_CONFIG			0xFFC01F48	/* MemDMA1 Stream 0 Source Configuration Register */
+#define	MDMA_S2_X_COUNT		0xFFC01F50	/* MemDMA1 Stream 0 Source X Count Register */
+#define	MDMA_S2_X_MODIFY		0xFFC01F54	/* MemDMA1 Stream 0 Source X Modify Register */
+#define	MDMA_S2_Y_COUNT		0xFFC01F58	/* MemDMA1 Stream 0 Source Y Count Register */
+#define	MDMA_S2_Y_MODIFY		0xFFC01F5C	/* MemDMA1 Stream 0 Source Y Modify Register */
+#define	MDMA_S2_CURR_DESC_PTR	0xFFC01F60	/* MemDMA1 Stream 0 Source Current Descriptor Pointer Register */
+#define	MDMA_S2_CURR_ADDR		0xFFC01F64	/* MemDMA1 Stream 0 Source Current Address Register */
+#define	MDMA_S2_IRQ_STATUS		0xFFC01F68	/* MemDMA1 Stream 0 Source Interrupt/Status Register */
+#define	MDMA_S2_PERIPHERAL_MAP	0xFFC01F6C	/* MemDMA1 Stream 0 Source Peripheral Map Register */
+#define	MDMA_S2_CURR_X_COUNT	0xFFC01F70	/* MemDMA1 Stream 0 Source Current X Count Register */
+#define	MDMA_S2_CURR_Y_COUNT	0xFFC01F78	/* MemDMA1 Stream 0 Source Current Y Count Register */
+
+#define	MDMA_D3_NEXT_DESC_PTR	0xFFC01F80	/* MemDMA1 Stream 1 Destination	Next Descriptor	Pointer	Register */
+#define	MDMA_D3_START_ADDR		0xFFC01F84	/* MemDMA1 Stream 1 Destination	Start Address Register */
+#define	MDMA_D3_CONFIG			0xFFC01F88	/* MemDMA1 Stream 1 Destination	Configuration Register */
+#define	MDMA_D3_X_COUNT		0xFFC01F90	/* MemDMA1 Stream 1 Destination	X Count	Register */
+#define	MDMA_D3_X_MODIFY		0xFFC01F94	/* MemDMA1 Stream 1 Destination	X Modify Register */
+#define	MDMA_D3_Y_COUNT		0xFFC01F98	/* MemDMA1 Stream 1 Destination	Y Count	Register */
+#define	MDMA_D3_Y_MODIFY		0xFFC01F9C	/* MemDMA1 Stream 1 Destination	Y Modify Register */
+#define	MDMA_D3_CURR_DESC_PTR	0xFFC01FA0	/* MemDMA1 Stream 1 Destination	Current	Descriptor Pointer Register */
+#define	MDMA_D3_CURR_ADDR		0xFFC01FA4	/* MemDMA1 Stream 1 Destination	Current	Address	Register */
+#define	MDMA_D3_IRQ_STATUS		0xFFC01FA8	/* MemDMA1 Stream 1 Destination	Interrupt/Status Register */
+#define	MDMA_D3_PERIPHERAL_MAP	0xFFC01FAC	/* MemDMA1 Stream 1 Destination	Peripheral Map Register */
+#define	MDMA_D3_CURR_X_COUNT	0xFFC01FB0	/* MemDMA1 Stream 1 Destination	Current	X Count	Register */
+#define	MDMA_D3_CURR_Y_COUNT	0xFFC01FB8	/* MemDMA1 Stream 1 Destination	Current	Y Count	Register */
+
+#define	MDMA_S3_NEXT_DESC_PTR	0xFFC01FC0	/* MemDMA1 Stream 1 Source Next	Descriptor Pointer Register */
+#define	MDMA_S3_START_ADDR		0xFFC01FC4	/* MemDMA1 Stream 1 Source Start Address Register */
+#define	MDMA_S3_CONFIG			0xFFC01FC8	/* MemDMA1 Stream 1 Source Configuration Register */
+#define	MDMA_S3_X_COUNT		0xFFC01FD0	/* MemDMA1 Stream 1 Source X Count Register */
+#define	MDMA_S3_X_MODIFY		0xFFC01FD4	/* MemDMA1 Stream 1 Source X Modify Register */
+#define	MDMA_S3_Y_COUNT		0xFFC01FD8	/* MemDMA1 Stream 1 Source Y Count Register */
+#define	MDMA_S3_Y_MODIFY		0xFFC01FDC	/* MemDMA1 Stream 1 Source Y Modify Register */
+#define	MDMA_S3_CURR_DESC_PTR	0xFFC01FE0	/* MemDMA1 Stream 1 Source Current Descriptor Pointer Register */
+#define	MDMA_S3_CURR_ADDR		0xFFC01FE4	/* MemDMA1 Stream 1 Source Current Address Register */
+#define	MDMA_S3_IRQ_STATUS		0xFFC01FE8	/* MemDMA1 Stream 1 Source Interrupt/Status Register */
+#define	MDMA_S3_PERIPHERAL_MAP	0xFFC01FEC	/* MemDMA1 Stream 1 Source Peripheral Map Register */
+#define	MDMA_S3_CURR_X_COUNT	0xFFC01FF0	/* MemDMA1 Stream 1 Source Current X Count Register */
+#define	MDMA_S3_CURR_Y_COUNT	0xFFC01FF8	/* MemDMA1 Stream 1 Source Current Y Count Register */
+
+
+/* UART1 Controller		(0xFFC02000 - 0xFFC020FF)	 */
+#define	UART1_THR			0xFFC02000	/* Transmit Holding register */
+#define	UART1_RBR			0xFFC02000	/* Receive Buffer register */
+#define	UART1_DLL			0xFFC02000	/* Divisor Latch (Low-Byte) */
+#define	UART1_IER			0xFFC02004	/* Interrupt Enable Register */
+#define	UART1_DLH			0xFFC02004	/* Divisor Latch (High-Byte) */
+#define	UART1_IIR			0xFFC02008	/* Interrupt Identification Register */
+#define	UART1_LCR			0xFFC0200C	/* Line	Control	Register */
+#define	UART1_MCR			0xFFC02010	/* Modem Control Register */
+#define	UART1_LSR			0xFFC02014	/* Line	Status Register */
+#define	UART1_SCR			0xFFC0201C	/* SCR Scratch Register */
+#define	UART1_GCTL			0xFFC02024	/* Global Control Register */
+
+
+/* UART2 Controller		(0xFFC02100 - 0xFFC021FF)	 */
+#define	UART2_THR			0xFFC02100	/* Transmit Holding register */
+#define	UART2_RBR			0xFFC02100	/* Receive Buffer register */
+#define	UART2_DLL			0xFFC02100	/* Divisor Latch (Low-Byte) */
+#define	UART2_IER			0xFFC02104	/* Interrupt Enable Register */
+#define	UART2_DLH			0xFFC02104	/* Divisor Latch (High-Byte) */
+#define	UART2_IIR			0xFFC02108	/* Interrupt Identification Register */
+#define	UART2_LCR			0xFFC0210C	/* Line	Control	Register */
+#define	UART2_MCR			0xFFC02110	/* Modem Control Register */
+#define	UART2_LSR			0xFFC02114	/* Line	Status Register */
+#define	UART2_SCR			0xFFC0211C	/* SCR Scratch Register */
+#define	UART2_GCTL			0xFFC02124	/* Global Control Register */
+
+
+/* Two-Wire Interface 1	(0xFFC02200 - 0xFFC022FF)			 */
+#define	TWI1_CLKDIV			0xFFC02200	/* Serial Clock	Divider	Register */
+#define	TWI1_CONTROL		0xFFC02204	/* TWI1	Master Internal	Time Reference Register */
+#define	TWI1_SLAVE_CTL		0xFFC02208	/* Slave Mode Control Register */
+#define	TWI1_SLAVE_STAT		0xFFC0220C	/* Slave Mode Status Register */
+#define	TWI1_SLAVE_ADDR		0xFFC02210	/* Slave Mode Address Register */
+#define	TWI1_MASTER_CTL	0xFFC02214	/* Master Mode Control Register */
+#define	TWI1_MASTER_STAT	0xFFC02218	/* Master Mode Status Register */
+#define	TWI1_MASTER_ADDR	0xFFC0221C	/* Master Mode Address Register */
+#define	TWI1_INT_STAT		0xFFC02220	/* TWI1	Master Interrupt Register */
+#define	TWI1_INT_MASK		0xFFC02224	/* TWI1	Master Interrupt Mask Register */
+#define	TWI1_FIFO_CTL		0xFFC02228	/* FIFO	Control	Register */
+#define	TWI1_FIFO_STAT		0xFFC0222C	/* FIFO	Status Register */
+#define	TWI1_XMT_DATA8		0xFFC02280	/* FIFO	Transmit Data Single Byte Register */
+#define	TWI1_XMT_DATA16		0xFFC02284	/* FIFO	Transmit Data Double Byte Register */
+#define	TWI1_RCV_DATA8		0xFFC02288	/* FIFO	Receive	Data Single Byte Register */
+#define	TWI1_RCV_DATA16		0xFFC0228C	/* FIFO	Receive	Data Double Byte Register */
+#define TWI1_REGBASE		TWI1_CLKDIV
+
+
+/* the following are for backwards compatibility */
+#define	TWI1_PRESCALE	  TWI1_CONTROL
+#define	TWI1_INT_SRC	  TWI1_INT_STAT
+#define	TWI1_INT_ENABLE	  TWI1_INT_MASK
+
+
+/* SPI1	Controller		(0xFFC02300 - 0xFFC023FF)	 */
+#define	SPI1_CTL			0xFFC02300  /* SPI1 Control Register */
+#define	SPI1_FLG			0xFFC02304  /* SPI1 Flag register */
+#define	SPI1_STAT			0xFFC02308  /* SPI1 Status register */
+#define	SPI1_TDBR			0xFFC0230C  /* SPI1 Transmit Data Buffer Register */
+#define	SPI1_RDBR			0xFFC02310  /* SPI1 Receive Data Buffer	Register */
+#define	SPI1_BAUD			0xFFC02314  /* SPI1 Baud rate Register */
+#define	SPI1_SHADOW			0xFFC02318  /* SPI1_RDBR Shadow	Register */
+#define SPI1_REGBASE			SPI1_CTL
+
+/* SPI2	Controller		(0xFFC02400 - 0xFFC024FF)	 */
+#define	SPI2_CTL			0xFFC02400  /* SPI2 Control Register */
+#define	SPI2_FLG			0xFFC02404  /* SPI2 Flag register */
+#define	SPI2_STAT			0xFFC02408  /* SPI2 Status register */
+#define	SPI2_TDBR			0xFFC0240C  /* SPI2 Transmit Data Buffer Register */
+#define	SPI2_RDBR			0xFFC02410  /* SPI2 Receive Data Buffer	Register */
+#define	SPI2_BAUD			0xFFC02414  /* SPI2 Baud rate Register */
+#define	SPI2_SHADOW			0xFFC02418  /* SPI2_RDBR Shadow	Register */
+#define SPI2_REGBASE			SPI2_CTL
+
+/* SPORT2 Controller		(0xFFC02500 - 0xFFC025FF)			 */
+#define	SPORT2_TCR1			0xFFC02500	/* SPORT2 Transmit Configuration 1 Register */
+#define	SPORT2_TCR2			0xFFC02504	/* SPORT2 Transmit Configuration 2 Register */
+#define	SPORT2_TCLKDIV		0xFFC02508	/* SPORT2 Transmit Clock Divider */
+#define	SPORT2_TFSDIV		0xFFC0250C	/* SPORT2 Transmit Frame Sync Divider */
+#define	SPORT2_TX			0xFFC02510	/* SPORT2 TX Data Register */
+#define	SPORT2_RX			0xFFC02518	/* SPORT2 RX Data Register */
+#define	SPORT2_RCR1			0xFFC02520	/* SPORT2 Transmit Configuration 1 Register */
+#define	SPORT2_RCR2			0xFFC02524	/* SPORT2 Transmit Configuration 2 Register */
+#define	SPORT2_RCLKDIV		0xFFC02528	/* SPORT2 Receive Clock	Divider */
+#define	SPORT2_RFSDIV		0xFFC0252C	/* SPORT2 Receive Frame	Sync Divider */
+#define	SPORT2_STAT			0xFFC02530	/* SPORT2 Status Register */
+#define	SPORT2_CHNL			0xFFC02534	/* SPORT2 Current Channel Register */
+#define	SPORT2_MCMC1		0xFFC02538	/* SPORT2 Multi-Channel	Configuration Register 1 */
+#define	SPORT2_MCMC2		0xFFC0253C	/* SPORT2 Multi-Channel	Configuration Register 2 */
+#define	SPORT2_MTCS0		0xFFC02540	/* SPORT2 Multi-Channel	Transmit Select	Register 0 */
+#define	SPORT2_MTCS1		0xFFC02544	/* SPORT2 Multi-Channel	Transmit Select	Register 1 */
+#define	SPORT2_MTCS2		0xFFC02548	/* SPORT2 Multi-Channel	Transmit Select	Register 2 */
+#define	SPORT2_MTCS3		0xFFC0254C	/* SPORT2 Multi-Channel	Transmit Select	Register 3 */
+#define	SPORT2_MRCS0		0xFFC02550	/* SPORT2 Multi-Channel	Receive	Select Register	0 */
+#define	SPORT2_MRCS1		0xFFC02554	/* SPORT2 Multi-Channel	Receive	Select Register	1 */
+#define	SPORT2_MRCS2		0xFFC02558	/* SPORT2 Multi-Channel	Receive	Select Register	2 */
+#define	SPORT2_MRCS3		0xFFC0255C	/* SPORT2 Multi-Channel	Receive	Select Register	3 */
+
+
+/* SPORT3 Controller		(0xFFC02600 - 0xFFC026FF)			 */
+#define	SPORT3_TCR1			0xFFC02600	/* SPORT3 Transmit Configuration 1 Register */
+#define	SPORT3_TCR2			0xFFC02604	/* SPORT3 Transmit Configuration 2 Register */
+#define	SPORT3_TCLKDIV		0xFFC02608	/* SPORT3 Transmit Clock Divider */
+#define	SPORT3_TFSDIV		0xFFC0260C	/* SPORT3 Transmit Frame Sync Divider */
+#define	SPORT3_TX			0xFFC02610	/* SPORT3 TX Data Register */
+#define	SPORT3_RX			0xFFC02618	/* SPORT3 RX Data Register */
+#define	SPORT3_RCR1			0xFFC02620	/* SPORT3 Transmit Configuration 1 Register */
+#define	SPORT3_RCR2			0xFFC02624	/* SPORT3 Transmit Configuration 2 Register */
+#define	SPORT3_RCLKDIV		0xFFC02628	/* SPORT3 Receive Clock	Divider */
+#define	SPORT3_RFSDIV		0xFFC0262C	/* SPORT3 Receive Frame	Sync Divider */
+#define	SPORT3_STAT			0xFFC02630	/* SPORT3 Status Register */
+#define	SPORT3_CHNL			0xFFC02634	/* SPORT3 Current Channel Register */
+#define	SPORT3_MCMC1		0xFFC02638	/* SPORT3 Multi-Channel	Configuration Register 1 */
+#define	SPORT3_MCMC2		0xFFC0263C	/* SPORT3 Multi-Channel	Configuration Register 2 */
+#define	SPORT3_MTCS0		0xFFC02640	/* SPORT3 Multi-Channel	Transmit Select	Register 0 */
+#define	SPORT3_MTCS1		0xFFC02644	/* SPORT3 Multi-Channel	Transmit Select	Register 1 */
+#define	SPORT3_MTCS2		0xFFC02648	/* SPORT3 Multi-Channel	Transmit Select	Register 2 */
+#define	SPORT3_MTCS3		0xFFC0264C	/* SPORT3 Multi-Channel	Transmit Select	Register 3 */
+#define	SPORT3_MRCS0		0xFFC02650	/* SPORT3 Multi-Channel	Receive	Select Register	0 */
+#define	SPORT3_MRCS1		0xFFC02654	/* SPORT3 Multi-Channel	Receive	Select Register	1 */
+#define	SPORT3_MRCS2		0xFFC02658	/* SPORT3 Multi-Channel	Receive	Select Register	2 */
+#define	SPORT3_MRCS3		0xFFC0265C	/* SPORT3 Multi-Channel	Receive	Select Register	3 */
+
+
+/* CAN Controller		(0xFFC02A00 - 0xFFC02FFF)				 */
+/* For Mailboxes 0-15											 */
+#define	CAN_MC1				0xFFC02A00	/* Mailbox config reg 1	 */
+#define	CAN_MD1				0xFFC02A04	/* Mailbox direction reg 1 */
+#define	CAN_TRS1			0xFFC02A08	/* Transmit Request Set	reg 1 */
+#define	CAN_TRR1			0xFFC02A0C	/* Transmit Request Reset reg 1 */
+#define	CAN_TA1				0xFFC02A10	/* Transmit Acknowledge	reg 1 */
+#define	CAN_AA1				0xFFC02A14	/* Transmit Abort Acknowledge reg 1 */
+#define	CAN_RMP1			0xFFC02A18	/* Receive Message Pending reg 1 */
+#define	CAN_RML1			0xFFC02A1C	/* Receive Message Lost	reg 1 */
+#define	CAN_MBTIF1			0xFFC02A20	/* Mailbox Transmit Interrupt Flag reg 1 */
+#define	CAN_MBRIF1			0xFFC02A24	/* Mailbox Receive  Interrupt Flag reg 1 */
+#define	CAN_MBIM1			0xFFC02A28	/* Mailbox Interrupt Mask reg 1 */
+#define	CAN_RFH1			0xFFC02A2C	/* Remote Frame	Handling reg 1 */
+#define	CAN_OPSS1			0xFFC02A30	/* Overwrite Protection	Single Shot Xmission reg 1 */
+
+/* For Mailboxes 16-31											 */
+#define	CAN_MC2				0xFFC02A40	/* Mailbox config reg 2	 */
+#define	CAN_MD2				0xFFC02A44	/* Mailbox direction reg 2 */
+#define	CAN_TRS2			0xFFC02A48	/* Transmit Request Set	reg 2 */
+#define	CAN_TRR2			0xFFC02A4C	/* Transmit Request Reset reg 2 */
+#define	CAN_TA2				0xFFC02A50	/* Transmit Acknowledge	reg 2 */
+#define	CAN_AA2				0xFFC02A54	/* Transmit Abort Acknowledge reg 2 */
+#define	CAN_RMP2			0xFFC02A58	/* Receive Message Pending reg 2 */
+#define	CAN_RML2			0xFFC02A5C	/* Receive Message Lost	reg 2 */
+#define	CAN_MBTIF2			0xFFC02A60	/* Mailbox Transmit Interrupt Flag reg 2 */
+#define	CAN_MBRIF2			0xFFC02A64	/* Mailbox Receive  Interrupt Flag reg 2 */
+#define	CAN_MBIM2			0xFFC02A68	/* Mailbox Interrupt Mask reg 2 */
+#define	CAN_RFH2			0xFFC02A6C	/* Remote Frame	Handling reg 2 */
+#define	CAN_OPSS2			0xFFC02A70	/* Overwrite Protection	Single Shot Xmission reg 2 */
+
+#define	CAN_CLOCK			0xFFC02A80	/* Bit Timing Configuration register 0 */
+#define	CAN_TIMING			0xFFC02A84	/* Bit Timing Configuration register 1 */
+
+#define	CAN_DEBUG			0xFFC02A88	/* Debug Register		 */
+/* the following is for	backwards compatibility */
+#define	CAN_CNF		 CAN_DEBUG
+
+#define	CAN_STATUS			0xFFC02A8C	/* Global Status Register */
+#define	CAN_CEC				0xFFC02A90	/* Error Counter Register */
+#define	CAN_GIS				0xFFC02A94	/* Global Interrupt Status Register */
+#define	CAN_GIM				0xFFC02A98	/* Global Interrupt Mask Register */
+#define	CAN_GIF				0xFFC02A9C	/* Global Interrupt Flag Register */
+#define	CAN_CONTROL			0xFFC02AA0	/* Master Control Register */
+#define	CAN_INTR			0xFFC02AA4	/* Interrupt Pending Register */
+#define	CAN_MBTD			0xFFC02AAC	/* Mailbox Temporary Disable Feature */
+#define	CAN_EWR				0xFFC02AB0	/* Programmable	Warning	Level */
+#define	CAN_ESR				0xFFC02AB4	/* Error Status	Register */
+#define	CAN_UCCNT			0xFFC02AC4	/* Universal Counter	 */
+#define	CAN_UCRC			0xFFC02AC8	/* Universal Counter Reload/Capture Register */
+#define	CAN_UCCNF			0xFFC02ACC	/* Universal Counter Configuration Register */
+
+/* Mailbox Acceptance Masks					 */
+#define	CAN_AM00L			0xFFC02B00	/* Mailbox 0 Low Acceptance Mask */
+#define	CAN_AM00H			0xFFC02B04	/* Mailbox 0 High Acceptance Mask */
+#define	CAN_AM01L			0xFFC02B08	/* Mailbox 1 Low Acceptance Mask */
+#define	CAN_AM01H			0xFFC02B0C	/* Mailbox 1 High Acceptance Mask */
+#define	CAN_AM02L			0xFFC02B10	/* Mailbox 2 Low Acceptance Mask */
+#define	CAN_AM02H			0xFFC02B14	/* Mailbox 2 High Acceptance Mask */
+#define	CAN_AM03L			0xFFC02B18	/* Mailbox 3 Low Acceptance Mask */
+#define	CAN_AM03H			0xFFC02B1C	/* Mailbox 3 High Acceptance Mask */
+#define	CAN_AM04L			0xFFC02B20	/* Mailbox 4 Low Acceptance Mask */
+#define	CAN_AM04H			0xFFC02B24	/* Mailbox 4 High Acceptance Mask */
+#define	CAN_AM05L			0xFFC02B28	/* Mailbox 5 Low Acceptance Mask */
+#define	CAN_AM05H			0xFFC02B2C	/* Mailbox 5 High Acceptance Mask */
+#define	CAN_AM06L			0xFFC02B30	/* Mailbox 6 Low Acceptance Mask */
+#define	CAN_AM06H			0xFFC02B34	/* Mailbox 6 High Acceptance Mask */
+#define	CAN_AM07L			0xFFC02B38	/* Mailbox 7 Low Acceptance Mask */
+#define	CAN_AM07H			0xFFC02B3C	/* Mailbox 7 High Acceptance Mask */
+#define	CAN_AM08L			0xFFC02B40	/* Mailbox 8 Low Acceptance Mask */
+#define	CAN_AM08H			0xFFC02B44	/* Mailbox 8 High Acceptance Mask */
+#define	CAN_AM09L			0xFFC02B48	/* Mailbox 9 Low Acceptance Mask */
+#define	CAN_AM09H			0xFFC02B4C	/* Mailbox 9 High Acceptance Mask */
+#define	CAN_AM10L			0xFFC02B50	/* Mailbox 10 Low Acceptance Mask */
+#define	CAN_AM10H			0xFFC02B54	/* Mailbox 10 High Acceptance Mask */
+#define	CAN_AM11L			0xFFC02B58	/* Mailbox 11 Low Acceptance Mask */
+#define	CAN_AM11H			0xFFC02B5C	/* Mailbox 11 High Acceptance Mask */
+#define	CAN_AM12L			0xFFC02B60	/* Mailbox 12 Low Acceptance Mask */
+#define	CAN_AM12H			0xFFC02B64	/* Mailbox 12 High Acceptance Mask */
+#define	CAN_AM13L			0xFFC02B68	/* Mailbox 13 Low Acceptance Mask */
+#define	CAN_AM13H			0xFFC02B6C	/* Mailbox 13 High Acceptance Mask */
+#define	CAN_AM14L			0xFFC02B70	/* Mailbox 14 Low Acceptance Mask */
+#define	CAN_AM14H			0xFFC02B74	/* Mailbox 14 High Acceptance Mask */
+#define	CAN_AM15L			0xFFC02B78	/* Mailbox 15 Low Acceptance Mask */
+#define	CAN_AM15H			0xFFC02B7C	/* Mailbox 15 High Acceptance Mask */
+
+#define	CAN_AM16L			0xFFC02B80	/* Mailbox 16 Low Acceptance Mask */
+#define	CAN_AM16H			0xFFC02B84	/* Mailbox 16 High Acceptance Mask */
+#define	CAN_AM17L			0xFFC02B88	/* Mailbox 17 Low Acceptance Mask */
+#define	CAN_AM17H			0xFFC02B8C	/* Mailbox 17 High Acceptance Mask */
+#define	CAN_AM18L			0xFFC02B90	/* Mailbox 18 Low Acceptance Mask */
+#define	CAN_AM18H			0xFFC02B94	/* Mailbox 18 High Acceptance Mask */
+#define	CAN_AM19L			0xFFC02B98	/* Mailbox 19 Low Acceptance Mask */
+#define	CAN_AM19H			0xFFC02B9C	/* Mailbox 19 High Acceptance Mask */
+#define	CAN_AM20L			0xFFC02BA0	/* Mailbox 20 Low Acceptance Mask */
+#define	CAN_AM20H			0xFFC02BA4	/* Mailbox 20 High Acceptance Mask */
+#define	CAN_AM21L			0xFFC02BA8	/* Mailbox 21 Low Acceptance Mask */
+#define	CAN_AM21H			0xFFC02BAC	/* Mailbox 21 High Acceptance Mask */
+#define	CAN_AM22L			0xFFC02BB0	/* Mailbox 22 Low Acceptance Mask */
+#define	CAN_AM22H			0xFFC02BB4	/* Mailbox 22 High Acceptance Mask */
+#define	CAN_AM23L			0xFFC02BB8	/* Mailbox 23 Low Acceptance Mask */
+#define	CAN_AM23H			0xFFC02BBC	/* Mailbox 23 High Acceptance Mask */
+#define	CAN_AM24L			0xFFC02BC0	/* Mailbox 24 Low Acceptance Mask */
+#define	CAN_AM24H			0xFFC02BC4	/* Mailbox 24 High Acceptance Mask */
+#define	CAN_AM25L			0xFFC02BC8	/* Mailbox 25 Low Acceptance Mask */
+#define	CAN_AM25H			0xFFC02BCC	/* Mailbox 25 High Acceptance Mask */
+#define	CAN_AM26L			0xFFC02BD0	/* Mailbox 26 Low Acceptance Mask */
+#define	CAN_AM26H			0xFFC02BD4	/* Mailbox 26 High Acceptance Mask */
+#define	CAN_AM27L			0xFFC02BD8	/* Mailbox 27 Low Acceptance Mask */
+#define	CAN_AM27H			0xFFC02BDC	/* Mailbox 27 High Acceptance Mask */
+#define	CAN_AM28L			0xFFC02BE0	/* Mailbox 28 Low Acceptance Mask */
+#define	CAN_AM28H			0xFFC02BE4	/* Mailbox 28 High Acceptance Mask */
+#define	CAN_AM29L			0xFFC02BE8	/* Mailbox 29 Low Acceptance Mask */
+#define	CAN_AM29H			0xFFC02BEC	/* Mailbox 29 High Acceptance Mask */
+#define	CAN_AM30L			0xFFC02BF0	/* Mailbox 30 Low Acceptance Mask */
+#define	CAN_AM30H			0xFFC02BF4	/* Mailbox 30 High Acceptance Mask */
+#define	CAN_AM31L			0xFFC02BF8	/* Mailbox 31 Low Acceptance Mask */
+#define	CAN_AM31H			0xFFC02BFC	/* Mailbox 31 High Acceptance Mask */
+
+/* CAN Acceptance Mask Macros */
+#define	CAN_AM_L(x)			(CAN_AM00L+((x)*0x8))
+#define	CAN_AM_H(x)			(CAN_AM00H+((x)*0x8))
+
+/* Mailbox Registers									 */
+#define	CAN_MB00_DATA0		0xFFC02C00	/* Mailbox 0 Data Word 0 [15:0]	Register */
+#define	CAN_MB00_DATA1		0xFFC02C04	/* Mailbox 0 Data Word 1 [31:16] Register */
+#define	CAN_MB00_DATA2		0xFFC02C08	/* Mailbox 0 Data Word 2 [47:32] Register */
+#define	CAN_MB00_DATA3		0xFFC02C0C	/* Mailbox 0 Data Word 3 [63:48] Register */
+#define	CAN_MB00_LENGTH		0xFFC02C10	/* Mailbox 0 Data Length Code Register */
+#define	CAN_MB00_TIMESTAMP	0xFFC02C14	/* Mailbox 0 Time Stamp	Value Register */
+#define	CAN_MB00_ID0		0xFFC02C18	/* Mailbox 0 Identifier	Low Register */
+#define	CAN_MB00_ID1		0xFFC02C1C	/* Mailbox 0 Identifier	High Register */
+
+#define	CAN_MB01_DATA0		0xFFC02C20	/* Mailbox 1 Data Word 0 [15:0]	Register */
+#define	CAN_MB01_DATA1		0xFFC02C24	/* Mailbox 1 Data Word 1 [31:16] Register */
+#define	CAN_MB01_DATA2		0xFFC02C28	/* Mailbox 1 Data Word 2 [47:32] Register */
+#define	CAN_MB01_DATA3		0xFFC02C2C	/* Mailbox 1 Data Word 3 [63:48] Register */
+#define	CAN_MB01_LENGTH		0xFFC02C30	/* Mailbox 1 Data Length Code Register */
+#define	CAN_MB01_TIMESTAMP	0xFFC02C34	/* Mailbox 1 Time Stamp	Value Register */
+#define	CAN_MB01_ID0		0xFFC02C38	/* Mailbox 1 Identifier	Low Register */
+#define	CAN_MB01_ID1		0xFFC02C3C	/* Mailbox 1 Identifier	High Register */
+
+#define	CAN_MB02_DATA0		0xFFC02C40	/* Mailbox 2 Data Word 0 [15:0]	Register */
+#define	CAN_MB02_DATA1		0xFFC02C44	/* Mailbox 2 Data Word 1 [31:16] Register */
+#define	CAN_MB02_DATA2		0xFFC02C48	/* Mailbox 2 Data Word 2 [47:32] Register */
+#define	CAN_MB02_DATA3		0xFFC02C4C	/* Mailbox 2 Data Word 3 [63:48] Register */
+#define	CAN_MB02_LENGTH		0xFFC02C50	/* Mailbox 2 Data Length Code Register */
+#define	CAN_MB02_TIMESTAMP	0xFFC02C54	/* Mailbox 2 Time Stamp	Value Register */
+#define	CAN_MB02_ID0		0xFFC02C58	/* Mailbox 2 Identifier	Low Register */
+#define	CAN_MB02_ID1		0xFFC02C5C	/* Mailbox 2 Identifier	High Register */
+
+#define	CAN_MB03_DATA0		0xFFC02C60	/* Mailbox 3 Data Word 0 [15:0]	Register */
+#define	CAN_MB03_DATA1		0xFFC02C64	/* Mailbox 3 Data Word 1 [31:16] Register */
+#define	CAN_MB03_DATA2		0xFFC02C68	/* Mailbox 3 Data Word 2 [47:32] Register */
+#define	CAN_MB03_DATA3		0xFFC02C6C	/* Mailbox 3 Data Word 3 [63:48] Register */
+#define	CAN_MB03_LENGTH		0xFFC02C70	/* Mailbox 3 Data Length Code Register */
+#define	CAN_MB03_TIMESTAMP	0xFFC02C74	/* Mailbox 3 Time Stamp	Value Register */
+#define	CAN_MB03_ID0		0xFFC02C78	/* Mailbox 3 Identifier	Low Register */
+#define	CAN_MB03_ID1		0xFFC02C7C	/* Mailbox 3 Identifier	High Register */
+
+#define	CAN_MB04_DATA0		0xFFC02C80	/* Mailbox 4 Data Word 0 [15:0]	Register */
+#define	CAN_MB04_DATA1		0xFFC02C84	/* Mailbox 4 Data Word 1 [31:16] Register */
+#define	CAN_MB04_DATA2		0xFFC02C88	/* Mailbox 4 Data Word 2 [47:32] Register */
+#define	CAN_MB04_DATA3		0xFFC02C8C	/* Mailbox 4 Data Word 3 [63:48] Register */
+#define	CAN_MB04_LENGTH		0xFFC02C90	/* Mailbox 4 Data Length Code Register */
+#define	CAN_MB04_TIMESTAMP	0xFFC02C94	/* Mailbox 4 Time Stamp	Value Register */
+#define	CAN_MB04_ID0		0xFFC02C98	/* Mailbox 4 Identifier	Low Register */
+#define	CAN_MB04_ID1		0xFFC02C9C	/* Mailbox 4 Identifier	High Register */
+
+#define	CAN_MB05_DATA0		0xFFC02CA0	/* Mailbox 5 Data Word 0 [15:0]	Register */
+#define	CAN_MB05_DATA1		0xFFC02CA4	/* Mailbox 5 Data Word 1 [31:16] Register */
+#define	CAN_MB05_DATA2		0xFFC02CA8	/* Mailbox 5 Data Word 2 [47:32] Register */
+#define	CAN_MB05_DATA3		0xFFC02CAC	/* Mailbox 5 Data Word 3 [63:48] Register */
+#define	CAN_MB05_LENGTH		0xFFC02CB0	/* Mailbox 5 Data Length Code Register */
+#define	CAN_MB05_TIMESTAMP	0xFFC02CB4	/* Mailbox 5 Time Stamp	Value Register */
+#define	CAN_MB05_ID0		0xFFC02CB8	/* Mailbox 5 Identifier	Low Register */
+#define	CAN_MB05_ID1		0xFFC02CBC	/* Mailbox 5 Identifier	High Register */
+
+#define	CAN_MB06_DATA0		0xFFC02CC0	/* Mailbox 6 Data Word 0 [15:0]	Register */
+#define	CAN_MB06_DATA1		0xFFC02CC4	/* Mailbox 6 Data Word 1 [31:16] Register */
+#define	CAN_MB06_DATA2		0xFFC02CC8	/* Mailbox 6 Data Word 2 [47:32] Register */
+#define	CAN_MB06_DATA3		0xFFC02CCC	/* Mailbox 6 Data Word 3 [63:48] Register */
+#define	CAN_MB06_LENGTH		0xFFC02CD0	/* Mailbox 6 Data Length Code Register */
+#define	CAN_MB06_TIMESTAMP	0xFFC02CD4	/* Mailbox 6 Time Stamp	Value Register */
+#define	CAN_MB06_ID0		0xFFC02CD8	/* Mailbox 6 Identifier	Low Register */
+#define	CAN_MB06_ID1		0xFFC02CDC	/* Mailbox 6 Identifier	High Register */
+
+#define	CAN_MB07_DATA0		0xFFC02CE0	/* Mailbox 7 Data Word 0 [15:0]	Register */
+#define	CAN_MB07_DATA1		0xFFC02CE4	/* Mailbox 7 Data Word 1 [31:16] Register */
+#define	CAN_MB07_DATA2		0xFFC02CE8	/* Mailbox 7 Data Word 2 [47:32] Register */
+#define	CAN_MB07_DATA3		0xFFC02CEC	/* Mailbox 7 Data Word 3 [63:48] Register */
+#define	CAN_MB07_LENGTH		0xFFC02CF0	/* Mailbox 7 Data Length Code Register */
+#define	CAN_MB07_TIMESTAMP	0xFFC02CF4	/* Mailbox 7 Time Stamp	Value Register */
+#define	CAN_MB07_ID0		0xFFC02CF8	/* Mailbox 7 Identifier	Low Register */
+#define	CAN_MB07_ID1		0xFFC02CFC	/* Mailbox 7 Identifier	High Register */
+
+#define	CAN_MB08_DATA0		0xFFC02D00	/* Mailbox 8 Data Word 0 [15:0]	Register */
+#define	CAN_MB08_DATA1		0xFFC02D04	/* Mailbox 8 Data Word 1 [31:16] Register */
+#define	CAN_MB08_DATA2		0xFFC02D08	/* Mailbox 8 Data Word 2 [47:32] Register */
+#define	CAN_MB08_DATA3		0xFFC02D0C	/* Mailbox 8 Data Word 3 [63:48] Register */
+#define	CAN_MB08_LENGTH		0xFFC02D10	/* Mailbox 8 Data Length Code Register */
+#define	CAN_MB08_TIMESTAMP	0xFFC02D14	/* Mailbox 8 Time Stamp	Value Register */
+#define	CAN_MB08_ID0		0xFFC02D18	/* Mailbox 8 Identifier	Low Register */
+#define	CAN_MB08_ID1		0xFFC02D1C	/* Mailbox 8 Identifier	High Register */
+
+#define	CAN_MB09_DATA0		0xFFC02D20	/* Mailbox 9 Data Word 0 [15:0]	Register */
+#define	CAN_MB09_DATA1		0xFFC02D24	/* Mailbox 9 Data Word 1 [31:16] Register */
+#define	CAN_MB09_DATA2		0xFFC02D28	/* Mailbox 9 Data Word 2 [47:32] Register */
+#define	CAN_MB09_DATA3		0xFFC02D2C	/* Mailbox 9 Data Word 3 [63:48] Register */
+#define	CAN_MB09_LENGTH		0xFFC02D30	/* Mailbox 9 Data Length Code Register */
+#define	CAN_MB09_TIMESTAMP	0xFFC02D34	/* Mailbox 9 Time Stamp	Value Register */
+#define	CAN_MB09_ID0		0xFFC02D38	/* Mailbox 9 Identifier	Low Register */
+#define	CAN_MB09_ID1		0xFFC02D3C	/* Mailbox 9 Identifier	High Register */
+
+#define	CAN_MB10_DATA0		0xFFC02D40	/* Mailbox 10 Data Word	0 [15:0] Register */
+#define	CAN_MB10_DATA1		0xFFC02D44	/* Mailbox 10 Data Word	1 [31:16] Register */
+#define	CAN_MB10_DATA2		0xFFC02D48	/* Mailbox 10 Data Word	2 [47:32] Register */
+#define	CAN_MB10_DATA3		0xFFC02D4C	/* Mailbox 10 Data Word	3 [63:48] Register */
+#define	CAN_MB10_LENGTH		0xFFC02D50	/* Mailbox 10 Data Length Code Register */
+#define	CAN_MB10_TIMESTAMP	0xFFC02D54	/* Mailbox 10 Time Stamp Value Register */
+#define	CAN_MB10_ID0		0xFFC02D58	/* Mailbox 10 Identifier Low Register */
+#define	CAN_MB10_ID1		0xFFC02D5C	/* Mailbox 10 Identifier High Register */
+
+#define	CAN_MB11_DATA0		0xFFC02D60	/* Mailbox 11 Data Word	0 [15:0] Register */
+#define	CAN_MB11_DATA1		0xFFC02D64	/* Mailbox 11 Data Word	1 [31:16] Register */
+#define	CAN_MB11_DATA2		0xFFC02D68	/* Mailbox 11 Data Word	2 [47:32] Register */
+#define	CAN_MB11_DATA3		0xFFC02D6C	/* Mailbox 11 Data Word	3 [63:48] Register */
+#define	CAN_MB11_LENGTH		0xFFC02D70	/* Mailbox 11 Data Length Code Register */
+#define	CAN_MB11_TIMESTAMP	0xFFC02D74	/* Mailbox 11 Time Stamp Value Register */
+#define	CAN_MB11_ID0		0xFFC02D78	/* Mailbox 11 Identifier Low Register */
+#define	CAN_MB11_ID1		0xFFC02D7C	/* Mailbox 11 Identifier High Register */
+
+#define	CAN_MB12_DATA0		0xFFC02D80	/* Mailbox 12 Data Word	0 [15:0] Register */
+#define	CAN_MB12_DATA1		0xFFC02D84	/* Mailbox 12 Data Word	1 [31:16] Register */
+#define	CAN_MB12_DATA2		0xFFC02D88	/* Mailbox 12 Data Word	2 [47:32] Register */
+#define	CAN_MB12_DATA3		0xFFC02D8C	/* Mailbox 12 Data Word	3 [63:48] Register */
+#define	CAN_MB12_LENGTH		0xFFC02D90	/* Mailbox 12 Data Length Code Register */
+#define	CAN_MB12_TIMESTAMP	0xFFC02D94	/* Mailbox 12 Time Stamp Value Register */
+#define	CAN_MB12_ID0		0xFFC02D98	/* Mailbox 12 Identifier Low Register */
+#define	CAN_MB12_ID1		0xFFC02D9C	/* Mailbox 12 Identifier High Register */
+
+#define	CAN_MB13_DATA0		0xFFC02DA0	/* Mailbox 13 Data Word	0 [15:0] Register */
+#define	CAN_MB13_DATA1		0xFFC02DA4	/* Mailbox 13 Data Word	1 [31:16] Register */
+#define	CAN_MB13_DATA2		0xFFC02DA8	/* Mailbox 13 Data Word	2 [47:32] Register */
+#define	CAN_MB13_DATA3		0xFFC02DAC	/* Mailbox 13 Data Word	3 [63:48] Register */
+#define	CAN_MB13_LENGTH		0xFFC02DB0	/* Mailbox 13 Data Length Code Register */
+#define	CAN_MB13_TIMESTAMP	0xFFC02DB4	/* Mailbox 13 Time Stamp Value Register */
+#define	CAN_MB13_ID0		0xFFC02DB8	/* Mailbox 13 Identifier Low Register */
+#define	CAN_MB13_ID1		0xFFC02DBC	/* Mailbox 13 Identifier High Register */
+
+#define	CAN_MB14_DATA0		0xFFC02DC0	/* Mailbox 14 Data Word	0 [15:0] Register */
+#define	CAN_MB14_DATA1		0xFFC02DC4	/* Mailbox 14 Data Word	1 [31:16] Register */
+#define	CAN_MB14_DATA2		0xFFC02DC8	/* Mailbox 14 Data Word	2 [47:32] Register */
+#define	CAN_MB14_DATA3		0xFFC02DCC	/* Mailbox 14 Data Word	3 [63:48] Register */
+#define	CAN_MB14_LENGTH		0xFFC02DD0	/* Mailbox 14 Data Length Code Register */
+#define	CAN_MB14_TIMESTAMP	0xFFC02DD4	/* Mailbox 14 Time Stamp Value Register */
+#define	CAN_MB14_ID0		0xFFC02DD8	/* Mailbox 14 Identifier Low Register */
+#define	CAN_MB14_ID1		0xFFC02DDC	/* Mailbox 14 Identifier High Register */
+
+#define	CAN_MB15_DATA0		0xFFC02DE0	/* Mailbox 15 Data Word	0 [15:0] Register */
+#define	CAN_MB15_DATA1		0xFFC02DE4	/* Mailbox 15 Data Word	1 [31:16] Register */
+#define	CAN_MB15_DATA2		0xFFC02DE8	/* Mailbox 15 Data Word	2 [47:32] Register */
+#define	CAN_MB15_DATA3		0xFFC02DEC	/* Mailbox 15 Data Word	3 [63:48] Register */
+#define	CAN_MB15_LENGTH		0xFFC02DF0	/* Mailbox 15 Data Length Code Register */
+#define	CAN_MB15_TIMESTAMP	0xFFC02DF4	/* Mailbox 15 Time Stamp Value Register */
+#define	CAN_MB15_ID0		0xFFC02DF8	/* Mailbox 15 Identifier Low Register */
+#define	CAN_MB15_ID1		0xFFC02DFC	/* Mailbox 15 Identifier High Register */
+
+#define	CAN_MB16_DATA0		0xFFC02E00	/* Mailbox 16 Data Word	0 [15:0] Register */
+#define	CAN_MB16_DATA1		0xFFC02E04	/* Mailbox 16 Data Word	1 [31:16] Register */
+#define	CAN_MB16_DATA2		0xFFC02E08	/* Mailbox 16 Data Word	2 [47:32] Register */
+#define	CAN_MB16_DATA3		0xFFC02E0C	/* Mailbox 16 Data Word	3 [63:48] Register */
+#define	CAN_MB16_LENGTH		0xFFC02E10	/* Mailbox 16 Data Length Code Register */
+#define	CAN_MB16_TIMESTAMP	0xFFC02E14	/* Mailbox 16 Time Stamp Value Register */
+#define	CAN_MB16_ID0		0xFFC02E18	/* Mailbox 16 Identifier Low Register */
+#define	CAN_MB16_ID1		0xFFC02E1C	/* Mailbox 16 Identifier High Register */
+
+#define	CAN_MB17_DATA0		0xFFC02E20	/* Mailbox 17 Data Word	0 [15:0] Register */
+#define	CAN_MB17_DATA1		0xFFC02E24	/* Mailbox 17 Data Word	1 [31:16] Register */
+#define	CAN_MB17_DATA2		0xFFC02E28	/* Mailbox 17 Data Word	2 [47:32] Register */
+#define	CAN_MB17_DATA3		0xFFC02E2C	/* Mailbox 17 Data Word	3 [63:48] Register */
+#define	CAN_MB17_LENGTH		0xFFC02E30	/* Mailbox 17 Data Length Code Register */
+#define	CAN_MB17_TIMESTAMP	0xFFC02E34	/* Mailbox 17 Time Stamp Value Register */
+#define	CAN_MB17_ID0		0xFFC02E38	/* Mailbox 17 Identifier Low Register */
+#define	CAN_MB17_ID1		0xFFC02E3C	/* Mailbox 17 Identifier High Register */
+
+#define	CAN_MB18_DATA0		0xFFC02E40	/* Mailbox 18 Data Word	0 [15:0] Register */
+#define	CAN_MB18_DATA1		0xFFC02E44	/* Mailbox 18 Data Word	1 [31:16] Register */
+#define	CAN_MB18_DATA2		0xFFC02E48	/* Mailbox 18 Data Word	2 [47:32] Register */
+#define	CAN_MB18_DATA3		0xFFC02E4C	/* Mailbox 18 Data Word	3 [63:48] Register */
+#define	CAN_MB18_LENGTH		0xFFC02E50	/* Mailbox 18 Data Length Code Register */
+#define	CAN_MB18_TIMESTAMP	0xFFC02E54	/* Mailbox 18 Time Stamp Value Register */
+#define	CAN_MB18_ID0		0xFFC02E58	/* Mailbox 18 Identifier Low Register */
+#define	CAN_MB18_ID1		0xFFC02E5C	/* Mailbox 18 Identifier High Register */
+
+#define	CAN_MB19_DATA0		0xFFC02E60	/* Mailbox 19 Data Word	0 [15:0] Register */
+#define	CAN_MB19_DATA1		0xFFC02E64	/* Mailbox 19 Data Word	1 [31:16] Register */
+#define	CAN_MB19_DATA2		0xFFC02E68	/* Mailbox 19 Data Word	2 [47:32] Register */
+#define	CAN_MB19_DATA3		0xFFC02E6C	/* Mailbox 19 Data Word	3 [63:48] Register */
+#define	CAN_MB19_LENGTH		0xFFC02E70	/* Mailbox 19 Data Length Code Register */
+#define	CAN_MB19_TIMESTAMP	0xFFC02E74	/* Mailbox 19 Time Stamp Value Register */
+#define	CAN_MB19_ID0		0xFFC02E78	/* Mailbox 19 Identifier Low Register */
+#define	CAN_MB19_ID1		0xFFC02E7C	/* Mailbox 19 Identifier High Register */
+
+#define	CAN_MB20_DATA0		0xFFC02E80	/* Mailbox 20 Data Word	0 [15:0] Register */
+#define	CAN_MB20_DATA1		0xFFC02E84	/* Mailbox 20 Data Word	1 [31:16] Register */
+#define	CAN_MB20_DATA2		0xFFC02E88	/* Mailbox 20 Data Word	2 [47:32] Register */
+#define	CAN_MB20_DATA3		0xFFC02E8C	/* Mailbox 20 Data Word	3 [63:48] Register */
+#define	CAN_MB20_LENGTH		0xFFC02E90	/* Mailbox 20 Data Length Code Register */
+#define	CAN_MB20_TIMESTAMP	0xFFC02E94	/* Mailbox 20 Time Stamp Value Register */
+#define	CAN_MB20_ID0		0xFFC02E98	/* Mailbox 20 Identifier Low Register */
+#define	CAN_MB20_ID1		0xFFC02E9C	/* Mailbox 20 Identifier High Register */
+
+#define	CAN_MB21_DATA0		0xFFC02EA0	/* Mailbox 21 Data Word	0 [15:0] Register */
+#define	CAN_MB21_DATA1		0xFFC02EA4	/* Mailbox 21 Data Word	1 [31:16] Register */
+#define	CAN_MB21_DATA2		0xFFC02EA8	/* Mailbox 21 Data Word	2 [47:32] Register */
+#define	CAN_MB21_DATA3		0xFFC02EAC	/* Mailbox 21 Data Word	3 [63:48] Register */
+#define	CAN_MB21_LENGTH		0xFFC02EB0	/* Mailbox 21 Data Length Code Register */
+#define	CAN_MB21_TIMESTAMP	0xFFC02EB4	/* Mailbox 21 Time Stamp Value Register */
+#define	CAN_MB21_ID0		0xFFC02EB8	/* Mailbox 21 Identifier Low Register */
+#define	CAN_MB21_ID1		0xFFC02EBC	/* Mailbox 21 Identifier High Register */
+
+#define	CAN_MB22_DATA0		0xFFC02EC0	/* Mailbox 22 Data Word	0 [15:0] Register */
+#define	CAN_MB22_DATA1		0xFFC02EC4	/* Mailbox 22 Data Word	1 [31:16] Register */
+#define	CAN_MB22_DATA2		0xFFC02EC8	/* Mailbox 22 Data Word	2 [47:32] Register */
+#define	CAN_MB22_DATA3		0xFFC02ECC	/* Mailbox 22 Data Word	3 [63:48] Register */
+#define	CAN_MB22_LENGTH		0xFFC02ED0	/* Mailbox 22 Data Length Code Register */
+#define	CAN_MB22_TIMESTAMP	0xFFC02ED4	/* Mailbox 22 Time Stamp Value Register */
+#define	CAN_MB22_ID0		0xFFC02ED8	/* Mailbox 22 Identifier Low Register */
+#define	CAN_MB22_ID1		0xFFC02EDC	/* Mailbox 22 Identifier High Register */
+
+#define	CAN_MB23_DATA0		0xFFC02EE0	/* Mailbox 23 Data Word	0 [15:0] Register */
+#define	CAN_MB23_DATA1		0xFFC02EE4	/* Mailbox 23 Data Word	1 [31:16] Register */
+#define	CAN_MB23_DATA2		0xFFC02EE8	/* Mailbox 23 Data Word	2 [47:32] Register */
+#define	CAN_MB23_DATA3		0xFFC02EEC	/* Mailbox 23 Data Word	3 [63:48] Register */
+#define	CAN_MB23_LENGTH		0xFFC02EF0	/* Mailbox 23 Data Length Code Register */
+#define	CAN_MB23_TIMESTAMP	0xFFC02EF4	/* Mailbox 23 Time Stamp Value Register */
+#define	CAN_MB23_ID0		0xFFC02EF8	/* Mailbox 23 Identifier Low Register */
+#define	CAN_MB23_ID1		0xFFC02EFC	/* Mailbox 23 Identifier High Register */
+
+#define	CAN_MB24_DATA0		0xFFC02F00	/* Mailbox 24 Data Word	0 [15:0] Register */
+#define	CAN_MB24_DATA1		0xFFC02F04	/* Mailbox 24 Data Word	1 [31:16] Register */
+#define	CAN_MB24_DATA2		0xFFC02F08	/* Mailbox 24 Data Word	2 [47:32] Register */
+#define	CAN_MB24_DATA3		0xFFC02F0C	/* Mailbox 24 Data Word	3 [63:48] Register */
+#define	CAN_MB24_LENGTH		0xFFC02F10	/* Mailbox 24 Data Length Code Register */
+#define	CAN_MB24_TIMESTAMP	0xFFC02F14	/* Mailbox 24 Time Stamp Value Register */
+#define	CAN_MB24_ID0		0xFFC02F18	/* Mailbox 24 Identifier Low Register */
+#define	CAN_MB24_ID1		0xFFC02F1C	/* Mailbox 24 Identifier High Register */
+
+#define	CAN_MB25_DATA0		0xFFC02F20	/* Mailbox 25 Data Word	0 [15:0] Register */
+#define	CAN_MB25_DATA1		0xFFC02F24	/* Mailbox 25 Data Word	1 [31:16] Register */
+#define	CAN_MB25_DATA2		0xFFC02F28	/* Mailbox 25 Data Word	2 [47:32] Register */
+#define	CAN_MB25_DATA3		0xFFC02F2C	/* Mailbox 25 Data Word	3 [63:48] Register */
+#define	CAN_MB25_LENGTH		0xFFC02F30	/* Mailbox 25 Data Length Code Register */
+#define	CAN_MB25_TIMESTAMP	0xFFC02F34	/* Mailbox 25 Time Stamp Value Register */
+#define	CAN_MB25_ID0		0xFFC02F38	/* Mailbox 25 Identifier Low Register */
+#define	CAN_MB25_ID1		0xFFC02F3C	/* Mailbox 25 Identifier High Register */
+
+#define	CAN_MB26_DATA0		0xFFC02F40	/* Mailbox 26 Data Word	0 [15:0] Register */
+#define	CAN_MB26_DATA1		0xFFC02F44	/* Mailbox 26 Data Word	1 [31:16] Register */
+#define	CAN_MB26_DATA2		0xFFC02F48	/* Mailbox 26 Data Word	2 [47:32] Register */
+#define	CAN_MB26_DATA3		0xFFC02F4C	/* Mailbox 26 Data Word	3 [63:48] Register */
+#define	CAN_MB26_LENGTH		0xFFC02F50	/* Mailbox 26 Data Length Code Register */
+#define	CAN_MB26_TIMESTAMP	0xFFC02F54	/* Mailbox 26 Time Stamp Value Register */
+#define	CAN_MB26_ID0		0xFFC02F58	/* Mailbox 26 Identifier Low Register */
+#define	CAN_MB26_ID1		0xFFC02F5C	/* Mailbox 26 Identifier High Register */
+
+#define	CAN_MB27_DATA0		0xFFC02F60	/* Mailbox 27 Data Word	0 [15:0] Register */
+#define	CAN_MB27_DATA1		0xFFC02F64	/* Mailbox 27 Data Word	1 [31:16] Register */
+#define	CAN_MB27_DATA2		0xFFC02F68	/* Mailbox 27 Data Word	2 [47:32] Register */
+#define	CAN_MB27_DATA3		0xFFC02F6C	/* Mailbox 27 Data Word	3 [63:48] Register */
+#define	CAN_MB27_LENGTH		0xFFC02F70	/* Mailbox 27 Data Length Code Register */
+#define	CAN_MB27_TIMESTAMP	0xFFC02F74	/* Mailbox 27 Time Stamp Value Register */
+#define	CAN_MB27_ID0		0xFFC02F78	/* Mailbox 27 Identifier Low Register */
+#define	CAN_MB27_ID1		0xFFC02F7C	/* Mailbox 27 Identifier High Register */
+
+#define	CAN_MB28_DATA0		0xFFC02F80	/* Mailbox 28 Data Word	0 [15:0] Register */
+#define	CAN_MB28_DATA1		0xFFC02F84	/* Mailbox 28 Data Word	1 [31:16] Register */
+#define	CAN_MB28_DATA2		0xFFC02F88	/* Mailbox 28 Data Word	2 [47:32] Register */
+#define	CAN_MB28_DATA3		0xFFC02F8C	/* Mailbox 28 Data Word	3 [63:48] Register */
+#define	CAN_MB28_LENGTH		0xFFC02F90	/* Mailbox 28 Data Length Code Register */
+#define	CAN_MB28_TIMESTAMP	0xFFC02F94	/* Mailbox 28 Time Stamp Value Register */
+#define	CAN_MB28_ID0		0xFFC02F98	/* Mailbox 28 Identifier Low Register */
+#define	CAN_MB28_ID1		0xFFC02F9C	/* Mailbox 28 Identifier High Register */
+
+#define	CAN_MB29_DATA0		0xFFC02FA0	/* Mailbox 29 Data Word	0 [15:0] Register */
+#define	CAN_MB29_DATA1		0xFFC02FA4	/* Mailbox 29 Data Word	1 [31:16] Register */
+#define	CAN_MB29_DATA2		0xFFC02FA8	/* Mailbox 29 Data Word	2 [47:32] Register */
+#define	CAN_MB29_DATA3		0xFFC02FAC	/* Mailbox 29 Data Word	3 [63:48] Register */
+#define	CAN_MB29_LENGTH		0xFFC02FB0	/* Mailbox 29 Data Length Code Register */
+#define	CAN_MB29_TIMESTAMP	0xFFC02FB4	/* Mailbox 29 Time Stamp Value Register */
+#define	CAN_MB29_ID0		0xFFC02FB8	/* Mailbox 29 Identifier Low Register */
+#define	CAN_MB29_ID1		0xFFC02FBC	/* Mailbox 29 Identifier High Register */
+
+#define	CAN_MB30_DATA0		0xFFC02FC0	/* Mailbox 30 Data Word	0 [15:0] Register */
+#define	CAN_MB30_DATA1		0xFFC02FC4	/* Mailbox 30 Data Word	1 [31:16] Register */
+#define	CAN_MB30_DATA2		0xFFC02FC8	/* Mailbox 30 Data Word	2 [47:32] Register */
+#define	CAN_MB30_DATA3		0xFFC02FCC	/* Mailbox 30 Data Word	3 [63:48] Register */
+#define	CAN_MB30_LENGTH		0xFFC02FD0	/* Mailbox 30 Data Length Code Register */
+#define	CAN_MB30_TIMESTAMP	0xFFC02FD4	/* Mailbox 30 Time Stamp Value Register */
+#define	CAN_MB30_ID0		0xFFC02FD8	/* Mailbox 30 Identifier Low Register */
+#define	CAN_MB30_ID1		0xFFC02FDC	/* Mailbox 30 Identifier High Register */
+
+#define	CAN_MB31_DATA0		0xFFC02FE0	/* Mailbox 31 Data Word	0 [15:0] Register */
+#define	CAN_MB31_DATA1		0xFFC02FE4	/* Mailbox 31 Data Word	1 [31:16] Register */
+#define	CAN_MB31_DATA2		0xFFC02FE8	/* Mailbox 31 Data Word	2 [47:32] Register */
+#define	CAN_MB31_DATA3		0xFFC02FEC	/* Mailbox 31 Data Word	3 [63:48] Register */
+#define	CAN_MB31_LENGTH		0xFFC02FF0	/* Mailbox 31 Data Length Code Register */
+#define	CAN_MB31_TIMESTAMP	0xFFC02FF4	/* Mailbox 31 Time Stamp Value Register */
+#define	CAN_MB31_ID0		0xFFC02FF8	/* Mailbox 31 Identifier Low Register */
+#define	CAN_MB31_ID1		0xFFC02FFC	/* Mailbox 31 Identifier High Register */
+
+/* CAN Mailbox Area Macros */
+#define	CAN_MB_ID1(x)		(CAN_MB00_ID1+((x)*0x20))
+#define	CAN_MB_ID0(x)		(CAN_MB00_ID0+((x)*0x20))
+#define	CAN_MB_TIMESTAMP(x)	(CAN_MB00_TIMESTAMP+((x)*0x20))
+#define	CAN_MB_LENGTH(x)	(CAN_MB00_LENGTH+((x)*0x20))
+#define	CAN_MB_DATA3(x)		(CAN_MB00_DATA3+((x)*0x20))
+#define	CAN_MB_DATA2(x)		(CAN_MB00_DATA2+((x)*0x20))
+#define	CAN_MB_DATA1(x)		(CAN_MB00_DATA1+((x)*0x20))
+#define	CAN_MB_DATA0(x)		(CAN_MB00_DATA0+((x)*0x20))
+
+
+/*********************************************************************************** */
+/* System MMR Register Bits and	Macros */
+/******************************************************************************* */
+
+/* SWRST Mask */
+#define	SYSTEM_RESET	0x0007	/* Initiates A System Software Reset */
+#define	DOUBLE_FAULT	0x0008	/* Core	Double Fault Causes Reset */
+#define	RESET_DOUBLE	0x2000	/* SW Reset Generated By Core Double-Fault */
+#define	RESET_WDOG		0x4000	/* SW Reset Generated By Watchdog Timer */
+#define	RESET_SOFTWARE	0x8000	/* SW Reset Occurred Since Last	Read Of	SWRST */
+
+/* SYSCR Masks													 */
+#define	BMODE			0x0006	/* Boot	Mode - Latched During HW Reset From Mode Pins */
+#define	NOBOOT			0x0010	/* Execute From	L1 or ASYNC Bank 0 When	BMODE =	0 */
+
+
+/* *************  SYSTEM INTERRUPT CONTROLLER MASKS ***************** */
+
+/* Peripheral Masks For	SIC0_ISR, SIC0_IWR, SIC0_IMASK */
+#define	PLL_WAKEUP_IRQ		0x00000001	/* PLL Wakeup Interrupt	Request */
+#define	DMAC0_ERR_IRQ		0x00000002	/* DMA Controller 0 Error Interrupt Request */
+#define	PPI_ERR_IRQ		0x00000004	/* PPI Error Interrupt Request */
+#define	SPORT0_ERR_IRQ		0x00000008	/* SPORT0 Error	Interrupt Request */
+#define	SPORT1_ERR_IRQ		0x00000010	/* SPORT1 Error	Interrupt Request */
+#define	SPI0_ERR_IRQ		0x00000020	/* SPI0	Error Interrupt	Request */
+#define	UART0_ERR_IRQ		0x00000040	/* UART0 Error Interrupt Request */
+#define	RTC_IRQ			0x00000080	/* Real-Time Clock Interrupt Request */
+#define	DMA0_IRQ		0x00000100	/* DMA Channel 0 (PPI) Interrupt Request */
+#define	DMA1_IRQ		0x00000200	/* DMA Channel 1 (SPORT0 RX) Interrupt Request */
+#define	DMA2_IRQ		0x00000400	/* DMA Channel 2 (SPORT0 TX) Interrupt Request */
+#define	DMA3_IRQ		0x00000800	/* DMA Channel 3 (SPORT1 RX) Interrupt Request */
+#define	DMA4_IRQ		0x00001000	/* DMA Channel 4 (SPORT1 TX) Interrupt Request */
+#define	DMA5_IRQ		0x00002000	/* DMA Channel 5 (SPI) Interrupt Request */
+#define	DMA6_IRQ		0x00004000	/* DMA Channel 6 (UART RX) Interrupt Request */
+#define	DMA7_IRQ		0x00008000	/* DMA Channel 7 (UART TX) Interrupt Request */
+#define	TIMER0_IRQ		0x00010000	/* Timer 0 Interrupt Request */
+#define	TIMER1_IRQ		0x00020000	/* Timer 1 Interrupt Request */
+#define	TIMER2_IRQ		0x00040000	/* Timer 2 Interrupt Request */
+#define	PFA_IRQ			0x00080000	/* Programmable	Flag Interrupt Request A */
+#define	PFB_IRQ			0x00100000	/* Programmable	Flag Interrupt Request B */
+#define	MDMA0_0_IRQ		0x00200000	/* MemDMA0 Stream 0 Interrupt Request */
+#define	MDMA0_1_IRQ		0x00400000	/* MemDMA0 Stream 1 Interrupt Request */
+#define	WDOG_IRQ		0x00800000	/* Software Watchdog Timer Interrupt Request */
+#define	DMAC1_ERR_IRQ		0x01000000	/* DMA Controller 1 Error Interrupt Request */
+#define	SPORT2_ERR_IRQ		0x02000000	/* SPORT2 Error	Interrupt Request */
+#define	SPORT3_ERR_IRQ		0x04000000	/* SPORT3 Error	Interrupt Request */
+#define	MXVR_SD_IRQ		0x08000000	/* MXVR	Synchronous Data Interrupt Request */
+#define	SPI1_ERR_IRQ		0x10000000	/* SPI1	Error Interrupt	Request */
+#define	SPI2_ERR_IRQ		0x20000000	/* SPI2	Error Interrupt	Request */
+#define	UART1_ERR_IRQ		0x40000000	/* UART1 Error Interrupt Request */
+#define	UART2_ERR_IRQ		0x80000000	/* UART2 Error Interrupt Request */
+
+/* the following are for backwards compatibility */
+#define	DMA0_ERR_IRQ		DMAC0_ERR_IRQ
+#define	DMA1_ERR_IRQ		DMAC1_ERR_IRQ
+
+
+/* Peripheral Masks For	SIC_ISR1, SIC_IWR1, SIC_IMASK1	 */
+#define	CAN_ERR_IRQ			0x00000001	/* CAN Error Interrupt Request */
+#define	DMA8_IRQ			0x00000002	/* DMA Channel 8 (SPORT2 RX) Interrupt Request */
+#define	DMA9_IRQ			0x00000004	/* DMA Channel 9 (SPORT2 TX) Interrupt Request */
+#define	DMA10_IRQ			0x00000008	/* DMA Channel 10 (SPORT3 RX) Interrupt	Request */
+#define	DMA11_IRQ			0x00000010	/* DMA Channel 11 (SPORT3 TX) Interrupt	Request */
+#define	DMA12_IRQ			0x00000020	/* DMA Channel 12 Interrupt Request */
+#define	DMA13_IRQ			0x00000040	/* DMA Channel 13 Interrupt Request */
+#define	DMA14_IRQ			0x00000080	/* DMA Channel 14 (SPI1) Interrupt Request */
+#define	DMA15_IRQ			0x00000100	/* DMA Channel 15 (SPI2) Interrupt Request */
+#define	DMA16_IRQ			0x00000200	/* DMA Channel 16 (UART1 RX) Interrupt Request */
+#define	DMA17_IRQ			0x00000400	/* DMA Channel 17 (UART1 TX) Interrupt Request */
+#define	DMA18_IRQ			0x00000800	/* DMA Channel 18 (UART2 RX) Interrupt Request */
+#define	DMA19_IRQ			0x00001000	/* DMA Channel 19 (UART2 TX) Interrupt Request */
+#define	TWI0_IRQ			0x00002000	/* TWI0	Interrupt Request */
+#define	TWI1_IRQ			0x00004000	/* TWI1	Interrupt Request */
+#define	CAN_RX_IRQ			0x00008000	/* CAN Receive Interrupt Request */
+#define	CAN_TX_IRQ			0x00010000	/* CAN Transmit	Interrupt Request */
+#define	MDMA1_0_IRQ			0x00020000	/* MemDMA1 Stream 0 Interrupt Request */
+#define	MDMA1_1_IRQ			0x00040000	/* MemDMA1 Stream 1 Interrupt Request */
+#define	MXVR_STAT_IRQ			0x00080000	/* MXVR	Status Interrupt Request */
+#define	MXVR_CM_IRQ			0x00100000	/* MXVR	Control	Message	Interrupt Request */
+#define	MXVR_AP_IRQ			0x00200000	/* MXVR	Asynchronous Packet Interrupt */
+
+/* the following are for backwards compatibility */
+#define	MDMA0_IRQ		MDMA1_0_IRQ
+#define	MDMA1_IRQ		MDMA1_1_IRQ
+
+#ifdef _MISRA_RULES
+#define	_MF15 0xFu
+#define	_MF7 7u
+#else
+#define	_MF15 0xF
+#define	_MF7 7
+#endif /* _MISRA_RULES */
+
+/* SIC_IMASKx Masks											 */
+#define	SIC_UNMASK_ALL	0x00000000					/* Unmask all peripheral interrupts */
+#define	SIC_MASK_ALL	0xFFFFFFFF					/* Mask	all peripheral interrupts */
+#ifdef _MISRA_RULES
+#define	SIC_MASK(x)		(1 << ((x)&0x1Fu))					/* Mask	Peripheral #x interrupt */
+#define	SIC_UNMASK(x)	(0xFFFFFFFFu ^ (1 << ((x)&0x1Fu)))	/* Unmask Peripheral #x	interrupt */
+#else
+#define	SIC_MASK(x)		(1 << ((x)&0x1F))					/* Mask	Peripheral #x interrupt */
+#define	SIC_UNMASK(x)	(0xFFFFFFFF ^ (1 << ((x)&0x1F)))	/* Unmask Peripheral #x	interrupt */
+#endif /* _MISRA_RULES */
+
+/* SIC_IWRx Masks											 */
+#define	IWR_DISABLE_ALL	0x00000000					/* Wakeup Disable all peripherals */
+#define	IWR_ENABLE_ALL	0xFFFFFFFF					/* Wakeup Enable all peripherals */
+#ifdef _MISRA_RULES
+#define	IWR_ENABLE(x)	(1 << ((x)&0x1Fu))					/* Wakeup Enable Peripheral #x */
+#define	IWR_DISABLE(x)	(0xFFFFFFFFu ^ (1 << ((x)&0x1Fu)))	/* Wakeup Disable Peripheral #x */
+#else
+#define	IWR_ENABLE(x)	(1 << ((x)&0x1F))					/* Wakeup Enable Peripheral #x */
+#define	IWR_DISABLE(x)	(0xFFFFFFFF ^ (1 << ((x)&0x1F)))	/* Wakeup Disable Peripheral #x */
+#endif /* _MISRA_RULES */
+
+/*  *********  PARALLEL	PERIPHERAL INTERFACE (PPI) MASKS ****************   */
+/*  PPI_CONTROL	Masks	      */
+#define	PORT_EN		0x0001	/* PPI Port Enable  */
+#define	PORT_DIR	0x0002	/* PPI Port Direction	    */
+#define	XFR_TYPE	0x000C	/* PPI Transfer	Type  */
+#define	PORT_CFG	0x0030	/* PPI Port Configuration */
+#define	FLD_SEL		0x0040	/* PPI Active Field Select */
+#define	PACK_EN		0x0080	/* PPI Packing Mode */
+/* previous versions of	defBF539.h erroneously included	DMA32 (PPI 32-bit DMA Enable) */
+#define	SKIP_EN		0x0200	/* PPI Skip Element Enable */
+#define	SKIP_EO		0x0400	/* PPI Skip Even/Odd Elements */
+#define	DLENGTH		0x3800	/* PPI Data Length  */
+#define	DLEN_8		0x0	     /*	PPI Data Length	mask for DLEN=8 */
+#define	DLEN_10		0x0800		/* Data	Length = 10 Bits */
+#define	DLEN_11		0x1000		/* Data	Length = 11 Bits */
+#define	DLEN_12		0x1800		/* Data	Length = 12 Bits */
+#define	DLEN_13		0x2000		/* Data	Length = 13 Bits */
+#define	DLEN_14		0x2800		/* Data	Length = 14 Bits */
+#define	DLEN_15		0x3000		/* Data	Length = 15 Bits */
+#define	DLEN_16		0x3800		/* Data	Length = 16 Bits */
+#ifdef _MISRA_RULES
+#define	DLEN(x)		((((x)-9u) & 0x07u) << 11)  /* PPI Data	Length (only works for x=10-->x=16) */
+#else
+#define	DLEN(x)		((((x)-9) & 0x07) << 11)  /* PPI Data Length (only works for x=10-->x=16) */
+#endif /* _MISRA_RULES */
+#define	POL			0xC000	/* PPI Signal Polarities       */
+#define	POLC		0x4000		/* PPI Clock Polarity */
+#define	POLS		0x8000		/* PPI Frame Sync Polarity */
+
+
+/* PPI_STATUS Masks					     */
+#define	FLD			0x0400	/* Field Indicator   */
+#define	FT_ERR		0x0800	/* Frame Track Error */
+#define	OVR			0x1000	/* FIFO	Overflow Error */
+#define	UNDR		0x2000	/* FIFO	Underrun Error */
+#define	ERR_DET		0x4000	/* Error Detected Indicator */
+#define	ERR_NCOR	0x8000	/* Error Not Corrected Indicator */
+
+
+/* **********  DMA CONTROLLER MASKS  ***********************/
+
+/* DMAx_PERIPHERAL_MAP,	MDMA_yy_PERIPHERAL_MAP Masks */
+
+#define	CTYPE			0x0040	/* DMA Channel Type Indicator */
+#define	CTYPE_P			0x6		/* DMA Channel Type Indicator BIT POSITION */
+#define	PCAP8			0x0080	/* DMA 8-bit Operation Indicator   */
+#define	PCAP16			0x0100	/* DMA 16-bit Operation	Indicator */
+#define	PCAP32			0x0200	/* DMA 32-bit Operation	Indicator */
+#define	PCAPWR			0x0400	/* DMA Write Operation Indicator */
+#define	PCAPRD			0x0800	/* DMA Read Operation Indicator */
+#define	PMAP			0xF000	/* DMA Peripheral Map Field */
+
+/* PMAP	Encodings For DMA Controller 0 */
+#define	PMAP_PPI		0x0000	/* PMAP	PPI Port DMA */
+#define	PMAP_SPORT0RX	0x1000	/* PMAP	SPORT0 Receive DMA */
+#define	PMAP_SPORT0TX	0x2000	/* PMAP	SPORT0 Transmit	DMA */
+#define	PMAP_SPORT1RX	0x3000	/* PMAP	SPORT1 Receive DMA */
+#define	PMAP_SPORT1TX	0x4000	/* PMAP	SPORT1 Transmit	DMA */
+#define	PMAP_SPI0		0x5000	/* PMAP	SPI DMA */
+#define	PMAP_UART0RX		0x6000	/* PMAP	UART Receive DMA */
+#define	PMAP_UART0TX		0x7000	/* PMAP	UART Transmit DMA */
+
+/* PMAP	Encodings For DMA Controller 1 */
+#define	PMAP_SPORT2RX	    0x0000  /* PMAP SPORT2 Receive DMA */
+#define	PMAP_SPORT2TX	    0x1000  /* PMAP SPORT2 Transmit DMA */
+#define	PMAP_SPORT3RX	    0x2000  /* PMAP SPORT3 Receive DMA */
+#define	PMAP_SPORT3TX	    0x3000  /* PMAP SPORT3 Transmit DMA */
+#define	PMAP_SPI1	    0x6000  /* PMAP SPI1 DMA */
+#define	PMAP_SPI2	    0x7000  /* PMAP SPI2 DMA */
+#define	PMAP_UART1RX	    0x8000  /* PMAP UART1 Receive DMA */
+#define	PMAP_UART1TX	    0x9000  /* PMAP UART1 Transmit DMA */
+#define	PMAP_UART2RX	    0xA000  /* PMAP UART2 Receive DMA */
+#define	PMAP_UART2TX	    0xB000  /* PMAP UART2 Transmit DMA */
+
+
+/*  *************  GENERAL PURPOSE TIMER MASKS	******************** */
+/* PWM Timer bit definitions */
+/* TIMER_ENABLE	Register */
+#define	TIMEN0			0x0001	/* Enable Timer	0 */
+#define	TIMEN1			0x0002	/* Enable Timer	1 */
+#define	TIMEN2			0x0004	/* Enable Timer	2 */
+
+#define	TIMEN0_P		0x00
+#define	TIMEN1_P		0x01
+#define	TIMEN2_P		0x02
+
+/* TIMER_DISABLE Register */
+#define	TIMDIS0			0x0001	/* Disable Timer 0 */
+#define	TIMDIS1			0x0002	/* Disable Timer 1 */
+#define	TIMDIS2			0x0004	/* Disable Timer 2 */
+
+#define	TIMDIS0_P		0x00
+#define	TIMDIS1_P		0x01
+#define	TIMDIS2_P		0x02
+
+/* TIMER_STATUS	Register */
+#define	TIMIL0			0x0001	/* Timer 0 Interrupt */
+#define	TIMIL1			0x0002	/* Timer 1 Interrupt */
+#define	TIMIL2			0x0004	/* Timer 2 Interrupt */
+#define	TOVF_ERR0		0x0010	/* Timer 0 Counter Overflow */
+#define	TOVF_ERR1		0x0020	/* Timer 1 Counter Overflow */
+#define	TOVF_ERR2		0x0040	/* Timer 2 Counter Overflow */
+#define	TRUN0			0x1000	/* Timer 0 Slave Enable	Status */
+#define	TRUN1			0x2000	/* Timer 1 Slave Enable	Status */
+#define	TRUN2			0x4000	/* Timer 2 Slave Enable	Status */
+
+#define	TIMIL0_P		0x00
+#define	TIMIL1_P		0x01
+#define	TIMIL2_P		0x02
+#define	TOVF_ERR0_P		0x04
+#define	TOVF_ERR1_P		0x05
+#define	TOVF_ERR2_P		0x06
+#define	TRUN0_P			0x0C
+#define	TRUN1_P			0x0D
+#define	TRUN2_P			0x0E
+
+/* Alternate Deprecated	Macros Provided	For Backwards Code Compatibility */
+#define	TOVL_ERR0		TOVF_ERR0
+#define	TOVL_ERR1		TOVF_ERR1
+#define	TOVL_ERR2		TOVF_ERR2
+#define	TOVL_ERR0_P		TOVF_ERR0_P
+#define	TOVL_ERR1_P	TOVF_ERR1_P
+#define	TOVL_ERR2_P	TOVF_ERR2_P
+
+/* TIMERx_CONFIG Registers */
+#define	PWM_OUT			0x0001
+#define	WDTH_CAP		0x0002
+#define	EXT_CLK			0x0003
+#define	PULSE_HI		0x0004
+#define	PERIOD_CNT		0x0008
+#define	IRQ_ENA			0x0010
+#define	TIN_SEL			0x0020
+#define	OUT_DIS			0x0040
+#define	CLK_SEL			0x0080
+#define	TOGGLE_HI		0x0100
+#define	EMU_RUN			0x0200
+#ifdef _MISRA_RULES
+#define	ERR_TYP(x)		(((x) &	0x03u) << 14)
+#else
+#define	ERR_TYP(x)		(((x) &	0x03) << 14)
+#endif /* _MISRA_RULES */
+
+#define	TMODE_P0		0x00
+#define	TMODE_P1		0x01
+#define	PULSE_HI_P		0x02
+#define	PERIOD_CNT_P	0x03
+#define	IRQ_ENA_P		0x04
+#define	TIN_SEL_P		0x05
+#define	OUT_DIS_P		0x06
+#define	CLK_SEL_P		0x07
+#define	TOGGLE_HI_P		0x08
+#define	EMU_RUN_P		0x09
+#define	ERR_TYP_P0		0x0E
+#define	ERR_TYP_P1		0x0F
+
+/* *********************  ASYNCHRONOUS MEMORY CONTROLLER MASKS	************* */
+/* EBIU_AMGCTL Masks */
+#define	AMCKEN		0x0001	/* Enable CLKOUT */
+#define	AMBEN_NONE	0x0000	/* All Banks Disabled */
+#define	AMBEN_B0	0x0002	/* Enable Asynchronous Memory Bank 0 only */
+#define	AMBEN_B0_B1	0x0004	/* Enable Asynchronous Memory Banks 0 &	1 only */
+#define	AMBEN_B0_B1_B2	0x0006	/* Enable Asynchronous Memory Banks 0, 1, and 2 */
+#define	AMBEN_ALL	0x0008	/* Enable Asynchronous Memory Banks (all) 0, 1,	2, and 3 */
+#define	CDPRIO		0x0100	/* DMA has priority over core for external accesses */
+
+/* EBIU_AMGCTL Bit Positions */
+#define	AMCKEN_P		0x0000	/* Enable CLKOUT */
+#define	AMBEN_P0		0x0001	/* Asynchronous	Memory Enable, 000 - banks 0-3 disabled, 001 - Bank 0 enabled */
+#define	AMBEN_P1		0x0002	/* Asynchronous	Memory Enable, 010 - banks 0&1 enabled,	 011 - banks 0-3 enabled */
+#define	AMBEN_P2		0x0003	/* Asynchronous	Memory Enable, 1xx - All banks (bank 0,	1, 2, and 3) enabled */
+
+/* EBIU_AMBCTL0	Masks */
+#define	B0RDYEN			0x00000001  /* Bank 0 RDY Enable, 0=disable, 1=enable */
+#define	B0RDYPOL		0x00000002  /* Bank 0 RDY Active high, 0=active	low, 1=active high */
+#define	B0TT_1			0x00000004  /* Bank 0 Transition Time from Read	to Write = 1 cycle */
+#define	B0TT_2			0x00000008  /* Bank 0 Transition Time from Read	to Write = 2 cycles */
+#define	B0TT_3			0x0000000C  /* Bank 0 Transition Time from Read	to Write = 3 cycles */
+#define	B0TT_4			0x00000000  /* Bank 0 Transition Time from Read	to Write = 4 cycles */
+#define	B0ST_1			0x00000010  /* Bank 0 Setup Time from AOE asserted to Read/Write asserted=1 cycle */
+#define	B0ST_2			0x00000020  /* Bank 0 Setup Time from AOE asserted to Read/Write asserted=2 cycles */
+#define	B0ST_3			0x00000030  /* Bank 0 Setup Time from AOE asserted to Read/Write asserted=3 cycles */
+#define	B0ST_4			0x00000000  /* Bank 0 Setup Time from AOE asserted to Read/Write asserted=4 cycles */
+#define	B0HT_1			0x00000040  /* Bank 0 Hold Time	from Read/Write	deasserted to AOE deasserted = 1 cycle */
+#define	B0HT_2			0x00000080  /* Bank 0 Hold Time	from Read/Write	deasserted to AOE deasserted = 2 cycles */
+#define	B0HT_3			0x000000C0  /* Bank 0 Hold Time	from Read/Write	deasserted to AOE deasserted = 3 cycles */
+#define	B0HT_0			0x00000000  /* Bank 0 Hold Time	from Read/Write	deasserted to AOE deasserted = 0 cycles */
+#define	B0RAT_1			0x00000100  /* Bank 0 Read Access Time = 1 cycle */
+#define	B0RAT_2			0x00000200  /* Bank 0 Read Access Time = 2 cycles */
+#define	B0RAT_3			0x00000300  /* Bank 0 Read Access Time = 3 cycles */
+#define	B0RAT_4			0x00000400  /* Bank 0 Read Access Time = 4 cycles */
+#define	B0RAT_5			0x00000500  /* Bank 0 Read Access Time = 5 cycles */
+#define	B0RAT_6			0x00000600  /* Bank 0 Read Access Time = 6 cycles */
+#define	B0RAT_7			0x00000700  /* Bank 0 Read Access Time = 7 cycles */
+#define	B0RAT_8			0x00000800  /* Bank 0 Read Access Time = 8 cycles */
+#define	B0RAT_9			0x00000900  /* Bank 0 Read Access Time = 9 cycles */
+#define	B0RAT_10		0x00000A00  /* Bank 0 Read Access Time = 10 cycles */
+#define	B0RAT_11		0x00000B00  /* Bank 0 Read Access Time = 11 cycles */
+#define	B0RAT_12		0x00000C00  /* Bank 0 Read Access Time = 12 cycles */
+#define	B0RAT_13		0x00000D00  /* Bank 0 Read Access Time = 13 cycles */
+#define	B0RAT_14		0x00000E00  /* Bank 0 Read Access Time = 14 cycles */
+#define	B0RAT_15		0x00000F00  /* Bank 0 Read Access Time = 15 cycles */
+#define	B0WAT_1			0x00001000  /* Bank 0 Write Access Time	= 1 cycle */
+#define	B0WAT_2			0x00002000  /* Bank 0 Write Access Time	= 2 cycles */
+#define	B0WAT_3			0x00003000  /* Bank 0 Write Access Time	= 3 cycles */
+#define	B0WAT_4			0x00004000  /* Bank 0 Write Access Time	= 4 cycles */
+#define	B0WAT_5			0x00005000  /* Bank 0 Write Access Time	= 5 cycles */
+#define	B0WAT_6			0x00006000  /* Bank 0 Write Access Time	= 6 cycles */
+#define	B0WAT_7			0x00007000  /* Bank 0 Write Access Time	= 7 cycles */
+#define	B0WAT_8			0x00008000  /* Bank 0 Write Access Time	= 8 cycles */
+#define	B0WAT_9			0x00009000  /* Bank 0 Write Access Time	= 9 cycles */
+#define	B0WAT_10		0x0000A000  /* Bank 0 Write Access Time	= 10 cycles */
+#define	B0WAT_11		0x0000B000  /* Bank 0 Write Access Time	= 11 cycles */
+#define	B0WAT_12		0x0000C000  /* Bank 0 Write Access Time	= 12 cycles */
+#define	B0WAT_13		0x0000D000  /* Bank 0 Write Access Time	= 13 cycles */
+#define	B0WAT_14		0x0000E000  /* Bank 0 Write Access Time	= 14 cycles */
+#define	B0WAT_15		0x0000F000  /* Bank 0 Write Access Time	= 15 cycles */
+#define	B1RDYEN			0x00010000  /* Bank 1 RDY enable, 0=disable, 1=enable */
+#define	B1RDYPOL		0x00020000  /* Bank 1 RDY Active high, 0=active	low, 1=active high */
+#define	B1TT_1			0x00040000  /* Bank 1 Transition Time from Read	to Write = 1 cycle */
+#define	B1TT_2			0x00080000  /* Bank 1 Transition Time from Read	to Write = 2 cycles */
+#define	B1TT_3			0x000C0000  /* Bank 1 Transition Time from Read	to Write = 3 cycles */
+#define	B1TT_4			0x00000000  /* Bank 1 Transition Time from Read	to Write = 4 cycles */
+#define	B1ST_1			0x00100000  /* Bank 1 Setup Time from AOE asserted to Read or Write asserted = 1 cycle */
+#define	B1ST_2			0x00200000  /* Bank 1 Setup Time from AOE asserted to Read or Write asserted = 2 cycles */
+#define	B1ST_3			0x00300000  /* Bank 1 Setup Time from AOE asserted to Read or Write asserted = 3 cycles */
+#define	B1ST_4			0x00000000  /* Bank 1 Setup Time from AOE asserted to Read or Write asserted = 4 cycles */
+#define	B1HT_1			0x00400000  /* Bank 1 Hold Time	from Read or Write deasserted to AOE deasserted	= 1 cycle */
+#define	B1HT_2			0x00800000  /* Bank 1 Hold Time	from Read or Write deasserted to AOE deasserted	= 2 cycles */
+#define	B1HT_3			0x00C00000  /* Bank 1 Hold Time	from Read or Write deasserted to AOE deasserted	= 3 cycles */
+#define	B1HT_0			0x00000000  /* Bank 1 Hold Time	from Read or Write deasserted to AOE deasserted	= 0 cycles */
+#define	B1RAT_1			0x01000000  /* Bank 1 Read Access Time = 1 cycle */
+#define	B1RAT_2			0x02000000  /* Bank 1 Read Access Time = 2 cycles */
+#define	B1RAT_3			0x03000000  /* Bank 1 Read Access Time = 3 cycles */
+#define	B1RAT_4			0x04000000  /* Bank 1 Read Access Time = 4 cycles */
+#define	B1RAT_5			0x05000000  /* Bank 1 Read Access Time = 5 cycles */
+#define	B1RAT_6			0x06000000  /* Bank 1 Read Access Time = 6 cycles */
+#define	B1RAT_7			0x07000000  /* Bank 1 Read Access Time = 7 cycles */
+#define	B1RAT_8			0x08000000  /* Bank 1 Read Access Time = 8 cycles */
+#define	B1RAT_9			0x09000000  /* Bank 1 Read Access Time = 9 cycles */
+#define	B1RAT_10		0x0A000000  /* Bank 1 Read Access Time = 10 cycles */
+#define	B1RAT_11		0x0B000000  /* Bank 1 Read Access Time = 11 cycles */
+#define	B1RAT_12		0x0C000000  /* Bank 1 Read Access Time = 12 cycles */
+#define	B1RAT_13		0x0D000000  /* Bank 1 Read Access Time = 13 cycles */
+#define	B1RAT_14		0x0E000000  /* Bank 1 Read Access Time = 14 cycles */
+#define	B1RAT_15		0x0F000000  /* Bank 1 Read Access Time = 15 cycles */
+#define	B1WAT_1			0x10000000 /* Bank 1 Write Access Time = 1 cycle */
+#define	B1WAT_2			0x20000000  /* Bank 1 Write Access Time	= 2 cycles */
+#define	B1WAT_3			0x30000000  /* Bank 1 Write Access Time	= 3 cycles */
+#define	B1WAT_4			0x40000000  /* Bank 1 Write Access Time	= 4 cycles */
+#define	B1WAT_5			0x50000000  /* Bank 1 Write Access Time	= 5 cycles */
+#define	B1WAT_6			0x60000000  /* Bank 1 Write Access Time	= 6 cycles */
+#define	B1WAT_7			0x70000000  /* Bank 1 Write Access Time	= 7 cycles */
+#define	B1WAT_8			0x80000000  /* Bank 1 Write Access Time	= 8 cycles */
+#define	B1WAT_9			0x90000000  /* Bank 1 Write Access Time	= 9 cycles */
+#define	B1WAT_10		0xA0000000  /* Bank 1 Write Access Time	= 10 cycles */
+#define	B1WAT_11		0xB0000000  /* Bank 1 Write Access Time	= 11 cycles */
+#define	B1WAT_12		0xC0000000  /* Bank 1 Write Access Time	= 12 cycles */
+#define	B1WAT_13		0xD0000000  /* Bank 1 Write Access Time	= 13 cycles */
+#define	B1WAT_14		0xE0000000  /* Bank 1 Write Access Time	= 14 cycles */
+#define	B1WAT_15		0xF0000000  /* Bank 1 Write Access Time	= 15 cycles */
+
+/* EBIU_AMBCTL1	Masks */
+#define	B2RDYEN			0x00000001  /* Bank 2 RDY Enable, 0=disable, 1=enable */
+#define	B2RDYPOL		0x00000002  /* Bank 2 RDY Active high, 0=active	low, 1=active high */
+#define	B2TT_1			0x00000004  /* Bank 2 Transition Time from Read	to Write = 1 cycle */
+#define	B2TT_2			0x00000008  /* Bank 2 Transition Time from Read	to Write = 2 cycles */
+#define	B2TT_3			0x0000000C  /* Bank 2 Transition Time from Read	to Write = 3 cycles */
+#define	B2TT_4			0x00000000  /* Bank 2 Transition Time from Read	to Write = 4 cycles */
+#define	B2ST_1			0x00000010  /* Bank 2 Setup Time from AOE asserted to Read or Write asserted = 1 cycle */
+#define	B2ST_2			0x00000020  /* Bank 2 Setup Time from AOE asserted to Read or Write asserted = 2 cycles */
+#define	B2ST_3			0x00000030  /* Bank 2 Setup Time from AOE asserted to Read or Write asserted = 3 cycles */
+#define	B2ST_4			0x00000000  /* Bank 2 Setup Time from AOE asserted to Read or Write asserted = 4 cycles */
+#define	B2HT_1			0x00000040  /* Bank 2 Hold Time	from Read or Write deasserted to AOE deasserted	= 1 cycle */
+#define	B2HT_2			0x00000080  /* Bank 2 Hold Time	from Read or Write deasserted to AOE deasserted	= 2 cycles */
+#define	B2HT_3			0x000000C0  /* Bank 2 Hold Time	from Read or Write deasserted to AOE deasserted	= 3 cycles */
+#define	B2HT_0			0x00000000  /* Bank 2 Hold Time	from Read or Write deasserted to AOE deasserted	= 0 cycles */
+#define	B2RAT_1			0x00000100  /* Bank 2 Read Access Time = 1 cycle */
+#define	B2RAT_2			0x00000200  /* Bank 2 Read Access Time = 2 cycles */
+#define	B2RAT_3			0x00000300  /* Bank 2 Read Access Time = 3 cycles */
+#define	B2RAT_4			0x00000400  /* Bank 2 Read Access Time = 4 cycles */
+#define	B2RAT_5			0x00000500  /* Bank 2 Read Access Time = 5 cycles */
+#define	B2RAT_6			0x00000600  /* Bank 2 Read Access Time = 6 cycles */
+#define	B2RAT_7			0x00000700  /* Bank 2 Read Access Time = 7 cycles */
+#define	B2RAT_8			0x00000800  /* Bank 2 Read Access Time = 8 cycles */
+#define	B2RAT_9			0x00000900  /* Bank 2 Read Access Time = 9 cycles */
+#define	B2RAT_10		0x00000A00  /* Bank 2 Read Access Time = 10 cycles */
+#define	B2RAT_11		0x00000B00  /* Bank 2 Read Access Time = 11 cycles */
+#define	B2RAT_12		0x00000C00  /* Bank 2 Read Access Time = 12 cycles */
+#define	B2RAT_13		0x00000D00  /* Bank 2 Read Access Time = 13 cycles */
+#define	B2RAT_14		0x00000E00  /* Bank 2 Read Access Time = 14 cycles */
+#define	B2RAT_15		0x00000F00  /* Bank 2 Read Access Time = 15 cycles */
+#define	B2WAT_1			0x00001000  /* Bank 2 Write Access Time	= 1 cycle */
+#define	B2WAT_2			0x00002000  /* Bank 2 Write Access Time	= 2 cycles */
+#define	B2WAT_3			0x00003000  /* Bank 2 Write Access Time	= 3 cycles */
+#define	B2WAT_4			0x00004000  /* Bank 2 Write Access Time	= 4 cycles */
+#define	B2WAT_5			0x00005000  /* Bank 2 Write Access Time	= 5 cycles */
+#define	B2WAT_6			0x00006000  /* Bank 2 Write Access Time	= 6 cycles */
+#define	B2WAT_7			0x00007000  /* Bank 2 Write Access Time	= 7 cycles */
+#define	B2WAT_8			0x00008000  /* Bank 2 Write Access Time	= 8 cycles */
+#define	B2WAT_9			0x00009000  /* Bank 2 Write Access Time	= 9 cycles */
+#define	B2WAT_10		0x0000A000  /* Bank 2 Write Access Time	= 10 cycles */
+#define	B2WAT_11		0x0000B000  /* Bank 2 Write Access Time	= 11 cycles */
+#define	B2WAT_12		0x0000C000  /* Bank 2 Write Access Time	= 12 cycles */
+#define	B2WAT_13		0x0000D000  /* Bank 2 Write Access Time	= 13 cycles */
+#define	B2WAT_14		0x0000E000  /* Bank 2 Write Access Time	= 14 cycles */
+#define	B2WAT_15		0x0000F000  /* Bank 2 Write Access Time	= 15 cycles */
+#define	B3RDYEN			0x00010000  /* Bank 3 RDY enable, 0=disable, 1=enable */
+#define	B3RDYPOL		0x00020000  /* Bank 3 RDY Active high, 0=active	low, 1=active high */
+#define	B3TT_1			0x00040000  /* Bank 3 Transition Time from Read	to Write = 1 cycle */
+#define	B3TT_2			0x00080000  /* Bank 3 Transition Time from Read	to Write = 2 cycles */
+#define	B3TT_3			0x000C0000  /* Bank 3 Transition Time from Read	to Write = 3 cycles */
+#define	B3TT_4			0x00000000  /* Bank 3 Transition Time from Read	to Write = 4 cycles */
+#define	B3ST_1			0x00100000  /* Bank 3 Setup Time from AOE asserted to Read or Write asserted = 1 cycle */
+#define	B3ST_2			0x00200000  /* Bank 3 Setup Time from AOE asserted to Read or Write asserted = 2 cycles */
+#define	B3ST_3			0x00300000  /* Bank 3 Setup Time from AOE asserted to Read or Write asserted = 3 cycles */
+#define	B3ST_4			0x00000000  /* Bank 3 Setup Time from AOE asserted to Read or Write asserted = 4 cycles */
+#define	B3HT_1			0x00400000  /* Bank 3 Hold Time	from Read or Write deasserted to AOE deasserted	= 1 cycle */
+#define	B3HT_2			0x00800000  /* Bank 3 Hold Time	from Read or Write deasserted to AOE deasserted	= 2 cycles */
+#define	B3HT_3			0x00C00000  /* Bank 3 Hold Time	from Read or Write deasserted to AOE deasserted	= 3 cycles */
+#define	B3HT_0			0x00000000  /* Bank 3 Hold Time	from Read or Write deasserted to AOE deasserted	= 0 cycles */
+#define	B3RAT_1			0x01000000 /* Bank 3 Read Access Time =	1 cycle */
+#define	B3RAT_2			0x02000000  /* Bank 3 Read Access Time = 2 cycles */
+#define	B3RAT_3			0x03000000  /* Bank 3 Read Access Time = 3 cycles */
+#define	B3RAT_4			0x04000000  /* Bank 3 Read Access Time = 4 cycles */
+#define	B3RAT_5			0x05000000  /* Bank 3 Read Access Time = 5 cycles */
+#define	B3RAT_6			0x06000000  /* Bank 3 Read Access Time = 6 cycles */
+#define	B3RAT_7			0x07000000  /* Bank 3 Read Access Time = 7 cycles */
+#define	B3RAT_8			0x08000000  /* Bank 3 Read Access Time = 8 cycles */
+#define	B3RAT_9			0x09000000  /* Bank 3 Read Access Time = 9 cycles */
+#define	B3RAT_10		0x0A000000  /* Bank 3 Read Access Time = 10 cycles */
+#define	B3RAT_11		0x0B000000  /* Bank 3 Read Access Time = 11 cycles */
+#define	B3RAT_12		0x0C000000  /* Bank 3 Read Access Time = 12 cycles */
+#define	B3RAT_13		0x0D000000  /* Bank 3 Read Access Time = 13 cycles */
+#define	B3RAT_14		0x0E000000  /* Bank 3 Read Access Time = 14 cycles */
+#define	B3RAT_15		0x0F000000  /* Bank 3 Read Access Time = 15 cycles */
+#define	B3WAT_1			0x10000000 /* Bank 3 Write Access Time = 1 cycle */
+#define	B3WAT_2			0x20000000  /* Bank 3 Write Access Time	= 2 cycles */
+#define	B3WAT_3			0x30000000  /* Bank 3 Write Access Time	= 3 cycles */
+#define	B3WAT_4			0x40000000  /* Bank 3 Write Access Time	= 4 cycles */
+#define	B3WAT_5			0x50000000  /* Bank 3 Write Access Time	= 5 cycles */
+#define	B3WAT_6			0x60000000  /* Bank 3 Write Access Time	= 6 cycles */
+#define	B3WAT_7			0x70000000  /* Bank 3 Write Access Time	= 7 cycles */
+#define	B3WAT_8			0x80000000  /* Bank 3 Write Access Time	= 8 cycles */
+#define	B3WAT_9			0x90000000  /* Bank 3 Write Access Time	= 9 cycles */
+#define	B3WAT_10		0xA0000000  /* Bank 3 Write Access Time	= 10 cycles */
+#define	B3WAT_11		0xB0000000  /* Bank 3 Write Access Time	= 11 cycles */
+#define	B3WAT_12		0xC0000000  /* Bank 3 Write Access Time	= 12 cycles */
+#define	B3WAT_13		0xD0000000  /* Bank 3 Write Access Time	= 13 cycles */
+#define	B3WAT_14		0xE0000000  /* Bank 3 Write Access Time	= 14 cycles */
+#define	B3WAT_15		0xF0000000  /* Bank 3 Write Access Time	= 15 cycles */
+
+/* **********************  SDRAM CONTROLLER MASKS  *************************** */
+/* EBIU_SDGCTL Masks */
+#define	SCTLE			0x00000001 /* Enable SCLK[0], /SRAS, /SCAS, /SWE, SDQM[3:0] */
+#define	CL_2			0x00000008 /* SDRAM CAS	latency	= 2 cycles */
+#define	CL_3			0x0000000C /* SDRAM CAS	latency	= 3 cycles */
+#define	PFE				0x00000010 /* Enable SDRAM prefetch */
+#define	PFP				0x00000020 /* Prefetch has priority over AMC requests */
+#define	PASR_ALL		0x00000000	/* All 4 SDRAM Banks Refreshed In Self-Refresh */
+#define	PASR_B0_B1		0x00000010	/* SDRAM Banks 0 and 1 Are Refreshed In	Self-Refresh */
+#define	PASR_B0			0x00000020	/* Only	SDRAM Bank 0 Is	Refreshed In Self-Refresh */
+#define	TRAS_1			0x00000040 /* SDRAM tRAS = 1 cycle */
+#define	TRAS_2			0x00000080 /* SDRAM tRAS = 2 cycles */
+#define	TRAS_3			0x000000C0 /* SDRAM tRAS = 3 cycles */
+#define	TRAS_4			0x00000100 /* SDRAM tRAS = 4 cycles */
+#define	TRAS_5			0x00000140 /* SDRAM tRAS = 5 cycles */
+#define	TRAS_6			0x00000180 /* SDRAM tRAS = 6 cycles */
+#define	TRAS_7			0x000001C0 /* SDRAM tRAS = 7 cycles */
+#define	TRAS_8			0x00000200 /* SDRAM tRAS = 8 cycles */
+#define	TRAS_9			0x00000240 /* SDRAM tRAS = 9 cycles */
+#define	TRAS_10			0x00000280 /* SDRAM tRAS = 10 cycles */
+#define	TRAS_11			0x000002C0 /* SDRAM tRAS = 11 cycles */
+#define	TRAS_12			0x00000300 /* SDRAM tRAS = 12 cycles */
+#define	TRAS_13			0x00000340 /* SDRAM tRAS = 13 cycles */
+#define	TRAS_14			0x00000380 /* SDRAM tRAS = 14 cycles */
+#define	TRAS_15			0x000003C0 /* SDRAM tRAS = 15 cycles */
+#define	TRP_1			0x00000800 /* SDRAM tRP	= 1 cycle */
+#define	TRP_2			0x00001000 /* SDRAM tRP	= 2 cycles */
+#define	TRP_3			0x00001800 /* SDRAM tRP	= 3 cycles */
+#define	TRP_4			0x00002000 /* SDRAM tRP	= 4 cycles */
+#define	TRP_5			0x00002800 /* SDRAM tRP	= 5 cycles */
+#define	TRP_6			0x00003000 /* SDRAM tRP	= 6 cycles */
+#define	TRP_7			0x00003800 /* SDRAM tRP	= 7 cycles */
+#define	TRCD_1			0x00008000 /* SDRAM tRCD = 1 cycle */
+#define	TRCD_2			0x00010000 /* SDRAM tRCD = 2 cycles */
+#define	TRCD_3			0x00018000 /* SDRAM tRCD = 3 cycles */
+#define	TRCD_4			0x00020000 /* SDRAM tRCD = 4 cycles */
+#define	TRCD_5			0x00028000 /* SDRAM tRCD = 5 cycles */
+#define	TRCD_6			0x00030000 /* SDRAM tRCD = 6 cycles */
+#define	TRCD_7			0x00038000 /* SDRAM tRCD = 7 cycles */
+#define	TWR_1			0x00080000 /* SDRAM tWR	= 1 cycle */
+#define	TWR_2			0x00100000 /* SDRAM tWR	= 2 cycles */
+#define	TWR_3			0x00180000 /* SDRAM tWR	= 3 cycles */
+#define	PUPSD			0x00200000 /*Power-up start delay */
+#define	PSM				0x00400000 /* SDRAM power-up sequence =	Precharge, mode	register set, 8	CBR refresh cycles */
+#define	PSS				0x00800000 /* enable SDRAM power-up sequence on	next SDRAM access */
+#define	SRFS			0x01000000 /* Start SDRAM self-refresh mode */
+#define	EBUFE			0x02000000 /* Enable external buffering	timing */
+#define	FBBRW			0x04000000 /* Fast back-to-back	read write enable */
+#define	EMREN			0x10000000 /* Extended mode register enable */
+#define	TCSR			0x20000000 /* Temp compensated self refresh value 85 deg C */
+#define	CDDBG			0x40000000 /* Tristate SDRAM controls during bus grant */
+
+/* EBIU_SDBCTL Masks */
+#define	EBE				0x00000001 /* Enable SDRAM external bank */
+#define	EBSZ_16			0x00000000 /* SDRAM external bank size = 16MB */
+#define	EBSZ_32			0x00000002 /* SDRAM external bank size = 32MB */
+#define	EBSZ_64			0x00000004 /* SDRAM external bank size = 64MB */
+#define	EBSZ_128		0x00000006 /* SDRAM external bank size = 128MB */
+#define	EBSZ_256		0x00000008 /* SDRAM External Bank Size = 256MB */
+#define	EBSZ_512		0x0000000A /* SDRAM External Bank Size = 512MB */
+#define	EBCAW_8			0x00000000 /* SDRAM external bank column address width = 8 bits */
+#define	EBCAW_9			0x00000010 /* SDRAM external bank column address width = 9 bits */
+#define	EBCAW_10		0x00000020 /* SDRAM external bank column address width = 9 bits */
+#define	EBCAW_11		0x00000030 /* SDRAM external bank column address width = 9 bits */
+
+/* EBIU_SDSTAT Masks */
+#define	SDCI			0x00000001 /* SDRAM controller is idle */
+#define	SDSRA			0x00000002 /* SDRAM SDRAM self refresh is active */
+#define	SDPUA			0x00000004 /* SDRAM power up active  */
+#define	SDRS			0x00000008 /* SDRAM is in reset	state */
+#define	SDEASE			0x00000010 /* SDRAM EAB	sticky error status - W1C */
+#define	BGSTAT			0x00000020 /* Bus granted */
+
+
+/*  ********************  TWO-WIRE INTERFACE (TWIx) MASKS  ***********************/
+/* TWIx_CLKDIV Macros (Use: *pTWIx_CLKDIV = CLKLOW(x)|CLKHI(y);	 ) */
+#ifdef _MISRA_RULES
+#define	CLKLOW(x)	((x) & 0xFFu)		/* Periods Clock Is Held Low */
+#define	CLKHI(y)	(((y)&0xFFu)<<0x8)	/* Periods Before New Clock Low */
+#else
+#define	CLKLOW(x)	((x) & 0xFF)		/* Periods Clock Is Held Low */
+#define	CLKHI(y)	(((y)&0xFF)<<0x8)	/* Periods Before New Clock Low */
+#endif /* _MISRA_RULES */
+
+/* TWIx_PRESCALE Masks								 */
+#define	PRESCALE	0x007F		/* SCLKs Per Internal Time Reference (10MHz) */
+#define	TWI_ENA		0x0080		/* TWI Enable		 */
+#define	SCCB		0x0200		/* SCCB	Compatibility Enable */
+
+/* TWIx_SLAVE_CTRL Masks								 */
+#define	SEN			0x0001		/* Slave Enable		 */
+#define	SADD_LEN	0x0002		/* Slave Address Length */
+#define	STDVAL		0x0004		/* Slave Transmit Data Valid */
+#define	NAK			0x0008		/* NAK/ACK* Generated At Conclusion Of Transfer */
+#define	GEN			0x0010		/* General Call	Adrress	Matching Enabled */
+
+/* TWIx_SLAVE_STAT Masks								 */
+#define	SDIR		0x0001		/* Slave Transfer Direction (Transmit/Receive*) */
+#define	GCALL		0x0002		/* General Call	Indicator */
+
+/* TWIx_MASTER_CTRL Masks						 */
+#define	MEN			0x0001		/* Master Mode Enable */
+#define	MADD_LEN	0x0002		/* Master Address Length */
+#define	MDIR		0x0004		/* Master Transmit Direction (RX/TX*) */
+#define	FAST		0x0008		/* Use Fast Mode Timing	Specs */
+#define	STOP		0x0010		/* Issue Stop Condition */
+#define	RSTART		0x0020		/* Repeat Start	or Stop* At End	Of Transfer */
+#define	DCNT		0x3FC0		/* Data	Bytes To Transfer */
+#define	SDAOVR		0x4000		/* Serial Data Override */
+#define	SCLOVR		0x8000		/* Serial Clock	Override */
+
+/* TWIx_MASTER_STAT Masks							 */
+#define	MPROG		0x0001		/* Master Transfer In Progress */
+#define	LOSTARB		0x0002		/* Lost	Arbitration Indicator (Xfer Aborted) */
+#define	ANAK		0x0004		/* Address Not Acknowledged */
+#define	DNAK		0x0008		/* Data	Not Acknowledged */
+#define	BUFRDERR	0x0010		/* Buffer Read Error */
+#define	BUFWRERR	0x0020		/* Buffer Write	Error */
+#define	SDASEN		0x0040		/* Serial Data Sense */
+#define	SCLSEN		0x0080		/* Serial Clock	Sense */
+#define	BUSBUSY		0x0100		/* Bus Busy Indicator */
+
+/* TWIx_INT_SRC	and TWIx_INT_ENABLE Masks */
+#define	SINIT		0x0001		/* Slave Transfer Initiated */
+#define	SCOMP		0x0002		/* Slave Transfer Complete */
+#define	SERR		0x0004		/* Slave Transfer Error */
+#define	SOVF		0x0008		/* Slave Overflow */
+#define	MCOMP		0x0010		/* Master Transfer Complete */
+#define	MERR		0x0020		/* Master Transfer Error */
+#define	XMTSERV		0x0040		/* Transmit FIFO Service */
+#define	RCVSERV		0x0080		/* Receive FIFO	Service */
+
+/* TWIx_FIFO_CTL Masks					 */
+#define	XMTFLUSH	0x0001		/* Transmit Buffer Flush */
+#define	RCVFLUSH	0x0002		/* Receive Buffer Flush */
+#define	XMTINTLEN	0x0004		/* Transmit Buffer Interrupt Length */
+#define	RCVINTLEN	0x0008		/* Receive Buffer Interrupt Length */
+
+/* TWIx_FIFO_STAT Masks								 */
+#define	XMTSTAT		0x0003		/* Transmit FIFO Status */
+#define	XMT_EMPTY	0x0000		/*		Transmit FIFO Empty */
+#define	XMT_HALF	0x0001		/*		Transmit FIFO Has 1 Byte To Write */
+#define	XMT_FULL	0x0003		/*		Transmit FIFO Full (2 Bytes To Write) */
+
+#define	RCVSTAT		0x000C		/* Receive FIFO	Status */
+#define	RCV_EMPTY	0x0000		/*		Receive	FIFO Empty */
+#define	RCV_HALF	0x0004		/*		Receive	FIFO Has 1 Byte	To Read */
+#define	RCV_FULL	0x000C		/*		Receive	FIFO Full (2 Bytes To Read) */
+
+#endif
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf538/include/mach/defBF539.h linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf538/include/mach/defBF539.h
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf538/include/mach/defBF539.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf538/include/mach/defBF539.h	2011-03-14 21:20:32.000000000 -0400
@@ -1,859 +1,13 @@
 /*
- * Copyright 2008-2009 Analog Devices Inc.
+ * Copyright 2008-2010 Analog Devices Inc.
  *
  * Licensed under the ADI BSD license or the GPL-2 (or later)
  */
 
-/* SYSTEM & MM REGISTER BIT & ADDRESS DEFINITIONS FOR ADSP-BF538/9 */
-
 #ifndef _DEF_BF539_H
 #define _DEF_BF539_H
 
-/* include all Core registers and bit definitions */
-#include <asm/def_LPBlackfin.h>
-
-
-/*********************************************************************************** */
-/* System MMR Register Map */
-/*********************************************************************************** */
-/* Clock/Regulator Control (0xFFC00000 - 0xFFC000FF) */
-#define	PLL_CTL			0xFFC00000	/* PLL Control register (16-bit) */
-#define	PLL_DIV			0xFFC00004	/* PLL Divide Register (16-bit) */
-#define	VR_CTL			0xFFC00008	/* Voltage Regulator Control Register (16-bit) */
-#define	PLL_STAT		0xFFC0000C	/* PLL Status register (16-bit) */
-#define	PLL_LOCKCNT		0xFFC00010	/* PLL Lock	Count register (16-bit) */
-#define	CHIPID			0xFFC00014	/* Chip	ID Register */
-
-/* CHIPID Masks */
-#define CHIPID_VERSION         0xF0000000
-#define CHIPID_FAMILY          0x0FFFF000
-#define CHIPID_MANUFACTURE     0x00000FFE
-
-/* System Interrupt Controller (0xFFC00100 - 0xFFC001FF) */
-#define	SWRST			0xFFC00100  /* Software	Reset Register (16-bit) */
-#define	SYSCR			0xFFC00104  /* System Configuration registe */
-#define	SIC_RVECT		0xFFC00108
-#define	SIC_IMASK0		0xFFC0010C  /* Interrupt Mask Register */
-#define	SIC_IAR0		0xFFC00110  /* Interrupt Assignment Register 0 */
-#define	SIC_IAR1		0xFFC00114  /* Interrupt Assignment Register 1 */
-#define	SIC_IAR2		0xFFC00118  /* Interrupt Assignment Register 2 */
-#define	SIC_IAR3			0xFFC0011C	/* Interrupt Assignment	Register 3 */
-#define	SIC_ISR0			0xFFC00120  /* Interrupt Status	Register */
-#define	SIC_IWR0			0xFFC00124  /* Interrupt Wakeup	Register */
-#define	SIC_IMASK1			0xFFC00128	/* Interrupt Mask Register 1 */
-#define	SIC_ISR1			0xFFC0012C	/* Interrupt Status Register 1 */
-#define	SIC_IWR1			0xFFC00130	/* Interrupt Wakeup Register 1 */
-#define	SIC_IAR4			0xFFC00134	/* Interrupt Assignment	Register 4 */
-#define	SIC_IAR5			0xFFC00138	/* Interrupt Assignment	Register 5 */
-#define	SIC_IAR6			0xFFC0013C	/* Interrupt Assignment	Register 6 */
-
-
-/* Watchdog Timer (0xFFC00200 -	0xFFC002FF) */
-#define	WDOG_CTL	0xFFC00200  /* Watchdog	Control	Register */
-#define	WDOG_CNT	0xFFC00204  /* Watchdog	Count Register */
-#define	WDOG_STAT	0xFFC00208  /* Watchdog	Status Register */
-
-
-/* Real	Time Clock (0xFFC00300 - 0xFFC003FF) */
-#define	RTC_STAT	0xFFC00300  /* RTC Status Register */
-#define	RTC_ICTL	0xFFC00304  /* RTC Interrupt Control Register */
-#define	RTC_ISTAT	0xFFC00308  /* RTC Interrupt Status Register */
-#define	RTC_SWCNT	0xFFC0030C  /* RTC Stopwatch Count Register */
-#define	RTC_ALARM	0xFFC00310  /* RTC Alarm Time Register */
-#define	RTC_FAST	0xFFC00314  /* RTC Prescaler Enable Register */
-#define	RTC_PREN		0xFFC00314  /* RTC Prescaler Enable Register (alternate	macro) */
-
-
-/* UART0 Controller (0xFFC00400	- 0xFFC004FF) */
-#define	UART0_THR	      0xFFC00400  /* Transmit Holding register */
-#define	UART0_RBR	      0xFFC00400  /* Receive Buffer register */
-#define	UART0_DLL	      0xFFC00400  /* Divisor Latch (Low-Byte) */
-#define	UART0_IER	      0xFFC00404  /* Interrupt Enable Register */
-#define	UART0_DLH	      0xFFC00404  /* Divisor Latch (High-Byte) */
-#define	UART0_IIR	      0xFFC00408  /* Interrupt Identification Register */
-#define	UART0_LCR	      0xFFC0040C  /* Line Control Register */
-#define	UART0_MCR			 0xFFC00410  /*	Modem Control Register */
-#define	UART0_LSR	      0xFFC00414  /* Line Status Register */
-#define	UART0_SCR	      0xFFC0041C  /* SCR Scratch Register */
-#define	UART0_GCTL		     0xFFC00424	 /* Global Control Register */
-
-
-/* SPI0	Controller (0xFFC00500 - 0xFFC005FF) */
-
-#define	SPI0_CTL			0xFFC00500  /* SPI0 Control Register */
-#define	SPI0_FLG			0xFFC00504  /* SPI0 Flag register */
-#define	SPI0_STAT			0xFFC00508  /* SPI0 Status register */
-#define	SPI0_TDBR			0xFFC0050C  /* SPI0 Transmit Data Buffer Register */
-#define	SPI0_RDBR			0xFFC00510  /* SPI0 Receive Data Buffer	Register */
-#define	SPI0_BAUD			0xFFC00514  /* SPI0 Baud rate Register */
-#define	SPI0_SHADOW			0xFFC00518  /* SPI0_RDBR Shadow	Register */
-#define SPI0_REGBASE			SPI0_CTL
-
-
-/* TIMER 0, 1, 2 Registers (0xFFC00600 - 0xFFC006FF) */
-#define	TIMER0_CONFIG			0xFFC00600     /* Timer	0 Configuration	Register */
-#define	TIMER0_COUNTER				0xFFC00604     /* Timer	0 Counter Register */
-#define	TIMER0_PERIOD			0xFFC00608     /* Timer	0 Period Register */
-#define	TIMER0_WIDTH			0xFFC0060C     /* Timer	0 Width	Register */
-
-#define	TIMER1_CONFIG			0xFFC00610	/*  Timer 1 Configuration Register   */
-#define	TIMER1_COUNTER			0xFFC00614	/*  Timer 1 Counter Register	     */
-#define	TIMER1_PERIOD			0xFFC00618	/*  Timer 1 Period Register	     */
-#define	TIMER1_WIDTH			0xFFC0061C	/*  Timer 1 Width Register	     */
-
-#define	TIMER2_CONFIG			0xFFC00620	/* Timer 2 Configuration Register   */
-#define	TIMER2_COUNTER			0xFFC00624	/* Timer 2 Counter Register	    */
-#define	TIMER2_PERIOD			0xFFC00628	/* Timer 2 Period Register	    */
-#define	TIMER2_WIDTH			0xFFC0062C	/* Timer 2 Width Register	    */
-
-#define	TIMER_ENABLE				0xFFC00640	/* Timer Enable	Register */
-#define	TIMER_DISABLE				0xFFC00644	/* Timer Disable Register */
-#define	TIMER_STATUS				0xFFC00648	/* Timer Status	Register */
-
-
-/* Programmable	Flags (0xFFC00700 - 0xFFC007FF) */
-#define	FIO_FLAG_D				0xFFC00700  /* Flag Mask to directly specify state of pins */
-#define	FIO_FLAG_C			0xFFC00704  /* Peripheral Interrupt Flag Register (clear) */
-#define	FIO_FLAG_S			0xFFC00708  /* Peripheral Interrupt Flag Register (set) */
-#define	FIO_FLAG_T					0xFFC0070C  /* Flag Mask to directly toggle state of pins */
-#define	FIO_MASKA_D			0xFFC00710  /* Flag Mask Interrupt A Register (set directly) */
-#define	FIO_MASKA_C			0xFFC00714  /* Flag Mask Interrupt A Register (clear) */
-#define	FIO_MASKA_S			0xFFC00718  /* Flag Mask Interrupt A Register (set) */
-#define	FIO_MASKA_T			0xFFC0071C  /* Flag Mask Interrupt A Register (toggle) */
-#define	FIO_MASKB_D			0xFFC00720  /* Flag Mask Interrupt B Register (set directly) */
-#define	FIO_MASKB_C			0xFFC00724  /* Flag Mask Interrupt B Register (clear) */
-#define	FIO_MASKB_S			0xFFC00728  /* Flag Mask Interrupt B Register (set) */
-#define	FIO_MASKB_T			0xFFC0072C  /* Flag Mask Interrupt B Register (toggle) */
-#define	FIO_DIR				0xFFC00730  /* Peripheral Flag Direction Register */
-#define	FIO_POLAR			0xFFC00734  /* Flag Source Polarity Register */
-#define	FIO_EDGE			0xFFC00738  /* Flag Source Sensitivity Register */
-#define	FIO_BOTH			0xFFC0073C  /* Flag Set	on BOTH	Edges Register */
-#define	FIO_INEN					0xFFC00740  /* Flag Input Enable Register  */
-
-
-/* SPORT0 Controller (0xFFC00800 - 0xFFC008FF) */
-#define	SPORT0_TCR1				0xFFC00800  /* SPORT0 Transmit Configuration 1 Register */
-#define	SPORT0_TCR2				0xFFC00804  /* SPORT0 Transmit Configuration 2 Register */
-#define	SPORT0_TCLKDIV			0xFFC00808  /* SPORT0 Transmit Clock Divider */
-#define	SPORT0_TFSDIV			0xFFC0080C  /* SPORT0 Transmit Frame Sync Divider */
-#define	SPORT0_TX			0xFFC00810  /* SPORT0 TX Data Register */
-#define	SPORT0_RX			0xFFC00818  /* SPORT0 RX Data Register */
-#define	SPORT0_RCR1				0xFFC00820  /* SPORT0 Transmit Configuration 1 Register */
-#define	SPORT0_RCR2				0xFFC00824  /* SPORT0 Transmit Configuration 2 Register */
-#define	SPORT0_RCLKDIV			0xFFC00828  /* SPORT0 Receive Clock Divider */
-#define	SPORT0_RFSDIV			0xFFC0082C  /* SPORT0 Receive Frame Sync Divider */
-#define	SPORT0_STAT			0xFFC00830  /* SPORT0 Status Register */
-#define	SPORT0_CHNL			0xFFC00834  /* SPORT0 Current Channel Register */
-#define	SPORT0_MCMC1			0xFFC00838  /* SPORT0 Multi-Channel Configuration Register 1 */
-#define	SPORT0_MCMC2			0xFFC0083C  /* SPORT0 Multi-Channel Configuration Register 2 */
-#define	SPORT0_MTCS0			0xFFC00840  /* SPORT0 Multi-Channel Transmit Select Register 0 */
-#define	SPORT0_MTCS1			0xFFC00844  /* SPORT0 Multi-Channel Transmit Select Register 1 */
-#define	SPORT0_MTCS2			0xFFC00848  /* SPORT0 Multi-Channel Transmit Select Register 2 */
-#define	SPORT0_MTCS3			0xFFC0084C  /* SPORT0 Multi-Channel Transmit Select Register 3 */
-#define	SPORT0_MRCS0			0xFFC00850  /* SPORT0 Multi-Channel Receive Select Register 0 */
-#define	SPORT0_MRCS1			0xFFC00854  /* SPORT0 Multi-Channel Receive Select Register 1 */
-#define	SPORT0_MRCS2			0xFFC00858  /* SPORT0 Multi-Channel Receive Select Register 2 */
-#define	SPORT0_MRCS3			0xFFC0085C  /* SPORT0 Multi-Channel Receive Select Register 3 */
-
-
-/* SPORT1 Controller (0xFFC00900 - 0xFFC009FF) */
-#define	SPORT1_TCR1				0xFFC00900  /* SPORT1 Transmit Configuration 1 Register */
-#define	SPORT1_TCR2				0xFFC00904  /* SPORT1 Transmit Configuration 2 Register */
-#define	SPORT1_TCLKDIV			0xFFC00908  /* SPORT1 Transmit Clock Divider */
-#define	SPORT1_TFSDIV			0xFFC0090C  /* SPORT1 Transmit Frame Sync Divider */
-#define	SPORT1_TX			0xFFC00910  /* SPORT1 TX Data Register */
-#define	SPORT1_RX			0xFFC00918  /* SPORT1 RX Data Register */
-#define	SPORT1_RCR1				0xFFC00920  /* SPORT1 Transmit Configuration 1 Register */
-#define	SPORT1_RCR2				0xFFC00924  /* SPORT1 Transmit Configuration 2 Register */
-#define	SPORT1_RCLKDIV			0xFFC00928  /* SPORT1 Receive Clock Divider */
-#define	SPORT1_RFSDIV			0xFFC0092C  /* SPORT1 Receive Frame Sync Divider */
-#define	SPORT1_STAT			0xFFC00930  /* SPORT1 Status Register */
-#define	SPORT1_CHNL			0xFFC00934  /* SPORT1 Current Channel Register */
-#define	SPORT1_MCMC1			0xFFC00938  /* SPORT1 Multi-Channel Configuration Register 1 */
-#define	SPORT1_MCMC2			0xFFC0093C  /* SPORT1 Multi-Channel Configuration Register 2 */
-#define	SPORT1_MTCS0			0xFFC00940  /* SPORT1 Multi-Channel Transmit Select Register 0 */
-#define	SPORT1_MTCS1			0xFFC00944  /* SPORT1 Multi-Channel Transmit Select Register 1 */
-#define	SPORT1_MTCS2			0xFFC00948  /* SPORT1 Multi-Channel Transmit Select Register 2 */
-#define	SPORT1_MTCS3			0xFFC0094C  /* SPORT1 Multi-Channel Transmit Select Register 3 */
-#define	SPORT1_MRCS0			0xFFC00950  /* SPORT1 Multi-Channel Receive Select Register 0 */
-#define	SPORT1_MRCS1			0xFFC00954  /* SPORT1 Multi-Channel Receive Select Register 1 */
-#define	SPORT1_MRCS2			0xFFC00958  /* SPORT1 Multi-Channel Receive Select Register 2 */
-#define	SPORT1_MRCS3			0xFFC0095C  /* SPORT1 Multi-Channel Receive Select Register 3 */
-
-
-/* External Bus	Interface Unit (0xFFC00A00 - 0xFFC00AFF) */
-/* Asynchronous	Memory Controller  */
-#define	EBIU_AMGCTL			0xFFC00A00  /* Asynchronous Memory Global Control Register */
-#define	EBIU_AMBCTL0		0xFFC00A04  /* Asynchronous Memory Bank	Control	Register 0 */
-#define	EBIU_AMBCTL1		0xFFC00A08  /* Asynchronous Memory Bank	Control	Register 1 */
-
-/* SDRAM Controller */
-#define	EBIU_SDGCTL			0xFFC00A10  /* SDRAM Global Control Register */
-#define	EBIU_SDBCTL			0xFFC00A14  /* SDRAM Bank Control Register */
-#define	EBIU_SDRRC			0xFFC00A18  /* SDRAM Refresh Rate Control Register */
-#define	EBIU_SDSTAT			0xFFC00A1C  /* SDRAM Status Register */
-
-
-
-/* DMA Controller 0 Traffic Control Registers (0xFFC00B00 - 0xFFC00BFF) */
-
-#define	DMAC0_TC_PER			0xFFC00B0C	/* DMA Controller 0 Traffic Control Periods Register */
-#define	DMAC0_TC_CNT			0xFFC00B10	/* DMA Controller 0 Traffic Control Current Counts Register */
-
-/* Alternate deprecated	register names (below) provided	for backwards code compatibility */
-#define	DMA0_TCPER			DMAC0_TC_PER
-#define	DMA0_TCCNT			DMAC0_TC_CNT
-
-
-/* DMA Controller 0 (0xFFC00C00	- 0xFFC00FFF)							 */
-
-#define	DMA0_NEXT_DESC_PTR		0xFFC00C00	/* DMA Channel 0 Next Descriptor Pointer Register */
-#define	DMA0_START_ADDR			0xFFC00C04	/* DMA Channel 0 Start Address Register */
-#define	DMA0_CONFIG				0xFFC00C08	/* DMA Channel 0 Configuration Register */
-#define	DMA0_X_COUNT			0xFFC00C10	/* DMA Channel 0 X Count Register */
-#define	DMA0_X_MODIFY			0xFFC00C14	/* DMA Channel 0 X Modify Register */
-#define	DMA0_Y_COUNT			0xFFC00C18	/* DMA Channel 0 Y Count Register */
-#define	DMA0_Y_MODIFY			0xFFC00C1C	/* DMA Channel 0 Y Modify Register */
-#define	DMA0_CURR_DESC_PTR		0xFFC00C20	/* DMA Channel 0 Current Descriptor Pointer Register */
-#define	DMA0_CURR_ADDR			0xFFC00C24	/* DMA Channel 0 Current Address Register */
-#define	DMA0_IRQ_STATUS			0xFFC00C28	/* DMA Channel 0 Interrupt/Status Register */
-#define	DMA0_PERIPHERAL_MAP		0xFFC00C2C	/* DMA Channel 0 Peripheral Map	Register */
-#define	DMA0_CURR_X_COUNT		0xFFC00C30	/* DMA Channel 0 Current X Count Register */
-#define	DMA0_CURR_Y_COUNT		0xFFC00C38	/* DMA Channel 0 Current Y Count Register */
-
-#define	DMA1_NEXT_DESC_PTR		0xFFC00C40	/* DMA Channel 1 Next Descriptor Pointer Register */
-#define	DMA1_START_ADDR			0xFFC00C44	/* DMA Channel 1 Start Address Register */
-#define	DMA1_CONFIG				0xFFC00C48	/* DMA Channel 1 Configuration Register */
-#define	DMA1_X_COUNT			0xFFC00C50	/* DMA Channel 1 X Count Register */
-#define	DMA1_X_MODIFY			0xFFC00C54	/* DMA Channel 1 X Modify Register */
-#define	DMA1_Y_COUNT			0xFFC00C58	/* DMA Channel 1 Y Count Register */
-#define	DMA1_Y_MODIFY			0xFFC00C5C	/* DMA Channel 1 Y Modify Register */
-#define	DMA1_CURR_DESC_PTR		0xFFC00C60	/* DMA Channel 1 Current Descriptor Pointer Register */
-#define	DMA1_CURR_ADDR			0xFFC00C64	/* DMA Channel 1 Current Address Register */
-#define	DMA1_IRQ_STATUS			0xFFC00C68	/* DMA Channel 1 Interrupt/Status Register */
-#define	DMA1_PERIPHERAL_MAP		0xFFC00C6C	/* DMA Channel 1 Peripheral Map	Register */
-#define	DMA1_CURR_X_COUNT		0xFFC00C70	/* DMA Channel 1 Current X Count Register */
-#define	DMA1_CURR_Y_COUNT		0xFFC00C78	/* DMA Channel 1 Current Y Count Register */
-
-#define	DMA2_NEXT_DESC_PTR		0xFFC00C80	/* DMA Channel 2 Next Descriptor Pointer Register */
-#define	DMA2_START_ADDR			0xFFC00C84	/* DMA Channel 2 Start Address Register */
-#define	DMA2_CONFIG				0xFFC00C88	/* DMA Channel 2 Configuration Register */
-#define	DMA2_X_COUNT			0xFFC00C90	/* DMA Channel 2 X Count Register */
-#define	DMA2_X_MODIFY			0xFFC00C94	/* DMA Channel 2 X Modify Register */
-#define	DMA2_Y_COUNT			0xFFC00C98	/* DMA Channel 2 Y Count Register */
-#define	DMA2_Y_MODIFY			0xFFC00C9C	/* DMA Channel 2 Y Modify Register */
-#define	DMA2_CURR_DESC_PTR		0xFFC00CA0	/* DMA Channel 2 Current Descriptor Pointer Register */
-#define	DMA2_CURR_ADDR			0xFFC00CA4	/* DMA Channel 2 Current Address Register */
-#define	DMA2_IRQ_STATUS			0xFFC00CA8	/* DMA Channel 2 Interrupt/Status Register */
-#define	DMA2_PERIPHERAL_MAP		0xFFC00CAC	/* DMA Channel 2 Peripheral Map	Register */
-#define	DMA2_CURR_X_COUNT		0xFFC00CB0	/* DMA Channel 2 Current X Count Register */
-#define	DMA2_CURR_Y_COUNT		0xFFC00CB8	/* DMA Channel 2 Current Y Count Register */
-
-#define	DMA3_NEXT_DESC_PTR		0xFFC00CC0	/* DMA Channel 3 Next Descriptor Pointer Register */
-#define	DMA3_START_ADDR			0xFFC00CC4	/* DMA Channel 3 Start Address Register */
-#define	DMA3_CONFIG				0xFFC00CC8	/* DMA Channel 3 Configuration Register */
-#define	DMA3_X_COUNT			0xFFC00CD0	/* DMA Channel 3 X Count Register */
-#define	DMA3_X_MODIFY			0xFFC00CD4	/* DMA Channel 3 X Modify Register */
-#define	DMA3_Y_COUNT			0xFFC00CD8	/* DMA Channel 3 Y Count Register */
-#define	DMA3_Y_MODIFY			0xFFC00CDC	/* DMA Channel 3 Y Modify Register */
-#define	DMA3_CURR_DESC_PTR		0xFFC00CE0	/* DMA Channel 3 Current Descriptor Pointer Register */
-#define	DMA3_CURR_ADDR			0xFFC00CE4	/* DMA Channel 3 Current Address Register */
-#define	DMA3_IRQ_STATUS			0xFFC00CE8	/* DMA Channel 3 Interrupt/Status Register */
-#define	DMA3_PERIPHERAL_MAP		0xFFC00CEC	/* DMA Channel 3 Peripheral Map	Register */
-#define	DMA3_CURR_X_COUNT		0xFFC00CF0	/* DMA Channel 3 Current X Count Register */
-#define	DMA3_CURR_Y_COUNT		0xFFC00CF8	/* DMA Channel 3 Current Y Count Register */
-
-#define	DMA4_NEXT_DESC_PTR		0xFFC00D00	/* DMA Channel 4 Next Descriptor Pointer Register */
-#define	DMA4_START_ADDR			0xFFC00D04	/* DMA Channel 4 Start Address Register */
-#define	DMA4_CONFIG				0xFFC00D08	/* DMA Channel 4 Configuration Register */
-#define	DMA4_X_COUNT			0xFFC00D10	/* DMA Channel 4 X Count Register */
-#define	DMA4_X_MODIFY			0xFFC00D14	/* DMA Channel 4 X Modify Register */
-#define	DMA4_Y_COUNT			0xFFC00D18	/* DMA Channel 4 Y Count Register */
-#define	DMA4_Y_MODIFY			0xFFC00D1C	/* DMA Channel 4 Y Modify Register */
-#define	DMA4_CURR_DESC_PTR		0xFFC00D20	/* DMA Channel 4 Current Descriptor Pointer Register */
-#define	DMA4_CURR_ADDR			0xFFC00D24	/* DMA Channel 4 Current Address Register */
-#define	DMA4_IRQ_STATUS			0xFFC00D28	/* DMA Channel 4 Interrupt/Status Register */
-#define	DMA4_PERIPHERAL_MAP		0xFFC00D2C	/* DMA Channel 4 Peripheral Map	Register */
-#define	DMA4_CURR_X_COUNT		0xFFC00D30	/* DMA Channel 4 Current X Count Register */
-#define	DMA4_CURR_Y_COUNT		0xFFC00D38	/* DMA Channel 4 Current Y Count Register */
-
-#define	DMA5_NEXT_DESC_PTR		0xFFC00D40	/* DMA Channel 5 Next Descriptor Pointer Register */
-#define	DMA5_START_ADDR			0xFFC00D44	/* DMA Channel 5 Start Address Register */
-#define	DMA5_CONFIG				0xFFC00D48	/* DMA Channel 5 Configuration Register */
-#define	DMA5_X_COUNT			0xFFC00D50	/* DMA Channel 5 X Count Register */
-#define	DMA5_X_MODIFY			0xFFC00D54	/* DMA Channel 5 X Modify Register */
-#define	DMA5_Y_COUNT			0xFFC00D58	/* DMA Channel 5 Y Count Register */
-#define	DMA5_Y_MODIFY			0xFFC00D5C	/* DMA Channel 5 Y Modify Register */
-#define	DMA5_CURR_DESC_PTR		0xFFC00D60	/* DMA Channel 5 Current Descriptor Pointer Register */
-#define	DMA5_CURR_ADDR			0xFFC00D64	/* DMA Channel 5 Current Address Register */
-#define	DMA5_IRQ_STATUS			0xFFC00D68	/* DMA Channel 5 Interrupt/Status Register */
-#define	DMA5_PERIPHERAL_MAP		0xFFC00D6C	/* DMA Channel 5 Peripheral Map	Register */
-#define	DMA5_CURR_X_COUNT		0xFFC00D70	/* DMA Channel 5 Current X Count Register */
-#define	DMA5_CURR_Y_COUNT		0xFFC00D78	/* DMA Channel 5 Current Y Count Register */
-
-#define	DMA6_NEXT_DESC_PTR		0xFFC00D80	/* DMA Channel 6 Next Descriptor Pointer Register */
-#define	DMA6_START_ADDR			0xFFC00D84	/* DMA Channel 6 Start Address Register */
-#define	DMA6_CONFIG				0xFFC00D88	/* DMA Channel 6 Configuration Register */
-#define	DMA6_X_COUNT			0xFFC00D90	/* DMA Channel 6 X Count Register */
-#define	DMA6_X_MODIFY			0xFFC00D94	/* DMA Channel 6 X Modify Register */
-#define	DMA6_Y_COUNT			0xFFC00D98	/* DMA Channel 6 Y Count Register */
-#define	DMA6_Y_MODIFY			0xFFC00D9C	/* DMA Channel 6 Y Modify Register */
-#define	DMA6_CURR_DESC_PTR		0xFFC00DA0	/* DMA Channel 6 Current Descriptor Pointer Register */
-#define	DMA6_CURR_ADDR			0xFFC00DA4	/* DMA Channel 6 Current Address Register */
-#define	DMA6_IRQ_STATUS			0xFFC00DA8	/* DMA Channel 6 Interrupt/Status Register */
-#define	DMA6_PERIPHERAL_MAP		0xFFC00DAC	/* DMA Channel 6 Peripheral Map	Register */
-#define	DMA6_CURR_X_COUNT		0xFFC00DB0	/* DMA Channel 6 Current X Count Register */
-#define	DMA6_CURR_Y_COUNT		0xFFC00DB8	/* DMA Channel 6 Current Y Count Register */
-
-#define	DMA7_NEXT_DESC_PTR		0xFFC00DC0	/* DMA Channel 7 Next Descriptor Pointer Register */
-#define	DMA7_START_ADDR			0xFFC00DC4	/* DMA Channel 7 Start Address Register */
-#define	DMA7_CONFIG				0xFFC00DC8	/* DMA Channel 7 Configuration Register */
-#define	DMA7_X_COUNT			0xFFC00DD0	/* DMA Channel 7 X Count Register */
-#define	DMA7_X_MODIFY			0xFFC00DD4	/* DMA Channel 7 X Modify Register */
-#define	DMA7_Y_COUNT			0xFFC00DD8	/* DMA Channel 7 Y Count Register */
-#define	DMA7_Y_MODIFY			0xFFC00DDC	/* DMA Channel 7 Y Modify Register */
-#define	DMA7_CURR_DESC_PTR		0xFFC00DE0	/* DMA Channel 7 Current Descriptor Pointer Register */
-#define	DMA7_CURR_ADDR			0xFFC00DE4	/* DMA Channel 7 Current Address Register */
-#define	DMA7_IRQ_STATUS			0xFFC00DE8	/* DMA Channel 7 Interrupt/Status Register */
-#define	DMA7_PERIPHERAL_MAP		0xFFC00DEC	/* DMA Channel 7 Peripheral Map	Register */
-#define	DMA7_CURR_X_COUNT		0xFFC00DF0	/* DMA Channel 7 Current X Count Register */
-#define	DMA7_CURR_Y_COUNT		0xFFC00DF8	/* DMA Channel 7 Current Y Count Register */
-
-#define	MDMA0_D0_NEXT_DESC_PTR	0xFFC00E00	/* MemDMA0 Stream 0 Destination	Next Descriptor	Pointer	Register */
-#define	MDMA0_D0_START_ADDR		0xFFC00E04	/* MemDMA0 Stream 0 Destination	Start Address Register */
-#define	MDMA0_D0_CONFIG			0xFFC00E08	/* MemDMA0 Stream 0 Destination	Configuration Register */
-#define	MDMA0_D0_X_COUNT		0xFFC00E10	/* MemDMA0 Stream 0 Destination	X Count	Register */
-#define	MDMA0_D0_X_MODIFY		0xFFC00E14	/* MemDMA0 Stream 0 Destination	X Modify Register */
-#define	MDMA0_D0_Y_COUNT		0xFFC00E18	/* MemDMA0 Stream 0 Destination	Y Count	Register */
-#define	MDMA0_D0_Y_MODIFY		0xFFC00E1C	/* MemDMA0 Stream 0 Destination	Y Modify Register */
-#define	MDMA0_D0_CURR_DESC_PTR	0xFFC00E20	/* MemDMA0 Stream 0 Destination	Current	Descriptor Pointer Register */
-#define	MDMA0_D0_CURR_ADDR		0xFFC00E24	/* MemDMA0 Stream 0 Destination	Current	Address	Register */
-#define	MDMA0_D0_IRQ_STATUS		0xFFC00E28	/* MemDMA0 Stream 0 Destination	Interrupt/Status Register */
-#define	MDMA0_D0_PERIPHERAL_MAP	0xFFC00E2C	/* MemDMA0 Stream 0 Destination	Peripheral Map Register */
-#define	MDMA0_D0_CURR_X_COUNT	0xFFC00E30	/* MemDMA0 Stream 0 Destination	Current	X Count	Register */
-#define	MDMA0_D0_CURR_Y_COUNT	0xFFC00E38	/* MemDMA0 Stream 0 Destination	Current	Y Count	Register */
-
-#define	MDMA0_S0_NEXT_DESC_PTR	0xFFC00E40	/* MemDMA0 Stream 0 Source Next	Descriptor Pointer Register */
-#define	MDMA0_S0_START_ADDR		0xFFC00E44	/* MemDMA0 Stream 0 Source Start Address Register */
-#define	MDMA0_S0_CONFIG			0xFFC00E48	/* MemDMA0 Stream 0 Source Configuration Register */
-#define	MDMA0_S0_X_COUNT		0xFFC00E50	/* MemDMA0 Stream 0 Source X Count Register */
-#define	MDMA0_S0_X_MODIFY		0xFFC00E54	/* MemDMA0 Stream 0 Source X Modify Register */
-#define	MDMA0_S0_Y_COUNT		0xFFC00E58	/* MemDMA0 Stream 0 Source Y Count Register */
-#define	MDMA0_S0_Y_MODIFY		0xFFC00E5C	/* MemDMA0 Stream 0 Source Y Modify Register */
-#define	MDMA0_S0_CURR_DESC_PTR	0xFFC00E60	/* MemDMA0 Stream 0 Source Current Descriptor Pointer Register */
-#define	MDMA0_S0_CURR_ADDR		0xFFC00E64	/* MemDMA0 Stream 0 Source Current Address Register */
-#define	MDMA0_S0_IRQ_STATUS		0xFFC00E68	/* MemDMA0 Stream 0 Source Interrupt/Status Register */
-#define	MDMA0_S0_PERIPHERAL_MAP	0xFFC00E6C	/* MemDMA0 Stream 0 Source Peripheral Map Register */
-#define	MDMA0_S0_CURR_X_COUNT	0xFFC00E70	/* MemDMA0 Stream 0 Source Current X Count Register */
-#define	MDMA0_S0_CURR_Y_COUNT	0xFFC00E78	/* MemDMA0 Stream 0 Source Current Y Count Register */
-
-#define	MDMA0_D1_NEXT_DESC_PTR	0xFFC00E80	/* MemDMA0 Stream 1 Destination	Next Descriptor	Pointer	Register */
-#define	MDMA0_D1_START_ADDR		0xFFC00E84	/* MemDMA0 Stream 1 Destination	Start Address Register */
-#define	MDMA0_D1_CONFIG			0xFFC00E88	/* MemDMA0 Stream 1 Destination	Configuration Register */
-#define	MDMA0_D1_X_COUNT		0xFFC00E90	/* MemDMA0 Stream 1 Destination	X Count	Register */
-#define	MDMA0_D1_X_MODIFY		0xFFC00E94	/* MemDMA0 Stream 1 Destination	X Modify Register */
-#define	MDMA0_D1_Y_COUNT		0xFFC00E98	/* MemDMA0 Stream 1 Destination	Y Count	Register */
-#define	MDMA0_D1_Y_MODIFY		0xFFC00E9C	/* MemDMA0 Stream 1 Destination	Y Modify Register */
-#define	MDMA0_D1_CURR_DESC_PTR	0xFFC00EA0	/* MemDMA0 Stream 1 Destination	Current	Descriptor Pointer Register */
-#define	MDMA0_D1_CURR_ADDR		0xFFC00EA4	/* MemDMA0 Stream 1 Destination	Current	Address	Register */
-#define	MDMA0_D1_IRQ_STATUS		0xFFC00EA8	/* MemDMA0 Stream 1 Destination	Interrupt/Status Register */
-#define	MDMA0_D1_PERIPHERAL_MAP	0xFFC00EAC	/* MemDMA0 Stream 1 Destination	Peripheral Map Register */
-#define	MDMA0_D1_CURR_X_COUNT	0xFFC00EB0	/* MemDMA0 Stream 1 Destination	Current	X Count	Register */
-#define	MDMA0_D1_CURR_Y_COUNT	0xFFC00EB8	/* MemDMA0 Stream 1 Destination	Current	Y Count	Register */
-
-#define	MDMA0_S1_NEXT_DESC_PTR	0xFFC00EC0	/* MemDMA0 Stream 1 Source Next	Descriptor Pointer Register */
-#define	MDMA0_S1_START_ADDR		0xFFC00EC4	/* MemDMA0 Stream 1 Source Start Address Register */
-#define	MDMA0_S1_CONFIG			0xFFC00EC8	/* MemDMA0 Stream 1 Source Configuration Register */
-#define	MDMA0_S1_X_COUNT		0xFFC00ED0	/* MemDMA0 Stream 1 Source X Count Register */
-#define	MDMA0_S1_X_MODIFY		0xFFC00ED4	/* MemDMA0 Stream 1 Source X Modify Register */
-#define	MDMA0_S1_Y_COUNT		0xFFC00ED8	/* MemDMA0 Stream 1 Source Y Count Register */
-#define	MDMA0_S1_Y_MODIFY		0xFFC00EDC	/* MemDMA0 Stream 1 Source Y Modify Register */
-#define	MDMA0_S1_CURR_DESC_PTR	0xFFC00EE0	/* MemDMA0 Stream 1 Source Current Descriptor Pointer Register */
-#define	MDMA0_S1_CURR_ADDR		0xFFC00EE4	/* MemDMA0 Stream 1 Source Current Address Register */
-#define	MDMA0_S1_IRQ_STATUS		0xFFC00EE8	/* MemDMA0 Stream 1 Source Interrupt/Status Register */
-#define	MDMA0_S1_PERIPHERAL_MAP	0xFFC00EEC	/* MemDMA0 Stream 1 Source Peripheral Map Register */
-#define	MDMA0_S1_CURR_X_COUNT	0xFFC00EF0	/* MemDMA0 Stream 1 Source Current X Count Register */
-#define	MDMA0_S1_CURR_Y_COUNT	0xFFC00EF8	/* MemDMA0 Stream 1 Source Current Y Count Register */
-
-#define MDMA_D0_NEXT_DESC_PTR MDMA0_D0_NEXT_DESC_PTR
-#define MDMA_D0_START_ADDR MDMA0_D0_START_ADDR
-#define MDMA_D0_CONFIG MDMA0_D0_CONFIG
-#define MDMA_D0_X_COUNT MDMA0_D0_X_COUNT
-#define MDMA_D0_X_MODIFY MDMA0_D0_X_MODIFY
-#define MDMA_D0_Y_COUNT MDMA0_D0_Y_COUNT
-#define MDMA_D0_Y_MODIFY MDMA0_D0_Y_MODIFY
-#define MDMA_D0_CURR_DESC_PTR MDMA0_D0_CURR_DESC_PTR
-#define MDMA_D0_CURR_ADDR MDMA0_D0_CURR_ADDR
-#define MDMA_D0_IRQ_STATUS MDMA0_D0_IRQ_STATUS
-#define MDMA_D0_PERIPHERAL_MAP MDMA0_D0_PERIPHERAL_MAP
-#define MDMA_D0_CURR_X_COUNT MDMA0_D0_CURR_X_COUNT
-#define MDMA_D0_CURR_Y_COUNT MDMA0_D0_CURR_Y_COUNT
-
-#define MDMA_S0_NEXT_DESC_PTR MDMA0_S0_NEXT_DESC_PTR
-#define MDMA_S0_START_ADDR MDMA0_S0_START_ADDR
-#define MDMA_S0_CONFIG MDMA0_S0_CONFIG
-#define MDMA_S0_X_COUNT MDMA0_S0_X_COUNT
-#define MDMA_S0_X_MODIFY MDMA0_S0_X_MODIFY
-#define MDMA_S0_Y_COUNT MDMA0_S0_Y_COUNT
-#define MDMA_S0_Y_MODIFY MDMA0_S0_Y_MODIFY
-#define MDMA_S0_CURR_DESC_PTR MDMA0_S0_CURR_DESC_PTR
-#define MDMA_S0_CURR_ADDR MDMA0_S0_CURR_ADDR
-#define MDMA_S0_IRQ_STATUS MDMA0_S0_IRQ_STATUS
-#define MDMA_S0_PERIPHERAL_MAP MDMA0_S0_PERIPHERAL_MAP
-#define MDMA_S0_CURR_X_COUNT MDMA0_S0_CURR_X_COUNT
-#define MDMA_S0_CURR_Y_COUNT MDMA0_S0_CURR_Y_COUNT
-
-#define MDMA_D1_NEXT_DESC_PTR MDMA0_D1_NEXT_DESC_PTR
-#define MDMA_D1_START_ADDR MDMA0_D1_START_ADDR
-#define MDMA_D1_CONFIG MDMA0_D1_CONFIG
-#define MDMA_D1_X_COUNT MDMA0_D1_X_COUNT
-#define MDMA_D1_X_MODIFY MDMA0_D1_X_MODIFY
-#define MDMA_D1_Y_COUNT MDMA0_D1_Y_COUNT
-#define MDMA_D1_Y_MODIFY MDMA0_D1_Y_MODIFY
-#define MDMA_D1_CURR_DESC_PTR MDMA0_D1_CURR_DESC_PTR
-#define MDMA_D1_CURR_ADDR MDMA0_D1_CURR_ADDR
-#define MDMA_D1_IRQ_STATUS MDMA0_D1_IRQ_STATUS
-#define MDMA_D1_PERIPHERAL_MAP MDMA0_D1_PERIPHERAL_MAP
-#define MDMA_D1_CURR_X_COUNT MDMA0_D1_CURR_X_COUNT
-#define MDMA_D1_CURR_Y_COUNT MDMA0_D1_CURR_Y_COUNT
-
-#define MDMA_S1_NEXT_DESC_PTR MDMA0_S1_NEXT_DESC_PTR
-#define MDMA_S1_START_ADDR MDMA0_S1_START_ADDR
-#define MDMA_S1_CONFIG MDMA0_S1_CONFIG
-#define MDMA_S1_X_COUNT MDMA0_S1_X_COUNT
-#define MDMA_S1_X_MODIFY MDMA0_S1_X_MODIFY
-#define MDMA_S1_Y_COUNT MDMA0_S1_Y_COUNT
-#define MDMA_S1_Y_MODIFY MDMA0_S1_Y_MODIFY
-#define MDMA_S1_CURR_DESC_PTR MDMA0_S1_CURR_DESC_PTR
-#define MDMA_S1_CURR_ADDR MDMA0_S1_CURR_ADDR
-#define MDMA_S1_IRQ_STATUS MDMA0_S1_IRQ_STATUS
-#define MDMA_S1_PERIPHERAL_MAP MDMA0_S1_PERIPHERAL_MAP
-#define MDMA_S1_CURR_X_COUNT MDMA0_S1_CURR_X_COUNT
-#define MDMA_S1_CURR_Y_COUNT MDMA0_S1_CURR_Y_COUNT
-
-
-/* Parallel Peripheral Interface (PPI) (0xFFC01000 - 0xFFC010FF) */
-#define	PPI_CONTROL			0xFFC01000	/* PPI Control Register */
-#define	PPI_STATUS			0xFFC01004	/* PPI Status Register */
-#define	PPI_COUNT			0xFFC01008	/* PPI Transfer	Count Register */
-#define	PPI_DELAY			0xFFC0100C	/* PPI Delay Count Register */
-#define	PPI_FRAME			0xFFC01010	/* PPI Frame Length Register */
-
-
-/* Two-Wire Interface 0	(0xFFC01400 - 0xFFC014FF)			 */
-#define	TWI0_CLKDIV			0xFFC01400	/* Serial Clock	Divider	Register */
-#define	TWI0_CONTROL		0xFFC01404	/* TWI0	Master Internal	Time Reference Register */
-#define	TWI0_SLAVE_CTL		0xFFC01408	/* Slave Mode Control Register */
-#define	TWI0_SLAVE_STAT		0xFFC0140C	/* Slave Mode Status Register */
-#define	TWI0_SLAVE_ADDR		0xFFC01410	/* Slave Mode Address Register */
-#define	TWI0_MASTER_CTL	0xFFC01414	/* Master Mode Control Register */
-#define	TWI0_MASTER_STAT	0xFFC01418	/* Master Mode Status Register */
-#define	TWI0_MASTER_ADDR	0xFFC0141C	/* Master Mode Address Register */
-#define	TWI0_INT_STAT		0xFFC01420	/* TWI0	Master Interrupt Register */
-#define	TWI0_INT_MASK		0xFFC01424	/* TWI0	Master Interrupt Mask Register */
-#define	TWI0_FIFO_CTL		0xFFC01428	/* FIFO	Control	Register */
-#define	TWI0_FIFO_STAT		0xFFC0142C	/* FIFO	Status Register */
-#define	TWI0_XMT_DATA8		0xFFC01480	/* FIFO	Transmit Data Single Byte Register */
-#define	TWI0_XMT_DATA16		0xFFC01484	/* FIFO	Transmit Data Double Byte Register */
-#define	TWI0_RCV_DATA8		0xFFC01488	/* FIFO	Receive	Data Single Byte Register */
-#define	TWI0_RCV_DATA16		0xFFC0148C	/* FIFO	Receive	Data Double Byte Register */
-
-#define TWI0_REGBASE		TWI0_CLKDIV
-
-/* the following are for backwards compatibility */
-#define	TWI0_PRESCALE	 TWI0_CONTROL
-#define	TWI0_INT_SRC	 TWI0_INT_STAT
-#define	TWI0_INT_ENABLE	 TWI0_INT_MASK
-
-
-/* General-Purpose Ports  (0xFFC01500 -	0xFFC015FF)	 */
-
-/* GPIO	Port C Register	Names */
-#define PORTCIO_FER			0xFFC01500	/* GPIO	Pin Port C Configuration Register */
-#define PORTCIO				0xFFC01510	/* GPIO	Pin Port C Data	Register */
-#define PORTCIO_CLEAR			0xFFC01520	/* Clear GPIO Pin Port C Register */
-#define PORTCIO_SET			0xFFC01530	/* Set GPIO Pin	Port C Register */
-#define PORTCIO_TOGGLE			0xFFC01540	/* Toggle GPIO Pin Port	C Register */
-#define PORTCIO_DIR			0xFFC01550	/* GPIO	Pin Port C Direction Register */
-#define PORTCIO_INEN			0xFFC01560	/* GPIO	Pin Port C Input Enable	Register */
-
-/* GPIO	Port D Register	Names */
-#define PORTDIO_FER			0xFFC01504	/* GPIO	Pin Port D Configuration Register */
-#define PORTDIO				0xFFC01514	/* GPIO	Pin Port D Data	Register */
-#define PORTDIO_CLEAR			0xFFC01524	/* Clear GPIO Pin Port D Register */
-#define PORTDIO_SET			0xFFC01534	/* Set GPIO Pin	Port D Register */
-#define PORTDIO_TOGGLE			0xFFC01544	/* Toggle GPIO Pin Port	D Register */
-#define PORTDIO_DIR			0xFFC01554	/* GPIO	Pin Port D Direction Register */
-#define PORTDIO_INEN			0xFFC01564	/* GPIO	Pin Port D Input Enable	Register */
-
-/* GPIO	Port E Register	Names */
-#define PORTEIO_FER			0xFFC01508	/* GPIO	Pin Port E Configuration Register */
-#define PORTEIO				0xFFC01518	/* GPIO	Pin Port E Data	Register */
-#define PORTEIO_CLEAR			0xFFC01528	/* Clear GPIO Pin Port E Register */
-#define PORTEIO_SET			0xFFC01538	/* Set GPIO Pin	Port E Register */
-#define PORTEIO_TOGGLE			0xFFC01548	/* Toggle GPIO Pin Port	E Register */
-#define PORTEIO_DIR			0xFFC01558	/* GPIO	Pin Port E Direction Register */
-#define PORTEIO_INEN			0xFFC01568	/* GPIO	Pin Port E Input Enable	Register */
-
-/* DMA Controller 1 Traffic Control Registers (0xFFC01B00 - 0xFFC01BFF) */
-
-#define	DMAC1_TC_PER			0xFFC01B0C	/* DMA Controller 1 Traffic Control Periods Register */
-#define	DMAC1_TC_CNT			0xFFC01B10	/* DMA Controller 1 Traffic Control Current Counts Register */
-
-/* Alternate deprecated	register names (below) provided	for backwards code compatibility */
-#define	DMA1_TCPER			DMAC1_TC_PER
-#define	DMA1_TCCNT			DMAC1_TC_CNT
-
-
-/* DMA Controller 1 (0xFFC01C00	- 0xFFC01FFF)							 */
-#define	DMA8_NEXT_DESC_PTR		0xFFC01C00	/* DMA Channel 8 Next Descriptor Pointer Register */
-#define	DMA8_START_ADDR			0xFFC01C04	/* DMA Channel 8 Start Address Register */
-#define	DMA8_CONFIG				0xFFC01C08	/* DMA Channel 8 Configuration Register */
-#define	DMA8_X_COUNT			0xFFC01C10	/* DMA Channel 8 X Count Register */
-#define	DMA8_X_MODIFY			0xFFC01C14	/* DMA Channel 8 X Modify Register */
-#define	DMA8_Y_COUNT			0xFFC01C18	/* DMA Channel 8 Y Count Register */
-#define	DMA8_Y_MODIFY			0xFFC01C1C	/* DMA Channel 8 Y Modify Register */
-#define	DMA8_CURR_DESC_PTR		0xFFC01C20	/* DMA Channel 8 Current Descriptor Pointer Register */
-#define	DMA8_CURR_ADDR			0xFFC01C24	/* DMA Channel 8 Current Address Register */
-#define	DMA8_IRQ_STATUS			0xFFC01C28	/* DMA Channel 8 Interrupt/Status Register */
-#define	DMA8_PERIPHERAL_MAP		0xFFC01C2C	/* DMA Channel 8 Peripheral Map	Register */
-#define	DMA8_CURR_X_COUNT		0xFFC01C30	/* DMA Channel 8 Current X Count Register */
-#define	DMA8_CURR_Y_COUNT		0xFFC01C38	/* DMA Channel 8 Current Y Count Register */
-
-#define	DMA9_NEXT_DESC_PTR		0xFFC01C40	/* DMA Channel 9 Next Descriptor Pointer Register */
-#define	DMA9_START_ADDR			0xFFC01C44	/* DMA Channel 9 Start Address Register */
-#define	DMA9_CONFIG				0xFFC01C48	/* DMA Channel 9 Configuration Register */
-#define	DMA9_X_COUNT			0xFFC01C50	/* DMA Channel 9 X Count Register */
-#define	DMA9_X_MODIFY			0xFFC01C54	/* DMA Channel 9 X Modify Register */
-#define	DMA9_Y_COUNT			0xFFC01C58	/* DMA Channel 9 Y Count Register */
-#define	DMA9_Y_MODIFY			0xFFC01C5C	/* DMA Channel 9 Y Modify Register */
-#define	DMA9_CURR_DESC_PTR		0xFFC01C60	/* DMA Channel 9 Current Descriptor Pointer Register */
-#define	DMA9_CURR_ADDR			0xFFC01C64	/* DMA Channel 9 Current Address Register */
-#define	DMA9_IRQ_STATUS			0xFFC01C68	/* DMA Channel 9 Interrupt/Status Register */
-#define	DMA9_PERIPHERAL_MAP		0xFFC01C6C	/* DMA Channel 9 Peripheral Map	Register */
-#define	DMA9_CURR_X_COUNT		0xFFC01C70	/* DMA Channel 9 Current X Count Register */
-#define	DMA9_CURR_Y_COUNT		0xFFC01C78	/* DMA Channel 9 Current Y Count Register */
-
-#define	DMA10_NEXT_DESC_PTR		0xFFC01C80	/* DMA Channel 10 Next Descriptor Pointer Register */
-#define	DMA10_START_ADDR		0xFFC01C84	/* DMA Channel 10 Start	Address	Register */
-#define	DMA10_CONFIG			0xFFC01C88	/* DMA Channel 10 Configuration	Register */
-#define	DMA10_X_COUNT			0xFFC01C90	/* DMA Channel 10 X Count Register */
-#define	DMA10_X_MODIFY			0xFFC01C94	/* DMA Channel 10 X Modify Register */
-#define	DMA10_Y_COUNT			0xFFC01C98	/* DMA Channel 10 Y Count Register */
-#define	DMA10_Y_MODIFY			0xFFC01C9C	/* DMA Channel 10 Y Modify Register */
-#define	DMA10_CURR_DESC_PTR		0xFFC01CA0	/* DMA Channel 10 Current Descriptor Pointer Register */
-#define	DMA10_CURR_ADDR			0xFFC01CA4	/* DMA Channel 10 Current Address Register */
-#define	DMA10_IRQ_STATUS		0xFFC01CA8	/* DMA Channel 10 Interrupt/Status Register */
-#define	DMA10_PERIPHERAL_MAP	0xFFC01CAC	/* DMA Channel 10 Peripheral Map Register */
-#define	DMA10_CURR_X_COUNT		0xFFC01CB0	/* DMA Channel 10 Current X Count Register */
-#define	DMA10_CURR_Y_COUNT		0xFFC01CB8	/* DMA Channel 10 Current Y Count Register */
-
-#define	DMA11_NEXT_DESC_PTR		0xFFC01CC0	/* DMA Channel 11 Next Descriptor Pointer Register */
-#define	DMA11_START_ADDR		0xFFC01CC4	/* DMA Channel 11 Start	Address	Register */
-#define	DMA11_CONFIG			0xFFC01CC8	/* DMA Channel 11 Configuration	Register */
-#define	DMA11_X_COUNT			0xFFC01CD0	/* DMA Channel 11 X Count Register */
-#define	DMA11_X_MODIFY			0xFFC01CD4	/* DMA Channel 11 X Modify Register */
-#define	DMA11_Y_COUNT			0xFFC01CD8	/* DMA Channel 11 Y Count Register */
-#define	DMA11_Y_MODIFY			0xFFC01CDC	/* DMA Channel 11 Y Modify Register */
-#define	DMA11_CURR_DESC_PTR		0xFFC01CE0	/* DMA Channel 11 Current Descriptor Pointer Register */
-#define	DMA11_CURR_ADDR			0xFFC01CE4	/* DMA Channel 11 Current Address Register */
-#define	DMA11_IRQ_STATUS		0xFFC01CE8	/* DMA Channel 11 Interrupt/Status Register */
-#define	DMA11_PERIPHERAL_MAP	0xFFC01CEC	/* DMA Channel 11 Peripheral Map Register */
-#define	DMA11_CURR_X_COUNT		0xFFC01CF0	/* DMA Channel 11 Current X Count Register */
-#define	DMA11_CURR_Y_COUNT		0xFFC01CF8	/* DMA Channel 11 Current Y Count Register */
-
-#define	DMA12_NEXT_DESC_PTR		0xFFC01D00	/* DMA Channel 12 Next Descriptor Pointer Register */
-#define	DMA12_START_ADDR		0xFFC01D04	/* DMA Channel 12 Start	Address	Register */
-#define	DMA12_CONFIG			0xFFC01D08	/* DMA Channel 12 Configuration	Register */
-#define	DMA12_X_COUNT			0xFFC01D10	/* DMA Channel 12 X Count Register */
-#define	DMA12_X_MODIFY			0xFFC01D14	/* DMA Channel 12 X Modify Register */
-#define	DMA12_Y_COUNT			0xFFC01D18	/* DMA Channel 12 Y Count Register */
-#define	DMA12_Y_MODIFY			0xFFC01D1C	/* DMA Channel 12 Y Modify Register */
-#define	DMA12_CURR_DESC_PTR		0xFFC01D20	/* DMA Channel 12 Current Descriptor Pointer Register */
-#define	DMA12_CURR_ADDR			0xFFC01D24	/* DMA Channel 12 Current Address Register */
-#define	DMA12_IRQ_STATUS		0xFFC01D28	/* DMA Channel 12 Interrupt/Status Register */
-#define	DMA12_PERIPHERAL_MAP	0xFFC01D2C	/* DMA Channel 12 Peripheral Map Register */
-#define	DMA12_CURR_X_COUNT		0xFFC01D30	/* DMA Channel 12 Current X Count Register */
-#define	DMA12_CURR_Y_COUNT		0xFFC01D38	/* DMA Channel 12 Current Y Count Register */
-
-#define	DMA13_NEXT_DESC_PTR		0xFFC01D40	/* DMA Channel 13 Next Descriptor Pointer Register */
-#define	DMA13_START_ADDR		0xFFC01D44	/* DMA Channel 13 Start	Address	Register */
-#define	DMA13_CONFIG			0xFFC01D48	/* DMA Channel 13 Configuration	Register */
-#define	DMA13_X_COUNT			0xFFC01D50	/* DMA Channel 13 X Count Register */
-#define	DMA13_X_MODIFY			0xFFC01D54	/* DMA Channel 13 X Modify Register */
-#define	DMA13_Y_COUNT			0xFFC01D58	/* DMA Channel 13 Y Count Register */
-#define	DMA13_Y_MODIFY			0xFFC01D5C	/* DMA Channel 13 Y Modify Register */
-#define	DMA13_CURR_DESC_PTR		0xFFC01D60	/* DMA Channel 13 Current Descriptor Pointer Register */
-#define	DMA13_CURR_ADDR			0xFFC01D64	/* DMA Channel 13 Current Address Register */
-#define	DMA13_IRQ_STATUS		0xFFC01D68	/* DMA Channel 13 Interrupt/Status Register */
-#define	DMA13_PERIPHERAL_MAP	0xFFC01D6C	/* DMA Channel 13 Peripheral Map Register */
-#define	DMA13_CURR_X_COUNT		0xFFC01D70	/* DMA Channel 13 Current X Count Register */
-#define	DMA13_CURR_Y_COUNT		0xFFC01D78	/* DMA Channel 13 Current Y Count Register */
-
-#define	DMA14_NEXT_DESC_PTR		0xFFC01D80	/* DMA Channel 14 Next Descriptor Pointer Register */
-#define	DMA14_START_ADDR		0xFFC01D84	/* DMA Channel 14 Start	Address	Register */
-#define	DMA14_CONFIG			0xFFC01D88	/* DMA Channel 14 Configuration	Register */
-#define	DMA14_X_COUNT			0xFFC01D90	/* DMA Channel 14 X Count Register */
-#define	DMA14_X_MODIFY			0xFFC01D94	/* DMA Channel 14 X Modify Register */
-#define	DMA14_Y_COUNT			0xFFC01D98	/* DMA Channel 14 Y Count Register */
-#define	DMA14_Y_MODIFY			0xFFC01D9C	/* DMA Channel 14 Y Modify Register */
-#define	DMA14_CURR_DESC_PTR		0xFFC01DA0	/* DMA Channel 14 Current Descriptor Pointer Register */
-#define	DMA14_CURR_ADDR			0xFFC01DA4	/* DMA Channel 14 Current Address Register */
-#define	DMA14_IRQ_STATUS		0xFFC01DA8	/* DMA Channel 14 Interrupt/Status Register */
-#define	DMA14_PERIPHERAL_MAP	0xFFC01DAC	/* DMA Channel 14 Peripheral Map Register */
-#define	DMA14_CURR_X_COUNT		0xFFC01DB0	/* DMA Channel 14 Current X Count Register */
-#define	DMA14_CURR_Y_COUNT		0xFFC01DB8	/* DMA Channel 14 Current Y Count Register */
-
-#define	DMA15_NEXT_DESC_PTR		0xFFC01DC0	/* DMA Channel 15 Next Descriptor Pointer Register */
-#define	DMA15_START_ADDR		0xFFC01DC4	/* DMA Channel 15 Start	Address	Register */
-#define	DMA15_CONFIG			0xFFC01DC8	/* DMA Channel 15 Configuration	Register */
-#define	DMA15_X_COUNT			0xFFC01DD0	/* DMA Channel 15 X Count Register */
-#define	DMA15_X_MODIFY			0xFFC01DD4	/* DMA Channel 15 X Modify Register */
-#define	DMA15_Y_COUNT			0xFFC01DD8	/* DMA Channel 15 Y Count Register */
-#define	DMA15_Y_MODIFY			0xFFC01DDC	/* DMA Channel 15 Y Modify Register */
-#define	DMA15_CURR_DESC_PTR		0xFFC01DE0	/* DMA Channel 15 Current Descriptor Pointer Register */
-#define	DMA15_CURR_ADDR			0xFFC01DE4	/* DMA Channel 15 Current Address Register */
-#define	DMA15_IRQ_STATUS		0xFFC01DE8	/* DMA Channel 15 Interrupt/Status Register */
-#define	DMA15_PERIPHERAL_MAP	0xFFC01DEC	/* DMA Channel 15 Peripheral Map Register */
-#define	DMA15_CURR_X_COUNT		0xFFC01DF0	/* DMA Channel 15 Current X Count Register */
-#define	DMA15_CURR_Y_COUNT		0xFFC01DF8	/* DMA Channel 15 Current Y Count Register */
-
-#define	DMA16_NEXT_DESC_PTR		0xFFC01E00	/* DMA Channel 16 Next Descriptor Pointer Register */
-#define	DMA16_START_ADDR		0xFFC01E04	/* DMA Channel 16 Start	Address	Register */
-#define	DMA16_CONFIG			0xFFC01E08	/* DMA Channel 16 Configuration	Register */
-#define	DMA16_X_COUNT			0xFFC01E10	/* DMA Channel 16 X Count Register */
-#define	DMA16_X_MODIFY			0xFFC01E14	/* DMA Channel 16 X Modify Register */
-#define	DMA16_Y_COUNT			0xFFC01E18	/* DMA Channel 16 Y Count Register */
-#define	DMA16_Y_MODIFY			0xFFC01E1C	/* DMA Channel 16 Y Modify Register */
-#define	DMA16_CURR_DESC_PTR		0xFFC01E20	/* DMA Channel 16 Current Descriptor Pointer Register */
-#define	DMA16_CURR_ADDR			0xFFC01E24	/* DMA Channel 16 Current Address Register */
-#define	DMA16_IRQ_STATUS		0xFFC01E28	/* DMA Channel 16 Interrupt/Status Register */
-#define	DMA16_PERIPHERAL_MAP	0xFFC01E2C	/* DMA Channel 16 Peripheral Map Register */
-#define	DMA16_CURR_X_COUNT		0xFFC01E30	/* DMA Channel 16 Current X Count Register */
-#define	DMA16_CURR_Y_COUNT		0xFFC01E38	/* DMA Channel 16 Current Y Count Register */
-
-#define	DMA17_NEXT_DESC_PTR		0xFFC01E40	/* DMA Channel 17 Next Descriptor Pointer Register */
-#define	DMA17_START_ADDR		0xFFC01E44	/* DMA Channel 17 Start	Address	Register */
-#define	DMA17_CONFIG			0xFFC01E48	/* DMA Channel 17 Configuration	Register */
-#define	DMA17_X_COUNT			0xFFC01E50	/* DMA Channel 17 X Count Register */
-#define	DMA17_X_MODIFY			0xFFC01E54	/* DMA Channel 17 X Modify Register */
-#define	DMA17_Y_COUNT			0xFFC01E58	/* DMA Channel 17 Y Count Register */
-#define	DMA17_Y_MODIFY			0xFFC01E5C	/* DMA Channel 17 Y Modify Register */
-#define	DMA17_CURR_DESC_PTR		0xFFC01E60	/* DMA Channel 17 Current Descriptor Pointer Register */
-#define	DMA17_CURR_ADDR			0xFFC01E64	/* DMA Channel 17 Current Address Register */
-#define	DMA17_IRQ_STATUS		0xFFC01E68	/* DMA Channel 17 Interrupt/Status Register */
-#define	DMA17_PERIPHERAL_MAP	0xFFC01E6C	/* DMA Channel 17 Peripheral Map Register */
-#define	DMA17_CURR_X_COUNT		0xFFC01E70	/* DMA Channel 17 Current X Count Register */
-#define	DMA17_CURR_Y_COUNT		0xFFC01E78	/* DMA Channel 17 Current Y Count Register */
-
-#define	DMA18_NEXT_DESC_PTR		0xFFC01E80	/* DMA Channel 18 Next Descriptor Pointer Register */
-#define	DMA18_START_ADDR		0xFFC01E84	/* DMA Channel 18 Start	Address	Register */
-#define	DMA18_CONFIG			0xFFC01E88	/* DMA Channel 18 Configuration	Register */
-#define	DMA18_X_COUNT			0xFFC01E90	/* DMA Channel 18 X Count Register */
-#define	DMA18_X_MODIFY			0xFFC01E94	/* DMA Channel 18 X Modify Register */
-#define	DMA18_Y_COUNT			0xFFC01E98	/* DMA Channel 18 Y Count Register */
-#define	DMA18_Y_MODIFY			0xFFC01E9C	/* DMA Channel 18 Y Modify Register */
-#define	DMA18_CURR_DESC_PTR		0xFFC01EA0	/* DMA Channel 18 Current Descriptor Pointer Register */
-#define	DMA18_CURR_ADDR			0xFFC01EA4	/* DMA Channel 18 Current Address Register */
-#define	DMA18_IRQ_STATUS		0xFFC01EA8	/* DMA Channel 18 Interrupt/Status Register */
-#define	DMA18_PERIPHERAL_MAP	0xFFC01EAC	/* DMA Channel 18 Peripheral Map Register */
-#define	DMA18_CURR_X_COUNT		0xFFC01EB0	/* DMA Channel 18 Current X Count Register */
-#define	DMA18_CURR_Y_COUNT		0xFFC01EB8	/* DMA Channel 18 Current Y Count Register */
-
-#define	DMA19_NEXT_DESC_PTR		0xFFC01EC0	/* DMA Channel 19 Next Descriptor Pointer Register */
-#define	DMA19_START_ADDR		0xFFC01EC4	/* DMA Channel 19 Start	Address	Register */
-#define	DMA19_CONFIG			0xFFC01EC8	/* DMA Channel 19 Configuration	Register */
-#define	DMA19_X_COUNT			0xFFC01ED0	/* DMA Channel 19 X Count Register */
-#define	DMA19_X_MODIFY			0xFFC01ED4	/* DMA Channel 19 X Modify Register */
-#define	DMA19_Y_COUNT			0xFFC01ED8	/* DMA Channel 19 Y Count Register */
-#define	DMA19_Y_MODIFY			0xFFC01EDC	/* DMA Channel 19 Y Modify Register */
-#define	DMA19_CURR_DESC_PTR		0xFFC01EE0	/* DMA Channel 19 Current Descriptor Pointer Register */
-#define	DMA19_CURR_ADDR			0xFFC01EE4	/* DMA Channel 19 Current Address Register */
-#define	DMA19_IRQ_STATUS		0xFFC01EE8	/* DMA Channel 19 Interrupt/Status Register */
-#define	DMA19_PERIPHERAL_MAP	0xFFC01EEC	/* DMA Channel 19 Peripheral Map Register */
-#define	DMA19_CURR_X_COUNT		0xFFC01EF0	/* DMA Channel 19 Current X Count Register */
-#define	DMA19_CURR_Y_COUNT		0xFFC01EF8	/* DMA Channel 19 Current Y Count Register */
-
-#define	MDMA1_D0_NEXT_DESC_PTR	0xFFC01F00	/* MemDMA1 Stream 0 Destination	Next Descriptor	Pointer	Register */
-#define	MDMA1_D0_START_ADDR		0xFFC01F04	/* MemDMA1 Stream 0 Destination	Start Address Register */
-#define	MDMA1_D0_CONFIG			0xFFC01F08	/* MemDMA1 Stream 0 Destination	Configuration Register */
-#define	MDMA1_D0_X_COUNT		0xFFC01F10	/* MemDMA1 Stream 0 Destination	X Count	Register */
-#define	MDMA1_D0_X_MODIFY		0xFFC01F14	/* MemDMA1 Stream 0 Destination	X Modify Register */
-#define	MDMA1_D0_Y_COUNT		0xFFC01F18	/* MemDMA1 Stream 0 Destination	Y Count	Register */
-#define	MDMA1_D0_Y_MODIFY		0xFFC01F1C	/* MemDMA1 Stream 0 Destination	Y Modify Register */
-#define	MDMA1_D0_CURR_DESC_PTR	0xFFC01F20	/* MemDMA1 Stream 0 Destination	Current	Descriptor Pointer Register */
-#define	MDMA1_D0_CURR_ADDR		0xFFC01F24	/* MemDMA1 Stream 0 Destination	Current	Address	Register */
-#define	MDMA1_D0_IRQ_STATUS		0xFFC01F28	/* MemDMA1 Stream 0 Destination	Interrupt/Status Register */
-#define	MDMA1_D0_PERIPHERAL_MAP	0xFFC01F2C	/* MemDMA1 Stream 0 Destination	Peripheral Map Register */
-#define	MDMA1_D0_CURR_X_COUNT	0xFFC01F30	/* MemDMA1 Stream 0 Destination	Current	X Count	Register */
-#define	MDMA1_D0_CURR_Y_COUNT	0xFFC01F38	/* MemDMA1 Stream 0 Destination	Current	Y Count	Register */
-
-#define	MDMA1_S0_NEXT_DESC_PTR	0xFFC01F40	/* MemDMA1 Stream 0 Source Next	Descriptor Pointer Register */
-#define	MDMA1_S0_START_ADDR		0xFFC01F44	/* MemDMA1 Stream 0 Source Start Address Register */
-#define	MDMA1_S0_CONFIG			0xFFC01F48	/* MemDMA1 Stream 0 Source Configuration Register */
-#define	MDMA1_S0_X_COUNT		0xFFC01F50	/* MemDMA1 Stream 0 Source X Count Register */
-#define	MDMA1_S0_X_MODIFY		0xFFC01F54	/* MemDMA1 Stream 0 Source X Modify Register */
-#define	MDMA1_S0_Y_COUNT		0xFFC01F58	/* MemDMA1 Stream 0 Source Y Count Register */
-#define	MDMA1_S0_Y_MODIFY		0xFFC01F5C	/* MemDMA1 Stream 0 Source Y Modify Register */
-#define	MDMA1_S0_CURR_DESC_PTR	0xFFC01F60	/* MemDMA1 Stream 0 Source Current Descriptor Pointer Register */
-#define	MDMA1_S0_CURR_ADDR		0xFFC01F64	/* MemDMA1 Stream 0 Source Current Address Register */
-#define	MDMA1_S0_IRQ_STATUS		0xFFC01F68	/* MemDMA1 Stream 0 Source Interrupt/Status Register */
-#define	MDMA1_S0_PERIPHERAL_MAP	0xFFC01F6C	/* MemDMA1 Stream 0 Source Peripheral Map Register */
-#define	MDMA1_S0_CURR_X_COUNT	0xFFC01F70	/* MemDMA1 Stream 0 Source Current X Count Register */
-#define	MDMA1_S0_CURR_Y_COUNT	0xFFC01F78	/* MemDMA1 Stream 0 Source Current Y Count Register */
-
-#define	MDMA1_D1_NEXT_DESC_PTR	0xFFC01F80	/* MemDMA1 Stream 1 Destination	Next Descriptor	Pointer	Register */
-#define	MDMA1_D1_START_ADDR		0xFFC01F84	/* MemDMA1 Stream 1 Destination	Start Address Register */
-#define	MDMA1_D1_CONFIG			0xFFC01F88	/* MemDMA1 Stream 1 Destination	Configuration Register */
-#define	MDMA1_D1_X_COUNT		0xFFC01F90	/* MemDMA1 Stream 1 Destination	X Count	Register */
-#define	MDMA1_D1_X_MODIFY		0xFFC01F94	/* MemDMA1 Stream 1 Destination	X Modify Register */
-#define	MDMA1_D1_Y_COUNT		0xFFC01F98	/* MemDMA1 Stream 1 Destination	Y Count	Register */
-#define	MDMA1_D1_Y_MODIFY		0xFFC01F9C	/* MemDMA1 Stream 1 Destination	Y Modify Register */
-#define	MDMA1_D1_CURR_DESC_PTR	0xFFC01FA0	/* MemDMA1 Stream 1 Destination	Current	Descriptor Pointer Register */
-#define	MDMA1_D1_CURR_ADDR		0xFFC01FA4	/* MemDMA1 Stream 1 Destination	Current	Address	Register */
-#define	MDMA1_D1_IRQ_STATUS		0xFFC01FA8	/* MemDMA1 Stream 1 Destination	Interrupt/Status Register */
-#define	MDMA1_D1_PERIPHERAL_MAP	0xFFC01FAC	/* MemDMA1 Stream 1 Destination	Peripheral Map Register */
-#define	MDMA1_D1_CURR_X_COUNT	0xFFC01FB0	/* MemDMA1 Stream 1 Destination	Current	X Count	Register */
-#define	MDMA1_D1_CURR_Y_COUNT	0xFFC01FB8	/* MemDMA1 Stream 1 Destination	Current	Y Count	Register */
-
-#define	MDMA1_S1_NEXT_DESC_PTR	0xFFC01FC0	/* MemDMA1 Stream 1 Source Next	Descriptor Pointer Register */
-#define	MDMA1_S1_START_ADDR		0xFFC01FC4	/* MemDMA1 Stream 1 Source Start Address Register */
-#define	MDMA1_S1_CONFIG			0xFFC01FC8	/* MemDMA1 Stream 1 Source Configuration Register */
-#define	MDMA1_S1_X_COUNT		0xFFC01FD0	/* MemDMA1 Stream 1 Source X Count Register */
-#define	MDMA1_S1_X_MODIFY		0xFFC01FD4	/* MemDMA1 Stream 1 Source X Modify Register */
-#define	MDMA1_S1_Y_COUNT		0xFFC01FD8	/* MemDMA1 Stream 1 Source Y Count Register */
-#define	MDMA1_S1_Y_MODIFY		0xFFC01FDC	/* MemDMA1 Stream 1 Source Y Modify Register */
-#define	MDMA1_S1_CURR_DESC_PTR	0xFFC01FE0	/* MemDMA1 Stream 1 Source Current Descriptor Pointer Register */
-#define	MDMA1_S1_CURR_ADDR		0xFFC01FE4	/* MemDMA1 Stream 1 Source Current Address Register */
-#define	MDMA1_S1_IRQ_STATUS		0xFFC01FE8	/* MemDMA1 Stream 1 Source Interrupt/Status Register */
-#define	MDMA1_S1_PERIPHERAL_MAP	0xFFC01FEC	/* MemDMA1 Stream 1 Source Peripheral Map Register */
-#define	MDMA1_S1_CURR_X_COUNT	0xFFC01FF0	/* MemDMA1 Stream 1 Source Current X Count Register */
-#define	MDMA1_S1_CURR_Y_COUNT	0xFFC01FF8	/* MemDMA1 Stream 1 Source Current Y Count Register */
-
-
-/* UART1 Controller		(0xFFC02000 - 0xFFC020FF)	 */
-#define	UART1_THR			0xFFC02000	/* Transmit Holding register */
-#define	UART1_RBR			0xFFC02000	/* Receive Buffer register */
-#define	UART1_DLL			0xFFC02000	/* Divisor Latch (Low-Byte) */
-#define	UART1_IER			0xFFC02004	/* Interrupt Enable Register */
-#define	UART1_DLH			0xFFC02004	/* Divisor Latch (High-Byte) */
-#define	UART1_IIR			0xFFC02008	/* Interrupt Identification Register */
-#define	UART1_LCR			0xFFC0200C	/* Line	Control	Register */
-#define	UART1_MCR			0xFFC02010	/* Modem Control Register */
-#define	UART1_LSR			0xFFC02014	/* Line	Status Register */
-#define	UART1_SCR			0xFFC0201C	/* SCR Scratch Register */
-#define	UART1_GCTL			0xFFC02024	/* Global Control Register */
-
-
-/* UART2 Controller		(0xFFC02100 - 0xFFC021FF)	 */
-#define	UART2_THR			0xFFC02100	/* Transmit Holding register */
-#define	UART2_RBR			0xFFC02100	/* Receive Buffer register */
-#define	UART2_DLL			0xFFC02100	/* Divisor Latch (Low-Byte) */
-#define	UART2_IER			0xFFC02104	/* Interrupt Enable Register */
-#define	UART2_DLH			0xFFC02104	/* Divisor Latch (High-Byte) */
-#define	UART2_IIR			0xFFC02108	/* Interrupt Identification Register */
-#define	UART2_LCR			0xFFC0210C	/* Line	Control	Register */
-#define	UART2_MCR			0xFFC02110	/* Modem Control Register */
-#define	UART2_LSR			0xFFC02114	/* Line	Status Register */
-#define	UART2_SCR			0xFFC0211C	/* SCR Scratch Register */
-#define	UART2_GCTL			0xFFC02124	/* Global Control Register */
-
-
-/* Two-Wire Interface 1	(0xFFC02200 - 0xFFC022FF)			 */
-#define	TWI1_CLKDIV			0xFFC02200	/* Serial Clock	Divider	Register */
-#define	TWI1_CONTROL		0xFFC02204	/* TWI1	Master Internal	Time Reference Register */
-#define	TWI1_SLAVE_CTL		0xFFC02208	/* Slave Mode Control Register */
-#define	TWI1_SLAVE_STAT		0xFFC0220C	/* Slave Mode Status Register */
-#define	TWI1_SLAVE_ADDR		0xFFC02210	/* Slave Mode Address Register */
-#define	TWI1_MASTER_CTL	0xFFC02214	/* Master Mode Control Register */
-#define	TWI1_MASTER_STAT	0xFFC02218	/* Master Mode Status Register */
-#define	TWI1_MASTER_ADDR	0xFFC0221C	/* Master Mode Address Register */
-#define	TWI1_INT_STAT		0xFFC02220	/* TWI1	Master Interrupt Register */
-#define	TWI1_INT_MASK		0xFFC02224	/* TWI1	Master Interrupt Mask Register */
-#define	TWI1_FIFO_CTL		0xFFC02228	/* FIFO	Control	Register */
-#define	TWI1_FIFO_STAT		0xFFC0222C	/* FIFO	Status Register */
-#define	TWI1_XMT_DATA8		0xFFC02280	/* FIFO	Transmit Data Single Byte Register */
-#define	TWI1_XMT_DATA16		0xFFC02284	/* FIFO	Transmit Data Double Byte Register */
-#define	TWI1_RCV_DATA8		0xFFC02288	/* FIFO	Receive	Data Single Byte Register */
-#define	TWI1_RCV_DATA16		0xFFC0228C	/* FIFO	Receive	Data Double Byte Register */
-#define TWI1_REGBASE		TWI1_CLKDIV
-
-
-/* the following are for backwards compatibility */
-#define	TWI1_PRESCALE	  TWI1_CONTROL
-#define	TWI1_INT_SRC	  TWI1_INT_STAT
-#define	TWI1_INT_ENABLE	  TWI1_INT_MASK
-
-
-/* SPI1	Controller		(0xFFC02300 - 0xFFC023FF)	 */
-#define	SPI1_CTL			0xFFC02300  /* SPI1 Control Register */
-#define	SPI1_FLG			0xFFC02304  /* SPI1 Flag register */
-#define	SPI1_STAT			0xFFC02308  /* SPI1 Status register */
-#define	SPI1_TDBR			0xFFC0230C  /* SPI1 Transmit Data Buffer Register */
-#define	SPI1_RDBR			0xFFC02310  /* SPI1 Receive Data Buffer	Register */
-#define	SPI1_BAUD			0xFFC02314  /* SPI1 Baud rate Register */
-#define	SPI1_SHADOW			0xFFC02318  /* SPI1_RDBR Shadow	Register */
-#define SPI1_REGBASE			SPI1_CTL
-
-/* SPI2	Controller		(0xFFC02400 - 0xFFC024FF)	 */
-#define	SPI2_CTL			0xFFC02400  /* SPI2 Control Register */
-#define	SPI2_FLG			0xFFC02404  /* SPI2 Flag register */
-#define	SPI2_STAT			0xFFC02408  /* SPI2 Status register */
-#define	SPI2_TDBR			0xFFC0240C  /* SPI2 Transmit Data Buffer Register */
-#define	SPI2_RDBR			0xFFC02410  /* SPI2 Receive Data Buffer	Register */
-#define	SPI2_BAUD			0xFFC02414  /* SPI2 Baud rate Register */
-#define	SPI2_SHADOW			0xFFC02418  /* SPI2_RDBR Shadow	Register */
-#define SPI2_REGBASE			SPI2_CTL
-
-/* SPORT2 Controller		(0xFFC02500 - 0xFFC025FF)			 */
-#define	SPORT2_TCR1			0xFFC02500	/* SPORT2 Transmit Configuration 1 Register */
-#define	SPORT2_TCR2			0xFFC02504	/* SPORT2 Transmit Configuration 2 Register */
-#define	SPORT2_TCLKDIV		0xFFC02508	/* SPORT2 Transmit Clock Divider */
-#define	SPORT2_TFSDIV		0xFFC0250C	/* SPORT2 Transmit Frame Sync Divider */
-#define	SPORT2_TX			0xFFC02510	/* SPORT2 TX Data Register */
-#define	SPORT2_RX			0xFFC02518	/* SPORT2 RX Data Register */
-#define	SPORT2_RCR1			0xFFC02520	/* SPORT2 Transmit Configuration 1 Register */
-#define	SPORT2_RCR2			0xFFC02524	/* SPORT2 Transmit Configuration 2 Register */
-#define	SPORT2_RCLKDIV		0xFFC02528	/* SPORT2 Receive Clock	Divider */
-#define	SPORT2_RFSDIV		0xFFC0252C	/* SPORT2 Receive Frame	Sync Divider */
-#define	SPORT2_STAT			0xFFC02530	/* SPORT2 Status Register */
-#define	SPORT2_CHNL			0xFFC02534	/* SPORT2 Current Channel Register */
-#define	SPORT2_MCMC1		0xFFC02538	/* SPORT2 Multi-Channel	Configuration Register 1 */
-#define	SPORT2_MCMC2		0xFFC0253C	/* SPORT2 Multi-Channel	Configuration Register 2 */
-#define	SPORT2_MTCS0		0xFFC02540	/* SPORT2 Multi-Channel	Transmit Select	Register 0 */
-#define	SPORT2_MTCS1		0xFFC02544	/* SPORT2 Multi-Channel	Transmit Select	Register 1 */
-#define	SPORT2_MTCS2		0xFFC02548	/* SPORT2 Multi-Channel	Transmit Select	Register 2 */
-#define	SPORT2_MTCS3		0xFFC0254C	/* SPORT2 Multi-Channel	Transmit Select	Register 3 */
-#define	SPORT2_MRCS0		0xFFC02550	/* SPORT2 Multi-Channel	Receive	Select Register	0 */
-#define	SPORT2_MRCS1		0xFFC02554	/* SPORT2 Multi-Channel	Receive	Select Register	1 */
-#define	SPORT2_MRCS2		0xFFC02558	/* SPORT2 Multi-Channel	Receive	Select Register	2 */
-#define	SPORT2_MRCS3		0xFFC0255C	/* SPORT2 Multi-Channel	Receive	Select Register	3 */
-
-
-/* SPORT3 Controller		(0xFFC02600 - 0xFFC026FF)			 */
-#define	SPORT3_TCR1			0xFFC02600	/* SPORT3 Transmit Configuration 1 Register */
-#define	SPORT3_TCR2			0xFFC02604	/* SPORT3 Transmit Configuration 2 Register */
-#define	SPORT3_TCLKDIV		0xFFC02608	/* SPORT3 Transmit Clock Divider */
-#define	SPORT3_TFSDIV		0xFFC0260C	/* SPORT3 Transmit Frame Sync Divider */
-#define	SPORT3_TX			0xFFC02610	/* SPORT3 TX Data Register */
-#define	SPORT3_RX			0xFFC02618	/* SPORT3 RX Data Register */
-#define	SPORT3_RCR1			0xFFC02620	/* SPORT3 Transmit Configuration 1 Register */
-#define	SPORT3_RCR2			0xFFC02624	/* SPORT3 Transmit Configuration 2 Register */
-#define	SPORT3_RCLKDIV		0xFFC02628	/* SPORT3 Receive Clock	Divider */
-#define	SPORT3_RFSDIV		0xFFC0262C	/* SPORT3 Receive Frame	Sync Divider */
-#define	SPORT3_STAT			0xFFC02630	/* SPORT3 Status Register */
-#define	SPORT3_CHNL			0xFFC02634	/* SPORT3 Current Channel Register */
-#define	SPORT3_MCMC1		0xFFC02638	/* SPORT3 Multi-Channel	Configuration Register 1 */
-#define	SPORT3_MCMC2		0xFFC0263C	/* SPORT3 Multi-Channel	Configuration Register 2 */
-#define	SPORT3_MTCS0		0xFFC02640	/* SPORT3 Multi-Channel	Transmit Select	Register 0 */
-#define	SPORT3_MTCS1		0xFFC02644	/* SPORT3 Multi-Channel	Transmit Select	Register 1 */
-#define	SPORT3_MTCS2		0xFFC02648	/* SPORT3 Multi-Channel	Transmit Select	Register 2 */
-#define	SPORT3_MTCS3		0xFFC0264C	/* SPORT3 Multi-Channel	Transmit Select	Register 3 */
-#define	SPORT3_MRCS0		0xFFC02650	/* SPORT3 Multi-Channel	Receive	Select Register	0 */
-#define	SPORT3_MRCS1		0xFFC02654	/* SPORT3 Multi-Channel	Receive	Select Register	1 */
-#define	SPORT3_MRCS2		0xFFC02658	/* SPORT3 Multi-Channel	Receive	Select Register	2 */
-#define	SPORT3_MRCS3		0xFFC0265C	/* SPORT3 Multi-Channel	Receive	Select Register	3 */
-
+#include "defBF538.h"
 
 /* Media Transceiver (MXVR)   (0xFFC02700 - 0xFFC028FF) */
 
@@ -995,1249 +149,4 @@
 #define	MXVR_BLOCK_CNT	      0xFFC028C0  /* MXVR Block	Counter */
 #define	MXVR_PLL_CTL_2	      0xFFC028C4  /* MXVR Phase	Lock Loop Control Register 2 */
 
-
-/* CAN Controller		(0xFFC02A00 - 0xFFC02FFF)				 */
-/* For Mailboxes 0-15											 */
-#define	CAN_MC1				0xFFC02A00	/* Mailbox config reg 1	 */
-#define	CAN_MD1				0xFFC02A04	/* Mailbox direction reg 1 */
-#define	CAN_TRS1			0xFFC02A08	/* Transmit Request Set	reg 1 */
-#define	CAN_TRR1			0xFFC02A0C	/* Transmit Request Reset reg 1 */
-#define	CAN_TA1				0xFFC02A10	/* Transmit Acknowledge	reg 1 */
-#define	CAN_AA1				0xFFC02A14	/* Transmit Abort Acknowledge reg 1 */
-#define	CAN_RMP1			0xFFC02A18	/* Receive Message Pending reg 1 */
-#define	CAN_RML1			0xFFC02A1C	/* Receive Message Lost	reg 1 */
-#define	CAN_MBTIF1			0xFFC02A20	/* Mailbox Transmit Interrupt Flag reg 1 */
-#define	CAN_MBRIF1			0xFFC02A24	/* Mailbox Receive  Interrupt Flag reg 1 */
-#define	CAN_MBIM1			0xFFC02A28	/* Mailbox Interrupt Mask reg 1 */
-#define	CAN_RFH1			0xFFC02A2C	/* Remote Frame	Handling reg 1 */
-#define	CAN_OPSS1			0xFFC02A30	/* Overwrite Protection	Single Shot Xmission reg 1 */
-
-/* For Mailboxes 16-31											 */
-#define	CAN_MC2				0xFFC02A40	/* Mailbox config reg 2	 */
-#define	CAN_MD2				0xFFC02A44	/* Mailbox direction reg 2 */
-#define	CAN_TRS2			0xFFC02A48	/* Transmit Request Set	reg 2 */
-#define	CAN_TRR2			0xFFC02A4C	/* Transmit Request Reset reg 2 */
-#define	CAN_TA2				0xFFC02A50	/* Transmit Acknowledge	reg 2 */
-#define	CAN_AA2				0xFFC02A54	/* Transmit Abort Acknowledge reg 2 */
-#define	CAN_RMP2			0xFFC02A58	/* Receive Message Pending reg 2 */
-#define	CAN_RML2			0xFFC02A5C	/* Receive Message Lost	reg 2 */
-#define	CAN_MBTIF2			0xFFC02A60	/* Mailbox Transmit Interrupt Flag reg 2 */
-#define	CAN_MBRIF2			0xFFC02A64	/* Mailbox Receive  Interrupt Flag reg 2 */
-#define	CAN_MBIM2			0xFFC02A68	/* Mailbox Interrupt Mask reg 2 */
-#define	CAN_RFH2			0xFFC02A6C	/* Remote Frame	Handling reg 2 */
-#define	CAN_OPSS2			0xFFC02A70	/* Overwrite Protection	Single Shot Xmission reg 2 */
-
-#define	CAN_CLOCK			0xFFC02A80	/* Bit Timing Configuration register 0 */
-#define	CAN_TIMING			0xFFC02A84	/* Bit Timing Configuration register 1 */
-
-#define	CAN_DEBUG			0xFFC02A88	/* Debug Register		 */
-/* the following is for	backwards compatibility */
-#define	CAN_CNF		 CAN_DEBUG
-
-#define	CAN_STATUS			0xFFC02A8C	/* Global Status Register */
-#define	CAN_CEC				0xFFC02A90	/* Error Counter Register */
-#define	CAN_GIS				0xFFC02A94	/* Global Interrupt Status Register */
-#define	CAN_GIM				0xFFC02A98	/* Global Interrupt Mask Register */
-#define	CAN_GIF				0xFFC02A9C	/* Global Interrupt Flag Register */
-#define	CAN_CONTROL			0xFFC02AA0	/* Master Control Register */
-#define	CAN_INTR			0xFFC02AA4	/* Interrupt Pending Register */
-#define	CAN_MBTD			0xFFC02AAC	/* Mailbox Temporary Disable Feature */
-#define	CAN_EWR				0xFFC02AB0	/* Programmable	Warning	Level */
-#define	CAN_ESR				0xFFC02AB4	/* Error Status	Register */
-#define	CAN_UCCNT			0xFFC02AC4	/* Universal Counter	 */
-#define	CAN_UCRC			0xFFC02AC8	/* Universal Counter Reload/Capture Register */
-#define	CAN_UCCNF			0xFFC02ACC	/* Universal Counter Configuration Register */
-
-/* Mailbox Acceptance Masks					 */
-#define	CAN_AM00L			0xFFC02B00	/* Mailbox 0 Low Acceptance Mask */
-#define	CAN_AM00H			0xFFC02B04	/* Mailbox 0 High Acceptance Mask */
-#define	CAN_AM01L			0xFFC02B08	/* Mailbox 1 Low Acceptance Mask */
-#define	CAN_AM01H			0xFFC02B0C	/* Mailbox 1 High Acceptance Mask */
-#define	CAN_AM02L			0xFFC02B10	/* Mailbox 2 Low Acceptance Mask */
-#define	CAN_AM02H			0xFFC02B14	/* Mailbox 2 High Acceptance Mask */
-#define	CAN_AM03L			0xFFC02B18	/* Mailbox 3 Low Acceptance Mask */
-#define	CAN_AM03H			0xFFC02B1C	/* Mailbox 3 High Acceptance Mask */
-#define	CAN_AM04L			0xFFC02B20	/* Mailbox 4 Low Acceptance Mask */
-#define	CAN_AM04H			0xFFC02B24	/* Mailbox 4 High Acceptance Mask */
-#define	CAN_AM05L			0xFFC02B28	/* Mailbox 5 Low Acceptance Mask */
-#define	CAN_AM05H			0xFFC02B2C	/* Mailbox 5 High Acceptance Mask */
-#define	CAN_AM06L			0xFFC02B30	/* Mailbox 6 Low Acceptance Mask */
-#define	CAN_AM06H			0xFFC02B34	/* Mailbox 6 High Acceptance Mask */
-#define	CAN_AM07L			0xFFC02B38	/* Mailbox 7 Low Acceptance Mask */
-#define	CAN_AM07H			0xFFC02B3C	/* Mailbox 7 High Acceptance Mask */
-#define	CAN_AM08L			0xFFC02B40	/* Mailbox 8 Low Acceptance Mask */
-#define	CAN_AM08H			0xFFC02B44	/* Mailbox 8 High Acceptance Mask */
-#define	CAN_AM09L			0xFFC02B48	/* Mailbox 9 Low Acceptance Mask */
-#define	CAN_AM09H			0xFFC02B4C	/* Mailbox 9 High Acceptance Mask */
-#define	CAN_AM10L			0xFFC02B50	/* Mailbox 10 Low Acceptance Mask */
-#define	CAN_AM10H			0xFFC02B54	/* Mailbox 10 High Acceptance Mask */
-#define	CAN_AM11L			0xFFC02B58	/* Mailbox 11 Low Acceptance Mask */
-#define	CAN_AM11H			0xFFC02B5C	/* Mailbox 11 High Acceptance Mask */
-#define	CAN_AM12L			0xFFC02B60	/* Mailbox 12 Low Acceptance Mask */
-#define	CAN_AM12H			0xFFC02B64	/* Mailbox 12 High Acceptance Mask */
-#define	CAN_AM13L			0xFFC02B68	/* Mailbox 13 Low Acceptance Mask */
-#define	CAN_AM13H			0xFFC02B6C	/* Mailbox 13 High Acceptance Mask */
-#define	CAN_AM14L			0xFFC02B70	/* Mailbox 14 Low Acceptance Mask */
-#define	CAN_AM14H			0xFFC02B74	/* Mailbox 14 High Acceptance Mask */
-#define	CAN_AM15L			0xFFC02B78	/* Mailbox 15 Low Acceptance Mask */
-#define	CAN_AM15H			0xFFC02B7C	/* Mailbox 15 High Acceptance Mask */
-
-#define	CAN_AM16L			0xFFC02B80	/* Mailbox 16 Low Acceptance Mask */
-#define	CAN_AM16H			0xFFC02B84	/* Mailbox 16 High Acceptance Mask */
-#define	CAN_AM17L			0xFFC02B88	/* Mailbox 17 Low Acceptance Mask */
-#define	CAN_AM17H			0xFFC02B8C	/* Mailbox 17 High Acceptance Mask */
-#define	CAN_AM18L			0xFFC02B90	/* Mailbox 18 Low Acceptance Mask */
-#define	CAN_AM18H			0xFFC02B94	/* Mailbox 18 High Acceptance Mask */
-#define	CAN_AM19L			0xFFC02B98	/* Mailbox 19 Low Acceptance Mask */
-#define	CAN_AM19H			0xFFC02B9C	/* Mailbox 19 High Acceptance Mask */
-#define	CAN_AM20L			0xFFC02BA0	/* Mailbox 20 Low Acceptance Mask */
-#define	CAN_AM20H			0xFFC02BA4	/* Mailbox 20 High Acceptance Mask */
-#define	CAN_AM21L			0xFFC02BA8	/* Mailbox 21 Low Acceptance Mask */
-#define	CAN_AM21H			0xFFC02BAC	/* Mailbox 21 High Acceptance Mask */
-#define	CAN_AM22L			0xFFC02BB0	/* Mailbox 22 Low Acceptance Mask */
-#define	CAN_AM22H			0xFFC02BB4	/* Mailbox 22 High Acceptance Mask */
-#define	CAN_AM23L			0xFFC02BB8	/* Mailbox 23 Low Acceptance Mask */
-#define	CAN_AM23H			0xFFC02BBC	/* Mailbox 23 High Acceptance Mask */
-#define	CAN_AM24L			0xFFC02BC0	/* Mailbox 24 Low Acceptance Mask */
-#define	CAN_AM24H			0xFFC02BC4	/* Mailbox 24 High Acceptance Mask */
-#define	CAN_AM25L			0xFFC02BC8	/* Mailbox 25 Low Acceptance Mask */
-#define	CAN_AM25H			0xFFC02BCC	/* Mailbox 25 High Acceptance Mask */
-#define	CAN_AM26L			0xFFC02BD0	/* Mailbox 26 Low Acceptance Mask */
-#define	CAN_AM26H			0xFFC02BD4	/* Mailbox 26 High Acceptance Mask */
-#define	CAN_AM27L			0xFFC02BD8	/* Mailbox 27 Low Acceptance Mask */
-#define	CAN_AM27H			0xFFC02BDC	/* Mailbox 27 High Acceptance Mask */
-#define	CAN_AM28L			0xFFC02BE0	/* Mailbox 28 Low Acceptance Mask */
-#define	CAN_AM28H			0xFFC02BE4	/* Mailbox 28 High Acceptance Mask */
-#define	CAN_AM29L			0xFFC02BE8	/* Mailbox 29 Low Acceptance Mask */
-#define	CAN_AM29H			0xFFC02BEC	/* Mailbox 29 High Acceptance Mask */
-#define	CAN_AM30L			0xFFC02BF0	/* Mailbox 30 Low Acceptance Mask */
-#define	CAN_AM30H			0xFFC02BF4	/* Mailbox 30 High Acceptance Mask */
-#define	CAN_AM31L			0xFFC02BF8	/* Mailbox 31 Low Acceptance Mask */
-#define	CAN_AM31H			0xFFC02BFC	/* Mailbox 31 High Acceptance Mask */
-
-/* CAN Acceptance Mask Macros */
-#define	CAN_AM_L(x)			(CAN_AM00L+((x)*0x8))
-#define	CAN_AM_H(x)			(CAN_AM00H+((x)*0x8))
-
-/* Mailbox Registers									 */
-#define	CAN_MB00_DATA0		0xFFC02C00	/* Mailbox 0 Data Word 0 [15:0]	Register */
-#define	CAN_MB00_DATA1		0xFFC02C04	/* Mailbox 0 Data Word 1 [31:16] Register */
-#define	CAN_MB00_DATA2		0xFFC02C08	/* Mailbox 0 Data Word 2 [47:32] Register */
-#define	CAN_MB00_DATA3		0xFFC02C0C	/* Mailbox 0 Data Word 3 [63:48] Register */
-#define	CAN_MB00_LENGTH		0xFFC02C10	/* Mailbox 0 Data Length Code Register */
-#define	CAN_MB00_TIMESTAMP	0xFFC02C14	/* Mailbox 0 Time Stamp	Value Register */
-#define	CAN_MB00_ID0		0xFFC02C18	/* Mailbox 0 Identifier	Low Register */
-#define	CAN_MB00_ID1		0xFFC02C1C	/* Mailbox 0 Identifier	High Register */
-
-#define	CAN_MB01_DATA0		0xFFC02C20	/* Mailbox 1 Data Word 0 [15:0]	Register */
-#define	CAN_MB01_DATA1		0xFFC02C24	/* Mailbox 1 Data Word 1 [31:16] Register */
-#define	CAN_MB01_DATA2		0xFFC02C28	/* Mailbox 1 Data Word 2 [47:32] Register */
-#define	CAN_MB01_DATA3		0xFFC02C2C	/* Mailbox 1 Data Word 3 [63:48] Register */
-#define	CAN_MB01_LENGTH		0xFFC02C30	/* Mailbox 1 Data Length Code Register */
-#define	CAN_MB01_TIMESTAMP	0xFFC02C34	/* Mailbox 1 Time Stamp	Value Register */
-#define	CAN_MB01_ID0		0xFFC02C38	/* Mailbox 1 Identifier	Low Register */
-#define	CAN_MB01_ID1		0xFFC02C3C	/* Mailbox 1 Identifier	High Register */
-
-#define	CAN_MB02_DATA0		0xFFC02C40	/* Mailbox 2 Data Word 0 [15:0]	Register */
-#define	CAN_MB02_DATA1		0xFFC02C44	/* Mailbox 2 Data Word 1 [31:16] Register */
-#define	CAN_MB02_DATA2		0xFFC02C48	/* Mailbox 2 Data Word 2 [47:32] Register */
-#define	CAN_MB02_DATA3		0xFFC02C4C	/* Mailbox 2 Data Word 3 [63:48] Register */
-#define	CAN_MB02_LENGTH		0xFFC02C50	/* Mailbox 2 Data Length Code Register */
-#define	CAN_MB02_TIMESTAMP	0xFFC02C54	/* Mailbox 2 Time Stamp	Value Register */
-#define	CAN_MB02_ID0		0xFFC02C58	/* Mailbox 2 Identifier	Low Register */
-#define	CAN_MB02_ID1		0xFFC02C5C	/* Mailbox 2 Identifier	High Register */
-
-#define	CAN_MB03_DATA0		0xFFC02C60	/* Mailbox 3 Data Word 0 [15:0]	Register */
-#define	CAN_MB03_DATA1		0xFFC02C64	/* Mailbox 3 Data Word 1 [31:16] Register */
-#define	CAN_MB03_DATA2		0xFFC02C68	/* Mailbox 3 Data Word 2 [47:32] Register */
-#define	CAN_MB03_DATA3		0xFFC02C6C	/* Mailbox 3 Data Word 3 [63:48] Register */
-#define	CAN_MB03_LENGTH		0xFFC02C70	/* Mailbox 3 Data Length Code Register */
-#define	CAN_MB03_TIMESTAMP	0xFFC02C74	/* Mailbox 3 Time Stamp	Value Register */
-#define	CAN_MB03_ID0		0xFFC02C78	/* Mailbox 3 Identifier	Low Register */
-#define	CAN_MB03_ID1		0xFFC02C7C	/* Mailbox 3 Identifier	High Register */
-
-#define	CAN_MB04_DATA0		0xFFC02C80	/* Mailbox 4 Data Word 0 [15:0]	Register */
-#define	CAN_MB04_DATA1		0xFFC02C84	/* Mailbox 4 Data Word 1 [31:16] Register */
-#define	CAN_MB04_DATA2		0xFFC02C88	/* Mailbox 4 Data Word 2 [47:32] Register */
-#define	CAN_MB04_DATA3		0xFFC02C8C	/* Mailbox 4 Data Word 3 [63:48] Register */
-#define	CAN_MB04_LENGTH		0xFFC02C90	/* Mailbox 4 Data Length Code Register */
-#define	CAN_MB04_TIMESTAMP	0xFFC02C94	/* Mailbox 4 Time Stamp	Value Register */
-#define	CAN_MB04_ID0		0xFFC02C98	/* Mailbox 4 Identifier	Low Register */
-#define	CAN_MB04_ID1		0xFFC02C9C	/* Mailbox 4 Identifier	High Register */
-
-#define	CAN_MB05_DATA0		0xFFC02CA0	/* Mailbox 5 Data Word 0 [15:0]	Register */
-#define	CAN_MB05_DATA1		0xFFC02CA4	/* Mailbox 5 Data Word 1 [31:16] Register */
-#define	CAN_MB05_DATA2		0xFFC02CA8	/* Mailbox 5 Data Word 2 [47:32] Register */
-#define	CAN_MB05_DATA3		0xFFC02CAC	/* Mailbox 5 Data Word 3 [63:48] Register */
-#define	CAN_MB05_LENGTH		0xFFC02CB0	/* Mailbox 5 Data Length Code Register */
-#define	CAN_MB05_TIMESTAMP	0xFFC02CB4	/* Mailbox 5 Time Stamp	Value Register */
-#define	CAN_MB05_ID0		0xFFC02CB8	/* Mailbox 5 Identifier	Low Register */
-#define	CAN_MB05_ID1		0xFFC02CBC	/* Mailbox 5 Identifier	High Register */
-
-#define	CAN_MB06_DATA0		0xFFC02CC0	/* Mailbox 6 Data Word 0 [15:0]	Register */
-#define	CAN_MB06_DATA1		0xFFC02CC4	/* Mailbox 6 Data Word 1 [31:16] Register */
-#define	CAN_MB06_DATA2		0xFFC02CC8	/* Mailbox 6 Data Word 2 [47:32] Register */
-#define	CAN_MB06_DATA3		0xFFC02CCC	/* Mailbox 6 Data Word 3 [63:48] Register */
-#define	CAN_MB06_LENGTH		0xFFC02CD0	/* Mailbox 6 Data Length Code Register */
-#define	CAN_MB06_TIMESTAMP	0xFFC02CD4	/* Mailbox 6 Time Stamp	Value Register */
-#define	CAN_MB06_ID0		0xFFC02CD8	/* Mailbox 6 Identifier	Low Register */
-#define	CAN_MB06_ID1		0xFFC02CDC	/* Mailbox 6 Identifier	High Register */
-
-#define	CAN_MB07_DATA0		0xFFC02CE0	/* Mailbox 7 Data Word 0 [15:0]	Register */
-#define	CAN_MB07_DATA1		0xFFC02CE4	/* Mailbox 7 Data Word 1 [31:16] Register */
-#define	CAN_MB07_DATA2		0xFFC02CE8	/* Mailbox 7 Data Word 2 [47:32] Register */
-#define	CAN_MB07_DATA3		0xFFC02CEC	/* Mailbox 7 Data Word 3 [63:48] Register */
-#define	CAN_MB07_LENGTH		0xFFC02CF0	/* Mailbox 7 Data Length Code Register */
-#define	CAN_MB07_TIMESTAMP	0xFFC02CF4	/* Mailbox 7 Time Stamp	Value Register */
-#define	CAN_MB07_ID0		0xFFC02CF8	/* Mailbox 7 Identifier	Low Register */
-#define	CAN_MB07_ID1		0xFFC02CFC	/* Mailbox 7 Identifier	High Register */
-
-#define	CAN_MB08_DATA0		0xFFC02D00	/* Mailbox 8 Data Word 0 [15:0]	Register */
-#define	CAN_MB08_DATA1		0xFFC02D04	/* Mailbox 8 Data Word 1 [31:16] Register */
-#define	CAN_MB08_DATA2		0xFFC02D08	/* Mailbox 8 Data Word 2 [47:32] Register */
-#define	CAN_MB08_DATA3		0xFFC02D0C	/* Mailbox 8 Data Word 3 [63:48] Register */
-#define	CAN_MB08_LENGTH		0xFFC02D10	/* Mailbox 8 Data Length Code Register */
-#define	CAN_MB08_TIMESTAMP	0xFFC02D14	/* Mailbox 8 Time Stamp	Value Register */
-#define	CAN_MB08_ID0		0xFFC02D18	/* Mailbox 8 Identifier	Low Register */
-#define	CAN_MB08_ID1		0xFFC02D1C	/* Mailbox 8 Identifier	High Register */
-
-#define	CAN_MB09_DATA0		0xFFC02D20	/* Mailbox 9 Data Word 0 [15:0]	Register */
-#define	CAN_MB09_DATA1		0xFFC02D24	/* Mailbox 9 Data Word 1 [31:16] Register */
-#define	CAN_MB09_DATA2		0xFFC02D28	/* Mailbox 9 Data Word 2 [47:32] Register */
-#define	CAN_MB09_DATA3		0xFFC02D2C	/* Mailbox 9 Data Word 3 [63:48] Register */
-#define	CAN_MB09_LENGTH		0xFFC02D30	/* Mailbox 9 Data Length Code Register */
-#define	CAN_MB09_TIMESTAMP	0xFFC02D34	/* Mailbox 9 Time Stamp	Value Register */
-#define	CAN_MB09_ID0		0xFFC02D38	/* Mailbox 9 Identifier	Low Register */
-#define	CAN_MB09_ID1		0xFFC02D3C	/* Mailbox 9 Identifier	High Register */
-
-#define	CAN_MB10_DATA0		0xFFC02D40	/* Mailbox 10 Data Word	0 [15:0] Register */
-#define	CAN_MB10_DATA1		0xFFC02D44	/* Mailbox 10 Data Word	1 [31:16] Register */
-#define	CAN_MB10_DATA2		0xFFC02D48	/* Mailbox 10 Data Word	2 [47:32] Register */
-#define	CAN_MB10_DATA3		0xFFC02D4C	/* Mailbox 10 Data Word	3 [63:48] Register */
-#define	CAN_MB10_LENGTH		0xFFC02D50	/* Mailbox 10 Data Length Code Register */
-#define	CAN_MB10_TIMESTAMP	0xFFC02D54	/* Mailbox 10 Time Stamp Value Register */
-#define	CAN_MB10_ID0		0xFFC02D58	/* Mailbox 10 Identifier Low Register */
-#define	CAN_MB10_ID1		0xFFC02D5C	/* Mailbox 10 Identifier High Register */
-
-#define	CAN_MB11_DATA0		0xFFC02D60	/* Mailbox 11 Data Word	0 [15:0] Register */
-#define	CAN_MB11_DATA1		0xFFC02D64	/* Mailbox 11 Data Word	1 [31:16] Register */
-#define	CAN_MB11_DATA2		0xFFC02D68	/* Mailbox 11 Data Word	2 [47:32] Register */
-#define	CAN_MB11_DATA3		0xFFC02D6C	/* Mailbox 11 Data Word	3 [63:48] Register */
-#define	CAN_MB11_LENGTH		0xFFC02D70	/* Mailbox 11 Data Length Code Register */
-#define	CAN_MB11_TIMESTAMP	0xFFC02D74	/* Mailbox 11 Time Stamp Value Register */
-#define	CAN_MB11_ID0		0xFFC02D78	/* Mailbox 11 Identifier Low Register */
-#define	CAN_MB11_ID1		0xFFC02D7C	/* Mailbox 11 Identifier High Register */
-
-#define	CAN_MB12_DATA0		0xFFC02D80	/* Mailbox 12 Data Word	0 [15:0] Register */
-#define	CAN_MB12_DATA1		0xFFC02D84	/* Mailbox 12 Data Word	1 [31:16] Register */
-#define	CAN_MB12_DATA2		0xFFC02D88	/* Mailbox 12 Data Word	2 [47:32] Register */
-#define	CAN_MB12_DATA3		0xFFC02D8C	/* Mailbox 12 Data Word	3 [63:48] Register */
-#define	CAN_MB12_LENGTH		0xFFC02D90	/* Mailbox 12 Data Length Code Register */
-#define	CAN_MB12_TIMESTAMP	0xFFC02D94	/* Mailbox 12 Time Stamp Value Register */
-#define	CAN_MB12_ID0		0xFFC02D98	/* Mailbox 12 Identifier Low Register */
-#define	CAN_MB12_ID1		0xFFC02D9C	/* Mailbox 12 Identifier High Register */
-
-#define	CAN_MB13_DATA0		0xFFC02DA0	/* Mailbox 13 Data Word	0 [15:0] Register */
-#define	CAN_MB13_DATA1		0xFFC02DA4	/* Mailbox 13 Data Word	1 [31:16] Register */
-#define	CAN_MB13_DATA2		0xFFC02DA8	/* Mailbox 13 Data Word	2 [47:32] Register */
-#define	CAN_MB13_DATA3		0xFFC02DAC	/* Mailbox 13 Data Word	3 [63:48] Register */
-#define	CAN_MB13_LENGTH		0xFFC02DB0	/* Mailbox 13 Data Length Code Register */
-#define	CAN_MB13_TIMESTAMP	0xFFC02DB4	/* Mailbox 13 Time Stamp Value Register */
-#define	CAN_MB13_ID0		0xFFC02DB8	/* Mailbox 13 Identifier Low Register */
-#define	CAN_MB13_ID1		0xFFC02DBC	/* Mailbox 13 Identifier High Register */
-
-#define	CAN_MB14_DATA0		0xFFC02DC0	/* Mailbox 14 Data Word	0 [15:0] Register */
-#define	CAN_MB14_DATA1		0xFFC02DC4	/* Mailbox 14 Data Word	1 [31:16] Register */
-#define	CAN_MB14_DATA2		0xFFC02DC8	/* Mailbox 14 Data Word	2 [47:32] Register */
-#define	CAN_MB14_DATA3		0xFFC02DCC	/* Mailbox 14 Data Word	3 [63:48] Register */
-#define	CAN_MB14_LENGTH		0xFFC02DD0	/* Mailbox 14 Data Length Code Register */
-#define	CAN_MB14_TIMESTAMP	0xFFC02DD4	/* Mailbox 14 Time Stamp Value Register */
-#define	CAN_MB14_ID0		0xFFC02DD8	/* Mailbox 14 Identifier Low Register */
-#define	CAN_MB14_ID1		0xFFC02DDC	/* Mailbox 14 Identifier High Register */
-
-#define	CAN_MB15_DATA0		0xFFC02DE0	/* Mailbox 15 Data Word	0 [15:0] Register */
-#define	CAN_MB15_DATA1		0xFFC02DE4	/* Mailbox 15 Data Word	1 [31:16] Register */
-#define	CAN_MB15_DATA2		0xFFC02DE8	/* Mailbox 15 Data Word	2 [47:32] Register */
-#define	CAN_MB15_DATA3		0xFFC02DEC	/* Mailbox 15 Data Word	3 [63:48] Register */
-#define	CAN_MB15_LENGTH		0xFFC02DF0	/* Mailbox 15 Data Length Code Register */
-#define	CAN_MB15_TIMESTAMP	0xFFC02DF4	/* Mailbox 15 Time Stamp Value Register */
-#define	CAN_MB15_ID0		0xFFC02DF8	/* Mailbox 15 Identifier Low Register */
-#define	CAN_MB15_ID1		0xFFC02DFC	/* Mailbox 15 Identifier High Register */
-
-#define	CAN_MB16_DATA0		0xFFC02E00	/* Mailbox 16 Data Word	0 [15:0] Register */
-#define	CAN_MB16_DATA1		0xFFC02E04	/* Mailbox 16 Data Word	1 [31:16] Register */
-#define	CAN_MB16_DATA2		0xFFC02E08	/* Mailbox 16 Data Word	2 [47:32] Register */
-#define	CAN_MB16_DATA3		0xFFC02E0C	/* Mailbox 16 Data Word	3 [63:48] Register */
-#define	CAN_MB16_LENGTH		0xFFC02E10	/* Mailbox 16 Data Length Code Register */
-#define	CAN_MB16_TIMESTAMP	0xFFC02E14	/* Mailbox 16 Time Stamp Value Register */
-#define	CAN_MB16_ID0		0xFFC02E18	/* Mailbox 16 Identifier Low Register */
-#define	CAN_MB16_ID1		0xFFC02E1C	/* Mailbox 16 Identifier High Register */
-
-#define	CAN_MB17_DATA0		0xFFC02E20	/* Mailbox 17 Data Word	0 [15:0] Register */
-#define	CAN_MB17_DATA1		0xFFC02E24	/* Mailbox 17 Data Word	1 [31:16] Register */
-#define	CAN_MB17_DATA2		0xFFC02E28	/* Mailbox 17 Data Word	2 [47:32] Register */
-#define	CAN_MB17_DATA3		0xFFC02E2C	/* Mailbox 17 Data Word	3 [63:48] Register */
-#define	CAN_MB17_LENGTH		0xFFC02E30	/* Mailbox 17 Data Length Code Register */
-#define	CAN_MB17_TIMESTAMP	0xFFC02E34	/* Mailbox 17 Time Stamp Value Register */
-#define	CAN_MB17_ID0		0xFFC02E38	/* Mailbox 17 Identifier Low Register */
-#define	CAN_MB17_ID1		0xFFC02E3C	/* Mailbox 17 Identifier High Register */
-
-#define	CAN_MB18_DATA0		0xFFC02E40	/* Mailbox 18 Data Word	0 [15:0] Register */
-#define	CAN_MB18_DATA1		0xFFC02E44	/* Mailbox 18 Data Word	1 [31:16] Register */
-#define	CAN_MB18_DATA2		0xFFC02E48	/* Mailbox 18 Data Word	2 [47:32] Register */
-#define	CAN_MB18_DATA3		0xFFC02E4C	/* Mailbox 18 Data Word	3 [63:48] Register */
-#define	CAN_MB18_LENGTH		0xFFC02E50	/* Mailbox 18 Data Length Code Register */
-#define	CAN_MB18_TIMESTAMP	0xFFC02E54	/* Mailbox 18 Time Stamp Value Register */
-#define	CAN_MB18_ID0		0xFFC02E58	/* Mailbox 18 Identifier Low Register */
-#define	CAN_MB18_ID1		0xFFC02E5C	/* Mailbox 18 Identifier High Register */
-
-#define	CAN_MB19_DATA0		0xFFC02E60	/* Mailbox 19 Data Word	0 [15:0] Register */
-#define	CAN_MB19_DATA1		0xFFC02E64	/* Mailbox 19 Data Word	1 [31:16] Register */
-#define	CAN_MB19_DATA2		0xFFC02E68	/* Mailbox 19 Data Word	2 [47:32] Register */
-#define	CAN_MB19_DATA3		0xFFC02E6C	/* Mailbox 19 Data Word	3 [63:48] Register */
-#define	CAN_MB19_LENGTH		0xFFC02E70	/* Mailbox 19 Data Length Code Register */
-#define	CAN_MB19_TIMESTAMP	0xFFC02E74	/* Mailbox 19 Time Stamp Value Register */
-#define	CAN_MB19_ID0		0xFFC02E78	/* Mailbox 19 Identifier Low Register */
-#define	CAN_MB19_ID1		0xFFC02E7C	/* Mailbox 19 Identifier High Register */
-
-#define	CAN_MB20_DATA0		0xFFC02E80	/* Mailbox 20 Data Word	0 [15:0] Register */
-#define	CAN_MB20_DATA1		0xFFC02E84	/* Mailbox 20 Data Word	1 [31:16] Register */
-#define	CAN_MB20_DATA2		0xFFC02E88	/* Mailbox 20 Data Word	2 [47:32] Register */
-#define	CAN_MB20_DATA3		0xFFC02E8C	/* Mailbox 20 Data Word	3 [63:48] Register */
-#define	CAN_MB20_LENGTH		0xFFC02E90	/* Mailbox 20 Data Length Code Register */
-#define	CAN_MB20_TIMESTAMP	0xFFC02E94	/* Mailbox 20 Time Stamp Value Register */
-#define	CAN_MB20_ID0		0xFFC02E98	/* Mailbox 20 Identifier Low Register */
-#define	CAN_MB20_ID1		0xFFC02E9C	/* Mailbox 20 Identifier High Register */
-
-#define	CAN_MB21_DATA0		0xFFC02EA0	/* Mailbox 21 Data Word	0 [15:0] Register */
-#define	CAN_MB21_DATA1		0xFFC02EA4	/* Mailbox 21 Data Word	1 [31:16] Register */
-#define	CAN_MB21_DATA2		0xFFC02EA8	/* Mailbox 21 Data Word	2 [47:32] Register */
-#define	CAN_MB21_DATA3		0xFFC02EAC	/* Mailbox 21 Data Word	3 [63:48] Register */
-#define	CAN_MB21_LENGTH		0xFFC02EB0	/* Mailbox 21 Data Length Code Register */
-#define	CAN_MB21_TIMESTAMP	0xFFC02EB4	/* Mailbox 21 Time Stamp Value Register */
-#define	CAN_MB21_ID0		0xFFC02EB8	/* Mailbox 21 Identifier Low Register */
-#define	CAN_MB21_ID1		0xFFC02EBC	/* Mailbox 21 Identifier High Register */
-
-#define	CAN_MB22_DATA0		0xFFC02EC0	/* Mailbox 22 Data Word	0 [15:0] Register */
-#define	CAN_MB22_DATA1		0xFFC02EC4	/* Mailbox 22 Data Word	1 [31:16] Register */
-#define	CAN_MB22_DATA2		0xFFC02EC8	/* Mailbox 22 Data Word	2 [47:32] Register */
-#define	CAN_MB22_DATA3		0xFFC02ECC	/* Mailbox 22 Data Word	3 [63:48] Register */
-#define	CAN_MB22_LENGTH		0xFFC02ED0	/* Mailbox 22 Data Length Code Register */
-#define	CAN_MB22_TIMESTAMP	0xFFC02ED4	/* Mailbox 22 Time Stamp Value Register */
-#define	CAN_MB22_ID0		0xFFC02ED8	/* Mailbox 22 Identifier Low Register */
-#define	CAN_MB22_ID1		0xFFC02EDC	/* Mailbox 22 Identifier High Register */
-
-#define	CAN_MB23_DATA0		0xFFC02EE0	/* Mailbox 23 Data Word	0 [15:0] Register */
-#define	CAN_MB23_DATA1		0xFFC02EE4	/* Mailbox 23 Data Word	1 [31:16] Register */
-#define	CAN_MB23_DATA2		0xFFC02EE8	/* Mailbox 23 Data Word	2 [47:32] Register */
-#define	CAN_MB23_DATA3		0xFFC02EEC	/* Mailbox 23 Data Word	3 [63:48] Register */
-#define	CAN_MB23_LENGTH		0xFFC02EF0	/* Mailbox 23 Data Length Code Register */
-#define	CAN_MB23_TIMESTAMP	0xFFC02EF4	/* Mailbox 23 Time Stamp Value Register */
-#define	CAN_MB23_ID0		0xFFC02EF8	/* Mailbox 23 Identifier Low Register */
-#define	CAN_MB23_ID1		0xFFC02EFC	/* Mailbox 23 Identifier High Register */
-
-#define	CAN_MB24_DATA0		0xFFC02F00	/* Mailbox 24 Data Word	0 [15:0] Register */
-#define	CAN_MB24_DATA1		0xFFC02F04	/* Mailbox 24 Data Word	1 [31:16] Register */
-#define	CAN_MB24_DATA2		0xFFC02F08	/* Mailbox 24 Data Word	2 [47:32] Register */
-#define	CAN_MB24_DATA3		0xFFC02F0C	/* Mailbox 24 Data Word	3 [63:48] Register */
-#define	CAN_MB24_LENGTH		0xFFC02F10	/* Mailbox 24 Data Length Code Register */
-#define	CAN_MB24_TIMESTAMP	0xFFC02F14	/* Mailbox 24 Time Stamp Value Register */
-#define	CAN_MB24_ID0		0xFFC02F18	/* Mailbox 24 Identifier Low Register */
-#define	CAN_MB24_ID1		0xFFC02F1C	/* Mailbox 24 Identifier High Register */
-
-#define	CAN_MB25_DATA0		0xFFC02F20	/* Mailbox 25 Data Word	0 [15:0] Register */
-#define	CAN_MB25_DATA1		0xFFC02F24	/* Mailbox 25 Data Word	1 [31:16] Register */
-#define	CAN_MB25_DATA2		0xFFC02F28	/* Mailbox 25 Data Word	2 [47:32] Register */
-#define	CAN_MB25_DATA3		0xFFC02F2C	/* Mailbox 25 Data Word	3 [63:48] Register */
-#define	CAN_MB25_LENGTH		0xFFC02F30	/* Mailbox 25 Data Length Code Register */
-#define	CAN_MB25_TIMESTAMP	0xFFC02F34	/* Mailbox 25 Time Stamp Value Register */
-#define	CAN_MB25_ID0		0xFFC02F38	/* Mailbox 25 Identifier Low Register */
-#define	CAN_MB25_ID1		0xFFC02F3C	/* Mailbox 25 Identifier High Register */
-
-#define	CAN_MB26_DATA0		0xFFC02F40	/* Mailbox 26 Data Word	0 [15:0] Register */
-#define	CAN_MB26_DATA1		0xFFC02F44	/* Mailbox 26 Data Word	1 [31:16] Register */
-#define	CAN_MB26_DATA2		0xFFC02F48	/* Mailbox 26 Data Word	2 [47:32] Register */
-#define	CAN_MB26_DATA3		0xFFC02F4C	/* Mailbox 26 Data Word	3 [63:48] Register */
-#define	CAN_MB26_LENGTH		0xFFC02F50	/* Mailbox 26 Data Length Code Register */
-#define	CAN_MB26_TIMESTAMP	0xFFC02F54	/* Mailbox 26 Time Stamp Value Register */
-#define	CAN_MB26_ID0		0xFFC02F58	/* Mailbox 26 Identifier Low Register */
-#define	CAN_MB26_ID1		0xFFC02F5C	/* Mailbox 26 Identifier High Register */
-
-#define	CAN_MB27_DATA0		0xFFC02F60	/* Mailbox 27 Data Word	0 [15:0] Register */
-#define	CAN_MB27_DATA1		0xFFC02F64	/* Mailbox 27 Data Word	1 [31:16] Register */
-#define	CAN_MB27_DATA2		0xFFC02F68	/* Mailbox 27 Data Word	2 [47:32] Register */
-#define	CAN_MB27_DATA3		0xFFC02F6C	/* Mailbox 27 Data Word	3 [63:48] Register */
-#define	CAN_MB27_LENGTH		0xFFC02F70	/* Mailbox 27 Data Length Code Register */
-#define	CAN_MB27_TIMESTAMP	0xFFC02F74	/* Mailbox 27 Time Stamp Value Register */
-#define	CAN_MB27_ID0		0xFFC02F78	/* Mailbox 27 Identifier Low Register */
-#define	CAN_MB27_ID1		0xFFC02F7C	/* Mailbox 27 Identifier High Register */
-
-#define	CAN_MB28_DATA0		0xFFC02F80	/* Mailbox 28 Data Word	0 [15:0] Register */
-#define	CAN_MB28_DATA1		0xFFC02F84	/* Mailbox 28 Data Word	1 [31:16] Register */
-#define	CAN_MB28_DATA2		0xFFC02F88	/* Mailbox 28 Data Word	2 [47:32] Register */
-#define	CAN_MB28_DATA3		0xFFC02F8C	/* Mailbox 28 Data Word	3 [63:48] Register */
-#define	CAN_MB28_LENGTH		0xFFC02F90	/* Mailbox 28 Data Length Code Register */
-#define	CAN_MB28_TIMESTAMP	0xFFC02F94	/* Mailbox 28 Time Stamp Value Register */
-#define	CAN_MB28_ID0		0xFFC02F98	/* Mailbox 28 Identifier Low Register */
-#define	CAN_MB28_ID1		0xFFC02F9C	/* Mailbox 28 Identifier High Register */
-
-#define	CAN_MB29_DATA0		0xFFC02FA0	/* Mailbox 29 Data Word	0 [15:0] Register */
-#define	CAN_MB29_DATA1		0xFFC02FA4	/* Mailbox 29 Data Word	1 [31:16] Register */
-#define	CAN_MB29_DATA2		0xFFC02FA8	/* Mailbox 29 Data Word	2 [47:32] Register */
-#define	CAN_MB29_DATA3		0xFFC02FAC	/* Mailbox 29 Data Word	3 [63:48] Register */
-#define	CAN_MB29_LENGTH		0xFFC02FB0	/* Mailbox 29 Data Length Code Register */
-#define	CAN_MB29_TIMESTAMP	0xFFC02FB4	/* Mailbox 29 Time Stamp Value Register */
-#define	CAN_MB29_ID0		0xFFC02FB8	/* Mailbox 29 Identifier Low Register */
-#define	CAN_MB29_ID1		0xFFC02FBC	/* Mailbox 29 Identifier High Register */
-
-#define	CAN_MB30_DATA0		0xFFC02FC0	/* Mailbox 30 Data Word	0 [15:0] Register */
-#define	CAN_MB30_DATA1		0xFFC02FC4	/* Mailbox 30 Data Word	1 [31:16] Register */
-#define	CAN_MB30_DATA2		0xFFC02FC8	/* Mailbox 30 Data Word	2 [47:32] Register */
-#define	CAN_MB30_DATA3		0xFFC02FCC	/* Mailbox 30 Data Word	3 [63:48] Register */
-#define	CAN_MB30_LENGTH		0xFFC02FD0	/* Mailbox 30 Data Length Code Register */
-#define	CAN_MB30_TIMESTAMP	0xFFC02FD4	/* Mailbox 30 Time Stamp Value Register */
-#define	CAN_MB30_ID0		0xFFC02FD8	/* Mailbox 30 Identifier Low Register */
-#define	CAN_MB30_ID1		0xFFC02FDC	/* Mailbox 30 Identifier High Register */
-
-#define	CAN_MB31_DATA0		0xFFC02FE0	/* Mailbox 31 Data Word	0 [15:0] Register */
-#define	CAN_MB31_DATA1		0xFFC02FE4	/* Mailbox 31 Data Word	1 [31:16] Register */
-#define	CAN_MB31_DATA2		0xFFC02FE8	/* Mailbox 31 Data Word	2 [47:32] Register */
-#define	CAN_MB31_DATA3		0xFFC02FEC	/* Mailbox 31 Data Word	3 [63:48] Register */
-#define	CAN_MB31_LENGTH		0xFFC02FF0	/* Mailbox 31 Data Length Code Register */
-#define	CAN_MB31_TIMESTAMP	0xFFC02FF4	/* Mailbox 31 Time Stamp Value Register */
-#define	CAN_MB31_ID0		0xFFC02FF8	/* Mailbox 31 Identifier Low Register */
-#define	CAN_MB31_ID1		0xFFC02FFC	/* Mailbox 31 Identifier High Register */
-
-/* CAN Mailbox Area Macros */
-#define	CAN_MB_ID1(x)		(CAN_MB00_ID1+((x)*0x20))
-#define	CAN_MB_ID0(x)		(CAN_MB00_ID0+((x)*0x20))
-#define	CAN_MB_TIMESTAMP(x)	(CAN_MB00_TIMESTAMP+((x)*0x20))
-#define	CAN_MB_LENGTH(x)	(CAN_MB00_LENGTH+((x)*0x20))
-#define	CAN_MB_DATA3(x)		(CAN_MB00_DATA3+((x)*0x20))
-#define	CAN_MB_DATA2(x)		(CAN_MB00_DATA2+((x)*0x20))
-#define	CAN_MB_DATA1(x)		(CAN_MB00_DATA1+((x)*0x20))
-#define	CAN_MB_DATA0(x)		(CAN_MB00_DATA0+((x)*0x20))
-
-
-/*********************************************************************************** */
-/* System MMR Register Bits and	Macros */
-/******************************************************************************* */
-
-/* SWRST Mask */
-#define	SYSTEM_RESET	0x0007	/* Initiates A System Software Reset */
-#define	DOUBLE_FAULT	0x0008	/* Core	Double Fault Causes Reset */
-#define	RESET_DOUBLE	0x2000	/* SW Reset Generated By Core Double-Fault */
-#define	RESET_WDOG		0x4000	/* SW Reset Generated By Watchdog Timer */
-#define	RESET_SOFTWARE	0x8000	/* SW Reset Occurred Since Last	Read Of	SWRST */
-
-/* SYSCR Masks													 */
-#define	BMODE			0x0006	/* Boot	Mode - Latched During HW Reset From Mode Pins */
-#define	NOBOOT			0x0010	/* Execute From	L1 or ASYNC Bank 0 When	BMODE =	0 */
-
-
-/* *************  SYSTEM INTERRUPT CONTROLLER MASKS ***************** */
-
-/* Peripheral Masks For	SIC0_ISR, SIC0_IWR, SIC0_IMASK */
-#define	PLL_WAKEUP_IRQ		0x00000001	/* PLL Wakeup Interrupt	Request */
-#define	DMAC0_ERR_IRQ		0x00000002	/* DMA Controller 0 Error Interrupt Request */
-#define	PPI_ERR_IRQ		0x00000004	/* PPI Error Interrupt Request */
-#define	SPORT0_ERR_IRQ		0x00000008	/* SPORT0 Error	Interrupt Request */
-#define	SPORT1_ERR_IRQ		0x00000010	/* SPORT1 Error	Interrupt Request */
-#define	SPI0_ERR_IRQ		0x00000020	/* SPI0	Error Interrupt	Request */
-#define	UART0_ERR_IRQ		0x00000040	/* UART0 Error Interrupt Request */
-#define	RTC_IRQ			0x00000080	/* Real-Time Clock Interrupt Request */
-#define	DMA0_IRQ		0x00000100	/* DMA Channel 0 (PPI) Interrupt Request */
-#define	DMA1_IRQ		0x00000200	/* DMA Channel 1 (SPORT0 RX) Interrupt Request */
-#define	DMA2_IRQ		0x00000400	/* DMA Channel 2 (SPORT0 TX) Interrupt Request */
-#define	DMA3_IRQ		0x00000800	/* DMA Channel 3 (SPORT1 RX) Interrupt Request */
-#define	DMA4_IRQ		0x00001000	/* DMA Channel 4 (SPORT1 TX) Interrupt Request */
-#define	DMA5_IRQ		0x00002000	/* DMA Channel 5 (SPI) Interrupt Request */
-#define	DMA6_IRQ		0x00004000	/* DMA Channel 6 (UART RX) Interrupt Request */
-#define	DMA7_IRQ		0x00008000	/* DMA Channel 7 (UART TX) Interrupt Request */
-#define	TIMER0_IRQ		0x00010000	/* Timer 0 Interrupt Request */
-#define	TIMER1_IRQ		0x00020000	/* Timer 1 Interrupt Request */
-#define	TIMER2_IRQ		0x00040000	/* Timer 2 Interrupt Request */
-#define	PFA_IRQ			0x00080000	/* Programmable	Flag Interrupt Request A */
-#define	PFB_IRQ			0x00100000	/* Programmable	Flag Interrupt Request B */
-#define	MDMA0_0_IRQ		0x00200000	/* MemDMA0 Stream 0 Interrupt Request */
-#define	MDMA0_1_IRQ		0x00400000	/* MemDMA0 Stream 1 Interrupt Request */
-#define	WDOG_IRQ		0x00800000	/* Software Watchdog Timer Interrupt Request */
-#define	DMAC1_ERR_IRQ		0x01000000	/* DMA Controller 1 Error Interrupt Request */
-#define	SPORT2_ERR_IRQ		0x02000000	/* SPORT2 Error	Interrupt Request */
-#define	SPORT3_ERR_IRQ		0x04000000	/* SPORT3 Error	Interrupt Request */
-#define	MXVR_SD_IRQ		0x08000000	/* MXVR	Synchronous Data Interrupt Request */
-#define	SPI1_ERR_IRQ		0x10000000	/* SPI1	Error Interrupt	Request */
-#define	SPI2_ERR_IRQ		0x20000000	/* SPI2	Error Interrupt	Request */
-#define	UART1_ERR_IRQ		0x40000000	/* UART1 Error Interrupt Request */
-#define	UART2_ERR_IRQ		0x80000000	/* UART2 Error Interrupt Request */
-
-/* the following are for backwards compatibility */
-#define	DMA0_ERR_IRQ		DMAC0_ERR_IRQ
-#define	DMA1_ERR_IRQ		DMAC1_ERR_IRQ
-
-
-/* Peripheral Masks For	SIC_ISR1, SIC_IWR1, SIC_IMASK1	 */
-#define	CAN_ERR_IRQ			0x00000001	/* CAN Error Interrupt Request */
-#define	DMA8_IRQ			0x00000002	/* DMA Channel 8 (SPORT2 RX) Interrupt Request */
-#define	DMA9_IRQ			0x00000004	/* DMA Channel 9 (SPORT2 TX) Interrupt Request */
-#define	DMA10_IRQ			0x00000008	/* DMA Channel 10 (SPORT3 RX) Interrupt	Request */
-#define	DMA11_IRQ			0x00000010	/* DMA Channel 11 (SPORT3 TX) Interrupt	Request */
-#define	DMA12_IRQ			0x00000020	/* DMA Channel 12 Interrupt Request */
-#define	DMA13_IRQ			0x00000040	/* DMA Channel 13 Interrupt Request */
-#define	DMA14_IRQ			0x00000080	/* DMA Channel 14 (SPI1) Interrupt Request */
-#define	DMA15_IRQ			0x00000100	/* DMA Channel 15 (SPI2) Interrupt Request */
-#define	DMA16_IRQ			0x00000200	/* DMA Channel 16 (UART1 RX) Interrupt Request */
-#define	DMA17_IRQ			0x00000400	/* DMA Channel 17 (UART1 TX) Interrupt Request */
-#define	DMA18_IRQ			0x00000800	/* DMA Channel 18 (UART2 RX) Interrupt Request */
-#define	DMA19_IRQ			0x00001000	/* DMA Channel 19 (UART2 TX) Interrupt Request */
-#define	TWI0_IRQ			0x00002000	/* TWI0	Interrupt Request */
-#define	TWI1_IRQ			0x00004000	/* TWI1	Interrupt Request */
-#define	CAN_RX_IRQ			0x00008000	/* CAN Receive Interrupt Request */
-#define	CAN_TX_IRQ			0x00010000	/* CAN Transmit	Interrupt Request */
-#define	MDMA1_0_IRQ			0x00020000	/* MemDMA1 Stream 0 Interrupt Request */
-#define	MDMA1_1_IRQ			0x00040000	/* MemDMA1 Stream 1 Interrupt Request */
-#define	MXVR_STAT_IRQ			0x00080000	/* MXVR	Status Interrupt Request */
-#define	MXVR_CM_IRQ			0x00100000	/* MXVR	Control	Message	Interrupt Request */
-#define	MXVR_AP_IRQ			0x00200000	/* MXVR	Asynchronous Packet Interrupt */
-
-/* the following are for backwards compatibility */
-#define	MDMA0_IRQ		MDMA1_0_IRQ
-#define	MDMA1_IRQ		MDMA1_1_IRQ
-
-#ifdef _MISRA_RULES
-#define	_MF15 0xFu
-#define	_MF7 7u
-#else
-#define	_MF15 0xF
-#define	_MF7 7
-#endif /* _MISRA_RULES */
-
-/* SIC_IMASKx Masks											 */
-#define	SIC_UNMASK_ALL	0x00000000					/* Unmask all peripheral interrupts */
-#define	SIC_MASK_ALL	0xFFFFFFFF					/* Mask	all peripheral interrupts */
-#ifdef _MISRA_RULES
-#define	SIC_MASK(x)		(1 << ((x)&0x1Fu))					/* Mask	Peripheral #x interrupt */
-#define	SIC_UNMASK(x)	(0xFFFFFFFFu ^ (1 << ((x)&0x1Fu)))	/* Unmask Peripheral #x	interrupt */
-#else
-#define	SIC_MASK(x)		(1 << ((x)&0x1F))					/* Mask	Peripheral #x interrupt */
-#define	SIC_UNMASK(x)	(0xFFFFFFFF ^ (1 << ((x)&0x1F)))	/* Unmask Peripheral #x	interrupt */
-#endif /* _MISRA_RULES */
-
-/* SIC_IWRx Masks											 */
-#define	IWR_DISABLE_ALL	0x00000000					/* Wakeup Disable all peripherals */
-#define	IWR_ENABLE_ALL	0xFFFFFFFF					/* Wakeup Enable all peripherals */
-#ifdef _MISRA_RULES
-#define	IWR_ENABLE(x)	(1 << ((x)&0x1Fu))					/* Wakeup Enable Peripheral #x */
-#define	IWR_DISABLE(x)	(0xFFFFFFFFu ^ (1 << ((x)&0x1Fu)))	/* Wakeup Disable Peripheral #x */
-#else
-#define	IWR_ENABLE(x)	(1 << ((x)&0x1F))					/* Wakeup Enable Peripheral #x */
-#define	IWR_DISABLE(x)	(0xFFFFFFFF ^ (1 << ((x)&0x1F)))	/* Wakeup Disable Peripheral #x */
-#endif /* _MISRA_RULES */
-
-
-/* ***************************** UART CONTROLLER MASKS ********************** */
-/* UARTx_LCR Register */
-#ifdef _MISRA_RULES
-#define	WLS(x)		(((x)-5u) & 0x03u)	/* Word	Length Select */
-#else
-#define	WLS(x)		(((x)-5) & 0x03)	/* Word	Length Select */
-#endif /* _MISRA_RULES */
-#define	STB			0x04				/* Stop	Bits */
-#define	PEN			0x08				/* Parity Enable */
-#define	EPS			0x10				/* Even	Parity Select */
-#define	STP			0x20				/* Stick Parity */
-#define	SB			0x40				/* Set Break */
-#define	DLAB		0x80				/* Divisor Latch Access */
-
-#define	DLAB_P		0x07
-#define	SB_P		0x06
-#define	STP_P		0x05
-#define	EPS_P		0x04
-#define	PEN_P		0x03
-#define	STB_P		0x02
-#define	WLS_P1		0x01
-#define	WLS_P0		0x00
-
-/* UARTx_MCR Register */
-#define	LOOP_ENA	0x10	/* Loopback Mode Enable */
-#define	LOOP_ENA_P	0x04
-/* Deprecated UARTx_MCR	Mask			 */
-
-/* UARTx_LSR Register */
-#define	DR			0x01	/* Data	Ready */
-#define	OE			0x02	/* Overrun Error */
-#define	PE			0x04	/* Parity Error */
-#define	FE			0x08	/* Framing Error */
-#define	BI			0x10	/* Break Interrupt */
-#define	THRE		0x20	/* THR Empty */
-#define	TEMT		0x40	/* TSR and UART_THR Empty */
-
-#define	TEMP_P		0x06
-#define	THRE_P		0x05
-#define	BI_P		0x04
-#define	FE_P		0x03
-#define	PE_P		0x02
-#define	OE_P		0x01
-#define	DR_P		0x00
-
-/* UARTx_IER Register */
-#define	ERBFI		0x01		/* Enable Receive Buffer Full Interrupt */
-#define	ETBEI		0x02		/* Enable Transmit Buffer Empty	Interrupt */
-#define	ELSI		0x04		/* Enable RX Status Interrupt */
-
-#define	ELSI_P		0x02
-#define	ETBEI_P		0x01
-#define	ERBFI_P		0x00
-
-/* UARTx_IIR Register */
-#define	NINT		0x01
-#define	STATUS_P1	0x02
-#define	STATUS_P0	0x01
-#define	NINT_P		0x00
-
-/* UARTx_GCTL Register */
-#define	UCEN		0x01		/* Enable UARTx	Clocks */
-#define	IREN		0x02		/* Enable IrDA Mode */
-#define	TPOLC		0x04		/* IrDA	TX Polarity Change */
-#define	RPOLC		0x08		/* IrDA	RX Polarity Change */
-#define	FPE			0x10		/* Force Parity	Error On Transmit */
-#define	FFE			0x20		/* Force Framing Error On Transmit */
-
-#define	FFE_P		0x05
-#define	FPE_P		0x04
-#define	RPOLC_P		0x03
-#define	TPOLC_P		0x02
-#define	IREN_P		0x01
-#define	UCEN_P		0x00
-
-
-/*  *********  PARALLEL	PERIPHERAL INTERFACE (PPI) MASKS ****************   */
-/*  PPI_CONTROL	Masks	      */
-#define	PORT_EN		0x0001	/* PPI Port Enable  */
-#define	PORT_DIR	0x0002	/* PPI Port Direction	    */
-#define	XFR_TYPE	0x000C	/* PPI Transfer	Type  */
-#define	PORT_CFG	0x0030	/* PPI Port Configuration */
-#define	FLD_SEL		0x0040	/* PPI Active Field Select */
-#define	PACK_EN		0x0080	/* PPI Packing Mode */
-/* previous versions of	defBF539.h erroneously included	DMA32 (PPI 32-bit DMA Enable) */
-#define	SKIP_EN		0x0200	/* PPI Skip Element Enable */
-#define	SKIP_EO		0x0400	/* PPI Skip Even/Odd Elements */
-#define	DLENGTH		0x3800	/* PPI Data Length  */
-#define	DLEN_8		0x0	     /*	PPI Data Length	mask for DLEN=8 */
-#define	DLEN_10		0x0800		/* Data	Length = 10 Bits */
-#define	DLEN_11		0x1000		/* Data	Length = 11 Bits */
-#define	DLEN_12		0x1800		/* Data	Length = 12 Bits */
-#define	DLEN_13		0x2000		/* Data	Length = 13 Bits */
-#define	DLEN_14		0x2800		/* Data	Length = 14 Bits */
-#define	DLEN_15		0x3000		/* Data	Length = 15 Bits */
-#define	DLEN_16		0x3800		/* Data	Length = 16 Bits */
-#ifdef _MISRA_RULES
-#define	DLEN(x)		((((x)-9u) & 0x07u) << 11)  /* PPI Data	Length (only works for x=10-->x=16) */
-#else
-#define	DLEN(x)		((((x)-9) & 0x07) << 11)  /* PPI Data Length (only works for x=10-->x=16) */
-#endif /* _MISRA_RULES */
-#define	POL			0xC000	/* PPI Signal Polarities       */
-#define	POLC		0x4000		/* PPI Clock Polarity */
-#define	POLS		0x8000		/* PPI Frame Sync Polarity */
-
-
-/* PPI_STATUS Masks					     */
-#define	FLD			0x0400	/* Field Indicator   */
-#define	FT_ERR		0x0800	/* Frame Track Error */
-#define	OVR			0x1000	/* FIFO	Overflow Error */
-#define	UNDR		0x2000	/* FIFO	Underrun Error */
-#define	ERR_DET		0x4000	/* Error Detected Indicator */
-#define	ERR_NCOR	0x8000	/* Error Not Corrected Indicator */
-
-
-/* **********  DMA CONTROLLER MASKS  ***********************/
-
-/* DMAx_PERIPHERAL_MAP,	MDMA_yy_PERIPHERAL_MAP Masks */
-
-#define	CTYPE			0x0040	/* DMA Channel Type Indicator */
-#define	CTYPE_P			0x6		/* DMA Channel Type Indicator BIT POSITION */
-#define	PCAP8			0x0080	/* DMA 8-bit Operation Indicator   */
-#define	PCAP16			0x0100	/* DMA 16-bit Operation	Indicator */
-#define	PCAP32			0x0200	/* DMA 32-bit Operation	Indicator */
-#define	PCAPWR			0x0400	/* DMA Write Operation Indicator */
-#define	PCAPRD			0x0800	/* DMA Read Operation Indicator */
-#define	PMAP			0xF000	/* DMA Peripheral Map Field */
-
-/* PMAP	Encodings For DMA Controller 0 */
-#define	PMAP_PPI		0x0000	/* PMAP	PPI Port DMA */
-#define	PMAP_SPORT0RX	0x1000	/* PMAP	SPORT0 Receive DMA */
-#define	PMAP_SPORT0TX	0x2000	/* PMAP	SPORT0 Transmit	DMA */
-#define	PMAP_SPORT1RX	0x3000	/* PMAP	SPORT1 Receive DMA */
-#define	PMAP_SPORT1TX	0x4000	/* PMAP	SPORT1 Transmit	DMA */
-#define	PMAP_SPI0		0x5000	/* PMAP	SPI DMA */
-#define	PMAP_UART0RX		0x6000	/* PMAP	UART Receive DMA */
-#define	PMAP_UART0TX		0x7000	/* PMAP	UART Transmit DMA */
-
-/* PMAP	Encodings For DMA Controller 1 */
-#define	PMAP_SPORT2RX	    0x0000  /* PMAP SPORT2 Receive DMA */
-#define	PMAP_SPORT2TX	    0x1000  /* PMAP SPORT2 Transmit DMA */
-#define	PMAP_SPORT3RX	    0x2000  /* PMAP SPORT3 Receive DMA */
-#define	PMAP_SPORT3TX	    0x3000  /* PMAP SPORT3 Transmit DMA */
-#define	PMAP_SPI1	    0x6000  /* PMAP SPI1 DMA */
-#define	PMAP_SPI2	    0x7000  /* PMAP SPI2 DMA */
-#define	PMAP_UART1RX	    0x8000  /* PMAP UART1 Receive DMA */
-#define	PMAP_UART1TX	    0x9000  /* PMAP UART1 Transmit DMA */
-#define	PMAP_UART2RX	    0xA000  /* PMAP UART2 Receive DMA */
-#define	PMAP_UART2TX	    0xB000  /* PMAP UART2 Transmit DMA */
-
-
-/*  *************  GENERAL PURPOSE TIMER MASKS	******************** */
-/* PWM Timer bit definitions */
-/* TIMER_ENABLE	Register */
-#define	TIMEN0			0x0001	/* Enable Timer	0 */
-#define	TIMEN1			0x0002	/* Enable Timer	1 */
-#define	TIMEN2			0x0004	/* Enable Timer	2 */
-
-#define	TIMEN0_P		0x00
-#define	TIMEN1_P		0x01
-#define	TIMEN2_P		0x02
-
-/* TIMER_DISABLE Register */
-#define	TIMDIS0			0x0001	/* Disable Timer 0 */
-#define	TIMDIS1			0x0002	/* Disable Timer 1 */
-#define	TIMDIS2			0x0004	/* Disable Timer 2 */
-
-#define	TIMDIS0_P		0x00
-#define	TIMDIS1_P		0x01
-#define	TIMDIS2_P		0x02
-
-/* TIMER_STATUS	Register */
-#define	TIMIL0			0x0001	/* Timer 0 Interrupt */
-#define	TIMIL1			0x0002	/* Timer 1 Interrupt */
-#define	TIMIL2			0x0004	/* Timer 2 Interrupt */
-#define	TOVF_ERR0		0x0010	/* Timer 0 Counter Overflow */
-#define	TOVF_ERR1		0x0020	/* Timer 1 Counter Overflow */
-#define	TOVF_ERR2		0x0040	/* Timer 2 Counter Overflow */
-#define	TRUN0			0x1000	/* Timer 0 Slave Enable	Status */
-#define	TRUN1			0x2000	/* Timer 1 Slave Enable	Status */
-#define	TRUN2			0x4000	/* Timer 2 Slave Enable	Status */
-
-#define	TIMIL0_P		0x00
-#define	TIMIL1_P		0x01
-#define	TIMIL2_P		0x02
-#define	TOVF_ERR0_P		0x04
-#define	TOVF_ERR1_P		0x05
-#define	TOVF_ERR2_P		0x06
-#define	TRUN0_P			0x0C
-#define	TRUN1_P			0x0D
-#define	TRUN2_P			0x0E
-
-/* Alternate Deprecated	Macros Provided	For Backwards Code Compatibility */
-#define	TOVL_ERR0		TOVF_ERR0
-#define	TOVL_ERR1		TOVF_ERR1
-#define	TOVL_ERR2		TOVF_ERR2
-#define	TOVL_ERR0_P		TOVF_ERR0_P
-#define	TOVL_ERR1_P	TOVF_ERR1_P
-#define	TOVL_ERR2_P	TOVF_ERR2_P
-
-/* TIMERx_CONFIG Registers */
-#define	PWM_OUT			0x0001
-#define	WDTH_CAP		0x0002
-#define	EXT_CLK			0x0003
-#define	PULSE_HI		0x0004
-#define	PERIOD_CNT		0x0008
-#define	IRQ_ENA			0x0010
-#define	TIN_SEL			0x0020
-#define	OUT_DIS			0x0040
-#define	CLK_SEL			0x0080
-#define	TOGGLE_HI		0x0100
-#define	EMU_RUN			0x0200
-#ifdef _MISRA_RULES
-#define	ERR_TYP(x)		(((x) &	0x03u) << 14)
-#else
-#define	ERR_TYP(x)		(((x) &	0x03) << 14)
-#endif /* _MISRA_RULES */
-
-#define	TMODE_P0		0x00
-#define	TMODE_P1		0x01
-#define	PULSE_HI_P		0x02
-#define	PERIOD_CNT_P	0x03
-#define	IRQ_ENA_P		0x04
-#define	TIN_SEL_P		0x05
-#define	OUT_DIS_P		0x06
-#define	CLK_SEL_P		0x07
-#define	TOGGLE_HI_P		0x08
-#define	EMU_RUN_P		0x09
-#define	ERR_TYP_P0		0x0E
-#define	ERR_TYP_P1		0x0F
-
-
-/*/ ******************	 GENERAL-PURPOSE I/O  ********************* */
-/*  Flag I/O (FIO_) Masks */
-#define	PF0			0x0001
-#define	PF1			0x0002
-#define	PF2			0x0004
-#define	PF3			0x0008
-#define	PF4			0x0010
-#define	PF5			0x0020
-#define	PF6			0x0040
-#define	PF7			0x0080
-#define	PF8			0x0100
-#define	PF9			0x0200
-#define	PF10		0x0400
-#define	PF11		0x0800
-#define	PF12		0x1000
-#define	PF13		0x2000
-#define	PF14		0x4000
-#define	PF15		0x8000
-
-/*  PORT F BIT POSITIONS */
-#define	PF0_P		0x0
-#define	PF1_P		0x1
-#define	PF2_P		0x2
-#define	PF3_P		0x3
-#define	PF4_P		0x4
-#define	PF5_P		0x5
-#define	PF6_P		0x6
-#define	PF7_P		0x7
-#define	PF8_P		0x8
-#define	PF9_P		0x9
-#define	PF10_P		0xA
-#define	PF11_P		0xB
-#define	PF12_P		0xC
-#define	PF13_P		0xD
-#define	PF14_P		0xE
-#define	PF15_P		0xF
-
-
-/*******************   GPIO MASKS  *********************/
-/* Port	C Masks */
-#define	PC0		0x0001
-#define	PC1		0x0002
-#define	PC4		0x0010
-#define	PC5		0x0020
-#define	PC6		0x0040
-#define	PC7		0x0080
-#define	PC8		0x0100
-#define	PC9		0x0200
-/* Port	C Bit Positions */
-#define	PC0_P	0x0
-#define	PC1_P	0x1
-#define	PC4_P	0x4
-#define	PC5_P	0x5
-#define	PC6_P	0x6
-#define	PC7_P	0x7
-#define	PC8_P	0x8
-#define	PC9_P	0x9
-
-/* Port	D */
-#define	PD0		0x0001
-#define	PD1		0x0002
-#define	PD2		0x0004
-#define	PD3		0x0008
-#define	PD4		0x0010
-#define	PD5		0x0020
-#define	PD6		0x0040
-#define	PD7		0x0080
-#define	PD8		0x0100
-#define	PD9		0x0200
-#define	PD10	0x0400
-#define	PD11	0x0800
-#define	PD12	0x1000
-#define	PD13	0x2000
-#define	PD14	0x4000
-#define	PD15	0x8000
-/* Port	D Bit Positions */
-#define	PD0_P	0x0
-#define	PD1_P	0x1
-#define	PD2_P	0x2
-#define	PD3_P	0x3
-#define	PD4_P	0x4
-#define	PD5_P	0x5
-#define	PD6_P	0x6
-#define	PD7_P	0x7
-#define	PD8_P	0x8
-#define	PD9_P	0x9
-#define	PD10_P	0xA
-#define	PD11_P	0xB
-#define	PD12_P	0xC
-#define	PD13_P	0xD
-#define	PD14_P	0xE
-#define	PD15_P	0xF
-
-/* Port	E */
-#define	PE0		0x0001
-#define	PE1		0x0002
-#define	PE2		0x0004
-#define	PE3		0x0008
-#define	PE4		0x0010
-#define	PE5		0x0020
-#define	PE6		0x0040
-#define	PE7		0x0080
-#define	PE8		0x0100
-#define	PE9		0x0200
-#define	PE10	0x0400
-#define	PE11	0x0800
-#define	PE12	0x1000
-#define	PE13	0x2000
-#define	PE14	0x4000
-#define	PE15	0x8000
-/* Port	E Bit Positions */
-#define	PE0_P	0x0
-#define	PE1_P	0x1
-#define	PE2_P	0x2
-#define	PE3_P	0x3
-#define	PE4_P	0x4
-#define	PE5_P	0x5
-#define	PE6_P	0x6
-#define	PE7_P	0x7
-#define	PE8_P	0x8
-#define	PE9_P	0x9
-#define	PE10_P	0xA
-#define	PE11_P	0xB
-#define	PE12_P	0xC
-#define	PE13_P	0xD
-#define	PE14_P	0xE
-#define	PE15_P	0xF
-
-/* *********************  ASYNCHRONOUS MEMORY CONTROLLER MASKS	************* */
-/* EBIU_AMGCTL Masks */
-#define	AMCKEN		0x0001	/* Enable CLKOUT */
-#define	AMBEN_NONE	0x0000	/* All Banks Disabled */
-#define	AMBEN_B0	0x0002	/* Enable Asynchronous Memory Bank 0 only */
-#define	AMBEN_B0_B1	0x0004	/* Enable Asynchronous Memory Banks 0 &	1 only */
-#define	AMBEN_B0_B1_B2	0x0006	/* Enable Asynchronous Memory Banks 0, 1, and 2 */
-#define	AMBEN_ALL	0x0008	/* Enable Asynchronous Memory Banks (all) 0, 1,	2, and 3 */
-#define	CDPRIO		0x0100	/* DMA has priority over core for external accesses */
-
-/* EBIU_AMGCTL Bit Positions */
-#define	AMCKEN_P		0x0000	/* Enable CLKOUT */
-#define	AMBEN_P0		0x0001	/* Asynchronous	Memory Enable, 000 - banks 0-3 disabled, 001 - Bank 0 enabled */
-#define	AMBEN_P1		0x0002	/* Asynchronous	Memory Enable, 010 - banks 0&1 enabled,	 011 - banks 0-3 enabled */
-#define	AMBEN_P2		0x0003	/* Asynchronous	Memory Enable, 1xx - All banks (bank 0,	1, 2, and 3) enabled */
-
-/* EBIU_AMBCTL0	Masks */
-#define	B0RDYEN			0x00000001  /* Bank 0 RDY Enable, 0=disable, 1=enable */
-#define	B0RDYPOL		0x00000002  /* Bank 0 RDY Active high, 0=active	low, 1=active high */
-#define	B0TT_1			0x00000004  /* Bank 0 Transition Time from Read	to Write = 1 cycle */
-#define	B0TT_2			0x00000008  /* Bank 0 Transition Time from Read	to Write = 2 cycles */
-#define	B0TT_3			0x0000000C  /* Bank 0 Transition Time from Read	to Write = 3 cycles */
-#define	B0TT_4			0x00000000  /* Bank 0 Transition Time from Read	to Write = 4 cycles */
-#define	B0ST_1			0x00000010  /* Bank 0 Setup Time from AOE asserted to Read/Write asserted=1 cycle */
-#define	B0ST_2			0x00000020  /* Bank 0 Setup Time from AOE asserted to Read/Write asserted=2 cycles */
-#define	B0ST_3			0x00000030  /* Bank 0 Setup Time from AOE asserted to Read/Write asserted=3 cycles */
-#define	B0ST_4			0x00000000  /* Bank 0 Setup Time from AOE asserted to Read/Write asserted=4 cycles */
-#define	B0HT_1			0x00000040  /* Bank 0 Hold Time	from Read/Write	deasserted to AOE deasserted = 1 cycle */
-#define	B0HT_2			0x00000080  /* Bank 0 Hold Time	from Read/Write	deasserted to AOE deasserted = 2 cycles */
-#define	B0HT_3			0x000000C0  /* Bank 0 Hold Time	from Read/Write	deasserted to AOE deasserted = 3 cycles */
-#define	B0HT_0			0x00000000  /* Bank 0 Hold Time	from Read/Write	deasserted to AOE deasserted = 0 cycles */
-#define	B0RAT_1			0x00000100  /* Bank 0 Read Access Time = 1 cycle */
-#define	B0RAT_2			0x00000200  /* Bank 0 Read Access Time = 2 cycles */
-#define	B0RAT_3			0x00000300  /* Bank 0 Read Access Time = 3 cycles */
-#define	B0RAT_4			0x00000400  /* Bank 0 Read Access Time = 4 cycles */
-#define	B0RAT_5			0x00000500  /* Bank 0 Read Access Time = 5 cycles */
-#define	B0RAT_6			0x00000600  /* Bank 0 Read Access Time = 6 cycles */
-#define	B0RAT_7			0x00000700  /* Bank 0 Read Access Time = 7 cycles */
-#define	B0RAT_8			0x00000800  /* Bank 0 Read Access Time = 8 cycles */
-#define	B0RAT_9			0x00000900  /* Bank 0 Read Access Time = 9 cycles */
-#define	B0RAT_10		0x00000A00  /* Bank 0 Read Access Time = 10 cycles */
-#define	B0RAT_11		0x00000B00  /* Bank 0 Read Access Time = 11 cycles */
-#define	B0RAT_12		0x00000C00  /* Bank 0 Read Access Time = 12 cycles */
-#define	B0RAT_13		0x00000D00  /* Bank 0 Read Access Time = 13 cycles */
-#define	B0RAT_14		0x00000E00  /* Bank 0 Read Access Time = 14 cycles */
-#define	B0RAT_15		0x00000F00  /* Bank 0 Read Access Time = 15 cycles */
-#define	B0WAT_1			0x00001000  /* Bank 0 Write Access Time	= 1 cycle */
-#define	B0WAT_2			0x00002000  /* Bank 0 Write Access Time	= 2 cycles */
-#define	B0WAT_3			0x00003000  /* Bank 0 Write Access Time	= 3 cycles */
-#define	B0WAT_4			0x00004000  /* Bank 0 Write Access Time	= 4 cycles */
-#define	B0WAT_5			0x00005000  /* Bank 0 Write Access Time	= 5 cycles */
-#define	B0WAT_6			0x00006000  /* Bank 0 Write Access Time	= 6 cycles */
-#define	B0WAT_7			0x00007000  /* Bank 0 Write Access Time	= 7 cycles */
-#define	B0WAT_8			0x00008000  /* Bank 0 Write Access Time	= 8 cycles */
-#define	B0WAT_9			0x00009000  /* Bank 0 Write Access Time	= 9 cycles */
-#define	B0WAT_10		0x0000A000  /* Bank 0 Write Access Time	= 10 cycles */
-#define	B0WAT_11		0x0000B000  /* Bank 0 Write Access Time	= 11 cycles */
-#define	B0WAT_12		0x0000C000  /* Bank 0 Write Access Time	= 12 cycles */
-#define	B0WAT_13		0x0000D000  /* Bank 0 Write Access Time	= 13 cycles */
-#define	B0WAT_14		0x0000E000  /* Bank 0 Write Access Time	= 14 cycles */
-#define	B0WAT_15		0x0000F000  /* Bank 0 Write Access Time	= 15 cycles */
-#define	B1RDYEN			0x00010000  /* Bank 1 RDY enable, 0=disable, 1=enable */
-#define	B1RDYPOL		0x00020000  /* Bank 1 RDY Active high, 0=active	low, 1=active high */
-#define	B1TT_1			0x00040000  /* Bank 1 Transition Time from Read	to Write = 1 cycle */
-#define	B1TT_2			0x00080000  /* Bank 1 Transition Time from Read	to Write = 2 cycles */
-#define	B1TT_3			0x000C0000  /* Bank 1 Transition Time from Read	to Write = 3 cycles */
-#define	B1TT_4			0x00000000  /* Bank 1 Transition Time from Read	to Write = 4 cycles */
-#define	B1ST_1			0x00100000  /* Bank 1 Setup Time from AOE asserted to Read or Write asserted = 1 cycle */
-#define	B1ST_2			0x00200000  /* Bank 1 Setup Time from AOE asserted to Read or Write asserted = 2 cycles */
-#define	B1ST_3			0x00300000  /* Bank 1 Setup Time from AOE asserted to Read or Write asserted = 3 cycles */
-#define	B1ST_4			0x00000000  /* Bank 1 Setup Time from AOE asserted to Read or Write asserted = 4 cycles */
-#define	B1HT_1			0x00400000  /* Bank 1 Hold Time	from Read or Write deasserted to AOE deasserted	= 1 cycle */
-#define	B1HT_2			0x00800000  /* Bank 1 Hold Time	from Read or Write deasserted to AOE deasserted	= 2 cycles */
-#define	B1HT_3			0x00C00000  /* Bank 1 Hold Time	from Read or Write deasserted to AOE deasserted	= 3 cycles */
-#define	B1HT_0			0x00000000  /* Bank 1 Hold Time	from Read or Write deasserted to AOE deasserted	= 0 cycles */
-#define	B1RAT_1			0x01000000  /* Bank 1 Read Access Time = 1 cycle */
-#define	B1RAT_2			0x02000000  /* Bank 1 Read Access Time = 2 cycles */
-#define	B1RAT_3			0x03000000  /* Bank 1 Read Access Time = 3 cycles */
-#define	B1RAT_4			0x04000000  /* Bank 1 Read Access Time = 4 cycles */
-#define	B1RAT_5			0x05000000  /* Bank 1 Read Access Time = 5 cycles */
-#define	B1RAT_6			0x06000000  /* Bank 1 Read Access Time = 6 cycles */
-#define	B1RAT_7			0x07000000  /* Bank 1 Read Access Time = 7 cycles */
-#define	B1RAT_8			0x08000000  /* Bank 1 Read Access Time = 8 cycles */
-#define	B1RAT_9			0x09000000  /* Bank 1 Read Access Time = 9 cycles */
-#define	B1RAT_10		0x0A000000  /* Bank 1 Read Access Time = 10 cycles */
-#define	B1RAT_11		0x0B000000  /* Bank 1 Read Access Time = 11 cycles */
-#define	B1RAT_12		0x0C000000  /* Bank 1 Read Access Time = 12 cycles */
-#define	B1RAT_13		0x0D000000  /* Bank 1 Read Access Time = 13 cycles */
-#define	B1RAT_14		0x0E000000  /* Bank 1 Read Access Time = 14 cycles */
-#define	B1RAT_15		0x0F000000  /* Bank 1 Read Access Time = 15 cycles */
-#define	B1WAT_1			0x10000000 /* Bank 1 Write Access Time = 1 cycle */
-#define	B1WAT_2			0x20000000  /* Bank 1 Write Access Time	= 2 cycles */
-#define	B1WAT_3			0x30000000  /* Bank 1 Write Access Time	= 3 cycles */
-#define	B1WAT_4			0x40000000  /* Bank 1 Write Access Time	= 4 cycles */
-#define	B1WAT_5			0x50000000  /* Bank 1 Write Access Time	= 5 cycles */
-#define	B1WAT_6			0x60000000  /* Bank 1 Write Access Time	= 6 cycles */
-#define	B1WAT_7			0x70000000  /* Bank 1 Write Access Time	= 7 cycles */
-#define	B1WAT_8			0x80000000  /* Bank 1 Write Access Time	= 8 cycles */
-#define	B1WAT_9			0x90000000  /* Bank 1 Write Access Time	= 9 cycles */
-#define	B1WAT_10		0xA0000000  /* Bank 1 Write Access Time	= 10 cycles */
-#define	B1WAT_11		0xB0000000  /* Bank 1 Write Access Time	= 11 cycles */
-#define	B1WAT_12		0xC0000000  /* Bank 1 Write Access Time	= 12 cycles */
-#define	B1WAT_13		0xD0000000  /* Bank 1 Write Access Time	= 13 cycles */
-#define	B1WAT_14		0xE0000000  /* Bank 1 Write Access Time	= 14 cycles */
-#define	B1WAT_15		0xF0000000  /* Bank 1 Write Access Time	= 15 cycles */
-
-/* EBIU_AMBCTL1	Masks */
-#define	B2RDYEN			0x00000001  /* Bank 2 RDY Enable, 0=disable, 1=enable */
-#define	B2RDYPOL		0x00000002  /* Bank 2 RDY Active high, 0=active	low, 1=active high */
-#define	B2TT_1			0x00000004  /* Bank 2 Transition Time from Read	to Write = 1 cycle */
-#define	B2TT_2			0x00000008  /* Bank 2 Transition Time from Read	to Write = 2 cycles */
-#define	B2TT_3			0x0000000C  /* Bank 2 Transition Time from Read	to Write = 3 cycles */
-#define	B2TT_4			0x00000000  /* Bank 2 Transition Time from Read	to Write = 4 cycles */
-#define	B2ST_1			0x00000010  /* Bank 2 Setup Time from AOE asserted to Read or Write asserted = 1 cycle */
-#define	B2ST_2			0x00000020  /* Bank 2 Setup Time from AOE asserted to Read or Write asserted = 2 cycles */
-#define	B2ST_3			0x00000030  /* Bank 2 Setup Time from AOE asserted to Read or Write asserted = 3 cycles */
-#define	B2ST_4			0x00000000  /* Bank 2 Setup Time from AOE asserted to Read or Write asserted = 4 cycles */
-#define	B2HT_1			0x00000040  /* Bank 2 Hold Time	from Read or Write deasserted to AOE deasserted	= 1 cycle */
-#define	B2HT_2			0x00000080  /* Bank 2 Hold Time	from Read or Write deasserted to AOE deasserted	= 2 cycles */
-#define	B2HT_3			0x000000C0  /* Bank 2 Hold Time	from Read or Write deasserted to AOE deasserted	= 3 cycles */
-#define	B2HT_0			0x00000000  /* Bank 2 Hold Time	from Read or Write deasserted to AOE deasserted	= 0 cycles */
-#define	B2RAT_1			0x00000100  /* Bank 2 Read Access Time = 1 cycle */
-#define	B2RAT_2			0x00000200  /* Bank 2 Read Access Time = 2 cycles */
-#define	B2RAT_3			0x00000300  /* Bank 2 Read Access Time = 3 cycles */
-#define	B2RAT_4			0x00000400  /* Bank 2 Read Access Time = 4 cycles */
-#define	B2RAT_5			0x00000500  /* Bank 2 Read Access Time = 5 cycles */
-#define	B2RAT_6			0x00000600  /* Bank 2 Read Access Time = 6 cycles */
-#define	B2RAT_7			0x00000700  /* Bank 2 Read Access Time = 7 cycles */
-#define	B2RAT_8			0x00000800  /* Bank 2 Read Access Time = 8 cycles */
-#define	B2RAT_9			0x00000900  /* Bank 2 Read Access Time = 9 cycles */
-#define	B2RAT_10		0x00000A00  /* Bank 2 Read Access Time = 10 cycles */
-#define	B2RAT_11		0x00000B00  /* Bank 2 Read Access Time = 11 cycles */
-#define	B2RAT_12		0x00000C00  /* Bank 2 Read Access Time = 12 cycles */
-#define	B2RAT_13		0x00000D00  /* Bank 2 Read Access Time = 13 cycles */
-#define	B2RAT_14		0x00000E00  /* Bank 2 Read Access Time = 14 cycles */
-#define	B2RAT_15		0x00000F00  /* Bank 2 Read Access Time = 15 cycles */
-#define	B2WAT_1			0x00001000  /* Bank 2 Write Access Time	= 1 cycle */
-#define	B2WAT_2			0x00002000  /* Bank 2 Write Access Time	= 2 cycles */
-#define	B2WAT_3			0x00003000  /* Bank 2 Write Access Time	= 3 cycles */
-#define	B2WAT_4			0x00004000  /* Bank 2 Write Access Time	= 4 cycles */
-#define	B2WAT_5			0x00005000  /* Bank 2 Write Access Time	= 5 cycles */
-#define	B2WAT_6			0x00006000  /* Bank 2 Write Access Time	= 6 cycles */
-#define	B2WAT_7			0x00007000  /* Bank 2 Write Access Time	= 7 cycles */
-#define	B2WAT_8			0x00008000  /* Bank 2 Write Access Time	= 8 cycles */
-#define	B2WAT_9			0x00009000  /* Bank 2 Write Access Time	= 9 cycles */
-#define	B2WAT_10		0x0000A000  /* Bank 2 Write Access Time	= 10 cycles */
-#define	B2WAT_11		0x0000B000  /* Bank 2 Write Access Time	= 11 cycles */
-#define	B2WAT_12		0x0000C000  /* Bank 2 Write Access Time	= 12 cycles */
-#define	B2WAT_13		0x0000D000  /* Bank 2 Write Access Time	= 13 cycles */
-#define	B2WAT_14		0x0000E000  /* Bank 2 Write Access Time	= 14 cycles */
-#define	B2WAT_15		0x0000F000  /* Bank 2 Write Access Time	= 15 cycles */
-#define	B3RDYEN			0x00010000  /* Bank 3 RDY enable, 0=disable, 1=enable */
-#define	B3RDYPOL		0x00020000  /* Bank 3 RDY Active high, 0=active	low, 1=active high */
-#define	B3TT_1			0x00040000  /* Bank 3 Transition Time from Read	to Write = 1 cycle */
-#define	B3TT_2			0x00080000  /* Bank 3 Transition Time from Read	to Write = 2 cycles */
-#define	B3TT_3			0x000C0000  /* Bank 3 Transition Time from Read	to Write = 3 cycles */
-#define	B3TT_4			0x00000000  /* Bank 3 Transition Time from Read	to Write = 4 cycles */
-#define	B3ST_1			0x00100000  /* Bank 3 Setup Time from AOE asserted to Read or Write asserted = 1 cycle */
-#define	B3ST_2			0x00200000  /* Bank 3 Setup Time from AOE asserted to Read or Write asserted = 2 cycles */
-#define	B3ST_3			0x00300000  /* Bank 3 Setup Time from AOE asserted to Read or Write asserted = 3 cycles */
-#define	B3ST_4			0x00000000  /* Bank 3 Setup Time from AOE asserted to Read or Write asserted = 4 cycles */
-#define	B3HT_1			0x00400000  /* Bank 3 Hold Time	from Read or Write deasserted to AOE deasserted	= 1 cycle */
-#define	B3HT_2			0x00800000  /* Bank 3 Hold Time	from Read or Write deasserted to AOE deasserted	= 2 cycles */
-#define	B3HT_3			0x00C00000  /* Bank 3 Hold Time	from Read or Write deasserted to AOE deasserted	= 3 cycles */
-#define	B3HT_0			0x00000000  /* Bank 3 Hold Time	from Read or Write deasserted to AOE deasserted	= 0 cycles */
-#define	B3RAT_1			0x01000000 /* Bank 3 Read Access Time =	1 cycle */
-#define	B3RAT_2			0x02000000  /* Bank 3 Read Access Time = 2 cycles */
-#define	B3RAT_3			0x03000000  /* Bank 3 Read Access Time = 3 cycles */
-#define	B3RAT_4			0x04000000  /* Bank 3 Read Access Time = 4 cycles */
-#define	B3RAT_5			0x05000000  /* Bank 3 Read Access Time = 5 cycles */
-#define	B3RAT_6			0x06000000  /* Bank 3 Read Access Time = 6 cycles */
-#define	B3RAT_7			0x07000000  /* Bank 3 Read Access Time = 7 cycles */
-#define	B3RAT_8			0x08000000  /* Bank 3 Read Access Time = 8 cycles */
-#define	B3RAT_9			0x09000000  /* Bank 3 Read Access Time = 9 cycles */
-#define	B3RAT_10		0x0A000000  /* Bank 3 Read Access Time = 10 cycles */
-#define	B3RAT_11		0x0B000000  /* Bank 3 Read Access Time = 11 cycles */
-#define	B3RAT_12		0x0C000000  /* Bank 3 Read Access Time = 12 cycles */
-#define	B3RAT_13		0x0D000000  /* Bank 3 Read Access Time = 13 cycles */
-#define	B3RAT_14		0x0E000000  /* Bank 3 Read Access Time = 14 cycles */
-#define	B3RAT_15		0x0F000000  /* Bank 3 Read Access Time = 15 cycles */
-#define	B3WAT_1			0x10000000 /* Bank 3 Write Access Time = 1 cycle */
-#define	B3WAT_2			0x20000000  /* Bank 3 Write Access Time	= 2 cycles */
-#define	B3WAT_3			0x30000000  /* Bank 3 Write Access Time	= 3 cycles */
-#define	B3WAT_4			0x40000000  /* Bank 3 Write Access Time	= 4 cycles */
-#define	B3WAT_5			0x50000000  /* Bank 3 Write Access Time	= 5 cycles */
-#define	B3WAT_6			0x60000000  /* Bank 3 Write Access Time	= 6 cycles */
-#define	B3WAT_7			0x70000000  /* Bank 3 Write Access Time	= 7 cycles */
-#define	B3WAT_8			0x80000000  /* Bank 3 Write Access Time	= 8 cycles */
-#define	B3WAT_9			0x90000000  /* Bank 3 Write Access Time	= 9 cycles */
-#define	B3WAT_10		0xA0000000  /* Bank 3 Write Access Time	= 10 cycles */
-#define	B3WAT_11		0xB0000000  /* Bank 3 Write Access Time	= 11 cycles */
-#define	B3WAT_12		0xC0000000  /* Bank 3 Write Access Time	= 12 cycles */
-#define	B3WAT_13		0xD0000000  /* Bank 3 Write Access Time	= 13 cycles */
-#define	B3WAT_14		0xE0000000  /* Bank 3 Write Access Time	= 14 cycles */
-#define	B3WAT_15		0xF0000000  /* Bank 3 Write Access Time	= 15 cycles */
-
-/* **********************  SDRAM CONTROLLER MASKS  *************************** */
-/* EBIU_SDGCTL Masks */
-#define	SCTLE			0x00000001 /* Enable SCLK[0], /SRAS, /SCAS, /SWE, SDQM[3:0] */
-#define	CL_2			0x00000008 /* SDRAM CAS	latency	= 2 cycles */
-#define	CL_3			0x0000000C /* SDRAM CAS	latency	= 3 cycles */
-#define	PFE				0x00000010 /* Enable SDRAM prefetch */
-#define	PFP				0x00000020 /* Prefetch has priority over AMC requests */
-#define	PASR_ALL		0x00000000	/* All 4 SDRAM Banks Refreshed In Self-Refresh */
-#define	PASR_B0_B1		0x00000010	/* SDRAM Banks 0 and 1 Are Refreshed In	Self-Refresh */
-#define	PASR_B0			0x00000020	/* Only	SDRAM Bank 0 Is	Refreshed In Self-Refresh */
-#define	TRAS_1			0x00000040 /* SDRAM tRAS = 1 cycle */
-#define	TRAS_2			0x00000080 /* SDRAM tRAS = 2 cycles */
-#define	TRAS_3			0x000000C0 /* SDRAM tRAS = 3 cycles */
-#define	TRAS_4			0x00000100 /* SDRAM tRAS = 4 cycles */
-#define	TRAS_5			0x00000140 /* SDRAM tRAS = 5 cycles */
-#define	TRAS_6			0x00000180 /* SDRAM tRAS = 6 cycles */
-#define	TRAS_7			0x000001C0 /* SDRAM tRAS = 7 cycles */
-#define	TRAS_8			0x00000200 /* SDRAM tRAS = 8 cycles */
-#define	TRAS_9			0x00000240 /* SDRAM tRAS = 9 cycles */
-#define	TRAS_10			0x00000280 /* SDRAM tRAS = 10 cycles */
-#define	TRAS_11			0x000002C0 /* SDRAM tRAS = 11 cycles */
-#define	TRAS_12			0x00000300 /* SDRAM tRAS = 12 cycles */
-#define	TRAS_13			0x00000340 /* SDRAM tRAS = 13 cycles */
-#define	TRAS_14			0x00000380 /* SDRAM tRAS = 14 cycles */
-#define	TRAS_15			0x000003C0 /* SDRAM tRAS = 15 cycles */
-#define	TRP_1			0x00000800 /* SDRAM tRP	= 1 cycle */
-#define	TRP_2			0x00001000 /* SDRAM tRP	= 2 cycles */
-#define	TRP_3			0x00001800 /* SDRAM tRP	= 3 cycles */
-#define	TRP_4			0x00002000 /* SDRAM tRP	= 4 cycles */
-#define	TRP_5			0x00002800 /* SDRAM tRP	= 5 cycles */
-#define	TRP_6			0x00003000 /* SDRAM tRP	= 6 cycles */
-#define	TRP_7			0x00003800 /* SDRAM tRP	= 7 cycles */
-#define	TRCD_1			0x00008000 /* SDRAM tRCD = 1 cycle */
-#define	TRCD_2			0x00010000 /* SDRAM tRCD = 2 cycles */
-#define	TRCD_3			0x00018000 /* SDRAM tRCD = 3 cycles */
-#define	TRCD_4			0x00020000 /* SDRAM tRCD = 4 cycles */
-#define	TRCD_5			0x00028000 /* SDRAM tRCD = 5 cycles */
-#define	TRCD_6			0x00030000 /* SDRAM tRCD = 6 cycles */
-#define	TRCD_7			0x00038000 /* SDRAM tRCD = 7 cycles */
-#define	TWR_1			0x00080000 /* SDRAM tWR	= 1 cycle */
-#define	TWR_2			0x00100000 /* SDRAM tWR	= 2 cycles */
-#define	TWR_3			0x00180000 /* SDRAM tWR	= 3 cycles */
-#define	PUPSD			0x00200000 /*Power-up start delay */
-#define	PSM				0x00400000 /* SDRAM power-up sequence =	Precharge, mode	register set, 8	CBR refresh cycles */
-#define	PSS				0x00800000 /* enable SDRAM power-up sequence on	next SDRAM access */
-#define	SRFS			0x01000000 /* Start SDRAM self-refresh mode */
-#define	EBUFE			0x02000000 /* Enable external buffering	timing */
-#define	FBBRW			0x04000000 /* Fast back-to-back	read write enable */
-#define	EMREN			0x10000000 /* Extended mode register enable */
-#define	TCSR			0x20000000 /* Temp compensated self refresh value 85 deg C */
-#define	CDDBG			0x40000000 /* Tristate SDRAM controls during bus grant */
-
-/* EBIU_SDBCTL Masks */
-#define	EBE				0x00000001 /* Enable SDRAM external bank */
-#define	EBSZ_16			0x00000000 /* SDRAM external bank size = 16MB */
-#define	EBSZ_32			0x00000002 /* SDRAM external bank size = 32MB */
-#define	EBSZ_64			0x00000004 /* SDRAM external bank size = 64MB */
-#define	EBSZ_128		0x00000006 /* SDRAM external bank size = 128MB */
-#define	EBSZ_256		0x00000008 /* SDRAM External Bank Size = 256MB */
-#define	EBSZ_512		0x0000000A /* SDRAM External Bank Size = 512MB */
-#define	EBCAW_8			0x00000000 /* SDRAM external bank column address width = 8 bits */
-#define	EBCAW_9			0x00000010 /* SDRAM external bank column address width = 9 bits */
-#define	EBCAW_10		0x00000020 /* SDRAM external bank column address width = 9 bits */
-#define	EBCAW_11		0x00000030 /* SDRAM external bank column address width = 9 bits */
-
-/* EBIU_SDSTAT Masks */
-#define	SDCI			0x00000001 /* SDRAM controller is idle */
-#define	SDSRA			0x00000002 /* SDRAM SDRAM self refresh is active */
-#define	SDPUA			0x00000004 /* SDRAM power up active  */
-#define	SDRS			0x00000008 /* SDRAM is in reset	state */
-#define	SDEASE			0x00000010 /* SDRAM EAB	sticky error status - W1C */
-#define	BGSTAT			0x00000020 /* Bus granted */
-
-
-/*  ********************  TWO-WIRE INTERFACE (TWIx) MASKS  ***********************/
-/* TWIx_CLKDIV Macros (Use: *pTWIx_CLKDIV = CLKLOW(x)|CLKHI(y);	 ) */
-#ifdef _MISRA_RULES
-#define	CLKLOW(x)	((x) & 0xFFu)		/* Periods Clock Is Held Low */
-#define	CLKHI(y)	(((y)&0xFFu)<<0x8)	/* Periods Before New Clock Low */
-#else
-#define	CLKLOW(x)	((x) & 0xFF)		/* Periods Clock Is Held Low */
-#define	CLKHI(y)	(((y)&0xFF)<<0x8)	/* Periods Before New Clock Low */
-#endif /* _MISRA_RULES */
-
-/* TWIx_PRESCALE Masks								 */
-#define	PRESCALE	0x007F		/* SCLKs Per Internal Time Reference (10MHz) */
-#define	TWI_ENA		0x0080		/* TWI Enable		 */
-#define	SCCB		0x0200		/* SCCB	Compatibility Enable */
-
-/* TWIx_SLAVE_CTRL Masks								 */
-#define	SEN			0x0001		/* Slave Enable		 */
-#define	SADD_LEN	0x0002		/* Slave Address Length */
-#define	STDVAL		0x0004		/* Slave Transmit Data Valid */
-#define	NAK			0x0008		/* NAK/ACK* Generated At Conclusion Of Transfer */
-#define	GEN			0x0010		/* General Call	Adrress	Matching Enabled */
-
-/* TWIx_SLAVE_STAT Masks								 */
-#define	SDIR		0x0001		/* Slave Transfer Direction (Transmit/Receive*) */
-#define	GCALL		0x0002		/* General Call	Indicator */
-
-/* TWIx_MASTER_CTRL Masks						 */
-#define	MEN			0x0001		/* Master Mode Enable */
-#define	MADD_LEN	0x0002		/* Master Address Length */
-#define	MDIR		0x0004		/* Master Transmit Direction (RX/TX*) */
-#define	FAST		0x0008		/* Use Fast Mode Timing	Specs */
-#define	STOP		0x0010		/* Issue Stop Condition */
-#define	RSTART		0x0020		/* Repeat Start	or Stop* At End	Of Transfer */
-#define	DCNT		0x3FC0		/* Data	Bytes To Transfer */
-#define	SDAOVR		0x4000		/* Serial Data Override */
-#define	SCLOVR		0x8000		/* Serial Clock	Override */
-
-/* TWIx_MASTER_STAT Masks							 */
-#define	MPROG		0x0001		/* Master Transfer In Progress */
-#define	LOSTARB		0x0002		/* Lost	Arbitration Indicator (Xfer Aborted) */
-#define	ANAK		0x0004		/* Address Not Acknowledged */
-#define	DNAK		0x0008		/* Data	Not Acknowledged */
-#define	BUFRDERR	0x0010		/* Buffer Read Error */
-#define	BUFWRERR	0x0020		/* Buffer Write	Error */
-#define	SDASEN		0x0040		/* Serial Data Sense */
-#define	SCLSEN		0x0080		/* Serial Clock	Sense */
-#define	BUSBUSY		0x0100		/* Bus Busy Indicator */
-
-/* TWIx_INT_SRC	and TWIx_INT_ENABLE Masks */
-#define	SINIT		0x0001		/* Slave Transfer Initiated */
-#define	SCOMP		0x0002		/* Slave Transfer Complete */
-#define	SERR		0x0004		/* Slave Transfer Error */
-#define	SOVF		0x0008		/* Slave Overflow */
-#define	MCOMP		0x0010		/* Master Transfer Complete */
-#define	MERR		0x0020		/* Master Transfer Error */
-#define	XMTSERV		0x0040		/* Transmit FIFO Service */
-#define	RCVSERV		0x0080		/* Receive FIFO	Service */
-
-/* TWIx_FIFO_CTL Masks					 */
-#define	XMTFLUSH	0x0001		/* Transmit Buffer Flush */
-#define	RCVFLUSH	0x0002		/* Receive Buffer Flush */
-#define	XMTINTLEN	0x0004		/* Transmit Buffer Interrupt Length */
-#define	RCVINTLEN	0x0008		/* Receive Buffer Interrupt Length */
-
-/* TWIx_FIFO_STAT Masks								 */
-#define	XMTSTAT		0x0003		/* Transmit FIFO Status */
-#define	XMT_EMPTY	0x0000		/*		Transmit FIFO Empty */
-#define	XMT_HALF	0x0001		/*		Transmit FIFO Has 1 Byte To Write */
-#define	XMT_FULL	0x0003		/*		Transmit FIFO Full (2 Bytes To Write) */
-
-#define	RCVSTAT		0x000C		/* Receive FIFO	Status */
-#define	RCV_EMPTY	0x0000		/*		Receive	FIFO Empty */
-#define	RCV_HALF	0x0004		/*		Receive	FIFO Has 1 Byte	To Read */
-#define	RCV_FULL	0x000C		/*		Receive	FIFO Full (2 Bytes To Read) */
-
 #endif /* _DEF_BF539_H */
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf538/include/mach/gpio.h linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf538/include/mach/gpio.h
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf538/include/mach/gpio.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf538/include/mach/gpio.h	2011-03-14 21:20:32.000000000 -0400
@@ -70,4 +70,9 @@
 #define PORT_D GPIO_PD0
 #define PORT_E GPIO_PE0
 
+#include <mach-common/ports-c.h>
+#include <mach-common/ports-d.h>
+#include <mach-common/ports-e.h>
+#include <mach-common/ports-f.h>
+
 #endif /* _MACH_GPIO_H_ */
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf538/include/mach/pll.h linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf538/include/mach/pll.h
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf538/include/mach/pll.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf538/include/mach/pll.h	2011-03-14 21:20:32.000000000 -0400
@@ -1,63 +1 @@
-/*
- * Copyright 2008-2009 Analog Devices Inc.
- *
- * Licensed under the GPL-2 or later.
- */
-
-#ifndef _MACH_PLL_H
-#define _MACH_PLL_H
-
-#include <asm/blackfin.h>
-#include <asm/irqflags.h>
-
-/* Writing to PLL_CTL initiates a PLL relock sequence. */
-static __inline__ void bfin_write_PLL_CTL(unsigned int val)
-{
-	unsigned long flags, iwr0, iwr1;
-
-	if (val == bfin_read_PLL_CTL())
-		return;
-
-	flags = hard_local_irq_save();
-	/* Enable the PLL Wakeup bit in SIC IWR */
-	iwr0 = bfin_read32(SIC_IWR0);
-	iwr1 = bfin_read32(SIC_IWR1);
-	/* Only allow PPL Wakeup) */
-	bfin_write32(SIC_IWR0, IWR_ENABLE(0));
-	bfin_write32(SIC_IWR1, 0);
-
-	bfin_write16(PLL_CTL, val);
-	SSYNC();
-	asm("IDLE;");
-
-	bfin_write32(SIC_IWR0, iwr0);
-	bfin_write32(SIC_IWR1, iwr1);
-	hard_local_irq_restore(flags);
-}
-
-/* Writing to VR_CTL initiates a PLL relock sequence. */
-static __inline__ void bfin_write_VR_CTL(unsigned int val)
-{
-	unsigned long flags, iwr0, iwr1;
-
-	if (val == bfin_read_VR_CTL())
-		return;
-
-	flags = hard_local_irq_save();
-	/* Enable the PLL Wakeup bit in SIC IWR */
-	iwr0 = bfin_read32(SIC_IWR0);
-	iwr1 = bfin_read32(SIC_IWR1);
-	/* Only allow PPL Wakeup) */
-	bfin_write32(SIC_IWR0, IWR_ENABLE(0));
-	bfin_write32(SIC_IWR1, 0);
-
-	bfin_write16(VR_CTL, val);
-	SSYNC();
-	asm("IDLE;");
-
-	bfin_write32(SIC_IWR0, iwr0);
-	bfin_write32(SIC_IWR1, iwr1);
-	hard_local_irq_restore(flags);
-}
-
-#endif /* _MACH_PLL_H */
+#include <mach-common/pll.h>
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf548/boards/cm_bf548.c linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf548/boards/cm_bf548.c
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf548/boards/cm_bf548.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf548/boards/cm_bf548.c	2011-03-14 21:20:32.000000000 -0400
@@ -156,7 +156,7 @@ static struct resource bfin_uart0_resour
 	},
 };
 
-unsigned short bfin_uart0_peripherals[] = {
+static unsigned short bfin_uart0_peripherals[] = {
 	P_UART0_TX, P_UART0_RX, 0
 };
 
@@ -211,7 +211,7 @@ static struct resource bfin_uart1_resour
 #endif
 };
 
-unsigned short bfin_uart1_peripherals[] = {
+static unsigned short bfin_uart1_peripherals[] = {
 	P_UART1_TX, P_UART1_RX,
 #ifdef CONFIG_BFIN_UART1_CTSRTS
 	P_UART1_RTS, P_UART1_CTS,
@@ -258,7 +258,7 @@ static struct resource bfin_uart2_resour
 	},
 };
 
-unsigned short bfin_uart2_peripherals[] = {
+static unsigned short bfin_uart2_peripherals[] = {
 	P_UART2_TX, P_UART2_RX, 0
 };
 
@@ -313,7 +313,7 @@ static struct resource bfin_uart3_resour
 #endif
 };
 
-unsigned short bfin_uart3_peripherals[] = {
+static unsigned short bfin_uart3_peripherals[] = {
 	P_UART3_TX, P_UART3_RX,
 #ifdef CONFIG_BFIN_UART3_CTSRTS
 	P_UART3_RTS, P_UART3_CTS,
@@ -482,11 +482,13 @@ static struct resource musb_resources[]
 		.start	= IRQ_USB_INT0,
 		.end	= IRQ_USB_INT0,
 		.flags	= IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
+		.name	= "mc"
 	},
 	[2] = {	/* DMA IRQ */
 		.start	= IRQ_USB_DMA,
 		.end	= IRQ_USB_DMA,
 		.flags	= IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
+		.name	= "dma"
 	},
 };
 
@@ -502,6 +504,7 @@ static struct musb_hdrc_config musb_conf
 	 * if it is the case.
 	 */
 	.gpio_vrsel_active	= 1,
+	.clkin          = 24,           /* musb CLKIN in MHZ */
 };
 
 static struct musb_hdrc_platform_data musb_plat = {
@@ -518,7 +521,7 @@ static struct musb_hdrc_platform_data mu
 static u64 musb_dmamask = ~(u32)0;
 
 static struct platform_device musb_device = {
-	.name		= "musb_hdrc",
+	.name		= "musb-blackfin",
 	.id		= 0,
 	.dev = {
 		.dma_mask		= &musb_dmamask,
@@ -550,9 +553,9 @@ static struct resource bfin_sport0_uart_
 	},
 };
 
-unsigned short bfin_sport0_peripherals[] = {
+static unsigned short bfin_sport0_peripherals[] = {
 	P_SPORT0_TFS, P_SPORT0_DTPRI, P_SPORT0_TSCLK, P_SPORT0_RFS,
-	P_SPORT0_DRPRI, P_SPORT0_RSCLK, P_SPORT0_DRSEC, P_SPORT0_DTSEC, 0
+	P_SPORT0_DRPRI, P_SPORT0_RSCLK, 0
 };
 
 static struct platform_device bfin_sport0_uart_device = {
@@ -584,9 +587,9 @@ static struct resource bfin_sport1_uart_
 	},
 };
 
-unsigned short bfin_sport1_peripherals[] = {
+static unsigned short bfin_sport1_peripherals[] = {
 	P_SPORT1_TFS, P_SPORT1_DTPRI, P_SPORT1_TSCLK, P_SPORT1_RFS,
-	P_SPORT1_DRPRI, P_SPORT1_RSCLK, P_SPORT1_DRSEC, P_SPORT1_DTSEC, 0
+	P_SPORT1_DRPRI, P_SPORT1_RSCLK, 0
 };
 
 static struct platform_device bfin_sport1_uart_device = {
@@ -618,7 +621,7 @@ static struct resource bfin_sport2_uart_
 	},
 };
 
-unsigned short bfin_sport2_peripherals[] = {
+static unsigned short bfin_sport2_peripherals[] = {
 	P_SPORT2_TFS, P_SPORT2_DTPRI, P_SPORT2_TSCLK, P_SPORT2_RFS,
 	P_SPORT2_DRPRI, P_SPORT2_RSCLK, P_SPORT2_DRSEC, P_SPORT2_DTSEC, 0
 };
@@ -652,7 +655,7 @@ static struct resource bfin_sport3_uart_
 	},
 };
 
-unsigned short bfin_sport3_peripherals[] = {
+static unsigned short bfin_sport3_peripherals[] = {
 	P_SPORT3_TFS, P_SPORT3_DTPRI, P_SPORT3_TSCLK, P_SPORT3_RFS,
 	P_SPORT3_DRPRI, P_SPORT3_RSCLK, P_SPORT3_DRSEC, P_SPORT3_DTSEC, 0
 };
@@ -754,7 +757,7 @@ static struct platform_device bf54x_sdh_
 #endif
 
 #if defined(CONFIG_CAN_BFIN) || defined(CONFIG_CAN_BFIN_MODULE)
-unsigned short bfin_can_peripherals[] = {
+static unsigned short bfin_can_peripherals[] = {
 	P_CAN0_RX, P_CAN0_TX, 0
 };
 
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf548/boards/ezkit.c linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf548/boards/ezkit.c
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf548/boards/ezkit.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf548/boards/ezkit.c	2011-03-14 21:20:32.000000000 -0400
@@ -261,7 +261,7 @@ static struct resource bfin_uart0_resour
 	},
 };
 
-unsigned short bfin_uart0_peripherals[] = {
+static unsigned short bfin_uart0_peripherals[] = {
 	P_UART0_TX, P_UART0_RX, 0
 };
 
@@ -316,7 +316,7 @@ static struct resource bfin_uart1_resour
 #endif
 };
 
-unsigned short bfin_uart1_peripherals[] = {
+static unsigned short bfin_uart1_peripherals[] = {
 	P_UART1_TX, P_UART1_RX,
 #ifdef CONFIG_BFIN_UART1_CTSRTS
 	P_UART1_RTS, P_UART1_CTS,
@@ -363,7 +363,7 @@ static struct resource bfin_uart2_resour
 	},
 };
 
-unsigned short bfin_uart2_peripherals[] = {
+static unsigned short bfin_uart2_peripherals[] = {
 	P_UART2_TX, P_UART2_RX, 0
 };
 
@@ -418,7 +418,7 @@ static struct resource bfin_uart3_resour
 #endif
 };
 
-unsigned short bfin_uart3_peripherals[] = {
+static unsigned short bfin_uart3_peripherals[] = {
 	P_UART3_TX, P_UART3_RX,
 #ifdef CONFIG_BFIN_UART3_CTSRTS
 	P_UART3_RTS, P_UART3_CTS,
@@ -587,11 +587,13 @@ static struct resource musb_resources[]
 		.start	= IRQ_USB_INT0,
 		.end	= IRQ_USB_INT0,
 		.flags	= IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
+		.name	= "mc"
 	},
 	[2] = {	/* DMA IRQ */
 		.start	= IRQ_USB_DMA,
 		.end	= IRQ_USB_DMA,
 		.flags	= IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
+		.name	= "dma"
 	},
 };
 
@@ -607,6 +609,7 @@ static struct musb_hdrc_config musb_conf
 	 * if it is the case.
 	 */
 	.gpio_vrsel_active	= 1,
+	.clkin          = 24,           /* musb CLKIN in MHZ */
 };
 
 static struct musb_hdrc_platform_data musb_plat = {
@@ -623,7 +626,7 @@ static struct musb_hdrc_platform_data mu
 static u64 musb_dmamask = ~(u32)0;
 
 static struct platform_device musb_device = {
-	.name		= "musb_hdrc",
+	.name		= "musb-blackfin",
 	.id		= 0,
 	.dev = {
 		.dma_mask		= &musb_dmamask,
@@ -655,9 +658,9 @@ static struct resource bfin_sport0_uart_
 	},
 };
 
-unsigned short bfin_sport0_peripherals[] = {
+static unsigned short bfin_sport0_peripherals[] = {
 	P_SPORT0_TFS, P_SPORT0_DTPRI, P_SPORT0_TSCLK, P_SPORT0_RFS,
-	P_SPORT0_DRPRI, P_SPORT0_RSCLK, P_SPORT0_DRSEC, P_SPORT0_DTSEC, 0
+	P_SPORT0_DRPRI, P_SPORT0_RSCLK, 0
 };
 
 static struct platform_device bfin_sport0_uart_device = {
@@ -689,9 +692,9 @@ static struct resource bfin_sport1_uart_
 	},
 };
 
-unsigned short bfin_sport1_peripherals[] = {
+static unsigned short bfin_sport1_peripherals[] = {
 	P_SPORT1_TFS, P_SPORT1_DTPRI, P_SPORT1_TSCLK, P_SPORT1_RFS,
-	P_SPORT1_DRPRI, P_SPORT1_RSCLK, P_SPORT1_DRSEC, P_SPORT1_DTSEC, 0
+	P_SPORT1_DRPRI, P_SPORT1_RSCLK, 0
 };
 
 static struct platform_device bfin_sport1_uart_device = {
@@ -723,7 +726,7 @@ static struct resource bfin_sport2_uart_
 	},
 };
 
-unsigned short bfin_sport2_peripherals[] = {
+static unsigned short bfin_sport2_peripherals[] = {
 	P_SPORT2_TFS, P_SPORT2_DTPRI, P_SPORT2_TSCLK, P_SPORT2_RFS,
 	P_SPORT2_DRPRI, P_SPORT2_RSCLK, P_SPORT2_DRSEC, P_SPORT2_DTSEC, 0
 };
@@ -757,7 +760,7 @@ static struct resource bfin_sport3_uart_
 	},
 };
 
-unsigned short bfin_sport3_peripherals[] = {
+static unsigned short bfin_sport3_peripherals[] = {
 	P_SPORT3_TFS, P_SPORT3_DTPRI, P_SPORT3_TSCLK, P_SPORT3_RFS,
 	P_SPORT3_DRPRI, P_SPORT3_RSCLK, P_SPORT3_DRSEC, P_SPORT3_DTSEC, 0
 };
@@ -775,7 +778,7 @@ static struct platform_device bfin_sport
 #endif
 
 #if defined(CONFIG_CAN_BFIN) || defined(CONFIG_CAN_BFIN_MODULE)
-unsigned short bfin_can_peripherals[] = {
+static unsigned short bfin_can_peripherals[] = {
 	P_CAN0_RX, P_CAN0_TX, 0
 };
 
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf548/dma.c linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf548/dma.c
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf548/dma.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf548/dma.c	2011-03-14 21:20:32.000000000 -0400
@@ -11,7 +11,7 @@
 #include <asm/blackfin.h>
 #include <asm/dma.h>
 
-struct dma_register *dma_io_base_addr[MAX_DMA_CHANNELS] = {
+struct dma_register * const dma_io_base_addr[MAX_DMA_CHANNELS] = {
 	(struct dma_register *) DMA0_NEXT_DESC_PTR,
 	(struct dma_register *) DMA1_NEXT_DESC_PTR,
 	(struct dma_register *) DMA2_NEXT_DESC_PTR,
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf548/include/mach/bfin_serial_5xx.h linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf548/include/mach/bfin_serial_5xx.h
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf548/include/mach/bfin_serial_5xx.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf548/include/mach/bfin_serial_5xx.h	2011-03-14 21:20:32.000000000 -0400
@@ -4,72 +4,14 @@
  * Licensed under the GPL-2 or later.
  */
 
-#include <linux/serial.h>
 #include <asm/dma.h>
 #include <asm/portmux.h>
 
-#define UART_GET_CHAR(uart)     bfin_read16(((uart)->port.membase + OFFSET_RBR))
-#define UART_GET_DLL(uart)	bfin_read16(((uart)->port.membase + OFFSET_DLL))
-#define UART_GET_DLH(uart)	bfin_read16(((uart)->port.membase + OFFSET_DLH))
-#define UART_GET_IER(uart)      bfin_read16(((uart)->port.membase + OFFSET_IER_SET))
-#define UART_GET_LCR(uart)      bfin_read16(((uart)->port.membase + OFFSET_LCR))
-#define UART_GET_LSR(uart)      bfin_read16(((uart)->port.membase + OFFSET_LSR))
-#define UART_GET_GCTL(uart)     bfin_read16(((uart)->port.membase + OFFSET_GCTL))
-#define UART_GET_MSR(uart)      bfin_read16(((uart)->port.membase + OFFSET_MSR))
-#define UART_GET_MCR(uart)      bfin_read16(((uart)->port.membase + OFFSET_MCR))
-
-#define UART_PUT_CHAR(uart,v)   bfin_write16(((uart)->port.membase + OFFSET_THR),v)
-#define UART_PUT_DLL(uart,v)    bfin_write16(((uart)->port.membase + OFFSET_DLL),v)
-#define UART_SET_IER(uart,v)    bfin_write16(((uart)->port.membase + OFFSET_IER_SET),v)
-#define UART_CLEAR_IER(uart,v)  bfin_write16(((uart)->port.membase + OFFSET_IER_CLEAR),v)
-#define UART_PUT_DLH(uart,v)    bfin_write16(((uart)->port.membase + OFFSET_DLH),v)
-#define UART_PUT_LSR(uart,v)	bfin_write16(((uart)->port.membase + OFFSET_LSR),v)
-#define UART_PUT_LCR(uart,v)    bfin_write16(((uart)->port.membase + OFFSET_LCR),v)
-#define UART_CLEAR_LSR(uart)    bfin_write16(((uart)->port.membase + OFFSET_LSR), -1)
-#define UART_PUT_GCTL(uart,v)   bfin_write16(((uart)->port.membase + OFFSET_GCTL),v)
-#define UART_PUT_MCR(uart,v)    bfin_write16(((uart)->port.membase + OFFSET_MCR),v)
-#define UART_CLEAR_SCTS(uart)   bfin_write16(((uart)->port.membase + OFFSET_MSR),SCTS)
-
-#define UART_SET_DLAB(uart)     /* MMRs not muxed on BF54x */
-#define UART_CLEAR_DLAB(uart)   /* MMRs not muxed on BF54x */
-
-#define UART_GET_CTS(x) (UART_GET_MSR(x) & CTS)
-#define UART_DISABLE_RTS(x) UART_PUT_MCR(x, UART_GET_MCR(x) & ~(ARTS|MRTS))
-#define UART_ENABLE_RTS(x) UART_PUT_MCR(x, UART_GET_MCR(x) | MRTS | ARTS)
-#define UART_ENABLE_INTS(x, v) UART_SET_IER(x, v)
-#define UART_DISABLE_INTS(x) UART_CLEAR_IER(x, 0xF)
-
 #if defined(CONFIG_BFIN_UART0_CTSRTS) || defined(CONFIG_BFIN_UART1_CTSRTS) || \
 	defined(CONFIG_BFIN_UART2_CTSRTS) || defined(CONFIG_BFIN_UART3_CTSRTS)
 # define CONFIG_SERIAL_BFIN_HARD_CTSRTS
 #endif
 
-#define BFIN_UART_TX_FIFO_SIZE	2
-
-/*
- * The pin configuration is different from schematic
- */
-struct bfin_serial_port {
-        struct uart_port        port;
-        unsigned int            old_status;
-	int			status_irq;
-#ifdef CONFIG_SERIAL_BFIN_DMA
-	int			tx_done;
-	int			tx_count;
-	struct circ_buf		rx_dma_buf;
-	struct timer_list       rx_dma_timer;
-	int			rx_dma_nrows;
-	unsigned int		tx_dma_channel;
-	unsigned int		rx_dma_channel;
-	struct work_struct	tx_dma_workqueue;
-#endif
-#ifdef CONFIG_SERIAL_BFIN_HARD_CTSRTS
-	int			scts;
-	int			cts_pin;
-	int			rts_pin;
-#endif
-};
-
 struct bfin_serial_res {
 	unsigned long	uart_base_addr;
 	int		uart_irq;
@@ -148,3 +90,5 @@ struct bfin_serial_res bfin_serial_resou
 };
 
 #define DRIVER_NAME "bfin-uart"
+
+#include <asm/bfin_serial.h>
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf548/include/mach/bfin_serial.h linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf548/include/mach/bfin_serial.h
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf548/include/mach/bfin_serial.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf548/include/mach/bfin_serial.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,16 @@
+/*
+ * mach/bfin_serial.h - Blackfin UART/Serial definitions
+ *
+ * Copyright 2006-2010 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#ifndef __BFIN_MACH_SERIAL_H__
+#define __BFIN_MACH_SERIAL_H__
+
+#define BFIN_UART_NR_PORTS	4
+
+#define BFIN_UART_BF54X_STYLE
+
+#endif
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf548/include/mach/blackfin.h linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf548/include/mach/blackfin.h
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf548/include/mach/blackfin.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf548/include/mach/blackfin.h	2011-03-14 21:20:32.000000000 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright 2007-2009 Analog Devices Inc.
+ * Copyright 2007-2010 Analog Devices Inc.
  *
  * Licensed under the GPL-2 or later.
  */
@@ -10,58 +10,40 @@
 #include "bf548.h"
 #include "anomaly.h"
 
+#include <asm/def_LPBlackfin.h>
 #ifdef CONFIG_BF542
-#include "defBF542.h"
-#endif
-
-#ifdef CONFIG_BF544
-#include "defBF544.h"
-#endif
-
-#ifdef CONFIG_BF547
-#include "defBF547.h"
-#endif
-
-#ifdef CONFIG_BF548
-#include "defBF548.h"
-#endif
-
-#ifdef CONFIG_BF549
-#include "defBF549.h"
-#endif
-
-#if !defined(__ASSEMBLY__)
-#ifdef CONFIG_BF542
-#include "cdefBF542.h"
+# include "defBF542.h"
 #endif
 #ifdef CONFIG_BF544
-#include "cdefBF544.h"
+# include "defBF544.h"
 #endif
 #ifdef CONFIG_BF547
-#include "cdefBF547.h"
+# include "defBF547.h"
 #endif
 #ifdef CONFIG_BF548
-#include "cdefBF548.h"
+# include "defBF548.h"
 #endif
 #ifdef CONFIG_BF549
-#include "cdefBF549.h"
+# include "defBF549.h"
 #endif
 
+#ifndef __ASSEMBLY__
+# include <asm/cdef_LPBlackfin.h>
+# ifdef CONFIG_BF542
+#  include "cdefBF542.h"
+# endif
+# ifdef CONFIG_BF544
+#  include "cdefBF544.h"
+# endif
+# ifdef CONFIG_BF547
+#  include "cdefBF547.h"
+# endif
+# ifdef CONFIG_BF548
+#  include "cdefBF548.h"
+# endif
+# ifdef CONFIG_BF549
+#  include "cdefBF549.h"
+# endif
 #endif
 
-#define BFIN_UART_NR_PORTS	4
-
-#define OFFSET_DLL              0x00	/* Divisor Latch (Low-Byte)             */
-#define OFFSET_DLH              0x04	/* Divisor Latch (High-Byte)            */
-#define OFFSET_GCTL             0x08	/* Global Control Register              */
-#define OFFSET_LCR              0x0C	/* Line Control Register                */
-#define OFFSET_MCR              0x10	/* Modem Control Register               */
-#define OFFSET_LSR              0x14	/* Line Status Register                 */
-#define OFFSET_MSR              0x18	/* Modem Status Register                */
-#define OFFSET_SCR              0x1C	/* SCR Scratch Register                 */
-#define OFFSET_IER_SET          0x20	/* Set Interrupt Enable Register        */
-#define OFFSET_IER_CLEAR        0x24	/* Clear Interrupt Enable Register      */
-#define OFFSET_THR              0x28	/* Transmit Holding register            */
-#define OFFSET_RBR              0x2C	/* Receive Buffer register              */
-
 #endif
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf548/include/mach/cdefBF542.h linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf548/include/mach/cdefBF542.h
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf548/include/mach/cdefBF542.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf548/include/mach/cdefBF542.h	2011-03-14 21:20:32.000000000 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright 2007-2008 Analog Devices Inc.
+ * Copyright 2007-2010 Analog Devices Inc.
  *
  * Licensed under the GPL-2 or later.
  */
@@ -7,14 +7,6 @@
 #ifndef _CDEF_BF542_H
 #define _CDEF_BF542_H
 
-/* include all Core registers and bit definitions */
-#include "defBF542.h"
-
-/* include core sbfin_read_()ecific register pointer definitions */
-#include <asm/cdef_LPBlackfin.h>
-
-/* SYSTEM & MMR ADDRESS DEFINITIONS FOR ADSP-BF542 */
-
 /* include cdefBF54x_base.h for the set of #defines that are common to all ADSP-BF54x bfin_read_()rocessors */
 #include "cdefBF54x_base.h"
 
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf548/include/mach/cdefBF544.h linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf548/include/mach/cdefBF544.h
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf548/include/mach/cdefBF544.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf548/include/mach/cdefBF544.h	2011-03-14 21:20:32.000000000 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright 2007-2008 Analog Devices Inc.
+ * Copyright 2007-2010 Analog Devices Inc.
  *
  * Licensed under the GPL-2 or later.
  */
@@ -7,14 +7,6 @@
 #ifndef _CDEF_BF544_H
 #define _CDEF_BF544_H
 
-/* include all Core registers and bit definitions */
-#include "defBF544.h"
-
-/* include core sbfin_read_()ecific register pointer definitions */
-#include <asm/cdef_LPBlackfin.h>
-
-/* SYSTEM & MMR ADDRESS DEFINITIONS FOR ADSP-BF544 */
-
 /* include cdefBF54x_base.h for the set of #defines that are common to all ADSP-BF54x bfin_read_()rocessors */
 #include "cdefBF54x_base.h"
 
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf548/include/mach/cdefBF547.h linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf548/include/mach/cdefBF547.h
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf548/include/mach/cdefBF547.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf548/include/mach/cdefBF547.h	2011-03-14 21:20:32.000000000 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright 2008 Analog Devices Inc.
+ * Copyright 2008-2010 Analog Devices Inc.
  *
  * Licensed under the GPL-2 or later.
  */
@@ -7,14 +7,6 @@
 #ifndef _CDEF_BF547_H
 #define _CDEF_BF547_H
 
-/* include all Core registers and bit definitions */
-#include "defBF547.h"
-
-/* include core sbfin_read_()ecific register pointer definitions */
-#include <asm/cdef_LPBlackfin.h>
-
-/* SYSTEM & MMR ADDRESS DEFINITIONS FOR ADSP-BF547 */
-
 /* include cdefBF54x_base.h for the set of #defines that are common to all ADSP-BF54x bfin_read_()rocessors */
 #include "cdefBF54x_base.h"
 
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf548/include/mach/cdefBF548.h linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf548/include/mach/cdefBF548.h
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf548/include/mach/cdefBF548.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf548/include/mach/cdefBF548.h	2011-03-14 21:20:32.000000000 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright 2007-2008 Analog Devices Inc.
+ * Copyright 2007-2010 Analog Devices Inc.
  *
  * Licensed under the GPL-2 or later.
  */
@@ -7,14 +7,6 @@
 #ifndef _CDEF_BF548_H
 #define _CDEF_BF548_H
 
-/* include all Core registers and bit definitions */
-#include "defBF548.h"
-
-/* include core sbfin_read_()ecific register pointer definitions */
-#include <asm/cdef_LPBlackfin.h>
-
-/* SYSTEM & MMR ADDRESS DEFINITIONS FOR ADSP-BF548 */
-
 /* include cdefBF54x_base.h for the set of #defines that are common to all ADSP-BF54x bfin_read_()rocessors */
 #include "cdefBF54x_base.h"
 
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf548/include/mach/cdefBF549.h linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf548/include/mach/cdefBF549.h
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf548/include/mach/cdefBF549.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf548/include/mach/cdefBF549.h	2011-03-14 21:20:32.000000000 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright 2007-2008 Analog Devices Inc.
+ * Copyright 2007-2010 Analog Devices Inc.
  *
  * Licensed under the GPL-2 or later.
  */
@@ -7,14 +7,6 @@
 #ifndef _CDEF_BF549_H
 #define _CDEF_BF549_H
 
-/* include all Core registers and bit definitions */
-#include "defBF549.h"
-
-/* include core sbfin_read_()ecific register pointer definitions */
-#include <asm/cdef_LPBlackfin.h>
-
-/* SYSTEM & MMR ADDRESS DEFINITIONS FOR ADSP-BF549 */
-
 /* include cdefBF54x_base.h for the set of #defines that are common to all ADSP-BF54x bfin_read_()rocessors */
 #include "cdefBF54x_base.h"
 
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf548/include/mach/cdefBF54x_base.h linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf548/include/mach/cdefBF54x_base.h
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf548/include/mach/cdefBF54x_base.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf548/include/mach/cdefBF54x_base.h	2011-03-14 21:20:32.000000000 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright 2007-2008 Analog Devices Inc.
+ * Copyright 2007-2010 Analog Devices Inc.
  *
  * Licensed under the GPL-2 or later.
  */
@@ -7,10 +7,6 @@
 #ifndef _CDEF_BF54X_H
 #define _CDEF_BF54X_H
 
-#include <asm/blackfin.h>
-
-#include "defBF54x_base.h"
-
 /* ************************************************************** */
 /* SYSTEM & MMR ADDRESS DEFINITIONS COMMON TO ALL ADSP-BF54x    */
 /* ************************************************************** */
@@ -2633,22 +2629,5 @@
 
 /* Handshake MDMA is not defined in the shared file because it is not available on the ADSP-BF542 bfin_read_()rocessor */
 
-/* legacy definitions */
-#define bfin_read_EBIU_AMCBCTL0		bfin_read_EBIU_AMBCTL0
-#define bfin_write_EBIU_AMCBCTL0	bfin_write_EBIU_AMBCTL0
-#define bfin_read_EBIU_AMCBCTL1		bfin_read_EBIU_AMBCTL1
-#define bfin_write_EBIU_AMCBCTL1	bfin_write_EBIU_AMBCTL1
-#define bfin_read_PINT0_IRQ		bfin_read_PINT0_REQUEST
-#define bfin_write_PINT0_IRQ		bfin_write_PINT0_REQUEST
-#define bfin_read_PINT1_IRQ		bfin_read_PINT1_REQUEST
-#define bfin_write_PINT1_IRQ		bfin_write_PINT1_REQUEST
-#define bfin_read_PINT2_IRQ		bfin_read_PINT2_REQUEST
-#define bfin_write_PINT2_IRQ		bfin_write_PINT2_REQUEST
-#define bfin_read_PINT3_IRQ		bfin_read_PINT3_REQUEST
-#define bfin_write_PINT3_IRQ		bfin_write_PINT3_REQUEST
-
-/* These need to be last due to the cdef/linux inter-dependencies */
-#include <asm/irq.h>
-
 #endif /* _CDEF_BF54X_H */
 
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf548/include/mach/defBF542.h linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf548/include/mach/defBF542.h
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf548/include/mach/defBF542.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf548/include/mach/defBF542.h	2011-03-14 21:20:32.000000000 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright 2007-2008 Analog Devices Inc.
+ * Copyright 2007-2010 Analog Devices Inc.
  *
  * Licensed under the ADI BSD license or the GPL-2 (or later)
  */
@@ -7,11 +7,6 @@
 #ifndef _DEF_BF542_H
 #define _DEF_BF542_H
 
-/* Include all Core registers and bit definitions */
-#include <asm/def_LPBlackfin.h>
-
-/* SYSTEM & MMR ADDRESS DEFINITIONS FOR ADSP-BF542 */
-
 /* Include defBF54x_base.h for the set of #defines that are common to all ADSP-BF54x processors */
 #include "defBF54x_base.h"
 
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf548/include/mach/defBF544.h linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf548/include/mach/defBF544.h
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf548/include/mach/defBF544.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf548/include/mach/defBF544.h	2011-03-14 21:20:32.000000000 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright 2007-2008 Analog Devices Inc.
+ * Copyright 2007-2010 Analog Devices Inc.
  *
  * Licensed under the ADI BSD license or the GPL-2 (or later)
  */
@@ -7,11 +7,6 @@
 #ifndef _DEF_BF544_H
 #define _DEF_BF544_H
 
-/* Include all Core registers and bit definitions */
-#include <asm/def_LPBlackfin.h>
-
-/* SYSTEM & MMR ADDRESS DEFINITIONS FOR ADSP-BF544 */
-
 /* Include defBF54x_base.h for the set of #defines that are common to all ADSP-BF54x processors */
 #include "defBF54x_base.h"
 
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf548/include/mach/defBF547.h linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf548/include/mach/defBF547.h
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf548/include/mach/defBF547.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf548/include/mach/defBF547.h	2011-03-14 21:20:32.000000000 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright 2008 Analog Devices Inc.
+ * Copyright 2008-2010 Analog Devices Inc.
  *
  * Licensed under the ADI BSD license or the GPL-2 (or later)
  */
@@ -7,11 +7,6 @@
 #ifndef _DEF_BF547_H
 #define _DEF_BF547_H
 
-/* Include all Core registers and bit definitions */
-#include <asm/def_LPBlackfin.h>
-
-/* SYSTEM & MMR ADDRESS DEFINITIONS FOR ADSP-BF547 */
-
 /* Include defBF54x_base.h for the set of #defines that are common to all ADSP-BF54x processors */
 #include "defBF54x_base.h"
 
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf548/include/mach/defBF548.h linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf548/include/mach/defBF548.h
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf548/include/mach/defBF548.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf548/include/mach/defBF548.h	2011-03-14 21:20:32.000000000 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright 2007-2008 Analog Devices Inc.
+ * Copyright 2007-2010 Analog Devices Inc.
  *
  * Licensed under the ADI BSD license or the GPL-2 (or later)
  */
@@ -7,11 +7,6 @@
 #ifndef _DEF_BF548_H
 #define _DEF_BF548_H
 
-/* Include all Core registers and bit definitions */
-#include <asm/def_LPBlackfin.h>
-
-/* SYSTEM & MMR ADDRESS DEFINITIONS FOR ADSP-BF548 */
-
 /* Include defBF54x_base.h for the set of #defines that are common to all ADSP-BF54x processors */
 #include "defBF54x_base.h"
 
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf548/include/mach/defBF549.h linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf548/include/mach/defBF549.h
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf548/include/mach/defBF549.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf548/include/mach/defBF549.h	2011-03-14 21:20:32.000000000 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright 2007-2008 Analog Devices Inc.
+ * Copyright 2007-2010 Analog Devices Inc.
  *
  * Licensed under the ADI BSD license or the GPL-2 (or later)
  */
@@ -7,11 +7,6 @@
 #ifndef _DEF_BF549_H
 #define _DEF_BF549_H
 
-/* Include all Core registers and bit definitions */
-#include <asm/def_LPBlackfin.h>
-
-/* SYSTEM & MMR ADDRESS DEFINITIONS FOR ADSP-BF549 */
-
 /* Include defBF54x_base.h for the set of #defines that are common to all ADSP-BF54x processors */
 #include "defBF54x_base.h"
 
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf548/include/mach/defBF54x_base.h linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf548/include/mach/defBF54x_base.h
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf548/include/mach/defBF54x_base.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf548/include/mach/defBF54x_base.h	2011-03-14 21:20:32.000000000 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright 2007-2008 Analog Devices Inc.
+ * Copyright 2007-2010 Analog Devices Inc.
  *
  * Licensed under the ADI BSD license or the GPL-2 (or later)
  */
@@ -1615,14 +1615,14 @@
 #define                     CTYPE  0x40       /* DMA Channel Type */
 #define                      PMAP  0xf000     /* Peripheral Mapped To This Channel */
 
-/* Bit masks for DMACx_TCPER */
+/* Bit masks for DMACx_TC_PER */
 
 #define        DCB_TRAFFIC_PERIOD  0xf        /* DCB Traffic Control Period */
 #define        DEB_TRAFFIC_PERIOD  0xf0       /* DEB Traffic Control Period */
 #define        DAB_TRAFFIC_PERIOD  0x700      /* DAB Traffic Control Period */
 #define   MDMA_ROUND_ROBIN_PERIOD  0xf800     /* MDMA Round Robin Period */
 
-/* Bit masks for DMACx_TCCNT */
+/* Bit masks for DMACx_TC_CNT */
 
 #define         DCB_TRAFFIC_COUNT  0xf        /* DCB Traffic Control Count */
 #define         DEB_TRAFFIC_COUNT  0xf0       /* DEB Traffic Control Count */
@@ -2172,68 +2172,6 @@
 
 #define                 RCVDATA16  0xffff     /* Receive FIFO 16-Bit Data */
 
-/* Bit masks for UARTx_LCR */
-
-#if 0
-/* conflicts with legacy one in last section */
-#define                       WLS  0x3        /* Word Length Select */
-#endif
-#define                       STB  0x4        /* Stop Bits */
-#define                       PEN  0x8        /* Parity Enable */
-#define                       EPS  0x10       /* Even Parity Select */
-#define                       STP  0x20       /* Sticky Parity */
-#define                        SB  0x40       /* Set Break */
-
-/* Bit masks for UARTx_MCR */
-
-#define                      XOFF  0x1        /* Transmitter Off */
-#define                      MRTS  0x2        /* Manual Request To Send */
-#define                      RFIT  0x4        /* Receive FIFO IRQ Threshold */
-#define                      RFRT  0x8        /* Receive FIFO RTS Threshold */
-#define                  LOOP_ENA  0x10       /* Loopback Mode Enable */
-#define                     FCPOL  0x20       /* Flow Control Pin Polarity */
-#define                      ARTS  0x40       /* Automatic Request To Send */
-#define                      ACTS  0x80       /* Automatic Clear To Send */
-
-/* Bit masks for UARTx_LSR */
-
-#define                        DR  0x1        /* Data Ready */
-#define                        OE  0x2        /* Overrun Error */
-#define                        PE  0x4        /* Parity Error */
-#define                        FE  0x8        /* Framing Error */
-#define                        BI  0x10       /* Break Interrupt */
-#define                      THRE  0x20       /* THR Empty */
-#define                      TEMT  0x40       /* Transmitter Empty */
-#define                       TFI  0x80       /* Transmission Finished Indicator */
-
-/* Bit masks for UARTx_MSR */
-
-#define                      SCTS  0x1        /* Sticky CTS */
-#define                       CTS  0x10       /* Clear To Send */
-#define                      RFCS  0x20       /* Receive FIFO Count Status */
-
-/* Bit masks for UARTx_IER_SET & UARTx_IER_CLEAR */
-
-#define                   ERBFI  0x1        /* Enable Receive Buffer Full Interrupt */
-#define                   ETBEI  0x2        /* Enable Transmit Buffer Empty Interrupt */
-#define                    ELSI  0x4        /* Enable Receive Status Interrupt */
-#define                   EDSSI  0x8        /* Enable Modem Status Interrupt */
-#define                  EDTPTI  0x10       /* Enable DMA Transmit PIRQ Interrupt */
-#define                    ETFI  0x20       /* Enable Transmission Finished Interrupt */
-#define                   ERFCI  0x40       /* Enable Receive FIFO Count Interrupt */
-
-/* Bit masks for UARTx_GCTL */
-
-#define                      UCEN  0x1        /* UART Enable */
-#define                      IREN  0x2        /* IrDA Mode Enable */
-#define                     TPOLC  0x4        /* IrDA TX Polarity Change */
-#define                     RPOLC  0x8        /* IrDA RX Polarity Change */
-#define                       FPE  0x10       /* Force Parity Error */
-#define                       FFE  0x20       /* Force Framing Error */
-#define                      EDBO  0x40       /* Enable Divide-by-One */
-#define                     EGLSI  0x80       /* Enable Global LS Interrupt */
-
-
 /* ******************************************* */
 /*     MULTI BIT MACRO ENUMERATIONS            */
 /* ******************************************* */
@@ -2251,13 +2189,6 @@
 #define WDTH_CAP 0x0002
 #define EXT_CLK  0x0003
 
-/* UARTx_LCR bit field options */
-
-#define WLS_5   0x0000    /* 5 data bits */
-#define WLS_6   0x0001    /* 6 data bits */
-#define WLS_7   0x0002    /* 7 data bits */
-#define WLS_8   0x0003    /* 8 data bits */
-
 /* PINTx Register Bit Definitions */
 
 #define PIQ0 0x00000001
@@ -2300,240 +2231,6 @@
 #define PIQ30 0x40000000
 #define PIQ31 0x80000000
 
-/* PORT A Bit Definitions for the registers
-PORTA, PORTA_SET, PORTA_CLEAR,
-PORTA_DIR_SET, PORTA_DIR_CLEAR, PORTA_INEN,
-PORTA_FER registers
-*/
-
-#define PA0 0x0001
-#define PA1 0x0002
-#define PA2 0x0004
-#define PA3 0x0008
-#define PA4 0x0010
-#define PA5 0x0020
-#define PA6 0x0040
-#define PA7 0x0080
-#define PA8 0x0100
-#define PA9 0x0200
-#define PA10 0x0400
-#define PA11 0x0800
-#define PA12 0x1000
-#define PA13 0x2000
-#define PA14 0x4000
-#define PA15 0x8000
-
-/* PORT B Bit Definitions for the registers
-PORTB, PORTB_SET, PORTB_CLEAR,
-PORTB_DIR_SET, PORTB_DIR_CLEAR, PORTB_INEN,
-PORTB_FER registers
-*/
-
-#define PB0 0x0001
-#define PB1 0x0002
-#define PB2 0x0004
-#define PB3 0x0008
-#define PB4 0x0010
-#define PB5 0x0020
-#define PB6 0x0040
-#define PB7 0x0080
-#define PB8 0x0100
-#define PB9 0x0200
-#define PB10 0x0400
-#define PB11 0x0800
-#define PB12 0x1000
-#define PB13 0x2000
-#define PB14 0x4000
-
-
-/* PORT C Bit Definitions for the registers
-PORTC, PORTC_SET, PORTC_CLEAR,
-PORTC_DIR_SET, PORTC_DIR_CLEAR, PORTC_INEN,
-PORTC_FER registers
-*/
-
-
-#define PC0 0x0001
-#define PC1 0x0002
-#define PC2 0x0004
-#define PC3 0x0008
-#define PC4 0x0010
-#define PC5 0x0020
-#define PC6 0x0040
-#define PC7 0x0080
-#define PC8 0x0100
-#define PC9 0x0200
-#define PC10 0x0400
-#define PC11 0x0800
-#define PC12 0x1000
-#define PC13 0x2000
-
-
-/* PORT D Bit Definitions for the registers
-PORTD, PORTD_SET, PORTD_CLEAR,
-PORTD_DIR_SET, PORTD_DIR_CLEAR, PORTD_INEN,
-PORTD_FER registers
-*/
-
-#define PD0 0x0001
-#define PD1 0x0002
-#define PD2 0x0004
-#define PD3 0x0008
-#define PD4 0x0010
-#define PD5 0x0020
-#define PD6 0x0040
-#define PD7 0x0080
-#define PD8 0x0100
-#define PD9 0x0200
-#define PD10 0x0400
-#define PD11 0x0800
-#define PD12 0x1000
-#define PD13 0x2000
-#define PD14 0x4000
-#define PD15 0x8000
-
-/* PORT E Bit Definitions for the registers
-PORTE, PORTE_SET, PORTE_CLEAR,
-PORTE_DIR_SET, PORTE_DIR_CLEAR, PORTE_INEN,
-PORTE_FER registers
-*/
-
-
-#define PE0 0x0001
-#define PE1 0x0002
-#define PE2 0x0004
-#define PE3 0x0008
-#define PE4 0x0010
-#define PE5 0x0020
-#define PE6 0x0040
-#define PE7 0x0080
-#define PE8 0x0100
-#define PE9 0x0200
-#define PE10 0x0400
-#define PE11 0x0800
-#define PE12 0x1000
-#define PE13 0x2000
-#define PE14 0x4000
-#define PE15 0x8000
-
-/* PORT F Bit Definitions for the registers
-PORTF, PORTF_SET, PORTF_CLEAR,
-PORTF_DIR_SET, PORTF_DIR_CLEAR, PORTF_INEN,
-PORTF_FER registers
-*/
-
-
-#define PF0 0x0001
-#define PF1 0x0002
-#define PF2 0x0004
-#define PF3 0x0008
-#define PF4 0x0010
-#define PF5 0x0020
-#define PF6 0x0040
-#define PF7 0x0080
-#define PF8 0x0100
-#define PF9 0x0200
-#define PF10 0x0400
-#define PF11 0x0800
-#define PF12 0x1000
-#define PF13 0x2000
-#define PF14 0x4000
-#define PF15 0x8000
-
-/* PORT G Bit Definitions for the registers
-PORTG, PORTG_SET, PORTG_CLEAR,
-PORTG_DIR_SET, PORTG_DIR_CLEAR, PORTG_INEN,
-PORTG_FER registers
-*/
-
-
-#define PG0 0x0001
-#define PG1 0x0002
-#define PG2 0x0004
-#define PG3 0x0008
-#define PG4 0x0010
-#define PG5 0x0020
-#define PG6 0x0040
-#define PG7 0x0080
-#define PG8 0x0100
-#define PG9 0x0200
-#define PG10 0x0400
-#define PG11 0x0800
-#define PG12 0x1000
-#define PG13 0x2000
-#define PG14 0x4000
-#define PG15 0x8000
-
-/* PORT H Bit Definitions for the registers
-PORTH, PORTH_SET, PORTH_CLEAR,
-PORTH_DIR_SET, PORTH_DIR_CLEAR, PORTH_INEN,
-PORTH_FER registers
-*/
-
-
-#define PH0 0x0001
-#define PH1 0x0002
-#define PH2 0x0004
-#define PH3 0x0008
-#define PH4 0x0010
-#define PH5 0x0020
-#define PH6 0x0040
-#define PH7 0x0080
-#define PH8 0x0100
-#define PH9 0x0200
-#define PH10 0x0400
-#define PH11 0x0800
-#define PH12 0x1000
-#define PH13 0x2000
-
-
-/* PORT I Bit Definitions for the registers
-PORTI, PORTI_SET, PORTI_CLEAR,
-PORTI_DIR_SET, PORTI_DIR_CLEAR, PORTI_INEN,
-PORTI_FER registers
-*/
-
-
-#define PI0 0x0001
-#define PI1 0x0002
-#define PI2 0x0004
-#define PI3 0x0008
-#define PI4 0x0010
-#define PI5 0x0020
-#define PI6 0x0040
-#define PI7 0x0080
-#define PI8 0x0100
-#define PI9 0x0200
-#define PI10 0x0400
-#define PI11 0x0800
-#define PI12 0x1000
-#define PI13 0x2000
-#define PI14 0x4000
-#define PI15 0x8000
-
-/* PORT J Bit Definitions for the registers
-PORTJ, PORTJ_SET, PORTJ_CLEAR,
-PORTJ_DIR_SET, PORTJ_DIR_CLEAR, PORTJ_INEN,
-PORTJ_FER registers
-*/
-
-
-#define PJ0 0x0001
-#define PJ1 0x0002
-#define PJ2 0x0004
-#define PJ3 0x0008
-#define PJ4 0x0010
-#define PJ5 0x0020
-#define PJ6 0x0040
-#define PJ7 0x0080
-#define PJ8 0x0100
-#define PJ9 0x0200
-#define PJ10 0x0400
-#define PJ11 0x0800
-#define PJ12 0x1000
-#define PJ13 0x2000
-
-
 /* Port Muxing Bit Fields for PORTx_MUX Registers */
 
 #define MUX0 0x00000003
@@ -2703,16 +2400,4 @@ PORTJ_FER registers
 #define B3MAP_PIH 0x06000000 /* Map Port I High to Byte 3 */
 #define B3MAP_PJH 0x07000000 /* Map Port J High to Byte 3 */
 
-
-/* for legacy compatibility */
-
-#define WLS(x)  (((x)-5) & 0x03) /* Word Length Select */
-#define W1LMAX_MAX W1LMAX_MIN
-#define EBIU_AMCBCTL0 EBIU_AMBCTL0
-#define EBIU_AMCBCTL1 EBIU_AMBCTL1
-#define PINT0_IRQ PINT0_REQUEST
-#define PINT1_IRQ PINT1_REQUEST
-#define PINT2_IRQ PINT2_REQUEST
-#define PINT3_IRQ PINT3_REQUEST
-
 #endif /* _DEF_BF54X_H */
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf548/include/mach/gpio.h linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf548/include/mach/gpio.h
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf548/include/mach/gpio.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf548/include/mach/gpio.h	2011-03-14 21:20:32.000000000 -0400
@@ -200,4 +200,15 @@ struct gpio_port_s {
 
 #endif
 
+#include <mach-common/ports-a.h>
+#include <mach-common/ports-b.h>
+#include <mach-common/ports-c.h>
+#include <mach-common/ports-d.h>
+#include <mach-common/ports-e.h>
+#include <mach-common/ports-f.h>
+#include <mach-common/ports-g.h>
+#include <mach-common/ports-h.h>
+#include <mach-common/ports-i.h>
+#include <mach-common/ports-j.h>
+
 #endif /* _MACH_GPIO_H_ */
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf548/include/mach/irq.h linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf548/include/mach/irq.h
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf548/include/mach/irq.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf548/include/mach/irq.h	2011-03-14 21:20:32.000000000 -0400
@@ -474,4 +474,26 @@ Events         (highest priority)  EMU
 #define IRQ_PINT2_POS		24
 #define IRQ_PINT3_POS		28
 
+#ifndef __ASSEMBLY__
+#include <linux/types.h>
+
+/*
+ * bfin pint registers layout
+ */
+struct bfin_pint_regs {
+	u32 mask_set;
+	u32 mask_clear;
+	u32 irq;
+	u32 assign;
+	u32 edge_set;
+	u32 edge_clear;
+	u32 invert_set;
+	u32 invert_clear;
+	u32 pinstate;
+	u32 latch;
+	u32 __pad0[2];
+};
+
+#endif
+
 #endif /* _BF548_IRQ_H_ */
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf548/include/mach/pll.h linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf548/include/mach/pll.h
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf548/include/mach/pll.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf548/include/mach/pll.h	2011-03-14 21:20:32.000000000 -0400
@@ -1,69 +1 @@
-/*
- * Copyright 2007-2008 Analog Devices Inc.
- *
- * Licensed under the GPL-2 or later.
- */
-
-#ifndef _MACH_PLL_H
-#define _MACH_PLL_H
-
-#include <asm/blackfin.h>
-#include <asm/irqflags.h>
-
-/* Writing to PLL_CTL initiates a PLL relock sequence. */
-static __inline__ void bfin_write_PLL_CTL(unsigned int val)
-{
-	unsigned long flags, iwr0, iwr1, iwr2;
-
-	if (val == bfin_read_PLL_CTL())
-		return;
-
-	flags = hard_local_irq_save();
-	/* Enable the PLL Wakeup bit in SIC IWR */
-	iwr0 = bfin_read32(SIC_IWR0);
-	iwr1 = bfin_read32(SIC_IWR1);
-	iwr2 = bfin_read32(SIC_IWR2);
-	/* Only allow PPL Wakeup) */
-	bfin_write32(SIC_IWR0, IWR_ENABLE(0));
-	bfin_write32(SIC_IWR1, 0);
-	bfin_write32(SIC_IWR2, 0);
-
-	bfin_write16(PLL_CTL, val);
-	SSYNC();
-	asm("IDLE;");
-
-	bfin_write32(SIC_IWR0, iwr0);
-	bfin_write32(SIC_IWR1, iwr1);
-	bfin_write32(SIC_IWR2, iwr2);
-	hard_local_irq_restore(flags);
-}
-
-/* Writing to VR_CTL initiates a PLL relock sequence. */
-static __inline__ void bfin_write_VR_CTL(unsigned int val)
-{
-	unsigned long flags, iwr0, iwr1, iwr2;
-
-	if (val == bfin_read_VR_CTL())
-		return;
-
-	flags = hard_local_irq_save();
-	/* Enable the PLL Wakeup bit in SIC IWR */
-	iwr0 = bfin_read32(SIC_IWR0);
-	iwr1 = bfin_read32(SIC_IWR1);
-	iwr2 = bfin_read32(SIC_IWR2);
-	/* Only allow PPL Wakeup) */
-	bfin_write32(SIC_IWR0, IWR_ENABLE(0));
-	bfin_write32(SIC_IWR1, 0);
-	bfin_write32(SIC_IWR2, 0);
-
-	bfin_write16(VR_CTL, val);
-	SSYNC();
-	asm("IDLE;");
-
-	bfin_write32(SIC_IWR0, iwr0);
-	bfin_write32(SIC_IWR1, iwr1);
-	bfin_write32(SIC_IWR2, iwr2);
-	hard_local_irq_restore(flags);
-}
-
-#endif /* _MACH_PLL_H */
+#include <mach-common/pll.h>
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf561/atomic.S linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf561/atomic.S
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf561/atomic.S	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf561/atomic.S	2011-03-14 21:20:32.000000000 -0400
@@ -49,6 +49,7 @@ ENTRY(_get_core_lock)
 	jump .Lretry_corelock
 .Ldone_corelock:
 	p0 = r1;
+	/* flush core internal write buffer before invalidate dcache */
 	CSYNC(r2);
 	flushinv[p0];
 	SSYNC(r2);
@@ -685,6 +686,8 @@ ENTRY(___raw_atomic_test_asm)
 	r1 = -L1_CACHE_BYTES;
 	r1 = r0 & r1;
 	p0 = r1;
+	/* flush core internal write buffer before invalidate dcache */
+	CSYNC(r2);
 	flushinv[p0];
 	SSYNC(r2);
 	r0 = [p1];
@@ -907,6 +910,8 @@ ENTRY(___raw_uncached_fetch_asm)
 	r1 = -L1_CACHE_BYTES;
 	r1 = r0 & r1;
 	p0 = r1;
+	/* flush core internal write buffer before invalidate dcache */
+	CSYNC(r2);
 	flushinv[p0];
 	SSYNC(r2);
 	r0 = [p1];
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf561/boards/acvilon.c linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf561/boards/acvilon.c
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf561/boards/acvilon.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf561/boards/acvilon.c	2011-03-14 21:20:32.000000000 -0400
@@ -224,7 +224,7 @@ static struct resource bfin_uart0_resour
 	 },
 };
 
-unsigned short bfin_uart0_peripherals[] = {
+static unsigned short bfin_uart0_peripherals[] = {
 	P_UART0_TX, P_UART0_RX, 0
 };
 
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf561/boards/cm_bf561.c linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf561/boards/cm_bf561.c
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf561/boards/cm_bf561.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf561/boards/cm_bf561.c	2011-03-14 21:20:32.000000000 -0400
@@ -334,7 +334,7 @@ static struct resource bfin_uart0_resour
 	},
 };
 
-unsigned short bfin_uart0_peripherals[] = {
+static unsigned short bfin_uart0_peripherals[] = {
 	P_UART0_TX, P_UART0_RX, 0
 };
 
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf561/boards/ezkit.c linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf561/boards/ezkit.c
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf561/boards/ezkit.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf561/boards/ezkit.c	2011-03-14 21:20:32.000000000 -0400
@@ -190,7 +190,7 @@ static struct resource bfin_uart0_resour
 	},
 };
 
-unsigned short bfin_uart0_peripherals[] = {
+static unsigned short bfin_uart0_peripherals[] = {
 	P_UART0_TX, P_UART0_RX, 0
 };
 
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf561/boards/tepla.c linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf561/boards/tepla.c
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf561/boards/tepla.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf561/boards/tepla.c	2011-03-14 21:20:32.000000000 -0400
@@ -72,7 +72,7 @@ static struct resource bfin_uart0_resour
 	},
 };
 
-unsigned short bfin_uart0_peripherals[] = {
+static unsigned short bfin_uart0_peripherals[] = {
 	P_UART0_TX, P_UART0_RX, 0
 };
 
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf561/dma.c linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf561/dma.c
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf561/dma.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf561/dma.c	2011-03-14 21:20:32.000000000 -0400
@@ -11,7 +11,7 @@
 #include <asm/blackfin.h>
 #include <asm/dma.h>
 
-struct dma_register *dma_io_base_addr[MAX_DMA_CHANNELS] = {
+struct dma_register * const dma_io_base_addr[MAX_DMA_CHANNELS] = {
 	(struct dma_register *) DMA1_0_NEXT_DESC_PTR,
 	(struct dma_register *) DMA1_1_NEXT_DESC_PTR,
 	(struct dma_register *) DMA1_2_NEXT_DESC_PTR,
@@ -36,14 +36,14 @@ struct dma_register *dma_io_base_addr[MA
 	(struct dma_register *) DMA2_9_NEXT_DESC_PTR,
 	(struct dma_register *) DMA2_10_NEXT_DESC_PTR,
 	(struct dma_register *) DMA2_11_NEXT_DESC_PTR,
-	(struct dma_register *) MDMA1_D0_NEXT_DESC_PTR,
-	(struct dma_register *) MDMA1_S0_NEXT_DESC_PTR,
-	(struct dma_register *) MDMA1_D1_NEXT_DESC_PTR,
-	(struct dma_register *) MDMA1_S1_NEXT_DESC_PTR,
-	(struct dma_register *) MDMA2_D0_NEXT_DESC_PTR,
-	(struct dma_register *) MDMA2_S0_NEXT_DESC_PTR,
-	(struct dma_register *) MDMA2_D1_NEXT_DESC_PTR,
-	(struct dma_register *) MDMA2_S1_NEXT_DESC_PTR,
+	(struct dma_register *) MDMA_D0_NEXT_DESC_PTR,
+	(struct dma_register *) MDMA_S0_NEXT_DESC_PTR,
+	(struct dma_register *) MDMA_D1_NEXT_DESC_PTR,
+	(struct dma_register *) MDMA_S1_NEXT_DESC_PTR,
+	(struct dma_register *) MDMA_D2_NEXT_DESC_PTR,
+	(struct dma_register *) MDMA_S2_NEXT_DESC_PTR,
+	(struct dma_register *) MDMA_D3_NEXT_DESC_PTR,
+	(struct dma_register *) MDMA_S3_NEXT_DESC_PTR,
 	(struct dma_register *) IMDMA_D0_NEXT_DESC_PTR,
 	(struct dma_register *) IMDMA_S0_NEXT_DESC_PTR,
 	(struct dma_register *) IMDMA_D1_NEXT_DESC_PTR,
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf561/hotplug.c linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf561/hotplug.c
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf561/hotplug.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf561/hotplug.c	2011-03-14 21:20:32.000000000 -0400
@@ -6,7 +6,9 @@
  */
 
 #include <asm/blackfin.h>
+#include <asm/irq.h>
 #include <asm/smp.h>
+
 #define SIC_SYSIRQ(irq)	(irq - (IRQ_CORETMR + 1))
 
 int hotplug_coreb;
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf561/include/mach/anomaly.h linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf561/include/mach/anomaly.h
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf561/include/mach/anomaly.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf561/include/mach/anomaly.h	2011-03-14 21:20:32.000000000 -0400
@@ -181,7 +181,11 @@
 /* Incorrect Timer Pulse Width in Single-Shot PWM_OUT Mode with External Clock */
 #define ANOMALY_05000254 (__SILICON_REVISION__ > 3)
 /* Interrupt/Exception During Short Hardware Loop May Cause Bad Instruction Fetches */
-#define ANOMALY_05000257 (__SILICON_REVISION__ < 5)
+/* Tempoary work around for kgdb bug 6333 in SMP kernel. It looks coreb hangs in exception
+ * without handling anomaly 05000257 properly on bf561 v0.5. This work around may change
+ * after the behavior and the root cause are confirmed with hardware team.
+ */
+#define ANOMALY_05000257 (__SILICON_REVISION__ < 5 || (__SILICON_REVISION__ == 5 && CONFIG_SMP))
 /* Instruction Cache Is Corrupted When Bits 9 and 12 of the ICPLB Data Registers Differ */
 #define ANOMALY_05000258 (__SILICON_REVISION__ < 5)
 /* ICPLB_STATUS MMR Register May Be Corrupted */
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf561/include/mach/bfin_serial_5xx.h linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf561/include/mach/bfin_serial_5xx.h
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf561/include/mach/bfin_serial_5xx.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf561/include/mach/bfin_serial_5xx.h	2011-03-14 21:20:32.000000000 -0400
@@ -4,36 +4,9 @@
  * Licensed under the GPL-2 or later.
  */
 
-#include <linux/serial.h>
 #include <asm/dma.h>
 #include <asm/portmux.h>
 
-#define UART_GET_CHAR(uart)     bfin_read16(((uart)->port.membase + OFFSET_RBR))
-#define UART_GET_DLL(uart)	bfin_read16(((uart)->port.membase + OFFSET_DLL))
-#define UART_GET_IER(uart)      bfin_read16(((uart)->port.membase + OFFSET_IER))
-#define UART_GET_DLH(uart)	bfin_read16(((uart)->port.membase + OFFSET_DLH))
-#define UART_GET_IIR(uart)      bfin_read16(((uart)->port.membase + OFFSET_IIR))
-#define UART_GET_LCR(uart)      bfin_read16(((uart)->port.membase + OFFSET_LCR))
-#define UART_GET_GCTL(uart)     bfin_read16(((uart)->port.membase + OFFSET_GCTL))
-
-#define UART_PUT_CHAR(uart,v)   bfin_write16(((uart)->port.membase + OFFSET_THR),v)
-#define UART_PUT_DLL(uart,v)    bfin_write16(((uart)->port.membase + OFFSET_DLL),v)
-#define UART_PUT_IER(uart,v)    bfin_write16(((uart)->port.membase + OFFSET_IER),v)
-#define UART_SET_IER(uart,v)    UART_PUT_IER(uart, UART_GET_IER(uart) | (v))
-#define UART_CLEAR_IER(uart,v)  UART_PUT_IER(uart, UART_GET_IER(uart) & ~(v))
-#define UART_PUT_DLH(uart,v)    bfin_write16(((uart)->port.membase + OFFSET_DLH),v)
-#define UART_PUT_LCR(uart,v)    bfin_write16(((uart)->port.membase + OFFSET_LCR),v)
-#define UART_PUT_GCTL(uart,v)   bfin_write16(((uart)->port.membase + OFFSET_GCTL),v)
-
-#define UART_SET_DLAB(uart)     do { UART_PUT_LCR(uart, UART_GET_LCR(uart) | DLAB); SSYNC(); } while (0)
-#define UART_CLEAR_DLAB(uart)   do { UART_PUT_LCR(uart, UART_GET_LCR(uart) & ~DLAB); SSYNC(); } while (0)
-
-#define UART_GET_CTS(x) gpio_get_value(x->cts_pin)
-#define UART_DISABLE_RTS(x) gpio_set_value(x->rts_pin, 1)
-#define UART_ENABLE_RTS(x) gpio_set_value(x->rts_pin, 0)
-#define UART_ENABLE_INTS(x, v) UART_PUT_IER(x, v)
-#define UART_DISABLE_INTS(x) UART_PUT_IER(x, 0)
-
 #ifdef CONFIG_BFIN_UART0_CTSRTS
 # define CONFIG_SERIAL_BFIN_CTSRTS
 # ifndef CONFIG_UART0_CTS_PIN
@@ -44,51 +17,6 @@
 # endif
 #endif
 
-#define BFIN_UART_TX_FIFO_SIZE	2
-
-struct bfin_serial_port {
-        struct uart_port        port;
-        unsigned int            old_status;
-	int			status_irq;
-	unsigned int lsr;
-#ifdef CONFIG_SERIAL_BFIN_DMA
-	int			tx_done;
-	int			tx_count;
-	struct circ_buf		rx_dma_buf;
-	struct timer_list       rx_dma_timer;
-	int			rx_dma_nrows;
-	unsigned int		tx_dma_channel;
-	unsigned int		rx_dma_channel;
-	struct work_struct	tx_dma_workqueue;
-#else
-# if ANOMALY_05000363
-	unsigned int anomaly_threshold;
-# endif
-#endif
-#ifdef CONFIG_SERIAL_BFIN_CTSRTS
-	struct timer_list       cts_timer;
-	int			cts_pin;
-	int			rts_pin;
-#endif
-};
-
-/* The hardware clears the LSR bits upon read, so we need to cache
- * some of the more fun bits in software so they don't get lost
- * when checking the LSR in other code paths (TX).
- */
-static inline unsigned int UART_GET_LSR(struct bfin_serial_port *uart)
-{
-	unsigned int lsr = bfin_read16(uart->port.membase + OFFSET_LSR);
-	uart->lsr |= (lsr & (BI|FE|PE|OE));
-	return lsr | uart->lsr;
-}
-
-static inline void UART_CLEAR_LSR(struct bfin_serial_port *uart)
-{
-	uart->lsr = 0;
-	bfin_write16(uart->port.membase + OFFSET_LSR, -1);
-}
-
 struct bfin_serial_res {
 	unsigned long	uart_base_addr;
 	int		uart_irq;
@@ -120,3 +48,5 @@ struct bfin_serial_res bfin_serial_resou
 };
 
 #define DRIVER_NAME "bfin-uart"
+
+#include <asm/bfin_serial.h>
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf561/include/mach/bfin_serial.h linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf561/include/mach/bfin_serial.h
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf561/include/mach/bfin_serial.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf561/include/mach/bfin_serial.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,14 @@
+/*
+ * mach/bfin_serial.h - Blackfin UART/Serial definitions
+ *
+ * Copyright 2006-2010 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#ifndef __BFIN_MACH_SERIAL_H__
+#define __BFIN_MACH_SERIAL_H__
+
+#define BFIN_UART_NR_PORTS	1
+
+#endif
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf561/include/mach/blackfin.h linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf561/include/mach/blackfin.h
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf561/include/mach/blackfin.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf561/include/mach/blackfin.h	2011-03-14 21:20:32.000000000 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright 2005-2009 Analog Devices Inc.
+ * Copyright 2005-2010 Analog Devices Inc.
  *
  * Licensed under the GPL-2 or later.
  */
@@ -10,11 +10,14 @@
 #define BF561_FAMILY
 
 #include "bf561.h"
-#include "defBF561.h"
 #include "anomaly.h"
 
-#if !defined(__ASSEMBLY__)
-#include "cdefBF561.h"
+#include <asm/def_LPBlackfin.h>
+#include "defBF561.h"
+
+#ifndef __ASSEMBLY__
+# include <asm/cdef_LPBlackfin.h>
+# include "cdefBF561.h"
 #endif
 
 #define bfin_read_FIO_FLAG_D() bfin_read_FIO0_FLAG_D()
@@ -35,19 +38,4 @@
 #define bfin_read_SICB_ISR(x)		bfin_read32(__SIC_MUX(SICB_ISR0, x))
 #define bfin_write_SICB_ISR(x, val)	bfin_write32(__SIC_MUX(SICB_ISR0, x), val)
 
-#define BFIN_UART_NR_PORTS      1
-
-#define OFFSET_THR              0x00	/* Transmit Holding register            */
-#define OFFSET_RBR              0x00	/* Receive Buffer register              */
-#define OFFSET_DLL              0x00	/* Divisor Latch (Low-Byte)             */
-#define OFFSET_IER              0x04	/* Interrupt Enable Register            */
-#define OFFSET_DLH              0x04	/* Divisor Latch (High-Byte)            */
-#define OFFSET_IIR              0x08	/* Interrupt Identification Register    */
-#define OFFSET_LCR              0x0C	/* Line Control Register                */
-#define OFFSET_MCR              0x10	/* Modem Control Register               */
-#define OFFSET_LSR              0x14	/* Line Status Register                 */
-#define OFFSET_MSR              0x18	/* Modem Status Register                */
-#define OFFSET_SCR              0x1C	/* SCR Scratch Register                 */
-#define OFFSET_GCTL             0x24	/* Global Control Register              */
-
 #endif				/* _MACH_BLACKFIN_H_ */
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf561/include/mach/cdefBF561.h linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf561/include/mach/cdefBF561.h
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf561/include/mach/cdefBF561.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf561/include/mach/cdefBF561.h	2011-03-14 21:20:32.000000000 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright 2005-2009 Analog Devices Inc.
+ * Copyright 2005-2010 Analog Devices Inc.
  *
  * Licensed under the GPL-2 or later.
  */
@@ -7,14 +7,6 @@
 #ifndef _CDEF_BF561_H
 #define _CDEF_BF561_H
 
-#include <asm/blackfin.h>
-
-/* include all Core registers and bit definitions */
-#include "defBF561.h"
-
-/*include core specific register pointer definitions*/
-#include <asm/cdef_LPBlackfin.h>
-
 /*********************************************************************************** */
 /* System MMR Register Map */
 /*********************************************************************************** */
@@ -523,14 +515,14 @@
 #define bfin_read_PPI1_FRAME()               bfin_read16(PPI1_FRAME)
 #define bfin_write_PPI1_FRAME(val)           bfin_write16(PPI1_FRAME,val)
 /*DMA traffic control registers */
-#define bfin_read_DMA1_TC_PER()              bfin_read16(DMA1_TC_PER)
-#define bfin_write_DMA1_TC_PER(val)          bfin_write16(DMA1_TC_PER,val)
-#define bfin_read_DMA1_TC_CNT()              bfin_read16(DMA1_TC_CNT)
-#define bfin_write_DMA1_TC_CNT(val)          bfin_write16(DMA1_TC_CNT,val)
-#define bfin_read_DMA2_TC_PER()              bfin_read16(DMA2_TC_PER)
-#define bfin_write_DMA2_TC_PER(val)          bfin_write16(DMA2_TC_PER,val)
-#define bfin_read_DMA2_TC_CNT()              bfin_read16(DMA2_TC_CNT)
-#define bfin_write_DMA2_TC_CNT(val)          bfin_write16(DMA2_TC_CNT,val)
+#define bfin_read_DMAC0_TC_PER()             bfin_read16(DMAC0_TC_PER)
+#define bfin_write_DMAC0_TC_PER(val)         bfin_write16(DMAC0_TC_PER,val)
+#define bfin_read_DMAC0_TC_CNT()             bfin_read16(DMAC0_TC_CNT)
+#define bfin_write_DMAC0_TC_CNT(val)         bfin_write16(DMAC0_TC_CNT,val)
+#define bfin_read_DMAC1_TC_PER()             bfin_read16(DMAC1_TC_PER)
+#define bfin_write_DMAC1_TC_PER(val)         bfin_write16(DMAC1_TC_PER,val)
+#define bfin_read_DMAC1_TC_CNT()             bfin_read16(DMAC1_TC_CNT)
+#define bfin_write_DMAC1_TC_CNT(val)         bfin_write16(DMAC1_TC_CNT,val)
 /* DMA1 Controller registers (0xFFC0 1C00-0xFFC0 1FFF) */
 #define bfin_read_DMA1_0_CONFIG()            bfin_read16(DMA1_0_CONFIG)
 #define bfin_write_DMA1_0_CONFIG(val)        bfin_write16(DMA1_0_CONFIG,val)
@@ -845,110 +837,110 @@
 #define bfin_read_DMA1_11_PERIPHERAL_MAP()   bfin_read16(DMA1_11_PERIPHERAL_MAP)
 #define bfin_write_DMA1_11_PERIPHERAL_MAP(val) bfin_write16(DMA1_11_PERIPHERAL_MAP,val)
 /* Memory DMA1 Controller registers (0xFFC0 1E80-0xFFC0 1FFF) */
-#define bfin_read_MDMA1_D0_CONFIG()          bfin_read16(MDMA1_D0_CONFIG)
-#define bfin_write_MDMA1_D0_CONFIG(val)      bfin_write16(MDMA1_D0_CONFIG,val)
-#define bfin_read_MDMA1_D0_NEXT_DESC_PTR()   bfin_read32(MDMA1_D0_NEXT_DESC_PTR)
-#define bfin_write_MDMA1_D0_NEXT_DESC_PTR(val) bfin_write32(MDMA1_D0_NEXT_DESC_PTR,val)
-#define bfin_read_MDMA1_D0_START_ADDR()      bfin_read32(MDMA1_D0_START_ADDR)
-#define bfin_write_MDMA1_D0_START_ADDR(val)  bfin_write32(MDMA1_D0_START_ADDR,val)
-#define bfin_read_MDMA1_D0_X_COUNT()         bfin_read16(MDMA1_D0_X_COUNT)
-#define bfin_write_MDMA1_D0_X_COUNT(val)     bfin_write16(MDMA1_D0_X_COUNT,val)
-#define bfin_read_MDMA1_D0_Y_COUNT()         bfin_read16(MDMA1_D0_Y_COUNT)
-#define bfin_write_MDMA1_D0_Y_COUNT(val)     bfin_write16(MDMA1_D0_Y_COUNT,val)
-#define bfin_read_MDMA1_D0_X_MODIFY()        bfin_read16(MDMA1_D0_X_MODIFY)
-#define bfin_write_MDMA1_D0_X_MODIFY(val)    bfin_write16(MDMA1_D0_X_MODIFY,val)
-#define bfin_read_MDMA1_D0_Y_MODIFY()        bfin_read16(MDMA1_D0_Y_MODIFY)
-#define bfin_write_MDMA1_D0_Y_MODIFY(val)    bfin_write16(MDMA1_D0_Y_MODIFY,val)
-#define bfin_read_MDMA1_D0_CURR_DESC_PTR()   bfin_read32(MDMA1_D0_CURR_DESC_PTR)
-#define bfin_write_MDMA1_D0_CURR_DESC_PTR(val) bfin_write32(MDMA1_D0_CURR_DESC_PTR,val)
-#define bfin_read_MDMA1_D0_CURR_ADDR()       bfin_read32(MDMA1_D0_CURR_ADDR)
-#define bfin_write_MDMA1_D0_CURR_ADDR(val)   bfin_write32(MDMA1_D0_CURR_ADDR,val)
-#define bfin_read_MDMA1_D0_CURR_X_COUNT()    bfin_read16(MDMA1_D0_CURR_X_COUNT)
-#define bfin_write_MDMA1_D0_CURR_X_COUNT(val) bfin_write16(MDMA1_D0_CURR_X_COUNT,val)
-#define bfin_read_MDMA1_D0_CURR_Y_COUNT()    bfin_read16(MDMA1_D0_CURR_Y_COUNT)
-#define bfin_write_MDMA1_D0_CURR_Y_COUNT(val) bfin_write16(MDMA1_D0_CURR_Y_COUNT,val)
-#define bfin_read_MDMA1_D0_IRQ_STATUS()      bfin_read16(MDMA1_D0_IRQ_STATUS)
-#define bfin_write_MDMA1_D0_IRQ_STATUS(val)  bfin_write16(MDMA1_D0_IRQ_STATUS,val)
-#define bfin_read_MDMA1_D0_PERIPHERAL_MAP()  bfin_read16(MDMA1_D0_PERIPHERAL_MAP)
-#define bfin_write_MDMA1_D0_PERIPHERAL_MAP(val) bfin_write16(MDMA1_D0_PERIPHERAL_MAP,val)
-#define bfin_read_MDMA1_S0_CONFIG()          bfin_read16(MDMA1_S0_CONFIG)
-#define bfin_write_MDMA1_S0_CONFIG(val)      bfin_write16(MDMA1_S0_CONFIG,val)
-#define bfin_read_MDMA1_S0_NEXT_DESC_PTR()   bfin_read32(MDMA1_S0_NEXT_DESC_PTR)
-#define bfin_write_MDMA1_S0_NEXT_DESC_PTR(val) bfin_write32(MDMA1_S0_NEXT_DESC_PTR,val)
-#define bfin_read_MDMA1_S0_START_ADDR()      bfin_read32(MDMA1_S0_START_ADDR)
-#define bfin_write_MDMA1_S0_START_ADDR(val)  bfin_write32(MDMA1_S0_START_ADDR,val)
-#define bfin_read_MDMA1_S0_X_COUNT()         bfin_read16(MDMA1_S0_X_COUNT)
-#define bfin_write_MDMA1_S0_X_COUNT(val)     bfin_write16(MDMA1_S0_X_COUNT,val)
-#define bfin_read_MDMA1_S0_Y_COUNT()         bfin_read16(MDMA1_S0_Y_COUNT)
-#define bfin_write_MDMA1_S0_Y_COUNT(val)     bfin_write16(MDMA1_S0_Y_COUNT,val)
-#define bfin_read_MDMA1_S0_X_MODIFY()        bfin_read16(MDMA1_S0_X_MODIFY)
-#define bfin_write_MDMA1_S0_X_MODIFY(val)    bfin_write16(MDMA1_S0_X_MODIFY,val)
-#define bfin_read_MDMA1_S0_Y_MODIFY()        bfin_read16(MDMA1_S0_Y_MODIFY)
-#define bfin_write_MDMA1_S0_Y_MODIFY(val)    bfin_write16(MDMA1_S0_Y_MODIFY,val)
-#define bfin_read_MDMA1_S0_CURR_DESC_PTR()   bfin_read32(MDMA1_S0_CURR_DESC_PTR)
-#define bfin_write_MDMA1_S0_CURR_DESC_PTR(val) bfin_write32(MDMA1_S0_CURR_DESC_PTR,val)
-#define bfin_read_MDMA1_S0_CURR_ADDR()       bfin_read32(MDMA1_S0_CURR_ADDR)
-#define bfin_write_MDMA1_S0_CURR_ADDR(val)   bfin_write32(MDMA1_S0_CURR_ADDR,val)
-#define bfin_read_MDMA1_S0_CURR_X_COUNT()    bfin_read16(MDMA1_S0_CURR_X_COUNT)
-#define bfin_write_MDMA1_S0_CURR_X_COUNT(val) bfin_write16(MDMA1_S0_CURR_X_COUNT,val)
-#define bfin_read_MDMA1_S0_CURR_Y_COUNT()    bfin_read16(MDMA1_S0_CURR_Y_COUNT)
-#define bfin_write_MDMA1_S0_CURR_Y_COUNT(val) bfin_write16(MDMA1_S0_CURR_Y_COUNT,val)
-#define bfin_read_MDMA1_S0_IRQ_STATUS()      bfin_read16(MDMA1_S0_IRQ_STATUS)
-#define bfin_write_MDMA1_S0_IRQ_STATUS(val)  bfin_write16(MDMA1_S0_IRQ_STATUS,val)
-#define bfin_read_MDMA1_S0_PERIPHERAL_MAP()  bfin_read16(MDMA1_S0_PERIPHERAL_MAP)
-#define bfin_write_MDMA1_S0_PERIPHERAL_MAP(val) bfin_write16(MDMA1_S0_PERIPHERAL_MAP,val)
-#define bfin_read_MDMA1_D1_CONFIG()          bfin_read16(MDMA1_D1_CONFIG)
-#define bfin_write_MDMA1_D1_CONFIG(val)      bfin_write16(MDMA1_D1_CONFIG,val)
-#define bfin_read_MDMA1_D1_NEXT_DESC_PTR()   bfin_read32(MDMA1_D1_NEXT_DESC_PTR)
-#define bfin_write_MDMA1_D1_NEXT_DESC_PTR(val) bfin_write32(MDMA1_D1_NEXT_DESC_PTR,val)
-#define bfin_read_MDMA1_D1_START_ADDR()      bfin_read32(MDMA1_D1_START_ADDR)
-#define bfin_write_MDMA1_D1_START_ADDR(val)  bfin_write32(MDMA1_D1_START_ADDR,val)
-#define bfin_read_MDMA1_D1_X_COUNT()         bfin_read16(MDMA1_D1_X_COUNT)
-#define bfin_write_MDMA1_D1_X_COUNT(val)     bfin_write16(MDMA1_D1_X_COUNT,val)
-#define bfin_read_MDMA1_D1_Y_COUNT()         bfin_read16(MDMA1_D1_Y_COUNT)
-#define bfin_write_MDMA1_D1_Y_COUNT(val)     bfin_write16(MDMA1_D1_Y_COUNT,val)
-#define bfin_read_MDMA1_D1_X_MODIFY()        bfin_read16(MDMA1_D1_X_MODIFY)
-#define bfin_write_MDMA1_D1_X_MODIFY(val)    bfin_write16(MDMA1_D1_X_MODIFY,val)
-#define bfin_read_MDMA1_D1_Y_MODIFY()        bfin_read16(MDMA1_D1_Y_MODIFY)
-#define bfin_write_MDMA1_D1_Y_MODIFY(val)    bfin_write16(MDMA1_D1_Y_MODIFY,val)
-#define bfin_read_MDMA1_D1_CURR_DESC_PTR()   bfin_read32(MDMA1_D1_CURR_DESC_PTR)
-#define bfin_write_MDMA1_D1_CURR_DESC_PTR(val) bfin_write32(MDMA1_D1_CURR_DESC_PTR,val)
-#define bfin_read_MDMA1_D1_CURR_ADDR()       bfin_read32(MDMA1_D1_CURR_ADDR)
-#define bfin_write_MDMA1_D1_CURR_ADDR(val)   bfin_write32(MDMA1_D1_CURR_ADDR,val)
-#define bfin_read_MDMA1_D1_CURR_X_COUNT()    bfin_read16(MDMA1_D1_CURR_X_COUNT)
-#define bfin_write_MDMA1_D1_CURR_X_COUNT(val) bfin_write16(MDMA1_D1_CURR_X_COUNT,val)
-#define bfin_read_MDMA1_D1_CURR_Y_COUNT()    bfin_read16(MDMA1_D1_CURR_Y_COUNT)
-#define bfin_write_MDMA1_D1_CURR_Y_COUNT(val) bfin_write16(MDMA1_D1_CURR_Y_COUNT,val)
-#define bfin_read_MDMA1_D1_IRQ_STATUS()      bfin_read16(MDMA1_D1_IRQ_STATUS)
-#define bfin_write_MDMA1_D1_IRQ_STATUS(val)  bfin_write16(MDMA1_D1_IRQ_STATUS,val)
-#define bfin_read_MDMA1_D1_PERIPHERAL_MAP()  bfin_read16(MDMA1_D1_PERIPHERAL_MAP)
-#define bfin_write_MDMA1_D1_PERIPHERAL_MAP(val) bfin_write16(MDMA1_D1_PERIPHERAL_MAP,val)
-#define bfin_read_MDMA1_S1_CONFIG()          bfin_read16(MDMA1_S1_CONFIG)
-#define bfin_write_MDMA1_S1_CONFIG(val)      bfin_write16(MDMA1_S1_CONFIG,val)
-#define bfin_read_MDMA1_S1_NEXT_DESC_PTR()   bfin_read32(MDMA1_S1_NEXT_DESC_PTR)
-#define bfin_write_MDMA1_S1_NEXT_DESC_PTR(val) bfin_write32(MDMA1_S1_NEXT_DESC_PTR,val)
-#define bfin_read_MDMA1_S1_START_ADDR()      bfin_read32(MDMA1_S1_START_ADDR)
-#define bfin_write_MDMA1_S1_START_ADDR(val)  bfin_write32(MDMA1_S1_START_ADDR,val)
-#define bfin_read_MDMA1_S1_X_COUNT()         bfin_read16(MDMA1_S1_X_COUNT)
-#define bfin_write_MDMA1_S1_X_COUNT(val)     bfin_write16(MDMA1_S1_X_COUNT,val)
-#define bfin_read_MDMA1_S1_Y_COUNT()         bfin_read16(MDMA1_S1_Y_COUNT)
-#define bfin_write_MDMA1_S1_Y_COUNT(val)     bfin_write16(MDMA1_S1_Y_COUNT,val)
-#define bfin_read_MDMA1_S1_X_MODIFY()        bfin_read16(MDMA1_S1_X_MODIFY)
-#define bfin_write_MDMA1_S1_X_MODIFY(val)    bfin_write16(MDMA1_S1_X_MODIFY,val)
-#define bfin_read_MDMA1_S1_Y_MODIFY()        bfin_read16(MDMA1_S1_Y_MODIFY)
-#define bfin_write_MDMA1_S1_Y_MODIFY(val)    bfin_write16(MDMA1_S1_Y_MODIFY,val)
-#define bfin_read_MDMA1_S1_CURR_DESC_PTR()   bfin_read32(MDMA1_S1_CURR_DESC_PTR)
-#define bfin_write_MDMA1_S1_CURR_DESC_PTR(val) bfin_write32(MDMA1_S1_CURR_DESC_PTR,val)
-#define bfin_read_MDMA1_S1_CURR_ADDR()       bfin_read32(MDMA1_S1_CURR_ADDR)
-#define bfin_write_MDMA1_S1_CURR_ADDR(val)   bfin_write32(MDMA1_S1_CURR_ADDR,val)
-#define bfin_read_MDMA1_S1_CURR_X_COUNT()    bfin_read16(MDMA1_S1_CURR_X_COUNT)
-#define bfin_write_MDMA1_S1_CURR_X_COUNT(val) bfin_write16(MDMA1_S1_CURR_X_COUNT,val)
-#define bfin_read_MDMA1_S1_CURR_Y_COUNT()    bfin_read16(MDMA1_S1_CURR_Y_COUNT)
-#define bfin_write_MDMA1_S1_CURR_Y_COUNT(val) bfin_write16(MDMA1_S1_CURR_Y_COUNT,val)
-#define bfin_read_MDMA1_S1_IRQ_STATUS()      bfin_read16(MDMA1_S1_IRQ_STATUS)
-#define bfin_write_MDMA1_S1_IRQ_STATUS(val)  bfin_write16(MDMA1_S1_IRQ_STATUS,val)
-#define bfin_read_MDMA1_S1_PERIPHERAL_MAP()  bfin_read16(MDMA1_S1_PERIPHERAL_MAP)
-#define bfin_write_MDMA1_S1_PERIPHERAL_MAP(val) bfin_write16(MDMA1_S1_PERIPHERAL_MAP,val)
+#define bfin_read_MDMA_D2_CONFIG()          bfin_read16(MDMA_D2_CONFIG)
+#define bfin_write_MDMA_D2_CONFIG(val)      bfin_write16(MDMA_D2_CONFIG,val)
+#define bfin_read_MDMA_D2_NEXT_DESC_PTR()   bfin_read32(MDMA_D2_NEXT_DESC_PTR)
+#define bfin_write_MDMA_D2_NEXT_DESC_PTR(val) bfin_write32(MDMA_D2_NEXT_DESC_PTR,val)
+#define bfin_read_MDMA_D2_START_ADDR()      bfin_read32(MDMA_D2_START_ADDR)
+#define bfin_write_MDMA_D2_START_ADDR(val)  bfin_write32(MDMA_D2_START_ADDR,val)
+#define bfin_read_MDMA_D2_X_COUNT()         bfin_read16(MDMA_D2_X_COUNT)
+#define bfin_write_MDMA_D2_X_COUNT(val)     bfin_write16(MDMA_D2_X_COUNT,val)
+#define bfin_read_MDMA_D2_Y_COUNT()         bfin_read16(MDMA_D2_Y_COUNT)
+#define bfin_write_MDMA_D2_Y_COUNT(val)     bfin_write16(MDMA_D2_Y_COUNT,val)
+#define bfin_read_MDMA_D2_X_MODIFY()        bfin_read16(MDMA_D2_X_MODIFY)
+#define bfin_write_MDMA_D2_X_MODIFY(val)    bfin_write16(MDMA_D2_X_MODIFY,val)
+#define bfin_read_MDMA_D2_Y_MODIFY()        bfin_read16(MDMA_D2_Y_MODIFY)
+#define bfin_write_MDMA_D2_Y_MODIFY(val)    bfin_write16(MDMA_D2_Y_MODIFY,val)
+#define bfin_read_MDMA_D2_CURR_DESC_PTR()   bfin_read32(MDMA_D2_CURR_DESC_PTR)
+#define bfin_write_MDMA_D2_CURR_DESC_PTR(val) bfin_write32(MDMA_D2_CURR_DESC_PTR,val)
+#define bfin_read_MDMA_D2_CURR_ADDR()       bfin_read32(MDMA_D2_CURR_ADDR)
+#define bfin_write_MDMA_D2_CURR_ADDR(val)   bfin_write32(MDMA_D2_CURR_ADDR,val)
+#define bfin_read_MDMA_D2_CURR_X_COUNT()    bfin_read16(MDMA_D2_CURR_X_COUNT)
+#define bfin_write_MDMA_D2_CURR_X_COUNT(val) bfin_write16(MDMA_D2_CURR_X_COUNT,val)
+#define bfin_read_MDMA_D2_CURR_Y_COUNT()    bfin_read16(MDMA_D2_CURR_Y_COUNT)
+#define bfin_write_MDMA_D2_CURR_Y_COUNT(val) bfin_write16(MDMA_D2_CURR_Y_COUNT,val)
+#define bfin_read_MDMA_D2_IRQ_STATUS()      bfin_read16(MDMA_D2_IRQ_STATUS)
+#define bfin_write_MDMA_D2_IRQ_STATUS(val)  bfin_write16(MDMA_D2_IRQ_STATUS,val)
+#define bfin_read_MDMA_D2_PERIPHERAL_MAP()  bfin_read16(MDMA_D2_PERIPHERAL_MAP)
+#define bfin_write_MDMA_D2_PERIPHERAL_MAP(val) bfin_write16(MDMA_D2_PERIPHERAL_MAP,val)
+#define bfin_read_MDMA_S2_CONFIG()          bfin_read16(MDMA_S2_CONFIG)
+#define bfin_write_MDMA_S2_CONFIG(val)      bfin_write16(MDMA_S2_CONFIG,val)
+#define bfin_read_MDMA_S2_NEXT_DESC_PTR()   bfin_read32(MDMA_S2_NEXT_DESC_PTR)
+#define bfin_write_MDMA_S2_NEXT_DESC_PTR(val) bfin_write32(MDMA_S2_NEXT_DESC_PTR,val)
+#define bfin_read_MDMA_S2_START_ADDR()      bfin_read32(MDMA_S2_START_ADDR)
+#define bfin_write_MDMA_S2_START_ADDR(val)  bfin_write32(MDMA_S2_START_ADDR,val)
+#define bfin_read_MDMA_S2_X_COUNT()         bfin_read16(MDMA_S2_X_COUNT)
+#define bfin_write_MDMA_S2_X_COUNT(val)     bfin_write16(MDMA_S2_X_COUNT,val)
+#define bfin_read_MDMA_S2_Y_COUNT()         bfin_read16(MDMA_S2_Y_COUNT)
+#define bfin_write_MDMA_S2_Y_COUNT(val)     bfin_write16(MDMA_S2_Y_COUNT,val)
+#define bfin_read_MDMA_S2_X_MODIFY()        bfin_read16(MDMA_S2_X_MODIFY)
+#define bfin_write_MDMA_S2_X_MODIFY(val)    bfin_write16(MDMA_S2_X_MODIFY,val)
+#define bfin_read_MDMA_S2_Y_MODIFY()        bfin_read16(MDMA_S2_Y_MODIFY)
+#define bfin_write_MDMA_S2_Y_MODIFY(val)    bfin_write16(MDMA_S2_Y_MODIFY,val)
+#define bfin_read_MDMA_S2_CURR_DESC_PTR()   bfin_read32(MDMA_S2_CURR_DESC_PTR)
+#define bfin_write_MDMA_S2_CURR_DESC_PTR(val) bfin_write32(MDMA_S2_CURR_DESC_PTR,val)
+#define bfin_read_MDMA_S2_CURR_ADDR()       bfin_read32(MDMA_S2_CURR_ADDR)
+#define bfin_write_MDMA_S2_CURR_ADDR(val)   bfin_write32(MDMA_S2_CURR_ADDR,val)
+#define bfin_read_MDMA_S2_CURR_X_COUNT()    bfin_read16(MDMA_S2_CURR_X_COUNT)
+#define bfin_write_MDMA_S2_CURR_X_COUNT(val) bfin_write16(MDMA_S2_CURR_X_COUNT,val)
+#define bfin_read_MDMA_S2_CURR_Y_COUNT()    bfin_read16(MDMA_S2_CURR_Y_COUNT)
+#define bfin_write_MDMA_S2_CURR_Y_COUNT(val) bfin_write16(MDMA_S2_CURR_Y_COUNT,val)
+#define bfin_read_MDMA_S2_IRQ_STATUS()      bfin_read16(MDMA_S2_IRQ_STATUS)
+#define bfin_write_MDMA_S2_IRQ_STATUS(val)  bfin_write16(MDMA_S2_IRQ_STATUS,val)
+#define bfin_read_MDMA_S2_PERIPHERAL_MAP()  bfin_read16(MDMA_S2_PERIPHERAL_MAP)
+#define bfin_write_MDMA_S2_PERIPHERAL_MAP(val) bfin_write16(MDMA_S2_PERIPHERAL_MAP,val)
+#define bfin_read_MDMA_D3_CONFIG()          bfin_read16(MDMA_D3_CONFIG)
+#define bfin_write_MDMA_D3_CONFIG(val)      bfin_write16(MDMA_D3_CONFIG,val)
+#define bfin_read_MDMA_D3_NEXT_DESC_PTR()   bfin_read32(MDMA_D3_NEXT_DESC_PTR)
+#define bfin_write_MDMA_D3_NEXT_DESC_PTR(val) bfin_write32(MDMA_D3_NEXT_DESC_PTR,val)
+#define bfin_read_MDMA_D3_START_ADDR()      bfin_read32(MDMA_D3_START_ADDR)
+#define bfin_write_MDMA_D3_START_ADDR(val)  bfin_write32(MDMA_D3_START_ADDR,val)
+#define bfin_read_MDMA_D3_X_COUNT()         bfin_read16(MDMA_D3_X_COUNT)
+#define bfin_write_MDMA_D3_X_COUNT(val)     bfin_write16(MDMA_D3_X_COUNT,val)
+#define bfin_read_MDMA_D3_Y_COUNT()         bfin_read16(MDMA_D3_Y_COUNT)
+#define bfin_write_MDMA_D3_Y_COUNT(val)     bfin_write16(MDMA_D3_Y_COUNT,val)
+#define bfin_read_MDMA_D3_X_MODIFY()        bfin_read16(MDMA_D3_X_MODIFY)
+#define bfin_write_MDMA_D3_X_MODIFY(val)    bfin_write16(MDMA_D3_X_MODIFY,val)
+#define bfin_read_MDMA_D3_Y_MODIFY()        bfin_read16(MDMA_D3_Y_MODIFY)
+#define bfin_write_MDMA_D3_Y_MODIFY(val)    bfin_write16(MDMA_D3_Y_MODIFY,val)
+#define bfin_read_MDMA_D3_CURR_DESC_PTR()   bfin_read32(MDMA_D3_CURR_DESC_PTR)
+#define bfin_write_MDMA_D3_CURR_DESC_PTR(val) bfin_write32(MDMA_D3_CURR_DESC_PTR,val)
+#define bfin_read_MDMA_D3_CURR_ADDR()       bfin_read32(MDMA_D3_CURR_ADDR)
+#define bfin_write_MDMA_D3_CURR_ADDR(val)   bfin_write32(MDMA_D3_CURR_ADDR,val)
+#define bfin_read_MDMA_D3_CURR_X_COUNT()    bfin_read16(MDMA_D3_CURR_X_COUNT)
+#define bfin_write_MDMA_D3_CURR_X_COUNT(val) bfin_write16(MDMA_D3_CURR_X_COUNT,val)
+#define bfin_read_MDMA_D3_CURR_Y_COUNT()    bfin_read16(MDMA_D3_CURR_Y_COUNT)
+#define bfin_write_MDMA_D3_CURR_Y_COUNT(val) bfin_write16(MDMA_D3_CURR_Y_COUNT,val)
+#define bfin_read_MDMA_D3_IRQ_STATUS()      bfin_read16(MDMA_D3_IRQ_STATUS)
+#define bfin_write_MDMA_D3_IRQ_STATUS(val)  bfin_write16(MDMA_D3_IRQ_STATUS,val)
+#define bfin_read_MDMA_D3_PERIPHERAL_MAP()  bfin_read16(MDMA_D3_PERIPHERAL_MAP)
+#define bfin_write_MDMA_D3_PERIPHERAL_MAP(val) bfin_write16(MDMA_D3_PERIPHERAL_MAP,val)
+#define bfin_read_MDMA_S3_CONFIG()          bfin_read16(MDMA_S3_CONFIG)
+#define bfin_write_MDMA_S3_CONFIG(val)      bfin_write16(MDMA_S3_CONFIG,val)
+#define bfin_read_MDMA_S3_NEXT_DESC_PTR()   bfin_read32(MDMA_S3_NEXT_DESC_PTR)
+#define bfin_write_MDMA_S3_NEXT_DESC_PTR(val) bfin_write32(MDMA_S3_NEXT_DESC_PTR,val)
+#define bfin_read_MDMA_S3_START_ADDR()      bfin_read32(MDMA_S3_START_ADDR)
+#define bfin_write_MDMA_S3_START_ADDR(val)  bfin_write32(MDMA_S3_START_ADDR,val)
+#define bfin_read_MDMA_S3_X_COUNT()         bfin_read16(MDMA_S3_X_COUNT)
+#define bfin_write_MDMA_S3_X_COUNT(val)     bfin_write16(MDMA_S3_X_COUNT,val)
+#define bfin_read_MDMA_S3_Y_COUNT()         bfin_read16(MDMA_S3_Y_COUNT)
+#define bfin_write_MDMA_S3_Y_COUNT(val)     bfin_write16(MDMA_S3_Y_COUNT,val)
+#define bfin_read_MDMA_S3_X_MODIFY()        bfin_read16(MDMA_S3_X_MODIFY)
+#define bfin_write_MDMA_S3_X_MODIFY(val)    bfin_write16(MDMA_S3_X_MODIFY,val)
+#define bfin_read_MDMA_S3_Y_MODIFY()        bfin_read16(MDMA_S3_Y_MODIFY)
+#define bfin_write_MDMA_S3_Y_MODIFY(val)    bfin_write16(MDMA_S3_Y_MODIFY,val)
+#define bfin_read_MDMA_S3_CURR_DESC_PTR()   bfin_read32(MDMA_S3_CURR_DESC_PTR)
+#define bfin_write_MDMA_S3_CURR_DESC_PTR(val) bfin_write32(MDMA_S3_CURR_DESC_PTR,val)
+#define bfin_read_MDMA_S3_CURR_ADDR()       bfin_read32(MDMA_S3_CURR_ADDR)
+#define bfin_write_MDMA_S3_CURR_ADDR(val)   bfin_write32(MDMA_S3_CURR_ADDR,val)
+#define bfin_read_MDMA_S3_CURR_X_COUNT()    bfin_read16(MDMA_S3_CURR_X_COUNT)
+#define bfin_write_MDMA_S3_CURR_X_COUNT(val) bfin_write16(MDMA_S3_CURR_X_COUNT,val)
+#define bfin_read_MDMA_S3_CURR_Y_COUNT()    bfin_read16(MDMA_S3_CURR_Y_COUNT)
+#define bfin_write_MDMA_S3_CURR_Y_COUNT(val) bfin_write16(MDMA_S3_CURR_Y_COUNT,val)
+#define bfin_read_MDMA_S3_IRQ_STATUS()      bfin_read16(MDMA_S3_IRQ_STATUS)
+#define bfin_write_MDMA_S3_IRQ_STATUS(val)  bfin_write16(MDMA_S3_IRQ_STATUS,val)
+#define bfin_read_MDMA_S3_PERIPHERAL_MAP()  bfin_read16(MDMA_S3_PERIPHERAL_MAP)
+#define bfin_write_MDMA_S3_PERIPHERAL_MAP(val) bfin_write16(MDMA_S3_PERIPHERAL_MAP,val)
 /* DMA2 Controller registers (0xFFC0 0C00-0xFFC0 0DFF) */
 #define bfin_read_DMA2_0_CONFIG()            bfin_read16(DMA2_0_CONFIG)
 #define bfin_write_DMA2_0_CONFIG(val)        bfin_write16(DMA2_0_CONFIG,val)
@@ -1263,110 +1255,110 @@
 #define bfin_read_DMA2_11_PERIPHERAL_MAP()   bfin_read16(DMA2_11_PERIPHERAL_MAP)
 #define bfin_write_DMA2_11_PERIPHERAL_MAP(val) bfin_write16(DMA2_11_PERIPHERAL_MAP,val)
 /* Memory DMA2 Controller registers (0xFFC0 0E80-0xFFC0 0FFF) */
-#define bfin_read_MDMA2_D0_CONFIG()          bfin_read16(MDMA2_D0_CONFIG)
-#define bfin_write_MDMA2_D0_CONFIG(val)      bfin_write16(MDMA2_D0_CONFIG,val)
-#define bfin_read_MDMA2_D0_NEXT_DESC_PTR()   bfin_read32(MDMA2_D0_NEXT_DESC_PTR)
-#define bfin_write_MDMA2_D0_NEXT_DESC_PTR(val) bfin_write32(MDMA2_D0_NEXT_DESC_PTR,val)
-#define bfin_read_MDMA2_D0_START_ADDR()      bfin_read32(MDMA2_D0_START_ADDR)
-#define bfin_write_MDMA2_D0_START_ADDR(val)  bfin_write32(MDMA2_D0_START_ADDR,val)
-#define bfin_read_MDMA2_D0_X_COUNT()         bfin_read16(MDMA2_D0_X_COUNT)
-#define bfin_write_MDMA2_D0_X_COUNT(val)     bfin_write16(MDMA2_D0_X_COUNT,val)
-#define bfin_read_MDMA2_D0_Y_COUNT()         bfin_read16(MDMA2_D0_Y_COUNT)
-#define bfin_write_MDMA2_D0_Y_COUNT(val)     bfin_write16(MDMA2_D0_Y_COUNT,val)
-#define bfin_read_MDMA2_D0_X_MODIFY()        bfin_read16(MDMA2_D0_X_MODIFY)
-#define bfin_write_MDMA2_D0_X_MODIFY(val)    bfin_write16(MDMA2_D0_X_MODIFY,val)
-#define bfin_read_MDMA2_D0_Y_MODIFY()        bfin_read16(MDMA2_D0_Y_MODIFY)
-#define bfin_write_MDMA2_D0_Y_MODIFY(val)    bfin_write16(MDMA2_D0_Y_MODIFY,val)
-#define bfin_read_MDMA2_D0_CURR_DESC_PTR()   bfin_read32(MDMA2_D0_CURR_DESC_PTR)
-#define bfin_write_MDMA2_D0_CURR_DESC_PTR(val) bfin_write32(MDMA2_D0_CURR_DESC_PTR,val)
-#define bfin_read_MDMA2_D0_CURR_ADDR()       bfin_read32(MDMA2_D0_CURR_ADDR)
-#define bfin_write_MDMA2_D0_CURR_ADDR(val)   bfin_write32(MDMA2_D0_CURR_ADDR,val)
-#define bfin_read_MDMA2_D0_CURR_X_COUNT()    bfin_read16(MDMA2_D0_CURR_X_COUNT)
-#define bfin_write_MDMA2_D0_CURR_X_COUNT(val) bfin_write16(MDMA2_D0_CURR_X_COUNT,val)
-#define bfin_read_MDMA2_D0_CURR_Y_COUNT()    bfin_read16(MDMA2_D0_CURR_Y_COUNT)
-#define bfin_write_MDMA2_D0_CURR_Y_COUNT(val) bfin_write16(MDMA2_D0_CURR_Y_COUNT,val)
-#define bfin_read_MDMA2_D0_IRQ_STATUS()      bfin_read16(MDMA2_D0_IRQ_STATUS)
-#define bfin_write_MDMA2_D0_IRQ_STATUS(val)  bfin_write16(MDMA2_D0_IRQ_STATUS,val)
-#define bfin_read_MDMA2_D0_PERIPHERAL_MAP()  bfin_read16(MDMA2_D0_PERIPHERAL_MAP)
-#define bfin_write_MDMA2_D0_PERIPHERAL_MAP(val) bfin_write16(MDMA2_D0_PERIPHERAL_MAP,val)
-#define bfin_read_MDMA2_S0_CONFIG()          bfin_read16(MDMA2_S0_CONFIG)
-#define bfin_write_MDMA2_S0_CONFIG(val)      bfin_write16(MDMA2_S0_CONFIG,val)
-#define bfin_read_MDMA2_S0_NEXT_DESC_PTR()   bfin_read32(MDMA2_S0_NEXT_DESC_PTR)
-#define bfin_write_MDMA2_S0_NEXT_DESC_PTR(val) bfin_write32(MDMA2_S0_NEXT_DESC_PTR,val)
-#define bfin_read_MDMA2_S0_START_ADDR()      bfin_read32(MDMA2_S0_START_ADDR)
-#define bfin_write_MDMA2_S0_START_ADDR(val)  bfin_write32(MDMA2_S0_START_ADDR,val)
-#define bfin_read_MDMA2_S0_X_COUNT()         bfin_read16(MDMA2_S0_X_COUNT)
-#define bfin_write_MDMA2_S0_X_COUNT(val)     bfin_write16(MDMA2_S0_X_COUNT,val)
-#define bfin_read_MDMA2_S0_Y_COUNT()         bfin_read16(MDMA2_S0_Y_COUNT)
-#define bfin_write_MDMA2_S0_Y_COUNT(val)     bfin_write16(MDMA2_S0_Y_COUNT,val)
-#define bfin_read_MDMA2_S0_X_MODIFY()        bfin_read16(MDMA2_S0_X_MODIFY)
-#define bfin_write_MDMA2_S0_X_MODIFY(val)    bfin_write16(MDMA2_S0_X_MODIFY,val)
-#define bfin_read_MDMA2_S0_Y_MODIFY()        bfin_read16(MDMA2_S0_Y_MODIFY)
-#define bfin_write_MDMA2_S0_Y_MODIFY(val)    bfin_write16(MDMA2_S0_Y_MODIFY,val)
-#define bfin_read_MDMA2_S0_CURR_DESC_PTR()   bfin_read32(MDMA2_S0_CURR_DESC_PTR)
-#define bfin_write_MDMA2_S0_CURR_DESC_PTR(val) bfin_write32(MDMA2_S0_CURR_DESC_PTR,val)
-#define bfin_read_MDMA2_S0_CURR_ADDR()       bfin_read32(MDMA2_S0_CURR_ADDR)
-#define bfin_write_MDMA2_S0_CURR_ADDR(val)   bfin_write32(MDMA2_S0_CURR_ADDR,val)
-#define bfin_read_MDMA2_S0_CURR_X_COUNT()    bfin_read16(MDMA2_S0_CURR_X_COUNT)
-#define bfin_write_MDMA2_S0_CURR_X_COUNT(val) bfin_write16(MDMA2_S0_CURR_X_COUNT,val)
-#define bfin_read_MDMA2_S0_CURR_Y_COUNT()    bfin_read16(MDMA2_S0_CURR_Y_COUNT)
-#define bfin_write_MDMA2_S0_CURR_Y_COUNT(val) bfin_write16(MDMA2_S0_CURR_Y_COUNT,val)
-#define bfin_read_MDMA2_S0_IRQ_STATUS()      bfin_read16(MDMA2_S0_IRQ_STATUS)
-#define bfin_write_MDMA2_S0_IRQ_STATUS(val)  bfin_write16(MDMA2_S0_IRQ_STATUS,val)
-#define bfin_read_MDMA2_S0_PERIPHERAL_MAP()  bfin_read16(MDMA2_S0_PERIPHERAL_MAP)
-#define bfin_write_MDMA2_S0_PERIPHERAL_MAP(val) bfin_write16(MDMA2_S0_PERIPHERAL_MAP,val)
-#define bfin_read_MDMA2_D1_CONFIG()          bfin_read16(MDMA2_D1_CONFIG)
-#define bfin_write_MDMA2_D1_CONFIG(val)      bfin_write16(MDMA2_D1_CONFIG,val)
-#define bfin_read_MDMA2_D1_NEXT_DESC_PTR()   bfin_read32(MDMA2_D1_NEXT_DESC_PTR)
-#define bfin_write_MDMA2_D1_NEXT_DESC_PTR(val) bfin_write32(MDMA2_D1_NEXT_DESC_PTR,val)
-#define bfin_read_MDMA2_D1_START_ADDR()      bfin_read32(MDMA2_D1_START_ADDR)
-#define bfin_write_MDMA2_D1_START_ADDR(val)  bfin_write32(MDMA2_D1_START_ADDR,val)
-#define bfin_read_MDMA2_D1_X_COUNT()         bfin_read16(MDMA2_D1_X_COUNT)
-#define bfin_write_MDMA2_D1_X_COUNT(val)     bfin_write16(MDMA2_D1_X_COUNT,val)
-#define bfin_read_MDMA2_D1_Y_COUNT()         bfin_read16(MDMA2_D1_Y_COUNT)
-#define bfin_write_MDMA2_D1_Y_COUNT(val)     bfin_write16(MDMA2_D1_Y_COUNT,val)
-#define bfin_read_MDMA2_D1_X_MODIFY()        bfin_read16(MDMA2_D1_X_MODIFY)
-#define bfin_write_MDMA2_D1_X_MODIFY(val)    bfin_write16(MDMA2_D1_X_MODIFY,val)
-#define bfin_read_MDMA2_D1_Y_MODIFY()        bfin_read16(MDMA2_D1_Y_MODIFY)
-#define bfin_write_MDMA2_D1_Y_MODIFY(val)    bfin_write16(MDMA2_D1_Y_MODIFY,val)
-#define bfin_read_MDMA2_D1_CURR_DESC_PTR()   bfin_read32(MDMA2_D1_CURR_DESC_PTR)
-#define bfin_write_MDMA2_D1_CURR_DESC_PTR(val) bfin_write32(MDMA2_D1_CURR_DESC_PTR,val)
-#define bfin_read_MDMA2_D1_CURR_ADDR()       bfin_read32(MDMA2_D1_CURR_ADDR)
-#define bfin_write_MDMA2_D1_CURR_ADDR(val)   bfin_write32(MDMA2_D1_CURR_ADDR,val)
-#define bfin_read_MDMA2_D1_CURR_X_COUNT()    bfin_read16(MDMA2_D1_CURR_X_COUNT)
-#define bfin_write_MDMA2_D1_CURR_X_COUNT(val) bfin_write16(MDMA2_D1_CURR_X_COUNT,val)
-#define bfin_read_MDMA2_D1_CURR_Y_COUNT()    bfin_read16(MDMA2_D1_CURR_Y_COUNT)
-#define bfin_write_MDMA2_D1_CURR_Y_COUNT(val) bfin_write16(MDMA2_D1_CURR_Y_COUNT,val)
-#define bfin_read_MDMA2_D1_IRQ_STATUS()      bfin_read16(MDMA2_D1_IRQ_STATUS)
-#define bfin_write_MDMA2_D1_IRQ_STATUS(val)  bfin_write16(MDMA2_D1_IRQ_STATUS,val)
-#define bfin_read_MDMA2_D1_PERIPHERAL_MAP()  bfin_read16(MDMA2_D1_PERIPHERAL_MAP)
-#define bfin_write_MDMA2_D1_PERIPHERAL_MAP(val) bfin_write16(MDMA2_D1_PERIPHERAL_MAP,val)
-#define bfin_read_MDMA2_S1_CONFIG()          bfin_read16(MDMA2_S1_CONFIG)
-#define bfin_write_MDMA2_S1_CONFIG(val)      bfin_write16(MDMA2_S1_CONFIG,val)
-#define bfin_read_MDMA2_S1_NEXT_DESC_PTR()   bfin_read32(MDMA2_S1_NEXT_DESC_PTR)
-#define bfin_write_MDMA2_S1_NEXT_DESC_PTR(val) bfin_write32(MDMA2_S1_NEXT_DESC_PTR,val)
-#define bfin_read_MDMA2_S1_START_ADDR()      bfin_read32(MDMA2_S1_START_ADDR)
-#define bfin_write_MDMA2_S1_START_ADDR(val)  bfin_write32(MDMA2_S1_START_ADDR,val)
-#define bfin_read_MDMA2_S1_X_COUNT()         bfin_read16(MDMA2_S1_X_COUNT)
-#define bfin_write_MDMA2_S1_X_COUNT(val)     bfin_write16(MDMA2_S1_X_COUNT,val)
-#define bfin_read_MDMA2_S1_Y_COUNT()         bfin_read16(MDMA2_S1_Y_COUNT)
-#define bfin_write_MDMA2_S1_Y_COUNT(val)     bfin_write16(MDMA2_S1_Y_COUNT,val)
-#define bfin_read_MDMA2_S1_X_MODIFY()        bfin_read16(MDMA2_S1_X_MODIFY)
-#define bfin_write_MDMA2_S1_X_MODIFY(val)    bfin_write16(MDMA2_S1_X_MODIFY,val)
-#define bfin_read_MDMA2_S1_Y_MODIFY()        bfin_read16(MDMA2_S1_Y_MODIFY)
-#define bfin_write_MDMA2_S1_Y_MODIFY(val)    bfin_write16(MDMA2_S1_Y_MODIFY,val)
-#define bfin_read_MDMA2_S1_CURR_DESC_PTR()   bfin_read32(MDMA2_S1_CURR_DESC_PTR)
-#define bfin_write_MDMA2_S1_CURR_DESC_PTR(val) bfin_write32(MDMA2_S1_CURR_DESC_PTR,val)
-#define bfin_read_MDMA2_S1_CURR_ADDR()       bfin_read32(MDMA2_S1_CURR_ADDR)
-#define bfin_write_MDMA2_S1_CURR_ADDR(val)   bfin_write32(MDMA2_S1_CURR_ADDR,val)
-#define bfin_read_MDMA2_S1_CURR_X_COUNT()    bfin_read16(MDMA2_S1_CURR_X_COUNT)
-#define bfin_write_MDMA2_S1_CURR_X_COUNT(val) bfin_write16(MDMA2_S1_CURR_X_COUNT,val)
-#define bfin_read_MDMA2_S1_CURR_Y_COUNT()    bfin_read16(MDMA2_S1_CURR_Y_COUNT)
-#define bfin_write_MDMA2_S1_CURR_Y_COUNT(val) bfin_write16(MDMA2_S1_CURR_Y_COUNT,val)
-#define bfin_read_MDMA2_S1_IRQ_STATUS()      bfin_read16(MDMA2_S1_IRQ_STATUS)
-#define bfin_write_MDMA2_S1_IRQ_STATUS(val)  bfin_write16(MDMA2_S1_IRQ_STATUS,val)
-#define bfin_read_MDMA2_S1_PERIPHERAL_MAP()  bfin_read16(MDMA2_S1_PERIPHERAL_MAP)
-#define bfin_write_MDMA2_S1_PERIPHERAL_MAP(val) bfin_write16(MDMA2_S1_PERIPHERAL_MAP,val)
+#define bfin_read_MDMA_D0_CONFIG()          bfin_read16(MDMA_D0_CONFIG)
+#define bfin_write_MDMA_D0_CONFIG(val)      bfin_write16(MDMA_D0_CONFIG,val)
+#define bfin_read_MDMA_D0_NEXT_DESC_PTR()   bfin_read32(MDMA_D0_NEXT_DESC_PTR)
+#define bfin_write_MDMA_D0_NEXT_DESC_PTR(val) bfin_write32(MDMA_D0_NEXT_DESC_PTR,val)
+#define bfin_read_MDMA_D0_START_ADDR()      bfin_read32(MDMA_D0_START_ADDR)
+#define bfin_write_MDMA_D0_START_ADDR(val)  bfin_write32(MDMA_D0_START_ADDR,val)
+#define bfin_read_MDMA_D0_X_COUNT()         bfin_read16(MDMA_D0_X_COUNT)
+#define bfin_write_MDMA_D0_X_COUNT(val)     bfin_write16(MDMA_D0_X_COUNT,val)
+#define bfin_read_MDMA_D0_Y_COUNT()         bfin_read16(MDMA_D0_Y_COUNT)
+#define bfin_write_MDMA_D0_Y_COUNT(val)     bfin_write16(MDMA_D0_Y_COUNT,val)
+#define bfin_read_MDMA_D0_X_MODIFY()        bfin_read16(MDMA_D0_X_MODIFY)
+#define bfin_write_MDMA_D0_X_MODIFY(val)    bfin_write16(MDMA_D0_X_MODIFY,val)
+#define bfin_read_MDMA_D0_Y_MODIFY()        bfin_read16(MDMA_D0_Y_MODIFY)
+#define bfin_write_MDMA_D0_Y_MODIFY(val)    bfin_write16(MDMA_D0_Y_MODIFY,val)
+#define bfin_read_MDMA_D0_CURR_DESC_PTR()   bfin_read32(MDMA_D0_CURR_DESC_PTR)
+#define bfin_write_MDMA_D0_CURR_DESC_PTR(val) bfin_write32(MDMA_D0_CURR_DESC_PTR,val)
+#define bfin_read_MDMA_D0_CURR_ADDR()       bfin_read32(MDMA_D0_CURR_ADDR)
+#define bfin_write_MDMA_D0_CURR_ADDR(val)   bfin_write32(MDMA_D0_CURR_ADDR,val)
+#define bfin_read_MDMA_D0_CURR_X_COUNT()    bfin_read16(MDMA_D0_CURR_X_COUNT)
+#define bfin_write_MDMA_D0_CURR_X_COUNT(val) bfin_write16(MDMA_D0_CURR_X_COUNT,val)
+#define bfin_read_MDMA_D0_CURR_Y_COUNT()    bfin_read16(MDMA_D0_CURR_Y_COUNT)
+#define bfin_write_MDMA_D0_CURR_Y_COUNT(val) bfin_write16(MDMA_D0_CURR_Y_COUNT,val)
+#define bfin_read_MDMA_D0_IRQ_STATUS()      bfin_read16(MDMA_D0_IRQ_STATUS)
+#define bfin_write_MDMA_D0_IRQ_STATUS(val)  bfin_write16(MDMA_D0_IRQ_STATUS,val)
+#define bfin_read_MDMA_D0_PERIPHERAL_MAP()  bfin_read16(MDMA_D0_PERIPHERAL_MAP)
+#define bfin_write_MDMA_D0_PERIPHERAL_MAP(val) bfin_write16(MDMA_D0_PERIPHERAL_MAP,val)
+#define bfin_read_MDMA_S0_CONFIG()          bfin_read16(MDMA_S0_CONFIG)
+#define bfin_write_MDMA_S0_CONFIG(val)      bfin_write16(MDMA_S0_CONFIG,val)
+#define bfin_read_MDMA_S0_NEXT_DESC_PTR()   bfin_read32(MDMA_S0_NEXT_DESC_PTR)
+#define bfin_write_MDMA_S0_NEXT_DESC_PTR(val) bfin_write32(MDMA_S0_NEXT_DESC_PTR,val)
+#define bfin_read_MDMA_S0_START_ADDR()      bfin_read32(MDMA_S0_START_ADDR)
+#define bfin_write_MDMA_S0_START_ADDR(val)  bfin_write32(MDMA_S0_START_ADDR,val)
+#define bfin_read_MDMA_S0_X_COUNT()         bfin_read16(MDMA_S0_X_COUNT)
+#define bfin_write_MDMA_S0_X_COUNT(val)     bfin_write16(MDMA_S0_X_COUNT,val)
+#define bfin_read_MDMA_S0_Y_COUNT()         bfin_read16(MDMA_S0_Y_COUNT)
+#define bfin_write_MDMA_S0_Y_COUNT(val)     bfin_write16(MDMA_S0_Y_COUNT,val)
+#define bfin_read_MDMA_S0_X_MODIFY()        bfin_read16(MDMA_S0_X_MODIFY)
+#define bfin_write_MDMA_S0_X_MODIFY(val)    bfin_write16(MDMA_S0_X_MODIFY,val)
+#define bfin_read_MDMA_S0_Y_MODIFY()        bfin_read16(MDMA_S0_Y_MODIFY)
+#define bfin_write_MDMA_S0_Y_MODIFY(val)    bfin_write16(MDMA_S0_Y_MODIFY,val)
+#define bfin_read_MDMA_S0_CURR_DESC_PTR()   bfin_read32(MDMA_S0_CURR_DESC_PTR)
+#define bfin_write_MDMA_S0_CURR_DESC_PTR(val) bfin_write32(MDMA_S0_CURR_DESC_PTR,val)
+#define bfin_read_MDMA_S0_CURR_ADDR()       bfin_read32(MDMA_S0_CURR_ADDR)
+#define bfin_write_MDMA_S0_CURR_ADDR(val)   bfin_write32(MDMA_S0_CURR_ADDR,val)
+#define bfin_read_MDMA_S0_CURR_X_COUNT()    bfin_read16(MDMA_S0_CURR_X_COUNT)
+#define bfin_write_MDMA_S0_CURR_X_COUNT(val) bfin_write16(MDMA_S0_CURR_X_COUNT,val)
+#define bfin_read_MDMA_S0_CURR_Y_COUNT()    bfin_read16(MDMA_S0_CURR_Y_COUNT)
+#define bfin_write_MDMA_S0_CURR_Y_COUNT(val) bfin_write16(MDMA_S0_CURR_Y_COUNT,val)
+#define bfin_read_MDMA_S0_IRQ_STATUS()      bfin_read16(MDMA_S0_IRQ_STATUS)
+#define bfin_write_MDMA_S0_IRQ_STATUS(val)  bfin_write16(MDMA_S0_IRQ_STATUS,val)
+#define bfin_read_MDMA_S0_PERIPHERAL_MAP()  bfin_read16(MDMA_S0_PERIPHERAL_MAP)
+#define bfin_write_MDMA_S0_PERIPHERAL_MAP(val) bfin_write16(MDMA_S0_PERIPHERAL_MAP,val)
+#define bfin_read_MDMA_D1_CONFIG()          bfin_read16(MDMA_D1_CONFIG)
+#define bfin_write_MDMA_D1_CONFIG(val)      bfin_write16(MDMA_D1_CONFIG,val)
+#define bfin_read_MDMA_D1_NEXT_DESC_PTR()   bfin_read32(MDMA_D1_NEXT_DESC_PTR)
+#define bfin_write_MDMA_D1_NEXT_DESC_PTR(val) bfin_write32(MDMA_D1_NEXT_DESC_PTR,val)
+#define bfin_read_MDMA_D1_START_ADDR()      bfin_read32(MDMA_D1_START_ADDR)
+#define bfin_write_MDMA_D1_START_ADDR(val)  bfin_write32(MDMA_D1_START_ADDR,val)
+#define bfin_read_MDMA_D1_X_COUNT()         bfin_read16(MDMA_D1_X_COUNT)
+#define bfin_write_MDMA_D1_X_COUNT(val)     bfin_write16(MDMA_D1_X_COUNT,val)
+#define bfin_read_MDMA_D1_Y_COUNT()         bfin_read16(MDMA_D1_Y_COUNT)
+#define bfin_write_MDMA_D1_Y_COUNT(val)     bfin_write16(MDMA_D1_Y_COUNT,val)
+#define bfin_read_MDMA_D1_X_MODIFY()        bfin_read16(MDMA_D1_X_MODIFY)
+#define bfin_write_MDMA_D1_X_MODIFY(val)    bfin_write16(MDMA_D1_X_MODIFY,val)
+#define bfin_read_MDMA_D1_Y_MODIFY()        bfin_read16(MDMA_D1_Y_MODIFY)
+#define bfin_write_MDMA_D1_Y_MODIFY(val)    bfin_write16(MDMA_D1_Y_MODIFY,val)
+#define bfin_read_MDMA_D1_CURR_DESC_PTR()   bfin_read32(MDMA_D1_CURR_DESC_PTR)
+#define bfin_write_MDMA_D1_CURR_DESC_PTR(val) bfin_write32(MDMA_D1_CURR_DESC_PTR,val)
+#define bfin_read_MDMA_D1_CURR_ADDR()       bfin_read32(MDMA_D1_CURR_ADDR)
+#define bfin_write_MDMA_D1_CURR_ADDR(val)   bfin_write32(MDMA_D1_CURR_ADDR,val)
+#define bfin_read_MDMA_D1_CURR_X_COUNT()    bfin_read16(MDMA_D1_CURR_X_COUNT)
+#define bfin_write_MDMA_D1_CURR_X_COUNT(val) bfin_write16(MDMA_D1_CURR_X_COUNT,val)
+#define bfin_read_MDMA_D1_CURR_Y_COUNT()    bfin_read16(MDMA_D1_CURR_Y_COUNT)
+#define bfin_write_MDMA_D1_CURR_Y_COUNT(val) bfin_write16(MDMA_D1_CURR_Y_COUNT,val)
+#define bfin_read_MDMA_D1_IRQ_STATUS()      bfin_read16(MDMA_D1_IRQ_STATUS)
+#define bfin_write_MDMA_D1_IRQ_STATUS(val)  bfin_write16(MDMA_D1_IRQ_STATUS,val)
+#define bfin_read_MDMA_D1_PERIPHERAL_MAP()  bfin_read16(MDMA_D1_PERIPHERAL_MAP)
+#define bfin_write_MDMA_D1_PERIPHERAL_MAP(val) bfin_write16(MDMA_D1_PERIPHERAL_MAP,val)
+#define bfin_read_MDMA_S1_CONFIG()          bfin_read16(MDMA_S1_CONFIG)
+#define bfin_write_MDMA_S1_CONFIG(val)      bfin_write16(MDMA_S1_CONFIG,val)
+#define bfin_read_MDMA_S1_NEXT_DESC_PTR()   bfin_read32(MDMA_S1_NEXT_DESC_PTR)
+#define bfin_write_MDMA_S1_NEXT_DESC_PTR(val) bfin_write32(MDMA_S1_NEXT_DESC_PTR,val)
+#define bfin_read_MDMA_S1_START_ADDR()      bfin_read32(MDMA_S1_START_ADDR)
+#define bfin_write_MDMA_S1_START_ADDR(val)  bfin_write32(MDMA_S1_START_ADDR,val)
+#define bfin_read_MDMA_S1_X_COUNT()         bfin_read16(MDMA_S1_X_COUNT)
+#define bfin_write_MDMA_S1_X_COUNT(val)     bfin_write16(MDMA_S1_X_COUNT,val)
+#define bfin_read_MDMA_S1_Y_COUNT()         bfin_read16(MDMA_S1_Y_COUNT)
+#define bfin_write_MDMA_S1_Y_COUNT(val)     bfin_write16(MDMA_S1_Y_COUNT,val)
+#define bfin_read_MDMA_S1_X_MODIFY()        bfin_read16(MDMA_S1_X_MODIFY)
+#define bfin_write_MDMA_S1_X_MODIFY(val)    bfin_write16(MDMA_S1_X_MODIFY,val)
+#define bfin_read_MDMA_S1_Y_MODIFY()        bfin_read16(MDMA_S1_Y_MODIFY)
+#define bfin_write_MDMA_S1_Y_MODIFY(val)    bfin_write16(MDMA_S1_Y_MODIFY,val)
+#define bfin_read_MDMA_S1_CURR_DESC_PTR()   bfin_read32(MDMA_S1_CURR_DESC_PTR)
+#define bfin_write_MDMA_S1_CURR_DESC_PTR(val) bfin_write32(MDMA_S1_CURR_DESC_PTR,val)
+#define bfin_read_MDMA_S1_CURR_ADDR()       bfin_read32(MDMA_S1_CURR_ADDR)
+#define bfin_write_MDMA_S1_CURR_ADDR(val)   bfin_write32(MDMA_S1_CURR_ADDR,val)
+#define bfin_read_MDMA_S1_CURR_X_COUNT()    bfin_read16(MDMA_S1_CURR_X_COUNT)
+#define bfin_write_MDMA_S1_CURR_X_COUNT(val) bfin_write16(MDMA_S1_CURR_X_COUNT,val)
+#define bfin_read_MDMA_S1_CURR_Y_COUNT()    bfin_read16(MDMA_S1_CURR_Y_COUNT)
+#define bfin_write_MDMA_S1_CURR_Y_COUNT(val) bfin_write16(MDMA_S1_CURR_Y_COUNT,val)
+#define bfin_read_MDMA_S1_IRQ_STATUS()      bfin_read16(MDMA_S1_IRQ_STATUS)
+#define bfin_write_MDMA_S1_IRQ_STATUS(val)  bfin_write16(MDMA_S1_IRQ_STATUS,val)
+#define bfin_read_MDMA_S1_PERIPHERAL_MAP()  bfin_read16(MDMA_S1_PERIPHERAL_MAP)
+#define bfin_write_MDMA_S1_PERIPHERAL_MAP(val) bfin_write16(MDMA_S1_PERIPHERAL_MAP,val)
 /* Internal Memory DMA Registers (0xFFC0_1800 - 0xFFC0_19FF) */
 #define bfin_read_IMDMA_D0_CONFIG()          bfin_read16(IMDMA_D0_CONFIG)
 #define bfin_write_IMDMA_D0_CONFIG(val)      bfin_write16(IMDMA_D0_CONFIG,val)
@@ -1465,65 +1457,4 @@
 #define bfin_read_IMDMA_S1_IRQ_STATUS()      bfin_read16(IMDMA_S1_IRQ_STATUS)
 #define bfin_write_IMDMA_S1_IRQ_STATUS(val)  bfin_write16(IMDMA_S1_IRQ_STATUS,val)
 
-#define bfin_read_MDMA_S0_CONFIG()  bfin_read_MDMA1_S0_CONFIG()
-#define bfin_write_MDMA_S0_CONFIG(val) bfin_write_MDMA1_S0_CONFIG(val)
-#define bfin_read_MDMA_S0_IRQ_STATUS()  bfin_read_MDMA1_S0_IRQ_STATUS()
-#define bfin_write_MDMA_S0_IRQ_STATUS(val) bfin_write_MDMA1_S0_IRQ_STATUS(val)
-#define bfin_read_MDMA_S0_X_MODIFY()  bfin_read_MDMA1_S0_X_MODIFY()
-#define bfin_write_MDMA_S0_X_MODIFY(val) bfin_write_MDMA1_S0_X_MODIFY(val)
-#define bfin_read_MDMA_S0_Y_MODIFY()  bfin_read_MDMA1_S0_Y_MODIFY()
-#define bfin_write_MDMA_S0_Y_MODIFY(val) bfin_write_MDMA1_S0_Y_MODIFY(val)
-#define bfin_read_MDMA_S0_X_COUNT()  bfin_read_MDMA1_S0_X_COUNT()
-#define bfin_write_MDMA_S0_X_COUNT(val) bfin_write_MDMA1_S0_X_COUNT(val)
-#define bfin_read_MDMA_S0_Y_COUNT()  bfin_read_MDMA1_S0_Y_COUNT()
-#define bfin_write_MDMA_S0_Y_COUNT(val) bfin_write_MDMA1_S0_Y_COUNT(val)
-#define bfin_read_MDMA_S0_START_ADDR()  bfin_read_MDMA1_S0_START_ADDR()
-#define bfin_write_MDMA_S0_START_ADDR(val) bfin_write_MDMA1_S0_START_ADDR(val)
-#define bfin_read_MDMA_D0_CONFIG()  bfin_read_MDMA1_D0_CONFIG()
-#define bfin_write_MDMA_D0_CONFIG(val) bfin_write_MDMA1_D0_CONFIG(val)
-#define bfin_read_MDMA_D0_IRQ_STATUS()  bfin_read_MDMA1_D0_IRQ_STATUS()
-#define bfin_write_MDMA_D0_IRQ_STATUS(val) bfin_write_MDMA1_D0_IRQ_STATUS(val)
-#define bfin_read_MDMA_D0_X_MODIFY()  bfin_read_MDMA1_D0_X_MODIFY()
-#define bfin_write_MDMA_D0_X_MODIFY(val) bfin_write_MDMA1_D0_X_MODIFY(val)
-#define bfin_read_MDMA_D0_Y_MODIFY()  bfin_read_MDMA1_D0_Y_MODIFY()
-#define bfin_write_MDMA_D0_Y_MODIFY(val) bfin_write_MDMA1_D0_Y_MODIFY(val)
-#define bfin_read_MDMA_D0_X_COUNT()  bfin_read_MDMA1_D0_X_COUNT()
-#define bfin_write_MDMA_D0_X_COUNT(val) bfin_write_MDMA1_D0_X_COUNT(val)
-#define bfin_read_MDMA_D0_Y_COUNT()  bfin_read_MDMA1_D0_Y_COUNT()
-#define bfin_write_MDMA_D0_Y_COUNT(val) bfin_write_MDMA1_D0_Y_COUNT(val)
-#define bfin_read_MDMA_D0_START_ADDR()  bfin_read_MDMA1_D0_START_ADDR()
-#define bfin_write_MDMA_D0_START_ADDR(val) bfin_write_MDMA1_D0_START_ADDR(val)
-
-#define bfin_read_MDMA_S1_CONFIG()  bfin_read_MDMA1_S1_CONFIG()
-#define bfin_write_MDMA_S1_CONFIG(val) bfin_write_MDMA1_S1_CONFIG(val)
-#define bfin_read_MDMA_S1_IRQ_STATUS()  bfin_read_MDMA1_S1_IRQ_STATUS()
-#define bfin_write_MDMA_S1_IRQ_STATUS(val) bfin_write_MDMA1_S1_IRQ_STATUS(val)
-#define bfin_read_MDMA_S1_X_MODIFY()  bfin_read_MDMA1_S1_X_MODIFY()
-#define bfin_write_MDMA_S1_X_MODIFY(val) bfin_write_MDMA1_S1_X_MODIFY(val)
-#define bfin_read_MDMA_S1_Y_MODIFY()  bfin_read_MDMA1_S1_Y_MODIFY()
-#define bfin_write_MDMA_S1_Y_MODIFY(val) bfin_write_MDMA1_S1_Y_MODIFY(val)
-#define bfin_read_MDMA_S1_X_COUNT()  bfin_read_MDMA1_S1_X_COUNT()
-#define bfin_write_MDMA_S1_X_COUNT(val) bfin_write_MDMA1_S1_X_COUNT(val)
-#define bfin_read_MDMA_S1_Y_COUNT()  bfin_read_MDMA1_S1_Y_COUNT()
-#define bfin_write_MDMA_S1_Y_COUNT(val) bfin_write_MDMA1_S1_Y_COUNT(val)
-#define bfin_read_MDMA_S1_START_ADDR()  bfin_read_MDMA1_S1_START_ADDR()
-#define bfin_write_MDMA_S1_START_ADDR(val) bfin_write_MDMA1_S1_START_ADDR(val)
-#define bfin_read_MDMA_D1_CONFIG()  bfin_read_MDMA1_D1_CONFIG()
-#define bfin_write_MDMA_D1_CONFIG(val) bfin_write_MDMA1_D1_CONFIG(val)
-#define bfin_read_MDMA_D1_IRQ_STATUS()  bfin_read_MDMA1_D1_IRQ_STATUS()
-#define bfin_write_MDMA_D1_IRQ_STATUS(val) bfin_write_MDMA1_D1_IRQ_STATUS(val)
-#define bfin_read_MDMA_D1_X_MODIFY()  bfin_read_MDMA1_D1_X_MODIFY()
-#define bfin_write_MDMA_D1_X_MODIFY(val) bfin_write_MDMA1_D1_X_MODIFY(val)
-#define bfin_read_MDMA_D1_Y_MODIFY()  bfin_read_MDMA1_D1_Y_MODIFY()
-#define bfin_write_MDMA_D1_Y_MODIFY(val) bfin_write_MDMA1_D1_Y_MODIFY(val)
-#define bfin_read_MDMA_D1_X_COUNT()  bfin_read_MDMA1_D1_X_COUNT()
-#define bfin_write_MDMA_D1_X_COUNT(val) bfin_write_MDMA1_D1_X_COUNT(val)
-#define bfin_read_MDMA_D1_Y_COUNT()  bfin_read_MDMA1_D1_Y_COUNT()
-#define bfin_write_MDMA_D1_Y_COUNT(val) bfin_write_MDMA1_D1_Y_COUNT(val)
-#define bfin_read_MDMA_D1_START_ADDR()  bfin_read_MDMA1_D1_START_ADDR()
-#define bfin_write_MDMA_D1_START_ADDR(val) bfin_write_MDMA1_D1_START_ADDR(val)
-
-/* These need to be last due to the cdef/linux inter-dependencies */
-#include <asm/irq.h>
-
 #endif				/* _CDEF_BF561_H */
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf561/include/mach/defBF561.h linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf561/include/mach/defBF561.h
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf561/include/mach/defBF561.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf561/include/mach/defBF561.h	2011-03-14 21:20:32.000000000 -0400
@@ -1,18 +1,11 @@
 /*
- * Copyright 2005-2009 Analog Devices Inc.
+ * Copyright 2005-2010 Analog Devices Inc.
  *
  * Licensed under the ADI BSD license or the GPL-2 (or later)
  */
 
 #ifndef _DEF_BF561_H
 #define _DEF_BF561_H
-/*
-#if !defined(__ADSPBF561__)
-#warning defBF561.h should only be included for BF561 chip.
-#endif
-*/
-/* include all Core registers and bit definitions */
-#include <asm/def_LPBlackfin.h>
 
 /*********************************************************************************** */
 /* System MMR Register Map */
@@ -311,10 +304,10 @@
 #define PPI1_FRAME 					0xFFC01310	/* PPI1 Frame Length register */
 
 /*DMA traffic control registers */
-#define	DMA1_TC_PER  0xFFC01B0C	/* Traffic control periods */
-#define	DMA1_TC_CNT  0xFFC01B10	/* Traffic control current counts */
-#define	DMA2_TC_PER  0xFFC00B0C	/* Traffic control periods */
-#define	DMA2_TC_CNT  0xFFC00B10	/* Traffic control current counts        */
+#define	DMAC0_TC_PER  0xFFC00B0C	/* Traffic control periods */
+#define	DMAC0_TC_CNT  0xFFC00B10	/* Traffic control current counts        */
+#define	DMAC1_TC_PER  0xFFC01B0C	/* Traffic control periods */
+#define	DMAC1_TC_CNT  0xFFC01B10	/* Traffic control current counts */
 
 /* DMA1 Controller registers (0xFFC0 1C00-0xFFC0 1FFF) */
 #define DMA1_0_CONFIG 0xFFC01C08	/* DMA1 Channel 0 Configuration register */
@@ -486,61 +479,61 @@
 #define DMA1_11_PERIPHERAL_MAP 0xFFC01EEC	/* DMA1 Channel 11 Peripheral Map Register */
 
 /* Memory DMA1 Controller registers (0xFFC0 1E80-0xFFC0 1FFF) */
-#define MDMA1_D0_CONFIG 0xFFC01F08	/*MemDMA1 Stream 0 Destination Configuration */
-#define MDMA1_D0_NEXT_DESC_PTR 0xFFC01F00	/*MemDMA1 Stream 0 Destination Next Descriptor Ptr Reg */
-#define MDMA1_D0_START_ADDR 0xFFC01F04	/*MemDMA1 Stream 0 Destination Start Address */
-#define MDMA1_D0_X_COUNT 0xFFC01F10	/*MemDMA1 Stream 0 Destination Inner-Loop Count */
-#define MDMA1_D0_Y_COUNT 0xFFC01F18	/*MemDMA1 Stream 0 Destination Outer-Loop Count */
-#define MDMA1_D0_X_MODIFY 0xFFC01F14	/*MemDMA1 Stream 0 Dest Inner-Loop Address-Increment */
-#define MDMA1_D0_Y_MODIFY 0xFFC01F1C	/*MemDMA1 Stream 0 Dest Outer-Loop Address-Increment */
-#define MDMA1_D0_CURR_DESC_PTR 0xFFC01F20	/*MemDMA1 Stream 0 Dest Current Descriptor Ptr reg */
-#define MDMA1_D0_CURR_ADDR 0xFFC01F24	/*MemDMA1 Stream 0 Destination Current Address */
-#define MDMA1_D0_CURR_X_COUNT 0xFFC01F30	/*MemDMA1 Stream 0 Dest Current Inner-Loop Count */
-#define MDMA1_D0_CURR_Y_COUNT 0xFFC01F38	/*MemDMA1 Stream 0 Dest Current Outer-Loop Count */
-#define MDMA1_D0_IRQ_STATUS 0xFFC01F28	/*MemDMA1 Stream 0 Destination Interrupt/Status */
-#define MDMA1_D0_PERIPHERAL_MAP 0xFFC01F2C	/*MemDMA1 Stream 0 Destination Peripheral Map */
+#define MDMA_D2_CONFIG 0xFFC01F08	/*MemDMA1 Stream 0 Destination Configuration */
+#define MDMA_D2_NEXT_DESC_PTR 0xFFC01F00	/*MemDMA1 Stream 0 Destination Next Descriptor Ptr Reg */
+#define MDMA_D2_START_ADDR 0xFFC01F04	/*MemDMA1 Stream 0 Destination Start Address */
+#define MDMA_D2_X_COUNT 0xFFC01F10	/*MemDMA1 Stream 0 Destination Inner-Loop Count */
+#define MDMA_D2_Y_COUNT 0xFFC01F18	/*MemDMA1 Stream 0 Destination Outer-Loop Count */
+#define MDMA_D2_X_MODIFY 0xFFC01F14	/*MemDMA1 Stream 0 Dest Inner-Loop Address-Increment */
+#define MDMA_D2_Y_MODIFY 0xFFC01F1C	/*MemDMA1 Stream 0 Dest Outer-Loop Address-Increment */
+#define MDMA_D2_CURR_DESC_PTR 0xFFC01F20	/*MemDMA1 Stream 0 Dest Current Descriptor Ptr reg */
+#define MDMA_D2_CURR_ADDR 0xFFC01F24	/*MemDMA1 Stream 0 Destination Current Address */
+#define MDMA_D2_CURR_X_COUNT 0xFFC01F30	/*MemDMA1 Stream 0 Dest Current Inner-Loop Count */
+#define MDMA_D2_CURR_Y_COUNT 0xFFC01F38	/*MemDMA1 Stream 0 Dest Current Outer-Loop Count */
+#define MDMA_D2_IRQ_STATUS 0xFFC01F28	/*MemDMA1 Stream 0 Destination Interrupt/Status */
+#define MDMA_D2_PERIPHERAL_MAP 0xFFC01F2C	/*MemDMA1 Stream 0 Destination Peripheral Map */
 
-#define MDMA1_S0_CONFIG 0xFFC01F48	/*MemDMA1 Stream 0 Source Configuration */
-#define MDMA1_S0_NEXT_DESC_PTR 0xFFC01F40	/*MemDMA1 Stream 0 Source Next Descriptor Ptr Reg */
-#define MDMA1_S0_START_ADDR 0xFFC01F44	/*MemDMA1 Stream 0 Source Start Address */
-#define MDMA1_S0_X_COUNT 0xFFC01F50	/*MemDMA1 Stream 0 Source Inner-Loop Count */
-#define MDMA1_S0_Y_COUNT 0xFFC01F58	/*MemDMA1 Stream 0 Source Outer-Loop Count */
-#define MDMA1_S0_X_MODIFY 0xFFC01F54	/*MemDMA1 Stream 0 Source Inner-Loop Address-Increment */
-#define MDMA1_S0_Y_MODIFY 0xFFC01F5C	/*MemDMA1 Stream 0 Source Outer-Loop Address-Increment */
-#define MDMA1_S0_CURR_DESC_PTR 0xFFC01F60	/*MemDMA1 Stream 0 Source Current Descriptor Ptr reg */
-#define MDMA1_S0_CURR_ADDR 0xFFC01F64	/*MemDMA1 Stream 0 Source Current Address */
-#define MDMA1_S0_CURR_X_COUNT 0xFFC01F70	/*MemDMA1 Stream 0 Source Current Inner-Loop Count */
-#define MDMA1_S0_CURR_Y_COUNT 0xFFC01F78	/*MemDMA1 Stream 0 Source Current Outer-Loop Count */
-#define MDMA1_S0_IRQ_STATUS 0xFFC01F68	/*MemDMA1 Stream 0 Source Interrupt/Status */
-#define MDMA1_S0_PERIPHERAL_MAP 0xFFC01F6C	/*MemDMA1 Stream 0 Source Peripheral Map */
+#define MDMA_S2_CONFIG 0xFFC01F48	/*MemDMA1 Stream 0 Source Configuration */
+#define MDMA_S2_NEXT_DESC_PTR 0xFFC01F40	/*MemDMA1 Stream 0 Source Next Descriptor Ptr Reg */
+#define MDMA_S2_START_ADDR 0xFFC01F44	/*MemDMA1 Stream 0 Source Start Address */
+#define MDMA_S2_X_COUNT 0xFFC01F50	/*MemDMA1 Stream 0 Source Inner-Loop Count */
+#define MDMA_S2_Y_COUNT 0xFFC01F58	/*MemDMA1 Stream 0 Source Outer-Loop Count */
+#define MDMA_S2_X_MODIFY 0xFFC01F54	/*MemDMA1 Stream 0 Source Inner-Loop Address-Increment */
+#define MDMA_S2_Y_MODIFY 0xFFC01F5C	/*MemDMA1 Stream 0 Source Outer-Loop Address-Increment */
+#define MDMA_S2_CURR_DESC_PTR 0xFFC01F60	/*MemDMA1 Stream 0 Source Current Descriptor Ptr reg */
+#define MDMA_S2_CURR_ADDR 0xFFC01F64	/*MemDMA1 Stream 0 Source Current Address */
+#define MDMA_S2_CURR_X_COUNT 0xFFC01F70	/*MemDMA1 Stream 0 Source Current Inner-Loop Count */
+#define MDMA_S2_CURR_Y_COUNT 0xFFC01F78	/*MemDMA1 Stream 0 Source Current Outer-Loop Count */
+#define MDMA_S2_IRQ_STATUS 0xFFC01F68	/*MemDMA1 Stream 0 Source Interrupt/Status */
+#define MDMA_S2_PERIPHERAL_MAP 0xFFC01F6C	/*MemDMA1 Stream 0 Source Peripheral Map */
 
-#define MDMA1_D1_CONFIG 0xFFC01F88	/*MemDMA1 Stream 1 Destination Configuration */
-#define MDMA1_D1_NEXT_DESC_PTR 0xFFC01F80	/*MemDMA1 Stream 1 Destination Next Descriptor Ptr Reg */
-#define MDMA1_D1_START_ADDR 0xFFC01F84	/*MemDMA1 Stream 1 Destination Start Address */
-#define MDMA1_D1_X_COUNT 0xFFC01F90	/*MemDMA1 Stream 1 Destination Inner-Loop Count */
-#define MDMA1_D1_Y_COUNT 0xFFC01F98	/*MemDMA1 Stream 1 Destination Outer-Loop Count */
-#define MDMA1_D1_X_MODIFY 0xFFC01F94	/*MemDMA1 Stream 1 Dest Inner-Loop Address-Increment */
-#define MDMA1_D1_Y_MODIFY 0xFFC01F9C	/*MemDMA1 Stream 1 Dest Outer-Loop Address-Increment */
-#define MDMA1_D1_CURR_DESC_PTR 0xFFC01FA0	/*MemDMA1 Stream 1 Dest Current Descriptor Ptr reg */
-#define MDMA1_D1_CURR_ADDR 0xFFC01FA4	/*MemDMA1 Stream 1 Dest Current Address */
-#define MDMA1_D1_CURR_X_COUNT 0xFFC01FB0	/*MemDMA1 Stream 1 Dest Current Inner-Loop Count */
-#define MDMA1_D1_CURR_Y_COUNT 0xFFC01FB8	/*MemDMA1 Stream 1 Dest Current Outer-Loop Count */
-#define MDMA1_D1_IRQ_STATUS 0xFFC01FA8	/*MemDMA1 Stream 1 Dest Interrupt/Status */
-#define MDMA1_D1_PERIPHERAL_MAP 0xFFC01FAC	/*MemDMA1 Stream 1 Dest Peripheral Map */
+#define MDMA_D3_CONFIG 0xFFC01F88	/*MemDMA1 Stream 1 Destination Configuration */
+#define MDMA_D3_NEXT_DESC_PTR 0xFFC01F80	/*MemDMA1 Stream 1 Destination Next Descriptor Ptr Reg */
+#define MDMA_D3_START_ADDR 0xFFC01F84	/*MemDMA1 Stream 1 Destination Start Address */
+#define MDMA_D3_X_COUNT 0xFFC01F90	/*MemDMA1 Stream 1 Destination Inner-Loop Count */
+#define MDMA_D3_Y_COUNT 0xFFC01F98	/*MemDMA1 Stream 1 Destination Outer-Loop Count */
+#define MDMA_D3_X_MODIFY 0xFFC01F94	/*MemDMA1 Stream 1 Dest Inner-Loop Address-Increment */
+#define MDMA_D3_Y_MODIFY 0xFFC01F9C	/*MemDMA1 Stream 1 Dest Outer-Loop Address-Increment */
+#define MDMA_D3_CURR_DESC_PTR 0xFFC01FA0	/*MemDMA1 Stream 1 Dest Current Descriptor Ptr reg */
+#define MDMA_D3_CURR_ADDR 0xFFC01FA4	/*MemDMA1 Stream 1 Dest Current Address */
+#define MDMA_D3_CURR_X_COUNT 0xFFC01FB0	/*MemDMA1 Stream 1 Dest Current Inner-Loop Count */
+#define MDMA_D3_CURR_Y_COUNT 0xFFC01FB8	/*MemDMA1 Stream 1 Dest Current Outer-Loop Count */
+#define MDMA_D3_IRQ_STATUS 0xFFC01FA8	/*MemDMA1 Stream 1 Dest Interrupt/Status */
+#define MDMA_D3_PERIPHERAL_MAP 0xFFC01FAC	/*MemDMA1 Stream 1 Dest Peripheral Map */
 
-#define MDMA1_S1_CONFIG 0xFFC01FC8	/*MemDMA1 Stream 1 Source Configuration */
-#define MDMA1_S1_NEXT_DESC_PTR 0xFFC01FC0	/*MemDMA1 Stream 1 Source Next Descriptor Ptr Reg */
-#define MDMA1_S1_START_ADDR 0xFFC01FC4	/*MemDMA1 Stream 1 Source Start Address */
-#define MDMA1_S1_X_COUNT 0xFFC01FD0	/*MemDMA1 Stream 1 Source Inner-Loop Count */
-#define MDMA1_S1_Y_COUNT 0xFFC01FD8	/*MemDMA1 Stream 1 Source Outer-Loop Count */
-#define MDMA1_S1_X_MODIFY 0xFFC01FD4	/*MemDMA1 Stream 1 Source Inner-Loop Address-Increment */
-#define MDMA1_S1_Y_MODIFY 0xFFC01FDC	/*MemDMA1 Stream 1 Source Outer-Loop Address-Increment */
-#define MDMA1_S1_CURR_DESC_PTR 0xFFC01FE0	/*MemDMA1 Stream 1 Source Current Descriptor Ptr reg */
-#define MDMA1_S1_CURR_ADDR 0xFFC01FE4	/*MemDMA1 Stream 1 Source Current Address */
-#define MDMA1_S1_CURR_X_COUNT 0xFFC01FF0	/*MemDMA1 Stream 1 Source Current Inner-Loop Count */
-#define MDMA1_S1_CURR_Y_COUNT 0xFFC01FF8	/*MemDMA1 Stream 1 Source Current Outer-Loop Count */
-#define MDMA1_S1_IRQ_STATUS 0xFFC01FE8	/*MemDMA1 Stream 1 Source Interrupt/Status */
-#define MDMA1_S1_PERIPHERAL_MAP 0xFFC01FEC	/*MemDMA1 Stream 1 Source Peripheral Map */
+#define MDMA_S3_CONFIG 0xFFC01FC8	/*MemDMA1 Stream 1 Source Configuration */
+#define MDMA_S3_NEXT_DESC_PTR 0xFFC01FC0	/*MemDMA1 Stream 1 Source Next Descriptor Ptr Reg */
+#define MDMA_S3_START_ADDR 0xFFC01FC4	/*MemDMA1 Stream 1 Source Start Address */
+#define MDMA_S3_X_COUNT 0xFFC01FD0	/*MemDMA1 Stream 1 Source Inner-Loop Count */
+#define MDMA_S3_Y_COUNT 0xFFC01FD8	/*MemDMA1 Stream 1 Source Outer-Loop Count */
+#define MDMA_S3_X_MODIFY 0xFFC01FD4	/*MemDMA1 Stream 1 Source Inner-Loop Address-Increment */
+#define MDMA_S3_Y_MODIFY 0xFFC01FDC	/*MemDMA1 Stream 1 Source Outer-Loop Address-Increment */
+#define MDMA_S3_CURR_DESC_PTR 0xFFC01FE0	/*MemDMA1 Stream 1 Source Current Descriptor Ptr reg */
+#define MDMA_S3_CURR_ADDR 0xFFC01FE4	/*MemDMA1 Stream 1 Source Current Address */
+#define MDMA_S3_CURR_X_COUNT 0xFFC01FF0	/*MemDMA1 Stream 1 Source Current Inner-Loop Count */
+#define MDMA_S3_CURR_Y_COUNT 0xFFC01FF8	/*MemDMA1 Stream 1 Source Current Outer-Loop Count */
+#define MDMA_S3_IRQ_STATUS 0xFFC01FE8	/*MemDMA1 Stream 1 Source Interrupt/Status */
+#define MDMA_S3_PERIPHERAL_MAP 0xFFC01FEC	/*MemDMA1 Stream 1 Source Peripheral Map */
 
 /* DMA2 Controller registers (0xFFC0 0C00-0xFFC0 0DFF) */
 #define DMA2_0_CONFIG 0xFFC00C08	/* DMA2 Channel 0 Configuration register */
@@ -712,117 +705,61 @@
 #define DMA2_11_PERIPHERAL_MAP 0xFFC00EEC	/* DMA2 Channel 11 Peripheral Map Register */
 
 /* Memory DMA2 Controller registers (0xFFC0 0E80-0xFFC0 0FFF) */
-#define MDMA2_D0_CONFIG 0xFFC00F08	/*MemDMA2 Stream 0 Destination Configuration register */
-#define MDMA2_D0_NEXT_DESC_PTR 0xFFC00F00	/*MemDMA2 Stream 0 Destination Next Descriptor Ptr Reg */
-#define MDMA2_D0_START_ADDR 0xFFC00F04	/*MemDMA2 Stream 0 Destination Start Address */
-#define MDMA2_D0_X_COUNT 0xFFC00F10	/*MemDMA2 Stream 0 Dest Inner-Loop Count register */
-#define MDMA2_D0_Y_COUNT 0xFFC00F18	/*MemDMA2 Stream 0 Dest Outer-Loop Count register */
-#define MDMA2_D0_X_MODIFY 0xFFC00F14	/*MemDMA2 Stream 0 Dest Inner-Loop Address-Increment */
-#define MDMA2_D0_Y_MODIFY 0xFFC00F1C	/*MemDMA2 Stream 0 Dest Outer-Loop Address-Increment */
-#define MDMA2_D0_CURR_DESC_PTR 0xFFC00F20	/*MemDMA2 Stream 0 Dest Current Descriptor Ptr reg */
-#define MDMA2_D0_CURR_ADDR 0xFFC00F24	/*MemDMA2 Stream 0 Destination Current Address */
-#define MDMA2_D0_CURR_X_COUNT 0xFFC00F30	/*MemDMA2 Stream 0 Dest Current Inner-Loop Count reg */
-#define MDMA2_D0_CURR_Y_COUNT 0xFFC00F38	/*MemDMA2 Stream 0 Dest Current Outer-Loop Count reg */
-#define MDMA2_D0_IRQ_STATUS 0xFFC00F28	/*MemDMA2 Stream 0 Dest Interrupt/Status Register */
-#define MDMA2_D0_PERIPHERAL_MAP 0xFFC00F2C	/*MemDMA2 Stream 0 Destination Peripheral Map register */
-
-#define MDMA2_S0_CONFIG 0xFFC00F48	/*MemDMA2 Stream 0 Source Configuration register */
-#define MDMA2_S0_NEXT_DESC_PTR 0xFFC00F40	/*MemDMA2 Stream 0 Source Next Descriptor Ptr Reg */
-#define MDMA2_S0_START_ADDR 0xFFC00F44	/*MemDMA2 Stream 0 Source Start Address */
-#define MDMA2_S0_X_COUNT 0xFFC00F50	/*MemDMA2 Stream 0 Source Inner-Loop Count register */
-#define MDMA2_S0_Y_COUNT 0xFFC00F58	/*MemDMA2 Stream 0 Source Outer-Loop Count register */
-#define MDMA2_S0_X_MODIFY 0xFFC00F54	/*MemDMA2 Stream 0 Src Inner-Loop Addr-Increment reg */
-#define MDMA2_S0_Y_MODIFY 0xFFC00F5C	/*MemDMA2 Stream 0 Src Outer-Loop Addr-Increment reg */
-#define MDMA2_S0_CURR_DESC_PTR 0xFFC00F60	/*MemDMA2 Stream 0 Source Current Descriptor Ptr reg */
-#define MDMA2_S0_CURR_ADDR 0xFFC00F64	/*MemDMA2 Stream 0 Source Current Address */
-#define MDMA2_S0_CURR_X_COUNT 0xFFC00F70	/*MemDMA2 Stream 0 Src Current Inner-Loop Count reg */
-#define MDMA2_S0_CURR_Y_COUNT 0xFFC00F78	/*MemDMA2 Stream 0 Src Current Outer-Loop Count reg */
-#define MDMA2_S0_IRQ_STATUS 0xFFC00F68	/*MemDMA2 Stream 0 Source Interrupt/Status Register */
-#define MDMA2_S0_PERIPHERAL_MAP 0xFFC00F6C	/*MemDMA2 Stream 0 Source Peripheral Map register */
-
-#define MDMA2_D1_CONFIG 0xFFC00F88	/*MemDMA2 Stream 1 Destination Configuration register */
-#define MDMA2_D1_NEXT_DESC_PTR 0xFFC00F80	/*MemDMA2 Stream 1 Destination Next Descriptor Ptr Reg */
-#define MDMA2_D1_START_ADDR 0xFFC00F84	/*MemDMA2 Stream 1 Destination Start Address */
-#define MDMA2_D1_X_COUNT 0xFFC00F90	/*MemDMA2 Stream 1 Dest Inner-Loop Count register */
-#define MDMA2_D1_Y_COUNT 0xFFC00F98	/*MemDMA2 Stream 1 Dest Outer-Loop Count register */
-#define MDMA2_D1_X_MODIFY 0xFFC00F94	/*MemDMA2 Stream 1 Dest Inner-Loop Address-Increment */
-#define MDMA2_D1_Y_MODIFY 0xFFC00F9C	/*MemDMA2 Stream 1 Dest Outer-Loop Address-Increment */
-#define MDMA2_D1_CURR_DESC_PTR 0xFFC00FA0	/*MemDMA2 Stream 1 Destination Current Descriptor Ptr */
-#define MDMA2_D1_CURR_ADDR 0xFFC00FA4	/*MemDMA2 Stream 1 Destination Current Address reg */
-#define MDMA2_D1_CURR_X_COUNT 0xFFC00FB0	/*MemDMA2 Stream 1 Dest Current Inner-Loop Count reg */
-#define MDMA2_D1_CURR_Y_COUNT 0xFFC00FB8	/*MemDMA2 Stream 1 Dest Current Outer-Loop Count reg */
-#define MDMA2_D1_IRQ_STATUS 0xFFC00FA8	/*MemDMA2 Stream 1 Destination Interrupt/Status Reg */
-#define MDMA2_D1_PERIPHERAL_MAP 0xFFC00FAC	/*MemDMA2 Stream 1 Destination Peripheral Map register */
-
-#define MDMA2_S1_CONFIG 0xFFC00FC8	/*MemDMA2 Stream 1 Source Configuration register */
-#define MDMA2_S1_NEXT_DESC_PTR 0xFFC00FC0	/*MemDMA2 Stream 1 Source Next Descriptor Ptr Reg */
-#define MDMA2_S1_START_ADDR 0xFFC00FC4	/*MemDMA2 Stream 1 Source Start Address */
-#define MDMA2_S1_X_COUNT 0xFFC00FD0	/*MemDMA2 Stream 1 Source Inner-Loop Count register */
-#define MDMA2_S1_Y_COUNT 0xFFC00FD8	/*MemDMA2 Stream 1 Source Outer-Loop Count register */
-#define MDMA2_S1_X_MODIFY 0xFFC00FD4	/*MemDMA2 Stream 1 Src Inner-Loop Address-Increment */
-#define MDMA2_S1_Y_MODIFY 0xFFC00FDC	/*MemDMA2 Stream 1 Source Outer-Loop Address-Increment */
-#define MDMA2_S1_CURR_DESC_PTR 0xFFC00FE0	/*MemDMA2 Stream 1 Source Current Descriptor Ptr reg */
-#define MDMA2_S1_CURR_ADDR 0xFFC00FE4	/*MemDMA2 Stream 1 Source Current Address */
-#define MDMA2_S1_CURR_X_COUNT 0xFFC00FF0	/*MemDMA2 Stream 1 Source Current Inner-Loop Count */
-#define MDMA2_S1_CURR_Y_COUNT 0xFFC00FF8	/*MemDMA2 Stream 1 Source Current Outer-Loop Count */
-#define MDMA2_S1_IRQ_STATUS 0xFFC00FE8	/*MemDMA2 Stream 1 Source Interrupt/Status Register */
-#define MDMA2_S1_PERIPHERAL_MAP 0xFFC00FEC	/*MemDMA2 Stream 1 Source Peripheral Map register */
-
-#define MDMA_D0_NEXT_DESC_PTR MDMA1_D0_NEXT_DESC_PTR
-#define MDMA_D0_START_ADDR MDMA1_D0_START_ADDR
-#define MDMA_D0_CONFIG MDMA1_D0_CONFIG
-#define MDMA_D0_X_COUNT MDMA1_D0_X_COUNT
-#define MDMA_D0_X_MODIFY MDMA1_D0_X_MODIFY
-#define MDMA_D0_Y_COUNT MDMA1_D0_Y_COUNT
-#define MDMA_D0_Y_MODIFY MDMA1_D0_Y_MODIFY
-#define MDMA_D0_CURR_DESC_PTR MDMA1_D0_CURR_DESC_PTR
-#define MDMA_D0_CURR_ADDR MDMA1_D0_CURR_ADDR
-#define MDMA_D0_IRQ_STATUS MDMA1_D0_IRQ_STATUS
-#define MDMA_D0_PERIPHERAL_MAP MDMA1_D0_PERIPHERAL_MAP
-#define MDMA_D0_CURR_X_COUNT MDMA1_D0_CURR_X_COUNT
-#define MDMA_D0_CURR_Y_COUNT MDMA1_D0_CURR_Y_COUNT
+#define MDMA_D0_CONFIG 0xFFC00F08	/*MemDMA2 Stream 0 Destination Configuration register */
+#define MDMA_D0_NEXT_DESC_PTR 0xFFC00F00	/*MemDMA2 Stream 0 Destination Next Descriptor Ptr Reg */
+#define MDMA_D0_START_ADDR 0xFFC00F04	/*MemDMA2 Stream 0 Destination Start Address */
+#define MDMA_D0_X_COUNT 0xFFC00F10	/*MemDMA2 Stream 0 Dest Inner-Loop Count register */
+#define MDMA_D0_Y_COUNT 0xFFC00F18	/*MemDMA2 Stream 0 Dest Outer-Loop Count register */
+#define MDMA_D0_X_MODIFY 0xFFC00F14	/*MemDMA2 Stream 0 Dest Inner-Loop Address-Increment */
+#define MDMA_D0_Y_MODIFY 0xFFC00F1C	/*MemDMA2 Stream 0 Dest Outer-Loop Address-Increment */
+#define MDMA_D0_CURR_DESC_PTR 0xFFC00F20	/*MemDMA2 Stream 0 Dest Current Descriptor Ptr reg */
+#define MDMA_D0_CURR_ADDR 0xFFC00F24	/*MemDMA2 Stream 0 Destination Current Address */
+#define MDMA_D0_CURR_X_COUNT 0xFFC00F30	/*MemDMA2 Stream 0 Dest Current Inner-Loop Count reg */
+#define MDMA_D0_CURR_Y_COUNT 0xFFC00F38	/*MemDMA2 Stream 0 Dest Current Outer-Loop Count reg */
+#define MDMA_D0_IRQ_STATUS 0xFFC00F28	/*MemDMA2 Stream 0 Dest Interrupt/Status Register */
+#define MDMA_D0_PERIPHERAL_MAP 0xFFC00F2C	/*MemDMA2 Stream 0 Destination Peripheral Map register */
 
-#define MDMA_S0_NEXT_DESC_PTR MDMA1_S0_NEXT_DESC_PTR
-#define MDMA_S0_START_ADDR MDMA1_S0_START_ADDR
-#define MDMA_S0_CONFIG MDMA1_S0_CONFIG
-#define MDMA_S0_X_COUNT MDMA1_S0_X_COUNT
-#define MDMA_S0_X_MODIFY MDMA1_S0_X_MODIFY
-#define MDMA_S0_Y_COUNT MDMA1_S0_Y_COUNT
-#define MDMA_S0_Y_MODIFY MDMA1_S0_Y_MODIFY
-#define MDMA_S0_CURR_DESC_PTR MDMA1_S0_CURR_DESC_PTR
-#define MDMA_S0_CURR_ADDR MDMA1_S0_CURR_ADDR
-#define MDMA_S0_IRQ_STATUS MDMA1_S0_IRQ_STATUS
-#define MDMA_S0_PERIPHERAL_MAP MDMA1_S0_PERIPHERAL_MAP
-#define MDMA_S0_CURR_X_COUNT MDMA1_S0_CURR_X_COUNT
-#define MDMA_S0_CURR_Y_COUNT MDMA1_S0_CURR_Y_COUNT
+#define MDMA_S0_CONFIG 0xFFC00F48	/*MemDMA2 Stream 0 Source Configuration register */
+#define MDMA_S0_NEXT_DESC_PTR 0xFFC00F40	/*MemDMA2 Stream 0 Source Next Descriptor Ptr Reg */
+#define MDMA_S0_START_ADDR 0xFFC00F44	/*MemDMA2 Stream 0 Source Start Address */
+#define MDMA_S0_X_COUNT 0xFFC00F50	/*MemDMA2 Stream 0 Source Inner-Loop Count register */
+#define MDMA_S0_Y_COUNT 0xFFC00F58	/*MemDMA2 Stream 0 Source Outer-Loop Count register */
+#define MDMA_S0_X_MODIFY 0xFFC00F54	/*MemDMA2 Stream 0 Src Inner-Loop Addr-Increment reg */
+#define MDMA_S0_Y_MODIFY 0xFFC00F5C	/*MemDMA2 Stream 0 Src Outer-Loop Addr-Increment reg */
+#define MDMA_S0_CURR_DESC_PTR 0xFFC00F60	/*MemDMA2 Stream 0 Source Current Descriptor Ptr reg */
+#define MDMA_S0_CURR_ADDR 0xFFC00F64	/*MemDMA2 Stream 0 Source Current Address */
+#define MDMA_S0_CURR_X_COUNT 0xFFC00F70	/*MemDMA2 Stream 0 Src Current Inner-Loop Count reg */
+#define MDMA_S0_CURR_Y_COUNT 0xFFC00F78	/*MemDMA2 Stream 0 Src Current Outer-Loop Count reg */
+#define MDMA_S0_IRQ_STATUS 0xFFC00F68	/*MemDMA2 Stream 0 Source Interrupt/Status Register */
+#define MDMA_S0_PERIPHERAL_MAP 0xFFC00F6C	/*MemDMA2 Stream 0 Source Peripheral Map register */
 
-#define MDMA_D1_NEXT_DESC_PTR MDMA1_D1_NEXT_DESC_PTR
-#define MDMA_D1_START_ADDR MDMA1_D1_START_ADDR
-#define MDMA_D1_CONFIG MDMA1_D1_CONFIG
-#define MDMA_D1_X_COUNT MDMA1_D1_X_COUNT
-#define MDMA_D1_X_MODIFY MDMA1_D1_X_MODIFY
-#define MDMA_D1_Y_COUNT MDMA1_D1_Y_COUNT
-#define MDMA_D1_Y_MODIFY MDMA1_D1_Y_MODIFY
-#define MDMA_D1_CURR_DESC_PTR MDMA1_D1_CURR_DESC_PTR
-#define MDMA_D1_CURR_ADDR MDMA1_D1_CURR_ADDR
-#define MDMA_D1_IRQ_STATUS MDMA1_D1_IRQ_STATUS
-#define MDMA_D1_PERIPHERAL_MAP MDMA1_D1_PERIPHERAL_MAP
-#define MDMA_D1_CURR_X_COUNT MDMA1_D1_CURR_X_COUNT
-#define MDMA_D1_CURR_Y_COUNT MDMA1_D1_CURR_Y_COUNT
+#define MDMA_D1_CONFIG 0xFFC00F88	/*MemDMA2 Stream 1 Destination Configuration register */
+#define MDMA_D1_NEXT_DESC_PTR 0xFFC00F80	/*MemDMA2 Stream 1 Destination Next Descriptor Ptr Reg */
+#define MDMA_D1_START_ADDR 0xFFC00F84	/*MemDMA2 Stream 1 Destination Start Address */
+#define MDMA_D1_X_COUNT 0xFFC00F90	/*MemDMA2 Stream 1 Dest Inner-Loop Count register */
+#define MDMA_D1_Y_COUNT 0xFFC00F98	/*MemDMA2 Stream 1 Dest Outer-Loop Count register */
+#define MDMA_D1_X_MODIFY 0xFFC00F94	/*MemDMA2 Stream 1 Dest Inner-Loop Address-Increment */
+#define MDMA_D1_Y_MODIFY 0xFFC00F9C	/*MemDMA2 Stream 1 Dest Outer-Loop Address-Increment */
+#define MDMA_D1_CURR_DESC_PTR 0xFFC00FA0	/*MemDMA2 Stream 1 Destination Current Descriptor Ptr */
+#define MDMA_D1_CURR_ADDR 0xFFC00FA4	/*MemDMA2 Stream 1 Destination Current Address reg */
+#define MDMA_D1_CURR_X_COUNT 0xFFC00FB0	/*MemDMA2 Stream 1 Dest Current Inner-Loop Count reg */
+#define MDMA_D1_CURR_Y_COUNT 0xFFC00FB8	/*MemDMA2 Stream 1 Dest Current Outer-Loop Count reg */
+#define MDMA_D1_IRQ_STATUS 0xFFC00FA8	/*MemDMA2 Stream 1 Destination Interrupt/Status Reg */
+#define MDMA_D1_PERIPHERAL_MAP 0xFFC00FAC	/*MemDMA2 Stream 1 Destination Peripheral Map register */
 
-#define MDMA_S1_NEXT_DESC_PTR MDMA1_S1_NEXT_DESC_PTR
-#define MDMA_S1_START_ADDR MDMA1_S1_START_ADDR
-#define MDMA_S1_CONFIG MDMA1_S1_CONFIG
-#define MDMA_S1_X_COUNT MDMA1_S1_X_COUNT
-#define MDMA_S1_X_MODIFY MDMA1_S1_X_MODIFY
-#define MDMA_S1_Y_COUNT MDMA1_S1_Y_COUNT
-#define MDMA_S1_Y_MODIFY MDMA1_S1_Y_MODIFY
-#define MDMA_S1_CURR_DESC_PTR MDMA1_S1_CURR_DESC_PTR
-#define MDMA_S1_CURR_ADDR MDMA1_S1_CURR_ADDR
-#define MDMA_S1_IRQ_STATUS MDMA1_S1_IRQ_STATUS
-#define MDMA_S1_PERIPHERAL_MAP MDMA1_S1_PERIPHERAL_MAP
-#define MDMA_S1_CURR_X_COUNT MDMA1_S1_CURR_X_COUNT
-#define MDMA_S1_CURR_Y_COUNT MDMA1_S1_CURR_Y_COUNT
+#define MDMA_S1_CONFIG 0xFFC00FC8	/*MemDMA2 Stream 1 Source Configuration register */
+#define MDMA_S1_NEXT_DESC_PTR 0xFFC00FC0	/*MemDMA2 Stream 1 Source Next Descriptor Ptr Reg */
+#define MDMA_S1_START_ADDR 0xFFC00FC4	/*MemDMA2 Stream 1 Source Start Address */
+#define MDMA_S1_X_COUNT 0xFFC00FD0	/*MemDMA2 Stream 1 Source Inner-Loop Count register */
+#define MDMA_S1_Y_COUNT 0xFFC00FD8	/*MemDMA2 Stream 1 Source Outer-Loop Count register */
+#define MDMA_S1_X_MODIFY 0xFFC00FD4	/*MemDMA2 Stream 1 Src Inner-Loop Address-Increment */
+#define MDMA_S1_Y_MODIFY 0xFFC00FDC	/*MemDMA2 Stream 1 Source Outer-Loop Address-Increment */
+#define MDMA_S1_CURR_DESC_PTR 0xFFC00FE0	/*MemDMA2 Stream 1 Source Current Descriptor Ptr reg */
+#define MDMA_S1_CURR_ADDR 0xFFC00FE4	/*MemDMA2 Stream 1 Source Current Address */
+#define MDMA_S1_CURR_X_COUNT 0xFFC00FF0	/*MemDMA2 Stream 1 Source Current Inner-Loop Count */
+#define MDMA_S1_CURR_Y_COUNT 0xFFC00FF8	/*MemDMA2 Stream 1 Source Current Outer-Loop Count */
+#define MDMA_S1_IRQ_STATUS 0xFFC00FE8	/*MemDMA2 Stream 1 Source Interrupt/Status Register */
+#define MDMA_S1_PERIPHERAL_MAP 0xFFC00FEC	/*MemDMA2 Stream 1 Source Peripheral Map register */
 
 /* Internal Memory DMA Registers (0xFFC0_1800 - 0xFFC0_19FF) */
 #define IMDMA_D0_CONFIG 0xFFC01808	/*IMDMA Stream 0 Destination Configuration */
@@ -927,83 +864,6 @@
 #define IWR_ENABLE(x)	       (1 << (x))	/* Wakeup Enable Peripheral #x */
 #define IWR_DISABLE(x) (0xFFFFFFFF ^ (1 << (x)))	/* Wakeup Disable Peripheral #x */
 
-/* ***************************** UART CONTROLLER MASKS ********************** */
-
-/* UART_LCR Register */
-
-#define DLAB	0x80
-#define SB      0x40
-#define STP      0x20
-#define EPS     0x10
-#define PEN	0x08
-#define STB	0x04
-#define WLS(x)	((x-5) & 0x03)
-
-#define DLAB_P	0x07
-#define SB_P	0x06
-#define STP_P	0x05
-#define EPS_P	0x04
-#define PEN_P	0x03
-#define STB_P	0x02
-#define WLS_P1	0x01
-#define WLS_P0	0x00
-
-/* UART_MCR Register */
-#define LOOP_ENA	0x10
-#define LOOP_ENA_P	0x04
-
-/* UART_LSR Register */
-#define TEMT	0x40
-#define THRE	0x20
-#define BI	0x10
-#define FE	0x08
-#define PE	0x04
-#define OE	0x02
-#define DR	0x01
-
-#define TEMP_P	0x06
-#define THRE_P	0x05
-#define BI_P	0x04
-#define FE_P	0x03
-#define PE_P	0x02
-#define OE_P	0x01
-#define DR_P	0x00
-
-/* UART_IER Register */
-#define ELSI	0x04
-#define ETBEI	0x02
-#define ERBFI	0x01
-
-#define ELSI_P	0x02
-#define ETBEI_P	0x01
-#define ERBFI_P	0x00
-
-/* UART_IIR Register */
-#define STATUS(x)	((x << 1) & 0x06)
-#define NINT		0x01
-#define STATUS_P1	0x02
-#define STATUS_P0	0x01
-#define NINT_P		0x00
-#define IIR_TX_READY    0x02	/* UART_THR empty                               */
-#define IIR_RX_READY    0x04	/* Receive data ready                           */
-#define IIR_LINE_CHANGE 0x06	/* Receive line status                          */
-#define IIR_STATUS	0x06
-
-/* UART_GCTL Register */
-#define FFE	0x20
-#define FPE	0x10
-#define RPOLC	0x08
-#define TPOLC	0x04
-#define IREN	0x02
-#define UCEN	0x01
-
-#define FFE_P	0x05
-#define FPE_P	0x04
-#define RPOLC_P	0x03
-#define TPOLC_P	0x02
-#define IREN_P	0x01
-#define UCEN_P	0x00
-
 /*  *********  PARALLEL PERIPHERAL INTERFACE (PPI) MASKS ****************   */
 
 /*  PPI_CONTROL Masks         */
@@ -1230,44 +1090,6 @@
 #define ERR_TYP_P0		0x0E
 #define ERR_TYP_P1		0x0F
 
-/*/ ******************   PROGRAMMABLE FLAG MASKS  ********************* */
-
-/*  General Purpose IO (0xFFC00700 - 0xFFC007FF)  Masks */
-#define PF0         0x0001
-#define PF1         0x0002
-#define PF2         0x0004
-#define PF3         0x0008
-#define PF4         0x0010
-#define PF5         0x0020
-#define PF6         0x0040
-#define PF7         0x0080
-#define PF8         0x0100
-#define PF9         0x0200
-#define PF10        0x0400
-#define PF11        0x0800
-#define PF12        0x1000
-#define PF13        0x2000
-#define PF14        0x4000
-#define PF15        0x8000
-
-/*  General Purpose IO (0xFFC00700 - 0xFFC007FF)  BIT POSITIONS */
-#define PF0_P         0
-#define PF1_P         1
-#define PF2_P         2
-#define PF3_P         3
-#define PF4_P         4
-#define PF5_P         5
-#define PF6_P         6
-#define PF7_P         7
-#define PF8_P         8
-#define PF9_P         9
-#define PF10_P        10
-#define PF11_P        11
-#define PF12_P        12
-#define PF13_P        13
-#define PF14_P        14
-#define PF15_P        15
-
 /* *********************  ASYNCHRONOUS MEMORY CONTROLLER MASKS  ************* */
 
 /* AMGCTL Masks */
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf561/include/mach/gpio.h linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf561/include/mach/gpio.h
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf561/include/mach/gpio.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf561/include/mach/gpio.h	2011-03-14 21:20:32.000000000 -0400
@@ -62,4 +62,6 @@
 #define PORT_FIO1 GPIO_16
 #define PORT_FIO2 GPIO_32
 
+#include <mach-common/ports-f.h>
+
 #endif /* _MACH_GPIO_H_ */
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf561/include/mach/mem_map.h linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf561/include/mach/mem_map.h
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf561/include/mach/mem_map.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf561/include/mach/mem_map.h	2011-03-14 21:20:32.000000000 -0400
@@ -106,7 +106,7 @@
 #define COREA_L1_SCRATCH_START	0xFFB00000
 #define COREB_L1_SCRATCH_START	0xFF700000
 
-#ifdef __ASSEMBLY__
+#ifdef CONFIG_SMP
 
 /*
  * The following macros both return the address of the PDA for the
@@ -121,8 +121,7 @@
  * is allowed to use the specified Dreg for determining the PDA
  * address to be returned into Preg.
  */
-#ifdef CONFIG_SMP
-#define GET_PDA_SAFE(preg)		\
+# define GET_PDA_SAFE(preg)		\
 	preg.l = lo(DSPID);		\
 	preg.h = hi(DSPID);		\
 	preg = [preg];			\
@@ -158,7 +157,7 @@
 	preg = [preg];			\
 4:
 
-#define GET_PDA(preg, dreg)		\
+# define GET_PDA(preg, dreg)		\
 	preg.l = lo(DSPID);		\
 	preg.h = hi(DSPID);		\
 	dreg = [preg];			\
@@ -169,13 +168,17 @@
 	preg = [preg];			\
 1:					\
 
-#define GET_CPUID(preg, dreg)		\
+# define GET_CPUID(preg, dreg)		\
 	preg.l = lo(DSPID);		\
 	preg.h = hi(DSPID);		\
 	dreg = [preg];			\
 	dreg = ROT dreg BY -1;		\
 	dreg = CC;
 
+# ifndef __ASSEMBLY__
+
+#  include <asm/processor.h>
+
 static inline unsigned long get_l1_scratch_start_cpu(int cpu)
 {
 	return cpu ? COREB_L1_SCRATCH_START : COREA_L1_SCRATCH_START;
@@ -210,8 +213,7 @@ static inline unsigned long get_l1_data_
 	return get_l1_data_b_start_cpu(blackfin_core_id());
 }
 
+# endif /* __ASSEMBLY__ */
 #endif /* CONFIG_SMP */
 
-#endif /* __ASSEMBLY__ */
-
 #endif
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf561/include/mach/pll.h linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf561/include/mach/pll.h
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf561/include/mach/pll.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf561/include/mach/pll.h	2011-03-14 21:20:32.000000000 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright 2005-2009 Analog Devices Inc.
+ * Copyright 2005-2010 Analog Devices Inc.
  *
  * Licensed under the GPL-2 or later.
  */
@@ -7,57 +7,48 @@
 #ifndef _MACH_PLL_H
 #define _MACH_PLL_H
 
+#ifndef __ASSEMBLY__
+
+#ifdef CONFIG_SMP
+
 #include <asm/blackfin.h>
 #include <asm/irqflags.h>
+#include <mach/irq.h>
 
-/* Writing to PLL_CTL initiates a PLL relock sequence. */
-static __inline__ void bfin_write_PLL_CTL(unsigned int val)
-{
-	unsigned long flags, iwr0, iwr1;
+#define SUPPLE_0_WAKEUP ((IRQ_SUPPLE_0 - (IRQ_CORETMR + 1)) % 32)
 
-	if (val == bfin_read_PLL_CTL())
-		return;
+static inline void
+bfin_iwr_restore(unsigned long iwr0, unsigned long iwr1, unsigned long iwr2)
+{
+	unsigned long SICA_SICB_OFF = ((bfin_read_DSPID() & 0xff) ? 0x1000 : 0);
 
-	flags = hard_local_irq_save();
-	/* Enable the PLL Wakeup bit in SIC IWR */
-	iwr0 = bfin_read32(SICA_IWR0);
-	iwr1 = bfin_read32(SICA_IWR1);
-	/* Only allow PPL Wakeup) */
-	bfin_write32(SICA_IWR0, IWR_ENABLE(0));
-	bfin_write32(SICA_IWR1, 0);
+	bfin_write32(SIC_IWR0 + SICA_SICB_OFF, iwr0);
+	bfin_write32(SIC_IWR1 + SICA_SICB_OFF, iwr1);
+}
+#define bfin_iwr_restore bfin_iwr_restore
 
-	bfin_write16(PLL_CTL, val);
-	SSYNC();
-	asm("IDLE;");
+static inline void
+bfin_iwr_save(unsigned long niwr0, unsigned long niwr1, unsigned long niwr2,
+              unsigned long *iwr0, unsigned long *iwr1, unsigned long *iwr2)
+{
+	unsigned long SICA_SICB_OFF = ((bfin_read_DSPID() & 0xff) ? 0x1000 : 0);
 
-	bfin_write32(SICA_IWR0, iwr0);
-	bfin_write32(SICA_IWR1, iwr1);
-	hard_local_irq_restore(flags);
+	*iwr0 = bfin_read32(SIC_IWR0 + SICA_SICB_OFF);
+	*iwr1 = bfin_read32(SIC_IWR1 + SICA_SICB_OFF);
+	bfin_iwr_restore(niwr0, niwr1, niwr2);
 }
+#define bfin_iwr_save bfin_iwr_save
 
-/* Writing to VR_CTL initiates a PLL relock sequence. */
-static __inline__ void bfin_write_VR_CTL(unsigned int val)
+static inline void
+bfin_iwr_set_sup0(unsigned long *iwr0, unsigned long *iwr1, unsigned long *iwr2)
 {
-	unsigned long flags, iwr0, iwr1;
-
-	if (val == bfin_read_VR_CTL())
-		return;
+	bfin_iwr_save(0, IWR_ENABLE(SUPPLE_0_WAKEUP), 0, iwr0, iwr1, iwr2);
+}
 
-	flags = hard_local_irq_save();
-	/* Enable the PLL Wakeup bit in SIC IWR */
-	iwr0 = bfin_read32(SICA_IWR0);
-	iwr1 = bfin_read32(SICA_IWR1);
-	/* Only allow PPL Wakeup) */
-	bfin_write32(SICA_IWR0, IWR_ENABLE(0));
-	bfin_write32(SICA_IWR1, 0);
+#endif
 
-	bfin_write16(VR_CTL, val);
-	SSYNC();
-	asm("IDLE;");
+#endif
 
-	bfin_write32(SICA_IWR0, iwr0);
-	bfin_write32(SICA_IWR1, iwr1);
-	hard_local_irq_restore(flags);
-}
+#include <mach-common/pll.h>
 
-#endif /* _MACH_PLL_H */
+#endif
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf561/include/mach/smp.h linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf561/include/mach/smp.h
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf561/include/mach/smp.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf561/include/mach/smp.h	2011-03-14 21:20:32.000000000 -0400
@@ -7,6 +7,8 @@
 #ifndef _MACH_BF561_SMP
 #define _MACH_BF561_SMP
 
+/* This header has to stand alone to avoid circular deps */
+
 struct task_struct;
 
 void platform_init_cpus(void);
@@ -17,13 +19,13 @@ int platform_boot_secondary(unsigned int
 
 void platform_secondary_init(unsigned int cpu);
 
-void platform_request_ipi(int (*handler)(int, void *));
+void platform_request_ipi(int irq, /*irq_handler_t*/ void *handler);
 
-void platform_send_ipi(cpumask_t callmap);
+void platform_send_ipi(cpumask_t callmap, int irq);
 
-void platform_send_ipi_cpu(unsigned int cpu);
+void platform_send_ipi_cpu(unsigned int cpu, int irq);
 
-void platform_clear_ipi(unsigned int cpu);
+void platform_clear_ipi(unsigned int cpu, int irq);
 
 void bfin_local_timer_setup(void);
 
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf561/smp.c linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf561/smp.c
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-bf561/smp.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-bf561/smp.c	2011-03-14 21:20:32.000000000 -0400
@@ -86,12 +86,12 @@ int __cpuinit platform_boot_secondary(un
 
 	spin_lock(&boot_lock);
 
-	if ((bfin_read_SIC_SYSCR() & COREB_SRAM_INIT) == 0) {
+	if ((bfin_read_SYSCR() & COREB_SRAM_INIT) == 0) {
 		/* CoreB already running, sending ipi to wakeup it */
 		platform_send_ipi_cpu(cpu, IRQ_SUPPLE_0);
 	} else {
 		/* Kick CoreB, which should start execution from CORE_SRAM_BASE. */
-		bfin_write_SIC_SYSCR(bfin_read_SIC_SYSCR() & ~COREB_SRAM_INIT);
+		bfin_write_SYSCR(bfin_read_SYSCR() & ~COREB_SRAM_INIT);
 		SSYNC();
 	}
 
@@ -111,41 +111,46 @@ int __cpuinit platform_boot_secondary(un
 		panic("CPU%u: processor failed to boot\n", cpu);
 }
 
-void __init platform_request_ipi(irq_handler_t handler)
+static const char supple0[] = "IRQ_SUPPLE_0";
+static const char supple1[] = "IRQ_SUPPLE_1";
+void __init platform_request_ipi(int irq, void *handler)
 {
 	int ret;
+	const char *name = (irq == IRQ_SUPPLE_0) ? supple0 : supple1;
 
-	ret = request_irq(IRQ_SUPPLE_0, handler, IRQF_DISABLED,
-			  "Supplemental Interrupt0", handler);
+	ret = request_irq(irq, handler, IRQF_DISABLED | IRQF_PERCPU, name, handler);
 	if (ret)
-		panic("Cannot request supplemental interrupt 0 for IPI service");
+		panic("Cannot request %s for IPI service", name);
 }
 
-void platform_send_ipi(cpumask_t callmap)
+void platform_send_ipi(cpumask_t callmap, int irq)
 {
 	unsigned int cpu;
+	int offset = (irq == IRQ_SUPPLE_0) ? 6 : 8;
 
 	for_each_cpu_mask(cpu, callmap) {
 		BUG_ON(cpu >= 2);
 		SSYNC();
-		bfin_write_SICB_SYSCR(bfin_read_SICB_SYSCR() | (1 << (6 + cpu)));
+		bfin_write_SICB_SYSCR(bfin_read_SICB_SYSCR() | (1 << (offset + cpu)));
 		SSYNC();
 	}
 }
 
-void platform_send_ipi_cpu(unsigned int cpu)
+void platform_send_ipi_cpu(unsigned int cpu, int irq)
 {
+	int offset = (irq == IRQ_SUPPLE_0) ? 6 : 8;
 	BUG_ON(cpu >= 2);
 	SSYNC();
-	bfin_write_SICB_SYSCR(bfin_read_SICB_SYSCR() | (1 << (6 + cpu)));
+	bfin_write_SICB_SYSCR(bfin_read_SICB_SYSCR() | (1 << (offset + cpu)));
 	SSYNC();
 }
 
-void platform_clear_ipi(unsigned int cpu)
+void platform_clear_ipi(unsigned int cpu, int irq)
 {
+	int offset = (irq == IRQ_SUPPLE_0) ? 10 : 12;
 	BUG_ON(cpu >= 2);
 	SSYNC();
-	bfin_write_SICB_SYSCR(bfin_read_SICB_SYSCR() | (1 << (10 + cpu)));
+	bfin_write_SICB_SYSCR(bfin_read_SICB_SYSCR() | (1 << (offset + cpu)));
 	SSYNC();
 }
 
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-common/cache.S linux-libre-2.6.38-gnu1/arch/blackfin/mach-common/cache.S
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-common/cache.S	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-common/cache.S	2011-03-14 21:20:32.000000000 -0400
@@ -58,6 +58,8 @@
 1:
 .ifeqs "\flushins", BROK_FLUSH_INST
 	\flushins [P0++];
+	nop;
+	nop;
 2:	nop;
 .else
 2:	\flushins [P0++];
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-common/entry.S linux-libre-2.6.38-gnu1/arch/blackfin/mach-common/entry.S
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-common/entry.S	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-common/entry.S	2011-03-14 21:20:32.000000000 -0400
@@ -615,7 +615,7 @@ ENTRY(_system_call)
 #ifdef CONFIG_IPIPE
 	r0 = sp;
 	SP += -12;
-	call ___ipipe_syscall_root;
+	pseudo_long_call ___ipipe_syscall_root, p0;
 	SP += 12;
 	cc = r0 == 1;
 	if cc jump .Lsyscall_really_exit;
@@ -692,7 +692,7 @@ ENTRY(_system_call)
 	[--sp] = reti;
 	SP += 4; /* don't merge with next insn to keep the pattern obvious */
 	SP += -12;
-	call ___ipipe_sync_root;
+	pseudo_long_call ___ipipe_sync_root, p4;
 	SP += 12;
 	jump .Lresume_userspace_1;
 .Lsyscall_no_irqsync:
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-common/ints-priority.c linux-libre-2.6.38-gnu1/arch/blackfin/mach-common/ints-priority.c
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-common/ints-priority.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-common/ints-priority.c	2011-03-14 21:20:32.000000000 -0400
@@ -866,7 +866,6 @@ static void bfin_gpio_unmask_irq(unsigne
 	u32 pintbit = PINT_BIT(pint_val);
 	u32 bank = PINT_2_BANK(pint_val);
 
-	pint[bank]->request = pintbit;
 	pint[bank]->mask_set = pintbit;
 }
 
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-common/pm.c linux-libre-2.6.38-gnu1/arch/blackfin/mach-common/pm.c
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-common/pm.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-common/pm.c	2011-03-14 21:20:32.000000000 -0400
@@ -23,9 +23,6 @@
 
 void bfin_pm_suspend_standby_enter(void)
 {
-	unsigned long flags;
-
-	flags = hard_local_irq_save();
 	bfin_pm_standby_setup();
 
 #ifdef CONFIG_PM_BFIN_SLEEP_DEEPER
@@ -55,8 +52,6 @@ void bfin_pm_suspend_standby_enter(void)
 #else
 	bfin_write_SIC_IWR(IWR_DISABLE_ALL);
 #endif
-
-	hard_local_irq_restore(flags);
 }
 
 int bf53x_suspend_l1_mem(unsigned char *memptr)
@@ -127,7 +122,6 @@ static void flushinv_all_dcache(void)
 
 int bfin_pm_suspend_mem_enter(void)
 {
-	unsigned long flags;
 	int wakeup, ret;
 
 	unsigned char *memptr = kmalloc(L1_CODE_LENGTH + L1_DATA_A_LENGTH
@@ -149,12 +143,9 @@ int bfin_pm_suspend_mem_enter(void)
 	wakeup |= GPWE;
 #endif
 
-	flags = hard_local_irq_save();
-
 	ret = blackfin_dma_suspend();
 
 	if (ret) {
-		hard_local_irq_restore(flags);
 		kfree(memptr);
 		return ret;
 	}
@@ -178,7 +169,6 @@ int bfin_pm_suspend_mem_enter(void)
 	bfin_gpio_pm_hibernate_restore();
 	blackfin_dma_resume();
 
-	hard_local_irq_restore(flags);
 	kfree(memptr);
 
 	return 0;
@@ -233,7 +223,7 @@ static int bfin_pm_enter(suspend_state_t
 	return 0;
 }
 
-struct platform_suspend_ops bfin_pm_ops = {
+static const struct platform_suspend_ops bfin_pm_ops = {
 	.enter = bfin_pm_enter,
 	.valid	= bfin_pm_valid,
 };
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mach-common/smp.c linux-libre-2.6.38-gnu1/arch/blackfin/mach-common/smp.c
--- linux-libre-2.6.37-gnu1/arch/blackfin/mach-common/smp.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mach-common/smp.c	2011-03-14 21:20:32.000000000 -0400
@@ -19,6 +19,7 @@
 #include <linux/mm.h>
 #include <linux/cpu.h>
 #include <linux/smp.h>
+#include <linux/cpumask.h>
 #include <linux/seq_file.h>
 #include <linux/irq.h>
 #include <linux/slab.h>
@@ -43,12 +44,6 @@ void __cpuinitdata *init_retx_coreb, *in
 	*init_saved_seqstat_coreb, *init_saved_icplb_fault_addr_coreb,
 	*init_saved_dcplb_fault_addr_coreb;
 
-cpumask_t cpu_possible_map;
-EXPORT_SYMBOL(cpu_possible_map);
-
-cpumask_t cpu_online_map;
-EXPORT_SYMBOL(cpu_online_map);
-
 #define BFIN_IPI_RESCHEDULE   0
 #define BFIN_IPI_CALL_FUNC    1
 #define BFIN_IPI_CPU_STOP     2
@@ -65,8 +60,7 @@ struct smp_call_struct {
 	void (*func)(void *info);
 	void *info;
 	int wait;
-	cpumask_t pending;
-	cpumask_t waitmask;
+	cpumask_t *waitmask;
 };
 
 static struct blackfin_flush_data smp_flush_data;
@@ -74,15 +68,19 @@ static struct blackfin_flush_data smp_fl
 static DEFINE_SPINLOCK(stop_lock);
 
 struct ipi_message {
-	struct list_head list;
 	unsigned long type;
 	struct smp_call_struct call_struct;
 };
 
+/* A magic number - stress test shows this is safe for common cases */
+#define BFIN_IPI_MSGQ_LEN 5
+
+/* Simple FIFO buffer, overflow leads to panic */
 struct ipi_message_queue {
-	struct list_head head;
 	spinlock_t lock;
 	unsigned long count;
+	unsigned long head; /* head of the queue */
+	struct ipi_message ipi_message[BFIN_IPI_MSGQ_LEN];
 };
 
 static DEFINE_PER_CPU(struct ipi_message_queue, ipi_msg_queue);
@@ -121,7 +119,6 @@ static void ipi_call_function(unsigned i
 	func = msg->call_struct.func;
 	info = msg->call_struct.info;
 	wait = msg->call_struct.wait;
-	cpu_clear(cpu, msg->call_struct.pending);
 	func(info);
 	if (wait) {
 #ifdef __ARCH_SYNC_CORE_DCACHE
@@ -132,51 +129,57 @@ static void ipi_call_function(unsigned i
 		 */
 		resync_core_dcache();
 #endif
-		cpu_clear(cpu, msg->call_struct.waitmask);
-	} else
-		kfree(msg);
+		cpu_clear(cpu, *msg->call_struct.waitmask);
+	}
 }
 
-static irqreturn_t ipi_handler(int irq, void *dev_instance)
+/* Use IRQ_SUPPLE_0 to request reschedule.
+ * When returning from interrupt to user space,
+ * there is chance to reschedule */
+static irqreturn_t ipi_handler_int0(int irq, void *dev_instance)
+{
+	unsigned int cpu = smp_processor_id();
+
+	platform_clear_ipi(cpu, IRQ_SUPPLE_0);
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t ipi_handler_int1(int irq, void *dev_instance)
 {
 	struct ipi_message *msg;
 	struct ipi_message_queue *msg_queue;
 	unsigned int cpu = smp_processor_id();
+	unsigned long flags;
 
-	platform_clear_ipi(cpu);
+	platform_clear_ipi(cpu, IRQ_SUPPLE_1);
 
 	msg_queue = &__get_cpu_var(ipi_msg_queue);
-	msg_queue->count++;
 
-	spin_lock(&msg_queue->lock);
-	while (!list_empty(&msg_queue->head)) {
-		msg = list_entry(msg_queue->head.next, typeof(*msg), list);
-		list_del(&msg->list);
+	spin_lock_irqsave(&msg_queue->lock, flags);
+
+	while (msg_queue->count) {
+		msg = &msg_queue->ipi_message[msg_queue->head];
 		switch (msg->type) {
-		case BFIN_IPI_RESCHEDULE:
-			/* That's the easiest one; leave it to
-			 * return_from_int. */
-			kfree(msg);
-			break;
 		case BFIN_IPI_CALL_FUNC:
-			spin_unlock(&msg_queue->lock);
+			spin_unlock_irqrestore(&msg_queue->lock, flags);
 			ipi_call_function(cpu, msg);
-			spin_lock(&msg_queue->lock);
+			spin_lock_irqsave(&msg_queue->lock, flags);
 			break;
 		case BFIN_IPI_CPU_STOP:
-			spin_unlock(&msg_queue->lock);
+			spin_unlock_irqrestore(&msg_queue->lock, flags);
 			ipi_cpu_stop(cpu);
-			spin_lock(&msg_queue->lock);
-			kfree(msg);
+			spin_lock_irqsave(&msg_queue->lock, flags);
 			break;
 		default:
 			printk(KERN_CRIT "CPU%u: Unknown IPI message 0x%lx\n",
 			       cpu, msg->type);
-			kfree(msg);
 			break;
 		}
+		msg_queue->head++;
+		msg_queue->head %= BFIN_IPI_MSGQ_LEN;
+		msg_queue->count--;
 	}
-	spin_unlock(&msg_queue->lock);
+	spin_unlock_irqrestore(&msg_queue->lock, flags);
 	return IRQ_HANDLED;
 }
 
@@ -186,48 +189,47 @@ static void ipi_queue_init(void)
 	struct ipi_message_queue *msg_queue;
 	for_each_possible_cpu(cpu) {
 		msg_queue = &per_cpu(ipi_msg_queue, cpu);
-		INIT_LIST_HEAD(&msg_queue->head);
 		spin_lock_init(&msg_queue->lock);
 		msg_queue->count = 0;
+		msg_queue->head = 0;
 	}
 }
 
-int smp_call_function(void (*func)(void *info), void *info, int wait)
+static inline void smp_send_message(cpumask_t callmap, unsigned long type,
+					void (*func) (void *info), void *info, int wait)
 {
 	unsigned int cpu;
-	cpumask_t callmap;
-	unsigned long flags;
 	struct ipi_message_queue *msg_queue;
 	struct ipi_message *msg;
-
-	callmap = cpu_online_map;
-	cpu_clear(smp_processor_id(), callmap);
-	if (cpus_empty(callmap))
-		return 0;
-
-	msg = kmalloc(sizeof(*msg), GFP_ATOMIC);
-	if (!msg)
-		return -ENOMEM;
-	INIT_LIST_HEAD(&msg->list);
-	msg->call_struct.func = func;
-	msg->call_struct.info = info;
-	msg->call_struct.wait = wait;
-	msg->call_struct.pending = callmap;
-	msg->call_struct.waitmask = callmap;
-	msg->type = BFIN_IPI_CALL_FUNC;
+	unsigned long flags, next_msg;
+	cpumask_t waitmask = callmap; /* waitmask is shared by all cpus */
 
 	for_each_cpu_mask(cpu, callmap) {
 		msg_queue = &per_cpu(ipi_msg_queue, cpu);
 		spin_lock_irqsave(&msg_queue->lock, flags);
-		list_add_tail(&msg->list, &msg_queue->head);
+		if (msg_queue->count < BFIN_IPI_MSGQ_LEN) {
+			next_msg = (msg_queue->head + msg_queue->count)
+					% BFIN_IPI_MSGQ_LEN;
+			msg = &msg_queue->ipi_message[next_msg];
+			msg->type = type;
+			if (type == BFIN_IPI_CALL_FUNC) {
+				msg->call_struct.func = func;
+				msg->call_struct.info = info;
+				msg->call_struct.wait = wait;
+				msg->call_struct.waitmask = &waitmask;
+			}
+			msg_queue->count++;
+		} else
+			panic("IPI message queue overflow\n");
 		spin_unlock_irqrestore(&msg_queue->lock, flags);
-		platform_send_ipi_cpu(cpu);
+		platform_send_ipi_cpu(cpu, IRQ_SUPPLE_1);
 	}
+
 	if (wait) {
-		while (!cpus_empty(msg->call_struct.waitmask))
+		while (!cpus_empty(waitmask))
 			blackfin_dcache_invalidate_range(
-				(unsigned long)(&msg->call_struct.waitmask),
-				(unsigned long)(&msg->call_struct.waitmask));
+				(unsigned long)(&waitmask),
+				(unsigned long)(&waitmask));
 #ifdef __ARCH_SYNC_CORE_DCACHE
 		/*
 		 * Invalidate D cache in case shared data was changed by
@@ -235,8 +237,20 @@ int smp_call_function(void (*func)(void
 		 */
 		resync_core_dcache();
 #endif
-		kfree(msg);
 	}
+}
+
+int smp_call_function(void (*func)(void *info), void *info, int wait)
+{
+	cpumask_t callmap;
+
+	callmap = cpu_online_map;
+	cpu_clear(smp_processor_id(), callmap);
+	if (cpus_empty(callmap))
+		return 0;
+
+	smp_send_message(callmap, BFIN_IPI_CALL_FUNC, func, info, wait);
+
 	return 0;
 }
 EXPORT_SYMBOL_GPL(smp_call_function);
@@ -246,100 +260,39 @@ int smp_call_function_single(int cpuid,
 {
 	unsigned int cpu = cpuid;
 	cpumask_t callmap;
-	unsigned long flags;
-	struct ipi_message_queue *msg_queue;
-	struct ipi_message *msg;
 
 	if (cpu_is_offline(cpu))
 		return 0;
 	cpus_clear(callmap);
 	cpu_set(cpu, callmap);
 
-	msg = kmalloc(sizeof(*msg), GFP_ATOMIC);
-	if (!msg)
-		return -ENOMEM;
-	INIT_LIST_HEAD(&msg->list);
-	msg->call_struct.func = func;
-	msg->call_struct.info = info;
-	msg->call_struct.wait = wait;
-	msg->call_struct.pending = callmap;
-	msg->call_struct.waitmask = callmap;
-	msg->type = BFIN_IPI_CALL_FUNC;
-
-	msg_queue = &per_cpu(ipi_msg_queue, cpu);
-	spin_lock_irqsave(&msg_queue->lock, flags);
-	list_add_tail(&msg->list, &msg_queue->head);
-	spin_unlock_irqrestore(&msg_queue->lock, flags);
-	platform_send_ipi_cpu(cpu);
+	smp_send_message(callmap, BFIN_IPI_CALL_FUNC, func, info, wait);
 
-	if (wait) {
-		while (!cpus_empty(msg->call_struct.waitmask))
-			blackfin_dcache_invalidate_range(
-				(unsigned long)(&msg->call_struct.waitmask),
-				(unsigned long)(&msg->call_struct.waitmask));
-#ifdef __ARCH_SYNC_CORE_DCACHE
-		/*
-		 * Invalidate D cache in case shared data was changed by
-		 * other processors to ensure cache coherence.
-		 */
-		resync_core_dcache();
-#endif
-		kfree(msg);
-	}
 	return 0;
 }
 EXPORT_SYMBOL_GPL(smp_call_function_single);
 
 void smp_send_reschedule(int cpu)
 {
-	unsigned long flags;
-	struct ipi_message_queue *msg_queue;
-	struct ipi_message *msg;
-
+	/* simply trigger an ipi */
 	if (cpu_is_offline(cpu))
 		return;
-
-	msg = kzalloc(sizeof(*msg), GFP_ATOMIC);
-	if (!msg)
-		return;
-	INIT_LIST_HEAD(&msg->list);
-	msg->type = BFIN_IPI_RESCHEDULE;
-
-	msg_queue = &per_cpu(ipi_msg_queue, cpu);
-	spin_lock_irqsave(&msg_queue->lock, flags);
-	list_add_tail(&msg->list, &msg_queue->head);
-	spin_unlock_irqrestore(&msg_queue->lock, flags);
-	platform_send_ipi_cpu(cpu);
+	platform_send_ipi_cpu(cpu, IRQ_SUPPLE_0);
 
 	return;
 }
 
 void smp_send_stop(void)
 {
-	unsigned int cpu;
 	cpumask_t callmap;
-	unsigned long flags;
-	struct ipi_message_queue *msg_queue;
-	struct ipi_message *msg;
 
 	callmap = cpu_online_map;
 	cpu_clear(smp_processor_id(), callmap);
 	if (cpus_empty(callmap))
 		return;
 
-	msg = kzalloc(sizeof(*msg), GFP_ATOMIC);
-	if (!msg)
-		return;
-	INIT_LIST_HEAD(&msg->list);
-	msg->type = BFIN_IPI_CPU_STOP;
+	smp_send_message(callmap, BFIN_IPI_CPU_STOP, NULL, NULL, 0);
 
-	for_each_cpu_mask(cpu, callmap) {
-		msg_queue = &per_cpu(ipi_msg_queue, cpu);
-		spin_lock_irqsave(&msg_queue->lock, flags);
-		list_add_tail(&msg->list, &msg_queue->head);
-		spin_unlock_irqrestore(&msg_queue->lock, flags);
-		platform_send_ipi_cpu(cpu);
-	}
 	return;
 }
 
@@ -446,7 +399,8 @@ void __init smp_prepare_cpus(unsigned in
 {
 	platform_prepare_cpus(max_cpus);
 	ipi_queue_init();
-	platform_request_ipi(&ipi_handler);
+	platform_request_ipi(IRQ_SUPPLE_0, ipi_handler_int0);
+	platform_request_ipi(IRQ_SUPPLE_1, ipi_handler_int1);
 }
 
 void __init smp_cpus_done(unsigned int max_cpus)
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/Makefile linux-libre-2.6.38-gnu1/arch/blackfin/Makefile
--- linux-libre-2.6.37-gnu1/arch/blackfin/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -19,7 +19,7 @@ KBUILD_CFLAGS           += -mlong-calls
 endif
 KBUILD_AFLAGS           += $(call cc-option,-mno-fdpic)
 KBUILD_CFLAGS_MODULE    += -mlong-calls
-KBUILD_LDFLAGS_MODULE   += -m elf32bfin
+LDFLAGS                 += -m elf32bfin
 KALLSYMS         += --symbol-prefix=_
 
 KBUILD_DEFCONFIG := BF537-STAMP_defconfig
@@ -97,8 +97,11 @@ rev-$(CONFIG_BF_REV_0_6)  := 0.6
 rev-$(CONFIG_BF_REV_NONE) := none
 rev-$(CONFIG_BF_REV_ANY)  := any
 
-KBUILD_CFLAGS += -mcpu=$(cpu-y)-$(rev-y)
-KBUILD_AFLAGS += -mcpu=$(cpu-y)-$(rev-y)
+CPU_REV := $(cpu-y)-$(rev-y)
+export CPU_REV
+
+KBUILD_CFLAGS += -mcpu=$(CPU_REV)
+KBUILD_AFLAGS += -mcpu=$(CPU_REV)
 
 # - we utilize the silicon rev from the toolchain, so move it over to the checkflags
 CHECKFLAGS_SILICON = $(shell echo "" | $(CPP) $(KBUILD_CFLAGS) -dD - 2>/dev/null | awk '$$2 == "__SILICON_REVISION__" { print $$3 }')
diff -druNp linux-libre-2.6.37-gnu1/arch/blackfin/mm/sram-alloc.c linux-libre-2.6.38-gnu1/arch/blackfin/mm/sram-alloc.c
--- linux-libre-2.6.37-gnu1/arch/blackfin/mm/sram-alloc.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/blackfin/mm/sram-alloc.c	2011-03-14 21:20:32.000000000 -0400
@@ -704,18 +704,18 @@ int sram_free_with_lsl(const void *addr)
 {
 	struct sram_list_struct *lsl, **tmp;
 	struct mm_struct *mm = current->mm;
+	int ret = -1;
 
 	for (tmp = &mm->context.sram_list; *tmp; tmp = &(*tmp)->next)
-		if ((*tmp)->addr == addr)
-			goto found;
-	return -1;
-found:
-	lsl = *tmp;
-	sram_free(addr);
-	*tmp = lsl->next;
-	kfree(lsl);
+		if ((*tmp)->addr == addr) {
+			lsl = *tmp;
+			ret = sram_free(addr);
+			*tmp = lsl->next;
+			kfree(lsl);
+			break;
+		}
 
-	return 0;
+	return ret;
 }
 EXPORT_SYMBOL(sram_free_with_lsl);
 
diff -druNp linux-libre-2.6.37-gnu1/arch/cris/arch-v10/kernel/irq.c linux-libre-2.6.38-gnu1/arch/cris/arch-v10/kernel/irq.c
--- linux-libre-2.6.37-gnu1/arch/cris/arch-v10/kernel/irq.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/cris/arch-v10/kernel/irq.c	2011-03-14 21:20:32.000000000 -0400
@@ -104,43 +104,21 @@ static void (*interrupt[NR_IRQS])(void)
 	IRQ31_interrupt
 };
 
-static void enable_crisv10_irq(unsigned int irq);
-
-static unsigned int startup_crisv10_irq(unsigned int irq)
-{
-	enable_crisv10_irq(irq);
-	return 0;
-}
-
-#define shutdown_crisv10_irq	disable_crisv10_irq
-
-static void enable_crisv10_irq(unsigned int irq)
-{
-	crisv10_unmask_irq(irq);
-}
-
-static void disable_crisv10_irq(unsigned int irq)
-{
-	crisv10_mask_irq(irq);
-}
-
-static void ack_crisv10_irq(unsigned int irq)
+static void enable_crisv10_irq(struct irq_data *data)
 {
+	crisv10_unmask_irq(data->irq);
 }
 
-static void end_crisv10_irq(unsigned int irq)
+static void disable_crisv10_irq(struct irq_data *data)
 {
+	crisv10_mask_irq(data->irq);
 }
 
 static struct irq_chip crisv10_irq_type = {
-	.name =        "CRISv10",
-	.startup =     startup_crisv10_irq,
-	.shutdown =    shutdown_crisv10_irq,
-	.enable =      enable_crisv10_irq,
-	.disable =     disable_crisv10_irq,
-	.ack =         ack_crisv10_irq,
-	.end =         end_crisv10_irq,
-	.set_affinity = NULL
+	.name		= "CRISv10",
+	.irq_shutdown	= disable_crisv10_irq,
+	.irq_enable	= enable_crisv10_irq,
+	.irq_disable	= disable_crisv10_irq,
 };
 
 void weird_irq(void);
@@ -221,7 +199,8 @@ init_IRQ(void)
 
 	/* Initialize IRQ handler descriptors. */
 	for(i = 2; i < NR_IRQS; i++) {
-		irq_desc[i].chip = &crisv10_irq_type;
+		set_irq_desc_and_handler(i, &crisv10_irq_type,
+					 handle_simple_irq);
 		set_int_vector(i, interrupt[i]);
 	}
 
diff -druNp linux-libre-2.6.37-gnu1/arch/cris/arch-v32/kernel/irq.c linux-libre-2.6.38-gnu1/arch/cris/arch-v32/kernel/irq.c
--- linux-libre-2.6.37-gnu1/arch/cris/arch-v32/kernel/irq.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/cris/arch-v32/kernel/irq.c	2011-03-14 21:20:32.000000000 -0400
@@ -291,54 +291,33 @@ void crisv32_unmask_irq(int irq)
 }
 
 
-static unsigned int startup_crisv32_irq(unsigned int irq)
-{
-	crisv32_unmask_irq(irq);
-	return 0;
-}
-
-static void shutdown_crisv32_irq(unsigned int irq)
-{
-	crisv32_mask_irq(irq);
-}
-
-static void enable_crisv32_irq(unsigned int irq)
-{
-	crisv32_unmask_irq(irq);
-}
-
-static void disable_crisv32_irq(unsigned int irq)
-{
-	crisv32_mask_irq(irq);
-}
-
-static void ack_crisv32_irq(unsigned int irq)
+static void enable_crisv32_irq(struct irq_data *data)
 {
+	crisv32_unmask_irq(data->irq);
 }
 
-static void end_crisv32_irq(unsigned int irq)
+static void disable_crisv32_irq(struct irq_data *data)
 {
+	crisv32_mask_irq(data->irq);
 }
 
-int set_affinity_crisv32_irq(unsigned int irq, const struct cpumask *dest)
+static int set_affinity_crisv32_irq(struct irq_data *data,
+				    const struct cpumask *dest, bool force)
 {
 	unsigned long flags;
+
 	spin_lock_irqsave(&irq_lock, flags);
-	irq_allocations[irq - FIRST_IRQ].mask = *dest;
+	irq_allocations[data->irq - FIRST_IRQ].mask = *dest;
 	spin_unlock_irqrestore(&irq_lock, flags);
-
 	return 0;
 }
 
 static struct irq_chip crisv32_irq_type = {
-	.name =        "CRISv32",
-	.startup =     startup_crisv32_irq,
-	.shutdown =    shutdown_crisv32_irq,
-	.enable =      enable_crisv32_irq,
-	.disable =     disable_crisv32_irq,
-	.ack =         ack_crisv32_irq,
-	.end =         end_crisv32_irq,
-	.set_affinity = set_affinity_crisv32_irq
+	.name			= "CRISv32",
+	.irq_shutdown		= disable_crisv32_irq,
+	.irq_enable		= enable_crisv32_irq,
+	.irq_disable		= disable_crisv32_irq,
+	.irq_set_affinity	= set_affinity_crisv32_irq,
 };
 
 void
@@ -472,7 +451,8 @@ init_IRQ(void)
 
 	/* Point all IRQ's to bad handlers. */
 	for (i = FIRST_IRQ, j = 0; j < NR_IRQS; i++, j++) {
-		irq_desc[j].chip = &crisv32_irq_type;
+		set_irq_chip_and_handler(j, &crisv32_irq_type,
+					 handle_simple_irq);
 		set_exception_vector(i, interrupt[j]);
 	}
 
diff -druNp linux-libre-2.6.37-gnu1/arch/cris/arch-v32/lib/nand_init.S linux-libre-2.6.38-gnu1/arch/cris/arch-v32/lib/nand_init.S
--- linux-libre-2.6.37-gnu1/arch/cris/arch-v32/lib/nand_init.S	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/cris/arch-v32/lib/nand_init.S	2011-03-14 21:20:32.000000000 -0400
@@ -139,7 +139,7 @@ copy_nand_to_ram:
 	lsrq	8, $r4
 	move.b	$r4, [$r1]	; Row address
 	lsrq	8, $r4
-	move.b	$r4, [$r1]	; Row adddress
+	move.b	$r4, [$r1]	; Row address
 	moveq	20, $r4
 2:	bne	2b
 	subq	1, $r4
diff -druNp linux-libre-2.6.37-gnu1/arch/cris/configs/artpec_3_defconfig linux-libre-2.6.38-gnu1/arch/cris/configs/artpec_3_defconfig
--- linux-libre-2.6.37-gnu1/arch/cris/configs/artpec_3_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/cris/configs/artpec_3_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -2,7 +2,7 @@ CONFIG_EXPERIMENTAL=y
 # CONFIG_SWAP is not set
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_KALLSYMS is not set
 # CONFIG_HOTPLUG is not set
 # CONFIG_BLK_DEV_BSG is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/cris/configs/etrax-100lx_v2_defconfig linux-libre-2.6.38-gnu1/arch/cris/configs/etrax-100lx_v2_defconfig
--- linux-libre-2.6.37-gnu1/arch/cris/configs/etrax-100lx_v2_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/cris/configs/etrax-100lx_v2_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -2,7 +2,7 @@ CONFIG_EXPERIMENTAL=y
 # CONFIG_SWAP is not set
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_KALLSYMS is not set
 # CONFIG_HOTPLUG is not set
 # CONFIG_BLK_DEV_BSG is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/cris/configs/etraxfs_defconfig linux-libre-2.6.38-gnu1/arch/cris/configs/etraxfs_defconfig
--- linux-libre-2.6.37-gnu1/arch/cris/configs/etraxfs_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/cris/configs/etraxfs_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -2,7 +2,7 @@ CONFIG_EXPERIMENTAL=y
 # CONFIG_SWAP is not set
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_KALLSYMS is not set
 # CONFIG_HOTPLUG is not set
 # CONFIG_BLK_DEV_BSG is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/cris/include/asm/etraxgpio.h linux-libre-2.6.38-gnu1/arch/cris/include/asm/etraxgpio.h
--- linux-libre-2.6.37-gnu1/arch/cris/include/asm/etraxgpio.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/cris/include/asm/etraxgpio.h	2011-03-14 21:20:32.000000000 -0400
@@ -1,5 +1,5 @@
 /*
- * The following devices are accessable using this driver using
+ * The following devices are accessible using this driver using
  * GPIO_MAJOR (120) and a couple of minor numbers.
  *
  * For ETRAX 100LX (CONFIG_ETRAX_ARCH_V10):
diff -druNp linux-libre-2.6.37-gnu1/arch/cris/Kconfig linux-libre-2.6.38-gnu1/arch/cris/Kconfig
--- linux-libre-2.6.37-gnu1/arch/cris/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/cris/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -54,6 +54,8 @@ config CRIS
 	bool
 	default y
 	select HAVE_IDE
+	select HAVE_GENERIC_HARDIRQS
+	select GENERIC_HARDIRQS_NO_DEPRECATED
 
 config HZ
 	int
@@ -67,10 +69,6 @@ menu "General setup"
 
 source "fs/Kconfig.binfmt"
 
-config GENERIC_HARDIRQS
-	bool
-	default y
-
 config ETRAX_CMDLINE
 	string "Kernel command line"
 	default "root=/dev/mtdblock3"
diff -druNp linux-libre-2.6.37-gnu1/arch/cris/kernel/irq.c linux-libre-2.6.38-gnu1/arch/cris/kernel/irq.c
--- linux-libre-2.6.37-gnu1/arch/cris/kernel/irq.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/cris/kernel/irq.c	2011-03-14 21:20:32.000000000 -0400
@@ -62,7 +62,7 @@ int show_interrupts(struct seq_file *p,
 		for_each_online_cpu(j)
 			seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
 #endif
-		seq_printf(p, " %14s", irq_desc[i].chip->name);
+		seq_printf(p, " %14s", irq_desc[i].irq_data.chip->name);
 		seq_printf(p, "  %s", action->name);
 
 		for (action=action->next; action; action = action->next)
@@ -93,8 +93,8 @@ asmlinkage void do_IRQ(int irq, struct p
 		printk("do_IRQ: stack overflow: %lX\n", sp);
 		show_stack(NULL, (unsigned long *)sp);
 	}
-	__do_IRQ(irq);
-        irq_exit();
+	generic_handle_irq(irq);
+	irq_exit();
 	set_irq_regs(old_regs);
 }
 
diff -druNp linux-libre-2.6.37-gnu1/arch/cris/kernel/time.c linux-libre-2.6.38-gnu1/arch/cris/kernel/time.c
--- linux-libre-2.6.37-gnu1/arch/cris/kernel/time.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/cris/kernel/time.c	2011-03-14 21:20:32.000000000 -0400
@@ -86,7 +86,7 @@ int set_rtc_mmss(unsigned long nowtime)
 		CMOS_WRITE(real_seconds,RTC_SECONDS);
 		CMOS_WRITE(real_minutes,RTC_MINUTES);
 	} else {
-		printk(KERN_WARNING
+		printk_once(KERN_NOTICE
 		       "set_rtc_mmss: can't update from %d to %d\n",
 		       cmos_minutes, real_minutes);
 		retval = -1;
diff -druNp linux-libre-2.6.37-gnu1/arch/cris/kernel/vmlinux.lds.S linux-libre-2.6.38-gnu1/arch/cris/kernel/vmlinux.lds.S
--- linux-libre-2.6.37-gnu1/arch/cris/kernel/vmlinux.lds.S	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/cris/kernel/vmlinux.lds.S	2011-03-14 21:20:32.000000000 -0400
@@ -72,11 +72,6 @@ SECTIONS
 	INIT_TEXT_SECTION(PAGE_SIZE)
 	.init.data : { INIT_DATA }
 	.init.setup : { INIT_SETUP(16) }
-#ifdef CONFIG_ETRAX_ARCH_V32
-	__start___param = .;
-	__param : { *(__param) }
-	__stop___param = .;
-#endif
 	.initcall.init : {
 		INIT_CALLS
 	}
diff -druNp linux-libre-2.6.37-gnu1/arch/frv/defconfig linux-libre-2.6.38-gnu1/arch/frv/defconfig
--- linux-libre-2.6.37-gnu1/arch/frv/defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/frv/defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -3,7 +3,7 @@ CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_HOTPLUG is not set
 CONFIG_MMU=y
 CONFIG_FRV_OUTOFLINE_ATOMIC_OPS=y
diff -druNp linux-libre-2.6.37-gnu1/arch/frv/Kconfig linux-libre-2.6.38-gnu1/arch/frv/Kconfig
--- linux-libre-2.6.37-gnu1/arch/frv/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/frv/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -5,6 +5,7 @@ config FRV
 	select HAVE_ARCH_TRACEHOOK
 	select HAVE_IRQ_WORK
 	select HAVE_PERF_EVENTS
+	select HAVE_GENERIC_HARDIRQS
 
 config ZONE_DMA
 	bool
@@ -29,14 +30,6 @@ config GENERIC_CALIBRATE_DELAY
 	bool
 	default n
 
-config GENERIC_HARDIRQS
-	bool
-	default y
-
-config GENERIC_HARDIRQS_NO__DO_IRQ
-	bool
-	default y
-
 config TIME_LOW_RES
 	bool
 	default y
diff -druNp linux-libre-2.6.37-gnu1/arch/h8300/defconfig linux-libre-2.6.38-gnu1/arch/h8300/defconfig
--- linux-libre-2.6.37-gnu1/arch/h8300/defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/h8300/defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -1,7 +1,7 @@
 CONFIG_EXPERIMENTAL=y
 # CONFIG_LOCALVERSION_AUTO is not set
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_UID16 is not set
 # CONFIG_SYSCTL_SYSCALL is not set
 # CONFIG_KALLSYMS is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/h8300/Kconfig linux-libre-2.6.38-gnu1/arch/h8300/Kconfig
--- linux-libre-2.6.37-gnu1/arch/h8300/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/h8300/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -2,6 +2,8 @@ config H8300
 	bool
 	default y
 	select HAVE_IDE
+	select HAVE_GENERIC_HARDIRQS
+	select GENERIC_HARDIRQS_NO_DEPRECATED
 
 config SYMBOL_PREFIX
 	string
@@ -47,10 +49,6 @@ config GENERIC_HWEIGHT
 	bool
 	default y
 
-config GENERIC_HARDIRQS
-	bool
-	default y
-
 config GENERIC_CALIBRATE_DELAY
 	bool
 	default y
diff -druNp linux-libre-2.6.37-gnu1/arch/h8300/Kconfig.debug linux-libre-2.6.38-gnu1/arch/h8300/Kconfig.debug
--- linux-libre-2.6.37-gnu1/arch/h8300/Kconfig.debug	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/h8300/Kconfig.debug	2011-03-14 21:20:32.000000000 -0400
@@ -48,7 +48,7 @@ config DEFAULT_CMDLINE
 	  builtin kernel commandline enabled.
 
 config KERNEL_COMMAND
-	string "Buildin commmand string"
+	string "Buildin command string"
 	depends on DEFAULT_CMDLINE
 	help
 	  builtin kernel commandline strings.
diff -druNp linux-libre-2.6.37-gnu1/arch/h8300/kernel/irq.c linux-libre-2.6.38-gnu1/arch/h8300/kernel/irq.c
--- linux-libre-2.6.37-gnu1/arch/h8300/kernel/irq.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/h8300/kernel/irq.c	2011-03-14 21:20:32.000000000 -0400
@@ -38,34 +38,30 @@ static inline int is_ext_irq(unsigned in
 	return (irq >= EXT_IRQ0 && irq <= (EXT_IRQ0 + EXT_IRQS));
 }
 
-static void h8300_enable_irq(unsigned int irq)
-{
-	if (is_ext_irq(irq))
-		IER_REGS |= 1 << (irq - EXT_IRQ0);
-}
-
-static void h8300_disable_irq(unsigned int irq)
+static void h8300_enable_irq(struct irq_data *data)
 {
-	if (is_ext_irq(irq))
-		IER_REGS &= ~(1 << (irq - EXT_IRQ0));
+	if (is_ext_irq(data->irq))
+		IER_REGS |= 1 << (data->irq - EXT_IRQ0);
 }
 
-static void h8300_end_irq(unsigned int irq)
+static void h8300_disable_irq(struct irq_data *data)
 {
+	if (is_ext_irq(data->irq))
+		IER_REGS &= ~(1 << (data->irq - EXT_IRQ0));
 }
 
-static unsigned int h8300_startup_irq(unsigned int irq)
+static unsigned int h8300_startup_irq(struct irq_data *data)
 {
-	if (is_ext_irq(irq))
-		return h8300_enable_irq_pin(irq);
+	if (is_ext_irq(data->irq))
+		return h8300_enable_irq_pin(data->irq);
 	else
 		return 0;
 }
 
-static void h8300_shutdown_irq(unsigned int irq)
+static void h8300_shutdown_irq(struct irq_data *data)
 {
-	if (is_ext_irq(irq))
-		h8300_disable_irq_pin(irq);
+	if (is_ext_irq(data->irq))
+		h8300_disable_irq_pin(data->irq);
 }
 
 /*
@@ -73,12 +69,10 @@ static void h8300_shutdown_irq(unsigned
  */
 struct irq_chip h8300irq_chip = {
 	.name		= "H8300-INTC",
-	.startup	= h8300_startup_irq,
-	.shutdown	= h8300_shutdown_irq,
-	.enable		= h8300_enable_irq,
-	.disable	= h8300_disable_irq,
-	.ack		= NULL,
-	.end		= h8300_end_irq,
+	.irq_startup	= h8300_startup_irq,
+	.irq_shutdown	= h8300_shutdown_irq,
+	.irq_enable	= h8300_enable_irq,
+	.irq_disable	= h8300_disable_irq,
 };
 
 #if defined(CONFIG_RAMKERNEL)
@@ -160,18 +154,14 @@ void __init init_IRQ(void)
 
 	setup_vector();
 
-	for (c = 0; c < NR_IRQS; c++) {
-		irq_desc[c].status = IRQ_DISABLED;
-		irq_desc[c].action = NULL;
-		irq_desc[c].depth = 1;
-		irq_desc[c].chip = &h8300irq_chip;
-	}
+	for (c = 0; c < NR_IRQS; c++)
+		set_irq_chip_and_handler(c, &h8300irq_chip, handle_simple_irq);
 }
 
 asmlinkage void do_IRQ(int irq)
 {
 	irq_enter();
-	__do_IRQ(irq);
+	generic_handle_irq(irq);
 	irq_exit();
 }
 
@@ -192,7 +182,7 @@ int show_interrupts(struct seq_file *p,
 			goto unlock;
 		seq_printf(p, "%3d: ",i);
 		seq_printf(p, "%10u ", kstat_irqs(i));
-		seq_printf(p, " %14s", irq_desc[i].chip->name);
+		seq_printf(p, " %14s", irq_desc[i].irq_data.chip->name);
 		seq_printf(p, "-%-8s", irq_desc[i].name);
 		seq_printf(p, "  %s", action->name);
 
diff -druNp linux-libre-2.6.37-gnu1/arch/ia64/include/asm/io.h linux-libre-2.6.38-gnu1/arch/ia64/include/asm/io.h
--- linux-libre-2.6.37-gnu1/arch/ia64/include/asm/io.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/ia64/include/asm/io.h	2011-03-14 21:20:32.000000000 -0400
@@ -426,6 +426,11 @@ extern void __iomem * ioremap_nocache (u
 extern void iounmap (volatile void __iomem *addr);
 extern void __iomem * early_ioremap (unsigned long phys_addr, unsigned long size);
 extern void early_iounmap (volatile void __iomem *addr, unsigned long size);
+static inline void __iomem * ioremap_cache (unsigned long phys_addr, unsigned long size)
+{
+	return ioremap(phys_addr, size);
+}
+
 
 /*
  * String version of IO memory access ops:
diff -druNp linux-libre-2.6.37-gnu1/arch/ia64/include/asm/kvm_host.h linux-libre-2.6.38-gnu1/arch/ia64/include/asm/kvm_host.h
--- linux-libre-2.6.37-gnu1/arch/ia64/include/asm/kvm_host.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/ia64/include/asm/kvm_host.h	2011-03-14 21:20:32.000000000 -0400
@@ -590,6 +590,10 @@ int kvm_emulate_halt(struct kvm_vcpu *vc
 int kvm_pal_emul(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run);
 void kvm_sal_emul(struct kvm_vcpu *vcpu);
 
+#define __KVM_HAVE_ARCH_VM_ALLOC 1
+struct kvm *kvm_arch_alloc_vm(void);
+void kvm_arch_free_vm(struct kvm *kvm);
+
 #endif /* __ASSEMBLY__*/
 
 #endif
diff -druNp linux-libre-2.6.37-gnu1/arch/ia64/include/asm/page.h linux-libre-2.6.38-gnu1/arch/ia64/include/asm/page.h
--- linux-libre-2.6.37-gnu1/arch/ia64/include/asm/page.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/ia64/include/asm/page.h	2011-03-14 21:20:32.000000000 -0400
@@ -189,6 +189,7 @@ get_order (unsigned long size)
 # 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 /* !STRICT_MM_TYPECHECKS */
diff -druNp linux-libre-2.6.37-gnu1/arch/ia64/include/asm/processor.h linux-libre-2.6.38-gnu1/arch/ia64/include/asm/processor.h
--- linux-libre-2.6.37-gnu1/arch/ia64/include/asm/processor.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/ia64/include/asm/processor.h	2011-03-14 21:20:32.000000000 -0400
@@ -717,8 +717,9 @@ prefetchw (const void *x)
 #define spin_lock_prefetch(x)	prefetchw(x)
 
 extern unsigned long boot_option_idle_override;
-extern unsigned long idle_halt;
-extern unsigned long idle_nomwait;
+
+enum idle_boot_override {IDLE_NO_OVERRIDE=0, IDLE_HALT, IDLE_FORCE_MWAIT,
+			 IDLE_NOMWAIT, IDLE_POLL};
 
 #endif /* !__ASSEMBLY__ */
 
diff -druNp linux-libre-2.6.37-gnu1/arch/ia64/Kconfig linux-libre-2.6.38-gnu1/arch/ia64/Kconfig
--- linux-libre-2.6.37-gnu1/arch/ia64/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/ia64/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -22,6 +22,10 @@ config IA64
 	select HAVE_KVM
 	select HAVE_ARCH_TRACEHOOK
 	select HAVE_DMA_API_DEBUG
+	select HAVE_GENERIC_HARDIRQS
+	select GENERIC_IRQ_PROBE
+	select GENERIC_PENDING_IRQ if SMP
+	select IRQ_PER_CPU
 	default y
 	help
 	  The Itanium Processor Family is Intel's 64-bit successor to
@@ -678,28 +682,6 @@ source "arch/ia64/kvm/Kconfig"
 
 source "lib/Kconfig"
 
-#
-# Use the generic interrupt handling code in kernel/irq/:
-#
-config GENERIC_HARDIRQS
-	def_bool y
-
-config GENERIC_HARDIRQS_NO__DO_IRQ
-	def_bool y
-
-config GENERIC_IRQ_PROBE
-	bool
-	default y
-
-config GENERIC_PENDING_IRQ
-	bool
-	depends on GENERIC_HARDIRQS && SMP
-	default y
-
-config IRQ_PER_CPU
-	bool
-	default y
-
 config IOMMU_HELPER
 	def_bool (IA64_HP_ZX1 || IA64_HP_ZX1_SWIOTLB || IA64_GENERIC || SWIOTLB)
 
diff -druNp linux-libre-2.6.37-gnu1/arch/ia64/kernel/acpi.c linux-libre-2.6.38-gnu1/arch/ia64/kernel/acpi.c
--- linux-libre-2.6.37-gnu1/arch/ia64/kernel/acpi.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/ia64/kernel/acpi.c	2011-03-14 21:20:32.000000000 -0400
@@ -477,6 +477,12 @@ acpi_numa_processor_affinity_init(struct
 	if (!(pa->flags & ACPI_SRAT_CPU_ENABLED))
 		return;
 
+	if (srat_num_cpus >= ARRAY_SIZE(node_cpuid)) {
+		printk_once(KERN_WARNING
+			    "node_cpuid[%ld] is too small, may not be able to use all cpus\n",
+			    ARRAY_SIZE(node_cpuid));
+		return;
+	}
 	pxm = get_processor_proximity_domain(pa);
 
 	/* record this node in proximity bitmap */
diff -druNp linux-libre-2.6.37-gnu1/arch/ia64/kernel/irq_ia64.c linux-libre-2.6.38-gnu1/arch/ia64/kernel/irq_ia64.c
--- linux-libre-2.6.37-gnu1/arch/ia64/kernel/irq_ia64.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/ia64/kernel/irq_ia64.c	2011-03-14 21:20:32.000000000 -0400
@@ -633,7 +633,7 @@ ia64_native_register_percpu_irq (ia64_ve
 	BUG_ON(bind_irq_vector(irq, vec, CPU_MASK_ALL));
 	desc = irq_desc + irq;
 	desc->status |= IRQ_PER_CPU;
-	desc->chip = &irq_type_ia64_lsapic;
+	set_irq_chip(irq, &irq_type_ia64_lsapic);
 	if (action)
 		setup_irq(irq, action);
 	set_irq_handler(irq, handle_percpu_irq);
diff -druNp linux-libre-2.6.37-gnu1/arch/ia64/kernel/perfmon.c linux-libre-2.6.38-gnu1/arch/ia64/kernel/perfmon.c
--- linux-libre-2.6.37-gnu1/arch/ia64/kernel/perfmon.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/ia64/kernel/perfmon.c	2011-03-14 21:20:32.000000000 -0400
@@ -617,11 +617,14 @@ pfm_get_unmapped_area(struct file *file,
 	return get_unmapped_area(file, addr, len, pgoff, flags);
 }
 
+/* forward declaration */
+static const struct dentry_operations pfmfs_dentry_operations;
 
 static struct dentry *
 pfmfs_mount(struct file_system_type *fs_type, int flags, const char *dev_name, void *data)
 {
-	return mount_pseudo(fs_type, "pfm:", NULL, PFMFS_MAGIC);
+	return mount_pseudo(fs_type, "pfm:", NULL, &pfmfs_dentry_operations,
+			PFMFS_MAGIC);
 }
 
 static struct file_system_type pfm_fs_type = {
@@ -829,10 +832,9 @@ pfm_rvmalloc(unsigned long size)
 	unsigned long addr;
 
 	size = PAGE_ALIGN(size);
-	mem  = vmalloc(size);
+	mem  = vzalloc(size);
 	if (mem) {
 		//printk("perfmon: CPU%d pfm_rvmalloc(%ld)=%p\n", smp_processor_id(), size, mem);
-		memset(mem, 0, size);
 		addr = (unsigned long)mem;
 		while (size > 0) {
 			pfm_reserve_page(addr);
@@ -1542,7 +1544,7 @@ pfm_exit_smpl_buffer(pfm_buffer_fmt_t *f
  * any operations on the root directory. However, we need a non-trivial
  * d_name - pfm: will go nicely and kill the special-casing in procfs.
  */
-static struct vfsmount *pfmfs_mnt;
+static struct vfsmount *pfmfs_mnt __read_mostly;
 
 static int __init
 init_pfm_fs(void)
@@ -2185,7 +2187,7 @@ static const struct file_operations pfm_
 };
 
 static int
-pfmfs_delete_dentry(struct dentry *dentry)
+pfmfs_delete_dentry(const struct dentry *dentry)
 {
 	return 1;
 }
@@ -2233,7 +2235,6 @@ pfm_alloc_file(pfm_context_t *ctx)
 	}
 	path.mnt = mntget(pfmfs_mnt);
 
-	path.dentry->d_op = &pfmfs_dentry_operations;
 	d_add(path.dentry, inode);
 
 	file = alloc_file(&path, FMODE_READ, &pfm_file_ops);
diff -druNp linux-libre-2.6.37-gnu1/arch/ia64/kernel/process.c linux-libre-2.6.38-gnu1/arch/ia64/kernel/process.c
--- linux-libre-2.6.37-gnu1/arch/ia64/kernel/process.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/ia64/kernel/process.c	2011-03-14 21:20:32.000000000 -0400
@@ -53,12 +53,8 @@
 
 void (*ia64_mark_idle)(int);
 
-unsigned long boot_option_idle_override = 0;
+unsigned long boot_option_idle_override = IDLE_NO_OVERRIDE;
 EXPORT_SYMBOL(boot_option_idle_override);
-unsigned long idle_halt;
-EXPORT_SYMBOL(idle_halt);
-unsigned long idle_nomwait;
-EXPORT_SYMBOL(idle_nomwait);
 void (*pm_idle) (void);
 EXPORT_SYMBOL(pm_idle);
 void (*pm_power_off) (void);
diff -druNp linux-libre-2.6.37-gnu1/arch/ia64/kernel/smp.c linux-libre-2.6.38-gnu1/arch/ia64/kernel/smp.c
--- linux-libre-2.6.37-gnu1/arch/ia64/kernel/smp.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/ia64/kernel/smp.c	2011-03-14 21:20:32.000000000 -0400
@@ -293,6 +293,7 @@ smp_flush_tlb_all (void)
 void
 smp_flush_tlb_mm (struct mm_struct *mm)
 {
+	cpumask_var_t cpus;
 	preempt_disable();
 	/* this happens for the common case of a single-threaded fork():  */
 	if (likely(mm == current->active_mm && atomic_read(&mm->mm_users) == 1))
@@ -301,9 +302,15 @@ smp_flush_tlb_mm (struct mm_struct *mm)
 		preempt_enable();
 		return;
 	}
-
-	smp_call_function_many(mm_cpumask(mm),
-		(void (*)(void *))local_finish_flush_tlb_mm, mm, 1);
+	if (!alloc_cpumask_var(&cpus, GFP_ATOMIC)) {
+		smp_call_function((void (*)(void *))local_finish_flush_tlb_mm,
+			mm, 1);
+	} else {
+		cpumask_copy(cpus, mm_cpumask(mm));
+		smp_call_function_many(cpus,
+			(void (*)(void *))local_finish_flush_tlb_mm, mm, 1);
+		free_cpumask_var(cpus);
+	}
 	local_irq_disable();
 	local_finish_flush_tlb_mm(mm);
 	local_irq_enable();
diff -druNp linux-libre-2.6.37-gnu1/arch/ia64/kernel/time.c linux-libre-2.6.38-gnu1/arch/ia64/kernel/time.c
--- linux-libre-2.6.37-gnu1/arch/ia64/kernel/time.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/ia64/kernel/time.c	2011-03-14 21:20:32.000000000 -0400
@@ -168,7 +168,7 @@ timer_interrupt (int irq, void *dev_id)
 {
 	unsigned long new_itm;
 
-	if (unlikely(cpu_is_offline(smp_processor_id()))) {
+	if (cpu_is_offline(smp_processor_id())) {
 		return IRQ_HANDLED;
 	}
 
diff -druNp linux-libre-2.6.37-gnu1/arch/ia64/kvm/kvm-ia64.c linux-libre-2.6.38-gnu1/arch/ia64/kvm/kvm-ia64.c
--- linux-libre-2.6.37-gnu1/arch/ia64/kvm/kvm-ia64.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/ia64/kvm/kvm-ia64.c	2011-03-14 21:20:32.000000000 -0400
@@ -749,7 +749,7 @@ out:
 	return r;
 }
 
-static struct kvm *kvm_alloc_kvm(void)
+struct kvm *kvm_arch_alloc_vm(void)
 {
 
 	struct kvm *kvm;
@@ -760,7 +760,7 @@ static struct kvm *kvm_alloc_kvm(void)
 	vm_base = __get_free_pages(GFP_KERNEL, get_order(KVM_VM_DATA_SIZE));
 
 	if (!vm_base)
-		return ERR_PTR(-ENOMEM);
+		return NULL;
 
 	memset((void *)vm_base, 0, KVM_VM_DATA_SIZE);
 	kvm = (struct kvm *)(vm_base +
@@ -806,10 +806,12 @@ static void kvm_build_io_pmt(struct kvm
 #define GUEST_PHYSICAL_RR4	0x2739
 #define VMM_INIT_RR		0x1660
 
-static void kvm_init_vm(struct kvm *kvm)
+int kvm_arch_init_vm(struct kvm *kvm)
 {
 	BUG_ON(!kvm);
 
+	kvm->arch.is_sn2 = ia64_platform_is("sn2");
+
 	kvm->arch.metaphysical_rr0 = GUEST_PHYSICAL_RR0;
 	kvm->arch.metaphysical_rr4 = GUEST_PHYSICAL_RR4;
 	kvm->arch.vmm_init_rr = VMM_INIT_RR;
@@ -823,21 +825,8 @@ static void kvm_init_vm(struct kvm *kvm)
 
 	/* Reserve bit 0 of irq_sources_bitmap for userspace irq source */
 	set_bit(KVM_USERSPACE_IRQ_SOURCE_ID, &kvm->arch.irq_sources_bitmap);
-}
-
-struct  kvm *kvm_arch_create_vm(void)
-{
-	struct kvm *kvm = kvm_alloc_kvm();
-
-	if (IS_ERR(kvm))
-		return ERR_PTR(-ENOMEM);
-
-	kvm->arch.is_sn2 = ia64_platform_is("sn2");
-
-	kvm_init_vm(kvm);
-
-	return kvm;
 
+	return 0;
 }
 
 static int kvm_vm_ioctl_get_irqchip(struct kvm *kvm,
@@ -962,7 +951,9 @@ long kvm_arch_vm_ioctl(struct file *filp
 			goto out;
 		r = kvm_setup_default_irq_routing(kvm);
 		if (r) {
+			mutex_lock(&kvm->slots_lock);
 			kvm_ioapic_destroy(kvm);
+			mutex_unlock(&kvm->slots_lock);
 			goto out;
 		}
 		break;
@@ -1357,7 +1348,7 @@ int kvm_arch_vcpu_ioctl_set_guest_debug(
 	return -EINVAL;
 }
 
-static void free_kvm(struct kvm *kvm)
+void kvm_arch_free_vm(struct kvm *kvm)
 {
 	unsigned long vm_base = kvm->arch.vm_base;
 
@@ -1399,9 +1390,6 @@ void kvm_arch_destroy_vm(struct kvm *kvm
 #endif
 	kfree(kvm->arch.vioapic);
 	kvm_release_vm_pages(kvm);
-	kvm_free_physmem(kvm);
-	cleanup_srcu_struct(&kvm->srcu);
-	free_kvm(kvm);
 }
 
 void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
diff -druNp linux-libre-2.6.37-gnu1/arch/ia64/kvm/mmio.c linux-libre-2.6.38-gnu1/arch/ia64/kvm/mmio.c
--- linux-libre-2.6.37-gnu1/arch/ia64/kvm/mmio.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/ia64/kvm/mmio.c	2011-03-14 21:20:32.000000000 -0400
@@ -130,7 +130,7 @@ static void mmio_access(struct kvm_vcpu
 
 	local_irq_save(psr);
 
-	/*Intercept the acces for PIB range*/
+	/*Intercept the access for PIB range*/
 	if (iot == GPFN_PIB) {
 		if (!dir)
 			lsapic_write(vcpu, src_pa, s, *dest);
diff -druNp linux-libre-2.6.37-gnu1/arch/ia64/mm/hugetlbpage.c linux-libre-2.6.38-gnu1/arch/ia64/mm/hugetlbpage.c
--- linux-libre-2.6.37-gnu1/arch/ia64/mm/hugetlbpage.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/ia64/mm/hugetlbpage.c	2011-03-14 21:20:32.000000000 -0400
@@ -38,7 +38,7 @@ huge_pte_alloc(struct mm_struct *mm, uns
 	if (pud) {
 		pmd = pmd_alloc(mm, pud, taddr);
 		if (pmd)
-			pte = pte_alloc_map(mm, pmd, taddr);
+			pte = pte_alloc_map(mm, NULL, pmd, taddr);
 	}
 	return pte;
 }
diff -druNp linux-libre-2.6.37-gnu1/arch/Kconfig linux-libre-2.6.38-gnu1/arch/Kconfig
--- linux-libre-2.6.37-gnu1/arch/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -175,4 +175,7 @@ config HAVE_PERF_EVENTS_NMI
 config HAVE_ARCH_JUMP_LABEL
 	bool
 
+config HAVE_ARCH_MUTEX_CPU_RELAX
+	bool
+
 source "kernel/gcov/Kconfig"
diff -druNp linux-libre-2.6.37-gnu1/arch/m32r/configs/m32700ut.smp_defconfig linux-libre-2.6.38-gnu1/arch/m32r/configs/m32700ut.smp_defconfig
--- linux-libre-2.6.37-gnu1/arch/m32r/configs/m32700ut.smp_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/m32r/configs/m32700ut.smp_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@ CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=15
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_KALLSYMS is not set
 # CONFIG_FUTEX is not set
 # CONFIG_EPOLL is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/m32r/configs/m32700ut.up_defconfig linux-libre-2.6.38-gnu1/arch/m32r/configs/m32700ut.up_defconfig
--- linux-libre-2.6.37-gnu1/arch/m32r/configs/m32700ut.up_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/m32r/configs/m32700ut.up_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@ CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_KALLSYMS is not set
 # CONFIG_FUTEX is not set
 # CONFIG_EPOLL is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/m32r/configs/mappi2.opsp_defconfig linux-libre-2.6.38-gnu1/arch/m32r/configs/mappi2.opsp_defconfig
--- linux-libre-2.6.37-gnu1/arch/m32r/configs/mappi2.opsp_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/m32r/configs/mappi2.opsp_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -4,7 +4,7 @@ CONFIG_BSD_PROCESS_ACCT=y
 CONFIG_IKCONFIG=y
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_KALLSYMS is not set
 # CONFIG_FUTEX is not set
 # CONFIG_EPOLL is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/m32r/configs/mappi2.vdec2_defconfig linux-libre-2.6.38-gnu1/arch/m32r/configs/mappi2.vdec2_defconfig
--- linux-libre-2.6.37-gnu1/arch/m32r/configs/mappi2.vdec2_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/m32r/configs/mappi2.vdec2_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -4,7 +4,7 @@ CONFIG_BSD_PROCESS_ACCT=y
 CONFIG_IKCONFIG=y
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_KALLSYMS is not set
 # CONFIG_FUTEX is not set
 # CONFIG_EPOLL is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/m32r/configs/mappi3.smp_defconfig linux-libre-2.6.38-gnu1/arch/m32r/configs/mappi3.smp_defconfig
--- linux-libre-2.6.37-gnu1/arch/m32r/configs/mappi3.smp_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/m32r/configs/mappi3.smp_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@ CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=15
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_KALLSYMS is not set
 # CONFIG_FUTEX is not set
 # CONFIG_EPOLL is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/m32r/configs/mappi.nommu_defconfig linux-libre-2.6.38-gnu1/arch/m32r/configs/mappi.nommu_defconfig
--- linux-libre-2.6.37-gnu1/arch/m32r/configs/mappi.nommu_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/m32r/configs/mappi.nommu_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -3,7 +3,7 @@ CONFIG_BSD_PROCESS_ACCT=y
 CONFIG_IKCONFIG=y
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_KALLSYMS is not set
 # CONFIG_FUTEX is not set
 # CONFIG_EPOLL is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/m32r/configs/mappi.smp_defconfig linux-libre-2.6.38-gnu1/arch/m32r/configs/mappi.smp_defconfig
--- linux-libre-2.6.37-gnu1/arch/m32r/configs/mappi.smp_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/m32r/configs/mappi.smp_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@ CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=15
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_KALLSYMS is not set
 # CONFIG_FUTEX is not set
 # CONFIG_EPOLL is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/m32r/configs/mappi.up_defconfig linux-libre-2.6.38-gnu1/arch/m32r/configs/mappi.up_defconfig
--- linux-libre-2.6.37-gnu1/arch/m32r/configs/mappi.up_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/m32r/configs/mappi.up_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@ CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_KALLSYMS is not set
 # CONFIG_FUTEX is not set
 # CONFIG_EPOLL is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/m32r/configs/oaks32r_defconfig linux-libre-2.6.38-gnu1/arch/m32r/configs/oaks32r_defconfig
--- linux-libre-2.6.37-gnu1/arch/m32r/configs/oaks32r_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/m32r/configs/oaks32r_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -2,7 +2,7 @@ CONFIG_EXPERIMENTAL=y
 CONFIG_BSD_PROCESS_ACCT=y
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_KALLSYMS is not set
 # CONFIG_FUTEX is not set
 # CONFIG_EPOLL is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/m32r/configs/opsput_defconfig linux-libre-2.6.38-gnu1/arch/m32r/configs/opsput_defconfig
--- linux-libre-2.6.37-gnu1/arch/m32r/configs/opsput_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/m32r/configs/opsput_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -4,7 +4,7 @@ CONFIG_BSD_PROCESS_ACCT=y
 CONFIG_IKCONFIG=y
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_KALLSYMS is not set
 # CONFIG_FUTEX is not set
 # CONFIG_EPOLL is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/m32r/configs/usrv_defconfig linux-libre-2.6.38-gnu1/arch/m32r/configs/usrv_defconfig
--- linux-libre-2.6.37-gnu1/arch/m32r/configs/usrv_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/m32r/configs/usrv_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@ CONFIG_BSD_PROCESS_ACCT=y
 CONFIG_LOG_BUF_SHIFT=15
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 CONFIG_KALLSYMS_EXTRA_PASS=y
 CONFIG_SLAB=y
 CONFIG_MODULES=y
diff -druNp linux-libre-2.6.37-gnu1/arch/m32r/Kconfig linux-libre-2.6.38-gnu1/arch/m32r/Kconfig
--- linux-libre-2.6.37-gnu1/arch/m32r/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/m32r/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -7,6 +7,9 @@ config M32R
 	select HAVE_KERNEL_GZIP
 	select HAVE_KERNEL_BZIP2
 	select HAVE_KERNEL_LZMA
+	select HAVE_GENERIC_HARDIRQS
+	select GENERIC_HARDIRQS_NO_DEPRECATED
+	select GENERIC_IRQ_PROBE
 
 config SBUS
 	bool
@@ -19,14 +22,6 @@ config ZONE_DMA
 	bool
 	default y
 
-config GENERIC_HARDIRQS
-	bool
-	default y
-
-config GENERIC_IRQ_PROBE
-	bool
-	default y
-
 config NO_IOPORT
 	def_bool y
 
diff -druNp linux-libre-2.6.37-gnu1/arch/m32r/kernel/irq.c linux-libre-2.6.38-gnu1/arch/m32r/kernel/irq.c
--- linux-libre-2.6.37-gnu1/arch/m32r/kernel/irq.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/m32r/kernel/irq.c	2011-03-14 21:20:32.000000000 -0400
@@ -40,8 +40,10 @@ int show_interrupts(struct seq_file *p,
 	}
 
 	if (i < NR_IRQS) {
-		raw_spin_lock_irqsave(&irq_desc[i].lock, flags);
-		action = irq_desc[i].action;
+		struct irq_desc *desc = irq_to_desc(i);
+
+		raw_spin_lock_irqsave(&desc->lock, flags);
+		action = desc->action;
 		if (!action)
 			goto skip;
 		seq_printf(p, "%3d: ",i);
@@ -51,7 +53,7 @@ int show_interrupts(struct seq_file *p,
 		for_each_online_cpu(j)
 			seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
 #endif
-		seq_printf(p, " %14s", irq_desc[i].chip->name);
+		seq_printf(p, " %14s", desc->irq_data.chip->name);
 		seq_printf(p, "  %s", action->name);
 
 		for (action=action->next; action; action = action->next)
@@ -59,7 +61,7 @@ int show_interrupts(struct seq_file *p,
 
 		seq_putc(p, '\n');
 skip:
-		raw_spin_unlock_irqrestore(&irq_desc[i].lock, flags);
+		raw_spin_unlock_irqrestore(&desc->lock, flags);
 	}
 	return 0;
 }
@@ -78,7 +80,7 @@ asmlinkage unsigned int do_IRQ(int irq,
 #ifdef CONFIG_DEBUG_STACKOVERFLOW
 	/* FIXME M32R */
 #endif
-	__do_IRQ(irq);
+	generic_handle_irq(irq);
 	irq_exit();
 	set_irq_regs(old_regs);
 
diff -druNp linux-libre-2.6.37-gnu1/arch/m32r/platforms/m32104ut/setup.c linux-libre-2.6.38-gnu1/arch/m32r/platforms/m32104ut/setup.c
--- linux-libre-2.6.37-gnu1/arch/m32r/platforms/m32104ut/setup.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/m32r/platforms/m32104ut/setup.c	2011-03-14 21:20:32.000000000 -0400
@@ -39,39 +39,30 @@ static void enable_m32104ut_irq(unsigned
 	outl(data, port);
 }
 
-static void mask_and_ack_m32104ut(unsigned int irq)
-{
-	disable_m32104ut_irq(irq);
-}
-
-static void end_m32104ut_irq(unsigned int irq)
+static void mask_m32104ut_irq(struct irq_data *data)
 {
-	enable_m32104ut_irq(irq);
+	disable_m32104ut_irq(data->irq);
 }
 
-static unsigned int startup_m32104ut_irq(unsigned int irq)
+static void unmask_m32104ut_irq(struct irq_data *data)
 {
-	enable_m32104ut_irq(irq);
-	return (0);
+	enable_m32104ut_irq(data->irq);
 }
 
-static void shutdown_m32104ut_irq(unsigned int irq)
+static void shutdown_m32104ut_irq(struct irq_data *data)
 {
-	unsigned long port;
+	unsigned int irq = data->irq;
+	unsigned long port = irq2port(irq);
 
-	port = irq2port(irq);
 	outl(M32R_ICUCR_ILEVEL7, port);
 }
 
 static struct irq_chip m32104ut_irq_type =
 {
-	.name = "M32104UT-IRQ",
-	.startup = startup_m32104ut_irq,
-	.shutdown = shutdown_m32104ut_irq,
-	.enable = enable_m32104ut_irq,
-	.disable = disable_m32104ut_irq,
-	.ack = mask_and_ack_m32104ut,
-	.end = end_m32104ut_irq
+	.name		= "M32104UT-IRQ",
+	.irq_shutdown	= shutdown_m32104ut_irq,
+	.irq_unmask	= unmask_m32104ut_irq,
+	.irq_mask	= mask_m32104ut_irq,
 };
 
 void __init init_IRQ(void)
@@ -85,36 +76,29 @@ void __init init_IRQ(void)
 
 #if defined(CONFIG_SMC91X)
 	/* INT#0: LAN controller on M32104UT-LAN (SMC91C111)*/
-	irq_desc[M32R_IRQ_INT0].status = IRQ_DISABLED;
-	irq_desc[M32R_IRQ_INT0].chip = &m32104ut_irq_type;
-	irq_desc[M32R_IRQ_INT0].action = 0;
-	irq_desc[M32R_IRQ_INT0].depth = 1;
-	icu_data[M32R_IRQ_INT0].icucr = M32R_ICUCR_IEN | M32R_ICUCR_ISMOD11; /* "H" level sense */
+	set_irq_chip_and_handler(M32R_IRQ_INT0, &m32104ut_irq_type,
+				 handle_level_irq);
+	/* "H" level sense */
+	cu_data[M32R_IRQ_INT0].icucr = M32R_ICUCR_IEN | M32R_ICUCR_ISMOD11;
 	disable_m32104ut_irq(M32R_IRQ_INT0);
 #endif  /* CONFIG_SMC91X */
 
 	/* MFT2 : system timer */
-	irq_desc[M32R_IRQ_MFT2].status = IRQ_DISABLED;
-	irq_desc[M32R_IRQ_MFT2].chip = &m32104ut_irq_type;
-	irq_desc[M32R_IRQ_MFT2].action = 0;
-	irq_desc[M32R_IRQ_MFT2].depth = 1;
+	set_irq_chip_and_handler(M32R_IRQ_MFT2, &m32104ut_irq_type,
+				 handle_level_irq);
 	icu_data[M32R_IRQ_MFT2].icucr = M32R_ICUCR_IEN;
 	disable_m32104ut_irq(M32R_IRQ_MFT2);
 
 #ifdef CONFIG_SERIAL_M32R_SIO
 	/* SIO0_R : uart receive data */
-	irq_desc[M32R_IRQ_SIO0_R].status = IRQ_DISABLED;
-	irq_desc[M32R_IRQ_SIO0_R].chip = &m32104ut_irq_type;
-	irq_desc[M32R_IRQ_SIO0_R].action = 0;
-	irq_desc[M32R_IRQ_SIO0_R].depth = 1;
+	set_irq_chip_and_handler(M32R_IRQ_SIO0_R, &m32104ut_irq_type,
+				 handle_level_irq);
 	icu_data[M32R_IRQ_SIO0_R].icucr = M32R_ICUCR_IEN;
 	disable_m32104ut_irq(M32R_IRQ_SIO0_R);
 
 	/* SIO0_S : uart send data */
-	irq_desc[M32R_IRQ_SIO0_S].status = IRQ_DISABLED;
-	irq_desc[M32R_IRQ_SIO0_S].chip = &m32104ut_irq_type;
-	irq_desc[M32R_IRQ_SIO0_S].action = 0;
-	irq_desc[M32R_IRQ_SIO0_S].depth = 1;
+	set_irq_chip_and_handler(M32R_IRQ_SIO0_S, &m32104ut_irq_type,
+				 handle_level_irq);
 	icu_data[M32R_IRQ_SIO0_S].icucr = M32R_ICUCR_IEN;
 	disable_m32104ut_irq(M32R_IRQ_SIO0_S);
 #endif /* CONFIG_SERIAL_M32R_SIO */
diff -druNp linux-libre-2.6.37-gnu1/arch/m32r/platforms/m32700ut/setup.c linux-libre-2.6.38-gnu1/arch/m32r/platforms/m32700ut/setup.c
--- linux-libre-2.6.37-gnu1/arch/m32r/platforms/m32700ut/setup.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/m32r/platforms/m32700ut/setup.c	2011-03-14 21:20:32.000000000 -0400
@@ -45,39 +45,30 @@ static void enable_m32700ut_irq(unsigned
 	outl(data, port);
 }
 
-static void mask_and_ack_m32700ut(unsigned int irq)
-{
-	disable_m32700ut_irq(irq);
-}
-
-static void end_m32700ut_irq(unsigned int irq)
+static void mask_m32700ut(struct irq_data *data)
 {
-	enable_m32700ut_irq(irq);
+	disable_m32700ut_irq(data->irq);
 }
 
-static unsigned int startup_m32700ut_irq(unsigned int irq)
+static void unmask_m32700ut(struct irq_data *data)
 {
-	enable_m32700ut_irq(irq);
-	return (0);
+	enable_m32700ut_irq(data->irq);
 }
 
-static void shutdown_m32700ut_irq(unsigned int irq)
+static void shutdown_m32700ut(struct irq_data *data)
 {
 	unsigned long port;
 
-	port = irq2port(irq);
+	port = irq2port(data->irq);
 	outl(M32R_ICUCR_ILEVEL7, port);
 }
 
 static struct irq_chip m32700ut_irq_type =
 {
-	.name = "M32700UT-IRQ",
-	.startup = startup_m32700ut_irq,
-	.shutdown = shutdown_m32700ut_irq,
-	.enable = enable_m32700ut_irq,
-	.disable = disable_m32700ut_irq,
-	.ack = mask_and_ack_m32700ut,
-	.end = end_m32700ut_irq
+	.name		= "M32700UT-IRQ",
+	.irq_shutdown	= shutdown_m32700ut,
+	.irq_mask	= mask_m32700ut,
+	.irq_unmask	= unmask_m32700ut
 };
 
 /*
@@ -99,7 +90,6 @@ static void disable_m32700ut_pld_irq(uns
 	unsigned int pldirq;
 
 	pldirq = irq2pldirq(irq);
-//	disable_m32700ut_irq(M32R_IRQ_INT1);
 	port = pldirq2port(pldirq);
 	data = pld_icu_data[pldirq].icucr|PLD_ICUCR_ILEVEL7;
 	outw(data, port);
@@ -111,50 +101,38 @@ static void enable_m32700ut_pld_irq(unsi
 	unsigned int pldirq;
 
 	pldirq = irq2pldirq(irq);
-//	enable_m32700ut_irq(M32R_IRQ_INT1);
 	port = pldirq2port(pldirq);
 	data = pld_icu_data[pldirq].icucr|PLD_ICUCR_IEN|PLD_ICUCR_ILEVEL6;
 	outw(data, port);
 }
 
-static void mask_and_ack_m32700ut_pld(unsigned int irq)
-{
-	disable_m32700ut_pld_irq(irq);
-//	mask_and_ack_m32700ut(M32R_IRQ_INT1);
-}
-
-static void end_m32700ut_pld_irq(unsigned int irq)
+static void mask_m32700ut_pld(struct irq_data *data)
 {
-	enable_m32700ut_pld_irq(irq);
-	end_m32700ut_irq(M32R_IRQ_INT1);
+	disable_m32700ut_pld_irq(data->irq);
 }
 
-static unsigned int startup_m32700ut_pld_irq(unsigned int irq)
+static void unmask_m32700ut_pld(struct irq_data *data)
 {
-	enable_m32700ut_pld_irq(irq);
-	return (0);
+	enable_m32700ut_pld_irq(data->irq);
+	enable_m32700ut_irq(M32R_IRQ_INT1);
 }
 
-static void shutdown_m32700ut_pld_irq(unsigned int irq)
+static void shutdown_m32700ut_pld_irq(struct irq_data *data)
 {
 	unsigned long port;
 	unsigned int pldirq;
 
-	pldirq = irq2pldirq(irq);
-//	shutdown_m32700ut_irq(M32R_IRQ_INT1);
+	pldirq = irq2pldirq(data->irq);
 	port = pldirq2port(pldirq);
 	outw(PLD_ICUCR_ILEVEL7, port);
 }
 
 static struct irq_chip m32700ut_pld_irq_type =
 {
-	.name = "M32700UT-PLD-IRQ",
-	.startup = startup_m32700ut_pld_irq,
-	.shutdown = shutdown_m32700ut_pld_irq,
-	.enable = enable_m32700ut_pld_irq,
-	.disable = disable_m32700ut_pld_irq,
-	.ack = mask_and_ack_m32700ut_pld,
-	.end = end_m32700ut_pld_irq
+	.name		= "M32700UT-PLD-IRQ",
+	.irq_shutdown	= shutdown_m32700ut_pld_irq,
+	.irq_mask	= mask_m32700ut_pld,
+	.irq_unmask	= unmask_m32700ut_pld,
 };
 
 /*
@@ -188,42 +166,33 @@ static void enable_m32700ut_lanpld_irq(u
 	outw(data, port);
 }
 
-static void mask_and_ack_m32700ut_lanpld(unsigned int irq)
-{
-	disable_m32700ut_lanpld_irq(irq);
-}
-
-static void end_m32700ut_lanpld_irq(unsigned int irq)
+static void mask_m32700ut_lanpld(struct irq_data *data)
 {
-	enable_m32700ut_lanpld_irq(irq);
-	end_m32700ut_irq(M32R_IRQ_INT0);
+	disable_m32700ut_lanpld_irq(data->irq);
 }
 
-static unsigned int startup_m32700ut_lanpld_irq(unsigned int irq)
+static void unmask_m32700ut_lanpld(struct irq_data *data)
 {
-	enable_m32700ut_lanpld_irq(irq);
-	return (0);
+	enable_m32700ut_lanpld_irq(data->irq);
+	enable_m32700ut_irq(M32R_IRQ_INT0);
 }
 
-static void shutdown_m32700ut_lanpld_irq(unsigned int irq)
+static void shutdown_m32700ut_lanpld(struct irq_data *data)
 {
 	unsigned long port;
 	unsigned int pldirq;
 
-	pldirq = irq2lanpldirq(irq);
+	pldirq = irq2lanpldirq(data->irq);
 	port = lanpldirq2port(pldirq);
 	outw(PLD_ICUCR_ILEVEL7, port);
 }
 
 static struct irq_chip m32700ut_lanpld_irq_type =
 {
-	.name = "M32700UT-PLD-LAN-IRQ",
-	.startup = startup_m32700ut_lanpld_irq,
-	.shutdown = shutdown_m32700ut_lanpld_irq,
-	.enable = enable_m32700ut_lanpld_irq,
-	.disable = disable_m32700ut_lanpld_irq,
-	.ack = mask_and_ack_m32700ut_lanpld,
-	.end = end_m32700ut_lanpld_irq
+	.name		= "M32700UT-PLD-LAN-IRQ",
+	.irq_shutdown	= shutdown_m32700ut_lanpld,
+	.irq_mask	= mask_m32700ut_lanpld,
+	.irq_unmask	= unmask_m32700ut_lanpld,
 };
 
 /*
@@ -257,143 +226,110 @@ static void enable_m32700ut_lcdpld_irq(u
 	outw(data, port);
 }
 
-static void mask_and_ack_m32700ut_lcdpld(unsigned int irq)
-{
-	disable_m32700ut_lcdpld_irq(irq);
-}
-
-static void end_m32700ut_lcdpld_irq(unsigned int irq)
+static void mask_m32700ut_lcdpld(struct irq_data *data)
 {
-	enable_m32700ut_lcdpld_irq(irq);
-	end_m32700ut_irq(M32R_IRQ_INT2);
+	disable_m32700ut_lcdpld_irq(data->irq);
 }
 
-static unsigned int startup_m32700ut_lcdpld_irq(unsigned int irq)
+static void unmask_m32700ut_lcdpld(struct irq_data *data)
 {
-	enable_m32700ut_lcdpld_irq(irq);
-	return (0);
+	enable_m32700ut_lcdpld_irq(data->irq);
+	enable_m32700ut_irq(M32R_IRQ_INT2);
 }
 
-static void shutdown_m32700ut_lcdpld_irq(unsigned int irq)
+static void shutdown_m32700ut_lcdpld(struct irq_data *data)
 {
 	unsigned long port;
 	unsigned int pldirq;
 
-	pldirq = irq2lcdpldirq(irq);
+	pldirq = irq2lcdpldirq(data->irq);
 	port = lcdpldirq2port(pldirq);
 	outw(PLD_ICUCR_ILEVEL7, port);
 }
 
 static struct irq_chip m32700ut_lcdpld_irq_type =
 {
-	.name = "M32700UT-PLD-LCD-IRQ",
-	.startup = startup_m32700ut_lcdpld_irq,
-	.shutdown = shutdown_m32700ut_lcdpld_irq,
-	.enable = enable_m32700ut_lcdpld_irq,
-	.disable = disable_m32700ut_lcdpld_irq,
-	.ack = mask_and_ack_m32700ut_lcdpld,
-	.end = end_m32700ut_lcdpld_irq
+	.name		= "M32700UT-PLD-LCD-IRQ",
+	.irq_shutdown	= shutdown_m32700ut_lcdpld,
+	.irq_mask	= mask_m32700ut_lcdpld,
+	.irq_unmask	= unmask_m32700ut_lcdpld,
 };
 
 void __init init_IRQ(void)
 {
 #if defined(CONFIG_SMC91X)
 	/* INT#0: LAN controller on M32700UT-LAN (SMC91C111)*/
-	irq_desc[M32700UT_LAN_IRQ_LAN].status = IRQ_DISABLED;
-	irq_desc[M32700UT_LAN_IRQ_LAN].chip = &m32700ut_lanpld_irq_type;
-	irq_desc[M32700UT_LAN_IRQ_LAN].action = 0;
-	irq_desc[M32700UT_LAN_IRQ_LAN].depth = 1;	/* disable nested irq */
+	set_irq_chip_and_handler(M32700UT_LAN_IRQ_LAN,
+				 &m32700ut_lanpld_irq_type, handle_level_irq);
 	lanpld_icu_data[irq2lanpldirq(M32700UT_LAN_IRQ_LAN)].icucr = PLD_ICUCR_IEN|PLD_ICUCR_ISMOD02;	/* "H" edge sense */
 	disable_m32700ut_lanpld_irq(M32700UT_LAN_IRQ_LAN);
 #endif  /* CONFIG_SMC91X */
 
 	/* MFT2 : system timer */
-	irq_desc[M32R_IRQ_MFT2].status = IRQ_DISABLED;
-	irq_desc[M32R_IRQ_MFT2].chip = &m32700ut_irq_type;
-	irq_desc[M32R_IRQ_MFT2].action = 0;
-	irq_desc[M32R_IRQ_MFT2].depth = 1;
+	set_irq_chip_and_handler(M32R_IRQ_MFT2, &m32700ut_irq_type,
+				 handle_level_irq);
 	icu_data[M32R_IRQ_MFT2].icucr = M32R_ICUCR_IEN;
 	disable_m32700ut_irq(M32R_IRQ_MFT2);
 
 	/* SIO0 : receive */
-	irq_desc[M32R_IRQ_SIO0_R].status = IRQ_DISABLED;
-	irq_desc[M32R_IRQ_SIO0_R].chip = &m32700ut_irq_type;
-	irq_desc[M32R_IRQ_SIO0_R].action = 0;
-	irq_desc[M32R_IRQ_SIO0_R].depth = 1;
+	set_irq_chip_and_handler(M32R_IRQ_SIO0_R, &m32700ut_irq_type,
+				 handle_level_irq);
 	icu_data[M32R_IRQ_SIO0_R].icucr = 0;
 	disable_m32700ut_irq(M32R_IRQ_SIO0_R);
 
 	/* SIO0 : send */
-	irq_desc[M32R_IRQ_SIO0_S].status = IRQ_DISABLED;
-	irq_desc[M32R_IRQ_SIO0_S].chip = &m32700ut_irq_type;
-	irq_desc[M32R_IRQ_SIO0_S].action = 0;
-	irq_desc[M32R_IRQ_SIO0_S].depth = 1;
+	set_irq_chip_and_handler(M32R_IRQ_SIO0_S, &m32700ut_irq_type,
+				 handle_level_irq);
 	icu_data[M32R_IRQ_SIO0_S].icucr = 0;
 	disable_m32700ut_irq(M32R_IRQ_SIO0_S);
 
 	/* SIO1 : receive */
-	irq_desc[M32R_IRQ_SIO1_R].status = IRQ_DISABLED;
-	irq_desc[M32R_IRQ_SIO1_R].chip = &m32700ut_irq_type;
-	irq_desc[M32R_IRQ_SIO1_R].action = 0;
-	irq_desc[M32R_IRQ_SIO1_R].depth = 1;
+	set_irq_chip_and_handler(M32R_IRQ_SIO1_R, &m32700ut_irq_type,
+				 handle_level_irq);
 	icu_data[M32R_IRQ_SIO1_R].icucr = 0;
 	disable_m32700ut_irq(M32R_IRQ_SIO1_R);
 
 	/* SIO1 : send */
-	irq_desc[M32R_IRQ_SIO1_S].status = IRQ_DISABLED;
-	irq_desc[M32R_IRQ_SIO1_S].chip = &m32700ut_irq_type;
-	irq_desc[M32R_IRQ_SIO1_S].action = 0;
-	irq_desc[M32R_IRQ_SIO1_S].depth = 1;
+	set_irq_chip_and_handler(M32R_IRQ_SIO1_S, &m32700ut_irq_type,
+				 handle_level_irq);
 	icu_data[M32R_IRQ_SIO1_S].icucr = 0;
 	disable_m32700ut_irq(M32R_IRQ_SIO1_S);
 
 	/* DMA1 : */
-	irq_desc[M32R_IRQ_DMA1].status = IRQ_DISABLED;
-	irq_desc[M32R_IRQ_DMA1].chip = &m32700ut_irq_type;
-	irq_desc[M32R_IRQ_DMA1].action = 0;
-	irq_desc[M32R_IRQ_DMA1].depth = 1;
+	set_irq_chip_and_handler(M32R_IRQ_DMA1, &m32700ut_irq_type,
+				 handle_level_irq);
 	icu_data[M32R_IRQ_DMA1].icucr = 0;
 	disable_m32700ut_irq(M32R_IRQ_DMA1);
 
 #ifdef CONFIG_SERIAL_M32R_PLDSIO
 	/* INT#1: SIO0 Receive on PLD */
-	irq_desc[PLD_IRQ_SIO0_RCV].status = IRQ_DISABLED;
-	irq_desc[PLD_IRQ_SIO0_RCV].chip = &m32700ut_pld_irq_type;
-	irq_desc[PLD_IRQ_SIO0_RCV].action = 0;
-	irq_desc[PLD_IRQ_SIO0_RCV].depth = 1;	/* disable nested irq */
+	set_irq_chip_and_handler(PLD_IRQ_SIO0_RCV, &m32700ut_pld_irq_type,
+				 handle_level_irq);
 	pld_icu_data[irq2pldirq(PLD_IRQ_SIO0_RCV)].icucr = PLD_ICUCR_IEN|PLD_ICUCR_ISMOD03;
 	disable_m32700ut_pld_irq(PLD_IRQ_SIO0_RCV);
 
 	/* INT#1: SIO0 Send on PLD */
-	irq_desc[PLD_IRQ_SIO0_SND].status = IRQ_DISABLED;
-	irq_desc[PLD_IRQ_SIO0_SND].chip = &m32700ut_pld_irq_type;
-	irq_desc[PLD_IRQ_SIO0_SND].action = 0;
-	irq_desc[PLD_IRQ_SIO0_SND].depth = 1;	/* disable nested irq */
+	set_irq_chip_and_handler(PLD_IRQ_SIO0_SND, &m32700ut_pld_irq_type,
+				 handle_level_irq);
 	pld_icu_data[irq2pldirq(PLD_IRQ_SIO0_SND)].icucr = PLD_ICUCR_IEN|PLD_ICUCR_ISMOD03;
 	disable_m32700ut_pld_irq(PLD_IRQ_SIO0_SND);
 #endif  /* CONFIG_SERIAL_M32R_PLDSIO */
 
 	/* INT#1: CFC IREQ on PLD */
-	irq_desc[PLD_IRQ_CFIREQ].status = IRQ_DISABLED;
-	irq_desc[PLD_IRQ_CFIREQ].chip = &m32700ut_pld_irq_type;
-	irq_desc[PLD_IRQ_CFIREQ].action = 0;
-	irq_desc[PLD_IRQ_CFIREQ].depth = 1;	/* disable nested irq */
+	set_irq_chip_and_handler(PLD_IRQ_CFIREQ, &m32700ut_pld_irq_type,
+				 handle_level_irq);
 	pld_icu_data[irq2pldirq(PLD_IRQ_CFIREQ)].icucr = PLD_ICUCR_IEN|PLD_ICUCR_ISMOD01;	/* 'L' level sense */
 	disable_m32700ut_pld_irq(PLD_IRQ_CFIREQ);
 
 	/* INT#1: CFC Insert on PLD */
-	irq_desc[PLD_IRQ_CFC_INSERT].status = IRQ_DISABLED;
-	irq_desc[PLD_IRQ_CFC_INSERT].chip = &m32700ut_pld_irq_type;
-	irq_desc[PLD_IRQ_CFC_INSERT].action = 0;
-	irq_desc[PLD_IRQ_CFC_INSERT].depth = 1;	/* disable nested irq */
+	set_irq_chip_and_handler(PLD_IRQ_CFC_INSERT, &m32700ut_pld_irq_type,
+				 handle_level_irq);
 	pld_icu_data[irq2pldirq(PLD_IRQ_CFC_INSERT)].icucr = PLD_ICUCR_IEN|PLD_ICUCR_ISMOD00;	/* 'L' edge sense */
 	disable_m32700ut_pld_irq(PLD_IRQ_CFC_INSERT);
 
 	/* INT#1: CFC Eject on PLD */
-	irq_desc[PLD_IRQ_CFC_EJECT].status = IRQ_DISABLED;
-	irq_desc[PLD_IRQ_CFC_EJECT].chip = &m32700ut_pld_irq_type;
-	irq_desc[PLD_IRQ_CFC_EJECT].action = 0;
-	irq_desc[PLD_IRQ_CFC_EJECT].depth = 1;	/* disable nested irq */
+	set_irq_chip_and_handler(PLD_IRQ_CFC_EJECT, &m32700ut_pld_irq_type,
+				 handle_level_irq);
 	pld_icu_data[irq2pldirq(PLD_IRQ_CFC_EJECT)].icucr = PLD_ICUCR_IEN|PLD_ICUCR_ISMOD02;	/* 'H' edge sense */
 	disable_m32700ut_pld_irq(PLD_IRQ_CFC_EJECT);
 
@@ -413,13 +349,11 @@ void __init init_IRQ(void)
 
 #if defined(CONFIG_USB)
 	outw(USBCR_OTGS, USBCR); 	/* USBCR: non-OTG */
+	set_irq_chip_and_handler(M32700UT_LCD_IRQ_USB_INT1,
+				 &m32700ut_lcdpld_irq_type, handle_level_irq);
 
-    irq_desc[M32700UT_LCD_IRQ_USB_INT1].status = IRQ_DISABLED;
-    irq_desc[M32700UT_LCD_IRQ_USB_INT1].chip = &m32700ut_lcdpld_irq_type;
-    irq_desc[M32700UT_LCD_IRQ_USB_INT1].action = 0;
-    irq_desc[M32700UT_LCD_IRQ_USB_INT1].depth = 1;
-    lcdpld_icu_data[irq2lcdpldirq(M32700UT_LCD_IRQ_USB_INT1)].icucr = PLD_ICUCR_IEN|PLD_ICUCR_ISMOD01;	/* "L" level sense */
-    disable_m32700ut_lcdpld_irq(M32700UT_LCD_IRQ_USB_INT1);
+	lcdpld_icu_data[irq2lcdpldirq(M32700UT_LCD_IRQ_USB_INT1)].icucr = PLD_ICUCR_IEN|PLD_ICUCR_ISMOD01;	/* "L" level sense */
+	disable_m32700ut_lcdpld_irq(M32700UT_LCD_IRQ_USB_INT1);
 #endif
 	/*
 	 * INT2# is used for BAT, USB, AUDIO
@@ -432,10 +366,8 @@ void __init init_IRQ(void)
 	/*
 	 * INT3# is used for AR
 	 */
-	irq_desc[M32R_IRQ_INT3].status = IRQ_DISABLED;
-	irq_desc[M32R_IRQ_INT3].chip = &m32700ut_irq_type;
-	irq_desc[M32R_IRQ_INT3].action = 0;
-	irq_desc[M32R_IRQ_INT3].depth = 1;
+	set_irq_chip_and_handler(M32R_IRQ_INT3, &m32700ut_irq_type,
+				 handle_level_irq);
 	icu_data[M32R_IRQ_INT3].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD10;
 	disable_m32700ut_irq(M32R_IRQ_INT3);
 #endif	/* CONFIG_VIDEO_M32R_AR */
diff -druNp linux-libre-2.6.37-gnu1/arch/m32r/platforms/mappi/setup.c linux-libre-2.6.38-gnu1/arch/m32r/platforms/mappi/setup.c
--- linux-libre-2.6.37-gnu1/arch/m32r/platforms/mappi/setup.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/m32r/platforms/mappi/setup.c	2011-03-14 21:20:32.000000000 -0400
@@ -38,40 +38,30 @@ static void enable_mappi_irq(unsigned in
 	outl(data, port);
 }
 
-static void mask_and_ack_mappi(unsigned int irq)
-{
-	disable_mappi_irq(irq);
-}
-
-static void end_mappi_irq(unsigned int irq)
+static void mask_mappi(struct irq_data *data)
 {
-	if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
-		enable_mappi_irq(irq);
+	disable_mappi_irq(data->irq);
 }
 
-static unsigned int startup_mappi_irq(unsigned int irq)
+static void unmask_mappi(struct irq_data *data)
 {
-	enable_mappi_irq(irq);
-	return (0);
+	enable_mappi_irq(data->irq);
 }
 
-static void shutdown_mappi_irq(unsigned int irq)
+static void shutdown_mappi(struct irq_data *data)
 {
 	unsigned long port;
 
-	port = irq2port(irq);
+	port = irq2port(data->irq);
 	outl(M32R_ICUCR_ILEVEL7, port);
 }
 
 static struct irq_chip mappi_irq_type =
 {
-	.name = "MAPPI-IRQ",
-	.startup = startup_mappi_irq,
-	.shutdown = shutdown_mappi_irq,
-	.enable = enable_mappi_irq,
-	.disable = disable_mappi_irq,
-	.ack = mask_and_ack_mappi,
-	.end = end_mappi_irq
+	.name		= "MAPPI-IRQ",
+	.irq_shutdown	= shutdown_mappi,
+	.irq_mask	= mask_mappi,
+	.irq_unmask	= unmask_mappi,
 };
 
 void __init init_IRQ(void)
@@ -85,70 +75,54 @@ void __init init_IRQ(void)
 
 #ifdef CONFIG_NE2000
 	/* INT0 : LAN controller (RTL8019AS) */
-	irq_desc[M32R_IRQ_INT0].status = IRQ_DISABLED;
-	irq_desc[M32R_IRQ_INT0].chip = &mappi_irq_type;
-	irq_desc[M32R_IRQ_INT0].action = NULL;
-	irq_desc[M32R_IRQ_INT0].depth = 1;
+	set_irq_chip_and_handler(M32R_IRQ_INT0, &mappi_irq_type,
+				 handle_level_irq);
 	icu_data[M32R_IRQ_INT0].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD11;
 	disable_mappi_irq(M32R_IRQ_INT0);
 #endif /* CONFIG_M32R_NE2000 */
 
 	/* MFT2 : system timer */
-	irq_desc[M32R_IRQ_MFT2].status = IRQ_DISABLED;
-	irq_desc[M32R_IRQ_MFT2].chip = &mappi_irq_type;
-	irq_desc[M32R_IRQ_MFT2].action = NULL;
-	irq_desc[M32R_IRQ_MFT2].depth = 1;
+	set_irq_chip_and_handler(M32R_IRQ_MFT2, &mappi_irq_type,
+				 handle_level_irq);
 	icu_data[M32R_IRQ_MFT2].icucr = M32R_ICUCR_IEN;
 	disable_mappi_irq(M32R_IRQ_MFT2);
 
 #ifdef CONFIG_SERIAL_M32R_SIO
 	/* SIO0_R : uart receive data */
-	irq_desc[M32R_IRQ_SIO0_R].status = IRQ_DISABLED;
-	irq_desc[M32R_IRQ_SIO0_R].chip = &mappi_irq_type;
-	irq_desc[M32R_IRQ_SIO0_R].action = NULL;
-	irq_desc[M32R_IRQ_SIO0_R].depth = 1;
+	set_irq_chip_and_handler(M32R_IRQ_SIO0_R, &mappi_irq_type,
+				 handle_level_irq);
 	icu_data[M32R_IRQ_SIO0_R].icucr = 0;
 	disable_mappi_irq(M32R_IRQ_SIO0_R);
 
 	/* SIO0_S : uart send data */
-	irq_desc[M32R_IRQ_SIO0_S].status = IRQ_DISABLED;
-	irq_desc[M32R_IRQ_SIO0_S].chip = &mappi_irq_type;
-	irq_desc[M32R_IRQ_SIO0_S].action = NULL;
-	irq_desc[M32R_IRQ_SIO0_S].depth = 1;
+	set_irq_chip_and_handler(M32R_IRQ_SIO0_S, &mappi_irq_type,
+				 handle_level_irq);
 	icu_data[M32R_IRQ_SIO0_S].icucr = 0;
 	disable_mappi_irq(M32R_IRQ_SIO0_S);
 
 	/* SIO1_R : uart receive data */
-	irq_desc[M32R_IRQ_SIO1_R].status = IRQ_DISABLED;
-	irq_desc[M32R_IRQ_SIO1_R].chip = &mappi_irq_type;
-	irq_desc[M32R_IRQ_SIO1_R].action = NULL;
-	irq_desc[M32R_IRQ_SIO1_R].depth = 1;
+	set_irq_chip_and_handler(M32R_IRQ_SIO1_R, &mappi_irq_type,
+				 handle_level_irq);
 	icu_data[M32R_IRQ_SIO1_R].icucr = 0;
 	disable_mappi_irq(M32R_IRQ_SIO1_R);
 
 	/* SIO1_S : uart send data */
-	irq_desc[M32R_IRQ_SIO1_S].status = IRQ_DISABLED;
-	irq_desc[M32R_IRQ_SIO1_S].chip = &mappi_irq_type;
-	irq_desc[M32R_IRQ_SIO1_S].action = NULL;
-	irq_desc[M32R_IRQ_SIO1_S].depth = 1;
+	set_irq_chip_and_handler(M32R_IRQ_SIO1_S, &mappi_irq_type,
+				 handle_level_irq);
 	icu_data[M32R_IRQ_SIO1_S].icucr = 0;
 	disable_mappi_irq(M32R_IRQ_SIO1_S);
 #endif /* CONFIG_SERIAL_M32R_SIO */
 
 #if defined(CONFIG_M32R_PCC)
 	/* INT1 : pccard0 interrupt */
-	irq_desc[M32R_IRQ_INT1].status = IRQ_DISABLED;
-	irq_desc[M32R_IRQ_INT1].chip = &mappi_irq_type;
-	irq_desc[M32R_IRQ_INT1].action = NULL;
-	irq_desc[M32R_IRQ_INT1].depth = 1;
+	set_irq_chip_and_handler(M32R_IRQ_INT1, &mappi_irq_type,
+				 handle_level_irq);
 	icu_data[M32R_IRQ_INT1].icucr = M32R_ICUCR_IEN | M32R_ICUCR_ISMOD00;
 	disable_mappi_irq(M32R_IRQ_INT1);
 
 	/* INT2 : pccard1 interrupt */
-	irq_desc[M32R_IRQ_INT2].status = IRQ_DISABLED;
-	irq_desc[M32R_IRQ_INT2].chip = &mappi_irq_type;
-	irq_desc[M32R_IRQ_INT2].action = NULL;
-	irq_desc[M32R_IRQ_INT2].depth = 1;
+	set_irq_chip_and_handler(M32R_IRQ_INT2, &mappi_irq_type,
+				 handle_level_irq);
 	icu_data[M32R_IRQ_INT2].icucr = M32R_ICUCR_IEN | M32R_ICUCR_ISMOD00;
 	disable_mappi_irq(M32R_IRQ_INT2);
 #endif /* CONFIG_M32RPCC */
diff -druNp linux-libre-2.6.37-gnu1/arch/m32r/platforms/mappi2/setup.c linux-libre-2.6.38-gnu1/arch/m32r/platforms/mappi2/setup.c
--- linux-libre-2.6.37-gnu1/arch/m32r/platforms/mappi2/setup.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/m32r/platforms/mappi2/setup.c	2011-03-14 21:20:32.000000000 -0400
@@ -46,126 +46,97 @@ static void enable_mappi2_irq(unsigned i
 	outl(data, port);
 }
 
-static void mask_and_ack_mappi2(unsigned int irq)
-{
-	disable_mappi2_irq(irq);
-}
-
-static void end_mappi2_irq(unsigned int irq)
+static void mask_mappi2(struct irq_data *data)
 {
-	enable_mappi2_irq(irq);
+	disable_mappi2_irq(data->irq);
 }
 
-static unsigned int startup_mappi2_irq(unsigned int irq)
+static void unmask_mappi2(struct irq_data *data)
 {
-	enable_mappi2_irq(irq);
-	return (0);
+	enable_mappi2_irq(data->irq);
 }
 
-static void shutdown_mappi2_irq(unsigned int irq)
+static void shutdown_mappi2(struct irq_data *data)
 {
 	unsigned long port;
 
-	port = irq2port(irq);
+	port = irq2port(data->irq);
 	outl(M32R_ICUCR_ILEVEL7, port);
 }
 
 static struct irq_chip mappi2_irq_type =
 {
-	.name = "MAPPI2-IRQ",
-	.startup = startup_mappi2_irq,
-	.shutdown = shutdown_mappi2_irq,
-	.enable = enable_mappi2_irq,
-	.disable = disable_mappi2_irq,
-	.ack = mask_and_ack_mappi2,
-	.end = end_mappi2_irq
+	.name		= "MAPPI2-IRQ",
+	.irq_shutdown	= shutdown_mappi2,
+	.irq_mask	= mask_mappi2,
+	.irq_unmask	= unmask_mappi2,
 };
 
 void __init init_IRQ(void)
 {
 #if defined(CONFIG_SMC91X)
 	/* INT0 : LAN controller (SMC91111) */
-	irq_desc[M32R_IRQ_INT0].status = IRQ_DISABLED;
-	irq_desc[M32R_IRQ_INT0].chip = &mappi2_irq_type;
-	irq_desc[M32R_IRQ_INT0].action = 0;
-	irq_desc[M32R_IRQ_INT0].depth = 1;
+	set_irq_chip_and_handler(M32R_IRQ_INT0, &mappi2_irq_type,
+				 handle_level_irq);
 	icu_data[M32R_IRQ_INT0].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD10;
 	disable_mappi2_irq(M32R_IRQ_INT0);
 #endif  /* CONFIG_SMC91X */
 
 	/* MFT2 : system timer */
-	irq_desc[M32R_IRQ_MFT2].status = IRQ_DISABLED;
-	irq_desc[M32R_IRQ_MFT2].chip = &mappi2_irq_type;
-	irq_desc[M32R_IRQ_MFT2].action = 0;
-	irq_desc[M32R_IRQ_MFT2].depth = 1;
+	set_irq_chip_and_handler(M32R_IRQ_MFT2, &mappi2_irq_type,
+				 handle_level_irq);
 	icu_data[M32R_IRQ_MFT2].icucr = M32R_ICUCR_IEN;
 	disable_mappi2_irq(M32R_IRQ_MFT2);
 
 #ifdef CONFIG_SERIAL_M32R_SIO
 	/* SIO0_R : uart receive data */
-	irq_desc[M32R_IRQ_SIO0_R].status = IRQ_DISABLED;
-	irq_desc[M32R_IRQ_SIO0_R].chip = &mappi2_irq_type;
-	irq_desc[M32R_IRQ_SIO0_R].action = 0;
-	irq_desc[M32R_IRQ_SIO0_R].depth = 1;
+	set_irq_chip_and_handler(M32R_IRQ_SIO0_R, &mappi2_irq_type,
+				 handle_level_irq);
 	icu_data[M32R_IRQ_SIO0_R].icucr = 0;
 	disable_mappi2_irq(M32R_IRQ_SIO0_R);
 
 	/* SIO0_S : uart send data */
-	irq_desc[M32R_IRQ_SIO0_S].status = IRQ_DISABLED;
-	irq_desc[M32R_IRQ_SIO0_S].chip = &mappi2_irq_type;
-	irq_desc[M32R_IRQ_SIO0_S].action = 0;
-	irq_desc[M32R_IRQ_SIO0_S].depth = 1;
+	set_irq_chip_and_handler(M32R_IRQ_SIO0_S, &mappi2_irq_type,
+				 handle_level_irq);
 	icu_data[M32R_IRQ_SIO0_S].icucr = 0;
 	disable_mappi2_irq(M32R_IRQ_SIO0_S);
 	/* SIO1_R : uart receive data */
-	irq_desc[M32R_IRQ_SIO1_R].status = IRQ_DISABLED;
-	irq_desc[M32R_IRQ_SIO1_R].chip = &mappi2_irq_type;
-	irq_desc[M32R_IRQ_SIO1_R].action = 0;
-	irq_desc[M32R_IRQ_SIO1_R].depth = 1;
+	set_irq_chip_and_handler(M32R_IRQ_SIO1_R, &mappi2_irq_type,
+				 handle_level_irq);
 	icu_data[M32R_IRQ_SIO1_R].icucr = 0;
 	disable_mappi2_irq(M32R_IRQ_SIO1_R);
 
 	/* SIO1_S : uart send data */
-	irq_desc[M32R_IRQ_SIO1_S].status = IRQ_DISABLED;
-	irq_desc[M32R_IRQ_SIO1_S].chip = &mappi2_irq_type;
-	irq_desc[M32R_IRQ_SIO1_S].action = 0;
-	irq_desc[M32R_IRQ_SIO1_S].depth = 1;
+	set_irq_chip_and_handler(M32R_IRQ_SIO1_S, &mappi2_irq_type,
+				 handle_level_irq);
 	icu_data[M32R_IRQ_SIO1_S].icucr = 0;
 	disable_mappi2_irq(M32R_IRQ_SIO1_S);
 #endif  /* CONFIG_M32R_USE_DBG_CONSOLE */
 
 #if defined(CONFIG_USB)
 	/* INT1 : USB Host controller interrupt */
-	irq_desc[M32R_IRQ_INT1].status = IRQ_DISABLED;
-	irq_desc[M32R_IRQ_INT1].chip = &mappi2_irq_type;
-	irq_desc[M32R_IRQ_INT1].action = 0;
-	irq_desc[M32R_IRQ_INT1].depth = 1;
+	set_irq_chip_and_handler(M32R_IRQ_INT1, &mappi2_irq_type,
+				 handle_level_irq);
 	icu_data[M32R_IRQ_INT1].icucr = M32R_ICUCR_ISMOD01;
 	disable_mappi2_irq(M32R_IRQ_INT1);
 #endif /* CONFIG_USB */
 
 	/* ICUCR40: CFC IREQ */
-	irq_desc[PLD_IRQ_CFIREQ].status = IRQ_DISABLED;
-	irq_desc[PLD_IRQ_CFIREQ].chip = &mappi2_irq_type;
-	irq_desc[PLD_IRQ_CFIREQ].action = 0;
-	irq_desc[PLD_IRQ_CFIREQ].depth = 1;	/* disable nested irq */
+	set_irq_chip_and_handler(PLD_IRQ_CFIREQ, &mappi2_irq_type,
+				 handle_level_irq);
 	icu_data[PLD_IRQ_CFIREQ].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD01;
 	disable_mappi2_irq(PLD_IRQ_CFIREQ);
 
 #if defined(CONFIG_M32R_CFC)
 	/* ICUCR41: CFC Insert */
-	irq_desc[PLD_IRQ_CFC_INSERT].status = IRQ_DISABLED;
-	irq_desc[PLD_IRQ_CFC_INSERT].chip = &mappi2_irq_type;
-	irq_desc[PLD_IRQ_CFC_INSERT].action = 0;
-	irq_desc[PLD_IRQ_CFC_INSERT].depth = 1;	/* disable nested irq */
+	set_irq_chip_and_handler(PLD_IRQ_CFC_INSERT, &mappi2_irq_type,
+				 handle_level_irq);
 	icu_data[PLD_IRQ_CFC_INSERT].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD00;
 	disable_mappi2_irq(PLD_IRQ_CFC_INSERT);
 
 	/* ICUCR42: CFC Eject */
-	irq_desc[PLD_IRQ_CFC_EJECT].status = IRQ_DISABLED;
-	irq_desc[PLD_IRQ_CFC_EJECT].chip = &mappi2_irq_type;
-	irq_desc[PLD_IRQ_CFC_EJECT].action = 0;
-	irq_desc[PLD_IRQ_CFC_EJECT].depth = 1;	/* disable nested irq */
+	set_irq_chip_and_handler(PLD_IRQ_CFC_EJECT, &mappi2_irq_type,
+				 handle_level_irq);
 	icu_data[PLD_IRQ_CFC_EJECT].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD10;
 	disable_mappi2_irq(PLD_IRQ_CFC_EJECT);
 #endif /* CONFIG_MAPPI2_CFC */
diff -druNp linux-libre-2.6.37-gnu1/arch/m32r/platforms/mappi3/setup.c linux-libre-2.6.38-gnu1/arch/m32r/platforms/mappi3/setup.c
--- linux-libre-2.6.37-gnu1/arch/m32r/platforms/mappi3/setup.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/m32r/platforms/mappi3/setup.c	2011-03-14 21:20:32.000000000 -0400
@@ -46,128 +46,98 @@ static void enable_mappi3_irq(unsigned i
 	outl(data, port);
 }
 
-static void mask_and_ack_mappi3(unsigned int irq)
-{
-	disable_mappi3_irq(irq);
-}
-
-static void end_mappi3_irq(unsigned int irq)
+static void mask_mappi3(struct irq_data *data)
 {
-	enable_mappi3_irq(irq);
+	disable_mappi3_irq(data->irq);
 }
 
-static unsigned int startup_mappi3_irq(unsigned int irq)
+static void unmask_mappi3(struct irq_data *data)
 {
-	enable_mappi3_irq(irq);
-	return (0);
+	enable_mappi3_irq(data->irq);
 }
 
-static void shutdown_mappi3_irq(unsigned int irq)
+static void shutdown_mappi3(struct irq_data *data)
 {
 	unsigned long port;
 
-	port = irq2port(irq);
+	port = irq2port(data->irq);
 	outl(M32R_ICUCR_ILEVEL7, port);
 }
 
-static struct irq_chip mappi3_irq_type =
-{
-	.name = "MAPPI3-IRQ",
-	.startup = startup_mappi3_irq,
-	.shutdown = shutdown_mappi3_irq,
-	.enable = enable_mappi3_irq,
-	.disable = disable_mappi3_irq,
-	.ack = mask_and_ack_mappi3,
-	.end = end_mappi3_irq
+static struct irq_chip mappi3_irq_type = {
+	.name		= "MAPPI3-IRQ",
+	.irq_shutdown	= shutdown_mappi3,
+	.irq_mask	= mask_mappi3,
+	.irq_unmask	= unmask_mappi3,
 };
 
 void __init init_IRQ(void)
 {
 #if defined(CONFIG_SMC91X)
 	/* INT0 : LAN controller (SMC91111) */
-	irq_desc[M32R_IRQ_INT0].status = IRQ_DISABLED;
-	irq_desc[M32R_IRQ_INT0].chip = &mappi3_irq_type;
-	irq_desc[M32R_IRQ_INT0].action = 0;
-	irq_desc[M32R_IRQ_INT0].depth = 1;
+	set_irq_chip_and_handler(M32R_IRQ_INT0, &mappi3_irq_type,
+				 handle_level_irq);
 	icu_data[M32R_IRQ_INT0].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD10;
 	disable_mappi3_irq(M32R_IRQ_INT0);
 #endif  /* CONFIG_SMC91X */
 
 	/* MFT2 : system timer */
-	irq_desc[M32R_IRQ_MFT2].status = IRQ_DISABLED;
-	irq_desc[M32R_IRQ_MFT2].chip = &mappi3_irq_type;
-	irq_desc[M32R_IRQ_MFT2].action = 0;
-	irq_desc[M32R_IRQ_MFT2].depth = 1;
+	set_irq_chip_and_handler(M32R_IRQ_MFT2, &mappi3_irq_type,
+				 handle_level_irq);
 	icu_data[M32R_IRQ_MFT2].icucr = M32R_ICUCR_IEN;
 	disable_mappi3_irq(M32R_IRQ_MFT2);
 
 #ifdef CONFIG_SERIAL_M32R_SIO
 	/* SIO0_R : uart receive data */
-	irq_desc[M32R_IRQ_SIO0_R].status = IRQ_DISABLED;
-	irq_desc[M32R_IRQ_SIO0_R].chip = &mappi3_irq_type;
-	irq_desc[M32R_IRQ_SIO0_R].action = 0;
-	irq_desc[M32R_IRQ_SIO0_R].depth = 1;
+	set_irq_chip_and_handler(M32R_IRQ_SIO0_R, &mappi3_irq_type,
+				 handle_level_irq);
 	icu_data[M32R_IRQ_SIO0_R].icucr = 0;
 	disable_mappi3_irq(M32R_IRQ_SIO0_R);
 
 	/* SIO0_S : uart send data */
-	irq_desc[M32R_IRQ_SIO0_S].status = IRQ_DISABLED;
-	irq_desc[M32R_IRQ_SIO0_S].chip = &mappi3_irq_type;
-	irq_desc[M32R_IRQ_SIO0_S].action = 0;
-	irq_desc[M32R_IRQ_SIO0_S].depth = 1;
+	set_irq_chip_and_handler(M32R_IRQ_SIO0_S, &mappi3_irq_type,
+				 handle_level_irq);
 	icu_data[M32R_IRQ_SIO0_S].icucr = 0;
 	disable_mappi3_irq(M32R_IRQ_SIO0_S);
 	/* SIO1_R : uart receive data */
-	irq_desc[M32R_IRQ_SIO1_R].status = IRQ_DISABLED;
-	irq_desc[M32R_IRQ_SIO1_R].chip = &mappi3_irq_type;
-	irq_desc[M32R_IRQ_SIO1_R].action = 0;
-	irq_desc[M32R_IRQ_SIO1_R].depth = 1;
+	set_irq_chip_and_handler(M32R_IRQ_SIO1_R, &mappi3_irq_type,
+				 handle_level_irq);
 	icu_data[M32R_IRQ_SIO1_R].icucr = 0;
 	disable_mappi3_irq(M32R_IRQ_SIO1_R);
 
 	/* SIO1_S : uart send data */
-	irq_desc[M32R_IRQ_SIO1_S].status = IRQ_DISABLED;
-	irq_desc[M32R_IRQ_SIO1_S].chip = &mappi3_irq_type;
-	irq_desc[M32R_IRQ_SIO1_S].action = 0;
-	irq_desc[M32R_IRQ_SIO1_S].depth = 1;
+	set_irq_chip_and_handler(M32R_IRQ_SIO1_S, &mappi3_irq_type,
+				 handle_level_irq);
 	icu_data[M32R_IRQ_SIO1_S].icucr = 0;
 	disable_mappi3_irq(M32R_IRQ_SIO1_S);
 #endif  /* CONFIG_M32R_USE_DBG_CONSOLE */
 
 #if defined(CONFIG_USB)
 	/* INT1 : USB Host controller interrupt */
-	irq_desc[M32R_IRQ_INT1].status = IRQ_DISABLED;
-	irq_desc[M32R_IRQ_INT1].chip = &mappi3_irq_type;
-	irq_desc[M32R_IRQ_INT1].action = 0;
-	irq_desc[M32R_IRQ_INT1].depth = 1;
+	set_irq_chip_and_handler(M32R_IRQ_INT1, &mappi3_irq_type,
+				 handle_level_irq);
 	icu_data[M32R_IRQ_INT1].icucr = M32R_ICUCR_ISMOD01;
 	disable_mappi3_irq(M32R_IRQ_INT1);
 #endif /* CONFIG_USB */
 
 	/* CFC IREQ */
-	irq_desc[PLD_IRQ_CFIREQ].status = IRQ_DISABLED;
-	irq_desc[PLD_IRQ_CFIREQ].chip = &mappi3_irq_type;
-	irq_desc[PLD_IRQ_CFIREQ].action = 0;
-	irq_desc[PLD_IRQ_CFIREQ].depth = 1;	/* disable nested irq */
+	set_irq_chip_and_handler(PLD_IRQ_CFIREQ, &mappi3_irq_type,
+				 handle_level_irq);
 	icu_data[PLD_IRQ_CFIREQ].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD01;
 	disable_mappi3_irq(PLD_IRQ_CFIREQ);
 
 #if defined(CONFIG_M32R_CFC)
 	/* ICUCR41: CFC Insert & eject */
-	irq_desc[PLD_IRQ_CFC_INSERT].status = IRQ_DISABLED;
-	irq_desc[PLD_IRQ_CFC_INSERT].chip = &mappi3_irq_type;
-	irq_desc[PLD_IRQ_CFC_INSERT].action = 0;
-	irq_desc[PLD_IRQ_CFC_INSERT].depth = 1;	/* disable nested irq */
+	set_irq_chip_and_handler(PLD_IRQ_CFC_INSERT, &mappi3_irq_type,
+				 handle_level_irq);
 	icu_data[PLD_IRQ_CFC_INSERT].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD00;
 	disable_mappi3_irq(PLD_IRQ_CFC_INSERT);
 
 #endif /* CONFIG_M32R_CFC */
 
 	/* IDE IREQ */
-	irq_desc[PLD_IRQ_IDEIREQ].status = IRQ_DISABLED;
-	irq_desc[PLD_IRQ_IDEIREQ].chip = &mappi3_irq_type;
-	irq_desc[PLD_IRQ_IDEIREQ].action = 0;
-	irq_desc[PLD_IRQ_IDEIREQ].depth = 1;	/* disable nested irq */
+	set_irq_chip_and_handler(PLD_IRQ_IDEIREQ, &mappi3_irq_type,
+				 handle_level_irq);
 	icu_data[PLD_IRQ_IDEIREQ].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD10;
 	disable_mappi3_irq(PLD_IRQ_IDEIREQ);
 
diff -druNp linux-libre-2.6.37-gnu1/arch/m32r/platforms/oaks32r/setup.c linux-libre-2.6.38-gnu1/arch/m32r/platforms/oaks32r/setup.c
--- linux-libre-2.6.37-gnu1/arch/m32r/platforms/oaks32r/setup.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/m32r/platforms/oaks32r/setup.c	2011-03-14 21:20:32.000000000 -0400
@@ -37,39 +37,30 @@ static void enable_oaks32r_irq(unsigned
 	outl(data, port);
 }
 
-static void mask_and_ack_mappi(unsigned int irq)
-{
-	disable_oaks32r_irq(irq);
-}
-
-static void end_oaks32r_irq(unsigned int irq)
+static void mask_oaks32r(struct irq_data *data)
 {
-	enable_oaks32r_irq(irq);
+	disable_oaks32r_irq(data->irq);
 }
 
-static unsigned int startup_oaks32r_irq(unsigned int irq)
+static void unmask_oaks32r(struct irq_data *data)
 {
-	enable_oaks32r_irq(irq);
-	return (0);
+	enable_oaks32r_irq(data->irq);
 }
 
-static void shutdown_oaks32r_irq(unsigned int irq)
+static void shutdown_oaks32r(struct irq_data *data)
 {
 	unsigned long port;
 
-	port = irq2port(irq);
+	port = irq2port(data->irq);
 	outl(M32R_ICUCR_ILEVEL7, port);
 }
 
 static struct irq_chip oaks32r_irq_type =
 {
-	.name = "OAKS32R-IRQ",
-	.startup = startup_oaks32r_irq,
-	.shutdown = shutdown_oaks32r_irq,
-	.enable = enable_oaks32r_irq,
-	.disable = disable_oaks32r_irq,
-	.ack = mask_and_ack_mappi,
-	.end = end_oaks32r_irq
+	.name		= "OAKS32R-IRQ",
+	.irq_shutdown	= shutdown_oaks32r,
+	.irq_mask	= mask_oaks32r,
+	.irq_unmask	= unmask_oaks32r,
 };
 
 void __init init_IRQ(void)
@@ -83,52 +74,40 @@ void __init init_IRQ(void)
 
 #ifdef CONFIG_NE2000
 	/* INT3 : LAN controller (RTL8019AS) */
-	irq_desc[M32R_IRQ_INT3].status = IRQ_DISABLED;
-	irq_desc[M32R_IRQ_INT3].chip = &oaks32r_irq_type;
-	irq_desc[M32R_IRQ_INT3].action = 0;
-	irq_desc[M32R_IRQ_INT3].depth = 1;
+	set_irq_chip_and_handler(M32R_IRQ_INT3, &oaks32r_irq_type,
+				 handle_level_irq);
 	icu_data[M32R_IRQ_INT3].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD10;
 	disable_oaks32r_irq(M32R_IRQ_INT3);
 #endif /* CONFIG_M32R_NE2000 */
 
 	/* MFT2 : system timer */
-	irq_desc[M32R_IRQ_MFT2].status = IRQ_DISABLED;
-	irq_desc[M32R_IRQ_MFT2].chip = &oaks32r_irq_type;
-	irq_desc[M32R_IRQ_MFT2].action = 0;
-	irq_desc[M32R_IRQ_MFT2].depth = 1;
+	set_irq_chip_and_handler(M32R_IRQ_MFT2, &oaks32r_irq_type,
+				 handle_level_irq);
 	icu_data[M32R_IRQ_MFT2].icucr = M32R_ICUCR_IEN;
 	disable_oaks32r_irq(M32R_IRQ_MFT2);
 
 #ifdef CONFIG_SERIAL_M32R_SIO
 	/* SIO0_R : uart receive data */
-	irq_desc[M32R_IRQ_SIO0_R].status = IRQ_DISABLED;
-	irq_desc[M32R_IRQ_SIO0_R].chip = &oaks32r_irq_type;
-	irq_desc[M32R_IRQ_SIO0_R].action = 0;
-	irq_desc[M32R_IRQ_SIO0_R].depth = 1;
+	set_irq_chip_and_handler(M32R_IRQ_SIO0_R, &oaks32r_irq_type,
+				 handle_level_irq);
 	icu_data[M32R_IRQ_SIO0_R].icucr = 0;
 	disable_oaks32r_irq(M32R_IRQ_SIO0_R);
 
 	/* SIO0_S : uart send data */
-	irq_desc[M32R_IRQ_SIO0_S].status = IRQ_DISABLED;
-	irq_desc[M32R_IRQ_SIO0_S].chip = &oaks32r_irq_type;
-	irq_desc[M32R_IRQ_SIO0_S].action = 0;
-	irq_desc[M32R_IRQ_SIO0_S].depth = 1;
+	set_irq_chip_and_handler(M32R_IRQ_SIO0_S, &oaks32r_irq_type,
+				 handle_level_irq);
 	icu_data[M32R_IRQ_SIO0_S].icucr = 0;
 	disable_oaks32r_irq(M32R_IRQ_SIO0_S);
 
 	/* SIO1_R : uart receive data */
-	irq_desc[M32R_IRQ_SIO1_R].status = IRQ_DISABLED;
-	irq_desc[M32R_IRQ_SIO1_R].chip = &oaks32r_irq_type;
-	irq_desc[M32R_IRQ_SIO1_R].action = 0;
-	irq_desc[M32R_IRQ_SIO1_R].depth = 1;
+	set_irq_chip_and_handler(M32R_IRQ_SIO1_R, &oaks32r_irq_type,
+				 handle_level_irq);
 	icu_data[M32R_IRQ_SIO1_R].icucr = 0;
 	disable_oaks32r_irq(M32R_IRQ_SIO1_R);
 
 	/* SIO1_S : uart send data */
-	irq_desc[M32R_IRQ_SIO1_S].status = IRQ_DISABLED;
-	irq_desc[M32R_IRQ_SIO1_S].chip = &oaks32r_irq_type;
-	irq_desc[M32R_IRQ_SIO1_S].action = 0;
-	irq_desc[M32R_IRQ_SIO1_S].depth = 1;
+	set_irq_chip_and_handler(M32R_IRQ_SIO1_S, &oaks32r_irq_type,
+				 handle_level_irq);
 	icu_data[M32R_IRQ_SIO1_S].icucr = 0;
 	disable_oaks32r_irq(M32R_IRQ_SIO1_S);
 #endif /* CONFIG_SERIAL_M32R_SIO */
diff -druNp linux-libre-2.6.37-gnu1/arch/m32r/platforms/opsput/setup.c linux-libre-2.6.38-gnu1/arch/m32r/platforms/opsput/setup.c
--- linux-libre-2.6.37-gnu1/arch/m32r/platforms/opsput/setup.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/m32r/platforms/opsput/setup.c	2011-03-14 21:20:32.000000000 -0400
@@ -46,39 +46,30 @@ static void enable_opsput_irq(unsigned i
 	outl(data, port);
 }
 
-static void mask_and_ack_opsput(unsigned int irq)
-{
-	disable_opsput_irq(irq);
-}
-
-static void end_opsput_irq(unsigned int irq)
+static void mask_opsput(struct irq_data *data)
 {
-	enable_opsput_irq(irq);
+	disable_opsput_irq(data->irq);
 }
 
-static unsigned int startup_opsput_irq(unsigned int irq)
+static void unmask_opsput(struct irq_data *data)
 {
-	enable_opsput_irq(irq);
-	return (0);
+	enable_opsput_irq(data->irq);
 }
 
-static void shutdown_opsput_irq(unsigned int irq)
+static void shutdown_opsput(struct irq_data *data)
 {
 	unsigned long port;
 
-	port = irq2port(irq);
+	port = irq2port(data->irq);
 	outl(M32R_ICUCR_ILEVEL7, port);
 }
 
 static struct irq_chip opsput_irq_type =
 {
-	.name = "OPSPUT-IRQ",
-	.startup = startup_opsput_irq,
-	.shutdown = shutdown_opsput_irq,
-	.enable = enable_opsput_irq,
-	.disable = disable_opsput_irq,
-	.ack = mask_and_ack_opsput,
-	.end = end_opsput_irq
+	.name		= "OPSPUT-IRQ",
+	.irq_shutdown	= shutdown_opsput,
+	.irq_mask	= mask_opsput,
+	.irq_unmask	= unmask_opsput,
 };
 
 /*
@@ -100,7 +91,6 @@ static void disable_opsput_pld_irq(unsig
 	unsigned int pldirq;
 
 	pldirq = irq2pldirq(irq);
-//	disable_opsput_irq(M32R_IRQ_INT1);
 	port = pldirq2port(pldirq);
 	data = pld_icu_data[pldirq].icucr|PLD_ICUCR_ILEVEL7;
 	outw(data, port);
@@ -112,50 +102,38 @@ static void enable_opsput_pld_irq(unsign
 	unsigned int pldirq;
 
 	pldirq = irq2pldirq(irq);
-//	enable_opsput_irq(M32R_IRQ_INT1);
 	port = pldirq2port(pldirq);
 	data = pld_icu_data[pldirq].icucr|PLD_ICUCR_IEN|PLD_ICUCR_ILEVEL6;
 	outw(data, port);
 }
 
-static void mask_and_ack_opsput_pld(unsigned int irq)
-{
-	disable_opsput_pld_irq(irq);
-//	mask_and_ack_opsput(M32R_IRQ_INT1);
-}
-
-static void end_opsput_pld_irq(unsigned int irq)
+static void mask_opsput_pld(struct irq_data *data)
 {
-	enable_opsput_pld_irq(irq);
-	end_opsput_irq(M32R_IRQ_INT1);
+	disable_opsput_pld_irq(data->irq);
 }
 
-static unsigned int startup_opsput_pld_irq(unsigned int irq)
+static void unmask_opsput_pld(struct irq_data *data)
 {
-	enable_opsput_pld_irq(irq);
-	return (0);
+	enable_opsput_pld_irq(data->irq);
+	enable_opsput_irq(M32R_IRQ_INT1);
 }
 
-static void shutdown_opsput_pld_irq(unsigned int irq)
+static void shutdown_opsput_pld(struct irq_data *data)
 {
 	unsigned long port;
 	unsigned int pldirq;
 
-	pldirq = irq2pldirq(irq);
-//	shutdown_opsput_irq(M32R_IRQ_INT1);
+	pldirq = irq2pldirq(data->irq);
 	port = pldirq2port(pldirq);
 	outw(PLD_ICUCR_ILEVEL7, port);
 }
 
 static struct irq_chip opsput_pld_irq_type =
 {
-	.name = "OPSPUT-PLD-IRQ",
-	.startup = startup_opsput_pld_irq,
-	.shutdown = shutdown_opsput_pld_irq,
-	.enable = enable_opsput_pld_irq,
-	.disable = disable_opsput_pld_irq,
-	.ack = mask_and_ack_opsput_pld,
-	.end = end_opsput_pld_irq
+	.name		= "OPSPUT-PLD-IRQ",
+	.irq_shutdown	= shutdown_opsput_pld,
+	.irq_mask	= mask_opsput_pld,
+	.irq_unmask	= unmask_opsput_pld,
 };
 
 /*
@@ -189,42 +167,33 @@ static void enable_opsput_lanpld_irq(uns
 	outw(data, port);
 }
 
-static void mask_and_ack_opsput_lanpld(unsigned int irq)
-{
-	disable_opsput_lanpld_irq(irq);
-}
-
-static void end_opsput_lanpld_irq(unsigned int irq)
+static void mask_opsput_lanpld(struct irq_data *data)
 {
-	enable_opsput_lanpld_irq(irq);
-	end_opsput_irq(M32R_IRQ_INT0);
+	disable_opsput_lanpld_irq(data->irq);
 }
 
-static unsigned int startup_opsput_lanpld_irq(unsigned int irq)
+static void unmask_opsput_lanpld(struct irq_data *data)
 {
-	enable_opsput_lanpld_irq(irq);
-	return (0);
+	enable_opsput_lanpld_irq(data->irq);
+	enable_opsput_irq(M32R_IRQ_INT0);
 }
 
-static void shutdown_opsput_lanpld_irq(unsigned int irq)
+static void shutdown_opsput_lanpld(struct irq_data *data)
 {
 	unsigned long port;
 	unsigned int pldirq;
 
-	pldirq = irq2lanpldirq(irq);
+	pldirq = irq2lanpldirq(data->irq);
 	port = lanpldirq2port(pldirq);
 	outw(PLD_ICUCR_ILEVEL7, port);
 }
 
 static struct irq_chip opsput_lanpld_irq_type =
 {
-	.name = "OPSPUT-PLD-LAN-IRQ",
-	.startup = startup_opsput_lanpld_irq,
-	.shutdown = shutdown_opsput_lanpld_irq,
-	.enable = enable_opsput_lanpld_irq,
-	.disable = disable_opsput_lanpld_irq,
-	.ack = mask_and_ack_opsput_lanpld,
-	.end = end_opsput_lanpld_irq
+	.name		= "OPSPUT-PLD-LAN-IRQ",
+	.irq_shutdown	= shutdown_opsput_lanpld,
+	.irq_mask	= mask_opsput_lanpld,
+	.irq_unmask	= unmask_opsput_lanpld,
 };
 
 /*
@@ -258,143 +227,109 @@ static void enable_opsput_lcdpld_irq(uns
 	outw(data, port);
 }
 
-static void mask_and_ack_opsput_lcdpld(unsigned int irq)
-{
-	disable_opsput_lcdpld_irq(irq);
-}
-
-static void end_opsput_lcdpld_irq(unsigned int irq)
+static void mask_opsput_lcdpld(struct irq_data *data)
 {
-	enable_opsput_lcdpld_irq(irq);
-	end_opsput_irq(M32R_IRQ_INT2);
+	disable_opsput_lcdpld_irq(data->irq);
 }
 
-static unsigned int startup_opsput_lcdpld_irq(unsigned int irq)
+static void unmask_opsput_lcdpld(struct irq_data *data)
 {
-	enable_opsput_lcdpld_irq(irq);
-	return (0);
+	enable_opsput_lcdpld_irq(data->irq);
+	enable_opsput_irq(M32R_IRQ_INT2);
 }
 
-static void shutdown_opsput_lcdpld_irq(unsigned int irq)
+static void shutdown_opsput_lcdpld(struct irq_data *data)
 {
 	unsigned long port;
 	unsigned int pldirq;
 
-	pldirq = irq2lcdpldirq(irq);
+	pldirq = irq2lcdpldirq(data->irq);
 	port = lcdpldirq2port(pldirq);
 	outw(PLD_ICUCR_ILEVEL7, port);
 }
 
-static struct irq_chip opsput_lcdpld_irq_type =
-{
-	"OPSPUT-PLD-LCD-IRQ",
-	startup_opsput_lcdpld_irq,
-	shutdown_opsput_lcdpld_irq,
-	enable_opsput_lcdpld_irq,
-	disable_opsput_lcdpld_irq,
-	mask_and_ack_opsput_lcdpld,
-	end_opsput_lcdpld_irq
+static struct irq_chip opsput_lcdpld_irq_type = {
+	.name		= "OPSPUT-PLD-LCD-IRQ",
+	.irq_shutdown	= shutdown_opsput_lcdpld,
+	.irq_mask	= mask_opsput_lcdpld,
+	.irq_unmask	= unmask_opsput_lcdpld,
 };
 
 void __init init_IRQ(void)
 {
 #if defined(CONFIG_SMC91X)
 	/* INT#0: LAN controller on OPSPUT-LAN (SMC91C111)*/
-	irq_desc[OPSPUT_LAN_IRQ_LAN].status = IRQ_DISABLED;
-	irq_desc[OPSPUT_LAN_IRQ_LAN].chip = &opsput_lanpld_irq_type;
-	irq_desc[OPSPUT_LAN_IRQ_LAN].action = 0;
-	irq_desc[OPSPUT_LAN_IRQ_LAN].depth = 1;	/* disable nested irq */
+	set_irq_chip_and_handler(OPSPUT_LAN_IRQ_LAN, &opsput_lanpld_irq_type,
+				 handle_level_irq);
 	lanpld_icu_data[irq2lanpldirq(OPSPUT_LAN_IRQ_LAN)].icucr = PLD_ICUCR_IEN|PLD_ICUCR_ISMOD02;	/* "H" edge sense */
 	disable_opsput_lanpld_irq(OPSPUT_LAN_IRQ_LAN);
 #endif  /* CONFIG_SMC91X */
 
 	/* MFT2 : system timer */
-	irq_desc[M32R_IRQ_MFT2].status = IRQ_DISABLED;
-	irq_desc[M32R_IRQ_MFT2].chip = &opsput_irq_type;
-	irq_desc[M32R_IRQ_MFT2].action = 0;
-	irq_desc[M32R_IRQ_MFT2].depth = 1;
+	set_irq_chip_and_handler(M32R_IRQ_MFT2, &opsput_irq_type,
+				 handle_level_irq);
 	icu_data[M32R_IRQ_MFT2].icucr = M32R_ICUCR_IEN;
 	disable_opsput_irq(M32R_IRQ_MFT2);
 
 	/* SIO0 : receive */
-	irq_desc[M32R_IRQ_SIO0_R].status = IRQ_DISABLED;
-	irq_desc[M32R_IRQ_SIO0_R].chip = &opsput_irq_type;
-	irq_desc[M32R_IRQ_SIO0_R].action = 0;
-	irq_desc[M32R_IRQ_SIO0_R].depth = 1;
+	set_irq_chip_and_handler(M32R_IRQ_SIO0_R, &opsput_irq_type,
+				 handle_level_irq);
 	icu_data[M32R_IRQ_SIO0_R].icucr = 0;
 	disable_opsput_irq(M32R_IRQ_SIO0_R);
 
 	/* SIO0 : send */
-	irq_desc[M32R_IRQ_SIO0_S].status = IRQ_DISABLED;
-	irq_desc[M32R_IRQ_SIO0_S].chip = &opsput_irq_type;
-	irq_desc[M32R_IRQ_SIO0_S].action = 0;
-	irq_desc[M32R_IRQ_SIO0_S].depth = 1;
+	set_irq_chip_and_handler(M32R_IRQ_SIO0_S, &opsput_irq_type,
+				 handle_level_irq);
 	icu_data[M32R_IRQ_SIO0_S].icucr = 0;
 	disable_opsput_irq(M32R_IRQ_SIO0_S);
 
 	/* SIO1 : receive */
-	irq_desc[M32R_IRQ_SIO1_R].status = IRQ_DISABLED;
-	irq_desc[M32R_IRQ_SIO1_R].chip = &opsput_irq_type;
-	irq_desc[M32R_IRQ_SIO1_R].action = 0;
-	irq_desc[M32R_IRQ_SIO1_R].depth = 1;
+	set_irq_chip_and_handler(M32R_IRQ_SIO1_R, &opsput_irq_type,
+				 handle_level_irq);
 	icu_data[M32R_IRQ_SIO1_R].icucr = 0;
 	disable_opsput_irq(M32R_IRQ_SIO1_R);
 
 	/* SIO1 : send */
-	irq_desc[M32R_IRQ_SIO1_S].status = IRQ_DISABLED;
-	irq_desc[M32R_IRQ_SIO1_S].chip = &opsput_irq_type;
-	irq_desc[M32R_IRQ_SIO1_S].action = 0;
-	irq_desc[M32R_IRQ_SIO1_S].depth = 1;
+	set_irq_chip_and_handler(M32R_IRQ_SIO1_S, &opsput_irq_type,
+				 handle_level_irq);
 	icu_data[M32R_IRQ_SIO1_S].icucr = 0;
 	disable_opsput_irq(M32R_IRQ_SIO1_S);
 
 	/* DMA1 : */
-	irq_desc[M32R_IRQ_DMA1].status = IRQ_DISABLED;
-	irq_desc[M32R_IRQ_DMA1].chip = &opsput_irq_type;
-	irq_desc[M32R_IRQ_DMA1].action = 0;
-	irq_desc[M32R_IRQ_DMA1].depth = 1;
+	set_irq_chip_and_handler(M32R_IRQ_DMA1, &opsput_irq_type,
+				 handle_level_irq);
 	icu_data[M32R_IRQ_DMA1].icucr = 0;
 	disable_opsput_irq(M32R_IRQ_DMA1);
 
 #ifdef CONFIG_SERIAL_M32R_PLDSIO
 	/* INT#1: SIO0 Receive on PLD */
-	irq_desc[PLD_IRQ_SIO0_RCV].status = IRQ_DISABLED;
-	irq_desc[PLD_IRQ_SIO0_RCV].chip = &opsput_pld_irq_type;
-	irq_desc[PLD_IRQ_SIO0_RCV].action = 0;
-	irq_desc[PLD_IRQ_SIO0_RCV].depth = 1;	/* disable nested irq */
+	set_irq_chip_and_handler(PLD_IRQ_SIO0_RCV, &opsput_pld_irq_type,
+				 handle_level_irq);
 	pld_icu_data[irq2pldirq(PLD_IRQ_SIO0_RCV)].icucr = PLD_ICUCR_IEN|PLD_ICUCR_ISMOD03;
 	disable_opsput_pld_irq(PLD_IRQ_SIO0_RCV);
 
 	/* INT#1: SIO0 Send on PLD */
-	irq_desc[PLD_IRQ_SIO0_SND].status = IRQ_DISABLED;
-	irq_desc[PLD_IRQ_SIO0_SND].chip = &opsput_pld_irq_type;
-	irq_desc[PLD_IRQ_SIO0_SND].action = 0;
-	irq_desc[PLD_IRQ_SIO0_SND].depth = 1;	/* disable nested irq */
+	set_irq_chip_and_handler(PLD_IRQ_SIO0_SND, &opsput_pld_irq_type,
+				 handle_level_irq);
 	pld_icu_data[irq2pldirq(PLD_IRQ_SIO0_SND)].icucr = PLD_ICUCR_IEN|PLD_ICUCR_ISMOD03;
 	disable_opsput_pld_irq(PLD_IRQ_SIO0_SND);
 #endif  /* CONFIG_SERIAL_M32R_PLDSIO */
 
 	/* INT#1: CFC IREQ on PLD */
-	irq_desc[PLD_IRQ_CFIREQ].status = IRQ_DISABLED;
-	irq_desc[PLD_IRQ_CFIREQ].chip = &opsput_pld_irq_type;
-	irq_desc[PLD_IRQ_CFIREQ].action = 0;
-	irq_desc[PLD_IRQ_CFIREQ].depth = 1;	/* disable nested irq */
+	set_irq_chip_and_handler(PLD_IRQ_CFIREQ, &opsput_pld_irq_type,
+				 handle_level_irq);
 	pld_icu_data[irq2pldirq(PLD_IRQ_CFIREQ)].icucr = PLD_ICUCR_IEN|PLD_ICUCR_ISMOD01;	/* 'L' level sense */
 	disable_opsput_pld_irq(PLD_IRQ_CFIREQ);
 
 	/* INT#1: CFC Insert on PLD */
-	irq_desc[PLD_IRQ_CFC_INSERT].status = IRQ_DISABLED;
-	irq_desc[PLD_IRQ_CFC_INSERT].chip = &opsput_pld_irq_type;
-	irq_desc[PLD_IRQ_CFC_INSERT].action = 0;
-	irq_desc[PLD_IRQ_CFC_INSERT].depth = 1;	/* disable nested irq */
+	set_irq_chip_and_handler(PLD_IRQ_CFC_INSERT, &opsput_pld_irq_type,
+				 handle_level_irq);
 	pld_icu_data[irq2pldirq(PLD_IRQ_CFC_INSERT)].icucr = PLD_ICUCR_IEN|PLD_ICUCR_ISMOD00;	/* 'L' edge sense */
 	disable_opsput_pld_irq(PLD_IRQ_CFC_INSERT);
 
 	/* INT#1: CFC Eject on PLD */
-	irq_desc[PLD_IRQ_CFC_EJECT].status = IRQ_DISABLED;
-	irq_desc[PLD_IRQ_CFC_EJECT].chip = &opsput_pld_irq_type;
-	irq_desc[PLD_IRQ_CFC_EJECT].action = 0;
-	irq_desc[PLD_IRQ_CFC_EJECT].depth = 1;	/* disable nested irq */
+	set_irq_chip_and_handler(PLD_IRQ_CFC_EJECT, &opsput_pld_irq_type,
+				 handle_level_irq);
 	pld_icu_data[irq2pldirq(PLD_IRQ_CFC_EJECT)].icucr = PLD_ICUCR_IEN|PLD_ICUCR_ISMOD02;	/* 'H' edge sense */
 	disable_opsput_pld_irq(PLD_IRQ_CFC_EJECT);
 
@@ -413,14 +348,11 @@ void __init init_IRQ(void)
 	enable_opsput_irq(M32R_IRQ_INT1);
 
 #if defined(CONFIG_USB)
-	outw(USBCR_OTGS, USBCR); 	/* USBCR: non-OTG */
-
-    irq_desc[OPSPUT_LCD_IRQ_USB_INT1].status = IRQ_DISABLED;
-    irq_desc[OPSPUT_LCD_IRQ_USB_INT1].chip = &opsput_lcdpld_irq_type;
-    irq_desc[OPSPUT_LCD_IRQ_USB_INT1].action = 0;
-    irq_desc[OPSPUT_LCD_IRQ_USB_INT1].depth = 1;
-    lcdpld_icu_data[irq2lcdpldirq(OPSPUT_LCD_IRQ_USB_INT1)].icucr = PLD_ICUCR_IEN|PLD_ICUCR_ISMOD01;	/* "L" level sense */
-    disable_opsput_lcdpld_irq(OPSPUT_LCD_IRQ_USB_INT1);
+	outw(USBCR_OTGS, USBCR);	/* USBCR: non-OTG */
+	set_irq_chip_and_handler(OPSPUT_LCD_IRQ_USB_INT1,
+				 &opsput_lcdpld_irq_type, handle_level_irq);
+	lcdpld_icu_data[irq2lcdpldirq(OPSPUT_LCD_IRQ_USB_INT1)].icucr = PLD_ICUCR_IEN|PLD_ICUCR_ISMOD01;	/* "L" level sense */
+	disable_opsput_lcdpld_irq(OPSPUT_LCD_IRQ_USB_INT1);
 #endif
 	/*
 	 * INT2# is used for BAT, USB, AUDIO
@@ -433,10 +365,8 @@ void __init init_IRQ(void)
 	/*
 	 * INT3# is used for AR
 	 */
-	irq_desc[M32R_IRQ_INT3].status = IRQ_DISABLED;
-	irq_desc[M32R_IRQ_INT3].chip = &opsput_irq_type;
-	irq_desc[M32R_IRQ_INT3].action = 0;
-	irq_desc[M32R_IRQ_INT3].depth = 1;
+	set_irq_chip_and_handler(M32R_IRQ_INT3, &opsput_irq_type,
+				 handle_level_irq);
 	icu_data[M32R_IRQ_INT3].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD10;
 	disable_opsput_irq(M32R_IRQ_INT3);
 #endif /* CONFIG_VIDEO_M32R_AR */
diff -druNp linux-libre-2.6.37-gnu1/arch/m32r/platforms/usrv/setup.c linux-libre-2.6.38-gnu1/arch/m32r/platforms/usrv/setup.c
--- linux-libre-2.6.37-gnu1/arch/m32r/platforms/usrv/setup.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/m32r/platforms/usrv/setup.c	2011-03-14 21:20:32.000000000 -0400
@@ -37,39 +37,30 @@ static void enable_mappi_irq(unsigned in
 	outl(data, port);
 }
 
-static void mask_and_ack_mappi(unsigned int irq)
-{
-	disable_mappi_irq(irq);
-}
-
-static void end_mappi_irq(unsigned int irq)
+static void mask_mappi(struct irq_data *data)
 {
-	enable_mappi_irq(irq);
+	disable_mappi_irq(data->irq);
 }
 
-static unsigned int startup_mappi_irq(unsigned int irq)
+static void unmask_mappi(struct irq_data *data)
 {
-	enable_mappi_irq(irq);
-	return 0;
+	enable_mappi_irq(data->irq);
 }
 
-static void shutdown_mappi_irq(unsigned int irq)
+static void shutdown_mappi(struct irq_data *data)
 {
 	unsigned long port;
 
-	port = irq2port(irq);
+	port = irq2port(data->irq);
 	outl(M32R_ICUCR_ILEVEL7, port);
 }
 
 static struct irq_chip mappi_irq_type =
 {
-	.name = "M32700-IRQ",
-	.startup = startup_mappi_irq,
-	.shutdown = shutdown_mappi_irq,
-	.enable = enable_mappi_irq,
-	.disable = disable_mappi_irq,
-	.ack = mask_and_ack_mappi,
-	.end = end_mappi_irq
+	.name		= "M32700-IRQ",
+	.irq_shutdown	= shutdown_mappi,
+	.irq_mask	= mask_mappi,
+	.irq_unmask	= unmask_mappi,
 };
 
 /*
@@ -107,42 +98,33 @@ static void enable_m32700ut_pld_irq(unsi
 	outw(data, port);
 }
 
-static void mask_and_ack_m32700ut_pld(unsigned int irq)
-{
-	disable_m32700ut_pld_irq(irq);
-}
-
-static void end_m32700ut_pld_irq(unsigned int irq)
+static void mask_m32700ut_pld(struct irq_data *data)
 {
-	enable_m32700ut_pld_irq(irq);
-	end_mappi_irq(M32R_IRQ_INT1);
+	disable_m32700ut_pld_irq(data->irq);
 }
 
-static unsigned int startup_m32700ut_pld_irq(unsigned int irq)
+static void unmask_m32700ut_pld(struct irq_data *data)
 {
-	enable_m32700ut_pld_irq(irq);
-	return 0;
+	enable_m32700ut_pld_irq(data->irq);
+	enable_mappi_irq(M32R_IRQ_INT1);
 }
 
-static void shutdown_m32700ut_pld_irq(unsigned int irq)
+static void shutdown_m32700ut_pld(struct irq_data *data)
 {
 	unsigned long port;
 	unsigned int pldirq;
 
-	pldirq = irq2pldirq(irq);
+	pldirq = irq2pldirq(data->irq);
 	port = pldirq2port(pldirq);
 	outw(PLD_ICUCR_ILEVEL7, port);
 }
 
 static struct irq_chip m32700ut_pld_irq_type =
 {
-	.name = "USRV-PLD-IRQ",
-	.startup = startup_m32700ut_pld_irq,
-	.shutdown = shutdown_m32700ut_pld_irq,
-	.enable = enable_m32700ut_pld_irq,
-	.disable = disable_m32700ut_pld_irq,
-	.ack = mask_and_ack_m32700ut_pld,
-	.end = end_m32700ut_pld_irq
+	.name		= "USRV-PLD-IRQ",
+	.irq_shutdown	= shutdown_m32700ut_pld,
+	.irq_mask	= mask_m32700ut_pld,
+	.irq_unmask	= unmask_m32700ut_pld,
 };
 
 void __init init_IRQ(void)
@@ -156,53 +138,42 @@ void __init init_IRQ(void)
 		once++;
 
 	/* MFT2 : system timer */
-	irq_desc[M32R_IRQ_MFT2].status = IRQ_DISABLED;
-	irq_desc[M32R_IRQ_MFT2].chip = &mappi_irq_type;
-	irq_desc[M32R_IRQ_MFT2].action = 0;
-	irq_desc[M32R_IRQ_MFT2].depth = 1;
+	set_irq_chip_and_handler(M32R_IRQ_MFT2, &mappi_irq_type,
+				 handle_level_irq);
 	icu_data[M32R_IRQ_MFT2].icucr = M32R_ICUCR_IEN;
 	disable_mappi_irq(M32R_IRQ_MFT2);
 
 #if defined(CONFIG_SERIAL_M32R_SIO)
 	/* SIO0_R : uart receive data */
-	irq_desc[M32R_IRQ_SIO0_R].status = IRQ_DISABLED;
-	irq_desc[M32R_IRQ_SIO0_R].chip = &mappi_irq_type;
-	irq_desc[M32R_IRQ_SIO0_R].action = 0;
-	irq_desc[M32R_IRQ_SIO0_R].depth = 1;
+	set_irq_chip_and_handler(M32R_IRQ_SIO0_R, &mappi_irq_type,
+				 handle_level_irq);
 	icu_data[M32R_IRQ_SIO0_R].icucr = 0;
 	disable_mappi_irq(M32R_IRQ_SIO0_R);
 
 	/* SIO0_S : uart send data */
-	irq_desc[M32R_IRQ_SIO0_S].status = IRQ_DISABLED;
-	irq_desc[M32R_IRQ_SIO0_S].chip = &mappi_irq_type;
-	irq_desc[M32R_IRQ_SIO0_S].action = 0;
-	irq_desc[M32R_IRQ_SIO0_S].depth = 1;
+	set_irq_chip_and_handler(M32R_IRQ_SIO0_S, &mappi_irq_type,
+				 handle_level_irq);
 	icu_data[M32R_IRQ_SIO0_S].icucr = 0;
 	disable_mappi_irq(M32R_IRQ_SIO0_S);
 
 	/* SIO1_R : uart receive data */
-	irq_desc[M32R_IRQ_SIO1_R].status = IRQ_DISABLED;
-	irq_desc[M32R_IRQ_SIO1_R].chip = &mappi_irq_type;
-	irq_desc[M32R_IRQ_SIO1_R].action = 0;
-	irq_desc[M32R_IRQ_SIO1_R].depth = 1;
+	set_irq_chip_and_handler(M32R_IRQ_SIO1_R, &mappi_irq_type,
+				 handle_level_irq);
 	icu_data[M32R_IRQ_SIO1_R].icucr = 0;
 	disable_mappi_irq(M32R_IRQ_SIO1_R);
 
 	/* SIO1_S : uart send data */
-	irq_desc[M32R_IRQ_SIO1_S].status = IRQ_DISABLED;
-	irq_desc[M32R_IRQ_SIO1_S].chip = &mappi_irq_type;
-	irq_desc[M32R_IRQ_SIO1_S].action = 0;
-	irq_desc[M32R_IRQ_SIO1_S].depth = 1;
+	set_irq_chip_and_handler(M32R_IRQ_SIO1_S, &mappi_irq_type,
+				 handle_level_irq);
 	icu_data[M32R_IRQ_SIO1_S].icucr = 0;
 	disable_mappi_irq(M32R_IRQ_SIO1_S);
 #endif  /* CONFIG_SERIAL_M32R_SIO */
 
 	/* INT#67-#71: CFC#0 IREQ on PLD */
 	for (i = 0 ; i < CONFIG_M32R_CFC_NUM ; i++ ) {
-		irq_desc[PLD_IRQ_CF0 + i].status = IRQ_DISABLED;
-		irq_desc[PLD_IRQ_CF0 + i].chip = &m32700ut_pld_irq_type;
-		irq_desc[PLD_IRQ_CF0 + i].action = 0;
-		irq_desc[PLD_IRQ_CF0 + i].depth = 1;	/* disable nested irq */
+		set_irq_chip_and_handler(PLD_IRQ_CF0 + i,
+					 &m32700ut_pld_irq_type,
+					 handle_level_irq);
 		pld_icu_data[irq2pldirq(PLD_IRQ_CF0 + i)].icucr
 			= PLD_ICUCR_ISMOD01;	/* 'L' level sense */
 		disable_m32700ut_pld_irq(PLD_IRQ_CF0 + i);
@@ -210,19 +181,15 @@ void __init init_IRQ(void)
 
 #if defined(CONFIG_SERIAL_8250) || defined(CONFIG_SERIAL_8250_MODULE)
 	/* INT#76: 16552D#0 IREQ on PLD */
-	irq_desc[PLD_IRQ_UART0].status = IRQ_DISABLED;
-	irq_desc[PLD_IRQ_UART0].chip = &m32700ut_pld_irq_type;
-	irq_desc[PLD_IRQ_UART0].action = 0;
-	irq_desc[PLD_IRQ_UART0].depth = 1;	/* disable nested irq */
+	set_irq_chip_and_handler(PLD_IRQ_UART0, &m32700ut_pld_irq_type,
+				 handle_level_irq);
 	pld_icu_data[irq2pldirq(PLD_IRQ_UART0)].icucr
 		= PLD_ICUCR_ISMOD03;	/* 'H' level sense */
 	disable_m32700ut_pld_irq(PLD_IRQ_UART0);
 
 	/* INT#77: 16552D#1 IREQ on PLD */
-	irq_desc[PLD_IRQ_UART1].status = IRQ_DISABLED;
-	irq_desc[PLD_IRQ_UART1].chip = &m32700ut_pld_irq_type;
-	irq_desc[PLD_IRQ_UART1].action = 0;
-	irq_desc[PLD_IRQ_UART1].depth = 1;	/* disable nested irq */
+	set_irq_chip_and_handler(PLD_IRQ_UART1, &m32700ut_pld_irq_type,
+				 handle_level_irq);
 	pld_icu_data[irq2pldirq(PLD_IRQ_UART1)].icucr
 		= PLD_ICUCR_ISMOD03;	/* 'H' level sense */
 	disable_m32700ut_pld_irq(PLD_IRQ_UART1);
@@ -230,10 +197,8 @@ void __init init_IRQ(void)
 
 #if defined(CONFIG_IDC_AK4524) || defined(CONFIG_IDC_AK4524_MODULE)
 	/* INT#80: AK4524 IREQ on PLD */
-	irq_desc[PLD_IRQ_SNDINT].status = IRQ_DISABLED;
-	irq_desc[PLD_IRQ_SNDINT].chip = &m32700ut_pld_irq_type;
-	irq_desc[PLD_IRQ_SNDINT].action = 0;
-	irq_desc[PLD_IRQ_SNDINT].depth = 1;	/* disable nested irq */
+	set_irq_chip_and_handler(PLD_IRQ_SNDINT, &m32700ut_pld_irq_type,
+				 handle_level_irq);
 	pld_icu_data[irq2pldirq(PLD_IRQ_SNDINT)].icucr
 		= PLD_ICUCR_ISMOD01;	/* 'L' level sense */
 	disable_m32700ut_pld_irq(PLD_IRQ_SNDINT);
diff -druNp linux-libre-2.6.37-gnu1/arch/m68k/amiga/config.c linux-libre-2.6.38-gnu1/arch/m68k/amiga/config.c
--- linux-libre-2.6.37-gnu1/arch/m68k/amiga/config.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/m68k/amiga/config.c	2011-03-14 21:20:32.000000000 -0400
@@ -610,17 +610,17 @@ static void amiga_mem_console_write(stru
 
 static int __init amiga_savekmsg_setup(char *arg)
 {
-	static struct resource debug_res = { .name = "Debug" };
-
 	if (!MACH_IS_AMIGA || strcmp(arg, "mem"))
-		goto done;
+		return 0;
 
-	if (!AMIGAHW_PRESENT(CHIP_RAM)) {
-		printk("Warning: no chipram present for debugging\n");
-		goto done;
+	if (amiga_chip_size < SAVEKMSG_MAXMEM) {
+		pr_err("Not enough chipram for debugging\n");
+		return -ENOMEM;
 	}
 
-	savekmsg = amiga_chip_alloc_res(SAVEKMSG_MAXMEM, &debug_res);
+	/* Just steal the block, the chipram allocator isn't functional yet */
+	amiga_chip_size -= SAVEKMSG_MAXMEM;
+	savekmsg = (void *)ZTWO_VADDR(CHIP_PHYSADDR + amiga_chip_size);
 	savekmsg->magic1 = SAVEKMSG_MAGIC1;
 	savekmsg->magic2 = SAVEKMSG_MAGIC2;
 	savekmsg->magicptr = ZTWO_PADDR(savekmsg);
@@ -628,8 +628,6 @@ static int __init amiga_savekmsg_setup(c
 
 	amiga_console_driver.write = amiga_mem_console_write;
 	register_console(&amiga_console_driver);
-
-done:
 	return 0;
 }
 
diff -druNp linux-libre-2.6.37-gnu1/arch/m68k/atari/ataints.c linux-libre-2.6.38-gnu1/arch/m68k/atari/ataints.c
--- linux-libre-2.6.37-gnu1/arch/m68k/atari/ataints.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/m68k/atari/ataints.c	2011-03-14 21:20:32.000000000 -0400
@@ -388,9 +388,9 @@ void __init atari_init_IRQ(void)
 	}
 
 	if (ATARIHW_PRESENT(SCC) && !atari_SCC_reset_done) {
-		scc.cha_a_ctrl = 9;
+		atari_scc.cha_a_ctrl = 9;
 		MFPDELAY();
-		scc.cha_a_ctrl = (char) 0xc0; /* hardware reset */
+		atari_scc.cha_a_ctrl = (char) 0xc0; /* hardware reset */
 	}
 
 	if (ATARIHW_PRESENT(SCU)) {
diff -druNp linux-libre-2.6.37-gnu1/arch/m68k/atari/config.c linux-libre-2.6.38-gnu1/arch/m68k/atari/config.c
--- linux-libre-2.6.37-gnu1/arch/m68k/atari/config.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/m68k/atari/config.c	2011-03-14 21:20:32.000000000 -0400
@@ -315,7 +315,7 @@ void __init config_atari(void)
 		ATARIHW_SET(SCC_DMA);
 		printk("SCC_DMA ");
 	}
-	if (scc_test(&scc.cha_a_ctrl)) {
+	if (scc_test(&atari_scc.cha_a_ctrl)) {
 		ATARIHW_SET(SCC);
 		printk("SCC ");
 	}
diff -druNp linux-libre-2.6.37-gnu1/arch/m68k/atari/debug.c linux-libre-2.6.38-gnu1/arch/m68k/atari/debug.c
--- linux-libre-2.6.37-gnu1/arch/m68k/atari/debug.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/m68k/atari/debug.c	2011-03-14 21:20:32.000000000 -0400
@@ -53,9 +53,9 @@ static inline void ata_scc_out(char c)
 {
 	do {
 		MFPDELAY();
-	} while (!(scc.cha_b_ctrl & 0x04)); /* wait for tx buf empty */
+	} while (!(atari_scc.cha_b_ctrl & 0x04)); /* wait for tx buf empty */
 	MFPDELAY();
-	scc.cha_b_data = c;
+	atari_scc.cha_b_data = c;
 }
 
 static void atari_scc_console_write(struct console *co, const char *str,
@@ -140,9 +140,9 @@ int atari_scc_console_wait_key(struct co
 {
 	do {
 		MFPDELAY();
-	} while (!(scc.cha_b_ctrl & 0x01)); /* wait for rx buf filled */
+	} while (!(atari_scc.cha_b_ctrl & 0x01)); /* wait for rx buf filled */
 	MFPDELAY();
-	return scc.cha_b_data;
+	return atari_scc.cha_b_data;
 }
 
 int atari_midi_console_wait_key(struct console *co)
@@ -185,9 +185,9 @@ static void __init atari_init_mfp_port(i
 
 #define SCC_WRITE(reg, val)				\
 	do {						\
-		scc.cha_b_ctrl = (reg);			\
+		atari_scc.cha_b_ctrl = (reg);		\
 		MFPDELAY();				\
-		scc.cha_b_ctrl = (val);			\
+		atari_scc.cha_b_ctrl = (val);		\
 		MFPDELAY();				\
 	} while (0)
 
@@ -240,7 +240,7 @@ static void __init atari_init_scc_port(i
 	reg3 = (cflag & CSIZE) == CS8 ? 0xc0 : 0x40;
 	reg5 = (cflag & CSIZE) == CS8 ? 0x60 : 0x20 | 0x82 /* assert DTR/RTS */;
 
-	(void)scc.cha_b_ctrl;		/* reset reg pointer */
+	(void)atari_scc.cha_b_ctrl;	/* reset reg pointer */
 	SCC_WRITE(9, 0xc0);		/* reset */
 	LONG_DELAY();			/* extra delay after WR9 access */
 	SCC_WRITE(4, (cflag & PARENB) ? ((cflag & PARODD) ? 0x01 : 0x03)
diff -druNp linux-libre-2.6.37-gnu1/arch/m68k/ifpsp060/src/fpsp.S linux-libre-2.6.38-gnu1/arch/m68k/ifpsp060/src/fpsp.S
--- linux-libre-2.6.37-gnu1/arch/m68k/ifpsp060/src/fpsp.S	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/m68k/ifpsp060/src/fpsp.S	2011-03-14 21:20:32.000000000 -0400
@@ -3881,7 +3881,7 @@ _fpsp_fline:
 # FP Unimplemented Instruction stack frame and jump to that entry
 # point.
 #
-# but, if the FPU is disabled, then we need to jump to the FPU diabled
+# but, if the FPU is disabled, then we need to jump to the FPU disabled
 # entry point.
 	movc		%pcr,%d0
 	btst		&0x1,%d0
diff -druNp linux-libre-2.6.37-gnu1/arch/m68k/include/asm/atarihw.h linux-libre-2.6.38-gnu1/arch/m68k/include/asm/atarihw.h
--- linux-libre-2.6.37-gnu1/arch/m68k/include/asm/atarihw.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/m68k/include/asm/atarihw.h	2011-03-14 21:20:32.000000000 -0400
@@ -449,7 +449,7 @@ struct SCC
   u_char char_dummy3;
   u_char cha_b_data;
  };
-# define scc ((*(volatile struct SCC*)SCC_BAS))
+# define atari_scc ((*(volatile struct SCC*)SCC_BAS))
 
 /* The ESCC (Z85230) in an Atari ST. The channels are reversed! */
 # define st_escc ((*(volatile struct SCC*)0xfffffa31))
diff -druNp linux-libre-2.6.37-gnu1/arch/m68k/include/asm/cacheflush_no.h linux-libre-2.6.38-gnu1/arch/m68k/include/asm/cacheflush_no.h
--- linux-libre-2.6.37-gnu1/arch/m68k/include/asm/cacheflush_no.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/m68k/include/asm/cacheflush_no.h	2011-03-14 21:20:32.000000000 -0400
@@ -2,21 +2,22 @@
 #define _M68KNOMMU_CACHEFLUSH_H
 
 /*
- * (C) Copyright 2000-2004, Greg Ungerer <gerg@snapgear.com>
+ * (C) Copyright 2000-2010, Greg Ungerer <gerg@snapgear.com>
  */
 #include <linux/mm.h>
+#include <asm/mcfsim.h>
 
 #define flush_cache_all()			__flush_cache_all()
 #define flush_cache_mm(mm)			do { } while (0)
 #define flush_cache_dup_mm(mm)			do { } while (0)
-#define flush_cache_range(vma, start, end)	__flush_cache_all()
+#define flush_cache_range(vma, start, end)	do { } while (0)
 #define flush_cache_page(vma, vmaddr)		do { } while (0)
-#define flush_dcache_range(start,len)		__flush_cache_all()
+#define flush_dcache_range(start, len)		__flush_dcache_all()
 #define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 0
 #define flush_dcache_page(page)			do { } while (0)
 #define flush_dcache_mmap_lock(mapping)		do { } while (0)
 #define flush_dcache_mmap_unlock(mapping)	do { } while (0)
-#define flush_icache_range(start,len)		__flush_cache_all()
+#define flush_icache_range(start, len)		__flush_icache_all()
 #define flush_icache_page(vma,pg)		do { } while (0)
 #define flush_icache_user_range(vma,pg,adr,len)	do { } while (0)
 #define flush_cache_vmap(start, end)		do { } while (0)
@@ -27,66 +28,52 @@
 #define copy_from_user_page(vma, page, vaddr, dst, src, len) \
 	memcpy(dst, src, len)
 
+void mcf_cache_push(void);
+
 static inline void __flush_cache_all(void)
 {
-#if defined(CONFIG_M5407) || defined(CONFIG_M548x)
-	/*
-	 *	Use cpushl to push and invalidate all cache lines.
-	 *	Gas doesn't seem to know how to generate the ColdFire
-	 *	cpushl instruction... Oh well, bit stuff it for now.
-	 */
-	__asm__ __volatile__ (
-		"nop\n\t"
-		"clrl	%%d0\n\t"
-		"1:\n\t"
-		"movel	%%d0,%%a0\n\t"
-		"2:\n\t"
-		".word	0xf468\n\t"
-		"addl	#0x10,%%a0\n\t"
-		"cmpl	#0x00000800,%%a0\n\t"
-		"blt	2b\n\t"
-		"addql	#1,%%d0\n\t"
-		"cmpil	#4,%%d0\n\t"
-		"bne	1b\n\t"
-		"movel	#0xb6088500,%%d0\n\t"
-		"movec	%%d0,%%CACR\n\t"
-		: : : "d0", "a0" );
-#endif /* CONFIG_M5407 */
-#if defined(CONFIG_M523x) || defined(CONFIG_M527x)
-	__asm__ __volatile__ (
-		"movel	#0x81400100, %%d0\n\t"
-		"movec	%%d0, %%CACR\n\t"
-		"nop\n\t"
-		: : : "d0" );
-#endif /* CONFIG_M523x || CONFIG_M527x */
-#if defined(CONFIG_M528x)
-	__asm__ __volatile__ (
-		"movel	#0x81000200, %%d0\n\t"
-		"movec	%%d0, %%CACR\n\t"
-		"nop\n\t"
-		: : : "d0" );
-#endif /* CONFIG_M528x */
-#if defined(CONFIG_M5206) || defined(CONFIG_M5206e) || defined(CONFIG_M5272)
+#ifdef CACHE_PUSH
+	mcf_cache_push();
+#endif
+#ifdef CACHE_INVALIDATE
 	__asm__ __volatile__ (
-		"movel	#0x81000100, %%d0\n\t"
+		"movel	%0, %%d0\n\t"
 		"movec	%%d0, %%CACR\n\t"
 		"nop\n\t"
-		: : : "d0" );
-#endif /* CONFIG_M5206 || CONFIG_M5206e || CONFIG_M5272 */
-#ifdef CONFIG_M5249
+		: : "i" (CACHE_INVALIDATE) : "d0" );
+#endif
+}
+
+/*
+ * Some ColdFire parts implement separate instruction and data caches,
+ * on those we should just flush the appropriate cache. If we don't need
+ * to do any specific flushing then this will be optimized away.
+ */
+static inline void __flush_icache_all(void)
+{
+#ifdef CACHE_INVALIDATEI
 	__asm__ __volatile__ (
-		"movel	#0xa1000200, %%d0\n\t"
+		"movel	%0, %%d0\n\t"
 		"movec	%%d0, %%CACR\n\t"
 		"nop\n\t"
-		: : : "d0" );
-#endif /* CONFIG_M5249 */
-#ifdef CONFIG_M532x
+		: : "i" (CACHE_INVALIDATEI) : "d0" );
+#endif
+}
+
+static inline void __flush_dcache_all(void)
+{
+#ifdef CACHE_PUSH
+	mcf_cache_push();
+#endif
+#ifdef CACHE_INVALIDATED
 	__asm__ __volatile__ (
-		"movel	#0x81000200, %%d0\n\t"
+		"movel	%0, %%d0\n\t"
 		"movec	%%d0, %%CACR\n\t"
 		"nop\n\t"
-		: : : "d0" );
-#endif /* CONFIG_M532x */
+		: : "i" (CACHE_INVALIDATED) : "d0" );
+#else
+	/* Flush the wrtite buffer */
+	__asm__ __volatile__ ( "nop" );
+#endif
 }
-
 #endif /* _M68KNOMMU_CACHEFLUSH_H */
diff -druNp linux-libre-2.6.37-gnu1/arch/m68k/include/asm/coldfire.h linux-libre-2.6.38-gnu1/arch/m68k/include/asm/coldfire.h
--- linux-libre-2.6.37-gnu1/arch/m68k/include/asm/coldfire.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/m68k/include/asm/coldfire.h	2011-03-14 21:20:32.000000000 -0400
@@ -32,7 +32,7 @@
  */
 #define	MCF_MBAR	0x10000000
 #define	MCF_MBAR2	0x80000000
-#if defined(CONFIG_M548x)
+#if defined(CONFIG_M54xx)
 #define	MCF_IPSBAR	MCF_MBAR
 #elif defined(CONFIG_M520x)
 #define	MCF_IPSBAR	0xFC000000
diff -druNp linux-libre-2.6.37-gnu1/arch/m68k/include/asm/entry_no.h linux-libre-2.6.38-gnu1/arch/m68k/include/asm/entry_no.h
--- linux-libre-2.6.37-gnu1/arch/m68k/include/asm/entry_no.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/m68k/include/asm/entry_no.h	2011-03-14 21:20:32.000000000 -0400
@@ -42,12 +42,16 @@
  */
 
 #ifdef CONFIG_COLDFIRE
+#ifdef CONFIG_COLDFIRE_SW_A7
 /*
- * This is made a little more tricky on the ColdFire. There is no
- * separate kernel and user stack pointers. Need to artificially
+ * 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 could happen.
+ * 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? */
@@ -74,9 +78,7 @@
 	7:
 .endm
 
-.macro RESTORE_ALL
-	btst	#5,%sp@(PT_SR)		/* going user? */
-	bnes	8f			/* no, skip */
+.macro RESTORE_USER
 	move	#0x2700,%sr		/* disable intrs */
 	movel	sw_usp,%a0		/* get usp */
 	movel	%sp@(PT_OFF_PC),%a0@-	/* copy exception program counter */
@@ -91,19 +93,22 @@
 	subql	#8,sw_usp		/* set exception */
 	movel	sw_usp,%sp		/* restore usp */
 	rte
-	8:
-	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
+	movel	sw_usp,%a2
+.endm
+
+.macro WRUSP
+	movel	%a0,sw_usp
+.endm
+
+#else /* !CONFIG_COLDFIRE_SW_A7 */
 /*
- * Quick exception save, use current stack only.
+ * Modern ColdFire parts have separate supervisor and user stack
+ * pointers. Simple load and restore macros for this case.
  */
-.macro SAVE_LOCAL
+.macro SAVE_ALL
 	move	#0x2700,%sr		/* disable intrs */
 	clrl	%sp@-			/* stkadj */
 	movel	%d0,%sp@-		/* orig d0 */
@@ -112,7 +117,7 @@
 	moveml	%d1-%d5/%a0-%a2,%sp@
 .endm
 
-.macro RESTORE_LOCAL
+.macro RESTORE_USER
 	moveml	%sp@,%d1-%d5/%a0-%a2
 	lea	%sp@(32),%sp		/* space for 8 regs */
 	movel	%sp@+,%d0
@@ -121,6 +126,18 @@
 	rte
 .endm
 
+.macro RDUSP
+	/*move	%usp,%a2*/
+	.word	0x4e6a
+.endm
+
+.macro WRUSP
+	/*move	%a0,%usp*/
+	.word	0x4e60
+.endm
+
+#endif /* !CONFIG_COLDFIRE_SW_A7 */
+
 .macro SAVE_SWITCH_STACK
 	lea	%sp@(-24),%sp		/* 6 regs */
 	moveml	%a3-%a6/%d6-%d7,%sp@
@@ -131,14 +148,6 @@
 	lea	%sp@(24),%sp		/* 6 regs */
 .endm
 
-/*
- * Software copy of the user and kernel stack pointers... Ugh...
- * Need these to get around ColdFire not having separate kernel
- * and user stack pointers.
- */
-.globl sw_usp
-.globl sw_ksp
-
 #else /* !CONFIG_COLDFIRE */
 
 /*
@@ -167,6 +176,6 @@
 	moveml	%sp@+,%a3-%a6/%d6-%d7
 .endm
 
-#endif /* !CONFIG_COLDFIRE */
+#endif /* !COLDFIRE_SW_A7 */
 #endif /* __ASSEMBLY__ */
 #endif /* __M68KNOMMU_ENTRY_H */
diff -druNp linux-libre-2.6.37-gnu1/arch/m68k/include/asm/gpio.h linux-libre-2.6.38-gnu1/arch/m68k/include/asm/gpio.h
--- linux-libre-2.6.37-gnu1/arch/m68k/include/asm/gpio.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/m68k/include/asm/gpio.h	2011-03-14 21:20:32.000000000 -0400
@@ -37,7 +37,7 @@
 #if defined(CONFIG_M5206) || defined(CONFIG_M5206e) || \
     defined(CONFIG_M520x) || defined(CONFIG_M523x) || \
     defined(CONFIG_M527x) || defined(CONFIG_M528x) || \
-    defined(CONFIG_M532x) || defined(CONFIG_M548x)
+    defined(CONFIG_M532x) || defined(CONFIG_M54xx)
 
 /* These parts have GPIO organized by 8 bit ports */
 
diff -druNp linux-libre-2.6.37-gnu1/arch/m68k/include/asm/io_no.h linux-libre-2.6.38-gnu1/arch/m68k/include/asm/io_no.h
--- linux-libre-2.6.37-gnu1/arch/m68k/include/asm/io_no.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/m68k/include/asm/io_no.h	2011-03-14 21:20:32.000000000 -0400
@@ -145,7 +145,6 @@ static inline void io_insl(unsigned int
 #define IOMAP_WRITETHROUGH		3
 
 extern void *__ioremap(unsigned long physaddr, unsigned long size, int cacheflag);
-extern void __iounmap(void *addr, unsigned long size);
 
 static inline void *ioremap(unsigned long physaddr, unsigned long size)
 {
diff -druNp linux-libre-2.6.37-gnu1/arch/m68k/include/asm/m5206sim.h linux-libre-2.6.38-gnu1/arch/m68k/include/asm/m5206sim.h
--- linux-libre-2.6.37-gnu1/arch/m68k/include/asm/m5206sim.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/m68k/include/asm/m5206sim.h	2011-03-14 21:20:32.000000000 -0400
@@ -12,6 +12,10 @@
 #define	m5206sim_h
 /****************************************************************************/
 
+#define	CPU_NAME		"COLDFIRE(m5206)"
+#define	CPU_INSTR_PER_JIFFY	3
+
+#include <asm/m52xxacr.h>
 
 /*
  *	Define the 5206 SIM register set addresses.
@@ -88,6 +92,14 @@
 #define	MCFSIM_PADDR		(MCF_MBAR + 0x1c5)	/* Parallel Direction (r/w) */
 #define	MCFSIM_PADAT		(MCF_MBAR + 0x1c9)	/* Parallel Port Value (r/w) */
 
+#if defined(CONFIG_NETtel)
+#define	MCFUART_BASE1		0x180		/* Base address of UART1 */
+#define	MCFUART_BASE2		0x140		/* Base address of UART2 */
+#else
+#define	MCFUART_BASE1		0x140		/* Base address of UART1 */
+#define	MCFUART_BASE2		0x180		/* Base address of UART2 */
+#endif
+
 /*
  *	Define system peripheral IRQ usage.
  */
@@ -95,7 +107,7 @@
 #define	MCF_IRQ_PROFILER	31		/* Timer1, Level 7 */
 
 /*
- * Generic GPIO
+ *	Generic GPIO
  */
 #define MCFGPIO_PIN_MAX		8
 #define MCFGPIO_IRQ_VECBASE	-1
diff -druNp linux-libre-2.6.37-gnu1/arch/m68k/include/asm/m520xsim.h linux-libre-2.6.38-gnu1/arch/m68k/include/asm/m520xsim.h
--- linux-libre-2.6.37-gnu1/arch/m68k/include/asm/m520xsim.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/m68k/include/asm/m520xsim.h	2011-03-14 21:20:32.000000000 -0400
@@ -11,6 +11,11 @@
 #define m520xsim_h
 /****************************************************************************/
 
+#define	CPU_NAME		"COLDFIRE(m520x)"
+#define	CPU_INSTR_PER_JIFFY	3
+
+#include <asm/m52xxacr.h>
+
 /*
  *  Define the 520x SIM register set addresses.
  */
@@ -54,6 +59,9 @@
 #define MCFSIM_SDCS0        0x000a8110	/* SDRAM Chip Select 0 Configuration */
 #define MCFSIM_SDCS1        0x000a8114	/* SDRAM Chip Select 1 Configuration */
 
+/*
+ * EPORT and GPIO registers.
+ */
 #define MCFEPORT_EPDDR			0xFC088002
 #define MCFEPORT_EPDR			0xFC088004
 #define MCFEPORT_EPPDR			0xFC088005
@@ -97,6 +105,7 @@
 #define MCFGPIO_PCLRR_UART		0xFC0A402A
 #define MCFGPIO_PCLRR_FECH		0xFC0A402B
 #define MCFGPIO_PCLRR_FECL		0xFC0A402C
+
 /*
  * Generic GPIO support
  */
@@ -109,7 +118,6 @@
 #define MCFGPIO_PIN_MAX			80
 #define MCFGPIO_IRQ_MAX			8
 #define MCFGPIO_IRQ_VECBASE		MCFINT_VECBASE
-/****************************************************************************/
 
 #define MCF_GPIO_PAR_UART                   (0xA4036)
 #define MCF_GPIO_PAR_FECI2C                 (0xA4033)
@@ -126,6 +134,13 @@
 #define MCF_GPIO_PAR_FECI2C_PAR_SCL_UTXD2   (0x04)
 
 /*
+ *  UART module.
+ */
+#define MCFUART_BASE1		0x60000		/* Base address of UART1 */
+#define MCFUART_BASE2		0x64000		/* Base address of UART2 */
+#define MCFUART_BASE3		0x68000		/* Base address of UART2 */
+
+/*
  *  Reset Controll Unit.
  */
 #define	MCF_RCR			0xFC0A0000
diff -druNp linux-libre-2.6.37-gnu1/arch/m68k/include/asm/m523xsim.h linux-libre-2.6.38-gnu1/arch/m68k/include/asm/m523xsim.h
--- linux-libre-2.6.37-gnu1/arch/m68k/include/asm/m523xsim.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/m68k/include/asm/m523xsim.h	2011-03-14 21:20:32.000000000 -0400
@@ -11,6 +11,10 @@
 #define	m523xsim_h
 /****************************************************************************/
 
+#define	CPU_NAME		"COLDFIRE(m523x)"
+#define	CPU_INSTR_PER_JIFFY	3
+
+#include <asm/m52xxacr.h>
 
 /*
  *	Define the 523x SIM register set addresses.
@@ -50,6 +54,13 @@
 #define	MCF_RCR_SWRESET		0x80		/* Software reset bit */
 #define	MCF_RCR_FRCSTOUT	0x40		/* Force external reset */
 
+/*
+ *  UART module.
+ */
+#define MCFUART_BASE1		0x200           /* Base address of UART1 */
+#define MCFUART_BASE2		0x240           /* Base address of UART2 */
+#define MCFUART_BASE3		0x280           /* Base address of UART3 */
+
 #define MCFGPIO_PODR_ADDR	(MCF_IPSBAR + 0x100000)
 #define MCFGPIO_PODR_DATAH	(MCF_IPSBAR + 0x100001)
 #define MCFGPIO_PODR_DATAL	(MCF_IPSBAR + 0x100002)
diff -druNp linux-libre-2.6.37-gnu1/arch/m68k/include/asm/m5249sim.h linux-libre-2.6.38-gnu1/arch/m68k/include/asm/m5249sim.h
--- linux-libre-2.6.37-gnu1/arch/m68k/include/asm/m5249sim.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/m68k/include/asm/m5249sim.h	2011-03-14 21:20:32.000000000 -0400
@@ -11,6 +11,11 @@
 #define	m5249sim_h
 /****************************************************************************/
 
+#define	CPU_NAME		"COLDFIRE(m5249)"
+#define	CPU_INSTR_PER_JIFFY	3
+
+#include <asm/m52xxacr.h>
+
 /*
  *	Define the 5249 SIM register set addresses.
  */
@@ -56,6 +61,11 @@
 #define MCFSIM_DACR1		0x110		/* DRAM 1 Addr and Ctrl (r/w) */
 #define MCFSIM_DMR1		0x114		/* DRAM 1 Mask reg (r/w) */
 
+/*
+ *	UART module.
+ */
+#define MCFUART_BASE1		0x1c0           /* Base address of UART1 */
+#define MCFUART_BASE2		0x200           /* Base address of UART2 */
 
 /*
  *	Some symbol defines for the above...
diff -druNp linux-libre-2.6.37-gnu1/arch/m68k/include/asm/m5272sim.h linux-libre-2.6.38-gnu1/arch/m68k/include/asm/m5272sim.h
--- linux-libre-2.6.37-gnu1/arch/m68k/include/asm/m5272sim.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/m68k/include/asm/m5272sim.h	2011-03-14 21:20:32.000000000 -0400
@@ -12,6 +12,11 @@
 #define	m5272sim_h
 /****************************************************************************/
 
+#define	CPU_NAME		"COLDFIRE(m5272)"
+#define	CPU_INSTR_PER_JIFFY	3
+
+#include <asm/m52xxacr.h>
+
 /*
  *	Define the 5272 SIM register set addresses.
  */
@@ -62,6 +67,9 @@
 #define	MCFSIM_DCMR1		0x5c		/* DRAM 1 Mask reg (r/w) */
 #define	MCFSIM_DCCR1		0x63		/* DRAM 1 Control reg (r/w) */
 
+#define	MCFUART_BASE1		0x100		/* Base address of UART1 */
+#define	MCFUART_BASE2		0x140		/* Base address of UART2 */
+
 #define	MCFSIM_PACNT		(MCF_MBAR + 0x80) /* Port A Control (r/w) */
 #define	MCFSIM_PADDR		(MCF_MBAR + 0x84) /* Port A Direction (r/w) */
 #define	MCFSIM_PADAT		(MCF_MBAR + 0x86) /* Port A Data (r/w) */
diff -druNp linux-libre-2.6.37-gnu1/arch/m68k/include/asm/m527xsim.h linux-libre-2.6.38-gnu1/arch/m68k/include/asm/m527xsim.h
--- linux-libre-2.6.37-gnu1/arch/m68k/include/asm/m527xsim.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/m68k/include/asm/m527xsim.h	2011-03-14 21:20:32.000000000 -0400
@@ -11,6 +11,10 @@
 #define	m527xsim_h
 /****************************************************************************/
 
+#define	CPU_NAME		"COLDFIRE(m527x)"
+#define	CPU_INSTR_PER_JIFFY	3
+
+#include <asm/m52xxacr.h>
 
 /*
  *	Define the 5270/5271 SIM register set addresses.
@@ -55,6 +59,12 @@
 #define	MCFSIM_DMR1		0x5c		/* SDRAM address mask 1 */
 #endif
 
+/*
+ *	UART module.
+ */
+#define MCFUART_BASE1		0x200           /* Base address of UART1 */
+#define MCFUART_BASE2		0x240           /* Base address of UART2 */
+#define MCFUART_BASE3		0x280           /* Base address of UART3 */
 
 #ifdef CONFIG_M5271
 #define MCFGPIO_PODR_ADDR	(MCF_IPSBAR + 0x100000)
diff -druNp linux-libre-2.6.37-gnu1/arch/m68k/include/asm/m528xsim.h linux-libre-2.6.38-gnu1/arch/m68k/include/asm/m528xsim.h
--- linux-libre-2.6.37-gnu1/arch/m68k/include/asm/m528xsim.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/m68k/include/asm/m528xsim.h	2011-03-14 21:20:32.000000000 -0400
@@ -11,6 +11,10 @@
 #define	m528xsim_h
 /****************************************************************************/
 
+#define	CPU_NAME		"COLDFIRE(m528x)"
+#define	CPU_INSTR_PER_JIFFY	3
+
+#include <asm/m52xxacr.h>
 
 /*
  *	Define the 5280/5282 SIM register set addresses.
@@ -42,6 +46,13 @@
 #define	MCFSIM_DMR1		0x54		/* SDRAM address mask 1 */
 
 /*
+ *	UART module.
+ */
+#define MCFUART_BASE1		0x200           /* Base address of UART1 */
+#define MCFUART_BASE2		0x240           /* Base address of UART2 */
+#define MCFUART_BASE3		0x280           /* Base address of UART3 */
+
+/*
  * 	GPIO registers
  */
 #define MCFGPIO_PORTA		(MCF_IPSBAR + 0x00100000)
diff -druNp linux-libre-2.6.37-gnu1/arch/m68k/include/asm/m52xxacr.h linux-libre-2.6.38-gnu1/arch/m68k/include/asm/m52xxacr.h
--- linux-libre-2.6.37-gnu1/arch/m68k/include/asm/m52xxacr.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/m68k/include/asm/m52xxacr.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,94 @@
+/****************************************************************************/
+
+/*
+ * m52xxacr.h -- ColdFire version 2 core cache support
+ *
+ * (C) Copyright 2010, Greg Ungerer <gerg@snapgear.com>
+ */
+
+/****************************************************************************/
+#ifndef m52xxacr_h
+#define m52xxacr_h
+/****************************************************************************/
+
+/*
+ * All varients of the ColdFire using version 2 cores have a similar
+ * cache setup. Although not absolutely identical the cache register
+ * definitions are compatible for all of them. Mostly they support a
+ * configurable cache memory that can be instruction only, data only,
+ * or split instruction and data. The exception is the very old version 2
+ * core based parts, like the 5206(e), 5249 and 5272, which are instruction
+ * cache only. Cache size varies from 2k up to 16k.
+ */
+
+/*
+ * Define the Cache Control register flags.
+ */
+#define CACR_CENB	0x80000000	/* Enable cache */
+#define CACR_CDPI	0x10000000	/* Disable invalidation by CPUSHL */
+#define CACR_CFRZ	0x08000000	/* Cache freeze mode */
+#define CACR_CINV	0x01000000	/* Invalidate cache */
+#define CACR_DISI	0x00800000	/* Disable instruction cache */
+#define CACR_DISD	0x00400000	/* Disable data cache */
+#define CACR_INVI	0x00200000	/* Invalidate instruction cache */
+#define CACR_INVD	0x00100000	/* Invalidate data cache */
+#define CACR_CEIB	0x00000400	/* Non-cachable instruction burst */
+#define CACR_DCM	0x00000200	/* Default cache mode */
+#define CACR_DBWE	0x00000100	/* Buffered write enable */
+#define CACR_DWP	0x00000020	/* Write protection */
+#define CACR_EUSP	0x00000010	/* Enable separate user a7 */
+
+/*
+ * Define the Access Control register flags.
+ */
+#define ACR_BASE_POS	24		/* Address Base (upper 8 bits) */
+#define ACR_MASK_POS	16		/* Address Mask (next 8 bits) */
+#define ACR_ENABLE	0x00008000	/* Enable this ACR */
+#define ACR_USER	0x00000000	/* Allow only user accesses */
+#define ACR_SUPER	0x00002000	/* Allow supervisor access only */
+#define ACR_ANY		0x00004000	/* Allow any access type */
+#define ACR_CENB	0x00000000	/* Caching of region enabled */
+#define ACR_CDIS	0x00000040	/* Caching of region disabled */
+#define ACR_BWE		0x00000020	/* Write buffer enabled */
+#define ACR_WPROTECT	0x00000004	/* Write protect region */
+
+/*
+ * Set the cache controller settings we will use. On the cores that support
+ * a split cache configuration we allow all the combinations at Kconfig
+ * time. For those cores that only have an instruction cache we just set
+ * that as on.
+ */
+#if defined(CONFIG_CACHE_I)
+#define CACHE_TYPE	(CACR_DISD + CACR_EUSP)
+#define CACHE_INVTYPEI	0
+#elif defined(CONFIG_CACHE_D)
+#define CACHE_TYPE	(CACR_DISI + CACR_EUSP)
+#define CACHE_INVTYPED	0
+#elif defined(CONFIG_CACHE_BOTH)
+#define CACHE_TYPE	CACR_EUSP
+#define CACHE_INVTYPEI	CACR_INVI
+#define CACHE_INVTYPED	CACR_INVD
+#else
+/* This is the instruction cache only devices (no split cache, no eusp) */
+#define CACHE_TYPE	0
+#define CACHE_INVTYPEI	0
+#endif
+
+#define CACHE_INIT	(CACR_CINV + CACHE_TYPE)
+#define CACHE_MODE	(CACR_CENB + CACHE_TYPE + CACR_DCM)
+
+#define CACHE_INVALIDATE  (CACHE_MODE + CACR_CINV)
+#if defined(CACHE_INVTYPEI)
+#define CACHE_INVALIDATEI (CACHE_MODE + CACR_CINV + CACHE_INVTYPEI)
+#endif
+#if defined(CACHE_INVTYPED)
+#define CACHE_INVALIDATED (CACHE_MODE + CACR_CINV + CACHE_INVTYPED)
+#endif
+
+#define ACR0_MODE	((CONFIG_RAMBASE & 0xff000000) + \
+			 (0x000f0000) + \
+			 (ACR_ENABLE + ACR_ANY + ACR_CENB + ACR_BWE))
+#define ACR1_MODE	0
+
+/****************************************************************************/
+#endif  /* m52xxsim_h */
diff -druNp linux-libre-2.6.37-gnu1/arch/m68k/include/asm/m5307sim.h linux-libre-2.6.38-gnu1/arch/m68k/include/asm/m5307sim.h
--- linux-libre-2.6.37-gnu1/arch/m68k/include/asm/m5307sim.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/m68k/include/asm/m5307sim.h	2011-03-14 21:20:32.000000000 -0400
@@ -14,6 +14,11 @@
 #define	m5307sim_h
 /****************************************************************************/
 
+#define	CPU_NAME		"COLDFIRE(m5307)"
+#define	CPU_INSTR_PER_JIFFY	3
+
+#include <asm/m53xxacr.h>
+
 /*
  *	Define the 5307 SIM register set addresses.
  */
@@ -94,6 +99,17 @@
 #define	MCFSIM_PADAT		(MCF_MBAR + 0x248)
 
 /*
+ *  UART module.
+ */
+#if defined(CONFIG_NETtel) || defined(CONFIG_SECUREEDGEMP3)
+#define MCFUART_BASE1		0x200           /* Base address of UART1 */
+#define MCFUART_BASE2		0x1c0           /* Base address of UART2 */
+#else
+#define MCFUART_BASE1		0x1c0           /* Base address of UART1 */
+#define MCFUART_BASE2		0x200           /* Base address of UART2 */
+#endif
+
+/*
  * Generic GPIO support
  */
 #define MCFGPIO_PIN_MAX			16
@@ -146,32 +162,5 @@
 #define	MCF_IRQ_TIMER		30		/* Timer0, Level 6 */
 #define	MCF_IRQ_PROFILER	31		/* Timer1, Level 7 */
 
-/*
- *	Define the Cache register flags.
- */
-#define	CACR_EC			(1<<31)
-#define	CACR_ESB		(1<<29)
-#define	CACR_DPI		(1<<28)
-#define	CACR_HLCK		(1<<27)
-#define	CACR_CINVA		(1<<24)
-#define	CACR_DNFB		(1<<10)
-#define	CACR_DCM_WTHRU		(0<<8)
-#define	CACR_DCM_WBACK		(1<<8)
-#define	CACR_DCM_OFF_PRE	(2<<8)
-#define	CACR_DCM_OFF_IMP	(3<<8)
-#define	CACR_DW			(1<<5)
-
-#define	ACR_BASE_POS		24
-#define	ACR_MASK_POS		16
-#define	ACR_ENABLE		(1<<15)
-#define	ACR_USER		(0<<13)
-#define	ACR_SUPER		(1<<13)
-#define	ACR_ANY			(2<<13)
-#define	ACR_CM_WTHRU		(0<<5)
-#define	ACR_CM_WBACK		(1<<5)
-#define	ACR_CM_OFF_PRE		(2<<5)
-#define	ACR_CM_OFF_IMP		(3<<5)
-#define	ACR_WPROTECT		(1<<2)
-
 /****************************************************************************/
 #endif	/* m5307sim_h */
diff -druNp linux-libre-2.6.37-gnu1/arch/m68k/include/asm/m532xsim.h linux-libre-2.6.38-gnu1/arch/m68k/include/asm/m532xsim.h
--- linux-libre-2.6.37-gnu1/arch/m68k/include/asm/m532xsim.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/m68k/include/asm/m532xsim.h	2011-03-14 21:20:32.000000000 -0400
@@ -9,6 +9,11 @@
 #define	m532xsim_h
 /****************************************************************************/
 
+#define	CPU_NAME		"COLDFIRE(m532x)"
+#define	CPU_INSTR_PER_JIFFY	3
+
+#include <asm/m53xxacr.h>
+
 #define MCF_REG32(x) (*(volatile unsigned long  *)(x))
 #define MCF_REG16(x) (*(volatile unsigned short *)(x))
 #define MCF_REG08(x) (*(volatile unsigned char  *)(x))
@@ -74,31 +79,11 @@
 #define	MCF_IRQ_PROFILER	(64 + 33)	/* Timer1 */
 
 /*
- *	Define the Cache register flags.
+ *  UART module.
  */
-#define	CACR_EC			(1<<31)
-#define	CACR_ESB		(1<<29)
-#define	CACR_DPI		(1<<28)
-#define	CACR_HLCK		(1<<27)
-#define	CACR_CINVA		(1<<24)
-#define	CACR_DNFB		(1<<10)
-#define	CACR_DCM_WTHRU		(0<<8)
-#define	CACR_DCM_WBACK		(1<<8)
-#define	CACR_DCM_OFF_PRE	(2<<8)
-#define	CACR_DCM_OFF_IMP	(3<<8)
-#define	CACR_DW			(1<<5)
-
-#define	ACR_BASE_POS		24
-#define	ACR_MASK_POS		16
-#define	ACR_ENABLE		(1<<15)
-#define	ACR_USER		(0<<13)
-#define	ACR_SUPER		(1<<13)
-#define	ACR_ANY			(2<<13)
-#define	ACR_CM_WTHRU		(0<<5)
-#define	ACR_CM_WBACK		(1<<5)
-#define	ACR_CM_OFF_PRE		(2<<5)
-#define	ACR_CM_OFF_IMP		(3<<5)
-#define	ACR_WPROTECT		(1<<2)
+#define MCFUART_BASE1		0xFC060000	/* Base address of UART1 */
+#define MCFUART_BASE2		0xFC064000	/* Base address of UART2 */
+#define MCFUART_BASE3		0xFC068000	/* Base address of UART3 */
 
 /*********************************************************************
  *
diff -druNp linux-libre-2.6.37-gnu1/arch/m68k/include/asm/m53xxacr.h linux-libre-2.6.38-gnu1/arch/m68k/include/asm/m53xxacr.h
--- linux-libre-2.6.37-gnu1/arch/m68k/include/asm/m53xxacr.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/m68k/include/asm/m53xxacr.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,101 @@
+/****************************************************************************/
+
+/*
+ * m53xxacr.h -- ColdFire version 3 core cache support
+ *
+ * (C) Copyright 2010, Greg Ungerer <gerg@snapgear.com>
+ */
+
+/****************************************************************************/
+#ifndef m53xxacr_h
+#define m53xxacr_h
+/****************************************************************************/
+
+/*
+ * All varients of the ColdFire using version 3 cores have a similar
+ * cache setup. They have a unified instruction and data cache, with
+ * configurable write-through or copy-back operation.
+ */
+
+/*
+ * Define the Cache Control register flags.
+ */
+#define CACR_EC		0x80000000	/* Enable cache */
+#define CACR_ESB	0x20000000	/* Enable store buffer */
+#define CACR_DPI	0x10000000	/* Disable invalidation by CPUSHL */
+#define CACR_HLCK	0x08000000	/* Half cache lock mode */
+#define CACR_CINVA	0x01000000	/* Invalidate cache */
+#define CACR_DNFB	0x00000400	/* Inhibited fill buffer */
+#define CACR_DCM_WT	0x00000000	/* Cacheable write-through */
+#define CACR_DCM_CB	0x00000100	/* Cacheable copy-back */
+#define CACR_DCM_PRE	0x00000200	/* Cache inhibited, precise */
+#define CACR_DCM_IMPRE	0x00000300	/* Cache inhibited, imprecise */
+#define CACR_WPROTECT	0x00000020	/* Write protect*/
+#define CACR_EUSP	0x00000010	/* Eanble separate user a7 */
+
+/*
+ * Define the Access Control register flags.
+ */
+#define ACR_BASE_POS	24		/* Address Base (upper 8 bits) */
+#define ACR_MASK_POS	16		/* Address Mask (next 8 bits) */
+#define ACR_ENABLE	0x00008000	/* Enable this ACR */
+#define ACR_USER	0x00000000	/* Allow only user accesses */
+#define ACR_SUPER	0x00002000	/* Allow supervisor access only */
+#define ACR_ANY		0x00004000	/* Allow any access type */
+#define ACR_CM_WT	0x00000000	/* Cacheable, write-through */
+#define ACR_CM_CB	0x00000020	/* Cacheable, copy-back */
+#define ACR_CM_PRE	0x00000040	/* Cache inhibited, precise */
+#define ACR_CM_IMPRE	0x00000060	/* Cache inhibited, imprecise */
+#define ACR_WPROTECT	0x00000004	/* Write protect region */
+
+/*
+ * Define the cache type and arrangement (needed for pushes).
+ */
+#if defined(CONFIG_M5307)
+#define	CACHE_SIZE	0x2000		/* 8k of unified cache */
+#define	ICACHE_SIZE	CACHE_SIZE
+#define	DCACHE_SIZE	CACHE_SIZE
+#elif defined(CONFIG_M532x)
+#define	CACHE_SIZE	0x4000		/* 32k of unified cache */
+#define	ICACHE_SIZE	CACHE_SIZE
+#define	DCACHE_SIZE	CACHE_SIZE
+#endif
+
+#define	CACHE_LINE_SIZE	16		/* 16 byte line size */
+#define	CACHE_WAYS	4		/* 4 ways - set associative */
+
+/*
+ * Set the cache controller settings we will use. This default in the
+ * CACR is cache inhibited, we use the ACR register to set cacheing
+ * enabled on the regions we want (eg RAM).
+ */
+#if defined(CONFIG_CACHE_COPYBACK)
+#define CACHE_TYPE	ACR_CM_CB
+#define CACHE_PUSH
+#else
+#define CACHE_TYPE	ACR_CM_WT
+#endif
+
+#ifdef CONFIG_COLDFIRE_SW_A7
+#define CACHE_MODE	(CACR_EC + CACR_ESB + CACR_DCM_PRE)
+#else
+#define CACHE_MODE	(CACR_EC + CACR_ESB + CACR_DCM_PRE + CACR_EUSP)
+#endif
+
+/*
+ * Unified cache means we will never need to flush for coherency of
+ * instruction fetch. We will need to flush to maintain memory/DMA
+ * coherency though in all cases. And for copyback caches we will need
+ * to push cached data as well.
+ */
+#define CACHE_INIT	  CACR_CINVA
+#define CACHE_INVALIDATE  CACR_CINVA
+#define CACHE_INVALIDATED CACR_CINVA
+
+#define ACR0_MODE	((CONFIG_RAMBASE & 0xff000000) + \
+			 (0x000f0000) + \
+			 (ACR_ENABLE + ACR_ANY + CACHE_TYPE))
+#define ACR1_MODE	0
+
+/****************************************************************************/
+#endif  /* m53xxsim_h */
diff -druNp linux-libre-2.6.37-gnu1/arch/m68k/include/asm/m5407sim.h linux-libre-2.6.38-gnu1/arch/m68k/include/asm/m5407sim.h
--- linux-libre-2.6.37-gnu1/arch/m68k/include/asm/m5407sim.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/m68k/include/asm/m5407sim.h	2011-03-14 21:20:32.000000000 -0400
@@ -14,6 +14,11 @@
 #define	m5407sim_h
 /****************************************************************************/
 
+#define	CPU_NAME		"COLDFIRE(m5407)"
+#define	CPU_INSTR_PER_JIFFY	3
+
+#include <asm/m54xxacr.h>
+
 /*
  *	Define the 5407 SIM register set addresses.
  */
@@ -73,6 +78,9 @@
 #define MCFSIM_DACR1		0x110		/* DRAM 1 Addr and Ctrl (r/w) */
 #define MCFSIM_DMR1		0x114		/* DRAM 1 Mask reg (r/w) */
 
+#define MCFUART_BASE1		0x1c0           /* Base address of UART1 */
+#define MCFUART_BASE2		0x200           /* Base address of UART2 */
+
 #define	MCFSIM_PADDR		(MCF_MBAR + 0x244)
 #define	MCFSIM_PADAT		(MCF_MBAR + 0x248)
 
@@ -117,39 +125,5 @@
 #define	MCF_IRQ_TIMER		30		/* Timer0, Level 6 */
 #define	MCF_IRQ_PROFILER	31		/* Timer1, Level 7 */
 
-/*
- *	Define the Cache register flags.
- */
-#define	CACR_DEC		0x80000000	/* Enable data cache */
-#define	CACR_DWP		0x40000000	/* Data write protection */
-#define	CACR_DESB		0x20000000	/* Enable data store buffer */
-#define	CACR_DDPI		0x10000000	/* Disable CPUSHL */
-#define	CACR_DHCLK		0x08000000	/* Half data cache lock mode */
-#define	CACR_DDCM_WT		0x00000000	/* Write through cache*/
-#define	CACR_DDCM_CP		0x02000000	/* Copyback cache */
-#define	CACR_DDCM_P		0x04000000	/* No cache, precise */
-#define	CACR_DDCM_IMP		0x06000000	/* No cache, imprecise */
-#define	CACR_DCINVA		0x01000000	/* Invalidate data cache */
-#define	CACR_BEC		0x00080000	/* Enable branch cache */
-#define	CACR_BCINVA		0x00040000	/* Invalidate branch cache */
-#define	CACR_IEC		0x00008000	/* Enable instruction cache */
-#define	CACR_DNFB		0x00002000	/* Inhibited fill buffer */
-#define	CACR_IDPI		0x00001000	/* Disable CPUSHL */
-#define	CACR_IHLCK		0x00000800	/* Intruction cache half lock */
-#define	CACR_IDCM		0x00000400	/* Intruction cache inhibit */
-#define	CACR_ICINVA		0x00000100	/* Invalidate instr cache */
-
-#define	ACR_BASE_POS		24		/* Address Base */
-#define	ACR_MASK_POS		16		/* Address Mask */
-#define	ACR_ENABLE		0x00008000	/* Enable address */
-#define	ACR_USER		0x00000000	/* User mode access only */
-#define	ACR_SUPER		0x00002000	/* Supervisor mode only */
-#define	ACR_ANY			0x00004000	/* Match any access mode */
-#define	ACR_CM_WT		0x00000000	/* Write through mode */
-#define	ACR_CM_CP		0x00000020	/* Copyback mode */
-#define	ACR_CM_OFF_PRE		0x00000040	/* No cache, precise */
-#define	ACR_CM_OFF_IMP		0x00000060	/* No cache, imprecise */
-#define	ACR_WPROTECT		0x00000004	/* Write protect */
-
 /****************************************************************************/
 #endif	/* m5407sim_h */
diff -druNp linux-libre-2.6.37-gnu1/arch/m68k/include/asm/m548xgpt.h linux-libre-2.6.38-gnu1/arch/m68k/include/asm/m548xgpt.h
--- linux-libre-2.6.37-gnu1/arch/m68k/include/asm/m548xgpt.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/m68k/include/asm/m548xgpt.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,88 +0,0 @@
-/*
- * File:	m548xgpt.h
- * Purpose:	Register and bit definitions for the MCF548X
- *
- * Notes:
- *
- */
-
-#ifndef m548xgpt_h
-#define m548xgpt_h
-
-/*********************************************************************
-*
-* General Purpose Timers (GPT)
-*
-*********************************************************************/
-
-/* Register read/write macros */
-#define MCF_GPT_GMS0       0x000800
-#define MCF_GPT_GCIR0      0x000804
-#define MCF_GPT_GPWM0      0x000808
-#define MCF_GPT_GSR0       0x00080C
-#define MCF_GPT_GMS1       0x000810
-#define MCF_GPT_GCIR1      0x000814
-#define MCF_GPT_GPWM1      0x000818
-#define MCF_GPT_GSR1       0x00081C
-#define MCF_GPT_GMS2       0x000820
-#define MCF_GPT_GCIR2      0x000824
-#define MCF_GPT_GPWM2      0x000828
-#define MCF_GPT_GSR2       0x00082C
-#define MCF_GPT_GMS3       0x000830
-#define MCF_GPT_GCIR3      0x000834
-#define MCF_GPT_GPWM3      0x000838
-#define MCF_GPT_GSR3       0x00083C
-#define MCF_GPT_GMS(x)     (0x000800+((x)*0x010))
-#define MCF_GPT_GCIR(x)    (0x000804+((x)*0x010))
-#define MCF_GPT_GPWM(x)    (0x000808+((x)*0x010))
-#define MCF_GPT_GSR(x)     (0x00080C+((x)*0x010))
-
-/* Bit definitions and macros for MCF_GPT_GMS */
-#define MCF_GPT_GMS_TMS(x)         (((x)&0x00000007)<<0)
-#define MCF_GPT_GMS_GPIO(x)        (((x)&0x00000003)<<4)
-#define MCF_GPT_GMS_IEN            (0x00000100)
-#define MCF_GPT_GMS_OD             (0x00000200)
-#define MCF_GPT_GMS_SC             (0x00000400)
-#define MCF_GPT_GMS_CE             (0x00001000)
-#define MCF_GPT_GMS_WDEN           (0x00008000)
-#define MCF_GPT_GMS_ICT(x)         (((x)&0x00000003)<<16)
-#define MCF_GPT_GMS_OCT(x)         (((x)&0x00000003)<<20)
-#define MCF_GPT_GMS_OCPW(x)        (((x)&0x000000FF)<<24)
-#define MCF_GPT_GMS_OCT_FRCLOW     (0x00000000)
-#define MCF_GPT_GMS_OCT_PULSEHI    (0x00100000)
-#define MCF_GPT_GMS_OCT_PULSELO    (0x00200000)
-#define MCF_GPT_GMS_OCT_TOGGLE     (0x00300000)
-#define MCF_GPT_GMS_ICT_ANY        (0x00000000)
-#define MCF_GPT_GMS_ICT_RISE       (0x00010000)
-#define MCF_GPT_GMS_ICT_FALL       (0x00020000)
-#define MCF_GPT_GMS_ICT_PULSE      (0x00030000)
-#define MCF_GPT_GMS_GPIO_INPUT     (0x00000000)
-#define MCF_GPT_GMS_GPIO_OUTLO     (0x00000020)
-#define MCF_GPT_GMS_GPIO_OUTHI     (0x00000030)
-#define MCF_GPT_GMS_TMS_DISABLE    (0x00000000)
-#define MCF_GPT_GMS_TMS_INCAPT     (0x00000001)
-#define MCF_GPT_GMS_TMS_OUTCAPT    (0x00000002)
-#define MCF_GPT_GMS_TMS_PWM        (0x00000003)
-#define MCF_GPT_GMS_TMS_GPIO       (0x00000004)
-
-/* Bit definitions and macros for MCF_GPT_GCIR */
-#define MCF_GPT_GCIR_CNT(x)        (((x)&0x0000FFFF)<<0)
-#define MCF_GPT_GCIR_PRE(x)        (((x)&0x0000FFFF)<<16)
-
-/* Bit definitions and macros for MCF_GPT_GPWM */
-#define MCF_GPT_GPWM_LOAD          (0x00000001)
-#define MCF_GPT_GPWM_PWMOP         (0x00000100)
-#define MCF_GPT_GPWM_WIDTH(x)      (((x)&0x0000FFFF)<<16)
-
-/* Bit definitions and macros for MCF_GPT_GSR */
-#define MCF_GPT_GSR_CAPT           (0x00000001)
-#define MCF_GPT_GSR_COMP           (0x00000002)
-#define MCF_GPT_GSR_PWMP           (0x00000004)
-#define MCF_GPT_GSR_TEXP           (0x00000008)
-#define MCF_GPT_GSR_PIN            (0x00000100)
-#define MCF_GPT_GSR_OVF(x)         (((x)&0x00000007)<<12)
-#define MCF_GPT_GSR_CAPTURE(x)     (((x)&0x0000FFFF)<<16)
-
-/********************************************************************/
-
-#endif /* m548xgpt_h */
diff -druNp linux-libre-2.6.37-gnu1/arch/m68k/include/asm/m548xsim.h linux-libre-2.6.38-gnu1/arch/m68k/include/asm/m548xsim.h
--- linux-libre-2.6.37-gnu1/arch/m68k/include/asm/m548xsim.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/m68k/include/asm/m548xsim.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,55 +0,0 @@
-/*
- *	m548xsim.h -- ColdFire 547x/548x System Integration Unit support.
- */
-
-#ifndef	m548xsim_h
-#define m548xsim_h
-
-#define MCFINT_VECBASE      64
-
-/*
- *      Interrupt Controller Registers
- */
-#define MCFICM_INTC0		0x0700		/* Base for Interrupt Ctrl 0 */
-#define MCFINTC_IPRH		0x00		/* Interrupt pending 32-63 */
-#define MCFINTC_IPRL		0x04		/* Interrupt pending 1-31 */
-#define MCFINTC_IMRH		0x08		/* Interrupt mask 32-63 */
-#define MCFINTC_IMRL		0x0c		/* Interrupt mask 1-31 */
-#define MCFINTC_INTFRCH		0x10		/* Interrupt force 32-63 */
-#define MCFINTC_INTFRCL		0x14		/* Interrupt force 1-31 */
-#define MCFINTC_IRLR		0x18		/* */
-#define MCFINTC_IACKL		0x19		/* */
-#define MCFINTC_ICR0		0x40		/* Base ICR register */
-
-/*
- *	Define system peripheral IRQ usage.
- */
-#define MCF_IRQ_TIMER		(64 + 54)	/* Slice Timer 0 */
-#define MCF_IRQ_PROFILER	(64 + 53)	/* Slice Timer 1 */
-
-/*
- *	Generic GPIO support
- */
-#define MCFGPIO_PIN_MAX		0	/* I am too lazy to count */
-#define MCFGPIO_IRQ_MAX		-1
-#define MCFGPIO_IRQ_VECBASE	-1
-
-/*
- *	Some PSC related definitions
- */
-#define MCF_PAR_PSC(x)		(0x000A4F-((x)&0x3))
-#define MCF_PAR_SDA		(0x0008)
-#define MCF_PAR_SCL		(0x0004)
-#define MCF_PAR_PSC_TXD		(0x04)
-#define MCF_PAR_PSC_RXD		(0x08)
-#define MCF_PAR_PSC_RTS(x)	(((x)&0x03)<<4)
-#define MCF_PAR_PSC_CTS(x)	(((x)&0x03)<<6)
-#define MCF_PAR_PSC_CTS_GPIO	(0x00)
-#define MCF_PAR_PSC_CTS_BCLK	(0x80)
-#define MCF_PAR_PSC_CTS_CTS	(0xC0)
-#define MCF_PAR_PSC_RTS_GPIO    (0x00)
-#define MCF_PAR_PSC_RTS_FSYNC	(0x20)
-#define MCF_PAR_PSC_RTS_RTS	(0x30)
-#define MCF_PAR_PSC_CANRX	(0x40)
-
-#endif	/* m548xsim_h */
diff -druNp linux-libre-2.6.37-gnu1/arch/m68k/include/asm/m54xxacr.h linux-libre-2.6.38-gnu1/arch/m68k/include/asm/m54xxacr.h
--- linux-libre-2.6.37-gnu1/arch/m68k/include/asm/m54xxacr.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/m68k/include/asm/m54xxacr.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,97 @@
+/*
+ * Bit definitions for the MCF54xx ACR and CACR registers.
+ */
+
+#ifndef	m54xxacr_h
+#define m54xxacr_h
+
+/*
+ *	Define the Cache register flags.
+ */
+#define CACR_DEC	0x80000000	/* Enable data cache */
+#define CACR_DWP	0x40000000	/* Data write protection */
+#define CACR_DESB	0x20000000	/* Enable data store buffer */
+#define CACR_DDPI	0x10000000	/* Disable invalidation by CPUSHL */
+#define CACR_DHCLK	0x08000000	/* Half data cache lock mode */
+#define CACR_DDCM_WT	0x00000000	/* Write through cache*/
+#define CACR_DDCM_CP	0x02000000	/* Copyback cache */
+#define CACR_DDCM_P	0x04000000	/* No cache, precise */
+#define CACR_DDCM_IMP	0x06000000	/* No cache, imprecise */
+#define CACR_DCINVA	0x01000000	/* Invalidate data cache */
+#define CACR_BEC	0x00080000	/* Enable branch cache */
+#define CACR_BCINVA	0x00040000	/* Invalidate branch cache */
+#define CACR_IEC	0x00008000	/* Enable instruction cache */
+#define CACR_DNFB	0x00002000	/* Inhibited fill buffer */
+#define CACR_IDPI	0x00001000	/* Disable CPUSHL */
+#define CACR_IHLCK	0x00000800	/* Intruction cache half lock */
+#define CACR_IDCM	0x00000400	/* Intruction cache inhibit */
+#define CACR_ICINVA	0x00000100	/* Invalidate instr cache */
+#define CACR_EUSP	0x00000020	/* Enable separate user a7 */
+
+#define ACR_BASE_POS	24		/* Address Base */
+#define ACR_MASK_POS	16		/* Address Mask */
+#define ACR_ENABLE	0x00008000	/* Enable address */
+#define ACR_USER	0x00000000	/* User mode access only */
+#define ACR_SUPER	0x00002000	/* Supervisor mode only */
+#define ACR_ANY		0x00004000	/* Match any access mode */
+#define ACR_CM_WT	0x00000000	/* Write through mode */
+#define ACR_CM_CP	0x00000020	/* Copyback mode */
+#define ACR_CM_OFF_PRE	0x00000040	/* No cache, precise */
+#define ACR_CM_OFF_IMP	0x00000060	/* No cache, imprecise */
+#define ACR_CM		0x00000060	/* Cache mode mask */
+#define ACR_WPROTECT	0x00000004	/* Write protect */
+
+#if defined(CONFIG_M5407)
+
+#define ICACHE_SIZE 0x4000	/* instruction - 16k */
+#define DCACHE_SIZE 0x2000	/* data - 8k */
+
+#elif defined(CONFIG_M54xx)
+
+#define ICACHE_SIZE 0x8000	/* instruction - 32k */
+#define DCACHE_SIZE 0x8000	/* data - 32k */
+
+#endif
+
+#define CACHE_LINE_SIZE 0x0010	/* 16 bytes */
+#define CACHE_WAYS 4		/* 4 ways */
+
+/*
+ *	Version 4 cores have a true harvard style separate instruction
+ *	and data cache. Enable data and instruction caches, also enable write
+ *	buffers and branch accelerator.
+ */
+/* attention : enabling CACR_DESB requires a "nop" to flush the store buffer */
+/* use '+' instead of '|' for assembler's sake */
+
+	/* Enable data cache */
+	/* Enable data store buffer */
+	/* outside ACRs : No cache, precise */
+	/* Enable instruction+branch caches */
+#if defined(CONFIG_M5407)
+#define CACHE_MODE (CACR_DEC+CACR_DESB+CACR_DDCM_P+CACR_BEC+CACR_IEC)
+#else
+#define CACHE_MODE (CACR_DEC+CACR_DESB+CACR_DDCM_P+CACR_BEC+CACR_IEC+CACR_EUSP)
+#endif
+#if defined(CONFIG_CACHE_COPYBACK)
+#define DATA_CACHE_MODE (ACR_ENABLE+ACR_ANY+ACR_CM_CP)
+#else
+#define DATA_CACHE_MODE (ACR_ENABLE+ACR_ANY+ACR_CM_WT)
+#endif
+#define INSN_CACHE_MODE (ACR_ENABLE+ACR_ANY)
+
+#define CACHE_INIT	(CACR_DCINVA+CACR_BCINVA+CACR_ICINVA)
+#define CACHE_INVALIDATE  (CACHE_MODE+CACR_DCINVA+CACR_BCINVA+CACR_ICINVA)
+#define CACHE_INVALIDATEI (CACHE_MODE+CACR_BCINVA+CACR_ICINVA)
+#define CACHE_INVALIDATED (CACHE_MODE+CACR_DCINVA)
+#define ACR0_MODE	(0x000f0000+DATA_CACHE_MODE)
+#define ACR1_MODE	0
+#define ACR2_MODE	(0x000f0000+INSN_CACHE_MODE)
+#define ACR3_MODE	0
+
+#if ((DATA_CACHE_MODE & ACR_CM) == ACR_CM_CP)
+/* Copyback cache mode must push dirty cache lines first */
+#define	CACHE_PUSH
+#endif
+
+#endif	/* m54xxacr_h */
diff -druNp linux-libre-2.6.37-gnu1/arch/m68k/include/asm/m54xxgpt.h linux-libre-2.6.38-gnu1/arch/m68k/include/asm/m54xxgpt.h
--- linux-libre-2.6.37-gnu1/arch/m68k/include/asm/m54xxgpt.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/m68k/include/asm/m54xxgpt.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,90 @@
+/*
+ * File:	m54xxgpt.h
+ * Purpose:	Register and bit definitions for the MCF54XX
+ *
+ * Notes:
+ *
+ */
+
+#ifndef m54xxgpt_h
+#define m54xxgpt_h
+
+/*********************************************************************
+*
+* General Purpose Timers (GPT)
+*
+*********************************************************************/
+
+/* Register read/write macros */
+#define MCF_GPT_GMS0       0x000800
+#define MCF_GPT_GCIR0      0x000804
+#define MCF_GPT_GPWM0      0x000808
+#define MCF_GPT_GSR0       0x00080C
+#define MCF_GPT_GMS1       0x000810
+#define MCF_GPT_GCIR1      0x000814
+#define MCF_GPT_GPWM1      0x000818
+#define MCF_GPT_GSR1       0x00081C
+#define MCF_GPT_GMS2       0x000820
+#define MCF_GPT_GCIR2      0x000824
+#define MCF_GPT_GPWM2      0x000828
+#define MCF_GPT_GSR2       0x00082C
+#define MCF_GPT_GMS3       0x000830
+#define MCF_GPT_GCIR3      0x000834
+#define MCF_GPT_GPWM3      0x000838
+#define MCF_GPT_GSR3       0x00083C
+#define MCF_GPT_GMS(x)     (0x000800+((x)*0x010))
+#define MCF_GPT_GCIR(x)    (0x000804+((x)*0x010))
+#define MCF_GPT_GPWM(x)    (0x000808+((x)*0x010))
+#define MCF_GPT_GSR(x)     (0x00080C+((x)*0x010))
+
+/* Bit definitions and macros for MCF_GPT_GMS */
+#define MCF_GPT_GMS_TMS(x)         (((x)&0x00000007)<<0)
+#define MCF_GPT_GMS_GPIO(x)        (((x)&0x00000003)<<4)
+#define MCF_GPT_GMS_IEN            (0x00000100)
+#define MCF_GPT_GMS_OD             (0x00000200)
+#define MCF_GPT_GMS_SC             (0x00000400)
+#define MCF_GPT_GMS_CE             (0x00001000)
+#define MCF_GPT_GMS_WDEN           (0x00008000)
+#define MCF_GPT_GMS_ICT(x)         (((x)&0x00000003)<<16)
+#define MCF_GPT_GMS_OCT(x)         (((x)&0x00000003)<<20)
+#define MCF_GPT_GMS_OCPW(x)        (((x)&0x000000FF)<<24)
+#define MCF_GPT_GMS_OCT_FRCLOW     (0x00000000)
+#define MCF_GPT_GMS_OCT_PULSEHI    (0x00100000)
+#define MCF_GPT_GMS_OCT_PULSELO    (0x00200000)
+#define MCF_GPT_GMS_OCT_TOGGLE     (0x00300000)
+#define MCF_GPT_GMS_ICT_ANY        (0x00000000)
+#define MCF_GPT_GMS_ICT_RISE       (0x00010000)
+#define MCF_GPT_GMS_ICT_FALL       (0x00020000)
+#define MCF_GPT_GMS_ICT_PULSE      (0x00030000)
+#define MCF_GPT_GMS_GPIO_INPUT     (0x00000000)
+#define MCF_GPT_GMS_GPIO_OUTLO     (0x00000020)
+#define MCF_GPT_GMS_GPIO_OUTHI     (0x00000030)
+#define MCF_GPT_GMS_GPIO_MASK      (0x00000030)
+#define MCF_GPT_GMS_TMS_DISABLE    (0x00000000)
+#define MCF_GPT_GMS_TMS_INCAPT     (0x00000001)
+#define MCF_GPT_GMS_TMS_OUTCAPT    (0x00000002)
+#define MCF_GPT_GMS_TMS_PWM        (0x00000003)
+#define MCF_GPT_GMS_TMS_GPIO       (0x00000004)
+#define MCF_GPT_GMS_TMS_MASK       (0x00000007)
+
+/* Bit definitions and macros for MCF_GPT_GCIR */
+#define MCF_GPT_GCIR_CNT(x)        (((x)&0x0000FFFF)<<0)
+#define MCF_GPT_GCIR_PRE(x)        (((x)&0x0000FFFF)<<16)
+
+/* Bit definitions and macros for MCF_GPT_GPWM */
+#define MCF_GPT_GPWM_LOAD          (0x00000001)
+#define MCF_GPT_GPWM_PWMOP         (0x00000100)
+#define MCF_GPT_GPWM_WIDTH(x)      (((x)&0x0000FFFF)<<16)
+
+/* Bit definitions and macros for MCF_GPT_GSR */
+#define MCF_GPT_GSR_CAPT           (0x00000001)
+#define MCF_GPT_GSR_COMP           (0x00000002)
+#define MCF_GPT_GSR_PWMP           (0x00000004)
+#define MCF_GPT_GSR_TEXP           (0x00000008)
+#define MCF_GPT_GSR_PIN            (0x00000100)
+#define MCF_GPT_GSR_OVF(x)         (((x)&0x00000007)<<12)
+#define MCF_GPT_GSR_CAPTURE(x)     (((x)&0x0000FFFF)<<16)
+
+/********************************************************************/
+
+#endif /* m54xxgpt_h */
diff -druNp linux-libre-2.6.37-gnu1/arch/m68k/include/asm/m54xxsim.h linux-libre-2.6.38-gnu1/arch/m68k/include/asm/m54xxsim.h
--- linux-libre-2.6.37-gnu1/arch/m68k/include/asm/m54xxsim.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/m68k/include/asm/m54xxsim.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,68 @@
+/*
+ *	m54xxsim.h -- ColdFire 547x/548x System Integration Unit support.
+ */
+
+#ifndef	m54xxsim_h
+#define m54xxsim_h
+
+#define	CPU_NAME		"COLDFIRE(m54xx)"
+#define	CPU_INSTR_PER_JIFFY	2
+
+#include <asm/m54xxacr.h>
+
+#define MCFINT_VECBASE		64
+
+/*
+ *      Interrupt Controller Registers
+ */
+#define MCFICM_INTC0		0x0700		/* Base for Interrupt Ctrl 0 */
+#define MCFINTC_IPRH		0x00		/* Interrupt pending 32-63 */
+#define MCFINTC_IPRL		0x04		/* Interrupt pending 1-31 */
+#define MCFINTC_IMRH		0x08		/* Interrupt mask 32-63 */
+#define MCFINTC_IMRL		0x0c		/* Interrupt mask 1-31 */
+#define MCFINTC_INTFRCH		0x10		/* Interrupt force 32-63 */
+#define MCFINTC_INTFRCL		0x14		/* Interrupt force 1-31 */
+#define MCFINTC_IRLR		0x18		/* */
+#define MCFINTC_IACKL		0x19		/* */
+#define MCFINTC_ICR0		0x40		/* Base ICR register */
+
+/*
+ *	UART module.
+ */
+#define MCFUART_BASE1		0x8600		/* Base address of UART1 */
+#define MCFUART_BASE2		0x8700		/* Base address of UART2 */
+#define MCFUART_BASE3		0x8800		/* Base address of UART3 */
+#define MCFUART_BASE4		0x8900		/* Base address of UART4 */
+
+/*
+ *	Define system peripheral IRQ usage.
+ */
+#define MCF_IRQ_TIMER		(64 + 54)	/* Slice Timer 0 */
+#define MCF_IRQ_PROFILER	(64 + 53)	/* Slice Timer 1 */
+
+/*
+ *	Generic GPIO support
+ */
+#define MCFGPIO_PIN_MAX		0	/* I am too lazy to count */
+#define MCFGPIO_IRQ_MAX		-1
+#define MCFGPIO_IRQ_VECBASE	-1
+
+/*
+ *	Some PSC related definitions
+ */
+#define MCF_PAR_PSC(x)		(0x000A4F-((x)&0x3))
+#define MCF_PAR_SDA		(0x0008)
+#define MCF_PAR_SCL		(0x0004)
+#define MCF_PAR_PSC_TXD		(0x04)
+#define MCF_PAR_PSC_RXD		(0x08)
+#define MCF_PAR_PSC_RTS(x)	(((x)&0x03)<<4)
+#define MCF_PAR_PSC_CTS(x)	(((x)&0x03)<<6)
+#define MCF_PAR_PSC_CTS_GPIO	(0x00)
+#define MCF_PAR_PSC_CTS_BCLK	(0x80)
+#define MCF_PAR_PSC_CTS_CTS	(0xC0)
+#define MCF_PAR_PSC_RTS_GPIO    (0x00)
+#define MCF_PAR_PSC_RTS_FSYNC	(0x20)
+#define MCF_PAR_PSC_RTS_RTS	(0x30)
+#define MCF_PAR_PSC_CANRX	(0x40)
+
+#endif	/* m54xxsim_h */
diff -druNp linux-libre-2.6.37-gnu1/arch/m68k/include/asm/mcfcache.h linux-libre-2.6.38-gnu1/arch/m68k/include/asm/mcfcache.h
--- linux-libre-2.6.37-gnu1/arch/m68k/include/asm/mcfcache.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/m68k/include/asm/mcfcache.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,150 +0,0 @@
-/****************************************************************************/
-
-/*
- *	mcfcache.h -- ColdFire CPU cache support code
- *
- *	(C) Copyright 2004, Greg Ungerer <gerg@snapgear.com>
- */
-
-/****************************************************************************/
-#ifndef	__M68KNOMMU_MCFCACHE_H
-#define	__M68KNOMMU_MCFCACHE_H
-/****************************************************************************/
-
-
-/*
- *	The different ColdFire families have different cache arrangments.
- *	Everything from a small instruction only cache, to configurable
- *	data and/or instruction cache, to unified instruction/data, to 
- *	harvard style separate instruction and data caches.
- */
-
-#if defined(CONFIG_M5206) || defined(CONFIG_M5206e) || defined(CONFIG_M5272)
-/*
- *	Simple version 2 core cache. These have instruction cache only,
- *	we just need to invalidate it and enable it.
- */
-.macro CACHE_ENABLE
-	movel	#0x01000000,%d0		/* invalidate cache cmd */
-	movec	%d0,%CACR		/* do invalidate cache */
-	movel	#0x80000100,%d0		/* setup cache mask */
-	movec	%d0,%CACR		/* enable cache */
-.endm
-#endif /* CONFIG_M5206 || CONFIG_M5206e || CONFIG_M5272 */
-
-#if defined(CONFIG_M523x) || defined(CONFIG_M527x)
-/*
- *	New version 2 cores have a configurable split cache arrangement.
- *	For now I am just enabling instruction cache - but ultimately I
- *	think a split instruction/data cache would be better.
- */
-.macro CACHE_ENABLE
-	movel	#0x01400000,%d0
-	movec	%d0,%CACR		/* invalidate cache */
-	nop
-	movel	#0x0000c000,%d0		/* set SDRAM cached only */
-	movec	%d0,%ACR0
-	movel	#0x00000000,%d0		/* no other regions cached */
-	movec	%d0,%ACR1
-	movel	#0x80400100,%d0		/* configure cache */
-	movec	%d0,%CACR		/* enable cache */
-	nop
-.endm
-#endif /* CONFIG_M523x || CONFIG_M527x */
-
-#if defined(CONFIG_M528x)
-.macro CACHE_ENABLE
-	nop
-	movel	#0x01000000, %d0
-	movec	%d0, %CACR		/* Invalidate cache */
-	nop
-	movel	#0x0000c020, %d0	/* Set SDRAM cached only */
-	movec	%d0, %ACR0
-	movel	#0x00000000, %d0	/* No other regions cached */
-	movec	%d0, %ACR1
-	movel	#0x80000200, %d0	/* Setup cache mask */
-	movec	%d0, %CACR		/* Enable cache */
-	nop
-.endm
-#endif /* CONFIG_M528x */
-
-#if defined(CONFIG_M5249) || defined(CONFIG_M5307)
-/*
- *	The version 3 core cache. Oddly enough the version 2 core 5249
- *	has the same SDRAM and cache setup as the version 3 cores.
- *	This is a single unified instruction/data cache.
- */
-.macro CACHE_ENABLE
-	movel	#0x01000000,%d0		/* invalidate whole cache */
-	movec	%d0,%CACR
-	nop
-#if defined(DEBUGGER_COMPATIBLE_CACHE) || defined(CONFIG_SECUREEDGEMP3)
-	movel	#0x0000c000,%d0		/* set SDRAM cached (write-thru) */
-#else
-	movel	#0x0000c020,%d0		/* set SDRAM cached (copyback) */
-#endif
-	movec	%d0,%ACR0
-	movel	#0x00000000,%d0		/* no other regions cached */
-	movec	%d0,%ACR1
-	movel	#0xa0000200,%d0		/* enable cache */
-	movec	%d0,%CACR
-	nop
-.endm
-#endif /* CONFIG_M5249 || CONFIG_M5307 */
-
-#if defined(CONFIG_M532x)
-.macro CACHE_ENABLE
-	movel	#0x01000000,%d0		/* invalidate cache cmd */
-	movec	%d0,%CACR		/* do invalidate cache */
-	nop
-	movel	#0x4001C000,%d0		/* set SDRAM cached (write-thru) */
-	movec	%d0,%ACR0
-	movel	#0x00000000,%d0		/* no other regions cached */
-	movec	%d0,%ACR1
-	movel	#0x80000200,%d0		/* setup cache mask */
-	movec	%d0,%CACR		/* enable cache */
-	nop
-.endm
-#endif /* CONFIG_M532x */
-
-#if defined(CONFIG_M5407) || defined(CONFIG_M548x)
-/*
- *	Version 4 cores have a true harvard style separate instruction
- *	and data cache. Invalidate and enable cache, also enable write
- *	buffers and branch accelerator.
- */
-.macro CACHE_ENABLE
-	movel	#0x01040100,%d0		/* invalidate whole cache */
-	movec	%d0,%CACR
-	nop
-	movel	#0x000fc000,%d0		/* set SDRAM cached only */
-	movec	%d0, %ACR0
-	movel	#0x00000000,%d0		/* no other regions cached */
-	movec	%d0, %ACR1
-	movel	#0x000fc000,%d0		/* set SDRAM cached only */
-	movec	%d0, %ACR2
-	movel	#0x00000000,%d0		/* no other regions cached */
-	movec	%d0, %ACR3
-	movel	#0xb6088400,%d0		/* enable caches */
-	movec	%d0,%CACR
-	nop
-.endm
-#endif /* CONFIG_M5407 */
-
-#if defined(CONFIG_M520x)
-.macro CACHE_ENABLE
-	move.l	#0x01000000,%d0		/* invalidate whole cache */
-	movec	%d0,%CACR
-	nop
-	move.l	#0x0000c000,%d0		/* set SDRAM cached (write-thru) */
-	movec	%d0,%ACR0
-	move.l	#0x00000000,%d0		/* no other regions cached */
-	movec	%d0,%ACR1
-	move.l	#0x80400000,%d0		/* enable 8K instruction cache */
-	movec	%d0,%CACR
-	nop
-.endm
-#endif /* CONFIG_M520x */
-
-/****************************************************************************/
-#endif	/* __M68KNOMMU_MCFCACHE_H */
diff -druNp linux-libre-2.6.37-gnu1/arch/m68k/include/asm/mcfsim.h linux-libre-2.6.38-gnu1/arch/m68k/include/asm/mcfsim.h
--- linux-libre-2.6.37-gnu1/arch/m68k/include/asm/mcfsim.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/m68k/include/asm/mcfsim.h	2011-03-14 21:20:32.000000000 -0400
@@ -41,8 +41,8 @@
 #elif defined(CONFIG_M5407)
 #include <asm/m5407sim.h>
 #include <asm/mcfintc.h>
-#elif defined(CONFIG_M548x)
-#include <asm/m548xsim.h>
+#elif defined(CONFIG_M54xx)
+#include <asm/m54xxsim.h>
 #endif
 
 /****************************************************************************/
diff -druNp linux-libre-2.6.37-gnu1/arch/m68k/include/asm/mcfuart.h linux-libre-2.6.38-gnu1/arch/m68k/include/asm/mcfuart.h
--- linux-libre-2.6.37-gnu1/arch/m68k/include/asm/mcfuart.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/m68k/include/asm/mcfuart.h	2011-03-14 21:20:32.000000000 -0400
@@ -12,49 +12,6 @@
 #define	mcfuart_h
 /****************************************************************************/
 
-/*
- *	Define the base address of the UARTS within the MBAR address
- *	space.
- */
-#if defined(CONFIG_M5272)
-#define	MCFUART_BASE1		0x100		/* Base address of UART1 */
-#define	MCFUART_BASE2		0x140		/* Base address of UART2 */
-#elif defined(CONFIG_M5206) || defined(CONFIG_M5206e)
-#if defined(CONFIG_NETtel)
-#define	MCFUART_BASE1		0x180		/* Base address of UART1 */
-#define	MCFUART_BASE2		0x140		/* Base address of UART2 */
-#else
-#define	MCFUART_BASE1		0x140		/* Base address of UART1 */
-#define	MCFUART_BASE2		0x180		/* Base address of UART2 */
-#endif
-#elif defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x)
-#define MCFUART_BASE1		0x200           /* Base address of UART1 */
-#define MCFUART_BASE2		0x240           /* Base address of UART2 */
-#define MCFUART_BASE3		0x280           /* Base address of UART3 */
-#elif defined(CONFIG_M5249) || defined(CONFIG_M5307) || defined(CONFIG_M5407)
-#if defined(CONFIG_NETtel) || defined(CONFIG_SECUREEDGEMP3)
-#define MCFUART_BASE1		0x200           /* Base address of UART1 */
-#define MCFUART_BASE2		0x1c0           /* Base address of UART2 */
-#else
-#define MCFUART_BASE1		0x1c0           /* Base address of UART1 */
-#define MCFUART_BASE2		0x200           /* Base address of UART2 */
-#endif
-#elif defined(CONFIG_M520x)
-#define MCFUART_BASE1		0x60000		/* Base address of UART1 */
-#define MCFUART_BASE2		0x64000		/* Base address of UART2 */
-#define MCFUART_BASE3		0x68000		/* Base address of UART2 */
-#elif defined(CONFIG_M532x)
-#define MCFUART_BASE1		0xfc060000	/* Base address of UART1 */
-#define MCFUART_BASE2		0xfc064000	/* Base address of UART2 */
-#define MCFUART_BASE3		0xfc068000	/* Base address of UART3 */
-#elif defined(CONFIG_M548x)
-#define MCFUART_BASE1		0x8600		/* on M548x */
-#define MCFUART_BASE2		0x8700		/* on M548x */
-#define MCFUART_BASE3		0x8800		/* on M548x */
-#define MCFUART_BASE4		0x8900		/* on M548x */
-#endif
-
-
 #include <linux/serial_core.h>
 #include <linux/platform_device.h>
 
@@ -217,7 +174,7 @@ struct mcf_platform_uart {
 #define	MCFUART_URF_RXS		0xc0		/* Receiver status */
 #endif
 
-#if defined(CONFIG_M548x)
+#if defined(CONFIG_M54xx)
 #define MCFUART_TXFIFOSIZE	512
 #elif defined(CONFIG_M5272)
 #define MCFUART_TXFIFOSIZE	25
diff -druNp linux-libre-2.6.37-gnu1/arch/m68k/include/asm/processor.h linux-libre-2.6.38-gnu1/arch/m68k/include/asm/processor.h
--- linux-libre-2.6.37-gnu1/arch/m68k/include/asm/processor.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/m68k/include/asm/processor.h	2011-03-14 21:20:32.000000000 -0400
@@ -20,23 +20,26 @@
 
 static inline unsigned long rdusp(void)
 {
-#ifdef CONFIG_COLDFIRE
+#ifdef CONFIG_COLDFIRE_SW_A7
 	extern unsigned int sw_usp;
 	return sw_usp;
 #else
-	unsigned long usp;
-	__asm__ __volatile__("move %/usp,%0" : "=a" (usp));
+	register unsigned long usp __asm__("a0");
+	/* move %usp,%a0 */
+	__asm__ __volatile__(".word 0x4e68" : "=a" (usp));
 	return usp;
 #endif
 }
 
 static inline void wrusp(unsigned long usp)
 {
-#ifdef CONFIG_COLDFIRE
+#ifdef CONFIG_COLDFIRE_SW_A7
 	extern unsigned int sw_usp;
 	sw_usp = usp;
 #else
-	__asm__ __volatile__("move %0,%/usp" : : "a" (usp));
+	register unsigned long a0 __asm__("a0") = usp;
+	/* move %a0,%usp */
+	__asm__ __volatile__(".word 0x4e60" : : "a" (a0) );
 #endif
 }
 
diff -druNp linux-libre-2.6.37-gnu1/arch/m68k/include/asm/string.h linux-libre-2.6.38-gnu1/arch/m68k/include/asm/string.h
--- linux-libre-2.6.37-gnu1/arch/m68k/include/asm/string.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/m68k/include/asm/string.h	2011-03-14 21:20:32.000000000 -0400
@@ -81,18 +81,6 @@ static inline char *strncpy(char *dest,
 	strcpy(__d + strlen(__d), (s));		\
 })
 
-#define __HAVE_ARCH_STRCHR
-static inline char *strchr(const char *s, int c)
-{
-	char sc, ch = c;
-
-	for (; (sc = *s++) != ch; ) {
-		if (!sc)
-			return NULL;
-	}
-	return (char *)s - 1;
-}
-
 #ifndef CONFIG_COLDFIRE
 #define __HAVE_ARCH_STRCMP
 static inline int strcmp(const char *cs, const char *ct)
@@ -111,14 +99,12 @@ static inline int strcmp(const char *cs,
 		: "+a" (cs), "+a" (ct), "=d" (res));
 	return res;
 }
+#endif /* CONFIG_COLDFIRE */
 
 #define __HAVE_ARCH_MEMMOVE
 extern void *memmove(void *, const void *, __kernel_size_t);
 
-#define __HAVE_ARCH_MEMCMP
-extern int memcmp(const void *, const void *, __kernel_size_t);
 #define memcmp(d, s, n) __builtin_memcmp(d, s, n)
-#endif /* CONFIG_COLDFIRE */
 
 #define __HAVE_ARCH_MEMSET
 extern void *memset(void *, int, __kernel_size_t);
diff -druNp linux-libre-2.6.37-gnu1/arch/m68k/include/asm/sun3_pgtable.h linux-libre-2.6.38-gnu1/arch/m68k/include/asm/sun3_pgtable.h
--- linux-libre-2.6.37-gnu1/arch/m68k/include/asm/sun3_pgtable.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/m68k/include/asm/sun3_pgtable.h	2011-03-14 21:20:32.000000000 -0400
@@ -217,9 +217,8 @@ static inline pte_t pgoff_to_pte(unsigne
 /* Find an entry in the third-level pagetable. */
 #define pte_index(address) ((address >> PAGE_SHIFT) & (PTRS_PER_PTE-1))
 #define pte_offset_kernel(pmd, address) ((pte_t *) __pmd_page(*pmd) + pte_index(address))
-/* FIXME: should we bother with kmap() here? */
-#define pte_offset_map(pmd, address) ((pte_t *)kmap(pmd_page(*pmd)) + pte_index(address))
-#define pte_unmap(pte) kunmap(pte)
+#define pte_offset_map(pmd, address) ((pte_t *)page_address(pmd_page(*pmd)) + pte_index(address))
+#define pte_unmap(pte) do { } while (0)
 
 /* Macros to (de)construct the fake PTEs representing swap pages. */
 #define __swp_type(x)		((x).val & 0x7F)
diff -druNp linux-libre-2.6.37-gnu1/arch/m68k/include/asm/thread_info.h linux-libre-2.6.38-gnu1/arch/m68k/include/asm/thread_info.h
--- linux-libre-2.6.37-gnu1/arch/m68k/include/asm/thread_info.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/m68k/include/asm/thread_info.h	2011-03-14 21:20:32.000000000 -0400
@@ -104,5 +104,6 @@ static inline struct thread_info *curren
 #define TIF_SYSCALL_TRACE	15	/* syscall trace active */
 #define TIF_MEMDIE		16	/* is terminating due to OOM killer */
 #define TIF_FREEZE		17	/* thread is freezing for suspend */
+#define TIF_RESTORE_SIGMASK	18	/* restore signal mask in do_signal */
 
 #endif	/* _ASM_M68K_THREAD_INFO_H */
diff -druNp linux-libre-2.6.37-gnu1/arch/m68k/include/asm/unistd.h linux-libre-2.6.38-gnu1/arch/m68k/include/asm/unistd.h
--- linux-libre-2.6.37-gnu1/arch/m68k/include/asm/unistd.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/m68k/include/asm/unistd.h	2011-03-14 21:20:32.000000000 -0400
@@ -373,6 +373,7 @@
 #define __ARCH_WANT_SYS_SIGPENDING
 #define __ARCH_WANT_SYS_SIGPROCMASK
 #define __ARCH_WANT_SYS_RT_SIGACTION
+#define __ARCH_WANT_SYS_RT_SIGSUSPEND
 
 /*
  * "Conditional" syscalls
diff -druNp linux-libre-2.6.37-gnu1/arch/m68k/kernel/entry.S linux-libre-2.6.38-gnu1/arch/m68k/kernel/entry.S
--- linux-libre-2.6.37-gnu1/arch/m68k/kernel/entry.S	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/m68k/kernel/entry.S	2011-03-14 21:20:32.000000000 -0400
@@ -99,7 +99,10 @@ do_trace_exit:
 	jra	.Lret_from_exception
 
 ENTRY(ret_from_signal)
-	RESTORE_SWITCH_STACK
+	tstb	%curptr@(TASK_INFO+TINFO_FLAGS+2)
+	jge	1f
+	jbsr	syscall_trace
+1:	RESTORE_SWITCH_STACK
 	addql	#4,%sp
 /* on 68040 complete pending writebacks if any */
 #ifdef CONFIG_M68040
@@ -174,16 +177,11 @@ do_signal_return:
 	subql	#4,%sp			| dummy return address
 	SAVE_SWITCH_STACK
 	pea	%sp@(SWITCH_STACK_SIZE)
-	clrl	%sp@-
 	bsrl	do_signal
-	addql	#8,%sp
+	addql	#4,%sp
 	RESTORE_SWITCH_STACK
 	addql	#4,%sp
-	tstl	%d0
-	jeq	resume_userspace
-	| when single stepping into handler stop at the first insn
-	btst	#6,%curptr@(TASK_INFO+TINFO_FLAGS+2)
-	jeq	resume_userspace
+	jbra	resume_userspace
 
 do_delayed_trace:
 	bclr	#7,%sp@(PT_OFF_SR)	| clear trace bit in SR
@@ -289,22 +287,6 @@ ENTRY(sys_vfork)
 	addql	#4,%sp
 	RESTORE_SWITCH_STACK
 	rts
-
-ENTRY(sys_sigsuspend)
-	SAVE_SWITCH_STACK
-	pea	%sp@(SWITCH_STACK_SIZE)
-	jbsr	do_sigsuspend
-	addql	#4,%sp
-	RESTORE_SWITCH_STACK
-	rts
-
-ENTRY(sys_rt_sigsuspend)
-	SAVE_SWITCH_STACK
-	pea	%sp@(SWITCH_STACK_SIZE)
-	jbsr	do_rt_sigsuspend
-	addql	#4,%sp
-	RESTORE_SWITCH_STACK
-	rts
 
 ENTRY(sys_sigreturn)
 	SAVE_SWITCH_STACK
diff -druNp linux-libre-2.6.37-gnu1/arch/m68k/kernel/signal.c linux-libre-2.6.38-gnu1/arch/m68k/kernel/signal.c
--- linux-libre-2.6.37-gnu1/arch/m68k/kernel/signal.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/m68k/kernel/signal.c	2011-03-14 21:20:32.000000000 -0400
@@ -51,8 +51,6 @@
 
 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
 
-asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs);
-
 const int frame_extra_sizes[16] = {
   [1]	= -1, /* sizeof(((struct frame *)0)->un.fmt1), */
   [2]	= sizeof(((struct frame *)0)->un.fmt2),
@@ -74,51 +72,21 @@ const int frame_extra_sizes[16] = {
 /*
  * Atomically swap in the new signal mask, and wait for a signal.
  */
-asmlinkage int do_sigsuspend(struct pt_regs *regs)
+asmlinkage int
+sys_sigsuspend(int unused0, int unused1, old_sigset_t mask)
 {
-	old_sigset_t mask = regs->d3;
-	sigset_t saveset;
-
 	mask &= _BLOCKABLE;
-	saveset = current->blocked;
+	spin_lock_irq(&current->sighand->siglock);
+	current->saved_sigmask = current->blocked;
 	siginitset(&current->blocked, mask);
 	recalc_sigpending();
+	spin_unlock_irq(&current->sighand->siglock);
 
-	regs->d0 = -EINTR;
-	while (1) {
-		current->state = TASK_INTERRUPTIBLE;
-		schedule();
-		if (do_signal(&saveset, regs))
-			return -EINTR;
-	}
-}
-
-asmlinkage int
-do_rt_sigsuspend(struct pt_regs *regs)
-{
-	sigset_t __user *unewset = (sigset_t __user *)regs->d1;
-	size_t sigsetsize = (size_t)regs->d2;
-	sigset_t saveset, newset;
-
-	/* XXX: Don't preclude handling different sized sigset_t's.  */
-	if (sigsetsize != sizeof(sigset_t))
-		return -EINVAL;
-
-	if (copy_from_user(&newset, unewset, sizeof(newset)))
-		return -EFAULT;
-	sigdelsetmask(&newset, ~_BLOCKABLE);
-
-	saveset = current->blocked;
-	current->blocked = newset;
-	recalc_sigpending();
+	current->state = TASK_INTERRUPTIBLE;
+	schedule();
+	set_restore_sigmask();
 
-	regs->d0 = -EINTR;
-	while (1) {
-		current->state = TASK_INTERRUPTIBLE;
-		schedule();
-		if (do_signal(&saveset, regs))
-			return -EINTR;
-	}
+	return -ERESTARTNOHAND;
 }
 
 asmlinkage int
@@ -132,10 +100,10 @@ sys_sigaction(int sig, const struct old_
 		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))
+		    __get_user(new_ka.sa.sa_restorer, &act->sa_restorer) ||
+		    __get_user(new_ka.sa.sa_flags, &act->sa_flags) ||
+		    __get_user(mask, &act->sa_mask))
 			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);
 	}
 
@@ -144,10 +112,10 @@ sys_sigaction(int sig, const struct old_
 	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))
+		    __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer) ||
+		    __put_user(old_ka.sa.sa_flags, &oact->sa_flags) ||
+		    __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask))
 			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;
@@ -318,36 +286,10 @@ out:
 	return err;
 }
 
-static inline int
-restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *usc, void __user *fp,
-		   int *pd0)
+static int mangle_kernel_stack(struct pt_regs *regs, int formatvec,
+			       void __user *fp)
 {
-	int fsize, formatvec;
-	struct sigcontext context;
-	int err;
-
-	/* Always make any pending restarted system calls return -EINTR */
-	current_thread_info()->restart_block.fn = do_no_restart_syscall;
-
-	/* get previous context */
-	if (copy_from_user(&context, usc, sizeof(context)))
-		goto badframe;
-
-	/* restore passed registers */
-	regs->d1 = context.sc_d1;
-	regs->a0 = context.sc_a0;
-	regs->a1 = context.sc_a1;
-	regs->sr = (regs->sr & 0xff00) | (context.sc_sr & 0xff);
-	regs->pc = context.sc_pc;
-	regs->orig_d0 = -1;		/* disable syscall checks */
-	wrusp(context.sc_usp);
-	formatvec = context.sc_formatvec;
-	regs->format = formatvec >> 12;
-	regs->vector = formatvec & 0xfff;
-
-	err = restore_fpu_state(&context);
-
-	fsize = frame_extra_sizes[regs->format];
+	int fsize = frame_extra_sizes[formatvec >> 12];
 	if (fsize < 0) {
 		/*
 		 * user process trying to return with weird frame format
@@ -355,16 +297,22 @@ restore_sigcontext(struct pt_regs *regs,
 #ifdef DEBUG
 		printk("user process returning with weird frame format\n");
 #endif
-		goto badframe;
+		return 1;
 	}
+	if (!fsize) {
+		regs->format = formatvec >> 12;
+		regs->vector = formatvec & 0xfff;
+	} else {
+		struct switch_stack *sw = (struct switch_stack *)regs - 1;
+		unsigned long buf[fsize / 2]; /* yes, twice as much */
 
-	/* OK.	Make room on the supervisor stack for the extra junk,
-	 * if necessary.
-	 */
+		/* that'll make sure that expansion won't crap over data */
+		if (copy_from_user(buf + fsize / 4, fp, fsize))
+			return 1;
 
-	if (fsize) {
-		struct switch_stack *sw = (struct switch_stack *)regs - 1;
-		regs->d0 = context.sc_d0;
+		/* point of no return */
+		regs->format = formatvec >> 12;
+		regs->vector = formatvec & 0xfff;
 #define frame_offset (sizeof(struct pt_regs)+sizeof(struct switch_stack))
 		__asm__ __volatile__
 			("   movel %0,%/a0\n\t"
@@ -376,30 +324,50 @@ restore_sigcontext(struct pt_regs *regs,
 			 "   lea %/sp@(%c3),%/a0\n\t" /* add offset of fmt */
 			 "   lsrl  #2,%1\n\t"
 			 "   subql #1,%1\n\t"
-			 "2: movesl %4@+,%2\n\t"
-			 "3: movel %2,%/a0@+\n\t"
+			 /* copy to the gap we'd made */
+			 "2: movel %4@+,%/a0@+\n\t"
 			 "   dbra %1,2b\n\t"
 			 "   bral ret_from_signal\n"
-			 "4:\n"
-			 ".section __ex_table,\"a\"\n"
-			 "   .align 4\n"
-			 "   .long 2b,4b\n"
-			 "   .long 3b,4b\n"
-			 ".previous"
 			 : /* no outputs, it doesn't ever return */
 			 : "a" (sw), "d" (fsize), "d" (frame_offset/4-1),
-			   "n" (frame_offset), "a" (fp)
+			   "n" (frame_offset), "a" (buf + fsize/4)
 			 : "a0");
 #undef frame_offset
-		/*
-		 * If we ever get here an exception occurred while
-		 * building the above stack-frame.
-		 */
-		goto badframe;
 	}
+	return 0;
+}
 
-	*pd0 = context.sc_d0;
-	return err;
+static inline int
+restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *usc, void __user *fp)
+{
+	int formatvec;
+	struct sigcontext context;
+	int err;
+
+	/* Always make any pending restarted system calls return -EINTR */
+	current_thread_info()->restart_block.fn = do_no_restart_syscall;
+
+	/* get previous context */
+	if (copy_from_user(&context, usc, sizeof(context)))
+		goto badframe;
+
+	/* restore passed registers */
+	regs->d0 = context.sc_d0;
+	regs->d1 = context.sc_d1;
+	regs->a0 = context.sc_a0;
+	regs->a1 = context.sc_a1;
+	regs->sr = (regs->sr & 0xff00) | (context.sc_sr & 0xff);
+	regs->pc = context.sc_pc;
+	regs->orig_d0 = -1;		/* disable syscall checks */
+	wrusp(context.sc_usp);
+	formatvec = context.sc_formatvec;
+
+	err = restore_fpu_state(&context);
+
+	if (err || mangle_kernel_stack(regs, formatvec, fp))
+		goto badframe;
+
+	return 0;
 
 badframe:
 	return 1;
@@ -407,9 +375,9 @@ badframe:
 
 static inline int
 rt_restore_ucontext(struct pt_regs *regs, struct switch_stack *sw,
-		    struct ucontext __user *uc, int *pd0)
+		    struct ucontext __user *uc)
 {
-	int fsize, temp;
+	int temp;
 	greg_t __user *gregs = uc->uc_mcontext.gregs;
 	unsigned long usp;
 	int err;
@@ -443,65 +411,16 @@ rt_restore_ucontext(struct pt_regs *regs
 	regs->sr = (regs->sr & 0xff00) | (temp & 0xff);
 	regs->orig_d0 = -1;		/* disable syscall checks */
 	err |= __get_user(temp, &uc->uc_formatvec);
-	regs->format = temp >> 12;
-	regs->vector = temp & 0xfff;
 
 	err |= rt_restore_fpu_state(uc);
 
-	if (do_sigaltstack(&uc->uc_stack, NULL, usp) == -EFAULT)
-		goto badframe;
-
-	fsize = frame_extra_sizes[regs->format];
-	if (fsize < 0) {
-		/*
-		 * user process trying to return with weird frame format
-		 */
-#ifdef DEBUG
-		printk("user process returning with weird frame format\n");
-#endif
+	if (err || do_sigaltstack(&uc->uc_stack, NULL, usp) == -EFAULT)
 		goto badframe;
-	}
-
-	/* OK.	Make room on the supervisor stack for the extra junk,
-	 * if necessary.
-	 */
 
-	if (fsize) {
-#define frame_offset (sizeof(struct pt_regs)+sizeof(struct switch_stack))
-		__asm__ __volatile__
-			("   movel %0,%/a0\n\t"
-			 "   subl %1,%/a0\n\t"     /* make room on stack */
-			 "   movel %/a0,%/sp\n\t"  /* set stack pointer */
-			 /* move switch_stack and pt_regs */
-			 "1: movel %0@+,%/a0@+\n\t"
-			 "   dbra %2,1b\n\t"
-			 "   lea %/sp@(%c3),%/a0\n\t" /* add offset of fmt */
-			 "   lsrl  #2,%1\n\t"
-			 "   subql #1,%1\n\t"
-			 "2: movesl %4@+,%2\n\t"
-			 "3: movel %2,%/a0@+\n\t"
-			 "   dbra %1,2b\n\t"
-			 "   bral ret_from_signal\n"
-			 "4:\n"
-			 ".section __ex_table,\"a\"\n"
-			 "   .align 4\n"
-			 "   .long 2b,4b\n"
-			 "   .long 3b,4b\n"
-			 ".previous"
-			 : /* no outputs, it doesn't ever return */
-			 : "a" (sw), "d" (fsize), "d" (frame_offset/4-1),
-			   "n" (frame_offset), "a" (&uc->uc_extra)
-			 : "a0");
-#undef frame_offset
-		/*
-		 * If we ever get here an exception occurred while
-		 * building the above stack-frame.
-		 */
+	if (mangle_kernel_stack(regs, temp, &uc->uc_extra))
 		goto badframe;
-	}
 
-	*pd0 = regs->d0;
-	return err;
+	return 0;
 
 badframe:
 	return 1;
@@ -514,7 +433,6 @@ asmlinkage int do_sigreturn(unsigned lon
 	unsigned long usp = rdusp();
 	struct sigframe __user *frame = (struct sigframe __user *)(usp - 4);
 	sigset_t set;
-	int d0;
 
 	if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
 		goto badframe;
@@ -528,9 +446,9 @@ asmlinkage int do_sigreturn(unsigned lon
 	current->blocked = set;
 	recalc_sigpending();
 
-	if (restore_sigcontext(regs, &frame->sc, frame + 1, &d0))
+	if (restore_sigcontext(regs, &frame->sc, frame + 1))
 		goto badframe;
-	return d0;
+	return regs->d0;
 
 badframe:
 	force_sig(SIGSEGV, current);
@@ -544,7 +462,6 @@ asmlinkage int do_rt_sigreturn(unsigned
 	unsigned long usp = rdusp();
 	struct rt_sigframe __user *frame = (struct rt_sigframe __user *)(usp - 4);
 	sigset_t set;
-	int d0;
 
 	if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
 		goto badframe;
@@ -555,9 +472,9 @@ asmlinkage int do_rt_sigreturn(unsigned
 	current->blocked = set;
 	recalc_sigpending();
 
-	if (rt_restore_ucontext(regs, sw, &frame->uc, &d0))
+	if (rt_restore_ucontext(regs, sw, &frame->uc))
 		goto badframe;
-	return d0;
+	return regs->d0;
 
 badframe:
 	force_sig(SIGSEGV, current);
@@ -775,7 +692,7 @@ get_sigframe(struct k_sigaction *ka, str
 	return (void __user *)((usp - frame_size) & -8UL);
 }
 
-static void setup_frame (int sig, struct k_sigaction *ka,
+static int setup_frame (int sig, struct k_sigaction *ka,
 			 sigset_t *set, struct pt_regs *regs)
 {
 	struct sigframe __user *frame;
@@ -793,10 +710,8 @@ static void setup_frame (int sig, struct
 
 	frame = get_sigframe(ka, regs, sizeof(*frame) + fsize);
 
-	if (fsize) {
+	if (fsize)
 		err |= copy_to_user (frame + 1, regs + 1, fsize);
-		regs->stkadj = fsize;
-	}
 
 	err |= __put_user((current_thread_info()->exec_domain
 			   && current_thread_info()->exec_domain->signal_invmap
@@ -826,11 +741,21 @@ static void setup_frame (int sig, struct
 
 	push_cache ((unsigned long) &frame->retcode);
 
-	/* Set up registers for signal handler */
+	/*
+	 * Set up registers for signal handler.  All the state we are about
+	 * to destroy is successfully copied to sigframe.
+	 */
 	wrusp ((unsigned long) frame);
 	regs->pc = (unsigned long) ka->sa.sa_handler;
 
-adjust_stack:
+	/*
+	 * This is subtle; if we build more than one sigframe, all but the
+	 * first one will see frame format 0 and have fsize == 0, so we won't
+	 * screw stkadj.
+	 */
+	if (fsize)
+		regs->stkadj = fsize;
+
 	/* Prepare to skip over the extra stuff in the exception frame.  */
 	if (regs->stkadj) {
 		struct pt_regs *tregs =
@@ -845,14 +770,14 @@ adjust_stack:
 		tregs->pc = regs->pc;
 		tregs->sr = regs->sr;
 	}
-	return;
+	return 0;
 
 give_sigsegv:
 	force_sigsegv(sig, current);
-	goto adjust_stack;
+	return err;
 }
 
-static void setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info,
+static int setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info,
 			    sigset_t *set, struct pt_regs *regs)
 {
 	struct rt_sigframe __user *frame;
@@ -869,10 +794,8 @@ static void setup_rt_frame (int sig, str
 
 	frame = get_sigframe(ka, regs, sizeof(*frame));
 
-	if (fsize) {
+	if (fsize)
 		err |= copy_to_user (&frame->uc.uc_extra, regs + 1, fsize);
-		regs->stkadj = fsize;
-	}
 
 	err |= __put_user((current_thread_info()->exec_domain
 			   && current_thread_info()->exec_domain->signal_invmap
@@ -914,11 +837,21 @@ static void setup_rt_frame (int sig, str
 
 	push_cache ((unsigned long) &frame->retcode);
 
-	/* Set up registers for signal handler */
+	/*
+	 * Set up registers for signal handler.  All the state we are about
+	 * to destroy is successfully copied to sigframe.
+	 */
 	wrusp ((unsigned long) frame);
 	regs->pc = (unsigned long) ka->sa.sa_handler;
 
-adjust_stack:
+	/*
+	 * This is subtle; if we build more than one sigframe, all but the
+	 * first one will see frame format 0 and have fsize == 0, so we won't
+	 * screw stkadj.
+	 */
+	if (fsize)
+		regs->stkadj = fsize;
+
 	/* Prepare to skip over the extra stuff in the exception frame.  */
 	if (regs->stkadj) {
 		struct pt_regs *tregs =
@@ -933,11 +866,11 @@ adjust_stack:
 		tregs->pc = regs->pc;
 		tregs->sr = regs->sr;
 	}
-	return;
+	return 0;
 
 give_sigsegv:
 	force_sigsegv(sig, current);
-	goto adjust_stack;
+	return err;
 }
 
 static inline void
@@ -995,6 +928,7 @@ static void
 handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
 	      sigset_t *oldset, struct pt_regs *regs)
 {
+	int err;
 	/* are we from a system call? */
 	if (regs->orig_d0 >= 0)
 		/* If so, check system call restarting.. */
@@ -1002,17 +936,24 @@ handle_signal(int sig, struct k_sigactio
 
 	/* set up the stack frame */
 	if (ka->sa.sa_flags & SA_SIGINFO)
-		setup_rt_frame(sig, ka, info, oldset, regs);
+		err = setup_rt_frame(sig, ka, info, oldset, regs);
 	else
-		setup_frame(sig, ka, oldset, regs);
+		err = setup_frame(sig, ka, oldset, regs);
 
-	if (ka->sa.sa_flags & SA_ONESHOT)
-		ka->sa.sa_handler = SIG_DFL;
+	if (err)
+		return;
 
 	sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
 	if (!(ka->sa.sa_flags & SA_NODEFER))
 		sigaddset(&current->blocked,sig);
 	recalc_sigpending();
+
+	if (test_thread_flag(TIF_DELAYED_TRACE)) {
+		regs->sr &= ~0x8000;
+		send_sig(SIGTRAP, current, 1);
+	}
+
+	clear_thread_flag(TIF_RESTORE_SIGMASK);
 }
 
 /*
@@ -1020,22 +961,25 @@ handle_signal(int sig, struct k_sigactio
  * want to handle. Thus you cannot kill init even with a SIGKILL even by
  * mistake.
  */
-asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs)
+asmlinkage void do_signal(struct pt_regs *regs)
 {
 	siginfo_t info;
 	struct k_sigaction ka;
 	int signr;
+	sigset_t *oldset;
 
 	current->thread.esp0 = (unsigned long) regs;
 
-	if (!oldset)
+	if (test_thread_flag(TIF_RESTORE_SIGMASK))
+		oldset = &current->saved_sigmask;
+	else
 		oldset = &current->blocked;
 
 	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
 	if (signr > 0) {
 		/* Whee!  Actually deliver the signal.  */
 		handle_signal(signr, &ka, &info, oldset, regs);
-		return 1;
+		return;
 	}
 
 	/* Did we come from a system call? */
@@ -1043,5 +987,9 @@ asmlinkage int do_signal(sigset_t *oldse
 		/* Restart the system call - no handlers present */
 		handle_restart(regs, NULL, 0);
 
-	return 0;
+	/* If there's no signal to deliver, we just restore the saved mask.  */
+	if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
+		clear_thread_flag(TIF_RESTORE_SIGMASK);
+		sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
+	}
 }
diff -druNp linux-libre-2.6.37-gnu1/arch/m68k/lib/string.c linux-libre-2.6.38-gnu1/arch/m68k/lib/string.c
--- linux-libre-2.6.37-gnu1/arch/m68k/lib/string.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/m68k/lib/string.c	2011-03-14 21:20:32.000000000 -0400
@@ -243,14 +243,3 @@ void *memmove(void *dest, const void *sr
 	return xdest;
 }
 EXPORT_SYMBOL(memmove);
-
-int memcmp(const void *cs, const void *ct, size_t count)
-{
-	const unsigned char *su1, *su2;
-
-	for (su1 = cs, su2 = ct; count > 0; ++su1, ++su2, count--)
-		if (*su1 != *su2)
-			return *su1 < *su2 ? -1 : +1;
-	return 0;
-}
-EXPORT_SYMBOL(memcmp);
diff -druNp linux-libre-2.6.37-gnu1/arch/m68k/mac/psc.c linux-libre-2.6.38-gnu1/arch/m68k/mac/psc.c
--- linux-libre-2.6.37-gnu1/arch/m68k/mac/psc.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/m68k/mac/psc.c	2011-03-14 21:20:32.000000000 -0400
@@ -88,7 +88,7 @@ void __init psc_init(void)
 
 	/*
 	 * The PSC is always at the same spot, but using psc
-	 * keeps things consisant with the psc_xxxx functions.
+	 * keeps things consistent with the psc_xxxx functions.
 	 */
 
 	psc = (void *) PSC_BASE;
diff -druNp linux-libre-2.6.37-gnu1/arch/m68knommu/configs/m5208evb_defconfig linux-libre-2.6.38-gnu1/arch/m68knommu/configs/m5208evb_defconfig
--- linux-libre-2.6.37-gnu1/arch/m68knommu/configs/m5208evb_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/m68knommu/configs/m5208evb_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -1,7 +1,7 @@
 CONFIG_EXPERIMENTAL=y
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_KALLSYMS is not set
 # CONFIG_HOTPLUG is not set
 # CONFIG_FUTEX is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/m68knommu/configs/m5249evb_defconfig linux-libre-2.6.38-gnu1/arch/m68knommu/configs/m5249evb_defconfig
--- linux-libre-2.6.37-gnu1/arch/m68knommu/configs/m5249evb_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/m68knommu/configs/m5249evb_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -1,7 +1,7 @@
 CONFIG_EXPERIMENTAL=y
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_KALLSYMS is not set
 # CONFIG_HOTPLUG is not set
 # CONFIG_FUTEX is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/m68knommu/configs/m5272c3_defconfig linux-libre-2.6.38-gnu1/arch/m68knommu/configs/m5272c3_defconfig
--- linux-libre-2.6.37-gnu1/arch/m68knommu/configs/m5272c3_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/m68knommu/configs/m5272c3_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -1,7 +1,7 @@
 CONFIG_EXPERIMENTAL=y
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_KALLSYMS is not set
 # CONFIG_HOTPLUG is not set
 # CONFIG_FUTEX is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/m68knommu/configs/m5275evb_defconfig linux-libre-2.6.38-gnu1/arch/m68knommu/configs/m5275evb_defconfig
--- linux-libre-2.6.37-gnu1/arch/m68knommu/configs/m5275evb_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/m68knommu/configs/m5275evb_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -1,7 +1,7 @@
 CONFIG_EXPERIMENTAL=y
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_KALLSYMS is not set
 # CONFIG_HOTPLUG is not set
 # CONFIG_FUTEX is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/m68knommu/configs/m5307c3_defconfig linux-libre-2.6.38-gnu1/arch/m68knommu/configs/m5307c3_defconfig
--- linux-libre-2.6.37-gnu1/arch/m68knommu/configs/m5307c3_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/m68knommu/configs/m5307c3_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -1,7 +1,7 @@
 CONFIG_EXPERIMENTAL=y
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_KALLSYMS is not set
 # CONFIG_HOTPLUG is not set
 # CONFIG_FUTEX is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/m68knommu/configs/m5407c3_defconfig linux-libre-2.6.38-gnu1/arch/m68knommu/configs/m5407c3_defconfig
--- linux-libre-2.6.37-gnu1/arch/m68knommu/configs/m5407c3_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/m68knommu/configs/m5407c3_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -1,7 +1,7 @@
 CONFIG_EXPERIMENTAL=y
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_KALLSYMS is not set
 # CONFIG_HOTPLUG is not set
 # CONFIG_FUTEX is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/m68knommu/defconfig linux-libre-2.6.38-gnu1/arch/m68knommu/defconfig
--- linux-libre-2.6.37-gnu1/arch/m68knommu/defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/m68knommu/defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -1,7 +1,7 @@
 CONFIG_EXPERIMENTAL=y
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_KALLSYMS is not set
 # CONFIG_HOTPLUG is not set
 # CONFIG_FUTEX is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/m68knommu/Kconfig linux-libre-2.6.38-gnu1/arch/m68knommu/Kconfig
--- linux-libre-2.6.37-gnu1/arch/m68knommu/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/m68knommu/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -2,6 +2,7 @@ config M68K
 	bool
 	default y
 	select HAVE_IDE
+	select HAVE_GENERIC_HARDIRQS
 
 config MMU
 	bool
@@ -48,14 +49,6 @@ config GENERIC_HWEIGHT
 	bool
 	default y
 
-config GENERIC_HARDIRQS
-	bool
-	default y
-
-config GENERIC_HARDIRQS_NO__DO_IRQ
-	bool
-	default y
-
 config GENERIC_CALIBRATE_DELAY
 	bool
 	default y
@@ -75,6 +68,16 @@ config GENERIC_CLOCKEVENTS
 config NO_IOPORT
 	def_bool y
 
+config COLDFIRE_SW_A7
+	bool
+	default n
+
+config HAVE_CACHE_SPLIT
+	bool
+
+config HAVE_CACHE_CB
+	bool
+
 source "init/Kconfig"
 
 source "kernel/Kconfig.freezer"
@@ -107,69 +110,90 @@ config M68360
 
 config M5206
 	bool "MCF5206"
+	select COLDFIRE_SW_A7
 	help
 	  Motorola ColdFire 5206 processor support.
 
 config M5206e
 	bool "MCF5206e"
+	select COLDFIRE_SW_A7
 	help
 	  Motorola ColdFire 5206e processor support.
 
 config M520x
 	bool "MCF520x"
 	select GENERIC_CLOCKEVENTS
+	select HAVE_CACHE_SPLIT
 	help
 	   Freescale Coldfire 5207/5208 processor support.
 
 config M523x
 	bool "MCF523x"
 	select GENERIC_CLOCKEVENTS
+	select HAVE_CACHE_SPLIT
 	help
 	  Freescale Coldfire 5230/1/2/4/5 processor support
 
 config M5249
 	bool "MCF5249"
+	select COLDFIRE_SW_A7
 	help
 	  Motorola ColdFire 5249 processor support.
 
 config M5271
 	bool "MCF5271"
+	select HAVE_CACHE_SPLIT
 	help
 	  Freescale (Motorola) ColdFire 5270/5271 processor support.
 
 config M5272
 	bool "MCF5272"
+	select COLDFIRE_SW_A7
 	help
 	  Motorola ColdFire 5272 processor support.
 
 config M5275
 	bool "MCF5275"
+	select HAVE_CACHE_SPLIT
 	help
 	  Freescale (Motorola) ColdFire 5274/5275 processor support.
 
 config M528x
 	bool "MCF528x"
 	select GENERIC_CLOCKEVENTS
+	select HAVE_CACHE_SPLIT
 	help
 	  Motorola ColdFire 5280/5282 processor support.
 
 config M5307
 	bool "MCF5307"
+	select COLDFIRE_SW_A7
+	select HAVE_CACHE_CB
 	help
 	  Motorola ColdFire 5307 processor support.
 
 config M532x
 	bool "MCF532x"
+	select HAVE_CACHE_CB
 	help
 	  Freescale (Motorola) ColdFire 532x processor support.
 
 config M5407
 	bool "MCF5407"
+	select COLDFIRE_SW_A7
+	select HAVE_CACHE_CB
 	help
 	  Motorola ColdFire 5407 processor support.
 
+config M547x
+	bool "MCF547x"
+	select HAVE_CACHE_CB
+	help
+	  Freescale ColdFire 5470/5471/5472/5473/5474/5475 processor support.
+
 config M548x
 	bool "MCF548x"
+	select HAVE_CACHE_CB
 	help
 	  Freescale ColdFire 5480/5481/5482/5483/5484/5485 processor support.
 
@@ -181,9 +205,14 @@ config M527x
 	select GENERIC_CLOCKEVENTS
 	default y
 
+config M54xx
+	bool
+	depends on (M548x || M547x)
+	default y
+
 config COLDFIRE
 	bool
-	depends on (M5206 || M5206e || M520x || M523x || M5249 || M527x || M5272 || M528x || M5307 || M532x || M5407 || M548x)
+	depends on (M5206 || M5206e || M520x || M523x || M5249 || M527x || M5272 || M528x || M5307 || M532x || M5407 || M54xx)
 	select GENERIC_GPIO
 	select ARCH_REQUIRE_GPIOLIB
 	default y
@@ -230,6 +259,46 @@ config OLDMASK
 	  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
@@ -245,16 +314,16 @@ config XCOPILOT_BUGS
 	  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.
+	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.
+	bool "Arcturus Networks uC5282 board support"
+	depends on M528x
+	help
+	  Support for the Arcturus Networks uC5282 dimm board.
 
 config UCSIMM
 	bool "uCsimm module support"
@@ -279,7 +348,7 @@ config DIRECT_IO_ACCESS
 	depends on (UCSIMM || UCDIMM || DRAGEN2)
 	help
 	  Disable the CPU internal registers protection in user mode,
-          to allow a user application to read/write them.
+	  to allow a user application to read/write them.
 
 config INIT_LCD
 	bool "Initialize LCD"
@@ -517,7 +586,7 @@ config EMAC_INC
 	depends on (SOM5282EM)
 
 config SNEHA
-        bool
+	bool
 	default y
 	depends on CPU16B
 
diff -druNp linux-libre-2.6.37-gnu1/arch/m68knommu/kernel/entry.S linux-libre-2.6.38-gnu1/arch/m68knommu/kernel/entry.S
--- linux-libre-2.6.37-gnu1/arch/m68knommu/kernel/entry.S	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/m68knommu/kernel/entry.S	2011-03-14 21:20:32.000000000 -0400
@@ -112,22 +112,6 @@ ENTRY(sys_clone)
 	RESTORE_SWITCH_STACK
 	rts
 
-ENTRY(sys_sigsuspend)
-	SAVE_SWITCH_STACK
-	pea	%sp@(SWITCH_STACK_SIZE)
-	jbsr	do_sigsuspend
-	addql	#4,%sp
-	RESTORE_SWITCH_STACK
-	rts
-
-ENTRY(sys_rt_sigsuspend)
-	SAVE_SWITCH_STACK
-	pea	%sp@(SWITCH_STACK_SIZE)
-	jbsr	do_rt_sigsuspend
-	addql	#4,%sp
-	RESTORE_SWITCH_STACK
-	rts
-
 ENTRY(sys_sigreturn)
 	SAVE_SWITCH_STACK
 	jbsr	do_sigreturn
diff -druNp linux-libre-2.6.37-gnu1/arch/m68knommu/kernel/setup.c linux-libre-2.6.38-gnu1/arch/m68knommu/kernel/setup.c
--- linux-libre-2.6.37-gnu1/arch/m68knommu/kernel/setup.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/m68knommu/kernel/setup.c	2011-03-14 21:20:32.000000000 -0400
@@ -55,55 +55,29 @@ void (*mach_halt)(void);
 void (*mach_power_off)(void);
 
 #ifdef CONFIG_M68328
-	#define CPU "MC68328"
+#define CPU_NAME	"MC68328"
 #endif
 #ifdef CONFIG_M68EZ328
-	#define CPU "MC68EZ328"
+#define CPU_NAME	"MC68EZ328"
 #endif
 #ifdef CONFIG_M68VZ328
-	#define CPU "MC68VZ328"
+#define CPU_NAME	"MC68VZ328"
 #endif
 #ifdef CONFIG_M68360
-	#define CPU "MC68360"
-#endif
-#if defined(CONFIG_M5206)
-	#define	CPU "COLDFIRE(m5206)"
-#endif
-#if defined(CONFIG_M5206e)
-	#define	CPU "COLDFIRE(m5206e)"
-#endif
-#if defined(CONFIG_M520x)
-	#define CPU "COLDFIRE(m520x)"
-#endif
-#if defined(CONFIG_M523x)
-	#define CPU "COLDFIRE(m523x)"
-#endif
-#if defined(CONFIG_M5249)
-	#define CPU "COLDFIRE(m5249)"
-#endif
-#if defined(CONFIG_M5271)
-	#define CPU "COLDFIRE(m5270/5271)"
-#endif
-#if defined(CONFIG_M5272)
-	#define CPU "COLDFIRE(m5272)"
-#endif
-#if defined(CONFIG_M5275)
-	#define CPU "COLDFIRE(m5274/5275)"
-#endif
-#if defined(CONFIG_M528x)
-	#define CPU "COLDFIRE(m5280/5282)"
-#endif
-#if defined(CONFIG_M5307)
-	#define	CPU "COLDFIRE(m5307)"
-#endif
-#if defined(CONFIG_M532x)
-	#define	CPU "COLDFIRE(m532x)"
+#define CPU_NAME	"MC68360"
 #endif
-#if defined(CONFIG_M5407)
-	#define	CPU "COLDFIRE(m5407)"
+#ifndef CPU_NAME
+#define	CPU_NAME	"UNKNOWN"
 #endif
-#ifndef CPU
-	#define	CPU "UNKNOWN"
+
+/*
+ * Different cores have different instruction execution timings.
+ * The old/traditional 68000 cores are basically all the same, at 16.
+ * The ColdFire cores vary a little, their values are defined in their
+ * headers. We default to the standard 68000 value here.
+ */
+#ifndef CPU_INSTR_PER_JIFFY
+#define	CPU_INSTR_PER_JIFFY	16
 #endif
 
 extern int _stext, _etext, _sdata, _edata, _sbss, _ebss, _end;
@@ -208,7 +182,7 @@ void __init setup_arch(char **cmdline_p)
 	command_line[sizeof(command_line) - 1] = 0;
 #endif /* CONFIG_UBOOT */
 
-	printk(KERN_INFO "\x0F\r\n\nuClinux/" CPU "\n");
+	printk(KERN_INFO "\x0F\r\n\nuClinux/" CPU_NAME "\n");
 
 #ifdef CONFIG_UCDIMM
 	printk(KERN_INFO "uCdimm by Lineo, Inc. <www.lineo.com>\n");
@@ -257,11 +231,6 @@ void __init setup_arch(char **cmdline_p)
 	memcpy(boot_command_line, command_line, COMMAND_LINE_SIZE);
 	boot_command_line[COMMAND_LINE_SIZE-1] = 0;
 
-#ifdef DEBUG
-	if (strlen(*cmdline_p))
-		printk(KERN_DEBUG "Command line: '%s'\n", *cmdline_p);
-#endif
-
 #if defined(CONFIG_FRAMEBUFFER_CONSOLE) && defined(CONFIG_DUMMY_CONSOLE)
 	conswitchp = &dummy_con;
 #endif
@@ -303,15 +272,10 @@ static int show_cpuinfo(struct seq_file
 	char *cpu, *mmu, *fpu;
 	u_long clockfreq;
 
-	cpu = CPU;
+	cpu = CPU_NAME;
 	mmu = "none";
 	fpu = "none";
-
-#ifdef CONFIG_COLDFIRE
-	clockfreq = (loops_per_jiffy * HZ) * 3;
-#else
-	clockfreq = (loops_per_jiffy * HZ) * 16;
-#endif
+	clockfreq = (loops_per_jiffy * HZ) * CPU_INSTR_PER_JIFFY;
 
 	seq_printf(m, "CPU:\t\t%s\n"
 		      "MMU:\t\t%s\n"
diff -druNp linux-libre-2.6.37-gnu1/arch/m68knommu/kernel/signal.c linux-libre-2.6.38-gnu1/arch/m68knommu/kernel/signal.c
--- linux-libre-2.6.37-gnu1/arch/m68knommu/kernel/signal.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/m68knommu/kernel/signal.c	2011-03-14 21:20:32.000000000 -0400
@@ -53,65 +53,30 @@
 
 void ret_from_user_signal(void);
 void ret_from_user_rt_signal(void);
-asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs);
 
 /*
  * Atomically swap in the new signal mask, and wait for a signal.
  */
-asmlinkage int do_sigsuspend(struct pt_regs *regs)
+asmlinkage int
+sys_sigsuspend(int unused0, int unused1, old_sigset_t mask)
 {
-	old_sigset_t mask = regs->d3;
-	sigset_t saveset;
-
 	mask &= _BLOCKABLE;
 	spin_lock_irq(&current->sighand->siglock);
-	saveset = current->blocked;
+	current->saved_sigmask = current->blocked;
 	siginitset(&current->blocked, mask);
 	recalc_sigpending();
 	spin_unlock_irq(&current->sighand->siglock);
 
-	regs->d0 = -EINTR;
-	while (1) {
-		current->state = TASK_INTERRUPTIBLE;
-		schedule();
-		if (do_signal(&saveset, regs))
-			return -EINTR;
-	}
-}
-
-asmlinkage int
-do_rt_sigsuspend(struct pt_regs *regs)
-{
-	sigset_t *unewset = (sigset_t *)regs->d1;
-	size_t sigsetsize = (size_t)regs->d2;
-	sigset_t saveset, newset;
-
-	/* XXX: Don't preclude handling different sized sigset_t's.  */
-	if (sigsetsize != sizeof(sigset_t))
-		return -EINVAL;
-
-	if (copy_from_user(&newset, unewset, sizeof(newset)))
-		return -EFAULT;
-	sigdelsetmask(&newset, ~_BLOCKABLE);
-
-	spin_lock_irq(&current->sighand->siglock);
-	saveset = current->blocked;
-	current->blocked = newset;
-	recalc_sigpending();
-	spin_unlock_irq(&current->sighand->siglock);
+	current->state = TASK_INTERRUPTIBLE;
+	schedule();
+	set_restore_sigmask();
 
-	regs->d0 = -EINTR;
-	while (1) {
-		current->state = TASK_INTERRUPTIBLE;
-		schedule();
-		if (do_signal(&saveset, regs))
-			return -EINTR;
-	}
+	return -ERESTARTNOHAND;
 }
 
-asmlinkage int 
-sys_sigaction(int sig, const struct old_sigaction *act,
-	      struct old_sigaction *oact)
+asmlinkage int
+sys_sigaction(int sig, const struct old_sigaction __user *act,
+	      struct old_sigaction __user *oact)
 {
 	struct k_sigaction new_ka, old_ka;
 	int ret;
@@ -120,10 +85,10 @@ sys_sigaction(int sig, const struct old_
 		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))
+		    __get_user(new_ka.sa.sa_restorer, &act->sa_restorer) ||
+		    __get_user(new_ka.sa.sa_flags, &act->sa_flags) ||
+		    __get_user(mask, &act->sa_mask))
 			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);
 	}
 
@@ -132,17 +97,17 @@ sys_sigaction(int sig, const struct old_
 	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))
+		    __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer) ||
+		    __put_user(old_ka.sa.sa_flags, &oact->sa_flags) ||
+		    __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask))
 			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;
 }
 
 asmlinkage int
-sys_sigaltstack(const stack_t *uss, stack_t *uoss)
+sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss)
 {
 	return do_sigaltstack(uss, uoss, rdusp());
 }
@@ -157,10 +122,10 @@ sys_sigaltstack(const stack_t *uss, stac
 
 struct sigframe
 {
-	char *pretcode;
+	char __user *pretcode;
 	int sig;
 	int code;
-	struct sigcontext *psc;
+	struct sigcontext __user *psc;
 	char retcode[8];
 	unsigned long extramask[_NSIG_WORDS-1];
 	struct sigcontext sc;
@@ -168,10 +133,10 @@ struct sigframe
 
 struct rt_sigframe
 {
-	char *pretcode;
+	char __user *pretcode;
 	int sig;
-	struct siginfo *pinfo;
-	void *puc;
+	struct siginfo __user *pinfo;
+	void __user *puc;
 	char retcode[8];
 	struct siginfo info;
 	struct ucontext uc;
@@ -198,8 +163,8 @@ static inline int restore_fpu_state(stru
 		goto out;
 
 	    __asm__ volatile (".chip 68k/68881\n\t"
-			      "fmovemx %0,%/fp0-%/fp1\n\t"
-			      "fmoveml %1,%/fpcr/%/fpsr/%/fpiar\n\t"
+			      "fmovemx %0,%%fp0-%%fp1\n\t"
+			      "fmoveml %1,%%fpcr/%%fpsr/%%fpiar\n\t"
 			      ".chip 68k"
 			      : /* no outputs */
 			      : "m" (*sc->sc_fpregs), "m" (*sc->sc_fpcntl));
@@ -218,7 +183,7 @@ out:
 #define uc_formatvec	uc_filler[FPCONTEXT_SIZE/4]
 #define uc_extra	uc_filler[FPCONTEXT_SIZE/4+1]
 
-static inline int rt_restore_fpu_state(struct ucontext *uc)
+static inline int rt_restore_fpu_state(struct ucontext __user *uc)
 {
 	unsigned char fpstate[FPCONTEXT_SIZE];
 	int context_size = 0;
@@ -228,7 +193,7 @@ static inline int rt_restore_fpu_state(s
 	if (FPU_IS_EMU) {
 		/* restore fpu control register */
 		if (__copy_from_user(current->thread.fpcntl,
-				&uc->uc_mcontext.fpregs.f_pcr, 12))
+				uc->uc_mcontext.fpregs.f_fpcntl, 12))
 			goto out;
 		/* restore all other fpu register */
 		if (__copy_from_user(current->thread.fp,
@@ -237,7 +202,7 @@ static inline int rt_restore_fpu_state(s
 		return 0;
 	}
 
-	if (__get_user(*(long *)fpstate, (long *)&uc->uc_fpstate))
+	if (__get_user(*(long *)fpstate, (long __user *)&uc->uc_fpstate))
 		goto out;
 	if (fpstate[0]) {
 		context_size = fpstate[1];
@@ -249,15 +214,15 @@ static inline int rt_restore_fpu_state(s
 		     sizeof(fpregs)))
 			goto out;
 		__asm__ volatile (".chip 68k/68881\n\t"
-				  "fmovemx %0,%/fp0-%/fp7\n\t"
-				  "fmoveml %1,%/fpcr/%/fpsr/%/fpiar\n\t"
+				  "fmovemx %0,%%fp0-%%fp7\n\t"
+				  "fmoveml %1,%%fpcr/%%fpsr/%%fpiar\n\t"
 				  ".chip 68k"
 				  : /* no outputs */
 				  : "m" (*fpregs.f_fpregs),
-				    "m" (fpregs.f_pcr));
+				    "m" (*fpregs.f_fpcntl));
 	}
 	if (context_size &&
-	    __copy_from_user(fpstate + 4, (long *)&uc->uc_fpstate + 1,
+	    __copy_from_user(fpstate + 4, (long __user *)&uc->uc_fpstate + 1,
 			     context_size))
 		goto out;
 	__asm__ volatile (".chip 68k/68881\n\t"
@@ -272,7 +237,7 @@ out:
 #endif
 
 static inline int
-restore_sigcontext(struct pt_regs *regs, struct sigcontext *usc, void *fp,
+restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *usc, void __user *fp,
 		   int *pd0)
 {
 	int formatvec;
@@ -312,10 +277,10 @@ badframe:
 
 static inline int
 rt_restore_ucontext(struct pt_regs *regs, struct switch_stack *sw,
-		    struct ucontext *uc, int *pd0)
+		    struct ucontext __user *uc, int *pd0)
 {
 	int temp;
-	greg_t *gregs = uc->uc_mcontext.gregs;
+	greg_t __user *gregs = uc->uc_mcontext.gregs;
 	unsigned long usp;
 	int err;
 
@@ -365,7 +330,7 @@ asmlinkage int do_sigreturn(unsigned lon
 	struct switch_stack *sw = (struct switch_stack *) &__unused;
 	struct pt_regs *regs = (struct pt_regs *) (sw + 1);
 	unsigned long usp = rdusp();
-	struct sigframe *frame = (struct sigframe *)(usp - 4);
+	struct sigframe __user *frame = (struct sigframe __user *)(usp - 4);
 	sigset_t set;
 	int d0;
 
@@ -397,7 +362,7 @@ asmlinkage int do_rt_sigreturn(unsigned
 	struct switch_stack *sw = (struct switch_stack *) &__unused;
 	struct pt_regs *regs = (struct pt_regs *) (sw + 1);
 	unsigned long usp = rdusp();
-	struct rt_sigframe *frame = (struct rt_sigframe *)(usp - 4);
+	struct rt_sigframe __user *frame = (struct rt_sigframe __user *)(usp - 4);
 	sigset_t set;
 	int d0;
 
@@ -443,17 +408,17 @@ static inline void save_fpu_state(struct
 	if (sc->sc_fpstate[0]) {
 		fpu_version = sc->sc_fpstate[0];
 		__asm__ volatile (".chip 68k/68881\n\t"
-				  "fmovemx %/fp0-%/fp1,%0\n\t"
-				  "fmoveml %/fpcr/%/fpsr/%/fpiar,%1\n\t"
+				  "fmovemx %%fp0-%%fp1,%0\n\t"
+				  "fmoveml %%fpcr/%%fpsr/%%fpiar,%1\n\t"
 				  ".chip 68k"
-				  : /* no outputs */
-				  : "m" (*sc->sc_fpregs),
-				    "m" (*sc->sc_fpcntl)
+				  : "=m" (*sc->sc_fpregs),
+				    "=m" (*sc->sc_fpcntl)
+				  : /* no inputs */
 				  : "memory");
 	}
 }
 
-static inline int rt_save_fpu_state(struct ucontext *uc, struct pt_regs *regs)
+static inline int rt_save_fpu_state(struct ucontext __user *uc, struct pt_regs *regs)
 {
 	unsigned char fpstate[FPCONTEXT_SIZE];
 	int context_size = 0;
@@ -461,7 +426,7 @@ static inline int rt_save_fpu_state(stru
 
 	if (FPU_IS_EMU) {
 		/* save fpu control register */
-		err |= copy_to_user(&uc->uc_mcontext.fpregs.f_pcr,
+		err |= copy_to_user(uc->uc_mcontext.fpregs.f_pcntl,
 				current->thread.fpcntl, 12);
 		/* save all other fpu register */
 		err |= copy_to_user(uc->uc_mcontext.fpregs.f_fpregs,
@@ -474,24 +439,24 @@ static inline int rt_save_fpu_state(stru
 			  ".chip 68k"
 			  : : "m" (*fpstate) : "memory");
 
-	err |= __put_user(*(long *)fpstate, (long *)&uc->uc_fpstate);
+	err |= __put_user(*(long *)fpstate, (long __user *)&uc->uc_fpstate);
 	if (fpstate[0]) {
 		fpregset_t fpregs;
 		context_size = fpstate[1];
 		fpu_version = fpstate[0];
 		__asm__ volatile (".chip 68k/68881\n\t"
-				  "fmovemx %/fp0-%/fp7,%0\n\t"
-				  "fmoveml %/fpcr/%/fpsr/%/fpiar,%1\n\t"
+				  "fmovemx %%fp0-%%fp7,%0\n\t"
+				  "fmoveml %%fpcr/%%fpsr/%%fpiar,%1\n\t"
 				  ".chip 68k"
-				  : /* no outputs */
-				  : "m" (*fpregs.f_fpregs),
-				    "m" (fpregs.f_pcr)
+				  : "=m" (*fpregs.f_fpregs),
+				    "=m" (*fpregs.f_fpcntl)
+				  : /* no inputs */
 				  : "memory");
 		err |= copy_to_user(&uc->uc_mcontext.fpregs, &fpregs,
 				    sizeof(fpregs));
 	}
 	if (context_size)
-		err |= copy_to_user((long *)&uc->uc_fpstate + 1, fpstate + 4,
+		err |= copy_to_user((long __user *)&uc->uc_fpstate + 1, fpstate + 4,
 				    context_size);
 	return err;
 }
@@ -516,10 +481,10 @@ static void setup_sigcontext(struct sigc
 #endif
 }
 
-static inline int rt_setup_ucontext(struct ucontext *uc, struct pt_regs *regs)
+static inline int rt_setup_ucontext(struct ucontext __user *uc, struct pt_regs *regs)
 {
 	struct switch_stack *sw = (struct switch_stack *)regs - 1;
-	greg_t *gregs = uc->uc_mcontext.gregs;
+	greg_t __user *gregs = uc->uc_mcontext.gregs;
 	int err = 0;
 
 	err |= __put_user(MCONTEXT_VERSION, &uc->uc_mcontext.version);
@@ -547,7 +512,7 @@ static inline int rt_setup_ucontext(stru
 	return err;
 }
 
-static inline void *
+static inline void __user *
 get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)
 {
 	unsigned long usp;
@@ -560,13 +525,13 @@ get_sigframe(struct k_sigaction *ka, str
 		if (!sas_ss_flags(usp))
 			usp = current->sas_ss_sp + current->sas_ss_size;
 	}
-	return (void *)((usp - frame_size) & -8UL);
+	return (void __user *)((usp - frame_size) & -8UL);
 }
 
-static void setup_frame (int sig, struct k_sigaction *ka,
+static int setup_frame (int sig, struct k_sigaction *ka,
 			 sigset_t *set, struct pt_regs *regs)
 {
-	struct sigframe *frame;
+	struct sigframe __user *frame;
 	struct sigcontext context;
 	int err = 0;
 
@@ -617,17 +582,17 @@ adjust_stack:
 		tregs->pc = regs->pc;
 		tregs->sr = regs->sr;
 	}
-	return;
+	return err;
 
 give_sigsegv:
 	force_sigsegv(sig, current);
 	goto adjust_stack;
 }
 
-static void setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info,
+static int setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info,
 			    sigset_t *set, struct pt_regs *regs)
 {
-	struct rt_sigframe *frame;
+	struct rt_sigframe __user *frame;
 	int err = 0;
 
 	frame = get_sigframe(ka, regs, sizeof(*frame));
@@ -644,8 +609,8 @@ static void setup_rt_frame (int sig, str
 
 	/* Create the ucontext.  */
 	err |= __put_user(0, &frame->uc.uc_flags);
-	err |= __put_user(0, &frame->uc.uc_link);
-	err |= __put_user((void *)current->sas_ss_sp,
+	err |= __put_user(NULL, &frame->uc.uc_link);
+	err |= __put_user((void __user *)current->sas_ss_sp,
 			  &frame->uc.uc_stack.ss_sp);
 	err |= __put_user(sas_ss_flags(rdusp()),
 			  &frame->uc.uc_stack.ss_flags);
@@ -681,7 +646,7 @@ adjust_stack:
 		tregs->pc = regs->pc;
 		tregs->sr = regs->sr;
 	}
-	return;
+	return err;
 
 give_sigsegv:
 	force_sigsegv(sig, current);
@@ -728,6 +693,7 @@ static void
 handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
 	      sigset_t *oldset, struct pt_regs *regs)
 {
+	int err;
 	/* are we from a system call? */
 	if (regs->orig_d0 >= 0)
 		/* If so, check system call restarting.. */
@@ -735,12 +701,12 @@ handle_signal(int sig, struct k_sigactio
 
 	/* set up the stack frame */
 	if (ka->sa.sa_flags & SA_SIGINFO)
-		setup_rt_frame(sig, ka, info, oldset, regs);
+		err = setup_rt_frame(sig, ka, info, oldset, regs);
 	else
-		setup_frame(sig, ka, oldset, regs);
+		err = setup_frame(sig, ka, oldset, regs);
 
-	if (ka->sa.sa_flags & SA_ONESHOT)
-		ka->sa.sa_handler = SIG_DFL;
+	if (err)
+		return;
 
 	spin_lock_irq(&current->sighand->siglock);
 	sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
@@ -748,6 +714,8 @@ handle_signal(int sig, struct k_sigactio
 		sigaddset(&current->blocked,sig);
 	recalc_sigpending();
 	spin_unlock_irq(&current->sighand->siglock);
+
+	clear_thread_flag(TIF_RESTORE_SIGMASK);
 }
 
 /*
@@ -755,11 +723,12 @@ handle_signal(int sig, struct k_sigactio
  * want to handle. Thus you cannot kill init even with a SIGKILL even by
  * mistake.
  */
-asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs)
+asmlinkage void do_signal(struct pt_regs *regs)
 {
 	struct k_sigaction ka;
 	siginfo_t info;
 	int signr;
+	sigset_t *oldset;
 
 	/*
 	 * We want the common case to go fast, which
@@ -768,16 +737,18 @@ asmlinkage int do_signal(sigset_t *oldse
 	 * if so.
 	 */
 	if (!user_mode(regs))
-		return 1;
+		return;
 
-	if (!oldset)
+	if (test_thread_flag(TIF_RESTORE_SIGMASK))
+		oldset = &current->saved_sigmask;
+	else
 		oldset = &current->blocked;
 
 	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
 	if (signr > 0) {
 		/* Whee!  Actually deliver the signal.  */
 		handle_signal(signr, &ka, &info, oldset, regs);
-		return 1;
+		return;
 	}
 
 	/* Did we come from a system call? */
@@ -785,5 +756,10 @@ asmlinkage int do_signal(sigset_t *oldse
 		/* Restart the system call - no handlers present */
 		handle_restart(regs, NULL, 0);
 	}
-	return 0;
+
+	/* If there's no signal to deliver, we just restore the saved mask.  */
+	if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
+		clear_thread_flag(TIF_RESTORE_SIGMASK);
+		sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
+	}
 }
diff -druNp linux-libre-2.6.37-gnu1/arch/m68knommu/kernel/vmlinux.lds.S linux-libre-2.6.38-gnu1/arch/m68knommu/kernel/vmlinux.lds.S
--- linux-libre-2.6.37-gnu1/arch/m68knommu/kernel/vmlinux.lds.S	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/m68knommu/kernel/vmlinux.lds.S	2011-03-14 21:20:32.000000000 -0400
@@ -141,6 +141,12 @@ SECTIONS {
 		*(__param)
 		__stop___param = .;
 
+		/* Built-in module versions */
+		. = ALIGN(4) ;
+		__start___modver = .;
+		*(__modver)
+		__stop___modver = .;
+
 		. = ALIGN(4) ;
 		_etext = . ;
 	} > TEXT
diff -druNp linux-libre-2.6.37-gnu1/arch/m68knommu/lib/Makefile linux-libre-2.6.38-gnu1/arch/m68knommu/lib/Makefile
--- linux-libre-2.6.37-gnu1/arch/m68knommu/lib/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/m68knommu/lib/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -4,4 +4,4 @@
 
 lib-y	:= ashldi3.o ashrdi3.o lshrdi3.o \
 	   muldi3.o mulsi3.o divsi3.o udivsi3.o modsi3.o umodsi3.o \
-	   checksum.o memcpy.o memset.o delay.o
+	   checksum.o memcpy.o memmove.o memset.o delay.o
diff -druNp linux-libre-2.6.37-gnu1/arch/m68knommu/lib/memmove.c linux-libre-2.6.38-gnu1/arch/m68knommu/lib/memmove.c
--- linux-libre-2.6.37-gnu1/arch/m68knommu/lib/memmove.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/m68knommu/lib/memmove.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,105 @@
+/*
+ * 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.
+ */
+
+#define __IN_STRING_C
+
+#include <linux/module.h>
+#include <linux/string.h>
+
+void *memmove(void *dest, const void *src, size_t n)
+{
+	void *xdest = dest;
+	size_t temp;
+
+	if (!n)
+		return xdest;
+
+	if (dest < src) {
+		if ((long)dest & 1) {
+			char *cdest = dest;
+			const char *csrc = src;
+			*cdest++ = *csrc++;
+			dest = cdest;
+			src = csrc;
+			n--;
+		}
+		if (n > 2 && (long)dest & 2) {
+			short *sdest = dest;
+			const short *ssrc = src;
+			*sdest++ = *ssrc++;
+			dest = sdest;
+			src = ssrc;
+			n -= 2;
+		}
+		temp = n >> 2;
+		if (temp) {
+			long *ldest = dest;
+			const long *lsrc = src;
+			temp--;
+			do
+				*ldest++ = *lsrc++;
+			while (temp--);
+			dest = ldest;
+			src = lsrc;
+		}
+		if (n & 2) {
+			short *sdest = dest;
+			const short *ssrc = src;
+			*sdest++ = *ssrc++;
+			dest = sdest;
+			src = ssrc;
+		}
+		if (n & 1) {
+			char *cdest = dest;
+			const char *csrc = src;
+			*cdest = *csrc;
+		}
+	} else {
+		dest = (char *)dest + n;
+		src = (const char *)src + n;
+		if ((long)dest & 1) {
+			char *cdest = dest;
+			const char *csrc = src;
+			*--cdest = *--csrc;
+			dest = cdest;
+			src = csrc;
+			n--;
+		}
+		if (n > 2 && (long)dest & 2) {
+			short *sdest = dest;
+			const short *ssrc = src;
+			*--sdest = *--ssrc;
+			dest = sdest;
+			src = ssrc;
+			n -= 2;
+		}
+		temp = n >> 2;
+		if (temp) {
+			long *ldest = dest;
+			const long *lsrc = src;
+			temp--;
+			do
+				*--ldest = *--lsrc;
+			while (temp--);
+			dest = ldest;
+			src = lsrc;
+		}
+		if (n & 2) {
+			short *sdest = dest;
+			const short *ssrc = src;
+			*--sdest = *--ssrc;
+			dest = sdest;
+			src = ssrc;
+		}
+		if (n & 1) {
+			char *cdest = dest;
+			const char *csrc = src;
+			*--cdest = *--csrc;
+		}
+	}
+	return xdest;
+}
+EXPORT_SYMBOL(memmove);
diff -druNp linux-libre-2.6.37-gnu1/arch/m68knommu/Makefile linux-libre-2.6.38-gnu1/arch/m68knommu/Makefile
--- linux-libre-2.6.37-gnu1/arch/m68knommu/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/m68knommu/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -25,7 +25,7 @@ platform-$(CONFIG_M528x)	:= 528x
 platform-$(CONFIG_M5307)	:= 5307
 platform-$(CONFIG_M532x)	:= 532x
 platform-$(CONFIG_M5407)	:= 5407
-platform-$(CONFIG_M548x)	:= 548x
+platform-$(CONFIG_M54xx)	:= 54xx
 PLATFORM := $(platform-y)
 
 board-$(CONFIG_PILOT)		:= pilot
@@ -74,7 +74,7 @@ cpuclass-$(CONFIG_M528x)	:= coldfire
 cpuclass-$(CONFIG_M5307)	:= coldfire
 cpuclass-$(CONFIG_M532x)	:= coldfire
 cpuclass-$(CONFIG_M5407)	:= coldfire
-cpuclass-$(CONFIG_M548x)	:= coldfire
+cpuclass-$(CONFIG_M54xx)	:= coldfire
 cpuclass-$(CONFIG_M68328)	:= 68328
 cpuclass-$(CONFIG_M68EZ328)	:= 68328
 cpuclass-$(CONFIG_M68VZ328)	:= 68328
@@ -91,18 +91,18 @@ 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,-m5206e,-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,-m528x,-m5307)
-cflags-$(CONFIG_M5307)		:= $(call cc-option,-m5307,-m5200)
+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,-m5407,-m5200)
-cflags-$(CONFIG_M548x)		:= $(call cc-option,-m5407,-m5200)
+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
diff -druNp linux-libre-2.6.37-gnu1/arch/m68knommu/mm/fault.c linux-libre-2.6.38-gnu1/arch/m68knommu/mm/fault.c
--- linux-libre-2.6.37-gnu1/arch/m68knommu/mm/fault.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/m68knommu/mm/fault.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,57 +0,0 @@
-/*
- *  linux/arch/m68knommu/mm/fault.c
- *
- *  Copyright (C) 1998  D. Jeff Dionne <jeff@lineo.ca>,
- *  Copyright (C) 2000  Lineo, Inc.  (www.lineo.com)
- *
- *  Based on:
- *
- *  linux/arch/m68k/mm/fault.c
- *
- *  Copyright (C) 1995  Hamish Macdonald
- */
-
-#include <linux/mman.h>
-#include <linux/mm.h>
-#include <linux/kernel.h>
-#include <linux/ptrace.h>
-
-#include <asm/system.h>
-#include <asm/pgtable.h>
-
-extern void die_if_kernel(char *, struct pt_regs *, long);
-
-/*
- * This routine handles page faults.  It determines the problem, and
- * then passes it off to one of the appropriate routines.
- *
- * error_code:
- *	bit 0 == 0 means no page found, 1 means protection fault
- *	bit 1 == 0 means read, 1 means write
- *
- * If this routine detects a bad access, it returns 1, otherwise it
- * returns 0.
- */
-asmlinkage int do_page_fault(struct pt_regs *regs, unsigned long address,
-			      unsigned long error_code)
-{
-#ifdef DEBUG
-	printk(KERN_DEBUG "regs->sr=%#x, regs->pc=%#lx, address=%#lx, %ld\n",
-		regs->sr, regs->pc, address, error_code);
-#endif
-
-	/*
-	 * Oops. The kernel tried to access some bad page. We'll have to
-	 * terminate things with extreme prejudice.
-	 */
-	if ((unsigned long) address < PAGE_SIZE)
-		printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference");
-	else
-		printk(KERN_ALERT "Unable to handle kernel access");
-	printk(KERN_ALERT " at virtual address %08lx\n", address);
-	die_if_kernel("Oops", regs, error_code);
-	do_exit(SIGKILL);
-
-	return 1;
-}
-
diff -druNp linux-libre-2.6.37-gnu1/arch/m68knommu/mm/kmap.c linux-libre-2.6.38-gnu1/arch/m68knommu/mm/kmap.c
--- linux-libre-2.6.37-gnu1/arch/m68knommu/mm/kmap.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/m68knommu/mm/kmap.c	2011-03-14 21:20:32.000000000 -0400
@@ -36,15 +36,6 @@ void iounmap(void *addr)
 }
 
 /*
- * __iounmap unmaps nearly everything, so be careful
- * it doesn't free currently pointer/page tables anymore but it
- * wans't used anyway and might be added later.
- */
-void __iounmap(void *addr, unsigned long size)
-{
-}
-
-/*
  * Set new cache mode for some kernel address space.
  * The caller must push data for that range itself, if such data may already
  * be in the cache.
diff -druNp linux-libre-2.6.37-gnu1/arch/m68knommu/mm/Makefile linux-libre-2.6.38-gnu1/arch/m68knommu/mm/Makefile
--- linux-libre-2.6.37-gnu1/arch/m68knommu/mm/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/m68knommu/mm/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -2,4 +2,4 @@
 # Makefile for the linux m68knommu specific parts of the memory manager.
 #
 
-obj-y += init.o fault.o memory.o kmap.o
+obj-y += init.o kmap.o
diff -druNp linux-libre-2.6.37-gnu1/arch/m68knommu/mm/memory.c linux-libre-2.6.38-gnu1/arch/m68knommu/mm/memory.c
--- linux-libre-2.6.37-gnu1/arch/m68knommu/mm/memory.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/m68knommu/mm/memory.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,33 +0,0 @@
-/*
- *  linux/arch/m68knommu/mm/memory.c
- *
- *  Copyright (C) 1998  Kenneth Albanowski <kjahds@kjahds.com>,
- *  Copyright (C) 1999-2002, Greg Ungerer (gerg@snapgear.com)
- *
- *  Based on:
- *
- *  linux/arch/m68k/mm/memory.c
- *
- *  Copyright (C) 1995  Hamish Macdonald
- */
-
-#include <linux/mm.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/types.h>
-
-#include <asm/segment.h>
-#include <asm/page.h>
-#include <asm/pgtable.h>
-#include <asm/system.h>
-
-/*
- * Map some physical address range into the kernel address space.
- */
-
-unsigned long kernel_map(unsigned long paddr, unsigned long size,
-			 int nocacheflag, unsigned long *memavailp )
-{
-	return paddr;
-}
-
diff -druNp linux-libre-2.6.37-gnu1/arch/m68knommu/platform/5249/intc2.c linux-libre-2.6.38-gnu1/arch/m68knommu/platform/5249/intc2.c
--- linux-libre-2.6.37-gnu1/arch/m68knommu/platform/5249/intc2.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/m68knommu/platform/5249/intc2.c	2011-03-14 21:20:32.000000000 -0400
@@ -50,8 +50,10 @@ static int __init mcf_intc2_init(void)
 	int irq;
 
 	/* GPIO interrupt sources */
-	for (irq = MCFINTC2_GPIOIRQ0; (irq <= MCFINTC2_GPIOIRQ7); irq++)
+	for (irq = MCFINTC2_GPIOIRQ0; (irq <= MCFINTC2_GPIOIRQ7); irq++) {
 		irq_desc[irq].chip = &intc2_irq_gpio_chip;
+		set_irq_handler(irq, handle_edge_irq);
+	}
 
 	return 0;
 }
diff -druNp linux-libre-2.6.37-gnu1/arch/m68knommu/platform/548x/config.c linux-libre-2.6.38-gnu1/arch/m68knommu/platform/548x/config.c
--- linux-libre-2.6.37-gnu1/arch/m68knommu/platform/548x/config.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/m68knommu/platform/548x/config.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,115 +0,0 @@
-/***************************************************************************/
-
-/*
- *	linux/arch/m68knommu/platform/548x/config.c
- *
- *	Copyright (C) 2010, Philippe De Muyter <phdm@macqel.be>
- */
-
-/***************************************************************************/
-
-#include <linux/kernel.h>
-#include <linux/param.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <asm/machdep.h>
-#include <asm/coldfire.h>
-#include <asm/m548xsim.h>
-#include <asm/mcfuart.h>
-#include <asm/m548xgpt.h>
-
-/***************************************************************************/
-
-static struct mcf_platform_uart m548x_uart_platform[] = {
-	{
-		.mapbase	= MCF_MBAR + MCFUART_BASE1,
-		.irq		= 64 + 35,
-	},
-	{
-		.mapbase	= MCF_MBAR + MCFUART_BASE2,
-		.irq		= 64 + 34,
-	},
-	{
-		.mapbase	= MCF_MBAR + MCFUART_BASE3,
-		.irq		= 64 + 33,
-	},
-	{
-		.mapbase	= MCF_MBAR + MCFUART_BASE4,
-		.irq		= 64 + 32,
-	},
-};
-
-static struct platform_device m548x_uart = {
-	.name			= "mcfuart",
-	.id			= 0,
-	.dev.platform_data	= m548x_uart_platform,
-};
-
-static struct platform_device *m548x_devices[] __initdata = {
-	&m548x_uart,
-};
-
-
-/***************************************************************************/
-
-static void __init m548x_uart_init_line(int line, int irq)
-{
-	int rts_cts;
-
-	/* enable io pins */
-	switch (line) {
-	case 0:
-		rts_cts = 0; break;
-	case 1:
-		rts_cts = MCF_PAR_PSC_RTS_RTS; break;
-	case 2:
-		rts_cts = MCF_PAR_PSC_RTS_RTS | MCF_PAR_PSC_CTS_CTS; break;
-	case 3:
-		rts_cts = 0; break;
-	}
-	__raw_writeb(MCF_PAR_PSC_TXD | rts_cts | MCF_PAR_PSC_RXD,
-						MCF_MBAR + MCF_PAR_PSC(line));
-}
-
-static void __init m548x_uarts_init(void)
-{
-	const int nrlines = ARRAY_SIZE(m548x_uart_platform);
-	int line;
-
-	for (line = 0; (line < nrlines); line++)
-		m548x_uart_init_line(line, m548x_uart_platform[line].irq);
-}
-
-/***************************************************************************/
-
-static void mcf548x_reset(void)
-{
-	/* disable interrupts and enable the watchdog */
-	asm("movew #0x2700, %sr\n");
-	__raw_writel(0, MCF_MBAR + MCF_GPT_GMS0);
-	__raw_writel(MCF_GPT_GCIR_CNT(1), MCF_MBAR + MCF_GPT_GCIR0);
-	__raw_writel(MCF_GPT_GMS_WDEN | MCF_GPT_GMS_CE | MCF_GPT_GMS_TMS(4),
-						MCF_MBAR + MCF_GPT_GMS0);
-}
-
-/***************************************************************************/
-
-void __init config_BSP(char *commandp, int size)
-{
-	mach_reset = mcf548x_reset;
-	m548x_uarts_init();
-}
-
-/***************************************************************************/
-
-static int __init init_BSP(void)
-{
-
-	platform_add_devices(m548x_devices, ARRAY_SIZE(m548x_devices));
-	return 0;
-}
-
-arch_initcall(init_BSP);
-
-/***************************************************************************/
diff -druNp linux-libre-2.6.37-gnu1/arch/m68knommu/platform/548x/Makefile linux-libre-2.6.38-gnu1/arch/m68knommu/platform/548x/Makefile
--- linux-libre-2.6.37-gnu1/arch/m68knommu/platform/548x/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/m68knommu/platform/548x/Makefile	1969-12-31 19:00:00.000000000 -0500
@@ -1,18 +0,0 @@
-#
-# Makefile for the m68knommu linux kernel.
-#
-
-#
-# If you want to play with the HW breakpoints then you will
-# need to add define this,  which will give you a stack backtrace
-# on the console port whenever a DBG interrupt occurs. You have to
-# set up you HW breakpoints to trigger a DBG interrupt:
-#
-# EXTRA_CFLAGS += -DTRAP_DBG_INTERRUPT
-# EXTRA_AFLAGS += -DTRAP_DBG_INTERRUPT
-#
-
-asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1
-
-obj-y := config.o
-
diff -druNp linux-libre-2.6.37-gnu1/arch/m68knommu/platform/54xx/config.c linux-libre-2.6.38-gnu1/arch/m68knommu/platform/54xx/config.c
--- linux-libre-2.6.37-gnu1/arch/m68knommu/platform/54xx/config.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/m68knommu/platform/54xx/config.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,115 @@
+/***************************************************************************/
+
+/*
+ *	linux/arch/m68knommu/platform/54xx/config.c
+ *
+ *	Copyright (C) 2010, Philippe De Muyter <phdm@macqel.be>
+ */
+
+/***************************************************************************/
+
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <asm/machdep.h>
+#include <asm/coldfire.h>
+#include <asm/m54xxsim.h>
+#include <asm/mcfuart.h>
+#include <asm/m54xxgpt.h>
+
+/***************************************************************************/
+
+static struct mcf_platform_uart m54xx_uart_platform[] = {
+	{
+		.mapbase	= MCF_MBAR + MCFUART_BASE1,
+		.irq		= 64 + 35,
+	},
+	{
+		.mapbase	= MCF_MBAR + MCFUART_BASE2,
+		.irq		= 64 + 34,
+	},
+	{
+		.mapbase	= MCF_MBAR + MCFUART_BASE3,
+		.irq		= 64 + 33,
+	},
+	{
+		.mapbase	= MCF_MBAR + MCFUART_BASE4,
+		.irq		= 64 + 32,
+	},
+};
+
+static struct platform_device m54xx_uart = {
+	.name			= "mcfuart",
+	.id			= 0,
+	.dev.platform_data	= m54xx_uart_platform,
+};
+
+static struct platform_device *m54xx_devices[] __initdata = {
+	&m54xx_uart,
+};
+
+
+/***************************************************************************/
+
+static void __init m54xx_uart_init_line(int line, int irq)
+{
+	int rts_cts;
+
+	/* enable io pins */
+	switch (line) {
+	case 0:
+		rts_cts = 0; break;
+	case 1:
+		rts_cts = MCF_PAR_PSC_RTS_RTS; break;
+	case 2:
+		rts_cts = MCF_PAR_PSC_RTS_RTS | MCF_PAR_PSC_CTS_CTS; break;
+	case 3:
+		rts_cts = 0; break;
+	}
+	__raw_writeb(MCF_PAR_PSC_TXD | rts_cts | MCF_PAR_PSC_RXD,
+						MCF_MBAR + MCF_PAR_PSC(line));
+}
+
+static void __init m54xx_uarts_init(void)
+{
+	const int nrlines = ARRAY_SIZE(m54xx_uart_platform);
+	int line;
+
+	for (line = 0; (line < nrlines); line++)
+		m54xx_uart_init_line(line, m54xx_uart_platform[line].irq);
+}
+
+/***************************************************************************/
+
+static void mcf54xx_reset(void)
+{
+	/* disable interrupts and enable the watchdog */
+	asm("movew #0x2700, %sr\n");
+	__raw_writel(0, MCF_MBAR + MCF_GPT_GMS0);
+	__raw_writel(MCF_GPT_GCIR_CNT(1), MCF_MBAR + MCF_GPT_GCIR0);
+	__raw_writel(MCF_GPT_GMS_WDEN | MCF_GPT_GMS_CE | MCF_GPT_GMS_TMS(4),
+						MCF_MBAR + MCF_GPT_GMS0);
+}
+
+/***************************************************************************/
+
+void __init config_BSP(char *commandp, int size)
+{
+	mach_reset = mcf54xx_reset;
+	m54xx_uarts_init();
+}
+
+/***************************************************************************/
+
+static int __init init_BSP(void)
+{
+
+	platform_add_devices(m54xx_devices, ARRAY_SIZE(m54xx_devices));
+	return 0;
+}
+
+arch_initcall(init_BSP);
+
+/***************************************************************************/
diff -druNp linux-libre-2.6.37-gnu1/arch/m68knommu/platform/54xx/Makefile linux-libre-2.6.38-gnu1/arch/m68knommu/platform/54xx/Makefile
--- linux-libre-2.6.37-gnu1/arch/m68knommu/platform/54xx/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/m68knommu/platform/54xx/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,18 @@
+#
+# Makefile for the m68knommu linux kernel.
+#
+
+#
+# If you want to play with the HW breakpoints then you will
+# need to add define this,  which will give you a stack backtrace
+# on the console port whenever a DBG interrupt occurs. You have to
+# set up you HW breakpoints to trigger a DBG interrupt:
+#
+# EXTRA_CFLAGS += -DTRAP_DBG_INTERRUPT
+# EXTRA_AFLAGS += -DTRAP_DBG_INTERRUPT
+#
+
+asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1
+
+obj-y := config.o
+
diff -druNp linux-libre-2.6.37-gnu1/arch/m68knommu/platform/68328/entry.S linux-libre-2.6.38-gnu1/arch/m68knommu/platform/68328/entry.S
--- linux-libre-2.6.37-gnu1/arch/m68knommu/platform/68328/entry.S	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/m68knommu/platform/68328/entry.S	2011-03-14 21:20:32.000000000 -0400
@@ -106,8 +106,8 @@ Luser_return:
 	movel	%sp,%d1			/* get thread_info pointer */
 	andl	#-THREAD_SIZE,%d1
 	movel	%d1,%a2
+1:
 	move	%a2@(TI_FLAGS),%d1	/* thread_info->flags */
-	andl	#_TIF_WORK_MASK,%d1
 	jne	Lwork_to_do
 	RESTORE_ALL
 
@@ -120,13 +120,11 @@ Lsignal_return:
 	subql	#4,%sp			/* dummy return address*/
 	SAVE_SWITCH_STACK
 	pea	%sp@(SWITCH_STACK_SIZE)
-	clrl	%sp@-
 	bsrw	do_signal
-	addql	#8,%sp
+	addql	#4,%sp
 	RESTORE_SWITCH_STACK
 	addql	#4,%sp
-Lreturn:
-	RESTORE_ALL
+	jra	1b
 
 /*
  * This is the main interrupt handler, responsible for calling process_int()
diff -druNp linux-libre-2.6.37-gnu1/arch/m68knommu/platform/68328/ints.c linux-libre-2.6.38-gnu1/arch/m68knommu/platform/68328/ints.c
--- linux-libre-2.6.37-gnu1/arch/m68knommu/platform/68328/ints.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/m68knommu/platform/68328/ints.c	2011-03-14 21:20:32.000000000 -0400
@@ -179,8 +179,8 @@ void __init init_IRQ(void)
 	IMR = ~0;
 
 	for (i = 0; (i < NR_IRQS); i++) {
-		set_irq_chip(irq, &intc_irq_chip);
-		set_irq_handler(irq, handle_level_irq);
+		set_irq_chip(i, &intc_irq_chip);
+		set_irq_handler(i, handle_level_irq);
 	}
 }
 
diff -druNp linux-libre-2.6.37-gnu1/arch/m68knommu/platform/68360/commproc.c linux-libre-2.6.38-gnu1/arch/m68knommu/platform/68360/commproc.c
--- linux-libre-2.6.37-gnu1/arch/m68knommu/platform/68360/commproc.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/m68knommu/platform/68360/commproc.c	2011-03-14 21:20:32.000000000 -0400
@@ -210,7 +210,7 @@ void
 cpm_install_handler(int vec, void (*handler)(), void *dev_id)
 {
 
-	request_irq(vec, handler, IRQ_FLG_LOCK, "timer", dev_id);
+	request_irq(vec, handler, 0, "timer", dev_id);
 
 /* 	if (cpm_vecs[vec].handler != 0) */
 /* 		printk(KERN_INFO "CPM interrupt %x replacing %x\n", */
diff -druNp linux-libre-2.6.37-gnu1/arch/m68knommu/platform/68360/config.c linux-libre-2.6.38-gnu1/arch/m68knommu/platform/68360/config.c
--- linux-libre-2.6.37-gnu1/arch/m68knommu/platform/68360/config.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/m68knommu/platform/68360/config.c	2011-03-14 21:20:32.000000000 -0400
@@ -75,7 +75,7 @@ void hw_timer_init(void)
   /* Set compare register  32Khz / 32 / 10 = 100 */
   TCMP = 10;                                                              
 
-  request_irq(IRQ_MACHSPEC | 1, timer_routine, IRQ_FLG_LOCK, "timer", NULL);
+  request_irq(IRQ_MACHSPEC | 1, timer_routine, 0, "timer", NULL);
 #endif
 
   /* General purpose quicc timers: MC68360UM p7-20 */
diff -druNp linux-libre-2.6.37-gnu1/arch/m68knommu/platform/68360/entry.S linux-libre-2.6.38-gnu1/arch/m68knommu/platform/68360/entry.S
--- linux-libre-2.6.37-gnu1/arch/m68knommu/platform/68360/entry.S	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/m68knommu/platform/68360/entry.S	2011-03-14 21:20:32.000000000 -0400
@@ -102,8 +102,8 @@ Luser_return:
 	movel	%sp,%d1			/* get thread_info pointer */
 	andl	#-THREAD_SIZE,%d1
 	movel	%d1,%a2
+1:
 	move	%a2@(TI_FLAGS),%d1	/* thread_info->flags */
-	andl	#_TIF_WORK_MASK,%d1
 	jne	Lwork_to_do
 	RESTORE_ALL
 
@@ -116,13 +116,11 @@ Lsignal_return:
 	subql	#4,%sp			/* dummy return address*/
 	SAVE_SWITCH_STACK
 	pea	%sp@(SWITCH_STACK_SIZE)
-	clrl	%sp@-
 	bsrw	do_signal
-	addql	#8,%sp
+	addql	#4,%sp
 	RESTORE_SWITCH_STACK
 	addql	#4,%sp
-Lreturn:
-	RESTORE_ALL
+	jra	1b
 
 /*
  * This is the main interrupt handler, responsible for calling do_IRQ()
diff -druNp linux-libre-2.6.37-gnu1/arch/m68knommu/platform/68360/ints.c linux-libre-2.6.38-gnu1/arch/m68knommu/platform/68360/ints.c
--- linux-libre-2.6.37-gnu1/arch/m68knommu/platform/68360/ints.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/m68knommu/platform/68360/ints.c	2011-03-14 21:20:32.000000000 -0400
@@ -132,8 +132,8 @@ void init_IRQ(void)
 	pquicc->intr_cimr = 0x00000000;
 
 	for (i = 0; (i < NR_IRQS); i++) {
-		set_irq_chip(irq, &intc_irq_chip);
-		set_irq_handler(irq, handle_level_irq);
+		set_irq_chip(i, &intc_irq_chip);
+		set_irq_handler(i, handle_level_irq);
 	}
 }
 
diff -druNp linux-libre-2.6.37-gnu1/arch/m68knommu/platform/coldfire/cache.c linux-libre-2.6.38-gnu1/arch/m68knommu/platform/coldfire/cache.c
--- linux-libre-2.6.37-gnu1/arch/m68knommu/platform/coldfire/cache.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/m68knommu/platform/coldfire/cache.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,48 @@
+/***************************************************************************/
+
+/*
+ *	cache.c -- general ColdFire Cache maintainence code
+ *
+ *	Copyright (C) 2010, Greg Ungerer (gerg@snapgear.com)
+ */
+
+/***************************************************************************/
+
+#include <linux/kernel.h>
+#include <asm/coldfire.h>
+#include <asm/mcfsim.h>
+
+/***************************************************************************/
+#ifdef CACHE_PUSH
+/***************************************************************************/
+
+/*
+ *	Use cpushl to push all dirty cache lines back to memory.
+ *	Older versions of GAS don't seem to know how to generate the
+ *	ColdFire cpushl instruction... Oh well, bit stuff it for now.
+ */
+
+void mcf_cache_push(void)
+{
+	__asm__ __volatile__ (
+		"clrl	%%d0\n\t"
+		"1:\n\t"
+		"movel	%%d0,%%a0\n\t"
+		"2:\n\t"
+		".word	0xf468\n\t"
+		"addl	%0,%%a0\n\t"
+		"cmpl	%1,%%a0\n\t"
+		"blt	2b\n\t"
+		"addql	#1,%%d0\n\t"
+		"cmpil	%2,%%d0\n\t"
+		"bne	1b\n\t"
+		: /* No output */
+		: "i" (CACHE_LINE_SIZE),
+		  "i" (DCACHE_SIZE / CACHE_WAYS),
+		  "i" (CACHE_WAYS)
+		: "d0", "a0" );
+}
+
+/***************************************************************************/
+#endif /* CACHE_PUSH */
+/***************************************************************************/
diff -druNp linux-libre-2.6.37-gnu1/arch/m68knommu/platform/coldfire/entry.S linux-libre-2.6.38-gnu1/arch/m68knommu/platform/coldfire/entry.S
--- linux-libre-2.6.37-gnu1/arch/m68knommu/platform/coldfire/entry.S	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/m68knommu/platform/coldfire/entry.S	2011-03-14 21:20:32.000000000 -0400
@@ -36,13 +36,16 @@
 #include <asm/asm-offsets.h>
 #include <asm/entry.h>
 
+#ifdef CONFIG_COLDFIRE_SW_A7
+/*
+ *	Define software copies of the supervisor and user stack pointers.
+ */
 .bss
-
 sw_ksp:
 .long	0
-
 sw_usp:
 .long	0
+#endif /* CONFIG_COLDFIRE_SW_A7 */
 
 .text
 
@@ -51,7 +54,6 @@ sw_usp:
 .globl ret_from_exception
 .globl ret_from_signal
 .globl sys_call_table
-.globl ret_from_interrupt
 .globl inthandler
 .globl fasthandler
 
@@ -136,24 +138,10 @@ Luser_return:
 	andl	#-THREAD_SIZE,%d1	/* at base of kernel stack */
 	movel	%d1,%a0
 	movel	%a0@(TI_FLAGS),%d1	/* get thread_info->flags */
-	andl	#0xefff,%d1
 	jne	Lwork_to_do		/* still work to do */
 
 Lreturn:
-	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		/* stk adj */
-	addql	#8,%sp			/* remove exception */
-	movel	%sp,sw_ksp		/* save ksp */
-	subql	#8,sw_usp		/* set exception */
-	movel	sw_usp,%sp		/* restore usp */
-	rte
+	RESTORE_USER
 
 Lwork_to_do:
 	movel	%a0@(TI_FLAGS),%d1	/* get thread_info->flags */
@@ -167,12 +155,11 @@ Lsignal_return:
 	subql	#4,%sp			/* dummy return address */
 	SAVE_SWITCH_STACK
 	pea	%sp@(SWITCH_STACK_SIZE)
-	clrl	%sp@-
 	jsr	do_signal
-	addql	#8,%sp
+	addql	#4,%sp
 	RESTORE_SWITCH_STACK
 	addql	#4,%sp
-	jmp	Lreturn
+	jmp	Luser_return
 
 /*
  * This is the generic interrupt handler (for all hardware interrupt
@@ -192,31 +179,7 @@ ENTRY(inthandler)
 	jbsr	do_IRQ			/* call high level irq handler */
 	lea	%sp@(8),%sp		/* pop args off stack */
 
-	bra	ret_from_interrupt	/* this was fallthrough */
-
-/*
- * This is the fast interrupt handler (for certain hardware interrupt
- * sources). Unlike the normal interrupt handler it just uses the
- * current stack (doesn't care if it is user or kernel). It also
- * doesn't bother doing the bottom half handlers.
- */
-ENTRY(fasthandler)
-	SAVE_LOCAL
-
-	movew	%sp@(PT_OFF_FORMATVEC),%d0
-	andl	#0x03fc,%d0		/* mask out vector only */
-
-	movel	%sp,%sp@-		/* push regs arg */
-	lsrl	#2,%d0			/* calculate real vector # */
-	movel	%d0,%sp@-		/* push vector number */
-	jbsr	do_IRQ			/* call high level irq handler */
-	lea	%sp@(8),%sp		/* pop args off stack */
-
-	RESTORE_LOCAL
-
-ENTRY(ret_from_interrupt)
-	/* the fasthandler is confusing me, haven't seen any user */
-	jmp	ret_from_exception
+	bra	ret_from_exception
 
 /*
  * Beware - when entering resume, prev (the current task) is
@@ -227,9 +190,8 @@ ENTRY(ret_from_interrupt)
  */
 ENTRY(resume)
 	movel	%a0, %d1			/* get prev thread in d1 */
-
-	movel	sw_usp,%d0			/* save usp */
-	movel	%d0,%a0@(TASK_THREAD+THREAD_USP)
+	RDUSP
+	movel	%a2,%a0@(TASK_THREAD+THREAD_USP)
 
 	SAVE_SWITCH_STACK
 	movel	%sp,%a0@(TASK_THREAD+THREAD_KSP) /* save kernel stack pointer */
@@ -237,5 +199,5 @@ ENTRY(resume)
 	RESTORE_SWITCH_STACK
 
 	movel	%a1@(TASK_THREAD+THREAD_USP),%a0 /* restore thread user stack */
-	movel	%a0, sw_usp
+	WRUSP
 	rts
diff -druNp linux-libre-2.6.37-gnu1/arch/m68knommu/platform/coldfire/head.S linux-libre-2.6.38-gnu1/arch/m68knommu/platform/coldfire/head.S
--- linux-libre-2.6.37-gnu1/arch/m68knommu/platform/coldfire/head.S	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/m68knommu/platform/coldfire/head.S	2011-03-14 21:20:32.000000000 -0400
@@ -3,7 +3,7 @@
 /*
  *	head.S -- common startup code for ColdFire CPUs.
  *
- *	(C) Copyright 1999-2006, Greg Ungerer <gerg@snapgear.com>.
+ *	(C) Copyright 1999-2010, Greg Ungerer <gerg@snapgear.com>.
  */
 
 /*****************************************************************************/
@@ -13,7 +13,6 @@
 #include <linux/init.h>
 #include <asm/asm-offsets.h>
 #include <asm/coldfire.h>
-#include <asm/mcfcache.h>
 #include <asm/mcfsim.h>
 #include <asm/thread_info.h>
 
@@ -173,10 +172,27 @@ _start:
 
 	/*
 	 *	Now that we know what the memory is, lets enable cache
-	 *	and get things moving. This is Coldfire CPU specific.
+	 *	and get things moving. This is Coldfire CPU specific. Not
+	 *	all version cores have identical cache register setup. But
+	 *	it is very similar. Define the exact settings in the headers
+	 *	then the code here is the same for all.
 	 */
-	CACHE_ENABLE				/* enable CPU cache */
-
+	movel	#CACHE_INIT,%d0			/* invalidate whole cache */
+	movec	%d0,%CACR
+	nop
+	movel	#ACR0_MODE,%d0			/* set RAM region for caching */
+	movec	%d0,%ACR0
+	movel	#ACR1_MODE,%d0			/* anything else to cache? */
+	movec	%d0,%ACR1
+#ifdef ACR2_MODE
+	movel	#ACR2_MODE,%d0
+	movec	%d0,%ACR2
+	movel	#ACR3_MODE,%d0
+	movec	%d0,%ACR3
+#endif
+	movel	#CACHE_MODE,%d0			/* enable cache */
+	movec	%d0,%CACR
+	nop
 
 #ifdef CONFIG_ROMFS_FS
 	/*
diff -druNp linux-libre-2.6.37-gnu1/arch/m68knommu/platform/coldfire/Makefile linux-libre-2.6.38-gnu1/arch/m68knommu/platform/coldfire/Makefile
--- linux-libre-2.6.37-gnu1/arch/m68knommu/platform/coldfire/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/m68knommu/platform/coldfire/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -14,7 +14,7 @@
 
 asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1
 
-obj-$(CONFIG_COLDFIRE)	+= clk.o dma.o entry.o vectors.o
+obj-$(CONFIG_COLDFIRE)	+= cache.o clk.o dma.o entry.o vectors.o
 obj-$(CONFIG_M5206)	+= timers.o intc.o
 obj-$(CONFIG_M5206e)	+= timers.o intc.o
 obj-$(CONFIG_M520x)	+= pit.o intc-simr.o
@@ -26,7 +26,7 @@ obj-$(CONFIG_M528x)	+= pit.o intc-2.o
 obj-$(CONFIG_M5307)	+= timers.o intc.o
 obj-$(CONFIG_M532x)	+= timers.o intc-simr.o
 obj-$(CONFIG_M5407)	+= timers.o intc.o
-obj-$(CONFIG_M548x)	+= sltimers.o intc-2.o
+obj-$(CONFIG_M54xx)	+= sltimers.o intc-2.o
 
 obj-y			+= pinmux.o gpio.o
 extra-y := head.o
diff -druNp linux-libre-2.6.37-gnu1/arch/microblaze/boot/Makefile linux-libre-2.6.38-gnu1/arch/microblaze/boot/Makefile
--- linux-libre-2.6.37-gnu1/arch/microblaze/boot/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/microblaze/boot/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -10,9 +10,6 @@ targets := linux.bin linux.bin.gz simple
 
 OBJCOPYFLAGS := -O binary
 
-# Where the DTS files live
-dtstree         := $(srctree)/$(src)/dts
-
 # Ensure system.dtb exists
 $(obj)/linked_dtb.o: $(obj)/system.dtb
 
@@ -51,14 +48,11 @@ $(obj)/simpleImage.%: vmlinux FORCE
 	$(call if_changed,strip)
 	@echo 'Kernel: $@ is ready' ' (#'`cat .version`')'
 
-# Rule to build device tree blobs
-DTC = $(objtree)/scripts/dtc/dtc
 
 # Rule to build device tree blobs
-quiet_cmd_dtc = DTC     $@
-	cmd_dtc = $(DTC) -O dtb -o $(obj)/$*.dtb -b 0 -p 1024 $(dtstree)/$*.dts
+DTC_FLAGS := -p 1024
 
-$(obj)/%.dtb: $(dtstree)/%.dts FORCE
-	$(call if_changed,dtc)
+$(obj)/%.dtb: $(src)/dts/%.dts FORCE
+	$(call cmd,dtc)
 
 clean-files += *.dtb simpleImage.*.unstrip linux.bin.ub
diff -druNp linux-libre-2.6.37-gnu1/arch/microblaze/configs/mmu_defconfig linux-libre-2.6.38-gnu1/arch/microblaze/configs/mmu_defconfig
--- linux-libre-2.6.37-gnu1/arch/microblaze/configs/mmu_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/microblaze/configs/mmu_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -7,7 +7,7 @@ CONFIG_BLK_DEV_INITRD=y
 CONFIG_INITRAMFS_SOURCE="rootfs.cpio"
 CONFIG_INITRAMFS_COMPRESSION_GZIP=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 CONFIG_KALLSYMS_ALL=y
 CONFIG_KALLSYMS_EXTRA_PASS=y
 # CONFIG_HOTPLUG is not set
@@ -66,5 +66,4 @@ CONFIG_DEBUG_SPINLOCK=y
 CONFIG_DEBUG_INFO=y
 # CONFIG_RCU_CPU_STALL_DETECTOR is not set
 CONFIG_EARLY_PRINTK=y
-CONFIG_DEBUG_BOOTMEM=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/microblaze/configs/nommu_defconfig linux-libre-2.6.38-gnu1/arch/microblaze/configs/nommu_defconfig
--- linux-libre-2.6.37-gnu1/arch/microblaze/configs/nommu_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/microblaze/configs/nommu_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -6,7 +6,7 @@ CONFIG_BSD_PROCESS_ACCT_V3=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 CONFIG_KALLSYMS_ALL=y
 CONFIG_KALLSYMS_EXTRA_PASS=y
 # CONFIG_HOTPLUG is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/microblaze/include/asm/irqflags.h linux-libre-2.6.38-gnu1/arch/microblaze/include/asm/irqflags.h
--- linux-libre-2.6.37-gnu1/arch/microblaze/include/asm/irqflags.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/microblaze/include/asm/irqflags.h	2011-03-14 21:20:32.000000000 -0400
@@ -12,7 +12,7 @@
 #include <linux/types.h>
 #include <asm/registers.h>
 
-#ifdef CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR
+#if CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR
 
 static inline unsigned long arch_local_irq_save(void)
 {
diff -druNp linux-libre-2.6.37-gnu1/arch/microblaze/include/asm/pgtable.h linux-libre-2.6.38-gnu1/arch/microblaze/include/asm/pgtable.h
--- linux-libre-2.6.37-gnu1/arch/microblaze/include/asm/pgtable.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/microblaze/include/asm/pgtable.h	2011-03-14 21:20:32.000000000 -0400
@@ -411,20 +411,19 @@ static inline pte_t pte_modify(pte_t pte
 static inline unsigned long pte_update(pte_t *p, unsigned long clr,
 				unsigned long set)
 {
-	unsigned long old, tmp, msr;
+	unsigned long flags, old, tmp;
 
-	__asm__ __volatile__("\
-	msrclr	%2, 0x2\n\
-	nop\n\
-	lw	%0, %4, r0\n\
-	andn	%1, %0, %5\n\
-	or	%1, %1, %6\n\
-	sw	%1, %4, r0\n\
-	mts     rmsr, %2\n\
-	nop"
-	: "=&r" (old), "=&r" (tmp), "=&r" (msr), "=m" (*p)
-	: "r" ((unsigned long)(p + 1) - 4), "r" (clr), "r" (set), "m" (*p)
-	: "cc");
+	raw_local_irq_save(flags);
+
+	__asm__ __volatile__(	"lw	%0, %2, r0	\n"
+				"andn	%1, %0, %3	\n"
+				"or	%1, %1, %4	\n"
+				"sw	%1, %2, r0	\n"
+			: "=&r" (old), "=&r" (tmp)
+			: "r" ((unsigned long)(p + 1) - 4), "r" (clr), "r" (set)
+			: "cc");
+
+	raw_local_irq_restore(flags);
 
 	return old;
 }
@@ -444,8 +443,9 @@ static inline void set_pte_at(struct mm_
 	*ptep = pte;
 }
 
-static inline int ptep_test_and_clear_young(struct mm_struct *mm,
-		unsigned long addr, pte_t *ptep)
+#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
+static inline int ptep_test_and_clear_young(struct vm_area_struct *vma,
+		unsigned long address, pte_t *ptep)
 {
 	return (pte_update(ptep, _PAGE_ACCESSED, 0) & _PAGE_ACCESSED) != 0;
 }
@@ -457,6 +457,7 @@ static inline int ptep_test_and_clear_di
 		(_PAGE_DIRTY | _PAGE_HWWRITE), 0) & _PAGE_DIRTY) != 0;
 }
 
+#define __HAVE_ARCH_PTEP_GET_AND_CLEAR
 static inline pte_t ptep_get_and_clear(struct mm_struct *mm,
 		unsigned long addr, pte_t *ptep)
 {
diff -druNp linux-libre-2.6.37-gnu1/arch/microblaze/include/asm/prom.h linux-libre-2.6.38-gnu1/arch/microblaze/include/asm/prom.h
--- linux-libre-2.6.37-gnu1/arch/microblaze/include/asm/prom.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/microblaze/include/asm/prom.h	2011-03-14 21:20:32.000000000 -0400
@@ -64,9 +64,6 @@ extern void kdump_move_device_tree(void)
 /* CPU OF node matching */
 struct device_node *of_get_cpu_node(int cpu, unsigned int *thread);
 
-/* Get the MAC address */
-extern const void *of_get_mac_address(struct device_node *np);
-
 /**
  * of_irq_map_pci - Resolve the interrupt for a PCI device
  * @pdev:	the device whose interrupt is to be resolved
diff -druNp linux-libre-2.6.37-gnu1/arch/microblaze/include/asm/pvr.h linux-libre-2.6.38-gnu1/arch/microblaze/include/asm/pvr.h
--- linux-libre-2.6.37-gnu1/arch/microblaze/include/asm/pvr.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/microblaze/include/asm/pvr.h	2011-03-14 21:20:32.000000000 -0400
@@ -1,9 +1,9 @@
 /*
  * Support for the MicroBlaze PVR (Processor Version Register)
  *
- * Copyright (C) 2009 Michal Simek <monstr@monstr.eu>
+ * Copyright (C) 2009 - 2011 Michal Simek <monstr@monstr.eu>
  * Copyright (C) 2007 John Williams <john.williams@petalogix.com>
- * Copyright (C) 2007 - 2009 PetaLogix
+ * Copyright (C) 2007 - 2011 PetaLogix
  *
  * 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
@@ -46,11 +46,11 @@ struct pvr_s {
 #define PVR2_I_LMB_MASK			0x10000000
 #define PVR2_INTERRUPT_IS_EDGE_MASK	0x08000000
 #define PVR2_EDGE_IS_POSITIVE_MASK	0x04000000
-#define PVR2_D_PLB_MASK			0x02000000	/* new */
-#define PVR2_I_PLB_MASK			0x01000000	/* new */
-#define PVR2_INTERCONNECT		0x00800000	/* new */
-#define PVR2_USE_EXTEND_FSL		0x00080000	/* new */
-#define PVR2_USE_FSL_EXC		0x00040000	/* new */
+#define PVR2_D_PLB_MASK			0x02000000 /* new */
+#define PVR2_I_PLB_MASK			0x01000000 /* new */
+#define PVR2_INTERCONNECT		0x00800000 /* new */
+#define PVR2_USE_EXTEND_FSL		0x00080000 /* new */
+#define PVR2_USE_FSL_EXC		0x00040000 /* new */
 #define PVR2_USE_MSR_INSTR		0x00020000
 #define PVR2_USE_PCMP_INSTR		0x00010000
 #define PVR2_AREA_OPTIMISED		0x00008000
@@ -59,7 +59,7 @@ struct pvr_s {
 #define PVR2_USE_HW_MUL_MASK		0x00001000
 #define PVR2_USE_FPU_MASK		0x00000800
 #define PVR2_USE_MUL64_MASK		0x00000400
-#define PVR2_USE_FPU2_MASK		0x00000200	/* new */
+#define PVR2_USE_FPU2_MASK		0x00000200 /* new */
 #define PVR2_USE_IPLBEXC 		0x00000100
 #define PVR2_USE_DPLBEXC		0x00000080
 #define PVR2_OPCODE_0x0_ILL_MASK	0x00000040
@@ -122,96 +122,103 @@ struct pvr_s {
 
 
 /* PVR access macros */
-#define PVR_IS_FULL(pvr)		(pvr.pvr[0] & PVR0_PVR_FULL_MASK)
-#define PVR_USE_BARREL(pvr)		(pvr.pvr[0] & PVR0_USE_BARREL_MASK)
-#define PVR_USE_DIV(pvr)		(pvr.pvr[0] & PVR0_USE_DIV_MASK)
-#define PVR_USE_HW_MUL(pvr)		(pvr.pvr[0] & PVR0_USE_HW_MUL_MASK)
-#define PVR_USE_FPU(pvr)		(pvr.pvr[0] & PVR0_USE_FPU_MASK)
-#define PVR_USE_FPU2(pvr)		(pvr.pvr[2] & PVR2_USE_FPU2_MASK)
-#define PVR_USE_ICACHE(pvr)		(pvr.pvr[0] & PVR0_USE_ICACHE_MASK)
-#define PVR_USE_DCACHE(pvr)		(pvr.pvr[0] & PVR0_USE_DCACHE_MASK)
-#define PVR_VERSION(pvr)	((pvr.pvr[0] & PVR0_VERSION_MASK) >> 8)
-#define PVR_USER1(pvr)			(pvr.pvr[0] & PVR0_USER1_MASK)
-#define PVR_USER2(pvr)			(pvr.pvr[1] & PVR1_USER2_MASK)
+#define PVR_IS_FULL(_pvr)	(_pvr.pvr[0] & PVR0_PVR_FULL_MASK)
+#define PVR_USE_BARREL(_pvr)	(_pvr.pvr[0] & PVR0_USE_BARREL_MASK)
+#define PVR_USE_DIV(_pvr)	(_pvr.pvr[0] & PVR0_USE_DIV_MASK)
+#define PVR_USE_HW_MUL(_pvr)	(_pvr.pvr[0] & PVR0_USE_HW_MUL_MASK)
+#define PVR_USE_FPU(_pvr)	(_pvr.pvr[0] & PVR0_USE_FPU_MASK)
+#define PVR_USE_FPU2(_pvr)	(_pvr.pvr[2] & PVR2_USE_FPU2_MASK)
+#define PVR_USE_ICACHE(_pvr)	(_pvr.pvr[0] & PVR0_USE_ICACHE_MASK)
+#define PVR_USE_DCACHE(_pvr)	(_pvr.pvr[0] & PVR0_USE_DCACHE_MASK)
+#define PVR_VERSION(_pvr)	((_pvr.pvr[0] & PVR0_VERSION_MASK) >> 8)
+#define PVR_USER1(_pvr)		(_pvr.pvr[0] & PVR0_USER1_MASK)
+#define PVR_USER2(_pvr)		(_pvr.pvr[1] & PVR1_USER2_MASK)
 
-#define PVR_D_OPB(pvr)			(pvr.pvr[2] & PVR2_D_OPB_MASK)
-#define PVR_D_LMB(pvr)			(pvr.pvr[2] & PVR2_D_LMB_MASK)
-#define PVR_I_OPB(pvr)			(pvr.pvr[2] & PVR2_I_OPB_MASK)
-#define PVR_I_LMB(pvr)			(pvr.pvr[2] & PVR2_I_LMB_MASK)
-#define PVR_INTERRUPT_IS_EDGE(pvr) \
-			(pvr.pvr[2] & PVR2_INTERRUPT_IS_EDGE_MASK)
-#define PVR_EDGE_IS_POSITIVE(pvr) \
-			(pvr.pvr[2] & PVR2_EDGE_IS_POSITIVE_MASK)
-#define PVR_USE_MSR_INSTR(pvr)		(pvr.pvr[2] & PVR2_USE_MSR_INSTR)
-#define PVR_USE_PCMP_INSTR(pvr)		(pvr.pvr[2] & PVR2_USE_PCMP_INSTR)
-#define PVR_AREA_OPTIMISED(pvr)		(pvr.pvr[2] & PVR2_AREA_OPTIMISED)
-#define PVR_USE_MUL64(pvr)		(pvr.pvr[2] & PVR2_USE_MUL64_MASK)
-#define PVR_OPCODE_0x0_ILLEGAL(pvr) \
-			(pvr.pvr[2] & PVR2_OPCODE_0x0_ILL_MASK)
-#define PVR_UNALIGNED_EXCEPTION(pvr) \
-			(pvr.pvr[2] & PVR2_UNALIGNED_EXC_MASK)
-#define PVR_ILL_OPCODE_EXCEPTION(pvr) \
-			(pvr.pvr[2] & PVR2_ILL_OPCODE_EXC_MASK)
-#define PVR_IOPB_BUS_EXCEPTION(pvr) \
-			(pvr.pvr[2] & PVR2_IOPB_BUS_EXC_MASK)
-#define PVR_DOPB_BUS_EXCEPTION(pvr) \
-			(pvr.pvr[2] & PVR2_DOPB_BUS_EXC_MASK)
-#define PVR_DIV_ZERO_EXCEPTION(pvr) \
-			(pvr.pvr[2] & PVR2_DIV_ZERO_EXC_MASK)
-#define PVR_FPU_EXCEPTION(pvr)		(pvr.pvr[2] & PVR2_FPU_EXC_MASK)
-#define PVR_FSL_EXCEPTION(pvr)		(pvr.pvr[2] & PVR2_USE_EXTEND_FSL)
+#define PVR_D_OPB(_pvr)		(_pvr.pvr[2] & PVR2_D_OPB_MASK)
+#define PVR_D_LMB(_pvr)		(_pvr.pvr[2] & PVR2_D_LMB_MASK)
+#define PVR_I_OPB(_pvr)		(_pvr.pvr[2] & PVR2_I_OPB_MASK)
+#define PVR_I_LMB(_pvr)		(_pvr.pvr[2] & PVR2_I_LMB_MASK)
+#define PVR_INTERRUPT_IS_EDGE(_pvr) \
+			(_pvr.pvr[2] & PVR2_INTERRUPT_IS_EDGE_MASK)
+#define PVR_EDGE_IS_POSITIVE(_pvr) \
+			(_pvr.pvr[2] & PVR2_EDGE_IS_POSITIVE_MASK)
+#define PVR_USE_MSR_INSTR(_pvr)		(_pvr.pvr[2] & PVR2_USE_MSR_INSTR)
+#define PVR_USE_PCMP_INSTR(_pvr)	(_pvr.pvr[2] & PVR2_USE_PCMP_INSTR)
+#define PVR_AREA_OPTIMISED(_pvr)	(_pvr.pvr[2] & PVR2_AREA_OPTIMISED)
+#define PVR_USE_MUL64(_pvr)		(_pvr.pvr[2] & PVR2_USE_MUL64_MASK)
+#define PVR_OPCODE_0x0_ILLEGAL(_pvr) \
+			(_pvr.pvr[2] & PVR2_OPCODE_0x0_ILL_MASK)
+#define PVR_UNALIGNED_EXCEPTION(_pvr) \
+			(_pvr.pvr[2] & PVR2_UNALIGNED_EXC_MASK)
+#define PVR_ILL_OPCODE_EXCEPTION(_pvr) \
+			(_pvr.pvr[2] & PVR2_ILL_OPCODE_EXC_MASK)
+#define PVR_IOPB_BUS_EXCEPTION(_pvr) \
+			(_pvr.pvr[2] & PVR2_IOPB_BUS_EXC_MASK)
+#define PVR_DOPB_BUS_EXCEPTION(_pvr) \
+			(_pvr.pvr[2] & PVR2_DOPB_BUS_EXC_MASK)
+#define PVR_DIV_ZERO_EXCEPTION(_pvr) \
+			(_pvr.pvr[2] & PVR2_DIV_ZERO_EXC_MASK)
+#define PVR_FPU_EXCEPTION(_pvr)		(_pvr.pvr[2] & PVR2_FPU_EXC_MASK)
+#define PVR_FSL_EXCEPTION(_pvr)		(_pvr.pvr[2] & PVR2_USE_EXTEND_FSL)
 
-#define PVR_DEBUG_ENABLED(pvr)		(pvr.pvr[3] & PVR3_DEBUG_ENABLED_MASK)
-#define PVR_NUMBER_OF_PC_BRK(pvr) \
-			((pvr.pvr[3] & PVR3_NUMBER_OF_PC_BRK_MASK) >> 25)
-#define PVR_NUMBER_OF_RD_ADDR_BRK(pvr) \
-			((pvr.pvr[3] & PVR3_NUMBER_OF_RD_ADDR_BRK_MASK) >> 19)
-#define PVR_NUMBER_OF_WR_ADDR_BRK(pvr) \
-			((pvr.pvr[3] & PVR3_NUMBER_OF_WR_ADDR_BRK_MASK) >> 13)
-#define PVR_FSL_LINKS(pvr)	((pvr.pvr[3] & PVR3_FSL_LINKS_MASK) >> 7)
+#define PVR_DEBUG_ENABLED(_pvr)		(_pvr.pvr[3] & PVR3_DEBUG_ENABLED_MASK)
+#define PVR_NUMBER_OF_PC_BRK(_pvr) \
+			((_pvr.pvr[3] & PVR3_NUMBER_OF_PC_BRK_MASK) >> 25)
+#define PVR_NUMBER_OF_RD_ADDR_BRK(_pvr) \
+			((_pvr.pvr[3] & PVR3_NUMBER_OF_RD_ADDR_BRK_MASK) >> 19)
+#define PVR_NUMBER_OF_WR_ADDR_BRK(_pvr) \
+			((_pvr.pvr[3] & PVR3_NUMBER_OF_WR_ADDR_BRK_MASK) >> 13)
+#define PVR_FSL_LINKS(_pvr)	((_pvr.pvr[3] & PVR3_FSL_LINKS_MASK) >> 7)
 
-#define PVR_ICACHE_ADDR_TAG_BITS(pvr) \
-			((pvr.pvr[4] & PVR4_ICACHE_ADDR_TAG_BITS_MASK) >> 26)
-#define PVR_ICACHE_USE_FSL(pvr)		(pvr.pvr[4] & PVR4_ICACHE_USE_FSL_MASK)
-#define PVR_ICACHE_ALLOW_WR(pvr)	(pvr.pvr[4] & PVR4_ICACHE_ALLOW_WR_MASK)
-#define PVR_ICACHE_LINE_LEN(pvr) \
-			(1 << ((pvr.pvr[4] & PVR4_ICACHE_LINE_LEN_MASK) >> 21))
-#define PVR_ICACHE_BYTE_SIZE(pvr) \
-			(1 << ((pvr.pvr[4] & PVR4_ICACHE_BYTE_SIZE_MASK) >> 16))
+#define PVR_ICACHE_ADDR_TAG_BITS(_pvr) \
+		((_pvr.pvr[4] & PVR4_ICACHE_ADDR_TAG_BITS_MASK) >> 26)
+#define PVR_ICACHE_USE_FSL(_pvr) \
+		(_pvr.pvr[4] & PVR4_ICACHE_USE_FSL_MASK)
+#define PVR_ICACHE_ALLOW_WR(_pvr) \
+		(_pvr.pvr[4] & PVR4_ICACHE_ALLOW_WR_MASK)
+#define PVR_ICACHE_LINE_LEN(_pvr) \
+		(1 << ((_pvr.pvr[4] & PVR4_ICACHE_LINE_LEN_MASK) >> 21))
+#define PVR_ICACHE_BYTE_SIZE(_pvr) \
+		(1 << ((_pvr.pvr[4] & PVR4_ICACHE_BYTE_SIZE_MASK) >> 16))
 
-#define PVR_DCACHE_ADDR_TAG_BITS(pvr) \
-			((pvr.pvr[5] & PVR5_DCACHE_ADDR_TAG_BITS_MASK) >> 26)
-#define PVR_DCACHE_USE_FSL(pvr)		(pvr.pvr[5] & PVR5_DCACHE_USE_FSL_MASK)
-#define PVR_DCACHE_ALLOW_WR(pvr)	(pvr.pvr[5] & PVR5_DCACHE_ALLOW_WR_MASK)
+#define PVR_DCACHE_ADDR_TAG_BITS(_pvr) \
+			((_pvr.pvr[5] & PVR5_DCACHE_ADDR_TAG_BITS_MASK) >> 26)
+#define PVR_DCACHE_USE_FSL(_pvr)	(_pvr.pvr[5] & PVR5_DCACHE_USE_FSL_MASK)
+#define PVR_DCACHE_ALLOW_WR(_pvr) \
+			(_pvr.pvr[5] & PVR5_DCACHE_ALLOW_WR_MASK)
 /* FIXME two shifts on one line needs any comment */
-#define PVR_DCACHE_LINE_LEN(pvr) \
-			(1 << ((pvr.pvr[5] & PVR5_DCACHE_LINE_LEN_MASK) >> 21))
-#define PVR_DCACHE_BYTE_SIZE(pvr) \
-			(1 << ((pvr.pvr[5] & PVR5_DCACHE_BYTE_SIZE_MASK) >> 16))
-
-#define PVR_DCACHE_USE_WRITEBACK(pvr) \
-			((pvr.pvr[5] & PVR5_DCACHE_USE_WRITEBACK) >> 14)
+#define PVR_DCACHE_LINE_LEN(_pvr) \
+		(1 << ((_pvr.pvr[5] & PVR5_DCACHE_LINE_LEN_MASK) >> 21))
+#define PVR_DCACHE_BYTE_SIZE(_pvr) \
+		(1 << ((_pvr.pvr[5] & PVR5_DCACHE_BYTE_SIZE_MASK) >> 16))
 
-#define PVR_ICACHE_BASEADDR(pvr)	(pvr.pvr[6] & PVR6_ICACHE_BASEADDR_MASK)
-#define PVR_ICACHE_HIGHADDR(pvr)	(pvr.pvr[7] & PVR7_ICACHE_HIGHADDR_MASK)
+#define PVR_DCACHE_USE_WRITEBACK(_pvr) \
+			((_pvr.pvr[5] & PVR5_DCACHE_USE_WRITEBACK) >> 14)
 
-#define PVR_DCACHE_BASEADDR(pvr)	(pvr.pvr[8] & PVR8_DCACHE_BASEADDR_MASK)
-#define PVR_DCACHE_HIGHADDR(pvr)	(pvr.pvr[9] & PVR9_DCACHE_HIGHADDR_MASK)
+#define PVR_ICACHE_BASEADDR(_pvr) \
+			(_pvr.pvr[6] & PVR6_ICACHE_BASEADDR_MASK)
+#define PVR_ICACHE_HIGHADDR(_pvr) \
+			(_pvr.pvr[7] & PVR7_ICACHE_HIGHADDR_MASK)
+#define PVR_DCACHE_BASEADDR(_pvr) \
+			(_pvr.pvr[8] & PVR8_DCACHE_BASEADDR_MASK)
+#define PVR_DCACHE_HIGHADDR(_pvr) \
+			(_pvr.pvr[9] & PVR9_DCACHE_HIGHADDR_MASK)
 
-#define PVR_TARGET_FAMILY(pvr)	((pvr.pvr[10] & PVR10_TARGET_FAMILY_MASK) >> 24)
+#define PVR_TARGET_FAMILY(_pvr) \
+			((_pvr.pvr[10] & PVR10_TARGET_FAMILY_MASK) >> 24)
 
-#define PVR_MSR_RESET_VALUE(pvr) \
-				(pvr.pvr[11] & PVR11_MSR_RESET_VALUE_MASK)
+#define PVR_MSR_RESET_VALUE(_pvr) \
+			(_pvr.pvr[11] & PVR11_MSR_RESET_VALUE_MASK)
 
 /* mmu */
-#define PVR_USE_MMU(pvr)	((pvr.pvr[11] & PVR11_USE_MMU) >> 30)
-#define PVR_MMU_ITLB_SIZE(pvr)	(pvr.pvr[11] & PVR11_MMU_ITLB_SIZE)
-#define PVR_MMU_DTLB_SIZE(pvr)	(pvr.pvr[11] & PVR11_MMU_DTLB_SIZE)
-#define PVR_MMU_TLB_ACCESS(pvr)	(pvr.pvr[11] & PVR11_MMU_TLB_ACCESS)
-#define PVR_MMU_ZONES(pvr)	(pvr.pvr[11] & PVR11_MMU_ZONES)
+#define PVR_USE_MMU(_pvr)		((_pvr.pvr[11] & PVR11_USE_MMU) >> 30)
+#define PVR_MMU_ITLB_SIZE(_pvr)		(_pvr.pvr[11] & PVR11_MMU_ITLB_SIZE)
+#define PVR_MMU_DTLB_SIZE(_pvr)		(_pvr.pvr[11] & PVR11_MMU_DTLB_SIZE)
+#define PVR_MMU_TLB_ACCESS(_pvr)	(_pvr.pvr[11] & PVR11_MMU_TLB_ACCESS)
+#define PVR_MMU_ZONES(_pvr)		(_pvr.pvr[11] & PVR11_MMU_ZONES)
 
 /* endian */
-#define PVR_ENDIAN(pvr)	(pvr.pvr[0] & PVR0_ENDI)
+#define PVR_ENDIAN(_pvr)	(_pvr.pvr[0] & PVR0_ENDI)
 
 int cpu_has_pvr(void);
 void get_pvr(struct pvr_s *pvr);
diff -druNp linux-libre-2.6.37-gnu1/arch/microblaze/include/asm/tlb.h linux-libre-2.6.38-gnu1/arch/microblaze/include/asm/tlb.h
--- linux-libre-2.6.37-gnu1/arch/microblaze/include/asm/tlb.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/microblaze/include/asm/tlb.h	2011-03-14 21:20:32.000000000 -0400
@@ -13,6 +13,7 @@
 
 #define tlb_flush(tlb)	flush_tlb_mm((tlb)->mm)
 
+#include <linux/pagemap.h>
 #include <asm-generic/tlb.h>
 
 #ifdef CONFIG_MMU
diff -druNp linux-libre-2.6.37-gnu1/arch/microblaze/Kconfig linux-libre-2.6.38-gnu1/arch/microblaze/Kconfig
--- linux-libre-2.6.37-gnu1/arch/microblaze/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/microblaze/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -14,7 +14,9 @@ config MICROBLAZE
 	select HAVE_DMA_API_DEBUG
 	select TRACING_SUPPORT
 	select OF
-	select OF_FLATTREE
+	select OF_EARLY_FLATTREE
+	select HAVE_GENERIC_HARDIRQS
+	select GENERIC_IRQ_PROBE
 
 config SWAP
 	def_bool n
@@ -37,12 +39,6 @@ config GENERIC_FIND_NEXT_BIT
 config GENERIC_HWEIGHT
 	def_bool y
 
-config GENERIC_HARDIRQS
-	def_bool y
-
-config GENERIC_IRQ_PROBE
-	def_bool y
-
 config GENERIC_CALIBRATE_DELAY
 	def_bool y
 
@@ -52,9 +48,6 @@ config GENERIC_TIME_VSYSCALL
 config GENERIC_CLOCKEVENTS
 	def_bool y
 
-config GENERIC_HARDIRQS_NO__DO_IRQ
-	def_bool y
-
 config GENERIC_GPIO
 	def_bool y
 
diff -druNp linux-libre-2.6.37-gnu1/arch/microblaze/Kconfig.debug linux-libre-2.6.38-gnu1/arch/microblaze/Kconfig.debug
--- linux-libre-2.6.37-gnu1/arch/microblaze/Kconfig.debug	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/microblaze/Kconfig.debug	2011-03-14 21:20:32.000000000 -0400
@@ -23,8 +23,4 @@ config HEART_BEAT
 	  This option turns on/off heart beat kernel functionality.
 	  First GPIO node is taken.
 
-config DEBUG_BOOTMEM
-	depends on DEBUG_KERNEL
-	bool "Debug BOOTMEM initialization"
-
 endmenu
diff -druNp linux-libre-2.6.37-gnu1/arch/microblaze/kernel/cpu/cpuinfo.c linux-libre-2.6.38-gnu1/arch/microblaze/kernel/cpu/cpuinfo.c
--- linux-libre-2.6.37-gnu1/arch/microblaze/kernel/cpu/cpuinfo.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/microblaze/kernel/cpu/cpuinfo.c	2011-03-14 21:20:32.000000000 -0400
@@ -32,6 +32,7 @@ const struct cpu_ver_key cpu_ver_lookup[
 	{"7.30.a", 0x10},
 	{"7.30.b", 0x11},
 	{"8.00.a", 0x12},
+	{"8.00.b", 0x13},
 	{NULL, 0},
 };
 
diff -druNp linux-libre-2.6.37-gnu1/arch/microblaze/kernel/cpu/pvr.c linux-libre-2.6.38-gnu1/arch/microblaze/kernel/cpu/pvr.c
--- linux-libre-2.6.37-gnu1/arch/microblaze/kernel/cpu/pvr.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/microblaze/kernel/cpu/pvr.c	2011-03-14 21:20:32.000000000 -0400
@@ -27,7 +27,7 @@
 	register unsigned tmp __asm__("r3");			\
 	tmp = 0x0;	/* Prevent warning about unused */	\
 	__asm__ __volatile__ (					\
-			"mfs	%0, rpvr" #pvrid ";"	\
+			"mfs	%0, rpvr" #pvrid ";"		\
 			: "=r" (tmp) : : "memory"); 		\
 	val = tmp;						\
 }
@@ -54,7 +54,7 @@ int cpu_has_pvr(void)
 	if (!(flags & PVR_MSR_BIT))
 		return 0;
 
-	get_single_pvr(0x00, pvr0);
+	get_single_pvr(0, pvr0);
 	pr_debug("%s: pvr0 is 0x%08x\n", __func__, pvr0);
 
 	if (pvr0 & PVR0_PVR_FULL_MASK)
diff -druNp linux-libre-2.6.37-gnu1/arch/microblaze/kernel/entry.S linux-libre-2.6.38-gnu1/arch/microblaze/kernel/entry.S
--- linux-libre-2.6.37-gnu1/arch/microblaze/kernel/entry.S	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/microblaze/kernel/entry.S	2011-03-14 21:20:32.000000000 -0400
@@ -287,25 +287,44 @@
  * are masked. This is nice, means we don't have to CLI before state save
  */
 C_ENTRY(_user_exception):
-	addi	r14, r14, 4	/* return address is 4 byte after call */
 	swi	r1, r0, TOPHYS(PER_CPU(ENTRY_SP)) /* save stack */
+	addi	r14, r14, 4	/* return address is 4 byte after call */
+
+	mfs	r1, rmsr
+	nop
+	andi	r1, r1, MSR_UMS
+	bnei	r1, 1f
+
+/* Kernel-mode state save - kernel execve */
+	lwi	r1, r0, TOPHYS(PER_CPU(ENTRY_SP)); /* Reload kernel stack-ptr*/
+	tophys(r1,r1);
 
+	addik	r1, r1, -STATE_SAVE_SIZE; /* Make room on the stack. */
+	SAVE_REGS
+
+	swi	r1, r1, PTO + PT_MODE; /* pt_regs -> kernel mode */
+	brid	2f;
+	nop;				/* Fill delay slot */
+
+/* User-mode state save.  */
+1:
 	lwi	r1, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); /* get saved current */
 	tophys(r1,r1);
 	lwi	r1, r1, TS_THREAD_INFO;	/* get stack from task_struct */
-	/* MS these three instructions can be added to one */
-	/* addik	r1, r1, THREAD_SIZE; */
-	/* tophys(r1,r1); */
-	/* addik	r1, r1, -STATE_SAVE_SIZE; */
-	addik r1, r1, THREAD_SIZE + CONFIG_KERNEL_BASE_ADDR - CONFIG_KERNEL_START - STATE_SAVE_SIZE;
+/* calculate kernel stack pointer from task struct 8k */
+	addik	r1, r1, THREAD_SIZE;
+	tophys(r1,r1);
+
+	addik	r1, r1, -STATE_SAVE_SIZE; /* Make room on the stack.  */
 	SAVE_REGS
 	swi	r0, r1, PTO + PT_R3
 	swi	r0, r1, PTO + PT_R4
 
+	swi	r0, r1, PTO + PT_MODE;			/* Was in user-mode. */
 	lwi	r11, r0, TOPHYS(PER_CPU(ENTRY_SP));
 	swi	r11, r1, PTO+PT_R1;		/* Store user SP.  */
 	clear_ums;
-	lwi	CURRENT_TASK, r0, TOPHYS(PER_CPU(CURRENT_SAVE));
+2:	lwi	CURRENT_TASK, r0, TOPHYS(PER_CPU(CURRENT_SAVE));
 	/* Save away the syscall number.  */
 	swi	r12, r1, PTO+PT_R0;
 	tovirt(r1,r1)
@@ -375,6 +394,9 @@ C_ENTRY(ret_from_trap):
 	swi	r3, r1, PTO + PT_R3
 	swi	r4, r1, PTO + PT_R4
 
+	lwi	r11, r1, PTO + PT_MODE;
+/* See if returning to kernel mode, if so, skip resched &c.  */
+	bnei	r11, 2f;
 	/* We're returning to user mode, so check for various conditions that
 	 * trigger rescheduling. */
 	/* FIXME: Restructure all these flag checks. */
@@ -417,6 +439,16 @@ C_ENTRY(ret_from_trap):
 	RESTORE_REGS;
 	addik	r1, r1, STATE_SAVE_SIZE		/* Clean up stack space.  */
 	lwi	r1, r1, PT_R1 - PT_SIZE;/* Restore user stack pointer. */
+	bri	6f;
+
+/* Return to kernel state.  */
+2:	set_bip;			/*  Ints masked for state restore */
+	VM_OFF;
+	tophys(r1,r1);
+	RESTORE_REGS;
+	addik	r1, r1, STATE_SAVE_SIZE		/* Clean up stack space.  */
+	tovirt(r1,r1);
+6:
 TRAP_return:		/* Make global symbol for debugging */
 	rtbd	r14, 0;	/* Instructions to return from an IRQ */
 	nop;
diff -druNp linux-libre-2.6.37-gnu1/arch/microblaze/kernel/exceptions.c linux-libre-2.6.38-gnu1/arch/microblaze/kernel/exceptions.c
--- linux-libre-2.6.37-gnu1/arch/microblaze/kernel/exceptions.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/microblaze/kernel/exceptions.c	2011-03-14 21:20:32.000000000 -0400
@@ -25,6 +25,7 @@
 #include <linux/errno.h>
 #include <linux/ptrace.h>
 #include <asm/current.h>
+#include <asm/cacheflush.h>
 
 #define MICROBLAZE_ILL_OPCODE_EXCEPTION	0x02
 #define MICROBLAZE_IBUS_EXCEPTION	0x03
@@ -52,6 +53,8 @@ void die(const char *str, struct pt_regs
 void sw_exception(struct pt_regs *regs)
 {
 	_exception(SIGTRAP, regs, TRAP_BRKPT, regs->r16);
+	flush_dcache_range(regs->r16, regs->r16 + 0x4);
+	flush_icache_range(regs->r16, regs->r16 + 0x4);
 }
 
 void _exception(int signr, struct pt_regs *regs, int code, unsigned long addr)
diff -druNp linux-libre-2.6.37-gnu1/arch/microblaze/kernel/head.S linux-libre-2.6.38-gnu1/arch/microblaze/kernel/head.S
--- linux-libre-2.6.37-gnu1/arch/microblaze/kernel/head.S	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/microblaze/kernel/head.S	2011-03-14 21:20:32.000000000 -0400
@@ -62,23 +62,32 @@ real_start:
 	andi	r1, r1, ~2
 	mts	rmsr, r1
 /*
- * Here is checking mechanism which check if Microblaze has msr instructions
- * We load msr and compare it with previous r1 value - if is the same,
- * msr instructions works if not - cpu don't have them.
+ * According to Xilinx, msrclr instruction behaves like 'mfs rX,rpc'
+ * if the msrclr instruction is not enabled. We use this to detect
+ * if the opcode is available, by issuing msrclr and then testing the result.
+ * r8 == 0 - msr instructions are implemented
+ * r8 != 0 - msr instructions are not implemented
  */
-	/* r8=0 - I have msr instr, 1 - I don't have them */
-	rsubi	r0, r0, 1	/* set the carry bit */
-	msrclr	r0, 0x4		/* try to clear it */
-	/* read the carry bit, r8 will be '0' if msrclr exists */
-	addik	r8, r0, 0
+	msrclr	r8, 0 /* clear nothing - just read msr for test */
+	cmpu	r8, r8, r1 /* r1 must contain msr reg content */
 
 /* r7 may point to an FDT, or there may be one linked in.
    if it's in r7, we've got to save it away ASAP.
    We ensure r7 points to a valid FDT, just in case the bootloader
    is broken or non-existent */
 	beqi	r7, no_fdt_arg			/* NULL pointer?  don't copy */
-	lw	r11, r0, r7			/* Does r7 point to a */
-	rsubi	r11, r11, OF_DT_HEADER		/* valid FDT? */
+/* Does r7 point to a valid FDT? Load HEADER magic number */
+	/* Run time Big/Little endian platform */
+	/* Save 1 as word and load byte - 0 - BIG, 1 - LITTLE */
+	addik	r11, r0, 0x1 /* BIG/LITTLE checking value */
+	/* __bss_start will be zeroed later - it is just temp location */
+	swi	r11, r0, TOPHYS(__bss_start)
+	lbui	r11, r0, TOPHYS(__bss_start)
+	beqid	r11, big_endian /* DO NOT break delay stop dependency */
+	lw	r11, r0, r7 /* Big endian load in delay slot */
+	lwr	r11, r0, r7 /* Little endian load */
+big_endian:
+	rsubi	r11, r11, OF_DT_HEADER	/* Check FDT header */
 	beqi	r11, _prepare_copy_fdt
 	or	r7, r0, r0		/* clear R7 when not valid DTB */
 	bnei	r11, no_fdt_arg			/* No - get out of here */
diff -druNp linux-libre-2.6.37-gnu1/arch/microblaze/kernel/hw_exception_handler.S linux-libre-2.6.38-gnu1/arch/microblaze/kernel/hw_exception_handler.S
--- linux-libre-2.6.37-gnu1/arch/microblaze/kernel/hw_exception_handler.S	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/microblaze/kernel/hw_exception_handler.S	2011-03-14 21:20:32.000000000 -0400
@@ -147,10 +147,6 @@
 	#if CONFIG_XILINX_MICROBLAZE0_USE_BARREL > 0
 	#define BSRLI(rD, rA, imm)	\
 		bsrli rD, rA, imm
-	#elif CONFIG_XILINX_MICROBLAZE0_USE_DIV > 0
-	#define BSRLI(rD, rA, imm)	\
-		ori rD, r0, (1 << imm);	\
-		idivu rD, rD, rA
 	#else
 	#define BSRLI(rD, rA, imm) BSRLI ## imm (rD, rA)
 	/* Only the used shift constants defined here - add more if needed */
@@ -945,11 +941,20 @@ store3:	sbi	r3, r4, 2;
 store4:	sbi	r3, r4, 3;	/* Delay slot */
 ex_shw_vm:
 	/* Store the lower half-word, byte-by-byte into destination address */
+#ifdef __MICROBLAZEEL__
+	lbui	r3, r5, 0;
+store5:	sbi	r3, r4, 0;
+	lbui	r3, r5, 1;
+	brid	ret_from_exc;
+store6:	sbi	r3, r4, 1;	/* Delay slot */
+#else
 	lbui	r3, r5, 2;
 store5:	sbi	r3, r4, 0;
 	lbui	r3, r5, 3;
 	brid	ret_from_exc;
 store6:	sbi	r3, r4, 1;	/* Delay slot */
+#endif
+
 ex_sw_end_vm:			/* Exception handling of store word, ends. */
 
 /* We have to prevent cases that get/put_user macros get unaligned pointer
diff -druNp linux-libre-2.6.37-gnu1/arch/microblaze/kernel/prom.c linux-libre-2.6.38-gnu1/arch/microblaze/kernel/prom.c
--- linux-libre-2.6.37-gnu1/arch/microblaze/kernel/prom.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/microblaze/kernel/prom.c	2011-03-14 21:20:32.000000000 -0400
@@ -47,9 +47,9 @@ void __init early_init_dt_add_memory_arc
 	memblock_add(base, size);
 }
 
-u64 __init early_init_dt_alloc_memory_arch(u64 size, u64 align)
+void * __init early_init_dt_alloc_memory_arch(u64 size, u64 align)
 {
-	return memblock_alloc(size, align);
+	return __va(memblock_alloc(size, align));
 }
 
 #ifdef CONFIG_EARLY_PRINTK
@@ -61,14 +61,12 @@ static int __init early_init_dt_scan_ser
 	char *p;
 	int *addr;
 
-	pr_debug("search \"chosen\", depth: %d, uname: %s\n", depth, uname);
+	pr_debug("search \"serial\", depth: %d, uname: %s\n", depth, uname);
 
 /* find all serial nodes */
 	if (strncmp(uname, "serial", 6) != 0)
 		return 0;
 
-	early_init_dt_check_for_initrd(node);
-
 /* find compatible node with uartlite */
 	p = of_get_flat_dt_prop(node, "compatible", &l);
 	if ((strncmp(p, "xlnx,xps-uartlite", 17) != 0) &&
diff -druNp linux-libre-2.6.37-gnu1/arch/microblaze/kernel/prom_parse.c linux-libre-2.6.38-gnu1/arch/microblaze/kernel/prom_parse.c
--- linux-libre-2.6.37-gnu1/arch/microblaze/kernel/prom_parse.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/microblaze/kernel/prom_parse.c	2011-03-14 21:20:32.000000000 -0400
@@ -110,41 +110,3 @@ void of_parse_dma_window(struct device_n
 	cells = prop ? *(u32 *)prop : of_n_size_cells(dn);
 	*size = of_read_number(dma_window, cells);
 }
-
-/**
- * Search the device tree for the best MAC address to use.  'mac-address' is
- * checked first, because that is supposed to contain to "most recent" MAC
- * address. If that isn't set, then 'local-mac-address' is checked next,
- * because that is the default address.  If that isn't set, then the obsolete
- * 'address' is checked, just in case we're using an old device tree.
- *
- * Note that the 'address' property is supposed to contain a virtual address of
- * the register set, but some DTS files have redefined that property to be the
- * MAC address.
- *
- * All-zero MAC addresses are rejected, because those could be properties that
- * exist in the device tree, but were not set by U-Boot.  For example, the
- * DTS could define 'mac-address' and 'local-mac-address', with zero MAC
- * addresses.  Some older U-Boots only initialized 'local-mac-address'.  In
- * this case, the real MAC is in 'local-mac-address', and 'mac-address' exists
- * but is all zeros.
-*/
-const void *of_get_mac_address(struct device_node *np)
-{
-	struct property *pp;
-
-	pp = of_find_property(np, "mac-address", NULL);
-	if (pp && (pp->length == 6) && is_valid_ether_addr(pp->value))
-		return pp->value;
-
-	pp = of_find_property(np, "local-mac-address", NULL);
-	if (pp && (pp->length == 6) && is_valid_ether_addr(pp->value))
-		return pp->value;
-
-	pp = of_find_property(np, "address", NULL);
-	if (pp && (pp->length == 6) && is_valid_ether_addr(pp->value))
-		return pp->value;
-
-	return NULL;
-}
-EXPORT_SYMBOL(of_get_mac_address);
diff -druNp linux-libre-2.6.37-gnu1/arch/microblaze/kernel/setup.c linux-libre-2.6.38-gnu1/arch/microblaze/kernel/setup.c
--- linux-libre-2.6.37-gnu1/arch/microblaze/kernel/setup.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/microblaze/kernel/setup.c	2011-03-14 21:20:32.000000000 -0400
@@ -161,11 +161,11 @@ void __init machine_early_init(const cha
 #if CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR
 	if (msr)
 		eprintk("!!!Your kernel has setup MSR instruction but "
-				"CPU don't have it %d\n", msr);
+				"CPU don't have it %x\n", msr);
 #else
 	if (!msr)
 		eprintk("!!!Your kernel not setup MSR instruction but "
-				"CPU have it %d\n", msr);
+				"CPU have it %x\n", msr);
 #endif
 
 	for (src = __ivt_start; src < __ivt_end; src++, dst++)
diff -druNp linux-libre-2.6.37-gnu1/arch/microblaze/kernel/vmlinux.lds.S linux-libre-2.6.38-gnu1/arch/microblaze/kernel/vmlinux.lds.S
--- linux-libre-2.6.37-gnu1/arch/microblaze/kernel/vmlinux.lds.S	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/microblaze/kernel/vmlinux.lds.S	2011-03-14 21:20:32.000000000 -0400
@@ -123,20 +123,10 @@ SECTIONS {
 
 	__init_end_before_initramfs = .;
 
-	.init.ramfs ALIGN(PAGE_SIZE) : AT(ADDR(.init.ramfs) - LOAD_OFFSET) {
-		__initramfs_start = .;
-		*(.init.ramfs)
-		__initramfs_end = .;
-		. = ALIGN(4);
-		LONG(0);
-/*
- * FIXME this can break initramfs for MMU.
- * Pad init.ramfs up to page boundary,
- * so that __init_end == __bss_start. This will make image.elf
- * consistent with the image.bin
- */
-		/* . = ALIGN(PAGE_SIZE); */
+	.init.ramfs : AT(ADDR(.init.ramfs) - LOAD_OFFSET) {
+		INIT_RAM_FS
 	}
+
 	__init_end = .;
 
 	.bss ALIGN (PAGE_SIZE) : AT(ADDR(.bss) - LOAD_OFFSET) {
diff -druNp linux-libre-2.6.37-gnu1/arch/microblaze/lib/fastcopy.S linux-libre-2.6.38-gnu1/arch/microblaze/lib/fastcopy.S
--- linux-libre-2.6.37-gnu1/arch/microblaze/lib/fastcopy.S	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/microblaze/lib/fastcopy.S	2011-03-14 21:20:32.000000000 -0400
@@ -29,6 +29,10 @@
  *	between mem locations with size of xfer spec'd in bytes
  */
 
+#ifdef __MICROBLAZEEL__
+#error Microblaze LE not support ASM optimized lib func. Disable OPT_LIB_ASM.
+#endif
+
 #include <linux/linkage.h>
 	.text
 	.globl	memcpy
diff -druNp linux-libre-2.6.37-gnu1/arch/microblaze/lib/memmove.c linux-libre-2.6.38-gnu1/arch/microblaze/lib/memmove.c
--- linux-libre-2.6.37-gnu1/arch/microblaze/lib/memmove.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/microblaze/lib/memmove.c	2011-03-14 21:20:32.000000000 -0400
@@ -182,7 +182,7 @@ void *memmove(void *v_dst, const void *v
 			for (; c >= 4; c -= 4) {
 				value = *--i_src;
 				*--i_dst = buf_hold | ((value & 0xFF000000)>> 24);
-				buf_hold = (value & 0xFFFFFF) << 8;;
+				buf_hold = (value & 0xFFFFFF) << 8;
 			}
 #endif
 			/* Realign the source */
diff -druNp linux-libre-2.6.37-gnu1/arch/microblaze/lib/muldi3.c linux-libre-2.6.38-gnu1/arch/microblaze/lib/muldi3.c
--- linux-libre-2.6.37-gnu1/arch/microblaze/lib/muldi3.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/microblaze/lib/muldi3.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,60 @@
+#include <linux/module.h>
+
+#include "libgcc.h"
+
+#define DWtype long long
+#define UWtype unsigned long
+#define UHWtype unsigned short
+
+#define W_TYPE_SIZE 32
+
+#define __ll_B ((UWtype) 1 << (W_TYPE_SIZE / 2))
+#define __ll_lowpart(t) ((UWtype) (t) & (__ll_B - 1))
+#define __ll_highpart(t) ((UWtype) (t) >> (W_TYPE_SIZE / 2))
+
+/* If we still don't have umul_ppmm, define it using plain C.  */
+#if !defined(umul_ppmm)
+#define umul_ppmm(w1, w0, u, v)						\
+	do {								\
+		UWtype __x0, __x1, __x2, __x3;				\
+		UHWtype __ul, __vl, __uh, __vh;				\
+									\
+		__ul = __ll_lowpart(u);					\
+		__uh = __ll_highpart(u);				\
+		__vl = __ll_lowpart(v);					\
+		__vh = __ll_highpart(v);				\
+									\
+		__x0 = (UWtype) __ul * __vl;				\
+		__x1 = (UWtype) __ul * __vh;				\
+		__x2 = (UWtype) __uh * __vl;				\
+		__x3 = (UWtype) __uh * __vh;				\
+									\
+		__x1 += __ll_highpart(__x0); /* this can't give carry */\
+		__x1 += __x2; /* but this indeed can */			\
+		if (__x1 < __x2) /* did we get it? */			\
+		__x3 += __ll_B; /* yes, add it in the proper pos */	\
+									\
+		(w1) = __x3 + __ll_highpart(__x1);			\
+		(w0) = __ll_lowpart(__x1) * __ll_B + __ll_lowpart(__x0);\
+	} while (0)
+#endif
+
+#if !defined(__umulsidi3)
+#define __umulsidi3(u, v) ({				\
+	DWunion __w;					\
+	umul_ppmm(__w.s.high, __w.s.low, u, v);		\
+	__w.ll;						\
+	})
+#endif
+
+DWtype __muldi3(DWtype u, DWtype v)
+{
+	const DWunion uu = {.ll = u};
+	const DWunion vv = {.ll = v};
+	DWunion w = {.ll = __umulsidi3(uu.s.low, vv.s.low)};
+
+	w.s.high += ((UWtype) uu.s.low * (UWtype) vv.s.high
+		+ (UWtype) uu.s.high * (UWtype) vv.s.low);
+
+	return w.ll;
+}
diff -druNp linux-libre-2.6.37-gnu1/arch/microblaze/lib/muldi3.S linux-libre-2.6.38-gnu1/arch/microblaze/lib/muldi3.S
--- linux-libre-2.6.37-gnu1/arch/microblaze/lib/muldi3.S	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/microblaze/lib/muldi3.S	1969-12-31 19:00:00.000000000 -0500
@@ -1,121 +0,0 @@
-#include <linux/linkage.h>
-
-/*
- * Multiply operation for 64 bit integers, for devices with hard multiply
- *	Input :	Operand1[H] in Reg r5
- *		Operand1[L] in Reg r6
- *		Operand2[H] in Reg r7
- *		Operand2[L] in Reg r8
- *	Output: Result[H] in Reg r3
- *		Result[L] in Reg r4
- *
- * Explaination:
- *
- *	Both the input numbers are divided into 16 bit number as follows
- *		op1 = A B C D
- *		op2 = E F G H
- *	result = D * H
- *		 + (C * H + D * G) << 16
- *		 + (B * H + C * G + D * F) << 32
- *		 + (A * H + B * G + C * F + D * E) << 48
- *
- *	Only 64 bits of the output are considered
- */
-
-	.text
-	.globl	__muldi3
-	.type __muldi3, @function
-	.ent __muldi3
-
-__muldi3:
-	addi	r1, r1, -40
-
-/* Save the input operands on the caller's stack */
-	swi	r5, r1, 44
-	swi	r6, r1, 48
-	swi	r7, r1, 52
-	swi	r8, r1, 56
-
-/* Store all the callee saved registers */
-	sw	r20, r1, r0
-	swi	r21, r1, 4
-	swi	r22, r1, 8
-	swi	r23, r1, 12
-	swi	r24, r1, 16
-	swi	r25, r1, 20
-	swi	r26, r1, 24
-	swi	r27, r1, 28
-
-/* Load all the 16 bit values for A thru H */
-	lhui	r20, r1, 44 /* A */
-	lhui	r21, r1, 46 /* B */
-	lhui	r22, r1, 48 /* C */
-	lhui	r23, r1, 50 /* D */
-	lhui	r24, r1, 52 /* E */
-	lhui	r25, r1, 54 /* F */
-	lhui	r26, r1, 56 /* G */
-	lhui	r27, r1, 58 /* H */
-
-/* D * H ==> LSB of the result on stack ==> Store1 */
-	mul	r9, r23, r27
-	swi	r9, r1, 36 /* Pos2 and Pos3 */
-
-/* Hi (Store1) + C * H + D * G ==> Store2 ==> Pos1 and Pos2 */
-/* Store the carry generated in position 2 for Pos 3 */
-	lhui	r11, r1, 36 /* Pos2 */
-	mul	r9, r22, r27 /* C * H */
-	mul	r10, r23, r26 /* D * G */
-	add	r9, r9, r10
-	addc	r12, r0, r0
-	add	r9, r9, r11
-	addc	r12, r12, r0 /* Store the Carry */
-	shi	r9, r1, 36 /* Store Pos2 */
-	swi	r9, r1, 32
-	lhui	r11, r1, 32
-	shi	r11, r1, 34 /* Store Pos1 */
-
-/* Hi (Store2) + B * H + C * G + D * F ==> Store3 ==> Pos0 and Pos1 */
-	mul	r9, r21, r27 /* B * H */
-	mul	r10, r22, r26 /* C * G */
-	mul	r7, r23, r25 /* D * F */
-	add	r9, r9, r11
-	add	r9, r9, r10
-	add	r9, r9, r7
-	swi	r9, r1, 32 /* Pos0 and Pos1 */
-
-/* Hi (Store3) + A * H + B * G + C * F + D * E ==> Store3 ==> Pos0 */
-	lhui	r11, r1, 32 /* Pos0 */
-	mul	r9, r20, r27 /* A * H */
-	mul	r10, r21, r26 /* B * G */
-	mul	r7, r22, r25 /* C * F */
-	mul	r8, r23, r24 /* D * E */
-	add	r9, r9, r11
-	add 	r9, r9, r10
-	add	r9, r9, r7
-	add	r9, r9, r8
-	sext16	r9, r9 /* Sign extend the MSB */
-	shi	r9, r1, 32
-
-/* Move results to r3 and r4 */
-	lhui	r3, r1, 32
-	add	r3, r3, r12
-	shi	r3, r1, 32
-	lwi	r3, r1, 32 /* Hi Part */
-	lwi	r4, r1, 36 /* Lo Part */
-
-/* Restore Callee saved registers */
-	lw	r20, r1, r0
-	lwi	r21, r1, 4
-	lwi	r22, r1, 8
-	lwi	r23, r1, 12
-	lwi	r24, r1, 16
-	lwi	r25, r1, 20
-	lwi	r26, r1, 24
-	lwi	r27, r1, 28
-
-/* Restore Frame and return */
-	rtsd	r15, 8
-	addi	r1, r1, 40
-
-.size __muldi3, . - __muldi3
-.end __muldi3
diff -druNp linux-libre-2.6.37-gnu1/arch/microblaze/Makefile linux-libre-2.6.38-gnu1/arch/microblaze/Makefile
--- linux-libre-2.6.37-gnu1/arch/microblaze/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/microblaze/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -17,7 +17,7 @@ export CPU_VER CPU_MAJOR CPU_MINOR CPU_R
 # The various CONFIG_XILINX cpu features options are integers 0/1/2...
 # rather than bools y/n
 
-# Work out HW multipler support.  This is icky.
+# Work out HW multipler support. This is tricky.
 # 1. Spartan2 has no HW multiplers.
 # 2. MicroBlaze v3.x always uses them, except in Spartan 2
 # 3. All other FPGa/CPU ver combos, we can trust the CONFIG_ settings
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/alchemy/common/power.c linux-libre-2.6.38-gnu1/arch/mips/alchemy/common/power.c
--- linux-libre-2.6.37-gnu1/arch/mips/alchemy/common/power.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/alchemy/common/power.c	2011-03-14 21:20:32.000000000 -0400
@@ -130,7 +130,7 @@ static void restore_core_regs(void)
 	au_writel(sleep_usb[1], USBD_ENABLE);
 	au_sync();
 #else
-	/* enable accces to OTG memory */
+	/* enable access to OTG memory */
 	au_writel(au_readl(USB_MSR_BASE + 4) | (1 << 6), USB_MSR_BASE + 4);
 	au_sync();
 
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/alchemy/devboards/pm.c linux-libre-2.6.38-gnu1/arch/mips/alchemy/devboards/pm.c
--- linux-libre-2.6.37-gnu1/arch/mips/alchemy/devboards/pm.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/alchemy/devboards/pm.c	2011-03-14 21:20:32.000000000 -0400
@@ -110,7 +110,7 @@ static void db1x_pm_end(void)
 
 }
 
-static struct platform_suspend_ops db1x_pm_ops = {
+static const struct platform_suspend_ops db1x_pm_ops = {
 	.valid		= suspend_valid_only_mem,
 	.begin		= db1x_pm_begin,
 	.enter		= db1x_pm_enter,
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/alchemy/mtx-1/board_setup.c linux-libre-2.6.38-gnu1/arch/mips/alchemy/mtx-1/board_setup.c
--- linux-libre-2.6.37-gnu1/arch/mips/alchemy/mtx-1/board_setup.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/alchemy/mtx-1/board_setup.c	2011-03-14 21:20:32.000000000 -0400
@@ -54,8 +54,8 @@ int mtx1_pci_idsel(unsigned int devsel,
 
 static void mtx1_reset(char *c)
 {
-	/* Hit BCSR.SYSTEM_CONTROL[SW_RST] */
-	au_writel(0x00000000, 0xAE00001C);
+	/* Jump to the reset vector */
+	__asm__ __volatile__("jr\t%0"::"r"(0xbfc00000));
 }
 
 static void mtx1_power_off(void)
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/alchemy/mtx-1/platform.c linux-libre-2.6.38-gnu1/arch/mips/alchemy/mtx-1/platform.c
--- linux-libre-2.6.37-gnu1/arch/mips/alchemy/mtx-1/platform.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/alchemy/mtx-1/platform.c	2011-03-14 21:20:32.000000000 -0400
@@ -28,6 +28,8 @@
 #include <linux/mtd/physmap.h>
 #include <mtd/mtd-abi.h>
 
+#include <asm/mach-au1x00/au1xxx_eth.h>
+
 static struct gpio_keys_button mtx1_gpio_button[] = {
 	{
 		.gpio = 207,
@@ -140,10 +142,17 @@ static struct __initdata platform_device
 	&mtx1_mtd,
 };
 
+static struct au1000_eth_platform_data mtx1_au1000_eth0_pdata = {
+	.phy_search_highest_addr	= 1,
+	.phy1_search_mac0 		= 1,
+};
+
 static int __init mtx1_register_devices(void)
 {
 	int rc;
 
+	au1xxx_override_eth_cfg(0, &mtx1_au1000_eth0_pdata);
+
 	rc = gpio_request(mtx1_gpio_button[0].gpio,
 					mtx1_gpio_button[0].desc);
 	if (rc < 0) {
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/alchemy/xxs1500/board_setup.c linux-libre-2.6.38-gnu1/arch/mips/alchemy/xxs1500/board_setup.c
--- linux-libre-2.6.37-gnu1/arch/mips/alchemy/xxs1500/board_setup.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/alchemy/xxs1500/board_setup.c	2011-03-14 21:20:32.000000000 -0400
@@ -36,8 +36,8 @@
 
 static void xxs1500_reset(char *c)
 {
-	/* Hit BCSR.SYSTEM_CONTROL[SW_RST] */
-	au_writel(0x00000000, 0xAE00001C);
+	/* Jump to the reset vector */
+	__asm__ __volatile__("jr\t%0"::"r"(0xbfc00000));
 }
 
 static void xxs1500_power_off(void)
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/ath79/clock.c linux-libre-2.6.38-gnu1/arch/mips/ath79/clock.c
--- linux-libre-2.6.37-gnu1/arch/mips/ath79/clock.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/ath79/clock.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,183 @@
+/*
+ *  Atheros AR71XX/AR724X/AR913X common routines
+ *
+ *  Copyright (C) 2011 Gabor Juhos <juhosg@openwrt.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License version 2 as published
+ *  by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+
+#include <asm/mach-ath79/ath79.h>
+#include <asm/mach-ath79/ar71xx_regs.h>
+#include "common.h"
+
+#define AR71XX_BASE_FREQ	40000000
+#define AR724X_BASE_FREQ	5000000
+#define AR913X_BASE_FREQ	5000000
+
+struct clk {
+	unsigned long rate;
+};
+
+static struct clk ath79_ref_clk;
+static struct clk ath79_cpu_clk;
+static struct clk ath79_ddr_clk;
+static struct clk ath79_ahb_clk;
+static struct clk ath79_wdt_clk;
+static struct clk ath79_uart_clk;
+
+static void __init ar71xx_clocks_init(void)
+{
+	u32 pll;
+	u32 freq;
+	u32 div;
+
+	ath79_ref_clk.rate = AR71XX_BASE_FREQ;
+
+	pll = ath79_pll_rr(AR71XX_PLL_REG_CPU_CONFIG);
+
+	div = ((pll >> AR71XX_PLL_DIV_SHIFT) & AR71XX_PLL_DIV_MASK) + 1;
+	freq = div * ath79_ref_clk.rate;
+
+	div = ((pll >> AR71XX_CPU_DIV_SHIFT) & AR71XX_CPU_DIV_MASK) + 1;
+	ath79_cpu_clk.rate = freq / div;
+
+	div = ((pll >> AR71XX_DDR_DIV_SHIFT) & AR71XX_DDR_DIV_MASK) + 1;
+	ath79_ddr_clk.rate = freq / div;
+
+	div = (((pll >> AR71XX_AHB_DIV_SHIFT) & AR71XX_AHB_DIV_MASK) + 1) * 2;
+	ath79_ahb_clk.rate = ath79_cpu_clk.rate / div;
+
+	ath79_wdt_clk.rate = ath79_ahb_clk.rate;
+	ath79_uart_clk.rate = ath79_ahb_clk.rate;
+}
+
+static void __init ar724x_clocks_init(void)
+{
+	u32 pll;
+	u32 freq;
+	u32 div;
+
+	ath79_ref_clk.rate = AR724X_BASE_FREQ;
+	pll = ath79_pll_rr(AR724X_PLL_REG_CPU_CONFIG);
+
+	div = ((pll >> AR724X_PLL_DIV_SHIFT) & AR724X_PLL_DIV_MASK);
+	freq = div * ath79_ref_clk.rate;
+
+	div = ((pll >> AR724X_PLL_REF_DIV_SHIFT) & AR724X_PLL_REF_DIV_MASK);
+	freq *= div;
+
+	ath79_cpu_clk.rate = freq;
+
+	div = ((pll >> AR724X_DDR_DIV_SHIFT) & AR724X_DDR_DIV_MASK) + 1;
+	ath79_ddr_clk.rate = freq / div;
+
+	div = (((pll >> AR724X_AHB_DIV_SHIFT) & AR724X_AHB_DIV_MASK) + 1) * 2;
+	ath79_ahb_clk.rate = ath79_cpu_clk.rate / div;
+
+	ath79_wdt_clk.rate = ath79_ahb_clk.rate;
+	ath79_uart_clk.rate = ath79_ahb_clk.rate;
+}
+
+static void __init ar913x_clocks_init(void)
+{
+	u32 pll;
+	u32 freq;
+	u32 div;
+
+	ath79_ref_clk.rate = AR913X_BASE_FREQ;
+	pll = ath79_pll_rr(AR913X_PLL_REG_CPU_CONFIG);
+
+	div = ((pll >> AR913X_PLL_DIV_SHIFT) & AR913X_PLL_DIV_MASK);
+	freq = div * ath79_ref_clk.rate;
+
+	ath79_cpu_clk.rate = freq;
+
+	div = ((pll >> AR913X_DDR_DIV_SHIFT) & AR913X_DDR_DIV_MASK) + 1;
+	ath79_ddr_clk.rate = freq / div;
+
+	div = (((pll >> AR913X_AHB_DIV_SHIFT) & AR913X_AHB_DIV_MASK) + 1) * 2;
+	ath79_ahb_clk.rate = ath79_cpu_clk.rate / div;
+
+	ath79_wdt_clk.rate = ath79_ahb_clk.rate;
+	ath79_uart_clk.rate = ath79_ahb_clk.rate;
+}
+
+void __init ath79_clocks_init(void)
+{
+	if (soc_is_ar71xx())
+		ar71xx_clocks_init();
+	else if (soc_is_ar724x())
+		ar724x_clocks_init();
+	else if (soc_is_ar913x())
+		ar913x_clocks_init();
+	else
+		BUG();
+
+	pr_info("Clocks: CPU:%lu.%03luMHz, DDR:%lu.%03luMHz, AHB:%lu.%03luMHz, "
+		"Ref:%lu.%03luMHz",
+		ath79_cpu_clk.rate / 1000000,
+		(ath79_cpu_clk.rate / 1000) % 1000,
+		ath79_ddr_clk.rate / 1000000,
+		(ath79_ddr_clk.rate / 1000) % 1000,
+		ath79_ahb_clk.rate / 1000000,
+		(ath79_ahb_clk.rate / 1000) % 1000,
+		ath79_ref_clk.rate / 1000000,
+		(ath79_ref_clk.rate / 1000) % 1000);
+}
+
+/*
+ * Linux clock API
+ */
+struct clk *clk_get(struct device *dev, const char *id)
+{
+	if (!strcmp(id, "ref"))
+		return &ath79_ref_clk;
+
+	if (!strcmp(id, "cpu"))
+		return &ath79_cpu_clk;
+
+	if (!strcmp(id, "ddr"))
+		return &ath79_ddr_clk;
+
+	if (!strcmp(id, "ahb"))
+		return &ath79_ahb_clk;
+
+	if (!strcmp(id, "wdt"))
+		return &ath79_wdt_clk;
+
+	if (!strcmp(id, "uart"))
+		return &ath79_uart_clk;
+
+	return ERR_PTR(-ENOENT);
+}
+EXPORT_SYMBOL(clk_get);
+
+int clk_enable(struct clk *clk)
+{
+	return 0;
+}
+EXPORT_SYMBOL(clk_enable);
+
+void clk_disable(struct clk *clk)
+{
+}
+EXPORT_SYMBOL(clk_disable);
+
+unsigned long clk_get_rate(struct clk *clk)
+{
+	return clk->rate;
+}
+EXPORT_SYMBOL(clk_get_rate);
+
+void clk_put(struct clk *clk)
+{
+}
+EXPORT_SYMBOL(clk_put);
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/ath79/common.c linux-libre-2.6.38-gnu1/arch/mips/ath79/common.c
--- linux-libre-2.6.37-gnu1/arch/mips/ath79/common.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/ath79/common.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,97 @@
+/*
+ *  Atheros AR71XX/AR724X/AR913X common routines
+ *
+ *  Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
+ *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License version 2 as published
+ *  by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/spinlock.h>
+
+#include <asm/mach-ath79/ath79.h>
+#include <asm/mach-ath79/ar71xx_regs.h>
+#include "common.h"
+
+static DEFINE_SPINLOCK(ath79_device_reset_lock);
+
+u32 ath79_cpu_freq;
+EXPORT_SYMBOL_GPL(ath79_cpu_freq);
+
+u32 ath79_ahb_freq;
+EXPORT_SYMBOL_GPL(ath79_ahb_freq);
+
+u32 ath79_ddr_freq;
+EXPORT_SYMBOL_GPL(ath79_ddr_freq);
+
+enum ath79_soc_type ath79_soc;
+
+void __iomem *ath79_pll_base;
+void __iomem *ath79_reset_base;
+EXPORT_SYMBOL_GPL(ath79_reset_base);
+void __iomem *ath79_ddr_base;
+
+void ath79_ddr_wb_flush(u32 reg)
+{
+	void __iomem *flush_reg = ath79_ddr_base + reg;
+
+	/* Flush the DDR write buffer. */
+	__raw_writel(0x1, flush_reg);
+	while (__raw_readl(flush_reg) & 0x1)
+		;
+
+	/* It must be run twice. */
+	__raw_writel(0x1, flush_reg);
+	while (__raw_readl(flush_reg) & 0x1)
+		;
+}
+EXPORT_SYMBOL_GPL(ath79_ddr_wb_flush);
+
+void ath79_device_reset_set(u32 mask)
+{
+	unsigned long flags;
+	u32 reg;
+	u32 t;
+
+	if (soc_is_ar71xx())
+		reg = AR71XX_RESET_REG_RESET_MODULE;
+	else if (soc_is_ar724x())
+		reg = AR724X_RESET_REG_RESET_MODULE;
+	else if (soc_is_ar913x())
+		reg = AR913X_RESET_REG_RESET_MODULE;
+	else
+		BUG();
+
+	spin_lock_irqsave(&ath79_device_reset_lock, flags);
+	t = ath79_reset_rr(reg);
+	ath79_reset_wr(reg, t | mask);
+	spin_unlock_irqrestore(&ath79_device_reset_lock, flags);
+}
+EXPORT_SYMBOL_GPL(ath79_device_reset_set);
+
+void ath79_device_reset_clear(u32 mask)
+{
+	unsigned long flags;
+	u32 reg;
+	u32 t;
+
+	if (soc_is_ar71xx())
+		reg = AR71XX_RESET_REG_RESET_MODULE;
+	else if (soc_is_ar724x())
+		reg = AR724X_RESET_REG_RESET_MODULE;
+	else if (soc_is_ar913x())
+		reg = AR913X_RESET_REG_RESET_MODULE;
+	else
+		BUG();
+
+	spin_lock_irqsave(&ath79_device_reset_lock, flags);
+	t = ath79_reset_rr(reg);
+	ath79_reset_wr(reg, t & ~mask);
+	spin_unlock_irqrestore(&ath79_device_reset_lock, flags);
+}
+EXPORT_SYMBOL_GPL(ath79_device_reset_clear);
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/ath79/common.h linux-libre-2.6.38-gnu1/arch/mips/ath79/common.h
--- linux-libre-2.6.37-gnu1/arch/mips/ath79/common.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/ath79/common.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,31 @@
+/*
+ *  Atheros AR71XX/AR724X/AR913X common definitions
+ *
+ *  Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org>
+ *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
+ *
+ *  Parts of this file are based on Atheros' 2.6.15 BSP
+ *
+ *  This program is free software; you can 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 __ATH79_COMMON_H
+#define __ATH79_COMMON_H
+
+#include <linux/types.h>
+#include <linux/init.h>
+
+#define ATH79_MEM_SIZE_MIN	(2 * 1024 * 1024)
+#define ATH79_MEM_SIZE_MAX	(128 * 1024 * 1024)
+
+void ath79_clocks_init(void);
+void ath79_ddr_wb_flush(unsigned int reg);
+
+void ath79_gpio_function_enable(u32 mask);
+void ath79_gpio_function_disable(u32 mask);
+void ath79_gpio_function_setup(u32 set, u32 clear);
+void ath79_gpio_init(void);
+
+#endif /* __ATH79_COMMON_H */
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/ath79/dev-ar913x-wmac.c linux-libre-2.6.38-gnu1/arch/mips/ath79/dev-ar913x-wmac.c
--- linux-libre-2.6.37-gnu1/arch/mips/ath79/dev-ar913x-wmac.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/ath79/dev-ar913x-wmac.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,60 @@
+/*
+ *  Atheros AR913X SoC built-in WMAC device support
+ *
+ *  Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
+ *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License version 2 as published
+ *  by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/platform_device.h>
+#include <linux/ath9k_platform.h>
+
+#include <asm/mach-ath79/ath79.h>
+#include <asm/mach-ath79/ar71xx_regs.h>
+#include "dev-ar913x-wmac.h"
+
+static struct ath9k_platform_data ar913x_wmac_data;
+
+static struct resource ar913x_wmac_resources[] = {
+	{
+		.start	= AR913X_WMAC_BASE,
+		.end	= AR913X_WMAC_BASE + AR913X_WMAC_SIZE - 1,
+		.flags	= IORESOURCE_MEM,
+	}, {
+		.start	= ATH79_CPU_IRQ_IP2,
+		.end	= ATH79_CPU_IRQ_IP2,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device ar913x_wmac_device = {
+	.name		= "ath9k",
+	.id		= -1,
+	.resource	= ar913x_wmac_resources,
+	.num_resources	= ARRAY_SIZE(ar913x_wmac_resources),
+	.dev = {
+		.platform_data = &ar913x_wmac_data,
+	},
+};
+
+void __init ath79_register_ar913x_wmac(u8 *cal_data)
+{
+	if (cal_data)
+		memcpy(ar913x_wmac_data.eeprom_data, cal_data,
+		       sizeof(ar913x_wmac_data.eeprom_data));
+
+	/* reset the WMAC */
+	ath79_device_reset_set(AR913X_RESET_AMBA2WMAC);
+	mdelay(10);
+
+	ath79_device_reset_clear(AR913X_RESET_AMBA2WMAC);
+	mdelay(10);
+
+	platform_device_register(&ar913x_wmac_device);
+}
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/ath79/dev-ar913x-wmac.h linux-libre-2.6.38-gnu1/arch/mips/ath79/dev-ar913x-wmac.h
--- linux-libre-2.6.37-gnu1/arch/mips/ath79/dev-ar913x-wmac.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/ath79/dev-ar913x-wmac.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,17 @@
+/*
+ *  Atheros AR913X SoC built-in WMAC device support
+ *
+ *  Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
+ *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License version 2 as published
+ *  by the Free Software Foundation.
+ */
+
+#ifndef _ATH79_DEV_AR913X_WMAC_H
+#define _ATH79_DEV_AR913X_WMAC_H
+
+void ath79_register_ar913x_wmac(u8 *cal_data);
+
+#endif /* _ATH79_DEV_AR913X_WMAC_H */
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/ath79/dev-common.c linux-libre-2.6.38-gnu1/arch/mips/ath79/dev-common.c
--- linux-libre-2.6.37-gnu1/arch/mips/ath79/dev-common.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/ath79/dev-common.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,77 @@
+/*
+ *  Atheros AR71XX/AR724X/AR913X common devices
+ *
+ *  Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org>
+ *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
+ *
+ *  Parts of this file are based on Atheros' 2.6.15 BSP
+ *
+ *  This program is free software; you can 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/platform_device.h>
+#include <linux/serial_8250.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+
+#include <asm/mach-ath79/ath79.h>
+#include <asm/mach-ath79/ar71xx_regs.h>
+#include "common.h"
+#include "dev-common.h"
+
+static struct resource ath79_uart_resources[] = {
+	{
+		.start	= AR71XX_UART_BASE,
+		.end	= AR71XX_UART_BASE + AR71XX_UART_SIZE - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+#define AR71XX_UART_FLAGS (UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP)
+static struct plat_serial8250_port ath79_uart_data[] = {
+	{
+		.mapbase	= AR71XX_UART_BASE,
+		.irq		= ATH79_MISC_IRQ_UART,
+		.flags		= AR71XX_UART_FLAGS,
+		.iotype		= UPIO_MEM32,
+		.regshift	= 2,
+	}, {
+		/* terminating entry */
+	}
+};
+
+static struct platform_device ath79_uart_device = {
+	.name		= "serial8250",
+	.id		= PLAT8250_DEV_PLATFORM,
+	.resource	= ath79_uart_resources,
+	.num_resources	= ARRAY_SIZE(ath79_uart_resources),
+	.dev = {
+		.platform_data	= ath79_uart_data
+	},
+};
+
+void __init ath79_register_uart(void)
+{
+	struct clk *clk;
+
+	clk = clk_get(NULL, "uart");
+	if (IS_ERR(clk))
+		panic("unable to get UART clock, err=%ld", PTR_ERR(clk));
+
+	ath79_uart_data[0].uartclk = clk_get_rate(clk);
+	platform_device_register(&ath79_uart_device);
+}
+
+static struct platform_device ath79_wdt_device = {
+	.name		= "ath79-wdt",
+	.id		= -1,
+};
+
+void __init ath79_register_wdt(void)
+{
+	platform_device_register(&ath79_wdt_device);
+}
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/ath79/dev-common.h linux-libre-2.6.38-gnu1/arch/mips/ath79/dev-common.h
--- linux-libre-2.6.37-gnu1/arch/mips/ath79/dev-common.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/ath79/dev-common.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,18 @@
+/*
+ *  Atheros AR71XX/AR724X/AR913X common devices
+ *
+ *  Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
+ *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License version 2 as published
+ *  by the Free Software Foundation.
+ */
+
+#ifndef _ATH79_DEV_COMMON_H
+#define _ATH79_DEV_COMMON_H
+
+void ath79_register_uart(void);
+void ath79_register_wdt(void);
+
+#endif /* _ATH79_DEV_COMMON_H */
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/ath79/dev-gpio-buttons.c linux-libre-2.6.38-gnu1/arch/mips/ath79/dev-gpio-buttons.c
--- linux-libre-2.6.37-gnu1/arch/mips/ath79/dev-gpio-buttons.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/ath79/dev-gpio-buttons.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,58 @@
+/*
+ *  Atheros AR71XX/AR724X/AR913X GPIO button support
+ *
+ *  Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
+ *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License version 2 as published
+ *  by the Free Software Foundation.
+ */
+
+#include "linux/init.h"
+#include "linux/slab.h"
+#include <linux/platform_device.h>
+
+#include "dev-gpio-buttons.h"
+
+void __init ath79_register_gpio_keys_polled(int id,
+					    unsigned poll_interval,
+					    unsigned nbuttons,
+					    struct gpio_keys_button *buttons)
+{
+	struct platform_device *pdev;
+	struct gpio_keys_platform_data pdata;
+	struct gpio_keys_button *p;
+	int err;
+
+	p = kmalloc(nbuttons * sizeof(*p), GFP_KERNEL);
+	if (!p)
+		return;
+
+	memcpy(p, buttons, nbuttons * sizeof(*p));
+
+	pdev = platform_device_alloc("gpio-keys-polled", id);
+	if (!pdev)
+		goto err_free_buttons;
+
+	memset(&pdata, 0, sizeof(pdata));
+	pdata.poll_interval = poll_interval;
+	pdata.nbuttons = nbuttons;
+	pdata.buttons = p;
+
+	err = platform_device_add_data(pdev, &pdata, sizeof(pdata));
+	if (err)
+		goto err_put_pdev;
+
+	err = platform_device_add(pdev);
+	if (err)
+		goto err_put_pdev;
+
+	return;
+
+err_put_pdev:
+	platform_device_put(pdev);
+
+err_free_buttons:
+	kfree(p);
+}
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/ath79/dev-gpio-buttons.h linux-libre-2.6.38-gnu1/arch/mips/ath79/dev-gpio-buttons.h
--- linux-libre-2.6.37-gnu1/arch/mips/ath79/dev-gpio-buttons.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/ath79/dev-gpio-buttons.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,23 @@
+/*
+ *  Atheros AR71XX/AR724X/AR913X GPIO button support
+ *
+ *  Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
+ *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License version 2 as published
+ *  by the Free Software Foundation.
+ */
+
+#ifndef _ATH79_DEV_GPIO_BUTTONS_H
+#define _ATH79_DEV_GPIO_BUTTONS_H
+
+#include <linux/input.h>
+#include <linux/gpio_keys.h>
+
+void ath79_register_gpio_keys_polled(int id,
+				     unsigned poll_interval,
+				     unsigned nbuttons,
+				     struct gpio_keys_button *buttons);
+
+#endif /* _ATH79_DEV_GPIO_BUTTONS_H */
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/ath79/dev-leds-gpio.c linux-libre-2.6.38-gnu1/arch/mips/ath79/dev-leds-gpio.c
--- linux-libre-2.6.37-gnu1/arch/mips/ath79/dev-leds-gpio.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/ath79/dev-leds-gpio.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,56 @@
+/*
+ *  Atheros AR71XX/AR724X/AR913X common GPIO LEDs support
+ *
+ *  Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
+ *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License version 2 as published
+ *  by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+
+#include "dev-leds-gpio.h"
+
+void __init ath79_register_leds_gpio(int id,
+				     unsigned num_leds,
+				     struct gpio_led *leds)
+{
+	struct platform_device *pdev;
+	struct gpio_led_platform_data pdata;
+	struct gpio_led *p;
+	int err;
+
+	p = kmalloc(num_leds * sizeof(*p), GFP_KERNEL);
+	if (!p)
+		return;
+
+	memcpy(p, leds, num_leds * sizeof(*p));
+
+	pdev = platform_device_alloc("leds-gpio", id);
+	if (!pdev)
+		goto err_free_leds;
+
+	memset(&pdata, 0, sizeof(pdata));
+	pdata.num_leds = num_leds;
+	pdata.leds = p;
+
+	err = platform_device_add_data(pdev, &pdata, sizeof(pdata));
+	if (err)
+		goto err_put_pdev;
+
+	err = platform_device_add(pdev);
+	if (err)
+		goto err_put_pdev;
+
+	return;
+
+err_put_pdev:
+	platform_device_put(pdev);
+
+err_free_leds:
+	kfree(p);
+}
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/ath79/dev-leds-gpio.h linux-libre-2.6.38-gnu1/arch/mips/ath79/dev-leds-gpio.h
--- linux-libre-2.6.37-gnu1/arch/mips/ath79/dev-leds-gpio.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/ath79/dev-leds-gpio.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,21 @@
+/*
+ *  Atheros AR71XX/AR724X/AR913X common GPIO LEDs support
+ *
+ *  Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
+ *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License version 2 as published
+ *  by the Free Software Foundation.
+ */
+
+#ifndef _ATH79_DEV_LEDS_GPIO_H
+#define _ATH79_DEV_LEDS_GPIO_H
+
+#include <linux/leds.h>
+
+void ath79_register_leds_gpio(int id,
+			      unsigned num_leds,
+			      struct gpio_led *leds);
+
+#endif /* _ATH79_DEV_LEDS_GPIO_H */
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/ath79/dev-spi.c linux-libre-2.6.38-gnu1/arch/mips/ath79/dev-spi.c
--- linux-libre-2.6.37-gnu1/arch/mips/ath79/dev-spi.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/ath79/dev-spi.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,38 @@
+/*
+ *  Atheros AR71XX/AR724X/AR913X SPI controller device
+ *
+ *  Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
+ *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License version 2 as published
+ *  by the Free Software Foundation.
+ */
+
+#include <linux/platform_device.h>
+#include <asm/mach-ath79/ar71xx_regs.h>
+#include "dev-spi.h"
+
+static struct resource ath79_spi_resources[] = {
+	{
+		.start	= AR71XX_SPI_BASE,
+		.end	= AR71XX_SPI_BASE + AR71XX_SPI_SIZE - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct platform_device ath79_spi_device = {
+	.name		= "ath79-spi",
+	.id		= -1,
+	.resource	= ath79_spi_resources,
+	.num_resources	= ARRAY_SIZE(ath79_spi_resources),
+};
+
+void __init ath79_register_spi(struct ath79_spi_platform_data *pdata,
+			       struct spi_board_info const *info,
+			       unsigned n)
+{
+	spi_register_board_info(info, n);
+	ath79_spi_device.dev.platform_data = pdata;
+	platform_device_register(&ath79_spi_device);
+}
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/ath79/dev-spi.h linux-libre-2.6.38-gnu1/arch/mips/ath79/dev-spi.h
--- linux-libre-2.6.37-gnu1/arch/mips/ath79/dev-spi.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/ath79/dev-spi.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,22 @@
+/*
+ *  Atheros AR71XX/AR724X/AR913X SPI controller device
+ *
+ *  Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
+ *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License version 2 as published
+ *  by the Free Software Foundation.
+ */
+
+#ifndef _ATH79_DEV_SPI_H
+#define _ATH79_DEV_SPI_H
+
+#include <linux/spi/spi.h>
+#include <asm/mach-ath79/ath79_spi_platform.h>
+
+void ath79_register_spi(struct ath79_spi_platform_data *pdata,
+			 struct spi_board_info const *info,
+			 unsigned n);
+
+#endif /* _ATH79_DEV_SPI_H */
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/ath79/early_printk.c linux-libre-2.6.38-gnu1/arch/mips/ath79/early_printk.c
--- linux-libre-2.6.37-gnu1/arch/mips/ath79/early_printk.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/ath79/early_printk.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,36 @@
+/*
+ *  Atheros AR71XX/AR724X/AR913X SoC early printk support
+ *
+ *  Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
+ *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License version 2 as published
+ *  by the Free Software Foundation.
+ */
+
+#include <linux/io.h>
+#include <linux/serial_reg.h>
+#include <asm/addrspace.h>
+
+#include <asm/mach-ath79/ar71xx_regs.h>
+
+static inline void prom_wait_thre(void __iomem *base)
+{
+	u32 lsr;
+
+	do {
+		lsr = __raw_readl(base + UART_LSR * 4);
+		if (lsr & UART_LSR_THRE)
+			break;
+	} while (1);
+}
+
+void prom_putchar(unsigned char ch)
+{
+	void __iomem *base = (void __iomem *)(KSEG1ADDR(AR71XX_UART_BASE));
+
+	prom_wait_thre(base);
+	__raw_writel(ch, base + UART_TX * 4);
+	prom_wait_thre(base);
+}
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/ath79/gpio.c linux-libre-2.6.38-gnu1/arch/mips/ath79/gpio.c
--- linux-libre-2.6.37-gnu1/arch/mips/ath79/gpio.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/ath79/gpio.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,197 @@
+/*
+ *  Atheros AR71XX/AR724X/AR913X GPIO API support
+ *
+ *  Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
+ *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License version 2 as published
+ *  by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/spinlock.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/gpio.h>
+
+#include <asm/mach-ath79/ar71xx_regs.h>
+#include <asm/mach-ath79/ath79.h>
+#include "common.h"
+
+static void __iomem *ath79_gpio_base;
+static unsigned long ath79_gpio_count;
+static DEFINE_SPINLOCK(ath79_gpio_lock);
+
+static void __ath79_gpio_set_value(unsigned gpio, int value)
+{
+	void __iomem *base = ath79_gpio_base;
+
+	if (value)
+		__raw_writel(1 << gpio, base + AR71XX_GPIO_REG_SET);
+	else
+		__raw_writel(1 << gpio, base + AR71XX_GPIO_REG_CLEAR);
+}
+
+static int __ath79_gpio_get_value(unsigned gpio)
+{
+	return (__raw_readl(ath79_gpio_base + AR71XX_GPIO_REG_IN) >> gpio) & 1;
+}
+
+static int ath79_gpio_get_value(struct gpio_chip *chip, unsigned offset)
+{
+	return __ath79_gpio_get_value(offset);
+}
+
+static void ath79_gpio_set_value(struct gpio_chip *chip,
+				  unsigned offset, int value)
+{
+	__ath79_gpio_set_value(offset, value);
+}
+
+static int ath79_gpio_direction_input(struct gpio_chip *chip,
+				       unsigned offset)
+{
+	void __iomem *base = ath79_gpio_base;
+	unsigned long flags;
+
+	spin_lock_irqsave(&ath79_gpio_lock, flags);
+
+	__raw_writel(__raw_readl(base + AR71XX_GPIO_REG_OE) & ~(1 << offset),
+		     base + AR71XX_GPIO_REG_OE);
+
+	spin_unlock_irqrestore(&ath79_gpio_lock, flags);
+
+	return 0;
+}
+
+static int ath79_gpio_direction_output(struct gpio_chip *chip,
+					unsigned offset, int value)
+{
+	void __iomem *base = ath79_gpio_base;
+	unsigned long flags;
+
+	spin_lock_irqsave(&ath79_gpio_lock, flags);
+
+	if (value)
+		__raw_writel(1 << offset, base + AR71XX_GPIO_REG_SET);
+	else
+		__raw_writel(1 << offset, base + AR71XX_GPIO_REG_CLEAR);
+
+	__raw_writel(__raw_readl(base + AR71XX_GPIO_REG_OE) | (1 << offset),
+		     base + AR71XX_GPIO_REG_OE);
+
+	spin_unlock_irqrestore(&ath79_gpio_lock, flags);
+
+	return 0;
+}
+
+static struct gpio_chip ath79_gpio_chip = {
+	.label			= "ath79",
+	.get			= ath79_gpio_get_value,
+	.set			= ath79_gpio_set_value,
+	.direction_input	= ath79_gpio_direction_input,
+	.direction_output	= ath79_gpio_direction_output,
+	.base			= 0,
+};
+
+void ath79_gpio_function_enable(u32 mask)
+{
+	void __iomem *base = ath79_gpio_base;
+	unsigned long flags;
+
+	spin_lock_irqsave(&ath79_gpio_lock, flags);
+
+	__raw_writel(__raw_readl(base + AR71XX_GPIO_REG_FUNC) | mask,
+		     base + AR71XX_GPIO_REG_FUNC);
+	/* flush write */
+	__raw_readl(base + AR71XX_GPIO_REG_FUNC);
+
+	spin_unlock_irqrestore(&ath79_gpio_lock, flags);
+}
+
+void ath79_gpio_function_disable(u32 mask)
+{
+	void __iomem *base = ath79_gpio_base;
+	unsigned long flags;
+
+	spin_lock_irqsave(&ath79_gpio_lock, flags);
+
+	__raw_writel(__raw_readl(base + AR71XX_GPIO_REG_FUNC) & ~mask,
+		     base + AR71XX_GPIO_REG_FUNC);
+	/* flush write */
+	__raw_readl(base + AR71XX_GPIO_REG_FUNC);
+
+	spin_unlock_irqrestore(&ath79_gpio_lock, flags);
+}
+
+void ath79_gpio_function_setup(u32 set, u32 clear)
+{
+	void __iomem *base = ath79_gpio_base;
+	unsigned long flags;
+
+	spin_lock_irqsave(&ath79_gpio_lock, flags);
+
+	__raw_writel((__raw_readl(base + AR71XX_GPIO_REG_FUNC) & ~clear) | set,
+		     base + AR71XX_GPIO_REG_FUNC);
+	/* flush write */
+	__raw_readl(base + AR71XX_GPIO_REG_FUNC);
+
+	spin_unlock_irqrestore(&ath79_gpio_lock, flags);
+}
+
+void __init ath79_gpio_init(void)
+{
+	int err;
+
+	if (soc_is_ar71xx())
+		ath79_gpio_count = AR71XX_GPIO_COUNT;
+	else if (soc_is_ar724x())
+		ath79_gpio_count = AR724X_GPIO_COUNT;
+	else if (soc_is_ar913x())
+		ath79_gpio_count = AR913X_GPIO_COUNT;
+	else
+		BUG();
+
+	ath79_gpio_base = ioremap_nocache(AR71XX_GPIO_BASE, AR71XX_GPIO_SIZE);
+	ath79_gpio_chip.ngpio = ath79_gpio_count;
+
+	err = gpiochip_add(&ath79_gpio_chip);
+	if (err)
+		panic("cannot add AR71xx GPIO chip, error=%d", err);
+}
+
+int gpio_get_value(unsigned gpio)
+{
+	if (gpio < ath79_gpio_count)
+		return __ath79_gpio_get_value(gpio);
+
+	return __gpio_get_value(gpio);
+}
+EXPORT_SYMBOL(gpio_get_value);
+
+void gpio_set_value(unsigned gpio, int value)
+{
+	if (gpio < ath79_gpio_count)
+		__ath79_gpio_set_value(gpio, value);
+	else
+		__gpio_set_value(gpio, value);
+}
+EXPORT_SYMBOL(gpio_set_value);
+
+int gpio_to_irq(unsigned gpio)
+{
+	/* FIXME */
+	return -EINVAL;
+}
+EXPORT_SYMBOL(gpio_to_irq);
+
+int irq_to_gpio(unsigned irq)
+{
+	/* FIXME */
+	return -EINVAL;
+}
+EXPORT_SYMBOL(irq_to_gpio);
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/ath79/irq.c linux-libre-2.6.38-gnu1/arch/mips/ath79/irq.c
--- linux-libre-2.6.37-gnu1/arch/mips/ath79/irq.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/ath79/irq.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,187 @@
+/*
+ *  Atheros AR71xx/AR724x/AR913x specific interrupt handling
+ *
+ *  Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
+ *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
+ *
+ *  Parts of this file are based on Atheros' 2.6.15 BSP
+ *
+ *  This program is free software; you can 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/interrupt.h>
+#include <linux/irq.h>
+
+#include <asm/irq_cpu.h>
+#include <asm/mipsregs.h>
+
+#include <asm/mach-ath79/ath79.h>
+#include <asm/mach-ath79/ar71xx_regs.h>
+#include "common.h"
+
+static unsigned int ath79_ip2_flush_reg;
+static unsigned int ath79_ip3_flush_reg;
+
+static void ath79_misc_irq_handler(unsigned int irq, struct irq_desc *desc)
+{
+	void __iomem *base = ath79_reset_base;
+	u32 pending;
+
+	pending = __raw_readl(base + AR71XX_RESET_REG_MISC_INT_STATUS) &
+		  __raw_readl(base + AR71XX_RESET_REG_MISC_INT_ENABLE);
+
+	if (pending & MISC_INT_UART)
+		generic_handle_irq(ATH79_MISC_IRQ_UART);
+
+	else if (pending & MISC_INT_DMA)
+		generic_handle_irq(ATH79_MISC_IRQ_DMA);
+
+	else if (pending & MISC_INT_PERFC)
+		generic_handle_irq(ATH79_MISC_IRQ_PERFC);
+
+	else if (pending & MISC_INT_TIMER)
+		generic_handle_irq(ATH79_MISC_IRQ_TIMER);
+
+	else if (pending & MISC_INT_OHCI)
+		generic_handle_irq(ATH79_MISC_IRQ_OHCI);
+
+	else if (pending & MISC_INT_ERROR)
+		generic_handle_irq(ATH79_MISC_IRQ_ERROR);
+
+	else if (pending & MISC_INT_GPIO)
+		generic_handle_irq(ATH79_MISC_IRQ_GPIO);
+
+	else if (pending & MISC_INT_WDOG)
+		generic_handle_irq(ATH79_MISC_IRQ_WDOG);
+
+	else
+		spurious_interrupt();
+}
+
+static void ar71xx_misc_irq_unmask(unsigned int irq)
+{
+	void __iomem *base = ath79_reset_base;
+	u32 t;
+
+	irq -= ATH79_MISC_IRQ_BASE;
+
+	t = __raw_readl(base + AR71XX_RESET_REG_MISC_INT_ENABLE);
+	__raw_writel(t | (1 << irq), base + AR71XX_RESET_REG_MISC_INT_ENABLE);
+
+	/* flush write */
+	__raw_readl(base + AR71XX_RESET_REG_MISC_INT_ENABLE);
+}
+
+static void ar71xx_misc_irq_mask(unsigned int irq)
+{
+	void __iomem *base = ath79_reset_base;
+	u32 t;
+
+	irq -= ATH79_MISC_IRQ_BASE;
+
+	t = __raw_readl(base + AR71XX_RESET_REG_MISC_INT_ENABLE);
+	__raw_writel(t & ~(1 << irq), base + AR71XX_RESET_REG_MISC_INT_ENABLE);
+
+	/* flush write */
+	__raw_readl(base + AR71XX_RESET_REG_MISC_INT_ENABLE);
+}
+
+static void ar724x_misc_irq_ack(unsigned int irq)
+{
+	void __iomem *base = ath79_reset_base;
+	u32 t;
+
+	irq -= ATH79_MISC_IRQ_BASE;
+
+	t = __raw_readl(base + AR71XX_RESET_REG_MISC_INT_STATUS);
+	__raw_writel(t & ~(1 << irq), base + AR71XX_RESET_REG_MISC_INT_STATUS);
+
+	/* flush write */
+	__raw_readl(base + AR71XX_RESET_REG_MISC_INT_STATUS);
+}
+
+static struct irq_chip ath79_misc_irq_chip = {
+	.name		= "MISC",
+	.unmask		= ar71xx_misc_irq_unmask,
+	.mask		= ar71xx_misc_irq_mask,
+};
+
+static void __init ath79_misc_irq_init(void)
+{
+	void __iomem *base = ath79_reset_base;
+	int i;
+
+	__raw_writel(0, base + AR71XX_RESET_REG_MISC_INT_ENABLE);
+	__raw_writel(0, base + AR71XX_RESET_REG_MISC_INT_STATUS);
+
+	if (soc_is_ar71xx() || soc_is_ar913x())
+		ath79_misc_irq_chip.mask_ack = ar71xx_misc_irq_mask;
+	else if (soc_is_ar724x())
+		ath79_misc_irq_chip.ack = ar724x_misc_irq_ack;
+	else
+		BUG();
+
+	for (i = ATH79_MISC_IRQ_BASE;
+	     i < ATH79_MISC_IRQ_BASE + ATH79_MISC_IRQ_COUNT; i++) {
+		irq_desc[i].status = IRQ_DISABLED;
+		set_irq_chip_and_handler(i, &ath79_misc_irq_chip,
+					 handle_level_irq);
+	}
+
+	set_irq_chained_handler(ATH79_CPU_IRQ_MISC, ath79_misc_irq_handler);
+}
+
+asmlinkage void plat_irq_dispatch(void)
+{
+	unsigned long pending;
+
+	pending = read_c0_status() & read_c0_cause() & ST0_IM;
+
+	if (pending & STATUSF_IP7)
+		do_IRQ(ATH79_CPU_IRQ_TIMER);
+
+	else if (pending & STATUSF_IP2) {
+		ath79_ddr_wb_flush(ath79_ip2_flush_reg);
+		do_IRQ(ATH79_CPU_IRQ_IP2);
+	}
+
+	else if (pending & STATUSF_IP4)
+		do_IRQ(ATH79_CPU_IRQ_GE0);
+
+	else if (pending & STATUSF_IP5)
+		do_IRQ(ATH79_CPU_IRQ_GE1);
+
+	else if (pending & STATUSF_IP3) {
+		ath79_ddr_wb_flush(ath79_ip3_flush_reg);
+		do_IRQ(ATH79_CPU_IRQ_USB);
+	}
+
+	else if (pending & STATUSF_IP6)
+		do_IRQ(ATH79_CPU_IRQ_MISC);
+
+	else
+		spurious_interrupt();
+}
+
+void __init arch_init_irq(void)
+{
+	if (soc_is_ar71xx()) {
+		ath79_ip2_flush_reg = AR71XX_DDR_REG_FLUSH_PCI;
+		ath79_ip3_flush_reg = AR71XX_DDR_REG_FLUSH_USB;
+	} else if (soc_is_ar724x()) {
+		ath79_ip2_flush_reg = AR724X_DDR_REG_FLUSH_PCIE;
+		ath79_ip3_flush_reg = AR724X_DDR_REG_FLUSH_USB;
+	} else if (soc_is_ar913x()) {
+		ath79_ip2_flush_reg = AR913X_DDR_REG_FLUSH_WMAC;
+		ath79_ip3_flush_reg = AR913X_DDR_REG_FLUSH_USB;
+	} else
+		BUG();
+
+	cp0_perfcount_irq = ATH79_MISC_IRQ_PERFC;
+	mips_cpu_irq_init();
+	ath79_misc_irq_init();
+}
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/ath79/Kconfig linux-libre-2.6.38-gnu1/arch/mips/ath79/Kconfig
--- linux-libre-2.6.37-gnu1/arch/mips/ath79/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/ath79/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,50 @@
+if ATH79
+
+menu "Atheros AR71XX/AR724X/AR913X machine selection"
+
+config ATH79_MACH_AP81
+	bool "Atheros AP81 reference board"
+	select SOC_AR913X
+	select ATH79_DEV_AR913X_WMAC
+	select ATH79_DEV_GPIO_BUTTONS
+	select ATH79_DEV_LEDS_GPIO
+	select ATH79_DEV_SPI
+	help
+	  Say 'Y' here if you want your kernel to support the
+	  Atheros AP81 reference board.
+
+config ATH79_MACH_PB44
+	bool "Atheros PB44 reference board"
+	select SOC_AR71XX
+	select ATH79_DEV_GPIO_BUTTONS
+	select ATH79_DEV_LEDS_GPIO
+	select ATH79_DEV_SPI
+	help
+	  Say 'Y' here if you want your kernel to support the
+	  Atheros PB44 reference board.
+
+endmenu
+
+config SOC_AR71XX
+	def_bool n
+
+config SOC_AR724X
+	def_bool n
+
+config SOC_AR913X
+	def_bool n
+
+config ATH79_DEV_AR913X_WMAC
+	depends on SOC_AR913X
+	def_bool n
+
+config ATH79_DEV_GPIO_BUTTONS
+	def_bool n
+
+config ATH79_DEV_LEDS_GPIO
+	def_bool n
+
+config ATH79_DEV_SPI
+	def_bool n
+
+endif
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/ath79/mach-ap81.c linux-libre-2.6.38-gnu1/arch/mips/ath79/mach-ap81.c
--- linux-libre-2.6.37-gnu1/arch/mips/ath79/mach-ap81.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/ath79/mach-ap81.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,98 @@
+/*
+ *  Atheros AP81 board support
+ *
+ *  Copyright (C) 2009-2010 Gabor Juhos <juhosg@openwrt.org>
+ *  Copyright (C) 2009 Imre Kaloz <kaloz@openwrt.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License version 2 as published
+ *  by the Free Software Foundation.
+ */
+
+#include "machtypes.h"
+#include "dev-ar913x-wmac.h"
+#include "dev-gpio-buttons.h"
+#include "dev-leds-gpio.h"
+#include "dev-spi.h"
+
+#define AP81_GPIO_LED_STATUS	1
+#define AP81_GPIO_LED_AOSS	3
+#define AP81_GPIO_LED_WLAN	6
+#define AP81_GPIO_LED_POWER	14
+
+#define AP81_GPIO_BTN_SW4	12
+#define AP81_GPIO_BTN_SW1	21
+
+#define AP81_KEYS_POLL_INTERVAL		20	/* msecs */
+#define AP81_KEYS_DEBOUNCE_INTERVAL	(3 * AP81_KEYS_POLL_INTERVAL)
+
+#define AP81_CAL_DATA_ADDR	0x1fff1000
+
+static struct gpio_led ap81_leds_gpio[] __initdata = {
+	{
+		.name		= "ap81:green:status",
+		.gpio		= AP81_GPIO_LED_STATUS,
+		.active_low	= 1,
+	}, {
+		.name		= "ap81:amber:aoss",
+		.gpio		= AP81_GPIO_LED_AOSS,
+		.active_low	= 1,
+	}, {
+		.name		= "ap81:green:wlan",
+		.gpio		= AP81_GPIO_LED_WLAN,
+		.active_low	= 1,
+	}, {
+		.name		= "ap81:green:power",
+		.gpio		= AP81_GPIO_LED_POWER,
+		.active_low	= 1,
+	}
+};
+
+static struct gpio_keys_button ap81_gpio_keys[] __initdata = {
+	{
+		.desc		= "sw1",
+		.type		= EV_KEY,
+		.code		= BTN_0,
+		.debounce_interval = AP81_KEYS_DEBOUNCE_INTERVAL,
+		.gpio		= AP81_GPIO_BTN_SW1,
+		.active_low	= 1,
+	} , {
+		.desc		= "sw4",
+		.type		= EV_KEY,
+		.code		= BTN_1,
+		.debounce_interval = AP81_KEYS_DEBOUNCE_INTERVAL,
+		.gpio		= AP81_GPIO_BTN_SW4,
+		.active_low	= 1,
+	}
+};
+
+static struct spi_board_info ap81_spi_info[] = {
+	{
+		.bus_num	= 0,
+		.chip_select	= 0,
+		.max_speed_hz	= 25000000,
+		.modalias	= "m25p64",
+	}
+};
+
+static struct ath79_spi_platform_data ap81_spi_data = {
+	.bus_num	= 0,
+	.num_chipselect	= 1,
+};
+
+static void __init ap81_setup(void)
+{
+	u8 *cal_data = (u8 *) KSEG1ADDR(AP81_CAL_DATA_ADDR);
+
+	ath79_register_leds_gpio(-1, ARRAY_SIZE(ap81_leds_gpio),
+				 ap81_leds_gpio);
+	ath79_register_gpio_keys_polled(-1, AP81_KEYS_POLL_INTERVAL,
+					ARRAY_SIZE(ap81_gpio_keys),
+					ap81_gpio_keys);
+	ath79_register_spi(&ap81_spi_data, ap81_spi_info,
+			   ARRAY_SIZE(ap81_spi_info));
+	ath79_register_ar913x_wmac(cal_data);
+}
+
+MIPS_MACHINE(ATH79_MACH_AP81, "AP81", "Atheros AP81 reference board",
+	     ap81_setup);
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/ath79/mach-pb44.c linux-libre-2.6.38-gnu1/arch/mips/ath79/mach-pb44.c
--- linux-libre-2.6.37-gnu1/arch/mips/ath79/mach-pb44.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/ath79/mach-pb44.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,118 @@
+/*
+ *  Atheros PB44 reference board support
+ *
+ *  Copyright (C) 2009-2010 Gabor Juhos <juhosg@openwrt.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License version 2 as published
+ *  by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/i2c.h>
+#include <linux/i2c-gpio.h>
+#include <linux/i2c/pcf857x.h>
+
+#include "machtypes.h"
+#include "dev-gpio-buttons.h"
+#include "dev-leds-gpio.h"
+#include "dev-spi.h"
+
+#define PB44_GPIO_I2C_SCL	0
+#define PB44_GPIO_I2C_SDA	1
+
+#define PB44_GPIO_EXP_BASE	16
+#define PB44_GPIO_SW_RESET	(PB44_GPIO_EXP_BASE + 6)
+#define PB44_GPIO_SW_JUMP	(PB44_GPIO_EXP_BASE + 8)
+#define PB44_GPIO_LED_JUMP1	(PB44_GPIO_EXP_BASE + 9)
+#define PB44_GPIO_LED_JUMP2	(PB44_GPIO_EXP_BASE + 10)
+
+#define PB44_KEYS_POLL_INTERVAL		20	/* msecs */
+#define PB44_KEYS_DEBOUNCE_INTERVAL	(3 * PB44_KEYS_POLL_INTERVAL)
+
+static struct i2c_gpio_platform_data pb44_i2c_gpio_data = {
+	.sda_pin        = PB44_GPIO_I2C_SDA,
+	.scl_pin        = PB44_GPIO_I2C_SCL,
+};
+
+static struct platform_device pb44_i2c_gpio_device = {
+	.name		= "i2c-gpio",
+	.id		= 0,
+	.dev = {
+		.platform_data	= &pb44_i2c_gpio_data,
+	}
+};
+
+static struct pcf857x_platform_data pb44_pcf857x_data = {
+	.gpio_base	= PB44_GPIO_EXP_BASE,
+};
+
+static struct i2c_board_info pb44_i2c_board_info[] __initdata = {
+	{
+		I2C_BOARD_INFO("pcf8575", 0x20),
+		.platform_data  = &pb44_pcf857x_data,
+	},
+};
+
+static struct gpio_led pb44_leds_gpio[] __initdata = {
+	{
+		.name		= "pb44:amber:jump1",
+		.gpio		= PB44_GPIO_LED_JUMP1,
+		.active_low	= 1,
+	}, {
+		.name		= "pb44:green:jump2",
+		.gpio		= PB44_GPIO_LED_JUMP2,
+		.active_low	= 1,
+	},
+};
+
+static struct gpio_keys_button pb44_gpio_keys[] __initdata = {
+	{
+		.desc		= "soft_reset",
+		.type		= EV_KEY,
+		.code		= KEY_RESTART,
+		.debounce_interval = PB44_KEYS_DEBOUNCE_INTERVAL,
+		.gpio		= PB44_GPIO_SW_RESET,
+		.active_low	= 1,
+	} , {
+		.desc		= "jumpstart",
+		.type		= EV_KEY,
+		.code		= KEY_WPS_BUTTON,
+		.debounce_interval = PB44_KEYS_DEBOUNCE_INTERVAL,
+		.gpio		= PB44_GPIO_SW_JUMP,
+		.active_low	= 1,
+	}
+};
+
+static struct spi_board_info pb44_spi_info[] = {
+	{
+		.bus_num	= 0,
+		.chip_select	= 0,
+		.max_speed_hz	= 25000000,
+		.modalias	= "m25p64",
+	},
+};
+
+static struct ath79_spi_platform_data pb44_spi_data = {
+	.bus_num		= 0,
+	.num_chipselect		= 1,
+};
+
+static void __init pb44_init(void)
+{
+	i2c_register_board_info(0, pb44_i2c_board_info,
+				ARRAY_SIZE(pb44_i2c_board_info));
+	platform_device_register(&pb44_i2c_gpio_device);
+
+	ath79_register_leds_gpio(-1, ARRAY_SIZE(pb44_leds_gpio),
+				 pb44_leds_gpio);
+	ath79_register_gpio_keys_polled(-1, PB44_KEYS_POLL_INTERVAL,
+					ARRAY_SIZE(pb44_gpio_keys),
+					pb44_gpio_keys);
+	ath79_register_spi(&pb44_spi_data, pb44_spi_info,
+			   ARRAY_SIZE(pb44_spi_info));
+}
+
+MIPS_MACHINE(ATH79_MACH_PB44, "PB44", "Atheros PB44 reference board",
+	     pb44_init);
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/ath79/machtypes.h linux-libre-2.6.38-gnu1/arch/mips/ath79/machtypes.h
--- linux-libre-2.6.37-gnu1/arch/mips/ath79/machtypes.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/ath79/machtypes.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,23 @@
+/*
+ *  Atheros AR71XX/AR724X/AR913X machine type definitions
+ *
+ *  Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
+ *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License version 2 as published
+ *  by the Free Software Foundation.
+ */
+
+#ifndef _ATH79_MACHTYPE_H
+#define _ATH79_MACHTYPE_H
+
+#include <asm/mips_machine.h>
+
+enum ath79_mach_type {
+	ATH79_MACH_GENERIC = 0,
+	ATH79_MACH_AP81,		/* Atheros AP81 reference board */
+	ATH79_MACH_PB44,		/* Atheros PB44 reference board */
+};
+
+#endif /* _ATH79_MACHTYPE_H */
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/ath79/Makefile linux-libre-2.6.38-gnu1/arch/mips/ath79/Makefile
--- linux-libre-2.6.37-gnu1/arch/mips/ath79/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/ath79/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,28 @@
+#
+# Makefile for the Atheros AR71XX/AR724X/AR913X specific parts of the kernel
+#
+# Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org>
+# Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 as published
+# by the Free Software Foundation.
+
+obj-y	:= prom.o setup.o irq.o common.o clock.o gpio.o
+
+obj-$(CONFIG_EARLY_PRINTK)		+= early_printk.o
+
+#
+# Devices
+#
+obj-y					+= dev-common.o
+obj-$(CONFIG_ATH79_DEV_AR913X_WMAC)	+= dev-ar913x-wmac.o
+obj-$(CONFIG_ATH79_DEV_GPIO_BUTTONS)	+= dev-gpio-buttons.o
+obj-$(CONFIG_ATH79_DEV_LEDS_GPIO)	+= dev-leds-gpio.o
+obj-$(CONFIG_ATH79_DEV_SPI)		+= dev-spi.o
+
+#
+# Machines
+#
+obj-$(CONFIG_ATH79_MACH_AP81)		+= mach-ap81.o
+obj-$(CONFIG_ATH79_MACH_PB44)		+= mach-pb44.o
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/ath79/Platform linux-libre-2.6.38-gnu1/arch/mips/ath79/Platform
--- linux-libre-2.6.37-gnu1/arch/mips/ath79/Platform	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/ath79/Platform	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,7 @@
+#
+# Atheros AR71xx/AR724x/AR913x
+#
+
+platform-$(CONFIG_ATH79)	+= ath79/
+cflags-$(CONFIG_ATH79)		+= -I$(srctree)/arch/mips/include/asm/mach-ath79
+load-$(CONFIG_ATH79)		= 0xffffffff80060000
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/ath79/prom.c linux-libre-2.6.38-gnu1/arch/mips/ath79/prom.c
--- linux-libre-2.6.37-gnu1/arch/mips/ath79/prom.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/ath79/prom.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,57 @@
+/*
+ *  Atheros AR71XX/AR724X/AR913X specific prom routines
+ *
+ *  Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
+ *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License version 2 as published
+ *  by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/string.h>
+
+#include <asm/bootinfo.h>
+#include <asm/addrspace.h>
+
+#include "common.h"
+
+static inline int is_valid_ram_addr(void *addr)
+{
+	if (((u32) addr > KSEG0) &&
+	    ((u32) addr < (KSEG0 + ATH79_MEM_SIZE_MAX)))
+		return 1;
+
+	if (((u32) addr > KSEG1) &&
+	    ((u32) addr < (KSEG1 + ATH79_MEM_SIZE_MAX)))
+		return 1;
+
+	return 0;
+}
+
+static __init void ath79_prom_init_cmdline(int argc, char **argv)
+{
+	int i;
+
+	if (!is_valid_ram_addr(argv))
+		return;
+
+	for (i = 0; i < argc; i++)
+		if (is_valid_ram_addr(argv[i])) {
+			strlcat(arcs_cmdline, " ", sizeof(arcs_cmdline));
+			strlcat(arcs_cmdline, argv[i], sizeof(arcs_cmdline));
+		}
+}
+
+void __init prom_init(void)
+{
+	ath79_prom_init_cmdline(fw_arg0, (char **)fw_arg1);
+}
+
+void __init prom_free_prom_memory(void)
+{
+	/* We do not have to prom memory to free */
+}
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/ath79/setup.c linux-libre-2.6.38-gnu1/arch/mips/ath79/setup.c
--- linux-libre-2.6.37-gnu1/arch/mips/ath79/setup.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/ath79/setup.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,206 @@
+/*
+ *  Atheros AR71XX/AR724X/AR913X specific setup
+ *
+ *  Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org>
+ *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
+ *
+ *  Parts of this file are based on Atheros' 2.6.15 BSP
+ *
+ *  This program is free software; you can 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/bootmem.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+
+#include <asm/bootinfo.h>
+#include <asm/time.h>		/* for mips_hpt_frequency */
+#include <asm/reboot.h>		/* for _machine_{restart,halt} */
+#include <asm/mips_machine.h>
+
+#include <asm/mach-ath79/ath79.h>
+#include <asm/mach-ath79/ar71xx_regs.h>
+#include "common.h"
+#include "dev-common.h"
+#include "machtypes.h"
+
+#define ATH79_SYS_TYPE_LEN	64
+
+#define AR71XX_BASE_FREQ	40000000
+#define AR724X_BASE_FREQ	5000000
+#define AR913X_BASE_FREQ	5000000
+
+static char ath79_sys_type[ATH79_SYS_TYPE_LEN];
+
+static void ath79_restart(char *command)
+{
+	ath79_device_reset_set(AR71XX_RESET_FULL_CHIP);
+	for (;;)
+		if (cpu_wait)
+			cpu_wait();
+}
+
+static void ath79_halt(void)
+{
+	while (1)
+		cpu_wait();
+}
+
+static void __init ath79_detect_mem_size(void)
+{
+	unsigned long size;
+
+	for (size = ATH79_MEM_SIZE_MIN; size < ATH79_MEM_SIZE_MAX;
+	     size <<= 1) {
+		if (!memcmp(ath79_detect_mem_size,
+			    ath79_detect_mem_size + size, 1024))
+			break;
+	}
+
+	add_memory_region(0, size, BOOT_MEM_RAM);
+}
+
+static void __init ath79_detect_sys_type(void)
+{
+	char *chip = "????";
+	u32 id;
+	u32 major;
+	u32 minor;
+	u32 rev = 0;
+
+	id = ath79_reset_rr(AR71XX_RESET_REG_REV_ID);
+	major = id & REV_ID_MAJOR_MASK;
+
+	switch (major) {
+	case REV_ID_MAJOR_AR71XX:
+		minor = id & AR71XX_REV_ID_MINOR_MASK;
+		rev = id >> AR71XX_REV_ID_REVISION_SHIFT;
+		rev &= AR71XX_REV_ID_REVISION_MASK;
+		switch (minor) {
+		case AR71XX_REV_ID_MINOR_AR7130:
+			ath79_soc = ATH79_SOC_AR7130;
+			chip = "7130";
+			break;
+
+		case AR71XX_REV_ID_MINOR_AR7141:
+			ath79_soc = ATH79_SOC_AR7141;
+			chip = "7141";
+			break;
+
+		case AR71XX_REV_ID_MINOR_AR7161:
+			ath79_soc = ATH79_SOC_AR7161;
+			chip = "7161";
+			break;
+		}
+		break;
+
+	case REV_ID_MAJOR_AR7240:
+		ath79_soc = ATH79_SOC_AR7240;
+		chip = "7240";
+		rev = (id & AR724X_REV_ID_REVISION_MASK);
+		break;
+
+	case REV_ID_MAJOR_AR7241:
+		ath79_soc = ATH79_SOC_AR7241;
+		chip = "7241";
+		rev = (id & AR724X_REV_ID_REVISION_MASK);
+		break;
+
+	case REV_ID_MAJOR_AR7242:
+		ath79_soc = ATH79_SOC_AR7242;
+		chip = "7242";
+		rev = (id & AR724X_REV_ID_REVISION_MASK);
+		break;
+
+	case REV_ID_MAJOR_AR913X:
+		minor = id & AR913X_REV_ID_MINOR_MASK;
+		rev = id >> AR913X_REV_ID_REVISION_SHIFT;
+		rev &= AR913X_REV_ID_REVISION_MASK;
+		switch (minor) {
+		case AR913X_REV_ID_MINOR_AR9130:
+			ath79_soc = ATH79_SOC_AR9130;
+			chip = "9130";
+			break;
+
+		case AR913X_REV_ID_MINOR_AR9132:
+			ath79_soc = ATH79_SOC_AR9132;
+			chip = "9132";
+			break;
+		}
+		break;
+
+	default:
+		panic("ath79: unknown SoC, id:0x%08x\n", id);
+	}
+
+	sprintf(ath79_sys_type, "Atheros AR%s rev %u", chip, rev);
+	pr_info("SoC: %s\n", ath79_sys_type);
+}
+
+const char *get_system_type(void)
+{
+	return ath79_sys_type;
+}
+
+unsigned int __cpuinit get_c0_compare_int(void)
+{
+	return CP0_LEGACY_COMPARE_IRQ;
+}
+
+void __init plat_mem_setup(void)
+{
+	set_io_port_base(KSEG1);
+
+	ath79_reset_base = ioremap_nocache(AR71XX_RESET_BASE,
+					   AR71XX_RESET_SIZE);
+	ath79_pll_base = ioremap_nocache(AR71XX_PLL_BASE,
+					 AR71XX_PLL_SIZE);
+	ath79_ddr_base = ioremap_nocache(AR71XX_DDR_CTRL_BASE,
+					 AR71XX_DDR_CTRL_SIZE);
+
+	ath79_detect_sys_type();
+	ath79_detect_mem_size();
+	ath79_clocks_init();
+
+	_machine_restart = ath79_restart;
+	_machine_halt = ath79_halt;
+	pm_power_off = ath79_halt;
+}
+
+void __init plat_time_init(void)
+{
+	struct clk *clk;
+
+	clk = clk_get(NULL, "cpu");
+	if (IS_ERR(clk))
+		panic("unable to get CPU clock, err=%ld", PTR_ERR(clk));
+
+	mips_hpt_frequency = clk_get_rate(clk) / 2;
+}
+
+static int __init ath79_setup(void)
+{
+	ath79_gpio_init();
+	ath79_register_uart();
+	ath79_register_wdt();
+
+	mips_machine_setup();
+
+	return 0;
+}
+
+arch_initcall(ath79_setup);
+
+static void __init ath79_generic_init(void)
+{
+	/* Nothing to do */
+}
+
+MIPS_MACHINE(ATH79_MACH_GENERIC,
+	     "Generic",
+	     "Generic AR71XX/AR724X/AR913X based board",
+	     ath79_generic_init);
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/configs/ar7_defconfig linux-libre-2.6.38-gnu1/arch/mips/configs/ar7_defconfig
--- linux-libre-2.6.37-gnu1/arch/mips/configs/ar7_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/configs/ar7_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -14,7 +14,7 @@ CONFIG_SYSFS_DEPRECATED_V2=y
 CONFIG_RELAY=y
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_RD_LZMA=y
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_KALLSYMS is not set
 # CONFIG_ELF_CORE is not set
 # CONFIG_PCSPKR_PLATFORM is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/configs/bcm47xx_defconfig linux-libre-2.6.38-gnu1/arch/mips/configs/bcm47xx_defconfig
--- linux-libre-2.6.37-gnu1/arch/mips/configs/bcm47xx_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/configs/bcm47xx_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -21,7 +21,7 @@ CONFIG_CGROUP_CPUACCT=y
 CONFIG_RELAY=y
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_RD_LZMA=y
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 CONFIG_SLAB=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/configs/bcm63xx_defconfig linux-libre-2.6.38-gnu1/arch/mips/configs/bcm63xx_defconfig
--- linux-libre-2.6.37-gnu1/arch/mips/configs/bcm63xx_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/configs/bcm63xx_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -10,7 +10,7 @@ CONFIG_EXPERIMENTAL=y
 # CONFIG_SWAP is not set
 CONFIG_TINY_RCU=y
 CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_PCSPKR_PLATFORM is not set
 # CONFIG_FUTEX is not set
 # CONFIG_EPOLL is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/configs/bigsur_defconfig linux-libre-2.6.38-gnu1/arch/mips/configs/bigsur_defconfig
--- linux-libre-2.6.37-gnu1/arch/mips/configs/bigsur_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/configs/bigsur_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -26,7 +26,7 @@ CONFIG_PID_NS=y
 CONFIG_NET_NS=y
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_SYSCTL_SYSCALL is not set
 # CONFIG_PCSPKR_PLATFORM is not set
 CONFIG_SLAB=y
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/configs/capcella_defconfig linux-libre-2.6.38-gnu1/arch/mips/configs/capcella_defconfig
--- linux-libre-2.6.37-gnu1/arch/mips/configs/capcella_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/configs/capcella_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -4,7 +4,7 @@ CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 CONFIG_SLAB=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/configs/cavium-octeon_defconfig linux-libre-2.6.38-gnu1/arch/mips/configs/cavium-octeon_defconfig
--- linux-libre-2.6.37-gnu1/arch/mips/configs/cavium-octeon_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/configs/cavium-octeon_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -15,7 +15,7 @@ CONFIG_SYSFS_DEPRECATED_V2=y
 CONFIG_RELAY=y
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_PCSPKR_PLATFORM is not set
 CONFIG_SLAB=y
 CONFIG_MODULES=y
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/configs/cobalt_defconfig linux-libre-2.6.38-gnu1/arch/mips/configs/cobalt_defconfig
--- linux-libre-2.6.37-gnu1/arch/mips/configs/cobalt_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/configs/cobalt_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -4,7 +4,7 @@ CONFIG_SYSVIPC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_RELAY=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_BLK_DEV_BSG is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/configs/db1000_defconfig linux-libre-2.6.38-gnu1/arch/mips/configs/db1000_defconfig
--- linux-libre-2.6.37-gnu1/arch/mips/configs/db1000_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/configs/db1000_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -11,7 +11,7 @@ CONFIG_POSIX_MQUEUE=y
 CONFIG_TINY_RCU=y
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_KALLSYMS is not set
 # CONFIG_PCSPKR_PLATFORM is not set
 # CONFIG_VM_EVENT_COUNTERS is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/configs/db1100_defconfig linux-libre-2.6.38-gnu1/arch/mips/configs/db1100_defconfig
--- linux-libre-2.6.37-gnu1/arch/mips/configs/db1100_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/configs/db1100_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -11,7 +11,7 @@ CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
 CONFIG_TINY_RCU=y
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_SYSCTL_SYSCALL is not set
 # CONFIG_KALLSYMS is not set
 # CONFIG_PCSPKR_PLATFORM is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/configs/db1200_defconfig linux-libre-2.6.38-gnu1/arch/mips/configs/db1200_defconfig
--- linux-libre-2.6.37-gnu1/arch/mips/configs/db1200_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/configs/db1200_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -12,7 +12,7 @@ CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
 CONFIG_TINY_RCU=y
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_SYSCTL_SYSCALL is not set
 # CONFIG_KALLSYMS is not set
 # CONFIG_PCSPKR_PLATFORM is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/configs/db1500_defconfig linux-libre-2.6.38-gnu1/arch/mips/configs/db1500_defconfig
--- linux-libre-2.6.37-gnu1/arch/mips/configs/db1500_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/configs/db1500_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -10,7 +10,7 @@ CONFIG_LOCALVERSION="-db1500"
 CONFIG_KERNEL_LZMA=y
 CONFIG_SYSVIPC=y
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_KALLSYMS is not set
 # CONFIG_PCSPKR_PLATFORM is not set
 # CONFIG_VM_EVENT_COUNTERS is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/configs/db1550_defconfig linux-libre-2.6.38-gnu1/arch/mips/configs/db1550_defconfig
--- linux-libre-2.6.37-gnu1/arch/mips/configs/db1550_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/configs/db1550_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -11,7 +11,7 @@ CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
 CONFIG_TINY_RCU=y
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_SYSCTL_SYSCALL is not set
 # CONFIG_KALLSYMS is not set
 # CONFIG_PCSPKR_PLATFORM is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/configs/decstation_defconfig linux-libre-2.6.38-gnu1/arch/mips/configs/decstation_defconfig
--- linux-libre-2.6.37-gnu1/arch/mips/configs/decstation_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/configs/decstation_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -4,7 +4,7 @@ CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_SYSCTL_SYSCALL is not set
 # CONFIG_HOTPLUG is not set
 CONFIG_SLAB=y
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/configs/e55_defconfig linux-libre-2.6.38-gnu1/arch/mips/configs/e55_defconfig
--- linux-libre-2.6.37-gnu1/arch/mips/configs/e55_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/configs/e55_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -4,7 +4,7 @@ CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_HOTPLUG is not set
 CONFIG_SLAB=y
 CONFIG_MODULES=y
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/configs/fuloong2e_defconfig linux-libre-2.6.38-gnu1/arch/mips/configs/fuloong2e_defconfig
--- linux-libre-2.6.37-gnu1/arch/mips/configs/fuloong2e_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/configs/fuloong2e_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -17,7 +17,7 @@ CONFIG_NAMESPACES=y
 CONFIG_USER_NS=y
 CONFIG_PID_NS=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_PCSPKR_PLATFORM is not set
 # CONFIG_COMPAT_BRK is not set
 CONFIG_SLAB=y
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/configs/gpr_defconfig linux-libre-2.6.38-gnu1/arch/mips/configs/gpr_defconfig
--- linux-libre-2.6.37-gnu1/arch/mips/configs/gpr_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/configs/gpr_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -11,7 +11,7 @@ CONFIG_BSD_PROCESS_ACCT_V3=y
 CONFIG_RELAY=y
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 CONFIG_SLAB=y
 CONFIG_PROFILING=y
 CONFIG_MODULES=y
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/configs/ip22_defconfig linux-libre-2.6.38-gnu1/arch/mips/configs/ip22_defconfig
--- linux-libre-2.6.37-gnu1/arch/mips/configs/ip22_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/configs/ip22_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -17,7 +17,7 @@ CONFIG_IPC_NS=y
 CONFIG_USER_NS=y
 CONFIG_PID_NS=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_HOTPLUG is not set
 # CONFIG_PCSPKR_PLATFORM is not set
 # CONFIG_COMPAT_BRK is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/configs/ip27_defconfig linux-libre-2.6.38-gnu1/arch/mips/configs/ip27_defconfig
--- linux-libre-2.6.37-gnu1/arch/mips/configs/ip27_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/configs/ip27_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -15,7 +15,7 @@ CONFIG_CGROUPS=y
 CONFIG_CPUSETS=y
 CONFIG_RELAY=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_PCSPKR_PLATFORM is not set
 CONFIG_SLAB=y
 CONFIG_MODULES=y
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/configs/ip28_defconfig linux-libre-2.6.38-gnu1/arch/mips/configs/ip28_defconfig
--- linux-libre-2.6.37-gnu1/arch/mips/configs/ip28_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/configs/ip28_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -8,7 +8,7 @@ CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_RELAY=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_HOTPLUG is not set
 CONFIG_SLAB=y
 CONFIG_MODULES=y
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/configs/ip32_defconfig linux-libre-2.6.38-gnu1/arch/mips/configs/ip32_defconfig
--- linux-libre-2.6.37-gnu1/arch/mips/configs/ip32_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/configs/ip32_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -10,7 +10,7 @@ CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_SYSFS_DEPRECATED_V2=y
 CONFIG_RELAY=y
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 CONFIG_SLAB=y
 CONFIG_PROFILING=y
 CONFIG_OPROFILE=m
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/configs/jazz_defconfig linux-libre-2.6.38-gnu1/arch/mips/configs/jazz_defconfig
--- linux-libre-2.6.37-gnu1/arch/mips/configs/jazz_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/configs/jazz_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -10,7 +10,7 @@ CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_RELAY=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_SYSCTL_SYSCALL is not set
 CONFIG_SLAB=y
 CONFIG_MODULES=y
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/configs/jmr3927_defconfig linux-libre-2.6.38-gnu1/arch/mips/configs/jmr3927_defconfig
--- linux-libre-2.6.37-gnu1/arch/mips/configs/jmr3927_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/configs/jmr3927_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -4,7 +4,7 @@ CONFIG_TOSHIBA_JMR3927=y
 CONFIG_SYSVIPC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_HOTPLUG is not set
 # CONFIG_PCSPKR_PLATFORM is not set
 CONFIG_SLAB=y
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/configs/lasat_defconfig linux-libre-2.6.38-gnu1/arch/mips/configs/lasat_defconfig
--- linux-libre-2.6.37-gnu1/arch/mips/configs/lasat_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/configs/lasat_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -8,7 +8,7 @@ CONFIG_HZ_1000=y
 CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_SYSCTL_SYSCALL is not set
 # CONFIG_KALLSYMS is not set
 # CONFIG_HOTPLUG is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/configs/lemote2f_defconfig linux-libre-2.6.38-gnu1/arch/mips/configs/lemote2f_defconfig
--- linux-libre-2.6.37-gnu1/arch/mips/configs/lemote2f_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/configs/lemote2f_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -21,7 +21,7 @@ CONFIG_BLK_DEV_INITRD=y
 CONFIG_RD_BZIP2=y
 CONFIG_RD_LZMA=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 CONFIG_PROFILING=y
 CONFIG_OPROFILE=m
 CONFIG_MODULES=y
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/configs/malta_defconfig linux-libre-2.6.38-gnu1/arch/mips/configs/malta_defconfig
--- linux-libre-2.6.37-gnu1/arch/mips/configs/malta_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/configs/malta_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -15,7 +15,7 @@ CONFIG_UTS_NS=y
 CONFIG_IPC_NS=y
 CONFIG_PID_NS=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_SYSCTL_SYSCALL is not set
 # CONFIG_COMPAT_BRK is not set
 CONFIG_SLAB=y
@@ -369,7 +369,10 @@ CONFIG_VT_HW_CONSOLE_BINDING=y
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
 # CONFIG_HWMON is not set
+CONFIG_FB=y
+CONFIG_FB_CIRRUS=y
 # CONFIG_VGA_CONSOLE is not set
+CONFIG_FRAMEBUFFER_CONSOLE=y
 CONFIG_HID=m
 CONFIG_LEDS_CLASS=m
 CONFIG_LEDS_TRIGGER_TIMER=m
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/configs/markeins_defconfig linux-libre-2.6.38-gnu1/arch/mips/configs/markeins_defconfig
--- linux-libre-2.6.37-gnu1/arch/mips/configs/markeins_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/configs/markeins_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -9,7 +9,7 @@ CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 CONFIG_SLAB=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/configs/mipssim_defconfig linux-libre-2.6.38-gnu1/arch/mips/configs/mipssim_defconfig
--- linux-libre-2.6.37-gnu1/arch/mips/configs/mipssim_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/configs/mipssim_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -7,7 +7,7 @@ CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 CONFIG_SLAB=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/configs/mpc30x_defconfig linux-libre-2.6.38-gnu1/arch/mips/configs/mpc30x_defconfig
--- linux-libre-2.6.37-gnu1/arch/mips/configs/mpc30x_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/configs/mpc30x_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@ CONFIG_SYSVIPC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_RELAY=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 CONFIG_SLAB=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/configs/msp71xx_defconfig linux-libre-2.6.38-gnu1/arch/mips/configs/msp71xx_defconfig
--- linux-libre-2.6.37-gnu1/arch/mips/configs/msp71xx_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/configs/msp71xx_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -8,7 +8,7 @@ CONFIG_LOCALVERSION="-pmc"
 CONFIG_SYSVIPC=y
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_SHMEM is not set
 CONFIG_SLAB=y
 CONFIG_MODULES=y
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/configs/mtx1_defconfig linux-libre-2.6.38-gnu1/arch/mips/configs/mtx1_defconfig
--- linux-libre-2.6.37-gnu1/arch/mips/configs/mtx1_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/configs/mtx1_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -11,7 +11,7 @@ CONFIG_AUDIT=y
 CONFIG_RELAY=y
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 CONFIG_SLAB=y
 CONFIG_PROFILING=y
 CONFIG_OPROFILE=m
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/configs/pb1100_defconfig linux-libre-2.6.38-gnu1/arch/mips/configs/pb1100_defconfig
--- linux-libre-2.6.37-gnu1/arch/mips/configs/pb1100_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/configs/pb1100_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -11,7 +11,7 @@ CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
 CONFIG_TINY_RCU=y
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_SYSCTL_SYSCALL is not set
 # CONFIG_KALLSYMS is not set
 # CONFIG_PCSPKR_PLATFORM is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/configs/pb1200_defconfig linux-libre-2.6.38-gnu1/arch/mips/configs/pb1200_defconfig
--- linux-libre-2.6.37-gnu1/arch/mips/configs/pb1200_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/configs/pb1200_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -12,7 +12,7 @@ CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
 CONFIG_TINY_RCU=y
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_SYSCTL_SYSCALL is not set
 # CONFIG_KALLSYMS is not set
 # CONFIG_PCSPKR_PLATFORM is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/configs/pb1500_defconfig linux-libre-2.6.38-gnu1/arch/mips/configs/pb1500_defconfig
--- linux-libre-2.6.37-gnu1/arch/mips/configs/pb1500_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/configs/pb1500_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -11,7 +11,7 @@ CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
 CONFIG_TINY_RCU=y
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_SYSCTL_SYSCALL is not set
 # CONFIG_KALLSYMS is not set
 # CONFIG_PCSPKR_PLATFORM is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/configs/pb1550_defconfig linux-libre-2.6.38-gnu1/arch/mips/configs/pb1550_defconfig
--- linux-libre-2.6.37-gnu1/arch/mips/configs/pb1550_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/configs/pb1550_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -11,7 +11,7 @@ CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
 CONFIG_TINY_RCU=y
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_SYSCTL_SYSCALL is not set
 # CONFIG_KALLSYMS is not set
 # CONFIG_PCSPKR_PLATFORM is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/configs/pnx8335-stb225_defconfig linux-libre-2.6.38-gnu1/arch/mips/configs/pnx8335-stb225_defconfig
--- linux-libre-2.6.37-gnu1/arch/mips/configs/pnx8335-stb225_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/configs/pnx8335-stb225_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -11,7 +11,7 @@ CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 CONFIG_SLAB=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/configs/pnx8550-jbs_defconfig linux-libre-2.6.38-gnu1/arch/mips/configs/pnx8550-jbs_defconfig
--- linux-libre-2.6.37-gnu1/arch/mips/configs/pnx8550-jbs_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/configs/pnx8550-jbs_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -6,7 +6,7 @@ CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_SYSCTL_SYSCALL is not set
 CONFIG_SLAB=y
 CONFIG_MODULES=y
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/configs/pnx8550-stb810_defconfig linux-libre-2.6.38-gnu1/arch/mips/configs/pnx8550-stb810_defconfig
--- linux-libre-2.6.37-gnu1/arch/mips/configs/pnx8550-stb810_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/configs/pnx8550-stb810_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -6,7 +6,7 @@ CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_SYSCTL_SYSCALL is not set
 # CONFIG_HOTPLUG is not set
 CONFIG_SLAB=y
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/configs/powertv_defconfig linux-libre-2.6.38-gnu1/arch/mips/configs/powertv_defconfig
--- linux-libre-2.6.37-gnu1/arch/mips/configs/powertv_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/configs/powertv_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -14,7 +14,7 @@ CONFIG_RELAY=y
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_RD_GZIP is not set
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_SYSCTL_SYSCALL is not set
 CONFIG_KALLSYMS_ALL=y
 # CONFIG_PCSPKR_PLATFORM is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/configs/rb532_defconfig linux-libre-2.6.38-gnu1/arch/mips/configs/rb532_defconfig
--- linux-libre-2.6.37-gnu1/arch/mips/configs/rb532_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/configs/rb532_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -13,7 +13,7 @@ CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_SYSFS_DEPRECATED_V2=y
 CONFIG_BLK_DEV_INITRD=y
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_KALLSYMS is not set
 # CONFIG_ELF_CORE is not set
 # CONFIG_VM_EVENT_COUNTERS is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/configs/rbtx49xx_defconfig linux-libre-2.6.38-gnu1/arch/mips/configs/rbtx49xx_defconfig
--- linux-libre-2.6.37-gnu1/arch/mips/configs/rbtx49xx_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/configs/rbtx49xx_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -12,7 +12,7 @@ CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_SYSFS_DEPRECATED_V2=y
 CONFIG_BLK_DEV_INITRD=y
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_HOTPLUG is not set
 # CONFIG_PCSPKR_PLATFORM is not set
 # CONFIG_EPOLL is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/configs/rm200_defconfig linux-libre-2.6.38-gnu1/arch/mips/configs/rm200_defconfig
--- linux-libre-2.6.37-gnu1/arch/mips/configs/rm200_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/configs/rm200_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -12,7 +12,7 @@ CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_RELAY=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 CONFIG_SLAB=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/configs/sb1250-swarm_defconfig linux-libre-2.6.38-gnu1/arch/mips/configs/sb1250-swarm_defconfig
--- linux-libre-2.6.37-gnu1/arch/mips/configs/sb1250-swarm_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/configs/sb1250-swarm_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -15,7 +15,7 @@ CONFIG_RELAY=y
 CONFIG_NAMESPACES=y
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_COMPAT_BRK is not set
 CONFIG_SLAB=y
 CONFIG_MODULES=y
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/configs/tb0219_defconfig linux-libre-2.6.38-gnu1/arch/mips/configs/tb0219_defconfig
--- linux-libre-2.6.37-gnu1/arch/mips/configs/tb0219_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/configs/tb0219_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@ CONFIG_SYSVIPC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_SYSFS_DEPRECATED_V2=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_PCSPKR_PLATFORM is not set
 CONFIG_SLAB=y
 CONFIG_MODULES=y
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/configs/tb0226_defconfig linux-libre-2.6.38-gnu1/arch/mips/configs/tb0226_defconfig
--- linux-libre-2.6.37-gnu1/arch/mips/configs/tb0226_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/configs/tb0226_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@ CONFIG_SYSVIPC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_SYSFS_DEPRECATED_V2=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_PCSPKR_PLATFORM is not set
 CONFIG_SLAB=y
 CONFIG_MODULES=y
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/configs/tb0287_defconfig linux-libre-2.6.38-gnu1/arch/mips/configs/tb0287_defconfig
--- linux-libre-2.6.37-gnu1/arch/mips/configs/tb0287_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/configs/tb0287_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -4,7 +4,7 @@ CONFIG_SYSVIPC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_SYSFS_DEPRECATED_V2=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_SYSCTL_SYSCALL is not set
 # CONFIG_PCSPKR_PLATFORM is not set
 CONFIG_SLAB=y
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/configs/workpad_defconfig linux-libre-2.6.38-gnu1/arch/mips/configs/workpad_defconfig
--- linux-libre-2.6.37-gnu1/arch/mips/configs/workpad_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/configs/workpad_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -4,7 +4,7 @@ CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 CONFIG_SLAB=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/configs/wrppmc_defconfig linux-libre-2.6.38-gnu1/arch/mips/configs/wrppmc_defconfig
--- linux-libre-2.6.37-gnu1/arch/mips/configs/wrppmc_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/configs/wrppmc_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -7,7 +7,7 @@ CONFIG_BSD_PROCESS_ACCT=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 CONFIG_KALLSYMS_EXTRA_PASS=y
 # CONFIG_EPOLL is not set
 CONFIG_SLAB=y
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/configs/yosemite_defconfig linux-libre-2.6.38-gnu1/arch/mips/configs/yosemite_defconfig
--- linux-libre-2.6.37-gnu1/arch/mips/configs/yosemite_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/configs/yosemite_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -8,7 +8,7 @@ CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_RELAY=y
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 CONFIG_SLAB=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/dec/time.c linux-libre-2.6.38-gnu1/arch/mips/dec/time.c
--- linux-libre-2.6.37-gnu1/arch/mips/dec/time.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/dec/time.c	2011-03-14 21:20:32.000000000 -0400
@@ -104,7 +104,7 @@ int rtc_mips_set_mmss(unsigned long nowt
 		CMOS_WRITE(real_seconds, RTC_SECONDS);
 		CMOS_WRITE(real_minutes, RTC_MINUTES);
 	} else {
-		printk(KERN_WARNING
+		printk_once(KERN_NOTICE
 		       "set_rtc_mmss: can't update from %d to %d\n",
 		       cmos_minutes, real_minutes);
 		retval = -1;
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/include/asm/cache.h linux-libre-2.6.38-gnu1/arch/mips/include/asm/cache.h
--- linux-libre-2.6.37-gnu1/arch/mips/include/asm/cache.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/include/asm/cache.h	2011-03-14 21:20:32.000000000 -0400
@@ -17,4 +17,6 @@
 #define SMP_CACHE_SHIFT		L1_CACHE_SHIFT
 #define SMP_CACHE_BYTES		L1_CACHE_BYTES
 
+#define __read_mostly __attribute__((__section__(".data.read_mostly")))
+
 #endif /* _ASM_CACHE_H */
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/include/asm/cpu-info.h linux-libre-2.6.38-gnu1/arch/mips/include/asm/cpu-info.h
--- linux-libre-2.6.37-gnu1/arch/mips/include/asm/cpu-info.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/include/asm/cpu-info.h	2011-03-14 21:20:32.000000000 -0400
@@ -78,6 +78,7 @@ struct cpuinfo_mips {
 	unsigned int		watch_reg_use_cnt; /* Usable by ptrace */
 #define NUM_WATCH_REGS 4
 	u16			watch_reg_masks[NUM_WATCH_REGS];
+	unsigned int		kscratch_mask; /* Usable KScratch mask. */
 } __attribute__((aligned(SMP_CACHE_BYTES)));
 
 extern struct cpuinfo_mips cpu_data[];
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/include/asm/inst.h linux-libre-2.6.38-gnu1/arch/mips/include/asm/inst.h
--- linux-libre-2.6.37-gnu1/arch/mips/include/asm/inst.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/include/asm/inst.h	2011-03-14 21:20:32.000000000 -0400
@@ -72,6 +72,7 @@ enum spec2_op {
 enum spec3_op {
 	ext_op, dextm_op, dextu_op, dext_op,
 	ins_op, dinsm_op, dinsu_op, dins_op,
+	lx_op = 0x0a,
 	bshfl_op = 0x20,
 	dbshfl_op = 0x24,
 	rdhwr_op = 0x3b
@@ -179,6 +180,19 @@ enum mad_func {
 };
 
 /*
+ * func field for special3 lx opcodes (Cavium Octeon).
+ */
+enum lx_func {
+	lwx_op	= 0x00,
+	lhx_op	= 0x04,
+	lbux_op	= 0x06,
+	ldx_op	= 0x08,
+	lwux_op	= 0x10,
+	lhux_op	= 0x14,
+	lbx_op	= 0x16,
+};
+
+/*
  * Damn ...  bitfields depend from byteorder :-(
  */
 #ifdef __MIPSEB__
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/include/asm/ioctls.h linux-libre-2.6.38-gnu1/arch/mips/include/asm/ioctls.h
--- linux-libre-2.6.37-gnu1/arch/mips/include/asm/ioctls.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/include/asm/ioctls.h	2011-03-14 21:20:32.000000000 -0400
@@ -83,6 +83,7 @@
 #define TCSETSF2	_IOW('T', 0x2D, struct termios2)
 #define TIOCGPTN	_IOR('T', 0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
 #define TIOCSPTLCK	_IOW('T', 0x31, int)  /* Lock/unlock Pty */
+#define TIOCGDEV	_IOR('T', 0x32, unsigned int) /* Get primary device node of /dev/console */
 #define TIOCSIG		_IOW('T', 0x36, int)  /* Generate signal on Pty slave */
 
 /* I hope the range from 0x5480 on is free ... */
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/include/asm/jump_label.h linux-libre-2.6.38-gnu1/arch/mips/include/asm/jump_label.h
--- linux-libre-2.6.37-gnu1/arch/mips/include/asm/jump_label.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/include/asm/jump_label.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,48 @@
+/*
+ * 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) 2010 Cavium Networks, Inc.
+ */
+#ifndef _ASM_MIPS_JUMP_LABEL_H
+#define _ASM_MIPS_JUMP_LABEL_H
+
+#include <linux/types.h>
+
+#ifdef __KERNEL__
+
+#define JUMP_LABEL_NOP_SIZE 4
+
+#ifdef CONFIG_64BIT
+#define WORD_INSN ".dword"
+#else
+#define WORD_INSN ".word"
+#endif
+
+#define JUMP_LABEL(key, label)						\
+	do {								\
+		asm goto("1:\tnop\n\t"					\
+			"nop\n\t"					\
+			".pushsection __jump_table,  \"a\"\n\t"		\
+			WORD_INSN " 1b, %l[" #label "], %0\n\t"		\
+			".popsection\n\t"				\
+			: :  "i" (key) :  : label);			\
+	} while (0)
+
+
+#endif /* __KERNEL__ */
+
+#ifdef CONFIG_64BIT
+typedef u64 jump_label_t;
+#else
+typedef u32 jump_label_t;
+#endif
+
+struct jump_entry {
+	jump_label_t code;
+	jump_label_t target;
+	jump_label_t key;
+};
+
+#endif /* _ASM_MIPS_JUMP_LABEL_H */
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/include/asm/mach-ath79/ar71xx_regs.h linux-libre-2.6.38-gnu1/arch/mips/include/asm/mach-ath79/ar71xx_regs.h
--- linux-libre-2.6.37-gnu1/arch/mips/include/asm/mach-ath79/ar71xx_regs.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/include/asm/mach-ath79/ar71xx_regs.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,233 @@
+/*
+ *  Atheros AR71XX/AR724X/AR913X SoC register definitions
+ *
+ *  Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
+ *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
+ *
+ *  Parts of this file are based on Atheros' 2.6.15 BSP
+ *
+ *  This program is free software; you can 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_AR71XX_REGS_H
+#define __ASM_MACH_AR71XX_REGS_H
+
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/bitops.h>
+
+#define AR71XX_APB_BASE		0x18000000
+#define AR71XX_SPI_BASE		0x1f000000
+#define AR71XX_SPI_SIZE		0x01000000
+
+#define AR71XX_DDR_CTRL_BASE	(AR71XX_APB_BASE + 0x00000000)
+#define AR71XX_DDR_CTRL_SIZE	0x100
+#define AR71XX_UART_BASE	(AR71XX_APB_BASE + 0x00020000)
+#define AR71XX_UART_SIZE	0x100
+#define AR71XX_GPIO_BASE        (AR71XX_APB_BASE + 0x00040000)
+#define AR71XX_GPIO_SIZE        0x100
+#define AR71XX_PLL_BASE		(AR71XX_APB_BASE + 0x00050000)
+#define AR71XX_PLL_SIZE		0x100
+#define AR71XX_RESET_BASE	(AR71XX_APB_BASE + 0x00060000)
+#define AR71XX_RESET_SIZE	0x100
+
+#define AR913X_WMAC_BASE	(AR71XX_APB_BASE + 0x000C0000)
+#define AR913X_WMAC_SIZE	0x30000
+
+/*
+ * DDR_CTRL block
+ */
+#define AR71XX_DDR_REG_PCI_WIN0		0x7c
+#define AR71XX_DDR_REG_PCI_WIN1		0x80
+#define AR71XX_DDR_REG_PCI_WIN2		0x84
+#define AR71XX_DDR_REG_PCI_WIN3		0x88
+#define AR71XX_DDR_REG_PCI_WIN4		0x8c
+#define AR71XX_DDR_REG_PCI_WIN5		0x90
+#define AR71XX_DDR_REG_PCI_WIN6		0x94
+#define AR71XX_DDR_REG_PCI_WIN7		0x98
+#define AR71XX_DDR_REG_FLUSH_GE0	0x9c
+#define AR71XX_DDR_REG_FLUSH_GE1	0xa0
+#define AR71XX_DDR_REG_FLUSH_USB	0xa4
+#define AR71XX_DDR_REG_FLUSH_PCI	0xa8
+
+#define AR724X_DDR_REG_FLUSH_GE0	0x7c
+#define AR724X_DDR_REG_FLUSH_GE1	0x80
+#define AR724X_DDR_REG_FLUSH_USB	0x84
+#define AR724X_DDR_REG_FLUSH_PCIE	0x88
+
+#define AR913X_DDR_REG_FLUSH_GE0	0x7c
+#define AR913X_DDR_REG_FLUSH_GE1	0x80
+#define AR913X_DDR_REG_FLUSH_USB	0x84
+#define AR913X_DDR_REG_FLUSH_WMAC	0x88
+
+/*
+ * PLL block
+ */
+#define AR71XX_PLL_REG_CPU_CONFIG	0x00
+#define AR71XX_PLL_REG_SEC_CONFIG	0x04
+#define AR71XX_PLL_REG_ETH0_INT_CLOCK	0x10
+#define AR71XX_PLL_REG_ETH1_INT_CLOCK	0x14
+
+#define AR71XX_PLL_DIV_SHIFT		3
+#define AR71XX_PLL_DIV_MASK		0x1f
+#define AR71XX_CPU_DIV_SHIFT		16
+#define AR71XX_CPU_DIV_MASK		0x3
+#define AR71XX_DDR_DIV_SHIFT		18
+#define AR71XX_DDR_DIV_MASK		0x3
+#define AR71XX_AHB_DIV_SHIFT		20
+#define AR71XX_AHB_DIV_MASK		0x7
+
+#define AR724X_PLL_REG_CPU_CONFIG	0x00
+#define AR724X_PLL_REG_PCIE_CONFIG	0x18
+
+#define AR724X_PLL_DIV_SHIFT		0
+#define AR724X_PLL_DIV_MASK		0x3ff
+#define AR724X_PLL_REF_DIV_SHIFT	10
+#define AR724X_PLL_REF_DIV_MASK		0xf
+#define AR724X_AHB_DIV_SHIFT		19
+#define AR724X_AHB_DIV_MASK		0x1
+#define AR724X_DDR_DIV_SHIFT		22
+#define AR724X_DDR_DIV_MASK		0x3
+
+#define AR913X_PLL_REG_CPU_CONFIG	0x00
+#define AR913X_PLL_REG_ETH_CONFIG	0x04
+#define AR913X_PLL_REG_ETH0_INT_CLOCK	0x14
+#define AR913X_PLL_REG_ETH1_INT_CLOCK	0x18
+
+#define AR913X_PLL_DIV_SHIFT		0
+#define AR913X_PLL_DIV_MASK		0x3ff
+#define AR913X_DDR_DIV_SHIFT		22
+#define AR913X_DDR_DIV_MASK		0x3
+#define AR913X_AHB_DIV_SHIFT		19
+#define AR913X_AHB_DIV_MASK		0x1
+
+/*
+ * RESET block
+ */
+#define AR71XX_RESET_REG_TIMER			0x00
+#define AR71XX_RESET_REG_TIMER_RELOAD		0x04
+#define AR71XX_RESET_REG_WDOG_CTRL		0x08
+#define AR71XX_RESET_REG_WDOG			0x0c
+#define AR71XX_RESET_REG_MISC_INT_STATUS	0x10
+#define AR71XX_RESET_REG_MISC_INT_ENABLE	0x14
+#define AR71XX_RESET_REG_PCI_INT_STATUS		0x18
+#define AR71XX_RESET_REG_PCI_INT_ENABLE		0x1c
+#define AR71XX_RESET_REG_GLOBAL_INT_STATUS	0x20
+#define AR71XX_RESET_REG_RESET_MODULE		0x24
+#define AR71XX_RESET_REG_PERFC_CTRL		0x2c
+#define AR71XX_RESET_REG_PERFC0			0x30
+#define AR71XX_RESET_REG_PERFC1			0x34
+#define AR71XX_RESET_REG_REV_ID			0x90
+
+#define AR913X_RESET_REG_GLOBAL_INT_STATUS	0x18
+#define AR913X_RESET_REG_RESET_MODULE		0x1c
+#define AR913X_RESET_REG_PERF_CTRL		0x20
+#define AR913X_RESET_REG_PERFC0			0x24
+#define AR913X_RESET_REG_PERFC1			0x28
+
+#define AR724X_RESET_REG_RESET_MODULE		0x1c
+
+#define MISC_INT_DMA			BIT(7)
+#define MISC_INT_OHCI			BIT(6)
+#define MISC_INT_PERFC			BIT(5)
+#define MISC_INT_WDOG			BIT(4)
+#define MISC_INT_UART			BIT(3)
+#define MISC_INT_GPIO			BIT(2)
+#define MISC_INT_ERROR			BIT(1)
+#define MISC_INT_TIMER			BIT(0)
+
+#define AR71XX_RESET_EXTERNAL		BIT(28)
+#define AR71XX_RESET_FULL_CHIP		BIT(24)
+#define AR71XX_RESET_CPU_NMI		BIT(21)
+#define AR71XX_RESET_CPU_COLD		BIT(20)
+#define AR71XX_RESET_DMA		BIT(19)
+#define AR71XX_RESET_SLIC		BIT(18)
+#define AR71XX_RESET_STEREO		BIT(17)
+#define AR71XX_RESET_DDR		BIT(16)
+#define AR71XX_RESET_GE1_MAC		BIT(13)
+#define AR71XX_RESET_GE1_PHY		BIT(12)
+#define AR71XX_RESET_USBSUS_OVERRIDE	BIT(10)
+#define AR71XX_RESET_GE0_MAC		BIT(9)
+#define AR71XX_RESET_GE0_PHY		BIT(8)
+#define AR71XX_RESET_USB_OHCI_DLL	BIT(6)
+#define AR71XX_RESET_USB_HOST		BIT(5)
+#define AR71XX_RESET_USB_PHY		BIT(4)
+#define AR71XX_RESET_PCI_BUS		BIT(1)
+#define AR71XX_RESET_PCI_CORE		BIT(0)
+
+#define AR724X_RESET_GE1_MDIO		BIT(23)
+#define AR724X_RESET_GE0_MDIO		BIT(22)
+#define AR724X_RESET_PCIE_PHY_SERIAL	BIT(10)
+#define AR724X_RESET_PCIE_PHY		BIT(7)
+#define AR724X_RESET_PCIE		BIT(6)
+#define AR724X_RESET_OHCI_DLL		BIT(3)
+
+#define AR913X_RESET_AMBA2WMAC		BIT(22)
+
+#define REV_ID_MAJOR_MASK		0xfff0
+#define REV_ID_MAJOR_AR71XX		0x00a0
+#define REV_ID_MAJOR_AR913X		0x00b0
+#define REV_ID_MAJOR_AR7240		0x00c0
+#define REV_ID_MAJOR_AR7241		0x0100
+#define REV_ID_MAJOR_AR7242		0x1100
+
+#define AR71XX_REV_ID_MINOR_MASK	0x3
+#define AR71XX_REV_ID_MINOR_AR7130	0x0
+#define AR71XX_REV_ID_MINOR_AR7141	0x1
+#define AR71XX_REV_ID_MINOR_AR7161	0x2
+#define AR71XX_REV_ID_REVISION_MASK	0x3
+#define AR71XX_REV_ID_REVISION_SHIFT	2
+
+#define AR913X_REV_ID_MINOR_MASK	0x3
+#define AR913X_REV_ID_MINOR_AR9130	0x0
+#define AR913X_REV_ID_MINOR_AR9132	0x1
+#define AR913X_REV_ID_REVISION_MASK	0x3
+#define AR913X_REV_ID_REVISION_SHIFT	2
+
+#define AR724X_REV_ID_REVISION_MASK	0x3
+
+/*
+ * SPI block
+ */
+#define AR71XX_SPI_REG_FS	0x00	/* Function Select */
+#define AR71XX_SPI_REG_CTRL	0x04	/* SPI Control */
+#define AR71XX_SPI_REG_IOC	0x08	/* SPI I/O Control */
+#define AR71XX_SPI_REG_RDS	0x0c	/* Read Data Shift */
+
+#define AR71XX_SPI_FS_GPIO	BIT(0)	/* Enable GPIO mode */
+
+#define AR71XX_SPI_CTRL_RD	BIT(6)	/* Remap Disable */
+#define AR71XX_SPI_CTRL_DIV_MASK 0x3f
+
+#define AR71XX_SPI_IOC_DO	BIT(0)	/* Data Out pin */
+#define AR71XX_SPI_IOC_CLK	BIT(8)	/* CLK pin */
+#define AR71XX_SPI_IOC_CS(n)	BIT(16 + (n))
+#define AR71XX_SPI_IOC_CS0	AR71XX_SPI_IOC_CS(0)
+#define AR71XX_SPI_IOC_CS1	AR71XX_SPI_IOC_CS(1)
+#define AR71XX_SPI_IOC_CS2	AR71XX_SPI_IOC_CS(2)
+#define AR71XX_SPI_IOC_CS_ALL	(AR71XX_SPI_IOC_CS0 | AR71XX_SPI_IOC_CS1 | \
+				 AR71XX_SPI_IOC_CS2)
+
+/*
+ * GPIO block
+ */
+#define AR71XX_GPIO_REG_OE		0x00
+#define AR71XX_GPIO_REG_IN		0x04
+#define AR71XX_GPIO_REG_OUT		0x08
+#define AR71XX_GPIO_REG_SET		0x0c
+#define AR71XX_GPIO_REG_CLEAR		0x10
+#define AR71XX_GPIO_REG_INT_MODE	0x14
+#define AR71XX_GPIO_REG_INT_TYPE	0x18
+#define AR71XX_GPIO_REG_INT_POLARITY	0x1c
+#define AR71XX_GPIO_REG_INT_PENDING	0x20
+#define AR71XX_GPIO_REG_INT_ENABLE	0x24
+#define AR71XX_GPIO_REG_FUNC		0x28
+
+#define AR71XX_GPIO_COUNT		16
+#define AR724X_GPIO_COUNT		18
+#define AR913X_GPIO_COUNT		22
+
+#endif /* __ASM_MACH_AR71XX_REGS_H */
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/include/asm/mach-ath79/ath79.h linux-libre-2.6.38-gnu1/arch/mips/include/asm/mach-ath79/ath79.h
--- linux-libre-2.6.37-gnu1/arch/mips/include/asm/mach-ath79/ath79.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/include/asm/mach-ath79/ath79.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,96 @@
+/*
+ *  Atheros AR71XX/AR724X/AR913X common definitions
+ *
+ *  Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org>
+ *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
+ *
+ *  Parts of this file are based on Atheros' 2.6.15 BSP
+ *
+ *  This program is free software; you can 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_ATH79_H
+#define __ASM_MACH_ATH79_H
+
+#include <linux/types.h>
+#include <linux/io.h>
+
+enum ath79_soc_type {
+	ATH79_SOC_UNKNOWN,
+	ATH79_SOC_AR7130,
+	ATH79_SOC_AR7141,
+	ATH79_SOC_AR7161,
+	ATH79_SOC_AR7240,
+	ATH79_SOC_AR7241,
+	ATH79_SOC_AR7242,
+	ATH79_SOC_AR9130,
+	ATH79_SOC_AR9132
+};
+
+extern enum ath79_soc_type ath79_soc;
+
+static inline int soc_is_ar71xx(void)
+{
+	return (ath79_soc == ATH79_SOC_AR7130 ||
+		ath79_soc == ATH79_SOC_AR7141 ||
+		ath79_soc == ATH79_SOC_AR7161);
+}
+
+static inline int soc_is_ar724x(void)
+{
+	return (ath79_soc == ATH79_SOC_AR7240 ||
+		ath79_soc == ATH79_SOC_AR7241 ||
+		ath79_soc == ATH79_SOC_AR7242);
+}
+
+static inline int soc_is_ar7240(void)
+{
+	return (ath79_soc == ATH79_SOC_AR7240);
+}
+
+static inline int soc_is_ar7241(void)
+{
+	return (ath79_soc == ATH79_SOC_AR7241);
+}
+
+static inline int soc_is_ar7242(void)
+{
+	return (ath79_soc == ATH79_SOC_AR7242);
+}
+
+static inline int soc_is_ar913x(void)
+{
+	return (ath79_soc == ATH79_SOC_AR9130 ||
+		ath79_soc == ATH79_SOC_AR9132);
+}
+
+extern void __iomem *ath79_ddr_base;
+extern void __iomem *ath79_pll_base;
+extern void __iomem *ath79_reset_base;
+
+static inline void ath79_pll_wr(unsigned reg, u32 val)
+{
+	__raw_writel(val, ath79_pll_base + reg);
+}
+
+static inline u32 ath79_pll_rr(unsigned reg)
+{
+	return __raw_readl(ath79_pll_base + reg);
+}
+
+static inline void ath79_reset_wr(unsigned reg, u32 val)
+{
+	__raw_writel(val, ath79_reset_base + reg);
+}
+
+static inline u32 ath79_reset_rr(unsigned reg)
+{
+	return __raw_readl(ath79_reset_base + reg);
+}
+
+void ath79_device_reset_set(u32 mask);
+void ath79_device_reset_clear(u32 mask);
+
+#endif /* __ASM_MACH_ATH79_H */
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/include/asm/mach-ath79/ath79_spi_platform.h linux-libre-2.6.38-gnu1/arch/mips/include/asm/mach-ath79/ath79_spi_platform.h
--- linux-libre-2.6.37-gnu1/arch/mips/include/asm/mach-ath79/ath79_spi_platform.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/include/asm/mach-ath79/ath79_spi_platform.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,23 @@
+/*
+ *  Platform data definition for Atheros AR71XX/AR724X/AR913X SPI controller
+ *
+ *  Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License version 2 as published
+ *  by the Free Software Foundation.
+ */
+
+#ifndef _ATH79_SPI_PLATFORM_H
+#define _ATH79_SPI_PLATFORM_H
+
+struct ath79_spi_platform_data {
+	unsigned	bus_num;
+	unsigned	num_chipselect;
+};
+
+struct ath79_spi_controller_data {
+	unsigned	gpio;
+};
+
+#endif /* _ATH79_SPI_PLATFORM_H */
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/include/asm/mach-ath79/cpu-feature-overrides.h linux-libre-2.6.38-gnu1/arch/mips/include/asm/mach-ath79/cpu-feature-overrides.h
--- linux-libre-2.6.37-gnu1/arch/mips/include/asm/mach-ath79/cpu-feature-overrides.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/include/asm/mach-ath79/cpu-feature-overrides.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,56 @@
+/*
+ *  Atheros AR71XX/AR724X/AR913X specific CPU feature overrides
+ *
+ *  Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
+ *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
+ *
+ *  This file was derived from: include/asm-mips/cpu-features.h
+ *	Copyright (C) 2003, 2004 Ralf Baechle
+ *	Copyright (C) 2004 Maciej W. Rozycki
+ *
+ *  This program is free software; you can 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_ATH79_CPU_FEATURE_OVERRIDES_H
+#define __ASM_MACH_ATH79_CPU_FEATURE_OVERRIDES_H
+
+#define cpu_has_tlb		1
+#define cpu_has_4kex		1
+#define cpu_has_3k_cache	0
+#define cpu_has_4k_cache	1
+#define cpu_has_tx39_cache	0
+#define cpu_has_sb1_cache	0
+#define cpu_has_fpu		0
+#define cpu_has_32fpr		0
+#define cpu_has_counter		1
+#define cpu_has_watch		1
+#define cpu_has_divec		1
+
+#define cpu_has_prefetch	1
+#define cpu_has_ejtag		1
+#define cpu_has_llsc		1
+
+#define cpu_has_mips16		1
+#define cpu_has_mdmx		0
+#define cpu_has_mips3d		0
+#define cpu_has_smartmips	0
+
+#define cpu_has_mips32r1	1
+#define cpu_has_mips32r2	1
+#define cpu_has_mips64r1	0
+#define cpu_has_mips64r2	0
+
+#define cpu_has_dsp		0
+#define cpu_has_mipsmt		0
+
+#define cpu_has_64bits		0
+#define cpu_has_64bit_zero_reg	0
+#define cpu_has_64bit_gp_regs	0
+#define cpu_has_64bit_addresses	0
+
+#define cpu_dcache_line_size()	32
+#define cpu_icache_line_size()	32
+
+#endif /* __ASM_MACH_ATH79_CPU_FEATURE_OVERRIDES_H */
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/include/asm/mach-ath79/gpio.h linux-libre-2.6.38-gnu1/arch/mips/include/asm/mach-ath79/gpio.h
--- linux-libre-2.6.37-gnu1/arch/mips/include/asm/mach-ath79/gpio.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/include/asm/mach-ath79/gpio.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,26 @@
+/*
+ *  Atheros AR71XX/AR724X/AR913X GPIO API definitions
+ *
+ *  Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
+ *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License version 2 as published
+ *  by the Free Software Foundation.
+ *
+ */
+
+#ifndef __ASM_MACH_ATH79_GPIO_H
+#define __ASM_MACH_ATH79_GPIO_H
+
+#define ARCH_NR_GPIOS	64
+#include <asm-generic/gpio.h>
+
+int gpio_to_irq(unsigned gpio);
+int irq_to_gpio(unsigned irq);
+int gpio_get_value(unsigned gpio);
+void gpio_set_value(unsigned gpio, int value);
+
+#define gpio_cansleep	__gpio_cansleep
+
+#endif /* __ASM_MACH_ATH79_GPIO_H */
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/include/asm/mach-ath79/irq.h linux-libre-2.6.38-gnu1/arch/mips/include/asm/mach-ath79/irq.h
--- linux-libre-2.6.37-gnu1/arch/mips/include/asm/mach-ath79/irq.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/include/asm/mach-ath79/irq.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,36 @@
+/*
+ *  Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
+ *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License version 2 as published
+ *  by the Free Software Foundation.
+ */
+#ifndef __ASM_MACH_ATH79_IRQ_H
+#define __ASM_MACH_ATH79_IRQ_H
+
+#define MIPS_CPU_IRQ_BASE	0
+#define NR_IRQS			16
+
+#define ATH79_MISC_IRQ_BASE	8
+#define ATH79_MISC_IRQ_COUNT	8
+
+#define ATH79_CPU_IRQ_IP2	(MIPS_CPU_IRQ_BASE + 2)
+#define ATH79_CPU_IRQ_USB	(MIPS_CPU_IRQ_BASE + 3)
+#define ATH79_CPU_IRQ_GE0	(MIPS_CPU_IRQ_BASE + 4)
+#define ATH79_CPU_IRQ_GE1	(MIPS_CPU_IRQ_BASE + 5)
+#define ATH79_CPU_IRQ_MISC	(MIPS_CPU_IRQ_BASE + 6)
+#define ATH79_CPU_IRQ_TIMER	(MIPS_CPU_IRQ_BASE + 7)
+
+#define ATH79_MISC_IRQ_TIMER	(ATH79_MISC_IRQ_BASE + 0)
+#define ATH79_MISC_IRQ_ERROR	(ATH79_MISC_IRQ_BASE + 1)
+#define ATH79_MISC_IRQ_GPIO	(ATH79_MISC_IRQ_BASE + 2)
+#define ATH79_MISC_IRQ_UART	(ATH79_MISC_IRQ_BASE + 3)
+#define ATH79_MISC_IRQ_WDOG	(ATH79_MISC_IRQ_BASE + 4)
+#define ATH79_MISC_IRQ_PERFC	(ATH79_MISC_IRQ_BASE + 5)
+#define ATH79_MISC_IRQ_OHCI	(ATH79_MISC_IRQ_BASE + 6)
+#define ATH79_MISC_IRQ_DMA	(ATH79_MISC_IRQ_BASE + 7)
+
+#include_next <irq.h>
+
+#endif /* __ASM_MACH_ATH79_IRQ_H */
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/include/asm/mach-ath79/kernel-entry-init.h linux-libre-2.6.38-gnu1/arch/mips/include/asm/mach-ath79/kernel-entry-init.h
--- linux-libre-2.6.37-gnu1/arch/mips/include/asm/mach-ath79/kernel-entry-init.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/include/asm/mach-ath79/kernel-entry-init.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,32 @@
+/*
+ *  Atheros AR71XX/AR724X/AR913X specific kernel entry setup
+ *
+ *  Copyright (C) 2009 Gabor Juhos <juhosg@openwrt.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License version 2 as published
+ *  by the Free Software Foundation.
+ *
+ */
+#ifndef __ASM_MACH_ATH79_KERNEL_ENTRY_H
+#define __ASM_MACH_ATH79_KERNEL_ENTRY_H
+
+	/*
+	 * Some bootloaders set the 'Kseg0 coherency algorithm' to
+	 * 'Cacheable, noncoherent, write-through, no write allocate'
+	 * and this cause performance issues. Let's go and change it to
+	 * 'Cacheable, noncoherent, write-back, write allocate'
+	 */
+	.macro	kernel_entry_setup
+	mfc0	t0, CP0_CONFIG
+	li	t1, ~CONF_CM_CMASK
+	and	t0, t1
+	ori	t0, CONF_CM_CACHABLE_NONCOHERENT
+	mtc0	t0, CP0_CONFIG
+	nop
+	.endm
+
+	.macro	smp_slave_setup
+	.endm
+
+#endif /* __ASM_MACH_ATH79_KERNEL_ENTRY_H */
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/include/asm/mach-ath79/war.h linux-libre-2.6.38-gnu1/arch/mips/include/asm/mach-ath79/war.h
--- linux-libre-2.6.37-gnu1/arch/mips/include/asm/mach-ath79/war.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/include/asm/mach-ath79/war.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,25 @@
+/*
+ * 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) 2002, 2004, 2007 by Ralf Baechle <ralf@linux-mips.org>
+ */
+#ifndef __ASM_MACH_ATH79_WAR_H
+#define __ASM_MACH_ATH79_WAR_H
+
+#define R4600_V1_INDEX_ICACHEOP_WAR	0
+#define R4600_V1_HIT_CACHEOP_WAR	0
+#define R4600_V2_HIT_CACHEOP_WAR	0
+#define R5432_CP0_INTERRUPT_WAR		0
+#define BCM1250_M3_WAR			0
+#define SIBYTE_1956_WAR			0
+#define MIPS4K_ICACHE_REFILL_WAR	0
+#define MIPS_CACHE_SYNC_WAR		0
+#define TX49XX_ICACHE_INDEX_INV_WAR	0
+#define RM9000_CDEX_SMP_WAR		0
+#define ICACHE_REFILLS_WORKAROUND_WAR	0
+#define R10000_LLSC_WAR			0
+#define MIPS34K_MISSED_ITLB_WAR		0
+
+#endif /* __ASM_MACH_ATH79_WAR_H */
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/include/asm/mach-powertv/ioremap.h linux-libre-2.6.38-gnu1/arch/mips/include/asm/mach-powertv/ioremap.h
--- linux-libre-2.6.37-gnu1/arch/mips/include/asm/mach-powertv/ioremap.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/include/asm/mach-powertv/ioremap.h	2011-03-14 21:20:32.000000000 -0400
@@ -88,7 +88,7 @@ static inline dma_addr_t _dma_to_phys_of
 }
 
 /* These are not portable and should not be used in drivers. Drivers should
- * be using ioremap() and friends to map physical addreses to virtual
+ * be using ioremap() and friends to map physical addresses to virtual
  * addresses and dma_map*() and friends to map virtual addresses into DMA
  * addresses and back.
  */
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/include/asm/mc146818-time.h linux-libre-2.6.38-gnu1/arch/mips/include/asm/mc146818-time.h
--- linux-libre-2.6.37-gnu1/arch/mips/include/asm/mc146818-time.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/include/asm/mc146818-time.h	2011-03-14 21:20:32.000000000 -0400
@@ -66,7 +66,7 @@ static inline int mc146818_set_rtc_mmss(
 		CMOS_WRITE(real_seconds, RTC_SECONDS);
 		CMOS_WRITE(real_minutes, RTC_MINUTES);
 	} else {
-		printk(KERN_WARNING
+		printk_once(KERN_NOTICE
 		       "set_rtc_mmss: can't update from %d to %d\n",
 		       cmos_minutes, real_minutes);
 		retval = -1;
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/include/asm/mips_machine.h linux-libre-2.6.38-gnu1/arch/mips/include/asm/mips_machine.h
--- linux-libre-2.6.37-gnu1/arch/mips/include/asm/mips_machine.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/include/asm/mips_machine.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,54 @@
+/*
+ *  Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License version 2 as published
+ *  by the Free Software Foundation.
+ *
+ */
+
+#ifndef __ASM_MIPS_MACHINE_H
+#define __ASM_MIPS_MACHINE_H
+
+#include <linux/init.h>
+#include <linux/stddef.h>
+
+#include <asm/bootinfo.h>
+
+struct mips_machine {
+	unsigned long		mach_type;
+	const char		*mach_id;
+	const char		*mach_name;
+	void			(*mach_setup)(void);
+};
+
+#define MIPS_MACHINE(_type, _id, _name, _setup)			\
+static const char machine_name_##_type[] __initconst		\
+			__aligned(1) = _name;			\
+static const char machine_id_##_type[] __initconst		\
+			__aligned(1) = _id;			\
+static struct mips_machine machine_##_type			\
+		__used __section(.mips.machines.init) =		\
+{								\
+	.mach_type	= _type,				\
+	.mach_id	= machine_id_##_type,			\
+	.mach_name	= machine_name_##_type,			\
+	.mach_setup	= _setup,				\
+};
+
+extern long __mips_machines_start;
+extern long __mips_machines_end;
+
+#ifdef CONFIG_MIPS_MACHINE
+int  mips_machtype_setup(char *id) __init;
+void mips_machine_setup(void) __init;
+void mips_set_machine_name(const char *name) __init;
+char *mips_get_machine_name(void);
+#else
+static inline int mips_machtype_setup(char *id) { return 1; }
+static inline void mips_machine_setup(void) { }
+static inline void mips_set_machine_name(const char *name) { }
+static inline char *mips_get_machine_name(void) { return NULL; }
+#endif /* CONFIG_MIPS_MACHINE */
+
+#endif /* __ASM_MIPS_MACHINE_H */
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/include/asm/mman.h linux-libre-2.6.38-gnu1/arch/mips/include/asm/mman.h
--- linux-libre-2.6.37-gnu1/arch/mips/include/asm/mman.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/include/asm/mman.h	2011-03-14 21:20:32.000000000 -0400
@@ -77,6 +77,9 @@
 #define MADV_UNMERGEABLE 13		/* KSM may not merge identical pages */
 #define MADV_HWPOISON    100		/* poison a page for testing */
 
+#define MADV_HUGEPAGE	14		/* Worth backing with hugepages */
+#define MADV_NOHUGEPAGE	15		/* Not worth backing with hugepages */
+
 /* compatibility flags */
 #define MAP_FILE	0
 
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/include/asm/mmu_context.h linux-libre-2.6.38-gnu1/arch/mips/include/asm/mmu_context.h
--- linux-libre-2.6.37-gnu1/arch/mips/include/asm/mmu_context.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/include/asm/mmu_context.h	2011-03-14 21:20:32.000000000 -0400
@@ -29,13 +29,7 @@
 #define TLBMISS_HANDLER_SETUP_PGD(pgd)				\
 	tlbmiss_handler_setup_pgd((unsigned long)(pgd))
 
-static inline void tlbmiss_handler_setup_pgd(unsigned long pgd)
-{
-	/* Check for swapper_pg_dir and convert to physical address. */
-	if ((pgd & CKSEG3) == CKSEG0)
-		pgd = CPHYSADDR(pgd);
-	write_c0_context(pgd << 11);
-}
+extern void tlbmiss_handler_setup_pgd(unsigned long pgd);
 
 #define TLBMISS_HANDLER_SETUP()						\
 	do {								\
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/include/asm/perf_event.h linux-libre-2.6.38-gnu1/arch/mips/include/asm/perf_event.h
--- linux-libre-2.6.37-gnu1/arch/mips/include/asm/perf_event.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/include/asm/perf_event.h	2011-03-14 21:20:32.000000000 -0400
@@ -11,15 +11,5 @@
 
 #ifndef __MIPS_PERF_EVENT_H__
 #define __MIPS_PERF_EVENT_H__
-
-/*
- * MIPS performance counters do not raise NMI upon overflow, a regular
- * interrupt will be signaled. Hence we can do the pending perf event
- * work at the tail of the irq handler.
- */
-static inline void
-set_perf_event_pending(void)
-{
-}
-
+/* Leave it empty here. The file is required by linux/perf_event.h */
 #endif /* __MIPS_PERF_EVENT_H__ */
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/include/asm/uasm.h linux-libre-2.6.38-gnu1/arch/mips/include/asm/uasm.h
--- linux-libre-2.6.37-gnu1/arch/mips/include/asm/uasm.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/include/asm/uasm.h	2011-03-14 21:20:32.000000000 -0400
@@ -115,7 +115,12 @@ Ip_0(_tlbwr);
 Ip_u3u1u2(_xor);
 Ip_u2u1u3(_xori);
 Ip_u2u1msbu3(_dins);
+Ip_u2u1msbu3(_dinsm);
 Ip_u1(_syscall);
+Ip_u1u2s3(_bbit0);
+Ip_u1u2s3(_bbit1);
+Ip_u3u1u2(_lwx);
+Ip_u3u1u2(_ldx);
 
 /* Handle labels. */
 struct uasm_label {
@@ -153,6 +158,7 @@ static inline void __uasminit uasm_l##lb
 # define UASM_i_SUBU(buf, rs, rt, rd) uasm_i_dsubu(buf, rs, rt, rd)
 # define UASM_i_LL(buf, rs, rt, off) uasm_i_lld(buf, rs, rt, off)
 # define UASM_i_SC(buf, rs, rt, off) uasm_i_scd(buf, rs, rt, off)
+# define UASM_i_LWX(buf, rs, rt, rd) uasm_i_ldx(buf, rs, rt, rd)
 #else
 # define UASM_i_LW(buf, rs, rt, off) uasm_i_lw(buf, rs, rt, off)
 # define UASM_i_SW(buf, rs, rt, off) uasm_i_sw(buf, rs, rt, off)
@@ -167,6 +173,7 @@ static inline void __uasminit uasm_l##lb
 # define UASM_i_SUBU(buf, rs, rt, rd) uasm_i_subu(buf, rs, rt, rd)
 # define UASM_i_LL(buf, rs, rt, off) uasm_i_ll(buf, rs, rt, off)
 # define UASM_i_SC(buf, rs, rt, off) uasm_i_sc(buf, rs, rt, off)
+# define UASM_i_LWX(buf, rs, rt, rd) uasm_i_lwx(buf, rs, rt, rd)
 #endif
 
 #define uasm_i_b(buf, off) uasm_i_beq(buf, 0, 0, off)
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/jz4740/board-qi_lb60.c linux-libre-2.6.38-gnu1/arch/mips/jz4740/board-qi_lb60.c
--- linux-libre-2.6.37-gnu1/arch/mips/jz4740/board-qi_lb60.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/jz4740/board-qi_lb60.c	2011-03-14 21:20:32.000000000 -0400
@@ -65,7 +65,7 @@ static struct nand_ecclayout qi_lb60_ecc
 
 /* Early prototypes of the QI LB60 had only 1GB of NAND.
  * In order to support these devices aswell the partition and ecc layout is
- * initalized depending on the NAND size */
+ * initialized depending on the NAND size */
 static struct mtd_partition qi_lb60_partitions_1gb[] = {
 	{
 		.name = "NAND BOOT partition",
@@ -464,7 +464,7 @@ static int __init qi_lb60_board_setup(vo
 	board_gpio_setup();
 
 	if (qi_lb60_init_platform_devices())
-		panic("Failed to initalize platform devices\n");
+		panic("Failed to initialize platform devices\n");
 
 	return 0;
 }
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/jz4740/gpio.c linux-libre-2.6.38-gnu1/arch/mips/jz4740/gpio.c
--- linux-libre-2.6.37-gnu1/arch/mips/jz4740/gpio.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/jz4740/gpio.c	2011-03-14 21:20:32.000000000 -0400
@@ -546,7 +546,7 @@ 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);
 
-	printk(KERN_INFO "JZ4740 GPIO initalized\n");
+	printk(KERN_INFO "JZ4740 GPIO initialized\n");
 
 	return 0;
 }
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/jz4740/pm.c linux-libre-2.6.38-gnu1/arch/mips/jz4740/pm.c
--- linux-libre-2.6.37-gnu1/arch/mips/jz4740/pm.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/jz4740/pm.c	2011-03-14 21:20:32.000000000 -0400
@@ -42,7 +42,7 @@ static int jz4740_pm_enter(suspend_state
 	return 0;
 }
 
-static struct platform_suspend_ops jz4740_pm_ops = {
+static const struct platform_suspend_ops jz4740_pm_ops = {
 	.valid		= suspend_valid_only_mem,
 	.enter		= jz4740_pm_enter,
 };
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/Kbuild.platforms linux-libre-2.6.38-gnu1/arch/mips/Kbuild.platforms
--- linux-libre-2.6.37-gnu1/arch/mips/Kbuild.platforms	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/Kbuild.platforms	2011-03-14 21:20:32.000000000 -0400
@@ -2,6 +2,7 @@
 
 platforms += alchemy
 platforms += ar7
+platforms += ath79
 platforms += bcm47xx
 platforms += bcm63xx
 platforms += cavium-octeon
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/Kconfig linux-libre-2.6.38-gnu1/arch/mips/Kconfig
--- linux-libre-2.6.37-gnu1/arch/mips/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -4,6 +4,7 @@ config MIPS
 	select HAVE_GENERIC_DMA_COHERENT
 	select HAVE_IDE
 	select HAVE_OPROFILE
+	select HAVE_IRQ_WORK
 	select HAVE_PERF_EVENTS
 	select PERF_USE_VMALLOC
 	select HAVE_ARCH_KGDB
@@ -21,6 +22,7 @@ config MIPS
 	select HAVE_DMA_API_DEBUG
 	select HAVE_GENERIC_HARDIRQS
 	select GENERIC_IRQ_PROBE
+	select HAVE_ARCH_JUMP_LABEL
 
 menu "Machine selection"
 
@@ -65,6 +67,22 @@ config AR7
 	  Support for the Texas Instruments AR7 System-on-a-Chip
 	  family: TNETD7100, 7200 and 7300.
 
+config ATH79
+	bool "Atheros AR71XX/AR724X/AR913X based boards"
+	select ARCH_REQUIRE_GPIOLIB
+	select BOOT_RAW
+	select CEVT_R4K
+	select CSRC_R4K
+	select DMA_NONCOHERENT
+	select IRQ_CPU
+	select MIPS_MACHINE
+	select SYS_HAS_CPU_MIPS32_R2
+	select SYS_HAS_EARLY_PRINTK
+	select SYS_SUPPORTS_32BIT_KERNEL
+	select SYS_SUPPORTS_BIG_ENDIAN
+	help
+	  Support for the Atheros AR71XX/AR724X/AR913X SoCs.
+
 config BCM47XX
 	bool "Broadcom BCM47XX based boards"
 	select CEVT_R4K
@@ -191,6 +209,7 @@ config MACH_JZ4740
 	select ARCH_REQUIRE_GPIOLIB
 	select SYS_HAS_EARLY_PRINTK
 	select HAVE_PWM
+	select HAVE_CLK
 
 config LASAT
 	bool "LASAT Networks platforms"
@@ -316,6 +335,8 @@ config PNX8550_STB810
 config PMC_MSP
 	bool "PMC-Sierra MSP chipsets"
 	depends on EXPERIMENTAL
+	select CEVT_R4K
+	select CSRC_R4K
 	select DMA_NONCOHERENT
 	select SWAP_IO_SPACE
 	select NO_EXCEPT_FILL
@@ -717,6 +738,7 @@ config CAVIUM_OCTEON_REFERENCE_BOARD
 endchoice
 
 source "arch/mips/alchemy/Kconfig"
+source "arch/mips/ath79/Kconfig"
 source "arch/mips/bcm63xx/Kconfig"
 source "arch/mips/jazz/Kconfig"
 source "arch/mips/jz4740/Kconfig"
@@ -775,9 +797,6 @@ config SCHED_OMIT_FRAME_POINTER
 	bool
 	default y
 
-config GENERIC_HARDIRQS_NO__DO_IRQ
-	def_bool y
-
 #
 # Select some configuration options automatically based on user selections.
 #
@@ -883,6 +902,9 @@ config MIPS_DISABLE_OBSOLETE_IDE
 config SYNC_R4K
 	bool
 
+config MIPS_MACHINE
+	def_bool n
+
 config NO_IOPORT
 	def_bool n
 
@@ -2218,7 +2240,7 @@ config SECCOMP
 config USE_OF
 	bool "Flattened Device Tree support"
 	select OF
-	select OF_FLATTREE
+	select OF_EARLY_FLATTREE
 	help
 	  Include support for flattened device tree machine descriptions.
 
@@ -2400,4 +2422,20 @@ source "security/Kconfig"
 
 source "crypto/Kconfig"
 
+menuconfig VIRTUALIZATION
+	bool "Virtualization"
+	default n
+	---help---
+	  Say Y here to get to see options for using your Linux host to run other
+	  operating systems inside virtual machines (guests).
+	  This option alone does not add any kernel code.
+
+	  If you say N, all options in this submenu will be skipped and disabled.
+
+if VIRTUALIZATION
+
+source drivers/virtio/Kconfig
+
+endif # VIRTUALIZATION
+
 source "lib/Kconfig"
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/Kconfig.debug linux-libre-2.6.38-gnu1/arch/mips/Kconfig.debug
--- linux-libre-2.6.37-gnu1/arch/mips/Kconfig.debug	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/Kconfig.debug	2011-03-14 21:20:32.000000000 -0400
@@ -7,7 +7,7 @@ config TRACE_IRQFLAGS_SUPPORT
 source "lib/Kconfig.debug"
 
 config EARLY_PRINTK
-	bool "Early printk" if EMBEDDED
+	bool "Early printk" if EXPERT
 	depends on SYS_HAS_EARLY_PRINTK
 	default y
 	help
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/kernel/cpu-probe.c linux-libre-2.6.38-gnu1/arch/mips/kernel/cpu-probe.c
--- linux-libre-2.6.37-gnu1/arch/mips/kernel/cpu-probe.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/kernel/cpu-probe.c	2011-03-14 21:20:32.000000000 -0400
@@ -739,6 +739,8 @@ static inline unsigned int decode_config
 	    && cpu_has_tlb)
 		c->tlbsize += (config4 & MIPS_CONF4_MMUSIZEEXT) * 0x40;
 
+	c->kscratch_mask = (config4 >> 16) & 0xff;
+
 	return config4 & MIPS_CONF_M;
 }
 
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/kernel/ftrace.c linux-libre-2.6.38-gnu1/arch/mips/kernel/ftrace.c
--- linux-libre-2.6.37-gnu1/arch/mips/kernel/ftrace.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/kernel/ftrace.c	2011-03-14 21:20:32.000000000 -0400
@@ -17,29 +17,13 @@
 #include <asm/cacheflush.h>
 #include <asm/uasm.h>
 
-/*
- * If the Instruction Pointer is in module space (0xc0000000), return true;
- * otherwise, it is in kernel space (0x80000000), return false.
- *
- * FIXME: This will not work when the kernel space and module space are the
- * same. If they are the same, we need to modify scripts/recordmcount.pl,
- * ftrace_make_nop/call() and the other related parts to ensure the
- * enabling/disabling of the calling site to _mcount is right for both kernel
- * and module.
- */
-
-static inline int in_module(unsigned long ip)
-{
-	return ip & 0x40000000;
-}
+#include <asm-generic/sections.h>
 
 #ifdef CONFIG_DYNAMIC_FTRACE
 
 #define JAL 0x0c000000		/* jump & link: ip --> ra, jump to target */
 #define ADDR_MASK 0x03ffffff	/*  op_code|addr : 31...26|25 ....0 */
 
-#define INSN_B_1F_4 0x10000004	/* b 1f; offset = 4 */
-#define INSN_B_1F_5 0x10000005	/* b 1f; offset = 5 */
 #define INSN_NOP 0x00000000	/* nop */
 #define INSN_JAL(addr)	\
 	((unsigned int)(JAL | (((addr) >> 2) & ADDR_MASK)))
@@ -69,6 +53,20 @@ static inline void ftrace_dyn_arch_init_
 #endif
 }
 
+/*
+ * Check if the address is in kernel space
+ *
+ * Clone core_kernel_text() from kernel/extable.c, but doesn't call
+ * init_kernel_text() for Ftrace doesn't trace functions in init sections.
+ */
+static inline int in_kernel_space(unsigned long ip)
+{
+	if (ip >= (unsigned long)_stext &&
+	    ip <= (unsigned long)_etext)
+		return 1;
+	return 0;
+}
+
 static int ftrace_modify_code(unsigned long ip, unsigned int new_code)
 {
 	int faulted;
@@ -84,6 +82,42 @@ static int ftrace_modify_code(unsigned l
 	return 0;
 }
 
+/*
+ * The details about the calling site of mcount on MIPS
+ *
+ * 1. For kernel:
+ *
+ * move at, ra
+ * jal _mcount		--> nop
+ *
+ * 2. For modules:
+ *
+ * 2.1 For KBUILD_MCOUNT_RA_ADDRESS and CONFIG_32BIT
+ *
+ * lui v1, hi_16bit_of_mcount        --> b 1f (0x10000005)
+ * addiu v1, v1, low_16bit_of_mcount
+ * move at, ra
+ * move $12, ra_address
+ * jalr v1
+ *  sub sp, sp, 8
+ *                                  1: offset = 5 instructions
+ * 2.2 For the Other situations
+ *
+ * lui v1, hi_16bit_of_mcount        --> b 1f (0x10000004)
+ * addiu v1, v1, low_16bit_of_mcount
+ * move at, ra
+ * jalr v1
+ *  nop | move $12, ra_address | sub sp, sp, 8
+ *                                  1: offset = 4 instructions
+ */
+
+#if defined(KBUILD_MCOUNT_RA_ADDRESS) && defined(CONFIG_32BIT)
+#define MCOUNT_OFFSET_INSNS 5
+#else
+#define MCOUNT_OFFSET_INSNS 4
+#endif
+#define INSN_B_1F (0x10000000 | MCOUNT_OFFSET_INSNS)
+
 int ftrace_make_nop(struct module *mod,
 		    struct dyn_ftrace *rec, unsigned long addr)
 {
@@ -91,39 +125,11 @@ int ftrace_make_nop(struct module *mod,
 	unsigned long ip = rec->ip;
 
 	/*
-	 * We have compiled module with -mlong-calls, but compiled the kernel
-	 * without it, we need to cope with them respectively.
+	 * If ip is in kernel space, no long call, otherwise, long call is
+	 * needed.
 	 */
-	if (in_module(ip)) {
-#if defined(KBUILD_MCOUNT_RA_ADDRESS) && defined(CONFIG_32BIT)
-		/*
-		 * lui v1, hi_16bit_of_mcount        --> b 1f (0x10000005)
-		 * addiu v1, v1, low_16bit_of_mcount
-		 * move at, ra
-		 * move $12, ra_address
-		 * jalr v1
-		 *  sub sp, sp, 8
-		 *                                  1: offset = 5 instructions
-		 */
-		new = INSN_B_1F_5;
-#else
-		/*
-		 * lui v1, hi_16bit_of_mcount        --> b 1f (0x10000004)
-		 * addiu v1, v1, low_16bit_of_mcount
-		 * move at, ra
-		 * jalr v1
-		 *  nop | move $12, ra_address | sub sp, sp, 8
-		 *                                  1: offset = 4 instructions
-		 */
-		new = INSN_B_1F_4;
-#endif
-	} else {
-		/*
-		 * move at, ra
-		 * jal _mcount		--> nop
-		 */
-		new = INSN_NOP;
-	}
+	new = in_kernel_space(ip) ? INSN_NOP : INSN_B_1F;
+
 	return ftrace_modify_code(ip, new);
 }
 
@@ -132,8 +138,8 @@ int ftrace_make_call(struct dyn_ftrace *
 	unsigned int new;
 	unsigned long ip = rec->ip;
 
-	/* ip, module: 0xc0000000, kernel: 0x80000000 */
-	new = in_module(ip) ? insn_lui_v1_hi16_mcount : insn_jal_ftrace_caller;
+	new = in_kernel_space(ip) ? insn_jal_ftrace_caller :
+		insn_lui_v1_hi16_mcount;
 
 	return ftrace_modify_code(ip, new);
 }
@@ -190,29 +196,25 @@ int ftrace_disable_ftrace_graph_caller(v
 #define S_R_SP	(0xafb0 << 16)  /* s{d,w} R, offset(sp) */
 #define OFFSET_MASK	0xffff	/* stack offset range: 0 ~ PT_SIZE */
 
-unsigned long ftrace_get_parent_addr(unsigned long self_addr,
-				     unsigned long parent,
-				     unsigned long parent_addr,
-				     unsigned long fp)
+unsigned long ftrace_get_parent_ra_addr(unsigned long self_ra, unsigned long
+		old_parent_ra, unsigned long parent_ra_addr, unsigned long fp)
 {
-	unsigned long sp, ip, ra;
+	unsigned long sp, ip, tmp;
 	unsigned int code;
 	int faulted;
 
 	/*
-	 * For module, move the ip from calling site of mcount to the
-	 * instruction "lui v1, hi_16bit_of_mcount"(offset is 20), but for
-	 * kernel, move to the instruction "move ra, at"(offset is 12)
+	 * For module, move the ip from the return address after the
+	 * instruction "lui v1, hi_16bit_of_mcount"(offset is 24), but for
+	 * kernel, move after the instruction "move ra, at"(offset is 16)
 	 */
-	ip = self_addr - (in_module(self_addr) ? 20 : 12);
+	ip = self_ra - (in_kernel_space(self_ra) ? 16 : 24);
 
 	/*
 	 * search the text until finding the non-store instruction or "s{d,w}
 	 * ra, offset(sp)" instruction
 	 */
 	do {
-		ip -= 4;
-
 		/* get the code at "ip": code = *(unsigned int *)ip; */
 		safe_load_code(code, ip, faulted);
 
@@ -224,18 +226,20 @@ unsigned long ftrace_get_parent_addr(uns
 		 * store the ra on the stack
 		 */
 		if ((code & S_R_SP) != S_R_SP)
-			return parent_addr;
+			return parent_ra_addr;
 
-	} while (((code & S_RA_SP) != S_RA_SP));
+		/* Move to the next instruction */
+		ip -= 4;
+	} while ((code & S_RA_SP) != S_RA_SP);
 
 	sp = fp + (code & OFFSET_MASK);
 
-	/* ra = *(unsigned long *)sp; */
-	safe_load_stack(ra, sp, faulted);
+	/* tmp = *(unsigned long *)sp; */
+	safe_load_stack(tmp, sp, faulted);
 	if (unlikely(faulted))
 		return 0;
 
-	if (ra == parent)
+	if (tmp == old_parent_ra)
 		return sp;
 	return 0;
 }
@@ -246,21 +250,21 @@ unsigned long ftrace_get_parent_addr(uns
  * Hook the return address and push it in the stack of return addrs
  * in current thread info.
  */
-void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
+void prepare_ftrace_return(unsigned long *parent_ra_addr, unsigned long self_ra,
 			   unsigned long fp)
 {
-	unsigned long old;
+	unsigned long old_parent_ra;
 	struct ftrace_graph_ent trace;
 	unsigned long return_hooker = (unsigned long)
 	    &return_to_handler;
-	int faulted;
+	int faulted, insns;
 
 	if (unlikely(atomic_read(&current->tracing_graph_pause)))
 		return;
 
 	/*
-	 * "parent" is the stack address saved the return address of the caller
-	 * of _mcount.
+	 * "parent_ra_addr" is the stack address saved the return address of
+	 * the caller of _mcount.
 	 *
 	 * if the gcc < 4.5, a leaf function does not save the return address
 	 * in the stack address, so, we "emulate" one in _mcount's stack space,
@@ -275,37 +279,44 @@ void prepare_ftrace_return(unsigned long
 	 * do it in ftrace_graph_caller of mcount.S.
 	 */
 
-	/* old = *parent; */
-	safe_load_stack(old, parent, faulted);
+	/* old_parent_ra = *parent_ra_addr; */
+	safe_load_stack(old_parent_ra, parent_ra_addr, faulted);
 	if (unlikely(faulted))
 		goto out;
 #ifndef KBUILD_MCOUNT_RA_ADDRESS
-	parent = (unsigned long *)ftrace_get_parent_addr(self_addr, old,
-			(unsigned long)parent, fp);
+	parent_ra_addr = (unsigned long *)ftrace_get_parent_ra_addr(self_ra,
+			old_parent_ra, (unsigned long)parent_ra_addr, fp);
 	/*
 	 * If fails when getting the stack address of the non-leaf function's
 	 * ra, stop function graph tracer and return
 	 */
-	if (parent == 0)
+	if (parent_ra_addr == 0)
 		goto out;
 #endif
-	/* *parent = return_hooker; */
-	safe_store_stack(return_hooker, parent, faulted);
+	/* *parent_ra_addr = return_hooker; */
+	safe_store_stack(return_hooker, parent_ra_addr, faulted);
 	if (unlikely(faulted))
 		goto out;
 
-	if (ftrace_push_return_trace(old, self_addr, &trace.depth, fp) ==
-	    -EBUSY) {
-		*parent = old;
+	if (ftrace_push_return_trace(old_parent_ra, self_ra, &trace.depth, fp)
+	    == -EBUSY) {
+		*parent_ra_addr = old_parent_ra;
 		return;
 	}
 
-	trace.func = self_addr;
+	/*
+	 * Get the recorded ip of the current mcount calling site in the
+	 * __mcount_loc section, which will be used to filter the function
+	 * entries configured through the tracing/set_graph_function interface.
+	 */
+
+	insns = in_kernel_space(self_ra) ? 2 : MCOUNT_OFFSET_INSNS + 1;
+	trace.func = self_ra - (MCOUNT_INSN_SIZE * insns);
 
 	/* Only trace if the calling function expects to */
 	if (!ftrace_graph_entry(&trace)) {
 		current->curr_ret_stack--;
-		*parent = old;
+		*parent_ra_addr = old_parent_ra;
 	}
 	return;
 out:
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/kernel/jump_label.c linux-libre-2.6.38-gnu1/arch/mips/kernel/jump_label.c
--- linux-libre-2.6.37-gnu1/arch/mips/kernel/jump_label.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/kernel/jump_label.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,54 @@
+/*
+ * 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) 2010 Cavium Networks, Inc.
+ */
+
+#include <linux/jump_label.h>
+#include <linux/kernel.h>
+#include <linux/memory.h>
+#include <linux/mutex.h>
+#include <linux/types.h>
+#include <linux/cpu.h>
+
+#include <asm/cacheflush.h>
+#include <asm/inst.h>
+
+#ifdef HAVE_JUMP_LABEL
+
+#define J_RANGE_MASK ((1ul << 28) - 1)
+
+void arch_jump_label_transform(struct jump_entry *e,
+			       enum jump_label_type type)
+{
+	union mips_instruction insn;
+	union mips_instruction *insn_p =
+		(union mips_instruction *)(unsigned long)e->code;
+
+	/* Jump only works within a 256MB aligned region. */
+	BUG_ON((e->target & ~J_RANGE_MASK) != (e->code & ~J_RANGE_MASK));
+
+	/* Target must have 4 byte alignment. */
+	BUG_ON((e->target & 3) != 0);
+
+	if (type == JUMP_LABEL_ENABLE) {
+		insn.j_format.opcode = j_op;
+		insn.j_format.target = (e->target & J_RANGE_MASK) >> 2;
+	} else {
+		insn.word = 0; /* nop */
+	}
+
+	get_online_cpus();
+	mutex_lock(&text_mutex);
+	*insn_p = insn;
+
+	flush_icache_range((unsigned long)insn_p,
+			   (unsigned long)insn_p + sizeof(*insn_p));
+
+	mutex_unlock(&text_mutex);
+	put_online_cpus();
+}
+
+#endif /* HAVE_JUMP_LABEL */
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/kernel/Makefile linux-libre-2.6.38-gnu1/arch/mips/kernel/Makefile
--- linux-libre-2.6.37-gnu1/arch/mips/kernel/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/kernel/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -95,6 +95,7 @@ obj-$(CONFIG_GPIO_TXX9)		+= gpio_txx9.o
 obj-$(CONFIG_KEXEC)		+= machine_kexec.o relocate_kernel.o
 obj-$(CONFIG_EARLY_PRINTK)	+= early_printk.o
 obj-$(CONFIG_SPINLOCK_TEST)	+= spinlock_test.o
+obj-$(CONFIG_MIPS_MACHINE)	+= mips_machine.o
 
 obj-$(CONFIG_OF)		+= prom.o
 
@@ -106,4 +107,6 @@ obj-$(CONFIG_MIPS_CPUFREQ)	+= cpufreq/
 
 obj-$(CONFIG_HW_PERF_EVENTS)	+= perf_event.o
 
+obj-$(CONFIG_JUMP_LABEL)	+= jump_label.o
+
 CPPFLAGS_vmlinux.lds		:= $(KBUILD_CFLAGS)
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/kernel/mips_machine.c linux-libre-2.6.38-gnu1/arch/mips/kernel/mips_machine.c
--- linux-libre-2.6.37-gnu1/arch/mips/kernel/mips_machine.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/kernel/mips_machine.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,86 @@
+/*
+ *  Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License version 2 as published
+ *  by the Free Software Foundation.
+ *
+ */
+#include <linux/mm.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+
+#include <asm/mips_machine.h>
+
+static struct mips_machine *mips_machine __initdata;
+static char *mips_machine_name = "Unknown";
+
+#define for_each_machine(mach) \
+	for ((mach) = (struct mips_machine *)&__mips_machines_start; \
+	     (mach) && \
+	     (unsigned long)(mach) < (unsigned long)&__mips_machines_end; \
+	     (mach)++)
+
+__init void mips_set_machine_name(const char *name)
+{
+	char *p;
+
+	if (name == NULL)
+		return;
+
+	p = kstrdup(name, GFP_KERNEL);
+	if (!p)
+		pr_err("MIPS: no memory for machine_name\n");
+
+	mips_machine_name = p;
+}
+
+char *mips_get_machine_name(void)
+{
+	return mips_machine_name;
+}
+
+__init int mips_machtype_setup(char *id)
+{
+	struct mips_machine *mach;
+
+	for_each_machine(mach) {
+		if (mach->mach_id == NULL)
+			continue;
+
+		if (strcmp(mach->mach_id, id) == 0) {
+			mips_machtype = mach->mach_type;
+			return 0;
+		}
+	}
+
+	pr_err("MIPS: no machine found for id '%s', supported machines:\n", id);
+	pr_err("%-24s %s\n", "id", "name");
+	for_each_machine(mach)
+		pr_err("%-24s %s\n", mach->mach_id, mach->mach_name);
+
+	return 1;
+}
+
+__setup("machtype=", mips_machtype_setup);
+
+__init void mips_machine_setup(void)
+{
+	struct mips_machine *mach;
+
+	for_each_machine(mach) {
+		if (mips_machtype == mach->mach_type) {
+			mips_machine = mach;
+			break;
+		}
+	}
+
+	if (!mips_machine)
+		return;
+
+	mips_set_machine_name(mips_machine->mach_name);
+	pr_info("MIPS: machine is %s\n", mips_machine_name);
+
+	if (mips_machine->mach_setup)
+		mips_machine->mach_setup();
+}
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/kernel/module.c linux-libre-2.6.38-gnu1/arch/mips/kernel/module.c
--- linux-libre-2.6.37-gnu1/arch/mips/kernel/module.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/kernel/module.c	2011-03-14 21:20:32.000000000 -0400
@@ -30,6 +30,8 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/spinlock.h>
+#include <linux/jump_label.h>
+
 #include <asm/pgtable.h>	/* MODULE_START */
 
 struct mips_hi16 {
@@ -46,17 +48,9 @@ static DEFINE_SPINLOCK(dbe_lock);
 void *module_alloc(unsigned long size)
 {
 #ifdef MODULE_START
-	struct vm_struct *area;
-
-	size = PAGE_ALIGN(size);
-	if (!size)
-		return NULL;
-
-	area = __get_vm_area(size, VM_ALLOC, MODULE_START, MODULE_END);
-	if (!area)
-		return NULL;
-
-	return __vmalloc_area(area, GFP_KERNEL, PAGE_KERNEL);
+	return __vmalloc_node_range(size, 1, MODULE_START, MODULE_END,
+				GFP_KERNEL, PAGE_KERNEL, -1,
+				__builtin_return_address(0));
 #else
 	if (size == 0)
 		return NULL;
@@ -390,6 +384,9 @@ int module_finalize(const Elf_Ehdr *hdr,
 	const Elf_Shdr *s;
 	char *secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
 
+	/* Make jump label nops. */
+	jump_label_apply_nops(me);
+
 	INIT_LIST_HEAD(&me->arch.dbe_list);
 	for (s = sechdrs; s < sechdrs + hdr->e_shnum; s++) {
 		if (strcmp("__dbe_table", secstrings + s->sh_name) != 0)
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/kernel/perf_event.c linux-libre-2.6.38-gnu1/arch/mips/kernel/perf_event.c
--- linux-libre-2.6.37-gnu1/arch/mips/kernel/perf_event.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/kernel/perf_event.c	2011-03-14 21:20:32.000000000 -0400
@@ -161,41 +161,6 @@ mipspmu_event_set_period(struct perf_eve
 	return ret;
 }
 
-static int mipspmu_enable(struct perf_event *event)
-{
-	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
-	struct hw_perf_event *hwc = &event->hw;
-	int idx;
-	int err = 0;
-
-	/* 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;
-
-	/* Set the period for the event. */
-	mipspmu_event_set_period(event, hwc, idx);
-
-	/* Enable the event. */
-	mipspmu->enable_event(hwc, idx);
-
-	/* Propagate our changes to the userspace mapping. */
-	perf_event_update_userpage(event);
-
-out:
-	return err;
-}
-
 static void mipspmu_event_update(struct perf_event *event,
 			struct hw_perf_event *hwc,
 			int idx)
@@ -204,7 +169,7 @@ static void mipspmu_event_update(struct
 	unsigned long flags;
 	int shift = 64 - TOTAL_BITS;
 	s64 prev_raw_count, new_raw_count;
-	s64 delta;
+	u64 delta;
 
 again:
 	prev_raw_count = local64_read(&hwc->prev_count);
@@ -231,32 +196,90 @@ again:
 	return;
 }
 
-static void mipspmu_disable(struct perf_event *event)
+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 = hwc->idx;
+	int idx;
+	int err = 0;
 
+	perf_pmu_disable(event->pmu);
 
-	WARN_ON(idx < 0 || idx >= mipspmu->num_counters);
+	/* To look for a free counter for this event. */
+	idx = mipspmu->alloc_counter(cpuc, hwc);
+	if (idx < 0) {
+		err = idx;
+		goto out;
+	}
 
-	/* We are working on a local event. */
+	/*
+	 * 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;
 
-	barrier();
-
-	mipspmu_event_update(event, hwc, idx);
-	cpuc->events[idx] = NULL;
-	clear_bit(idx, cpuc->used_mask);
+	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_unthrottle(struct perf_event *event)
+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;
 
-	mipspmu->enable_event(hwc, 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)
@@ -270,12 +293,17 @@ static void mipspmu_read(struct perf_eve
 	mipspmu_event_update(event, hwc, hwc->idx);
 }
 
-static struct pmu pmu = {
-	.enable		= mipspmu_enable,
-	.disable	= mipspmu_disable,
-	.unthrottle	= mipspmu_unthrottle,
-	.read		= mipspmu_read,
-};
+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);
@@ -318,6 +346,82 @@ static void mipspmu_free_irq(void)
 		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)
 {
@@ -382,8 +486,9 @@ static int validate_event(struct cpu_hw_
 {
 	struct hw_perf_event fake_hwc = event->hw;
 
-	if (event->pmu && event->pmu != &pmu)
-		return 0;
+	/* 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;
 }
@@ -409,73 +514,6 @@ static int validate_group(struct perf_ev
 	return 0;
 }
 
-/*
- * 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);
-	}
-}
-
-const struct pmu *hw_perf_event_init(struct perf_event *event)
-{
-	int err = 0;
-
-	if (!mipspmu || event->cpu >= nr_cpumask_bits ||
-		(event->cpu >= 0 && !cpu_online(event->cpu)))
-		return ERR_PTR(-ENODEV);
-
-	if (!atomic_inc_not_zero(&active_events)) {
-		if (atomic_read(&active_events) > MIPS_MAX_HWEVENTS) {
-			atomic_dec(&active_events);
-			return ERR_PTR(-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_PTR(err);
-
-	err = __hw_perf_event_init(event);
-	if (err)
-		hw_perf_event_destroy(event);
-
-	return err ? ERR_PTR(err) : &pmu;
-}
-
-void hw_perf_enable(void)
-{
-	if (mipspmu)
-		mipspmu->start();
-}
-
-void hw_perf_disable(void)
-{
-	if (mipspmu)
-		mipspmu->stop();
-}
-
 /* This is needed by specific irq handlers in perf_event_*.c */
 static void
 handle_associated_event(struct cpu_hw_events *cpuc,
@@ -496,21 +534,13 @@ handle_associated_event(struct cpu_hw_ev
 #include "perf_event_mipsxx.c"
 
 /* Callchain handling code. */
-static inline void
-callchain_store(struct perf_callchain_entry *entry,
-		u64 ip)
-{
-	if (entry->nr < PERF_MAX_STACK_DEPTH)
-		entry->ip[entry->nr++] = ip;
-}
 
 /*
  * Leave userspace callchain empty for now. When we find a way to trace
  * the user stack callchains, we add here.
  */
-static void
-perf_callchain_user(struct pt_regs *regs,
-		    struct perf_callchain_entry *entry)
+void perf_callchain_user(struct perf_callchain_entry *entry,
+		    struct pt_regs *regs)
 {
 }
 
@@ -523,23 +553,21 @@ static void save_raw_perf_callchain(stru
 	while (!kstack_end(sp)) {
 		addr = *sp++;
 		if (__kernel_text_address(addr)) {
-			callchain_store(entry, addr);
+			perf_callchain_store(entry, addr);
 			if (entry->nr >= PERF_MAX_STACK_DEPTH)
 				break;
 		}
 	}
 }
 
-static void
-perf_callchain_kernel(struct pt_regs *regs,
-		      struct perf_callchain_entry *entry)
+void perf_callchain_kernel(struct perf_callchain_entry *entry,
+		      struct pt_regs *regs)
 {
 	unsigned long sp = regs->regs[29];
 #ifdef CONFIG_KALLSYMS
 	unsigned long ra = regs->regs[31];
 	unsigned long pc = regs->cp0_epc;
 
-	callchain_store(entry, PERF_CONTEXT_KERNEL);
 	if (raw_show_trace || !__kernel_text_address(pc)) {
 		unsigned long stack_page =
 			(unsigned long)task_stack_page(current);
@@ -549,53 +577,12 @@ perf_callchain_kernel(struct pt_regs *re
 		return;
 	}
 	do {
-		callchain_store(entry, pc);
+		perf_callchain_store(entry, pc);
 		if (entry->nr >= PERF_MAX_STACK_DEPTH)
 			break;
 		pc = unwind_stack(current, &sp, pc, &ra);
 	} while (pc);
 #else
-	callchain_store(entry, PERF_CONTEXT_KERNEL);
 	save_raw_perf_callchain(entry, sp);
 #endif
 }
-
-static void
-perf_do_callchain(struct pt_regs *regs,
-		  struct perf_callchain_entry *entry)
-{
-	int is_user;
-
-	if (!regs)
-		return;
-
-	is_user = user_mode(regs);
-
-	if (!current || !current->pid)
-		return;
-
-	if (is_user && current->state != TASK_RUNNING)
-		return;
-
-	if (!is_user) {
-		perf_callchain_kernel(regs, entry);
-		if (current->mm)
-			regs = task_pt_regs(current);
-		else
-			regs = NULL;
-	}
-	if (regs)
-		perf_callchain_user(regs, entry);
-}
-
-static DEFINE_PER_CPU(struct perf_callchain_entry, pmc_irq_entry);
-
-struct perf_callchain_entry *
-perf_callchain(struct pt_regs *regs)
-{
-	struct perf_callchain_entry *entry = &__get_cpu_var(pmc_irq_entry);
-
-	entry->nr = 0;
-	perf_do_callchain(regs, entry);
-	return entry;
-}
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/kernel/perf_event_mipsxx.c linux-libre-2.6.38-gnu1/arch/mips/kernel/perf_event_mipsxx.c
--- linux-libre-2.6.37-gnu1/arch/mips/kernel/perf_event_mipsxx.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/kernel/perf_event_mipsxx.c	2011-03-14 21:20:32.000000000 -0400
@@ -696,7 +696,7 @@ static int mipsxx_pmu_handle_shared_irq(
 	 * interrupt, not NMI.
 	 */
 	if (handled == IRQ_HANDLED)
-		perf_event_do_pending();
+		irq_work_run();
 
 #ifdef CONFIG_MIPS_MT_SMP
 	read_unlock(&pmuint_rwlock);
@@ -1045,8 +1045,10 @@ init_hw_perf_events(void)
 			"CPU, irq %d%s\n", mipspmu->name, counters, irq,
 			irq < 0 ? " (share with timer interrupt)" : "");
 
+	perf_pmu_register(&pmu, "cpu", PERF_TYPE_RAW);
+
 	return 0;
 }
-arch_initcall(init_hw_perf_events);
+early_initcall(init_hw_perf_events);
 
 #endif /* defined(CONFIG_CPU_MIPS32)... */
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/kernel/proc.c linux-libre-2.6.38-gnu1/arch/mips/kernel/proc.c
--- linux-libre-2.6.37-gnu1/arch/mips/kernel/proc.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/kernel/proc.c	2011-03-14 21:20:32.000000000 -0400
@@ -12,6 +12,7 @@
 #include <asm/cpu-features.h>
 #include <asm/mipsregs.h>
 #include <asm/processor.h>
+#include <asm/mips_machine.h>
 
 unsigned int vced_count, vcei_count;
 
@@ -31,8 +32,12 @@ static int show_cpuinfo(struct seq_file
 	/*
 	 * For the first processor also print the system type
 	 */
-	if (n == 0)
+	if (n == 0) {
 		seq_printf(m, "system type\t\t: %s\n", get_system_type());
+		if (mips_get_machine_name())
+			seq_printf(m, "machine\t\t\t: %s\n",
+				   mips_get_machine_name());
+	}
 
 	seq_printf(m, "processor\t\t: %ld\n", n);
 	sprintf(fmt, "cpu model\t\t: %%s V%%d.%%d%s\n",
@@ -69,6 +74,8 @@ static int show_cpuinfo(struct seq_file
 		);
 	seq_printf(m, "shadow register sets\t: %d\n",
 		       cpu_data[n].srsets);
+	seq_printf(m, "kscratch registers\t: %d\n",
+		   hweight8(cpu_data[n].kscratch_mask));
 	seq_printf(m, "core\t\t\t: %d\n", cpu_data[n].core);
 
 	sprintf(fmt, "VCE%%c exceptions\t\t: %s\n",
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/kernel/prom.c linux-libre-2.6.38-gnu1/arch/mips/kernel/prom.c
--- linux-libre-2.6.37-gnu1/arch/mips/kernel/prom.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/kernel/prom.c	2011-03-14 21:20:32.000000000 -0400
@@ -45,11 +45,9 @@ void __init free_mem_mach(unsigned long
 	return free_bootmem(addr, size);
 }
 
-u64 __init early_init_dt_alloc_memory_arch(u64 size, u64 align)
+void * __init early_init_dt_alloc_memory_arch(u64 size, u64 align)
 {
-	return virt_to_phys(
-		__alloc_bootmem(size, align, __pa(MAX_DMA_ADDRESS))
-		);
+	return __alloc_bootmem(size, align, __pa(MAX_DMA_ADDRESS));
 }
 
 #ifdef CONFIG_BLK_DEV_INITRD
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/kernel/setup.c linux-libre-2.6.38-gnu1/arch/mips/kernel/setup.c
--- linux-libre-2.6.37-gnu1/arch/mips/kernel/setup.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/kernel/setup.c	2011-03-14 21:20:32.000000000 -0400
@@ -70,7 +70,7 @@ static char __initdata builtin_cmdline[C
  * mips_io_port_base is the begin of the address space to which x86 style
  * I/O ports are mapped.
  */
-const unsigned long mips_io_port_base __read_mostly = -1;
+const unsigned long mips_io_port_base = -1;
 EXPORT_SYMBOL(mips_io_port_base);
 
 static struct resource code_resource = { .name = "Kernel code", };
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/kernel/signal32.c linux-libre-2.6.38-gnu1/arch/mips/kernel/signal32.c
--- linux-libre-2.6.37-gnu1/arch/mips/kernel/signal32.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/kernel/signal32.c	2011-03-14 21:20:32.000000000 -0400
@@ -115,7 +115,7 @@ static int protected_save_fp_context32(s
 
 static int protected_restore_fp_context32(struct sigcontext32 __user *sc)
 {
-	int err, tmp;
+	int err, tmp __maybe_unused;
 	while (1) {
 		lock_fpu_owner();
 		own_fpu_inatomic(0);
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/kernel/signal.c linux-libre-2.6.38-gnu1/arch/mips/kernel/signal.c
--- linux-libre-2.6.37-gnu1/arch/mips/kernel/signal.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/kernel/signal.c	2011-03-14 21:20:32.000000000 -0400
@@ -84,7 +84,7 @@ static int protected_save_fp_context(str
 
 static int protected_restore_fp_context(struct sigcontext __user *sc)
 {
-	int err, tmp;
+	int err, tmp __maybe_unused;
 	while (1) {
 		lock_fpu_owner();
 		own_fpu_inatomic(0);
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/kernel/smp.c linux-libre-2.6.38-gnu1/arch/mips/kernel/smp.c
--- linux-libre-2.6.37-gnu1/arch/mips/kernel/smp.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/kernel/smp.c	2011-03-14 21:20:32.000000000 -0400
@@ -193,6 +193,22 @@ void __devinit smp_prepare_boot_cpu(void
  */
 static struct task_struct *cpu_idle_thread[NR_CPUS];
 
+struct create_idle {
+	struct work_struct work;
+	struct task_struct *idle;
+	struct completion done;
+	int cpu;
+};
+
+static void __cpuinit do_fork_idle(struct work_struct *work)
+{
+	struct create_idle *c_idle =
+		container_of(work, struct create_idle, work);
+
+	c_idle->idle = fork_idle(c_idle->cpu);
+	complete(&c_idle->done);
+}
+
 int __cpuinit __cpu_up(unsigned int cpu)
 {
 	struct task_struct *idle;
@@ -203,8 +219,19 @@ int __cpuinit __cpu_up(unsigned int cpu)
 	 * Linux can schedule processes on this slave.
 	 */
 	if (!cpu_idle_thread[cpu]) {
-		idle = fork_idle(cpu);
-		cpu_idle_thread[cpu] = idle;
+		/*
+		 * Schedule work item to avoid forking user task
+		 * Ported from arch/x86/kernel/smpboot.c
+		 */
+		struct create_idle c_idle = {
+			.cpu    = cpu,
+			.done   = COMPLETION_INITIALIZER_ONSTACK(c_idle.done),
+		};
+
+		INIT_WORK_ONSTACK(&c_idle.work, do_fork_idle);
+		schedule_work(&c_idle.work);
+		wait_for_completion(&c_idle.done);
+		idle = cpu_idle_thread[cpu] = c_idle.idle;
 
 		if (IS_ERR(idle))
 			panic(KERN_ERR "Fork failed for CPU %d", cpu);
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/kernel/syscall.c linux-libre-2.6.38-gnu1/arch/mips/kernel/syscall.c
--- linux-libre-2.6.37-gnu1/arch/mips/kernel/syscall.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/kernel/syscall.c	2011-03-14 21:20:32.000000000 -0400
@@ -383,12 +383,11 @@ save_static_function(sys_sysmips);
 static int __used noinline
 _sys_sysmips(nabi_no_regargs struct pt_regs regs)
 {
-	long cmd, arg1, arg2, arg3;
+	long cmd, arg1, arg2;
 
 	cmd = regs.regs[4];
 	arg1 = regs.regs[5];
 	arg2 = regs.regs[6];
-	arg3 = regs.regs[7];
 
 	switch (cmd) {
 	case MIPS_ATOMIC_SET:
@@ -405,7 +404,7 @@ _sys_sysmips(nabi_no_regargs struct pt_r
 		if (arg1 & 2)
 			set_thread_flag(TIF_LOGADE);
 		else
-			clear_thread_flag(TIF_FIXADE);
+			clear_thread_flag(TIF_LOGADE);
 
 		return 0;
 
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/kernel/traps.c linux-libre-2.6.38-gnu1/arch/mips/kernel/traps.c
--- linux-libre-2.6.37-gnu1/arch/mips/kernel/traps.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/kernel/traps.c	2011-03-14 21:20:32.000000000 -0400
@@ -1592,7 +1592,6 @@ void __cpuinit per_cpu_trap_init(void)
 #endif /* CONFIG_MIPS_MT_SMTC */
 
 	cpu_data[cpu].asid_cache = ASID_FIRST_VERSION;
-	TLBMISS_HANDLER_SETUP();
 
 	atomic_inc(&init_mm.mm_count);
 	current->active_mm = &init_mm;
@@ -1614,6 +1613,7 @@ void __cpuinit per_cpu_trap_init(void)
 		write_c0_wired(0);
 	}
 #endif /* CONFIG_MIPS_MT_SMTC */
+	TLBMISS_HANDLER_SETUP();
 }
 
 /* Install CPU exception handler */
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/kernel/vmlinux.lds.S linux-libre-2.6.38-gnu1/arch/mips/kernel/vmlinux.lds.S
--- linux-libre-2.6.37-gnu1/arch/mips/kernel/vmlinux.lds.S	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/kernel/vmlinux.lds.S	2011-03-14 21:20:32.000000000 -0400
@@ -98,6 +98,13 @@ SECTIONS
 	INIT_TEXT_SECTION(PAGE_SIZE)
 	INIT_DATA_SECTION(16)
 
+	. = ALIGN(4);
+	.mips.machines.init : AT(ADDR(.mips.machines.init) - LOAD_OFFSET) {
+		__mips_machines_start = .;
+		*(.mips.machines.init)
+		__mips_machines_end = .;
+	}
+
 	/* .exit.text is discarded at runtime, not link time, to deal with
 	 * references from .rodata
 	 */
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/kernel/vpe.c linux-libre-2.6.38-gnu1/arch/mips/kernel/vpe.c
--- linux-libre-2.6.37-gnu1/arch/mips/kernel/vpe.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/kernel/vpe.c	2011-03-14 21:20:32.000000000 -0400
@@ -148,9 +148,9 @@ struct {
 	spinlock_t tc_list_lock;
 	struct list_head tc_list;	/* Thread contexts */
 } vpecontrol = {
-	.vpe_list_lock	= SPIN_LOCK_UNLOCKED,
+	.vpe_list_lock	= __SPIN_LOCK_UNLOCKED(vpe_list_lock),
 	.vpe_list	= LIST_HEAD_INIT(vpecontrol.vpe_list),
-	.tc_list_lock	= SPIN_LOCK_UNLOCKED,
+	.tc_list_lock	= __SPIN_LOCK_UNLOCKED(tc_list_lock),
 	.tc_list	= LIST_HEAD_INIT(vpecontrol.tc_list)
 };
 
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/loongson/common/cmdline.c linux-libre-2.6.38-gnu1/arch/mips/loongson/common/cmdline.c
--- linux-libre-2.6.37-gnu1/arch/mips/loongson/common/cmdline.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/loongson/common/cmdline.c	2011-03-14 21:20:32.000000000 -0400
@@ -44,10 +44,5 @@ void __init prom_init_cmdline(void)
 		strcat(arcs_cmdline, " ");
 	}
 
-	if ((strstr(arcs_cmdline, "console=")) == NULL)
-		strcat(arcs_cmdline, " console=ttyS0,115200");
-	if ((strstr(arcs_cmdline, "root=")) == NULL)
-		strcat(arcs_cmdline, " root=/dev/hda1");
-
 	prom_init_machtype();
 }
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/loongson/common/machtype.c linux-libre-2.6.38-gnu1/arch/mips/loongson/common/machtype.c
--- linux-libre-2.6.37-gnu1/arch/mips/loongson/common/machtype.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/loongson/common/machtype.c	2011-03-14 21:20:32.000000000 -0400
@@ -41,7 +41,7 @@ void __weak __init mach_prom_init_machty
 
 void __init prom_init_machtype(void)
 {
-	char *p, str[MACHTYPE_LEN];
+	char *p, str[MACHTYPE_LEN + 1];
 	int machtype = MACH_LEMOTE_FL2E;
 
 	mips_machtype = LOONGSON_MACHTYPE;
@@ -53,6 +53,7 @@ void __init prom_init_machtype(void)
 	}
 	p += strlen("machtype=");
 	strncpy(str, p, MACHTYPE_LEN);
+	str[MACHTYPE_LEN] = '\0';
 	p = strstr(str, " ");
 	if (p)
 		*p = '\0';
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/loongson/common/pm.c linux-libre-2.6.38-gnu1/arch/mips/loongson/common/pm.c
--- linux-libre-2.6.37-gnu1/arch/mips/loongson/common/pm.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/loongson/common/pm.c	2011-03-14 21:20:32.000000000 -0400
@@ -147,7 +147,7 @@ static int loongson_pm_valid_state(suspe
 	}
 }
 
-static struct platform_suspend_ops loongson_pm_ops = {
+static const struct platform_suspend_ops loongson_pm_ops = {
 	.valid	= loongson_pm_valid_state,
 	.enter	= loongson_pm_enter,
 };
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/loongson/Kconfig linux-libre-2.6.38-gnu1/arch/mips/loongson/Kconfig
--- linux-libre-2.6.37-gnu1/arch/mips/loongson/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/loongson/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -1,6 +1,7 @@
+if MACH_LOONGSON
+
 choice
 	prompt "Machine Type"
-	depends on MACH_LOONGSON
 
 config LEMOTE_FULOONG2E
 	bool "Lemote Fuloong(2e) mini-PC"
@@ -87,3 +88,5 @@ config LOONGSON_UART_BASE
 config LOONGSON_MC146818
 	bool
 	default n
+
+endif # MACH_LOONGSON
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/math-emu/ieee754int.h linux-libre-2.6.38-gnu1/arch/mips/math-emu/ieee754int.h
--- linux-libre-2.6.37-gnu1/arch/mips/math-emu/ieee754int.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/math-emu/ieee754int.h	2011-03-14 21:20:32.000000000 -0400
@@ -70,7 +70,7 @@
 
 
 #define COMPXSP \
-  unsigned xm; int xe; int xs; int xc
+  unsigned xm; int xe; int xs __maybe_unused; int xc
 
 #define COMPYSP \
   unsigned ym; int ye; int ys; int yc
@@ -104,7 +104,7 @@
 
 
 #define COMPXDP \
-u64 xm; int xe; int xs; int xc
+u64 xm; int xe; int xs __maybe_unused; int xc
 
 #define COMPYDP \
 u64 ym; int ye; int ys; int yc
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/mm/init.c linux-libre-2.6.38-gnu1/arch/mips/mm/init.c
--- linux-libre-2.6.37-gnu1/arch/mips/mm/init.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/mm/init.c	2011-03-14 21:20:32.000000000 -0400
@@ -324,7 +324,7 @@ int page_is_ram(unsigned long pagenr)
 void __init paging_init(void)
 {
 	unsigned long max_zone_pfns[MAX_NR_ZONES];
-	unsigned long lastpfn;
+	unsigned long lastpfn __maybe_unused;
 
 	pagetable_init();
 
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/mm/tlbex.c linux-libre-2.6.38-gnu1/arch/mips/mm/tlbex.c
--- linux-libre-2.6.37-gnu1/arch/mips/mm/tlbex.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/mm/tlbex.c	2011-03-14 21:20:32.000000000 -0400
@@ -26,8 +26,10 @@
 #include <linux/smp.h>
 #include <linux/string.h>
 #include <linux/init.h>
+#include <linux/cache.h>
 
-#include <asm/mmu_context.h>
+#include <asm/cacheflush.h>
+#include <asm/pgtable.h>
 #include <asm/war.h>
 #include <asm/uasm.h>
 
@@ -63,6 +65,54 @@ static inline int __maybe_unused r10000_
 	return R10000_LLSC_WAR;
 }
 
+static int use_bbit_insns(void)
+{
+	switch (current_cpu_type()) {
+	case CPU_CAVIUM_OCTEON:
+	case CPU_CAVIUM_OCTEON_PLUS:
+	case CPU_CAVIUM_OCTEON2:
+		return 1;
+	default:
+		return 0;
+	}
+}
+
+static int use_lwx_insns(void)
+{
+	switch (current_cpu_type()) {
+	case CPU_CAVIUM_OCTEON2:
+		return 1;
+	default:
+		return 0;
+	}
+}
+#if defined(CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE) && \
+    CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE > 0
+static bool scratchpad_available(void)
+{
+	return true;
+}
+static int scratchpad_offset(int i)
+{
+	/*
+	 * CVMSEG starts at address -32768 and extends for
+	 * CAVIUM_OCTEON_CVMSEG_SIZE 128 byte cache lines.
+	 */
+	i += 1; /* Kernel use starts at the top and works down. */
+	return CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE * 128 - (8 * i) - 32768;
+}
+#else
+static bool scratchpad_available(void)
+{
+	return false;
+}
+static int scratchpad_offset(int i)
+{
+	BUG();
+	/* Really unreachable, but evidently some GCC want this. */
+	return 0;
+}
+#endif
 /*
  * Found by experiment: At least some revisions of the 4kc throw under
  * some circumstances a machine check exception, triggered by invalid
@@ -173,11 +223,41 @@ static struct uasm_reloc relocs[128] __c
 static int check_for_high_segbits __cpuinitdata;
 #endif
 
+static int check_for_high_segbits __cpuinitdata;
+
+static unsigned int kscratch_used_mask __cpuinitdata;
+
+static int __cpuinit allocate_kscratch(void)
+{
+	int r;
+	unsigned int a = cpu_data[0].kscratch_mask & ~kscratch_used_mask;
+
+	r = ffs(a);
+
+	if (r == 0)
+		return -1;
+
+	r--; /* make it zero based */
+
+	kscratch_used_mask |= (1 << r);
+
+	return r;
+}
+
+static int scratch_reg __cpuinitdata;
+static int pgd_reg __cpuinitdata;
+enum vmalloc64_mode {not_refill, refill_scratch, refill_noscratch};
+
 #ifndef CONFIG_MIPS_PGD_C0_CONTEXT
+
 /*
  * CONFIG_MIPS_PGD_C0_CONTEXT implies 64 bit and lack of pgd_current,
  * we cannot do r3000 under these circumstances.
+ *
+ * Declare pgd_current here instead of including mmu_context.h to avoid type
+ * conflicts for tlbmiss_handler_setup_pgd
  */
+extern unsigned long pgd_current[];
 
 /*
  * The R3000 TLB handler is simple.
@@ -440,21 +520,43 @@ static __cpuinit __maybe_unused void bui
 static __cpuinit void build_restore_pagemask(u32 **p,
 					     struct uasm_reloc **r,
 					     unsigned int tmp,
-					     enum label_id lid)
+					     enum label_id lid,
+					     int restore_scratch)
 {
-	/* Reset default page size */
-	if (PM_DEFAULT_MASK >> 16) {
-		uasm_i_lui(p, tmp, PM_DEFAULT_MASK >> 16);
-		uasm_i_ori(p, tmp, tmp, PM_DEFAULT_MASK & 0xffff);
-		uasm_il_b(p, r, lid);
-		uasm_i_mtc0(p, tmp, C0_PAGEMASK);
-	} else if (PM_DEFAULT_MASK) {
-		uasm_i_ori(p, tmp, 0, PM_DEFAULT_MASK);
-		uasm_il_b(p, r, lid);
-		uasm_i_mtc0(p, tmp, C0_PAGEMASK);
+	if (restore_scratch) {
+		/* Reset default page size */
+		if (PM_DEFAULT_MASK >> 16) {
+			uasm_i_lui(p, tmp, PM_DEFAULT_MASK >> 16);
+			uasm_i_ori(p, tmp, tmp, PM_DEFAULT_MASK & 0xffff);
+			uasm_i_mtc0(p, tmp, C0_PAGEMASK);
+			uasm_il_b(p, r, lid);
+		} else if (PM_DEFAULT_MASK) {
+			uasm_i_ori(p, tmp, 0, PM_DEFAULT_MASK);
+			uasm_i_mtc0(p, tmp, C0_PAGEMASK);
+			uasm_il_b(p, r, lid);
+		} else {
+			uasm_i_mtc0(p, 0, C0_PAGEMASK);
+			uasm_il_b(p, r, lid);
+		}
+		if (scratch_reg > 0)
+			UASM_i_MFC0(p, 1, 31, scratch_reg);
+		else
+			UASM_i_LW(p, 1, scratchpad_offset(0), 0);
 	} else {
-		uasm_il_b(p, r, lid);
-		uasm_i_mtc0(p, 0, C0_PAGEMASK);
+		/* Reset default page size */
+		if (PM_DEFAULT_MASK >> 16) {
+			uasm_i_lui(p, tmp, PM_DEFAULT_MASK >> 16);
+			uasm_i_ori(p, tmp, tmp, PM_DEFAULT_MASK & 0xffff);
+			uasm_il_b(p, r, lid);
+			uasm_i_mtc0(p, tmp, C0_PAGEMASK);
+		} else if (PM_DEFAULT_MASK) {
+			uasm_i_ori(p, tmp, 0, PM_DEFAULT_MASK);
+			uasm_il_b(p, r, lid);
+			uasm_i_mtc0(p, tmp, C0_PAGEMASK);
+		} else {
+			uasm_il_b(p, r, lid);
+			uasm_i_mtc0(p, 0, C0_PAGEMASK);
+		}
 	}
 }
 
@@ -462,7 +564,8 @@ static __cpuinit void build_huge_tlb_wri
 						 struct uasm_label **l,
 						 struct uasm_reloc **r,
 						 unsigned int tmp,
-						 enum tlb_write_entry wmode)
+						 enum tlb_write_entry wmode,
+						 int restore_scratch)
 {
 	/* Set huge page tlb entry size */
 	uasm_i_lui(p, tmp, PM_HUGE_MASK >> 16);
@@ -471,7 +574,7 @@ static __cpuinit void build_huge_tlb_wri
 
 	build_tlb_write_entry(p, l, r, wmode);
 
-	build_restore_pagemask(p, r, tmp, label_leave);
+	build_restore_pagemask(p, r, tmp, label_leave, restore_scratch);
 }
 
 /*
@@ -482,8 +585,12 @@ build_is_huge_pte(u32 **p, struct uasm_r
 		unsigned int pmd, int lid)
 {
 	UASM_i_LW(p, tmp, 0, pmd);
-	uasm_i_andi(p, tmp, tmp, _PAGE_HUGE);
-	uasm_il_bnez(p, r, tmp, lid);
+	if (use_bbit_insns()) {
+		uasm_il_bbit1(p, r, tmp, ilog2(_PAGE_HUGE), lid);
+	} else {
+		uasm_i_andi(p, tmp, tmp, _PAGE_HUGE);
+		uasm_il_bnez(p, r, tmp, lid);
+	}
 }
 
 static __cpuinit void build_huge_update_entries(u32 **p,
@@ -532,7 +639,7 @@ static __cpuinit void build_huge_handler
 	UASM_i_SW(p, pte, 0, ptr);
 #endif
 	build_huge_update_entries(p, pte, ptr);
-	build_huge_tlb_write_entry(p, l, r, pte, tlb_indexed);
+	build_huge_tlb_write_entry(p, l, r, pte, tlb_indexed, 0);
 }
 #endif /* CONFIG_HUGETLB_PAGE */
 
@@ -573,13 +680,22 @@ build_get_pmde64(u32 **p, struct uasm_la
 	/* No uasm_i_nop needed here, since the next insn doesn't touch TMP. */
 
 #ifdef CONFIG_MIPS_PGD_C0_CONTEXT
-	/*
-	 * &pgd << 11 stored in CONTEXT [23..63].
-	 */
-	UASM_i_MFC0(p, ptr, C0_CONTEXT);
-	uasm_i_dins(p, ptr, 0, 0, 23); /* Clear lower 23 bits of context. */
-	uasm_i_ori(p, ptr, ptr, 0x540); /* 1 0  1 0 1  << 6  xkphys cached */
-	uasm_i_drotr(p, ptr, ptr, 11);
+	if (pgd_reg != -1) {
+		/* pgd is in pgd_reg */
+		UASM_i_MFC0(p, ptr, 31, pgd_reg);
+	} else {
+		/*
+		 * &pgd << 11 stored in CONTEXT [23..63].
+		 */
+		UASM_i_MFC0(p, ptr, C0_CONTEXT);
+
+		/* Clear lower 23 bits of context. */
+		uasm_i_dins(p, ptr, 0, 0, 23);
+
+		/* 1 0  1 0 1  << 6  xkphys cached */
+		uasm_i_ori(p, ptr, ptr, 0x540);
+		uasm_i_drotr(p, ptr, ptr, 11);
+	}
 #elif defined(CONFIG_SMP)
 # ifdef  CONFIG_MIPS_MT_SMTC
 	/*
@@ -620,7 +736,6 @@ build_get_pmde64(u32 **p, struct uasm_la
 #endif
 }
 
-enum vmalloc64_mode {not_refill, refill};
 /*
  * BVADDR is the faulting address, PTR is scratch.
  * PTR will hold the pgd for vmalloc.
@@ -638,7 +753,7 @@ build_get_pgd_vmalloc64(u32 **p, struct
 
 	uasm_l_vmalloc(l, *p);
 
-	if (mode == refill && check_for_high_segbits) {
+	if (mode != not_refill && check_for_high_segbits) {
 		if (single_insn_swpd) {
 			uasm_il_bltz(p, r, bvaddr, label_vmalloc_done);
 			uasm_i_lui(p, ptr, uasm_rel_hi(swpd));
@@ -661,7 +776,7 @@ build_get_pgd_vmalloc64(u32 **p, struct
 				uasm_i_daddiu(p, ptr, ptr, uasm_rel_lo(swpd));
 		}
 	}
-	if (mode == refill && check_for_high_segbits) {
+	if (mode != not_refill && check_for_high_segbits) {
 		uasm_l_large_segbits_fault(l, *p);
 		/*
 		 * We get here if we are an xsseg address, or if we are
@@ -677,7 +792,15 @@ build_get_pgd_vmalloc64(u32 **p, struct
 		 */
 		UASM_i_LA(p, ptr, (unsigned long)tlb_do_page_fault_0);
 		uasm_i_jr(p, ptr);
-		uasm_i_nop(p);
+
+		if (mode == refill_scratch) {
+			if (scratch_reg > 0)
+				UASM_i_MFC0(p, 1, 31, scratch_reg);
+			else
+				UASM_i_LW(p, 1, scratchpad_offset(0), 0);
+		} else {
+			uasm_i_nop(p);
+		}
 	}
 }
 
@@ -834,6 +957,185 @@ static void __cpuinit build_update_entri
 #endif
 }
 
+struct mips_huge_tlb_info {
+	int huge_pte;
+	int restore_scratch;
+};
+
+static struct mips_huge_tlb_info __cpuinit
+build_fast_tlb_refill_handler (u32 **p, struct uasm_label **l,
+			       struct uasm_reloc **r, unsigned int tmp,
+			       unsigned int ptr, int c0_scratch)
+{
+	struct mips_huge_tlb_info rv;
+	unsigned int even, odd;
+	int vmalloc_branch_delay_filled = 0;
+	const int scratch = 1; /* Our extra working register */
+
+	rv.huge_pte = scratch;
+	rv.restore_scratch = 0;
+
+	if (check_for_high_segbits) {
+		UASM_i_MFC0(p, tmp, C0_BADVADDR);
+
+		if (pgd_reg != -1)
+			UASM_i_MFC0(p, ptr, 31, pgd_reg);
+		else
+			UASM_i_MFC0(p, ptr, C0_CONTEXT);
+
+		if (c0_scratch >= 0)
+			UASM_i_MTC0(p, scratch, 31, c0_scratch);
+		else
+			UASM_i_SW(p, scratch, scratchpad_offset(0), 0);
+
+		uasm_i_dsrl_safe(p, scratch, tmp,
+				 PGDIR_SHIFT + PGD_ORDER + PAGE_SHIFT - 3);
+		uasm_il_bnez(p, r, scratch, label_vmalloc);
+
+		if (pgd_reg == -1) {
+			vmalloc_branch_delay_filled = 1;
+			/* Clear lower 23 bits of context. */
+			uasm_i_dins(p, ptr, 0, 0, 23);
+		}
+	} else {
+		if (pgd_reg != -1)
+			UASM_i_MFC0(p, ptr, 31, pgd_reg);
+		else
+			UASM_i_MFC0(p, ptr, C0_CONTEXT);
+
+		UASM_i_MFC0(p, tmp, C0_BADVADDR);
+
+		if (c0_scratch >= 0)
+			UASM_i_MTC0(p, scratch, 31, c0_scratch);
+		else
+			UASM_i_SW(p, scratch, scratchpad_offset(0), 0);
+
+		if (pgd_reg == -1)
+			/* Clear lower 23 bits of context. */
+			uasm_i_dins(p, ptr, 0, 0, 23);
+
+		uasm_il_bltz(p, r, tmp, label_vmalloc);
+	}
+
+	if (pgd_reg == -1) {
+		vmalloc_branch_delay_filled = 1;
+		/* 1 0  1 0 1  << 6  xkphys cached */
+		uasm_i_ori(p, ptr, ptr, 0x540);
+		uasm_i_drotr(p, ptr, ptr, 11);
+	}
+
+#ifdef __PAGETABLE_PMD_FOLDED
+#define LOC_PTEP scratch
+#else
+#define LOC_PTEP ptr
+#endif
+
+	if (!vmalloc_branch_delay_filled)
+		/* get pgd offset in bytes */
+		uasm_i_dsrl_safe(p, scratch, tmp, PGDIR_SHIFT - 3);
+
+	uasm_l_vmalloc_done(l, *p);
+
+	/*
+	 *                         tmp          ptr
+	 * fall-through case =   badvaddr  *pgd_current
+	 * vmalloc case      =   badvaddr  swapper_pg_dir
+	 */
+
+	if (vmalloc_branch_delay_filled)
+		/* get pgd offset in bytes */
+		uasm_i_dsrl_safe(p, scratch, tmp, PGDIR_SHIFT - 3);
+
+#ifdef __PAGETABLE_PMD_FOLDED
+	GET_CONTEXT(p, tmp); /* get context reg */
+#endif
+	uasm_i_andi(p, scratch, scratch, (PTRS_PER_PGD - 1) << 3);
+
+	if (use_lwx_insns()) {
+		UASM_i_LWX(p, LOC_PTEP, scratch, ptr);
+	} else {
+		uasm_i_daddu(p, ptr, ptr, scratch); /* add in pgd offset */
+		uasm_i_ld(p, LOC_PTEP, 0, ptr); /* get pmd pointer */
+	}
+
+#ifndef __PAGETABLE_PMD_FOLDED
+	/* get pmd offset in bytes */
+	uasm_i_dsrl_safe(p, scratch, tmp, PMD_SHIFT - 3);
+	uasm_i_andi(p, scratch, scratch, (PTRS_PER_PMD - 1) << 3);
+	GET_CONTEXT(p, tmp); /* get context reg */
+
+	if (use_lwx_insns()) {
+		UASM_i_LWX(p, scratch, scratch, ptr);
+	} else {
+		uasm_i_daddu(p, ptr, ptr, scratch); /* add in pmd offset */
+		UASM_i_LW(p, scratch, 0, ptr);
+	}
+#endif
+	/* Adjust the context during the load latency. */
+	build_adjust_context(p, tmp);
+
+#ifdef CONFIG_HUGETLB_PAGE
+	uasm_il_bbit1(p, r, scratch, ilog2(_PAGE_HUGE), label_tlb_huge_update);
+	/*
+	 * The in the LWX case we don't want to do the load in the
+	 * delay slot.  It cannot issue in the same cycle and may be
+	 * speculative and unneeded.
+	 */
+	if (use_lwx_insns())
+		uasm_i_nop(p);
+#endif /* CONFIG_HUGETLB_PAGE */
+
+
+	/* build_update_entries */
+	if (use_lwx_insns()) {
+		even = ptr;
+		odd = tmp;
+		UASM_i_LWX(p, even, scratch, tmp);
+		UASM_i_ADDIU(p, tmp, tmp, sizeof(pte_t));
+		UASM_i_LWX(p, odd, scratch, tmp);
+	} else {
+		UASM_i_ADDU(p, ptr, scratch, tmp); /* add in offset */
+		even = tmp;
+		odd = ptr;
+		UASM_i_LW(p, even, 0, ptr); /* get even pte */
+		UASM_i_LW(p, odd, sizeof(pte_t), ptr); /* get odd pte */
+	}
+	if (kernel_uses_smartmips_rixi) {
+		uasm_i_dsrl_safe(p, even, even, ilog2(_PAGE_NO_EXEC));
+		uasm_i_dsrl_safe(p, odd, odd, ilog2(_PAGE_NO_EXEC));
+		uasm_i_drotr(p, even, even,
+			     ilog2(_PAGE_GLOBAL) - ilog2(_PAGE_NO_EXEC));
+		UASM_i_MTC0(p, even, C0_ENTRYLO0); /* load it */
+		uasm_i_drotr(p, odd, odd,
+			     ilog2(_PAGE_GLOBAL) - ilog2(_PAGE_NO_EXEC));
+	} else {
+		uasm_i_dsrl_safe(p, even, even, ilog2(_PAGE_GLOBAL));
+		UASM_i_MTC0(p, even, C0_ENTRYLO0); /* load it */
+		uasm_i_dsrl_safe(p, odd, odd, ilog2(_PAGE_GLOBAL));
+	}
+	UASM_i_MTC0(p, odd, C0_ENTRYLO1); /* load it */
+
+	if (c0_scratch >= 0) {
+		UASM_i_MFC0(p, scratch, 31, c0_scratch);
+		build_tlb_write_entry(p, l, r, tlb_random);
+		uasm_l_leave(l, *p);
+		rv.restore_scratch = 1;
+	} else if (PAGE_SHIFT == 14 || PAGE_SHIFT == 13)  {
+		build_tlb_write_entry(p, l, r, tlb_random);
+		uasm_l_leave(l, *p);
+		UASM_i_LW(p, scratch, scratchpad_offset(0), 0);
+	} else {
+		UASM_i_LW(p, scratch, scratchpad_offset(0), 0);
+		build_tlb_write_entry(p, l, r, tlb_random);
+		uasm_l_leave(l, *p);
+		rv.restore_scratch = 1;
+	}
+
+	uasm_i_eret(p); /* return from trap */
+
+	return rv;
+}
+
 /*
  * For a 64-bit kernel, we are using the 64-bit XTLB refill exception
  * because EXL == 0.  If we wrap, we can also use the 32 instruction
@@ -849,54 +1151,67 @@ static void __cpuinit build_r4000_tlb_re
 	struct uasm_reloc *r = relocs;
 	u32 *f;
 	unsigned int final_len;
+	struct mips_huge_tlb_info htlb_info;
+	enum vmalloc64_mode vmalloc_mode;
 
 	memset(tlb_handler, 0, sizeof(tlb_handler));
 	memset(labels, 0, sizeof(labels));
 	memset(relocs, 0, sizeof(relocs));
 	memset(final_handler, 0, sizeof(final_handler));
 
-	/*
-	 * create the plain linear handler
-	 */
-	if (bcm1250_m3_war()) {
-		unsigned int segbits = 44;
+	if (scratch_reg == 0)
+		scratch_reg = allocate_kscratch();
 
-		uasm_i_dmfc0(&p, K0, C0_BADVADDR);
-		uasm_i_dmfc0(&p, K1, C0_ENTRYHI);
-		uasm_i_xor(&p, K0, K0, K1);
-		uasm_i_dsrl_safe(&p, K1, K0, 62);
-		uasm_i_dsrl_safe(&p, K0, K0, 12 + 1);
-		uasm_i_dsll_safe(&p, K0, K0, 64 + 12 + 1 - segbits);
-		uasm_i_or(&p, K0, K0, K1);
-		uasm_il_bnez(&p, &r, K0, label_leave);
-		/* No need for uasm_i_nop */
-	}
+	if ((scratch_reg > 0 || scratchpad_available()) && use_bbit_insns()) {
+		htlb_info = build_fast_tlb_refill_handler(&p, &l, &r, K0, K1,
+							  scratch_reg);
+		vmalloc_mode = refill_scratch;
+	} else {
+		htlb_info.huge_pte = K0;
+		htlb_info.restore_scratch = 0;
+		vmalloc_mode = refill_noscratch;
+		/*
+		 * create the plain linear handler
+		 */
+		if (bcm1250_m3_war()) {
+			unsigned int segbits = 44;
+
+			uasm_i_dmfc0(&p, K0, C0_BADVADDR);
+			uasm_i_dmfc0(&p, K1, C0_ENTRYHI);
+			uasm_i_xor(&p, K0, K0, K1);
+			uasm_i_dsrl_safe(&p, K1, K0, 62);
+			uasm_i_dsrl_safe(&p, K0, K0, 12 + 1);
+			uasm_i_dsll_safe(&p, K0, K0, 64 + 12 + 1 - segbits);
+			uasm_i_or(&p, K0, K0, K1);
+			uasm_il_bnez(&p, &r, K0, label_leave);
+			/* No need for uasm_i_nop */
+		}
 
 #ifdef CONFIG_64BIT
-	build_get_pmde64(&p, &l, &r, K0, K1); /* get pmd in K1 */
+		build_get_pmde64(&p, &l, &r, K0, K1); /* get pmd in K1 */
 #else
-	build_get_pgde32(&p, K0, K1); /* get pgd in K1 */
+		build_get_pgde32(&p, K0, K1); /* get pgd in K1 */
 #endif
 
 #ifdef CONFIG_HUGETLB_PAGE
-	build_is_huge_pte(&p, &r, K0, K1, label_tlb_huge_update);
+		build_is_huge_pte(&p, &r, K0, K1, label_tlb_huge_update);
 #endif
 
-	build_get_ptep(&p, K0, K1);
-	build_update_entries(&p, K0, K1);
-	build_tlb_write_entry(&p, &l, &r, tlb_random);
-	uasm_l_leave(&l, p);
-	uasm_i_eret(&p); /* return from trap */
-
+		build_get_ptep(&p, K0, K1);
+		build_update_entries(&p, K0, K1);
+		build_tlb_write_entry(&p, &l, &r, tlb_random);
+		uasm_l_leave(&l, p);
+		uasm_i_eret(&p); /* return from trap */
+	}
 #ifdef CONFIG_HUGETLB_PAGE
 	uasm_l_tlb_huge_update(&l, p);
-	UASM_i_LW(&p, K0, 0, K1);
-	build_huge_update_entries(&p, K0, K1);
-	build_huge_tlb_write_entry(&p, &l, &r, K0, tlb_random);
+	build_huge_update_entries(&p, htlb_info.huge_pte, K1);
+	build_huge_tlb_write_entry(&p, &l, &r, K0, tlb_random,
+				   htlb_info.restore_scratch);
 #endif
 
 #ifdef CONFIG_64BIT
-	build_get_pgd_vmalloc64(&p, &l, &r, K0, K1, refill);
+	build_get_pgd_vmalloc64(&p, &l, &r, K0, K1, vmalloc_mode);
 #endif
 
 	/*
@@ -1014,6 +1329,55 @@ static void __cpuinit build_r4000_tlb_re
 u32 handle_tlbl[FASTPATH_SIZE] __cacheline_aligned;
 u32 handle_tlbs[FASTPATH_SIZE] __cacheline_aligned;
 u32 handle_tlbm[FASTPATH_SIZE] __cacheline_aligned;
+#ifdef CONFIG_MIPS_PGD_C0_CONTEXT
+u32 tlbmiss_handler_setup_pgd[16] __cacheline_aligned;
+
+static void __cpuinit build_r4000_setup_pgd(void)
+{
+	const int a0 = 4;
+	const int a1 = 5;
+	u32 *p = tlbmiss_handler_setup_pgd;
+	struct uasm_label *l = labels;
+	struct uasm_reloc *r = relocs;
+
+	memset(tlbmiss_handler_setup_pgd, 0, sizeof(tlbmiss_handler_setup_pgd));
+	memset(labels, 0, sizeof(labels));
+	memset(relocs, 0, sizeof(relocs));
+
+	pgd_reg = allocate_kscratch();
+
+	if (pgd_reg == -1) {
+		/* PGD << 11 in c0_Context */
+		/*
+		 * If it is a ckseg0 address, convert to a physical
+		 * address.  Shifting right by 29 and adding 4 will
+		 * result in zero for these addresses.
+		 *
+		 */
+		UASM_i_SRA(&p, a1, a0, 29);
+		UASM_i_ADDIU(&p, a1, a1, 4);
+		uasm_il_bnez(&p, &r, a1, label_tlbl_goaround1);
+		uasm_i_nop(&p);
+		uasm_i_dinsm(&p, a0, 0, 29, 64 - 29);
+		uasm_l_tlbl_goaround1(&l, p);
+		UASM_i_SLL(&p, a0, a0, 11);
+		uasm_i_jr(&p, 31);
+		UASM_i_MTC0(&p, a0, C0_CONTEXT);
+	} else {
+		/* PGD in c0_KScratch */
+		uasm_i_jr(&p, 31);
+		UASM_i_MTC0(&p, a0, 31, pgd_reg);
+	}
+	if (p - tlbmiss_handler_setup_pgd > ARRAY_SIZE(tlbmiss_handler_setup_pgd))
+		panic("tlbmiss_handler_setup_pgd space exceeded");
+	uasm_resolve_relocs(relocs, labels);
+	pr_debug("Wrote tlbmiss_handler_setup_pgd (%u instructions).\n",
+		 (unsigned int)(p - tlbmiss_handler_setup_pgd));
+
+	dump_handler(tlbmiss_handler_setup_pgd,
+		     ARRAY_SIZE(tlbmiss_handler_setup_pgd));
+}
+#endif
 
 static void __cpuinit
 iPTE_LW(u32 **p, unsigned int pte, unsigned int ptr)
@@ -1100,14 +1464,20 @@ build_pte_present(u32 **p, struct uasm_r
 		  unsigned int pte, unsigned int ptr, enum label_id lid)
 {
 	if (kernel_uses_smartmips_rixi) {
-		uasm_i_andi(p, pte, pte, _PAGE_PRESENT);
-		uasm_il_beqz(p, r, pte, lid);
+		if (use_bbit_insns()) {
+			uasm_il_bbit0(p, r, pte, ilog2(_PAGE_PRESENT), lid);
+			uasm_i_nop(p);
+		} else {
+			uasm_i_andi(p, pte, pte, _PAGE_PRESENT);
+			uasm_il_beqz(p, r, pte, lid);
+			iPTE_LW(p, pte, ptr);
+		}
 	} else {
 		uasm_i_andi(p, pte, pte, _PAGE_PRESENT | _PAGE_READ);
 		uasm_i_xori(p, pte, pte, _PAGE_PRESENT | _PAGE_READ);
 		uasm_il_bnez(p, r, pte, lid);
+		iPTE_LW(p, pte, ptr);
 	}
-	iPTE_LW(p, pte, ptr);
 }
 
 /* Make PTE valid, store result in PTR. */
@@ -1128,10 +1498,17 @@ static void __cpuinit
 build_pte_writable(u32 **p, struct uasm_reloc **r,
 		   unsigned int pte, unsigned int ptr, enum label_id lid)
 {
-	uasm_i_andi(p, pte, pte, _PAGE_PRESENT | _PAGE_WRITE);
-	uasm_i_xori(p, pte, pte, _PAGE_PRESENT | _PAGE_WRITE);
-	uasm_il_bnez(p, r, pte, lid);
-	iPTE_LW(p, pte, ptr);
+	if (use_bbit_insns()) {
+		uasm_il_bbit0(p, r, pte, ilog2(_PAGE_PRESENT), lid);
+		uasm_i_nop(p);
+		uasm_il_bbit0(p, r, pte, ilog2(_PAGE_WRITE), lid);
+		uasm_i_nop(p);
+	} else {
+		uasm_i_andi(p, pte, pte, _PAGE_PRESENT | _PAGE_WRITE);
+		uasm_i_xori(p, pte, pte, _PAGE_PRESENT | _PAGE_WRITE);
+		uasm_il_bnez(p, r, pte, lid);
+		iPTE_LW(p, pte, ptr);
+	}
 }
 
 /* Make PTE writable, update software status bits as well, then store
@@ -1155,12 +1532,19 @@ static void __cpuinit
 build_pte_modifiable(u32 **p, struct uasm_reloc **r,
 		     unsigned int pte, unsigned int ptr, enum label_id lid)
 {
-	uasm_i_andi(p, pte, pte, _PAGE_WRITE);
-	uasm_il_beqz(p, r, pte, lid);
-	iPTE_LW(p, pte, ptr);
+	if (use_bbit_insns()) {
+		uasm_il_bbit0(p, r, pte, ilog2(_PAGE_WRITE), lid);
+		uasm_i_nop(p);
+	} else {
+		uasm_i_andi(p, pte, pte, _PAGE_WRITE);
+		uasm_il_beqz(p, r, pte, lid);
+		iPTE_LW(p, pte, ptr);
+	}
 }
 
 #ifndef CONFIG_MIPS_PGD_C0_CONTEXT
+
+
 /*
  * R3000 style TLB load/store/modify handlers.
  */
@@ -1402,14 +1786,23 @@ static void __cpuinit build_r4000_tlb_lo
 		 * If the page is not _PAGE_VALID, RI or XI could not
 		 * have triggered it.  Skip the expensive test..
 		 */
-		uasm_i_andi(&p, K0, K0, _PAGE_VALID);
-		uasm_il_beqz(&p, &r, K0, label_tlbl_goaround1);
+		if (use_bbit_insns()) {
+			uasm_il_bbit0(&p, &r, K0, ilog2(_PAGE_VALID),
+				      label_tlbl_goaround1);
+		} else {
+			uasm_i_andi(&p, K0, K0, _PAGE_VALID);
+			uasm_il_beqz(&p, &r, K0, label_tlbl_goaround1);
+		}
 		uasm_i_nop(&p);
 
 		uasm_i_tlbr(&p);
 		/* Examine  entrylo 0 or 1 based on ptr. */
-		uasm_i_andi(&p, K0, K1, sizeof(pte_t));
-		uasm_i_beqz(&p, K0, 8);
+		if (use_bbit_insns()) {
+			uasm_i_bbit0(&p, K1, ilog2(sizeof(pte_t)), 8);
+		} else {
+			uasm_i_andi(&p, K0, K1, sizeof(pte_t));
+			uasm_i_beqz(&p, K0, 8);
+		}
 
 		UASM_i_MFC0(&p, K0, C0_ENTRYLO0); /* load it in the delay slot*/
 		UASM_i_MFC0(&p, K0, C0_ENTRYLO1); /* load it if ptr is odd */
@@ -1417,12 +1810,18 @@ static void __cpuinit build_r4000_tlb_lo
 		 * If the entryLo (now in K0) is valid (bit 1), RI or
 		 * XI must have triggered it.
 		 */
-		uasm_i_andi(&p, K0, K0, 2);
-		uasm_il_bnez(&p, &r, K0, label_nopage_tlbl);
-
-		uasm_l_tlbl_goaround1(&l, p);
-		/* Reload the PTE value */
-		iPTE_LW(&p, K0, K1);
+		if (use_bbit_insns()) {
+			uasm_il_bbit1(&p, &r, K0, 1, label_nopage_tlbl);
+			/* Reload the PTE value */
+			iPTE_LW(&p, K0, K1);
+			uasm_l_tlbl_goaround1(&l, p);
+		} else {
+			uasm_i_andi(&p, K0, K0, 2);
+			uasm_il_bnez(&p, &r, K0, label_nopage_tlbl);
+			uasm_l_tlbl_goaround1(&l, p);
+			/* Reload the PTE value */
+			iPTE_LW(&p, K0, K1);
+		}
 	}
 	build_make_valid(&p, &r, K0, K1);
 	build_r4000_tlbchange_handler_tail(&p, &l, &r, K0, K1);
@@ -1442,23 +1841,35 @@ static void __cpuinit build_r4000_tlb_lo
 		 * If the page is not _PAGE_VALID, RI or XI could not
 		 * have triggered it.  Skip the expensive test..
 		 */
-		uasm_i_andi(&p, K0, K0, _PAGE_VALID);
-		uasm_il_beqz(&p, &r, K0, label_tlbl_goaround2);
+		if (use_bbit_insns()) {
+			uasm_il_bbit0(&p, &r, K0, ilog2(_PAGE_VALID),
+				      label_tlbl_goaround2);
+		} else {
+			uasm_i_andi(&p, K0, K0, _PAGE_VALID);
+			uasm_il_beqz(&p, &r, K0, label_tlbl_goaround2);
+		}
 		uasm_i_nop(&p);
 
 		uasm_i_tlbr(&p);
 		/* Examine  entrylo 0 or 1 based on ptr. */
-		uasm_i_andi(&p, K0, K1, sizeof(pte_t));
-		uasm_i_beqz(&p, K0, 8);
-
+		if (use_bbit_insns()) {
+			uasm_i_bbit0(&p, K1, ilog2(sizeof(pte_t)), 8);
+		} else {
+			uasm_i_andi(&p, K0, K1, sizeof(pte_t));
+			uasm_i_beqz(&p, K0, 8);
+		}
 		UASM_i_MFC0(&p, K0, C0_ENTRYLO0); /* load it in the delay slot*/
 		UASM_i_MFC0(&p, K0, C0_ENTRYLO1); /* load it if ptr is odd */
 		/*
 		 * If the entryLo (now in K0) is valid (bit 1), RI or
 		 * XI must have triggered it.
 		 */
-		uasm_i_andi(&p, K0, K0, 2);
-		uasm_il_beqz(&p, &r, K0, label_tlbl_goaround2);
+		if (use_bbit_insns()) {
+			uasm_il_bbit0(&p, &r, K0, 1, label_tlbl_goaround2);
+		} else {
+			uasm_i_andi(&p, K0, K0, 2);
+			uasm_il_beqz(&p, &r, K0, label_tlbl_goaround2);
+		}
 		/* Reload the PTE value */
 		iPTE_LW(&p, K0, K1);
 
@@ -1466,7 +1877,7 @@ static void __cpuinit build_r4000_tlb_lo
 		 * We clobbered C0_PAGEMASK, restore it.  On the other branch
 		 * it is restored in build_huge_tlb_write_entry.
 		 */
-		build_restore_pagemask(&p, &r, K0, label_nopage_tlbl);
+		build_restore_pagemask(&p, &r, K0, label_nopage_tlbl, 0);
 
 		uasm_l_tlbl_goaround2(&l, p);
 	}
@@ -1623,13 +2034,16 @@ void __cpuinit build_tlb_refill_handler(
 		break;
 
 	default:
-		build_r4000_tlb_refill_handler();
 		if (!run_once) {
+#ifdef CONFIG_MIPS_PGD_C0_CONTEXT
+			build_r4000_setup_pgd();
+#endif
 			build_r4000_tlb_load_handler();
 			build_r4000_tlb_store_handler();
 			build_r4000_tlb_modify_handler();
 			run_once++;
 		}
+		build_r4000_tlb_refill_handler();
 	}
 }
 
@@ -1641,4 +2055,8 @@ void __cpuinit flush_tlb_handlers(void)
 			   (unsigned long)handle_tlbs + sizeof(handle_tlbs));
 	local_flush_icache_range((unsigned long)handle_tlbm,
 			   (unsigned long)handle_tlbm + sizeof(handle_tlbm));
+#ifdef CONFIG_MIPS_PGD_C0_CONTEXT
+	local_flush_icache_range((unsigned long)tlbmiss_handler_setup_pgd,
+			   (unsigned long)tlbmiss_handler_setup_pgd + sizeof(handle_tlbm));
+#endif
 }
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/mm/uasm.c linux-libre-2.6.38-gnu1/arch/mips/mm/uasm.c
--- linux-libre-2.6.37-gnu1/arch/mips/mm/uasm.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/mm/uasm.c	2011-03-14 21:20:32.000000000 -0400
@@ -68,7 +68,8 @@ enum opcode {
 	insn_pref, insn_rfe, insn_sc, insn_scd, insn_sd, insn_sll,
 	insn_sra, insn_srl, insn_rotr, insn_subu, insn_sw, insn_tlbp,
 	insn_tlbr, insn_tlbwi, insn_tlbwr, insn_xor, insn_xori,
-	insn_dins, insn_syscall, insn_bbit0, insn_bbit1
+	insn_dins, insn_dinsm, insn_syscall, insn_bbit0, insn_bbit1,
+	insn_lwx, insn_ldx
 };
 
 struct insn {
@@ -142,9 +143,12 @@ static struct insn insn_table[] __uasmin
 	{ insn_xor,  M(spec_op, 0, 0, 0, 0, xor_op),  RS | RT | RD },
 	{ insn_xori,  M(xori_op, 0, 0, 0, 0, 0),  RS | RT | UIMM },
 	{ insn_dins, M(spec3_op, 0, 0, 0, 0, dins_op), RS | RT | RD | RE },
+	{ insn_dinsm, M(spec3_op, 0, 0, 0, 0, dinsm_op), RS | RT | RD | RE },
 	{ insn_syscall, M(spec_op, 0, 0, 0, 0, syscall_op), SCIMM},
 	{ insn_bbit0, M(lwc2_op, 0, 0, 0, 0, 0), RS | RT | BIMM },
 	{ insn_bbit1, M(swc2_op, 0, 0, 0, 0, 0), RS | RT | BIMM },
+	{ insn_lwx, M(spec3_op, 0, 0, 0, lwx_op, lx_op), RS | RT | RD },
+	{ insn_ldx, M(spec3_op, 0, 0, 0, ldx_op, lx_op), RS | RT | RD },
 	{ insn_invalid, 0, 0 }
 };
 
@@ -152,91 +156,83 @@ static struct insn insn_table[] __uasmin
 
 static inline __uasminit u32 build_rs(u32 arg)
 {
-	if (arg & ~RS_MASK)
-		printk(KERN_WARNING "Micro-assembler field overflow\n");
+	WARN(arg & ~RS_MASK, KERN_WARNING "Micro-assembler field overflow\n");
 
 	return (arg & RS_MASK) << RS_SH;
 }
 
 static inline __uasminit u32 build_rt(u32 arg)
 {
-	if (arg & ~RT_MASK)
-		printk(KERN_WARNING "Micro-assembler field overflow\n");
+	WARN(arg & ~RT_MASK, KERN_WARNING "Micro-assembler field overflow\n");
 
 	return (arg & RT_MASK) << RT_SH;
 }
 
 static inline __uasminit u32 build_rd(u32 arg)
 {
-	if (arg & ~RD_MASK)
-		printk(KERN_WARNING "Micro-assembler field overflow\n");
+	WARN(arg & ~RD_MASK, KERN_WARNING "Micro-assembler field overflow\n");
 
 	return (arg & RD_MASK) << RD_SH;
 }
 
 static inline __uasminit u32 build_re(u32 arg)
 {
-	if (arg & ~RE_MASK)
-		printk(KERN_WARNING "Micro-assembler field overflow\n");
+	WARN(arg & ~RE_MASK, KERN_WARNING "Micro-assembler field overflow\n");
 
 	return (arg & RE_MASK) << RE_SH;
 }
 
 static inline __uasminit u32 build_simm(s32 arg)
 {
-	if (arg > 0x7fff || arg < -0x8000)
-		printk(KERN_WARNING "Micro-assembler field overflow\n");
+	WARN(arg > 0x7fff || arg < -0x8000,
+	     KERN_WARNING "Micro-assembler field overflow\n");
 
 	return arg & 0xffff;
 }
 
 static inline __uasminit u32 build_uimm(u32 arg)
 {
-	if (arg & ~IMM_MASK)
-		printk(KERN_WARNING "Micro-assembler field overflow\n");
+	WARN(arg & ~IMM_MASK, KERN_WARNING "Micro-assembler field overflow\n");
 
 	return arg & IMM_MASK;
 }
 
 static inline __uasminit u32 build_bimm(s32 arg)
 {
-	if (arg > 0x1ffff || arg < -0x20000)
-		printk(KERN_WARNING "Micro-assembler field overflow\n");
+	WARN(arg > 0x1ffff || arg < -0x20000,
+	     KERN_WARNING "Micro-assembler field overflow\n");
 
-	if (arg & 0x3)
-		printk(KERN_WARNING "Invalid micro-assembler branch target\n");
+	WARN(arg & 0x3, KERN_WARNING "Invalid micro-assembler branch target\n");
 
 	return ((arg < 0) ? (1 << 15) : 0) | ((arg >> 2) & 0x7fff);
 }
 
 static inline __uasminit u32 build_jimm(u32 arg)
 {
-	if (arg & ~((JIMM_MASK) << 2))
-		printk(KERN_WARNING "Micro-assembler field overflow\n");
+	WARN(arg & ~(JIMM_MASK << 2),
+	     KERN_WARNING "Micro-assembler field overflow\n");
 
 	return (arg >> 2) & JIMM_MASK;
 }
 
 static inline __uasminit u32 build_scimm(u32 arg)
 {
-	if (arg & ~SCIMM_MASK)
-		printk(KERN_WARNING "Micro-assembler field overflow\n");
+	WARN(arg & ~SCIMM_MASK,
+	     KERN_WARNING "Micro-assembler field overflow\n");
 
 	return (arg & SCIMM_MASK) << SCIMM_SH;
 }
 
 static inline __uasminit u32 build_func(u32 arg)
 {
-	if (arg & ~FUNC_MASK)
-		printk(KERN_WARNING "Micro-assembler field overflow\n");
+	WARN(arg & ~FUNC_MASK, KERN_WARNING "Micro-assembler field overflow\n");
 
 	return arg & FUNC_MASK;
 }
 
 static inline __uasminit u32 build_set(u32 arg)
 {
-	if (arg & ~SET_MASK)
-		printk(KERN_WARNING "Micro-assembler field overflow\n");
+	WARN(arg & ~SET_MASK, KERN_WARNING "Micro-assembler field overflow\n");
 
 	return arg & SET_MASK;
 }
@@ -340,6 +336,13 @@ Ip_u2u1msbu3(op)					\
 }							\
 UASM_EXPORT_SYMBOL(uasm_i##op);
 
+#define I_u2u1msb32u3(op)				\
+Ip_u2u1msbu3(op)					\
+{							\
+	build_insn(buf, insn##op, b, a, c+d-33, c);	\
+}							\
+UASM_EXPORT_SYMBOL(uasm_i##op);
+
 #define I_u1u2(op)					\
 Ip_u1u2(op)						\
 {							\
@@ -422,9 +425,12 @@ I_0(_tlbwr)
 I_u3u1u2(_xor)
 I_u2u1u3(_xori)
 I_u2u1msbu3(_dins);
+I_u2u1msb32u3(_dinsm);
 I_u1(_syscall);
 I_u1u2s3(_bbit0);
 I_u1u2s3(_bbit1);
+I_u3u1u2(_lwx)
+I_u3u1u2(_ldx)
 
 #ifdef CONFIG_CPU_CAVIUM_OCTEON
 #include <asm/octeon/octeon.h>
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/mti-malta/malta-memory.c linux-libre-2.6.38-gnu1/arch/mips/mti-malta/malta-memory.c
--- linux-libre-2.6.37-gnu1/arch/mips/mti-malta/malta-memory.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/mti-malta/malta-memory.c	2011-03-14 21:20:32.000000000 -0400
@@ -43,7 +43,7 @@ static struct prom_pmemblock mdesc[PROM_
 static char *mtypes[3] = {
 	"Dont use memory",
 	"YAMON PROM memory",
-	"Free memmory",
+	"Free memory",
 };
 #endif
 
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/pci/ops-pmcmsp.c linux-libre-2.6.38-gnu1/arch/mips/pci/ops-pmcmsp.c
--- linux-libre-2.6.37-gnu1/arch/mips/pci/ops-pmcmsp.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/pci/ops-pmcmsp.c	2011-03-14 21:20:32.000000000 -0400
@@ -308,7 +308,7 @@ static struct resource pci_mem_resource
  *  RETURNS:     PCIBIOS_SUCCESSFUL  - success
  *
  ****************************************************************************/
-static int bpci_interrupt(int irq, void *dev_id)
+static irqreturn_t bpci_interrupt(int irq, void *dev_id)
 {
 	struct msp_pci_regs *preg = (void *)PCI_BASE_REG;
 	unsigned int stat = preg->if_status;
@@ -326,7 +326,7 @@ static int bpci_interrupt(int irq, void
 	/* write to clear all asserted interrupts */
 	preg->if_status = stat;
 
-	return PCIBIOS_SUCCESSFUL;
+	return IRQ_HANDLED;
 }
 
 /*****************************************************************************
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/pci/pcie-octeon.c linux-libre-2.6.38-gnu1/arch/mips/pci/pcie-octeon.c
--- linux-libre-2.6.37-gnu1/arch/mips/pci/pcie-octeon.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/pci/pcie-octeon.c	2011-03-14 21:20:32.000000000 -0400
@@ -900,7 +900,7 @@ static int cvmx_pcie_rc_initialize(int p
 	mem_access_subid.s.ror = 0;
 	/* Disable Relaxed Ordering for Writes. */
 	mem_access_subid.s.row = 0;
-	/* PCIe Adddress Bits <63:34>. */
+	/* PCIe Address Bits <63:34>. */
 	mem_access_subid.s.ba = 0;
 
 	/*
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/pmc-sierra/Kconfig linux-libre-2.6.38-gnu1/arch/mips/pmc-sierra/Kconfig
--- linux-libre-2.6.37-gnu1/arch/mips/pmc-sierra/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/pmc-sierra/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -4,15 +4,11 @@ choice
 
 config PMC_MSP4200_EVAL
 	bool "PMC-Sierra MSP4200 Eval Board"
-	select CEVT_R4K
-	select CSRC_R4K
 	select IRQ_MSP_SLP
 	select HW_HAS_PCI
 
 config PMC_MSP4200_GW
 	bool "PMC-Sierra MSP4200 VoIP Gateway"
-	select CEVT_R4K
-	select CSRC_R4K
 	select IRQ_MSP_SLP
 	select HW_HAS_PCI
 
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/pmc-sierra/msp71xx/msp_time.c linux-libre-2.6.38-gnu1/arch/mips/pmc-sierra/msp71xx/msp_time.c
--- linux-libre-2.6.37-gnu1/arch/mips/pmc-sierra/msp71xx/msp_time.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/pmc-sierra/msp71xx/msp_time.c	2011-03-14 21:20:32.000000000 -0400
@@ -81,7 +81,7 @@ void __init plat_time_init(void)
 	mips_hpt_frequency = cpu_rate/2;
 }
 
-unsigned int __init get_c0_compare_int(void)
+unsigned int __cpuinit get_c0_compare_int(void)
 {
 	return MSP_INT_VPE0_TIMER;
 }
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/powertv/memory.c linux-libre-2.6.38-gnu1/arch/mips/powertv/memory.c
--- linux-libre-2.6.37-gnu1/arch/mips/powertv/memory.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/powertv/memory.c	2011-03-14 21:20:32.000000000 -0400
@@ -57,7 +57,7 @@
 unsigned long ptv_memsize;
 
 /*
- * struct low_mem_reserved - Items in low memmory that are reserved
+ * struct low_mem_reserved - Items in low memory that are reserved
  * @start:	Physical address of item
  * @size:	Size, in bytes, of this item
  * @is_aliased:	True if this is RAM aliased from another location. If false,
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/sibyte/common/sb_tbprof.c linux-libre-2.6.38-gnu1/arch/mips/sibyte/common/sb_tbprof.c
--- linux-libre-2.6.37-gnu1/arch/mips/sibyte/common/sb_tbprof.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/sibyte/common/sb_tbprof.c	2011-03-14 21:20:32.000000000 -0400
@@ -410,14 +410,13 @@ static int sbprof_tb_open(struct inode *
 		return -EBUSY;
 
 	memset(&sbp, 0, sizeof(struct sbprof_tb));
-	sbp.sbprof_tbbuf = vmalloc(MAX_TBSAMPLE_BYTES);
+	sbp.sbprof_tbbuf = vzalloc(MAX_TBSAMPLE_BYTES);
 	if (!sbp.sbprof_tbbuf) {
 		sbp.open = SB_CLOSED;
 		wmb();
 		return -ENOMEM;
 	}
 
-	memset(sbp.sbprof_tbbuf, 0, MAX_TBSAMPLE_BYTES);
 	init_waitqueue_head(&sbp.tb_sync);
 	init_waitqueue_head(&sbp.tb_read);
 	mutex_init(&sbp.lock);
diff -druNp linux-libre-2.6.37-gnu1/arch/mips/txx9/generic/pci.c linux-libre-2.6.38-gnu1/arch/mips/txx9/generic/pci.c
--- linux-libre-2.6.37-gnu1/arch/mips/txx9/generic/pci.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mips/txx9/generic/pci.c	2011-03-14 21:20:32.000000000 -0400
@@ -107,7 +107,7 @@ int txx9_pci_mem_high __initdata;
 
 /*
  * allocate pci_controller and resources.
- * mem_base, io_base: physical addresss.  0 for auto assignment.
+ * mem_base, io_base: physical address.  0 for auto assignment.
  * mem_size and io_size means max size on auto assignment.
  * pcic must be &txx9_primary_pcic or NULL.
  */
@@ -213,11 +213,8 @@ txx9_alloc_pci_controller(struct pci_con
 
 	pcic->mem_offset = 0;	/* busaddr == physaddr */
 
-	printk(KERN_INFO "PCI: IO 0x%08llx-0x%08llx MEM 0x%08llx-0x%08llx\n",
-	       (unsigned long long)pcic->mem_resource[1].start,
-	       (unsigned long long)pcic->mem_resource[1].end,
-	       (unsigned long long)pcic->mem_resource[0].start,
-	       (unsigned long long)pcic->mem_resource[0].end);
+	printk(KERN_INFO "PCI: IO %pR MEM %pR\n",
+	       &pcic->mem_resource[1], &pcic->mem_resource[0]);
 
 	/* register_pci_controller() will request MEM resource */
 	release_resource(&pcic->mem_resource[0]);
diff -druNp linux-libre-2.6.37-gnu1/arch/mn10300/configs/asb2303_defconfig linux-libre-2.6.38-gnu1/arch/mn10300/configs/asb2303_defconfig
--- linux-libre-2.6.37-gnu1/arch/mn10300/configs/asb2303_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mn10300/configs/asb2303_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -4,7 +4,7 @@ CONFIG_BSD_PROCESS_ACCT=y
 CONFIG_TINY_RCU=y
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_KALLSYMS is not set
 # CONFIG_HOTPLUG is not set
 # CONFIG_VM_EVENT_COUNTERS is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/mn10300/configs/asb2364_defconfig linux-libre-2.6.38-gnu1/arch/mn10300/configs/asb2364_defconfig
--- linux-libre-2.6.37-gnu1/arch/mn10300/configs/asb2364_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mn10300/configs/asb2364_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -15,7 +15,7 @@ CONFIG_CGROUP_CPUACCT=y
 CONFIG_RESOURCE_COUNTERS=y
 CONFIG_RELAY=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_KALLSYMS is not set
 # CONFIG_VM_EVENT_COUNTERS is not set
 CONFIG_SLAB=y
diff -druNp linux-libre-2.6.37-gnu1/arch/mn10300/include/asm/atomic.h linux-libre-2.6.38-gnu1/arch/mn10300/include/asm/atomic.h
--- linux-libre-2.6.37-gnu1/arch/mn10300/include/asm/atomic.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mn10300/include/asm/atomic.h	2011-03-14 21:20:32.000000000 -0400
@@ -139,7 +139,7 @@ static inline unsigned long __cmpxchg(vo
  * Atomically reads the value of @v.  Note that the guaranteed
  * useful range of an atomic_t is only 24 bits.
  */
-#define atomic_read(v)	((v)->counter)
+#define atomic_read(v)	(ACCESS_ONCE((v)->counter))
 
 /**
  * atomic_set - set atomic variable
diff -druNp linux-libre-2.6.37-gnu1/arch/mn10300/include/asm/uaccess.h linux-libre-2.6.38-gnu1/arch/mn10300/include/asm/uaccess.h
--- linux-libre-2.6.37-gnu1/arch/mn10300/include/asm/uaccess.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mn10300/include/asm/uaccess.h	2011-03-14 21:20:32.000000000 -0400
@@ -160,9 +160,10 @@ struct __large_struct { unsigned long bu
 
 #define __get_user_check(x, ptr, size)					\
 ({									\
+	const __typeof__(ptr) __guc_ptr = (ptr);			\
 	int _e;								\
-	if (likely(__access_ok((unsigned long) (ptr), (size))))		\
-		_e = __get_user_nocheck((x), (ptr), (size));		\
+	if (likely(__access_ok((unsigned long) __guc_ptr, (size))))	\
+		_e = __get_user_nocheck((x), __guc_ptr, (size));	\
 	else {								\
 		_e = -EFAULT;						\
 		(x) = (__typeof__(x))0;					\
diff -druNp linux-libre-2.6.37-gnu1/arch/mn10300/Kconfig linux-libre-2.6.38-gnu1/arch/mn10300/Kconfig
--- linux-libre-2.6.37-gnu1/arch/mn10300/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mn10300/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -1,6 +1,7 @@
 config MN10300
 	def_bool y
 	select HAVE_OPROFILE
+	select GENERIC_HARDIRQS
 
 config AM33_2
 	def_bool n
@@ -34,9 +35,6 @@ config RWSEM_GENERIC_SPINLOCK
 config RWSEM_XCHGADD_ALGORITHM
 	bool
 
-config GENERIC_HARDIRQS_NO__DO_IRQ
-	def_bool y
-
 config GENERIC_CALIBRATE_DELAY
 	def_bool y
 
@@ -79,10 +77,6 @@ config QUICKLIST
 config ARCH_HAS_ILOG2_U32
 	def_bool y
 
-# Use the generic interrupt handling code in kernel/irq/
-config GENERIC_HARDIRQS
-	def_bool y
-
 config HOTPLUG_CPU
 	def_bool n
 
@@ -203,6 +197,7 @@ endmenu
 config SMP
 	bool "Symmetric multi-processing support"
 	default y
+	select USE_GENERIC_SMP_HELPERS
 	depends on MN10300_PROC_MN2WS0038 || MN10300_PROC_MN2WS0050
 	---help---
 	  This enables support for systems with more than one CPU. If you have
@@ -226,11 +221,6 @@ config NR_CPUS
 	depends on SMP
 	default "2"
 
-config USE_GENERIC_SMP_HELPERS
-	bool
-	depends on SMP
-	default y
-
 source "kernel/Kconfig.preempt"
 
 config MN10300_CURRENT_IN_E2
diff -druNp linux-libre-2.6.37-gnu1/arch/mn10300/kernel/rtc.c linux-libre-2.6.38-gnu1/arch/mn10300/kernel/rtc.c
--- linux-libre-2.6.37-gnu1/arch/mn10300/kernel/rtc.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mn10300/kernel/rtc.c	2011-03-14 21:20:32.000000000 -0400
@@ -89,7 +89,7 @@ static int set_rtc_mmss(unsigned long no
 		CMOS_WRITE(real_seconds, RTC_SECONDS);
 		CMOS_WRITE(real_minutes, RTC_MINUTES);
 	} else {
-		printk(KERN_WARNING
+		printk_once(KERN_NOTICE
 		       "set_rtc_mmss: can't update from %d to %d\n",
 		       cmos_minutes, real_minutes);
 		retval = -1;
diff -druNp linux-libre-2.6.37-gnu1/arch/mn10300/mm/cache-inv-icache.c linux-libre-2.6.38-gnu1/arch/mn10300/mm/cache-inv-icache.c
--- linux-libre-2.6.37-gnu1/arch/mn10300/mm/cache-inv-icache.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/mn10300/mm/cache-inv-icache.c	2011-03-14 21:20:32.000000000 -0400
@@ -69,7 +69,7 @@ static void flush_icache_page_range(unsi
 
 	/* invalidate the icache coverage on that region */
 	mn10300_local_icache_inv_range2(addr + off, size);
-	smp_cache_call(SMP_ICACHE_INV_FLUSH_RANGE, start, end);
+	smp_cache_call(SMP_ICACHE_INV_RANGE, start, end);
 }
 
 /**
@@ -101,7 +101,7 @@ void flush_icache_range(unsigned long st
 		 * directly */
 		start_page = (start >= 0x80000000UL) ? start : 0x80000000UL;
 		mn10300_icache_inv_range(start_page, end);
-		smp_cache_call(SMP_ICACHE_INV_FLUSH_RANGE, start, end);
+		smp_cache_call(SMP_ICACHE_INV_RANGE, start, end);
 		if (start_page == start)
 			goto done;
 		end = start_page;
diff -druNp linux-libre-2.6.37-gnu1/arch/parisc/configs/a500_defconfig linux-libre-2.6.38-gnu1/arch/parisc/configs/a500_defconfig
--- linux-libre-2.6.37-gnu1/arch/parisc/configs/a500_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/parisc/configs/a500_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -8,7 +8,7 @@ CONFIG_LOG_BUF_SHIFT=16
 CONFIG_SYSFS_DEPRECATED_V2=y
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 CONFIG_KALLSYMS_ALL=y
 CONFIG_SLAB=y
 CONFIG_PROFILING=y
diff -druNp linux-libre-2.6.37-gnu1/arch/parisc/configs/c3000_defconfig linux-libre-2.6.38-gnu1/arch/parisc/configs/c3000_defconfig
--- linux-libre-2.6.37-gnu1/arch/parisc/configs/c3000_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/parisc/configs/c3000_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -6,7 +6,7 @@ CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=16
 CONFIG_SYSFS_DEPRECATED_V2=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 CONFIG_KALLSYMS_ALL=y
 CONFIG_SLAB=y
 CONFIG_PROFILING=y
diff -druNp linux-libre-2.6.37-gnu1/arch/parisc/include/asm/ioctls.h linux-libre-2.6.38-gnu1/arch/parisc/include/asm/ioctls.h
--- linux-libre-2.6.37-gnu1/arch/parisc/include/asm/ioctls.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/parisc/include/asm/ioctls.h	2011-03-14 21:20:32.000000000 -0400
@@ -52,6 +52,7 @@
 #define TCSETSF2	_IOW('T',0x2D, struct termios2)
 #define TIOCGPTN	_IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
 #define TIOCSPTLCK	_IOW('T',0x31, int)  /* Lock/unlock Pty */
+#define TIOCGDEV	_IOR('T',0x32, int)  /* Get primary device node of /dev/console */
 #define TIOCSIG		_IOW('T',0x36, int)  /* Generate signal on Pty slave */
 
 #define FIONCLEX	0x5450  /* these numbers need to be adjusted. */
diff -druNp linux-libre-2.6.37-gnu1/arch/parisc/include/asm/mman.h linux-libre-2.6.38-gnu1/arch/parisc/include/asm/mman.h
--- linux-libre-2.6.37-gnu1/arch/parisc/include/asm/mman.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/parisc/include/asm/mman.h	2011-03-14 21:20:32.000000000 -0400
@@ -59,6 +59,9 @@
 #define MADV_MERGEABLE   65		/* KSM may merge identical pages */
 #define MADV_UNMERGEABLE 66		/* KSM may not merge identical pages */
 
+#define MADV_HUGEPAGE	67		/* Worth backing with hugepages */
+#define MADV_NOHUGEPAGE	68		/* Not worth backing with hugepages */
+
 /* compatibility flags */
 #define MAP_FILE	0
 #define MAP_VARIABLE	0
diff -druNp linux-libre-2.6.37-gnu1/arch/parisc/include/asm/pgtable.h linux-libre-2.6.38-gnu1/arch/parisc/include/asm/pgtable.h
--- linux-libre-2.6.37-gnu1/arch/parisc/include/asm/pgtable.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/parisc/include/asm/pgtable.h	2011-03-14 21:20:32.000000000 -0400
@@ -10,11 +10,13 @@
  * we simulate an x86-style page table for the linux mm code
  */
 
-#include <linux/mm.h>		/* for vm_area_struct */
 #include <linux/bitops.h>
+#include <linux/spinlock.h>
 #include <asm/processor.h>
 #include <asm/cache.h>
 
+struct vm_area_struct;
+
 /*
  * kern_addr_valid(ADDR) tests if ADDR is pointing to valid kernel
  * memory.  For the return value to be meaningful, ADDR must be >=
diff -druNp linux-libre-2.6.37-gnu1/arch/parisc/Kconfig linux-libre-2.6.38-gnu1/arch/parisc/Kconfig
--- linux-libre-2.6.37-gnu1/arch/parisc/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/parisc/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -12,7 +12,10 @@ config PARISC
 	select HAVE_IRQ_WORK
 	select HAVE_PERF_EVENTS
 	select GENERIC_ATOMIC64 if !64BIT
-	select GENERIC_HARDIRQS_NO__DO_IRQ
+	select HAVE_GENERIC_HARDIRQS
+	select GENERIC_IRQ_PROBE
+	select IRQ_PER_CPU
+
 	help
 	  The PA-RISC microprocessor is designed by Hewlett-Packard and used
 	  in many of their workstations & servers (HP9000 700 and 800 series,
@@ -66,22 +69,9 @@ config TIME_LOW_RES
 	depends on SMP
 	default y
 
-config GENERIC_HARDIRQS
-	def_bool y
-
-config GENERIC_IRQ_PROBE
-	def_bool y
-
 config HAVE_LATENCYTOP_SUPPORT
         def_bool y
 
-config IRQ_PER_CPU
-	bool
-	default y
-
-config GENERIC_HARDIRQS_NO__DO_IRQ
-	def_bool y
-
 # unless you want to implement ACPI on PA-RISC ... ;-)
 config PM
 	bool
diff -druNp linux-libre-2.6.37-gnu1/arch/parisc/kernel/firmware.c linux-libre-2.6.38-gnu1/arch/parisc/kernel/firmware.c
--- linux-libre-2.6.37-gnu1/arch/parisc/kernel/firmware.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/parisc/kernel/firmware.c	2011-03-14 21:20:32.000000000 -0400
@@ -1126,15 +1126,13 @@ int pdc_iodc_print(const unsigned char *
 	unsigned int i;
 	unsigned long flags;
 
-	for (i = 0; i < count && i < 79;) {
+	for (i = 0; i < count;) {
 		switch(str[i]) {
 		case '\n':
 			iodc_dbuf[i+0] = '\r';
 			iodc_dbuf[i+1] = '\n';
 			i += 2;
 			goto print;
-		case '\b':	/* BS */
-			i--; /* overwrite last */
 		default:
 			iodc_dbuf[i] = str[i];
 			i++;
@@ -1142,15 +1140,6 @@ int pdc_iodc_print(const unsigned char *
 		}
 	}
 
-	/* if we're at the end of line, and not already inserting a newline,
-	 * insert one anyway. iodc console doesn't claim to support >79 char
-	 * lines. don't account for this in the return value.
-	 */
-	if (i == 79 && iodc_dbuf[i-1] != '\n') {
-		iodc_dbuf[i+0] = '\r';
-		iodc_dbuf[i+1] = '\n';
-	}
-
 print:
         spin_lock_irqsave(&pdc_lock, flags);
         real32_call(PAGE0->mem_cons.iodc_io,
diff -druNp linux-libre-2.6.37-gnu1/arch/parisc/kernel/pdc_cons.c linux-libre-2.6.38-gnu1/arch/parisc/kernel/pdc_cons.c
--- linux-libre-2.6.37-gnu1/arch/parisc/kernel/pdc_cons.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/parisc/kernel/pdc_cons.c	2011-03-14 21:20:32.000000000 -0400
@@ -92,8 +92,6 @@ static int pdc_console_setup(struct cons
 
 static struct timer_list pdc_console_timer;
 
-extern struct console * console_drivers;
-
 static int pdc_console_tty_open(struct tty_struct *tty, struct file *filp)
 {
 
@@ -169,11 +167,13 @@ static int __init pdc_console_tty_driver
 	 * It is unregistered if the pdc console was not selected as the
 	 * primary console. */
 
-	struct console *tmp = console_drivers;
+	struct console *tmp;
 
-	for (tmp = console_drivers; tmp; tmp = tmp->next)
+	console_lock();
+	for_each_console(tmp)
 		if (tmp == &pdc_cons)
 			break;
+	console_unlock();
 
 	if (!tmp) {
 		printk(KERN_INFO "PDC console driver not registered anymore, not creating %s\n", pdc_cons.name);
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/boot/dts/bluestone.dts linux-libre-2.6.38-gnu1/arch/powerpc/boot/dts/bluestone.dts
--- linux-libre-2.6.37-gnu1/arch/powerpc/boot/dts/bluestone.dts	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/boot/dts/bluestone.dts	2011-03-14 21:20:32.000000000 -0400
@@ -33,7 +33,7 @@
 	aliases {
 		ethernet0 = &EMAC0;
 		serial0 = &UART0;
-		serial1 = &UART1;
+		//serial1 = &UART1; --gcl missing UART1 label
 	};
 
 	cpus {
@@ -52,7 +52,7 @@
 			d-cache-size = <32768>;
 			dcr-controller;
 			dcr-access-method = "native";
-			next-level-cache = <&L2C0>;
+			//next-level-cache = <&L2C0>; --gcl missing L2C0 label
 		};
 	};
 
@@ -142,7 +142,7 @@
 					/*RXEOB*/ 0x7 0x4
 					/*SERR*/  0x3 0x4
 					/*TXDE*/  0x4 0x4
-					/*RXDE*/  0x5 0x4
+					/*RXDE*/  0x5 0x4>;
 		};
 
 		POB0: opb {
@@ -182,7 +182,7 @@
 						reg = <0x001a0000 0x00060000>;
 					};
 				};
-			}
+			};
 
 			UART0: serial@ef600300 {
 				device_type = "serial";
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/boot/dts/canyonlands.dts linux-libre-2.6.38-gnu1/arch/powerpc/boot/dts/canyonlands.dts
--- linux-libre-2.6.37-gnu1/arch/powerpc/boot/dts/canyonlands.dts	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/boot/dts/canyonlands.dts	2011-03-14 21:20:32.000000000 -0400
@@ -105,6 +105,15 @@
 		dcr-reg = <0x00c 0x002>;
 	};
 
+	CPM0: cpm {
+		compatible = "ibm,cpm";
+		dcr-access-method = "native";
+		dcr-reg = <0x160 0x003>;
+		unused-units = <0x00000100>;
+		idle-doze = <0x02000000>;
+		standby = <0xfeff791d>;
+	};
+
 	L2C0: l2c {
 		compatible = "ibm,l2-cache-460ex", "ibm,l2-cache";
 		dcr-reg = <0x020 0x008		/* Internal SRAM DCR's */
@@ -270,28 +279,6 @@
 				interrupts = <0x1 0x4>;
 			};
 
-			UART2: serial@ef600500 {
-				device_type = "serial";
-				compatible = "ns16550";
-				reg = <0xef600500 0x00000008>;
-				virtual-reg = <0xef600500>;
-				clock-frequency = <0>; /* Filled in by U-Boot */
-				current-speed = <0>; /* Filled in by U-Boot */
-				interrupt-parent = <&UIC1>;
-				interrupts = <28 0x4>;
-			};
-
-			UART3: serial@ef600600 {
-				device_type = "serial";
-				compatible = "ns16550";
-				reg = <0xef600600 0x00000008>;
-				virtual-reg = <0xef600600>;
-				clock-frequency = <0>; /* Filled in by U-Boot */
-				current-speed = <0>; /* Filled in by U-Boot */
-				interrupt-parent = <&UIC1>;
-				interrupts = <29 0x4>;
-			};
-
 			IIC0: i2c@ef600700 {
 				compatible = "ibm,iic-460ex", "ibm,iic";
 				reg = <0xef600700 0x00000014>;
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/boot/dts/cm5200.dts linux-libre-2.6.38-gnu1/arch/powerpc/boot/dts/cm5200.dts
--- linux-libre-2.6.37-gnu1/arch/powerpc/boot/dts/cm5200.dts	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/boot/dts/cm5200.dts	2011-03-14 21:20:32.000000000 -0400
@@ -10,220 +10,74 @@
  * option) any later version.
  */
 
-/dts-v1/;
+/include/ "mpc5200b.dtsi"
 
 / {
 	model = "schindler,cm5200";
 	compatible = "schindler,cm5200";
-	#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 0x04000000>;	// 64MB
-	};
 
 	soc5200@f0000000 {
-		#address-cells = <1>;
-		#size-cells = <1>;
-		compatible = "fsl,mpc5200b-immr";
-		ranges = <0 0xf0000000 0x0000c000>;
-		reg = <0xf0000000 0x00000100>;
-		bus-frequency = <0>;		// from bootloader
-		system-frequency = <0>;		// from bootloader
-
-		cdm@200 {
-			compatible = "fsl,mpc5200b-cdm","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,mpc5200b-pic","fsl,mpc5200-pic";
-			reg = <0x500 0x80>;
-		};
-
 		timer@600 {	// General Purpose Timer
-			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
-			reg = <0x600 0x10>;
-			interrupts = <1 9 0>;
 			fsl,has-wdt;
 		};
 
-		timer@610 {	// General Purpose Timer
-			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
-			reg = <0x610 0x10>;
-			interrupts = <1 10 0>;
-		};
-
-		timer@620 {	// General Purpose Timer
-			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
-			reg = <0x620 0x10>;
-			interrupts = <1 11 0>;
-		};
-
-		timer@630 {	// General Purpose Timer
-			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
-			reg = <0x630 0x10>;
-			interrupts = <1 12 0>;
-		};
-
-		timer@640 {	// General Purpose Timer
-			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
-			reg = <0x640 0x10>;
-			interrupts = <1 13 0>;
-		};
-
-		timer@650 {	// General Purpose Timer
-			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
-			reg = <0x650 0x10>;
-			interrupts = <1 14 0>;
-		};
-
-		timer@660 {	// General Purpose Timer
-			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
-			reg = <0x660 0x10>;
-			interrupts = <1 15 0>;
-		};
-
-		timer@670 {	// General Purpose Timer
-			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
-			reg = <0x670 0x10>;
-			interrupts = <1 16 0>;
-		};
-
-		rtc@800 {	// Real time clock
-			compatible = "fsl,mpc5200b-rtc","fsl,mpc5200-rtc";
-			reg = <0x800 0x100>;
-			interrupts = <1 5 0 1 6 0>;
-		};
-
-		gpio_simple: gpio@b00 {
-			compatible = "fsl,mpc5200b-gpio","fsl,mpc5200-gpio";
-			reg = <0xb00 0x40>;
-			interrupts = <1 7 0>;
-			gpio-controller;
-			#gpio-cells = <2>;
-		};
-
-		gpio_wkup: gpio@c00 {
-			compatible = "fsl,mpc5200b-gpio-wkup","fsl,mpc5200-gpio-wkup";
-			reg = <0xc00 0x40>;
-			interrupts = <1 8 0 0 3 0>;
-			gpio-controller;
-			#gpio-cells = <2>;
-		};
-
-		spi@f00 {
-			compatible = "fsl,mpc5200b-spi","fsl,mpc5200-spi";
-			reg = <0xf00 0x20>;
-			interrupts = <2 13 0 2 14 0>;
+		can@900 {
+			status = "disabled";
 		};
 
-		usb@1000 {
-			compatible = "fsl,mpc5200b-ohci","fsl,mpc5200-ohci","ohci-be";
-			reg = <0x1000 0xff>;
-			interrupts = <2 6 0>;
+		can@980 {
+			status = "disabled";
 		};
 
-		dma-controller@1200 {
-			compatible = "fsl,mpc5200b-bestcomm","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>;
+		psc@2000 {		// PSC1
+			compatible = "fsl,mpc5200b-psc-uart","fsl,mpc5200-psc-uart";
 		};
 
-		xlb@1f00 {
-			compatible = "fsl,mpc5200b-xlb","fsl,mpc5200-xlb";
-			reg = <0x1f00 0x100>;
+		psc@2200 {		// PSC2
+			compatible = "fsl,mpc5200b-psc-uart","fsl,mpc5200-psc-uart";
 		};
 
-		serial@2000 {		// PSC1
+		psc@2400 {		// PSC3
 			compatible = "fsl,mpc5200b-psc-uart","fsl,mpc5200-psc-uart";
-			reg = <0x2000 0x100>;
-			interrupts = <2 1 0>;
 		};
 
-		serial@2200 {		// PSC2
-			compatible = "fsl,mpc5200b-psc-uart","fsl,mpc5200-psc-uart";
-			reg = <0x2200 0x100>;
-			interrupts = <2 2 0>;
+		psc@2600 {		// PSC4
+			status = "disabled";
 		};
 
-		serial@2400 {		// PSC3
-			compatible = "fsl,mpc5200b-psc-uart","fsl,mpc5200-psc-uart";
-			reg = <0x2400 0x100>;
-			interrupts = <2 3 0>;
+		psc@2800 {		// PSC5
+			status = "disabled";
 		};
 
-		serial@2c00 {		// PSC6
+		psc@2c00 {		// PSC6
 			compatible = "fsl,mpc5200b-psc-uart","fsl,mpc5200-psc-uart";
-			reg = <0x2c00 0x100>;
-			interrupts = <2 4 0>;
 		};
 
 		ethernet@3000 {
-			compatible = "fsl,mpc5200b-fec","fsl,mpc5200-fec";
-			reg = <0x3000 0x400>;
-			local-mac-address = [ 00 00 00 00 00 00 ];
-			interrupts = <2 5 0>;
 			phy-handle = <&phy0>;
 		};
 
 		mdio@3000 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,mpc5200b-mdio","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.
-
 			phy0: ethernet-phy@0 {
 				reg = <0>;
 			};
 		};
 
-		i2c@3d40 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,mpc5200b-i2c","fsl,mpc5200-i2c","fsl-i2c";
-			reg = <0x3d40 0x40>;
-			interrupts = <2 16 0>;
+		ata@3a00 {
+			status = "disabled";
 		};
 
-		sram@8000 {
-			compatible = "fsl,mpc5200b-sram","fsl,mpc5200-sram";
-			reg = <0x8000 0x4000>;
+		i2c@3d00 {
+			status = "disabled";
 		};
+
 	};
 
-	localbus {
-		compatible = "fsl,mpc5200b-lpb","simple-bus";
-		#address-cells = <2>;
-		#size-cells = <1>;
-		ranges = <0 0 0xfc000000 0x2000000>;
+	pci@f0000d00 {
+		status = "disabled";
+	};
 
+	localbus {
 		// 16-bit flash device at LocalPlus Bus CS0
 		flash@0,0 {
 			compatible = "cfi-flash";
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/boot/dts/digsy_mtc.dts linux-libre-2.6.38-gnu1/arch/powerpc/boot/dts/digsy_mtc.dts
--- linux-libre-2.6.37-gnu1/arch/powerpc/boot/dts/digsy_mtc.dts	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/boot/dts/digsy_mtc.dts	2011-03-14 21:20:32.000000000 -0400
@@ -11,195 +11,68 @@
  * option) any later version.
  */
 
-/dts-v1/;
+/include/ "mpc5200b.dtsi"
 
 / {
 	model = "intercontrol,digsy-mtc";
 	compatible = "intercontrol,digsy-mtc";
-	#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 0x02000000>;	// 32MB
 	};
 
 	soc5200@f0000000 {
-		#address-cells = <1>;
-		#size-cells = <1>;
-		compatible = "fsl,mpc5200b-immr";
-		ranges = <0 0xf0000000 0x0000c000>;
-		reg = <0xf0000000 0x00000100>;
-		bus-frequency = <0>;		// from bootloader
-		system-frequency = <0>;		// from bootloader
-
-		cdm@200 {
-			compatible = "fsl,mpc5200b-cdm","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,mpc5200b-pic","fsl,mpc5200-pic";
-			reg = <0x500 0x80>;
-		};
-
 		timer@600 {	// General Purpose Timer
-			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
-			reg = <0x600 0x10>;
-			interrupts = <1 9 0>;
 			fsl,has-wdt;
 		};
 
-		timer@610 {	// General Purpose Timer
-			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
-			reg = <0x610 0x10>;
-			interrupts = <1 10 0>;
-		};
-
-		timer@620 {	// General Purpose Timer
-			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
-			reg = <0x620 0x10>;
-			interrupts = <1 11 0>;
-		};
-
-		timer@630 {	// General Purpose Timer
-			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
-			reg = <0x630 0x10>;
-			interrupts = <1 12 0>;
-		};
-
-		timer@640 {	// General Purpose Timer
-			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
-			reg = <0x640 0x10>;
-			interrupts = <1 13 0>;
-		};
-
-		timer@650 {	// General Purpose Timer
-			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
-			reg = <0x650 0x10>;
-			interrupts = <1 14 0>;
-		};
-
-		timer@660 {	// General Purpose Timer
-			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
-			reg = <0x660 0x10>;
-			interrupts = <1 15 0>;
-		};
-
-		timer@670 {	// General Purpose Timer
-			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
-			reg = <0x670 0x10>;
-			interrupts = <1 16 0>;
+		rtc@800 {
+			status = "disabled";
 		};
 
-		gpio_simple: gpio@b00 {
-			compatible = "fsl,mpc5200b-gpio","fsl,mpc5200-gpio";
-			reg = <0xb00 0x40>;
-			interrupts = <1 7 0>;
-			gpio-controller;
-			#gpio-cells = <2>;
+		can@900 {
+			status = "disabled";
 		};
 
-		gpio_wkup: gpio@c00 {
-			compatible = "fsl,mpc5200b-gpio-wkup","fsl,mpc5200-gpio-wkup";
-			reg = <0xc00 0x40>;
-			interrupts = <1 8 0 0 3 0>;
-			gpio-controller;
-			#gpio-cells = <2>;
+		can@980 {
+			status = "disabled";
 		};
 
-		spi@f00 {
-			compatible = "fsl,mpc5200b-spi","fsl,mpc5200-spi";
-			reg = <0xf00 0x20>;
-			interrupts = <2 13 0 2 14 0>;
+		psc@2000 {		// PSC1
+			status = "disabled";
 		};
 
-		usb@1000 {
-			compatible = "fsl,mpc5200b-ohci","fsl,mpc5200-ohci","ohci-be";
-			reg = <0x1000 0xff>;
-			interrupts = <2 6 0>;
+		psc@2200 {		// PSC2
+			status = "disabled";
 		};
 
-		dma-controller@1200 {
-			compatible = "fsl,mpc5200b-bestcomm","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>;
+		psc@2400 {		// PSC3
+			status = "disabled";
 		};
 
-		xlb@1f00 {
-			compatible = "fsl,mpc5200b-xlb","fsl,mpc5200-xlb";
-			reg = <0x1f00 0x100>;
+		psc@2600 {		// PSC4
+			compatible = "fsl,mpc5200b-psc-uart","fsl,mpc5200-psc-uart";
 		};
 
-		serial@2600 {		// PSC4
+		psc@2800 {		// PSC5
 			compatible = "fsl,mpc5200b-psc-uart","fsl,mpc5200-psc-uart";
-			reg = <0x2600 0x100>;
-			interrupts = <2 11 0>;
 		};
 
-		serial@2800 {		// PSC5
-			compatible = "fsl,mpc5200b-psc-uart","fsl,mpc5200-psc-uart";
-			reg = <0x2800 0x100>;
-			interrupts = <2 12 0>;
+		psc@2c00 {		// PSC6
+			status = "disabled";
 		};
 
 		ethernet@3000 {
-			compatible = "fsl,mpc5200b-fec","fsl,mpc5200-fec";
-			reg = <0x3000 0x400>;
-			local-mac-address = [ 00 00 00 00 00 00 ];
-			interrupts = <2 5 0>;
 			phy-handle = <&phy0>;
 		};
 
 		mdio@3000 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,mpc5200b-mdio","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.
-
 			phy0: ethernet-phy@0 {
 				reg = <0>;
 			};
 		};
 
-		ata@3a00 {
-			compatible = "fsl,mpc5200b-ata","fsl,mpc5200-ata";
-			reg = <0x3a00 0x100>;
-			interrupts = <2 7 0>;
-		};
-
 		i2c@3d00 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,mpc5200b-i2c","fsl,mpc5200-i2c","fsl-i2c";
-			reg = <0x3d00 0x40>;
-			interrupts = <2 15 0>;
-
 			rtc@50 {
 				compatible = "at,24c08";
 				reg = <0x50>;
@@ -211,16 +84,16 @@
 			};
 		};
 
-		sram@8000 {
-			compatible = "fsl,mpc5200b-sram","fsl,mpc5200-sram";
-			reg = <0x8000 0x4000>;
+		i2c@3d40 {
+			status = "disabled";
 		};
 	};
 
-	lpb {
-		compatible = "fsl,mpc5200b-lpb","simple-bus";
-		#address-cells = <2>;
-		#size-cells = <1>;
+	pci@f0000d00 {
+		status = "disabled";
+	};
+
+	localbus {
 		ranges = <0 0 0xff000000 0x1000000>;
 
 		// 16-bit flash device at LocalPlus Bus CS0
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/boot/dts/hotfoot.dts linux-libre-2.6.38-gnu1/arch/powerpc/boot/dts/hotfoot.dts
--- linux-libre-2.6.37-gnu1/arch/powerpc/boot/dts/hotfoot.dts	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/boot/dts/hotfoot.dts	2011-03-14 21:20:32.000000000 -0400
@@ -117,6 +117,8 @@
 			};
 
 			IIC: i2c@ef600500 {
+				#address-cells = <1>;
+				#size-cells = <0>;
 				compatible = "ibm,iic-405ep", "ibm,iic";
 				reg = <0xef600500 0x00000011>;
 				interrupt-parent = <&UIC0>;
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/boot/dts/kilauea.dts linux-libre-2.6.38-gnu1/arch/powerpc/boot/dts/kilauea.dts
--- linux-libre-2.6.37-gnu1/arch/powerpc/boot/dts/kilauea.dts	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/boot/dts/kilauea.dts	2011-03-14 21:20:32.000000000 -0400
@@ -82,6 +82,15 @@
 		interrupt-parent = <&UIC0>;
 	};
 
+	CPM0: cpm {
+		compatible = "ibm,cpm";
+		dcr-access-method = "native";
+		dcr-reg = <0x0b0 0x003>;
+		unused-units = <0x00000000>;
+		idle-doze = <0x02000000>;
+		standby = <0xe3e74800>;
+	};
+
 	plb {
 		compatible = "ibm,plb-405ex", "ibm,plb4";
 		#address-cells = <1>;
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/boot/dts/lite5200b.dts linux-libre-2.6.38-gnu1/arch/powerpc/boot/dts/lite5200b.dts
--- linux-libre-2.6.37-gnu1/arch/powerpc/boot/dts/lite5200b.dts	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/boot/dts/lite5200b.dts	2011-03-14 21:20:32.000000000 -0400
@@ -10,256 +10,75 @@
  * option) any later version.
  */
 
-/dts-v1/;
+/include/ "mpc5200b.dtsi"
 
 / {
 	model = "fsl,lite5200b";
 	compatible = "fsl,lite5200b";
-	#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 0x10000000>;	// 256MB
 	};
 
 	soc5200@f0000000 {
-		#address-cells = <1>;
-		#size-cells = <1>;
-		compatible = "fsl,mpc5200b-immr";
-		ranges = <0 0xf0000000 0x0000c000>;
-		reg = <0xf0000000 0x00000100>;
-		bus-frequency = <0>;		// from bootloader
-		system-frequency = <0>;		// from bootloader
-
-		cdm@200 {
-			compatible = "fsl,mpc5200b-cdm","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,mpc5200b-pic","fsl,mpc5200-pic";
-			reg = <0x500 0x80>;
-		};
-
 		timer@600 {	// General Purpose Timer
-			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
-			reg = <0x600 0x10>;
-			interrupts = <1 9 0>;
 			fsl,has-wdt;
 		};
 
-		timer@610 {	// General Purpose Timer
-			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
-			reg = <0x610 0x10>;
-			interrupts = <1 10 0>;
-		};
-
-		timer@620 {	// General Purpose Timer
-			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
-			reg = <0x620 0x10>;
-			interrupts = <1 11 0>;
-		};
-
-		timer@630 {	// General Purpose Timer
-			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
-			reg = <0x630 0x10>;
-			interrupts = <1 12 0>;
-		};
-
-		timer@640 {	// General Purpose Timer
-			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
-			reg = <0x640 0x10>;
-			interrupts = <1 13 0>;
-		};
-
-		timer@650 {	// General Purpose Timer
-			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
-			reg = <0x650 0x10>;
-			interrupts = <1 14 0>;
-		};
-
-		timer@660 {	// General Purpose Timer
-			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
-			reg = <0x660 0x10>;
-			interrupts = <1 15 0>;
-		};
-
-		timer@670 {	// General Purpose Timer
-			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
-			reg = <0x670 0x10>;
-			interrupts = <1 16 0>;
-		};
-
-		rtc@800 {	// Real time clock
-			compatible = "fsl,mpc5200b-rtc","fsl,mpc5200-rtc";
-			reg = <0x800 0x100>;
-			interrupts = <1 5 0 1 6 0>;
-		};
-
-		can@900 {
-			compatible = "fsl,mpc5200b-mscan","fsl,mpc5200-mscan";
-			interrupts = <2 17 0>;
-			reg = <0x900 0x80>;
-		};
-
-		can@980 {
-			compatible = "fsl,mpc5200b-mscan","fsl,mpc5200-mscan";
-			interrupts = <2 18 0>;
-			reg = <0x980 0x80>;
-		};
-
-		gpio_simple: gpio@b00 {
-			compatible = "fsl,mpc5200b-gpio","fsl,mpc5200-gpio";
-			reg = <0xb00 0x40>;
-			interrupts = <1 7 0>;
-			gpio-controller;
-			#gpio-cells = <2>;
-		};
-
-		gpio_wkup: gpio@c00 {
-			compatible = "fsl,mpc5200b-gpio-wkup","fsl,mpc5200-gpio-wkup";
-			reg = <0xc00 0x40>;
-			interrupts = <1 8 0 0 3 0>;
-			gpio-controller;
-			#gpio-cells = <2>;
+		psc@2000 {		// PSC1
+			compatible = "fsl,mpc5200b-psc-uart","fsl,mpc5200-psc-uart";
+			cell-index = <0>;
 		};
 
-		spi@f00 {
-			compatible = "fsl,mpc5200b-spi","fsl,mpc5200-spi";
-			reg = <0xf00 0x20>;
-			interrupts = <2 13 0 2 14 0>;
+		psc@2200 {		// PSC2
+			status = "disabled";
 		};
 
-		usb@1000 {
-			compatible = "fsl,mpc5200b-ohci","fsl,mpc5200-ohci","ohci-be";
-			reg = <0x1000 0xff>;
-			interrupts = <2 6 0>;
+		psc@2400 {		// PSC3
+			status = "disabled";
 		};
 
-		dma-controller@1200 {
-			compatible = "fsl,mpc5200b-bestcomm","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>;
+		psc@2600 {		// PSC4
+			status = "disabled";
 		};
 
-		xlb@1f00 {
-			compatible = "fsl,mpc5200b-xlb","fsl,mpc5200-xlb";
-			reg = <0x1f00 0x100>;
+		psc@2800 {		// PSC5
+			status = "disabled";
 		};
 
-		serial@2000 {		// PSC1
-			compatible = "fsl,mpc5200b-psc-uart","fsl,mpc5200-psc-uart";
-			cell-index = <0>;
-			reg = <0x2000 0x100>;
-			interrupts = <2 1 0>;
+		psc@2c00 {		// PSC6
+			status = "disabled";
 		};
 
 		// PSC2 in ac97 mode example
 		//ac97@2200 {		// PSC2
 		//	compatible = "fsl,mpc5200b-psc-ac97","fsl,mpc5200-psc-ac97";
 		//	cell-index = <1>;
-		//	reg = <0x2200 0x100>;
-		//	interrupts = <2 2 0>;
 		//};
 
 		// PSC3 in CODEC mode example
 		//i2s@2400 {		// PSC3
 		//	compatible = "fsl,mpc5200b-psc-i2s"; //not 5200 compatible
 		//	cell-index = <2>;
-		//	reg = <0x2400 0x100>;
-		//	interrupts = <2 3 0>;
-		//};
-
-		// PSC4 in uart mode example
-		//serial@2600 {		// PSC4
-		//	compatible = "fsl,mpc5200b-psc-uart","fsl,mpc5200-psc-uart";
-		//	cell-index = <3>;
-		//	reg = <0x2600 0x100>;
-		//	interrupts = <2 11 0>;
-		//};
-
-		// PSC5 in uart mode example
-		//serial@2800 {		// PSC5
-		//	compatible = "fsl,mpc5200b-psc-uart","fsl,mpc5200-psc-uart";
-		//	cell-index = <4>;
-		//	reg = <0x2800 0x100>;
-		//	interrupts = <2 12 0>;
 		//};
 
 		// PSC6 in spi mode example
 		//spi@2c00 {		// PSC6
 		//	compatible = "fsl,mpc5200b-psc-spi","fsl,mpc5200-psc-spi";
 		//	cell-index = <5>;
-		//	reg = <0x2c00 0x100>;
-		//	interrupts = <2 4 0>;
 		//};
 
 		ethernet@3000 {
-			compatible = "fsl,mpc5200b-fec","fsl,mpc5200-fec";
-			reg = <0x3000 0x400>;
-			local-mac-address = [ 00 00 00 00 00 00 ];
-			interrupts = <2 5 0>;
 			phy-handle = <&phy0>;
 		};
 
 		mdio@3000 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,mpc5200b-mdio","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.
-
 			phy0: ethernet-phy@0 {
 				reg = <0>;
 			};
 		};
 
-		ata@3a00 {
-			compatible = "fsl,mpc5200b-ata","fsl,mpc5200-ata";
-			reg = <0x3a00 0x100>;
-			interrupts = <2 7 0>;
-		};
-
-		i2c@3d00 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,mpc5200b-i2c","fsl,mpc5200-i2c","fsl-i2c";
-			reg = <0x3d00 0x40>;
-			interrupts = <2 15 0>;
-		};
-
 		i2c@3d40 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,mpc5200b-i2c","fsl,mpc5200-i2c","fsl-i2c";
-			reg = <0x3d40 0x40>;
-			interrupts = <2 16 0>;
-
 			eeprom@50 {
 				compatible = "atmel,24c02";
 				reg = <0x50>;
@@ -273,12 +92,6 @@
 	};
 
 	pci@f0000d00 {
-		#interrupt-cells = <1>;
-		#size-cells = <2>;
-		#address-cells = <3>;
-		device_type = "pci";
-		compatible = "fsl,mpc5200b-pci","fsl,mpc5200-pci";
-		reg = <0xf0000d00 0x100>;
 		interrupt-map-mask = <0xf800 0 0 7>;
 		interrupt-map = <0xc000 0 0 1 &mpc5200_pic 0 0 3 // 1st slot
 				 0xc000 0 0 2 &mpc5200_pic 1 1 3
@@ -298,11 +111,6 @@
 	};
 
 	localbus {
-		compatible = "fsl,mpc5200b-lpb","fsl,mpc5200-lpb","simple-bus";
-
-		#address-cells = <2>;
-		#size-cells = <1>;
-
 		ranges = <0 0 0xfe000000 0x02000000>;
 
 		flash@0,0 {
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/boot/dts/media5200.dts linux-libre-2.6.38-gnu1/arch/powerpc/boot/dts/media5200.dts
--- linux-libre-2.6.37-gnu1/arch/powerpc/boot/dts/media5200.dts	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/boot/dts/media5200.dts	2011-03-14 21:20:32.000000000 -0400
@@ -11,14 +11,11 @@
  * option) any later version.
  */
 
-/dts-v1/;
+/include/ "mpc5200b.dtsi"
 
 / {
 	model = "fsl,media5200";
 	compatible = "fsl,media5200";
-	#address-cells = <1>;
-	#size-cells = <1>;
-	interrupt-parent = <&mpc5200_pic>;
 
 	aliases {
 		console = &console;
@@ -30,16 +27,7 @@
 	};
 
 	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 = <33000000>;	// 33 MHz, these were configured by U-Boot
 			bus-frequency = <132000000>;		// 132 MHz
 			clock-frequency = <396000000>;		// 396 MHz
@@ -47,205 +35,57 @@
 	};
 
 	memory {
-		device_type = "memory";
 		reg = <0x00000000 0x08000000>;	// 128MB RAM
 	};
 
-	soc@f0000000 {
-		#address-cells = <1>;
-		#size-cells = <1>;
-		compatible = "fsl,mpc5200b-immr";
-		ranges = <0 0xf0000000 0x0000c000>;
-		reg = <0xf0000000 0x00000100>;
+	soc5200@f0000000 {
 		bus-frequency = <132000000>;// 132 MHz
-		system-frequency = <0>;		// from bootloader
-
-		cdm@200 {
-			compatible = "fsl,mpc5200b-cdm","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,mpc5200b-pic","fsl,mpc5200-pic";
-			reg = <0x500 0x80>;
-		};
 
 		timer@600 {	// General Purpose Timer
-			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
-			reg = <0x600 0x10>;
-			interrupts = <1 9 0>;
 			fsl,has-wdt;
 		};
 
-		timer@610 {	// General Purpose Timer
-			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
-			reg = <0x610 0x10>;
-			interrupts = <1 10 0>;
-		};
-
-		timer@620 {	// General Purpose Timer
-			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
-			reg = <0x620 0x10>;
-			interrupts = <1 11 0>;
-		};
-
-		timer@630 {	// General Purpose Timer
-			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
-			reg = <0x630 0x10>;
-			interrupts = <1 12 0>;
-		};
-
-		timer@640 {	// General Purpose Timer
-			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
-			reg = <0x640 0x10>;
-			interrupts = <1 13 0>;
-		};
-
-		timer@650 {	// General Purpose Timer
-			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
-			reg = <0x650 0x10>;
-			interrupts = <1 14 0>;
-		};
-
-		timer@660 {	// General Purpose Timer
-			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
-			reg = <0x660 0x10>;
-			interrupts = <1 15 0>;
-		};
-
-		timer@670 {	// General Purpose Timer
-			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
-			reg = <0x670 0x10>;
-			interrupts = <1 16 0>;
-		};
-
-		rtc@800 {	// Real time clock
-			compatible = "fsl,mpc5200b-rtc","fsl,mpc5200-rtc";
-			reg = <0x800 0x100>;
-			interrupts = <1 5 0 1 6 0>;
-		};
-
-		can@900 {
-			compatible = "fsl,mpc5200b-mscan","fsl,mpc5200-mscan";
-			interrupts = <2 17 0>;
-			reg = <0x900 0x80>;
-		};
-
-		can@980 {
-			compatible = "fsl,mpc5200b-mscan","fsl,mpc5200-mscan";
-			interrupts = <2 18 0>;
-			reg = <0x980 0x80>;
-		};
-
-		gpio_simple: gpio@b00 {
-			compatible = "fsl,mpc5200b-gpio","fsl,mpc5200-gpio";
-			reg = <0xb00 0x40>;
-			interrupts = <1 7 0>;
-			gpio-controller;
-			#gpio-cells = <2>;
-		};
-
-		gpio_wkup: gpio@c00 {
-			compatible = "fsl,mpc5200b-gpio-wkup","fsl,mpc5200-gpio-wkup";
-			reg = <0xc00 0x40>;
-			interrupts = <1 8 0 0 3 0>;
-			gpio-controller;
-			#gpio-cells = <2>;
+		psc@2000 {	// PSC1
+			status = "disabled";
 		};
 
-		spi@f00 {
-			compatible = "fsl,mpc5200b-spi","fsl,mpc5200-spi";
-			reg = <0xf00 0x20>;
-			interrupts = <2 13 0 2 14 0>;
+		psc@2200 {	// PSC2
+			status = "disabled";
 		};
 
-		usb@1000 {
-			compatible = "fsl,mpc5200b-ohci","fsl,mpc5200-ohci","ohci-be";
-			reg = <0x1000 0x100>;
-			interrupts = <2 6 0>;
+		psc@2400 {	// PSC3
+			status = "disabled";
 		};
 
-		dma-controller@1200 {
-			compatible = "fsl,mpc5200b-bestcomm","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>;
+		psc@2600 {	// PSC4
+			status = "disabled";
 		};
 
-		xlb@1f00 {
-			compatible = "fsl,mpc5200b-xlb","fsl,mpc5200-xlb";
-			reg = <0x1f00 0x100>;
+		psc@2800 {	// PSC5
+			status = "disabled";
 		};
 
 		// PSC6 in uart mode
-		console: serial@2c00 {		// PSC6
+		console: psc@2c00 {		// PSC6
 			compatible = "fsl,mpc5200b-psc-uart","fsl,mpc5200-psc-uart";
-			cell-index = <5>;
-			port-number = <0>;  // Logical port assignment
-			reg = <0x2c00 0x100>;
-			interrupts = <2 4 0>;
 		};
 
-		eth0: ethernet@3000 {
-			compatible = "fsl,mpc5200b-fec","fsl,mpc5200-fec";
-			reg = <0x3000 0x400>;
-			local-mac-address = [ 00 00 00 00 00 00 ];
-			interrupts = <2 5 0>;
+		ethernet@3000 {
 			phy-handle = <&phy0>;
 		};
 
 		mdio@3000 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,mpc5200b-mdio","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.
-
 			phy0: ethernet-phy@0 {
 				reg = <0>;
 			};
 		};
 
-		ata@3a00 {
-			compatible = "fsl,mpc5200b-ata","fsl,mpc5200-ata";
-			reg = <0x3a00 0x100>;
-			interrupts = <2 7 0>;
-		};
-
-		i2c@3d00 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,mpc5200b-i2c","fsl,mpc5200-i2c","fsl-i2c";
-			reg = <0x3d00 0x40>;
-			interrupts = <2 15 0>;
-		};
-
-		i2c@3d40 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,mpc5200b-i2c","fsl,mpc5200-i2c","fsl-i2c";
-			reg = <0x3d40 0x40>;
-			interrupts = <2 16 0>;
-		};
-
-		sram@8000 {
-			compatible = "fsl,mpc5200b-sram","fsl,mpc5200-sram";
-			reg = <0x8000 0x4000>;
+		usb@1000 {
+			reg = <0x1000 0x100>;
 		};
 	};
 
 	pci@f0000d00 {
-		#interrupt-cells = <1>;
-		#size-cells = <2>;
-		#address-cells = <3>;
-		device_type = "pci";
-		compatible = "fsl,mpc5200b-pci","fsl,mpc5200-pci";
-		reg = <0xf0000d00 0x100>;
 		interrupt-map-mask = <0xf800 0 0 7>;
 		interrupt-map = <0xc000 0 0 1 &media5200_fpga 0 2 // 1st slot
 				 0xc000 0 0 2 &media5200_fpga 0 3
@@ -262,37 +102,29 @@
 
 				 0xe000 0 0 1 &media5200_fpga 0 5 // CoralIP
 				>;
-		clock-frequency = <0>; // From boot loader
-		interrupts = <2 8 0 2 9 0 2 10 0>;
-		interrupt-parent = <&mpc5200_pic>;
-		bus-range = <0 0>;
 		ranges = <0x42000000 0 0x80000000 0x80000000 0 0x20000000
 			  0x02000000 0 0xa0000000 0xa0000000 0 0x10000000
 			  0x01000000 0 0x00000000 0xb0000000 0 0x01000000>;
+		interrupt-parent = <&mpc5200_pic>;
 	};
 
 	localbus {
-		compatible = "fsl,mpc5200b-lpb","simple-bus";
-		#address-cells = <2>;
-		#size-cells = <1>;
-
 		ranges = < 0 0 0xfc000000 0x02000000
 			   1 0 0xfe000000 0x02000000
 			   2 0 0xf0010000 0x00010000
 			   3 0 0xf0020000 0x00010000 >;
-
 		flash@0,0 {
 			compatible = "amd,am29lv28ml", "cfi-flash";
-			reg = <0 0x0 0x2000000>;		// 32 MB
-			bank-width = <4>;			// Width in bytes of the flash bank
-			device-width = <2>;			// Two devices on each bank
+			reg = <0 0x0 0x2000000>;                // 32 MB
+			bank-width = <4>;                       // Width in bytes of the flash bank
+			device-width = <2>;                     // Two devices on each bank
 		};
 
 		flash@1,0 {
 			compatible = "amd,am29lv28ml", "cfi-flash";
-			reg = <1 0 0x2000000>;			// 32 MB
-			bank-width = <4>;			// Width in bytes of the flash bank
-			device-width = <2>;			// Two devices on each bank
+			reg = <1 0 0x2000000>;                  // 32 MB
+			bank-width = <4>;                       // Width in bytes of the flash bank
+			device-width = <2>;                     // Two devices on each bank
 		};
 
 		media5200_fpga: fpga@2,0 {
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/boot/dts/motionpro.dts linux-libre-2.6.38-gnu1/arch/powerpc/boot/dts/motionpro.dts
--- linux-libre-2.6.37-gnu1/arch/powerpc/boot/dts/motionpro.dts	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/boot/dts/motionpro.dts	2011-03-14 21:20:32.000000000 -0400
@@ -10,219 +10,73 @@
  * option) any later version.
  */
 
-/dts-v1/;
+/include/ "mpc5200b.dtsi"
 
 / {
 	model = "promess,motionpro";
 	compatible = "promess,motionpro";
-	#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 0x04000000>;	// 64MB
-	};
 
 	soc5200@f0000000 {
-		#address-cells = <1>;
-		#size-cells = <1>;
-		compatible = "fsl,mpc5200b-immr";
-		ranges = <0 0xf0000000 0x0000c000>;
-		reg = <0xf0000000 0x00000100>;
-		bus-frequency = <0>;		// from bootloader
-		system-frequency = <0>;		// from bootloader
-
-		cdm@200 {
-			compatible = "fsl,mpc5200b-cdm","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,mpc5200b-pic","fsl,mpc5200-pic";
-			reg = <0x500 0x80>;
-		};
-
 		timer@600 {	// General Purpose Timer
-			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
-			reg = <0x600 0x10>;
-			interrupts = <1 9 0>;
 			fsl,has-wdt;
 		};
 
-		timer@610 {	// General Purpose Timer
-			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
-			reg = <0x610 0x10>;
-			interrupts = <1 10 0>;
-		};
-
-		timer@620 {	// General Purpose Timer
-			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
-			reg = <0x620 0x10>;
-			interrupts = <1 11 0>;
-		};
-
-		timer@630 {	// General Purpose Timer
-			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
-			reg = <0x630 0x10>;
-			interrupts = <1 12 0>;
-		};
-
-		timer@640 {	// General Purpose Timer
-			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
-			reg = <0x640 0x10>;
-			interrupts = <1 13 0>;
-		};
-
-		timer@650 {	// General Purpose Timer
-			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
-			reg = <0x650 0x10>;
-			interrupts = <1 14 0>;
-		};
-
-		motionpro-led@660 {	// Motion-PRO status LED
+		timer@660 {	// Motion-PRO status LED
 			compatible = "promess,motionpro-led";
 			label = "motionpro-statusled";
-			reg = <0x660 0x10>;
-			interrupts = <1 15 0>;
 			blink-delay = <100>; // 100 msec
 		};
 
-		motionpro-led@670 {	// Motion-PRO ready LED
+		timer@670 {	// Motion-PRO ready LED
 			compatible = "promess,motionpro-led";
 			label = "motionpro-readyled";
-			reg = <0x670 0x10>;
-			interrupts = <1 16 0>;
-		};
-
-		rtc@800 {	// Real time clock
-			compatible = "fsl,mpc5200b-rtc","fsl,mpc5200-rtc";
-			reg = <0x800 0x100>;
-			interrupts = <1 5 0 1 6 0>;
-		};
-
-		can@980 {
-			compatible = "fsl,mpc5200b-mscan","fsl,mpc5200-mscan";
-			interrupts = <2 18 0>;
-			reg = <0x980 0x80>;
 		};
 
-		gpio_simple: gpio@b00 {
-			compatible = "fsl,mpc5200b-gpio","fsl,mpc5200-gpio";
-			reg = <0xb00 0x40>;
-			interrupts = <1 7 0>;
-			gpio-controller;
-			#gpio-cells = <2>;
-		};
-
-		gpio_wkup: gpio@c00 {
-			compatible = "fsl,mpc5200b-gpio-wkup","fsl,mpc5200-gpio-wkup";
-			reg = <0xc00 0x40>;
-			interrupts = <1 8 0 0 3 0>;
-			gpio-controller;
-			#gpio-cells = <2>;
+		can@900 {
+			status = "disabled";
 		};
 
-		spi@f00 {
-			compatible = "fsl,mpc5200b-spi","fsl,mpc5200-spi";
-			reg = <0xf00 0x20>;
-			interrupts = <2 13 0 2 14 0>;
+		psc@2000 {		// PSC1
+			compatible = "fsl,mpc5200b-psc-uart","fsl,mpc5200-psc-uart";
 		};
 
-		usb@1000 {
-			compatible = "fsl,mpc5200b-ohci","fsl,mpc5200-ohci","ohci-be";
-			reg = <0x1000 0xff>;
-			interrupts = <2 6 0>;
+		// PSC2 in spi master mode 
+		psc@2200 {		// PSC2
+			compatible = "fsl,mpc5200b-psc-spi","fsl,mpc5200-psc-spi";
+			cell-index = <1>;
 		};
 
-		dma-controller@1200 {
-			compatible = "fsl,mpc5200b-bestcomm","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>;
+		psc@2400 {		// PSC3
+			status = "disabled";
 		};
 
-		xlb@1f00 {
-			compatible = "fsl,mpc5200b-xlb","fsl,mpc5200-xlb";
-			reg = <0x1f00 0x100>;
+		psc@2600 {		// PSC4
+			status = "disabled";
 		};
 
-		serial@2000 {		// PSC1
+		psc@2800 {		// PSC5
 			compatible = "fsl,mpc5200b-psc-uart","fsl,mpc5200-psc-uart";
-			reg = <0x2000 0x100>;
-			interrupts = <2 1 0>;
-		};
-
-		// PSC2 in spi master mode 
-		spi@2200 {		// PSC2
-			compatible = "fsl,mpc5200b-psc-spi","fsl,mpc5200-psc-spi";
-			cell-index = <1>;
-			reg = <0x2200 0x100>;
-			interrupts = <2 2 0>;
 		};
 
-		// PSC5 in uart mode
-		serial@2800 {		// PSC5
-			compatible = "fsl,mpc5200b-psc-uart","fsl,mpc5200-psc-uart";
-			reg = <0x2800 0x100>;
-			interrupts = <2 12 0>;
+		psc@2c00 {		// PSC6
+			status = "disabled";
 		};
 
 		ethernet@3000 {
-			compatible = "fsl,mpc5200b-fec","fsl,mpc5200-fec";
-			reg = <0x3000 0x400>;
-			local-mac-address = [ 00 00 00 00 00 00 ];
-			interrupts = <2 5 0>;
 			phy-handle = <&phy0>;
 		};
 
 		mdio@3000 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,mpc5200b-mdio","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.
-
 			phy0: ethernet-phy@2 {
 				reg = <2>;
 			};
 		};
 
-		ata@3a00 {
-			compatible = "fsl,mpc5200b-ata","fsl,mpc5200-ata";
-			reg = <0x3a00 0x100>;
-			interrupts = <2 7 0>;
+		i2c@3d00 {
+			status = "disabled";
 		};
 
 		i2c@3d40 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,mpc5200b-i2c","fsl,mpc5200-i2c","fsl-i2c";
-			reg = <0x3d40 0x40>;
-			interrupts = <2 16 0>;
-
 			rtc@68 {
 				compatible = "dallas,ds1339";
 				reg = <0x68>;
@@ -235,10 +89,11 @@
 		};
 	};
 
+	pci@f0000d00 {
+		status = "disabled";
+	};
+
 	localbus {
-		compatible = "fsl,mpc5200b-lpb","simple-bus";
-		#address-cells = <2>;
-		#size-cells = <1>;
 		ranges = <0 0 0xff000000 0x01000000
 			  1 0 0x50000000 0x00010000
 			  2 0 0x50010000 0x00010000
@@ -280,5 +135,6 @@
 			#size-cells = <1>;
 			#address-cells = <1>;
 		};
+
 	};
 };
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/boot/dts/mpc5200b.dtsi linux-libre-2.6.38-gnu1/arch/powerpc/boot/dts/mpc5200b.dtsi
--- linux-libre-2.6.37-gnu1/arch/powerpc/boot/dts/mpc5200b.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/boot/dts/mpc5200b.dtsi	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,275 @@
+/*
+ * base MPC5200b Device Tree Source
+ *
+ * Copyright (C) 2010 SecretLab
+ * Grant Likely <grant@secretlab.ca>
+ * John Bonesio <bones@secretlab.ca>
+ *
+ * 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 = "fsl,mpc5200b";
+	compatible = "fsl,mpc5200b";
+	#address-cells = <1>;
+	#size-cells = <1>;
+	interrupt-parent = <&mpc5200_pic>;
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		powerpc: 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: memory {
+		device_type = "memory";
+		reg = <0x00000000 0x04000000>;	// 64MB
+	};
+
+	soc: soc5200@f0000000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "fsl,mpc5200b-immr";
+		ranges = <0 0xf0000000 0x0000c000>;
+		reg = <0xf0000000 0x00000100>;
+		bus-frequency = <0>;		// from bootloader
+		system-frequency = <0>;		// from bootloader
+
+		cdm@200 {
+			compatible = "fsl,mpc5200b-cdm","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,mpc5200b-pic","fsl,mpc5200-pic";
+			reg = <0x500 0x80>;
+		};
+
+		timer@600 {	// General Purpose Timer
+			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
+			reg = <0x600 0x10>;
+			interrupts = <1 9 0>;
+		};
+
+		timer@610 {	// General Purpose Timer
+			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
+			reg = <0x610 0x10>;
+			interrupts = <1 10 0>;
+		};
+
+		timer@620 {	// General Purpose Timer
+			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
+			reg = <0x620 0x10>;
+			interrupts = <1 11 0>;
+		};
+
+		timer@630 {	// General Purpose Timer
+			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
+			reg = <0x630 0x10>;
+			interrupts = <1 12 0>;
+		};
+
+		timer@640 {	// General Purpose Timer
+			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
+			reg = <0x640 0x10>;
+			interrupts = <1 13 0>;
+		};
+
+		timer@650 {	// General Purpose Timer
+			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
+			reg = <0x650 0x10>;
+			interrupts = <1 14 0>;
+		};
+
+		timer@660 {	// General Purpose Timer
+			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
+			reg = <0x660 0x10>;
+			interrupts = <1 15 0>;
+		};
+
+		timer@670 {	// General Purpose Timer
+			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
+			reg = <0x670 0x10>;
+			interrupts = <1 16 0>;
+		};
+
+		rtc@800 {	// Real time clock
+			compatible = "fsl,mpc5200b-rtc","fsl,mpc5200-rtc";
+			reg = <0x800 0x100>;
+			interrupts = <1 5 0 1 6 0>;
+		};
+
+		can@900 {
+			compatible = "fsl,mpc5200b-mscan","fsl,mpc5200-mscan";
+			interrupts = <2 17 0>;
+			reg = <0x900 0x80>;
+		};
+
+		can@980 {
+			compatible = "fsl,mpc5200b-mscan","fsl,mpc5200-mscan";
+			interrupts = <2 18 0>;
+			reg = <0x980 0x80>;
+		};
+
+		gpio_simple: gpio@b00 {
+			compatible = "fsl,mpc5200b-gpio","fsl,mpc5200-gpio";
+			reg = <0xb00 0x40>;
+			interrupts = <1 7 0>;
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+
+		gpio_wkup: gpio@c00 {
+			compatible = "fsl,mpc5200b-gpio-wkup","fsl,mpc5200-gpio-wkup";
+			reg = <0xc00 0x40>;
+			interrupts = <1 8 0 0 3 0>;
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+
+		spi@f00 {
+			compatible = "fsl,mpc5200b-spi","fsl,mpc5200-spi";
+			reg = <0xf00 0x20>;
+			interrupts = <2 13 0 2 14 0>;
+		};
+
+		usb: usb@1000 {
+			compatible = "fsl,mpc5200b-ohci","fsl,mpc5200-ohci","ohci-be";
+			reg = <0x1000 0xff>;
+			interrupts = <2 6 0>;
+		};
+
+		dma-controller@1200 {
+			compatible = "fsl,mpc5200b-bestcomm","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,mpc5200b-xlb","fsl,mpc5200-xlb";
+			reg = <0x1f00 0x100>;
+		};
+
+		psc1: psc@2000 {		// PSC1
+			compatible = "fsl,mpc5200b-psc","fsl,mpc5200-psc";
+			reg = <0x2000 0x100>;
+			interrupts = <2 1 0>;
+		};
+
+		psc2: psc@2200 {		// PSC2
+			compatible = "fsl,mpc5200b-psc","fsl,mpc5200-psc";
+			reg = <0x2200 0x100>;
+			interrupts = <2 2 0>;
+		};
+
+		psc3: psc@2400 {		// PSC3
+			compatible = "fsl,mpc5200b-psc","fsl,mpc5200-psc";
+			reg = <0x2400 0x100>;
+			interrupts = <2 3 0>;
+		};
+
+		psc4: psc@2600 {		// PSC4
+			compatible = "fsl,mpc5200b-psc","fsl,mpc5200-psc";
+			reg = <0x2600 0x100>;
+			interrupts = <2 11 0>;
+		};
+
+		psc5: psc@2800 {		// PSC5
+			compatible = "fsl,mpc5200b-psc","fsl,mpc5200-psc";
+			reg = <0x2800 0x100>;
+			interrupts = <2 12 0>;
+		};
+
+		psc6: psc@2c00 {		// PSC6
+			compatible = "fsl,mpc5200b-psc","fsl,mpc5200-psc";
+			reg = <0x2c00 0x100>;
+			interrupts = <2 4 0>;
+		};
+
+		eth0: ethernet@3000 {
+			compatible = "fsl,mpc5200b-fec","fsl,mpc5200-fec";
+			reg = <0x3000 0x400>;
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			interrupts = <2 5 0>;
+		};
+
+		mdio@3000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "fsl,mpc5200b-mdio","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,mpc5200b-ata","fsl,mpc5200-ata";
+			reg = <0x3a00 0x100>;
+			interrupts = <2 7 0>;
+		};
+
+		i2c@3d00 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "fsl,mpc5200b-i2c","fsl,mpc5200-i2c","fsl-i2c";
+			reg = <0x3d00 0x40>;
+			interrupts = <2 15 0>;
+		};
+
+		i2c@3d40 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "fsl,mpc5200b-i2c","fsl,mpc5200-i2c","fsl-i2c";
+			reg = <0x3d40 0x40>;
+			interrupts = <2 16 0>;
+		};
+
+		sram@8000 {
+			compatible = "fsl,mpc5200b-sram","fsl,mpc5200-sram";
+			reg = <0x8000 0x4000>;
+		};
+	};
+
+	pci: pci@f0000d00 {
+		#interrupt-cells = <1>;
+		#size-cells = <2>;
+		#address-cells = <3>;
+		device_type = "pci";
+		compatible = "fsl,mpc5200b-pci","fsl,mpc5200-pci";
+		reg = <0xf0000d00 0x100>;
+		// interrupt-map-mask = need to add
+		// interrupt-map = need to add
+		clock-frequency = <0>; // From boot loader
+		interrupts = <2 8 0 2 9 0 2 10 0>;
+		bus-range = <0 0>;
+		// ranges = need to add
+	};
+
+	localbus: localbus {
+		compatible = "fsl,mpc5200b-lpb","fsl,mpc5200-lpb","simple-bus";
+		#address-cells = <2>;
+		#size-cells = <1>;
+		ranges = <0 0 0xfc000000 0x2000000>;
+	};
+};
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/boot/dts/mpc8308_p1m.dts linux-libre-2.6.38-gnu1/arch/powerpc/boot/dts/mpc8308_p1m.dts
--- linux-libre-2.6.37-gnu1/arch/powerpc/boot/dts/mpc8308_p1m.dts	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/boot/dts/mpc8308_p1m.dts	2011-03-14 21:20:32.000000000 -0400
@@ -297,6 +297,14 @@
 			interrupt-parent = < &ipic >;
 		};
 
+		dma@2c000 {
+			compatible = "fsl,mpc8308-dma", "fsl,mpc5121-dma";
+			reg = <0x2c000 0x1800>;
+			interrupts = <3 0x8
+					94 0x8>;
+			interrupt-parent = < &ipic >;
+		};
+
 	};
 
 	pci0: pcie@e0009000 {
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/boot/dts/mpc8308rdb.dts linux-libre-2.6.38-gnu1/arch/powerpc/boot/dts/mpc8308rdb.dts
--- linux-libre-2.6.37-gnu1/arch/powerpc/boot/dts/mpc8308rdb.dts	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/boot/dts/mpc8308rdb.dts	2011-03-14 21:20:32.000000000 -0400
@@ -109,7 +109,7 @@
 		#address-cells = <1>;
 		#size-cells = <1>;
 		device_type = "soc";
-		compatible = "fsl,mpc8315-immr", "simple-bus";
+		compatible = "fsl,mpc8308-immr", "simple-bus";
 		ranges = <0 0xe0000000 0x00100000>;
 		reg = <0xe0000000 0x00000200>;
 		bus-frequency = <0>;
@@ -265,6 +265,14 @@
 			interrupt-parent = < &ipic >;
 		};
 
+		dma@2c000 {
+			compatible = "fsl,mpc8308-dma", "fsl,mpc5121-dma";
+			reg = <0x2c000 0x1800>;
+			interrupts = <3 0x8
+					94 0x8>;
+			interrupt-parent = < &ipic >;
+		};
+
 	};
 
 	pci0: pcie@e0009000 {
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/boot/dts/mucmc52.dts linux-libre-2.6.38-gnu1/arch/powerpc/boot/dts/mucmc52.dts
--- linux-libre-2.6.37-gnu1/arch/powerpc/boot/dts/mucmc52.dts	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/boot/dts/mucmc52.dts	2011-03-14 21:20:32.000000000 -0400
@@ -11,172 +11,109 @@
  * option) any later version.
  */
 
-/dts-v1/;
+/include/ "mpc5200b.dtsi"
 
 / {
 	model = "manroland,mucmc52";
 	compatible = "manroland,mucmc52";
-	#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 0x04000000>;	// 64MB
-	};
 
 	soc5200@f0000000 {
-		#address-cells = <1>;
-		#size-cells = <1>;
-		compatible = "fsl,mpc5200b-immr";
-		ranges = <0 0xf0000000 0x0000c000>;
-		reg = <0xf0000000 0x00000100>;
-		bus-frequency = <0>;		// from bootloader
-		system-frequency = <0>;		// from bootloader
-
-		cdm@200 {
-			compatible = "fsl,mpc5200b-cdm","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,mpc5200b-pic","fsl,mpc5200-pic";
-			reg = <0x500 0x80>;
-		};
-
 		gpt0: timer@600 {	// GPT 0 in GPIO mode
-			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
-			reg = <0x600 0x10>;
-			interrupts = <1 9 0>;
 			gpio-controller;
 			#gpio-cells = <2>;
 		};
 
 		gpt1: timer@610 {	// General Purpose Timer in GPIO mode
-			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
-			reg = <0x610 0x10>;
-			interrupts = <1 10 0>;
 			gpio-controller;
 			#gpio-cells = <2>;
 		};
 
 		gpt2: timer@620 {	// General Purpose Timer in GPIO mode
-			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
-			reg = <0x620 0x10>;
-			interrupts = <1 11 0>;
 			gpio-controller;
 			#gpio-cells = <2>;
 		};
 
 		gpt3: timer@630 {	// General Purpose Timer in GPIO mode
-			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
-			reg = <0x630 0x10>;
-			interrupts = <1 12 0>;
 			gpio-controller;
 			#gpio-cells = <2>;
 		};
 
-		gpio_simple: gpio@b00 {
-			compatible = "fsl,mpc5200b-gpio","fsl,mpc5200-gpio";
-			reg = <0xb00 0x40>;
-			interrupts = <1 7 0>;
-			gpio-controller;
-			#gpio-cells = <2>;
+		timer@640 {
+			status = "disabled";
 		};
 
-		gpio_wkup: gpio@c00 {
-			compatible = "fsl,mpc5200b-gpio-wkup","fsl,mpc5200-gpio-wkup";
-			reg = <0xc00 0x40>;
-			interrupts = <1 8 0 0 3 0>;
-			gpio-controller;
-			#gpio-cells = <2>;
+		timer@650 {
+			status = "disabled";
 		};
 
-		dma-controller@1200 {
-			compatible = "fsl,mpc5200b-bestcomm","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>;
+		timer@660 {
+			status = "disabled";
 		};
 
-		xlb@1f00 {
-			compatible = "fsl,mpc5200b-xlb","fsl,mpc5200-xlb";
-			reg = <0x1f00 0x100>;
+		timer@670 {
+			status = "disabled";
 		};
 
-		serial@2000 { /* PSC1 in UART mode */
+		rtc@800 {
+			status = "disabled";
+		};
+
+		can@900 {
+			status = "disabled";
+		};
+
+		can@980 {
+			status = "disabled";
+		};
+
+		spi@f00 {
+			status = "disabled";
+		};
+
+		usb@1000 {
+			status = "disabled";
+		};
+
+		psc@2000 {		// PSC1
 			compatible = "fsl,mpc5200b-psc-uart","fsl,mpc5200-psc-uart";
-			reg = <0x2000 0x100>;
-			interrupts = <2 1 0>;
 		};
 
-		serial@2200 { /* PSC2 in UART mode */
+		psc@2200 {		// PSC2
 			compatible = "fsl,mpc5200b-psc-uart","fsl,mpc5200-psc-uart";
-			reg = <0x2200 0x100>;
-			interrupts = <2 2 0>;
 		};
 
-		serial@2c00 { /* PSC6 in UART mode */
+		psc@2400 {		// PSC3
+			status = "disabled";
+		};
+
+		psc@2600 {		// PSC4
+			status = "disabled";
+		};
+
+		psc@2800 {		// PSC5
+			status = "disabled";
+		};
+
+		psc@2c00 {		// PSC6
 			compatible = "fsl,mpc5200b-psc-uart","fsl,mpc5200-psc-uart";
-			reg = <0x2c00 0x100>;
-			interrupts = <2 4 0>;
 		};
 
 		ethernet@3000 {
-			compatible = "fsl,mpc5200b-fec","fsl,mpc5200-fec";
-			reg = <0x3000 0x400>;
-			local-mac-address = [ 00 00 00 00 00 00 ];
-			interrupts = <2 5 0>;
 			phy-handle = <&phy0>;
 		};
 
 		mdio@3000 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,mpc5200b-mdio","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.
-
 			phy0: ethernet-phy@0 {
 				compatible = "intel,lxt971";
 				reg = <0>;
 			};
 		};
 
-		ata@3a00 {
-			compatible = "fsl,mpc5200b-ata","fsl,mpc5200-ata";
-			reg = <0x3a00 0x100>;
-			interrupts = <2 7 0>;
+		i2c@3d00 {
+			status = "disabled";
 		};
 
 		i2c@3d40 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,mpc5200b-i2c","fsl,mpc5200-i2c","fsl-i2c";
-			reg = <0x3d40 0x40>;
-			interrupts = <2 16 0>;
 			hwmon@2c {
 				compatible = "ad,adm9240";
 				reg = <0x2c>;
@@ -186,20 +123,9 @@
 				reg = <0x51>;
 			};
 		};
-
-		sram@8000 {
-			compatible = "fsl,mpc5200b-sram","fsl,mpc5200-sram";
-			reg = <0x8000 0x4000>;
-		};
 	};
 
 	pci@f0000d00 {
-		#interrupt-cells = <1>;
-		#size-cells = <2>;
-		#address-cells = <3>;
-		device_type = "pci";
-		compatible = "fsl,mpc5200b-pci","fsl,mpc5200-pci";
-		reg = <0xf0000d00 0x100>;
 		interrupt-map-mask = <0xf800 0 0 7>;
 		interrupt-map = <
 				/* IDSEL 0x10 */
@@ -208,20 +134,12 @@
 				0x8000 0 0 3 &mpc5200_pic 0 2 3
 				0x8000 0 0 4 &mpc5200_pic 0 1 3
 				>;
-		clock-frequency = <0>; // From boot loader
-		interrupts = <2 8 0 2 9 0 2 10 0>;
-		bus-range = <0 0>;
 		ranges = <0x42000000 0 0x60000000 0x60000000 0 0x10000000
 			  0x02000000 0 0x90000000 0x90000000 0 0x10000000
 			  0x01000000 0 0x00000000 0xa0000000 0 0x01000000>;
 	};
 
 	localbus {
-		compatible = "fsl,mpc5200b-lpb","fsl,mpc5200-lpb","simple-bus";
-
-		#address-cells = <2>;
-		#size-cells = <1>;
-
 		ranges = <0 0 0xff800000 0x00800000
 			  1 0 0x80000000 0x00800000
 			  3 0 0x80000000 0x00800000>;
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/boot/dts/p1022ds.dts linux-libre-2.6.38-gnu1/arch/powerpc/boot/dts/p1022ds.dts
--- linux-libre-2.6.37-gnu1/arch/powerpc/boot/dts/p1022ds.dts	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/boot/dts/p1022ds.dts	2011-03-14 21:20:32.000000000 -0400
@@ -291,13 +291,13 @@
 			ranges = <0x0 0xc100 0x200>;
 			cell-index = <1>;
 			dma00: dma-channel@0 {
-				compatible = "fsl,eloplus-dma-channel";
+				compatible = "fsl,ssi-dma-channel";
 				reg = <0x0 0x80>;
 				cell-index = <0>;
 				interrupts = <76 2>;
 			};
 			dma01: dma-channel@80 {
-				compatible = "fsl,eloplus-dma-channel";
+				compatible = "fsl,ssi-dma-channel";
 				reg = <0x80 0x80>;
 				cell-index = <1>;
 				interrupts = <77 2>;
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/boot/dts/pcm030.dts linux-libre-2.6.38-gnu1/arch/powerpc/boot/dts/pcm030.dts
--- linux-libre-2.6.37-gnu1/arch/powerpc/boot/dts/pcm030.dts	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/boot/dts/pcm030.dts	2011-03-14 21:20:32.000000000 -0400
@@ -12,246 +12,92 @@
  * option) any later version.
  */
 
-/dts-v1/;
+/include/ "mpc5200b.dtsi"
 
 / {
 	model = "phytec,pcm030";
 	compatible = "phytec,pcm030";
-	#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 0x04000000>;	// 64MB
-	};
 
 	soc5200@f0000000 {
-		#address-cells = <1>;
-		#size-cells = <1>;
-		compatible = "fsl,mpc5200b-immr";
-		ranges = <0 0xf0000000 0x0000c000>;
-		bus-frequency = <0>;		// from bootloader
-		system-frequency = <0>;		// from bootloader
-
-		cdm@200 {
-			compatible = "fsl,mpc5200b-cdm","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,mpc5200b-pic","fsl,mpc5200-pic";
-			reg = <0x500 0x80>;
-		};
-
-		timer@600 {	// General Purpose Timer
-			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
-			reg = <0x600 0x10>;
-			interrupts = <1 9 0>;
+		timer@600 {		// General Purpose Timer
 			fsl,has-wdt;
 		};
 
-		timer@610 {	// General Purpose Timer
-			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
-			reg = <0x610 0x10>;
-			interrupts = <1 10 0>;
-		};
-
 		gpt2: timer@620 {	// General Purpose Timer in GPIO mode
 			compatible = "fsl,mpc5200b-gpt-gpio","fsl,mpc5200-gpt-gpio";
-			reg = <0x620 0x10>;
-			interrupts = <1 11 0>;
 			gpio-controller;
 			#gpio-cells = <2>;
 		};
 
 		gpt3: timer@630 {	// General Purpose Timer in GPIO mode
 			compatible = "fsl,mpc5200b-gpt-gpio","fsl,mpc5200-gpt-gpio";
-			reg = <0x630 0x10>;
-			interrupts = <1 12 0>;
 			gpio-controller;
 			#gpio-cells = <2>;
 		};
 
 		gpt4: timer@640 {	// General Purpose Timer in GPIO mode
 			compatible = "fsl,mpc5200b-gpt-gpio","fsl,mpc5200-gpt-gpio";
-			reg = <0x640 0x10>;
-			interrupts = <1 13 0>;
 			gpio-controller;
 			#gpio-cells = <2>;
 		};
 
 		gpt5: timer@650 {	// General Purpose Timer in GPIO mode
 			compatible = "fsl,mpc5200b-gpt-gpio","fsl,mpc5200-gpt-gpio";
-			reg = <0x650 0x10>;
-			interrupts = <1 14 0>;
 			gpio-controller;
 			#gpio-cells = <2>;
 		};
 
 		gpt6: timer@660 {	// General Purpose Timer in GPIO mode
 			compatible = "fsl,mpc5200b-gpt-gpio","fsl,mpc5200-gpt-gpio";
-			reg = <0x660 0x10>;
-			interrupts = <1 15 0>;
 			gpio-controller;
 			#gpio-cells = <2>;
 		};
 
 		gpt7: timer@670 {	// General Purpose Timer in GPIO mode
 			compatible = "fsl,mpc5200b-gpt-gpio","fsl,mpc5200-gpt-gpio";
-			reg = <0x670 0x10>;
-			interrupts = <1 16 0>;
-			gpio-controller;
-			#gpio-cells = <2>;
-		};
-
-		rtc@800 {	// Real time clock
-			compatible = "fsl,mpc5200b-rtc","fsl,mpc5200-rtc";
-			reg = <0x800 0x100>;
-			interrupts = <1 5 0 1 6 0>;
-		};
-
-		can@900 {
-			compatible = "fsl,mpc5200b-mscan","fsl,mpc5200-mscan";
-			interrupts = <2 17 0>;
-			reg = <0x900 0x80>;
-		};
-
-		can@980 {
-			compatible = "fsl,mpc5200b-mscan","fsl,mpc5200-mscan";
-			interrupts = <2 18 0>;
-			reg = <0x980 0x80>;
-		};
-
-		gpio_simple: gpio@b00 {
-			compatible = "fsl,mpc5200b-gpio","fsl,mpc5200-gpio";
-			reg = <0xb00 0x40>;
-			interrupts = <1 7 0>;
-			gpio-controller;
-			#gpio-cells = <2>;
-		};
-
-		gpio_wkup: gpio@c00 {
-			compatible = "fsl,mpc5200b-gpio-wkup","fsl,mpc5200-gpio-wkup";
-			reg = <0xc00 0x40>;
-			interrupts = <1 8 0 0 3 0>;
 			gpio-controller;
 			#gpio-cells = <2>;
 		};
 
-		spi@f00 {
-			compatible = "fsl,mpc5200b-spi","fsl,mpc5200-spi";
-			reg = <0xf00 0x20>;
-			interrupts = <2 13 0 2 14 0>;
-		};
-
-		usb@1000 {
-			compatible = "fsl,mpc5200b-ohci","fsl,mpc5200-ohci","ohci-be";
-			reg = <0x1000 0xff>;
-			interrupts = <2 6 0>;
-		};
-
-		dma-controller@1200 {
-			compatible = "fsl,mpc5200b-bestcomm","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,mpc5200b-xlb","fsl,mpc5200-xlb";
-			reg = <0x1f00 0x100>;
-		};
-
-		ac97@2000 { /* PSC1 in ac97 mode */
+		psc@2000 { /* PSC1 in ac97 mode */
 			compatible = "mpc5200b-psc-ac97","fsl,mpc5200b-psc-ac97";
 			cell-index = <0>;
-			reg = <0x2000 0x100>;
-			interrupts = <2 1 0>;
 		};
 
 		/* PSC2 port is used by CAN1/2 */
+		psc@2200 {
+			status = "disabled";
+		};
 
-		serial@2400 { /* PSC3 in UART mode */
+		psc@2400 { /* PSC3 in UART mode */
 			compatible = "fsl,mpc5200b-psc-uart","fsl,mpc5200-psc-uart";
-			cell-index = <2>;
-			reg = <0x2400 0x100>;
-			interrupts = <2 3 0>;
 		};
 
 		/* PSC4 is ??? */
+		psc@2600 {
+			status = "disabled";
+		};
 
 		/* PSC5 is ??? */
+		psc@2800 {
+			status = "disabled";
+		};
 
-		serial@2c00 { /* PSC6 in UART mode */
+		psc@2c00 { /* PSC6 in UART mode */
 			compatible = "fsl,mpc5200b-psc-uart","fsl,mpc5200-psc-uart";
-			cell-index = <5>;
-			reg = <0x2c00 0x100>;
-			interrupts = <2 4 0>;
 		};
 
 		ethernet@3000 {
-			compatible = "fsl,mpc5200b-fec","fsl,mpc5200-fec";
-			reg = <0x3000 0x400>;
-			local-mac-address = [ 00 00 00 00 00 00 ];
-			interrupts = <2 5 0>;
 			phy-handle = <&phy0>;
 		};
 
 		mdio@3000 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,mpc5200b-mdio","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.
-
 			phy0: ethernet-phy@0 {
 				reg = <0>;
 			};
 		};
 
-		ata@3a00 {
-			compatible = "fsl,mpc5200b-ata","fsl,mpc5200-ata";
-			reg = <0x3a00 0x100>;
-			interrupts = <2 7 0>;
-		};
-
-		i2c@3d00 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,mpc5200b-i2c","fsl,mpc5200-i2c","fsl-i2c";
-			reg = <0x3d00 0x40>;
-			interrupts = <2 15 0>;
-		};
-
 		i2c@3d40 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,mpc5200b-i2c","fsl,mpc5200-i2c","fsl-i2c";
-			reg = <0x3d40 0x40>;
-			interrupts = <2 16 0>;
 			rtc@51 {
 				compatible = "nxp,pcf8563";
 				reg = <0x51>;
@@ -259,6 +105,7 @@
 			eeprom@52 {
 				compatible = "catalyst,24c32";
 				reg = <0x52>;
+				pagesize = <32>;
 			};
 		};
 
@@ -269,12 +116,6 @@
 	};
 
 	pci@f0000d00 {
-		#interrupt-cells = <1>;
-		#size-cells = <2>;
-		#address-cells = <3>;
-		device_type = "pci";
-		compatible = "fsl,mpc5200b-pci","fsl,mpc5200-pci";
-		reg = <0xf0000d00 0x100>;
 		interrupt-map-mask = <0xf800 0 0 7>;
 		interrupt-map = <0xc000 0 0 1 &mpc5200_pic 0 0 3 // 1st slot
 				 0xc000 0 0 2 &mpc5200_pic 1 1 3
@@ -285,11 +126,12 @@
 				 0xc800 0 0 2 &mpc5200_pic 1 2 3
 				 0xc800 0 0 3 &mpc5200_pic 1 3 3
 				 0xc800 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 0x20000000
 			  0x02000000 0 0xa0000000 0xa0000000 0 0x10000000
 			  0x01000000 0 0x00000000 0xb0000000 0 0x01000000>;
 	};
+
+	localbus {
+		status = "disabled";
+	};
 };
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/boot/dts/pcm032.dts linux-libre-2.6.38-gnu1/arch/powerpc/boot/dts/pcm032.dts
--- linux-libre-2.6.37-gnu1/arch/powerpc/boot/dts/pcm032.dts	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/boot/dts/pcm032.dts	2011-03-14 21:20:32.000000000 -0400
@@ -12,99 +12,37 @@
  * option) any later version.
  */
 
-/dts-v1/;
+/include/ "mpc5200b.dtsi"
 
 / {
 	model = "phytec,pcm032";
 	compatible = "phytec,pcm032";
-	#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,mpc5200b-immr";
-		ranges = <0 0xf0000000 0x0000c000>;
-		bus-frequency = <0>;		// from bootloader
-		system-frequency = <0>;		// from bootloader
-
-		cdm@200 {
-			compatible = "fsl,mpc5200b-cdm","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,mpc5200b-pic","fsl,mpc5200-pic";
-			reg = <0x500 0x80>;
-		};
-
-		timer@600 {	// General Purpose Timer
-			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
-			reg = <0x600 0x10>;
-			interrupts = <1 9 0>;
+		timer@600 {		// General Purpose Timer
 			fsl,has-wdt;
 		};
 
-		timer@610 {	// General Purpose Timer
-			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
-			reg = <0x610 0x10>;
-			interrupts = <1 10 0>;
-		};
-
 		gpt2: timer@620 {	// General Purpose Timer in GPIO mode
-			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
-			reg = <0x620 0x10>;
-			interrupts = <1 11 0>;
 			gpio-controller;
 			#gpio-cells = <2>;
 		};
 
 		gpt3: timer@630 {	// General Purpose Timer in GPIO mode
-			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
-			reg = <0x630 0x10>;
-			interrupts = <1 12 0>;
 			gpio-controller;
 			#gpio-cells = <2>;
 		};
 
 		gpt4: timer@640 {	// General Purpose Timer in GPIO mode
-			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
-			reg = <0x640 0x10>;
-			interrupts = <1 13 0>;
 			gpio-controller;
 			#gpio-cells = <2>;
 		};
 
 		gpt5: timer@650 {	// General Purpose Timer in GPIO mode
-			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
-			reg = <0x650 0x10>;
-			interrupts = <1 14 0>;
 			gpio-controller;
 			#gpio-cells = <2>;
 		};
@@ -118,163 +56,62 @@
 		};
 
 		gpt7: timer@670 {	// General Purpose Timer in GPIO mode
-			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
-			reg = <0x670 0x10>;
-			interrupts = <1 16 0>;
-			gpio-controller;
-			#gpio-cells = <2>;
-		};
-
-		rtc@800 {	// Real time clock
-			compatible = "fsl,mpc5200b-rtc","fsl,mpc5200-rtc";
-			reg = <0x800 0x100>;
-			interrupts = <1 5 0 1 6 0>;
-		};
-
-		can@900 {
-			compatible = "fsl,mpc5200b-mscan","fsl,mpc5200-mscan";
-			interrupts = <2 17 0>;
-			reg = <0x900 0x80>;
-		};
-
-		can@980 {
-			compatible = "fsl,mpc5200b-mscan","fsl,mpc5200-mscan";
-			interrupts = <2 18 0>;
-			reg = <0x980 0x80>;
-		};
-
-		gpio_simple: gpio@b00 {
-			compatible = "fsl,mpc5200b-gpio","fsl,mpc5200-gpio";
-			reg = <0xb00 0x40>;
-			interrupts = <1 7 0>;
 			gpio-controller;
 			#gpio-cells = <2>;
 		};
 
-		gpio_wkup: gpio@c00 {
-			compatible = "fsl,mpc5200b-gpio-wkup","fsl,mpc5200-gpio-wkup";
-			reg = <0xc00 0x40>;
-			interrupts = <1 8 0 0 3 0>;
-			gpio-controller;
-			#gpio-cells = <2>;
-		};
-
-		spi@f00 {
-			compatible = "fsl,mpc5200b-spi","fsl,mpc5200-spi";
-			reg = <0xf00 0x20>;
-			interrupts = <2 13 0 2 14 0>;
-		};
-
-		usb@1000 {
-			compatible = "fsl,mpc5200b-ohci","fsl,mpc5200-ohci","ohci-be";
-			reg = <0x1000 0xff>;
-			interrupts = <2 6 0>;
-		};
-
-		dma-controller@1200 {
-			compatible = "fsl,mpc5200b-bestcomm","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,mpc5200b-xlb","fsl,mpc5200-xlb";
-			reg = <0x1f00 0x100>;
-		};
-
-		ac97@2000 {	/* PSC1 is ac97 */
+		psc@2000 {	/* PSC1 is ac97 */
 			compatible = "fsl,mpc5200b-psc-ac97","fsl,mpc5200-psc-ac97";
 			cell-index = <0>;
-			reg = <0x2000 0x100>;
-			interrupts = <2 1 0>;
 		};
 
 		/* PSC2 port is used by CAN1/2 */
+		psc@2200 {
+			status = "disabled";
+		};
 
-		serial@2400 { /* PSC3 in UART mode */
+		psc@2400 { /* PSC3 in UART mode */
 			compatible = "fsl,mpc5200b-psc-uart","fsl,mpc5200-psc-uart";
-			cell-index = <2>;
-			reg = <0x2400 0x100>;
-			interrupts = <2 3 0>;
 		};
 
 		/* PSC4 is ??? */
+		psc@2600 {
+			status = "disabled";
+		};
 
 		/* PSC5 is ??? */
+		psc@2800 {
+			status = "disabled";
+		};
 
-		serial@2c00 { /* PSC6 in UART mode */
+		psc@2c00 { /* PSC6 in UART mode */
 			compatible = "fsl,mpc5200b-psc-uart","fsl,mpc5200-psc-uart";
-			cell-index = <5>;
-			reg = <0x2c00 0x100>;
-			interrupts = <2 4 0>;
 		};
 
 		ethernet@3000 {
-			compatible = "fsl,mpc5200b-fec","fsl,mpc5200-fec";
-			reg = <0x3000 0x400>;
-			local-mac-address = [ 00 00 00 00 00 00 ];
-			interrupts = <2 5 0>;
 			phy-handle = <&phy0>;
 		};
 
 		mdio@3000 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,mpc5200b-mdio","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.
-
 			phy0: ethernet-phy@0 {
 				reg = <0>;
 			};
 		};
 
-		ata@3a00 {
-			compatible = "fsl,mpc5200b-ata","fsl,mpc5200-ata";
-			reg = <0x3a00 0x100>;
-			interrupts = <2 7 0>;
-		};
-
-		i2c@3d00 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,mpc5200b-i2c","fsl,mpc5200-i2c","fsl-i2c";
-			reg = <0x3d00 0x40>;
-			interrupts = <2 15 0>;
-		};
-
 		i2c@3d40 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,mpc5200b-i2c","fsl,mpc5200-i2c","fsl-i2c";
-			reg = <0x3d40 0x40>;
-			interrupts = <2 16 0>;
 			rtc@51 {
 				compatible = "nxp,pcf8563";
 				reg = <0x51>;
 			};
 			eeprom@52 {
-				compatible = "at24,24c32";
+				compatible = "catalyst,24c32";
 				reg = <0x52>;
+				pagesize = <32>;
 			};
 		};
-
-		sram@8000 {
-			compatible = "fsl,mpc5200b-sram","fsl,mpc5200-sram";
-			reg = <0x8000 0x4000>;
-		};
 	};
 
 	pci@f0000d00 {
-		#interrupt-cells = <1>;
-		#size-cells = <2>;
-		#address-cells = <3>;
-		device_type = "pci";
-		compatible = "fsl,mpc5200b-pci","fsl,mpc5200-pci";
-		reg = <0xf0000d00 0x100>;
 		interrupt-map-mask = <0xf800 0 0 7>;
 		interrupt-map = <0xc000 0 0 1 &mpc5200_pic 0 0 3 // 1st slot
 				 0xc000 0 0 2 &mpc5200_pic 1 1 3
@@ -285,20 +122,12 @@
 				 0xc800 0 0 2 &mpc5200_pic 1 2 3
 				 0xc800 0 0 3 &mpc5200_pic 1 3 3
 				 0xc800 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 0x20000000
 			  0x02000000 0 0xa0000000 0xa0000000 0 0x10000000
 			  0x01000000 0 0x00000000 0xb0000000 0 0x01000000>;
 	};
 
 	localbus {
-		compatible = "fsl,mpc5200b-lpb","fsl,mpc5200-lpb","simple-bus";
-
-		#address-cells = <2>;
-		#size-cells = <1>;
-
 		ranges = <0 0 0xfe000000 0x02000000
 			  1 0 0xfc000000 0x02000000
 			  2 0 0xfbe00000 0x00200000
@@ -351,40 +180,39 @@
 			bank-width = <2>;
 		};
 
-                /*
+		/*
 		 * example snippets for FPGA
 		 *
 		 * fpga@3,0 {
-		 *         compatible = "fpga_driver";
-		 *         reg = <3 0 0x02000000>;
-		 *         bank-width = <4>;
+		 *	 compatible = "fpga_driver";
+		 *	 reg = <3 0 0x02000000>;
+		 *	 bank-width = <4>;
 		 * };
 		 *
 		 * fpga@4,0 {
-		 *         compatible = "fpga_driver";
-		 *         reg = <4 0 0x02000000>;
-		 *         bank-width = <4>;
+		 *	 compatible = "fpga_driver";
+		 *	 reg = <4 0 0x02000000>;
+		 *	 bank-width = <4>;
 		 * };
-                 */
+		 */
 
-                /*
+		/*
 		 * example snippets for free chipselects
-                 *
+		 *
 		 * device@5,0 {
-		 *         compatible = "custom_driver";
-		 *         reg = <5 0 0x02000000>;
+		 *	 compatible = "custom_driver";
+		 *	 reg = <5 0 0x02000000>;
 		 * };
-                 *
+		 *
 		 * device@6,0 {
-		 *         compatible = "custom_driver";
-		 *         reg = <6 0 0x02000000>;
+		 *	 compatible = "custom_driver";
+		 *	 reg = <6 0 0x02000000>;
 		 * };
-                 *
+		 *
 		 * device@7,0 {
-		 *         compatible = "custom_driver";
-		 *         reg = <7 0 0x02000000>;
+		 *	 compatible = "custom_driver";
+		 *	 reg = <7 0 0x02000000>;
 		 * };
-                 */
+		 */
 	};
 };
-
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/boot/dts/uc101.dts linux-libre-2.6.38-gnu1/arch/powerpc/boot/dts/uc101.dts
--- linux-libre-2.6.37-gnu1/arch/powerpc/boot/dts/uc101.dts	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/boot/dts/uc101.dts	2011-03-14 21:20:32.000000000 -0400
@@ -11,79 +11,24 @@
  * option) any later version.
  */
 
-/dts-v1/;
+/include/ "mpc5200b.dtsi"
 
 / {
 	model = "manroland,uc101";
 	compatible = "manroland,uc101";
-	#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 0x04000000>;	// 64MB
-	};
 
 	soc5200@f0000000 {
-		#address-cells = <1>;
-		#size-cells = <1>;
-		compatible = "fsl,mpc5200b-immr";
-		ranges = <0 0xf0000000 0x0000c000>;
-		reg = <0xf0000000 0x00000100>;
-		bus-frequency = <0>;		// from bootloader
-		system-frequency = <0>;		// from bootloader
-
-		cdm@200 {
-			compatible = "fsl,mpc5200b-cdm","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,mpc5200b-pic","fsl,mpc5200-pic";
-			reg = <0x500 0x80>;
-		};
-
 		gpt0: timer@600 {	// General Purpose Timer in GPIO mode
-			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
-			reg = <0x600 0x10>;
-			interrupts = <1 9 0>;
 			gpio-controller;
 			#gpio-cells = <2>;
 		};
 
 		gpt1: timer@610 {	// General Purpose Timer in GPIO mode
-			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
-			reg = <0x610 0x10>;
-			interrupts = <1 10 0>;
 			gpio-controller;
 			#gpio-cells = <2>;
 		};
 
 		gpt2: timer@620 {	// General Purpose Timer in GPIO mode
-			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
-			reg = <0x620 0x10>;
-			interrupts = <1 11 0>;
 			gpio-controller;
 			#gpio-cells = <2>;
 		};
@@ -97,118 +42,85 @@
 		};
 
 		gpt4: timer@640 {	// General Purpose Timer in GPIO mode
-			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
-			reg = <0x640 0x10>;
-			interrupts = <1 13 0>;
 			gpio-controller;
 			#gpio-cells = <2>;
 		};
 
 		gpt5: timer@650 {	// General Purpose Timer in GPIO mode
-			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
-			reg = <0x650 0x10>;
-			interrupts = <1 14 0>;
 			gpio-controller;
 			#gpio-cells = <2>;
 		};
 
 		gpt6: timer@660 {	// General Purpose Timer in GPIO mode
-			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
-			reg = <0x660 0x10>;
-			interrupts = <1 15 0>;
 			gpio-controller;
 			#gpio-cells = <2>;
 		};
 
 		gpt7: timer@670 {	// General Purpose Timer in GPIO mode
-			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
-			reg = <0x670 0x10>;
-			interrupts = <1 16 0>;
 			gpio-controller;
 			#gpio-cells = <2>;
 		};
 
-		gpio_simple: gpio@b00 {
-			compatible = "fsl,mpc5200b-gpio","fsl,mpc5200-gpio";
-			reg = <0xb00 0x40>;
-			interrupts = <1 7 0>;
-			gpio-controller;
-			#gpio-cells = <2>;
+		rtc@800 {
+			status = "disabled";
 		};
 
-		gpio_wkup: gpio@c00 {
-			compatible = "fsl,mpc5200b-gpio-wkup","fsl,mpc5200-gpio-wkup";
-			reg = <0xc00 0x40>;
-			interrupts = <1 8 0 0 3 0>;
-			gpio-controller;
-			#gpio-cells = <2>;
+		can@900 {
+			status = "disabled";
 		};
 
-		dma-controller@1200 {
-			compatible = "fsl,mpc5200b-bestcomm","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>;
+		can@980 {
+			status = "disabled";
 		};
 
-		xlb@1f00 {
-			compatible = "fsl,mpc5200b-xlb","fsl,mpc5200-xlb";
-			reg = <0x1f00 0x100>;
+		spi@f00 {
+			status = "disabled";
 		};
 
-		serial@2000 { /* PSC1 in UART mode */
+		usb@1000 {
+			status = "disabled";
+		};
+
+		psc@2000 {	// PSC1
 			compatible = "fsl,mpc5200b-psc-uart","fsl,mpc5200-psc-uart";
-			reg = <0x2000 0x100>;
-			interrupts = <2 1 0>;
 		};
 
-		serial@2200 { /* PSC2 in UART mode */
+		psc@2200 {	// PSC2
 			compatible = "fsl,mpc5200b-psc-uart","fsl,mpc5200-psc-uart";
-			reg = <0x2200 0x100>;
-			interrupts = <2 2 0>;
 		};
 
-		serial@2c00 {		/* PSC6 in UART mode */
+		psc@2400 {	// PSC3
+			status = "disabled";
+		};
+
+		psc@2600 {	// PSC4
+			status = "disabled";
+		};
+
+		psc@2800 {	// PSC5
+			status = "disabled";
+		};
+
+		psc@2c00 {	// PSC6
 			compatible = "fsl,mpc5200b-psc-uart","fsl,mpc5200-psc-uart";
-			reg = <0x2c00 0x100>;
-			interrupts = <2 4 0>;
 		};
 
 		ethernet@3000 {
-			compatible = "fsl,mpc5200b-fec","fsl,mpc5200-fec";
-			reg = <0x3000 0x400>;
-			local-mac-address = [ 00 00 00 00 00 00 ];
-			interrupts = <2 5 0>;
 			phy-handle = <&phy0>;
 		};
 
 		mdio@3000 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,mpc5200b-mdio","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.
-
 			phy0: ethernet-phy@0 {
 				compatible = "intel,lxt971";
 				reg = <0>;
 			};
 		};
 
-		ata@3a00 {
-			compatible = "fsl,mpc5200b-ata","fsl,mpc5200-ata";
-			reg = <0x3a00 0x100>;
-			interrupts = <2 7 0>;
+		i2c@3d00 {
+			status = "disabled";
 		};
 
 		i2c@3d40 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,mpc5200b-i2c","fsl,mpc5200-i2c","fsl-i2c";
-			reg = <0x3d40 0x40>;
-			interrupts = <2 16 0>;
 			fsl,preserve-clocking;
 			clock-frequency = <400000>;
 
@@ -221,19 +133,13 @@
 				reg = <0x51>;
 			};
 		};
+	};
 
-		sram@8000 {
-			compatible = "fsl,mpc5200b-sram","fsl,mpc5200-sram";
-			reg = <0x8000 0x4000>;
-		};
+	pci@f0000d00 {
+		status = "disabled";
 	};
 
 	localbus {
-		compatible = "fsl,mpc5200b-lpb","fsl,mpc5200-lpb","simple-bus";
-
-		#address-cells = <2>;
-		#size-cells = <1>;
-
 		ranges = <0 0 0xff800000 0x00800000
 			  1 0 0x80000000 0x00800000
 			  3 0 0x80000000 0x00800000>;
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/boot/Makefile linux-libre-2.6.38-gnu1/arch/powerpc/boot/Makefile
--- linux-libre-2.6.37-gnu1/arch/powerpc/boot/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/boot/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -35,7 +35,7 @@ endif
 
 BOOTCFLAGS	+= -I$(obj) -I$(srctree)/$(obj)
 
-DTS_FLAGS	?= -p 1024
+DTC_FLAGS	?= -p 1024
 
 $(obj)/4xx.o: BOOTCFLAGS += -mcpu=405
 $(obj)/ebony.o: BOOTCFLAGS += -mcpu=405
@@ -332,10 +332,8 @@ $(obj)/treeImage.%: vmlinux $(obj)/%.dtb
 	$(call if_changed,wrap,treeboot-$*,,$(obj)/$*.dtb)
 
 # Rule to build device tree blobs
-DTC = $(objtree)/scripts/dtc/dtc
-
-$(obj)/%.dtb: $(dtstree)/%.dts
-	$(DTC) -O dtb -o $(obj)/$*.dtb -b 0 $(DTS_FLAGS) $(dtstree)/$*.dts
+$(obj)/%.dtb: $(src)/dts/%.dts
+	$(call cmd,dtc)
 
 # If there isn't a platform selected then just strip the vmlinux.
 ifeq (,$(image-y))
@@ -370,7 +368,7 @@ INSTALL := install
 extra-installed		:= $(patsubst $(obj)/%, $(DESTDIR)$(WRAPPER_OBJDIR)/%, $(extra-y))
 hostprogs-installed	:= $(patsubst %, $(DESTDIR)$(WRAPPER_BINDIR)/%, $(hostprogs-y))
 wrapper-installed	:= $(DESTDIR)$(WRAPPER_BINDIR)/wrapper
-dts-installed		:= $(patsubst $(obj)/dts/%, $(DESTDIR)$(WRAPPER_DTSDIR)/%, $(wildcard $(obj)/dts/*.dts))
+dts-installed		:= $(patsubst $(dtstree)/%, $(DESTDIR)$(WRAPPER_DTSDIR)/%, $(wildcard $(dtstree)/*.dts))
 
 all-installed		:= $(extra-installed) $(hostprogs-installed) $(wrapper-installed) $(dts-installed)
 
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/configs/40x/acadia_defconfig linux-libre-2.6.38-gnu1/arch/powerpc/configs/40x/acadia_defconfig
--- linux-libre-2.6.37-gnu1/arch/powerpc/configs/40x/acadia_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/configs/40x/acadia_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@ CONFIG_POSIX_MQUEUE=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 CONFIG_KALLSYMS_ALL=y
 CONFIG_KALLSYMS_EXTRA_PASS=y
 CONFIG_MODULES=y
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/configs/40x/ep405_defconfig linux-libre-2.6.38-gnu1/arch/powerpc/configs/40x/ep405_defconfig
--- linux-libre-2.6.37-gnu1/arch/powerpc/configs/40x/ep405_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/configs/40x/ep405_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@ CONFIG_POSIX_MQUEUE=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 CONFIG_KALLSYMS_ALL=y
 CONFIG_KALLSYMS_EXTRA_PASS=y
 CONFIG_MODULES=y
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/configs/40x/hcu4_defconfig linux-libre-2.6.38-gnu1/arch/powerpc/configs/40x/hcu4_defconfig
--- linux-libre-2.6.37-gnu1/arch/powerpc/configs/40x/hcu4_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/configs/40x/hcu4_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@ CONFIG_POSIX_MQUEUE=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 CONFIG_KALLSYMS_ALL=y
 CONFIG_KALLSYMS_EXTRA_PASS=y
 CONFIG_MODULES=y
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/configs/40x/kilauea_defconfig linux-libre-2.6.38-gnu1/arch/powerpc/configs/40x/kilauea_defconfig
--- linux-libre-2.6.37-gnu1/arch/powerpc/configs/40x/kilauea_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/configs/40x/kilauea_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -5,13 +5,15 @@ CONFIG_POSIX_MQUEUE=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+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_KILAUEA=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
 # CONFIG_WALNUT is not set
 CONFIG_SPARSE_IRQ=y
 CONFIG_PCI=y
@@ -42,6 +44,9 @@ CONFIG_MTD_PHYSMAP_OF=y
 CONFIG_MTD_NAND=y
 CONFIG_MTD_NAND_NDFC=y
 CONFIG_PROC_DEVICETREE=y
+CONFIG_PM=y
+CONFIG_SUSPEND=y
+CONFIG_PPC4xx_CPM=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=35000
 # CONFIG_MISC_DEVICES is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/configs/40x/makalu_defconfig linux-libre-2.6.38-gnu1/arch/powerpc/configs/40x/makalu_defconfig
--- linux-libre-2.6.37-gnu1/arch/powerpc/configs/40x/makalu_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/configs/40x/makalu_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@ CONFIG_POSIX_MQUEUE=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 CONFIG_KALLSYMS_ALL=y
 CONFIG_KALLSYMS_EXTRA_PASS=y
 CONFIG_MODULES=y
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/configs/40x/walnut_defconfig linux-libre-2.6.38-gnu1/arch/powerpc/configs/40x/walnut_defconfig
--- linux-libre-2.6.37-gnu1/arch/powerpc/configs/40x/walnut_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/configs/40x/walnut_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@ CONFIG_POSIX_MQUEUE=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 CONFIG_KALLSYMS_ALL=y
 CONFIG_KALLSYMS_EXTRA_PASS=y
 CONFIG_MODULES=y
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/configs/44x/arches_defconfig linux-libre-2.6.38-gnu1/arch/powerpc/configs/44x/arches_defconfig
--- linux-libre-2.6.37-gnu1/arch/powerpc/configs/44x/arches_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/configs/44x/arches_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@ CONFIG_POSIX_MQUEUE=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_BLK_DEV_BSG is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/configs/44x/bamboo_defconfig linux-libre-2.6.38-gnu1/arch/powerpc/configs/44x/bamboo_defconfig
--- linux-libre-2.6.37-gnu1/arch/powerpc/configs/44x/bamboo_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/configs/44x/bamboo_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@ CONFIG_POSIX_MQUEUE=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_BLK_DEV_BSG is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/configs/44x/bluestone_defconfig linux-libre-2.6.38-gnu1/arch/powerpc/configs/44x/bluestone_defconfig
--- linux-libre-2.6.37-gnu1/arch/powerpc/configs/44x/bluestone_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/configs/44x/bluestone_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -4,7 +4,7 @@ CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_VM_EVENT_COUNTERS is not set
 # CONFIG_PCI_QUIRKS is not set
 # CONFIG_COMPAT_BRK is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/configs/44x/canyonlands_defconfig linux-libre-2.6.38-gnu1/arch/powerpc/configs/44x/canyonlands_defconfig
--- linux-libre-2.6.37-gnu1/arch/powerpc/configs/44x/canyonlands_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/configs/44x/canyonlands_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@ CONFIG_POSIX_MQUEUE=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_BLK_DEV_BSG is not set
@@ -42,6 +42,9 @@ CONFIG_MTD_PHYSMAP_OF=y
 CONFIG_MTD_NAND=y
 CONFIG_MTD_NAND_NDFC=y
 CONFIG_PROC_DEVICETREE=y
+CONFIG_PM=y
+CONFIG_SUSPEND=y
+CONFIG_PPC4xx_CPM=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=35000
 # CONFIG_MISC_DEVICES is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/configs/44x/ebony_defconfig linux-libre-2.6.38-gnu1/arch/powerpc/configs/44x/ebony_defconfig
--- linux-libre-2.6.37-gnu1/arch/powerpc/configs/44x/ebony_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/configs/44x/ebony_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@ CONFIG_POSIX_MQUEUE=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 CONFIG_KALLSYMS_ALL=y
 CONFIG_KALLSYMS_EXTRA_PASS=y
 CONFIG_MODULES=y
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/configs/44x/eiger_defconfig linux-libre-2.6.38-gnu1/arch/powerpc/configs/44x/eiger_defconfig
--- linux-libre-2.6.37-gnu1/arch/powerpc/configs/44x/eiger_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/configs/44x/eiger_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@ CONFIG_POSIX_MQUEUE=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_BLK_DEV_BSG is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/configs/44x/icon_defconfig linux-libre-2.6.38-gnu1/arch/powerpc/configs/44x/icon_defconfig
--- linux-libre-2.6.37-gnu1/arch/powerpc/configs/44x/icon_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/configs/44x/icon_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -6,7 +6,7 @@ CONFIG_LOG_BUF_SHIFT=14
 CONFIG_SYSFS_DEPRECATED_V2=y
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_BLK_DEV_BSG is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/configs/44x/iss476-smp_defconfig linux-libre-2.6.38-gnu1/arch/powerpc/configs/44x/iss476-smp_defconfig
--- linux-libre-2.6.37-gnu1/arch/powerpc/configs/44x/iss476-smp_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/configs/44x/iss476-smp_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -7,7 +7,7 @@ CONFIG_LOG_BUF_SHIFT=14
 CONFIG_SYSFS_DEPRECATED_V2=y
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 CONFIG_KALLSYMS_ALL=y
 CONFIG_KALLSYMS_EXTRA_PASS=y
 CONFIG_PROFILING=y
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/configs/44x/katmai_defconfig linux-libre-2.6.38-gnu1/arch/powerpc/configs/44x/katmai_defconfig
--- linux-libre-2.6.37-gnu1/arch/powerpc/configs/44x/katmai_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/configs/44x/katmai_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@ CONFIG_POSIX_MQUEUE=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_BLK_DEV_BSG is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/configs/44x/rainier_defconfig linux-libre-2.6.38-gnu1/arch/powerpc/configs/44x/rainier_defconfig
--- linux-libre-2.6.37-gnu1/arch/powerpc/configs/44x/rainier_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/configs/44x/rainier_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@ CONFIG_POSIX_MQUEUE=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_BLK_DEV_BSG is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/configs/44x/redwood_defconfig linux-libre-2.6.38-gnu1/arch/powerpc/configs/44x/redwood_defconfig
--- linux-libre-2.6.37-gnu1/arch/powerpc/configs/44x/redwood_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/configs/44x/redwood_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@ CONFIG_POSIX_MQUEUE=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_BLK_DEV_BSG is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/configs/44x/sam440ep_defconfig linux-libre-2.6.38-gnu1/arch/powerpc/configs/44x/sam440ep_defconfig
--- linux-libre-2.6.37-gnu1/arch/powerpc/configs/44x/sam440ep_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/configs/44x/sam440ep_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -6,7 +6,7 @@ CONFIG_IKCONFIG=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_BLK_DEV_BSG is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/configs/44x/sequoia_defconfig linux-libre-2.6.38-gnu1/arch/powerpc/configs/44x/sequoia_defconfig
--- linux-libre-2.6.37-gnu1/arch/powerpc/configs/44x/sequoia_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/configs/44x/sequoia_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@ CONFIG_POSIX_MQUEUE=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_BLK_DEV_BSG is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/configs/44x/taishan_defconfig linux-libre-2.6.38-gnu1/arch/powerpc/configs/44x/taishan_defconfig
--- linux-libre-2.6.37-gnu1/arch/powerpc/configs/44x/taishan_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/configs/44x/taishan_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@ CONFIG_POSIX_MQUEUE=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_BLK_DEV_BSG is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/configs/44x/warp_defconfig linux-libre-2.6.38-gnu1/arch/powerpc/configs/44x/warp_defconfig
--- linux-libre-2.6.37-gnu1/arch/powerpc/configs/44x/warp_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/configs/44x/warp_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -8,7 +8,7 @@ CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_BLK_DEV_BSG is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/configs/52xx/cm5200_defconfig linux-libre-2.6.38-gnu1/arch/powerpc/configs/52xx/cm5200_defconfig
--- linux-libre-2.6.37-gnu1/arch/powerpc/configs/52xx/cm5200_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/configs/52xx/cm5200_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -3,7 +3,7 @@ CONFIG_SYSVIPC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_SYSCTL_SYSCALL is not set
 # CONFIG_KALLSYMS is not set
 # CONFIG_EPOLL is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/configs/52xx/lite5200b_defconfig linux-libre-2.6.38-gnu1/arch/powerpc/configs/52xx/lite5200b_defconfig
--- linux-libre-2.6.37-gnu1/arch/powerpc/configs/52xx/lite5200b_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/configs/52xx/lite5200b_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -3,7 +3,7 @@ CONFIG_SYSVIPC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_SYSCTL_SYSCALL is not set
 # CONFIG_KALLSYMS is not set
 # CONFIG_EPOLL is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/configs/52xx/motionpro_defconfig linux-libre-2.6.38-gnu1/arch/powerpc/configs/52xx/motionpro_defconfig
--- linux-libre-2.6.37-gnu1/arch/powerpc/configs/52xx/motionpro_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/configs/52xx/motionpro_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -3,7 +3,7 @@ CONFIG_SYSVIPC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_SYSCTL_SYSCALL is not set
 # CONFIG_KALLSYMS is not set
 # CONFIG_EPOLL is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/configs/52xx/pcm030_defconfig linux-libre-2.6.38-gnu1/arch/powerpc/configs/52xx/pcm030_defconfig
--- linux-libre-2.6.37-gnu1/arch/powerpc/configs/52xx/pcm030_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/configs/52xx/pcm030_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -8,7 +8,7 @@ CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_SYSCTL_SYSCALL is not set
 # CONFIG_VM_EVENT_COUNTERS is not set
 CONFIG_SLAB=y
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/configs/52xx/tqm5200_defconfig linux-libre-2.6.38-gnu1/arch/powerpc/configs/52xx/tqm5200_defconfig
--- linux-libre-2.6.37-gnu1/arch/powerpc/configs/52xx/tqm5200_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/configs/52xx/tqm5200_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -3,7 +3,7 @@ CONFIG_SYSVIPC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_SYSCTL_SYSCALL is not set
 # CONFIG_KALLSYMS is not set
 # CONFIG_EPOLL is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/configs/83xx/asp8347_defconfig linux-libre-2.6.38-gnu1/arch/powerpc/configs/83xx/asp8347_defconfig
--- linux-libre-2.6.37-gnu1/arch/powerpc/configs/83xx/asp8347_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/configs/83xx/asp8347_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -4,7 +4,7 @@ CONFIG_SYSVIPC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_KALLSYMS is not set
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/configs/83xx/kmeter1_defconfig linux-libre-2.6.38-gnu1/arch/powerpc/configs/83xx/kmeter1_defconfig
--- linux-libre-2.6.37-gnu1/arch/powerpc/configs/83xx/kmeter1_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/configs/83xx/kmeter1_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -3,7 +3,7 @@ CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_HOTPLUG is not set
 CONFIG_SLAB=y
 CONFIG_MODULES=y
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/configs/83xx/mpc8313_rdb_defconfig linux-libre-2.6.38-gnu1/arch/powerpc/configs/83xx/mpc8313_rdb_defconfig
--- linux-libre-2.6.37-gnu1/arch/powerpc/configs/83xx/mpc8313_rdb_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/configs/83xx/mpc8313_rdb_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -3,7 +3,7 @@ CONFIG_SYSVIPC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_KALLSYMS is not set
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/configs/83xx/mpc8315_rdb_defconfig linux-libre-2.6.38-gnu1/arch/powerpc/configs/83xx/mpc8315_rdb_defconfig
--- linux-libre-2.6.37-gnu1/arch/powerpc/configs/83xx/mpc8315_rdb_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/configs/83xx/mpc8315_rdb_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -3,7 +3,7 @@ CONFIG_SYSVIPC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_KALLSYMS is not set
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/configs/83xx/mpc832x_mds_defconfig linux-libre-2.6.38-gnu1/arch/powerpc/configs/83xx/mpc832x_mds_defconfig
--- linux-libre-2.6.37-gnu1/arch/powerpc/configs/83xx/mpc832x_mds_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/configs/83xx/mpc832x_mds_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -3,7 +3,7 @@ CONFIG_SYSVIPC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_KALLSYMS is not set
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/configs/83xx/mpc832x_rdb_defconfig linux-libre-2.6.38-gnu1/arch/powerpc/configs/83xx/mpc832x_rdb_defconfig
--- linux-libre-2.6.37-gnu1/arch/powerpc/configs/83xx/mpc832x_rdb_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/configs/83xx/mpc832x_rdb_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -3,7 +3,7 @@ CONFIG_SYSVIPC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_KALLSYMS is not set
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/configs/83xx/mpc834x_itx_defconfig linux-libre-2.6.38-gnu1/arch/powerpc/configs/83xx/mpc834x_itx_defconfig
--- linux-libre-2.6.37-gnu1/arch/powerpc/configs/83xx/mpc834x_itx_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/configs/83xx/mpc834x_itx_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -3,7 +3,7 @@ CONFIG_SYSVIPC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_KALLSYMS is not set
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/configs/83xx/mpc834x_itxgp_defconfig linux-libre-2.6.38-gnu1/arch/powerpc/configs/83xx/mpc834x_itxgp_defconfig
--- linux-libre-2.6.37-gnu1/arch/powerpc/configs/83xx/mpc834x_itxgp_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/configs/83xx/mpc834x_itxgp_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -3,7 +3,7 @@ CONFIG_SYSVIPC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_KALLSYMS is not set
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/configs/83xx/mpc834x_mds_defconfig linux-libre-2.6.38-gnu1/arch/powerpc/configs/83xx/mpc834x_mds_defconfig
--- linux-libre-2.6.37-gnu1/arch/powerpc/configs/83xx/mpc834x_mds_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/configs/83xx/mpc834x_mds_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -3,7 +3,7 @@ CONFIG_SYSVIPC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_KALLSYMS is not set
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/configs/83xx/mpc836x_mds_defconfig linux-libre-2.6.38-gnu1/arch/powerpc/configs/83xx/mpc836x_mds_defconfig
--- linux-libre-2.6.37-gnu1/arch/powerpc/configs/83xx/mpc836x_mds_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/configs/83xx/mpc836x_mds_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -3,7 +3,7 @@ CONFIG_SYSVIPC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_KALLSYMS is not set
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/configs/83xx/mpc836x_rdk_defconfig linux-libre-2.6.38-gnu1/arch/powerpc/configs/83xx/mpc836x_rdk_defconfig
--- linux-libre-2.6.37-gnu1/arch/powerpc/configs/83xx/mpc836x_rdk_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/configs/83xx/mpc836x_rdk_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -3,7 +3,7 @@ CONFIG_SYSVIPC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_KALLSYMS is not set
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/configs/83xx/mpc837x_mds_defconfig linux-libre-2.6.38-gnu1/arch/powerpc/configs/83xx/mpc837x_mds_defconfig
--- linux-libre-2.6.37-gnu1/arch/powerpc/configs/83xx/mpc837x_mds_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/configs/83xx/mpc837x_mds_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -3,7 +3,7 @@ CONFIG_SYSVIPC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 CONFIG_SLAB=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/configs/83xx/mpc837x_rdb_defconfig linux-libre-2.6.38-gnu1/arch/powerpc/configs/83xx/mpc837x_rdb_defconfig
--- linux-libre-2.6.37-gnu1/arch/powerpc/configs/83xx/mpc837x_rdb_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/configs/83xx/mpc837x_rdb_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -3,7 +3,7 @@ CONFIG_SYSVIPC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 CONFIG_SLAB=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/configs/83xx/sbc834x_defconfig linux-libre-2.6.38-gnu1/arch/powerpc/configs/83xx/sbc834x_defconfig
--- linux-libre-2.6.37-gnu1/arch/powerpc/configs/83xx/sbc834x_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/configs/83xx/sbc834x_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -3,7 +3,7 @@ CONFIG_SYSVIPC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_KALLSYMS is not set
 CONFIG_SLAB=y
 CONFIG_MODULES=y
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/configs/85xx/ksi8560_defconfig linux-libre-2.6.38-gnu1/arch/powerpc/configs/85xx/ksi8560_defconfig
--- linux-libre-2.6.37-gnu1/arch/powerpc/configs/85xx/ksi8560_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/configs/85xx/ksi8560_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -4,7 +4,7 @@ CONFIG_SYSVIPC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_BLK_DEV_BSG is not set
 CONFIG_KSI8560=y
 CONFIG_CPM2=y
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/configs/85xx/mpc8540_ads_defconfig linux-libre-2.6.38-gnu1/arch/powerpc/configs/85xx/mpc8540_ads_defconfig
--- linux-libre-2.6.37-gnu1/arch/powerpc/configs/85xx/mpc8540_ads_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/configs/85xx/mpc8540_ads_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -4,7 +4,7 @@ CONFIG_SYSVIPC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_BLK_DEV_BSG is not set
 CONFIG_MPC8540_ADS=y
 CONFIG_NO_HZ=y
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/configs/85xx/mpc8560_ads_defconfig linux-libre-2.6.38-gnu1/arch/powerpc/configs/85xx/mpc8560_ads_defconfig
--- linux-libre-2.6.37-gnu1/arch/powerpc/configs/85xx/mpc8560_ads_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/configs/85xx/mpc8560_ads_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -4,7 +4,7 @@ CONFIG_SYSVIPC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_BLK_DEV_BSG is not set
 CONFIG_MPC8560_ADS=y
 CONFIG_BINFMT_MISC=y
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/configs/85xx/mpc85xx_cds_defconfig linux-libre-2.6.38-gnu1/arch/powerpc/configs/85xx/mpc85xx_cds_defconfig
--- linux-libre-2.6.37-gnu1/arch/powerpc/configs/85xx/mpc85xx_cds_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/configs/85xx/mpc85xx_cds_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -4,7 +4,7 @@ CONFIG_SYSVIPC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_BLK_DEV_BSG is not set
 CONFIG_MPC85xx_CDS=y
 CONFIG_NO_HZ=y
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/configs/85xx/sbc8548_defconfig linux-libre-2.6.38-gnu1/arch/powerpc/configs/85xx/sbc8548_defconfig
--- linux-libre-2.6.37-gnu1/arch/powerpc/configs/85xx/sbc8548_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/configs/85xx/sbc8548_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -4,7 +4,7 @@ CONFIG_SYSVIPC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 CONFIG_SLAB=y
 # CONFIG_BLK_DEV_BSG is not set
 CONFIG_SBC8548=y
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/configs/85xx/sbc8560_defconfig linux-libre-2.6.38-gnu1/arch/powerpc/configs/85xx/sbc8560_defconfig
--- linux-libre-2.6.37-gnu1/arch/powerpc/configs/85xx/sbc8560_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/configs/85xx/sbc8560_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -4,7 +4,7 @@ CONFIG_SYSVIPC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 CONFIG_SLAB=y
 # CONFIG_BLK_DEV_BSG is not set
 CONFIG_SBC8560=y
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/configs/85xx/socrates_defconfig linux-libre-2.6.38-gnu1/arch/powerpc/configs/85xx/socrates_defconfig
--- linux-libre-2.6.37-gnu1/arch/powerpc/configs/85xx/socrates_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/configs/85xx/socrates_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -4,7 +4,7 @@ CONFIG_SYSVIPC=y
 CONFIG_LOG_BUF_SHIFT=16
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_KALLSYMS is not set
 # CONFIG_HOTPLUG is not set
 # CONFIG_EPOLL is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/configs/85xx/stx_gp3_defconfig linux-libre-2.6.38-gnu1/arch/powerpc/configs/85xx/stx_gp3_defconfig
--- linux-libre-2.6.37-gnu1/arch/powerpc/configs/85xx/stx_gp3_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/configs/85xx/stx_gp3_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -4,7 +4,7 @@ CONFIG_SYSVIPC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 CONFIG_MODULES=y
 CONFIG_MODVERSIONS=y
 # CONFIG_BLK_DEV_BSG is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/configs/85xx/tqm8540_defconfig linux-libre-2.6.38-gnu1/arch/powerpc/configs/85xx/tqm8540_defconfig
--- linux-libre-2.6.37-gnu1/arch/powerpc/configs/85xx/tqm8540_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/configs/85xx/tqm8540_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -4,7 +4,7 @@ CONFIG_SYSVIPC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_KALLSYMS is not set
 # CONFIG_HOTPLUG is not set
 # CONFIG_EPOLL is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/configs/85xx/tqm8541_defconfig linux-libre-2.6.38-gnu1/arch/powerpc/configs/85xx/tqm8541_defconfig
--- linux-libre-2.6.37-gnu1/arch/powerpc/configs/85xx/tqm8541_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/configs/85xx/tqm8541_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -4,7 +4,7 @@ CONFIG_SYSVIPC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_KALLSYMS is not set
 # CONFIG_HOTPLUG is not set
 # CONFIG_EPOLL is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/configs/85xx/tqm8548_defconfig linux-libre-2.6.38-gnu1/arch/powerpc/configs/85xx/tqm8548_defconfig
--- linux-libre-2.6.37-gnu1/arch/powerpc/configs/85xx/tqm8548_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/configs/85xx/tqm8548_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -4,7 +4,7 @@ CONFIG_SYSVIPC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_BLK_DEV_BSG is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/configs/85xx/tqm8555_defconfig linux-libre-2.6.38-gnu1/arch/powerpc/configs/85xx/tqm8555_defconfig
--- linux-libre-2.6.37-gnu1/arch/powerpc/configs/85xx/tqm8555_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/configs/85xx/tqm8555_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -4,7 +4,7 @@ CONFIG_SYSVIPC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_KALLSYMS is not set
 # CONFIG_HOTPLUG is not set
 # CONFIG_EPOLL is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/configs/85xx/tqm8560_defconfig linux-libre-2.6.38-gnu1/arch/powerpc/configs/85xx/tqm8560_defconfig
--- linux-libre-2.6.37-gnu1/arch/powerpc/configs/85xx/tqm8560_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/configs/85xx/tqm8560_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -4,7 +4,7 @@ CONFIG_SYSVIPC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_KALLSYMS is not set
 # CONFIG_HOTPLUG is not set
 # CONFIG_EPOLL is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/configs/85xx/xes_mpc85xx_defconfig linux-libre-2.6.38-gnu1/arch/powerpc/configs/85xx/xes_mpc85xx_defconfig
--- linux-libre-2.6.37-gnu1/arch/powerpc/configs/85xx/xes_mpc85xx_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/configs/85xx/xes_mpc85xx_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -11,7 +11,7 @@ CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 CONFIG_KALLSYMS_ALL=y
 CONFIG_KALLSYMS_EXTRA_PASS=y
 CONFIG_MODULES=y
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/configs/86xx/gef_ppc9a_defconfig linux-libre-2.6.38-gnu1/arch/powerpc/configs/86xx/gef_ppc9a_defconfig
--- linux-libre-2.6.37-gnu1/arch/powerpc/configs/86xx/gef_ppc9a_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/configs/86xx/gef_ppc9a_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -11,7 +11,7 @@ CONFIG_LOG_BUF_SHIFT=14
 CONFIG_RELAY=y
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 CONFIG_SLAB=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/configs/86xx/gef_sbc310_defconfig linux-libre-2.6.38-gnu1/arch/powerpc/configs/86xx/gef_sbc310_defconfig
--- linux-libre-2.6.37-gnu1/arch/powerpc/configs/86xx/gef_sbc310_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/configs/86xx/gef_sbc310_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -11,7 +11,7 @@ CONFIG_LOG_BUF_SHIFT=14
 CONFIG_RELAY=y
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 CONFIG_SLAB=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/configs/86xx/gef_sbc610_defconfig linux-libre-2.6.38-gnu1/arch/powerpc/configs/86xx/gef_sbc610_defconfig
--- linux-libre-2.6.37-gnu1/arch/powerpc/configs/86xx/gef_sbc610_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/configs/86xx/gef_sbc610_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -11,7 +11,7 @@ CONFIG_LOG_BUF_SHIFT=14
 CONFIG_RELAY=y
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 CONFIG_SLAB=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/configs/86xx/mpc8610_hpcd_defconfig linux-libre-2.6.38-gnu1/arch/powerpc/configs/86xx/mpc8610_hpcd_defconfig
--- linux-libre-2.6.37-gnu1/arch/powerpc/configs/86xx/mpc8610_hpcd_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/configs/86xx/mpc8610_hpcd_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -6,7 +6,7 @@ CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 CONFIG_KALLSYMS_EXTRA_PASS=y
 # CONFIG_ELF_CORE is not set
 CONFIG_MODULES=y
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/configs/86xx/mpc8641_hpcn_defconfig linux-libre-2.6.38-gnu1/arch/powerpc/configs/86xx/mpc8641_hpcn_defconfig
--- linux-libre-2.6.37-gnu1/arch/powerpc/configs/86xx/mpc8641_hpcn_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/configs/86xx/mpc8641_hpcn_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -10,7 +10,7 @@ CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 CONFIG_KALLSYMS_ALL=y
 CONFIG_KALLSYMS_EXTRA_PASS=y
 CONFIG_MODULES=y
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/configs/86xx/sbc8641d_defconfig linux-libre-2.6.38-gnu1/arch/powerpc/configs/86xx/sbc8641d_defconfig
--- linux-libre-2.6.37-gnu1/arch/powerpc/configs/86xx/sbc8641d_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/configs/86xx/sbc8641d_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -11,7 +11,7 @@ CONFIG_LOG_BUF_SHIFT=14
 CONFIG_RELAY=y
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 CONFIG_SLAB=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/configs/adder875_defconfig linux-libre-2.6.38-gnu1/arch/powerpc/configs/adder875_defconfig
--- linux-libre-2.6.37-gnu1/arch/powerpc/configs/adder875_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/configs/adder875_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -4,7 +4,7 @@ CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_SYSCTL_SYSCALL is not set
 # CONFIG_ELF_CORE is not set
 # CONFIG_BASE_FULL is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/configs/e55xx_smp_defconfig linux-libre-2.6.38-gnu1/arch/powerpc/configs/e55xx_smp_defconfig
--- linux-libre-2.6.37-gnu1/arch/powerpc/configs/e55xx_smp_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/configs/e55xx_smp_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -12,7 +12,7 @@ CONFIG_LOG_BUF_SHIFT=14
 CONFIG_SYSFS_DEPRECATED_V2=y
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 CONFIG_KALLSYMS_ALL=y
 CONFIG_KALLSYMS_EXTRA_PASS=y
 CONFIG_MODULES=y
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/configs/ep8248e_defconfig linux-libre-2.6.38-gnu1/arch/powerpc/configs/ep8248e_defconfig
--- linux-libre-2.6.37-gnu1/arch/powerpc/configs/ep8248e_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/configs/ep8248e_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -2,7 +2,7 @@ CONFIG_SYSVIPC=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 CONFIG_KALLSYMS_ALL=y
 CONFIG_SLAB=y
 # CONFIG_IOSCHED_CFQ is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/configs/ep88xc_defconfig linux-libre-2.6.38-gnu1/arch/powerpc/configs/ep88xc_defconfig
--- linux-libre-2.6.37-gnu1/arch/powerpc/configs/ep88xc_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/configs/ep88xc_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -4,7 +4,7 @@ CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_SYSCTL_SYSCALL is not set
 # CONFIG_ELF_CORE is not set
 # CONFIG_BASE_FULL is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/configs/gamecube_defconfig linux-libre-2.6.38-gnu1/arch/powerpc/configs/gamecube_defconfig
--- linux-libre-2.6.37-gnu1/arch/powerpc/configs/gamecube_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/configs/gamecube_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -6,7 +6,7 @@ CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_ELF_CORE is not set
 CONFIG_PERF_COUNTERS=y
 # CONFIG_VM_EVENT_COUNTERS is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/configs/holly_defconfig linux-libre-2.6.38-gnu1/arch/powerpc/configs/holly_defconfig
--- linux-libre-2.6.37-gnu1/arch/powerpc/configs/holly_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/configs/holly_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -3,7 +3,7 @@ CONFIG_SYSVIPC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 CONFIG_MODULES=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_PPC_CHRP is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/configs/mgcoge_defconfig linux-libre-2.6.38-gnu1/arch/powerpc/configs/mgcoge_defconfig
--- linux-libre-2.6.37-gnu1/arch/powerpc/configs/mgcoge_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/configs/mgcoge_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -3,7 +3,7 @@ CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 CONFIG_KALLSYMS_ALL=y
 CONFIG_SLAB=y
 # CONFIG_IOSCHED_CFQ is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/configs/mgsuvd_defconfig linux-libre-2.6.38-gnu1/arch/powerpc/configs/mgsuvd_defconfig
--- linux-libre-2.6.37-gnu1/arch/powerpc/configs/mgsuvd_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/configs/mgsuvd_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -4,7 +4,7 @@ CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_SYSCTL_SYSCALL is not set
 # CONFIG_HOTPLUG is not set
 # CONFIG_BUG is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/configs/mpc7448_hpc2_defconfig linux-libre-2.6.38-gnu1/arch/powerpc/configs/mpc7448_hpc2_defconfig
--- linux-libre-2.6.37-gnu1/arch/powerpc/configs/mpc7448_hpc2_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/configs/mpc7448_hpc2_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -4,7 +4,7 @@ CONFIG_SYSVIPC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_PPC_CHRP is not set
 # CONFIG_PPC_PMAC is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/configs/mpc8272_ads_defconfig linux-libre-2.6.38-gnu1/arch/powerpc/configs/mpc8272_ads_defconfig
--- linux-libre-2.6.37-gnu1/arch/powerpc/configs/mpc8272_ads_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/configs/mpc8272_ads_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -2,7 +2,7 @@ CONFIG_SYSVIPC=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 CONFIG_KALLSYMS_ALL=y
 # CONFIG_PPC_CHRP is not set
 # CONFIG_PPC_PMAC is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/configs/mpc83xx_defconfig linux-libre-2.6.38-gnu1/arch/powerpc/configs/mpc83xx_defconfig
--- linux-libre-2.6.37-gnu1/arch/powerpc/configs/mpc83xx_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/configs/mpc83xx_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -3,7 +3,7 @@ CONFIG_SYSVIPC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 CONFIG_SLAB=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/configs/mpc85xx_defconfig linux-libre-2.6.38-gnu1/arch/powerpc/configs/mpc85xx_defconfig
--- linux-libre-2.6.37-gnu1/arch/powerpc/configs/mpc85xx_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/configs/mpc85xx_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -10,7 +10,7 @@ CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 CONFIG_KALLSYMS_ALL=y
 CONFIG_KALLSYMS_EXTRA_PASS=y
 CONFIG_MODULES=y
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/configs/mpc85xx_smp_defconfig linux-libre-2.6.38-gnu1/arch/powerpc/configs/mpc85xx_smp_defconfig
--- linux-libre-2.6.37-gnu1/arch/powerpc/configs/mpc85xx_smp_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/configs/mpc85xx_smp_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -12,7 +12,7 @@ CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 CONFIG_KALLSYMS_ALL=y
 CONFIG_KALLSYMS_EXTRA_PASS=y
 CONFIG_MODULES=y
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/configs/mpc866_ads_defconfig linux-libre-2.6.38-gnu1/arch/powerpc/configs/mpc866_ads_defconfig
--- linux-libre-2.6.37-gnu1/arch/powerpc/configs/mpc866_ads_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/configs/mpc866_ads_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -4,7 +4,7 @@ CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_SYSCTL_SYSCALL is not set
 # CONFIG_HOTPLUG is not set
 # CONFIG_BUG is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/configs/mpc86xx_defconfig linux-libre-2.6.38-gnu1/arch/powerpc/configs/mpc86xx_defconfig
--- linux-libre-2.6.37-gnu1/arch/powerpc/configs/mpc86xx_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/configs/mpc86xx_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -10,7 +10,7 @@ CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 CONFIG_KALLSYMS_ALL=y
 CONFIG_KALLSYMS_EXTRA_PASS=y
 CONFIG_MODULES=y
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/configs/mpc885_ads_defconfig linux-libre-2.6.38-gnu1/arch/powerpc/configs/mpc885_ads_defconfig
--- linux-libre-2.6.37-gnu1/arch/powerpc/configs/mpc885_ads_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/configs/mpc885_ads_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -4,7 +4,7 @@ CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_SYSCTL_SYSCALL is not set
 # CONFIG_ELF_CORE is not set
 # CONFIG_BASE_FULL is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/configs/ppc40x_defconfig linux-libre-2.6.38-gnu1/arch/powerpc/configs/ppc40x_defconfig
--- linux-libre-2.6.37-gnu1/arch/powerpc/configs/ppc40x_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/configs/ppc40x_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@ CONFIG_POSIX_MQUEUE=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 CONFIG_KALLSYMS_ALL=y
 CONFIG_KALLSYMS_EXTRA_PASS=y
 CONFIG_MODULES=y
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/configs/ppc44x_defconfig linux-libre-2.6.38-gnu1/arch/powerpc/configs/ppc44x_defconfig
--- linux-libre-2.6.37-gnu1/arch/powerpc/configs/ppc44x_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/configs/ppc44x_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@ CONFIG_POSIX_MQUEUE=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 CONFIG_KALLSYMS_ALL=y
 CONFIG_KALLSYMS_EXTRA_PASS=y
 CONFIG_MODULES=y
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/configs/pq2fads_defconfig linux-libre-2.6.38-gnu1/arch/powerpc/configs/pq2fads_defconfig
--- linux-libre-2.6.37-gnu1/arch/powerpc/configs/pq2fads_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/configs/pq2fads_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -3,7 +3,7 @@ CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 CONFIG_KALLSYMS_ALL=y
 # CONFIG_PPC_CHRP is not set
 # CONFIG_PPC_PMAC is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/configs/ps3_defconfig linux-libre-2.6.38-gnu1/arch/powerpc/configs/ps3_defconfig
--- linux-libre-2.6.37-gnu1/arch/powerpc/configs/ps3_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/configs/ps3_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -8,7 +8,7 @@ CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
 CONFIG_NAMESPACES=y
 CONFIG_BLK_DEV_INITRD=y
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 CONFIG_KALLSYMS_EXTRA_PASS=y
 # CONFIG_PERF_EVENTS is not set
 # CONFIG_COMPAT_BRK is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/configs/pseries_defconfig linux-libre-2.6.38-gnu1/arch/powerpc/configs/pseries_defconfig
--- linux-libre-2.6.37-gnu1/arch/powerpc/configs/pseries_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/configs/pseries_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -2,7 +2,7 @@ CONFIG_PPC64=y
 CONFIG_ALTIVEC=y
 CONFIG_VSX=y
 CONFIG_SMP=y
-CONFIG_NR_CPUS=128
+CONFIG_NR_CPUS=1024
 CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
@@ -45,6 +45,8 @@ CONFIG_KEXEC=y
 CONFIG_IRQ_ALL_CPUS=y
 CONFIG_MEMORY_HOTPLUG=y
 CONFIG_MEMORY_HOTREMOVE=y
+CONFIG_PPC_64K_PAGES=y
+CONFIG_PPC_SUBPAGE_PROT=y
 CONFIG_SCHED_SMT=y
 CONFIG_HOTPLUG_PCI=m
 CONFIG_HOTPLUG_PCI_RPA=m
@@ -184,6 +186,7 @@ CONFIG_ACENIC_OMIT_TIGON_I=y
 CONFIG_E1000=y
 CONFIG_E1000E=y
 CONFIG_TIGON3=y
+CONFIG_BNX2=m
 CONFIG_CHELSIO_T1=m
 CONFIG_CHELSIO_T3=m
 CONFIG_EHEA=y
@@ -311,9 +314,7 @@ CONFIG_DEBUG_KERNEL=y
 # CONFIG_RCU_CPU_STALL_DETECTOR is not set
 CONFIG_LATENCYTOP=y
 CONFIG_SYSCTL_SYSCALL_CHECK=y
-CONFIG_IRQSOFF_TRACER=y
 CONFIG_SCHED_TRACER=y
-CONFIG_STACK_TRACER=y
 CONFIG_BLK_DEV_IO_TRACE=y
 CONFIG_DEBUG_STACKOVERFLOW=y
 CONFIG_DEBUG_STACK_USAGE=y
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/configs/storcenter_defconfig linux-libre-2.6.38-gnu1/arch/powerpc/configs/storcenter_defconfig
--- linux-libre-2.6.37-gnu1/arch/powerpc/configs/storcenter_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/configs/storcenter_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -1,7 +1,7 @@
 CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_KALLSYMS is not set
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/configs/tqm8xx_defconfig linux-libre-2.6.38-gnu1/arch/powerpc/configs/tqm8xx_defconfig
--- linux-libre-2.6.37-gnu1/arch/powerpc/configs/tqm8xx_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/configs/tqm8xx_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@ CONFIG_SYSVIPC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_SYSFS_DEPRECATED_V2=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_SYSCTL_SYSCALL is not set
 # CONFIG_ELF_CORE is not set
 # CONFIG_BASE_FULL is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/configs/wii_defconfig linux-libre-2.6.38-gnu1/arch/powerpc/configs/wii_defconfig
--- linux-libre-2.6.37-gnu1/arch/powerpc/configs/wii_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/configs/wii_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -7,7 +7,7 @@ CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_ELF_CORE is not set
 CONFIG_PERF_COUNTERS=y
 # CONFIG_VM_EVENT_COUNTERS is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/include/asm/8xx_immap.h linux-libre-2.6.38-gnu1/arch/powerpc/include/asm/8xx_immap.h
--- linux-libre-2.6.37-gnu1/arch/powerpc/include/asm/8xx_immap.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/include/asm/8xx_immap.h	2011-03-14 21:20:32.000000000 -0400
@@ -93,7 +93,7 @@ typedef struct	mem_ctlr {
 } memctl8xx_t;
 
 /*-----------------------------------------------------------------------
- * BR - Memory Controler: Base Register					16-9
+ * BR - Memory Controller: Base Register					16-9
  */
 #define BR_BA_MSK	0xffff8000	/* Base Address Mask			*/
 #define BR_AT_MSK	0x00007000	/* Address Type Mask			*/
@@ -110,7 +110,7 @@ typedef struct	mem_ctlr {
 #define BR_V		0x00000001	/* Bank Valid				*/
 
 /*-----------------------------------------------------------------------
- * OR - Memory Controler: Option Register				16-11
+ * OR - Memory Controller: Option Register				16-11
  */
 #define OR_AM_MSK	0xffff8000	/* Address Mask Mask			*/
 #define OR_ATM_MSK	0x00007000	/* Address Type Mask Mask		*/
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/include/asm/bitops.h linux-libre-2.6.38-gnu1/arch/powerpc/include/asm/bitops.h
--- linux-libre-2.6.37-gnu1/arch/powerpc/include/asm/bitops.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/include/asm/bitops.h	2011-03-14 21:20:32.000000000 -0400
@@ -267,7 +267,16 @@ static __inline__ int fls64(__u64 x)
 #include <asm-generic/bitops/fls64.h>
 #endif /* __powerpc64__ */
 
+#ifdef CONFIG_PPC64
+unsigned int __arch_hweight8(unsigned int w);
+unsigned int __arch_hweight16(unsigned int w);
+unsigned int __arch_hweight32(unsigned int w);
+unsigned long __arch_hweight64(__u64 w);
+#include <asm-generic/bitops/const_hweight.h>
+#else
 #include <asm-generic/bitops/hweight.h>
+#endif
+
 #include <asm-generic/bitops/find.h>
 
 /* Little-endian versions */
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/include/asm/cputable.h linux-libre-2.6.38-gnu1/arch/powerpc/include/asm/cputable.h
--- linux-libre-2.6.37-gnu1/arch/powerpc/include/asm/cputable.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/include/asm/cputable.h	2011-03-14 21:20:32.000000000 -0400
@@ -199,6 +199,8 @@ extern const char *powerpc_base_platform
 #define CPU_FTR_UNALIGNED_LD_STD	LONG_ASM_CONST(0x0080000000000000)
 #define CPU_FTR_ASYM_SMT		LONG_ASM_CONST(0x0100000000000000)
 #define CPU_FTR_STCX_CHECKS_ADDRESS	LONG_ASM_CONST(0x0200000000000000)
+#define CPU_FTR_POPCNTB			LONG_ASM_CONST(0x0400000000000000)
+#define CPU_FTR_POPCNTD			LONG_ASM_CONST(0x0800000000000000)
 
 #ifndef __ASSEMBLY__
 
@@ -403,21 +405,22 @@ extern const char *powerpc_base_platform
 	    CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
 	    CPU_FTR_MMCRA | CPU_FTR_SMT | \
 	    CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE | \
-	    CPU_FTR_PURR | CPU_FTR_STCX_CHECKS_ADDRESS)
+	    CPU_FTR_PURR | CPU_FTR_STCX_CHECKS_ADDRESS | \
+	    CPU_FTR_POPCNTB)
 #define CPU_FTRS_POWER6 (CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \
 	    CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
 	    CPU_FTR_MMCRA | CPU_FTR_SMT | \
 	    CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE | \
 	    CPU_FTR_PURR | CPU_FTR_SPURR | CPU_FTR_REAL_LE | \
 	    CPU_FTR_DSCR | CPU_FTR_UNALIGNED_LD_STD | \
-	    CPU_FTR_STCX_CHECKS_ADDRESS)
+	    CPU_FTR_STCX_CHECKS_ADDRESS | CPU_FTR_POPCNTB)
 #define CPU_FTRS_POWER7 (CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \
 	    CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
 	    CPU_FTR_MMCRA | CPU_FTR_SMT | \
 	    CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE | \
 	    CPU_FTR_PURR | CPU_FTR_SPURR | CPU_FTR_REAL_LE | \
 	    CPU_FTR_DSCR | CPU_FTR_SAO  | CPU_FTR_ASYM_SMT | \
-	    CPU_FTR_STCX_CHECKS_ADDRESS)
+	    CPU_FTR_STCX_CHECKS_ADDRESS | CPU_FTR_POPCNTB | CPU_FTR_POPCNTD)
 #define CPU_FTRS_CELL	(CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \
 	    CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
 	    CPU_FTR_ALTIVEC_COMP | CPU_FTR_MMCRA | CPU_FTR_SMT | \
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/include/asm/cputhreads.h linux-libre-2.6.38-gnu1/arch/powerpc/include/asm/cputhreads.h
--- linux-libre-2.6.37-gnu1/arch/powerpc/include/asm/cputhreads.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/include/asm/cputhreads.h	2011-03-14 21:20:32.000000000 -0400
@@ -61,22 +61,25 @@ static inline cpumask_t cpu_online_cores
 	return cpu_thread_mask_to_cores(cpu_online_map);
 }
 
-static inline int cpu_thread_to_core(int cpu)
-{
-	return cpu >> threads_shift;
-}
+#ifdef CONFIG_SMP
+int cpu_core_index_of_thread(int cpu);
+int cpu_first_thread_of_core(int core);
+#else
+static inline int cpu_core_index_of_thread(int cpu) { return cpu; }
+static inline int cpu_first_thread_of_core(int core) { return core; }
+#endif
 
 static inline int cpu_thread_in_core(int cpu)
 {
 	return cpu & (threads_per_core - 1);
 }
 
-static inline int cpu_first_thread_in_core(int cpu)
+static inline int cpu_first_thread_sibling(int cpu)
 {
 	return cpu & ~(threads_per_core - 1);
 }
 
-static inline int cpu_last_thread_in_core(int cpu)
+static inline int cpu_last_thread_sibling(int cpu)
 {
 	return cpu | (threads_per_core - 1);
 }
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/include/asm/device.h linux-libre-2.6.38-gnu1/arch/powerpc/include/asm/device.h
--- linux-libre-2.6.37-gnu1/arch/powerpc/include/asm/device.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/include/asm/device.h	2011-03-14 21:20:32.000000000 -0400
@@ -9,6 +9,12 @@
 struct dma_map_ops;
 struct device_node;
 
+/*
+ * Arch extensions to struct device.
+ *
+ * When adding fields, consider macio_add_one_device in
+ * drivers/macintosh/macio_asic.c
+ */
 struct dev_archdata {
 	/* DMA operations on that device */
 	struct dma_map_ops	*dma_ops;
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/include/asm/feature-fixups.h linux-libre-2.6.38-gnu1/arch/powerpc/include/asm/feature-fixups.h
--- linux-libre-2.6.37-gnu1/arch/powerpc/include/asm/feature-fixups.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/include/asm/feature-fixups.h	2011-03-14 21:20:32.000000000 -0400
@@ -37,18 +37,21 @@ label##2:						\
 	.align 2;					\
 label##3:
 
-#define MAKE_FTR_SECTION_ENTRY(msk, val, label, sect)	\
-label##4:						\
-	.popsection;					\
-	.pushsection sect,"a";				\
-	.align 3;					\
-label##5:					       	\
-	FTR_ENTRY_LONG msk;				\
-	FTR_ENTRY_LONG val;				\
-	FTR_ENTRY_OFFSET label##1b-label##5b;		\
-	FTR_ENTRY_OFFSET label##2b-label##5b;	 	\
-	FTR_ENTRY_OFFSET label##3b-label##5b;		\
-	FTR_ENTRY_OFFSET label##4b-label##5b;	 	\
+#define MAKE_FTR_SECTION_ENTRY(msk, val, label, sect)		\
+label##4:							\
+	.popsection;						\
+	.pushsection sect,"a";					\
+	.align 3;						\
+label##5:							\
+	FTR_ENTRY_LONG msk;					\
+	FTR_ENTRY_LONG val;					\
+	FTR_ENTRY_OFFSET label##1b-label##5b;			\
+	FTR_ENTRY_OFFSET label##2b-label##5b;			\
+	FTR_ENTRY_OFFSET label##3b-label##5b;			\
+	FTR_ENTRY_OFFSET label##4b-label##5b;			\
+	.ifgt (label##4b-label##3b)-(label##2b-label##1b);	\
+	.error "Feature section else case larger than body";	\
+	.endif;							\
 	.popsection;
 
 
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/include/asm/firmware.h linux-libre-2.6.38-gnu1/arch/powerpc/include/asm/firmware.h
--- linux-libre-2.6.37-gnu1/arch/powerpc/include/asm/firmware.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/include/asm/firmware.h	2011-03-14 21:20:32.000000000 -0400
@@ -46,6 +46,7 @@
 #define FW_FEATURE_PS3_LV1	ASM_CONST(0x0000000000800000)
 #define FW_FEATURE_BEAT		ASM_CONST(0x0000000001000000)
 #define FW_FEATURE_CMO		ASM_CONST(0x0000000002000000)
+#define FW_FEATURE_VPHN		ASM_CONST(0x0000000004000000)
 
 #ifndef __ASSEMBLY__
 
@@ -59,7 +60,7 @@ enum {
 		FW_FEATURE_VIO | FW_FEATURE_RDMA | FW_FEATURE_LLAN |
 		FW_FEATURE_BULK_REMOVE | FW_FEATURE_XDABR |
 		FW_FEATURE_MULTITCE | FW_FEATURE_SPLPAR | FW_FEATURE_LPAR |
-		FW_FEATURE_CMO,
+		FW_FEATURE_CMO | FW_FEATURE_VPHN,
 	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,
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/include/asm/hvcall.h linux-libre-2.6.38-gnu1/arch/powerpc/include/asm/hvcall.h
--- linux-libre-2.6.37-gnu1/arch/powerpc/include/asm/hvcall.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/include/asm/hvcall.h	2011-03-14 21:20:32.000000000 -0400
@@ -232,7 +232,9 @@
 #define H_GET_EM_PARMS		0x2B8
 #define H_SET_MPP		0x2D0
 #define H_GET_MPP		0x2D4
-#define MAX_HCALL_OPCODE	H_GET_MPP
+#define H_HOME_NODE_ASSOCIATIVITY 0x2EC
+#define H_BEST_ENERGY		0x2F4
+#define MAX_HCALL_OPCODE	H_BEST_ENERGY
 
 #ifndef __ASSEMBLY__
 
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/include/asm/immap_qe.h linux-libre-2.6.38-gnu1/arch/powerpc/include/asm/immap_qe.h
--- linux-libre-2.6.37-gnu1/arch/powerpc/include/asm/immap_qe.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/include/asm/immap_qe.h	2011-03-14 21:20:32.000000000 -0400
@@ -467,13 +467,22 @@ struct qe_immap {
 extern struct qe_immap __iomem *qe_immr;
 extern phys_addr_t get_qe_base(void);
 
-static inline unsigned long immrbar_virt_to_phys(void *address)
+/*
+ * Returns the offset within the QE address space of the given pointer.
+ *
+ * Note that the QE does not support 36-bit physical addresses, so if
+ * get_qe_base() returns a number above 4GB, the caller will probably fail.
+ */
+static inline phys_addr_t immrbar_virt_to_phys(void *address)
 {
-	if ( ((u32)address >= (u32)qe_immr) &&
-			((u32)address < ((u32)qe_immr + QE_IMMAP_SIZE)) )
-		return (unsigned long)(address - (u32)qe_immr +
-				(u32)get_qe_base());
-	return (unsigned long)virt_to_phys(address);
+	void *q = (void *)qe_immr;
+
+	/* Is it a MURAM address? */
+	if ((address >= q) && (address < (q + QE_IMMAP_SIZE)))
+		return get_qe_base() + (address - q);
+
+	/* It's an address returned by kmalloc */
+	return virt_to_phys(address);
 }
 
 #endif /* __KERNEL__ */
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/include/asm/ioctls.h linux-libre-2.6.38-gnu1/arch/powerpc/include/asm/ioctls.h
--- linux-libre-2.6.37-gnu1/arch/powerpc/include/asm/ioctls.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/include/asm/ioctls.h	2011-03-14 21:20:32.000000000 -0400
@@ -94,6 +94,7 @@
 #define TIOCSRS485	0x542f
 #define TIOCGPTN	_IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
 #define TIOCSPTLCK	_IOW('T',0x31, int)  /* Lock/unlock Pty */
+#define TIOCGDEV	_IOR('T',0x32, unsigned int) /* Get primary device node of /dev/console */
 #define TIOCSIG		_IOW('T',0x36, int)  /* Generate signal on Pty slave */
 
 #define TIOCSERCONFIG	0x5453
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/include/asm/irqflags.h linux-libre-2.6.38-gnu1/arch/powerpc/include/asm/irqflags.h
--- linux-libre-2.6.37-gnu1/arch/powerpc/include/asm/irqflags.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/include/asm/irqflags.h	2011-03-14 21:20:32.000000000 -0400
@@ -12,24 +12,44 @@
 
 #else
 #ifdef CONFIG_TRACE_IRQFLAGS
+#ifdef CONFIG_IRQSOFF_TRACER
+/*
+ * Since the ftrace irqsoff latency trace checks CALLER_ADDR1,
+ * which is the stack frame here, we need to force a stack frame
+ * in case we came from user space.
+ */
+#define TRACE_WITH_FRAME_BUFFER(func)		\
+	mflr	r0;				\
+	stdu	r1, -32(r1);			\
+	std	r0, 16(r1);			\
+	stdu	r1, -32(r1);			\
+	bl func;				\
+	ld	r1, 0(r1);			\
+	ld	r1, 0(r1);
+#else
+#define TRACE_WITH_FRAME_BUFFER(func)		\
+	bl func;
+#endif
+
 /*
  * Most of the CPU's IRQ-state tracing is done from assembly code; we
  * have to call a C function so call a wrapper that saves all the
  * C-clobbered registers.
  */
-#define TRACE_ENABLE_INTS	bl .trace_hardirqs_on
-#define TRACE_DISABLE_INTS	bl .trace_hardirqs_off
-#define TRACE_AND_RESTORE_IRQ_PARTIAL(en,skip)	\
-	cmpdi	en,0;				\
-	bne	95f;				\
-	stb	en,PACASOFTIRQEN(r13);		\
-	bl	.trace_hardirqs_off;		\
-	b	skip;				\
-95:	bl	.trace_hardirqs_on;		\
+#define TRACE_ENABLE_INTS	TRACE_WITH_FRAME_BUFFER(.trace_hardirqs_on)
+#define TRACE_DISABLE_INTS	TRACE_WITH_FRAME_BUFFER(.trace_hardirqs_off)
+
+#define TRACE_AND_RESTORE_IRQ_PARTIAL(en,skip)		\
+	cmpdi	en,0;					\
+	bne	95f;					\
+	stb	en,PACASOFTIRQEN(r13);			\
+	TRACE_WITH_FRAME_BUFFER(.trace_hardirqs_off)	\
+	b	skip;					\
+95:	TRACE_WITH_FRAME_BUFFER(.trace_hardirqs_on)	\
 	li	en,1;
 #define TRACE_AND_RESTORE_IRQ(en)		\
 	TRACE_AND_RESTORE_IRQ_PARTIAL(en,96f);	\
-	stb	en,PACASOFTIRQEN(r13);	        \
+	stb	en,PACASOFTIRQEN(r13);		\
 96:
 #else
 #define TRACE_ENABLE_INTS
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/include/asm/lppaca.h linux-libre-2.6.38-gnu1/arch/powerpc/include/asm/lppaca.h
--- linux-libre-2.6.37-gnu1/arch/powerpc/include/asm/lppaca.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/include/asm/lppaca.h	2011-03-14 21:20:32.000000000 -0400
@@ -33,9 +33,25 @@
 //
 //----------------------------------------------------------------------------
 #include <linux/cache.h>
+#include <linux/threads.h>
 #include <asm/types.h>
 #include <asm/mmu.h>
 
+/*
+ * We only have to have statically allocated lppaca structs on
+ * legacy iSeries, which supports at most 64 cpus.
+ */
+#ifdef CONFIG_PPC_ISERIES
+#if NR_CPUS < 64
+#define NR_LPPACAS	NR_CPUS
+#else
+#define NR_LPPACAS	64
+#endif
+#else /* not iSeries */
+#define NR_LPPACAS	1
+#endif
+
+
 /* The Hypervisor barfs if the lppaca crosses a page boundary.  A 1k
  * alignment is sufficient to prevent this */
 struct lppaca {
@@ -62,7 +78,10 @@ struct lppaca {
 	volatile u32 dyn_pir;		// Dynamic ProcIdReg value	x20-x23
 	u32	dsei_data;           	// DSEI data                  	x24-x27
 	u64	sprg3;               	// SPRG3 value                	x28-x2F
-	u8	reserved3[80];		// Reserved			x30-x7F
+	u8	reserved3[40];		// Reserved			x30-x57
+	volatile u8 vphn_assoc_counts[8]; // Virtual processor home node
+					// associativity change counters x58-x5F
+	u8	reserved4[32];		// Reserved			x60-x7F
 
 //=============================================================================
 // CACHE_LINE_2 0x0080 - 0x00FF Contains local read-write data
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/include/asm/machdep.h linux-libre-2.6.38-gnu1/arch/powerpc/include/asm/machdep.h
--- linux-libre-2.6.37-gnu1/arch/powerpc/include/asm/machdep.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/include/asm/machdep.h	2011-03-14 21:20:32.000000000 -0400
@@ -27,9 +27,7 @@ struct iommu_table;
 struct rtc_time;
 struct file;
 struct pci_controller;
-#ifdef CONFIG_KEXEC
 struct kimage;
-#endif
 
 #ifdef CONFIG_SMP
 struct smp_ops_t {
@@ -72,7 +70,7 @@ struct machdep_calls {
 					     int psize, int ssize);
 	void		(*flush_hash_range)(unsigned long number, int local);
 
-	/* special for kexec, to be called in real mode, linar mapping is
+	/* special for kexec, to be called in real mode, linear mapping is
 	 * destroyed as well */
 	void		(*hpte_clear_all)(void);
 
@@ -118,9 +116,6 @@ struct machdep_calls {
 	 * If for some reason there is no irq, but the interrupt
 	 * shouldn't be counted as spurious, return NO_IRQ_IGNORE. */
 	unsigned int	(*get_irq)(void);
-#ifdef CONFIG_KEXEC
-	void		(*kexec_cpu_down)(int crash_shutdown, int secondary);
-#endif
 
 	/* PCI stuff */
 	/* Called after scanning the bus, before allocating resources */
@@ -237,11 +232,7 @@ struct machdep_calls {
 	void (*machine_shutdown)(void);
 
 #ifdef CONFIG_KEXEC
-	/* Called to do the minimal shutdown needed to run a kexec'd kernel
-	 * to run successfully.
-	 * XXX Should we move this one out of kexec scope?
-	 */
-	void (*machine_crash_shutdown)(struct pt_regs *regs);
+	void (*kexec_cpu_down)(int crash_shutdown, int secondary);
 
 	/* Called to do what every setup is needed on image and the
 	 * reboot code buffer. Returns 0 on success.
@@ -250,9 +241,6 @@ struct machdep_calls {
 	 */
 	int (*machine_kexec_prepare)(struct kimage *image);
 
-	/* Called to handle any machine specific cleanup on image */
-	void (*machine_kexec_cleanup)(struct kimage *image);
-
 	/* Called to perform the _real_ kexec.
 	 * Do NOT allocate memory or fail here. We are past the point of
 	 * no return.
@@ -324,8 +312,6 @@ extern sys_ctrler_t sys_ctrler;
 
 #endif /* CONFIG_PPC_PMAC */
 
-extern void setup_pci_ptrs(void);
-
 #ifdef CONFIG_SMP
 /* Poor default implementations */
 extern void __devinit smp_generic_give_timebase(void);
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/include/asm/mmu-book3e.h linux-libre-2.6.38-gnu1/arch/powerpc/include/asm/mmu-book3e.h
--- linux-libre-2.6.37-gnu1/arch/powerpc/include/asm/mmu-book3e.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/include/asm/mmu-book3e.h	2011-03-14 21:20:32.000000000 -0400
@@ -40,8 +40,8 @@
 
 /* MAS registers bit definitions */
 
-#define MAS0_TLBSEL(x)		((x << 28) & 0x30000000)
-#define MAS0_ESEL(x)		((x << 16) & 0x0FFF0000)
+#define MAS0_TLBSEL(x)		(((x) << 28) & 0x30000000)
+#define MAS0_ESEL(x)		(((x) << 16) & 0x0FFF0000)
 #define MAS0_NV(x)		((x) & 0x00000FFF)
 #define MAS0_HES		0x00004000
 #define MAS0_WQ_ALLWAYS		0x00000000
@@ -50,12 +50,12 @@
 
 #define MAS1_VALID		0x80000000
 #define MAS1_IPROT		0x40000000
-#define MAS1_TID(x)		((x << 16) & 0x3FFF0000)
+#define MAS1_TID(x)		(((x) << 16) & 0x3FFF0000)
 #define MAS1_IND		0x00002000
 #define MAS1_TS			0x00001000
 #define MAS1_TSIZE_MASK		0x00000f80
 #define MAS1_TSIZE_SHIFT	7
-#define MAS1_TSIZE(x)		((x << MAS1_TSIZE_SHIFT) & MAS1_TSIZE_MASK)
+#define MAS1_TSIZE(x)		(((x) << MAS1_TSIZE_SHIFT) & MAS1_TSIZE_MASK)
 
 #define MAS2_EPN		0xFFFFF000
 #define MAS2_X0			0x00000040
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/include/asm/mmzone.h linux-libre-2.6.38-gnu1/arch/powerpc/include/asm/mmzone.h
--- linux-libre-2.6.37-gnu1/arch/powerpc/include/asm/mmzone.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/include/asm/mmzone.h	2011-03-14 21:20:32.000000000 -0400
@@ -33,6 +33,9 @@ extern int numa_cpu_lookup_table[];
 extern cpumask_var_t node_to_cpumask_map[];
 #ifdef CONFIG_MEMORY_HOTPLUG
 extern unsigned long max_pfn;
+u64 memory_hotplug_max(void);
+#else
+#define memory_hotplug_max() memblock_end_of_DRAM()
 #endif
 
 /*
@@ -42,6 +45,8 @@ extern unsigned long max_pfn;
 #define node_start_pfn(nid)	(NODE_DATA(nid)->node_start_pfn)
 #define node_end_pfn(nid)	(NODE_DATA(nid)->node_end_pfn)
 
+#else
+#define memory_hotplug_max() memblock_end_of_DRAM()
 #endif /* CONFIG_NEED_MULTIPLE_NODES */
 
 #endif /* __KERNEL__ */
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/include/asm/nvram.h linux-libre-2.6.38-gnu1/arch/powerpc/include/asm/nvram.h
--- linux-libre-2.6.37-gnu1/arch/powerpc/include/asm/nvram.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/include/asm/nvram.h	2011-03-14 21:20:32.000000000 -0400
@@ -10,31 +10,7 @@
 #ifndef _ASM_POWERPC_NVRAM_H
 #define _ASM_POWERPC_NVRAM_H
 
-#include <linux/errno.h>
-
-#define NVRW_CNT 0x20
-#define NVRAM_HEADER_LEN 16 /* sizeof(struct nvram_header) */
-#define NVRAM_BLOCK_LEN 16
-#define NVRAM_MAX_REQ (2080/NVRAM_BLOCK_LEN)
-#define NVRAM_MIN_REQ (1056/NVRAM_BLOCK_LEN)
-
-#define NVRAM_AS0  0x74
-#define NVRAM_AS1  0x75
-#define NVRAM_DATA 0x77
-
-
-/* RTC Offsets */
-
-#define MOTO_RTC_SECONDS	0x1FF9
-#define MOTO_RTC_MINUTES	0x1FFA
-#define MOTO_RTC_HOURS		0x1FFB
-#define MOTO_RTC_DAY_OF_WEEK	0x1FFC
-#define MOTO_RTC_DAY_OF_MONTH	0x1FFD
-#define MOTO_RTC_MONTH		0x1FFE
-#define MOTO_RTC_YEAR		0x1FFF
-#define MOTO_RTC_CONTROLA       0x1FF8
-#define MOTO_RTC_CONTROLB       0x1FF9
-
+/* Signatures for nvram partitions */
 #define NVRAM_SIG_SP	0x02	/* support processor */
 #define NVRAM_SIG_OF	0x50	/* open firmware config */
 #define NVRAM_SIG_FW	0x51	/* general firmware */
@@ -49,32 +25,19 @@
 #define NVRAM_SIG_OS	0xa0	/* OS defined */
 #define NVRAM_SIG_PANIC	0xa1	/* Apple OSX "panic" */
 
-/* If change this size, then change the size of NVNAME_LEN */
-struct nvram_header {
-	unsigned char signature;
-	unsigned char checksum;
-	unsigned short length;
-	char name[12];
-};
-
 #ifdef __KERNEL__
 
+#include <linux/errno.h>
 #include <linux/list.h>
 
-struct nvram_partition {
-	struct list_head partition;
-	struct nvram_header header;
-	unsigned int index;
-};
-
-
+#ifdef CONFIG_PPC_PSERIES
 extern int nvram_write_error_log(char * buff, int length,
 					 unsigned int err_type, unsigned int err_seq);
 extern int nvram_read_error_log(char * buff, int length,
 					 unsigned int * err_type, unsigned int *err_seq);
 extern int nvram_clear_error_log(void);
-
 extern int pSeries_nvram_init(void);
+#endif /* CONFIG_PPC_PSERIES */
 
 #ifdef CONFIG_MMIO_NVRAM
 extern int mmio_nvram_init(void);
@@ -85,6 +48,13 @@ static inline int mmio_nvram_init(void)
 }
 #endif
 
+extern int __init nvram_scan_partitions(void);
+extern loff_t nvram_create_partition(const char *name, int sig,
+				     int req_size, int min_size);
+extern int nvram_remove_partition(const char *name, int sig);
+extern int nvram_get_partition_size(loff_t data_index);
+extern loff_t nvram_find_partition(const char *name, int sig, int *out_size);
+
 #endif /* __KERNEL__ */
 
 /* PowerMac specific nvram stuffs */
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/include/asm/page.h linux-libre-2.6.38-gnu1/arch/powerpc/include/asm/page.h
--- linux-libre-2.6.37-gnu1/arch/powerpc/include/asm/page.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/include/asm/page.h	2011-03-14 21:20:32.000000000 -0400
@@ -101,7 +101,7 @@ extern phys_addr_t kernstart_addr;
 
 #ifdef CONFIG_FLATMEM
 #define ARCH_PFN_OFFSET		(MEMORY_START >> PAGE_SHIFT)
-#define pfn_valid(pfn)		((pfn) >= ARCH_PFN_OFFSET && (pfn) < (ARCH_PFN_OFFSET + max_mapnr))
+#define pfn_valid(pfn)		((pfn) >= ARCH_PFN_OFFSET && (pfn) < max_mapnr)
 #endif
 
 #define virt_to_page(kaddr)	pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/include/asm/ppc-opcode.h linux-libre-2.6.38-gnu1/arch/powerpc/include/asm/ppc-opcode.h
--- linux-libre-2.6.37-gnu1/arch/powerpc/include/asm/ppc-opcode.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/include/asm/ppc-opcode.h	2011-03-14 21:20:32.000000000 -0400
@@ -36,6 +36,8 @@
 #define PPC_INST_NOP			0x60000000
 #define PPC_INST_POPCNTB		0x7c0000f4
 #define PPC_INST_POPCNTB_MASK		0xfc0007fe
+#define PPC_INST_POPCNTD		0x7c0003f4
+#define PPC_INST_POPCNTW		0x7c0002f4
 #define PPC_INST_RFCI			0x4c000066
 #define PPC_INST_RFDI			0x4c00004e
 #define PPC_INST_RFMCI			0x4c00004c
@@ -88,6 +90,12 @@
 					__PPC_RB(b) | __PPC_EH(eh))
 #define PPC_MSGSND(b)		stringify_in_c(.long PPC_INST_MSGSND | \
 					__PPC_RB(b))
+#define PPC_POPCNTB(a, s)	stringify_in_c(.long PPC_INST_POPCNTB | \
+					__PPC_RA(a) | __PPC_RS(s))
+#define PPC_POPCNTD(a, s)	stringify_in_c(.long PPC_INST_POPCNTD | \
+					__PPC_RA(a) | __PPC_RS(s))
+#define PPC_POPCNTW(a, s)	stringify_in_c(.long PPC_INST_POPCNTW | \
+					__PPC_RA(a) | __PPC_RS(s))
 #define PPC_RFCI		stringify_in_c(.long PPC_INST_RFCI)
 #define PPC_RFDI		stringify_in_c(.long PPC_INST_RFDI)
 #define PPC_RFMCI		stringify_in_c(.long PPC_INST_RFMCI)
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/include/asm/processor.h linux-libre-2.6.38-gnu1/arch/powerpc/include/asm/processor.h
--- linux-libre-2.6.37-gnu1/arch/powerpc/include/asm/processor.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/include/asm/processor.h	2011-03-14 21:20:32.000000000 -0400
@@ -122,7 +122,6 @@ extern struct task_struct *last_task_use
 		TASK_UNMAPPED_BASE_USER32 : TASK_UNMAPPED_BASE_USER64 )
 #endif
 
-#ifdef __KERNEL__
 #ifdef __powerpc64__
 
 #define STACK_TOP_USER64 TASK_SIZE_USER64
@@ -139,7 +138,6 @@ extern struct task_struct *last_task_use
 #define STACK_TOP_MAX	STACK_TOP
 
 #endif /* __powerpc64__ */
-#endif /* __KERNEL__ */
 
 typedef struct {
 	unsigned long seg;
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/include/asm/prom.h linux-libre-2.6.38-gnu1/arch/powerpc/include/asm/prom.h
--- linux-libre-2.6.37-gnu1/arch/powerpc/include/asm/prom.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/include/asm/prom.h	2011-03-14 21:20:32.000000000 -0400
@@ -42,7 +42,7 @@ extern void pci_create_OF_bus_map(void);
 
 /* Translate a DMA address from device space to CPU space */
 extern u64 of_translate_dma_address(struct device_node *dev,
-				    const u32 *in_addr);
+				    const __be32 *in_addr);
 
 #ifdef CONFIG_PCI
 extern unsigned long pci_address_to_pio(phys_addr_t address);
@@ -63,9 +63,6 @@ struct device_node *of_get_cpu_node(int
 /* cache lookup */
 struct device_node *of_find_next_cache_node(struct device_node *np);
 
-/* Get the MAC address */
-extern const void *of_get_mac_address(struct device_node *np);
-
 #ifdef CONFIG_NUMA
 extern int of_node_to_nid(struct device_node *device);
 #else
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/include/asm/reg_booke.h linux-libre-2.6.38-gnu1/arch/powerpc/include/asm/reg_booke.h
--- linux-libre-2.6.37-gnu1/arch/powerpc/include/asm/reg_booke.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/include/asm/reg_booke.h	2011-03-14 21:20:32.000000000 -0400
@@ -246,6 +246,20 @@
 					store or cache line push */
 #endif
 
+/* Bit definitions for the HID1 */
+#ifdef CONFIG_E500
+/* e500v1/v2 */
+#define HID1_PLL_CFG_MASK 0xfc000000	/* PLL_CFG input pins */
+#define HID1_RFXE	0x00020000	/* Read fault exception enable */
+#define HID1_R1DPE	0x00008000	/* R1 data bus parity enable */
+#define HID1_R2DPE	0x00004000	/* R2 data bus parity enable */
+#define HID1_ASTME	0x00002000	/* Address bus streaming mode enable */
+#define HID1_ABE	0x00001000	/* Address broadcast enable */
+#define HID1_MPXTT	0x00000400	/* MPX re-map transfer type */
+#define HID1_ATS	0x00000080	/* Atomic status */
+#define HID1_MID_MASK	0x0000000f	/* MID input pins */
+#endif
+
 /* Bit definitions for the DBSR. */
 /*
  * DBSR bits which have conflicting definitions on true Book E versus IBM 40x.
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/include/asm/reg.h linux-libre-2.6.38-gnu1/arch/powerpc/include/asm/reg.h
--- linux-libre-2.6.37-gnu1/arch/powerpc/include/asm/reg.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/include/asm/reg.h	2011-03-14 21:20:32.000000000 -0400
@@ -283,6 +283,7 @@
 #define HID0_NOPTI	(1<<0)		/* No-op dcbt and dcbst instr. */
 
 #define SPRN_HID1	0x3F1		/* Hardware Implementation Register 1 */
+#ifdef CONFIG_6xx
 #define HID1_EMCP	(1<<31)		/* 7450 Machine Check Pin Enable */
 #define HID1_DFS	(1<<22)		/* 7447A Dynamic Frequency Scaling */
 #define HID1_PC0	(1<<16)		/* 7450 PLL_CFG[0] */
@@ -292,6 +293,7 @@
 #define HID1_SYNCBE	(1<<11)		/* 7450 ABE for sync, eieio */
 #define HID1_ABE	(1<<10)		/* 7450 Address Broadcast Enable */
 #define HID1_PS		(1<<16)		/* 750FX PLL selection */
+#endif
 #define SPRN_HID2	0x3F8		/* Hardware Implementation Register 2 */
 #define SPRN_HID2_GEKKO	0x398		/* Gekko HID2 Register */
 #define SPRN_IABR	0x3F2	/* Instruction Address Breakpoint Register */
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/include/asm/spu.h linux-libre-2.6.38-gnu1/arch/powerpc/include/asm/spu.h
--- linux-libre-2.6.37-gnu1/arch/powerpc/include/asm/spu.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/include/asm/spu.h	2011-03-14 21:20:32.000000000 -0400
@@ -203,14 +203,6 @@ void spu_irq_setaffinity(struct spu *spu
 void spu_setup_kernel_slbs(struct spu *spu, struct spu_lscsa *lscsa,
 		void *code, int code_size);
 
-#ifdef CONFIG_KEXEC
-void crash_register_spus(struct list_head *list);
-#else
-static inline void crash_register_spus(struct list_head *list)
-{
-}
-#endif
-
 extern void spu_invalidate_slbs(struct spu *spu);
 extern void spu_associate_mm(struct spu *spu, struct mm_struct *mm);
 int spu_64k_pages_available(void);
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/include/asm/topology.h linux-libre-2.6.38-gnu1/arch/powerpc/include/asm/topology.h
--- linux-libre-2.6.37-gnu1/arch/powerpc/include/asm/topology.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/include/asm/topology.h	2011-03-14 21:20:32.000000000 -0400
@@ -106,9 +106,22 @@ static inline void sysfs_remove_device_f
 						int nid)
 {
 }
-
 #endif /* CONFIG_NUMA */
 
+#if defined(CONFIG_NUMA) && defined(CONFIG_PPC_SPLPAR)
+extern int start_topology_update(void);
+extern int stop_topology_update(void);
+#else
+static inline int start_topology_update(void)
+{
+	return 0;
+}
+static inline int stop_topology_update(void)
+{
+	return 0;
+}
+#endif /* CONFIG_NUMA && CONFIG_PPC_SPLPAR */
+
 #include <asm-generic/topology.h>
 
 #ifdef CONFIG_SMP
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/include/asm/vdso_datapage.h linux-libre-2.6.38-gnu1/arch/powerpc/include/asm/vdso_datapage.h
--- linux-libre-2.6.37-gnu1/arch/powerpc/include/asm/vdso_datapage.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/include/asm/vdso_datapage.h	2011-03-14 21:20:32.000000000 -0400
@@ -116,9 +116,7 @@ struct vdso_data {
 
 #endif /* CONFIG_PPC64 */
 
-#ifdef __KERNEL__
 extern struct vdso_data *vdso_data;
-#endif
 
 #endif /* __ASSEMBLY__ */
 
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/Kconfig linux-libre-2.6.38-gnu1/arch/powerpc/Kconfig
--- linux-libre-2.6.37-gnu1/arch/powerpc/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -20,6 +20,9 @@ config WORD_SIZE
 config ARCH_PHYS_ADDR_T_64BIT
        def_bool PPC64 || PHYS_64BIT
 
+config ARCH_DMA_ADDR_T_64BIT
+	def_bool ARCH_PHYS_ADDR_T_64BIT
+
 config MMU
 	bool
 	default y
@@ -33,24 +36,12 @@ config GENERIC_TIME_VSYSCALL
 config GENERIC_CLOCKEVENTS
 	def_bool y
 
-config GENERIC_HARDIRQS
-	bool
-	default y
-
-config GENERIC_HARDIRQS_NO__DO_IRQ
-	bool
-	default y
-
 config HAVE_SETUP_PER_CPU_AREA
 	def_bool PPC64
 
 config NEED_PER_CPU_EMBED_FIRST_CHUNK
 	def_bool PPC64
 
-config IRQ_PER_CPU
-	bool
-	default y
-
 config NR_IRQS
 	int "Number of virtual interrupt numbers"
 	range 32 32768
@@ -116,7 +107,7 @@ config PPC
 	bool
 	default y
 	select OF
-	select OF_FLATTREE
+	select OF_EARLY_FLATTREE
 	select HAVE_FTRACE_MCOUNT_RECORD
 	select HAVE_DYNAMIC_FTRACE
 	select HAVE_FUNCTION_TRACER
@@ -140,6 +131,9 @@ config PPC
 	select HAVE_PERF_EVENTS
 	select HAVE_REGS_AND_STACK_ACCESS_API
 	select HAVE_HW_BREAKPOINT if PERF_EVENTS && PPC_BOOK3S_64
+	select HAVE_GENERIC_HARDIRQS
+	select HAVE_SPARSE_IRQ
+	select IRQ_PER_CPU
 
 config EARLY_PRINTK
 	bool
@@ -209,7 +203,7 @@ config ARCH_HIBERNATION_POSSIBLE
 config ARCH_SUSPEND_POSSIBLE
 	def_bool y
 	depends on ADB_PMU || PPC_EFIKA || PPC_LITE5200 || PPC_83xx || \
-		   PPC_85xx || PPC_86xx || PPC_PSERIES
+		   PPC_85xx || PPC_86xx || PPC_PSERIES || 44x || 40x
 
 config PPC_DCR_NATIVE
 	bool
@@ -389,19 +383,6 @@ config IRQ_ALL_CPUS
 	  CPU.  Generally saying Y is safe, although some problems have been
 	  reported with SMP Power Macintoshes with this option enabled.
 
-config SPARSE_IRQ
-	bool "Support sparse irq numbering"
-	default n
-	help
-	  This enables support for sparse irqs. This is useful for distro
-	  kernels that want to define a high CONFIG_NR_CPUS value but still
-	  want to have low kernel memory footprint on smaller machines.
-
-	  ( Sparse IRQs can also be beneficial on NUMA boxes, as they spread
-	    out the irq_desc[] array in a more NUMA-friendly way. )
-
-	  If you don't know what to do here, say N.
-
 config NUMA
 	bool "NUMA support"
 	depends on PPC64
@@ -595,13 +576,11 @@ config EXTRA_TARGETS
 
 	  If unsure, leave blank
 
-if !44x || BROKEN
 config ARCH_WANTS_FREEZER_CONTROL
 	def_bool y
 	depends on ADB_PMU
 
 source kernel/power/Kconfig
-endif
 
 config SECCOMP
 	bool "Enable seccomp to safely compute untrusted bytecode"
@@ -682,6 +661,15 @@ config FSL_PMC
 	  Freescale MPC85xx/MPC86xx power management controller support
 	  (suspend/resume). For MPC83xx see platforms/83xx/suspend.c
 
+config PPC4xx_CPM
+	bool
+	default y
+	depends on SUSPEND && (44x || 40x)
+	help
+	  PPC4xx Clock Power Management (CPM) support (suspend/resume).
+	  It also enables support for two different idle states (idle-wait
+	  and idle-doze).
+
 config 4xx_SOC
 	bool
 
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/kernel/asm-offsets.c linux-libre-2.6.38-gnu1/arch/powerpc/kernel/asm-offsets.c
--- linux-libre-2.6.37-gnu1/arch/powerpc/kernel/asm-offsets.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/kernel/asm-offsets.c	2011-03-14 21:20:32.000000000 -0400
@@ -209,7 +209,6 @@ int main(void)
 	DEFINE(RTASENTRY, offsetof(struct rtas_t, entry));
 
 	/* Interrupt register frame */
-	DEFINE(STACK_FRAME_OVERHEAD, STACK_FRAME_OVERHEAD);
 	DEFINE(INT_FRAME_SIZE, STACK_INT_FRAME_SIZE);
 	DEFINE(SWITCH_FRAME_SIZE, STACK_FRAME_OVERHEAD + sizeof(struct pt_regs));
 #ifdef CONFIG_PPC64
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/kernel/cpu_setup_6xx.S linux-libre-2.6.38-gnu1/arch/powerpc/kernel/cpu_setup_6xx.S
--- linux-libre-2.6.37-gnu1/arch/powerpc/kernel/cpu_setup_6xx.S	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/kernel/cpu_setup_6xx.S	2011-03-14 21:20:32.000000000 -0400
@@ -18,7 +18,7 @@
 #include <asm/mmu.h>
 
 _GLOBAL(__setup_cpu_603)
-	mflr	r4
+	mflr	r5
 BEGIN_MMU_FTR_SECTION
 	li	r10,0
 	mtspr	SPRN_SPRG_603_LRU,r10		/* init SW LRU tracking */
@@ -27,60 +27,60 @@ BEGIN_FTR_SECTION
 	bl	__init_fpu_registers
 END_FTR_SECTION_IFCLR(CPU_FTR_FPU_UNAVAILABLE)
 	bl	setup_common_caches
-	mtlr	r4
+	mtlr	r5
 	blr
 _GLOBAL(__setup_cpu_604)
-	mflr	r4
+	mflr	r5
 	bl	setup_common_caches
 	bl	setup_604_hid0
-	mtlr	r4
+	mtlr	r5
 	blr
 _GLOBAL(__setup_cpu_750)
-	mflr	r4
+	mflr	r5
 	bl	__init_fpu_registers
 	bl	setup_common_caches
 	bl	setup_750_7400_hid0
-	mtlr	r4
+	mtlr	r5
 	blr
 _GLOBAL(__setup_cpu_750cx)
-	mflr	r4
+	mflr	r5
 	bl	__init_fpu_registers
 	bl	setup_common_caches
 	bl	setup_750_7400_hid0
 	bl	setup_750cx
-	mtlr	r4
+	mtlr	r5
 	blr
 _GLOBAL(__setup_cpu_750fx)
-	mflr	r4
+	mflr	r5
 	bl	__init_fpu_registers
 	bl	setup_common_caches
 	bl	setup_750_7400_hid0
 	bl	setup_750fx
-	mtlr	r4
+	mtlr	r5
 	blr
 _GLOBAL(__setup_cpu_7400)
-	mflr	r4
+	mflr	r5
 	bl	__init_fpu_registers
 	bl	setup_7400_workarounds
 	bl	setup_common_caches
 	bl	setup_750_7400_hid0
-	mtlr	r4
+	mtlr	r5
 	blr
 _GLOBAL(__setup_cpu_7410)
-	mflr	r4
+	mflr	r5
 	bl	__init_fpu_registers
 	bl	setup_7410_workarounds
 	bl	setup_common_caches
 	bl	setup_750_7400_hid0
 	li	r3,0
 	mtspr	SPRN_L2CR2,r3
-	mtlr	r4
+	mtlr	r5
 	blr
 _GLOBAL(__setup_cpu_745x)
-	mflr	r4
+	mflr	r5
 	bl	setup_common_caches
 	bl	setup_745x_specifics
-	mtlr	r4
+	mtlr	r5
 	blr
 
 /* Enable caches for 603's, 604, 750 & 7400 */
@@ -194,10 +194,10 @@ setup_750cx:
 	cror	4*cr0+eq,4*cr0+eq,4*cr1+eq
 	cror	4*cr0+eq,4*cr0+eq,4*cr2+eq
 	bnelr
-	lwz	r6,CPU_SPEC_FEATURES(r5)
+	lwz	r6,CPU_SPEC_FEATURES(r4)
 	li	r7,CPU_FTR_CAN_NAP
 	andc	r6,r6,r7
-	stw	r6,CPU_SPEC_FEATURES(r5)
+	stw	r6,CPU_SPEC_FEATURES(r4)
 	blr
 
 /* 750fx specific
@@ -225,12 +225,12 @@ BEGIN_FTR_SECTION
 	andis.	r11,r11,L3CR_L3E@h
 	beq	1f
 END_FTR_SECTION_IFSET(CPU_FTR_L3CR)
-	lwz	r6,CPU_SPEC_FEATURES(r5)
+	lwz	r6,CPU_SPEC_FEATURES(r4)
 	andi.	r0,r6,CPU_FTR_L3_DISABLE_NAP
 	beq	1f
 	li	r7,CPU_FTR_CAN_NAP
 	andc	r6,r6,r7
-	stw	r6,CPU_SPEC_FEATURES(r5)
+	stw	r6,CPU_SPEC_FEATURES(r4)
 1:
 	mfspr	r11,SPRN_HID0
 
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/kernel/cpu_setup_fsl_booke.S linux-libre-2.6.38-gnu1/arch/powerpc/kernel/cpu_setup_fsl_booke.S
--- linux-libre-2.6.37-gnu1/arch/powerpc/kernel/cpu_setup_fsl_booke.S	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/kernel/cpu_setup_fsl_booke.S	2011-03-14 21:20:32.000000000 -0400
@@ -64,6 +64,12 @@ _GLOBAL(__setup_cpu_e500v2)
 	bl	__e500_icache_setup
 	bl	__e500_dcache_setup
 	bl	__setup_e500_ivors
+#ifdef CONFIG_RAPIDIO
+	/* Ensure that RFXE is set */
+	mfspr	r3,SPRN_HID1
+	oris	r3,r3,HID1_RFXE@h
+	mtspr	SPRN_HID1,r3
+#endif
 	mtlr	r4
 	blr
 _GLOBAL(__setup_cpu_e500mc)
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/kernel/cputable.c linux-libre-2.6.38-gnu1/arch/powerpc/kernel/cputable.c
--- linux-libre-2.6.37-gnu1/arch/powerpc/kernel/cputable.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/kernel/cputable.c	2011-03-14 21:20:32.000000000 -0400
@@ -116,7 +116,6 @@ static struct cpu_spec __initdata cpu_sp
 		.pmc_type		= PPC_PMC_IBM,
 		.oprofile_cpu_type	= "ppc64/power3",
 		.oprofile_type		= PPC_OPROFILE_RS64,
-		.machine_check		= machine_check_generic,
 		.platform		= "power3",
 	},
 	{	/* Power3+ */
@@ -132,7 +131,6 @@ static struct cpu_spec __initdata cpu_sp
 		.pmc_type		= PPC_PMC_IBM,
 		.oprofile_cpu_type	= "ppc64/power3",
 		.oprofile_type		= PPC_OPROFILE_RS64,
-		.machine_check		= machine_check_generic,
 		.platform		= "power3",
 	},
 	{	/* Northstar */
@@ -148,7 +146,6 @@ static struct cpu_spec __initdata cpu_sp
 		.pmc_type		= PPC_PMC_IBM,
 		.oprofile_cpu_type	= "ppc64/rs64",
 		.oprofile_type		= PPC_OPROFILE_RS64,
-		.machine_check		= machine_check_generic,
 		.platform		= "rs64",
 	},
 	{	/* Pulsar */
@@ -164,7 +161,6 @@ static struct cpu_spec __initdata cpu_sp
 		.pmc_type		= PPC_PMC_IBM,
 		.oprofile_cpu_type	= "ppc64/rs64",
 		.oprofile_type		= PPC_OPROFILE_RS64,
-		.machine_check		= machine_check_generic,
 		.platform		= "rs64",
 	},
 	{	/* I-star */
@@ -180,7 +176,6 @@ static struct cpu_spec __initdata cpu_sp
 		.pmc_type		= PPC_PMC_IBM,
 		.oprofile_cpu_type	= "ppc64/rs64",
 		.oprofile_type		= PPC_OPROFILE_RS64,
-		.machine_check		= machine_check_generic,
 		.platform		= "rs64",
 	},
 	{	/* S-star */
@@ -196,7 +191,6 @@ static struct cpu_spec __initdata cpu_sp
 		.pmc_type		= PPC_PMC_IBM,
 		.oprofile_cpu_type	= "ppc64/rs64",
 		.oprofile_type		= PPC_OPROFILE_RS64,
-		.machine_check		= machine_check_generic,
 		.platform		= "rs64",
 	},
 	{	/* Power4 */
@@ -212,7 +206,6 @@ static struct cpu_spec __initdata cpu_sp
 		.pmc_type		= PPC_PMC_IBM,
 		.oprofile_cpu_type	= "ppc64/power4",
 		.oprofile_type		= PPC_OPROFILE_POWER4,
-		.machine_check		= machine_check_generic,
 		.platform		= "power4",
 	},
 	{	/* Power4+ */
@@ -228,7 +221,6 @@ static struct cpu_spec __initdata cpu_sp
 		.pmc_type		= PPC_PMC_IBM,
 		.oprofile_cpu_type	= "ppc64/power4",
 		.oprofile_type		= PPC_OPROFILE_POWER4,
-		.machine_check		= machine_check_generic,
 		.platform		= "power4",
 	},
 	{	/* PPC970 */
@@ -247,7 +239,6 @@ static struct cpu_spec __initdata cpu_sp
 		.cpu_restore		= __restore_cpu_ppc970,
 		.oprofile_cpu_type	= "ppc64/970",
 		.oprofile_type		= PPC_OPROFILE_POWER4,
-		.machine_check		= machine_check_generic,
 		.platform		= "ppc970",
 	},
 	{	/* PPC970FX */
@@ -266,7 +257,6 @@ static struct cpu_spec __initdata cpu_sp
 		.cpu_restore		= __restore_cpu_ppc970,
 		.oprofile_cpu_type	= "ppc64/970",
 		.oprofile_type		= PPC_OPROFILE_POWER4,
-		.machine_check		= machine_check_generic,
 		.platform		= "ppc970",
 	},
 	{	/* PPC970MP DD1.0 - no DEEPNAP, use regular 970 init */
@@ -285,7 +275,6 @@ static struct cpu_spec __initdata cpu_sp
 		.cpu_restore		= __restore_cpu_ppc970,
 		.oprofile_cpu_type	= "ppc64/970MP",
 		.oprofile_type		= PPC_OPROFILE_POWER4,
-		.machine_check		= machine_check_generic,
 		.platform		= "ppc970",
 	},
 	{	/* PPC970MP */
@@ -304,7 +293,6 @@ static struct cpu_spec __initdata cpu_sp
 		.cpu_restore		= __restore_cpu_ppc970,
 		.oprofile_cpu_type	= "ppc64/970MP",
 		.oprofile_type		= PPC_OPROFILE_POWER4,
-		.machine_check		= machine_check_generic,
 		.platform		= "ppc970",
 	},
 	{	/* PPC970GX */
@@ -322,7 +310,6 @@ static struct cpu_spec __initdata cpu_sp
 		.cpu_setup		= __setup_cpu_ppc970,
 		.oprofile_cpu_type	= "ppc64/970",
 		.oprofile_type		= PPC_OPROFILE_POWER4,
-		.machine_check		= machine_check_generic,
 		.platform		= "ppc970",
 	},
 	{	/* Power5 GR */
@@ -343,7 +330,6 @@ static struct cpu_spec __initdata cpu_sp
 		 */
 		.oprofile_mmcra_sihv	= MMCRA_SIHV,
 		.oprofile_mmcra_sipr	= MMCRA_SIPR,
-		.machine_check		= machine_check_generic,
 		.platform		= "power5",
 	},
 	{	/* Power5++ */
@@ -360,7 +346,6 @@ static struct cpu_spec __initdata cpu_sp
 		.oprofile_type		= PPC_OPROFILE_POWER4,
 		.oprofile_mmcra_sihv	= MMCRA_SIHV,
 		.oprofile_mmcra_sipr	= MMCRA_SIPR,
-		.machine_check		= machine_check_generic,
 		.platform		= "power5+",
 	},
 	{	/* Power5 GS */
@@ -378,7 +363,6 @@ static struct cpu_spec __initdata cpu_sp
 		.oprofile_type		= PPC_OPROFILE_POWER4,
 		.oprofile_mmcra_sihv	= MMCRA_SIHV,
 		.oprofile_mmcra_sipr	= MMCRA_SIPR,
-		.machine_check		= machine_check_generic,
 		.platform		= "power5+",
 	},
 	{	/* POWER6 in P5+ mode; 2.04-compliant processor */
@@ -390,7 +374,6 @@ static struct cpu_spec __initdata cpu_sp
 		.mmu_features		= MMU_FTR_HPTE_TABLE,
 		.icache_bsize		= 128,
 		.dcache_bsize		= 128,
-		.machine_check		= machine_check_generic,
 		.oprofile_cpu_type	= "ppc64/ibm-compat-v1",
 		.oprofile_type		= PPC_OPROFILE_POWER4,
 		.platform		= "power5+",
@@ -413,7 +396,6 @@ static struct cpu_spec __initdata cpu_sp
 		.oprofile_mmcra_sipr	= POWER6_MMCRA_SIPR,
 		.oprofile_mmcra_clear	= POWER6_MMCRA_THRM |
 			POWER6_MMCRA_OTHER,
-		.machine_check		= machine_check_generic,
 		.platform		= "power6x",
 	},
 	{	/* 2.05-compliant processor, i.e. Power6 "architected" mode */
@@ -425,7 +407,6 @@ static struct cpu_spec __initdata cpu_sp
 		.mmu_features		= MMU_FTR_HPTE_TABLE,
 		.icache_bsize		= 128,
 		.dcache_bsize		= 128,
-		.machine_check		= machine_check_generic,
 		.oprofile_cpu_type	= "ppc64/ibm-compat-v1",
 		.oprofile_type		= PPC_OPROFILE_POWER4,
 		.platform		= "power6",
@@ -440,7 +421,6 @@ static struct cpu_spec __initdata cpu_sp
 			MMU_FTR_TLBIE_206,
 		.icache_bsize		= 128,
 		.dcache_bsize		= 128,
-		.machine_check		= machine_check_generic,
 		.oprofile_type		= PPC_OPROFILE_POWER4,
 		.oprofile_cpu_type	= "ppc64/ibm-compat-v1",
 		.platform		= "power7",
@@ -457,16 +437,26 @@ static struct cpu_spec __initdata cpu_sp
 		.dcache_bsize		= 128,
 		.num_pmcs		= 6,
 		.pmc_type		= PPC_PMC_IBM,
-		.cpu_setup		= __setup_cpu_power7,
-		.cpu_restore		= __restore_cpu_power7,
 		.oprofile_cpu_type	= "ppc64/power7",
 		.oprofile_type		= PPC_OPROFILE_POWER4,
-		.oprofile_mmcra_sihv	= POWER6_MMCRA_SIHV,
-		.oprofile_mmcra_sipr	= POWER6_MMCRA_SIPR,
-		.oprofile_mmcra_clear	= POWER6_MMCRA_THRM |
-			POWER6_MMCRA_OTHER,
 		.platform		= "power7",
 	},
+	{	/* Power7+ */
+		.pvr_mask		= 0xffff0000,
+		.pvr_value		= 0x004A0000,
+		.cpu_name		= "POWER7+ (raw)",
+		.cpu_features		= CPU_FTRS_POWER7,
+		.cpu_user_features	= COMMON_USER_POWER7,
+		.mmu_features		= MMU_FTR_HPTE_TABLE |
+			MMU_FTR_TLBIE_206,
+		.icache_bsize		= 128,
+		.dcache_bsize		= 128,
+		.num_pmcs		= 6,
+		.pmc_type		= PPC_PMC_IBM,
+		.oprofile_cpu_type	= "ppc64/power7",
+		.oprofile_type		= PPC_OPROFILE_POWER4,
+		.platform		= "power7+",
+	},
 	{	/* Cell Broadband Engine */
 		.pvr_mask		= 0xffff0000,
 		.pvr_value		= 0x00700000,
@@ -482,7 +472,6 @@ static struct cpu_spec __initdata cpu_sp
 		.pmc_type		= PPC_PMC_IBM,
 		.oprofile_cpu_type	= "ppc64/cell-be",
 		.oprofile_type		= PPC_OPROFILE_CELL,
-		.machine_check		= machine_check_generic,
 		.platform		= "ppc-cell-be",
 	},
 	{	/* PA Semi PA6T */
@@ -500,7 +489,6 @@ static struct cpu_spec __initdata cpu_sp
 		.cpu_restore		= __restore_cpu_pa6t,
 		.oprofile_cpu_type	= "ppc64/pa6t",
 		.oprofile_type		= PPC_OPROFILE_PA6T,
-		.machine_check		= machine_check_generic,
 		.platform		= "pa6t",
 	},
 	{	/* default match */
@@ -514,7 +502,6 @@ static struct cpu_spec __initdata cpu_sp
 		.dcache_bsize		= 128,
 		.num_pmcs		= 6,
 		.pmc_type		= PPC_PMC_IBM,
-		.machine_check		= machine_check_generic,
 		.platform		= "power4",
 	}
 #endif	/* CONFIG_PPC_BOOK3S_64 */
@@ -2089,8 +2076,8 @@ static void __init setup_cpu_spec(unsign
 	 * pointer on ppc64 and booke as we are running at 0 in real mode
 	 * on ppc64 and reloc_offset is always 0 on booke.
 	 */
-	if (s->cpu_setup) {
-		s->cpu_setup(offset, s);
+	if (t->cpu_setup) {
+		t->cpu_setup(offset, t);
 	}
 #endif /* CONFIG_PPC64 || CONFIG_BOOKE */
 }
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/kernel/crash.c linux-libre-2.6.38-gnu1/arch/powerpc/kernel/crash.c
--- linux-libre-2.6.37-gnu1/arch/powerpc/kernel/crash.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/kernel/crash.c	2011-03-14 21:20:32.000000000 -0400
@@ -48,7 +48,7 @@ int crashing_cpu = -1;
 static cpumask_t cpus_in_crash = CPU_MASK_NONE;
 cpumask_t cpus_in_sr = CPU_MASK_NONE;
 
-#define CRASH_HANDLER_MAX 2
+#define CRASH_HANDLER_MAX 3
 /* NULL terminated list of shutdown handles */
 static crash_shutdown_t crash_shutdown_handles[CRASH_HANDLER_MAX+1];
 static DEFINE_SPINLOCK(crash_handlers_lock);
@@ -125,7 +125,7 @@ static void crash_kexec_prepare_cpus(int
 	smp_wmb();
 
 	/*
-	 * FIXME: Until we will have the way to stop other CPUSs reliabally,
+	 * FIXME: Until we will have the way to stop other CPUs reliably,
 	 * the crash CPU will send an IPI and wait for other CPUs to
 	 * respond.
 	 * Delay of at least 10 seconds.
@@ -254,72 +254,6 @@ void crash_kexec_secondary(struct pt_reg
 	cpus_in_sr = CPU_MASK_NONE;
 }
 #endif
-#ifdef CONFIG_SPU_BASE
-
-#include <asm/spu.h>
-#include <asm/spu_priv1.h>
-
-struct crash_spu_info {
-	struct spu *spu;
-	u32 saved_spu_runcntl_RW;
-	u32 saved_spu_status_R;
-	u32 saved_spu_npc_RW;
-	u64 saved_mfc_sr1_RW;
-	u64 saved_mfc_dar;
-	u64 saved_mfc_dsisr;
-};
-
-#define CRASH_NUM_SPUS	16	/* Enough for current hardware */
-static struct crash_spu_info crash_spu_info[CRASH_NUM_SPUS];
-
-static void crash_kexec_stop_spus(void)
-{
-	struct spu *spu;
-	int i;
-	u64 tmp;
-
-	for (i = 0; i < CRASH_NUM_SPUS; i++) {
-		if (!crash_spu_info[i].spu)
-			continue;
-
-		spu = crash_spu_info[i].spu;
-
-		crash_spu_info[i].saved_spu_runcntl_RW =
-			in_be32(&spu->problem->spu_runcntl_RW);
-		crash_spu_info[i].saved_spu_status_R =
-			in_be32(&spu->problem->spu_status_R);
-		crash_spu_info[i].saved_spu_npc_RW =
-			in_be32(&spu->problem->spu_npc_RW);
-
-		crash_spu_info[i].saved_mfc_dar    = spu_mfc_dar_get(spu);
-		crash_spu_info[i].saved_mfc_dsisr  = spu_mfc_dsisr_get(spu);
-		tmp = spu_mfc_sr1_get(spu);
-		crash_spu_info[i].saved_mfc_sr1_RW = tmp;
-
-		tmp &= ~MFC_STATE1_MASTER_RUN_CONTROL_MASK;
-		spu_mfc_sr1_set(spu, tmp);
-
-		__delay(200);
-	}
-}
-
-void crash_register_spus(struct list_head *list)
-{
-	struct spu *spu;
-
-	list_for_each_entry(spu, list, full_list) {
-		if (WARN_ON(spu->number >= CRASH_NUM_SPUS))
-			continue;
-
-		crash_spu_info[spu->number].spu = spu;
-	}
-}
-
-#else
-static inline void crash_kexec_stop_spus(void)
-{
-}
-#endif /* CONFIG_SPU_BASE */
 
 /*
  * Register a function to be called on shutdown.  Only use this if you
@@ -439,8 +373,6 @@ void default_machine_crash_shutdown(stru
 	crash_shutdown_cpu = -1;
 	__debugger_fault_handler = old_handler;
 
-	crash_kexec_stop_spus();
-
 	if (ppc_md.kexec_cpu_down)
 		ppc_md.kexec_cpu_down(1, 0);
 }
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/kernel/crash_dump.c linux-libre-2.6.38-gnu1/arch/powerpc/kernel/crash_dump.c
--- linux-libre-2.6.37-gnu1/arch/powerpc/kernel/crash_dump.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/kernel/crash_dump.c	2011-03-14 21:20:32.000000000 -0400
@@ -19,6 +19,7 @@
 #include <asm/prom.h>
 #include <asm/firmware.h>
 #include <asm/uaccess.h>
+#include <asm/rtas.h>
 
 #ifdef DEBUG
 #include <asm/udbg.h>
@@ -141,3 +142,35 @@ ssize_t copy_oldmem_page(unsigned long p
 
 	return csize;
 }
+
+#ifdef CONFIG_PPC_RTAS
+/*
+ * The crashkernel region will almost always overlap the RTAS region, so
+ * we have to be careful when shrinking the crashkernel region.
+ */
+void crash_free_reserved_phys_range(unsigned long begin, unsigned long end)
+{
+	unsigned long addr;
+	const u32 *basep, *sizep;
+	unsigned int rtas_start = 0, rtas_end = 0;
+
+	basep = of_get_property(rtas.dev, "linux,rtas-base", NULL);
+	sizep = of_get_property(rtas.dev, "rtas-size", NULL);
+
+	if (basep && sizep) {
+		rtas_start = *basep;
+		rtas_end = *basep + *sizep;
+	}
+
+	for (addr = begin; addr < end; addr += PAGE_SIZE) {
+		/* Does this page overlap with the RTAS region? */
+		if (addr <= rtas_end && ((addr + PAGE_SIZE) > rtas_start))
+			continue;
+
+		ClearPageReserved(pfn_to_page(addr >> PAGE_SHIFT));
+		init_page_count(pfn_to_page(addr >> PAGE_SHIFT));
+		free_page((unsigned long)__va(addr));
+		totalram_pages++;
+	}
+}
+#endif
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/kernel/dma-iommu.c linux-libre-2.6.38-gnu1/arch/powerpc/kernel/dma-iommu.c
--- linux-libre-2.6.37-gnu1/arch/powerpc/kernel/dma-iommu.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/kernel/dma-iommu.c	2011-03-14 21:20:32.000000000 -0400
@@ -19,7 +19,7 @@ static void *dma_iommu_alloc_coherent(st
 				      dma_addr_t *dma_handle, gfp_t flag)
 {
 	return iommu_alloc_coherent(dev, get_iommu_table_base(dev), size,
-				    dma_handle, device_to_mask(dev), flag,
+				    dma_handle, dev->coherent_dma_mask, flag,
 				    dev_to_node(dev));
 }
 
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/kernel/e500-pmu.c linux-libre-2.6.38-gnu1/arch/powerpc/kernel/e500-pmu.c
--- linux-libre-2.6.37-gnu1/arch/powerpc/kernel/e500-pmu.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/kernel/e500-pmu.c	2011-03-14 21:20:32.000000000 -0400
@@ -126,4 +126,4 @@ static int init_e500_pmu(void)
 	return register_fsl_emb_pmu(&e500_pmu);
 }
 
-arch_initcall(init_e500_pmu);
+early_initcall(init_e500_pmu);
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/kernel/entry_32.S linux-libre-2.6.38-gnu1/arch/powerpc/kernel/entry_32.S
--- linux-libre-2.6.37-gnu1/arch/powerpc/kernel/entry_32.S	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/kernel/entry_32.S	2011-03-14 21:20:32.000000000 -0400
@@ -31,6 +31,7 @@
 #include <asm/asm-offsets.h>
 #include <asm/unistd.h>
 #include <asm/ftrace.h>
+#include <asm/ptrace.h>
 
 #undef SHOW_SYSCALLS
 #undef SHOW_SYSCALLS_TASK
@@ -879,7 +880,18 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_TYPE_4
 	 */
 	andi.	r10,r9,MSR_EE
 	beq	1f
+	/*
+	 * Since the ftrace irqsoff latency trace checks CALLER_ADDR1,
+	 * which is the stack frame here, we need to force a stack frame
+	 * in case we came from user space.
+	 */
+	stwu	r1,-32(r1)
+	mflr	r0
+	stw	r0,4(r1)
+	stwu	r1,-32(r1)
 	bl	trace_hardirqs_on
+	lwz	r1,0(r1)
+	lwz	r1,0(r1)
 	lwz	r9,_MSR(r1)
 1:
 #endif /* CONFIG_TRACE_IRQFLAGS */
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/kernel/exceptions-64s.S linux-libre-2.6.38-gnu1/arch/powerpc/kernel/exceptions-64s.S
--- linux-libre-2.6.37-gnu1/arch/powerpc/kernel/exceptions-64s.S	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/kernel/exceptions-64s.S	2011-03-14 21:20:32.000000000 -0400
@@ -13,6 +13,7 @@
  */
 
 #include <asm/exception-64s.h>
+#include <asm/ptrace.h>
 
 /*
  * We layout physical memory as follows:
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/kernel/fpu.S linux-libre-2.6.38-gnu1/arch/powerpc/kernel/fpu.S
--- linux-libre-2.6.37-gnu1/arch/powerpc/kernel/fpu.S	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/kernel/fpu.S	2011-03-14 21:20:32.000000000 -0400
@@ -23,6 +23,7 @@
 #include <asm/thread_info.h>
 #include <asm/ppc_asm.h>
 #include <asm/asm-offsets.h>
+#include <asm/ptrace.h>
 
 #ifdef CONFIG_VSX
 #define REST_32FPVSRS(n,c,base)						\
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/kernel/head_40x.S linux-libre-2.6.38-gnu1/arch/powerpc/kernel/head_40x.S
--- linux-libre-2.6.37-gnu1/arch/powerpc/kernel/head_40x.S	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/kernel/head_40x.S	2011-03-14 21:20:32.000000000 -0400
@@ -40,6 +40,7 @@
 #include <asm/thread_info.h>
 #include <asm/ppc_asm.h>
 #include <asm/asm-offsets.h>
+#include <asm/ptrace.h>
 
 /* As with the other PowerPC ports, it is expected that when code
  * execution begins here, the following registers contain valid, yet
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/kernel/head_44x.S linux-libre-2.6.38-gnu1/arch/powerpc/kernel/head_44x.S
--- linux-libre-2.6.37-gnu1/arch/powerpc/kernel/head_44x.S	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/kernel/head_44x.S	2011-03-14 21:20:32.000000000 -0400
@@ -37,6 +37,7 @@
 #include <asm/thread_info.h>
 #include <asm/ppc_asm.h>
 #include <asm/asm-offsets.h>
+#include <asm/ptrace.h>
 #include <asm/synch.h>
 #include "head_booke.h"
 
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/kernel/head_64.S linux-libre-2.6.38-gnu1/arch/powerpc/kernel/head_64.S
--- linux-libre-2.6.37-gnu1/arch/powerpc/kernel/head_64.S	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/kernel/head_64.S	2011-03-14 21:20:32.000000000 -0400
@@ -38,6 +38,7 @@
 #include <asm/page_64.h>
 #include <asm/irqflags.h>
 #include <asm/kvm_book3s_asm.h>
+#include <asm/ptrace.h>
 
 /* The physical memory is layed out such that the secondary processor
  * spin code sits at 0x0000...0x00ff. On server, the vectors follow
@@ -96,7 +97,7 @@ __secondary_hold_acknowledge:
 	.llong hvReleaseData-KERNELBASE
 #endif /* CONFIG_PPC_ISERIES */
 
-#ifdef CONFIG_CRASH_DUMP
+#ifdef CONFIG_RELOCATABLE
 	/* This flag is set to 1 by a loader if the kernel should run
 	 * at the loaded address instead of the linked address.  This
 	 * is used by kexec-tools to keep the the kdump kernel in the
@@ -384,12 +385,10 @@ _STATIC(__after_prom_start)
 	/* process relocations for the final address of the kernel */
 	lis	r25,PAGE_OFFSET@highest	/* compute virtual base of kernel */
 	sldi	r25,r25,32
-#ifdef CONFIG_CRASH_DUMP
 	lwz	r7,__run_at_load-_stext(r26)
-	cmplwi	cr0,r7,1	/* kdump kernel ? - stay where we are */
+	cmplwi	cr0,r7,1	/* flagged to stay where we are ? */
 	bne	1f
 	add	r25,r25,r26
-#endif
 1:	mr	r3,r25
 	bl	.relocate
 #endif
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/kernel/head_8xx.S linux-libre-2.6.38-gnu1/arch/powerpc/kernel/head_8xx.S
--- linux-libre-2.6.37-gnu1/arch/powerpc/kernel/head_8xx.S	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/kernel/head_8xx.S	2011-03-14 21:20:32.000000000 -0400
@@ -29,6 +29,7 @@
 #include <asm/thread_info.h>
 #include <asm/ppc_asm.h>
 #include <asm/asm-offsets.h>
+#include <asm/ptrace.h>
 
 /* Macro to make the code more readable. */
 #ifdef CONFIG_8xx_CPU6
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/kernel/head_fsl_booke.S linux-libre-2.6.38-gnu1/arch/powerpc/kernel/head_fsl_booke.S
--- linux-libre-2.6.37-gnu1/arch/powerpc/kernel/head_fsl_booke.S	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/kernel/head_fsl_booke.S	2011-03-14 21:20:32.000000000 -0400
@@ -41,6 +41,7 @@
 #include <asm/ppc_asm.h>
 #include <asm/asm-offsets.h>
 #include <asm/cache.h>
+#include <asm/ptrace.h>
 #include "head_booke.h"
 
 /* As with the other PowerPC ports, it is expected that when code
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/kernel/iommu.c linux-libre-2.6.38-gnu1/arch/powerpc/kernel/iommu.c
--- linux-libre-2.6.37-gnu1/arch/powerpc/kernel/iommu.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/kernel/iommu.c	2011-03-14 21:20:32.000000000 -0400
@@ -311,8 +311,9 @@ int iommu_map_sg(struct device *dev, str
 		/* Handle failure */
 		if (unlikely(entry == DMA_ERROR_CODE)) {
 			if (printk_ratelimit())
-				printk(KERN_INFO "iommu_alloc failed, tbl %p vaddr %lx"
-				       " npages %lx\n", tbl, vaddr, npages);
+				dev_info(dev, "iommu_alloc failed, tbl %p "
+					 "vaddr %lx npages %lu\n", tbl, vaddr,
+					 npages);
 			goto failure;
 		}
 
@@ -579,9 +580,9 @@ dma_addr_t iommu_map_page(struct device
 					 attrs);
 		if (dma_handle == DMA_ERROR_CODE) {
 			if (printk_ratelimit())  {
-				printk(KERN_INFO "iommu_alloc failed, "
-						"tbl %p vaddr %p npages %d\n",
-						tbl, vaddr, npages);
+				dev_info(dev, "iommu_alloc failed, tbl %p "
+					 "vaddr %p npages %d\n", tbl, vaddr,
+					 npages);
 			}
 		} else
 			dma_handle |= (uaddr & ~IOMMU_PAGE_MASK);
@@ -627,7 +628,8 @@ void *iommu_alloc_coherent(struct device
 	 * the tce tables.
 	 */
 	if (order >= IOMAP_MAX_ORDER) {
-		printk("iommu_alloc_consistent size too large: 0x%lx\n", size);
+		dev_info(dev, "iommu_alloc_consistent size too large: 0x%lx\n",
+			 size);
 		return NULL;
 	}
 
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/kernel/machine_kexec.c linux-libre-2.6.38-gnu1/arch/powerpc/kernel/machine_kexec.c
--- linux-libre-2.6.37-gnu1/arch/powerpc/kernel/machine_kexec.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/kernel/machine_kexec.c	2011-03-14 21:20:32.000000000 -0400
@@ -15,6 +15,7 @@
 #include <linux/memblock.h>
 #include <linux/of.h>
 #include <linux/irq.h>
+#include <linux/ftrace.h>
 
 #include <asm/machdep.h>
 #include <asm/prom.h>
@@ -44,10 +45,7 @@ void machine_kexec_mask_interrupts(void)
 
 void machine_crash_shutdown(struct pt_regs *regs)
 {
-	if (ppc_md.machine_crash_shutdown)
-		ppc_md.machine_crash_shutdown(regs);
-	else
-		default_machine_crash_shutdown(regs);
+	default_machine_crash_shutdown(regs);
 }
 
 /*
@@ -65,8 +63,6 @@ int machine_kexec_prepare(struct kimage
 
 void machine_kexec_cleanup(struct kimage *image)
 {
-	if (ppc_md.machine_kexec_cleanup)
-		ppc_md.machine_kexec_cleanup(image);
 }
 
 void arch_crash_save_vmcoreinfo(void)
@@ -87,11 +83,17 @@ void arch_crash_save_vmcoreinfo(void)
  */
 void machine_kexec(struct kimage *image)
 {
+	int save_ftrace_enabled;
+
+	save_ftrace_enabled = __ftrace_enabled_save();
+
 	if (ppc_md.machine_kexec)
 		ppc_md.machine_kexec(image);
 	else
 		default_machine_kexec(image);
 
+	__ftrace_enabled_restore(save_ftrace_enabled);
+
 	/* Fall back to normal restart if we're still alive. */
 	machine_restart(NULL);
 	for(;;);
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/kernel/Makefile linux-libre-2.6.38-gnu1/arch/powerpc/kernel/Makefile
--- linux-libre-2.6.37-gnu1/arch/powerpc/kernel/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/kernel/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -29,8 +29,10 @@ endif
 obj-y				:= cputable.o ptrace.o syscalls.o \
 				   irq.o align.o signal_32.o pmc.o vdso.o \
 				   init_task.o process.o systbl.o idle.o \
-				   signal.o sysfs.o cacheinfo.o
-obj-y				+= vdso32/
+				   signal.o sysfs.o cacheinfo.o time.o \
+				   prom.o traps.o setup-common.o \
+				   udbg.o misc.o io.o dma.o \
+				   misc_$(CONFIG_WORD_SIZE).o vdso32/
 obj-$(CONFIG_PPC64)		+= setup_64.o sys_ppc32.o \
 				   signal_64.o ptrace32.o \
 				   paca.o nvram_64.o firmware.o
@@ -80,9 +82,6 @@ extra-$(CONFIG_FSL_BOOKE)	:= head_fsl_bo
 extra-$(CONFIG_8xx)		:= head_8xx.o
 extra-y				+= vmlinux.lds
 
-obj-y				+= time.o prom.o traps.o setup-common.o \
-				   udbg.o misc.o io.o dma.o \
-				   misc_$(CONFIG_WORD_SIZE).o
 obj-$(CONFIG_PPC32)		+= entry_32.o setup_32.o
 obj-$(CONFIG_PPC64)		+= dma-iommu.o iommu.o
 obj-$(CONFIG_KGDB)		+= kgdb.o
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/kernel/misc_32.S linux-libre-2.6.38-gnu1/arch/powerpc/kernel/misc_32.S
--- linux-libre-2.6.37-gnu1/arch/powerpc/kernel/misc_32.S	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/kernel/misc_32.S	2011-03-14 21:20:32.000000000 -0400
@@ -30,6 +30,7 @@
 #include <asm/processor.h>
 #include <asm/kexec.h>
 #include <asm/bug.h>
+#include <asm/ptrace.h>
 
 	.text
 
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/kernel/misc_64.S linux-libre-2.6.38-gnu1/arch/powerpc/kernel/misc_64.S
--- linux-libre-2.6.37-gnu1/arch/powerpc/kernel/misc_64.S	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/kernel/misc_64.S	2011-03-14 21:20:32.000000000 -0400
@@ -25,6 +25,7 @@
 #include <asm/cputable.h>
 #include <asm/thread_info.h>
 #include <asm/kexec.h>
+#include <asm/ptrace.h>
 
 	.text
 
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/kernel/misc.S linux-libre-2.6.38-gnu1/arch/powerpc/kernel/misc.S
--- linux-libre-2.6.37-gnu1/arch/powerpc/kernel/misc.S	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/kernel/misc.S	2011-03-14 21:20:32.000000000 -0400
@@ -122,8 +122,3 @@ _GLOBAL(longjmp)
 	mtlr	r0
 	mr	r3,r4
 	blr
-
-_GLOBAL(__setup_cpu_power7)
-_GLOBAL(__restore_cpu_power7)
-	/* place holder */
-	blr
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/kernel/mpc7450-pmu.c linux-libre-2.6.38-gnu1/arch/powerpc/kernel/mpc7450-pmu.c
--- linux-libre-2.6.37-gnu1/arch/powerpc/kernel/mpc7450-pmu.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/kernel/mpc7450-pmu.c	2011-03-14 21:20:32.000000000 -0400
@@ -414,4 +414,4 @@ static int init_mpc7450_pmu(void)
 	return register_power_pmu(&mpc7450_pmu);
 }
 
-arch_initcall(init_mpc7450_pmu);
+early_initcall(init_mpc7450_pmu);
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/kernel/nvram_64.c linux-libre-2.6.38-gnu1/arch/powerpc/kernel/nvram_64.c
--- linux-libre-2.6.37-gnu1/arch/powerpc/kernel/nvram_64.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/kernel/nvram_64.c	2011-03-14 21:20:32.000000000 -0400
@@ -34,15 +34,26 @@
 
 #undef DEBUG_NVRAM
 
-static struct nvram_partition * nvram_part;
-static long nvram_error_log_index = -1;
-static long nvram_error_log_size = 0;
+#define NVRAM_HEADER_LEN	sizeof(struct nvram_header)
+#define NVRAM_BLOCK_LEN		NVRAM_HEADER_LEN
 
-struct err_log_info {
-	int error_type;
-	unsigned int seq_num;
+/* If change this size, then change the size of NVNAME_LEN */
+struct nvram_header {
+	unsigned char signature;
+	unsigned char checksum;
+	unsigned short length;
+	/* Terminating null required only for names < 12 chars. */
+	char name[12];
 };
 
+struct nvram_partition {
+	struct list_head partition;
+	struct nvram_header header;
+	unsigned int index;
+};
+
+static LIST_HEAD(nvram_partitions);
+
 static loff_t dev_nvram_llseek(struct file *file, loff_t offset, int origin)
 {
 	int size;
@@ -186,14 +197,12 @@ static struct miscdevice nvram_dev = {
 #ifdef DEBUG_NVRAM
 static void __init nvram_print_partitions(char * label)
 {
-	struct list_head * p;
 	struct nvram_partition * tmp_part;
 	
 	printk(KERN_WARNING "--------%s---------\n", label);
 	printk(KERN_WARNING "indx\t\tsig\tchks\tlen\tname\n");
-	list_for_each(p, &nvram_part->partition) {
-		tmp_part = list_entry(p, struct nvram_partition, partition);
-		printk(KERN_WARNING "%4d    \t%02x\t%02x\t%d\t%s\n",
+	list_for_each_entry(tmp_part, &nvram_partitions, partition) {
+		printk(KERN_WARNING "%4d    \t%02x\t%02x\t%d\t%12s\n",
 		       tmp_part->index, tmp_part->header.signature,
 		       tmp_part->header.checksum, tmp_part->header.length,
 		       tmp_part->header.name);
@@ -228,95 +237,113 @@ static unsigned char __init nvram_checks
 	return c_sum;
 }
 
-static int __init nvram_remove_os_partition(void)
+/**
+ * nvram_remove_partition - Remove one or more partitions in nvram
+ * @name: name of the partition to remove, or NULL for a
+ *        signature only match
+ * @sig: signature of the partition(s) to remove
+ */
+
+int __init nvram_remove_partition(const char *name, int sig)
 {
-	struct list_head *i;
-	struct list_head *j;
-	struct nvram_partition * part;
-	struct nvram_partition * cur_part;
+	struct nvram_partition *part, *prev, *tmp;
 	int rc;
 
-	list_for_each(i, &nvram_part->partition) {
-		part = list_entry(i, struct nvram_partition, partition);
-		if (part->header.signature != NVRAM_SIG_OS)
+	list_for_each_entry(part, &nvram_partitions, partition) {
+		if (part->header.signature != sig)
 			continue;
-		
-		/* Make os partition a free partition */
+		if (name && strncmp(name, part->header.name, 12))
+			continue;
+
+		/* Make partition a free partition */
 		part->header.signature = NVRAM_SIG_FREE;
-		sprintf(part->header.name, "wwwwwwwwwwww");
+		strncpy(part->header.name, "wwwwwwwwwwww", 12);
 		part->header.checksum = nvram_checksum(&part->header);
-
-		/* Merge contiguous free partitions backwards */
-		list_for_each_prev(j, &part->partition) {
-			cur_part = list_entry(j, struct nvram_partition, partition);
-			if (cur_part == nvram_part || cur_part->header.signature != NVRAM_SIG_FREE) {
-				break;
-			}
-			
-			part->header.length += cur_part->header.length;
-			part->header.checksum = nvram_checksum(&part->header);
-			part->index = cur_part->index;
-
-			list_del(&cur_part->partition);
-			kfree(cur_part);
-			j = &part->partition; /* fixup our loop */
-		}
-		
-		/* Merge contiguous free partitions forwards */
-		list_for_each(j, &part->partition) {
-			cur_part = list_entry(j, struct nvram_partition, partition);
-			if (cur_part == nvram_part || cur_part->header.signature != NVRAM_SIG_FREE) {
-				break;
-			}
-
-			part->header.length += cur_part->header.length;
-			part->header.checksum = nvram_checksum(&part->header);
-
-			list_del(&cur_part->partition);
-			kfree(cur_part);
-			j = &part->partition; /* fixup our loop */
-		}
-		
 		rc = nvram_write_header(part);
 		if (rc <= 0) {
-			printk(KERN_ERR "nvram_remove_os_partition: nvram_write failed (%d)\n", rc);
+			printk(KERN_ERR "nvram_remove_partition: nvram_write failed (%d)\n", rc);
 			return rc;
 		}
+	}
 
+	/* Merge contiguous ones */
+	prev = NULL;
+	list_for_each_entry_safe(part, tmp, &nvram_partitions, partition) {
+		if (part->header.signature != NVRAM_SIG_FREE) {
+			prev = NULL;
+			continue;
+		}
+		if (prev) {
+			prev->header.length += part->header.length;
+			prev->header.checksum = nvram_checksum(&part->header);
+			rc = nvram_write_header(part);
+			if (rc <= 0) {
+				printk(KERN_ERR "nvram_remove_partition: nvram_write failed (%d)\n", rc);
+				return rc;
+			}
+			list_del(&part->partition);
+			kfree(part);
+		} else
+			prev = part;
 	}
 	
 	return 0;
 }
 
-/* nvram_create_os_partition
+/**
+ * nvram_create_partition - Create a partition in nvram
+ * @name: name of the partition to create
+ * @sig: signature of the partition to create
+ * @req_size: size of data to allocate in bytes
+ * @min_size: minimum acceptable size (0 means req_size)
  *
- * Create a OS linux partition to buffer error logs.
- * Will create a partition starting at the first free
- * space found if space has enough room.
+ * Returns a negative error code or a positive nvram index
+ * of the beginning of the data area of the newly created
+ * partition. If you provided a min_size smaller than req_size
+ * you need to query for the actual size yourself after the
+ * call using nvram_partition_get_size().
  */
-static int __init nvram_create_os_partition(void)
+loff_t __init nvram_create_partition(const char *name, int sig,
+				     int req_size, int min_size)
 {
 	struct nvram_partition *part;
 	struct nvram_partition *new_part;
 	struct nvram_partition *free_part = NULL;
-	int seq_init[2] = { 0, 0 };
+	static char nv_init_vals[16];
 	loff_t tmp_index;
 	long size = 0;
 	int rc;
-	
+
+	/* Convert sizes from bytes to blocks */
+	req_size = _ALIGN_UP(req_size, NVRAM_BLOCK_LEN) / NVRAM_BLOCK_LEN;
+	min_size = _ALIGN_UP(min_size, NVRAM_BLOCK_LEN) / NVRAM_BLOCK_LEN;
+
+	/* If no minimum size specified, make it the same as the
+	 * requested size
+	 */
+	if (min_size == 0)
+		min_size = req_size;
+	if (min_size > req_size)
+		return -EINVAL;
+
+	/* Now add one block to each for the header */
+	req_size += 1;
+	min_size += 1;
+
 	/* Find a free partition that will give us the maximum needed size 
 	   If can't find one that will give us the minimum size needed */
-	list_for_each_entry(part, &nvram_part->partition, partition) {
+	list_for_each_entry(part, &nvram_partitions, partition) {
 		if (part->header.signature != NVRAM_SIG_FREE)
 			continue;
 
-		if (part->header.length >= NVRAM_MAX_REQ) {
-			size = NVRAM_MAX_REQ;
+		if (part->header.length >= req_size) {
+			size = req_size;
 			free_part = part;
 			break;
 		}
-		if (!size && part->header.length >= NVRAM_MIN_REQ) {
-			size = NVRAM_MIN_REQ;
+		if (part->header.length > size &&
+		    part->header.length >= min_size) {
+			size = part->header.length;
 			free_part = part;
 		}
 	}
@@ -326,136 +353,95 @@ static int __init nvram_create_os_partit
 	/* Create our OS partition */
 	new_part = kmalloc(sizeof(*new_part), GFP_KERNEL);
 	if (!new_part) {
-		printk(KERN_ERR "nvram_create_os_partition: kmalloc failed\n");
+		pr_err("nvram_create_os_partition: kmalloc failed\n");
 		return -ENOMEM;
 	}
 
 	new_part->index = free_part->index;
-	new_part->header.signature = NVRAM_SIG_OS;
+	new_part->header.signature = sig;
 	new_part->header.length = size;
-	strcpy(new_part->header.name, "ppc64,linux");
+	strncpy(new_part->header.name, name, 12);
 	new_part->header.checksum = nvram_checksum(&new_part->header);
 
 	rc = nvram_write_header(new_part);
 	if (rc <= 0) {
-		printk(KERN_ERR "nvram_create_os_partition: nvram_write_header "
-				"failed (%d)\n", rc);
-		return rc;
-	}
-
-	/* make sure and initialize to zero the sequence number and the error
-	   type logged */
-	tmp_index = new_part->index + NVRAM_HEADER_LEN;
-	rc = ppc_md.nvram_write((char *)&seq_init, sizeof(seq_init), &tmp_index);
-	if (rc <= 0) {
-		printk(KERN_ERR "nvram_create_os_partition: nvram_write "
+		pr_err("nvram_create_os_partition: nvram_write_header "
 		       "failed (%d)\n", rc);
 		return rc;
 	}
-	
-	nvram_error_log_index = new_part->index + NVRAM_HEADER_LEN;
-	nvram_error_log_size = ((part->header.length - 1) *
-				NVRAM_BLOCK_LEN) - sizeof(struct err_log_info);
-	
 	list_add_tail(&new_part->partition, &free_part->partition);
 
-	if (free_part->header.length <= size) {
+	/* Adjust or remove the partition we stole the space from */
+	if (free_part->header.length > size) {
+		free_part->index += size * NVRAM_BLOCK_LEN;
+		free_part->header.length -= size;
+		free_part->header.checksum = nvram_checksum(&free_part->header);
+		rc = nvram_write_header(free_part);
+		if (rc <= 0) {
+			pr_err("nvram_create_os_partition: nvram_write_header "
+			       "failed (%d)\n", rc);
+			return rc;
+		}
+	} else {
 		list_del(&free_part->partition);
 		kfree(free_part);
-		return 0;
 	} 
 
-	/* Adjust the partition we stole the space from */
-	free_part->index += size * NVRAM_BLOCK_LEN;
-	free_part->header.length -= size;
-	free_part->header.checksum = nvram_checksum(&free_part->header);
-	
-	rc = nvram_write_header(free_part);
-	if (rc <= 0) {
-		printk(KERN_ERR "nvram_create_os_partition: nvram_write_header "
-		       "failed (%d)\n", rc);
-		return rc;
+	/* Clear the new partition */
+	for (tmp_index = new_part->index + NVRAM_HEADER_LEN;
+	     tmp_index <  ((size - 1) * NVRAM_BLOCK_LEN);
+	     tmp_index += NVRAM_BLOCK_LEN) {
+		rc = ppc_md.nvram_write(nv_init_vals, NVRAM_BLOCK_LEN, &tmp_index);
+		if (rc <= 0) {
+			pr_err("nvram_create_partition: nvram_write failed (%d)\n", rc);
+			return rc;
+		}
 	}
-
-	return 0;
+	
+	return new_part->index + NVRAM_HEADER_LEN;
 }
 
-
-/* nvram_setup_partition
- *
- * This will setup the partition we need for buffering the
- * error logs and cleanup partitions if needed.
- *
- * The general strategy is the following:
- * 1.) If there is ppc64,linux partition large enough then use it.
- * 2.) If there is not a ppc64,linux partition large enough, search
- * for a free partition that is large enough.
- * 3.) If there is not a free partition large enough remove 
- * _all_ OS partitions and consolidate the space.
- * 4.) Will first try getting a chunk that will satisfy the maximum
- * error log size (NVRAM_MAX_REQ).
- * 5.) If the max chunk cannot be allocated then try finding a chunk
- * that will satisfy the minum needed (NVRAM_MIN_REQ).
+/**
+ * nvram_get_partition_size - Get the data size of an nvram partition
+ * @data_index: This is the offset of the start of the data of
+ *              the partition. The same value that is returned by
+ *              nvram_create_partition().
  */
-static int __init nvram_setup_partition(void)
+int nvram_get_partition_size(loff_t data_index)
 {
-	struct list_head * p;
-	struct nvram_partition * part;
-	int rc;
-
-	/* For now, we don't do any of this on pmac, until I
-	 * have figured out if it's worth killing some unused stuffs
-	 * in our nvram, as Apple defined partitions use pretty much
-	 * all of the space
-	 */
-	if (machine_is(powermac))
-		return -ENOSPC;
+	struct nvram_partition *part;
+	
+	list_for_each_entry(part, &nvram_partitions, partition) {
+		if (part->index + NVRAM_HEADER_LEN == data_index)
+			return (part->header.length - 1) * NVRAM_BLOCK_LEN;
+	}
+	return -1;
+}
 
-	/* see if we have an OS partition that meets our needs.
-	   will try getting the max we need.  If not we'll delete
-	   partitions and try again. */
-	list_for_each(p, &nvram_part->partition) {
-		part = list_entry(p, struct nvram_partition, partition);
-		if (part->header.signature != NVRAM_SIG_OS)
-			continue;
 
-		if (strcmp(part->header.name, "ppc64,linux"))
-			continue;
+/**
+ * nvram_find_partition - Find an nvram partition by signature and name
+ * @name: Name of the partition or NULL for any name
+ * @sig: Signature to test against
+ * @out_size: if non-NULL, returns the size of the data part of the partition
+ */
+loff_t nvram_find_partition(const char *name, int sig, int *out_size)
+{
+	struct nvram_partition *p;
 
-		if (part->header.length >= NVRAM_MIN_REQ) {
-			/* found our partition */
-			nvram_error_log_index = part->index + NVRAM_HEADER_LEN;
-			nvram_error_log_size = ((part->header.length - 1) *
-						NVRAM_BLOCK_LEN) - sizeof(struct err_log_info);
-			return 0;
+	list_for_each_entry(p, &nvram_partitions, partition) {
+		if (p->header.signature == sig &&
+		    (!name || !strncmp(p->header.name, name, 12))) {
+			if (out_size)
+				*out_size = (p->header.length - 1) *
+					NVRAM_BLOCK_LEN;
+			return p->index + NVRAM_HEADER_LEN;
 		}
 	}
-	
-	/* try creating a partition with the free space we have */
-	rc = nvram_create_os_partition();
-	if (!rc) {
-		return 0;
-	}
-		
-	/* need to free up some space */
-	rc = nvram_remove_os_partition();
-	if (rc) {
-		return rc;
-	}
-	
-	/* create a partition in this new space */
-	rc = nvram_create_os_partition();
-	if (rc) {
-		printk(KERN_ERR "nvram_create_os_partition: Could not find a "
-		       "NVRAM partition large enough\n");
-		return rc;
-	}
-	
 	return 0;
 }
 
-
-static int __init nvram_scan_partitions(void)
+int __init nvram_scan_partitions(void)
 {
 	loff_t cur_index = 0;
 	struct nvram_header phead;
@@ -465,7 +451,7 @@ static int __init nvram_scan_partitions(
 	int total_size;
 	int err;
 
-	if (ppc_md.nvram_size == NULL)
+	if (ppc_md.nvram_size == NULL || ppc_md.nvram_size() <= 0)
 		return -ENODEV;
 	total_size = ppc_md.nvram_size();
 	
@@ -512,12 +498,16 @@ static int __init nvram_scan_partitions(
 		
 		memcpy(&tmp_part->header, &phead, NVRAM_HEADER_LEN);
 		tmp_part->index = cur_index;
-		list_add_tail(&tmp_part->partition, &nvram_part->partition);
+		list_add_tail(&tmp_part->partition, &nvram_partitions);
 		
 		cur_index += phead.length * NVRAM_BLOCK_LEN;
 	}
 	err = 0;
 
+#ifdef DEBUG_NVRAM
+	nvram_print_partitions("NVRAM Partitions");
+#endif
+
  out:
 	kfree(header);
 	return err;
@@ -525,9 +515,10 @@ static int __init nvram_scan_partitions(
 
 static int __init nvram_init(void)
 {
-	int error;
 	int rc;
 	
+	BUILD_BUG_ON(NVRAM_BLOCK_LEN != 16);
+
 	if (ppc_md.nvram_size == NULL || ppc_md.nvram_size() <= 0)
 		return  -ENODEV;
 
@@ -537,29 +528,6 @@ static int __init nvram_init(void)
 		return rc;
 	}
   	
-  	/* initialize our anchor for the nvram partition list */
-  	nvram_part = kmalloc(sizeof(struct nvram_partition), GFP_KERNEL);
-  	if (!nvram_part) {
-  		printk(KERN_ERR "nvram_init: Failed kmalloc\n");
-  		return -ENOMEM;
-  	}
-  	INIT_LIST_HEAD(&nvram_part->partition);
-  
-  	/* Get all the NVRAM partitions */
-  	error = nvram_scan_partitions();
-  	if (error) {
-  		printk(KERN_ERR "nvram_init: Failed nvram_scan_partitions\n");
-  		return error;
-  	}
-  		
-  	if(nvram_setup_partition()) 
-  		printk(KERN_WARNING "nvram_init: Could not find nvram partition"
-  		       " for nvram buffered error logging.\n");
-  
-#ifdef DEBUG_NVRAM
-	nvram_print_partitions("NVRAM Partitions");
-#endif
-
   	return rc;
 }
 
@@ -568,135 +536,6 @@ void __exit nvram_cleanup(void)
         misc_deregister( &nvram_dev );
 }
 
-
-#ifdef CONFIG_PPC_PSERIES
-
-/* nvram_write_error_log
- *
- * We need to buffer the error logs into nvram to ensure that we have
- * the failure information to decode.  If we have a severe error there
- * is no way to guarantee that the OS or the machine is in a state to
- * get back to user land and write the error to disk.  For example if
- * the SCSI device driver causes a Machine Check by writing to a bad
- * IO address, there is no way of guaranteeing that the device driver
- * is in any state that is would also be able to write the error data
- * captured to disk, thus we buffer it in NVRAM for analysis on the
- * next boot.
- *
- * In NVRAM the partition containing the error log buffer will looks like:
- * Header (in bytes):
- * +-----------+----------+--------+------------+------------------+
- * | signature | checksum | length | name       | data             |
- * |0          |1         |2      3|4         15|16        length-1|
- * +-----------+----------+--------+------------+------------------+
- *
- * The 'data' section would look like (in bytes):
- * +--------------+------------+-----------------------------------+
- * | event_logged | sequence # | error log                         |
- * |0            3|4          7|8            nvram_error_log_size-1|
- * +--------------+------------+-----------------------------------+
- *
- * event_logged: 0 if event has not been logged to syslog, 1 if it has
- * sequence #: The unique sequence # for each event. (until it wraps)
- * error log: The error log from event_scan
- */
-int nvram_write_error_log(char * buff, int length,
-                          unsigned int err_type, unsigned int error_log_cnt)
-{
-	int rc;
-	loff_t tmp_index;
-	struct err_log_info info;
-	
-	if (nvram_error_log_index == -1) {
-		return -ESPIPE;
-	}
-
-	if (length > nvram_error_log_size) {
-		length = nvram_error_log_size;
-	}
-
-	info.error_type = err_type;
-	info.seq_num = error_log_cnt;
-
-	tmp_index = nvram_error_log_index;
-
-	rc = ppc_md.nvram_write((char *)&info, sizeof(struct err_log_info), &tmp_index);
-	if (rc <= 0) {
-		printk(KERN_ERR "nvram_write_error_log: Failed nvram_write (%d)\n", rc);
-		return rc;
-	}
-
-	rc = ppc_md.nvram_write(buff, length, &tmp_index);
-	if (rc <= 0) {
-		printk(KERN_ERR "nvram_write_error_log: Failed nvram_write (%d)\n", rc);
-		return rc;
-	}
-	
-	return 0;
-}
-
-/* nvram_read_error_log
- *
- * Reads nvram for error log for at most 'length'
- */
-int nvram_read_error_log(char * buff, int length,
-                         unsigned int * err_type, unsigned int * error_log_cnt)
-{
-	int rc;
-	loff_t tmp_index;
-	struct err_log_info info;
-	
-	if (nvram_error_log_index == -1)
-		return -1;
-
-	if (length > nvram_error_log_size)
-		length = nvram_error_log_size;
-
-	tmp_index = nvram_error_log_index;
-
-	rc = ppc_md.nvram_read((char *)&info, sizeof(struct err_log_info), &tmp_index);
-	if (rc <= 0) {
-		printk(KERN_ERR "nvram_read_error_log: Failed nvram_read (%d)\n", rc);
-		return rc;
-	}
-
-	rc = ppc_md.nvram_read(buff, length, &tmp_index);
-	if (rc <= 0) {
-		printk(KERN_ERR "nvram_read_error_log: Failed nvram_read (%d)\n", rc);
-		return rc;
-	}
-
-	*error_log_cnt = info.seq_num;
-	*err_type = info.error_type;
-
-	return 0;
-}
-
-/* This doesn't actually zero anything, but it sets the event_logged
- * word to tell that this event is safely in syslog.
- */
-int nvram_clear_error_log(void)
-{
-	loff_t tmp_index;
-	int clear_word = ERR_FLAG_ALREADY_LOGGED;
-	int rc;
-
-	if (nvram_error_log_index == -1)
-		return -1;
-
-	tmp_index = nvram_error_log_index;
-	
-	rc = ppc_md.nvram_write((char *)&clear_word, sizeof(int), &tmp_index);
-	if (rc <= 0) {
-		printk(KERN_ERR "nvram_clear_error_log: Failed nvram_write (%d)\n", rc);
-		return rc;
-	}
-
-	return 0;
-}
-
-#endif /* CONFIG_PPC_PSERIES */
-
 module_init(nvram_init);
 module_exit(nvram_cleanup);
 MODULE_LICENSE("GPL");
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/kernel/paca.c linux-libre-2.6.38-gnu1/arch/powerpc/kernel/paca.c
--- linux-libre-2.6.37-gnu1/arch/powerpc/kernel/paca.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/kernel/paca.c	2011-03-14 21:20:32.000000000 -0400
@@ -27,20 +27,6 @@ extern unsigned long __toc_start;
 #ifdef CONFIG_PPC_BOOK3S
 
 /*
- * We only have to have statically allocated lppaca structs on
- * legacy iSeries, which supports at most 64 cpus.
- */
-#ifdef CONFIG_PPC_ISERIES
-#if NR_CPUS < 64
-#define NR_LPPACAS	NR_CPUS
-#else
-#define NR_LPPACAS	64
-#endif
-#else /* not iSeries */
-#define NR_LPPACAS	1
-#endif
-
-/*
  * The structure which the hypervisor knows about - this structure
  * should not cross a page boundary.  The vpa_init/register_vpa call
  * is now known to fail if the lppaca structure crosses a page
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/kernel/pci_64.c linux-libre-2.6.38-gnu1/arch/powerpc/kernel/pci_64.c
--- linux-libre-2.6.37-gnu1/arch/powerpc/kernel/pci_64.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/kernel/pci_64.c	2011-03-14 21:20:32.000000000 -0400
@@ -193,8 +193,7 @@ int __devinit pcibios_map_io_space(struc
 	hose->io_resource.start += io_virt_offset;
 	hose->io_resource.end += io_virt_offset;
 
-	pr_debug("  hose->io_resource=0x%016llx...0x%016llx\n",
-		 hose->io_resource.start, hose->io_resource.end);
+	pr_debug("  hose->io_resource=%pR\n", &hose->io_resource);
 
 	return 0;
 }
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/kernel/perf_event.c linux-libre-2.6.38-gnu1/arch/powerpc/kernel/perf_event.c
--- linux-libre-2.6.37-gnu1/arch/powerpc/kernel/perf_event.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/kernel/perf_event.c	2011-03-14 21:20:32.000000000 -0400
@@ -1212,6 +1212,7 @@ static void record_and_restart(struct pe
 			if (left <= 0)
 				left = period;
 			record = 1;
+			event->hw.last_period = event->hw.sample_period;
 		}
 		if (left < 0x80000000LL)
 			val = 0x80000000LL - left;
@@ -1379,7 +1380,7 @@ int register_power_pmu(struct power_pmu
 		freeze_events_kernel = MMCR0_FCHV;
 #endif /* CONFIG_PPC64 */
 
-	perf_pmu_register(&power_pmu);
+	perf_pmu_register(&power_pmu, "cpu", PERF_TYPE_RAW);
 	perf_cpu_notifier(power_pmu_notifier);
 
 	return 0;
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/kernel/perf_event_fsl_emb.c linux-libre-2.6.38-gnu1/arch/powerpc/kernel/perf_event_fsl_emb.c
--- linux-libre-2.6.37-gnu1/arch/powerpc/kernel/perf_event_fsl_emb.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/kernel/perf_event_fsl_emb.c	2011-03-14 21:20:32.000000000 -0400
@@ -596,6 +596,7 @@ static void record_and_restart(struct pe
 			if (left <= 0)
 				left = period;
 			record = 1;
+			event->hw.last_period = event->hw.sample_period;
 		}
 		if (left < 0x80000000LL)
 			val = 0x80000000LL - left;
@@ -681,7 +682,7 @@ int register_fsl_emb_pmu(struct fsl_emb_
 	pr_info("%s performance monitor hardware support registered\n",
 		pmu->name);
 
-	perf_pmu_register(&fsl_emb_pmu);
+	perf_pmu_register(&fsl_emb_pmu, "cpu", PERF_TYPE_RAW);
 
 	return 0;
 }
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/kernel/power4-pmu.c linux-libre-2.6.38-gnu1/arch/powerpc/kernel/power4-pmu.c
--- linux-libre-2.6.37-gnu1/arch/powerpc/kernel/power4-pmu.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/kernel/power4-pmu.c	2011-03-14 21:20:32.000000000 -0400
@@ -613,4 +613,4 @@ static int init_power4_pmu(void)
 	return register_power_pmu(&power4_pmu);
 }
 
-arch_initcall(init_power4_pmu);
+early_initcall(init_power4_pmu);
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/kernel/power5-pmu.c linux-libre-2.6.38-gnu1/arch/powerpc/kernel/power5-pmu.c
--- linux-libre-2.6.37-gnu1/arch/powerpc/kernel/power5-pmu.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/kernel/power5-pmu.c	2011-03-14 21:20:32.000000000 -0400
@@ -621,4 +621,4 @@ static int init_power5_pmu(void)
 	return register_power_pmu(&power5_pmu);
 }
 
-arch_initcall(init_power5_pmu);
+early_initcall(init_power5_pmu);
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/kernel/power5+-pmu.c linux-libre-2.6.38-gnu1/arch/powerpc/kernel/power5+-pmu.c
--- linux-libre-2.6.37-gnu1/arch/powerpc/kernel/power5+-pmu.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/kernel/power5+-pmu.c	2011-03-14 21:20:32.000000000 -0400
@@ -682,4 +682,4 @@ static int init_power5p_pmu(void)
 	return register_power_pmu(&power5p_pmu);
 }
 
-arch_initcall(init_power5p_pmu);
+early_initcall(init_power5p_pmu);
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/kernel/power6-pmu.c linux-libre-2.6.38-gnu1/arch/powerpc/kernel/power6-pmu.c
--- linux-libre-2.6.37-gnu1/arch/powerpc/kernel/power6-pmu.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/kernel/power6-pmu.c	2011-03-14 21:20:32.000000000 -0400
@@ -544,4 +544,4 @@ static int init_power6_pmu(void)
 	return register_power_pmu(&power6_pmu);
 }
 
-arch_initcall(init_power6_pmu);
+early_initcall(init_power6_pmu);
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/kernel/power7-pmu.c linux-libre-2.6.38-gnu1/arch/powerpc/kernel/power7-pmu.c
--- linux-libre-2.6.37-gnu1/arch/powerpc/kernel/power7-pmu.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/kernel/power7-pmu.c	2011-03-14 21:20:32.000000000 -0400
@@ -369,4 +369,4 @@ static int init_power7_pmu(void)
 	return register_power_pmu(&power7_pmu);
 }
 
-arch_initcall(init_power7_pmu);
+early_initcall(init_power7_pmu);
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/kernel/ppc970-pmu.c linux-libre-2.6.38-gnu1/arch/powerpc/kernel/ppc970-pmu.c
--- linux-libre-2.6.37-gnu1/arch/powerpc/kernel/ppc970-pmu.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/kernel/ppc970-pmu.c	2011-03-14 21:20:32.000000000 -0400
@@ -494,4 +494,4 @@ static int init_ppc970_pmu(void)
 	return register_power_pmu(&ppc970_pmu);
 }
 
-arch_initcall(init_ppc970_pmu);
+early_initcall(init_ppc970_pmu);
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/kernel/ppc_ksyms.c linux-libre-2.6.38-gnu1/arch/powerpc/kernel/ppc_ksyms.c
--- linux-libre-2.6.37-gnu1/arch/powerpc/kernel/ppc_ksyms.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/kernel/ppc_ksyms.c	2011-03-14 21:20:32.000000000 -0400
@@ -186,3 +186,10 @@ EXPORT_SYMBOL(__mtdcr);
 EXPORT_SYMBOL(__mfdcr);
 #endif
 EXPORT_SYMBOL(empty_zero_page);
+
+#ifdef CONFIG_PPC64
+EXPORT_SYMBOL(__arch_hweight8);
+EXPORT_SYMBOL(__arch_hweight16);
+EXPORT_SYMBOL(__arch_hweight32);
+EXPORT_SYMBOL(__arch_hweight64);
+#endif
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/kernel/ppc_save_regs.S linux-libre-2.6.38-gnu1/arch/powerpc/kernel/ppc_save_regs.S
--- linux-libre-2.6.37-gnu1/arch/powerpc/kernel/ppc_save_regs.S	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/kernel/ppc_save_regs.S	2011-03-14 21:20:32.000000000 -0400
@@ -11,6 +11,7 @@
 #include <asm/processor.h>
 #include <asm/ppc_asm.h>
 #include <asm/asm-offsets.h>
+#include <asm/ptrace.h>
 
 /*
  * Grab the register values as they are now.
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/kernel/process.c linux-libre-2.6.38-gnu1/arch/powerpc/kernel/process.c
--- linux-libre-2.6.37-gnu1/arch/powerpc/kernel/process.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/kernel/process.c	2011-03-14 21:20:32.000000000 -0400
@@ -353,6 +353,7 @@ static void switch_booke_debug_regs(stru
 			prime_debug_regs(new_thread);
 }
 #else	/* !CONFIG_PPC_ADV_DEBUG_REGS */
+#ifndef CONFIG_HAVE_HW_BREAKPOINT
 static void set_debug_reg_defaults(struct thread_struct *thread)
 {
 	if (thread->dabr) {
@@ -360,6 +361,7 @@ static void set_debug_reg_defaults(struc
 		set_dabr(0);
 	}
 }
+#endif /* !CONFIG_HAVE_HW_BREAKPOINT */
 #endif	/* CONFIG_PPC_ADV_DEBUG_REGS */
 
 int set_dabr(unsigned long dabr)
@@ -631,7 +633,7 @@ void show_regs(struct pt_regs * regs)
 #ifdef CONFIG_PPC_ADV_DEBUG_REGS
 		printk("DEAR: "REG", ESR: "REG"\n", regs->dar, regs->dsisr);
 #else
-		printk("DAR: "REG", DSISR: "REG"\n", regs->dar, regs->dsisr);
+		printk("DAR: "REG", DSISR: %08lx\n", regs->dar, regs->dsisr);
 #endif
 	printk("TASK = %p[%d] '%s' THREAD: %p",
 	       current, task_pid_nr(current), current->comm, task_thread_info(current));
@@ -670,11 +672,11 @@ void flush_thread(void)
 {
 	discard_lazy_cpu_state();
 
-#ifdef CONFIG_HAVE_HW_BREAKPOINTS
+#ifdef CONFIG_HAVE_HW_BREAKPOINT
 	flush_ptrace_hw_breakpoint(current);
-#else /* CONFIG_HAVE_HW_BREAKPOINTS */
+#else /* CONFIG_HAVE_HW_BREAKPOINT */
 	set_debug_reg_defaults(&current->thread);
-#endif /* CONFIG_HAVE_HW_BREAKPOINTS */
+#endif /* CONFIG_HAVE_HW_BREAKPOINT */
 }
 
 void
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/kernel/prom.c linux-libre-2.6.38-gnu1/arch/powerpc/kernel/prom.c
--- linux-libre-2.6.37-gnu1/arch/powerpc/kernel/prom.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/kernel/prom.c	2011-03-14 21:20:32.000000000 -0400
@@ -519,9 +519,9 @@ void __init early_init_dt_add_memory_arc
 	memblock_add(base, size);
 }
 
-u64 __init early_init_dt_alloc_memory_arch(u64 size, u64 align)
+void * __init early_init_dt_alloc_memory_arch(u64 size, u64 align)
 {
-	return memblock_alloc(size, align);
+	return __va(memblock_alloc(size, align));
 }
 
 #ifdef CONFIG_BLK_DEV_INITRD
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/kernel/prom_parse.c linux-libre-2.6.38-gnu1/arch/powerpc/kernel/prom_parse.c
--- linux-libre-2.6.37-gnu1/arch/powerpc/kernel/prom_parse.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/kernel/prom_parse.c	2011-03-14 21:20:32.000000000 -0400
@@ -117,41 +117,3 @@ void of_parse_dma_window(struct device_n
 	cells = prop ? *(u32 *)prop : of_n_size_cells(dn);
 	*size = of_read_number(dma_window, cells);
 }
-
-/**
- * Search the device tree for the best MAC address to use.  'mac-address' is
- * checked first, because that is supposed to contain to "most recent" MAC
- * address. If that isn't set, then 'local-mac-address' is checked next,
- * because that is the default address.  If that isn't set, then the obsolete
- * 'address' is checked, just in case we're using an old device tree.
- *
- * Note that the 'address' property is supposed to contain a virtual address of
- * the register set, but some DTS files have redefined that property to be the
- * MAC address.
- *
- * All-zero MAC addresses are rejected, because those could be properties that
- * exist in the device tree, but were not set by U-Boot.  For example, the
- * DTS could define 'mac-address' and 'local-mac-address', with zero MAC
- * addresses.  Some older U-Boots only initialized 'local-mac-address'.  In
- * this case, the real MAC is in 'local-mac-address', and 'mac-address' exists
- * but is all zeros.
-*/
-const void *of_get_mac_address(struct device_node *np)
-{
-	struct property *pp;
-
-	pp = of_find_property(np, "mac-address", NULL);
-	if (pp && (pp->length == 6) && is_valid_ether_addr(pp->value))
-		return pp->value;
-
-	pp = of_find_property(np, "local-mac-address", NULL);
-	if (pp && (pp->length == 6) && is_valid_ether_addr(pp->value))
-		return pp->value;
-
-	pp = of_find_property(np, "address", NULL);
-	if (pp && (pp->length == 6) && is_valid_ether_addr(pp->value))
-		return pp->value;
-
-	return NULL;
-}
-EXPORT_SYMBOL(of_get_mac_address);
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/kernel/ptrace32.c linux-libre-2.6.38-gnu1/arch/powerpc/kernel/ptrace32.c
--- linux-libre-2.6.37-gnu1/arch/powerpc/kernel/ptrace32.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/kernel/ptrace32.c	2011-03-14 21:20:32.000000000 -0400
@@ -280,7 +280,11 @@ long compat_arch_ptrace(struct task_stru
 		/* We only support one DABR and no IABRS at the moment */
 		if (addr > 0)
 			break;
+#ifdef CONFIG_PPC_ADV_DEBUG_REGS
+		ret = put_user(child->thread.dac1, (u32 __user *)data);
+#else
 		ret = put_user(child->thread.dabr, (u32 __user *)data);
+#endif
 		break;
 	}
 
@@ -312,6 +316,9 @@ long compat_arch_ptrace(struct task_stru
 	case PTRACE_SET_DEBUGREG:
 	case PTRACE_SYSCALL:
 	case PTRACE_CONT:
+	case PPC_PTRACE_GETHWDBGINFO:
+	case PPC_PTRACE_SETHWDEBUG:
+	case PPC_PTRACE_DELHWDEBUG:
 		ret = arch_ptrace(child, request, addr, data);
 		break;
 
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/kernel/ptrace.c linux-libre-2.6.38-gnu1/arch/powerpc/kernel/ptrace.c
--- linux-libre-2.6.37-gnu1/arch/powerpc/kernel/ptrace.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/kernel/ptrace.c	2011-03-14 21:20:32.000000000 -0400
@@ -1316,6 +1316,10 @@ static int set_dac_range(struct task_str
 static long ppc_set_hwdebug(struct task_struct *child,
 		     struct ppc_hw_breakpoint *bp_info)
 {
+#ifndef CONFIG_PPC_ADV_DEBUG_REGS
+	unsigned long dabr;
+#endif
+
 	if (bp_info->version != 1)
 		return -ENOTSUPP;
 #ifdef CONFIG_PPC_ADV_DEBUG_REGS
@@ -1353,11 +1357,10 @@ static long ppc_set_hwdebug(struct task_
 	/*
 	 * We only support one data breakpoint
 	 */
-	if (((bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_RW) == 0) ||
-	    ((bp_info->trigger_type & ~PPC_BREAKPOINT_TRIGGER_RW) != 0) ||
-	    (bp_info->trigger_type != PPC_BREAKPOINT_TRIGGER_WRITE) ||
-	    (bp_info->addr_mode != PPC_BREAKPOINT_MODE_EXACT) ||
-	    (bp_info->condition_mode != PPC_BREAKPOINT_CONDITION_NONE))
+	if ((bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_RW) == 0 ||
+	    (bp_info->trigger_type & ~PPC_BREAKPOINT_TRIGGER_RW) != 0 ||
+	    bp_info->addr_mode != PPC_BREAKPOINT_MODE_EXACT ||
+	    bp_info->condition_mode != PPC_BREAKPOINT_CONDITION_NONE)
 		return -EINVAL;
 
 	if (child->thread.dabr)
@@ -1366,7 +1369,14 @@ static long ppc_set_hwdebug(struct task_
 	if ((unsigned long)bp_info->addr >= TASK_SIZE)
 		return -EIO;
 
-	child->thread.dabr = (unsigned long)bp_info->addr;
+	dabr = (unsigned long)bp_info->addr & ~7UL;
+	dabr |= DABR_TRANSLATION;
+	if (bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_READ)
+		dabr |= DABR_DATA_READ;
+	if (bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_WRITE)
+		dabr |= DABR_DATA_WRITE;
+
+	child->thread.dabr = dabr;
 
 	return 1;
 #endif /* !CONFIG_PPC_ADV_DEBUG_DVCS */
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/kernel/rtas.c linux-libre-2.6.38-gnu1/arch/powerpc/kernel/rtas.c
--- linux-libre-2.6.37-gnu1/arch/powerpc/kernel/rtas.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/kernel/rtas.c	2011-03-14 21:20:32.000000000 -0400
@@ -41,6 +41,7 @@
 #include <asm/atomic.h>
 #include <asm/time.h>
 #include <asm/mmu.h>
+#include <asm/topology.h>
 
 struct rtas_t rtas = {
 	.lock = __ARCH_SPIN_LOCK_UNLOCKED
@@ -713,6 +714,7 @@ static int __rtas_suspend_last_cpu(struc
 	int cpu;
 
 	slb_set_size(SLB_MIN_SIZE);
+	stop_topology_update();
 	printk(KERN_DEBUG "calling ibm,suspend-me on cpu %i\n", smp_processor_id());
 
 	while (rc == H_MULTI_THREADS_ACTIVE && !atomic_read(&data->done) &&
@@ -728,6 +730,7 @@ static int __rtas_suspend_last_cpu(struc
 		rc = atomic_read(&data->error);
 
 	atomic_set(&data->error, rc);
+	start_topology_update();
 
 	if (wake_when_done) {
 		atomic_set(&data->done, 1);
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/kernel/rtasd.c linux-libre-2.6.38-gnu1/arch/powerpc/kernel/rtasd.c
--- linux-libre-2.6.37-gnu1/arch/powerpc/kernel/rtasd.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/kernel/rtasd.c	2011-03-14 21:20:32.000000000 -0400
@@ -160,7 +160,7 @@ static int log_rtas_len(char * buf)
 	/* rtas fixed header */
 	len = 8;
 	err = (struct rtas_error_log *)buf;
-	if (err->extended_log_length) {
+	if (err->extended && err->extended_log_length) {
 
 		/* extended header */
 		len += err->extended_log_length;
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/kernel/rtas_flash.c linux-libre-2.6.38-gnu1/arch/powerpc/kernel/rtas_flash.c
--- linux-libre-2.6.37-gnu1/arch/powerpc/kernel/rtas_flash.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/kernel/rtas_flash.c	2011-03-14 21:20:32.000000000 -0400
@@ -256,31 +256,16 @@ static ssize_t rtas_flash_read(struct fi
 	struct proc_dir_entry *dp = PDE(file->f_path.dentry->d_inode);
 	struct rtas_update_flash_t *uf;
 	char msg[RTAS_MSG_MAXLEN];
-	int msglen;
 
-	uf = (struct rtas_update_flash_t *) dp->data;
+	uf = dp->data;
 
 	if (!strcmp(dp->name, FIRMWARE_FLASH_NAME)) {
 		get_flash_status_msg(uf->status, msg);
 	} else {	   /* FIRMWARE_UPDATE_NAME */
 		sprintf(msg, "%d\n", uf->status);
 	}
-	msglen = strlen(msg);
-	if (msglen > count)
-		msglen = count;
-
-	if (ppos && *ppos != 0)
-		return 0;	/* be cheap */
 
-	if (!access_ok(VERIFY_WRITE, buf, msglen))
-		return -EINVAL;
-
-	if (copy_to_user(buf, msg, msglen))
-		return -EFAULT;
-
-	if (ppos)
-		*ppos = msglen;
-	return msglen;
+	return simple_read_from_buffer(buf, count, ppos, msg, strlen(msg));
 }
 
 /* constructor for flash_block_cache */
@@ -394,26 +379,13 @@ static ssize_t manage_flash_read(struct
 	char msg[RTAS_MSG_MAXLEN];
 	int msglen;
 
-	args_buf = (struct rtas_manage_flash_t *) dp->data;
+	args_buf = dp->data;
 	if (args_buf == NULL)
 		return 0;
 
 	msglen = sprintf(msg, "%d\n", args_buf->status);
-	if (msglen > count)
-		msglen = count;
-
-	if (ppos && *ppos != 0)
-		return 0;	/* be cheap */
 
-	if (!access_ok(VERIFY_WRITE, buf, msglen))
-		return -EINVAL;
-
-	if (copy_to_user(buf, msg, msglen))
-		return -EFAULT;
-
-	if (ppos)
-		*ppos = msglen;
-	return msglen;
+	return simple_read_from_buffer(buf, count, ppos, msg, msglen);
 }
 
 static ssize_t manage_flash_write(struct file *file, const char __user *buf,
@@ -495,24 +467,11 @@ static ssize_t validate_flash_read(struc
 	char msg[RTAS_MSG_MAXLEN];
 	int msglen;
 
-	args_buf = (struct rtas_validate_flash_t *) dp->data;
+	args_buf = dp->data;
 
-	if (ppos && *ppos != 0)
-		return 0;	/* be cheap */
-	
 	msglen = get_validate_flash_msg(args_buf, msg);
-	if (msglen > count)
-		msglen = count;
 
-	if (!access_ok(VERIFY_WRITE, buf, msglen))
-		return -EINVAL;
-
-	if (copy_to_user(buf, msg, msglen))
-		return -EFAULT;
-
-	if (ppos)
-		*ppos = msglen;
-	return msglen;
+	return simple_read_from_buffer(buf, count, ppos, msg, msglen);
 }
 
 static ssize_t validate_flash_write(struct file *file, const char __user *buf,
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/kernel/setup_64.c linux-libre-2.6.38-gnu1/arch/powerpc/kernel/setup_64.c
--- linux-libre-2.6.37-gnu1/arch/powerpc/kernel/setup_64.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/kernel/setup_64.c	2011-03-14 21:20:32.000000000 -0400
@@ -437,8 +437,8 @@ static void __init irqstack_early_init(v
 	unsigned int i;
 
 	/*
-	 * interrupt stacks must be under 256MB, we cannot afford to take
-	 * SLB misses on them.
+	 * Interrupt stacks must be in the first segment since we
+	 * cannot afford to take SLB misses on them.
 	 */
 	for_each_possible_cpu(i) {
 		softirq_ctx[i] = (struct thread_info *)
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/kernel/smp.c linux-libre-2.6.38-gnu1/arch/powerpc/kernel/smp.c
--- linux-libre-2.6.37-gnu1/arch/powerpc/kernel/smp.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/kernel/smp.c	2011-03-14 21:20:32.000000000 -0400
@@ -466,7 +466,20 @@ out:
 	return id;
 }
 
-/* Must be called when no change can occur to cpu_present_mask,
+/* Helper routines for cpu to core mapping */
+int cpu_core_index_of_thread(int cpu)
+{
+	return cpu >> threads_shift;
+}
+EXPORT_SYMBOL_GPL(cpu_core_index_of_thread);
+
+int cpu_first_thread_of_core(int core)
+{
+	return core << threads_shift;
+}
+EXPORT_SYMBOL_GPL(cpu_first_thread_of_core);
+
+/* Must be called when no change can occur to cpu_present_map,
  * i.e. during cpu online or offline.
  */
 static struct device_node *cpu_to_l2cache(int cpu)
@@ -514,7 +527,7 @@ int __devinit start_secondary(void *unus
 	notify_cpu_starting(cpu);
 	set_cpu_online(cpu, true);
 	/* Update sibling maps */
-	base = cpu_first_thread_in_core(cpu);
+	base = cpu_first_thread_sibling(cpu);
 	for (i = 0; i < threads_per_core; i++) {
 		if (cpu_is_offline(base + i))
 			continue;
@@ -600,7 +613,7 @@ int __cpu_disable(void)
 		return err;
 
 	/* Update sibling maps */
-	base = cpu_first_thread_in_core(cpu);
+	base = cpu_first_thread_sibling(cpu);
 	for (i = 0; i < threads_per_core; i++) {
 		cpumask_clear_cpu(cpu, cpu_sibling_mask(base + i));
 		cpumask_clear_cpu(base + i, cpu_sibling_mask(cpu));
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/kernel/time.c linux-libre-2.6.38-gnu1/arch/powerpc/kernel/time.c
--- linux-libre-2.6.37-gnu1/arch/powerpc/kernel/time.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/kernel/time.c	2011-03-14 21:20:32.000000000 -0400
@@ -155,7 +155,7 @@ EXPORT_SYMBOL_GPL(rtc_lock);
 
 static u64 tb_to_ns_scale __read_mostly;
 static unsigned tb_to_ns_shift __read_mostly;
-static unsigned long boot_tb __read_mostly;
+static u64 boot_tb __read_mostly;
 
 extern struct timezone sys_tz;
 static long timezone_offset;
@@ -265,11 +265,26 @@ void accumulate_stolen_time(void)
 {
 	u64 sst, ust;
 
-	sst = scan_dispatch_log(get_paca()->starttime_user);
-	ust = scan_dispatch_log(get_paca()->starttime);
-	get_paca()->system_time -= sst;
-	get_paca()->user_time -= ust;
-	get_paca()->stolen_time += ust + sst;
+	u8 save_soft_enabled = local_paca->soft_enabled;
+	u8 save_hard_enabled = local_paca->hard_enabled;
+
+	/* We are called early in the exception entry, before
+	 * soft/hard_enabled are sync'ed to the expected state
+	 * for the exception. We are hard disabled but the PACA
+	 * needs to reflect that so various debug stuff doesn't
+	 * complain
+	 */
+	local_paca->soft_enabled = 0;
+	local_paca->hard_enabled = 0;
+
+	sst = scan_dispatch_log(local_paca->starttime_user);
+	ust = scan_dispatch_log(local_paca->starttime);
+	local_paca->system_time -= sst;
+	local_paca->user_time -= ust;
+	local_paca->stolen_time += ust + sst;
+
+	local_paca->soft_enabled = save_soft_enabled;
+	local_paca->hard_enabled = save_hard_enabled;
 }
 
 static inline u64 calculate_stolen_time(u64 stop_tb)
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/kernel/traps.c linux-libre-2.6.38-gnu1/arch/powerpc/kernel/traps.c
--- linux-libre-2.6.37-gnu1/arch/powerpc/kernel/traps.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/kernel/traps.c	2011-03-14 21:20:32.000000000 -0400
@@ -626,12 +626,6 @@ void machine_check_exception(struct pt_r
 	if (recover > 0)
 		return;
 
-	if (user_mode(regs)) {
-		regs->msr |= MSR_RI;
-		_exception(SIGBUS, regs, BUS_ADRERR, regs->nip);
-		return;
-	}
-
 #if defined(CONFIG_8xx) && defined(CONFIG_PCI)
 	/* the qspan pci read routines can cause machine checks -- Cort
 	 *
@@ -643,16 +637,12 @@ void machine_check_exception(struct pt_r
 	return;
 #endif
 
-	if (debugger_fault_handler(regs)) {
-		regs->msr |= MSR_RI;
+	if (debugger_fault_handler(regs))
 		return;
-	}
 
 	if (check_io_access(regs))
 		return;
 
-	if (debugger_fault_handler(regs))
-		return;
 	die("Machine check", regs, SIGBUS);
 
 	/* Must die if the interrupt is not recoverable */
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/kernel/vector.S linux-libre-2.6.38-gnu1/arch/powerpc/kernel/vector.S
--- linux-libre-2.6.37-gnu1/arch/powerpc/kernel/vector.S	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/kernel/vector.S	2011-03-14 21:20:32.000000000 -0400
@@ -5,6 +5,7 @@
 #include <asm/cputable.h>
 #include <asm/thread_info.h>
 #include <asm/page.h>
+#include <asm/ptrace.h>
 
 /*
  * load_up_altivec(unused, unused, tsk)
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/kernel/vio.c linux-libre-2.6.38-gnu1/arch/powerpc/kernel/vio.c
--- linux-libre-2.6.37-gnu1/arch/powerpc/kernel/vio.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/kernel/vio.c	2011-03-14 21:20:32.000000000 -0400
@@ -600,6 +600,11 @@ static void vio_dma_iommu_unmap_sg(struc
 	vio_cmo_dealloc(viodev, alloc_size);
 }
 
+static int vio_dma_iommu_dma_supported(struct device *dev, u64 mask)
+{
+        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,
@@ -607,6 +612,7 @@ struct dma_map_ops vio_dma_mapping_ops =
 	.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,
 
 };
 
@@ -858,8 +864,7 @@ static void vio_cmo_bus_remove(struct vi
 
 static void vio_cmo_set_dma_ops(struct vio_dev *viodev)
 {
-	vio_dma_mapping_ops.dma_supported = dma_iommu_ops.dma_supported;
-	viodev->dev.archdata.dma_ops = &vio_dma_mapping_ops;
+	set_dma_ops(&viodev->dev, &vio_dma_mapping_ops);
 }
 
 /**
@@ -1244,7 +1249,7 @@ struct vio_dev *vio_register_device_node
 	if (firmware_has_feature(FW_FEATURE_CMO))
 		vio_cmo_set_dma_ops(viodev);
 	else
-		viodev->dev.archdata.dma_ops = &dma_iommu_ops;
+		set_dma_ops(&viodev->dev, &dma_iommu_ops);
 	set_iommu_table_base(&viodev->dev, vio_build_iommu_table(viodev));
 	set_dev_node(&viodev->dev, of_node_to_nid(of_node));
 
@@ -1252,6 +1257,10 @@ struct vio_dev *vio_register_device_node
 	viodev->dev.parent = &vio_bus_device.dev;
 	viodev->dev.bus = &vio_bus_type;
 	viodev->dev.release = vio_dev_release;
+        /* needed to ensure proper operation of coherent allocations
+         * later, in case driver doesn't set it explicitly */
+        dma_set_mask(&viodev->dev, DMA_BIT_MASK(64));
+        dma_set_coherent_mask(&viodev->dev, DMA_BIT_MASK(64));
 
 	/* register with generic device framework */
 	if (device_register(&viodev->dev)) {
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/kvm/book3s.c linux-libre-2.6.38-gnu1/arch/powerpc/kvm/book3s.c
--- linux-libre-2.6.37-gnu1/arch/powerpc/kvm/book3s.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/kvm/book3s.c	2011-03-14 21:20:32.000000000 -0400
@@ -1307,12 +1307,10 @@ struct kvm_vcpu *kvmppc_core_vcpu_create
 	int err = -ENOMEM;
 	unsigned long p;
 
-	vcpu_book3s = vmalloc(sizeof(struct kvmppc_vcpu_book3s));
+	vcpu_book3s = vzalloc(sizeof(struct kvmppc_vcpu_book3s));
 	if (!vcpu_book3s)
 		goto out;
 
-	memset(vcpu_book3s, 0, sizeof(struct kvmppc_vcpu_book3s));
-
 	vcpu_book3s->shadow_vcpu = (struct kvmppc_book3s_shadow_vcpu *)
 		kzalloc(sizeof(*vcpu_book3s->shadow_vcpu), GFP_KERNEL);
 	if (!vcpu_book3s->shadow_vcpu)
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/kvm/powerpc.c linux-libre-2.6.38-gnu1/arch/powerpc/kvm/powerpc.c
--- linux-libre-2.6.37-gnu1/arch/powerpc/kvm/powerpc.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/kvm/powerpc.c	2011-03-14 21:20:32.000000000 -0400
@@ -145,18 +145,12 @@ void kvm_arch_check_processor_compat(voi
 	*(int *)rtn = kvmppc_core_check_processor_compat();
 }
 
-struct kvm *kvm_arch_create_vm(void)
+int kvm_arch_init_vm(struct kvm *kvm)
 {
-	struct kvm *kvm;
-
-	kvm = kzalloc(sizeof(struct kvm), GFP_KERNEL);
-	if (!kvm)
-		return ERR_PTR(-ENOMEM);
-
-	return kvm;
+	return 0;
 }
 
-static void kvmppc_free_vcpus(struct kvm *kvm)
+void kvm_arch_destroy_vm(struct kvm *kvm)
 {
 	unsigned int i;
 	struct kvm_vcpu *vcpu;
@@ -176,14 +170,6 @@ void kvm_arch_sync_events(struct kvm *kv
 {
 }
 
-void kvm_arch_destroy_vm(struct kvm *kvm)
-{
-	kvmppc_free_vcpus(kvm);
-	kvm_free_physmem(kvm);
-	cleanup_srcu_struct(&kvm->srcu);
-	kfree(kvm);
-}
-
 int kvm_dev_ioctl_check_extension(long ext)
 {
 	int r;
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/lib/feature-fixups-test.S linux-libre-2.6.38-gnu1/arch/powerpc/lib/feature-fixups-test.S
--- linux-libre-2.6.37-gnu1/arch/powerpc/lib/feature-fixups-test.S	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/lib/feature-fixups-test.S	2011-03-14 21:20:32.000000000 -0400
@@ -172,6 +172,25 @@ globl(ftr_fixup_test6_expected)
 3:	or	3,3,3
 
 
+#if 0
+/* Test that if we have a larger else case the assembler spots it and
+ * reports an error. #if 0'ed so as not to break the build normally.
+ */
+ftr_fixup_test7:
+	or	1,1,1
+BEGIN_FTR_SECTION
+	or	2,2,2
+	or	2,2,2
+	or	2,2,2
+FTR_SECTION_ELSE
+	or	3,3,3
+	or	3,3,3
+	or	3,3,3
+	or	3,3,3
+ALT_FTR_SECTION_END(0, 1)
+	or	1,1,1
+#endif
+
 #define	MAKE_MACRO_TEST(TYPE)						\
 globl(ftr_fixup_test_ ##TYPE##_macros)					\
 	or	1,1,1;							\
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/lib/hweight_64.S linux-libre-2.6.38-gnu1/arch/powerpc/lib/hweight_64.S
--- linux-libre-2.6.37-gnu1/arch/powerpc/lib/hweight_64.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/lib/hweight_64.S	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,110 @@
+/*
+ * 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.
+ *
+ * Copyright (C) IBM Corporation, 2010
+ *
+ * Author: Anton Blanchard <anton@au.ibm.com>
+ */
+#include <asm/processor.h>
+#include <asm/ppc_asm.h>
+
+/* Note: This code relies on -mminimal-toc */
+
+_GLOBAL(__arch_hweight8)
+BEGIN_FTR_SECTION
+	b .__sw_hweight8
+	nop
+	nop
+FTR_SECTION_ELSE
+	PPC_POPCNTB(r3,r3)
+	clrldi	r3,r3,64-8
+	blr
+ALT_FTR_SECTION_END_IFCLR(CPU_FTR_POPCNTB)
+
+_GLOBAL(__arch_hweight16)
+BEGIN_FTR_SECTION
+	b .__sw_hweight16
+	nop
+	nop
+	nop
+	nop
+FTR_SECTION_ELSE
+  BEGIN_FTR_SECTION_NESTED(50)
+	PPC_POPCNTB(r3,r3)
+	srdi	r4,r3,8
+	add	r3,r4,r3
+	clrldi	r3,r3,64-8
+	blr
+  FTR_SECTION_ELSE_NESTED(50)
+	clrlwi  r3,r3,16
+	PPC_POPCNTW(r3,r3)
+	clrldi	r3,r3,64-8
+	blr
+  ALT_FTR_SECTION_END_NESTED_IFCLR(CPU_FTR_POPCNTD, 50)
+ALT_FTR_SECTION_END_IFCLR(CPU_FTR_POPCNTB)
+
+_GLOBAL(__arch_hweight32)
+BEGIN_FTR_SECTION
+	b .__sw_hweight32
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+FTR_SECTION_ELSE
+  BEGIN_FTR_SECTION_NESTED(51)
+	PPC_POPCNTB(r3,r3)
+	srdi	r4,r3,16
+	add	r3,r4,r3
+	srdi	r4,r3,8
+	add	r3,r4,r3
+	clrldi	r3,r3,64-8
+	blr
+  FTR_SECTION_ELSE_NESTED(51)
+	PPC_POPCNTW(r3,r3)
+	clrldi	r3,r3,64-8
+	blr
+  ALT_FTR_SECTION_END_NESTED_IFCLR(CPU_FTR_POPCNTD, 51)
+ALT_FTR_SECTION_END_IFCLR(CPU_FTR_POPCNTB)
+
+_GLOBAL(__arch_hweight64)
+BEGIN_FTR_SECTION
+	b .__sw_hweight64
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+FTR_SECTION_ELSE
+  BEGIN_FTR_SECTION_NESTED(52)
+	PPC_POPCNTB(r3,r3)
+	srdi	r4,r3,32
+	add	r3,r4,r3
+	srdi	r4,r3,16
+	add	r3,r4,r3
+	srdi	r4,r3,8
+	add	r3,r4,r3
+	clrldi	r3,r3,64-8
+	blr
+  FTR_SECTION_ELSE_NESTED(52)
+	PPC_POPCNTD(r3,r3)
+	clrldi	r3,r3,64-8
+	blr
+  ALT_FTR_SECTION_END_NESTED_IFCLR(CPU_FTR_POPCNTD, 52)
+ALT_FTR_SECTION_END_IFCLR(CPU_FTR_POPCNTB)
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/lib/Makefile linux-libre-2.6.38-gnu1/arch/powerpc/lib/Makefile
--- linux-libre-2.6.37-gnu1/arch/powerpc/lib/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/lib/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -16,7 +16,7 @@ obj-$(CONFIG_HAS_IOMEM)	+= devres.o
 
 obj-$(CONFIG_PPC64)	+= copypage_64.o copyuser_64.o \
 			   memcpy_64.o usercopy_64.o mem_64.o string.o \
-			   checksum_wrappers_64.o
+			   checksum_wrappers_64.o hweight_64.o
 obj-$(CONFIG_XMON)	+= sstep.o ldstfp.o
 obj-$(CONFIG_KPROBES)	+= sstep.o ldstfp.o
 obj-$(CONFIG_HAVE_HW_BREAKPOINT)	+= sstep.o ldstfp.o
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/mm/gup.c linux-libre-2.6.38-gnu1/arch/powerpc/mm/gup.c
--- linux-libre-2.6.37-gnu1/arch/powerpc/mm/gup.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/mm/gup.c	2011-03-14 21:20:32.000000000 -0400
@@ -16,6 +16,16 @@
 
 #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
@@ -47,6 +57,8 @@ 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-2.6.37-gnu1/arch/powerpc/mm/hash_utils_64.c linux-libre-2.6.38-gnu1/arch/powerpc/mm/hash_utils_64.c
--- linux-libre-2.6.37-gnu1/arch/powerpc/mm/hash_utils_64.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/mm/hash_utils_64.c	2011-03-14 21:20:32.000000000 -0400
@@ -1070,7 +1070,7 @@ void hash_preload(struct mm_struct *mm,
 		  unsigned long access, unsigned long trap)
 {
 	unsigned long vsid;
-	void *pgdir;
+	pgd_t *pgdir;
 	pte_t *ptep;
 	unsigned long flags;
 	int rc, ssize, local = 0;
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/mm/mmu_context_nohash.c linux-libre-2.6.38-gnu1/arch/powerpc/mm/mmu_context_nohash.c
--- linux-libre-2.6.37-gnu1/arch/powerpc/mm/mmu_context_nohash.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/mm/mmu_context_nohash.c	2011-03-14 21:20:32.000000000 -0400
@@ -111,8 +111,8 @@ static unsigned int steal_context_smp(un
 		 * a core map instead but this will do for now.
 		 */
 		for_each_cpu(cpu, mm_cpumask(mm)) {
-			for (i = cpu_first_thread_in_core(cpu);
-			     i <= cpu_last_thread_in_core(cpu); i++)
+			for (i = cpu_first_thread_sibling(cpu);
+			     i <= cpu_last_thread_sibling(cpu); i++)
 				__set_bit(id, stale_map[i]);
 			cpu = i - 1;
 		}
@@ -264,14 +264,14 @@ void switch_mmu_context(struct mm_struct
 	 */
 	if (test_bit(id, stale_map[cpu])) {
 		pr_hardcont(" | stale flush %d [%d..%d]",
-			    id, cpu_first_thread_in_core(cpu),
-			    cpu_last_thread_in_core(cpu));
+			    id, cpu_first_thread_sibling(cpu),
+			    cpu_last_thread_sibling(cpu));
 
 		local_flush_tlb_mm(next);
 
 		/* XXX This clear should ultimately be part of local_flush_tlb_mm */
-		for (i = cpu_first_thread_in_core(cpu);
-		     i <= cpu_last_thread_in_core(cpu); i++) {
+		for (i = cpu_first_thread_sibling(cpu);
+		     i <= cpu_last_thread_sibling(cpu); i++) {
 			__clear_bit(id, stale_map[i]);
 		}
 	}
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/mm/numa.c linux-libre-2.6.38-gnu1/arch/powerpc/mm/numa.c
--- linux-libre-2.6.37-gnu1/arch/powerpc/mm/numa.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/mm/numa.c	2011-03-14 21:20:32.000000000 -0400
@@ -20,10 +20,15 @@
 #include <linux/memblock.h>
 #include <linux/of.h>
 #include <linux/pfn.h>
+#include <linux/cpuset.h>
+#include <linux/node.h>
 #include <asm/sparsemem.h>
 #include <asm/prom.h>
 #include <asm/system.h>
 #include <asm/smp.h>
+#include <asm/firmware.h>
+#include <asm/paca.h>
+#include <asm/hvcall.h>
 
 static int numa_enabled = 1;
 
@@ -163,7 +168,7 @@ static void __init get_node_active_regio
 	work_with_active_regions(nid, get_active_region_work_fn, node_ar);
 }
 
-static void __cpuinit map_cpu_to_node(int cpu, int node)
+static void map_cpu_to_node(int cpu, int node)
 {
 	numa_cpu_lookup_table[cpu] = node;
 
@@ -173,7 +178,7 @@ static void __cpuinit map_cpu_to_node(in
 		cpumask_set_cpu(cpu, node_to_cpumask_map[node]);
 }
 
-#ifdef CONFIG_HOTPLUG_CPU
+#if defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_PPC_SPLPAR)
 static void unmap_cpu_from_node(unsigned long cpu)
 {
 	int node = numa_cpu_lookup_table[cpu];
@@ -181,13 +186,13 @@ static void unmap_cpu_from_node(unsigned
 	dbg("removing cpu %lu from node %d\n", cpu, node);
 
 	if (cpumask_test_cpu(cpu, node_to_cpumask_map[node])) {
-		cpumask_set_cpu(cpu, node_to_cpumask_map[node]);
+		cpumask_clear_cpu(cpu, node_to_cpumask_map[node]);
 	} else {
 		printk(KERN_ERR "WARNING: cpu %lu not found in node %d\n",
 		       cpu, node);
 	}
 }
-#endif /* CONFIG_HOTPLUG_CPU */
+#endif /* CONFIG_HOTPLUG_CPU || CONFIG_PPC_SPLPAR */
 
 /* must hold reference to node during call */
 static const int *of_get_associativity(struct device_node *dev)
@@ -246,32 +251,41 @@ static void initialize_distance_lookup_t
 /* Returns nid in the range [0..MAX_NUMNODES-1], or -1 if no useful numa
  * info is found.
  */
-static int of_node_to_nid_single(struct device_node *device)
+static int associativity_to_nid(const unsigned int *associativity)
 {
 	int nid = -1;
-	const unsigned int *tmp;
 
 	if (min_common_depth == -1)
 		goto out;
 
-	tmp = of_get_associativity(device);
-	if (!tmp)
-		goto out;
-
-	if (tmp[0] >= min_common_depth)
-		nid = tmp[min_common_depth];
+	if (associativity[0] >= min_common_depth)
+		nid = associativity[min_common_depth];
 
 	/* POWER4 LPAR uses 0xffff as invalid node */
 	if (nid == 0xffff || nid >= MAX_NUMNODES)
 		nid = -1;
 
-	if (nid > 0 && tmp[0] >= distance_ref_points_depth)
-		initialize_distance_lookup_table(nid, tmp);
+	if (nid > 0 && associativity[0] >= distance_ref_points_depth)
+		initialize_distance_lookup_table(nid, associativity);
 
 out:
 	return nid;
 }
 
+/* Returns the nid associated with the given device tree node,
+ * or -1 if not found.
+ */
+static int of_node_to_nid_single(struct device_node *device)
+{
+	int nid = -1;
+	const unsigned int *tmp;
+
+	tmp = of_get_associativity(device);
+	if (tmp)
+		nid = associativity_to_nid(tmp);
+	return nid;
+}
+
 /* Walk the device tree upwards, looking for an associativity id */
 int of_node_to_nid(struct device_node *device)
 {
@@ -1247,4 +1261,281 @@ int hot_add_scn_to_nid(unsigned long scn
 	return nid;
 }
 
+static u64 hot_add_drconf_memory_max(void)
+{
+        struct device_node *memory = NULL;
+        unsigned int drconf_cell_cnt = 0;
+        u64 lmb_size = 0;
+        const u32 *dm = 0;
+
+        memory = of_find_node_by_path("/ibm,dynamic-reconfiguration-memory");
+        if (memory) {
+                drconf_cell_cnt = of_get_drconf_memory(memory, &dm);
+                lmb_size = of_get_lmb_size(memory);
+                of_node_put(memory);
+        }
+        return lmb_size * drconf_cell_cnt;
+}
+
+/*
+ * memory_hotplug_max - return max address of memory that may be added
+ *
+ * This is currently only used on systems that support drconfig memory
+ * hotplug.
+ */
+u64 memory_hotplug_max(void)
+{
+        return max(hot_add_drconf_memory_max(), memblock_end_of_DRAM());
+}
 #endif /* CONFIG_MEMORY_HOTPLUG */
+
+/* Virtual Processor Home Node (VPHN) support */
+#ifdef CONFIG_PPC_SPLPAR
+static u8 vphn_cpu_change_counts[NR_CPUS][MAX_DISTANCE_REF_POINTS];
+static cpumask_t cpu_associativity_changes_mask;
+static int vphn_enabled;
+static void set_topology_timer(void);
+
+/*
+ * Store the current values of the associativity change counters in the
+ * hypervisor.
+ */
+static void setup_cpu_associativity_change_counters(void)
+{
+	int cpu;
+
+	/* The VPHN feature supports a maximum of 8 reference points */
+	BUILD_BUG_ON(MAX_DISTANCE_REF_POINTS > 8);
+
+	for_each_possible_cpu(cpu) {
+		int i;
+		u8 *counts = vphn_cpu_change_counts[cpu];
+		volatile u8 *hypervisor_counts = lppaca[cpu].vphn_assoc_counts;
+
+		for (i = 0; i < distance_ref_points_depth; i++)
+			counts[i] = hypervisor_counts[i];
+	}
+}
+
+/*
+ * The hypervisor maintains a set of 8 associativity change counters in
+ * the VPA of each cpu that correspond to the associativity levels in the
+ * ibm,associativity-reference-points property. When an associativity
+ * level changes, the corresponding counter is incremented.
+ *
+ * Set a bit in cpu_associativity_changes_mask for each cpu whose home
+ * node associativity levels have changed.
+ *
+ * Returns the number of cpus with unhandled associativity changes.
+ */
+static int update_cpu_associativity_changes_mask(void)
+{
+	int cpu, nr_cpus = 0;
+	cpumask_t *changes = &cpu_associativity_changes_mask;
+
+	cpumask_clear(changes);
+
+	for_each_possible_cpu(cpu) {
+		int i, changed = 0;
+		u8 *counts = vphn_cpu_change_counts[cpu];
+		volatile u8 *hypervisor_counts = lppaca[cpu].vphn_assoc_counts;
+
+		for (i = 0; i < distance_ref_points_depth; i++) {
+			if (hypervisor_counts[i] != counts[i]) {
+				counts[i] = hypervisor_counts[i];
+				changed = 1;
+			}
+		}
+		if (changed) {
+			cpumask_set_cpu(cpu, changes);
+			nr_cpus++;
+		}
+	}
+
+	return nr_cpus;
+}
+
+/*
+ * 6 64-bit registers unpacked into 12 32-bit associativity values. To form
+ * the complete property we have to add the length in the first cell.
+ */
+#define VPHN_ASSOC_BUFSIZE (6*sizeof(u64)/sizeof(u32) + 1)
+
+/*
+ * Convert the associativity domain numbers returned from the hypervisor
+ * to the sequence they would appear in the ibm,associativity property.
+ */
+static int vphn_unpack_associativity(const long *packed, unsigned int *unpacked)
+{
+	int i, nr_assoc_doms = 0;
+	const u16 *field = (const u16*) packed;
+
+#define VPHN_FIELD_UNUSED	(0xffff)
+#define VPHN_FIELD_MSB		(0x8000)
+#define VPHN_FIELD_MASK		(~VPHN_FIELD_MSB)
+
+	for (i = 1; i < VPHN_ASSOC_BUFSIZE; i++) {
+		if (*field == VPHN_FIELD_UNUSED) {
+			/* All significant fields processed, and remaining
+			 * fields contain the reserved value of all 1's.
+			 * Just store them.
+			 */
+			unpacked[i] = *((u32*)field);
+			field += 2;
+		} else if (*field & VPHN_FIELD_MSB) {
+			/* Data is in the lower 15 bits of this field */
+			unpacked[i] = *field & VPHN_FIELD_MASK;
+			field++;
+			nr_assoc_doms++;
+		} else {
+			/* Data is in the lower 15 bits of this field
+			 * concatenated with the next 16 bit field
+			 */
+			unpacked[i] = *((u32*)field);
+			field += 2;
+			nr_assoc_doms++;
+		}
+	}
+
+	/* The first cell contains the length of the property */
+	unpacked[0] = nr_assoc_doms;
+
+	return nr_assoc_doms;
+}
+
+/*
+ * Retrieve the new associativity information for a virtual processor's
+ * home node.
+ */
+static long hcall_vphn(unsigned long cpu, unsigned int *associativity)
+{
+	long rc;
+	long retbuf[PLPAR_HCALL9_BUFSIZE] = {0};
+	u64 flags = 1;
+	int hwcpu = get_hard_smp_processor_id(cpu);
+
+	rc = plpar_hcall9(H_HOME_NODE_ASSOCIATIVITY, retbuf, flags, hwcpu);
+	vphn_unpack_associativity(retbuf, associativity);
+
+	return rc;
+}
+
+static long vphn_get_associativity(unsigned long cpu,
+					unsigned int *associativity)
+{
+	long rc;
+
+	rc = hcall_vphn(cpu, associativity);
+
+	switch (rc) {
+	case H_FUNCTION:
+		printk(KERN_INFO
+			"VPHN is not supported. Disabling polling...\n");
+		stop_topology_update();
+		break;
+	case H_HARDWARE:
+		printk(KERN_ERR
+			"hcall_vphn() experienced a hardware fault "
+			"preventing VPHN. Disabling polling...\n");
+		stop_topology_update();
+	}
+
+	return rc;
+}
+
+/*
+ * Update the node maps and sysfs entries for each cpu whose home node
+ * has changed.
+ */
+int arch_update_cpu_topology(void)
+{
+	int cpu, nid, old_nid;
+	unsigned int associativity[VPHN_ASSOC_BUFSIZE] = {0};
+	struct sys_device *sysdev;
+
+	for_each_cpu_mask(cpu, cpu_associativity_changes_mask) {
+		vphn_get_associativity(cpu, associativity);
+		nid = associativity_to_nid(associativity);
+
+		if (nid < 0 || !node_online(nid))
+			nid = first_online_node;
+
+		old_nid = numa_cpu_lookup_table[cpu];
+
+		/* Disable hotplug while we update the cpu
+		 * masks and sysfs.
+		 */
+		get_online_cpus();
+		unregister_cpu_under_node(cpu, old_nid);
+		unmap_cpu_from_node(cpu);
+		map_cpu_to_node(cpu, nid);
+		register_cpu_under_node(cpu, nid);
+		put_online_cpus();
+
+		sysdev = get_cpu_sysdev(cpu);
+		if (sysdev)
+			kobject_uevent(&sysdev->kobj, KOBJ_CHANGE);
+	}
+
+	return 1;
+}
+
+static void topology_work_fn(struct work_struct *work)
+{
+	rebuild_sched_domains();
+}
+static DECLARE_WORK(topology_work, topology_work_fn);
+
+void topology_schedule_update(void)
+{
+	schedule_work(&topology_work);
+}
+
+static void topology_timer_fn(unsigned long ignored)
+{
+	if (!vphn_enabled)
+		return;
+	if (update_cpu_associativity_changes_mask() > 0)
+		topology_schedule_update();
+	set_topology_timer();
+}
+static struct timer_list topology_timer =
+	TIMER_INITIALIZER(topology_timer_fn, 0, 0);
+
+static void set_topology_timer(void)
+{
+	topology_timer.data = 0;
+	topology_timer.expires = jiffies + 60 * HZ;
+	add_timer(&topology_timer);
+}
+
+/*
+ * Start polling for VPHN associativity changes.
+ */
+int start_topology_update(void)
+{
+	int rc = 0;
+
+	/* Disabled until races with load balancing are fixed */
+	if (0 && firmware_has_feature(FW_FEATURE_VPHN) &&
+	    get_lppaca()->shared_proc) {
+		vphn_enabled = 1;
+		setup_cpu_associativity_change_counters();
+		init_timer_deferrable(&topology_timer);
+		set_topology_timer();
+		rc = 1;
+	}
+
+	return rc;
+}
+__initcall(start_topology_update);
+
+/*
+ * Disable polling for VPHN associativity changes.
+ */
+int stop_topology_update(void)
+{
+	vphn_enabled = 0;
+	return del_timer_sync(&topology_timer);
+}
+#endif /* CONFIG_PPC_SPLPAR */
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/mm/pgtable_32.c linux-libre-2.6.38-gnu1/arch/powerpc/mm/pgtable_32.c
--- linux-libre-2.6.37-gnu1/arch/powerpc/mm/pgtable_32.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/mm/pgtable_32.c	2011-03-14 21:20:32.000000000 -0400
@@ -78,7 +78,7 @@ pgd_t *pgd_alloc(struct mm_struct *mm)
 
 	/* pgdir take page or two with 4K pages and a page fraction otherwise */
 #ifndef CONFIG_PPC_4K_PAGES
-	ret = (pgd_t *)kzalloc(1 << PGDIR_ORDER, GFP_KERNEL);
+	ret = kzalloc(1 << PGDIR_ORDER, GFP_KERNEL);
 #else
 	ret = (pgd_t *)__get_free_pages(GFP_KERNEL|__GFP_ZERO,
 			PGDIR_ORDER - PAGE_SHIFT);
@@ -230,6 +230,7 @@ __ioremap_caller(phys_addr_t addr, unsig
 		area = get_vm_area_caller(size, VM_IOREMAP, caller);
 		if (area == 0)
 			return NULL;
+		area->phys_addr = p;
 		v = (unsigned long) area->addr;
 	} else {
 		v = (ioremap_bot -= size);
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/mm/pgtable_64.c linux-libre-2.6.38-gnu1/arch/powerpc/mm/pgtable_64.c
--- linux-libre-2.6.37-gnu1/arch/powerpc/mm/pgtable_64.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/mm/pgtable_64.c	2011-03-14 21:20:32.000000000 -0400
@@ -223,6 +223,8 @@ void __iomem * __ioremap_caller(phys_add
 					    caller);
 		if (area == NULL)
 			return NULL;
+
+		area->phys_addr = paligned;
 		ret = __ioremap_at(paligned, area->addr, size, flags);
 		if (!ret)
 			vunmap(area->addr);
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/mm/tlb_hash64.c linux-libre-2.6.38-gnu1/arch/powerpc/mm/tlb_hash64.c
--- linux-libre-2.6.37-gnu1/arch/powerpc/mm/tlb_hash64.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/mm/tlb_hash64.c	2011-03-14 21:20:32.000000000 -0400
@@ -38,13 +38,11 @@ DEFINE_PER_CPU(struct ppc64_tlb_batch, p
  * neesd to be flushed. This function will either perform the flush
  * immediately or will batch it up if the current CPU has an active
  * batch on it.
- *
- * Must be called from within some kind of spinlock/non-preempt region...
  */
 void hpte_need_flush(struct mm_struct *mm, unsigned long addr,
 		     pte_t *ptep, unsigned long pte, int huge)
 {
-	struct ppc64_tlb_batch *batch = &__get_cpu_var(ppc64_tlb_batch);
+	struct ppc64_tlb_batch *batch = &get_cpu_var(ppc64_tlb_batch);
 	unsigned long vsid, vaddr;
 	unsigned int psize;
 	int ssize;
@@ -99,6 +97,7 @@ void hpte_need_flush(struct mm_struct *m
 	 */
 	if (!batch->active) {
 		flush_hash_page(vaddr, rpte, psize, ssize, 0);
+		put_cpu_var(ppc64_tlb_batch);
 		return;
 	}
 
@@ -127,6 +126,7 @@ void hpte_need_flush(struct mm_struct *m
 	batch->index = ++i;
 	if (i >= PPC64_TLB_BATCH_NR)
 		__flush_tlb_pending(batch);
+	put_cpu_var(ppc64_tlb_batch);
 }
 
 /*
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/oprofile/op_model_cell.c linux-libre-2.6.38-gnu1/arch/powerpc/oprofile/op_model_cell.c
--- linux-libre-2.6.37-gnu1/arch/powerpc/oprofile/op_model_cell.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/oprofile/op_model_cell.c	2011-03-14 21:20:32.000000000 -0400
@@ -1469,7 +1469,7 @@ static int cell_global_start(struct op_c
  * The pm_interval register is setup to write the SPU PC value into the
  * trace buffer at the maximum rate possible.  The trace buffer is configured
  * to store the PCs, wrapping when it is full.  The performance counter is
- * intialized to the max hardware count minus the number of events, N, between
+ * initialized to the max hardware count minus the number of events, N, between
  * samples.  Once the N events have occured, a HW counter overflow occurs
  * causing the generation of a HW counter interrupt which also stops the
  * writing of the SPU PC values to the trace buffer.  Hence the last PC
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/platforms/40x/ppc40x_simple.c linux-libre-2.6.38-gnu1/arch/powerpc/platforms/40x/ppc40x_simple.c
--- linux-libre-2.6.37-gnu1/arch/powerpc/platforms/40x/ppc40x_simple.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/platforms/40x/ppc40x_simple.c	2011-03-14 21:20:32.000000000 -0400
@@ -50,7 +50,7 @@ machine_device_initcall(ppc40x_simple, p
  * Again, if your board needs to do things differently then create a
  * board.c file for it rather than adding it to this list.
  */
-static char *board[] __initdata = {
+static const char *board[] __initdata = {
 	"amcc,acadia",
 	"amcc,haleakala",
 	"amcc,kilauea",
@@ -60,14 +60,9 @@ static char *board[] __initdata = {
 
 static int __init ppc40x_probe(void)
 {
-	unsigned long root = of_get_flat_dt_root();
-	int i = 0;
-
-	for (i = 0; i < ARRAY_SIZE(board); i++) {
-		if (of_flat_dt_is_compatible(root, board[i])) {
-			ppc_pci_set_flags(PPC_PCI_REASSIGN_ALL_RSRC);
-			return 1;
-		}
+	if (of_flat_dt_match(of_get_flat_dt_root(), board)) {
+		ppc_pci_set_flags(PPC_PCI_REASSIGN_ALL_RSRC);
+		return 1;
 	}
 
 	return 0;
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/platforms/44x/Makefile linux-libre-2.6.38-gnu1/arch/powerpc/platforms/44x/Makefile
--- linux-libre-2.6.37-gnu1/arch/powerpc/platforms/44x/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/platforms/44x/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -1,4 +1,7 @@
-obj-$(CONFIG_44x)	:= misc_44x.o idle.o
+obj-$(CONFIG_44x)	+= misc_44x.o
+ifneq ($(CONFIG_PPC4xx_CPM),y)
+obj-$(CONFIG_44x)	+= idle.o
+endif
 obj-$(CONFIG_PPC44x_SIMPLE) += ppc44x_simple.o
 obj-$(CONFIG_EBONY)	+= ebony.o
 obj-$(CONFIG_SAM440EP) 	+= sam440ep.o
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/platforms/512x/mpc5121_generic.c linux-libre-2.6.38-gnu1/arch/powerpc/platforms/512x/mpc5121_generic.c
--- linux-libre-2.6.37-gnu1/arch/powerpc/platforms/512x/mpc5121_generic.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/platforms/512x/mpc5121_generic.c	2011-03-14 21:20:32.000000000 -0400
@@ -26,7 +26,7 @@
 /*
  * list of supported boards
  */
-static char *board[] __initdata = {
+static const char *board[] __initdata = {
 	"prt,prtlvt",
 	NULL
 };
@@ -36,16 +36,7 @@ static char *board[] __initdata = {
  */
 static int __init mpc5121_generic_probe(void)
 {
-	unsigned long node = of_get_flat_dt_root();
-	int i = 0;
-
-	while (board[i]) {
-		if (of_flat_dt_is_compatible(node, board[i]))
-			break;
-		i++;
-	}
-
-	return board[i] != NULL;
+	return of_flat_dt_match(of_get_flat_dt_root(), board);
 }
 
 define_machine(mpc5121_generic) {
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/platforms/52xx/lite5200.c linux-libre-2.6.38-gnu1/arch/powerpc/platforms/52xx/lite5200.c
--- linux-libre-2.6.37-gnu1/arch/powerpc/platforms/52xx/lite5200.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/platforms/52xx/lite5200.c	2011-03-14 21:20:32.000000000 -0400
@@ -172,20 +172,18 @@ static void __init lite5200_setup_arch(v
 	mpc52xx_setup_pci();
 }
 
+static const char *board[] __initdata = {
+	"fsl,lite5200",
+	"fsl,lite5200b",
+	NULL,
+};
+
 /*
  * Called very early, MMU is off, device-tree isn't unflattened
  */
 static int __init lite5200_probe(void)
 {
-	unsigned long node = of_get_flat_dt_root();
-	const char *model = of_get_flat_dt_prop(node, "model", NULL);
-
-	if (!of_flat_dt_is_compatible(node, "fsl,lite5200") &&
-	    !of_flat_dt_is_compatible(node, "fsl,lite5200b"))
-		return 0;
-	pr_debug("%s board found\n", model ? model : "unknown");
-
-	return 1;
+	return of_flat_dt_match(of_get_flat_dt_root(), board);
 }
 
 define_machine(lite5200) {
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/platforms/52xx/lite5200_pm.c linux-libre-2.6.38-gnu1/arch/powerpc/platforms/52xx/lite5200_pm.c
--- linux-libre-2.6.37-gnu1/arch/powerpc/platforms/52xx/lite5200_pm.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/platforms/52xx/lite5200_pm.c	2011-03-14 21:20:32.000000000 -0400
@@ -232,7 +232,7 @@ static void lite5200_pm_end(void)
 	lite5200_pm_target_state = PM_SUSPEND_ON;
 }
 
-static struct platform_suspend_ops lite5200_pm_ops = {
+static const struct platform_suspend_ops lite5200_pm_ops = {
 	.valid		= lite5200_pm_valid,
 	.begin		= lite5200_pm_begin,
 	.prepare	= lite5200_pm_prepare,
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/platforms/52xx/media5200.c linux-libre-2.6.38-gnu1/arch/powerpc/platforms/52xx/media5200.c
--- linux-libre-2.6.37-gnu1/arch/powerpc/platforms/52xx/media5200.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/platforms/52xx/media5200.c	2011-03-14 21:20:32.000000000 -0400
@@ -239,7 +239,7 @@ static void __init media5200_setup_arch(
 }
 
 /* list of the supported boards */
-static char *board[] __initdata = {
+static const char *board[] __initdata = {
 	"fsl,media5200",
 	NULL
 };
@@ -249,16 +249,7 @@ static char *board[] __initdata = {
  */
 static int __init media5200_probe(void)
 {
-	unsigned long node = of_get_flat_dt_root();
-	int i = 0;
-
-	while (board[i]) {
-		if (of_flat_dt_is_compatible(node, board[i]))
-			break;
-		i++;
-	}
-
-	return (board[i] != NULL);
+	return of_flat_dt_match(of_get_flat_dt_root(), board);
 }
 
 define_machine(media5200_platform) {
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/platforms/52xx/mpc5200_simple.c linux-libre-2.6.38-gnu1/arch/powerpc/platforms/52xx/mpc5200_simple.c
--- linux-libre-2.6.37-gnu1/arch/powerpc/platforms/52xx/mpc5200_simple.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/platforms/52xx/mpc5200_simple.c	2011-03-14 21:20:32.000000000 -0400
@@ -49,7 +49,7 @@ static void __init mpc5200_simple_setup_
 }
 
 /* list of the supported boards */
-static char *board[] __initdata = {
+static const char *board[] __initdata = {
 	"intercontrol,digsy-mtc",
 	"manroland,mucmc52",
 	"manroland,uc101",
@@ -66,16 +66,7 @@ static char *board[] __initdata = {
  */
 static int __init mpc5200_simple_probe(void)
 {
-	unsigned long node = of_get_flat_dt_root();
-	int i = 0;
-
-	while (board[i]) {
-		if (of_flat_dt_is_compatible(node, board[i]))
-			break;
-		i++;
-	}
-	
-	return (board[i] != NULL);
+	return of_flat_dt_match(of_get_flat_dt_root(), board);
 }
 
 define_machine(mpc5200_simple_platform) {
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/platforms/52xx/mpc52xx_pm.c linux-libre-2.6.38-gnu1/arch/powerpc/platforms/52xx/mpc52xx_pm.c
--- linux-libre-2.6.37-gnu1/arch/powerpc/platforms/52xx/mpc52xx_pm.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/platforms/52xx/mpc52xx_pm.c	2011-03-14 21:20:32.000000000 -0400
@@ -186,7 +186,7 @@ void mpc52xx_pm_finish(void)
 	iounmap(mbar);
 }
 
-static struct platform_suspend_ops mpc52xx_pm_ops = {
+static const struct platform_suspend_ops mpc52xx_pm_ops = {
 	.valid		= mpc52xx_pm_valid,
 	.prepare	= mpc52xx_pm_prepare,
 	.enter		= mpc52xx_pm_enter,
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/platforms/83xx/mpc830x_rdb.c linux-libre-2.6.38-gnu1/arch/powerpc/platforms/83xx/mpc830x_rdb.c
--- linux-libre-2.6.37-gnu1/arch/powerpc/platforms/83xx/mpc830x_rdb.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/platforms/83xx/mpc830x_rdb.c	2011-03-14 21:20:32.000000000 -0400
@@ -57,16 +57,19 @@ static void __init mpc830x_rdb_init_IRQ(
 	ipic_set_default_priority();
 }
 
+static const char *board[] __initdata = {
+	"MPC8308RDB",
+	"fsl,mpc8308rdb",
+	"denx,mpc8308_p1m",
+	NULL
+};
+
 /*
  * Called very early, MMU is off, device-tree isn't unflattened
  */
 static int __init mpc830x_rdb_probe(void)
 {
-	unsigned long root = of_get_flat_dt_root();
-
-	return of_flat_dt_is_compatible(root, "MPC8308RDB") ||
-	       of_flat_dt_is_compatible(root, "fsl,mpc8308rdb") ||
-	       of_flat_dt_is_compatible(root, "denx,mpc8308_p1m");
+	return of_flat_dt_match(of_get_flat_dt_root(), board);
 }
 
 static struct of_device_id __initdata of_bus_ids[] = {
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/platforms/83xx/mpc831x_rdb.c linux-libre-2.6.38-gnu1/arch/powerpc/platforms/83xx/mpc831x_rdb.c
--- linux-libre-2.6.37-gnu1/arch/powerpc/platforms/83xx/mpc831x_rdb.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/platforms/83xx/mpc831x_rdb.c	2011-03-14 21:20:32.000000000 -0400
@@ -60,15 +60,18 @@ static void __init mpc831x_rdb_init_IRQ(
 	ipic_set_default_priority();
 }
 
+static const char *board[] __initdata = {
+	"MPC8313ERDB",
+	"fsl,mpc8315erdb",
+	NULL
+};
+
 /*
  * Called very early, MMU is off, device-tree isn't unflattened
  */
 static int __init mpc831x_rdb_probe(void)
 {
-	unsigned long root = of_get_flat_dt_root();
-
-	return of_flat_dt_is_compatible(root, "MPC8313ERDB") ||
-	       of_flat_dt_is_compatible(root, "fsl,mpc8315erdb");
+	return of_flat_dt_match(of_get_flat_dt_root(), board);
 }
 
 static struct of_device_id __initdata of_bus_ids[] = {
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/platforms/83xx/mpc837x_rdb.c linux-libre-2.6.38-gnu1/arch/powerpc/platforms/83xx/mpc837x_rdb.c
--- linux-libre-2.6.37-gnu1/arch/powerpc/platforms/83xx/mpc837x_rdb.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/platforms/83xx/mpc837x_rdb.c	2011-03-14 21:20:32.000000000 -0400
@@ -101,17 +101,20 @@ static void __init mpc837x_rdb_init_IRQ(
 	ipic_set_default_priority();
 }
 
+static const char *board[] __initdata = {
+	"fsl,mpc8377rdb",
+	"fsl,mpc8378rdb",
+	"fsl,mpc8379rdb",
+	"fsl,mpc8377wlan",
+	NULL
+};
+
 /*
  * Called very early, MMU is off, device-tree isn't unflattened
  */
 static int __init mpc837x_rdb_probe(void)
 {
-	unsigned long root = of_get_flat_dt_root();
-
-	return of_flat_dt_is_compatible(root, "fsl,mpc8377rdb") ||
-	       of_flat_dt_is_compatible(root, "fsl,mpc8378rdb") ||
-	       of_flat_dt_is_compatible(root, "fsl,mpc8379rdb") ||
-	       of_flat_dt_is_compatible(root, "fsl,mpc8377wlan");
+	return of_flat_dt_match(of_get_flat_dt_root(), board);
 }
 
 define_machine(mpc837x_rdb) {
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/platforms/83xx/mpc83xx.h linux-libre-2.6.38-gnu1/arch/powerpc/platforms/83xx/mpc83xx.h
--- linux-libre-2.6.37-gnu1/arch/powerpc/platforms/83xx/mpc83xx.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/platforms/83xx/mpc83xx.h	2011-03-14 21:20:32.000000000 -0400
@@ -35,6 +35,8 @@
 
 /* system i/o configuration register high */
 #define MPC83XX_SICRH_OFFS         0x118
+#define MPC8308_SICRH_USB_MASK     0x000c0000
+#define MPC8308_SICRH_USB_ULPI     0x00040000
 #define MPC834X_SICRH_USB_UTMI     0x00020000
 #define MPC831X_SICRH_USB_MASK     0x000000e0
 #define MPC831X_SICRH_USB_ULPI     0x000000a0
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/platforms/83xx/suspend-asm.S linux-libre-2.6.38-gnu1/arch/powerpc/platforms/83xx/suspend-asm.S
--- linux-libre-2.6.37-gnu1/arch/powerpc/platforms/83xx/suspend-asm.S	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/platforms/83xx/suspend-asm.S	2011-03-14 21:20:32.000000000 -0400
@@ -231,7 +231,7 @@ _GLOBAL(mpc83xx_enter_deep_sleep)
 	ori	r4, r4, 0x002a
 	mtspr	SPRN_DBAT0L, r4
 	lis	r8, TMP_VIRT_IMMR@h
-	ori	r4, r8, 0x001e	/* 1 MByte accessable from Kernel Space only */
+	ori	r4, r8, 0x001e	/* 1 MByte accessible from Kernel Space only */
 	mtspr	SPRN_DBAT0U, r4
 	isync
 
@@ -241,7 +241,7 @@ _GLOBAL(mpc83xx_enter_deep_sleep)
 	ori	r4, r4, 0x002a
 	mtspr	SPRN_DBAT1L, r4
 	lis	r9, (TMP_VIRT_IMMR + 0x01000000)@h
-	ori	r4, r9, 0x001e	/* 1 MByte accessable from Kernel Space only */
+	ori	r4, r9, 0x001e	/* 1 MByte accessible from Kernel Space only */
 	mtspr	SPRN_DBAT1U, r4
 	isync
 
@@ -253,7 +253,7 @@ _GLOBAL(mpc83xx_enter_deep_sleep)
 	li	r4, 0x0002
 	mtspr	SPRN_DBAT2L, r4
 	lis	r4, KERNELBASE@h
-	ori	r4, r4, 0x001e	/* 1 MByte accessable from Kernel Space only */
+	ori	r4, r4, 0x001e	/* 1 MByte accessible from Kernel Space only */
 	mtspr	SPRN_DBAT2U, r4
 	isync
 
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/platforms/83xx/suspend.c linux-libre-2.6.38-gnu1/arch/powerpc/platforms/83xx/suspend.c
--- linux-libre-2.6.37-gnu1/arch/powerpc/platforms/83xx/suspend.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/platforms/83xx/suspend.c	2011-03-14 21:20:32.000000000 -0400
@@ -311,7 +311,7 @@ static int mpc83xx_is_pci_agent(void)
 	return ret;
 }
 
-static struct platform_suspend_ops mpc83xx_suspend_ops = {
+static const struct platform_suspend_ops mpc83xx_suspend_ops = {
 	.valid = mpc83xx_suspend_valid,
 	.begin = mpc83xx_suspend_begin,
 	.enter = mpc83xx_suspend_enter,
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/platforms/83xx/usb.c linux-libre-2.6.38-gnu1/arch/powerpc/platforms/83xx/usb.c
--- linux-libre-2.6.37-gnu1/arch/powerpc/platforms/83xx/usb.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/platforms/83xx/usb.c	2011-03-14 21:20:32.000000000 -0400
@@ -127,7 +127,8 @@ int mpc831x_usb_cfg(void)
 
 	/* Configure clock */
 	immr_node = of_get_parent(np);
-	if (immr_node && of_device_is_compatible(immr_node, "fsl,mpc8315-immr"))
+	if (immr_node && (of_device_is_compatible(immr_node, "fsl,mpc8315-immr") ||
+			of_device_is_compatible(immr_node, "fsl,mpc8308-immr")))
 		clrsetbits_be32(immap + MPC83XX_SCCR_OFFS,
 		                MPC8315_SCCR_USB_MASK,
 		                MPC8315_SCCR_USB_DRCM_01);
@@ -138,7 +139,11 @@ int mpc831x_usb_cfg(void)
 
 	/* Configure pin mux for ULPI.  There is no pin mux for UTMI */
 	if (prop && !strcmp(prop, "ulpi")) {
-		if (of_device_is_compatible(immr_node, "fsl,mpc8315-immr")) {
+		if (of_device_is_compatible(immr_node, "fsl,mpc8308-immr")) {
+			clrsetbits_be32(immap + MPC83XX_SICRH_OFFS,
+					MPC8308_SICRH_USB_MASK,
+					MPC8308_SICRH_USB_ULPI);
+		} else if (of_device_is_compatible(immr_node, "fsl,mpc8315-immr")) {
 			clrsetbits_be32(immap + MPC83XX_SICRL_OFFS,
 					MPC8315_SICRL_USB_MASK,
 					MPC8315_SICRL_USB_ULPI);
@@ -173,6 +178,9 @@ int mpc831x_usb_cfg(void)
 		     !strcmp(prop, "utmi"))) {
 		u32 refsel;
 
+		if (of_device_is_compatible(immr_node, "fsl,mpc8308-immr"))
+			goto out;
+
 		if (of_device_is_compatible(immr_node, "fsl,mpc8315-immr"))
 			refsel = CONTROL_REFSEL_24MHZ;
 		else
@@ -186,9 +194,11 @@ int mpc831x_usb_cfg(void)
 		temp = CONTROL_PHY_CLK_SEL_ULPI;
 #ifdef CONFIG_USB_OTG
 		/* Set OTG_PORT */
-		dr_mode = of_get_property(np, "dr_mode", NULL);
-		if (dr_mode && !strcmp(dr_mode, "otg"))
-			temp |= CONTROL_OTG_PORT;
+		if (!of_device_is_compatible(immr_node, "fsl,mpc8308-immr")) {
+			dr_mode = of_get_property(np, "dr_mode", NULL);
+			if (dr_mode && !strcmp(dr_mode, "otg"))
+				temp |= CONTROL_OTG_PORT;
+		}
 #endif /* CONFIG_USB_OTG */
 		out_be32(usb_regs + FSL_USB2_CONTROL_OFFS, temp);
 	} else {
@@ -196,6 +206,7 @@ int mpc831x_usb_cfg(void)
 		ret = -EINVAL;
 	}
 
+out:
 	iounmap(usb_regs);
 	of_node_put(np);
 	return ret;
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/platforms/85xx/mpc85xx_mds.c linux-libre-2.6.38-gnu1/arch/powerpc/platforms/85xx/mpc85xx_mds.c
--- linux-libre-2.6.37-gnu1/arch/powerpc/platforms/85xx/mpc85xx_mds.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/platforms/85xx/mpc85xx_mds.c	2011-03-14 21:20:32.000000000 -0400
@@ -309,7 +309,7 @@ static void __init mpc85xx_mds_qe_init(v
 			/* P1021 has pins muxed for QE and other functions. To
 			 * enable QE UEC mode, we need to set bit QE0 for UCC1
 			 * in Eth mode, QE0 and QE3 for UCC5 in Eth mode, QE9
-			 * and QE12 for QE MII management singals in PMUXCR
+			 * and QE12 for QE MII management signals in PMUXCR
 			 * register.
 			 */
 				setbits32(pmuxcr, MPC85xx_PMUXCR_QE0 |
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/platforms/85xx/tqm85xx.c linux-libre-2.6.38-gnu1/arch/powerpc/platforms/85xx/tqm85xx.c
--- linux-libre-2.6.37-gnu1/arch/powerpc/platforms/85xx/tqm85xx.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/platforms/85xx/tqm85xx.c	2011-03-14 21:20:32.000000000 -0400
@@ -186,21 +186,21 @@ static int __init declare_of_platform_de
 }
 machine_device_initcall(tqm85xx, declare_of_platform_devices);
 
+static const char *board[] __initdata = {
+	"tqc,tqm8540",
+	"tqc,tqm8541",
+	"tqc,tqm8548",
+	"tqc,tqm8555",
+	"tqc,tqm8560",
+	NULL
+};
+
 /*
  * Called very early, device-tree isn't unflattened
  */
 static int __init tqm85xx_probe(void)
 {
-	unsigned long root = of_get_flat_dt_root();
-
-	if ((of_flat_dt_is_compatible(root, "tqc,tqm8540")) ||
-	    (of_flat_dt_is_compatible(root, "tqc,tqm8541")) ||
-	    (of_flat_dt_is_compatible(root, "tqc,tqm8548")) ||
-	    (of_flat_dt_is_compatible(root, "tqc,tqm8555")) ||
-	    (of_flat_dt_is_compatible(root, "tqc,tqm8560")))
-		return 1;
-
-	return 0;
+	return of_flat_dt_match(of_get_flat_dt_root(), board);
 }
 
 define_machine(tqm85xx) {
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/platforms/cell/beat_iommu.c linux-libre-2.6.38-gnu1/arch/powerpc/platforms/cell/beat_iommu.c
--- linux-libre-2.6.37-gnu1/arch/powerpc/platforms/cell/beat_iommu.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/platforms/cell/beat_iommu.c	2011-03-14 21:20:32.000000000 -0400
@@ -76,7 +76,7 @@ static void __init celleb_init_direct_ma
 
 static void celleb_dma_dev_setup(struct device *dev)
 {
-	dev->archdata.dma_ops = get_pci_dma_ops();
+	set_dma_ops(dev, &dma_direct_ops);
 	set_dma_offset(dev, celleb_dma_direct_offset);
 }
 
@@ -106,7 +106,6 @@ static struct notifier_block celleb_of_b
 static int __init celleb_init_iommu(void)
 {
 	celleb_init_direct_mapping();
-	set_pci_dma_ops(&dma_direct_ops);
 	ppc_md.pci_dma_dev_setup = celleb_pci_dma_dev_setup;
 	bus_register_notifier(&platform_bus_type, &celleb_of_bus_notifier);
 
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/platforms/cell/cpufreq_spudemand.c linux-libre-2.6.38-gnu1/arch/powerpc/platforms/cell/cpufreq_spudemand.c
--- linux-libre-2.6.37-gnu1/arch/powerpc/platforms/cell/cpufreq_spudemand.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/platforms/cell/cpufreq_spudemand.c	2011-03-14 21:20:32.000000000 -0400
@@ -39,8 +39,6 @@ struct spu_gov_info_struct {
 };
 static DEFINE_PER_CPU(struct spu_gov_info_struct, spu_gov_info);
 
-static struct workqueue_struct *kspugov_wq;
-
 static int calc_freq(struct spu_gov_info_struct *info)
 {
 	int cpu;
@@ -71,14 +69,14 @@ static void spu_gov_work(struct work_str
 	__cpufreq_driver_target(info->policy, target_freq, CPUFREQ_RELATION_H);
 
 	delay = usecs_to_jiffies(info->poll_int);
-	queue_delayed_work_on(info->policy->cpu, kspugov_wq, &info->work, delay);
+	schedule_delayed_work_on(info->policy->cpu, &info->work, delay);
 }
 
 static void spu_gov_init_work(struct spu_gov_info_struct *info)
 {
 	int delay = usecs_to_jiffies(info->poll_int);
 	INIT_DELAYED_WORK_DEFERRABLE(&info->work, spu_gov_work);
-	queue_delayed_work_on(info->policy->cpu, kspugov_wq, &info->work, delay);
+	schedule_delayed_work_on(info->policy->cpu, &info->work, delay);
 }
 
 static void spu_gov_cancel_work(struct spu_gov_info_struct *info)
@@ -152,27 +150,15 @@ static int __init spu_gov_init(void)
 {
 	int ret;
 
-	kspugov_wq = create_workqueue("kspugov");
-	if (!kspugov_wq) {
-		printk(KERN_ERR "creation of kspugov failed\n");
-		ret = -EFAULT;
-		goto out;
-	}
-
 	ret = cpufreq_register_governor(&spu_governor);
-	if (ret) {
+	if (ret)
 		printk(KERN_ERR "registration of governor failed\n");
-		destroy_workqueue(kspugov_wq);
-		goto out;
-	}
-out:
 	return ret;
 }
 
 static void __exit spu_gov_exit(void)
 {
 	cpufreq_unregister_governor(&spu_governor);
-	destroy_workqueue(kspugov_wq);
 }
 
 
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/platforms/cell/qpace_setup.c linux-libre-2.6.38-gnu1/arch/powerpc/platforms/cell/qpace_setup.c
--- linux-libre-2.6.37-gnu1/arch/powerpc/platforms/cell/qpace_setup.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/platforms/cell/qpace_setup.c	2011-03-14 21:20:32.000000000 -0400
@@ -145,9 +145,4 @@ define_machine(qpace) {
 	.calibrate_decr		= generic_calibrate_decr,
 	.progress		= qpace_progress,
 	.init_IRQ		= iic_init_IRQ,
-#ifdef CONFIG_KEXEC
-	.machine_kexec		= default_machine_kexec,
-	.machine_kexec_prepare	= default_machine_kexec_prepare,
-	.machine_crash_shutdown	= default_machine_crash_shutdown,
-#endif
 };
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/platforms/cell/spu_base.c linux-libre-2.6.38-gnu1/arch/powerpc/platforms/cell/spu_base.c
--- linux-libre-2.6.37-gnu1/arch/powerpc/platforms/cell/spu_base.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/platforms/cell/spu_base.c	2011-03-14 21:20:32.000000000 -0400
@@ -37,6 +37,7 @@
 #include <asm/spu_csa.h>
 #include <asm/xmon.h>
 #include <asm/prom.h>
+#include <asm/kexec.h>
 
 const struct spu_management_ops *spu_management_ops;
 EXPORT_SYMBOL_GPL(spu_management_ops);
@@ -727,6 +728,75 @@ static ssize_t spu_stat_show(struct sys_
 
 static SYSDEV_ATTR(stat, 0644, spu_stat_show, NULL);
 
+#ifdef CONFIG_KEXEC
+
+struct crash_spu_info {
+	struct spu *spu;
+	u32 saved_spu_runcntl_RW;
+	u32 saved_spu_status_R;
+	u32 saved_spu_npc_RW;
+	u64 saved_mfc_sr1_RW;
+	u64 saved_mfc_dar;
+	u64 saved_mfc_dsisr;
+};
+
+#define CRASH_NUM_SPUS	16	/* Enough for current hardware */
+static struct crash_spu_info crash_spu_info[CRASH_NUM_SPUS];
+
+static void crash_kexec_stop_spus(void)
+{
+	struct spu *spu;
+	int i;
+	u64 tmp;
+
+	for (i = 0; i < CRASH_NUM_SPUS; i++) {
+		if (!crash_spu_info[i].spu)
+			continue;
+
+		spu = crash_spu_info[i].spu;
+
+		crash_spu_info[i].saved_spu_runcntl_RW =
+			in_be32(&spu->problem->spu_runcntl_RW);
+		crash_spu_info[i].saved_spu_status_R =
+			in_be32(&spu->problem->spu_status_R);
+		crash_spu_info[i].saved_spu_npc_RW =
+			in_be32(&spu->problem->spu_npc_RW);
+
+		crash_spu_info[i].saved_mfc_dar    = spu_mfc_dar_get(spu);
+		crash_spu_info[i].saved_mfc_dsisr  = spu_mfc_dsisr_get(spu);
+		tmp = spu_mfc_sr1_get(spu);
+		crash_spu_info[i].saved_mfc_sr1_RW = tmp;
+
+		tmp &= ~MFC_STATE1_MASTER_RUN_CONTROL_MASK;
+		spu_mfc_sr1_set(spu, tmp);
+
+		__delay(200);
+	}
+}
+
+static void crash_register_spus(struct list_head *list)
+{
+	struct spu *spu;
+	int ret;
+
+	list_for_each_entry(spu, list, full_list) {
+		if (WARN_ON(spu->number >= CRASH_NUM_SPUS))
+			continue;
+
+		crash_spu_info[spu->number].spu = spu;
+	}
+
+	ret = crash_shutdown_register(&crash_kexec_stop_spus);
+	if (ret)
+		printk(KERN_ERR "Could not register SPU crash handler");
+}
+
+#else
+static inline void crash_register_spus(struct list_head *list)
+{
+}
+#endif
+
 static int __init init_spu_base(void)
 {
 	int i, ret = 0;
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/platforms/cell/spufs/file.c linux-libre-2.6.38-gnu1/arch/powerpc/platforms/cell/spufs/file.c
--- linux-libre-2.6.37-gnu1/arch/powerpc/platforms/cell/spufs/file.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/platforms/cell/spufs/file.c	2011-03-14 21:20:32.000000000 -0400
@@ -219,24 +219,17 @@ spufs_mem_write(struct file *file, const
 	loff_t pos = *ppos;
 	int ret;
 
-	if (pos < 0)
-		return -EINVAL;
 	if (pos > LS_SIZE)
 		return -EFBIG;
-	if (size > LS_SIZE - pos)
-		size = LS_SIZE - pos;
 
 	ret = spu_acquire(ctx);
 	if (ret)
 		return ret;
 
 	local_store = ctx->ops->get_ls(ctx);
-	ret = copy_from_user(local_store + pos, buffer, size);
+	size = simple_write_to_buffer(local_store, LS_SIZE, ppos, buffer, size);
 	spu_release(ctx);
 
-	if (ret)
-		return -EFAULT;
-	*ppos = pos + size;
 	return size;
 }
 
@@ -574,18 +567,15 @@ spufs_regs_write(struct file *file, cons
 	if (*pos >= sizeof(lscsa->gprs))
 		return -EFBIG;
 
-	size = min_t(ssize_t, sizeof(lscsa->gprs) - *pos, size);
-	*pos += size;
-
 	ret = spu_acquire_saved(ctx);
 	if (ret)
 		return ret;
 
-	ret = copy_from_user((char *)lscsa->gprs + *pos - size,
-			     buffer, size) ? -EFAULT : size;
+	size = simple_write_to_buffer(lscsa->gprs, sizeof(lscsa->gprs), pos,
+					buffer, size);
 
 	spu_release_saved(ctx);
-	return ret;
+	return size;
 }
 
 static const struct file_operations spufs_regs_fops = {
@@ -630,18 +620,15 @@ spufs_fpcr_write(struct file *file, cons
 	if (*pos >= sizeof(lscsa->fpcr))
 		return -EFBIG;
 
-	size = min_t(ssize_t, sizeof(lscsa->fpcr) - *pos, size);
-
 	ret = spu_acquire_saved(ctx);
 	if (ret)
 		return ret;
 
-	*pos += size;
-	ret = copy_from_user((char *)&lscsa->fpcr + *pos - size,
-			     buffer, size) ? -EFAULT : size;
+	size = simple_write_to_buffer(&lscsa->fpcr, sizeof(lscsa->fpcr), pos,
+					buffer, size);
 
 	spu_release_saved(ctx);
-	return ret;
+	return size;
 }
 
 static const struct file_operations spufs_fpcr_fops = {
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/platforms/cell/spufs/inode.c linux-libre-2.6.38-gnu1/arch/powerpc/platforms/cell/spufs/inode.c
--- linux-libre-2.6.37-gnu1/arch/powerpc/platforms/cell/spufs/inode.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/platforms/cell/spufs/inode.c	2011-03-14 21:20:32.000000000 -0400
@@ -71,12 +71,18 @@ spufs_alloc_inode(struct super_block *sb
 	return &ei->vfs_inode;
 }
 
-static void
-spufs_destroy_inode(struct inode *inode)
+static void spufs_i_callback(struct rcu_head *head)
 {
+	struct inode *inode = container_of(head, struct inode, i_rcu);
+	INIT_LIST_HEAD(&inode->i_dentry);
 	kmem_cache_free(spufs_inode_cache, SPUFS_I(inode));
 }
 
+static void spufs_destroy_inode(struct inode *inode)
+{
+	call_rcu(&inode->i_rcu, spufs_i_callback);
+}
+
 static void
 spufs_init_once(void *p)
 {
@@ -159,18 +165,18 @@ static void spufs_prune_dir(struct dentr
 
 	mutex_lock(&dir->d_inode->i_mutex);
 	list_for_each_entry_safe(dentry, tmp, &dir->d_subdirs, d_u.d_child) {
-		spin_lock(&dcache_lock);
 		spin_lock(&dentry->d_lock);
 		if (!(d_unhashed(dentry)) && dentry->d_inode) {
-			dget_locked(dentry);
+			dget_dlock(dentry);
 			__d_drop(dentry);
 			spin_unlock(&dentry->d_lock);
 			simple_unlink(dir->d_inode, dentry);
-			spin_unlock(&dcache_lock);
+			/* XXX: what was dcache_lock protecting here? Other
+			 * filesystems (IB, configfs) release dcache_lock
+			 * before unlink */
 			dput(dentry);
 		} else {
 			spin_unlock(&dentry->d_lock);
-			spin_unlock(&dcache_lock);
 		}
 	}
 	shrink_dcache_parent(dir);
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/platforms/cell/spufs/lscsa_alloc.c linux-libre-2.6.38-gnu1/arch/powerpc/platforms/cell/spufs/lscsa_alloc.c
--- linux-libre-2.6.37-gnu1/arch/powerpc/platforms/cell/spufs/lscsa_alloc.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/platforms/cell/spufs/lscsa_alloc.c	2011-03-14 21:20:32.000000000 -0400
@@ -36,10 +36,9 @@ static int spu_alloc_lscsa_std(struct sp
 	struct spu_lscsa *lscsa;
 	unsigned char *p;
 
-	lscsa = vmalloc(sizeof(struct spu_lscsa));
+	lscsa = vzalloc(sizeof(struct spu_lscsa));
 	if (!lscsa)
 		return -ENOMEM;
-	memset(lscsa, 0, sizeof(struct spu_lscsa));
 	csa->lscsa = lscsa;
 
 	/* Set LS pages reserved to allow for user-space mapping. */
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/platforms/chrp/time.c linux-libre-2.6.38-gnu1/arch/powerpc/platforms/chrp/time.c
--- linux-libre-2.6.37-gnu1/arch/powerpc/platforms/chrp/time.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/platforms/chrp/time.c	2011-03-14 21:20:32.000000000 -0400
@@ -29,6 +29,10 @@
 
 extern spinlock_t rtc_lock;
 
+#define NVRAM_AS0  0x74
+#define NVRAM_AS1  0x75
+#define NVRAM_DATA 0x77
+
 static int nvram_as1 = NVRAM_AS1;
 static int nvram_as0 = NVRAM_AS0;
 static int nvram_data = NVRAM_DATA;
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/platforms/embedded6xx/gamecube.c linux-libre-2.6.38-gnu1/arch/powerpc/platforms/embedded6xx/gamecube.c
--- linux-libre-2.6.37-gnu1/arch/powerpc/platforms/embedded6xx/gamecube.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/platforms/embedded6xx/gamecube.c	2011-03-14 21:20:32.000000000 -0400
@@ -75,14 +75,6 @@ static void gamecube_shutdown(void)
 	flipper_quiesce();
 }
 
-#ifdef CONFIG_KEXEC
-static int gamecube_kexec_prepare(struct kimage *image)
-{
-	return 0;
-}
-#endif /* CONFIG_KEXEC */
-
-
 define_machine(gamecube) {
 	.name			= "gamecube",
 	.probe			= gamecube_probe,
@@ -95,9 +87,6 @@ define_machine(gamecube) {
 	.calibrate_decr		= generic_calibrate_decr,
 	.progress		= udbg_progress,
 	.machine_shutdown	= gamecube_shutdown,
-#ifdef CONFIG_KEXEC
-	.machine_kexec_prepare	= gamecube_kexec_prepare,
-#endif
 };
 
 
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/platforms/embedded6xx/wii.c linux-libre-2.6.38-gnu1/arch/powerpc/platforms/embedded6xx/wii.c
--- linux-libre-2.6.37-gnu1/arch/powerpc/platforms/embedded6xx/wii.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/platforms/embedded6xx/wii.c	2011-03-14 21:20:32.000000000 -0400
@@ -18,7 +18,6 @@
 #include <linux/init.h>
 #include <linux/irq.h>
 #include <linux/seq_file.h>
-#include <linux/kexec.h>
 #include <linux/of_platform.h>
 #include <linux/memblock.h>
 #include <mm/mmu_decl.h>
@@ -226,13 +225,6 @@ static void wii_shutdown(void)
 	flipper_quiesce();
 }
 
-#ifdef CONFIG_KEXEC
-static int wii_machine_kexec_prepare(struct kimage *image)
-{
-	return 0;
-}
-#endif /* CONFIG_KEXEC */
-
 define_machine(wii) {
 	.name			= "wii",
 	.probe			= wii_probe,
@@ -246,9 +238,6 @@ define_machine(wii) {
 	.calibrate_decr		= generic_calibrate_decr,
 	.progress		= udbg_progress,
 	.machine_shutdown	= wii_shutdown,
-#ifdef CONFIG_KEXEC
-	.machine_kexec_prepare	= wii_machine_kexec_prepare,
-#endif
 };
 
 static struct of_device_id wii_of_bus[] = {
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/platforms/iseries/dt.c linux-libre-2.6.38-gnu1/arch/powerpc/platforms/iseries/dt.c
--- linux-libre-2.6.37-gnu1/arch/powerpc/platforms/iseries/dt.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/platforms/iseries/dt.c	2011-03-14 21:20:32.000000000 -0400
@@ -242,8 +242,8 @@ static void __init dt_cpus(struct iserie
 	pft_size[0] = 0; /* NUMA CEC cookie, 0 for non NUMA  */
 	pft_size[1] = __ilog2(HvCallHpt_getHptPages() * HW_PAGE_SIZE);
 
-	for (i = 0; i < NR_CPUS; i++) {
-		if (lppaca_of(i).dyn_proc_status >= 2)
+	for (i = 0; i < NR_LPPACAS; i++) {
+		if (lppaca[i].dyn_proc_status >= 2)
 			continue;
 
 		snprintf(p, 32 - (p - buf), "@%d", i);
@@ -251,7 +251,7 @@ static void __init dt_cpus(struct iserie
 
 		dt_prop_str(dt, "device_type", device_type_cpu);
 
-		index = lppaca_of(i).dyn_hv_phys_proc_index;
+		index = lppaca[i].dyn_hv_phys_proc_index;
 		d = &xIoHriProcessorVpd[index];
 
 		dt_prop_u32(dt, "i-cache-size", d->xInstCacheSize * 1024);
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/platforms/iseries/Kconfig linux-libre-2.6.38-gnu1/arch/powerpc/platforms/iseries/Kconfig
--- linux-libre-2.6.37-gnu1/arch/powerpc/platforms/iseries/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/platforms/iseries/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -2,7 +2,7 @@ config PPC_ISERIES
 	bool "IBM Legacy iSeries"
 	depends on PPC64 && PPC_BOOK3S
 	select PPC_INDIRECT_IO
-	select PPC_PCI_CHOICE if EMBEDDED
+	select PPC_PCI_CHOICE if EXPERT
 
 menu "iSeries device drivers"
 	depends on PPC_ISERIES
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/platforms/iseries/mf.c linux-libre-2.6.38-gnu1/arch/powerpc/platforms/iseries/mf.c
--- linux-libre-2.6.37-gnu1/arch/powerpc/platforms/iseries/mf.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/platforms/iseries/mf.c	2011-03-14 21:20:32.000000000 -0400
@@ -1045,71 +1045,9 @@ static const struct file_operations mf_s
 	.write		= mf_side_proc_write,
 };
 
-#if 0
-static void mf_getSrcHistory(char *buffer, int size)
-{
-	struct IplTypeReturnStuff return_stuff;
-	struct pending_event *ev = new_pending_event();
-	int rc = 0;
-	char *pages[4];
-
-	pages[0] = kmalloc(4096, GFP_ATOMIC);
-	pages[1] = kmalloc(4096, GFP_ATOMIC);
-	pages[2] = kmalloc(4096, GFP_ATOMIC);
-	pages[3] = kmalloc(4096, GFP_ATOMIC);
-	if ((ev == NULL) || (pages[0] == NULL) || (pages[1] == NULL)
-			 || (pages[2] == NULL) || (pages[3] == NULL))
-		return -ENOMEM;
-
-	return_stuff.xType = 0;
-	return_stuff.xRc = 0;
-	return_stuff.xDone = 0;
-	ev->event.hp_lp_event.xSubtype = 6;
-	ev->event.hp_lp_event.x.xSubtypeData =
-		subtype_data('M', 'F', 'V', 'I');
-	ev->event.data.vsp_cmd.xEvent = &return_stuff;
-	ev->event.data.vsp_cmd.cmd = 4;
-	ev->event.data.vsp_cmd.lp_index = HvLpConfig_getLpIndex();
-	ev->event.data.vsp_cmd.result_code = 0xFF;
-	ev->event.data.vsp_cmd.reserved = 0;
-	ev->event.data.vsp_cmd.sub_data.page[0] = iseries_hv_addr(pages[0]);
-	ev->event.data.vsp_cmd.sub_data.page[1] = iseries_hv_addr(pages[1]);
-	ev->event.data.vsp_cmd.sub_data.page[2] = iseries_hv_addr(pages[2]);
-	ev->event.data.vsp_cmd.sub_data.page[3] = iseries_hv_addr(pages[3]);
-	mb();
-	if (signal_event(ev) != 0)
-		return;
-
- 	while (return_stuff.xDone != 1)
- 		udelay(10);
- 	if (return_stuff.xRc == 0)
- 		memcpy(buffer, pages[0], size);
-	kfree(pages[0]);
-	kfree(pages[1]);
-	kfree(pages[2]);
-	kfree(pages[3]);
-}
-#endif
-
 static int mf_src_proc_show(struct seq_file *m, void *v)
 {
-#if 0
-	int len;
-
-	mf_getSrcHistory(page, count);
-	len = count;
-	len -= off;
-	if (len < count) {
-		*eof = 1;
-		if (len <= 0)
-			return 0;
-	} else
-		len = count;
-	*start = page + off;
-	return len;
-#else
 	return 0;
-#endif
 }
 
 static int mf_src_proc_open(struct inode *inode, struct file *file)
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/platforms/iseries/setup.c linux-libre-2.6.38-gnu1/arch/powerpc/platforms/iseries/setup.c
--- linux-libre-2.6.37-gnu1/arch/powerpc/platforms/iseries/setup.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/platforms/iseries/setup.c	2011-03-14 21:20:32.000000000 -0400
@@ -680,6 +680,7 @@ void * __init iSeries_early_setup(void)
 	 * on but calling this function multiple times is fine.
 	 */
 	identify_cpu(0, mfspr(SPRN_PVR));
+	initialise_paca(&boot_paca, 0);
 
 	powerpc_firmware_features |= FW_FEATURE_ISERIES;
 	powerpc_firmware_features |= FW_FEATURE_LPAR;
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/platforms/Kconfig linux-libre-2.6.38-gnu1/arch/powerpc/platforms/Kconfig
--- linux-libre-2.6.37-gnu1/arch/powerpc/platforms/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/platforms/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -313,13 +313,14 @@ config OF_RTC
 source "arch/powerpc/sysdev/bestcomm/Kconfig"
 
 config MPC8xxx_GPIO
-	bool "MPC8xxx GPIO support"
-	depends on PPC_MPC831x || PPC_MPC834x || PPC_MPC837x || FSL_SOC_BOOKE || PPC_86xx
+	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
-	  MPC831x/834x/837x/8572/8610 GPIOs.
+	  MPC512x/831x/834x/837x/8572/8610 GPIOs.
 
 config SIMPLE_GPIO
 	bool "Support for simple, memory-mapped GPIO controllers"
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/platforms/pasemi/iommu.c linux-libre-2.6.38-gnu1/arch/powerpc/platforms/pasemi/iommu.c
--- linux-libre-2.6.37-gnu1/arch/powerpc/platforms/pasemi/iommu.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/platforms/pasemi/iommu.c	2011-03-14 21:20:32.000000000 -0400
@@ -156,20 +156,12 @@ static void iommu_table_iobmap_setup(voi
 
 static void pci_dma_bus_setup_pasemi(struct pci_bus *bus)
 {
-	struct device_node *dn;
-
 	pr_debug("pci_dma_bus_setup, bus %p, bus->self %p\n", bus, bus->self);
 
 	if (!iommu_table_iobmap_inited) {
 		iommu_table_iobmap_inited = 1;
 		iommu_table_iobmap_setup();
 	}
-
-	dn = pci_bus_to_OF_node(bus);
-
-	if (dn)
-		PCI_DN(dn)->iommu_table = &iommu_table_iobmap;
-
 }
 
 
@@ -192,9 +184,6 @@ static void pci_dma_dev_setup_pasemi(str
 	set_iommu_table_base(&dev->dev, &iommu_table_iobmap);
 }
 
-static void pci_dma_bus_setup_null(struct pci_bus *b) { }
-static void pci_dma_dev_setup_null(struct pci_dev *d) { }
-
 int __init iob_init(struct device_node *dn)
 {
 	unsigned long tmp;
@@ -251,14 +240,8 @@ void __init iommu_init_early_pasemi(void
 	iommu_off = of_chosen &&
 			of_get_property(of_chosen, "linux,iommu-off", NULL);
 #endif
-	if (iommu_off) {
-		/* Direct I/O, IOMMU off */
-		ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_null;
-		ppc_md.pci_dma_bus_setup = pci_dma_bus_setup_null;
-		set_pci_dma_ops(&dma_direct_ops);
-
+	if (iommu_off)
 		return;
-	}
 
 	iob_init(NULL);
 
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/platforms/powermac/setup.c linux-libre-2.6.38-gnu1/arch/powerpc/platforms/powermac/setup.c
--- linux-libre-2.6.37-gnu1/arch/powerpc/platforms/powermac/setup.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/platforms/powermac/setup.c	2011-03-14 21:20:32.000000000 -0400
@@ -506,6 +506,15 @@ static int __init pmac_declare_of_platfo
 		of_platform_device_create(np, "smu", NULL);
 		of_node_put(np);
 	}
+	np = of_find_node_by_type(NULL, "fcu");
+	if (np == NULL) {
+		/* Some machines have strangely broken device-tree */
+		np = of_find_node_by_path("/u3@0,f8000000/i2c@f8001000/fan@15e");
+	}
+	if (np) {
+		of_platform_device_create(np, "temperature", NULL);
+		of_node_put(np);
+	}
 
 	return 0;
 }
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/platforms/ps3/device-init.c linux-libre-2.6.38-gnu1/arch/powerpc/platforms/ps3/device-init.c
--- linux-libre-2.6.37-gnu1/arch/powerpc/platforms/ps3/device-init.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/platforms/ps3/device-init.c	2011-03-14 21:20:32.000000000 -0400
@@ -566,10 +566,10 @@ static int ps3_setup_dynamic_device(cons
 	case PS3_DEV_TYPE_STOR_DISK:
 		result = ps3_setup_storage_dev(repo, PS3_MATCH_ID_STOR_DISK);
 
-		/* Some devices are not accessable from the Other OS lpar. */
+		/* Some devices are not accessible from the Other OS lpar. */
 		if (result == -ENODEV) {
 			result = 0;
-			pr_debug("%s:%u: not accessable\n", __func__,
+			pr_debug("%s:%u: not accessible\n", __func__,
 				 __LINE__);
 		}
 
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/platforms/ps3/interrupt.c linux-libre-2.6.38-gnu1/arch/powerpc/platforms/ps3/interrupt.c
--- linux-libre-2.6.37-gnu1/arch/powerpc/platforms/ps3/interrupt.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/platforms/ps3/interrupt.c	2011-03-14 21:20:32.000000000 -0400
@@ -44,7 +44,7 @@
  * @lock:
  * @ipi_debug_brk_mask:
  *
- * The HV mantains per SMT thread mappings of HV outlet to HV plug on
+ * The HV maintains per SMT thread mappings of HV outlet to HV plug on
  * behalf of the guest.  These mappings are implemented as 256 bit guest
  * supplied bitmaps indexed by plug number.  The addresses of the bitmaps
  * are registered with the HV through lv1_configure_irq_state_bitmap().
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/platforms/pseries/eeh_sysfs.c linux-libre-2.6.38-gnu1/arch/powerpc/platforms/pseries/eeh_sysfs.c
--- linux-libre-2.6.37-gnu1/arch/powerpc/platforms/pseries/eeh_sysfs.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/platforms/pseries/eeh_sysfs.c	2011-03-14 21:20:32.000000000 -0400
@@ -25,7 +25,6 @@
 #include <linux/pci.h>
 #include <asm/ppc-pci.h>
 #include <asm/pci-bridge.h>
-#include <linux/kobject.h>
 
 /**
  * EEH_SHOW_ATTR -- create sysfs entry for eeh statistic
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/platforms/pseries/firmware.c linux-libre-2.6.38-gnu1/arch/powerpc/platforms/pseries/firmware.c
--- linux-libre-2.6.37-gnu1/arch/powerpc/platforms/pseries/firmware.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/platforms/pseries/firmware.c	2011-03-14 21:20:32.000000000 -0400
@@ -55,6 +55,7 @@ firmware_features_table[FIRMWARE_MAX_FEA
 	{FW_FEATURE_XDABR,		"hcall-xdabr"},
 	{FW_FEATURE_MULTITCE,		"hcall-multi-tce"},
 	{FW_FEATURE_SPLPAR,		"hcall-splpar"},
+	{FW_FEATURE_VPHN,		"hcall-vphn"},
 };
 
 /* Build up the firmware features bitmask using the contents of
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/platforms/pseries/hvCall_inst.c linux-libre-2.6.38-gnu1/arch/powerpc/platforms/pseries/hvCall_inst.c
--- linux-libre-2.6.37-gnu1/arch/powerpc/platforms/pseries/hvCall_inst.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/platforms/pseries/hvCall_inst.c	2011-03-14 21:20:32.000000000 -0400
@@ -55,7 +55,7 @@ static void hc_stop(struct seq_file *m,
 static int hc_show(struct seq_file *m, void *p)
 {
 	unsigned long h_num = (unsigned long)p;
-	struct hcall_stats *hs = (struct hcall_stats *)m->private;
+	struct hcall_stats *hs = m->private;
 
 	if (hs[h_num].num_calls) {
 		if (cpu_has_feature(CPU_FTR_PURR))
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/platforms/pseries/hvCall.S linux-libre-2.6.38-gnu1/arch/powerpc/platforms/pseries/hvCall.S
--- linux-libre-2.6.37-gnu1/arch/powerpc/platforms/pseries/hvCall.S	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/platforms/pseries/hvCall.S	2011-03-14 21:20:32.000000000 -0400
@@ -11,6 +11,7 @@
 #include <asm/processor.h>
 #include <asm/ppc_asm.h>
 #include <asm/asm-offsets.h>
+#include <asm/ptrace.h>
 	
 #define STK_PARM(i)     (48 + ((i)-3)*8)
 
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/platforms/pseries/iommu.c linux-libre-2.6.38-gnu1/arch/powerpc/platforms/pseries/iommu.c
--- linux-libre-2.6.37-gnu1/arch/powerpc/platforms/pseries/iommu.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/platforms/pseries/iommu.c	2011-03-14 21:20:32.000000000 -0400
@@ -140,7 +140,7 @@ static int tce_build_pSeriesLP(struct io
 	return ret;
 }
 
-static DEFINE_PER_CPU(u64 *, tce_page) = NULL;
+static DEFINE_PER_CPU(u64 *, tce_page);
 
 static int tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum,
 				     long npages, unsigned long uaddr,
@@ -323,14 +323,13 @@ static void iommu_table_setparms(struct
 static void iommu_table_setparms_lpar(struct pci_controller *phb,
 				      struct device_node *dn,
 				      struct iommu_table *tbl,
-				      const void *dma_window,
-				      int bussubno)
+				      const void *dma_window)
 {
 	unsigned long offset, size;
 
-	tbl->it_busno  = bussubno;
 	of_parse_dma_window(dn, dma_window, &tbl->it_index, &offset, &size);
 
+	tbl->it_busno = phb->bus->number;
 	tbl->it_base   = 0;
 	tbl->it_blocksize  = 16;
 	tbl->it_type = TCE_PCI;
@@ -450,14 +449,10 @@ static void pci_dma_bus_setup_pSeriesLP(
 	if (!ppci->iommu_table) {
 		tbl = kzalloc_node(sizeof(struct iommu_table), GFP_KERNEL,
 				   ppci->phb->node);
-		iommu_table_setparms_lpar(ppci->phb, pdn, tbl, dma_window,
-			bus->number);
+		iommu_table_setparms_lpar(ppci->phb, pdn, tbl, dma_window);
 		ppci->iommu_table = iommu_init_table(tbl, ppci->phb->node);
 		pr_debug("  created table: %p\n", ppci->iommu_table);
 	}
-
-	if (pdn != dn)
-		PCI_DN(dn)->iommu_table = ppci->iommu_table;
 }
 
 
@@ -533,21 +528,11 @@ static void pci_dma_dev_setup_pSeriesLP(
 	}
 	pr_debug("  parent is %s\n", pdn->full_name);
 
-	/* Check for parent == NULL so we don't try to setup the empty EADS
-	 * slots on POWER4 machines.
-	 */
-	if (dma_window == NULL || pdn->parent == NULL) {
-		pr_debug("  no dma window for device, linking to parent\n");
-		set_iommu_table_base(&dev->dev, PCI_DN(pdn)->iommu_table);
-		return;
-	}
-
 	pci = PCI_DN(pdn);
 	if (!pci->iommu_table) {
 		tbl = kzalloc_node(sizeof(struct iommu_table), GFP_KERNEL,
 				   pci->phb->node);
-		iommu_table_setparms_lpar(pci->phb, pdn, tbl, dma_window,
-			pci->phb->bus->number);
+		iommu_table_setparms_lpar(pci->phb, pdn, tbl, dma_window);
 		pci->iommu_table = iommu_init_table(tbl, pci->phb->node);
 		pr_debug("  created table: %p\n", pci->iommu_table);
 	} else {
@@ -571,8 +556,7 @@ static int iommu_reconfig_notifier(struc
 
 	switch (action) {
 	case PSERIES_RECONFIG_REMOVE:
-		if (pci && pci->iommu_table &&
-		    of_get_property(np, "ibm,dma-window", NULL))
+		if (pci && pci->iommu_table)
 			iommu_free_table(pci->iommu_table, np->full_name);
 		break;
 	default:
@@ -589,13 +573,8 @@ static struct notifier_block iommu_recon
 /* These are called very early. */
 void iommu_init_early_pSeries(void)
 {
-	if (of_chosen && of_get_property(of_chosen, "linux,iommu-off", NULL)) {
-		/* Direct I/O, IOMMU off */
-		ppc_md.pci_dma_dev_setup = NULL;
-		ppc_md.pci_dma_bus_setup = NULL;
-		set_pci_dma_ops(&dma_direct_ops);
+	if (of_chosen && of_get_property(of_chosen, "linux,iommu-off", NULL))
 		return;
-	}
 
 	if (firmware_has_feature(FW_FEATURE_LPAR)) {
 		if (firmware_has_feature(FW_FEATURE_MULTITCE)) {
@@ -622,3 +601,17 @@ void iommu_init_early_pSeries(void)
 	set_pci_dma_ops(&dma_iommu_ops);
 }
 
+static int __init disable_multitce(char *str)
+{
+	if (strcmp(str, "off") == 0 &&
+	    firmware_has_feature(FW_FEATURE_LPAR) &&
+	    firmware_has_feature(FW_FEATURE_MULTITCE)) {
+		printk(KERN_INFO "Disabling MULTITCE firmware feature\n");
+		ppc_md.tce_build = tce_build_pSeriesLP;
+		ppc_md.tce_free	 = tce_free_pSeriesLP;
+		powerpc_firmware_features &= ~FW_FEATURE_MULTITCE;
+	}
+	return 1;
+}
+
+__setup("multitce=", disable_multitce);
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/platforms/pseries/Kconfig linux-libre-2.6.38-gnu1/arch/powerpc/platforms/pseries/Kconfig
--- linux-libre-2.6.37-gnu1/arch/powerpc/platforms/pseries/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/platforms/pseries/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -10,7 +10,7 @@ config PPC_PSERIES
 	select RTAS_ERROR_LOGGING
 	select PPC_UDBG_16550
 	select PPC_NATIVE
-	select PPC_PCI_CHOICE if EMBEDDED
+	select PPC_PCI_CHOICE if EXPERT
 	default y
 
 config PPC_SPLPAR
@@ -24,15 +24,25 @@ config PPC_SPLPAR
 	  two or more partitions.
 
 config EEH
-	bool "PCI Extended Error Handling (EEH)" if EMBEDDED
+	bool "PCI Extended Error Handling (EEH)" if EXPERT
 	depends on PPC_PSERIES && PCI
-	default y if !EMBEDDED
+	default y if !EXPERT
 
 config PSERIES_MSI
        bool
        depends on PCI_MSI && EEH
        default y
 
+config PSERIES_ENERGY
+	tristate "pSeries energy management capabilities driver"
+	depends on PPC_PSERIES
+	default y
+	help
+	  Provides interface to platform energy management capabilities
+	  on supported PSERIES platforms.
+	  Provides: /sys/devices/system/cpu/pseries_(de)activation_hint_list
+	  and /sys/devices/system/cpu/cpuN/pseries_(de)activation_hint
+
 config SCANLOG
 	tristate "Scanlog dump interface"
 	depends on RTAS_PROC && PPC_PSERIES
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/platforms/pseries/kexec.c linux-libre-2.6.38-gnu1/arch/powerpc/platforms/pseries/kexec.c
--- linux-libre-2.6.37-gnu1/arch/powerpc/platforms/pseries/kexec.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/platforms/pseries/kexec.c	2011-03-14 21:20:32.000000000 -0400
@@ -61,13 +61,3 @@ void __init setup_kexec_cpu_down_xics(vo
 {
 	ppc_md.kexec_cpu_down = pseries_kexec_cpu_down_xics;
 }
-
-static int __init pseries_kexec_setup(void)
-{
-	ppc_md.machine_kexec = default_machine_kexec;
-	ppc_md.machine_kexec_prepare = default_machine_kexec_prepare;
-	ppc_md.machine_crash_shutdown = default_machine_crash_shutdown;
-
-	return 0;
-}
-machine_device_initcall(pseries, pseries_kexec_setup);
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/platforms/pseries/lpar.c linux-libre-2.6.38-gnu1/arch/powerpc/platforms/pseries/lpar.c
--- linux-libre-2.6.37-gnu1/arch/powerpc/platforms/pseries/lpar.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/platforms/pseries/lpar.c	2011-03-14 21:20:32.000000000 -0400
@@ -627,6 +627,18 @@ static void pSeries_lpar_flush_hash_rang
 		spin_unlock_irqrestore(&pSeries_lpar_tlbie_lock, flags);
 }
 
+static int __init disable_bulk_remove(char *str)
+{
+	if (strcmp(str, "off") == 0 &&
+	    firmware_has_feature(FW_FEATURE_BULK_REMOVE)) {
+			printk(KERN_INFO "Disabling BULK_REMOVE firmware feature");
+			powerpc_firmware_features &= ~FW_FEATURE_BULK_REMOVE;
+	}
+	return 1;
+}
+
+__setup("bulk_remove=", disable_bulk_remove);
+
 void __init hpte_init_lpar(void)
 {
 	ppc_md.hpte_invalidate	= pSeries_lpar_hpte_invalidate;
@@ -701,6 +713,13 @@ EXPORT_SYMBOL(arch_free_page);
 /* NB: reg/unreg are called while guarded with the tracepoints_mutex */
 extern long hcall_tracepoint_refcount;
 
+/* 
+ * Since the tracing code might execute hcalls we need to guard against
+ * recursion. One example of this are spinlocks calling H_YIELD on
+ * shared processor partitions.
+ */
+static DEFINE_PER_CPU(unsigned int, hcall_trace_depth);
+
 void hcall_tracepoint_regfunc(void)
 {
 	hcall_tracepoint_refcount++;
@@ -713,12 +732,42 @@ void hcall_tracepoint_unregfunc(void)
 
 void __trace_hcall_entry(unsigned long opcode, unsigned long *args)
 {
+	unsigned long flags;
+	unsigned int *depth;
+
+	local_irq_save(flags);
+
+	depth = &__get_cpu_var(hcall_trace_depth);
+
+	if (*depth)
+		goto out;
+
+	(*depth)++;
 	trace_hcall_entry(opcode, args);
+	(*depth)--;
+
+out:
+	local_irq_restore(flags);
 }
 
 void __trace_hcall_exit(long opcode, unsigned long retval,
 			unsigned long *retbuf)
 {
+	unsigned long flags;
+	unsigned int *depth;
+
+	local_irq_save(flags);
+
+	depth = &__get_cpu_var(hcall_trace_depth);
+
+	if (*depth)
+		goto out;
+
+	(*depth)++;
 	trace_hcall_exit(opcode, retval, retbuf);
+	(*depth)--;
+
+out:
+	local_irq_restore(flags);
 }
 #endif
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/platforms/pseries/Makefile linux-libre-2.6.38-gnu1/arch/powerpc/platforms/pseries/Makefile
--- linux-libre-2.6.37-gnu1/arch/powerpc/platforms/pseries/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/platforms/pseries/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -11,6 +11,7 @@ obj-$(CONFIG_EEH)	+= eeh.o eeh_cache.o e
 obj-$(CONFIG_KEXEC)	+= kexec.o
 obj-$(CONFIG_PCI)	+= pci.o pci_dlpar.o
 obj-$(CONFIG_PSERIES_MSI)	+= msi.o
+obj-$(CONFIG_PSERIES_ENERGY)	+= pseries_energy.o
 
 obj-$(CONFIG_HOTPLUG_CPU)	+= hotplug-cpu.o
 obj-$(CONFIG_MEMORY_HOTPLUG)	+= hotplug-memory.o
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/platforms/pseries/nvram.c linux-libre-2.6.38-gnu1/arch/powerpc/platforms/pseries/nvram.c
--- linux-libre-2.6.37-gnu1/arch/powerpc/platforms/pseries/nvram.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/platforms/pseries/nvram.c	2011-03-14 21:20:32.000000000 -0400
@@ -22,11 +22,25 @@
 #include <asm/prom.h>
 #include <asm/machdep.h>
 
+/* Max bytes to read/write in one go */
+#define NVRW_CNT 0x20
+
 static unsigned int nvram_size;
 static int nvram_fetch, nvram_store;
 static char nvram_buf[NVRW_CNT];	/* assume this is in the first 4GB */
 static DEFINE_SPINLOCK(nvram_lock);
 
+static long nvram_error_log_index = -1;
+static long nvram_error_log_size = 0;
+
+struct err_log_info {
+	int error_type;
+	unsigned int seq_num;
+};
+#define NVRAM_MAX_REQ		2079
+#define NVRAM_MIN_REQ		1055
+
+#define NVRAM_LOG_PART_NAME	"ibm,rtas-log"
 
 static ssize_t pSeries_nvram_read(char *buf, size_t count, loff_t *index)
 {
@@ -119,6 +133,197 @@ static ssize_t pSeries_nvram_get_size(vo
 	return nvram_size ? nvram_size : -ENODEV;
 }
 
+
+/* nvram_write_error_log
+ *
+ * We need to buffer the error logs into nvram to ensure that we have
+ * the failure information to decode.  If we have a severe error there
+ * is no way to guarantee that the OS or the machine is in a state to
+ * get back to user land and write the error to disk.  For example if
+ * the SCSI device driver causes a Machine Check by writing to a bad
+ * IO address, there is no way of guaranteeing that the device driver
+ * is in any state that is would also be able to write the error data
+ * captured to disk, thus we buffer it in NVRAM for analysis on the
+ * next boot.
+ *
+ * In NVRAM the partition containing the error log buffer will looks like:
+ * Header (in bytes):
+ * +-----------+----------+--------+------------+------------------+
+ * | signature | checksum | length | name       | data             |
+ * |0          |1         |2      3|4         15|16        length-1|
+ * +-----------+----------+--------+------------+------------------+
+ *
+ * The 'data' section would look like (in bytes):
+ * +--------------+------------+-----------------------------------+
+ * | event_logged | sequence # | error log                         |
+ * |0            3|4          7|8            nvram_error_log_size-1|
+ * +--------------+------------+-----------------------------------+
+ *
+ * event_logged: 0 if event has not been logged to syslog, 1 if it has
+ * sequence #: The unique sequence # for each event. (until it wraps)
+ * error log: The error log from event_scan
+ */
+int nvram_write_error_log(char * buff, int length,
+                          unsigned int err_type, unsigned int error_log_cnt)
+{
+	int rc;
+	loff_t tmp_index;
+	struct err_log_info info;
+	
+	if (nvram_error_log_index == -1) {
+		return -ESPIPE;
+	}
+
+	if (length > nvram_error_log_size) {
+		length = nvram_error_log_size;
+	}
+
+	info.error_type = err_type;
+	info.seq_num = error_log_cnt;
+
+	tmp_index = nvram_error_log_index;
+
+	rc = ppc_md.nvram_write((char *)&info, sizeof(struct err_log_info), &tmp_index);
+	if (rc <= 0) {
+		printk(KERN_ERR "nvram_write_error_log: Failed nvram_write (%d)\n", rc);
+		return rc;
+	}
+
+	rc = ppc_md.nvram_write(buff, length, &tmp_index);
+	if (rc <= 0) {
+		printk(KERN_ERR "nvram_write_error_log: Failed nvram_write (%d)\n", rc);
+		return rc;
+	}
+	
+	return 0;
+}
+
+/* nvram_read_error_log
+ *
+ * Reads nvram for error log for at most 'length'
+ */
+int nvram_read_error_log(char * buff, int length,
+                         unsigned int * err_type, unsigned int * error_log_cnt)
+{
+	int rc;
+	loff_t tmp_index;
+	struct err_log_info info;
+	
+	if (nvram_error_log_index == -1)
+		return -1;
+
+	if (length > nvram_error_log_size)
+		length = nvram_error_log_size;
+
+	tmp_index = nvram_error_log_index;
+
+	rc = ppc_md.nvram_read((char *)&info, sizeof(struct err_log_info), &tmp_index);
+	if (rc <= 0) {
+		printk(KERN_ERR "nvram_read_error_log: Failed nvram_read (%d)\n", rc);
+		return rc;
+	}
+
+	rc = ppc_md.nvram_read(buff, length, &tmp_index);
+	if (rc <= 0) {
+		printk(KERN_ERR "nvram_read_error_log: Failed nvram_read (%d)\n", rc);
+		return rc;
+	}
+
+	*error_log_cnt = info.seq_num;
+	*err_type = info.error_type;
+
+	return 0;
+}
+
+/* This doesn't actually zero anything, but it sets the event_logged
+ * word to tell that this event is safely in syslog.
+ */
+int nvram_clear_error_log(void)
+{
+	loff_t tmp_index;
+	int clear_word = ERR_FLAG_ALREADY_LOGGED;
+	int rc;
+
+	if (nvram_error_log_index == -1)
+		return -1;
+
+	tmp_index = nvram_error_log_index;
+	
+	rc = ppc_md.nvram_write((char *)&clear_word, sizeof(int), &tmp_index);
+	if (rc <= 0) {
+		printk(KERN_ERR "nvram_clear_error_log: Failed nvram_write (%d)\n", rc);
+		return rc;
+	}
+
+	return 0;
+}
+
+/* pseries_nvram_init_log_partition
+ *
+ * This will setup the partition we need for buffering the
+ * error logs and cleanup partitions if needed.
+ *
+ * The general strategy is the following:
+ * 1.) If there is log partition large enough then use it.
+ * 2.) If there is none large enough, search
+ * for a free partition that is large enough.
+ * 3.) If there is not a free partition large enough remove 
+ * _all_ OS partitions and consolidate the space.
+ * 4.) Will first try getting a chunk that will satisfy the maximum
+ * error log size (NVRAM_MAX_REQ).
+ * 5.) If the max chunk cannot be allocated then try finding a chunk
+ * that will satisfy the minum needed (NVRAM_MIN_REQ).
+ */
+static int __init pseries_nvram_init_log_partition(void)
+{
+	loff_t p;
+	int size;
+
+	/* Scan nvram for partitions */
+	nvram_scan_partitions();
+
+	/* Lookg for ours */
+	p = nvram_find_partition(NVRAM_LOG_PART_NAME, NVRAM_SIG_OS, &size);
+
+	/* Found one but too small, remove it */
+	if (p && size < NVRAM_MIN_REQ) {
+		pr_info("nvram: Found too small "NVRAM_LOG_PART_NAME" partition"
+			",removing it...");
+		nvram_remove_partition(NVRAM_LOG_PART_NAME, NVRAM_SIG_OS);
+		p = 0;
+	}
+
+	/* Create one if we didn't find */
+	if (!p) {
+		p = nvram_create_partition(NVRAM_LOG_PART_NAME, NVRAM_SIG_OS,
+					   NVRAM_MAX_REQ, NVRAM_MIN_REQ);
+		/* No room for it, try to get rid of any OS partition
+		 * and try again
+		 */
+		if (p == -ENOSPC) {
+			pr_info("nvram: No room to create "NVRAM_LOG_PART_NAME
+				" partition, deleting all OS partitions...");
+			nvram_remove_partition(NULL, NVRAM_SIG_OS);
+			p = nvram_create_partition(NVRAM_LOG_PART_NAME,
+						   NVRAM_SIG_OS, NVRAM_MAX_REQ,
+						   NVRAM_MIN_REQ);
+		}
+	}
+
+	if (p <= 0) {
+		pr_err("nvram: Failed to find or create "NVRAM_LOG_PART_NAME
+		       " partition, err %d\n", (int)p);
+		return 0;
+	}
+
+	nvram_error_log_index = p;
+	nvram_error_log_size = nvram_get_partition_size(p) -
+		sizeof(struct err_log_info);
+	
+	return 0;
+}
+machine_arch_initcall(pseries, pseries_nvram_init_log_partition);
+
 int __init pSeries_nvram_init(void)
 {
 	struct device_node *nvram;
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/platforms/pseries/pseries_energy.c linux-libre-2.6.38-gnu1/arch/powerpc/platforms/pseries/pseries_energy.c
--- linux-libre-2.6.37-gnu1/arch/powerpc/platforms/pseries/pseries_energy.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/platforms/pseries/pseries_energy.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,326 @@
+/*
+ * POWER platform energy management driver
+ * Copyright (C) 2010 IBM 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.
+ *
+ * This pseries platform device driver provides access to
+ * platform energy management capabilities.
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/seq_file.h>
+#include <linux/sysdev.h>
+#include <linux/cpu.h>
+#include <linux/of.h>
+#include <asm/cputhreads.h>
+#include <asm/page.h>
+#include <asm/hvcall.h>
+
+
+#define MODULE_VERS "1.0"
+#define MODULE_NAME "pseries_energy"
+
+/* Driver flags */
+
+static int sysfs_entries;
+
+/* Helper routines */
+
+/*
+ * Routine to detect firmware support for hcall
+ * return 1 if H_BEST_ENERGY is supported
+ * else return 0
+ */
+
+static int check_for_h_best_energy(void)
+{
+	struct device_node *rtas = NULL;
+	const char *hypertas, *s;
+	int length;
+	int rc = 0;
+
+	rtas = of_find_node_by_path("/rtas");
+	if (!rtas)
+		return 0;
+
+	hypertas = of_get_property(rtas, "ibm,hypertas-functions", &length);
+	if (!hypertas) {
+		of_node_put(rtas);
+		return 0;
+	}
+
+	/* hypertas will have list of strings with hcall names */
+	for (s = hypertas; s < hypertas + length; s += strlen(s) + 1) {
+		if (!strncmp("hcall-best-energy-1", s, 19)) {
+			rc = 1; /* Found the string */
+			break;
+		}
+	}
+	of_node_put(rtas);
+	return rc;
+}
+
+/* Helper Routines to convert between drc_index to cpu numbers */
+
+static u32 cpu_to_drc_index(int cpu)
+{
+	struct device_node *dn = NULL;
+	const int *indexes;
+	int i;
+	int rc = 1;
+	u32 ret = 0;
+
+	dn = of_find_node_by_path("/cpus");
+	if (dn == NULL)
+		goto err;
+	indexes = of_get_property(dn, "ibm,drc-indexes", NULL);
+	if (indexes == NULL)
+		goto err_of_node_put;
+	/* Convert logical cpu number to core number */
+	i = cpu_core_index_of_thread(cpu);
+	/*
+	 * The first element indexes[0] is the number of drc_indexes
+	 * returned in the list.  Hence i+1 will get the drc_index
+	 * corresponding to core number i.
+	 */
+	WARN_ON(i > indexes[0]);
+	ret = indexes[i + 1];
+	rc = 0;
+
+err_of_node_put:
+	of_node_put(dn);
+err:
+	if (rc)
+		printk(KERN_WARNING "cpu_to_drc_index(%d) failed", cpu);
+	return ret;
+}
+
+static int drc_index_to_cpu(u32 drc_index)
+{
+	struct device_node *dn = NULL;
+	const int *indexes;
+	int i, cpu = 0;
+	int rc = 1;
+
+	dn = of_find_node_by_path("/cpus");
+	if (dn == NULL)
+		goto err;
+	indexes = of_get_property(dn, "ibm,drc-indexes", NULL);
+	if (indexes == NULL)
+		goto err_of_node_put;
+	/*
+	 * First element in the array is the number of drc_indexes
+	 * returned.  Search through the list to find the matching
+	 * drc_index and get the core number
+	 */
+	for (i = 0; i < indexes[0]; i++) {
+		if (indexes[i + 1] == drc_index)
+			break;
+	}
+	/* Convert core number to logical cpu number */
+	cpu = cpu_first_thread_of_core(i);
+	rc = 0;
+
+err_of_node_put:
+	of_node_put(dn);
+err:
+	if (rc)
+		printk(KERN_WARNING "drc_index_to_cpu(%d) failed", drc_index);
+	return cpu;
+}
+
+/*
+ * pseries hypervisor call H_BEST_ENERGY provides hints to OS on
+ * preferred logical cpus to activate or deactivate for optimized
+ * energy consumption.
+ */
+
+#define FLAGS_MODE1	0x004E200000080E01
+#define FLAGS_MODE2	0x004E200000080401
+#define FLAGS_ACTIVATE  0x100
+
+static ssize_t get_best_energy_list(char *page, int activate)
+{
+	int rc, cnt, i, cpu;
+	unsigned long retbuf[PLPAR_HCALL9_BUFSIZE];
+	unsigned long flags = 0;
+	u32 *buf_page;
+	char *s = page;
+
+	buf_page = (u32 *) get_zeroed_page(GFP_KERNEL);
+	if (!buf_page)
+		return -ENOMEM;
+
+	flags = FLAGS_MODE1;
+	if (activate)
+		flags |= FLAGS_ACTIVATE;
+
+	rc = plpar_hcall9(H_BEST_ENERGY, retbuf, flags, 0, __pa(buf_page),
+				0, 0, 0, 0, 0, 0);
+	if (rc != H_SUCCESS) {
+		free_page((unsigned long) buf_page);
+		return -EINVAL;
+	}
+
+	cnt = retbuf[0];
+	for (i = 0; i < cnt; i++) {
+		cpu = drc_index_to_cpu(buf_page[2*i+1]);
+		if ((cpu_online(cpu) && !activate) ||
+		    (!cpu_online(cpu) && activate))
+			s += sprintf(s, "%d,", cpu);
+	}
+	if (s > page) { /* Something to show */
+		s--; /* Suppress last comma */
+		s += sprintf(s, "\n");
+	}
+
+	free_page((unsigned long) buf_page);
+	return s-page;
+}
+
+static ssize_t get_best_energy_data(struct sys_device *dev,
+					char *page, int activate)
+{
+	int rc;
+	unsigned long retbuf[PLPAR_HCALL9_BUFSIZE];
+	unsigned long flags = 0;
+
+	flags = FLAGS_MODE2;
+	if (activate)
+		flags |= FLAGS_ACTIVATE;
+
+	rc = plpar_hcall9(H_BEST_ENERGY, retbuf, flags,
+				cpu_to_drc_index(dev->id),
+				0, 0, 0, 0, 0, 0, 0);
+
+	if (rc != H_SUCCESS)
+		return -EINVAL;
+
+	return sprintf(page, "%lu\n", retbuf[1] >> 32);
+}
+
+/* Wrapper functions */
+
+static ssize_t cpu_activate_hint_list_show(struct sysdev_class *class,
+			struct sysdev_class_attribute *attr, char *page)
+{
+	return get_best_energy_list(page, 1);
+}
+
+static ssize_t cpu_deactivate_hint_list_show(struct sysdev_class *class,
+			struct sysdev_class_attribute *attr, char *page)
+{
+	return get_best_energy_list(page, 0);
+}
+
+static ssize_t percpu_activate_hint_show(struct sys_device *dev,
+			struct sysdev_attribute *attr, char *page)
+{
+	return get_best_energy_data(dev, page, 1);
+}
+
+static ssize_t percpu_deactivate_hint_show(struct sys_device *dev,
+			struct sysdev_attribute *attr, char *page)
+{
+	return get_best_energy_data(dev, page, 0);
+}
+
+/*
+ * Create sysfs interface:
+ * /sys/devices/system/cpu/pseries_activate_hint_list
+ * /sys/devices/system/cpu/pseries_deactivate_hint_list
+ *	Comma separated list of cpus to activate or deactivate
+ * /sys/devices/system/cpu/cpuN/pseries_activate_hint
+ * /sys/devices/system/cpu/cpuN/pseries_deactivate_hint
+ *	Per-cpu value of the hint
+ */
+
+struct sysdev_class_attribute attr_cpu_activate_hint_list =
+		_SYSDEV_CLASS_ATTR(pseries_activate_hint_list, 0444,
+		cpu_activate_hint_list_show, NULL);
+
+struct sysdev_class_attribute attr_cpu_deactivate_hint_list =
+		_SYSDEV_CLASS_ATTR(pseries_deactivate_hint_list, 0444,
+		cpu_deactivate_hint_list_show, NULL);
+
+struct sysdev_attribute attr_percpu_activate_hint =
+		_SYSDEV_ATTR(pseries_activate_hint, 0444,
+		percpu_activate_hint_show, NULL);
+
+struct sysdev_attribute attr_percpu_deactivate_hint =
+		_SYSDEV_ATTR(pseries_deactivate_hint, 0444,
+		percpu_deactivate_hint_show, NULL);
+
+static int __init pseries_energy_init(void)
+{
+	int cpu, err;
+	struct sys_device *cpu_sys_dev;
+
+	if (!check_for_h_best_energy()) {
+		printk(KERN_INFO "Hypercall H_BEST_ENERGY not supported\n");
+		return 0;
+	}
+	/* Create the sysfs files */
+	err = sysfs_create_file(&cpu_sysdev_class.kset.kobj,
+				&attr_cpu_activate_hint_list.attr);
+	if (!err)
+		err = sysfs_create_file(&cpu_sysdev_class.kset.kobj,
+				&attr_cpu_deactivate_hint_list.attr);
+
+	if (err)
+		return err;
+	for_each_possible_cpu(cpu) {
+		cpu_sys_dev = get_cpu_sysdev(cpu);
+		err = sysfs_create_file(&cpu_sys_dev->kobj,
+				&attr_percpu_activate_hint.attr);
+		if (err)
+			break;
+		err = sysfs_create_file(&cpu_sys_dev->kobj,
+				&attr_percpu_deactivate_hint.attr);
+		if (err)
+			break;
+	}
+
+	if (err)
+		return err;
+
+	sysfs_entries = 1; /* Removed entries on cleanup */
+	return 0;
+
+}
+
+static void __exit pseries_energy_cleanup(void)
+{
+	int cpu;
+	struct sys_device *cpu_sys_dev;
+
+	if (!sysfs_entries)
+		return;
+
+	/* Remove the sysfs files */
+	sysfs_remove_file(&cpu_sysdev_class.kset.kobj,
+				&attr_cpu_activate_hint_list.attr);
+
+	sysfs_remove_file(&cpu_sysdev_class.kset.kobj,
+				&attr_cpu_deactivate_hint_list.attr);
+
+	for_each_possible_cpu(cpu) {
+		cpu_sys_dev = get_cpu_sysdev(cpu);
+		sysfs_remove_file(&cpu_sys_dev->kobj,
+				&attr_percpu_activate_hint.attr);
+		sysfs_remove_file(&cpu_sys_dev->kobj,
+				&attr_percpu_deactivate_hint.attr);
+	}
+}
+
+module_init(pseries_energy_init);
+module_exit(pseries_energy_cleanup);
+MODULE_DESCRIPTION("Driver for pSeries platform energy management");
+MODULE_AUTHOR("Vaidyanathan Srinivasan");
+MODULE_LICENSE("GPL");
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/platforms/pseries/ras.c linux-libre-2.6.38-gnu1/arch/powerpc/platforms/pseries/ras.c
--- linux-libre-2.6.37-gnu1/arch/powerpc/platforms/pseries/ras.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/platforms/pseries/ras.c	2011-03-14 21:20:32.000000000 -0400
@@ -54,7 +54,8 @@
 static unsigned char ras_log_buf[RTAS_ERROR_LOG_MAX];
 static DEFINE_SPINLOCK(ras_log_buf_lock);
 
-static char mce_data_buf[RTAS_ERROR_LOG_MAX];
+static char global_mce_data_buf[RTAS_ERROR_LOG_MAX];
+static DEFINE_PER_CPU(__u64, mce_data_buf);
 
 static int ras_get_sensor_state_token;
 static int ras_check_exception_token;
@@ -196,12 +197,24 @@ static irqreturn_t ras_error_interrupt(i
 	return IRQ_HANDLED;
 }
 
-/* Get the error information for errors coming through the
+/*
+ * Some versions of FWNMI place the buffer inside the 4kB page starting at
+ * 0x7000. Other versions place it inside the rtas buffer. We check both.
+ */
+#define VALID_FWNMI_BUFFER(A) \
+	((((A) >= 0x7000) && ((A) < 0x7ff0)) || \
+	(((A) >= rtas.base) && ((A) < (rtas.base + rtas.size - 16))))
+
+/*
+ * Get the error information for errors coming through the
  * FWNMI vectors.  The pt_regs' r3 will be updated to reflect
  * the actual r3 if possible, and a ptr to the error log entry
  * will be returned if found.
  *
- * The mce_data_buf does not have any locks or protection around it,
+ * If the RTAS error is not of the extended type, then we put it in a per
+ * cpu 64bit buffer. If it is the extended type we use global_mce_data_buf.
+ *
+ * The global_mce_data_buf does not have any locks or protection around it,
  * if a second machine check comes in, or a system reset is done
  * before we have logged the error, then we will get corruption in the
  * error log.  This is preferable over holding off on calling
@@ -210,20 +223,31 @@ static irqreturn_t ras_error_interrupt(i
  */
 static struct rtas_error_log *fwnmi_get_errinfo(struct pt_regs *regs)
 {
-	unsigned long errdata = regs->gpr[3];
-	struct rtas_error_log *errhdr = NULL;
 	unsigned long *savep;
+	struct rtas_error_log *h, *errhdr = NULL;
 
-	if ((errdata >= 0x7000 && errdata < 0x7fff0) ||
-	    (errdata >= rtas.base && errdata < rtas.base + rtas.size - 16)) {
-		savep = __va(errdata);
-		regs->gpr[3] = savep[0];	/* restore original r3 */
-		memset(mce_data_buf, 0, RTAS_ERROR_LOG_MAX);
-		memcpy(mce_data_buf, (char *)(savep + 1), RTAS_ERROR_LOG_MAX);
-		errhdr = (struct rtas_error_log *)mce_data_buf;
+	if (!VALID_FWNMI_BUFFER(regs->gpr[3])) {
+		printk(KERN_ERR "FWNMI: corrupt r3\n");
+		return NULL;
+	}
+
+	savep = __va(regs->gpr[3]);
+	regs->gpr[3] = savep[0];	/* restore original r3 */
+
+	/* If it isn't an extended log we can use the per cpu 64bit buffer */
+	h = (struct rtas_error_log *)&savep[1];
+	if (!h->extended) {
+		memcpy(&__get_cpu_var(mce_data_buf), h, sizeof(__u64));
+		errhdr = (struct rtas_error_log *)&__get_cpu_var(mce_data_buf);
 	} else {
-		printk("FWNMI: corrupt r3\n");
+		int len;
+
+		len = max_t(int, 8+h->extended_log_length, RTAS_ERROR_LOG_MAX);
+		memset(global_mce_data_buf, 0, RTAS_ERROR_LOG_MAX);
+		memcpy(global_mce_data_buf, h, len);
+		errhdr = (struct rtas_error_log *)global_mce_data_buf;
 	}
+
 	return errhdr;
 }
 
@@ -235,7 +259,7 @@ static void fwnmi_release_errinfo(void)
 {
 	int ret = rtas_call(rtas_token("ibm,nmi-interlock"), 0, 1, NULL);
 	if (ret != 0)
-		printk("FWNMI: nmi-interlock failed: %d\n", ret);
+		printk(KERN_ERR "FWNMI: nmi-interlock failed: %d\n", ret);
 }
 
 int pSeries_system_reset_exception(struct pt_regs *regs)
@@ -259,31 +283,43 @@ int pSeries_system_reset_exception(struc
  * Return 1 if corrected (or delivered a signal).
  * Return 0 if there is nothing we can do.
  */
-static int recover_mce(struct pt_regs *regs, struct rtas_error_log * err)
+static int recover_mce(struct pt_regs *regs, struct rtas_error_log *err)
 {
-	int nonfatal = 0;
+	int recovered = 0;
 
-	if (err->disposition == RTAS_DISP_FULLY_RECOVERED) {
+	if (!(regs->msr & MSR_RI)) {
+		/* If MSR_RI isn't set, we cannot recover */
+		recovered = 0;
+
+	} else if (err->disposition == RTAS_DISP_FULLY_RECOVERED) {
 		/* Platform corrected itself */
-		nonfatal = 1;
-	} else if ((regs->msr & MSR_RI) &&
-		   user_mode(regs) &&
-		   err->severity == RTAS_SEVERITY_ERROR_SYNC &&
-		   err->disposition == RTAS_DISP_NOT_RECOVERED &&
-		   err->target == RTAS_TARGET_MEMORY &&
-		   err->type == RTAS_TYPE_ECC_UNCORR &&
-		   !(current->pid == 0 || is_global_init(current))) {
-		/* Kill off a user process with an ECC error */
-		printk(KERN_ERR "MCE: uncorrectable ecc error for pid %d\n",
-		       current->pid);
-		/* XXX something better for ECC error? */
-		_exception(SIGBUS, regs, BUS_ADRERR, regs->nip);
-		nonfatal = 1;
+		recovered = 1;
+
+	} else if (err->disposition == RTAS_DISP_LIMITED_RECOVERY) {
+		/* Platform corrected itself but could be degraded */
+		printk(KERN_ERR "MCE: limited recovery, system may "
+		       "be degraded\n");
+		recovered = 1;
+
+	} else if (user_mode(regs) && !is_global_init(current) &&
+		   err->severity == RTAS_SEVERITY_ERROR_SYNC) {
+
+		/*
+		 * If we received a synchronous error when in userspace
+		 * kill the task. Firmware may report details of the fail
+		 * asynchronously, so we can't rely on the target and type
+		 * fields being valid here.
+		 */
+		printk(KERN_ERR "MCE: uncorrectable error, killing task "
+		       "%s:%d\n", current->comm, current->pid);
+
+		_exception(SIGBUS, regs, BUS_MCEERR_AR, regs->nip);
+		recovered = 1;
 	}
 
-	log_error((char *)err, ERR_TYPE_RTAS_LOG, !nonfatal);
+	log_error((char *)err, ERR_TYPE_RTAS_LOG, 0);
 
-	return nonfatal;
+	return recovered;
 }
 
 /*
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/platforms/pseries/suspend.c linux-libre-2.6.38-gnu1/arch/powerpc/platforms/pseries/suspend.c
--- linux-libre-2.6.37-gnu1/arch/powerpc/platforms/pseries/suspend.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/platforms/pseries/suspend.c	2011-03-14 21:20:32.000000000 -0400
@@ -153,7 +153,7 @@ static struct sysdev_class suspend_sysde
 	.name = "power",
 };
 
-static struct platform_suspend_ops pseries_suspend_ops = {
+static const struct platform_suspend_ops pseries_suspend_ops = {
 	.valid		= suspend_valid_only_mem,
 	.begin		= pseries_suspend_begin,
 	.prepare_late	= pseries_prepare_late,
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/sysdev/dart_iommu.c linux-libre-2.6.38-gnu1/arch/powerpc/sysdev/dart_iommu.c
--- linux-libre-2.6.37-gnu1/arch/powerpc/sysdev/dart_iommu.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/sysdev/dart_iommu.c	2011-03-14 21:20:32.000000000 -0400
@@ -312,17 +312,10 @@ static void pci_dma_dev_setup_dart(struc
 
 static void pci_dma_bus_setup_dart(struct pci_bus *bus)
 {
-	struct device_node *dn;
-
 	if (!iommu_table_dart_inited) {
 		iommu_table_dart_inited = 1;
 		iommu_table_dart_setup();
 	}
-
-	dn = pci_bus_to_OF_node(bus);
-
-	if (dn)
-		PCI_DN(dn)->iommu_table = &iommu_table_dart;
 }
 
 static bool dart_device_on_pcie(struct device *dev)
@@ -373,7 +366,7 @@ void __init iommu_init_early_dart(void)
 	if (dn == NULL) {
 		dn = of_find_compatible_node(NULL, "dart", "u4-dart");
 		if (dn == NULL)
-			goto bail;
+			return;	/* use default direct_dma_ops */
 		dart_is_u4 = 1;
 	}
 
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/sysdev/fsl_pmc.c linux-libre-2.6.38-gnu1/arch/powerpc/sysdev/fsl_pmc.c
--- linux-libre-2.6.37-gnu1/arch/powerpc/sysdev/fsl_pmc.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/sysdev/fsl_pmc.c	2011-03-14 21:20:32.000000000 -0400
@@ -53,7 +53,7 @@ static int pmc_suspend_valid(suspend_sta
 	return 1;
 }
 
-static struct platform_suspend_ops pmc_suspend_ops = {
+static const struct platform_suspend_ops pmc_suspend_ops = {
 	.valid = pmc_suspend_valid,
 	.enter = pmc_suspend_enter,
 };
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/sysdev/fsl_rio.c linux-libre-2.6.38-gnu1/arch/powerpc/sysdev/fsl_rio.c
--- linux-libre-2.6.37-gnu1/arch/powerpc/sysdev/fsl_rio.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/sysdev/fsl_rio.c	2011-03-14 21:20:32.000000000 -0400
@@ -973,7 +973,6 @@ fsl_rio_dbell_handler(int irq, void *dev
 	if (dsr & DOORBELL_DSR_QFI) {
 		pr_info("RIO: doorbell queue full\n");
 		out_be32(&priv->msg_regs->dsr, DOORBELL_DSR_QFI);
-		goto out;
 	}
 
 	/* XXX Need to check/dispatch until queue empty */
@@ -1556,8 +1555,6 @@ int fsl_rio_setup(struct platform_device
 	saved_mcheck_exception = ppc_md.machine_check_exception;
 	ppc_md.machine_check_exception = fsl_rio_mcheck_exception;
 #endif
-	/* Ensure that RFXE is set */
-	mtspr(SPRN_HID1, (mfspr(SPRN_HID1) | 0x20000));
 
 	return 0;
 err:
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/sysdev/Makefile linux-libre-2.6.38-gnu1/arch/powerpc/sysdev/Makefile
--- linux-libre-2.6.37-gnu1/arch/powerpc/sysdev/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/sysdev/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -41,6 +41,7 @@ obj-$(CONFIG_OF_RTC)		+= of_rtc.o
 ifeq ($(CONFIG_PCI),y)
 obj-$(CONFIG_4xx)		+= ppc4xx_pci.o
 endif
+obj-$(CONFIG_PPC4xx_CPM)	+= ppc4xx_cpm.o
 obj-$(CONFIG_PPC4xx_GPIO)	+= ppc4xx_gpio.o
 
 obj-$(CONFIG_CPM)		+= cpm_common.o
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/sysdev/mpc8xxx_gpio.c linux-libre-2.6.38-gnu1/arch/powerpc/sysdev/mpc8xxx_gpio.c
--- linux-libre-2.6.37-gnu1/arch/powerpc/sysdev/mpc8xxx_gpio.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/sysdev/mpc8xxx_gpio.c	2011-03-14 21:20:32.000000000 -0400
@@ -1,5 +1,5 @@
 /*
- * GPIOs on MPC8349/8572/8610 and compatible
+ * GPIOs on MPC512x/8349/8572/8610 and compatible
  *
  * Copyright (C) 2008 Peter Korsgaard <jacmet@sunsite.dk>
  *
@@ -26,6 +26,7 @@
 #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;
@@ -37,6 +38,7 @@ struct mpc8xxx_gpio_chip {
 	 */
 	u32 data;
 	struct irq_host *irq;
+	void *of_dev_id_data;
 };
 
 static inline u32 mpc8xxx_gpio2mask(unsigned int gpio)
@@ -215,6 +217,51 @@ static int mpc8xxx_irq_set_type(unsigned
 	return 0;
 }
 
+static int mpc512x_irq_set_type(unsigned int virq, unsigned int flow_type)
+{
+	struct mpc8xxx_gpio_chip *mpc8xxx_gc = get_irq_chip_data(virq);
+	struct of_mm_gpio_chip *mm = &mpc8xxx_gc->mm_gc;
+	unsigned long gpio = virq_to_hw(virq);
+	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",
 	.unmask		= mpc8xxx_irq_unmask,
@@ -226,6 +273,11 @@ static struct irq_chip mpc8xxx_irq_chip
 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.set_type = mpc8xxx_gc->of_dev_id_data;
+
 	set_irq_chip_data(virq, h->host_data);
 	set_irq_chip_and_handler(virq, &mpc8xxx_irq_chip, handle_level_irq);
 	set_irq_type(virq, IRQ_TYPE_NONE);
@@ -253,11 +305,20 @@ static struct irq_host_ops mpc8xxx_gpio_
 	.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, },
+	{}
+};
+
 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;
 
@@ -297,6 +358,10 @@ static void __init mpc8xxx_add_controlle
 	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 */
@@ -321,13 +386,7 @@ static int __init mpc8xxx_add_gpiochips(
 {
 	struct device_node *np;
 
-	for_each_compatible_node(np, NULL, "fsl,mpc8349-gpio")
-		mpc8xxx_add_controller(np);
-
-	for_each_compatible_node(np, NULL, "fsl,mpc8572-gpio")
-		mpc8xxx_add_controller(np);
-
-	for_each_compatible_node(np, NULL, "fsl,mpc8610-gpio")
+	for_each_matching_node(np, mpc8xxx_gpio_ids)
 		mpc8xxx_add_controller(np);
 
 	for_each_compatible_node(np, NULL, "fsl,qoriq-gpio")
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/sysdev/mpic.c linux-libre-2.6.38-gnu1/arch/powerpc/sysdev/mpic.c
--- linux-libre-2.6.37-gnu1/arch/powerpc/sysdev/mpic.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/sysdev/mpic.c	2011-03-14 21:20:32.000000000 -0400
@@ -674,7 +674,8 @@ void mpic_unmask_irq(unsigned int irq)
 	/* make sure mask gets to controller before we return to user */
 	do {
 		if (!loops--) {
-			printk(KERN_ERR "mpic_enable_irq timeout\n");
+			printk(KERN_ERR "%s: timeout on hwirq %u\n",
+			       __func__, src);
 			break;
 		}
 	} while(mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI)) & MPIC_VECPRI_MASK);
@@ -695,7 +696,8 @@ void mpic_mask_irq(unsigned int irq)
 	/* make sure mask gets to controller before we return to user */
 	do {
 		if (!loops--) {
-			printk(KERN_ERR "mpic_enable_irq timeout\n");
+			printk(KERN_ERR "%s: timeout on hwirq %u\n",
+			       __func__, src);
 			break;
 		}
 	} while(!(mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI)) & MPIC_VECPRI_MASK));
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/sysdev/mv64x60_dev.c linux-libre-2.6.38-gnu1/arch/powerpc/sysdev/mv64x60_dev.c
--- linux-libre-2.6.37-gnu1/arch/powerpc/sysdev/mv64x60_dev.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/sysdev/mv64x60_dev.c	2011-03-14 21:20:32.000000000 -0400
@@ -16,6 +16,7 @@
 #include <linux/mv643xx.h>
 #include <linux/platform_device.h>
 #include <linux/of_platform.h>
+#include <linux/of_net.h>
 #include <linux/dma-mapping.h>
 
 #include <asm/prom.h>
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/sysdev/ppc4xx_cpm.c linux-libre-2.6.38-gnu1/arch/powerpc/sysdev/ppc4xx_cpm.c
--- linux-libre-2.6.37-gnu1/arch/powerpc/sysdev/ppc4xx_cpm.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/sysdev/ppc4xx_cpm.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,346 @@
+/*
+ * PowerPC 4xx Clock and Power Management
+ *
+ * Copyright (C) 2010, Applied Micro Circuits Corporation
+ * Victor Gallardo (vgallardo@apm.com)
+ *
+ * Based on arch/powerpc/platforms/44x/idle.c:
+ * Jerone Young <jyoung5@us.ibm.com>
+ * Copyright 2008 IBM Corp.
+ *
+ * Based on arch/powerpc/sysdev/fsl_pmc.c:
+ * Anton Vorontsov <avorontsov@ru.mvista.com>
+ * Copyright 2009  MontaVista Software, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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/of_platform.h>
+#include <linux/sysfs.h>
+#include <linux/cpu.h>
+#include <linux/suspend.h>
+#include <asm/dcr.h>
+#include <asm/dcr-native.h>
+#include <asm/machdep.h>
+
+#define CPM_ER	0
+#define CPM_FR	1
+#define CPM_SR	2
+
+#define CPM_IDLE_WAIT	0
+#define CPM_IDLE_DOZE	1
+
+struct cpm {
+	dcr_host_t	dcr_host;
+	unsigned int	dcr_offset[3];
+	unsigned int	powersave_off;
+	unsigned int	unused;
+	unsigned int	idle_doze;
+	unsigned int	standby;
+	unsigned int	suspend;
+};
+
+static struct cpm cpm;
+
+struct cpm_idle_mode {
+	unsigned int enabled;
+	const char  *name;
+};
+
+static struct cpm_idle_mode idle_mode[] = {
+	[CPM_IDLE_WAIT] = { 1, "wait" }, /* default */
+	[CPM_IDLE_DOZE] = { 0, "doze" },
+};
+
+static unsigned int cpm_set(unsigned int cpm_reg, unsigned int mask)
+{
+	unsigned int value;
+
+	/* CPM controller supports 3 different types of sleep interface
+	 * known as class 1, 2 and 3. For class 1 units, they are
+	 * unconditionally put to sleep when the corresponding CPM bit is
+	 * set. For class 2 and 3 units this is not case; if they can be
+	 * put to to sleep, they will. Here we do not verify, we just
+	 * set them and expect them to eventually go off when they can.
+	 */
+	value = dcr_read(cpm.dcr_host, cpm.dcr_offset[cpm_reg]);
+	dcr_write(cpm.dcr_host, cpm.dcr_offset[cpm_reg], value | mask);
+
+	/* return old state, to restore later if needed */
+	return value;
+}
+
+static void cpm_idle_wait(void)
+{
+	unsigned long msr_save;
+
+	/* save off initial state */
+	msr_save = mfmsr();
+	/* sync required when CPM0_ER[CPU] is set */
+	mb();
+	/* set wait state MSR */
+	mtmsr(msr_save|MSR_WE|MSR_EE|MSR_CE|MSR_DE);
+	isync();
+	/* return to initial state */
+	mtmsr(msr_save);
+	isync();
+}
+
+static void cpm_idle_sleep(unsigned int mask)
+{
+	unsigned int er_save;
+
+	/* update CPM_ER state */
+	er_save = cpm_set(CPM_ER, mask);
+
+	/* go to wait state so that CPM0_ER[CPU] can take effect */
+	cpm_idle_wait();
+
+	/* restore CPM_ER state */
+	dcr_write(cpm.dcr_host, cpm.dcr_offset[CPM_ER], er_save);
+}
+
+static void cpm_idle_doze(void)
+{
+	cpm_idle_sleep(cpm.idle_doze);
+}
+
+static void cpm_idle_config(int mode)
+{
+	int i;
+
+	if (idle_mode[mode].enabled)
+		return;
+
+	for (i = 0; i < ARRAY_SIZE(idle_mode); i++)
+		idle_mode[i].enabled = 0;
+
+	idle_mode[mode].enabled = 1;
+}
+
+static ssize_t cpm_idle_show(struct kobject *kobj,
+			     struct kobj_attribute *attr, char *buf)
+{
+	char *s = buf;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(idle_mode); i++) {
+		if (idle_mode[i].enabled)
+			s += sprintf(s, "[%s] ", idle_mode[i].name);
+		else
+			s += sprintf(s, "%s ", idle_mode[i].name);
+	}
+
+	*(s-1) = '\n'; /* convert the last space to a newline */
+
+	return s - buf;
+}
+
+static ssize_t cpm_idle_store(struct kobject *kobj,
+			      struct kobj_attribute *attr,
+			      const char *buf, size_t n)
+{
+	int i;
+	char *p;
+	int len;
+
+	p = memchr(buf, '\n', n);
+	len = p ? p - buf : n;
+
+	for (i = 0; i < ARRAY_SIZE(idle_mode); i++) {
+		if (strncmp(buf, idle_mode[i].name, len) == 0) {
+			cpm_idle_config(i);
+			return n;
+		}
+	}
+
+	return -EINVAL;
+}
+
+static struct kobj_attribute cpm_idle_attr =
+	__ATTR(idle, 0644, cpm_idle_show, cpm_idle_store);
+
+static void cpm_idle_config_sysfs(void)
+{
+	struct sys_device *sys_dev;
+	unsigned long ret;
+
+	sys_dev = get_cpu_sysdev(0);
+
+	ret = sysfs_create_file(&sys_dev->kobj,
+				&cpm_idle_attr.attr);
+	if (ret)
+		printk(KERN_WARNING
+		       "cpm: failed to create idle sysfs entry\n");
+}
+
+static void cpm_idle(void)
+{
+	if (idle_mode[CPM_IDLE_DOZE].enabled)
+		cpm_idle_doze();
+	else
+		cpm_idle_wait();
+}
+
+static int cpm_suspend_valid(suspend_state_t state)
+{
+	switch (state) {
+	case PM_SUSPEND_STANDBY:
+		return !!cpm.standby;
+	case PM_SUSPEND_MEM:
+		return !!cpm.suspend;
+	default:
+		return 0;
+	}
+}
+
+static void cpm_suspend_standby(unsigned int mask)
+{
+	unsigned long tcr_save;
+
+	/* disable decrement interrupt */
+	tcr_save = mfspr(SPRN_TCR);
+	mtspr(SPRN_TCR, tcr_save & ~TCR_DIE);
+
+	/* go to sleep state */
+	cpm_idle_sleep(mask);
+
+	/* restore decrement interrupt */
+	mtspr(SPRN_TCR, tcr_save);
+}
+
+static int cpm_suspend_enter(suspend_state_t state)
+{
+	switch (state) {
+	case PM_SUSPEND_STANDBY:
+		cpm_suspend_standby(cpm.standby);
+		break;
+	case PM_SUSPEND_MEM:
+		cpm_suspend_standby(cpm.suspend);
+		break;
+	}
+
+	return 0;
+}
+
+static struct platform_suspend_ops cpm_suspend_ops = {
+	.valid		= cpm_suspend_valid,
+	.enter		= cpm_suspend_enter,
+};
+
+static int cpm_get_uint_property(struct device_node *np,
+				 const char *name)
+{
+	int len;
+	const unsigned int *prop = of_get_property(np, name, &len);
+
+	if (prop == NULL || len < sizeof(u32))
+		return 0;
+
+	return *prop;
+}
+
+static int __init cpm_init(void)
+{
+	struct device_node *np;
+	int dcr_base, dcr_len;
+	int ret = 0;
+
+	if (!cpm.powersave_off) {
+		cpm_idle_config(CPM_IDLE_WAIT);
+		ppc_md.power_save = &cpm_idle;
+	}
+
+	np = of_find_compatible_node(NULL, NULL, "ibm,cpm");
+	if (!np) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	dcr_base = dcr_resource_start(np, 0);
+	dcr_len = dcr_resource_len(np, 0);
+
+	if (dcr_base == 0 || dcr_len == 0) {
+		printk(KERN_ERR "cpm: could not parse dcr property for %s\n",
+		       np->full_name);
+		ret = -EINVAL;
+		goto out;
+	}
+
+	cpm.dcr_host = dcr_map(np, dcr_base, dcr_len);
+
+	if (!DCR_MAP_OK(cpm.dcr_host)) {
+		printk(KERN_ERR "cpm: failed to map dcr property for %s\n",
+		       np->full_name);
+		ret = -EINVAL;
+		goto out;
+	}
+
+	/* All 4xx SoCs with a CPM controller have one of two
+	 * different order for the CPM registers. Some have the
+	 * CPM registers in the following order (ER,FR,SR). The
+	 * others have them in the following order (SR,ER,FR).
+	 */
+
+	if (cpm_get_uint_property(np, "er-offset") == 0) {
+		cpm.dcr_offset[CPM_ER] = 0;
+		cpm.dcr_offset[CPM_FR] = 1;
+		cpm.dcr_offset[CPM_SR] = 2;
+	} else {
+		cpm.dcr_offset[CPM_ER] = 1;
+		cpm.dcr_offset[CPM_FR] = 2;
+		cpm.dcr_offset[CPM_SR] = 0;
+	}
+
+	/* Now let's see what IPs to turn off for the following modes */
+
+	cpm.unused = cpm_get_uint_property(np, "unused-units");
+	cpm.idle_doze = cpm_get_uint_property(np, "idle-doze");
+	cpm.standby = cpm_get_uint_property(np, "standby");
+	cpm.suspend = cpm_get_uint_property(np, "suspend");
+
+	/* If some IPs are unused let's turn them off now */
+
+	if (cpm.unused) {
+		cpm_set(CPM_ER, cpm.unused);
+		cpm_set(CPM_FR, cpm.unused);
+	}
+
+	/* Now let's export interfaces */
+
+	if (!cpm.powersave_off && cpm.idle_doze)
+		cpm_idle_config_sysfs();
+
+	if (cpm.standby || cpm.suspend)
+		suspend_set_ops(&cpm_suspend_ops);
+out:
+	if (np)
+		of_node_put(np);
+	return ret;
+}
+
+late_initcall(cpm_init);
+
+static int __init cpm_powersave_off(char *arg)
+{
+	cpm.powersave_off = 1;
+	return 0;
+}
+__setup("powersave=off", cpm_powersave_off);
diff -druNp linux-libre-2.6.37-gnu1/arch/powerpc/sysdev/tsi108_dev.c linux-libre-2.6.38-gnu1/arch/powerpc/sysdev/tsi108_dev.c
--- linux-libre-2.6.37-gnu1/arch/powerpc/sysdev/tsi108_dev.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/powerpc/sysdev/tsi108_dev.c	2011-03-14 21:20:32.000000000 -0400
@@ -19,6 +19,7 @@
 #include <linux/module.h>
 #include <linux/device.h>
 #include <linux/platform_device.h>
+#include <linux/of_net.h>
 #include <asm/tsi108.h>
 
 #include <asm/system.h>
@@ -83,8 +84,8 @@ static int __init tsi108_eth_of_init(voi
 		memset(&tsi_eth_data, 0, sizeof(tsi_eth_data));
 
 		ret = of_address_to_resource(np, 0, &r[0]);
-		DBG("%s: name:start->end = %s:0x%lx-> 0x%lx\n",
-			__func__,r[0].name, r[0].start, r[0].end);
+		DBG("%s: name:start->end = %s:%pR\n",
+		    __func__, r[0].name, &r[0]);
 		if (ret)
 			goto err;
 
@@ -92,8 +93,8 @@ static int __init tsi108_eth_of_init(voi
 		r[1].start = irq_of_parse_and_map(np, 0);
 		r[1].end = irq_of_parse_and_map(np, 0);
 		r[1].flags = IORESOURCE_IRQ;
-		DBG("%s: name:start->end = %s:0x%lx-> 0x%lx\n",
-			__func__,r[1].name, r[1].start, r[1].end);
+		DBG("%s: name:start->end = %s:%pR\n",
+			__func__, r[1].name, &r[1]);
 
 		tsi_eth_dev =
 		    platform_device_register_simple("tsi-ethernet", i++, &r[0],
diff -druNp linux-libre-2.6.37-gnu1/arch/s390/boot/compressed/misc.c linux-libre-2.6.38-gnu1/arch/s390/boot/compressed/misc.c
--- linux-libre-2.6.37-gnu1/arch/s390/boot/compressed/misc.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/s390/boot/compressed/misc.c	2011-03-14 21:20:32.000000000 -0400
@@ -133,11 +133,12 @@ unsigned long decompress_kernel(void)
 	unsigned long output_addr;
 	unsigned char *output;
 
-	check_ipl_parmblock((void *) 0, (unsigned long) output + SZ__bss_start);
+	output_addr = ((unsigned long) &_end + HEAP_SIZE + 4095UL) & -4096UL;
+	check_ipl_parmblock((void *) 0, output_addr + SZ__bss_start);
 	memset(&_bss, 0, &_ebss - &_bss);
 	free_mem_ptr = (unsigned long)&_end;
 	free_mem_end_ptr = free_mem_ptr + HEAP_SIZE;
-	output = (unsigned char *) ((free_mem_end_ptr + 4095UL) & -4096UL);
+	output = (unsigned char *) output_addr;
 
 #ifdef CONFIG_BLK_DEV_INITRD
 	/*
diff -druNp linux-libre-2.6.37-gnu1/arch/s390/crypto/sha_common.c linux-libre-2.6.38-gnu1/arch/s390/crypto/sha_common.c
--- linux-libre-2.6.37-gnu1/arch/s390/crypto/sha_common.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/s390/crypto/sha_common.c	2011-03-14 21:20:32.000000000 -0400
@@ -38,6 +38,7 @@ int s390_sha_update(struct shash_desc *d
 		BUG_ON(ret != bsize);
 		data += bsize - index;
 		len -= bsize - index;
+		index = 0;
 	}
 
 	/* process as many blocks as possible */
diff -druNp linux-libre-2.6.37-gnu1/arch/s390/defconfig linux-libre-2.6.38-gnu1/arch/s390/defconfig
--- linux-libre-2.6.37-gnu1/arch/s390/defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/s390/defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -2,17 +2,24 @@ CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
 CONFIG_AUDIT=y
+CONFIG_RCU_TRACE=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_CGROUPS=y
-CONFIG_CGROUP_NS=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_UTS_NS=y
-CONFIG_IPC_NS=y
+CONFIG_CPUSETS=y
+CONFIG_CGROUP_CPUACCT=y
+CONFIG_RESOURCE_COUNTERS=y
+CONFIG_CGROUP_MEM_RES_CTLR=y
+CONFIG_CGROUP_MEM_RES_CTLR_SWAP=y
+CONFIG_CGROUP_SCHED=y
+CONFIG_RT_GROUP_SCHED=y
+CONFIG_BLK_CGROUP=y
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 # 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
@@ -20,24 +27,14 @@ CONFIG_MODVERSIONS=y
 CONFIG_DEFAULT_DEADLINE=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
-CONFIG_64BIT=y
-CONFIG_SMP=y
-CONFIG_NR_CPUS=32
-CONFIG_COMPAT=y
-CONFIG_S390_EXEC_PROTECT=y
-CONFIG_PACK_STACK=y
-CONFIG_CHECK_STACK=y
 CONFIG_PREEMPT=y
 CONFIG_MEMORY_HOTPLUG=y
 CONFIG_MEMORY_HOTREMOVE=y
-CONFIG_QDIO=y
-CONFIG_CHSC_SCH=m
-CONFIG_IPL=y
+CONFIG_KSM=y
 CONFIG_BINFMT_MISC=m
-CONFIG_PFAULT=y
+CONFIG_CMM=m
 CONFIG_HZ_100=y
 CONFIG_KEXEC=y
-CONFIG_S390_GUEST=y
 CONFIG_PM=y
 CONFIG_HIBERNATION=y
 CONFIG_PACKET=y
@@ -46,16 +43,15 @@ CONFIG_NET_KEY=y
 CONFIG_AFIUCV=m
 CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
+# CONFIG_INET_LRO is not set
 CONFIG_IPV6=y
-CONFIG_NETFILTER=y
-CONFIG_NETFILTER_NETLINK_QUEUE=m
-CONFIG_NETFILTER_NETLINK_LOG=m
-CONFIG_NF_CONNTRACK=m
-# CONFIG_NF_CT_PROTO_SCTP is not set
+CONFIG_NET_SCTPPROBE=m
+CONFIG_L2TP=m
+CONFIG_L2TP_DEBUGFS=m
+CONFIG_VLAN_8021Q=y
 CONFIG_NET_SCHED=y
 CONFIG_NET_SCH_CBQ=m
 CONFIG_NET_SCH_PRIO=m
-CONFIG_NET_SCH_MULTIQ=y
 CONFIG_NET_SCH_RED=m
 CONFIG_NET_SCH_SFQ=m
 CONFIG_NET_SCH_TEQL=m
@@ -69,28 +65,14 @@ CONFIG_NET_CLS_U32=m
 CONFIG_CLS_U32_MARK=y
 CONFIG_NET_CLS_RSVP=m
 CONFIG_NET_CLS_RSVP6=m
-CONFIG_NET_CLS_FLOW=m
 CONFIG_NET_CLS_ACT=y
 CONFIG_NET_ACT_POLICE=y
-CONFIG_NET_ACT_NAT=m
-CONFIG_CAN=m
-CONFIG_CAN_RAW=m
-CONFIG_CAN_BCM=m
-CONFIG_CAN_VCAN=m
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 # CONFIG_FIRMWARE_IN_KERNEL is not set
 CONFIG_BLK_DEV_LOOP=m
 CONFIG_BLK_DEV_NBD=m
 CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_XIP=y
-CONFIG_BLK_DEV_XPRAM=m
-CONFIG_DASD=y
-CONFIG_DASD_PROFILE=y
-CONFIG_DASD_ECKD=y
-CONFIG_DASD_FBA=y
-CONFIG_DASD_DIAG=y
-CONFIG_DASD_EER=y
-CONFIG_VIRTIO_BLK=m
+CONFIG_VIRTIO_BLK=y
 CONFIG_SCSI=y
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=y
@@ -102,101 +84,93 @@ CONFIG_SCSI_CONSTANTS=y
 CONFIG_SCSI_LOGGING=y
 CONFIG_SCSI_SCAN_ASYNC=y
 CONFIG_ZFCP=y
-CONFIG_SCSI_DH=m
-CONFIG_SCSI_DH_RDAC=m
-CONFIG_SCSI_DH_HP_SW=m
-CONFIG_SCSI_DH_EMC=m
-CONFIG_SCSI_DH_ALUA=m
-CONFIG_SCSI_OSD_INITIATOR=m
-CONFIG_SCSI_OSD_ULD=m
-CONFIG_MD=y
-CONFIG_BLK_DEV_MD=y
-CONFIG_MD_LINEAR=m
-CONFIG_MD_RAID0=m
-CONFIG_MD_RAID1=m
-CONFIG_MD_MULTIPATH=m
-CONFIG_BLK_DEV_DM=y
-CONFIG_DM_CRYPT=y
-CONFIG_DM_SNAPSHOT=y
-CONFIG_DM_MIRROR=y
-CONFIG_DM_ZERO=y
-CONFIG_DM_MULTIPATH=m
+CONFIG_ZFCP_DIF=y
 CONFIG_NETDEVICES=y
 CONFIG_DUMMY=m
 CONFIG_BONDING=m
 CONFIG_EQUALIZER=m
 CONFIG_TUN=m
-CONFIG_VETH=m
 CONFIG_NET_ETHERNET=y
-CONFIG_LCS=m
-CONFIG_CTCM=m
-CONFIG_QETH=y
-CONFIG_QETH_L2=y
-CONFIG_QETH_L3=y
-CONFIG_VIRTIO_NET=m
-CONFIG_HW_RANDOM_VIRTIO=m
+CONFIG_VIRTIO_NET=y
 CONFIG_RAW_DRIVER=m
-CONFIG_TN3270=y
-CONFIG_TN3270_TTY=y
-CONFIG_TN3270_FS=m
-CONFIG_TN3270_CONSOLE=y
-CONFIG_TN3215=y
-CONFIG_TN3215_CONSOLE=y
-CONFIG_SCLP_TTY=y
-CONFIG_SCLP_CONSOLE=y
-CONFIG_SCLP_VT220_TTY=y
-CONFIG_SCLP_VT220_CONSOLE=y
-CONFIG_SCLP_CPI=m
-CONFIG_SCLP_ASYNC=m
-CONFIG_S390_TAPE=m
-CONFIG_S390_TAPE_BLOCK=y
-CONFIG_S390_TAPE_34XX=m
-CONFIG_ACCESSIBILITY=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
 # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+CONFIG_EXT4_FS=y
+CONFIG_EXT4_FS_POSIX_ACL=y
+CONFIG_EXT4_FS_SECURITY=y
 CONFIG_PROC_KCORE=y
 CONFIG_TMPFS=y
 CONFIG_TMPFS_POSIX_ACL=y
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-CONFIG_NFSD=y
-CONFIG_NFSD_V3=y
+# CONFIG_NETWORK_FILESYSTEMS is not set
 CONFIG_PARTITION_ADVANCED=y
 CONFIG_IBM_PARTITION=y
 CONFIG_DLM=m
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_DEBUG_KERNEL=y
-# CONFIG_SCHED_DEBUG is not set
-CONFIG_DEBUG_SPINLOCK=y
-CONFIG_DEBUG_MUTEXES=y
+CONFIG_TIMER_STATS=y
+CONFIG_PROVE_LOCKING=y
+CONFIG_PROVE_RCU=y
+CONFIG_LOCK_STAT=y
+CONFIG_DEBUG_LOCKDEP=y
 CONFIG_DEBUG_SPINLOCK_SLEEP=y
+CONFIG_DEBUG_LIST=y
+CONFIG_DEBUG_NOTIFIERS=y
 # CONFIG_RCU_CPU_STALL_DETECTOR is not set
+CONFIG_KPROBES_SANITY_TEST=y
 CONFIG_DEBUG_FORCE_WEAK_PER_CPU=y
+CONFIG_CPU_NOTIFIER_ERROR_INJECT=m
+CONFIG_LATENCYTOP=y
 CONFIG_SYSCTL_SYSCALL_CHECK=y
-CONFIG_SAMPLES=y
-CONFIG_CRYPTO_FIPS=y
+CONFIG_DEBUG_PAGEALLOC=y
+# CONFIG_FTRACE is not set
+# CONFIG_STRICT_DEVMEM is not set
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_CRYPTD=m
 CONFIG_CRYPTO_AUTHENC=m
+CONFIG_CRYPTO_TEST=m
 CONFIG_CRYPTO_CCM=m
 CONFIG_CRYPTO_GCM=m
+CONFIG_CRYPTO_CBC=y
 CONFIG_CRYPTO_CTS=m
 CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_LRW=m
 CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_XTS=m
+CONFIG_CRYPTO_XCBC=m
 CONFIG_CRYPTO_VMAC=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
 CONFIG_CRYPTO_RMD128=m
 CONFIG_CRYPTO_RMD160=m
 CONFIG_CRYPTO_RMD256=m
 CONFIG_CRYPTO_RMD320=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_BLOWFISH=m
 CONFIG_CRYPTO_CAMELLIA=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_DES=m
 CONFIG_CRYPTO_FCRYPT=m
+CONFIG_CRYPTO_KHAZAD=m
 CONFIG_CRYPTO_SALSA20=m
 CONFIG_CRYPTO_SEED=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_DEFLATE=m
 CONFIG_CRYPTO_ZLIB=m
 CONFIG_CRYPTO_LZO=m
 CONFIG_ZCRYPT=m
+CONFIG_CRYPTO_SHA1_S390=m
+CONFIG_CRYPTO_SHA256_S390=m
 CONFIG_CRYPTO_SHA512_S390=m
-CONFIG_CRC_T10DIF=y
-CONFIG_CRC32=m
+CONFIG_CRYPTO_DES_S390=m
+CONFIG_CRYPTO_AES_S390=m
 CONFIG_CRC7=m
-CONFIG_KVM=m
-CONFIG_VIRTIO_BALLOON=m
+CONFIG_VIRTIO_BALLOON=y
diff -druNp linux-libre-2.6.37-gnu1/arch/s390/hypfs/hypfs_dbfs.c linux-libre-2.6.38-gnu1/arch/s390/hypfs/hypfs_dbfs.c
--- linux-libre-2.6.37-gnu1/arch/s390/hypfs/hypfs_dbfs.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/s390/hypfs/hypfs_dbfs.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,116 @@
+/*
+ * Hypervisor filesystem for Linux on s390 - debugfs interface
+ *
+ * Copyright (C) IBM Corp. 2010
+ * Author(s): Michael Holzheu <holzheu@linux.vnet.ibm.com>
+ */
+
+#include <linux/slab.h>
+#include "hypfs.h"
+
+static struct dentry *dbfs_dir;
+
+static struct hypfs_dbfs_data *hypfs_dbfs_data_alloc(struct hypfs_dbfs_file *f)
+{
+	struct hypfs_dbfs_data *data;
+
+	data = kmalloc(sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return NULL;
+	kref_init(&data->kref);
+	data->dbfs_file = f;
+	return data;
+}
+
+static void hypfs_dbfs_data_free(struct kref *kref)
+{
+	struct hypfs_dbfs_data *data;
+
+	data = container_of(kref, struct hypfs_dbfs_data, kref);
+	data->dbfs_file->data_free(data->buf_free_ptr);
+	kfree(data);
+}
+
+static void data_free_delayed(struct work_struct *work)
+{
+	struct hypfs_dbfs_data *data;
+	struct hypfs_dbfs_file *df;
+
+	df = container_of(work, struct hypfs_dbfs_file, data_free_work.work);
+	mutex_lock(&df->lock);
+	data = df->data;
+	df->data = NULL;
+	mutex_unlock(&df->lock);
+	kref_put(&data->kref, hypfs_dbfs_data_free);
+}
+
+static ssize_t dbfs_read(struct file *file, char __user *buf,
+			 size_t size, loff_t *ppos)
+{
+	struct hypfs_dbfs_data *data;
+	struct hypfs_dbfs_file *df;
+	ssize_t rc;
+
+	if (*ppos != 0)
+		return 0;
+
+	df = file->f_path.dentry->d_inode->i_private;
+	mutex_lock(&df->lock);
+	if (!df->data) {
+		data = hypfs_dbfs_data_alloc(df);
+		if (!data) {
+			mutex_unlock(&df->lock);
+			return -ENOMEM;
+		}
+		rc = df->data_create(&data->buf, &data->buf_free_ptr,
+				     &data->size);
+		if (rc) {
+			mutex_unlock(&df->lock);
+			kfree(data);
+			return rc;
+		}
+		df->data = data;
+		schedule_delayed_work(&df->data_free_work, HZ);
+	}
+	data = df->data;
+	kref_get(&data->kref);
+	mutex_unlock(&df->lock);
+
+	rc = simple_read_from_buffer(buf, size, ppos, data->buf, data->size);
+	kref_put(&data->kref, hypfs_dbfs_data_free);
+	return rc;
+}
+
+static const struct file_operations dbfs_ops = {
+	.read		= dbfs_read,
+	.llseek		= no_llseek,
+};
+
+int hypfs_dbfs_create_file(struct hypfs_dbfs_file *df)
+{
+	df->dentry = debugfs_create_file(df->name, 0400, dbfs_dir, df,
+					 &dbfs_ops);
+	if (IS_ERR(df->dentry))
+		return PTR_ERR(df->dentry);
+	mutex_init(&df->lock);
+	INIT_DELAYED_WORK(&df->data_free_work, data_free_delayed);
+	return 0;
+}
+
+void hypfs_dbfs_remove_file(struct hypfs_dbfs_file *df)
+{
+	debugfs_remove(df->dentry);
+}
+
+int hypfs_dbfs_init(void)
+{
+	dbfs_dir = debugfs_create_dir("s390_hypfs", NULL);
+	if (IS_ERR(dbfs_dir))
+		return PTR_ERR(dbfs_dir);
+	return 0;
+}
+
+void hypfs_dbfs_exit(void)
+{
+	debugfs_remove(dbfs_dir);
+}
diff -druNp linux-libre-2.6.37-gnu1/arch/s390/hypfs/hypfs_diag.c linux-libre-2.6.38-gnu1/arch/s390/hypfs/hypfs_diag.c
--- linux-libre-2.6.37-gnu1/arch/s390/hypfs/hypfs_diag.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/s390/hypfs/hypfs_diag.c	2011-03-14 21:20:32.000000000 -0400
@@ -555,81 +555,38 @@ struct dbfs_d204 {
 	char			buf[];	/* d204 buffer */
 } __attribute__ ((packed));
 
-struct dbfs_d204_private {
-	struct dbfs_d204	*d204;	/* Aligned d204 data with header */
-	void			*base;	/* Base pointer (needed for vfree) */
-};
-
-static int dbfs_d204_open(struct inode *inode, struct file *file)
+static int dbfs_d204_create(void **data, void **data_free_ptr, size_t *size)
 {
-	struct dbfs_d204_private *data;
 	struct dbfs_d204 *d204;
 	int rc, buf_size;
+	void *base;
 
-	data = kzalloc(sizeof(*data), GFP_KERNEL);
-	if (!data)
-		return -ENOMEM;
 	buf_size = PAGE_SIZE * (diag204_buf_pages + 1) + sizeof(d204->hdr);
-	data->base = vmalloc(buf_size);
-	if (!data->base) {
-		rc = -ENOMEM;
-		goto fail_kfree_data;
+	base = vmalloc(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) {
+		vfree(base);
+		return rc;
 	}
-	memset(data->base, 0, buf_size);
-	d204 = page_align_ptr(data->base + sizeof(d204->hdr))
-		- sizeof(d204->hdr);
-	rc = diag204_do_store(&d204->buf, diag204_buf_pages);
-	if (rc)
-		goto fail_vfree_base;
 	d204->hdr.version = DBFS_D204_HDR_VERSION;
 	d204->hdr.len = PAGE_SIZE * diag204_buf_pages;
 	d204->hdr.sc = diag204_store_sc;
-	data->d204 = d204;
-	file->private_data = data;
-	return nonseekable_open(inode, file);
-
-fail_vfree_base:
-	vfree(data->base);
-fail_kfree_data:
-	kfree(data);
-	return rc;
-}
-
-static int dbfs_d204_release(struct inode *inode, struct file *file)
-{
-	struct dbfs_d204_private *data = file->private_data;
-
-	vfree(data->base);
-	kfree(data);
+	*data = d204;
+	*data_free_ptr = base;
+	*size = d204->hdr.len + sizeof(struct dbfs_d204_hdr);
 	return 0;
 }
 
-static ssize_t dbfs_d204_read(struct file *file, char __user *buf,
-			      size_t size, loff_t *ppos)
-{
-	struct dbfs_d204_private *data = file->private_data;
-
-	return simple_read_from_buffer(buf, size, ppos, data->d204,
-				       data->d204->hdr.len +
-				       sizeof(data->d204->hdr));
-}
-
-static const struct file_operations dbfs_d204_ops = {
-	.open		= dbfs_d204_open,
-	.read		= dbfs_d204_read,
-	.release	= dbfs_d204_release,
-	.llseek		= no_llseek,
+static struct hypfs_dbfs_file dbfs_file_d204 = {
+	.name		= "diag_204",
+	.data_create	= dbfs_d204_create,
+	.data_free	= vfree,
 };
 
-static int hypfs_dbfs_init(void)
-{
-	dbfs_d204_file = debugfs_create_file("diag_204", 0400, hypfs_dbfs_dir,
-					     NULL, &dbfs_d204_ops);
-	if (IS_ERR(dbfs_d204_file))
-		return PTR_ERR(dbfs_d204_file);
-	return 0;
-}
-
 __init int hypfs_diag_init(void)
 {
 	int rc;
@@ -639,7 +596,7 @@ __init int hypfs_diag_init(void)
 		return -ENODATA;
 	}
 	if (diag204_info_type == INFO_EXT) {
-		rc = hypfs_dbfs_init();
+		rc = hypfs_dbfs_create_file(&dbfs_file_d204);
 		if (rc)
 			return rc;
 	}
@@ -660,6 +617,7 @@ void hypfs_diag_exit(void)
 	debugfs_remove(dbfs_d204_file);
 	diag224_delete_name_table();
 	diag204_free_buffer();
+	hypfs_dbfs_remove_file(&dbfs_file_d204);
 }
 
 /*
diff -druNp linux-libre-2.6.37-gnu1/arch/s390/hypfs/hypfs.h linux-libre-2.6.38-gnu1/arch/s390/hypfs/hypfs.h
--- linux-libre-2.6.37-gnu1/arch/s390/hypfs/hypfs.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/s390/hypfs/hypfs.h	2011-03-14 21:20:32.000000000 -0400
@@ -12,6 +12,8 @@
 #include <linux/fs.h>
 #include <linux/types.h>
 #include <linux/debugfs.h>
+#include <linux/workqueue.h>
+#include <linux/kref.h>
 
 #define REG_FILE_MODE    0440
 #define UPDATE_FILE_MODE 0220
@@ -38,6 +40,33 @@ extern int hypfs_vm_init(void);
 extern void hypfs_vm_exit(void);
 extern int hypfs_vm_create_files(struct super_block *sb, struct dentry *root);
 
-/* Directory for debugfs files */
-extern struct dentry *hypfs_dbfs_dir;
+/* debugfs interface */
+struct hypfs_dbfs_file;
+
+struct hypfs_dbfs_data {
+	void			*buf;
+	void			*buf_free_ptr;
+	size_t			size;
+	struct hypfs_dbfs_file	*dbfs_file;;
+	struct kref		kref;
+};
+
+struct hypfs_dbfs_file {
+	const char	*name;
+	int		(*data_create)(void **data, void **data_free_ptr,
+				       size_t *size);
+	void		(*data_free)(const void *buf_free_ptr);
+
+	/* Private data for hypfs_dbfs.c */
+	struct hypfs_dbfs_data	*data;
+	struct delayed_work	data_free_work;
+	struct mutex		lock;
+	struct dentry		*dentry;
+};
+
+extern int hypfs_dbfs_init(void);
+extern void hypfs_dbfs_exit(void);
+extern int hypfs_dbfs_create_file(struct hypfs_dbfs_file *df);
+extern void hypfs_dbfs_remove_file(struct hypfs_dbfs_file *df);
+
 #endif /* _HYPFS_H_ */
diff -druNp linux-libre-2.6.37-gnu1/arch/s390/hypfs/hypfs_vm.c linux-libre-2.6.38-gnu1/arch/s390/hypfs/hypfs_vm.c
--- linux-libre-2.6.37-gnu1/arch/s390/hypfs/hypfs_vm.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/s390/hypfs/hypfs_vm.c	2011-03-14 21:20:32.000000000 -0400
@@ -20,8 +20,6 @@ static char local_guest[] = "        ";
 static char all_guests[] = "*       ";
 static char *guest_query;
 
-static struct dentry *dbfs_d2fc_file;
-
 struct diag2fc_data {
 	__u32 version;
 	__u32 flags;
@@ -104,7 +102,7 @@ static void *diag2fc_store(char *query,
 	return data;
 }
 
-static void diag2fc_free(void *data)
+static void diag2fc_free(const void *data)
 {
 	vfree(data);
 }
@@ -239,43 +237,29 @@ struct dbfs_d2fc {
 	char			buf[];	/* d2fc buffer */
 } __attribute__ ((packed));
 
-static int dbfs_d2fc_open(struct inode *inode, struct file *file)
+static int dbfs_diag2fc_create(void **data, void **data_free_ptr, size_t *size)
 {
-	struct dbfs_d2fc *data;
+	struct dbfs_d2fc *d2fc;
 	unsigned int count;
 
-	data = diag2fc_store(guest_query, &count, sizeof(data->hdr));
-	if (IS_ERR(data))
-		return PTR_ERR(data);
-	get_clock_ext(data->hdr.tod_ext);
-	data->hdr.len = count * sizeof(struct diag2fc_data);
-	data->hdr.version = DBFS_D2FC_HDR_VERSION;
-	data->hdr.count = count;
-	memset(&data->hdr.reserved, 0, sizeof(data->hdr.reserved));
-	file->private_data = data;
-	return nonseekable_open(inode, file);
-}
-
-static int dbfs_d2fc_release(struct inode *inode, struct file *file)
-{
-	diag2fc_free(file->private_data);
+	d2fc = diag2fc_store(guest_query, &count, sizeof(d2fc->hdr));
+	if (IS_ERR(d2fc))
+		return PTR_ERR(d2fc);
+	get_clock_ext(d2fc->hdr.tod_ext);
+	d2fc->hdr.len = count * sizeof(struct diag2fc_data);
+	d2fc->hdr.version = DBFS_D2FC_HDR_VERSION;
+	d2fc->hdr.count = count;
+	memset(&d2fc->hdr.reserved, 0, sizeof(d2fc->hdr.reserved));
+	*data = d2fc;
+	*data_free_ptr = d2fc;
+	*size = d2fc->hdr.len + sizeof(struct dbfs_d2fc_hdr);
 	return 0;
 }
 
-static ssize_t dbfs_d2fc_read(struct file *file, char __user *buf,
-				    size_t size, loff_t *ppos)
-{
-	struct dbfs_d2fc *data = file->private_data;
-
-	return simple_read_from_buffer(buf, size, ppos, data, data->hdr.len +
-				       sizeof(struct dbfs_d2fc_hdr));
-}
-
-static const struct file_operations dbfs_d2fc_ops = {
-	.open		= dbfs_d2fc_open,
-	.read		= dbfs_d2fc_read,
-	.release	= dbfs_d2fc_release,
-	.llseek		= no_llseek,
+static struct hypfs_dbfs_file dbfs_file_2fc = {
+	.name		= "diag_2fc",
+	.data_create	= dbfs_diag2fc_create,
+	.data_free	= diag2fc_free,
 };
 
 int hypfs_vm_init(void)
@@ -288,18 +272,12 @@ int hypfs_vm_init(void)
 		guest_query = local_guest;
 	else
 		return -EACCES;
-
-	dbfs_d2fc_file = debugfs_create_file("diag_2fc", 0400, hypfs_dbfs_dir,
-					     NULL, &dbfs_d2fc_ops);
-	if (IS_ERR(dbfs_d2fc_file))
-		return PTR_ERR(dbfs_d2fc_file);
-
-	return 0;
+	return hypfs_dbfs_create_file(&dbfs_file_2fc);
 }
 
 void hypfs_vm_exit(void)
 {
 	if (!MACHINE_IS_VM)
 		return;
-	debugfs_remove(dbfs_d2fc_file);
+	hypfs_dbfs_remove_file(&dbfs_file_2fc);
 }
diff -druNp linux-libre-2.6.37-gnu1/arch/s390/hypfs/inode.c linux-libre-2.6.38-gnu1/arch/s390/hypfs/inode.c
--- linux-libre-2.6.37-gnu1/arch/s390/hypfs/inode.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/s390/hypfs/inode.c	2011-03-14 21:20:32.000000000 -0400
@@ -46,8 +46,6 @@ static const struct super_operations hyp
 /* start of list of all dentries, which have to be deleted on update */
 static struct dentry *hypfs_last_dentry;
 
-struct dentry *hypfs_dbfs_dir;
-
 static void hypfs_update_update(struct super_block *sb)
 {
 	struct hypfs_sb_info *sb_info = sb->s_fs_info;
@@ -471,13 +469,12 @@ static int __init hypfs_init(void)
 {
 	int rc;
 
-	hypfs_dbfs_dir = debugfs_create_dir("s390_hypfs", NULL);
-	if (IS_ERR(hypfs_dbfs_dir))
-		return PTR_ERR(hypfs_dbfs_dir);
-
+	rc = hypfs_dbfs_init();
+	if (rc)
+		return rc;
 	if (hypfs_diag_init()) {
 		rc = -ENODATA;
-		goto fail_debugfs_remove;
+		goto fail_dbfs_exit;
 	}
 	if (hypfs_vm_init()) {
 		rc = -ENODATA;
@@ -499,9 +496,8 @@ fail_hypfs_vm_exit:
 	hypfs_vm_exit();
 fail_hypfs_diag_exit:
 	hypfs_diag_exit();
-fail_debugfs_remove:
-	debugfs_remove(hypfs_dbfs_dir);
-
+fail_dbfs_exit:
+	hypfs_dbfs_exit();
 	pr_err("Initialization of hypfs failed with rc=%i\n", rc);
 	return rc;
 }
@@ -510,7 +506,7 @@ static void __exit hypfs_exit(void)
 {
 	hypfs_diag_exit();
 	hypfs_vm_exit();
-	debugfs_remove(hypfs_dbfs_dir);
+	hypfs_dbfs_exit();
 	unregister_filesystem(&hypfs_type);
 	kobject_put(s390_kobj);
 }
diff -druNp linux-libre-2.6.37-gnu1/arch/s390/hypfs/Makefile linux-libre-2.6.38-gnu1/arch/s390/hypfs/Makefile
--- linux-libre-2.6.37-gnu1/arch/s390/hypfs/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/s390/hypfs/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -4,4 +4,4 @@
 
 obj-$(CONFIG_S390_HYPFS_FS) += s390_hypfs.o
 
-s390_hypfs-objs := inode.o hypfs_diag.o hypfs_vm.o
+s390_hypfs-objs := inode.o hypfs_diag.o hypfs_vm.o hypfs_dbfs.o
diff -druNp linux-libre-2.6.37-gnu1/arch/s390/include/asm/atomic.h linux-libre-2.6.38-gnu1/arch/s390/include/asm/atomic.h
--- linux-libre-2.6.37-gnu1/arch/s390/include/asm/atomic.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/s390/include/asm/atomic.h	2011-03-14 21:20:32.000000000 -0400
@@ -36,14 +36,19 @@
 
 static inline int atomic_read(const atomic_t *v)
 {
-	barrier();
-	return v->counter;
+	int c;
+
+	asm volatile(
+		"	l	%0,%1\n"
+		: "=d" (c) : "Q" (v->counter));
+	return c;
 }
 
 static inline void atomic_set(atomic_t *v, int i)
 {
-	v->counter = i;
-	barrier();
+	asm volatile(
+		"	st	%1,%0\n"
+		: "=Q" (v->counter) : "d" (i));
 }
 
 static inline int atomic_add_return(int i, atomic_t *v)
@@ -128,14 +133,19 @@ static inline int atomic_add_unless(atom
 
 static inline long long atomic64_read(const atomic64_t *v)
 {
-	barrier();
-	return v->counter;
+	long long c;
+
+	asm volatile(
+		"	lg	%0,%1\n"
+		: "=d" (c) : "Q" (v->counter));
+	return c;
 }
 
 static inline void atomic64_set(atomic64_t *v, long long i)
 {
-	v->counter = i;
-	barrier();
+	asm volatile(
+		"	stg	%1,%0\n"
+		: "=Q" (v->counter) : "d" (i));
 }
 
 static inline long long atomic64_add_return(long long i, atomic64_t *v)
diff -druNp linux-libre-2.6.37-gnu1/arch/s390/include/asm/cacheflush.h linux-libre-2.6.38-gnu1/arch/s390/include/asm/cacheflush.h
--- linux-libre-2.6.37-gnu1/arch/s390/include/asm/cacheflush.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/s390/include/asm/cacheflush.h	2011-03-14 21:20:32.000000000 -0400
@@ -1,29 +1,8 @@
 #ifndef _S390_CACHEFLUSH_H
 #define _S390_CACHEFLUSH_H
 
-/* Keep includes the same across arches.  */
-#include <linux/mm.h>
-
 /* Caches aren't brain-dead on the s390. */
-#define flush_cache_all()			do { } while (0)
-#define flush_cache_mm(mm)			do { } while (0)
-#define flush_cache_dup_mm(mm)			do { } while (0)
-#define flush_cache_range(vma, start, end)	do { } while (0)
-#define flush_cache_page(vma, vmaddr, pfn)	do { } while (0)
-#define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 0
-#define flush_dcache_page(page)			do { } while (0)
-#define flush_dcache_mmap_lock(mapping)		do { } while (0)
-#define flush_dcache_mmap_unlock(mapping)	do { } while (0)
-#define flush_icache_range(start, end)		do { } while (0)
-#define flush_icache_page(vma,pg)		do { } while (0)
-#define flush_icache_user_range(vma,pg,adr,len)	do { } while (0)
-#define flush_cache_vmap(start, end)		do { } while (0)
-#define flush_cache_vunmap(start, end)		do { } while (0)
-
-#define copy_to_user_page(vma, page, vaddr, dst, src, len) \
-	memcpy(dst, src, len)
-#define copy_from_user_page(vma, page, vaddr, dst, src, len) \
-	memcpy(dst, src, len)
+#include <asm-generic/cacheflush.h>
 
 #ifdef CONFIG_DEBUG_PAGEALLOC
 void kernel_map_pages(struct page *page, int numpages, int enable);
diff -druNp linux-libre-2.6.37-gnu1/arch/s390/include/asm/cache.h linux-libre-2.6.38-gnu1/arch/s390/include/asm/cache.h
--- linux-libre-2.6.37-gnu1/arch/s390/include/asm/cache.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/s390/include/asm/cache.h	2011-03-14 21:20:32.000000000 -0400
@@ -13,6 +13,7 @@
 
 #define L1_CACHE_BYTES     256
 #define L1_CACHE_SHIFT     8
+#define NET_SKB_PAD	   32
 
 #define __read_mostly __attribute__((__section__(".data..read_mostly")))
 
diff -druNp linux-libre-2.6.37-gnu1/arch/s390/include/asm/ccwdev.h linux-libre-2.6.38-gnu1/arch/s390/include/asm/ccwdev.h
--- linux-libre-2.6.37-gnu1/arch/s390/include/asm/ccwdev.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/s390/include/asm/ccwdev.h	2011-03-14 21:20:32.000000000 -0400
@@ -204,6 +204,8 @@ int ccw_device_tm_start_timeout(struct c
 			    unsigned long, u8, int);
 int ccw_device_tm_intrg(struct ccw_device *cdev);
 
+int ccw_device_get_mdc(struct ccw_device *cdev, u8 mask);
+
 extern int ccw_device_set_online(struct ccw_device *cdev);
 extern int ccw_device_set_offline(struct ccw_device *cdev);
 
diff -druNp linux-libre-2.6.37-gnu1/arch/s390/include/asm/compat.h linux-libre-2.6.38-gnu1/arch/s390/include/asm/compat.h
--- linux-libre-2.6.37-gnu1/arch/s390/include/asm/compat.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/s390/include/asm/compat.h	2011-03-14 21:20:32.000000000 -0400
@@ -169,7 +169,7 @@ static inline compat_uptr_t ptr_to_compa
 
 static inline int is_compat_task(void)
 {
-	return test_thread_flag(TIF_31BIT);
+	return is_32bit_task();
 }
 
 #else
diff -druNp linux-libre-2.6.37-gnu1/arch/s390/include/asm/cputime.h linux-libre-2.6.38-gnu1/arch/s390/include/asm/cputime.h
--- linux-libre-2.6.37-gnu1/arch/s390/include/asm/cputime.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/s390/include/asm/cputime.h	2011-03-14 21:20:32.000000000 -0400
@@ -202,7 +202,7 @@ static inline void s390_idle_check(struc
 
 static inline int s390_nohz_delay(int cpu)
 {
-	return per_cpu(s390_idle, cpu).nohz_delay != 0;
+	return __get_cpu_var(s390_idle).nohz_delay != 0;
 }
 
 #define arch_needs_cpu(cpu) s390_nohz_delay(cpu)
diff -druNp linux-libre-2.6.37-gnu1/arch/s390/include/asm/dasd.h linux-libre-2.6.38-gnu1/arch/s390/include/asm/dasd.h
--- linux-libre-2.6.37-gnu1/arch/s390/include/asm/dasd.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/s390/include/asm/dasd.h	2011-03-14 21:20:32.000000000 -0400
@@ -73,6 +73,7 @@ typedef struct dasd_information2_t {
  * 0x02: use diag discipline (diag)
  * 0x04: set the device initially online (internal use only)
  * 0x08: enable ERP related logging
+ * 0x20: give access to raw eckd data
  */
 #define DASD_FEATURE_DEFAULT	     0x00
 #define DASD_FEATURE_READONLY	     0x01
@@ -80,6 +81,8 @@ typedef struct dasd_information2_t {
 #define DASD_FEATURE_INITIAL_ONLINE  0x04
 #define DASD_FEATURE_ERPLOG	     0x08
 #define DASD_FEATURE_FAILFAST	     0x10
+#define DASD_FEATURE_FAILONSLCK      0x20
+#define DASD_FEATURE_USERAW	     0x40
 
 #define DASD_PARTN_BITS 2
 
diff -druNp linux-libre-2.6.37-gnu1/arch/s390/include/asm/elf.h linux-libre-2.6.38-gnu1/arch/s390/include/asm/elf.h
--- linux-libre-2.6.37-gnu1/arch/s390/include/asm/elf.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/s390/include/asm/elf.h	2011-03-14 21:20:32.000000000 -0400
@@ -161,7 +161,9 @@ extern unsigned int vdso_enabled;
    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		(STACK_TOP / 3 * 2)
+
+extern unsigned long randomize_et_dyn(unsigned long base);
+#define ELF_ET_DYN_BASE		(randomize_et_dyn(STACK_TOP / 3 * 2))
 
 /* This yields a mask that user programs can use to figure out what
    instruction set this CPU supports. */
@@ -206,6 +208,8 @@ do {								\
 	current->mm->context.noexec == 0;		\
 })
 
+#define STACK_RND_MASK	0x7ffUL
+
 #define ARCH_DLINFO							    \
 do {									    \
 	if (vdso_enabled)						    \
@@ -218,4 +222,7 @@ struct linux_binprm;
 #define ARCH_HAS_SETUP_ADDITIONAL_PAGES 1
 int arch_setup_additional_pages(struct linux_binprm *, int);
 
+extern unsigned long arch_randomize_brk(struct mm_struct *mm);
+#define arch_randomize_brk arch_randomize_brk
+
 #endif
diff -druNp linux-libre-2.6.37-gnu1/arch/s390/include/asm/ftrace.h linux-libre-2.6.38-gnu1/arch/s390/include/asm/ftrace.h
--- linux-libre-2.6.37-gnu1/arch/s390/include/asm/ftrace.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/s390/include/asm/ftrace.h	2011-03-14 21:20:32.000000000 -0400
@@ -4,20 +4,17 @@
 #ifndef __ASSEMBLY__
 
 extern void _mcount(void);
-extern unsigned long ftrace_dyn_func;
 
 struct dyn_arch_ftrace { };
 
 #define MCOUNT_ADDR ((long)_mcount)
 
 #ifdef CONFIG_64BIT
-#define MCOUNT_OFFSET_RET 18
-#define MCOUNT_INSN_SIZE  24
-#define MCOUNT_OFFSET	  14
-#else
-#define MCOUNT_OFFSET_RET 26
-#define MCOUNT_INSN_SIZE  30
+#define MCOUNT_INSN_SIZE  12
 #define MCOUNT_OFFSET	   8
+#else
+#define MCOUNT_INSN_SIZE  20
+#define MCOUNT_OFFSET	   4
 #endif
 
 static inline unsigned long ftrace_call_adjust(unsigned long addr)
diff -druNp linux-libre-2.6.37-gnu1/arch/s390/include/asm/hardirq.h linux-libre-2.6.38-gnu1/arch/s390/include/asm/hardirq.h
--- linux-libre-2.6.37-gnu1/arch/s390/include/asm/hardirq.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/s390/include/asm/hardirq.h	2011-03-14 21:20:32.000000000 -0400
@@ -21,20 +21,4 @@
 
 #define HARDIRQ_BITS	8
 
-void clock_comparator_work(void);
-
-static inline unsigned long long local_tick_disable(void)
-{
-	unsigned long long old;
-
-	old = S390_lowcore.clock_comparator;
-	S390_lowcore.clock_comparator = -1ULL;
-	return old;
-}
-
-static inline void local_tick_enable(unsigned long long comp)
-{
-	S390_lowcore.clock_comparator = comp;
-}
-
 #endif /* __ASM_HARDIRQ_H */
diff -druNp linux-libre-2.6.37-gnu1/arch/s390/include/asm/irq.h linux-libre-2.6.38-gnu1/arch/s390/include/asm/irq.h
--- linux-libre-2.6.37-gnu1/arch/s390/include/asm/irq.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/s390/include/asm/irq.h	2011-03-14 21:20:32.000000000 -0400
@@ -1,23 +1,33 @@
 #ifndef _ASM_IRQ_H
 #define _ASM_IRQ_H
 
-#ifdef __KERNEL__
 #include <linux/hardirq.h>
 
-/*
- * the definition of irqs has changed in 2.5.46:
- * NR_IRQS is no longer the number of i/o
- * interrupts (65536), but rather the number
- * of interrupt classes (2).
- * Only external and i/o interrupts make much sense here (CH).
- */
-
 enum interruption_class {
 	EXTERNAL_INTERRUPT,
 	IO_INTERRUPT,
-
+	EXTINT_CLK,
+	EXTINT_IPI,
+	EXTINT_TMR,
+	EXTINT_TLA,
+	EXTINT_PFL,
+	EXTINT_DSD,
+	EXTINT_VRT,
+	EXTINT_SCP,
+	EXTINT_IUC,
+	IOINT_QAI,
+	IOINT_QDI,
+	IOINT_DAS,
+	IOINT_C15,
+	IOINT_C70,
+	IOINT_TAP,
+	IOINT_VMR,
+	IOINT_LCS,
+	IOINT_CLW,
+	IOINT_CTC,
+	IOINT_APB,
+	NMI_NMI,
 	NR_IRQS,
 };
 
-#endif /* __KERNEL__ */
-#endif
+#endif /* _ASM_IRQ_H */
diff -druNp linux-libre-2.6.37-gnu1/arch/s390/include/asm/kprobes.h linux-libre-2.6.38-gnu1/arch/s390/include/asm/kprobes.h
--- linux-libre-2.6.37-gnu1/arch/s390/include/asm/kprobes.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/s390/include/asm/kprobes.h	2011-03-14 21:20:32.000000000 -0400
@@ -31,7 +31,6 @@
 #include <linux/ptrace.h>
 #include <linux/percpu.h>
 
-#define  __ARCH_WANT_KPROBES_INSN_SLOT
 struct pt_regs;
 struct kprobe;
 
@@ -58,23 +57,12 @@ typedef u16 kprobe_opcode_t;
 /* Architecture specific copy of original instruction */
 struct arch_specific_insn {
 	/* copy of original instruction */
-	kprobe_opcode_t *insn;
-	int fixup;
-	int ilen;
-	int reg;
+	kprobe_opcode_t insn[MAX_INSN_SIZE];
 };
 
-struct ins_replace_args {
-	kprobe_opcode_t *ptr;
-	kprobe_opcode_t old;
-	kprobe_opcode_t new;
-};
 struct prev_kprobe {
 	struct kprobe *kp;
 	unsigned long status;
-	unsigned long saved_psw;
-	unsigned long kprobe_saved_imask;
-	unsigned long kprobe_saved_ctl[3];
 };
 
 /* per-cpu kprobe control block */
@@ -82,17 +70,13 @@ struct kprobe_ctlblk {
 	unsigned long kprobe_status;
 	unsigned long kprobe_saved_imask;
 	unsigned long kprobe_saved_ctl[3];
-	struct pt_regs jprobe_saved_regs;
-	unsigned long jprobe_saved_r14;
-	unsigned long jprobe_saved_r15;
 	struct prev_kprobe prev_kprobe;
+	struct pt_regs jprobe_saved_regs;
 	kprobe_opcode_t jprobes_stack[MAX_STACK_SIZE];
 };
 
 void arch_remove_kprobe(struct kprobe *p);
 void kretprobe_trampoline(void);
-int  is_prohibited_opcode(kprobe_opcode_t *instruction);
-void get_instruction_type(struct arch_specific_insn *ainsn);
 
 int kprobe_fault_handler(struct pt_regs *regs, int trapnr);
 int kprobe_exceptions_notify(struct notifier_block *self,
diff -druNp linux-libre-2.6.37-gnu1/arch/s390/include/asm/mutex.h linux-libre-2.6.38-gnu1/arch/s390/include/asm/mutex.h
--- linux-libre-2.6.37-gnu1/arch/s390/include/asm/mutex.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/s390/include/asm/mutex.h	2011-03-14 21:20:32.000000000 -0400
@@ -7,3 +7,5 @@
  */
 
 #include <asm-generic/mutex-dec.h>
+
+#define arch_mutex_cpu_relax()	barrier()
diff -druNp linux-libre-2.6.37-gnu1/arch/s390/include/asm/processor.h linux-libre-2.6.38-gnu1/arch/s390/include/asm/processor.h
--- linux-libre-2.6.37-gnu1/arch/s390/include/asm/processor.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/s390/include/asm/processor.h	2011-03-14 21:20:32.000000000 -0400
@@ -32,7 +32,6 @@ static inline void get_cpu_id(struct cpu
 }
 
 extern void s390_adjust_jiffies(void);
-extern void print_cpu_info(void);
 extern int get_cpu_capability(unsigned int *);
 
 /*
@@ -81,7 +80,8 @@ struct thread_struct {
 	mm_segment_t mm_segment;
         unsigned long prot_addr;        /* address of protection-excep.     */
         unsigned int trap_no;
-        per_struct per_info;
+	struct per_regs per_user;	/* User specified PER registers */
+	struct per_event per_event;	/* Cause of the last PER trap */
         /* pfault_wait is used to block the process on a pfault event */
 	unsigned long pfault_wait;
 };
@@ -148,11 +148,6 @@ extern int kernel_thread(int (*fn)(void
  */
 extern unsigned long thread_saved_pc(struct task_struct *t);
 
-/*
- * Print register of task into buffer. Used in fs/proc/array.c.
- */
-extern void task_show_regs(struct seq_file *m, struct task_struct *task);
-
 extern void show_code(struct pt_regs *regs);
 
 unsigned long get_wchan(struct task_struct *p);
diff -druNp linux-libre-2.6.37-gnu1/arch/s390/include/asm/ptrace.h linux-libre-2.6.38-gnu1/arch/s390/include/asm/ptrace.h
--- linux-libre-2.6.37-gnu1/arch/s390/include/asm/ptrace.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/s390/include/asm/ptrace.h	2011-03-14 21:20:32.000000000 -0400
@@ -331,10 +331,60 @@ struct pt_regs
 	unsigned short ilc;
 	unsigned short svcnr;
 };
+
+/*
+ * Program event recording (PER) register set.
+ */
+struct per_regs {
+	unsigned long control;		/* PER control bits */
+	unsigned long start;		/* PER starting address */
+	unsigned long end;		/* PER ending address */
+};
+
+/*
+ * PER event contains information about the cause of the last PER exception.
+ */
+struct per_event {
+	unsigned short cause;		/* PER code, ATMID and AI */
+	unsigned long address;		/* PER address */
+	unsigned char paid;		/* PER access identification */
+};
+
+/*
+ * Simplified per_info structure used to decode the ptrace user space ABI.
+ */
+struct per_struct_kernel {
+	unsigned long cr9;		/* PER control bits */
+	unsigned long cr10;		/* PER starting address */
+	unsigned long cr11;		/* PER ending address */
+	unsigned long bits;		/* Obsolete software bits */
+	unsigned long starting_addr;	/* User specified start address */
+	unsigned long ending_addr;	/* User specified end address */
+	unsigned short perc_atmid;	/* PER trap ATMID */
+	unsigned long address;		/* PER trap instruction address */
+	unsigned char access_id;	/* PER trap access identification */
+};
+
+#define PER_EVENT_MASK			0xE9000000UL
+
+#define PER_EVENT_BRANCH		0x80000000UL
+#define PER_EVENT_IFETCH		0x40000000UL
+#define PER_EVENT_STORE			0x20000000UL
+#define PER_EVENT_STORE_REAL		0x08000000UL
+#define PER_EVENT_NULLIFICATION		0x01000000UL
+
+#define PER_CONTROL_MASK		0x00a00000UL
+
+#define PER_CONTROL_BRANCH_ADDRESS	0x00800000UL
+#define PER_CONTROL_ALTERATION		0x00200000UL
+
 #endif
 
 /*
- * Now for the program event recording (trace) definitions.
+ * Now for the user space program event recording (trace) definitions.
+ * The following structures are used only for the ptrace interface, don't
+ * touch or even look at it if you don't want to modify the user-space
+ * ptrace interface. In particular stay away from it for in-kernel PER.
  */
 typedef struct
 {
diff -druNp linux-libre-2.6.37-gnu1/arch/s390/include/asm/qdio.h linux-libre-2.6.38-gnu1/arch/s390/include/asm/qdio.h
--- linux-libre-2.6.37-gnu1/arch/s390/include/asm/qdio.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/s390/include/asm/qdio.h	2011-03-14 21:20:32.000000000 -0400
@@ -361,6 +361,7 @@ struct qdio_initialize {
 	qdio_handler_t *input_handler;
 	qdio_handler_t *output_handler;
 	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;
diff -druNp linux-libre-2.6.37-gnu1/arch/s390/include/asm/qeth.h linux-libre-2.6.38-gnu1/arch/s390/include/asm/qeth.h
--- linux-libre-2.6.37-gnu1/arch/s390/include/asm/qeth.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/s390/include/asm/qeth.h	2011-03-14 21:20:32.000000000 -0400
@@ -28,39 +28,70 @@ struct qeth_arp_cache_entry {
 	__u8  reserved2[32];
 } __attribute__ ((packed));
 
+enum qeth_arp_ipaddrtype {
+	QETHARP_IP_ADDR_V4 = 1,
+	QETHARP_IP_ADDR_V6 = 2,
+};
+struct qeth_arp_entrytype {
+	__u8 mac;
+	__u8 ip;
+} __attribute__((packed));
+
+#define QETH_QARP_MEDIASPECIFIC_BYTES 32
+#define QETH_QARP_MACADDRTYPE_BYTES 1
 struct qeth_arp_qi_entry7 {
-	__u8 media_specific[32];
-	__u8 macaddr_type;
-	__u8 ipaddr_type;
+	__u8 media_specific[QETH_QARP_MEDIASPECIFIC_BYTES];
+	struct qeth_arp_entrytype type;
 	__u8 macaddr[6];
 	__u8 ipaddr[4];
 } __attribute__((packed));
 
+struct qeth_arp_qi_entry7_ipv6 {
+	__u8 media_specific[QETH_QARP_MEDIASPECIFIC_BYTES];
+	struct qeth_arp_entrytype type;
+	__u8 macaddr[6];
+	__u8 ipaddr[16];
+} __attribute__((packed));
+
 struct qeth_arp_qi_entry7_short {
-	__u8 macaddr_type;
-	__u8 ipaddr_type;
+	struct qeth_arp_entrytype type;
 	__u8 macaddr[6];
 	__u8 ipaddr[4];
 } __attribute__((packed));
 
+struct qeth_arp_qi_entry7_short_ipv6 {
+	struct qeth_arp_entrytype type;
+	__u8 macaddr[6];
+	__u8 ipaddr[16];
+} __attribute__((packed));
+
 struct qeth_arp_qi_entry5 {
-	__u8 media_specific[32];
-	__u8 macaddr_type;
-	__u8 ipaddr_type;
+	__u8 media_specific[QETH_QARP_MEDIASPECIFIC_BYTES];
+	struct qeth_arp_entrytype type;
 	__u8 ipaddr[4];
 } __attribute__((packed));
 
+struct qeth_arp_qi_entry5_ipv6 {
+	__u8 media_specific[QETH_QARP_MEDIASPECIFIC_BYTES];
+	struct qeth_arp_entrytype type;
+	__u8 ipaddr[16];
+} __attribute__((packed));
+
 struct qeth_arp_qi_entry5_short {
-	__u8 macaddr_type;
-	__u8 ipaddr_type;
+	struct qeth_arp_entrytype type;
 	__u8 ipaddr[4];
 } __attribute__((packed));
 
+struct qeth_arp_qi_entry5_short_ipv6 {
+	struct qeth_arp_entrytype type;
+	__u8 ipaddr[16];
+} __attribute__((packed));
 /*
  * can be set by user if no "media specific information" is wanted
  * -> saves a lot of space in user space buffer
  */
 #define QETH_QARP_STRIP_ENTRIES  0x8000
+#define QETH_QARP_WITH_IPV6	 0x4000
 #define QETH_QARP_REQUEST_MASK   0x00ff
 
 /* data sent to user space as result of query arp ioctl */
diff -druNp linux-libre-2.6.37-gnu1/arch/s390/include/asm/s390_ext.h linux-libre-2.6.38-gnu1/arch/s390/include/asm/s390_ext.h
--- linux-libre-2.6.37-gnu1/arch/s390/include/asm/s390_ext.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/s390/include/asm/s390_ext.h	2011-03-14 21:20:32.000000000 -0400
@@ -1,32 +1,17 @@
-#ifndef _S390_EXTINT_H
-#define _S390_EXTINT_H
-
 /*
- *  include/asm-s390/s390_ext.h
- *
- *  S390 version
- *    Copyright IBM Corp. 1999,2007
- *    Author(s): Holger Smolinski (Holger.Smolinski@de.ibm.com),
- *               Martin Schwidefsky (schwidefsky@de.ibm.com)
+ *    Copyright IBM Corp. 1999,2010
+ *    Author(s): Holger Smolinski <Holger.Smolinski@de.ibm.com>,
+ *		 Martin Schwidefsky <schwidefsky@de.ibm.com>,
  */
 
+#ifndef _S390_EXTINT_H
+#define _S390_EXTINT_H
+
 #include <linux/types.h>
 
 typedef void (*ext_int_handler_t)(unsigned int, unsigned int, unsigned long);
 
-typedef struct ext_int_info_t {
-	struct ext_int_info_t *next;
-	ext_int_handler_t handler;
-	__u16 code;
-} ext_int_info_t;
-
-extern ext_int_info_t *ext_int_hash[];
-
 int register_external_interrupt(__u16 code, ext_int_handler_t handler);
-int register_early_external_interrupt(__u16 code, ext_int_handler_t handler,
-				      ext_int_info_t *info);
 int unregister_external_interrupt(__u16 code, ext_int_handler_t handler);
-int unregister_early_external_interrupt(__u16 code, ext_int_handler_t handler,
-					ext_int_info_t *info);
 
-#endif
+#endif /* _S390_EXTINT_H */
diff -druNp linux-libre-2.6.37-gnu1/arch/s390/include/asm/smp.h linux-libre-2.6.38-gnu1/arch/s390/include/asm/smp.h
--- linux-libre-2.6.37-gnu1/arch/s390/include/asm/smp.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/s390/include/asm/smp.h	2011-03-14 21:20:32.000000000 -0400
@@ -20,7 +20,6 @@ extern void machine_power_off_smp(void);
 
 extern int __cpu_disable (void);
 extern void __cpu_die (unsigned int cpu);
-extern void cpu_die (void) __attribute__ ((noreturn));
 extern int __cpu_up (unsigned int cpu);
 
 extern struct mutex smp_cpu_state_mutex;
@@ -71,8 +70,10 @@ static inline void smp_switch_to_ipl_cpu
 
 #ifdef CONFIG_HOTPLUG_CPU
 extern int smp_rescan_cpus(void);
+extern void __noreturn cpu_die(void);
 #else
 static inline int smp_rescan_cpus(void) { return 0; }
+static inline void cpu_die(void) { }
 #endif
 
 #endif /* __ASM_SMP_H */
diff -druNp linux-libre-2.6.37-gnu1/arch/s390/include/asm/system.h linux-libre-2.6.38-gnu1/arch/s390/include/asm/system.h
--- linux-libre-2.6.37-gnu1/arch/s390/include/asm/system.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/s390/include/asm/system.h	2011-03-14 21:20:32.000000000 -0400
@@ -20,6 +20,7 @@
 struct task_struct;
 
 extern struct task_struct *__switch_to(void *, void *);
+extern void update_per_regs(struct task_struct *task);
 
 static inline void save_fp_regs(s390_fp_regs *fpregs)
 {
@@ -93,6 +94,7 @@ static inline void restore_access_regs(u
 	if (next->mm) {							\
 		restore_fp_regs(&next->thread.fp_regs);			\
 		restore_access_regs(&next->thread.acrs[0]);		\
+		update_per_regs(next);					\
 	}								\
 	prev = __switch_to(prev,next);					\
 } while (0)
@@ -101,11 +103,9 @@ extern void account_vtime(struct task_st
 extern void account_tick_vtime(struct task_struct *);
 
 #ifdef CONFIG_PFAULT
-extern void pfault_irq_init(void);
 extern int pfault_init(void);
 extern void pfault_fini(void);
 #else /* CONFIG_PFAULT */
-#define pfault_irq_init()	do { } while (0)
 #define pfault_init()		({-1;})
 #define pfault_fini()		do { } while (0)
 #endif /* CONFIG_PFAULT */
@@ -449,7 +449,7 @@ extern void (*_machine_restart)(char *co
 extern void (*_machine_halt)(void);
 extern void (*_machine_power_off)(void);
 
-#define arch_align_stack(x) (x)
+extern unsigned long arch_align_stack(unsigned long sp);
 
 static inline int tprot(unsigned long addr)
 {
diff -druNp linux-libre-2.6.37-gnu1/arch/s390/include/asm/thread_info.h linux-libre-2.6.38-gnu1/arch/s390/include/asm/thread_info.h
--- linux-libre-2.6.37-gnu1/arch/s390/include/asm/thread_info.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/s390/include/asm/thread_info.h	2011-03-14 21:20:32.000000000 -0400
@@ -74,7 +74,7 @@ struct thread_info {
 /* how to get the thread information struct from C */
 static inline struct thread_info *current_thread_info(void)
 {
-	return (struct thread_info *)(S390_lowcore.kernel_stack - THREAD_SIZE);
+	return (struct thread_info *) S390_lowcore.thread_info;
 }
 
 #define THREAD_SIZE_ORDER THREAD_ORDER
@@ -88,7 +88,7 @@ static inline struct thread_info *curren
 #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_SINGLE_STEP		6	/* deliver sigtrap on return to user */
+#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 */
 #define TIF_SYSCALL_AUDIT	9	/* syscall auditing active */
@@ -99,14 +99,15 @@ static inline struct thread_info *curren
 #define TIF_31BIT		17	/* 32bit process */
 #define TIF_MEMDIE		18	/* is terminating due to OOM killer */
 #define TIF_RESTORE_SIGMASK	19	/* restore signal mask in do_signal() */
-#define TIF_FREEZE		20	/* thread is freezing for suspend */
+#define TIF_SINGLE_STEP		20	/* This task is single stepped */
+#define TIF_FREEZE		21	/* thread is freezing for suspend */
 
 #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_SINGLE_STEP	(1<<TIF_SINGLE_STEP)
+#define _TIF_PER_TRAP		(1<<TIF_PER_TRAP)
 #define _TIF_MCCK_PENDING	(1<<TIF_MCCK_PENDING)
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
 #define _TIF_SYSCALL_AUDIT	(1<<TIF_SYSCALL_AUDIT)
@@ -114,8 +115,15 @@ static inline struct thread_info *curren
 #define _TIF_SYSCALL_TRACEPOINT	(1<<TIF_SYSCALL_TRACEPOINT)
 #define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
 #define _TIF_31BIT		(1<<TIF_31BIT)
+#define _TIF_SINGLE_STEP	(1<<TIF_FREEZE)
 #define _TIF_FREEZE		(1<<TIF_FREEZE)
 
+#ifdef CONFIG_64BIT
+#define is_32bit_task()		(test_thread_flag(TIF_31BIT))
+#else
+#define is_32bit_task()		(1)
+#endif
+
 #endif /* __KERNEL__ */
 
 #define PREEMPT_ACTIVE		0x4000000
diff -druNp linux-libre-2.6.37-gnu1/arch/s390/include/asm/timex.h linux-libre-2.6.38-gnu1/arch/s390/include/asm/timex.h
--- linux-libre-2.6.37-gnu1/arch/s390/include/asm/timex.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/s390/include/asm/timex.h	2011-03-14 21:20:32.000000000 -0400
@@ -11,6 +11,8 @@
 #ifndef _ASM_S390_TIMEX_H
 #define _ASM_S390_TIMEX_H
 
+#include <asm/lowcore.h>
+
 /* The value of the TOD clock for 1.1.1970. */
 #define TOD_UNIX_EPOCH 0x7d91048bca000000ULL
 
@@ -49,6 +51,24 @@ static inline void store_clock_comparato
 	asm volatile("stckc %0" : "=Q" (*time));
 }
 
+void clock_comparator_work(void);
+
+static inline unsigned long long local_tick_disable(void)
+{
+	unsigned long long old;
+
+	old = S390_lowcore.clock_comparator;
+	S390_lowcore.clock_comparator = -1ULL;
+	set_clock_comparator(S390_lowcore.clock_comparator);
+	return old;
+}
+
+static inline void local_tick_enable(unsigned long long comp)
+{
+	S390_lowcore.clock_comparator = comp;
+	set_clock_comparator(S390_lowcore.clock_comparator);
+}
+
 #define CLOCK_TICK_RATE	1193180 /* Underlying HZ */
 
 typedef unsigned long long cycles_t;
diff -druNp linux-libre-2.6.37-gnu1/arch/s390/include/asm/tlb.h linux-libre-2.6.38-gnu1/arch/s390/include/asm/tlb.h
--- linux-libre-2.6.37-gnu1/arch/s390/include/asm/tlb.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/s390/include/asm/tlb.h	2011-03-14 21:20:32.000000000 -0400
@@ -22,6 +22,7 @@
  */
 
 #include <linux/mm.h>
+#include <linux/pagemap.h>
 #include <linux/swap.h>
 #include <asm/processor.h>
 #include <asm/pgalloc.h>
diff -druNp linux-libre-2.6.37-gnu1/arch/s390/Kconfig linux-libre-2.6.38-gnu1/arch/s390/Kconfig
--- linux-libre-2.6.37-gnu1/arch/s390/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/s390/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -1,13 +1,8 @@
-config SCHED_MC
-	def_bool y
-	depends on SMP
-
 config MMU
 	def_bool y
 
 config ZONE_DMA
-	def_bool y
-	depends on 64BIT
+	def_bool y if 64BIT
 
 config LOCKDEP_SUPPORT
 	def_bool y
@@ -25,12 +20,10 @@ config RWSEM_XCHGADD_ALGORITHM
 	def_bool y
 
 config ARCH_HAS_ILOG2_U32
-	bool
-	default n
+	def_bool n
 
 config ARCH_HAS_ILOG2_U64
-	bool
-	default n
+	def_bool n
 
 config GENERIC_HWEIGHT
 	def_bool y
@@ -42,9 +35,7 @@ config GENERIC_CLOCKEVENTS
 	def_bool y
 
 config GENERIC_BUG
-	bool
-	depends on BUG
-	default y
+	def_bool y if BUG
 
 config GENERIC_BUG_RELATIVE_POINTERS
 	def_bool y
@@ -59,13 +50,10 @@ config ARCH_DMA_ADDR_T_64BIT
 	def_bool 64BIT
 
 config GENERIC_LOCKBREAK
-	bool
-	default y
-	depends on SMP && PREEMPT
+	def_bool y if SMP && PREEMPT
 
 config PGSTE
-	bool
-	default y if KVM
+	def_bool y if KVM
 
 config VIRT_CPU_ACCOUNTING
 	def_bool y
@@ -85,7 +73,6 @@ config S390
 	select HAVE_DYNAMIC_FTRACE
 	select HAVE_FUNCTION_GRAPH_TRACER
 	select HAVE_REGS_AND_STACK_ACCESS_API
-	select HAVE_DEFAULT_NO_SPIN_MUTEXES
 	select HAVE_OPROFILE
 	select HAVE_KPROBES
 	select HAVE_KRETPROBES
@@ -99,6 +86,7 @@ config S390
 	select HAVE_KERNEL_LZMA
 	select HAVE_KERNEL_LZO
 	select HAVE_GET_USER_PAGES_FAST
+	select HAVE_ARCH_MUTEX_CPU_RELAX
 	select ARCH_INLINE_SPIN_TRYLOCK
 	select ARCH_INLINE_SPIN_TRYLOCK_BH
 	select ARCH_INLINE_SPIN_LOCK
@@ -129,8 +117,7 @@ config S390
 	select ARCH_INLINE_WRITE_UNLOCK_IRQRESTORE
 
 config SCHED_OMIT_FRAME_POINTER
-	bool
-	default y
+	def_bool y
 
 source "init/Kconfig"
 
@@ -143,20 +130,21 @@ comment "Processor type and features"
 source "kernel/time/Kconfig"
 
 config 64BIT
-	bool "64 bit kernel"
+	def_bool y
+	prompt "64 bit kernel"
 	help
 	  Select this option if you have an IBM z/Architecture machine
 	  and want to use the 64 bit addressing mode.
 
 config 32BIT
-	bool
-	default y if !64BIT
+	def_bool y if !64BIT
 
 config KTIME_SCALAR
 	def_bool 32BIT
 
 config SMP
-	bool "Symmetric multi-processing support"
+	def_bool y
+	prompt "Symmetric multi-processing support"
 	---help---
 	  This enables support for systems with more than one CPU. If you have
 	  a system with only one CPU, like most personal computers, say N. If
@@ -188,10 +176,10 @@ config NR_CPUS
 	  approximately sixteen kilobytes to the kernel image.
 
 config HOTPLUG_CPU
-	bool "Support for hot-pluggable CPUs"
+	def_bool y
+	prompt "Support for hot-pluggable CPUs"
 	depends on SMP
 	select HOTPLUG
-	default n
 	help
 	  Say Y here to be able to turn CPUs off and on. CPUs
 	  can be controlled through /sys/devices/system/cpu/cpu#.
@@ -207,14 +195,16 @@ config SCHED_MC
 	  increased overhead in some places.
 
 config SCHED_BOOK
-	bool "Book scheduler support"
+	def_bool y
+	prompt "Book scheduler support"
 	depends on SMP && SCHED_MC
 	help
 	  Book scheduler support improves the CPU scheduler's decision making
 	  when dealing with machines that have several books.
 
 config MATHEMU
-	bool "IEEE FPU emulation"
+	def_bool y
+	prompt "IEEE FPU emulation"
 	depends on MARCH_G5
 	help
 	  This option is required for IEEE compliant floating point arithmetic
@@ -222,7 +212,8 @@ config MATHEMU
 	  need this.
 
 config COMPAT
-	bool "Kernel support for 31 bit emulation"
+	def_bool y
+	prompt "Kernel support for 31 bit emulation"
 	depends on 64BIT
 	select COMPAT_BINFMT_ELF
 	help
@@ -232,16 +223,14 @@ config COMPAT
 	  executing 31 bit applications.  It is safe to say "Y".
 
 config SYSVIPC_COMPAT
-	bool
-	depends on COMPAT && SYSVIPC
-	default y
+	def_bool y if COMPAT && SYSVIPC
 
 config AUDIT_ARCH
-	bool
-	default y
+	def_bool y
 
 config S390_EXEC_PROTECT
-	bool "Data execute protection"
+	def_bool y
+	prompt "Data execute protection"
 	help
 	  This option allows to enable a buffer overflow protection for user
 	  space programs and it also selects the addressing mode option above.
@@ -301,7 +290,8 @@ config MARCH_Z196
 endchoice
 
 config PACK_STACK
-	bool "Pack kernel stack"
+	def_bool y
+	prompt "Pack kernel stack"
 	help
 	  This option enables the compiler option -mkernel-backchain if it
 	  is available. If the option is available the compiler supports
@@ -314,7 +304,8 @@ config PACK_STACK
 	  Say Y if you are unsure.
 
 config SMALL_STACK
-	bool "Use 8kb for kernel stack instead of 16kb"
+	def_bool n
+	prompt "Use 8kb for kernel stack instead of 16kb"
 	depends on PACK_STACK && 64BIT && !LOCKDEP
 	help
 	  If you say Y here and the compiler supports the -mkernel-backchain
@@ -326,7 +317,8 @@ config SMALL_STACK
 	  Say N if you are unsure.
 
 config CHECK_STACK
-	bool "Detect kernel stack overflow"
+	def_bool y
+	prompt "Detect kernel stack overflow"
 	help
 	  This option enables the compiler option -mstack-guard and
 	  -mstack-size if they are available. If the compiler supports them
@@ -350,7 +342,8 @@ config STACK_GUARD
 	  512 for 64 bit.
 
 config WARN_STACK
-	bool "Emit compiler warnings for function with broken stack usage"
+	def_bool n
+	prompt "Emit compiler warnings for function with broken stack usage"
 	help
 	  This option enables the compiler options -mwarn-framesize and
 	  -mwarn-dynamicstack. If the compiler supports these options it
@@ -385,24 +378,24 @@ config ARCH_SPARSEMEM_DEFAULT
 	def_bool y
 
 config ARCH_SELECT_MEMORY_MODEL
-       def_bool y
+	def_bool y
 
 config ARCH_ENABLE_MEMORY_HOTPLUG
-	def_bool y
-	depends on SPARSEMEM
+	def_bool y if SPARSEMEM
 
 config ARCH_ENABLE_MEMORY_HOTREMOVE
 	def_bool y
 
 config ARCH_HIBERNATION_POSSIBLE
-       def_bool y if 64BIT
+	def_bool y if 64BIT
 
 source "mm/Kconfig"
 
 comment "I/O subsystem configuration"
 
 config QDIO
-	tristate "QDIO support"
+	def_tristate y
+	prompt "QDIO support"
 	---help---
 	  This driver provides the Queued Direct I/O base support for
 	  IBM System z.
@@ -413,7 +406,8 @@ config QDIO
 	  If unsure, say Y.
 
 config CHSC_SCH
-	tristate "Support for CHSC subchannels"
+	def_tristate m
+	prompt "Support for CHSC subchannels"
 	help
 	  This driver allows usage of CHSC subchannels. A CHSC subchannel
 	  is usually present on LPAR only.
@@ -431,7 +425,8 @@ config CHSC_SCH
 comment "Misc"
 
 config IPL
-	bool "Builtin IPL record support"
+	def_bool y
+	prompt "Builtin IPL record support"
 	help
 	  If you want to use the produced kernel to IPL directly from a
 	  device, you have to merge a bootsector specific to the device
@@ -463,7 +458,8 @@ config FORCE_MAX_ZONEORDER
 	default "9"
 
 config PFAULT
-	bool "Pseudo page fault support"
+	def_bool y
+	prompt "Pseudo page fault support"
 	help
 	  Select this option, if you want to use PFAULT pseudo page fault
 	  handling under VM. If running native or in LPAR, this option
@@ -475,7 +471,8 @@ config PFAULT
 	  this option.
 
 config SHARED_KERNEL
-	bool "VM shared kernel support"
+	def_bool y
+	prompt "VM shared kernel support"
 	help
 	  Select this option, if you want to share the text segment of the
 	  Linux kernel between different VM guests. This reduces memory
@@ -486,7 +483,8 @@ config SHARED_KERNEL
 	  doing and want to exploit this feature.
 
 config CMM
-	tristate "Cooperative memory management"
+	def_tristate n
+	prompt "Cooperative memory management"
 	help
 	  Select this option, if you want to enable the kernel interface
 	  to reduce the memory size of the system. This is accomplished
@@ -498,14 +496,16 @@ config CMM
 	  option.
 
 config CMM_IUCV
-	bool "IUCV special message interface to cooperative memory management"
+	def_bool y
+	prompt "IUCV special message interface to cooperative memory management"
 	depends on CMM && (SMSGIUCV=y || CMM=SMSGIUCV)
 	help
 	  Select this option to enable the special message interface to
 	  the cooperative memory management.
 
 config APPLDATA_BASE
-	bool "Linux - VM Monitor Stream, base infrastructure"
+	def_bool n
+	prompt "Linux - VM Monitor Stream, base infrastructure"
 	depends on PROC_FS
 	help
 	  This provides a kernel interface for creating and updating z/VM APPLDATA
@@ -520,7 +520,8 @@ config APPLDATA_BASE
 	  The /proc entries can also be read from, showing the current settings.
 
 config APPLDATA_MEM
-	tristate "Monitor memory management statistics"
+	def_tristate m
+	prompt "Monitor memory management statistics"
 	depends on APPLDATA_BASE && VM_EVENT_COUNTERS
 	help
 	  This provides memory management related data to the Linux - VM Monitor
@@ -536,7 +537,8 @@ config APPLDATA_MEM
 	  appldata_mem.o.
 
 config APPLDATA_OS
-	tristate "Monitor OS statistics"
+	def_tristate m
+	prompt "Monitor OS statistics"
 	depends on APPLDATA_BASE
 	help
 	  This provides OS related data to the Linux - VM Monitor Stream, like
@@ -550,7 +552,8 @@ config APPLDATA_OS
 	  appldata_os.o.
 
 config APPLDATA_NET_SUM
-	tristate "Monitor overall network statistics"
+	def_tristate m
+	prompt "Monitor overall network statistics"
 	depends on APPLDATA_BASE && NET
 	help
 	  This provides network related data to the Linux - VM Monitor Stream,
@@ -567,30 +570,32 @@ config APPLDATA_NET_SUM
 source kernel/Kconfig.hz
 
 config S390_HYPFS_FS
-	bool "s390 hypervisor file system support"
+	def_bool y
+	prompt "s390 hypervisor file system support"
 	select SYS_HYPERVISOR
-	default y
 	help
 	  This is a virtual file system intended to provide accounting
 	  information in an s390 hypervisor environment.
 
 config KEXEC
-	bool "kexec system call"
+	def_bool n
+	prompt "kexec system call"
 	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
 	  but is independent of hardware/microcode support.
 
 config ZFCPDUMP
-	bool "zfcpdump support"
+	def_bool n
+	prompt "zfcpdump support"
 	select SMP
-	default n
 	help
 	  Select this option if you want to build an zfcpdump enabled kernel.
 	  Refer to <file:Documentation/s390/zfcpdump.txt> for more details on this.
 
 config S390_GUEST
-bool "s390 guest support for KVM (EXPERIMENTAL)"
+	def_bool y
+	prompt "s390 guest support for KVM (EXPERIMENTAL)"
 	depends on 64BIT && EXPERIMENTAL
 	select VIRTIO
 	select VIRTIO_RING
@@ -602,9 +607,9 @@ bool "s390 guest support for KVM (EXPERI
 	  the default console.
 
 config SECCOMP
-	bool "Enable seccomp to safely compute untrusted bytecode"
+	def_bool y
+	prompt "Enable seccomp to safely compute untrusted bytecode"
 	depends on PROC_FS
-	default y
 	help
 	  This kernel feature is useful for number crunching applications
 	  that may need to compute untrusted bytecode during their
diff -druNp linux-libre-2.6.37-gnu1/arch/s390/Kconfig.debug linux-libre-2.6.38-gnu1/arch/s390/Kconfig.debug
--- linux-libre-2.6.37-gnu1/arch/s390/Kconfig.debug	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/s390/Kconfig.debug	2011-03-14 21:20:32.000000000 -0400
@@ -1,8 +1,7 @@
 menu "Kernel hacking"
 
 config TRACE_IRQFLAGS_SUPPORT
-	bool
-	default y
+	def_bool y
 
 source "lib/Kconfig.debug"
 
@@ -19,7 +18,8 @@ config STRICT_DEVMEM
 	  If you are unsure, say Y.
 
 config DEBUG_STRICT_USER_COPY_CHECKS
-	bool "Strict user copy size checks"
+	def_bool n
+	prompt "Strict user copy size checks"
 	---help---
 	  Enabling this option turns a certain set of sanity checks for user
 	  copy operations into compile time warnings.
diff -druNp linux-libre-2.6.37-gnu1/arch/s390/kernel/asm-offsets.c linux-libre-2.6.38-gnu1/arch/s390/kernel/asm-offsets.c
--- linux-libre-2.6.37-gnu1/arch/s390/kernel/asm-offsets.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/s390/kernel/asm-offsets.c	2011-03-14 21:20:32.000000000 -0400
@@ -23,14 +23,16 @@ int main(void)
 {
 	DEFINE(__THREAD_info, offsetof(struct task_struct, stack));
 	DEFINE(__THREAD_ksp, offsetof(struct task_struct, thread.ksp));
-	DEFINE(__THREAD_per, offsetof(struct task_struct, thread.per_info));
 	DEFINE(__THREAD_mm_segment, offsetof(struct task_struct, thread.mm_segment));
 	BLANK();
 	DEFINE(__TASK_pid, offsetof(struct task_struct, pid));
 	BLANK();
-	DEFINE(__PER_atmid, offsetof(per_struct, lowcore.words.perc_atmid));
-	DEFINE(__PER_address, offsetof(per_struct, lowcore.words.address));
-	DEFINE(__PER_access_id, offsetof(per_struct, lowcore.words.access_id));
+	DEFINE(__THREAD_per_cause,
+	       offsetof(struct task_struct, thread.per_event.cause));
+	DEFINE(__THREAD_per_address,
+	       offsetof(struct task_struct, thread.per_event.address));
+	DEFINE(__THREAD_per_paid,
+	       offsetof(struct task_struct, thread.per_event.paid));
 	BLANK();
 	DEFINE(__TI_task, offsetof(struct thread_info, task));
 	DEFINE(__TI_domain, offsetof(struct thread_info, exec_domain));
@@ -85,9 +87,9 @@ int main(void)
 	DEFINE(__LC_PGM_ILC, offsetof(struct _lowcore, pgm_ilc));
 	DEFINE(__LC_PGM_INT_CODE, offsetof(struct _lowcore, pgm_code));
 	DEFINE(__LC_TRANS_EXC_CODE, offsetof(struct _lowcore, trans_exc_code));
-	DEFINE(__LC_PER_ATMID, offsetof(struct _lowcore, per_perc_atmid));
+	DEFINE(__LC_PER_CAUSE, offsetof(struct _lowcore, per_perc_atmid));
 	DEFINE(__LC_PER_ADDRESS, offsetof(struct _lowcore, per_address));
-	DEFINE(__LC_PER_ACCESS_ID, offsetof(struct _lowcore, per_access_id));
+	DEFINE(__LC_PER_PAID, offsetof(struct _lowcore, per_access_id));
 	DEFINE(__LC_AR_MODE_ID, offsetof(struct _lowcore, ar_access_id));
 	DEFINE(__LC_SUBCHANNEL_ID, offsetof(struct _lowcore, subchannel_id));
 	DEFINE(__LC_SUBCHANNEL_NR, offsetof(struct _lowcore, subchannel_nr));
diff -druNp linux-libre-2.6.37-gnu1/arch/s390/kernel/compat_ptrace.h linux-libre-2.6.38-gnu1/arch/s390/kernel/compat_ptrace.h
--- linux-libre-2.6.37-gnu1/arch/s390/kernel/compat_ptrace.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/s390/kernel/compat_ptrace.h	2011-03-14 21:20:32.000000000 -0400
@@ -4,40 +4,19 @@
 #include <asm/ptrace.h>    /* needed for NUM_CR_WORDS */
 #include "compat_linux.h"  /* needed for psw_compat_t */
 
-typedef struct {
-	__u32 cr[NUM_CR_WORDS];
-} per_cr_words32;
-
-typedef struct {
-	__u16          perc_atmid;          /* 0x096 */
-	__u32          address;             /* 0x098 */
-	__u8           access_id;           /* 0x0a1 */
-} per_lowcore_words32;
-
-typedef struct {
-	union {
-		per_cr_words32   words;
-	} control_regs;
-	/*
-	 * Use these flags instead of setting em_instruction_fetch
-	 * directly they are used so that single stepping can be
-	 * switched on & off while not affecting other tracing
-	 */
-	unsigned  single_step       : 1;
-	unsigned  instruction_fetch : 1;
-	unsigned                    : 30;
-	/*
-	 * These addresses are copied into cr10 & cr11 if single
-	 * stepping is switched off
-	 */
-	__u32     starting_addr;
-	__u32     ending_addr;
-	union {
-		per_lowcore_words32 words;
-	} lowcore; 
-} per_struct32;
+struct compat_per_struct_kernel {
+	__u32 cr9;		/* PER control bits */
+	__u32 cr10;		/* PER starting address */
+	__u32 cr11;		/* PER ending address */
+	__u32 bits;		/* Obsolete software bits */
+	__u32 starting_addr;	/* User specified start address */
+	__u32 ending_addr;	/* User specified end address */
+	__u16 perc_atmid;	/* PER trap ATMID */
+	__u32 address;		/* PER trap instruction address */
+	__u8  access_id;	/* PER trap access identification */
+};
 
-struct user_regs_struct32
+struct compat_user_regs_struct
 {
 	psw_compat_t psw;
 	u32 gprs[NUM_GPRS];
@@ -50,14 +29,14 @@ struct user_regs_struct32
 	 * itself as there is no "official" ptrace interface for hardware
 	 * watchpoints. This is the way intel does it.
 	 */
-	per_struct32 per_info;
+	struct compat_per_struct_kernel per_info;
 	u32  ieee_instruction_pointer;	/* obsolete, always 0 */
 };
 
-struct user32 {
+struct compat_user {
 	/* We start with the registers, to mimic the way that "memory"
 	   is returned from the ptrace(3,...) function.  */
-	struct user_regs_struct32 regs; /* Where the registers are actually stored */
+	struct compat_user_regs_struct regs;
 	/* The rest of this junk is to help gdb figure out what goes where */
 	u32 u_tsize;		/* Text segment size (pages). */
 	u32 u_dsize;	        /* Data segment size (pages). */
@@ -79,6 +58,6 @@ typedef struct
 	__u32   len;
 	__u32   kernel_addr;
 	__u32   process_addr;
-} ptrace_area_emu31;
+} compat_ptrace_area;
 
 #endif /* _PTRACE32_H */
diff -druNp linux-libre-2.6.37-gnu1/arch/s390/kernel/entry64.S linux-libre-2.6.38-gnu1/arch/s390/kernel/entry64.S
--- linux-libre-2.6.37-gnu1/arch/s390/kernel/entry64.S	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/s390/kernel/entry64.S	2011-03-14 21:20:32.000000000 -0400
@@ -51,7 +51,7 @@ 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_SINGLE_STEP )
+		 _TIF_MCCK_PENDING | _TIF_RESTART_SVC | _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 | \
@@ -197,6 +197,8 @@ _TIF_SYSCALL = (_TIF_SYSCALL_TRACE>>8 |
 	ssm	__SF_EMPTY(%r15)
 	.endm
 
+	.section .kprobes.text, "ax"
+
 /*
  * Scheduler resume function, called by switch_to
  *  gpr2 = (task_struct *) prev
@@ -206,30 +208,21 @@ _TIF_SYSCALL = (_TIF_SYSCALL_TRACE>>8 |
  */
 	.globl	__switch_to
 __switch_to:
-	tm	__THREAD_per+4(%r3),0xe8 # is the new process using per ?
-	jz	__switch_to_noper		# if not we're fine
-	stctg	%c9,%c11,__SF_EMPTY(%r15)# We are using per stuff
-	clc	__THREAD_per(24,%r3),__SF_EMPTY(%r15)
-	je	__switch_to_noper	     # we got away without bashing TLB's
-	lctlg	%c9,%c11,__THREAD_per(%r3)	# Nope we didn't
-__switch_to_noper:
-	lg	%r4,__THREAD_info(%r2)		    # get thread_info of prev
+	lg	%r4,__THREAD_info(%r2)		# get thread_info of prev
+	lg	%r5,__THREAD_info(%r3)		# get thread_info of next
 	tm	__TI_flags+7(%r4),_TIF_MCCK_PENDING # machine check pending?
-	jz	__switch_to_no_mcck
-	ni	__TI_flags+7(%r4),255-_TIF_MCCK_PENDING # clear flag in prev
-	lg	%r4,__THREAD_info(%r3)		    # get thread_info of next
-	oi	__TI_flags+7(%r4),_TIF_MCCK_PENDING # set it in next
-__switch_to_no_mcck:
-	stmg	%r6,%r15,__SF_GPRS(%r15)# store __switch_to registers of prev task
-	stg	%r15,__THREAD_ksp(%r2)	# store kernel stack to prev->tss.ksp
-	lg	%r15,__THREAD_ksp(%r3)	# load kernel stack from next->tss.ksp
-	lmg	%r6,%r15,__SF_GPRS(%r15)# load __switch_to registers of next task
-	stg	%r3,__LC_CURRENT	# __LC_CURRENT = current task struct
-	lctl	%c4,%c4,__TASK_pid(%r3) # load pid to control reg. 4
-	lg	%r3,__THREAD_info(%r3)	# load thread_info from task struct
-	stg	%r3,__LC_THREAD_INFO
-	aghi	%r3,STACK_SIZE
-	stg	%r3,__LC_KERNEL_STACK	# __LC_KERNEL_STACK = new kernel stack
+	jz	0f
+	ni	__TI_flags+7(%r4),255-_TIF_MCCK_PENDING	# clear flag in prev
+	oi	__TI_flags+7(%r5),_TIF_MCCK_PENDING	# set it in next
+0:	stmg	%r6,%r15,__SF_GPRS(%r15)	# store gprs of prev task
+	stg	%r15,__THREAD_ksp(%r2)		# store kernel stack of prev
+	lg	%r15,__THREAD_ksp(%r3)		# load kernel stack of next
+	lctl	%c4,%c4,__TASK_pid(%r3)		# load pid to control reg. 4
+	lmg	%r6,%r15,__SF_GPRS(%r15)	# load gprs of next task
+	stg	%r3,__LC_CURRENT		# store task struct of next
+	stg	%r5,__LC_THREAD_INFO		# store thread info of next
+	aghi	%r5,STACK_SIZE			# end of kernel stack of next
+	stg	%r5,__LC_KERNEL_STACK		# store end of kernel stack
 	br	%r14
 
 __critical_start:
@@ -309,7 +302,7 @@ sysc_work_tif:
 	jo	sysc_notify_resume
 	tm	__TI_flags+7(%r12),_TIF_RESTART_SVC
 	jo	sysc_restart
-	tm	__TI_flags+7(%r12),_TIF_SINGLE_STEP
+	tm	__TI_flags+7(%r12),_TIF_PER_TRAP
 	jo	sysc_singlestep
 	j	sysc_return		# beware of critical section cleanup
 
@@ -331,12 +324,12 @@ sysc_mcck_pending:
 # _TIF_SIGPENDING is set, call do_signal
 #
 sysc_sigpending:
-	ni	__TI_flags+7(%r12),255-_TIF_SINGLE_STEP # clear TIF_SINGLE_STEP
+	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_SINGLE_STEP
+	tm	__TI_flags+7(%r12),_TIF_PER_TRAP
 	jo	sysc_singlestep
 	j	sysc_return
 
@@ -361,14 +354,14 @@ sysc_restart:
 	j	sysc_nr_ok		# restart svc
 
 #
-# _TIF_SINGLE_STEP is set, call do_single_step
+# _TIF_PER_TRAP is set, call do_per_trap
 #
 sysc_singlestep:
-	ni	__TI_flags+7(%r12),255-_TIF_SINGLE_STEP	# clear TIF_SINGLE_STEP
+	ni	__TI_flags+7(%r12),255-_TIF_PER_TRAP	# clear TIF_PER_TRAP
 	xc	SP_SVCNR(2,%r15),SP_SVCNR(%r15)		# clear svc number
 	la	%r2,SP_PTREGS(%r15)	# address of register-save area
 	larl	%r14,sysc_return	# load adr. of system return
-	jg	do_single_step		# branch to do_sigtrap
+	jg	do_per_trap
 
 #
 # call tracehook_report_syscall_entry/tracehook_report_syscall_exit before
@@ -524,10 +517,10 @@ pgm_no_vtime2:
 	lg	%r1,__TI_task(%r12)
 	tm	SP_PSW+1(%r15),0x01	# kernel per event ?
 	jz	kernel_per
-	mvc	__THREAD_per+__PER_atmid(2,%r1),__LC_PER_ATMID
-	mvc	__THREAD_per+__PER_address(8,%r1),__LC_PER_ADDRESS
-	mvc	__THREAD_per+__PER_access_id(1,%r1),__LC_PER_ACCESS_ID
-	oi	__TI_flags+7(%r12),_TIF_SINGLE_STEP # set TIF_SINGLE_STEP
+	mvc	__THREAD_per_cause(2,%r1),__LC_PER_CAUSE
+	mvc	__THREAD_per_address(8,%r1),__LC_PER_ADDRESS
+	mvc	__THREAD_per_paid(1,%r1),__LC_PER_PAID
+	oi	__TI_flags+7(%r12),_TIF_PER_TRAP # set TIF_PER_TRAP
 	lgf	%r3,__LC_PGM_ILC	# load program interruption code
 	lg	%r4,__LC_TRANS_EXC_CODE
 	REENABLE_IRQS
@@ -556,10 +549,10 @@ pgm_svcper:
 	mvc	__LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
 	LAST_BREAK
 	lg	%r8,__TI_task(%r12)
-	mvc	__THREAD_per+__PER_atmid(2,%r8),__LC_PER_ATMID
-	mvc	__THREAD_per+__PER_address(8,%r8),__LC_PER_ADDRESS
-	mvc	__THREAD_per+__PER_access_id(1,%r8),__LC_PER_ACCESS_ID
-	oi	__TI_flags+7(%r12),_TIF_SINGLE_STEP # set TIF_SINGLE_STEP
+	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 +564,7 @@ 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_single_step
+	brasl	%r14,do_per_trap
 	j	pgm_exit
 
 /*
@@ -868,6 +861,8 @@ restart_crash:
 restart_go:
 #endif
 
+	.section .kprobes.text, "ax"
+
 #ifdef CONFIG_CHECK_STACK
 /*
  * The synchronous or the asynchronous stack overflowed. We are dead.
diff -druNp linux-libre-2.6.37-gnu1/arch/s390/kernel/entry.h linux-libre-2.6.38-gnu1/arch/s390/kernel/entry.h
--- linux-libre-2.6.37-gnu1/arch/s390/kernel/entry.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/s390/kernel/entry.h	2011-03-14 21:20:32.000000000 -0400
@@ -12,7 +12,7 @@ pgm_check_handler_t do_dat_exception;
 
 extern int sysctl_userprocess_debug;
 
-void do_single_step(struct pt_regs *regs);
+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);
diff -druNp linux-libre-2.6.37-gnu1/arch/s390/kernel/entry.S linux-libre-2.6.38-gnu1/arch/s390/kernel/entry.S
--- linux-libre-2.6.37-gnu1/arch/s390/kernel/entry.S	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/s390/kernel/entry.S	2011-03-14 21:20:32.000000000 -0400
@@ -9,7 +9,6 @@
  *		 Heiko Carstens <heiko.carstens@de.ibm.com>
  */
 
-#include <linux/sys.h>
 #include <linux/linkage.h>
 #include <linux/init.h>
 #include <asm/cache.h>
@@ -49,7 +48,7 @@ SP_SVCNR     =	STACK_FRAME_OVERHEAD + __
 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_SINGLE_STEP )
+		 _TIF_MCCK_PENDING | _TIF_RESTART_SVC | _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 | \
@@ -110,31 +109,36 @@ STACK_SIZE  = 1 << STACK_SHIFT
 1:	stm	%r10,%r11,\lc_sum
 	.endm
 
-	.macro	SAVE_ALL_BASE savearea
+	.macro	SAVE_ALL_SVC psworg,savearea
 	stm	%r12,%r15,\savearea
 	l	%r13,__LC_SVC_NEW_PSW+4	# load &system_call to %r13
+	l	%r15,__LC_KERNEL_STACK	# problem state -> load ksp
+	s	%r15,BASED(.Lc_spsize)	# make room for registers & psw
 	.endm
 
-	.macro	SAVE_ALL_SVC psworg,savearea
-	la	%r12,\psworg
-	l	%r15,__LC_KERNEL_STACK	# problem state -> load ksp
+	.macro	SAVE_ALL_BASE savearea
+	stm	%r12,%r15,\savearea
+	l	%r13,__LC_SVC_NEW_PSW+4	# load &system_call to %r13
 	.endm
 
-	.macro	SAVE_ALL_SYNC psworg,savearea
-	la	%r12,\psworg
+	.macro	SAVE_ALL_PGM psworg,savearea
 	tm	\psworg+1,0x01		# test problem state bit
-	bz	BASED(2f)		# skip stack setup save
-	l	%r15,__LC_KERNEL_STACK	# problem state -> load ksp
 #ifdef CONFIG_CHECK_STACK
-	b	BASED(3f)
-2:	tml	%r15,STACK_SIZE - CONFIG_STACK_GUARD
-	bz	BASED(stack_overflow)
-3:
+	bnz	BASED(1f)
+	tml	%r15,STACK_SIZE - CONFIG_STACK_GUARD
+	bnz	BASED(2f)
+	la	%r12,\psworg
+	b	BASED(stack_overflow)
+#else
+	bz	BASED(2f)
 #endif
-2:
+1:	l	%r15,__LC_KERNEL_STACK	# problem state -> load ksp
+2:	s	%r15,BASED(.Lc_spsize)	# make room for registers & psw
 	.endm
 
 	.macro	SAVE_ALL_ASYNC psworg,savearea
+	stm	%r12,%r15,\savearea
+	l	%r13,__LC_SVC_NEW_PSW+4	# load &system_call to %r13
 	la	%r12,\psworg
 	tm	\psworg+1,0x01		# test problem state bit
 	bnz	BASED(1f)		# from user -> load async stack
@@ -149,27 +153,23 @@ STACK_SIZE  = 1 << STACK_SHIFT
 0:	l	%r14,__LC_ASYNC_STACK	# are we already on the async stack ?
 	slr	%r14,%r15
 	sra	%r14,STACK_SHIFT
-	be	BASED(2f)
-1:	l	%r15,__LC_ASYNC_STACK
 #ifdef CONFIG_CHECK_STACK
-	b	BASED(3f)
-2:	tml	%r15,STACK_SIZE - CONFIG_STACK_GUARD
-	bz	BASED(stack_overflow)
-3:
+	bnz	BASED(1f)
+	tml	%r15,STACK_SIZE - CONFIG_STACK_GUARD
+	bnz	BASED(2f)
+	b	BASED(stack_overflow)
+#else
+	bz	BASED(2f)
 #endif
-2:
+1:	l	%r15,__LC_ASYNC_STACK
+2:	s	%r15,BASED(.Lc_spsize)	# make room for registers & psw
 	.endm
 
-	.macro	CREATE_STACK_FRAME psworg,savearea
-	s	%r15,BASED(.Lc_spsize)	# make room for registers & psw
-	mvc	SP_PSW(8,%r15),0(%r12)	# move user PSW to stack
+	.macro	CREATE_STACK_FRAME savearea
+	xc	__SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15)
 	st	%r2,SP_ORIG_R2(%r15)	# store original content of gpr 2
-	icm	%r12,12,__LC_SVC_ILC
-	stm	%r0,%r11,SP_R0(%r15)	# store gprs %r0-%r11 to kernel stack
-	st	%r12,SP_ILC(%r15)
 	mvc	SP_R12(16,%r15),\savearea # move %r12-%r15 to stack
-	la	%r12,0
-	st	%r12,__SF_BACKCHAIN(%r15)	# clear back chain
+	stm	%r0,%r11,SP_R0(%r15)	# store gprs %r0-%r11 to kernel stack
 	.endm
 
 	.macro	RESTORE_ALL psworg,sync
@@ -188,6 +188,8 @@ STACK_SIZE  = 1 << STACK_SHIFT
 	ssm	__SF_EMPTY(%r15)
 	.endm
 
+	.section .kprobes.text, "ax"
+
 /*
  * Scheduler resume function, called by switch_to
  *  gpr2 = (task_struct *) prev
@@ -198,31 +200,21 @@ STACK_SIZE  = 1 << STACK_SHIFT
 	.globl	__switch_to
 __switch_to:
 	basr	%r1,0
-__switch_to_base:
-	tm	__THREAD_per(%r3),0xe8		# new process is using per ?
-	bz	__switch_to_noper-__switch_to_base(%r1)	# if not we're fine
-	stctl	%c9,%c11,__SF_EMPTY(%r15)	# We are using per stuff
-	clc	__THREAD_per(12,%r3),__SF_EMPTY(%r15)
-	be	__switch_to_noper-__switch_to_base(%r1)	# we got away w/o bashing TLB's
-	lctl	%c9,%c11,__THREAD_per(%r3)	# Nope we didn't
-__switch_to_noper:
-	l	%r4,__THREAD_info(%r2)		# get thread_info of prev
+0:	l	%r4,__THREAD_info(%r2)		# get thread_info of prev
+	l	%r5,__THREAD_info(%r3)		# get thread_info of next
 	tm	__TI_flags+3(%r4),_TIF_MCCK_PENDING # machine check pending?
-	bz	__switch_to_no_mcck-__switch_to_base(%r1)
-	ni	__TI_flags+3(%r4),255-_TIF_MCCK_PENDING # clear flag in prev
-	l	%r4,__THREAD_info(%r3)		# get thread_info of next
-	oi	__TI_flags+3(%r4),_TIF_MCCK_PENDING # set it in next
-__switch_to_no_mcck:
-	stm	%r6,%r15,__SF_GPRS(%r15)# store __switch_to registers of prev task
-	st	%r15,__THREAD_ksp(%r2)	# store kernel stack to prev->tss.ksp
-	l	%r15,__THREAD_ksp(%r3)	# load kernel stack from next->tss.ksp
-	lm	%r6,%r15,__SF_GPRS(%r15)# load __switch_to registers of next task
-	st	%r3,__LC_CURRENT	# __LC_CURRENT = current task struct
-	lctl	%c4,%c4,__TASK_pid(%r3) # load pid to control reg. 4
-	l	%r3,__THREAD_info(%r3)	# load thread_info from task struct
-	st	%r3,__LC_THREAD_INFO
-	ahi	%r3,STACK_SIZE
-	st	%r3,__LC_KERNEL_STACK	# __LC_KERNEL_STACK = new kernel stack
+	bz	1f-0b(%r1)
+	ni	__TI_flags+3(%r4),255-_TIF_MCCK_PENDING	# clear flag in prev
+	oi	__TI_flags+3(%r5),_TIF_MCCK_PENDING	# set it in next
+1:	stm	%r6,%r15,__SF_GPRS(%r15)	# store gprs of prev task
+	st	%r15,__THREAD_ksp(%r2)		# store kernel stack of prev
+	l	%r15,__THREAD_ksp(%r3)		# load kernel stack of next
+	lctl	%c4,%c4,__TASK_pid(%r3)		# load pid to control reg. 4
+	lm	%r6,%r15,__SF_GPRS(%r15)	# load gprs of next task
+	st	%r3,__LC_CURRENT		# store task struct of next
+	st	%r5,__LC_THREAD_INFO		# store thread info of next
+	ahi	%r5,STACK_SIZE			# end of kernel stack of next
+	st	%r5,__LC_KERNEL_STACK		# store end of kernel stack
 	br	%r14
 
 __critical_start:
@@ -235,10 +227,11 @@ __critical_start:
 system_call:
 	stpt	__LC_SYNC_ENTER_TIMER
 sysc_saveall:
-	SAVE_ALL_BASE __LC_SAVE_AREA
 	SAVE_ALL_SVC __LC_SVC_OLD_PSW,__LC_SAVE_AREA
-	CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA
-	lh	%r7,0x8a	  # get svc number from lowcore
+	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
 sysc_vtime:
 	UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER
 sysc_stime:
@@ -246,20 +239,20 @@ sysc_stime:
 sysc_update:
 	mvc	__LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
 sysc_do_svc:
-	l	%r9,__LC_THREAD_INFO	# load pointer to thread_info struct
-	ltr	%r7,%r7			# test for svc 0
+	xr	%r7,%r7
+	icm	%r7,3,SP_SVCNR(%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)
 	lr	%r7,%r1 	  # copy svc number to %r7
 sysc_nr_ok:
-	sth	%r7,SP_SVCNR(%r15)
 	sll	%r7,2		  # svc number *4
-	l	%r8,BASED(.Lsysc_table)
-	tm	__TI_flags+2(%r9),_TIF_SYSCALL
+	l	%r10,BASED(.Lsysc_table)
+	tm	__TI_flags+2(%r12),_TIF_SYSCALL
 	mvc	SP_ARGS(4,%r15),SP_R7(%r15)
-	l	%r8,0(%r7,%r8)	  # get system call addr.
+	l	%r8,0(%r7,%r10)	  # get system call addr.
 	bnz	BASED(sysc_tracesys)
 	basr	%r14,%r8	  # call sys_xxxx
 	st	%r2,SP_R2(%r15)   # store return value (change R2 on stack)
@@ -267,7 +260,7 @@ sysc_nr_ok:
 sysc_return:
 	LOCKDEP_SYS_EXIT
 sysc_tif:
-	tm	__TI_flags+3(%r9),_TIF_WORK_SVC
+	tm	__TI_flags+3(%r12),_TIF_WORK_SVC
 	bnz	BASED(sysc_work)  # there is work to do (signals etc.)
 sysc_restore:
 	RESTORE_ALL __LC_RETURN_PSW,1
@@ -284,17 +277,17 @@ sysc_work:
 # One of the work bits is on. Find out which one.
 #
 sysc_work_tif:
-	tm	__TI_flags+3(%r9),_TIF_MCCK_PENDING
+	tm	__TI_flags+3(%r12),_TIF_MCCK_PENDING
 	bo	BASED(sysc_mcck_pending)
-	tm	__TI_flags+3(%r9),_TIF_NEED_RESCHED
+	tm	__TI_flags+3(%r12),_TIF_NEED_RESCHED
 	bo	BASED(sysc_reschedule)
-	tm	__TI_flags+3(%r9),_TIF_SIGPENDING
+	tm	__TI_flags+3(%r12),_TIF_SIGPENDING
 	bo	BASED(sysc_sigpending)
-	tm	__TI_flags+3(%r9),_TIF_NOTIFY_RESUME
+	tm	__TI_flags+3(%r12),_TIF_NOTIFY_RESUME
 	bo	BASED(sysc_notify_resume)
-	tm	__TI_flags+3(%r9),_TIF_RESTART_SVC
+	tm	__TI_flags+3(%r12),_TIF_RESTART_SVC
 	bo	BASED(sysc_restart)
-	tm	__TI_flags+3(%r9),_TIF_SINGLE_STEP
+	tm	__TI_flags+3(%r12),_TIF_PER_TRAP
 	bo	BASED(sysc_singlestep)
 	b	BASED(sysc_return)	# beware of critical section cleanup
 
@@ -318,13 +311,13 @@ sysc_mcck_pending:
 # _TIF_SIGPENDING is set, call do_signal
 #
 sysc_sigpending:
-	ni	__TI_flags+3(%r9),255-_TIF_SINGLE_STEP # clear TIF_SINGLE_STEP
+	ni	__TI_flags+3(%r12),255-_TIF_PER_TRAP # clear TIF_PER_TRAP
 	la	%r2,SP_PTREGS(%r15)	# load pt_regs
 	l	%r1,BASED(.Ldo_signal)
 	basr	%r14,%r1		# call do_signal
-	tm	__TI_flags+3(%r9),_TIF_RESTART_SVC
+	tm	__TI_flags+3(%r12),_TIF_RESTART_SVC
 	bo	BASED(sysc_restart)
-	tm	__TI_flags+3(%r9),_TIF_SINGLE_STEP
+	tm	__TI_flags+3(%r12),_TIF_PER_TRAP
 	bo	BASED(sysc_singlestep)
 	b	BASED(sysc_return)
 
@@ -342,23 +335,23 @@ sysc_notify_resume:
 # _TIF_RESTART_SVC is set, set up registers and restart svc
 #
 sysc_restart:
-	ni	__TI_flags+3(%r9),255-_TIF_RESTART_SVC # clear TIF_RESTART_SVC
+	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_SINGLE_STEP is set, call do_single_step
+# _TIF_PER_TRAP is set, call do_per_trap
 #
 sysc_singlestep:
-	ni	__TI_flags+3(%r9),255-_TIF_SINGLE_STEP # clear TIF_SINGLE_STEP
-	mvi	SP_SVCNR(%r15),0xff	# set trap indication to pgm check
-	mvi	SP_SVCNR+1(%r15),0xff
+	ni	__TI_flags+3(%r12),255-_TIF_PER_TRAP # clear TIF_PER_TRAP
+	xc	SP_SVCNR(2,%r15),SP_SVCNR(%r15)		# clear svc number
 	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
-	br	%r1			# branch to do_single_step
+	br	%r1			# branch to do_per_trap
 
 #
 # call tracehook_report_syscall_entry/tracehook_report_syscall_exit before
@@ -368,15 +361,15 @@ sysc_tracesys:
 	l	%r1,BASED(.Ltrace_entry)
 	la	%r2,SP_PTREGS(%r15)	# load pt_regs
 	la	%r3,0
-	srl	%r7,2
-	st	%r7,SP_R2(%r15)
+	xr	%r0,%r0
+	icm	%r0,3,SP_SVCNR(%r15)
+	st	%r0,SP_R2(%r15)
 	basr	%r14,%r1
 	cl	%r2,BASED(.Lnr_syscalls)
 	bnl	BASED(sysc_tracenogo)
-	l	%r8,BASED(.Lsysc_table)
 	lr	%r7,%r2
 	sll	%r7,2			# svc number *4
-	l	%r8,0(%r7,%r8)
+	l	%r8,0(%r7,%r10)
 sysc_tracego:
 	lm	%r3,%r6,SP_R3(%r15)
 	mvc	SP_ARGS(4,%r15),SP_R7(%r15)
@@ -384,7 +377,7 @@ sysc_tracego:
 	basr	%r14,%r8		# call sys_xxx
 	st	%r2,SP_R2(%r15)		# store return value
 sysc_tracenogo:
-	tm	__TI_flags+2(%r9),_TIF_SYSCALL
+	tm	__TI_flags+2(%r12),_TIF_SYSCALL
 	bz	BASED(sysc_return)
 	l	%r1,BASED(.Ltrace_exit)
 	la	%r2,SP_PTREGS(%r15)	# load pt_regs
@@ -397,7 +390,7 @@ sysc_tracenogo:
 	.globl	ret_from_fork
 ret_from_fork:
 	l	%r13,__LC_SVC_NEW_PSW+4
-	l	%r9,__LC_THREAD_INFO	# load pointer to thread_info struct
+	l	%r12,__LC_THREAD_INFO	# load pointer to thread_info struct
 	tm	SP_PSW+1(%r15),0x01	# forking a kernel thread ?
 	bo	BASED(0f)
 	st	%r15,SP_R15(%r15)	# store stack pointer for new kthread
@@ -432,8 +425,8 @@ kernel_execve:
 0:	stnsm	__SF_EMPTY(%r15),0xfc	# disable interrupts
 	l	%r15,__LC_KERNEL_STACK	# load ksp
 	s	%r15,BASED(.Lc_spsize)	# make room for registers & psw
-	l	%r9,__LC_THREAD_INFO
 	mvc	SP_PTREGS(__PT_SIZE,%r15),0(%r12)	# copy pt_regs
+	l	%r12,__LC_THREAD_INFO
 	xc	__SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15)
 	stosm	__SF_EMPTY(%r15),0x03	# reenable interrupts
 	l	%r1,BASED(.Lexecve_tail)
@@ -463,26 +456,27 @@ pgm_check_handler:
 	SAVE_ALL_BASE __LC_SAVE_AREA
 	tm	__LC_PGM_INT_CODE+1,0x80 # check whether we got a per exception
 	bnz	BASED(pgm_per)		# got per exception -> special case
-	SAVE_ALL_SYNC __LC_PGM_OLD_PSW,__LC_SAVE_AREA
-	CREATE_STACK_FRAME __LC_PGM_OLD_PSW,__LC_SAVE_AREA
+	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 ?
 	bz	BASED(pgm_no_vtime)
 	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
 pgm_no_vtime:
-	l	%r9,__LC_THREAD_INFO	# load pointer to thread_info struct
 	l	%r3,__LC_PGM_ILC	# load program interruption code
 	l	%r4,__LC_TRANS_EXC_CODE
 	REENABLE_IRQS
 	la	%r8,0x7f
 	nr	%r8,%r3
-pgm_do_call:
-	l	%r7,BASED(.Ljump_table)
 	sll	%r8,2
-	l	%r7,0(%r8,%r7)		# load address of handler routine
+	l	%r1,BASED(.Ljump_table)
+	l	%r1,0(%r8,%r1)		# load address of handler routine
 	la	%r2,SP_PTREGS(%r15)	# address of register-save area
-	basr	%r14,%r7		# branch to interrupt-handler
+	basr	%r14,%r1		# branch to interrupt-handler
 pgm_exit:
 	b	BASED(sysc_return)
 
@@ -503,33 +497,34 @@ pgm_per:
 # Normal per exception
 #
 pgm_per_std:
-	SAVE_ALL_SYNC __LC_PGM_OLD_PSW,__LC_SAVE_AREA
-	CREATE_STACK_FRAME __LC_PGM_OLD_PSW,__LC_SAVE_AREA
+	SAVE_ALL_PGM __LC_PGM_OLD_PSW,__LC_SAVE_AREA
+	CREATE_STACK_FRAME __LC_SAVE_AREA
+	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 ?
 	bz	BASED(pgm_no_vtime2)
 	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
 pgm_no_vtime2:
-	l	%r9,__LC_THREAD_INFO	# load pointer to thread_info struct
-	l	%r1,__TI_task(%r9)
+	l	%r1,__TI_task(%r12)
 	tm	SP_PSW+1(%r15),0x01	# kernel per event ?
 	bz	BASED(kernel_per)
-	mvc	__THREAD_per+__PER_atmid(2,%r1),__LC_PER_ATMID
-	mvc	__THREAD_per+__PER_address(4,%r1),__LC_PER_ADDRESS
-	mvc	__THREAD_per+__PER_access_id(1,%r1),__LC_PER_ACCESS_ID
-	oi	__TI_flags+3(%r9),_TIF_SINGLE_STEP # set TIF_SINGLE_STEP
+	mvc	__THREAD_per_cause(2,%r1),__LC_PER_CAUSE
+	mvc	__THREAD_per_address(4,%r1),__LC_PER_ADDRESS
+	mvc	__THREAD_per_paid(1,%r1),__LC_PER_PAID
+	oi	__TI_flags+3(%r12),_TIF_PER_TRAP # set TIF_PER_TRAP
 	l	%r3,__LC_PGM_ILC	# load program interruption code
 	l	%r4,__LC_TRANS_EXC_CODE
 	REENABLE_IRQS
 	la	%r8,0x7f
 	nr	%r8,%r3 		# clear per-event-bit and ilc
 	be	BASED(pgm_exit2)	# only per or per+check ?
-	l	%r7,BASED(.Ljump_table)
 	sll	%r8,2
-	l	%r7,0(%r8,%r7)		# load address of handler routine
+	l	%r1,BASED(.Ljump_table)
+	l	%r1,0(%r8,%r1)		# load address of handler routine
 	la	%r2,SP_PTREGS(%r15)	# address of register-save area
-	basr	%r14,%r7		# branch to interrupt-handler
+	basr	%r14,%r1		# branch to interrupt-handler
 pgm_exit2:
 	b	BASED(sysc_return)
 
@@ -537,18 +532,19 @@ pgm_exit2:
 # it was a single stepped SVC that is causing all the trouble
 #
 pgm_svcper:
-	SAVE_ALL_SYNC __LC_SVC_OLD_PSW,__LC_SAVE_AREA
-	CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA
+	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
 	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
-	lh	%r7,0x8a		# get svc number from lowcore
-	l	%r9,__LC_THREAD_INFO	# load pointer to thread_info struct
-	l	%r8,__TI_task(%r9)
-	mvc	__THREAD_per+__PER_atmid(2,%r8),__LC_PER_ATMID
-	mvc	__THREAD_per+__PER_address(4,%r8),__LC_PER_ADDRESS
-	mvc	__THREAD_per+__PER_access_id(1,%r8),__LC_PER_ACCESS_ID
-	oi	__TI_flags+3(%r9),_TIF_SINGLE_STEP # set TIF_SINGLE_STEP
+	l	%r8,__TI_task(%r12)
+	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)
@@ -558,8 +554,7 @@ pgm_svcper:
 #
 kernel_per:
 	REENABLE_IRQS
-	mvi	SP_SVCNR(%r15),0xff	# set trap indication to pgm check
-	mvi	SP_SVCNR+1(%r15),0xff
+	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
@@ -573,9 +568,10 @@ kernel_per:
 io_int_handler:
 	stck	__LC_INT_CLOCK
 	stpt	__LC_ASYNC_ENTER_TIMER
-	SAVE_ALL_BASE __LC_SAVE_AREA+16
 	SAVE_ALL_ASYNC __LC_IO_OLD_PSW,__LC_SAVE_AREA+16
-	CREATE_STACK_FRAME __LC_IO_OLD_PSW,__LC_SAVE_AREA+16
+	CREATE_STACK_FRAME __LC_SAVE_AREA+16
+	mvc	SP_PSW(8,%r15),0(%r12)	# move user PSW to stack
+	l	%r12,__LC_THREAD_INFO	# load pointer to thread_info struct
 	tm	SP_PSW+1(%r15),0x01	# interrupting from user ?
 	bz	BASED(io_no_vtime)
 	UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER
@@ -583,7 +579,6 @@ io_int_handler:
 	mvc	__LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER
 io_no_vtime:
 	TRACE_IRQS_OFF
-	l	%r9,__LC_THREAD_INFO	# load pointer to thread_info struct
 	l	%r1,BASED(.Ldo_IRQ)	# load address of do_IRQ
 	la	%r2,SP_PTREGS(%r15)	# address of register-save area
 	basr	%r14,%r1		# branch to standard irq handler
@@ -591,7 +586,7 @@ io_return:
 	LOCKDEP_SYS_EXIT
 	TRACE_IRQS_ON
 io_tif:
-	tm	__TI_flags+3(%r9),_TIF_WORK_INT
+	tm	__TI_flags+3(%r12),_TIF_WORK_INT
 	bnz	BASED(io_work)		# there is work to do (signals etc.)
 io_restore:
 	RESTORE_ALL __LC_RETURN_PSW,0
@@ -609,9 +604,9 @@ io_work:
 	bo	BASED(io_work_user)	# yes -> do resched & signal
 #ifdef CONFIG_PREEMPT
 	# check for preemptive scheduling
-	icm	%r0,15,__TI_precount(%r9)
+	icm	%r0,15,__TI_precount(%r12)
 	bnz	BASED(io_restore)	# preemption disabled
-	tm	__TI_flags+3(%r9),_TIF_NEED_RESCHED
+	tm	__TI_flags+3(%r12),_TIF_NEED_RESCHED
 	bno	BASED(io_restore)
 	# switch to kernel stack
 	l	%r1,SP_R15(%r15)
@@ -645,13 +640,13 @@ io_work_user:
 #		and _TIF_MCCK_PENDING
 #
 io_work_tif:
-	tm	__TI_flags+3(%r9),_TIF_MCCK_PENDING
+	tm	__TI_flags+3(%r12),_TIF_MCCK_PENDING
 	bo	BASED(io_mcck_pending)
-	tm	__TI_flags+3(%r9),_TIF_NEED_RESCHED
+	tm	__TI_flags+3(%r12),_TIF_NEED_RESCHED
 	bo	BASED(io_reschedule)
-	tm	__TI_flags+3(%r9),_TIF_SIGPENDING
+	tm	__TI_flags+3(%r12),_TIF_SIGPENDING
 	bo	BASED(io_sigpending)
-	tm	__TI_flags+3(%r9),_TIF_NOTIFY_RESUME
+	tm	__TI_flags+3(%r12),_TIF_NOTIFY_RESUME
 	bo	BASED(io_notify_resume)
 	b	BASED(io_return)	# beware of critical section cleanup
 
@@ -711,16 +706,16 @@ io_notify_resume:
 ext_int_handler:
 	stck	__LC_INT_CLOCK
 	stpt	__LC_ASYNC_ENTER_TIMER
-	SAVE_ALL_BASE __LC_SAVE_AREA+16
 	SAVE_ALL_ASYNC __LC_EXT_OLD_PSW,__LC_SAVE_AREA+16
-	CREATE_STACK_FRAME __LC_EXT_OLD_PSW,__LC_SAVE_AREA+16
+	CREATE_STACK_FRAME __LC_SAVE_AREA+16
+	mvc	SP_PSW(8,%r15),0(%r12)	# move user PSW to stack
+	l	%r12,__LC_THREAD_INFO	# load pointer to thread_info struct
 	tm	SP_PSW+1(%r15),0x01	# interrupting from user ?
 	bz	BASED(ext_no_vtime)
 	UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER
 	UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
 	mvc	__LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER
 ext_no_vtime:
-	l	%r9,__LC_THREAD_INFO	# load pointer to thread_info struct
 	TRACE_IRQS_OFF
 	la	%r2,SP_PTREGS(%r15)	# address of register-save area
 	l	%r3,__LC_CPU_ADDRESS	# get cpu address + interruption code
@@ -775,7 +770,10 @@ mcck_int_main:
 	sra	%r14,PAGE_SHIFT
 	be	BASED(0f)
 	l	%r15,__LC_PANIC_STACK	# load panic stack
-0:	CREATE_STACK_FRAME __LC_MCK_OLD_PSW,__LC_SAVE_AREA+32
+0:	s	%r15,BASED(.Lc_spsize)	# make room for registers & psw
+	CREATE_STACK_FRAME __LC_SAVE_AREA+32
+	mvc	SP_PSW(8,%r15),0(%r12)
+	l	%r12,__LC_THREAD_INFO	# load pointer to thread_info struct
 	tm	__LC_MCCK_CODE+2,0x08	# mwp of old psw valid?
 	bno	BASED(mcck_no_vtime)	# no -> skip cleanup critical
 	tm	SP_PSW+1(%r15),0x01	# interrupting from user ?
@@ -784,7 +782,6 @@ mcck_int_main:
 	UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
 	mvc	__LC_LAST_UPDATE_TIMER(8),__LC_MCCK_ENTER_TIMER
 mcck_no_vtime:
-	l	%r9,__LC_THREAD_INFO	# load pointer to thread_info struct
 	la	%r2,SP_PTREGS(%r15)	# load pt_regs
 	l	%r1,BASED(.Ls390_mcck)
 	basr	%r14,%r1		# call machine check handler
@@ -796,7 +793,7 @@ mcck_no_vtime:
 	xc	__SF_BACKCHAIN(4,%r1),__SF_BACKCHAIN(%r1) # clear back chain
 	lr	%r15,%r1
 	stosm	__SF_EMPTY(%r15),0x04	# turn dat on
-	tm	__TI_flags+3(%r9),_TIF_MCCK_PENDING
+	tm	__TI_flags+3(%r12),_TIF_MCCK_PENDING
 	bno	BASED(mcck_return)
 	TRACE_IRQS_OFF
 	l	%r1,BASED(.Ls390_handle_mcck)
@@ -861,6 +858,8 @@ restart_crash:
 restart_go:
 #endif
 
+	.section .kprobes.text, "ax"
+
 #ifdef CONFIG_CHECK_STACK
 /*
  * The synchronous or the asynchronous stack overflowed. We are dead.
@@ -943,12 +942,13 @@ cleanup_system_call:
 	bh	BASED(0f)
 	mvc	__LC_SAVE_AREA(16),0(%r12)
 0:	st	%r13,4(%r12)
-	st	%r12,__LC_SAVE_AREA+48	# argh
-	SAVE_ALL_SYNC __LC_SVC_OLD_PSW,__LC_SAVE_AREA
-	CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA
-	l	%r12,__LC_SAVE_AREA+48	# argh
+	l	%r15,__LC_KERNEL_STACK	# problem state -> load ksp
+	s	%r15,BASED(.Lc_spsize)	# make room for registers & psw
 	st	%r15,12(%r12)
-	lh	%r7,0x8a
+	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
 cleanup_vtime:
 	clc	__LC_RETURN_PSW+4(4),BASED(cleanup_system_call_insn+12)
 	bhe	BASED(cleanup_stime)
@@ -1046,7 +1046,7 @@ cleanup_io_restore_insn:
 .Ldo_signal:	.long	do_signal
 .Ldo_notify_resume:
 		.long	do_notify_resume
-.Lhandle_per:	.long	do_single_step
+.Lhandle_per:	.long	do_per_trap
 .Ldo_execve:	.long	do_execve
 .Lexecve_tail:	.long	execve_tail
 .Ljump_table:	.long	pgm_check_table
diff -druNp linux-libre-2.6.37-gnu1/arch/s390/kernel/ftrace.c linux-libre-2.6.38-gnu1/arch/s390/kernel/ftrace.c
--- linux-libre-2.6.37-gnu1/arch/s390/kernel/ftrace.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/s390/kernel/ftrace.c	2011-03-14 21:20:32.000000000 -0400
@@ -4,7 +4,7 @@
  * Copyright IBM Corp. 2009
  *
  *   Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>,
- *
+ *		Martin Schwidefsky <schwidefsky@de.ibm.com>
  */
 
 #include <linux/hardirq.h>
@@ -12,176 +12,144 @@
 #include <linux/ftrace.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
+#include <linux/kprobes.h>
 #include <trace/syscall.h>
 #include <asm/asm-offsets.h>
 
+#ifdef CONFIG_64BIT
+#define MCOUNT_OFFSET_RET 12
+#else
+#define MCOUNT_OFFSET_RET 22
+#endif
+
 #ifdef CONFIG_DYNAMIC_FTRACE
 
 void ftrace_disable_code(void);
-void ftrace_disable_return(void);
-void ftrace_call_code(void);
-void ftrace_nop_code(void);
-
-#define FTRACE_INSN_SIZE 4
+void ftrace_enable_insn(void);
 
 #ifdef CONFIG_64BIT
-
+/*
+ * The 64-bit mcount code looks like this:
+ *	stg	%r14,8(%r15)		# offset 0
+ * >	larl	%r1,<&counter>		# offset 6
+ * >	brasl	%r14,_mcount		# offset 12
+ *	lg	%r14,8(%r15)		# offset 18
+ * Total length is 24 bytes. The middle two instructions of the mcount
+ * block get overwritten by ftrace_make_nop / ftrace_make_call.
+ * The 64-bit enabled ftrace code block looks like this:
+ *	stg	%r14,8(%r15)		# offset 0
+ * >	lg	%r1,__LC_FTRACE_FUNC	# offset 6
+ * >	lgr	%r0,%r0			# offset 12
+ * >	basr	%r14,%r1		# offset 16
+ *	lg	%r14,8(%15)		# offset 18
+ * The return points of the mcount/ftrace function have the same offset 18.
+ * The 64-bit disable ftrace code block looks like this:
+ *	stg	%r14,8(%r15)		# offset 0
+ * >	jg	.+18			# offset 6
+ * >	lgr	%r0,%r0			# offset 12
+ * >	basr	%r14,%r1		# offset 16
+ *	lg	%r14,8(%15)		# offset 18
+ * The jg instruction branches to offset 24 to skip as many instructions
+ * as possible.
+ */
 asm(
 	"	.align	4\n"
 	"ftrace_disable_code:\n"
-	"	j	0f\n"
-	"	.word	0x0024\n"
-	"	lg	%r1,"__stringify(__LC_FTRACE_FUNC)"\n"
-	"	basr	%r14,%r1\n"
-	"ftrace_disable_return:\n"
-	"	lg	%r14,8(15)\n"
+	"	jg	0f\n"
 	"	lgr	%r0,%r0\n"
-	"0:\n");
-
-asm(
+	"	basr	%r14,%r1\n"
+	"0:\n"
 	"	.align	4\n"
-	"ftrace_nop_code:\n"
-	"	j	.+"__stringify(MCOUNT_INSN_SIZE)"\n");
+	"ftrace_enable_insn:\n"
+	"	lg	%r1,"__stringify(__LC_FTRACE_FUNC)"\n");
 
-asm(
-	"	.align	4\n"
-	"ftrace_call_code:\n"
-	"	stg	%r14,8(%r15)\n");
+#define FTRACE_INSN_SIZE	6
 
 #else /* CONFIG_64BIT */
-
+/*
+ * The 31-bit mcount code looks like this:
+ *	st	%r14,4(%r15)		# offset 0
+ * >	bras	%r1,0f			# offset 4
+ * >	.long	_mcount			# offset 8
+ * >	.long	<&counter>		# offset 12
+ * > 0:	l	%r14,0(%r1)		# offset 16
+ * >	l	%r1,4(%r1)		# offset 20
+ *	basr	%r14,%r14		# offset 24
+ *	l	%r14,4(%r15)		# offset 26
+ * Total length is 30 bytes. The twenty bytes starting from offset 4
+ * to offset 24 get overwritten by ftrace_make_nop / ftrace_make_call.
+ * The 31-bit enabled ftrace code block looks like this:
+ *	st	%r14,4(%r15)		# offset 0
+ * >	l	%r14,__LC_FTRACE_FUNC	# offset 4
+ * >	j	0f			# offset 8
+ * >	.fill	12,1,0x07		# offset 12
+ *   0:	basr	%r14,%r14		# offset 24
+ *	l	%r14,4(%r14)		# offset 26
+ * The return points of the mcount/ftrace function have the same offset 26.
+ * The 31-bit disabled ftrace code block looks like this:
+ *	st	%r14,4(%r15)		# offset 0
+ * >	j	.+26			# offset 4
+ * >	j	0f			# offset 8
+ * >	.fill	12,1,0x07		# offset 12
+ *   0:	basr	%r14,%r14		# offset 24
+ *	l	%r14,4(%r14)		# offset 26
+ * The j instruction branches to offset 30 to skip as many instructions
+ * as possible.
+ */
 asm(
 	"	.align	4\n"
 	"ftrace_disable_code:\n"
+	"	j	1f\n"
 	"	j	0f\n"
-	"	l	%r1,"__stringify(__LC_FTRACE_FUNC)"\n"
-	"	basr	%r14,%r1\n"
-	"ftrace_disable_return:\n"
-	"	l	%r14,4(%r15)\n"
-	"	j	0f\n"
-	"	bcr	0,%r7\n"
-	"	bcr	0,%r7\n"
-	"	bcr	0,%r7\n"
-	"	bcr	0,%r7\n"
-	"	bcr	0,%r7\n"
-	"	bcr	0,%r7\n"
-	"0:\n");
-
-asm(
+	"	.fill	12,1,0x07\n"
+	"0:	basr	%r14,%r14\n"
+	"1:\n"
 	"	.align	4\n"
-	"ftrace_nop_code:\n"
-	"	j	.+"__stringify(MCOUNT_INSN_SIZE)"\n");
+	"ftrace_enable_insn:\n"
+	"	l	%r14,"__stringify(__LC_FTRACE_FUNC)"\n");
 
-asm(
-	"	.align	4\n"
-	"ftrace_call_code:\n"
-	"	st	%r14,4(%r15)\n");
+#define FTRACE_INSN_SIZE	4
 
 #endif /* CONFIG_64BIT */
 
-static int ftrace_modify_code(unsigned long ip,
-			      void *old_code, int old_size,
-			      void *new_code, int new_size)
-{
-	unsigned char replaced[MCOUNT_INSN_SIZE];
-
-	/*
-	 * Note: Due to modules code can disappear and change.
-	 *  We need to protect against faulting as well as code
-	 *  changing. We do this by using the probe_kernel_*
-	 *  functions.
-	 *  This however is just a simple sanity check.
-	 */
-	if (probe_kernel_read(replaced, (void *)ip, old_size))
-		return -EFAULT;
-	if (memcmp(replaced, old_code, old_size) != 0)
-		return -EINVAL;
-	if (probe_kernel_write((void *)ip, new_code, new_size))
-		return -EPERM;
-	return 0;
-}
-
-static int ftrace_make_initial_nop(struct module *mod, struct dyn_ftrace *rec,
-				   unsigned long addr)
-{
-	return ftrace_modify_code(rec->ip,
-				  ftrace_call_code, FTRACE_INSN_SIZE,
-				  ftrace_disable_code, MCOUNT_INSN_SIZE);
-}
 
 int ftrace_make_nop(struct module *mod, struct dyn_ftrace *rec,
 		    unsigned long addr)
 {
-	if (addr == MCOUNT_ADDR)
-		return ftrace_make_initial_nop(mod, rec, addr);
-	return ftrace_modify_code(rec->ip,
-				  ftrace_call_code, FTRACE_INSN_SIZE,
-				  ftrace_nop_code, FTRACE_INSN_SIZE);
+	if (probe_kernel_write((void *) rec->ip, ftrace_disable_code,
+			       MCOUNT_INSN_SIZE))
+		return -EPERM;
+	return 0;
 }
 
 int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
 {
-	return ftrace_modify_code(rec->ip,
-				  ftrace_nop_code, FTRACE_INSN_SIZE,
-				  ftrace_call_code, FTRACE_INSN_SIZE);
+	if (probe_kernel_write((void *) rec->ip, ftrace_enable_insn,
+			       FTRACE_INSN_SIZE))
+		return -EPERM;
+	return 0;
 }
 
 int ftrace_update_ftrace_func(ftrace_func_t func)
 {
-	ftrace_dyn_func = (unsigned long)func;
 	return 0;
 }
 
 int __init ftrace_dyn_arch_init(void *data)
 {
-	*(unsigned long *)data = 0;
+	*(unsigned long *) data = 0;
 	return 0;
 }
 
 #endif /* CONFIG_DYNAMIC_FTRACE */
 
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
-#ifdef CONFIG_DYNAMIC_FTRACE
-/*
- * Patch the kernel code at ftrace_graph_caller location:
- * The instruction there is branch relative on condition. The condition mask
- * is either all ones (always branch aka disable ftrace_graph_caller) or all
- * zeroes (nop aka enable ftrace_graph_caller).
- * Instruction format for brc is a7m4xxxx where m is the condition mask.
- */
-int ftrace_enable_ftrace_graph_caller(void)
-{
-	unsigned short opcode = 0xa704;
-
-	return probe_kernel_write(ftrace_graph_caller, &opcode, sizeof(opcode));
-}
-
-int ftrace_disable_ftrace_graph_caller(void)
-{
-	unsigned short opcode = 0xa7f4;
-
-	return probe_kernel_write(ftrace_graph_caller, &opcode, sizeof(opcode));
-}
-
-static inline unsigned long ftrace_mcount_call_adjust(unsigned long addr)
-{
-	return addr - (ftrace_disable_return - ftrace_disable_code);
-}
-
-#else /* CONFIG_DYNAMIC_FTRACE */
-
-static inline unsigned long ftrace_mcount_call_adjust(unsigned long addr)
-{
-	return addr - MCOUNT_OFFSET_RET;
-}
-
-#endif /* CONFIG_DYNAMIC_FTRACE */
-
 /*
  * Hook the return address and push it in the stack of return addresses
  * in current thread info.
  */
-unsigned long prepare_ftrace_return(unsigned long ip, unsigned long parent)
+unsigned long __kprobes prepare_ftrace_return(unsigned long parent,
+					      unsigned long ip)
 {
 	struct ftrace_graph_ent trace;
 
@@ -189,14 +157,42 @@ unsigned long prepare_ftrace_return(unsi
 		goto out;
 	if (ftrace_push_return_trace(parent, ip, &trace.depth, 0) == -EBUSY)
 		goto out;
-	trace.func = ftrace_mcount_call_adjust(ip) & PSW_ADDR_INSN;
+	trace.func = (ip & PSW_ADDR_INSN) - MCOUNT_OFFSET_RET;
 	/* Only trace if the calling function expects to. */
 	if (!ftrace_graph_entry(&trace)) {
 		current->curr_ret_stack--;
 		goto out;
 	}
-	parent = (unsigned long)return_to_handler;
+	parent = (unsigned long) return_to_handler;
 out:
 	return parent;
 }
+
+#ifdef CONFIG_DYNAMIC_FTRACE
+/*
+ * Patch the kernel code at ftrace_graph_caller location. The instruction
+ * there is branch relative and save to prepare_ftrace_return. To disable
+ * the call to prepare_ftrace_return we patch the bras offset to point
+ * directly after the instructions. To enable the call we calculate
+ * the original offset to prepare_ftrace_return and put it back.
+ */
+int ftrace_enable_ftrace_graph_caller(void)
+{
+	unsigned short offset;
+
+	offset = ((void *) prepare_ftrace_return -
+		  (void *) ftrace_graph_caller) / 2;
+	return probe_kernel_write(ftrace_graph_caller + 2,
+				  &offset, sizeof(offset));
+}
+
+int ftrace_disable_ftrace_graph_caller(void)
+{
+	static unsigned short offset = 0x0002;
+
+	return probe_kernel_write(ftrace_graph_caller + 2,
+				  &offset, sizeof(offset));
+}
+
+#endif /* CONFIG_DYNAMIC_FTRACE */
 #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
diff -druNp linux-libre-2.6.37-gnu1/arch/s390/kernel/irq.c linux-libre-2.6.38-gnu1/arch/s390/kernel/irq.c
--- linux-libre-2.6.37-gnu1/arch/s390/kernel/irq.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/s390/kernel/irq.c	2011-03-14 21:20:32.000000000 -0400
@@ -1,7 +1,5 @@
 /*
- *  arch/s390/kernel/irq.c
- *
- *    Copyright IBM Corp. 2004,2007
+ *    Copyright IBM Corp. 2004,2010
  *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
  *		 Thomas Spatzier (tspat@de.ibm.com)
  *
@@ -17,12 +15,42 @@
 #include <linux/proc_fs.h>
 #include <linux/profile.h>
 
+struct irq_class {
+	char *name;
+	char *desc;
+};
+
+static const struct irq_class intrclass_names[] = {
+	{.name = "EXT" },
+	{.name = "I/O" },
+	{.name = "CLK", .desc = "[EXT] Clock Comparator" },
+	{.name = "IPI", .desc = "[EXT] Signal Processor" },
+	{.name = "TMR", .desc = "[EXT] CPU Timer" },
+	{.name = "TAL", .desc = "[EXT] Timing Alert" },
+	{.name = "PFL", .desc = "[EXT] Pseudo Page Fault" },
+	{.name = "DSD", .desc = "[EXT] DASD Diag" },
+	{.name = "VRT", .desc = "[EXT] Virtio" },
+	{.name = "SCP", .desc = "[EXT] Service Call" },
+	{.name = "IUC", .desc = "[EXT] IUCV" },
+	{.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" },
+	{.name = "TAP", .desc = "[I/O] Tape" },
+	{.name = "VMR", .desc = "[I/O] Unit Record Devices" },
+	{.name = "LCS", .desc = "[I/O] LCS" },
+	{.name = "CLW", .desc = "[I/O] CLAW" },
+	{.name = "CTC", .desc = "[I/O] CTC" },
+	{.name = "APB", .desc = "[I/O] AP Bus" },
+	{.name = "NMI", .desc = "[NMI] Machine Check" },
+};
+
 /*
  * show_interrupts is needed by /proc/interrupts.
  */
 int show_interrupts(struct seq_file *p, void *v)
 {
-	static const char *intrclass_names[] = { "EXT", "I/O", };
 	int i = *(loff_t *) v, j;
 
 	get_online_cpus();
@@ -34,15 +62,16 @@ int show_interrupts(struct seq_file *p,
 	}
 
 	if (i < NR_IRQS) {
-		seq_printf(p, "%s: ", intrclass_names[i]);
+		seq_printf(p, "%s: ", intrclass_names[i].name);
 #ifndef CONFIG_SMP
 		seq_printf(p, "%10u ", kstat_irqs(i));
 #else
 		for_each_online_cpu(j)
 			seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
 #endif
+		if (intrclass_names[i].desc)
+			seq_printf(p, "  %s", intrclass_names[i].desc);
                 seq_putc(p, '\n');
-
         }
 	put_online_cpus();
         return 0;
diff -druNp linux-libre-2.6.37-gnu1/arch/s390/kernel/kprobes.c linux-libre-2.6.38-gnu1/arch/s390/kernel/kprobes.c
--- linux-libre-2.6.37-gnu1/arch/s390/kernel/kprobes.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/s390/kernel/kprobes.c	2011-03-14 21:20:32.000000000 -0400
@@ -32,34 +32,14 @@
 #include <linux/slab.h>
 #include <linux/hardirq.h>
 
-DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL;
+DEFINE_PER_CPU(struct kprobe *, current_kprobe);
 DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);
 
-struct kretprobe_blackpoint kretprobe_blacklist[] = {{NULL, NULL}};
-
-int __kprobes arch_prepare_kprobe(struct kprobe *p)
-{
-	/* Make sure the probe isn't going on a difficult instruction */
-	if (is_prohibited_opcode((kprobe_opcode_t *) p->addr))
-		return -EINVAL;
-
-	if ((unsigned long)p->addr & 0x01)
-		return -EINVAL;
-
-	/* Use the get_insn_slot() facility for correctness */
-	if (!(p->ainsn.insn = get_insn_slot()))
-		return -ENOMEM;
-
-	memcpy(p->ainsn.insn, p->addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t));
-
-	get_instruction_type(&p->ainsn);
-	p->opcode = *p->addr;
-	return 0;
-}
+struct kretprobe_blackpoint kretprobe_blacklist[] = { };
 
-int __kprobes is_prohibited_opcode(kprobe_opcode_t *instruction)
+static int __kprobes is_prohibited_opcode(kprobe_opcode_t *insn)
 {
-	switch (*(__u8 *) instruction) {
+	switch (insn[0] >> 8) {
 	case 0x0c:	/* bassm */
 	case 0x0b:	/* bsm	 */
 	case 0x83:	/* diag  */
@@ -68,7 +48,7 @@ int __kprobes is_prohibited_opcode(kprob
 	case 0xad:	/* stosm */
 		return -EINVAL;
 	}
-	switch (*(__u16 *) instruction) {
+	switch (insn[0]) {
 	case 0x0101:	/* pr	 */
 	case 0xb25a:	/* bsa	 */
 	case 0xb240:	/* bakr  */
@@ -81,93 +61,92 @@ int __kprobes is_prohibited_opcode(kprob
 	return 0;
 }
 
-void __kprobes get_instruction_type(struct arch_specific_insn *ainsn)
+static int __kprobes get_fixup_type(kprobe_opcode_t *insn)
 {
 	/* default fixup method */
-	ainsn->fixup = FIXUP_PSW_NORMAL;
-
-	/* save r1 operand */
-	ainsn->reg = (*ainsn->insn & 0xf0) >> 4;
-
-	/* save the instruction length (pop 5-5) in bytes */
-	switch (*(__u8 *) (ainsn->insn) >> 6) {
-	case 0:
-		ainsn->ilen = 2;
-		break;
-	case 1:
-	case 2:
-		ainsn->ilen = 4;
-		break;
-	case 3:
-		ainsn->ilen = 6;
-		break;
-	}
+	int fixup = FIXUP_PSW_NORMAL;
 
-	switch (*(__u8 *) ainsn->insn) {
+	switch (insn[0] >> 8) {
 	case 0x05:	/* balr	*/
 	case 0x0d:	/* basr */
-		ainsn->fixup = FIXUP_RETURN_REGISTER;
+		fixup = FIXUP_RETURN_REGISTER;
 		/* if r2 = 0, no branch will be taken */
-		if ((*ainsn->insn & 0x0f) == 0)
-			ainsn->fixup |= FIXUP_BRANCH_NOT_TAKEN;
+		if ((insn[0] & 0x0f) == 0)
+			fixup |= FIXUP_BRANCH_NOT_TAKEN;
 		break;
 	case 0x06:	/* bctr	*/
 	case 0x07:	/* bcr	*/
-		ainsn->fixup = FIXUP_BRANCH_NOT_TAKEN;
+		fixup = FIXUP_BRANCH_NOT_TAKEN;
 		break;
 	case 0x45:	/* bal	*/
 	case 0x4d:	/* bas	*/
-		ainsn->fixup = FIXUP_RETURN_REGISTER;
+		fixup = FIXUP_RETURN_REGISTER;
 		break;
 	case 0x47:	/* bc	*/
 	case 0x46:	/* bct	*/
 	case 0x86:	/* bxh	*/
 	case 0x87:	/* bxle	*/
-		ainsn->fixup = FIXUP_BRANCH_NOT_TAKEN;
+		fixup = FIXUP_BRANCH_NOT_TAKEN;
 		break;
 	case 0x82:	/* lpsw	*/
-		ainsn->fixup = FIXUP_NOT_REQUIRED;
+		fixup = FIXUP_NOT_REQUIRED;
 		break;
 	case 0xb2:	/* lpswe */
-		if (*(((__u8 *) ainsn->insn) + 1) == 0xb2) {
-			ainsn->fixup = FIXUP_NOT_REQUIRED;
-		}
+		if ((insn[0] & 0xff) == 0xb2)
+			fixup = FIXUP_NOT_REQUIRED;
 		break;
 	case 0xa7:	/* bras	*/
-		if ((*ainsn->insn & 0x0f) == 0x05) {
-			ainsn->fixup |= FIXUP_RETURN_REGISTER;
-		}
+		if ((insn[0] & 0x0f) == 0x05)
+			fixup |= FIXUP_RETURN_REGISTER;
 		break;
 	case 0xc0:
-		if ((*ainsn->insn & 0x0f) == 0x00  /* larl  */
-			|| (*ainsn->insn & 0x0f) == 0x05) /* brasl */
-		ainsn->fixup |= FIXUP_RETURN_REGISTER;
+		if ((insn[0] & 0x0f) == 0x00 ||	/* larl  */
+		    (insn[0] & 0x0f) == 0x05)	/* brasl */
+		fixup |= FIXUP_RETURN_REGISTER;
 		break;
 	case 0xeb:
-		if (*(((__u8 *) ainsn->insn) + 5 ) == 0x44 ||	/* bxhg  */
-			*(((__u8 *) ainsn->insn) + 5) == 0x45) {/* bxleg */
-			ainsn->fixup = FIXUP_BRANCH_NOT_TAKEN;
-		}
+		if ((insn[2] & 0xff) == 0x44 ||	/* bxhg  */
+		    (insn[2] & 0xff) == 0x45)	/* bxleg */
+			fixup = FIXUP_BRANCH_NOT_TAKEN;
 		break;
 	case 0xe3:	/* bctg	*/
-		if (*(((__u8 *) ainsn->insn) + 5) == 0x46) {
-			ainsn->fixup = FIXUP_BRANCH_NOT_TAKEN;
-		}
+		if ((insn[2] & 0xff) == 0x46)
+			fixup = FIXUP_BRANCH_NOT_TAKEN;
 		break;
 	}
+	return fixup;
 }
 
+int __kprobes arch_prepare_kprobe(struct kprobe *p)
+{
+	if ((unsigned long) p->addr & 0x01)
+		return -EINVAL;
+
+	/* Make sure the probe isn't going on a difficult instruction */
+	if (is_prohibited_opcode(p->addr))
+		return -EINVAL;
+
+	p->opcode = *p->addr;
+	memcpy(p->ainsn.insn, p->addr, ((p->opcode >> 14) + 3) & -2);
+
+	return 0;
+}
+
+struct ins_replace_args {
+	kprobe_opcode_t *ptr;
+	kprobe_opcode_t opcode;
+};
+
 static int __kprobes swap_instruction(void *aref)
 {
 	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
 	unsigned long status = kcb->kprobe_status;
 	struct ins_replace_args *args = aref;
-	int rc;
 
 	kcb->kprobe_status = KPROBE_SWAP_INST;
-	rc = probe_kernel_write(args->ptr, &args->new, sizeof(args->new));
+	probe_kernel_write(args->ptr, &args->opcode, sizeof(args->opcode));
 	kcb->kprobe_status = status;
-	return rc;
+	return 0;
 }
 
 void __kprobes arch_arm_kprobe(struct kprobe *p)
@@ -175,8 +154,7 @@ void __kprobes arch_arm_kprobe(struct kp
 	struct ins_replace_args args;
 
 	args.ptr = p->addr;
-	args.old = p->opcode;
-	args.new = BREAKPOINT_INSTRUCTION;
+	args.opcode = BREAKPOINT_INSTRUCTION;
 	stop_machine(swap_instruction, &args, NULL);
 }
 
@@ -185,64 +163,69 @@ void __kprobes arch_disarm_kprobe(struct
 	struct ins_replace_args args;
 
 	args.ptr = p->addr;
-	args.old = BREAKPOINT_INSTRUCTION;
-	args.new = p->opcode;
+	args.opcode = p->opcode;
 	stop_machine(swap_instruction, &args, NULL);
 }
 
 void __kprobes arch_remove_kprobe(struct kprobe *p)
 {
-	if (p->ainsn.insn) {
-		free_insn_slot(p->ainsn.insn, 0);
-		p->ainsn.insn = NULL;
-	}
 }
 
-static void __kprobes prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
+static void __kprobes enable_singlestep(struct kprobe_ctlblk *kcb,
+					struct pt_regs *regs,
+					unsigned long ip)
 {
-	per_cr_bits kprobe_per_regs[1];
+	struct per_regs per_kprobe;
 
-	memset(kprobe_per_regs, 0, sizeof(per_cr_bits));
-	regs->psw.addr = (unsigned long)p->ainsn.insn | PSW_ADDR_AMODE;
+	/* Set up the PER control registers %cr9-%cr11 */
+	per_kprobe.control = PER_EVENT_IFETCH;
+	per_kprobe.start = ip;
+	per_kprobe.end = ip;
 
-	/* Set up the per control reg info, will pass to lctl */
-	kprobe_per_regs[0].em_instruction_fetch = 1;
-	kprobe_per_regs[0].starting_addr = (unsigned long)p->ainsn.insn;
-	kprobe_per_regs[0].ending_addr = (unsigned long)p->ainsn.insn + 1;
+	/* Save control regs and psw mask */
+	__ctl_store(kcb->kprobe_saved_ctl, 9, 11);
+	kcb->kprobe_saved_imask = regs->psw.mask &
+		(PSW_MASK_PER | PSW_MASK_IO | PSW_MASK_EXT);
 
-	/* Set the PER control regs, turns on single step for this address */
-	__ctl_load(kprobe_per_regs, 9, 11);
+	/* Set PER control regs, turns on single step for the given address */
+	__ctl_load(per_kprobe, 9, 11);
 	regs->psw.mask |= PSW_MASK_PER;
 	regs->psw.mask &= ~(PSW_MASK_IO | PSW_MASK_EXT);
+	regs->psw.addr = ip | PSW_ADDR_AMODE;
 }
 
-static void __kprobes save_previous_kprobe(struct kprobe_ctlblk *kcb)
+static void __kprobes disable_singlestep(struct kprobe_ctlblk *kcb,
+					 struct pt_regs *regs,
+					 unsigned long ip)
 {
-	kcb->prev_kprobe.kp = kprobe_running();
-	kcb->prev_kprobe.status = kcb->kprobe_status;
-	kcb->prev_kprobe.kprobe_saved_imask = kcb->kprobe_saved_imask;
-	memcpy(kcb->prev_kprobe.kprobe_saved_ctl, kcb->kprobe_saved_ctl,
-					sizeof(kcb->kprobe_saved_ctl));
+	/* Restore control regs and psw mask, set new psw address */
+	__ctl_load(kcb->kprobe_saved_ctl, 9, 11);
+	regs->psw.mask &= ~PSW_MASK_PER;
+	regs->psw.mask |= kcb->kprobe_saved_imask;
+	regs->psw.addr = ip | PSW_ADDR_AMODE;
 }
 
-static void __kprobes restore_previous_kprobe(struct kprobe_ctlblk *kcb)
+/*
+ * Activate a kprobe by storing its pointer to current_kprobe. The
+ * previous kprobe is stored in kcb->prev_kprobe. A stack of up to
+ * two kprobes can be active, see KPROBE_REENTER.
+ */
+static void __kprobes push_kprobe(struct kprobe_ctlblk *kcb, struct kprobe *p)
 {
-	__get_cpu_var(current_kprobe) = kcb->prev_kprobe.kp;
-	kcb->kprobe_status = kcb->prev_kprobe.status;
-	kcb->kprobe_saved_imask = kcb->prev_kprobe.kprobe_saved_imask;
-	memcpy(kcb->kprobe_saved_ctl, kcb->prev_kprobe.kprobe_saved_ctl,
-					sizeof(kcb->kprobe_saved_ctl));
+	kcb->prev_kprobe.kp = __get_cpu_var(current_kprobe);
+	kcb->prev_kprobe.status = kcb->kprobe_status;
+	__get_cpu_var(current_kprobe) = p;
 }
 
-static void __kprobes set_current_kprobe(struct kprobe *p, struct pt_regs *regs,
-						struct kprobe_ctlblk *kcb)
+/*
+ * Deactivate a kprobe by backing up to the previous state. If the
+ * current state is KPROBE_REENTER prev_kprobe.kp will be non-NULL,
+ * for any other state prev_kprobe.kp will be NULL.
+ */
+static void __kprobes pop_kprobe(struct kprobe_ctlblk *kcb)
 {
-	__get_cpu_var(current_kprobe) = p;
-	/* Save the interrupt and per flags */
-	kcb->kprobe_saved_imask = regs->psw.mask &
-		(PSW_MASK_PER | PSW_MASK_IO | PSW_MASK_EXT);
-	/* Save the control regs that govern PER */
-	__ctl_store(kcb->kprobe_saved_ctl, 9, 11);
+	__get_cpu_var(current_kprobe) = kcb->prev_kprobe.kp;
+	kcb->kprobe_status = kcb->prev_kprobe.status;
 }
 
 void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri,
@@ -251,79 +234,104 @@ void __kprobes arch_prepare_kretprobe(st
 	ri->ret_addr = (kprobe_opcode_t *) regs->gprs[14];
 
 	/* Replace the return addr with trampoline addr */
-	regs->gprs[14] = (unsigned long)&kretprobe_trampoline;
+	regs->gprs[14] = (unsigned long) &kretprobe_trampoline;
+}
+
+static void __kprobes kprobe_reenter_check(struct kprobe_ctlblk *kcb,
+					   struct kprobe *p)
+{
+	switch (kcb->kprobe_status) {
+	case KPROBE_HIT_SSDONE:
+	case KPROBE_HIT_ACTIVE:
+		kprobes_inc_nmissed_count(p);
+		break;
+	case KPROBE_HIT_SS:
+	case KPROBE_REENTER:
+	default:
+		/*
+		 * A kprobe on the code path to single step an instruction
+		 * is a BUG. The code path resides in the .kprobes.text
+		 * section and is executed with interrupts disabled.
+		 */
+		printk(KERN_EMERG "Invalid kprobe detected at %p.\n", p->addr);
+		dump_kprobe(p);
+		BUG();
+	}
 }
 
 static int __kprobes kprobe_handler(struct pt_regs *regs)
 {
-	struct kprobe *p;
-	int ret = 0;
-	unsigned long *addr = (unsigned long *)
-		((regs->psw.addr & PSW_ADDR_INSN) - 2);
 	struct kprobe_ctlblk *kcb;
+	struct kprobe *p;
 
 	/*
-	 * We don't want to be preempted for the entire
-	 * duration of kprobe processing
+	 * We want to disable preemption for the entire duration of kprobe
+	 * processing. That includes the calls to the pre/post handlers
+	 * and single stepping the kprobe instruction.
 	 */
 	preempt_disable();
 	kcb = get_kprobe_ctlblk();
+	p = get_kprobe((void *)((regs->psw.addr & PSW_ADDR_INSN) - 2));
 
-	/* Check we're not actually recursing */
-	if (kprobe_running()) {
-		p = get_kprobe(addr);
-		if (p) {
-			if (kcb->kprobe_status == KPROBE_HIT_SS &&
-			    *p->ainsn.insn == BREAKPOINT_INSTRUCTION) {
-				regs->psw.mask &= ~PSW_MASK_PER;
-				regs->psw.mask |= kcb->kprobe_saved_imask;
-				goto no_kprobe;
-			}
-			/* We have reentered the kprobe_handler(), since
-			 * another probe was hit while within the handler.
-			 * We here save the original kprobes variables and
-			 * just single step on the instruction of the new probe
-			 * without calling any user handlers.
+	if (p) {
+		if (kprobe_running()) {
+			/*
+			 * We have hit a kprobe while another is still
+			 * active. This can happen in the pre and post
+			 * handler. Single step the instruction of the
+			 * new probe but do not call any handler function
+			 * of this secondary kprobe.
+			 * push_kprobe and pop_kprobe saves and restores
+			 * the currently active kprobe.
 			 */
-			save_previous_kprobe(kcb);
-			set_current_kprobe(p, regs, kcb);
-			kprobes_inc_nmissed_count(p);
-			prepare_singlestep(p, regs);
+			kprobe_reenter_check(kcb, p);
+			push_kprobe(kcb, p);
 			kcb->kprobe_status = KPROBE_REENTER;
-			return 1;
 		} else {
-			p = __get_cpu_var(current_kprobe);
-			if (p->break_handler && p->break_handler(p, regs)) {
-				goto ss_probe;
-			}
+			/*
+			 * If we have no pre-handler or it returned 0, we
+			 * continue with single stepping. If we have a
+			 * pre-handler and it returned non-zero, it prepped
+			 * for calling the break_handler below on re-entry
+			 * for jprobe processing, so get out doing nothing
+			 * more here.
+			 */
+			push_kprobe(kcb, p);
+			kcb->kprobe_status = KPROBE_HIT_ACTIVE;
+			if (p->pre_handler && p->pre_handler(p, regs))
+				return 1;
+			kcb->kprobe_status = KPROBE_HIT_SS;
 		}
-		goto no_kprobe;
-	}
-
-	p = get_kprobe(addr);
-	if (!p)
-		/*
-		 * No kprobe at this address. The fault has not been
-		 * caused by a kprobe breakpoint. The race of breakpoint
-		 * vs. kprobe remove does not exist because on s390 we
-		 * use stop_machine to arm/disarm the breakpoints.
-		 */
-		goto no_kprobe;
-
-	kcb->kprobe_status = KPROBE_HIT_ACTIVE;
-	set_current_kprobe(p, regs, kcb);
-	if (p->pre_handler && p->pre_handler(p, regs))
-		/* handler has already set things up, so skip ss setup */
+		enable_singlestep(kcb, regs, (unsigned long) p->ainsn.insn);
 		return 1;
-
-ss_probe:
-	prepare_singlestep(p, regs);
-	kcb->kprobe_status = KPROBE_HIT_SS;
-	return 1;
-
-no_kprobe:
+	} else if (kprobe_running()) {
+		p = __get_cpu_var(current_kprobe);
+		if (p->break_handler && p->break_handler(p, regs)) {
+			/*
+			 * Continuation after the jprobe completed and
+			 * caused the jprobe_return trap. The jprobe
+			 * break_handler "returns" to the original
+			 * function that still has the kprobe breakpoint
+			 * installed. We continue with single stepping.
+			 */
+			kcb->kprobe_status = KPROBE_HIT_SS;
+			enable_singlestep(kcb, regs,
+					  (unsigned long) p->ainsn.insn);
+			return 1;
+		} /* else:
+		   * No kprobe at this address and the current kprobe
+		   * has no break handler (no jprobe!). The kernel just
+		   * exploded, let the standard trap handler pick up the
+		   * pieces.
+		   */
+	} /* else:
+	   * No kprobe at this address and no active kprobe. The trap has
+	   * not been caused by a kprobe breakpoint. The race of breakpoint
+	   * vs. kprobe remove does not exist because on s390 as we use
+	   * stop_machine to arm/disarm the breakpoints.
+	   */
 	preempt_enable_no_resched();
-	return ret;
+	return 0;
 }
 
 /*
@@ -344,12 +352,12 @@ static void __used kretprobe_trampoline_
 static int __kprobes trampoline_probe_handler(struct kprobe *p,
 					      struct pt_regs *regs)
 {
-	struct kretprobe_instance *ri = NULL;
+	struct kretprobe_instance *ri;
 	struct hlist_head *head, empty_rp;
 	struct hlist_node *node, *tmp;
-	unsigned long flags, orig_ret_address = 0;
-	unsigned long trampoline_address = (unsigned long)&kretprobe_trampoline;
-	kprobe_opcode_t *correct_ret_addr = NULL;
+	unsigned long flags, orig_ret_address;
+	unsigned long trampoline_address;
+	kprobe_opcode_t *correct_ret_addr;
 
 	INIT_HLIST_HEAD(&empty_rp);
 	kretprobe_hash_lock(current, &head, &flags);
@@ -367,12 +375,16 @@ static int __kprobes trampoline_probe_ha
 	 *	 real return address, and all the rest will point to
 	 *	 kretprobe_trampoline
 	 */
+	ri = NULL;
+	orig_ret_address = 0;
+	correct_ret_addr = NULL;
+	trampoline_address = (unsigned long) &kretprobe_trampoline;
 	hlist_for_each_entry_safe(ri, node, tmp, head, hlist) {
 		if (ri->task != current)
 			/* another task is sharing our hash bucket */
 			continue;
 
-		orig_ret_address = (unsigned long)ri->ret_addr;
+		orig_ret_address = (unsigned long) ri->ret_addr;
 
 		if (orig_ret_address != trampoline_address)
 			/*
@@ -391,7 +403,7 @@ static int __kprobes trampoline_probe_ha
 			/* another task is sharing our hash bucket */
 			continue;
 
-		orig_ret_address = (unsigned long)ri->ret_addr;
+		orig_ret_address = (unsigned long) ri->ret_addr;
 
 		if (ri->rp && ri->rp->handler) {
 			ri->ret_addr = correct_ret_addr;
@@ -400,19 +412,18 @@ static int __kprobes trampoline_probe_ha
 
 		recycle_rp_inst(ri, &empty_rp);
 
-		if (orig_ret_address != trampoline_address) {
+		if (orig_ret_address != trampoline_address)
 			/*
 			 * This is the real return address. Any other
 			 * instances associated with this task are for
 			 * other calls deeper on the call stack
 			 */
 			break;
-		}
 	}
 
 	regs->psw.addr = orig_ret_address | PSW_ADDR_AMODE;
 
-	reset_current_kprobe();
+	pop_kprobe(get_kprobe_ctlblk());
 	kretprobe_hash_unlock(current, &flags);
 	preempt_enable_no_resched();
 
@@ -439,55 +450,42 @@ static int __kprobes trampoline_probe_ha
 static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs)
 {
 	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
+	unsigned long ip = regs->psw.addr & PSW_ADDR_INSN;
+	int fixup = get_fixup_type(p->ainsn.insn);
 
-	regs->psw.addr &= PSW_ADDR_INSN;
-
-	if (p->ainsn.fixup & FIXUP_PSW_NORMAL)
-		regs->psw.addr = (unsigned long)p->addr +
-				((unsigned long)regs->psw.addr -
-				 (unsigned long)p->ainsn.insn);
+	if (fixup & FIXUP_PSW_NORMAL)
+		ip += (unsigned long) p->addr - (unsigned long) p->ainsn.insn;
 
-	if (p->ainsn.fixup & FIXUP_BRANCH_NOT_TAKEN)
-		if ((unsigned long)regs->psw.addr -
-		    (unsigned long)p->ainsn.insn == p->ainsn.ilen)
-			regs->psw.addr = (unsigned long)p->addr + p->ainsn.ilen;
+	if (fixup & FIXUP_BRANCH_NOT_TAKEN) {
+		int ilen = ((p->ainsn.insn[0] >> 14) + 3) & -2;
+		if (ip - (unsigned long) p->ainsn.insn == ilen)
+			ip = (unsigned long) p->addr + ilen;
+	}
 
-	if (p->ainsn.fixup & FIXUP_RETURN_REGISTER)
-		regs->gprs[p->ainsn.reg] = ((unsigned long)p->addr +
-						(regs->gprs[p->ainsn.reg] -
-						(unsigned long)p->ainsn.insn))
-						| PSW_ADDR_AMODE;
+	if (fixup & FIXUP_RETURN_REGISTER) {
+		int reg = (p->ainsn.insn[0] & 0xf0) >> 4;
+		regs->gprs[reg] += (unsigned long) p->addr -
+				   (unsigned long) p->ainsn.insn;
+	}
 
-	regs->psw.addr |= PSW_ADDR_AMODE;
-	/* turn off PER mode */
-	regs->psw.mask &= ~PSW_MASK_PER;
-	/* Restore the original per control regs */
-	__ctl_load(kcb->kprobe_saved_ctl, 9, 11);
-	regs->psw.mask |= kcb->kprobe_saved_imask;
+	disable_singlestep(kcb, regs, ip);
 }
 
 static int __kprobes post_kprobe_handler(struct pt_regs *regs)
 {
-	struct kprobe *cur = kprobe_running();
 	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
+	struct kprobe *p = kprobe_running();
 
-	if (!cur)
+	if (!p)
 		return 0;
 
-	if ((kcb->kprobe_status != KPROBE_REENTER) && cur->post_handler) {
+	if (kcb->kprobe_status != KPROBE_REENTER && p->post_handler) {
 		kcb->kprobe_status = KPROBE_HIT_SSDONE;
-		cur->post_handler(cur, regs, 0);
+		p->post_handler(p, regs, 0);
 	}
 
-	resume_execution(cur, regs);
-
-	/*Restore back the original saved kprobes variables and continue. */
-	if (kcb->kprobe_status == KPROBE_REENTER) {
-		restore_previous_kprobe(kcb);
-		goto out;
-	}
-	reset_current_kprobe();
-out:
+	resume_execution(p, regs);
+	pop_kprobe(kcb);
 	preempt_enable_no_resched();
 
 	/*
@@ -495,17 +493,16 @@ out:
 	 * will have PER set, in which case, continue the remaining processing
 	 * of do_single_step, as if this is not a probe hit.
 	 */
-	if (regs->psw.mask & PSW_MASK_PER) {
+	if (regs->psw.mask & PSW_MASK_PER)
 		return 0;
-	}
 
 	return 1;
 }
 
 static int __kprobes kprobe_trap_handler(struct pt_regs *regs, int trapnr)
 {
-	struct kprobe *cur = kprobe_running();
 	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
+	struct kprobe *p = kprobe_running();
 	const struct exception_table_entry *entry;
 
 	switch(kcb->kprobe_status) {
@@ -521,14 +518,8 @@ static int __kprobes kprobe_trap_handler
 		 * and allow the page fault handler to continue as a
 		 * normal page fault.
 		 */
-		regs->psw.addr = (unsigned long)cur->addr | PSW_ADDR_AMODE;
-		regs->psw.mask &= ~PSW_MASK_PER;
-		regs->psw.mask |= kcb->kprobe_saved_imask;
-		if (kcb->kprobe_status == KPROBE_REENTER)
-			restore_previous_kprobe(kcb);
-		else {
-			reset_current_kprobe();
-		}
+		disable_singlestep(kcb, regs, (unsigned long) p->addr);
+		pop_kprobe(kcb);
 		preempt_enable_no_resched();
 		break;
 	case KPROBE_HIT_ACTIVE:
@@ -538,7 +529,7 @@ static int __kprobes kprobe_trap_handler
 		 * we can also use npre/npostfault count for accouting
 		 * these specific fault cases.
 		 */
-		kprobes_inc_nmissed_count(cur);
+		kprobes_inc_nmissed_count(p);
 
 		/*
 		 * We come here because instructions in the pre/post
@@ -547,7 +538,7 @@ static int __kprobes kprobe_trap_handler
 		 * copy_from_user(), get_user() etc. Let the
 		 * user-specified handler try to fix it first.
 		 */
-		if (cur->fault_handler && cur->fault_handler(cur, regs, trapnr))
+		if (p->fault_handler && p->fault_handler(p, regs, trapnr))
 			return 1;
 
 		/*
@@ -589,7 +580,7 @@ int __kprobes kprobe_fault_handler(struc
 int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
 				       unsigned long val, void *data)
 {
-	struct die_args *args = (struct die_args *)data;
+	struct die_args *args = (struct die_args *) data;
 	struct pt_regs *regs = args->regs;
 	int ret = NOTIFY_DONE;
 
@@ -598,16 +589,16 @@ int __kprobes kprobe_exceptions_notify(s
 
 	switch (val) {
 	case DIE_BPT:
-		if (kprobe_handler(args->regs))
+		if (kprobe_handler(regs))
 			ret = NOTIFY_STOP;
 		break;
 	case DIE_SSTEP:
-		if (post_kprobe_handler(args->regs))
+		if (post_kprobe_handler(regs))
 			ret = NOTIFY_STOP;
 		break;
 	case DIE_TRAP:
 		if (!preemptible() && kprobe_running() &&
-		    kprobe_trap_handler(args->regs, args->trapnr))
+		    kprobe_trap_handler(regs, args->trapnr))
 			ret = NOTIFY_STOP;
 		break;
 	default:
@@ -623,23 +614,19 @@ int __kprobes kprobe_exceptions_notify(s
 int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
 {
 	struct jprobe *jp = container_of(p, struct jprobe, kp);
-	unsigned long addr;
 	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
+	unsigned long stack;
 
 	memcpy(&kcb->jprobe_saved_regs, regs, sizeof(struct pt_regs));
 
 	/* setup return addr to the jprobe handler routine */
-	regs->psw.addr = (unsigned long)(jp->entry) | PSW_ADDR_AMODE;
+	regs->psw.addr = (unsigned long) jp->entry | PSW_ADDR_AMODE;
 	regs->psw.mask &= ~(PSW_MASK_IO | PSW_MASK_EXT);
 
-	/* r14 is the function return address */
-	kcb->jprobe_saved_r14 = (unsigned long)regs->gprs[14];
 	/* r15 is the stack pointer */
-	kcb->jprobe_saved_r15 = (unsigned long)regs->gprs[15];
-	addr = (unsigned long)kcb->jprobe_saved_r15;
+	stack = (unsigned long) regs->gprs[15];
 
-	memcpy(kcb->jprobes_stack, (kprobe_opcode_t *) addr,
-	       MIN_STACK_SIZE(addr));
+	memcpy(kcb->jprobes_stack, (void *) stack, MIN_STACK_SIZE(stack));
 	return 1;
 }
 
@@ -656,30 +643,29 @@ void __kprobes jprobe_return_end(void)
 int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
 {
 	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
-	unsigned long stack_addr = (unsigned long)(kcb->jprobe_saved_r15);
+	unsigned long stack;
+
+	stack = (unsigned long) kcb->jprobe_saved_regs.gprs[15];
 
 	/* Put the regs back */
 	memcpy(regs, &kcb->jprobe_saved_regs, sizeof(struct pt_regs));
 	/* put the stack back */
-	memcpy((kprobe_opcode_t *) stack_addr, kcb->jprobes_stack,
-	       MIN_STACK_SIZE(stack_addr));
+	memcpy((void *) stack, kcb->jprobes_stack, MIN_STACK_SIZE(stack));
 	preempt_enable_no_resched();
 	return 1;
 }
 
-static struct kprobe trampoline_p = {
-	.addr = (kprobe_opcode_t *) & kretprobe_trampoline,
+static struct kprobe trampoline = {
+	.addr = (kprobe_opcode_t *) &kretprobe_trampoline,
 	.pre_handler = trampoline_probe_handler
 };
 
 int __init arch_init_kprobes(void)
 {
-	return register_kprobe(&trampoline_p);
+	return register_kprobe(&trampoline);
 }
 
 int __kprobes arch_trampoline_kprobe(struct kprobe *p)
 {
-	if (p->addr == (kprobe_opcode_t *) & kretprobe_trampoline)
-		return 1;
-	return 0;
+	return p->addr == (kprobe_opcode_t *) &kretprobe_trampoline;
 }
diff -druNp linux-libre-2.6.37-gnu1/arch/s390/kernel/mcount64.S linux-libre-2.6.38-gnu1/arch/s390/kernel/mcount64.S
--- linux-libre-2.6.37-gnu1/arch/s390/kernel/mcount64.S	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/s390/kernel/mcount64.S	2011-03-14 21:20:32.000000000 -0400
@@ -7,6 +7,8 @@
 
 #include <asm/asm-offsets.h>
 
+	.section .kprobes.text, "ax"
+
 	.globl ftrace_stub
 ftrace_stub:
 	br	%r14
@@ -16,12 +18,6 @@ _mcount:
 #ifdef CONFIG_DYNAMIC_FTRACE
 	br	%r14
 
-	.data
-	.globl	ftrace_dyn_func
-ftrace_dyn_func:
-	.quad	ftrace_stub
-	.previous
-
 	.globl ftrace_caller
 ftrace_caller:
 #endif
@@ -35,26 +31,19 @@ ftrace_caller:
 	stg	%r1,__SF_BACKCHAIN(%r15)
 	lgr	%r2,%r14
 	lg	%r3,168(%r15)
-#ifdef CONFIG_DYNAMIC_FTRACE
-	larl	%r14,ftrace_dyn_func
-#else
 	larl	%r14,ftrace_trace_function
-#endif
 	lg	%r14,0(%r14)
 	basr	%r14,%r14
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
-#ifdef CONFIG_DYNAMIC_FTRACE
+	lg	%r2,168(%r15)
+	lg	%r3,272(%r15)
 	.globl	ftrace_graph_caller
 ftrace_graph_caller:
-	# This unconditional branch gets runtime patched. Change only if
-	# you know what you are doing. See ftrace_enable_graph_caller().
-	j	0f
-#endif
-	lg	%r2,272(%r15)
-	lg	%r3,168(%r15)
-	brasl	%r14,prepare_ftrace_return
-	stg	%r2,168(%r15)
-0:
+# The bras instruction gets runtime patched to call prepare_ftrace_return.
+# See ftrace_enable_ftrace_graph_caller. The patched instruction is:
+#	bras	%r14,prepare_ftrace_return
+	bras	%r14,0f
+0:	stg	%r2,168(%r15)
 #endif
 	aghi	%r15,160
 	lmg	%r2,%r5,32(%r15)
diff -druNp linux-libre-2.6.37-gnu1/arch/s390/kernel/mcount.S linux-libre-2.6.38-gnu1/arch/s390/kernel/mcount.S
--- linux-libre-2.6.37-gnu1/arch/s390/kernel/mcount.S	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/s390/kernel/mcount.S	2011-03-14 21:20:32.000000000 -0400
@@ -7,6 +7,8 @@
 
 #include <asm/asm-offsets.h>
 
+	.section .kprobes.text, "ax"
+
 	.globl ftrace_stub
 ftrace_stub:
 	br	%r14
@@ -16,22 +18,12 @@ _mcount:
 #ifdef CONFIG_DYNAMIC_FTRACE
 	br	%r14
 
-	.data
-	.globl	ftrace_dyn_func
-ftrace_dyn_func:
-	.long	ftrace_stub
-	.previous
-
 	.globl ftrace_caller
 ftrace_caller:
 #endif
 	stm	%r2,%r5,16(%r15)
 	bras	%r1,2f
-#ifdef CONFIG_DYNAMIC_FTRACE
-0:	.long	ftrace_dyn_func
-#else
 0:	.long	ftrace_trace_function
-#endif
 1:	.long	function_trace_stop
 2:	l	%r2,1b-0b(%r1)
 	icm	%r2,0xf,0(%r2)
@@ -47,21 +39,15 @@ ftrace_caller:
 	l	%r14,0(%r14)
 	basr	%r14,%r14
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
-#ifdef CONFIG_DYNAMIC_FTRACE
+	l	%r2,100(%r15)
+	l	%r3,152(%r15)
 	.globl	ftrace_graph_caller
 ftrace_graph_caller:
-	# This unconditional branch gets runtime patched. Change only if
-	# you know what you are doing. See ftrace_enable_graph_caller().
-	j	1f
-#endif
-	bras	%r1,0f
-	.long	prepare_ftrace_return
-0:	l	%r2,152(%r15)
-	l	%r4,0(%r1)
-	l	%r3,100(%r15)
-	basr	%r14,%r4
-	st	%r2,100(%r15)
-1:
+# The bras instruction gets runtime patched to call prepare_ftrace_return.
+# See ftrace_enable_ftrace_graph_caller. The patched instruction is:
+#	bras	%r14,prepare_ftrace_return
+	bras	%r14,0f
+0:	st	%r2,100(%r15)
 #endif
 	ahi	%r15,96
 	l	%r14,56(%r15)
diff -druNp linux-libre-2.6.37-gnu1/arch/s390/kernel/nmi.c linux-libre-2.6.38-gnu1/arch/s390/kernel/nmi.c
--- linux-libre-2.6.37-gnu1/arch/s390/kernel/nmi.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/s390/kernel/nmi.c	2011-03-14 21:20:32.000000000 -0400
@@ -8,6 +8,7 @@
  *		 Heiko Carstens <heiko.carstens@de.ibm.com>,
  */
 
+#include <linux/kernel_stat.h>
 #include <linux/init.h>
 #include <linux/errno.h>
 #include <linux/hardirq.h>
@@ -255,7 +256,7 @@ void notrace s390_do_machine_check(struc
 	nmi_enter();
 	s390_idle_check(regs, S390_lowcore.mcck_clock,
 			S390_lowcore.mcck_enter_timer);
-
+	kstat_cpu(smp_processor_id()).irqs[NMI_NMI]++;
 	mci = (struct mci *) &S390_lowcore.mcck_interruption_code;
 	mcck = &__get_cpu_var(cpu_mcck);
 	umode = user_mode(regs);
diff -druNp linux-libre-2.6.37-gnu1/arch/s390/kernel/process.c linux-libre-2.6.38-gnu1/arch/s390/kernel/process.c
--- linux-libre-2.6.37-gnu1/arch/s390/kernel/process.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/s390/kernel/process.c	2011-03-14 21:20:32.000000000 -0400
@@ -30,8 +30,11 @@
 #include <linux/tick.h>
 #include <linux/elfcore.h>
 #include <linux/kernel_stat.h>
+#include <linux/personality.h>
 #include <linux/syscalls.h>
 #include <linux/compat.h>
+#include <linux/kprobes.h>
+#include <linux/random.h>
 #include <asm/compat.h>
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
@@ -41,6 +44,7 @@
 #include <asm/irq.h>
 #include <asm/timer.h>
 #include <asm/nmi.h>
+#include <asm/smp.h>
 #include "entry.h"
 
 asmlinkage void ret_from_fork(void) asm ("ret_from_fork");
@@ -75,13 +79,8 @@ unsigned long thread_saved_pc(struct tas
  */
 static void default_idle(void)
 {
-	/* CPU is going idle. */
-#ifdef CONFIG_HOTPLUG_CPU
-	if (cpu_is_offline(smp_processor_id())) {
-		preempt_enable_no_resched();
+	if (cpu_is_offline(smp_processor_id()))
 		cpu_die();
-	}
-#endif
 	local_irq_disable();
 	if (need_resched()) {
 		local_irq_enable();
@@ -116,15 +115,17 @@ void cpu_idle(void)
 	}
 }
 
-extern void kernel_thread_starter(void);
+extern void __kprobes kernel_thread_starter(void);
 
 asm(
-	".align 4\n"
+	".section .kprobes.text, \"ax\"\n"
+	".global kernel_thread_starter\n"
 	"kernel_thread_starter:\n"
 	"    la    2,0(10)\n"
 	"    basr  14,9\n"
 	"    la    2,0\n"
-	"    br    11\n");
+	"    br    11\n"
+	".previous\n");
 
 int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
 {
@@ -214,8 +215,10 @@ int copy_thread(unsigned long clone_flag
 	/* start new process with ar4 pointing to the correct address space */
 	p->thread.mm_segment = get_fs();
 	/* Don't copy debug registers */
-	memset(&p->thread.per_info, 0, sizeof(p->thread.per_info));
+	memset(&p->thread.per_user, 0, sizeof(p->thread.per_user));
+	memset(&p->thread.per_event, 0, sizeof(p->thread.per_event));
 	clear_tsk_thread_flag(p, TIF_SINGLE_STEP);
+	clear_tsk_thread_flag(p, TIF_PER_TRAP);
 	/* Initialize per thread user and system timer values */
 	ti = task_thread_info(p);
 	ti->user_timer = 0;
@@ -331,3 +334,39 @@ unsigned long get_wchan(struct task_stru
 	}
 	return 0;
 }
+
+unsigned long arch_align_stack(unsigned long sp)
+{
+	if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space)
+		sp -= get_random_int() & ~PAGE_MASK;
+	return sp & ~0xf;
+}
+
+static inline unsigned long brk_rnd(void)
+{
+	/* 8MB for 32bit, 1GB for 64bit */
+	if (is_32bit_task())
+		return (get_random_int() & 0x7ffUL) << PAGE_SHIFT;
+	else
+		return (get_random_int() & 0x3ffffUL) << PAGE_SHIFT;
+}
+
+unsigned long arch_randomize_brk(struct mm_struct *mm)
+{
+	unsigned long ret = PAGE_ALIGN(mm->brk + brk_rnd());
+
+	if (ret < mm->brk)
+		return mm->brk;
+	return ret;
+}
+
+unsigned long randomize_et_dyn(unsigned long base)
+{
+	unsigned long ret = PAGE_ALIGN(base + brk_rnd());
+
+	if (!(current->flags & PF_RANDOMIZE))
+		return base;
+	if (ret < base)
+		return base;
+	return ret;
+}
diff -druNp linux-libre-2.6.37-gnu1/arch/s390/kernel/processor.c linux-libre-2.6.38-gnu1/arch/s390/kernel/processor.c
--- linux-libre-2.6.37-gnu1/arch/s390/kernel/processor.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/s390/kernel/processor.c	2011-03-14 21:20:32.000000000 -0400
@@ -13,7 +13,7 @@
 #include <linux/smp.h>
 #include <linux/seq_file.h>
 #include <linux/delay.h>
-
+#include <linux/cpu.h>
 #include <asm/elf.h>
 #include <asm/lowcore.h>
 #include <asm/param.h>
@@ -35,17 +35,6 @@ void __cpuinit cpu_init(void)
 }
 
 /*
- * print_cpu_info - print basic information about a cpu
- */
-void __cpuinit print_cpu_info(void)
-{
-	struct cpuid *id = &per_cpu(cpu_id, smp_processor_id());
-
-	pr_info("Processor %d started, address %d, identification %06X\n",
-		S390_lowcore.cpu_nr, stap(), id->ident);
-}
-
-/*
  * show_cpuinfo - Get information on one CPU for use by procfs.
  */
 static int show_cpuinfo(struct seq_file *m, void *v)
@@ -57,9 +46,8 @@ static int show_cpuinfo(struct seq_file
 	unsigned long n = (unsigned long) v - 1;
 	int i;
 
-	s390_adjust_jiffies();
-	preempt_disable();
 	if (!n) {
+		s390_adjust_jiffies();
 		seq_printf(m, "vendor_id       : IBM/S390\n"
 			   "# processors    : %i\n"
 			   "bogomips per cpu: %lu.%02lu\n",
@@ -71,7 +59,7 @@ static int show_cpuinfo(struct seq_file
 				seq_printf(m, "%s ", hwcap_str[i]);
 		seq_puts(m, "\n");
 	}
-
+	get_online_cpus();
 	if (cpu_online(n)) {
 		struct cpuid *id = &per_cpu(cpu_id, n);
 		seq_printf(m, "processor %li: "
@@ -80,7 +68,7 @@ static int show_cpuinfo(struct seq_file
 			   "machine = %04X\n",
 			   n, id->version, id->ident, id->machine);
 	}
-	preempt_enable();
+	put_online_cpus();
 	return 0;
 }
 
diff -druNp linux-libre-2.6.37-gnu1/arch/s390/kernel/ptrace.c linux-libre-2.6.38-gnu1/arch/s390/kernel/ptrace.c
--- linux-libre-2.6.37-gnu1/arch/s390/kernel/ptrace.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/s390/kernel/ptrace.c	2011-03-14 21:20:32.000000000 -0400
@@ -1,25 +1,9 @@
 /*
- *  arch/s390/kernel/ptrace.c
+ *  Ptrace user space interface.
  *
- *  S390 version
- *    Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
- *    Author(s): Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com),
+ *    Copyright IBM Corp. 1999,2010
+ *    Author(s): Denis Joseph Barrow
  *               Martin Schwidefsky (schwidefsky@de.ibm.com)
- *
- *  Based on PowerPC version 
- *    Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
- *
- *  Derived from "arch/m68k/kernel/ptrace.c"
- *  Copyright (C) 1994 by Hamish Macdonald
- *  Taken from linux/kernel/ptrace.c and modified for M680x0.
- *  linux/kernel/ptrace.c is by Ross Biro 1/23/92, edited by Linus Torvalds
- *
- * Modified by Cort Dougan (cort@cs.nmt.edu) 
- *
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file README.legal in the main directory of
- * this archive for more details.
  */
 
 #include <linux/kernel.h>
@@ -61,76 +45,58 @@ enum s390_regset {
 	REGSET_GENERAL_EXTENDED,
 };
 
-static void
-FixPerRegisters(struct task_struct *task)
+void update_per_regs(struct task_struct *task)
 {
-	struct pt_regs *regs;
-	per_struct *per_info;
-	per_cr_words cr_words;
-
-	regs = task_pt_regs(task);
-	per_info = (per_struct *) &task->thread.per_info;
-	per_info->control_regs.bits.em_instruction_fetch =
-		per_info->single_step | per_info->instruction_fetch;
-	
-	if (per_info->single_step) {
-		per_info->control_regs.bits.starting_addr = 0;
-#ifdef CONFIG_COMPAT
-		if (is_compat_task())
-			per_info->control_regs.bits.ending_addr = 0x7fffffffUL;
-		else
-#endif
-			per_info->control_regs.bits.ending_addr = PSW_ADDR_INSN;
-	} else {
-		per_info->control_regs.bits.starting_addr =
-			per_info->starting_addr;
-		per_info->control_regs.bits.ending_addr =
-			per_info->ending_addr;
-	}
-	/*
-	 * if any of the control reg tracing bits are on 
-	 * we switch on per in the psw
-	 */
-	if (per_info->control_regs.words.cr[0] & PER_EM_MASK)
-		regs->psw.mask |= PSW_MASK_PER;
-	else
-		regs->psw.mask &= ~PSW_MASK_PER;
+	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;
 
-	if (per_info->control_regs.bits.em_storage_alteration)
-		per_info->control_regs.bits.storage_alt_space_ctl = 1;
-	else
-		per_info->control_regs.bits.storage_alt_space_ctl = 0;
+	/* TIF_SINGLE_STEP overrides the user specified PER registers. */
+	new = test_tsk_thread_flag(task, TIF_SINGLE_STEP) ?
+		&per_single_step : &thread->per_user;
 
-	if (task == current) {
-		__ctl_store(cr_words, 9, 11);
-		if (memcmp(&cr_words, &per_info->control_regs.words,
-			   sizeof(cr_words)) != 0)
-			__ctl_load(per_info->control_regs.words, 9, 11);
+	/* Take care of the PER enablement bit in the PSW. */
+	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);
 }
 
 void user_enable_single_step(struct task_struct *task)
 {
-	task->thread.per_info.single_step = 1;
-	FixPerRegisters(task);
+	set_tsk_thread_flag(task, TIF_SINGLE_STEP);
+	if (task == current)
+		update_per_regs(task);
 }
 
 void user_disable_single_step(struct task_struct *task)
 {
-	task->thread.per_info.single_step = 0;
-	FixPerRegisters(task);
+	clear_tsk_thread_flag(task, TIF_SINGLE_STEP);
+	if (task == current)
+		update_per_regs(task);
 }
 
 /*
  * Called by kernel/ptrace.c when detaching..
  *
- * Make sure single step bits etc are not set.
+ * Clear all debugging related fields.
  */
-void
-ptrace_disable(struct task_struct *child)
+void ptrace_disable(struct task_struct *task)
 {
-	/* make sure the single step bit is not set. */
-	user_disable_single_step(child);
+	memset(&task->thread.per_user, 0, sizeof(task->thread.per_user));
+	memset(&task->thread.per_event, 0, sizeof(task->thread.per_event));
+	clear_tsk_thread_flag(task, TIF_SINGLE_STEP);
+	clear_tsk_thread_flag(task, TIF_PER_TRAP);
 }
 
 #ifndef CONFIG_64BIT
@@ -139,6 +105,47 @@ ptrace_disable(struct task_struct *child
 # define __ADDR_MASK 7
 #endif
 
+static inline unsigned long __peek_user_per(struct task_struct *child,
+					    addr_t addr)
+{
+	struct per_struct_kernel *dummy = NULL;
+
+	if (addr == (addr_t) &dummy->cr9)
+		/* Control bits of the active per set. */
+		return test_thread_flag(TIF_SINGLE_STEP) ?
+			PER_EVENT_IFETCH : child->thread.per_user.control;
+	else if (addr == (addr_t) &dummy->cr10)
+		/* Start address of the active per set. */
+		return test_thread_flag(TIF_SINGLE_STEP) ?
+			0 : child->thread.per_user.start;
+	else if (addr == (addr_t) &dummy->cr11)
+		/* End address of the active per set. */
+		return test_thread_flag(TIF_SINGLE_STEP) ?
+			PSW_ADDR_INSN : child->thread.per_user.end;
+	else if (addr == (addr_t) &dummy->bits)
+		/* Single-step bit. */
+		return test_thread_flag(TIF_SINGLE_STEP) ?
+			(1UL << (BITS_PER_LONG - 1)) : 0;
+	else if (addr == (addr_t) &dummy->starting_addr)
+		/* Start address of the user specified per set. */
+		return child->thread.per_user.start;
+	else if (addr == (addr_t) &dummy->ending_addr)
+		/* End address of the user specified per set. */
+		return child->thread.per_user.end;
+	else if (addr == (addr_t) &dummy->perc_atmid)
+		/* PER code, ATMID and AI of the last PER trap */
+		return (unsigned long)
+			child->thread.per_event.cause << (BITS_PER_LONG - 16);
+	else if (addr == (addr_t) &dummy->address)
+		/* Address of the last PER trap */
+		return child->thread.per_event.address;
+	else if (addr == (addr_t) &dummy->access_id)
+		/* Access id of the last PER trap */
+		return (unsigned long)
+			child->thread.per_event.paid << (BITS_PER_LONG - 8);
+	return 0;
+}
+
 /*
  * Read the word at offset addr from the user area of a process. The
  * trouble here is that the information is littered over different
@@ -204,10 +211,10 @@ static unsigned long __peek_user(struct
 
 	} else if (addr < (addr_t) (&dummy->regs.per_info + 1)) {
 		/*
-		 * per_info is found in the thread structure
+		 * Handle access to the per_info structure.
 		 */
-		offset = addr - (addr_t) &dummy->regs.per_info;
-		tmp = *(addr_t *)((addr_t) &child->thread.per_info + offset);
+		addr -= (addr_t) &dummy->regs.per_info;
+		tmp = __peek_user_per(child, addr);
 
 	} else
 		tmp = 0;
@@ -237,6 +244,35 @@ peek_user(struct task_struct *child, add
 	return put_user(tmp, (addr_t __user *) data);
 }
 
+static inline void __poke_user_per(struct task_struct *child,
+				   addr_t addr, addr_t data)
+{
+	struct per_struct_kernel *dummy = NULL;
+
+	/*
+	 * There are only three fields in the per_info struct that the
+	 * debugger user can write to.
+	 * 1) cr9: the debugger wants to set a new PER event mask
+	 * 2) starting_addr: the debugger wants to set a new starting
+	 *    address to use with the PER event mask.
+	 * 3) ending_addr: the debugger wants to set a new ending
+	 *    address to use with the PER event mask.
+	 * The user specified PER event mask and the start and end
+	 * addresses are used only if single stepping is not in effect.
+	 * Writes to any other field in per_info are ignored.
+	 */
+	if (addr == (addr_t) &dummy->cr9)
+		/* PER event mask of the user specified per set. */
+		child->thread.per_user.control =
+			data & (PER_EVENT_MASK | PER_CONTROL_MASK);
+	else if (addr == (addr_t) &dummy->starting_addr)
+		/* Starting address of the user specified per set. */
+		child->thread.per_user.start = data;
+	else if (addr == (addr_t) &dummy->ending_addr)
+		/* Ending address of the user specified per set. */
+		child->thread.per_user.end = data;
+}
+
 /*
  * Write a word to the user area of a process at location addr. This
  * operation does have an additional problem compared to peek_user.
@@ -311,19 +347,17 @@ static int __poke_user(struct task_struc
 
 	} else if (addr < (addr_t) (&dummy->regs.per_info + 1)) {
 		/*
-		 * per_info is found in the thread structure 
+		 * Handle access to the per_info structure.
 		 */
-		offset = addr - (addr_t) &dummy->regs.per_info;
-		*(addr_t *)((addr_t) &child->thread.per_info + offset) = data;
+		addr -= (addr_t) &dummy->regs.per_info;
+		__poke_user_per(child, addr, data);
 
 	}
 
-	FixPerRegisters(child);
 	return 0;
 }
 
-static int
-poke_user(struct task_struct *child, addr_t addr, addr_t data)
+static int poke_user(struct task_struct *child, addr_t addr, addr_t data)
 {
 	addr_t mask;
 
@@ -410,12 +444,53 @@ long arch_ptrace(struct task_struct *chi
  */
 
 /*
+ * Same as peek_user_per but for a 31 bit program.
+ */
+static inline __u32 __peek_user_per_compat(struct task_struct *child,
+					   addr_t addr)
+{
+	struct compat_per_struct_kernel *dummy32 = NULL;
+
+	if (addr == (addr_t) &dummy32->cr9)
+		/* Control bits of the active per set. */
+		return (__u32) test_thread_flag(TIF_SINGLE_STEP) ?
+			PER_EVENT_IFETCH : child->thread.per_user.control;
+	else if (addr == (addr_t) &dummy32->cr10)
+		/* Start address of the active per set. */
+		return (__u32) test_thread_flag(TIF_SINGLE_STEP) ?
+			0 : child->thread.per_user.start;
+	else if (addr == (addr_t) &dummy32->cr11)
+		/* End address of the active per set. */
+		return test_thread_flag(TIF_SINGLE_STEP) ?
+			PSW32_ADDR_INSN : child->thread.per_user.end;
+	else if (addr == (addr_t) &dummy32->bits)
+		/* Single-step bit. */
+		return (__u32) test_thread_flag(TIF_SINGLE_STEP) ?
+			0x80000000 : 0;
+	else if (addr == (addr_t) &dummy32->starting_addr)
+		/* Start address of the user specified per set. */
+		return (__u32) child->thread.per_user.start;
+	else if (addr == (addr_t) &dummy32->ending_addr)
+		/* End address of the user specified per set. */
+		return (__u32) child->thread.per_user.end;
+	else if (addr == (addr_t) &dummy32->perc_atmid)
+		/* PER code, ATMID and AI of the last PER trap */
+		return (__u32) child->thread.per_event.cause << 16;
+	else if (addr == (addr_t) &dummy32->address)
+		/* Address of the last PER trap */
+		return (__u32) child->thread.per_event.address;
+	else if (addr == (addr_t) &dummy32->access_id)
+		/* Access id of the last PER trap */
+		return (__u32) child->thread.per_event.paid << 24;
+	return 0;
+}
+
+/*
  * Same as peek_user but for a 31 bit program.
  */
 static u32 __peek_user_compat(struct task_struct *child, addr_t addr)
 {
-	struct user32 *dummy32 = NULL;
-	per_struct32 *dummy_per32 = NULL;
+	struct compat_user *dummy32 = NULL;
 	addr_t offset;
 	__u32 tmp;
 
@@ -465,19 +540,10 @@ static u32 __peek_user_compat(struct tas
 
 	} else if (addr < (addr_t) (&dummy32->regs.per_info + 1)) {
 		/*
-		 * per_info is found in the thread structure
+		 * Handle access to the per_info structure.
 		 */
-		offset = addr - (addr_t) &dummy32->regs.per_info;
-		/* This is magic. See per_struct and per_struct32. */
-		if ((offset >= (addr_t) &dummy_per32->control_regs &&
-		     offset < (addr_t) (&dummy_per32->control_regs + 1)) ||
-		    (offset >= (addr_t) &dummy_per32->starting_addr &&
-		     offset <= (addr_t) &dummy_per32->ending_addr) ||
-		    offset == (addr_t) &dummy_per32->lowcore.words.address)
-			offset = offset*2 + 4;
-		else
-			offset = offset*2;
-		tmp = *(__u32 *)((addr_t) &child->thread.per_info + offset);
+		addr -= (addr_t) &dummy32->regs.per_info;
+		tmp = __peek_user_per_compat(child, addr);
 
 	} else
 		tmp = 0;
@@ -498,13 +564,32 @@ static int peek_user_compat(struct task_
 }
 
 /*
+ * Same as poke_user_per but for a 31 bit program.
+ */
+static inline void __poke_user_per_compat(struct task_struct *child,
+					  addr_t addr, __u32 data)
+{
+	struct compat_per_struct_kernel *dummy32 = NULL;
+
+	if (addr == (addr_t) &dummy32->cr9)
+		/* PER event mask of the user specified per set. */
+		child->thread.per_user.control =
+			data & (PER_EVENT_MASK | PER_CONTROL_MASK);
+	else if (addr == (addr_t) &dummy32->starting_addr)
+		/* Starting address of the user specified per set. */
+		child->thread.per_user.start = data;
+	else if (addr == (addr_t) &dummy32->ending_addr)
+		/* Ending address of the user specified per set. */
+		child->thread.per_user.end = data;
+}
+
+/*
  * Same as poke_user but for a 31 bit program.
  */
 static int __poke_user_compat(struct task_struct *child,
 			      addr_t addr, addr_t data)
 {
-	struct user32 *dummy32 = NULL;
-	per_struct32 *dummy_per32 = NULL;
+	struct compat_user *dummy32 = NULL;
 	__u32 tmp = (__u32) data;
 	addr_t offset;
 
@@ -561,37 +646,20 @@ static int __poke_user_compat(struct tas
 
 	} else if (addr < (addr_t) (&dummy32->regs.per_info + 1)) {
 		/*
-		 * per_info is found in the thread structure.
-		 */
-		offset = addr - (addr_t) &dummy32->regs.per_info;
-		/*
-		 * This is magic. See per_struct and per_struct32.
-		 * By incident the offsets in per_struct are exactly
-		 * twice the offsets in per_struct32 for all fields.
-		 * The 8 byte fields need special handling though,
-		 * because the second half (bytes 4-7) is needed and
-		 * not the first half.
+		 * Handle access to the per_info structure.
 		 */
-		if ((offset >= (addr_t) &dummy_per32->control_regs &&
-		     offset < (addr_t) (&dummy_per32->control_regs + 1)) ||
-		    (offset >= (addr_t) &dummy_per32->starting_addr &&
-		     offset <= (addr_t) &dummy_per32->ending_addr) ||
-		    offset == (addr_t) &dummy_per32->lowcore.words.address)
-			offset = offset*2 + 4;
-		else
-			offset = offset*2;
-		*(__u32 *)((addr_t) &child->thread.per_info + offset) = tmp;
-
+		addr -= (addr_t) &dummy32->regs.per_info;
+		__poke_user_per_compat(child, addr, data);
 	}
 
-	FixPerRegisters(child);
 	return 0;
 }
 
 static int poke_user_compat(struct task_struct *child,
 			    addr_t addr, addr_t data)
 {
-	if (!is_compat_task() || (addr & 3) || addr > sizeof(struct user32) - 3)
+	if (!is_compat_task() || (addr & 3) ||
+	    addr > sizeof(struct compat_user) - 3)
 		return -EIO;
 
 	return __poke_user_compat(child, addr, data);
@@ -602,7 +670,7 @@ long compat_arch_ptrace(struct task_stru
 {
 	unsigned long addr = caddr;
 	unsigned long data = cdata;
-	ptrace_area_emu31 parea; 
+	compat_ptrace_area parea;
 	int copied, ret;
 
 	switch (request) {
diff -druNp linux-libre-2.6.37-gnu1/arch/s390/kernel/s390_ext.c linux-libre-2.6.38-gnu1/arch/s390/kernel/s390_ext.c
--- linux-libre-2.6.37-gnu1/arch/s390/kernel/s390_ext.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/s390/kernel/s390_ext.c	2011-03-14 21:20:32.000000000 -0400
@@ -1,33 +1,36 @@
 /*
- *  arch/s390/kernel/s390_ext.c
- *
- *  S390 version
- *    Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
- *    Author(s): Holger Smolinski (Holger.Smolinski@de.ibm.com),
- *               Martin Schwidefsky (schwidefsky@de.ibm.com)
+ *    Copyright IBM Corp. 1999,2010
+ *    Author(s): Holger Smolinski <Holger.Smolinski@de.ibm.com>,
+ *		 Martin Schwidefsky <schwidefsky@de.ibm.com>,
  */
 
+#include <linux/kernel_stat.h>
+#include <linux/interrupt.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/slab.h>
 #include <linux/ftrace.h>
 #include <linux/errno.h>
-#include <linux/kernel_stat.h>
-#include <linux/interrupt.h>
-#include <asm/cputime.h>
-#include <asm/lowcore.h>
+#include <linux/slab.h>
 #include <asm/s390_ext.h>
 #include <asm/irq_regs.h>
+#include <asm/cputime.h>
+#include <asm/lowcore.h>
 #include <asm/irq.h>
 #include "entry.h"
 
+struct ext_int_info {
+	struct ext_int_info *next;
+	ext_int_handler_t handler;
+	__u16 code;
+};
+
 /*
  * ext_int_hash[index] is the start of the list for all external interrupts
  * that hash to this index. With the current set of external interrupts 
  * (0x1202 external call, 0x1004 cpu timer, 0x2401 hwc console, 0x4000
  * iucv and 0x2603 pfault) this is always the first element. 
  */
-ext_int_info_t *ext_int_hash[256] = { NULL, };
+static struct ext_int_info *ext_int_hash[256];
 
 static inline int ext_hash(__u16 code)
 {
@@ -36,90 +39,53 @@ static inline int ext_hash(__u16 code)
 
 int register_external_interrupt(__u16 code, ext_int_handler_t handler)
 {
-        ext_int_info_t *p;
-        int index;
-
-	p = kmalloc(sizeof(ext_int_info_t), GFP_ATOMIC);
-        if (p == NULL)
-                return -ENOMEM;
-        p->code = code;
-        p->handler = handler;
-	index = ext_hash(code);
-        p->next = ext_int_hash[index];
-        ext_int_hash[index] = p;
-        return 0;
-}
-
-int register_early_external_interrupt(__u16 code, ext_int_handler_t handler,
-				      ext_int_info_t *p)
-{
-        int index;
+	struct ext_int_info *p;
+	int index;
 
-        if (p == NULL)
-                return -EINVAL;
-        p->code = code;
-        p->handler = handler;
+	p = kmalloc(sizeof(*p), GFP_ATOMIC);
+	if (!p)
+		return -ENOMEM;
+	p->code = code;
+	p->handler = handler;
 	index = ext_hash(code);
-        p->next = ext_int_hash[index];
-        ext_int_hash[index] = p;
-        return 0;
+	p->next = ext_int_hash[index];
+	ext_int_hash[index] = p;
+	return 0;
 }
+EXPORT_SYMBOL(register_external_interrupt);
 
 int unregister_external_interrupt(__u16 code, ext_int_handler_t handler)
 {
-        ext_int_info_t *p, *q;
-        int index;
-
-	index = ext_hash(code);
-        q = NULL;
-        p = ext_int_hash[index];
-        while (p != NULL) {
-                if (p->code == code && p->handler == handler)
-                        break;
-                q = p;
-                p = p->next;
-        }
-        if (p == NULL)
-                return -ENOENT;
-        if (q != NULL)
-                q->next = p->next;
-        else
-                ext_int_hash[index] = p->next;
-	kfree(p);
-        return 0;
-}
-
-int unregister_early_external_interrupt(__u16 code, ext_int_handler_t handler,
-					ext_int_info_t *p)
-{
-	ext_int_info_t *q;
+	struct ext_int_info *p, *q;
 	int index;
 
-	if (p == NULL || p->code != code || p->handler != handler)
-		return -EINVAL;
 	index = ext_hash(code);
-	q = ext_int_hash[index];
-	if (p != q) {
-		while (q != NULL) {
-			if (q->next == p)
-				break;
-			q = q->next;
-		}
-		if (q == NULL)
-			return -ENOENT;
+	q = NULL;
+	p = ext_int_hash[index];
+	while (p) {
+		if (p->code == code && p->handler == handler)
+			break;
+		q = p;
+		p = p->next;
+	}
+	if (!p)
+		return -ENOENT;
+	if (q)
 		q->next = p->next;
-	} else
+	else
 		ext_int_hash[index] = p->next;
+	kfree(p);
 	return 0;
 }
+EXPORT_SYMBOL(unregister_external_interrupt);
 
 void __irq_entry do_extint(struct pt_regs *regs, unsigned int ext_int_code,
 			   unsigned int param32, unsigned long param64)
 {
 	struct pt_regs *old_regs;
 	unsigned short code;
-        ext_int_info_t *p;
-        int index;
+	struct ext_int_info *p;
+	int index;
 
 	code = (unsigned short) ext_int_code;
 	old_regs = set_irq_regs(regs);
@@ -132,7 +98,7 @@ void __irq_entry do_extint(struct pt_reg
 	kstat_cpu(smp_processor_id()).irqs[EXTERNAL_INTERRUPT]++;
 	if (code != 0x1004)
 		__get_cpu_var(s390_idle).nohz_delay = 1;
-        index = ext_hash(code);
+	index = ext_hash(code);
 	for (p = ext_int_hash[index]; p; p = p->next) {
 		if (likely(p->code == code))
 			p->handler(ext_int_code, param32, param64);
@@ -140,6 +106,3 @@ void __irq_entry do_extint(struct pt_reg
 	irq_exit();
 	set_irq_regs(old_regs);
 }
-
-EXPORT_SYMBOL(register_external_interrupt);
-EXPORT_SYMBOL(unregister_external_interrupt);
diff -druNp linux-libre-2.6.37-gnu1/arch/s390/kernel/signal.c linux-libre-2.6.38-gnu1/arch/s390/kernel/signal.c
--- linux-libre-2.6.37-gnu1/arch/s390/kernel/signal.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/s390/kernel/signal.c	2011-03-14 21:20:32.000000000 -0400
@@ -505,7 +505,7 @@ void do_signal(struct pt_regs *regs)
 			 * Let tracing know that we've done the handler setup.
 			 */
 			tracehook_signal_handler(signr, &info, &ka, regs,
-					current->thread.per_info.single_step);
+					test_thread_flag(TIF_SINGLE_STEP));
 		}
 		return;
 	}
diff -druNp linux-libre-2.6.37-gnu1/arch/s390/kernel/smp.c linux-libre-2.6.38-gnu1/arch/s390/kernel/smp.c
--- linux-libre-2.6.37-gnu1/arch/s390/kernel/smp.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/s390/kernel/smp.c	2011-03-14 21:20:32.000000000 -0400
@@ -23,6 +23,7 @@
 #define KMSG_COMPONENT "cpu"
 #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
 
+#include <linux/workqueue.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/mm.h>
@@ -161,6 +162,7 @@ static void do_ext_call_interrupt(unsign
 {
 	unsigned long bits;
 
+	kstat_cpu(smp_processor_id()).irqs[EXTINT_IPI]++;
 	/*
 	 * handle bit signal external calls
 	 *
@@ -469,25 +471,25 @@ int __cpuinit start_secondary(void *cpuv
 	ipi_call_unlock();
 	/* Switch on interrupts */
 	local_irq_enable();
-	/* Print info about this processor */
-	print_cpu_info();
 	/* cpu_idle will call schedule for us */
 	cpu_idle();
 	return 0;
 }
 
-static void __init smp_create_idle(unsigned int cpu)
+struct create_idle {
+	struct work_struct work;
+	struct task_struct *idle;
+	struct completion done;
+	int cpu;
+};
+
+static void __cpuinit smp_fork_idle(struct work_struct *work)
 {
-	struct task_struct *p;
+	struct create_idle *c_idle;
 
-	/*
-	 *  don't care about the psw and regs settings since we'll never
-	 *  reschedule the forked task.
-	 */
-	p = fork_idle(cpu);
-	if (IS_ERR(p))
-		panic("failed fork for CPU %u: %li", cpu, PTR_ERR(p));
-	current_set[cpu] = p;
+	c_idle = container_of(work, struct create_idle, work);
+	c_idle->idle = fork_idle(c_idle->cpu);
+	complete(&c_idle->done);
 }
 
 static int __cpuinit smp_alloc_lowcore(int cpu)
@@ -551,6 +553,7 @@ static void smp_free_lowcore(int cpu)
 int __cpuinit __cpu_up(unsigned int cpu)
 {
 	struct _lowcore *cpu_lowcore;
+	struct create_idle c_idle;
 	struct task_struct *idle;
 	struct stack_frame *sf;
 	u32 lowcore;
@@ -558,6 +561,19 @@ int __cpuinit __cpu_up(unsigned int cpu)
 
 	if (smp_cpu_state[cpu] != CPU_STATE_CONFIGURED)
 		return -EIO;
+	idle = current_set[cpu];
+	if (!idle) {
+		c_idle.done = COMPLETION_INITIALIZER_ONSTACK(c_idle.done);
+		INIT_WORK_ONSTACK(&c_idle.work, smp_fork_idle);
+		c_idle.cpu = cpu;
+		schedule_work(&c_idle.work);
+		wait_for_completion(&c_idle.done);
+		if (IS_ERR(c_idle.idle))
+			return PTR_ERR(c_idle.idle);
+		idle = c_idle.idle;
+		current_set[cpu] = c_idle.idle;
+	}
+	init_idle(idle, cpu);
 	if (smp_alloc_lowcore(cpu))
 		return -ENOMEM;
 	do {
@@ -572,7 +588,6 @@ int __cpuinit __cpu_up(unsigned int cpu)
 	while (sigp_p(lowcore, cpu, sigp_set_prefix) == sigp_busy)
 		udelay(10);
 
-	idle = current_set[cpu];
 	cpu_lowcore = lowcore_ptr[cpu];
 	cpu_lowcore->kernel_stack = (unsigned long)
 		task_stack_page(idle) + THREAD_SIZE;
@@ -664,7 +679,6 @@ void __cpu_die(unsigned int cpu)
 		udelay(10);
 	smp_free_lowcore(cpu);
 	atomic_dec(&init_mm.context.attach_count);
-	pr_info("Processor %d stopped\n", cpu);
 }
 
 void cpu_die(void)
@@ -684,14 +698,12 @@ void __init smp_prepare_cpus(unsigned in
 #endif
 	unsigned long async_stack, panic_stack;
 	struct _lowcore *lowcore;
-	unsigned int cpu;
 
 	smp_detect_cpus();
 
 	/* request the 0x1201 emergency signal external interrupt */
 	if (register_external_interrupt(0x1201, do_ext_call_interrupt) != 0)
 		panic("Couldn't request external interrupt 0x1201");
-	print_cpu_info();
 
 	/* Reallocate current lowcore, but keep its contents. */
 	lowcore = (void *) __get_free_pages(GFP_KERNEL | GFP_DMA, LC_ORDER);
@@ -719,9 +731,6 @@ void __init smp_prepare_cpus(unsigned in
 	if (vdso_alloc_per_cpu(smp_processor_id(), &S390_lowcore))
 		BUG();
 #endif
-	for_each_possible_cpu(cpu)
-		if (cpu != smp_processor_id())
-			smp_create_idle(cpu);
 }
 
 void __init smp_prepare_boot_cpu(void)
diff -druNp linux-libre-2.6.37-gnu1/arch/s390/kernel/time.c linux-libre-2.6.38-gnu1/arch/s390/kernel/time.c
--- linux-libre-2.6.37-gnu1/arch/s390/kernel/time.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/s390/kernel/time.c	2011-03-14 21:20:32.000000000 -0400
@@ -15,6 +15,7 @@
 #define KMSG_COMPONENT "time"
 #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
 
+#include <linux/kernel_stat.h>
 #include <linux/errno.h>
 #include <linux/module.h>
 #include <linux/sched.h>
@@ -37,6 +38,7 @@
 #include <linux/clocksource.h>
 #include <linux/clockchips.h>
 #include <linux/gfp.h>
+#include <linux/kprobes.h>
 #include <asm/uaccess.h>
 #include <asm/delay.h>
 #include <asm/s390_ext.h>
@@ -60,7 +62,7 @@ static DEFINE_PER_CPU(struct clock_event
 /*
  * Scheduler clock - returns current time in nanosec units.
  */
-unsigned long long notrace sched_clock(void)
+unsigned long long notrace __kprobes sched_clock(void)
 {
 	return (get_clock_monotonic() * 125) >> 9;
 }
@@ -159,6 +161,7 @@ static void clock_comparator_interrupt(u
 				       unsigned int param32,
 				       unsigned long param64)
 {
+	kstat_cpu(smp_processor_id()).irqs[EXTINT_CLK]++;
 	if (S390_lowcore.clock_comparator == -1ULL)
 		set_clock_comparator(S390_lowcore.clock_comparator);
 }
@@ -169,6 +172,7 @@ static void stp_timing_alert(struct stp_
 static void timing_alert_interrupt(unsigned int ext_int_code,
 				   unsigned int param32, unsigned long param64)
 {
+	kstat_cpu(smp_processor_id()).irqs[EXTINT_TLA]++;
 	if (param32 & 0x00c40000)
 		etr_timing_alert((struct etr_irq_parm *) &param32);
 	if (param32 & 0x00038000)
diff -druNp linux-libre-2.6.37-gnu1/arch/s390/kernel/traps.c linux-libre-2.6.38-gnu1/arch/s390/kernel/traps.c
--- linux-libre-2.6.37-gnu1/arch/s390/kernel/traps.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/s390/kernel/traps.c	2011-03-14 21:20:32.000000000 -0400
@@ -237,43 +237,6 @@ void show_regs(struct pt_regs *regs)
 	show_last_breaking_event(regs);
 }
 
-/* This is called from fs/proc/array.c */
-void task_show_regs(struct seq_file *m, struct task_struct *task)
-{
-	struct pt_regs *regs;
-
-	regs = task_pt_regs(task);
-	seq_printf(m, "task: %p, ksp: %p\n",
-		       task, (void *)task->thread.ksp);
-	seq_printf(m, "User PSW : %p %p\n",
-		       (void *) regs->psw.mask, (void *)regs->psw.addr);
-
-	seq_printf(m, "User GPRS: " FOURLONG,
-			  regs->gprs[0], regs->gprs[1],
-			  regs->gprs[2], regs->gprs[3]);
-	seq_printf(m, "           " FOURLONG,
-			  regs->gprs[4], regs->gprs[5],
-			  regs->gprs[6], regs->gprs[7]);
-	seq_printf(m, "           " FOURLONG,
-			  regs->gprs[8], regs->gprs[9],
-			  regs->gprs[10], regs->gprs[11]);
-	seq_printf(m, "           " FOURLONG,
-			  regs->gprs[12], regs->gprs[13],
-			  regs->gprs[14], regs->gprs[15]);
-	seq_printf(m, "User ACRS: %08x %08x %08x %08x\n",
-			  task->thread.acrs[0], task->thread.acrs[1],
-			  task->thread.acrs[2], task->thread.acrs[3]);
-	seq_printf(m, "           %08x %08x %08x %08x\n",
-			  task->thread.acrs[4], task->thread.acrs[5],
-			  task->thread.acrs[6], task->thread.acrs[7]);
-	seq_printf(m, "           %08x %08x %08x %08x\n",
-			  task->thread.acrs[8], task->thread.acrs[9],
-			  task->thread.acrs[10], task->thread.acrs[11]);
-	seq_printf(m, "           %08x %08x %08x %08x\n",
-			  task->thread.acrs[12], task->thread.acrs[13],
-			  task->thread.acrs[14], task->thread.acrs[15]);
-}
-
 static DEFINE_SPINLOCK(die_lock);
 
 void die(const char * str, struct pt_regs * regs, long err)
@@ -365,12 +328,10 @@ static inline void __user *get_psw_addre
 		((regs->psw.addr - (pgm_int_code >> 16)) & PSW_ADDR_INSN);
 }
 
-void __kprobes do_single_step(struct pt_regs *regs)
+void __kprobes do_per_trap(struct pt_regs *regs)
 {
-	if (notify_die(DIE_SSTEP, "sstep", regs, 0, 0,
-					SIGTRAP) == NOTIFY_STOP){
+	if (notify_die(DIE_SSTEP, "sstep", regs, 0, 0, SIGTRAP) == NOTIFY_STOP)
 		return;
-	}
 	if (tracehook_consider_fatal_signal(current, SIGTRAP))
 		force_sig(SIGTRAP, current);
 }
@@ -451,8 +412,8 @@ static inline void do_fp_trap(struct pt_
 		"floating point exception", regs, &si);
 }
 
-static void illegal_op(struct pt_regs *regs, long pgm_int_code,
-		       unsigned long trans_exc_code)
+static void __kprobes illegal_op(struct pt_regs *regs, long pgm_int_code,
+				 unsigned long trans_exc_code)
 {
 	siginfo_t info;
         __u8 opcode[6];
@@ -688,7 +649,7 @@ static void space_switch_exception(struc
 	do_trap(pgm_int_code, SIGILL, "space switch event", regs, &info);
 }
 
-asmlinkage void kernel_stack_overflow(struct pt_regs * regs)
+asmlinkage void __kprobes kernel_stack_overflow(struct pt_regs * regs)
 {
 	bust_spinlocks(1);
 	printk("Kernel stack overflow.\n");
@@ -733,5 +694,6 @@ void __init trap_init(void)
         pgm_check_table[0x15] = &operand_exception;
         pgm_check_table[0x1C] = &space_switch_exception;
         pgm_check_table[0x1D] = &hfp_sqrt_exception;
-	pfault_irq_init();
+	/* Enable machine checks early. */
+	local_mcck_enable();
 }
diff -druNp linux-libre-2.6.37-gnu1/arch/s390/kernel/vdso.c linux-libre-2.6.38-gnu1/arch/s390/kernel/vdso.c
--- linux-libre-2.6.37-gnu1/arch/s390/kernel/vdso.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/s390/kernel/vdso.c	2011-03-14 21:20:32.000000000 -0400
@@ -203,7 +203,6 @@ int arch_setup_additional_pages(struct l
 	if (!uses_interp)
 		return 0;
 
-	vdso_base = mm->mmap_base;
 #ifdef CONFIG_64BIT
 	vdso_pagelist = vdso64_pagelist;
 	vdso_pages = vdso64_pages;
@@ -233,8 +232,7 @@ int arch_setup_additional_pages(struct l
 	 * fail and end up putting it elsewhere.
 	 */
 	down_write(&mm->mmap_sem);
-	vdso_base = get_unmapped_area(NULL, vdso_base,
-				      vdso_pages << PAGE_SHIFT, 0, 0);
+	vdso_base = get_unmapped_area(NULL, 0, vdso_pages << PAGE_SHIFT, 0, 0);
 	if (IS_ERR_VALUE(vdso_base)) {
 		rc = vdso_base;
 		goto out_up;
diff -druNp linux-libre-2.6.37-gnu1/arch/s390/kernel/vtime.c linux-libre-2.6.38-gnu1/arch/s390/kernel/vtime.c
--- linux-libre-2.6.37-gnu1/arch/s390/kernel/vtime.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/s390/kernel/vtime.c	2011-03-14 21:20:32.000000000 -0400
@@ -20,6 +20,7 @@
 #include <linux/rcupdate.h>
 #include <linux/posix-timers.h>
 #include <linux/cpu.h>
+#include <linux/kprobes.h>
 
 #include <asm/s390_ext.h>
 #include <asm/timer.h>
@@ -122,7 +123,7 @@ void account_system_vtime(struct task_st
 }
 EXPORT_SYMBOL_GPL(account_system_vtime);
 
-void vtime_start_cpu(__u64 int_clock, __u64 enter_timer)
+void __kprobes vtime_start_cpu(__u64 int_clock, __u64 enter_timer)
 {
 	struct s390_idle_data *idle = &__get_cpu_var(s390_idle);
 	struct vtimer_queue *vq = &__get_cpu_var(virt_cpu_timer);
@@ -162,7 +163,7 @@ void vtime_start_cpu(__u64 int_clock, __
 	idle->sequence++;
 }
 
-void vtime_stop_cpu(void)
+void __kprobes vtime_stop_cpu(void)
 {
 	struct s390_idle_data *idle = &__get_cpu_var(s390_idle);
 	struct vtimer_queue *vq = &__get_cpu_var(virt_cpu_timer);
@@ -323,6 +324,7 @@ static void do_cpu_timer_interrupt(unsig
 	struct list_head cb_list;	/* the callback queue */
 	__u64 elapsed, next;
 
+	kstat_cpu(smp_processor_id()).irqs[EXTINT_TMR]++;
 	INIT_LIST_HEAD(&cb_list);
 	vq = &__get_cpu_var(virt_cpu_timer);
 
diff -druNp linux-libre-2.6.37-gnu1/arch/s390/kvm/Kconfig linux-libre-2.6.38-gnu1/arch/s390/kvm/Kconfig
--- linux-libre-2.6.37-gnu1/arch/s390/kvm/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/s390/kvm/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -4,8 +4,8 @@
 source "virt/kvm/Kconfig"
 
 menuconfig VIRTUALIZATION
-	bool "Virtualization"
-	default y
+	def_bool y
+	prompt "Virtualization"
 	---help---
 	  Say Y here to get to see options for using your Linux host to run other
 	  operating systems inside virtual machines (guests).
@@ -16,7 +16,8 @@ menuconfig VIRTUALIZATION
 if VIRTUALIZATION
 
 config KVM
-	tristate "Kernel-based Virtual Machine (KVM) support"
+	def_tristate y
+	prompt "Kernel-based Virtual Machine (KVM) support"
 	depends on HAVE_KVM && EXPERIMENTAL
 	select PREEMPT_NOTIFIERS
 	select ANON_INODES
diff -druNp linux-libre-2.6.37-gnu1/arch/s390/kvm/kvm-s390.c linux-libre-2.6.38-gnu1/arch/s390/kvm/kvm-s390.c
--- linux-libre-2.6.37-gnu1/arch/s390/kvm/kvm-s390.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/s390/kvm/kvm-s390.c	2011-03-14 21:20:32.000000000 -0400
@@ -164,24 +164,18 @@ long kvm_arch_vm_ioctl(struct file *filp
 	return r;
 }
 
-struct kvm *kvm_arch_create_vm(void)
+int kvm_arch_init_vm(struct kvm *kvm)
 {
-	struct kvm *kvm;
 	int rc;
 	char debug_name[16];
 
 	rc = s390_enable_sie();
 	if (rc)
-		goto out_nokvm;
-
-	rc = -ENOMEM;
-	kvm = kzalloc(sizeof(struct kvm), GFP_KERNEL);
-	if (!kvm)
-		goto out_nokvm;
+		goto out_err;
 
 	kvm->arch.sca = (struct sca_block *) get_zeroed_page(GFP_KERNEL);
 	if (!kvm->arch.sca)
-		goto out_nosca;
+		goto out_err;
 
 	sprintf(debug_name, "kvm-%u", current->pid);
 
@@ -195,13 +189,11 @@ struct kvm *kvm_arch_create_vm(void)
 	debug_register_view(kvm->arch.dbf, &debug_sprintf_view);
 	VM_EVENT(kvm, 3, "%s", "vm created");
 
-	return kvm;
+	return 0;
 out_nodbf:
 	free_page((unsigned long)(kvm->arch.sca));
-out_nosca:
-	kfree(kvm);
-out_nokvm:
-	return ERR_PTR(rc);
+out_err:
+	return rc;
 }
 
 void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu)
@@ -240,11 +232,8 @@ void kvm_arch_sync_events(struct kvm *kv
 void kvm_arch_destroy_vm(struct kvm *kvm)
 {
 	kvm_free_vcpus(kvm);
-	kvm_free_physmem(kvm);
 	free_page((unsigned long)(kvm->arch.sca));
 	debug_unregister(kvm->arch.dbf);
-	cleanup_srcu_struct(&kvm->srcu);
-	kfree(kvm);
 }
 
 /* Section: vcpu related */
diff -druNp linux-libre-2.6.37-gnu1/arch/s390/lib/delay.c linux-libre-2.6.38-gnu1/arch/s390/lib/delay.c
--- linux-libre-2.6.37-gnu1/arch/s390/lib/delay.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/s390/lib/delay.c	2011-03-14 21:20:32.000000000 -0400
@@ -47,7 +47,6 @@ static void __udelay_disabled(unsigned l
 	lockdep_on();
 	__ctl_load(cr0_saved, 0, 0);
 	local_tick_enable(clock_saved);
-	set_clock_comparator(S390_lowcore.clock_comparator);
 }
 
 static void __udelay_enabled(unsigned long long usecs)
@@ -70,7 +69,6 @@ static void __udelay_enabled(unsigned lo
 		if (clock_saved)
 			local_tick_enable(clock_saved);
 	} while (get_clock() < end);
-	set_clock_comparator(S390_lowcore.clock_comparator);
 }
 
 /*
diff -druNp linux-libre-2.6.37-gnu1/arch/s390/lib/uaccess_std.c linux-libre-2.6.38-gnu1/arch/s390/lib/uaccess_std.c
--- linux-libre-2.6.37-gnu1/arch/s390/lib/uaccess_std.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/s390/lib/uaccess_std.c	2011-03-14 21:20:32.000000000 -0400
@@ -125,9 +125,9 @@ static size_t copy_in_user_std(size_t si
 	unsigned long tmp1;
 
 	asm volatile(
+		"   sacf  256\n"
 		"  "AHI"  %0,-1\n"
 		"   jo    5f\n"
-		"   sacf  256\n"
 		"   bras  %3,3f\n"
 		"0:"AHI"  %0,257\n"
 		"1: mvc   0(1,%1),0(%2)\n"
@@ -142,9 +142,8 @@ static size_t copy_in_user_std(size_t si
 		"3:"AHI"  %0,-256\n"
 		"   jnm   2b\n"
 		"4: ex    %0,1b-0b(%3)\n"
-		"   sacf  0\n"
 		"5: "SLR"  %0,%0\n"
-		"6:\n"
+		"6: sacf  0\n"
 		EX_TABLE(1b,6b) EX_TABLE(2b,0b) EX_TABLE(4b,0b)
 		: "+a" (size), "+a" (to), "+a" (from), "=a" (tmp1)
 		: : "cc", "memory");
@@ -156,9 +155,9 @@ static size_t clear_user_std(size_t size
 	unsigned long tmp1, tmp2;
 
 	asm volatile(
+		"   sacf  256\n"
 		"  "AHI"  %0,-1\n"
 		"   jo    5f\n"
-		"   sacf  256\n"
 		"   bras  %3,3f\n"
 		"   xc    0(1,%1),0(%1)\n"
 		"0:"AHI"  %0,257\n"
@@ -178,9 +177,8 @@ static size_t clear_user_std(size_t size
 		"3:"AHI"  %0,-256\n"
 		"   jnm   2b\n"
 		"4: ex    %0,0(%3)\n"
-		"   sacf  0\n"
 		"5: "SLR"  %0,%0\n"
-		"6:\n"
+		"6: sacf  0\n"
 		EX_TABLE(1b,6b) EX_TABLE(2b,0b) EX_TABLE(4b,0b)
 		: "+a" (size), "+a" (to), "=a" (tmp1), "=a" (tmp2)
 		: : "cc", "memory");
diff -druNp linux-libre-2.6.37-gnu1/arch/s390/mm/fault.c linux-libre-2.6.38-gnu1/arch/s390/mm/fault.c
--- linux-libre-2.6.37-gnu1/arch/s390/mm/fault.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/s390/mm/fault.c	2011-03-14 21:20:32.000000000 -0400
@@ -10,6 +10,7 @@
  *    Copyright (C) 1995  Linus Torvalds
  */
 
+#include <linux/kernel_stat.h>
 #include <linux/perf_event.h>
 #include <linux/signal.h>
 #include <linux/sched.h>
@@ -234,13 +235,13 @@ static noinline int signal_return(struct
 	rc = __get_user(instruction, (u16 __user *) regs->psw.addr);
 
 	if (!rc && instruction == 0x0a77) {
-		clear_tsk_thread_flag(current, TIF_SINGLE_STEP);
+		clear_tsk_thread_flag(current, TIF_PER_TRAP);
 		if (is_compat_task())
 			sys32_sigreturn();
 		else
 			sys_sigreturn();
 	} else if (!rc && instruction == 0x0aad) {
-		clear_tsk_thread_flag(current, TIF_SINGLE_STEP);
+		clear_tsk_thread_flag(current, TIF_PER_TRAP);
 		if (is_compat_task())
 			sys32_rt_sigreturn();
 		else
@@ -378,7 +379,7 @@ static inline int do_exception(struct pt
 	 * The instruction that caused the program check will
 	 * be repeated. Don't signal single step via SIGTRAP.
 	 */
-	clear_tsk_thread_flag(tsk, TIF_SINGLE_STEP);
+	clear_tsk_thread_flag(tsk, TIF_PER_TRAP);
 	fault = 0;
 out_up:
 	up_read(&mm->mmap_sem);
@@ -480,8 +481,7 @@ int __handle_fault(unsigned long uaddr,
 /*
  * 'pfault' pseudo page faults routines.
  */
-static ext_int_info_t ext_int_pfault;
-static int pfault_disable = 0;
+static int pfault_disable;
 
 static int __init nopfault(char *str)
 {
@@ -543,6 +543,7 @@ static void pfault_interrupt(unsigned in
 	struct task_struct *tsk;
 	__u16 subcode;
 
+	kstat_cpu(smp_processor_id()).irqs[EXTINT_PFL]++;
 	/*
 	 * Get the external interruption subcode & pfault
 	 * initial/completion signal bit. VM stores this 
@@ -592,24 +593,28 @@ static void pfault_interrupt(unsigned in
 	}
 }
 
-void __init pfault_irq_init(void)
+static int __init pfault_irq_init(void)
 {
-	if (!MACHINE_IS_VM)
-		return;
+	int rc;
 
+	if (!MACHINE_IS_VM)
+		return 0;
 	/*
 	 * Try to get pfault pseudo page faults going.
 	 */
-	if (register_early_external_interrupt(0x2603, pfault_interrupt,
-					      &ext_int_pfault) != 0)
-		panic("Couldn't request external interrupt 0x2603");
-
+	rc = register_external_interrupt(0x2603, pfault_interrupt);
+	if (rc) {
+		pfault_disable = 1;
+		return rc;
+	}
 	if (pfault_init() == 0)
-		return;
+		return 0;
 
 	/* Tough luck, no pfault. */
 	pfault_disable = 1;
-	unregister_early_external_interrupt(0x2603, pfault_interrupt,
-					    &ext_int_pfault);
+	unregister_external_interrupt(0x2603, pfault_interrupt);
+	return 0;
 }
+early_initcall(pfault_irq_init);
+
 #endif
diff -druNp linux-libre-2.6.37-gnu1/arch/s390/mm/mmap.c linux-libre-2.6.38-gnu1/arch/s390/mm/mmap.c
--- linux-libre-2.6.37-gnu1/arch/s390/mm/mmap.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/s390/mm/mmap.c	2011-03-14 21:20:32.000000000 -0400
@@ -27,17 +27,44 @@
 #include <linux/personality.h>
 #include <linux/mm.h>
 #include <linux/module.h>
+#include <linux/random.h>
 #include <asm/pgalloc.h>
 #include <asm/compat.h>
 
+static unsigned long stack_maxrandom_size(void)
+{
+	if (!(current->flags & PF_RANDOMIZE))
+		return 0;
+	if (current->personality & ADDR_NO_RANDOMIZE)
+		return 0;
+	return STACK_RND_MASK << PAGE_SHIFT;
+}
+
 /*
  * Top of mmap area (just below the process stack).
  *
- * Leave an at least ~128 MB hole.
+ * Leave at least a ~32 MB hole.
  */
-#define MIN_GAP (128*1024*1024)
+#define MIN_GAP (32*1024*1024)
 #define MAX_GAP (STACK_TOP/6*5)
 
+static inline int mmap_is_legacy(void)
+{
+	if (current->personality & ADDR_COMPAT_LAYOUT)
+		return 1;
+	if (rlimit(RLIMIT_STACK) == RLIM_INFINITY)
+		return 1;
+	return sysctl_legacy_va_layout;
+}
+
+static unsigned long mmap_rnd(void)
+{
+	if (!(current->flags & PF_RANDOMIZE))
+		return 0;
+	/* 8MB randomization for mmap_base */
+	return (get_random_int() & 0x7ffUL) << PAGE_SHIFT;
+}
+
 static inline unsigned long mmap_base(void)
 {
 	unsigned long gap = rlimit(RLIMIT_STACK);
@@ -46,22 +73,8 @@ static inline unsigned long mmap_base(vo
 		gap = MIN_GAP;
 	else if (gap > MAX_GAP)
 		gap = MAX_GAP;
-
-	return STACK_TOP - (gap & PAGE_MASK);
-}
-
-static inline int mmap_is_legacy(void)
-{
-#ifdef CONFIG_64BIT
-	/*
-	 * Force standard allocation for 64 bit programs.
-	 */
-	if (!is_compat_task())
-		return 1;
-#endif
-	return sysctl_legacy_va_layout ||
-	    (current->personality & ADDR_COMPAT_LAYOUT) ||
-	    rlimit(RLIMIT_STACK) == RLIM_INFINITY;
+	gap &= PAGE_MASK;
+	return STACK_TOP - stack_maxrandom_size() - mmap_rnd() - gap;
 }
 
 #ifndef CONFIG_64BIT
diff -druNp linux-libre-2.6.37-gnu1/arch/s390/mm/pgtable.c linux-libre-2.6.38-gnu1/arch/s390/mm/pgtable.c
--- linux-libre-2.6.37-gnu1/arch/s390/mm/pgtable.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/s390/mm/pgtable.c	2011-03-14 21:20:32.000000000 -0400
@@ -336,7 +336,8 @@ void page_table_free(struct mm_struct *m
 	page->flags ^= bits;
 	if (page->flags & FRAG_MASK) {
 		/* Page now has some free pgtable fragments. */
-		list_move(&page->lru, &mm->context.pgtable_list);
+		if (!list_empty(&page->lru))
+			list_move(&page->lru, &mm->context.pgtable_list);
 		page = NULL;
 	} else
 		/* All fragments of the 4K page have been freed. */
diff -druNp linux-libre-2.6.37-gnu1/arch/score/configs/spct6600_defconfig linux-libre-2.6.38-gnu1/arch/score/configs/spct6600_defconfig
--- linux-libre-2.6.37-gnu1/arch/score/configs/spct6600_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/score/configs/spct6600_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -9,7 +9,7 @@ CONFIG_LOG_BUF_SHIFT=12
 CONFIG_SYSFS_DEPRECATED_V2=y
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_KALLSYMS is not set
 # CONFIG_HOTPLUG is not set
 CONFIG_SLAB=y
diff -druNp linux-libre-2.6.37-gnu1/arch/score/Kconfig linux-libre-2.6.38-gnu1/arch/score/Kconfig
--- linux-libre-2.6.37-gnu1/arch/score/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/score/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -1,5 +1,9 @@
 menu "Machine selection"
 
+config SCORE
+       def_bool y
+       select HAVE_GENERIC_HARDIRQS
+
 choice
 	prompt "System type"
 	default MACH_SPCT6600
@@ -53,9 +57,6 @@ config GENERIC_CLOCKEVENTS
 config SCHED_NO_NO_OMIT_FRAME_POINTER
 	def_bool y
 
-config GENERIC_HARDIRQS_NO__DO_IRQ
-	def_bool y
-
 config GENERIC_SYSCALL_TABLE
 	def_bool y
 
@@ -68,9 +69,6 @@ menu "Kernel type"
 config 32BIT
 	def_bool y
 
-config GENERIC_HARDIRQS
-	def_bool y
-
 config ARCH_FLATMEM_ENABLE
 	def_bool y
 
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/boards/board-apsh4a3a.c linux-libre-2.6.38-gnu1/arch/sh/boards/board-apsh4a3a.c
--- linux-libre-2.6.37-gnu1/arch/sh/boards/board-apsh4a3a.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/boards/board-apsh4a3a.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,175 @@
+/*
+ * ALPHAPROJECT AP-SH4A-3A Support.
+ *
+ * Copyright (C) 2010 ALPHAPROJECT Co.,Ltd.
+ * Copyright (C) 2008  Yoshihiro Shimoda
+ * Copyright (C) 2009  Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/mtd/physmap.h>
+#include <linux/smsc911x.h>
+#include <linux/irq.h>
+#include <linux/clk.h>
+#include <asm/machvec.h>
+#include <asm/sizes.h>
+#include <asm/clock.h>
+
+static struct mtd_partition nor_flash_partitions[] = {
+	{
+		.name		= "loader",
+		.offset		= 0x00000000,
+		.size		= 512 * 1024,
+	},
+	{
+		.name		= "bootenv",
+		.offset		= MTDPART_OFS_APPEND,
+		.size		= 512 * 1024,
+	},
+	{
+		.name		= "kernel",
+		.offset		= MTDPART_OFS_APPEND,
+		.size		= 4 * 1024 * 1024,
+	},
+	{
+		.name		= "data",
+		.offset		= MTDPART_OFS_APPEND,
+		.size		= MTDPART_SIZ_FULL,
+	},
+};
+
+static struct physmap_flash_data nor_flash_data = {
+	.width		= 4,
+	.parts		= nor_flash_partitions,
+	.nr_parts	= ARRAY_SIZE(nor_flash_partitions),
+};
+
+static struct resource nor_flash_resources[] = {
+	[0]	= {
+		.start	= 0x00000000,
+		.end	= 0x01000000 - 1,
+		.flags	= IORESOURCE_MEM,
+	}
+};
+
+static struct platform_device nor_flash_device = {
+	.name		= "physmap-flash",
+	.dev		= {
+		.platform_data	= &nor_flash_data,
+	},
+	.num_resources	= ARRAY_SIZE(nor_flash_resources),
+	.resource	= nor_flash_resources,
+};
+
+static struct resource smsc911x_resources[] = {
+	[0] = {
+		.name		= "smsc911x-memory",
+		.start		= 0xA4000000,
+		.end		= 0xA4000000 + SZ_256 - 1,
+		.flags		= IORESOURCE_MEM,
+	},
+	[1] = {
+		.name		= "smsc911x-irq",
+		.start		= evt2irq(0x200),
+		.end		= evt2irq(0x200),
+		.flags		= IORESOURCE_IRQ,
+	},
+};
+
+static struct smsc911x_platform_config smsc911x_config = {
+	.irq_polarity	= SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
+	.irq_type	= SMSC911X_IRQ_TYPE_OPEN_DRAIN,
+	.flags		= SMSC911X_USE_16BIT,
+	.phy_interface	= PHY_INTERFACE_MODE_MII,
+};
+
+static struct platform_device smsc911x_device = {
+	.name		= "smsc911x",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(smsc911x_resources),
+	.resource	= smsc911x_resources,
+	.dev = {
+		.platform_data = &smsc911x_config,
+	},
+};
+
+static struct platform_device *apsh4a3a_devices[] __initdata = {
+	&nor_flash_device,
+	&smsc911x_device,
+};
+
+static int __init apsh4a3a_devices_setup(void)
+{
+	return platform_add_devices(apsh4a3a_devices,
+				    ARRAY_SIZE(apsh4a3a_devices));
+}
+device_initcall(apsh4a3a_devices_setup);
+
+static int apsh4a3a_clk_init(void)
+{
+	struct clk *clk;
+	int ret;
+
+	clk = clk_get(NULL, "extal");
+	if (!clk || IS_ERR(clk))
+		return PTR_ERR(clk);
+	ret = clk_set_rate(clk, 33333000);
+	clk_put(clk);
+
+	return ret;
+}
+
+/* Initialize the board */
+static void __init apsh4a3a_setup(char **cmdline_p)
+{
+	printk(KERN_INFO "Alpha Project AP-SH4A-3A support:\n");
+}
+
+static void __init apsh4a3a_init_irq(void)
+{
+	plat_irq_setup_pins(IRQ_MODE_IRQ7654);
+}
+
+/* Return the board specific boot mode pin configuration */
+static int apsh4a3a_mode_pins(void)
+{
+	int value = 0;
+
+	/* These are the factory default settings of SW1 and SW2.
+	 * If you change these dip switches then you will need to
+	 * adjust the values below as well.
+	 */
+	value &= ~MODE_PIN0;  /* Clock Mode 16 */
+	value &= ~MODE_PIN1;
+	value &= ~MODE_PIN2;
+	value &= ~MODE_PIN3;
+	value |=  MODE_PIN4;
+	value &= ~MODE_PIN5;  /* 16-bit Area0 bus width */
+	value |=  MODE_PIN6;  /* Area 0 SRAM interface */
+	value |=  MODE_PIN7;
+	value |=  MODE_PIN8;  /* Little Endian */
+	value |=  MODE_PIN9;  /* Master Mode */
+	value |=  MODE_PIN10; /* Crystal resonator */
+	value |=  MODE_PIN11; /* Display Unit */
+	value |=  MODE_PIN12;
+	value &= ~MODE_PIN13; /* 29-bit address mode */
+	value |=  MODE_PIN14; /* No PLL step-up */
+
+	return value;
+}
+
+/*
+ * The Machine Vector
+ */
+static struct sh_machine_vector mv_apsh4a3a __initmv = {
+	.mv_name		= "AP-SH4A-3A",
+	.mv_setup		= apsh4a3a_setup,
+	.mv_clk_init		= apsh4a3a_clk_init,
+	.mv_init_irq		= apsh4a3a_init_irq,
+	.mv_mode_pins		= apsh4a3a_mode_pins,
+};
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/boards/board-apsh4ad0a.c linux-libre-2.6.38-gnu1/arch/sh/boards/board-apsh4ad0a.c
--- linux-libre-2.6.37-gnu1/arch/sh/boards/board-apsh4ad0a.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/boards/board-apsh4ad0a.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,125 @@
+/*
+ * ALPHAPROJECT AP-SH4AD-0A Support.
+ *
+ * Copyright (C) 2010 ALPHAPROJECT Co.,Ltd.
+ * Copyright (C) 2010  Matt Fleming
+ * Copyright (C) 2010  Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/smsc911x.h>
+#include <linux/irq.h>
+#include <linux/clk.h>
+#include <asm/machvec.h>
+#include <asm/sizes.h>
+
+static struct resource smsc911x_resources[] = {
+	[0] = {
+		.name		= "smsc911x-memory",
+		.start		= 0xA4000000,
+		.end		= 0xA4000000 + SZ_256 - 1,
+		.flags		= IORESOURCE_MEM,
+	},
+	[1] = {
+		.name		= "smsc911x-irq",
+		.start		= evt2irq(0x200),
+		.end		= evt2irq(0x200),
+		.flags		= IORESOURCE_IRQ,
+	},
+};
+
+static struct smsc911x_platform_config smsc911x_config = {
+	.irq_polarity	= SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
+	.irq_type	= SMSC911X_IRQ_TYPE_OPEN_DRAIN,
+	.flags		= SMSC911X_USE_16BIT,
+	.phy_interface	= PHY_INTERFACE_MODE_MII,
+};
+
+static struct platform_device smsc911x_device = {
+	.name		= "smsc911x",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(smsc911x_resources),
+	.resource	= smsc911x_resources,
+	.dev = {
+		.platform_data = &smsc911x_config,
+	},
+};
+
+static struct platform_device *apsh4ad0a_devices[] __initdata = {
+	&smsc911x_device,
+};
+
+static int __init apsh4ad0a_devices_setup(void)
+{
+	return platform_add_devices(apsh4ad0a_devices,
+				    ARRAY_SIZE(apsh4ad0a_devices));
+}
+device_initcall(apsh4ad0a_devices_setup);
+
+static int apsh4ad0a_mode_pins(void)
+{
+	int value = 0;
+
+	/* These are the factory default settings of SW1 and SW2.
+	 * If you change these dip switches then you will need to
+	 * adjust the values below as well.
+	 */
+	value |=  MODE_PIN0;  /* Clock Mode 3 */
+	value |=  MODE_PIN1;
+	value &= ~MODE_PIN2;
+	value &= ~MODE_PIN3;
+	value &= ~MODE_PIN4;  /* 16-bit Area0 bus width  */
+	value |=  MODE_PIN5;
+	value |=  MODE_PIN6;
+	value |=  MODE_PIN7;  /* Normal mode */
+	value |=  MODE_PIN8;  /* Little Endian */
+	value |=  MODE_PIN9;  /* Crystal resonator */
+	value &= ~MODE_PIN10; /* 29-bit address mode */
+	value &= ~MODE_PIN11; /* PCI-E Root port */
+	value &= ~MODE_PIN12; /* 4 lane + 1 lane */
+	value |=  MODE_PIN13; /* AUD Enable */
+	value &= ~MODE_PIN14; /* Normal Operation */
+
+	return value;
+}
+
+static int apsh4ad0a_clk_init(void)
+{
+	struct clk *clk;
+	int ret;
+
+	clk = clk_get(NULL, "extal");
+	if (!clk || IS_ERR(clk))
+		return PTR_ERR(clk);
+	ret = clk_set_rate(clk, 33333000);
+	clk_put(clk);
+
+	return ret;
+}
+
+/* Initialize the board */
+static void __init apsh4ad0a_setup(char **cmdline_p)
+{
+	pr_info("Alpha Project AP-SH4AD-0A support:\n");
+}
+
+static void __init apsh4ad0a_init_irq(void)
+{
+	plat_irq_setup_pins(IRQ_MODE_IRQ3210);
+}
+
+/*
+ * The Machine Vector
+ */
+static struct sh_machine_vector mv_apsh4ad0a __initmv = {
+	.mv_name		= "AP-SH4AD-0A",
+	.mv_setup		= apsh4ad0a_setup,
+	.mv_mode_pins		= apsh4ad0a_mode_pins,
+	.mv_clk_init		= apsh4ad0a_clk_init,
+	.mv_init_irq		= apsh4ad0a_init_irq,
+};
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/boards/board-edosk7705.c linux-libre-2.6.38-gnu1/arch/sh/boards/board-edosk7705.c
--- linux-libre-2.6.37-gnu1/arch/sh/boards/board-edosk7705.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/boards/board-edosk7705.c	2011-03-14 21:20:32.000000000 -0400
@@ -66,7 +66,7 @@ static int __init init_edosk7705_devices
 	return platform_add_devices(edosk7705_devices,
 				    ARRAY_SIZE(edosk7705_devices));
 }
-__initcall(init_edosk7705_devices);
+device_initcall(init_edosk7705_devices);
 
 /*
  * The Machine Vector
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/boards/board-edosk7760.c linux-libre-2.6.38-gnu1/arch/sh/boards/board-edosk7760.c
--- linux-libre-2.6.37-gnu1/arch/sh/boards/board-edosk7760.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/boards/board-edosk7760.c	2011-03-14 21:20:32.000000000 -0400
@@ -182,7 +182,7 @@ static int __init init_edosk7760_devices
 	return platform_add_devices(edosk7760_devices,
 				    ARRAY_SIZE(edosk7760_devices));
 }
-__initcall(init_edosk7760_devices);
+device_initcall(init_edosk7760_devices);
 
 /*
  * The Machine Vector
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/boards/board-secureedge5410.c linux-libre-2.6.38-gnu1/arch/sh/boards/board-secureedge5410.c
--- linux-libre-2.6.37-gnu1/arch/sh/boards/board-secureedge5410.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/boards/board-secureedge5410.c	2011-03-14 21:20:32.000000000 -0400
@@ -29,8 +29,6 @@ unsigned short secureedge5410_ioport;
  */
 static irqreturn_t eraseconfig_interrupt(int irq, void *dev_id)
 {
-	ctrl_delay();	/* dummy read */
-
 	printk("SnapGear: erase switch interrupt!\n");
 
 	return IRQ_HANDLED;
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/boards/board-sh7785lcr.c linux-libre-2.6.38-gnu1/arch/sh/boards/board-sh7785lcr.c
--- linux-libre-2.6.37-gnu1/arch/sh/boards/board-sh7785lcr.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/boards/board-sh7785lcr.c	2011-03-14 21:20:32.000000000 -0400
@@ -284,7 +284,7 @@ static int __init sh7785lcr_devices_setu
 	return platform_add_devices(sh7785lcr_devices,
 				    ARRAY_SIZE(sh7785lcr_devices));
 }
-__initcall(sh7785lcr_devices_setup);
+device_initcall(sh7785lcr_devices_setup);
 
 /* Initialize IRQ setting */
 void __init init_sh7785lcr_IRQ(void)
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/boards/Kconfig linux-libre-2.6.38-gnu1/arch/sh/boards/Kconfig
--- linux-libre-2.6.37-gnu1/arch/sh/boards/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/boards/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -3,6 +3,9 @@ menu "Board support"
 config SOLUTION_ENGINE
 	bool
 
+config SH_ALPHA_BOARD
+	bool
+
 config SH_SOLUTION_ENGINE
 	bool "SolutionEngine"
 	select SOLUTION_ENGINE
@@ -320,6 +323,21 @@ config SH_SH2007
 	  Compact Flash socket, two serial ports and PC-104 bus.
 	  More information at <http://sh2000.sh-linux.org>.
 
+config SH_APSH4A3A
+	bool "AP-SH4A-3A"
+	select SH_ALPHA_BOARD
+	depends on CPU_SUBTYPE_SH7785
+	help
+	  Select AP-SH4A-3A if configuring for an ALPHAPROJECT AP-SH4A-3A.
+
+config SH_APSH4AD0A
+	bool "AP-SH4AD-0A"
+	select SH_ALPHA_BOARD
+	select SYS_SUPPORTS_PCI
+	depends on CPU_SUBTYPE_SH7786
+	help
+	  Select AP-SH4AD-0A if configuring for an ALPHAPROJECT AP-SH4AD-0A.
+
 endmenu
 
 source "arch/sh/boards/mach-r2d/Kconfig"
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/boards/mach-ap325rxa/setup.c linux-libre-2.6.38-gnu1/arch/sh/boards/mach-ap325rxa/setup.c
--- linux-libre-2.6.37-gnu1/arch/sh/boards/mach-ap325rxa/setup.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/boards/mach-ap325rxa/setup.c	2011-03-14 21:20:32.000000000 -0400
@@ -14,6 +14,8 @@
 #include <linux/device.h>
 #include <linux/interrupt.h>
 #include <linux/platform_device.h>
+#include <linux/mfd/sh_mobile_sdhi.h>
+#include <linux/mmc/host.h>
 #include <linux/mtd/physmap.h>
 #include <linux/mtd/sh_flctl.h>
 #include <linux/delay.h>
@@ -430,11 +432,18 @@ static struct resource sdhi0_cn3_resourc
 	},
 };
 
+static struct sh_mobile_sdhi_info sdhi0_cn3_data = {
+	.tmio_caps      = MMC_CAP_SDIO_IRQ,
+};
+
 static struct platform_device sdhi0_cn3_device = {
 	.name		= "sh_mobile_sdhi",
 	.id             = 0, /* "sdhi0" clock */
 	.num_resources	= ARRAY_SIZE(sdhi0_cn3_resources),
 	.resource	= sdhi0_cn3_resources,
+	.dev = {
+		.platform_data = &sdhi0_cn3_data,
+	},
 	.archdata = {
 		.hwblk_id = HWBLK_SDHI0,
 	},
@@ -453,11 +462,18 @@ static struct resource sdhi1_cn7_resourc
 	},
 };
 
+static struct sh_mobile_sdhi_info sdhi1_cn7_data = {
+	.tmio_caps      = MMC_CAP_SDIO_IRQ,
+};
+
 static struct platform_device sdhi1_cn7_device = {
 	.name		= "sh_mobile_sdhi",
 	.id             = 1, /* "sdhi1" clock */
 	.num_resources	= ARRAY_SIZE(sdhi1_cn7_resources),
 	.resource	= sdhi1_cn7_resources,
+	.dev = {
+		.platform_data = &sdhi1_cn7_data,
+	},
 	.archdata = {
 		.hwblk_id = HWBLK_SDHI1,
 	},
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/boards/mach-cayman/setup.c linux-libre-2.6.38-gnu1/arch/sh/boards/mach-cayman/setup.c
--- linux-libre-2.6.37-gnu1/arch/sh/boards/mach-cayman/setup.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/boards/mach-cayman/setup.c	2011-03-14 21:20:32.000000000 -0400
@@ -165,7 +165,7 @@ static int __init smsc_superio_setup(voi
 
 	return 0;
 }
-__initcall(smsc_superio_setup);
+device_initcall(smsc_superio_setup);
 
 static void __iomem *cayman_ioport_map(unsigned long port, unsigned int len)
 {
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/boards/mach-ecovec24/setup.c linux-libre-2.6.38-gnu1/arch/sh/boards/mach-ecovec24/setup.c
--- linux-libre-2.6.37-gnu1/arch/sh/boards/mach-ecovec24/setup.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/boards/mach-ecovec24/setup.c	2011-03-14 21:20:32.000000000 -0400
@@ -473,6 +473,7 @@ static struct sh_mobile_sdhi_info sdhi0_
 	.dma_slave_tx	= SHDMA_SLAVE_SDHI0_TX,
 	.dma_slave_rx	= SHDMA_SLAVE_SDHI0_RX,
 	.set_pwr	= sdhi0_set_pwr,
+	.tmio_caps      = MMC_CAP_SDIO_IRQ | MMC_CAP_POWER_OFF_CARD,
 };
 
 static struct resource sdhi0_resources[] = {
@@ -511,6 +512,7 @@ static void sdhi1_set_pwr(struct platfor
 static struct sh_mobile_sdhi_info sdhi1_info = {
 	.dma_slave_tx	= SHDMA_SLAVE_SDHI1_TX,
 	.dma_slave_rx	= SHDMA_SLAVE_SDHI1_RX,
+	.tmio_caps      = MMC_CAP_SDIO_IRQ | MMC_CAP_POWER_OFF_CARD,
 	.set_pwr	= sdhi1_set_pwr,
 };
 
@@ -1292,6 +1294,7 @@ static int __init arch_setup(void)
 	i2c_register_board_info(1, i2c1_devices,
 				ARRAY_SIZE(i2c1_devices));
 
+#if defined(CONFIG_VIDEO_SH_VOU) || defined(CONFIG_VIDEO_SH_VOU_MODULE)
 	/* VOU */
 	gpio_request(GPIO_FN_DV_D15, NULL);
 	gpio_request(GPIO_FN_DV_D14, NULL);
@@ -1323,6 +1326,7 @@ static int __init arch_setup(void)
 
 	/* Remove reset */
 	gpio_set_value(GPIO_PTG4, 1);
+#endif
 
 	return platform_add_devices(ecovec_devices,
 				    ARRAY_SIZE(ecovec_devices));
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/boards/mach-highlander/setup.c linux-libre-2.6.38-gnu1/arch/sh/boards/mach-highlander/setup.c
--- linux-libre-2.6.37-gnu1/arch/sh/boards/mach-highlander/setup.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/boards/mach-highlander/setup.c	2011-03-14 21:20:32.000000000 -0400
@@ -24,10 +24,10 @@
 #include <linux/interrupt.h>
 #include <linux/usb/r8a66597.h>
 #include <linux/usb/m66592.h>
+#include <linux/clkdev.h>
 #include <net/ax88796.h>
 #include <asm/machvec.h>
 #include <mach/highlander.h>
-#include <asm/clkdev.h>
 #include <asm/clock.h>
 #include <asm/heartbeat.h>
 #include <asm/io.h>
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/boards/mach-hp6xx/pm.c linux-libre-2.6.38-gnu1/arch/sh/boards/mach-hp6xx/pm.c
--- linux-libre-2.6.37-gnu1/arch/sh/boards/mach-hp6xx/pm.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/boards/mach-hp6xx/pm.c	2011-03-14 21:20:32.000000000 -0400
@@ -143,7 +143,7 @@ static int hp6x0_pm_enter(suspend_state_
 	return 0;
 }
 
-static struct platform_suspend_ops hp6x0_pm_ops = {
+static const struct platform_suspend_ops hp6x0_pm_ops = {
 	.enter		= hp6x0_pm_enter,
 	.valid		= suspend_valid_only_mem,
 };
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/boards/mach-kfr2r09/setup.c linux-libre-2.6.38-gnu1/arch/sh/boards/mach-kfr2r09/setup.c
--- linux-libre-2.6.37-gnu1/arch/sh/boards/mach-kfr2r09/setup.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/boards/mach-kfr2r09/setup.c	2011-03-14 21:20:32.000000000 -0400
@@ -11,6 +11,7 @@
 #include <linux/platform_device.h>
 #include <linux/interrupt.h>
 #include <linux/mfd/sh_mobile_sdhi.h>
+#include <linux/mmc/host.h>
 #include <linux/mfd/tmio.h>
 #include <linux/mtd/physmap.h>
 #include <linux/mtd/onenand.h>
@@ -366,6 +367,7 @@ static struct sh_mobile_sdhi_info sh7724
 	.dma_slave_tx	= SHDMA_SLAVE_SDHI0_TX,
 	.dma_slave_rx	= SHDMA_SLAVE_SDHI0_RX,
 	.tmio_flags	= TMIO_MMC_WRPROTECT_DISABLE,
+	.tmio_caps      = MMC_CAP_SDIO_IRQ,
 };
 
 static struct platform_device kfr2r09_sh_sdhi0_device = {
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/boards/mach-landisk/irq.c linux-libre-2.6.38-gnu1/arch/sh/boards/mach-landisk/irq.c
--- linux-libre-2.6.37-gnu1/arch/sh/boards/mach-landisk/irq.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/boards/mach-landisk/irq.c	2011-03-14 21:20:32.000000000 -0400
@@ -1,9 +1,10 @@
 /*
- * arch/sh/boards/landisk/irq.c
+ * arch/sh/boards/mach-landisk/irq.c
  *
  * I-O DATA Device, Inc. LANDISK Support
  *
  * Copyright (C) 2005-2007 kogiidena
+ * Copyright (C) 2011 Nobuhiro Iwamatsu
  *
  * Copyright (C) 2001  Ian da Silva, Jeremy Siegel
  * Based largely on io_se.c.
@@ -12,44 +13,54 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  */
+
 #include <linux/init.h>
 #include <linux/irq.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
 #include <mach-landisk/mach/iodata_landisk.h>
 
-static void disable_landisk_irq(struct irq_data *data)
-{
-	unsigned char mask = 0xff ^ (0x01 << (data->irq - 5));
-
-	__raw_writeb(__raw_readb(PA_IMASK) & mask, PA_IMASK);
-}
+enum {
+	UNUSED = 0,
 
-static void enable_landisk_irq(struct irq_data *data)
-{
-	unsigned char value = (0x01 << (data->irq - 5));
+	PCI_INTA, /* PCI int A */
+	PCI_INTB, /* PCI int B */
+	PCI_INTC, /* PCI int C */
+	PCI_INTD, /* PCI int D */
+	ATA,	  /* ATA */
+	FATA,	  /* CF */
+	POWER,	  /* Power swtich */
+	BUTTON,	  /* Button swtich */
+};
 
-	__raw_writeb(__raw_readb(PA_IMASK) | value, PA_IMASK);
-}
+/* Vectors for LANDISK */
+static struct intc_vect vectors_landisk[] __initdata = {
+	INTC_IRQ(PCI_INTA, IRQ_PCIINTA),
+	INTC_IRQ(PCI_INTB, IRQ_PCIINTB),
+	INTC_IRQ(PCI_INTC, IRQ_PCIINTC),
+	INTC_IRQ(PCI_INTD, IRQ_PCIINTD),
+	INTC_IRQ(ATA, IRQ_ATA),
+	INTC_IRQ(FATA, IRQ_FATA),
+	INTC_IRQ(POWER, IRQ_POWER),
+	INTC_IRQ(BUTTON, IRQ_BUTTON),
+};
 
-static struct irq_chip landisk_irq_chip __read_mostly = {
-	.name		= "LANDISK",
-	.irq_mask	= disable_landisk_irq,
-	.irq_unmask	= enable_landisk_irq,
+/* IRLMSK mask register layout for LANDISK */
+static struct intc_mask_reg mask_registers_landisk[] __initdata = {
+	{ PA_IMASK, 0, 8, /* IRLMSK */
+	  {  BUTTON, POWER, FATA, ATA,
+	     PCI_INTD, PCI_INTC, PCI_INTB, PCI_INTA,
+	  }
+	},
 };
 
+static DECLARE_INTC_DESC(intc_desc_landisk, "landisk", vectors_landisk, NULL,
+			mask_registers_landisk, NULL, NULL);
 /*
  * Initialize IRQ setting
  */
 void __init init_landisk_IRQ(void)
 {
-	int i;
-
-	for (i = 5; i < 14; i++) {
-		disable_irq_nosync(i);
-		set_irq_chip_and_handler_name(i, &landisk_irq_chip,
-					      handle_level_irq, "level");
-		enable_landisk_irq(irq_get_irq_data(i));
-	}
+	register_intc_controller(&intc_desc_landisk);
 	__raw_writeb(0x00, PA_PWRINT_CLR);
 }
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/boards/mach-landisk/setup.c linux-libre-2.6.38-gnu1/arch/sh/boards/mach-landisk/setup.c
--- linux-libre-2.6.37-gnu1/arch/sh/boards/mach-landisk/setup.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/boards/mach-landisk/setup.c	2011-03-14 21:20:32.000000000 -0400
@@ -21,8 +21,6 @@
 #include <mach-landisk/mach/iodata_landisk.h>
 #include <asm/io.h>
 
-void init_landisk_IRQ(void);
-
 static void landisk_power_off(void)
 {
         __raw_writeb(0x01, PA_SHUTDOWN);
@@ -83,7 +81,7 @@ static int __init landisk_devices_setup(
 				    ARRAY_SIZE(landisk_devices));
 }
 
-__initcall(landisk_devices_setup);
+device_initcall(landisk_devices_setup);
 
 static void __init landisk_setup(char **cmdline_p)
 {
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/boards/mach-migor/setup.c linux-libre-2.6.38-gnu1/arch/sh/boards/mach-migor/setup.c
--- linux-libre-2.6.37-gnu1/arch/sh/boards/mach-migor/setup.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/boards/mach-migor/setup.c	2011-03-14 21:20:32.000000000 -0400
@@ -13,6 +13,7 @@
 #include <linux/input.h>
 #include <linux/input/sh_keysc.h>
 #include <linux/mfd/sh_mobile_sdhi.h>
+#include <linux/mmc/host.h>
 #include <linux/mtd/physmap.h>
 #include <linux/mtd/nand.h>
 #include <linux/i2c.h>
@@ -410,6 +411,7 @@ static struct resource sdhi_cn9_resource
 static struct sh_mobile_sdhi_info sh7724_sdhi_data = {
 	.dma_slave_tx	= SHDMA_SLAVE_SDHI0_TX,
 	.dma_slave_rx	= SHDMA_SLAVE_SDHI0_RX,
+	.tmio_caps      = MMC_CAP_SDIO_IRQ,
 };
 
 static struct platform_device sdhi_cn9_device = {
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/boards/mach-r2d/setup.c linux-libre-2.6.38-gnu1/arch/sh/boards/mach-r2d/setup.c
--- linux-libre-2.6.37-gnu1/arch/sh/boards/mach-r2d/setup.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/boards/mach-r2d/setup.c	2011-03-14 21:20:32.000000000 -0400
@@ -258,7 +258,7 @@ static int __init rts7751r2d_devices_set
 	return platform_add_devices(rts7751r2d_devices,
 				    ARRAY_SIZE(rts7751r2d_devices));
 }
-__initcall(rts7751r2d_devices_setup);
+device_initcall(rts7751r2d_devices_setup);
 
 static void rts7751r2d_power_off(void)
 {
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/boards/mach-rsk/devices-rsk7203.c linux-libre-2.6.38-gnu1/arch/sh/boards/mach-rsk/devices-rsk7203.c
--- linux-libre-2.6.37-gnu1/arch/sh/boards/mach-rsk/devices-rsk7203.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/boards/mach-rsk/devices-rsk7203.c	2011-03-14 21:20:32.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  * Renesas Technology Europe RSK+ 7203 Support.
  *
- * Copyright (C) 2008 Paul Mundt
+ * Copyright (C) 2008 - 2010  Paul Mundt
  *
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file "COPYING" in the main directory of this archive
@@ -12,7 +12,9 @@
 #include <linux/platform_device.h>
 #include <linux/interrupt.h>
 #include <linux/smsc911x.h>
+#include <linux/input.h>
 #include <linux/gpio.h>
+#include <linux/gpio_keys.h>
 #include <linux/leds.h>
 #include <asm/machvec.h>
 #include <asm/io.h>
@@ -84,9 +86,42 @@ static struct platform_device led_device
 	},
 };
 
+static struct gpio_keys_button rsk7203_gpio_keys_table[] = {
+	{
+		.code		= BTN_0,
+		.gpio		= GPIO_PB0,
+		.active_low	= 1,
+		.desc		= "SW1",
+	}, {
+		.code		= BTN_1,
+		.gpio		= GPIO_PB1,
+		.active_low	= 1,
+		.desc		= "SW2",
+	}, {
+		.code		= BTN_2,
+		.gpio		= GPIO_PB2,
+		.active_low	= 1,
+		.desc		= "SW3",
+	},
+};
+
+static struct gpio_keys_platform_data rsk7203_gpio_keys_info = {
+	.buttons	= rsk7203_gpio_keys_table,
+	.nbuttons	= ARRAY_SIZE(rsk7203_gpio_keys_table),
+	.poll_interval	= 50, /* default to 50ms */
+};
+
+static struct platform_device keys_device = {
+	.name		= "gpio-keys-polled",
+	.dev		= {
+		.platform_data	= &rsk7203_gpio_keys_info,
+	},
+};
+
 static struct platform_device *rsk7203_devices[] __initdata = {
 	&smsc911x_device,
 	&led_device,
+	&keys_device,
 };
 
 static int __init rsk7203_devices_setup(void)
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/boards/mach-sdk7786/Makefile linux-libre-2.6.38-gnu1/arch/sh/boards/mach-sdk7786/Makefile
--- linux-libre-2.6.37-gnu1/arch/sh/boards/mach-sdk7786/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/boards/mach-sdk7786/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -1,4 +1,4 @@
-obj-y	:= fpga.o irq.o setup.o
+obj-y	:= fpga.o irq.o nmi.o setup.o
 
 obj-$(CONFIG_GENERIC_GPIO)	+= gpio.o
 obj-$(CONFIG_HAVE_SRAM_POOL)	+= sram.o
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/boards/mach-sdk7786/nmi.c linux-libre-2.6.38-gnu1/arch/sh/boards/mach-sdk7786/nmi.c
--- linux-libre-2.6.37-gnu1/arch/sh/boards/mach-sdk7786/nmi.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/boards/mach-sdk7786/nmi.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,83 @@
+/*
+ * SDK7786 FPGA NMI Support.
+ *
+ * Copyright (C) 2010  Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <mach/fpga.h>
+
+enum {
+	NMI_MODE_MANUAL,
+	NMI_MODE_AUX,
+	NMI_MODE_MASKED,
+	NMI_MODE_ANY,
+	NMI_MODE_UNKNOWN,
+};
+
+/*
+ * Default to the manual NMI switch.
+ */
+static unsigned int __initdata nmi_mode = NMI_MODE_ANY;
+
+static int __init nmi_mode_setup(char *str)
+{
+	if (!str)
+		return 0;
+
+	if (strcmp(str, "manual") == 0)
+		nmi_mode = NMI_MODE_MANUAL;
+	else if (strcmp(str, "aux") == 0)
+		nmi_mode = NMI_MODE_AUX;
+	else if (strcmp(str, "masked") == 0)
+		nmi_mode = NMI_MODE_MASKED;
+	else if (strcmp(str, "any") == 0)
+		nmi_mode = NMI_MODE_ANY;
+	else {
+		nmi_mode = NMI_MODE_UNKNOWN;
+		pr_warning("Unknown NMI mode %s\n", str);
+	}
+
+	printk("Set NMI mode to %d\n", nmi_mode);
+	return 0;
+}
+early_param("nmi_mode", nmi_mode_setup);
+
+void __init sdk7786_nmi_init(void)
+{
+	unsigned int source, mask, tmp;
+
+	switch (nmi_mode) {
+	case NMI_MODE_MANUAL:
+		source = NMISR_MAN_NMI;
+		mask = NMIMR_MAN_NMIM;
+		break;
+	case NMI_MODE_AUX:
+		source = NMISR_AUX_NMI;
+		mask = NMIMR_AUX_NMIM;
+		break;
+	case NMI_MODE_ANY:
+		source = NMISR_MAN_NMI | NMISR_AUX_NMI;
+		mask = NMIMR_MAN_NMIM | NMIMR_AUX_NMIM;
+		break;
+	case NMI_MODE_MASKED:
+	case NMI_MODE_UNKNOWN:
+	default:
+		source = mask = 0;
+		break;
+	}
+
+	/* Set the NMI source */
+	tmp = fpga_read_reg(NMISR);
+	tmp &= ~NMISR_MASK;
+	tmp |= source;
+	fpga_write_reg(tmp, NMISR);
+
+	/* And the IRQ masking */
+	fpga_write_reg(NMIMR_MASK ^ mask, NMIMR);
+}
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/boards/mach-sdk7786/setup.c linux-libre-2.6.38-gnu1/arch/sh/boards/mach-sdk7786/setup.c
--- linux-libre-2.6.37-gnu1/arch/sh/boards/mach-sdk7786/setup.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/boards/mach-sdk7786/setup.c	2011-03-14 21:20:32.000000000 -0400
@@ -15,13 +15,13 @@
 #include <linux/i2c.h>
 #include <linux/irq.h>
 #include <linux/clk.h>
+#include <linux/clkdev.h>
 #include <mach/fpga.h>
 #include <mach/irq.h>
 #include <asm/machvec.h>
 #include <asm/heartbeat.h>
 #include <asm/sizes.h>
 #include <asm/clock.h>
-#include <asm/clkdev.h>
 #include <asm/reboot.h>
 #include <asm/smp-ops.h>
 
@@ -135,7 +135,7 @@ static int __init sdk7786_devices_setup(
 
 	return sdk7786_i2c_setup();
 }
-__initcall(sdk7786_devices_setup);
+device_initcall(sdk7786_devices_setup);
 
 static int sdk7786_mode_pins(void)
 {
@@ -237,6 +237,7 @@ static void __init sdk7786_setup(char **
 	pr_info("Renesas Technology Europe SDK7786 support:\n");
 
 	sdk7786_fpga_init();
+	sdk7786_nmi_init();
 
 	pr_info("\tPCB revision:\t%d\n", fpga_read_reg(PCBRR) & 0xf);
 
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/boards/mach-se/7206/setup.c linux-libre-2.6.38-gnu1/arch/sh/boards/mach-se/7206/setup.c
--- linux-libre-2.6.37-gnu1/arch/sh/boards/mach-se/7206/setup.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/boards/mach-se/7206/setup.c	2011-03-14 21:20:32.000000000 -0400
@@ -77,7 +77,12 @@ static int __init se7206_devices_setup(v
 {
 	return platform_add_devices(se7206_devices, ARRAY_SIZE(se7206_devices));
 }
-__initcall(se7206_devices_setup);
+device_initcall(se7206_devices_setup);
+
+static int se7206_mode_pins(void)
+{
+	return MODE_PIN1 | MODE_PIN2;
+}
 
 /*
  * The Machine Vector
@@ -87,4 +92,5 @@ static struct sh_machine_vector mv_se __
 	.mv_name		= "SolutionEngine",
 	.mv_nr_irqs		= 256,
 	.mv_init_irq		= init_se7206_IRQ,
+	.mv_mode_pins		= se7206_mode_pins,
 };
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/boards/mach-se/7724/setup.c linux-libre-2.6.38-gnu1/arch/sh/boards/mach-se/7724/setup.c
--- linux-libre-2.6.37-gnu1/arch/sh/boards/mach-se/7724/setup.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/boards/mach-se/7724/setup.c	2011-03-14 21:20:32.000000000 -0400
@@ -15,6 +15,7 @@
 #include <linux/interrupt.h>
 #include <linux/platform_device.h>
 #include <linux/mfd/sh_mobile_sdhi.h>
+#include <linux/mmc/host.h>
 #include <linux/mtd/physmap.h>
 #include <linux/delay.h>
 #include <linux/smc91x.h>
@@ -318,6 +319,10 @@ static struct platform_device fsi_device
 	},
 };
 
+static struct platform_device fsi_ak4642_device = {
+	.name		= "sh_fsi_a_ak4642",
+};
+
 /* KEYSC in SoC (Needs SW33-2 set to ON) */
 static struct sh_keysc_info keysc_info = {
 	.mode = SH_KEYSC_MODE_1,
@@ -467,6 +472,7 @@ static struct resource sdhi0_cn7_resourc
 static struct sh_mobile_sdhi_info sh7724_sdhi0_data = {
 	.dma_slave_tx	= SHDMA_SLAVE_SDHI0_TX,
 	.dma_slave_rx	= SHDMA_SLAVE_SDHI0_RX,
+	.tmio_caps      = MMC_CAP_SDIO_IRQ,
 };
 
 static struct platform_device sdhi0_cn7_device = {
@@ -498,6 +504,7 @@ static struct resource sdhi1_cn8_resourc
 static struct sh_mobile_sdhi_info sh7724_sdhi1_data = {
 	.dma_slave_tx	= SHDMA_SLAVE_SDHI1_TX,
 	.dma_slave_rx	= SHDMA_SLAVE_SDHI1_RX,
+	.tmio_caps      = MMC_CAP_SDIO_IRQ,
 };
 
 static struct platform_device sdhi1_cn8_device = {
@@ -590,6 +597,7 @@ static struct platform_device *ms7724se_
 	&sh7724_usb0_host_device,
 	&sh7724_usb1_gadget_device,
 	&fsi_device,
+	&fsi_ak4642_device,
 	&sdhi0_cn7_device,
 	&sdhi1_cn8_device,
 	&irda_device,
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/boards/mach-se/7751/setup.c linux-libre-2.6.38-gnu1/arch/sh/boards/mach-se/7751/setup.c
--- linux-libre-2.6.37-gnu1/arch/sh/boards/mach-se/7751/setup.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/boards/mach-se/7751/setup.c	2011-03-14 21:20:32.000000000 -0400
@@ -48,7 +48,7 @@ static int __init se7751_devices_setup(v
 {
 	return platform_add_devices(se7751_devices, ARRAY_SIZE(se7751_devices));
 }
-__initcall(se7751_devices_setup);
+device_initcall(se7751_devices_setup);
 
 /*
  * The Machine Vector
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/boards/mach-se/board-se7619.c linux-libre-2.6.38-gnu1/arch/sh/boards/mach-se/board-se7619.c
--- linux-libre-2.6.37-gnu1/arch/sh/boards/mach-se/board-se7619.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/boards/mach-se/board-se7619.c	2011-03-14 21:20:32.000000000 -0400
@@ -11,6 +11,11 @@
 #include <asm/io.h>
 #include <asm/machvec.h>
 
+static int se7619_mode_pins(void)
+{
+	return MODE_PIN2 | MODE_PIN0;
+}
+
 /*
  * The Machine Vector
  */
@@ -18,4 +23,5 @@
 static struct sh_machine_vector mv_se __initmv = {
 	.mv_name		= "SolutionEngine",
 	.mv_nr_irqs		= 108,
+	.mv_mode_pins		= se7619_mode_pins,
 };
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/boards/mach-sh03/rtc.c linux-libre-2.6.38-gnu1/arch/sh/boards/mach-sh03/rtc.c
--- linux-libre-2.6.37-gnu1/arch/sh/boards/mach-sh03/rtc.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/boards/mach-sh03/rtc.c	2011-03-14 21:20:32.000000000 -0400
@@ -108,7 +108,7 @@ static int set_rtc_mmss(unsigned long no
 		__raw_writeb(real_minutes % 10, RTC_MIN1);
 		__raw_writeb(real_minutes / 10, RTC_MIN10);
 	} else {
-		printk(KERN_WARNING
+		printk_once(KERN_NOTICE
 		       "set_rtc_mmss: can't update from %d to %d\n",
 		       cmos_minutes, real_minutes);
 		retval = -1;
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/boards/mach-sh03/setup.c linux-libre-2.6.38-gnu1/arch/sh/boards/mach-sh03/setup.c
--- linux-libre-2.6.37-gnu1/arch/sh/boards/mach-sh03/setup.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/boards/mach-sh03/setup.c	2011-03-14 21:20:32.000000000 -0400
@@ -96,7 +96,7 @@ static int __init sh03_devices_setup(voi
 
 	return platform_add_devices(sh03_devices, ARRAY_SIZE(sh03_devices));
 }
-__initcall(sh03_devices_setup);
+device_initcall(sh03_devices_setup);
 
 static struct sh_machine_vector mv_sh03 __initmv = {
 	.mv_name		= "Interface (CTP/PCI-SH03)",
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/boards/Makefile linux-libre-2.6.38-gnu1/arch/sh/boards/Makefile
--- linux-libre-2.6.37-gnu1/arch/sh/boards/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/boards/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -13,3 +13,5 @@ obj-$(CONFIG_SH_ESPT)		+= board-espt.o
 obj-$(CONFIG_SH_POLARIS)	+= board-polaris.o
 obj-$(CONFIG_SH_TITAN)		+= board-titan.o
 obj-$(CONFIG_SH_SH7757LCR)	+= board-sh7757lcr.o
+obj-$(CONFIG_SH_APSH4A3A)	+= board-apsh4a3a.o
+obj-$(CONFIG_SH_APSH4AD0A)	+= board-apsh4ad0a.o
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/boot/compressed/Makefile linux-libre-2.6.38-gnu1/arch/sh/boot/compressed/Makefile
--- linux-libre-2.6.37-gnu1/arch/sh/boot/compressed/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/boot/compressed/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -6,7 +6,7 @@
 
 targets		:= vmlinux vmlinux.bin vmlinux.bin.gz \
 		   vmlinux.bin.bz2 vmlinux.bin.lzma \
-		   vmlinux.bin.lzo \
+		   vmlinux.bin.xz vmlinux.bin.lzo \
 		   head_$(BITS).o misc.o piggy.o
 
 OBJECTS = $(obj)/head_$(BITS).o $(obj)/misc.o $(obj)/cache.o
@@ -50,6 +50,8 @@ $(obj)/vmlinux.bin.bz2: $(vmlinux.bin.al
 	$(call if_changed,bzip2)
 $(obj)/vmlinux.bin.lzma: $(vmlinux.bin.all-y) FORCE
 	$(call if_changed,lzma)
+$(obj)/vmlinux.bin.xz: $(vmlinux.bin.all-y) FORCE
+	$(call if_changed,xzkern)
 $(obj)/vmlinux.bin.lzo: $(vmlinux.bin.all-y) FORCE
 	$(call if_changed,lzo)
 
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/boot/compressed/misc.c linux-libre-2.6.38-gnu1/arch/sh/boot/compressed/misc.c
--- linux-libre-2.6.37-gnu1/arch/sh/boot/compressed/misc.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/boot/compressed/misc.c	2011-03-14 21:20:32.000000000 -0400
@@ -61,6 +61,10 @@ static unsigned long free_mem_end_ptr;
 #include "../../../../lib/decompress_unlzma.c"
 #endif
 
+#ifdef CONFIG_KERNEL_XZ
+#include "../../../../lib/decompress_unxz.c"
+#endif
+
 #ifdef CONFIG_KERNEL_LZO
 #include "../../../../lib/decompress_unlzo.c"
 #endif
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/boot/Makefile linux-libre-2.6.38-gnu1/arch/sh/boot/Makefile
--- linux-libre-2.6.37-gnu1/arch/sh/boot/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/boot/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -24,12 +24,13 @@ suffix-y := bin
 suffix-$(CONFIG_KERNEL_GZIP)	:= gz
 suffix-$(CONFIG_KERNEL_BZIP2)	:= bz2
 suffix-$(CONFIG_KERNEL_LZMA)	:= lzma
+suffix-$(CONFIG_KERNEL_XZ)	:= xz
 suffix-$(CONFIG_KERNEL_LZO)	:= lzo
 
 targets := zImage vmlinux.srec romImage uImage uImage.srec uImage.gz \
-	   uImage.bz2 uImage.lzma uImage.lzo uImage.bin
+	   uImage.bz2 uImage.lzma uImage.xz uImage.lzo uImage.bin
 extra-y += vmlinux.bin vmlinux.bin.gz vmlinux.bin.bz2 vmlinux.bin.lzma \
-	   vmlinux.bin.lzo
+	   vmlinux.bin.xz vmlinux.bin.lzo
 subdir- := compressed romimage
 
 $(obj)/zImage: $(obj)/compressed/vmlinux FORCE
@@ -76,6 +77,9 @@ $(obj)/vmlinux.bin.bz2: $(obj)/vmlinux.b
 $(obj)/vmlinux.bin.lzma: $(obj)/vmlinux.bin FORCE
 	$(call if_changed,lzma)
 
+$(obj)/vmlinux.bin.xz: $(obj)/vmlinux.bin FORCE
+	$(call if_changed,xzkern)
+
 $(obj)/vmlinux.bin.lzo: $(obj)/vmlinux.bin FORCE
 	$(call if_changed,lzo)
 
@@ -88,6 +92,9 @@ $(obj)/uImage.gz: $(obj)/vmlinux.bin.gz
 $(obj)/uImage.lzma: $(obj)/vmlinux.bin.lzma
 	$(call if_changed,uimage,lzma)
 
+$(obj)/uImage.xz: $(obj)/vmlinux.bin.xz
+	$(call if_changed,uimage,xz)
+
 $(obj)/uImage.lzo: $(obj)/vmlinux.bin.lzo
 	$(call if_changed,uimage,lzo)
 
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/boot/romimage/mmcif-sh7724.c linux-libre-2.6.38-gnu1/arch/sh/boot/romimage/mmcif-sh7724.c
--- linux-libre-2.6.37-gnu1/arch/sh/boot/romimage/mmcif-sh7724.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/boot/romimage/mmcif-sh7724.c	2011-03-14 21:20:32.000000000 -0400
@@ -21,9 +21,6 @@
 #define HIZCRC		0xa405015c
 #define DRVCRA		0xa405018a
 
-enum { MMCIF_PROGRESS_ENTER, MMCIF_PROGRESS_INIT,
-       MMCIF_PROGRESS_LOAD, MMCIF_PROGRESS_DONE };
-
 /* SH7724 specific MMCIF loader
  *
  * loads the romImage from an MMC card starting from block 512
@@ -63,7 +60,9 @@ asmlinkage void mmcif_loader(unsigned ch
 	mmcif_update_progress(MMCIF_PROGRESS_LOAD);
 
 	/* load kernel via MMCIF interface */
-	sh_mmcif_boot_slurp(MMCIF_BASE, buf, no_bytes);
+	sh_mmcif_boot_do_read(MMCIF_BASE, 512,
+	                      (no_bytes + SH_MMCIF_BBS - 1) / SH_MMCIF_BBS,
+			      buf);
 
 	/* disable clock to the MMCIF hardware block */
 	__raw_writel(__raw_readl(MSTPCR2) | 0x20000000, MSTPCR2);
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/configs/apsh4a3a_defconfig linux-libre-2.6.38-gnu1/arch/sh/configs/apsh4a3a_defconfig
--- linux-libre-2.6.37-gnu1/arch/sh/configs/apsh4a3a_defconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/configs/apsh4a3a_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,102 @@
+CONFIG_EXPERIMENTAL=y
+CONFIG_SYSVIPC=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_SLAB=y
+CONFIG_PROFILING=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_BLK_DEV_BSG is not set
+CONFIG_CPU_SUBTYPE_SH7785=y
+CONFIG_MEMORY_START=0x0C000000
+CONFIG_FLATMEM_MANUAL=y
+CONFIG_SH_STORE_QUEUES=y
+CONFIG_SH_APSH4A3A=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_KEXEC=y
+CONFIG_PREEMPT=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_INET_LRO is not set
+# CONFIG_IPV6 is not set
+# CONFIG_WIRELESS is not set
+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_CHAR=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_CFI=y
+CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_MTD_PHYSMAP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=16384
+CONFIG_NETDEVICES=y
+CONFIG_NET_ETHERNET=y
+CONFIG_SMSC911X=y
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+# CONFIG_WLAN 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_VT_HW_CONSOLE_BINDING=y
+CONFIG_SERIAL_SH_SCI=y
+CONFIG_SERIAL_SH_SCI_NR_UARTS=6
+CONFIG_SERIAL_SH_SCI_CONSOLE=y
+CONFIG_HW_RANDOM=y
+# CONFIG_HWMON is not set
+CONFIG_FB=y
+CONFIG_FB_SH7785FB=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FONTS=y
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+CONFIG_LOGO=y
+# CONFIG_HID_SUPPORT is not set
+# CONFIG_USB_SUPPORT is not set
+CONFIG_EXT2_FS=y
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_NTFS_FS=y
+CONFIG_NTFS_RW=y
+CONFIG_PROC_KCORE=y
+CONFIG_TMPFS=y
+CONFIG_JFFS2_FS=y
+CONFIG_CRAMFS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_NFS_V4=y
+CONFIG_CIFS=y
+CONFIG_NLS_DEFAULT="utf8"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_932=y
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_UTF8=y
+# CONFIG_ENABLE_WARN_DEPRECATED is not set
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_DEBUG_FS=y
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_PREEMPT is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_DEBUG_INFO=y
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_FTRACE is not set
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+# CONFIG_CRYPTO_HW is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/configs/apsh4ad0a_defconfig linux-libre-2.6.38-gnu1/arch/sh/configs/apsh4ad0a_defconfig
--- linux-libre-2.6.37-gnu1/arch/sh/configs/apsh4ad0a_defconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/configs/apsh4ad0a_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,133 @@
+CONFIG_EXPERIMENTAL=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_RCU_TRACE=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_CGROUPS=y
+CONFIG_CGROUP_NS=y
+CONFIG_CGROUP_FREEZER=y
+CONFIG_CGROUP_DEVICE=y
+CONFIG_CGROUP_CPUACCT=y
+CONFIG_RESOURCE_COUNTERS=y
+CONFIG_CGROUP_MEM_RES_CTLR=y
+CONFIG_BLK_CGROUP=y
+CONFIG_NAMESPACES=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_KALLSYMS_ALL=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_SLAB=y
+CONFIG_PROFILING=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_LBDAF is not set
+# CONFIG_BLK_DEV_BSG is not set
+CONFIG_CFQ_GROUP_IOSCHED=y
+CONFIG_CPU_SUBTYPE_SH7786=y
+CONFIG_MEMORY_SIZE=0x10000000
+CONFIG_HUGETLB_PAGE_SIZE_1MB=y
+CONFIG_MEMORY_HOTPLUG=y
+CONFIG_MEMORY_HOTREMOVE=y
+CONFIG_KSM=y
+CONFIG_SH_STORE_QUEUES=y
+CONFIG_SH_APSH4AD0A=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=m
+CONFIG_CPU_FREQ_GOV_USERSPACE=m
+CONFIG_CPU_FREQ_GOV_ONDEMAND=m
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m
+CONFIG_SH_CPU_FREQ=y
+CONFIG_KEXEC=y
+CONFIG_SECCOMP=y
+CONFIG_PREEMPT=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_BINFMT_MISC=y
+CONFIG_PM=y
+CONFIG_PM_DEBUG=y
+CONFIG_PM_VERBOSE=y
+CONFIG_PM_RUNTIME=y
+CONFIG_CPU_IDLE=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+# CONFIG_INET_LRO is not set
+# CONFIG_IPV6 is not set
+# CONFIG_WIRELESS is not set
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+# CONFIG_FW_LOADER is not set
+CONFIG_MTD=y
+CONFIG_MTD_CFI=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=16384
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_SCSI_MULTI_LUN=y
+# CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_NETDEVICES=y
+CONFIG_MDIO_BITBANG=y
+CONFIG_NET_ETHERNET=y
+CONFIG_SMSC911X=y
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+# CONFIG_WLAN is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_SERIO is not set
+CONFIG_SERIAL_SH_SCI=y
+CONFIG_SERIAL_SH_SCI_NR_UARTS=6
+CONFIG_SERIAL_SH_SCI_CONSOLE=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_HWMON is not set
+CONFIG_VIDEO_OUTPUT_CONTROL=y
+CONFIG_FB=y
+CONFIG_FB_SH7785FB=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FONTS=y
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+CONFIG_LOGO=y
+CONFIG_USB=y
+CONFIG_USB_DEBUG=y
+CONFIG_USB_MON=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_STORAGE=y
+CONFIG_EXT2_FS=y
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_NTFS_FS=y
+CONFIG_NTFS_RW=y
+CONFIG_PROC_KCORE=y
+CONFIG_TMPFS=y
+CONFIG_HUGETLBFS=y
+CONFIG_JFFS2_FS=y
+CONFIG_CRAMFS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_NFS_V4=y
+CONFIG_CIFS=y
+CONFIG_NLS_DEFAULT="utf8"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_932=y
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_UTF8=y
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_DEBUG_SHIRQ=y
+CONFIG_DETECT_HUNG_TASK=y
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_VM=y
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+CONFIG_DWARF_UNWINDER=y
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/configs/migor_defconfig linux-libre-2.6.38-gnu1/arch/sh/configs/migor_defconfig
--- linux-libre-2.6.37-gnu1/arch/sh/configs/migor_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/configs/migor_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -54,6 +54,8 @@ CONFIG_INPUT_EVDEV=y
 # CONFIG_KEYBOARD_ATKBD is not set
 CONFIG_KEYBOARD_SH_KEYSC=y
 # CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_MIGOR=y
 # CONFIG_SERIO is not set
 CONFIG_VT_HW_CONSOLE_BINDING=y
 CONFIG_SERIAL_SH_SCI=y
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/configs/sh7757lcr_defconfig linux-libre-2.6.38-gnu1/arch/sh/configs/sh7757lcr_defconfig
--- linux-libre-2.6.37-gnu1/arch/sh/configs/sh7757lcr_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/configs/sh7757lcr_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -39,21 +39,15 @@ CONFIG_IPV6=y
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 # CONFIG_FW_LOADER is not set
 CONFIG_BLK_DEV_RAM=y
-# CONFIG_MISC_DEVICES is not set
 CONFIG_NETDEVICES=y
-CONFIG_PHYLIB=y
 CONFIG_VITESSE_PHY=y
-CONFIG_MDIO_BITBANG=y
 CONFIG_NET_ETHERNET=y
-CONFIG_MII=y
+CONFIG_SH_ETH=y
 # CONFIG_NETDEV_10000 is not set
 # CONFIG_WLAN is not set
 # CONFIG_KEYBOARD_ATKBD is not set
 # CONFIG_MOUSE_PS2 is not set
 # CONFIG_SERIO is not set
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_NR_UARTS=2
 CONFIG_SERIAL_SH_SCI=y
 CONFIG_SERIAL_SH_SCI_NR_UARTS=3
 CONFIG_SERIAL_SH_SCI_CONSOLE=y
@@ -63,7 +57,6 @@ CONFIG_SERIAL_SH_SCI_CONSOLE=y
 # CONFIG_USB_SUPPORT is not set
 CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
-CONFIG_INOTIFY=y
 CONFIG_ISO9660_FS=y
 CONFIG_VFAT_FS=y
 CONFIG_PROC_KCORE=y
@@ -76,10 +69,8 @@ CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_CODEPAGE_932=y
 CONFIG_NLS_ISO8859_1=y
 CONFIG_DEBUG_KERNEL=y
-# CONFIG_DETECT_SOFTLOCKUP is not set
 # CONFIG_SCHED_DEBUG is not set
 # CONFIG_DEBUG_BUGVERBOSE is not set
 CONFIG_DEBUG_INFO=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
 # CONFIG_FTRACE is not set
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/drivers/pci/fixups-landisk.c linux-libre-2.6.38-gnu1/arch/sh/drivers/pci/fixups-landisk.c
--- linux-libre-2.6.37-gnu1/arch/sh/drivers/pci/fixups-landisk.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/drivers/pci/fixups-landisk.c	2011-03-14 21:20:32.000000000 -0400
@@ -1,9 +1,10 @@
 /*
- * arch/sh/drivers/pci/ops-landisk.c
+ * arch/sh/drivers/pci/fixups-landisk.c
  *
  * PCI initialization for the I-O DATA Device, Inc. LANDISK board
  *
  * Copyright (C) 2006 kogiidena
+ * Copyright (C) 2010 Nobuhiro Iwamatsu
  *
  * May be copied or modified under the terms of the GNU General Public
  * License.  See linux/COPYING for more information.
@@ -15,6 +16,9 @@
 #include <linux/pci.h>
 #include "pci-sh4.h"
 
+#define PCIMCR_MRSET_OFF	0xBFFFFFFF
+#define PCIMCR_RFSH_OFF		0xFFFFFFFB
+
 int pcibios_map_platform_irq(struct pci_dev *pdev, u8 slot, u8 pin)
 {
 	/*
@@ -26,9 +30,29 @@ int pcibios_map_platform_irq(struct pci_
 	int irq = ((slot + pin - 1) & 0x3) + 5;
 
 	if ((slot | (pin - 1)) > 0x3) {
-		printk("PCI: Bad IRQ mapping request for slot %d pin %c\n",
+		printk(KERN_WARNING "PCI: Bad IRQ mapping request for slot %d pin %c\n",
 		       slot, pin - 1 + 'A');
 		return -1;
 	}
 	return irq;
 }
+
+int pci_fixup_pcic(struct pci_channel *chan)
+{
+	unsigned long bcr1, mcr;
+
+	bcr1 = __raw_readl(SH7751_BCR1);
+	bcr1 |= 0x40080000;	/* Enable Bit 19 BREQEN, set PCIC to slave */
+	pci_write_reg(chan, bcr1, SH4_PCIBCR1);
+
+	mcr = __raw_readl(SH7751_MCR);
+	mcr = (mcr & PCIMCR_MRSET_OFF) & PCIMCR_RFSH_OFF;
+	pci_write_reg(chan, mcr, SH4_PCIMCR);
+
+	pci_write_reg(chan, 0x0c000000, SH7751_PCICONF5);
+	pci_write_reg(chan, 0xd0000000, SH7751_PCICONF6);
+	pci_write_reg(chan, 0x0c000000, SH4_PCILAR0);
+	pci_write_reg(chan, 0x00000000, SH4_PCILAR1);
+
+	return 0;
+}
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/drivers/pci/pci.c linux-libre-2.6.38-gnu1/arch/sh/drivers/pci/pci.c
--- linux-libre-2.6.37-gnu1/arch/sh/drivers/pci/pci.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/drivers/pci/pci.c	2011-03-14 21:20:32.000000000 -0400
@@ -382,14 +382,13 @@ static void __iomem *ioport_map_pci(stru
 	struct pci_channel *chan = dev->sysdata;
 
 	if (unlikely(!chan->io_map_base)) {
-		chan->io_map_base = generic_io_base;
+		chan->io_map_base = sh_io_port_base;
 
 		if (pci_domains_supported)
 			panic("To avoid data corruption io_map_base MUST be "
 			      "set with multiple PCI domains.");
 	}
 
-
 	return (void __iomem *)(chan->io_map_base + port);
 }
 
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/drivers/push-switch.c linux-libre-2.6.38-gnu1/arch/sh/drivers/push-switch.c
--- linux-libre-2.6.37-gnu1/arch/sh/drivers/push-switch.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/drivers/push-switch.c	2011-03-14 21:20:32.000000000 -0400
@@ -107,7 +107,7 @@ static int switch_drv_remove(struct plat
 		device_remove_file(&pdev->dev, &dev_attr_switch);
 
 	platform_set_drvdata(pdev, NULL);
-	flush_scheduled_work();
+	flush_work_sync(&psw->work);
 	del_timer_sync(&psw->debounce);
 	free_irq(irq, pdev);
 
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/include/asm/clkdev.h linux-libre-2.6.38-gnu1/arch/sh/include/asm/clkdev.h
--- linux-libre-2.6.37-gnu1/arch/sh/include/asm/clkdev.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/include/asm/clkdev.h	2011-03-14 21:20:32.000000000 -0400
@@ -1,9 +1,5 @@
 /*
- *  arch/sh/include/asm/clkdev.h
- *
- * Cloned from arch/arm/include/asm/clkdev.h:
- *
- *  Copyright (C) 2008 Russell King.
+ *  Copyright (C) 2010 Paul Mundt <lethal@linux-sh.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
@@ -11,25 +7,25 @@
  *
  * Helper for the clk API to assist looking up a struct clk.
  */
-#ifndef __ASM_CLKDEV_H
-#define __ASM_CLKDEV_H
 
-struct clk;
+#ifndef __CLKDEV__H_
+#define __CLKDEV__H_
 
-struct clk_lookup {
-	struct list_head	node;
-	const char		*dev_id;
-	const char		*con_id;
-	struct clk		*clk;
-};
+#include <linux/bootmem.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
 
-struct clk_lookup *clkdev_alloc(struct clk *clk, const char *con_id,
-	const char *dev_fmt, ...);
+#include <asm/clock.h>
 
-void clkdev_add(struct clk_lookup *cl);
-void clkdev_drop(struct clk_lookup *cl);
+static inline struct clk_lookup_alloc *__clkdev_alloc(size_t size)
+{
+	if (!slab_is_available())
+		return alloc_bootmem_low_pages(size);
+	else
+		return kzalloc(size, GFP_KERNEL);
+}
 
-void clkdev_add_table(struct clk_lookup *, size_t);
-int clk_add_alias(const char *, const char *, char *, struct device *);
+#define __clk_put(clk)
+#define __clk_get(clk) ({ 1; })
 
-#endif
+#endif /* __CLKDEV_H__ */
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/include/asm/ioctls.h linux-libre-2.6.38-gnu1/arch/sh/include/asm/ioctls.h
--- linux-libre-2.6.37-gnu1/arch/sh/include/asm/ioctls.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/include/asm/ioctls.h	2011-03-14 21:20:32.000000000 -0400
@@ -85,6 +85,7 @@
 #define TCSETSF2	_IOW('T', 45, struct termios2)
 #define TIOCGPTN	_IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
 #define TIOCSPTLCK	_IOW('T',0x31, int)  /* Lock/unlock Pty */
+#define TIOCGDEV	_IOR('T',0x32, unsigned int) /* Get primary device node of /dev/console */
 #define TIOCSIG		_IOW('T',0x36, int)  /* Generate signal on Pty slave */
 
 #define TIOCSERCONFIG	_IO('T', 83) /* 0x5453 */
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/include/asm/io_generic.h linux-libre-2.6.38-gnu1/arch/sh/include/asm/io_generic.h
--- linux-libre-2.6.37-gnu1/arch/sh/include/asm/io_generic.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/include/asm/io_generic.h	2011-03-14 21:20:32.000000000 -0400
@@ -11,31 +11,6 @@
 #error "Don't include this header without a valid system prefix"
 #endif
 
-u8 IO_CONCAT(__IO_PREFIX,inb)(unsigned long);
-u16 IO_CONCAT(__IO_PREFIX,inw)(unsigned long);
-u32 IO_CONCAT(__IO_PREFIX,inl)(unsigned long);
-
-void IO_CONCAT(__IO_PREFIX,outb)(u8, unsigned long);
-void IO_CONCAT(__IO_PREFIX,outw)(u16, unsigned long);
-void IO_CONCAT(__IO_PREFIX,outl)(u32, unsigned long);
-
-u8 IO_CONCAT(__IO_PREFIX,inb_p)(unsigned long);
-u16 IO_CONCAT(__IO_PREFIX,inw_p)(unsigned long);
-u32 IO_CONCAT(__IO_PREFIX,inl_p)(unsigned long);
-void IO_CONCAT(__IO_PREFIX,outb_p)(u8, unsigned long);
-void IO_CONCAT(__IO_PREFIX,outw_p)(u16, unsigned long);
-void IO_CONCAT(__IO_PREFIX,outl_p)(u32, unsigned long);
-
-void IO_CONCAT(__IO_PREFIX,insb)(unsigned long, void *dst, unsigned long count);
-void IO_CONCAT(__IO_PREFIX,insw)(unsigned long, void *dst, unsigned long count);
-void IO_CONCAT(__IO_PREFIX,insl)(unsigned long, void *dst, unsigned long count);
-void IO_CONCAT(__IO_PREFIX,outsb)(unsigned long, const void *src, unsigned long count);
-void IO_CONCAT(__IO_PREFIX,outsw)(unsigned long, const void *src, unsigned long count);
-void IO_CONCAT(__IO_PREFIX,outsl)(unsigned long, const void *src, unsigned long count);
-
-void *IO_CONCAT(__IO_PREFIX,ioremap)(unsigned long offset, unsigned long size);
-void IO_CONCAT(__IO_PREFIX,iounmap)(void *addr);
-
 void __iomem *IO_CONCAT(__IO_PREFIX,ioport_map)(unsigned long addr, unsigned int size);
 void IO_CONCAT(__IO_PREFIX,ioport_unmap)(void __iomem *addr);
 void IO_CONCAT(__IO_PREFIX,mem_init)(void);
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/include/asm/io.h linux-libre-2.6.38-gnu1/arch/sh/include/asm/io.h
--- linux-libre-2.6.37-gnu1/arch/sh/include/asm/io.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/include/asm/io.h	2011-03-14 21:20:32.000000000 -0400
@@ -1,5 +1,6 @@
 #ifndef __ASM_SH_IO_H
 #define __ASM_SH_IO_H
+
 /*
  * Convention:
  *    read{b,w,l,q}/write{b,w,l,q} are for PCI,
@@ -10,17 +11,6 @@
  *
  * While read{b,w,l,q} and write{b,w,l,q} contain memory barriers
  * automatically, there are also __raw versions, which do not.
- *
- * Historically, we have also had ctrl_in{b,w,l,q}/ctrl_out{b,w,l,q} for
- * SuperH specific I/O (raw I/O to on-chip CPU peripherals). In practice
- * these have the same semantics as the __raw variants, and as such, all
- * new code should be using the __raw versions.
- *
- * All ISA I/O routines are wrapped through the machine vector. If a
- * board does not provide overrides, a generic set that are copied in
- * from the default machine vector are used instead. These are largely
- * for old compat code for I/O offseting to SuperIOs, all of which are
- * better handled through the machvec ioport mapping routines these days.
  */
 #include <linux/errno.h>
 #include <asm/cache.h>
@@ -31,39 +21,10 @@
 #include <asm-generic/iomap.h>
 
 #ifdef __KERNEL__
-/*
- * Depending on which platform we are running on, we need different
- * I/O functions.
- */
-#define __IO_PREFIX	generic
+#define __IO_PREFIX     generic
 #include <asm/io_generic.h>
 #include <asm/io_trapped.h>
 
-#ifdef CONFIG_HAS_IOPORT
-
-#define inb(p)			sh_mv.mv_inb((p))
-#define inw(p)			sh_mv.mv_inw((p))
-#define inl(p)			sh_mv.mv_inl((p))
-#define outb(x,p)		sh_mv.mv_outb((x),(p))
-#define outw(x,p)		sh_mv.mv_outw((x),(p))
-#define outl(x,p)		sh_mv.mv_outl((x),(p))
-
-#define inb_p(p)		sh_mv.mv_inb_p((p))
-#define inw_p(p)		sh_mv.mv_inw_p((p))
-#define inl_p(p)		sh_mv.mv_inl_p((p))
-#define outb_p(x,p)		sh_mv.mv_outb_p((x),(p))
-#define outw_p(x,p)		sh_mv.mv_outw_p((x),(p))
-#define outl_p(x,p)		sh_mv.mv_outl_p((x),(p))
-
-#define insb(p,b,c)		sh_mv.mv_insb((p), (b), (c))
-#define insw(p,b,c)		sh_mv.mv_insw((p), (b), (c))
-#define insl(p,b,c)		sh_mv.mv_insl((p), (b), (c))
-#define outsb(p,b,c)		sh_mv.mv_outsb((p), (b), (c))
-#define outsw(p,b,c)		sh_mv.mv_outsw((p), (b), (c))
-#define outsl(p,b,c)		sh_mv.mv_outsl((p), (b), (c))
-
-#endif
-
 #define __raw_writeb(v,a)	(__chk_io_ptr(a), *(volatile u8  __force *)(a) = (v))
 #define __raw_writew(v,a)	(__chk_io_ptr(a), *(volatile u16 __force *)(a) = (v))
 #define __raw_writel(v,a)	(__chk_io_ptr(a), *(volatile u32 __force *)(a) = (v))
@@ -74,68 +35,39 @@
 #define __raw_readl(a)		(__chk_io_ptr(a), *(volatile u32 __force *)(a))
 #define __raw_readq(a)		(__chk_io_ptr(a), *(volatile u64 __force *)(a))
 
-#define readb(a)		({ u8  r_ = __raw_readb(a); mb(); r_; })
-#define readw(a)		({ u16 r_ = __raw_readw(a); mb(); r_; })
-#define readl(a)		({ u32 r_ = __raw_readl(a); mb(); r_; })
-#define readq(a)		({ u64 r_ = __raw_readq(a); mb(); r_; })
-
-#define writeb(v,a)		({ __raw_writeb((v),(a)); mb(); })
-#define writew(v,a)		({ __raw_writew((v),(a)); mb(); })
-#define writel(v,a)		({ __raw_writel((v),(a)); mb(); })
-#define writeq(v,a)		({ __raw_writeq((v),(a)); mb(); })
-
-/*
- * Legacy SuperH on-chip I/O functions
- *
- * These are all deprecated, all new (and especially cross-platform) code
- * should be using the __raw_xxx() routines directly.
- */
-static inline u8 __deprecated ctrl_inb(unsigned long addr)
-{
-	return __raw_readb(addr);
-}
-
-static inline u16 __deprecated ctrl_inw(unsigned long addr)
-{
-	return __raw_readw(addr);
-}
-
-static inline u32 __deprecated ctrl_inl(unsigned long addr)
-{
-	return __raw_readl(addr);
-}
-
-static inline u64 __deprecated ctrl_inq(unsigned long addr)
-{
-	return __raw_readq(addr);
-}
-
-static inline void __deprecated ctrl_outb(u8 v, unsigned long addr)
-{
-	__raw_writeb(v, addr);
-}
+#define readb_relaxed(c)	({ u8  __v = __raw_readb(c); __v; })
+#define readw_relaxed(c)	({ u16 __v = le16_to_cpu((__force __le16) \
+					__raw_readw(c)); __v; })
+#define readl_relaxed(c)	({ u32 __v = le32_to_cpu((__force __le32) \
+					__raw_readl(c)); __v; })
+#define readq_relaxed(c)	({ u64 __v = le64_to_cpu((__force __le64) \
+					__raw_readq(c)); __v; })
 
-static inline void __deprecated ctrl_outw(u16 v, unsigned long addr)
-{
-	__raw_writew(v, addr);
-}
+#define writeb_relaxed(v,c)	((void)__raw_writeb(v,c))
+#define writew_relaxed(v,c)	((void)__raw_writew((__force u16) \
+					cpu_to_le16(v),c))
+#define writel_relaxed(v,c)	((void)__raw_writel((__force u32) \
+					cpu_to_le32(v),c))
+#define writeq_relaxed(v,c)	((void)__raw_writeq((__force u64) \
+					cpu_to_le64(v),c))
 
-static inline void __deprecated ctrl_outl(u32 v, unsigned long addr)
-{
-	__raw_writel(v, addr);
-}
+#define readb(a)		({ u8  r_ = readb_relaxed(a); rmb(); r_; })
+#define readw(a)		({ u16 r_ = readw_relaxed(a); rmb(); r_; })
+#define readl(a)		({ u32 r_ = readl_relaxed(a); rmb(); r_; })
+#define readq(a)		({ u64 r_ = readq_relaxed(a); rmb(); r_; })
 
-static inline void __deprecated ctrl_outq(u64 v, unsigned long addr)
-{
-	__raw_writeq(v, addr);
-}
+#define writeb(v,a)		({ wmb(); writeb_relaxed((v),(a)); })
+#define writew(v,a)		({ wmb(); writew_relaxed((v),(a)); })
+#define writel(v,a)		({ wmb(); writel_relaxed((v),(a)); })
+#define writeq(v,a)		({ wmb(); writeq_relaxed((v),(a)); })
 
-extern unsigned long generic_io_base;
+#define readsb(p,d,l)		__raw_readsb(p,d,l)
+#define readsw(p,d,l)		__raw_readsw(p,d,l)
+#define readsl(p,d,l)		__raw_readsl(p,d,l)
 
-static inline void ctrl_delay(void)
-{
-	__raw_readw(generic_io_base);
-}
+#define writesb(p,d,l)		__raw_writesb(p,d,l)
+#define writesw(p,d,l)		__raw_writesw(p,d,l)
+#define writesl(p,d,l)		__raw_writesl(p,d,l)
 
 #define __BUILD_UNCACHED_IO(bwlq, type)					\
 static inline type read##bwlq##_uncached(unsigned long addr)		\
@@ -159,10 +91,11 @@ __BUILD_UNCACHED_IO(w, u16)
 __BUILD_UNCACHED_IO(l, u32)
 __BUILD_UNCACHED_IO(q, u64)
 
-#define __BUILD_MEMORY_STRING(bwlq, type)				\
+#define __BUILD_MEMORY_STRING(pfx, bwlq, type)				\
 									\
-static inline void __raw_writes##bwlq(volatile void __iomem *mem,	\
-				const void *addr, unsigned int count)	\
+static inline void							\
+pfx##writes##bwlq(volatile void __iomem *mem, const void *addr,		\
+		  unsigned int count)					\
 {									\
 	const volatile type *__addr = addr;				\
 									\
@@ -172,8 +105,8 @@ static inline void __raw_writes##bwlq(vo
 	}								\
 }									\
 									\
-static inline void __raw_reads##bwlq(volatile void __iomem *mem,	\
-			       void *addr, unsigned int count)		\
+static inline void pfx##reads##bwlq(volatile void __iomem *mem,		\
+				    void *addr, unsigned int count)	\
 {									\
 	volatile type *__addr = addr;					\
 									\
@@ -183,86 +116,121 @@ static inline void __raw_reads##bwlq(vol
 	}								\
 }
 
-__BUILD_MEMORY_STRING(b, u8)
-__BUILD_MEMORY_STRING(w, u16)
+__BUILD_MEMORY_STRING(__raw_, b, u8)
+__BUILD_MEMORY_STRING(__raw_, w, u16)
 
 #ifdef CONFIG_SUPERH32
 void __raw_writesl(void __iomem *addr, const void *data, int longlen);
 void __raw_readsl(const void __iomem *addr, void *data, int longlen);
 #else
-__BUILD_MEMORY_STRING(l, u32)
+__BUILD_MEMORY_STRING(__raw_, l, u32)
 #endif
 
-__BUILD_MEMORY_STRING(q, u64)
-
-#define writesb			__raw_writesb
-#define writesw			__raw_writesw
-#define writesl			__raw_writesl
-
-#define readsb			__raw_readsb
-#define readsw			__raw_readsw
-#define readsl			__raw_readsl
+__BUILD_MEMORY_STRING(__raw_, q, u64)
 
-#define readb_relaxed(a)	readb(a)
-#define readw_relaxed(a)	readw(a)
-#define readl_relaxed(a)	readl(a)
-#define readq_relaxed(a)	readq(a)
+#ifdef CONFIG_HAS_IOPORT
 
-#ifndef CONFIG_GENERIC_IOMAP
-/* Simple MMIO */
-#define ioread8(a)		__raw_readb(a)
-#define ioread16(a)		__raw_readw(a)
-#define ioread16be(a)		be16_to_cpu(__raw_readw((a)))
-#define ioread32(a)		__raw_readl(a)
-#define ioread32be(a)		be32_to_cpu(__raw_readl((a)))
+/*
+ * Slowdown I/O port space accesses for antique hardware.
+ */
+#undef CONF_SLOWDOWN_IO
 
-#define iowrite8(v,a)		__raw_writeb((v),(a))
-#define iowrite16(v,a)		__raw_writew((v),(a))
-#define iowrite16be(v,a)	__raw_writew(cpu_to_be16((v)),(a))
-#define iowrite32(v,a)		__raw_writel((v),(a))
-#define iowrite32be(v,a)	__raw_writel(cpu_to_be32((v)),(a))
+/*
+ * On SuperH I/O ports are memory mapped, so we access them using normal
+ * load/store instructions. sh_io_port_base is the virtual address to
+ * which all ports are being mapped.
+ */
+extern const unsigned long sh_io_port_base;
 
-#define ioread8_rep(a, d, c)	__raw_readsb((a), (d), (c))
-#define ioread16_rep(a, d, c)	__raw_readsw((a), (d), (c))
-#define ioread32_rep(a, d, c)	__raw_readsl((a), (d), (c))
+static inline void __set_io_port_base(unsigned long pbase)
+{
+	*(unsigned long *)&sh_io_port_base = pbase;
+	barrier();
+}
 
-#define iowrite8_rep(a, s, c)	__raw_writesb((a), (s), (c))
-#define iowrite16_rep(a, s, c)	__raw_writesw((a), (s), (c))
-#define iowrite32_rep(a, s, c)	__raw_writesl((a), (s), (c))
+#ifdef CONFIG_GENERIC_IOMAP
+#define __ioport_map ioport_map
+#else
+extern void __iomem *__ioport_map(unsigned long addr, unsigned int size);
 #endif
 
-#define mmio_insb(p,d,c)	__raw_readsb(p,d,c)
-#define mmio_insw(p,d,c)	__raw_readsw(p,d,c)
-#define mmio_insl(p,d,c)	__raw_readsl(p,d,c)
+#ifdef CONF_SLOWDOWN_IO
+#define SLOW_DOWN_IO __raw_readw(sh_io_port_base)
+#else
+#define SLOW_DOWN_IO
+#endif
 
-#define mmio_outsb(p,s,c)	__raw_writesb(p,s,c)
-#define mmio_outsw(p,s,c)	__raw_writesw(p,s,c)
-#define mmio_outsl(p,s,c)	__raw_writesl(p,s,c)
+#define __BUILD_IOPORT_SINGLE(pfx, bwlq, type, p, slow)			\
+									\
+static inline void pfx##out##bwlq##p(type val, unsigned long port)	\
+{									\
+	volatile type *__addr;						\
+									\
+	__addr = __ioport_map(port, sizeof(type));			\
+	*__addr = val;							\
+	slow;								\
+}									\
+									\
+static inline type pfx##in##bwlq##p(unsigned long port)			\
+{									\
+	volatile type *__addr;						\
+	type __val;							\
+									\
+	__addr = __ioport_map(port, sizeof(type));			\
+	__val = *__addr;						\
+	slow;								\
+									\
+	return __val;							\
+}
 
-/* synco on SH-4A, otherwise a nop */
-#define mmiowb()		wmb()
+#define __BUILD_IOPORT_PFX(bus, bwlq, type)				\
+	__BUILD_IOPORT_SINGLE(bus, bwlq, type, ,)			\
+	__BUILD_IOPORT_SINGLE(bus, bwlq, type, _p, SLOW_DOWN_IO)
 
-#define IO_SPACE_LIMIT 0xffffffff
+#define BUILDIO_IOPORT(bwlq, type)					\
+	__BUILD_IOPORT_PFX(, bwlq, type)
 
-#ifdef CONFIG_HAS_IOPORT
+BUILDIO_IOPORT(b, u8)
+BUILDIO_IOPORT(w, u16)
+BUILDIO_IOPORT(l, u32)
+BUILDIO_IOPORT(q, u64)
 
-/*
- * This function provides a method for the generic case where a
- * board-specific ioport_map simply needs to return the port + some
- * arbitrary port base.
- *
- * We use this at board setup time to implicitly set the port base, and
- * as a result, we can use the generic ioport_map.
- */
-static inline void __set_io_port_base(unsigned long pbase)
-{
-	generic_io_base = pbase;
+#define __BUILD_IOPORT_STRING(bwlq, type)				\
+									\
+static inline void outs##bwlq(unsigned long port, const void *addr,	\
+			      unsigned int count)			\
+{									\
+	const volatile type *__addr = addr;				\
+									\
+	while (count--) {						\
+		out##bwlq(*__addr, port);				\
+		__addr++;						\
+	}								\
+}									\
+									\
+static inline void ins##bwlq(unsigned long port, void *addr,		\
+			     unsigned int count)			\
+{									\
+	volatile type *__addr = addr;					\
+									\
+	while (count--) {						\
+		*__addr = in##bwlq(port);				\
+		__addr++;						\
+	}								\
 }
 
-#define __ioport_map(p, n) sh_mv.mv_ioport_map((p), (n))
+__BUILD_IOPORT_STRING(b, u8)
+__BUILD_IOPORT_STRING(w, u16)
+__BUILD_IOPORT_STRING(l, u32)
+__BUILD_IOPORT_STRING(q, u64)
 
 #endif
 
+#define IO_SPACE_LIMIT 0xffffffff
+
+/* synco on SH-4A, otherwise a nop */
+#define mmiowb()		wmb()
+
 /* We really want to try and get these to memcpy etc */
 void memcpy_fromio(void *, const volatile void __iomem *, unsigned long);
 void memcpy_toio(volatile void __iomem *, const void *, unsigned long);
@@ -322,7 +290,15 @@ __ioremap_29bit(phys_addr_t offset, unsi
 	 * mapping must be done by the PMB or by using page tables.
 	 */
 	if (likely(PXSEG(offset) < P3SEG && PXSEG(last_addr) < P3SEG)) {
-		if (unlikely(pgprot_val(prot) & _PAGE_CACHABLE))
+		u64 flags = pgprot_val(prot);
+
+		/*
+		 * Anything using the legacy PTEA space attributes needs
+		 * to be kicked down to page table mappings.
+		 */
+		if (unlikely(flags & _PAGE_PCC_MASK))
+			return NULL;
+		if (unlikely(flags & _PAGE_CACHABLE))
 			return (void __iomem *)P1SEGADDR(offset);
 
 		return (void __iomem *)P2SEGADDR(offset);
@@ -395,10 +371,6 @@ static inline int iounmap_fixed(void __i
 #define ioremap_nocache	ioremap
 #define iounmap		__iounmap
 
-#define maybebadio(port) \
-	printk(KERN_ERR "bad PC-like io %s:%u for port 0x%lx at 0x%08x\n", \
-	       __func__, __LINE__, (port), (u32)__builtin_return_address(0))
-
 /*
  * Convert a physical pointer to a virtual kernel pointer for /dev/mem
  * access
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/include/asm/machvec.h linux-libre-2.6.38-gnu1/arch/sh/include/asm/machvec.h
--- linux-libre-2.6.37-gnu1/arch/sh/include/asm/machvec.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/include/asm/machvec.h	2011-03-14 21:20:32.000000000 -0400
@@ -23,27 +23,6 @@ struct sh_machine_vector {
 	void (*mv_init_irq)(void);
 
 #ifdef CONFIG_HAS_IOPORT
-	u8 (*mv_inb)(unsigned long);
-	u16 (*mv_inw)(unsigned long);
-	u32 (*mv_inl)(unsigned long);
-	void (*mv_outb)(u8, unsigned long);
-	void (*mv_outw)(u16, unsigned long);
-	void (*mv_outl)(u32, unsigned long);
-
-	u8 (*mv_inb_p)(unsigned long);
-	u16 (*mv_inw_p)(unsigned long);
-	u32 (*mv_inl_p)(unsigned long);
-	void (*mv_outb_p)(u8, unsigned long);
-	void (*mv_outw_p)(u16, unsigned long);
-	void (*mv_outl_p)(u32, unsigned long);
-
-	void (*mv_insb)(unsigned long, void *dst, unsigned long count);
-	void (*mv_insw)(unsigned long, void *dst, unsigned long count);
-	void (*mv_insl)(unsigned long, void *dst, unsigned long count);
-	void (*mv_outsb)(unsigned long, const void *src, unsigned long count);
-	void (*mv_outsw)(unsigned long, const void *src, unsigned long count);
-	void (*mv_outsl)(unsigned long, const void *src, unsigned long count);
-
 	void __iomem *(*mv_ioport_map)(unsigned long port, unsigned int size);
 	void (*mv_ioport_unmap)(void __iomem *);
 #endif
@@ -52,6 +31,7 @@ struct sh_machine_vector {
 	int (*mv_mode_pins)(void);
 
 	void (*mv_mem_init)(void);
+	void (*mv_mem_reserve)(void);
 };
 
 extern struct sh_machine_vector sh_mv;
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/include/asm/pgtable_32.h linux-libre-2.6.38-gnu1/arch/sh/include/asm/pgtable_32.h
--- linux-libre-2.6.37-gnu1/arch/sh/include/asm/pgtable_32.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/include/asm/pgtable_32.h	2011-03-14 21:20:32.000000000 -0400
@@ -76,6 +76,10 @@
 /* Wrapper for extended mode pgprot twiddling */
 #define _PAGE_EXT(x)		((unsigned long long)(x) << 32)
 
+#ifdef CONFIG_X2TLB
+#define _PAGE_PCC_MASK	0x00000000	/* No legacy PTEA support */
+#else
+
 /* software: moves to PTEA.TC (Timing Control) */
 #define _PAGE_PCC_AREA5	0x00000000	/* use BSC registers for area5 */
 #define _PAGE_PCC_AREA6	0x80000000	/* use BSC registers for area6 */
@@ -89,7 +93,8 @@
 #define _PAGE_PCC_ATR8	0x60000000	/* Attribute Memory space, 8 bit bus */
 #define _PAGE_PCC_ATR16	0x60000001	/* Attribute Memory space, 6 bit bus */
 
-#ifndef CONFIG_X2TLB
+#define _PAGE_PCC_MASK	0xe0000001
+
 /* copy the ptea attributes */
 static inline unsigned long copy_ptea_attributes(unsigned long x)
 {
@@ -231,13 +236,7 @@ static inline unsigned long copy_ptea_at
 					   _PAGE_EXT_KERN_EXEC))
 
 #define PAGE_KERNEL_PCC(slot, type) \
-			__pgprot(_PAGE_PRESENT | _PAGE_DIRTY | \
-				 _PAGE_ACCESSED | _PAGE_FLAGS_HARD | \
-				 _PAGE_EXT(_PAGE_EXT_KERN_READ | \
-					   _PAGE_EXT_KERN_WRITE | \
-					   _PAGE_EXT_KERN_EXEC) \
-				 (slot ? _PAGE_PCC_AREA5 : _PAGE_PCC_AREA6) | \
-				 (type))
+			__pgprot(0)
 
 #elif defined(CONFIG_MMU) /* SH-X TLB */
 #define PAGE_NONE	__pgprot(_PAGE_PROTNONE | _PAGE_CACHABLE | \
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/include/asm/pgtable.h linux-libre-2.6.38-gnu1/arch/sh/include/asm/pgtable.h
--- linux-libre-2.6.37-gnu1/arch/sh/include/asm/pgtable.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/include/asm/pgtable.h	2011-03-14 21:20:32.000000000 -0400
@@ -134,6 +134,7 @@ typedef pte_t *pte_addr_t;
 extern void pgtable_cache_init(void);
 
 struct vm_area_struct;
+struct mm_struct;
 
 extern void __update_cache(struct vm_area_struct *vma,
 			   unsigned long address, pte_t pte);
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/include/asm/processor_32.h linux-libre-2.6.38-gnu1/arch/sh/include/asm/processor_32.h
--- linux-libre-2.6.37-gnu1/arch/sh/include/asm/processor_32.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/include/asm/processor_32.h	2011-03-14 21:20:32.000000000 -0400
@@ -194,15 +194,17 @@ extern unsigned long get_wchan(struct ta
 #define KSTK_ESP(tsk)  (task_pt_regs(tsk)->regs[15])
 
 #if defined(CONFIG_CPU_SH2A) || defined(CONFIG_CPU_SH4)
+
 #define PREFETCH_STRIDE		L1_CACHE_BYTES
 #define ARCH_HAS_PREFETCH
 #define ARCH_HAS_PREFETCHW
-static inline void prefetch(void *x)
+
+static inline void prefetch(const void *x)
 {
 	__builtin_prefetch(x, 0, 3);
 }
 
-static inline void prefetchw(void *x)
+static inline void prefetchw(const void *x)
 {
 	__builtin_prefetch(x, 1, 3);
 }
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/include/asm/processor.h linux-libre-2.6.38-gnu1/arch/sh/include/asm/processor.h
--- linux-libre-2.6.37-gnu1/arch/sh/include/asm/processor.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/include/asm/processor.h	2011-03-14 21:20:32.000000000 -0400
@@ -35,7 +35,7 @@ enum cpu_type {
 	CPU_SH7723, CPU_SH7724, CPU_SH7757, CPU_SHX3,
 
 	/* SH4AL-DSP types */
-	CPU_SH7343, CPU_SH7722, CPU_SH7366,
+	CPU_SH7343, CPU_SH7722, CPU_SH7366, CPU_SH7372,
 
 	/* SH-5 types */
         CPU_SH5_101, CPU_SH5_103,
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/include/asm/ptrace_32.h linux-libre-2.6.38-gnu1/arch/sh/include/asm/ptrace_32.h
--- linux-libre-2.6.37-gnu1/arch/sh/include/asm/ptrace_32.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/include/asm/ptrace_32.h	2011-03-14 21:20:32.000000000 -0400
@@ -76,7 +76,7 @@ struct pt_dspregs {
 #ifdef __KERNEL__
 
 #define MAX_REG_OFFSET		offsetof(struct pt_regs, tra)
-#define regs_return_value(regs)	((regs)->regs[0])
+#define regs_return_value(_regs)	((_regs)->regs[0])
 
 #endif /* __KERNEL__ */
 
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/include/asm/ptrace_64.h linux-libre-2.6.38-gnu1/arch/sh/include/asm/ptrace_64.h
--- linux-libre-2.6.37-gnu1/arch/sh/include/asm/ptrace_64.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/include/asm/ptrace_64.h	2011-03-14 21:20:32.000000000 -0400
@@ -13,7 +13,7 @@ struct pt_regs {
 #ifdef __KERNEL__
 
 #define MAX_REG_OFFSET		offsetof(struct pt_regs, tregs[7])
-#define regs_return_value(regs)	((regs)->regs[3])
+#define regs_return_value(_regs)	((_regs)->regs[3])
 
 #endif /* __KERNEL__ */
 
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/include/asm/ptrace.h linux-libre-2.6.38-gnu1/arch/sh/include/asm/ptrace.h
--- linux-libre-2.6.37-gnu1/arch/sh/include/asm/ptrace.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/include/asm/ptrace.h	2011-03-14 21:20:32.000000000 -0400
@@ -40,8 +40,8 @@
 #include <asm/system.h>
 
 #define user_mode(regs)			(((regs)->sr & 0x40000000)==0)
-#define user_stack_pointer(regs)	((unsigned long)(regs)->regs[15])
-#define kernel_stack_pointer(regs)	((unsigned long)(regs)->regs[15])
+#define user_stack_pointer(_regs)	((unsigned long)(_regs)->regs[15])
+#define kernel_stack_pointer(_regs)	((unsigned long)(_regs)->regs[15])
 #define instruction_pointer(regs)	((unsigned long)(regs)->pc)
 
 extern void show_regs(struct pt_regs *);
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/include/asm/sections.h linux-libre-2.6.38-gnu1/arch/sh/include/asm/sections.h
--- linux-libre-2.6.37-gnu1/arch/sh/include/asm/sections.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/include/asm/sections.h	2011-03-14 21:20:32.000000000 -0400
@@ -3,7 +3,7 @@
 
 #include <asm-generic/sections.h>
 
-extern void __nosave_begin, __nosave_end;
+extern long __nosave_begin, __nosave_end;
 extern long __machvec_start, __machvec_end;
 extern char __uncached_start, __uncached_end;
 extern char _ebss[];
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/include/asm/unaligned-sh4a.h linux-libre-2.6.38-gnu1/arch/sh/include/asm/unaligned-sh4a.h
--- linux-libre-2.6.37-gnu1/arch/sh/include/asm/unaligned-sh4a.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/include/asm/unaligned-sh4a.h	2011-03-14 21:20:32.000000000 -0400
@@ -18,10 +18,20 @@
  * of spill registers and blowing up when building at low optimization
  * levels. See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=34777.
  */
+#include <linux/unaligned/packed_struct.h>
 #include <linux/types.h>
 #include <asm/byteorder.h>
 
-static __always_inline u32 __get_unaligned_cpu32(const u8 *p)
+static inline u16 sh4a_get_unaligned_cpu16(const u8 *p)
+{
+#ifdef __LITTLE_ENDIAN
+	return p[0] | p[1] << 8;
+#else
+	return p[0] << 8 | p[1];
+#endif
+}
+
+static __always_inline u32 sh4a_get_unaligned_cpu32(const u8 *p)
 {
 	unsigned long unaligned;
 
@@ -34,218 +44,148 @@ static __always_inline u32 __get_unalign
 	return unaligned;
 }
 
-struct __una_u16 { u16 x __attribute__((packed)); };
-struct __una_u32 { u32 x __attribute__((packed)); };
-struct __una_u64 { u64 x __attribute__((packed)); };
-
-static inline u16 __get_unaligned_cpu16(const u8 *p)
-{
-#ifdef __LITTLE_ENDIAN
-	return p[0] | p[1] << 8;
-#else
-	return p[0] << 8 | p[1];
-#endif
-}
-
 /*
  * Even though movua.l supports auto-increment on the read side, it can
  * only store to r0 due to instruction encoding constraints, so just let
  * the compiler sort it out on its own.
  */
-static inline u64 __get_unaligned_cpu64(const u8 *p)
+static inline u64 sh4a_get_unaligned_cpu64(const u8 *p)
 {
 #ifdef __LITTLE_ENDIAN
-	return (u64)__get_unaligned_cpu32(p + 4) << 32 |
-		    __get_unaligned_cpu32(p);
+	return (u64)sh4a_get_unaligned_cpu32(p + 4) << 32 |
+		    sh4a_get_unaligned_cpu32(p);
 #else
-	return (u64)__get_unaligned_cpu32(p) << 32 |
-		    __get_unaligned_cpu32(p + 4);
+	return (u64)sh4a_get_unaligned_cpu32(p) << 32 |
+		    sh4a_get_unaligned_cpu32(p + 4);
 #endif
 }
 
 static inline u16 get_unaligned_le16(const void *p)
 {
-	return le16_to_cpu(__get_unaligned_cpu16(p));
+	return le16_to_cpu(sh4a_get_unaligned_cpu16(p));
 }
 
 static inline u32 get_unaligned_le32(const void *p)
 {
-	return le32_to_cpu(__get_unaligned_cpu32(p));
+	return le32_to_cpu(sh4a_get_unaligned_cpu32(p));
 }
 
 static inline u64 get_unaligned_le64(const void *p)
 {
-	return le64_to_cpu(__get_unaligned_cpu64(p));
+	return le64_to_cpu(sh4a_get_unaligned_cpu64(p));
 }
 
 static inline u16 get_unaligned_be16(const void *p)
 {
-	return be16_to_cpu(__get_unaligned_cpu16(p));
+	return be16_to_cpu(sh4a_get_unaligned_cpu16(p));
 }
 
 static inline u32 get_unaligned_be32(const void *p)
 {
-	return be32_to_cpu(__get_unaligned_cpu32(p));
+	return be32_to_cpu(sh4a_get_unaligned_cpu32(p));
 }
 
 static inline u64 get_unaligned_be64(const void *p)
 {
-	return be64_to_cpu(__get_unaligned_cpu64(p));
+	return be64_to_cpu(sh4a_get_unaligned_cpu64(p));
 }
 
-static inline void __put_le16_noalign(u8 *p, u16 val)
+static inline void nonnative_put_le16(u16 val, u8 *p)
 {
 	*p++ = val;
 	*p++ = val >> 8;
 }
 
-static inline void __put_le32_noalign(u8 *p, u32 val)
+static inline void nonnative_put_le32(u32 val, u8 *p)
 {
-	__put_le16_noalign(p, val);
-	__put_le16_noalign(p + 2, val >> 16);
+	nonnative_put_le16(val, p);
+	nonnative_put_le16(val >> 16, p + 2);
 }
 
-static inline void __put_le64_noalign(u8 *p, u64 val)
+static inline void nonnative_put_le64(u64 val, u8 *p)
 {
-	__put_le32_noalign(p, val);
-	__put_le32_noalign(p + 4, val >> 32);
+	nonnative_put_le32(val, p);
+	nonnative_put_le32(val >> 32, p + 4);
 }
 
-static inline void __put_be16_noalign(u8 *p, u16 val)
+static inline void nonnative_put_be16(u16 val, u8 *p)
 {
 	*p++ = val >> 8;
 	*p++ = val;
 }
 
-static inline void __put_be32_noalign(u8 *p, u32 val)
+static inline void nonnative_put_be32(u32 val, u8 *p)
 {
-	__put_be16_noalign(p, val >> 16);
-	__put_be16_noalign(p + 2, val);
+	nonnative_put_be16(val >> 16, p);
+	nonnative_put_be16(val, p + 2);
 }
 
-static inline void __put_be64_noalign(u8 *p, u64 val)
+static inline void nonnative_put_be64(u64 val, u8 *p)
 {
-	__put_be32_noalign(p, val >> 32);
-	__put_be32_noalign(p + 4, val);
+	nonnative_put_be32(val >> 32, p);
+	nonnative_put_be32(val, p + 4);
 }
 
 static inline void put_unaligned_le16(u16 val, void *p)
 {
 #ifdef __LITTLE_ENDIAN
-	((struct __una_u16 *)p)->x = val;
+	__put_unaligned_cpu16(val, p);
 #else
-	__put_le16_noalign(p, val);
+	nonnative_put_le16(val, p);
 #endif
 }
 
 static inline void put_unaligned_le32(u32 val, void *p)
 {
 #ifdef __LITTLE_ENDIAN
-	((struct __una_u32 *)p)->x = val;
+	__put_unaligned_cpu32(val, p);
 #else
-	__put_le32_noalign(p, val);
+	nonnative_put_le32(val, p);
 #endif
 }
 
 static inline void put_unaligned_le64(u64 val, void *p)
 {
 #ifdef __LITTLE_ENDIAN
-	((struct __una_u64 *)p)->x = val;
+	__put_unaligned_cpu64(val, p);
 #else
-	__put_le64_noalign(p, val);
+	nonnative_put_le64(val, p);
 #endif
 }
 
 static inline void put_unaligned_be16(u16 val, void *p)
 {
 #ifdef __BIG_ENDIAN
-	((struct __una_u16 *)p)->x = val;
+	__put_unaligned_cpu16(val, p);
 #else
-	__put_be16_noalign(p, val);
+	nonnative_put_be16(val, p);
 #endif
 }
 
 static inline void put_unaligned_be32(u32 val, void *p)
 {
 #ifdef __BIG_ENDIAN
-	((struct __una_u32 *)p)->x = val;
+	__put_unaligned_cpu32(val, p);
 #else
-	__put_be32_noalign(p, val);
+	nonnative_put_be32(val, p);
 #endif
 }
 
 static inline void put_unaligned_be64(u64 val, void *p)
 {
 #ifdef __BIG_ENDIAN
-	((struct __una_u64 *)p)->x = val;
+	__put_unaligned_cpu64(val, p);
 #else
-	__put_be64_noalign(p, val);
+	nonnative_put_be64(val, p);
 #endif
 }
 
 /*
- * Cause a link-time error if we try an unaligned access other than
- * 1,2,4 or 8 bytes long
+ * While it's a bit non-obvious, even though the generic le/be wrappers
+ * use the __get/put_xxx prefixing, they actually wrap in to the
+ * non-prefixed get/put_xxx variants as provided above.
  */
-extern void __bad_unaligned_access_size(void);
-
-#define __get_unaligned_le(ptr) ((__force typeof(*(ptr)))({			\
-	__builtin_choose_expr(sizeof(*(ptr)) == 1, *(ptr),			\
-	__builtin_choose_expr(sizeof(*(ptr)) == 2, get_unaligned_le16((ptr)),	\
-	__builtin_choose_expr(sizeof(*(ptr)) == 4, get_unaligned_le32((ptr)),	\
-	__builtin_choose_expr(sizeof(*(ptr)) == 8, get_unaligned_le64((ptr)),	\
-	__bad_unaligned_access_size()))));					\
-	}))
-
-#define __get_unaligned_be(ptr) ((__force typeof(*(ptr)))({			\
-	__builtin_choose_expr(sizeof(*(ptr)) == 1, *(ptr),			\
-	__builtin_choose_expr(sizeof(*(ptr)) == 2, get_unaligned_be16((ptr)),	\
-	__builtin_choose_expr(sizeof(*(ptr)) == 4, get_unaligned_be32((ptr)),	\
-	__builtin_choose_expr(sizeof(*(ptr)) == 8, get_unaligned_be64((ptr)),	\
-	__bad_unaligned_access_size()))));					\
-	}))
-
-#define __put_unaligned_le(val, ptr) ({					\
-	void *__gu_p = (ptr);						\
-	switch (sizeof(*(ptr))) {					\
-	case 1:								\
-		*(u8 *)__gu_p = (__force u8)(val);			\
-		break;							\
-	case 2:								\
-		put_unaligned_le16((__force u16)(val), __gu_p);		\
-		break;							\
-	case 4:								\
-		put_unaligned_le32((__force u32)(val), __gu_p);		\
-		break;							\
-	case 8:								\
-		put_unaligned_le64((__force u64)(val), __gu_p);		\
-		break;							\
-	default:							\
-		__bad_unaligned_access_size();				\
-		break;							\
-	}								\
-	(void)0; })
-
-#define __put_unaligned_be(val, ptr) ({					\
-	void *__gu_p = (ptr);						\
-	switch (sizeof(*(ptr))) {					\
-	case 1:								\
-		*(u8 *)__gu_p = (__force u8)(val);			\
-		break;							\
-	case 2:								\
-		put_unaligned_be16((__force u16)(val), __gu_p);		\
-		break;							\
-	case 4:								\
-		put_unaligned_be32((__force u32)(val), __gu_p);		\
-		break;							\
-	case 8:								\
-		put_unaligned_be64((__force u64)(val), __gu_p);		\
-		break;							\
-	default:							\
-		__bad_unaligned_access_size();				\
-		break;							\
-	}								\
-	(void)0; })
+#include <linux/unaligned/generic.h>
 
 #ifdef __LITTLE_ENDIAN
 # define get_unaligned __get_unaligned_le
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/include/mach-common/mach/romimage.h linux-libre-2.6.38-gnu1/arch/sh/include/mach-common/mach/romimage.h
--- linux-libre-2.6.37-gnu1/arch/sh/include/mach-common/mach/romimage.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/include/mach-common/mach/romimage.h	2011-03-14 21:20:32.000000000 -0400
@@ -4,7 +4,7 @@
 
 #else /* __ASSEMBLY__ */
 
-extern inline void mmcif_update_progress(int nr)
+static inline void mmcif_update_progress(int nr)
 {
 }
 
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/include/mach-ecovec24/mach/romimage.h linux-libre-2.6.38-gnu1/arch/sh/include/mach-ecovec24/mach/romimage.h
--- linux-libre-2.6.37-gnu1/arch/sh/include/mach-ecovec24/mach/romimage.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/include/mach-ecovec24/mach/romimage.h	2011-03-14 21:20:32.000000000 -0400
@@ -35,7 +35,7 @@
 #define HIZCRA		0xa4050158
 #define PGDR		0xa405012c
 
-extern inline void mmcif_update_progress(int nr)
+static inline void mmcif_update_progress(int nr)
 {
 	/* disable Hi-Z for LED pins */
 	__raw_writew(__raw_readw(HIZCRA) & ~(1 << 1), HIZCRA);
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/include/mach-kfr2r09/mach/romimage.h linux-libre-2.6.38-gnu1/arch/sh/include/mach-kfr2r09/mach/romimage.h
--- linux-libre-2.6.37-gnu1/arch/sh/include/mach-kfr2r09/mach/romimage.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/include/mach-kfr2r09/mach/romimage.h	2011-03-14 21:20:32.000000000 -0400
@@ -23,7 +23,7 @@
 
 #else /* __ASSEMBLY__ */
 
-extern inline void mmcif_update_progress(int nr)
+static inline void mmcif_update_progress(int nr)
 {
 }
 
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/include/mach-landisk/mach/iodata_landisk.h linux-libre-2.6.38-gnu1/arch/sh/include/mach-landisk/mach/iodata_landisk.h
--- linux-libre-2.6.37-gnu1/arch/sh/include/mach-landisk/mach/iodata_landisk.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/include/mach-landisk/mach/iodata_landisk.h	2011-03-14 21:20:32.000000000 -0400
@@ -2,7 +2,7 @@
 #define __ASM_SH_IODATA_LANDISK_H
 
 /*
- * linux/include/asm-sh/landisk/iodata_landisk.h
+ * arch/sh/include/mach-landisk/mach/iodata_landisk.h
  *
  * Copyright (C) 2000  Atom Create Engineering Co., Ltd.
  *
@@ -27,7 +27,7 @@
 
 #define IRQ_PCIINTA	5		/* PCI INTA IRQ */
 #define IRQ_PCIINTB	6		/* PCI INTB IRQ */
-#define IRQ_PCIINDC	7		/* PCI INTC IRQ */
+#define IRQ_PCIINTC	7		/* PCI INTC IRQ */
 #define IRQ_PCIINTD	8		/* PCI INTD IRQ */
 #define IRQ_ATA		9		/* ATA IRQ */
 #define IRQ_FATA	10		/* FATA IRQ */
@@ -35,6 +35,8 @@
 #define IRQ_BUTTON	12		/* USL-5P Button IRQ */
 #define IRQ_FAULT	13		/* USL-5P Fault  IRQ */
 
+void init_landisk_IRQ(void);
+
 #define __IO_PREFIX landisk
 #include <asm/io_generic.h>
 
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/include/mach-sdk7786/mach/fpga.h linux-libre-2.6.38-gnu1/arch/sh/include/mach-sdk7786/mach/fpga.h
--- linux-libre-2.6.37-gnu1/arch/sh/include/mach-sdk7786/mach/fpga.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/include/mach-sdk7786/mach/fpga.h	2011-03-14 21:20:32.000000000 -0400
@@ -14,11 +14,16 @@
 #define INTTESTR	0x040
 #define SYSSR		0x050
 #define NRGPR		0x060
+
 #define NMISR		0x070
+#define  NMISR_MAN_NMI	BIT(0)
+#define  NMISR_AUX_NMI	BIT(1)
+#define  NMISR_MASK	(NMISR_MAN_NMI | NMISR_AUX_NMI)
 
 #define NMIMR		0x080
 #define  NMIMR_MAN_NMIM	BIT(0)	/* Manual NMI mask */
 #define  NMIMR_AUX_NMIM	BIT(1)	/* Auxiliary NMI mask */
+#define  NMIMR_MASK	(NMIMR_MAN_NMIM | NMIMR_AUX_NMIM)
 
 #define INTBSR		0x090
 #define INTBMR		0x0a0
@@ -126,6 +131,9 @@
 extern void __iomem *sdk7786_fpga_base;
 extern void sdk7786_fpga_init(void);
 
+/* arch/sh/boards/mach-sdk7786/nmi.c */
+extern void sdk7786_nmi_init(void);
+
 #define SDK7786_FPGA_REGADDR(reg)	(sdk7786_fpga_base + (reg))
 
 /*
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/Kconfig linux-libre-2.6.38-gnu1/arch/sh/Kconfig
--- linux-libre-2.6.37-gnu1/arch/sh/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -1,7 +1,7 @@
 config SUPERH
 	def_bool y
-	select EMBEDDED
-	select HAVE_CLK
+	select EXPERT
+	select CLKDEV_LOOKUP
 	select HAVE_IDE if HAS_IOPORT
 	select HAVE_MEMBLOCK
 	select HAVE_OPROFILE
@@ -15,6 +15,7 @@ config SUPERH
 	select HAVE_KERNEL_GZIP
 	select HAVE_KERNEL_BZIP2
 	select HAVE_KERNEL_LZMA
+	select HAVE_KERNEL_XZ
 	select HAVE_KERNEL_LZO
 	select HAVE_SYSCALL_TRACEPOINTS
 	select HAVE_REGS_AND_STACK_ACCESS_API
@@ -162,7 +163,8 @@ config ARCH_HAS_CPU_IDLE_WAIT
 	def_bool y
 
 config NO_IOPORT
-	bool
+	def_bool !PCI
+	depends on !SH_CAYMAN && !SH_SH4202_MICRODEV
 
 config IO_TRAPPED
 	bool
@@ -275,6 +277,7 @@ config CPU_SUBTYPE_SH7203
 	select CPU_HAS_FPU
 	select SYS_SUPPORTS_CMT
 	select SYS_SUPPORTS_MTU2
+	select ARCH_WANT_OPTIONAL_GPIOLIB
 
 config CPU_SUBTYPE_SH7206
 	bool "Support SH7206 processor"
@@ -346,6 +349,8 @@ config CPU_SUBTYPE_SH7720
 	select CPU_SH3
 	select CPU_HAS_DSP
 	select SYS_SUPPORTS_CMT
+	select ARCH_WANT_OPTIONAL_GPIOLIB
+	select USB_ARCH_HAS_OHCI
 	help
 	  Select SH7720 if you have a SH3-DSP SH7720 CPU.
 
@@ -354,6 +359,7 @@ config CPU_SUBTYPE_SH7721
 	select CPU_SH3
 	select CPU_HAS_DSP
 	select SYS_SUPPORTS_CMT
+	select USB_ARCH_HAS_OHCI
 	help
 	  Select SH7721 if you have a SH3-DSP SH7721 CPU.
 
@@ -408,6 +414,7 @@ config CPU_SUBTYPE_SH7723
 	select ARCH_SHMOBILE
 	select ARCH_SPARSEMEM_ENABLE
 	select SYS_SUPPORTS_CMT
+	select ARCH_WANT_OPTIONAL_GPIOLIB
 	help
 	  Select SH7723 if you have an SH-MobileR2 CPU.
 
@@ -418,6 +425,7 @@ config CPU_SUBTYPE_SH7724
 	select ARCH_SHMOBILE
 	select ARCH_SPARSEMEM_ENABLE
 	select SYS_SUPPORTS_CMT
+	select ARCH_WANT_OPTIONAL_GPIOLIB
 	help
 	  Select SH7724 if you have an SH-MobileR2R CPU.
 
@@ -425,12 +433,14 @@ config CPU_SUBTYPE_SH7757
 	bool "Support SH7757 processor"
 	select CPU_SH4A
 	select CPU_SHX2
+	select ARCH_WANT_OPTIONAL_GPIOLIB
 	help
 	  Select SH7757 if you have a SH4A SH7757 CPU.
 
 config CPU_SUBTYPE_SH7763
 	bool "Support SH7763 processor"
 	select CPU_SH4A
+	select USB_ARCH_HAS_OHCI
 	help
 	  Select SH7763 if you have a SH4A SH7763(R5S77631) CPU.
 
@@ -448,6 +458,7 @@ config CPU_SUBTYPE_SH7785
 	select CPU_SHX2
 	select ARCH_SPARSEMEM_ENABLE
 	select SYS_SUPPORTS_NUMA
+	select ARCH_WANT_OPTIONAL_GPIOLIB
 
 config CPU_SUBTYPE_SH7786
 	bool "Support SH7786 processor"
@@ -455,6 +466,9 @@ config CPU_SUBTYPE_SH7786
 	select CPU_SHX3
 	select CPU_HAS_PTEAEX
 	select GENERIC_CLOCKEVENTS_BROADCAST if SMP
+	select ARCH_WANT_OPTIONAL_GPIOLIB
+	select USB_ARCH_HAS_OHCI
+	select USB_ARCH_HAS_EHCI
 
 config CPU_SUBTYPE_SHX3
 	bool "Support SH-X3 processor"
@@ -479,6 +493,7 @@ config CPU_SUBTYPE_SH7722
 	select ARCH_SPARSEMEM_ENABLE
 	select SYS_SUPPORTS_NUMA
 	select SYS_SUPPORTS_CMT
+	select ARCH_WANT_OPTIONAL_GPIOLIB
 
 config CPU_SUBTYPE_SH7366
 	bool "Support SH7366 processor"
@@ -568,15 +583,6 @@ config SH_CLK_CPG_LEGACY
 	def_bool y if !CPU_SUBTYPE_SH7785 && !ARCH_SHMOBILE && \
 		      !CPU_SHX3 && !CPU_SUBTYPE_SH7757
 
-config SH_CLK_MD
-	int "CPU Mode Pin Setting"
-	depends on CPU_SH2
-	default 6 if CPU_SUBTYPE_SH7206
-	default 5 if CPU_SUBTYPE_SH7619
-	default 0
-	help
-	  MD2 - MD0 pin setting.
-
 source "kernel/time/Kconfig"
 
 endmenu
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/kernel/clkdev.c linux-libre-2.6.38-gnu1/arch/sh/kernel/clkdev.c
--- linux-libre-2.6.37-gnu1/arch/sh/kernel/clkdev.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/kernel/clkdev.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,171 +0,0 @@
-/*
- * arch/sh/kernel/clkdev.c
- *
- * Cloned from arch/arm/common/clkdev.c:
- *
- *  Copyright (C) 2008 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.
- *
- * Helper for the clk API to assist looking up a struct clk.
- */
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/device.h>
-#include <linux/list.h>
-#include <linux/errno.h>
-#include <linux/err.h>
-#include <linux/string.h>
-#include <linux/mutex.h>
-#include <linux/clk.h>
-#include <linux/slab.h>
-#include <linux/bootmem.h>
-#include <linux/mm.h>
-#include <asm/clock.h>
-#include <asm/clkdev.h>
-
-static LIST_HEAD(clocks);
-static DEFINE_MUTEX(clocks_mutex);
-
-/*
- * Find the correct struct clk for the device and connection ID.
- * We do slightly fuzzy matching here:
- *  An entry with a NULL ID is assumed to be a wildcard.
- *  If an entry has a device ID, it must match
- *  If an entry has a connection ID, it must match
- * Then we take the most specific entry - with the following
- * order of precedence: dev+con > dev only > con only.
- */
-static struct clk *clk_find(const char *dev_id, const char *con_id)
-{
-	struct clk_lookup *p;
-	struct clk *clk = NULL;
-	int match, best = 0;
-
-	list_for_each_entry(p, &clocks, node) {
-		match = 0;
-		if (p->dev_id) {
-			if (!dev_id || strcmp(p->dev_id, dev_id))
-				continue;
-			match += 2;
-		}
-		if (p->con_id) {
-			if (!con_id || strcmp(p->con_id, con_id))
-				continue;
-			match += 1;
-		}
-		if (match == 0)
-			continue;
-
-		if (match > best) {
-			clk = p->clk;
-			best = match;
-		}
-	}
-	return clk;
-}
-
-struct clk *clk_get_sys(const char *dev_id, const char *con_id)
-{
-	struct clk *clk;
-
-	mutex_lock(&clocks_mutex);
-	clk = clk_find(dev_id, con_id);
-	mutex_unlock(&clocks_mutex);
-
-	return clk ? clk : ERR_PTR(-ENOENT);
-}
-EXPORT_SYMBOL(clk_get_sys);
-
-void clkdev_add(struct clk_lookup *cl)
-{
-	mutex_lock(&clocks_mutex);
-	list_add_tail(&cl->node, &clocks);
-	mutex_unlock(&clocks_mutex);
-}
-EXPORT_SYMBOL(clkdev_add);
-
-void __init clkdev_add_table(struct clk_lookup *cl, size_t num)
-{
-	mutex_lock(&clocks_mutex);
-	while (num--) {
-		list_add_tail(&cl->node, &clocks);
-		cl++;
-	}
-	mutex_unlock(&clocks_mutex);
-}
-
-#define MAX_DEV_ID	20
-#define MAX_CON_ID	16
-
-struct clk_lookup_alloc {
-	struct clk_lookup cl;
-	char	dev_id[MAX_DEV_ID];
-	char	con_id[MAX_CON_ID];
-};
-
-struct clk_lookup * __init_refok
-clkdev_alloc(struct clk *clk, const char *con_id, const char *dev_fmt, ...)
-{
-	struct clk_lookup_alloc *cla;
-
-	if (!slab_is_available())
-		cla = alloc_bootmem_low_pages(sizeof(*cla));
-	else
-		cla = kzalloc(sizeof(*cla), GFP_KERNEL);
-
-	if (!cla)
-		return NULL;
-
-	cla->cl.clk = clk;
-	if (con_id) {
-		strlcpy(cla->con_id, con_id, sizeof(cla->con_id));
-		cla->cl.con_id = cla->con_id;
-	}
-
-	if (dev_fmt) {
-		va_list ap;
-
-		va_start(ap, dev_fmt);
-		vscnprintf(cla->dev_id, sizeof(cla->dev_id), dev_fmt, ap);
-		cla->cl.dev_id = cla->dev_id;
-		va_end(ap);
-	}
-
-	return &cla->cl;
-}
-EXPORT_SYMBOL(clkdev_alloc);
-
-int clk_add_alias(const char *alias, const char *alias_dev_name, char *id,
-	struct device *dev)
-{
-	struct clk *r = clk_get(dev, id);
-	struct clk_lookup *l;
-
-	if (IS_ERR(r))
-		return PTR_ERR(r);
-
-	l = clkdev_alloc(r, alias, alias_dev_name);
-	clk_put(r);
-	if (!l)
-		return -ENODEV;
-	clkdev_add(l);
-	return 0;
-}
-EXPORT_SYMBOL(clk_add_alias);
-
-/*
- * clkdev_drop - remove a clock dynamically allocated
- */
-void clkdev_drop(struct clk_lookup *cl)
-{
-	struct clk_lookup_alloc *cla = container_of(cl, struct clk_lookup_alloc, cl);
-
-	mutex_lock(&clocks_mutex);
-	list_del(&cl->node);
-	mutex_unlock(&clocks_mutex);
-	kfree(cla);
-}
-EXPORT_SYMBOL(clkdev_drop);
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/kernel/cpu/clock.c linux-libre-2.6.38-gnu1/arch/sh/kernel/cpu/clock.c
--- linux-libre-2.6.37-gnu1/arch/sh/kernel/cpu/clock.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/kernel/cpu/clock.c	2011-03-14 21:20:32.000000000 -0400
@@ -48,20 +48,4 @@ int __init clk_init(void)
 	return ret;
 }
 
-/*
- * Returns a clock. Note that we first try to use device id on the bus
- * and clock name. If this fails, we try to use clock name only.
- */
-struct clk *clk_get(struct device *dev, const char *con_id)
-{
-	const char *dev_id = dev ? dev_name(dev) : NULL;
-
-	return clk_get_sys(dev_id, con_id);
-}
-EXPORT_SYMBOL_GPL(clk_get);
-
-void clk_put(struct clk *clk)
-{
-}
-EXPORT_SYMBOL_GPL(clk_put);
 
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/kernel/cpu/clock-cpg.c linux-libre-2.6.38-gnu1/arch/sh/kernel/cpu/clock-cpg.c
--- linux-libre-2.6.37-gnu1/arch/sh/kernel/cpu/clock-cpg.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/kernel/cpu/clock-cpg.c	2011-03-14 21:20:32.000000000 -0400
@@ -2,7 +2,7 @@
 #include <linux/compiler.h>
 #include <linux/slab.h>
 #include <linux/io.h>
-#include <asm/clkdev.h>
+#include <linux/clkdev.h>
 #include <asm/clock.h>
 
 static struct clk master_clk = {
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/kernel/cpu/Makefile linux-libre-2.6.38-gnu1/arch/sh/kernel/cpu/Makefile
--- linux-libre-2.6.37-gnu1/arch/sh/kernel/cpu/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/kernel/cpu/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -20,4 +20,4 @@ obj-$(CONFIG_SH_CLK_CPG_LEGACY)	+= clock
 obj-$(CONFIG_SH_FPU)		+= fpu.o
 obj-$(CONFIG_SH_FPU_EMU)	+= fpu.o
 
-obj-y	+= irq/ init.o clock.o hwblk.o
+obj-y	+= irq/ init.o clock.o hwblk.o proc.o
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/kernel/cpu/proc.c linux-libre-2.6.38-gnu1/arch/sh/kernel/cpu/proc.c
--- linux-libre-2.6.37-gnu1/arch/sh/kernel/cpu/proc.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/kernel/cpu/proc.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,148 @@
+#include <linux/seq_file.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <asm/machvec.h>
+#include <asm/processor.h>
+
+static const char *cpu_name[] = {
+	[CPU_SH7201]	= "SH7201",
+	[CPU_SH7203]	= "SH7203",	[CPU_SH7263]	= "SH7263",
+	[CPU_SH7206]	= "SH7206",	[CPU_SH7619]	= "SH7619",
+	[CPU_SH7705]	= "SH7705",	[CPU_SH7706]	= "SH7706",
+	[CPU_SH7707]	= "SH7707",	[CPU_SH7708]	= "SH7708",
+	[CPU_SH7709]	= "SH7709",	[CPU_SH7710]	= "SH7710",
+	[CPU_SH7712]	= "SH7712",	[CPU_SH7720]	= "SH7720",
+	[CPU_SH7721]	= "SH7721",	[CPU_SH7729]	= "SH7729",
+	[CPU_SH7750]	= "SH7750",	[CPU_SH7750S]	= "SH7750S",
+	[CPU_SH7750R]	= "SH7750R",	[CPU_SH7751]	= "SH7751",
+	[CPU_SH7751R]	= "SH7751R",	[CPU_SH7760]	= "SH7760",
+	[CPU_SH4_202]	= "SH4-202",	[CPU_SH4_501]	= "SH4-501",
+	[CPU_SH7763]	= "SH7763",	[CPU_SH7770]	= "SH7770",
+	[CPU_SH7780]	= "SH7780",	[CPU_SH7781]	= "SH7781",
+	[CPU_SH7343]	= "SH7343",	[CPU_SH7785]	= "SH7785",
+	[CPU_SH7786]	= "SH7786",	[CPU_SH7757]	= "SH7757",
+	[CPU_SH7722]	= "SH7722",	[CPU_SHX3]	= "SH-X3",
+	[CPU_SH5_101]	= "SH5-101",	[CPU_SH5_103]	= "SH5-103",
+	[CPU_MXG]	= "MX-G",	[CPU_SH7723]	= "SH7723",
+	[CPU_SH7366]	= "SH7366",	[CPU_SH7724]	= "SH7724",
+	[CPU_SH7372]	= "SH7372",	[CPU_SH_NONE]	= "Unknown"
+};
+
+const char *get_cpu_subtype(struct sh_cpuinfo *c)
+{
+	return cpu_name[c->type];
+}
+EXPORT_SYMBOL(get_cpu_subtype);
+
+#ifdef CONFIG_PROC_FS
+/* Symbolic CPU flags, keep in sync with asm/cpu-features.h */
+static const char *cpu_flags[] = {
+	"none", "fpu", "p2flush", "mmuassoc", "dsp", "perfctr",
+	"ptea", "llsc", "l2", "op32", "pteaex", NULL
+};
+
+static void show_cpuflags(struct seq_file *m, struct sh_cpuinfo *c)
+{
+	unsigned long i;
+
+	seq_printf(m, "cpu flags\t:");
+
+	if (!c->flags) {
+		seq_printf(m, " %s\n", cpu_flags[0]);
+		return;
+	}
+
+	for (i = 0; cpu_flags[i]; i++)
+		if ((c->flags & (1 << i)))
+			seq_printf(m, " %s", cpu_flags[i+1]);
+
+	seq_printf(m, "\n");
+}
+
+static void show_cacheinfo(struct seq_file *m, const char *type,
+			   struct cache_info info)
+{
+	unsigned int cache_size;
+
+	cache_size = info.ways * info.sets * info.linesz;
+
+	seq_printf(m, "%s size\t: %2dKiB (%d-way)\n",
+		   type, cache_size >> 10, info.ways);
+}
+
+/*
+ *	Get CPU information for use by the procfs.
+ */
+static int show_cpuinfo(struct seq_file *m, void *v)
+{
+	struct sh_cpuinfo *c = v;
+	unsigned int cpu = c - cpu_data;
+
+	if (!cpu_online(cpu))
+		return 0;
+
+	if (cpu == 0)
+		seq_printf(m, "machine\t\t: %s\n", get_system_type());
+	else
+		seq_printf(m, "\n");
+
+	seq_printf(m, "processor\t: %d\n", cpu);
+	seq_printf(m, "cpu family\t: %s\n", init_utsname()->machine);
+	seq_printf(m, "cpu type\t: %s\n", get_cpu_subtype(c));
+	if (c->cut_major == -1)
+		seq_printf(m, "cut\t\t: unknown\n");
+	else if (c->cut_minor == -1)
+		seq_printf(m, "cut\t\t: %d.x\n", c->cut_major);
+	else
+		seq_printf(m, "cut\t\t: %d.%d\n", c->cut_major, c->cut_minor);
+
+	show_cpuflags(m, c);
+
+	seq_printf(m, "cache type\t: ");
+
+	/*
+	 * Check for what type of cache we have, we support both the
+	 * unified cache on the SH-2 and SH-3, as well as the harvard
+	 * style cache on the SH-4.
+	 */
+	if (c->icache.flags & SH_CACHE_COMBINED) {
+		seq_printf(m, "unified\n");
+		show_cacheinfo(m, "cache", c->icache);
+	} else {
+		seq_printf(m, "split (harvard)\n");
+		show_cacheinfo(m, "icache", c->icache);
+		show_cacheinfo(m, "dcache", c->dcache);
+	}
+
+	/* Optional secondary cache */
+	if (c->flags & CPU_HAS_L2_CACHE)
+		show_cacheinfo(m, "scache", c->scache);
+
+	seq_printf(m, "address sizes\t: %u bits physical\n", c->phys_bits);
+
+	seq_printf(m, "bogomips\t: %lu.%02lu\n",
+		     c->loops_per_jiffy/(500000/HZ),
+		     (c->loops_per_jiffy/(5000/HZ)) % 100);
+
+	return 0;
+}
+
+static void *c_start(struct seq_file *m, loff_t *pos)
+{
+	return *pos < NR_CPUS ? cpu_data + *pos : 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)
+{
+}
+const struct seq_operations cpuinfo_op = {
+	.start	= c_start,
+	.next	= c_next,
+	.stop	= c_stop,
+	.show	= show_cpuinfo,
+};
+#endif /* CONFIG_PROC_FS */
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/kernel/cpu/sh2/clock-sh7619.c linux-libre-2.6.38-gnu1/arch/sh/kernel/cpu/sh2/clock-sh7619.c
--- linux-libre-2.6.37-gnu1/arch/sh/kernel/cpu/sh2/clock-sh7619.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/kernel/cpu/sh2/clock-sh7619.c	2011-03-14 21:20:32.000000000 -0400
@@ -14,24 +14,18 @@
  */
 #include <linux/init.h>
 #include <linux/kernel.h>
+#include <linux/io.h>
 #include <asm/clock.h>
 #include <asm/freq.h>
-#include <asm/io.h>
+#include <asm/processor.h>
 
 static const int pll1rate[] = {1,2};
 static const int pfc_divisors[] = {1,2,0,4};
-
-#if (CONFIG_SH_CLK_MD == 1) || (CONFIG_SH_CLK_MD == 2)
-#define PLL2 (4)
-#elif (CONFIG_SH_CLK_MD == 5) || (CONFIG_SH_CLK_MD == 6)
-#define PLL2 (2)
-#else
-#error "Illigal Clock Mode!"
-#endif
+static unsigned int pll2_mult;
 
 static void master_clk_init(struct clk *clk)
 {
-	clk->rate *= PLL2 * pll1rate[(__raw_readw(FREQCR) >> 8) & 7];
+	clk->rate *= pll2_mult * pll1rate[(__raw_readw(FREQCR) >> 8) & 7];
 }
 
 static struct clk_ops sh7619_master_clk_ops = {
@@ -70,6 +64,14 @@ static struct clk_ops *sh7619_clk_ops[]
 
 void __init arch_init_clk_ops(struct clk_ops **ops, int idx)
 {
+	if (test_mode_pin(MODE_PIN2 | MODE_PIN0) ||
+	    test_mode_pin(MODE_PIN2 | MODE_PIN1))
+		pll2_mult = 2;
+	else if (test_mode_pin(MODE_PIN0) || test_mode_pin(MODE_PIN1))
+		pll2_mult = 4;
+
+	BUG_ON(!pll2_mult);
+
 	if (idx < ARRAY_SIZE(sh7619_clk_ops))
 		*ops = sh7619_clk_ops[idx];
 }
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/kernel/cpu/sh2/setup-sh7619.c linux-libre-2.6.38-gnu1/arch/sh/kernel/cpu/sh2/setup-sh7619.c
--- linux-libre-2.6.37-gnu1/arch/sh/kernel/cpu/sh2/setup-sh7619.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/kernel/cpu/sh2/setup-sh7619.c	2011-03-14 21:20:32.000000000 -0400
@@ -62,6 +62,8 @@ static DECLARE_INTC_DESC(intc_desc, "sh7
 static struct plat_sci_port scif0_platform_data = {
 	.mapbase	= 0xf8400000,
 	.flags		= UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+	.scbrr_algo_id	= SCBRR_ALGO_2,
 	.type		= PORT_SCIF,
 	.irqs		= { 88, 88, 88, 88 },
 };
@@ -77,6 +79,8 @@ static struct platform_device scif0_devi
 static struct plat_sci_port scif1_platform_data = {
 	.mapbase	= 0xf8410000,
 	.flags		= UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+	.scbrr_algo_id	= SCBRR_ALGO_2,
 	.type		= PORT_SCIF,
 	.irqs		= { 92, 92, 92, 92 },
 };
@@ -92,6 +96,8 @@ static struct platform_device scif1_devi
 static struct plat_sci_port scif2_platform_data = {
 	.mapbase	= 0xf8420000,
 	.flags		= UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+	.scbrr_algo_id	= SCBRR_ALGO_2,
 	.type		= PORT_SCIF,
 	.irqs		= { 96, 96, 96, 96 },
 };
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/kernel/cpu/sh2a/clock-sh7201.c linux-libre-2.6.38-gnu1/arch/sh/kernel/cpu/sh2a/clock-sh7201.c
--- linux-libre-2.6.37-gnu1/arch/sh/kernel/cpu/sh2a/clock-sh7201.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/kernel/cpu/sh2a/clock-sh7201.c	2011-03-14 21:20:32.000000000 -0400
@@ -22,19 +22,12 @@ static const int pll1rate[]={1,2,3,4,6,8
 static const int pfc_divisors[]={1,2,3,4,6,8,12};
 #define ifc_divisors pfc_divisors
 
-#if (CONFIG_SH_CLK_MD == 0)
-#define PLL2 (4)
-#elif (CONFIG_SH_CLK_MD == 2)
-#define PLL2 (2)
-#elif (CONFIG_SH_CLK_MD == 3)
-#define PLL2 (1)
-#else
-#error "Illegal Clock Mode!"
-#endif
+static unsigned int pll2_mult;
 
 static void master_clk_init(struct clk *clk)
 {
-	clk->rate = 10000000 * PLL2 * pll1rate[(__raw_readw(FREQCR) >> 8) & 0x0007];
+	clk->rate = 10000000 * pll2_mult *
+	       pll1rate[(__raw_readw(FREQCR) >> 8) & 0x0007];
 }
 
 static struct clk_ops sh7201_master_clk_ops = {
@@ -80,6 +73,13 @@ static struct clk_ops *sh7201_clk_ops[]
 
 void __init arch_init_clk_ops(struct clk_ops **ops, int idx)
 {
+	if (test_mode_pin(MODE_PIN1 | MODE_PIN0))
+		pll2_mult = 1;
+	else if (test_mode_pin(MODE_PIN1))
+		pll2_mult = 2;
+	else
+		pll2_mult = 4;
+
 	if (idx < ARRAY_SIZE(sh7201_clk_ops))
 		*ops = sh7201_clk_ops[idx];
 }
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/kernel/cpu/sh2a/clock-sh7203.c linux-libre-2.6.38-gnu1/arch/sh/kernel/cpu/sh2a/clock-sh7203.c
--- linux-libre-2.6.37-gnu1/arch/sh/kernel/cpu/sh2a/clock-sh7203.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/kernel/cpu/sh2a/clock-sh7203.c	2011-03-14 21:20:32.000000000 -0400
@@ -25,21 +25,11 @@ static const int pll1rate[]={8,12,16,0};
 static const int pfc_divisors[]={1,2,3,4,6,8,12};
 #define ifc_divisors pfc_divisors
 
-#if (CONFIG_SH_CLK_MD == 0)
-#define PLL2 (1)
-#elif (CONFIG_SH_CLK_MD == 1)
-#define PLL2 (2)
-#elif (CONFIG_SH_CLK_MD == 2)
-#define PLL2 (4)
-#elif (CONFIG_SH_CLK_MD == 3)
-#define PLL2 (4)
-#else
-#error "Illegal Clock Mode!"
-#endif
+static unsigned int pll2_mult;
 
 static void master_clk_init(struct clk *clk)
 {
-	clk->rate *= pll1rate[(__raw_readw(FREQCR) >> 8) & 0x0003] * PLL2 ;
+	clk->rate *= pll1rate[(__raw_readw(FREQCR) >> 8) & 0x0003] * pll2_mult;
 }
 
 static struct clk_ops sh7203_master_clk_ops = {
@@ -79,6 +69,13 @@ static struct clk_ops *sh7203_clk_ops[]
 
 void __init arch_init_clk_ops(struct clk_ops **ops, int idx)
 {
+	if (test_mode_pin(MODE_PIN1))
+		pll2_mult = 4;
+	else if (test_mode_pin(MODE_PIN0))
+		pll2_mult = 2;
+	else
+		pll2_mult = 1;
+
 	if (idx < ARRAY_SIZE(sh7203_clk_ops))
 		*ops = sh7203_clk_ops[idx];
 }
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/kernel/cpu/sh2a/clock-sh7206.c linux-libre-2.6.38-gnu1/arch/sh/kernel/cpu/sh2a/clock-sh7206.c
--- linux-libre-2.6.37-gnu1/arch/sh/kernel/cpu/sh2a/clock-sh7206.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/kernel/cpu/sh2a/clock-sh7206.c	2011-03-14 21:20:32.000000000 -0400
@@ -22,19 +22,11 @@ static const int pll1rate[]={1,2,3,4,6,8
 static const int pfc_divisors[]={1,2,3,4,6,8,12};
 #define ifc_divisors pfc_divisors
 
-#if (CONFIG_SH_CLK_MD == 2)
-#define PLL2 (4)
-#elif (CONFIG_SH_CLK_MD == 6)
-#define PLL2 (2)
-#elif (CONFIG_SH_CLK_MD == 7)
-#define PLL2 (1)
-#else
-#error "Illigal Clock Mode!"
-#endif
+static unsigned int pll2_mult;
 
 static void master_clk_init(struct clk *clk)
 {
-	clk->rate *= PLL2 * pll1rate[(__raw_readw(FREQCR) >> 8) & 0x0007];
+	clk->rate *= pll2_mult * pll1rate[(__raw_readw(FREQCR) >> 8) & 0x0007];
 }
 
 static struct clk_ops sh7206_master_clk_ops = {
@@ -79,7 +71,13 @@ static struct clk_ops *sh7206_clk_ops[]
 
 void __init arch_init_clk_ops(struct clk_ops **ops, int idx)
 {
+	if (test_mode_pin(MODE_PIN2 | MODE_PIN1 | MODE_PIN0))
+		pll2_mult = 1;
+	else if (test_mode_pin(MODE_PIN2 | MODE_PIN1))
+		pll2_mult = 2;
+	else if (test_mode_pin(MODE_PIN1))
+		pll2_mult = 4;
+
 	if (idx < ARRAY_SIZE(sh7206_clk_ops))
 		*ops = sh7206_clk_ops[idx];
 }
-
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/kernel/cpu/sh2a/setup-mxg.c linux-libre-2.6.38-gnu1/arch/sh/kernel/cpu/sh2a/setup-mxg.c
--- linux-libre-2.6.37-gnu1/arch/sh/kernel/cpu/sh2a/setup-mxg.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/kernel/cpu/sh2a/setup-mxg.c	2011-03-14 21:20:32.000000000 -0400
@@ -201,6 +201,8 @@ static struct platform_device mtu2_2_dev
 static struct plat_sci_port scif0_platform_data = {
 	.mapbase	= 0xff804000,
 	.flags		= UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+	.scbrr_algo_id	= SCBRR_ALGO_2,
 	.type		= PORT_SCIF,
 	.irqs		= { 220, 220, 220, 220 },
 };
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/kernel/cpu/sh2a/setup-sh7201.c linux-libre-2.6.38-gnu1/arch/sh/kernel/cpu/sh2a/setup-sh7201.c
--- linux-libre-2.6.37-gnu1/arch/sh/kernel/cpu/sh2a/setup-sh7201.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/kernel/cpu/sh2a/setup-sh7201.c	2011-03-14 21:20:32.000000000 -0400
@@ -180,6 +180,8 @@ 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,
+	.scbrr_algo_id	= SCBRR_ALGO_2,
 	.type		= PORT_SCIF,
 	.irqs		= { 180, 180, 180, 180 }
 };
@@ -195,6 +197,8 @@ 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,
+	.scbrr_algo_id	= SCBRR_ALGO_2,
 	.type		= PORT_SCIF,
 	.irqs		= { 184, 184, 184, 184 }
 };
@@ -210,6 +214,8 @@ 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,
+	.scbrr_algo_id	= SCBRR_ALGO_2,
 	.type		= PORT_SCIF,
 	.irqs		= { 188, 188, 188, 188 }
 };
@@ -225,6 +231,8 @@ 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,
+	.scbrr_algo_id	= SCBRR_ALGO_2,
 	.type		= PORT_SCIF,
 	.irqs		= { 192, 192, 192, 192 }
 };
@@ -240,6 +248,8 @@ static struct platform_device scif3_devi
 static struct plat_sci_port scif4_platform_data = {
 	.mapbase	= 0xfffea000,
 	.flags		= UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+	.scbrr_algo_id	= SCBRR_ALGO_2,
 	.type		= PORT_SCIF,
 	.irqs		= { 196, 196, 196, 196 }
 };
@@ -255,6 +265,8 @@ static struct platform_device scif4_devi
 static struct plat_sci_port scif5_platform_data = {
 	.mapbase	= 0xfffea800,
 	.flags		= UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+	.scbrr_algo_id	= SCBRR_ALGO_2,
 	.type		= PORT_SCIF,
 	.irqs		= { 200, 200, 200, 200 }
 };
@@ -270,6 +282,8 @@ static struct platform_device scif5_devi
 static struct plat_sci_port scif6_platform_data = {
 	.mapbase	= 0xfffeb000,
 	.flags		= UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+	.scbrr_algo_id	= SCBRR_ALGO_2,
 	.type		= PORT_SCIF,
 	.irqs		= { 204, 204, 204, 204 }
 };
@@ -285,6 +299,8 @@ static struct platform_device scif6_devi
 static struct plat_sci_port scif7_platform_data = {
 	.mapbase	= 0xfffeb800,
 	.flags		= UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+	.scbrr_algo_id	= SCBRR_ALGO_2,
 	.type		= PORT_SCIF,
 	.irqs		= { 208, 208, 208, 208 }
 };
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/kernel/cpu/sh2a/setup-sh7203.c linux-libre-2.6.38-gnu1/arch/sh/kernel/cpu/sh2a/setup-sh7203.c
--- linux-libre-2.6.37-gnu1/arch/sh/kernel/cpu/sh2a/setup-sh7203.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/kernel/cpu/sh2a/setup-sh7203.c	2011-03-14 21:20:32.000000000 -0400
@@ -176,6 +176,8 @@ 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,
+	.scbrr_algo_id	= SCBRR_ALGO_2,
 	.type		= PORT_SCIF,
 	.irqs		=  { 192, 192, 192, 192 },
 };
@@ -191,6 +193,8 @@ 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,
+	.scbrr_algo_id	= SCBRR_ALGO_2,
 	.type		= PORT_SCIF,
 	.irqs		=  { 196, 196, 196, 196 },
 };
@@ -206,6 +210,8 @@ 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,
+	.scbrr_algo_id	= SCBRR_ALGO_2,
 	.type		= PORT_SCIF,
 	.irqs		=  { 200, 200, 200, 200 },
 };
@@ -221,6 +227,8 @@ 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,
+	.scbrr_algo_id	= SCBRR_ALGO_2,
 	.type		= PORT_SCIF,
 	.irqs		=  { 204, 204, 204, 204 },
 };
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/kernel/cpu/sh2a/setup-sh7206.c linux-libre-2.6.38-gnu1/arch/sh/kernel/cpu/sh2a/setup-sh7206.c
--- linux-libre-2.6.37-gnu1/arch/sh/kernel/cpu/sh2a/setup-sh7206.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/kernel/cpu/sh2a/setup-sh7206.c	2011-03-14 21:20:32.000000000 -0400
@@ -136,6 +136,8 @@ 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,
+	.scbrr_algo_id	= SCBRR_ALGO_2,
 	.type		= PORT_SCIF,
 	.irqs		= { 240, 240, 240, 240 },
 };
@@ -151,6 +153,8 @@ 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,
+	.scbrr_algo_id	= SCBRR_ALGO_2,
 	.type		= PORT_SCIF,
 	.irqs		= { 244, 244, 244, 244 },
 };
@@ -166,6 +170,8 @@ 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,
+	.scbrr_algo_id	= SCBRR_ALGO_2,
 	.type		= PORT_SCIF,
 	.irqs		= { 248, 248, 248, 248 },
 };
@@ -181,6 +187,8 @@ 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,
+	.scbrr_algo_id	= SCBRR_ALGO_2,
 	.type		= PORT_SCIF,
 	.irqs		= { 252, 252, 252, 252 },
 };
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/kernel/cpu/sh3/setup-sh7705.c linux-libre-2.6.38-gnu1/arch/sh/kernel/cpu/sh3/setup-sh7705.c
--- linux-libre-2.6.37-gnu1/arch/sh/kernel/cpu/sh3/setup-sh7705.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/kernel/cpu/sh3/setup-sh7705.c	2011-03-14 21:20:32.000000000 -0400
@@ -70,6 +70,9 @@ static DECLARE_INTC_DESC(intc_desc, "sh7
 static struct plat_sci_port scif0_platform_data = {
 	.mapbase	= 0xa4410000,
 	.flags		= UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_TIE | SCSCR_RIE  | SCSCR_TE |
+			  SCSCR_RE  | SCSCR_CKE1 | SCSCR_CKE0,
+	.scbrr_algo_id	= SCBRR_ALGO_4,
 	.type		= PORT_SCIF,
 	.irqs		= { 56, 56, 56 },
 };
@@ -85,6 +88,8 @@ static struct platform_device scif0_devi
 static struct plat_sci_port scif1_platform_data = {
 	.mapbase	= 0xa4400000,
 	.flags		= UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_TIE | SCSCR_RIE | SCSCR_TE | SCSCR_RE,
+	.scbrr_algo_id	= SCBRR_ALGO_4,
 	.type		= PORT_SCIF,
 	.irqs		= { 52, 52, 52 },
 };
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/kernel/cpu/sh3/setup-sh770x.c linux-libre-2.6.38-gnu1/arch/sh/kernel/cpu/sh3/setup-sh770x.c
--- linux-libre-2.6.37-gnu1/arch/sh/kernel/cpu/sh3/setup-sh770x.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/kernel/cpu/sh3/setup-sh770x.c	2011-03-14 21:20:32.000000000 -0400
@@ -109,6 +109,8 @@ static struct platform_device rtc_device
 static struct plat_sci_port scif0_platform_data = {
 	.mapbase	= 0xfffffe80,
 	.flags		= UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_TE | SCSCR_RE,
+	.scbrr_algo_id	= SCBRR_ALGO_2,
 	.type		= PORT_SCI,
 	.irqs		= { 23, 23, 23, 0 },
 };
@@ -126,6 +128,8 @@ static struct platform_device scif0_devi
 static struct plat_sci_port scif1_platform_data = {
 	.mapbase	= 0xa4000150,
 	.flags		= UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_TE | SCSCR_RE,
+	.scbrr_algo_id	= SCBRR_ALGO_2,
 	.type		= PORT_SCIF,
 	.irqs		= { 56, 56, 56, 56 },
 };
@@ -143,6 +147,8 @@ static struct platform_device scif1_devi
 static struct plat_sci_port scif2_platform_data = {
 	.mapbase	= 0xa4000140,
 	.flags		= UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_TE | SCSCR_RE,
+	.scbrr_algo_id	= SCBRR_ALGO_2,
 	.type		= PORT_IRDA,
 	.irqs		= { 52, 52, 52, 52 },
 };
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/kernel/cpu/sh3/setup-sh7710.c linux-libre-2.6.38-gnu1/arch/sh/kernel/cpu/sh3/setup-sh7710.c
--- linux-libre-2.6.37-gnu1/arch/sh/kernel/cpu/sh3/setup-sh7710.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/kernel/cpu/sh3/setup-sh7710.c	2011-03-14 21:20:32.000000000 -0400
@@ -99,6 +99,9 @@ static struct platform_device rtc_device
 static struct plat_sci_port scif0_platform_data = {
 	.mapbase	= 0xa4400000,
 	.flags		= UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_TE | SCSCR_RE | SCSCR_REIE |
+			  SCSCR_CKE1 | SCSCR_CKE0,
+	.scbrr_algo_id	= SCBRR_ALGO_2,
 	.type		= PORT_SCIF,
 	.irqs		= { 52, 52, 52, 52 },
 };
@@ -114,6 +117,9 @@ static struct platform_device scif0_devi
 static struct plat_sci_port scif1_platform_data = {
 	.mapbase	= 0xa4410000,
 	.flags		= UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_TE | SCSCR_RE | SCSCR_REIE |
+			  SCSCR_CKE1 | SCSCR_CKE0,
+	.scbrr_algo_id	= SCBRR_ALGO_2,
 	.type		= PORT_SCIF,
 	.irqs           = { 56, 56, 56, 56 },
 };
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/kernel/cpu/sh3/setup-sh7720.c linux-libre-2.6.38-gnu1/arch/sh/kernel/cpu/sh3/setup-sh7720.c
--- linux-libre-2.6.37-gnu1/arch/sh/kernel/cpu/sh3/setup-sh7720.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/kernel/cpu/sh3/setup-sh7720.c	2011-03-14 21:20:32.000000000 -0400
@@ -1,5 +1,5 @@
 /*
- * SH7720 Setup
+ * Setup code for SH7720, SH7721.
  *
  *  Copyright (C) 2007  Markus Brunner, Mark Jonas
  *  Copyright (C) 2009  Paul Mundt
@@ -51,6 +51,8 @@ static struct platform_device rtc_device
 static struct plat_sci_port scif0_platform_data = {
 	.mapbase	= 0xa4430000,
 	.flags		= UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_RE | SCSCR_TE,
+	.scbrr_algo_id	= SCBRR_ALGO_4,
 	.type		= PORT_SCIF,
 	.irqs		= { 80, 80, 80, 80 },
 };
@@ -66,6 +68,8 @@ static struct platform_device scif0_devi
 static struct plat_sci_port scif1_platform_data = {
 	.mapbase	= 0xa4438000,
 	.flags		= UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_RE | SCSCR_TE,
+	.scbrr_algo_id	= SCBRR_ALGO_4,
 	.type		= PORT_SCIF,
 	.irqs           = { 81, 81, 81, 81 },
 };
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/kernel/cpu/sh4/clock-sh4-202.c linux-libre-2.6.38-gnu1/arch/sh/kernel/cpu/sh4/clock-sh4-202.c
--- linux-libre-2.6.37-gnu1/arch/sh/kernel/cpu/sh4/clock-sh4-202.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/kernel/cpu/sh4/clock-sh4-202.c	2011-03-14 21:20:32.000000000 -0400
@@ -13,7 +13,7 @@
 #include <linux/kernel.h>
 #include <linux/err.h>
 #include <linux/io.h>
-#include <asm/clkdev.h>
+#include <linux/clkdev.h>
 #include <asm/clock.h>
 #include <asm/freq.h>
 
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/kernel/cpu/sh4/perf_event.c linux-libre-2.6.38-gnu1/arch/sh/kernel/cpu/sh4/perf_event.c
--- linux-libre-2.6.37-gnu1/arch/sh/kernel/cpu/sh4/perf_event.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/kernel/cpu/sh4/perf_event.c	2011-03-14 21:20:32.000000000 -0400
@@ -250,4 +250,4 @@ static int __init sh7750_pmu_init(void)
 
 	return register_sh_pmu(&sh7750_pmu);
 }
-arch_initcall(sh7750_pmu_init);
+early_initcall(sh7750_pmu_init);
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/kernel/cpu/sh4/probe.c linux-libre-2.6.38-gnu1/arch/sh/kernel/cpu/sh4/probe.c
--- linux-libre-2.6.37-gnu1/arch/sh/kernel/cpu/sh4/probe.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/kernel/cpu/sh4/probe.c	2011-03-14 21:20:32.000000000 -0400
@@ -151,8 +151,14 @@ void __cpuinit cpu_probe(void)
 			boot_cpu_data.flags |= CPU_HAS_L2_CACHE;
 			break;
 		case 0x10:
+		case 0x11:
 			boot_cpu_data.type = CPU_SH7757;
 			break;
+		case 0xd0:
+		case 0x40: /* yon-ten-go */
+			boot_cpu_data.type = CPU_SH7372;
+			break;
+
 		}
 		break;
 	case 0x4000:	/* 1st cut */
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/kernel/cpu/sh4/setup-sh4-202.c linux-libre-2.6.38-gnu1/arch/sh/kernel/cpu/sh4/setup-sh4-202.c
--- linux-libre-2.6.37-gnu1/arch/sh/kernel/cpu/sh4/setup-sh4-202.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/kernel/cpu/sh4/setup-sh4-202.c	2011-03-14 21:20:32.000000000 -0400
@@ -18,6 +18,8 @@
 static struct plat_sci_port scif0_platform_data = {
 	.mapbase	= 0xffe80000,
 	.flags		= UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+	.scbrr_algo_id	= SCBRR_ALGO_2,
 	.type		= PORT_SCIF,
 	.irqs		= { 40, 41, 43, 42 },
 };
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/kernel/cpu/sh4/setup-sh7750.c linux-libre-2.6.38-gnu1/arch/sh/kernel/cpu/sh4/setup-sh7750.c
--- linux-libre-2.6.37-gnu1/arch/sh/kernel/cpu/sh4/setup-sh7750.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/kernel/cpu/sh4/setup-sh7750.c	2011-03-14 21:20:32.000000000 -0400
@@ -14,6 +14,7 @@
 #include <linux/io.h>
 #include <linux/sh_timer.h>
 #include <linux/serial_sci.h>
+#include <generated/machtypes.h>
 
 static struct resource rtc_resources[] = {
 	[0] = {
@@ -35,33 +36,37 @@ static struct platform_device rtc_device
 	.resource	= rtc_resources,
 };
 
-static struct plat_sci_port scif0_platform_data = {
+static struct plat_sci_port sci_platform_data = {
 	.mapbase	= 0xffe00000,
 	.flags		= UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_TE | SCSCR_RE,
+	.scbrr_algo_id	= SCBRR_ALGO_2,
 	.type		= PORT_SCI,
 	.irqs		= { 23, 23, 23, 0 },
 };
 
-static struct platform_device scif0_device = {
+static struct platform_device sci_device = {
 	.name		= "sh-sci",
 	.id		= 0,
 	.dev		= {
-		.platform_data	= &scif0_platform_data,
+		.platform_data	= &sci_platform_data,
 	},
 };
 
-static struct plat_sci_port scif1_platform_data = {
+static struct plat_sci_port scif_platform_data = {
 	.mapbase	= 0xffe80000,
 	.flags		= UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_TE | SCSCR_RE | SCSCR_REIE,
+	.scbrr_algo_id	= SCBRR_ALGO_2,
 	.type		= PORT_SCIF,
 	.irqs		= { 40, 40, 40, 40 },
 };
 
-static struct platform_device scif1_device = {
+static struct platform_device scif_device = {
 	.name		= "sh-sci",
 	.id		= 1,
 	.dev		= {
-		.platform_data	= &scif1_platform_data,
+		.platform_data	= &scif_platform_data,
 	},
 };
 
@@ -210,8 +215,6 @@ static struct platform_device tmu4_devic
 #endif
 
 static struct platform_device *sh7750_devices[] __initdata = {
-	&scif0_device,
-	&scif1_device,
 	&rtc_device,
 	&tmu0_device,
 	&tmu1_device,
@@ -226,14 +229,19 @@ static struct platform_device *sh7750_de
 
 static int __init sh7750_devices_setup(void)
 {
+	if (mach_is_rts7751r2d()) {
+		platform_device_register(&scif_device);
+	} else {
+		platform_device_register(&sci_device);
+		platform_device_register(&scif_device);
+	}
+
 	return platform_add_devices(sh7750_devices,
 				    ARRAY_SIZE(sh7750_devices));
 }
 arch_initcall(sh7750_devices_setup);
 
 static struct platform_device *sh7750_early_devices[] __initdata = {
-	&scif0_device,
-	&scif1_device,
 	&tmu0_device,
 	&tmu1_device,
 	&tmu2_device,
@@ -247,6 +255,19 @@ static struct platform_device *sh7750_ea
 
 void __init plat_early_device_setup(void)
 {
+	struct platform_device *dev[1];
+
+	if (mach_is_rts7751r2d()) {
+		scif_platform_data.scscr |= SCSCR_CKE1;
+		dev[0] = &scif_device;
+		early_platform_add_devices(dev, 1);
+	} else {
+		dev[0] = &sci_device;
+		early_platform_add_devices(dev, 1);
+		dev[0] = &scif_device;
+		early_platform_add_devices(dev, 1);
+	}
+
 	early_platform_add_devices(sh7750_early_devices,
 				   ARRAY_SIZE(sh7750_early_devices));
 }
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/kernel/cpu/sh4/setup-sh7760.c linux-libre-2.6.38-gnu1/arch/sh/kernel/cpu/sh4/setup-sh7760.c
--- linux-libre-2.6.37-gnu1/arch/sh/kernel/cpu/sh4/setup-sh7760.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/kernel/cpu/sh4/setup-sh7760.c	2011-03-14 21:20:32.000000000 -0400
@@ -129,6 +129,8 @@ static DECLARE_INTC_DESC(intc_desc_irq,
 static struct plat_sci_port scif0_platform_data = {
 	.mapbase	= 0xfe600000,
 	.flags		= UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+	.scbrr_algo_id	= SCBRR_ALGO_2,
 	.type		= PORT_SCIF,
 	.irqs		= { 52, 53, 55, 54 },
 };
@@ -145,6 +147,8 @@ static struct plat_sci_port scif1_platfo
 	.mapbase	= 0xfe610000,
 	.flags		= UPF_BOOT_AUTOCONF,
 	.type		= PORT_SCIF,
+	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+	.scbrr_algo_id	= SCBRR_ALGO_2,
 	.irqs		= { 72, 73, 75, 74 },
 };
 
@@ -159,6 +163,8 @@ static struct platform_device scif1_devi
 static struct plat_sci_port scif2_platform_data = {
 	.mapbase	= 0xfe620000,
 	.flags		= UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+	.scbrr_algo_id	= SCBRR_ALGO_2,
 	.type		= PORT_SCIF,
 	.irqs		= { 76, 77, 79, 78 },
 };
@@ -174,6 +180,8 @@ static struct platform_device scif2_devi
 static struct plat_sci_port scif3_platform_data = {
 	.mapbase	= 0xfe480000,
 	.flags		= UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+	.scbrr_algo_id	= SCBRR_ALGO_2,
 	.type		= PORT_SCI,
 	.irqs		= { 80, 81, 82, 0 },
 };
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/kernel/cpu/sh4a/clock-sh7343.c linux-libre-2.6.38-gnu1/arch/sh/kernel/cpu/sh4a/clock-sh7343.c
--- linux-libre-2.6.37-gnu1/arch/sh/kernel/cpu/sh4a/clock-sh7343.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/kernel/cpu/sh4a/clock-sh7343.c	2011-03-14 21:20:32.000000000 -0400
@@ -21,7 +21,7 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/io.h>
-#include <asm/clkdev.h>
+#include <linux/clkdev.h>
 #include <asm/clock.h>
 
 /* SH7343 registers */
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/kernel/cpu/sh4a/clock-sh7366.c linux-libre-2.6.38-gnu1/arch/sh/kernel/cpu/sh4a/clock-sh7366.c
--- linux-libre-2.6.37-gnu1/arch/sh/kernel/cpu/sh4a/clock-sh7366.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/kernel/cpu/sh4a/clock-sh7366.c	2011-03-14 21:20:32.000000000 -0400
@@ -21,7 +21,7 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/io.h>
-#include <asm/clkdev.h>
+#include <linux/clkdev.h>
 #include <asm/clock.h>
 
 /* SH7366 registers */
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/kernel/cpu/sh4a/clock-sh7722.c linux-libre-2.6.38-gnu1/arch/sh/kernel/cpu/sh4a/clock-sh7722.c
--- linux-libre-2.6.37-gnu1/arch/sh/kernel/cpu/sh4a/clock-sh7722.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/kernel/cpu/sh4a/clock-sh7722.c	2011-03-14 21:20:32.000000000 -0400
@@ -21,7 +21,7 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/io.h>
-#include <asm/clkdev.h>
+#include <linux/clkdev.h>
 #include <asm/clock.h>
 #include <asm/hwblk.h>
 #include <cpu/sh7722.h>
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/kernel/cpu/sh4a/clock-sh7723.c linux-libre-2.6.38-gnu1/arch/sh/kernel/cpu/sh4a/clock-sh7723.c
--- linux-libre-2.6.37-gnu1/arch/sh/kernel/cpu/sh4a/clock-sh7723.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/kernel/cpu/sh4a/clock-sh7723.c	2011-03-14 21:20:32.000000000 -0400
@@ -22,7 +22,7 @@
 #include <linux/kernel.h>
 #include <linux/io.h>
 #include <linux/clk.h>
-#include <asm/clkdev.h>
+#include <linux/clkdev.h>
 #include <asm/clock.h>
 #include <asm/hwblk.h>
 #include <cpu/sh7723.h>
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/kernel/cpu/sh4a/clock-sh7724.c linux-libre-2.6.38-gnu1/arch/sh/kernel/cpu/sh4a/clock-sh7724.c
--- linux-libre-2.6.37-gnu1/arch/sh/kernel/cpu/sh4a/clock-sh7724.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/kernel/cpu/sh4a/clock-sh7724.c	2011-03-14 21:20:32.000000000 -0400
@@ -22,7 +22,7 @@
 #include <linux/kernel.h>
 #include <linux/io.h>
 #include <linux/clk.h>
-#include <asm/clkdev.h>
+#include <linux/clkdev.h>
 #include <asm/clock.h>
 #include <asm/hwblk.h>
 #include <cpu/sh7724.h>
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/kernel/cpu/sh4a/clock-sh7757.c linux-libre-2.6.38-gnu1/arch/sh/kernel/cpu/sh4a/clock-sh7757.c
--- linux-libre-2.6.37-gnu1/arch/sh/kernel/cpu/sh4a/clock-sh7757.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/kernel/cpu/sh4a/clock-sh7757.c	2011-03-14 21:20:32.000000000 -0400
@@ -12,7 +12,7 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/io.h>
-#include <asm/clkdev.h>
+#include <linux/clkdev.h>
 #include <asm/clock.h>
 #include <asm/freq.h>
 
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/kernel/cpu/sh4a/clock-sh7763.c linux-libre-2.6.38-gnu1/arch/sh/kernel/cpu/sh4a/clock-sh7763.c
--- linux-libre-2.6.37-gnu1/arch/sh/kernel/cpu/sh4a/clock-sh7763.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/kernel/cpu/sh4a/clock-sh7763.c	2011-03-14 21:20:32.000000000 -0400
@@ -13,7 +13,7 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/io.h>
-#include <asm/clkdev.h>
+#include <linux/clkdev.h>
 #include <asm/clock.h>
 #include <asm/freq.h>
 #include <asm/io.h>
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/kernel/cpu/sh4a/clock-sh7780.c linux-libre-2.6.38-gnu1/arch/sh/kernel/cpu/sh4a/clock-sh7780.c
--- linux-libre-2.6.37-gnu1/arch/sh/kernel/cpu/sh4a/clock-sh7780.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/kernel/cpu/sh4a/clock-sh7780.c	2011-03-14 21:20:32.000000000 -0400
@@ -12,7 +12,7 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/io.h>
-#include <asm/clkdev.h>
+#include <linux/clkdev.h>
 #include <asm/clock.h>
 #include <asm/freq.h>
 #include <asm/io.h>
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/kernel/cpu/sh4a/clock-sh7785.c linux-libre-2.6.38-gnu1/arch/sh/kernel/cpu/sh4a/clock-sh7785.c
--- linux-libre-2.6.37-gnu1/arch/sh/kernel/cpu/sh4a/clock-sh7785.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/kernel/cpu/sh4a/clock-sh7785.c	2011-03-14 21:20:32.000000000 -0400
@@ -14,7 +14,7 @@
 #include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/cpufreq.h>
-#include <asm/clkdev.h>
+#include <linux/clkdev.h>
 #include <asm/clock.h>
 #include <asm/freq.h>
 #include <cpu/sh7785.h>
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/kernel/cpu/sh4a/clock-sh7786.c linux-libre-2.6.38-gnu1/arch/sh/kernel/cpu/sh4a/clock-sh7786.c
--- linux-libre-2.6.37-gnu1/arch/sh/kernel/cpu/sh4a/clock-sh7786.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/kernel/cpu/sh4a/clock-sh7786.c	2011-03-14 21:20:32.000000000 -0400
@@ -13,7 +13,7 @@
 #include <linux/kernel.h>
 #include <linux/clk.h>
 #include <linux/io.h>
-#include <asm/clkdev.h>
+#include <linux/clkdev.h>
 #include <asm/clock.h>
 #include <asm/freq.h>
 
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/kernel/cpu/sh4a/clock-shx3.c linux-libre-2.6.38-gnu1/arch/sh/kernel/cpu/sh4a/clock-shx3.c
--- linux-libre-2.6.37-gnu1/arch/sh/kernel/cpu/sh4a/clock-shx3.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/kernel/cpu/sh4a/clock-shx3.c	2011-03-14 21:20:32.000000000 -0400
@@ -14,7 +14,7 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/io.h>
-#include <asm/clkdev.h>
+#include <linux/clkdev.h>
 #include <asm/clock.h>
 #include <asm/freq.h>
 
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/kernel/cpu/sh4a/perf_event.c linux-libre-2.6.38-gnu1/arch/sh/kernel/cpu/sh4a/perf_event.c
--- linux-libre-2.6.37-gnu1/arch/sh/kernel/cpu/sh4a/perf_event.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/kernel/cpu/sh4a/perf_event.c	2011-03-14 21:20:32.000000000 -0400
@@ -284,4 +284,4 @@ static int __init sh4a_pmu_init(void)
 
 	return register_sh_pmu(&sh4a_pmu);
 }
-arch_initcall(sh4a_pmu_init);
+early_initcall(sh4a_pmu_init);
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/kernel/cpu/sh4a/setup-sh7343.c linux-libre-2.6.38-gnu1/arch/sh/kernel/cpu/sh4a/setup-sh7343.c
--- linux-libre-2.6.37-gnu1/arch/sh/kernel/cpu/sh4a/setup-sh7343.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/kernel/cpu/sh4a/setup-sh7343.c	2011-03-14 21:20:32.000000000 -0400
@@ -19,6 +19,8 @@
 static struct plat_sci_port scif0_platform_data = {
 	.mapbase        = 0xffe00000,
 	.flags          = UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_CKE1,
+	.scbrr_algo_id	= SCBRR_ALGO_2,
 	.type           = PORT_SCIF,
 	.irqs           = { 80, 80, 80, 80 },
 };
@@ -34,6 +36,8 @@ static struct platform_device scif0_devi
 static struct plat_sci_port scif1_platform_data = {
 	.mapbase        = 0xffe10000,
 	.flags          = UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_CKE1,
+	.scbrr_algo_id	= SCBRR_ALGO_2,
 	.type           = PORT_SCIF,
 	.irqs           = { 81, 81, 81, 81 },
 };
@@ -49,6 +53,8 @@ static struct platform_device scif1_devi
 static struct plat_sci_port scif2_platform_data = {
 	.mapbase        = 0xffe20000,
 	.flags          = UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_CKE1,
+	.scbrr_algo_id	= SCBRR_ALGO_2,
 	.type           = PORT_SCIF,
 	.irqs           = { 82, 82, 82, 82 },
 };
@@ -64,6 +70,8 @@ static struct platform_device scif2_devi
 static struct plat_sci_port scif3_platform_data = {
 	.mapbase        = 0xffe30000,
 	.flags          = UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_CKE1,
+	.scbrr_algo_id	= SCBRR_ALGO_2,
 	.type           = PORT_SCIF,
 	.irqs           = { 83, 83, 83, 83 },
 };
@@ -360,6 +368,8 @@ void __init plat_early_device_setup(void
 
 enum {
 	UNUSED = 0,
+	ENABLED,
+	DISABLED,
 
 	/* interrupt sources */
 	IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7,
@@ -375,15 +385,13 @@ enum {
 	I2C0_ALI, I2C0_TACKI, I2C0_WAITI, I2C0_DTEI,
 	I2C1_ALI, I2C1_TACKI, I2C1_WAITI, I2C1_DTEI,
 	SIM_TEI, SIM_TXI, SIM_RXI, SIM_ERI,
-	IRDA,
-	SDHI0, SDHI1, SDHI2, SDHI3,
-	CMT, TSIF, SIU,
+	IRDA, SDHI, CMT, TSIF, SIU,
 	TMU0, TMU1, TMU2,
 	JPU, LCDC,
 
 	/* interrupt groups */
 
-	DMAC0123, VIOVOU, MMC, DMAC45, FLCTL, I2C0, I2C1, SIM, SDHI, USB,
+	DMAC0123, VIOVOU, MMC, DMAC45, FLCTL, I2C0, I2C1, SIM, USB,
 };
 
 static struct intc_vect vectors[] __initdata = {
@@ -412,8 +420,8 @@ static struct intc_vect vectors[] __init
 	INTC_VECT(FLCTL_FLTREQ0I, 0xdc0), INTC_VECT(FLCTL_FLTREQ1I, 0xde0),
 	INTC_VECT(I2C0_ALI, 0xe00), INTC_VECT(I2C0_TACKI, 0xe20),
 	INTC_VECT(I2C0_WAITI, 0xe40), INTC_VECT(I2C0_DTEI, 0xe60),
-	INTC_VECT(SDHI0, 0xe80), INTC_VECT(SDHI1, 0xea0),
-	INTC_VECT(SDHI2, 0xec0), INTC_VECT(SDHI3, 0xee0),
+	INTC_VECT(SDHI, 0xe80), INTC_VECT(SDHI, 0xea0),
+	INTC_VECT(SDHI, 0xec0), INTC_VECT(SDHI, 0xee0),
 	INTC_VECT(CMT, 0xf00), INTC_VECT(TSIF, 0xf20),
 	INTC_VECT(SIU, 0xf80),
 	INTC_VECT(TMU0, 0x400), INTC_VECT(TMU1, 0x420),
@@ -431,7 +439,6 @@ static struct intc_group groups[] __init
 	INTC_GROUP(I2C0, I2C0_ALI, I2C0_TACKI, I2C0_WAITI, I2C0_DTEI),
 	INTC_GROUP(I2C1, I2C1_ALI, I2C1_TACKI, I2C1_WAITI, I2C1_DTEI),
 	INTC_GROUP(SIM, SIM_TEI, SIM_TXI, SIM_RXI, SIM_ERI),
-	INTC_GROUP(SDHI, SDHI0, SDHI1, SDHI2, SDHI3),
 	INTC_GROUP(USB, USBI0, USBI1),
 };
 
@@ -452,7 +459,7 @@ static struct intc_mask_reg mask_registe
 	  { I2C0_DTEI, I2C0_WAITI, I2C0_TACKI, I2C0_ALI,
 	    FLCTL_FLTREQ1I, FLCTL_FLTREQ0I, FLCTL_FLENDI, FLCTL_FLSTEI } },
 	{ 0xa40800a0, 0xa40800e0, 8, /* IMR8 / IMCR8 */
-	  { SDHI3, SDHI2, SDHI1, SDHI0, 0, 0, 0, SIU } },
+	  { DISABLED, ENABLED, ENABLED, ENABLED, 0, 0, 0, SIU } },
 	{ 0xa40800a4, 0xa40800e4, 8, /* IMR9 / IMCR9 */
 	  { 0, 0, 0, CMT, 0, USBI1, USBI0 } },
 	{ 0xa40800a8, 0xa40800e8, 8, /* IMR10 / IMCR10 */
@@ -488,9 +495,13 @@ static struct intc_mask_reg ack_register
 	  { IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7 } },
 };
 
-static DECLARE_INTC_DESC_ACK(intc_desc, "sh7343", vectors, groups,
-			     mask_registers, prio_registers, sense_registers,
-			     ack_registers);
+static struct intc_desc intc_desc __initdata = {
+	.name = "sh7343",
+	.force_enable = ENABLED,
+	.force_disable = DISABLED,
+	.hw = INTC_HW_DESC(vectors, groups, mask_registers,
+			   prio_registers, sense_registers, ack_registers),
+};
 
 void __init plat_irq_setup(void)
 {
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/kernel/cpu/sh4a/setup-sh7366.c linux-libre-2.6.38-gnu1/arch/sh/kernel/cpu/sh4a/setup-sh7366.c
--- linux-libre-2.6.37-gnu1/arch/sh/kernel/cpu/sh4a/setup-sh7366.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/kernel/cpu/sh4a/setup-sh7366.c	2011-03-14 21:20:32.000000000 -0400
@@ -21,6 +21,8 @@
 static struct plat_sci_port scif0_platform_data = {
 	.mapbase	= 0xffe00000,
 	.flags		= UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+	.scbrr_algo_id	= SCBRR_ALGO_2,
 	.type		= PORT_SCIF,
 	.irqs		= { 80, 80, 80, 80 },
 };
@@ -319,6 +321,8 @@ void __init plat_early_device_setup(void
 
 enum {
 	UNUSED=0,
+	ENABLED,
+	DISABLED,
 
 	/* interrupt sources */
 	IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7,
@@ -332,14 +336,13 @@ enum {
 	DENC, MSIOF,
 	FLCTL_FLSTEI, FLCTL_FLENDI, FLCTL_FLTREQ0I, FLCTL_FLTREQ1I,
 	I2C_ALI, I2C_TACKI, I2C_WAITI, I2C_DTEI,
-	SDHI0, SDHI1, SDHI2, SDHI3,
-	CMT, TSIF, SIU,
+	SDHI, CMT, TSIF, SIU,
 	TMU0, TMU1, TMU2,
 	VEU2, LCDC,
 
 	/* interrupt groups */
 
-	DMAC0123, VIOVOU, MMC, DMAC45, FLCTL, I2C, SDHI,
+	DMAC0123, VIOVOU, MMC, DMAC45, FLCTL, I2C,
 };
 
 static struct intc_vect vectors[] __initdata = {
@@ -364,8 +367,8 @@ static struct intc_vect vectors[] __init
 	INTC_VECT(FLCTL_FLTREQ0I, 0xdc0), INTC_VECT(FLCTL_FLTREQ1I, 0xde0),
 	INTC_VECT(I2C_ALI, 0xe00), INTC_VECT(I2C_TACKI, 0xe20),
 	INTC_VECT(I2C_WAITI, 0xe40), INTC_VECT(I2C_DTEI, 0xe60),
-	INTC_VECT(SDHI0, 0xe80), INTC_VECT(SDHI1, 0xea0),
-	INTC_VECT(SDHI2, 0xec0), INTC_VECT(SDHI3, 0xee0),
+	INTC_VECT(SDHI, 0xe80), INTC_VECT(SDHI, 0xea0),
+	INTC_VECT(SDHI, 0xec0), INTC_VECT(SDHI, 0xee0),
 	INTC_VECT(CMT, 0xf00), INTC_VECT(TSIF, 0xf20),
 	INTC_VECT(SIU, 0xf80),
 	INTC_VECT(TMU0, 0x400), INTC_VECT(TMU1, 0x420),
@@ -381,7 +384,6 @@ static struct intc_group groups[] __init
 	INTC_GROUP(FLCTL, FLCTL_FLSTEI, FLCTL_FLENDI,
 		   FLCTL_FLTREQ0I, FLCTL_FLTREQ1I),
 	INTC_GROUP(I2C, I2C_ALI, I2C_TACKI, I2C_WAITI, I2C_DTEI),
-	INTC_GROUP(SDHI, SDHI0, SDHI1, SDHI2, SDHI3),
 };
 
 static struct intc_mask_reg mask_registers[] __initdata = {
@@ -403,7 +405,7 @@ static struct intc_mask_reg mask_registe
 	  { I2C_DTEI, I2C_WAITI, I2C_TACKI, I2C_ALI,
 	    FLCTL_FLTREQ1I, FLCTL_FLTREQ0I, FLCTL_FLENDI, FLCTL_FLSTEI } },
 	{ 0xa40800a0, 0xa40800e0, 8, /* IMR8 / IMCR8 */
-	  { SDHI3, SDHI2, SDHI1, SDHI0, 0, 0, 0, SIU } },
+	  { DISABLED, ENABLED, ENABLED, ENABLED, 0, 0, 0, SIU } },
 	{ 0xa40800a4, 0xa40800e4, 8, /* IMR9 / IMCR9 */
 	  { 0, 0, 0, CMT, 0, USB, } },
 	{ 0xa40800a8, 0xa40800e8, 8, /* IMR10 / IMCR10 */
@@ -441,9 +443,13 @@ static struct intc_mask_reg ack_register
 	  { IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7 } },
 };
 
-static DECLARE_INTC_DESC_ACK(intc_desc, "sh7366", vectors, groups,
-			     mask_registers, prio_registers, sense_registers,
-			     ack_registers);
+static struct intc_desc intc_desc __initdata = {
+	.name = "sh7366",
+	.force_enable = ENABLED,
+	.force_disable = DISABLED,
+	.hw = INTC_HW_DESC(vectors, groups, mask_registers,
+			   prio_registers, sense_registers, ack_registers),
+};
 
 void __init plat_irq_setup(void)
 {
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/kernel/cpu/sh4a/setup-sh7722.c linux-libre-2.6.38-gnu1/arch/sh/kernel/cpu/sh4a/setup-sh7722.c
--- linux-libre-2.6.37-gnu1/arch/sh/kernel/cpu/sh4a/setup-sh7722.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/kernel/cpu/sh4a/setup-sh7722.c	2011-03-14 21:20:32.000000000 -0400
@@ -181,6 +181,8 @@ struct platform_device dma_device = {
 static struct plat_sci_port scif0_platform_data = {
 	.mapbase        = 0xffe00000,
 	.flags          = UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+	.scbrr_algo_id	= SCBRR_ALGO_2,
 	.type           = PORT_SCIF,
 	.irqs           = { 80, 80, 80, 80 },
 };
@@ -196,6 +198,8 @@ static struct platform_device scif0_devi
 static struct plat_sci_port scif1_platform_data = {
 	.mapbase        = 0xffe10000,
 	.flags          = UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+	.scbrr_algo_id	= SCBRR_ALGO_2,
 	.type           = PORT_SCIF,
 	.irqs           = { 81, 81, 81, 81 },
 };
@@ -211,6 +215,8 @@ static struct platform_device scif1_devi
 static struct plat_sci_port scif2_platform_data = {
 	.mapbase        = 0xffe20000,
 	.flags          = UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+	.scbrr_algo_id	= SCBRR_ALGO_2,
 	.type           = PORT_SCIF,
 	.irqs           = { 82, 82, 82, 82 },
 };
@@ -699,7 +705,7 @@ static struct intc_mask_reg mask_registe
 	  { I2C_DTEI, I2C_WAITI, I2C_TACKI, I2C_ALI,
 	    FLCTL_FLTREQ1I, FLCTL_FLTREQ0I, FLCTL_FLENDI, FLCTL_FLSTEI } },
 	{ 0xa40800a0, 0xa40800e0, 8, /* IMR8 / IMCR8 */
-	  { DISABLED, DISABLED, ENABLED, ENABLED, 0, 0, TWODG, SIU } },
+	  { DISABLED, ENABLED, ENABLED, ENABLED, 0, 0, TWODG, SIU } },
 	{ 0xa40800a4, 0xa40800e4, 8, /* IMR9 / IMCR9 */
 	  { 0, 0, 0, CMT, 0, USB_USBI1, USB_USBI0, } },
 	{ 0xa40800a8, 0xa40800e8, 8, /* IMR10 / IMCR10 */
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/kernel/cpu/sh4a/setup-sh7723.c linux-libre-2.6.38-gnu1/arch/sh/kernel/cpu/sh4a/setup-sh7723.c
--- linux-libre-2.6.37-gnu1/arch/sh/kernel/cpu/sh4a/setup-sh7723.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/kernel/cpu/sh4a/setup-sh7723.c	2011-03-14 21:20:32.000000000 -0400
@@ -24,6 +24,8 @@
 static struct plat_sci_port scif0_platform_data = {
 	.mapbase        = 0xffe00000,
 	.flags          = UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+	.scbrr_algo_id	= SCBRR_ALGO_2,
 	.type           = PORT_SCIF,
 	.irqs           = { 80, 80, 80, 80 },
 };
@@ -39,6 +41,8 @@ static struct platform_device scif0_devi
 static struct plat_sci_port scif1_platform_data = {
 	.mapbase        = 0xffe10000,
 	.flags          = UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+	.scbrr_algo_id	= SCBRR_ALGO_2,
 	.type           = PORT_SCIF,
 	.irqs           = { 81, 81, 81, 81 },
 };
@@ -54,6 +58,8 @@ static struct platform_device scif1_devi
 static struct plat_sci_port scif2_platform_data = {
 	.mapbase        = 0xffe20000,
 	.flags          = UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+	.scbrr_algo_id	= SCBRR_ALGO_2,
 	.type           = PORT_SCIF,
 	.irqs           = { 82, 82, 82, 82 },
 };
@@ -69,6 +75,8 @@ static struct platform_device scif2_devi
 static struct plat_sci_port scif3_platform_data = {
 	.mapbase        = 0xa4e30000,
 	.flags          = UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+	.scbrr_algo_id	= SCBRR_ALGO_3,
 	.type           = PORT_SCIFA,
 	.irqs           = { 56, 56, 56, 56 },
 };
@@ -84,6 +92,8 @@ static struct platform_device scif3_devi
 static struct plat_sci_port scif4_platform_data = {
 	.mapbase        = 0xa4e40000,
 	.flags          = UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+	.scbrr_algo_id	= SCBRR_ALGO_3,
 	.type           = PORT_SCIFA,
 	.irqs           = { 88, 88, 88, 88 },
 };
@@ -99,6 +109,8 @@ static struct platform_device scif4_devi
 static struct plat_sci_port scif5_platform_data = {
 	.mapbase        = 0xa4e50000,
 	.flags          = UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+	.scbrr_algo_id	= SCBRR_ALGO_3,
 	.type           = PORT_SCIFA,
 	.irqs           = { 109, 109, 109, 109 },
 };
@@ -719,7 +731,7 @@ static struct intc_group groups[] __init
 static struct intc_mask_reg mask_registers[] __initdata = {
 	{ 0xa4080080, 0xa40800c0, 8, /* IMR0 / IMCR0 */
 	  { 0, TMU1_TUNI2, TMU1_TUNI1, TMU1_TUNI0,
-	    0, DISABLED, ENABLED, ENABLED } },
+	    0, ENABLED, ENABLED, ENABLED } },
 	{ 0xa4080084, 0xa40800c4, 8, /* IMR1 / IMCR1 */
 	  { VIO_VOUI, VIO_VEU2HI,VIO_BEUI,VIO_CEUI,DMAC0A_DEI3,DMAC0A_DEI2,DMAC0A_DEI1,DMAC0A_DEI0 } },
 	{ 0xa4080088, 0xa40800c8, 8, /* IMR2 / IMCR2 */
@@ -736,7 +748,7 @@ static struct intc_mask_reg mask_registe
 	  { I2C_DTEI, I2C_WAITI, I2C_TACKI, I2C_ALI,
 	    FLCTL_FLTREQ1I, FLCTL_FLTREQ0I, FLCTL_FLTENDI, FLCTL_FLSTEI } },
 	{ 0xa40800a0, 0xa40800e0, 8, /* IMR8 / IMCR8 */
-	  { 0, DISABLED, ENABLED, ENABLED,
+	  { 0, ENABLED, ENABLED, ENABLED,
 	    0, 0, SCIFA_SCIFA2, SIU_SIUI } },
 	{ 0xa40800a4, 0xa40800e4, 8, /* IMR9 / IMCR9 */
 	  { 0, 0, 0, CMT_CMTI, 0, 0, USB_USI0,0 } },
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/kernel/cpu/sh4a/setup-sh7724.c linux-libre-2.6.38-gnu1/arch/sh/kernel/cpu/sh4a/setup-sh7724.c
--- linux-libre-2.6.37-gnu1/arch/sh/kernel/cpu/sh4a/setup-sh7724.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/kernel/cpu/sh4a/setup-sh7724.c	2011-03-14 21:20:32.000000000 -0400
@@ -257,6 +257,8 @@ static struct platform_device dma1_devic
 static struct plat_sci_port scif0_platform_data = {
 	.mapbase        = 0xffe00000,
 	.flags          = UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+	.scbrr_algo_id	= SCBRR_ALGO_2,
 	.type           = PORT_SCIF,
 	.irqs           = { 80, 80, 80, 80 },
 };
@@ -272,6 +274,8 @@ static struct platform_device scif0_devi
 static struct plat_sci_port scif1_platform_data = {
 	.mapbase        = 0xffe10000,
 	.flags          = UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+	.scbrr_algo_id	= SCBRR_ALGO_2,
 	.type           = PORT_SCIF,
 	.irqs           = { 81, 81, 81, 81 },
 };
@@ -287,6 +291,8 @@ static struct platform_device scif1_devi
 static struct plat_sci_port scif2_platform_data = {
 	.mapbase        = 0xffe20000,
 	.flags          = UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+	.scbrr_algo_id	= SCBRR_ALGO_2,
 	.type           = PORT_SCIF,
 	.irqs           = { 82, 82, 82, 82 },
 };
@@ -302,6 +308,8 @@ static struct platform_device scif2_devi
 static struct plat_sci_port scif3_platform_data = {
 	.mapbase        = 0xa4e30000,
 	.flags          = UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_RE | SCSCR_TE,
+	.scbrr_algo_id	= SCBRR_ALGO_3,
 	.type           = PORT_SCIFA,
 	.irqs           = { 56, 56, 56, 56 },
 };
@@ -317,6 +325,8 @@ static struct platform_device scif3_devi
 static struct plat_sci_port scif4_platform_data = {
 	.mapbase        = 0xa4e40000,
 	.flags          = UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_RE | SCSCR_TE,
+	.scbrr_algo_id	= SCBRR_ALGO_3,
 	.type           = PORT_SCIFA,
 	.irqs           = { 88, 88, 88, 88 },
 };
@@ -332,6 +342,8 @@ static struct platform_device scif4_devi
 static struct plat_sci_port scif5_platform_data = {
 	.mapbase        = 0xa4e50000,
 	.flags          = UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_RE | SCSCR_TE,
+	.scbrr_algo_id	= SCBRR_ALGO_3,
 	.type           = PORT_SCIFA,
 	.irqs           = { 109, 109, 109, 109 },
 };
@@ -1144,7 +1156,7 @@ static struct intc_group groups[] __init
 static struct intc_mask_reg mask_registers[] __initdata = {
 	{ 0xa4080080, 0xa40800c0, 8, /* IMR0 / IMCR0 */
 	  { 0, TMU1_TUNI2, TMU1_TUNI1, TMU1_TUNI0,
-	    0, DISABLED, ENABLED, ENABLED } },
+	    0, ENABLED, ENABLED, ENABLED } },
 	{ 0xa4080084, 0xa40800c4, 8, /* IMR1 / IMCR1 */
 	  { VIO_VOU, VIO_VEU1, VIO_BEU0, VIO_CEU0,
 	    DMAC0A_DEI3, DMAC0A_DEI2, DMAC0A_DEI1, DMAC0A_DEI0 } },
@@ -1166,7 +1178,7 @@ static struct intc_mask_reg mask_registe
 	  { I2C0_DTEI, I2C0_WAITI, I2C0_TACKI, I2C0_ALI,
 	    I2C1_DTEI, I2C1_WAITI, I2C1_TACKI, I2C1_ALI } },
 	{ 0xa40800a0, 0xa40800e0, 8, /* IMR8 / IMCR8 */
-	  { DISABLED, DISABLED, ENABLED, ENABLED,
+	  { DISABLED, ENABLED, ENABLED, ENABLED,
 	    0, 0, SCIFA5, FSI } },
 	{ 0xa40800a4, 0xa40800e4, 8, /* IMR9 / IMCR9 */
 	  { 0, 0, 0, CMT, 0, USB1, USB0, 0 } },
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/kernel/cpu/sh4a/setup-sh7757.c linux-libre-2.6.38-gnu1/arch/sh/kernel/cpu/sh4a/setup-sh7757.c
--- linux-libre-2.6.37-gnu1/arch/sh/kernel/cpu/sh4a/setup-sh7757.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/kernel/cpu/sh4a/setup-sh7757.c	2011-03-14 21:20:32.000000000 -0400
@@ -20,6 +20,8 @@
 static struct plat_sci_port scif2_platform_data = {
 	.mapbase	= 0xfe4b0000,		/* SCIF2 */
 	.flags		= UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+	.scbrr_algo_id	= SCBRR_ALGO_2,
 	.type		= PORT_SCIF,
 	.irqs		= { 40, 40, 40, 40 },
 };
@@ -35,6 +37,8 @@ static struct platform_device scif2_devi
 static struct plat_sci_port scif3_platform_data = {
 	.mapbase	= 0xfe4c0000,		/* SCIF3 */
 	.flags		= UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+	.scbrr_algo_id	= SCBRR_ALGO_2,
 	.type		= PORT_SCIF,
 	.irqs		= { 76, 76, 76, 76 },
 };
@@ -50,6 +54,8 @@ static struct platform_device scif3_devi
 static struct plat_sci_port scif4_platform_data = {
 	.mapbase	= 0xfe4d0000,		/* SCIF4 */
 	.flags		= UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+	.scbrr_algo_id	= SCBRR_ALGO_2,
 	.type		= PORT_SCIF,
 	.irqs		= { 104, 104, 104, 104 },
 };
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/kernel/cpu/sh4a/setup-sh7763.c linux-libre-2.6.38-gnu1/arch/sh/kernel/cpu/sh4a/setup-sh7763.c
--- linux-libre-2.6.37-gnu1/arch/sh/kernel/cpu/sh4a/setup-sh7763.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/kernel/cpu/sh4a/setup-sh7763.c	2011-03-14 21:20:32.000000000 -0400
@@ -19,6 +19,8 @@
 static struct plat_sci_port scif0_platform_data = {
 	.mapbase	= 0xffe00000,
 	.flags		= UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+	.scbrr_algo_id	= SCBRR_ALGO_2,
 	.type		= PORT_SCIF,
 	.irqs		= { 40, 40, 40, 40 },
 };
@@ -34,6 +36,8 @@ static struct platform_device scif0_devi
 static struct plat_sci_port scif1_platform_data = {
 	.mapbase	= 0xffe08000,
 	.flags		= UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+	.scbrr_algo_id	= SCBRR_ALGO_2,
 	.type		= PORT_SCIF,
 	.irqs		= { 76, 76, 76, 76 },
 };
@@ -49,6 +53,8 @@ static struct platform_device scif1_devi
 static struct plat_sci_port scif2_platform_data = {
 	.mapbase	= 0xffe10000,
 	.flags		= UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+	.scbrr_algo_id	= SCBRR_ALGO_2,
 	.type		= PORT_SCIF,
 	.irqs		= { 104, 104, 104, 104 },
 };
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/kernel/cpu/sh4a/setup-sh7770.c linux-libre-2.6.38-gnu1/arch/sh/kernel/cpu/sh4a/setup-sh7770.c
--- linux-libre-2.6.37-gnu1/arch/sh/kernel/cpu/sh4a/setup-sh7770.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/kernel/cpu/sh4a/setup-sh7770.c	2011-03-14 21:20:32.000000000 -0400
@@ -17,6 +17,8 @@
 static struct plat_sci_port scif0_platform_data = {
 	.mapbase	= 0xff923000,
 	.flags		= UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE | SCSCR_TOIE,
+	.scbrr_algo_id	= SCBRR_ALGO_2,
 	.type		= PORT_SCIF,
 	.irqs		= { 61, 61, 61, 61 },
 };
@@ -32,6 +34,8 @@ static struct platform_device scif0_devi
 static struct plat_sci_port scif1_platform_data = {
 	.mapbase	= 0xff924000,
 	.flags		= UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE | SCSCR_TOIE,
+	.scbrr_algo_id	= SCBRR_ALGO_2,
 	.type		= PORT_SCIF,
 	.irqs		= { 62, 62, 62, 62 },
 };
@@ -47,6 +51,8 @@ static struct platform_device scif1_devi
 static struct plat_sci_port scif2_platform_data = {
 	.mapbase	= 0xff925000,
 	.flags		= UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE | SCSCR_TOIE,
+	.scbrr_algo_id	= SCBRR_ALGO_2,
 	.type		= PORT_SCIF,
 	.irqs		= { 63, 63, 63, 63 },
 };
@@ -62,6 +68,8 @@ static struct platform_device scif2_devi
 static struct plat_sci_port scif3_platform_data = {
 	.mapbase	= 0xff926000,
 	.flags		= UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE | SCSCR_TOIE,
+	.scbrr_algo_id	= SCBRR_ALGO_2,
 	.type		= PORT_SCIF,
 	.irqs		= { 64, 64, 64, 64 },
 };
@@ -77,6 +85,8 @@ static struct platform_device scif3_devi
 static struct plat_sci_port scif4_platform_data = {
 	.mapbase	= 0xff927000,
 	.flags		= UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE | SCSCR_TOIE,
+	.scbrr_algo_id	= SCBRR_ALGO_2,
 	.type		= PORT_SCIF,
 	.irqs		= { 65, 65, 65, 65 },
 };
@@ -92,6 +102,8 @@ static struct platform_device scif4_devi
 static struct plat_sci_port scif5_platform_data = {
 	.mapbase	= 0xff928000,
 	.flags		= UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE | SCSCR_TOIE,
+	.scbrr_algo_id	= SCBRR_ALGO_2,
 	.type		= PORT_SCIF,
 	.irqs		= { 66, 66, 66, 66 },
 };
@@ -107,6 +119,8 @@ static struct platform_device scif5_devi
 static struct plat_sci_port scif6_platform_data = {
 	.mapbase	= 0xff929000,
 	.flags		= UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE | SCSCR_TOIE,
+	.scbrr_algo_id	= SCBRR_ALGO_2,
 	.type		= PORT_SCIF,
 	.irqs		= { 67, 67, 67, 67 },
 };
@@ -122,6 +136,8 @@ static struct platform_device scif6_devi
 static struct plat_sci_port scif7_platform_data = {
 	.mapbase	= 0xff92a000,
 	.flags		= UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE | SCSCR_TOIE,
+	.scbrr_algo_id	= SCBRR_ALGO_2,
 	.type		= PORT_SCIF,
 	.irqs		= { 68, 68, 68, 68 },
 };
@@ -137,6 +153,8 @@ static struct platform_device scif7_devi
 static struct plat_sci_port scif8_platform_data = {
 	.mapbase	= 0xff92b000,
 	.flags		= UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE | SCSCR_TOIE,
+	.scbrr_algo_id	= SCBRR_ALGO_2,
 	.type		= PORT_SCIF,
 	.irqs		= { 69, 69, 69, 69 },
 };
@@ -152,6 +170,8 @@ static struct platform_device scif8_devi
 static struct plat_sci_port scif9_platform_data = {
 	.mapbase	= 0xff92c000,
 	.flags		= UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE | SCSCR_TOIE,
+	.scbrr_algo_id	= SCBRR_ALGO_2,
 	.type		= PORT_SCIF,
 	.irqs		= { 70, 70, 70, 70 },
 };
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/kernel/cpu/sh4a/setup-sh7780.c linux-libre-2.6.38-gnu1/arch/sh/kernel/cpu/sh4a/setup-sh7780.c
--- linux-libre-2.6.37-gnu1/arch/sh/kernel/cpu/sh4a/setup-sh7780.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/kernel/cpu/sh4a/setup-sh7780.c	2011-03-14 21:20:32.000000000 -0400
@@ -20,6 +20,8 @@
 static struct plat_sci_port scif0_platform_data = {
 	.mapbase	= 0xffe00000,
 	.flags		= UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE | SCSCR_CKE1,
+	.scbrr_algo_id	= SCBRR_ALGO_1,
 	.type		= PORT_SCIF,
 	.irqs		= { 40, 40, 40, 40 },
 };
@@ -35,6 +37,8 @@ static struct platform_device scif0_devi
 static struct plat_sci_port scif1_platform_data = {
 	.mapbase	= 0xffe10000,
 	.flags		= UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE | SCSCR_CKE1,
+	.scbrr_algo_id	= SCBRR_ALGO_1,
 	.type		= PORT_SCIF,
 	.irqs		= { 76, 76, 76, 76 },
 };
@@ -379,6 +383,7 @@ static int __init sh7780_devices_setup(v
 				    ARRAY_SIZE(sh7780_devices));
 }
 arch_initcall(sh7780_devices_setup);
+
 static struct platform_device *sh7780_early_devices[] __initdata = {
 	&scif0_device,
 	&scif1_device,
@@ -392,6 +397,13 @@ static struct platform_device *sh7780_ea
 
 void __init plat_early_device_setup(void)
 {
+	if (mach_is_sh2007()) {
+		scif0_platform_data.scscr &= ~SCSCR_CKE1;
+		scif0_platform_data.scbrr_algo_id = SCBRR_ALGO_2;
+		scif1_platform_data.scscr &= ~SCSCR_CKE1;
+		scif1_platform_data.scbrr_algo_id = SCBRR_ALGO_2;
+	}
+
 	early_platform_add_devices(sh7780_early_devices,
 				   ARRAY_SIZE(sh7780_early_devices));
 }
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/kernel/cpu/sh4a/setup-sh7785.c linux-libre-2.6.38-gnu1/arch/sh/kernel/cpu/sh4a/setup-sh7785.c
--- linux-libre-2.6.37-gnu1/arch/sh/kernel/cpu/sh4a/setup-sh7785.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/kernel/cpu/sh4a/setup-sh7785.c	2011-03-14 21:20:32.000000000 -0400
@@ -23,6 +23,8 @@
 static struct plat_sci_port scif0_platform_data = {
 	.mapbase	= 0xffea0000,
 	.flags		= UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE | SCSCR_CKE1,
+	.scbrr_algo_id	= SCBRR_ALGO_1,
 	.type		= PORT_SCIF,
 	.irqs		= { 40, 40, 40, 40 },
 };
@@ -38,6 +40,8 @@ static struct platform_device scif0_devi
 static struct plat_sci_port scif1_platform_data = {
 	.mapbase	= 0xffeb0000,
 	.flags		= UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE | SCSCR_CKE1,
+	.scbrr_algo_id	= SCBRR_ALGO_1,
 	.type		= PORT_SCIF,
 	.irqs		= { 44, 44, 44, 44 },
 };
@@ -53,6 +57,8 @@ static struct platform_device scif1_devi
 static struct plat_sci_port scif2_platform_data = {
 	.mapbase	= 0xffec0000,
 	.flags		= UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE | SCSCR_CKE1,
+	.scbrr_algo_id	= SCBRR_ALGO_1,
 	.type		= PORT_SCIF,
 	.irqs		= { 60, 60, 60, 60 },
 };
@@ -68,6 +74,8 @@ static struct platform_device scif2_devi
 static struct plat_sci_port scif3_platform_data = {
 	.mapbase	= 0xffed0000,
 	.flags		= UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE | SCSCR_CKE1,
+	.scbrr_algo_id	= SCBRR_ALGO_1,
 	.type		= PORT_SCIF,
 	.irqs		= { 61, 61, 61, 61 },
 };
@@ -83,6 +91,8 @@ static struct platform_device scif3_devi
 static struct plat_sci_port scif4_platform_data = {
 	.mapbase	= 0xffee0000,
 	.flags		= UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE | SCSCR_CKE1,
+	.scbrr_algo_id	= SCBRR_ALGO_1,
 	.type		= PORT_SCIF,
 	.irqs		= { 62, 62, 62, 62 },
 };
@@ -98,6 +108,8 @@ static struct platform_device scif4_devi
 static struct plat_sci_port scif5_platform_data = {
 	.mapbase	= 0xffef0000,
 	.flags		= UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE | SCSCR_CKE1,
+	.scbrr_algo_id	= SCBRR_ALGO_1,
 	.type		= PORT_SCIF,
 	.irqs		= { 63, 63, 63, 63 },
 };
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/kernel/cpu/sh4a/setup-sh7786.c linux-libre-2.6.38-gnu1/arch/sh/kernel/cpu/sh4a/setup-sh7786.c
--- linux-libre-2.6.37-gnu1/arch/sh/kernel/cpu/sh4a/setup-sh7786.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/kernel/cpu/sh4a/setup-sh7786.c	2011-03-14 21:20:32.000000000 -0400
@@ -29,6 +29,8 @@
 static struct plat_sci_port scif0_platform_data = {
 	.mapbase	= 0xffea0000,
 	.flags		= UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE | SCSCR_CKE1,
+	.scbrr_algo_id	= SCBRR_ALGO_1,
 	.type		= PORT_SCIF,
 	.irqs		= { 40, 41, 43, 42 },
 };
@@ -47,6 +49,8 @@ static struct platform_device scif0_devi
 static struct plat_sci_port scif1_platform_data = {
 	.mapbase	= 0xffeb0000,
 	.flags		= UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE | SCSCR_CKE1,
+	.scbrr_algo_id	= SCBRR_ALGO_1,
 	.type		= PORT_SCIF,
 	.irqs		= { 44, 44, 44, 44 },
 };
@@ -62,6 +66,8 @@ static struct platform_device scif1_devi
 static struct plat_sci_port scif2_platform_data = {
 	.mapbase	= 0xffec0000,
 	.flags		= UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE | SCSCR_CKE1,
+	.scbrr_algo_id	= SCBRR_ALGO_1,
 	.type		= PORT_SCIF,
 	.irqs		= { 50, 50, 50, 50 },
 };
@@ -77,6 +83,8 @@ static struct platform_device scif2_devi
 static struct plat_sci_port scif3_platform_data = {
 	.mapbase	= 0xffed0000,
 	.flags		= UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE | SCSCR_CKE1,
+	.scbrr_algo_id	= SCBRR_ALGO_1,
 	.type		= PORT_SCIF,
 	.irqs		= { 51, 51, 51, 51 },
 };
@@ -92,6 +100,8 @@ static struct platform_device scif3_devi
 static struct plat_sci_port scif4_platform_data = {
 	.mapbase	= 0xffee0000,
 	.flags		= UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE | SCSCR_CKE1,
+	.scbrr_algo_id	= SCBRR_ALGO_1,
 	.type		= PORT_SCIF,
 	.irqs		= { 52, 52, 52, 52 },
 };
@@ -107,6 +117,8 @@ static struct platform_device scif4_devi
 static struct plat_sci_port scif5_platform_data = {
 	.mapbase	= 0xffef0000,
 	.flags		= UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE | SCSCR_CKE1,
+	.scbrr_algo_id	= SCBRR_ALGO_1,
 	.type		= PORT_SCIF,
 	.irqs		= { 53, 53, 53, 53 },
 };
@@ -522,10 +534,37 @@ static struct platform_device dma0_devic
 	},
 };
 
+#define USB_EHCI_START 0xffe70000
+#define USB_OHCI_START 0xffe70400
+
+static struct resource usb_ehci_resources[] = {
+	[0] = {
+		.start	= USB_EHCI_START,
+		.end	= USB_EHCI_START + 0x3ff,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 77,
+		.end	= 77,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device usb_ehci_device = {
+	.name		= "sh_ehci",
+	.id		= -1,
+	.dev = {
+		.dma_mask		= &usb_ehci_device.dev.coherent_dma_mask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	},
+	.num_resources	= ARRAY_SIZE(usb_ehci_resources),
+	.resource	= usb_ehci_resources,
+};
+
 static struct resource usb_ohci_resources[] = {
 	[0] = {
-		.start	= 0xffe70400,
-		.end	= 0xffe704ff,
+		.start	= USB_OHCI_START,
+		.end	= USB_OHCI_START + 0x3ff,
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
@@ -535,12 +574,11 @@ static struct resource usb_ohci_resource
 	},
 };
 
-static u64 usb_ohci_dma_mask = DMA_BIT_MASK(32);
 static struct platform_device usb_ohci_device = {
 	.name		= "sh_ohci",
 	.id		= -1,
 	.dev = {
-		.dma_mask		= &usb_ohci_dma_mask,
+		.dma_mask		= &usb_ohci_device.dev.coherent_dma_mask,
 		.coherent_dma_mask	= DMA_BIT_MASK(32),
 	},
 	.num_resources	= ARRAY_SIZE(usb_ohci_resources),
@@ -570,6 +608,7 @@ static struct platform_device *sh7786_ea
 
 static struct platform_device *sh7786_devices[] __initdata = {
 	&dma0_device,
+	&usb_ehci_device,
 	&usb_ohci_device,
 };
 
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/kernel/cpu/sh4a/setup-shx3.c linux-libre-2.6.38-gnu1/arch/sh/kernel/cpu/sh4a/setup-shx3.c
--- linux-libre-2.6.37-gnu1/arch/sh/kernel/cpu/sh4a/setup-shx3.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/kernel/cpu/sh4a/setup-shx3.c	2011-03-14 21:20:32.000000000 -0400
@@ -29,6 +29,8 @@
 static struct plat_sci_port scif0_platform_data = {
 	.mapbase	= 0xffc30000,
 	.flags		= UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+	.scbrr_algo_id	= SCBRR_ALGO_2,
 	.type		= PORT_SCIF,
 	.irqs		= { 40, 41, 43, 42 },
 };
@@ -44,6 +46,8 @@ static struct platform_device scif0_devi
 static struct plat_sci_port scif1_platform_data = {
 	.mapbase	= 0xffc40000,
 	.flags		= UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+	.scbrr_algo_id	= SCBRR_ALGO_2,
 	.type		= PORT_SCIF,
 	.irqs		= { 44, 45, 47, 46 },
 };
@@ -59,6 +63,8 @@ static struct platform_device scif1_devi
 static struct plat_sci_port scif2_platform_data = {
 	.mapbase	= 0xffc60000,
 	.flags		= UPF_BOOT_AUTOCONF,
+	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+	.scbrr_algo_id	= SCBRR_ALGO_2,
 	.type		= PORT_SCIF,
 	.irqs		= { 52, 53, 55, 54 },
 };
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/kernel/cpu/sh5/setup-sh5.c linux-libre-2.6.38-gnu1/arch/sh/kernel/cpu/sh5/setup-sh5.c
--- linux-libre-2.6.37-gnu1/arch/sh/kernel/cpu/sh5/setup-sh5.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/kernel/cpu/sh5/setup-sh5.c	2011-03-14 21:20:32.000000000 -0400
@@ -19,6 +19,8 @@
 static struct plat_sci_port scif0_platform_data = {
 	.mapbase	= PHYS_PERIPHERAL_BLOCK + 0x01030000,
 	.flags		= UPF_BOOT_AUTOCONF | UPF_IOREMAP,
+	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+	.scbrr_algo_id	= SCBRR_ALGO_2,
 	.type		= PORT_SCIF,
 	.irqs		= { 39, 40, 42, 0 },
 };
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/kernel/cpu/shmobile/cpuidle.c linux-libre-2.6.38-gnu1/arch/sh/kernel/cpu/shmobile/cpuidle.c
--- linux-libre-2.6.37-gnu1/arch/sh/kernel/cpu/shmobile/cpuidle.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/kernel/cpu/shmobile/cpuidle.c	2011-03-14 21:20:32.000000000 -0400
@@ -81,7 +81,6 @@ void sh_mobile_setup_cpuidle(void)
 	state->target_residency = 1 * 2;
 	state->power_usage = 3;
 	state->flags = 0;
-	state->flags |= CPUIDLE_FLAG_SHALLOW;
 	state->flags |= CPUIDLE_FLAG_TIME_VALID;
 	state->enter = cpuidle_sleep_enter;
 
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/kernel/cpu/shmobile/pm.c linux-libre-2.6.38-gnu1/arch/sh/kernel/cpu/shmobile/pm.c
--- linux-libre-2.6.37-gnu1/arch/sh/kernel/cpu/shmobile/pm.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/kernel/cpu/shmobile/pm.c	2011-03-14 21:20:32.000000000 -0400
@@ -141,7 +141,7 @@ static int sh_pm_enter(suspend_state_t s
 	return 0;
 }
 
-static struct platform_suspend_ops sh_pm_ops = {
+static const struct platform_suspend_ops sh_pm_ops = {
 	.enter          = sh_pm_enter,
 	.valid          = suspend_valid_only_mem,
 };
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/kernel/io_generic.c linux-libre-2.6.38-gnu1/arch/sh/kernel/io_generic.c
--- linux-libre-2.6.37-gnu1/arch/sh/kernel/io_generic.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/kernel/io_generic.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,180 +0,0 @@
-/*
- * arch/sh/kernel/io_generic.c
- *
- * Copyright (C) 2000  Niibe Yutaka
- * Copyright (C) 2005 - 2007 Paul Mundt
- *
- * Generic I/O routine. These can be used where a machine specific version
- * is not required.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- */
-#include <linux/module.h>
-#include <linux/io.h>
-#include <asm/machvec.h>
-
-#ifdef CONFIG_CPU_SH3
-/* SH3 has a PCMCIA bug that needs a dummy read from area 6 for a
- * workaround. */
-/* I'm not sure SH7709 has this kind of bug */
-#define dummy_read()	__raw_readb(0xba000000)
-#else
-#define dummy_read()
-#endif
-
-unsigned long generic_io_base = 0;
-
-u8 generic_inb(unsigned long port)
-{
-	return __raw_readb(__ioport_map(port, 1));
-}
-
-u16 generic_inw(unsigned long port)
-{
-	return __raw_readw(__ioport_map(port, 2));
-}
-
-u32 generic_inl(unsigned long port)
-{
-	return __raw_readl(__ioport_map(port, 4));
-}
-
-u8 generic_inb_p(unsigned long port)
-{
-	unsigned long v = generic_inb(port);
-
-	ctrl_delay();
-	return v;
-}
-
-u16 generic_inw_p(unsigned long port)
-{
-	unsigned long v = generic_inw(port);
-
-	ctrl_delay();
-	return v;
-}
-
-u32 generic_inl_p(unsigned long port)
-{
-	unsigned long v = generic_inl(port);
-
-	ctrl_delay();
-	return v;
-}
-
-/*
- * insb/w/l all read a series of bytes/words/longs from a fixed port
- * address. However as the port address doesn't change we only need to
- * convert the port address to real address once.
- */
-
-void generic_insb(unsigned long port, void *dst, unsigned long count)
-{
-	__raw_readsb(__ioport_map(port, 1), dst, count);
-	dummy_read();
-}
-
-void generic_insw(unsigned long port, void *dst, unsigned long count)
-{
-	__raw_readsw(__ioport_map(port, 2), dst, count);
-	dummy_read();
-}
-
-void generic_insl(unsigned long port, void *dst, unsigned long count)
-{
-	__raw_readsl(__ioport_map(port, 4), dst, count);
-	dummy_read();
-}
-
-void generic_outb(u8 b, unsigned long port)
-{
-	__raw_writeb(b, __ioport_map(port, 1));
-}
-
-void generic_outw(u16 b, unsigned long port)
-{
-	__raw_writew(b, __ioport_map(port, 2));
-}
-
-void generic_outl(u32 b, unsigned long port)
-{
-	__raw_writel(b, __ioport_map(port, 4));
-}
-
-void generic_outb_p(u8 b, unsigned long port)
-{
-	generic_outb(b, port);
-	ctrl_delay();
-}
-
-void generic_outw_p(u16 b, unsigned long port)
-{
-	generic_outw(b, port);
-	ctrl_delay();
-}
-
-void generic_outl_p(u32 b, unsigned long port)
-{
-	generic_outl(b, port);
-	ctrl_delay();
-}
-
-/*
- * outsb/w/l all write a series of bytes/words/longs to a fixed port
- * address. However as the port address doesn't change we only need to
- * convert the port address to real address once.
- */
-void generic_outsb(unsigned long port, const void *src, unsigned long count)
-{
-	__raw_writesb(__ioport_map(port, 1), src, count);
-	dummy_read();
-}
-
-void generic_outsw(unsigned long port, const void *src, unsigned long count)
-{
-	__raw_writesw(__ioport_map(port, 2), src, count);
-	dummy_read();
-}
-
-void generic_outsl(unsigned long port, const void *src, unsigned long count)
-{
-	__raw_writesl(__ioport_map(port, 4), src, count);
-	dummy_read();
-}
-
-void __iomem *generic_ioport_map(unsigned long addr, unsigned int size)
-{
-#ifdef P1SEG
-	if (PXSEG(addr) >= P1SEG)
-		return (void __iomem *)addr;
-#endif
-
-	return (void __iomem *)(addr + generic_io_base);
-}
-
-void generic_ioport_unmap(void __iomem *addr)
-{
-}
-
-#ifndef CONFIG_GENERIC_IOMAP
-void __iomem *ioport_map(unsigned long port, unsigned int nr)
-{
-	void __iomem *ret;
-
-	ret = __ioport_map_trapped(port, nr);
-	if (ret)
-		return ret;
-
-	return __ioport_map(port, nr);
-}
-EXPORT_SYMBOL(ioport_map);
-
-void ioport_unmap(void __iomem *addr)
-{
-	sh_mv.mv_ioport_unmap(addr);
-}
-EXPORT_SYMBOL(ioport_unmap);
-#endif /* CONFIG_GENERIC_IOMAP */
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/kernel/iomap.c linux-libre-2.6.38-gnu1/arch/sh/kernel/iomap.c
--- linux-libre-2.6.37-gnu1/arch/sh/kernel/iomap.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/kernel/iomap.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,165 @@
+/*
+ * arch/sh/kernel/iomap.c
+ *
+ * Copyright (C) 2000  Niibe Yutaka
+ * Copyright (C) 2005 - 2007 Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/module.h>
+#include <linux/io.h>
+
+unsigned int ioread8(void __iomem *addr)
+{
+	return readb(addr);
+}
+EXPORT_SYMBOL(ioread8);
+
+unsigned int ioread16(void __iomem *addr)
+{
+	return readw(addr);
+}
+EXPORT_SYMBOL(ioread16);
+
+unsigned int ioread16be(void __iomem *addr)
+{
+	return be16_to_cpu(__raw_readw(addr));
+}
+EXPORT_SYMBOL(ioread16be);
+
+unsigned int ioread32(void __iomem *addr)
+{
+	return readl(addr);
+}
+EXPORT_SYMBOL(ioread32);
+
+unsigned int ioread32be(void __iomem *addr)
+{
+	return be32_to_cpu(__raw_readl(addr));
+}
+EXPORT_SYMBOL(ioread32be);
+
+void iowrite8(u8 val, void __iomem *addr)
+{
+	writeb(val, addr);
+}
+EXPORT_SYMBOL(iowrite8);
+
+void iowrite16(u16 val, void __iomem *addr)
+{
+	writew(val, addr);
+}
+EXPORT_SYMBOL(iowrite16);
+
+void iowrite16be(u16 val, void __iomem *addr)
+{
+	__raw_writew(cpu_to_be16(val), addr);
+}
+EXPORT_SYMBOL(iowrite16be);
+
+void iowrite32(u32 val, void __iomem *addr)
+{
+	writel(val, addr);
+}
+EXPORT_SYMBOL(iowrite32);
+
+void iowrite32be(u32 val, void __iomem *addr)
+{
+	__raw_writel(cpu_to_be32(val), addr);
+}
+EXPORT_SYMBOL(iowrite32be);
+
+/*
+ * These are the "repeat MMIO read/write" functions.
+ * Note the "__raw" accesses, since we don't want to
+ * convert to CPU byte order. We write in "IO byte
+ * order" (we also don't have IO barriers).
+ */
+static inline void mmio_insb(void __iomem *addr, u8 *dst, int count)
+{
+	while (--count >= 0) {
+		u8 data = __raw_readb(addr);
+		*dst = data;
+		dst++;
+	}
+}
+
+static inline void mmio_insw(void __iomem *addr, u16 *dst, int count)
+{
+	while (--count >= 0) {
+		u16 data = __raw_readw(addr);
+		*dst = data;
+		dst++;
+	}
+}
+
+static inline void mmio_insl(void __iomem *addr, u32 *dst, int count)
+{
+	while (--count >= 0) {
+		u32 data = __raw_readl(addr);
+		*dst = data;
+		dst++;
+	}
+}
+
+static inline void mmio_outsb(void __iomem *addr, const u8 *src, int count)
+{
+	while (--count >= 0) {
+		__raw_writeb(*src, addr);
+		src++;
+	}
+}
+
+static inline void mmio_outsw(void __iomem *addr, const u16 *src, int count)
+{
+	while (--count >= 0) {
+		__raw_writew(*src, addr);
+		src++;
+	}
+}
+
+static inline void mmio_outsl(void __iomem *addr, const u32 *src, int count)
+{
+	while (--count >= 0) {
+		__raw_writel(*src, addr);
+		src++;
+	}
+}
+
+void ioread8_rep(void __iomem *addr, void *dst, unsigned long count)
+{
+	mmio_insb(addr, dst, count);
+}
+EXPORT_SYMBOL(ioread8_rep);
+
+void ioread16_rep(void __iomem *addr, void *dst, unsigned long count)
+{
+	mmio_insw(addr, dst, count);
+}
+EXPORT_SYMBOL(ioread16_rep);
+
+void ioread32_rep(void __iomem *addr, void *dst, unsigned long count)
+{
+	mmio_insl(addr, dst, count);
+}
+EXPORT_SYMBOL(ioread32_rep);
+
+void iowrite8_rep(void __iomem *addr, const void *src, unsigned long count)
+{
+	mmio_outsb(addr, src, count);
+}
+EXPORT_SYMBOL(iowrite8_rep);
+
+void iowrite16_rep(void __iomem *addr, const void *src, unsigned long count)
+{
+	mmio_outsw(addr, src, count);
+}
+EXPORT_SYMBOL(iowrite16_rep);
+
+void iowrite32_rep(void __iomem *addr, const void *src, unsigned long count)
+{
+	mmio_outsl(addr, src, count);
+}
+EXPORT_SYMBOL(iowrite32_rep);
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/kernel/ioport.c linux-libre-2.6.38-gnu1/arch/sh/kernel/ioport.c
--- linux-libre-2.6.37-gnu1/arch/sh/kernel/ioport.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/kernel/ioport.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,43 @@
+/*
+ * arch/sh/kernel/ioport.c
+ *
+ * Copyright (C) 2000  Niibe Yutaka
+ * Copyright (C) 2005 - 2007 Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/module.h>
+#include <linux/io.h>
+
+const unsigned long sh_io_port_base __read_mostly = -1;
+EXPORT_SYMBOL(sh_io_port_base);
+
+void __iomem *__ioport_map(unsigned long addr, unsigned int size)
+{
+	if (sh_mv.mv_ioport_map)
+		return sh_mv.mv_ioport_map(addr, size);
+
+	return (void __iomem *)(addr + sh_io_port_base);
+}
+EXPORT_SYMBOL(__ioport_map);
+
+void __iomem *ioport_map(unsigned long port, unsigned int nr)
+{
+	void __iomem *ret;
+
+	ret = __ioport_map_trapped(port, nr);
+	if (ret)
+		return ret;
+
+	return __ioport_map(port, nr);
+}
+EXPORT_SYMBOL(ioport_map);
+
+void ioport_unmap(void __iomem *addr)
+{
+	if (sh_mv.mv_ioport_unmap)
+		sh_mv.mv_ioport_unmap(addr);
+}
+EXPORT_SYMBOL(ioport_unmap);
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/kernel/machvec.c linux-libre-2.6.38-gnu1/arch/sh/kernel/machvec.c
--- linux-libre-2.6.37-gnu1/arch/sh/kernel/machvec.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/kernel/machvec.c	2011-03-14 21:20:32.000000000 -0400
@@ -118,28 +118,6 @@ void __init sh_mv_setup(void)
 		sh_mv.mv_##elem = generic_##elem; \
 } while (0)
 
-#ifdef CONFIG_HAS_IOPORT
-
-#ifdef P2SEG
-	__set_io_port_base(P2SEG);
-#else
-	__set_io_port_base(0);
-#endif
-
-	mv_set(inb);	mv_set(inw);	mv_set(inl);
-	mv_set(outb);	mv_set(outw);	mv_set(outl);
-
-	mv_set(inb_p);	mv_set(inw_p);	mv_set(inl_p);
-	mv_set(outb_p);	mv_set(outw_p);	mv_set(outl_p);
-
-	mv_set(insb);	mv_set(insw);	mv_set(insl);
-	mv_set(outsb);	mv_set(outsw);	mv_set(outsl);
-
-	mv_set(ioport_map);
-	mv_set(ioport_unmap);
-
-#endif
-
 	mv_set(irq_demux);
 	mv_set(mode_pins);
 	mv_set(mem_init);
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/kernel/Makefile linux-libre-2.6.38-gnu1/arch/sh/kernel/Makefile
--- linux-libre-2.6.37-gnu1/arch/sh/kernel/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/kernel/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -11,7 +11,7 @@ endif
 
 CFLAGS_REMOVE_return_address.o = -pg
 
-obj-y	:= clkdev.o debugtraps.o dma-nommu.o dumpstack.o 		\
+obj-y	:= debugtraps.o dma-nommu.o dumpstack.o 		\
 	   idle.o io.o irq.o irq_$(BITS).o kdebugfs.o			\
 	   machvec.o nmi_debug.o process.o				\
 	   process_$(BITS).o ptrace.o ptrace_$(BITS).o			\
@@ -20,6 +20,11 @@ obj-y	:= clkdev.o debugtraps.o dma-nommu
 	   syscalls_$(BITS).o time.o topology.o traps.o			\
 	   traps_$(BITS).o unwinder.o
 
+ifndef CONFIG_GENERIC_IOMAP
+obj-y				+= iomap.o
+obj-$(CONFIG_HAS_IOPORT)	+= ioport.o
+endif
+
 obj-y				+= cpu/
 obj-$(CONFIG_VSYSCALL)		+= vsyscall/
 obj-$(CONFIG_SMP)		+= smp.o
@@ -39,7 +44,6 @@ obj-$(CONFIG_DUMP_CODE)		+= disassemble.
 obj-$(CONFIG_HIBERNATION)	+= swsusp.o
 obj-$(CONFIG_DWARF_UNWINDER)	+= dwarf.o
 obj-$(CONFIG_PERF_EVENTS)	+= perf_event.o perf_callchain.o
-obj-$(CONFIG_HAS_IOPORT)	+= io_generic.o
 
 obj-$(CONFIG_HAVE_HW_BREAKPOINT)		+= hw_breakpoint.o
 obj-$(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST)	+= localtimer.o
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/kernel/perf_event.c linux-libre-2.6.38-gnu1/arch/sh/kernel/perf_event.c
--- linux-libre-2.6.37-gnu1/arch/sh/kernel/perf_event.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/kernel/perf_event.c	2011-03-14 21:20:32.000000000 -0400
@@ -389,7 +389,7 @@ int __cpuinit register_sh_pmu(struct sh_
 
 	WARN_ON(_pmu->num_events > MAX_HWEVENTS);
 
-	perf_pmu_register(&pmu);
+	perf_pmu_register(&pmu, "cpu", PERF_TYPE_RAW);
 	perf_cpu_notifier(sh_pmu_notifier);
 	return 0;
 }
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/kernel/setup.c linux-libre-2.6.38-gnu1/arch/sh/kernel/setup.c
--- linux-libre-2.6.37-gnu1/arch/sh/kernel/setup.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/kernel/setup.c	2011-03-14 21:20:32.000000000 -0400
@@ -12,7 +12,6 @@
 #include <linux/initrd.h>
 #include <linux/bootmem.h>
 #include <linux/console.h>
-#include <linux/seq_file.h>
 #include <linux/root_dev.h>
 #include <linux/utsname.h>
 #include <linux/nodemask.h>
@@ -319,146 +318,3 @@ int test_mode_pin(int pin)
 {
 	return sh_mv.mv_mode_pins() & pin;
 }
-
-static const char *cpu_name[] = {
-	[CPU_SH7201]	= "SH7201",
-	[CPU_SH7203]	= "SH7203",	[CPU_SH7263]	= "SH7263",
-	[CPU_SH7206]	= "SH7206",	[CPU_SH7619]	= "SH7619",
-	[CPU_SH7705]	= "SH7705",	[CPU_SH7706]	= "SH7706",
-	[CPU_SH7707]	= "SH7707",	[CPU_SH7708]	= "SH7708",
-	[CPU_SH7709]	= "SH7709",	[CPU_SH7710]	= "SH7710",
-	[CPU_SH7712]	= "SH7712",	[CPU_SH7720]	= "SH7720",
-	[CPU_SH7721]	= "SH7721",	[CPU_SH7729]	= "SH7729",
-	[CPU_SH7750]	= "SH7750",	[CPU_SH7750S]	= "SH7750S",
-	[CPU_SH7750R]	= "SH7750R",	[CPU_SH7751]	= "SH7751",
-	[CPU_SH7751R]	= "SH7751R",	[CPU_SH7760]	= "SH7760",
-	[CPU_SH4_202]	= "SH4-202",	[CPU_SH4_501]	= "SH4-501",
-	[CPU_SH7763]	= "SH7763",	[CPU_SH7770]	= "SH7770",
-	[CPU_SH7780]	= "SH7780",	[CPU_SH7781]	= "SH7781",
-	[CPU_SH7343]	= "SH7343",	[CPU_SH7785]	= "SH7785",
-	[CPU_SH7786]	= "SH7786",	[CPU_SH7757]	= "SH7757",
-	[CPU_SH7722]	= "SH7722",	[CPU_SHX3]	= "SH-X3",
-	[CPU_SH5_101]	= "SH5-101",	[CPU_SH5_103]	= "SH5-103",
-	[CPU_MXG]	= "MX-G",	[CPU_SH7723]	= "SH7723",
-	[CPU_SH7366]	= "SH7366",	[CPU_SH7724]	= "SH7724",
-	[CPU_SH_NONE]	= "Unknown"
-};
-
-const char *get_cpu_subtype(struct sh_cpuinfo *c)
-{
-	return cpu_name[c->type];
-}
-EXPORT_SYMBOL(get_cpu_subtype);
-
-#ifdef CONFIG_PROC_FS
-/* Symbolic CPU flags, keep in sync with asm/cpu-features.h */
-static const char *cpu_flags[] = {
-	"none", "fpu", "p2flush", "mmuassoc", "dsp", "perfctr",
-	"ptea", "llsc", "l2", "op32", "pteaex", NULL
-};
-
-static void show_cpuflags(struct seq_file *m, struct sh_cpuinfo *c)
-{
-	unsigned long i;
-
-	seq_printf(m, "cpu flags\t:");
-
-	if (!c->flags) {
-		seq_printf(m, " %s\n", cpu_flags[0]);
-		return;
-	}
-
-	for (i = 0; cpu_flags[i]; i++)
-		if ((c->flags & (1 << i)))
-			seq_printf(m, " %s", cpu_flags[i+1]);
-
-	seq_printf(m, "\n");
-}
-
-static void show_cacheinfo(struct seq_file *m, const char *type,
-			   struct cache_info info)
-{
-	unsigned int cache_size;
-
-	cache_size = info.ways * info.sets * info.linesz;
-
-	seq_printf(m, "%s size\t: %2dKiB (%d-way)\n",
-		   type, cache_size >> 10, info.ways);
-}
-
-/*
- *	Get CPU information for use by the procfs.
- */
-static int show_cpuinfo(struct seq_file *m, void *v)
-{
-	struct sh_cpuinfo *c = v;
-	unsigned int cpu = c - cpu_data;
-
-	if (!cpu_online(cpu))
-		return 0;
-
-	if (cpu == 0)
-		seq_printf(m, "machine\t\t: %s\n", get_system_type());
-	else
-		seq_printf(m, "\n");
-
-	seq_printf(m, "processor\t: %d\n", cpu);
-	seq_printf(m, "cpu family\t: %s\n", init_utsname()->machine);
-	seq_printf(m, "cpu type\t: %s\n", get_cpu_subtype(c));
-	if (c->cut_major == -1)
-		seq_printf(m, "cut\t\t: unknown\n");
-	else if (c->cut_minor == -1)
-		seq_printf(m, "cut\t\t: %d.x\n", c->cut_major);
-	else
-		seq_printf(m, "cut\t\t: %d.%d\n", c->cut_major, c->cut_minor);
-
-	show_cpuflags(m, c);
-
-	seq_printf(m, "cache type\t: ");
-
-	/*
-	 * Check for what type of cache we have, we support both the
-	 * unified cache on the SH-2 and SH-3, as well as the harvard
-	 * style cache on the SH-4.
-	 */
-	if (c->icache.flags & SH_CACHE_COMBINED) {
-		seq_printf(m, "unified\n");
-		show_cacheinfo(m, "cache", c->icache);
-	} else {
-		seq_printf(m, "split (harvard)\n");
-		show_cacheinfo(m, "icache", c->icache);
-		show_cacheinfo(m, "dcache", c->dcache);
-	}
-
-	/* Optional secondary cache */
-	if (c->flags & CPU_HAS_L2_CACHE)
-		show_cacheinfo(m, "scache", c->scache);
-
-	seq_printf(m, "address sizes\t: %u bits physical\n", c->phys_bits);
-
-	seq_printf(m, "bogomips\t: %lu.%02lu\n",
-		     c->loops_per_jiffy/(500000/HZ),
-		     (c->loops_per_jiffy/(5000/HZ)) % 100);
-
-	return 0;
-}
-
-static void *c_start(struct seq_file *m, loff_t *pos)
-{
-	return *pos < NR_CPUS ? cpu_data + *pos : 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)
-{
-}
-const struct seq_operations cpuinfo_op = {
-	.start	= c_start,
-	.next	= c_next,
-	.stop	= c_stop,
-	.show	= show_cpuinfo,
-};
-#endif /* CONFIG_PROC_FS */
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/kernel/topology.c linux-libre-2.6.38-gnu1/arch/sh/kernel/topology.c
--- linux-libre-2.6.37-gnu1/arch/sh/kernel/topology.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/kernel/topology.c	2011-03-14 21:20:32.000000000 -0400
@@ -17,6 +17,7 @@
 static DEFINE_PER_CPU(struct cpu, cpu_devices);
 
 cpumask_t cpu_core_map[NR_CPUS];
+EXPORT_SYMBOL(cpu_core_map);
 
 static cpumask_t cpu_coregroup_map(unsigned int cpu)
 {
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/lib/delay.c linux-libre-2.6.38-gnu1/arch/sh/lib/delay.c
--- linux-libre-2.6.37-gnu1/arch/sh/lib/delay.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/lib/delay.c	2011-03-14 21:20:32.000000000 -0400
@@ -10,6 +10,16 @@
 void __delay(unsigned long loops)
 {
 	__asm__ __volatile__(
+		/*
+		 * ST40-300 appears to have an issue with this code,
+		 * normally taking two cycles each loop, as with all
+		 * other SH variants. If however the branch and the
+		 * delay slot straddle an 8 byte boundary, this increases
+		 * to 3 cycles.
+		 * This align directive ensures this doesn't occur.
+		 */
+		".balign 8\n\t"
+
 		"tst	%0, %0\n\t"
 		"1:\t"
 		"bf/s	1b\n\t"
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/Makefile linux-libre-2.6.38-gnu1/arch/sh/Makefile
--- linux-libre-2.6.37-gnu1/arch/sh/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -200,7 +200,7 @@ endif
 libs-$(CONFIG_SUPERH32)		:= arch/sh/lib/	$(libs-y)
 libs-$(CONFIG_SUPERH64)		:= arch/sh/lib64/ $(libs-y)
 
-BOOT_TARGETS = uImage uImage.bz2 uImage.gz uImage.lzma uImage.lzo \
+BOOT_TARGETS = uImage uImage.bz2 uImage.gz uImage.lzma uImage.xz uImage.lzo \
 	       uImage.srec uImage.bin zImage vmlinux.bin vmlinux.srec \
 	       romImage
 PHONY += $(BOOT_TARGETS)
@@ -230,5 +230,6 @@ define archhelp
 	@echo '* uImage.gz	           - Kernel-only image for U-Boot (gzip)'
 	@echo '  uImage.bz2	           - Kernel-only image for U-Boot (bzip2)'
 	@echo '  uImage.lzma	           - Kernel-only image for U-Boot (lzma)'
+	@echo '  uImage.xz	           - Kernel-only image for U-Boot (xz)'
 	@echo '  uImage.lzo	           - Kernel-only image for U-Boot (lzo)'
 endef
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/mm/cache.c linux-libre-2.6.38-gnu1/arch/sh/mm/cache.c
--- linux-libre-2.6.37-gnu1/arch/sh/mm/cache.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/mm/cache.c	2011-03-14 21:20:32.000000000 -0400
@@ -108,7 +108,8 @@ void copy_user_highpage(struct page *to,
 		kunmap_atomic(vfrom, KM_USER0);
 	}
 
-	if (pages_do_alias((unsigned long)vto, vaddr & PAGE_MASK))
+	if (pages_do_alias((unsigned long)vto, vaddr & PAGE_MASK) ||
+	    (vma->vm_flags & VM_EXEC))
 		__flush_purge_region(vto, PAGE_SIZE);
 
 	kunmap_atomic(vto, KM_USER1);
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/mm/cache-sh5.c linux-libre-2.6.38-gnu1/arch/sh/mm/cache-sh5.c
--- linux-libre-2.6.37-gnu1/arch/sh/mm/cache-sh5.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/mm/cache-sh5.c	2011-03-14 21:20:32.000000000 -0400
@@ -568,7 +568,7 @@ static void sh5_flush_dcache_page(void *
 }
 
 /*
- * Flush the range [start,end] of kernel virtual adddress space from
+ * Flush the range [start,end] of kernel virtual address space from
  * the I-cache.  The corresponding range must be purged from the
  * D-cache also because the SH-5 doesn't have cache snooping between
  * the caches.  The addresses will be visible through the superpage
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/mm/hugetlbpage.c linux-libre-2.6.38-gnu1/arch/sh/mm/hugetlbpage.c
--- linux-libre-2.6.37-gnu1/arch/sh/mm/hugetlbpage.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/mm/hugetlbpage.c	2011-03-14 21:20:32.000000000 -0400
@@ -35,7 +35,7 @@ pte_t *huge_pte_alloc(struct mm_struct *
 		if (pud) {
 			pmd = pmd_alloc(mm, pud, addr);
 			if (pmd)
-				pte = pte_alloc_map(mm, pmd, addr);
+				pte = pte_alloc_map(mm, NULL, pmd, addr);
 		}
 	}
 
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/mm/init.c linux-libre-2.6.38-gnu1/arch/sh/mm/init.c
--- linux-libre-2.6.37-gnu1/arch/sh/mm/init.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/mm/init.c	2011-03-14 21:20:32.000000000 -0400
@@ -2,7 +2,7 @@
  * linux/arch/sh/mm/init.c
  *
  *  Copyright (C) 1999  Niibe Yutaka
- *  Copyright (C) 2002 - 2010  Paul Mundt
+ *  Copyright (C) 2002 - 2011  Paul Mundt
  *
  *  Based on linux/arch/i386/mm/init.c:
  *   Copyright (C) 1995  Linus Torvalds
@@ -325,11 +325,17 @@ void __init paging_init(void)
 	int nid;
 
 	memblock_init();
-
 	sh_mv.mv_mem_init();
 
 	early_reserve_mem();
 
+	/*
+	 * Once the early reservations are out of the way, give the
+	 * platforms a chance to kick out some memory.
+	 */
+	if (sh_mv.mv_mem_reserve)
+		sh_mv.mv_mem_reserve();
+
 	memblock_enforce_memory_limit(memory_limit);
 	memblock_analyze();
 
diff -druNp linux-libre-2.6.37-gnu1/arch/sh/tools/mach-types linux-libre-2.6.38-gnu1/arch/sh/tools/mach-types
--- linux-libre-2.6.37-gnu1/arch/sh/tools/mach-types	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sh/tools/mach-types	2011-03-14 21:20:32.000000000 -0400
@@ -9,6 +9,7 @@ SE			SH_SOLUTION_ENGINE
 HIGHLANDER		SH_HIGHLANDER
 RTS7751R2D		SH_RTS7751R2D
 RSK			SH_RSK
+ALPHA_BOARD		SH_ALPHA_BOARD
 
 #
 # List of companion chips / MFDs.
@@ -61,3 +62,5 @@ ESPT			SH_ESPT
 POLARIS			SH_POLARIS
 KFR2R09			SH_KFR2R09
 ECOVEC			SH_ECOVEC
+APSH4A3A		SH_APSH4A3A
+APSH4AD0A		SH_APSH4AD0A
diff -druNp linux-libre-2.6.37-gnu1/arch/sparc/boot/Makefile linux-libre-2.6.38-gnu1/arch/sparc/boot/Makefile
--- linux-libre-2.6.37-gnu1/arch/sparc/boot/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sparc/boot/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -6,25 +6,24 @@
 ROOT_IMG	:= /usr/src/root.img
 ELFTOAOUT	:= elftoaout
 
-hostprogs-y	:= piggyback_32 piggyback_64 btfixupprep
+hostprogs-y	:= piggyback btfixupprep
 targets		:= tftpboot.img btfix.o btfix.S image zImage vmlinux.aout
 clean-files	:= System.map
 
 quiet_cmd_elftoaout	= ELFTOAOUT $@
       cmd_elftoaout	= $(ELFTOAOUT) $(obj)/image -o $@
+quiet_cmd_piggy		= PIGGY   $@
+      cmd_piggy		= $(obj)/piggyback $(BITS) $@ System.map $(ROOT_IMG)
+quiet_cmd_strip		= STRIP   $@
+      cmd_strip		= $(STRIP) -R .comment -R .note -K sun4u_init -K _end -K _start $< -o $@
 
 ifeq ($(CONFIG_SPARC32),y)
-quiet_cmd_piggy		= PIGGY   $@
-      cmd_piggy		= $(obj)/piggyback_32 $@ System.map $(ROOT_IMG)
 quiet_cmd_btfix		= BTFIX   $@
       cmd_btfix		= $(OBJDUMP) -x vmlinux | $(obj)/btfixupprep > $@
 quiet_cmd_sysmap        = SYSMAP  $(obj)/System.map
       cmd_sysmap        = $(CONFIG_SHELL) $(srctree)/scripts/mksysmap
 quiet_cmd_image = LD      $@
       cmd_image = $(LD) $(LDFLAGS) $(EXTRA_LDFLAGS) $(LDFLAGS_$(@F)) -o $@
-quiet_cmd_strip = STRIP   $@
-      cmd_strip = $(STRIP) -R .comment -R .note -K sun4u_init -K _end -K _start $(obj)/image -o $@
-
 
 define rule_image
 	$(if $($(quiet)cmd_image),               \
@@ -57,10 +56,7 @@ $(obj)/image: $(obj)/btfix.o FORCE
 
 $(obj)/zImage: $(obj)/image
 	$(call if_changed,strip)
-
-$(obj)/tftpboot.img: $(obj)/image $(obj)/piggyback_32 System.map $(ROOT_IMG) FORCE
-	$(call if_changed,elftoaout)
-	$(call if_changed,piggy)
+	@echo '  kernel: $@ is ready'
 
 $(obj)/btfix.S: $(obj)/btfixupprep vmlinux FORCE
 	$(call if_changed,btfix)
@@ -68,11 +64,6 @@ $(obj)/btfix.S: $(obj)/btfixupprep vmlin
 endif
 
 ifeq ($(CONFIG_SPARC64),y)
-quiet_cmd_piggy     = PIGGY   $@
-      cmd_piggy     = $(obj)/piggyback_64 $@ System.map $(ROOT_IMG)
-quiet_cmd_strip     = STRIP   $@
-      cmd_strip     = $(STRIP) -R .comment -R .note -K sun4u_init -K _end -K _start vmlinux -o $@
-
 
 # Actual linking
 $(obj)/image: vmlinux FORCE
@@ -81,10 +72,6 @@ $(obj)/image: vmlinux FORCE
 
 $(obj)/zImage: $(obj)/image
 	$(call if_changed,gzip)
-
-$(obj)/tftpboot.img: $(obj)/image $(obj)/piggyback_64 System.map $(ROOT_IMG) FORCE
-	$(call if_changed,elftoaout)
-	$(call if_changed,piggy)
 	@echo '  kernel: $@ is ready'
 
 $(obj)/vmlinux.aout: vmlinux FORCE
@@ -92,3 +79,6 @@ $(obj)/vmlinux.aout: vmlinux FORCE
 	@echo '  kernel: $@ is ready'
 endif
 
+$(obj)/tftpboot.img: $(obj)/image $(obj)/piggyback System.map $(ROOT_IMG) FORCE
+	$(call if_changed,elftoaout)
+	$(call if_changed,piggy)
diff -druNp linux-libre-2.6.37-gnu1/arch/sparc/boot/piggyback_32.c linux-libre-2.6.38-gnu1/arch/sparc/boot/piggyback_32.c
--- linux-libre-2.6.37-gnu1/arch/sparc/boot/piggyback_32.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sparc/boot/piggyback_32.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,137 +0,0 @@
-/*
-   Simple utility to make a single-image install kernel with initial ramdisk
-   for Sparc tftpbooting without need to set up nfs.
-
-   Copyright (C) 1996 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
-   Pete Zaitcev <zaitcev@yahoo.com> endian fixes for cross-compiles, 2000.
-
-   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 <stdio.h>
-#include <string.h>
-#include <ctype.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <dirent.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-
-/*
- * Note: run this on an a.out kernel (use elftoaout for it),
- * as PROM looks for a.out image only.
- */
-
-static unsigned short ld2(char *p)
-{
-	return (p[0] << 8) | p[1];
-}
-
-static unsigned int ld4(char *p)
-{
-	return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
-}
-
-static void st4(char *p, unsigned int x)
-{
-	p[0] = x >> 24;
-	p[1] = x >> 16;
-	p[2] = x >> 8;
-	p[3] = x;
-}
-
-static void usage(void)
-{
-	/* fs_img.gz is an image of initial ramdisk. */
-	fprintf(stderr, "Usage: piggyback vmlinux.aout System.map fs_img.gz\n");
-	fprintf(stderr, "\tKernel image will be modified in place.\n");
-	exit(1);
-}
-
-static void die(char *str)
-{
-	perror (str);
-	exit(1);
-}
-
-int main(int argc,char **argv)
-{
-	static char aout_magic[] = { 0x01, 0x03, 0x01, 0x07 };
-	char buffer[1024], *q, *r;
-	unsigned int i, j, k, start, end, offset;
-	FILE *map;
-	struct stat s;
-	int image, tail;
-
-	if (argc != 4) usage();
-	start = end = 0;
-	if (stat (argv[3], &s) < 0) die (argv[3]);
-	map = fopen (argv[2], "r");
-	if (!map) die(argv[2]);
-	while (fgets (buffer, 1024, map)) {
-		if (!strcmp (buffer + 8, " T start\n") || !strcmp (buffer + 16, " T start\n"))
-			start = strtoul (buffer, NULL, 16);
-		else if (!strcmp (buffer + 8, " A _end\n") || !strcmp (buffer + 16, " A _end\n"))
-			end = strtoul (buffer, NULL, 16);
-	}
-	fclose (map);
-	if (!start || !end) {
-		fprintf (stderr, "Could not determine start and end from System.map\n");
-		exit(1);
-	}
-	if ((image = open(argv[1],O_RDWR)) < 0) die(argv[1]);
-	if (read(image,buffer,512) != 512) die(argv[1]);
-	if (memcmp (buffer, "\177ELF", 4) == 0) {
-		q = buffer + ld4(buffer + 28);
-		i = ld4(q + 4) + ld4(buffer + 24) - ld4(q + 8);
-		if (lseek(image,i,0) < 0) die("lseek");
-		if (read(image,buffer,512) != 512) die(argv[1]);
-		j = 0;
-	} else if (memcmp(buffer, aout_magic, 4) == 0) {
-		i = j = 32;
-	} else {
-		fprintf (stderr, "Not ELF nor a.out. Don't blame me.\n");
-		exit(1);
-	}
-	k = i;
-	i += (ld2(buffer + j + 2)<<2) - 512;
-	if (lseek(image,i,0) < 0) die("lseek");
-	if (read(image,buffer,1024) != 1024) die(argv[1]);
-	for (q = buffer, r = q + 512; q < r; q += 4) {
-		if (*q == 'H' && q[1] == 'd' && q[2] == 'r' && q[3] == 'S')
-			break;
-	}
-	if (q == r) {
-		fprintf (stderr, "Couldn't find headers signature in the kernel.\n");
-		exit(1);
-	}
-	offset = i + (q - buffer) + 10;
-	if (lseek(image, offset, 0) < 0) die ("lseek");
-
-	st4(buffer, 0);
-	st4(buffer + 4, 0x01000000);
-	st4(buffer + 8, (end + 32 + 4095) & ~4095);
-	st4(buffer + 12, s.st_size);
-
-	if (write(image,buffer+2,14) != 14) die (argv[1]);
-	if (lseek(image, k - start + ((end + 32 + 4095) & ~4095), 0) < 0) die ("lseek");
-	if ((tail = open(argv[3],O_RDONLY)) < 0) die(argv[3]);
-	while ((i = read (tail,buffer,1024)) > 0)
-		if (write(image,buffer,i) != i) die (argv[1]);
-	if (close(image) < 0) die("close");
-	if (close(tail) < 0) die("close");
-    	return 0;
-}
diff -druNp linux-libre-2.6.37-gnu1/arch/sparc/boot/piggyback_64.c linux-libre-2.6.38-gnu1/arch/sparc/boot/piggyback_64.c
--- linux-libre-2.6.37-gnu1/arch/sparc/boot/piggyback_64.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sparc/boot/piggyback_64.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,110 +0,0 @@
-/*
-   Simple utility to make a single-image install kernel with initial ramdisk
-   for Sparc64 tftpbooting without need to set up nfs.
-   
-   Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
-   
-   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 <stdio.h>
-#include <string.h>
-#include <ctype.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <dirent.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-
-/* Note: run this on an a.out kernel (use elftoaout for it), as PROM looks for a.out image onlly
-   usage: piggyback vmlinux System.map tail, where tail is gzipped fs of the initial ramdisk */
-
-static void die(char *str)
-{
-	perror (str);
-	exit(1);
-}
-
-int main(int argc,char **argv)
-{
-	char buffer [1024], *q, *r;
-	unsigned int i, j, k, start, end, offset;
-	FILE *map;
-	struct stat s;
-	int image, tail;
-	
-	start = end = 0;
-	if (stat (argv[3], &s) < 0) die (argv[3]);
-	map = fopen (argv[2], "r");
-	if (!map) die(argv[2]);
-	while (fgets (buffer, 1024, map)) {
-		if (!strcmp (buffer + 19, "_start\n"))
-		start = strtoul (buffer + 8, NULL, 16);
-		else if (!strcmp (buffer + 19, "_end\n"))
-		end = strtoul (buffer + 8, NULL, 16);
-	}
-	fclose (map);
-	if ((image = open(argv[1],O_RDWR)) < 0) die(argv[1]);
-	if (read(image,buffer,512) != 512) die(argv[1]);
-	if (!memcmp (buffer, "\177ELF", 4)) {
-		unsigned int *p = (unsigned int *)(buffer + *(unsigned int *)(buffer + 28));
-		
-		i = p[1] + *(unsigned int *)(buffer + 24) - p[2];
-		if (lseek(image,i,0) < 0) die("lseek");
-		if (read(image,buffer,512) != 512) die(argv[1]);
-		j = 0;
-	} else if (*(unsigned int *)buffer == 0x01030107) {
-		i = j = 32;
-	} else {
-		fprintf (stderr, "Not ELF nor a.out. Don't blame me.\n");
-		exit(1);
-	}
-	k = i;
-	if (j == 32 && buffer[40] == 'H' && buffer[41] == 'd' && buffer[42] == 'r' && buffer[43] == 'S') {
-		offset = 40 + 10;
-	} else {
-		i += ((*(unsigned short *)(buffer + j + 2))<<2) - 512;
-		if (lseek(image,i,0) < 0) die("lseek");
-		if (read(image,buffer,1024) != 1024) die(argv[1]);
-		for (q = buffer, r = q + 512; q < r; q += 4) {
-			if (*q == 'H' && q[1] == 'd' && q[2] == 'r' && q[3] == 'S')
-				break;
-		}
-		if (q == r) {
-			fprintf (stderr, "Couldn't find headers signature in the kernel.\n");
-			exit(1);
-		}
-		offset = i + (q - buffer) + 10;
-	}
-	if (lseek(image, offset, 0) < 0) die ("lseek");
-	*(unsigned *)buffer = 0;
-	*(unsigned *)(buffer + 4) = 0x01000000;
-	*(unsigned *)(buffer + 8) = ((end + 32 + 8191) & ~8191);
-	*(unsigned *)(buffer + 12) = s.st_size;
-	if (write(image,buffer+2,14) != 14) die (argv[1]);
-	if (lseek(image, 4, 0) < 0) die ("lseek");
-	*(unsigned *)buffer = ((end + 32 + 8191) & ~8191) - (start & ~0x3fffffUL) + s.st_size;
-	*(unsigned *)(buffer + 4) = 0;
-	*(unsigned *)(buffer + 8) = 0;
-	if (write(image,buffer,12) != 12) die (argv[1]);
-	if (lseek(image, k - start + ((end + 32 + 8191) & ~8191), 0) < 0) die ("lseek");
-	if ((tail = open(argv[3],O_RDONLY)) < 0) die(argv[3]);
-	while ((i = read (tail,buffer,1024)) > 0)
-		if (write(image,buffer,i) != i) die (argv[1]);
-	if (close(image) < 0) die("close");
-	if (close(tail) < 0) die("close");
-    	return 0;
-}
diff -druNp linux-libre-2.6.37-gnu1/arch/sparc/boot/piggyback.c linux-libre-2.6.38-gnu1/arch/sparc/boot/piggyback.c
--- linux-libre-2.6.37-gnu1/arch/sparc/boot/piggyback.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sparc/boot/piggyback.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,272 @@
+/*
+   Simple utility to make a single-image install kernel with initial ramdisk
+   for Sparc tftpbooting without need to set up nfs.
+
+   Copyright (C) 1996,1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
+   Pete Zaitcev <zaitcev@yahoo.com> endian fixes for cross-compiles, 2000.
+   Copyright (C) 2011 Sam Ravnborg <sam@ravnborg.org>
+
+   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 <dirent.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+/*
+ * Note: run this on an a.out kernel (use elftoaout for it),
+ * as PROM looks for a.out image only.
+ */
+
+#define AOUT_TEXT_OFFSET   32
+
+static int is64bit = 0;
+
+/* align to power-of-two size */
+static int align(int n)
+{
+	if (is64bit)
+		return (n + 0x1fff) & ~0x1fff;
+	else
+		return (n + 0xfff) & ~0xfff;
+}
+
+/* read two bytes as big endian */
+static unsigned short ld2(char *p)
+{
+	return (p[0] << 8) | p[1];
+}
+
+/* save 4 bytes as big endian */
+static void st4(char *p, unsigned int x)
+{
+	p[0] = x >> 24;
+	p[1] = x >> 16;
+	p[2] = x >> 8;
+	p[3] = x;
+}
+
+static void die(const char *str)
+{
+	perror(str);
+	exit(1);
+}
+
+static void usage(void)
+{
+	/* fs_img.gz is an image of initial ramdisk. */
+	fprintf(stderr, "Usage: piggyback bits vmlinux.aout System.map fs_img.gz\n");
+	fprintf(stderr, "\tKernel image will be modified in place.\n");
+	exit(1);
+}
+
+static int start_line(const char *line)
+{
+	if (strcmp(line + 8, " T _start\n") == 0)
+		return 1;
+	else if (strcmp(line + 16, " T _start\n") == 0)
+		return 1;
+	return 0;
+}
+
+static int end_line(const char *line)
+{
+	if (strcmp(line + 8, " A _end\n") == 0)
+		return 1;
+	else if (strcmp (line + 16, " A _end\n") == 0)
+		return 1;
+	return 0;
+}
+
+/*
+ * Find address for start and end in System.map.
+ * The file looks like this:
+ * f0004000 T _start
+ * f0379f79 A _end
+ * 1234567890123456
+ * ^coloumn 1
+ * There is support for 64 bit addresses too.
+ *
+ * Return 0 if either start or end is not found
+ */
+static int get_start_end(const char *filename, unsigned int *start,
+                                               unsigned int *end)
+{
+	FILE *map;
+	char buffer[1024];
+
+	*start = 0;
+	*end = 0;
+	map = fopen(filename, "r");
+	if (!map)
+		die(filename);
+	while (fgets(buffer, 1024, map)) {
+		if (start_line(buffer))
+			*start = strtoul(buffer, NULL, 16);
+		else if (end_line(buffer))
+			*end = strtoul(buffer, NULL, 16);
+	}
+	fclose (map);
+
+	if (*start == 0 || *end == 0)
+		return 0;
+
+	return 1;
+}
+
+#define LOOKBACK (128 * 4)
+#define BUFSIZE 1024
+/*
+ * Find the HdrS entry from head_32/head_64.
+ * We check if it is at the beginning of the file (sparc64 case)
+ * and if not we search for it.
+ * When we search do so in steps of 4 as HdrS is on a 4-byte aligned
+ * address (it is on same alignment as sparc instructions)
+ * Return the offset to the HdrS entry (as off_t)
+ */
+static off_t get_hdrs_offset(int kernelfd, const char *filename)
+{
+	char buffer[BUFSIZE];
+	off_t offset;
+	int i;
+
+	if (lseek(kernelfd, 0, SEEK_SET) < 0)
+		die("lseek");
+	if (read(kernelfd, buffer, BUFSIZE) != BUFSIZE)
+		die(filename);
+
+	if (buffer[40] == 'H' && buffer[41] == 'd' &&
+	    buffer[42] == 'r' && buffer[43] == 'S') {
+		return 40;
+	} else {
+		/*  Find the gokernel label */
+		/* Decode offset from branch instruction */
+		offset = ld2(buffer + AOUT_TEXT_OFFSET + 2) << 2;
+		/* Go back 512 bytes so we do not miss HdrS */
+		offset -= LOOKBACK;
+		/* skip a.out header */
+		offset += AOUT_TEXT_OFFSET;
+		if (lseek(kernelfd, offset, SEEK_SET) < 0)
+			die("lseek");
+		if (read(kernelfd, buffer, BUFSIZE) != BUFSIZE)
+			die(filename);
+
+		for (i = 0; i < LOOKBACK; i += 4) {
+			if (buffer[i + 0] == 'H' && buffer[i + 1] == 'd' &&
+			    buffer[i + 2] == 'r' && buffer[i + 3] == 'S') {
+				return offset + i;
+			}
+		}
+	}
+	fprintf (stderr, "Couldn't find headers signature in %s\n", filename);
+	exit(1);
+}
+
+int main(int argc,char **argv)
+{
+	static char aout_magic[] = { 0x01, 0x03, 0x01, 0x07 };
+	char buffer[1024];
+	unsigned int i, start, end;
+	off_t offset;
+	struct stat s;
+	int image, tail;
+
+	if (argc != 5)
+		usage();
+	if (strcmp(argv[1], "64") == 0)
+		is64bit = 1;
+	if (stat (argv[4], &s) < 0)
+		die(argv[4]);
+
+	if (!get_start_end(argv[3], &start, &end)) {
+		fprintf(stderr, "Could not determine start and end from %s\n",
+		        argv[3]);
+		exit(1);
+	}
+	if ((image = open(argv[2], O_RDWR)) < 0)
+		die(argv[2]);
+	if (read(image, buffer, 512) != 512)
+		die(argv[2]);
+	if (memcmp(buffer, aout_magic, 4) != 0) {
+		fprintf (stderr, "Not a.out. Don't blame me.\n");
+		exit(1);
+	}
+	/*
+	 * We need to fill in values for
+	 * sparc_ramdisk_image + sparc_ramdisk_size
+	 * To locate these symbols search for the "HdrS" text which appear
+	 * in the image a little before the gokernel symbol.
+	 * See definition of these in init_32.S
+	 */
+
+	offset = get_hdrs_offset(image, argv[2]);
+	/* skip HdrS + LINUX_VERSION_CODE + HdrS version */
+	offset += 10;
+
+	if (lseek(image, offset, 0) < 0)
+		die("lseek");
+
+	/*
+	 * root_flags = 0
+	 * root_dev = 1 (RAMDISK_MAJOR)
+	 * ram_flags = 0
+	 * sparc_ramdisk_image = "PAGE aligned address after _end")
+	 * sparc_ramdisk_size = size of image
+	 */
+	st4(buffer, 0);
+	st4(buffer + 4, 0x01000000);
+	st4(buffer + 8, align(end + 32));
+	st4(buffer + 12, s.st_size);
+
+	if (write(image, buffer + 2, 14) != 14)
+		die(argv[2]);
+
+	/* For sparc64 update a_text and clear a_data + a_bss */
+	if (is64bit)
+	{
+		if (lseek(image, 4, 0) < 0)
+			die("lseek");
+		/* a_text */
+		st4(buffer, align(end + 32 + 8191) - (start & ~0x3fffffUL) +
+		            s.st_size);
+		/* a_data */
+		st4(buffer + 4, 0);
+		/* a_bss */
+		st4(buffer + 8, 0);
+		if (write(image, buffer, 12) != 12)
+			die(argv[2]);
+	}
+
+	/* seek page aligned boundary in the image file and add boot image */
+	if (lseek(image, AOUT_TEXT_OFFSET - start + align(end + 32), 0) < 0)
+		die("lseek");
+	if ((tail = open(argv[4], O_RDONLY)) < 0)
+		die(argv[4]);
+	while ((i = read(tail, buffer, 1024)) > 0)
+		if (write(image, buffer, i) != i)
+			die(argv[2]);
+	if (close(image) < 0)
+		die("close");
+	if (close(tail) < 0)
+		die("close");
+	return 0;
+}
diff -druNp linux-libre-2.6.37-gnu1/arch/sparc/include/asm/ioctls.h linux-libre-2.6.38-gnu1/arch/sparc/include/asm/ioctls.h
--- linux-libre-2.6.37-gnu1/arch/sparc/include/asm/ioctls.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sparc/include/asm/ioctls.h	2011-03-14 21:20:32.000000000 -0400
@@ -19,6 +19,7 @@
 #define TCSETS2		_IOW('T', 13, struct termios2)
 #define TCSETSW2	_IOW('T', 14, struct termios2)
 #define TCSETSF2	_IOW('T', 15, struct termios2)
+#define TIOCGDEV	_IOR('T',0x32, unsigned int) /* Get primary device node of /dev/console */
 
 /* Note that all the ioctls that are not available in Linux have a 
  * double underscore on the front to: a) avoid some programs to
diff -druNp linux-libre-2.6.37-gnu1/arch/sparc/include/asm/leon_amba.h linux-libre-2.6.38-gnu1/arch/sparc/include/asm/leon_amba.h
--- linux-libre-2.6.37-gnu1/arch/sparc/include/asm/leon_amba.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sparc/include/asm/leon_amba.h	2011-03-14 21:20:32.000000000 -0400
@@ -100,9 +100,8 @@ struct leon3_irqctrl_regs_map {
 	u32 mpbroadcast;
 	u32 notused02;
 	u32 notused03;
-	u32 notused10;
-	u32 notused11;
-	u32 notused12;
+	u32 ampctrl;
+	u32 icsel[2];
 	u32 notused13;
 	u32 notused20;
 	u32 notused21;
@@ -112,6 +111,7 @@ struct leon3_irqctrl_regs_map {
 	u32 force[16];
 	/* Extended IRQ registers */
 	u32 intid[16];	/* 0xc0 */
+	u32 unused[(0x1000-0x100)/4];
 };
 
 struct leon3_apbuart_regs_map {
diff -druNp linux-libre-2.6.37-gnu1/arch/sparc/include/asm/leon.h linux-libre-2.6.38-gnu1/arch/sparc/include/asm/leon.h
--- linux-libre-2.6.37-gnu1/arch/sparc/include/asm/leon.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sparc/include/asm/leon.h	2011-03-14 21:20:32.000000000 -0400
@@ -224,6 +224,18 @@ static inline void sparc_leon3_disable_c
 			  "sta %%l2, [%%g0] 2\n\t" : : : "l1", "l2");
 };
 
+static inline unsigned long sparc_leon3_asr17(void)
+{
+	u32 asr17;
+	__asm__ __volatile__ ("rd %%asr17, %0\n\t" : "=r"(asr17));
+	return asr17;
+};
+
+static inline int sparc_leon3_cpuid(void)
+{
+	return sparc_leon3_asr17() >> 28;
+}
+
 #endif /*!__ASSEMBLY__*/
 
 #ifdef CONFIG_SMP
diff -druNp linux-libre-2.6.37-gnu1/arch/sparc/include/asm/oplib_32.h linux-libre-2.6.38-gnu1/arch/sparc/include/asm/oplib_32.h
--- linux-libre-2.6.37-gnu1/arch/sparc/include/asm/oplib_32.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sparc/include/asm/oplib_32.h	2011-03-14 21:20:32.000000000 -0400
@@ -48,18 +48,6 @@ extern void prom_init(struct linux_romve
 /* Boot argument acquisition, returns the boot command line string. */
 extern char *prom_getbootargs(void);
 
-/* Device utilities. */
-
-/* Map and unmap devices in IO space at virtual addresses. Note that the
- * virtual address you pass is a request and the prom may put your mappings
- * somewhere else, so check your return value as that is where your new
- * mappings really are!
- *
- * Another note, these are only available on V2 or higher proms!
- */
-extern char *prom_mapio(char *virt_hint, int io_space, unsigned int phys_addr, unsigned int num_bytes);
-extern void prom_unmapio(char *virt_addr, unsigned int num_bytes);
-
 /* Miscellaneous routines, don't really fit in any category per se. */
 
 /* Reboot the machine with the command line passed. */
@@ -76,7 +64,7 @@ extern void prom_cmdline(void);
 /* Enter the prom, with no chance of continuation for the stand-alone
  * which calls this.
  */
-extern void prom_halt(void) __attribute__ ((noreturn));
+extern void __noreturn prom_halt(void);
 
 /* Set the PROM 'sync' callback function to the passed function pointer.
  * When the user gives the 'sync' command at the prom prompt while the
@@ -117,25 +105,6 @@ extern void prom_write(const char *buf,
 extern int prom_startcpu(int cpunode, struct linux_prom_registers *context_table,
 			 int context, char *program_counter);
 
-/* Stop the CPU with the passed device tree node. */
-extern int prom_stopcpu(int cpunode);
-
-/* Idle the CPU with the passed device tree node. */
-extern int prom_idlecpu(int cpunode);
-
-/* Re-Start the CPU with the passed device tree node. */
-extern int prom_restartcpu(int cpunode);
-
-/* PROM memory allocation facilities... */
-
-/* Allocated at possibly the given virtual address a chunk of the
- * indicated size.
- */
-extern char *prom_alloc(char *virt_hint, unsigned int size);
-
-/* Free a previously allocated chunk. */
-extern void prom_free(char *virt_addr, unsigned int size);
-
 /* Sun4/sun4c specific memory-management startup hook. */
 
 /* Map the passed segment in the given context at the passed
@@ -144,6 +113,8 @@ extern void prom_free(char *virt_addr, u
 extern void prom_putsegment(int context, unsigned long virt_addr,
 			    int physical_segment);
 
+/* Initialize the memory lists based upon the prom version. */
+void prom_meminit(void);
 
 /* PROM device tree traversal functions... */
 
@@ -178,19 +149,11 @@ extern int prom_getbool(phandle node, ch
 /* Acquire a string property, null string on error. */
 extern void prom_getstring(phandle node, char *prop, char *buf, int bufsize);
 
-/* Does the passed node have the given "name"? YES=1 NO=0 */
-extern int prom_nodematch(phandle thisnode, char *name);
-
 /* Search all siblings starting at the passed node for "name" matching
  * the given string.  Returns the node on success, zero on failure.
  */
 extern phandle prom_searchsiblings(phandle node_start, char *name);
 
-/* Return the first property type, as a string, for the given node.
- * Returns a null string on error.
- */
-extern char *prom_firstprop(phandle node, char *buffer);
-
 /* Returns the next property after the passed property for the given
  * node.  Returns null string on failure.
  */
@@ -199,9 +162,6 @@ extern char *prom_nextprop(phandle node,
 /* Returns phandle of the path specified */
 extern phandle prom_finddevice(char *name);
 
-/* Returns 1 if the specified node has given property. */
-extern int prom_node_has_property(phandle node, char *property);
-
 /* Set the indicated property at the given node with the passed value.
  * Returns the number of bytes of your value that the prom took.
  */
@@ -219,6 +179,8 @@ extern void prom_apply_obio_ranges(struc
 extern void prom_apply_generic_ranges(phandle node, phandle parent,
 				      struct linux_prom_registers *sbusregs, int nregs);
 
+void prom_ranges_init(void);
+
 /* CPU probing helpers.  */
 int cpu_find_by_instance(int instance, phandle *prom_node, int *mid);
 int cpu_find_by_mid(int mid, phandle *prom_node);
diff -druNp linux-libre-2.6.37-gnu1/arch/sparc/include/asm/oplib_64.h linux-libre-2.6.38-gnu1/arch/sparc/include/asm/oplib_64.h
--- linux-libre-2.6.37-gnu1/arch/sparc/include/asm/oplib_64.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sparc/include/asm/oplib_64.h	2011-03-14 21:20:32.000000000 -0400
@@ -18,8 +18,8 @@ extern char prom_version[];
  */
 extern phandle prom_root_node;
 
-/* PROM stdin and stdout */
-extern int prom_stdin, prom_stdout;
+/* PROM stdout */
+extern int prom_stdout;
 
 /* /chosen node of the prom device tree, this stays constant after
  * initialization is complete.
diff -druNp linux-libre-2.6.37-gnu1/arch/sparc/include/asm/pcr.h linux-libre-2.6.38-gnu1/arch/sparc/include/asm/pcr.h
--- linux-libre-2.6.37-gnu1/arch/sparc/include/asm/pcr.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sparc/include/asm/pcr.h	2011-03-14 21:20:32.000000000 -0400
@@ -43,4 +43,6 @@ static inline u64 picl_value(unsigned in
 
 extern u64 pcr_enable;
 
+extern int pcr_arch_init(void);
+
 #endif /* __PCR_H */
diff -druNp linux-libre-2.6.37-gnu1/arch/sparc/include/asm/perf_event.h linux-libre-2.6.38-gnu1/arch/sparc/include/asm/perf_event.h
--- linux-libre-2.6.37-gnu1/arch/sparc/include/asm/perf_event.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sparc/include/asm/perf_event.h	2011-03-14 21:20:32.000000000 -0400
@@ -4,8 +4,6 @@
 #ifdef CONFIG_PERF_EVENTS
 #include <asm/ptrace.h>
 
-extern void init_hw_perf_events(void);
-
 #define perf_arch_fetch_caller_regs(regs, ip)		\
 do {							\
 	unsigned long _pstate, _asi, _pil, _i7, _fp;	\
@@ -26,8 +24,6 @@ do {							\
 	(regs)->u_regs[UREG_I6] = _fp;			\
 	(regs)->u_regs[UREG_I7] = _i7;			\
 } while (0)
-#else
-static inline void init_hw_perf_events(void)	{ }
 #endif
 
 #endif
diff -druNp linux-libre-2.6.37-gnu1/arch/sparc/Kconfig linux-libre-2.6.38-gnu1/arch/sparc/Kconfig
--- linux-libre-2.6.37-gnu1/arch/sparc/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sparc/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -50,6 +50,7 @@ config SPARC64
 	select RTC_DRV_STARFIRE
 	select HAVE_PERF_EVENTS
 	select PERF_USE_VMALLOC
+	select HAVE_GENERIC_HARDIRQS
 
 config ARCH_DEFCONFIG
 	string
@@ -107,10 +108,6 @@ config NEED_PER_CPU_EMBED_FIRST_CHUNK
 config NEED_PER_CPU_PAGE_FIRST_CHUNK
 	def_bool y if SPARC64
 
-config GENERIC_HARDIRQS_NO__DO_IRQ
-	bool
-	def_bool y if SPARC64
-
 config MMU
 	bool
 	default y
@@ -276,10 +273,6 @@ config HOTPLUG_CPU
 	  can be controlled through /sys/devices/system/cpu/cpu#.
 	  Say N if you want to disable CPU hotplug.
 
-config GENERIC_HARDIRQS
-	bool
-	default y if SPARC64
-
 source "kernel/time/Kconfig"
 
 if SPARC64
diff -druNp linux-libre-2.6.37-gnu1/arch/sparc/kernel/auxio_32.c linux-libre-2.6.38-gnu1/arch/sparc/kernel/auxio_32.c
--- linux-libre-2.6.37-gnu1/arch/sparc/kernel/auxio_32.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sparc/kernel/auxio_32.c	2011-03-14 21:20:32.000000000 -0400
@@ -121,7 +121,7 @@ void __init auxio_power_probe(void)
 	node = prom_searchsiblings(node, "obio");
 	node = prom_getchild(node);
 	node = prom_searchsiblings(node, "power");
-	if (node == 0 || node == -1)
+	if (node == 0 || (s32)node == -1)
 		return;
 
 	/* Map the power control register. */
diff -druNp linux-libre-2.6.37-gnu1/arch/sparc/kernel/cpu.c linux-libre-2.6.38-gnu1/arch/sparc/kernel/cpu.c
--- linux-libre-2.6.37-gnu1/arch/sparc/kernel/cpu.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sparc/kernel/cpu.c	2011-03-14 21:20:32.000000000 -0400
@@ -375,5 +375,5 @@ static int __init cpu_type_probe(void)
 	return 0;
 }
 
-arch_initcall(cpu_type_probe);
+early_initcall(cpu_type_probe);
 #endif
diff -druNp linux-libre-2.6.37-gnu1/arch/sparc/kernel/head_32.S linux-libre-2.6.38-gnu1/arch/sparc/kernel/head_32.S
--- linux-libre-2.6.37-gnu1/arch/sparc/kernel/head_32.S	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sparc/kernel/head_32.S	2011-03-14 21:20:32.000000000 -0400
@@ -73,12 +73,11 @@ sun4e_notsup:
 
 	/* The Sparc trap table, bootloader gives us control at _start. */
 	__HEAD
-	.globl	start, _stext, _start, __stext
+	.globl	_stext, _start, __stext
 	.globl  trapbase
 _start:   /* danger danger */
 __stext:
 _stext:
-start:
 trapbase:
 #ifdef CONFIG_SMP
 trapbase_cpu0:
diff -druNp linux-libre-2.6.37-gnu1/arch/sparc/kernel/iommu.c linux-libre-2.6.38-gnu1/arch/sparc/kernel/iommu.c
--- linux-libre-2.6.37-gnu1/arch/sparc/kernel/iommu.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sparc/kernel/iommu.c	2011-03-14 21:20:32.000000000 -0400
@@ -255,10 +255,9 @@ static inline iopte_t *alloc_npages(stru
 static int iommu_alloc_ctx(struct iommu *iommu)
 {
 	int lowest = iommu->ctx_lowest_free;
-	int sz = IOMMU_NUM_CTXS - lowest;
-	int n = find_next_zero_bit(iommu->ctx_bitmap, sz, lowest);
+	int n = find_next_zero_bit(iommu->ctx_bitmap, IOMMU_NUM_CTXS, lowest);
 
-	if (unlikely(n == sz)) {
+	if (unlikely(n == IOMMU_NUM_CTXS)) {
 		n = find_next_zero_bit(iommu->ctx_bitmap, lowest, 1);
 		if (unlikely(n == lowest)) {
 			printk(KERN_WARNING "IOMMU: Ran out of contexts.\n");
diff -druNp linux-libre-2.6.37-gnu1/arch/sparc/kernel/leon_kernel.c linux-libre-2.6.38-gnu1/arch/sparc/kernel/leon_kernel.c
--- linux-libre-2.6.37-gnu1/arch/sparc/kernel/leon_kernel.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sparc/kernel/leon_kernel.c	2011-03-14 21:20:32.000000000 -0400
@@ -23,15 +23,16 @@
 #include "prom.h"
 #include "irq.h"
 
-struct leon3_irqctrl_regs_map *leon3_irqctrl_regs; /* interrupt controller base address, initialized by amba_init() */
-struct leon3_gptimer_regs_map *leon3_gptimer_regs; /* timer controller base address, initialized by amba_init() */
+struct leon3_irqctrl_regs_map *leon3_irqctrl_regs; /* interrupt controller base address */
+struct leon3_gptimer_regs_map *leon3_gptimer_regs; /* timer controller base address */
 struct amba_apb_device leon_percpu_timer_dev[16];
 
 int leondebug_irq_disable;
 int leon_debug_irqout;
 static int dummy_master_l10_counter;
 
-unsigned long leon3_gptimer_irq; /* interrupt controller irq number, initialized by amba_init() */
+unsigned long leon3_gptimer_irq; /* interrupt controller irq number */
+unsigned long leon3_gptimer_idx; /* Timer Index (0..6) within Timer Core */
 unsigned int sparc_leon_eirq;
 #define LEON_IMASK ((&leon3_irqctrl_regs->mask[0]))
 
@@ -105,21 +106,79 @@ static void leon_disable_irq(unsigned in
 void __init leon_init_timers(irq_handler_t counter_fn)
 {
 	int irq;
+	struct device_node *rootnp, *np, *nnp;
+	struct property *pp;
+	int len;
+	int cpu, icsel;
+	int ampopts;
 
 	leondebug_irq_disable = 0;
 	leon_debug_irqout = 0;
 	master_l10_counter = (unsigned int *)&dummy_master_l10_counter;
 	dummy_master_l10_counter = 0;
 
-	if (leon3_gptimer_regs && leon3_irqctrl_regs) {
-		LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[0].val, 0);
-		LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[0].rld,
-				      (((1000000 / HZ) - 1)));
-		LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[0].ctrl, 0);
+	/*Find IRQMP IRQ Controller Registers base address otherwise bail out.*/
+	rootnp = of_find_node_by_path("/ambapp0");
+	if (!rootnp)
+		goto bad;
+	np = of_find_node_by_name(rootnp, "GAISLER_IRQMP");
+	if (!np) {
+		np = of_find_node_by_name(rootnp, "01_00d");
+		if (!np)
+			goto bad;
+	}
+	pp = of_find_property(np, "reg", &len);
+	if (!pp)
+		goto bad;
+	leon3_irqctrl_regs = *(struct leon3_irqctrl_regs_map **)pp->value;
+
+	/* Find GPTIMER Timer Registers base address otherwise bail out. */
+	nnp = rootnp;
+	do {
+		np = of_find_node_by_name(nnp, "GAISLER_GPTIMER");
+		if (!np) {
+			np = of_find_node_by_name(nnp, "01_011");
+			if (!np)
+				goto bad;
+		}
+
+		ampopts = 0;
+		pp = of_find_property(np, "ampopts", &len);
+		if (pp) {
+			ampopts = *(int *)pp->value;
+			if (ampopts == 0) {
+				/* Skip this instance, resource already
+				 * allocated by other OS */
+				nnp = np;
+				continue;
+			}
+		}
+
+		/* Select Timer-Instance on Timer Core. Default is zero */
+		leon3_gptimer_idx = ampopts & 0x7;
+
+		pp = of_find_property(np, "reg", &len);
+		if (pp)
+			leon3_gptimer_regs = *(struct leon3_gptimer_regs_map **)
+						pp->value;
+		pp = of_find_property(np, "interrupts", &len);
+		if (pp)
+			leon3_gptimer_irq = *(unsigned int *)pp->value;
+	} while (0);
+
+	if (leon3_gptimer_regs && leon3_irqctrl_regs && leon3_gptimer_irq) {
+		LEON3_BYPASS_STORE_PA(
+			&leon3_gptimer_regs->e[leon3_gptimer_idx].val, 0);
+		LEON3_BYPASS_STORE_PA(
+			&leon3_gptimer_regs->e[leon3_gptimer_idx].rld,
+			(((1000000 / HZ) - 1)));
+		LEON3_BYPASS_STORE_PA(
+			&leon3_gptimer_regs->e[leon3_gptimer_idx].ctrl, 0);
 
 #ifdef CONFIG_SMP
 		leon_percpu_timer_dev[0].start = (int)leon3_gptimer_regs;
-		leon_percpu_timer_dev[0].irq = leon3_gptimer_irq+1;
+		leon_percpu_timer_dev[0].irq = leon3_gptimer_irq + 1 +
+					       leon3_gptimer_idx;
 
 		if (!(LEON3_BYPASS_LOAD_PA(&leon3_gptimer_regs->config) &
 		      (1<<LEON3_GPTIMER_SEPIRQ))) {
@@ -127,17 +186,33 @@ void __init leon_init_timers(irq_handler
 			BUG();
 		}
 
-		LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[1].val, 0);
-		LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[1].rld, (((1000000/HZ) - 1)));
-		LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[1].ctrl, 0);
+		LEON3_BYPASS_STORE_PA(
+			&leon3_gptimer_regs->e[leon3_gptimer_idx+1].val, 0);
+		LEON3_BYPASS_STORE_PA(
+			&leon3_gptimer_regs->e[leon3_gptimer_idx+1].rld,
+			(((1000000/HZ) - 1)));
+		LEON3_BYPASS_STORE_PA(
+			&leon3_gptimer_regs->e[leon3_gptimer_idx+1].ctrl, 0);
 # endif
 
+		/*
+		 * The IRQ controller may (if implemented) consist of multiple
+		 * IRQ controllers, each mapped on a 4Kb boundary.
+		 * Each CPU may be routed to different IRQCTRLs, however
+		 * we assume that all CPUs (in SMP system) is routed to the
+		 * same IRQ Controller, and for non-SMP only one IRQCTRL is
+		 * accessed anyway.
+		 * In AMP systems, Linux must run on CPU0 for the time being.
+		 */
+		cpu = sparc_leon3_cpuid();
+		icsel = LEON3_BYPASS_LOAD_PA(&leon3_irqctrl_regs->icsel[cpu/8]);
+		icsel = (icsel >> ((7 - (cpu&0x7)) * 4)) & 0xf;
+		leon3_irqctrl_regs += icsel;
 	} else {
-		printk(KERN_ERR "No Timer/irqctrl found\n");
-		BUG();
+		goto bad;
 	}
 
-	irq = request_irq(leon3_gptimer_irq,
+	irq = request_irq(leon3_gptimer_irq+leon3_gptimer_idx,
 			  counter_fn,
 			  (IRQF_DISABLED | SA_STATIC_ALLOC), "timer", NULL);
 
@@ -169,13 +244,13 @@ void __init leon_init_timers(irq_handler
 # endif
 
 	if (leon3_gptimer_regs) {
-		LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[0].ctrl,
+		LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx].ctrl,
 				      LEON3_GPTIMER_EN |
 				      LEON3_GPTIMER_RL |
 				      LEON3_GPTIMER_LD | LEON3_GPTIMER_IRQEN);
 
 #ifdef CONFIG_SMP
-		LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[1].ctrl,
+		LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx+1].ctrl,
 				      LEON3_GPTIMER_EN |
 				      LEON3_GPTIMER_RL |
 				      LEON3_GPTIMER_LD |
@@ -183,6 +258,11 @@ void __init leon_init_timers(irq_handler
 #endif
 
 	}
+	return;
+bad:
+	printk(KERN_ERR "No Timer/irqctrl found\n");
+	BUG();
+	return;
 }
 
 void leon_clear_clock_irq(void)
diff -druNp linux-libre-2.6.37-gnu1/arch/sparc/kernel/module.c linux-libre-2.6.38-gnu1/arch/sparc/kernel/module.c
--- linux-libre-2.6.37-gnu1/arch/sparc/kernel/module.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sparc/kernel/module.c	2011-03-14 21:20:32.000000000 -0400
@@ -23,17 +23,11 @@
 
 static void *module_map(unsigned long size)
 {
-	struct vm_struct *area;
-
-	size = PAGE_ALIGN(size);
-	if (!size || size > MODULES_LEN)
-		return NULL;
-
-	area = __get_vm_area(size, VM_ALLOC, MODULES_VADDR, MODULES_END);
-	if (!area)
+	if (PAGE_ALIGN(size) > MODULES_LEN)
 		return NULL;
-
-	return __vmalloc_area(area, GFP_KERNEL, PAGE_KERNEL);
+	return __vmalloc_node_range(size, 1, MODULES_VADDR, MODULES_END,
+				GFP_KERNEL, PAGE_KERNEL, -1,
+				__builtin_return_address(0));
 }
 
 static char *dot2underscore(char *name)
diff -druNp linux-libre-2.6.37-gnu1/arch/sparc/kernel/nmi.c linux-libre-2.6.38-gnu1/arch/sparc/kernel/nmi.c
--- linux-libre-2.6.37-gnu1/arch/sparc/kernel/nmi.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sparc/kernel/nmi.c	2011-03-14 21:20:32.000000000 -0400
@@ -270,8 +270,6 @@ int __init nmi_init(void)
 			atomic_set(&nmi_active, -1);
 		}
 	}
-	if (!err)
-		init_hw_perf_events();
 
 	return err;
 }
diff -druNp linux-libre-2.6.37-gnu1/arch/sparc/kernel/pcr.c linux-libre-2.6.38-gnu1/arch/sparc/kernel/pcr.c
--- linux-libre-2.6.37-gnu1/arch/sparc/kernel/pcr.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sparc/kernel/pcr.c	2011-03-14 21:20:32.000000000 -0400
@@ -167,5 +167,3 @@ out_unregister:
 	unregister_perf_hsvc();
 	return err;
 }
-
-arch_initcall(pcr_arch_init);
diff -druNp linux-libre-2.6.37-gnu1/arch/sparc/kernel/perf_event.c linux-libre-2.6.38-gnu1/arch/sparc/kernel/perf_event.c
--- linux-libre-2.6.37-gnu1/arch/sparc/kernel/perf_event.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sparc/kernel/perf_event.c	2011-03-14 21:20:32.000000000 -0400
@@ -1307,20 +1307,23 @@ static bool __init supported_pmu(void)
 	return false;
 }
 
-void __init init_hw_perf_events(void)
+int __init init_hw_perf_events(void)
 {
 	pr_info("Performance events: ");
 
 	if (!supported_pmu()) {
 		pr_cont("No support for PMU type '%s'\n", sparc_pmu_type);
-		return;
+		return 0;
 	}
 
 	pr_cont("Supported PMU type is '%s'\n", sparc_pmu_type);
 
-	perf_pmu_register(&pmu);
+	perf_pmu_register(&pmu, "cpu", PERF_TYPE_RAW);
 	register_die_notifier(&perf_event_nmi_notifier);
+
+	return 0;
 }
+early_initcall(init_hw_perf_events);
 
 void perf_callchain_kernel(struct perf_callchain_entry *entry,
 			   struct pt_regs *regs)
diff -druNp linux-libre-2.6.37-gnu1/arch/sparc/kernel/prom_32.c linux-libre-2.6.38-gnu1/arch/sparc/kernel/prom_32.c
--- linux-libre-2.6.37-gnu1/arch/sparc/kernel/prom_32.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sparc/kernel/prom_32.c	2011-03-14 21:20:32.000000000 -0400
@@ -136,18 +136,29 @@ static void __init ebus_path_component(s
 /* "name:vendor:device@irq,addrlo" */
 static void __init ambapp_path_component(struct device_node *dp, char *tmp_buf)
 {
-	struct amba_prom_registers *regs; unsigned int *intr;
-	unsigned int *device, *vendor;
+	struct amba_prom_registers *regs;
+	unsigned int *intr, *device, *vendor, reg0;
 	struct property *prop;
+	int interrupt = 0;
 
+	/* In order to get a unique ID in the device tree (multiple AMBA devices
+	 * may have the same name) the node number is printed
+	 */
 	prop = of_find_property(dp, "reg", NULL);
-	if (!prop)
-		return;
-	regs = prop->value;
+	if (!prop) {
+		reg0 = (unsigned int)dp->phandle;
+	} else {
+		regs = prop->value;
+		reg0 = regs->phys_addr;
+	}
+
+	/* Not all cores have Interrupt */
 	prop = of_find_property(dp, "interrupts", NULL);
 	if (!prop)
-		return;
-	intr = prop->value;
+		intr = &interrupt; /* IRQ0 does not exist */
+	else
+		intr = prop->value;
+
 	prop = of_find_property(dp, "vendor", NULL);
 	if (!prop)
 		return;
@@ -159,7 +170,7 @@ static void __init ambapp_path_component
 
 	sprintf(tmp_buf, "%s:%d:%d@%x,%x",
 		dp->name, *vendor, *device,
-		*intr, regs->phys_addr);
+		*intr, reg0);
 }
 
 static void __init __build_path_component(struct device_node *dp, char *tmp_buf)
diff -druNp linux-libre-2.6.37-gnu1/arch/sparc/kernel/setup_32.c linux-libre-2.6.38-gnu1/arch/sparc/kernel/setup_32.c
--- linux-libre-2.6.37-gnu1/arch/sparc/kernel/setup_32.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sparc/kernel/setup_32.c	2011-03-14 21:20:32.000000000 -0400
@@ -185,7 +185,6 @@ static void __init boot_flags_init(char
 
 extern void sun4c_probe_vac(void);
 extern char cputypval;
-extern unsigned long start, end;
 
 extern unsigned short root_flags;
 extern unsigned short root_dev;
@@ -210,7 +209,7 @@ void __init setup_arch(char **cmdline_p)
 	int i;
 	unsigned long highest_paddr;
 
-	sparc_ttable = (struct tt_entry *) &start;
+	sparc_ttable = (struct tt_entry *) &trapbase;
 
 	/* Initialize PROM console and command line. */
 	*cmdline_p = prom_getbootargs();
diff -druNp linux-libre-2.6.37-gnu1/arch/sparc/kernel/smp_64.c linux-libre-2.6.38-gnu1/arch/sparc/kernel/smp_64.c
--- linux-libre-2.6.37-gnu1/arch/sparc/kernel/smp_64.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sparc/kernel/smp_64.c	2011-03-14 21:20:32.000000000 -0400
@@ -49,6 +49,7 @@
 #include <asm/mdesc.h>
 #include <asm/ldc.h>
 #include <asm/hypervisor.h>
+#include <asm/pcr.h>
 
 #include "cpumap.h"
 
@@ -1358,6 +1359,7 @@ void __cpu_die(unsigned int cpu)
 
 void __init smp_cpus_done(unsigned int max_cpus)
 {
+	pcr_arch_init();
 }
 
 void smp_send_reschedule(int cpu)
diff -druNp linux-libre-2.6.37-gnu1/arch/sparc/kernel/starfire.c linux-libre-2.6.38-gnu1/arch/sparc/kernel/starfire.c
--- linux-libre-2.6.37-gnu1/arch/sparc/kernel/starfire.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sparc/kernel/starfire.c	2011-03-14 21:20:32.000000000 -0400
@@ -24,7 +24,7 @@ int this_is_starfire = 0;
 void check_if_starfire(void)
 {
 	phandle ssnode = prom_finddevice("/ssp-serial");
-	if (ssnode != 0 && ssnode != -1)
+	if (ssnode != 0 && (s32)ssnode != -1)
 		this_is_starfire = 1;
 }
 
diff -druNp linux-libre-2.6.37-gnu1/arch/sparc/kernel/traps_64.c linux-libre-2.6.38-gnu1/arch/sparc/kernel/traps_64.c
--- linux-libre-2.6.37-gnu1/arch/sparc/kernel/traps_64.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sparc/kernel/traps_64.c	2011-03-14 21:20:32.000000000 -0400
@@ -622,7 +622,7 @@ static const char CHAFSR_PERR_msg[] =
 static const char CHAFSR_IERR_msg[] =
 	"Internal processor error";
 static const char CHAFSR_ISAP_msg[] =
-	"System request parity error on incoming addresss";
+	"System request parity error on incoming address";
 static const char CHAFSR_UCU_msg[] =
 	"Uncorrectable E-cache ECC error for ifetch/data";
 static const char CHAFSR_UCC_msg[] =
diff -druNp linux-libre-2.6.37-gnu1/arch/sparc/kernel/una_asm_32.S linux-libre-2.6.38-gnu1/arch/sparc/kernel/una_asm_32.S
--- linux-libre-2.6.37-gnu1/arch/sparc/kernel/una_asm_32.S	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sparc/kernel/una_asm_32.S	2011-03-14 21:20:32.000000000 -0400
@@ -24,9 +24,9 @@ retl_efault:
 	.globl	__do_int_store
 __do_int_store:
 	ld	[%o2], %g1
-	cmp	%1, 2
+	cmp	%o1, 2
 	be	2f
-	 cmp	%1, 4
+	 cmp	%o1, 4
 	be	1f
 	 srl	%g1, 24, %g2
 	srl	%g1, 16, %g7
diff -druNp linux-libre-2.6.37-gnu1/arch/sparc/lib/bitext.c linux-libre-2.6.38-gnu1/arch/sparc/lib/bitext.c
--- linux-libre-2.6.37-gnu1/arch/sparc/lib/bitext.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sparc/lib/bitext.c	2011-03-14 21:20:32.000000000 -0400
@@ -10,7 +10,7 @@
  */
 
 #include <linux/string.h>
-#include <linux/bitops.h>
+#include <linux/bitmap.h>
 
 #include <asm/bitext.h>
 
@@ -80,8 +80,7 @@ int bit_map_string_get(struct bit_map *t
 		while (test_bit(offset + i, t->map) == 0) {
 			i++;
 			if (i == len) {
-				for (i = 0; i < len; i++)
-					__set_bit(offset + i, t->map);
+				bitmap_set(t->map, offset, len);
 				if (offset == t->first_free)
 					t->first_free = find_next_zero_bit
 							(t->map, t->size,
diff -druNp linux-libre-2.6.37-gnu1/arch/sparc/mm/generic_32.c linux-libre-2.6.38-gnu1/arch/sparc/mm/generic_32.c
--- linux-libre-2.6.37-gnu1/arch/sparc/mm/generic_32.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sparc/mm/generic_32.c	2011-03-14 21:20:32.000000000 -0400
@@ -50,7 +50,7 @@ static inline int io_remap_pmd_range(str
 		end = PGDIR_SIZE;
 	offset -= address;
 	do {
-		pte_t * pte = pte_alloc_map(mm, pmd, address);
+		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);
diff -druNp linux-libre-2.6.37-gnu1/arch/sparc/mm/generic_64.c linux-libre-2.6.38-gnu1/arch/sparc/mm/generic_64.c
--- linux-libre-2.6.37-gnu1/arch/sparc/mm/generic_64.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sparc/mm/generic_64.c	2011-03-14 21:20:32.000000000 -0400
@@ -92,7 +92,7 @@ static inline int io_remap_pmd_range(str
 		end = PGDIR_SIZE;
 	offset -= address;
 	do {
-		pte_t * pte = pte_alloc_map(mm, pmd, address);
+		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);
diff -druNp linux-libre-2.6.37-gnu1/arch/sparc/mm/hugetlbpage.c linux-libre-2.6.38-gnu1/arch/sparc/mm/hugetlbpage.c
--- linux-libre-2.6.37-gnu1/arch/sparc/mm/hugetlbpage.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sparc/mm/hugetlbpage.c	2011-03-14 21:20:32.000000000 -0400
@@ -214,7 +214,7 @@ pte_t *huge_pte_alloc(struct mm_struct *
 	if (pud) {
 		pmd = pmd_alloc(mm, pud, addr);
 		if (pmd)
-			pte = pte_alloc_map(mm, pmd, addr);
+			pte = pte_alloc_map(mm, NULL, pmd, addr);
 	}
 	return pte;
 }
diff -druNp linux-libre-2.6.37-gnu1/arch/sparc/mm/sun4c.c linux-libre-2.6.38-gnu1/arch/sparc/mm/sun4c.c
--- linux-libre-2.6.37-gnu1/arch/sparc/mm/sun4c.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sparc/mm/sun4c.c	2011-03-14 21:20:32.000000000 -0400
@@ -435,16 +435,14 @@ void __init sun4c_probe_memerr_reg(void)
 
 static inline void sun4c_init_ss2_cache_bug(void)
 {
-	extern unsigned long start;
-
 	if ((idprom->id_machtype == (SM_SUN4C | SM_4C_SS2)) ||
 	    (idprom->id_machtype == (SM_SUN4C | SM_4C_IPX)) ||
 	    (idprom->id_machtype == (SM_SUN4C | SM_4C_ELC))) {
 		/* Whee.. */
 		printk("SS2 cache bug detected, uncaching trap table page\n");
-		sun4c_flush_page((unsigned int) &start);
-		sun4c_put_pte(((unsigned long) &start),
-			(sun4c_get_pte((unsigned long) &start) | _SUN4C_PAGE_NOCACHE));
+		sun4c_flush_page((unsigned int) &_start);
+		sun4c_put_pte(((unsigned long) &_start),
+			(sun4c_get_pte((unsigned long) &_start) | _SUN4C_PAGE_NOCACHE));
 	}
 }
 
diff -druNp linux-libre-2.6.37-gnu1/arch/sparc/prom/bootstr_32.c linux-libre-2.6.38-gnu1/arch/sparc/prom/bootstr_32.c
--- linux-libre-2.6.37-gnu1/arch/sparc/prom/bootstr_32.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sparc/prom/bootstr_32.c	2011-03-14 21:20:32.000000000 -0400
@@ -29,7 +29,8 @@ prom_getbootargs(void)
 		/* Start from 1 and go over fd(0,0,0)kernel */
 		for(iter = 1; iter < 8; iter++) {
 			arg = (*(romvec->pv_v0bootargs))->argv[iter];
-			if(arg == 0) break;
+			if (arg == NULL)
+				break;
 			while(*arg != 0) {
 				/* Leave place for space and null. */
 				if(cp >= barg_buf + BARG_LEN-2){
diff -druNp linux-libre-2.6.37-gnu1/arch/sparc/prom/console_32.c linux-libre-2.6.38-gnu1/arch/sparc/prom/console_32.c
--- linux-libre-2.6.37-gnu1/arch/sparc/prom/console_32.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sparc/prom/console_32.c	2011-03-14 21:20:32.000000000 -0400
@@ -27,13 +27,14 @@ static int prom_nbputchar(const char *bu
 	spin_lock_irqsave(&prom_lock, flags);
 	switch(prom_vers) {
 	case PROM_V0:
-		i = (*(romvec->pv_nbputchar))(*buf);
+		if ((*(romvec->pv_nbputchar))(*buf))
+			i = 1;
 		break;
 	case PROM_V2:
 	case PROM_V3:
 		if ((*(romvec->pv_v2devops).v2_dev_write)(*romvec->pv_v2bootargs.fd_stdout,
 							  buf, 0x1) == 1)
-			i = 0;
+			i = 1;
 		break;
 	default:
 		break;
@@ -47,7 +48,7 @@ void prom_console_write_buf(const char *
 {
 	while (len) {
 		int n = prom_nbputchar(buf);
-		if (n)
+		if (n < 0)
 			continue;
 		len--;
 		buf++;
diff -druNp linux-libre-2.6.37-gnu1/arch/sparc/prom/console_64.c linux-libre-2.6.38-gnu1/arch/sparc/prom/console_64.c
--- linux-libre-2.6.37-gnu1/arch/sparc/prom/console_64.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sparc/prom/console_64.c	2011-03-14 21:20:32.000000000 -0400
@@ -13,8 +13,6 @@
 #include <asm/system.h>
 #include <linux/string.h>
 
-extern int prom_stdin, prom_stdout;
-
 static int __prom_console_write_buf(const char *buf, int len)
 {
 	unsigned long args[7];
diff -druNp linux-libre-2.6.37-gnu1/arch/sparc/prom/devmap.c linux-libre-2.6.38-gnu1/arch/sparc/prom/devmap.c
--- linux-libre-2.6.37-gnu1/arch/sparc/prom/devmap.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sparc/prom/devmap.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,53 +0,0 @@
-/*
- * promdevmap.c:  Map device/IO areas to virtual addresses.
- *
- * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
- */
-
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-
-#include <asm/openprom.h>
-#include <asm/oplib.h>
-
-extern void restore_current(void);
-
-/* Just like the routines in palloc.c, these should not be used
- * by the kernel at all.  Bootloader facility mainly.  And again,
- * this is only available on V2 proms and above.
- */
-
-/* Map physical device address 'paddr' in IO space 'ios' of size
- * 'num_bytes' to a virtual address, with 'vhint' being a hint to
- * the prom as to where you would prefer the mapping.  We return
- * where the prom actually mapped it.
- */
-char *
-prom_mapio(char *vhint, int ios, unsigned int paddr, unsigned int num_bytes)
-{
-	unsigned long flags;
-	char *ret;
-
-	spin_lock_irqsave(&prom_lock, flags);
-	if((num_bytes == 0) || (paddr == 0)) ret = (char *) 0x0;
-	else
-	ret = (*(romvec->pv_v2devops.v2_dumb_mmap))(vhint, ios, paddr,
-						    num_bytes);
-	restore_current();
-	spin_unlock_irqrestore(&prom_lock, flags);
-	return ret;
-}
-
-/* Unmap an IO/device area that was mapped using the above routine. */
-void
-prom_unmapio(char *vaddr, unsigned int num_bytes)
-{
-	unsigned long flags;
-
-	if(num_bytes == 0x0) return;
-	spin_lock_irqsave(&prom_lock, flags);
-	(*(romvec->pv_v2devops.v2_dumb_munmap))(vaddr, num_bytes);
-	restore_current();
-	spin_unlock_irqrestore(&prom_lock, flags);
-}
diff -druNp linux-libre-2.6.37-gnu1/arch/sparc/prom/init_32.c linux-libre-2.6.38-gnu1/arch/sparc/prom/init_32.c
--- linux-libre-2.6.37-gnu1/arch/sparc/prom/init_32.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sparc/prom/init_32.c	2011-03-14 21:20:32.000000000 -0400
@@ -60,7 +60,7 @@ void __init prom_init(struct linux_romve
 	prom_nodeops = romvec->pv_nodeops;
 
 	prom_root_node = prom_getsibling(0);
-	if((prom_root_node == 0) || (prom_root_node == -1))
+	if ((prom_root_node == 0) || ((s32)prom_root_node == -1))
 		prom_halt();
 
 	if((((unsigned long) prom_nodeops) == 0) || 
diff -druNp linux-libre-2.6.37-gnu1/arch/sparc/prom/init_64.c linux-libre-2.6.38-gnu1/arch/sparc/prom/init_64.c
--- linux-libre-2.6.37-gnu1/arch/sparc/prom/init_64.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sparc/prom/init_64.c	2011-03-14 21:20:32.000000000 -0400
@@ -18,7 +18,7 @@
 char prom_version[80];
 
 /* The root node of the prom device tree. */
-int prom_stdin, prom_stdout;
+int prom_stdout;
 phandle prom_chosen_node;
 
 /* You must call prom_init() before you attempt to use any of the
@@ -35,14 +35,13 @@ void __init prom_init(void *cif_handler,
 	prom_cif_init(cif_handler, cif_stack);
 
 	prom_chosen_node = prom_finddevice(prom_chosen_path);
-	if (!prom_chosen_node || prom_chosen_node == -1)
+	if (!prom_chosen_node || (s32)prom_chosen_node == -1)
 		prom_halt();
 
-	prom_stdin = prom_getint(prom_chosen_node, "stdin");
 	prom_stdout = prom_getint(prom_chosen_node, "stdout");
 
 	node = prom_finddevice("/openprom");
-	if (!node || node == -1)
+	if (!node || (s32)node == -1)
 		prom_halt();
 
 	prom_getstring(node, "version", prom_version, sizeof(prom_version));
diff -druNp linux-libre-2.6.37-gnu1/arch/sparc/prom/Makefile linux-libre-2.6.38-gnu1/arch/sparc/prom/Makefile
--- linux-libre-2.6.37-gnu1/arch/sparc/prom/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sparc/prom/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -5,12 +5,10 @@ asflags := -ansi
 ccflags := -Werror
 
 lib-y                 := bootstr_$(BITS).o
-lib-$(CONFIG_SPARC32) += devmap.o
 lib-y                 += init_$(BITS).o
 lib-$(CONFIG_SPARC32) += memory.o
 lib-y                 += misc_$(BITS).o
 lib-$(CONFIG_SPARC32) += mp.o
-lib-$(CONFIG_SPARC32) += palloc.o
 lib-$(CONFIG_SPARC32) += ranges.o
 lib-$(CONFIG_SPARC32) += segment.o
 lib-y                 += console_$(BITS).o
diff -druNp linux-libre-2.6.37-gnu1/arch/sparc/prom/misc_32.c linux-libre-2.6.38-gnu1/arch/sparc/prom/misc_32.c
--- linux-libre-2.6.37-gnu1/arch/sparc/prom/misc_32.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sparc/prom/misc_32.c	2011-03-14 21:20:32.000000000 -0400
@@ -70,7 +70,7 @@ prom_cmdline(void)
 /* Drop into the prom, but completely terminate the program.
  * No chance of continuing.
  */
-void
+void __noreturn
 prom_halt(void)
 {
 	unsigned long flags;
diff -druNp linux-libre-2.6.37-gnu1/arch/sparc/prom/mp.c linux-libre-2.6.38-gnu1/arch/sparc/prom/mp.c
--- linux-libre-2.6.37-gnu1/arch/sparc/prom/mp.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sparc/prom/mp.c	2011-03-14 21:20:32.000000000 -0400
@@ -41,81 +41,3 @@ prom_startcpu(int cpunode, struct linux_
 
 	return ret;
 }
-
-/* Stop CPU with device prom-tree node 'cpunode'.
- * XXX Again, what does the return value really mean? XXX
- */
-int
-prom_stopcpu(int cpunode)
-{
-	int ret;
-	unsigned long flags;
-
-	spin_lock_irqsave(&prom_lock, flags);
-	switch(prom_vers) {
-	case PROM_V0:
-	case PROM_V2:
-	default:
-		ret = -1;
-		break;
-	case PROM_V3:
-		ret = (*(romvec->v3_cpustop))(cpunode);
-		break;
-	};
-	restore_current();
-	spin_unlock_irqrestore(&prom_lock, flags);
-
-	return ret;
-}
-
-/* Make CPU with device prom-tree node 'cpunode' idle.
- * XXX Return value, anyone? XXX
- */
-int
-prom_idlecpu(int cpunode)
-{
-	int ret;
-	unsigned long flags;
-
-	spin_lock_irqsave(&prom_lock, flags);
-	switch(prom_vers) {
-	case PROM_V0:
-	case PROM_V2:
-	default:
-		ret = -1;
-		break;
-	case PROM_V3:
-		ret = (*(romvec->v3_cpuidle))(cpunode);
-		break;
-	};
-	restore_current();
-	spin_unlock_irqrestore(&prom_lock, flags);
-
-	return ret;
-}
-
-/* Resume the execution of CPU with nodeid 'cpunode'.
- * XXX Come on, somebody has to know... XXX
- */
-int
-prom_restartcpu(int cpunode)
-{
-	int ret;
-	unsigned long flags;
-
-	spin_lock_irqsave(&prom_lock, flags);
-	switch(prom_vers) {
-	case PROM_V0:
-	case PROM_V2:
-	default:
-		ret = -1;
-		break;
-	case PROM_V3:
-		ret = (*(romvec->v3_cpuresume))(cpunode);
-		break;
-	};
-	restore_current();
-	spin_unlock_irqrestore(&prom_lock, flags);
-
-	return ret;
-}
diff -druNp linux-libre-2.6.37-gnu1/arch/sparc/prom/palloc.c linux-libre-2.6.38-gnu1/arch/sparc/prom/palloc.c
--- linux-libre-2.6.37-gnu1/arch/sparc/prom/palloc.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sparc/prom/palloc.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,43 +0,0 @@
-/*
- * palloc.c:  Memory allocation from the Sun PROM.
- *
- * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
- */
-
-#include <asm/openprom.h>
-#include <asm/oplib.h>
-
-/* You should not call these routines after memory management
- * has been initialized in the kernel, if fact you should not
- * use these if at all possible in the kernel.  They are mainly
- * to be used for a bootloader for temporary allocations which
- * it will free before jumping into the kernel it has loaded.
- *
- * Also, these routines don't work on V0 proms, only V2 and later.
- */
-
-/* Allocate a chunk of memory of size 'num_bytes' giving a suggestion
- * of virtual_hint as the preferred virtual base address of this chunk.
- * There are no guarantees that you will get the allocation, or that
- * the prom will abide by your "hint".  So check your return value.
- */
-char *
-prom_alloc(char *virtual_hint, unsigned int num_bytes)
-{
-	if(prom_vers == PROM_V0) return (char *) 0x0;
-	if(num_bytes == 0x0) return (char *) 0x0;
-	return (*(romvec->pv_v2devops.v2_dumb_mem_alloc))(virtual_hint, num_bytes);
-}
-
-/* Free a previously allocated chunk back to the prom at virtual address
- * 'vaddr' of size 'num_bytes'.  NOTE: This vaddr is not the hint you
- * used for the allocation, but the virtual address the prom actually
- * returned to you.  They may be have been the same, they may have not,
- * doesn't matter.
- */
-void
-prom_free(char *vaddr, unsigned int num_bytes)
-{
-	if((prom_vers == PROM_V0) || (num_bytes == 0x0)) return;
-	(*(romvec->pv_v2devops.v2_dumb_mem_free))(vaddr, num_bytes);
-}
diff -druNp linux-libre-2.6.37-gnu1/arch/sparc/prom/ranges.c linux-libre-2.6.38-gnu1/arch/sparc/prom/ranges.c
--- linux-libre-2.6.37-gnu1/arch/sparc/prom/ranges.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sparc/prom/ranges.c	2011-03-14 21:20:32.000000000 -0400
@@ -13,8 +13,8 @@
 #include <asm/types.h>
 #include <asm/system.h>
 
-struct linux_prom_ranges promlib_obio_ranges[PROMREG_MAX];
-int num_obio_ranges;
+static struct linux_prom_ranges promlib_obio_ranges[PROMREG_MAX];
+static int num_obio_ranges;
 
 /* Adjust register values based upon the ranges parameters. */
 static void
@@ -35,7 +35,7 @@ prom_adjust_regs(struct linux_prom_regis
 	}
 }
 
-void
+static void
 prom_adjust_ranges(struct linux_prom_ranges *ranges1, int nranges1,
 		   struct linux_prom_ranges *ranges2, int nranges2)
 {
diff -druNp linux-libre-2.6.37-gnu1/arch/sparc/prom/tree_32.c linux-libre-2.6.38-gnu1/arch/sparc/prom/tree_32.c
--- linux-libre-2.6.37-gnu1/arch/sparc/prom/tree_32.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sparc/prom/tree_32.c	2011-03-14 21:20:32.000000000 -0400
@@ -20,7 +20,7 @@ extern void restore_current(void);
 static char promlib_buf[128];
 
 /* Internal version of prom_getchild that does not alter return values. */
-phandle __prom_getchild(phandle node)
+static phandle __prom_getchild(phandle node)
 {
 	unsigned long flags;
 	phandle cnode;
@@ -40,11 +40,11 @@ phandle prom_getchild(phandle node)
 {
 	phandle cnode;
 
-	if (node == -1)
+	if ((s32)node == -1)
 		return 0;
 
 	cnode = __prom_getchild(node);
-	if (cnode == 0 || cnode == -1)
+	if (cnode == 0 || (s32)cnode == -1)
 		return 0;
 
 	return cnode;
@@ -52,7 +52,7 @@ phandle prom_getchild(phandle node)
 EXPORT_SYMBOL(prom_getchild);
 
 /* Internal version of prom_getsibling that does not alter return values. */
-phandle __prom_getsibling(phandle node)
+static phandle __prom_getsibling(phandle node)
 {
 	unsigned long flags;
 	phandle cnode;
@@ -72,11 +72,11 @@ phandle prom_getsibling(phandle node)
 {
 	phandle sibnode;
 
-	if (node == -1)
+	if ((s32)node == -1)
 		return 0;
 
 	sibnode = __prom_getsibling(node);
-	if (sibnode == 0 || sibnode == -1)
+	if (sibnode == 0 || (s32)sibnode == -1)
 		return 0;
 
 	return sibnode;
@@ -177,20 +177,6 @@ void prom_getstring(phandle node, char *
 EXPORT_SYMBOL(prom_getstring);
 
 
-/* Does the device at node 'node' have name 'name'?
- * YES = 1   NO = 0
- */
-int prom_nodematch(phandle node, char *name)
-{
-	int error;
-
-	static char namebuf[128];
-	error = prom_getproperty(node, "name", namebuf, sizeof(namebuf));
-	if (error == -1) return 0;
-	if(strcmp(namebuf, name) == 0) return 1;
-	return 0;
-}
-
 /* Search siblings at 'node_start' for a node with name
  * 'nodename'.  Return node if successful, zero if not.
  */
@@ -214,7 +200,7 @@ phandle prom_searchsiblings(phandle node
 EXPORT_SYMBOL(prom_searchsiblings);
 
 /* Interal version of nextprop that does not alter return values. */
-char *__prom_nextprop(phandle node, char * oprop)
+static char *__prom_nextprop(phandle node, char * oprop)
 {
 	unsigned long flags;
 	char *prop;
@@ -227,24 +213,13 @@ char *__prom_nextprop(phandle node, char
 	return prop;
 }
 
-/* Return the first property name for node 'node'. */
-/* buffer is unused argument, but as v9 uses it, we need to have the same interface */
-char *prom_firstprop(phandle node, char *bufer)
-{
-	if (node == 0 || node == -1)
-		return "";
-
-	return __prom_nextprop(node, "");
-}
-EXPORT_SYMBOL(prom_firstprop);
-
 /* Return the property type string after property type 'oprop'
  * at node 'node' .  Returns empty string if no more
  * property types for this node.
  */
 char *prom_nextprop(phandle node, char *oprop, char *buffer)
 {
-	if (node == 0 || node == -1)
+	if (node == 0 || (s32)node == -1)
 		return "";
 
 	return __prom_nextprop(node, oprop);
@@ -278,7 +253,7 @@ phandle prom_finddevice(char *name)
 				if (d != s + 3 && (!*d || *d == '/')
 				    && d <= s + 3 + 8) {
 					node2 = node;
-					while (node2 && node2 != -1) {
+					while (node2 && (s32)node2 != -1) {
 						if (prom_getproperty (node2, "reg", (char *)reg, sizeof (reg)) > 0) {
 							if (which_io == reg[0].which_io && phys_addr == reg[0].phys_addr) {
 								node = node2;
@@ -286,7 +261,7 @@ phandle prom_finddevice(char *name)
 							}
 						}
 						node2 = prom_getsibling(node2);
-						if (!node2 || node2 == -1)
+						if (!node2 || (s32)node2 == -1)
 							break;
 						node2 = prom_searchsiblings(prom_getsibling(node2), nbuf);
 					}
@@ -299,19 +274,6 @@ phandle prom_finddevice(char *name)
 }
 EXPORT_SYMBOL(prom_finddevice);
 
-int prom_node_has_property(phandle node, char *prop)
-{
-	char *current_property = "";
-
-	do {
-		current_property = prom_nextprop(node, current_property, NULL);
-		if(!strcmp(current_property, prop))
-		   return 1;
-	} while (*current_property);
-	return 0;
-}
-EXPORT_SYMBOL(prom_node_has_property);
-
 /* Set property 'pname' at node 'node' to value 'value' which has a length
  * of 'size' bytes.  Return the number of bytes the prom accepted.
  */
@@ -320,8 +282,10 @@ int prom_setprop(phandle node, const cha
 	unsigned long flags;
 	int ret;
 
-	if(size == 0) return 0;
-	if((pname == 0) || (value == 0)) return 0;
+	if (size == 0)
+		return 0;
+	if ((pname == NULL) || (value == NULL))
+		return 0;
 	spin_lock_irqsave(&prom_lock, flags);
 	ret = prom_nodeops->no_setprop(node, pname, value, size);
 	restore_current();
@@ -339,6 +303,7 @@ phandle prom_inst2pkg(int inst)
 	node = (*romvec->pv_v2devops.v2_inst2pkg)(inst);
 	restore_current();
 	spin_unlock_irqrestore(&prom_lock, flags);
-	if (node == -1) return 0;
+	if ((s32)node == -1)
+		return 0;
 	return node;
 }
diff -druNp linux-libre-2.6.37-gnu1/arch/sparc/prom/tree_64.c linux-libre-2.6.38-gnu1/arch/sparc/prom/tree_64.c
--- linux-libre-2.6.37-gnu1/arch/sparc/prom/tree_64.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/sparc/prom/tree_64.c	2011-03-14 21:20:32.000000000 -0400
@@ -43,10 +43,10 @@ inline phandle prom_getchild(phandle nod
 {
 	phandle cnode;
 
-	if (node == -1)
+	if ((s32)node == -1)
 		return 0;
 	cnode = __prom_getchild(node);
-	if (cnode == -1)
+	if ((s32)cnode == -1)
 		return 0;
 	return cnode;
 }
@@ -56,10 +56,10 @@ inline phandle prom_getparent(phandle no
 {
 	phandle cnode;
 
-	if (node == -1)
+	if ((s32)node == -1)
 		return 0;
 	cnode = prom_node_to_node("parent", node);
-	if (cnode == -1)
+	if ((s32)cnode == -1)
 		return 0;
 	return cnode;
 }
@@ -76,10 +76,10 @@ inline phandle prom_getsibling(phandle n
 {
 	phandle sibnode;
 
-	if (node == -1)
+	if ((s32)node == -1)
 		return 0;
 	sibnode = __prom_getsibling(node);
-	if (sibnode == -1)
+	if ((s32)sibnode == -1)
 		return 0;
 
 	return sibnode;
@@ -240,7 +240,7 @@ inline char *prom_firstprop(phandle node
 	unsigned long args[7];
 
 	*buffer = 0;
-	if (node == -1)
+	if ((s32)node == -1)
 		return buffer;
 
 	args[0] = (unsigned long) prom_nextprop_name;
@@ -266,7 +266,7 @@ inline char *prom_nextprop(phandle node,
 	unsigned long args[7];
 	char buf[32];
 
-	if (node == -1) {
+	if ((s32)node == -1) {
 		*buffer = 0;
 		return buffer;
 	}
@@ -369,7 +369,7 @@ inline phandle prom_inst2pkg(int inst)
 	p1275_cmd_direct(args);
 
 	node = (int) args[4];
-	if (node == -1)
+	if ((s32)node == -1)
 		return 0;
 	return node;
 }
diff -druNp linux-libre-2.6.37-gnu1/arch/tile/configs/tile_defconfig linux-libre-2.6.38-gnu1/arch/tile/configs/tile_defconfig
--- linux-libre-2.6.37-gnu1/arch/tile/configs/tile_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/tile/configs/tile_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -3,7 +3,7 @@ CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_INITRAMFS_SOURCE="usr/contents.txt"
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 # CONFIG_COMPAT_BRK is not set
 CONFIG_PROFILING=y
 CONFIG_MODULES=y
diff -druNp linux-libre-2.6.37-gnu1/arch/tile/Kconfig linux-libre-2.6.38-gnu1/arch/tile/Kconfig
--- linux-libre-2.6.37-gnu1/arch/tile/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/tile/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -1,24 +1,33 @@
 # For a description of the syntax of this configuration file,
 # see Documentation/kbuild/config-language.txt.
 
-config MMU
-	def_bool y
-
-config GENERIC_CSUM
-	def_bool y
-
-config GENERIC_HARDIRQS
+config TILE
 	def_bool y
+	select HAVE_KVM if !TILEGX
+	select GENERIC_FIND_FIRST_BIT
+	select GENERIC_FIND_NEXT_BIT
+	select USE_GENERIC_SMP_HELPERS
+	select CC_OPTIMIZE_FOR_SIZE
+	select HAVE_GENERIC_HARDIRQS
+	select GENERIC_IRQ_PROBE
+	select GENERIC_PENDING_IRQ if SMP
 
-config GENERIC_HARDIRQS_NO__DO_IRQ
-	def_bool y
+# FIXME: investigate whether we need/want these options.
+#	select HAVE_IOREMAP_PROT
+#       select HAVE_OPTPROBES
+#       select HAVE_REGS_AND_STACK_ACCESS_API
+#       select HAVE_HW_BREAKPOINT
+#       select PERF_EVENTS
+#       select HAVE_USER_RETURN_NOTIFIER
+#       config NO_BOOTMEM
+#       config ARCH_SUPPORTS_DEBUG_PAGEALLOC
+#       config HUGETLB_PAGE_SIZE_VARIABLE
 
-config GENERIC_IRQ_PROBE
+config MMU
 	def_bool y
 
-config GENERIC_PENDING_IRQ
+config GENERIC_CSUM
 	def_bool y
-	depends on GENERIC_HARDIRQS && SMP
 
 config SEMAPHORE_SLEEPERS
 	def_bool y
@@ -97,26 +106,6 @@ config HVC_TILE
 	select HVC_DRIVER
 	def_bool y
 
-config TILE
-	def_bool y
-	select HAVE_KVM if !TILEGX
-	select GENERIC_FIND_FIRST_BIT
-	select GENERIC_FIND_NEXT_BIT
-	select USE_GENERIC_SMP_HELPERS
-	select CC_OPTIMIZE_FOR_SIZE
-
-# FIXME: investigate whether we need/want these options.
-#	select HAVE_IOREMAP_PROT
-#       select HAVE_OPTPROBES
-#       select HAVE_REGS_AND_STACK_ACCESS_API
-#       select HAVE_HW_BREAKPOINT
-#       select PERF_EVENTS
-#       select HAVE_USER_RETURN_NOTIFIER
-#       config NO_BOOTMEM
-#       config ARCH_SUPPORTS_DEBUG_PAGEALLOC
-#       config HUGETLB_PAGE_SIZE_VARIABLE
-
-
 # Please note: TILE-Gx support is not yet finalized; this is
 # the preliminary support.  TILE-Gx drivers are only provided
 # with the alpha or beta test versions for Tilera customers.
@@ -220,7 +209,7 @@ config FORCE_MAX_ZONEORDER
 
 choice
 	depends on !TILEGX
-	prompt "Memory split" if EMBEDDED
+	prompt "Memory split" if EXPERT
 	default VMSPLIT_3G
 	---help---
 	  Select the desired split between kernel and user memory.
diff -druNp linux-libre-2.6.37-gnu1/arch/tile/Kconfig.debug linux-libre-2.6.38-gnu1/arch/tile/Kconfig.debug
--- linux-libre-2.6.37-gnu1/arch/tile/Kconfig.debug	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/tile/Kconfig.debug	2011-03-14 21:20:32.000000000 -0400
@@ -3,7 +3,7 @@ menu "Kernel hacking"
 source "lib/Kconfig.debug"
 
 config EARLY_PRINTK
-	bool "Early printk" if EMBEDDED && DEBUG_KERNEL
+	bool "Early printk" if EXPERT && DEBUG_KERNEL
 	default y
 	help
 	  Write kernel log output directly via the hypervisor console.
diff -druNp linux-libre-2.6.37-gnu1/arch/um/defconfig linux-libre-2.6.38-gnu1/arch/um/defconfig
--- linux-libre-2.6.37-gnu1/arch/um/defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/um/defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -133,7 +133,7 @@ CONFIG_SYSFS_DEPRECATED=y
 # CONFIG_BLK_DEV_INITRD is not set
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 CONFIG_SYSCTL=y
-# CONFIG_EMBEDDED is not set
+# CONFIG_EXPERT is not set
 CONFIG_UID16=y
 CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
diff -druNp linux-libre-2.6.37-gnu1/arch/um/drivers/line.c linux-libre-2.6.38-gnu1/arch/um/drivers/line.c
--- linux-libre-2.6.37-gnu1/arch/um/drivers/line.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/um/drivers/line.c	2011-03-14 21:20:32.000000000 -0400
@@ -821,12 +821,12 @@ void register_winch_irq(int fd, int tty_
 
 static void unregister_winch(struct tty_struct *tty)
 {
-	struct list_head *ele;
+	struct list_head *ele, *next;
 	struct winch *winch;
 
 	spin_lock(&winch_handler_lock);
 
-	list_for_each(ele, &winch_handlers) {
+	list_for_each_safe(ele, next, &winch_handlers) {
 		winch = list_entry(ele, struct winch, list);
 		if (winch->tty == tty) {
 			free_winch(winch, 1);
diff -druNp linux-libre-2.6.37-gnu1/arch/um/drivers/mmapper_kern.c linux-libre-2.6.38-gnu1/arch/um/drivers/mmapper_kern.c
--- linux-libre-2.6.37-gnu1/arch/um/drivers/mmapper_kern.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/um/drivers/mmapper_kern.c	2011-03-14 21:20:32.000000000 -0400
@@ -37,13 +37,7 @@ static ssize_t mmapper_write(struct file
 	if (*ppos > mmapper_size)
 		return -EINVAL;
 
-	if (count > mmapper_size - *ppos)
-		count = mmapper_size - *ppos;
-
-	if (copy_from_user(&v_buf[*ppos], buf, count))
-		return -EFAULT;
-
-	return count;
+	return simple_write_to_buffer(v_buf, mmapper_size, ppos, buf, count);
 }
 
 static long mmapper_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
@@ -137,3 +131,4 @@ module_exit(mmapper_exit);
 
 MODULE_AUTHOR("Greg Lonnon <glonnon@ridgerun.com>");
 MODULE_DESCRIPTION("DSPLinux simulator mmapper driver");
+MODULE_LICENSE("GPL");
diff -druNp linux-libre-2.6.37-gnu1/arch/um/Kconfig.common linux-libre-2.6.38-gnu1/arch/um/Kconfig.common
--- linux-libre-2.6.37-gnu1/arch/um/Kconfig.common	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/um/Kconfig.common	2011-03-14 21:20:32.000000000 -0400
@@ -3,14 +3,10 @@ config DEFCONFIG_LIST
 	option defconfig_list
 	default "arch/$ARCH/defconfig"
 
-# UML uses the generic IRQ subsystem
-config GENERIC_HARDIRQS
-	bool
-	default y
-
 config UML
 	bool
 	default y
+	select HAVE_GENERIC_HARDIRQS
 
 config MMU
 	bool
diff -druNp linux-libre-2.6.37-gnu1/arch/um/Kconfig.um linux-libre-2.6.38-gnu1/arch/um/Kconfig.um
--- linux-libre-2.6.37-gnu1/arch/um/Kconfig.um	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/um/Kconfig.um	2011-03-14 21:20:32.000000000 -0400
@@ -120,9 +120,6 @@ config SMP
 
 	  If you don't know what to do, say N.
 
-config GENERIC_HARDIRQS_NO__DO_IRQ
-	def_bool y
-
 config NR_CPUS
 	int "Maximum number of CPUs (2-32)"
 	range 2 32
@@ -131,7 +128,7 @@ config NR_CPUS
 
 config HIGHMEM
 	bool "Highmem support (EXPERIMENTAL)"
-	depends on !64BIT && EXPERIMENTAL
+	depends on !64BIT && BROKEN
 	default n
 	help
 	  This was used to allow UML to run with big amounts of memory.
diff -druNp linux-libre-2.6.37-gnu1/arch/um/kernel/skas/mmu.c linux-libre-2.6.38-gnu1/arch/um/kernel/skas/mmu.c
--- linux-libre-2.6.37-gnu1/arch/um/kernel/skas/mmu.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/um/kernel/skas/mmu.c	2011-03-14 21:20:32.000000000 -0400
@@ -31,7 +31,7 @@ static int init_stub_pte(struct mm_struc
 	if (!pmd)
 		goto out_pmd;
 
-	pte = pte_alloc_map(mm, pmd, proc);
+	pte = pte_alloc_map(mm, NULL, pmd, proc);
 	if (!pte)
 		goto out_pte;
 
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/boot/compressed/head_64.S linux-libre-2.6.38-gnu1/arch/x86/boot/compressed/head_64.S
--- linux-libre-2.6.37-gnu1/arch/x86/boot/compressed/head_64.S	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/boot/compressed/head_64.S	2011-03-14 21:20:32.000000000 -0400
@@ -182,7 +182,7 @@ no_longmode:
 	hlt
 	jmp     1b
 
-#include "../../kernel/verify_cpu_64.S"
+#include "../../kernel/verify_cpu.S"
 
 	/*
 	 * Be careful here startup_64 needs to be at a predictable
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/boot/compressed/Makefile linux-libre-2.6.38-gnu1/arch/x86/boot/compressed/Makefile
--- linux-libre-2.6.37-gnu1/arch/x86/boot/compressed/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/boot/compressed/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -4,7 +4,7 @@
 # create a compressed vmlinux image from the original vmlinux
 #
 
-targets := vmlinux.lds vmlinux vmlinux.bin vmlinux.bin.gz vmlinux.bin.bz2 vmlinux.bin.lzma vmlinux.bin.lzo head_$(BITS).o misc.o string.o cmdline.o early_serial_console.o piggy.o
+targets := vmlinux.lds vmlinux vmlinux.bin vmlinux.bin.gz vmlinux.bin.bz2 vmlinux.bin.lzma vmlinux.bin.xz vmlinux.bin.lzo head_$(BITS).o misc.o string.o cmdline.o early_serial_console.o piggy.o
 
 KBUILD_CFLAGS := -m$(BITS) -D__KERNEL__ $(LINUX_INCLUDE) -O2
 KBUILD_CFLAGS += -fno-strict-aliasing -fPIC
@@ -49,12 +49,15 @@ $(obj)/vmlinux.bin.bz2: $(vmlinux.bin.al
 	$(call if_changed,bzip2)
 $(obj)/vmlinux.bin.lzma: $(vmlinux.bin.all-y) FORCE
 	$(call if_changed,lzma)
+$(obj)/vmlinux.bin.xz: $(vmlinux.bin.all-y) FORCE
+	$(call if_changed,xzkern)
 $(obj)/vmlinux.bin.lzo: $(vmlinux.bin.all-y) FORCE
 	$(call if_changed,lzo)
 
 suffix-$(CONFIG_KERNEL_GZIP)	:= gz
 suffix-$(CONFIG_KERNEL_BZIP2)	:= bz2
 suffix-$(CONFIG_KERNEL_LZMA)	:= lzma
+suffix-$(CONFIG_KERNEL_XZ)	:= xz
 suffix-$(CONFIG_KERNEL_LZO) 	:= lzo
 
 quiet_cmd_mkpiggy = MKPIGGY $@
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/boot/compressed/misc.c linux-libre-2.6.38-gnu1/arch/x86/boot/compressed/misc.c
--- linux-libre-2.6.37-gnu1/arch/x86/boot/compressed/misc.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/boot/compressed/misc.c	2011-03-14 21:20:32.000000000 -0400
@@ -139,6 +139,10 @@ static int lines, cols;
 #include "../../../../lib/decompress_unlzma.c"
 #endif
 
+#ifdef CONFIG_KERNEL_XZ
+#include "../../../../lib/decompress_unxz.c"
+#endif
+
 #ifdef CONFIG_KERNEL_LZO
 #include "../../../../lib/decompress_unlzo.c"
 #endif
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/boot/compressed/mkpiggy.c linux-libre-2.6.38-gnu1/arch/x86/boot/compressed/mkpiggy.c
--- linux-libre-2.6.37-gnu1/arch/x86/boot/compressed/mkpiggy.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/boot/compressed/mkpiggy.c	2011-03-14 21:20:32.000000000 -0400
@@ -62,7 +62,12 @@ int main(int argc, char *argv[])
 	if (fseek(f, -4L, SEEK_END)) {
 		perror(argv[1]);
 	}
-	fread(&olen, sizeof olen, 1, f);
+
+	if (fread(&olen, sizeof(olen), 1, f) != 1) {
+		perror(argv[1]);
+		return 1;
+	}
+
 	ilen = ftell(f);
 	olen = getle32(&olen);
 	fclose(f);
@@ -74,7 +79,7 @@ int main(int argc, char *argv[])
 
 	offs = (olen > ilen) ? olen - ilen : 0;
 	offs += olen >> 12;	/* Add 8 bytes for each 32K block */
-	offs += 32*1024 + 18;	/* Add 32K + 18 bytes slack */
+	offs += 64*1024 + 128;	/* Add 64K + 128 bytes slack */
 	offs = (offs+4095) & ~4095; /* Round to a 4K boundary */
 
 	printf(".section \".rodata..compressed\",\"a\",@progbits\n");
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/crypto/aesni-intel_asm.S linux-libre-2.6.38-gnu1/arch/x86/crypto/aesni-intel_asm.S
--- linux-libre-2.6.37-gnu1/arch/x86/crypto/aesni-intel_asm.S	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/crypto/aesni-intel_asm.S	2011-03-14 21:20:32.000000000 -0400
@@ -9,6 +9,20 @@
  *            Vinodh Gopal <vinodh.gopal@intel.com>
  *            Kahraman Akdemir
  *
+ * Added RFC4106 AES-GCM support for 128-bit keys under the AEAD
+ * interface for 64-bit kernels.
+ *    Authors: Erdinc Ozturk (erdinc.ozturk@intel.com)
+ *             Aidan O'Mahony (aidan.o.mahony@intel.com)
+ *             Adrian Hoban <adrian.hoban@intel.com>
+ *             James Guilford (james.guilford@intel.com)
+ *             Gabriele Paoloni <gabriele.paoloni@intel.com>
+ *             Tadeusz Struk (tadeusz.struk@intel.com)
+ *             Wajdi Feghali (wajdi.k.feghali@intel.com)
+ *    Copyright (c) 2010, Intel Corporation.
+ *
+ * Ported x86_64 version to x86:
+ *    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
@@ -18,8 +32,62 @@
 #include <linux/linkage.h>
 #include <asm/inst.h>
 
+#ifdef __x86_64__
+.data
+POLY:   .octa 0xC2000000000000000000000000000001
+TWOONE: .octa 0x00000001000000000000000000000001
+
+# order of these constants should not change.
+# more specifically, ALL_F should follow SHIFT_MASK,
+# and ZERO should follow ALL_F
+
+SHUF_MASK:  .octa 0x000102030405060708090A0B0C0D0E0F
+MASK1:      .octa 0x0000000000000000ffffffffffffffff
+MASK2:      .octa 0xffffffffffffffff0000000000000000
+SHIFT_MASK: .octa 0x0f0e0d0c0b0a09080706050403020100
+ALL_F:      .octa 0xffffffffffffffffffffffffffffffff
+ZERO:       .octa 0x00000000000000000000000000000000
+ONE:        .octa 0x00000000000000000000000000000001
+F_MIN_MASK: .octa 0xf1f2f3f4f5f6f7f8f9fafbfcfdfeff0
+dec:        .octa 0x1
+enc:        .octa 0x2
+
+
 .text
 
+
+#define	STACK_OFFSET    8*3
+#define	HashKey		16*0	// store HashKey <<1 mod poly here
+#define	HashKey_2	16*1	// store HashKey^2 <<1 mod poly here
+#define	HashKey_3	16*2	// store HashKey^3 <<1 mod poly here
+#define	HashKey_4	16*3	// store HashKey^4 <<1 mod poly here
+#define	HashKey_k	16*4	// store XOR of High 64 bits and Low 64
+				// bits of  HashKey <<1 mod poly here
+				//(for Karatsuba purposes)
+#define	HashKey_2_k	16*5	// store XOR of High 64 bits and Low 64
+				// bits of  HashKey^2 <<1 mod poly here
+				// (for Karatsuba purposes)
+#define	HashKey_3_k	16*6	// store XOR of High 64 bits and Low 64
+				// bits of  HashKey^3 <<1 mod poly here
+				// (for Karatsuba purposes)
+#define	HashKey_4_k	16*7	// store XOR of High 64 bits and Low 64
+				// bits of  HashKey^4 <<1 mod poly here
+				// (for Karatsuba purposes)
+#define	VARIABLE_OFFSET	16*8
+
+#define arg1 rdi
+#define arg2 rsi
+#define arg3 rdx
+#define arg4 rcx
+#define arg5 r8
+#define arg6 r9
+#define arg7 STACK_OFFSET+8(%r14)
+#define arg8 STACK_OFFSET+16(%r14)
+#define arg9 STACK_OFFSET+24(%r14)
+#define arg10 STACK_OFFSET+32(%r14)
+#endif
+
+
 #define STATE1	%xmm0
 #define STATE2	%xmm4
 #define STATE3	%xmm5
@@ -32,12 +100,16 @@
 #define IN	IN1
 #define KEY	%xmm2
 #define IV	%xmm3
+
 #define BSWAP_MASK %xmm10
 #define CTR	%xmm11
 #define INC	%xmm12
 
+#ifdef __x86_64__
+#define AREG	%rax
 #define KEYP	%rdi
 #define OUTP	%rsi
+#define UKEYP	OUTP
 #define INP	%rdx
 #define LEN	%rcx
 #define IVP	%r8
@@ -46,6 +118,1588 @@
 #define TKEYP	T1
 #define T2	%r11
 #define TCTR_LOW T2
+#else
+#define AREG	%eax
+#define KEYP	%edi
+#define OUTP	AREG
+#define UKEYP	OUTP
+#define INP	%edx
+#define LEN	%esi
+#define IVP	%ebp
+#define KLEN	%ebx
+#define T1	%ecx
+#define TKEYP	T1
+#endif
+
+
+#ifdef __x86_64__
+/* GHASH_MUL MACRO to implement: Data*HashKey mod (128,127,126,121,0)
+*
+*
+* Input: A and B (128-bits each, bit-reflected)
+* Output: C = A*B*x mod poly, (i.e. >>1 )
+* To compute GH = GH*HashKey mod poly, give HK = HashKey<<1 mod poly as input
+* GH = GH * HK * x mod poly which is equivalent to GH*HashKey mod poly.
+*
+*/
+.macro GHASH_MUL GH HK TMP1 TMP2 TMP3 TMP4 TMP5
+	movdqa	  \GH, \TMP1
+	pshufd	  $78, \GH, \TMP2
+	pshufd	  $78, \HK, \TMP3
+	pxor	  \GH, \TMP2            # TMP2 = a1+a0
+	pxor	  \HK, \TMP3            # TMP3 = b1+b0
+	PCLMULQDQ 0x11, \HK, \TMP1     # TMP1 = a1*b1
+	PCLMULQDQ 0x00, \HK, \GH       # GH = a0*b0
+	PCLMULQDQ 0x00, \TMP3, \TMP2   # TMP2 = (a0+a1)*(b1+b0)
+	pxor	  \GH, \TMP2
+	pxor	  \TMP1, \TMP2          # TMP2 = (a0*b0)+(a1*b0)
+	movdqa	  \TMP2, \TMP3
+	pslldq	  $8, \TMP3             # left shift TMP3 2 DWs
+	psrldq	  $8, \TMP2             # right shift TMP2 2 DWs
+	pxor	  \TMP3, \GH
+	pxor	  \TMP2, \TMP1          # TMP2:GH holds the result of GH*HK
+
+        # first phase of the reduction
+
+	movdqa    \GH, \TMP2
+	movdqa    \GH, \TMP3
+	movdqa    \GH, \TMP4            # copy GH into TMP2,TMP3 and TMP4
+					# in in order to perform
+					# independent shifts
+	pslld     $31, \TMP2            # packed right shift <<31
+	pslld     $30, \TMP3            # packed right shift <<30
+	pslld     $25, \TMP4            # packed right shift <<25
+	pxor      \TMP3, \TMP2          # xor the shifted versions
+	pxor      \TMP4, \TMP2
+	movdqa    \TMP2, \TMP5
+	psrldq    $4, \TMP5             # right shift TMP5 1 DW
+	pslldq    $12, \TMP2            # left shift TMP2 3 DWs
+	pxor      \TMP2, \GH
+
+        # second phase of the reduction
+
+	movdqa    \GH,\TMP2             # copy GH into TMP2,TMP3 and TMP4
+					# in in order to perform
+					# independent shifts
+	movdqa    \GH,\TMP3
+	movdqa    \GH,\TMP4
+	psrld     $1,\TMP2              # packed left shift >>1
+	psrld     $2,\TMP3              # packed left shift >>2
+	psrld     $7,\TMP4              # packed left shift >>7
+	pxor      \TMP3,\TMP2		# xor the shifted versions
+	pxor      \TMP4,\TMP2
+	pxor      \TMP5, \TMP2
+	pxor      \TMP2, \GH
+	pxor      \TMP1, \GH            # result is in TMP1
+.endm
+
+/*
+* if a = number of total plaintext bytes
+* b = floor(a/16)
+* num_initial_blocks = b mod 4
+* encrypt the initial num_initial_blocks blocks and apply ghash on
+* the ciphertext
+* %r10, %r11, %r12, %rax, %xmm5, %xmm6, %xmm7, %xmm8, %xmm9 registers
+* are clobbered
+* arg1, %arg2, %arg3, %r14 are used as a pointer only, not modified
+*/
+
+
+.macro INITIAL_BLOCKS_DEC num_initial_blocks TMP1 TMP2 TMP3 TMP4 TMP5 XMM0 XMM1 \
+XMM2 XMM3 XMM4 XMMDst TMP6 TMP7 i i_seq operation
+	mov	   arg7, %r10           # %r10 = AAD
+	mov	   arg8, %r12           # %r12 = aadLen
+	mov	   %r12, %r11
+	pxor	   %xmm\i, %xmm\i
+_get_AAD_loop\num_initial_blocks\operation:
+	movd	   (%r10), \TMP1
+	pslldq	   $12, \TMP1
+	psrldq	   $4, %xmm\i
+	pxor	   \TMP1, %xmm\i
+	add	   $4, %r10
+	sub	   $4, %r12
+	jne	   _get_AAD_loop\num_initial_blocks\operation
+	cmp	   $16, %r11
+	je	   _get_AAD_loop2_done\num_initial_blocks\operation
+	mov	   $16, %r12
+_get_AAD_loop2\num_initial_blocks\operation:
+	psrldq	   $4, %xmm\i
+	sub	   $4, %r12
+	cmp	   %r11, %r12
+	jne	   _get_AAD_loop2\num_initial_blocks\operation
+_get_AAD_loop2_done\num_initial_blocks\operation:
+        movdqa     SHUF_MASK(%rip), %xmm14
+	PSHUFB_XMM   %xmm14, %xmm\i # byte-reflect the AAD data
+
+	xor	   %r11, %r11 # initialise the data pointer offset as zero
+
+        # start AES for num_initial_blocks blocks
+
+	mov	   %arg5, %rax                      # %rax = *Y0
+	movdqu	   (%rax), \XMM0                    # XMM0 = Y0
+        movdqa     SHUF_MASK(%rip), %xmm14
+	PSHUFB_XMM   %xmm14, \XMM0
+
+.if (\i == 5) || (\i == 6) || (\i == 7)
+.irpc index, \i_seq
+	paddd	   ONE(%rip), \XMM0                 # INCR Y0
+	movdqa	   \XMM0, %xmm\index
+        movdqa     SHUF_MASK(%rip), %xmm14
+	PSHUFB_XMM   %xmm14, %xmm\index      # perform a 16 byte swap
+
+.endr
+.irpc index, \i_seq
+	pxor	   16*0(%arg1), %xmm\index
+.endr
+.irpc index, \i_seq
+	movaps 0x10(%rdi), \TMP1
+	AESENC     \TMP1, %xmm\index          # Round 1
+.endr
+.irpc index, \i_seq
+	movaps 0x20(%arg1), \TMP1
+	AESENC     \TMP1, %xmm\index          # Round 2
+.endr
+.irpc index, \i_seq
+	movaps 0x30(%arg1), \TMP1
+	AESENC     \TMP1, %xmm\index          # Round 2
+.endr
+.irpc index, \i_seq
+	movaps 0x40(%arg1), \TMP1
+	AESENC     \TMP1, %xmm\index          # Round 2
+.endr
+.irpc index, \i_seq
+	movaps 0x50(%arg1), \TMP1
+	AESENC     \TMP1, %xmm\index          # Round 2
+.endr
+.irpc index, \i_seq
+	movaps 0x60(%arg1), \TMP1
+	AESENC     \TMP1, %xmm\index          # Round 2
+.endr
+.irpc index, \i_seq
+	movaps 0x70(%arg1), \TMP1
+	AESENC     \TMP1, %xmm\index          # Round 2
+.endr
+.irpc index, \i_seq
+	movaps 0x80(%arg1), \TMP1
+	AESENC     \TMP1, %xmm\index          # Round 2
+.endr
+.irpc index, \i_seq
+	movaps 0x90(%arg1), \TMP1
+	AESENC     \TMP1, %xmm\index          # Round 2
+.endr
+.irpc index, \i_seq
+	movaps 0xa0(%arg1), \TMP1
+	AESENCLAST \TMP1, %xmm\index         # Round 10
+.endr
+.irpc index, \i_seq
+	movdqu	   (%arg3 , %r11, 1), \TMP1
+	pxor	   \TMP1, %xmm\index
+	movdqu	   %xmm\index, (%arg2 , %r11, 1)
+	# write back plaintext/ciphertext for num_initial_blocks
+	add	   $16, %r11
+
+	movdqa     \TMP1, %xmm\index
+        movdqa     SHUF_MASK(%rip), %xmm14
+	PSHUFB_XMM	   %xmm14, %xmm\index
+
+		# prepare plaintext/ciphertext for GHASH computation
+.endr
+.endif
+	GHASH_MUL  %xmm\i, \TMP3, \TMP1, \TMP2, \TMP4, \TMP5, \XMM1
+        # apply GHASH on num_initial_blocks blocks
+
+.if \i == 5
+        pxor       %xmm5, %xmm6
+	GHASH_MUL  %xmm6, \TMP3, \TMP1, \TMP2, \TMP4, \TMP5, \XMM1
+        pxor       %xmm6, %xmm7
+	GHASH_MUL  %xmm7, \TMP3, \TMP1, \TMP2, \TMP4, \TMP5, \XMM1
+        pxor       %xmm7, %xmm8
+	GHASH_MUL  %xmm8, \TMP3, \TMP1, \TMP2, \TMP4, \TMP5, \XMM1
+.elseif \i == 6
+        pxor       %xmm6, %xmm7
+	GHASH_MUL  %xmm7, \TMP3, \TMP1, \TMP2, \TMP4, \TMP5, \XMM1
+        pxor       %xmm7, %xmm8
+	GHASH_MUL  %xmm8, \TMP3, \TMP1, \TMP2, \TMP4, \TMP5, \XMM1
+.elseif \i == 7
+        pxor       %xmm7, %xmm8
+	GHASH_MUL  %xmm8, \TMP3, \TMP1, \TMP2, \TMP4, \TMP5, \XMM1
+.endif
+	cmp	   $64, %r13
+	jl	_initial_blocks_done\num_initial_blocks\operation
+	# no need for precomputed values
+/*
+*
+* Precomputations for HashKey parallel with encryption of first 4 blocks.
+* Haskey_i_k holds XORed values of the low and high parts of the Haskey_i
+*/
+	paddd	   ONE(%rip), \XMM0              # INCR Y0
+	movdqa	   \XMM0, \XMM1
+        movdqa     SHUF_MASK(%rip), %xmm14
+	PSHUFB_XMM  %xmm14, \XMM1        # perform a 16 byte swap
+
+	paddd	   ONE(%rip), \XMM0              # INCR Y0
+	movdqa	   \XMM0, \XMM2
+        movdqa     SHUF_MASK(%rip), %xmm14
+	PSHUFB_XMM  %xmm14, \XMM2        # perform a 16 byte swap
+
+	paddd	   ONE(%rip), \XMM0              # INCR Y0
+	movdqa	   \XMM0, \XMM3
+        movdqa     SHUF_MASK(%rip), %xmm14
+	PSHUFB_XMM %xmm14, \XMM3        # perform a 16 byte swap
+
+	paddd	   ONE(%rip), \XMM0              # INCR Y0
+	movdqa	   \XMM0, \XMM4
+        movdqa     SHUF_MASK(%rip), %xmm14
+	PSHUFB_XMM %xmm14, \XMM4        # perform a 16 byte swap
+
+	pxor	   16*0(%arg1), \XMM1
+	pxor	   16*0(%arg1), \XMM2
+	pxor	   16*0(%arg1), \XMM3
+	pxor	   16*0(%arg1), \XMM4
+	movdqa	   \TMP3, \TMP5
+	pshufd	   $78, \TMP3, \TMP1
+	pxor	   \TMP3, \TMP1
+	movdqa	   \TMP1, HashKey_k(%rsp)
+	GHASH_MUL  \TMP5, \TMP3, \TMP1, \TMP2, \TMP4, \TMP6, \TMP7
+# TMP5 = HashKey^2<<1 (mod poly)
+	movdqa	   \TMP5, HashKey_2(%rsp)
+# HashKey_2 = HashKey^2<<1 (mod poly)
+	pshufd	   $78, \TMP5, \TMP1
+	pxor	   \TMP5, \TMP1
+	movdqa	   \TMP1, HashKey_2_k(%rsp)
+.irpc index, 1234 # do 4 rounds
+	movaps 0x10*\index(%arg1), \TMP1
+	AESENC	   \TMP1, \XMM1
+	AESENC	   \TMP1, \XMM2
+	AESENC	   \TMP1, \XMM3
+	AESENC	   \TMP1, \XMM4
+.endr
+	GHASH_MUL  \TMP5, \TMP3, \TMP1, \TMP2, \TMP4, \TMP6, \TMP7
+# TMP5 = HashKey^3<<1 (mod poly)
+	movdqa	   \TMP5, HashKey_3(%rsp)
+	pshufd	   $78, \TMP5, \TMP1
+	pxor	   \TMP5, \TMP1
+	movdqa	   \TMP1, HashKey_3_k(%rsp)
+.irpc index, 56789 # do next 5 rounds
+	movaps 0x10*\index(%arg1), \TMP1
+	AESENC	   \TMP1, \XMM1
+	AESENC	   \TMP1, \XMM2
+	AESENC	   \TMP1, \XMM3
+	AESENC	   \TMP1, \XMM4
+.endr
+	GHASH_MUL  \TMP5, \TMP3, \TMP1, \TMP2, \TMP4, \TMP6, \TMP7
+# TMP5 = HashKey^3<<1 (mod poly)
+	movdqa	   \TMP5, HashKey_4(%rsp)
+	pshufd	   $78, \TMP5, \TMP1
+	pxor	   \TMP5, \TMP1
+	movdqa	   \TMP1, HashKey_4_k(%rsp)
+	movaps 0xa0(%arg1), \TMP2
+	AESENCLAST \TMP2, \XMM1
+	AESENCLAST \TMP2, \XMM2
+	AESENCLAST \TMP2, \XMM3
+	AESENCLAST \TMP2, \XMM4
+	movdqu	   16*0(%arg3 , %r11 , 1), \TMP1
+	pxor	   \TMP1, \XMM1
+	movdqu	   \XMM1, 16*0(%arg2 , %r11 , 1)
+	movdqa     \TMP1, \XMM1
+	movdqu	   16*1(%arg3 , %r11 , 1), \TMP1
+	pxor	   \TMP1, \XMM2
+	movdqu	   \XMM2, 16*1(%arg2 , %r11 , 1)
+	movdqa     \TMP1, \XMM2
+	movdqu	   16*2(%arg3 , %r11 , 1), \TMP1
+	pxor	   \TMP1, \XMM3
+	movdqu	   \XMM3, 16*2(%arg2 , %r11 , 1)
+	movdqa     \TMP1, \XMM3
+	movdqu	   16*3(%arg3 , %r11 , 1), \TMP1
+	pxor	   \TMP1, \XMM4
+	movdqu	   \XMM4, 16*3(%arg2 , %r11 , 1)
+	movdqa     \TMP1, \XMM4
+	add	   $64, %r11
+        movdqa     SHUF_MASK(%rip), %xmm14
+	PSHUFB_XMM %xmm14, \XMM1 # perform a 16 byte swap
+	pxor	   \XMMDst, \XMM1
+# combine GHASHed value with the corresponding ciphertext
+        movdqa     SHUF_MASK(%rip), %xmm14
+	PSHUFB_XMM %xmm14, \XMM2 # perform a 16 byte swap
+        movdqa     SHUF_MASK(%rip), %xmm14
+	PSHUFB_XMM %xmm14, \XMM3 # perform a 16 byte swap
+        movdqa     SHUF_MASK(%rip), %xmm14
+	PSHUFB_XMM %xmm14, \XMM4 # perform a 16 byte swap
+
+_initial_blocks_done\num_initial_blocks\operation:
+
+.endm
+
+
+/*
+* if a = number of total plaintext bytes
+* b = floor(a/16)
+* num_initial_blocks = b mod 4
+* encrypt the initial num_initial_blocks blocks and apply ghash on
+* the ciphertext
+* %r10, %r11, %r12, %rax, %xmm5, %xmm6, %xmm7, %xmm8, %xmm9 registers
+* are clobbered
+* arg1, %arg2, %arg3, %r14 are used as a pointer only, not modified
+*/
+
+
+.macro INITIAL_BLOCKS_ENC num_initial_blocks TMP1 TMP2 TMP3 TMP4 TMP5 XMM0 XMM1 \
+XMM2 XMM3 XMM4 XMMDst TMP6 TMP7 i i_seq operation
+	mov	   arg7, %r10           # %r10 = AAD
+	mov	   arg8, %r12           # %r12 = aadLen
+	mov	   %r12, %r11
+	pxor	   %xmm\i, %xmm\i
+_get_AAD_loop\num_initial_blocks\operation:
+	movd	   (%r10), \TMP1
+	pslldq	   $12, \TMP1
+	psrldq	   $4, %xmm\i
+	pxor	   \TMP1, %xmm\i
+	add	   $4, %r10
+	sub	   $4, %r12
+	jne	   _get_AAD_loop\num_initial_blocks\operation
+	cmp	   $16, %r11
+	je	   _get_AAD_loop2_done\num_initial_blocks\operation
+	mov	   $16, %r12
+_get_AAD_loop2\num_initial_blocks\operation:
+	psrldq	   $4, %xmm\i
+	sub	   $4, %r12
+	cmp	   %r11, %r12
+	jne	   _get_AAD_loop2\num_initial_blocks\operation
+_get_AAD_loop2_done\num_initial_blocks\operation:
+        movdqa     SHUF_MASK(%rip), %xmm14
+	PSHUFB_XMM   %xmm14, %xmm\i # byte-reflect the AAD data
+
+	xor	   %r11, %r11 # initialise the data pointer offset as zero
+
+        # start AES for num_initial_blocks blocks
+
+	mov	   %arg5, %rax                      # %rax = *Y0
+	movdqu	   (%rax), \XMM0                    # XMM0 = Y0
+        movdqa     SHUF_MASK(%rip), %xmm14
+	PSHUFB_XMM   %xmm14, \XMM0
+
+.if (\i == 5) || (\i == 6) || (\i == 7)
+.irpc index, \i_seq
+	paddd	   ONE(%rip), \XMM0                 # INCR Y0
+	movdqa	   \XMM0, %xmm\index
+        movdqa     SHUF_MASK(%rip), %xmm14
+	PSHUFB_XMM   %xmm14, %xmm\index      # perform a 16 byte swap
+
+.endr
+.irpc index, \i_seq
+	pxor	   16*0(%arg1), %xmm\index
+.endr
+.irpc index, \i_seq
+	movaps 0x10(%rdi), \TMP1
+	AESENC     \TMP1, %xmm\index          # Round 1
+.endr
+.irpc index, \i_seq
+	movaps 0x20(%arg1), \TMP1
+	AESENC     \TMP1, %xmm\index          # Round 2
+.endr
+.irpc index, \i_seq
+	movaps 0x30(%arg1), \TMP1
+	AESENC     \TMP1, %xmm\index          # Round 2
+.endr
+.irpc index, \i_seq
+	movaps 0x40(%arg1), \TMP1
+	AESENC     \TMP1, %xmm\index          # Round 2
+.endr
+.irpc index, \i_seq
+	movaps 0x50(%arg1), \TMP1
+	AESENC     \TMP1, %xmm\index          # Round 2
+.endr
+.irpc index, \i_seq
+	movaps 0x60(%arg1), \TMP1
+	AESENC     \TMP1, %xmm\index          # Round 2
+.endr
+.irpc index, \i_seq
+	movaps 0x70(%arg1), \TMP1
+	AESENC     \TMP1, %xmm\index          # Round 2
+.endr
+.irpc index, \i_seq
+	movaps 0x80(%arg1), \TMP1
+	AESENC     \TMP1, %xmm\index          # Round 2
+.endr
+.irpc index, \i_seq
+	movaps 0x90(%arg1), \TMP1
+	AESENC     \TMP1, %xmm\index          # Round 2
+.endr
+.irpc index, \i_seq
+	movaps 0xa0(%arg1), \TMP1
+	AESENCLAST \TMP1, %xmm\index         # Round 10
+.endr
+.irpc index, \i_seq
+	movdqu	   (%arg3 , %r11, 1), \TMP1
+	pxor	   \TMP1, %xmm\index
+	movdqu	   %xmm\index, (%arg2 , %r11, 1)
+	# write back plaintext/ciphertext for num_initial_blocks
+	add	   $16, %r11
+
+        movdqa     SHUF_MASK(%rip), %xmm14
+	PSHUFB_XMM	   %xmm14, %xmm\index
+
+		# prepare plaintext/ciphertext for GHASH computation
+.endr
+.endif
+	GHASH_MUL  %xmm\i, \TMP3, \TMP1, \TMP2, \TMP4, \TMP5, \XMM1
+        # apply GHASH on num_initial_blocks blocks
+
+.if \i == 5
+        pxor       %xmm5, %xmm6
+	GHASH_MUL  %xmm6, \TMP3, \TMP1, \TMP2, \TMP4, \TMP5, \XMM1
+        pxor       %xmm6, %xmm7
+	GHASH_MUL  %xmm7, \TMP3, \TMP1, \TMP2, \TMP4, \TMP5, \XMM1
+        pxor       %xmm7, %xmm8
+	GHASH_MUL  %xmm8, \TMP3, \TMP1, \TMP2, \TMP4, \TMP5, \XMM1
+.elseif \i == 6
+        pxor       %xmm6, %xmm7
+	GHASH_MUL  %xmm7, \TMP3, \TMP1, \TMP2, \TMP4, \TMP5, \XMM1
+        pxor       %xmm7, %xmm8
+	GHASH_MUL  %xmm8, \TMP3, \TMP1, \TMP2, \TMP4, \TMP5, \XMM1
+.elseif \i == 7
+        pxor       %xmm7, %xmm8
+	GHASH_MUL  %xmm8, \TMP3, \TMP1, \TMP2, \TMP4, \TMP5, \XMM1
+.endif
+	cmp	   $64, %r13
+	jl	_initial_blocks_done\num_initial_blocks\operation
+	# no need for precomputed values
+/*
+*
+* Precomputations for HashKey parallel with encryption of first 4 blocks.
+* Haskey_i_k holds XORed values of the low and high parts of the Haskey_i
+*/
+	paddd	   ONE(%rip), \XMM0              # INCR Y0
+	movdqa	   \XMM0, \XMM1
+        movdqa     SHUF_MASK(%rip), %xmm14
+	PSHUFB_XMM  %xmm14, \XMM1        # perform a 16 byte swap
+
+	paddd	   ONE(%rip), \XMM0              # INCR Y0
+	movdqa	   \XMM0, \XMM2
+        movdqa     SHUF_MASK(%rip), %xmm14
+	PSHUFB_XMM  %xmm14, \XMM2        # perform a 16 byte swap
+
+	paddd	   ONE(%rip), \XMM0              # INCR Y0
+	movdqa	   \XMM0, \XMM3
+        movdqa     SHUF_MASK(%rip), %xmm14
+	PSHUFB_XMM %xmm14, \XMM3        # perform a 16 byte swap
+
+	paddd	   ONE(%rip), \XMM0              # INCR Y0
+	movdqa	   \XMM0, \XMM4
+        movdqa     SHUF_MASK(%rip), %xmm14
+	PSHUFB_XMM %xmm14, \XMM4        # perform a 16 byte swap
+
+	pxor	   16*0(%arg1), \XMM1
+	pxor	   16*0(%arg1), \XMM2
+	pxor	   16*0(%arg1), \XMM3
+	pxor	   16*0(%arg1), \XMM4
+	movdqa	   \TMP3, \TMP5
+	pshufd	   $78, \TMP3, \TMP1
+	pxor	   \TMP3, \TMP1
+	movdqa	   \TMP1, HashKey_k(%rsp)
+	GHASH_MUL  \TMP5, \TMP3, \TMP1, \TMP2, \TMP4, \TMP6, \TMP7
+# TMP5 = HashKey^2<<1 (mod poly)
+	movdqa	   \TMP5, HashKey_2(%rsp)
+# HashKey_2 = HashKey^2<<1 (mod poly)
+	pshufd	   $78, \TMP5, \TMP1
+	pxor	   \TMP5, \TMP1
+	movdqa	   \TMP1, HashKey_2_k(%rsp)
+.irpc index, 1234 # do 4 rounds
+	movaps 0x10*\index(%arg1), \TMP1
+	AESENC	   \TMP1, \XMM1
+	AESENC	   \TMP1, \XMM2
+	AESENC	   \TMP1, \XMM3
+	AESENC	   \TMP1, \XMM4
+.endr
+	GHASH_MUL  \TMP5, \TMP3, \TMP1, \TMP2, \TMP4, \TMP6, \TMP7
+# TMP5 = HashKey^3<<1 (mod poly)
+	movdqa	   \TMP5, HashKey_3(%rsp)
+	pshufd	   $78, \TMP5, \TMP1
+	pxor	   \TMP5, \TMP1
+	movdqa	   \TMP1, HashKey_3_k(%rsp)
+.irpc index, 56789 # do next 5 rounds
+	movaps 0x10*\index(%arg1), \TMP1
+	AESENC	   \TMP1, \XMM1
+	AESENC	   \TMP1, \XMM2
+	AESENC	   \TMP1, \XMM3
+	AESENC	   \TMP1, \XMM4
+.endr
+	GHASH_MUL  \TMP5, \TMP3, \TMP1, \TMP2, \TMP4, \TMP6, \TMP7
+# TMP5 = HashKey^3<<1 (mod poly)
+	movdqa	   \TMP5, HashKey_4(%rsp)
+	pshufd	   $78, \TMP5, \TMP1
+	pxor	   \TMP5, \TMP1
+	movdqa	   \TMP1, HashKey_4_k(%rsp)
+	movaps 0xa0(%arg1), \TMP2
+	AESENCLAST \TMP2, \XMM1
+	AESENCLAST \TMP2, \XMM2
+	AESENCLAST \TMP2, \XMM3
+	AESENCLAST \TMP2, \XMM4
+	movdqu	   16*0(%arg3 , %r11 , 1), \TMP1
+	pxor	   \TMP1, \XMM1
+	movdqu	   16*1(%arg3 , %r11 , 1), \TMP1
+	pxor	   \TMP1, \XMM2
+	movdqu	   16*2(%arg3 , %r11 , 1), \TMP1
+	pxor	   \TMP1, \XMM3
+	movdqu	   16*3(%arg3 , %r11 , 1), \TMP1
+	pxor	   \TMP1, \XMM4
+	movdqu     \XMM1, 16*0(%arg2 , %r11 , 1)
+	movdqu     \XMM2, 16*1(%arg2 , %r11 , 1)
+	movdqu     \XMM3, 16*2(%arg2 , %r11 , 1)
+	movdqu     \XMM4, 16*3(%arg2 , %r11 , 1)
+
+	add	   $64, %r11
+        movdqa     SHUF_MASK(%rip), %xmm14
+	PSHUFB_XMM %xmm14, \XMM1 # perform a 16 byte swap
+	pxor	   \XMMDst, \XMM1
+# combine GHASHed value with the corresponding ciphertext
+        movdqa     SHUF_MASK(%rip), %xmm14
+	PSHUFB_XMM %xmm14, \XMM2 # perform a 16 byte swap
+        movdqa     SHUF_MASK(%rip), %xmm14
+	PSHUFB_XMM %xmm14, \XMM3 # perform a 16 byte swap
+        movdqa     SHUF_MASK(%rip), %xmm14
+	PSHUFB_XMM %xmm14, \XMM4 # perform a 16 byte swap
+
+_initial_blocks_done\num_initial_blocks\operation:
+
+.endm
+
+/*
+* encrypt 4 blocks at a time
+* ghash the 4 previously encrypted ciphertext blocks
+* arg1, %arg2, %arg3 are used as pointers only, not modified
+* %r11 is the data offset value
+*/
+.macro GHASH_4_ENCRYPT_4_PARALLEL_ENC TMP1 TMP2 TMP3 TMP4 TMP5 \
+TMP6 XMM0 XMM1 XMM2 XMM3 XMM4 XMM5 XMM6 XMM7 XMM8 operation
+
+	movdqa	  \XMM1, \XMM5
+	movdqa	  \XMM2, \XMM6
+	movdqa	  \XMM3, \XMM7
+	movdqa	  \XMM4, \XMM8
+
+        movdqa    SHUF_MASK(%rip), %xmm15
+        # multiply TMP5 * HashKey using karatsuba
+
+	movdqa	  \XMM5, \TMP4
+	pshufd	  $78, \XMM5, \TMP6
+	pxor	  \XMM5, \TMP6
+	paddd     ONE(%rip), \XMM0		# INCR CNT
+	movdqa	  HashKey_4(%rsp), \TMP5
+	PCLMULQDQ 0x11, \TMP5, \TMP4           # TMP4 = a1*b1
+	movdqa    \XMM0, \XMM1
+	paddd     ONE(%rip), \XMM0		# INCR CNT
+	movdqa    \XMM0, \XMM2
+	paddd     ONE(%rip), \XMM0		# INCR CNT
+	movdqa    \XMM0, \XMM3
+	paddd     ONE(%rip), \XMM0		# INCR CNT
+	movdqa    \XMM0, \XMM4
+	PSHUFB_XMM %xmm15, \XMM1	# perform a 16 byte swap
+	PCLMULQDQ 0x00, \TMP5, \XMM5           # XMM5 = a0*b0
+	PSHUFB_XMM %xmm15, \XMM2	# perform a 16 byte swap
+	PSHUFB_XMM %xmm15, \XMM3	# perform a 16 byte swap
+	PSHUFB_XMM %xmm15, \XMM4	# perform a 16 byte swap
+
+	pxor	  (%arg1), \XMM1
+	pxor	  (%arg1), \XMM2
+	pxor	  (%arg1), \XMM3
+	pxor	  (%arg1), \XMM4
+	movdqa	  HashKey_4_k(%rsp), \TMP5
+	PCLMULQDQ 0x00, \TMP5, \TMP6           # TMP6 = (a1+a0)*(b1+b0)
+	movaps 0x10(%arg1), \TMP1
+	AESENC	  \TMP1, \XMM1              # Round 1
+	AESENC	  \TMP1, \XMM2
+	AESENC	  \TMP1, \XMM3
+	AESENC	  \TMP1, \XMM4
+	movaps 0x20(%arg1), \TMP1
+	AESENC	  \TMP1, \XMM1              # Round 2
+	AESENC	  \TMP1, \XMM2
+	AESENC	  \TMP1, \XMM3
+	AESENC	  \TMP1, \XMM4
+	movdqa	  \XMM6, \TMP1
+	pshufd	  $78, \XMM6, \TMP2
+	pxor	  \XMM6, \TMP2
+	movdqa	  HashKey_3(%rsp), \TMP5
+	PCLMULQDQ 0x11, \TMP5, \TMP1           # TMP1 = a1 * b1
+	movaps 0x30(%arg1), \TMP3
+	AESENC    \TMP3, \XMM1              # Round 3
+	AESENC    \TMP3, \XMM2
+	AESENC    \TMP3, \XMM3
+	AESENC    \TMP3, \XMM4
+	PCLMULQDQ 0x00, \TMP5, \XMM6           # XMM6 = a0*b0
+	movaps 0x40(%arg1), \TMP3
+	AESENC	  \TMP3, \XMM1              # Round 4
+	AESENC	  \TMP3, \XMM2
+	AESENC	  \TMP3, \XMM3
+	AESENC	  \TMP3, \XMM4
+	movdqa	  HashKey_3_k(%rsp), \TMP5
+	PCLMULQDQ 0x00, \TMP5, \TMP2           # TMP2 = (a1+a0)*(b1+b0)
+	movaps 0x50(%arg1), \TMP3
+	AESENC	  \TMP3, \XMM1              # Round 5
+	AESENC	  \TMP3, \XMM2
+	AESENC	  \TMP3, \XMM3
+	AESENC	  \TMP3, \XMM4
+	pxor	  \TMP1, \TMP4
+# accumulate the results in TMP4:XMM5, TMP6 holds the middle part
+	pxor	  \XMM6, \XMM5
+	pxor	  \TMP2, \TMP6
+	movdqa	  \XMM7, \TMP1
+	pshufd	  $78, \XMM7, \TMP2
+	pxor	  \XMM7, \TMP2
+	movdqa	  HashKey_2(%rsp ), \TMP5
+
+        # Multiply TMP5 * HashKey using karatsuba
+
+	PCLMULQDQ 0x11, \TMP5, \TMP1           # TMP1 = a1*b1
+	movaps 0x60(%arg1), \TMP3
+	AESENC	  \TMP3, \XMM1              # Round 6
+	AESENC	  \TMP3, \XMM2
+	AESENC	  \TMP3, \XMM3
+	AESENC	  \TMP3, \XMM4
+	PCLMULQDQ 0x00, \TMP5, \XMM7           # XMM7 = a0*b0
+	movaps 0x70(%arg1), \TMP3
+	AESENC	  \TMP3, \XMM1             # Round 7
+	AESENC	  \TMP3, \XMM2
+	AESENC	  \TMP3, \XMM3
+	AESENC	  \TMP3, \XMM4
+	movdqa	  HashKey_2_k(%rsp), \TMP5
+	PCLMULQDQ 0x00, \TMP5, \TMP2           # TMP2 = (a1+a0)*(b1+b0)
+	movaps 0x80(%arg1), \TMP3
+	AESENC	  \TMP3, \XMM1             # Round 8
+	AESENC	  \TMP3, \XMM2
+	AESENC	  \TMP3, \XMM3
+	AESENC	  \TMP3, \XMM4
+	pxor	  \TMP1, \TMP4
+# accumulate the results in TMP4:XMM5, TMP6 holds the middle part
+	pxor	  \XMM7, \XMM5
+	pxor	  \TMP2, \TMP6
+
+        # Multiply XMM8 * HashKey
+        # XMM8 and TMP5 hold the values for the two operands
+
+	movdqa	  \XMM8, \TMP1
+	pshufd	  $78, \XMM8, \TMP2
+	pxor	  \XMM8, \TMP2
+	movdqa	  HashKey(%rsp), \TMP5
+	PCLMULQDQ 0x11, \TMP5, \TMP1          # TMP1 = a1*b1
+	movaps 0x90(%arg1), \TMP3
+	AESENC	  \TMP3, \XMM1            # Round 9
+	AESENC	  \TMP3, \XMM2
+	AESENC	  \TMP3, \XMM3
+	AESENC	  \TMP3, \XMM4
+	PCLMULQDQ 0x00, \TMP5, \XMM8          # XMM8 = a0*b0
+	movaps 0xa0(%arg1), \TMP3
+	AESENCLAST \TMP3, \XMM1           # Round 10
+	AESENCLAST \TMP3, \XMM2
+	AESENCLAST \TMP3, \XMM3
+	AESENCLAST \TMP3, \XMM4
+	movdqa    HashKey_k(%rsp), \TMP5
+	PCLMULQDQ 0x00, \TMP5, \TMP2          # TMP2 = (a1+a0)*(b1+b0)
+	movdqu	  (%arg3,%r11,1), \TMP3
+	pxor	  \TMP3, \XMM1                 # Ciphertext/Plaintext XOR EK
+	movdqu	  16(%arg3,%r11,1), \TMP3
+	pxor	  \TMP3, \XMM2                 # Ciphertext/Plaintext XOR EK
+	movdqu	  32(%arg3,%r11,1), \TMP3
+	pxor	  \TMP3, \XMM3                 # Ciphertext/Plaintext XOR EK
+	movdqu	  48(%arg3,%r11,1), \TMP3
+	pxor	  \TMP3, \XMM4                 # Ciphertext/Plaintext XOR EK
+        movdqu    \XMM1, (%arg2,%r11,1)        # Write to the ciphertext buffer
+        movdqu    \XMM2, 16(%arg2,%r11,1)      # Write to the ciphertext buffer
+        movdqu    \XMM3, 32(%arg2,%r11,1)      # Write to the ciphertext buffer
+        movdqu    \XMM4, 48(%arg2,%r11,1)      # Write to the ciphertext buffer
+	PSHUFB_XMM %xmm15, \XMM1        # perform a 16 byte swap
+	PSHUFB_XMM %xmm15, \XMM2	# perform a 16 byte swap
+	PSHUFB_XMM %xmm15, \XMM3	# perform a 16 byte swap
+	PSHUFB_XMM %xmm15, \XMM4	# perform a 16 byte swap
+
+	pxor	  \TMP4, \TMP1
+	pxor	  \XMM8, \XMM5
+	pxor	  \TMP6, \TMP2
+	pxor	  \TMP1, \TMP2
+	pxor	  \XMM5, \TMP2
+	movdqa	  \TMP2, \TMP3
+	pslldq	  $8, \TMP3                    # left shift TMP3 2 DWs
+	psrldq	  $8, \TMP2                    # right shift TMP2 2 DWs
+	pxor	  \TMP3, \XMM5
+	pxor	  \TMP2, \TMP1	  # accumulate the results in TMP1:XMM5
+
+        # first phase of reduction
+
+	movdqa    \XMM5, \TMP2
+	movdqa    \XMM5, \TMP3
+	movdqa    \XMM5, \TMP4
+# move XMM5 into TMP2, TMP3, TMP4 in order to perform shifts independently
+	pslld     $31, \TMP2                   # packed right shift << 31
+	pslld     $30, \TMP3                   # packed right shift << 30
+	pslld     $25, \TMP4                   # packed right shift << 25
+	pxor      \TMP3, \TMP2	               # xor the shifted versions
+	pxor      \TMP4, \TMP2
+	movdqa    \TMP2, \TMP5
+	psrldq    $4, \TMP5                    # right shift T5 1 DW
+	pslldq    $12, \TMP2                   # left shift T2 3 DWs
+	pxor      \TMP2, \XMM5
+
+        # second phase of reduction
+
+	movdqa    \XMM5,\TMP2 # make 3 copies of XMM5 into TMP2, TMP3, TMP4
+	movdqa    \XMM5,\TMP3
+	movdqa    \XMM5,\TMP4
+	psrld     $1, \TMP2                    # packed left shift >>1
+	psrld     $2, \TMP3                    # packed left shift >>2
+	psrld     $7, \TMP4                    # packed left shift >>7
+	pxor      \TMP3,\TMP2		       # xor the shifted versions
+	pxor      \TMP4,\TMP2
+	pxor      \TMP5, \TMP2
+	pxor      \TMP2, \XMM5
+	pxor      \TMP1, \XMM5                 # result is in TMP1
+
+	pxor	  \XMM5, \XMM1
+.endm
+
+/*
+* decrypt 4 blocks at a time
+* ghash the 4 previously decrypted ciphertext blocks
+* arg1, %arg2, %arg3 are used as pointers only, not modified
+* %r11 is the data offset value
+*/
+.macro GHASH_4_ENCRYPT_4_PARALLEL_DEC TMP1 TMP2 TMP3 TMP4 TMP5 \
+TMP6 XMM0 XMM1 XMM2 XMM3 XMM4 XMM5 XMM6 XMM7 XMM8 operation
+
+	movdqa	  \XMM1, \XMM5
+	movdqa	  \XMM2, \XMM6
+	movdqa	  \XMM3, \XMM7
+	movdqa	  \XMM4, \XMM8
+
+        movdqa    SHUF_MASK(%rip), %xmm15
+        # multiply TMP5 * HashKey using karatsuba
+
+	movdqa	  \XMM5, \TMP4
+	pshufd	  $78, \XMM5, \TMP6
+	pxor	  \XMM5, \TMP6
+	paddd     ONE(%rip), \XMM0		# INCR CNT
+	movdqa	  HashKey_4(%rsp), \TMP5
+	PCLMULQDQ 0x11, \TMP5, \TMP4           # TMP4 = a1*b1
+	movdqa    \XMM0, \XMM1
+	paddd     ONE(%rip), \XMM0		# INCR CNT
+	movdqa    \XMM0, \XMM2
+	paddd     ONE(%rip), \XMM0		# INCR CNT
+	movdqa    \XMM0, \XMM3
+	paddd     ONE(%rip), \XMM0		# INCR CNT
+	movdqa    \XMM0, \XMM4
+	PSHUFB_XMM %xmm15, \XMM1	# perform a 16 byte swap
+	PCLMULQDQ 0x00, \TMP5, \XMM5           # XMM5 = a0*b0
+	PSHUFB_XMM %xmm15, \XMM2	# perform a 16 byte swap
+	PSHUFB_XMM %xmm15, \XMM3	# perform a 16 byte swap
+	PSHUFB_XMM %xmm15, \XMM4	# perform a 16 byte swap
+
+	pxor	  (%arg1), \XMM1
+	pxor	  (%arg1), \XMM2
+	pxor	  (%arg1), \XMM3
+	pxor	  (%arg1), \XMM4
+	movdqa	  HashKey_4_k(%rsp), \TMP5
+	PCLMULQDQ 0x00, \TMP5, \TMP6           # TMP6 = (a1+a0)*(b1+b0)
+	movaps 0x10(%arg1), \TMP1
+	AESENC	  \TMP1, \XMM1              # Round 1
+	AESENC	  \TMP1, \XMM2
+	AESENC	  \TMP1, \XMM3
+	AESENC	  \TMP1, \XMM4
+	movaps 0x20(%arg1), \TMP1
+	AESENC	  \TMP1, \XMM1              # Round 2
+	AESENC	  \TMP1, \XMM2
+	AESENC	  \TMP1, \XMM3
+	AESENC	  \TMP1, \XMM4
+	movdqa	  \XMM6, \TMP1
+	pshufd	  $78, \XMM6, \TMP2
+	pxor	  \XMM6, \TMP2
+	movdqa	  HashKey_3(%rsp), \TMP5
+	PCLMULQDQ 0x11, \TMP5, \TMP1           # TMP1 = a1 * b1
+	movaps 0x30(%arg1), \TMP3
+	AESENC    \TMP3, \XMM1              # Round 3
+	AESENC    \TMP3, \XMM2
+	AESENC    \TMP3, \XMM3
+	AESENC    \TMP3, \XMM4
+	PCLMULQDQ 0x00, \TMP5, \XMM6           # XMM6 = a0*b0
+	movaps 0x40(%arg1), \TMP3
+	AESENC	  \TMP3, \XMM1              # Round 4
+	AESENC	  \TMP3, \XMM2
+	AESENC	  \TMP3, \XMM3
+	AESENC	  \TMP3, \XMM4
+	movdqa	  HashKey_3_k(%rsp), \TMP5
+	PCLMULQDQ 0x00, \TMP5, \TMP2           # TMP2 = (a1+a0)*(b1+b0)
+	movaps 0x50(%arg1), \TMP3
+	AESENC	  \TMP3, \XMM1              # Round 5
+	AESENC	  \TMP3, \XMM2
+	AESENC	  \TMP3, \XMM3
+	AESENC	  \TMP3, \XMM4
+	pxor	  \TMP1, \TMP4
+# accumulate the results in TMP4:XMM5, TMP6 holds the middle part
+	pxor	  \XMM6, \XMM5
+	pxor	  \TMP2, \TMP6
+	movdqa	  \XMM7, \TMP1
+	pshufd	  $78, \XMM7, \TMP2
+	pxor	  \XMM7, \TMP2
+	movdqa	  HashKey_2(%rsp ), \TMP5
+
+        # Multiply TMP5 * HashKey using karatsuba
+
+	PCLMULQDQ 0x11, \TMP5, \TMP1           # TMP1 = a1*b1
+	movaps 0x60(%arg1), \TMP3
+	AESENC	  \TMP3, \XMM1              # Round 6
+	AESENC	  \TMP3, \XMM2
+	AESENC	  \TMP3, \XMM3
+	AESENC	  \TMP3, \XMM4
+	PCLMULQDQ 0x00, \TMP5, \XMM7           # XMM7 = a0*b0
+	movaps 0x70(%arg1), \TMP3
+	AESENC	  \TMP3, \XMM1             # Round 7
+	AESENC	  \TMP3, \XMM2
+	AESENC	  \TMP3, \XMM3
+	AESENC	  \TMP3, \XMM4
+	movdqa	  HashKey_2_k(%rsp), \TMP5
+	PCLMULQDQ 0x00, \TMP5, \TMP2           # TMP2 = (a1+a0)*(b1+b0)
+	movaps 0x80(%arg1), \TMP3
+	AESENC	  \TMP3, \XMM1             # Round 8
+	AESENC	  \TMP3, \XMM2
+	AESENC	  \TMP3, \XMM3
+	AESENC	  \TMP3, \XMM4
+	pxor	  \TMP1, \TMP4
+# accumulate the results in TMP4:XMM5, TMP6 holds the middle part
+	pxor	  \XMM7, \XMM5
+	pxor	  \TMP2, \TMP6
+
+        # Multiply XMM8 * HashKey
+        # XMM8 and TMP5 hold the values for the two operands
+
+	movdqa	  \XMM8, \TMP1
+	pshufd	  $78, \XMM8, \TMP2
+	pxor	  \XMM8, \TMP2
+	movdqa	  HashKey(%rsp), \TMP5
+	PCLMULQDQ 0x11, \TMP5, \TMP1          # TMP1 = a1*b1
+	movaps 0x90(%arg1), \TMP3
+	AESENC	  \TMP3, \XMM1            # Round 9
+	AESENC	  \TMP3, \XMM2
+	AESENC	  \TMP3, \XMM3
+	AESENC	  \TMP3, \XMM4
+	PCLMULQDQ 0x00, \TMP5, \XMM8          # XMM8 = a0*b0
+	movaps 0xa0(%arg1), \TMP3
+	AESENCLAST \TMP3, \XMM1           # Round 10
+	AESENCLAST \TMP3, \XMM2
+	AESENCLAST \TMP3, \XMM3
+	AESENCLAST \TMP3, \XMM4
+	movdqa    HashKey_k(%rsp), \TMP5
+	PCLMULQDQ 0x00, \TMP5, \TMP2          # TMP2 = (a1+a0)*(b1+b0)
+	movdqu	  (%arg3,%r11,1), \TMP3
+	pxor	  \TMP3, \XMM1                 # Ciphertext/Plaintext XOR EK
+	movdqu	  \XMM1, (%arg2,%r11,1)        # Write to plaintext buffer
+	movdqa    \TMP3, \XMM1
+	movdqu	  16(%arg3,%r11,1), \TMP3
+	pxor	  \TMP3, \XMM2                 # Ciphertext/Plaintext XOR EK
+	movdqu	  \XMM2, 16(%arg2,%r11,1)      # Write to plaintext buffer
+	movdqa    \TMP3, \XMM2
+	movdqu	  32(%arg3,%r11,1), \TMP3
+	pxor	  \TMP3, \XMM3                 # Ciphertext/Plaintext XOR EK
+	movdqu	  \XMM3, 32(%arg2,%r11,1)      # Write to plaintext buffer
+	movdqa    \TMP3, \XMM3
+	movdqu	  48(%arg3,%r11,1), \TMP3
+	pxor	  \TMP3, \XMM4                 # Ciphertext/Plaintext XOR EK
+	movdqu	  \XMM4, 48(%arg2,%r11,1)      # Write to plaintext buffer
+	movdqa    \TMP3, \XMM4
+	PSHUFB_XMM %xmm15, \XMM1        # perform a 16 byte swap
+	PSHUFB_XMM %xmm15, \XMM2	# perform a 16 byte swap
+	PSHUFB_XMM %xmm15, \XMM3	# perform a 16 byte swap
+	PSHUFB_XMM %xmm15, \XMM4	# perform a 16 byte swap
+
+	pxor	  \TMP4, \TMP1
+	pxor	  \XMM8, \XMM5
+	pxor	  \TMP6, \TMP2
+	pxor	  \TMP1, \TMP2
+	pxor	  \XMM5, \TMP2
+	movdqa	  \TMP2, \TMP3
+	pslldq	  $8, \TMP3                    # left shift TMP3 2 DWs
+	psrldq	  $8, \TMP2                    # right shift TMP2 2 DWs
+	pxor	  \TMP3, \XMM5
+	pxor	  \TMP2, \TMP1	  # accumulate the results in TMP1:XMM5
+
+        # first phase of reduction
+
+	movdqa    \XMM5, \TMP2
+	movdqa    \XMM5, \TMP3
+	movdqa    \XMM5, \TMP4
+# move XMM5 into TMP2, TMP3, TMP4 in order to perform shifts independently
+	pslld     $31, \TMP2                   # packed right shift << 31
+	pslld     $30, \TMP3                   # packed right shift << 30
+	pslld     $25, \TMP4                   # packed right shift << 25
+	pxor      \TMP3, \TMP2	               # xor the shifted versions
+	pxor      \TMP4, \TMP2
+	movdqa    \TMP2, \TMP5
+	psrldq    $4, \TMP5                    # right shift T5 1 DW
+	pslldq    $12, \TMP2                   # left shift T2 3 DWs
+	pxor      \TMP2, \XMM5
+
+        # second phase of reduction
+
+	movdqa    \XMM5,\TMP2 # make 3 copies of XMM5 into TMP2, TMP3, TMP4
+	movdqa    \XMM5,\TMP3
+	movdqa    \XMM5,\TMP4
+	psrld     $1, \TMP2                    # packed left shift >>1
+	psrld     $2, \TMP3                    # packed left shift >>2
+	psrld     $7, \TMP4                    # packed left shift >>7
+	pxor      \TMP3,\TMP2		       # xor the shifted versions
+	pxor      \TMP4,\TMP2
+	pxor      \TMP5, \TMP2
+	pxor      \TMP2, \XMM5
+	pxor      \TMP1, \XMM5                 # result is in TMP1
+
+	pxor	  \XMM5, \XMM1
+.endm
+
+/* GHASH the last 4 ciphertext blocks. */
+.macro	GHASH_LAST_4 TMP1 TMP2 TMP3 TMP4 TMP5 TMP6 \
+TMP7 XMM1 XMM2 XMM3 XMM4 XMMDst
+
+        # Multiply TMP6 * HashKey (using Karatsuba)
+
+	movdqa	  \XMM1, \TMP6
+	pshufd	  $78, \XMM1, \TMP2
+	pxor	  \XMM1, \TMP2
+	movdqa	  HashKey_4(%rsp), \TMP5
+	PCLMULQDQ 0x11, \TMP5, \TMP6       # TMP6 = a1*b1
+	PCLMULQDQ 0x00, \TMP5, \XMM1       # XMM1 = a0*b0
+	movdqa	  HashKey_4_k(%rsp), \TMP4
+	PCLMULQDQ 0x00, \TMP4, \TMP2       # TMP2 = (a1+a0)*(b1+b0)
+	movdqa	  \XMM1, \XMMDst
+	movdqa	  \TMP2, \XMM1              # result in TMP6, XMMDst, XMM1
+
+        # Multiply TMP1 * HashKey (using Karatsuba)
+
+	movdqa	  \XMM2, \TMP1
+	pshufd	  $78, \XMM2, \TMP2
+	pxor	  \XMM2, \TMP2
+	movdqa	  HashKey_3(%rsp), \TMP5
+	PCLMULQDQ 0x11, \TMP5, \TMP1       # TMP1 = a1*b1
+	PCLMULQDQ 0x00, \TMP5, \XMM2       # XMM2 = a0*b0
+	movdqa	  HashKey_3_k(%rsp), \TMP4
+	PCLMULQDQ 0x00, \TMP4, \TMP2       # TMP2 = (a1+a0)*(b1+b0)
+	pxor	  \TMP1, \TMP6
+	pxor	  \XMM2, \XMMDst
+	pxor	  \TMP2, \XMM1
+# results accumulated in TMP6, XMMDst, XMM1
+
+        # Multiply TMP1 * HashKey (using Karatsuba)
+
+	movdqa	  \XMM3, \TMP1
+	pshufd	  $78, \XMM3, \TMP2
+	pxor	  \XMM3, \TMP2
+	movdqa	  HashKey_2(%rsp), \TMP5
+	PCLMULQDQ 0x11, \TMP5, \TMP1       # TMP1 = a1*b1
+	PCLMULQDQ 0x00, \TMP5, \XMM3       # XMM3 = a0*b0
+	movdqa	  HashKey_2_k(%rsp), \TMP4
+	PCLMULQDQ 0x00, \TMP4, \TMP2       # TMP2 = (a1+a0)*(b1+b0)
+	pxor	  \TMP1, \TMP6
+	pxor	  \XMM3, \XMMDst
+	pxor	  \TMP2, \XMM1   # results accumulated in TMP6, XMMDst, XMM1
+
+        # Multiply TMP1 * HashKey (using Karatsuba)
+	movdqa	  \XMM4, \TMP1
+	pshufd	  $78, \XMM4, \TMP2
+	pxor	  \XMM4, \TMP2
+	movdqa	  HashKey(%rsp), \TMP5
+	PCLMULQDQ 0x11, \TMP5, \TMP1	    # TMP1 = a1*b1
+	PCLMULQDQ 0x00, \TMP5, \XMM4       # XMM4 = a0*b0
+	movdqa	  HashKey_k(%rsp), \TMP4
+	PCLMULQDQ 0x00, \TMP4, \TMP2       # TMP2 = (a1+a0)*(b1+b0)
+	pxor	  \TMP1, \TMP6
+	pxor	  \XMM4, \XMMDst
+	pxor	  \XMM1, \TMP2
+	pxor	  \TMP6, \TMP2
+	pxor	  \XMMDst, \TMP2
+	# middle section of the temp results combined as in karatsuba algorithm
+	movdqa	  \TMP2, \TMP4
+	pslldq	  $8, \TMP4                 # left shift TMP4 2 DWs
+	psrldq	  $8, \TMP2                 # right shift TMP2 2 DWs
+	pxor	  \TMP4, \XMMDst
+	pxor	  \TMP2, \TMP6
+# TMP6:XMMDst holds the result of the accumulated carry-less multiplications
+	# first phase of the reduction
+	movdqa    \XMMDst, \TMP2
+	movdqa    \XMMDst, \TMP3
+	movdqa    \XMMDst, \TMP4
+# move XMMDst into TMP2, TMP3, TMP4 in order to perform 3 shifts independently
+	pslld     $31, \TMP2                # packed right shifting << 31
+	pslld     $30, \TMP3                # packed right shifting << 30
+	pslld     $25, \TMP4                # packed right shifting << 25
+	pxor      \TMP3, \TMP2              # xor the shifted versions
+	pxor      \TMP4, \TMP2
+	movdqa    \TMP2, \TMP7
+	psrldq    $4, \TMP7                 # right shift TMP7 1 DW
+	pslldq    $12, \TMP2                # left shift TMP2 3 DWs
+	pxor      \TMP2, \XMMDst
+
+        # second phase of the reduction
+	movdqa    \XMMDst, \TMP2
+	# make 3 copies of XMMDst for doing 3 shift operations
+	movdqa    \XMMDst, \TMP3
+	movdqa    \XMMDst, \TMP4
+	psrld     $1, \TMP2                 # packed left shift >> 1
+	psrld     $2, \TMP3                 # packed left shift >> 2
+	psrld     $7, \TMP4                 # packed left shift >> 7
+	pxor      \TMP3, \TMP2              # xor the shifted versions
+	pxor      \TMP4, \TMP2
+	pxor      \TMP7, \TMP2
+	pxor      \TMP2, \XMMDst
+	pxor      \TMP6, \XMMDst            # reduced result is in XMMDst
+.endm
+
+/* Encryption of a single block done*/
+.macro ENCRYPT_SINGLE_BLOCK XMM0 TMP1
+
+	pxor	(%arg1), \XMM0
+        movaps 16(%arg1), \TMP1
+	AESENC	\TMP1, \XMM0
+        movaps 32(%arg1), \TMP1
+	AESENC	\TMP1, \XMM0
+        movaps 48(%arg1), \TMP1
+	AESENC	\TMP1, \XMM0
+        movaps 64(%arg1), \TMP1
+	AESENC	\TMP1, \XMM0
+        movaps 80(%arg1), \TMP1
+	AESENC	\TMP1, \XMM0
+        movaps 96(%arg1), \TMP1
+	AESENC	\TMP1, \XMM0
+        movaps 112(%arg1), \TMP1
+	AESENC	\TMP1, \XMM0
+        movaps 128(%arg1), \TMP1
+	AESENC	\TMP1, \XMM0
+        movaps 144(%arg1), \TMP1
+	AESENC	\TMP1, \XMM0
+        movaps 160(%arg1), \TMP1
+	AESENCLAST	\TMP1, \XMM0
+.endm
+
+
+/*****************************************************************************
+* void aesni_gcm_dec(void *aes_ctx,    // AES Key schedule. Starts on a 16 byte boundary.
+*                   u8 *out,           // Plaintext output. Encrypt in-place is allowed.
+*                   const u8 *in,      // Ciphertext input
+*                   u64 plaintext_len, // Length of data in bytes for decryption.
+*                   u8 *iv,            // Pre-counter block j0: 4 byte salt (from Security Association)
+*                                      // concatenated with 8 byte Initialisation Vector (from IPSec ESP Payload)
+*                                      // concatenated with 0x00000001. 16-byte aligned pointer.
+*                   u8 *hash_subkey,   // H, the Hash sub key input. Data starts on a 16-byte boundary.
+*                   const u8 *aad,     // Additional Authentication Data (AAD)
+*                   u64 aad_len,       // Length of AAD in bytes. With RFC4106 this is going to be 8 or 12 bytes
+*                   u8  *auth_tag,     // Authenticated Tag output. The driver will compare this to the
+*                                      // given authentication tag and only return the plaintext if they match.
+*                   u64 auth_tag_len); // Authenticated Tag Length in bytes. Valid values are 16
+*                                      // (most likely), 12 or 8.
+*
+* Assumptions:
+*
+* keys:
+*       keys are pre-expanded and aligned to 16 bytes. we are using the first
+*       set of 11 keys in the data structure void *aes_ctx
+*
+* iv:
+*       0                   1                   2                   3
+*       0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+*       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*       |                             Salt  (From the SA)               |
+*       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*       |                     Initialization Vector                     |
+*       |         (This is the sequence number from IPSec header)       |
+*       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*       |                              0x1                              |
+*       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*
+*
+*
+* AAD:
+*       AAD padded to 128 bits with 0
+*       for example, assume AAD is a u32 vector
+*
+*       if AAD is 8 bytes:
+*       AAD[3] = {A0, A1};
+*       padded AAD in xmm register = {A1 A0 0 0}
+*
+*       0                   1                   2                   3
+*       0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+*       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*       |                               SPI (A1)                        |
+*       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*       |                     32-bit Sequence Number (A0)               |
+*       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*       |                              0x0                              |
+*       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*
+*                                       AAD Format with 32-bit Sequence Number
+*
+*       if AAD is 12 bytes:
+*       AAD[3] = {A0, A1, A2};
+*       padded AAD in xmm register = {A2 A1 A0 0}
+*
+*       0                   1                   2                   3
+*       0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+*       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*       0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+*       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*       |                               SPI (A2)                        |
+*       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*       |                 64-bit Extended Sequence Number {A1,A0}       |
+*       |                                                               |
+*       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*       |                              0x0                              |
+*       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*
+*                        AAD Format with 64-bit Extended Sequence Number
+*
+* aadLen:
+*       from the definition of the spec, aadLen can only be 8 or 12 bytes.
+*       The code supports 16 too but for other sizes, the code will fail.
+*
+* TLen:
+*       from the definition of the spec, TLen can only be 8, 12 or 16 bytes.
+*       For other sizes, the code will fail.
+*
+* poly = x^128 + x^127 + x^126 + x^121 + 1
+*
+*****************************************************************************/
+
+ENTRY(aesni_gcm_dec)
+	push	%r12
+	push	%r13
+	push	%r14
+	mov	%rsp, %r14
+/*
+* states of %xmm registers %xmm6:%xmm15 not saved
+* all %xmm registers are clobbered
+*/
+	sub	$VARIABLE_OFFSET, %rsp
+	and	$~63, %rsp                        # align rsp to 64 bytes
+	mov	%arg6, %r12
+	movdqu	(%r12), %xmm13			  # %xmm13 = HashKey
+        movdqa  SHUF_MASK(%rip), %xmm2
+	PSHUFB_XMM %xmm2, %xmm13
+
+
+# Precompute HashKey<<1 (mod poly) from the hash key (required for GHASH)
+
+	movdqa	%xmm13, %xmm2
+	psllq	$1, %xmm13
+	psrlq	$63, %xmm2
+	movdqa	%xmm2, %xmm1
+	pslldq	$8, %xmm2
+	psrldq	$8, %xmm1
+	por	%xmm2, %xmm13
+
+        # Reduction
+
+	pshufd	$0x24, %xmm1, %xmm2
+	pcmpeqd TWOONE(%rip), %xmm2
+	pand	POLY(%rip), %xmm2
+	pxor	%xmm2, %xmm13     # %xmm13 holds the HashKey<<1 (mod poly)
+
+
+        # Decrypt first few blocks
+
+	movdqa %xmm13, HashKey(%rsp)           # store HashKey<<1 (mod poly)
+	mov %arg4, %r13    # save the number of bytes of plaintext/ciphertext
+	and $-16, %r13                      # %r13 = %r13 - (%r13 mod 16)
+	mov %r13, %r12
+	and $(3<<4), %r12
+	jz _initial_num_blocks_is_0_decrypt
+	cmp $(2<<4), %r12
+	jb _initial_num_blocks_is_1_decrypt
+	je _initial_num_blocks_is_2_decrypt
+_initial_num_blocks_is_3_decrypt:
+	INITIAL_BLOCKS_DEC 3, %xmm9, %xmm10, %xmm13, %xmm11, %xmm12, %xmm0, \
+%xmm1, %xmm2, %xmm3, %xmm4, %xmm8, %xmm5, %xmm6, 5, 678, dec
+	sub	$48, %r13
+	jmp	_initial_blocks_decrypted
+_initial_num_blocks_is_2_decrypt:
+	INITIAL_BLOCKS_DEC	2, %xmm9, %xmm10, %xmm13, %xmm11, %xmm12, %xmm0, \
+%xmm1, %xmm2, %xmm3, %xmm4, %xmm8, %xmm5, %xmm6, 6, 78, dec
+	sub	$32, %r13
+	jmp	_initial_blocks_decrypted
+_initial_num_blocks_is_1_decrypt:
+	INITIAL_BLOCKS_DEC	1, %xmm9, %xmm10, %xmm13, %xmm11, %xmm12, %xmm0, \
+%xmm1, %xmm2, %xmm3, %xmm4, %xmm8, %xmm5, %xmm6, 7, 8, dec
+	sub	$16, %r13
+	jmp	_initial_blocks_decrypted
+_initial_num_blocks_is_0_decrypt:
+	INITIAL_BLOCKS_DEC	0, %xmm9, %xmm10, %xmm13, %xmm11, %xmm12, %xmm0, \
+%xmm1, %xmm2, %xmm3, %xmm4, %xmm8, %xmm5, %xmm6, 8, 0, dec
+_initial_blocks_decrypted:
+	cmp	$0, %r13
+	je	_zero_cipher_left_decrypt
+	sub	$64, %r13
+	je	_four_cipher_left_decrypt
+_decrypt_by_4:
+	GHASH_4_ENCRYPT_4_PARALLEL_DEC	%xmm9, %xmm10, %xmm11, %xmm12, %xmm13, \
+%xmm14, %xmm0, %xmm1, %xmm2, %xmm3, %xmm4, %xmm5, %xmm6, %xmm7, %xmm8, dec
+	add	$64, %r11
+	sub	$64, %r13
+	jne	_decrypt_by_4
+_four_cipher_left_decrypt:
+	GHASH_LAST_4	%xmm9, %xmm10, %xmm11, %xmm12, %xmm13, %xmm14, \
+%xmm15, %xmm1, %xmm2, %xmm3, %xmm4, %xmm8
+_zero_cipher_left_decrypt:
+	mov	%arg4, %r13
+	and	$15, %r13				# %r13 = arg4 (mod 16)
+	je	_multiple_of_16_bytes_decrypt
+
+        # Handle the last <16 byte block seperately
+
+	paddd ONE(%rip), %xmm0         # increment CNT to get Yn
+        movdqa SHUF_MASK(%rip), %xmm10
+	PSHUFB_XMM %xmm10, %xmm0
+
+	ENCRYPT_SINGLE_BLOCK  %xmm0, %xmm1    # E(K, Yn)
+	sub $16, %r11
+	add %r13, %r11
+	movdqu (%arg3,%r11,1), %xmm1   # recieve the last <16 byte block
+	lea SHIFT_MASK+16(%rip), %r12
+	sub %r13, %r12
+# adjust the shuffle mask pointer to be able to shift 16-%r13 bytes
+# (%r13 is the number of bytes in plaintext mod 16)
+	movdqu (%r12), %xmm2           # get the appropriate shuffle mask
+	PSHUFB_XMM %xmm2, %xmm1            # right shift 16-%r13 butes
+
+	movdqa  %xmm1, %xmm2
+	pxor %xmm1, %xmm0            # Ciphertext XOR E(K, Yn)
+	movdqu ALL_F-SHIFT_MASK(%r12), %xmm1
+	# get the appropriate mask to mask out top 16-%r13 bytes of %xmm0
+	pand %xmm1, %xmm0            # mask out top 16-%r13 bytes of %xmm0
+	pand    %xmm1, %xmm2
+        movdqa SHUF_MASK(%rip), %xmm10
+	PSHUFB_XMM %xmm10 ,%xmm2
+
+	pxor %xmm2, %xmm8
+	GHASH_MUL %xmm8, %xmm13, %xmm9, %xmm10, %xmm11, %xmm5, %xmm6
+	          # GHASH computation for the last <16 byte block
+	sub %r13, %r11
+	add $16, %r11
+
+        # output %r13 bytes
+	MOVQ_R64_XMM	%xmm0, %rax
+	cmp	$8, %r13
+	jle	_less_than_8_bytes_left_decrypt
+	mov	%rax, (%arg2 , %r11, 1)
+	add	$8, %r11
+	psrldq	$8, %xmm0
+	MOVQ_R64_XMM	%xmm0, %rax
+	sub	$8, %r13
+_less_than_8_bytes_left_decrypt:
+	mov	%al,  (%arg2, %r11, 1)
+	add	$1, %r11
+	shr	$8, %rax
+	sub	$1, %r13
+	jne	_less_than_8_bytes_left_decrypt
+_multiple_of_16_bytes_decrypt:
+	mov	arg8, %r12		  # %r13 = aadLen (number of bytes)
+	shl	$3, %r12		  # convert into number of bits
+	movd	%r12d, %xmm15		  # len(A) in %xmm15
+	shl	$3, %arg4		  # len(C) in bits (*128)
+	MOVQ_R64_XMM	%arg4, %xmm1
+	pslldq	$8, %xmm15		  # %xmm15 = len(A)||0x0000000000000000
+	pxor	%xmm1, %xmm15		  # %xmm15 = len(A)||len(C)
+	pxor	%xmm15, %xmm8
+	GHASH_MUL	%xmm8, %xmm13, %xmm9, %xmm10, %xmm11, %xmm5, %xmm6
+	         # final GHASH computation
+        movdqa SHUF_MASK(%rip), %xmm10
+	PSHUFB_XMM %xmm10, %xmm8
+
+	mov	%arg5, %rax		  # %rax = *Y0
+	movdqu	(%rax), %xmm0		  # %xmm0 = Y0
+	ENCRYPT_SINGLE_BLOCK	%xmm0,  %xmm1	  # E(K, Y0)
+	pxor	%xmm8, %xmm0
+_return_T_decrypt:
+	mov	arg9, %r10                # %r10 = authTag
+	mov	arg10, %r11               # %r11 = auth_tag_len
+	cmp	$16, %r11
+	je	_T_16_decrypt
+	cmp	$12, %r11
+	je	_T_12_decrypt
+_T_8_decrypt:
+	MOVQ_R64_XMM	%xmm0, %rax
+	mov	%rax, (%r10)
+	jmp	_return_T_done_decrypt
+_T_12_decrypt:
+	MOVQ_R64_XMM	%xmm0, %rax
+	mov	%rax, (%r10)
+	psrldq	$8, %xmm0
+	movd	%xmm0, %eax
+	mov	%eax, 8(%r10)
+	jmp	_return_T_done_decrypt
+_T_16_decrypt:
+	movdqu	%xmm0, (%r10)
+_return_T_done_decrypt:
+	mov	%r14, %rsp
+	pop	%r14
+	pop	%r13
+	pop	%r12
+	ret
+
+
+/*****************************************************************************
+* void aesni_gcm_enc(void *aes_ctx,      // AES Key schedule. Starts on a 16 byte boundary.
+*                    u8 *out,            // Ciphertext output. Encrypt in-place is allowed.
+*                    const u8 *in,       // Plaintext input
+*                    u64 plaintext_len,  // Length of data in bytes for encryption.
+*                    u8 *iv,             // Pre-counter block j0: 4 byte salt (from Security Association)
+*                                        // concatenated with 8 byte Initialisation Vector (from IPSec ESP Payload)
+*                                        // concatenated with 0x00000001. 16-byte aligned pointer.
+*                    u8 *hash_subkey,    // H, the Hash sub key input. Data starts on a 16-byte boundary.
+*                    const u8 *aad,      // Additional Authentication Data (AAD)
+*                    u64 aad_len,        // Length of AAD in bytes. With RFC4106 this is going to be 8 or 12 bytes
+*                    u8 *auth_tag,       // Authenticated Tag output.
+*                    u64 auth_tag_len);  // Authenticated Tag Length in bytes. Valid values are 16 (most likely),
+*                                        // 12 or 8.
+*
+* Assumptions:
+*
+* keys:
+*       keys are pre-expanded and aligned to 16 bytes. we are using the
+*       first set of 11 keys in the data structure void *aes_ctx
+*
+*
+* iv:
+*       0                   1                   2                   3
+*       0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+*       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*       |                             Salt  (From the SA)               |
+*       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*       |                     Initialization Vector                     |
+*       |         (This is the sequence number from IPSec header)       |
+*       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*       |                              0x1                              |
+*       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*
+*
+*
+* AAD:
+*       AAD padded to 128 bits with 0
+*       for example, assume AAD is a u32 vector
+*
+*       if AAD is 8 bytes:
+*       AAD[3] = {A0, A1};
+*       padded AAD in xmm register = {A1 A0 0 0}
+*
+*       0                   1                   2                   3
+*       0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+*       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*       |                               SPI (A1)                        |
+*       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*       |                     32-bit Sequence Number (A0)               |
+*       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*       |                              0x0                              |
+*       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*
+*                                 AAD Format with 32-bit Sequence Number
+*
+*       if AAD is 12 bytes:
+*       AAD[3] = {A0, A1, A2};
+*       padded AAD in xmm register = {A2 A1 A0 0}
+*
+*       0                   1                   2                   3
+*       0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+*       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*       |                               SPI (A2)                        |
+*       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*       |                 64-bit Extended Sequence Number {A1,A0}       |
+*       |                                                               |
+*       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*       |                              0x0                              |
+*       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*
+*                         AAD Format with 64-bit Extended Sequence Number
+*
+* aadLen:
+*       from the definition of the spec, aadLen can only be 8 or 12 bytes.
+*       The code supports 16 too but for other sizes, the code will fail.
+*
+* TLen:
+*       from the definition of the spec, TLen can only be 8, 12 or 16 bytes.
+*       For other sizes, the code will fail.
+*
+* poly = x^128 + x^127 + x^126 + x^121 + 1
+***************************************************************************/
+ENTRY(aesni_gcm_enc)
+	push	%r12
+	push	%r13
+	push	%r14
+	mov	%rsp, %r14
+#
+# states of %xmm registers %xmm6:%xmm15 not saved
+# all %xmm registers are clobbered
+#
+	sub	$VARIABLE_OFFSET, %rsp
+	and	$~63, %rsp
+	mov	%arg6, %r12
+	movdqu	(%r12), %xmm13
+        movdqa  SHUF_MASK(%rip), %xmm2
+	PSHUFB_XMM %xmm2, %xmm13
+
+
+# precompute HashKey<<1 mod poly from the HashKey (required for GHASH)
+
+	movdqa	%xmm13, %xmm2
+	psllq	$1, %xmm13
+	psrlq	$63, %xmm2
+	movdqa	%xmm2, %xmm1
+	pslldq	$8, %xmm2
+	psrldq	$8, %xmm1
+	por	%xmm2, %xmm13
+
+        # reduce HashKey<<1
+
+	pshufd	$0x24, %xmm1, %xmm2
+	pcmpeqd TWOONE(%rip), %xmm2
+	pand	POLY(%rip), %xmm2
+	pxor	%xmm2, %xmm13
+	movdqa	%xmm13, HashKey(%rsp)
+	mov	%arg4, %r13            # %xmm13 holds HashKey<<1 (mod poly)
+	and	$-16, %r13
+	mov	%r13, %r12
+
+        # Encrypt first few blocks
+
+	and	$(3<<4), %r12
+	jz	_initial_num_blocks_is_0_encrypt
+	cmp	$(2<<4), %r12
+	jb	_initial_num_blocks_is_1_encrypt
+	je	_initial_num_blocks_is_2_encrypt
+_initial_num_blocks_is_3_encrypt:
+	INITIAL_BLOCKS_ENC	3, %xmm9, %xmm10, %xmm13, %xmm11, %xmm12, %xmm0, \
+%xmm1, %xmm2, %xmm3, %xmm4, %xmm8, %xmm5, %xmm6, 5, 678, enc
+	sub	$48, %r13
+	jmp	_initial_blocks_encrypted
+_initial_num_blocks_is_2_encrypt:
+	INITIAL_BLOCKS_ENC	2, %xmm9, %xmm10, %xmm13, %xmm11, %xmm12, %xmm0, \
+%xmm1, %xmm2, %xmm3, %xmm4, %xmm8, %xmm5, %xmm6, 6, 78, enc
+	sub	$32, %r13
+	jmp	_initial_blocks_encrypted
+_initial_num_blocks_is_1_encrypt:
+	INITIAL_BLOCKS_ENC	1, %xmm9, %xmm10, %xmm13, %xmm11, %xmm12, %xmm0, \
+%xmm1, %xmm2, %xmm3, %xmm4, %xmm8, %xmm5, %xmm6, 7, 8, enc
+	sub	$16, %r13
+	jmp	_initial_blocks_encrypted
+_initial_num_blocks_is_0_encrypt:
+	INITIAL_BLOCKS_ENC	0, %xmm9, %xmm10, %xmm13, %xmm11, %xmm12, %xmm0, \
+%xmm1, %xmm2, %xmm3, %xmm4, %xmm8, %xmm5, %xmm6, 8, 0, enc
+_initial_blocks_encrypted:
+
+        # Main loop - Encrypt remaining blocks
+
+	cmp	$0, %r13
+	je	_zero_cipher_left_encrypt
+	sub	$64, %r13
+	je	_four_cipher_left_encrypt
+_encrypt_by_4_encrypt:
+	GHASH_4_ENCRYPT_4_PARALLEL_ENC	%xmm9, %xmm10, %xmm11, %xmm12, %xmm13, \
+%xmm14, %xmm0, %xmm1, %xmm2, %xmm3, %xmm4, %xmm5, %xmm6, %xmm7, %xmm8, enc
+	add	$64, %r11
+	sub	$64, %r13
+	jne	_encrypt_by_4_encrypt
+_four_cipher_left_encrypt:
+	GHASH_LAST_4	%xmm9, %xmm10, %xmm11, %xmm12, %xmm13, %xmm14, \
+%xmm15, %xmm1, %xmm2, %xmm3, %xmm4, %xmm8
+_zero_cipher_left_encrypt:
+	mov	%arg4, %r13
+	and	$15, %r13			# %r13 = arg4 (mod 16)
+	je	_multiple_of_16_bytes_encrypt
+
+         # Handle the last <16 Byte block seperately
+	paddd ONE(%rip), %xmm0                # INCR CNT to get Yn
+        movdqa SHUF_MASK(%rip), %xmm10
+	PSHUFB_XMM %xmm10, %xmm0
+
+	ENCRYPT_SINGLE_BLOCK	%xmm0, %xmm1        # Encrypt(K, Yn)
+	sub $16, %r11
+	add %r13, %r11
+	movdqu (%arg3,%r11,1), %xmm1     # receive the last <16 byte blocks
+	lea SHIFT_MASK+16(%rip), %r12
+	sub %r13, %r12
+	# adjust the shuffle mask pointer to be able to shift 16-r13 bytes
+	# (%r13 is the number of bytes in plaintext mod 16)
+	movdqu	(%r12), %xmm2           # get the appropriate shuffle mask
+	PSHUFB_XMM	%xmm2, %xmm1            # shift right 16-r13 byte
+	pxor	%xmm1, %xmm0            # Plaintext XOR Encrypt(K, Yn)
+	movdqu	ALL_F-SHIFT_MASK(%r12), %xmm1
+	# get the appropriate mask to mask out top 16-r13 bytes of xmm0
+	pand	%xmm1, %xmm0            # mask out top 16-r13 bytes of xmm0
+        movdqa SHUF_MASK(%rip), %xmm10
+	PSHUFB_XMM %xmm10,%xmm0
+
+	pxor	%xmm0, %xmm8
+	GHASH_MUL %xmm8, %xmm13, %xmm9, %xmm10, %xmm11, %xmm5, %xmm6
+	# GHASH computation for the last <16 byte block
+	sub	%r13, %r11
+	add	$16, %r11
+	PSHUFB_XMM %xmm10, %xmm1
+
+	# shuffle xmm0 back to output as ciphertext
+
+        # Output %r13 bytes
+	MOVQ_R64_XMM %xmm0, %rax
+	cmp $8, %r13
+	jle _less_than_8_bytes_left_encrypt
+	mov %rax, (%arg2 , %r11, 1)
+	add $8, %r11
+	psrldq $8, %xmm0
+	MOVQ_R64_XMM %xmm0, %rax
+	sub $8, %r13
+_less_than_8_bytes_left_encrypt:
+	mov %al,  (%arg2, %r11, 1)
+	add $1, %r11
+	shr $8, %rax
+	sub $1, %r13
+	jne _less_than_8_bytes_left_encrypt
+_multiple_of_16_bytes_encrypt:
+	mov	arg8, %r12    # %r12 = addLen (number of bytes)
+	shl	$3, %r12
+	movd	%r12d, %xmm15       # len(A) in %xmm15
+	shl	$3, %arg4               # len(C) in bits (*128)
+	MOVQ_R64_XMM	%arg4, %xmm1
+	pslldq	$8, %xmm15          # %xmm15 = len(A)||0x0000000000000000
+	pxor	%xmm1, %xmm15       # %xmm15 = len(A)||len(C)
+	pxor	%xmm15, %xmm8
+	GHASH_MUL	%xmm8, %xmm13, %xmm9, %xmm10, %xmm11, %xmm5, %xmm6
+	# final GHASH computation
+        movdqa SHUF_MASK(%rip), %xmm10
+	PSHUFB_XMM %xmm10, %xmm8         # perform a 16 byte swap
+
+	mov	%arg5, %rax		       # %rax  = *Y0
+	movdqu	(%rax), %xmm0		       # %xmm0 = Y0
+	ENCRYPT_SINGLE_BLOCK	%xmm0, %xmm15         # Encrypt(K, Y0)
+	pxor	%xmm8, %xmm0
+_return_T_encrypt:
+	mov	arg9, %r10                     # %r10 = authTag
+	mov	arg10, %r11                    # %r11 = auth_tag_len
+	cmp	$16, %r11
+	je	_T_16_encrypt
+	cmp	$12, %r11
+	je	_T_12_encrypt
+_T_8_encrypt:
+	MOVQ_R64_XMM	%xmm0, %rax
+	mov	%rax, (%r10)
+	jmp	_return_T_done_encrypt
+_T_12_encrypt:
+	MOVQ_R64_XMM	%xmm0, %rax
+	mov	%rax, (%r10)
+	psrldq	$8, %xmm0
+	movd	%xmm0, %eax
+	mov	%eax, 8(%r10)
+	jmp	_return_T_done_encrypt
+_T_16_encrypt:
+	movdqu	%xmm0, (%r10)
+_return_T_done_encrypt:
+	mov	%r14, %rsp
+	pop	%r14
+	pop	%r13
+	pop	%r12
+	ret
+
+#endif
+
 
 _key_expansion_128:
 _key_expansion_256a:
@@ -55,10 +1709,11 @@ _key_expansion_256a:
 	shufps $0b10001100, %xmm0, %xmm4
 	pxor %xmm4, %xmm0
 	pxor %xmm1, %xmm0
-	movaps %xmm0, (%rcx)
-	add $0x10, %rcx
+	movaps %xmm0, (TKEYP)
+	add $0x10, TKEYP
 	ret
 
+.align 4
 _key_expansion_192a:
 	pshufd $0b01010101, %xmm1, %xmm1
 	shufps $0b00010000, %xmm0, %xmm4
@@ -76,12 +1731,13 @@ _key_expansion_192a:
 
 	movaps %xmm0, %xmm1
 	shufps $0b01000100, %xmm0, %xmm6
-	movaps %xmm6, (%rcx)
+	movaps %xmm6, (TKEYP)
 	shufps $0b01001110, %xmm2, %xmm1
-	movaps %xmm1, 16(%rcx)
-	add $0x20, %rcx
+	movaps %xmm1, 0x10(TKEYP)
+	add $0x20, TKEYP
 	ret
 
+.align 4
 _key_expansion_192b:
 	pshufd $0b01010101, %xmm1, %xmm1
 	shufps $0b00010000, %xmm0, %xmm4
@@ -96,10 +1752,11 @@ _key_expansion_192b:
 	pxor %xmm3, %xmm2
 	pxor %xmm5, %xmm2
 
-	movaps %xmm0, (%rcx)
-	add $0x10, %rcx
+	movaps %xmm0, (TKEYP)
+	add $0x10, TKEYP
 	ret
 
+.align 4
 _key_expansion_256b:
 	pshufd $0b10101010, %xmm1, %xmm1
 	shufps $0b00010000, %xmm2, %xmm4
@@ -107,8 +1764,8 @@ _key_expansion_256b:
 	shufps $0b10001100, %xmm2, %xmm4
 	pxor %xmm4, %xmm2
 	pxor %xmm1, %xmm2
-	movaps %xmm2, (%rcx)
-	add $0x10, %rcx
+	movaps %xmm2, (TKEYP)
+	add $0x10, TKEYP
 	ret
 
 /*
@@ -116,17 +1773,23 @@ _key_expansion_256b:
  *                   unsigned int key_len)
  */
 ENTRY(aesni_set_key)
-	movups (%rsi), %xmm0		# user key (first 16 bytes)
-	movaps %xmm0, (%rdi)
-	lea 0x10(%rdi), %rcx		# key addr
-	movl %edx, 480(%rdi)
+#ifndef __x86_64__
+	pushl KEYP
+	movl 8(%esp), KEYP		# ctx
+	movl 12(%esp), UKEYP		# in_key
+	movl 16(%esp), %edx		# key_len
+#endif
+	movups (UKEYP), %xmm0		# user key (first 16 bytes)
+	movaps %xmm0, (KEYP)
+	lea 0x10(KEYP), TKEYP		# key addr
+	movl %edx, 480(KEYP)
 	pxor %xmm4, %xmm4		# xmm4 is assumed 0 in _key_expansion_x
 	cmp $24, %dl
 	jb .Lenc_key128
 	je .Lenc_key192
-	movups 0x10(%rsi), %xmm2	# other user key
-	movaps %xmm2, (%rcx)
-	add $0x10, %rcx
+	movups 0x10(UKEYP), %xmm2	# other user key
+	movaps %xmm2, (TKEYP)
+	add $0x10, TKEYP
 	AESKEYGENASSIST 0x1 %xmm2 %xmm1		# round 1
 	call _key_expansion_256a
 	AESKEYGENASSIST 0x1 %xmm0 %xmm1
@@ -155,7 +1818,7 @@ ENTRY(aesni_set_key)
 	call _key_expansion_256a
 	jmp .Ldec_key
 .Lenc_key192:
-	movq 0x10(%rsi), %xmm2		# other user key
+	movq 0x10(UKEYP), %xmm2		# other user key
 	AESKEYGENASSIST 0x1 %xmm2 %xmm1		# round 1
 	call _key_expansion_192a
 	AESKEYGENASSIST 0x2 %xmm2 %xmm1		# round 2
@@ -195,33 +1858,47 @@ ENTRY(aesni_set_key)
 	AESKEYGENASSIST 0x36 %xmm0 %xmm1	# round 10
 	call _key_expansion_128
 .Ldec_key:
-	sub $0x10, %rcx
-	movaps (%rdi), %xmm0
-	movaps (%rcx), %xmm1
-	movaps %xmm0, 240(%rcx)
-	movaps %xmm1, 240(%rdi)
-	add $0x10, %rdi
-	lea 240-16(%rcx), %rsi
+	sub $0x10, TKEYP
+	movaps (KEYP), %xmm0
+	movaps (TKEYP), %xmm1
+	movaps %xmm0, 240(TKEYP)
+	movaps %xmm1, 240(KEYP)
+	add $0x10, KEYP
+	lea 240-16(TKEYP), UKEYP
 .align 4
 .Ldec_key_loop:
-	movaps (%rdi), %xmm0
+	movaps (KEYP), %xmm0
 	AESIMC %xmm0 %xmm1
-	movaps %xmm1, (%rsi)
-	add $0x10, %rdi
-	sub $0x10, %rsi
-	cmp %rcx, %rdi
+	movaps %xmm1, (UKEYP)
+	add $0x10, KEYP
+	sub $0x10, UKEYP
+	cmp TKEYP, KEYP
 	jb .Ldec_key_loop
-	xor %rax, %rax
+	xor AREG, AREG
+#ifndef __x86_64__
+	popl KEYP
+#endif
 	ret
 
 /*
  * void aesni_enc(struct crypto_aes_ctx *ctx, u8 *dst, const u8 *src)
  */
 ENTRY(aesni_enc)
+#ifndef __x86_64__
+	pushl KEYP
+	pushl KLEN
+	movl 12(%esp), KEYP
+	movl 16(%esp), OUTP
+	movl 20(%esp), INP
+#endif
 	movl 480(KEYP), KLEN		# key length
 	movups (INP), STATE		# input
 	call _aesni_enc1
 	movups STATE, (OUTP)		# output
+#ifndef __x86_64__
+	popl KLEN
+	popl KEYP
+#endif
 	ret
 
 /*
@@ -236,6 +1913,7 @@ ENTRY(aesni_enc)
  *	KEY
  *	TKEYP (T1)
  */
+.align 4
 _aesni_enc1:
 	movaps (KEYP), KEY		# key
 	mov KEYP, TKEYP
@@ -298,6 +1976,7 @@ _aesni_enc1:
  *	KEY
  *	TKEYP (T1)
  */
+.align 4
 _aesni_enc4:
 	movaps (KEYP), KEY		# key
 	mov KEYP, TKEYP
@@ -391,11 +2070,22 @@ _aesni_enc4:
  * void aesni_dec (struct crypto_aes_ctx *ctx, u8 *dst, const u8 *src)
  */
 ENTRY(aesni_dec)
+#ifndef __x86_64__
+	pushl KEYP
+	pushl KLEN
+	movl 12(%esp), KEYP
+	movl 16(%esp), OUTP
+	movl 20(%esp), INP
+#endif
 	mov 480(KEYP), KLEN		# key length
 	add $240, KEYP
 	movups (INP), STATE		# input
 	call _aesni_dec1
 	movups STATE, (OUTP)		#output
+#ifndef __x86_64__
+	popl KLEN
+	popl KEYP
+#endif
 	ret
 
 /*
@@ -410,6 +2100,7 @@ ENTRY(aesni_dec)
  *	KEY
  *	TKEYP (T1)
  */
+.align 4
 _aesni_dec1:
 	movaps (KEYP), KEY		# key
 	mov KEYP, TKEYP
@@ -472,6 +2163,7 @@ _aesni_dec1:
  *	KEY
  *	TKEYP (T1)
  */
+.align 4
 _aesni_dec4:
 	movaps (KEYP), KEY		# key
 	mov KEYP, TKEYP
@@ -566,6 +2258,15 @@ _aesni_dec4:
  *		      size_t len)
  */
 ENTRY(aesni_ecb_enc)
+#ifndef __x86_64__
+	pushl LEN
+	pushl KEYP
+	pushl KLEN
+	movl 16(%esp), KEYP
+	movl 20(%esp), OUTP
+	movl 24(%esp), INP
+	movl 28(%esp), LEN
+#endif
 	test LEN, LEN		# check length
 	jz .Lecb_enc_ret
 	mov 480(KEYP), KLEN
@@ -602,6 +2303,11 @@ ENTRY(aesni_ecb_enc)
 	cmp $16, LEN
 	jge .Lecb_enc_loop1
 .Lecb_enc_ret:
+#ifndef __x86_64__
+	popl KLEN
+	popl KEYP
+	popl LEN
+#endif
 	ret
 
 /*
@@ -609,6 +2315,15 @@ ENTRY(aesni_ecb_enc)
  *		      size_t len);
  */
 ENTRY(aesni_ecb_dec)
+#ifndef __x86_64__
+	pushl LEN
+	pushl KEYP
+	pushl KLEN
+	movl 16(%esp), KEYP
+	movl 20(%esp), OUTP
+	movl 24(%esp), INP
+	movl 28(%esp), LEN
+#endif
 	test LEN, LEN
 	jz .Lecb_dec_ret
 	mov 480(KEYP), KLEN
@@ -646,6 +2361,11 @@ ENTRY(aesni_ecb_dec)
 	cmp $16, LEN
 	jge .Lecb_dec_loop1
 .Lecb_dec_ret:
+#ifndef __x86_64__
+	popl KLEN
+	popl KEYP
+	popl LEN
+#endif
 	ret
 
 /*
@@ -653,6 +2373,17 @@ ENTRY(aesni_ecb_dec)
  *		      size_t len, u8 *iv)
  */
 ENTRY(aesni_cbc_enc)
+#ifndef __x86_64__
+	pushl IVP
+	pushl LEN
+	pushl KEYP
+	pushl KLEN
+	movl 20(%esp), KEYP
+	movl 24(%esp), OUTP
+	movl 28(%esp), INP
+	movl 32(%esp), LEN
+	movl 36(%esp), IVP
+#endif
 	cmp $16, LEN
 	jb .Lcbc_enc_ret
 	mov 480(KEYP), KLEN
@@ -670,6 +2401,12 @@ ENTRY(aesni_cbc_enc)
 	jge .Lcbc_enc_loop
 	movups STATE, (IVP)
 .Lcbc_enc_ret:
+#ifndef __x86_64__
+	popl KLEN
+	popl KEYP
+	popl LEN
+	popl IVP
+#endif
 	ret
 
 /*
@@ -677,6 +2414,17 @@ ENTRY(aesni_cbc_enc)
  *		      size_t len, u8 *iv)
  */
 ENTRY(aesni_cbc_dec)
+#ifndef __x86_64__
+	pushl IVP
+	pushl LEN
+	pushl KEYP
+	pushl KLEN
+	movl 20(%esp), KEYP
+	movl 24(%esp), OUTP
+	movl 28(%esp), INP
+	movl 32(%esp), LEN
+	movl 36(%esp), IVP
+#endif
 	cmp $16, LEN
 	jb .Lcbc_dec_just_ret
 	mov 480(KEYP), KLEN
@@ -690,16 +2438,30 @@ ENTRY(aesni_cbc_dec)
 	movaps IN1, STATE1
 	movups 0x10(INP), IN2
 	movaps IN2, STATE2
+#ifdef __x86_64__
 	movups 0x20(INP), IN3
 	movaps IN3, STATE3
 	movups 0x30(INP), IN4
 	movaps IN4, STATE4
+#else
+	movups 0x20(INP), IN1
+	movaps IN1, STATE3
+	movups 0x30(INP), IN2
+	movaps IN2, STATE4
+#endif
 	call _aesni_dec4
 	pxor IV, STATE1
+#ifdef __x86_64__
 	pxor IN1, STATE2
 	pxor IN2, STATE3
 	pxor IN3, STATE4
 	movaps IN4, IV
+#else
+	pxor (INP), STATE2
+	pxor 0x10(INP), STATE3
+	pxor IN1, STATE4
+	movaps IN2, IV
+#endif
 	movups STATE1, (OUTP)
 	movups STATE2, 0x10(OUTP)
 	movups STATE3, 0x20(OUTP)
@@ -727,8 +2489,15 @@ ENTRY(aesni_cbc_dec)
 .Lcbc_dec_ret:
 	movups IV, (IVP)
 .Lcbc_dec_just_ret:
+#ifndef __x86_64__
+	popl KLEN
+	popl KEYP
+	popl LEN
+	popl IVP
+#endif
 	ret
 
+#ifdef __x86_64__
 .align 16
 .Lbswap_mask:
 	.byte 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
@@ -744,6 +2513,7 @@ ENTRY(aesni_cbc_dec)
  *	INC:	== 1, in little endian
  *	BSWAP_MASK == endian swapping mask
  */
+.align 4
 _aesni_inc_init:
 	movaps .Lbswap_mask, BSWAP_MASK
 	movaps IV, CTR
@@ -768,6 +2538,7 @@ _aesni_inc_init:
  *	CTR:	== output IV, in little endian
  *	TCTR_LOW: == lower qword of CTR
  */
+.align 4
 _aesni_inc:
 	paddq INC, CTR
 	add $1, TCTR_LOW
@@ -839,3 +2610,4 @@ ENTRY(aesni_ctr_enc)
 	movups IV, (IVP)
 .Lctr_enc_just_ret:
 	ret
+#endif
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/crypto/aesni-intel_glue.c linux-libre-2.6.38-gnu1/arch/x86/crypto/aesni-intel_glue.c
--- linux-libre-2.6.37-gnu1/arch/x86/crypto/aesni-intel_glue.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/crypto/aesni-intel_glue.c	2011-03-14 21:20:32.000000000 -0400
@@ -5,6 +5,14 @@
  * Copyright (C) 2008, Intel Corp.
  *    Author: Huang Ying <ying.huang@intel.com>
  *
+ * Added RFC4106 AES-GCM support for 128-bit keys under the AEAD
+ * interface for 64-bit kernels.
+ *    Authors: Adrian Hoban <adrian.hoban@intel.com>
+ *             Gabriele Paoloni <gabriele.paoloni@intel.com>
+ *             Tadeusz Struk (tadeusz.struk@intel.com)
+ *             Aidan O'Mahony (aidan.o.mahony@intel.com)
+ *    Copyright (c) 2010, 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
@@ -21,6 +29,10 @@
 #include <crypto/ctr.h>
 #include <asm/i387.h>
 #include <asm/aes.h>
+#include <crypto/scatterwalk.h>
+#include <crypto/internal/aead.h>
+#include <linux/workqueue.h>
+#include <linux/spinlock.h>
 
 #if defined(CONFIG_CRYPTO_CTR) || defined(CONFIG_CRYPTO_CTR_MODULE)
 #define HAS_CTR
@@ -42,8 +54,31 @@ struct async_aes_ctx {
 	struct cryptd_ablkcipher *cryptd_tfm;
 };
 
-#define AESNI_ALIGN	16
+/* This data is stored at the end of the crypto_tfm struct.
+ * It's a type of per "session" data storage location.
+ * This needs to be 16 byte aligned.
+ */
+struct aesni_rfc4106_gcm_ctx {
+	u8 hash_subkey[16];
+	struct crypto_aes_ctx aes_key_expanded;
+	u8 nonce[4];
+	struct cryptd_aead *cryptd_tfm;
+};
+
+struct aesni_gcm_set_hash_subkey_result {
+	int err;
+	struct completion completion;
+};
+
+struct aesni_hash_subkey_req_data {
+	u8 iv[16];
+	struct aesni_gcm_set_hash_subkey_result result;
+	struct scatterlist sg;
+};
+
+#define AESNI_ALIGN	(16)
 #define AES_BLOCK_MASK	(~(AES_BLOCK_SIZE-1))
+#define RFC4106_HASH_SUBKEY_SIZE 16
 
 asmlinkage int aesni_set_key(struct crypto_aes_ctx *ctx, const u8 *in_key,
 			     unsigned int key_len);
@@ -59,9 +94,62 @@ asmlinkage void aesni_cbc_enc(struct cry
 			      const u8 *in, unsigned int len, u8 *iv);
 asmlinkage void aesni_cbc_dec(struct crypto_aes_ctx *ctx, u8 *out,
 			      const u8 *in, unsigned int len, u8 *iv);
+#ifdef CONFIG_X86_64
 asmlinkage void aesni_ctr_enc(struct crypto_aes_ctx *ctx, u8 *out,
 			      const u8 *in, unsigned int len, u8 *iv);
 
+/* asmlinkage void aesni_gcm_enc()
+ * void *ctx,  AES Key schedule. Starts on a 16 byte boundary.
+ * u8 *out, Ciphertext output. Encrypt in-place is allowed.
+ * const u8 *in, Plaintext input
+ * unsigned long plaintext_len, Length of data in bytes for encryption.
+ * u8 *iv, Pre-counter block j0: 4 byte salt (from Security Association)
+ *         concatenated with 8 byte Initialisation Vector (from IPSec ESP
+ *         Payload) concatenated with 0x00000001. 16-byte aligned pointer.
+ * u8 *hash_subkey, the Hash sub key input. Data starts on a 16-byte boundary.
+ * const u8 *aad, Additional Authentication Data (AAD)
+ * unsigned long aad_len, Length of AAD in bytes. With RFC4106 this
+ *          is going to be 8 or 12 bytes
+ * u8 *auth_tag, Authenticated Tag output.
+ * unsigned long auth_tag_len), Authenticated Tag Length in bytes.
+ *          Valid values are 16 (most likely), 12 or 8.
+ */
+asmlinkage void aesni_gcm_enc(void *ctx, u8 *out,
+			const u8 *in, unsigned long plaintext_len, u8 *iv,
+			u8 *hash_subkey, const u8 *aad, unsigned long aad_len,
+			u8 *auth_tag, unsigned long auth_tag_len);
+
+/* asmlinkage void aesni_gcm_dec()
+ * void *ctx, AES Key schedule. Starts on a 16 byte boundary.
+ * u8 *out, Plaintext output. Decrypt in-place is allowed.
+ * const u8 *in, Ciphertext input
+ * unsigned long ciphertext_len, Length of data in bytes for decryption.
+ * u8 *iv, Pre-counter block j0: 4 byte salt (from Security Association)
+ *         concatenated with 8 byte Initialisation Vector (from IPSec ESP
+ *         Payload) concatenated with 0x00000001. 16-byte aligned pointer.
+ * u8 *hash_subkey, the Hash sub key input. Data starts on a 16-byte boundary.
+ * const u8 *aad, Additional Authentication Data (AAD)
+ * unsigned long aad_len, Length of AAD in bytes. With RFC4106 this is going
+ * to be 8 or 12 bytes
+ * u8 *auth_tag, Authenticated Tag output.
+ * unsigned long auth_tag_len) Authenticated Tag Length in bytes.
+ * Valid values are 16 (most likely), 12 or 8.
+ */
+asmlinkage void aesni_gcm_dec(void *ctx, u8 *out,
+			const u8 *in, unsigned long ciphertext_len, u8 *iv,
+			u8 *hash_subkey, const u8 *aad, unsigned long aad_len,
+			u8 *auth_tag, unsigned long auth_tag_len);
+
+static inline struct
+aesni_rfc4106_gcm_ctx *aesni_rfc4106_gcm_ctx_get(struct crypto_aead *tfm)
+{
+	return
+		(struct aesni_rfc4106_gcm_ctx *)
+		PTR_ALIGN((u8 *)
+		crypto_tfm_ctx(crypto_aead_tfm(tfm)), AESNI_ALIGN);
+}
+#endif
+
 static inline struct crypto_aes_ctx *aes_ctx(void *raw_ctx)
 {
 	unsigned long addr = (unsigned long)raw_ctx;
@@ -324,6 +412,7 @@ static struct crypto_alg blk_cbc_alg = {
 	},
 };
 
+#ifdef CONFIG_X86_64
 static void ctr_crypt_final(struct crypto_aes_ctx *ctx,
 			    struct blkcipher_walk *walk)
 {
@@ -389,6 +478,7 @@ static struct crypto_alg blk_ctr_alg = {
 		},
 	},
 };
+#endif
 
 static int ablk_set_key(struct crypto_ablkcipher *tfm, const u8 *key,
 			unsigned int key_len)
@@ -536,6 +626,7 @@ static struct crypto_alg ablk_cbc_alg =
 	},
 };
 
+#ifdef CONFIG_X86_64
 static int ablk_ctr_init(struct crypto_tfm *tfm)
 {
 	struct cryptd_ablkcipher *cryptd_tfm;
@@ -612,6 +703,7 @@ static struct crypto_alg ablk_rfc3686_ct
 	},
 };
 #endif
+#endif
 
 #ifdef HAS_LRW
 static int ablk_lrw_init(struct crypto_tfm *tfm)
@@ -730,6 +822,424 @@ static struct crypto_alg ablk_xts_alg =
 };
 #endif
 
+#ifdef CONFIG_X86_64
+static int rfc4106_init(struct crypto_tfm *tfm)
+{
+	struct cryptd_aead *cryptd_tfm;
+	struct aesni_rfc4106_gcm_ctx *ctx = (struct aesni_rfc4106_gcm_ctx *)
+		PTR_ALIGN((u8 *)crypto_tfm_ctx(tfm), AESNI_ALIGN);
+	cryptd_tfm = cryptd_alloc_aead("__driver-gcm-aes-aesni", 0, 0);
+	if (IS_ERR(cryptd_tfm))
+		return PTR_ERR(cryptd_tfm);
+	ctx->cryptd_tfm = cryptd_tfm;
+	tfm->crt_aead.reqsize = sizeof(struct aead_request)
+		+ crypto_aead_reqsize(&cryptd_tfm->base);
+	return 0;
+}
+
+static void rfc4106_exit(struct crypto_tfm *tfm)
+{
+	struct aesni_rfc4106_gcm_ctx *ctx =
+		(struct aesni_rfc4106_gcm_ctx *)
+		PTR_ALIGN((u8 *)crypto_tfm_ctx(tfm), AESNI_ALIGN);
+	if (!IS_ERR(ctx->cryptd_tfm))
+		cryptd_free_aead(ctx->cryptd_tfm);
+	return;
+}
+
+static void
+rfc4106_set_hash_subkey_done(struct crypto_async_request *req, int err)
+{
+	struct aesni_gcm_set_hash_subkey_result *result = req->data;
+
+	if (err == -EINPROGRESS)
+		return;
+	result->err = err;
+	complete(&result->completion);
+}
+
+static int
+rfc4106_set_hash_subkey(u8 *hash_subkey, const u8 *key, unsigned int key_len)
+{
+	struct crypto_ablkcipher *ctr_tfm;
+	struct ablkcipher_request *req;
+	int ret = -EINVAL;
+	struct aesni_hash_subkey_req_data *req_data;
+
+	ctr_tfm = crypto_alloc_ablkcipher("ctr(aes)", 0, 0);
+	if (IS_ERR(ctr_tfm))
+		return PTR_ERR(ctr_tfm);
+
+	crypto_ablkcipher_clear_flags(ctr_tfm, ~0);
+
+	ret = crypto_ablkcipher_setkey(ctr_tfm, key, key_len);
+	if (ret) {
+		crypto_free_ablkcipher(ctr_tfm);
+		return ret;
+	}
+
+	req = ablkcipher_request_alloc(ctr_tfm, GFP_KERNEL);
+	if (!req) {
+		crypto_free_ablkcipher(ctr_tfm);
+		return -EINVAL;
+	}
+
+	req_data = kmalloc(sizeof(*req_data), GFP_KERNEL);
+	if (!req_data) {
+		crypto_free_ablkcipher(ctr_tfm);
+		return -ENOMEM;
+	}
+	memset(req_data->iv, 0, sizeof(req_data->iv));
+
+	/* Clear the data in the hash sub key container to zero.*/
+	/* We want to cipher all zeros to create the hash sub key. */
+	memset(hash_subkey, 0, RFC4106_HASH_SUBKEY_SIZE);
+
+	init_completion(&req_data->result.completion);
+	sg_init_one(&req_data->sg, hash_subkey, RFC4106_HASH_SUBKEY_SIZE);
+	ablkcipher_request_set_tfm(req, ctr_tfm);
+	ablkcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_SLEEP |
+					CRYPTO_TFM_REQ_MAY_BACKLOG,
+					rfc4106_set_hash_subkey_done,
+					&req_data->result);
+
+	ablkcipher_request_set_crypt(req, &req_data->sg,
+		&req_data->sg, RFC4106_HASH_SUBKEY_SIZE, req_data->iv);
+
+	ret = crypto_ablkcipher_encrypt(req);
+	if (ret == -EINPROGRESS || ret == -EBUSY) {
+		ret = wait_for_completion_interruptible
+			(&req_data->result.completion);
+		if (!ret)
+			ret = req_data->result.err;
+	}
+	ablkcipher_request_free(req);
+	kfree(req_data);
+	crypto_free_ablkcipher(ctr_tfm);
+	return ret;
+}
+
+static int rfc4106_set_key(struct crypto_aead *parent, const u8 *key,
+						   unsigned int key_len)
+{
+	int ret = 0;
+	struct crypto_tfm *tfm = crypto_aead_tfm(parent);
+	struct aesni_rfc4106_gcm_ctx *ctx = aesni_rfc4106_gcm_ctx_get(parent);
+	u8 *new_key_mem = NULL;
+
+	if (key_len < 4) {
+		crypto_tfm_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
+		return -EINVAL;
+	}
+	/*Account for 4 byte nonce at the end.*/
+	key_len -= 4;
+	if (key_len != AES_KEYSIZE_128) {
+		crypto_tfm_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
+		return -EINVAL;
+	}
+
+	memcpy(ctx->nonce, key + key_len, sizeof(ctx->nonce));
+	/*This must be on a 16 byte boundary!*/
+	if ((unsigned long)(&(ctx->aes_key_expanded.key_enc[0])) % AESNI_ALIGN)
+		return -EINVAL;
+
+	if ((unsigned long)key % AESNI_ALIGN) {
+		/*key is not aligned: use an auxuliar aligned pointer*/
+		new_key_mem = kmalloc(key_len+AESNI_ALIGN, GFP_KERNEL);
+		if (!new_key_mem)
+			return -ENOMEM;
+
+		new_key_mem = PTR_ALIGN(new_key_mem, AESNI_ALIGN);
+		memcpy(new_key_mem, key, key_len);
+		key = new_key_mem;
+	}
+
+	if (!irq_fpu_usable())
+		ret = crypto_aes_expand_key(&(ctx->aes_key_expanded),
+		key, key_len);
+	else {
+		kernel_fpu_begin();
+		ret = aesni_set_key(&(ctx->aes_key_expanded), key, key_len);
+		kernel_fpu_end();
+	}
+	/*This must be on a 16 byte boundary!*/
+	if ((unsigned long)(&(ctx->hash_subkey[0])) % AESNI_ALIGN) {
+		ret = -EINVAL;
+		goto exit;
+	}
+	ret = rfc4106_set_hash_subkey(ctx->hash_subkey, key, key_len);
+exit:
+	kfree(new_key_mem);
+	return ret;
+}
+
+/* This is the Integrity Check Value (aka the authentication tag length and can
+ * be 8, 12 or 16 bytes long. */
+static int rfc4106_set_authsize(struct crypto_aead *parent,
+				unsigned int authsize)
+{
+	struct aesni_rfc4106_gcm_ctx *ctx = aesni_rfc4106_gcm_ctx_get(parent);
+	struct crypto_aead *cryptd_child = cryptd_aead_child(ctx->cryptd_tfm);
+
+	switch (authsize) {
+	case 8:
+	case 12:
+	case 16:
+		break;
+	default:
+		return -EINVAL;
+	}
+	crypto_aead_crt(parent)->authsize = authsize;
+	crypto_aead_crt(cryptd_child)->authsize = authsize;
+	return 0;
+}
+
+static int rfc4106_encrypt(struct aead_request *req)
+{
+	int ret;
+	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
+	struct aesni_rfc4106_gcm_ctx *ctx = aesni_rfc4106_gcm_ctx_get(tfm);
+	struct crypto_aead *cryptd_child = cryptd_aead_child(ctx->cryptd_tfm);
+
+	if (!irq_fpu_usable()) {
+		struct aead_request *cryptd_req =
+			(struct aead_request *) aead_request_ctx(req);
+		memcpy(cryptd_req, req, sizeof(*req));
+		aead_request_set_tfm(cryptd_req, &ctx->cryptd_tfm->base);
+		return crypto_aead_encrypt(cryptd_req);
+	} else {
+		kernel_fpu_begin();
+		ret = cryptd_child->base.crt_aead.encrypt(req);
+		kernel_fpu_end();
+		return ret;
+	}
+}
+
+static int rfc4106_decrypt(struct aead_request *req)
+{
+	int ret;
+	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
+	struct aesni_rfc4106_gcm_ctx *ctx = aesni_rfc4106_gcm_ctx_get(tfm);
+	struct crypto_aead *cryptd_child = cryptd_aead_child(ctx->cryptd_tfm);
+
+	if (!irq_fpu_usable()) {
+		struct aead_request *cryptd_req =
+			(struct aead_request *) aead_request_ctx(req);
+		memcpy(cryptd_req, req, sizeof(*req));
+		aead_request_set_tfm(cryptd_req, &ctx->cryptd_tfm->base);
+		return crypto_aead_decrypt(cryptd_req);
+	} else {
+		kernel_fpu_begin();
+		ret = cryptd_child->base.crt_aead.decrypt(req);
+		kernel_fpu_end();
+		return ret;
+	}
+}
+
+static struct crypto_alg rfc4106_alg = {
+	.cra_name = "rfc4106(gcm(aes))",
+	.cra_driver_name = "rfc4106-gcm-aesni",
+	.cra_priority = 400,
+	.cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC,
+	.cra_blocksize = 1,
+	.cra_ctxsize = sizeof(struct aesni_rfc4106_gcm_ctx) + AESNI_ALIGN,
+	.cra_alignmask = 0,
+	.cra_type = &crypto_nivaead_type,
+	.cra_module = THIS_MODULE,
+	.cra_list = LIST_HEAD_INIT(rfc4106_alg.cra_list),
+	.cra_init = rfc4106_init,
+	.cra_exit = rfc4106_exit,
+	.cra_u = {
+		.aead = {
+			.setkey = rfc4106_set_key,
+			.setauthsize = rfc4106_set_authsize,
+			.encrypt = rfc4106_encrypt,
+			.decrypt = rfc4106_decrypt,
+			.geniv = "seqiv",
+			.ivsize = 8,
+			.maxauthsize = 16,
+		},
+	},
+};
+
+static int __driver_rfc4106_encrypt(struct aead_request *req)
+{
+	u8 one_entry_in_sg = 0;
+	u8 *src, *dst, *assoc;
+	__be32 counter = cpu_to_be32(1);
+	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
+	struct aesni_rfc4106_gcm_ctx *ctx = aesni_rfc4106_gcm_ctx_get(tfm);
+	void *aes_ctx = &(ctx->aes_key_expanded);
+	unsigned long auth_tag_len = crypto_aead_authsize(tfm);
+	u8 iv_tab[16+AESNI_ALIGN];
+	u8* iv = (u8 *) PTR_ALIGN((u8 *)iv_tab, AESNI_ALIGN);
+	struct scatter_walk src_sg_walk;
+	struct scatter_walk assoc_sg_walk;
+	struct scatter_walk dst_sg_walk;
+	unsigned int i;
+
+	/* Assuming we are supporting rfc4106 64-bit extended */
+	/* sequence numbers We need to have the AAD length equal */
+	/* to 8 or 12 bytes */
+	if (unlikely(req->assoclen != 8 && req->assoclen != 12))
+		return -EINVAL;
+	/* IV below built */
+	for (i = 0; i < 4; i++)
+		*(iv+i) = ctx->nonce[i];
+	for (i = 0; i < 8; i++)
+		*(iv+4+i) = req->iv[i];
+	*((__be32 *)(iv+12)) = counter;
+
+	if ((sg_is_last(req->src)) && (sg_is_last(req->assoc))) {
+		one_entry_in_sg = 1;
+		scatterwalk_start(&src_sg_walk, req->src);
+		scatterwalk_start(&assoc_sg_walk, req->assoc);
+		src = scatterwalk_map(&src_sg_walk, 0);
+		assoc = scatterwalk_map(&assoc_sg_walk, 0);
+		dst = src;
+		if (unlikely(req->src != req->dst)) {
+			scatterwalk_start(&dst_sg_walk, req->dst);
+			dst = scatterwalk_map(&dst_sg_walk, 0);
+		}
+
+	} else {
+		/* Allocate memory for src, dst, assoc */
+		src = kmalloc(req->cryptlen + auth_tag_len + req->assoclen,
+			GFP_ATOMIC);
+		if (unlikely(!src))
+			return -ENOMEM;
+		assoc = (src + req->cryptlen + auth_tag_len);
+		scatterwalk_map_and_copy(src, req->src, 0, req->cryptlen, 0);
+		scatterwalk_map_and_copy(assoc, req->assoc, 0,
+					req->assoclen, 0);
+		dst = src;
+	}
+
+	aesni_gcm_enc(aes_ctx, dst, src, (unsigned long)req->cryptlen, iv,
+		ctx->hash_subkey, assoc, (unsigned long)req->assoclen, dst
+		+ ((unsigned long)req->cryptlen), auth_tag_len);
+
+	/* The authTag (aka the Integrity Check Value) needs to be written
+	 * back to the packet. */
+	if (one_entry_in_sg) {
+		if (unlikely(req->src != req->dst)) {
+			scatterwalk_unmap(dst, 0);
+			scatterwalk_done(&dst_sg_walk, 0, 0);
+		}
+		scatterwalk_unmap(src, 0);
+		scatterwalk_unmap(assoc, 0);
+		scatterwalk_done(&src_sg_walk, 0, 0);
+		scatterwalk_done(&assoc_sg_walk, 0, 0);
+	} else {
+		scatterwalk_map_and_copy(dst, req->dst, 0,
+			req->cryptlen + auth_tag_len, 1);
+		kfree(src);
+	}
+	return 0;
+}
+
+static int __driver_rfc4106_decrypt(struct aead_request *req)
+{
+	u8 one_entry_in_sg = 0;
+	u8 *src, *dst, *assoc;
+	unsigned long tempCipherLen = 0;
+	__be32 counter = cpu_to_be32(1);
+	int retval = 0;
+	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
+	struct aesni_rfc4106_gcm_ctx *ctx = aesni_rfc4106_gcm_ctx_get(tfm);
+	void *aes_ctx = &(ctx->aes_key_expanded);
+	unsigned long auth_tag_len = crypto_aead_authsize(tfm);
+	u8 iv_and_authTag[32+AESNI_ALIGN];
+	u8 *iv = (u8 *) PTR_ALIGN((u8 *)iv_and_authTag, AESNI_ALIGN);
+	u8 *authTag = iv + 16;
+	struct scatter_walk src_sg_walk;
+	struct scatter_walk assoc_sg_walk;
+	struct scatter_walk dst_sg_walk;
+	unsigned int i;
+
+	if (unlikely((req->cryptlen < auth_tag_len) ||
+		(req->assoclen != 8 && req->assoclen != 12)))
+		return -EINVAL;
+	/* Assuming we are supporting rfc4106 64-bit extended */
+	/* sequence numbers We need to have the AAD length */
+	/* equal to 8 or 12 bytes */
+
+	tempCipherLen = (unsigned long)(req->cryptlen - auth_tag_len);
+	/* IV below built */
+	for (i = 0; i < 4; i++)
+		*(iv+i) = ctx->nonce[i];
+	for (i = 0; i < 8; i++)
+		*(iv+4+i) = req->iv[i];
+	*((__be32 *)(iv+12)) = counter;
+
+	if ((sg_is_last(req->src)) && (sg_is_last(req->assoc))) {
+		one_entry_in_sg = 1;
+		scatterwalk_start(&src_sg_walk, req->src);
+		scatterwalk_start(&assoc_sg_walk, req->assoc);
+		src = scatterwalk_map(&src_sg_walk, 0);
+		assoc = scatterwalk_map(&assoc_sg_walk, 0);
+		dst = src;
+		if (unlikely(req->src != req->dst)) {
+			scatterwalk_start(&dst_sg_walk, req->dst);
+			dst = scatterwalk_map(&dst_sg_walk, 0);
+		}
+
+	} else {
+		/* Allocate memory for src, dst, assoc */
+		src = kmalloc(req->cryptlen + req->assoclen, GFP_ATOMIC);
+		if (!src)
+			return -ENOMEM;
+		assoc = (src + req->cryptlen + auth_tag_len);
+		scatterwalk_map_and_copy(src, req->src, 0, req->cryptlen, 0);
+		scatterwalk_map_and_copy(assoc, req->assoc, 0,
+			req->assoclen, 0);
+		dst = src;
+	}
+
+	aesni_gcm_dec(aes_ctx, dst, src, tempCipherLen, iv,
+		ctx->hash_subkey, assoc, (unsigned long)req->assoclen,
+		authTag, auth_tag_len);
+
+	/* Compare generated tag with passed in tag. */
+	retval = memcmp(src + tempCipherLen, authTag, auth_tag_len) ?
+		-EBADMSG : 0;
+
+	if (one_entry_in_sg) {
+		if (unlikely(req->src != req->dst)) {
+			scatterwalk_unmap(dst, 0);
+			scatterwalk_done(&dst_sg_walk, 0, 0);
+		}
+		scatterwalk_unmap(src, 0);
+		scatterwalk_unmap(assoc, 0);
+		scatterwalk_done(&src_sg_walk, 0, 0);
+		scatterwalk_done(&assoc_sg_walk, 0, 0);
+	} else {
+		scatterwalk_map_and_copy(dst, req->dst, 0, req->cryptlen, 1);
+		kfree(src);
+	}
+	return retval;
+}
+
+static struct crypto_alg __rfc4106_alg = {
+	.cra_name		= "__gcm-aes-aesni",
+	.cra_driver_name	= "__driver-gcm-aes-aesni",
+	.cra_priority		= 0,
+	.cra_flags		= CRYPTO_ALG_TYPE_AEAD,
+	.cra_blocksize		= 1,
+	.cra_ctxsize	= sizeof(struct aesni_rfc4106_gcm_ctx) + AESNI_ALIGN,
+	.cra_alignmask		= 0,
+	.cra_type		= &crypto_aead_type,
+	.cra_module		= THIS_MODULE,
+	.cra_list		= LIST_HEAD_INIT(__rfc4106_alg.cra_list),
+	.cra_u = {
+		.aead = {
+			.encrypt	= __driver_rfc4106_encrypt,
+			.decrypt	= __driver_rfc4106_decrypt,
+		},
+	},
+};
+#endif
+
 static int __init aesni_init(void)
 {
 	int err;
@@ -738,6 +1248,7 @@ static int __init aesni_init(void)
 		printk(KERN_INFO "Intel AES-NI instructions are not detected.\n");
 		return -ENODEV;
 	}
+
 	if ((err = crypto_register_alg(&aesni_alg)))
 		goto aes_err;
 	if ((err = crypto_register_alg(&__aesni_alg)))
@@ -746,18 +1257,24 @@ static int __init aesni_init(void)
 		goto blk_ecb_err;
 	if ((err = crypto_register_alg(&blk_cbc_alg)))
 		goto blk_cbc_err;
-	if ((err = crypto_register_alg(&blk_ctr_alg)))
-		goto blk_ctr_err;
 	if ((err = crypto_register_alg(&ablk_ecb_alg)))
 		goto ablk_ecb_err;
 	if ((err = crypto_register_alg(&ablk_cbc_alg)))
 		goto ablk_cbc_err;
+#ifdef CONFIG_X86_64
+	if ((err = crypto_register_alg(&blk_ctr_alg)))
+		goto blk_ctr_err;
 	if ((err = crypto_register_alg(&ablk_ctr_alg)))
 		goto ablk_ctr_err;
+	if ((err = crypto_register_alg(&__rfc4106_alg)))
+		goto __aead_gcm_err;
+	if ((err = crypto_register_alg(&rfc4106_alg)))
+		goto aead_gcm_err;
 #ifdef HAS_CTR
 	if ((err = crypto_register_alg(&ablk_rfc3686_ctr_alg)))
 		goto ablk_rfc3686_ctr_err;
 #endif
+#endif
 #ifdef HAS_LRW
 	if ((err = crypto_register_alg(&ablk_lrw_alg)))
 		goto ablk_lrw_err;
@@ -770,7 +1287,6 @@ static int __init aesni_init(void)
 	if ((err = crypto_register_alg(&ablk_xts_alg)))
 		goto ablk_xts_err;
 #endif
-
 	return err;
 
 #ifdef HAS_XTS
@@ -784,18 +1300,24 @@ ablk_pcbc_err:
 	crypto_unregister_alg(&ablk_lrw_alg);
 ablk_lrw_err:
 #endif
+#ifdef CONFIG_X86_64
 #ifdef HAS_CTR
 	crypto_unregister_alg(&ablk_rfc3686_ctr_alg);
 ablk_rfc3686_ctr_err:
 #endif
+	crypto_unregister_alg(&rfc4106_alg);
+aead_gcm_err:
+	crypto_unregister_alg(&__rfc4106_alg);
+__aead_gcm_err:
 	crypto_unregister_alg(&ablk_ctr_alg);
 ablk_ctr_err:
+	crypto_unregister_alg(&blk_ctr_alg);
+blk_ctr_err:
+#endif
 	crypto_unregister_alg(&ablk_cbc_alg);
 ablk_cbc_err:
 	crypto_unregister_alg(&ablk_ecb_alg);
 ablk_ecb_err:
-	crypto_unregister_alg(&blk_ctr_alg);
-blk_ctr_err:
 	crypto_unregister_alg(&blk_cbc_alg);
 blk_cbc_err:
 	crypto_unregister_alg(&blk_ecb_alg);
@@ -818,13 +1340,17 @@ static void __exit aesni_exit(void)
 #ifdef HAS_LRW
 	crypto_unregister_alg(&ablk_lrw_alg);
 #endif
+#ifdef CONFIG_X86_64
 #ifdef HAS_CTR
 	crypto_unregister_alg(&ablk_rfc3686_ctr_alg);
 #endif
+	crypto_unregister_alg(&rfc4106_alg);
+	crypto_unregister_alg(&__rfc4106_alg);
 	crypto_unregister_alg(&ablk_ctr_alg);
+	crypto_unregister_alg(&blk_ctr_alg);
+#endif
 	crypto_unregister_alg(&ablk_cbc_alg);
 	crypto_unregister_alg(&ablk_ecb_alg);
-	crypto_unregister_alg(&blk_ctr_alg);
 	crypto_unregister_alg(&blk_cbc_alg);
 	crypto_unregister_alg(&blk_ecb_alg);
 	crypto_unregister_alg(&__aesni_alg);
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/include/asm/acpi.h linux-libre-2.6.38-gnu1/arch/x86/include/asm/acpi.h
--- linux-libre-2.6.37-gnu1/arch/x86/include/asm/acpi.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/include/asm/acpi.h	2011-03-14 21:20:32.000000000 -0400
@@ -88,6 +88,7 @@ extern int acpi_disabled;
 extern int acpi_pci_disabled;
 extern int acpi_skip_timer_override;
 extern int acpi_use_timer_override;
+extern int acpi_fix_pin2_polarity;
 
 extern u8 acpi_sci_flags;
 extern int acpi_sci_override_gsi;
@@ -185,17 +186,16 @@ struct bootnode;
 
 #ifdef CONFIG_ACPI_NUMA
 extern int acpi_numa;
-extern int acpi_get_nodes(struct bootnode *physnodes);
+extern void acpi_get_nodes(struct bootnode *physnodes, unsigned long start,
+				unsigned long end);
 extern int acpi_scan_nodes(unsigned long start, unsigned long end);
 #define NR_NODE_MEMBLKS (MAX_NUMNODES*2)
+
+#ifdef CONFIG_NUMA_EMU
 extern void acpi_fake_nodes(const struct bootnode *fake_nodes,
 				   int num_nodes);
-#else
-static inline void acpi_fake_nodes(const struct bootnode *fake_nodes,
-				   int num_nodes)
-{
-}
 #endif
+#endif /* CONFIG_ACPI_NUMA */
 
 #define acpi_unlazy_tlb(x)	leave_mm(x)
 
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/include/asm/alternative.h linux-libre-2.6.38-gnu1/arch/x86/include/asm/alternative.h
--- linux-libre-2.6.37-gnu1/arch/x86/include/asm/alternative.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/include/asm/alternative.h	2011-03-14 21:20:32.000000000 -0400
@@ -66,6 +66,7 @@ extern void alternatives_smp_module_add(
 extern void alternatives_smp_module_del(struct module *mod);
 extern void alternatives_smp_switch(int smp);
 extern int alternatives_text_reserved(void *start, void *end);
+extern bool skip_smp_alternatives;
 #else
 static inline void alternatives_smp_module_add(struct module *mod, char *name,
 					       void *locks, void *locks_end,
@@ -180,8 +181,15 @@ extern void *text_poke_early(void *addr,
  * On the local CPU you need to be protected again NMI or MCE handlers seeing an
  * inconsistent instruction while you patch.
  */
+struct text_poke_param {
+	void *addr;
+	const void *opcode;
+	size_t len;
+};
+
 extern void *text_poke(void *addr, const void *opcode, size_t len);
 extern void *text_poke_smp(void *addr, const void *opcode, size_t len);
+extern void text_poke_smp_batch(struct text_poke_param *params, int n);
 
 #if defined(CONFIG_DYNAMIC_FTRACE) || defined(HAVE_JUMP_LABEL)
 #define IDEAL_NOP_SIZE_5 5
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/include/asm/amd_nb.h linux-libre-2.6.38-gnu1/arch/x86/include/asm/amd_nb.h
--- linux-libre-2.6.37-gnu1/arch/x86/include/asm/amd_nb.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/include/asm/amd_nb.h	2011-03-14 21:20:32.000000000 -0400
@@ -3,36 +3,64 @@
 
 #include <linux/pci.h>
 
-extern struct pci_device_id k8_nb_ids[];
+struct amd_nb_bus_dev_range {
+	u8 bus;
+	u8 dev_base;
+	u8 dev_limit;
+};
+
+extern struct pci_device_id amd_nb_misc_ids[];
+extern const struct amd_nb_bus_dev_range amd_nb_bus_dev_ranges[];
 struct bootnode;
 
-extern int early_is_k8_nb(u32 value);
-extern int cache_k8_northbridges(void);
-extern void k8_flush_garts(void);
-extern int k8_get_nodes(struct bootnode *nodes);
-extern int k8_numa_init(unsigned long start_pfn, unsigned long end_pfn);
-extern int k8_scan_nodes(void);
+extern int early_is_amd_nb(u32 value);
+extern int amd_cache_northbridges(void);
+extern void amd_flush_garts(void);
+extern int amd_numa_init(unsigned long start_pfn, unsigned long end_pfn);
+extern int amd_scan_nodes(void);
 
-struct k8_northbridge_info {
+#ifdef CONFIG_NUMA_EMU
+extern void amd_fake_nodes(const struct bootnode *nodes, int nr_nodes);
+extern void amd_get_nodes(struct bootnode *nodes);
+#endif
+
+struct amd_northbridge {
+	struct pci_dev *misc;
+};
+
+struct amd_northbridge_info {
 	u16 num;
-	u8 gart_supported;
-	struct pci_dev **nb_misc;
+	u64 flags;
+	struct amd_northbridge *nb;
 };
-extern struct k8_northbridge_info k8_northbridges;
+extern struct amd_northbridge_info amd_northbridges;
+
+#define AMD_NB_GART			0x1
+#define AMD_NB_L3_INDEX_DISABLE		0x2
 
 #ifdef CONFIG_AMD_NB
 
-static inline struct pci_dev *node_to_k8_nb_misc(int node)
+static inline int amd_nb_num(void)
 {
-	return (node < k8_northbridges.num) ? k8_northbridges.nb_misc[node] : NULL;
+	return amd_northbridges.num;
 }
 
-#else
+static inline int amd_nb_has_feature(int feature)
+{
+	return ((amd_northbridges.flags & feature) == feature);
+}
 
-static inline struct pci_dev *node_to_k8_nb_misc(int node)
+static inline struct amd_northbridge *node_to_amd_nb(int node)
 {
-	return NULL;
+	return (node < amd_northbridges.num) ? &amd_northbridges.nb[node] : NULL;
 }
+
+#else
+
+#define amd_nb_num(x)		0
+#define amd_nb_has_feature(x)	false
+#define node_to_amd_nb(x)	NULL
+
 #endif
 
 
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/include/asm/apicdef.h linux-libre-2.6.38-gnu1/arch/x86/include/asm/apicdef.h
--- linux-libre-2.6.37-gnu1/arch/x86/include/asm/apicdef.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/include/asm/apicdef.h	2011-03-14 21:20:32.000000000 -0400
@@ -145,6 +145,7 @@
 
 #ifdef CONFIG_X86_32
 # define MAX_IO_APICS 64
+# define MAX_LOCAL_APIC 256
 #else
 # define MAX_IO_APICS 128
 # define MAX_LOCAL_APIC 32768
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/include/asm/apic.h linux-libre-2.6.38-gnu1/arch/x86/include/asm/apic.h
--- linux-libre-2.6.37-gnu1/arch/x86/include/asm/apic.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/include/asm/apic.h	2011-03-14 21:20:32.000000000 -0400
@@ -233,17 +233,19 @@ extern void sync_Arb_IDs(void);
 extern void init_bsp_APIC(void);
 extern void setup_local_APIC(void);
 extern void end_local_APIC_setup(void);
+extern void bsp_end_local_APIC_setup(void);
 extern void init_apic_mappings(void);
+void register_lapic_address(unsigned long address);
 extern void setup_boot_APIC_clock(void);
 extern void setup_secondary_APIC_clock(void);
 extern int APIC_init_uniprocessor(void);
 extern void enable_NMI_through_LVT0(void);
+extern int apic_force_enable(void);
 
 /*
  * On 32bit this is mach-xxx local
  */
 #ifdef CONFIG_X86_64
-extern void early_init_lapic_mapping(void);
 extern int apic_is_clustered_box(void);
 #else
 static inline int apic_is_clustered_box(void)
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/include/asm/boot.h linux-libre-2.6.38-gnu1/arch/x86/include/asm/boot.h
--- linux-libre-2.6.37-gnu1/arch/x86/include/asm/boot.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/include/asm/boot.h	2011-03-14 21:20:32.000000000 -0400
@@ -32,11 +32,7 @@
 #define BOOT_HEAP_SIZE             0x400000
 #else /* !CONFIG_KERNEL_BZIP2 */
 
-#ifdef CONFIG_X86_64
-#define BOOT_HEAP_SIZE	0x7000
-#else
-#define BOOT_HEAP_SIZE	0x4000
-#endif
+#define BOOT_HEAP_SIZE	0x8000
 
 #endif /* !CONFIG_KERNEL_BZIP2 */
 
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/include/asm/bootparam.h linux-libre-2.6.38-gnu1/arch/x86/include/asm/bootparam.h
--- linux-libre-2.6.37-gnu1/arch/x86/include/asm/bootparam.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/include/asm/bootparam.h	2011-03-14 21:20:32.000000000 -0400
@@ -124,6 +124,7 @@ enum {
 	X86_SUBARCH_LGUEST,
 	X86_SUBARCH_XEN,
 	X86_SUBARCH_MRST,
+	X86_SUBARCH_CE4100,
 	X86_NR_SUBARCHS,
 };
 
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/include/asm/cacheflush.h linux-libre-2.6.38-gnu1/arch/x86/include/asm/cacheflush.h
--- linux-libre-2.6.37-gnu1/arch/x86/include/asm/cacheflush.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/include/asm/cacheflush.h	2011-03-14 21:20:32.000000000 -0400
@@ -1,48 +1,8 @@
 #ifndef _ASM_X86_CACHEFLUSH_H
 #define _ASM_X86_CACHEFLUSH_H
 
-/* Keep includes the same across arches.  */
-#include <linux/mm.h>
-
 /* Caches aren't brain-dead on the intel. */
-static inline void flush_cache_all(void) { }
-static inline void flush_cache_mm(struct mm_struct *mm) { }
-static inline void flush_cache_dup_mm(struct mm_struct *mm) { }
-static inline void flush_cache_range(struct vm_area_struct *vma,
-				     unsigned long start, unsigned long end) { }
-static inline void flush_cache_page(struct vm_area_struct *vma,
-				    unsigned long vmaddr, unsigned long pfn) { }
-#define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 0
-static inline void flush_dcache_page(struct page *page) { }
-static inline void flush_dcache_mmap_lock(struct address_space *mapping) { }
-static inline void flush_dcache_mmap_unlock(struct address_space *mapping) { }
-static inline void flush_icache_range(unsigned long start,
-				      unsigned long end) { }
-static inline void flush_icache_page(struct vm_area_struct *vma,
-				     struct page *page) { }
-static inline void flush_icache_user_range(struct vm_area_struct *vma,
-					   struct page *page,
-					   unsigned long addr,
-					   unsigned long len) { }
-static inline void flush_cache_vmap(unsigned long start, unsigned long end) { }
-static inline void flush_cache_vunmap(unsigned long start,
-				      unsigned long end) { }
-
-static inline void copy_to_user_page(struct vm_area_struct *vma,
-				     struct page *page, unsigned long vaddr,
-				     void *dst, const void *src,
-				     unsigned long len)
-{
-	memcpy(dst, src, len);
-}
-
-static inline void copy_from_user_page(struct vm_area_struct *vma,
-				       struct page *page, unsigned long vaddr,
-				       void *dst, const void *src,
-				       unsigned long len)
-{
-	memcpy(dst, src, len);
-}
+#include <asm-generic/cacheflush.h>
 
 #ifdef CONFIG_X86_PAT
 /*
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/include/asm/ce4100.h linux-libre-2.6.38-gnu1/arch/x86/include/asm/ce4100.h
--- linux-libre-2.6.37-gnu1/arch/x86/include/asm/ce4100.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/include/asm/ce4100.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,6 @@
+#ifndef _ASM_CE4100_H_
+#define _ASM_CE4100_H_
+
+int ce4100_pci_init(void);
+
+#endif
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/include/asm/cpu.h linux-libre-2.6.38-gnu1/arch/x86/include/asm/cpu.h
--- linux-libre-2.6.37-gnu1/arch/x86/include/asm/cpu.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/include/asm/cpu.h	2011-03-14 21:20:32.000000000 -0400
@@ -32,5 +32,6 @@ extern void arch_unregister_cpu(int);
 
 DECLARE_PER_CPU(int, cpu_state);
 
+int mwait_usable(const struct cpuinfo_x86 *);
 
 #endif /* _ASM_X86_CPU_H */
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/include/asm/debugreg.h linux-libre-2.6.38-gnu1/arch/x86/include/asm/debugreg.h
--- linux-libre-2.6.37-gnu1/arch/x86/include/asm/debugreg.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/include/asm/debugreg.h	2011-03-14 21:20:32.000000000 -0400
@@ -94,7 +94,7 @@ static inline void hw_breakpoint_disable
 
 static inline int hw_breakpoint_active(void)
 {
-	return __get_cpu_var(cpu_dr7) & DR_GLOBAL_ENABLE_MASK;
+	return __this_cpu_read(cpu_dr7) & DR_GLOBAL_ENABLE_MASK;
 }
 
 extern void aout_dump_debugregs(struct user *dump);
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/include/asm/fixmap.h linux-libre-2.6.38-gnu1/arch/x86/include/asm/fixmap.h
--- linux-libre-2.6.37-gnu1/arch/x86/include/asm/fixmap.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/include/asm/fixmap.h	2011-03-14 21:20:32.000000000 -0400
@@ -116,7 +116,11 @@ enum fixed_addresses {
 #endif
 	FIX_TEXT_POKE1,	/* reserve 2 pages for text_poke() */
 	FIX_TEXT_POKE0, /* first page is last, because allocation is backward */
+#ifdef	CONFIG_X86_MRST
+	FIX_LNW_VRTC,
+#endif
 	__end_of_permanent_fixed_addresses,
+
 	/*
 	 * 256 temporary boot-time mappings, used by early_ioremap(),
 	 * before ioremap() is functional.
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/include/asm/gpio.h linux-libre-2.6.38-gnu1/arch/x86/include/asm/gpio.h
--- linux-libre-2.6.37-gnu1/arch/x86/include/asm/gpio.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/include/asm/gpio.h	2011-03-14 21:20:32.000000000 -0400
@@ -38,12 +38,9 @@ static inline int gpio_cansleep(unsigned
 	return __gpio_cansleep(gpio);
 }
 
-/*
- * Not implemented, yet.
- */
 static inline int gpio_to_irq(unsigned int gpio)
 {
-	return -ENOSYS;
+	return __gpio_to_irq(gpio);
 }
 
 static inline int irq_to_gpio(unsigned int irq)
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/include/asm/hypervisor.h linux-libre-2.6.38-gnu1/arch/x86/include/asm/hypervisor.h
--- linux-libre-2.6.37-gnu1/arch/x86/include/asm/hypervisor.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/include/asm/hypervisor.h	2011-03-14 21:20:32.000000000 -0400
@@ -20,6 +20,9 @@
 #ifndef _ASM_X86_HYPERVISOR_H
 #define _ASM_X86_HYPERVISOR_H
 
+#include <asm/kvm_para.h>
+#include <asm/xen/hypervisor.h>
+
 extern void init_hypervisor(struct cpuinfo_x86 *c);
 extern void init_hypervisor_platform(void);
 
@@ -47,4 +50,13 @@ extern const struct hypervisor_x86 x86_h
 extern const struct hypervisor_x86 x86_hyper_ms_hyperv;
 extern const struct hypervisor_x86 x86_hyper_xen_hvm;
 
+static inline bool hypervisor_x2apic_available(void)
+{
+	if (kvm_para_available())
+		return true;
+	if (xen_x2apic_para_available())
+		return true;
+	return false;
+}
+
 #endif
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/include/asm/i387.h linux-libre-2.6.38-gnu1/arch/x86/include/asm/i387.h
--- linux-libre-2.6.37-gnu1/arch/x86/include/asm/i387.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/include/asm/i387.h	2011-03-14 21:20:32.000000000 -0400
@@ -93,6 +93,17 @@ static inline int fxrstor_checking(struc
 	int err;
 
 	/* See comment in fxsave() below. */
+#ifdef CONFIG_AS_FXSAVEQ
+	asm volatile("1:  fxrstorq %[fx]\n\t"
+		     "2:\n"
+		     ".section .fixup,\"ax\"\n"
+		     "3:  movl $-1,%[err]\n"
+		     "    jmp  2b\n"
+		     ".previous\n"
+		     _ASM_EXTABLE(1b, 3b)
+		     : [err] "=r" (err)
+		     : [fx] "m" (*fx), "0" (0));
+#else
 	asm volatile("1:  rex64/fxrstor (%[fx])\n\t"
 		     "2:\n"
 		     ".section .fixup,\"ax\"\n"
@@ -102,6 +113,7 @@ static inline int fxrstor_checking(struc
 		     _ASM_EXTABLE(1b, 3b)
 		     : [err] "=r" (err)
 		     : [fx] "R" (fx), "m" (*fx), "0" (0));
+#endif
 	return err;
 }
 
@@ -119,6 +131,17 @@ static inline int fxsave_user(struct i38
 		return -EFAULT;
 
 	/* See comment in fxsave() below. */
+#ifdef CONFIG_AS_FXSAVEQ
+	asm volatile("1:  fxsaveq %[fx]\n\t"
+		     "2:\n"
+		     ".section .fixup,\"ax\"\n"
+		     "3:  movl $-1,%[err]\n"
+		     "    jmp  2b\n"
+		     ".previous\n"
+		     _ASM_EXTABLE(1b, 3b)
+		     : [err] "=r" (err), [fx] "=m" (*fx)
+		     : "0" (0));
+#else
 	asm volatile("1:  rex64/fxsave (%[fx])\n\t"
 		     "2:\n"
 		     ".section .fixup,\"ax\"\n"
@@ -128,6 +151,7 @@ static inline int fxsave_user(struct i38
 		     _ASM_EXTABLE(1b, 3b)
 		     : [err] "=r" (err), "=m" (*fx)
 		     : [fx] "R" (fx), "0" (0));
+#endif
 	if (unlikely(err) &&
 	    __clear_user(fx, sizeof(struct i387_fxsave_struct)))
 		err = -EFAULT;
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/include/asm/io_apic.h linux-libre-2.6.38-gnu1/arch/x86/include/asm/io_apic.h
--- linux-libre-2.6.37-gnu1/arch/x86/include/asm/io_apic.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/include/asm/io_apic.h	2011-03-14 21:20:32.000000000 -0400
@@ -159,7 +159,7 @@ struct io_apic_irq_attr;
 extern int io_apic_set_pci_routing(struct device *dev, int irq,
 		 struct io_apic_irq_attr *irq_attr);
 void setup_IO_APIC_irq_extra(u32 gsi);
-extern void ioapic_init_mappings(void);
+extern void ioapic_and_gsi_init(void);
 extern void ioapic_insert_resources(void);
 
 extern struct IO_APIC_route_entry **alloc_ioapic_entries(void);
@@ -168,10 +168,10 @@ extern int save_IO_APIC_setup(struct IO_
 extern void mask_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries);
 extern int restore_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries);
 
-extern void probe_nr_irqs_gsi(void);
 extern int get_nr_irqs_gsi(void);
 
 extern void setup_ioapic_ids_from_mpc(void);
+extern void setup_ioapic_ids_from_mpc_nocheck(void);
 
 struct mp_ioapic_gsi{
 	u32 gsi_base;
@@ -184,14 +184,15 @@ int mp_find_ioapic_pin(int ioapic, u32 g
 void __init mp_register_ioapic(int id, u32 address, u32 gsi_base);
 extern void __init pre_init_apic_IRQ0(void);
 
+extern void mp_save_irq(struct mpc_intsrc *m);
+
 #else  /* !CONFIG_X86_IO_APIC */
 
 #define io_apic_assign_pci_irqs 0
 #define setup_ioapic_ids_from_mpc x86_init_noop
 static const int timer_through_8259 = 0;
-static inline void ioapic_init_mappings(void)	{ }
+static inline void ioapic_and_gsi_init(void) { }
 static inline void ioapic_insert_resources(void) { }
-static inline void probe_nr_irqs_gsi(void)	{ }
 #define gsi_top (NR_IRQS_LEGACY)
 static inline int mp_find_ioapic(u32 gsi) { return 0; }
 
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/include/asm/irq.h linux-libre-2.6.38-gnu1/arch/x86/include/asm/irq.h
--- linux-libre-2.6.37-gnu1/arch/x86/include/asm/irq.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/include/asm/irq.h	2011-03-14 21:20:32.000000000 -0400
@@ -10,15 +10,14 @@
 #include <asm/apicdef.h>
 #include <asm/irq_vectors.h>
 
+/* Even though we don't support this, supply it to appease OF */
+static inline void irq_dispose_mapping(unsigned int virq) { }
+
 static inline int irq_canonicalize(int irq)
 {
 	return ((irq == 2) ? 9 : irq);
 }
 
-#ifdef CONFIG_X86_LOCAL_APIC
-# define ARCH_HAS_NMI_WATCHDOG
-#endif
-
 #ifdef CONFIG_X86_32
 extern void irq_ctx_init(int cpu);
 #else
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/include/asm/jump_label.h linux-libre-2.6.38-gnu1/arch/x86/include/asm/jump_label.h
--- linux-libre-2.6.37-gnu1/arch/x86/include/asm/jump_label.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/include/asm/jump_label.h	2011-03-14 21:20:32.000000000 -0400
@@ -14,7 +14,7 @@
 	do {							\
 		asm goto("1:"					\
 			JUMP_LABEL_INITIAL_NOP			\
-			".pushsection __jump_table,  \"a\" \n\t"\
+			".pushsection __jump_table,  \"aw\" \n\t"\
 			_ASM_PTR "1b, %l[" #label "], %c0 \n\t" \
 			".popsection \n\t"			\
 			: :  "i" (key) :  : label);		\
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/include/asm/kdebug.h linux-libre-2.6.38-gnu1/arch/x86/include/asm/kdebug.h
--- linux-libre-2.6.37-gnu1/arch/x86/include/asm/kdebug.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/include/asm/kdebug.h	2011-03-14 21:20:32.000000000 -0400
@@ -18,7 +18,6 @@ enum die_val {
 	DIE_TRAP,
 	DIE_GPF,
 	DIE_CALL,
-	DIE_NMI_IPI,
 	DIE_PAGE_FAULT,
 	DIE_NMIUNKNOWN,
 };
@@ -28,7 +27,7 @@ extern void die(const char *, struct pt_
 extern int __must_check __die(const char *, struct pt_regs *, long);
 extern void show_registers(struct pt_regs *regs);
 extern void show_trace(struct task_struct *t, struct pt_regs *regs,
-		       unsigned long *sp, unsigned long bp);
+		       unsigned long *sp);
 extern void __show_regs(struct pt_regs *regs, int all);
 extern void show_regs(struct pt_regs *regs);
 extern unsigned long oops_begin(void);
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/include/asm/kvm_emulate.h linux-libre-2.6.38-gnu1/arch/x86/include/asm/kvm_emulate.h
--- linux-libre-2.6.37-gnu1/arch/x86/include/asm/kvm_emulate.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/include/asm/kvm_emulate.h	2011-03-14 21:20:32.000000000 -0400
@@ -15,6 +15,14 @@
 
 struct x86_emulate_ctxt;
 
+struct x86_exception {
+	u8 vector;
+	bool error_code_valid;
+	u16 error_code;
+	bool nested_page_fault;
+	u64 address; /* cr2 or nested page fault gpa */
+};
+
 /*
  * x86_emulate_ops:
  *
@@ -64,7 +72,8 @@ struct x86_emulate_ops {
 	 *  @bytes: [IN ] Number of bytes to read from memory.
 	 */
 	int (*read_std)(unsigned long addr, void *val,
-			unsigned int bytes, struct kvm_vcpu *vcpu, u32 *error);
+			unsigned int bytes, struct kvm_vcpu *vcpu,
+			struct x86_exception *fault);
 
 	/*
 	 * write_std: Write bytes of standard (non-emulated/special) memory.
@@ -74,7 +83,8 @@ struct x86_emulate_ops {
 	 *  @bytes: [IN ] Number of bytes to write to memory.
 	 */
 	int (*write_std)(unsigned long addr, void *val,
-			 unsigned int bytes, struct kvm_vcpu *vcpu, u32 *error);
+			 unsigned int bytes, struct kvm_vcpu *vcpu,
+			 struct x86_exception *fault);
 	/*
 	 * fetch: Read bytes of standard (non-emulated/special) memory.
 	 *        Used for instruction fetch.
@@ -83,7 +93,8 @@ struct x86_emulate_ops {
 	 *  @bytes: [IN ] Number of bytes to read from memory.
 	 */
 	int (*fetch)(unsigned long addr, void *val,
-			unsigned int bytes, struct kvm_vcpu *vcpu, u32 *error);
+		     unsigned int bytes, struct kvm_vcpu *vcpu,
+		     struct x86_exception *fault);
 
 	/*
 	 * read_emulated: Read bytes from emulated/special memory area.
@@ -94,7 +105,7 @@ struct x86_emulate_ops {
 	int (*read_emulated)(unsigned long addr,
 			     void *val,
 			     unsigned int bytes,
-			     unsigned int *error,
+			     struct x86_exception *fault,
 			     struct kvm_vcpu *vcpu);
 
 	/*
@@ -107,7 +118,7 @@ struct x86_emulate_ops {
 	int (*write_emulated)(unsigned long addr,
 			      const void *val,
 			      unsigned int bytes,
-			      unsigned int *error,
+			      struct x86_exception *fault,
 			      struct kvm_vcpu *vcpu);
 
 	/*
@@ -122,7 +133,7 @@ struct x86_emulate_ops {
 				const void *old,
 				const void *new,
 				unsigned int bytes,
-				unsigned int *error,
+				struct x86_exception *fault,
 				struct kvm_vcpu *vcpu);
 
 	int (*pio_in_emulated)(int size, unsigned short port, void *val,
@@ -159,7 +170,10 @@ struct operand {
 	};
 	union {
 		unsigned long *reg;
-		unsigned long mem;
+		struct segmented_address {
+			ulong ea;
+			unsigned seg;
+		} mem;
 	} addr;
 	union {
 		unsigned long val;
@@ -226,9 +240,8 @@ struct x86_emulate_ctxt {
 
 	bool perm_ok; /* do not check permissions if true */
 
-	int exception; /* exception that happens during emulation or -1 */
-	u32 error_code; /* error code for exception */
-	bool error_code_valid;
+	bool have_exception;
+	struct x86_exception exception;
 
 	/* decode cache */
 	struct decode_cache decode;
@@ -252,7 +265,7 @@ struct x86_emulate_ctxt {
 #define X86EMUL_MODE_HOST X86EMUL_MODE_PROT64
 #endif
 
-int x86_decode_insn(struct x86_emulate_ctxt *ctxt);
+int x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len);
 #define EMULATION_FAILED -1
 #define EMULATION_OK 0
 #define EMULATION_RESTART 1
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/include/asm/kvm_host.h linux-libre-2.6.38-gnu1/arch/x86/include/asm/kvm_host.h
--- linux-libre-2.6.37-gnu1/arch/x86/include/asm/kvm_host.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/include/asm/kvm_host.h	2011-03-14 21:20:32.000000000 -0400
@@ -83,11 +83,14 @@
 #define KVM_NR_FIXED_MTRR_REGION 88
 #define KVM_NR_VAR_MTRR 8
 
+#define ASYNC_PF_PER_VCPU 64
+
 extern spinlock_t kvm_lock;
 extern struct list_head vm_list;
 
 struct kvm_vcpu;
 struct kvm;
+struct kvm_async_pf;
 
 enum kvm_reg {
 	VCPU_REGS_RAX = 0,
@@ -114,6 +117,7 @@ enum kvm_reg {
 
 enum kvm_reg_ex {
 	VCPU_EXREG_PDPTR = NR_VCPU_REGS,
+	VCPU_EXREG_CR3,
 };
 
 enum {
@@ -238,16 +242,18 @@ 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);
-	int (*page_fault)(struct kvm_vcpu *vcpu, gva_t gva, u32 err);
-	void (*inject_page_fault)(struct kvm_vcpu *vcpu);
+	int (*page_fault)(struct kvm_vcpu *vcpu, gva_t gva, u32 err,
+			  bool prefault);
+	void (*inject_page_fault)(struct kvm_vcpu *vcpu,
+				  struct x86_exception *fault);
 	void (*free)(struct kvm_vcpu *vcpu);
 	gpa_t (*gva_to_gpa)(struct kvm_vcpu *vcpu, gva_t gva, u32 access,
-			    u32 *error);
+			    struct x86_exception *exception);
 	gpa_t (*translate_gpa)(struct kvm_vcpu *vcpu, gpa_t gpa, u32 access);
 	void (*prefetch_page)(struct kvm_vcpu *vcpu,
 			      struct kvm_mmu_page *page);
 	int (*sync_page)(struct kvm_vcpu *vcpu,
-			 struct kvm_mmu_page *sp, bool clear_unsync);
+			 struct kvm_mmu_page *sp);
 	void (*invlpg)(struct kvm_vcpu *vcpu, gva_t gva);
 	hpa_t root_hpa;
 	int root_level;
@@ -315,16 +321,6 @@ struct kvm_vcpu_arch {
 	 */
 	struct kvm_mmu *walk_mmu;
 
-	/*
-	 * This struct is filled with the necessary information to propagate a
-	 * page fault into the guest
-	 */
-	struct {
-		u64      address;
-		unsigned error_code;
-		bool     nested;
-	} fault;
-
 	/* only needed in kvm_pv_mmu_op() path, but it's hot so
 	 * put it here to avoid allocation */
 	struct kvm_pv_mmu_op_buffer mmu_op_buffer;
@@ -412,6 +408,15 @@ struct kvm_vcpu_arch {
 	u64 hv_vapic;
 
 	cpumask_var_t wbinvd_dirty_mask;
+
+	struct {
+		bool halted;
+		gfn_t gfns[roundup_pow_of_two(ASYNC_PF_PER_VCPU)];
+		struct gfn_to_hva_cache data;
+		u64 msr_val;
+		u32 id;
+		bool send_user_only;
+	} apf;
 };
 
 struct kvm_arch {
@@ -456,6 +461,10 @@ struct kvm_arch {
 	/* fields used by HYPER-V emulation */
 	u64 hv_guest_os_id;
 	u64 hv_hypercall;
+
+	#ifdef CONFIG_KVM_MMU_AUDIT
+	int audit_point;
+	#endif
 };
 
 struct kvm_vm_stat {
@@ -529,6 +538,7 @@ struct kvm_x86_ops {
 			    struct kvm_segment *var, int seg);
 	void (*get_cs_db_l_bits)(struct kvm_vcpu *vcpu, int *db, int *l);
 	void (*decache_cr0_guest_bits)(struct kvm_vcpu *vcpu);
+	void (*decache_cr3)(struct kvm_vcpu *vcpu);
 	void (*decache_cr4_guest_bits)(struct kvm_vcpu *vcpu);
 	void (*set_cr0)(struct kvm_vcpu *vcpu, unsigned long cr0);
 	void (*set_cr3)(struct kvm_vcpu *vcpu, unsigned long cr3);
@@ -582,9 +592,17 @@ struct kvm_x86_ops {
 
 	void (*write_tsc_offset)(struct kvm_vcpu *vcpu, u64 offset);
 
+	void (*get_exit_info)(struct kvm_vcpu *vcpu, u64 *info1, u64 *info2);
 	const struct trace_print_flags *exit_reasons_str;
 };
 
+struct kvm_arch_async_pf {
+	u32 token;
+	gfn_t gfn;
+	unsigned long cr3;
+	bool direct_map;
+};
+
 extern struct kvm_x86_ops *kvm_x86_ops;
 
 int kvm_mmu_module_init(void);
@@ -594,7 +612,6 @@ void kvm_mmu_destroy(struct kvm_vcpu *vc
 int kvm_mmu_create(struct kvm_vcpu *vcpu);
 int kvm_mmu_setup(struct kvm_vcpu *vcpu);
 void kvm_mmu_set_nonpresent_ptes(u64 trap_pte, u64 notrap_pte);
-void kvm_mmu_set_base_ptes(u64 base_pte);
 void kvm_mmu_set_mask_ptes(u64 user_mask, u64 accessed_mask,
 		u64 dirty_mask, u64 nx_mask, u64 x_mask);
 
@@ -623,8 +640,15 @@ enum emulation_result {
 #define EMULTYPE_NO_DECODE	    (1 << 0)
 #define EMULTYPE_TRAP_UD	    (1 << 1)
 #define EMULTYPE_SKIP		    (1 << 2)
-int emulate_instruction(struct kvm_vcpu *vcpu,
-			unsigned long cr2, u16 error_code, int emulation_type);
+int x86_emulate_instruction(struct kvm_vcpu *vcpu, unsigned long cr2,
+			    int emulation_type, void *insn, int insn_len);
+
+static inline int emulate_instruction(struct kvm_vcpu *vcpu,
+			int emulation_type)
+{
+	return x86_emulate_instruction(vcpu, 0, emulation_type, NULL, 0);
+}
+
 void realmode_lgdt(struct kvm_vcpu *vcpu, u16 size, unsigned long address);
 void realmode_lidt(struct kvm_vcpu *vcpu, u16 size, unsigned long address);
 
@@ -650,7 +674,7 @@ int kvm_task_switch(struct kvm_vcpu *vcp
 int kvm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0);
 int kvm_set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3);
 int kvm_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4);
-void kvm_set_cr8(struct kvm_vcpu *vcpu, unsigned long cr8);
+int kvm_set_cr8(struct kvm_vcpu *vcpu, unsigned long cr8);
 int kvm_set_dr(struct kvm_vcpu *vcpu, int dr, unsigned long val);
 int kvm_get_dr(struct kvm_vcpu *vcpu, int dr, unsigned long *val);
 unsigned long kvm_get_cr8(struct kvm_vcpu *vcpu);
@@ -668,11 +692,11 @@ void kvm_queue_exception(struct kvm_vcpu
 void kvm_queue_exception_e(struct kvm_vcpu *vcpu, unsigned nr, u32 error_code);
 void kvm_requeue_exception(struct kvm_vcpu *vcpu, unsigned nr);
 void kvm_requeue_exception_e(struct kvm_vcpu *vcpu, unsigned nr, u32 error_code);
-void kvm_inject_page_fault(struct kvm_vcpu *vcpu);
+void kvm_inject_page_fault(struct kvm_vcpu *vcpu, struct x86_exception *fault);
 int kvm_read_guest_page_mmu(struct kvm_vcpu *vcpu, struct kvm_mmu *mmu,
 			    gfn_t gfn, void *data, int offset, int len,
 			    u32 access);
-void kvm_propagate_fault(struct kvm_vcpu *vcpu);
+void kvm_propagate_fault(struct kvm_vcpu *vcpu, struct x86_exception *fault);
 bool kvm_require_cpl(struct kvm_vcpu *vcpu, int required_cpl);
 
 int kvm_pic_set_irq(void *opaque, int irq, int level);
@@ -690,16 +714,21 @@ void __kvm_mmu_free_some_pages(struct kv
 int kvm_mmu_load(struct kvm_vcpu *vcpu);
 void kvm_mmu_unload(struct kvm_vcpu *vcpu);
 void kvm_mmu_sync_roots(struct kvm_vcpu *vcpu);
-gpa_t kvm_mmu_gva_to_gpa_read(struct kvm_vcpu *vcpu, gva_t gva, u32 *error);
-gpa_t kvm_mmu_gva_to_gpa_fetch(struct kvm_vcpu *vcpu, gva_t gva, u32 *error);
-gpa_t kvm_mmu_gva_to_gpa_write(struct kvm_vcpu *vcpu, gva_t gva, u32 *error);
-gpa_t kvm_mmu_gva_to_gpa_system(struct kvm_vcpu *vcpu, gva_t gva, u32 *error);
+gpa_t kvm_mmu_gva_to_gpa_read(struct kvm_vcpu *vcpu, gva_t gva,
+			      struct x86_exception *exception);
+gpa_t kvm_mmu_gva_to_gpa_fetch(struct kvm_vcpu *vcpu, gva_t gva,
+			       struct x86_exception *exception);
+gpa_t kvm_mmu_gva_to_gpa_write(struct kvm_vcpu *vcpu, gva_t gva,
+			       struct x86_exception *exception);
+gpa_t kvm_mmu_gva_to_gpa_system(struct kvm_vcpu *vcpu, gva_t gva,
+				struct x86_exception *exception);
 
 int kvm_emulate_hypercall(struct kvm_vcpu *vcpu);
 
 int kvm_fix_hypercall(struct kvm_vcpu *vcpu);
 
-int kvm_mmu_page_fault(struct kvm_vcpu *vcpu, gva_t gva, u32 error_code);
+int kvm_mmu_page_fault(struct kvm_vcpu *vcpu, gva_t gva, u32 error_code,
+		       void *insn, int insn_len);
 void kvm_mmu_invlpg(struct kvm_vcpu *vcpu, gva_t gva);
 
 void kvm_enable_tdp(void);
@@ -766,20 +795,25 @@ enum {
 #define HF_VINTR_MASK		(1 << 2)
 #define HF_NMI_MASK		(1 << 3)
 #define HF_IRET_MASK		(1 << 4)
+#define HF_GUEST_MASK		(1 << 5) /* VCPU is in guest-mode */
 
 /*
  * Hardware virtualization extension instructions may fault if a
  * reboot turns off virtualization while processes are running.
  * Trap the fault and ignore the instruction if that happens.
  */
-asmlinkage void kvm_handle_fault_on_reboot(void);
+asmlinkage void kvm_spurious_fault(void);
+extern bool kvm_rebooting;
 
 #define __kvm_handle_fault_on_reboot(insn) \
 	"666: " insn "\n\t" \
+	"668: \n\t"                           \
 	".pushsection .fixup, \"ax\" \n" \
 	"667: \n\t" \
+	"cmpb $0, kvm_rebooting \n\t"	      \
+	"jne 668b \n\t"      		      \
 	__ASM_SIZE(push) " $666b \n\t"	      \
-	"jmp kvm_handle_fault_on_reboot \n\t" \
+	"call kvm_spurious_fault \n\t"	      \
 	".popsection \n\t" \
 	".pushsection __ex_table, \"a\" \n\t" \
 	_ASM_PTR " 666b, 667b \n\t" \
@@ -788,6 +822,7 @@ asmlinkage void kvm_handle_fault_on_rebo
 #define KVM_ARCH_WANT_MMU_NOTIFIER
 int kvm_unmap_hva(struct kvm *kvm, unsigned long hva);
 int kvm_age_hva(struct kvm *kvm, unsigned long hva);
+int kvm_test_age_hva(struct kvm *kvm, unsigned long hva);
 void kvm_set_spte_hva(struct kvm *kvm, unsigned long hva, pte_t pte);
 int cpuid_maxphyaddr(struct kvm_vcpu *vcpu);
 int kvm_cpu_has_interrupt(struct kvm_vcpu *vcpu);
@@ -799,4 +834,15 @@ void kvm_set_shared_msr(unsigned index,
 
 bool kvm_is_linear_rip(struct kvm_vcpu *vcpu, unsigned long linear_rip);
 
+void kvm_arch_async_page_not_present(struct kvm_vcpu *vcpu,
+				     struct kvm_async_pf *work);
+void kvm_arch_async_page_present(struct kvm_vcpu *vcpu,
+				 struct kvm_async_pf *work);
+void kvm_arch_async_page_ready(struct kvm_vcpu *vcpu,
+			       struct kvm_async_pf *work);
+bool kvm_arch_can_inject_async_page_present(struct kvm_vcpu *vcpu);
+extern bool kvm_find_async_pf_gfn(struct kvm_vcpu *vcpu, gfn_t gfn);
+
+void kvm_complete_insn_gp(struct kvm_vcpu *vcpu, int err);
+
 #endif /* _ASM_X86_KVM_HOST_H */
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/include/asm/kvm_para.h linux-libre-2.6.38-gnu1/arch/x86/include/asm/kvm_para.h
--- linux-libre-2.6.37-gnu1/arch/x86/include/asm/kvm_para.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/include/asm/kvm_para.h	2011-03-14 21:20:32.000000000 -0400
@@ -20,6 +20,7 @@
  * are available. The use of 0x11 and 0x12 is deprecated
  */
 #define KVM_FEATURE_CLOCKSOURCE2        3
+#define KVM_FEATURE_ASYNC_PF		4
 
 /* The last 8 bits are used to indicate how to interpret the flags field
  * in pvclock structure. If no bits are set, all flags are ignored.
@@ -32,9 +33,13 @@
 /* Custom MSRs falls in the range 0x4b564d00-0x4b564dff */
 #define MSR_KVM_WALL_CLOCK_NEW  0x4b564d00
 #define MSR_KVM_SYSTEM_TIME_NEW 0x4b564d01
+#define MSR_KVM_ASYNC_PF_EN 0x4b564d02
 
 #define KVM_MAX_MMU_OP_BATCH           32
 
+#define KVM_ASYNC_PF_ENABLED			(1 << 0)
+#define KVM_ASYNC_PF_SEND_ALWAYS		(1 << 1)
+
 /* Operations for KVM_HC_MMU_OP */
 #define KVM_MMU_OP_WRITE_PTE            1
 #define KVM_MMU_OP_FLUSH_TLB	        2
@@ -61,10 +66,20 @@ struct kvm_mmu_op_release_pt {
 	__u64 pt_phys;
 };
 
+#define KVM_PV_REASON_PAGE_NOT_PRESENT 1
+#define KVM_PV_REASON_PAGE_READY 2
+
+struct kvm_vcpu_pv_apf_data {
+	__u32 reason;
+	__u8 pad[60];
+	__u32 enabled;
+};
+
 #ifdef __KERNEL__
 #include <asm/processor.h>
 
 extern void kvmclock_init(void);
+extern int kvm_register_clock(char *txt);
 
 
 /* This instruction is vmcall.  On non-VT architectures, it will generate a
@@ -160,8 +175,17 @@ static inline unsigned int kvm_arch_para
 
 #ifdef CONFIG_KVM_GUEST
 void __init kvm_guest_init(void);
+void kvm_async_pf_task_wait(u32 token);
+void kvm_async_pf_task_wake(u32 token);
+u32 kvm_read_and_reset_pf_reason(void);
 #else
 #define kvm_guest_init() do { } while (0)
+#define kvm_async_pf_task_wait(T) do {} while(0)
+#define kvm_async_pf_task_wake(T) do {} while(0)
+static inline u32 kvm_read_and_reset_pf_reason(void)
+{
+	return 0;
+}
 #endif
 
 #endif /* __KERNEL__ */
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/include/asm/mach_traps.h linux-libre-2.6.38-gnu1/arch/x86/include/asm/mach_traps.h
--- linux-libre-2.6.37-gnu1/arch/x86/include/asm/mach_traps.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/include/asm/mach_traps.h	2011-03-14 21:20:32.000000000 -0400
@@ -7,9 +7,19 @@
 
 #include <asm/mc146818rtc.h>
 
+#define NMI_REASON_PORT		0x61
+
+#define NMI_REASON_SERR		0x80
+#define NMI_REASON_IOCHK	0x40
+#define NMI_REASON_MASK		(NMI_REASON_SERR | NMI_REASON_IOCHK)
+
+#define NMI_REASON_CLEAR_SERR	0x04
+#define NMI_REASON_CLEAR_IOCHK	0x08
+#define NMI_REASON_CLEAR_MASK	0x0f
+
 static inline unsigned char get_nmi_reason(void)
 {
-	return inb(0x61);
+	return inb(NMI_REASON_PORT);
 }
 
 static inline void reassert_nmi(void)
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/include/asm/mce.h linux-libre-2.6.38-gnu1/arch/x86/include/asm/mce.h
--- linux-libre-2.6.37-gnu1/arch/x86/include/asm/mce.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/include/asm/mce.h	2011-03-14 21:20:32.000000000 -0400
@@ -223,6 +223,9 @@ void intel_init_thermal(struct cpuinfo_x
 
 void mce_log_therm_throt_event(__u64 status);
 
+/* Interrupt Handler for core thermal thresholds */
+extern int (*platform_thermal_notify)(__u64 msr_val);
+
 #ifdef CONFIG_X86_THERMAL_VECTOR
 extern void mcheck_intel_therm_init(void);
 #else
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/include/asm/microcode.h linux-libre-2.6.38-gnu1/arch/x86/include/asm/microcode.h
--- linux-libre-2.6.37-gnu1/arch/x86/include/asm/microcode.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/include/asm/microcode.h	2011-03-14 21:20:32.000000000 -0400
@@ -48,6 +48,12 @@ static inline struct microcode_ops * __i
 
 #ifdef CONFIG_MICROCODE_AMD
 extern struct microcode_ops * __init init_amd_microcode(void);
+
+static inline void get_ucode_data(void *to, const u8 *from, size_t n)
+{
+	memcpy(to, from, n);
+}
+
 #else
 static inline struct microcode_ops * __init init_amd_microcode(void)
 {
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/include/asm/mmu_context.h linux-libre-2.6.38-gnu1/arch/x86/include/asm/mmu_context.h
--- linux-libre-2.6.37-gnu1/arch/x86/include/asm/mmu_context.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/include/asm/mmu_context.h	2011-03-14 21:20:32.000000000 -0400
@@ -36,8 +36,6 @@ static inline void switch_mm(struct mm_s
 	unsigned cpu = smp_processor_id();
 
 	if (likely(prev != next)) {
-		/* stop flush ipis for the previous mm */
-		cpumask_clear_cpu(cpu, mm_cpumask(prev));
 #ifdef CONFIG_SMP
 		percpu_write(cpu_tlbstate.state, TLBSTATE_OK);
 		percpu_write(cpu_tlbstate.active_mm, next);
@@ -47,6 +45,9 @@ static inline void switch_mm(struct mm_s
 		/* Re-load page tables */
 		load_cr3(next->pgd);
 
+		/* stop flush ipis for the previous mm */
+		cpumask_clear_cpu(cpu, mm_cpumask(prev));
+
 		/*
 		 * load the LDT, if the LDT is different:
 		 */
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/include/asm/mpspec_def.h linux-libre-2.6.38-gnu1/arch/x86/include/asm/mpspec_def.h
--- linux-libre-2.6.37-gnu1/arch/x86/include/asm/mpspec_def.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/include/asm/mpspec_def.h	2011-03-14 21:20:32.000000000 -0400
@@ -15,13 +15,6 @@
 
 #ifdef CONFIG_X86_32
 # define MAX_MPC_ENTRY 1024
-# define MAX_APICS      256
-#else
-# if NR_CPUS <= 255
-#  define MAX_APICS     255
-# else
-#  define MAX_APICS   32768
-# endif
 #endif
 
 /* Intel MP Floating Pointer Structure */
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/include/asm/mpspec.h linux-libre-2.6.38-gnu1/arch/x86/include/asm/mpspec.h
--- linux-libre-2.6.37-gnu1/arch/x86/include/asm/mpspec.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/include/asm/mpspec.h	2011-03-14 21:20:32.000000000 -0400
@@ -5,8 +5,9 @@
 
 #include <asm/mpspec_def.h>
 #include <asm/x86_init.h>
+#include <asm/apicdef.h>
 
-extern int apic_version[MAX_APICS];
+extern int apic_version[];
 extern int pic_mode;
 
 #ifdef CONFIG_X86_32
@@ -107,7 +108,7 @@ extern int mp_register_gsi(struct device
 				 int active_high_low);
 #endif /* CONFIG_ACPI */
 
-#define PHYSID_ARRAY_SIZE	BITS_TO_LONGS(MAX_APICS)
+#define PHYSID_ARRAY_SIZE	BITS_TO_LONGS(MAX_LOCAL_APIC)
 
 struct physid_mask {
 	unsigned long mask[PHYSID_ARRAY_SIZE];
@@ -122,31 +123,31 @@ typedef struct physid_mask physid_mask_t
 	test_and_set_bit(physid, (map).mask)
 
 #define physids_and(dst, src1, src2)					\
-	bitmap_and((dst).mask, (src1).mask, (src2).mask, MAX_APICS)
+	bitmap_and((dst).mask, (src1).mask, (src2).mask, MAX_LOCAL_APIC)
 
 #define physids_or(dst, src1, src2)					\
-	bitmap_or((dst).mask, (src1).mask, (src2).mask, MAX_APICS)
+	bitmap_or((dst).mask, (src1).mask, (src2).mask, MAX_LOCAL_APIC)
 
 #define physids_clear(map)					\
-	bitmap_zero((map).mask, MAX_APICS)
+	bitmap_zero((map).mask, MAX_LOCAL_APIC)
 
 #define physids_complement(dst, src)				\
-	bitmap_complement((dst).mask, (src).mask, MAX_APICS)
+	bitmap_complement((dst).mask, (src).mask, MAX_LOCAL_APIC)
 
 #define physids_empty(map)					\
-	bitmap_empty((map).mask, MAX_APICS)
+	bitmap_empty((map).mask, MAX_LOCAL_APIC)
 
 #define physids_equal(map1, map2)				\
-	bitmap_equal((map1).mask, (map2).mask, MAX_APICS)
+	bitmap_equal((map1).mask, (map2).mask, MAX_LOCAL_APIC)
 
 #define physids_weight(map)					\
-	bitmap_weight((map).mask, MAX_APICS)
+	bitmap_weight((map).mask, MAX_LOCAL_APIC)
 
 #define physids_shift_right(d, s, n)				\
-	bitmap_shift_right((d).mask, (s).mask, n, MAX_APICS)
+	bitmap_shift_right((d).mask, (s).mask, n, MAX_LOCAL_APIC)
 
 #define physids_shift_left(d, s, n)				\
-	bitmap_shift_left((d).mask, (s).mask, n, MAX_APICS)
+	bitmap_shift_left((d).mask, (s).mask, n, MAX_LOCAL_APIC)
 
 static inline unsigned long physids_coerce(physid_mask_t *map)
 {
@@ -159,14 +160,6 @@ static inline void physids_promote(unsig
 	map->mask[0] = physids;
 }
 
-/* Note: will create very large stack frames if physid_mask_t is big */
-#define physid_mask_of_physid(physid)					\
-	({								\
-		physid_mask_t __physid_mask = PHYSID_MASK_NONE;		\
-		physid_set(physid, __physid_mask);			\
-		__physid_mask;						\
-	})
-
 static inline void physid_set_mask_of_physid(int physid, physid_mask_t *map)
 {
 	physids_clear(*map);
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/include/asm/mrst.h linux-libre-2.6.38-gnu1/arch/x86/include/asm/mrst.h
--- linux-libre-2.6.37-gnu1/arch/x86/include/asm/mrst.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/include/asm/mrst.h	2011-03-14 21:20:32.000000000 -0400
@@ -14,7 +14,9 @@
 #include <linux/sfi.h>
 
 extern int pci_mrst_init(void);
-int __init sfi_parse_mrtc(struct sfi_table_header *table);
+extern int __init sfi_parse_mrtc(struct sfi_table_header *table);
+extern int sfi_mrtc_num;
+extern struct sfi_rtc_table_entry sfi_mrtc_array[];
 
 /*
  * Medfield is the follow-up of Moorestown, it combines two chip solution into
@@ -50,4 +52,14 @@ extern void mrst_early_console_init(void
 
 extern struct console early_hsu_console;
 extern void hsu_early_console_init(void);
+
+extern void intel_scu_devices_create(void);
+extern void intel_scu_devices_destroy(void);
+
+/* VRTC timer */
+#define MRST_VRTC_MAP_SZ	(1024)
+/*#define MRST_VRTC_PGOFFSET	(0xc00) */
+
+extern void mrst_rtc_init(void);
+
 #endif /* _ASM_X86_MRST_H */
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/include/asm/mrst-vrtc.h linux-libre-2.6.38-gnu1/arch/x86/include/asm/mrst-vrtc.h
--- linux-libre-2.6.37-gnu1/arch/x86/include/asm/mrst-vrtc.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/include/asm/mrst-vrtc.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,9 @@
+#ifndef _MRST_VRTC_H
+#define _MRST_VRTC_H
+
+extern unsigned char vrtc_cmos_read(unsigned char reg);
+extern void vrtc_cmos_write(unsigned char val, unsigned char reg);
+extern unsigned long vrtc_get_time(void);
+extern int vrtc_set_mmss(unsigned long nowtime);
+
+#endif
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/include/asm/msr-index.h linux-libre-2.6.38-gnu1/arch/x86/include/asm/msr-index.h
--- linux-libre-2.6.37-gnu1/arch/x86/include/asm/msr-index.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/include/asm/msr-index.h	2011-03-14 21:20:32.000000000 -0400
@@ -36,6 +36,11 @@
 #define MSR_IA32_PERFCTR1		0x000000c2
 #define MSR_FSB_FREQ			0x000000cd
 
+#define MSR_NHM_SNB_PKG_CST_CFG_CTL	0x000000e2
+#define NHM_C3_AUTO_DEMOTE		(1UL << 25)
+#define NHM_C1_AUTO_DEMOTE		(1UL << 26)
+#define ATM_LNC_C6_AUTO_DEMOTE		(1UL << 25)
+
 #define MSR_MTRRcap			0x000000fe
 #define MSR_IA32_BBL_CR_CTL		0x00000119
 
@@ -123,6 +128,10 @@
 #define MSR_AMD64_IBSCTL		0xc001103a
 #define MSR_AMD64_IBSBRTARGET		0xc001103b
 
+/* Fam 15h MSRs */
+#define MSR_F15H_PERF_CTL		0xc0010200
+#define MSR_F15H_PERF_CTR		0xc0010201
+
 /* Fam 10h MSRs */
 #define MSR_FAM10H_MMIO_CONF_BASE	0xc0010058
 #define FAM10H_MMIO_CONF_ENABLE		(1<<0)
@@ -253,6 +262,18 @@
 #define PACKAGE_THERM_INT_LOW_ENABLE		(1 << 1)
 #define PACKAGE_THERM_INT_PLN_ENABLE		(1 << 24)
 
+/* Thermal Thresholds Support */
+#define THERM_INT_THRESHOLD0_ENABLE    (1 << 15)
+#define THERM_SHIFT_THRESHOLD0        8
+#define THERM_MASK_THRESHOLD0          (0x7f << THERM_SHIFT_THRESHOLD0)
+#define THERM_INT_THRESHOLD1_ENABLE    (1 << 23)
+#define THERM_SHIFT_THRESHOLD1        16
+#define THERM_MASK_THRESHOLD1          (0x7f << THERM_SHIFT_THRESHOLD1)
+#define THERM_STATUS_THRESHOLD0        (1 << 6)
+#define THERM_LOG_THRESHOLD0           (1 << 7)
+#define THERM_STATUS_THRESHOLD1        (1 << 8)
+#define THERM_LOG_THRESHOLD1           (1 << 9)
+
 /* MISC_ENABLE bits: architectural */
 #define MSR_IA32_MISC_ENABLE_FAST_STRING	(1ULL << 0)
 #define MSR_IA32_MISC_ENABLE_TCC		(1ULL << 1)
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/include/asm/nmi.h linux-libre-2.6.38-gnu1/arch/x86/include/asm/nmi.h
--- linux-libre-2.6.37-gnu1/arch/x86/include/asm/nmi.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/include/asm/nmi.h	2011-03-14 21:20:32.000000000 -0400
@@ -5,41 +5,15 @@
 #include <asm/irq.h>
 #include <asm/io.h>
 
-#ifdef ARCH_HAS_NMI_WATCHDOG
-
-/**
- * do_nmi_callback
- *
- * Check to see if a callback exists and execute it.  Return 1
- * if the handler exists and was handled successfully.
- */
-int do_nmi_callback(struct pt_regs *regs, int cpu);
+#ifdef CONFIG_X86_LOCAL_APIC
 
 extern void die_nmi(char *str, struct pt_regs *regs, int do_panic);
-extern int check_nmi_watchdog(void);
-#if !defined(CONFIG_LOCKUP_DETECTOR)
-extern int nmi_watchdog_enabled;
-#endif
 extern int avail_to_resrv_perfctr_nmi_bit(unsigned int);
 extern int reserve_perfctr_nmi(unsigned int);
 extern void release_perfctr_nmi(unsigned int);
 extern int reserve_evntsel_nmi(unsigned int);
 extern void release_evntsel_nmi(unsigned int);
 
-extern void setup_apic_nmi_watchdog(void *);
-extern void stop_apic_nmi_watchdog(void *);
-extern void disable_timer_nmi_watchdog(void);
-extern void enable_timer_nmi_watchdog(void);
-extern int nmi_watchdog_tick(struct pt_regs *regs, unsigned reason);
-extern void cpu_nmi_set_wd_enabled(void);
-
-extern atomic_t nmi_active;
-extern unsigned int nmi_watchdog;
-#define NMI_NONE	0
-#define NMI_IO_APIC	1
-#define NMI_LOCAL_APIC	2
-#define NMI_INVALID	3
-
 struct ctl_table;
 extern int proc_nmi_enabled(struct ctl_table *, int ,
 			void __user *, size_t *, loff_t *);
@@ -47,33 +21,28 @@ extern int unknown_nmi_panic;
 
 void arch_trigger_all_cpu_backtrace(void);
 #define arch_trigger_all_cpu_backtrace arch_trigger_all_cpu_backtrace
+#endif
 
-static inline void localise_nmi_watchdog(void)
-{
-	if (nmi_watchdog == NMI_IO_APIC)
-		nmi_watchdog = NMI_LOCAL_APIC;
-}
+/*
+ * 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 seperate
+ * the priorities.  This can go alot higher if needed be.
+ */
 
-/* check if nmi_watchdog is active (ie was specified at boot) */
-static inline int nmi_watchdog_active(void)
-{
-	/*
-	 * actually it should be:
-	 * 	return (nmi_watchdog == NMI_LOCAL_APIC ||
-	 * 		nmi_watchdog == NMI_IO_APIC)
-	 * but since they are power of two we could use a
-	 * cheaper way --cvg
-	 */
-	return nmi_watchdog & (NMI_LOCAL_APIC | NMI_IO_APIC);
-}
-#endif
+#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)
 
-void lapic_watchdog_stop(void);
-int lapic_watchdog_init(unsigned nmi_hz);
-int lapic_wd_event(unsigned nmi_hz);
-unsigned lapic_adjust_nmi_hz(unsigned hz);
-void disable_lapic_nmi_watchdog(void);
-void enable_lapic_nmi_watchdog(void);
 void stop_nmi(void);
 void restart_nmi(void);
 
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/include/asm/numa_32.h linux-libre-2.6.38-gnu1/arch/x86/include/asm/numa_32.h
--- linux-libre-2.6.37-gnu1/arch/x86/include/asm/numa_32.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/include/asm/numa_32.h	2011-03-14 21:20:32.000000000 -0400
@@ -1,6 +1,8 @@
 #ifndef _ASM_X86_NUMA_32_H
 #define _ASM_X86_NUMA_32_H
 
+extern int numa_off;
+
 extern int pxm_to_nid(int pxm);
 extern void numa_remove_cpu(int cpu);
 
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/include/asm/numa_64.h linux-libre-2.6.38-gnu1/arch/x86/include/asm/numa_64.h
--- linux-libre-2.6.37-gnu1/arch/x86/include/asm/numa_64.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/include/asm/numa_64.h	2011-03-14 21:20:32.000000000 -0400
@@ -38,8 +38,9 @@ extern void __cpuinit numa_add_cpu(int c
 extern void __cpuinit numa_remove_cpu(int cpu);
 
 #ifdef CONFIG_NUMA_EMU
-#define FAKE_NODE_MIN_SIZE	((u64)64 << 20)
+#define FAKE_NODE_MIN_SIZE	((u64)32 << 20)
 #define FAKE_NODE_MIN_HASH_MASK	(~(FAKE_NODE_MIN_SIZE - 1UL))
+void numa_emu_cmdline(char *);
 #endif /* CONFIG_NUMA_EMU */
 #else
 static inline void init_cpu_to_node(void)		{ }
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/include/asm/olpc.h linux-libre-2.6.38-gnu1/arch/x86/include/asm/olpc.h
--- linux-libre-2.6.37-gnu1/arch/x86/include/asm/olpc.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/include/asm/olpc.h	2011-03-14 21:20:32.000000000 -0400
@@ -107,10 +107,14 @@ extern int olpc_ec_mask_unset(uint8_t bi
 /* GPIO assignments */
 
 #define OLPC_GPIO_MIC_AC	1
-#define OLPC_GPIO_DCON_IRQ	geode_gpio(7)
+#define OLPC_GPIO_DCON_STAT0	5
+#define OLPC_GPIO_DCON_STAT1	6
+#define OLPC_GPIO_DCON_IRQ	7
 #define OLPC_GPIO_THRM_ALRM	geode_gpio(10)
-#define OLPC_GPIO_SMB_CLK	geode_gpio(14)
-#define OLPC_GPIO_SMB_DATA	geode_gpio(15)
+#define OLPC_GPIO_DCON_LOAD    11
+#define OLPC_GPIO_DCON_BLANK   12
+#define OLPC_GPIO_SMB_CLK      14
+#define OLPC_GPIO_SMB_DATA     15
 #define OLPC_GPIO_WORKAUX	geode_gpio(24)
 #define OLPC_GPIO_LID		geode_gpio(26)
 #define OLPC_GPIO_ECSCI		geode_gpio(27)
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/include/asm/olpc_ofw.h linux-libre-2.6.38-gnu1/arch/x86/include/asm/olpc_ofw.h
--- linux-libre-2.6.37-gnu1/arch/x86/include/asm/olpc_ofw.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/include/asm/olpc_ofw.h	2011-03-14 21:20:32.000000000 -0400
@@ -8,6 +8,8 @@
 
 #ifdef CONFIG_OLPC_OPENFIRMWARE
 
+extern bool olpc_ofw_is_installed(void);
+
 /* run an OFW command by calling into the firmware */
 #define olpc_ofw(name, args, res) \
 	__olpc_ofw((name), ARRAY_SIZE(args), args, ARRAY_SIZE(res), res)
@@ -26,10 +28,17 @@ extern bool olpc_ofw_present(void);
 
 #else /* !CONFIG_OLPC_OPENFIRMWARE */
 
+static inline bool olpc_ofw_is_installed(void) { return false; }
 static inline void olpc_ofw_detect(void) { }
 static inline void setup_olpc_ofw_pgd(void) { }
 static inline bool olpc_ofw_present(void) { return false; }
 
 #endif /* !CONFIG_OLPC_OPENFIRMWARE */
 
+#ifdef CONFIG_OLPC_OPENFIRMWARE_DT
+extern void olpc_dt_build_devicetree(void);
+#else
+static inline void olpc_dt_build_devicetree(void) { }
+#endif /* CONFIG_OLPC_OPENFIRMWARE_DT */
+
 #endif /* _ASM_X86_OLPC_OFW_H */
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/include/asm/paravirt.h linux-libre-2.6.38-gnu1/arch/x86/include/asm/paravirt.h
--- linux-libre-2.6.37-gnu1/arch/x86/include/asm/paravirt.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/include/asm/paravirt.h	2011-03-14 21:20:32.000000000 -0400
@@ -112,7 +112,7 @@ static inline void arch_safe_halt(void)
 
 static inline void halt(void)
 {
-	PVOP_VCALL0(pv_irq_ops.safe_halt);
+	PVOP_VCALL0(pv_irq_ops.halt);
 }
 
 static inline void wbinvd(void)
@@ -435,6 +435,11 @@ static inline void pte_update(struct mm_
 {
 	PVOP_VCALL3(pv_mmu_ops.pte_update, mm, addr, ptep);
 }
+static inline void pmd_update(struct mm_struct *mm, unsigned long addr,
+			      pmd_t *pmdp)
+{
+	PVOP_VCALL3(pv_mmu_ops.pmd_update, mm, addr, pmdp);
+}
 
 static inline void pte_update_defer(struct mm_struct *mm, unsigned long addr,
 				    pte_t *ptep)
@@ -442,6 +447,12 @@ static inline void pte_update_defer(stru
 	PVOP_VCALL3(pv_mmu_ops.pte_update_defer, mm, addr, ptep);
 }
 
+static inline void pmd_update_defer(struct mm_struct *mm, unsigned long addr,
+				    pmd_t *pmdp)
+{
+	PVOP_VCALL3(pv_mmu_ops.pmd_update_defer, mm, addr, pmdp);
+}
+
 static inline pte_t __pte(pteval_t val)
 {
 	pteval_t ret;
@@ -543,6 +554,19 @@ static inline void set_pte_at(struct mm_
 		PVOP_VCALL4(pv_mmu_ops.set_pte_at, mm, addr, ptep, pte.pte);
 }
 
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
+static inline void set_pmd_at(struct mm_struct *mm, unsigned long addr,
+			      pmd_t *pmdp, pmd_t pmd)
+{
+	if (sizeof(pmdval_t) > sizeof(long))
+		/* 5 arg words */
+		pv_mmu_ops.set_pmd_at(mm, addr, pmdp, pmd);
+	else
+		PVOP_VCALL4(pv_mmu_ops.set_pmd_at, mm, addr, pmdp,
+			    native_pmd_val(pmd));
+}
+#endif
+
 static inline void set_pmd(pmd_t *pmdp, pmd_t pmd)
 {
 	pmdval_t val = native_pmd_val(pmd);
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/include/asm/paravirt_types.h linux-libre-2.6.38-gnu1/arch/x86/include/asm/paravirt_types.h
--- linux-libre-2.6.37-gnu1/arch/x86/include/asm/paravirt_types.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/include/asm/paravirt_types.h	2011-03-14 21:20:32.000000000 -0400
@@ -265,10 +265,16 @@ struct pv_mmu_ops {
 	void (*set_pte_at)(struct mm_struct *mm, unsigned long addr,
 			   pte_t *ptep, pte_t pteval);
 	void (*set_pmd)(pmd_t *pmdp, pmd_t pmdval);
+	void (*set_pmd_at)(struct mm_struct *mm, unsigned long addr,
+			   pmd_t *pmdp, pmd_t pmdval);
 	void (*pte_update)(struct mm_struct *mm, unsigned long addr,
 			   pte_t *ptep);
 	void (*pte_update_defer)(struct mm_struct *mm,
 				 unsigned long addr, pte_t *ptep);
+	void (*pmd_update)(struct mm_struct *mm, unsigned long addr,
+			   pmd_t *pmdp);
+	void (*pmd_update_defer)(struct mm_struct *mm,
+				 unsigned long addr, pmd_t *pmdp);
 
 	pte_t (*ptep_modify_prot_start)(struct mm_struct *mm, unsigned long addr,
 					pte_t *ptep);
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/include/asm/pci.h linux-libre-2.6.38-gnu1/arch/x86/include/asm/pci.h
--- linux-libre-2.6.37-gnu1/arch/x86/include/asm/pci.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/include/asm/pci.h	2011-03-14 21:20:32.000000000 -0400
@@ -65,6 +65,7 @@ extern unsigned long pci_mem_start;
 
 #define PCIBIOS_MIN_CARDBUS_IO	0x4000
 
+extern int pcibios_enabled;
 void pcibios_config_init(void);
 struct pci_bus *pcibios_scan_root(int bus);
 
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/include/asm/percpu.h linux-libre-2.6.38-gnu1/arch/x86/include/asm/percpu.h
--- linux-libre-2.6.37-gnu1/arch/x86/include/asm/percpu.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/include/asm/percpu.h	2011-03-14 21:20:32.000000000 -0400
@@ -230,6 +230,125 @@ do {									\
 })
 
 /*
+ * Add return operation
+ */
+#define percpu_add_return_op(var, val)					\
+({									\
+	typeof(var) paro_ret__ = val;					\
+	switch (sizeof(var)) {						\
+	case 1:								\
+		asm("xaddb %0, "__percpu_arg(1)				\
+			    : "+q" (paro_ret__), "+m" (var)		\
+			    : : "memory");				\
+		break;							\
+	case 2:								\
+		asm("xaddw %0, "__percpu_arg(1)				\
+			    : "+r" (paro_ret__), "+m" (var)		\
+			    : : "memory");				\
+		break;							\
+	case 4:								\
+		asm("xaddl %0, "__percpu_arg(1)				\
+			    : "+r" (paro_ret__), "+m" (var)		\
+			    : : "memory");				\
+		break;							\
+	case 8:								\
+		asm("xaddq %0, "__percpu_arg(1)				\
+			    : "+re" (paro_ret__), "+m" (var)		\
+			    : : "memory");				\
+		break;							\
+	default: __bad_percpu_size();					\
+	}								\
+	paro_ret__ += val;						\
+	paro_ret__;							\
+})
+
+/*
+ * xchg is implemented using cmpxchg without a lock prefix. xchg is
+ * expensive due to the implied lock prefix.  The processor cannot prefetch
+ * cachelines if xchg is used.
+ */
+#define percpu_xchg_op(var, nval)					\
+({									\
+	typeof(var) pxo_ret__;						\
+	typeof(var) pxo_new__ = (nval);					\
+	switch (sizeof(var)) {						\
+	case 1:								\
+		asm("\n\tmov "__percpu_arg(1)",%%al"			\
+		    "\n1:\tcmpxchgb %2, "__percpu_arg(1)		\
+		    "\n\tjnz 1b"					\
+			    : "=&a" (pxo_ret__), "+m" (var)		\
+			    : "q" (pxo_new__)				\
+			    : "memory");				\
+		break;							\
+	case 2:								\
+		asm("\n\tmov "__percpu_arg(1)",%%ax"			\
+		    "\n1:\tcmpxchgw %2, "__percpu_arg(1)		\
+		    "\n\tjnz 1b"					\
+			    : "=&a" (pxo_ret__), "+m" (var)		\
+			    : "r" (pxo_new__)				\
+			    : "memory");				\
+		break;							\
+	case 4:								\
+		asm("\n\tmov "__percpu_arg(1)",%%eax"			\
+		    "\n1:\tcmpxchgl %2, "__percpu_arg(1)		\
+		    "\n\tjnz 1b"					\
+			    : "=&a" (pxo_ret__), "+m" (var)		\
+			    : "r" (pxo_new__)				\
+			    : "memory");				\
+		break;							\
+	case 8:								\
+		asm("\n\tmov "__percpu_arg(1)",%%rax"			\
+		    "\n1:\tcmpxchgq %2, "__percpu_arg(1)		\
+		    "\n\tjnz 1b"					\
+			    : "=&a" (pxo_ret__), "+m" (var)		\
+			    : "r" (pxo_new__)				\
+			    : "memory");				\
+		break;							\
+	default: __bad_percpu_size();					\
+	}								\
+	pxo_ret__;							\
+})
+
+/*
+ * cmpxchg has no such implied lock semantics as a result it is much
+ * more efficient for cpu local operations.
+ */
+#define percpu_cmpxchg_op(var, oval, nval)				\
+({									\
+	typeof(var) pco_ret__;						\
+	typeof(var) pco_old__ = (oval);					\
+	typeof(var) pco_new__ = (nval);					\
+	switch (sizeof(var)) {						\
+	case 1:								\
+		asm("cmpxchgb %2, "__percpu_arg(1)			\
+			    : "=a" (pco_ret__), "+m" (var)		\
+			    : "q" (pco_new__), "0" (pco_old__)		\
+			    : "memory");				\
+		break;							\
+	case 2:								\
+		asm("cmpxchgw %2, "__percpu_arg(1)			\
+			    : "=a" (pco_ret__), "+m" (var)		\
+			    : "r" (pco_new__), "0" (pco_old__)		\
+			    : "memory");				\
+		break;							\
+	case 4:								\
+		asm("cmpxchgl %2, "__percpu_arg(1)			\
+			    : "=a" (pco_ret__), "+m" (var)		\
+			    : "r" (pco_new__), "0" (pco_old__)		\
+			    : "memory");				\
+		break;							\
+	case 8:								\
+		asm("cmpxchgq %2, "__percpu_arg(1)			\
+			    : "=a" (pco_ret__), "+m" (var)		\
+			    : "r" (pco_new__), "0" (pco_old__)		\
+			    : "memory");				\
+		break;							\
+	default: __bad_percpu_size();					\
+	}								\
+	pco_ret__;							\
+})
+
+/*
  * percpu_read() makes gcc load the percpu variable every time it is
  * accessed while percpu_read_stable() allows the value to be cached.
  * percpu_read_stable() is more efficient and can be used if its value
@@ -267,6 +386,12 @@ do {									\
 #define __this_cpu_xor_1(pcp, val)	percpu_to_op("xor", (pcp), val)
 #define __this_cpu_xor_2(pcp, val)	percpu_to_op("xor", (pcp), val)
 #define __this_cpu_xor_4(pcp, val)	percpu_to_op("xor", (pcp), val)
+/*
+ * Generic fallback operations for __this_cpu_xchg_[1-4] are okay and much
+ * faster than an xchg with forced lock semantics.
+ */
+#define __this_cpu_xchg_8(pcp, nval)	percpu_xchg_op(pcp, nval)
+#define __this_cpu_cmpxchg_8(pcp, oval, nval)	percpu_cmpxchg_op(pcp, oval, nval)
 
 #define this_cpu_read_1(pcp)		percpu_from_op("mov", (pcp), "m"(pcp))
 #define this_cpu_read_2(pcp)		percpu_from_op("mov", (pcp), "m"(pcp))
@@ -286,6 +411,9 @@ do {									\
 #define this_cpu_xor_1(pcp, val)	percpu_to_op("xor", (pcp), val)
 #define this_cpu_xor_2(pcp, val)	percpu_to_op("xor", (pcp), val)
 #define this_cpu_xor_4(pcp, val)	percpu_to_op("xor", (pcp), val)
+#define this_cpu_xchg_1(pcp, nval)	percpu_xchg_op(pcp, nval)
+#define this_cpu_xchg_2(pcp, nval)	percpu_xchg_op(pcp, nval)
+#define this_cpu_xchg_4(pcp, nval)	percpu_xchg_op(pcp, nval)
 
 #define irqsafe_cpu_add_1(pcp, val)	percpu_add_op((pcp), val)
 #define irqsafe_cpu_add_2(pcp, val)	percpu_add_op((pcp), val)
@@ -299,6 +427,29 @@ do {									\
 #define irqsafe_cpu_xor_1(pcp, val)	percpu_to_op("xor", (pcp), val)
 #define irqsafe_cpu_xor_2(pcp, val)	percpu_to_op("xor", (pcp), val)
 #define irqsafe_cpu_xor_4(pcp, val)	percpu_to_op("xor", (pcp), val)
+#define irqsafe_cpu_xchg_1(pcp, nval)	percpu_xchg_op(pcp, nval)
+#define irqsafe_cpu_xchg_2(pcp, nval)	percpu_xchg_op(pcp, nval)
+#define irqsafe_cpu_xchg_4(pcp, nval)	percpu_xchg_op(pcp, nval)
+
+#ifndef CONFIG_M386
+#define __this_cpu_add_return_1(pcp, val) percpu_add_return_op(pcp, val)
+#define __this_cpu_add_return_2(pcp, val) percpu_add_return_op(pcp, val)
+#define __this_cpu_add_return_4(pcp, val) percpu_add_return_op(pcp, val)
+#define __this_cpu_cmpxchg_1(pcp, oval, nval)	percpu_cmpxchg_op(pcp, oval, nval)
+#define __this_cpu_cmpxchg_2(pcp, oval, nval)	percpu_cmpxchg_op(pcp, oval, nval)
+#define __this_cpu_cmpxchg_4(pcp, oval, nval)	percpu_cmpxchg_op(pcp, oval, nval)
+
+#define this_cpu_add_return_1(pcp, val)	percpu_add_return_op(pcp, val)
+#define this_cpu_add_return_2(pcp, val)	percpu_add_return_op(pcp, val)
+#define this_cpu_add_return_4(pcp, val)	percpu_add_return_op(pcp, val)
+#define this_cpu_cmpxchg_1(pcp, oval, nval)	percpu_cmpxchg_op(pcp, oval, nval)
+#define this_cpu_cmpxchg_2(pcp, oval, nval)	percpu_cmpxchg_op(pcp, oval, nval)
+#define this_cpu_cmpxchg_4(pcp, oval, nval)	percpu_cmpxchg_op(pcp, oval, nval)
+
+#define irqsafe_cpu_cmpxchg_1(pcp, oval, nval)	percpu_cmpxchg_op(pcp, oval, nval)
+#define irqsafe_cpu_cmpxchg_2(pcp, oval, nval)	percpu_cmpxchg_op(pcp, oval, nval)
+#define irqsafe_cpu_cmpxchg_4(pcp, oval, nval)	percpu_cmpxchg_op(pcp, oval, nval)
+#endif /* !CONFIG_M386 */
 
 /*
  * Per cpu atomic 64 bit operations are only available under 64 bit.
@@ -311,6 +462,7 @@ do {									\
 #define __this_cpu_and_8(pcp, val)	percpu_to_op("and", (pcp), val)
 #define __this_cpu_or_8(pcp, val)	percpu_to_op("or", (pcp), val)
 #define __this_cpu_xor_8(pcp, val)	percpu_to_op("xor", (pcp), val)
+#define __this_cpu_add_return_8(pcp, val) percpu_add_return_op(pcp, val)
 
 #define this_cpu_read_8(pcp)		percpu_from_op("mov", (pcp), "m"(pcp))
 #define this_cpu_write_8(pcp, val)	percpu_to_op("mov", (pcp), val)
@@ -318,12 +470,16 @@ do {									\
 #define this_cpu_and_8(pcp, val)	percpu_to_op("and", (pcp), val)
 #define this_cpu_or_8(pcp, val)		percpu_to_op("or", (pcp), val)
 #define this_cpu_xor_8(pcp, val)	percpu_to_op("xor", (pcp), val)
+#define this_cpu_add_return_8(pcp, val)	percpu_add_return_op(pcp, val)
+#define this_cpu_xchg_8(pcp, nval)	percpu_xchg_op(pcp, nval)
+#define this_cpu_cmpxchg_8(pcp, oval, nval)	percpu_cmpxchg_op(pcp, oval, nval)
 
 #define irqsafe_cpu_add_8(pcp, val)	percpu_add_op((pcp), val)
 #define irqsafe_cpu_and_8(pcp, val)	percpu_to_op("and", (pcp), val)
 #define irqsafe_cpu_or_8(pcp, val)	percpu_to_op("or", (pcp), val)
 #define irqsafe_cpu_xor_8(pcp, val)	percpu_to_op("xor", (pcp), val)
-
+#define irqsafe_cpu_xchg_8(pcp, nval)	percpu_xchg_op(pcp, nval)
+#define irqsafe_cpu_cmpxchg_8(pcp, oval, nval)	percpu_cmpxchg_op(pcp, oval, nval)
 #endif
 
 /* This is not atomic against other CPUs -- CPU preemption needs to be off */
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/include/asm/perf_event.h linux-libre-2.6.38-gnu1/arch/x86/include/asm/perf_event.h
--- linux-libre-2.6.37-gnu1/arch/x86/include/asm/perf_event.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/include/asm/perf_event.h	2011-03-14 21:20:32.000000000 -0400
@@ -125,7 +125,6 @@ union cpuid10_edx {
 #define IBS_OP_MAX_CNT_EXT	0x007FFFFFULL	/* not a register bit mask */
 
 #ifdef CONFIG_PERF_EVENTS
-extern void init_hw_perf_events(void);
 extern void perf_events_lapic_init(void);
 
 #define PERF_EVENT_INDEX_OFFSET			0
@@ -156,7 +155,6 @@ extern unsigned long perf_misc_flags(str
 }
 
 #else
-static inline void init_hw_perf_events(void)		{ }
 static inline void perf_events_lapic_init(void)	{ }
 #endif
 
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/include/asm/perf_event_p4.h linux-libre-2.6.38-gnu1/arch/x86/include/asm/perf_event_p4.h
--- linux-libre-2.6.37-gnu1/arch/x86/include/asm/perf_event_p4.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/include/asm/perf_event_p4.h	2011-03-14 21:20:32.000000000 -0400
@@ -20,6 +20,10 @@
 #define ARCH_P4_MAX_ESCR	(ARCH_P4_TOTAL_ESCR - ARCH_P4_RESERVED_ESCR)
 #define ARCH_P4_MAX_CCCR	(18)
 
+#define ARCH_P4_CNTRVAL_BITS	(40)
+#define ARCH_P4_CNTRVAL_MASK	((1ULL << ARCH_P4_CNTRVAL_BITS) - 1)
+#define ARCH_P4_UNFLAGGED_BIT	((1ULL) << (ARCH_P4_CNTRVAL_BITS - 1))
+
 #define P4_ESCR_EVENT_MASK	0x7e000000U
 #define P4_ESCR_EVENT_SHIFT	25
 #define P4_ESCR_EVENTMASK_MASK	0x01fffe00U
@@ -744,14 +748,6 @@ enum P4_ESCR_EMASKS {
 };
 
 /*
- * P4 PEBS specifics (Replay Event only)
- *
- * Format (bits):
- *   0-6: metric from P4_PEBS_METRIC enum
- *    7 : reserved
- *    8 : reserved
- * 9-11 : reserved
- *
  * Note we have UOP and PEBS bits reserved for now
  * just in case if we will need them once
  */
@@ -788,5 +784,60 @@ enum P4_PEBS_METRIC {
 	P4_PEBS_METRIC__max
 };
 
+/*
+ * Notes on internal configuration of ESCR+CCCR tuples
+ *
+ * Since P4 has quite the different architecture of
+ * performance registers in compare with "architectural"
+ * once and we have on 64 bits to keep configuration
+ * of performance event, the following trick is used.
+ *
+ * 1) Since both ESCR and CCCR registers have only low
+ *    32 bits valuable, we pack them into a single 64 bit
+ *    configuration. Low 32 bits of such config correspond
+ *    to low 32 bits of CCCR register and high 32 bits
+ *    correspond to low 32 bits of ESCR register.
+ *
+ * 2) The meaning of every bit of such config field can
+ *    be found in Intel SDM but it should be noted that
+ *    we "borrow" some reserved bits for own usage and
+ *    clean them or set to a proper value when we do
+ *    a real write to hardware registers.
+ *
+ * 3) The format of bits of config is the following
+ *    and should be either 0 or set to some predefined
+ *    values:
+ *
+ *    Low 32 bits
+ *    -----------
+ *      0-6: P4_PEBS_METRIC enum
+ *     7-11:                    reserved
+ *       12:                    reserved (Enable)
+ *    13-15:                    reserved (ESCR select)
+ *    16-17: Active Thread
+ *       18: Compare
+ *       19: Complement
+ *    20-23: Threshold
+ *       24: Edge
+ *       25:                    reserved (FORCE_OVF)
+ *       26:                    reserved (OVF_PMI_T0)
+ *       27:                    reserved (OVF_PMI_T1)
+ *    28-29:                    reserved
+ *       30:                    reserved (Cascade)
+ *       31:                    reserved (OVF)
+ *
+ *    High 32 bits
+ *    ------------
+ *        0:                    reserved (T1_USR)
+ *        1:                    reserved (T1_OS)
+ *        2:                    reserved (T0_USR)
+ *        3:                    reserved (T0_OS)
+ *        4: Tag Enable
+ *      5-8: Tag Value
+ *     9-24: Event Mask (may use P4_ESCR_EMASK_BIT helper)
+ *    25-30: enum P4_EVENTS
+ *       31:                    reserved (HT thread)
+ */
+
 #endif /* PERF_EVENT_P4_H */
 
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/include/asm/pgalloc.h linux-libre-2.6.38-gnu1/arch/x86/include/asm/pgalloc.h
--- linux-libre-2.6.37-gnu1/arch/x86/include/asm/pgalloc.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/include/asm/pgalloc.h	2011-03-14 21:20:32.000000000 -0400
@@ -92,7 +92,7 @@ static inline void pmd_free(struct mm_st
 extern void ___pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd);
 
 static inline void __pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd,
-				  unsigned long adddress)
+				  unsigned long address)
 {
 	___pmd_free_tlb(tlb, pmd);
 }
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/include/asm/pgtable-2level.h linux-libre-2.6.38-gnu1/arch/x86/include/asm/pgtable-2level.h
--- linux-libre-2.6.37-gnu1/arch/x86/include/asm/pgtable-2level.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/include/asm/pgtable-2level.h	2011-03-14 21:20:32.000000000 -0400
@@ -46,6 +46,15 @@ static inline pte_t native_ptep_get_and_
 #define native_ptep_get_and_clear(xp) native_local_ptep_get_and_clear(xp)
 #endif
 
+#ifdef CONFIG_SMP
+static inline pmd_t native_pmdp_get_and_clear(pmd_t *xp)
+{
+	return __pmd(xchg((pmdval_t *)xp, 0));
+}
+#else
+#define native_pmdp_get_and_clear(xp) native_local_pmdp_get_and_clear(xp)
+#endif
+
 /*
  * Bits _PAGE_BIT_PRESENT, _PAGE_BIT_FILE and _PAGE_BIT_PROTNONE are taken,
  * split up the 29 bits of offset into this range:
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/include/asm/pgtable-3level.h linux-libre-2.6.38-gnu1/arch/x86/include/asm/pgtable-3level.h
--- linux-libre-2.6.37-gnu1/arch/x86/include/asm/pgtable-3level.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/include/asm/pgtable-3level.h	2011-03-14 21:20:32.000000000 -0400
@@ -104,6 +104,29 @@ static inline pte_t native_ptep_get_and_
 #define native_ptep_get_and_clear(xp) native_local_ptep_get_and_clear(xp)
 #endif
 
+#ifdef CONFIG_SMP
+union split_pmd {
+	struct {
+		u32 pmd_low;
+		u32 pmd_high;
+	};
+	pmd_t pmd;
+};
+static inline pmd_t native_pmdp_get_and_clear(pmd_t *pmdp)
+{
+	union split_pmd res, *orig = (union split_pmd *)pmdp;
+
+	/* xchg acts as a barrier before setting of the high bits */
+	res.pmd_low = xchg(&orig->pmd_low, 0);
+	res.pmd_high = orig->pmd_high;
+	orig->pmd_high = 0;
+
+	return res.pmd;
+}
+#else
+#define native_pmdp_get_and_clear(xp) native_local_pmdp_get_and_clear(xp)
+#endif
+
 /*
  * Bits 0, 6 and 7 are taken in the low part of the pte,
  * put the 32 bits of offset into the high part.
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/include/asm/pgtable_64.h linux-libre-2.6.38-gnu1/arch/x86/include/asm/pgtable_64.h
--- linux-libre-2.6.37-gnu1/arch/x86/include/asm/pgtable_64.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/include/asm/pgtable_64.h	2011-03-14 21:20:32.000000000 -0400
@@ -59,6 +59,16 @@ static inline void native_set_pte_atomic
 	native_set_pte(ptep, pte);
 }
 
+static inline void native_set_pmd(pmd_t *pmdp, pmd_t pmd)
+{
+	*pmdp = pmd;
+}
+
+static inline void native_pmd_clear(pmd_t *pmd)
+{
+	native_set_pmd(pmd, native_make_pmd(0));
+}
+
 static inline pte_t native_ptep_get_and_clear(pte_t *xp)
 {
 #ifdef CONFIG_SMP
@@ -72,14 +82,17 @@ static inline pte_t native_ptep_get_and_
 #endif
 }
 
-static inline void native_set_pmd(pmd_t *pmdp, pmd_t pmd)
-{
-	*pmdp = pmd;
-}
-
-static inline void native_pmd_clear(pmd_t *pmd)
+static inline pmd_t native_pmdp_get_and_clear(pmd_t *xp)
 {
-	native_set_pmd(pmd, native_make_pmd(0));
+#ifdef CONFIG_SMP
+	return native_make_pmd(xchg(&xp->pmd, 0));
+#else
+	/* native_local_pmdp_get_and_clear,
+	   but duplicated because of cyclic dependency */
+	pmd_t ret = *xp;
+	native_pmd_clear(xp);
+	return ret;
+#endif
 }
 
 static inline void native_set_pud(pud_t *pudp, pud_t pud)
@@ -168,6 +181,7 @@ extern void cleanup_highmap(void);
 #define	kc_offset_to_vaddr(o) ((o) | ~__VIRTUAL_MASK)
 
 #define __HAVE_ARCH_PTE_SAME
+
 #endif /* !__ASSEMBLY__ */
 
 #endif /* _ASM_X86_PGTABLE_64_H */
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/include/asm/pgtable.h linux-libre-2.6.38-gnu1/arch/x86/include/asm/pgtable.h
--- linux-libre-2.6.37-gnu1/arch/x86/include/asm/pgtable.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/include/asm/pgtable.h	2011-03-14 21:20:32.000000000 -0400
@@ -35,6 +35,7 @@ extern struct mm_struct *pgd_page_get_mm
 #else  /* !CONFIG_PARAVIRT */
 #define set_pte(ptep, pte)		native_set_pte(ptep, pte)
 #define set_pte_at(mm, addr, ptep, pte)	native_set_pte_at(mm, addr, ptep, pte)
+#define set_pmd_at(mm, addr, pmdp, pmd)	native_set_pmd_at(mm, addr, pmdp, pmd)
 
 #define set_pte_atomic(ptep, pte)					\
 	native_set_pte_atomic(ptep, pte)
@@ -59,6 +60,8 @@ extern struct mm_struct *pgd_page_get_mm
 
 #define pte_update(mm, addr, ptep)              do { } while (0)
 #define pte_update_defer(mm, addr, ptep)        do { } while (0)
+#define pmd_update(mm, addr, ptep)              do { } while (0)
+#define pmd_update_defer(mm, addr, ptep)        do { } while (0)
 
 #define pgd_val(x)	native_pgd_val(x)
 #define __pgd(x)	native_make_pgd(x)
@@ -94,6 +97,11 @@ static inline int pte_young(pte_t pte)
 	return pte_flags(pte) & _PAGE_ACCESSED;
 }
 
+static inline int pmd_young(pmd_t pmd)
+{
+	return pmd_flags(pmd) & _PAGE_ACCESSED;
+}
+
 static inline int pte_write(pte_t pte)
 {
 	return pte_flags(pte) & _PAGE_RW;
@@ -142,6 +150,23 @@ static inline int pmd_large(pmd_t pte)
 		(_PAGE_PSE | _PAGE_PRESENT);
 }
 
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
+static inline int pmd_trans_splitting(pmd_t pmd)
+{
+	return pmd_val(pmd) & _PAGE_SPLITTING;
+}
+
+static inline int pmd_trans_huge(pmd_t pmd)
+{
+	return pmd_val(pmd) & _PAGE_PSE;
+}
+
+static inline int has_transparent_hugepage(void)
+{
+	return cpu_has_pse;
+}
+#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
+
 static inline pte_t pte_set_flags(pte_t pte, pteval_t set)
 {
 	pteval_t v = native_pte_val(pte);
@@ -216,6 +241,55 @@ static inline pte_t pte_mkspecial(pte_t
 	return pte_set_flags(pte, _PAGE_SPECIAL);
 }
 
+static inline pmd_t pmd_set_flags(pmd_t pmd, pmdval_t set)
+{
+	pmdval_t v = native_pmd_val(pmd);
+
+	return __pmd(v | set);
+}
+
+static inline pmd_t pmd_clear_flags(pmd_t pmd, pmdval_t clear)
+{
+	pmdval_t v = native_pmd_val(pmd);
+
+	return __pmd(v & ~clear);
+}
+
+static inline pmd_t pmd_mkold(pmd_t pmd)
+{
+	return pmd_clear_flags(pmd, _PAGE_ACCESSED);
+}
+
+static inline pmd_t pmd_wrprotect(pmd_t pmd)
+{
+	return pmd_clear_flags(pmd, _PAGE_RW);
+}
+
+static inline pmd_t pmd_mkdirty(pmd_t pmd)
+{
+	return pmd_set_flags(pmd, _PAGE_DIRTY);
+}
+
+static inline pmd_t pmd_mkhuge(pmd_t pmd)
+{
+	return pmd_set_flags(pmd, _PAGE_PSE);
+}
+
+static inline pmd_t pmd_mkyoung(pmd_t pmd)
+{
+	return pmd_set_flags(pmd, _PAGE_ACCESSED);
+}
+
+static inline pmd_t pmd_mkwrite(pmd_t pmd)
+{
+	return pmd_set_flags(pmd, _PAGE_RW);
+}
+
+static inline pmd_t pmd_mknotpresent(pmd_t pmd)
+{
+	return pmd_clear_flags(pmd, _PAGE_PRESENT);
+}
+
 /*
  * Mask out unsupported bits in a present pgprot.  Non-present pgprots
  * can use those bits for other purposes, so leave them be.
@@ -256,6 +330,16 @@ static inline pte_t pte_modify(pte_t pte
 	return __pte(val);
 }
 
+static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot)
+{
+	pmdval_t val = pmd_val(pmd);
+
+	val &= _HPAGE_CHG_MASK;
+	val |= massage_pgprot(newprot) & ~_HPAGE_CHG_MASK;
+
+	return __pmd(val);
+}
+
 /* mprotect needs to preserve PAT bits when updating vm_page_prot */
 #define pgprot_modify pgprot_modify
 static inline pgprot_t pgprot_modify(pgprot_t oldprot, pgprot_t newprot)
@@ -350,7 +434,7 @@ static inline unsigned long pmd_page_vad
  * Currently stuck as a macro due to indirect forward reference to
  * linux/mmzone.h's __section_mem_map_addr() definition:
  */
-#define pmd_page(pmd)	pfn_to_page(pmd_val(pmd) >> PAGE_SHIFT)
+#define pmd_page(pmd)	pfn_to_page((pmd_val(pmd) & PTE_PFN_MASK) >> PAGE_SHIFT)
 
 /*
  * the pmd page can be thought of an array like this: pmd_t[PTRS_PER_PMD]
@@ -524,12 +608,26 @@ static inline pte_t native_local_ptep_ge
 	return res;
 }
 
+static inline pmd_t native_local_pmdp_get_and_clear(pmd_t *pmdp)
+{
+	pmd_t res = *pmdp;
+
+	native_pmd_clear(pmdp);
+	return res;
+}
+
 static inline void native_set_pte_at(struct mm_struct *mm, unsigned long addr,
 				     pte_t *ptep , pte_t pte)
 {
 	native_set_pte(ptep, pte);
 }
 
+static inline void native_set_pmd_at(struct mm_struct *mm, unsigned long addr,
+				     pmd_t *pmdp , pmd_t pmd)
+{
+	native_set_pmd(pmdp, pmd);
+}
+
 #ifndef CONFIG_PARAVIRT
 /*
  * Rules for using pte_update - it must be called after any PTE update which
@@ -607,6 +705,49 @@ static inline void ptep_set_wrprotect(st
 
 #define flush_tlb_fix_spurious_fault(vma, address)
 
+#define mk_pmd(page, pgprot)   pfn_pmd(page_to_pfn(page), (pgprot))
+
+#define  __HAVE_ARCH_PMDP_SET_ACCESS_FLAGS
+extern int pmdp_set_access_flags(struct vm_area_struct *vma,
+				 unsigned long address, pmd_t *pmdp,
+				 pmd_t entry, int dirty);
+
+#define __HAVE_ARCH_PMDP_TEST_AND_CLEAR_YOUNG
+extern int pmdp_test_and_clear_young(struct vm_area_struct *vma,
+				     unsigned long addr, pmd_t *pmdp);
+
+#define __HAVE_ARCH_PMDP_CLEAR_YOUNG_FLUSH
+extern int pmdp_clear_flush_young(struct vm_area_struct *vma,
+				  unsigned long address, pmd_t *pmdp);
+
+
+#define __HAVE_ARCH_PMDP_SPLITTING_FLUSH
+extern void pmdp_splitting_flush(struct vm_area_struct *vma,
+				 unsigned long addr, pmd_t *pmdp);
+
+#define __HAVE_ARCH_PMD_WRITE
+static inline int pmd_write(pmd_t pmd)
+{
+	return pmd_flags(pmd) & _PAGE_RW;
+}
+
+#define __HAVE_ARCH_PMDP_GET_AND_CLEAR
+static inline pmd_t pmdp_get_and_clear(struct mm_struct *mm, unsigned long addr,
+				       pmd_t *pmdp)
+{
+	pmd_t pmd = native_pmdp_get_and_clear(pmdp);
+	pmd_update(mm, addr, pmdp);
+	return pmd;
+}
+
+#define __HAVE_ARCH_PMDP_SET_WRPROTECT
+static inline void pmdp_set_wrprotect(struct mm_struct *mm,
+				      unsigned long addr, pmd_t *pmdp)
+{
+	clear_bit(_PAGE_BIT_RW, (unsigned long *)pmdp);
+	pmd_update(mm, addr, pmdp);
+}
+
 /*
  * clone_pgd_range(pgd_t *dst, pgd_t *src, int count);
  *
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/include/asm/pgtable_types.h linux-libre-2.6.38-gnu1/arch/x86/include/asm/pgtable_types.h
--- linux-libre-2.6.37-gnu1/arch/x86/include/asm/pgtable_types.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/include/asm/pgtable_types.h	2011-03-14 21:20:32.000000000 -0400
@@ -22,6 +22,7 @@
 #define _PAGE_BIT_PAT_LARGE	12	/* On 2MB or 1GB pages */
 #define _PAGE_BIT_SPECIAL	_PAGE_BIT_UNUSED1
 #define _PAGE_BIT_CPA_TEST	_PAGE_BIT_UNUSED1
+#define _PAGE_BIT_SPLITTING	_PAGE_BIT_UNUSED1 /* only valid on a PSE pmd */
 #define _PAGE_BIT_NX           63       /* No execute: only valid after cpuid check */
 
 /* If _PAGE_BIT_PRESENT is clear, we use these: */
@@ -45,6 +46,7 @@
 #define _PAGE_PAT_LARGE (_AT(pteval_t, 1) << _PAGE_BIT_PAT_LARGE)
 #define _PAGE_SPECIAL	(_AT(pteval_t, 1) << _PAGE_BIT_SPECIAL)
 #define _PAGE_CPA_TEST	(_AT(pteval_t, 1) << _PAGE_BIT_CPA_TEST)
+#define _PAGE_SPLITTING	(_AT(pteval_t, 1) << _PAGE_BIT_SPLITTING)
 #define __HAVE_ARCH_PTE_SPECIAL
 
 #ifdef CONFIG_KMEMCHECK
@@ -70,6 +72,7 @@
 /* Set of bits not changed in pte_modify */
 #define _PAGE_CHG_MASK	(PTE_PFN_MASK | _PAGE_PCD | _PAGE_PWT |		\
 			 _PAGE_SPECIAL | _PAGE_ACCESSED | _PAGE_DIRTY)
+#define _HPAGE_CHG_MASK (_PAGE_CHG_MASK | _PAGE_PSE)
 
 #define _PAGE_CACHE_MASK	(_PAGE_PCD | _PAGE_PWT)
 #define _PAGE_CACHE_WB		(0)
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/include/asm/processor.h linux-libre-2.6.38-gnu1/arch/x86/include/asm/processor.h
--- linux-libre-2.6.37-gnu1/arch/x86/include/asm/processor.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/include/asm/processor.h	2011-03-14 21:20:32.000000000 -0400
@@ -141,10 +141,9 @@ extern __u32			cpu_caps_set[NCAPINTS];
 #ifdef CONFIG_SMP
 DECLARE_PER_CPU_SHARED_ALIGNED(struct cpuinfo_x86, cpu_info);
 #define cpu_data(cpu)		per_cpu(cpu_info, cpu)
-#define current_cpu_data	__get_cpu_var(cpu_info)
 #else
+#define cpu_info		boot_cpu_data
 #define cpu_data(cpu)		boot_cpu_data
-#define current_cpu_data	boot_cpu_data
 #endif
 
 extern const struct seq_operations cpuinfo_op;
@@ -762,10 +761,11 @@ extern void select_idle_routine(const st
 extern void init_c1e_mask(void);
 
 extern unsigned long		boot_option_idle_override;
-extern unsigned long		idle_halt;
-extern unsigned long		idle_nomwait;
 extern bool			c1e_detected;
 
+enum idle_boot_override {IDLE_NO_OVERRIDE=0, IDLE_HALT, IDLE_NOMWAIT,
+			 IDLE_POLL, IDLE_FORCE_MWAIT};
+
 extern void enable_sep_cpu(void);
 extern int sysenter_setup(void);
 
@@ -902,7 +902,7 @@ extern unsigned long thread_saved_pc(str
 /*
  * The below -8 is to reserve 8 bytes on top of the ring0 stack.
  * This is necessary to guarantee that the entire "struct pt_regs"
- * is accessable even if the CPU haven't stored the SS/ESP registers
+ * is accessible even if the CPU haven't stored the SS/ESP registers
  * on the stack (interrupt gate does not save these registers
  * when switching to the same priv ring).
  * Therefore beware: accessing the ss/esp fields of the
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/include/asm/prom.h linux-libre-2.6.38-gnu1/arch/x86/include/asm/prom.h
--- linux-libre-2.6.37-gnu1/arch/x86/include/asm/prom.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/include/asm/prom.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1 @@
+/* dummy prom.h; here to make linux/of.h's #includes happy */
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/include/asm/setup.h linux-libre-2.6.38-gnu1/arch/x86/include/asm/setup.h
--- linux-libre-2.6.37-gnu1/arch/x86/include/asm/setup.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/include/asm/setup.h	2011-03-14 21:20:32.000000000 -0400
@@ -53,6 +53,12 @@ extern void x86_mrst_early_setup(void);
 static inline void x86_mrst_early_setup(void) { }
 #endif
 
+#ifdef CONFIG_X86_INTEL_CE
+extern void x86_ce4100_early_setup(void);
+#else
+static inline void x86_ce4100_early_setup(void) { }
+#endif
+
 #ifndef _SETUP
 
 /*
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/include/asm/smpboot_hooks.h linux-libre-2.6.38-gnu1/arch/x86/include/asm/smpboot_hooks.h
--- linux-libre-2.6.37-gnu1/arch/x86/include/asm/smpboot_hooks.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/include/asm/smpboot_hooks.h	2011-03-14 21:20:32.000000000 -0400
@@ -34,7 +34,7 @@ static inline void smpboot_restore_warm_
 	 */
 	CMOS_WRITE(0, 0xf);
 
-	*((volatile long *)phys_to_virt(apic->trampoline_phys_low)) = 0;
+	*((volatile u32 *)phys_to_virt(apic->trampoline_phys_low)) = 0;
 }
 
 static inline void __init smpboot_setup_io_apic(void)
@@ -48,7 +48,6 @@ static inline void __init smpboot_setup_
 		setup_IO_APIC();
 	else {
 		nr_ioapics = 0;
-		localise_nmi_watchdog();
 	}
 #endif
 }
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/include/asm/smp.h linux-libre-2.6.38-gnu1/arch/x86/include/asm/smp.h
--- linux-libre-2.6.37-gnu1/arch/x86/include/asm/smp.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/include/asm/smp.h	2011-03-14 21:20:32.000000000 -0400
@@ -40,10 +40,7 @@ DECLARE_EARLY_PER_CPU(u16, x86_cpu_to_ap
 DECLARE_EARLY_PER_CPU(u16, x86_bios_cpu_apicid);
 
 /* Static state in head.S used to set up a CPU */
-extern struct {
-	void *sp;
-	unsigned short ss;
-} stack_start;
+extern unsigned long stack_start; /* Initial stack pointer address */
 
 struct smp_ops {
 	void (*smp_prepare_boot_cpu)(void);
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/include/asm/stacktrace.h linux-libre-2.6.38-gnu1/arch/x86/include/asm/stacktrace.h
--- linux-libre-2.6.37-gnu1/arch/x86/include/asm/stacktrace.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/include/asm/stacktrace.h	2011-03-14 21:20:32.000000000 -0400
@@ -7,6 +7,7 @@
 #define _ASM_X86_STACKTRACE_H
 
 #include <linux/uaccess.h>
+#include <linux/ptrace.h>
 
 extern int kstack_depth_to_print;
 
@@ -46,7 +47,7 @@ struct stacktrace_ops {
 };
 
 void dump_trace(struct task_struct *tsk, struct pt_regs *regs,
-		unsigned long *stack, unsigned long bp,
+		unsigned long *stack,
 		const struct stacktrace_ops *ops, void *data);
 
 #ifdef CONFIG_X86_32
@@ -57,13 +58,39 @@ void dump_trace(struct task_struct *tsk,
 #define get_bp(bp) asm("movq %%rbp, %0" : "=r" (bp) :)
 #endif
 
+#ifdef CONFIG_FRAME_POINTER
+static inline unsigned long
+stack_frame(struct task_struct *task, struct pt_regs *regs)
+{
+	unsigned long bp;
+
+	if (regs)
+		return regs->bp;
+
+	if (task == current) {
+		/* Grab bp right from our regs */
+		get_bp(bp);
+		return bp;
+	}
+
+	/* bp is the last reg pushed by switch_to */
+	return *(unsigned long *)task->thread.sp;
+}
+#else
+static inline unsigned long
+stack_frame(struct task_struct *task, struct pt_regs *regs)
+{
+	return 0;
+}
+#endif
+
 extern void
 show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs,
-		unsigned long *stack, unsigned long bp, char *log_lvl);
+		   unsigned long *stack, char *log_lvl);
 
 extern void
 show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs,
-		unsigned long *sp, unsigned long bp, char *log_lvl);
+		   unsigned long *sp, char *log_lvl);
 
 extern unsigned int code_bytes;
 
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/include/asm/svm.h linux-libre-2.6.38-gnu1/arch/x86/include/asm/svm.h
--- linux-libre-2.6.37-gnu1/arch/x86/include/asm/svm.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/include/asm/svm.h	2011-03-14 21:20:32.000000000 -0400
@@ -47,14 +47,13 @@ enum {
 	INTERCEPT_MONITOR,
 	INTERCEPT_MWAIT,
 	INTERCEPT_MWAIT_COND,
+	INTERCEPT_XSETBV,
 };
 
 
 struct __attribute__ ((__packed__)) vmcb_control_area {
-	u16 intercept_cr_read;
-	u16 intercept_cr_write;
-	u16 intercept_dr_read;
-	u16 intercept_dr_write;
+	u32 intercept_cr;
+	u32 intercept_dr;
 	u32 intercept_exceptions;
 	u64 intercept;
 	u8 reserved_1[42];
@@ -81,14 +80,19 @@ struct __attribute__ ((__packed__)) vmcb
 	u32 event_inj_err;
 	u64 nested_cr3;
 	u64 lbr_ctl;
-	u64 reserved_5;
+	u32 clean;
+	u32 reserved_5;
 	u64 next_rip;
-	u8 reserved_6[816];
+	u8 insn_len;
+	u8 insn_bytes[15];
+	u8 reserved_6[800];
 };
 
 
 #define TLB_CONTROL_DO_NOTHING 0
 #define TLB_CONTROL_FLUSH_ALL_ASID 1
+#define TLB_CONTROL_FLUSH_ASID 3
+#define TLB_CONTROL_FLUSH_ASID_LOCAL 7
 
 #define V_TPR_MASK 0x0f
 
@@ -204,19 +208,31 @@ struct __attribute__ ((__packed__)) vmcb
 #define SVM_SELECTOR_READ_MASK SVM_SELECTOR_WRITE_MASK
 #define SVM_SELECTOR_CODE_MASK (1 << 3)
 
-#define INTERCEPT_CR0_MASK 1
-#define INTERCEPT_CR3_MASK (1 << 3)
-#define INTERCEPT_CR4_MASK (1 << 4)
-#define INTERCEPT_CR8_MASK (1 << 8)
+#define INTERCEPT_CR0_READ	0
+#define INTERCEPT_CR3_READ	3
+#define INTERCEPT_CR4_READ	4
+#define INTERCEPT_CR8_READ	8
+#define INTERCEPT_CR0_WRITE	(16 + 0)
+#define INTERCEPT_CR3_WRITE	(16 + 3)
+#define INTERCEPT_CR4_WRITE	(16 + 4)
+#define INTERCEPT_CR8_WRITE	(16 + 8)
 
-#define INTERCEPT_DR0_MASK 1
-#define INTERCEPT_DR1_MASK (1 << 1)
-#define INTERCEPT_DR2_MASK (1 << 2)
-#define INTERCEPT_DR3_MASK (1 << 3)
-#define INTERCEPT_DR4_MASK (1 << 4)
-#define INTERCEPT_DR5_MASK (1 << 5)
-#define INTERCEPT_DR6_MASK (1 << 6)
-#define INTERCEPT_DR7_MASK (1 << 7)
+#define INTERCEPT_DR0_READ	0
+#define INTERCEPT_DR1_READ	1
+#define INTERCEPT_DR2_READ	2
+#define INTERCEPT_DR3_READ	3
+#define INTERCEPT_DR4_READ	4
+#define INTERCEPT_DR5_READ	5
+#define INTERCEPT_DR6_READ	6
+#define INTERCEPT_DR7_READ	7
+#define INTERCEPT_DR0_WRITE	(16 + 0)
+#define INTERCEPT_DR1_WRITE	(16 + 1)
+#define INTERCEPT_DR2_WRITE	(16 + 2)
+#define INTERCEPT_DR3_WRITE	(16 + 3)
+#define INTERCEPT_DR4_WRITE	(16 + 4)
+#define INTERCEPT_DR5_WRITE	(16 + 5)
+#define INTERCEPT_DR6_WRITE	(16 + 6)
+#define INTERCEPT_DR7_WRITE	(16 + 7)
 
 #define SVM_EVTINJ_VEC_MASK 0xff
 
@@ -246,6 +262,8 @@ struct __attribute__ ((__packed__)) vmcb
 #define SVM_EXITINFOSHIFT_TS_REASON_JMP 38
 #define SVM_EXITINFOSHIFT_TS_HAS_ERROR_CODE 44
 
+#define SVM_EXITINFO_REG_MASK 0x0F
+
 #define	SVM_EXIT_READ_CR0 	0x000
 #define	SVM_EXIT_READ_CR3 	0x003
 #define	SVM_EXIT_READ_CR4 	0x004
@@ -316,6 +334,7 @@ struct __attribute__ ((__packed__)) vmcb
 #define SVM_EXIT_MONITOR	0x08a
 #define SVM_EXIT_MWAIT		0x08b
 #define SVM_EXIT_MWAIT_COND	0x08c
+#define SVM_EXIT_XSETBV		0x08d
 #define SVM_EXIT_NPF  		0x400
 
 #define SVM_EXIT_ERR		-1
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/include/asm/system_64.h linux-libre-2.6.38-gnu1/arch/x86/include/asm/system_64.h
--- linux-libre-2.6.37-gnu1/arch/x86/include/asm/system_64.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/include/asm/system_64.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,22 +0,0 @@
-#ifndef _ASM_X86_SYSTEM_64_H
-#define _ASM_X86_SYSTEM_64_H
-
-#include <asm/segment.h>
-#include <asm/cmpxchg.h>
-
-
-static inline unsigned long read_cr8(void)
-{
-	unsigned long cr8;
-	asm volatile("movq %%cr8,%0" : "=r" (cr8));
-	return cr8;
-}
-
-static inline void write_cr8(unsigned long val)
-{
-	asm volatile("movq %0,%%cr8" :: "r" (val) : "memory");
-}
-
-#include <linux/irqflags.h>
-
-#endif /* _ASM_X86_SYSTEM_64_H */
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/include/asm/timer.h linux-libre-2.6.38-gnu1/arch/x86/include/asm/timer.h
--- linux-libre-2.6.37-gnu1/arch/x86/include/asm/timer.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/include/asm/timer.h	2011-03-14 21:20:32.000000000 -0400
@@ -10,12 +10,6 @@
 unsigned long long native_sched_clock(void);
 extern int recalibrate_cpu_khz(void);
 
-#if defined(CONFIG_X86_32) && defined(CONFIG_X86_IO_APIC)
-extern int timer_ack;
-#else
-# define timer_ack (0)
-#endif
-
 extern int no_timer_check;
 
 /* Accelerators for sched_clock()
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/include/asm/traps.h linux-libre-2.6.38-gnu1/arch/x86/include/asm/traps.h
--- linux-libre-2.6.37-gnu1/arch/x86/include/asm/traps.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/include/asm/traps.h	2011-03-14 21:20:32.000000000 -0400
@@ -30,6 +30,7 @@ asmlinkage void segment_not_present(void
 asmlinkage void stack_segment(void);
 asmlinkage void general_protection(void);
 asmlinkage void page_fault(void);
+asmlinkage void async_page_fault(void);
 asmlinkage void spurious_interrupt_bug(void);
 asmlinkage void coprocessor_error(void);
 asmlinkage void alignment_check(void);
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/include/asm/uv/uv_bau.h linux-libre-2.6.38-gnu1/arch/x86/include/asm/uv/uv_bau.h
--- linux-libre-2.6.37-gnu1/arch/x86/include/asm/uv/uv_bau.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/include/asm/uv/uv_bau.h	2011-03-14 21:20:32.000000000 -0400
@@ -26,20 +26,22 @@
  * BAU_SB_DESCRIPTOR_BASE register, set 1 is located at BASE + 512,
  * set 2 is at BASE + 2*512, set 3 at BASE + 3*512, and so on.
  *
- * We will use 31 sets, one for sending BAU messages from each of the 32
+ * We will use one set for sending BAU messages from each of the
  * cpu's on the uvhub.
  *
  * TLB shootdown will use the first of the 8 descriptors of each set.
  * Each of the descriptors is 64 bytes in size (8*64 = 512 bytes in a set).
  */
 
+#define MAX_CPUS_PER_UVHUB		64
+#define MAX_CPUS_PER_SOCKET		32
+#define UV_ADP_SIZE			64 /* hardware-provided max. */
+#define UV_CPUS_PER_ACT_STATUS		32 /* hardware-provided max. */
 #define UV_ITEMS_PER_DESCRIPTOR		8
 /* the 'throttle' to prevent the hardware stay-busy bug */
 #define MAX_BAU_CONCURRENT		3
-#define UV_CPUS_PER_ACT_STATUS		32
 #define UV_ACT_STATUS_MASK		0x3
 #define UV_ACT_STATUS_SIZE		2
-#define UV_ADP_SIZE			32
 #define UV_DISTRIBUTION_SIZE		256
 #define UV_SW_ACK_NPENDING		8
 #define UV_NET_ENDPOINT_INTD		0x38
@@ -100,7 +102,6 @@
  * number of destination side software ack resources
  */
 #define DEST_NUM_RESOURCES		8
-#define MAX_CPUS_PER_NODE		32
 /*
  * completion statuses for sending a TLB flush message
  */
@@ -175,7 +176,7 @@ struct bau_msg_payload {
 struct bau_msg_header {
 	unsigned int dest_subnodeid:6;	/* must be 0x10, for the LB */
 	/* bits 5:0 */
-	unsigned int base_dest_nodeid:15; /* nasid (pnode<<1) of */
+	unsigned int base_dest_nodeid:15; /* nasid of the */
 	/* bits 20:6 */			  /* first bit in uvhub map */
 	unsigned int command:8;	/* message type */
 	/* bits 28:21 */
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/include/asm/vmx.h linux-libre-2.6.38-gnu1/arch/x86/include/asm/vmx.h
--- linux-libre-2.6.37-gnu1/arch/x86/include/asm/vmx.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/include/asm/vmx.h	2011-03-14 21:20:32.000000000 -0400
@@ -66,15 +66,23 @@
 #define PIN_BASED_NMI_EXITING                   0x00000008
 #define PIN_BASED_VIRTUAL_NMIS                  0x00000020
 
+#define VM_EXIT_SAVE_DEBUG_CONTROLS             0x00000002
 #define VM_EXIT_HOST_ADDR_SPACE_SIZE            0x00000200
+#define VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL      0x00001000
 #define VM_EXIT_ACK_INTR_ON_EXIT                0x00008000
 #define VM_EXIT_SAVE_IA32_PAT			0x00040000
 #define VM_EXIT_LOAD_IA32_PAT			0x00080000
+#define VM_EXIT_SAVE_IA32_EFER                  0x00100000
+#define VM_EXIT_LOAD_IA32_EFER                  0x00200000
+#define VM_EXIT_SAVE_VMX_PREEMPTION_TIMER       0x00400000
 
+#define VM_ENTRY_LOAD_DEBUG_CONTROLS            0x00000002
 #define VM_ENTRY_IA32E_MODE                     0x00000200
 #define VM_ENTRY_SMM                            0x00000400
 #define VM_ENTRY_DEACT_DUAL_MONITOR             0x00000800
+#define VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL     0x00002000
 #define VM_ENTRY_LOAD_IA32_PAT			0x00004000
+#define VM_ENTRY_LOAD_IA32_EFER                 0x00008000
 
 /* VMCS Encodings */
 enum vmcs_field {
@@ -239,6 +247,7 @@ enum vmcs_field {
 #define EXIT_REASON_TASK_SWITCH         9
 #define EXIT_REASON_CPUID               10
 #define EXIT_REASON_HLT                 12
+#define EXIT_REASON_INVD                13
 #define EXIT_REASON_INVLPG              14
 #define EXIT_REASON_RDPMC               15
 #define EXIT_REASON_RDTSC               16
@@ -296,6 +305,12 @@ enum vmcs_field {
 #define GUEST_INTR_STATE_SMI		0x00000004
 #define GUEST_INTR_STATE_NMI		0x00000008
 
+/* GUEST_ACTIVITY_STATE flags */
+#define GUEST_ACTIVITY_ACTIVE		0
+#define GUEST_ACTIVITY_HLT		1
+#define GUEST_ACTIVITY_SHUTDOWN		2
+#define GUEST_ACTIVITY_WAIT_SIPI	3
+
 /*
  * Exit Qualifications for MOV for Control Register Access
  */
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/include/asm/xen/hypervisor.h linux-libre-2.6.38-gnu1/arch/x86/include/asm/xen/hypervisor.h
--- linux-libre-2.6.37-gnu1/arch/x86/include/asm/xen/hypervisor.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/include/asm/xen/hypervisor.h	2011-03-14 21:20:32.000000000 -0400
@@ -37,4 +37,39 @@
 extern struct shared_info *HYPERVISOR_shared_info;
 extern struct start_info *xen_start_info;
 
+#include <asm/processor.h>
+
+static inline uint32_t xen_cpuid_base(void)
+{
+	uint32_t base, eax, ebx, ecx, edx;
+	char signature[13];
+
+	for (base = 0x40000000; base < 0x40010000; base += 0x100) {
+		cpuid(base, &eax, &ebx, &ecx, &edx);
+		*(uint32_t *)(signature + 0) = ebx;
+		*(uint32_t *)(signature + 4) = ecx;
+		*(uint32_t *)(signature + 8) = edx;
+		signature[12] = 0;
+
+		if (!strcmp("XenVMMXenVMM", signature) && ((eax - base) >= 2))
+			return base;
+	}
+
+	return 0;
+}
+
+#ifdef CONFIG_XEN
+extern bool xen_hvm_need_lapic(void);
+
+static inline bool xen_x2apic_para_available(void)
+{
+	return xen_hvm_need_lapic();
+}
+#else
+static inline bool xen_x2apic_para_available(void)
+{
+	return (xen_cpuid_base() != 0);
+}
+#endif
+
 #endif /* _ASM_X86_XEN_HYPERVISOR_H */
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/include/asm/xen/page.h linux-libre-2.6.38-gnu1/arch/x86/include/asm/xen/page.h
--- linux-libre-2.6.37-gnu1/arch/x86/include/asm/xen/page.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/include/asm/xen/page.h	2011-03-14 21:20:32.000000000 -0400
@@ -42,6 +42,11 @@ extern unsigned int   machine_to_phys_or
 extern unsigned long get_phys_to_machine(unsigned long pfn);
 extern bool set_phys_to_machine(unsigned long pfn, unsigned long mfn);
 
+extern int m2p_add_override(unsigned long mfn, struct page *page);
+extern int m2p_remove_override(struct page *page);
+extern struct page *m2p_find_override(unsigned long mfn);
+extern unsigned long m2p_find_override_pfn(unsigned long mfn, unsigned long pfn);
+
 static inline unsigned long pfn_to_mfn(unsigned long pfn)
 {
 	unsigned long mfn;
@@ -72,9 +77,6 @@ static inline unsigned long mfn_to_pfn(u
 	if (xen_feature(XENFEAT_auto_translated_physmap))
 		return mfn;
 
-	if (unlikely((mfn >> machine_to_phys_order) != 0))
-		return ~0;
-
 	pfn = 0;
 	/*
 	 * The array access can fail (e.g., device space beyond end of RAM).
@@ -83,6 +85,14 @@ static inline unsigned long mfn_to_pfn(u
 	 */
 	__get_user(pfn, &machine_to_phys_mapping[mfn]);
 
+	/*
+	 * If this appears to be a foreign mfn (because the pfn
+	 * doesn't map back to the mfn), then check the local override
+	 * table to see if there's a better pfn to use.
+	 */
+	if (get_phys_to_machine(pfn) != mfn)
+		pfn = m2p_find_override_pfn(mfn, pfn);
+
 	return pfn;
 }
 
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/Kconfig linux-libre-2.6.38-gnu1/arch/x86/Kconfig
--- linux-libre-2.6.37-gnu1/arch/x86/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -51,6 +51,7 @@ config X86
 	select HAVE_KERNEL_GZIP
 	select HAVE_KERNEL_BZIP2
 	select HAVE_KERNEL_LZMA
+	select HAVE_KERNEL_XZ
 	select HAVE_KERNEL_LZO
 	select HAVE_HW_BREAKPOINT
 	select HAVE_MIXED_BREAKPOINTS_REGS
@@ -65,6 +66,7 @@ config X86
 	select HAVE_SPARSE_IRQ
 	select GENERIC_IRQ_PROBE
 	select GENERIC_PENDING_IRQ if SMP
+	select USE_GENERIC_SMP_HELPERS if SMP
 
 config INSTRUCTION_DECODER
 	def_bool (KPROBES || PERF_EVENTS)
@@ -203,10 +205,6 @@ config HAVE_INTEL_TXT
 	def_bool y
 	depends on EXPERIMENTAL && DMAR && ACPI
 
-config USE_GENERIC_SMP_HELPERS
-	def_bool y
-	depends on SMP
-
 config X86_32_SMP
 	def_bool y
 	depends on X86_32 && SMP
@@ -377,6 +375,18 @@ config X86_ELAN
 
 	  If unsure, choose "PC-compatible" instead.
 
+config X86_INTEL_CE
+	bool "CE4100 TV platform"
+	depends on PCI
+	depends on PCI_GODIRECT
+	depends on X86_32
+	depends on X86_EXTENDED_PLATFORM
+	select X86_REBOOTFIXUPS
+	---help---
+	  Select for the Intel CE media processor (CE4100) SOC.
+	  This option compiles in support for the CE4100 SOC for settop
+	  boxes and media devices.
+
 config X86_MRST
        bool "Moorestown MID platform"
 	depends on PCI
@@ -385,6 +395,10 @@ config X86_MRST
 	depends on X86_EXTENDED_PLATFORM
 	depends on X86_IO_APIC
 	select APB_TIMER
+	select I2C
+	select SPI
+	select INTEL_SCU_IPC
+	select X86_PLATFORM_DEVICES
 	---help---
 	  Moorestown is Intel's Low Power Intel Architecture (LPIA) based Moblin
 	  Internet Device(MID) platform. Moorestown consists of two chips:
@@ -466,6 +480,19 @@ config X86_ES7000
 	  Support for Unisys ES7000 systems.  Say 'Y' here if this kernel is
 	  supposed to run on an IA32-based Unisys ES7000 system.
 
+config X86_32_IRIS
+	tristate "Eurobraille/Iris poweroff module"
+	depends on X86_32
+	---help---
+	  The Iris machines from EuroBraille do not have APM or ACPI support
+	  to shut themselves down properly.  A special I/O sequence is
+	  needed to do so, which is what this module does at
+	  kernel shutdown.
+
+	  This is only for Iris machines from EuroBraille.
+
+	  If unused, say N.
+
 config SCHED_OMIT_FRAME_POINTER
 	def_bool y
 	prompt "Single-depth WCHAN output"
@@ -600,11 +627,11 @@ config APB_TIMER
          as it is off-chip. APB timers are always running regardless of CPU
          C states, they are used as per CPU clockevent device when possible.
 
-# Mark as embedded because too many people got it wrong.
+# Mark as expert because too many people got it wrong.
 # The code disables itself when not needed.
 config DMI
 	default y
-	bool "Enable DMI scanning" if EMBEDDED
+	bool "Enable DMI scanning" if EXPERT
 	---help---
 	  Enabled scanning of DMI to identify machine quirks. Say Y
 	  here unless you have verified that your setup is not
@@ -612,7 +639,7 @@ config DMI
 	  BIOS code.
 
 config GART_IOMMU
-	bool "GART IOMMU support" if EMBEDDED
+	bool "GART IOMMU support" if EXPERT
 	default y
 	select SWIOTLB
 	depends on X86_64 && PCI && AMD_NB
@@ -862,7 +889,7 @@ config X86_THERMAL_VECTOR
 	depends on X86_MCE_INTEL
 
 config VM86
-	bool "Enable VM86 support" if EMBEDDED
+	bool "Enable VM86 support" if EXPERT
 	default y
 	depends on X86_32
 	---help---
@@ -1046,7 +1073,7 @@ endchoice
 
 choice
 	depends on EXPERIMENTAL
-	prompt "Memory split" if EMBEDDED
+	prompt "Memory split" if EXPERT
 	default VMSPLIT_3G
 	depends on X86_32
 	---help---
@@ -1108,7 +1135,7 @@ config ARCH_DMA_ADDR_T_64BIT
 	def_bool X86_64 || HIGHMEM64G
 
 config DIRECT_GBPAGES
-	bool "Enable 1GB pages for kernel pagetables" if EMBEDDED
+	bool "Enable 1GB pages for kernel pagetables" if EXPERT
 	default y
 	depends on X86_64
 	---help---
@@ -1141,16 +1168,16 @@ config NUMA
 comment "NUMA (Summit) requires SMP, 64GB highmem support, ACPI"
 	depends on X86_32 && X86_SUMMIT && (!HIGHMEM64G || !ACPI)
 
-config K8_NUMA
+config AMD_NUMA
 	def_bool y
 	prompt "Old style AMD Opteron NUMA detection"
 	depends on X86_64 && NUMA && PCI
 	---help---
-	  Enable K8 NUMA node topology detection.  You should say Y here if
-	  you have a multi processor AMD K8 system. This uses an old
-	  method to read the NUMA configuration directly from the builtin
-	  Northbridge of Opteron. It is recommended to use X86_64_ACPI_NUMA
-	  instead, which also takes priority if both are compiled in.
+	  Enable AMD NUMA node topology detection.  You should say Y here if
+	  you have a multi processor AMD system. This uses an old method to
+	  read the NUMA configuration directly from the builtin Northbridge
+	  of Opteron. It is recommended to use X86_64_ACPI_NUMA instead,
+	  which also takes priority if both are compiled in.
 
 config X86_64_ACPI_NUMA
 	def_bool y
@@ -1342,7 +1369,7 @@ config MATH_EMULATION
 
 config MTRR
 	def_bool y
-	prompt "MTRR (Memory Type Range Register) support" if EMBEDDED
+	prompt "MTRR (Memory Type Range Register) support" if EXPERT
 	---help---
 	  On Intel P6 family processors (Pentium Pro, Pentium II and later)
 	  the Memory Type Range Registers (MTRRs) may be used to control
@@ -1408,7 +1435,7 @@ config MTRR_SANITIZER_SPARE_REG_NR_DEFAU
 
 config X86_PAT
 	def_bool y
-	prompt "x86 PAT support" if EMBEDDED
+	prompt "x86 PAT support" if EXPERT
 	depends on MTRR
 	---help---
 	  Use PAT attributes to setup page level cache control.
@@ -1512,7 +1539,7 @@ config KEXEC_JUMP
 	  code in physical address mode via KEXEC
 
 config PHYSICAL_START
-	hex "Physical address where the kernel is loaded" if (EMBEDDED || CRASH_DUMP)
+	hex "Physical address where the kernel is loaded" if (EXPERT || CRASH_DUMP)
 	default "0x1000000"
 	---help---
 	  This gives the physical address where the kernel is loaded.
@@ -1907,13 +1934,19 @@ config PCI_MMCONFIG
 	depends on X86_64 && PCI && ACPI
 
 config PCI_CNB20LE_QUIRK
-	bool "Read CNB20LE Host Bridge Windows"
-	depends on PCI
+	bool "Read CNB20LE Host Bridge Windows" if EXPERT
+	default n
+	depends on PCI && EXPERIMENTAL
 	help
 	  Read the PCI windows out of the CNB20LE host bridge. This allows
 	  PCI hotplug to work on systems with the CNB20LE chipset which do
 	  not have ACPI.
 
+	  There's no public spec for this chipset, and this functionality
+	  is known to be incomplete.
+
+	  You should say N unless you know you need this.
+
 config DMAR
 	bool "Support for DMA Remapping Devices (EXPERIMENTAL)"
 	depends on PCI_MSI && ACPI && EXPERIMENTAL
@@ -2035,13 +2068,14 @@ config OLPC
 	bool "One Laptop Per Child support"
 	select GPIOLIB
 	select OLPC_OPENFIRMWARE
+	depends on !X86_64 && !X86_PAE
 	---help---
 	  Add support for detecting the unique features of the OLPC
 	  XO hardware.
 
 config OLPC_XO1
 	tristate "OLPC XO-1 support"
-	depends on OLPC && PCI
+	depends on OLPC && MFD_CS5535
 	---help---
 	  Add support for non-essential features of the OLPC XO-1 laptop.
 
@@ -2049,11 +2083,17 @@ config OLPC_OPENFIRMWARE
 	bool "Support for OLPC's Open Firmware"
 	depends on !X86_64 && !X86_PAE
 	default n
+	select OF
 	help
 	  This option adds support for the implementation of Open Firmware
 	  that is used on the OLPC XO-1 Children's Machine.
 	  If unsure, say N here.
 
+config OLPC_OPENFIRMWARE_DT
+	bool
+	default y if OLPC_OPENFIRMWARE && PROC_DEVICETREE
+	select OF_PROMTREE
+
 endif # X86_32
 
 config AMD_NB
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/Kconfig.cpu linux-libre-2.6.38-gnu1/arch/x86/Kconfig.cpu
--- linux-libre-2.6.37-gnu1/arch/x86/Kconfig.cpu	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/Kconfig.cpu	2011-03-14 21:20:32.000000000 -0400
@@ -310,6 +310,9 @@ config X86_INTERNODE_CACHE_SHIFT
 config X86_CMPXCHG
 	def_bool X86_64 || (X86_32 && !M386)
 
+config CMPXCHG_LOCAL
+	def_bool X86_64 || (X86_32 && !M386)
+
 config X86_L1_CACHE_SHIFT
 	int
 	default "7" if MPENTIUM4 || MPSC
@@ -421,7 +424,7 @@ config X86_DEBUGCTLMSR
 	depends on !(MK6 || MWINCHIPC6 || MWINCHIP3D || MCYRIXIII || M586MMX || M586TSC || M586 || M486 || M386) && !UML
 
 menuconfig PROCESSOR_SELECT
-	bool "Supported processor vendors" if EMBEDDED
+	bool "Supported processor vendors" if EXPERT
 	---help---
 	  This lets you choose what x86 vendor support code your kernel
 	  will include.
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/Kconfig.debug linux-libre-2.6.38-gnu1/arch/x86/Kconfig.debug
--- linux-libre-2.6.37-gnu1/arch/x86/Kconfig.debug	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/Kconfig.debug	2011-03-14 21:20:32.000000000 -0400
@@ -31,7 +31,7 @@ config X86_VERBOSE_BOOTUP
 	  see errors. Disable this if you want silent bootup.
 
 config EARLY_PRINTK
-	bool "Early printk" if EMBEDDED
+	bool "Early printk" if EXPERT
 	default y
 	---help---
 	  Write kernel log output directly into the VGA buffer or to a serial
@@ -117,6 +117,17 @@ config DEBUG_RODATA_TEST
 	  feature as well as for the change_page_attr() infrastructure.
 	  If in doubt, say "N"
 
+config DEBUG_SET_MODULE_RONX
+	bool "Set loadable kernel module data as NX and text as RO"
+	depends on MODULES
+	---help---
+	  This option helps catch unintended modifications to loadable
+	  kernel module's text and read-only data. It also prevents execution
+	  of module data. Such protection may interfere with run-time code
+	  patching and dynamic kernel tracing - and they might also protect
+	  against certain classes of kernel exploits.
+	  If in doubt, say "N".
+
 config DEBUG_NX_TEST
 	tristate "Testcase for the NX non-executable stack feature"
 	depends on DEBUG_KERNEL && m
@@ -127,7 +138,7 @@ config DEBUG_NX_TEST
 
 config DOUBLEFAULT
 	default y
-	bool "Enable doublefault exception handler" if EMBEDDED
+	bool "Enable doublefault exception handler" if EXPERT
 	depends on X86_32
 	---help---
 	  This option allows trapping of rare doublefault exceptions that
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/kernel/acpi/boot.c linux-libre-2.6.38-gnu1/arch/x86/kernel/acpi/boot.c
--- linux-libre-2.6.37-gnu1/arch/x86/kernel/acpi/boot.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/kernel/acpi/boot.c	2011-03-14 21:20:32.000000000 -0400
@@ -72,6 +72,7 @@ u8 acpi_sci_flags __initdata;
 int acpi_sci_override_gsi __initdata;
 int acpi_skip_timer_override __initdata;
 int acpi_use_timer_override __initdata;
+int acpi_fix_pin2_polarity __initdata;
 
 #ifdef CONFIG_X86_LOCAL_APIC
 static u64 acpi_lapic_addr __initdata = APIC_DEFAULT_PHYS_BASE;
@@ -198,6 +199,11 @@ static void __cpuinit acpi_register_lapi
 {
 	unsigned int ver = 0;
 
+	if (id >= (MAX_LOCAL_APIC-1)) {
+		printk(KERN_INFO PREFIX "skipped apicid that is too big\n");
+		return;
+	}
+
 	if (!enabled) {
 		++disabled_cpus;
 		return;
@@ -410,10 +416,15 @@ acpi_parse_int_src_ovr(struct acpi_subta
 		return 0;
 	}
 
-	if (acpi_skip_timer_override &&
-	    intsrc->source_irq == 0 && intsrc->global_irq == 2) {
-		printk(PREFIX "BIOS IRQ0 pin2 override ignored.\n");
-		return 0;
+	if (intsrc->source_irq == 0 && intsrc->global_irq == 2) {
+		if (acpi_skip_timer_override) {
+			printk(PREFIX "BIOS IRQ0 pin2 override ignored.\n");
+			return 0;
+		}
+		if (acpi_fix_pin2_polarity && (intsrc->inti_flags & ACPI_MADT_POLARITY_MASK)) {
+			intsrc->inti_flags &= ~ACPI_MADT_POLARITY_MASK;
+			printk(PREFIX "BIOS IRQ0 pin2 override: forcing polarity to high active.\n");
+		}
 	}
 
 	mp_override_legacy_irq(intsrc->source_irq,
@@ -504,6 +515,7 @@ int acpi_gsi_to_irq(u32 gsi, unsigned in
 
 	return 0;
 }
+EXPORT_SYMBOL_GPL(acpi_gsi_to_irq);
 
 int acpi_isa_irq_to_gsi(unsigned isa_irq, u32 *gsi)
 {
@@ -847,18 +859,6 @@ static int __init acpi_parse_fadt(struct
  * returns 0 on success, < 0 on error
  */
 
-static void __init acpi_register_lapic_address(unsigned long address)
-{
-	mp_lapic_addr = address;
-
-	set_fixmap_nocache(FIX_APIC_BASE, address);
-	if (boot_cpu_physical_apicid == -1U) {
-		boot_cpu_physical_apicid  = read_apic_id();
-		apic_version[boot_cpu_physical_apicid] =
-			 GET_APIC_VERSION(apic_read(APIC_LVR));
-	}
-}
-
 static int __init early_acpi_parse_madt_lapic_addr_ovr(void)
 {
 	int count;
@@ -880,7 +880,7 @@ static int __init early_acpi_parse_madt_
 		return count;
 	}
 
-	acpi_register_lapic_address(acpi_lapic_addr);
+	register_lapic_address(acpi_lapic_addr);
 
 	return count;
 }
@@ -907,16 +907,16 @@ static int __init acpi_parse_madt_lapic_
 		return count;
 	}
 
-	acpi_register_lapic_address(acpi_lapic_addr);
+	register_lapic_address(acpi_lapic_addr);
 
 	count = acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_SAPIC,
-				      acpi_parse_sapic, MAX_APICS);
+				      acpi_parse_sapic, MAX_LOCAL_APIC);
 
 	if (!count) {
 		x2count = acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_X2APIC,
-						acpi_parse_x2apic, MAX_APICS);
+					acpi_parse_x2apic, MAX_LOCAL_APIC);
 		count = acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_APIC,
-					      acpi_parse_lapic, MAX_APICS);
+					acpi_parse_lapic, MAX_LOCAL_APIC);
 	}
 	if (!count && !x2count) {
 		printk(KERN_ERR PREFIX "No LAPIC entries present\n");
@@ -949,32 +949,6 @@ static int __init acpi_parse_madt_lapic_
 extern int es7000_plat;
 #endif
 
-static void assign_to_mp_irq(struct mpc_intsrc *m,
-				    struct mpc_intsrc *mp_irq)
-{
-	memcpy(mp_irq, m, sizeof(struct mpc_intsrc));
-}
-
-static int mp_irq_cmp(struct mpc_intsrc *mp_irq,
-				struct mpc_intsrc *m)
-{
-	return memcmp(mp_irq, m, sizeof(struct mpc_intsrc));
-}
-
-static void save_mp_irq(struct mpc_intsrc *m)
-{
-	int i;
-
-	for (i = 0; i < mp_irq_entries; i++) {
-		if (!mp_irq_cmp(&mp_irqs[i], m))
-			return;
-	}
-
-	assign_to_mp_irq(m, &mp_irqs[mp_irq_entries]);
-	if (++mp_irq_entries == MAX_IRQ_SOURCES)
-		panic("Max # of irq sources exceeded!!\n");
-}
-
 void __init mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger, u32 gsi)
 {
 	int ioapic;
@@ -1005,7 +979,7 @@ void __init mp_override_legacy_irq(u8 bu
 	mp_irq.dstapic = mp_ioapics[ioapic].apicid; /* APIC ID */
 	mp_irq.dstirq = pin;	/* INTIN# */
 
-	save_mp_irq(&mp_irq);
+	mp_save_irq(&mp_irq);
 
 	isa_irq_to_gsi[bus_irq] = gsi;
 }
@@ -1080,7 +1054,7 @@ void __init mp_config_acpi_legacy_irqs(v
 		mp_irq.srcbusirq = i; /* Identity mapped */
 		mp_irq.dstirq = pin;
 
-		save_mp_irq(&mp_irq);
+		mp_save_irq(&mp_irq);
 	}
 }
 
@@ -1117,7 +1091,7 @@ static int mp_config_acpi_gsi(struct dev
 	mp_irq.dstapic = mp_ioapics[ioapic].apicid;
 	mp_irq.dstirq = mp_find_ioapic_pin(ioapic, gsi);
 
-	save_mp_irq(&mp_irq);
+	mp_save_irq(&mp_irq);
 #endif
 	return 0;
 }
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/kernel/acpi/sleep.c linux-libre-2.6.38-gnu1/arch/x86/kernel/acpi/sleep.c
--- linux-libre-2.6.37-gnu1/arch/x86/kernel/acpi/sleep.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/kernel/acpi/sleep.c	2011-03-14 21:20:32.000000000 -0400
@@ -12,10 +12,8 @@
 #include <linux/cpumask.h>
 #include <asm/segment.h>
 #include <asm/desc.h>
-
-#ifdef CONFIG_X86_32
 #include <asm/pgtable.h>
-#endif
+#include <asm/cacheflush.h>
 
 #include "realmode/wakeup.h"
 #include "sleep.h"
@@ -100,7 +98,7 @@ int acpi_save_state_mem(void)
 #else /* CONFIG_64BIT */
 	header->trampoline_segment = setup_trampoline() >> 4;
 #ifdef CONFIG_SMP
-	stack_start.sp = temp_stack + sizeof(temp_stack);
+	stack_start = (unsigned long)temp_stack + sizeof(temp_stack);
 	early_gdt_descr.address =
 			(unsigned long)get_cpu_gdt_table(smp_processor_id());
 	initial_gs = per_cpu_offset(smp_processor_id());
@@ -149,6 +147,15 @@ void __init acpi_reserve_wakeup_memory(v
 	memblock_x86_reserve_range(mem, mem + WAKEUP_SIZE, "ACPI WAKEUP");
 }
 
+int __init acpi_configure_wakeup_memory(void)
+{
+	if (acpi_realmode)
+		set_memory_x(acpi_realmode, WAKEUP_SIZE >> PAGE_SHIFT);
+
+	return 0;
+}
+arch_initcall(acpi_configure_wakeup_memory);
+
 
 static int __init acpi_sleep_setup(char *str)
 {
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/kernel/alternative.c linux-libre-2.6.38-gnu1/arch/x86/kernel/alternative.c
--- linux-libre-2.6.37-gnu1/arch/x86/kernel/alternative.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/kernel/alternative.c	2011-03-14 21:20:32.000000000 -0400
@@ -353,6 +353,7 @@ void __init_or_module alternatives_smp_m
 	mutex_unlock(&smp_alt);
 }
 
+bool skip_smp_alternatives;
 void alternatives_smp_switch(int smp)
 {
 	struct smp_alt_module *mod;
@@ -368,7 +369,7 @@ void alternatives_smp_switch(int smp)
 	printk("lockdep: fixing up alternatives.\n");
 #endif
 
-	if (noreplace_smp || smp_alt_once)
+	if (noreplace_smp || smp_alt_once || skip_smp_alternatives)
 		return;
 	BUG_ON(!smp && (num_online_cpus() > 1));
 
@@ -591,17 +592,21 @@ static atomic_t stop_machine_first;
 static int wrote_text;
 
 struct text_poke_params {
-	void *addr;
-	const void *opcode;
-	size_t len;
+	struct text_poke_param *params;
+	int nparams;
 };
 
 static int __kprobes stop_machine_text_poke(void *data)
 {
 	struct text_poke_params *tpp = data;
+	struct text_poke_param *p;
+	int i;
 
 	if (atomic_dec_and_test(&stop_machine_first)) {
-		text_poke(tpp->addr, tpp->opcode, tpp->len);
+		for (i = 0; i < tpp->nparams; i++) {
+			p = &tpp->params[i];
+			text_poke(p->addr, p->opcode, p->len);
+		}
 		smp_wmb();	/* Make sure other cpus see that this has run */
 		wrote_text = 1;
 	} else {
@@ -610,8 +615,12 @@ static int __kprobes stop_machine_text_p
 		smp_mb();	/* Load wrote_text before following execution */
 	}
 
-	flush_icache_range((unsigned long)tpp->addr,
-			   (unsigned long)tpp->addr + tpp->len);
+	for (i = 0; i < tpp->nparams; i++) {
+		p = &tpp->params[i];
+		flush_icache_range((unsigned long)p->addr,
+				   (unsigned long)p->addr + p->len);
+	}
+
 	return 0;
 }
 
@@ -631,10 +640,13 @@ static int __kprobes stop_machine_text_p
 void *__kprobes text_poke_smp(void *addr, const void *opcode, size_t len)
 {
 	struct text_poke_params tpp;
+	struct text_poke_param p;
 
-	tpp.addr = addr;
-	tpp.opcode = opcode;
-	tpp.len = len;
+	p.addr = addr;
+	p.opcode = opcode;
+	p.len = len;
+	tpp.params = &p;
+	tpp.nparams = 1;
 	atomic_set(&stop_machine_first, 1);
 	wrote_text = 0;
 	/* Use __stop_machine() because the caller already got online_cpus. */
@@ -642,6 +654,26 @@ void *__kprobes text_poke_smp(void *addr
 	return addr;
 }
 
+/**
+ * text_poke_smp_batch - Update instructions on a live kernel on SMP
+ * @params: an array of text_poke parameters
+ * @n: the number of elements in params.
+ *
+ * Modify multi-byte instruction by using stop_machine() on SMP. Since the
+ * stop_machine() is heavy task, it is better to aggregate text_poke requests
+ * and do it once if possible.
+ *
+ * Note: Must be called under get_online_cpus() and text_mutex.
+ */
+void __kprobes text_poke_smp_batch(struct text_poke_param *params, int n)
+{
+	struct text_poke_params tpp = {.params = params, .nparams = n};
+
+	atomic_set(&stop_machine_first, 1);
+	wrote_text = 0;
+	__stop_machine(stop_machine_text_poke, (void *)&tpp, NULL);
+}
+
 #if defined(CONFIG_DYNAMIC_FTRACE) || defined(HAVE_JUMP_LABEL)
 
 #ifdef CONFIG_X86_64
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/kernel/amd_iommu.c linux-libre-2.6.38-gnu1/arch/x86/kernel/amd_iommu.c
--- linux-libre-2.6.37-gnu1/arch/x86/kernel/amd_iommu.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/kernel/amd_iommu.c	2011-03-14 21:20:32.000000000 -0400
@@ -1086,7 +1086,7 @@ static int alloc_new_range(struct dma_op
 
 	dma_dom->aperture_size += APERTURE_RANGE_SIZE;
 
-	/* Intialize the exclusion range if necessary */
+	/* Initialize the exclusion range if necessary */
 	for_each_iommu(iommu) {
 		if (iommu->exclusion_start &&
 		    iommu->exclusion_start >= dma_dom->aperture[index]->offset
@@ -1353,7 +1353,7 @@ static void dma_ops_domain_free(struct d
 
 /*
  * Allocates a new protection domain usable for the dma_ops functions.
- * It also intializes the page table and the address allocator data
+ * It also initializes the page table and the address allocator data
  * structures required for the dma_ops interface
  */
 static struct dma_ops_domain *dma_ops_domain_alloc(void)
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/kernel/amd_nb.c linux-libre-2.6.38-gnu1/arch/x86/kernel/amd_nb.c
--- linux-libre-2.6.37-gnu1/arch/x86/kernel/amd_nb.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/kernel/amd_nb.c	2011-03-14 21:20:32.000000000 -0400
@@ -12,95 +12,123 @@
 
 static u32 *flush_words;
 
-struct pci_device_id k8_nb_ids[] = {
+struct pci_device_id amd_nb_misc_ids[] = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_K8_NB_MISC) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_10H_NB_MISC) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_15H_NB_MISC) },
 	{}
 };
-EXPORT_SYMBOL(k8_nb_ids);
+EXPORT_SYMBOL(amd_nb_misc_ids);
 
-struct k8_northbridge_info k8_northbridges;
-EXPORT_SYMBOL(k8_northbridges);
+const struct amd_nb_bus_dev_range amd_nb_bus_dev_ranges[] __initconst = {
+	{ 0x00, 0x18, 0x20 },
+	{ 0xff, 0x00, 0x20 },
+	{ 0xfe, 0x00, 0x20 },
+	{ }
+};
 
-static struct pci_dev *next_k8_northbridge(struct pci_dev *dev)
+struct amd_northbridge_info amd_northbridges;
+EXPORT_SYMBOL(amd_northbridges);
+
+static struct pci_dev *next_northbridge(struct pci_dev *dev,
+					struct pci_device_id *ids)
 {
 	do {
 		dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev);
 		if (!dev)
 			break;
-	} while (!pci_match_id(&k8_nb_ids[0], dev));
+	} while (!pci_match_id(ids, dev));
 	return dev;
 }
 
-int cache_k8_northbridges(void)
+int amd_cache_northbridges(void)
 {
-	int i;
-	struct pci_dev *dev;
+	int i = 0;
+	struct amd_northbridge *nb;
+	struct pci_dev *misc;
 
-	if (k8_northbridges.num)
+	if (amd_nb_num())
 		return 0;
 
-	dev = NULL;
-	while ((dev = next_k8_northbridge(dev)) != NULL)
-		k8_northbridges.num++;
+	misc = NULL;
+	while ((misc = next_northbridge(misc, amd_nb_misc_ids)) != NULL)
+		i++;
 
-	/* some CPU families (e.g. family 0x11) do not support GART */
-	if (boot_cpu_data.x86 == 0xf || boot_cpu_data.x86 == 0x10 ||
-	    boot_cpu_data.x86 == 0x15)
-		k8_northbridges.gart_supported = 1;
+	if (i == 0)
+		return 0;
 
-	k8_northbridges.nb_misc = kmalloc((k8_northbridges.num + 1) *
-					  sizeof(void *), GFP_KERNEL);
-	if (!k8_northbridges.nb_misc)
+	nb = kzalloc(i * sizeof(struct amd_northbridge), GFP_KERNEL);
+	if (!nb)
 		return -ENOMEM;
 
-	if (!k8_northbridges.num) {
-		k8_northbridges.nb_misc[0] = NULL;
-		return 0;
-	}
+	amd_northbridges.nb = nb;
+	amd_northbridges.num = i;
 
-	if (k8_northbridges.gart_supported) {
-		flush_words = kmalloc(k8_northbridges.num * sizeof(u32),
-				      GFP_KERNEL);
-		if (!flush_words) {
-			kfree(k8_northbridges.nb_misc);
-			return -ENOMEM;
-		}
-	}
+	misc = NULL;
+	for (i = 0; i != amd_nb_num(); i++) {
+		node_to_amd_nb(i)->misc = misc =
+			next_northbridge(misc, amd_nb_misc_ids);
+        }
+
+	/* some CPU families (e.g. family 0x11) do not support GART */
+	if (boot_cpu_data.x86 == 0xf || boot_cpu_data.x86 == 0x10 ||
+	    boot_cpu_data.x86 == 0x15)
+		amd_northbridges.flags |= AMD_NB_GART;
+
+	/*
+	 * Some CPU families support L3 Cache Index Disable. There are some
+	 * limitations because of E382 and E388 on family 0x10.
+	 */
+	if (boot_cpu_data.x86 == 0x10 &&
+	    boot_cpu_data.x86_model >= 0x8 &&
+	    (boot_cpu_data.x86_model > 0x9 ||
+	     boot_cpu_data.x86_mask >= 0x1))
+		amd_northbridges.flags |= AMD_NB_L3_INDEX_DISABLE;
 
-	dev = NULL;
-	i = 0;
-	while ((dev = next_k8_northbridge(dev)) != NULL) {
-		k8_northbridges.nb_misc[i] = dev;
-		if (k8_northbridges.gart_supported)
-			pci_read_config_dword(dev, 0x9c, &flush_words[i++]);
-	}
-	k8_northbridges.nb_misc[i] = NULL;
 	return 0;
 }
-EXPORT_SYMBOL_GPL(cache_k8_northbridges);
+EXPORT_SYMBOL_GPL(amd_cache_northbridges);
 
 /* Ignores subdevice/subvendor but as far as I can figure out
    they're useless anyways */
-int __init early_is_k8_nb(u32 device)
+int __init early_is_amd_nb(u32 device)
 {
 	struct pci_device_id *id;
 	u32 vendor = device & 0xffff;
 	device >>= 16;
-	for (id = k8_nb_ids; id->vendor; id++)
+	for (id = amd_nb_misc_ids; id->vendor; id++)
 		if (vendor == id->vendor && device == id->device)
 			return 1;
 	return 0;
 }
 
-void k8_flush_garts(void)
+int amd_cache_gart(void)
+{
+       int i;
+
+       if (!amd_nb_has_feature(AMD_NB_GART))
+               return 0;
+
+       flush_words = kmalloc(amd_nb_num() * sizeof(u32), GFP_KERNEL);
+       if (!flush_words) {
+               amd_northbridges.flags &= ~AMD_NB_GART;
+               return -ENOMEM;
+       }
+
+       for (i = 0; i != amd_nb_num(); i++)
+               pci_read_config_dword(node_to_amd_nb(i)->misc, 0x9c,
+                                     &flush_words[i]);
+
+       return 0;
+}
+
+void amd_flush_garts(void)
 {
 	int flushed, i;
 	unsigned long flags;
 	static DEFINE_SPINLOCK(gart_lock);
 
-	if (!k8_northbridges.gart_supported)
+	if (!amd_nb_has_feature(AMD_NB_GART))
 		return;
 
 	/* Avoid races between AGP and IOMMU. In theory it's not needed
@@ -109,16 +137,16 @@ void k8_flush_garts(void)
 	   that it doesn't matter to serialize more. -AK */
 	spin_lock_irqsave(&gart_lock, flags);
 	flushed = 0;
-	for (i = 0; i < k8_northbridges.num; i++) {
-		pci_write_config_dword(k8_northbridges.nb_misc[i], 0x9c,
-				       flush_words[i]|1);
+	for (i = 0; i < amd_nb_num(); i++) {
+		pci_write_config_dword(node_to_amd_nb(i)->misc, 0x9c,
+				       flush_words[i] | 1);
 		flushed++;
 	}
-	for (i = 0; i < k8_northbridges.num; i++) {
+	for (i = 0; i < amd_nb_num(); i++) {
 		u32 w;
 		/* Make sure the hardware actually executed the flush*/
 		for (;;) {
-			pci_read_config_dword(k8_northbridges.nb_misc[i],
+			pci_read_config_dword(node_to_amd_nb(i)->misc,
 					      0x9c, &w);
 			if (!(w & 1))
 				break;
@@ -129,19 +157,23 @@ void k8_flush_garts(void)
 	if (!flushed)
 		printk("nothing to flush?\n");
 }
-EXPORT_SYMBOL_GPL(k8_flush_garts);
+EXPORT_SYMBOL_GPL(amd_flush_garts);
 
-static __init int init_k8_nbs(void)
+static __init int init_amd_nbs(void)
 {
 	int err = 0;
 
-	err = cache_k8_northbridges();
+	err = amd_cache_northbridges();
 
 	if (err < 0)
-		printk(KERN_NOTICE "K8 NB: Cannot enumerate AMD northbridges.\n");
+		printk(KERN_NOTICE "AMD NB: Cannot enumerate AMD northbridges.\n");
+
+	if (amd_cache_gart() < 0)
+		printk(KERN_NOTICE "AMD NB: Cannot initialize GART flush words, "
+		       "GART support disabled.\n");
 
 	return err;
 }
 
 /* This has to go after the PCI subsystem */
-fs_initcall(init_k8_nbs);
+fs_initcall(init_amd_nbs);
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/kernel/apb_timer.c linux-libre-2.6.38-gnu1/arch/x86/kernel/apb_timer.c
--- linux-libre-2.6.37-gnu1/arch/x86/kernel/apb_timer.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/kernel/apb_timer.c	2011-03-14 21:20:32.000000000 -0400
@@ -284,7 +284,7 @@ static int __init apbt_clockevent_regist
 	memcpy(&adev->evt, &apbt_clockevent, sizeof(struct clock_event_device));
 
 	if (mrst_timer_options == MRST_TIMER_LAPIC_APBT) {
-		apbt_clockevent.rating = APBT_CLOCKEVENT_RATING - 100;
+		adev->evt.rating = APBT_CLOCKEVENT_RATING - 100;
 		global_clock_event = &adev->evt;
 		printk(KERN_DEBUG "%s clockevent registered as global\n",
 		       global_clock_event->name);
@@ -313,13 +313,16 @@ static void apbt_setup_irq(struct apbt_d
 	if (adev->irq == 0)
 		return;
 
+	irq_modify_status(adev->irq, 0, IRQ_MOVE_PCNTXT);
+	irq_set_affinity(adev->irq, cpumask_of(adev->cpu));
+	/* APB timer irqs are set up as mp_irqs, timer is edge type */
+	__set_irq_handler(adev->irq, handle_edge_irq, 0, "edge");
+
 	if (system_state == SYSTEM_BOOTING) {
-		irq_modify_status(adev->irq, 0, IRQ_MOVE_PCNTXT);
-		/* APB timer irqs are set up as mp_irqs, timer is edge type */
-		__set_irq_handler(adev->irq, handle_edge_irq, 0, "edge");
 		if (request_irq(adev->irq, apbt_interrupt_handler,
-				IRQF_TIMER | IRQF_DISABLED | IRQF_NOBALANCING,
-				adev->name, adev)) {
+					IRQF_TIMER | IRQF_DISABLED |
+					IRQF_NOBALANCING,
+					adev->name, adev)) {
 			printk(KERN_ERR "Failed request IRQ for APBT%d\n",
 			       adev->num);
 		}
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/kernel/aperture_64.c linux-libre-2.6.38-gnu1/arch/x86/kernel/aperture_64.c
--- linux-libre-2.6.37-gnu1/arch/x86/kernel/aperture_64.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/kernel/aperture_64.c	2011-03-14 21:20:32.000000000 -0400
@@ -39,18 +39,6 @@ int fallback_aper_force __initdata;
 
 int fix_aperture __initdata = 1;
 
-struct bus_dev_range {
-	int bus;
-	int dev_base;
-	int dev_limit;
-};
-
-static struct bus_dev_range bus_dev_ranges[] __initdata = {
-	{ 0x00, 0x18, 0x20},
-	{ 0xff, 0x00, 0x20},
-	{ 0xfe, 0x00, 0x20}
-};
-
 static struct resource gart_resource = {
 	.name	= "GART",
 	.flags	= IORESOURCE_MEM,
@@ -206,7 +194,7 @@ static u32 __init read_agp(int bus, int
  * Do an PCI bus scan by hand because we're running before the PCI
  * subsystem.
  *
- * All K8 AGP bridges are AGPv3 compliant, so we can do this scan
+ * All AMD AGP bridges are AGPv3 compliant, so we can do this scan
  * generically. It's probably overkill to always scan all slots because
  * the AGP bridges should be always an own bus on the HT hierarchy,
  * but do it here for future safety.
@@ -294,16 +282,16 @@ void __init early_gart_iommu_check(void)
 	search_agp_bridge(&agp_aper_order, &valid_agp);
 
 	fix = 0;
-	for (i = 0; i < ARRAY_SIZE(bus_dev_ranges); i++) {
+	for (i = 0; amd_nb_bus_dev_ranges[i].dev_limit; i++) {
 		int bus;
 		int dev_base, dev_limit;
 
-		bus = bus_dev_ranges[i].bus;
-		dev_base = bus_dev_ranges[i].dev_base;
-		dev_limit = bus_dev_ranges[i].dev_limit;
+		bus = amd_nb_bus_dev_ranges[i].bus;
+		dev_base = amd_nb_bus_dev_ranges[i].dev_base;
+		dev_limit = amd_nb_bus_dev_ranges[i].dev_limit;
 
 		for (slot = dev_base; slot < dev_limit; slot++) {
-			if (!early_is_k8_nb(read_pci_config(bus, slot, 3, 0x00)))
+			if (!early_is_amd_nb(read_pci_config(bus, slot, 3, 0x00)))
 				continue;
 
 			ctl = read_pci_config(bus, slot, 3, AMD64_GARTAPERTURECTL);
@@ -349,16 +337,16 @@ void __init early_gart_iommu_check(void)
 		return;
 
 	/* disable them all at first */
-	for (i = 0; i < ARRAY_SIZE(bus_dev_ranges); i++) {
+	for (i = 0; i < amd_nb_bus_dev_ranges[i].dev_limit; i++) {
 		int bus;
 		int dev_base, dev_limit;
 
-		bus = bus_dev_ranges[i].bus;
-		dev_base = bus_dev_ranges[i].dev_base;
-		dev_limit = bus_dev_ranges[i].dev_limit;
+		bus = amd_nb_bus_dev_ranges[i].bus;
+		dev_base = amd_nb_bus_dev_ranges[i].dev_base;
+		dev_limit = amd_nb_bus_dev_ranges[i].dev_limit;
 
 		for (slot = dev_base; slot < dev_limit; slot++) {
-			if (!early_is_k8_nb(read_pci_config(bus, slot, 3, 0x00)))
+			if (!early_is_amd_nb(read_pci_config(bus, slot, 3, 0x00)))
 				continue;
 
 			ctl = read_pci_config(bus, slot, 3, AMD64_GARTAPERTURECTL);
@@ -390,17 +378,17 @@ int __init gart_iommu_hole_init(void)
 
 	fix = 0;
 	node = 0;
-	for (i = 0; i < ARRAY_SIZE(bus_dev_ranges); i++) {
+	for (i = 0; i < amd_nb_bus_dev_ranges[i].dev_limit; i++) {
 		int bus;
 		int dev_base, dev_limit;
 		u32 ctl;
 
-		bus = bus_dev_ranges[i].bus;
-		dev_base = bus_dev_ranges[i].dev_base;
-		dev_limit = bus_dev_ranges[i].dev_limit;
+		bus = amd_nb_bus_dev_ranges[i].bus;
+		dev_base = amd_nb_bus_dev_ranges[i].dev_base;
+		dev_limit = amd_nb_bus_dev_ranges[i].dev_limit;
 
 		for (slot = dev_base; slot < dev_limit; slot++) {
-			if (!early_is_k8_nb(read_pci_config(bus, slot, 3, 0x00)))
+			if (!early_is_amd_nb(read_pci_config(bus, slot, 3, 0x00)))
 				continue;
 
 			iommu_detected = 1;
@@ -505,7 +493,7 @@ out:
 	}
 
 	/* Fix up the north bridges */
-	for (i = 0; i < ARRAY_SIZE(bus_dev_ranges); i++) {
+	for (i = 0; i < amd_nb_bus_dev_ranges[i].dev_limit; i++) {
 		int bus, dev_base, dev_limit;
 
 		/*
@@ -514,11 +502,11 @@ out:
 		 */
 		u32 ctl = DISTLBWALKPRB | aper_order << 1;
 
-		bus = bus_dev_ranges[i].bus;
-		dev_base = bus_dev_ranges[i].dev_base;
-		dev_limit = bus_dev_ranges[i].dev_limit;
+		bus = amd_nb_bus_dev_ranges[i].bus;
+		dev_base = amd_nb_bus_dev_ranges[i].dev_base;
+		dev_limit = amd_nb_bus_dev_ranges[i].dev_limit;
 		for (slot = dev_base; slot < dev_limit; slot++) {
-			if (!early_is_k8_nb(read_pci_config(bus, slot, 3, 0x00)))
+			if (!early_is_amd_nb(read_pci_config(bus, slot, 3, 0x00)))
 				continue;
 
 			write_pci_config(bus, slot, 3, AMD64_GARTAPERTURECTL, ctl);
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/kernel/apic/apic.c linux-libre-2.6.38-gnu1/arch/x86/kernel/apic/apic.c
--- linux-libre-2.6.37-gnu1/arch/x86/kernel/apic/apic.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/kernel/apic/apic.c	2011-03-14 21:20:32.000000000 -0400
@@ -31,7 +31,6 @@
 #include <linux/init.h>
 #include <linux/cpu.h>
 #include <linux/dmi.h>
-#include <linux/nmi.h>
 #include <linux/smp.h>
 #include <linux/mm.h>
 
@@ -50,8 +49,8 @@
 #include <asm/mtrr.h>
 #include <asm/smp.h>
 #include <asm/mce.h>
-#include <asm/kvm_para.h>
 #include <asm/tsc.h>
+#include <asm/hypervisor.h>
 
 unsigned int num_processors;
 
@@ -432,17 +431,18 @@ int setup_APIC_eilvt(u8 offset, u8 vecto
 	reserved = reserve_eilvt_offset(offset, new);
 
 	if (reserved != new) {
-		pr_err(FW_BUG "cpu %d, try to setup vector 0x%x, but "
-		       "vector 0x%x was already reserved by another core, "
-		       "APIC%lX=0x%x\n",
-		       smp_processor_id(), new, reserved, reg, old);
+		pr_err(FW_BUG "cpu %d, try to use APIC%lX (LVT offset %d) for "
+		       "vector 0x%x, but the register is already in use for "
+		       "vector 0x%x on another cpu\n",
+		       smp_processor_id(), reg, offset, new, reserved);
 		return -EINVAL;
 	}
 
 	if (!eilvt_entry_is_changeable(old, new)) {
-		pr_err(FW_BUG "cpu %d, try to setup vector 0x%x but "
-		       "register already in use, APIC%lX=0x%x\n",
-		       smp_processor_id(), new, reg, old);
+		pr_err(FW_BUG "cpu %d, try to use APIC%lX (LVT offset %d) for "
+		       "vector 0x%x, but the register is already in use for "
+		       "vector 0x%x on this cpu\n",
+		       smp_processor_id(), reg, offset, new, old);
 		return -EBUSY;
 	}
 
@@ -516,7 +516,7 @@ static void __cpuinit setup_APIC_timer(v
 {
 	struct clock_event_device *levt = &__get_cpu_var(lapic_events);
 
-	if (cpu_has(&current_cpu_data, X86_FEATURE_ARAT)) {
+	if (cpu_has(__this_cpu_ptr(&cpu_info), X86_FEATURE_ARAT)) {
 		lapic_clockevent.features &= ~CLOCK_EVT_FEAT_C3STOP;
 		/* Make LAPIC timer preferrable over percpu HPET */
 		lapic_clockevent.rating = 150;
@@ -684,7 +684,7 @@ static int __init calibrate_APIC_clock(v
 	lapic_clockevent.mult = div_sc(delta, TICK_NSEC * LAPIC_CAL_LOOPS,
 				       lapic_clockevent.shift);
 	lapic_clockevent.max_delta_ns =
-		clockevent_delta2ns(0x7FFFFF, &lapic_clockevent);
+		clockevent_delta2ns(0x7FFFFFFF, &lapic_clockevent);
 	lapic_clockevent.min_delta_ns =
 		clockevent_delta2ns(0xF, &lapic_clockevent);
 
@@ -799,11 +799,7 @@ void __init setup_boot_APIC_clock(void)
 	 * PIT/HPET going.  Otherwise register lapic as a dummy
 	 * device.
 	 */
-	if (nmi_watchdog != NMI_IO_APIC)
-		lapic_clockevent.features &= ~CLOCK_EVT_FEAT_DUMMY;
-	else
-		pr_warning("APIC timer registered as dummy,"
-			" due to nmi_watchdog=%d!\n", nmi_watchdog);
+	lapic_clockevent.features &= ~CLOCK_EVT_FEAT_DUMMY;
 
 	/* Setup the lapic or request the broadcast */
 	setup_APIC_timer();
@@ -1195,12 +1191,15 @@ static void __cpuinit lapic_setup_esr(vo
 			oldvalue, value);
 }
 
-
 /**
  * setup_local_APIC - setup the local APIC
+ *
+ * Used to setup local APIC while initializing BSP or bringin up APs.
+ * Always called with preemption disabled.
  */
 void __cpuinit setup_local_APIC(void)
 {
+	int cpu = smp_processor_id();
 	unsigned int value, queued;
 	int i, j, acked = 0;
 	unsigned long long tsc = 0, ntsc;
@@ -1225,8 +1224,6 @@ void __cpuinit setup_local_APIC(void)
 #endif
 	perf_events_lapic_init();
 
-	preempt_disable();
-
 	/*
 	 * Double-check whether this APIC is really registered.
 	 * This is meaningless in clustered apic mode, so we skip it.
@@ -1342,21 +1339,19 @@ void __cpuinit setup_local_APIC(void)
 	 * TODO: set up through-local-APIC from through-I/O-APIC? --macro
 	 */
 	value = apic_read(APIC_LVT0) & APIC_LVT_MASKED;
-	if (!smp_processor_id() && (pic_mode || !value)) {
+	if (!cpu && (pic_mode || !value)) {
 		value = APIC_DM_EXTINT;
-		apic_printk(APIC_VERBOSE, "enabled ExtINT on CPU#%d\n",
-				smp_processor_id());
+		apic_printk(APIC_VERBOSE, "enabled ExtINT on CPU#%d\n", cpu);
 	} else {
 		value = APIC_DM_EXTINT | APIC_LVT_MASKED;
-		apic_printk(APIC_VERBOSE, "masked ExtINT on CPU#%d\n",
-				smp_processor_id());
+		apic_printk(APIC_VERBOSE, "masked ExtINT on CPU#%d\n", cpu);
 	}
 	apic_write(APIC_LVT0, value);
 
 	/*
 	 * only the BP should see the LINT1 NMI signal, obviously.
 	 */
-	if (!smp_processor_id())
+	if (!cpu)
 		value = APIC_DM_NMI;
 	else
 		value = APIC_DM_NMI | APIC_LVT_MASKED;
@@ -1364,11 +1359,9 @@ void __cpuinit setup_local_APIC(void)
 		value |= APIC_LVT_LEVEL_TRIGGER;
 	apic_write(APIC_LVT1, value);
 
-	preempt_enable();
-
 #ifdef CONFIG_X86_MCE_INTEL
 	/* Recheck CMCI information after local APIC is up on CPU #0 */
-	if (smp_processor_id() == 0)
+	if (!cpu)
 		cmci_recheck();
 #endif
 }
@@ -1387,14 +1380,18 @@ void __cpuinit end_local_APIC_setup(void
 	}
 #endif
 
-	setup_apic_nmi_watchdog(NULL);
 	apic_pm_activate();
+}
+
+void __init bsp_end_local_APIC_setup(void)
+{
+	end_local_APIC_setup();
 
 	/*
 	 * Now that local APIC setup is completed for BP, configure the fault
 	 * handling for interrupt remapping.
 	 */
-	if (!smp_processor_id() && intr_remapping_enabled)
+	if (intr_remapping_enabled)
 		enable_drhd_fault_handling();
 
 }
@@ -1484,7 +1481,8 @@ void __init enable_IR_x2apic(void)
 		/* IR is required if there is APIC ID > 255 even when running
 		 * under KVM
 		 */
-		if (max_physical_apicid > 255 || !kvm_para_available())
+		if (max_physical_apicid > 255 ||
+		    !hypervisor_x2apic_available())
 			goto nox2apic;
 		/*
 		 * without IR all CPUs can be addressed by IOAPIC/MSI
@@ -1538,13 +1536,60 @@ static int __init detect_init_APIC(void)
 	return 0;
 }
 #else
+
+static int apic_verify(void)
+{
+	u32 features, h, l;
+
+	/*
+	 * The APIC feature bit should now be enabled
+	 * in `cpuid'
+	 */
+	features = cpuid_edx(1);
+	if (!(features & (1 << X86_FEATURE_APIC))) {
+		pr_warning("Could not enable APIC!\n");
+		return -1;
+	}
+	set_cpu_cap(&boot_cpu_data, X86_FEATURE_APIC);
+	mp_lapic_addr = APIC_DEFAULT_PHYS_BASE;
+
+	/* The BIOS may have set up the APIC at some other address */
+	rdmsr(MSR_IA32_APICBASE, l, h);
+	if (l & MSR_IA32_APICBASE_ENABLE)
+		mp_lapic_addr = l & MSR_IA32_APICBASE_BASE;
+
+	pr_info("Found and enabled local APIC!\n");
+	return 0;
+}
+
+int apic_force_enable(void)
+{
+	u32 h, l;
+
+	if (disable_apic)
+		return -1;
+
+	/*
+	 * Some BIOSes disable the local APIC in the APIC_BASE
+	 * MSR. This can only be done in software for Intel P6 or later
+	 * and AMD K7 (Model > 1) or later.
+	 */
+	rdmsr(MSR_IA32_APICBASE, l, h);
+	if (!(l & MSR_IA32_APICBASE_ENABLE)) {
+		pr_info("Local APIC disabled by BIOS -- reenabling.\n");
+		l &= ~MSR_IA32_APICBASE_BASE;
+		l |= MSR_IA32_APICBASE_ENABLE | APIC_DEFAULT_PHYS_BASE;
+		wrmsr(MSR_IA32_APICBASE, l, h);
+		enabled_via_apicbase = 1;
+	}
+	return apic_verify();
+}
+
 /*
  * Detect and initialize APIC
  */
 static int __init detect_init_APIC(void)
 {
-	u32 h, l, features;
-
 	/* Disabled by kernel option? */
 	if (disable_apic)
 		return -1;
@@ -1574,38 +1619,12 @@ static int __init detect_init_APIC(void)
 				"you can enable it with \"lapic\"\n");
 			return -1;
 		}
-		/*
-		 * Some BIOSes disable the local APIC in the APIC_BASE
-		 * MSR. This can only be done in software for Intel P6 or later
-		 * and AMD K7 (Model > 1) or later.
-		 */
-		rdmsr(MSR_IA32_APICBASE, l, h);
-		if (!(l & MSR_IA32_APICBASE_ENABLE)) {
-			pr_info("Local APIC disabled by BIOS -- reenabling.\n");
-			l &= ~MSR_IA32_APICBASE_BASE;
-			l |= MSR_IA32_APICBASE_ENABLE | APIC_DEFAULT_PHYS_BASE;
-			wrmsr(MSR_IA32_APICBASE, l, h);
-			enabled_via_apicbase = 1;
-		}
-	}
-	/*
-	 * The APIC feature bit should now be enabled
-	 * in `cpuid'
-	 */
-	features = cpuid_edx(1);
-	if (!(features & (1 << X86_FEATURE_APIC))) {
-		pr_warning("Could not enable APIC!\n");
-		return -1;
+		if (apic_force_enable())
+			return -1;
+	} else {
+		if (apic_verify())
+			return -1;
 	}
-	set_cpu_cap(&boot_cpu_data, X86_FEATURE_APIC);
-	mp_lapic_addr = APIC_DEFAULT_PHYS_BASE;
-
-	/* The BIOS may have set up the APIC at some other address */
-	rdmsr(MSR_IA32_APICBASE, l, h);
-	if (l & MSR_IA32_APICBASE_ENABLE)
-		mp_lapic_addr = l & MSR_IA32_APICBASE_BASE;
-
-	pr_info("Found and enabled local APIC!\n");
 
 	apic_pm_activate();
 
@@ -1617,28 +1636,6 @@ no_apic:
 }
 #endif
 
-#ifdef CONFIG_X86_64
-void __init early_init_lapic_mapping(void)
-{
-	/*
-	 * If no local APIC can be found then go out
-	 * : it means there is no mpatable and MADT
-	 */
-	if (!smp_found_config)
-		return;
-
-	set_fixmap_nocache(FIX_APIC_BASE, mp_lapic_addr);
-	apic_printk(APIC_VERBOSE, "mapped APIC to %16lx (%16lx)\n",
-		    APIC_BASE, mp_lapic_addr);
-
-	/*
-	 * Fetch the APIC ID of the BSP in case we have a
-	 * default configuration (or the MP table is broken).
-	 */
-	boot_cpu_physical_apicid = read_apic_id();
-}
-#endif
-
 /**
  * init_apic_mappings - initialize APIC mappings
  */
@@ -1664,10 +1661,7 @@ void __init init_apic_mappings(void)
 		 * acpi_register_lapic_address()
 		 */
 		if (!acpi_lapic && !smp_found_config)
-			set_fixmap_nocache(FIX_APIC_BASE, apic_phys);
-
-		apic_printk(APIC_VERBOSE, "mapped APIC to %08lx (%08lx)\n",
-					APIC_BASE, apic_phys);
+			register_lapic_address(apic_phys);
 	}
 
 	/*
@@ -1689,11 +1683,27 @@ void __init init_apic_mappings(void)
 	}
 }
 
+void __init register_lapic_address(unsigned long address)
+{
+	mp_lapic_addr = address;
+
+	if (!x2apic_mode) {
+		set_fixmap_nocache(FIX_APIC_BASE, address);
+		apic_printk(APIC_VERBOSE, "mapped APIC to %16lx (%16lx)\n",
+			    APIC_BASE, mp_lapic_addr);
+	}
+	if (boot_cpu_physical_apicid == -1U) {
+		boot_cpu_physical_apicid  = read_apic_id();
+		apic_version[boot_cpu_physical_apicid] =
+			 GET_APIC_VERSION(apic_read(APIC_LVR));
+	}
+}
+
 /*
  * This initializes the IO-APIC and APIC hardware if this is
  * a UP kernel.
  */
-int apic_version[MAX_APICS];
+int apic_version[MAX_LOCAL_APIC];
 
 int __init APIC_init_uniprocessor(void)
 {
@@ -1751,24 +1761,17 @@ int __init APIC_init_uniprocessor(void)
 		enable_IO_APIC();
 #endif
 
-	end_local_APIC_setup();
+	bsp_end_local_APIC_setup();
 
 #ifdef CONFIG_X86_IO_APIC
 	if (smp_found_config && !skip_ioapic_setup && nr_ioapics)
 		setup_IO_APIC();
 	else {
 		nr_ioapics = 0;
-		localise_nmi_watchdog();
 	}
-#else
-	localise_nmi_watchdog();
 #endif
 
 	x86_init.timers.setup_percpu_clockev();
-#ifdef CONFIG_X86_64
-	check_nmi_watchdog();
-#endif
-
 	return 0;
 }
 
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/kernel/apic/hw_nmi.c linux-libre-2.6.38-gnu1/arch/x86/kernel/apic/hw_nmi.c
--- linux-libre-2.6.37-gnu1/arch/x86/kernel/apic/hw_nmi.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/kernel/apic/hw_nmi.c	2011-03-14 21:20:32.000000000 -0400
@@ -17,20 +17,31 @@
 #include <linux/nmi.h>
 #include <linux/module.h>
 
+#ifdef CONFIG_HARDLOCKUP_DETECTOR
 u64 hw_nmi_get_sample_period(void)
 {
 	return (u64)(cpu_khz) * 1000 * 60;
 }
+#endif
 
-#ifdef ARCH_HAS_NMI_WATCHDOG
-
+#ifdef arch_trigger_all_cpu_backtrace
 /* For reliability, we're prepared to waste bits here. */
 static DECLARE_BITMAP(backtrace_mask, NR_CPUS) __read_mostly;
 
+/* "in progress" flag of arch_trigger_all_cpu_backtrace */
+static unsigned long backtrace_flag;
+
 void arch_trigger_all_cpu_backtrace(void)
 {
 	int i;
 
+	if (test_and_set_bit(0, &backtrace_flag))
+		/*
+		 * If there is already a trigger_all_cpu_backtrace() in progress
+		 * (backtrace_flag == 1), don't output double cpu dump infos.
+		 */
+		return;
+
 	cpumask_copy(to_cpumask(backtrace_mask), cpu_online_mask);
 
 	printk(KERN_INFO "sending NMI to all CPUs:\n");
@@ -42,6 +53,9 @@ void arch_trigger_all_cpu_backtrace(void
 			break;
 		mdelay(1);
 	}
+
+	clear_bit(0, &backtrace_flag);
+	smp_mb__after_clear_bit();
 }
 
 static int __kprobes
@@ -50,11 +64,10 @@ arch_trigger_all_cpu_backtrace_handler(s
 {
 	struct die_args *args = __args;
 	struct pt_regs *regs;
-	int cpu = smp_processor_id();
+	int cpu;
 
 	switch (cmd) {
 	case DIE_NMI:
-	case DIE_NMI_IPI:
 		break;
 
 	default:
@@ -62,6 +75,7 @@ arch_trigger_all_cpu_backtrace_handler(s
 	}
 
 	regs = args->regs;
+	cpu = smp_processor_id();
 
 	if (cpumask_test_cpu(cpu, to_cpumask(backtrace_mask))) {
 		static arch_spinlock_t lock = __ARCH_SPIN_LOCK_UNLOCKED;
@@ -81,7 +95,7 @@ arch_trigger_all_cpu_backtrace_handler(s
 static __read_mostly struct notifier_block backtrace_notifier = {
 	.notifier_call          = arch_trigger_all_cpu_backtrace_handler,
 	.next                   = NULL,
-	.priority               = 1
+	.priority               = NMI_LOCAL_LOW_PRIOR,
 };
 
 static int __init register_trigger_all_cpu_backtrace(void)
@@ -91,18 +105,3 @@ static int __init register_trigger_all_c
 }
 early_initcall(register_trigger_all_cpu_backtrace);
 #endif
-
-/* STUB calls to mimic old nmi_watchdog behaviour */
-#if defined(CONFIG_X86_LOCAL_APIC)
-unsigned int nmi_watchdog = NMI_NONE;
-EXPORT_SYMBOL(nmi_watchdog);
-void acpi_nmi_enable(void) { return; }
-void acpi_nmi_disable(void) { return; }
-#endif
-atomic_t nmi_active = ATOMIC_INIT(0);           /* oprofile uses this */
-EXPORT_SYMBOL(nmi_active);
-int unknown_nmi_panic;
-void cpu_nmi_set_wd_enabled(void) { return; }
-void stop_apic_nmi_watchdog(void *unused) { return; }
-void setup_apic_nmi_watchdog(void *unused) { return; }
-int __init check_nmi_watchdog(void) { return 0; }
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/kernel/apic/io_apic.c linux-libre-2.6.38-gnu1/arch/x86/kernel/apic/io_apic.c
--- linux-libre-2.6.37-gnu1/arch/x86/kernel/apic/io_apic.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/kernel/apic/io_apic.c	2011-03-14 21:20:32.000000000 -0400
@@ -54,7 +54,6 @@
 #include <asm/dma.h>
 #include <asm/timer.h>
 #include <asm/i8259.h>
-#include <asm/nmi.h>
 #include <asm/msidef.h>
 #include <asm/hypertransport.h>
 #include <asm/setup.h>
@@ -126,6 +125,26 @@ static int __init parse_noapic(char *str
 }
 early_param("noapic", parse_noapic);
 
+/* Will be called in mpparse/acpi/sfi codes for saving IRQ info */
+void mp_save_irq(struct mpc_intsrc *m)
+{
+	int i;
+
+	apic_printk(APIC_VERBOSE, "Int: type %d, pol %d, trig %d, bus %02x,"
+		" IRQ %02x, APIC ID %x, APIC INT %02x\n",
+		m->irqtype, m->irqflag & 3, (m->irqflag >> 2) & 3, m->srcbus,
+		m->srcbusirq, m->dstapic, m->dstirq);
+
+	for (i = 0; i < mp_irq_entries; i++) {
+		if (!memcmp(&mp_irqs[i], m, sizeof(*m)))
+			return;
+	}
+
+	memcpy(&mp_irqs[mp_irq_entries], m, sizeof(*m));
+	if (++mp_irq_entries == MAX_IRQ_SOURCES)
+		panic("Max # of irq sources exceeded!!\n");
+}
+
 struct irq_pin_list {
 	int apic, pin;
 	struct irq_pin_list *next;
@@ -136,6 +155,7 @@ static struct irq_pin_list *alloc_irq_pi
 	return kzalloc_node(sizeof(struct irq_pin_list), GFP_KERNEL, node);
 }
 
+
 /* 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];
@@ -1934,8 +1954,7 @@ void disable_IO_APIC(void)
  *
  * by Matt Domsch <Matt_Domsch@dell.com>  Tue Dec 21 12:25:05 CST 1999
  */
-
-void __init setup_ioapic_ids_from_mpc(void)
+void __init setup_ioapic_ids_from_mpc_nocheck(void)
 {
 	union IO_APIC_reg_00 reg_00;
 	physid_mask_t phys_id_present_map;
@@ -1944,15 +1963,6 @@ void __init setup_ioapic_ids_from_mpc(vo
 	unsigned char old_id;
 	unsigned long flags;
 
-	if (acpi_ioapic)
-		return;
-	/*
-	 * Don't check I/O APIC IDs for xAPIC systems.  They have
-	 * no meaning without the serial APIC bus.
-	 */
-	if (!(boot_cpu_data.x86_vendor == X86_VENDOR_INTEL)
-		|| APIC_XAPIC(apic_version[boot_cpu_physical_apicid]))
-		return;
 	/*
 	 * This is broken; anything with a real cpu count has to
 	 * circumvent this idiocy regardless.
@@ -2006,7 +2016,6 @@ void __init setup_ioapic_ids_from_mpc(vo
 			physids_or(phys_id_present_map, phys_id_present_map, tmp);
 		}
 
-
 		/*
 		 * We need to adjust the IRQ routing table
 		 * if the ID changed.
@@ -2018,9 +2027,12 @@ void __init setup_ioapic_ids_from_mpc(vo
 						= mp_ioapics[apic_id].apicid;
 
 		/*
-		 * Read the right value from the MPC table and
-		 * write it into the ID register.
+		 * Update the ID register according to the right value
+		 * from the MPC table if they are different.
 		 */
+		if (mp_ioapics[apic_id].apicid == reg_00.bits.ID)
+			continue;
+
 		apic_printk(APIC_VERBOSE, KERN_INFO
 			"...changing IO-APIC physical APIC ID to %d ...",
 			mp_ioapics[apic_id].apicid);
@@ -2042,6 +2054,21 @@ void __init setup_ioapic_ids_from_mpc(vo
 			apic_printk(APIC_VERBOSE, " ok.\n");
 	}
 }
+
+void __init setup_ioapic_ids_from_mpc(void)
+{
+
+	if (acpi_ioapic)
+		return;
+	/*
+	 * Don't check I/O APIC IDs for xAPIC systems.  They have
+	 * no meaning without the serial APIC bus.
+	 */
+	if (!(boot_cpu_data.x86_vendor == X86_VENDOR_INTEL)
+		|| APIC_XAPIC(apic_version[boot_cpu_physical_apicid]))
+		return;
+	setup_ioapic_ids_from_mpc_nocheck();
+}
 #endif
 
 int no_timer_check __initdata;
@@ -2302,7 +2329,7 @@ asmlinkage void smp_irq_move_cleanup_int
 		unsigned int irr;
 		struct irq_desc *desc;
 		struct irq_cfg *cfg;
-		irq = __get_cpu_var(vector_irq)[vector];
+		irq = __this_cpu_read(vector_irq[vector]);
 
 		if (irq == -1)
 			continue;
@@ -2336,7 +2363,7 @@ asmlinkage void smp_irq_move_cleanup_int
 			apic->send_IPI_self(IRQ_MOVE_CLEANUP_VECTOR);
 			goto unlock;
 		}
-		__get_cpu_var(vector_irq)[vector] = -1;
+		__this_cpu_write(vector_irq[vector], -1);
 unlock:
 		raw_spin_unlock(&desc->lock);
 	}
@@ -2642,24 +2669,6 @@ static void lapic_register_intr(int irq)
 				      "edge");
 }
 
-static void __init setup_nmi(void)
-{
-	/*
-	 * Dirty trick to enable the NMI watchdog ...
-	 * We put the 8259A master into AEOI mode and
-	 * unmask on all local APICs LVT0 as NMI.
-	 *
-	 * The idea to use the 8259A in AEOI mode ('8259A Virtual Wire')
-	 * is from Maciej W. Rozycki - so we do not have to EOI from
-	 * the NMI handler or the timer interrupt.
-	 */
-	apic_printk(APIC_VERBOSE, KERN_INFO "activating NMI Watchdog ...");
-
-	enable_NMI_through_LVT0();
-
-	apic_printk(APIC_VERBOSE, " done.\n");
-}
-
 /*
  * This looks a bit hackish but it's about the only one way of sending
  * a few INTA cycles to 8259As and any associated glue logic.  ICR does
@@ -2765,15 +2774,6 @@ static inline void __init check_timer(vo
 	 */
 	apic_write(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_EXTINT);
 	legacy_pic->init(1);
-#ifdef CONFIG_X86_32
-	{
-		unsigned int ver;
-
-		ver = apic_read(APIC_LVR);
-		ver = GET_APIC_VERSION(ver);
-		timer_ack = (nmi_watchdog == NMI_IO_APIC && !APIC_INTEGRATED(ver));
-	}
-#endif
 
 	pin1  = find_isa_irq_pin(0, mp_INT);
 	apic1 = find_isa_irq_apic(0, mp_INT);
@@ -2821,10 +2821,6 @@ static inline void __init check_timer(vo
 				unmask_ioapic(cfg);
 		}
 		if (timer_irq_works()) {
-			if (nmi_watchdog == NMI_IO_APIC) {
-				setup_nmi();
-				legacy_pic->unmask(0);
-			}
 			if (disable_timer_pin_1 > 0)
 				clear_IO_APIC_pin(0, pin1);
 			goto out;
@@ -2850,11 +2846,6 @@ static inline void __init check_timer(vo
 		if (timer_irq_works()) {
 			apic_printk(APIC_QUIET, KERN_INFO "....... works.\n");
 			timer_through_8259 = 1;
-			if (nmi_watchdog == NMI_IO_APIC) {
-				legacy_pic->mask(0);
-				setup_nmi();
-				legacy_pic->unmask(0);
-			}
 			goto out;
 		}
 		/*
@@ -2866,15 +2857,6 @@ static inline void __init check_timer(vo
 		apic_printk(APIC_QUIET, KERN_INFO "....... failed.\n");
 	}
 
-	if (nmi_watchdog == NMI_IO_APIC) {
-		apic_printk(APIC_QUIET, KERN_WARNING "timer doesn't work "
-			    "through the IO-APIC - disabling NMI Watchdog!\n");
-		nmi_watchdog = NMI_NONE;
-	}
-#ifdef CONFIG_X86_32
-	timer_ack = 0;
-#endif
-
 	apic_printk(APIC_QUIET, KERN_INFO
 		    "...trying to set up timer as Virtual Wire IRQ...\n");
 
@@ -3639,7 +3621,7 @@ int __init io_apic_get_redir_entries (in
 	return reg_01.bits.entries + 1;
 }
 
-void __init probe_nr_irqs_gsi(void)
+static void __init probe_nr_irqs_gsi(void)
 {
 	int nr;
 
@@ -3956,7 +3938,7 @@ static struct resource * __init ioapic_s
 	return res;
 }
 
-void __init ioapic_init_mappings(void)
+void __init ioapic_and_gsi_init(void)
 {
 	unsigned long ioapic_phys, idx = FIX_IO_APIC_BASE_0;
 	struct resource *ioapic_res;
@@ -3994,6 +3976,8 @@ fake_ioapic_page:
 		ioapic_res->end = ioapic_phys + IO_APIC_SLOT_SIZE - 1;
 		ioapic_res++;
 	}
+
+	probe_nr_irqs_gsi();
 }
 
 void __init ioapic_insert_resources(void)
@@ -4018,6 +4002,9 @@ int mp_find_ioapic(u32 gsi)
 {
 	int i = 0;
 
+	if (nr_ioapics == 0)
+		return -1;
+
 	/* Find the IOAPIC that manages this GSI. */
 	for (i = 0; i < nr_ioapics; i++) {
 		if ((gsi >= mp_gsi_routing[i].gsi_base)
@@ -4103,7 +4090,8 @@ void __init pre_init_apic_IRQ0(void)
 
 	printk(KERN_INFO "Early APIC setup for system timer0\n");
 #ifndef CONFIG_SMP
-	phys_cpu_present_map = physid_mask_of_physid(boot_cpu_physical_apicid);
+	physid_set_mask_of_physid(boot_cpu_physical_apicid,
+					 &phys_cpu_present_map);
 #endif
 	/* Make sure the irq descriptor is set up */
 	cfg = alloc_irq_and_cfg_at(0, 0);
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/kernel/apic/Makefile linux-libre-2.6.38-gnu1/arch/x86/kernel/apic/Makefile
--- linux-libre-2.6.37-gnu1/arch/x86/kernel/apic/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/kernel/apic/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -3,10 +3,7 @@
 #
 
 obj-$(CONFIG_X86_LOCAL_APIC)	+= apic.o apic_noop.o probe_$(BITS).o ipi.o
-ifneq ($(CONFIG_HARDLOCKUP_DETECTOR),y)
-obj-$(CONFIG_X86_LOCAL_APIC)	+= nmi.o
-endif
-obj-$(CONFIG_HARDLOCKUP_DETECTOR)	+= hw_nmi.o
+obj-y				+= hw_nmi.o
 
 obj-$(CONFIG_X86_IO_APIC)	+= io_apic.o
 obj-$(CONFIG_SMP)		+= ipi.o
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/kernel/apic/nmi.c linux-libre-2.6.38-gnu1/arch/x86/kernel/apic/nmi.c
--- linux-libre-2.6.37-gnu1/arch/x86/kernel/apic/nmi.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/kernel/apic/nmi.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,567 +0,0 @@
-/*
- *  NMI watchdog support on APIC systems
- *
- *  Started by Ingo Molnar <mingo@redhat.com>
- *
- *  Fixes:
- *  Mikael Pettersson	: AMD K7 support for local APIC NMI watchdog.
- *  Mikael Pettersson	: Power Management for local APIC NMI watchdog.
- *  Mikael Pettersson	: Pentium 4 support for local APIC NMI watchdog.
- *  Pavel Machek and
- *  Mikael Pettersson	: PM converted to driver model. Disable/enable API.
- */
-
-#include <asm/apic.h>
-
-#include <linux/nmi.h>
-#include <linux/mm.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/sysdev.h>
-#include <linux/sysctl.h>
-#include <linux/percpu.h>
-#include <linux/kprobes.h>
-#include <linux/cpumask.h>
-#include <linux/kernel_stat.h>
-#include <linux/kdebug.h>
-#include <linux/smp.h>
-
-#include <asm/i8259.h>
-#include <asm/io_apic.h>
-#include <asm/proto.h>
-#include <asm/timer.h>
-
-#include <asm/mce.h>
-
-#include <asm/mach_traps.h>
-
-int unknown_nmi_panic;
-int nmi_watchdog_enabled;
-
-/* For reliability, we're prepared to waste bits here. */
-static DECLARE_BITMAP(backtrace_mask, NR_CPUS) __read_mostly;
-
-/* nmi_active:
- * >0: the lapic NMI watchdog is active, but can be disabled
- * <0: the lapic NMI watchdog has not been set up, and cannot
- *     be enabled
- *  0: the lapic NMI watchdog is disabled, but can be enabled
- */
-atomic_t nmi_active = ATOMIC_INIT(0);		/* oprofile uses this */
-EXPORT_SYMBOL(nmi_active);
-
-unsigned int nmi_watchdog = NMI_NONE;
-EXPORT_SYMBOL(nmi_watchdog);
-
-static int panic_on_timeout;
-
-static unsigned int nmi_hz = HZ;
-static DEFINE_PER_CPU(short, wd_enabled);
-static int endflag __initdata;
-
-static inline unsigned int get_nmi_count(int cpu)
-{
-	return per_cpu(irq_stat, cpu).__nmi_count;
-}
-
-static inline int mce_in_progress(void)
-{
-#if defined(CONFIG_X86_MCE)
-	return atomic_read(&mce_entry) > 0;
-#endif
-	return 0;
-}
-
-/*
- * Take the local apic timer and PIT/HPET into account. We don't
- * know which one is active, when we have highres/dyntick on
- */
-static inline unsigned int get_timer_irqs(int cpu)
-{
-	return per_cpu(irq_stat, cpu).apic_timer_irqs +
-		per_cpu(irq_stat, cpu).irq0_irqs;
-}
-
-#ifdef CONFIG_SMP
-/*
- * The performance counters used by NMI_LOCAL_APIC don't trigger when
- * the CPU is idle. To make sure the NMI watchdog really ticks on all
- * CPUs during the test make them busy.
- */
-static __init void nmi_cpu_busy(void *data)
-{
-	local_irq_enable_in_hardirq();
-	/*
-	 * Intentionally don't use cpu_relax here. This is
-	 * to make sure that the performance counter really ticks,
-	 * even if there is a simulator or similar that catches the
-	 * pause instruction. On a real HT machine this is fine because
-	 * all other CPUs are busy with "useless" delay loops and don't
-	 * care if they get somewhat less cycles.
-	 */
-	while (endflag == 0)
-		mb();
-}
-#endif
-
-static void report_broken_nmi(int cpu, unsigned int *prev_nmi_count)
-{
-	printk(KERN_CONT "\n");
-
-	printk(KERN_WARNING
-		"WARNING: CPU#%d: NMI appears to be stuck (%d->%d)!\n",
-			cpu, prev_nmi_count[cpu], get_nmi_count(cpu));
-
-	printk(KERN_WARNING
-		"Please report this to bugzilla.kernel.org,\n");
-	printk(KERN_WARNING
-		"and attach the output of the 'dmesg' command.\n");
-
-	per_cpu(wd_enabled, cpu) = 0;
-	atomic_dec(&nmi_active);
-}
-
-static void __acpi_nmi_disable(void *__unused)
-{
-	apic_write(APIC_LVT0, APIC_DM_NMI | APIC_LVT_MASKED);
-}
-
-int __init check_nmi_watchdog(void)
-{
-	unsigned int *prev_nmi_count;
-	int cpu;
-
-	if (!nmi_watchdog_active() || !atomic_read(&nmi_active))
-		return 0;
-
-	prev_nmi_count = kmalloc(nr_cpu_ids * sizeof(int), GFP_KERNEL);
-	if (!prev_nmi_count)
-		goto error;
-
-	printk(KERN_INFO "Testing NMI watchdog ... ");
-
-#ifdef CONFIG_SMP
-	if (nmi_watchdog == NMI_LOCAL_APIC)
-		smp_call_function(nmi_cpu_busy, (void *)&endflag, 0);
-#endif
-
-	for_each_possible_cpu(cpu)
-		prev_nmi_count[cpu] = get_nmi_count(cpu);
-	local_irq_enable();
-	mdelay((20 * 1000) / nmi_hz); /* wait 20 ticks */
-
-	for_each_online_cpu(cpu) {
-		if (!per_cpu(wd_enabled, cpu))
-			continue;
-		if (get_nmi_count(cpu) - prev_nmi_count[cpu] <= 5)
-			report_broken_nmi(cpu, prev_nmi_count);
-	}
-	endflag = 1;
-	if (!atomic_read(&nmi_active)) {
-		kfree(prev_nmi_count);
-		atomic_set(&nmi_active, -1);
-		goto error;
-	}
-	printk("OK.\n");
-
-	/*
-	 * now that we know it works we can reduce NMI frequency to
-	 * something more reasonable; makes a difference in some configs
-	 */
-	if (nmi_watchdog == NMI_LOCAL_APIC)
-		nmi_hz = lapic_adjust_nmi_hz(1);
-
-	kfree(prev_nmi_count);
-	return 0;
-error:
-	if (nmi_watchdog == NMI_IO_APIC) {
-		if (!timer_through_8259)
-			legacy_pic->mask(0);
-		on_each_cpu(__acpi_nmi_disable, NULL, 1);
-	}
-
-#ifdef CONFIG_X86_32
-	timer_ack = 0;
-#endif
-	return -1;
-}
-
-static int __init setup_nmi_watchdog(char *str)
-{
-	unsigned int nmi;
-
-	if (!strncmp(str, "panic", 5)) {
-		panic_on_timeout = 1;
-		str = strchr(str, ',');
-		if (!str)
-			return 1;
-		++str;
-	}
-
-	if (!strncmp(str, "lapic", 5))
-		nmi_watchdog = NMI_LOCAL_APIC;
-	else if (!strncmp(str, "ioapic", 6))
-		nmi_watchdog = NMI_IO_APIC;
-	else {
-		get_option(&str, &nmi);
-		if (nmi >= NMI_INVALID)
-			return 0;
-		nmi_watchdog = nmi;
-	}
-
-	return 1;
-}
-__setup("nmi_watchdog=", setup_nmi_watchdog);
-
-/*
- * Suspend/resume support
- */
-#ifdef CONFIG_PM
-
-static int nmi_pm_active; /* nmi_active before suspend */
-
-static int lapic_nmi_suspend(struct sys_device *dev, pm_message_t state)
-{
-	/* only CPU0 goes here, other CPUs should be offline */
-	nmi_pm_active = atomic_read(&nmi_active);
-	stop_apic_nmi_watchdog(NULL);
-	BUG_ON(atomic_read(&nmi_active) != 0);
-	return 0;
-}
-
-static int lapic_nmi_resume(struct sys_device *dev)
-{
-	/* only CPU0 goes here, other CPUs should be offline */
-	if (nmi_pm_active > 0) {
-		setup_apic_nmi_watchdog(NULL);
-		touch_nmi_watchdog();
-	}
-	return 0;
-}
-
-static struct sysdev_class nmi_sysclass = {
-	.name		= "lapic_nmi",
-	.resume		= lapic_nmi_resume,
-	.suspend	= lapic_nmi_suspend,
-};
-
-static struct sys_device device_lapic_nmi = {
-	.id	= 0,
-	.cls	= &nmi_sysclass,
-};
-
-static int __init init_lapic_nmi_sysfs(void)
-{
-	int error;
-
-	/*
-	 * should really be a BUG_ON but b/c this is an
-	 * init call, it just doesn't work.  -dcz
-	 */
-	if (nmi_watchdog != NMI_LOCAL_APIC)
-		return 0;
-
-	if (atomic_read(&nmi_active) < 0)
-		return 0;
-
-	error = sysdev_class_register(&nmi_sysclass);
-	if (!error)
-		error = sysdev_register(&device_lapic_nmi);
-	return error;
-}
-
-/* must come after the local APIC's device_initcall() */
-late_initcall(init_lapic_nmi_sysfs);
-
-#endif	/* CONFIG_PM */
-
-static void __acpi_nmi_enable(void *__unused)
-{
-	apic_write(APIC_LVT0, APIC_DM_NMI);
-}
-
-/*
- * Enable timer based NMIs on all CPUs:
- */
-void acpi_nmi_enable(void)
-{
-	if (atomic_read(&nmi_active) && nmi_watchdog == NMI_IO_APIC)
-		on_each_cpu(__acpi_nmi_enable, NULL, 1);
-}
-
-/*
- * Disable timer based NMIs on all CPUs:
- */
-void acpi_nmi_disable(void)
-{
-	if (atomic_read(&nmi_active) && nmi_watchdog == NMI_IO_APIC)
-		on_each_cpu(__acpi_nmi_disable, NULL, 1);
-}
-
-/*
- * This function is called as soon the LAPIC NMI watchdog driver has everything
- * in place and it's ready to check if the NMIs belong to the NMI watchdog
- */
-void cpu_nmi_set_wd_enabled(void)
-{
-	__get_cpu_var(wd_enabled) = 1;
-}
-
-void setup_apic_nmi_watchdog(void *unused)
-{
-	if (__get_cpu_var(wd_enabled))
-		return;
-
-	/* cheap hack to support suspend/resume */
-	/* if cpu0 is not active neither should the other cpus */
-	if (smp_processor_id() != 0 && atomic_read(&nmi_active) <= 0)
-		return;
-
-	switch (nmi_watchdog) {
-	case NMI_LOCAL_APIC:
-		if (lapic_watchdog_init(nmi_hz) < 0) {
-			__get_cpu_var(wd_enabled) = 0;
-			return;
-		}
-		/* FALL THROUGH */
-	case NMI_IO_APIC:
-		__get_cpu_var(wd_enabled) = 1;
-		atomic_inc(&nmi_active);
-	}
-}
-
-void stop_apic_nmi_watchdog(void *unused)
-{
-	/* only support LOCAL and IO APICs for now */
-	if (!nmi_watchdog_active())
-		return;
-	if (__get_cpu_var(wd_enabled) == 0)
-		return;
-	if (nmi_watchdog == NMI_LOCAL_APIC)
-		lapic_watchdog_stop();
-	else
-		__acpi_nmi_disable(NULL);
-	__get_cpu_var(wd_enabled) = 0;
-	atomic_dec(&nmi_active);
-}
-
-/*
- * the best way to detect whether a CPU has a 'hard lockup' problem
- * is to check it's local APIC timer IRQ counts. If they are not
- * changing then that CPU has some problem.
- *
- * as these watchdog NMI IRQs are generated on every CPU, we only
- * have to check the current processor.
- *
- * since NMIs don't listen to _any_ locks, we have to be extremely
- * careful not to rely on unsafe variables. The printk might lock
- * up though, so we have to break up any console locks first ...
- * [when there will be more tty-related locks, break them up here too!]
- */
-
-static DEFINE_PER_CPU(unsigned, last_irq_sum);
-static DEFINE_PER_CPU(long, alert_counter);
-static DEFINE_PER_CPU(int, nmi_touch);
-
-void touch_nmi_watchdog(void)
-{
-	if (nmi_watchdog_active()) {
-		unsigned cpu;
-
-		/*
-		 * Tell other CPUs to reset their alert counters. We cannot
-		 * do it ourselves because the alert count increase is not
-		 * atomic.
-		 */
-		for_each_present_cpu(cpu) {
-			if (per_cpu(nmi_touch, cpu) != 1)
-				per_cpu(nmi_touch, cpu) = 1;
-		}
-	}
-
-	/*
-	 * Tickle the softlockup detector too:
-	 */
-	touch_softlockup_watchdog();
-}
-EXPORT_SYMBOL(touch_nmi_watchdog);
-
-notrace __kprobes int
-nmi_watchdog_tick(struct pt_regs *regs, unsigned reason)
-{
-	/*
-	 * Since current_thread_info()-> is always on the stack, and we
-	 * always switch the stack NMI-atomically, it's safe to use
-	 * smp_processor_id().
-	 */
-	unsigned int sum;
-	int touched = 0;
-	int cpu = smp_processor_id();
-	int rc = 0;
-
-	sum = get_timer_irqs(cpu);
-
-	if (__get_cpu_var(nmi_touch)) {
-		__get_cpu_var(nmi_touch) = 0;
-		touched = 1;
-	}
-
-	/* We can be called before check_nmi_watchdog, hence NULL check. */
-	if (cpumask_test_cpu(cpu, to_cpumask(backtrace_mask))) {
-		static DEFINE_RAW_SPINLOCK(lock); /* Serialise the printks */
-
-		raw_spin_lock(&lock);
-		printk(KERN_WARNING "NMI backtrace for cpu %d\n", cpu);
-		show_regs(regs);
-		dump_stack();
-		raw_spin_unlock(&lock);
-		cpumask_clear_cpu(cpu, to_cpumask(backtrace_mask));
-
-		rc = 1;
-	}
-
-	/* Could check oops_in_progress here too, but it's safer not to */
-	if (mce_in_progress())
-		touched = 1;
-
-	/* if the none of the timers isn't firing, this cpu isn't doing much */
-	if (!touched && __get_cpu_var(last_irq_sum) == sum) {
-		/*
-		 * Ayiee, looks like this CPU is stuck ...
-		 * wait a few IRQs (5 seconds) before doing the oops ...
-		 */
-		__this_cpu_inc(alert_counter);
-		if (__this_cpu_read(alert_counter) == 5 * nmi_hz)
-			/*
-			 * die_nmi will return ONLY if NOTIFY_STOP happens..
-			 */
-			die_nmi("BUG: NMI Watchdog detected LOCKUP",
-				regs, panic_on_timeout);
-	} else {
-		__get_cpu_var(last_irq_sum) = sum;
-		__this_cpu_write(alert_counter, 0);
-	}
-
-	/* see if the nmi watchdog went off */
-	if (!__get_cpu_var(wd_enabled))
-		return rc;
-	switch (nmi_watchdog) {
-	case NMI_LOCAL_APIC:
-		rc |= lapic_wd_event(nmi_hz);
-		break;
-	case NMI_IO_APIC:
-		/*
-		 * don't know how to accurately check for this.
-		 * just assume it was a watchdog timer interrupt
-		 * This matches the old behaviour.
-		 */
-		rc = 1;
-		break;
-	}
-	return rc;
-}
-
-#ifdef CONFIG_SYSCTL
-
-static void enable_ioapic_nmi_watchdog_single(void *unused)
-{
-	__get_cpu_var(wd_enabled) = 1;
-	atomic_inc(&nmi_active);
-	__acpi_nmi_enable(NULL);
-}
-
-static void enable_ioapic_nmi_watchdog(void)
-{
-	on_each_cpu(enable_ioapic_nmi_watchdog_single, NULL, 1);
-	touch_nmi_watchdog();
-}
-
-static void disable_ioapic_nmi_watchdog(void)
-{
-	on_each_cpu(stop_apic_nmi_watchdog, NULL, 1);
-}
-
-static int __init setup_unknown_nmi_panic(char *str)
-{
-	unknown_nmi_panic = 1;
-	return 1;
-}
-__setup("unknown_nmi_panic", setup_unknown_nmi_panic);
-
-static int unknown_nmi_panic_callback(struct pt_regs *regs, int cpu)
-{
-	unsigned char reason = get_nmi_reason();
-	char buf[64];
-
-	sprintf(buf, "NMI received for unknown reason %02x\n", reason);
-	die_nmi(buf, regs, 1); /* Always panic here */
-	return 0;
-}
-
-/*
- * proc handler for /proc/sys/kernel/nmi
- */
-int proc_nmi_enabled(struct ctl_table *table, int write,
-			void __user *buffer, size_t *length, loff_t *ppos)
-{
-	int old_state;
-
-	nmi_watchdog_enabled = (atomic_read(&nmi_active) > 0) ? 1 : 0;
-	old_state = nmi_watchdog_enabled;
-	proc_dointvec(table, write, buffer, length, ppos);
-	if (!!old_state == !!nmi_watchdog_enabled)
-		return 0;
-
-	if (atomic_read(&nmi_active) < 0 || !nmi_watchdog_active()) {
-		printk(KERN_WARNING
-			"NMI watchdog is permanently disabled\n");
-		return -EIO;
-	}
-
-	if (nmi_watchdog == NMI_LOCAL_APIC) {
-		if (nmi_watchdog_enabled)
-			enable_lapic_nmi_watchdog();
-		else
-			disable_lapic_nmi_watchdog();
-	} else if (nmi_watchdog == NMI_IO_APIC) {
-		if (nmi_watchdog_enabled)
-			enable_ioapic_nmi_watchdog();
-		else
-			disable_ioapic_nmi_watchdog();
-	} else {
-		printk(KERN_WARNING
-			"NMI watchdog doesn't know what hardware to touch\n");
-		return -EIO;
-	}
-	return 0;
-}
-
-#endif /* CONFIG_SYSCTL */
-
-int do_nmi_callback(struct pt_regs *regs, int cpu)
-{
-#ifdef CONFIG_SYSCTL
-	if (unknown_nmi_panic)
-		return unknown_nmi_panic_callback(regs, cpu);
-#endif
-	return 0;
-}
-
-void arch_trigger_all_cpu_backtrace(void)
-{
-	int i;
-
-	cpumask_copy(to_cpumask(backtrace_mask), cpu_online_mask);
-
-	printk(KERN_INFO "sending NMI to all CPUs:\n");
-	apic->send_IPI_all(NMI_VECTOR);
-
-	/* Wait for up to 10 seconds for all CPUs to do the backtrace */
-	for (i = 0; i < 10 * 1000; i++) {
-		if (cpumask_empty(to_cpumask(backtrace_mask)))
-			break;
-		mdelay(1);
-	}
-}
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/kernel/apic/x2apic_uv_x.c linux-libre-2.6.38-gnu1/arch/x86/kernel/apic/x2apic_uv_x.c
--- linux-libre-2.6.37-gnu1/arch/x86/kernel/apic/x2apic_uv_x.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/kernel/apic/x2apic_uv_x.c	2011-03-14 21:20:32.000000000 -0400
@@ -48,6 +48,16 @@ unsigned int uv_apicid_hibits;
 EXPORT_SYMBOL_GPL(uv_apicid_hibits);
 static DEFINE_SPINLOCK(uv_nmi_lock);
 
+static unsigned long __init uv_early_read_mmr(unsigned long addr)
+{
+	unsigned long val, *mmr;
+
+	mmr = early_ioremap(UV_LOCAL_MMR_BASE | addr, sizeof(*mmr));
+	val = *mmr;
+	early_iounmap(mmr, sizeof(*mmr));
+	return val;
+}
+
 static inline bool is_GRU_range(u64 start, u64 end)
 {
 	return start >= gru_start_paddr && end <= gru_end_paddr;
@@ -58,28 +68,24 @@ static bool uv_is_untracked_pat_range(u6
 	return is_ISA_range(start, end) || is_GRU_range(start, end);
 }
 
-static int early_get_nodeid(void)
+static int __init early_get_pnodeid(void)
 {
 	union uvh_node_id_u node_id;
-	unsigned long *mmr;
-
-	mmr = early_ioremap(UV_LOCAL_MMR_BASE | UVH_NODE_ID, sizeof(*mmr));
-	node_id.v = *mmr;
-	early_iounmap(mmr, sizeof(*mmr));
+	union uvh_rh_gam_config_mmr_u  m_n_config;
+	int pnode;
 
 	/* Currently, all blades have same revision number */
+	node_id.v = uv_early_read_mmr(UVH_NODE_ID);
+	m_n_config.v = uv_early_read_mmr(UVH_RH_GAM_CONFIG_MMR);
 	uv_min_hub_revision_id = node_id.s.revision;
 
-	return node_id.s.node_id;
+	pnode = (node_id.s.node_id >> 1) & ((1 << m_n_config.s.n_skt) - 1);
+	return pnode;
 }
 
 static void __init early_get_apic_pnode_shift(void)
 {
-	unsigned long *mmr;
-
-	mmr = early_ioremap(UV_LOCAL_MMR_BASE | UVH_APICID, sizeof(*mmr));
-	uvh_apicid.v = *mmr;
-	early_iounmap(mmr, sizeof(*mmr));
+	uvh_apicid.v = uv_early_read_mmr(UVH_APICID);
 	if (!uvh_apicid.v)
 		/*
 		 * Old bios, use default value
@@ -95,21 +101,17 @@ static void __init early_get_apic_pnode_
 static void __init uv_set_apicid_hibit(void)
 {
 	union uvh_lb_target_physical_apic_id_mask_u apicid_mask;
-	unsigned long *mmr;
 
-	mmr = early_ioremap(UV_LOCAL_MMR_BASE |
-		UVH_LB_TARGET_PHYSICAL_APIC_ID_MASK, sizeof(*mmr));
-	apicid_mask.v = *mmr;
-	early_iounmap(mmr, sizeof(*mmr));
+	apicid_mask.v = uv_early_read_mmr(UVH_LB_TARGET_PHYSICAL_APIC_ID_MASK);
 	uv_apicid_hibits = apicid_mask.s.bit_enables & UV_APICID_HIBIT_MASK;
 }
 
 static int __init uv_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
 {
-	int nodeid;
+	int pnodeid;
 
 	if (!strcmp(oem_id, "SGI")) {
-		nodeid = early_get_nodeid();
+		pnodeid = early_get_pnodeid();
 		early_get_apic_pnode_shift();
 		x86_platform.is_untracked_pat_range =  uv_is_untracked_pat_range;
 		x86_platform.nmi_init = uv_nmi_init;
@@ -118,8 +120,8 @@ static int __init uv_acpi_madt_oem_check
 		else if (!strcmp(oem_table_id, "UVX"))
 			uv_system_type = UV_X2APIC;
 		else if (!strcmp(oem_table_id, "UVH")) {
-			__get_cpu_var(x2apic_extra_bits) =
-				nodeid << (uvh_apicid.s.pnode_shift - 1);
+			__this_cpu_write(x2apic_extra_bits,
+				pnodeid << uvh_apicid.s.pnode_shift);
 			uv_system_type = UV_NON_UNIQUE_APIC;
 			uv_set_apicid_hibit();
 			return 1;
@@ -284,7 +286,7 @@ static unsigned int x2apic_get_apic_id(u
 	unsigned int id;
 
 	WARN_ON(preemptible() && num_online_cpus() > 1);
-	id = x | __get_cpu_var(x2apic_extra_bits);
+	id = x | __this_cpu_read(x2apic_extra_bits);
 
 	return id;
 }
@@ -376,7 +378,7 @@ struct apic __refdata apic_x2apic_uv_x =
 
 static __cpuinit void set_x2apic_extra_bits(int pnode)
 {
-	__get_cpu_var(x2apic_extra_bits) = (pnode << 6);
+	__this_cpu_write(x2apic_extra_bits, pnode << uvh_apicid.s.pnode_shift);
 }
 
 /*
@@ -639,7 +641,7 @@ void __cpuinit uv_cpu_init(void)
  */
 int uv_handle_nmi(struct notifier_block *self, unsigned long reason, void *data)
 {
-	if (reason != DIE_NMI_IPI)
+	if (reason != DIE_NMIUNKNOWN)
 		return NOTIFY_OK;
 
 	if (in_crash_kexec)
@@ -682,27 +684,32 @@ void uv_nmi_init(void)
 void __init uv_system_init(void)
 {
 	union uvh_rh_gam_config_mmr_u  m_n_config;
+	union uvh_rh_gam_mmioh_overlay_config_mmr_u mmioh;
 	union uvh_node_id_u node_id;
 	unsigned long gnode_upper, lowmem_redir_base, lowmem_redir_size;
-	int bytes, nid, cpu, lcpu, pnode, blade, i, j, m_val, n_val;
+	int bytes, nid, cpu, lcpu, pnode, blade, i, j, m_val, n_val, n_io;
 	int gnode_extra, max_pnode = 0;
 	unsigned long mmr_base, present, paddr;
-	unsigned short pnode_mask;
+	unsigned short pnode_mask, pnode_io_mask;
 
 	map_low_mmrs();
 
 	m_n_config.v = uv_read_local_mmr(UVH_RH_GAM_CONFIG_MMR );
 	m_val = m_n_config.s.m_skt;
 	n_val = m_n_config.s.n_skt;
+	mmioh.v = uv_read_local_mmr(UVH_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR);
+	n_io = mmioh.s.n_io;
 	mmr_base =
 	    uv_read_local_mmr(UVH_RH_GAM_MMR_OVERLAY_CONFIG_MMR) &
 	    ~UV_MMR_ENABLE;
 	pnode_mask = (1 << n_val) - 1;
+	pnode_io_mask = (1 << n_io) - 1;
+
 	node_id.v = uv_read_local_mmr(UVH_NODE_ID);
 	gnode_extra = (node_id.s.node_id & ~((1 << n_val) - 1)) >> 1;
 	gnode_upper = ((unsigned long)gnode_extra  << m_val);
-	printk(KERN_DEBUG "UV: N %d, M %d, gnode_upper 0x%lx, gnode_extra 0x%x\n",
-			n_val, m_val, gnode_upper, gnode_extra);
+	printk(KERN_INFO "UV: N %d, M %d, N_IO: %d, gnode_upper 0x%lx, gnode_extra 0x%x, pnode_mask 0x%x, pnode_io_mask 0x%x\n",
+			n_val, m_val, n_io, gnode_upper, gnode_extra, pnode_mask, pnode_io_mask);
 
 	printk(KERN_DEBUG "UV: global MMR base 0x%lx\n", mmr_base);
 
@@ -735,7 +742,7 @@ void __init uv_system_init(void)
 		for (j = 0; j < 64; j++) {
 			if (!test_bit(j, &present))
 				continue;
-			pnode = (i * 64 + j);
+			pnode = (i * 64 + j) & pnode_mask;
 			uv_blade_info[blade].pnode = pnode;
 			uv_blade_info[blade].nr_possible_cpus = 0;
 			uv_blade_info[blade].nr_online_cpus = 0;
@@ -756,6 +763,7 @@ void __init uv_system_init(void)
 		/*
 		 * apic_pnode_shift must be set before calling uv_apicid_to_pnode();
 		 */
+		uv_cpu_hub_info(cpu)->pnode_mask = pnode_mask;
 		uv_cpu_hub_info(cpu)->apic_pnode_shift = uvh_apicid.s.pnode_shift;
 		pnode = uv_apicid_to_pnode(apicid);
 		blade = boot_pnode_to_blade(pnode);
@@ -772,7 +780,6 @@ void __init uv_system_init(void)
 		uv_cpu_hub_info(cpu)->numa_blade_id = blade;
 		uv_cpu_hub_info(cpu)->blade_processor_id = lcpu;
 		uv_cpu_hub_info(cpu)->pnode = pnode;
-		uv_cpu_hub_info(cpu)->pnode_mask = pnode_mask;
 		uv_cpu_hub_info(cpu)->gpa_mask = (1UL << (m_val + n_val)) - 1;
 		uv_cpu_hub_info(cpu)->gnode_upper = gnode_upper;
 		uv_cpu_hub_info(cpu)->gnode_extra = gnode_extra;
@@ -796,7 +803,7 @@ void __init uv_system_init(void)
 
 	map_gru_high(max_pnode);
 	map_mmr_high(max_pnode);
-	map_mmioh_high(max_pnode);
+	map_mmioh_high(max_pnode & pnode_io_mask);
 
 	uv_cpu_init();
 	uv_scir_register_cpu_notifier();
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/kernel/check.c linux-libre-2.6.38-gnu1/arch/x86/kernel/check.c
--- linux-libre-2.6.37-gnu1/arch/x86/kernel/check.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/kernel/check.c	2011-03-14 21:20:32.000000000 -0400
@@ -106,8 +106,8 @@ void __init setup_bios_corruption_check(
 		addr += size;
 	}
 
-	printk(KERN_INFO "Scanning %d areas for low memory corruption\n",
-	       num_scan_areas);
+	if (num_scan_areas)
+		printk(KERN_INFO "Scanning %d areas for low memory corruption\n", num_scan_areas);
 }
 
 
@@ -143,12 +143,12 @@ static void check_corruption(struct work
 {
 	check_for_bios_corruption();
 	schedule_delayed_work(&bios_check_work,
-		round_jiffies_relative(corruption_check_period*HZ)); 
+		round_jiffies_relative(corruption_check_period*HZ));
 }
 
 static int start_periodic_check_for_corruption(void)
 {
-	if (!memory_corruption_check || corruption_check_period == 0)
+	if (!num_scan_areas || !memory_corruption_check || corruption_check_period == 0)
 		return 0;
 
 	printk(KERN_INFO "Scanning for low memory corruption every %d seconds\n",
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/kernel/cpu/amd.c linux-libre-2.6.38-gnu1/arch/x86/kernel/cpu/amd.c
--- linux-libre-2.6.37-gnu1/arch/x86/kernel/cpu/amd.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/kernel/cpu/amd.c	2011-03-14 21:20:32.000000000 -0400
@@ -668,7 +668,7 @@ EXPORT_SYMBOL_GPL(amd_erratum_383);
 
 bool cpu_has_amd_erratum(const int *erratum)
 {
-	struct cpuinfo_x86 *cpu = &current_cpu_data;
+	struct cpuinfo_x86 *cpu = __this_cpu_ptr(&cpu_info);
 	int osvw_id = *erratum++;
 	u32 range;
 	u32 ms;
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/kernel/cpu/common.c linux-libre-2.6.38-gnu1/arch/x86/kernel/cpu/common.c
--- linux-libre-2.6.37-gnu1/arch/x86/kernel/cpu/common.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/kernel/cpu/common.c	2011-03-14 21:20:32.000000000 -0400
@@ -894,7 +894,6 @@ void __init identify_boot_cpu(void)
 #else
 	vgetcpu_set_mode();
 #endif
-	init_hw_perf_events();
 }
 
 void __cpuinit identify_secondary_cpu(struct cpuinfo_x86 *c)
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/kernel/cpu/cpufreq/p4-clockmod.c linux-libre-2.6.38-gnu1/arch/x86/kernel/cpu/cpufreq/p4-clockmod.c
--- linux-libre-2.6.37-gnu1/arch/x86/kernel/cpu/cpufreq/p4-clockmod.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/kernel/cpu/cpufreq/p4-clockmod.c	2011-03-14 21:20:32.000000000 -0400
@@ -158,9 +158,9 @@ static unsigned int cpufreq_p4_get_frequ
 {
 	if (c->x86 == 0x06) {
 		if (cpu_has(c, X86_FEATURE_EST))
-			printk(KERN_WARNING PFX "Warning: EST-capable CPU "
-			       "detected. The acpi-cpufreq module offers "
-			       "voltage scaling in addition of frequency "
+			printk_once(KERN_WARNING PFX "Warning: EST-capable "
+			       "CPU detected. The acpi-cpufreq module offers "
+			       "voltage scaling in addition to frequency "
 			       "scaling. You should use that instead of "
 			       "p4-clockmod, if possible.\n");
 		switch (c->x86_model) {
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/kernel/cpu/cpufreq/pcc-cpufreq.c linux-libre-2.6.38-gnu1/arch/x86/kernel/cpu/cpufreq/pcc-cpufreq.c
--- linux-libre-2.6.37-gnu1/arch/x86/kernel/cpu/cpufreq/pcc-cpufreq.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/kernel/cpu/cpufreq/pcc-cpufreq.c	2011-03-14 21:20:32.000000000 -0400
@@ -195,7 +195,7 @@ static unsigned int pcc_get_freq(unsigne
 cmd_incomplete:
 	iowrite16(0, &pcch_hdr->status);
 	spin_unlock(&pcc_lock);
-	return -EINVAL;
+	return 0;
 }
 
 static int pcc_cpufreq_target(struct cpufreq_policy *policy,
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/kernel/cpu/cpufreq/powernow-k8.c linux-libre-2.6.38-gnu1/arch/x86/kernel/cpu/cpufreq/powernow-k8.c
--- linux-libre-2.6.37-gnu1/arch/x86/kernel/cpu/cpufreq/powernow-k8.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/kernel/cpu/cpufreq/powernow-k8.c	2011-03-14 21:20:32.000000000 -0400
@@ -521,7 +521,7 @@ static void check_supported_cpu(void *_r
 
 	*rc = -ENODEV;
 
-	if (current_cpu_data.x86_vendor != X86_VENDOR_AMD)
+	if (__this_cpu_read(cpu_info.x86_vendor) != X86_VENDOR_AMD)
 		return;
 
 	eax = cpuid_eax(CPUID_PROCESSOR_SIGNATURE);
@@ -1377,7 +1377,7 @@ static int __devexit powernowk8_cpu_exit
 static void query_values_on_cpu(void *_err)
 {
 	int *err = _err;
-	struct powernow_k8_data *data = __get_cpu_var(powernow_data);
+	struct powernow_k8_data *data = __this_cpu_read(powernow_data);
 
 	*err = query_current_values_with_pending_wait(data);
 }
@@ -1537,6 +1537,7 @@ static struct notifier_block cpb_nb = {
 static int __cpuinit powernowk8_init(void)
 {
 	unsigned int i, supported_cpus = 0, cpu;
+	int rv;
 
 	for_each_online_cpu(i) {
 		int rc;
@@ -1555,14 +1556,14 @@ static int __cpuinit powernowk8_init(voi
 
 		cpb_capable = true;
 
-		register_cpu_notifier(&cpb_nb);
-
 		msrs = msrs_alloc();
 		if (!msrs) {
 			printk(KERN_ERR "%s: Error allocating msrs!\n", __func__);
 			return -ENOMEM;
 		}
 
+		register_cpu_notifier(&cpb_nb);
+
 		rdmsr_on_cpus(cpu_online_mask, MSR_K7_HWCR, msrs);
 
 		for_each_cpu(cpu, cpu_online_mask) {
@@ -1574,7 +1575,13 @@ static int __cpuinit powernowk8_init(voi
 			(cpb_enabled ? "on" : "off"));
 	}
 
-	return cpufreq_register_driver(&cpufreq_amd64_driver);
+	rv = cpufreq_register_driver(&cpufreq_amd64_driver);
+	if (rv < 0 && boot_cpu_has(X86_FEATURE_CPB)) {
+		unregister_cpu_notifier(&cpb_nb);
+		msrs_free(msrs);
+		msrs = NULL;
+	}
+	return rv;
 }
 
 /* driver entry point for term */
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/kernel/cpu/intel_cacheinfo.c linux-libre-2.6.38-gnu1/arch/x86/kernel/cpu/intel_cacheinfo.c
--- linux-libre-2.6.37-gnu1/arch/x86/kernel/cpu/intel_cacheinfo.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/kernel/cpu/intel_cacheinfo.c	2011-03-14 21:20:32.000000000 -0400
@@ -45,6 +45,7 @@ static const struct _cache_table __cpuin
 	{ 0x0a, LVL_1_DATA, 8 },	/* 2 way set assoc, 32 byte line size */
 	{ 0x0c, LVL_1_DATA, 16 },	/* 4-way set assoc, 32 byte line size */
 	{ 0x0d, LVL_1_DATA, 16 },	/* 4-way set assoc, 64 byte line size */
+	{ 0x0e, LVL_1_DATA, 24 },	/* 6-way set assoc, 64 byte line size */
 	{ 0x21, LVL_2,      256 },	/* 8-way set assoc, 64 byte line size */
 	{ 0x22, LVL_3,      512 },	/* 4-way set assoc, sectored cache, 64 byte line size */
 	{ 0x23, LVL_3,      MB(1) },	/* 8-way set assoc, sectored cache, 64 byte line size */
@@ -66,6 +67,7 @@ static const struct _cache_table __cpuin
 	{ 0x45, LVL_2,      MB(2) },	/* 4-way set assoc, 32 byte line size */
 	{ 0x46, LVL_3,      MB(4) },	/* 4-way set assoc, 64 byte line size */
 	{ 0x47, LVL_3,      MB(8) },	/* 8-way set assoc, 64 byte line size */
+	{ 0x48, LVL_2,      MB(3) },	/* 12-way set assoc, 64 byte line size */
 	{ 0x49, LVL_3,      MB(4) },	/* 16-way set assoc, 64 byte line size */
 	{ 0x4a, LVL_3,      MB(6) },	/* 12-way set assoc, 64 byte line size */
 	{ 0x4b, LVL_3,      MB(8) },	/* 16-way set assoc, 64 byte line size */
@@ -87,6 +89,7 @@ static const struct _cache_table __cpuin
 	{ 0x7c, LVL_2,      MB(1) },	/* 8-way set assoc, sectored cache, 64 byte line size */
 	{ 0x7d, LVL_2,      MB(2) },	/* 8-way set assoc, 64 byte line size */
 	{ 0x7f, LVL_2,      512 },	/* 2-way set assoc, 64 byte line size */
+	{ 0x80, LVL_2,      512 },	/* 8-way set assoc, 64 byte line size */
 	{ 0x82, LVL_2,      256 },	/* 8-way set assoc, 32 byte line size */
 	{ 0x83, LVL_2,      512 },	/* 8-way set assoc, 32 byte line size */
 	{ 0x84, LVL_2,      MB(1) },	/* 8-way set assoc, 32 byte line size */
@@ -149,8 +152,7 @@ union _cpuid4_leaf_ecx {
 };
 
 struct amd_l3_cache {
-	struct	 pci_dev *dev;
-	bool	 can_disable;
+	struct	 amd_northbridge *nb;
 	unsigned indices;
 	u8	 subcaches[4];
 };
@@ -266,7 +268,7 @@ amd_cpuid4(int leaf, union _cpuid4_leaf_
 		line_size = l2.line_size;
 		lines_per_tag = l2.lines_per_tag;
 		/* cpu_data has errata corrections for K7 applied */
-		size_in_kb = current_cpu_data.x86_cache_size;
+		size_in_kb = __this_cpu_read(cpu_info.x86_cache_size);
 		break;
 	case 3:
 		if (!l3.val)
@@ -288,7 +290,7 @@ amd_cpuid4(int leaf, union _cpuid4_leaf_
 	eax->split.type = types[leaf];
 	eax->split.level = levels[leaf];
 	eax->split.num_threads_sharing = 0;
-	eax->split.num_cores_on_die = current_cpu_data.x86_max_cores - 1;
+	eax->split.num_cores_on_die = __this_cpu_read(cpu_info.x86_max_cores) - 1;
 
 
 	if (assoc == 0xffff)
@@ -311,14 +313,12 @@ struct _cache_attr {
 /*
  * L3 cache descriptors
  */
-static struct amd_l3_cache **__cpuinitdata l3_caches;
-
 static void __cpuinit amd_calc_l3_indices(struct amd_l3_cache *l3)
 {
 	unsigned int sc0, sc1, sc2, sc3;
 	u32 val = 0;
 
-	pci_read_config_dword(l3->dev, 0x1C4, &val);
+	pci_read_config_dword(l3->nb->misc, 0x1C4, &val);
 
 	/* calculate subcache sizes */
 	l3->subcaches[0] = sc0 = !(val & BIT(0));
@@ -330,47 +330,14 @@ static void __cpuinit amd_calc_l3_indice
 	l3->indices = (max(max3(sc0, sc1, sc2), sc3) << 10) - 1;
 }
 
-static struct amd_l3_cache * __cpuinit amd_init_l3_cache(int node)
-{
-	struct amd_l3_cache *l3;
-	struct pci_dev *dev = node_to_k8_nb_misc(node);
-
-	l3 = kzalloc(sizeof(struct amd_l3_cache), GFP_ATOMIC);
-	if (!l3) {
-		printk(KERN_WARNING "Error allocating L3 struct\n");
-		return NULL;
-	}
-
-	l3->dev = dev;
-
-	amd_calc_l3_indices(l3);
-
-	return l3;
-}
-
-static void __cpuinit amd_check_l3_disable(struct _cpuid4_info_regs *this_leaf,
-					   int index)
+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;
 
-	if (boot_cpu_data.x86 != 0x10)
-		return;
-
-	if (index < 3)
-		return;
-
-	/* see errata #382 and #388 */
-	if (boot_cpu_data.x86_model < 0x8)
-		return;
-
-	if ((boot_cpu_data.x86_model == 0x8 ||
-	     boot_cpu_data.x86_model == 0x9)
-		&&
-	     boot_cpu_data.x86_mask < 0x1)
-			return;
-
-	/* not in virtualized environments */
-	if (k8_northbridges.num == 0)
+	/* only for L3, and not in virtualized environments */
+	if (index < 3 || amd_nb_num() == 0)
 		return;
 
 	/*
@@ -378,7 +345,7 @@ static void __cpuinit amd_check_l3_disab
 	 * never freed but this is done only on shutdown so it doesn't matter.
 	 */
 	if (!l3_caches) {
-		int size = k8_northbridges.num * sizeof(struct amd_l3_cache *);
+		int size = amd_nb_num() * sizeof(struct amd_l3_cache);
 
 		l3_caches = kzalloc(size, GFP_ATOMIC);
 		if (!l3_caches)
@@ -387,14 +354,12 @@ static void __cpuinit amd_check_l3_disab
 
 	node = amd_get_nb_id(smp_processor_id());
 
-	if (!l3_caches[node]) {
-		l3_caches[node] = amd_init_l3_cache(node);
-		l3_caches[node]->can_disable = true;
+	if (!l3_caches[node].nb) {
+		l3_caches[node].nb = node_to_amd_nb(node);
+		amd_calc_l3_indices(&l3_caches[node]);
 	}
 
-	WARN_ON(!l3_caches[node]);
-
-	this_leaf->l3 = l3_caches[node];
+	this_leaf->l3 = &l3_caches[node];
 }
 
 /*
@@ -408,7 +373,7 @@ int amd_get_l3_disable_slot(struct amd_l
 {
 	unsigned int reg = 0;
 
-	pci_read_config_dword(l3->dev, 0x1BC + slot * 4, &reg);
+	pci_read_config_dword(l3->nb->misc, 0x1BC + slot * 4, &reg);
 
 	/* check whether this slot is activated already */
 	if (reg & (3UL << 30))
@@ -422,7 +387,8 @@ static ssize_t show_cache_disable(struct
 {
 	int index;
 
-	if (!this_leaf->l3 || !this_leaf->l3->can_disable)
+	if (!this_leaf->l3 ||
+	    !amd_nb_has_feature(AMD_NB_L3_INDEX_DISABLE))
 		return -EINVAL;
 
 	index = amd_get_l3_disable_slot(this_leaf->l3, slot);
@@ -457,7 +423,7 @@ static void amd_l3_disable_index(struct
 		if (!l3->subcaches[i])
 			continue;
 
-		pci_write_config_dword(l3->dev, 0x1BC + slot * 4, reg);
+		pci_write_config_dword(l3->nb->misc, 0x1BC + slot * 4, reg);
 
 		/*
 		 * We need to WBINVD on a core on the node containing the L3
@@ -467,7 +433,7 @@ static void amd_l3_disable_index(struct
 		wbinvd_on_cpu(cpu);
 
 		reg |= BIT(31);
-		pci_write_config_dword(l3->dev, 0x1BC + slot * 4, reg);
+		pci_write_config_dword(l3->nb->misc, 0x1BC + slot * 4, reg);
 	}
 }
 
@@ -524,7 +490,8 @@ static ssize_t store_cache_disable(struc
 	if (!capable(CAP_SYS_ADMIN))
 		return -EPERM;
 
-	if (!this_leaf->l3 || !this_leaf->l3->can_disable)
+	if (!this_leaf->l3 ||
+	    !amd_nb_has_feature(AMD_NB_L3_INDEX_DISABLE))
 		return -EINVAL;
 
 	cpu = cpumask_first(to_cpumask(this_leaf->shared_cpu_map));
@@ -545,7 +512,7 @@ static ssize_t store_cache_disable(struc
 #define STORE_CACHE_DISABLE(slot)					\
 static ssize_t								\
 store_cache_disable_##slot(struct _cpuid4_info *this_leaf,		\
-			    const char *buf, size_t count)		\
+			   const char *buf, size_t count)		\
 {									\
 	return store_cache_disable(this_leaf, buf, count, slot);	\
 }
@@ -558,10 +525,7 @@ static struct _cache_attr cache_disable_
 		show_cache_disable_1, store_cache_disable_1);
 
 #else	/* CONFIG_AMD_NB */
-static void __cpuinit
-amd_check_l3_disable(struct _cpuid4_info_regs *this_leaf, int index)
-{
-};
+#define amd_init_l3_cache(x, y)
 #endif /* CONFIG_AMD_NB */
 
 static int
@@ -575,7 +539,7 @@ __cpuinit cpuid4_cache_lookup_regs(int i
 
 	if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) {
 		amd_cpuid4(index, &eax, &ebx, &ecx);
-		amd_check_l3_disable(this_leaf, index);
+		amd_init_l3_cache(this_leaf, index);
 	} else {
 		cpuid_count(4, index, &eax.full, &ebx.full, &ecx.full, &edx);
 	}
@@ -983,30 +947,48 @@ define_one_ro(size);
 define_one_ro(shared_cpu_map);
 define_one_ro(shared_cpu_list);
 
-#define DEFAULT_SYSFS_CACHE_ATTRS	\
-	&type.attr,			\
-	&level.attr,			\
-	&coherency_line_size.attr,	\
-	&physical_line_partition.attr,	\
-	&ways_of_associativity.attr,	\
-	&number_of_sets.attr,		\
-	&size.attr,			\
-	&shared_cpu_map.attr,		\
-	&shared_cpu_list.attr
-
 static struct attribute *default_attrs[] = {
-	DEFAULT_SYSFS_CACHE_ATTRS,
+	&type.attr,
+	&level.attr,
+	&coherency_line_size.attr,
+	&physical_line_partition.attr,
+	&ways_of_associativity.attr,
+	&number_of_sets.attr,
+	&size.attr,
+	&shared_cpu_map.attr,
+	&shared_cpu_list.attr,
 	NULL
 };
 
-static struct attribute *default_l3_attrs[] = {
-	DEFAULT_SYSFS_CACHE_ATTRS,
 #ifdef CONFIG_AMD_NB
-	&cache_disable_0.attr,
-	&cache_disable_1.attr,
+static struct attribute ** __cpuinit amd_l3_attrs(void)
+{
+	static struct attribute **attrs;
+	int n;
+
+	if (attrs)
+		return attrs;
+
+	n = sizeof (default_attrs) / sizeof (struct attribute *);
+
+	if (amd_nb_has_feature(AMD_NB_L3_INDEX_DISABLE))
+		n += 2;
+
+	attrs = kzalloc(n * sizeof (struct attribute *), GFP_KERNEL);
+	if (attrs == NULL)
+		return attrs = default_attrs;
+
+	for (n = 0; default_attrs[n]; n++)
+		attrs[n] = default_attrs[n];
+
+	if (amd_nb_has_feature(AMD_NB_L3_INDEX_DISABLE)) {
+		attrs[n++] = &cache_disable_0.attr;
+		attrs[n++] = &cache_disable_1.attr;
+	}
+
+	return attrs;
+}
 #endif
-	NULL
-};
 
 static ssize_t show(struct kobject *kobj, struct attribute *attr, char *buf)
 {
@@ -1117,11 +1099,11 @@ static int __cpuinit cache_add_dev(struc
 
 		this_leaf = CPUID4_INFO_IDX(cpu, i);
 
-		if (this_leaf->l3 && this_leaf->l3->can_disable)
-			ktype_cache.default_attrs = default_l3_attrs;
-		else
-			ktype_cache.default_attrs = default_attrs;
-
+		ktype_cache.default_attrs = default_attrs;
+#ifdef CONFIG_AMD_NB
+		if (this_leaf->l3)
+			ktype_cache.default_attrs = amd_l3_attrs();
+#endif
 		retval = kobject_init_and_add(&(this_object->kobj),
 					      &ktype_cache,
 					      per_cpu(ici_cache_kobject, cpu),
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/kernel/cpu/mcheck/mce_amd.c linux-libre-2.6.38-gnu1/arch/x86/kernel/cpu/mcheck/mce_amd.c
--- linux-libre-2.6.37-gnu1/arch/x86/kernel/cpu/mcheck/mce_amd.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/kernel/cpu/mcheck/mce_amd.c	2011-03-14 21:20:32.000000000 -0400
@@ -31,8 +31,6 @@
 #include <asm/mce.h>
 #include <asm/msr.h>
 
-#define PFX               "mce_threshold: "
-#define VERSION           "version 1.1.1"
 #define NR_BANKS          6
 #define NR_BLOCKS         9
 #define THRESHOLD_MAX     0xFFF
@@ -59,12 +57,6 @@ struct threshold_block {
 	struct list_head	miscj;
 };
 
-/* defaults used early on boot */
-static struct threshold_block threshold_defaults = {
-	.interrupt_enable	= 0,
-	.threshold_limit	= THRESHOLD_MAX,
-};
-
 struct threshold_bank {
 	struct kobject		*kobj;
 	struct threshold_block	*blocks;
@@ -89,50 +81,101 @@ static void amd_threshold_interrupt(void
 struct thresh_restart {
 	struct threshold_block	*b;
 	int			reset;
+	int			set_lvt_off;
+	int			lvt_off;
 	u16			old_limit;
 };
 
+static int lvt_off_valid(struct threshold_block *b, int apic, u32 lo, u32 hi)
+{
+	int msr = (hi & MASK_LVTOFF_HI) >> 20;
+
+	if (apic < 0) {
+		pr_err(FW_BUG "cpu %d, failed to setup threshold interrupt "
+		       "for bank %d, block %d (MSR%08X=0x%x%08x)\n", b->cpu,
+		       b->bank, b->block, b->address, hi, lo);
+		return 0;
+	}
+
+	if (apic != msr) {
+		pr_err(FW_BUG "cpu %d, invalid threshold interrupt offset %d "
+		       "for bank %d, block %d (MSR%08X=0x%x%08x)\n",
+		       b->cpu, apic, b->bank, b->block, b->address, hi, lo);
+		return 0;
+	}
+
+	return 1;
+};
+
 /* must be called with correct cpu affinity */
 /* Called via smp_call_function_single() */
 static void threshold_restart_bank(void *_tr)
 {
 	struct thresh_restart *tr = _tr;
-	u32 mci_misc_hi, mci_misc_lo;
+	u32 hi, lo;
 
-	rdmsr(tr->b->address, mci_misc_lo, mci_misc_hi);
+	rdmsr(tr->b->address, lo, hi);
 
-	if (tr->b->threshold_limit < (mci_misc_hi & THRESHOLD_MAX))
+	if (tr->b->threshold_limit < (hi & THRESHOLD_MAX))
 		tr->reset = 1;	/* limit cannot be lower than err count */
 
 	if (tr->reset) {		/* reset err count and overflow bit */
-		mci_misc_hi =
-		    (mci_misc_hi & ~(MASK_ERR_COUNT_HI | MASK_OVERFLOW_HI)) |
+		hi =
+		    (hi & ~(MASK_ERR_COUNT_HI | MASK_OVERFLOW_HI)) |
 		    (THRESHOLD_MAX - tr->b->threshold_limit);
 	} else if (tr->old_limit) {	/* change limit w/o reset */
-		int new_count = (mci_misc_hi & THRESHOLD_MAX) +
+		int new_count = (hi & THRESHOLD_MAX) +
 		    (tr->old_limit - tr->b->threshold_limit);
 
-		mci_misc_hi = (mci_misc_hi & ~MASK_ERR_COUNT_HI) |
+		hi = (hi & ~MASK_ERR_COUNT_HI) |
 		    (new_count & THRESHOLD_MAX);
 	}
 
+	if (tr->set_lvt_off) {
+		if (lvt_off_valid(tr->b, tr->lvt_off, lo, hi)) {
+			/* set new lvt offset */
+			hi &= ~MASK_LVTOFF_HI;
+			hi |= tr->lvt_off << 20;
+		}
+	}
+
 	tr->b->interrupt_enable ?
-	    (mci_misc_hi = (mci_misc_hi & ~MASK_INT_TYPE_HI) | INT_TYPE_APIC) :
-	    (mci_misc_hi &= ~MASK_INT_TYPE_HI);
+	    (hi = (hi & ~MASK_INT_TYPE_HI) | INT_TYPE_APIC) :
+	    (hi &= ~MASK_INT_TYPE_HI);
 
-	mci_misc_hi |= MASK_COUNT_EN_HI;
-	wrmsr(tr->b->address, mci_misc_lo, mci_misc_hi);
+	hi |= MASK_COUNT_EN_HI;
+	wrmsr(tr->b->address, lo, hi);
+}
+
+static void mce_threshold_block_init(struct threshold_block *b, int offset)
+{
+	struct thresh_restart tr = {
+		.b			= b,
+		.set_lvt_off		= 1,
+		.lvt_off		= offset,
+	};
+
+	b->threshold_limit		= THRESHOLD_MAX;
+	threshold_restart_bank(&tr);
+};
+
+static int setup_APIC_mce(int reserved, int new)
+{
+	if (reserved < 0 && !setup_APIC_eilvt(new, THRESHOLD_APIC_VECTOR,
+					      APIC_EILVT_MSG_FIX, 0))
+		return new;
+
+	return reserved;
 }
 
 /* cpu init entry point, called from mce.c with preempt off */
 void mce_amd_feature_init(struct cpuinfo_x86 *c)
 {
+	struct threshold_block b;
 	unsigned int cpu = smp_processor_id();
 	u32 low = 0, high = 0, address = 0;
 	unsigned int bank, block;
-	struct thresh_restart tr;
-	int lvt_off = -1;
-	u8 offset;
+	int offset = -1;
 
 	for (bank = 0; bank < NR_BANKS; ++bank) {
 		for (block = 0; block < NR_BLOCKS; ++block) {
@@ -163,39 +206,16 @@ void mce_amd_feature_init(struct cpuinfo
 			if (shared_bank[bank] && c->cpu_core_id)
 				break;
 #endif
-			offset = (high & MASK_LVTOFF_HI) >> 20;
-			if (lvt_off < 0) {
-				if (setup_APIC_eilvt(offset,
-						     THRESHOLD_APIC_VECTOR,
-						     APIC_EILVT_MSG_FIX, 0)) {
-					pr_err(FW_BUG "cpu %d, failed to "
-					       "setup threshold interrupt "
-					       "for bank %d, block %d "
-					       "(MSR%08X=0x%x%08x)",
-					       smp_processor_id(), bank, block,
-					       address, high, low);
-					continue;
-				}
-				lvt_off = offset;
-			} else if (lvt_off != offset) {
-				pr_err(FW_BUG "cpu %d, invalid threshold "
-				       "interrupt offset %d for bank %d,"
-				       "block %d (MSR%08X=0x%x%08x)",
-				       smp_processor_id(), lvt_off, bank,
-				       block, address, high, low);
-				continue;
-			}
-
-			high &= ~MASK_LVTOFF_HI;
-			high |= lvt_off << 20;
-			wrmsr(address, low, high);
+			offset = setup_APIC_mce(offset,
+						(high & MASK_LVTOFF_HI) >> 20);
 
-			threshold_defaults.address = address;
-			tr.b = &threshold_defaults;
-			tr.reset = 0;
-			tr.old_limit = 0;
-			threshold_restart_bank(&tr);
+			memset(&b, 0, sizeof(b));
+			b.cpu		= cpu;
+			b.bank		= bank;
+			b.block		= block;
+			b.address	= address;
 
+			mce_threshold_block_init(&b, offset);
 			mce_threshold_vector = amd_threshold_interrupt;
 		}
 	}
@@ -298,9 +318,8 @@ store_interrupt_enable(struct threshold_
 
 	b->interrupt_enable = !!new;
 
+	memset(&tr, 0, sizeof(tr));
 	tr.b		= b;
-	tr.reset	= 0;
-	tr.old_limit	= 0;
 
 	smp_call_function_single(b->cpu, threshold_restart_bank, &tr, 1);
 
@@ -321,10 +340,10 @@ store_threshold_limit(struct threshold_b
 	if (new < 1)
 		new = 1;
 
+	memset(&tr, 0, sizeof(tr));
 	tr.old_limit = b->threshold_limit;
 	b->threshold_limit = new;
 	tr.b = b;
-	tr.reset = 0;
 
 	smp_call_function_single(b->cpu, threshold_restart_bank, &tr, 1);
 
@@ -603,9 +622,9 @@ static __cpuinit int threshold_create_de
 			continue;
 		err = threshold_create_bank(cpu, bank);
 		if (err)
-			goto out;
+			return err;
 	}
-out:
+
 	return err;
 }
 
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/kernel/cpu/mcheck/mce.c linux-libre-2.6.38-gnu1/arch/x86/kernel/cpu/mcheck/mce.c
--- linux-libre-2.6.37-gnu1/arch/x86/kernel/cpu/mcheck/mce.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/kernel/cpu/mcheck/mce.c	2011-03-14 21:20:32.000000000 -0400
@@ -326,7 +326,7 @@ static void mce_panic(char *msg, struct
 
 static int msr_to_offset(u32 msr)
 {
-	unsigned bank = __get_cpu_var(injectm.bank);
+	unsigned bank = __this_cpu_read(injectm.bank);
 
 	if (msr == rip_msr)
 		return offsetof(struct mce, ip);
@@ -346,7 +346,7 @@ static u64 mce_rdmsrl(u32 msr)
 {
 	u64 v;
 
-	if (__get_cpu_var(injectm).finished) {
+	if (__this_cpu_read(injectm.finished)) {
 		int offset = msr_to_offset(msr);
 
 		if (offset < 0)
@@ -369,7 +369,7 @@ static u64 mce_rdmsrl(u32 msr)
 
 static void mce_wrmsrl(u32 msr, u64 v)
 {
-	if (__get_cpu_var(injectm).finished) {
+	if (__this_cpu_read(injectm.finished)) {
 		int offset = msr_to_offset(msr);
 
 		if (offset >= 0)
@@ -1159,7 +1159,7 @@ static void mce_start_timer(unsigned lon
 
 	WARN_ON(smp_processor_id() != data);
 
-	if (mce_available(&current_cpu_data)) {
+	if (mce_available(__this_cpu_ptr(&cpu_info))) {
 		machine_check_poll(MCP_TIMESTAMP,
 				&__get_cpu_var(mce_poll_banks));
 	}
@@ -1767,7 +1767,7 @@ static int mce_shutdown(struct sys_devic
 static int mce_resume(struct sys_device *dev)
 {
 	__mcheck_cpu_init_generic();
-	__mcheck_cpu_init_vendor(&current_cpu_data);
+	__mcheck_cpu_init_vendor(__this_cpu_ptr(&cpu_info));
 
 	return 0;
 }
@@ -1775,7 +1775,7 @@ static int mce_resume(struct sys_device
 static void mce_cpu_restart(void *data)
 {
 	del_timer_sync(&__get_cpu_var(mce_timer));
-	if (!mce_available(&current_cpu_data))
+	if (!mce_available(__this_cpu_ptr(&cpu_info)))
 		return;
 	__mcheck_cpu_init_generic();
 	__mcheck_cpu_init_timer();
@@ -1790,7 +1790,7 @@ static void mce_restart(void)
 /* Toggle features for corrected errors */
 static void mce_disable_ce(void *all)
 {
-	if (!mce_available(&current_cpu_data))
+	if (!mce_available(__this_cpu_ptr(&cpu_info)))
 		return;
 	if (all)
 		del_timer_sync(&__get_cpu_var(mce_timer));
@@ -1799,7 +1799,7 @@ static void mce_disable_ce(void *all)
 
 static void mce_enable_ce(void *all)
 {
-	if (!mce_available(&current_cpu_data))
+	if (!mce_available(__this_cpu_ptr(&cpu_info)))
 		return;
 	cmci_reenable();
 	cmci_recheck();
@@ -2022,7 +2022,7 @@ static void __cpuinit mce_disable_cpu(vo
 	unsigned long action = *(unsigned long *)h;
 	int i;
 
-	if (!mce_available(&current_cpu_data))
+	if (!mce_available(__this_cpu_ptr(&cpu_info)))
 		return;
 
 	if (!(action & CPU_TASKS_FROZEN))
@@ -2040,7 +2040,7 @@ static void __cpuinit mce_reenable_cpu(v
 	unsigned long action = *(unsigned long *)h;
 	int i;
 
-	if (!mce_available(&current_cpu_data))
+	if (!mce_available(__this_cpu_ptr(&cpu_info)))
 		return;
 
 	if (!(action & CPU_TASKS_FROZEN))
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/kernel/cpu/mcheck/mce-inject.c linux-libre-2.6.38-gnu1/arch/x86/kernel/cpu/mcheck/mce-inject.c
--- linux-libre-2.6.37-gnu1/arch/x86/kernel/cpu/mcheck/mce-inject.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/kernel/cpu/mcheck/mce-inject.c	2011-03-14 21:20:32.000000000 -0400
@@ -25,6 +25,7 @@
 #include <linux/gfp.h>
 #include <asm/mce.h>
 #include <asm/apic.h>
+#include <asm/nmi.h>
 
 /* Update fake mce registers on current CPU. */
 static void inject_mce(struct mce *m)
@@ -83,7 +84,7 @@ static int mce_raise_notify(struct notif
 	struct die_args *args = (struct die_args *)data;
 	int cpu = smp_processor_id();
 	struct mce *m = &__get_cpu_var(injectm);
-	if (val != DIE_NMI_IPI || !cpumask_test_cpu(cpu, mce_inject_cpumask))
+	if (val != DIE_NMI || !cpumask_test_cpu(cpu, mce_inject_cpumask))
 		return NOTIFY_DONE;
 	cpumask_clear_cpu(cpu, mce_inject_cpumask);
 	if (m->inject_flags & MCJ_EXCEPTION)
@@ -95,7 +96,7 @@ static int mce_raise_notify(struct notif
 
 static struct notifier_block mce_raise_nb = {
 	.notifier_call = mce_raise_notify,
-	.priority = 1000,
+	.priority = NMI_LOCAL_NORMAL_PRIOR,
 };
 
 /* Inject mce on current CPU */
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/kernel/cpu/mcheck/mce_intel.c linux-libre-2.6.38-gnu1/arch/x86/kernel/cpu/mcheck/mce_intel.c
--- linux-libre-2.6.37-gnu1/arch/x86/kernel/cpu/mcheck/mce_intel.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/kernel/cpu/mcheck/mce_intel.c	2011-03-14 21:20:32.000000000 -0400
@@ -130,7 +130,7 @@ void cmci_recheck(void)
 	unsigned long flags;
 	int banks;
 
-	if (!mce_available(&current_cpu_data) || !cmci_supported(&banks))
+	if (!mce_available(__this_cpu_ptr(&cpu_info)) || !cmci_supported(&banks))
 		return;
 	local_irq_save(flags);
 	machine_check_poll(MCP_TIMESTAMP, &__get_cpu_var(mce_banks_owned));
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/kernel/cpu/mcheck/therm_throt.c linux-libre-2.6.38-gnu1/arch/x86/kernel/cpu/mcheck/therm_throt.c
--- linux-libre-2.6.37-gnu1/arch/x86/kernel/cpu/mcheck/therm_throt.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/kernel/cpu/mcheck/therm_throt.c	2011-03-14 21:20:32.000000000 -0400
@@ -53,8 +53,14 @@ struct thermal_state {
 	struct _thermal_state core_power_limit;
 	struct _thermal_state package_throttle;
 	struct _thermal_state package_power_limit;
+	struct _thermal_state core_thresh0;
+	struct _thermal_state core_thresh1;
 };
 
+/* Callback to handle core threshold interrupts */
+int (*platform_thermal_notify)(__u64 msr_val);
+EXPORT_SYMBOL(platform_thermal_notify);
+
 static DEFINE_PER_CPU(struct thermal_state, thermal_state);
 
 static atomic_t therm_throt_en	= ATOMIC_INIT(0);
@@ -200,6 +206,22 @@ static int therm_throt_process(bool new_
 	return 0;
 }
 
+static int thresh_event_valid(int event)
+{
+	struct _thermal_state *state;
+	unsigned int this_cpu = smp_processor_id();
+	struct thermal_state *pstate = &per_cpu(thermal_state, this_cpu);
+	u64 now = get_jiffies_64();
+
+	state = (event == 0) ? &pstate->core_thresh0 : &pstate->core_thresh1;
+
+	if (time_before64(now, state->next_check))
+		return 0;
+
+	state->next_check = now + CHECK_INTERVAL;
+	return 1;
+}
+
 #ifdef CONFIG_SYSFS
 /* Add/Remove thermal_throttle interface for CPU device: */
 static __cpuinit int thermal_throttle_add_dev(struct sys_device *sys_dev,
@@ -313,6 +335,22 @@ device_initcall(thermal_throttle_init_de
 #define PACKAGE_THROTTLED	((__u64)2 << 62)
 #define PACKAGE_POWER_LIMIT	((__u64)3 << 62)
 
+static void notify_thresholds(__u64 msr_val)
+{
+	/* check whether the interrupt handler is defined;
+	 * otherwise simply return
+	 */
+	if (!platform_thermal_notify)
+		return;
+
+	/* lower threshold reached */
+	if ((msr_val & THERM_LOG_THRESHOLD0) &&	thresh_event_valid(0))
+		platform_thermal_notify(msr_val);
+	/* higher threshold reached */
+	if ((msr_val & THERM_LOG_THRESHOLD1) && thresh_event_valid(1))
+		platform_thermal_notify(msr_val);
+}
+
 /* Thermal transition interrupt handler */
 static void intel_thermal_interrupt(void)
 {
@@ -321,6 +359,9 @@ static void intel_thermal_interrupt(void
 
 	rdmsrl(MSR_IA32_THERM_STATUS, msr_val);
 
+	/* Check for violation of core thermal thresholds*/
+	notify_thresholds(msr_val);
+
 	if (therm_throt_process(msr_val & THERM_STATUS_PROCHOT,
 				THERMAL_THROTTLING_EVENT,
 				CORE_LEVEL) != 0)
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/kernel/cpu/mtrr/main.c linux-libre-2.6.38-gnu1/arch/x86/kernel/cpu/mtrr/main.c
--- linux-libre-2.6.37-gnu1/arch/x86/kernel/cpu/mtrr/main.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/kernel/cpu/mtrr/main.c	2011-03-14 21:20:32.000000000 -0400
@@ -793,13 +793,21 @@ void set_mtrr_aps_delayed_init(void)
 }
 
 /*
- * MTRR initialization for all AP's
+ * Delayed MTRR initialization for all AP's
  */
 void mtrr_aps_init(void)
 {
 	if (!use_intel())
 		return;
 
+	/*
+	 * Check if someone has requested the delay of AP MTRR initialization,
+	 * by doing set_mtrr_aps_delayed_init(), prior to this point. If not,
+	 * then we are done.
+	 */
+	if (!mtrr_aps_delayed_init)
+		return;
+
 	set_mtrr(~0U, 0, 0, 0);
 	mtrr_aps_delayed_init = false;
 }
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/kernel/cpu/perfctr-watchdog.c linux-libre-2.6.38-gnu1/arch/x86/kernel/cpu/perfctr-watchdog.c
--- linux-libre-2.6.37-gnu1/arch/x86/kernel/cpu/perfctr-watchdog.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/kernel/cpu/perfctr-watchdog.c	2011-03-14 21:20:32.000000000 -0400
@@ -16,32 +16,12 @@
 #include <linux/kernel.h>
 #include <linux/bitops.h>
 #include <linux/smp.h>
-#include <linux/nmi.h>
+#include <asm/nmi.h>
 #include <linux/kprobes.h>
 
 #include <asm/apic.h>
 #include <asm/perf_event.h>
 
-struct nmi_watchdog_ctlblk {
-	unsigned int cccr_msr;
-	unsigned int perfctr_msr;  /* the MSR to reset in NMI handler */
-	unsigned int evntsel_msr;  /* the MSR to select the events to handle */
-};
-
-/* Interface defining a CPU specific perfctr watchdog */
-struct wd_ops {
-	int (*reserve)(void);
-	void (*unreserve)(void);
-	int (*setup)(unsigned nmi_hz);
-	void (*rearm)(struct nmi_watchdog_ctlblk *wd, unsigned nmi_hz);
-	void (*stop)(void);
-	unsigned perfctr;
-	unsigned evntsel;
-	u64 checkbit;
-};
-
-static const struct wd_ops *wd_ops;
-
 /*
  * this number is calculated from Intel's MSR_P4_CRU_ESCR5 register and it's
  * offset from MSR_P4_BSU_ESCR0.
@@ -60,8 +40,6 @@ static const struct wd_ops *wd_ops;
 static DECLARE_BITMAP(perfctr_nmi_owner, NMI_MAX_COUNTER_BITS);
 static DECLARE_BITMAP(evntsel_nmi_owner, NMI_MAX_COUNTER_BITS);
 
-static DEFINE_PER_CPU(struct nmi_watchdog_ctlblk, nmi_watchdog_ctlblk);
-
 /* converts an msr to an appropriate reservation bit */
 static inline unsigned int nmi_perfctr_msr_to_bit(unsigned int msr)
 {
@@ -172,623 +150,3 @@ void release_evntsel_nmi(unsigned int ms
 	clear_bit(counter, evntsel_nmi_owner);
 }
 EXPORT_SYMBOL(release_evntsel_nmi);
-
-void disable_lapic_nmi_watchdog(void)
-{
-	BUG_ON(nmi_watchdog != NMI_LOCAL_APIC);
-
-	if (atomic_read(&nmi_active) <= 0)
-		return;
-
-	on_each_cpu(stop_apic_nmi_watchdog, NULL, 1);
-
-	if (wd_ops)
-		wd_ops->unreserve();
-
-	BUG_ON(atomic_read(&nmi_active) != 0);
-}
-
-void enable_lapic_nmi_watchdog(void)
-{
-	BUG_ON(nmi_watchdog != NMI_LOCAL_APIC);
-
-	/* are we already enabled */
-	if (atomic_read(&nmi_active) != 0)
-		return;
-
-	/* are we lapic aware */
-	if (!wd_ops)
-		return;
-	if (!wd_ops->reserve()) {
-		printk(KERN_ERR "NMI watchdog: cannot reserve perfctrs\n");
-		return;
-	}
-
-	on_each_cpu(setup_apic_nmi_watchdog, NULL, 1);
-	touch_nmi_watchdog();
-}
-
-/*
- * Activate the NMI watchdog via the local APIC.
- */
-
-static unsigned int adjust_for_32bit_ctr(unsigned int hz)
-{
-	u64 counter_val;
-	unsigned int retval = hz;
-
-	/*
-	 * On Intel CPUs with P6/ARCH_PERFMON only 32 bits in the counter
-	 * are writable, with higher bits sign extending from bit 31.
-	 * So, we can only program the counter with 31 bit values and
-	 * 32nd bit should be 1, for 33.. to be 1.
-	 * Find the appropriate nmi_hz
-	 */
-	counter_val = (u64)cpu_khz * 1000;
-	do_div(counter_val, retval);
-	if (counter_val > 0x7fffffffULL) {
-		u64 count = (u64)cpu_khz * 1000;
-		do_div(count, 0x7fffffffUL);
-		retval = count + 1;
-	}
-	return retval;
-}
-
-static void write_watchdog_counter(unsigned int perfctr_msr,
-				const char *descr, unsigned nmi_hz)
-{
-	u64 count = (u64)cpu_khz * 1000;
-
-	do_div(count, nmi_hz);
-	if (descr)
-		pr_debug("setting %s to -0x%08Lx\n", descr, count);
-	wrmsrl(perfctr_msr, 0 - count);
-}
-
-static void write_watchdog_counter32(unsigned int perfctr_msr,
-				const char *descr, unsigned nmi_hz)
-{
-	u64 count = (u64)cpu_khz * 1000;
-
-	do_div(count, nmi_hz);
-	if (descr)
-		pr_debug("setting %s to -0x%08Lx\n", descr, count);
-	wrmsr(perfctr_msr, (u32)(-count), 0);
-}
-
-/*
- * AMD K7/K8/Family10h/Family11h support.
- * AMD keeps this interface nicely stable so there is not much variety
- */
-#define K7_EVNTSEL_ENABLE	(1 << 22)
-#define K7_EVNTSEL_INT		(1 << 20)
-#define K7_EVNTSEL_OS		(1 << 17)
-#define K7_EVNTSEL_USR		(1 << 16)
-#define K7_EVENT_CYCLES_PROCESSOR_IS_RUNNING	0x76
-#define K7_NMI_EVENT		K7_EVENT_CYCLES_PROCESSOR_IS_RUNNING
-
-static int setup_k7_watchdog(unsigned nmi_hz)
-{
-	unsigned int perfctr_msr, evntsel_msr;
-	unsigned int evntsel;
-	struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk);
-
-	perfctr_msr = wd_ops->perfctr;
-	evntsel_msr = wd_ops->evntsel;
-
-	wrmsrl(perfctr_msr, 0UL);
-
-	evntsel = K7_EVNTSEL_INT
-		| K7_EVNTSEL_OS
-		| K7_EVNTSEL_USR
-		| K7_NMI_EVENT;
-
-	/* setup the timer */
-	wrmsr(evntsel_msr, evntsel, 0);
-	write_watchdog_counter(perfctr_msr, "K7_PERFCTR0", nmi_hz);
-
-	/* initialize the wd struct before enabling */
-	wd->perfctr_msr = perfctr_msr;
-	wd->evntsel_msr = evntsel_msr;
-	wd->cccr_msr = 0;  /* unused */
-
-	/* ok, everything is initialized, announce that we're set */
-	cpu_nmi_set_wd_enabled();
-
-	apic_write(APIC_LVTPC, APIC_DM_NMI);
-	evntsel |= K7_EVNTSEL_ENABLE;
-	wrmsr(evntsel_msr, evntsel, 0);
-
-	return 1;
-}
-
-static void single_msr_stop_watchdog(void)
-{
-	struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk);
-
-	wrmsr(wd->evntsel_msr, 0, 0);
-}
-
-static int single_msr_reserve(void)
-{
-	if (!reserve_perfctr_nmi(wd_ops->perfctr))
-		return 0;
-
-	if (!reserve_evntsel_nmi(wd_ops->evntsel)) {
-		release_perfctr_nmi(wd_ops->perfctr);
-		return 0;
-	}
-	return 1;
-}
-
-static void single_msr_unreserve(void)
-{
-	release_evntsel_nmi(wd_ops->evntsel);
-	release_perfctr_nmi(wd_ops->perfctr);
-}
-
-static void __kprobes
-single_msr_rearm(struct nmi_watchdog_ctlblk *wd, unsigned nmi_hz)
-{
-	/* start the cycle over again */
-	write_watchdog_counter(wd->perfctr_msr, NULL, nmi_hz);
-}
-
-static const struct wd_ops k7_wd_ops = {
-	.reserve	= single_msr_reserve,
-	.unreserve	= single_msr_unreserve,
-	.setup		= setup_k7_watchdog,
-	.rearm		= single_msr_rearm,
-	.stop		= single_msr_stop_watchdog,
-	.perfctr	= MSR_K7_PERFCTR0,
-	.evntsel	= MSR_K7_EVNTSEL0,
-	.checkbit	= 1ULL << 47,
-};
-
-/*
- * Intel Model 6 (PPro+,P2,P3,P-M,Core1)
- */
-#define P6_EVNTSEL0_ENABLE	(1 << 22)
-#define P6_EVNTSEL_INT		(1 << 20)
-#define P6_EVNTSEL_OS		(1 << 17)
-#define P6_EVNTSEL_USR		(1 << 16)
-#define P6_EVENT_CPU_CLOCKS_NOT_HALTED	0x79
-#define P6_NMI_EVENT		P6_EVENT_CPU_CLOCKS_NOT_HALTED
-
-static int setup_p6_watchdog(unsigned nmi_hz)
-{
-	unsigned int perfctr_msr, evntsel_msr;
-	unsigned int evntsel;
-	struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk);
-
-	perfctr_msr = wd_ops->perfctr;
-	evntsel_msr = wd_ops->evntsel;
-
-	/* KVM doesn't implement this MSR */
-	if (wrmsr_safe(perfctr_msr, 0, 0) < 0)
-		return 0;
-
-	evntsel = P6_EVNTSEL_INT
-		| P6_EVNTSEL_OS
-		| P6_EVNTSEL_USR
-		| P6_NMI_EVENT;
-
-	/* setup the timer */
-	wrmsr(evntsel_msr, evntsel, 0);
-	nmi_hz = adjust_for_32bit_ctr(nmi_hz);
-	write_watchdog_counter32(perfctr_msr, "P6_PERFCTR0", nmi_hz);
-
-	/* initialize the wd struct before enabling */
-	wd->perfctr_msr = perfctr_msr;
-	wd->evntsel_msr = evntsel_msr;
-	wd->cccr_msr = 0;  /* unused */
-
-	/* ok, everything is initialized, announce that we're set */
-	cpu_nmi_set_wd_enabled();
-
-	apic_write(APIC_LVTPC, APIC_DM_NMI);
-	evntsel |= P6_EVNTSEL0_ENABLE;
-	wrmsr(evntsel_msr, evntsel, 0);
-
-	return 1;
-}
-
-static void __kprobes p6_rearm(struct nmi_watchdog_ctlblk *wd, unsigned nmi_hz)
-{
-	/*
-	 * P6 based Pentium M need to re-unmask
-	 * the apic vector but it doesn't hurt
-	 * other P6 variant.
-	 * ArchPerfom/Core Duo also needs this
-	 */
-	apic_write(APIC_LVTPC, APIC_DM_NMI);
-
-	/* P6/ARCH_PERFMON has 32 bit counter write */
-	write_watchdog_counter32(wd->perfctr_msr, NULL, nmi_hz);
-}
-
-static const struct wd_ops p6_wd_ops = {
-	.reserve	= single_msr_reserve,
-	.unreserve	= single_msr_unreserve,
-	.setup		= setup_p6_watchdog,
-	.rearm		= p6_rearm,
-	.stop		= single_msr_stop_watchdog,
-	.perfctr	= MSR_P6_PERFCTR0,
-	.evntsel	= MSR_P6_EVNTSEL0,
-	.checkbit	= 1ULL << 39,
-};
-
-/*
- * Intel P4 performance counters.
- * By far the most complicated of all.
- */
-#define MSR_P4_MISC_ENABLE_PERF_AVAIL	(1 << 7)
-#define P4_ESCR_EVENT_SELECT(N)	((N) << 25)
-#define P4_ESCR_OS		(1 << 3)
-#define P4_ESCR_USR		(1 << 2)
-#define P4_CCCR_OVF_PMI0	(1 << 26)
-#define P4_CCCR_OVF_PMI1	(1 << 27)
-#define P4_CCCR_THRESHOLD(N)	((N) << 20)
-#define P4_CCCR_COMPLEMENT	(1 << 19)
-#define P4_CCCR_COMPARE		(1 << 18)
-#define P4_CCCR_REQUIRED	(3 << 16)
-#define P4_CCCR_ESCR_SELECT(N)	((N) << 13)
-#define P4_CCCR_ENABLE		(1 << 12)
-#define P4_CCCR_OVF 		(1 << 31)
-
-#define P4_CONTROLS 18
-static unsigned int p4_controls[18] = {
-	MSR_P4_BPU_CCCR0,
-	MSR_P4_BPU_CCCR1,
-	MSR_P4_BPU_CCCR2,
-	MSR_P4_BPU_CCCR3,
-	MSR_P4_MS_CCCR0,
-	MSR_P4_MS_CCCR1,
-	MSR_P4_MS_CCCR2,
-	MSR_P4_MS_CCCR3,
-	MSR_P4_FLAME_CCCR0,
-	MSR_P4_FLAME_CCCR1,
-	MSR_P4_FLAME_CCCR2,
-	MSR_P4_FLAME_CCCR3,
-	MSR_P4_IQ_CCCR0,
-	MSR_P4_IQ_CCCR1,
-	MSR_P4_IQ_CCCR2,
-	MSR_P4_IQ_CCCR3,
-	MSR_P4_IQ_CCCR4,
-	MSR_P4_IQ_CCCR5,
-};
-/*
- * Set up IQ_COUNTER0 to behave like a clock, by having IQ_CCCR0 filter
- * CRU_ESCR0 (with any non-null event selector) through a complemented
- * max threshold. [IA32-Vol3, Section 14.9.9]
- */
-static int setup_p4_watchdog(unsigned nmi_hz)
-{
-	unsigned int perfctr_msr, evntsel_msr, cccr_msr;
-	unsigned int evntsel, cccr_val;
-	unsigned int misc_enable, dummy;
-	unsigned int ht_num;
-	struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk);
-
-	rdmsr(MSR_IA32_MISC_ENABLE, misc_enable, dummy);
-	if (!(misc_enable & MSR_P4_MISC_ENABLE_PERF_AVAIL))
-		return 0;
-
-#ifdef CONFIG_SMP
-	/* detect which hyperthread we are on */
-	if (smp_num_siblings == 2) {
-		unsigned int ebx, apicid;
-
-		ebx = cpuid_ebx(1);
-		apicid = (ebx >> 24) & 0xff;
-		ht_num = apicid & 1;
-	} else
-#endif
-		ht_num = 0;
-
-	/*
-	 * performance counters are shared resources
-	 * assign each hyperthread its own set
-	 * (re-use the ESCR0 register, seems safe
-	 * and keeps the cccr_val the same)
-	 */
-	if (!ht_num) {
-		/* logical cpu 0 */
-		perfctr_msr = MSR_P4_IQ_PERFCTR0;
-		evntsel_msr = MSR_P4_CRU_ESCR0;
-		cccr_msr = MSR_P4_IQ_CCCR0;
-		cccr_val = P4_CCCR_OVF_PMI0 | P4_CCCR_ESCR_SELECT(4);
-
-		/*
-		 * If we're on the kdump kernel or other situation, we may
-		 * still have other performance counter registers set to
-		 * interrupt and they'll keep interrupting forever because
-		 * of the P4_CCCR_OVF quirk. So we need to ACK all the
-		 * pending interrupts and disable all the registers here,
-		 * before reenabling the NMI delivery. Refer to p4_rearm()
-		 * about the P4_CCCR_OVF quirk.
-		 */
-		if (reset_devices) {
-			unsigned int low, high;
-			int i;
-
-			for (i = 0; i < P4_CONTROLS; i++) {
-				rdmsr(p4_controls[i], low, high);
-				low &= ~(P4_CCCR_ENABLE | P4_CCCR_OVF);
-				wrmsr(p4_controls[i], low, high);
-			}
-		}
-	} else {
-		/* logical cpu 1 */
-		perfctr_msr = MSR_P4_IQ_PERFCTR1;
-		evntsel_msr = MSR_P4_CRU_ESCR0;
-		cccr_msr = MSR_P4_IQ_CCCR1;
-
-		/* Pentium 4 D processors don't support P4_CCCR_OVF_PMI1 */
-		if (boot_cpu_data.x86_model == 4 && boot_cpu_data.x86_mask == 4)
-			cccr_val = P4_CCCR_OVF_PMI0;
-		else
-			cccr_val = P4_CCCR_OVF_PMI1;
-		cccr_val |= P4_CCCR_ESCR_SELECT(4);
-	}
-
-	evntsel = P4_ESCR_EVENT_SELECT(0x3F)
-		| P4_ESCR_OS
-		| P4_ESCR_USR;
-
-	cccr_val |= P4_CCCR_THRESHOLD(15)
-		 | P4_CCCR_COMPLEMENT
-		 | P4_CCCR_COMPARE
-		 | P4_CCCR_REQUIRED;
-
-	wrmsr(evntsel_msr, evntsel, 0);
-	wrmsr(cccr_msr, cccr_val, 0);
-	write_watchdog_counter(perfctr_msr, "P4_IQ_COUNTER0", nmi_hz);
-
-	wd->perfctr_msr = perfctr_msr;
-	wd->evntsel_msr = evntsel_msr;
-	wd->cccr_msr = cccr_msr;
-
-	/* ok, everything is initialized, announce that we're set */
-	cpu_nmi_set_wd_enabled();
-
-	apic_write(APIC_LVTPC, APIC_DM_NMI);
-	cccr_val |= P4_CCCR_ENABLE;
-	wrmsr(cccr_msr, cccr_val, 0);
-	return 1;
-}
-
-static void stop_p4_watchdog(void)
-{
-	struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk);
-	wrmsr(wd->cccr_msr, 0, 0);
-	wrmsr(wd->evntsel_msr, 0, 0);
-}
-
-static int p4_reserve(void)
-{
-	if (!reserve_perfctr_nmi(MSR_P4_IQ_PERFCTR0))
-		return 0;
-#ifdef CONFIG_SMP
-	if (smp_num_siblings > 1 && !reserve_perfctr_nmi(MSR_P4_IQ_PERFCTR1))
-		goto fail1;
-#endif
-	if (!reserve_evntsel_nmi(MSR_P4_CRU_ESCR0))
-		goto fail2;
-	/* RED-PEN why is ESCR1 not reserved here? */
-	return 1;
- fail2:
-#ifdef CONFIG_SMP
-	if (smp_num_siblings > 1)
-		release_perfctr_nmi(MSR_P4_IQ_PERFCTR1);
- fail1:
-#endif
-	release_perfctr_nmi(MSR_P4_IQ_PERFCTR0);
-	return 0;
-}
-
-static void p4_unreserve(void)
-{
-#ifdef CONFIG_SMP
-	if (smp_num_siblings > 1)
-		release_perfctr_nmi(MSR_P4_IQ_PERFCTR1);
-#endif
-	release_evntsel_nmi(MSR_P4_CRU_ESCR0);
-	release_perfctr_nmi(MSR_P4_IQ_PERFCTR0);
-}
-
-static void __kprobes p4_rearm(struct nmi_watchdog_ctlblk *wd, unsigned nmi_hz)
-{
-	unsigned dummy;
-	/*
-	 * P4 quirks:
-	 * - An overflown perfctr will assert its interrupt
-	 *   until the OVF flag in its CCCR is cleared.
-	 * - LVTPC is masked on interrupt and must be
-	 *   unmasked by the LVTPC handler.
-	 */
-	rdmsrl(wd->cccr_msr, dummy);
-	dummy &= ~P4_CCCR_OVF;
-	wrmsrl(wd->cccr_msr, dummy);
-	apic_write(APIC_LVTPC, APIC_DM_NMI);
-	/* start the cycle over again */
-	write_watchdog_counter(wd->perfctr_msr, NULL, nmi_hz);
-}
-
-static const struct wd_ops p4_wd_ops = {
-	.reserve	= p4_reserve,
-	.unreserve	= p4_unreserve,
-	.setup		= setup_p4_watchdog,
-	.rearm		= p4_rearm,
-	.stop		= stop_p4_watchdog,
-	/* RED-PEN this is wrong for the other sibling */
-	.perfctr	= MSR_P4_BPU_PERFCTR0,
-	.evntsel	= MSR_P4_BSU_ESCR0,
-	.checkbit	= 1ULL << 39,
-};
-
-/*
- * Watchdog using the Intel architected PerfMon.
- * Used for Core2 and hopefully all future Intel CPUs.
- */
-#define ARCH_PERFMON_NMI_EVENT_SEL	ARCH_PERFMON_UNHALTED_CORE_CYCLES_SEL
-#define ARCH_PERFMON_NMI_EVENT_UMASK	ARCH_PERFMON_UNHALTED_CORE_CYCLES_UMASK
-
-static struct wd_ops intel_arch_wd_ops;
-
-static int setup_intel_arch_watchdog(unsigned nmi_hz)
-{
-	unsigned int ebx;
-	union cpuid10_eax eax;
-	unsigned int unused;
-	unsigned int perfctr_msr, evntsel_msr;
-	unsigned int evntsel;
-	struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk);
-
-	/*
-	 * Check whether the Architectural PerfMon supports
-	 * Unhalted Core Cycles Event or not.
-	 * NOTE: Corresponding bit = 0 in ebx indicates event present.
-	 */
-	cpuid(10, &(eax.full), &ebx, &unused, &unused);
-	if ((eax.split.mask_length <
-			(ARCH_PERFMON_UNHALTED_CORE_CYCLES_INDEX+1)) ||
-	    (ebx & ARCH_PERFMON_UNHALTED_CORE_CYCLES_PRESENT))
-		return 0;
-
-	perfctr_msr = wd_ops->perfctr;
-	evntsel_msr = wd_ops->evntsel;
-
-	wrmsrl(perfctr_msr, 0UL);
-
-	evntsel = ARCH_PERFMON_EVENTSEL_INT
-		| ARCH_PERFMON_EVENTSEL_OS
-		| ARCH_PERFMON_EVENTSEL_USR
-		| ARCH_PERFMON_NMI_EVENT_SEL
-		| ARCH_PERFMON_NMI_EVENT_UMASK;
-
-	/* setup the timer */
-	wrmsr(evntsel_msr, evntsel, 0);
-	nmi_hz = adjust_for_32bit_ctr(nmi_hz);
-	write_watchdog_counter32(perfctr_msr, "INTEL_ARCH_PERFCTR0", nmi_hz);
-
-	wd->perfctr_msr = perfctr_msr;
-	wd->evntsel_msr = evntsel_msr;
-	wd->cccr_msr = 0;  /* unused */
-
-	/* ok, everything is initialized, announce that we're set */
-	cpu_nmi_set_wd_enabled();
-
-	apic_write(APIC_LVTPC, APIC_DM_NMI);
-	evntsel |= ARCH_PERFMON_EVENTSEL_ENABLE;
-	wrmsr(evntsel_msr, evntsel, 0);
-	intel_arch_wd_ops.checkbit = 1ULL << (eax.split.bit_width - 1);
-	return 1;
-}
-
-static struct wd_ops intel_arch_wd_ops __read_mostly = {
-	.reserve	= single_msr_reserve,
-	.unreserve	= single_msr_unreserve,
-	.setup		= setup_intel_arch_watchdog,
-	.rearm		= p6_rearm,
-	.stop		= single_msr_stop_watchdog,
-	.perfctr	= MSR_ARCH_PERFMON_PERFCTR1,
-	.evntsel	= MSR_ARCH_PERFMON_EVENTSEL1,
-};
-
-static void probe_nmi_watchdog(void)
-{
-	switch (boot_cpu_data.x86_vendor) {
-	case X86_VENDOR_AMD:
-		if (boot_cpu_data.x86 == 6 ||
-		    (boot_cpu_data.x86 >= 0xf && boot_cpu_data.x86 <= 0x15))
-			wd_ops = &k7_wd_ops;
-		return;
-	case X86_VENDOR_INTEL:
-		/* Work around where perfctr1 doesn't have a working enable
-		 * bit as described in the following errata:
-		 * AE49 Core Duo and Intel Core Solo 65 nm
-		 * AN49 Intel Pentium Dual-Core
-		 * AF49 Dual-Core Intel Xeon Processor LV
-		 */
-		if ((boot_cpu_data.x86 == 6 && boot_cpu_data.x86_model == 14) ||
-		    ((boot_cpu_data.x86 == 6 && boot_cpu_data.x86_model == 15 &&
-		     boot_cpu_data.x86_mask == 4))) {
-			intel_arch_wd_ops.perfctr = MSR_ARCH_PERFMON_PERFCTR0;
-			intel_arch_wd_ops.evntsel = MSR_ARCH_PERFMON_EVENTSEL0;
-		}
-		if (cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON)) {
-			wd_ops = &intel_arch_wd_ops;
-			break;
-		}
-		switch (boot_cpu_data.x86) {
-		case 6:
-			if (boot_cpu_data.x86_model > 13)
-				return;
-
-			wd_ops = &p6_wd_ops;
-			break;
-		case 15:
-			wd_ops = &p4_wd_ops;
-			break;
-		default:
-			return;
-		}
-		break;
-	}
-}
-
-/* Interface to nmi.c */
-
-int lapic_watchdog_init(unsigned nmi_hz)
-{
-	if (!wd_ops) {
-		probe_nmi_watchdog();
-		if (!wd_ops) {
-			printk(KERN_INFO "NMI watchdog: CPU not supported\n");
-			return -1;
-		}
-
-		if (!wd_ops->reserve()) {
-			printk(KERN_ERR
-				"NMI watchdog: cannot reserve perfctrs\n");
-			return -1;
-		}
-	}
-
-	if (!(wd_ops->setup(nmi_hz))) {
-		printk(KERN_ERR "Cannot setup NMI watchdog on CPU %d\n",
-		       raw_smp_processor_id());
-		return -1;
-	}
-
-	return 0;
-}
-
-void lapic_watchdog_stop(void)
-{
-	if (wd_ops)
-		wd_ops->stop();
-}
-
-unsigned lapic_adjust_nmi_hz(unsigned hz)
-{
-	struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk);
-	if (wd->perfctr_msr == MSR_P6_PERFCTR0 ||
-	    wd->perfctr_msr == MSR_ARCH_PERFMON_PERFCTR1)
-		hz = adjust_for_32bit_ctr(hz);
-	return hz;
-}
-
-int __kprobes lapic_wd_event(unsigned nmi_hz)
-{
-	struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk);
-	u64 ctr;
-
-	rdmsrl(wd->perfctr_msr, ctr);
-	if (ctr & wd_ops->checkbit) /* perfctr still running? */
-		return 0;
-
-	wd_ops->rearm(wd, nmi_hz);
-	return 1;
-}
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/kernel/cpu/perf_event_amd.c linux-libre-2.6.38-gnu1/arch/x86/kernel/cpu/perf_event_amd.c
--- linux-libre-2.6.37-gnu1/arch/x86/kernel/cpu/perf_event_amd.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/kernel/cpu/perf_event_amd.c	2011-03-14 21:20:32.000000000 -0400
@@ -1,7 +1,5 @@
 #ifdef CONFIG_CPU_SUP_AMD
 
-static DEFINE_RAW_SPINLOCK(amd_nb_lock);
-
 static __initconst const u64 amd_hw_cache_event_ids
 				[PERF_COUNT_HW_CACHE_MAX]
 				[PERF_COUNT_HW_CACHE_OP_MAX]
@@ -275,7 +273,7 @@ done:
 	return &emptyconstraint;
 }
 
-static struct amd_nb *amd_alloc_nb(int cpu, int nb_id)
+static struct amd_nb *amd_alloc_nb(int cpu)
 {
 	struct amd_nb *nb;
 	int i;
@@ -285,7 +283,7 @@ static struct amd_nb *amd_alloc_nb(int c
 	if (!nb)
 		return NULL;
 
-	nb->nb_id = nb_id;
+	nb->nb_id = -1;
 
 	/*
 	 * initialize all possible NB constraints
@@ -306,7 +304,7 @@ static int amd_pmu_cpu_prepare(int cpu)
 	if (boot_cpu_data.x86_max_cores < 2)
 		return NOTIFY_OK;
 
-	cpuc->amd_nb = amd_alloc_nb(cpu, -1);
+	cpuc->amd_nb = amd_alloc_nb(cpu);
 	if (!cpuc->amd_nb)
 		return NOTIFY_BAD;
 
@@ -325,8 +323,6 @@ static void amd_pmu_cpu_starting(int cpu
 	nb_id = amd_get_nb_id(cpu);
 	WARN_ON_ONCE(nb_id == BAD_APICID);
 
-	raw_spin_lock(&amd_nb_lock);
-
 	for_each_online_cpu(i) {
 		nb = per_cpu(cpu_hw_events, i).amd_nb;
 		if (WARN_ON_ONCE(!nb))
@@ -341,8 +337,6 @@ static void amd_pmu_cpu_starting(int cpu
 
 	cpuc->amd_nb->nb_id = nb_id;
 	cpuc->amd_nb->refcnt++;
-
-	raw_spin_unlock(&amd_nb_lock);
 }
 
 static void amd_pmu_cpu_dead(int cpu)
@@ -354,8 +348,6 @@ static void amd_pmu_cpu_dead(int cpu)
 
 	cpuhw = &per_cpu(cpu_hw_events, cpu);
 
-	raw_spin_lock(&amd_nb_lock);
-
 	if (cpuhw->amd_nb) {
 		struct amd_nb *nb = cpuhw->amd_nb;
 
@@ -364,8 +356,6 @@ static void amd_pmu_cpu_dead(int cpu)
 
 		cpuhw->amd_nb = NULL;
 	}
-
-	raw_spin_unlock(&amd_nb_lock);
 }
 
 static __initconst const struct x86_pmu amd_pmu = {
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/kernel/cpu/perf_event.c linux-libre-2.6.38-gnu1/arch/x86/kernel/cpu/perf_event.c
--- linux-libre-2.6.37-gnu1/arch/x86/kernel/cpu/perf_event.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/kernel/cpu/perf_event.c	2011-03-14 21:20:32.000000000 -0400
@@ -330,9 +330,6 @@ static bool reserve_pmc_hardware(void)
 {
 	int i;
 
-	if (nmi_watchdog == NMI_LOCAL_APIC)
-		disable_lapic_nmi_watchdog();
-
 	for (i = 0; i < x86_pmu.num_counters; i++) {
 		if (!reserve_perfctr_nmi(x86_pmu.perfctr + i))
 			goto perfctr_fail;
@@ -355,9 +352,6 @@ perfctr_fail:
 	for (i--; i >= 0; i--)
 		release_perfctr_nmi(x86_pmu.perfctr + i);
 
-	if (nmi_watchdog == NMI_LOCAL_APIC)
-		enable_lapic_nmi_watchdog();
-
 	return false;
 }
 
@@ -369,9 +363,6 @@ static void release_pmc_hardware(void)
 		release_perfctr_nmi(x86_pmu.perfctr + i);
 		release_evntsel_nmi(x86_pmu.eventsel + i);
 	}
-
-	if (nmi_watchdog == NMI_LOCAL_APIC)
-		enable_lapic_nmi_watchdog();
 }
 
 #else
@@ -384,15 +375,53 @@ static void release_pmc_hardware(void) {
 static bool check_hw_exists(void)
 {
 	u64 val, val_new = 0;
-	int ret = 0;
+	int i, reg, ret = 0;
+
+	/*
+	 * Check to see if the BIOS enabled any of the counters, if so
+	 * complain and bail.
+	 */
+	for (i = 0; i < x86_pmu.num_counters; i++) {
+		reg = x86_pmu.eventsel + i;
+		ret = rdmsrl_safe(reg, &val);
+		if (ret)
+			goto msr_fail;
+		if (val & ARCH_PERFMON_EVENTSEL_ENABLE)
+			goto bios_fail;
+	}
+
+	if (x86_pmu.num_counters_fixed) {
+		reg = MSR_ARCH_PERFMON_FIXED_CTR_CTRL;
+		ret = rdmsrl_safe(reg, &val);
+		if (ret)
+			goto msr_fail;
+		for (i = 0; i < x86_pmu.num_counters_fixed; i++) {
+			if (val & (0x03 << i*4))
+				goto bios_fail;
+		}
+	}
 
+	/*
+	 * Now write a value and read it back to see if it matches,
+	 * this is needed to detect certain hardware emulators (qemu/kvm)
+	 * that don't trap on the MSR access and always return 0s.
+	 */
 	val = 0xabcdUL;
-	ret |= checking_wrmsrl(x86_pmu.perfctr, val);
+	ret = checking_wrmsrl(x86_pmu.perfctr, val);
 	ret |= rdmsrl_safe(x86_pmu.perfctr, &val_new);
 	if (ret || val != val_new)
-		return false;
+		goto msr_fail;
 
 	return true;
+
+bios_fail:
+	printk(KERN_CONT "Broken BIOS detected, using software events only.\n");
+	printk(KERN_ERR FW_BUG "the BIOS has corrupted hw-PMU resources (MSR %x is %Lx)\n", reg, val);
+	return false;
+
+msr_fail:
+	printk(KERN_CONT "Broken PMU hardware detected, using software events only.\n");
+	return false;
 }
 
 static void reserve_ds_buffers(void);
@@ -451,7 +480,7 @@ static int x86_setup_perfctr(struct perf
 	struct hw_perf_event *hwc = &event->hw;
 	u64 config;
 
-	if (!hwc->sample_period) {
+	if (!is_sampling_event(event)) {
 		hwc->sample_period = x86_pmu.max_period;
 		hwc->last_period = hwc->sample_period;
 		local64_set(&hwc->period_left, hwc->sample_period);
@@ -968,8 +997,7 @@ x86_perf_event_set_period(struct perf_ev
 
 static void x86_pmu_enable_event(struct perf_event *event)
 {
-	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
-	if (cpuc->enabled)
+	if (__this_cpu_read(cpu_hw_events.enabled))
 		__x86_pmu_enable_event(&event->hw,
 				       ARCH_PERFMON_EVENTSEL_ENABLE);
 }
@@ -1239,11 +1267,10 @@ perf_event_nmi_handler(struct notifier_b
 
 	switch (cmd) {
 	case DIE_NMI:
-	case DIE_NMI_IPI:
 		break;
 	case DIE_NMIUNKNOWN:
 		this_nmi = percpu_read(irq_stat.__nmi_count);
-		if (this_nmi != __get_cpu_var(pmu_nmi).marked)
+		if (this_nmi != __this_cpu_read(pmu_nmi.marked))
 			/* let the kernel handle the unknown nmi */
 			return NOTIFY_DONE;
 		/*
@@ -1267,8 +1294,8 @@ perf_event_nmi_handler(struct notifier_b
 	this_nmi = percpu_read(irq_stat.__nmi_count);
 	if ((handled > 1) ||
 		/* the next nmi could be a back-to-back nmi */
-	    ((__get_cpu_var(pmu_nmi).marked == this_nmi) &&
-	     (__get_cpu_var(pmu_nmi).handled > 1))) {
+	    ((__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
@@ -1279,8 +1306,8 @@ perf_event_nmi_handler(struct notifier_b
 		 * handling more than one counter. We will mark the
 		 * next (3rd) and then drop it if unhandled.
 		 */
-		__get_cpu_var(pmu_nmi).marked	= this_nmi + 1;
-		__get_cpu_var(pmu_nmi).handled	= handled;
+		__this_cpu_write(pmu_nmi.marked, this_nmi + 1);
+		__this_cpu_write(pmu_nmi.handled, handled);
 	}
 
 	return NOTIFY_STOP;
@@ -1289,7 +1316,7 @@ perf_event_nmi_handler(struct notifier_b
 static __read_mostly struct notifier_block perf_event_nmi_notifier = {
 	.notifier_call		= perf_event_nmi_handler,
 	.next			= NULL,
-	.priority		= 1
+	.priority		= NMI_LOCAL_LOW_PRIOR,
 };
 
 static struct event_constraint unconstrained;
@@ -1362,7 +1389,7 @@ static void __init pmu_check_apic(void)
 	pr_info("no hardware sampling interrupt available.\n");
 }
 
-void __init init_hw_perf_events(void)
+int __init init_hw_perf_events(void)
 {
 	struct event_constraint *c;
 	int err;
@@ -1377,20 +1404,18 @@ void __init init_hw_perf_events(void)
 		err = amd_pmu_init();
 		break;
 	default:
-		return;
+		return 0;
 	}
 	if (err != 0) {
 		pr_cont("no PMU driver, software events only.\n");
-		return;
+		return 0;
 	}
 
 	pmu_check_apic();
 
 	/* sanity check that the hardware exists or is emulated */
-	if (!check_hw_exists()) {
-		pr_cont("Broken PMU hardware detected, software events only.\n");
-		return;
-	}
+	if (!check_hw_exists())
+		return 0;
 
 	pr_cont("%s PMU driver.\n", x86_pmu.name);
 
@@ -1438,9 +1463,12 @@ void __init init_hw_perf_events(void)
 	pr_info("... fixed-purpose events:   %d\n",     x86_pmu.num_counters_fixed);
 	pr_info("... event mask:             %016Lx\n", x86_pmu.intel_ctrl);
 
-	perf_pmu_register(&pmu);
+	perf_pmu_register(&pmu, "cpu", PERF_TYPE_RAW);
 	perf_cpu_notifier(x86_pmu_notifier);
+
+	return 0;
 }
+early_initcall(init_hw_perf_events);
 
 static inline void x86_pmu_read(struct perf_event *event)
 {
@@ -1454,11 +1482,9 @@ static inline void x86_pmu_read(struct p
  */
 static void x86_pmu_start_txn(struct pmu *pmu)
 {
-	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
-
 	perf_pmu_disable(pmu);
-	cpuc->group_flag |= PERF_EVENT_TXN;
-	cpuc->n_txn = 0;
+	__this_cpu_or(cpu_hw_events.group_flag, PERF_EVENT_TXN);
+	__this_cpu_write(cpu_hw_events.n_txn, 0);
 }
 
 /*
@@ -1468,14 +1494,12 @@ static void x86_pmu_start_txn(struct pmu
  */
 static void x86_pmu_cancel_txn(struct pmu *pmu)
 {
-	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
-
-	cpuc->group_flag &= ~PERF_EVENT_TXN;
+	__this_cpu_and(cpu_hw_events.group_flag, ~PERF_EVENT_TXN);
 	/*
 	 * Truncate the collected events.
 	 */
-	cpuc->n_added -= cpuc->n_txn;
-	cpuc->n_events -= cpuc->n_txn;
+	__this_cpu_sub(cpu_hw_events.n_added, __this_cpu_read(cpu_hw_events.n_txn));
+	__this_cpu_sub(cpu_hw_events.n_events, __this_cpu_read(cpu_hw_events.n_txn));
 	perf_pmu_enable(pmu);
 }
 
@@ -1686,7 +1710,7 @@ perf_callchain_kernel(struct perf_callch
 
 	perf_callchain_store(entry, regs->ip);
 
-	dump_trace(NULL, regs, NULL, regs->bp, &backtrace_ops, entry);
+	dump_trace(NULL, regs, NULL, &backtrace_ops, entry);
 }
 
 #ifdef CONFIG_COMPAT
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/kernel/cpu/perf_event_intel.c linux-libre-2.6.38-gnu1/arch/x86/kernel/cpu/perf_event_intel.c
--- linux-libre-2.6.37-gnu1/arch/x86/kernel/cpu/perf_event_intel.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/kernel/cpu/perf_event_intel.c	2011-03-14 21:20:32.000000000 -0400
@@ -649,7 +649,7 @@ static void intel_pmu_enable_event(struc
 	struct hw_perf_event *hwc = &event->hw;
 
 	if (unlikely(hwc->idx == X86_PMC_IDX_FIXED_BTS)) {
-		if (!__get_cpu_var(cpu_hw_events).enabled)
+		if (!__this_cpu_read(cpu_hw_events.enabled))
 			return;
 
 		intel_pmu_enable_bts(hwc->config);
@@ -679,7 +679,7 @@ static int intel_pmu_save_and_restart(st
 
 static void intel_pmu_reset(void)
 {
-	struct debug_store *ds = __get_cpu_var(cpu_hw_events).ds;
+	struct debug_store *ds = __this_cpu_read(cpu_hw_events.ds);
 	unsigned long flags;
 	int idx;
 
@@ -816,6 +816,32 @@ static int intel_pmu_hw_config(struct pe
 	if (ret)
 		return ret;
 
+	if (event->attr.precise_ip &&
+	    (event->hw.config & X86_RAW_EVENT_MASK) == 0x003c) {
+		/*
+		 * Use an alternative encoding for CPU_CLK_UNHALTED.THREAD_P
+		 * (0x003c) so that we can use it with PEBS.
+		 *
+		 * The regular CPU_CLK_UNHALTED.THREAD_P event (0x003c) isn't
+		 * PEBS capable. However we can use INST_RETIRED.ANY_P
+		 * (0x00c0), which is a PEBS capable event, to get the same
+		 * count.
+		 *
+		 * INST_RETIRED.ANY_P counts the number of cycles that retires
+		 * CNTMASK instructions. By setting CNTMASK to a value (16)
+		 * larger than the maximum number of instructions that can be
+		 * retired per cycle (4) and then inverting the condition, we
+		 * count all cycles that retire 16 or less instructions, which
+		 * is every cycle.
+		 *
+		 * Thereby we gain a PEBS capable cycle counter.
+		 */
+		u64 alt_config = 0x108000c0; /* INST_RETIRED.TOTAL_CYCLES */
+
+		alt_config |= (event->hw.config & ~X86_RAW_EVENT_MASK);
+		event->hw.config = alt_config;
+	}
+
 	if (event->attr.type != PERF_TYPE_RAW)
 		return 0;
 
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/kernel/cpu/perf_event_p4.c linux-libre-2.6.38-gnu1/arch/x86/kernel/cpu/perf_event_p4.c
--- linux-libre-2.6.37-gnu1/arch/x86/kernel/cpu/perf_event_p4.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/kernel/cpu/perf_event_p4.c	2011-03-14 21:20:32.000000000 -0400
@@ -682,7 +682,7 @@ static int p4_validate_raw_event(struct
 	 * if an event is shared accross the logical threads
 	 * the user needs special permissions to be able to use it
 	 */
-	if (p4_event_bind_map[v].shared) {
+	if (p4_ht_active() && p4_event_bind_map[v].shared) {
 		if (perf_paranoid_cpu() && !capable(CAP_SYS_ADMIN))
 			return -EACCES;
 	}
@@ -727,7 +727,8 @@ static int p4_hw_config(struct perf_even
 		event->hw.config = p4_set_ht_bit(event->hw.config);
 
 	if (event->attr.type == PERF_TYPE_RAW) {
-
+		struct p4_event_bind *bind;
+		unsigned int esel;
 		/*
 		 * Clear bits we reserve to be managed by kernel itself
 		 * and never allowed from a user space
@@ -743,6 +744,13 @@ static int p4_hw_config(struct perf_even
 		 * bits since we keep additional info here (for cache events and etc)
 		 */
 		event->hw.config |= event->attr.config;
+		bind = p4_config_get_bind(event->attr.config);
+		if (!bind) {
+			rc = -EINVAL;
+			goto out;
+		}
+		esel = P4_OPCODE_ESEL(bind->opcode);
+		event->hw.config |= p4_config_pack_cccr(P4_CCCR_ESEL(esel));
 	}
 
 	rc = x86_setup_perfctr(event);
@@ -753,19 +761,26 @@ out:
 
 static inline int p4_pmu_clear_cccr_ovf(struct hw_perf_event *hwc)
 {
-	int overflow = 0;
-	u32 low, high;
-
-	rdmsr(hwc->config_base + hwc->idx, low, high);
+	u64 v;
 
-	/* we need to check high bit for unflagged overflows */
-	if ((low & P4_CCCR_OVF) || !(high & (1 << 31))) {
-		overflow = 1;
-		(void)checking_wrmsrl(hwc->config_base + hwc->idx,
-			((u64)low) & ~P4_CCCR_OVF);
+	/* an official way for overflow indication */
+	rdmsrl(hwc->config_base + hwc->idx, v);
+	if (v & P4_CCCR_OVF) {
+		wrmsrl(hwc->config_base + hwc->idx, v & ~P4_CCCR_OVF);
+		return 1;
 	}
 
-	return overflow;
+	/*
+	 * In some circumstances the overflow might issue an NMI but did
+	 * not set P4_CCCR_OVF bit. Because a counter holds a negative value
+	 * we simply check for high bit being set, if it's cleared it means
+	 * the counter has reached zero value and continued counting before
+	 * real NMI signal was received:
+	 */
+	if (!(v & ARCH_P4_UNFLAGGED_BIT))
+		return 1;
+
+	return 0;
 }
 
 static void p4_pmu_disable_pebs(void)
@@ -1152,9 +1167,9 @@ static __initconst const struct x86_pmu
 	 */
 	.num_counters		= ARCH_P4_MAX_CCCR,
 	.apic			= 1,
-	.cntval_bits		= 40,
-	.cntval_mask		= (1ULL << 40) - 1,
-	.max_period		= (1ULL << 39) - 1,
+	.cntval_bits		= ARCH_P4_CNTRVAL_BITS,
+	.cntval_mask		= ARCH_P4_CNTRVAL_MASK,
+	.max_period		= (1ULL << (ARCH_P4_CNTRVAL_BITS - 1)) - 1,
 	.hw_config		= p4_hw_config,
 	.schedule_events	= p4_pmu_schedule_events,
 	/*
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/kernel/dumpstack_32.c linux-libre-2.6.38-gnu1/arch/x86/kernel/dumpstack_32.c
--- linux-libre-2.6.37-gnu1/arch/x86/kernel/dumpstack_32.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/kernel/dumpstack_32.c	2011-03-14 21:20:32.000000000 -0400
@@ -17,11 +17,12 @@
 #include <asm/stacktrace.h>
 
 
-void dump_trace(struct task_struct *task, struct pt_regs *regs,
-		unsigned long *stack, unsigned long bp,
+void dump_trace(struct task_struct *task,
+		struct pt_regs *regs, unsigned long *stack,
 		const struct stacktrace_ops *ops, void *data)
 {
 	int graph = 0;
+	unsigned long bp;
 
 	if (!task)
 		task = current;
@@ -34,18 +35,7 @@ void dump_trace(struct task_struct *task
 			stack = (unsigned long *)task->thread.sp;
 	}
 
-#ifdef CONFIG_FRAME_POINTER
-	if (!bp) {
-		if (task == current) {
-			/* Grab bp right from our regs */
-			get_bp(bp);
-		} else {
-			/* bp is the last reg pushed by switch_to */
-			bp = *(unsigned long *) task->thread.sp;
-		}
-	}
-#endif
-
+	bp = stack_frame(task, regs);
 	for (;;) {
 		struct thread_info *context;
 
@@ -65,7 +55,7 @@ EXPORT_SYMBOL(dump_trace);
 
 void
 show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs,
-		   unsigned long *sp, unsigned long bp, char *log_lvl)
+		   unsigned long *sp, char *log_lvl)
 {
 	unsigned long *stack;
 	int i;
@@ -87,7 +77,7 @@ show_stack_log_lvl(struct task_struct *t
 		touch_nmi_watchdog();
 	}
 	printk(KERN_CONT "\n");
-	show_trace_log_lvl(task, regs, sp, bp, log_lvl);
+	show_trace_log_lvl(task, regs, sp, log_lvl);
 }
 
 
@@ -112,8 +102,7 @@ void show_registers(struct pt_regs *regs
 		u8 *ip;
 
 		printk(KERN_EMERG "Stack:\n");
-		show_stack_log_lvl(NULL, regs, &regs->sp,
-				0, KERN_EMERG);
+		show_stack_log_lvl(NULL, regs, &regs->sp, KERN_EMERG);
 
 		printk(KERN_EMERG "Code: ");
 
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/kernel/dumpstack_64.c linux-libre-2.6.38-gnu1/arch/x86/kernel/dumpstack_64.c
--- linux-libre-2.6.37-gnu1/arch/x86/kernel/dumpstack_64.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/kernel/dumpstack_64.c	2011-03-14 21:20:32.000000000 -0400
@@ -139,8 +139,8 @@ fixup_bp_irq_link(unsigned long bp, unsi
  * severe exception (double fault, nmi, stack fault, debug, mce) hardware stack
  */
 
-void dump_trace(struct task_struct *task, struct pt_regs *regs,
-		unsigned long *stack, unsigned long bp,
+void dump_trace(struct task_struct *task,
+		struct pt_regs *regs, unsigned long *stack,
 		const struct stacktrace_ops *ops, void *data)
 {
 	const unsigned cpu = get_cpu();
@@ -149,29 +149,19 @@ void dump_trace(struct task_struct *task
 	unsigned used = 0;
 	struct thread_info *tinfo;
 	int graph = 0;
+	unsigned long dummy;
+	unsigned long bp;
 
 	if (!task)
 		task = current;
 
 	if (!stack) {
-		unsigned long dummy;
 		stack = &dummy;
 		if (task && task != current)
 			stack = (unsigned long *)task->thread.sp;
 	}
 
-#ifdef CONFIG_FRAME_POINTER
-	if (!bp) {
-		if (task == current) {
-			/* Grab bp right from our regs */
-			get_bp(bp);
-		} else {
-			/* bp is the last reg pushed by switch_to */
-			bp = *(unsigned long *) task->thread.sp;
-		}
-	}
-#endif
-
+	bp = stack_frame(task, regs);
 	/*
 	 * Print function call entries in all stacks, starting at the
 	 * current stack address. If the stacks consist of nested
@@ -235,7 +225,7 @@ EXPORT_SYMBOL(dump_trace);
 
 void
 show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs,
-		   unsigned long *sp, unsigned long bp, char *log_lvl)
+		   unsigned long *sp, char *log_lvl)
 {
 	unsigned long *irq_stack_end;
 	unsigned long *irq_stack;
@@ -279,7 +269,7 @@ show_stack_log_lvl(struct task_struct *t
 	preempt_enable();
 
 	printk(KERN_CONT "\n");
-	show_trace_log_lvl(task, regs, sp, bp, log_lvl);
+	show_trace_log_lvl(task, regs, sp, log_lvl);
 }
 
 void show_registers(struct pt_regs *regs)
@@ -308,7 +298,7 @@ void show_registers(struct pt_regs *regs
 
 		printk(KERN_EMERG "Stack:\n");
 		show_stack_log_lvl(NULL, regs, (unsigned long *)sp,
-				regs->bp, KERN_EMERG);
+				   KERN_EMERG);
 
 		printk(KERN_EMERG "Code: ");
 
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/kernel/dumpstack.c linux-libre-2.6.38-gnu1/arch/x86/kernel/dumpstack.c
--- linux-libre-2.6.37-gnu1/arch/x86/kernel/dumpstack.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/kernel/dumpstack.c	2011-03-14 21:20:32.000000000 -0400
@@ -175,21 +175,21 @@ static const struct stacktrace_ops print
 
 void
 show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs,
-		unsigned long *stack, unsigned long bp, char *log_lvl)
+		unsigned long *stack, char *log_lvl)
 {
 	printk("%sCall Trace:\n", log_lvl);
-	dump_trace(task, regs, stack, bp, &print_trace_ops, log_lvl);
+	dump_trace(task, regs, stack, &print_trace_ops, log_lvl);
 }
 
 void show_trace(struct task_struct *task, struct pt_regs *regs,
-		unsigned long *stack, unsigned long bp)
+		unsigned long *stack)
 {
-	show_trace_log_lvl(task, regs, stack, bp, "");
+	show_trace_log_lvl(task, regs, stack, "");
 }
 
 void show_stack(struct task_struct *task, unsigned long *sp)
 {
-	show_stack_log_lvl(task, NULL, sp, 0, "");
+	show_stack_log_lvl(task, NULL, sp, "");
 }
 
 /*
@@ -197,20 +197,14 @@ void show_stack(struct task_struct *task
  */
 void dump_stack(void)
 {
-	unsigned long bp = 0;
 	unsigned long stack;
 
-#ifdef CONFIG_FRAME_POINTER
-	if (!bp)
-		get_bp(bp);
-#endif
-
 	printk("Pid: %d, comm: %.20s %s %s %.*s\n",
 		current->pid, current->comm, print_tainted(),
 		init_utsname()->release,
 		(int)strcspn(init_utsname()->version, " "),
 		init_utsname()->version);
-	show_trace(NULL, NULL, &stack, bp);
+	show_trace(NULL, NULL, &stack);
 }
 EXPORT_SYMBOL(dump_stack);
 
@@ -240,6 +234,7 @@ unsigned __kprobes long oops_begin(void)
 	bust_spinlocks(1);
 	return flags;
 }
+EXPORT_SYMBOL_GPL(oops_begin);
 
 void __kprobes oops_end(unsigned long flags, struct pt_regs *regs, int signr)
 {
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/kernel/e820.c linux-libre-2.6.38-gnu1/arch/x86/kernel/e820.c
--- linux-libre-2.6.37-gnu1/arch/x86/kernel/e820.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/kernel/e820.c	2011-03-14 21:20:32.000000000 -0400
@@ -14,6 +14,7 @@
 #include <linux/bootmem.h>
 #include <linux/pfn.h>
 #include <linux/suspend.h>
+#include <linux/acpi.h>
 #include <linux/firmware-map.h>
 #include <linux/memblock.h>
 
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/kernel/early_printk.c linux-libre-2.6.38-gnu1/arch/x86/kernel/early_printk.c
--- linux-libre-2.6.37-gnu1/arch/x86/kernel/early_printk.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/kernel/early_printk.c	2011-03-14 21:20:32.000000000 -0400
@@ -240,7 +240,7 @@ static int __init setup_early_printk(cha
 		if (!strncmp(buf, "xen", 3))
 			early_console_register(&xenboot_console, keep);
 #endif
-#ifdef CONFIG_X86_MRST_EARLY_PRINTK
+#ifdef CONFIG_EARLY_PRINTK_MRST
 		if (!strncmp(buf, "mrst", 4)) {
 			mrst_early_console_init();
 			early_console_register(&early_mrst_console, keep);
@@ -250,7 +250,6 @@ static int __init setup_early_printk(cha
 			hsu_early_console_init();
 			early_console_register(&early_hsu_console, keep);
 		}
-
 #endif
 		buf++;
 	}
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/kernel/early_printk_mrst.c linux-libre-2.6.38-gnu1/arch/x86/kernel/early_printk_mrst.c
--- linux-libre-2.6.37-gnu1/arch/x86/kernel/early_printk_mrst.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/kernel/early_printk_mrst.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,319 +0,0 @@
-/*
- * early_printk_mrst.c - early consoles for Intel MID platforms
- *
- * Copyright (c) 2008-2010, 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; version 2
- * of the License.
- */
-
-/*
- * This file implements two early consoles named mrst and hsu.
- * mrst is based on Maxim3110 spi-uart device, it exists in both
- * Moorestown and Medfield platforms, while hsu is based on a High
- * Speed UART device which only exists in the Medfield platform
- */
-
-#include <linux/serial_reg.h>
-#include <linux/serial_mfd.h>
-#include <linux/kmsg_dump.h>
-#include <linux/console.h>
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/io.h>
-
-#include <asm/fixmap.h>
-#include <asm/pgtable.h>
-#include <asm/mrst.h>
-
-#define MRST_SPI_TIMEOUT		0x200000
-#define MRST_REGBASE_SPI0		0xff128000
-#define MRST_REGBASE_SPI1		0xff128400
-#define MRST_CLK_SPI0_REG		0xff11d86c
-
-/* Bit fields in CTRLR0 */
-#define SPI_DFS_OFFSET			0
-
-#define SPI_FRF_OFFSET			4
-#define SPI_FRF_SPI			0x0
-#define SPI_FRF_SSP			0x1
-#define SPI_FRF_MICROWIRE		0x2
-#define SPI_FRF_RESV			0x3
-
-#define SPI_MODE_OFFSET			6
-#define SPI_SCPH_OFFSET			6
-#define SPI_SCOL_OFFSET			7
-#define SPI_TMOD_OFFSET			8
-#define	SPI_TMOD_TR			0x0		/* xmit & recv */
-#define SPI_TMOD_TO			0x1		/* xmit only */
-#define SPI_TMOD_RO			0x2		/* recv only */
-#define SPI_TMOD_EPROMREAD		0x3		/* eeprom read mode */
-
-#define SPI_SLVOE_OFFSET		10
-#define SPI_SRL_OFFSET			11
-#define SPI_CFS_OFFSET			12
-
-/* Bit fields in SR, 7 bits */
-#define SR_MASK				0x7f		/* cover 7 bits */
-#define SR_BUSY				(1 << 0)
-#define SR_TF_NOT_FULL			(1 << 1)
-#define SR_TF_EMPT			(1 << 2)
-#define SR_RF_NOT_EMPT			(1 << 3)
-#define SR_RF_FULL			(1 << 4)
-#define SR_TX_ERR			(1 << 5)
-#define SR_DCOL				(1 << 6)
-
-struct dw_spi_reg {
-	u32	ctrl0;
-	u32	ctrl1;
-	u32	ssienr;
-	u32	mwcr;
-	u32	ser;
-	u32	baudr;
-	u32	txfltr;
-	u32	rxfltr;
-	u32	txflr;
-	u32	rxflr;
-	u32	sr;
-	u32	imr;
-	u32	isr;
-	u32	risr;
-	u32	txoicr;
-	u32	rxoicr;
-	u32	rxuicr;
-	u32	msticr;
-	u32	icr;
-	u32	dmacr;
-	u32	dmatdlr;
-	u32	dmardlr;
-	u32	idr;
-	u32	version;
-
-	/* Currently operates as 32 bits, though only the low 16 bits matter */
-	u32	dr;
-} __packed;
-
-#define dw_readl(dw, name)		__raw_readl(&(dw)->name)
-#define dw_writel(dw, name, val)	__raw_writel((val), &(dw)->name)
-
-/* Default use SPI0 register for mrst, we will detect Penwell and use SPI1 */
-static unsigned long mrst_spi_paddr = MRST_REGBASE_SPI0;
-
-static u32 *pclk_spi0;
-/* Always contains an accessable address, start with 0 */
-static struct dw_spi_reg *pspi;
-
-static struct kmsg_dumper dw_dumper;
-static int dumper_registered;
-
-static void dw_kmsg_dump(struct kmsg_dumper *dumper,
-			enum kmsg_dump_reason reason,
-			const char *s1, unsigned long l1,
-			const char *s2, unsigned long l2)
-{
-	int i;
-
-	/* When run to this, we'd better re-init the HW */
-	mrst_early_console_init();
-
-	for (i = 0; i < l1; i++)
-		early_mrst_console.write(&early_mrst_console, s1 + i, 1);
-	for (i = 0; i < l2; i++)
-		early_mrst_console.write(&early_mrst_console, s2 + i, 1);
-}
-
-/* Set the ratio rate to 115200, 8n1, IRQ disabled */
-static void max3110_write_config(void)
-{
-	u16 config;
-
-	config = 0xc001;
-	dw_writel(pspi, dr, config);
-}
-
-/* Translate char to a eligible word and send to max3110 */
-static void max3110_write_data(char c)
-{
-	u16 data;
-
-	data = 0x8000 | c;
-	dw_writel(pspi, dr, data);
-}
-
-void mrst_early_console_init(void)
-{
-	u32 ctrlr0 = 0;
-	u32 spi0_cdiv;
-	u32 freq; /* Freqency info only need be searched once */
-
-	/* Base clk is 100 MHz, the actual clk = 100M / (clk_divider + 1) */
-	pclk_spi0 = (void *)set_fixmap_offset_nocache(FIX_EARLYCON_MEM_BASE,
-							MRST_CLK_SPI0_REG);
-	spi0_cdiv = ((*pclk_spi0) & 0xe00) >> 9;
-	freq = 100000000 / (spi0_cdiv + 1);
-
-	if (mrst_identify_cpu() == MRST_CPU_CHIP_PENWELL)
-		mrst_spi_paddr = MRST_REGBASE_SPI1;
-
-	pspi = (void *)set_fixmap_offset_nocache(FIX_EARLYCON_MEM_BASE,
-						mrst_spi_paddr);
-
-	/* Disable SPI controller */
-	dw_writel(pspi, ssienr, 0);
-
-	/* Set control param, 8 bits, transmit only mode */
-	ctrlr0 = dw_readl(pspi, ctrl0);
-
-	ctrlr0 &= 0xfcc0;
-	ctrlr0 |= 0xf | (SPI_FRF_SPI << SPI_FRF_OFFSET)
-		      | (SPI_TMOD_TO << SPI_TMOD_OFFSET);
-	dw_writel(pspi, ctrl0, ctrlr0);
-
-	/*
-	 * Change the spi0 clk to comply with 115200 bps, use 100000 to
-	 * calculate the clk dividor to make the clock a little slower
-	 * than real baud rate.
-	 */
-	dw_writel(pspi, baudr, freq/100000);
-
-	/* Disable all INT for early phase */
-	dw_writel(pspi, imr, 0x0);
-
-	/* Set the cs to spi-uart */
-	dw_writel(pspi, ser, 0x2);
-
-	/* Enable the HW, the last step for HW init */
-	dw_writel(pspi, ssienr, 0x1);
-
-	/* Set the default configuration */
-	max3110_write_config();
-
-	/* Register the kmsg dumper */
-	if (!dumper_registered) {
-		dw_dumper.dump = dw_kmsg_dump;
-		kmsg_dump_register(&dw_dumper);
-		dumper_registered = 1;
-	}
-}
-
-/* Slave select should be called in the read/write function */
-static void early_mrst_spi_putc(char c)
-{
-	unsigned int timeout;
-	u32 sr;
-
-	timeout = MRST_SPI_TIMEOUT;
-	/* Early putc needs to make sure the TX FIFO is not full */
-	while (--timeout) {
-		sr = dw_readl(pspi, sr);
-		if (!(sr & SR_TF_NOT_FULL))
-			cpu_relax();
-		else
-			break;
-	}
-
-	if (!timeout)
-		pr_warning("MRST earlycon: timed out\n");
-	else
-		max3110_write_data(c);
-}
-
-/* Early SPI only uses polling mode */
-static void early_mrst_spi_write(struct console *con, const char *str, unsigned n)
-{
-	int i;
-
-	for (i = 0; i < n && *str; i++) {
-		if (*str == '\n')
-			early_mrst_spi_putc('\r');
-		early_mrst_spi_putc(*str);
-		str++;
-	}
-}
-
-struct console early_mrst_console = {
-	.name =		"earlymrst",
-	.write =	early_mrst_spi_write,
-	.flags =	CON_PRINTBUFFER,
-	.index =	-1,
-};
-
-/*
- * Following is the early console based on Medfield HSU (High
- * Speed UART) device.
- */
-#define HSU_PORT2_PADDR		0xffa28180
-
-static void __iomem *phsu;
-
-void hsu_early_console_init(void)
-{
-	u8 lcr;
-
-	phsu = (void *)set_fixmap_offset_nocache(FIX_EARLYCON_MEM_BASE,
-							HSU_PORT2_PADDR);
-
-	/* Disable FIFO */
-	writeb(0x0, phsu + UART_FCR);
-
-	/* Set to default 115200 bps, 8n1 */
-	lcr = readb(phsu + UART_LCR);
-	writeb((0x80 | lcr), phsu + UART_LCR);
-	writeb(0x18, phsu + UART_DLL);
-	writeb(lcr,  phsu + UART_LCR);
-	writel(0x3600, phsu + UART_MUL*4);
-
-	writeb(0x8, phsu + UART_MCR);
-	writeb(0x7, phsu + UART_FCR);
-	writeb(0x3, phsu + UART_LCR);
-
-	/* Clear IRQ status */
-	readb(phsu + UART_LSR);
-	readb(phsu + UART_RX);
-	readb(phsu + UART_IIR);
-	readb(phsu + UART_MSR);
-
-	/* Enable FIFO */
-	writeb(0x7, phsu + UART_FCR);
-}
-
-#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
-
-static void early_hsu_putc(char ch)
-{
-	unsigned int timeout = 10000; /* 10ms */
-	u8 status;
-
-	while (--timeout) {
-		status = readb(phsu + UART_LSR);
-		if (status & BOTH_EMPTY)
-			break;
-		udelay(1);
-	}
-
-	/* Only write the char when there was no timeout */
-	if (timeout)
-		writeb(ch, phsu + UART_TX);
-}
-
-static void early_hsu_write(struct console *con, const char *str, unsigned n)
-{
-	int i;
-
-	for (i = 0; i < n && *str; i++) {
-		if (*str == '\n')
-			early_hsu_putc('\r');
-		early_hsu_putc(*str);
-		str++;
-	}
-}
-
-struct console early_hsu_console = {
-	.name =		"earlyhsu",
-	.write =	early_hsu_write,
-	.flags =	CON_PRINTBUFFER,
-	.index =	-1,
-};
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/kernel/early-quirks.c linux-libre-2.6.38-gnu1/arch/x86/kernel/early-quirks.c
--- linux-libre-2.6.37-gnu1/arch/x86/kernel/early-quirks.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/kernel/early-quirks.c	2011-03-14 21:20:32.000000000 -0400
@@ -143,15 +143,10 @@ static void __init ati_bugs(int num, int
 
 static u32 __init ati_sbx00_rev(int num, int slot, int func)
 {
-	u32 old, d;
+	u32 d;
 
-	d = read_pci_config(num, slot, func, 0x70);
-	old = d;
-	d &= ~(1<<8);
-	write_pci_config(num, slot, func, 0x70, d);
 	d = read_pci_config(num, slot, func, 0x8);
 	d &= 0xff;
-	write_pci_config(num, slot, func, 0x70, old);
 
 	return d;
 }
@@ -160,13 +155,16 @@ static void __init ati_bugs_contd(int nu
 {
 	u32 d, rev;
 
-	if (acpi_use_timer_override)
-		return;
-
 	rev = ati_sbx00_rev(num, slot, func);
+	if (rev >= 0x40)
+		acpi_fix_pin2_polarity = 1;
+
 	if (rev > 0x13)
 		return;
 
+	if (acpi_use_timer_override)
+		return;
+
 	/* check for IRQ0 interrupt swap */
 	d = read_pci_config(num, slot, func, 0x64);
 	if (!(d & (1<<14)))
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/kernel/entry_32.S linux-libre-2.6.38-gnu1/arch/x86/kernel/entry_32.S
--- linux-libre-2.6.37-gnu1/arch/x86/kernel/entry_32.S	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/kernel/entry_32.S	2011-03-14 21:20:32.000000000 -0400
@@ -1406,6 +1406,16 @@ ENTRY(general_protection)
 	CFI_ENDPROC
 END(general_protection)
 
+#ifdef CONFIG_KVM_GUEST
+ENTRY(async_page_fault)
+	RING0_EC_FRAME
+	pushl $do_async_page_fault
+	CFI_ADJUST_CFA_OFFSET 4
+	jmp error_code
+	CFI_ENDPROC
+END(apf_page_fault)
+#endif
+
 /*
  * End of kprobes section
  */
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/kernel/entry_64.S linux-libre-2.6.38-gnu1/arch/x86/kernel/entry_64.S
--- linux-libre-2.6.37-gnu1/arch/x86/kernel/entry_64.S	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/kernel/entry_64.S	2011-03-14 21:20:32.000000000 -0400
@@ -299,17 +299,21 @@ ENDPROC(native_usergs_sysret64)
 ENTRY(save_args)
 	XCPT_FRAME
 	cld
-	movq_cfi rdi, RDI+16-ARGOFFSET
-	movq_cfi rsi, RSI+16-ARGOFFSET
-	movq_cfi rdx, RDX+16-ARGOFFSET
-	movq_cfi rcx, RCX+16-ARGOFFSET
-	movq_cfi rax, RAX+16-ARGOFFSET
-	movq_cfi  r8,  R8+16-ARGOFFSET
-	movq_cfi  r9,  R9+16-ARGOFFSET
-	movq_cfi r10, R10+16-ARGOFFSET
-	movq_cfi r11, R11+16-ARGOFFSET
+	/*
+	 * start from rbp in pt_regs and jump over
+	 * return address.
+	 */
+	movq_cfi rdi, RDI+8-RBP
+	movq_cfi rsi, RSI+8-RBP
+	movq_cfi rdx, RDX+8-RBP
+	movq_cfi rcx, RCX+8-RBP
+	movq_cfi rax, RAX+8-RBP
+	movq_cfi  r8,  R8+8-RBP
+	movq_cfi  r9,  R9+8-RBP
+	movq_cfi r10, R10+8-RBP
+	movq_cfi r11, R11+8-RBP
 
-	leaq -ARGOFFSET+16(%rsp),%rdi	/* arg1 for handler */
+	leaq -RBP+8(%rsp),%rdi	/* arg1 for handler */
 	movq_cfi rbp, 8		/* push %rbp */
 	leaq 8(%rsp), %rbp		/* mov %rsp, %ebp */
 	testl $3, CS(%rdi)
@@ -782,8 +786,9 @@ END(interrupt)
 
 /* 0(%rsp): ~(interrupt number) */
 	.macro interrupt func
-	subq $ORIG_RAX-ARGOFFSET+8, %rsp
-	CFI_ADJUST_CFA_OFFSET ORIG_RAX-ARGOFFSET+8
+	/* reserve pt_regs for scratch regs and rbp */
+	subq $ORIG_RAX-RBP, %rsp
+	CFI_ADJUST_CFA_OFFSET ORIG_RAX-RBP
 	call save_args
 	PARTIAL_FRAME 0
 	call \func
@@ -808,9 +813,14 @@ ret_from_intr:
 	TRACE_IRQS_OFF
 	decl PER_CPU_VAR(irq_count)
 	leaveq
+
 	CFI_RESTORE		rbp
 	CFI_DEF_CFA_REGISTER	rsp
 	CFI_ADJUST_CFA_OFFSET	-8
+
+	/* we did not save rbx, restore only from ARGOFFSET */
+	addq $8, %rsp
+	CFI_ADJUST_CFA_OFFSET	-8
 exit_intr:
 	GET_THREAD_INFO(%rcx)
 	testl $3,CS-ARGOFFSET(%rsp)
@@ -1319,6 +1329,9 @@ errorentry xen_stack_segment do_stack_se
 #endif
 errorentry general_protection do_general_protection
 errorentry page_fault do_page_fault
+#ifdef CONFIG_KVM_GUEST
+errorentry async_page_fault do_async_page_fault
+#endif
 #ifdef CONFIG_X86_MCE
 paranoidzeroentry machine_check *machine_check_vector(%rip)
 #endif
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/kernel/ftrace.c linux-libre-2.6.38-gnu1/arch/x86/kernel/ftrace.c
--- linux-libre-2.6.37-gnu1/arch/x86/kernel/ftrace.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/kernel/ftrace.c	2011-03-14 21:20:32.000000000 -0400
@@ -19,6 +19,7 @@
 #include <linux/sched.h>
 #include <linux/init.h>
 #include <linux/list.h>
+#include <linux/module.h>
 
 #include <trace/syscall.h>
 
@@ -49,6 +50,7 @@ static DEFINE_PER_CPU(int, save_modifyin
 int ftrace_arch_code_modify_prepare(void)
 {
 	set_kernel_text_rw();
+	set_all_modules_text_rw();
 	modifying_code = 1;
 	return 0;
 }
@@ -56,6 +58,7 @@ int ftrace_arch_code_modify_prepare(void
 int ftrace_arch_code_modify_post_process(void)
 {
 	modifying_code = 0;
+	set_all_modules_text_ro();
 	set_kernel_text_ro();
 	return 0;
 }
@@ -167,9 +170,9 @@ static void ftrace_mod_code(void)
 
 void ftrace_nmi_enter(void)
 {
-	__get_cpu_var(save_modifying_code) = modifying_code;
+	__this_cpu_write(save_modifying_code, modifying_code);
 
-	if (!__get_cpu_var(save_modifying_code))
+	if (!__this_cpu_read(save_modifying_code))
 		return;
 
 	if (atomic_inc_return(&nmi_running) & MOD_CODE_WRITE_FLAG) {
@@ -183,7 +186,7 @@ void ftrace_nmi_enter(void)
 
 void ftrace_nmi_exit(void)
 {
-	if (!__get_cpu_var(save_modifying_code))
+	if (!__this_cpu_read(save_modifying_code))
 		return;
 
 	/* Finish all executions before clearing nmi_running */
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/kernel/head32.c linux-libre-2.6.38-gnu1/arch/x86/kernel/head32.c
--- linux-libre-2.6.37-gnu1/arch/x86/kernel/head32.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/kernel/head32.c	2011-03-14 21:20:32.000000000 -0400
@@ -61,6 +61,9 @@ void __init i386_start_kernel(void)
 	case X86_SUBARCH_MRST:
 		x86_mrst_early_setup();
 		break;
+	case X86_SUBARCH_CE4100:
+		x86_ce4100_early_setup();
+		break;
 	default:
 		i386_default_early_setup();
 		break;
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/kernel/head_32.S linux-libre-2.6.38-gnu1/arch/x86/kernel/head_32.S
--- linux-libre-2.6.37-gnu1/arch/x86/kernel/head_32.S	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/kernel/head_32.S	2011-03-14 21:20:32.000000000 -0400
@@ -85,6 +85,8 @@ RESERVE_BRK(pagetables, INIT_MAP_SIZE)
  */
 __HEAD
 ENTRY(startup_32)
+	movl pa(stack_start),%ecx
+	
 	/* test KEEP_SEGMENTS flag to see if the bootloader is asking
 		us to not reload segments */
 	testb $(1<<6), BP_loadflags(%esi)
@@ -99,7 +101,9 @@ ENTRY(startup_32)
 	movl %eax,%es
 	movl %eax,%fs
 	movl %eax,%gs
+	movl %eax,%ss
 2:
+	leal -__PAGE_OFFSET(%ecx),%esp
 
 /*
  * Clear BSS first so that there are no surprises...
@@ -126,7 +130,7 @@ ENTRY(startup_32)
 	movsl
 	movl pa(boot_params) + NEW_CL_POINTER,%esi
 	andl %esi,%esi
-	jz 1f			# No comand line
+	jz 1f			# No command line
 	movl $pa(boot_command_line),%edi
 	movl $(COMMAND_LINE_SIZE/4),%ecx
 	rep
@@ -139,49 +143,13 @@ ENTRY(startup_32)
 	movl %eax, pa(olpc_ofw_pgd)
 #endif
 
-#ifdef CONFIG_PARAVIRT
-	/* This is can only trip for a broken bootloader... */
-	cmpw $0x207, pa(boot_params + BP_version)
-	jb default_entry
-
-	/* Paravirt-compatible boot parameters.  Look to see what architecture
-		we're booting under. */
-	movl pa(boot_params + BP_hardware_subarch), %eax
-	cmpl $num_subarch_entries, %eax
-	jae bad_subarch
-
-	movl pa(subarch_entries)(,%eax,4), %eax
-	subl $__PAGE_OFFSET, %eax
-	jmp *%eax
-
-bad_subarch:
-WEAK(lguest_entry)
-WEAK(xen_entry)
-	/* Unknown implementation; there's really
-	   nothing we can do at this point. */
-	ud2a
-
-	__INITDATA
-
-subarch_entries:
-	.long default_entry		/* normal x86/PC */
-	.long lguest_entry		/* lguest hypervisor */
-	.long xen_entry			/* Xen hypervisor */
-	.long default_entry		/* Moorestown MID */
-num_subarch_entries = (. - subarch_entries) / 4
-.previous
-#endif /* CONFIG_PARAVIRT */
-
 /*
  * Initialize page tables.  This creates a PDE and a set of page
  * tables, which are located immediately beyond __brk_base.  The variable
  * _brk_end is set up to point to the first "safe" location.
  * Mappings are created both at virtual address 0 (identity mapping)
  * and PAGE_OFFSET for up to _end.
- *
- * Note that the stack is not yet set up!
  */
-default_entry:
 #ifdef CONFIG_X86_PAE
 
 	/*
@@ -261,7 +229,42 @@ page_pde_offset = (__PAGE_OFFSET >> 20);
 	movl $pa(initial_pg_fixmap)+PDE_IDENT_ATTR,%eax
 	movl %eax,pa(initial_page_table+0xffc)
 #endif
-	jmp 3f
+
+#ifdef CONFIG_PARAVIRT
+	/* This is can only trip for a broken bootloader... */
+	cmpw $0x207, pa(boot_params + BP_version)
+	jb default_entry
+
+	/* Paravirt-compatible boot parameters.  Look to see what architecture
+		we're booting under. */
+	movl pa(boot_params + BP_hardware_subarch), %eax
+	cmpl $num_subarch_entries, %eax
+	jae bad_subarch
+
+	movl pa(subarch_entries)(,%eax,4), %eax
+	subl $__PAGE_OFFSET, %eax
+	jmp *%eax
+
+bad_subarch:
+WEAK(lguest_entry)
+WEAK(xen_entry)
+	/* Unknown implementation; there's really
+	   nothing we can do at this point. */
+	ud2a
+
+	__INITDATA
+
+subarch_entries:
+	.long default_entry		/* normal x86/PC */
+	.long lguest_entry		/* lguest hypervisor */
+	.long xen_entry			/* Xen hypervisor */
+	.long default_entry		/* Moorestown MID */
+num_subarch_entries = (. - subarch_entries) / 4
+.previous
+#else
+	jmp default_entry
+#endif /* CONFIG_PARAVIRT */
+
 /*
  * Non-boot CPU entry point; entered from trampoline.S
  * We can't lgdt here, because lgdt itself uses a data segment, but
@@ -281,8 +284,11 @@ ENTRY(startup_32_smp)
 	movl %eax,%es
 	movl %eax,%fs
 	movl %eax,%gs
+	movl pa(stack_start),%ecx
+	movl %eax,%ss
+	leal -__PAGE_OFFSET(%ecx),%esp
 #endif /* CONFIG_SMP */
-3:
+default_entry:
 
 /*
  *	New page tables may be in 4Mbyte page mode and may
@@ -316,6 +322,10 @@ ENTRY(startup_32_smp)
 	subl $0x80000001, %eax
 	cmpl $(0x8000ffff-0x80000001), %eax
 	ja 6f
+
+	/* Clear bogus XD_DISABLE bits */
+	call verify_cpu
+
 	mov $0x80000001, %eax
 	cpuid
 	/* Execute Disable bit supported? */
@@ -342,8 +352,8 @@ ENTRY(startup_32_smp)
 	movl %eax,%cr0		/* ..and set paging (PG) bit */
 	ljmp $__BOOT_CS,$1f	/* Clear prefetch and normalize %eip */
 1:
-	/* Set up the stack pointer */
-	lss stack_start,%esp
+	/* Shift the stack pointer to a virtual address */
+	addl $__PAGE_OFFSET, %esp
 
 /*
  * Initialize eflags.  Some BIOS's leave bits like NT set.  This would
@@ -355,9 +365,7 @@ ENTRY(startup_32_smp)
 
 #ifdef CONFIG_SMP
 	cmpb $0, ready
-	jz  1f				/* Initial CPU cleans BSS */
-	jmp checkCPUtype
-1:
+	jnz checkCPUtype
 #endif /* CONFIG_SMP */
 
 /*
@@ -465,14 +473,7 @@ is386:	movl $2,%ecx		# set MP
 
 	cld			# gcc2 wants the direction flag cleared at all times
 	pushl $0		# fake return address for unwinder
-#ifdef CONFIG_SMP
-	movb ready, %cl
 	movb $1, ready
-	cmpb $0,%cl		# the first CPU calls start_kernel
-	je   1f
-	movl (stack_start), %esp
-1:
-#endif /* CONFIG_SMP */
 	jmp *(initial_code)
 
 /*
@@ -611,6 +612,8 @@ ignore_int:
 #endif
 	iret
 
+#include "verify_cpu.S"
+
 	__REFDATA
 .align 4
 ENTRY(initial_code)
@@ -622,13 +625,13 @@ ENTRY(initial_code)
 __PAGE_ALIGNED_BSS
 	.align PAGE_SIZE_asm
 #ifdef CONFIG_X86_PAE
-ENTRY(initial_pg_pmd)
+initial_pg_pmd:
 	.fill 1024*KPMDS,4,0
 #else
 ENTRY(initial_page_table)
 	.fill 1024,4,0
 #endif
-ENTRY(initial_pg_fixmap)
+initial_pg_fixmap:
 	.fill 1024,4,0
 ENTRY(empty_zero_page)
 	.fill 4096,1,0
@@ -663,15 +666,15 @@ ENTRY(initial_page_table)
 #endif
 
 .data
+.balign 4
 ENTRY(stack_start)
 	.long init_thread_union+THREAD_SIZE
-	.long __BOOT_DS
-
-ready:	.byte 0
 
 early_recursion_flag:
 	.long 0
 
+ready:	.byte 0
+
 int_msg:
 	.asciz "Unknown interrupt or fault at: %p %p %p\n"
 
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/kernel/hw_breakpoint.c linux-libre-2.6.38-gnu1/arch/x86/kernel/hw_breakpoint.c
--- linux-libre-2.6.37-gnu1/arch/x86/kernel/hw_breakpoint.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/kernel/hw_breakpoint.c	2011-03-14 21:20:32.000000000 -0400
@@ -122,7 +122,7 @@ int arch_install_hw_breakpoint(struct pe
 		return -EBUSY;
 
 	set_debugreg(info->address, i);
-	__get_cpu_var(cpu_debugreg[i]) = info->address;
+	__this_cpu_write(cpu_debugreg[i], info->address);
 
 	dr7 = &__get_cpu_var(cpu_dr7);
 	*dr7 |= encode_dr7(i, info->len, info->type);
@@ -397,12 +397,12 @@ void flush_ptrace_hw_breakpoint(struct t
 
 void hw_breakpoint_restore(void)
 {
-	set_debugreg(__get_cpu_var(cpu_debugreg[0]), 0);
-	set_debugreg(__get_cpu_var(cpu_debugreg[1]), 1);
-	set_debugreg(__get_cpu_var(cpu_debugreg[2]), 2);
-	set_debugreg(__get_cpu_var(cpu_debugreg[3]), 3);
+	set_debugreg(__this_cpu_read(cpu_debugreg[0]), 0);
+	set_debugreg(__this_cpu_read(cpu_debugreg[1]), 1);
+	set_debugreg(__this_cpu_read(cpu_debugreg[2]), 2);
+	set_debugreg(__this_cpu_read(cpu_debugreg[3]), 3);
 	set_debugreg(current->thread.debugreg6, 6);
-	set_debugreg(__get_cpu_var(cpu_dr7), 7);
+	set_debugreg(__this_cpu_read(cpu_dr7), 7);
 }
 EXPORT_SYMBOL_GPL(hw_breakpoint_restore);
 
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/kernel/i387.c linux-libre-2.6.38-gnu1/arch/x86/kernel/i387.c
--- linux-libre-2.6.37-gnu1/arch/x86/kernel/i387.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/kernel/i387.c	2011-03-14 21:20:32.000000000 -0400
@@ -169,6 +169,7 @@ int init_fpu(struct task_struct *tsk)
 	set_stopped_child_used_math(tsk);
 	return 0;
 }
+EXPORT_SYMBOL_GPL(init_fpu);
 
 /*
  * The xstateregs_active() routine is the same as the fpregs_active() routine,
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/kernel/irq_32.c linux-libre-2.6.38-gnu1/arch/x86/kernel/irq_32.c
--- linux-libre-2.6.37-gnu1/arch/x86/kernel/irq_32.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/kernel/irq_32.c	2011-03-14 21:20:32.000000000 -0400
@@ -79,7 +79,7 @@ execute_on_irq_stack(int overflow, struc
 	u32 *isp, arg1, arg2;
 
 	curctx = (union irq_ctx *) current_thread_info();
-	irqctx = __get_cpu_var(hardirq_ctx);
+	irqctx = __this_cpu_read(hardirq_ctx);
 
 	/*
 	 * this is where we switch to the IRQ stack. However, if we are
@@ -129,8 +129,7 @@ void __cpuinit irq_ctx_init(int cpu)
 	irqctx = page_address(alloc_pages_node(cpu_to_node(cpu),
 					       THREAD_FLAGS,
 					       THREAD_ORDER));
-	irqctx->tinfo.task		= NULL;
-	irqctx->tinfo.exec_domain	= NULL;
+	memset(&irqctx->tinfo, 0, sizeof(struct thread_info));
 	irqctx->tinfo.cpu		= cpu;
 	irqctx->tinfo.preempt_count	= HARDIRQ_OFFSET;
 	irqctx->tinfo.addr_limit	= MAKE_MM_SEG(0);
@@ -140,10 +139,8 @@ void __cpuinit irq_ctx_init(int cpu)
 	irqctx = page_address(alloc_pages_node(cpu_to_node(cpu),
 					       THREAD_FLAGS,
 					       THREAD_ORDER));
-	irqctx->tinfo.task		= NULL;
-	irqctx->tinfo.exec_domain	= NULL;
+	memset(&irqctx->tinfo, 0, sizeof(struct thread_info));
 	irqctx->tinfo.cpu		= cpu;
-	irqctx->tinfo.preempt_count	= 0;
 	irqctx->tinfo.addr_limit	= MAKE_MM_SEG(0);
 
 	per_cpu(softirq_ctx, cpu) = irqctx;
@@ -166,7 +163,7 @@ asmlinkage void do_softirq(void)
 
 	if (local_softirq_pending()) {
 		curctx = current_thread_info();
-		irqctx = __get_cpu_var(softirq_ctx);
+		irqctx = __this_cpu_read(softirq_ctx);
 		irqctx->tinfo.task = curctx->task;
 		irqctx->tinfo.previous_esp = current_stack_pointer;
 
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/kernel/irq.c linux-libre-2.6.38-gnu1/arch/x86/kernel/irq.c
--- linux-libre-2.6.37-gnu1/arch/x86/kernel/irq.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/kernel/irq.c	2011-03-14 21:20:32.000000000 -0400
@@ -4,6 +4,7 @@
 #include <linux/cpu.h>
 #include <linux/interrupt.h>
 #include <linux/kernel_stat.h>
+#include <linux/of.h>
 #include <linux/seq_file.h>
 #include <linux/smp.h>
 #include <linux/ftrace.h>
@@ -234,7 +235,7 @@ unsigned int __irq_entry do_IRQ(struct p
 	exit_idle();
 	irq_enter();
 
-	irq = __get_cpu_var(vector_irq)[vector];
+	irq = __this_cpu_read(vector_irq[vector]);
 
 	if (!handle_irq(irq, regs)) {
 		ack_APIC_irq();
@@ -275,6 +276,15 @@ void smp_x86_platform_ipi(struct pt_regs
 
 EXPORT_SYMBOL_GPL(vector_used_by_percpu_irq);
 
+#ifdef CONFIG_OF
+unsigned int irq_create_of_mapping(struct device_node *controller,
+		const u32 *intspec, unsigned int intsize)
+{
+	return intspec[0];
+}
+EXPORT_SYMBOL_GPL(irq_create_of_mapping);
+#endif
+
 #ifdef CONFIG_HOTPLUG_CPU
 /* A cpu has been removed from cpu_online_mask.  Reset irq affinities. */
 void fixup_irqs(void)
@@ -350,14 +360,15 @@ void fixup_irqs(void)
 	for (vector = FIRST_EXTERNAL_VECTOR; vector < NR_VECTORS; vector++) {
 		unsigned int irr;
 
-		if (__get_cpu_var(vector_irq)[vector] < 0)
+		if (__this_cpu_read(vector_irq[vector]) < 0)
 			continue;
 
 		irr = apic_read(APIC_IRR + (vector / 32 * 0x10));
 		if (irr  & (1 << (vector % 32))) {
-			irq = __get_cpu_var(vector_irq)[vector];
+			irq = __this_cpu_read(vector_irq[vector]);
 
-			data = irq_get_irq_data(irq);
+			desc = irq_to_desc(irq);
+			data = &desc->irq_data;
 			raw_spin_lock(&desc->lock);
 			if (data->chip->irq_retrigger)
 				data->chip->irq_retrigger(data);
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/kernel/kgdb.c linux-libre-2.6.38-gnu1/arch/x86/kernel/kgdb.c
--- linux-libre-2.6.37-gnu1/arch/x86/kernel/kgdb.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/kernel/kgdb.c	2011-03-14 21:20:32.000000000 -0400
@@ -48,6 +48,7 @@
 #include <asm/apicdef.h>
 #include <asm/system.h>
 #include <asm/apic.h>
+#include <asm/nmi.h>
 
 struct dbg_reg_def_t dbg_reg_def[DBG_MAX_REG_NUM] =
 {
@@ -525,10 +526,6 @@ static int __kgdb_notify(struct die_args
 		}
 		return NOTIFY_DONE;
 
-	case DIE_NMI_IPI:
-		/* Just ignore, we will handle the roundup on DIE_NMI. */
-		return NOTIFY_DONE;
-
 	case DIE_NMIUNKNOWN:
 		if (was_in_debug_nmi[raw_smp_processor_id()]) {
 			was_in_debug_nmi[raw_smp_processor_id()] = 0;
@@ -606,7 +603,7 @@ static struct notifier_block kgdb_notifi
 	/*
 	 * Lowest-prio notifier priority, we want to be notified last:
 	 */
-	.priority	= -INT_MAX,
+	.priority	= NMI_LOCAL_LOW_PRIOR,
 };
 
 /**
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/kernel/kprobes.c linux-libre-2.6.38-gnu1/arch/x86/kernel/kprobes.c
--- linux-libre-2.6.37-gnu1/arch/x86/kernel/kprobes.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/kernel/kprobes.c	2011-03-14 21:20:32.000000000 -0400
@@ -403,7 +403,7 @@ static void __kprobes save_previous_kpro
 
 static void __kprobes restore_previous_kprobe(struct kprobe_ctlblk *kcb)
 {
-	__get_cpu_var(current_kprobe) = kcb->prev_kprobe.kp;
+	__this_cpu_write(current_kprobe, kcb->prev_kprobe.kp);
 	kcb->kprobe_status = kcb->prev_kprobe.status;
 	kcb->kprobe_old_flags = kcb->prev_kprobe.old_flags;
 	kcb->kprobe_saved_flags = kcb->prev_kprobe.saved_flags;
@@ -412,7 +412,7 @@ static void __kprobes restore_previous_k
 static void __kprobes set_current_kprobe(struct kprobe *p, struct pt_regs *regs,
 				struct kprobe_ctlblk *kcb)
 {
-	__get_cpu_var(current_kprobe) = p;
+	__this_cpu_write(current_kprobe, p);
 	kcb->kprobe_saved_flags = kcb->kprobe_old_flags
 		= (regs->flags & (X86_EFLAGS_TF | X86_EFLAGS_IF));
 	if (is_IF_modifier(p->ainsn.insn))
@@ -586,7 +586,7 @@ static int __kprobes kprobe_handler(stru
 		preempt_enable_no_resched();
 		return 1;
 	} else if (kprobe_running()) {
-		p = __get_cpu_var(current_kprobe);
+		p = __this_cpu_read(current_kprobe);
 		if (p->break_handler && p->break_handler(p, regs)) {
 			setup_singlestep(p, regs, kcb, 0);
 			return 1;
@@ -759,11 +759,11 @@ static __used __kprobes void *trampoline
 
 		orig_ret_address = (unsigned long)ri->ret_addr;
 		if (ri->rp && ri->rp->handler) {
-			__get_cpu_var(current_kprobe) = &ri->rp->kp;
+			__this_cpu_write(current_kprobe, &ri->rp->kp);
 			get_kprobe_ctlblk()->kprobe_status = KPROBE_HIT_ACTIVE;
 			ri->ret_addr = correct_ret_addr;
 			ri->rp->handler(ri, regs);
-			__get_cpu_var(current_kprobe) = NULL;
+			__this_cpu_write(current_kprobe, NULL);
 		}
 
 		recycle_rp_inst(ri, &empty_rp);
@@ -1184,6 +1184,10 @@ static void __kprobes optimized_callback
 {
 	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
 
+	/* This is possible if op is under delayed unoptimizing */
+	if (kprobe_disabled(&op->kp))
+		return;
+
 	preempt_disable();
 	if (kprobe_running()) {
 		kprobes_inc_nmissed_count(&op->kp);
@@ -1198,10 +1202,10 @@ static void __kprobes optimized_callback
 		regs->ip = (unsigned long)op->kp.addr + INT3_SIZE;
 		regs->orig_ax = ~0UL;
 
-		__get_cpu_var(current_kprobe) = &op->kp;
+		__this_cpu_write(current_kprobe, &op->kp);
 		kcb->kprobe_status = KPROBE_HIT_ACTIVE;
 		opt_pre_handler(&op->kp, regs);
-		__get_cpu_var(current_kprobe) = NULL;
+		__this_cpu_write(current_kprobe, NULL);
 	}
 	preempt_enable_no_resched();
 }
@@ -1401,10 +1405,16 @@ int __kprobes arch_prepare_optimized_kpr
 	return 0;
 }
 
-/* Replace a breakpoint (int3) with a relative jump.  */
-int __kprobes arch_optimize_kprobe(struct optimized_kprobe *op)
+#define MAX_OPTIMIZE_PROBES 256
+static struct text_poke_param *jump_poke_params;
+static struct jump_poke_buffer {
+	u8 buf[RELATIVEJUMP_SIZE];
+} *jump_poke_bufs;
+
+static void __kprobes setup_optimize_kprobe(struct text_poke_param *tprm,
+					    u8 *insn_buf,
+					    struct optimized_kprobe *op)
 {
-	unsigned char jmp_code[RELATIVEJUMP_SIZE];
 	s32 rel = (s32)((long)op->optinsn.insn -
 			((long)op->kp.addr + RELATIVEJUMP_SIZE));
 
@@ -1412,16 +1422,79 @@ int __kprobes arch_optimize_kprobe(struc
 	memcpy(op->optinsn.copied_insn, op->kp.addr + INT3_SIZE,
 	       RELATIVE_ADDR_SIZE);
 
-	jmp_code[0] = RELATIVEJUMP_OPCODE;
-	*(s32 *)(&jmp_code[1]) = rel;
+	insn_buf[0] = RELATIVEJUMP_OPCODE;
+	*(s32 *)(&insn_buf[1]) = rel;
+
+	tprm->addr = op->kp.addr;
+	tprm->opcode = insn_buf;
+	tprm->len = RELATIVEJUMP_SIZE;
+}
+
+/*
+ * Replace breakpoints (int3) with relative jumps.
+ * Caller must call with locking kprobe_mutex and text_mutex.
+ */
+void __kprobes arch_optimize_kprobes(struct list_head *oplist)
+{
+	struct optimized_kprobe *op, *tmp;
+	int c = 0;
+
+	list_for_each_entry_safe(op, tmp, oplist, list) {
+		WARN_ON(kprobe_disabled(&op->kp));
+		/* Setup param */
+		setup_optimize_kprobe(&jump_poke_params[c],
+				      jump_poke_bufs[c].buf, op);
+		list_del_init(&op->list);
+		if (++c >= MAX_OPTIMIZE_PROBES)
+			break;
+	}
 
 	/*
 	 * text_poke_smp doesn't support NMI/MCE code modifying.
 	 * However, since kprobes itself also doesn't support NMI/MCE
 	 * code probing, it's not a problem.
 	 */
-	text_poke_smp(op->kp.addr, jmp_code, RELATIVEJUMP_SIZE);
-	return 0;
+	text_poke_smp_batch(jump_poke_params, c);
+}
+
+static void __kprobes setup_unoptimize_kprobe(struct text_poke_param *tprm,
+					      u8 *insn_buf,
+					      struct optimized_kprobe *op)
+{
+	/* Set int3 to first byte for kprobes */
+	insn_buf[0] = BREAKPOINT_INSTRUCTION;
+	memcpy(insn_buf + 1, op->optinsn.copied_insn, RELATIVE_ADDR_SIZE);
+
+	tprm->addr = op->kp.addr;
+	tprm->opcode = insn_buf;
+	tprm->len = RELATIVEJUMP_SIZE;
+}
+
+/*
+ * Recover original instructions and breakpoints from relative jumps.
+ * Caller must call with locking kprobe_mutex.
+ */
+extern void arch_unoptimize_kprobes(struct list_head *oplist,
+				    struct list_head *done_list)
+{
+	struct optimized_kprobe *op, *tmp;
+	int c = 0;
+
+	list_for_each_entry_safe(op, tmp, oplist, list) {
+		/* Setup param */
+		setup_unoptimize_kprobe(&jump_poke_params[c],
+					jump_poke_bufs[c].buf, op);
+		list_move(&op->list, done_list);
+		if (++c >= MAX_OPTIMIZE_PROBES)
+			break;
+	}
+
+	/*
+	 * text_poke_smp doesn't support NMI/MCE code modifying.
+	 * However, since kprobes itself also doesn't support NMI/MCE
+	 * code probing, it's not a problem.
+	 */
+	text_poke_smp_batch(jump_poke_params, c);
 }
 
 /* Replace a relative jump with a breakpoint (int3).  */
@@ -1453,11 +1526,35 @@ static int  __kprobes setup_detour_execu
 	}
 	return 0;
 }
+
+static int __kprobes init_poke_params(void)
+{
+	/* Allocate code buffer and parameter array */
+	jump_poke_bufs = kmalloc(sizeof(struct jump_poke_buffer) *
+				 MAX_OPTIMIZE_PROBES, GFP_KERNEL);
+	if (!jump_poke_bufs)
+		return -ENOMEM;
+
+	jump_poke_params = kmalloc(sizeof(struct text_poke_param) *
+				   MAX_OPTIMIZE_PROBES, GFP_KERNEL);
+	if (!jump_poke_params) {
+		kfree(jump_poke_bufs);
+		jump_poke_bufs = NULL;
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+#else	/* !CONFIG_OPTPROBES */
+static int __kprobes init_poke_params(void)
+{
+	return 0;
+}
 #endif
 
 int __init arch_init_kprobes(void)
 {
-	return 0;
+	return init_poke_params();
 }
 
 int __kprobes arch_trampoline_kprobe(struct kprobe *p)
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/kernel/kvm.c linux-libre-2.6.38-gnu1/arch/x86/kernel/kvm.c
--- linux-libre-2.6.37-gnu1/arch/x86/kernel/kvm.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/kernel/kvm.c	2011-03-14 21:20:32.000000000 -0400
@@ -27,16 +27,37 @@
 #include <linux/mm.h>
 #include <linux/highmem.h>
 #include <linux/hardirq.h>
+#include <linux/notifier.h>
+#include <linux/reboot.h>
+#include <linux/hash.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/kprobes.h>
 #include <asm/timer.h>
+#include <asm/cpu.h>
+#include <asm/traps.h>
+#include <asm/desc.h>
+#include <asm/tlbflush.h>
 
 #define MMU_QUEUE_SIZE 1024
 
+static int kvmapf = 1;
+
+static int parse_no_kvmapf(char *arg)
+{
+        kvmapf = 0;
+        return 0;
+}
+
+early_param("no-kvmapf", parse_no_kvmapf);
+
 struct kvm_para_state {
 	u8 mmu_queue[MMU_QUEUE_SIZE];
 	int mmu_queue_len;
 };
 
 static DEFINE_PER_CPU(struct kvm_para_state, para_state);
+static DEFINE_PER_CPU(struct kvm_vcpu_pv_apf_data, apf_reason) __aligned(64);
 
 static struct kvm_para_state *kvm_para_state(void)
 {
@@ -50,6 +71,195 @@ static void kvm_io_delay(void)
 {
 }
 
+#define KVM_TASK_SLEEP_HASHBITS 8
+#define KVM_TASK_SLEEP_HASHSIZE (1<<KVM_TASK_SLEEP_HASHBITS)
+
+struct kvm_task_sleep_node {
+	struct hlist_node link;
+	wait_queue_head_t wq;
+	u32 token;
+	int cpu;
+	bool halted;
+	struct mm_struct *mm;
+};
+
+static struct kvm_task_sleep_head {
+	spinlock_t lock;
+	struct hlist_head list;
+} async_pf_sleepers[KVM_TASK_SLEEP_HASHSIZE];
+
+static struct kvm_task_sleep_node *_find_apf_task(struct kvm_task_sleep_head *b,
+						  u32 token)
+{
+	struct hlist_node *p;
+
+	hlist_for_each(p, &b->list) {
+		struct kvm_task_sleep_node *n =
+			hlist_entry(p, typeof(*n), link);
+		if (n->token == token)
+			return n;
+	}
+
+	return NULL;
+}
+
+void kvm_async_pf_task_wait(u32 token)
+{
+	u32 key = hash_32(token, KVM_TASK_SLEEP_HASHBITS);
+	struct kvm_task_sleep_head *b = &async_pf_sleepers[key];
+	struct kvm_task_sleep_node n, *e;
+	DEFINE_WAIT(wait);
+	int cpu, idle;
+
+	cpu = get_cpu();
+	idle = idle_cpu(cpu);
+	put_cpu();
+
+	spin_lock(&b->lock);
+	e = _find_apf_task(b, token);
+	if (e) {
+		/* dummy entry exist -> wake up was delivered ahead of PF */
+		hlist_del(&e->link);
+		kfree(e);
+		spin_unlock(&b->lock);
+		return;
+	}
+
+	n.token = token;
+	n.cpu = smp_processor_id();
+	n.mm = current->active_mm;
+	n.halted = idle || preempt_count() > 1;
+	atomic_inc(&n.mm->mm_count);
+	init_waitqueue_head(&n.wq);
+	hlist_add_head(&n.link, &b->list);
+	spin_unlock(&b->lock);
+
+	for (;;) {
+		if (!n.halted)
+			prepare_to_wait(&n.wq, &wait, TASK_UNINTERRUPTIBLE);
+		if (hlist_unhashed(&n.link))
+			break;
+
+		if (!n.halted) {
+			local_irq_enable();
+			schedule();
+			local_irq_disable();
+		} else {
+			/*
+			 * We cannot reschedule. So halt.
+			 */
+			native_safe_halt();
+			local_irq_disable();
+		}
+	}
+	if (!n.halted)
+		finish_wait(&n.wq, &wait);
+
+	return;
+}
+EXPORT_SYMBOL_GPL(kvm_async_pf_task_wait);
+
+static void apf_task_wake_one(struct kvm_task_sleep_node *n)
+{
+	hlist_del_init(&n->link);
+	if (!n->mm)
+		return;
+	mmdrop(n->mm);
+	if (n->halted)
+		smp_send_reschedule(n->cpu);
+	else if (waitqueue_active(&n->wq))
+		wake_up(&n->wq);
+}
+
+static void apf_task_wake_all(void)
+{
+	int i;
+
+	for (i = 0; i < KVM_TASK_SLEEP_HASHSIZE; i++) {
+		struct hlist_node *p, *next;
+		struct kvm_task_sleep_head *b = &async_pf_sleepers[i];
+		spin_lock(&b->lock);
+		hlist_for_each_safe(p, next, &b->list) {
+			struct kvm_task_sleep_node *n =
+				hlist_entry(p, typeof(*n), link);
+			if (n->cpu == smp_processor_id())
+				apf_task_wake_one(n);
+		}
+		spin_unlock(&b->lock);
+	}
+}
+
+void kvm_async_pf_task_wake(u32 token)
+{
+	u32 key = hash_32(token, KVM_TASK_SLEEP_HASHBITS);
+	struct kvm_task_sleep_head *b = &async_pf_sleepers[key];
+	struct kvm_task_sleep_node *n;
+
+	if (token == ~0) {
+		apf_task_wake_all();
+		return;
+	}
+
+again:
+	spin_lock(&b->lock);
+	n = _find_apf_task(b, token);
+	if (!n) {
+		/*
+		 * async PF was not yet handled.
+		 * Add dummy entry for the token.
+		 */
+		n = kmalloc(sizeof(*n), GFP_ATOMIC);
+		if (!n) {
+			/*
+			 * Allocation failed! Busy wait while other cpu
+			 * handles async PF.
+			 */
+			spin_unlock(&b->lock);
+			cpu_relax();
+			goto again;
+		}
+		n->token = token;
+		n->cpu = smp_processor_id();
+		n->mm = NULL;
+		init_waitqueue_head(&n->wq);
+		hlist_add_head(&n->link, &b->list);
+	} else
+		apf_task_wake_one(n);
+	spin_unlock(&b->lock);
+	return;
+}
+EXPORT_SYMBOL_GPL(kvm_async_pf_task_wake);
+
+u32 kvm_read_and_reset_pf_reason(void)
+{
+	u32 reason = 0;
+
+	if (__get_cpu_var(apf_reason).enabled) {
+		reason = __get_cpu_var(apf_reason).reason;
+		__get_cpu_var(apf_reason).reason = 0;
+	}
+
+	return reason;
+}
+EXPORT_SYMBOL_GPL(kvm_read_and_reset_pf_reason);
+
+dotraplinkage void __kprobes
+do_async_page_fault(struct pt_regs *regs, unsigned long error_code)
+{
+	switch (kvm_read_and_reset_pf_reason()) {
+	default:
+		do_page_fault(regs, error_code);
+		break;
+	case KVM_PV_REASON_PAGE_NOT_PRESENT:
+		/* page is swapped out by the host. */
+		kvm_async_pf_task_wait((u32)read_cr2());
+		break;
+	case KVM_PV_REASON_PAGE_READY:
+		kvm_async_pf_task_wake((u32)read_cr2());
+		break;
+	}
+}
+
 static void kvm_mmu_op(void *buffer, unsigned len)
 {
 	int r;
@@ -231,10 +441,117 @@ static void __init paravirt_ops_setup(vo
 #endif
 }
 
+void __cpuinit kvm_guest_cpu_init(void)
+{
+	if (!kvm_para_available())
+		return;
+
+	if (kvm_para_has_feature(KVM_FEATURE_ASYNC_PF) && kvmapf) {
+		u64 pa = __pa(&__get_cpu_var(apf_reason));
+
+#ifdef CONFIG_PREEMPT
+		pa |= KVM_ASYNC_PF_SEND_ALWAYS;
+#endif
+		wrmsrl(MSR_KVM_ASYNC_PF_EN, pa | KVM_ASYNC_PF_ENABLED);
+		__get_cpu_var(apf_reason).enabled = 1;
+		printk(KERN_INFO"KVM setup async PF for cpu %d\n",
+		       smp_processor_id());
+	}
+}
+
+static void kvm_pv_disable_apf(void *unused)
+{
+	if (!__get_cpu_var(apf_reason).enabled)
+		return;
+
+	wrmsrl(MSR_KVM_ASYNC_PF_EN, 0);
+	__get_cpu_var(apf_reason).enabled = 0;
+
+	printk(KERN_INFO"Unregister pv shared memory for cpu %d\n",
+	       smp_processor_id());
+}
+
+static int kvm_pv_reboot_notify(struct notifier_block *nb,
+				unsigned long code, void *unused)
+{
+	if (code == SYS_RESTART)
+		on_each_cpu(kvm_pv_disable_apf, NULL, 1);
+	return NOTIFY_DONE;
+}
+
+static struct notifier_block kvm_pv_reboot_nb = {
+	.notifier_call = kvm_pv_reboot_notify,
+};
+
+#ifdef CONFIG_SMP
+static void __init kvm_smp_prepare_boot_cpu(void)
+{
+#ifdef CONFIG_KVM_CLOCK
+	WARN_ON(kvm_register_clock("primary cpu clock"));
+#endif
+	kvm_guest_cpu_init();
+	native_smp_prepare_boot_cpu();
+}
+
+static void kvm_guest_cpu_online(void *dummy)
+{
+	kvm_guest_cpu_init();
+}
+
+static void kvm_guest_cpu_offline(void *dummy)
+{
+	kvm_pv_disable_apf(NULL);
+	apf_task_wake_all();
+}
+
+static int __cpuinit kvm_cpu_notify(struct notifier_block *self,
+				    unsigned long action, void *hcpu)
+{
+	int cpu = (unsigned long)hcpu;
+	switch (action) {
+	case CPU_ONLINE:
+	case CPU_DOWN_FAILED:
+	case CPU_ONLINE_FROZEN:
+		smp_call_function_single(cpu, kvm_guest_cpu_online, NULL, 0);
+		break;
+	case CPU_DOWN_PREPARE:
+	case CPU_DOWN_PREPARE_FROZEN:
+		smp_call_function_single(cpu, kvm_guest_cpu_offline, NULL, 1);
+		break;
+	default:
+		break;
+	}
+	return NOTIFY_OK;
+}
+
+static struct notifier_block __cpuinitdata kvm_cpu_notifier = {
+        .notifier_call  = kvm_cpu_notify,
+};
+#endif
+
+static void __init kvm_apf_trap_init(void)
+{
+	set_intr_gate(14, &async_page_fault);
+}
+
 void __init kvm_guest_init(void)
 {
+	int i;
+
 	if (!kvm_para_available())
 		return;
 
 	paravirt_ops_setup();
+	register_reboot_notifier(&kvm_pv_reboot_nb);
+	for (i = 0; i < KVM_TASK_SLEEP_HASHSIZE; i++)
+		spin_lock_init(&async_pf_sleepers[i].lock);
+	if (kvm_para_has_feature(KVM_FEATURE_ASYNC_PF))
+		x86_init.irqs.trap_init = kvm_apf_trap_init;
+
+#ifdef CONFIG_SMP
+	smp_ops.smp_prepare_boot_cpu = kvm_smp_prepare_boot_cpu;
+	register_cpu_notifier(&kvm_cpu_notifier);
+#else
+	kvm_guest_cpu_init();
+#endif
 }
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/kernel/kvmclock.c linux-libre-2.6.38-gnu1/arch/x86/kernel/kvmclock.c
--- linux-libre-2.6.37-gnu1/arch/x86/kernel/kvmclock.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/kernel/kvmclock.c	2011-03-14 21:20:32.000000000 -0400
@@ -125,7 +125,7 @@ static struct clocksource kvm_clock = {
 	.flags = CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
-static int kvm_register_clock(char *txt)
+int kvm_register_clock(char *txt)
 {
 	int cpu = smp_processor_id();
 	int low, high, ret;
@@ -152,14 +152,6 @@ static void __cpuinit kvm_setup_secondar
 }
 #endif
 
-#ifdef CONFIG_SMP
-static void __init kvm_smp_prepare_boot_cpu(void)
-{
-	WARN_ON(kvm_register_clock("primary cpu clock"));
-	native_smp_prepare_boot_cpu();
-}
-#endif
-
 /*
  * After the clock is registered, the host will keep writing to the
  * registered memory location. If the guest happens to shutdown, this memory
@@ -206,9 +198,6 @@ void __init kvmclock_init(void)
 	x86_cpuinit.setup_percpu_clockev =
 		kvm_setup_secondary_clock;
 #endif
-#ifdef CONFIG_SMP
-	smp_ops.smp_prepare_boot_cpu = kvm_smp_prepare_boot_cpu;
-#endif
 	machine_ops.shutdown  = kvm_shutdown;
 #ifdef CONFIG_KEXEC
 	machine_ops.crash_shutdown  = kvm_crash_shutdown;
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/kernel/Makefile linux-libre-2.6.38-gnu1/arch/x86/kernel/Makefile
--- linux-libre-2.6.37-gnu1/arch/x86/kernel/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/kernel/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -85,7 +85,6 @@ obj-$(CONFIG_DOUBLEFAULT) 	+= doublefaul
 obj-$(CONFIG_KGDB)		+= kgdb.o
 obj-$(CONFIG_VM86)		+= vm86_32.o
 obj-$(CONFIG_EARLY_PRINTK)	+= early_printk.o
-obj-$(CONFIG_EARLY_PRINTK_MRST)	+= early_printk_mrst.o
 
 obj-$(CONFIG_HPET_TIMER) 	+= hpet.o
 obj-$(CONFIG_APB_TIMER)		+= apb_timer.o
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/kernel/microcode_amd.c linux-libre-2.6.38-gnu1/arch/x86/kernel/microcode_amd.c
--- linux-libre-2.6.37-gnu1/arch/x86/kernel/microcode_amd.c	2013-05-03 03:53:47.000000000 -0400
+++ linux-libre-2.6.38-gnu1/arch/x86/kernel/microcode_amd.c	2013-05-03 01:52:40.000000000 -0400
@@ -155,12 +155,6 @@ static int apply_microcode_amd(int cpu)
 	return 0;
 }
 
-static int get_ucode_data(void *to, const u8 *from, size_t n)
-{
-	memcpy(to, from, n);
-	return 0;
-}
-
 static void *
 get_next_ucode(const u8 *buf, unsigned int size, unsigned int *mc_size)
 {
@@ -168,8 +162,7 @@ get_next_ucode(const u8 *buf, unsigned i
 	u8 section_hdr[UCODE_CONTAINER_SECTION_HDR];
 	void *mc;
 
-	if (get_ucode_data(section_hdr, buf, UCODE_CONTAINER_SECTION_HDR))
-		return NULL;
+	get_ucode_data(section_hdr, buf, UCODE_CONTAINER_SECTION_HDR);
 
 	if (section_hdr[0] != UCODE_UCODE_TYPE) {
 		pr_err("error: invalid type field in container file section header\n");
@@ -183,16 +176,13 @@ get_next_ucode(const u8 *buf, unsigned i
 		return NULL;
 	}
 
-	mc = vmalloc(UCODE_MAX_SIZE);
-	if (mc) {
-		memset(mc, 0, UCODE_MAX_SIZE);
-		if (get_ucode_data(mc, buf + UCODE_CONTAINER_SECTION_HDR,
-				   total_size)) {
-			vfree(mc);
-			mc = NULL;
-		} else
-			*mc_size = total_size + UCODE_CONTAINER_SECTION_HDR;
-	}
+	mc = vzalloc(UCODE_MAX_SIZE);
+	if (!mc)
+		return NULL;
+
+	get_ucode_data(mc, buf + UCODE_CONTAINER_SECTION_HDR, total_size);
+	*mc_size = total_size + UCODE_CONTAINER_SECTION_HDR;
+
 	return mc;
 }
 
@@ -202,8 +192,7 @@ static int install_equiv_cpu_table(const
 	unsigned int *buf_pos = (unsigned int *)container_hdr;
 	unsigned long size;
 
-	if (get_ucode_data(&container_hdr, buf, UCODE_CONTAINER_HEADER_SIZE))
-		return 0;
+	get_ucode_data(&container_hdr, buf, UCODE_CONTAINER_HEADER_SIZE);
 
 	size = buf_pos[2];
 
@@ -219,10 +208,7 @@ static int install_equiv_cpu_table(const
 	}
 
 	buf += UCODE_CONTAINER_HEADER_SIZE;
-	if (get_ucode_data(equiv_cpu_table, buf, size)) {
-		vfree(equiv_cpu_table);
-		return 0;
-	}
+	get_ucode_data(equiv_cpu_table, buf, size);
 
 	return size + UCODE_CONTAINER_HEADER_SIZE; /* add header length */
 }
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/kernel/module.c linux-libre-2.6.38-gnu1/arch/x86/kernel/module.c
--- linux-libre-2.6.37-gnu1/arch/x86/kernel/module.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/kernel/module.c	2011-03-14 21:20:32.000000000 -0400
@@ -37,20 +37,11 @@
 
 void *module_alloc(unsigned long size)
 {
-	struct vm_struct *area;
-
-	if (!size)
-		return NULL;
-	size = PAGE_ALIGN(size);
-	if (size > MODULES_LEN)
-		return NULL;
-
-	area = __get_vm_area(size, VM_ALLOC, MODULES_VADDR, MODULES_END);
-	if (!area)
+	if (PAGE_ALIGN(size) > MODULES_LEN)
 		return NULL;
-
-	return __vmalloc_area(area, GFP_KERNEL | __GFP_HIGHMEM,
-					PAGE_KERNEL_EXEC);
+	return __vmalloc_node_range(size, 1, MODULES_VADDR, MODULES_END,
+				GFP_KERNEL | __GFP_HIGHMEM, PAGE_KERNEL_EXEC,
+				-1, __builtin_return_address(0));
 }
 
 /* Free memory returned from module_alloc */
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/kernel/mpparse.c linux-libre-2.6.38-gnu1/arch/x86/kernel/mpparse.c
--- linux-libre-2.6.37-gnu1/arch/x86/kernel/mpparse.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/kernel/mpparse.c	2011-03-14 21:20:32.000000000 -0400
@@ -118,21 +118,8 @@ static void __init MP_bus_info(struct mp
 
 static void __init MP_ioapic_info(struct mpc_ioapic *m)
 {
-	if (!(m->flags & MPC_APIC_USABLE))
-		return;
-
-	printk(KERN_INFO "I/O APIC #%d Version %d at 0x%X.\n",
-	       m->apicid, m->apicver, m->apicaddr);
-
-	mp_register_ioapic(m->apicid, m->apicaddr, gsi_top);
-}
-
-static void print_MP_intsrc_info(struct mpc_intsrc *m)
-{
-	apic_printk(APIC_VERBOSE, "Int: type %d, pol %d, trig %d, bus %02x,"
-		" IRQ %02x, APIC ID %x, APIC INT %02x\n",
-		m->irqtype, m->irqflag & 3, (m->irqflag >> 2) & 3, m->srcbus,
-		m->srcbusirq, m->dstapic, m->dstirq);
+	if (m->flags & MPC_APIC_USABLE)
+		mp_register_ioapic(m->apicid, m->apicaddr, gsi_top);
 }
 
 static void __init print_mp_irq_info(struct mpc_intsrc *mp_irq)
@@ -144,73 +131,11 @@ static void __init print_mp_irq_info(str
 		mp_irq->srcbusirq, mp_irq->dstapic, mp_irq->dstirq);
 }
 
-static void __init assign_to_mp_irq(struct mpc_intsrc *m,
-				    struct mpc_intsrc *mp_irq)
-{
-	mp_irq->dstapic = m->dstapic;
-	mp_irq->type = m->type;
-	mp_irq->irqtype = m->irqtype;
-	mp_irq->irqflag = m->irqflag;
-	mp_irq->srcbus = m->srcbus;
-	mp_irq->srcbusirq = m->srcbusirq;
-	mp_irq->dstirq = m->dstirq;
-}
-
-static void __init assign_to_mpc_intsrc(struct mpc_intsrc *mp_irq,
-					struct mpc_intsrc *m)
-{
-	m->dstapic = mp_irq->dstapic;
-	m->type = mp_irq->type;
-	m->irqtype = mp_irq->irqtype;
-	m->irqflag = mp_irq->irqflag;
-	m->srcbus = mp_irq->srcbus;
-	m->srcbusirq = mp_irq->srcbusirq;
-	m->dstirq = mp_irq->dstirq;
-}
-
-static int __init mp_irq_mpc_intsrc_cmp(struct mpc_intsrc *mp_irq,
-					struct mpc_intsrc *m)
-{
-	if (mp_irq->dstapic != m->dstapic)
-		return 1;
-	if (mp_irq->type != m->type)
-		return 2;
-	if (mp_irq->irqtype != m->irqtype)
-		return 3;
-	if (mp_irq->irqflag != m->irqflag)
-		return 4;
-	if (mp_irq->srcbus != m->srcbus)
-		return 5;
-	if (mp_irq->srcbusirq != m->srcbusirq)
-		return 6;
-	if (mp_irq->dstirq != m->dstirq)
-		return 7;
-
-	return 0;
-}
-
-static void __init MP_intsrc_info(struct mpc_intsrc *m)
-{
-	int i;
-
-	print_MP_intsrc_info(m);
-
-	for (i = 0; i < mp_irq_entries; i++) {
-		if (!mp_irq_mpc_intsrc_cmp(&mp_irqs[i], m))
-			return;
-	}
-
-	assign_to_mp_irq(m, &mp_irqs[mp_irq_entries]);
-	if (++mp_irq_entries == MAX_IRQ_SOURCES)
-		panic("Max # of irq sources exceeded!!\n");
-}
 #else /* CONFIG_X86_IO_APIC */
 static inline void __init MP_bus_info(struct mpc_bus *m) {}
 static inline void __init MP_ioapic_info(struct mpc_ioapic *m) {}
-static inline void __init MP_intsrc_info(struct mpc_intsrc *m) {}
 #endif /* CONFIG_X86_IO_APIC */
 
-
 static void __init MP_lintsrc_info(struct mpc_lintsrc *m)
 {
 	apic_printk(APIC_VERBOSE, "Lint: type %d, pol %d, trig %d, bus %02x,"
@@ -222,7 +147,6 @@ static void __init MP_lintsrc_info(struc
 /*
  * Read/parse the MPC
  */
-
 static int __init smp_check_mpc(struct mpc_table *mpc, char *oem, char *str)
 {
 
@@ -275,18 +199,6 @@ static void __init smp_dump_mptable(stru
 
 void __init default_smp_read_mpc_oem(struct mpc_table *mpc) { }
 
-static void __init smp_register_lapic_address(unsigned long address)
-{
-	mp_lapic_addr = address;
-
-	set_fixmap_nocache(FIX_APIC_BASE, address);
-	if (boot_cpu_physical_apicid == -1U) {
-		boot_cpu_physical_apicid  = read_apic_id();
-		apic_version[boot_cpu_physical_apicid] =
-			 GET_APIC_VERSION(apic_read(APIC_LVR));
-	}
-}
-
 static int __init smp_read_mpc(struct mpc_table *mpc, unsigned early)
 {
 	char str[16];
@@ -301,17 +213,13 @@ static int __init smp_read_mpc(struct mp
 #ifdef CONFIG_X86_32
 	generic_mps_oem_check(mpc, oem, str);
 #endif
-	/* save the local APIC address, it might be non-default */
+	/* Initialize the lapic mapping */
 	if (!acpi_lapic)
-		mp_lapic_addr = mpc->lapic;
+		register_lapic_address(mpc->lapic);
 
 	if (early)
 		return 1;
 
-	/* Initialize the lapic mapping */
-	if (!acpi_lapic)
-		smp_register_lapic_address(mpc->lapic);
-
 	if (mpc->oemptr)
 		x86_init.mpparse.smp_read_mpc_oem(mpc);
 
@@ -337,7 +245,7 @@ static int __init smp_read_mpc(struct mp
 			skip_entry(&mpt, &count, sizeof(struct mpc_ioapic));
 			break;
 		case MP_INTSRC:
-			MP_intsrc_info((struct mpc_intsrc *)mpt);
+			mp_save_irq((struct mpc_intsrc *)mpt);
 			skip_entry(&mpt, &count, sizeof(struct mpc_intsrc));
 			break;
 		case MP_LINTSRC:
@@ -429,13 +337,13 @@ static void __init construct_default_ioi
 
 		intsrc.srcbusirq = i;
 		intsrc.dstirq = i ? i : 2;	/* IRQ0 to INTIN2 */
-		MP_intsrc_info(&intsrc);
+		mp_save_irq(&intsrc);
 	}
 
 	intsrc.irqtype = mp_ExtINT;
 	intsrc.srcbusirq = 0;
 	intsrc.dstirq = 0;	/* 8259A to INTIN0 */
-	MP_intsrc_info(&intsrc);
+	mp_save_irq(&intsrc);
 }
 
 
@@ -784,11 +692,11 @@ static void __init check_irq_src(struct
 	int i;
 
 	apic_printk(APIC_VERBOSE, "OLD ");
-	print_MP_intsrc_info(m);
+	print_mp_irq_info(m);
 
 	i = get_MP_intsrc_index(m);
 	if (i > 0) {
-		assign_to_mpc_intsrc(&mp_irqs[i], m);
+		memcpy(m, &mp_irqs[i], sizeof(*m));
 		apic_printk(APIC_VERBOSE, "NEW ");
 		print_mp_irq_info(&mp_irqs[i]);
 		return;
@@ -875,14 +783,14 @@ static int  __init replace_intsrc_all(st
 		if (nr_m_spare > 0) {
 			apic_printk(APIC_VERBOSE, "*NEW* found\n");
 			nr_m_spare--;
-			assign_to_mpc_intsrc(&mp_irqs[i], m_spare[nr_m_spare]);
+			memcpy(m_spare[nr_m_spare], &mp_irqs[i], sizeof(mp_irqs[i]));
 			m_spare[nr_m_spare] = NULL;
 		} else {
 			struct mpc_intsrc *m = (struct mpc_intsrc *)mpt;
 			count += sizeof(struct mpc_intsrc);
 			if (check_slot(mpc_new_phys, mpc_new_length, count) < 0)
 				goto out;
-			assign_to_mpc_intsrc(&mp_irqs[i], m);
+			memcpy(m, &mp_irqs[i], sizeof(*m));
 			mpc->length = count;
 			mpt += sizeof(struct mpc_intsrc);
 		}
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/kernel/paravirt.c linux-libre-2.6.38-gnu1/arch/x86/kernel/paravirt.c
--- linux-libre-2.6.37-gnu1/arch/x86/kernel/paravirt.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/kernel/paravirt.c	2011-03-14 21:20:32.000000000 -0400
@@ -421,8 +421,11 @@ struct pv_mmu_ops pv_mmu_ops = {
 	.set_pte = native_set_pte,
 	.set_pte_at = native_set_pte_at,
 	.set_pmd = native_set_pmd,
+	.set_pmd_at = native_set_pmd_at,
 	.pte_update = paravirt_nop,
 	.pte_update_defer = paravirt_nop,
+	.pmd_update = paravirt_nop,
+	.pmd_update_defer = paravirt_nop,
 
 	.ptep_modify_prot_start = __ptep_modify_prot_start,
 	.ptep_modify_prot_commit = __ptep_modify_prot_commit,
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/kernel/pci-gart_64.c linux-libre-2.6.38-gnu1/arch/x86/kernel/pci-gart_64.c
--- linux-libre-2.6.37-gnu1/arch/x86/kernel/pci-gart_64.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/kernel/pci-gart_64.c	2011-03-14 21:20:32.000000000 -0400
@@ -143,7 +143,7 @@ static void flush_gart(void)
 
 	spin_lock_irqsave(&iommu_bitmap_lock, flags);
 	if (need_flush) {
-		k8_flush_garts();
+		amd_flush_garts();
 		need_flush = false;
 	}
 	spin_unlock_irqrestore(&iommu_bitmap_lock, flags);
@@ -561,17 +561,17 @@ static void enable_gart_translations(voi
 {
 	int i;
 
-	if (!k8_northbridges.gart_supported)
+	if (!amd_nb_has_feature(AMD_NB_GART))
 		return;
 
-	for (i = 0; i < k8_northbridges.num; i++) {
-		struct pci_dev *dev = k8_northbridges.nb_misc[i];
+	for (i = 0; i < amd_nb_num(); i++) {
+		struct pci_dev *dev = node_to_amd_nb(i)->misc;
 
 		enable_gart_translation(dev, __pa(agp_gatt_table));
 	}
 
 	/* Flush the GART-TLB to remove stale entries */
-	k8_flush_garts();
+	amd_flush_garts();
 }
 
 /*
@@ -596,13 +596,13 @@ static void gart_fixup_northbridges(stru
 	if (!fix_up_north_bridges)
 		return;
 
-	if (!k8_northbridges.gart_supported)
+	if (!amd_nb_has_feature(AMD_NB_GART))
 		return;
 
 	pr_info("PCI-DMA: Restoring GART aperture settings\n");
 
-	for (i = 0; i < k8_northbridges.num; i++) {
-		struct pci_dev *dev = k8_northbridges.nb_misc[i];
+	for (i = 0; i < amd_nb_num(); i++) {
+		struct pci_dev *dev = node_to_amd_nb(i)->misc;
 
 		/*
 		 * Don't enable translations just yet.  That is the next
@@ -644,7 +644,7 @@ static struct sys_device device_gart = {
  * Private Northbridge GATT initialization in case we cannot use the
  * AGP driver for some reason.
  */
-static __init int init_k8_gatt(struct agp_kern_info *info)
+static __init int init_amd_gatt(struct agp_kern_info *info)
 {
 	unsigned aper_size, gatt_size, new_aper_size;
 	unsigned aper_base, new_aper_base;
@@ -656,8 +656,8 @@ static __init int init_k8_gatt(struct ag
 
 	aper_size = aper_base = info->aper_size = 0;
 	dev = NULL;
-	for (i = 0; i < k8_northbridges.num; i++) {
-		dev = k8_northbridges.nb_misc[i];
+	for (i = 0; i < amd_nb_num(); i++) {
+		dev = node_to_amd_nb(i)->misc;
 		new_aper_base = read_aperture(dev, &new_aper_size);
 		if (!new_aper_base)
 			goto nommu;
@@ -725,13 +725,13 @@ static void gart_iommu_shutdown(void)
 	if (!no_agp)
 		return;
 
-	if (!k8_northbridges.gart_supported)
+	if (!amd_nb_has_feature(AMD_NB_GART))
 		return;
 
-	for (i = 0; i < k8_northbridges.num; i++) {
+	for (i = 0; i < amd_nb_num(); i++) {
 		u32 ctl;
 
-		dev = k8_northbridges.nb_misc[i];
+		dev = node_to_amd_nb(i)->misc;
 		pci_read_config_dword(dev, AMD64_GARTAPERTURECTL, &ctl);
 
 		ctl &= ~GARTEN;
@@ -749,14 +749,14 @@ int __init gart_iommu_init(void)
 	unsigned long scratch;
 	long i;
 
-	if (!k8_northbridges.gart_supported)
+	if (!amd_nb_has_feature(AMD_NB_GART))
 		return 0;
 
 #ifndef CONFIG_AGP_AMD64
 	no_agp = 1;
 #else
 	/* Makefile puts PCI initialization via subsys_initcall first. */
-	/* Add other K8 AGP bridge drivers here */
+	/* Add other AMD AGP bridge drivers here */
 	no_agp = no_agp ||
 		(agp_amd64_init() < 0) ||
 		(agp_copy_info(agp_bridge, &info) < 0);
@@ -765,7 +765,7 @@ int __init gart_iommu_init(void)
 	if (no_iommu ||
 	    (!force_iommu && max_pfn <= MAX_DMA32_PFN) ||
 	    !gart_iommu_aperture ||
-	    (no_agp && init_k8_gatt(&info) < 0)) {
+	    (no_agp && init_amd_gatt(&info) < 0)) {
 		if (max_pfn > MAX_DMA32_PFN) {
 			pr_warning("More than 4GB of memory but GART IOMMU not available.\n");
 			pr_warning("falling back to iommu=soft.\n");
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/kernel/process_32.c linux-libre-2.6.38-gnu1/arch/x86/kernel/process_32.c
--- linux-libre-2.6.37-gnu1/arch/x86/kernel/process_32.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/kernel/process_32.c	2011-03-14 21:20:32.000000000 -0400
@@ -57,8 +57,6 @@
 #include <asm/syscalls.h>
 #include <asm/debugreg.h>
 
-#include <trace/events/power.h>
-
 asmlinkage void ret_from_fork(void) __asm__("ret_from_fork");
 
 /*
@@ -113,8 +111,6 @@ void cpu_idle(void)
 			stop_critical_timings();
 			pm_idle();
 			start_critical_timings();
-
-			trace_power_end(smp_processor_id());
 		}
 		tick_nohz_restart_sched_tick();
 		preempt_enable_no_resched();
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/kernel/process_64.c linux-libre-2.6.38-gnu1/arch/x86/kernel/process_64.c
--- linux-libre-2.6.37-gnu1/arch/x86/kernel/process_64.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/kernel/process_64.c	2011-03-14 21:20:32.000000000 -0400
@@ -51,8 +51,6 @@
 #include <asm/syscalls.h>
 #include <asm/debugreg.h>
 
-#include <trace/events/power.h>
-
 asmlinkage extern void ret_from_fork(void);
 
 DEFINE_PER_CPU(unsigned long, old_rsp);
@@ -141,8 +139,6 @@ void cpu_idle(void)
 			pm_idle();
 			start_critical_timings();
 
-			trace_power_end(smp_processor_id());
-
 			/* In many cases the interrupt that ended idle
 			   has already called exit_idle. But some idle
 			   loops can be woken up without interrupt. */
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/kernel/process.c linux-libre-2.6.38-gnu1/arch/x86/kernel/process.c
--- linux-libre-2.6.37-gnu1/arch/x86/kernel/process.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/kernel/process.c	2011-03-14 21:20:32.000000000 -0400
@@ -14,6 +14,7 @@
 #include <linux/utsname.h>
 #include <trace/events/power.h>
 #include <linux/hw_breakpoint.h>
+#include <asm/cpu.h>
 #include <asm/system.h>
 #include <asm/apic.h>
 #include <asm/syscalls.h>
@@ -22,11 +23,6 @@
 #include <asm/i387.h>
 #include <asm/debugreg.h>
 
-unsigned long idle_halt;
-EXPORT_SYMBOL(idle_halt);
-unsigned long idle_nomwait;
-EXPORT_SYMBOL(idle_nomwait);
-
 struct kmem_cache *task_xstate_cachep;
 EXPORT_SYMBOL_GPL(task_xstate_cachep);
 
@@ -91,27 +87,36 @@ void exit_thread(void)
 void show_regs(struct pt_regs *regs)
 {
 	show_registers(regs);
-	show_trace(NULL, regs, (unsigned long *)kernel_stack_pointer(regs),
-		   regs->bp);
+	show_trace(NULL, regs, (unsigned long *)kernel_stack_pointer(regs));
 }
 
 void show_regs_common(void)
 {
-	const char *board, *product;
+	const char *vendor, *product, *board;
 
-	board = dmi_get_system_info(DMI_BOARD_NAME);
-	if (!board)
-		board = "";
+	vendor = dmi_get_system_info(DMI_SYS_VENDOR);
+	if (!vendor)
+		vendor = "";
 	product = dmi_get_system_info(DMI_PRODUCT_NAME);
 	if (!product)
 		product = "";
 
+	/* Board Name is optional */
+	board = dmi_get_system_info(DMI_BOARD_NAME);
+
 	printk(KERN_CONT "\n");
-	printk(KERN_DEFAULT "Pid: %d, comm: %.20s %s %s %.*s %s/%s\n",
+	printk(KERN_DEFAULT "Pid: %d, comm: %.20s %s %s %.*s",
 		current->pid, current->comm, print_tainted(),
 		init_utsname()->release,
 		(int)strcspn(init_utsname()->version, " "),
-		init_utsname()->version, board, product);
+		init_utsname()->version);
+	printk(KERN_CONT " ");
+	printk(KERN_CONT "%s %s", vendor, product);
+	if (board) {
+		printk(KERN_CONT "/");
+		printk(KERN_CONT "%s", board);
+	}
+	printk(KERN_CONT "\n");
 }
 
 void flush_thread(void)
@@ -328,7 +333,7 @@ long sys_execve(const char __user *name,
 /*
  * Idle related variables and functions
  */
-unsigned long boot_option_idle_override = 0;
+unsigned long boot_option_idle_override = IDLE_NO_OVERRIDE;
 EXPORT_SYMBOL(boot_option_idle_override);
 
 /*
@@ -374,6 +379,7 @@ void default_idle(void)
 {
 	if (hlt_use_halt()) {
 		trace_power_start(POWER_CSTATE, 1, smp_processor_id());
+		trace_cpu_idle(1, smp_processor_id());
 		current_thread_info()->status &= ~TS_POLLING;
 		/*
 		 * TS_POLLING-cleared state must be visible before we
@@ -386,6 +392,8 @@ void default_idle(void)
 		else
 			local_irq_enable();
 		current_thread_info()->status |= TS_POLLING;
+		trace_power_end(smp_processor_id());
+		trace_cpu_idle(PWR_EVENT_EXIT, smp_processor_id());
 	} else {
 		local_irq_enable();
 		/* loop is done by the caller */
@@ -443,9 +451,8 @@ EXPORT_SYMBOL_GPL(cpu_idle_wait);
  */
 void mwait_idle_with_hints(unsigned long ax, unsigned long cx)
 {
-	trace_power_start(POWER_CSTATE, (ax>>4)+1, smp_processor_id());
 	if (!need_resched()) {
-		if (cpu_has(&current_cpu_data, X86_FEATURE_CLFLUSH_MONITOR))
+		if (cpu_has(__this_cpu_ptr(&cpu_info), X86_FEATURE_CLFLUSH_MONITOR))
 			clflush((void *)&current_thread_info()->flags);
 
 		__monitor((void *)&current_thread_info()->flags, 0, 0);
@@ -460,7 +467,8 @@ static void mwait_idle(void)
 {
 	if (!need_resched()) {
 		trace_power_start(POWER_CSTATE, 1, smp_processor_id());
-		if (cpu_has(&current_cpu_data, X86_FEATURE_CLFLUSH_MONITOR))
+		trace_cpu_idle(1, smp_processor_id());
+		if (cpu_has(__this_cpu_ptr(&cpu_info), X86_FEATURE_CLFLUSH_MONITOR))
 			clflush((void *)&current_thread_info()->flags);
 
 		__monitor((void *)&current_thread_info()->flags, 0, 0);
@@ -469,6 +477,8 @@ static void mwait_idle(void)
 			__sti_mwait(0, 0);
 		else
 			local_irq_enable();
+		trace_power_end(smp_processor_id());
+		trace_cpu_idle(PWR_EVENT_EXIT, smp_processor_id());
 	} else
 		local_irq_enable();
 }
@@ -481,10 +491,12 @@ static void mwait_idle(void)
 static void poll_idle(void)
 {
 	trace_power_start(POWER_CSTATE, 0, smp_processor_id());
+	trace_cpu_idle(0, smp_processor_id());
 	local_irq_enable();
 	while (!need_resched())
 		cpu_relax();
-	trace_power_end(0);
+	trace_power_end(smp_processor_id());
+	trace_cpu_idle(PWR_EVENT_EXIT, smp_processor_id());
 }
 
 /*
@@ -499,17 +511,16 @@ static void poll_idle(void)
  *
  * idle=mwait overrides this decision and forces the usage of mwait.
  */
-static int __cpuinitdata force_mwait;
 
 #define MWAIT_INFO			0x05
 #define MWAIT_ECX_EXTENDED_INFO		0x01
 #define MWAIT_EDX_C1			0xf0
 
-static int __cpuinit mwait_usable(const struct cpuinfo_x86 *c)
+int mwait_usable(const struct cpuinfo_x86 *c)
 {
 	u32 eax, ebx, ecx, edx;
 
-	if (force_mwait)
+	if (boot_option_idle_override == IDLE_FORCE_MWAIT)
 		return 1;
 
 	if (c->cpuid_level < MWAIT_INFO)
@@ -629,9 +640,10 @@ static int __init idle_setup(char *str)
 	if (!strcmp(str, "poll")) {
 		printk("using polling idle threads.\n");
 		pm_idle = poll_idle;
-	} else if (!strcmp(str, "mwait"))
-		force_mwait = 1;
-	else if (!strcmp(str, "halt")) {
+		boot_option_idle_override = IDLE_POLL;
+	} else if (!strcmp(str, "mwait")) {
+		boot_option_idle_override = IDLE_FORCE_MWAIT;
+	} else if (!strcmp(str, "halt")) {
 		/*
 		 * When the boot option of idle=halt is added, halt is
 		 * forced to be used for CPU idle. In such case CPU C2/C3
@@ -640,8 +652,7 @@ static int __init idle_setup(char *str)
 		 * the boot_option_idle_override.
 		 */
 		pm_idle = default_idle;
-		idle_halt = 1;
-		return 0;
+		boot_option_idle_override = IDLE_HALT;
 	} else if (!strcmp(str, "nomwait")) {
 		/*
 		 * If the boot option of "idle=nomwait" is added,
@@ -649,12 +660,10 @@ static int __init idle_setup(char *str)
 		 * states. In such case it won't touch the variable
 		 * of boot_option_idle_override.
 		 */
-		idle_nomwait = 1;
-		return 0;
+		boot_option_idle_override = IDLE_NOMWAIT;
 	} else
 		return -1;
 
-	boot_option_idle_override = 1;
 	return 0;
 }
 early_param("idle", idle_setup);
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/kernel/reboot.c linux-libre-2.6.38-gnu1/arch/x86/kernel/reboot.c
--- linux-libre-2.6.37-gnu1/arch/x86/kernel/reboot.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/kernel/reboot.c	2011-03-14 21:20:32.000000000 -0400
@@ -18,6 +18,7 @@
 #include <asm/pci_x86.h>
 #include <asm/virtext.h>
 #include <asm/cpu.h>
+#include <asm/nmi.h>
 
 #ifdef CONFIG_X86_32
 # include <linux/ctype.h>
@@ -284,6 +285,14 @@ static struct dmi_system_id __initdata r
 			DMI_MATCH(DMI_BOARD_NAME, "P4S800"),
 		},
 	},
+	{	/* Handle problems with rebooting on VersaLogic Menlow boards */
+		.callback = set_bios_reboot,
+		.ident = "VersaLogic Menlow based board",
+		.matches = {
+			DMI_MATCH(DMI_BOARD_VENDOR, "VersaLogic Corporation"),
+			DMI_MATCH(DMI_BOARD_NAME, "VersaLogic Menlow board"),
+		},
+	},
 	{ }
 };
 
@@ -747,7 +756,7 @@ static int crash_nmi_callback(struct not
 {
 	int cpu;
 
-	if (val != DIE_NMI_IPI)
+	if (val != DIE_NMI)
 		return NOTIFY_OK;
 
 	cpu = raw_smp_processor_id();
@@ -778,6 +787,8 @@ static void smp_send_nmi_allbutself(void
 
 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
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/kernel/reboot_fixups_32.c linux-libre-2.6.38-gnu1/arch/x86/kernel/reboot_fixups_32.c
--- linux-libre-2.6.37-gnu1/arch/x86/kernel/reboot_fixups_32.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/kernel/reboot_fixups_32.c	2011-03-14 21:20:32.000000000 -0400
@@ -43,17 +43,33 @@ static void rdc321x_reset(struct pci_dev
 	outb(1, 0x92);
 }
 
+static void ce4100_reset(struct pci_dev *dev)
+{
+	int i;
+
+	for (i = 0; i < 10; i++) {
+		outb(0x2, 0xcf9);
+		udelay(50);
+	}
+}
+
 struct device_fixup {
 	unsigned int vendor;
 	unsigned int device;
 	void (*reboot_fixup)(struct pci_dev *);
 };
 
+/*
+ * PCI ids solely used for fixups_table go here
+ */
+#define PCI_DEVICE_ID_INTEL_CE4100	0x0708
+
 static const struct device_fixup fixups_table[] = {
 { PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5530_LEGACY, cs5530a_warm_reset },
 { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA, cs5536_warm_reset },
 { PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_SC1100_BRIDGE, cs5530a_warm_reset },
 { PCI_VENDOR_ID_RDC, PCI_DEVICE_ID_RDC_R6030, rdc321x_reset },
+{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CE4100, ce4100_reset },
 };
 
 /*
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/kernel/rtc.c linux-libre-2.6.38-gnu1/arch/x86/kernel/rtc.c
--- linux-libre-2.6.37-gnu1/arch/x86/kernel/rtc.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/kernel/rtc.c	2011-03-14 21:20:32.000000000 -0400
@@ -76,7 +76,7 @@ int mach_set_rtc_mmss(unsigned long nowt
 		CMOS_WRITE(real_seconds, RTC_SECONDS);
 		CMOS_WRITE(real_minutes, RTC_MINUTES);
 	} else {
-		printk(KERN_WARNING
+		printk_once(KERN_NOTICE
 		       "set_rtc_mmss: can't update from %d to %d\n",
 		       cmos_minutes, real_minutes);
 		retval = -1;
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/kernel/setup.c linux-libre-2.6.38-gnu1/arch/x86/kernel/setup.c
--- linux-libre-2.6.37-gnu1/arch/x86/kernel/setup.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/kernel/setup.c	2011-03-14 21:20:32.000000000 -0400
@@ -705,7 +705,7 @@ static u64 __init get_max_mapped(void)
 void __init setup_arch(char **cmdline_p)
 {
 	int acpi = 0;
-	int k8 = 0;
+	int amd = 0;
 	unsigned long flags;
 
 #ifdef CONFIG_X86_32
@@ -991,12 +991,12 @@ void __init setup_arch(char **cmdline_p)
 	acpi = acpi_numa_init();
 #endif
 
-#ifdef CONFIG_K8_NUMA
+#ifdef CONFIG_AMD_NUMA
 	if (!acpi)
-		k8 = !k8_numa_init(0, max_pfn);
+		amd = !amd_numa_init(0, max_pfn);
 #endif
 
-	initmem_init(0, max_pfn, acpi, k8);
+	initmem_init(0, max_pfn, acpi, amd);
 	memblock_find_dma_reserve();
 	dma32_reserve_bootmem();
 
@@ -1045,10 +1045,7 @@ void __init setup_arch(char **cmdline_p)
 #endif
 
 	init_apic_mappings();
-	ioapic_init_mappings();
-
-	/* need to wait for io_apic is mapped */
-	probe_nr_irqs_gsi();
+	ioapic_and_gsi_init();
 
 	kvm_guest_init();
 
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/kernel/smpboot.c linux-libre-2.6.38-gnu1/arch/x86/kernel/smpboot.c
--- linux-libre-2.6.37-gnu1/arch/x86/kernel/smpboot.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/kernel/smpboot.c	2011-03-14 21:20:32.000000000 -0400
@@ -97,12 +97,12 @@ static DEFINE_PER_CPU(struct task_struct
  */
 static DEFINE_MUTEX(x86_cpu_hotplug_driver_mutex);
 
-void cpu_hotplug_driver_lock()
+void cpu_hotplug_driver_lock(void)
 {
         mutex_lock(&x86_cpu_hotplug_driver_mutex);
 }
 
-void cpu_hotplug_driver_unlock()
+void cpu_hotplug_driver_unlock(void)
 {
         mutex_unlock(&x86_cpu_hotplug_driver_mutex);
 }
@@ -281,6 +281,13 @@ static void __cpuinit smp_callin(void)
 	 */
 	smp_store_cpu_info(cpuid);
 
+	/*
+	 * This must be done before setting cpu_online_mask
+	 * or calling notify_cpu_starting.
+	 */
+	set_cpu_sibling_map(raw_smp_processor_id());
+	wmb();
+
 	notify_cpu_starting(cpuid);
 
 	/*
@@ -316,16 +323,6 @@ notrace static void __cpuinit start_seco
 	 */
 	check_tsc_sync_target();
 
-	if (nmi_watchdog == NMI_IO_APIC) {
-		legacy_pic->mask(0);
-		enable_NMI_through_LVT0();
-		legacy_pic->unmask(0);
-	}
-
-	/* This must be done before setting cpu_online_mask */
-	set_cpu_sibling_map(raw_smp_processor_id());
-	wmb();
-
 	/*
 	 * We need to hold call_lock, so there is no inconsistency
 	 * between the time smp_call_function() determines number of
@@ -430,7 +427,7 @@ void __cpuinit set_cpu_sibling_map(int c
 
 	cpumask_set_cpu(cpu, c->llc_shared_map);
 
-	if (current_cpu_data.x86_max_cores == 1) {
+	if (__this_cpu_read(cpu_info.x86_max_cores) == 1) {
 		cpumask_copy(cpu_core_mask(cpu), cpu_sibling_mask(cpu));
 		c->booted_cores = 1;
 		return;
@@ -641,7 +638,7 @@ wakeup_secondary_cpu_via_init(int phys_a
 	 * target processor state.
 	 */
 	startup_ipi_hook(phys_apicid, (unsigned long) start_secondary,
-			 (unsigned long)stack_start.sp);
+			 stack_start);
 
 	/*
 	 * Run STARTUP IPI loop.
@@ -788,7 +785,7 @@ do_rest:
 #endif
 	early_gdt_descr.address = (unsigned long)get_cpu_gdt_table(cpu);
 	initial_code = (unsigned long)start_secondary;
-	stack_start.sp = (void *) c_idle.idle->thread.sp;
+	stack_start  = c_idle.idle->thread.sp;
 
 	/* start_ip had better be page-aligned! */
 	start_ip = setup_trampoline();
@@ -1061,11 +1058,9 @@ static int __init smp_sanity_check(unsig
 		printk(KERN_INFO "SMP mode deactivated.\n");
 		smpboot_clear_io_apic();
 
-		localise_nmi_watchdog();
-
 		connect_bsp_APIC();
 		setup_local_APIC();
-		end_local_APIC_setup();
+		bsp_end_local_APIC_setup();
 		return -1;
 	}
 
@@ -1094,7 +1089,7 @@ void __init native_smp_prepare_cpus(unsi
 
 	preempt_disable();
 	smp_cpu_index_default();
-	current_cpu_data = boot_cpu_data;
+	memcpy(__this_cpu_ptr(&cpu_info), &boot_cpu_data, sizeof(cpu_info));
 	cpumask_copy(cpu_callin_mask, cpumask_of(0));
 	mb();
 	/*
@@ -1142,7 +1137,7 @@ void __init native_smp_prepare_cpus(unsi
 	if (!skip_ioapic_setup && nr_ioapics)
 		enable_IO_APIC();
 
-	end_local_APIC_setup();
+	bsp_end_local_APIC_setup();
 
 	map_cpu_to_logical_apicid();
 
@@ -1166,6 +1161,20 @@ out:
 	preempt_enable();
 }
 
+void arch_disable_nonboot_cpus_begin(void)
+{
+	/*
+	 * Avoid the smp alternatives switch during the disable_nonboot_cpus().
+	 * In the suspend path, we will be back in the SMP mode shortly anyways.
+	 */
+	skip_smp_alternatives = true;
+}
+
+void arch_disable_nonboot_cpus_end(void)
+{
+	skip_smp_alternatives = false;
+}
+
 void arch_enable_nonboot_cpus_begin(void)
 {
 	set_mtrr_aps_delayed_init();
@@ -1196,7 +1205,6 @@ void __init native_smp_cpus_done(unsigne
 #ifdef CONFIG_X86_IO_APIC
 	setup_ioapic_dest();
 #endif
-	check_nmi_watchdog();
 	mtrr_aps_init();
 }
 
@@ -1341,8 +1349,6 @@ int native_cpu_disable(void)
 	if (cpu == 0)
 		return -EBUSY;
 
-	if (nmi_watchdog == NMI_LOCAL_APIC)
-		stop_apic_nmi_watchdog(NULL);
 	clear_local_APIC();
 
 	cpu_disable_common();
@@ -1377,7 +1383,7 @@ void play_dead_common(void)
 
 	mb();
 	/* Ack it */
-	__get_cpu_var(cpu_state) = CPU_DEAD;
+	__this_cpu_write(cpu_state, CPU_DEAD);
 
 	/*
 	 * With physical CPU hotplug, we should halt the cpu
@@ -1396,12 +1402,13 @@ static inline void mwait_play_dead(void)
 	unsigned int highest_subcstate = 0;
 	int i;
 	void *mwait_ptr;
+	struct cpuinfo_x86 *c = __this_cpu_ptr(&cpu_info);
 
-	if (!cpu_has(&current_cpu_data, X86_FEATURE_MWAIT))
+	if (!(cpu_has(c, X86_FEATURE_MWAIT) && mwait_usable(c)))
 		return;
-	if (!cpu_has(&current_cpu_data, X86_FEATURE_CLFLSH))
+	if (!cpu_has(__this_cpu_ptr(&cpu_info), X86_FEATURE_CLFLSH))
 		return;
-	if (current_cpu_data.cpuid_level < CPUID_MWAIT_LEAF)
+	if (__this_cpu_read(cpu_info.cpuid_level) < CPUID_MWAIT_LEAF)
 		return;
 
 	eax = CPUID_MWAIT_LEAF;
@@ -1452,7 +1459,7 @@ static inline void mwait_play_dead(void)
 
 static inline void hlt_play_dead(void)
 {
-	if (current_cpu_data.x86 >= 4)
+	if (__this_cpu_read(cpu_info.x86) >= 4)
 		wbinvd();
 
 	while (1) {
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/kernel/stacktrace.c linux-libre-2.6.38-gnu1/arch/x86/kernel/stacktrace.c
--- linux-libre-2.6.37-gnu1/arch/x86/kernel/stacktrace.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/kernel/stacktrace.c	2011-03-14 21:20:32.000000000 -0400
@@ -73,22 +73,22 @@ static const struct stacktrace_ops save_
  */
 void save_stack_trace(struct stack_trace *trace)
 {
-	dump_trace(current, NULL, NULL, 0, &save_stack_ops, trace);
+	dump_trace(current, NULL, NULL, &save_stack_ops, trace);
 	if (trace->nr_entries < trace->max_entries)
 		trace->entries[trace->nr_entries++] = ULONG_MAX;
 }
 EXPORT_SYMBOL_GPL(save_stack_trace);
 
-void save_stack_trace_bp(struct stack_trace *trace, unsigned long bp)
+void save_stack_trace_regs(struct stack_trace *trace, struct pt_regs *regs)
 {
-	dump_trace(current, NULL, NULL, bp, &save_stack_ops, trace);
+	dump_trace(current, regs, NULL, &save_stack_ops, trace);
 	if (trace->nr_entries < trace->max_entries)
 		trace->entries[trace->nr_entries++] = ULONG_MAX;
 }
 
 void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
 {
-	dump_trace(tsk, NULL, NULL, 0, &save_stack_ops_nosched, trace);
+	dump_trace(tsk, NULL, NULL, &save_stack_ops_nosched, trace);
 	if (trace->nr_entries < trace->max_entries)
 		trace->entries[trace->nr_entries++] = ULONG_MAX;
 }
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/kernel/tboot.c linux-libre-2.6.38-gnu1/arch/x86/kernel/tboot.c
--- linux-libre-2.6.37-gnu1/arch/x86/kernel/tboot.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/kernel/tboot.c	2011-03-14 21:20:32.000000000 -0400
@@ -133,7 +133,7 @@ static int map_tboot_page(unsigned long
 	pmd = pmd_alloc(&tboot_mm, pud, vaddr);
 	if (!pmd)
 		return -1;
-	pte = pte_alloc_map(&tboot_mm, pmd, vaddr);
+	pte = pte_alloc_map(&tboot_mm, NULL, pmd, vaddr);
 	if (!pte)
 		return -1;
 	set_pte_at(&tboot_mm, vaddr, pte, pfn_pte(pfn, prot));
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/kernel/time.c linux-libre-2.6.38-gnu1/arch/x86/kernel/time.c
--- linux-libre-2.6.37-gnu1/arch/x86/kernel/time.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/kernel/time.c	2011-03-14 21:20:32.000000000 -0400
@@ -22,10 +22,6 @@
 #include <asm/hpet.h>
 #include <asm/time.h>
 
-#if defined(CONFIG_X86_32) && defined(CONFIG_X86_IO_APIC)
-int timer_ack;
-#endif
-
 #ifdef CONFIG_X86_64
 volatile unsigned long __jiffies __section_jiffies = INITIAL_JIFFIES;
 #endif
@@ -63,20 +59,6 @@ static irqreturn_t timer_interrupt(int i
 	/* Keep nmi watchdog up to date */
 	inc_irq_stat(irq0_irqs);
 
-	/* Optimized out for !IO_APIC and x86_64 */
-	if (timer_ack) {
-		/*
-		 * Subtle, when I/O APICs are used we have to ack timer IRQ
-		 * manually to deassert NMI lines for the watchdog if run
-		 * on an 82489DX-based system.
-		 */
-		raw_spin_lock(&i8259A_lock);
-		outb(0x0c, PIC_MASTER_OCW3);
-		/* Ack the IRQ; AEOI will end it automatically. */
-		inb(PIC_MASTER_POLL);
-		raw_spin_unlock(&i8259A_lock);
-	}
-
 	global_clock_event->event_handler(global_clock_event);
 
 	/* MCA bus quirk: Acknowledge irq0 by setting bit 7 in port 0x61 */
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/kernel/trampoline_64.S linux-libre-2.6.38-gnu1/arch/x86/kernel/trampoline_64.S
--- linux-libre-2.6.37-gnu1/arch/x86/kernel/trampoline_64.S	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/kernel/trampoline_64.S	2011-03-14 21:20:32.000000000 -0400
@@ -127,7 +127,7 @@ startup_64:
 no_longmode:
 	hlt
 	jmp no_longmode
-#include "verify_cpu_64.S"
+#include "verify_cpu.S"
 
 	# Careful these need to be in the same 64K segment as the above;
 tidt:
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/kernel/traps.c linux-libre-2.6.38-gnu1/arch/x86/kernel/traps.c
--- linux-libre-2.6.37-gnu1/arch/x86/kernel/traps.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/kernel/traps.c	2011-03-14 21:20:32.000000000 -0400
@@ -83,6 +83,13 @@ 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)
@@ -300,16 +307,23 @@ gp_in_kernel:
 	die("general protection fault", regs, error_code);
 }
 
-static notrace __kprobes void
-mem_parity_error(unsigned char reason, struct pt_regs *regs)
+static int __init setup_unknown_nmi_panic(char *str)
 {
-	printk(KERN_EMERG
-		"Uhhuh. NMI received for unknown reason %02x on CPU %d.\n",
-			reason, smp_processor_id());
+	unknown_nmi_panic = 1;
+	return 1;
+}
+__setup("unknown_nmi_panic", setup_unknown_nmi_panic);
 
-	printk(KERN_EMERG
-		"You have some hardware problem, likely on the PCI bus.\n");
+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();
@@ -320,11 +334,11 @@ mem_parity_error(unsigned char reason, s
 	if (panic_on_unrecovered_nmi)
 		panic("NMI: Not continuing");
 
-	printk(KERN_EMERG "Dazed and confused, but trying to continue\n");
+	pr_emerg("Dazed and confused, but trying to continue\n");
 
-	/* Clear and disable the memory parity error line. */
-	reason = (reason & 0xf) | 4;
-	outb(reason, 0x61);
+	/* 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
@@ -332,22 +346,26 @@ io_check_error(unsigned char reason, str
 {
 	unsigned long i;
 
-	printk(KERN_EMERG "NMI: IOCK error (debug interrupt?)\n");
+	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 & 0xf) | 8;
-	outb(reason, 0x61);
+	reason = (reason & NMI_REASON_CLEAR_MASK) | NMI_REASON_CLEAR_IOCHK;
+	outb(reason, NMI_REASON_PORT);
 
-	i = 2000;
-	while (--i)
-		udelay(1000);
+	i = 20000;
+	while (--i) {
+		touch_nmi_watchdog();
+		udelay(100);
+	}
 
-	reason &= ~8;
-	outb(reason, 0x61);
+	reason &= ~NMI_REASON_CLEAR_IOCHK;
+	outb(reason, NMI_REASON_PORT);
 }
 
 static notrace __kprobes void
@@ -366,69 +384,50 @@ unknown_nmi_error(unsigned char reason,
 		return;
 	}
 #endif
-	printk(KERN_EMERG
-		"Uhhuh. NMI received for unknown reason %02x on CPU %d.\n",
-			reason, smp_processor_id());
+	pr_emerg("Uhhuh. NMI received for unknown reason %02x on CPU %d.\n",
+		 reason, smp_processor_id());
 
-	printk(KERN_EMERG "Do you have a strange power saving mode enabled?\n");
-	if (panic_on_unrecovered_nmi)
+	pr_emerg("Do you have a strange power saving mode enabled?\n");
+	if (unknown_nmi_panic || panic_on_unrecovered_nmi)
 		panic("NMI: Not continuing");
 
-	printk(KERN_EMERG "Dazed and confused, but trying to continue\n");
+	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;
-	int cpu;
 
-	cpu = smp_processor_id();
-
-	/* Only the BSP gets external NMIs from the system. */
-	if (!cpu)
-		reason = get_nmi_reason();
-
-	if (!(reason & 0xc0)) {
-		if (notify_die(DIE_NMI_IPI, "nmi_ipi", regs, reason, 2, SIGINT)
-								== NOTIFY_STOP)
-			return;
+	/*
+	 * 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;
 
-#ifdef CONFIG_X86_LOCAL_APIC
-		if (notify_die(DIE_NMI, "nmi", regs, reason, 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();
 
-#ifndef CONFIG_LOCKUP_DETECTOR
+	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
 		/*
-		 * Ok, so this is none of the documented NMI sources,
-		 * so it must be the NMI watchdog.
+		 * Reassert NMI in case it became active
+		 * meanwhile as it's edge-triggered:
 		 */
-		if (nmi_watchdog_tick(regs, reason))
-			return;
-		if (!do_nmi_callback(regs, cpu))
-#endif /* !CONFIG_LOCKUP_DETECTOR */
-			unknown_nmi_error(reason, regs);
-#else
-		unknown_nmi_error(reason, regs);
+		reassert_nmi();
 #endif
-
+		raw_spin_unlock(&nmi_reason_lock);
 		return;
 	}
-	if (notify_die(DIE_NMI, "nmi", regs, reason, 2, SIGINT) == NOTIFY_STOP)
-		return;
+	raw_spin_unlock(&nmi_reason_lock);
 
-	/* AK: following checks seem to be broken on modern chipsets. FIXME */
-	if (reason & 0x80)
-		mem_parity_error(reason, regs);
-	if (reason & 0x40)
-		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
+	unknown_nmi_error(reason, regs);
 }
 
 dotraplinkage notrace __kprobes void
@@ -446,14 +445,12 @@ do_nmi(struct pt_regs *regs, long error_
 
 void stop_nmi(void)
 {
-	acpi_nmi_disable();
 	ignore_nmis++;
 }
 
 void restart_nmi(void)
 {
 	ignore_nmis--;
-	acpi_nmi_enable();
 }
 
 /* May run on IST stack. */
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/kernel/tsc.c linux-libre-2.6.38-gnu1/arch/x86/kernel/tsc.c
--- linux-libre-2.6.37-gnu1/arch/x86/kernel/tsc.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/kernel/tsc.c	2011-03-14 21:20:32.000000000 -0400
@@ -464,7 +464,7 @@ unsigned long native_calibrate_tsc(void)
 		tsc_pit_min = min(tsc_pit_min, tsc_pit_khz);
 
 		/* hpet or pmtimer available ? */
-		if (!hpet && !ref1 && !ref2)
+		if (ref1 == ref2)
 			continue;
 
 		/* Check, whether the sampling was disturbed by an SMI */
@@ -659,7 +659,7 @@ void restore_sched_clock_state(void)
 
 	local_irq_save(flags);
 
-	__get_cpu_var(cyc2ns_offset) = 0;
+	__this_cpu_write(cyc2ns_offset, 0);
 	offset = cyc2ns_suspend - sched_clock();
 
 	for_each_possible_cpu(cpu)
@@ -872,6 +872,9 @@ __cpuinit int unsynchronized_tsc(void)
 
 	if (boot_cpu_has(X86_FEATURE_CONSTANT_TSC))
 		return 0;
+
+	if (tsc_clocksource_reliable)
+		return 0;
 	/*
 	 * Intel systems are normally all synchronized.
 	 * Exceptions must mark TSC as unstable:
@@ -879,14 +882,92 @@ __cpuinit int unsynchronized_tsc(void)
 	if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL) {
 		/* assume multi socket systems are not synchronized: */
 		if (num_possible_cpus() > 1)
-			tsc_unstable = 1;
+			return 1;
 	}
 
-	return tsc_unstable;
+	return 0;
 }
 
-static void __init init_tsc_clocksource(void)
+
+static void tsc_refine_calibration_work(struct work_struct *work);
+static DECLARE_DELAYED_WORK(tsc_irqwork, tsc_refine_calibration_work);
+/**
+ * tsc_refine_calibration_work - Further refine tsc freq calibration
+ * @work - ignored.
+ *
+ * This functions uses delayed work over a period of a
+ * second to further refine the TSC freq value. Since this is
+ * timer based, instead of loop based, we don't block the boot
+ * process while this longer calibration is done.
+ *
+ * If there are any calibration anomolies (too many SMIs, etc),
+ * or the refined calibration is off by 1% of the fast early
+ * calibration, we throw out the new calibration and use the
+ * early calibration.
+ */
+static void tsc_refine_calibration_work(struct work_struct *work)
+{
+	static u64 tsc_start = -1, ref_start;
+	static int hpet;
+	u64 tsc_stop, ref_stop, delta;
+	unsigned long freq;
+
+	/* Don't bother refining TSC on unstable systems */
+	if (check_tsc_unstable())
+		goto out;
+
+	/*
+	 * Since the work is started early in boot, we may be
+	 * delayed the first time we expire. So set the workqueue
+	 * again once we know timers are working.
+	 */
+	if (tsc_start == -1) {
+		/*
+		 * Only set hpet once, to avoid mixing hardware
+		 * if the hpet becomes enabled later.
+		 */
+		hpet = is_hpet_enabled();
+		schedule_delayed_work(&tsc_irqwork, HZ);
+		tsc_start = tsc_read_refs(&ref_start, hpet);
+		return;
+	}
+
+	tsc_stop = tsc_read_refs(&ref_stop, hpet);
+
+	/* hpet or pmtimer available ? */
+	if (ref_start == ref_stop)
+		goto out;
+
+	/* Check, whether the sampling was disturbed by an SMI */
+	if (tsc_start == ULLONG_MAX || tsc_stop == ULLONG_MAX)
+		goto out;
+
+	delta = tsc_stop - tsc_start;
+	delta *= 1000000LL;
+	if (hpet)
+		freq = calc_hpet_ref(delta, ref_start, ref_stop);
+	else
+		freq = calc_pmtimer_ref(delta, ref_start, ref_stop);
+
+	/* Make sure we're within 1% */
+	if (abs(tsc_khz - freq) > tsc_khz/100)
+		goto out;
+
+	tsc_khz = freq;
+	printk(KERN_INFO "Refined TSC clocksource calibration: "
+		"%lu.%03lu MHz.\n", (unsigned long)tsc_khz / 1000,
+					(unsigned long)tsc_khz % 1000);
+
+out:
+	clocksource_register_khz(&clocksource_tsc, tsc_khz);
+}
+
+
+static int __init init_tsc_clocksource(void)
 {
+	if (!cpu_has_tsc || tsc_disabled > 0 || !tsc_khz)
+		return 0;
+
 	if (tsc_clocksource_reliable)
 		clocksource_tsc.flags &= ~CLOCK_SOURCE_MUST_VERIFY;
 	/* lower the rating if we already know its unstable: */
@@ -894,8 +975,14 @@ static void __init init_tsc_clocksource(
 		clocksource_tsc.rating = 0;
 		clocksource_tsc.flags &= ~CLOCK_SOURCE_IS_CONTINUOUS;
 	}
-	clocksource_register_khz(&clocksource_tsc, tsc_khz);
+	schedule_delayed_work(&tsc_irqwork, 0);
+	return 0;
 }
+/*
+ * We use device_initcall here, to ensure we run after the hpet
+ * is fully initialized, which may occur at fs_initcall time.
+ */
+device_initcall(init_tsc_clocksource);
 
 void __init tsc_init(void)
 {
@@ -949,6 +1036,5 @@ void __init tsc_init(void)
 		mark_tsc_unstable("TSCs unsynchronized");
 
 	check_system_tsc_reliable();
-	init_tsc_clocksource();
 }
 
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/kernel/verify_cpu_64.S linux-libre-2.6.38-gnu1/arch/x86/kernel/verify_cpu_64.S
--- linux-libre-2.6.37-gnu1/arch/x86/kernel/verify_cpu_64.S	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/kernel/verify_cpu_64.S	1969-12-31 19:00:00.000000000 -0500
@@ -1,106 +0,0 @@
-/*
- *
- *	verify_cpu.S - Code for cpu long mode and SSE verification. This
- *	code has been borrowed from boot/setup.S and was introduced by
- * 	Andi Kleen.
- *
- *	Copyright (c) 2007  Andi Kleen (ak@suse.de)
- *	Copyright (c) 2007  Eric Biederman (ebiederm@xmission.com)
- *	Copyright (c) 2007  Vivek Goyal (vgoyal@in.ibm.com)
- *
- * 	This source code is licensed under the GNU General Public License,
- * 	Version 2.  See the file COPYING for more details.
- *
- *	This is a common code for verification whether CPU supports
- * 	long mode and SSE or not. It is not called directly instead this
- *	file is included at various places and compiled in that context.
- * 	Following are the current usage.
- *
- * 	This file is included by both 16bit and 32bit code.
- *
- *	arch/x86_64/boot/setup.S : Boot cpu verification (16bit)
- *	arch/x86_64/boot/compressed/head.S: Boot cpu verification (32bit)
- *	arch/x86_64/kernel/trampoline.S: secondary processor verfication (16bit)
- *	arch/x86_64/kernel/acpi/wakeup.S:Verfication at resume (16bit)
- *
- *	verify_cpu, returns the status of cpu check in register %eax.
- *		0: Success    1: Failure
- *
- * 	The caller needs to check for the error code and take the action
- * 	appropriately. Either display a message or halt.
- */
-
-#include <asm/cpufeature.h>
-#include <asm/msr-index.h>
-
-verify_cpu:
-	pushfl				# Save caller passed flags
-	pushl	$0			# Kill any dangerous flags
-	popfl
-
-	pushfl				# standard way to check for cpuid
-	popl	%eax
-	movl	%eax,%ebx
-	xorl	$0x200000,%eax
-	pushl	%eax
-	popfl
-	pushfl
-	popl	%eax
-	cmpl	%eax,%ebx
-	jz	verify_cpu_no_longmode	# cpu has no cpuid
-
-	movl	$0x0,%eax		# See if cpuid 1 is implemented
-	cpuid
-	cmpl	$0x1,%eax
-	jb	verify_cpu_no_longmode	# no cpuid 1
-
-	xor	%di,%di
-	cmpl	$0x68747541,%ebx	# AuthenticAMD
-	jnz	verify_cpu_noamd
-	cmpl	$0x69746e65,%edx
-	jnz	verify_cpu_noamd
-	cmpl	$0x444d4163,%ecx
-	jnz	verify_cpu_noamd
-	mov	$1,%di			# cpu is from AMD
-
-verify_cpu_noamd:
-	movl    $0x1,%eax		# Does the cpu have what it takes
-	cpuid
-	andl	$REQUIRED_MASK0,%edx
-	xorl	$REQUIRED_MASK0,%edx
-	jnz	verify_cpu_no_longmode
-
-	movl    $0x80000000,%eax	# See if extended cpuid is implemented
-	cpuid
-	cmpl    $0x80000001,%eax
-	jb      verify_cpu_no_longmode	# no extended cpuid
-
-	movl    $0x80000001,%eax	# Does the cpu have what it takes
-	cpuid
-	andl    $REQUIRED_MASK1,%edx
-	xorl    $REQUIRED_MASK1,%edx
-	jnz     verify_cpu_no_longmode
-
-verify_cpu_sse_test:
-	movl	$1,%eax
-	cpuid
-	andl	$SSE_MASK,%edx
-	cmpl	$SSE_MASK,%edx
-	je	verify_cpu_sse_ok
-	test	%di,%di
-	jz	verify_cpu_no_longmode	# only try to force SSE on AMD
-	movl	$MSR_K7_HWCR,%ecx
-	rdmsr
-	btr	$15,%eax		# enable SSE
-	wrmsr
-	xor	%di,%di			# don't loop
-	jmp	verify_cpu_sse_test	# try again
-
-verify_cpu_no_longmode:
-	popfl				# Restore caller passed flags
-	movl $1,%eax
-	ret
-verify_cpu_sse_ok:
-	popfl				# Restore caller passed flags
-	xorl %eax, %eax
-	ret
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/kernel/verify_cpu.S linux-libre-2.6.38-gnu1/arch/x86/kernel/verify_cpu.S
--- linux-libre-2.6.37-gnu1/arch/x86/kernel/verify_cpu.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/kernel/verify_cpu.S	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,139 @@
+/*
+ *
+ *	verify_cpu.S - Code for cpu long mode and SSE verification. This
+ *	code has been borrowed from boot/setup.S and was introduced by
+ * 	Andi Kleen.
+ *
+ *	Copyright (c) 2007  Andi Kleen (ak@suse.de)
+ *	Copyright (c) 2007  Eric Biederman (ebiederm@xmission.com)
+ *	Copyright (c) 2007  Vivek Goyal (vgoyal@in.ibm.com)
+ *	Copyright (c) 2010  Kees Cook (kees.cook@canonical.com)
+ *
+ * 	This source code is licensed under the GNU General Public License,
+ * 	Version 2.  See the file COPYING for more details.
+ *
+ *	This is a common code for verification whether CPU supports
+ * 	long mode and SSE or not. It is not called directly instead this
+ *	file is included at various places and compiled in that context.
+ *	This file is expected to run in 32bit code.  Currently:
+ *
+ *	arch/x86/boot/compressed/head_64.S: Boot cpu verification
+ *	arch/x86/kernel/trampoline_64.S: secondary processor verfication
+ *	arch/x86/kernel/head_32.S: processor startup
+ *
+ *	verify_cpu, returns the status of longmode and SSE in register %eax.
+ *		0: Success    1: Failure
+ *
+ *	On Intel, the XD_DISABLE flag will be cleared as a side-effect.
+ *
+ * 	The caller needs to check for the error code and take the action
+ * 	appropriately. Either display a message or halt.
+ */
+
+#include <asm/cpufeature.h>
+#include <asm/msr-index.h>
+
+verify_cpu:
+	pushfl				# Save caller passed flags
+	pushl	$0			# Kill any dangerous flags
+	popfl
+
+	pushfl				# standard way to check for cpuid
+	popl	%eax
+	movl	%eax,%ebx
+	xorl	$0x200000,%eax
+	pushl	%eax
+	popfl
+	pushfl
+	popl	%eax
+	cmpl	%eax,%ebx
+	jz	verify_cpu_no_longmode	# cpu has no cpuid
+
+	movl	$0x0,%eax		# See if cpuid 1 is implemented
+	cpuid
+	cmpl	$0x1,%eax
+	jb	verify_cpu_no_longmode	# no cpuid 1
+
+	xor	%di,%di
+	cmpl	$0x68747541,%ebx	# AuthenticAMD
+	jnz	verify_cpu_noamd
+	cmpl	$0x69746e65,%edx
+	jnz	verify_cpu_noamd
+	cmpl	$0x444d4163,%ecx
+	jnz	verify_cpu_noamd
+	mov	$1,%di			# cpu is from AMD
+	jmp	verify_cpu_check
+
+verify_cpu_noamd:
+	cmpl	$0x756e6547,%ebx        # GenuineIntel?
+	jnz	verify_cpu_check
+	cmpl	$0x49656e69,%edx
+	jnz	verify_cpu_check
+	cmpl	$0x6c65746e,%ecx
+	jnz	verify_cpu_check
+
+	# only call IA32_MISC_ENABLE when:
+	# family > 6 || (family == 6 && model >= 0xd)
+	movl	$0x1, %eax		# check CPU family and model
+	cpuid
+	movl	%eax, %ecx
+
+	andl	$0x0ff00f00, %eax	# mask family and extended family
+	shrl	$8, %eax
+	cmpl	$6, %eax
+	ja	verify_cpu_clear_xd	# family > 6, ok
+	jb	verify_cpu_check	# family < 6, skip
+
+	andl	$0x000f00f0, %ecx	# mask model and extended model
+	shrl	$4, %ecx
+	cmpl	$0xd, %ecx
+	jb	verify_cpu_check	# family == 6, model < 0xd, skip
+
+verify_cpu_clear_xd:
+	movl	$MSR_IA32_MISC_ENABLE, %ecx
+	rdmsr
+	btrl	$2, %edx		# clear MSR_IA32_MISC_ENABLE_XD_DISABLE
+	jnc	verify_cpu_check	# only write MSR if bit was changed
+	wrmsr
+
+verify_cpu_check:
+	movl    $0x1,%eax		# Does the cpu have what it takes
+	cpuid
+	andl	$REQUIRED_MASK0,%edx
+	xorl	$REQUIRED_MASK0,%edx
+	jnz	verify_cpu_no_longmode
+
+	movl    $0x80000000,%eax	# See if extended cpuid is implemented
+	cpuid
+	cmpl    $0x80000001,%eax
+	jb      verify_cpu_no_longmode	# no extended cpuid
+
+	movl    $0x80000001,%eax	# Does the cpu have what it takes
+	cpuid
+	andl    $REQUIRED_MASK1,%edx
+	xorl    $REQUIRED_MASK1,%edx
+	jnz     verify_cpu_no_longmode
+
+verify_cpu_sse_test:
+	movl	$1,%eax
+	cpuid
+	andl	$SSE_MASK,%edx
+	cmpl	$SSE_MASK,%edx
+	je	verify_cpu_sse_ok
+	test	%di,%di
+	jz	verify_cpu_no_longmode	# only try to force SSE on AMD
+	movl	$MSR_K7_HWCR,%ecx
+	rdmsr
+	btr	$15,%eax		# enable SSE
+	wrmsr
+	xor	%di,%di			# don't loop
+	jmp	verify_cpu_sse_test	# try again
+
+verify_cpu_no_longmode:
+	popfl				# Restore caller passed flags
+	movl $1,%eax
+	ret
+verify_cpu_sse_ok:
+	popfl				# Restore caller passed flags
+	xorl %eax, %eax
+	ret
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/kernel/vm86_32.c linux-libre-2.6.38-gnu1/arch/x86/kernel/vm86_32.c
--- linux-libre-2.6.37-gnu1/arch/x86/kernel/vm86_32.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/kernel/vm86_32.c	2011-03-14 21:20:32.000000000 -0400
@@ -179,6 +179,7 @@ static void mark_screen_rdonly(struct mm
 	if (pud_none_or_clear_bad(pud))
 		goto out;
 	pmd = pmd_offset(pud, 0xA0000);
+	split_huge_page_pmd(mm, pmd);
 	if (pmd_none_or_clear_bad(pmd))
 		goto out;
 	pte = pte_offset_map_lock(mm, pmd, 0xA0000, &ptl);
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/kernel/vmlinux.lds.S linux-libre-2.6.38-gnu1/arch/x86/kernel/vmlinux.lds.S
--- linux-libre-2.6.37-gnu1/arch/x86/kernel/vmlinux.lds.S	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/kernel/vmlinux.lds.S	2011-03-14 21:20:32.000000000 -0400
@@ -69,7 +69,7 @@ jiffies_64 = jiffies;
 
 PHDRS {
 	text PT_LOAD FLAGS(5);          /* R_E */
-	data PT_LOAD FLAGS(7);          /* RWE */
+	data PT_LOAD FLAGS(6);          /* RW_ */
 #ifdef CONFIG_X86_64
 	user PT_LOAD FLAGS(5);          /* R_E */
 #ifdef CONFIG_SMP
@@ -116,6 +116,10 @@ SECTIONS
 
 	EXCEPTION_TABLE(16) :text = 0x9090
 
+#if defined(CONFIG_DEBUG_RODATA)
+	/* .text should occupy whole number of pages */
+	. = ALIGN(PAGE_SIZE);
+#endif
 	X64_ALIGN_DEBUG_RODATA_BEGIN
 	RO_DATA(PAGE_SIZE)
 	X64_ALIGN_DEBUG_RODATA_END
@@ -335,7 +339,7 @@ SECTIONS
 		__bss_start = .;
 		*(.bss..page_aligned)
 		*(.bss)
-		. = ALIGN(4);
+		. = ALIGN(PAGE_SIZE);
 		__bss_stop = .;
 	}
 
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/kvm/emulate.c linux-libre-2.6.38-gnu1/arch/x86/kvm/emulate.c
--- linux-libre-2.6.37-gnu1/arch/x86/kvm/emulate.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/kvm/emulate.c	2011-03-14 21:20:32.000000000 -0400
@@ -20,16 +20,8 @@
  * From: xen-unstable 10676:af9809f51f81a3c43f276f00c81a52ef558afda4
  */
 
-#ifndef __KERNEL__
-#include <stdio.h>
-#include <stdint.h>
-#include <public/xen.h>
-#define DPRINTF(_f, _a ...) printf(_f , ## _a)
-#else
 #include <linux/kvm_host.h>
 #include "kvm_cache_regs.h"
-#define DPRINTF(x...) do {} while (0)
-#endif
 #include <linux/module.h>
 #include <asm/kvm_emulate.h>
 
@@ -418,9 +410,9 @@ address_mask(struct decode_cache *c, uns
 }
 
 static inline unsigned long
-register_address(struct decode_cache *c, unsigned long base, unsigned long reg)
+register_address(struct decode_cache *c, unsigned long reg)
 {
-	return base + address_mask(c, reg);
+	return address_mask(c, reg);
 }
 
 static inline void
@@ -452,60 +444,55 @@ static unsigned long seg_base(struct x86
 	return ops->get_cached_segment_base(seg, ctxt->vcpu);
 }
 
-static unsigned long seg_override_base(struct x86_emulate_ctxt *ctxt,
-				       struct x86_emulate_ops *ops,
-				       struct decode_cache *c)
+static unsigned seg_override(struct x86_emulate_ctxt *ctxt,
+			     struct x86_emulate_ops *ops,
+			     struct decode_cache *c)
 {
 	if (!c->has_seg_override)
 		return 0;
 
-	return seg_base(ctxt, ops, c->seg_override);
-}
-
-static unsigned long es_base(struct x86_emulate_ctxt *ctxt,
-			     struct x86_emulate_ops *ops)
-{
-	return seg_base(ctxt, ops, VCPU_SREG_ES);
+	return c->seg_override;
 }
 
-static unsigned long ss_base(struct x86_emulate_ctxt *ctxt,
-			     struct x86_emulate_ops *ops)
+static ulong linear(struct x86_emulate_ctxt *ctxt,
+		    struct segmented_address addr)
 {
-	return seg_base(ctxt, ops, VCPU_SREG_SS);
-}
+	struct decode_cache *c = &ctxt->decode;
+	ulong la;
 
-static void emulate_exception(struct x86_emulate_ctxt *ctxt, int vec,
-				      u32 error, bool valid)
-{
-	ctxt->exception = vec;
-	ctxt->error_code = error;
-	ctxt->error_code_valid = valid;
+	la = seg_base(ctxt, ctxt->ops, addr.seg) + addr.ea;
+	if (c->ad_bytes != 8)
+		la &= (u32)-1;
+	return la;
 }
 
-static void emulate_gp(struct x86_emulate_ctxt *ctxt, int err)
+static int emulate_exception(struct x86_emulate_ctxt *ctxt, int vec,
+			     u32 error, bool valid)
 {
-	emulate_exception(ctxt, GP_VECTOR, err, true);
+	ctxt->exception.vector = vec;
+	ctxt->exception.error_code = error;
+	ctxt->exception.error_code_valid = valid;
+	return X86EMUL_PROPAGATE_FAULT;
 }
 
-static void emulate_pf(struct x86_emulate_ctxt *ctxt)
+static int emulate_gp(struct x86_emulate_ctxt *ctxt, int err)
 {
-	emulate_exception(ctxt, PF_VECTOR, 0, true);
+	return emulate_exception(ctxt, GP_VECTOR, err, true);
 }
 
-static void emulate_ud(struct x86_emulate_ctxt *ctxt)
+static int emulate_ud(struct x86_emulate_ctxt *ctxt)
 {
-	emulate_exception(ctxt, UD_VECTOR, 0, false);
+	return emulate_exception(ctxt, UD_VECTOR, 0, false);
 }
 
-static void emulate_ts(struct x86_emulate_ctxt *ctxt, int err)
+static int emulate_ts(struct x86_emulate_ctxt *ctxt, int err)
 {
-	emulate_exception(ctxt, TS_VECTOR, err, true);
+	return emulate_exception(ctxt, TS_VECTOR, err, true);
 }
 
 static int emulate_de(struct x86_emulate_ctxt *ctxt)
 {
-	emulate_exception(ctxt, DE_VECTOR, 0, false);
-	return X86EMUL_PROPAGATE_FAULT;
+	return emulate_exception(ctxt, DE_VECTOR, 0, false);
 }
 
 static int do_fetch_insn_byte(struct x86_emulate_ctxt *ctxt,
@@ -520,7 +507,7 @@ static int do_fetch_insn_byte(struct x86
 		cur_size = fc->end - fc->start;
 		size = min(15UL - cur_size, PAGE_SIZE - offset_in_page(eip));
 		rc = ops->fetch(ctxt->cs_base + eip, fc->data + cur_size,
-				size, ctxt->vcpu, NULL);
+				size, ctxt->vcpu, &ctxt->exception);
 		if (rc != X86EMUL_CONTINUE)
 			return rc;
 		fc->end += size;
@@ -564,7 +551,7 @@ static void *decode_register(u8 modrm_re
 
 static int read_descriptor(struct x86_emulate_ctxt *ctxt,
 			   struct x86_emulate_ops *ops,
-			   ulong addr,
+			   struct segmented_address addr,
 			   u16 *size, unsigned long *address, int op_bytes)
 {
 	int rc;
@@ -572,10 +559,13 @@ static int read_descriptor(struct x86_em
 	if (op_bytes == 2)
 		op_bytes = 3;
 	*address = 0;
-	rc = ops->read_std(addr, (unsigned long *)size, 2, ctxt->vcpu, NULL);
+	rc = ops->read_std(linear(ctxt, addr), (unsigned long *)size, 2,
+			   ctxt->vcpu, &ctxt->exception);
 	if (rc != X86EMUL_CONTINUE)
 		return rc;
-	rc = ops->read_std(addr + 2, address, op_bytes, ctxt->vcpu, NULL);
+	addr.ea += 2;
+	rc = ops->read_std(linear(ctxt, addr), address, op_bytes,
+			   ctxt->vcpu, &ctxt->exception);
 	return rc;
 }
 
@@ -768,7 +758,7 @@ static int decode_modrm(struct x86_emula
 			break;
 		}
 	}
-	op->addr.mem = modrm_ea;
+	op->addr.mem.ea = modrm_ea;
 done:
 	return rc;
 }
@@ -783,13 +773,13 @@ static int decode_abs(struct x86_emulate
 	op->type = OP_MEM;
 	switch (c->ad_bytes) {
 	case 2:
-		op->addr.mem = insn_fetch(u16, 2, c->eip);
+		op->addr.mem.ea = insn_fetch(u16, 2, c->eip);
 		break;
 	case 4:
-		op->addr.mem = insn_fetch(u32, 4, c->eip);
+		op->addr.mem.ea = insn_fetch(u32, 4, c->eip);
 		break;
 	case 8:
-		op->addr.mem = insn_fetch(u64, 8, c->eip);
+		op->addr.mem.ea = insn_fetch(u64, 8, c->eip);
 		break;
 	}
 done:
@@ -808,7 +798,7 @@ static void fetch_bit_operand(struct dec
 		else if (c->src.bytes == 4)
 			sv = (s32)c->src.val & (s32)mask;
 
-		c->dst.addr.mem += (sv >> 3);
+		c->dst.addr.mem.ea += (sv >> 3);
 	}
 
 	/* only subword offset */
@@ -821,7 +811,6 @@ static int read_emulated(struct x86_emul
 {
 	int rc;
 	struct read_cache *mc = &ctxt->decode.mem_read;
-	u32 err;
 
 	while (size) {
 		int n = min(size, 8u);
@@ -829,10 +818,8 @@ static int read_emulated(struct x86_emul
 		if (mc->pos < mc->end)
 			goto read_cached;
 
-		rc = ops->read_emulated(addr, mc->data + mc->end, n, &err,
-					ctxt->vcpu);
-		if (rc == X86EMUL_PROPAGATE_FAULT)
-			emulate_pf(ctxt);
+		rc = ops->read_emulated(addr, mc->data + mc->end, n,
+					&ctxt->exception, ctxt->vcpu);
 		if (rc != X86EMUL_CONTINUE)
 			return rc;
 		mc->end += n;
@@ -907,19 +894,15 @@ static int read_segment_descriptor(struc
 	struct desc_ptr dt;
 	u16 index = selector >> 3;
 	int ret;
-	u32 err;
 	ulong addr;
 
 	get_descriptor_table_ptr(ctxt, ops, selector, &dt);
 
-	if (dt.size < index * 8 + 7) {
-		emulate_gp(ctxt, selector & 0xfffc);
-		return X86EMUL_PROPAGATE_FAULT;
-	}
+	if (dt.size < index * 8 + 7)
+		return emulate_gp(ctxt, selector & 0xfffc);
 	addr = dt.address + index * 8;
-	ret = ops->read_std(addr, desc, sizeof *desc, ctxt->vcpu,  &err);
-	if (ret == X86EMUL_PROPAGATE_FAULT)
-		emulate_pf(ctxt);
+	ret = ops->read_std(addr, desc, sizeof *desc, ctxt->vcpu,
+			    &ctxt->exception);
 
        return ret;
 }
@@ -931,21 +914,17 @@ static int write_segment_descriptor(stru
 {
 	struct desc_ptr dt;
 	u16 index = selector >> 3;
-	u32 err;
 	ulong addr;
 	int ret;
 
 	get_descriptor_table_ptr(ctxt, ops, selector, &dt);
 
-	if (dt.size < index * 8 + 7) {
-		emulate_gp(ctxt, selector & 0xfffc);
-		return X86EMUL_PROPAGATE_FAULT;
-	}
+	if (dt.size < index * 8 + 7)
+		return emulate_gp(ctxt, selector & 0xfffc);
 
 	addr = dt.address + index * 8;
-	ret = ops->write_std(addr, desc, sizeof *desc, ctxt->vcpu, &err);
-	if (ret == X86EMUL_PROPAGATE_FAULT)
-		emulate_pf(ctxt);
+	ret = ops->write_std(addr, desc, sizeof *desc, ctxt->vcpu,
+			     &ctxt->exception);
 
 	return ret;
 }
@@ -1092,7 +1071,6 @@ static inline int writeback(struct x86_e
 {
 	int rc;
 	struct decode_cache *c = &ctxt->decode;
-	u32 err;
 
 	switch (c->dst.type) {
 	case OP_REG:
@@ -1101,21 +1079,19 @@ static inline int writeback(struct x86_e
 	case OP_MEM:
 		if (c->lock_prefix)
 			rc = ops->cmpxchg_emulated(
-					c->dst.addr.mem,
+					linear(ctxt, c->dst.addr.mem),
 					&c->dst.orig_val,
 					&c->dst.val,
 					c->dst.bytes,
-					&err,
+					&ctxt->exception,
 					ctxt->vcpu);
 		else
 			rc = ops->write_emulated(
-					c->dst.addr.mem,
+					linear(ctxt, c->dst.addr.mem),
 					&c->dst.val,
 					c->dst.bytes,
-					&err,
+					&ctxt->exception,
 					ctxt->vcpu);
-		if (rc == X86EMUL_PROPAGATE_FAULT)
-			emulate_pf(ctxt);
 		if (rc != X86EMUL_CONTINUE)
 			return rc;
 		break;
@@ -1137,8 +1113,8 @@ static inline void emulate_push(struct x
 	c->dst.bytes = c->op_bytes;
 	c->dst.val = c->src.val;
 	register_address_increment(c, &c->regs[VCPU_REGS_RSP], -c->op_bytes);
-	c->dst.addr.mem = register_address(c, ss_base(ctxt, ops),
-					   c->regs[VCPU_REGS_RSP]);
+	c->dst.addr.mem.ea = register_address(c, c->regs[VCPU_REGS_RSP]);
+	c->dst.addr.mem.seg = VCPU_SREG_SS;
 }
 
 static int emulate_pop(struct x86_emulate_ctxt *ctxt,
@@ -1147,10 +1123,11 @@ static int emulate_pop(struct x86_emulat
 {
 	struct decode_cache *c = &ctxt->decode;
 	int rc;
+	struct segmented_address addr;
 
-	rc = read_emulated(ctxt, ops, register_address(c, ss_base(ctxt, ops),
-						       c->regs[VCPU_REGS_RSP]),
-			   dest, len);
+	addr.ea = register_address(c, c->regs[VCPU_REGS_RSP]);
+	addr.seg = VCPU_SREG_SS;
+	rc = read_emulated(ctxt, ops, linear(ctxt, addr), dest, len);
 	if (rc != X86EMUL_CONTINUE)
 		return rc;
 
@@ -1184,10 +1161,8 @@ static int emulate_popf(struct x86_emula
 			change_mask |= EFLG_IF;
 		break;
 	case X86EMUL_MODE_VM86:
-		if (iopl < 3) {
-			emulate_gp(ctxt, 0);
-			return X86EMUL_PROPAGATE_FAULT;
-		}
+		if (iopl < 3)
+			return emulate_gp(ctxt, 0);
 		change_mask |= EFLG_IF;
 		break;
 	default: /* real mode */
@@ -1198,9 +1173,6 @@ static int emulate_popf(struct x86_emula
 	*(unsigned long *)dest =
 		(ctxt->eflags & ~change_mask) | (val & change_mask);
 
-	if (rc == X86EMUL_PROPAGATE_FAULT)
-		emulate_pf(ctxt);
-
 	return rc;
 }
 
@@ -1287,7 +1259,6 @@ int emulate_int_real(struct x86_emulate_
 	gva_t cs_addr;
 	gva_t eip_addr;
 	u16 cs, eip;
-	u32 err;
 
 	/* TODO: Add limit checks */
 	c->src.val = ctxt->eflags;
@@ -1317,11 +1288,11 @@ int emulate_int_real(struct x86_emulate_
 	eip_addr = dt.address + (irq << 2);
 	cs_addr = dt.address + (irq << 2) + 2;
 
-	rc = ops->read_std(cs_addr, &cs, 2, ctxt->vcpu, &err);
+	rc = ops->read_std(cs_addr, &cs, 2, ctxt->vcpu, &ctxt->exception);
 	if (rc != X86EMUL_CONTINUE)
 		return rc;
 
-	rc = ops->read_std(eip_addr, &eip, 2, ctxt->vcpu, &err);
+	rc = ops->read_std(eip_addr, &eip, 2, ctxt->vcpu, &ctxt->exception);
 	if (rc != X86EMUL_CONTINUE)
 		return rc;
 
@@ -1370,10 +1341,8 @@ static int emulate_iret_real(struct x86_
 	if (rc != X86EMUL_CONTINUE)
 		return rc;
 
-	if (temp_eip & ~0xffff) {
-		emulate_gp(ctxt, 0);
-		return X86EMUL_PROPAGATE_FAULT;
-	}
+	if (temp_eip & ~0xffff)
+		return emulate_gp(ctxt, 0);
 
 	rc = emulate_pop(ctxt, ops, &cs, c->op_bytes);
 
@@ -1624,10 +1593,8 @@ emulate_syscall(struct x86_emulate_ctxt
 
 	/* syscall is not available in real mode */
 	if (ctxt->mode == X86EMUL_MODE_REAL ||
-	    ctxt->mode == X86EMUL_MODE_VM86) {
-		emulate_ud(ctxt);
-		return X86EMUL_PROPAGATE_FAULT;
-	}
+	    ctxt->mode == X86EMUL_MODE_VM86)
+		return emulate_ud(ctxt);
 
 	setup_syscalls_segments(ctxt, ops, &cs, &ss);
 
@@ -1678,34 +1645,26 @@ emulate_sysenter(struct x86_emulate_ctxt
 	u16 cs_sel, ss_sel;
 
 	/* inject #GP if in real mode */
-	if (ctxt->mode == X86EMUL_MODE_REAL) {
-		emulate_gp(ctxt, 0);
-		return X86EMUL_PROPAGATE_FAULT;
-	}
+	if (ctxt->mode == X86EMUL_MODE_REAL)
+		return emulate_gp(ctxt, 0);
 
 	/* XXX sysenter/sysexit have not been tested in 64bit mode.
 	* Therefore, we inject an #UD.
 	*/
-	if (ctxt->mode == X86EMUL_MODE_PROT64) {
-		emulate_ud(ctxt);
-		return X86EMUL_PROPAGATE_FAULT;
-	}
+	if (ctxt->mode == X86EMUL_MODE_PROT64)
+		return emulate_ud(ctxt);
 
 	setup_syscalls_segments(ctxt, ops, &cs, &ss);
 
 	ops->get_msr(ctxt->vcpu, MSR_IA32_SYSENTER_CS, &msr_data);
 	switch (ctxt->mode) {
 	case X86EMUL_MODE_PROT32:
-		if ((msr_data & 0xfffc) == 0x0) {
-			emulate_gp(ctxt, 0);
-			return X86EMUL_PROPAGATE_FAULT;
-		}
+		if ((msr_data & 0xfffc) == 0x0)
+			return emulate_gp(ctxt, 0);
 		break;
 	case X86EMUL_MODE_PROT64:
-		if (msr_data == 0x0) {
-			emulate_gp(ctxt, 0);
-			return X86EMUL_PROPAGATE_FAULT;
-		}
+		if (msr_data == 0x0)
+			return emulate_gp(ctxt, 0);
 		break;
 	}
 
@@ -1745,10 +1704,8 @@ emulate_sysexit(struct x86_emulate_ctxt
 
 	/* inject #GP if in real mode or Virtual 8086 mode */
 	if (ctxt->mode == X86EMUL_MODE_REAL ||
-	    ctxt->mode == X86EMUL_MODE_VM86) {
-		emulate_gp(ctxt, 0);
-		return X86EMUL_PROPAGATE_FAULT;
-	}
+	    ctxt->mode == X86EMUL_MODE_VM86)
+		return emulate_gp(ctxt, 0);
 
 	setup_syscalls_segments(ctxt, ops, &cs, &ss);
 
@@ -1763,18 +1720,14 @@ emulate_sysexit(struct x86_emulate_ctxt
 	switch (usermode) {
 	case X86EMUL_MODE_PROT32:
 		cs_sel = (u16)(msr_data + 16);
-		if ((msr_data & 0xfffc) == 0x0) {
-			emulate_gp(ctxt, 0);
-			return X86EMUL_PROPAGATE_FAULT;
-		}
+		if ((msr_data & 0xfffc) == 0x0)
+			return emulate_gp(ctxt, 0);
 		ss_sel = (u16)(msr_data + 24);
 		break;
 	case X86EMUL_MODE_PROT64:
 		cs_sel = (u16)(msr_data + 32);
-		if (msr_data == 0x0) {
-			emulate_gp(ctxt, 0);
-			return X86EMUL_PROPAGATE_FAULT;
-		}
+		if (msr_data == 0x0)
+			return emulate_gp(ctxt, 0);
 		ss_sel = cs_sel + 8;
 		cs.d = 0;
 		cs.l = 1;
@@ -1934,33 +1887,27 @@ static int task_switch_16(struct x86_emu
 {
 	struct tss_segment_16 tss_seg;
 	int ret;
-	u32 err, new_tss_base = get_desc_base(new_desc);
+	u32 new_tss_base = get_desc_base(new_desc);
 
 	ret = ops->read_std(old_tss_base, &tss_seg, sizeof tss_seg, ctxt->vcpu,
-			    &err);
-	if (ret == X86EMUL_PROPAGATE_FAULT) {
+			    &ctxt->exception);
+	if (ret != X86EMUL_CONTINUE)
 		/* FIXME: need to provide precise fault address */
-		emulate_pf(ctxt);
 		return ret;
-	}
 
 	save_state_to_tss16(ctxt, ops, &tss_seg);
 
 	ret = ops->write_std(old_tss_base, &tss_seg, sizeof tss_seg, ctxt->vcpu,
-			     &err);
-	if (ret == X86EMUL_PROPAGATE_FAULT) {
+			     &ctxt->exception);
+	if (ret != X86EMUL_CONTINUE)
 		/* FIXME: need to provide precise fault address */
-		emulate_pf(ctxt);
 		return ret;
-	}
 
 	ret = ops->read_std(new_tss_base, &tss_seg, sizeof tss_seg, ctxt->vcpu,
-			    &err);
-	if (ret == X86EMUL_PROPAGATE_FAULT) {
+			    &ctxt->exception);
+	if (ret != X86EMUL_CONTINUE)
 		/* FIXME: need to provide precise fault address */
-		emulate_pf(ctxt);
 		return ret;
-	}
 
 	if (old_tss_sel != 0xffff) {
 		tss_seg.prev_task_link = old_tss_sel;
@@ -1968,12 +1915,10 @@ static int task_switch_16(struct x86_emu
 		ret = ops->write_std(new_tss_base,
 				     &tss_seg.prev_task_link,
 				     sizeof tss_seg.prev_task_link,
-				     ctxt->vcpu, &err);
-		if (ret == X86EMUL_PROPAGATE_FAULT) {
+				     ctxt->vcpu, &ctxt->exception);
+		if (ret != X86EMUL_CONTINUE)
 			/* FIXME: need to provide precise fault address */
-			emulate_pf(ctxt);
 			return ret;
-		}
 	}
 
 	return load_state_from_tss16(ctxt, ops, &tss_seg);
@@ -2013,10 +1958,8 @@ static int load_state_from_tss32(struct
 	struct decode_cache *c = &ctxt->decode;
 	int ret;
 
-	if (ops->set_cr(3, tss->cr3, ctxt->vcpu)) {
-		emulate_gp(ctxt, 0);
-		return X86EMUL_PROPAGATE_FAULT;
-	}
+	if (ops->set_cr(3, tss->cr3, ctxt->vcpu))
+		return emulate_gp(ctxt, 0);
 	c->eip = tss->eip;
 	ctxt->eflags = tss->eflags | 2;
 	c->regs[VCPU_REGS_RAX] = tss->eax;
@@ -2076,33 +2019,27 @@ static int task_switch_32(struct x86_emu
 {
 	struct tss_segment_32 tss_seg;
 	int ret;
-	u32 err, new_tss_base = get_desc_base(new_desc);
+	u32 new_tss_base = get_desc_base(new_desc);
 
 	ret = ops->read_std(old_tss_base, &tss_seg, sizeof tss_seg, ctxt->vcpu,
-			    &err);
-	if (ret == X86EMUL_PROPAGATE_FAULT) {
+			    &ctxt->exception);
+	if (ret != X86EMUL_CONTINUE)
 		/* FIXME: need to provide precise fault address */
-		emulate_pf(ctxt);
 		return ret;
-	}
 
 	save_state_to_tss32(ctxt, ops, &tss_seg);
 
 	ret = ops->write_std(old_tss_base, &tss_seg, sizeof tss_seg, ctxt->vcpu,
-			     &err);
-	if (ret == X86EMUL_PROPAGATE_FAULT) {
+			     &ctxt->exception);
+	if (ret != X86EMUL_CONTINUE)
 		/* FIXME: need to provide precise fault address */
-		emulate_pf(ctxt);
 		return ret;
-	}
 
 	ret = ops->read_std(new_tss_base, &tss_seg, sizeof tss_seg, ctxt->vcpu,
-			    &err);
-	if (ret == X86EMUL_PROPAGATE_FAULT) {
+			    &ctxt->exception);
+	if (ret != X86EMUL_CONTINUE)
 		/* FIXME: need to provide precise fault address */
-		emulate_pf(ctxt);
 		return ret;
-	}
 
 	if (old_tss_sel != 0xffff) {
 		tss_seg.prev_task_link = old_tss_sel;
@@ -2110,12 +2047,10 @@ static int task_switch_32(struct x86_emu
 		ret = ops->write_std(new_tss_base,
 				     &tss_seg.prev_task_link,
 				     sizeof tss_seg.prev_task_link,
-				     ctxt->vcpu, &err);
-		if (ret == X86EMUL_PROPAGATE_FAULT) {
+				     ctxt->vcpu, &ctxt->exception);
+		if (ret != X86EMUL_CONTINUE)
 			/* FIXME: need to provide precise fault address */
-			emulate_pf(ctxt);
 			return ret;
-		}
 	}
 
 	return load_state_from_tss32(ctxt, ops, &tss_seg);
@@ -2146,10 +2081,8 @@ static int emulator_do_task_switch(struc
 
 	if (reason != TASK_SWITCH_IRET) {
 		if ((tss_selector & 3) > next_tss_desc.dpl ||
-		    ops->cpl(ctxt->vcpu) > next_tss_desc.dpl) {
-			emulate_gp(ctxt, 0);
-			return X86EMUL_PROPAGATE_FAULT;
-		}
+		    ops->cpl(ctxt->vcpu) > next_tss_desc.dpl)
+			return emulate_gp(ctxt, 0);
 	}
 
 	desc_limit = desc_limit_scaled(&next_tss_desc);
@@ -2231,14 +2164,15 @@ int emulator_task_switch(struct x86_emul
 	return (rc == X86EMUL_UNHANDLEABLE) ? -1 : 0;
 }
 
-static void string_addr_inc(struct x86_emulate_ctxt *ctxt, unsigned long base,
+static void string_addr_inc(struct x86_emulate_ctxt *ctxt, unsigned seg,
 			    int reg, struct operand *op)
 {
 	struct decode_cache *c = &ctxt->decode;
 	int df = (ctxt->eflags & EFLG_DF) ? -1 : 1;
 
 	register_address_increment(c, &c->regs[reg], df * op->bytes);
-	op->addr.mem = register_address(c,  base, c->regs[reg]);
+	op->addr.mem.ea = register_address(c, c->regs[reg]);
+	op->addr.mem.seg = seg;
 }
 
 static int em_push(struct x86_emulate_ctxt *ctxt)
@@ -2369,10 +2303,8 @@ static int em_rdtsc(struct x86_emulate_c
 	struct decode_cache *c = &ctxt->decode;
 	u64 tsc = 0;
 
-	if (cpl > 0 && (ctxt->ops->get_cr(4, ctxt->vcpu) & X86_CR4_TSD)) {
-		emulate_gp(ctxt, 0);
-		return X86EMUL_PROPAGATE_FAULT;
-	}
+	if (cpl > 0 && (ctxt->ops->get_cr(4, ctxt->vcpu) & X86_CR4_TSD))
+		return emulate_gp(ctxt, 0);
 	ctxt->ops->get_msr(ctxt->vcpu, MSR_IA32_TSC, &tsc);
 	c->regs[VCPU_REGS_RAX] = (u32)tsc;
 	c->regs[VCPU_REGS_RDX] = tsc >> 32;
@@ -2647,7 +2579,7 @@ static int decode_imm(struct x86_emulate
 
 	op->type = OP_IMM;
 	op->bytes = size;
-	op->addr.mem = c->eip;
+	op->addr.mem.ea = c->eip;
 	/* NB. Immediates are sign-extended as necessary. */
 	switch (op->bytes) {
 	case 1:
@@ -2678,7 +2610,7 @@ done:
 }
 
 int
-x86_decode_insn(struct x86_emulate_ctxt *ctxt)
+x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len)
 {
 	struct x86_emulate_ops *ops = ctxt->ops;
 	struct decode_cache *c = &ctxt->decode;
@@ -2689,7 +2621,10 @@ x86_decode_insn(struct x86_emulate_ctxt
 	struct operand memop = { .type = OP_NONE };
 
 	c->eip = ctxt->eip;
-	c->fetch.start = c->fetch.end = c->eip;
+	c->fetch.start = c->eip;
+	c->fetch.end = c->fetch.start + insn_len;
+	if (insn_len > 0)
+		memcpy(c->fetch.data, insn, insn_len);
 	ctxt->cs_base = seg_base(ctxt, ops, VCPU_SREG_CS);
 
 	switch (mode) {
@@ -2803,10 +2738,8 @@ done_prefixes:
 	c->execute = opcode.u.execute;
 
 	/* Unrecognised? */
-	if (c->d == 0 || (c->d & Undefined)) {
-		DPRINTF("Cannot emulate %02x\n", c->b);
+	if (c->d == 0 || (c->d & Undefined))
 		return -1;
-	}
 
 	if (mode == X86EMUL_MODE_PROT64 && (c->d & Stack))
 		c->op_bytes = 8;
@@ -2831,14 +2764,13 @@ done_prefixes:
 	if (!c->has_seg_override)
 		set_seg_override(c, VCPU_SREG_DS);
 
-	if (memop.type == OP_MEM && !(!c->twobyte && c->b == 0x8d))
-		memop.addr.mem += seg_override_base(ctxt, ops, c);
+	memop.addr.mem.seg = seg_override(ctxt, ops, c);
 
 	if (memop.type == OP_MEM && c->ad_bytes != 8)
-		memop.addr.mem = (u32)memop.addr.mem;
+		memop.addr.mem.ea = (u32)memop.addr.mem.ea;
 
 	if (memop.type == OP_MEM && c->rip_relative)
-		memop.addr.mem += c->eip;
+		memop.addr.mem.ea += c->eip;
 
 	/*
 	 * Decode and fetch the source operand: register, memory
@@ -2890,14 +2822,14 @@ done_prefixes:
 	case SrcSI:
 		c->src.type = OP_MEM;
 		c->src.bytes = (c->d & ByteOp) ? 1 : c->op_bytes;
-		c->src.addr.mem =
-			register_address(c,  seg_override_base(ctxt, ops, c),
-					 c->regs[VCPU_REGS_RSI]);
+		c->src.addr.mem.ea =
+			register_address(c, c->regs[VCPU_REGS_RSI]);
+		c->src.addr.mem.seg = seg_override(ctxt, ops, c),
 		c->src.val = 0;
 		break;
 	case SrcImmFAddr:
 		c->src.type = OP_IMM;
-		c->src.addr.mem = c->eip;
+		c->src.addr.mem.ea = c->eip;
 		c->src.bytes = c->op_bytes + 2;
 		insn_fetch_arr(c->src.valptr, c->src.bytes, c->eip);
 		break;
@@ -2944,7 +2876,7 @@ done_prefixes:
 		break;
 	case DstImmUByte:
 		c->dst.type = OP_IMM;
-		c->dst.addr.mem = c->eip;
+		c->dst.addr.mem.ea = c->eip;
 		c->dst.bytes = 1;
 		c->dst.val = insn_fetch(u8, 1, c->eip);
 		break;
@@ -2969,9 +2901,9 @@ done_prefixes:
 	case DstDI:
 		c->dst.type = OP_MEM;
 		c->dst.bytes = (c->d & ByteOp) ? 1 : c->op_bytes;
-		c->dst.addr.mem =
-			register_address(c, es_base(ctxt, ops),
-					 c->regs[VCPU_REGS_RDI]);
+		c->dst.addr.mem.ea =
+			register_address(c, c->regs[VCPU_REGS_RDI]);
+		c->dst.addr.mem.seg = VCPU_SREG_ES;
 		c->dst.val = 0;
 		break;
 	case ImplicitOps:
@@ -3020,24 +2952,24 @@ x86_emulate_insn(struct x86_emulate_ctxt
 	ctxt->decode.mem_read.pos = 0;
 
 	if (ctxt->mode == X86EMUL_MODE_PROT64 && (c->d & No64)) {
-		emulate_ud(ctxt);
+		rc = emulate_ud(ctxt);
 		goto done;
 	}
 
 	/* LOCK prefix is allowed only with some instructions */
 	if (c->lock_prefix && (!(c->d & Lock) || c->dst.type != OP_MEM)) {
-		emulate_ud(ctxt);
+		rc = emulate_ud(ctxt);
 		goto done;
 	}
 
 	if ((c->d & SrcMask) == SrcMemFAddr && c->src.type != OP_MEM) {
-		emulate_ud(ctxt);
+		rc = emulate_ud(ctxt);
 		goto done;
 	}
 
 	/* Privileged instruction can be executed only in CPL=0 */
 	if ((c->d & Priv) && ops->cpl(ctxt->vcpu)) {
-		emulate_gp(ctxt, 0);
+		rc = emulate_gp(ctxt, 0);
 		goto done;
 	}
 
@@ -3050,7 +2982,7 @@ x86_emulate_insn(struct x86_emulate_ctxt
 	}
 
 	if ((c->src.type == OP_MEM) && !(c->d & NoAccess)) {
-		rc = read_emulated(ctxt, ops, c->src.addr.mem,
+		rc = read_emulated(ctxt, ops, linear(ctxt, c->src.addr.mem),
 					c->src.valptr, c->src.bytes);
 		if (rc != X86EMUL_CONTINUE)
 			goto done;
@@ -3058,7 +2990,7 @@ x86_emulate_insn(struct x86_emulate_ctxt
 	}
 
 	if (c->src2.type == OP_MEM) {
-		rc = read_emulated(ctxt, ops, c->src2.addr.mem,
+		rc = read_emulated(ctxt, ops, linear(ctxt, c->src2.addr.mem),
 					&c->src2.val, c->src2.bytes);
 		if (rc != X86EMUL_CONTINUE)
 			goto done;
@@ -3070,7 +3002,7 @@ x86_emulate_insn(struct x86_emulate_ctxt
 
 	if ((c->dst.type == OP_MEM) && !(c->d & Mov)) {
 		/* optimisation - avoid slow emulated read if Mov */
-		rc = read_emulated(ctxt, ops, c->dst.addr.mem,
+		rc = read_emulated(ctxt, ops, linear(ctxt, c->dst.addr.mem),
 				   &c->dst.val, c->dst.bytes);
 		if (rc != X86EMUL_CONTINUE)
 			goto done;
@@ -3215,13 +3147,13 @@ special_insn:
 		break;
 	case 0x8c:  /* mov r/m, sreg */
 		if (c->modrm_reg > VCPU_SREG_GS) {
-			emulate_ud(ctxt);
+			rc = emulate_ud(ctxt);
 			goto done;
 		}
 		c->dst.val = ops->get_segment_selector(c->modrm_reg, ctxt->vcpu);
 		break;
 	case 0x8d: /* lea r16/r32, m */
-		c->dst.val = c->src.addr.mem;
+		c->dst.val = c->src.addr.mem.ea;
 		break;
 	case 0x8e: { /* mov seg, r/m16 */
 		uint16_t sel;
@@ -3230,7 +3162,7 @@ special_insn:
 
 		if (c->modrm_reg == VCPU_SREG_CS ||
 		    c->modrm_reg > VCPU_SREG_GS) {
-			emulate_ud(ctxt);
+			rc = emulate_ud(ctxt);
 			goto done;
 		}
 
@@ -3268,7 +3200,6 @@ special_insn:
 		break;
 	case 0xa6 ... 0xa7:	/* cmps */
 		c->dst.type = OP_NONE; /* Disable writeback. */
-		DPRINTF("cmps: mem1=0x%p mem2=0x%p\n", c->src.addr.mem, c->dst.addr.mem);
 		goto cmp;
 	case 0xa8 ... 0xa9:	/* test ax, imm */
 		goto test;
@@ -3363,7 +3294,7 @@ special_insn:
 	do_io_in:
 		c->dst.bytes = min(c->dst.bytes, 4u);
 		if (!emulator_io_permited(ctxt, ops, c->src.val, c->dst.bytes)) {
-			emulate_gp(ctxt, 0);
+			rc = emulate_gp(ctxt, 0);
 			goto done;
 		}
 		if (!pio_in_emulated(ctxt, ops, c->dst.bytes, c->src.val,
@@ -3377,7 +3308,7 @@ special_insn:
 		c->src.bytes = min(c->src.bytes, 4u);
 		if (!emulator_io_permited(ctxt, ops, c->dst.val,
 					  c->src.bytes)) {
-			emulate_gp(ctxt, 0);
+			rc = emulate_gp(ctxt, 0);
 			goto done;
 		}
 		ops->pio_out_emulated(c->src.bytes, c->dst.val,
@@ -3402,14 +3333,14 @@ special_insn:
 		break;
 	case 0xfa: /* cli */
 		if (emulator_bad_iopl(ctxt, ops)) {
-			emulate_gp(ctxt, 0);
+			rc = emulate_gp(ctxt, 0);
 			goto done;
 		} else
 			ctxt->eflags &= ~X86_EFLAGS_IF;
 		break;
 	case 0xfb: /* sti */
 		if (emulator_bad_iopl(ctxt, ops)) {
-			emulate_gp(ctxt, 0);
+			rc = emulate_gp(ctxt, 0);
 			goto done;
 		} else {
 			ctxt->interruptibility = KVM_X86_SHADOW_INT_STI;
@@ -3449,11 +3380,11 @@ writeback:
 	c->dst.type = saved_dst_type;
 
 	if ((c->d & SrcMask) == SrcSI)
-		string_addr_inc(ctxt, seg_override_base(ctxt, ops, c),
+		string_addr_inc(ctxt, seg_override(ctxt, ops, c),
 				VCPU_REGS_RSI, &c->src);
 
 	if ((c->d & DstMask) == DstDI)
-		string_addr_inc(ctxt, es_base(ctxt, ops), VCPU_REGS_RDI,
+		string_addr_inc(ctxt, VCPU_SREG_ES, VCPU_REGS_RDI,
 				&c->dst);
 
 	if (c->rep_prefix && (c->d & String)) {
@@ -3482,6 +3413,8 @@ writeback:
 	ctxt->eip = c->eip;
 
 done:
+	if (rc == X86EMUL_PROPAGATE_FAULT)
+		ctxt->have_exception = true;
 	return (rc == X86EMUL_UNHANDLEABLE) ? EMULATION_FAILED : EMULATION_OK;
 
 twobyte_insn:
@@ -3544,9 +3477,11 @@ twobyte_insn:
 			break;
 		case 5: /* not defined */
 			emulate_ud(ctxt);
+			rc = X86EMUL_PROPAGATE_FAULT;
 			goto done;
 		case 7: /* invlpg*/
-			emulate_invlpg(ctxt->vcpu, c->src.addr.mem);
+			emulate_invlpg(ctxt->vcpu,
+				       linear(ctxt, c->src.addr.mem));
 			/* Disable writeback. */
 			c->dst.type = OP_NONE;
 			break;
@@ -3573,6 +3508,7 @@ twobyte_insn:
 		case 5 ... 7:
 		case 9 ... 15:
 			emulate_ud(ctxt);
+			rc = X86EMUL_PROPAGATE_FAULT;
 			goto done;
 		}
 		c->dst.val = ops->get_cr(c->modrm_reg, ctxt->vcpu);
@@ -3581,6 +3517,7 @@ twobyte_insn:
 		if ((ops->get_cr(4, ctxt->vcpu) & X86_CR4_DE) &&
 		    (c->modrm_reg == 4 || c->modrm_reg == 5)) {
 			emulate_ud(ctxt);
+			rc = X86EMUL_PROPAGATE_FAULT;
 			goto done;
 		}
 		ops->get_dr(c->modrm_reg, &c->dst.val, ctxt->vcpu);
@@ -3588,6 +3525,7 @@ twobyte_insn:
 	case 0x22: /* mov reg, cr */
 		if (ops->set_cr(c->modrm_reg, c->src.val, ctxt->vcpu)) {
 			emulate_gp(ctxt, 0);
+			rc = X86EMUL_PROPAGATE_FAULT;
 			goto done;
 		}
 		c->dst.type = OP_NONE;
@@ -3596,6 +3534,7 @@ twobyte_insn:
 		if ((ops->get_cr(4, ctxt->vcpu) & X86_CR4_DE) &&
 		    (c->modrm_reg == 4 || c->modrm_reg == 5)) {
 			emulate_ud(ctxt);
+			rc = X86EMUL_PROPAGATE_FAULT;
 			goto done;
 		}
 
@@ -3604,6 +3543,7 @@ twobyte_insn:
 				 ~0ULL : ~0U), ctxt->vcpu) < 0) {
 			/* #UD condition is already handled by the code above */
 			emulate_gp(ctxt, 0);
+			rc = X86EMUL_PROPAGATE_FAULT;
 			goto done;
 		}
 
@@ -3615,6 +3555,7 @@ twobyte_insn:
 			| ((u64)c->regs[VCPU_REGS_RDX] << 32);
 		if (ops->set_msr(ctxt->vcpu, c->regs[VCPU_REGS_RCX], msr_data)) {
 			emulate_gp(ctxt, 0);
+			rc = X86EMUL_PROPAGATE_FAULT;
 			goto done;
 		}
 		rc = X86EMUL_CONTINUE;
@@ -3623,6 +3564,7 @@ twobyte_insn:
 		/* rdmsr */
 		if (ops->get_msr(ctxt->vcpu, c->regs[VCPU_REGS_RCX], &msr_data)) {
 			emulate_gp(ctxt, 0);
+			rc = X86EMUL_PROPAGATE_FAULT;
 			goto done;
 		} else {
 			c->regs[VCPU_REGS_RAX] = (u32)msr_data;
@@ -3785,6 +3727,5 @@ twobyte_insn:
 	goto writeback;
 
 cannot_emulate:
-	DPRINTF("Cannot emulate %02x\n", c->b);
 	return -1;
 }
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/kvm/Kconfig linux-libre-2.6.38-gnu1/arch/x86/kvm/Kconfig
--- linux-libre-2.6.37-gnu1/arch/x86/kvm/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/kvm/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -28,6 +28,7 @@ config KVM
 	select HAVE_KVM_IRQCHIP
 	select HAVE_KVM_EVENTFD
 	select KVM_APIC_ARCHITECTURE
+	select KVM_ASYNC_PF
 	select USER_RETURN_NOTIFIER
 	select KVM_MMIO
 	---help---
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/kvm/kvm_cache_regs.h linux-libre-2.6.38-gnu1/arch/x86/kvm/kvm_cache_regs.h
--- linux-libre-2.6.37-gnu1/arch/x86/kvm/kvm_cache_regs.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/kvm/kvm_cache_regs.h	2011-03-14 21:20:32.000000000 -0400
@@ -73,6 +73,13 @@ static inline ulong kvm_read_cr4_bits(st
 	return vcpu->arch.cr4 & mask;
 }
 
+static inline ulong kvm_read_cr3(struct kvm_vcpu *vcpu)
+{
+	if (!test_bit(VCPU_EXREG_CR3, (ulong *)&vcpu->arch.regs_avail))
+		kvm_x86_ops->decache_cr3(vcpu);
+	return vcpu->arch.cr3;
+}
+
 static inline ulong kvm_read_cr4(struct kvm_vcpu *vcpu)
 {
 	return kvm_read_cr4_bits(vcpu, ~0UL);
@@ -84,4 +91,19 @@ static inline u64 kvm_read_edx_eax(struc
 		| ((u64)(kvm_register_read(vcpu, VCPU_REGS_RDX) & -1u) << 32);
 }
 
+static inline void enter_guest_mode(struct kvm_vcpu *vcpu)
+{
+	vcpu->arch.hflags |= HF_GUEST_MASK;
+}
+
+static inline void leave_guest_mode(struct kvm_vcpu *vcpu)
+{
+	vcpu->arch.hflags &= ~HF_GUEST_MASK;
+}
+
+static inline bool is_guest_mode(struct kvm_vcpu *vcpu)
+{
+	return vcpu->arch.hflags & HF_GUEST_MASK;
+}
+
 #endif
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/kvm/lapic.c linux-libre-2.6.38-gnu1/arch/x86/kvm/lapic.c
--- linux-libre-2.6.37-gnu1/arch/x86/kvm/lapic.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/kvm/lapic.c	2011-03-14 21:20:32.000000000 -0400
@@ -277,7 +277,8 @@ static void apic_update_ppr(struct kvm_l
 
 	if (old_ppr != ppr) {
 		apic_set_reg(apic, APIC_PROCPRI, ppr);
-		kvm_make_request(KVM_REQ_EVENT, apic->vcpu);
+		if (ppr < old_ppr)
+			kvm_make_request(KVM_REQ_EVENT, apic->vcpu);
 	}
 }
 
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/kvm/Makefile linux-libre-2.6.38-gnu1/arch/x86/kvm/Makefile
--- linux-libre-2.6.37-gnu1/arch/x86/kvm/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/kvm/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -1,5 +1,5 @@
 
-EXTRA_CFLAGS += -Ivirt/kvm -Iarch/x86/kvm
+ccflags-y += -Ivirt/kvm -Iarch/x86/kvm
 
 CFLAGS_x86.o := -I.
 CFLAGS_svm.o := -I.
@@ -9,6 +9,7 @@ kvm-y			+= $(addprefix ../../../virt/kvm
 				coalesced_mmio.o irq_comm.o eventfd.o \
 				assigned-dev.o)
 kvm-$(CONFIG_IOMMU_API)	+= $(addprefix ../../../virt/kvm/, iommu.o)
+kvm-$(CONFIG_KVM_ASYNC_PF)	+= $(addprefix ../../../virt/kvm/, async_pf.o)
 
 kvm-y			+= x86.o mmu.o emulate.o i8259.o irq.o lapic.o \
 			   i8254.o timer.o
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/kvm/mmu_audit.c linux-libre-2.6.38-gnu1/arch/x86/kvm/mmu_audit.c
--- linux-libre-2.6.37-gnu1/arch/x86/kvm/mmu_audit.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/kvm/mmu_audit.c	2011-03-14 21:20:32.000000000 -0400
@@ -19,11 +19,9 @@
 
 #include <linux/ratelimit.h>
 
-static int audit_point;
-
-#define audit_printk(fmt, args...)		\
+#define audit_printk(kvm, fmt, args...)		\
 	printk(KERN_ERR "audit: (%s) error: "	\
-		fmt, audit_point_name[audit_point], ##args)
+		fmt, audit_point_name[kvm->arch.audit_point], ##args)
 
 typedef void (*inspect_spte_fn) (struct kvm_vcpu *vcpu, u64 *sptep, int level);
 
@@ -97,18 +95,21 @@ static void audit_mappings(struct kvm_vc
 
 	if (sp->unsync) {
 		if (level != PT_PAGE_TABLE_LEVEL) {
-			audit_printk("unsync sp: %p level = %d\n", sp, level);
+			audit_printk(vcpu->kvm, "unsync sp: %p "
+				     "level = %d\n", sp, level);
 			return;
 		}
 
 		if (*sptep == shadow_notrap_nonpresent_pte) {
-			audit_printk("notrap spte in unsync sp: %p\n", sp);
+			audit_printk(vcpu->kvm, "notrap spte in unsync "
+				     "sp: %p\n", sp);
 			return;
 		}
 	}
 
 	if (sp->role.direct && *sptep == shadow_notrap_nonpresent_pte) {
-		audit_printk("notrap spte in direct sp: %p\n", sp);
+		audit_printk(vcpu->kvm, "notrap spte in direct sp: %p\n",
+			     sp);
 		return;
 	}
 
@@ -125,8 +126,9 @@ static void audit_mappings(struct kvm_vc
 
 	hpa =  pfn << PAGE_SHIFT;
 	if ((*sptep & PT64_BASE_ADDR_MASK) != hpa)
-		audit_printk("levels %d pfn %llx hpa %llx ent %llxn",
-				   vcpu->arch.mmu.root_level, pfn, hpa, *sptep);
+		audit_printk(vcpu->kvm, "levels %d pfn %llx hpa %llx "
+			     "ent %llxn", vcpu->arch.mmu.root_level, pfn,
+			     hpa, *sptep);
 }
 
 static void inspect_spte_has_rmap(struct kvm *kvm, u64 *sptep)
@@ -142,8 +144,8 @@ static void inspect_spte_has_rmap(struct
 	if (!gfn_to_memslot(kvm, gfn)) {
 		if (!printk_ratelimit())
 			return;
-		audit_printk("no memslot for gfn %llx\n", gfn);
-		audit_printk("index %ld of sp (gfn=%llx)\n",
+		audit_printk(kvm, "no memslot for gfn %llx\n", gfn);
+		audit_printk(kvm, "index %ld of sp (gfn=%llx)\n",
 		       (long int)(sptep - rev_sp->spt), rev_sp->gfn);
 		dump_stack();
 		return;
@@ -153,7 +155,8 @@ static void inspect_spte_has_rmap(struct
 	if (!*rmapp) {
 		if (!printk_ratelimit())
 			return;
-		audit_printk("no rmap for writable spte %llx\n", *sptep);
+		audit_printk(kvm, "no rmap for writable spte %llx\n",
+			     *sptep);
 		dump_stack();
 	}
 }
@@ -168,8 +171,9 @@ static void audit_spte_after_sync(struct
 {
 	struct kvm_mmu_page *sp = page_header(__pa(sptep));
 
-	if (audit_point == AUDIT_POST_SYNC && sp->unsync)
-		audit_printk("meet unsync sp(%p) after sync root.\n", sp);
+	if (vcpu->kvm->arch.audit_point == AUDIT_POST_SYNC && sp->unsync)
+		audit_printk(vcpu->kvm, "meet unsync sp(%p) after sync "
+			     "root.\n", sp);
 }
 
 static void check_mappings_rmap(struct kvm *kvm, struct kvm_mmu_page *sp)
@@ -202,8 +206,9 @@ static void audit_write_protection(struc
 	spte = rmap_next(kvm, rmapp, NULL);
 	while (spte) {
 		if (is_writable_pte(*spte))
-			audit_printk("shadow page has writable mappings: gfn "
-				     "%llx role %x\n", sp->gfn, sp->role.word);
+			audit_printk(kvm, "shadow page has writable "
+				     "mappings: gfn %llx role %x\n",
+				     sp->gfn, sp->role.word);
 		spte = rmap_next(kvm, rmapp, spte);
 	}
 }
@@ -238,7 +243,7 @@ static void kvm_mmu_audit(void *ignore,
 	if (!__ratelimit(&ratelimit_state))
 		return;
 
-	audit_point = point;
+	vcpu->kvm->arch.audit_point = point;
 	audit_all_active_sps(vcpu->kvm);
 	audit_vcpu_spte(vcpu);
 }
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/kvm/mmu.c linux-libre-2.6.38-gnu1/arch/x86/kvm/mmu.c
--- linux-libre-2.6.37-gnu1/arch/x86/kvm/mmu.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/kvm/mmu.c	2011-03-14 21:20:32.000000000 -0400
@@ -18,9 +18,11 @@
  *
  */
 
+#include "irq.h"
 #include "mmu.h"
 #include "x86.h"
 #include "kvm_cache_regs.h"
+#include "x86.h"
 
 #include <linux/kvm_host.h>
 #include <linux/types.h>
@@ -194,7 +196,6 @@ static struct percpu_counter kvm_total_u
 
 static u64 __read_mostly shadow_trap_nonpresent_pte;
 static u64 __read_mostly shadow_notrap_nonpresent_pte;
-static u64 __read_mostly shadow_base_present_pte;
 static u64 __read_mostly shadow_nx_mask;
 static u64 __read_mostly shadow_x_mask;	/* mutual exclusive with nx_mask */
 static u64 __read_mostly shadow_user_mask;
@@ -213,12 +214,6 @@ void kvm_mmu_set_nonpresent_ptes(u64 tra
 }
 EXPORT_SYMBOL_GPL(kvm_mmu_set_nonpresent_ptes);
 
-void kvm_mmu_set_base_ptes(u64 base_pte)
-{
-	shadow_base_present_pte = base_pte;
-}
-EXPORT_SYMBOL_GPL(kvm_mmu_set_base_ptes);
-
 void kvm_mmu_set_mask_ptes(u64 user_mask, u64 accessed_mask,
 		u64 dirty_mask, u64 nx_mask, u64 x_mask)
 {
@@ -482,46 +477,46 @@ static void kvm_mmu_page_set_gfn(struct
 }
 
 /*
- * Return the pointer to the largepage write count for a given
- * gfn, handling slots that are not large page aligned.
+ * Return the pointer to the large page information for a given gfn,
+ * handling slots that are not large page aligned.
  */
-static int *slot_largepage_idx(gfn_t gfn,
-			       struct kvm_memory_slot *slot,
-			       int level)
+static struct kvm_lpage_info *lpage_info_slot(gfn_t gfn,
+					      struct kvm_memory_slot *slot,
+					      int level)
 {
 	unsigned long idx;
 
 	idx = (gfn >> KVM_HPAGE_GFN_SHIFT(level)) -
 	      (slot->base_gfn >> KVM_HPAGE_GFN_SHIFT(level));
-	return &slot->lpage_info[level - 2][idx].write_count;
+	return &slot->lpage_info[level - 2][idx];
 }
 
 static void account_shadowed(struct kvm *kvm, gfn_t gfn)
 {
 	struct kvm_memory_slot *slot;
-	int *write_count;
+	struct kvm_lpage_info *linfo;
 	int i;
 
 	slot = gfn_to_memslot(kvm, gfn);
 	for (i = PT_DIRECTORY_LEVEL;
 	     i < PT_PAGE_TABLE_LEVEL + KVM_NR_PAGE_SIZES; ++i) {
-		write_count   = slot_largepage_idx(gfn, slot, i);
-		*write_count += 1;
+		linfo = lpage_info_slot(gfn, slot, i);
+		linfo->write_count += 1;
 	}
 }
 
 static void unaccount_shadowed(struct kvm *kvm, gfn_t gfn)
 {
 	struct kvm_memory_slot *slot;
-	int *write_count;
+	struct kvm_lpage_info *linfo;
 	int i;
 
 	slot = gfn_to_memslot(kvm, gfn);
 	for (i = PT_DIRECTORY_LEVEL;
 	     i < PT_PAGE_TABLE_LEVEL + KVM_NR_PAGE_SIZES; ++i) {
-		write_count   = slot_largepage_idx(gfn, slot, i);
-		*write_count -= 1;
-		WARN_ON(*write_count < 0);
+		linfo = lpage_info_slot(gfn, slot, i);
+		linfo->write_count -= 1;
+		WARN_ON(linfo->write_count < 0);
 	}
 }
 
@@ -530,12 +525,12 @@ static int has_wrprotected_page(struct k
 				int level)
 {
 	struct kvm_memory_slot *slot;
-	int *largepage_idx;
+	struct kvm_lpage_info *linfo;
 
 	slot = gfn_to_memslot(kvm, gfn);
 	if (slot) {
-		largepage_idx = slot_largepage_idx(gfn, slot, level);
-		return *largepage_idx;
+		linfo = lpage_info_slot(gfn, slot, level);
+		return linfo->write_count;
 	}
 
 	return 1;
@@ -559,14 +554,18 @@ static int host_mapping_level(struct kvm
 	return ret;
 }
 
-static int mapping_level(struct kvm_vcpu *vcpu, gfn_t large_gfn)
+static bool mapping_level_dirty_bitmap(struct kvm_vcpu *vcpu, gfn_t large_gfn)
 {
 	struct kvm_memory_slot *slot;
-	int host_level, level, max_level;
-
 	slot = gfn_to_memslot(vcpu->kvm, large_gfn);
 	if (slot && slot->dirty_bitmap)
-		return PT_PAGE_TABLE_LEVEL;
+		return true;
+	return false;
+}
+
+static int mapping_level(struct kvm_vcpu *vcpu, gfn_t large_gfn)
+{
+	int host_level, level, max_level;
 
 	host_level = host_mapping_level(vcpu->kvm, large_gfn);
 
@@ -590,16 +589,15 @@ static int mapping_level(struct kvm_vcpu
 static unsigned long *gfn_to_rmap(struct kvm *kvm, gfn_t gfn, int level)
 {
 	struct kvm_memory_slot *slot;
-	unsigned long idx;
+	struct kvm_lpage_info *linfo;
 
 	slot = gfn_to_memslot(kvm, gfn);
 	if (likely(level == PT_PAGE_TABLE_LEVEL))
 		return &slot->rmap[gfn - slot->base_gfn];
 
-	idx = (gfn >> KVM_HPAGE_GFN_SHIFT(level)) -
-		(slot->base_gfn >> KVM_HPAGE_GFN_SHIFT(level));
+	linfo = lpage_info_slot(gfn, slot, level);
 
-	return &slot->lpage_info[level - 2][idx].rmap_pde;
+	return &linfo->rmap_pde;
 }
 
 /*
@@ -887,19 +885,16 @@ static int kvm_handle_hva(struct kvm *kv
 		end = start + (memslot->npages << PAGE_SHIFT);
 		if (hva >= start && hva < end) {
 			gfn_t gfn_offset = (hva - start) >> PAGE_SHIFT;
+			gfn_t gfn = memslot->base_gfn + gfn_offset;
 
 			ret = handler(kvm, &memslot->rmap[gfn_offset], data);
 
 			for (j = 0; j < KVM_NR_PAGE_SIZES - 1; ++j) {
-				unsigned long idx;
-				int sh;
+				struct kvm_lpage_info *linfo;
 
-				sh = KVM_HPAGE_GFN_SHIFT(PT_DIRECTORY_LEVEL+j);
-				idx = ((memslot->base_gfn+gfn_offset) >> sh) -
-					(memslot->base_gfn >> sh);
-				ret |= handler(kvm,
-					&memslot->lpage_info[j][idx].rmap_pde,
-					data);
+				linfo = lpage_info_slot(gfn, memslot,
+							PT_DIRECTORY_LEVEL + j);
+				ret |= handler(kvm, &linfo->rmap_pde, data);
 			}
 			trace_kvm_age_page(hva, memslot, ret);
 			retval |= ret;
@@ -950,6 +945,35 @@ static int kvm_age_rmapp(struct kvm *kvm
 	return young;
 }
 
+static int kvm_test_age_rmapp(struct kvm *kvm, unsigned long *rmapp,
+			      unsigned long data)
+{
+	u64 *spte;
+	int young = 0;
+
+	/*
+	 * If there's no access bit in the secondary pte set by the
+	 * hardware it's up to gup-fast/gup to set the access bit in
+	 * the primary pte or in the page structure.
+	 */
+	if (!shadow_accessed_mask)
+		goto out;
+
+	spte = rmap_next(kvm, rmapp, NULL);
+	while (spte) {
+		u64 _spte = *spte;
+		BUG_ON(!(_spte & PT_PRESENT_MASK));
+		young = _spte & PT_ACCESSED_MASK;
+		if (young) {
+			young = 1;
+			break;
+		}
+		spte = rmap_next(kvm, rmapp, spte);
+	}
+out:
+	return young;
+}
+
 #define RMAP_RECYCLE_THRESHOLD 1000
 
 static void rmap_recycle(struct kvm_vcpu *vcpu, u64 *spte, gfn_t gfn)
@@ -970,6 +994,11 @@ int kvm_age_hva(struct kvm *kvm, unsigne
 	return kvm_handle_hva(kvm, hva, 0, kvm_age_rmapp);
 }
 
+int kvm_test_age_hva(struct kvm *kvm, unsigned long hva)
+{
+	return kvm_handle_hva(kvm, hva, 0, kvm_test_age_rmapp);
+}
+
 #ifdef MMU_DEBUG
 static int is_empty_shadow_page(u64 *spt)
 {
@@ -1161,7 +1190,7 @@ static void nonpaging_prefetch_page(stru
 }
 
 static int nonpaging_sync_page(struct kvm_vcpu *vcpu,
-			       struct kvm_mmu_page *sp, bool clear_unsync)
+			       struct kvm_mmu_page *sp)
 {
 	return 1;
 }
@@ -1291,7 +1320,7 @@ static int __kvm_sync_page(struct kvm_vc
 	if (clear_unsync)
 		kvm_unlink_unsync_page(vcpu->kvm, sp);
 
-	if (vcpu->arch.mmu.sync_page(vcpu, sp, clear_unsync)) {
+	if (vcpu->arch.mmu.sync_page(vcpu, sp)) {
 		kvm_mmu_prepare_zap_page(vcpu->kvm, sp, invalid_list);
 		return 1;
 	}
@@ -1332,12 +1361,12 @@ static void kvm_sync_pages(struct kvm_vc
 			continue;
 
 		WARN_ON(s->role.level != PT_PAGE_TABLE_LEVEL);
+		kvm_unlink_unsync_page(vcpu->kvm, s);
 		if ((s->role.cr4_pae != !!is_pae(vcpu)) ||
-			(vcpu->arch.mmu.sync_page(vcpu, s, true))) {
+			(vcpu->arch.mmu.sync_page(vcpu, s))) {
 			kvm_mmu_prepare_zap_page(vcpu->kvm, s, &invalid_list);
 			continue;
 		}
-		kvm_unlink_unsync_page(vcpu->kvm, s);
 		flush = true;
 	}
 
@@ -1963,9 +1992,9 @@ static int set_spte(struct kvm_vcpu *vcp
 		    unsigned pte_access, int user_fault,
 		    int write_fault, int dirty, int level,
 		    gfn_t gfn, pfn_t pfn, bool speculative,
-		    bool can_unsync, bool reset_host_protection)
+		    bool can_unsync, bool host_writable)
 {
-	u64 spte;
+	u64 spte, entry = *sptep;
 	int ret = 0;
 
 	/*
@@ -1973,7 +2002,7 @@ static int set_spte(struct kvm_vcpu *vcp
 	 * whether the guest actually used the pte (in order to detect
 	 * demand paging).
 	 */
-	spte = shadow_base_present_pte;
+	spte = PT_PRESENT_MASK;
 	if (!speculative)
 		spte |= shadow_accessed_mask;
 	if (!dirty)
@@ -1990,8 +2019,10 @@ static int set_spte(struct kvm_vcpu *vcp
 		spte |= kvm_x86_ops->get_mt_mask(vcpu, gfn,
 			kvm_is_mmio_pfn(pfn));
 
-	if (reset_host_protection)
+	if (host_writable)
 		spte |= SPTE_HOST_WRITEABLE;
+	else
+		pte_access &= ~ACC_WRITE_MASK;
 
 	spte |= (u64)pfn << PAGE_SHIFT;
 
@@ -2036,6 +2067,14 @@ static int set_spte(struct kvm_vcpu *vcp
 
 set_pte:
 	update_spte(sptep, spte);
+	/*
+	 * If we overwrite a writable spte with a read-only one we
+	 * should flush remote TLBs. Otherwise rmap_write_protect
+	 * will find a read-only spte, even though the writable spte
+	 * might be cached on a CPU's TLB.
+	 */
+	if (is_writable_pte(entry) && !is_writable_pte(*sptep))
+		kvm_flush_remote_tlbs(vcpu->kvm);
 done:
 	return ret;
 }
@@ -2045,7 +2084,7 @@ static void mmu_set_spte(struct kvm_vcpu
 			 int user_fault, int write_fault, int dirty,
 			 int *ptwrite, int level, gfn_t gfn,
 			 pfn_t pfn, bool speculative,
-			 bool reset_host_protection)
+			 bool host_writable)
 {
 	int was_rmapped = 0;
 	int rmap_count;
@@ -2080,7 +2119,7 @@ static void mmu_set_spte(struct kvm_vcpu
 
 	if (set_spte(vcpu, sptep, pte_access, user_fault, write_fault,
 		      dirty, level, gfn, pfn, speculative, true,
-		      reset_host_protection)) {
+		      host_writable)) {
 		if (write_fault)
 			*ptwrite = 1;
 		kvm_mmu_flush_tlb(vcpu);
@@ -2211,7 +2250,8 @@ static void direct_pte_prefetch(struct k
 }
 
 static int __direct_map(struct kvm_vcpu *vcpu, gpa_t v, int write,
-			int level, gfn_t gfn, pfn_t pfn)
+			int map_writable, int level, gfn_t gfn, pfn_t pfn,
+			bool prefault)
 {
 	struct kvm_shadow_walk_iterator iterator;
 	struct kvm_mmu_page *sp;
@@ -2220,9 +2260,11 @@ static int __direct_map(struct kvm_vcpu
 
 	for_each_shadow_entry(vcpu, (u64)gfn << PAGE_SHIFT, iterator) {
 		if (iterator.level == level) {
-			mmu_set_spte(vcpu, iterator.sptep, ACC_ALL, ACC_ALL,
+			unsigned pte_access = ACC_ALL;
+
+			mmu_set_spte(vcpu, iterator.sptep, ACC_ALL, pte_access,
 				     0, write, 1, &pt_write,
-				     level, gfn, pfn, false, true);
+				     level, gfn, pfn, prefault, map_writable);
 			direct_pte_prefetch(vcpu, iterator.sptep);
 			++vcpu->stat.pf_fixed;
 			break;
@@ -2277,27 +2319,81 @@ static int kvm_handle_bad_page(struct kv
 	return 1;
 }
 
-static int nonpaging_map(struct kvm_vcpu *vcpu, gva_t v, int write, gfn_t gfn)
+static void transparent_hugepage_adjust(struct kvm_vcpu *vcpu,
+					gfn_t *gfnp, pfn_t *pfnp, int *levelp)
+{
+	pfn_t pfn = *pfnp;
+	gfn_t gfn = *gfnp;
+	int level = *levelp;
+
+	/*
+	 * Check if it's a transparent hugepage. If this would be an
+	 * hugetlbfs page, level wouldn't be set to
+	 * PT_PAGE_TABLE_LEVEL and there would be no adjustment done
+	 * here.
+	 */
+	if (!is_error_pfn(pfn) && !kvm_is_mmio_pfn(pfn) &&
+	    level == PT_PAGE_TABLE_LEVEL &&
+	    PageTransCompound(pfn_to_page(pfn)) &&
+	    !has_wrprotected_page(vcpu->kvm, gfn, PT_DIRECTORY_LEVEL)) {
+		unsigned long mask;
+		/*
+		 * mmu_notifier_retry was successful and we hold the
+		 * mmu_lock here, so the pmd can't become splitting
+		 * from under us, and in turn
+		 * __split_huge_page_refcount() can't run from under
+		 * us and we can safely transfer the refcount from
+		 * PG_tail to PG_head as we switch the pfn to tail to
+		 * head.
+		 */
+		*levelp = level = PT_DIRECTORY_LEVEL;
+		mask = KVM_PAGES_PER_HPAGE(level) - 1;
+		VM_BUG_ON((gfn & mask) != (pfn & mask));
+		if (pfn & mask) {
+			gfn &= ~mask;
+			*gfnp = gfn;
+			kvm_release_pfn_clean(pfn);
+			pfn &= ~mask;
+			if (!get_page_unless_zero(pfn_to_page(pfn)))
+				BUG();
+			*pfnp = pfn;
+		}
+	}
+}
+
+static bool try_async_pf(struct kvm_vcpu *vcpu, bool prefault, gfn_t gfn,
+			 gva_t gva, pfn_t *pfn, bool write, bool *writable);
+
+static int nonpaging_map(struct kvm_vcpu *vcpu, gva_t v, int write, gfn_t gfn,
+			 bool prefault)
 {
 	int r;
 	int level;
+	int force_pt_level;
 	pfn_t pfn;
 	unsigned long mmu_seq;
+	bool map_writable;
 
-	level = mapping_level(vcpu, gfn);
-
-	/*
-	 * This path builds a PAE pagetable - so we can map 2mb pages at
-	 * maximum. Therefore check if the level is larger than that.
-	 */
-	if (level > PT_DIRECTORY_LEVEL)
-		level = PT_DIRECTORY_LEVEL;
+	force_pt_level = mapping_level_dirty_bitmap(vcpu, gfn);
+	if (likely(!force_pt_level)) {
+		level = mapping_level(vcpu, gfn);
+		/*
+		 * This path builds a PAE pagetable - so we can map
+		 * 2mb pages at maximum. Therefore check if the level
+		 * is larger than that.
+		 */
+		if (level > PT_DIRECTORY_LEVEL)
+			level = PT_DIRECTORY_LEVEL;
 
-	gfn &= ~(KVM_PAGES_PER_HPAGE(level) - 1);
+		gfn &= ~(KVM_PAGES_PER_HPAGE(level) - 1);
+	} else
+		level = PT_PAGE_TABLE_LEVEL;
 
 	mmu_seq = vcpu->kvm->mmu_notifier_seq;
 	smp_rmb();
-	pfn = gfn_to_pfn(vcpu->kvm, gfn);
+
+	if (try_async_pf(vcpu, prefault, gfn, v, &pfn, write, &map_writable))
+		return 0;
 
 	/* mmio */
 	if (is_error_pfn(pfn))
@@ -2307,7 +2403,10 @@ static int nonpaging_map(struct kvm_vcpu
 	if (mmu_notifier_retry(vcpu, mmu_seq))
 		goto out_unlock;
 	kvm_mmu_free_some_pages(vcpu);
-	r = __direct_map(vcpu, v, write, level, gfn, pfn);
+	if (likely(!force_pt_level))
+		transparent_hugepage_adjust(vcpu, &gfn, &pfn, &level);
+	r = __direct_map(vcpu, v, write, map_writable, level, gfn, pfn,
+			 prefault);
 	spin_unlock(&vcpu->kvm->mmu_lock);
 
 
@@ -2530,6 +2629,7 @@ static void mmu_sync_roots(struct kvm_vc
 		hpa_t root = vcpu->arch.mmu.root_hpa;
 		sp = page_header(root);
 		mmu_sync_children(vcpu, sp);
+		trace_kvm_mmu_audit(vcpu, AUDIT_POST_SYNC);
 		return;
 	}
 	for (i = 0; i < 4; ++i) {
@@ -2552,23 +2652,24 @@ void kvm_mmu_sync_roots(struct kvm_vcpu
 }
 
 static gpa_t nonpaging_gva_to_gpa(struct kvm_vcpu *vcpu, gva_t vaddr,
-				  u32 access, u32 *error)
+				  u32 access, struct x86_exception *exception)
 {
-	if (error)
-		*error = 0;
+	if (exception)
+		exception->error_code = 0;
 	return vaddr;
 }
 
 static gpa_t nonpaging_gva_to_gpa_nested(struct kvm_vcpu *vcpu, gva_t vaddr,
-					 u32 access, u32 *error)
+					 u32 access,
+					 struct x86_exception *exception)
 {
-	if (error)
-		*error = 0;
+	if (exception)
+		exception->error_code = 0;
 	return vcpu->arch.nested_mmu.translate_gpa(vcpu, vaddr, access);
 }
 
 static int nonpaging_page_fault(struct kvm_vcpu *vcpu, gva_t gva,
-				u32 error_code)
+				u32 error_code, bool prefault)
 {
 	gfn_t gfn;
 	int r;
@@ -2584,17 +2685,68 @@ static int nonpaging_page_fault(struct k
 	gfn = gva >> PAGE_SHIFT;
 
 	return nonpaging_map(vcpu, gva & PAGE_MASK,
-			     error_code & PFERR_WRITE_MASK, gfn);
+			     error_code & PFERR_WRITE_MASK, gfn, prefault);
 }
 
-static int tdp_page_fault(struct kvm_vcpu *vcpu, gva_t gpa,
-				u32 error_code)
+static int kvm_arch_setup_async_pf(struct kvm_vcpu *vcpu, gva_t gva, gfn_t gfn)
+{
+	struct kvm_arch_async_pf arch;
+
+	arch.token = (vcpu->arch.apf.id++ << 12) | vcpu->vcpu_id;
+	arch.gfn = gfn;
+	arch.direct_map = vcpu->arch.mmu.direct_map;
+	arch.cr3 = vcpu->arch.mmu.get_cr3(vcpu);
+
+	return kvm_setup_async_pf(vcpu, gva, gfn, &arch);
+}
+
+static bool can_do_async_pf(struct kvm_vcpu *vcpu)
+{
+	if (unlikely(!irqchip_in_kernel(vcpu->kvm) ||
+		     kvm_event_needs_reinjection(vcpu)))
+		return false;
+
+	return kvm_x86_ops->interrupt_allowed(vcpu);
+}
+
+static bool try_async_pf(struct kvm_vcpu *vcpu, bool prefault, gfn_t gfn,
+			 gva_t gva, pfn_t *pfn, bool write, bool *writable)
+{
+	bool async;
+
+	*pfn = gfn_to_pfn_async(vcpu->kvm, gfn, &async, write, writable);
+
+	if (!async)
+		return false; /* *pfn has correct page already */
+
+	put_page(pfn_to_page(*pfn));
+
+	if (!prefault && can_do_async_pf(vcpu)) {
+		trace_kvm_try_async_get_page(gva, gfn);
+		if (kvm_find_async_pf_gfn(vcpu, gfn)) {
+			trace_kvm_async_pf_doublefault(gva, gfn);
+			kvm_make_request(KVM_REQ_APF_HALT, vcpu);
+			return true;
+		} else if (kvm_arch_setup_async_pf(vcpu, gva, gfn))
+			return true;
+	}
+
+	*pfn = gfn_to_pfn_prot(vcpu->kvm, gfn, write, writable);
+
+	return false;
+}
+
+static int tdp_page_fault(struct kvm_vcpu *vcpu, gva_t gpa, u32 error_code,
+			  bool prefault)
 {
 	pfn_t pfn;
 	int r;
 	int level;
+	int force_pt_level;
 	gfn_t gfn = gpa >> PAGE_SHIFT;
 	unsigned long mmu_seq;
+	int write = error_code & PFERR_WRITE_MASK;
+	bool map_writable;
 
 	ASSERT(vcpu);
 	ASSERT(VALID_PAGE(vcpu->arch.mmu.root_hpa));
@@ -2603,21 +2755,30 @@ static int tdp_page_fault(struct kvm_vcp
 	if (r)
 		return r;
 
-	level = mapping_level(vcpu, gfn);
-
-	gfn &= ~(KVM_PAGES_PER_HPAGE(level) - 1);
+	force_pt_level = mapping_level_dirty_bitmap(vcpu, gfn);
+	if (likely(!force_pt_level)) {
+		level = mapping_level(vcpu, gfn);
+		gfn &= ~(KVM_PAGES_PER_HPAGE(level) - 1);
+	} else
+		level = PT_PAGE_TABLE_LEVEL;
 
 	mmu_seq = vcpu->kvm->mmu_notifier_seq;
 	smp_rmb();
-	pfn = gfn_to_pfn(vcpu->kvm, gfn);
+
+	if (try_async_pf(vcpu, prefault, gfn, gpa, &pfn, write, &map_writable))
+		return 0;
+
+	/* mmio */
 	if (is_error_pfn(pfn))
 		return kvm_handle_bad_page(vcpu->kvm, gfn, pfn);
 	spin_lock(&vcpu->kvm->mmu_lock);
 	if (mmu_notifier_retry(vcpu, mmu_seq))
 		goto out_unlock;
 	kvm_mmu_free_some_pages(vcpu);
-	r = __direct_map(vcpu, gpa, error_code & PFERR_WRITE_MASK,
-			 level, gfn, pfn);
+	if (likely(!force_pt_level))
+		transparent_hugepage_adjust(vcpu, &gfn, &pfn, &level);
+	r = __direct_map(vcpu, gpa, write, map_writable,
+			 level, gfn, pfn, prefault);
 	spin_unlock(&vcpu->kvm->mmu_lock);
 
 	return r;
@@ -2659,18 +2820,19 @@ void kvm_mmu_flush_tlb(struct kvm_vcpu *
 
 static void paging_new_cr3(struct kvm_vcpu *vcpu)
 {
-	pgprintk("%s: cr3 %lx\n", __func__, vcpu->arch.cr3);
+	pgprintk("%s: cr3 %lx\n", __func__, kvm_read_cr3(vcpu));
 	mmu_free_roots(vcpu);
 }
 
 static unsigned long get_cr3(struct kvm_vcpu *vcpu)
 {
-	return vcpu->arch.cr3;
+	return kvm_read_cr3(vcpu);
 }
 
-static void inject_page_fault(struct kvm_vcpu *vcpu)
+static void inject_page_fault(struct kvm_vcpu *vcpu,
+			      struct x86_exception *fault)
 {
-	vcpu->arch.mmu.inject_page_fault(vcpu);
+	vcpu->arch.mmu.inject_page_fault(vcpu, fault);
 }
 
 static void paging_free(struct kvm_vcpu *vcpu)
@@ -2816,6 +2978,7 @@ static int init_kvm_tdp_mmu(struct kvm_v
 {
 	struct kvm_mmu *context = vcpu->arch.walk_mmu;
 
+	context->base_role.word = 0;
 	context->new_cr3 = nonpaging_new_cr3;
 	context->page_fault = tdp_page_fault;
 	context->free = nonpaging_free;
@@ -3008,9 +3171,6 @@ static void mmu_pte_write_new_pte(struct
 		return;
         }
 
-	if (is_rsvd_bits_set(&vcpu->arch.mmu, *(u64 *)new, PT_PAGE_TABLE_LEVEL))
-		return;
-
 	++vcpu->kvm->stat.mmu_pte_updated;
 	if (!sp->role.cr4_pae)
 		paging32_update_pte(vcpu, sp, spte, new);
@@ -3264,12 +3424,13 @@ void __kvm_mmu_free_some_pages(struct kv
 	}
 }
 
-int kvm_mmu_page_fault(struct kvm_vcpu *vcpu, gva_t cr2, u32 error_code)
+int kvm_mmu_page_fault(struct kvm_vcpu *vcpu, gva_t cr2, u32 error_code,
+		       void *insn, int insn_len)
 {
 	int r;
 	enum emulation_result er;
 
-	r = vcpu->arch.mmu.page_fault(vcpu, cr2, error_code);
+	r = vcpu->arch.mmu.page_fault(vcpu, cr2, error_code, false);
 	if (r < 0)
 		goto out;
 
@@ -3282,7 +3443,7 @@ int kvm_mmu_page_fault(struct kvm_vcpu *
 	if (r)
 		goto out;
 
-	er = emulate_instruction(vcpu, cr2, error_code, 0);
+	er = x86_emulate_instruction(vcpu, cr2, 0, insn, insn_len);
 
 	switch (er) {
 	case EMULATE_DONE:
@@ -3377,11 +3538,14 @@ void kvm_mmu_slot_remove_write_access(st
 		if (!test_bit(slot, sp->slot_bitmap))
 			continue;
 
+		if (sp->role.level != PT_PAGE_TABLE_LEVEL)
+			continue;
+
 		pt = sp->spt;
 		for (i = 0; i < PT64_ENT_PER_PAGE; ++i)
 			/* avoid RMW */
 			if (is_writable_pte(pt[i]))
-				pt[i] &= ~PT_WRITABLE_MASK;
+				update_spte(&pt[i], pt[i] & ~PT_WRITABLE_MASK);
 	}
 	kvm_flush_remote_tlbs(kvm);
 }
@@ -3463,13 +3627,6 @@ static void mmu_destroy_caches(void)
 		kmem_cache_destroy(mmu_page_header_cache);
 }
 
-void kvm_mmu_module_exit(void)
-{
-	mmu_destroy_caches();
-	percpu_counter_destroy(&kvm_total_used_mmu_pages);
-	unregister_shrinker(&mmu_shrinker);
-}
-
 int kvm_mmu_module_init(void)
 {
 	pte_chain_cache = kmem_cache_create("kvm_pte_chain",
@@ -3566,7 +3723,7 @@ static int kvm_pv_mmu_write(struct kvm_v
 
 static int kvm_pv_mmu_flush_tlb(struct kvm_vcpu *vcpu)
 {
-	(void)kvm_set_cr3(vcpu, vcpu->arch.cr3);
+	(void)kvm_set_cr3(vcpu, kvm_read_cr3(vcpu));
 	return 1;
 }
 
@@ -3662,12 +3819,6 @@ int kvm_mmu_get_spte_hierarchy(struct kv
 }
 EXPORT_SYMBOL_GPL(kvm_mmu_get_spte_hierarchy);
 
-#ifdef CONFIG_KVM_MMU_AUDIT
-#include "mmu_audit.c"
-#else
-static void mmu_audit_disable(void) { }
-#endif
-
 void kvm_mmu_destroy(struct kvm_vcpu *vcpu)
 {
 	ASSERT(vcpu);
@@ -3675,5 +3826,18 @@ void kvm_mmu_destroy(struct kvm_vcpu *vc
 	destroy_kvm_mmu(vcpu);
 	free_mmu_pages(vcpu);
 	mmu_free_memory_caches(vcpu);
+}
+
+#ifdef CONFIG_KVM_MMU_AUDIT
+#include "mmu_audit.c"
+#else
+static void mmu_audit_disable(void) { }
+#endif
+
+void kvm_mmu_module_exit(void)
+{
+	mmu_destroy_caches();
+	percpu_counter_destroy(&kvm_total_used_mmu_pages);
+	unregister_shrinker(&mmu_shrinker);
 	mmu_audit_disable();
 }
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/kvm/paging_tmpl.h linux-libre-2.6.38-gnu1/arch/x86/kvm/paging_tmpl.h
--- linux-libre-2.6.37-gnu1/arch/x86/kvm/paging_tmpl.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/kvm/paging_tmpl.h	2011-03-14 21:20:32.000000000 -0400
@@ -72,7 +72,7 @@ struct guest_walker {
 	unsigned pt_access;
 	unsigned pte_access;
 	gfn_t gfn;
-	u32 error_code;
+	struct x86_exception fault;
 };
 
 static gfn_t gpte_to_gfn_lvl(pt_element_t gpte, int lvl)
@@ -266,21 +266,23 @@ walk:
 	return 1;
 
 error:
-	walker->error_code = 0;
+	walker->fault.vector = PF_VECTOR;
+	walker->fault.error_code_valid = true;
+	walker->fault.error_code = 0;
 	if (present)
-		walker->error_code |= PFERR_PRESENT_MASK;
+		walker->fault.error_code |= PFERR_PRESENT_MASK;
 
-	walker->error_code |= write_fault | user_fault;
+	walker->fault.error_code |= write_fault | user_fault;
 
 	if (fetch_fault && mmu->nx)
-		walker->error_code |= PFERR_FETCH_MASK;
+		walker->fault.error_code |= PFERR_FETCH_MASK;
 	if (rsvd_fault)
-		walker->error_code |= PFERR_RSVD_MASK;
+		walker->fault.error_code |= PFERR_RSVD_MASK;
 
-	vcpu->arch.fault.address    = addr;
-	vcpu->arch.fault.error_code = walker->error_code;
+	walker->fault.address = addr;
+	walker->fault.nested_page_fault = mmu != vcpu->arch.walk_mmu;
 
-	trace_kvm_mmu_walker_error(walker->error_code);
+	trace_kvm_mmu_walker_error(walker->fault.error_code);
 	return 0;
 }
 
@@ -299,25 +301,42 @@ static int FNAME(walk_addr_nested)(struc
 					addr, access);
 }
 
+static bool FNAME(prefetch_invalid_gpte)(struct kvm_vcpu *vcpu,
+				    struct kvm_mmu_page *sp, u64 *spte,
+				    pt_element_t gpte)
+{
+	u64 nonpresent = shadow_trap_nonpresent_pte;
+
+	if (is_rsvd_bits_set(&vcpu->arch.mmu, gpte, PT_PAGE_TABLE_LEVEL))
+		goto no_present;
+
+	if (!is_present_gpte(gpte)) {
+		if (!sp->unsync)
+			nonpresent = shadow_notrap_nonpresent_pte;
+		goto no_present;
+	}
+
+	if (!(gpte & PT_ACCESSED_MASK))
+		goto no_present;
+
+	return false;
+
+no_present:
+	drop_spte(vcpu->kvm, spte, nonpresent);
+	return true;
+}
+
 static void FNAME(update_pte)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp,
 			      u64 *spte, const void *pte)
 {
 	pt_element_t gpte;
 	unsigned pte_access;
 	pfn_t pfn;
-	u64 new_spte;
 
 	gpte = *(const pt_element_t *)pte;
-	if (~gpte & (PT_PRESENT_MASK | PT_ACCESSED_MASK)) {
-		if (!is_present_gpte(gpte)) {
-			if (sp->unsync)
-				new_spte = shadow_trap_nonpresent_pte;
-			else
-				new_spte = shadow_notrap_nonpresent_pte;
-			__set_spte(spte, new_spte);
-		}
+	if (FNAME(prefetch_invalid_gpte)(vcpu, sp, spte, gpte))
 		return;
-	}
+
 	pgprintk("%s: gpte %llx spte %p\n", __func__, (u64)gpte, spte);
 	pte_access = sp->role.access & FNAME(gpte_access)(vcpu, gpte);
 	if (gpte_to_gfn(gpte) != vcpu->arch.update_pte.gfn)
@@ -329,7 +348,7 @@ static void FNAME(update_pte)(struct kvm
 		return;
 	kvm_get_pfn(pfn);
 	/*
-	 * we call mmu_set_spte() with reset_host_protection = true beacuse that
+	 * we call mmu_set_spte() with host_writable = true beacuse that
 	 * vcpu->arch.update_pte.pfn was fetched from get_user_pages(write = 1).
 	 */
 	mmu_set_spte(vcpu, spte, sp->role.access, pte_access, 0, 0,
@@ -364,7 +383,6 @@ static void FNAME(pte_prefetch)(struct k
 				u64 *sptep)
 {
 	struct kvm_mmu_page *sp;
-	struct kvm_mmu *mmu = &vcpu->arch.mmu;
 	pt_element_t *gptep = gw->prefetch_ptes;
 	u64 *spte;
 	int i;
@@ -395,14 +413,7 @@ static void FNAME(pte_prefetch)(struct k
 
 		gpte = gptep[i];
 
-		if (!is_present_gpte(gpte) ||
-		      is_rsvd_bits_set(mmu, gpte, PT_PAGE_TABLE_LEVEL)) {
-			if (!sp->unsync)
-				__set_spte(spte, shadow_notrap_nonpresent_pte);
-			continue;
-		}
-
-		if (!(gpte & PT_ACCESSED_MASK))
+		if (FNAME(prefetch_invalid_gpte)(vcpu, sp, spte, gpte))
 			continue;
 
 		pte_access = sp->role.access & FNAME(gpte_access)(vcpu, gpte);
@@ -427,7 +438,8 @@ static void FNAME(pte_prefetch)(struct k
 static u64 *FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr,
 			 struct guest_walker *gw,
 			 int user_fault, int write_fault, int hlevel,
-			 int *ptwrite, pfn_t pfn)
+			 int *ptwrite, pfn_t pfn, bool map_writable,
+			 bool prefault)
 {
 	unsigned access = gw->pt_access;
 	struct kvm_mmu_page *sp = NULL;
@@ -501,7 +513,7 @@ static u64 *FNAME(fetch)(struct kvm_vcpu
 
 	mmu_set_spte(vcpu, it.sptep, access, gw->pte_access & access,
 		     user_fault, write_fault, dirty, ptwrite, it.level,
-		     gw->gfn, pfn, false, true);
+		     gw->gfn, pfn, prefault, map_writable);
 	FNAME(pte_prefetch)(vcpu, gw, it.sptep);
 
 	return it.sptep;
@@ -527,8 +539,8 @@ out_gpte_changed:
  *  Returns: 1 if we need to emulate the instruction, 0 otherwise, or
  *           a negative value on error.
  */
-static int FNAME(page_fault)(struct kvm_vcpu *vcpu, gva_t addr,
-			       u32 error_code)
+static int FNAME(page_fault)(struct kvm_vcpu *vcpu, gva_t addr, u32 error_code,
+			     bool prefault)
 {
 	int write_fault = error_code & PFERR_WRITE_MASK;
 	int user_fault = error_code & PFERR_USER_MASK;
@@ -538,7 +550,9 @@ static int FNAME(page_fault)(struct kvm_
 	int r;
 	pfn_t pfn;
 	int level = PT_PAGE_TABLE_LEVEL;
+	int force_pt_level;
 	unsigned long mmu_seq;
+	bool map_writable;
 
 	pgprintk("%s: addr %lx err %x\n", __func__, addr, error_code);
 
@@ -556,19 +570,29 @@ static int FNAME(page_fault)(struct kvm_
 	 */
 	if (!r) {
 		pgprintk("%s: guest page fault\n", __func__);
-		inject_page_fault(vcpu);
-		vcpu->arch.last_pt_write_count = 0; /* reset fork detector */
+		if (!prefault) {
+			inject_page_fault(vcpu, &walker.fault);
+			/* reset fork detector */
+			vcpu->arch.last_pt_write_count = 0;
+		}
 		return 0;
 	}
 
-	if (walker.level >= PT_DIRECTORY_LEVEL) {
+	if (walker.level >= PT_DIRECTORY_LEVEL)
+		force_pt_level = mapping_level_dirty_bitmap(vcpu, walker.gfn);
+	else
+		force_pt_level = 1;
+	if (!force_pt_level) {
 		level = min(walker.level, mapping_level(vcpu, walker.gfn));
 		walker.gfn = walker.gfn & ~(KVM_PAGES_PER_HPAGE(level) - 1);
 	}
 
 	mmu_seq = vcpu->kvm->mmu_notifier_seq;
 	smp_rmb();
-	pfn = gfn_to_pfn(vcpu->kvm, walker.gfn);
+
+	if (try_async_pf(vcpu, prefault, walker.gfn, addr, &pfn, write_fault,
+			 &map_writable))
+		return 0;
 
 	/* mmio */
 	if (is_error_pfn(pfn))
@@ -580,8 +604,10 @@ static int FNAME(page_fault)(struct kvm_
 
 	trace_kvm_mmu_audit(vcpu, AUDIT_PRE_PAGE_FAULT);
 	kvm_mmu_free_some_pages(vcpu);
+	if (!force_pt_level)
+		transparent_hugepage_adjust(vcpu, &walker.gfn, &pfn, &level);
 	sptep = FNAME(fetch)(vcpu, addr, &walker, user_fault, write_fault,
-			     level, &write_pt, pfn);
+			     level, &write_pt, pfn, map_writable, prefault);
 	(void)sptep;
 	pgprintk("%s: shadow pte %p %llx ptwrite %d\n", __func__,
 		 sptep, *sptep, write_pt);
@@ -661,7 +687,7 @@ static void FNAME(invlpg)(struct kvm_vcp
 }
 
 static gpa_t FNAME(gva_to_gpa)(struct kvm_vcpu *vcpu, gva_t vaddr, u32 access,
-			       u32 *error)
+			       struct x86_exception *exception)
 {
 	struct guest_walker walker;
 	gpa_t gpa = UNMAPPED_GVA;
@@ -672,14 +698,15 @@ static gpa_t FNAME(gva_to_gpa)(struct kv
 	if (r) {
 		gpa = gfn_to_gpa(walker.gfn);
 		gpa |= vaddr & ~PAGE_MASK;
-	} else if (error)
-		*error = walker.error_code;
+	} else if (exception)
+		*exception = walker.fault;
 
 	return gpa;
 }
 
 static gpa_t FNAME(gva_to_gpa_nested)(struct kvm_vcpu *vcpu, gva_t vaddr,
-				      u32 access, u32 *error)
+				      u32 access,
+				      struct x86_exception *exception)
 {
 	struct guest_walker walker;
 	gpa_t gpa = UNMAPPED_GVA;
@@ -690,8 +717,8 @@ static gpa_t FNAME(gva_to_gpa_nested)(st
 	if (r) {
 		gpa = gfn_to_gpa(walker.gfn);
 		gpa |= vaddr & ~PAGE_MASK;
-	} else if (error)
-		*error = walker.error_code;
+	} else if (exception)
+		*exception = walker.fault;
 
 	return gpa;
 }
@@ -730,12 +757,19 @@ static void FNAME(prefetch_page)(struct
  * Using the cached information from sp->gfns is safe because:
  * - The spte has a reference to the struct page, so the pfn for a given gfn
  *   can't change unless all sptes pointing to it are nuked first.
+ *
+ * Note:
+ *   We should flush all tlbs if spte is dropped even though guest is
+ *   responsible for it. Since if we don't, kvm_mmu_notifier_invalidate_page
+ *   and kvm_mmu_notifier_invalidate_range_start detect the mapping page isn't
+ *   used by guest then tlbs are not flushed, so guest is allowed to access the
+ *   freed pages.
+ *   And we increase kvm->tlbs_dirty to delay tlbs flush in this case.
  */
-static int FNAME(sync_page)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp,
-			    bool clear_unsync)
+static int FNAME(sync_page)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp)
 {
 	int i, offset, nr_present;
-	bool reset_host_protection;
+	bool host_writable;
 	gpa_t first_pte_gpa;
 
 	offset = nr_present = 0;
@@ -764,31 +798,27 @@ static int FNAME(sync_page)(struct kvm_v
 			return -EINVAL;
 
 		gfn = gpte_to_gfn(gpte);
-		if (is_rsvd_bits_set(&vcpu->arch.mmu, gpte, PT_PAGE_TABLE_LEVEL)
-		      || gfn != sp->gfns[i] || !is_present_gpte(gpte)
-		      || !(gpte & PT_ACCESSED_MASK)) {
-			u64 nonpresent;
 
-			if (is_present_gpte(gpte) || !clear_unsync)
-				nonpresent = shadow_trap_nonpresent_pte;
-			else
-				nonpresent = shadow_notrap_nonpresent_pte;
-			drop_spte(vcpu->kvm, &sp->spt[i], nonpresent);
+		if (FNAME(prefetch_invalid_gpte)(vcpu, sp, &sp->spt[i], gpte)) {
+			vcpu->kvm->tlbs_dirty++;
+			continue;
+		}
+
+		if (gfn != sp->gfns[i]) {
+			drop_spte(vcpu->kvm, &sp->spt[i],
+				      shadow_trap_nonpresent_pte);
+			vcpu->kvm->tlbs_dirty++;
 			continue;
 		}
 
 		nr_present++;
 		pte_access = sp->role.access & FNAME(gpte_access)(vcpu, gpte);
-		if (!(sp->spt[i] & SPTE_HOST_WRITEABLE)) {
-			pte_access &= ~ACC_WRITE_MASK;
-			reset_host_protection = 0;
-		} else {
-			reset_host_protection = 1;
-		}
+		host_writable = sp->spt[i] & SPTE_HOST_WRITEABLE;
+
 		set_spte(vcpu, &sp->spt[i], pte_access, 0, 0,
 			 is_dirty_gpte(gpte), PT_PAGE_TABLE_LEVEL, gfn,
 			 spte_to_pfn(sp->spt[i]), true, false,
-			 reset_host_protection);
+			 host_writable);
 	}
 
 	return !nr_present;
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/kvm/svm.c linux-libre-2.6.38-gnu1/arch/x86/kvm/svm.c
--- linux-libre-2.6.37-gnu1/arch/x86/kvm/svm.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/kvm/svm.c	2011-03-14 21:20:32.000000000 -0400
@@ -31,6 +31,7 @@
 
 #include <asm/tlbflush.h>
 #include <asm/desc.h>
+#include <asm/kvm_para.h>
 
 #include <asm/virtext.h>
 #include "trace.h"
@@ -50,6 +51,10 @@ MODULE_LICENSE("GPL");
 #define SVM_FEATURE_LBRV           (1 <<  1)
 #define SVM_FEATURE_SVML           (1 <<  2)
 #define SVM_FEATURE_NRIP           (1 <<  3)
+#define SVM_FEATURE_TSC_RATE       (1 <<  4)
+#define SVM_FEATURE_VMCB_CLEAN     (1 <<  5)
+#define SVM_FEATURE_FLUSH_ASID     (1 <<  6)
+#define SVM_FEATURE_DECODE_ASSIST  (1 <<  7)
 #define SVM_FEATURE_PAUSE_FILTER   (1 << 10)
 
 #define NESTED_EXIT_HOST	0	/* Exit handled on host level */
@@ -97,10 +102,8 @@ struct nested_state {
 	unsigned long vmexit_rax;
 
 	/* cache for intercepts of the guest */
-	u16 intercept_cr_read;
-	u16 intercept_cr_write;
-	u16 intercept_dr_read;
-	u16 intercept_dr_write;
+	u32 intercept_cr;
+	u32 intercept_dr;
 	u32 intercept_exceptions;
 	u64 intercept;
 
@@ -123,7 +126,12 @@ struct vcpu_svm {
 	u64 next_rip;
 
 	u64 host_user_msrs[NR_HOST_SAVE_USER_MSRS];
-	u64 host_gs_base;
+	struct {
+		u16 fs;
+		u16 gs;
+		u16 ldt;
+		u64 gs_base;
+	} host;
 
 	u32 *msrpm;
 
@@ -133,6 +141,7 @@ struct vcpu_svm {
 
 	unsigned int3_injected;
 	unsigned long int3_rip;
+	u32 apf_reason;
 };
 
 #define MSR_INVALID			0xffffffffU
@@ -180,14 +189,151 @@ static int nested_svm_vmexit(struct vcpu
 static int nested_svm_check_exception(struct vcpu_svm *svm, unsigned nr,
 				      bool has_error_code, u32 error_code);
 
+enum {
+	VMCB_INTERCEPTS, /* Intercept vectors, TSC offset,
+			    pause filter count */
+	VMCB_PERM_MAP,   /* IOPM Base and MSRPM Base */
+	VMCB_ASID,	 /* ASID */
+	VMCB_INTR,	 /* int_ctl, int_vector */
+	VMCB_NPT,        /* npt_en, nCR3, gPAT */
+	VMCB_CR,	 /* CR0, CR3, CR4, EFER */
+	VMCB_DR,         /* DR6, DR7 */
+	VMCB_DT,         /* GDT, IDT */
+	VMCB_SEG,        /* CS, DS, SS, ES, CPL */
+	VMCB_CR2,        /* CR2 only */
+	VMCB_LBR,        /* DBGCTL, BR_FROM, BR_TO, LAST_EX_FROM, LAST_EX_TO */
+	VMCB_DIRTY_MAX,
+};
+
+/* TPR and CR2 are always written before VMRUN */
+#define VMCB_ALWAYS_DIRTY_MASK	((1U << VMCB_INTR) | (1U << VMCB_CR2))
+
+static inline void mark_all_dirty(struct vmcb *vmcb)
+{
+	vmcb->control.clean = 0;
+}
+
+static inline void mark_all_clean(struct vmcb *vmcb)
+{
+	vmcb->control.clean = ((1 << VMCB_DIRTY_MAX) - 1)
+			       & ~VMCB_ALWAYS_DIRTY_MASK;
+}
+
+static inline void mark_dirty(struct vmcb *vmcb, int bit)
+{
+	vmcb->control.clean &= ~(1 << bit);
+}
+
 static inline struct vcpu_svm *to_svm(struct kvm_vcpu *vcpu)
 {
 	return container_of(vcpu, struct vcpu_svm, vcpu);
 }
 
-static inline bool is_nested(struct vcpu_svm *svm)
+static void recalc_intercepts(struct vcpu_svm *svm)
 {
-	return svm->nested.vmcb;
+	struct vmcb_control_area *c, *h;
+	struct nested_state *g;
+
+	mark_dirty(svm->vmcb, VMCB_INTERCEPTS);
+
+	if (!is_guest_mode(&svm->vcpu))
+		return;
+
+	c = &svm->vmcb->control;
+	h = &svm->nested.hsave->control;
+	g = &svm->nested;
+
+	c->intercept_cr = h->intercept_cr | g->intercept_cr;
+	c->intercept_dr = h->intercept_dr | g->intercept_dr;
+	c->intercept_exceptions = h->intercept_exceptions | g->intercept_exceptions;
+	c->intercept = h->intercept | g->intercept;
+}
+
+static inline struct vmcb *get_host_vmcb(struct vcpu_svm *svm)
+{
+	if (is_guest_mode(&svm->vcpu))
+		return svm->nested.hsave;
+	else
+		return svm->vmcb;
+}
+
+static inline void set_cr_intercept(struct vcpu_svm *svm, int bit)
+{
+	struct vmcb *vmcb = get_host_vmcb(svm);
+
+	vmcb->control.intercept_cr |= (1U << bit);
+
+	recalc_intercepts(svm);
+}
+
+static inline void clr_cr_intercept(struct vcpu_svm *svm, int bit)
+{
+	struct vmcb *vmcb = get_host_vmcb(svm);
+
+	vmcb->control.intercept_cr &= ~(1U << bit);
+
+	recalc_intercepts(svm);
+}
+
+static inline bool is_cr_intercept(struct vcpu_svm *svm, int bit)
+{
+	struct vmcb *vmcb = get_host_vmcb(svm);
+
+	return vmcb->control.intercept_cr & (1U << bit);
+}
+
+static inline void set_dr_intercept(struct vcpu_svm *svm, int bit)
+{
+	struct vmcb *vmcb = get_host_vmcb(svm);
+
+	vmcb->control.intercept_dr |= (1U << bit);
+
+	recalc_intercepts(svm);
+}
+
+static inline void clr_dr_intercept(struct vcpu_svm *svm, int bit)
+{
+	struct vmcb *vmcb = get_host_vmcb(svm);
+
+	vmcb->control.intercept_dr &= ~(1U << bit);
+
+	recalc_intercepts(svm);
+}
+
+static inline void set_exception_intercept(struct vcpu_svm *svm, int bit)
+{
+	struct vmcb *vmcb = get_host_vmcb(svm);
+
+	vmcb->control.intercept_exceptions |= (1U << bit);
+
+	recalc_intercepts(svm);
+}
+
+static inline void clr_exception_intercept(struct vcpu_svm *svm, int bit)
+{
+	struct vmcb *vmcb = get_host_vmcb(svm);
+
+	vmcb->control.intercept_exceptions &= ~(1U << bit);
+
+	recalc_intercepts(svm);
+}
+
+static inline void set_intercept(struct vcpu_svm *svm, int bit)
+{
+	struct vmcb *vmcb = get_host_vmcb(svm);
+
+	vmcb->control.intercept |= (1ULL << bit);
+
+	recalc_intercepts(svm);
+}
+
+static inline void clr_intercept(struct vcpu_svm *svm, int bit)
+{
+	struct vmcb *vmcb = get_host_vmcb(svm);
+
+	vmcb->control.intercept &= ~(1ULL << bit);
+
+	recalc_intercepts(svm);
 }
 
 static inline void enable_gif(struct vcpu_svm *svm)
@@ -264,11 +410,6 @@ static u32 svm_msrpm_offset(u32 msr)
 
 #define MAX_INST_SIZE 15
 
-static inline u32 svm_has(u32 feat)
-{
-	return svm_features & feat;
-}
-
 static inline void clgi(void)
 {
 	asm volatile (__ex(SVM_CLGI));
@@ -284,16 +425,6 @@ static inline void invlpga(unsigned long
 	asm volatile (__ex(SVM_INVLPGA) : : "a"(addr), "c"(asid));
 }
 
-static inline void force_new_asid(struct kvm_vcpu *vcpu)
-{
-	to_svm(vcpu)->asid_generation--;
-}
-
-static inline void flush_guest_tlb(struct kvm_vcpu *vcpu)
-{
-	force_new_asid(vcpu);
-}
-
 static int get_npt_level(void)
 {
 #ifdef CONFIG_X86_64
@@ -310,6 +441,7 @@ static void svm_set_efer(struct kvm_vcpu
 		efer &= ~EFER_LME;
 
 	to_svm(vcpu)->vmcb->save.efer = efer | EFER_SVME;
+	mark_dirty(to_svm(vcpu)->vmcb, VMCB_CR);
 }
 
 static int is_external_interrupt(u32 info)
@@ -347,7 +479,7 @@ static void skip_emulated_instruction(st
 		svm->next_rip = svm->vmcb->control.next_rip;
 
 	if (!svm->next_rip) {
-		if (emulate_instruction(vcpu, 0, 0, EMULTYPE_SKIP) !=
+		if (emulate_instruction(vcpu, EMULTYPE_SKIP) !=
 				EMULATE_DONE)
 			printk(KERN_DEBUG "%s: NOP\n", __func__);
 		return;
@@ -374,7 +506,7 @@ static void svm_queue_exception(struct k
 	    nested_svm_check_exception(svm, nr, has_error_code, error_code))
 		return;
 
-	if (nr == BP_VECTOR && !svm_has(SVM_FEATURE_NRIP)) {
+	if (nr == BP_VECTOR && !static_cpu_has(X86_FEATURE_NRIPS)) {
 		unsigned long rip, old_rip = kvm_rip_read(&svm->vcpu);
 
 		/*
@@ -670,7 +802,7 @@ static __init int svm_hardware_setup(voi
 
 	svm_features = cpuid_edx(SVM_CPUID_FUNC);
 
-	if (!svm_has(SVM_FEATURE_NPT))
+	if (!boot_cpu_has(X86_FEATURE_NPT))
 		npt_enabled = false;
 
 	if (npt_enabled && !npt) {
@@ -725,13 +857,15 @@ static void svm_write_tsc_offset(struct
 	struct vcpu_svm *svm = to_svm(vcpu);
 	u64 g_tsc_offset = 0;
 
-	if (is_nested(svm)) {
+	if (is_guest_mode(vcpu)) {
 		g_tsc_offset = svm->vmcb->control.tsc_offset -
 			       svm->nested.hsave->control.tsc_offset;
 		svm->nested.hsave->control.tsc_offset = offset;
 	}
 
 	svm->vmcb->control.tsc_offset = offset + g_tsc_offset;
+
+	mark_dirty(svm->vmcb, VMCB_INTERCEPTS);
 }
 
 static void svm_adjust_tsc_offset(struct kvm_vcpu *vcpu, s64 adjustment)
@@ -739,8 +873,9 @@ static void svm_adjust_tsc_offset(struct
 	struct vcpu_svm *svm = to_svm(vcpu);
 
 	svm->vmcb->control.tsc_offset += adjustment;
-	if (is_nested(svm))
+	if (is_guest_mode(vcpu))
 		svm->nested.hsave->control.tsc_offset += adjustment;
+	mark_dirty(svm->vmcb, VMCB_INTERCEPTS);
 }
 
 static void init_vmcb(struct vcpu_svm *svm)
@@ -749,62 +884,62 @@ static void init_vmcb(struct vcpu_svm *s
 	struct vmcb_save_area *save = &svm->vmcb->save;
 
 	svm->vcpu.fpu_active = 1;
+	svm->vcpu.arch.hflags = 0;
 
-	control->intercept_cr_read =	INTERCEPT_CR0_MASK |
-					INTERCEPT_CR3_MASK |
-					INTERCEPT_CR4_MASK;
-
-	control->intercept_cr_write =	INTERCEPT_CR0_MASK |
-					INTERCEPT_CR3_MASK |
-					INTERCEPT_CR4_MASK |
-					INTERCEPT_CR8_MASK;
-
-	control->intercept_dr_read =	INTERCEPT_DR0_MASK |
-					INTERCEPT_DR1_MASK |
-					INTERCEPT_DR2_MASK |
-					INTERCEPT_DR3_MASK |
-					INTERCEPT_DR4_MASK |
-					INTERCEPT_DR5_MASK |
-					INTERCEPT_DR6_MASK |
-					INTERCEPT_DR7_MASK;
+	set_cr_intercept(svm, INTERCEPT_CR0_READ);
+	set_cr_intercept(svm, INTERCEPT_CR3_READ);
+	set_cr_intercept(svm, INTERCEPT_CR4_READ);
+	set_cr_intercept(svm, INTERCEPT_CR0_WRITE);
+	set_cr_intercept(svm, INTERCEPT_CR3_WRITE);
+	set_cr_intercept(svm, INTERCEPT_CR4_WRITE);
+	set_cr_intercept(svm, INTERCEPT_CR8_WRITE);
 
-	control->intercept_dr_write =	INTERCEPT_DR0_MASK |
-					INTERCEPT_DR1_MASK |
-					INTERCEPT_DR2_MASK |
-					INTERCEPT_DR3_MASK |
-					INTERCEPT_DR4_MASK |
-					INTERCEPT_DR5_MASK |
-					INTERCEPT_DR6_MASK |
-					INTERCEPT_DR7_MASK;
+	set_dr_intercept(svm, INTERCEPT_DR0_READ);
+	set_dr_intercept(svm, INTERCEPT_DR1_READ);
+	set_dr_intercept(svm, INTERCEPT_DR2_READ);
+	set_dr_intercept(svm, INTERCEPT_DR3_READ);
+	set_dr_intercept(svm, INTERCEPT_DR4_READ);
+	set_dr_intercept(svm, INTERCEPT_DR5_READ);
+	set_dr_intercept(svm, INTERCEPT_DR6_READ);
+	set_dr_intercept(svm, INTERCEPT_DR7_READ);
 
-	control->intercept_exceptions = (1 << PF_VECTOR) |
-					(1 << UD_VECTOR) |
-					(1 << MC_VECTOR);
+	set_dr_intercept(svm, INTERCEPT_DR0_WRITE);
+	set_dr_intercept(svm, INTERCEPT_DR1_WRITE);
+	set_dr_intercept(svm, INTERCEPT_DR2_WRITE);
+	set_dr_intercept(svm, INTERCEPT_DR3_WRITE);
+	set_dr_intercept(svm, INTERCEPT_DR4_WRITE);
+	set_dr_intercept(svm, INTERCEPT_DR5_WRITE);
+	set_dr_intercept(svm, INTERCEPT_DR6_WRITE);
+	set_dr_intercept(svm, INTERCEPT_DR7_WRITE);
 
+	set_exception_intercept(svm, PF_VECTOR);
+	set_exception_intercept(svm, UD_VECTOR);
+	set_exception_intercept(svm, MC_VECTOR);
 
-	control->intercept =	(1ULL << INTERCEPT_INTR) |
-				(1ULL << INTERCEPT_NMI) |
-				(1ULL << INTERCEPT_SMI) |
-				(1ULL << INTERCEPT_SELECTIVE_CR0) |
-				(1ULL << INTERCEPT_CPUID) |
-				(1ULL << INTERCEPT_INVD) |
-				(1ULL << INTERCEPT_HLT) |
-				(1ULL << INTERCEPT_INVLPG) |
-				(1ULL << INTERCEPT_INVLPGA) |
-				(1ULL << INTERCEPT_IOIO_PROT) |
-				(1ULL << INTERCEPT_MSR_PROT) |
-				(1ULL << INTERCEPT_TASK_SWITCH) |
-				(1ULL << INTERCEPT_SHUTDOWN) |
-				(1ULL << INTERCEPT_VMRUN) |
-				(1ULL << INTERCEPT_VMMCALL) |
-				(1ULL << INTERCEPT_VMLOAD) |
-				(1ULL << INTERCEPT_VMSAVE) |
-				(1ULL << INTERCEPT_STGI) |
-				(1ULL << INTERCEPT_CLGI) |
-				(1ULL << INTERCEPT_SKINIT) |
-				(1ULL << INTERCEPT_WBINVD) |
-				(1ULL << INTERCEPT_MONITOR) |
-				(1ULL << INTERCEPT_MWAIT);
+	set_intercept(svm, INTERCEPT_INTR);
+	set_intercept(svm, INTERCEPT_NMI);
+	set_intercept(svm, INTERCEPT_SMI);
+	set_intercept(svm, INTERCEPT_SELECTIVE_CR0);
+	set_intercept(svm, INTERCEPT_CPUID);
+	set_intercept(svm, INTERCEPT_INVD);
+	set_intercept(svm, INTERCEPT_HLT);
+	set_intercept(svm, INTERCEPT_INVLPG);
+	set_intercept(svm, INTERCEPT_INVLPGA);
+	set_intercept(svm, INTERCEPT_IOIO_PROT);
+	set_intercept(svm, INTERCEPT_MSR_PROT);
+	set_intercept(svm, INTERCEPT_TASK_SWITCH);
+	set_intercept(svm, INTERCEPT_SHUTDOWN);
+	set_intercept(svm, INTERCEPT_VMRUN);
+	set_intercept(svm, INTERCEPT_VMMCALL);
+	set_intercept(svm, INTERCEPT_VMLOAD);
+	set_intercept(svm, INTERCEPT_VMSAVE);
+	set_intercept(svm, INTERCEPT_STGI);
+	set_intercept(svm, INTERCEPT_CLGI);
+	set_intercept(svm, INTERCEPT_SKINIT);
+	set_intercept(svm, INTERCEPT_WBINVD);
+	set_intercept(svm, INTERCEPT_MONITOR);
+	set_intercept(svm, INTERCEPT_MWAIT);
+	set_intercept(svm, INTERCEPT_XSETBV);
 
 	control->iopm_base_pa = iopm_base;
 	control->msrpm_base_pa = __pa(svm->msrpm);
@@ -855,25 +990,27 @@ static void init_vmcb(struct vcpu_svm *s
 	if (npt_enabled) {
 		/* Setup VMCB for Nested Paging */
 		control->nested_ctl = 1;
-		control->intercept &= ~((1ULL << INTERCEPT_TASK_SWITCH) |
-					(1ULL << INTERCEPT_INVLPG));
-		control->intercept_exceptions &= ~(1 << PF_VECTOR);
-		control->intercept_cr_read &= ~INTERCEPT_CR3_MASK;
-		control->intercept_cr_write &= ~INTERCEPT_CR3_MASK;
+		clr_intercept(svm, INTERCEPT_TASK_SWITCH);
+		clr_intercept(svm, INTERCEPT_INVLPG);
+		clr_exception_intercept(svm, PF_VECTOR);
+		clr_cr_intercept(svm, INTERCEPT_CR3_READ);
+		clr_cr_intercept(svm, INTERCEPT_CR3_WRITE);
 		save->g_pat = 0x0007040600070406ULL;
 		save->cr3 = 0;
 		save->cr4 = 0;
 	}
-	force_new_asid(&svm->vcpu);
+	svm->asid_generation = 0;
 
 	svm->nested.vmcb = 0;
 	svm->vcpu.arch.hflags = 0;
 
-	if (svm_has(SVM_FEATURE_PAUSE_FILTER)) {
+	if (boot_cpu_has(X86_FEATURE_PAUSEFILTER)) {
 		control->pause_filter_count = 3000;
-		control->intercept |= (1ULL << INTERCEPT_PAUSE);
+		set_intercept(svm, INTERCEPT_PAUSE);
 	}
 
+	mark_all_dirty(svm->vmcb);
+
 	enable_gif(svm);
 }
 
@@ -990,8 +1127,16 @@ static void svm_vcpu_load(struct kvm_vcp
 
 	if (unlikely(cpu != vcpu->cpu)) {
 		svm->asid_generation = 0;
+		mark_all_dirty(svm->vmcb);
 	}
 
+#ifdef CONFIG_X86_64
+	rdmsrl(MSR_GS_BASE, to_svm(vcpu)->host.gs_base);
+#endif
+	savesegment(fs, svm->host.fs);
+	savesegment(gs, svm->host.gs);
+	svm->host.ldt = kvm_read_ldt();
+
 	for (i = 0; i < NR_HOST_SAVE_USER_MSRS; i++)
 		rdmsrl(host_save_user_msrs[i], svm->host_user_msrs[i]);
 }
@@ -1002,6 +1147,14 @@ static void svm_vcpu_put(struct kvm_vcpu
 	int i;
 
 	++vcpu->stat.host_state_reload;
+	kvm_load_ldt(svm->host.ldt);
+#ifdef CONFIG_X86_64
+	loadsegment(fs, svm->host.fs);
+	wrmsrl(MSR_KERNEL_GS_BASE, current->thread.gs);
+	load_gs_index(svm->host.gs);
+#else
+	loadsegment(gs, svm->host.gs);
+#endif
 	for (i = 0; i < NR_HOST_SAVE_USER_MSRS; i++)
 		wrmsrl(host_save_user_msrs[i], svm->host_user_msrs[i]);
 }
@@ -1021,7 +1174,7 @@ static void svm_cache_reg(struct kvm_vcp
 	switch (reg) {
 	case VCPU_EXREG_PDPTR:
 		BUG_ON(!npt_enabled);
-		load_pdptrs(vcpu, vcpu->arch.walk_mmu, vcpu->arch.cr3);
+		load_pdptrs(vcpu, vcpu->arch.walk_mmu, kvm_read_cr3(vcpu));
 		break;
 	default:
 		BUG();
@@ -1030,12 +1183,12 @@ static void svm_cache_reg(struct kvm_vcp
 
 static void svm_set_vintr(struct vcpu_svm *svm)
 {
-	svm->vmcb->control.intercept |= 1ULL << INTERCEPT_VINTR;
+	set_intercept(svm, INTERCEPT_VINTR);
 }
 
 static void svm_clear_vintr(struct vcpu_svm *svm)
 {
-	svm->vmcb->control.intercept &= ~(1ULL << INTERCEPT_VINTR);
+	clr_intercept(svm, INTERCEPT_VINTR);
 }
 
 static struct vmcb_seg *svm_seg(struct kvm_vcpu *vcpu, int seg)
@@ -1150,6 +1303,7 @@ static void svm_set_idt(struct kvm_vcpu
 
 	svm->vmcb->save.idtr.limit = dt->size;
 	svm->vmcb->save.idtr.base = dt->address ;
+	mark_dirty(svm->vmcb, VMCB_DT);
 }
 
 static void svm_get_gdt(struct kvm_vcpu *vcpu, struct desc_ptr *dt)
@@ -1166,19 +1320,23 @@ static void svm_set_gdt(struct kvm_vcpu
 
 	svm->vmcb->save.gdtr.limit = dt->size;
 	svm->vmcb->save.gdtr.base = dt->address ;
+	mark_dirty(svm->vmcb, VMCB_DT);
 }
 
 static void svm_decache_cr0_guest_bits(struct kvm_vcpu *vcpu)
 {
 }
 
+static void svm_decache_cr3(struct kvm_vcpu *vcpu)
+{
+}
+
 static void svm_decache_cr4_guest_bits(struct kvm_vcpu *vcpu)
 {
 }
 
 static void update_cr0_intercept(struct vcpu_svm *svm)
 {
-	struct vmcb *vmcb = svm->vmcb;
 	ulong gcr0 = svm->vcpu.arch.cr0;
 	u64 *hcr0 = &svm->vmcb->save.cr0;
 
@@ -1188,27 +1346,14 @@ static void update_cr0_intercept(struct
 		*hcr0 = (*hcr0 & ~SVM_CR0_SELECTIVE_MASK)
 			| (gcr0 & SVM_CR0_SELECTIVE_MASK);
 
+	mark_dirty(svm->vmcb, VMCB_CR);
 
 	if (gcr0 == *hcr0 && svm->vcpu.fpu_active) {
-		vmcb->control.intercept_cr_read &= ~INTERCEPT_CR0_MASK;
-		vmcb->control.intercept_cr_write &= ~INTERCEPT_CR0_MASK;
-		if (is_nested(svm)) {
-			struct vmcb *hsave = svm->nested.hsave;
-
-			hsave->control.intercept_cr_read  &= ~INTERCEPT_CR0_MASK;
-			hsave->control.intercept_cr_write &= ~INTERCEPT_CR0_MASK;
-			vmcb->control.intercept_cr_read  |= svm->nested.intercept_cr_read;
-			vmcb->control.intercept_cr_write |= svm->nested.intercept_cr_write;
-		}
+		clr_cr_intercept(svm, INTERCEPT_CR0_READ);
+		clr_cr_intercept(svm, INTERCEPT_CR0_WRITE);
 	} else {
-		svm->vmcb->control.intercept_cr_read |= INTERCEPT_CR0_MASK;
-		svm->vmcb->control.intercept_cr_write |= INTERCEPT_CR0_MASK;
-		if (is_nested(svm)) {
-			struct vmcb *hsave = svm->nested.hsave;
-
-			hsave->control.intercept_cr_read |= INTERCEPT_CR0_MASK;
-			hsave->control.intercept_cr_write |= INTERCEPT_CR0_MASK;
-		}
+		set_cr_intercept(svm, INTERCEPT_CR0_READ);
+		set_cr_intercept(svm, INTERCEPT_CR0_WRITE);
 	}
 }
 
@@ -1216,7 +1361,7 @@ static void svm_set_cr0(struct kvm_vcpu
 {
 	struct vcpu_svm *svm = to_svm(vcpu);
 
-	if (is_nested(svm)) {
+	if (is_guest_mode(vcpu)) {
 		/*
 		 * We are here because we run in nested mode, the host kvm
 		 * intercepts cr0 writes but the l1 hypervisor does not.
@@ -1268,6 +1413,7 @@ static void svm_set_cr0(struct kvm_vcpu
 	 */
 	cr0 &= ~(X86_CR0_CD | X86_CR0_NW);
 	svm->vmcb->save.cr0 = cr0;
+	mark_dirty(svm->vmcb, VMCB_CR);
 	update_cr0_intercept(svm);
 }
 
@@ -1277,13 +1423,14 @@ static void svm_set_cr4(struct kvm_vcpu
 	unsigned long old_cr4 = to_svm(vcpu)->vmcb->save.cr4;
 
 	if (npt_enabled && ((old_cr4 ^ cr4) & X86_CR4_PGE))
-		force_new_asid(vcpu);
+		svm_flush_tlb(vcpu);
 
 	vcpu->arch.cr4 = cr4;
 	if (!npt_enabled)
 		cr4 |= X86_CR4_PAE;
 	cr4 |= host_cr4_mce;
 	to_svm(vcpu)->vmcb->save.cr4 = cr4;
+	mark_dirty(to_svm(vcpu)->vmcb, VMCB_CR);
 }
 
 static void svm_set_segment(struct kvm_vcpu *vcpu,
@@ -1312,26 +1459,25 @@ static void svm_set_segment(struct kvm_v
 			= (svm->vmcb->save.cs.attrib
 			   >> SVM_SELECTOR_DPL_SHIFT) & 3;
 
+	mark_dirty(svm->vmcb, VMCB_SEG);
 }
 
 static void update_db_intercept(struct kvm_vcpu *vcpu)
 {
 	struct vcpu_svm *svm = to_svm(vcpu);
 
-	svm->vmcb->control.intercept_exceptions &=
-		~((1 << DB_VECTOR) | (1 << BP_VECTOR));
+	clr_exception_intercept(svm, DB_VECTOR);
+	clr_exception_intercept(svm, BP_VECTOR);
 
 	if (svm->nmi_singlestep)
-		svm->vmcb->control.intercept_exceptions |= (1 << DB_VECTOR);
+		set_exception_intercept(svm, DB_VECTOR);
 
 	if (vcpu->guest_debug & KVM_GUESTDBG_ENABLE) {
 		if (vcpu->guest_debug &
 		    (KVM_GUESTDBG_SINGLESTEP | KVM_GUESTDBG_USE_HW_BP))
-			svm->vmcb->control.intercept_exceptions |=
-				1 << DB_VECTOR;
+			set_exception_intercept(svm, DB_VECTOR);
 		if (vcpu->guest_debug & KVM_GUESTDBG_USE_SW_BP)
-			svm->vmcb->control.intercept_exceptions |=
-				1 << BP_VECTOR;
+			set_exception_intercept(svm, BP_VECTOR);
 	} else
 		vcpu->guest_debug = 0;
 }
@@ -1345,21 +1491,9 @@ static void svm_guest_debug(struct kvm_v
 	else
 		svm->vmcb->save.dr7 = vcpu->arch.dr7;
 
-	update_db_intercept(vcpu);
-}
-
-static void load_host_msrs(struct kvm_vcpu *vcpu)
-{
-#ifdef CONFIG_X86_64
-	wrmsrl(MSR_GS_BASE, to_svm(vcpu)->host_gs_base);
-#endif
-}
+	mark_dirty(svm->vmcb, VMCB_DR);
 
-static void save_host_msrs(struct kvm_vcpu *vcpu)
-{
-#ifdef CONFIG_X86_64
-	rdmsrl(MSR_GS_BASE, to_svm(vcpu)->host_gs_base);
-#endif
+	update_db_intercept(vcpu);
 }
 
 static void new_asid(struct vcpu_svm *svm, struct svm_cpu_data *sd)
@@ -1372,6 +1506,8 @@ static void new_asid(struct vcpu_svm *sv
 
 	svm->asid_generation = sd->asid_generation;
 	svm->vmcb->control.asid = sd->next_asid++;
+
+	mark_dirty(svm->vmcb, VMCB_ASID);
 }
 
 static void svm_set_dr7(struct kvm_vcpu *vcpu, unsigned long value)
@@ -1379,20 +1515,40 @@ static void svm_set_dr7(struct kvm_vcpu
 	struct vcpu_svm *svm = to_svm(vcpu);
 
 	svm->vmcb->save.dr7 = value;
+	mark_dirty(svm->vmcb, VMCB_DR);
 }
 
 static int pf_interception(struct vcpu_svm *svm)
 {
-	u64 fault_address;
+	u64 fault_address = svm->vmcb->control.exit_info_2;
 	u32 error_code;
+	int r = 1;
 
-	fault_address  = svm->vmcb->control.exit_info_2;
-	error_code = svm->vmcb->control.exit_info_1;
+	switch (svm->apf_reason) {
+	default:
+		error_code = svm->vmcb->control.exit_info_1;
 
-	trace_kvm_page_fault(fault_address, error_code);
-	if (!npt_enabled && kvm_event_needs_reinjection(&svm->vcpu))
-		kvm_mmu_unprotect_page_virt(&svm->vcpu, fault_address);
-	return kvm_mmu_page_fault(&svm->vcpu, fault_address, error_code);
+		trace_kvm_page_fault(fault_address, error_code);
+		if (!npt_enabled && kvm_event_needs_reinjection(&svm->vcpu))
+			kvm_mmu_unprotect_page_virt(&svm->vcpu, fault_address);
+		r = kvm_mmu_page_fault(&svm->vcpu, fault_address, error_code,
+			svm->vmcb->control.insn_bytes,
+			svm->vmcb->control.insn_len);
+		break;
+	case KVM_PV_REASON_PAGE_NOT_PRESENT:
+		svm->apf_reason = 0;
+		local_irq_disable();
+		kvm_async_pf_task_wait(fault_address);
+		local_irq_enable();
+		break;
+	case KVM_PV_REASON_PAGE_READY:
+		svm->apf_reason = 0;
+		local_irq_disable();
+		kvm_async_pf_task_wake(fault_address);
+		local_irq_enable();
+		break;
+	}
+	return r;
 }
 
 static int db_interception(struct vcpu_svm *svm)
@@ -1440,7 +1596,7 @@ static int ud_interception(struct vcpu_s
 {
 	int er;
 
-	er = emulate_instruction(&svm->vcpu, 0, 0, EMULTYPE_TRAP_UD);
+	er = emulate_instruction(&svm->vcpu, EMULTYPE_TRAP_UD);
 	if (er != EMULATE_DONE)
 		kvm_queue_exception(&svm->vcpu, UD_VECTOR);
 	return 1;
@@ -1449,21 +1605,8 @@ static int ud_interception(struct vcpu_s
 static void svm_fpu_activate(struct kvm_vcpu *vcpu)
 {
 	struct vcpu_svm *svm = to_svm(vcpu);
-	u32 excp;
-
-	if (is_nested(svm)) {
-		u32 h_excp, n_excp;
 
-		h_excp  = svm->nested.hsave->control.intercept_exceptions;
-		n_excp  = svm->nested.intercept_exceptions;
-		h_excp &= ~(1 << NM_VECTOR);
-		excp    = h_excp | n_excp;
-	} else {
-		excp  = svm->vmcb->control.intercept_exceptions;
-		excp &= ~(1 << NM_VECTOR);
-	}
-
-	svm->vmcb->control.intercept_exceptions = excp;
+	clr_exception_intercept(svm, NM_VECTOR);
 
 	svm->vcpu.fpu_active = 1;
 	update_cr0_intercept(svm);
@@ -1570,7 +1713,7 @@ static int io_interception(struct vcpu_s
 	string = (io_info & SVM_IOIO_STR_MASK) != 0;
 	in = (io_info & SVM_IOIO_TYPE_MASK) != 0;
 	if (string || in)
-		return emulate_instruction(vcpu, 0, 0, 0) == EMULATE_DONE;
+		return emulate_instruction(vcpu, 0) == EMULATE_DONE;
 
 	port = io_info >> 16;
 	size = (io_info & SVM_IOIO_SIZE_MASK) >> SVM_IOIO_SIZE_SHIFT;
@@ -1624,17 +1767,19 @@ static void nested_svm_set_tdp_cr3(struc
 	struct vcpu_svm *svm = to_svm(vcpu);
 
 	svm->vmcb->control.nested_cr3 = root;
-	force_new_asid(vcpu);
+	mark_dirty(svm->vmcb, VMCB_NPT);
+	svm_flush_tlb(vcpu);
 }
 
-static void nested_svm_inject_npf_exit(struct kvm_vcpu *vcpu)
+static void nested_svm_inject_npf_exit(struct kvm_vcpu *vcpu,
+				       struct x86_exception *fault)
 {
 	struct vcpu_svm *svm = to_svm(vcpu);
 
 	svm->vmcb->control.exit_code = SVM_EXIT_NPF;
 	svm->vmcb->control.exit_code_hi = 0;
-	svm->vmcb->control.exit_info_1 = vcpu->arch.fault.error_code;
-	svm->vmcb->control.exit_info_2 = vcpu->arch.fault.address;
+	svm->vmcb->control.exit_info_1 = fault->error_code;
+	svm->vmcb->control.exit_info_2 = fault->address;
 
 	nested_svm_vmexit(svm);
 }
@@ -1680,7 +1825,7 @@ static int nested_svm_check_exception(st
 {
 	int vmexit;
 
-	if (!is_nested(svm))
+	if (!is_guest_mode(&svm->vcpu))
 		return 0;
 
 	svm->vmcb->control.exit_code = SVM_EXIT_EXCP_BASE + nr;
@@ -1698,7 +1843,7 @@ static int nested_svm_check_exception(st
 /* This function returns true if it is save to enable the irq window */
 static inline bool nested_svm_intr(struct vcpu_svm *svm)
 {
-	if (!is_nested(svm))
+	if (!is_guest_mode(&svm->vcpu))
 		return true;
 
 	if (!(svm->vcpu.arch.hflags & HF_VINTR_MASK))
@@ -1737,7 +1882,7 @@ static inline bool nested_svm_intr(struc
 /* This function returns true if it is save to enable the nmi window */
 static inline bool nested_svm_nmi(struct vcpu_svm *svm)
 {
-	if (!is_nested(svm))
+	if (!is_guest_mode(&svm->vcpu))
 		return true;
 
 	if (!(svm->nested.intercept & (1ULL << INTERCEPT_NMI)))
@@ -1836,8 +1981,8 @@ static int nested_svm_exit_special(struc
 			return NESTED_EXIT_HOST;
 		break;
 	case SVM_EXIT_EXCP_BASE + PF_VECTOR:
-		/* When we're shadowing, trap PFs */
-		if (!npt_enabled)
+		/* When we're shadowing, trap PFs, but not async PF */
+		if (!npt_enabled && svm->apf_reason == 0)
 			return NESTED_EXIT_HOST;
 		break;
 	case SVM_EXIT_EXCP_BASE + NM_VECTOR:
@@ -1865,27 +2010,15 @@ static int nested_svm_intercept(struct v
 	case SVM_EXIT_IOIO:
 		vmexit = nested_svm_intercept_ioio(svm);
 		break;
-	case SVM_EXIT_READ_CR0 ... SVM_EXIT_READ_CR8: {
-		u32 cr_bits = 1 << (exit_code - SVM_EXIT_READ_CR0);
-		if (svm->nested.intercept_cr_read & cr_bits)
-			vmexit = NESTED_EXIT_DONE;
-		break;
-	}
-	case SVM_EXIT_WRITE_CR0 ... SVM_EXIT_WRITE_CR8: {
-		u32 cr_bits = 1 << (exit_code - SVM_EXIT_WRITE_CR0);
-		if (svm->nested.intercept_cr_write & cr_bits)
-			vmexit = NESTED_EXIT_DONE;
-		break;
-	}
-	case SVM_EXIT_READ_DR0 ... SVM_EXIT_READ_DR7: {
-		u32 dr_bits = 1 << (exit_code - SVM_EXIT_READ_DR0);
-		if (svm->nested.intercept_dr_read & dr_bits)
+	case SVM_EXIT_READ_CR0 ... SVM_EXIT_WRITE_CR8: {
+		u32 bit = 1U << (exit_code - SVM_EXIT_READ_CR0);
+		if (svm->nested.intercept_cr & bit)
 			vmexit = NESTED_EXIT_DONE;
 		break;
 	}
-	case SVM_EXIT_WRITE_DR0 ... SVM_EXIT_WRITE_DR7: {
-		u32 dr_bits = 1 << (exit_code - SVM_EXIT_WRITE_DR0);
-		if (svm->nested.intercept_dr_write & dr_bits)
+	case SVM_EXIT_READ_DR0 ... SVM_EXIT_WRITE_DR7: {
+		u32 bit = 1U << (exit_code - SVM_EXIT_READ_DR0);
+		if (svm->nested.intercept_dr & bit)
 			vmexit = NESTED_EXIT_DONE;
 		break;
 	}
@@ -1893,6 +2026,10 @@ static int nested_svm_intercept(struct v
 		u32 excp_bits = 1 << (exit_code - SVM_EXIT_EXCP_BASE);
 		if (svm->nested.intercept_exceptions & excp_bits)
 			vmexit = NESTED_EXIT_DONE;
+		/* async page fault always cause vmexit */
+		else if ((exit_code == SVM_EXIT_EXCP_BASE + PF_VECTOR) &&
+			 svm->apf_reason != 0)
+			vmexit = NESTED_EXIT_DONE;
 		break;
 	}
 	case SVM_EXIT_ERR: {
@@ -1926,10 +2063,8 @@ static inline void copy_vmcb_control_are
 	struct vmcb_control_area *dst  = &dst_vmcb->control;
 	struct vmcb_control_area *from = &from_vmcb->control;
 
-	dst->intercept_cr_read    = from->intercept_cr_read;
-	dst->intercept_cr_write   = from->intercept_cr_write;
-	dst->intercept_dr_read    = from->intercept_dr_read;
-	dst->intercept_dr_write   = from->intercept_dr_write;
+	dst->intercept_cr         = from->intercept_cr;
+	dst->intercept_dr         = from->intercept_dr;
 	dst->intercept_exceptions = from->intercept_exceptions;
 	dst->intercept            = from->intercept;
 	dst->iopm_base_pa         = from->iopm_base_pa;
@@ -1970,7 +2105,8 @@ static int nested_svm_vmexit(struct vcpu
 	if (!nested_vmcb)
 		return 1;
 
-	/* Exit nested SVM mode */
+	/* Exit Guest-Mode */
+	leave_guest_mode(&svm->vcpu);
 	svm->nested.vmcb = 0;
 
 	/* Give the current vmcb to the guest */
@@ -1984,7 +2120,7 @@ static int nested_svm_vmexit(struct vcpu
 	nested_vmcb->save.idtr   = vmcb->save.idtr;
 	nested_vmcb->save.efer   = svm->vcpu.arch.efer;
 	nested_vmcb->save.cr0    = kvm_read_cr0(&svm->vcpu);
-	nested_vmcb->save.cr3    = svm->vcpu.arch.cr3;
+	nested_vmcb->save.cr3    = kvm_read_cr3(&svm->vcpu);
 	nested_vmcb->save.cr2    = vmcb->save.cr2;
 	nested_vmcb->save.cr4    = svm->vcpu.arch.cr4;
 	nested_vmcb->save.rflags = vmcb->save.rflags;
@@ -2061,6 +2197,8 @@ static int nested_svm_vmexit(struct vcpu
 	svm->vmcb->save.cpl = 0;
 	svm->vmcb->control.exit_int_info = 0;
 
+	mark_all_dirty(svm->vmcb);
+
 	nested_svm_unmap(page);
 
 	nested_svm_uninit_mmu_context(&svm->vcpu);
@@ -2148,8 +2286,8 @@ static bool nested_svm_vmrun(struct vcpu
 			       nested_vmcb->control.event_inj,
 			       nested_vmcb->control.nested_ctl);
 
-	trace_kvm_nested_intercepts(nested_vmcb->control.intercept_cr_read,
-				    nested_vmcb->control.intercept_cr_write,
+	trace_kvm_nested_intercepts(nested_vmcb->control.intercept_cr & 0xffff,
+				    nested_vmcb->control.intercept_cr >> 16,
 				    nested_vmcb->control.intercept_exceptions,
 				    nested_vmcb->control.intercept);
 
@@ -2177,7 +2315,7 @@ static bool nested_svm_vmrun(struct vcpu
 	if (npt_enabled)
 		hsave->save.cr3    = vmcb->save.cr3;
 	else
-		hsave->save.cr3    = svm->vcpu.arch.cr3;
+		hsave->save.cr3    = kvm_read_cr3(&svm->vcpu);
 
 	copy_vmcb_control_area(hsave, vmcb);
 
@@ -2229,14 +2367,12 @@ static bool nested_svm_vmrun(struct vcpu
 	svm->nested.vmcb_iopm  = nested_vmcb->control.iopm_base_pa  & ~0x0fffULL;
 
 	/* cache intercepts */
-	svm->nested.intercept_cr_read    = nested_vmcb->control.intercept_cr_read;
-	svm->nested.intercept_cr_write   = nested_vmcb->control.intercept_cr_write;
-	svm->nested.intercept_dr_read    = nested_vmcb->control.intercept_dr_read;
-	svm->nested.intercept_dr_write   = nested_vmcb->control.intercept_dr_write;
+	svm->nested.intercept_cr         = nested_vmcb->control.intercept_cr;
+	svm->nested.intercept_dr         = nested_vmcb->control.intercept_dr;
 	svm->nested.intercept_exceptions = nested_vmcb->control.intercept_exceptions;
 	svm->nested.intercept            = nested_vmcb->control.intercept;
 
-	force_new_asid(&svm->vcpu);
+	svm_flush_tlb(&svm->vcpu);
 	svm->vmcb->control.int_ctl = nested_vmcb->control.int_ctl | V_INTR_MASKING_MASK;
 	if (nested_vmcb->control.int_ctl & V_INTR_MASKING_MASK)
 		svm->vcpu.arch.hflags |= HF_VINTR_MASK;
@@ -2245,29 +2381,12 @@ static bool nested_svm_vmrun(struct vcpu
 
 	if (svm->vcpu.arch.hflags & HF_VINTR_MASK) {
 		/* We only want the cr8 intercept bits of the guest */
-		svm->vmcb->control.intercept_cr_read &= ~INTERCEPT_CR8_MASK;
-		svm->vmcb->control.intercept_cr_write &= ~INTERCEPT_CR8_MASK;
+		clr_cr_intercept(svm, INTERCEPT_CR8_READ);
+		clr_cr_intercept(svm, INTERCEPT_CR8_WRITE);
 	}
 
 	/* We don't want to see VMMCALLs from a nested guest */
-	svm->vmcb->control.intercept &= ~(1ULL << INTERCEPT_VMMCALL);
-
-	/*
-	 * We don't want a nested guest to be more powerful than the guest, so
-	 * all intercepts are ORed
-	 */
-	svm->vmcb->control.intercept_cr_read |=
-		nested_vmcb->control.intercept_cr_read;
-	svm->vmcb->control.intercept_cr_write |=
-		nested_vmcb->control.intercept_cr_write;
-	svm->vmcb->control.intercept_dr_read |=
-		nested_vmcb->control.intercept_dr_read;
-	svm->vmcb->control.intercept_dr_write |=
-		nested_vmcb->control.intercept_dr_write;
-	svm->vmcb->control.intercept_exceptions |=
-		nested_vmcb->control.intercept_exceptions;
-
-	svm->vmcb->control.intercept |= nested_vmcb->control.intercept;
+	clr_intercept(svm, INTERCEPT_VMMCALL);
 
 	svm->vmcb->control.lbr_ctl = nested_vmcb->control.lbr_ctl;
 	svm->vmcb->control.int_vector = nested_vmcb->control.int_vector;
@@ -2278,11 +2397,21 @@ static bool nested_svm_vmrun(struct vcpu
 
 	nested_svm_unmap(page);
 
-	/* nested_vmcb is our indicator if nested SVM is activated */
+	/* Enter Guest-Mode */
+	enter_guest_mode(&svm->vcpu);
+
+	/*
+	 * Merge guest and host intercepts - must be called  with vcpu in
+	 * guest-mode to take affect here
+	 */
+	recalc_intercepts(svm);
+
 	svm->nested.vmcb = vmcb_gpa;
 
 	enable_gif(svm);
 
+	mark_all_dirty(svm->vmcb);
+
 	return true;
 }
 
@@ -2400,6 +2529,8 @@ static int clgi_interception(struct vcpu
 	svm_clear_vintr(svm);
 	svm->vmcb->control.int_ctl &= ~V_IRQ_MASK;
 
+	mark_dirty(svm->vmcb, VMCB_INTR);
+
 	return 1;
 }
 
@@ -2426,6 +2557,19 @@ static int skinit_interception(struct vc
 	return 1;
 }
 
+static int xsetbv_interception(struct vcpu_svm *svm)
+{
+	u64 new_bv = kvm_read_edx_eax(&svm->vcpu);
+	u32 index = kvm_register_read(&svm->vcpu, VCPU_REGS_RCX);
+
+	if (kvm_set_xcr(&svm->vcpu, index, new_bv) == 0) {
+		svm->next_rip = kvm_rip_read(&svm->vcpu) + 3;
+		skip_emulated_instruction(&svm->vcpu);
+	}
+
+	return 1;
+}
+
 static int invalid_op_interception(struct vcpu_svm *svm)
 {
 	kvm_queue_exception(&svm->vcpu, UD_VECTOR);
@@ -2507,19 +2651,92 @@ static int cpuid_interception(struct vcp
 static int iret_interception(struct vcpu_svm *svm)
 {
 	++svm->vcpu.stat.nmi_window_exits;
-	svm->vmcb->control.intercept &= ~(1ULL << INTERCEPT_IRET);
+	clr_intercept(svm, INTERCEPT_IRET);
 	svm->vcpu.arch.hflags |= HF_IRET_MASK;
 	return 1;
 }
 
 static int invlpg_interception(struct vcpu_svm *svm)
 {
-	return emulate_instruction(&svm->vcpu, 0, 0, 0) == EMULATE_DONE;
+	if (!static_cpu_has(X86_FEATURE_DECODEASSISTS))
+		return emulate_instruction(&svm->vcpu, 0) == EMULATE_DONE;
+
+	kvm_mmu_invlpg(&svm->vcpu, svm->vmcb->control.exit_info_1);
+	skip_emulated_instruction(&svm->vcpu);
+	return 1;
 }
 
 static int emulate_on_interception(struct vcpu_svm *svm)
 {
-	return emulate_instruction(&svm->vcpu, 0, 0, 0) == EMULATE_DONE;
+	return emulate_instruction(&svm->vcpu, 0) == EMULATE_DONE;
+}
+
+#define CR_VALID (1ULL << 63)
+
+static int cr_interception(struct vcpu_svm *svm)
+{
+	int reg, cr;
+	unsigned long val;
+	int err;
+
+	if (!static_cpu_has(X86_FEATURE_DECODEASSISTS))
+		return emulate_on_interception(svm);
+
+	if (unlikely((svm->vmcb->control.exit_info_1 & CR_VALID) == 0))
+		return emulate_on_interception(svm);
+
+	reg = svm->vmcb->control.exit_info_1 & SVM_EXITINFO_REG_MASK;
+	cr = svm->vmcb->control.exit_code - SVM_EXIT_READ_CR0;
+
+	err = 0;
+	if (cr >= 16) { /* mov to cr */
+		cr -= 16;
+		val = kvm_register_read(&svm->vcpu, reg);
+		switch (cr) {
+		case 0:
+			err = kvm_set_cr0(&svm->vcpu, val);
+			break;
+		case 3:
+			err = kvm_set_cr3(&svm->vcpu, val);
+			break;
+		case 4:
+			err = kvm_set_cr4(&svm->vcpu, val);
+			break;
+		case 8:
+			err = kvm_set_cr8(&svm->vcpu, val);
+			break;
+		default:
+			WARN(1, "unhandled write to CR%d", cr);
+			kvm_queue_exception(&svm->vcpu, UD_VECTOR);
+			return 1;
+		}
+	} else { /* mov from cr */
+		switch (cr) {
+		case 0:
+			val = kvm_read_cr0(&svm->vcpu);
+			break;
+		case 2:
+			val = svm->vcpu.arch.cr2;
+			break;
+		case 3:
+			val = kvm_read_cr3(&svm->vcpu);
+			break;
+		case 4:
+			val = kvm_read_cr4(&svm->vcpu);
+			break;
+		case 8:
+			val = kvm_get_cr8(&svm->vcpu);
+			break;
+		default:
+			WARN(1, "unhandled read from CR%d", cr);
+			kvm_queue_exception(&svm->vcpu, UD_VECTOR);
+			return 1;
+		}
+		kvm_register_write(&svm->vcpu, reg, val);
+	}
+	kvm_complete_insn_gp(&svm->vcpu, err);
+
+	return 1;
 }
 
 static int cr0_write_interception(struct vcpu_svm *svm)
@@ -2527,7 +2744,7 @@ static int cr0_write_interception(struct
 	struct kvm_vcpu *vcpu = &svm->vcpu;
 	int r;
 
-	r = emulate_instruction(&svm->vcpu, 0, 0, 0);
+	r = cr_interception(svm);
 
 	if (svm->nested.vmexit_rip) {
 		kvm_register_write(vcpu, VCPU_REGS_RIP, svm->nested.vmexit_rip);
@@ -2536,22 +2753,49 @@ static int cr0_write_interception(struct
 		svm->nested.vmexit_rip = 0;
 	}
 
-	return r == EMULATE_DONE;
+	return r;
+}
+
+static int dr_interception(struct vcpu_svm *svm)
+{
+	int reg, dr;
+	unsigned long val;
+	int err;
+
+	if (!boot_cpu_has(X86_FEATURE_DECODEASSISTS))
+		return emulate_on_interception(svm);
+
+	reg = svm->vmcb->control.exit_info_1 & SVM_EXITINFO_REG_MASK;
+	dr = svm->vmcb->control.exit_code - SVM_EXIT_READ_DR0;
+
+	if (dr >= 16) { /* mov to DRn */
+		val = kvm_register_read(&svm->vcpu, reg);
+		kvm_set_dr(&svm->vcpu, dr - 16, val);
+	} else {
+		err = kvm_get_dr(&svm->vcpu, dr, &val);
+		if (!err)
+			kvm_register_write(&svm->vcpu, reg, val);
+	}
+
+	skip_emulated_instruction(&svm->vcpu);
+
+	return 1;
 }
 
 static int cr8_write_interception(struct vcpu_svm *svm)
 {
 	struct kvm_run *kvm_run = svm->vcpu.run;
+	int r;
 
 	u8 cr8_prev = kvm_get_cr8(&svm->vcpu);
 	/* instruction emulation calls kvm_set_cr8() */
-	emulate_instruction(&svm->vcpu, 0, 0, 0);
+	r = cr_interception(svm);
 	if (irqchip_in_kernel(svm->vcpu.kvm)) {
-		svm->vmcb->control.intercept_cr_write &= ~INTERCEPT_CR8_MASK;
-		return 1;
+		clr_cr_intercept(svm, INTERCEPT_CR8_WRITE);
+		return r;
 	}
 	if (cr8_prev <= kvm_get_cr8(&svm->vcpu))
-		return 1;
+		return r;
 	kvm_run->exit_reason = KVM_EXIT_SET_TPR;
 	return 0;
 }
@@ -2562,14 +2806,9 @@ static int svm_get_msr(struct kvm_vcpu *
 
 	switch (ecx) {
 	case MSR_IA32_TSC: {
-		u64 tsc_offset;
-
-		if (is_nested(svm))
-			tsc_offset = svm->nested.hsave->control.tsc_offset;
-		else
-			tsc_offset = svm->vmcb->control.tsc_offset;
+		struct vmcb *vmcb = get_host_vmcb(svm);
 
-		*data = tsc_offset + native_read_tsc();
+		*data = vmcb->control.tsc_offset + native_read_tsc();
 		break;
 	}
 	case MSR_STAR:
@@ -2714,7 +2953,7 @@ static int svm_set_msr(struct kvm_vcpu *
 		svm->vmcb->save.sysenter_esp = data;
 		break;
 	case MSR_IA32_DEBUGCTLMSR:
-		if (!svm_has(SVM_FEATURE_LBRV)) {
+		if (!boot_cpu_has(X86_FEATURE_LBRV)) {
 			pr_unimpl(vcpu, "%s: MSR_IA32_DEBUGCTL 0x%llx, nop\n",
 					__func__, data);
 			break;
@@ -2723,6 +2962,7 @@ static int svm_set_msr(struct kvm_vcpu *
 			return 1;
 
 		svm->vmcb->save.dbgctl = data;
+		mark_dirty(svm->vmcb, VMCB_LBR);
 		if (data & (1ULL<<0))
 			svm_enable_lbrv(svm);
 		else
@@ -2775,6 +3015,7 @@ static int interrupt_window_interception
 	kvm_make_request(KVM_REQ_EVENT, &svm->vcpu);
 	svm_clear_vintr(svm);
 	svm->vmcb->control.int_ctl &= ~V_IRQ_MASK;
+	mark_dirty(svm->vmcb, VMCB_INTR);
 	/*
 	 * If the user space waits to inject interrupts, exit as soon as
 	 * possible
@@ -2797,31 +3038,31 @@ static int pause_interception(struct vcp
 }
 
 static int (*svm_exit_handlers[])(struct vcpu_svm *svm) = {
-	[SVM_EXIT_READ_CR0]			= emulate_on_interception,
-	[SVM_EXIT_READ_CR3]			= emulate_on_interception,
-	[SVM_EXIT_READ_CR4]			= emulate_on_interception,
-	[SVM_EXIT_READ_CR8]			= emulate_on_interception,
+	[SVM_EXIT_READ_CR0]			= cr_interception,
+	[SVM_EXIT_READ_CR3]			= cr_interception,
+	[SVM_EXIT_READ_CR4]			= cr_interception,
+	[SVM_EXIT_READ_CR8]			= cr_interception,
 	[SVM_EXIT_CR0_SEL_WRITE]		= emulate_on_interception,
 	[SVM_EXIT_WRITE_CR0]			= cr0_write_interception,
-	[SVM_EXIT_WRITE_CR3]			= emulate_on_interception,
-	[SVM_EXIT_WRITE_CR4]			= emulate_on_interception,
+	[SVM_EXIT_WRITE_CR3]			= cr_interception,
+	[SVM_EXIT_WRITE_CR4]			= cr_interception,
 	[SVM_EXIT_WRITE_CR8]			= cr8_write_interception,
-	[SVM_EXIT_READ_DR0]			= emulate_on_interception,
-	[SVM_EXIT_READ_DR1]			= emulate_on_interception,
-	[SVM_EXIT_READ_DR2]			= emulate_on_interception,
-	[SVM_EXIT_READ_DR3]			= emulate_on_interception,
-	[SVM_EXIT_READ_DR4]			= emulate_on_interception,
-	[SVM_EXIT_READ_DR5]			= emulate_on_interception,
-	[SVM_EXIT_READ_DR6]			= emulate_on_interception,
-	[SVM_EXIT_READ_DR7]			= emulate_on_interception,
-	[SVM_EXIT_WRITE_DR0]			= emulate_on_interception,
-	[SVM_EXIT_WRITE_DR1]			= emulate_on_interception,
-	[SVM_EXIT_WRITE_DR2]			= emulate_on_interception,
-	[SVM_EXIT_WRITE_DR3]			= emulate_on_interception,
-	[SVM_EXIT_WRITE_DR4]			= emulate_on_interception,
-	[SVM_EXIT_WRITE_DR5]			= emulate_on_interception,
-	[SVM_EXIT_WRITE_DR6]			= emulate_on_interception,
-	[SVM_EXIT_WRITE_DR7]			= emulate_on_interception,
+	[SVM_EXIT_READ_DR0]			= dr_interception,
+	[SVM_EXIT_READ_DR1]			= dr_interception,
+	[SVM_EXIT_READ_DR2]			= dr_interception,
+	[SVM_EXIT_READ_DR3]			= dr_interception,
+	[SVM_EXIT_READ_DR4]			= dr_interception,
+	[SVM_EXIT_READ_DR5]			= dr_interception,
+	[SVM_EXIT_READ_DR6]			= dr_interception,
+	[SVM_EXIT_READ_DR7]			= dr_interception,
+	[SVM_EXIT_WRITE_DR0]			= dr_interception,
+	[SVM_EXIT_WRITE_DR1]			= dr_interception,
+	[SVM_EXIT_WRITE_DR2]			= dr_interception,
+	[SVM_EXIT_WRITE_DR3]			= dr_interception,
+	[SVM_EXIT_WRITE_DR4]			= dr_interception,
+	[SVM_EXIT_WRITE_DR5]			= dr_interception,
+	[SVM_EXIT_WRITE_DR6]			= dr_interception,
+	[SVM_EXIT_WRITE_DR7]			= dr_interception,
 	[SVM_EXIT_EXCP_BASE + DB_VECTOR]	= db_interception,
 	[SVM_EXIT_EXCP_BASE + BP_VECTOR]	= bp_interception,
 	[SVM_EXIT_EXCP_BASE + UD_VECTOR]	= ud_interception,
@@ -2854,6 +3095,7 @@ static int (*svm_exit_handlers[])(struct
 	[SVM_EXIT_WBINVD]                       = emulate_on_interception,
 	[SVM_EXIT_MONITOR]			= invalid_op_interception,
 	[SVM_EXIT_MWAIT]			= invalid_op_interception,
+	[SVM_EXIT_XSETBV]			= xsetbv_interception,
 	[SVM_EXIT_NPF]				= pf_interception,
 };
 
@@ -2864,10 +3106,10 @@ void dump_vmcb(struct kvm_vcpu *vcpu)
 	struct vmcb_save_area *save = &svm->vmcb->save;
 
 	pr_err("VMCB Control Area:\n");
-	pr_err("cr_read:            %04x\n", control->intercept_cr_read);
-	pr_err("cr_write:           %04x\n", control->intercept_cr_write);
-	pr_err("dr_read:            %04x\n", control->intercept_dr_read);
-	pr_err("dr_write:           %04x\n", control->intercept_dr_write);
+	pr_err("cr_read:            %04x\n", control->intercept_cr & 0xffff);
+	pr_err("cr_write:           %04x\n", control->intercept_cr >> 16);
+	pr_err("dr_read:            %04x\n", control->intercept_dr & 0xffff);
+	pr_err("dr_write:           %04x\n", control->intercept_dr >> 16);
 	pr_err("exceptions:         %08x\n", control->intercept_exceptions);
 	pr_err("intercepts:         %016llx\n", control->intercept);
 	pr_err("pause filter count: %d\n", control->pause_filter_count);
@@ -2950,15 +3192,23 @@ void dump_vmcb(struct kvm_vcpu *vcpu)
 
 }
 
+static void svm_get_exit_info(struct kvm_vcpu *vcpu, u64 *info1, u64 *info2)
+{
+	struct vmcb_control_area *control = &to_svm(vcpu)->vmcb->control;
+
+	*info1 = control->exit_info_1;
+	*info2 = control->exit_info_2;
+}
+
 static int handle_exit(struct kvm_vcpu *vcpu)
 {
 	struct vcpu_svm *svm = to_svm(vcpu);
 	struct kvm_run *kvm_run = vcpu->run;
 	u32 exit_code = svm->vmcb->control.exit_code;
 
-	trace_kvm_exit(exit_code, vcpu);
+	trace_kvm_exit(exit_code, vcpu, KVM_ISA_SVM);
 
-	if (!(svm->vmcb->control.intercept_cr_write & INTERCEPT_CR0_MASK))
+	if (!is_cr_intercept(svm, INTERCEPT_CR0_WRITE))
 		vcpu->arch.cr0 = svm->vmcb->save.cr0;
 	if (npt_enabled)
 		vcpu->arch.cr3 = svm->vmcb->save.cr3;
@@ -2970,7 +3220,7 @@ static int handle_exit(struct kvm_vcpu *
 		return 1;
 	}
 
-	if (is_nested(svm)) {
+	if (is_guest_mode(vcpu)) {
 		int vmexit;
 
 		trace_kvm_nested_vmexit(svm->vmcb->save.rip, exit_code,
@@ -3033,7 +3283,6 @@ static void pre_svm_run(struct vcpu_svm
 
 	struct svm_cpu_data *sd = per_cpu(svm_data, cpu);
 
-	svm->vmcb->control.tlb_ctl = TLB_CONTROL_DO_NOTHING;
 	/* FIXME: handle wraparound of asid_generation */
 	if (svm->asid_generation != sd->asid_generation)
 		new_asid(svm, sd);
@@ -3045,7 +3294,7 @@ static void svm_inject_nmi(struct kvm_vc
 
 	svm->vmcb->control.event_inj = SVM_EVTINJ_VALID | SVM_EVTINJ_TYPE_NMI;
 	vcpu->arch.hflags |= HF_NMI_MASK;
-	svm->vmcb->control.intercept |= (1ULL << INTERCEPT_IRET);
+	set_intercept(svm, INTERCEPT_IRET);
 	++vcpu->stat.nmi_injections;
 }
 
@@ -3058,6 +3307,7 @@ static inline void svm_inject_irq(struct
 	control->int_ctl &= ~V_INTR_PRIO_MASK;
 	control->int_ctl |= V_IRQ_MASK |
 		((/*control->int_vector >> 4*/ 0xf) << V_INTR_PRIO_SHIFT);
+	mark_dirty(svm->vmcb, VMCB_INTR);
 }
 
 static void svm_set_irq(struct kvm_vcpu *vcpu)
@@ -3077,14 +3327,14 @@ static void update_cr8_intercept(struct
 {
 	struct vcpu_svm *svm = to_svm(vcpu);
 
-	if (is_nested(svm) && (vcpu->arch.hflags & HF_VINTR_MASK))
+	if (is_guest_mode(vcpu) && (vcpu->arch.hflags & HF_VINTR_MASK))
 		return;
 
 	if (irr == -1)
 		return;
 
 	if (tpr >= irr)
-		svm->vmcb->control.intercept_cr_write |= INTERCEPT_CR8_MASK;
+		set_cr_intercept(svm, INTERCEPT_CR8_WRITE);
 }
 
 static int svm_nmi_allowed(struct kvm_vcpu *vcpu)
@@ -3112,10 +3362,10 @@ static void svm_set_nmi_mask(struct kvm_
 
 	if (masked) {
 		svm->vcpu.arch.hflags |= HF_NMI_MASK;
-		svm->vmcb->control.intercept |= (1ULL << INTERCEPT_IRET);
+		set_intercept(svm, INTERCEPT_IRET);
 	} else {
 		svm->vcpu.arch.hflags &= ~HF_NMI_MASK;
-		svm->vmcb->control.intercept &= ~(1ULL << INTERCEPT_IRET);
+		clr_intercept(svm, INTERCEPT_IRET);
 	}
 }
 
@@ -3131,7 +3381,7 @@ static int svm_interrupt_allowed(struct
 
 	ret = !!(vmcb->save.rflags & X86_EFLAGS_IF);
 
-	if (is_nested(svm))
+	if (is_guest_mode(vcpu))
 		return ret && !(svm->vcpu.arch.hflags & HF_VINTR_MASK);
 
 	return ret;
@@ -3177,7 +3427,12 @@ static int svm_set_tss_addr(struct kvm *
 
 static void svm_flush_tlb(struct kvm_vcpu *vcpu)
 {
-	force_new_asid(vcpu);
+	struct vcpu_svm *svm = to_svm(vcpu);
+
+	if (static_cpu_has(X86_FEATURE_FLUSHBYASID))
+		svm->vmcb->control.tlb_ctl = TLB_CONTROL_FLUSH_ASID;
+	else
+		svm->asid_generation--;
 }
 
 static void svm_prepare_guest_switch(struct kvm_vcpu *vcpu)
@@ -3188,10 +3443,10 @@ static inline void sync_cr8_to_lapic(str
 {
 	struct vcpu_svm *svm = to_svm(vcpu);
 
-	if (is_nested(svm) && (vcpu->arch.hflags & HF_VINTR_MASK))
+	if (is_guest_mode(vcpu) && (vcpu->arch.hflags & HF_VINTR_MASK))
 		return;
 
-	if (!(svm->vmcb->control.intercept_cr_write & INTERCEPT_CR8_MASK)) {
+	if (!is_cr_intercept(svm, INTERCEPT_CR8_WRITE)) {
 		int cr8 = svm->vmcb->control.int_ctl & V_TPR_MASK;
 		kvm_set_cr8(vcpu, cr8);
 	}
@@ -3202,7 +3457,7 @@ static inline void sync_lapic_to_cr8(str
 	struct vcpu_svm *svm = to_svm(vcpu);
 	u64 cr8;
 
-	if (is_nested(svm) && (vcpu->arch.hflags & HF_VINTR_MASK))
+	if (is_guest_mode(vcpu) && (vcpu->arch.hflags & HF_VINTR_MASK))
 		return;
 
 	cr8 = kvm_get_cr8(vcpu);
@@ -3289,9 +3544,6 @@ static void svm_cancel_injection(struct
 static void svm_vcpu_run(struct kvm_vcpu *vcpu)
 {
 	struct vcpu_svm *svm = to_svm(vcpu);
-	u16 fs_selector;
-	u16 gs_selector;
-	u16 ldt_selector;
 
 	svm->vmcb->save.rax = vcpu->arch.regs[VCPU_REGS_RAX];
 	svm->vmcb->save.rsp = vcpu->arch.regs[VCPU_REGS_RSP];
@@ -3308,10 +3560,6 @@ static void svm_vcpu_run(struct kvm_vcpu
 
 	sync_lapic_to_cr8(vcpu);
 
-	save_host_msrs(vcpu);
-	savesegment(fs, fs_selector);
-	savesegment(gs, gs_selector);
-	ldt_selector = kvm_read_ldt();
 	svm->vmcb->save.cr2 = vcpu->arch.cr2;
 
 	clgi();
@@ -3389,19 +3637,10 @@ static void svm_vcpu_run(struct kvm_vcpu
 #endif
 		);
 
-	vcpu->arch.cr2 = svm->vmcb->save.cr2;
-	vcpu->arch.regs[VCPU_REGS_RAX] = svm->vmcb->save.rax;
-	vcpu->arch.regs[VCPU_REGS_RSP] = svm->vmcb->save.rsp;
-	vcpu->arch.regs[VCPU_REGS_RIP] = svm->vmcb->save.rip;
-
-	load_host_msrs(vcpu);
-	kvm_load_ldt(ldt_selector);
-	loadsegment(fs, fs_selector);
 #ifdef CONFIG_X86_64
-	load_gs_index(gs_selector);
-	wrmsrl(MSR_KERNEL_GS_BASE, current->thread.gs);
+	wrmsrl(MSR_GS_BASE, svm->host.gs_base);
 #else
-	loadsegment(gs, gs_selector);
+	loadsegment(fs, svm->host.fs);
 #endif
 
 	reload_tss(vcpu);
@@ -3410,10 +3649,21 @@ static void svm_vcpu_run(struct kvm_vcpu
 
 	stgi();
 
+	vcpu->arch.cr2 = svm->vmcb->save.cr2;
+	vcpu->arch.regs[VCPU_REGS_RAX] = svm->vmcb->save.rax;
+	vcpu->arch.regs[VCPU_REGS_RSP] = svm->vmcb->save.rsp;
+	vcpu->arch.regs[VCPU_REGS_RIP] = svm->vmcb->save.rip;
+
 	sync_cr8_to_lapic(vcpu);
 
 	svm->next_rip = 0;
 
+	svm->vmcb->control.tlb_ctl = TLB_CONTROL_DO_NOTHING;
+
+	/* if exit due to PF check for async PF */
+	if (svm->vmcb->control.exit_code == SVM_EXIT_EXCP_BASE + PF_VECTOR)
+		svm->apf_reason = kvm_read_and_reset_pf_reason();
+
 	if (npt_enabled) {
 		vcpu->arch.regs_avail &= ~(1 << VCPU_EXREG_PDPTR);
 		vcpu->arch.regs_dirty &= ~(1 << VCPU_EXREG_PDPTR);
@@ -3426,6 +3676,8 @@ static void svm_vcpu_run(struct kvm_vcpu
 	if (unlikely(svm->vmcb->control.exit_code ==
 		     SVM_EXIT_EXCP_BASE + MC_VECTOR))
 		svm_handle_mce(svm);
+
+	mark_all_clean(svm->vmcb);
 }
 
 #undef R
@@ -3435,7 +3687,8 @@ static void svm_set_cr3(struct kvm_vcpu
 	struct vcpu_svm *svm = to_svm(vcpu);
 
 	svm->vmcb->save.cr3 = root;
-	force_new_asid(vcpu);
+	mark_dirty(svm->vmcb, VMCB_CR);
+	svm_flush_tlb(vcpu);
 }
 
 static void set_tdp_cr3(struct kvm_vcpu *vcpu, unsigned long root)
@@ -3443,11 +3696,13 @@ static void set_tdp_cr3(struct kvm_vcpu
 	struct vcpu_svm *svm = to_svm(vcpu);
 
 	svm->vmcb->control.nested_cr3 = root;
+	mark_dirty(svm->vmcb, VMCB_NPT);
 
 	/* Also sync guest cr3 here in case we live migrate */
-	svm->vmcb->save.cr3 = vcpu->arch.cr3;
+	svm->vmcb->save.cr3 = kvm_read_cr3(vcpu);
+	mark_dirty(svm->vmcb, VMCB_CR);
 
-	force_new_asid(vcpu);
+	svm_flush_tlb(vcpu);
 }
 
 static int is_disabled(void)
@@ -3494,10 +3749,6 @@ static void svm_cpuid_update(struct kvm_
 static void svm_set_supported_cpuid(u32 func, struct kvm_cpuid_entry2 *entry)
 {
 	switch (func) {
-	case 0x00000001:
-		/* Mask out xsave bit as long as it is not supported by SVM */
-		entry->ecx &= ~(bit(X86_FEATURE_XSAVE));
-		break;
 	case 0x80000001:
 		if (nested)
 			entry->ecx |= (1 << 2); /* Set SVM bit */
@@ -3511,7 +3762,7 @@ static void svm_set_supported_cpuid(u32
 				   additional features */
 
 		/* Support next_rip if host supports it */
-		if (svm_has(SVM_FEATURE_NRIP))
+		if (boot_cpu_has(X86_FEATURE_NRIPS))
 			entry->edx |= SVM_FEATURE_NRIP;
 
 		/* Support NPT for the guest if enabled */
@@ -3571,6 +3822,7 @@ static const struct trace_print_flags sv
 	{ SVM_EXIT_WBINVD,			"wbinvd" },
 	{ SVM_EXIT_MONITOR,			"monitor" },
 	{ SVM_EXIT_MWAIT,			"mwait" },
+	{ SVM_EXIT_XSETBV,			"xsetbv" },
 	{ SVM_EXIT_NPF,				"npf" },
 	{ -1, NULL }
 };
@@ -3594,9 +3846,7 @@ static void svm_fpu_deactivate(struct kv
 {
 	struct vcpu_svm *svm = to_svm(vcpu);
 
-	svm->vmcb->control.intercept_exceptions |= 1 << NM_VECTOR;
-	if (is_nested(svm))
-		svm->nested.hsave->control.intercept_exceptions |= 1 << NM_VECTOR;
+	set_exception_intercept(svm, NM_VECTOR);
 	update_cr0_intercept(svm);
 }
 
@@ -3627,6 +3877,7 @@ static struct kvm_x86_ops svm_x86_ops =
 	.get_cpl = svm_get_cpl,
 	.get_cs_db_l_bits = kvm_get_cs_db_l_bits,
 	.decache_cr0_guest_bits = svm_decache_cr0_guest_bits,
+	.decache_cr3 = svm_decache_cr3,
 	.decache_cr4_guest_bits = svm_decache_cr4_guest_bits,
 	.set_cr0 = svm_set_cr0,
 	.set_cr3 = svm_set_cr3,
@@ -3667,7 +3918,9 @@ static struct kvm_x86_ops svm_x86_ops =
 	.get_tdp_level = get_npt_level,
 	.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,
 
 	.cpuid_update = svm_cpuid_update,
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/kvm/trace.h linux-libre-2.6.38-gnu1/arch/x86/kvm/trace.h
--- linux-libre-2.6.37-gnu1/arch/x86/kvm/trace.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/kvm/trace.h	2011-03-14 21:20:32.000000000 -0400
@@ -178,27 +178,36 @@ TRACE_EVENT(kvm_apic,
 #define trace_kvm_apic_read(reg, val)		trace_kvm_apic(0, reg, val)
 #define trace_kvm_apic_write(reg, val)		trace_kvm_apic(1, reg, val)
 
+#define KVM_ISA_VMX   1
+#define KVM_ISA_SVM   2
+
 /*
  * Tracepoint for kvm guest exit:
  */
 TRACE_EVENT(kvm_exit,
-	TP_PROTO(unsigned int exit_reason, struct kvm_vcpu *vcpu),
-	TP_ARGS(exit_reason, vcpu),
+	TP_PROTO(unsigned int exit_reason, struct kvm_vcpu *vcpu, u32 isa),
+	TP_ARGS(exit_reason, vcpu, isa),
 
 	TP_STRUCT__entry(
 		__field(	unsigned int,	exit_reason	)
 		__field(	unsigned long,	guest_rip	)
+		__field(	u32,	        isa             )
+		__field(	u64,	        info1           )
+		__field(	u64,	        info2           )
 	),
 
 	TP_fast_assign(
 		__entry->exit_reason	= exit_reason;
 		__entry->guest_rip	= kvm_rip_read(vcpu);
+		__entry->isa            = isa;
+		kvm_x86_ops->get_exit_info(vcpu, &__entry->info1,
+					   &__entry->info2);
 	),
 
-	TP_printk("reason %s rip 0x%lx",
+	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->guest_rip)
+		 __entry->guest_rip, __entry->info1, __entry->info2)
 );
 
 /*
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/kvm/vmx.c linux-libre-2.6.38-gnu1/arch/x86/kvm/vmx.c
--- linux-libre-2.6.37-gnu1/arch/x86/kvm/vmx.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/kvm/vmx.c	2011-03-14 21:20:32.000000000 -0400
@@ -69,6 +69,9 @@ module_param(emulate_invalid_guest_state
 static int __read_mostly vmm_exclusive = 1;
 module_param(vmm_exclusive, bool, S_IRUGO);
 
+static int __read_mostly yield_on_hlt = 1;
+module_param(yield_on_hlt, bool, S_IRUGO);
+
 #define KVM_GUEST_CR0_MASK_UNRESTRICTED_GUEST				\
 	(X86_CR0_WP | X86_CR0_NE | X86_CR0_NW | X86_CR0_CD)
 #define KVM_GUEST_CR0_MASK						\
@@ -177,6 +180,7 @@ static int init_rmode(struct kvm *kvm);
 static u64 construct_eptp(unsigned long root_hpa);
 static void kvm_cpu_vmxon(u64 addr);
 static void kvm_cpu_vmxoff(void);
+static void vmx_set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3);
 
 static DEFINE_PER_CPU(struct vmcs *, vmxarea);
 static DEFINE_PER_CPU(struct vmcs *, current_vmcs);
@@ -188,6 +192,8 @@ static unsigned long *vmx_io_bitmap_b;
 static unsigned long *vmx_msr_bitmap_legacy;
 static unsigned long *vmx_msr_bitmap_longmode;
 
+static bool cpu_has_load_ia32_efer;
+
 static DECLARE_BITMAP(vmx_vpid_bitmap, VMX_NR_VPIDS);
 static DEFINE_SPINLOCK(vmx_vpid_lock);
 
@@ -472,7 +478,7 @@ static void vmcs_clear(struct vmcs *vmcs
 	u8 error;
 
 	asm volatile (__ex(ASM_VMX_VMCLEAR_RAX) "; setna %0"
-		      : "=g"(error) : "a"(&phys_addr), "m"(phys_addr)
+		      : "=qm"(error) : "a"(&phys_addr), "m"(phys_addr)
 		      : "cc", "memory");
 	if (error)
 		printk(KERN_ERR "kvm: vmclear fail: %p/%llx\n",
@@ -485,7 +491,7 @@ static void vmcs_load(struct vmcs *vmcs)
 	u8 error;
 
 	asm volatile (__ex(ASM_VMX_VMPTRLD_RAX) "; setna %0"
-			: "=g"(error) : "a"(&phys_addr), "m"(phys_addr)
+			: "=qm"(error) : "a"(&phys_addr), "m"(phys_addr)
 			: "cc", "memory");
 	if (error)
 		printk(KERN_ERR "kvm: vmptrld %p/%llx fail\n",
@@ -565,10 +571,10 @@ static inline void ept_sync_individual_a
 
 static unsigned long vmcs_readl(unsigned long field)
 {
-	unsigned long value;
+	unsigned long value = 0;
 
 	asm volatile (__ex(ASM_VMX_VMREAD_RDX_RAX)
-		      : "=a"(value) : "d"(field) : "cc");
+		      : "+a"(value) : "d"(field) : "cc");
 	return value;
 }
 
@@ -661,6 +667,12 @@ static void clear_atomic_switch_msr(stru
 	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;
+	}
+
 	for (i = 0; i < m->nr; ++i)
 		if (m->guest[i].index == msr)
 			break;
@@ -680,6 +692,14 @@ static void add_atomic_switch_msr(struct
 	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;
+	}
+
 	for (i = 0; i < m->nr; ++i)
 		if (m->guest[i].index == msr)
 			break;
@@ -1009,6 +1029,17 @@ static void skip_emulated_instruction(st
 	vmx_set_interrupt_shadow(vcpu, 0);
 }
 
+static void vmx_clear_hlt(struct kvm_vcpu *vcpu)
+{
+	/* Ensure that we clear the HLT state in the VMCS.  We don't need to
+	 * explicitly skip the instruction because if the HLT state is set, then
+	 * the instruction is already executing and RIP has already been
+	 * advanced. */
+	if (!yield_on_hlt &&
+	    vmcs_read32(GUEST_ACTIVITY_STATE) == GUEST_ACTIVITY_HLT)
+		vmcs_write32(GUEST_ACTIVITY_STATE, GUEST_ACTIVITY_ACTIVE);
+}
+
 static void vmx_queue_exception(struct kvm_vcpu *vcpu, unsigned nr,
 				bool has_error_code, u32 error_code,
 				bool reinject)
@@ -1035,6 +1066,7 @@ static void vmx_queue_exception(struct k
 		intr_info |= INTR_TYPE_HARD_EXCEPTION;
 
 	vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, intr_info);
+	vmx_clear_hlt(vcpu);
 }
 
 static bool vmx_rdtscp_supported(void)
@@ -1305,8 +1337,11 @@ static __init int vmx_disabled_by_bios(v
 			&& tboot_enabled())
 			return 1;
 		if (!(msr & FEATURE_CONTROL_VMXON_ENABLED_OUTSIDE_SMX)
-			&& !tboot_enabled())
+			&& !tboot_enabled()) {
+			printk(KERN_WARNING "kvm: disable TXT in the BIOS or "
+				" activate TXT before enabling KVM\n");
 			return 1;
+		}
 	}
 
 	return 0;
@@ -1400,6 +1435,14 @@ static __init int adjust_vmx_controls(u3
 	return 0;
 }
 
+static __init bool allow_1_setting(u32 msr, u32 ctl)
+{
+	u32 vmx_msr_low, vmx_msr_high;
+
+	rdmsr(msr, vmx_msr_low, vmx_msr_high);
+	return vmx_msr_high & ctl;
+}
+
 static __init int setup_vmcs_config(struct vmcs_config *vmcs_conf)
 {
 	u32 vmx_msr_low, vmx_msr_high;
@@ -1416,7 +1459,7 @@ static __init int setup_vmcs_config(stru
 				&_pin_based_exec_control) < 0)
 		return -EIO;
 
-	min = CPU_BASED_HLT_EXITING |
+	min =
 #ifdef CONFIG_X86_64
 	      CPU_BASED_CR8_LOAD_EXITING |
 	      CPU_BASED_CR8_STORE_EXITING |
@@ -1429,6 +1472,10 @@ static __init int setup_vmcs_config(stru
 	      CPU_BASED_MWAIT_EXITING |
 	      CPU_BASED_MONITOR_EXITING |
 	      CPU_BASED_INVLPG_EXITING;
+
+	if (yield_on_hlt)
+		min |= CPU_BASED_HLT_EXITING;
+
 	opt = CPU_BASED_TPR_SHADOW |
 	      CPU_BASED_USE_MSR_BITMAPS |
 	      CPU_BASED_ACTIVATE_SECONDARY_CONTROLS;
@@ -1510,6 +1557,12 @@ static __init int setup_vmcs_config(stru
 	vmcs_conf->vmexit_ctrl         = _vmexit_control;
 	vmcs_conf->vmentry_ctrl        = _vmentry_control;
 
+	cpu_has_load_ia32_efer =
+		allow_1_setting(MSR_IA32_VMX_ENTRY_CTLS,
+				VM_ENTRY_LOAD_IA32_EFER)
+		&& allow_1_setting(MSR_IA32_VMX_EXIT_CTLS,
+				   VM_EXIT_LOAD_IA32_EFER);
+
 	return 0;
 }
 
@@ -1683,9 +1736,13 @@ static void fix_rmode_seg(int seg, struc
 	save->limit = vmcs_read32(sf->limit);
 	save->ar = vmcs_read32(sf->ar_bytes);
 	vmcs_write16(sf->selector, save->base >> 4);
-	vmcs_write32(sf->base, save->base & 0xfffff);
+	vmcs_write32(sf->base, save->base & 0xffff0);
 	vmcs_write32(sf->limit, 0xffff);
 	vmcs_write32(sf->ar_bytes, 0xf3);
+	if (save->base & 0xf)
+		printk_once(KERN_WARNING "kvm: segment base is not paragraph"
+			    " aligned when entering protected mode (seg=%d)",
+			    seg);
 }
 
 static void enter_rmode(struct kvm_vcpu *vcpu)
@@ -1814,6 +1871,13 @@ static void vmx_decache_cr0_guest_bits(s
 	vcpu->arch.cr0 |= vmcs_readl(GUEST_CR0) & cr0_guest_owned_bits;
 }
 
+static void vmx_decache_cr3(struct kvm_vcpu *vcpu)
+{
+	if (enable_ept && is_paging(vcpu))
+		vcpu->arch.cr3 = vmcs_readl(GUEST_CR3);
+	__set_bit(VCPU_EXREG_CR3, (ulong *)&vcpu->arch.regs_avail);
+}
+
 static void vmx_decache_cr4_guest_bits(struct kvm_vcpu *vcpu)
 {
 	ulong cr4_guest_owned_bits = vcpu->arch.cr4_guest_owned_bits;
@@ -1857,6 +1921,7 @@ static void ept_update_paging_mode_cr0(u
 					unsigned long cr0,
 					struct kvm_vcpu *vcpu)
 {
+	vmx_decache_cr3(vcpu);
 	if (!(cr0 & X86_CR0_PG)) {
 		/* From paging/starting to nonpaging */
 		vmcs_write32(CPU_BASED_VM_EXEC_CONTROL,
@@ -1937,7 +2002,7 @@ static void vmx_set_cr3(struct kvm_vcpu
 	if (enable_ept) {
 		eptp = construct_eptp(cr3);
 		vmcs_write64(EPT_POINTER, eptp);
-		guest_cr3 = is_paging(vcpu) ? vcpu->arch.cr3 :
+		guest_cr3 = is_paging(vcpu) ? kvm_read_cr3(vcpu) :
 			vcpu->kvm->arch.ept_identity_map_addr;
 		ept_load_pdptrs(vcpu);
 	}
@@ -2725,7 +2790,7 @@ static int vmx_vcpu_reset(struct kvm_vcp
 	vmcs_writel(GUEST_IDTR_BASE, 0);
 	vmcs_write32(GUEST_IDTR_LIMIT, 0xffff);
 
-	vmcs_write32(GUEST_ACTIVITY_STATE, 0);
+	vmcs_write32(GUEST_ACTIVITY_STATE, GUEST_ACTIVITY_ACTIVE);
 	vmcs_write32(GUEST_INTERRUPTIBILITY_INFO, 0);
 	vmcs_write32(GUEST_PENDING_DBG_EXCEPTIONS, 0);
 
@@ -2787,6 +2852,10 @@ static void enable_nmi_window(struct kvm
 		return;
 	}
 
+	if (vmcs_read32(GUEST_INTERRUPTIBILITY_INFO) & GUEST_INTR_STATE_STI) {
+		enable_irq_window(vcpu);
+		return;
+	}
 	cpu_based_vm_exec_control = vmcs_read32(CPU_BASED_VM_EXEC_CONTROL);
 	cpu_based_vm_exec_control |= CPU_BASED_VIRTUAL_NMI_PENDING;
 	vmcs_write32(CPU_BASED_VM_EXEC_CONTROL, cpu_based_vm_exec_control);
@@ -2814,6 +2883,7 @@ static void vmx_inject_irq(struct kvm_vc
 	} else
 		intr |= INTR_TYPE_EXT_INTR;
 	vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, intr);
+	vmx_clear_hlt(vcpu);
 }
 
 static void vmx_inject_nmi(struct kvm_vcpu *vcpu)
@@ -2841,6 +2911,7 @@ static void vmx_inject_nmi(struct kvm_vc
 	}
 	vmcs_write32(VM_ENTRY_INTR_INFO_FIELD,
 			INTR_TYPE_NMI_INTR | INTR_INFO_VALID_MASK | NMI_VECTOR);
+	vmx_clear_hlt(vcpu);
 }
 
 static int vmx_nmi_allowed(struct kvm_vcpu *vcpu)
@@ -2849,7 +2920,8 @@ static int vmx_nmi_allowed(struct kvm_vc
 		return 0;
 
 	return	!(vmcs_read32(GUEST_INTERRUPTIBILITY_INFO) &
-			(GUEST_INTR_STATE_MOV_SS | GUEST_INTR_STATE_NMI));
+		  (GUEST_INTR_STATE_MOV_SS | GUEST_INTR_STATE_STI
+		   | GUEST_INTR_STATE_NMI));
 }
 
 static bool vmx_get_nmi_mask(struct kvm_vcpu *vcpu)
@@ -2910,7 +2982,7 @@ static int handle_rmode_exception(struct
 	 * Cause the #SS fault with 0 error code in VM86 mode.
 	 */
 	if (((vec == GP_VECTOR) || (vec == SS_VECTOR)) && err_code == 0)
-		if (emulate_instruction(vcpu, 0, 0, 0) == EMULATE_DONE)
+		if (emulate_instruction(vcpu, 0) == EMULATE_DONE)
 			return 1;
 	/*
 	 * Forward all other exceptions that are valid in real mode.
@@ -3007,7 +3079,7 @@ static int handle_exception(struct kvm_v
 	}
 
 	if (is_invalid_opcode(intr_info)) {
-		er = emulate_instruction(vcpu, 0, 0, EMULTYPE_TRAP_UD);
+		er = emulate_instruction(vcpu, EMULTYPE_TRAP_UD);
 		if (er != EMULATE_DONE)
 			kvm_queue_exception(vcpu, UD_VECTOR);
 		return 1;
@@ -3026,7 +3098,7 @@ static int handle_exception(struct kvm_v
 
 		if (kvm_event_needs_reinjection(vcpu))
 			kvm_mmu_unprotect_page_virt(vcpu, cr2);
-		return kvm_mmu_page_fault(vcpu, cr2, error_code);
+		return kvm_mmu_page_fault(vcpu, cr2, error_code, NULL, 0);
 	}
 
 	if (vmx->rmode.vm86_active &&
@@ -3098,7 +3170,7 @@ static int handle_io(struct kvm_vcpu *vc
 	++vcpu->stat.io_exits;
 
 	if (string || in)
-		return emulate_instruction(vcpu, 0, 0, 0) == EMULATE_DONE;
+		return emulate_instruction(vcpu, 0) == EMULATE_DONE;
 
 	port = exit_qualification >> 16;
 	size = (exit_qualification & 7) + 1;
@@ -3118,14 +3190,6 @@ vmx_patch_hypercall(struct kvm_vcpu *vcp
 	hypercall[2] = 0xc1;
 }
 
-static void complete_insn_gp(struct kvm_vcpu *vcpu, int err)
-{
-	if (err)
-		kvm_inject_gp(vcpu, 0);
-	else
-		skip_emulated_instruction(vcpu);
-}
-
 static int handle_cr(struct kvm_vcpu *vcpu)
 {
 	unsigned long exit_qualification, val;
@@ -3143,21 +3207,21 @@ static int handle_cr(struct kvm_vcpu *vc
 		switch (cr) {
 		case 0:
 			err = kvm_set_cr0(vcpu, val);
-			complete_insn_gp(vcpu, err);
+			kvm_complete_insn_gp(vcpu, err);
 			return 1;
 		case 3:
 			err = kvm_set_cr3(vcpu, val);
-			complete_insn_gp(vcpu, err);
+			kvm_complete_insn_gp(vcpu, err);
 			return 1;
 		case 4:
 			err = kvm_set_cr4(vcpu, val);
-			complete_insn_gp(vcpu, err);
+			kvm_complete_insn_gp(vcpu, err);
 			return 1;
 		case 8: {
 				u8 cr8_prev = kvm_get_cr8(vcpu);
 				u8 cr8 = kvm_register_read(vcpu, reg);
-				kvm_set_cr8(vcpu, cr8);
-				skip_emulated_instruction(vcpu);
+				err = kvm_set_cr8(vcpu, cr8);
+				kvm_complete_insn_gp(vcpu, err);
 				if (irqchip_in_kernel(vcpu->kvm))
 					return 1;
 				if (cr8_prev <= cr8)
@@ -3176,8 +3240,9 @@ static int handle_cr(struct kvm_vcpu *vc
 	case 1: /*mov from cr*/
 		switch (cr) {
 		case 3:
-			kvm_register_write(vcpu, reg, vcpu->arch.cr3);
-			trace_kvm_cr_read(cr, vcpu->arch.cr3);
+			val = kvm_read_cr3(vcpu);
+			kvm_register_write(vcpu, reg, val);
+			trace_kvm_cr_read(cr, val);
 			skip_emulated_instruction(vcpu);
 			return 1;
 		case 8:
@@ -3349,6 +3414,11 @@ static int handle_vmx_insn(struct kvm_vc
 	return 1;
 }
 
+static int handle_invd(struct kvm_vcpu *vcpu)
+{
+	return emulate_instruction(vcpu, 0) == EMULATE_DONE;
+}
+
 static int handle_invlpg(struct kvm_vcpu *vcpu)
 {
 	unsigned long exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
@@ -3377,7 +3447,7 @@ static int handle_xsetbv(struct kvm_vcpu
 
 static int handle_apic_access(struct kvm_vcpu *vcpu)
 {
-	return emulate_instruction(vcpu, 0, 0, 0) == EMULATE_DONE;
+	return emulate_instruction(vcpu, 0) == EMULATE_DONE;
 }
 
 static int handle_task_switch(struct kvm_vcpu *vcpu)
@@ -3476,7 +3546,7 @@ static int handle_ept_violation(struct k
 
 	gpa = vmcs_read64(GUEST_PHYSICAL_ADDRESS);
 	trace_kvm_page_fault(gpa, exit_qualification);
-	return kvm_mmu_page_fault(vcpu, gpa & PAGE_MASK, 0);
+	return kvm_mmu_page_fault(vcpu, gpa, exit_qualification & 0x3, NULL, 0);
 }
 
 static u64 ept_rsvd_mask(u64 spte, int level)
@@ -3592,7 +3662,7 @@ static int handle_invalid_guest_state(st
 		    && (kvm_get_rflags(&vmx->vcpu) & X86_EFLAGS_IF))
 			return handle_interrupt_window(&vmx->vcpu);
 
-		err = emulate_instruction(vcpu, 0, 0, 0);
+		err = emulate_instruction(vcpu, 0);
 
 		if (err == EMULATE_DO_MMIO) {
 			ret = 0;
@@ -3649,6 +3719,7 @@ static int (*kvm_vmx_exit_handlers[])(st
 	[EXIT_REASON_MSR_WRITE]               = handle_wrmsr,
 	[EXIT_REASON_PENDING_INTERRUPT]       = handle_interrupt_window,
 	[EXIT_REASON_HLT]                     = handle_halt,
+	[EXIT_REASON_INVD]		      = handle_invd,
 	[EXIT_REASON_INVLPG]		      = handle_invlpg,
 	[EXIT_REASON_VMCALL]                  = handle_vmcall,
 	[EXIT_REASON_VMCLEAR]	              = handle_vmx_insn,
@@ -3676,6 +3747,12 @@ static int (*kvm_vmx_exit_handlers[])(st
 static const int kvm_vmx_max_exit_handlers =
 	ARRAY_SIZE(kvm_vmx_exit_handlers);
 
+static void vmx_get_exit_info(struct kvm_vcpu *vcpu, u64 *info1, u64 *info2)
+{
+	*info1 = vmcs_readl(EXIT_QUALIFICATION);
+	*info2 = vmcs_read32(VM_EXIT_INTR_INFO);
+}
+
 /*
  * The guest has exited.  See if we can fix it or if we need userspace
  * assistance.
@@ -3686,17 +3763,12 @@ 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);
+	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);
 
-	/* Access CR3 don't cause VMExit in paging mode, so we need
-	 * to sync with guest real CR3. */
-	if (enable_ept && is_paging(vcpu))
-		vcpu->arch.cr3 = vmcs_readl(GUEST_CR3);
-
 	if (exit_reason & VMX_EXIT_REASONS_FAILED_VMENTRY) {
 		vcpu->run->exit_reason = KVM_EXIT_FAIL_ENTRY;
 		vcpu->run->fail_entry.hardware_entry_failure_reason
@@ -4013,7 +4085,8 @@ static void vmx_vcpu_run(struct kvm_vcpu
 	      );
 
 	vcpu->arch.regs_avail = ~((1 << VCPU_REGS_RIP) | (1 << VCPU_REGS_RSP)
-				  | (1 << VCPU_EXREG_PDPTR));
+				  | (1 << VCPU_EXREG_PDPTR)
+				  | (1 << VCPU_EXREG_CR3));
 	vcpu->arch.regs_dirty = 0;
 
 	vmx->idt_vectoring_info = vmcs_read32(IDT_VECTORING_INFO_FIELD);
@@ -4280,6 +4353,7 @@ static struct kvm_x86_ops vmx_x86_ops =
 	.get_cpl = vmx_get_cpl,
 	.get_cs_db_l_bits = vmx_get_cs_db_l_bits,
 	.decache_cr0_guest_bits = vmx_decache_cr0_guest_bits,
+	.decache_cr3 = vmx_decache_cr3,
 	.decache_cr4_guest_bits = vmx_decache_cr4_guest_bits,
 	.set_cr0 = vmx_set_cr0,
 	.set_cr3 = vmx_set_cr3,
@@ -4320,7 +4394,9 @@ static struct kvm_x86_ops vmx_x86_ops =
 	.get_tdp_level = get_ept_level,
 	.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,
 
 	.cpuid_update = vmx_cpuid_update,
@@ -4396,8 +4472,6 @@ static int __init vmx_init(void)
 
 	if (enable_ept) {
 		bypass_guest_pf = 0;
-		kvm_mmu_set_base_ptes(VMX_EPT_READABLE_MASK |
-			VMX_EPT_WRITABLE_MASK);
 		kvm_mmu_set_mask_ptes(0ull, 0ull, 0ull, 0ull,
 				VMX_EPT_EXECUTABLE_MASK);
 		kvm_enable_tdp();
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/kvm/x86.c linux-libre-2.6.38-gnu1/arch/x86/kvm/x86.c
--- linux-libre-2.6.37-gnu1/arch/x86/kvm/x86.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/kvm/x86.c	2011-03-14 21:20:32.000000000 -0400
@@ -43,6 +43,7 @@
 #include <linux/slab.h>
 #include <linux/perf_event.h>
 #include <linux/uaccess.h>
+#include <linux/hash.h>
 #include <trace/events/kvm.h>
 
 #define CREATE_TRACE_POINTS
@@ -155,6 +156,13 @@ struct kvm_stats_debugfs_item debugfs_en
 
 u64 __read_mostly host_xcr0;
 
+static inline void kvm_async_pf_hash_reset(struct kvm_vcpu *vcpu)
+{
+	int i;
+	for (i = 0; i < roundup_pow_of_two(ASYNC_PF_PER_VCPU); i++)
+		vcpu->arch.apf.gfns[i] = ~0;
+}
+
 static void kvm_on_user_return(struct user_return_notifier *urn)
 {
 	unsigned slot;
@@ -326,23 +334,28 @@ void kvm_requeue_exception(struct kvm_vc
 }
 EXPORT_SYMBOL_GPL(kvm_requeue_exception);
 
-void kvm_inject_page_fault(struct kvm_vcpu *vcpu)
+void kvm_complete_insn_gp(struct kvm_vcpu *vcpu, int err)
 {
-	unsigned error_code = vcpu->arch.fault.error_code;
+	if (err)
+		kvm_inject_gp(vcpu, 0);
+	else
+		kvm_x86_ops->skip_emulated_instruction(vcpu);
+}
+EXPORT_SYMBOL_GPL(kvm_complete_insn_gp);
 
+void kvm_inject_page_fault(struct kvm_vcpu *vcpu, struct x86_exception *fault)
+{
 	++vcpu->stat.pf_guest;
-	vcpu->arch.cr2 = vcpu->arch.fault.address;
-	kvm_queue_exception_e(vcpu, PF_VECTOR, error_code);
+	vcpu->arch.cr2 = fault->address;
+	kvm_queue_exception_e(vcpu, PF_VECTOR, fault->error_code);
 }
 
-void kvm_propagate_fault(struct kvm_vcpu *vcpu)
+void kvm_propagate_fault(struct kvm_vcpu *vcpu, struct x86_exception *fault)
 {
-	if (mmu_is_nested(vcpu) && !vcpu->arch.fault.nested)
-		vcpu->arch.nested_mmu.inject_page_fault(vcpu);
+	if (mmu_is_nested(vcpu) && !fault->nested_page_fault)
+		vcpu->arch.nested_mmu.inject_page_fault(vcpu, fault);
 	else
-		vcpu->arch.mmu.inject_page_fault(vcpu);
-
-	vcpu->arch.fault.nested = false;
+		vcpu->arch.mmu.inject_page_fault(vcpu, fault);
 }
 
 void kvm_inject_nmi(struct kvm_vcpu *vcpu)
@@ -460,8 +473,8 @@ static bool pdptrs_changed(struct kvm_vc
 		      (unsigned long *)&vcpu->arch.regs_avail))
 		return true;
 
-	gfn = (vcpu->arch.cr3 & ~31u) >> PAGE_SHIFT;
-	offset = (vcpu->arch.cr3 & ~31u) & (PAGE_SIZE - 1);
+	gfn = (kvm_read_cr3(vcpu) & ~31u) >> PAGE_SHIFT;
+	offset = (kvm_read_cr3(vcpu) & ~31u) & (PAGE_SIZE - 1);
 	r = kvm_read_nested_guest_page(vcpu, gfn, pdpte, offset, sizeof(pdpte),
 				       PFERR_USER_MASK | PFERR_WRITE_MASK);
 	if (r < 0)
@@ -506,12 +519,15 @@ int kvm_set_cr0(struct kvm_vcpu *vcpu, u
 		} else
 #endif
 		if (is_pae(vcpu) && !load_pdptrs(vcpu, vcpu->arch.walk_mmu,
-						 vcpu->arch.cr3))
+						 kvm_read_cr3(vcpu)))
 			return 1;
 	}
 
 	kvm_x86_ops->set_cr0(vcpu, cr0);
 
+	if ((cr0 ^ old_cr0) & X86_CR0_PG)
+		kvm_clear_async_pf_completion_queue(vcpu);
+
 	if ((cr0 ^ old_cr0) & update_bits)
 		kvm_mmu_reset_context(vcpu);
 	return 0;
@@ -595,7 +611,8 @@ int kvm_set_cr4(struct kvm_vcpu *vcpu, u
 			return 1;
 	} else if (is_paging(vcpu) && (cr4 & X86_CR4_PAE)
 		   && ((cr4 ^ old_cr4) & pdptr_bits)
-		   && !load_pdptrs(vcpu, vcpu->arch.walk_mmu, vcpu->arch.cr3))
+		   && !load_pdptrs(vcpu, vcpu->arch.walk_mmu,
+				   kvm_read_cr3(vcpu)))
 		return 1;
 
 	if (cr4 & X86_CR4_VMXE)
@@ -615,7 +632,7 @@ EXPORT_SYMBOL_GPL(kvm_set_cr4);
 
 int kvm_set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3)
 {
-	if (cr3 == vcpu->arch.cr3 && !pdptrs_changed(vcpu)) {
+	if (cr3 == kvm_read_cr3(vcpu) && !pdptrs_changed(vcpu)) {
 		kvm_mmu_sync_roots(vcpu);
 		kvm_mmu_flush_tlb(vcpu);
 		return 0;
@@ -650,12 +667,13 @@ int kvm_set_cr3(struct kvm_vcpu *vcpu, u
 	if (unlikely(!gfn_to_memslot(vcpu->kvm, cr3 >> PAGE_SHIFT)))
 		return 1;
 	vcpu->arch.cr3 = cr3;
+	__set_bit(VCPU_EXREG_CR3, (ulong *)&vcpu->arch.regs_avail);
 	vcpu->arch.mmu.new_cr3(vcpu);
 	return 0;
 }
 EXPORT_SYMBOL_GPL(kvm_set_cr3);
 
-int __kvm_set_cr8(struct kvm_vcpu *vcpu, unsigned long cr8)
+int kvm_set_cr8(struct kvm_vcpu *vcpu, unsigned long cr8)
 {
 	if (cr8 & CR8_RESERVED_BITS)
 		return 1;
@@ -665,12 +683,6 @@ int __kvm_set_cr8(struct kvm_vcpu *vcpu,
 		vcpu->arch.cr8 = cr8;
 	return 0;
 }
-
-void kvm_set_cr8(struct kvm_vcpu *vcpu, unsigned long cr8)
-{
-	if (__kvm_set_cr8(vcpu, cr8))
-		kvm_inject_gp(vcpu, 0);
-}
 EXPORT_SYMBOL_GPL(kvm_set_cr8);
 
 unsigned long kvm_get_cr8(struct kvm_vcpu *vcpu)
@@ -775,12 +787,12 @@ EXPORT_SYMBOL_GPL(kvm_get_dr);
  * kvm-specific. Those are put in the beginning of the list.
  */
 
-#define KVM_SAVE_MSRS_BEGIN	7
+#define KVM_SAVE_MSRS_BEGIN	8
 static u32 msrs_to_save[] = {
 	MSR_KVM_SYSTEM_TIME, MSR_KVM_WALL_CLOCK,
 	MSR_KVM_SYSTEM_TIME_NEW, MSR_KVM_WALL_CLOCK_NEW,
 	HV_X64_MSR_GUEST_OS_ID, HV_X64_MSR_HYPERCALL,
-	HV_X64_MSR_APIC_ASSIST_PAGE,
+	HV_X64_MSR_APIC_ASSIST_PAGE, MSR_KVM_ASYNC_PF_EN,
 	MSR_IA32_SYSENTER_CS, MSR_IA32_SYSENTER_ESP, MSR_IA32_SYSENTER_EIP,
 	MSR_STAR,
 #ifdef CONFIG_X86_64
@@ -830,7 +842,6 @@ static int set_efer(struct kvm_vcpu *vcp
 	kvm_x86_ops->set_efer(vcpu, efer);
 
 	vcpu->arch.mmu.base_role.nxe = (efer & EFER_NX) && !tdp_enabled;
-	kvm_mmu_reset_context(vcpu);
 
 	/* Update reserved bits */
 	if ((efer ^ old_efer) & EFER_NX)
@@ -976,7 +987,7 @@ static inline u64 nsec_to_cycles(u64 nse
 	if (kvm_tsc_changes_freq())
 		printk_once(KERN_WARNING
 		 "kvm: unreliable cycle conversion on adjustable rate TSC\n");
-	ret = nsec * __get_cpu_var(cpu_tsc_khz);
+	ret = nsec * __this_cpu_read(cpu_tsc_khz);
 	do_div(ret, USEC_PER_SEC);
 	return ret;
 }
@@ -1061,7 +1072,7 @@ static int kvm_guest_time_update(struct
 	local_irq_save(flags);
 	kvm_get_msr(v, MSR_IA32_TSC, &tsc_timestamp);
 	kernel_ns = get_kernel_ns();
-	this_tsc_khz = __get_cpu_var(cpu_tsc_khz);
+	this_tsc_khz = __this_cpu_read(cpu_tsc_khz);
 
 	if (unlikely(this_tsc_khz == 0)) {
 		local_irq_restore(flags);
@@ -1418,6 +1429,30 @@ static int set_msr_hyperv(struct kvm_vcp
 	return 0;
 }
 
+static int kvm_pv_enable_async_pf(struct kvm_vcpu *vcpu, u64 data)
+{
+	gpa_t gpa = data & ~0x3f;
+
+	/* Bits 2:5 are resrved, Should be zero */
+	if (data & 0x3c)
+		return 1;
+
+	vcpu->arch.apf.msr_val = data;
+
+	if (!(data & KVM_ASYNC_PF_ENABLED)) {
+		kvm_clear_async_pf_completion_queue(vcpu);
+		kvm_async_pf_hash_reset(vcpu);
+		return 0;
+	}
+
+	if (kvm_gfn_to_hva_cache_init(vcpu->kvm, &vcpu->arch.apf.data, gpa))
+		return 1;
+
+	vcpu->arch.apf.send_user_only = !(data & KVM_ASYNC_PF_SEND_ALWAYS);
+	kvm_async_pf_wakeup_all(vcpu);
+	return 0;
+}
+
 int kvm_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data)
 {
 	switch (msr) {
@@ -1499,6 +1534,10 @@ int kvm_set_msr_common(struct kvm_vcpu *
 		}
 		break;
 	}
+	case MSR_KVM_ASYNC_PF_EN:
+		if (kvm_pv_enable_async_pf(vcpu, data))
+			return 1;
+		break;
 	case MSR_IA32_MCG_CTL:
 	case MSR_IA32_MCG_STATUS:
 	case MSR_IA32_MC0_CTL ... MSR_IA32_MC0_CTL + 4 * KVM_MAX_MCE_BANKS - 1:
@@ -1775,6 +1814,9 @@ int kvm_get_msr_common(struct kvm_vcpu *
 	case MSR_KVM_SYSTEM_TIME_NEW:
 		data = vcpu->arch.time;
 		break;
+	case MSR_KVM_ASYNC_PF_EN:
+		data = vcpu->arch.apf.msr_val;
+		break;
 	case MSR_IA32_P5_MC_ADDR:
 	case MSR_IA32_P5_MC_TYPE:
 	case MSR_IA32_MCG_CAP:
@@ -1904,6 +1946,7 @@ int kvm_dev_ioctl_check_extension(long e
 	case KVM_CAP_NOP_IO_DELAY:
 	case KVM_CAP_MP_STATE:
 	case KVM_CAP_SYNC_MMU:
+	case KVM_CAP_USER_NMI:
 	case KVM_CAP_REINJECT_CONTROL:
 	case KVM_CAP_IRQ_INJECT_STATUS:
 	case KVM_CAP_ASSIGN_DEV_IRQ:
@@ -1922,6 +1965,7 @@ int kvm_dev_ioctl_check_extension(long e
 	case KVM_CAP_DEBUGREGS:
 	case KVM_CAP_X86_ROBUST_SINGLESTEP:
 	case KVM_CAP_XSAVE:
+	case KVM_CAP_ASYNC_PF:
 		r = 1;
 		break;
 	case KVM_CAP_COALESCED_MMIO:
@@ -2185,6 +2229,11 @@ out:
 	return r;
 }
 
+static void cpuid_mask(u32 *word, int wordnum)
+{
+	*word &= boot_cpu_data.x86_capability[wordnum];
+}
+
 static void do_cpuid_1_ent(struct kvm_cpuid_entry2 *entry, u32 function,
 			   u32 index)
 {
@@ -2259,7 +2308,9 @@ static void do_cpuid_ent(struct kvm_cpui
 		break;
 	case 1:
 		entry->edx &= kvm_supported_word0_x86_features;
+		cpuid_mask(&entry->edx, 0);
 		entry->ecx &= kvm_supported_word4_x86_features;
+		cpuid_mask(&entry->ecx, 4);
 		/* we support x2apic emulation even if host does not support
 		 * it since we emulate x2apic in software */
 		entry->ecx |= F(X2APIC);
@@ -2350,7 +2401,9 @@ static void do_cpuid_ent(struct kvm_cpui
 		break;
 	case 0x80000001:
 		entry->edx &= kvm_supported_word1_x86_features;
+		cpuid_mask(&entry->edx, 1);
 		entry->ecx &= kvm_supported_word6_x86_features;
+		cpuid_mask(&entry->ecx, 6);
 		break;
 	}
 
@@ -3169,20 +3222,18 @@ int kvm_vm_ioctl_get_dirty_log(struct kv
 		struct kvm_memslots *slots, *old_slots;
 		unsigned long *dirty_bitmap;
 
-		r = -ENOMEM;
-		dirty_bitmap = vmalloc(n);
-		if (!dirty_bitmap)
-			goto out;
+		dirty_bitmap = memslot->dirty_bitmap_head;
+		if (memslot->dirty_bitmap == dirty_bitmap)
+			dirty_bitmap += n / sizeof(long);
 		memset(dirty_bitmap, 0, n);
 
 		r = -ENOMEM;
 		slots = kzalloc(sizeof(struct kvm_memslots), GFP_KERNEL);
-		if (!slots) {
-			vfree(dirty_bitmap);
+		if (!slots)
 			goto out;
-		}
 		memcpy(slots, kvm->memslots, sizeof(struct kvm_memslots));
 		slots->memslots[log->slot].dirty_bitmap = dirty_bitmap;
+		slots->generation++;
 
 		old_slots = kvm->memslots;
 		rcu_assign_pointer(kvm->memslots, slots);
@@ -3195,11 +3246,8 @@ int kvm_vm_ioctl_get_dirty_log(struct kv
 		spin_unlock(&kvm->mmu_lock);
 
 		r = -EFAULT;
-		if (copy_to_user(log->dirty_bitmap, dirty_bitmap, n)) {
-			vfree(dirty_bitmap);
+		if (copy_to_user(log->dirty_bitmap, dirty_bitmap, n))
 			goto out;
-		}
-		vfree(dirty_bitmap);
 	} else {
 		r = -EFAULT;
 		if (clear_user(log->dirty_bitmap, n))
@@ -3266,8 +3314,10 @@ long kvm_arch_vm_ioctl(struct file *filp
 		if (vpic) {
 			r = kvm_ioapic_init(kvm);
 			if (r) {
+				mutex_lock(&kvm->slots_lock);
 				kvm_io_bus_unregister_dev(kvm, KVM_PIO_BUS,
 							  &vpic->dev);
+				mutex_unlock(&kvm->slots_lock);
 				kfree(vpic);
 				goto create_irqchip_unlock;
 			}
@@ -3278,10 +3328,12 @@ long kvm_arch_vm_ioctl(struct file *filp
 		smp_wmb();
 		r = kvm_setup_default_irq_routing(kvm);
 		if (r) {
+			mutex_lock(&kvm->slots_lock);
 			mutex_lock(&kvm->irq_lock);
 			kvm_ioapic_destroy(kvm);
 			kvm_destroy_pic(kvm);
 			mutex_unlock(&kvm->irq_lock);
+			mutex_unlock(&kvm->slots_lock);
 		}
 	create_irqchip_unlock:
 		mutex_unlock(&kvm->lock);
@@ -3557,63 +3609,63 @@ static gpa_t translate_gpa(struct kvm_vc
 static gpa_t translate_nested_gpa(struct kvm_vcpu *vcpu, gpa_t gpa, u32 access)
 {
 	gpa_t t_gpa;
-	u32 error;
+	struct x86_exception exception;
 
 	BUG_ON(!mmu_is_nested(vcpu));
 
 	/* NPT walks are always user-walks */
 	access |= PFERR_USER_MASK;
-	t_gpa  = vcpu->arch.mmu.gva_to_gpa(vcpu, gpa, access, &error);
-	if (t_gpa == UNMAPPED_GVA)
-		vcpu->arch.fault.nested = true;
+	t_gpa  = vcpu->arch.mmu.gva_to_gpa(vcpu, gpa, access, &exception);
 
 	return t_gpa;
 }
 
-gpa_t kvm_mmu_gva_to_gpa_read(struct kvm_vcpu *vcpu, gva_t gva, u32 *error)
+gpa_t kvm_mmu_gva_to_gpa_read(struct kvm_vcpu *vcpu, gva_t gva,
+			      struct x86_exception *exception)
 {
 	u32 access = (kvm_x86_ops->get_cpl(vcpu) == 3) ? PFERR_USER_MASK : 0;
-	return vcpu->arch.walk_mmu->gva_to_gpa(vcpu, gva, access, error);
+	return vcpu->arch.walk_mmu->gva_to_gpa(vcpu, gva, access, exception);
 }
 
- gpa_t kvm_mmu_gva_to_gpa_fetch(struct kvm_vcpu *vcpu, gva_t gva, u32 *error)
+ gpa_t kvm_mmu_gva_to_gpa_fetch(struct kvm_vcpu *vcpu, gva_t gva,
+				struct x86_exception *exception)
 {
 	u32 access = (kvm_x86_ops->get_cpl(vcpu) == 3) ? PFERR_USER_MASK : 0;
 	access |= PFERR_FETCH_MASK;
-	return vcpu->arch.walk_mmu->gva_to_gpa(vcpu, gva, access, error);
+	return vcpu->arch.walk_mmu->gva_to_gpa(vcpu, gva, access, exception);
 }
 
-gpa_t kvm_mmu_gva_to_gpa_write(struct kvm_vcpu *vcpu, gva_t gva, u32 *error)
+gpa_t kvm_mmu_gva_to_gpa_write(struct kvm_vcpu *vcpu, gva_t gva,
+			       struct x86_exception *exception)
 {
 	u32 access = (kvm_x86_ops->get_cpl(vcpu) == 3) ? PFERR_USER_MASK : 0;
 	access |= PFERR_WRITE_MASK;
-	return vcpu->arch.walk_mmu->gva_to_gpa(vcpu, gva, access, error);
+	return vcpu->arch.walk_mmu->gva_to_gpa(vcpu, gva, access, exception);
 }
 
 /* uses this to access any guest's mapped memory without checking CPL */
-gpa_t kvm_mmu_gva_to_gpa_system(struct kvm_vcpu *vcpu, gva_t gva, u32 *error)
+gpa_t kvm_mmu_gva_to_gpa_system(struct kvm_vcpu *vcpu, gva_t gva,
+				struct x86_exception *exception)
 {
-	return vcpu->arch.walk_mmu->gva_to_gpa(vcpu, gva, 0, error);
+	return vcpu->arch.walk_mmu->gva_to_gpa(vcpu, gva, 0, exception);
 }
 
 static int kvm_read_guest_virt_helper(gva_t addr, void *val, unsigned int bytes,
 				      struct kvm_vcpu *vcpu, u32 access,
-				      u32 *error)
+				      struct x86_exception *exception)
 {
 	void *data = val;
 	int r = X86EMUL_CONTINUE;
 
 	while (bytes) {
 		gpa_t gpa = vcpu->arch.walk_mmu->gva_to_gpa(vcpu, addr, access,
-							    error);
+							    exception);
 		unsigned offset = addr & (PAGE_SIZE-1);
 		unsigned toread = min(bytes, (unsigned)PAGE_SIZE - offset);
 		int ret;
 
-		if (gpa == UNMAPPED_GVA) {
-			r = X86EMUL_PROPAGATE_FAULT;
-			goto out;
-		}
+		if (gpa == UNMAPPED_GVA)
+			return X86EMUL_PROPAGATE_FAULT;
 		ret = kvm_read_guest(vcpu->kvm, gpa, data, toread);
 		if (ret < 0) {
 			r = X86EMUL_IO_NEEDED;
@@ -3630,31 +3682,35 @@ out:
 
 /* used for instruction fetching */
 static int kvm_fetch_guest_virt(gva_t addr, void *val, unsigned int bytes,
-				struct kvm_vcpu *vcpu, u32 *error)
+				struct kvm_vcpu *vcpu,
+				struct x86_exception *exception)
 {
 	u32 access = (kvm_x86_ops->get_cpl(vcpu) == 3) ? PFERR_USER_MASK : 0;
 	return kvm_read_guest_virt_helper(addr, val, bytes, vcpu,
-					  access | PFERR_FETCH_MASK, error);
+					  access | PFERR_FETCH_MASK,
+					  exception);
 }
 
 static int kvm_read_guest_virt(gva_t addr, void *val, unsigned int bytes,
-			       struct kvm_vcpu *vcpu, u32 *error)
+			       struct kvm_vcpu *vcpu,
+			       struct x86_exception *exception)
 {
 	u32 access = (kvm_x86_ops->get_cpl(vcpu) == 3) ? PFERR_USER_MASK : 0;
 	return kvm_read_guest_virt_helper(addr, val, bytes, vcpu, access,
-					  error);
+					  exception);
 }
 
 static int kvm_read_guest_virt_system(gva_t addr, void *val, unsigned int bytes,
-			       struct kvm_vcpu *vcpu, u32 *error)
+				      struct kvm_vcpu *vcpu,
+				      struct x86_exception *exception)
 {
-	return kvm_read_guest_virt_helper(addr, val, bytes, vcpu, 0, error);
+	return kvm_read_guest_virt_helper(addr, val, bytes, vcpu, 0, exception);
 }
 
 static int kvm_write_guest_virt_system(gva_t addr, void *val,
 				       unsigned int bytes,
 				       struct kvm_vcpu *vcpu,
-				       u32 *error)
+				       struct x86_exception *exception)
 {
 	void *data = val;
 	int r = X86EMUL_CONTINUE;
@@ -3662,15 +3718,13 @@ static int kvm_write_guest_virt_system(g
 	while (bytes) {
 		gpa_t gpa =  vcpu->arch.walk_mmu->gva_to_gpa(vcpu, addr,
 							     PFERR_WRITE_MASK,
-							     error);
+							     exception);
 		unsigned offset = addr & (PAGE_SIZE-1);
 		unsigned towrite = min(bytes, (unsigned)PAGE_SIZE - offset);
 		int ret;
 
-		if (gpa == UNMAPPED_GVA) {
-			r = X86EMUL_PROPAGATE_FAULT;
-			goto out;
-		}
+		if (gpa == UNMAPPED_GVA)
+			return X86EMUL_PROPAGATE_FAULT;
 		ret = kvm_write_guest(vcpu->kvm, gpa, data, towrite);
 		if (ret < 0) {
 			r = X86EMUL_IO_NEEDED;
@@ -3688,7 +3742,7 @@ out:
 static int emulator_read_emulated(unsigned long addr,
 				  void *val,
 				  unsigned int bytes,
-				  unsigned int *error_code,
+				  struct x86_exception *exception,
 				  struct kvm_vcpu *vcpu)
 {
 	gpa_t                 gpa;
@@ -3701,7 +3755,7 @@ static int emulator_read_emulated(unsign
 		return X86EMUL_CONTINUE;
 	}
 
-	gpa = kvm_mmu_gva_to_gpa_read(vcpu, addr, error_code);
+	gpa = kvm_mmu_gva_to_gpa_read(vcpu, addr, exception);
 
 	if (gpa == UNMAPPED_GVA)
 		return X86EMUL_PROPAGATE_FAULT;
@@ -3710,8 +3764,8 @@ static int emulator_read_emulated(unsign
 	if ((gpa & PAGE_MASK) == APIC_DEFAULT_PHYS_BASE)
 		goto mmio;
 
-	if (kvm_read_guest_virt(addr, val, bytes, vcpu, NULL)
-				== X86EMUL_CONTINUE)
+	if (kvm_read_guest_virt(addr, val, bytes, vcpu, exception)
+	    == X86EMUL_CONTINUE)
 		return X86EMUL_CONTINUE;
 
 mmio:
@@ -3735,7 +3789,7 @@ mmio:
 }
 
 int emulator_write_phys(struct kvm_vcpu *vcpu, gpa_t gpa,
-			  const void *val, int bytes)
+			const void *val, int bytes)
 {
 	int ret;
 
@@ -3749,12 +3803,12 @@ int emulator_write_phys(struct kvm_vcpu
 static int emulator_write_emulated_onepage(unsigned long addr,
 					   const void *val,
 					   unsigned int bytes,
-					   unsigned int *error_code,
+					   struct x86_exception *exception,
 					   struct kvm_vcpu *vcpu)
 {
 	gpa_t                 gpa;
 
-	gpa = kvm_mmu_gva_to_gpa_write(vcpu, addr, error_code);
+	gpa = kvm_mmu_gva_to_gpa_write(vcpu, addr, exception);
 
 	if (gpa == UNMAPPED_GVA)
 		return X86EMUL_PROPAGATE_FAULT;
@@ -3787,7 +3841,7 @@ mmio:
 int emulator_write_emulated(unsigned long addr,
 			    const void *val,
 			    unsigned int bytes,
-			    unsigned int *error_code,
+			    struct x86_exception *exception,
 			    struct kvm_vcpu *vcpu)
 {
 	/* Crossing a page boundary? */
@@ -3795,7 +3849,7 @@ int emulator_write_emulated(unsigned lon
 		int rc, now;
 
 		now = -addr & ~PAGE_MASK;
-		rc = emulator_write_emulated_onepage(addr, val, now, error_code,
+		rc = emulator_write_emulated_onepage(addr, val, now, exception,
 						     vcpu);
 		if (rc != X86EMUL_CONTINUE)
 			return rc;
@@ -3803,7 +3857,7 @@ int emulator_write_emulated(unsigned lon
 		val += now;
 		bytes -= now;
 	}
-	return emulator_write_emulated_onepage(addr, val, bytes, error_code,
+	return emulator_write_emulated_onepage(addr, val, bytes, exception,
 					       vcpu);
 }
 
@@ -3821,7 +3875,7 @@ static int emulator_cmpxchg_emulated(uns
 				     const void *old,
 				     const void *new,
 				     unsigned int bytes,
-				     unsigned int *error_code,
+				     struct x86_exception *exception,
 				     struct kvm_vcpu *vcpu)
 {
 	gpa_t gpa;
@@ -3879,7 +3933,7 @@ static int emulator_cmpxchg_emulated(uns
 emul_write:
 	printk_once(KERN_WARNING "kvm: emulating exchange as write\n");
 
-	return emulator_write_emulated(addr, new, bytes, error_code, vcpu);
+	return emulator_write_emulated(addr, new, bytes, exception, vcpu);
 }
 
 static int kernel_pio(struct kvm_vcpu *vcpu, void *pd)
@@ -3904,7 +3958,7 @@ static int emulator_pio_in_emulated(int
 	if (vcpu->arch.pio.count)
 		goto data_avail;
 
-	trace_kvm_pio(0, port, size, 1);
+	trace_kvm_pio(0, port, size, count);
 
 	vcpu->arch.pio.port = port;
 	vcpu->arch.pio.in = 1;
@@ -3932,7 +3986,7 @@ static int emulator_pio_out_emulated(int
 			      const void *val, unsigned int count,
 			      struct kvm_vcpu *vcpu)
 {
-	trace_kvm_pio(1, port, size, 1);
+	trace_kvm_pio(1, port, size, count);
 
 	vcpu->arch.pio.port = port;
 	vcpu->arch.pio.in = 0;
@@ -3973,13 +4027,15 @@ int kvm_emulate_wbinvd(struct kvm_vcpu *
 		return X86EMUL_CONTINUE;
 
 	if (kvm_x86_ops->has_wbinvd_exit()) {
-		preempt_disable();
+		int cpu = get_cpu();
+
+		cpumask_set_cpu(cpu, vcpu->arch.wbinvd_dirty_mask);
 		smp_call_function_many(vcpu->arch.wbinvd_dirty_mask,
 				wbinvd_ipi, NULL, 1);
-		preempt_enable();
+		put_cpu();
 		cpumask_clear(vcpu->arch.wbinvd_dirty_mask);
-	}
-	wbinvd();
+	} else
+		wbinvd();
 	return X86EMUL_CONTINUE;
 }
 EXPORT_SYMBOL_GPL(kvm_emulate_wbinvd);
@@ -4019,7 +4075,7 @@ static unsigned long emulator_get_cr(int
 		value = vcpu->arch.cr2;
 		break;
 	case 3:
-		value = vcpu->arch.cr3;
+		value = kvm_read_cr3(vcpu);
 		break;
 	case 4:
 		value = kvm_read_cr4(vcpu);
@@ -4053,7 +4109,7 @@ static int emulator_set_cr(int cr, unsig
 		res = kvm_set_cr4(vcpu, mk_cr_64(kvm_read_cr4(vcpu), val));
 		break;
 	case 8:
-		res = __kvm_set_cr8(vcpu, val & 0xfUL);
+		res = kvm_set_cr8(vcpu, val);
 		break;
 	default:
 		vcpu_printf(vcpu, "%s: unexpected cr %u\n", __func__, cr);
@@ -4206,12 +4262,13 @@ static void toggle_interruptibility(stru
 static void inject_emulated_exception(struct kvm_vcpu *vcpu)
 {
 	struct x86_emulate_ctxt *ctxt = &vcpu->arch.emulate_ctxt;
-	if (ctxt->exception == PF_VECTOR)
-		kvm_propagate_fault(vcpu);
-	else if (ctxt->error_code_valid)
-		kvm_queue_exception_e(vcpu, ctxt->exception, ctxt->error_code);
+	if (ctxt->exception.vector == PF_VECTOR)
+		kvm_propagate_fault(vcpu, &ctxt->exception);
+	else if (ctxt->exception.error_code_valid)
+		kvm_queue_exception_e(vcpu, ctxt->exception.vector,
+				      ctxt->exception.error_code);
 	else
-		kvm_queue_exception(vcpu, ctxt->exception);
+		kvm_queue_exception(vcpu, ctxt->exception.vector);
 }
 
 static void init_emulate_ctxt(struct kvm_vcpu *vcpu)
@@ -4267,13 +4324,19 @@ EXPORT_SYMBOL_GPL(kvm_inject_realmode_in
 
 static int handle_emulation_failure(struct kvm_vcpu *vcpu)
 {
+	int r = EMULATE_DONE;
+
 	++vcpu->stat.insn_emulation_fail;
 	trace_kvm_emulate_insn_failed(vcpu);
-	vcpu->run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
-	vcpu->run->internal.suberror = KVM_INTERNAL_ERROR_EMULATION;
-	vcpu->run->internal.ndata = 0;
+	if (!is_guest_mode(vcpu)) {
+		vcpu->run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
+		vcpu->run->internal.suberror = KVM_INTERNAL_ERROR_EMULATION;
+		vcpu->run->internal.ndata = 0;
+		r = EMULATE_FAIL;
+	}
 	kvm_queue_exception(vcpu, UD_VECTOR);
-	return EMULATE_FAIL;
+
+	return r;
 }
 
 static bool reexecute_instruction(struct kvm_vcpu *vcpu, gva_t gva)
@@ -4302,10 +4365,11 @@ static bool reexecute_instruction(struct
 	return false;
 }
 
-int emulate_instruction(struct kvm_vcpu *vcpu,
-			unsigned long cr2,
-			u16 error_code,
-			int emulation_type)
+int x86_emulate_instruction(struct kvm_vcpu *vcpu,
+			    unsigned long cr2,
+			    int emulation_type,
+			    void *insn,
+			    int insn_len)
 {
 	int r;
 	struct decode_cache *c = &vcpu->arch.emulate_ctxt.decode;
@@ -4323,10 +4387,10 @@ int emulate_instruction(struct kvm_vcpu
 	if (!(emulation_type & EMULTYPE_NO_DECODE)) {
 		init_emulate_ctxt(vcpu);
 		vcpu->arch.emulate_ctxt.interruptibility = 0;
-		vcpu->arch.emulate_ctxt.exception = -1;
+		vcpu->arch.emulate_ctxt.have_exception = false;
 		vcpu->arch.emulate_ctxt.perm_ok = false;
 
-		r = x86_decode_insn(&vcpu->arch.emulate_ctxt);
+		r = x86_decode_insn(&vcpu->arch.emulate_ctxt, insn, insn_len);
 		if (r == X86EMUL_PROPAGATE_FAULT)
 			goto done;
 
@@ -4389,7 +4453,7 @@ restart:
 	}
 
 done:
-	if (vcpu->arch.emulate_ctxt.exception >= 0) {
+	if (vcpu->arch.emulate_ctxt.have_exception) {
 		inject_emulated_exception(vcpu);
 		r = EMULATE_DONE;
 	} else if (vcpu->arch.pio.count) {
@@ -4413,7 +4477,7 @@ done:
 
 	return r;
 }
-EXPORT_SYMBOL_GPL(emulate_instruction);
+EXPORT_SYMBOL_GPL(x86_emulate_instruction);
 
 int kvm_fast_pio_out(struct kvm_vcpu *vcpu, int size, unsigned short port)
 {
@@ -4427,7 +4491,7 @@ EXPORT_SYMBOL_GPL(kvm_fast_pio_out);
 
 static void tsc_bad(void *info)
 {
-	__get_cpu_var(cpu_tsc_khz) = 0;
+	__this_cpu_write(cpu_tsc_khz, 0);
 }
 
 static void tsc_khz_changed(void *data)
@@ -4441,7 +4505,7 @@ static void tsc_khz_changed(void *data)
 		khz = cpufreq_quick_get(raw_smp_processor_id());
 	if (!khz)
 		khz = tsc_khz;
-	__get_cpu_var(cpu_tsc_khz) = khz;
+	__this_cpu_write(cpu_tsc_khz, khz);
 }
 
 static int kvmclock_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
@@ -4653,7 +4717,6 @@ int kvm_arch_init(void *opaque)
 
 	kvm_x86_ops = ops;
 	kvm_mmu_set_nonpresent_ptes(0ull, 0ull);
-	kvm_mmu_set_base_ptes(PT_PRESENT_MASK);
 	kvm_mmu_set_mask_ptes(PT_USER_MASK, PT_ACCESSED_MASK,
 			PT_DIRTY_MASK, PT64_NX_MASK, 0);
 
@@ -5116,6 +5179,12 @@ static int vcpu_enter_guest(struct kvm_v
 			vcpu->fpu_active = 0;
 			kvm_x86_ops->fpu_deactivate(vcpu);
 		}
+		if (kvm_check_request(KVM_REQ_APF_HALT, vcpu)) {
+			/* Page is swapped out. Do synthetic halt */
+			vcpu->arch.apf.halted = true;
+			r = 1;
+			goto out;
+		}
 	}
 
 	r = kvm_mmu_reload(vcpu);
@@ -5244,7 +5313,8 @@ static int __vcpu_run(struct kvm_vcpu *v
 
 	r = 1;
 	while (r > 0) {
-		if (vcpu->arch.mp_state == KVM_MP_STATE_RUNNABLE)
+		if (vcpu->arch.mp_state == KVM_MP_STATE_RUNNABLE &&
+		    !vcpu->arch.apf.halted)
 			r = vcpu_enter_guest(vcpu);
 		else {
 			srcu_read_unlock(&kvm->srcu, vcpu->srcu_idx);
@@ -5257,6 +5327,7 @@ static int __vcpu_run(struct kvm_vcpu *v
 					vcpu->arch.mp_state =
 						KVM_MP_STATE_RUNNABLE;
 				case KVM_MP_STATE_RUNNABLE:
+					vcpu->arch.apf.halted = false;
 					break;
 				case KVM_MP_STATE_SIPI_RECEIVED:
 				default:
@@ -5278,6 +5349,9 @@ static int __vcpu_run(struct kvm_vcpu *v
 			vcpu->run->exit_reason = KVM_EXIT_INTR;
 			++vcpu->stat.request_irq_exits;
 		}
+
+		kvm_check_async_pf_completion(vcpu);
+
 		if (signal_pending(current)) {
 			r = -EINTR;
 			vcpu->run->exit_reason = KVM_EXIT_INTR;
@@ -5302,6 +5376,9 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_v
 	int r;
 	sigset_t sigsaved;
 
+	if (!tsk_used_math(current) && init_fpu(current))
+		return -ENOMEM;
+
 	if (vcpu->sigset_active)
 		sigprocmask(SIG_SETMASK, &vcpu->sigset, &sigsaved);
 
@@ -5313,8 +5390,12 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_v
 	}
 
 	/* re-sync apic's tpr */
-	if (!irqchip_in_kernel(vcpu->kvm))
-		kvm_set_cr8(vcpu, kvm_run->cr8);
+	if (!irqchip_in_kernel(vcpu->kvm)) {
+		if (kvm_set_cr8(vcpu, kvm_run->cr8) != 0) {
+			r = -EINVAL;
+			goto out;
+		}
+	}
 
 	if (vcpu->arch.pio.count || vcpu->mmio_needed) {
 		if (vcpu->mmio_needed) {
@@ -5323,7 +5404,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_v
 			vcpu->mmio_needed = 0;
 		}
 		vcpu->srcu_idx = srcu_read_lock(&vcpu->kvm->srcu);
-		r = emulate_instruction(vcpu, 0, 0, EMULTYPE_NO_DECODE);
+		r = emulate_instruction(vcpu, EMULTYPE_NO_DECODE);
 		srcu_read_unlock(&vcpu->kvm->srcu, vcpu->srcu_idx);
 		if (r != EMULATE_DONE) {
 			r = 0;
@@ -5436,7 +5517,7 @@ int kvm_arch_vcpu_ioctl_get_sregs(struct
 
 	sregs->cr0 = kvm_read_cr0(vcpu);
 	sregs->cr2 = vcpu->arch.cr2;
-	sregs->cr3 = vcpu->arch.cr3;
+	sregs->cr3 = kvm_read_cr3(vcpu);
 	sregs->cr4 = kvm_read_cr4(vcpu);
 	sregs->cr8 = kvm_get_cr8(vcpu);
 	sregs->efer = vcpu->arch.efer;
@@ -5504,8 +5585,9 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct
 	kvm_x86_ops->set_gdt(vcpu, &dt);
 
 	vcpu->arch.cr2 = sregs->cr2;
-	mmu_reset_needed |= vcpu->arch.cr3 != sregs->cr3;
+	mmu_reset_needed |= kvm_read_cr3(vcpu) != sregs->cr3;
 	vcpu->arch.cr3 = sregs->cr3;
+	__set_bit(VCPU_EXREG_CR3, (ulong *)&vcpu->arch.regs_avail);
 
 	kvm_set_cr8(vcpu, sregs->cr8);
 
@@ -5522,7 +5604,7 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct
 	if (sregs->cr4 & X86_CR4_OSXSAVE)
 		update_cpuid(vcpu);
 	if (!is_long_mode(vcpu) && is_pae(vcpu)) {
-		load_pdptrs(vcpu, vcpu->arch.walk_mmu, vcpu->arch.cr3);
+		load_pdptrs(vcpu, vcpu->arch.walk_mmu, kvm_read_cr3(vcpu));
 		mmu_reset_needed = 1;
 	}
 
@@ -5773,6 +5855,8 @@ free_vcpu:
 
 void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu)
 {
+	vcpu->arch.apf.msr_val = 0;
+
 	vcpu_load(vcpu);
 	kvm_mmu_unload(vcpu);
 	vcpu_put(vcpu);
@@ -5792,6 +5876,11 @@ int kvm_arch_vcpu_reset(struct kvm_vcpu
 	vcpu->arch.dr7 = DR7_FIXED_1;
 
 	kvm_make_request(KVM_REQ_EVENT, vcpu);
+	vcpu->arch.apf.msr_val = 0;
+
+	kvm_clear_async_pf_completion_queue(vcpu);
+	kvm_async_pf_hash_reset(vcpu);
+	vcpu->arch.apf.halted = false;
 
 	return kvm_x86_ops->vcpu_reset(vcpu);
 }
@@ -5881,6 +5970,8 @@ int kvm_arch_vcpu_init(struct kvm_vcpu *
 	if (!zalloc_cpumask_var(&vcpu->arch.wbinvd_dirty_mask, GFP_KERNEL))
 		goto fail_free_mce_banks;
 
+	kvm_async_pf_hash_reset(vcpu);
+
 	return 0;
 fail_free_mce_banks:
 	kfree(vcpu->arch.mce_banks);
@@ -5906,13 +5997,8 @@ void kvm_arch_vcpu_uninit(struct kvm_vcp
 	free_page((unsigned long)vcpu->arch.pio_data);
 }
 
-struct  kvm *kvm_arch_create_vm(void)
+int kvm_arch_init_vm(struct kvm *kvm)
 {
-	struct kvm *kvm = kzalloc(sizeof(struct kvm), GFP_KERNEL);
-
-	if (!kvm)
-		return ERR_PTR(-ENOMEM);
-
 	INIT_LIST_HEAD(&kvm->arch.active_mmu_pages);
 	INIT_LIST_HEAD(&kvm->arch.assigned_dev_head);
 
@@ -5921,7 +6007,7 @@ struct  kvm *kvm_arch_create_vm(void)
 
 	spin_lock_init(&kvm->arch.tsc_write_lock);
 
-	return kvm;
+	return 0;
 }
 
 static void kvm_unload_vcpu_mmu(struct kvm_vcpu *vcpu)
@@ -5939,8 +6025,10 @@ static void kvm_free_vcpus(struct kvm *k
 	/*
 	 * Unpin any mmu pages first.
 	 */
-	kvm_for_each_vcpu(i, vcpu, kvm)
+	kvm_for_each_vcpu(i, vcpu, kvm) {
+		kvm_clear_async_pf_completion_queue(vcpu);
 		kvm_unload_vcpu_mmu(vcpu);
+	}
 	kvm_for_each_vcpu(i, vcpu, kvm)
 		kvm_arch_vcpu_free(vcpu);
 
@@ -5964,13 +6052,10 @@ void kvm_arch_destroy_vm(struct kvm *kvm
 	kfree(kvm->arch.vpic);
 	kfree(kvm->arch.vioapic);
 	kvm_free_vcpus(kvm);
-	kvm_free_physmem(kvm);
 	if (kvm->arch.apic_access_page)
 		put_page(kvm->arch.apic_access_page);
 	if (kvm->arch.ept_identity_pagetable)
 		put_page(kvm->arch.ept_identity_pagetable);
-	cleanup_srcu_struct(&kvm->srcu);
-	kfree(kvm);
 }
 
 int kvm_arch_prepare_memory_region(struct kvm *kvm,
@@ -6051,7 +6136,9 @@ void kvm_arch_flush_shadow(struct kvm *k
 
 int kvm_arch_vcpu_runnable(struct kvm_vcpu *vcpu)
 {
-	return vcpu->arch.mp_state == KVM_MP_STATE_RUNNABLE
+	return (vcpu->arch.mp_state == KVM_MP_STATE_RUNNABLE &&
+		!vcpu->arch.apf.halted)
+		|| !list_empty_careful(&vcpu->async_pf.done)
 		|| vcpu->arch.mp_state == KVM_MP_STATE_SIPI_RECEIVED
 		|| vcpu->arch.nmi_pending ||
 		(kvm_arch_interrupt_allowed(vcpu) &&
@@ -6110,6 +6197,147 @@ void kvm_set_rflags(struct kvm_vcpu *vcp
 }
 EXPORT_SYMBOL_GPL(kvm_set_rflags);
 
+void kvm_arch_async_page_ready(struct kvm_vcpu *vcpu, struct kvm_async_pf *work)
+{
+	int r;
+
+	if ((vcpu->arch.mmu.direct_map != work->arch.direct_map) ||
+	      is_error_page(work->page))
+		return;
+
+	r = kvm_mmu_reload(vcpu);
+	if (unlikely(r))
+		return;
+
+	if (!vcpu->arch.mmu.direct_map &&
+	      work->arch.cr3 != vcpu->arch.mmu.get_cr3(vcpu))
+		return;
+
+	vcpu->arch.mmu.page_fault(vcpu, work->gva, 0, true);
+}
+
+static inline u32 kvm_async_pf_hash_fn(gfn_t gfn)
+{
+	return hash_32(gfn & 0xffffffff, order_base_2(ASYNC_PF_PER_VCPU));
+}
+
+static inline u32 kvm_async_pf_next_probe(u32 key)
+{
+	return (key + 1) & (roundup_pow_of_two(ASYNC_PF_PER_VCPU) - 1);
+}
+
+static void kvm_add_async_pf_gfn(struct kvm_vcpu *vcpu, gfn_t gfn)
+{
+	u32 key = kvm_async_pf_hash_fn(gfn);
+
+	while (vcpu->arch.apf.gfns[key] != ~0)
+		key = kvm_async_pf_next_probe(key);
+
+	vcpu->arch.apf.gfns[key] = gfn;
+}
+
+static u32 kvm_async_pf_gfn_slot(struct kvm_vcpu *vcpu, gfn_t gfn)
+{
+	int i;
+	u32 key = kvm_async_pf_hash_fn(gfn);
+
+	for (i = 0; i < roundup_pow_of_two(ASYNC_PF_PER_VCPU) &&
+		     (vcpu->arch.apf.gfns[key] != gfn &&
+		      vcpu->arch.apf.gfns[key] != ~0); i++)
+		key = kvm_async_pf_next_probe(key);
+
+	return key;
+}
+
+bool kvm_find_async_pf_gfn(struct kvm_vcpu *vcpu, gfn_t gfn)
+{
+	return vcpu->arch.apf.gfns[kvm_async_pf_gfn_slot(vcpu, gfn)] == gfn;
+}
+
+static void kvm_del_async_pf_gfn(struct kvm_vcpu *vcpu, gfn_t gfn)
+{
+	u32 i, j, k;
+
+	i = j = kvm_async_pf_gfn_slot(vcpu, gfn);
+	while (true) {
+		vcpu->arch.apf.gfns[i] = ~0;
+		do {
+			j = kvm_async_pf_next_probe(j);
+			if (vcpu->arch.apf.gfns[j] == ~0)
+				return;
+			k = kvm_async_pf_hash_fn(vcpu->arch.apf.gfns[j]);
+			/*
+			 * k lies cyclically in ]i,j]
+			 * |    i.k.j |
+			 * |....j i.k.| or  |.k..j i...|
+			 */
+		} while ((i <= j) ? (i < k && k <= j) : (i < k || k <= j));
+		vcpu->arch.apf.gfns[i] = vcpu->arch.apf.gfns[j];
+		i = j;
+	}
+}
+
+static int apf_put_user(struct kvm_vcpu *vcpu, u32 val)
+{
+
+	return kvm_write_guest_cached(vcpu->kvm, &vcpu->arch.apf.data, &val,
+				      sizeof(val));
+}
+
+void kvm_arch_async_page_not_present(struct kvm_vcpu *vcpu,
+				     struct kvm_async_pf *work)
+{
+	struct x86_exception fault;
+
+	trace_kvm_async_pf_not_present(work->arch.token, work->gva);
+	kvm_add_async_pf_gfn(vcpu, work->arch.gfn);
+
+	if (!(vcpu->arch.apf.msr_val & KVM_ASYNC_PF_ENABLED) ||
+	    (vcpu->arch.apf.send_user_only &&
+	     kvm_x86_ops->get_cpl(vcpu) == 0))
+		kvm_make_request(KVM_REQ_APF_HALT, vcpu);
+	else if (!apf_put_user(vcpu, KVM_PV_REASON_PAGE_NOT_PRESENT)) {
+		fault.vector = PF_VECTOR;
+		fault.error_code_valid = true;
+		fault.error_code = 0;
+		fault.nested_page_fault = false;
+		fault.address = work->arch.token;
+		kvm_inject_page_fault(vcpu, &fault);
+	}
+}
+
+void kvm_arch_async_page_present(struct kvm_vcpu *vcpu,
+				 struct kvm_async_pf *work)
+{
+	struct x86_exception fault;
+
+	trace_kvm_async_pf_ready(work->arch.token, work->gva);
+	if (is_error_page(work->page))
+		work->arch.token = ~0; /* broadcast wakeup */
+	else
+		kvm_del_async_pf_gfn(vcpu, work->arch.gfn);
+
+	if ((vcpu->arch.apf.msr_val & KVM_ASYNC_PF_ENABLED) &&
+	    !apf_put_user(vcpu, KVM_PV_REASON_PAGE_READY)) {
+		fault.vector = PF_VECTOR;
+		fault.error_code_valid = true;
+		fault.error_code = 0;
+		fault.nested_page_fault = false;
+		fault.address = work->arch.token;
+		kvm_inject_page_fault(vcpu, &fault);
+	}
+	vcpu->arch.apf.halted = false;
+}
+
+bool kvm_arch_can_inject_async_page_present(struct kvm_vcpu *vcpu)
+{
+	if (!(vcpu->arch.apf.msr_val & KVM_ASYNC_PF_ENABLED))
+		return true;
+	else
+		return !kvm_event_needs_reinjection(vcpu) &&
+			kvm_x86_ops->interrupt_allowed(vcpu);
+}
+
 EXPORT_TRACEPOINT_SYMBOL_GPL(kvm_exit);
 EXPORT_TRACEPOINT_SYMBOL_GPL(kvm_inj_virq);
 EXPORT_TRACEPOINT_SYMBOL_GPL(kvm_page_fault);
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/lguest/boot.c linux-libre-2.6.38-gnu1/arch/x86/lguest/boot.c
--- linux-libre-2.6.37-gnu1/arch/x86/lguest/boot.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/lguest/boot.c	2011-03-14 21:20:32.000000000 -0400
@@ -824,7 +824,7 @@ static void __init lguest_init_IRQ(void)
 
 	for (i = FIRST_EXTERNAL_VECTOR; i < NR_VECTORS; i++) {
 		/* Some systems map "vectors" to interrupts weirdly.  Not us! */
-		__get_cpu_var(vector_irq)[i] = i - FIRST_EXTERNAL_VECTOR;
+		__this_cpu_write(vector_irq[i], i - FIRST_EXTERNAL_VECTOR);
 		if (i != SYSCALL_VECTOR)
 			set_intr_gate(i, interrupt[i - FIRST_EXTERNAL_VECTOR]);
 	}
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/lguest/i386_head.S linux-libre-2.6.38-gnu1/arch/x86/lguest/i386_head.S
--- linux-libre-2.6.37-gnu1/arch/x86/lguest/i386_head.S	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/lguest/i386_head.S	2011-03-14 21:20:32.000000000 -0400
@@ -4,7 +4,6 @@
 #include <asm/asm-offsets.h>
 #include <asm/thread_info.h>
 #include <asm/processor-flags.h>
-#include <asm/pgtable.h>
 
 /*G:020
  * Our story starts with the kernel booting into startup_32 in
@@ -38,113 +37,9 @@ ENTRY(lguest_entry)
 	/* Set up the initial stack so we can run C code. */
 	movl $(init_thread_union+THREAD_SIZE),%esp
 
-	call init_pagetables
-
 	/* Jumps are relative: we're running __PAGE_OFFSET too low. */
 	jmp lguest_init+__PAGE_OFFSET
 
-/*
- * Initialize page tables.  This creates a PDE and a set of page
- * tables, which are located immediately beyond __brk_base.  The variable
- * _brk_end is set up to point to the first "safe" location.
- * Mappings are created both at virtual address 0 (identity mapping)
- * and PAGE_OFFSET for up to _end.
- *
- * FIXME: This code is taken verbatim from arch/x86/kernel/head_32.S: they
- * don't have a stack at this point, so we can't just use call and ret.
- */
-init_pagetables:
-#if PTRS_PER_PMD > 1
-#define PAGE_TABLE_SIZE(pages) (((pages) / PTRS_PER_PMD) + PTRS_PER_PGD)
-#else
-#define PAGE_TABLE_SIZE(pages) ((pages) / PTRS_PER_PGD)
-#endif
-#define pa(X) ((X) - __PAGE_OFFSET)
-
-/* Enough space to fit pagetables for the low memory linear map */
-MAPPING_BEYOND_END = \
-	PAGE_TABLE_SIZE(((1<<32) - __PAGE_OFFSET) >> PAGE_SHIFT) << PAGE_SHIFT
-#ifdef CONFIG_X86_PAE
-
-	/*
-	 * In PAE mode initial_page_table is statically defined to contain
-	 * enough entries to cover the VMSPLIT option (that is the top 1, 2 or 3
-	 * entries). The identity mapping is handled by pointing two PGD entries
-	 * to the first kernel PMD.
-	 *
-	 * Note the upper half of each PMD or PTE are always zero at this stage.
-	 */
-
-#define KPMDS (((-__PAGE_OFFSET) >> 30) & 3) /* Number of kernel PMDs */
-
-	xorl %ebx,%ebx				/* %ebx is kept at zero */
-
-	movl $pa(__brk_base), %edi
-	movl $pa(initial_pg_pmd), %edx
-	movl $PTE_IDENT_ATTR, %eax
-10:
-	leal PDE_IDENT_ATTR(%edi),%ecx		/* Create PMD entry */
-	movl %ecx,(%edx)			/* Store PMD entry */
-						/* Upper half already zero */
-	addl $8,%edx
-	movl $512,%ecx
-11:
-	stosl
-	xchgl %eax,%ebx
-	stosl
-	xchgl %eax,%ebx
-	addl $0x1000,%eax
-	loop 11b
-
-	/*
-	 * End condition: we must map up to the end + MAPPING_BEYOND_END.
-	 */
-	movl $pa(_end) + MAPPING_BEYOND_END + PTE_IDENT_ATTR, %ebp
-	cmpl %ebp,%eax
-	jb 10b
-1:
-	addl $__PAGE_OFFSET, %edi
-	movl %edi, pa(_brk_end)
-	shrl $12, %eax
-	movl %eax, pa(max_pfn_mapped)
-
-	/* Do early initialization of the fixmap area */
-	movl $pa(initial_pg_fixmap)+PDE_IDENT_ATTR,%eax
-	movl %eax,pa(initial_pg_pmd+0x1000*KPMDS-8)
-#else	/* Not PAE */
-
-page_pde_offset = (__PAGE_OFFSET >> 20);
-
-	movl $pa(__brk_base), %edi
-	movl $pa(initial_page_table), %edx
-	movl $PTE_IDENT_ATTR, %eax
-10:
-	leal PDE_IDENT_ATTR(%edi),%ecx		/* Create PDE entry */
-	movl %ecx,(%edx)			/* Store identity PDE entry */
-	movl %ecx,page_pde_offset(%edx)		/* Store kernel PDE entry */
-	addl $4,%edx
-	movl $1024, %ecx
-11:
-	stosl
-	addl $0x1000,%eax
-	loop 11b
-	/*
-	 * End condition: we must map up to the end + MAPPING_BEYOND_END.
-	 */
-	movl $pa(_end) + MAPPING_BEYOND_END + PTE_IDENT_ATTR, %ebp
-	cmpl %ebp,%eax
-	jb 10b
-	addl $__PAGE_OFFSET, %edi
-	movl %edi, pa(_brk_end)
-	shrl $12, %eax
-	movl %eax, pa(max_pfn_mapped)
-
-	/* Do early initialization of the fixmap area */
-	movl $pa(initial_pg_fixmap)+PDE_IDENT_ATTR,%eax
-	movl %eax,pa(initial_page_table+0xffc)
-#endif
-	ret
-
 /*G:055
  * We create a macro which puts the assembler code between lgstart_ and lgend_
  * markers.  These templates are put in the .text section: they can't be
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/lguest/Kconfig linux-libre-2.6.38-gnu1/arch/x86/lguest/Kconfig
--- linux-libre-2.6.37-gnu1/arch/x86/lguest/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/lguest/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -2,6 +2,7 @@ config LGUEST_GUEST
 	bool "Lguest guest support"
 	select PARAVIRT
 	depends on X86_32
+	select VIRTUALIZATION
 	select VIRTIO
 	select VIRTIO_RING
 	select VIRTIO_CONSOLE
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/lib/delay.c linux-libre-2.6.38-gnu1/arch/x86/lib/delay.c
--- linux-libre-2.6.37-gnu1/arch/x86/lib/delay.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/lib/delay.c	2011-03-14 21:20:32.000000000 -0400
@@ -121,7 +121,7 @@ inline void __const_udelay(unsigned long
 	asm("mull %%edx"
 		:"=d" (xloops), "=&a" (d0)
 		:"1" (xloops), "0"
-		(cpu_data(raw_smp_processor_id()).loops_per_jiffy * (HZ/4)));
+		(this_cpu_read(cpu_info.loops_per_jiffy) * (HZ/4)));
 
 	__delay(++xloops);
 }
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/mm/amdtopology_64.c linux-libre-2.6.38-gnu1/arch/x86/mm/amdtopology_64.c
--- linux-libre-2.6.37-gnu1/arch/x86/mm/amdtopology_64.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/mm/amdtopology_64.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,294 @@
+/*
+ * AMD NUMA support.
+ * Discover the memory map and associated nodes.
+ *
+ * This version reads it directly from the AMD northbridge.
+ *
+ * Copyright 2002,2003 Andi Kleen, SuSE Labs.
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/string.h>
+#include <linux/module.h>
+#include <linux/nodemask.h>
+#include <linux/memblock.h>
+
+#include <asm/io.h>
+#include <linux/pci_ids.h>
+#include <linux/acpi.h>
+#include <asm/types.h>
+#include <asm/mmzone.h>
+#include <asm/proto.h>
+#include <asm/e820.h>
+#include <asm/pci-direct.h>
+#include <asm/numa.h>
+#include <asm/mpspec.h>
+#include <asm/apic.h>
+#include <asm/amd_nb.h>
+
+static struct bootnode __initdata nodes[8];
+static unsigned char __initdata nodeids[8];
+static nodemask_t __initdata nodes_parsed = NODE_MASK_NONE;
+
+static __init int find_northbridge(void)
+{
+	int num;
+
+	for (num = 0; num < 32; num++) {
+		u32 header;
+
+		header = read_pci_config(0, num, 0, 0x00);
+		if (header != (PCI_VENDOR_ID_AMD | (0x1100<<16)) &&
+			header != (PCI_VENDOR_ID_AMD | (0x1200<<16)) &&
+			header != (PCI_VENDOR_ID_AMD | (0x1300<<16)))
+			continue;
+
+		header = read_pci_config(0, num, 1, 0x00);
+		if (header != (PCI_VENDOR_ID_AMD | (0x1101<<16)) &&
+			header != (PCI_VENDOR_ID_AMD | (0x1201<<16)) &&
+			header != (PCI_VENDOR_ID_AMD | (0x1301<<16)))
+			continue;
+		return num;
+	}
+
+	return -1;
+}
+
+static __init void early_get_boot_cpu_id(void)
+{
+	/*
+	 * need to get the APIC ID of the BSP so can use that to
+	 * create apicid_to_node in amd_scan_nodes()
+	 */
+#ifdef CONFIG_X86_MPPARSE
+	/*
+	 * get boot-time SMP configuration:
+	 */
+	if (smp_found_config)
+		early_get_smp_config();
+#endif
+}
+
+int __init amd_numa_init(unsigned long start_pfn, unsigned long end_pfn)
+{
+	unsigned long start = PFN_PHYS(start_pfn);
+	unsigned long end = PFN_PHYS(end_pfn);
+	unsigned numnodes;
+	unsigned long prevbase;
+	int i, nb, found = 0;
+	u32 nodeid, reg;
+
+	if (!early_pci_allowed())
+		return -1;
+
+	nb = find_northbridge();
+	if (nb < 0)
+		return nb;
+
+	pr_info("Scanning NUMA topology in Northbridge %d\n", nb);
+
+	reg = read_pci_config(0, nb, 0, 0x60);
+	numnodes = ((reg >> 4) & 0xF) + 1;
+	if (numnodes <= 1)
+		return -1;
+
+	pr_info("Number of physical nodes %d\n", numnodes);
+
+	prevbase = 0;
+	for (i = 0; i < 8; i++) {
+		unsigned long base, limit;
+
+		base = read_pci_config(0, nb, 1, 0x40 + i*8);
+		limit = read_pci_config(0, nb, 1, 0x44 + i*8);
+
+		nodeids[i] = nodeid = limit & 7;
+		if ((base & 3) == 0) {
+			if (i < numnodes)
+				pr_info("Skipping disabled node %d\n", i);
+			continue;
+		}
+		if (nodeid >= numnodes) {
+			pr_info("Ignoring excess node %d (%lx:%lx)\n", nodeid,
+				base, limit);
+			continue;
+		}
+
+		if (!limit) {
+			pr_info("Skipping node entry %d (base %lx)\n",
+				i, base);
+			continue;
+		}
+		if ((base >> 8) & 3 || (limit >> 8) & 3) {
+			pr_err("Node %d using interleaving mode %lx/%lx\n",
+			       nodeid, (base >> 8) & 3, (limit >> 8) & 3);
+			return -1;
+		}
+		if (node_isset(nodeid, nodes_parsed)) {
+			pr_info("Node %d already present, skipping\n",
+				nodeid);
+			continue;
+		}
+
+		limit >>= 16;
+		limit <<= 24;
+		limit |= (1<<24)-1;
+		limit++;
+
+		if (limit > end)
+			limit = end;
+		if (limit <= base)
+			continue;
+
+		base >>= 16;
+		base <<= 24;
+
+		if (base < start)
+			base = start;
+		if (limit > end)
+			limit = end;
+		if (limit == base) {
+			pr_err("Empty node %d\n", nodeid);
+			continue;
+		}
+		if (limit < base) {
+			pr_err("Node %d bogus settings %lx-%lx.\n",
+			       nodeid, base, limit);
+			continue;
+		}
+
+		/* Could sort here, but pun for now. Should not happen anyroads. */
+		if (prevbase > base) {
+			pr_err("Node map not sorted %lx,%lx\n",
+			       prevbase, base);
+			return -1;
+		}
+
+		pr_info("Node %d MemBase %016lx Limit %016lx\n",
+			nodeid, base, limit);
+
+		found++;
+
+		nodes[nodeid].start = base;
+		nodes[nodeid].end = limit;
+
+		prevbase = base;
+
+		node_set(nodeid, nodes_parsed);
+	}
+
+	if (!found)
+		return -1;
+	return 0;
+}
+
+#ifdef CONFIG_NUMA_EMU
+static s16 fake_apicid_to_node[MAX_LOCAL_APIC] __initdata = {
+	[0 ... MAX_LOCAL_APIC-1] = NUMA_NO_NODE
+};
+
+void __init amd_get_nodes(struct bootnode *physnodes)
+{
+	int i;
+
+	for_each_node_mask(i, nodes_parsed) {
+		physnodes[i].start = nodes[i].start;
+		physnodes[i].end = nodes[i].end;
+	}
+}
+
+static int __init find_node_by_addr(unsigned long addr)
+{
+	int ret = NUMA_NO_NODE;
+	int i;
+
+	for (i = 0; i < 8; i++)
+		if (addr >= nodes[i].start && addr < nodes[i].end) {
+			ret = i;
+			break;
+		}
+	return ret;
+}
+
+/*
+ * For NUMA emulation, fake proximity domain (_PXM) to node id mappings must be
+ * setup to represent the physical topology but reflect the emulated
+ * environment.  For each emulated node, the real node which it appears on is
+ * found and a fake pxm to nid mapping is created which mirrors the actual
+ * locality.  node_distance() then represents the correct distances between
+ * emulated nodes by using the fake acpi mappings to pxms.
+ */
+void __init amd_fake_nodes(const struct bootnode *nodes, int nr_nodes)
+{
+	unsigned int bits;
+	unsigned int cores;
+	unsigned int apicid_base = 0;
+	int i;
+
+	bits = boot_cpu_data.x86_coreid_bits;
+	cores = 1 << bits;
+	early_get_boot_cpu_id();
+	if (boot_cpu_physical_apicid > 0)
+		apicid_base = boot_cpu_physical_apicid;
+
+	for (i = 0; i < nr_nodes; i++) {
+		int index;
+		int nid;
+		int j;
+
+		nid = find_node_by_addr(nodes[i].start);
+		if (nid == NUMA_NO_NODE)
+			continue;
+
+		index = nodeids[nid] << bits;
+		if (fake_apicid_to_node[index + apicid_base] == NUMA_NO_NODE)
+			for (j = apicid_base; j < cores + apicid_base; j++)
+				fake_apicid_to_node[index + j] = i;
+#ifdef CONFIG_ACPI_NUMA
+		__acpi_map_pxm_to_node(nid, i);
+#endif
+	}
+	memcpy(apicid_to_node, fake_apicid_to_node, sizeof(apicid_to_node));
+}
+#endif /* CONFIG_NUMA_EMU */
+
+int __init amd_scan_nodes(void)
+{
+	unsigned int bits;
+	unsigned int cores;
+	unsigned int apicid_base;
+	int i;
+
+	BUG_ON(nodes_empty(nodes_parsed));
+	node_possible_map = nodes_parsed;
+	memnode_shift = compute_hash_shift(nodes, 8, NULL);
+	if (memnode_shift < 0) {
+		pr_err("No NUMA node hash function found. Contact maintainer\n");
+		return -1;
+	}
+	pr_info("Using node hash shift of %d\n", memnode_shift);
+
+	/* use the coreid bits from early_identify_cpu */
+	bits = boot_cpu_data.x86_coreid_bits;
+	cores = (1<<bits);
+	apicid_base = 0;
+	/* get the APIC ID of the BSP early for systems with apicid lifting */
+	early_get_boot_cpu_id();
+	if (boot_cpu_physical_apicid > 0) {
+		pr_info("BSP APIC ID: %02x\n", boot_cpu_physical_apicid);
+		apicid_base = boot_cpu_physical_apicid;
+	}
+
+	for_each_node_mask(i, node_possible_map) {
+		int j;
+
+		memblock_x86_register_active_regions(i,
+				nodes[i].start >> PAGE_SHIFT,
+				nodes[i].end >> PAGE_SHIFT);
+		for (j = apicid_base; j < cores + apicid_base; j++)
+			apicid_to_node[(i << bits) + j] = i;
+		setup_node_bootmem(i, nodes[i].start, nodes[i].end);
+	}
+
+	numa_init_array();
+	return 0;
+}
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/mm/fault.c linux-libre-2.6.38-gnu1/arch/x86/mm/fault.c
--- linux-libre-2.6.37-gnu1/arch/x86/mm/fault.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/mm/fault.c	2011-03-14 21:20:32.000000000 -0400
@@ -229,15 +229,14 @@ void vmalloc_sync_all(void)
 	for (address = VMALLOC_START & PMD_MASK;
 	     address >= TASK_SIZE && address < FIXADDR_TOP;
 	     address += PMD_SIZE) {
-
-		unsigned long flags;
 		struct page *page;
 
-		spin_lock_irqsave(&pgd_lock, flags);
+		spin_lock(&pgd_lock);
 		list_for_each_entry(page, &pgd_list, lru) {
 			spinlock_t *pgt_lock;
 			pmd_t *ret;
 
+			/* the pgt_lock only for Xen */
 			pgt_lock = &pgd_page_get_mm(page)->page_table_lock;
 
 			spin_lock(pgt_lock);
@@ -247,7 +246,7 @@ void vmalloc_sync_all(void)
 			if (!ret)
 				break;
 		}
-		spin_unlock_irqrestore(&pgd_lock, flags);
+		spin_unlock(&pgd_lock);
 	}
 }
 
@@ -828,6 +827,13 @@ mm_fault_error(struct pt_regs *regs, uns
 	       unsigned long address, unsigned int fault)
 {
 	if (fault & VM_FAULT_OOM) {
+		/* Kernel mode? Handle exceptions or die: */
+		if (!(error_code & PF_USER)) {
+			up_read(&current->mm->mmap_sem);
+			no_context(regs, error_code, address);
+			return;
+		}
+
 		out_of_memory(regs, error_code, address);
 	} else {
 		if (fault & (VM_FAULT_SIGBUS|VM_FAULT_HWPOISON|
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/mm/gup.c linux-libre-2.6.38-gnu1/arch/x86/mm/gup.c
--- linux-libre-2.6.37-gnu1/arch/x86/mm/gup.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/mm/gup.c	2011-03-14 21:20:32.000000000 -0400
@@ -8,6 +8,7 @@
 #include <linux/mm.h>
 #include <linux/vmstat.h>
 #include <linux/highmem.h>
+#include <linux/swap.h>
 
 #include <asm/pgtable.h>
 
@@ -89,6 +90,7 @@ static noinline int gup_pte_range(pmd_t
 		VM_BUG_ON(!pfn_valid(pte_pfn(pte)));
 		page = pte_page(pte);
 		get_page(page);
+		SetPageReferenced(page);
 		pages[*nr] = page;
 		(*nr)++;
 
@@ -103,6 +105,17 @@ static inline void get_head_page_multipl
 	VM_BUG_ON(page != compound_head(page));
 	VM_BUG_ON(page_count(page) == 0);
 	atomic_add(nr, &page->_count);
+	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,
@@ -128,6 +141,8 @@ static noinline int gup_huge_pmd(pmd_t p
 	do {
 		VM_BUG_ON(compound_head(page) != head);
 		pages[*nr] = page;
+		if (PageTail(page))
+			get_huge_page_tail(page);
 		(*nr)++;
 		page++;
 		refs++;
@@ -148,7 +163,18 @@ static int gup_pmd_range(pud_t pud, unsi
 		pmd_t pmd = *pmdp;
 
 		next = pmd_addr_end(addr, end);
-		if (pmd_none(pmd))
+		/*
+		 * The pmd_trans_splitting() check below explains why
+		 * pmdp_splitting_flush has to flush the tlb, to stop
+		 * this gup-fast code from running while we set the
+		 * splitting bit in the pmd. Returning zero will take
+		 * the slow path that will call wait_split_huge_page()
+		 * if the pmd is still in splitting state. gup-fast
+		 * can't because it has irq disabled and
+		 * wait_split_huge_page() would never return as the
+		 * tlb flush IPI wouldn't run.
+		 */
+		if (pmd_none(pmd) || pmd_trans_splitting(pmd))
 			return 0;
 		if (unlikely(pmd_large(pmd))) {
 			if (!gup_huge_pmd(pmd, addr, next, write, pages, nr))
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/mm/init_32.c linux-libre-2.6.38-gnu1/arch/x86/mm/init_32.c
--- linux-libre-2.6.37-gnu1/arch/x86/mm/init_32.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/mm/init_32.c	2011-03-14 21:20:32.000000000 -0400
@@ -45,6 +45,7 @@
 #include <asm/bugs.h>
 #include <asm/tlb.h>
 #include <asm/tlbflush.h>
+#include <asm/olpc_ofw.h>
 #include <asm/pgalloc.h>
 #include <asm/sections.h>
 #include <asm/paravirt.h>
@@ -226,7 +227,7 @@ page_table_range_init(unsigned long star
 
 static inline int is_kernel_text(unsigned long addr)
 {
-	if (addr >= PAGE_OFFSET && addr <= (unsigned long)__init_end)
+	if (addr >= (unsigned long)_text && addr <= (unsigned long)__init_end)
 		return 1;
 	return 0;
 }
@@ -715,6 +716,7 @@ void __init paging_init(void)
 	/*
 	 * NOTE: at this point the bootmem allocator is fully available.
 	 */
+	olpc_dt_build_devicetree();
 	sparse_init();
 	zone_sizes_init();
 }
@@ -912,6 +914,23 @@ void set_kernel_text_ro(void)
 	set_pages_ro(virt_to_page(start), size >> PAGE_SHIFT);
 }
 
+static void mark_nxdata_nx(void)
+{
+	/*
+	 * When this called, init has already been executed and released,
+	 * so everything past _etext sould be NX.
+	 */
+	unsigned long start = PFN_ALIGN(_etext);
+	/*
+	 * This comes from is_kernel_text upper limit. Also HPAGE where used:
+	 */
+	unsigned long size = (((unsigned long)__init_end + HPAGE_SIZE) & HPAGE_MASK) - start;
+
+	if (__supported_pte_mask & _PAGE_NX)
+		printk(KERN_INFO "NX-protecting the kernel data: %luk\n", size >> 10);
+	set_pages_nx(virt_to_page(start), size >> PAGE_SHIFT);
+}
+
 void mark_rodata_ro(void)
 {
 	unsigned long start = PFN_ALIGN(_text);
@@ -946,6 +965,7 @@ void mark_rodata_ro(void)
 	printk(KERN_INFO "Testing CPA: write protecting again\n");
 	set_pages_ro(virt_to_page(start), size >> PAGE_SHIFT);
 #endif
+	mark_nxdata_nx();
 }
 #endif
 
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/mm/init_64.c linux-libre-2.6.38-gnu1/arch/x86/mm/init_64.c
--- linux-libre-2.6.37-gnu1/arch/x86/mm/init_64.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/mm/init_64.c	2011-03-14 21:20:32.000000000 -0400
@@ -105,18 +105,18 @@ void sync_global_pgds(unsigned long star
 
 	for (address = start; address <= end; address += PGDIR_SIZE) {
 		const pgd_t *pgd_ref = pgd_offset_k(address);
-		unsigned long flags;
 		struct page *page;
 
 		if (pgd_none(*pgd_ref))
 			continue;
 
-		spin_lock_irqsave(&pgd_lock, flags);
+		spin_lock(&pgd_lock);
 		list_for_each_entry(page, &pgd_list, lru) {
 			pgd_t *pgd;
 			spinlock_t *pgt_lock;
 
 			pgd = (pgd_t *)page_address(page) + pgd_index(address);
+			/* the pgt_lock only for Xen */
 			pgt_lock = &pgd_page_get_mm(page)->page_table_lock;
 			spin_lock(pgt_lock);
 
@@ -128,7 +128,7 @@ void sync_global_pgds(unsigned long star
 
 			spin_unlock(pgt_lock);
 		}
-		spin_unlock_irqrestore(&pgd_lock, flags);
+		spin_unlock(&pgd_lock);
 	}
 }
 
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/mm/init.c linux-libre-2.6.38-gnu1/arch/x86/mm/init.c
--- linux-libre-2.6.37-gnu1/arch/x86/mm/init.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/mm/init.c	2011-03-14 21:20:32.000000000 -0400
@@ -364,8 +364,9 @@ void free_init_pages(char *what, unsigne
 	/*
 	 * We just marked the kernel text read only above, now that
 	 * we are going to free part of that, we need to make that
-	 * writeable first.
+	 * writeable and non-executable first.
 	 */
+	set_memory_nx(begin, (end - begin) >> PAGE_SHIFT);
 	set_memory_rw(begin, (end - begin) >> PAGE_SHIFT);
 
 	printk(KERN_INFO "Freeing %s: %luk freed\n", what, (end - begin) >> 10);
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/mm/k8topology_64.c linux-libre-2.6.38-gnu1/arch/x86/mm/k8topology_64.c
--- linux-libre-2.6.37-gnu1/arch/x86/mm/k8topology_64.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/mm/k8topology_64.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,237 +0,0 @@
-/*
- * AMD K8 NUMA support.
- * Discover the memory map and associated nodes.
- *
- * This version reads it directly from the K8 northbridge.
- *
- * Copyright 2002,2003 Andi Kleen, SuSE Labs.
- */
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/string.h>
-#include <linux/module.h>
-#include <linux/nodemask.h>
-#include <linux/memblock.h>
-
-#include <asm/io.h>
-#include <linux/pci_ids.h>
-#include <linux/acpi.h>
-#include <asm/types.h>
-#include <asm/mmzone.h>
-#include <asm/proto.h>
-#include <asm/e820.h>
-#include <asm/pci-direct.h>
-#include <asm/numa.h>
-#include <asm/mpspec.h>
-#include <asm/apic.h>
-#include <asm/amd_nb.h>
-
-static struct bootnode __initdata nodes[8];
-static nodemask_t __initdata nodes_parsed = NODE_MASK_NONE;
-
-static __init int find_northbridge(void)
-{
-	int num;
-
-	for (num = 0; num < 32; num++) {
-		u32 header;
-
-		header = read_pci_config(0, num, 0, 0x00);
-		if (header != (PCI_VENDOR_ID_AMD | (0x1100<<16)) &&
-			header != (PCI_VENDOR_ID_AMD | (0x1200<<16)) &&
-			header != (PCI_VENDOR_ID_AMD | (0x1300<<16)))
-			continue;
-
-		header = read_pci_config(0, num, 1, 0x00);
-		if (header != (PCI_VENDOR_ID_AMD | (0x1101<<16)) &&
-			header != (PCI_VENDOR_ID_AMD | (0x1201<<16)) &&
-			header != (PCI_VENDOR_ID_AMD | (0x1301<<16)))
-			continue;
-		return num;
-	}
-
-	return -1;
-}
-
-static __init void early_get_boot_cpu_id(void)
-{
-	/*
-	 * need to get the APIC ID of the BSP so can use that to
-	 * create apicid_to_node in k8_scan_nodes()
-	 */
-#ifdef CONFIG_X86_MPPARSE
-	/*
-	 * get boot-time SMP configuration:
-	 */
-	if (smp_found_config)
-		early_get_smp_config();
-#endif
-	early_init_lapic_mapping();
-}
-
-int __init k8_get_nodes(struct bootnode *physnodes)
-{
-	int i;
-	int ret = 0;
-
-	for_each_node_mask(i, nodes_parsed) {
-		physnodes[ret].start = nodes[i].start;
-		physnodes[ret].end = nodes[i].end;
-		ret++;
-	}
-	return ret;
-}
-
-int __init k8_numa_init(unsigned long start_pfn, unsigned long end_pfn)
-{
-	unsigned long start = PFN_PHYS(start_pfn);
-	unsigned long end = PFN_PHYS(end_pfn);
-	unsigned numnodes;
-	unsigned long prevbase;
-	int i, nb, found = 0;
-	u32 nodeid, reg;
-
-	if (!early_pci_allowed())
-		return -1;
-
-	nb = find_northbridge();
-	if (nb < 0)
-		return nb;
-
-	pr_info("Scanning NUMA topology in Northbridge %d\n", nb);
-
-	reg = read_pci_config(0, nb, 0, 0x60);
-	numnodes = ((reg >> 4) & 0xF) + 1;
-	if (numnodes <= 1)
-		return -1;
-
-	pr_info("Number of physical nodes %d\n", numnodes);
-
-	prevbase = 0;
-	for (i = 0; i < 8; i++) {
-		unsigned long base, limit;
-
-		base = read_pci_config(0, nb, 1, 0x40 + i*8);
-		limit = read_pci_config(0, nb, 1, 0x44 + i*8);
-
-		nodeid = limit & 7;
-		if ((base & 3) == 0) {
-			if (i < numnodes)
-				pr_info("Skipping disabled node %d\n", i);
-			continue;
-		}
-		if (nodeid >= numnodes) {
-			pr_info("Ignoring excess node %d (%lx:%lx)\n", nodeid,
-				base, limit);
-			continue;
-		}
-
-		if (!limit) {
-			pr_info("Skipping node entry %d (base %lx)\n",
-				i, base);
-			continue;
-		}
-		if ((base >> 8) & 3 || (limit >> 8) & 3) {
-			pr_err("Node %d using interleaving mode %lx/%lx\n",
-			       nodeid, (base >> 8) & 3, (limit >> 8) & 3);
-			return -1;
-		}
-		if (node_isset(nodeid, nodes_parsed)) {
-			pr_info("Node %d already present, skipping\n",
-				nodeid);
-			continue;
-		}
-
-		limit >>= 16;
-		limit <<= 24;
-		limit |= (1<<24)-1;
-		limit++;
-
-		if (limit > end)
-			limit = end;
-		if (limit <= base)
-			continue;
-
-		base >>= 16;
-		base <<= 24;
-
-		if (base < start)
-			base = start;
-		if (limit > end)
-			limit = end;
-		if (limit == base) {
-			pr_err("Empty node %d\n", nodeid);
-			continue;
-		}
-		if (limit < base) {
-			pr_err("Node %d bogus settings %lx-%lx.\n",
-			       nodeid, base, limit);
-			continue;
-		}
-
-		/* Could sort here, but pun for now. Should not happen anyroads. */
-		if (prevbase > base) {
-			pr_err("Node map not sorted %lx,%lx\n",
-			       prevbase, base);
-			return -1;
-		}
-
-		pr_info("Node %d MemBase %016lx Limit %016lx\n",
-			nodeid, base, limit);
-
-		found++;
-
-		nodes[nodeid].start = base;
-		nodes[nodeid].end = limit;
-
-		prevbase = base;
-
-		node_set(nodeid, nodes_parsed);
-	}
-
-	if (!found)
-		return -1;
-	return 0;
-}
-
-int __init k8_scan_nodes(void)
-{
-	unsigned int bits;
-	unsigned int cores;
-	unsigned int apicid_base;
-	int i;
-
-	BUG_ON(nodes_empty(nodes_parsed));
-	node_possible_map = nodes_parsed;
-	memnode_shift = compute_hash_shift(nodes, 8, NULL);
-	if (memnode_shift < 0) {
-		pr_err("No NUMA node hash function found. Contact maintainer\n");
-		return -1;
-	}
-	pr_info("Using node hash shift of %d\n", memnode_shift);
-
-	/* use the coreid bits from early_identify_cpu */
-	bits = boot_cpu_data.x86_coreid_bits;
-	cores = (1<<bits);
-	apicid_base = 0;
-	/* get the APIC ID of the BSP early for systems with apicid lifting */
-	early_get_boot_cpu_id();
-	if (boot_cpu_physical_apicid > 0) {
-		pr_info("BSP APIC ID: %02x\n", boot_cpu_physical_apicid);
-		apicid_base = boot_cpu_physical_apicid;
-	}
-
-	for_each_node_mask(i, node_possible_map) {
-		int j;
-
-		memblock_x86_register_active_regions(i,
-				nodes[i].start >> PAGE_SHIFT,
-				nodes[i].end >> PAGE_SHIFT);
-		for (j = apicid_base; j < cores + apicid_base; j++)
-			apicid_to_node[(i << bits) + j] = i;
-		setup_node_bootmem(i, nodes[i].start, nodes[i].end);
-	}
-
-	numa_init_array();
-	return 0;
-}
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/mm/kmemcheck/error.c linux-libre-2.6.38-gnu1/arch/x86/mm/kmemcheck/error.c
--- linux-libre-2.6.37-gnu1/arch/x86/mm/kmemcheck/error.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/mm/kmemcheck/error.c	2011-03-14 21:20:32.000000000 -0400
@@ -185,7 +185,7 @@ void kmemcheck_error_save(enum kmemcheck
 	e->trace.entries = e->trace_entries;
 	e->trace.max_entries = ARRAY_SIZE(e->trace_entries);
 	e->trace.skip = 0;
-	save_stack_trace_bp(&e->trace, regs->bp);
+	save_stack_trace_regs(&e->trace, regs);
 
 	/* Round address down to nearest 16 bytes */
 	shadow_copy = kmemcheck_shadow_lookup(address
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/mm/Makefile linux-libre-2.6.38-gnu1/arch/x86/mm/Makefile
--- linux-libre-2.6.37-gnu1/arch/x86/mm/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/mm/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -23,7 +23,7 @@ mmiotrace-y			:= kmmio.o pf_in.o mmio-mo
 obj-$(CONFIG_MMIOTRACE_TEST)	+= testmmiotrace.o
 
 obj-$(CONFIG_NUMA)		+= numa.o numa_$(BITS).o
-obj-$(CONFIG_K8_NUMA)		+= k8topology_64.o
+obj-$(CONFIG_AMD_NUMA)		+= amdtopology_64.o
 obj-$(CONFIG_ACPI_NUMA)		+= srat_$(BITS).o
 
 obj-$(CONFIG_HAVE_MEMBLOCK)		+= memblock.o
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/mm/numa_64.c linux-libre-2.6.38-gnu1/arch/x86/mm/numa_64.c
--- linux-libre-2.6.37-gnu1/arch/x86/mm/numa_64.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/mm/numa_64.c	2011-03-14 21:20:32.000000000 -0400
@@ -30,7 +30,6 @@ s16 apicid_to_node[MAX_LOCAL_APIC] __cpu
 	[0 ... MAX_LOCAL_APIC-1] = NUMA_NO_NODE
 };
 
-int numa_off __initdata;
 static unsigned long __initdata nodemap_addr;
 static unsigned long __initdata nodemap_size;
 
@@ -260,30 +259,35 @@ void __init numa_init_array(void)
 #ifdef CONFIG_NUMA_EMU
 /* Numa emulation */
 static struct bootnode nodes[MAX_NUMNODES] __initdata;
-static struct bootnode physnodes[MAX_NUMNODES] __initdata;
+static struct bootnode physnodes[MAX_NUMNODES] __cpuinitdata;
 static char *cmdline __initdata;
 
+void __init numa_emu_cmdline(char *str)
+{
+	cmdline = str;
+}
+
 static int __init setup_physnodes(unsigned long start, unsigned long end,
-					int acpi, int k8)
+					int acpi, int amd)
 {
-	int nr_nodes = 0;
 	int ret = 0;
 	int i;
 
+	memset(physnodes, 0, sizeof(physnodes));
 #ifdef CONFIG_ACPI_NUMA
 	if (acpi)
-		nr_nodes = acpi_get_nodes(physnodes);
+		acpi_get_nodes(physnodes, start, end);
 #endif
-#ifdef CONFIG_K8_NUMA
-	if (k8)
-		nr_nodes = k8_get_nodes(physnodes);
+#ifdef CONFIG_AMD_NUMA
+	if (amd)
+		amd_get_nodes(physnodes);
 #endif
 	/*
 	 * Basic sanity checking on the physical node map: there may be errors
-	 * if the SRAT or K8 incorrectly reported the topology or the mem=
+	 * if the SRAT or AMD code incorrectly reported the topology or the mem=
 	 * kernel parameter is used.
 	 */
-	for (i = 0; i < nr_nodes; i++) {
+	for (i = 0; i < MAX_NUMNODES; i++) {
 		if (physnodes[i].start == physnodes[i].end)
 			continue;
 		if (physnodes[i].start > end) {
@@ -298,17 +302,6 @@ static int __init setup_physnodes(unsign
 			physnodes[i].start = start;
 		if (physnodes[i].end > end)
 			physnodes[i].end = end;
-	}
-
-	/*
-	 * Remove all nodes that have no memory or were truncated because of the
-	 * limited address range.
-	 */
-	for (i = 0; i < nr_nodes; i++) {
-		if (physnodes[i].start == physnodes[i].end)
-			continue;
-		physnodes[ret].start = physnodes[i].start;
-		physnodes[ret].end = physnodes[i].end;
 		ret++;
 	}
 
@@ -324,6 +317,24 @@ static int __init setup_physnodes(unsign
 	return ret;
 }
 
+static void __init fake_physnodes(int acpi, int amd, int nr_nodes)
+{
+	int i;
+
+	BUG_ON(acpi && amd);
+#ifdef CONFIG_ACPI_NUMA
+	if (acpi)
+		acpi_fake_nodes(nodes, nr_nodes);
+#endif
+#ifdef CONFIG_AMD_NUMA
+	if (amd)
+		amd_fake_nodes(nodes, nr_nodes);
+#endif
+	if (!acpi && !amd)
+		for (i = 0; i < nr_cpu_ids; i++)
+			numa_set_node(i, 0);
+}
+
 /*
  * Setups up nid to range from addr to addr + size.  If the end
  * boundary is greater than max_addr, then max_addr is used instead.
@@ -352,8 +363,7 @@ static int __init setup_node_range(int n
  * Sets up nr_nodes fake nodes interleaved over physical nodes ranging from addr
  * to max_addr.  The return value is the number of nodes allocated.
  */
-static int __init split_nodes_interleave(u64 addr, u64 max_addr,
-						int nr_phys_nodes, int nr_nodes)
+static int __init split_nodes_interleave(u64 addr, u64 max_addr, int nr_nodes)
 {
 	nodemask_t physnode_mask = NODE_MASK_NONE;
 	u64 size;
@@ -384,7 +394,7 @@ static int __init split_nodes_interleave
 		return -1;
 	}
 
-	for (i = 0; i < nr_phys_nodes; i++)
+	for (i = 0; i < MAX_NUMNODES; i++)
 		if (physnodes[i].start != physnodes[i].end)
 			node_set(i, physnode_mask);
 
@@ -549,15 +559,13 @@ static int __init split_nodes_size_inter
  * numa=fake command-line option.
  */
 static int __init numa_emulation(unsigned long start_pfn,
-			unsigned long last_pfn, int acpi, int k8)
+			unsigned long last_pfn, int acpi, int amd)
 {
 	u64 addr = start_pfn << PAGE_SHIFT;
 	u64 max_addr = last_pfn << PAGE_SHIFT;
-	int num_phys_nodes;
 	int num_nodes;
 	int i;
 
-	num_phys_nodes = setup_physnodes(addr, max_addr, acpi, k8);
 	/*
 	 * If the numa=fake command-line contains a 'M' or 'G', it represents
 	 * the fixed node size.  Otherwise, if it is just a single number N,
@@ -572,7 +580,7 @@ static int __init numa_emulation(unsigne
 		unsigned long n;
 
 		n = simple_strtoul(cmdline, NULL, 0);
-		num_nodes = split_nodes_interleave(addr, max_addr, num_phys_nodes, n);
+		num_nodes = split_nodes_interleave(addr, max_addr, n);
 	}
 
 	if (num_nodes < 0)
@@ -595,14 +603,15 @@ static int __init numa_emulation(unsigne
 						nodes[i].end >> PAGE_SHIFT);
 		setup_node_bootmem(i, nodes[i].start, nodes[i].end);
 	}
-	acpi_fake_nodes(nodes, num_nodes);
+	setup_physnodes(addr, max_addr, acpi, amd);
+	fake_physnodes(acpi, amd, num_nodes);
 	numa_init_array();
 	return 0;
 }
 #endif /* CONFIG_NUMA_EMU */
 
 void __init initmem_init(unsigned long start_pfn, unsigned long last_pfn,
-				int acpi, int k8)
+				int acpi, int amd)
 {
 	int i;
 
@@ -610,8 +619,12 @@ void __init initmem_init(unsigned long s
 	nodes_clear(node_online_map);
 
 #ifdef CONFIG_NUMA_EMU
-	if (cmdline && !numa_emulation(start_pfn, last_pfn, acpi, k8))
+	setup_physnodes(start_pfn << PAGE_SHIFT, last_pfn << PAGE_SHIFT,
+			acpi, amd);
+	if (cmdline && !numa_emulation(start_pfn, last_pfn, acpi, amd))
 		return;
+	setup_physnodes(start_pfn << PAGE_SHIFT, last_pfn << PAGE_SHIFT,
+			acpi, amd);
 	nodes_clear(node_possible_map);
 	nodes_clear(node_online_map);
 #endif
@@ -624,8 +637,8 @@ void __init initmem_init(unsigned long s
 	nodes_clear(node_online_map);
 #endif
 
-#ifdef CONFIG_K8_NUMA
-	if (!numa_off && k8 && !k8_scan_nodes())
+#ifdef CONFIG_AMD_NUMA
+	if (!numa_off && amd && !amd_scan_nodes())
 		return;
 	nodes_clear(node_possible_map);
 	nodes_clear(node_online_map);
@@ -661,24 +674,6 @@ unsigned long __init numa_free_all_bootm
 	return pages;
 }
 
-static __init int numa_setup(char *opt)
-{
-	if (!opt)
-		return -EINVAL;
-	if (!strncmp(opt, "off", 3))
-		numa_off = 1;
-#ifdef CONFIG_NUMA_EMU
-	if (!strncmp(opt, "fake=", 5))
-		cmdline = opt + 5;
-#endif
-#ifdef CONFIG_ACPI_NUMA
-	if (!strncmp(opt, "noacpi", 6))
-		acpi_numa = -1;
-#endif
-	return 0;
-}
-early_param("numa", numa_setup);
-
 #ifdef CONFIG_NUMA
 
 static __init int find_near_online_node(int node)
@@ -767,6 +762,7 @@ void __cpuinit numa_clear_node(int cpu)
 
 #ifndef CONFIG_DEBUG_PER_CPU_MAPS
 
+#ifndef CONFIG_NUMA_EMU
 void __cpuinit numa_add_cpu(int cpu)
 {
 	cpumask_set_cpu(cpu, node_to_cpumask_map[early_cpu_to_node(cpu)]);
@@ -776,34 +772,111 @@ void __cpuinit numa_remove_cpu(int cpu)
 {
 	cpumask_clear_cpu(cpu, node_to_cpumask_map[early_cpu_to_node(cpu)]);
 }
+#else
+void __cpuinit numa_add_cpu(int cpu)
+{
+	unsigned long addr;
+	u16 apicid;
+	int physnid;
+	int nid = NUMA_NO_NODE;
+
+	nid = early_cpu_to_node(cpu);
+	BUG_ON(nid == NUMA_NO_NODE || !node_online(nid));
+
+	/*
+	 * Use the starting address of the emulated node to find which physical
+	 * node it is allocated on.
+	 */
+	addr = node_start_pfn(nid) << PAGE_SHIFT;
+	for (physnid = 0; physnid < MAX_NUMNODES; physnid++)
+		if (addr >= physnodes[physnid].start &&
+		    addr < physnodes[physnid].end)
+			break;
+
+	/*
+	 * Map the cpu to each emulated node that is allocated on the physical
+	 * node of the cpu's apic id.
+	 */
+	for_each_online_node(nid) {
+		addr = node_start_pfn(nid) << PAGE_SHIFT;
+		if (addr >= physnodes[physnid].start &&
+		    addr < physnodes[physnid].end)
+			cpumask_set_cpu(cpu, node_to_cpumask_map[nid]);
+	}
+}
+
+void __cpuinit numa_remove_cpu(int cpu)
+{
+	int i;
+
+	for_each_online_node(i)
+		cpumask_clear_cpu(cpu, node_to_cpumask_map[i]);
+}
+#endif /* !CONFIG_NUMA_EMU */
 
 #else /* CONFIG_DEBUG_PER_CPU_MAPS */
+static struct cpumask __cpuinit *debug_cpumask_set_cpu(int cpu, int enable)
+{
+	int node = early_cpu_to_node(cpu);
+	struct cpumask *mask;
+	char buf[64];
+
+	mask = node_to_cpumask_map[node];
+	if (!mask) {
+		pr_err("node_to_cpumask_map[%i] NULL\n", node);
+		dump_stack();
+		return NULL;
+	}
+
+	cpulist_scnprintf(buf, sizeof(buf), mask);
+	printk(KERN_DEBUG "%s cpu %d node %d: mask now %s\n",
+		enable ? "numa_add_cpu" : "numa_remove_cpu",
+		cpu, node, buf);
+	return mask;
+}
 
 /*
  * --------- debug versions of the numa functions ---------
  */
+#ifndef CONFIG_NUMA_EMU
 static void __cpuinit numa_set_cpumask(int cpu, int enable)
 {
-	int node = early_cpu_to_node(cpu);
 	struct cpumask *mask;
-	char buf[64];
 
-	mask = node_to_cpumask_map[node];
-	if (mask == NULL) {
-		printk(KERN_ERR "node_to_cpumask_map[%i] NULL\n", node);
-		dump_stack();
+	mask = debug_cpumask_set_cpu(cpu, enable);
+	if (!mask)
 		return;
-	}
 
 	if (enable)
 		cpumask_set_cpu(cpu, mask);
 	else
 		cpumask_clear_cpu(cpu, mask);
+}
+#else
+static void __cpuinit numa_set_cpumask(int cpu, int enable)
+{
+	int node = early_cpu_to_node(cpu);
+	struct cpumask *mask;
+	int i;
 
-	cpulist_scnprintf(buf, sizeof(buf), mask);
-	printk(KERN_DEBUG "%s cpu %d node %d: mask now %s\n",
-		enable ? "numa_add_cpu" : "numa_remove_cpu", cpu, node, buf);
+	for_each_online_node(i) {
+		unsigned long addr;
+
+		addr = node_start_pfn(i) << PAGE_SHIFT;
+		if (addr < physnodes[node].start ||
+					addr >= physnodes[node].end)
+			continue;
+		mask = debug_cpumask_set_cpu(cpu, enable);
+		if (!mask)
+			return;
+
+		if (enable)
+			cpumask_set_cpu(cpu, mask);
+		else
+			cpumask_clear_cpu(cpu, mask);
+	}
 }
+#endif /* CONFIG_NUMA_EMU */
 
 void __cpuinit numa_add_cpu(int cpu)
 {
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/mm/numa.c linux-libre-2.6.38-gnu1/arch/x86/mm/numa.c
--- linux-libre-2.6.37-gnu1/arch/x86/mm/numa.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/mm/numa.c	2011-03-14 21:20:32.000000000 -0400
@@ -2,6 +2,28 @@
 #include <linux/topology.h>
 #include <linux/module.h>
 #include <linux/bootmem.h>
+#include <asm/numa.h>
+#include <asm/acpi.h>
+
+int __initdata numa_off;
+
+static __init int numa_setup(char *opt)
+{
+	if (!opt)
+		return -EINVAL;
+	if (!strncmp(opt, "off", 3))
+		numa_off = 1;
+#ifdef CONFIG_NUMA_EMU
+	if (!strncmp(opt, "fake=", 5))
+		numa_emu_cmdline(opt + 5);
+#endif
+#ifdef CONFIG_ACPI_NUMA
+	if (!strncmp(opt, "noacpi", 6))
+		acpi_numa = -1;
+#endif
+	return 0;
+}
+early_param("numa", numa_setup);
 
 /*
  * Which logical CPUs are on which nodes
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/mm/pageattr.c linux-libre-2.6.38-gnu1/arch/x86/mm/pageattr.c
--- linux-libre-2.6.37-gnu1/arch/x86/mm/pageattr.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/mm/pageattr.c	2011-03-14 21:20:32.000000000 -0400
@@ -13,6 +13,7 @@
 #include <linux/pfn.h>
 #include <linux/percpu.h>
 #include <linux/gfp.h>
+#include <linux/pci.h>
 
 #include <asm/e820.h>
 #include <asm/processor.h>
@@ -56,12 +57,10 @@ static unsigned long direct_pages_count[
 
 void update_page_count(int level, unsigned long pages)
 {
-	unsigned long flags;
-
 	/* Protect against CPA */
-	spin_lock_irqsave(&pgd_lock, flags);
+	spin_lock(&pgd_lock);
 	direct_pages_count[level] += pages;
-	spin_unlock_irqrestore(&pgd_lock, flags);
+	spin_unlock(&pgd_lock);
 }
 
 static void split_page_count(int level)
@@ -260,8 +259,10 @@ static inline pgprot_t static_protection
 	 * The BIOS area between 640k and 1Mb needs to be executable for
 	 * PCI BIOS based config access (CONFIG_PCI_GOBIOS) support.
 	 */
-	if (within(pfn, BIOS_BEGIN >> PAGE_SHIFT, BIOS_END >> PAGE_SHIFT))
+#ifdef CONFIG_PCI_BIOS
+	if (pcibios_enabled && within(pfn, BIOS_BEGIN >> PAGE_SHIFT, BIOS_END >> PAGE_SHIFT))
 		pgprot_val(forbidden) |= _PAGE_NX;
+#endif
 
 	/*
 	 * The kernel text needs to be executable for obvious reasons
@@ -391,16 +392,16 @@ static int
 try_preserve_large_page(pte_t *kpte, unsigned long address,
 			struct cpa_data *cpa)
 {
-	unsigned long nextpage_addr, numpages, pmask, psize, flags, addr, pfn;
+	unsigned long nextpage_addr, numpages, pmask, psize, addr, pfn;
 	pte_t new_pte, old_pte, *tmp;
-	pgprot_t old_prot, new_prot;
+	pgprot_t old_prot, new_prot, req_prot;
 	int i, do_split = 1;
 	unsigned int level;
 
 	if (cpa->force_split)
 		return 1;
 
-	spin_lock_irqsave(&pgd_lock, flags);
+	spin_lock(&pgd_lock);
 	/*
 	 * Check for races, another CPU might have split this page
 	 * up already:
@@ -438,10 +439,10 @@ try_preserve_large_page(pte_t *kpte, uns
 	 * We are safe now. Check whether the new pgprot is the same:
 	 */
 	old_pte = *kpte;
-	old_prot = new_prot = pte_pgprot(old_pte);
+	old_prot = new_prot = req_prot = pte_pgprot(old_pte);
 
-	pgprot_val(new_prot) &= ~pgprot_val(cpa->mask_clr);
-	pgprot_val(new_prot) |= pgprot_val(cpa->mask_set);
+	pgprot_val(req_prot) &= ~pgprot_val(cpa->mask_clr);
+	pgprot_val(req_prot) |= pgprot_val(cpa->mask_set);
 
 	/*
 	 * old_pte points to the large page base address. So we need
@@ -450,17 +451,17 @@ try_preserve_large_page(pte_t *kpte, uns
 	pfn = pte_pfn(old_pte) + ((address & (psize - 1)) >> PAGE_SHIFT);
 	cpa->pfn = pfn;
 
-	new_prot = static_protections(new_prot, address, pfn);
+	new_prot = static_protections(req_prot, address, pfn);
 
 	/*
 	 * We need to check the full range, whether
 	 * static_protection() requires a different pgprot for one of
 	 * the pages in the range we try to preserve:
 	 */
-	addr = address + PAGE_SIZE;
-	pfn++;
-	for (i = 1; i < cpa->numpages; i++, addr += PAGE_SIZE, pfn++) {
-		pgprot_t chk_prot = static_protections(new_prot, addr, pfn);
+	addr = address & pmask;
+	pfn = pte_pfn(old_pte);
+	for (i = 0; i < (psize >> PAGE_SHIFT); i++, addr += PAGE_SIZE, pfn++) {
+		pgprot_t chk_prot = static_protections(req_prot, addr, pfn);
 
 		if (pgprot_val(chk_prot) != pgprot_val(new_prot))
 			goto out_unlock;
@@ -483,7 +484,7 @@ try_preserve_large_page(pte_t *kpte, uns
 	 * that we limited the number of possible pages already to
 	 * the number of pages in the large page.
 	 */
-	if (address == (nextpage_addr - psize) && cpa->numpages == numpages) {
+	if (address == (address & pmask) && cpa->numpages == (psize >> PAGE_SHIFT)) {
 		/*
 		 * The address is aligned and the number of pages
 		 * covers the full page.
@@ -495,14 +496,14 @@ try_preserve_large_page(pte_t *kpte, uns
 	}
 
 out_unlock:
-	spin_unlock_irqrestore(&pgd_lock, flags);
+	spin_unlock(&pgd_lock);
 
 	return do_split;
 }
 
 static int split_large_page(pte_t *kpte, unsigned long address)
 {
-	unsigned long flags, pfn, pfninc = 1;
+	unsigned long pfn, pfninc = 1;
 	unsigned int i, level;
 	pte_t *pbase, *tmp;
 	pgprot_t ref_prot;
@@ -516,7 +517,7 @@ static int split_large_page(pte_t *kpte,
 	if (!base)
 		return -ENOMEM;
 
-	spin_lock_irqsave(&pgd_lock, flags);
+	spin_lock(&pgd_lock);
 	/*
 	 * Check for races, another CPU might have split this page
 	 * up for us already:
@@ -588,7 +589,7 @@ out_unlock:
 	 */
 	if (base)
 		__free_page(base);
-	spin_unlock_irqrestore(&pgd_lock, flags);
+	spin_unlock(&pgd_lock);
 
 	return 0;
 }
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/mm/pgtable.c linux-libre-2.6.38-gnu1/arch/x86/mm/pgtable.c
--- linux-libre-2.6.37-gnu1/arch/x86/mm/pgtable.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/mm/pgtable.c	2011-03-14 21:20:32.000000000 -0400
@@ -121,14 +121,12 @@ static void pgd_ctor(struct mm_struct *m
 
 static void pgd_dtor(pgd_t *pgd)
 {
-	unsigned long flags; /* can be called from interrupt context */
-
 	if (SHARED_KERNEL_PMD)
 		return;
 
-	spin_lock_irqsave(&pgd_lock, flags);
+	spin_lock(&pgd_lock);
 	pgd_list_del(pgd);
-	spin_unlock_irqrestore(&pgd_lock, flags);
+	spin_unlock(&pgd_lock);
 }
 
 /*
@@ -260,7 +258,6 @@ pgd_t *pgd_alloc(struct mm_struct *mm)
 {
 	pgd_t *pgd;
 	pmd_t *pmds[PREALLOCATED_PMDS];
-	unsigned long flags;
 
 	pgd = (pgd_t *)__get_free_page(PGALLOC_GFP);
 
@@ -280,12 +277,12 @@ pgd_t *pgd_alloc(struct mm_struct *mm)
 	 * respect to anything walking the pgd_list, so that they
 	 * never see a partially populated pgd.
 	 */
-	spin_lock_irqsave(&pgd_lock, flags);
+	spin_lock(&pgd_lock);
 
 	pgd_ctor(mm, pgd);
 	pgd_prepopulate_pmd(mm, pgd, pmds);
 
-	spin_unlock_irqrestore(&pgd_lock, flags);
+	spin_unlock(&pgd_lock);
 
 	return pgd;
 
@@ -320,6 +317,25 @@ int ptep_set_access_flags(struct vm_area
 	return changed;
 }
 
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
+int pmdp_set_access_flags(struct vm_area_struct *vma,
+			  unsigned long address, pmd_t *pmdp,
+			  pmd_t entry, int dirty)
+{
+	int changed = !pmd_same(*pmdp, entry);
+
+	VM_BUG_ON(address & ~HPAGE_PMD_MASK);
+
+	if (changed && dirty) {
+		*pmdp = entry;
+		pmd_update_defer(vma->vm_mm, address, pmdp);
+		flush_tlb_range(vma, address, address + HPAGE_PMD_SIZE);
+	}
+
+	return changed;
+}
+#endif
+
 int ptep_test_and_clear_young(struct vm_area_struct *vma,
 			      unsigned long addr, pte_t *ptep)
 {
@@ -335,6 +351,23 @@ int ptep_test_and_clear_young(struct vm_
 	return ret;
 }
 
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
+int pmdp_test_and_clear_young(struct vm_area_struct *vma,
+			      unsigned long addr, pmd_t *pmdp)
+{
+	int ret = 0;
+
+	if (pmd_young(*pmdp))
+		ret = test_and_clear_bit(_PAGE_BIT_ACCESSED,
+					 (unsigned long *)pmdp);
+
+	if (ret)
+		pmd_update(vma->vm_mm, addr, pmdp);
+
+	return ret;
+}
+#endif
+
 int ptep_clear_flush_young(struct vm_area_struct *vma,
 			   unsigned long address, pte_t *ptep)
 {
@@ -347,6 +380,36 @@ int ptep_clear_flush_young(struct vm_are
 	return young;
 }
 
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
+int pmdp_clear_flush_young(struct vm_area_struct *vma,
+			   unsigned long address, pmd_t *pmdp)
+{
+	int young;
+
+	VM_BUG_ON(address & ~HPAGE_PMD_MASK);
+
+	young = pmdp_test_and_clear_young(vma, address, pmdp);
+	if (young)
+		flush_tlb_range(vma, address, address + HPAGE_PMD_SIZE);
+
+	return young;
+}
+
+void pmdp_splitting_flush(struct vm_area_struct *vma,
+			  unsigned long address, pmd_t *pmdp)
+{
+	int set;
+	VM_BUG_ON(address & ~HPAGE_PMD_MASK);
+	set = !test_and_set_bit(_PAGE_BIT_SPLITTING,
+				(unsigned long *)pmdp);
+	if (set) {
+		pmd_update(vma->vm_mm, address, pmdp);
+		/* need tlb flush only to serialize against gup-fast */
+		flush_tlb_range(vma, address, address + HPAGE_PMD_SIZE);
+	}
+}
+#endif
+
 /**
  * reserve_top_address - reserves a hole in the top of kernel address space
  * @reserve - size of hole to reserve
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/mm/setup_nx.c linux-libre-2.6.38-gnu1/arch/x86/mm/setup_nx.c
--- linux-libre-2.6.37-gnu1/arch/x86/mm/setup_nx.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/mm/setup_nx.c	2011-03-14 21:20:32.000000000 -0400
@@ -41,7 +41,7 @@ void __init x86_report_nx(void)
 {
 	if (!cpu_has_nx) {
 		printk(KERN_NOTICE "Notice: NX (Execute Disable) protection "
-		       "missing in CPU or disabled in BIOS!\n");
+		       "missing in CPU!\n");
 	} else {
 #if defined(CONFIG_X86_64) || defined(CONFIG_X86_PAE)
 		if (disable_nx) {
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/mm/srat_32.c linux-libre-2.6.38-gnu1/arch/x86/mm/srat_32.c
--- linux-libre-2.6.37-gnu1/arch/x86/mm/srat_32.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/mm/srat_32.c	2011-03-14 21:20:32.000000000 -0400
@@ -59,7 +59,6 @@ static struct node_memory_chunk_s __init
 static int __initdata num_memory_chunks; /* total number of memory chunks */
 static u8 __initdata apicid_to_pxm[MAX_APICID];
 
-int numa_off __initdata;
 int acpi_numa __initdata;
 
 static __init void bad_srat(void)
@@ -92,6 +91,7 @@ acpi_numa_processor_affinity_init(struct
 	/* mark this node as "seen" in node bitmap */
 	BMAP_SET(pxm_bitmap, cpu_affinity->proximity_domain_lo);
 
+	/* don't need to check apic_id here, because it is always 8 bits */
 	apicid_to_pxm[cpu_affinity->apic_id] = cpu_affinity->proximity_domain_lo;
 
 	printk(KERN_DEBUG "CPU %02x in proximity domain %02x\n",
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/mm/srat_64.c linux-libre-2.6.38-gnu1/arch/x86/mm/srat_64.c
--- linux-libre-2.6.37-gnu1/arch/x86/mm/srat_64.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/mm/srat_64.c	2011-03-14 21:20:32.000000000 -0400
@@ -134,6 +134,10 @@ acpi_numa_x2apic_affinity_init(struct ac
 	}
 
 	apic_id = pa->apic_id;
+	if (apic_id >= MAX_LOCAL_APIC) {
+		printk(KERN_INFO "SRAT: PXM %u -> APIC 0x%04x -> Node %u skipped apicid that is too big\n", pxm, apic_id, node);
+		return;
+	}
 	apicid_to_node[apic_id] = node;
 	node_set(node, cpu_nodes_parsed);
 	acpi_numa = 1;
@@ -168,6 +172,12 @@ acpi_numa_processor_affinity_init(struct
 		apic_id = (pa->apic_id << 8) | pa->local_sapic_eid;
 	else
 		apic_id = pa->apic_id;
+
+	if (apic_id >= MAX_LOCAL_APIC) {
+		printk(KERN_INFO "SRAT: PXM %u -> APIC 0x%02x -> Node %u skipped apicid that is too big\n", pxm, apic_id, node);
+		return;
+	}
+
 	apicid_to_node[apic_id] = node;
 	node_set(node, cpu_nodes_parsed);
 	acpi_numa = 1;
@@ -339,18 +349,19 @@ static int __init nodes_cover_memory(con
 
 void __init acpi_numa_arch_fixup(void) {}
 
-int __init acpi_get_nodes(struct bootnode *physnodes)
+#ifdef CONFIG_NUMA_EMU
+void __init acpi_get_nodes(struct bootnode *physnodes, unsigned long start,
+				unsigned long end)
 {
 	int i;
-	int ret = 0;
 
 	for_each_node_mask(i, nodes_parsed) {
-		physnodes[ret].start = nodes[i].start;
-		physnodes[ret].end = nodes[i].end;
-		ret++;
+		cutoff_node(i, start, end);
+		physnodes[i].start = nodes[i].start;
+		physnodes[i].end = nodes[i].end;
 	}
-	return ret;
 }
+#endif /* CONFIG_NUMA_EMU */
 
 /* Use the information discovered above to actually set up the nodes. */
 int __init acpi_scan_nodes(unsigned long start, unsigned long end)
@@ -495,8 +506,6 @@ void __init acpi_fake_nodes(const struct
 {
 	int i, j;
 
-	printk(KERN_INFO "Faking PXM affinity for fake nodes on real "
-			 "topology.\n");
 	for (i = 0; i < num_nodes; i++) {
 		int nid, pxm;
 
@@ -516,6 +525,17 @@ void __init acpi_fake_nodes(const struct
 			    fake_apicid_to_node[j] == NUMA_NO_NODE)
 				fake_apicid_to_node[j] = i;
 	}
+
+	/*
+	 * If there are apicid-to-node mappings for physical nodes that do not
+	 * have a corresponding emulated node, it should default to a guaranteed
+	 * value.
+	 */
+	for (i = 0; i < MAX_LOCAL_APIC; i++)
+		if (apicid_to_node[i] != NUMA_NO_NODE &&
+		    fake_apicid_to_node[i] == NUMA_NO_NODE)
+			fake_apicid_to_node[i] = 0;
+
 	for (i = 0; i < num_nodes; i++)
 		__acpi_map_pxm_to_node(fake_node_to_pxm_map[i], i);
 	memcpy(apicid_to_node, fake_apicid_to_node, sizeof(apicid_to_node));
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/oprofile/backtrace.c linux-libre-2.6.38-gnu1/arch/x86/oprofile/backtrace.c
--- linux-libre-2.6.37-gnu1/arch/x86/oprofile/backtrace.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/oprofile/backtrace.c	2011-03-14 21:20:32.000000000 -0400
@@ -126,7 +126,7 @@ x86_backtrace(struct pt_regs * const reg
 	if (!user_mode_vm(regs)) {
 		unsigned long stack = kernel_stack_pointer(regs);
 		if (depth)
-			dump_trace(NULL, regs, (unsigned long *)stack, 0,
+			dump_trace(NULL, regs, (unsigned long *)stack,
 				   &backtrace_ops, &depth);
 		return;
 	}
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/oprofile/nmi_int.c linux-libre-2.6.38-gnu1/arch/x86/oprofile/nmi_int.c
--- linux-libre-2.6.37-gnu1/arch/x86/oprofile/nmi_int.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/oprofile/nmi_int.c	2011-03-14 21:20:32.000000000 -0400
@@ -65,7 +65,6 @@ static int profile_exceptions_notify(str
 
 	switch (val) {
 	case DIE_NMI:
-	case DIE_NMI_IPI:
 		if (ctr_running)
 			model->check_ctrs(args->regs, &__get_cpu_var(cpu_msrs));
 		else if (!nmi_enabled)
@@ -143,7 +142,7 @@ static inline int has_mux(void)
 
 inline int op_x86_phys_to_virt(int phys)
 {
-	return __get_cpu_var(switch_index) + phys;
+	return __this_cpu_read(switch_index) + phys;
 }
 
 inline int op_x86_virt_to_phys(int virt)
@@ -361,7 +360,7 @@ static void nmi_cpu_setup(void *dummy)
 static struct notifier_block profile_exceptions_nb = {
 	.notifier_call = profile_exceptions_notify,
 	.next = NULL,
-	.priority = 2
+	.priority = NMI_LOCAL_LOW_PRIOR,
 };
 
 static void nmi_cpu_restore_registers(struct op_msrs *msrs)
@@ -732,6 +731,9 @@ int __init op_nmi_init(struct oprofile_o
 		case 0x14:
 			cpu_type = "x86-64/family14h";
 			break;
+		case 0x15:
+			cpu_type = "x86-64/family15h";
+			break;
 		default:
 			return -ENODEV;
 		}
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/oprofile/nmi_timer_int.c linux-libre-2.6.38-gnu1/arch/x86/oprofile/nmi_timer_int.c
--- linux-libre-2.6.37-gnu1/arch/x86/oprofile/nmi_timer_int.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/oprofile/nmi_timer_int.c	2011-03-14 21:20:32.000000000 -0400
@@ -38,7 +38,7 @@ static int profile_timer_exceptions_noti
 static struct notifier_block profile_timer_exceptions_nb = {
 	.notifier_call = profile_timer_exceptions_notify,
 	.next = NULL,
-	.priority = 0
+	.priority = NMI_LOW_PRIOR,
 };
 
 static int timer_start(void)
@@ -58,9 +58,6 @@ static void timer_stop(void)
 
 int __init op_nmi_timer_init(struct oprofile_operations *ops)
 {
-	if ((nmi_watchdog != NMI_IO_APIC) || (atomic_read(&nmi_active) <= 0))
-		return -ENODEV;
-
 	ops->start = timer_start;
 	ops->stop = timer_stop;
 	ops->cpu_type = "timer";
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/oprofile/op_model_amd.c linux-libre-2.6.38-gnu1/arch/x86/oprofile/op_model_amd.c
--- linux-libre-2.6.37-gnu1/arch/x86/oprofile/op_model_amd.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/oprofile/op_model_amd.c	2011-03-14 21:20:32.000000000 -0400
@@ -29,11 +29,12 @@
 #include "op_x86_model.h"
 #include "op_counter.h"
 
-#define NUM_COUNTERS 4
+#define NUM_COUNTERS		4
+#define NUM_COUNTERS_F15H	6
 #ifdef CONFIG_OPROFILE_EVENT_MULTIPLEX
-#define NUM_VIRT_COUNTERS 32
+#define NUM_VIRT_COUNTERS	32
 #else
-#define NUM_VIRT_COUNTERS NUM_COUNTERS
+#define NUM_VIRT_COUNTERS	0
 #endif
 
 #define OP_EVENT_MASK			0x0FFF
@@ -41,7 +42,8 @@
 
 #define MSR_AMD_EVENTSEL_RESERVED	((0xFFFFFCF0ULL<<32)|(1ULL<<21))
 
-static unsigned long reset_value[NUM_VIRT_COUNTERS];
+static int num_counters;
+static unsigned long reset_value[OP_MAX_COUNTER];
 
 #define IBS_FETCH_SIZE			6
 #define IBS_OP_SIZE			12
@@ -387,7 +389,7 @@ static void op_mux_switch_ctrl(struct op
 	int i;
 
 	/* enable active counters */
-	for (i = 0; i < NUM_COUNTERS; ++i) {
+	for (i = 0; i < num_counters; ++i) {
 		int virt = op_x86_phys_to_virt(i);
 		if (!reset_value[virt])
 			continue;
@@ -406,7 +408,7 @@ static void op_amd_shutdown(struct op_ms
 {
 	int i;
 
-	for (i = 0; i < NUM_COUNTERS; ++i) {
+	for (i = 0; i < num_counters; ++i) {
 		if (!msrs->counters[i].addr)
 			continue;
 		release_perfctr_nmi(MSR_K7_PERFCTR0 + i);
@@ -418,7 +420,7 @@ static int op_amd_fill_in_addresses(stru
 {
 	int i;
 
-	for (i = 0; i < NUM_COUNTERS; i++) {
+	for (i = 0; i < num_counters; i++) {
 		if (!reserve_perfctr_nmi(MSR_K7_PERFCTR0 + i))
 			goto fail;
 		if (!reserve_evntsel_nmi(MSR_K7_EVNTSEL0 + i)) {
@@ -426,8 +428,13 @@ static int op_amd_fill_in_addresses(stru
 			goto fail;
 		}
 		/* both registers must be reserved */
-		msrs->counters[i].addr = MSR_K7_PERFCTR0 + i;
-		msrs->controls[i].addr = MSR_K7_EVNTSEL0 + i;
+		if (num_counters == NUM_COUNTERS_F15H) {
+			msrs->counters[i].addr = MSR_F15H_PERF_CTR + (i << 1);
+			msrs->controls[i].addr = MSR_F15H_PERF_CTL + (i << 1);
+		} else {
+			msrs->controls[i].addr = MSR_K7_EVNTSEL0 + i;
+			msrs->counters[i].addr = MSR_K7_PERFCTR0 + i;
+		}
 		continue;
 	fail:
 		if (!counter_config[i].enabled)
@@ -447,7 +454,7 @@ static void op_amd_setup_ctrs(struct op_
 	int i;
 
 	/* setup reset_value */
-	for (i = 0; i < NUM_VIRT_COUNTERS; ++i) {
+	for (i = 0; i < OP_MAX_COUNTER; ++i) {
 		if (counter_config[i].enabled
 		    && msrs->counters[op_x86_virt_to_phys(i)].addr)
 			reset_value[i] = counter_config[i].count;
@@ -456,7 +463,7 @@ static void op_amd_setup_ctrs(struct op_
 	}
 
 	/* clear all counters */
-	for (i = 0; i < NUM_COUNTERS; ++i) {
+	for (i = 0; i < num_counters; ++i) {
 		if (!msrs->controls[i].addr)
 			continue;
 		rdmsrl(msrs->controls[i].addr, val);
@@ -472,7 +479,7 @@ static void op_amd_setup_ctrs(struct op_
 	}
 
 	/* enable active counters */
-	for (i = 0; i < NUM_COUNTERS; ++i) {
+	for (i = 0; i < num_counters; ++i) {
 		int virt = op_x86_phys_to_virt(i);
 		if (!reset_value[virt])
 			continue;
@@ -503,7 +510,7 @@ static int op_amd_check_ctrs(struct pt_r
 	u64 val;
 	int i;
 
-	for (i = 0; i < NUM_COUNTERS; ++i) {
+	for (i = 0; i < num_counters; ++i) {
 		int virt = op_x86_phys_to_virt(i);
 		if (!reset_value[virt])
 			continue;
@@ -526,7 +533,7 @@ static void op_amd_start(struct op_msrs
 	u64 val;
 	int i;
 
-	for (i = 0; i < NUM_COUNTERS; ++i) {
+	for (i = 0; i < num_counters; ++i) {
 		if (!reset_value[op_x86_phys_to_virt(i)])
 			continue;
 		rdmsrl(msrs->controls[i].addr, val);
@@ -546,7 +553,7 @@ static void op_amd_stop(struct op_msrs c
 	 * Subtle: stop on all counters to avoid race with setting our
 	 * pm callback
 	 */
-	for (i = 0; i < NUM_COUNTERS; ++i) {
+	for (i = 0; i < num_counters; ++i) {
 		if (!reset_value[op_x86_phys_to_virt(i)])
 			continue;
 		rdmsrl(msrs->controls[i].addr, val);
@@ -603,6 +610,7 @@ static int force_ibs_eilvt_setup(void)
 		ret = setup_ibs_ctl(i);
 		if (ret)
 			return ret;
+		pr_err(FW_BUG "using offset %d for IBS interrupts\n", i);
 		return 0;
 	}
 
@@ -706,18 +714,29 @@ static int setup_ibs_files(struct super_
 	return 0;
 }
 
+struct op_x86_model_spec op_amd_spec;
+
 static int op_amd_init(struct oprofile_operations *ops)
 {
 	init_ibs();
 	create_arch_files = ops->create_files;
 	ops->create_files = setup_ibs_files;
+
+	if (boot_cpu_data.x86 == 0x15) {
+		num_counters = NUM_COUNTERS_F15H;
+	} else {
+		num_counters = NUM_COUNTERS;
+	}
+
+	op_amd_spec.num_counters = num_counters;
+	op_amd_spec.num_controls = num_counters;
+	op_amd_spec.num_virt_counters = max(num_counters, NUM_VIRT_COUNTERS);
+
 	return 0;
 }
 
 struct op_x86_model_spec op_amd_spec = {
-	.num_counters		= NUM_COUNTERS,
-	.num_controls		= NUM_COUNTERS,
-	.num_virt_counters	= NUM_VIRT_COUNTERS,
+	/* num_counters/num_controls filled in at runtime */
 	.reserved		= MSR_AMD_EVENTSEL_RESERVED,
 	.event_mask		= OP_EVENT_MASK,
 	.init			= op_amd_init,
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/oprofile/op_model_p4.c linux-libre-2.6.38-gnu1/arch/x86/oprofile/op_model_p4.c
--- linux-libre-2.6.37-gnu1/arch/x86/oprofile/op_model_p4.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/oprofile/op_model_p4.c	2011-03-14 21:20:32.000000000 -0400
@@ -11,7 +11,7 @@
 #include <linux/oprofile.h>
 #include <linux/smp.h>
 #include <linux/ptrace.h>
-#include <linux/nmi.h>
+#include <asm/nmi.h>
 #include <asm/msr.h>
 #include <asm/fixmap.h>
 #include <asm/apic.h>
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/oprofile/op_model_ppro.c linux-libre-2.6.38-gnu1/arch/x86/oprofile/op_model_ppro.c
--- linux-libre-2.6.37-gnu1/arch/x86/oprofile/op_model_ppro.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/oprofile/op_model_ppro.c	2011-03-14 21:20:32.000000000 -0400
@@ -95,8 +95,8 @@ static void ppro_setup_ctrs(struct op_x8
 		 * counter width:
 		 */
 		if (!(eax.split.version_id == 0 &&
-			current_cpu_data.x86 == 6 &&
-				current_cpu_data.x86_model == 15)) {
+			__this_cpu_read(cpu_info.x86) == 6 &&
+				__this_cpu_read(cpu_info.x86_model) == 15)) {
 
 			if (counter_width < eax.split.bit_width)
 				counter_width = eax.split.bit_width;
@@ -235,8 +235,8 @@ static void arch_perfmon_setup_counters(
 	eax.full = cpuid_eax(0xa);
 
 	/* Workaround for BIOS bugs in 6/15. Taken from perfmon2 */
-	if (eax.split.version_id == 0 && current_cpu_data.x86 == 6 &&
-		current_cpu_data.x86_model == 15) {
+	if (eax.split.version_id == 0 && __this_cpu_read(cpu_info.x86) == 6 &&
+		__this_cpu_read(cpu_info.x86_model) == 15) {
 		eax.split.version_id = 2;
 		eax.split.num_counters = 2;
 		eax.split.bit_width = 40;
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/pci/amd_bus.c linux-libre-2.6.38-gnu1/arch/x86/pci/amd_bus.c
--- linux-libre-2.6.37-gnu1/arch/x86/pci/amd_bus.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/pci/amd_bus.c	2011-03-14 21:20:32.000000000 -0400
@@ -4,6 +4,7 @@
 #include <linux/cpu.h>
 #include <linux/range.h>
 
+#include <asm/amd_nb.h>
 #include <asm/pci_x86.h>
 
 #include <asm/pci-direct.h>
@@ -378,6 +379,34 @@ static struct notifier_block __cpuinitda
 	.notifier_call	= amd_cpu_notify,
 };
 
+static void __init pci_enable_pci_io_ecs(void)
+{
+#ifdef CONFIG_AMD_NB
+	unsigned int i, n;
+
+	for (n = i = 0; !n && amd_nb_bus_dev_ranges[i].dev_limit; ++i) {
+		u8 bus = amd_nb_bus_dev_ranges[i].bus;
+		u8 slot = amd_nb_bus_dev_ranges[i].dev_base;
+		u8 limit = amd_nb_bus_dev_ranges[i].dev_limit;
+
+		for (; slot < limit; ++slot) {
+			u32 val = read_pci_config(bus, slot, 3, 0);
+
+			if (!early_is_amd_nb(val))
+				continue;
+
+			val = read_pci_config(bus, slot, 3, 0x8c);
+			if (!(val & (ENABLE_CF8_EXT_CFG >> 32))) {
+				val |= ENABLE_CF8_EXT_CFG >> 32;
+				write_pci_config(bus, slot, 3, 0x8c, val);
+			}
+			++n;
+		}
+	}
+	pr_info("Extended Config Space enabled on %u nodes\n", n);
+#endif
+}
+
 static int __init pci_io_ecs_init(void)
 {
 	int cpu;
@@ -386,6 +415,10 @@ static int __init pci_io_ecs_init(void)
         if (boot_cpu_data.x86 < 0x10)
 		return 0;
 
+	/* Try the PCI method first. */
+	if (early_pci_allowed())
+		pci_enable_pci_io_ecs();
+
 	register_cpu_notifier(&amd_cpu_notifier);
 	for_each_online_cpu(cpu)
 		amd_cpu_notify(&amd_cpu_notifier, (unsigned long)CPU_ONLINE,
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/pci/broadcom_bus.c linux-libre-2.6.38-gnu1/arch/x86/pci/broadcom_bus.c
--- linux-libre-2.6.37-gnu1/arch/x86/pci/broadcom_bus.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/pci/broadcom_bus.c	2011-03-14 21:20:32.000000000 -0400
@@ -9,6 +9,7 @@
  * option) any later version.
  */
 
+#include <linux/acpi.h>
 #include <linux/delay.h>
 #include <linux/dmi.h>
 #include <linux/pci.h>
@@ -25,12 +26,14 @@ static void __devinit cnb20le_res(struct
 	u8 fbus, lbus;
 	int i;
 
+#ifdef CONFIG_ACPI
 	/*
-	 * The x86_pci_root_bus_res_quirks() function already refuses to use
-	 * this information if ACPI _CRS was used. Therefore, we don't bother
-	 * checking if ACPI is enabled, and just generate the information
-	 * for both the ACPI _CRS and no ACPI cases.
+	 * We should get host bridge information from ACPI unless the BIOS
+	 * doesn't support it.
 	 */
+	if (acpi_os_get_root_pointer())
+		return;
+#endif
 
 	info = &pci_root_info[pci_root_num];
 	pci_root_num++;
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/pci/ce4100.c linux-libre-2.6.38-gnu1/arch/x86/pci/ce4100.c
--- linux-libre-2.6.37-gnu1/arch/x86/pci/ce4100.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/pci/ce4100.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,316 @@
+/*
+ *  GPL LICENSE SUMMARY
+ *
+ *  Copyright(c) 2010 Intel Corporation. All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of version 2 of the GNU General Public License 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 St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *  The full GNU General Public License is included in this distribution
+ *  in the file called LICENSE.GPL.
+ *
+ *  Contact Information:
+ *    Intel Corporation
+ *    2200 Mission College Blvd.
+ *    Santa Clara, CA  97052
+ *
+ * This provides access methods for PCI registers that mis-behave on
+ * the CE4100. Each register can be assigned a private init, read and
+ * write routine. The exception to this is the bridge device.  The
+ * bridge device is the only device on bus zero (0) that requires any
+ * fixup so it is a special case ATM
+ */
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+
+#include <asm/ce4100.h>
+#include <asm/pci_x86.h>
+
+struct sim_reg {
+	u32 value;
+	u32 mask;
+};
+
+struct sim_dev_reg {
+	int dev_func;
+	int reg;
+	void (*init)(struct sim_dev_reg *reg);
+	void (*read)(struct sim_dev_reg *reg, u32 *value);
+	void (*write)(struct sim_dev_reg *reg, u32 value);
+	struct sim_reg sim_reg;
+};
+
+struct sim_reg_op {
+	void (*init)(struct sim_dev_reg *reg);
+	void (*read)(struct sim_dev_reg *reg, u32 value);
+	void (*write)(struct sim_dev_reg *reg, u32 value);
+};
+
+#define MB (1024 * 1024)
+#define KB (1024)
+#define SIZE_TO_MASK(size) (~(size - 1))
+
+#define DEFINE_REG(device, func, offset, size, init_op, read_op, write_op)\
+{ PCI_DEVFN(device, func), offset, init_op, read_op, write_op,\
+	{0, SIZE_TO_MASK(size)} },
+
+static void reg_init(struct sim_dev_reg *reg)
+{
+	pci_direct_conf1.read(0, 1, reg->dev_func, reg->reg, 4,
+			      &reg->sim_reg.value);
+}
+
+static void reg_read(struct sim_dev_reg *reg, u32 *value)
+{
+	unsigned long flags;
+
+	raw_spin_lock_irqsave(&pci_config_lock, flags);
+	*value = reg->sim_reg.value;
+	raw_spin_unlock_irqrestore(&pci_config_lock, flags);
+}
+
+static void reg_write(struct sim_dev_reg *reg, u32 value)
+{
+	unsigned long flags;
+
+	raw_spin_lock_irqsave(&pci_config_lock, flags);
+	reg->sim_reg.value = (value & reg->sim_reg.mask) |
+		(reg->sim_reg.value & ~reg->sim_reg.mask);
+	raw_spin_unlock_irqrestore(&pci_config_lock, flags);
+}
+
+static void sata_reg_init(struct sim_dev_reg *reg)
+{
+	pci_direct_conf1.read(0, 1, PCI_DEVFN(14, 0), 0x10, 4,
+			      &reg->sim_reg.value);
+	reg->sim_reg.value += 0x400;
+}
+
+static void ehci_reg_read(struct sim_dev_reg *reg, u32 *value)
+{
+	reg_read(reg, value);
+	if (*value != reg->sim_reg.mask)
+		*value |= 0x100;
+}
+
+void sata_revid_init(struct sim_dev_reg *reg)
+{
+	reg->sim_reg.value = 0x01060100;
+	reg->sim_reg.mask = 0;
+}
+
+static void sata_revid_read(struct sim_dev_reg *reg, u32 *value)
+{
+	reg_read(reg, value);
+}
+
+static struct sim_dev_reg bus1_fixups[] = {
+	DEFINE_REG(2, 0, 0x10, (16*MB), reg_init, reg_read, reg_write)
+	DEFINE_REG(2, 0, 0x14, (256), reg_init, reg_read, reg_write)
+	DEFINE_REG(2, 1, 0x10, (64*KB), reg_init, reg_read, reg_write)
+	DEFINE_REG(3, 0, 0x10, (64*KB), reg_init, reg_read, reg_write)
+	DEFINE_REG(4, 0, 0x10, (128*KB), reg_init, reg_read, reg_write)
+	DEFINE_REG(4, 1, 0x10, (128*KB), reg_init, reg_read, reg_write)
+	DEFINE_REG(6, 0, 0x10, (512*KB), reg_init, reg_read, reg_write)
+	DEFINE_REG(6, 1, 0x10, (512*KB), reg_init, reg_read, reg_write)
+	DEFINE_REG(6, 2, 0x10, (64*KB), reg_init, reg_read, reg_write)
+	DEFINE_REG(8, 0, 0x10, (1*MB), reg_init, reg_read, reg_write)
+	DEFINE_REG(8, 1, 0x10, (64*KB), reg_init, reg_read, reg_write)
+	DEFINE_REG(8, 2, 0x10, (64*KB), reg_init, reg_read, reg_write)
+	DEFINE_REG(9, 0, 0x10 , (1*MB), reg_init, reg_read, reg_write)
+	DEFINE_REG(9, 0, 0x14, (64*KB), reg_init, reg_read, reg_write)
+	DEFINE_REG(10, 0, 0x10, (256), reg_init, reg_read, reg_write)
+	DEFINE_REG(10, 0, 0x14, (256*MB), reg_init, reg_read, reg_write)
+	DEFINE_REG(11, 0, 0x10, (256), reg_init, reg_read, reg_write)
+	DEFINE_REG(11, 0, 0x14, (256), reg_init, reg_read, reg_write)
+	DEFINE_REG(11, 1, 0x10, (256), reg_init, reg_read, reg_write)
+	DEFINE_REG(11, 2, 0x10, (256), reg_init, reg_read, reg_write)
+	DEFINE_REG(11, 2, 0x14, (256), reg_init, reg_read, reg_write)
+	DEFINE_REG(11, 2, 0x18, (256), reg_init, reg_read, reg_write)
+	DEFINE_REG(11, 3, 0x10, (256), reg_init, reg_read, reg_write)
+	DEFINE_REG(11, 3, 0x14, (256), reg_init, reg_read, reg_write)
+	DEFINE_REG(11, 4, 0x10, (256), reg_init, reg_read, reg_write)
+	DEFINE_REG(11, 5, 0x10, (64*KB), reg_init, reg_read, reg_write)
+	DEFINE_REG(11, 6, 0x10, (256), reg_init, reg_read, reg_write)
+	DEFINE_REG(11, 7, 0x10, (64*KB), reg_init, reg_read, reg_write)
+	DEFINE_REG(12, 0, 0x10, (128*KB), reg_init, reg_read, reg_write)
+	DEFINE_REG(12, 0, 0x14, (256), reg_init, reg_read, reg_write)
+	DEFINE_REG(12, 1, 0x10, (1024), reg_init, reg_read, reg_write)
+	DEFINE_REG(13, 0, 0x10, (32*KB), reg_init, ehci_reg_read, reg_write)
+	DEFINE_REG(13, 1, 0x10, (32*KB), reg_init, ehci_reg_read, reg_write)
+	DEFINE_REG(14, 0, 0x8,  0, sata_revid_init, sata_revid_read, 0)
+	DEFINE_REG(14, 0, 0x10, 0, reg_init, reg_read, reg_write)
+	DEFINE_REG(14, 0, 0x14, 0, reg_init, reg_read, reg_write)
+	DEFINE_REG(14, 0, 0x18, 0, reg_init, reg_read, reg_write)
+	DEFINE_REG(14, 0, 0x1C, 0, reg_init, reg_read, reg_write)
+	DEFINE_REG(14, 0, 0x20, 0, reg_init, reg_read, reg_write)
+	DEFINE_REG(14, 0, 0x24, (0x200), sata_reg_init, reg_read, reg_write)
+	DEFINE_REG(15, 0, 0x10, (64*KB), reg_init, reg_read, reg_write)
+	DEFINE_REG(15, 0, 0x14, (64*KB), reg_init, reg_read, reg_write)
+	DEFINE_REG(16, 0, 0x10, (64*KB), reg_init, reg_read, reg_write)
+	DEFINE_REG(16, 0, 0x14, (64*MB), reg_init, reg_read, reg_write)
+	DEFINE_REG(16, 0, 0x18, (64*MB), reg_init, reg_read, reg_write)
+	DEFINE_REG(17, 0, 0x10, (128*KB), reg_init, reg_read, reg_write)
+	DEFINE_REG(18, 0, 0x10, (1*KB), reg_init, reg_read, reg_write)
+};
+
+static void __init init_sim_regs(void)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(bus1_fixups); i++) {
+		if (bus1_fixups[i].init)
+			bus1_fixups[i].init(&bus1_fixups[i]);
+	}
+}
+
+static inline void extract_bytes(u32 *value, int reg, int len)
+{
+	uint32_t mask;
+
+	*value >>= ((reg & 3) * 8);
+	mask = 0xFFFFFFFF >> ((4 - len) * 8);
+	*value &= mask;
+}
+
+int bridge_read(unsigned int devfn, int reg, int len, u32 *value)
+{
+	u32 av_bridge_base, av_bridge_limit;
+	int retval = 0;
+
+	switch (reg) {
+	/* Make BARs appear to not request any memory. */
+	case PCI_BASE_ADDRESS_0:
+	case PCI_BASE_ADDRESS_0 + 1:
+	case PCI_BASE_ADDRESS_0 + 2:
+	case PCI_BASE_ADDRESS_0 + 3:
+		*value = 0;
+		break;
+
+		/* Since subordinate bus number register is hardwired
+		 * to zero and read only, so do the simulation.
+		 */
+	case PCI_PRIMARY_BUS:
+		if (len == 4)
+			*value = 0x00010100;
+		break;
+
+	case PCI_SUBORDINATE_BUS:
+		*value = 1;
+		break;
+
+	case PCI_MEMORY_BASE:
+	case PCI_MEMORY_LIMIT:
+		/* Get the A/V bridge base address. */
+		pci_direct_conf1.read(0, 0, devfn,
+				PCI_BASE_ADDRESS_0, 4, &av_bridge_base);
+
+		av_bridge_limit = av_bridge_base + (512*MB - 1);
+		av_bridge_limit >>= 16;
+		av_bridge_limit &= 0xFFF0;
+
+		av_bridge_base >>= 16;
+		av_bridge_base &= 0xFFF0;
+
+		if (reg == PCI_MEMORY_LIMIT)
+			*value = av_bridge_limit;
+		else if (len == 2)
+			*value = av_bridge_base;
+		else
+			*value = (av_bridge_limit << 16) | av_bridge_base;
+		break;
+		/* Make prefetchable memory limit smaller than prefetchable
+		 * memory base, so not claim prefetchable memory space.
+		 */
+	case PCI_PREF_MEMORY_BASE:
+		*value = 0xFFF0;
+		break;
+	case PCI_PREF_MEMORY_LIMIT:
+		*value = 0x0;
+		break;
+		/* Make IO limit smaller than IO base, so not claim IO space. */
+	case PCI_IO_BASE:
+		*value = 0xF0;
+		break;
+	case PCI_IO_LIMIT:
+		*value = 0;
+		break;
+	default:
+		retval = 1;
+	}
+	return retval;
+}
+
+static int ce4100_conf_read(unsigned int seg, unsigned int bus,
+			    unsigned int devfn, int reg, int len, u32 *value)
+{
+	int i, retval = 1;
+
+	if (bus == 1) {
+		for (i = 0; i < ARRAY_SIZE(bus1_fixups); i++) {
+			if (bus1_fixups[i].dev_func == devfn &&
+			    bus1_fixups[i].reg == (reg & ~3) &&
+			    bus1_fixups[i].read) {
+				bus1_fixups[i].read(&(bus1_fixups[i]),
+						    value);
+				extract_bytes(value, reg, len);
+				return 0;
+			}
+		}
+	}
+
+	if (bus == 0 && (PCI_DEVFN(1, 0) == devfn) &&
+	    !bridge_read(devfn, reg, len, value))
+		return 0;
+
+	return pci_direct_conf1.read(seg, bus, devfn, reg, len, value);
+}
+
+static int ce4100_conf_write(unsigned int seg, unsigned int bus,
+			     unsigned int devfn, int reg, int len, u32 value)
+{
+	int i;
+
+	if (bus == 1) {
+		for (i = 0; i < ARRAY_SIZE(bus1_fixups); i++) {
+			if (bus1_fixups[i].dev_func == devfn &&
+			    bus1_fixups[i].reg == (reg & ~3) &&
+			    bus1_fixups[i].write) {
+				bus1_fixups[i].write(&(bus1_fixups[i]),
+						     value);
+				return 0;
+			}
+		}
+	}
+
+	/* Discard writes to A/V bridge BAR. */
+	if (bus == 0 && PCI_DEVFN(1, 0) == devfn &&
+	    ((reg & ~3) == PCI_BASE_ADDRESS_0))
+		return 0;
+
+	return pci_direct_conf1.write(seg, bus, devfn, reg, len, value);
+}
+
+struct pci_raw_ops ce4100_pci_conf = {
+	.read =	ce4100_conf_read,
+	.write = ce4100_conf_write,
+};
+
+int __init ce4100_pci_init(void)
+{
+	init_sim_regs();
+	raw_pci_ops = &ce4100_pci_conf;
+	/* Indicate caller that it should invoke pci_legacy_init() */
+	return 1;
+}
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/pci/common.c linux-libre-2.6.38-gnu1/arch/x86/pci/common.c
--- linux-libre-2.6.37-gnu1/arch/x86/pci/common.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/pci/common.c	2011-03-14 21:20:32.000000000 -0400
@@ -22,6 +22,7 @@ unsigned int pci_probe = PCI_PROBE_BIOS
 
 unsigned int pci_early_dump_regs;
 static int pci_bf_sort;
+static int smbios_type_b1_flag;
 int pci_routeirq;
 int noioapicquirk;
 #ifdef CONFIG_X86_REROUTE_FOR_BROKEN_BOOT_IRQS
@@ -185,6 +186,39 @@ static int __devinit set_bf_sort(const s
 	return 0;
 }
 
+static void __devinit read_dmi_type_b1(const struct dmi_header *dm,
+				       void *private_data)
+{
+	u8 *d = (u8 *)dm + 4;
+
+	if (dm->type != 0xB1)
+		return;
+	switch (((*(u32 *)d) >> 9) & 0x03) {
+	case 0x00:
+		printk(KERN_INFO "dmi type 0xB1 record - unknown flag\n");
+		break;
+	case 0x01: /* set pci=bfsort */
+		smbios_type_b1_flag = 1;
+		break;
+	case 0x02: /* do not set pci=bfsort */
+		smbios_type_b1_flag = 2;
+		break;
+	default:
+		break;
+	}
+}
+
+static int __devinit find_sort_method(const struct dmi_system_id *d)
+{
+	dmi_walk(read_dmi_type_b1, NULL);
+
+	if (smbios_type_b1_flag == 1) {
+		set_bf_sort(d);
+		return 0;
+	}
+	return -1;
+}
+
 /*
  * Enable renumbering of PCI bus# ranges to reach all PCI busses (Cardbus)
  */
@@ -213,6 +247,13 @@ static const struct dmi_system_id __devi
 	},
 #endif		/* __i386__ */
 	{
+		.callback = find_sort_method,
+		.ident = "Dell System",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
+		},
+	},
+	{
 		.callback = set_bf_sort,
 		.ident = "Dell PowerEdge 1950",
 		.matches = {
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/pci/irq.c linux-libre-2.6.38-gnu1/arch/x86/pci/irq.c
--- linux-libre-2.6.37-gnu1/arch/x86/pci/irq.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/pci/irq.c	2011-03-14 21:20:32.000000000 -0400
@@ -589,7 +589,8 @@ static __init int intel_router_probe(str
 	case PCI_DEVICE_ID_INTEL_ICH10_1:
 	case PCI_DEVICE_ID_INTEL_ICH10_2:
 	case PCI_DEVICE_ID_INTEL_ICH10_3:
-	case PCI_DEVICE_ID_INTEL_PATSBURG_LPC:
+	case PCI_DEVICE_ID_INTEL_PATSBURG_LPC_0:
+	case PCI_DEVICE_ID_INTEL_PATSBURG_LPC_1:
 		r->name = "PIIX/ICH";
 		r->get = pirq_piix_get;
 		r->set = pirq_piix_set;
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/pci/Makefile linux-libre-2.6.38-gnu1/arch/x86/pci/Makefile
--- linux-libre-2.6.37-gnu1/arch/x86/pci/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/pci/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -7,6 +7,7 @@ obj-$(CONFIG_PCI_OLPC)		+= olpc.o
 obj-$(CONFIG_PCI_XEN)		+= xen.o
 
 obj-y				+= fixup.o
+obj-$(CONFIG_X86_INTEL_CE)      += ce4100.o
 obj-$(CONFIG_ACPI)		+= acpi.o
 obj-y				+= legacy.o irq.o
 
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/pci/pcbios.c linux-libre-2.6.38-gnu1/arch/x86/pci/pcbios.c
--- linux-libre-2.6.37-gnu1/arch/x86/pci/pcbios.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/pci/pcbios.c	2011-03-14 21:20:32.000000000 -0400
@@ -9,6 +9,7 @@
 #include <linux/uaccess.h>
 #include <asm/pci_x86.h>
 #include <asm/pci-functions.h>
+#include <asm/cacheflush.h>
 
 /* BIOS32 signature: "_32_" */
 #define BIOS32_SIGNATURE	(('_' << 0) + ('3' << 8) + ('2' << 16) + ('_' << 24))
@@ -25,6 +26,27 @@
 #define PCIBIOS_HW_TYPE1_SPEC		0x10
 #define PCIBIOS_HW_TYPE2_SPEC		0x20
 
+int pcibios_enabled;
+
+/* According to the BIOS specification at:
+ * http://members.datafast.net.au/dft0802/specs/bios21.pdf, we could
+ * restrict the x zone to some pages and make it ro. But this may be
+ * broken on some bios, complex to handle with static_protections.
+ * We could make the 0xe0000-0x100000 range rox, but this can break
+ * some ISA mapping.
+ *
+ * So we let's an rw and x hole when pcibios is used. This shouldn't
+ * happen for modern system with mmconfig, and if you don't want it
+ * you could disable pcibios...
+ */
+static inline void set_bios_x(void)
+{
+	pcibios_enabled = 1;
+	set_memory_x(PAGE_OFFSET + BIOS_BEGIN, (BIOS_END - BIOS_BEGIN) >> PAGE_SHIFT);
+	if (__supported_pte_mask & _PAGE_NX)
+		printk(KERN_INFO "PCI : PCI BIOS aera is rw and x. Use pci=nobios if you want it NX.\n");
+}
+
 /*
  * This is the standard structure used to identify the entry point
  * to the BIOS32 Service Directory, as documented in
@@ -332,6 +354,7 @@ static struct pci_raw_ops * __devinit pc
 			DBG("PCI: BIOS32 Service Directory entry at 0x%lx\n",
 					bios32_entry);
 			bios32_indirect.address = bios32_entry + PAGE_OFFSET;
+			set_bios_x();
 			if (check_pcibios())
 				return &pci_bios_access;
 		}
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/platform/ce4100/ce4100.c linux-libre-2.6.38-gnu1/arch/x86/platform/ce4100/ce4100.c
--- linux-libre-2.6.37-gnu1/arch/x86/platform/ce4100/ce4100.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/platform/ce4100/ce4100.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,134 @@
+/*
+ * Intel CE4100  platform specific setup code
+ *
+ * (C) Copyright 2010 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; version 2
+ * of the License.
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/irq.h>
+#include <linux/module.h>
+#include <linux/serial_reg.h>
+#include <linux/serial_8250.h>
+
+#include <asm/ce4100.h>
+#include <asm/setup.h>
+#include <asm/io.h>
+
+static int ce4100_i8042_detect(void)
+{
+	return 0;
+}
+
+static void __init sdv_find_smp_config(void)
+{
+}
+
+#ifdef CONFIG_SERIAL_8250
+
+
+static unsigned int mem_serial_in(struct uart_port *p, int offset)
+{
+	offset = offset << p->regshift;
+	return readl(p->membase + offset);
+}
+
+/*
+ * The UART Tx interrupts are not set under some conditions and therefore serial
+ * transmission hangs. This is a silicon issue and has not been root caused. The
+ * workaround for this silicon issue checks UART_LSR_THRE bit and UART_LSR_TEMT
+ * bit of LSR register in interrupt handler to see whether at least one of these
+ * two bits is set, if so then process the transmit request. If this workaround
+ * is not applied, then the serial transmission may hang. This workaround is for
+ * errata number 9 in Errata - B step.
+*/
+
+static unsigned int ce4100_mem_serial_in(struct uart_port *p, int offset)
+{
+	unsigned int ret, ier, lsr;
+
+	if (offset == UART_IIR) {
+		offset = offset << p->regshift;
+		ret = readl(p->membase + offset);
+		if (ret & UART_IIR_NO_INT) {
+			/* see if the TX interrupt should have really set */
+			ier = mem_serial_in(p, UART_IER);
+			/* see if the UART's XMIT interrupt is enabled */
+			if (ier & UART_IER_THRI) {
+				lsr = mem_serial_in(p, UART_LSR);
+				/* now check to see if the UART should be
+				   generating an interrupt (but isn't) */
+				if (lsr & (UART_LSR_THRE | UART_LSR_TEMT))
+					ret &= ~UART_IIR_NO_INT;
+			}
+		}
+	} else
+		ret =  mem_serial_in(p, offset);
+	return ret;
+}
+
+static void ce4100_mem_serial_out(struct uart_port *p, int offset, int value)
+{
+	offset = offset << p->regshift;
+	writel(value, p->membase + offset);
+}
+
+static void ce4100_serial_fixup(int port, struct uart_port *up,
+	unsigned short *capabilites)
+{
+#ifdef CONFIG_EARLY_PRINTK
+	/*
+	 * Over ride the legacy port configuration that comes from
+	 * asm/serial.h. Using the ioport driver then switching to the
+	 * PCI memmaped driver hangs the IOAPIC
+	 */
+	if (up->iotype !=  UPIO_MEM32) {
+		up->uartclk  = 14745600;
+		up->mapbase = 0xdffe0200;
+		set_fixmap_nocache(FIX_EARLYCON_MEM_BASE,
+				up->mapbase & PAGE_MASK);
+		up->membase =
+			(void __iomem *)__fix_to_virt(FIX_EARLYCON_MEM_BASE);
+		up->membase += up->mapbase & ~PAGE_MASK;
+		up->iotype   = UPIO_MEM32;
+		up->regshift = 2;
+	}
+#endif
+	up->iobase = 0;
+	up->serial_in = ce4100_mem_serial_in;
+	up->serial_out = ce4100_mem_serial_out;
+
+	*capabilites |= (1 << 12);
+}
+
+static __init void sdv_serial_fixup(void)
+{
+	serial8250_set_isa_configurator(ce4100_serial_fixup);
+}
+
+#else
+static inline void sdv_serial_fixup(void);
+#endif
+
+static void __init sdv_arch_setup(void)
+{
+	sdv_serial_fixup();
+}
+
+/*
+ * CE4100 specific x86_init function overrides and early setup
+ * calls.
+ */
+void __init x86_ce4100_early_setup(void)
+{
+	x86_init.oem.arch_setup = sdv_arch_setup;
+	x86_platform.i8042_detect = ce4100_i8042_detect;
+	x86_init.resources.probe_roms = x86_init_noop;
+	x86_init.mpparse.get_smp_config = x86_init_uint_noop;
+	x86_init.mpparse.find_smp_config = sdv_find_smp_config;
+	x86_init.pci.init = ce4100_pci_init;
+}
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/platform/ce4100/Makefile linux-libre-2.6.38-gnu1/arch/x86/platform/ce4100/Makefile
--- linux-libre-2.6.37-gnu1/arch/x86/platform/ce4100/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/platform/ce4100/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1 @@
+obj-$(CONFIG_X86_INTEL_CE)	+= ce4100.o
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/platform/iris/iris.c linux-libre-2.6.38-gnu1/arch/x86/platform/iris/iris.c
--- linux-libre-2.6.37-gnu1/arch/x86/platform/iris/iris.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/platform/iris/iris.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,91 @@
+/*
+ * Eurobraille/Iris power off support.
+ *
+ * Eurobraille's Iris machine is a PC with no APM or ACPI support.
+ * It is shutdown by a special I/O sequence which this module provides.
+ *
+ *  Copyright (C) Shérab <Sebastien.Hinderer@ens-lyon.org>
+ *
+ * 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 the program ; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/moduleparam.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/pm.h>
+#include <asm/io.h>
+
+#define IRIS_GIO_BASE		0x340
+#define IRIS_GIO_INPUT		IRIS_GIO_BASE
+#define IRIS_GIO_OUTPUT		(IRIS_GIO_BASE + 1)
+#define IRIS_GIO_PULSE		0x80 /* First byte to send */
+#define IRIS_GIO_REST		0x00 /* Second byte to send */
+#define IRIS_GIO_NODEV		0xff /* Likely not an Iris */
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Sébastien Hinderer <Sebastien.Hinderer@ens-lyon.org>");
+MODULE_DESCRIPTION("A power_off handler for Iris devices from EuroBraille");
+MODULE_SUPPORTED_DEVICE("Eurobraille/Iris");
+
+static int force;
+
+module_param(force, bool, 0);
+MODULE_PARM_DESC(force, "Set to one to force poweroff handler installation.");
+
+static void (*old_pm_power_off)(void);
+
+static void iris_power_off(void)
+{
+	outb(IRIS_GIO_PULSE, IRIS_GIO_OUTPUT);
+	msleep(850);
+	outb(IRIS_GIO_REST, IRIS_GIO_OUTPUT);
+}
+
+/*
+ * Before installing the power_off handler, try to make sure the OS is
+ * running on an Iris.  Since Iris does not support DMI, this is done
+ * by reading its input port and seeing whether the read value is
+ * meaningful.
+ */
+static int iris_init(void)
+{
+	unsigned char status;
+	if (force != 1) {
+		printk(KERN_ERR "The force parameter has not been set to 1 so the Iris poweroff handler will not be installed.\n");
+		return -ENODEV;
+	}
+	status = inb(IRIS_GIO_INPUT);
+	if (status == IRIS_GIO_NODEV) {
+		printk(KERN_ERR "This machine does not seem to be an Iris. Power_off handler not installed.\n");
+		return -ENODEV;
+	}
+	old_pm_power_off = pm_power_off;
+	pm_power_off = &iris_power_off;
+	printk(KERN_INFO "Iris power_off handler installed.\n");
+
+	return 0;
+}
+
+static void iris_exit(void)
+{
+	pm_power_off = old_pm_power_off;
+	printk(KERN_INFO "Iris power_off handler uninstalled.\n");
+}
+
+module_init(iris_init);
+module_exit(iris_exit);
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/platform/iris/Makefile linux-libre-2.6.38-gnu1/arch/x86/platform/iris/Makefile
--- linux-libre-2.6.37-gnu1/arch/x86/platform/iris/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/platform/iris/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1 @@
+obj-$(CONFIG_X86_32_IRIS)		+= iris.o
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/platform/Makefile linux-libre-2.6.38-gnu1/arch/x86/platform/Makefile
--- linux-libre-2.6.37-gnu1/arch/x86/platform/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/platform/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -1,5 +1,7 @@
 # Platform specific code goes here
+obj-y	+= ce4100/
 obj-y	+= efi/
+obj-y	+= iris/
 obj-y	+= mrst/
 obj-y	+= olpc/
 obj-y	+= scx200/
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/platform/mrst/early_printk_mrst.c linux-libre-2.6.38-gnu1/arch/x86/platform/mrst/early_printk_mrst.c
--- linux-libre-2.6.37-gnu1/arch/x86/platform/mrst/early_printk_mrst.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/platform/mrst/early_printk_mrst.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,319 @@
+/*
+ * early_printk_mrst.c - early consoles for Intel MID platforms
+ *
+ * Copyright (c) 2008-2010, 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; version 2
+ * of the License.
+ */
+
+/*
+ * This file implements two early consoles named mrst and hsu.
+ * mrst is based on Maxim3110 spi-uart device, it exists in both
+ * Moorestown and Medfield platforms, while hsu is based on a High
+ * Speed UART device which only exists in the Medfield platform
+ */
+
+#include <linux/serial_reg.h>
+#include <linux/serial_mfd.h>
+#include <linux/kmsg_dump.h>
+#include <linux/console.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/io.h>
+
+#include <asm/fixmap.h>
+#include <asm/pgtable.h>
+#include <asm/mrst.h>
+
+#define MRST_SPI_TIMEOUT		0x200000
+#define MRST_REGBASE_SPI0		0xff128000
+#define MRST_REGBASE_SPI1		0xff128400
+#define MRST_CLK_SPI0_REG		0xff11d86c
+
+/* Bit fields in CTRLR0 */
+#define SPI_DFS_OFFSET			0
+
+#define SPI_FRF_OFFSET			4
+#define SPI_FRF_SPI			0x0
+#define SPI_FRF_SSP			0x1
+#define SPI_FRF_MICROWIRE		0x2
+#define SPI_FRF_RESV			0x3
+
+#define SPI_MODE_OFFSET			6
+#define SPI_SCPH_OFFSET			6
+#define SPI_SCOL_OFFSET			7
+#define SPI_TMOD_OFFSET			8
+#define	SPI_TMOD_TR			0x0		/* xmit & recv */
+#define SPI_TMOD_TO			0x1		/* xmit only */
+#define SPI_TMOD_RO			0x2		/* recv only */
+#define SPI_TMOD_EPROMREAD		0x3		/* eeprom read mode */
+
+#define SPI_SLVOE_OFFSET		10
+#define SPI_SRL_OFFSET			11
+#define SPI_CFS_OFFSET			12
+
+/* Bit fields in SR, 7 bits */
+#define SR_MASK				0x7f		/* cover 7 bits */
+#define SR_BUSY				(1 << 0)
+#define SR_TF_NOT_FULL			(1 << 1)
+#define SR_TF_EMPT			(1 << 2)
+#define SR_RF_NOT_EMPT			(1 << 3)
+#define SR_RF_FULL			(1 << 4)
+#define SR_TX_ERR			(1 << 5)
+#define SR_DCOL				(1 << 6)
+
+struct dw_spi_reg {
+	u32	ctrl0;
+	u32	ctrl1;
+	u32	ssienr;
+	u32	mwcr;
+	u32	ser;
+	u32	baudr;
+	u32	txfltr;
+	u32	rxfltr;
+	u32	txflr;
+	u32	rxflr;
+	u32	sr;
+	u32	imr;
+	u32	isr;
+	u32	risr;
+	u32	txoicr;
+	u32	rxoicr;
+	u32	rxuicr;
+	u32	msticr;
+	u32	icr;
+	u32	dmacr;
+	u32	dmatdlr;
+	u32	dmardlr;
+	u32	idr;
+	u32	version;
+
+	/* Currently operates as 32 bits, though only the low 16 bits matter */
+	u32	dr;
+} __packed;
+
+#define dw_readl(dw, name)		__raw_readl(&(dw)->name)
+#define dw_writel(dw, name, val)	__raw_writel((val), &(dw)->name)
+
+/* Default use SPI0 register for mrst, we will detect Penwell and use SPI1 */
+static unsigned long mrst_spi_paddr = MRST_REGBASE_SPI0;
+
+static u32 *pclk_spi0;
+/* Always contains an accessible address, start with 0 */
+static struct dw_spi_reg *pspi;
+
+static struct kmsg_dumper dw_dumper;
+static int dumper_registered;
+
+static void dw_kmsg_dump(struct kmsg_dumper *dumper,
+			enum kmsg_dump_reason reason,
+			const char *s1, unsigned long l1,
+			const char *s2, unsigned long l2)
+{
+	int i;
+
+	/* When run to this, we'd better re-init the HW */
+	mrst_early_console_init();
+
+	for (i = 0; i < l1; i++)
+		early_mrst_console.write(&early_mrst_console, s1 + i, 1);
+	for (i = 0; i < l2; i++)
+		early_mrst_console.write(&early_mrst_console, s2 + i, 1);
+}
+
+/* Set the ratio rate to 115200, 8n1, IRQ disabled */
+static void max3110_write_config(void)
+{
+	u16 config;
+
+	config = 0xc001;
+	dw_writel(pspi, dr, config);
+}
+
+/* Translate char to a eligible word and send to max3110 */
+static void max3110_write_data(char c)
+{
+	u16 data;
+
+	data = 0x8000 | c;
+	dw_writel(pspi, dr, data);
+}
+
+void mrst_early_console_init(void)
+{
+	u32 ctrlr0 = 0;
+	u32 spi0_cdiv;
+	u32 freq; /* Freqency info only need be searched once */
+
+	/* Base clk is 100 MHz, the actual clk = 100M / (clk_divider + 1) */
+	pclk_spi0 = (void *)set_fixmap_offset_nocache(FIX_EARLYCON_MEM_BASE,
+							MRST_CLK_SPI0_REG);
+	spi0_cdiv = ((*pclk_spi0) & 0xe00) >> 9;
+	freq = 100000000 / (spi0_cdiv + 1);
+
+	if (mrst_identify_cpu() == MRST_CPU_CHIP_PENWELL)
+		mrst_spi_paddr = MRST_REGBASE_SPI1;
+
+	pspi = (void *)set_fixmap_offset_nocache(FIX_EARLYCON_MEM_BASE,
+						mrst_spi_paddr);
+
+	/* Disable SPI controller */
+	dw_writel(pspi, ssienr, 0);
+
+	/* Set control param, 8 bits, transmit only mode */
+	ctrlr0 = dw_readl(pspi, ctrl0);
+
+	ctrlr0 &= 0xfcc0;
+	ctrlr0 |= 0xf | (SPI_FRF_SPI << SPI_FRF_OFFSET)
+		      | (SPI_TMOD_TO << SPI_TMOD_OFFSET);
+	dw_writel(pspi, ctrl0, ctrlr0);
+
+	/*
+	 * Change the spi0 clk to comply with 115200 bps, use 100000 to
+	 * calculate the clk dividor to make the clock a little slower
+	 * than real baud rate.
+	 */
+	dw_writel(pspi, baudr, freq/100000);
+
+	/* Disable all INT for early phase */
+	dw_writel(pspi, imr, 0x0);
+
+	/* Set the cs to spi-uart */
+	dw_writel(pspi, ser, 0x2);
+
+	/* Enable the HW, the last step for HW init */
+	dw_writel(pspi, ssienr, 0x1);
+
+	/* Set the default configuration */
+	max3110_write_config();
+
+	/* Register the kmsg dumper */
+	if (!dumper_registered) {
+		dw_dumper.dump = dw_kmsg_dump;
+		kmsg_dump_register(&dw_dumper);
+		dumper_registered = 1;
+	}
+}
+
+/* Slave select should be called in the read/write function */
+static void early_mrst_spi_putc(char c)
+{
+	unsigned int timeout;
+	u32 sr;
+
+	timeout = MRST_SPI_TIMEOUT;
+	/* Early putc needs to make sure the TX FIFO is not full */
+	while (--timeout) {
+		sr = dw_readl(pspi, sr);
+		if (!(sr & SR_TF_NOT_FULL))
+			cpu_relax();
+		else
+			break;
+	}
+
+	if (!timeout)
+		pr_warning("MRST earlycon: timed out\n");
+	else
+		max3110_write_data(c);
+}
+
+/* Early SPI only uses polling mode */
+static void early_mrst_spi_write(struct console *con, const char *str, unsigned n)
+{
+	int i;
+
+	for (i = 0; i < n && *str; i++) {
+		if (*str == '\n')
+			early_mrst_spi_putc('\r');
+		early_mrst_spi_putc(*str);
+		str++;
+	}
+}
+
+struct console early_mrst_console = {
+	.name =		"earlymrst",
+	.write =	early_mrst_spi_write,
+	.flags =	CON_PRINTBUFFER,
+	.index =	-1,
+};
+
+/*
+ * Following is the early console based on Medfield HSU (High
+ * Speed UART) device.
+ */
+#define HSU_PORT2_PADDR		0xffa28180
+
+static void __iomem *phsu;
+
+void hsu_early_console_init(void)
+{
+	u8 lcr;
+
+	phsu = (void *)set_fixmap_offset_nocache(FIX_EARLYCON_MEM_BASE,
+							HSU_PORT2_PADDR);
+
+	/* Disable FIFO */
+	writeb(0x0, phsu + UART_FCR);
+
+	/* Set to default 115200 bps, 8n1 */
+	lcr = readb(phsu + UART_LCR);
+	writeb((0x80 | lcr), phsu + UART_LCR);
+	writeb(0x18, phsu + UART_DLL);
+	writeb(lcr,  phsu + UART_LCR);
+	writel(0x3600, phsu + UART_MUL*4);
+
+	writeb(0x8, phsu + UART_MCR);
+	writeb(0x7, phsu + UART_FCR);
+	writeb(0x3, phsu + UART_LCR);
+
+	/* Clear IRQ status */
+	readb(phsu + UART_LSR);
+	readb(phsu + UART_RX);
+	readb(phsu + UART_IIR);
+	readb(phsu + UART_MSR);
+
+	/* Enable FIFO */
+	writeb(0x7, phsu + UART_FCR);
+}
+
+#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
+
+static void early_hsu_putc(char ch)
+{
+	unsigned int timeout = 10000; /* 10ms */
+	u8 status;
+
+	while (--timeout) {
+		status = readb(phsu + UART_LSR);
+		if (status & BOTH_EMPTY)
+			break;
+		udelay(1);
+	}
+
+	/* Only write the char when there was no timeout */
+	if (timeout)
+		writeb(ch, phsu + UART_TX);
+}
+
+static void early_hsu_write(struct console *con, const char *str, unsigned n)
+{
+	int i;
+
+	for (i = 0; i < n && *str; i++) {
+		if (*str == '\n')
+			early_hsu_putc('\r');
+		early_hsu_putc(*str);
+		str++;
+	}
+}
+
+struct console early_hsu_console = {
+	.name =		"earlyhsu",
+	.write =	early_hsu_write,
+	.flags =	CON_PRINTBUFFER,
+	.index =	-1,
+};
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/platform/mrst/Makefile linux-libre-2.6.38-gnu1/arch/x86/platform/mrst/Makefile
--- linux-libre-2.6.37-gnu1/arch/x86/platform/mrst/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/platform/mrst/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -1 +1,3 @@
 obj-$(CONFIG_X86_MRST)		+= mrst.o
+obj-$(CONFIG_X86_MRST)		+= vrtc.o
+obj-$(CONFIG_EARLY_PRINTK_MRST)	+= early_printk_mrst.o
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/platform/mrst/mrst.c linux-libre-2.6.38-gnu1/arch/x86/platform/mrst/mrst.c
--- linux-libre-2.6.37-gnu1/arch/x86/platform/mrst/mrst.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/platform/mrst/mrst.c	2011-03-14 21:20:32.000000000 -0400
@@ -9,9 +9,19 @@
  * as published by the Free Software Foundation; version 2
  * of the License.
  */
+
+#define pr_fmt(fmt) "mrst: " fmt
+
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/sfi.h>
+#include <linux/intel_pmic_gpio.h>
+#include <linux/spi/spi.h>
+#include <linux/i2c.h>
+#include <linux/i2c/pca953x.h>
+#include <linux/gpio_keys.h>
+#include <linux/input.h>
+#include <linux/platform_device.h>
 #include <linux/irq.h>
 #include <linux/module.h>
 
@@ -23,7 +33,9 @@
 #include <asm/mrst.h>
 #include <asm/io.h>
 #include <asm/i8259.h>
+#include <asm/intel_scu_ipc.h>
 #include <asm/apb_timer.h>
+#include <asm/reboot.h>
 
 /*
  * the clockevent devices on Moorestown/Medfield can be APBT or LAPIC clock,
@@ -59,32 +71,6 @@ struct sfi_rtc_table_entry sfi_mrtc_arra
 EXPORT_SYMBOL_GPL(sfi_mrtc_array);
 int sfi_mrtc_num;
 
-static inline void assign_to_mp_irq(struct mpc_intsrc *m,
-				    struct mpc_intsrc *mp_irq)
-{
-	memcpy(mp_irq, m, sizeof(struct mpc_intsrc));
-}
-
-static inline int mp_irq_cmp(struct mpc_intsrc *mp_irq,
-				struct mpc_intsrc *m)
-{
-	return memcmp(mp_irq, m, sizeof(struct mpc_intsrc));
-}
-
-static void save_mp_irq(struct mpc_intsrc *m)
-{
-	int i;
-
-	for (i = 0; i < mp_irq_entries; i++) {
-		if (!mp_irq_cmp(&mp_irqs[i], m))
-			return;
-	}
-
-	assign_to_mp_irq(m, &mp_irqs[mp_irq_entries]);
-	if (++mp_irq_entries == MAX_IRQ_SOURCES)
-		panic("Max # of irq sources exceeded!!\n");
-}
-
 /* parse all the mtimer info to a static mtimer array */
 static int __init sfi_parse_mtmr(struct sfi_table_header *table)
 {
@@ -102,10 +88,10 @@ static int __init sfi_parse_mtmr(struct
 		memcpy(sfi_mtimer_array, pentry, totallen);
 	}
 
-	printk(KERN_INFO "SFI: MTIMER info (num = %d):\n", sfi_mtimer_num);
+	pr_debug("SFI MTIMER info (num = %d):\n", sfi_mtimer_num);
 	pentry = sfi_mtimer_array;
 	for (totallen = 0; totallen < sfi_mtimer_num; totallen++, pentry++) {
-		printk(KERN_INFO "timer[%d]: paddr = 0x%08x, freq = %dHz,"
+		pr_debug("timer[%d]: paddr = 0x%08x, freq = %dHz,"
 			" irq = %d\n", totallen, (u32)pentry->phys_addr,
 			pentry->freq_hz, pentry->irq);
 			if (!pentry->irq)
@@ -118,7 +104,7 @@ static int __init sfi_parse_mtmr(struct
 			mp_irq.srcbusirq = pentry->irq;	/* IRQ */
 			mp_irq.dstapic = MP_APIC_ALL;
 			mp_irq.dstirq = pentry->irq;
-			save_mp_irq(&mp_irq);
+			mp_save_irq(&mp_irq);
 	}
 
 	return 0;
@@ -176,19 +162,19 @@ int __init sfi_parse_mrtc(struct sfi_tab
 		memcpy(sfi_mrtc_array, pentry, totallen);
 	}
 
-	printk(KERN_INFO "SFI: RTC info (num = %d):\n", sfi_mrtc_num);
+	pr_debug("SFI RTC info (num = %d):\n", sfi_mrtc_num);
 	pentry = sfi_mrtc_array;
 	for (totallen = 0; totallen < sfi_mrtc_num; totallen++, pentry++) {
-		printk(KERN_INFO "RTC[%d]: paddr = 0x%08x, irq = %d\n",
+		pr_debug("RTC[%d]: paddr = 0x%08x, irq = %d\n",
 			totallen, (u32)pentry->phys_addr, pentry->irq);
 		mp_irq.type = MP_IOAPIC;
 		mp_irq.irqtype = mp_INT;
-		mp_irq.irqflag = 0;
+		mp_irq.irqflag = 0xf;	/* level trigger and active low */
 		mp_irq.srcbus = 0;
 		mp_irq.srcbusirq = pentry->irq;	/* IRQ */
 		mp_irq.dstapic = MP_APIC_ALL;
 		mp_irq.dstirq = pentry->irq;
-		save_mp_irq(&mp_irq);
+		mp_save_irq(&mp_irq);
 	}
 	return 0;
 }
@@ -209,6 +195,7 @@ static unsigned long __init mrst_calibra
 
 void __init mrst_time_init(void)
 {
+	sfi_table_parse(SFI_SIG_MTMR, NULL, NULL, sfi_parse_mtmr);
 	switch (mrst_timer_options) {
 	case MRST_TIMER_APBT_ONLY:
 		break;
@@ -224,16 +211,10 @@ void __init mrst_time_init(void)
 		return;
 	}
 	/* we need at least one APB timer */
-	sfi_table_parse(SFI_SIG_MTMR, NULL, NULL, sfi_parse_mtmr);
 	pre_init_apic_IRQ0();
 	apbt_time_init();
 }
 
-void __init mrst_rtc_init(void)
-{
-	sfi_table_parse(SFI_SIG_MRTC, NULL, NULL, sfi_parse_mrtc);
-}
-
 void __cpuinit mrst_arch_setup(void)
 {
 	if (boot_cpu_data.x86 == 6 && boot_cpu_data.x86_model == 0x27)
@@ -256,6 +237,17 @@ 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)
+{
+	intel_scu_ipc_simple_command(0xf1, 0);
+}
+
 /*
  * Moorestown specific x86_init function overrides and early setup
  * calls.
@@ -281,6 +273,10 @@ void __init x86_mrst_early_setup(void)
 
 	legacy_pic = &null_legacy_pic;
 
+	/* Moorestown specific power_off/restart method */
+	pm_power_off = mrst_power_off;
+	machine_ops.emergency_restart  = mrst_reboot;
+
 	/* Avoid searching for BIOS MP tables */
 	x86_init.mpparse.find_smp_config = x86_init_noop;
 	x86_init.mpparse.get_smp_config = x86_init_uint_noop;
@@ -309,3 +305,505 @@ static inline int __init setup_x86_mrst_
 	return 0;
 }
 __setup("x86_mrst_timer=", setup_x86_mrst_timer);
+
+/*
+ * Parsing GPIO table first, since the DEVS table will need this table
+ * to map the pin name to the actual pin.
+ */
+static struct sfi_gpio_table_entry *gpio_table;
+static int gpio_num_entry;
+
+static int __init sfi_parse_gpio(struct sfi_table_header *table)
+{
+	struct sfi_table_simple *sb;
+	struct sfi_gpio_table_entry *pentry;
+	int num, i;
+
+	if (gpio_table)
+		return 0;
+	sb = (struct sfi_table_simple *)table;
+	num = SFI_GET_NUM_ENTRIES(sb, struct sfi_gpio_table_entry);
+	pentry = (struct sfi_gpio_table_entry *)sb->pentry;
+
+	gpio_table = (struct sfi_gpio_table_entry *)
+				kmalloc(num * sizeof(*pentry), GFP_KERNEL);
+	if (!gpio_table)
+		return -1;
+	memcpy(gpio_table, pentry, num * sizeof(*pentry));
+	gpio_num_entry = num;
+
+	pr_debug("GPIO pin info:\n");
+	for (i = 0; i < num; i++, pentry++)
+		pr_debug("info[%2d]: controller = %16.16s, pin_name = %16.16s,"
+		" pin = %d\n", i,
+			pentry->controller_name,
+			pentry->pin_name,
+			pentry->pin_no);
+	return 0;
+}
+
+static int get_gpio_by_name(const char *name)
+{
+	struct sfi_gpio_table_entry *pentry = gpio_table;
+	int i;
+
+	if (!pentry)
+		return -1;
+	for (i = 0; i < gpio_num_entry; i++, pentry++) {
+		if (!strncmp(name, pentry->pin_name, SFI_NAME_LEN))
+			return pentry->pin_no;
+	}
+	return -1;
+}
+
+/*
+ * Here defines the array of devices platform data that IAFW would export
+ * through SFI "DEVS" table, we use name and type to match the device and
+ * its platform data.
+ */
+struct devs_id {
+	char name[SFI_NAME_LEN + 1];
+	u8 type;
+	u8 delay;
+	void *(*get_platform_data)(void *info);
+};
+
+/* the offset for the mapping of global gpio pin to irq */
+#define MRST_IRQ_OFFSET 0x100
+
+static void __init *pmic_gpio_platform_data(void *info)
+{
+	static struct intel_pmic_gpio_platform_data pmic_gpio_pdata;
+	int gpio_base = get_gpio_by_name("pmic_gpio_base");
+
+	if (gpio_base == -1)
+		gpio_base = 64;
+	pmic_gpio_pdata.gpio_base = gpio_base;
+	pmic_gpio_pdata.irq_base = gpio_base + MRST_IRQ_OFFSET;
+	pmic_gpio_pdata.gpiointr = 0xffffeff8;
+
+	return &pmic_gpio_pdata;
+}
+
+static void __init *max3111_platform_data(void *info)
+{
+	struct spi_board_info *spi_info = info;
+	int intr = get_gpio_by_name("max3111_int");
+
+	if (intr == -1)
+		return NULL;
+	spi_info->irq = intr + MRST_IRQ_OFFSET;
+	return NULL;
+}
+
+/* we have multiple max7315 on the board ... */
+#define MAX7315_NUM 2
+static void __init *max7315_platform_data(void *info)
+{
+	static struct pca953x_platform_data max7315_pdata[MAX7315_NUM];
+	static int nr;
+	struct pca953x_platform_data *max7315 = &max7315_pdata[nr];
+	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];
+
+	if (nr == MAX7315_NUM) {
+		pr_err("too many max7315s, we only support %d\n",
+				MAX7315_NUM);
+		return NULL;
+	}
+	/* we have several max7315 on the board, we only need load several
+	 * instances of the same pca953x driver to cover them
+	 */
+	strcpy(i2c_info->type, "max7315");
+	if (nr++) {
+		sprintf(base_pin_name, "max7315_%d_base", nr);
+		sprintf(intr_pin_name, "max7315_%d_int", nr);
+	} else {
+		strcpy(base_pin_name, "max7315_base");
+		strcpy(intr_pin_name, "max7315_int");
+	}
+
+	gpio_base = get_gpio_by_name(base_pin_name);
+	intr = get_gpio_by_name(intr_pin_name);
+
+	if (gpio_base == -1)
+		return NULL;
+	max7315->gpio_base = gpio_base;
+	if (intr != -1) {
+		i2c_info->irq = intr + MRST_IRQ_OFFSET;
+		max7315->irq_base = gpio_base + MRST_IRQ_OFFSET;
+	} else {
+		i2c_info->irq = -1;
+		max7315->irq_base = -1;
+	}
+	return max7315;
+}
+
+static void __init *emc1403_platform_data(void *info)
+{
+	static short intr2nd_pdata;
+	struct i2c_board_info *i2c_info = info;
+	int intr = get_gpio_by_name("thermal_int");
+	int intr2nd = get_gpio_by_name("thermal_alert");
+
+	if (intr == -1 || intr2nd == -1)
+		return NULL;
+
+	i2c_info->irq = intr + MRST_IRQ_OFFSET;
+	intr2nd_pdata = intr2nd + MRST_IRQ_OFFSET;
+
+	return &intr2nd_pdata;
+}
+
+static void __init *lis331dl_platform_data(void *info)
+{
+	static short intr2nd_pdata;
+	struct i2c_board_info *i2c_info = info;
+	int intr = get_gpio_by_name("accel_int");
+	int intr2nd = get_gpio_by_name("accel_2");
+
+	if (intr == -1 || intr2nd == -1)
+		return NULL;
+
+	i2c_info->irq = intr + MRST_IRQ_OFFSET;
+	intr2nd_pdata = intr2nd + MRST_IRQ_OFFSET;
+
+	return &intr2nd_pdata;
+}
+
+static void __init *no_platform_data(void *info)
+{
+	return NULL;
+}
+
+static const struct devs_id __initconst device_ids[] = {
+	{"pmic_gpio", SFI_DEV_TYPE_SPI, 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},
+	{"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},
+	{},
+};
+
+#define MAX_IPCDEVS	24
+static struct platform_device *ipc_devs[MAX_IPCDEVS];
+static int ipc_next_dev;
+
+#define MAX_SCU_SPI	24
+static struct spi_board_info *spi_devs[MAX_SCU_SPI];
+static int spi_next_dev;
+
+#define MAX_SCU_I2C	24
+static struct i2c_board_info *i2c_devs[MAX_SCU_I2C];
+static int i2c_bus[MAX_SCU_I2C];
+static int i2c_next_dev;
+
+static void __init intel_scu_device_register(struct platform_device *pdev)
+{
+	if(ipc_next_dev == MAX_IPCDEVS)
+		pr_err("too many SCU IPC devices");
+	else
+		ipc_devs[ipc_next_dev++] = pdev;
+}
+
+static void __init intel_scu_spi_device_register(struct spi_board_info *sdev)
+{
+	struct spi_board_info *new_dev;
+
+	if (spi_next_dev == MAX_SCU_SPI) {
+		pr_err("too many SCU SPI devices");
+		return;
+	}
+
+	new_dev = kzalloc(sizeof(*sdev), GFP_KERNEL);
+	if (!new_dev) {
+		pr_err("failed to alloc mem for delayed spi dev %s\n",
+			sdev->modalias);
+		return;
+	}
+	memcpy(new_dev, sdev, sizeof(*sdev));
+
+	spi_devs[spi_next_dev++] = new_dev;
+}
+
+static void __init intel_scu_i2c_device_register(int bus,
+						struct i2c_board_info *idev)
+{
+	struct i2c_board_info *new_dev;
+
+	if (i2c_next_dev == MAX_SCU_I2C) {
+		pr_err("too many SCU I2C devices");
+		return;
+	}
+
+	new_dev = kzalloc(sizeof(*idev), GFP_KERNEL);
+	if (!new_dev) {
+		pr_err("failed to alloc mem for delayed i2c dev %s\n",
+			idev->type);
+		return;
+	}
+	memcpy(new_dev, idev, sizeof(*idev));
+
+	i2c_bus[i2c_next_dev] = bus;
+	i2c_devs[i2c_next_dev++] = new_dev;
+}
+
+/* Called by IPC driver */
+void intel_scu_devices_create(void)
+{
+	int i;
+
+	for (i = 0; i < ipc_next_dev; i++)
+		platform_device_add(ipc_devs[i]);
+
+	for (i = 0; i < spi_next_dev; i++)
+		spi_register_board_info(spi_devs[i], 1);
+
+	for (i = 0; i < i2c_next_dev; i++) {
+		struct i2c_adapter *adapter;
+		struct i2c_client *client;
+
+		adapter = i2c_get_adapter(i2c_bus[i]);
+		if (adapter) {
+			client = i2c_new_device(adapter, i2c_devs[i]);
+			if (!client)
+				pr_err("can't create i2c device %s\n",
+					i2c_devs[i]->type);
+		} else
+			i2c_register_board_info(i2c_bus[i], i2c_devs[i], 1);
+	}
+}
+EXPORT_SYMBOL_GPL(intel_scu_devices_create);
+
+/* Called by IPC driver */
+void intel_scu_devices_destroy(void)
+{
+	int i;
+
+	for (i = 0; i < ipc_next_dev; i++)
+		platform_device_del(ipc_devs[i]);
+}
+EXPORT_SYMBOL_GPL(intel_scu_devices_destroy);
+
+static void __init install_irq_resource(struct platform_device *pdev, int irq)
+{
+	/* Single threaded */
+	static struct resource __initdata res = {
+		.name = "IRQ",
+		.flags = IORESOURCE_IRQ,
+	};
+	res.start = irq;
+	platform_device_add_resources(pdev, &res, 1);
+}
+
+static void __init sfi_handle_ipc_dev(struct platform_device *pdev)
+{
+	const struct devs_id *dev = device_ids;
+	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);
+			break;
+		}
+		dev++;
+	}
+	pdev->dev.platform_data = pdata;
+	intel_scu_device_register(pdev);
+}
+
+static void __init sfi_handle_spi_dev(struct spi_board_info *spi_info)
+{
+	const struct devs_id *dev = device_ids;
+	void *pdata = NULL;
+
+	while (dev->name[0]) {
+		if (dev->type == SFI_DEV_TYPE_SPI &&
+				!strncmp(dev->name, spi_info->modalias, SFI_NAME_LEN)) {
+			pdata = dev->get_platform_data(spi_info);
+			break;
+		}
+		dev++;
+	}
+	spi_info->platform_data = pdata;
+	if (dev->delay)
+		intel_scu_spi_device_register(spi_info);
+	else
+		spi_register_board_info(spi_info, 1);
+}
+
+static void __init sfi_handle_i2c_dev(int bus, struct i2c_board_info *i2c_info)
+{
+	const struct devs_id *dev = device_ids;
+	void *pdata = NULL;
+
+	while (dev->name[0]) {
+		if (dev->type == SFI_DEV_TYPE_I2C &&
+			!strncmp(dev->name, i2c_info->type, SFI_NAME_LEN)) {
+			pdata = dev->get_platform_data(i2c_info);
+			break;
+		}
+		dev++;
+	}
+	i2c_info->platform_data = pdata;
+
+	if (dev->delay)
+		intel_scu_i2c_device_register(bus, i2c_info);
+	else
+		i2c_register_board_info(bus, i2c_info, 1);
+ }
+
+
+static int __init sfi_parse_devs(struct sfi_table_header *table)
+{
+	struct sfi_table_simple *sb;
+	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;
+
+	sb = (struct sfi_table_simple *)table;
+	num = SFI_GET_NUM_ENTRIES(sb, struct sfi_device_table_entry);
+	pentry = (struct sfi_device_table_entry *)sb->pentry;
+
+	for (i = 0; i < num; i++, pentry++) {
+		if (pentry->irq != (u8)0xff) { /* native RTE case */
+			/* these SPI2 devices are not exposed to system as PCI
+			 * devices, but they have separate RTE entry in IOAPIC
+			 * so we have to enable them one by one here
+			 */
+			ioapic = mp_find_ioapic(pentry->irq);
+			irq_attr.ioapic = ioapic;
+			irq_attr.ioapic_pin = pentry->irq;
+			irq_attr.trigger = 1;
+			irq_attr.polarity = 1;
+			io_apic_set_pci_routing(NULL, pentry->irq, &irq_attr);
+		}
+		switch (pentry->type) {
+		case SFI_DEV_TYPE_IPC:
+			/* ID as IRQ is a hack that will go away */
+			pdev = platform_device_alloc(pentry->name, pentry->irq);
+			if (pdev == NULL) {
+				pr_err("out of memory for SFI platform device '%s'.\n",
+							pentry->name);
+				continue;
+			}
+			install_irq_resource(pdev, pentry->irq);
+			pr_debug("info[%2d]: IPC bus, name = %16.16s, "
+				"irq = 0x%2x\n", i, pentry->name, pentry->irq);
+			sfi_handle_ipc_dev(pdev);
+			break;
+		case SFI_DEV_TYPE_SPI:
+			memset(&spi_info, 0, sizeof(spi_info));
+			strncpy(spi_info.modalias, pentry->name, SFI_NAME_LEN);
+			spi_info.irq = pentry->irq;
+			spi_info.bus_num = pentry->host_num;
+			spi_info.chip_select = pentry->addr;
+			spi_info.max_speed_hz = pentry->max_freq;
+			pr_debug("info[%2d]: SPI bus = %d, name = %16.16s, "
+				"irq = 0x%2x, max_freq = %d, cs = %d\n", i,
+				spi_info.bus_num,
+				spi_info.modalias,
+				spi_info.irq,
+				spi_info.max_speed_hz,
+				spi_info.chip_select);
+			sfi_handle_spi_dev(&spi_info);
+			break;
+		case SFI_DEV_TYPE_I2C:
+			memset(&i2c_info, 0, sizeof(i2c_info));
+			bus = pentry->host_num;
+			strncpy(i2c_info.type, pentry->name, SFI_NAME_LEN);
+			i2c_info.irq = pentry->irq;
+			i2c_info.addr = pentry->addr;
+			pr_debug("info[%2d]: I2C bus = %d, name = %16.16s, "
+				"irq = 0x%2x, addr = 0x%x\n", i, bus,
+				i2c_info.type,
+				i2c_info.irq,
+				i2c_info.addr);
+			sfi_handle_i2c_dev(bus, &i2c_info);
+			break;
+		case SFI_DEV_TYPE_UART:
+		case SFI_DEV_TYPE_HSI:
+		default:
+			;
+		}
+	}
+	return 0;
+}
+
+static int __init mrst_platform_init(void)
+{
+	sfi_table_parse(SFI_SIG_GPIO, NULL, NULL, sfi_parse_gpio);
+	sfi_table_parse(SFI_SIG_DEVS, NULL, NULL, sfi_parse_devs);
+	return 0;
+}
+arch_initcall(mrst_platform_init);
+
+/*
+ * we will search these buttons in SFI GPIO table (by name)
+ * and register them dynamically. Please add all possible
+ * buttons here, we will shrink them if no GPIO found.
+ */
+static struct gpio_keys_button gpio_button[] = {
+	{KEY_POWER,		-1, 1, "power_btn",	EV_KEY, 0, 3000},
+	{KEY_PROG1,		-1, 1, "prog_btn1",	EV_KEY, 0, 20},
+	{KEY_PROG2,		-1, 1, "prog_btn2",	EV_KEY, 0, 20},
+	{SW_LID,		-1, 1, "lid_switch",	EV_SW,  0, 20},
+	{KEY_VOLUMEUP,		-1, 1, "vol_up",	EV_KEY, 0, 20},
+	{KEY_VOLUMEDOWN,	-1, 1, "vol_down",	EV_KEY, 0, 20},
+	{KEY_CAMERA,		-1, 1, "camera_full",	EV_KEY, 0, 20},
+	{KEY_CAMERA_FOCUS,	-1, 1, "camera_half",	EV_KEY, 0, 20},
+	{SW_KEYPAD_SLIDE,	-1, 1, "MagSw1",	EV_SW,  0, 20},
+	{SW_KEYPAD_SLIDE,	-1, 1, "MagSw2",	EV_SW,  0, 20},
+};
+
+static struct gpio_keys_platform_data mrst_gpio_keys = {
+	.buttons	= gpio_button,
+	.rep		= 1,
+	.nbuttons	= -1, /* will fill it after search */
+};
+
+static struct platform_device pb_device = {
+	.name		= "gpio-keys",
+	.id		= -1,
+	.dev		= {
+		.platform_data	= &mrst_gpio_keys,
+	},
+};
+
+/*
+ * Shrink the non-existent buttons, register the gpio button
+ * device if there is some
+ */
+static int __init pb_keys_init(void)
+{
+	struct gpio_keys_button *gb = gpio_button;
+	int i, num, good = 0;
+
+	num = sizeof(gpio_button) / sizeof(struct gpio_keys_button);
+	for (i = 0; i < num; i++) {
+		gb[i].gpio = get_gpio_by_name(gb[i].desc);
+		if (gb[i].gpio == -1)
+			continue;
+
+		if (i != good)
+			gb[good] = gb[i];
+		good++;
+	}
+
+	if (good) {
+		mrst_gpio_keys.nbuttons = good;
+		return platform_device_register(&pb_device);
+	}
+	return 0;
+}
+late_initcall(pb_keys_init);
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/platform/mrst/vrtc.c linux-libre-2.6.38-gnu1/arch/x86/platform/mrst/vrtc.c
--- linux-libre-2.6.37-gnu1/arch/x86/platform/mrst/vrtc.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/platform/mrst/vrtc.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,165 @@
+/*
+ * vrtc.c: Driver for virtual RTC device on Intel MID platform
+ *
+ * (C) Copyright 2009 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; version 2
+ * of the License.
+ *
+ * Note:
+ * VRTC is emulated by system controller firmware, the real HW
+ * RTC is located in the PMIC device. SCU FW shadows PMIC RTC
+ * in a memory mapped IO space that is visible to the host IA
+ * processor.
+ *
+ * This driver is based on RTC CMOS driver.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/sfi.h>
+#include <linux/platform_device.h>
+
+#include <asm/mrst.h>
+#include <asm/mrst-vrtc.h>
+#include <asm/time.h>
+#include <asm/fixmap.h>
+
+static unsigned char __iomem *vrtc_virt_base;
+
+unsigned char vrtc_cmos_read(unsigned char reg)
+{
+	unsigned char retval;
+
+	/* vRTC's registers range from 0x0 to 0xD */
+	if (reg > 0xd || !vrtc_virt_base)
+		return 0xff;
+
+	lock_cmos_prefix(reg);
+	retval = __raw_readb(vrtc_virt_base + (reg << 2));
+	lock_cmos_suffix(reg);
+	return retval;
+}
+EXPORT_SYMBOL_GPL(vrtc_cmos_read);
+
+void vrtc_cmos_write(unsigned char val, unsigned char reg)
+{
+	if (reg > 0xd || !vrtc_virt_base)
+		return;
+
+	lock_cmos_prefix(reg);
+	__raw_writeb(val, vrtc_virt_base + (reg << 2));
+	lock_cmos_suffix(reg);
+}
+EXPORT_SYMBOL_GPL(vrtc_cmos_write);
+
+unsigned long vrtc_get_time(void)
+{
+	u8 sec, min, hour, mday, mon;
+	u32 year;
+
+	while ((vrtc_cmos_read(RTC_FREQ_SELECT) & RTC_UIP))
+		cpu_relax();
+
+	sec = vrtc_cmos_read(RTC_SECONDS);
+	min = vrtc_cmos_read(RTC_MINUTES);
+	hour = vrtc_cmos_read(RTC_HOURS);
+	mday = vrtc_cmos_read(RTC_DAY_OF_MONTH);
+	mon = vrtc_cmos_read(RTC_MONTH);
+	year = vrtc_cmos_read(RTC_YEAR);
+
+	/* vRTC YEAR reg contains the offset to 1960 */
+	year += 1960;
+
+	printk(KERN_INFO "vRTC: sec: %d min: %d hour: %d day: %d "
+		"mon: %d year: %d\n", sec, min, hour, mday, mon, year);
+
+	return mktime(year, mon, mday, hour, min, sec);
+}
+
+/* Only care about the minutes and seconds */
+int vrtc_set_mmss(unsigned long nowtime)
+{
+	int real_sec, real_min;
+	int vrtc_min;
+
+	vrtc_min = vrtc_cmos_read(RTC_MINUTES);
+
+	real_sec = nowtime % 60;
+	real_min = nowtime / 60;
+	if (((abs(real_min - vrtc_min) + 15)/30) & 1)
+		real_min += 30;
+	real_min %= 60;
+
+	vrtc_cmos_write(real_sec, RTC_SECONDS);
+	vrtc_cmos_write(real_min, RTC_MINUTES);
+	return 0;
+}
+
+void __init mrst_rtc_init(void)
+{
+	unsigned long rtc_paddr;
+	void __iomem *virt_base;
+
+	sfi_table_parse(SFI_SIG_MRTC, NULL, NULL, sfi_parse_mrtc);
+	if (!sfi_mrtc_num)
+		return;
+
+	rtc_paddr = sfi_mrtc_array[0].phys_addr;
+
+	/* vRTC's register address may not be page aligned */
+	set_fixmap_nocache(FIX_LNW_VRTC, rtc_paddr);
+
+	virt_base = (void __iomem *)__fix_to_virt(FIX_LNW_VRTC);
+	virt_base += rtc_paddr & ~PAGE_MASK;
+	vrtc_virt_base = virt_base;
+
+	x86_platform.get_wallclock = vrtc_get_time;
+	x86_platform.set_wallclock = vrtc_set_mmss;
+}
+
+/*
+ * The Moorestown platform has a memory mapped virtual RTC device that emulates
+ * the programming interface of the RTC.
+ */
+
+static struct resource vrtc_resources[] = {
+	[0] = {
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.flags	= IORESOURCE_IRQ,
+	}
+};
+
+static struct platform_device vrtc_device = {
+	.name		= "rtc_mrst",
+	.id		= -1,
+	.resource	= vrtc_resources,
+	.num_resources	= ARRAY_SIZE(vrtc_resources),
+};
+
+/* Register the RTC device if appropriate */
+static int __init mrst_device_create(void)
+{
+	/* No Moorestown, no device */
+	if (!mrst_identify_cpu())
+		return -ENODEV;
+	/* No timer, no device */
+	if (!sfi_mrtc_num)
+		return -ENODEV;
+
+	/* iomem resource */
+	vrtc_resources[0].start = sfi_mrtc_array[0].phys_addr;
+	vrtc_resources[0].end = sfi_mrtc_array[0].phys_addr +
+				MRST_VRTC_MAP_SZ;
+	/* irq resource */
+	vrtc_resources[1].start = sfi_mrtc_array[0].irq;
+	vrtc_resources[1].end = sfi_mrtc_array[0].irq;
+
+	return platform_device_register(&vrtc_device);
+}
+
+module_init(mrst_device_create);
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/platform/olpc/Makefile linux-libre-2.6.38-gnu1/arch/x86/platform/olpc/Makefile
--- linux-libre-2.6.37-gnu1/arch/x86/platform/olpc/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/platform/olpc/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -1,3 +1,4 @@
 obj-$(CONFIG_OLPC)		+= olpc.o
 obj-$(CONFIG_OLPC_XO1)		+= olpc-xo1.o
 obj-$(CONFIG_OLPC_OPENFIRMWARE)	+= olpc_ofw.o
+obj-$(CONFIG_OLPC_OPENFIRMWARE_DT)	+= olpc_dt.o
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/platform/olpc/olpc_dt.c linux-libre-2.6.38-gnu1/arch/x86/platform/olpc/olpc_dt.c
--- linux-libre-2.6.37-gnu1/arch/x86/platform/olpc/olpc_dt.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/platform/olpc/olpc_dt.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,182 @@
+/*
+ * OLPC-specific OFW device tree support code.
+ *
+ * Paul Mackerras	August 1996.
+ * Copyright (C) 1996-2005 Paul Mackerras.
+ *
+ *  Adapted for 64bit PowerPC by Dave Engebretsen and Peter Bergner.
+ *    {engebret|bergner}@us.ibm.com
+ *
+ *  Adapted for sparc by David S. Miller davem@davemloft.net
+ *  Adapted for x86/OLPC by Andres Salomon <dilinger@queued.net>
+ *
+ *      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/bootmem.h>
+#include <linux/of.h>
+#include <linux/of_pdt.h>
+#include <asm/olpc_ofw.h>
+
+static phandle __init olpc_dt_getsibling(phandle node)
+{
+	const void *args[] = { (void *)node };
+	void *res[] = { &node };
+
+	if ((s32)node == -1)
+		return 0;
+
+	if (olpc_ofw("peer", args, res) || (s32)node == -1)
+		return 0;
+
+	return node;
+}
+
+static phandle __init olpc_dt_getchild(phandle node)
+{
+	const void *args[] = { (void *)node };
+	void *res[] = { &node };
+
+	if ((s32)node == -1)
+		return 0;
+
+	if (olpc_ofw("child", args, res) || (s32)node == -1) {
+		pr_err("PROM: %s: fetching child failed!\n", __func__);
+		return 0;
+	}
+
+	return node;
+}
+
+static int __init olpc_dt_getproplen(phandle node, const char *prop)
+{
+	const void *args[] = { (void *)node, prop };
+	int len;
+	void *res[] = { &len };
+
+	if ((s32)node == -1)
+		return -1;
+
+	if (olpc_ofw("getproplen", args, res)) {
+		pr_err("PROM: %s: getproplen failed!\n", __func__);
+		return -1;
+	}
+
+	return len;
+}
+
+static int __init olpc_dt_getproperty(phandle node, const char *prop,
+		char *buf, int bufsize)
+{
+	int plen;
+
+	plen = olpc_dt_getproplen(node, prop);
+	if (plen > bufsize || plen < 1) {
+		return -1;
+	} else {
+		const void *args[] = { (void *)node, prop, buf, (void *)plen };
+		void *res[] = { &plen };
+
+		if (olpc_ofw("getprop", args, res)) {
+			pr_err("PROM: %s: getprop failed!\n", __func__);
+			return -1;
+		}
+	}
+
+	return plen;
+}
+
+static int __init olpc_dt_nextprop(phandle node, char *prev, char *buf)
+{
+	const void *args[] = { (void *)node, prev, buf };
+	int success;
+	void *res[] = { &success };
+
+	buf[0] = '\0';
+
+	if ((s32)node == -1)
+		return -1;
+
+	if (olpc_ofw("nextprop", args, res) || success != 1)
+		return -1;
+
+	return 0;
+}
+
+static int __init olpc_dt_pkg2path(phandle node, char *buf,
+		const int buflen, int *len)
+{
+	const void *args[] = { (void *)node, buf, (void *)buflen };
+	void *res[] = { len };
+
+	if ((s32)node == -1)
+		return -1;
+
+	if (olpc_ofw("package-to-path", args, res) || *len < 1)
+		return -1;
+
+	return 0;
+}
+
+static unsigned int prom_early_allocated __initdata;
+
+void * __init prom_early_alloc(unsigned long size)
+{
+	static u8 *mem;
+	static size_t free_mem;
+	void *res;
+
+	if (free_mem < size) {
+		const size_t chunk_size = max(PAGE_SIZE, size);
+
+		/*
+		 * To mimimize the number of allocations, grab at least
+		 * PAGE_SIZE of memory (that's an arbitrary choice that's
+		 * fast enough on the platforms we care about while minimizing
+		 * wasted bootmem) and hand off chunks of it to callers.
+		 */
+		res = alloc_bootmem(chunk_size);
+		BUG_ON(!res);
+		prom_early_allocated += chunk_size;
+		memset(res, 0, chunk_size);
+		free_mem = chunk_size;
+		mem = res;
+	}
+
+	/* allocate from the local cache */
+	free_mem -= size;
+	res = mem;
+	mem += size;
+	return res;
+}
+
+static struct of_pdt_ops prom_olpc_ops __initdata = {
+	.nextprop = olpc_dt_nextprop,
+	.getproplen = olpc_dt_getproplen,
+	.getproperty = olpc_dt_getproperty,
+	.getchild = olpc_dt_getchild,
+	.getsibling = olpc_dt_getsibling,
+	.pkg2path = olpc_dt_pkg2path,
+};
+
+void __init olpc_dt_build_devicetree(void)
+{
+	phandle root;
+
+	if (!olpc_ofw_is_installed())
+		return;
+
+	root = olpc_dt_getsibling(0);
+	if (!root) {
+		pr_err("PROM: unable to get root node from OFW!\n");
+		return;
+	}
+	of_pdt_build_devicetree(root, &prom_olpc_ops);
+
+	pr_info("PROM DT: Built device tree with %u bytes of memory.\n",
+			prom_early_allocated);
+}
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/platform/olpc/olpc_ofw.c linux-libre-2.6.38-gnu1/arch/x86/platform/olpc/olpc_ofw.c
--- linux-libre-2.6.37-gnu1/arch/x86/platform/olpc/olpc_ofw.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/platform/olpc/olpc_ofw.c	2011-03-14 21:20:32.000000000 -0400
@@ -110,3 +110,8 @@ void __init olpc_ofw_detect(void)
 			(unsigned long)olpc_ofw_cif, (-start) >> 20);
 	reserve_top_address(-start);
 }
+
+bool __init olpc_ofw_is_installed(void)
+{
+	return olpc_ofw_cif != NULL;
+}
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/platform/olpc/olpc-xo1.c linux-libre-2.6.38-gnu1/arch/x86/platform/olpc/olpc-xo1.c
--- linux-libre-2.6.37-gnu1/arch/x86/platform/olpc/olpc-xo1.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/platform/olpc/olpc-xo1.c	2011-03-14 21:20:32.000000000 -0400
@@ -1,6 +1,7 @@
 /*
  * Support for features of the OLPC XO-1 laptop
  *
+ * Copyright (C) 2010 Andres Salomon <dilinger@queued.net>
  * Copyright (C) 2010 One Laptop per Child
  * Copyright (C) 2006 Red Hat, Inc.
  * Copyright (C) 2006 Advanced Micro Devices, Inc.
@@ -12,8 +13,6 @@
  */
 
 #include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/pci_ids.h>
 #include <linux/platform_device.h>
 #include <linux/pm.h>
 
@@ -22,9 +21,6 @@
 
 #define DRV_NAME "olpc-xo1"
 
-#define PMS_BAR		4
-#define ACPI_BAR	5
-
 /* PMC registers (PMS block) */
 #define PM_SCLK		0x10
 #define PM_IN_SLPCTL	0x20
@@ -57,65 +53,67 @@ static void xo1_power_off(void)
 	outl(0x00002000, acpi_base + PM1_CNT);
 }
 
-/* Read the base addresses from the PCI BAR info */
-static int __devinit setup_bases(struct pci_dev *pdev)
+static int __devinit olpc_xo1_probe(struct platform_device *pdev)
 {
-	int r;
+	struct resource *res;
 
-	r = pci_enable_device_io(pdev);
-	if (r) {
-		dev_err(&pdev->dev, "can't enable device IO\n");
-		return r;
-	}
+	/* don't run on non-XOs */
+	if (!machine_is_olpc())
+		return -ENODEV;
 
-	r = pci_request_region(pdev, ACPI_BAR, DRV_NAME);
-	if (r) {
-		dev_err(&pdev->dev, "can't alloc PCI BAR #%d\n", ACPI_BAR);
-		return r;
+	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+	if (!res) {
+		dev_err(&pdev->dev, "can't fetch device resource info\n");
+		return -EIO;
 	}
 
-	r = pci_request_region(pdev, PMS_BAR, DRV_NAME);
-	if (r) {
-		dev_err(&pdev->dev, "can't alloc PCI BAR #%d\n", PMS_BAR);
-		pci_release_region(pdev, ACPI_BAR);
-		return r;
+	if (!request_region(res->start, resource_size(res), DRV_NAME)) {
+		dev_err(&pdev->dev, "can't request region\n");
+		return -EIO;
 	}
 
-	acpi_base = pci_resource_start(pdev, ACPI_BAR);
-	pms_base = pci_resource_start(pdev, PMS_BAR);
+	if (strcmp(pdev->name, "cs5535-pms") == 0)
+		pms_base = res->start;
+	else if (strcmp(pdev->name, "cs5535-acpi") == 0)
+		acpi_base = res->start;
+
+	/* If we have both addresses, we can override the poweroff hook */
+	if (pms_base && acpi_base) {
+		pm_power_off = xo1_power_off;
+		printk(KERN_INFO "OLPC XO-1 support registered\n");
+	}
 
 	return 0;
 }
 
-static int __devinit olpc_xo1_probe(struct platform_device *pdev)
+static int __devexit olpc_xo1_remove(struct platform_device *pdev)
 {
-	struct pci_dev *pcidev;
-	int r;
-
-	pcidev = pci_get_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA,
-				NULL);
-	if (!pdev)
-		return -ENODEV;
-
-	r = setup_bases(pcidev);
-	if (r)
-		return r;
+	struct resource *r;
 
-	pm_power_off = xo1_power_off;
+	r = platform_get_resource(pdev, IORESOURCE_IO, 0);
+	release_region(r->start, resource_size(r));
 
-	printk(KERN_INFO "OLPC XO-1 support registered\n");
-	return 0;
-}
+	if (strcmp(pdev->name, "cs5535-pms") == 0)
+		pms_base = 0;
+	else if (strcmp(pdev->name, "cs5535-acpi") == 0)
+		acpi_base = 0;
 
-static int __devexit olpc_xo1_remove(struct platform_device *pdev)
-{
 	pm_power_off = NULL;
 	return 0;
 }
 
-static struct platform_driver olpc_xo1_driver = {
+static struct platform_driver cs5535_pms_drv = {
 	.driver = {
-		.name = DRV_NAME,
+		.name = "cs5535-pms",
+		.owner = THIS_MODULE,
+	},
+	.probe = olpc_xo1_probe,
+	.remove = __devexit_p(olpc_xo1_remove),
+};
+
+static struct platform_driver cs5535_acpi_drv = {
+	.driver = {
+		.name = "cs5535-acpi",
 		.owner = THIS_MODULE,
 	},
 	.probe = olpc_xo1_probe,
@@ -124,12 +122,23 @@ static struct platform_driver olpc_xo1_d
 
 static int __init olpc_xo1_init(void)
 {
-	return platform_driver_register(&olpc_xo1_driver);
+	int r;
+
+	r = platform_driver_register(&cs5535_pms_drv);
+	if (r)
+		return r;
+
+	r = platform_driver_register(&cs5535_acpi_drv);
+	if (r)
+		platform_driver_unregister(&cs5535_pms_drv);
+
+	return r;
 }
 
 static void __exit olpc_xo1_exit(void)
 {
-	platform_driver_unregister(&olpc_xo1_driver);
+	platform_driver_unregister(&cs5535_acpi_drv);
+	platform_driver_unregister(&cs5535_pms_drv);
 }
 
 MODULE_AUTHOR("Daniel Drake <dsd@laptop.org>");
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/platform/sfi/sfi.c linux-libre-2.6.38-gnu1/arch/x86/platform/sfi/sfi.c
--- linux-libre-2.6.37-gnu1/arch/x86/platform/sfi/sfi.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/platform/sfi/sfi.c	2011-03-14 21:20:32.000000000 -0400
@@ -34,23 +34,12 @@
 #ifdef CONFIG_X86_LOCAL_APIC
 static unsigned long sfi_lapic_addr __initdata = APIC_DEFAULT_PHYS_BASE;
 
-static void __init mp_sfi_register_lapic_address(unsigned long address)
-{
-	mp_lapic_addr = address;
-
-	set_fixmap_nocache(FIX_APIC_BASE, mp_lapic_addr);
-	if (boot_cpu_physical_apicid == -1U)
-		boot_cpu_physical_apicid = read_apic_id();
-
-	pr_info("Boot CPU = %d\n", boot_cpu_physical_apicid);
-}
-
 /* All CPUs enumerated by SFI must be present and enabled */
 static void __cpuinit mp_sfi_register_lapic(u8 id)
 {
-	if (MAX_APICS - id <= 0) {
+	if (MAX_LOCAL_APIC - id <= 0) {
 		pr_warning("Processor #%d invalid (max %d)\n",
-			id, MAX_APICS);
+			id, MAX_LOCAL_APIC);
 		return;
 	}
 
@@ -110,7 +99,7 @@ static int __init sfi_parse_ioapic(struc
 int __init sfi_platform_init(void)
 {
 #ifdef CONFIG_X86_LOCAL_APIC
-	mp_sfi_register_lapic_address(sfi_lapic_addr);
+	register_lapic_address(sfi_lapic_addr);
 	sfi_table_parse(SFI_SIG_CPUS, NULL, NULL, sfi_parse_cpus);
 #endif
 #ifdef CONFIG_X86_IO_APIC
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/platform/uv/tlb_uv.c linux-libre-2.6.38-gnu1/arch/x86/platform/uv/tlb_uv.c
--- linux-libre-2.6.37-gnu1/arch/x86/platform/uv/tlb_uv.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/platform/uv/tlb_uv.c	2011-03-14 21:20:32.000000000 -0400
@@ -1341,7 +1341,7 @@ uv_activation_descriptor_init(int node,
 
 	/*
 	 * each bau_desc is 64 bytes; there are 8 (UV_ITEMS_PER_DESCRIPTOR)
-	 * per cpu; and up to 32 (UV_ADP_SIZE) cpu's per uvhub
+	 * per cpu; and one per cpu on the uvhub (UV_ADP_SIZE)
 	 */
 	bau_desc = kmalloc_node(sizeof(struct bau_desc) * UV_ADP_SIZE
 				* UV_ITEMS_PER_DESCRIPTOR, GFP_KERNEL, node);
@@ -1364,11 +1364,11 @@ uv_activation_descriptor_init(int node,
 		memset(bd2, 0, sizeof(struct bau_desc));
 		bd2->header.sw_ack_flag = 1;
 		/*
-		 * base_dest_nodeid is the nasid (pnode<<1) of the first uvhub
+		 * base_dest_nodeid is the nasid of the first uvhub
 		 * in the partition. The bit map will indicate uvhub numbers,
 		 * which are 0-N in a partition. Pnodes are unique system-wide.
 		 */
-		bd2->header.base_dest_nodeid = uv_partition_base_pnode << 1;
+		bd2->header.base_dest_nodeid = UV_PNODE_TO_NASID(uv_partition_base_pnode);
 		bd2->header.dest_subnodeid = 0x10; /* the LB */
 		bd2->header.command = UV_NET_ENDPOINT_INTD;
 		bd2->header.int_both = 1;
@@ -1490,7 +1490,7 @@ calculate_destination_timeout(void)
 /*
  * initialize the bau_control structure for each cpu
  */
-static void __init uv_init_per_cpu(int nuvhubs)
+static int __init uv_init_per_cpu(int nuvhubs)
 {
 	int i;
 	int cpu;
@@ -1507,7 +1507,7 @@ static void __init uv_init_per_cpu(int n
 	struct bau_control *smaster = NULL;
 	struct socket_desc {
 		short num_cpus;
-		short cpu_number[16];
+		short cpu_number[MAX_CPUS_PER_SOCKET];
 	};
 	struct uvhub_desc {
 		unsigned short socket_mask;
@@ -1540,6 +1540,10 @@ static void __init uv_init_per_cpu(int n
 		sdp = &bdp->socket[socket];
 		sdp->cpu_number[sdp->num_cpus] = cpu;
 		sdp->num_cpus++;
+		if (sdp->num_cpus > MAX_CPUS_PER_SOCKET) {
+			printk(KERN_EMERG "%d cpus per socket invalid\n", sdp->num_cpus);
+			return 1;
+		}
 	}
 	for (uvhub = 0; uvhub < nuvhubs; uvhub++) {
 		if (!(*(uvhub_mask + (uvhub/8)) & (1 << (uvhub%8))))
@@ -1570,6 +1574,12 @@ static void __init uv_init_per_cpu(int n
 				bcp->uvhub_master = hmaster;
 				bcp->uvhub_cpu = uv_cpu_hub_info(cpu)->
 						blade_processor_id;
+				if (bcp->uvhub_cpu >= MAX_CPUS_PER_UVHUB) {
+					printk(KERN_EMERG
+						"%d cpus per uvhub invalid\n",
+						bcp->uvhub_cpu);
+					return 1;
+				}
 			}
 nextsocket:
 			socket++;
@@ -1595,6 +1605,7 @@ nextsocket:
 		bcp->congested_reps = congested_reps;
 		bcp->congested_period = congested_period;
 	}
+	return 0;
 }
 
 /*
@@ -1625,7 +1636,10 @@ static int __init uv_bau_init(void)
 	spin_lock_init(&disable_lock);
 	congested_cycles = microsec_2_cycles(congested_response_us);
 
-	uv_init_per_cpu(nuvhubs);
+	if (uv_init_per_cpu(nuvhubs)) {
+		nobau = 1;
+		return 0;
+	}
 
 	uv_partition_base_pnode = 0x7fffffff;
 	for (uvhub = 0; uvhub < nuvhubs; uvhub++)
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/platform/visws/visws_quirks.c linux-libre-2.6.38-gnu1/arch/x86/platform/visws/visws_quirks.c
--- linux-libre-2.6.37-gnu1/arch/x86/platform/visws/visws_quirks.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/platform/visws/visws_quirks.c	2011-03-14 21:20:32.000000000 -0400
@@ -171,7 +171,7 @@ static void __init MP_processor_info(str
 	ver = m->apicver;
 	if ((ver >= 0x14 && m->apicid >= 0xff) || m->apicid >= 0xf) {
 		printk(KERN_ERR "Processor #%d INVALID. (Max ID: %d).\n",
-			m->apicid, MAX_APICS);
+			m->apicid, MAX_LOCAL_APIC);
 		return;
 	}
 
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/xen/enlighten.c linux-libre-2.6.38-gnu1/arch/x86/xen/enlighten.c
--- linux-libre-2.6.37-gnu1/arch/x86/xen/enlighten.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/xen/enlighten.c	2011-03-14 21:20:32.000000000 -0400
@@ -574,8 +574,8 @@ static void xen_write_idt_entry(gate_des
 
 	preempt_disable();
 
-	start = __get_cpu_var(idt_desc).address;
-	end = start + __get_cpu_var(idt_desc).size + 1;
+	start = __this_cpu_read(idt_desc.address);
+	end = start + __this_cpu_read(idt_desc.size) + 1;
 
 	xen_mc_flush();
 
@@ -1174,6 +1174,15 @@ asmlinkage void __init xen_start_kernel(
 
 	xen_smp_init();
 
+#ifdef CONFIG_ACPI_NUMA
+	/*
+	 * The pages we from Xen are not related to machine pages, so
+	 * any NUMA information the kernel tries to get from ACPI will
+	 * be meaningless.  Prevent it from trying.
+	 */
+	acpi_numa = -1;
+#endif
+
 	pgd = (pgd_t *)xen_start_info->pt_base;
 
 	if (!xen_initial_domain())
@@ -1185,7 +1194,7 @@ asmlinkage void __init xen_start_kernel(
 	per_cpu(xen_vcpu, 0) = &HYPERVISOR_shared_info->vcpu_info[0];
 
 	local_irq_disable();
-	early_boot_irqs_off();
+	early_boot_irqs_disabled = true;
 
 	memblock_init();
 
@@ -1256,25 +1265,6 @@ asmlinkage void __init xen_start_kernel(
 #endif
 }
 
-static uint32_t xen_cpuid_base(void)
-{
-	uint32_t base, eax, ebx, ecx, edx;
-	char signature[13];
-
-	for (base = 0x40000000; base < 0x40010000; base += 0x100) {
-		cpuid(base, &eax, &ebx, &ecx, &edx);
-		*(uint32_t *)(signature + 0) = ebx;
-		*(uint32_t *)(signature + 4) = ecx;
-		*(uint32_t *)(signature + 8) = edx;
-		signature[12] = 0;
-
-		if (!strcmp("XenVMMXenVMM", signature) && ((eax - base) >= 2))
-			return base;
-	}
-
-	return 0;
-}
-
 static int init_hvm_pv_info(int *major, int *minor)
 {
 	uint32_t eax, ebx, ecx, edx, pages, msr, base;
@@ -1384,6 +1374,18 @@ static bool __init xen_hvm_platform(void
 	return true;
 }
 
+bool xen_hvm_need_lapic(void)
+{
+	if (xen_pv_domain())
+		return false;
+	if (!xen_hvm_domain())
+		return false;
+	if (xen_feature(XENFEAT_hvm_pirqs) && xen_have_vector_callback)
+		return false;
+	return true;
+}
+EXPORT_SYMBOL_GPL(xen_hvm_need_lapic);
+
 const __refconst struct hypervisor_x86 x86_hyper_xen_hvm = {
 	.name			= "Xen HVM",
 	.detect			= xen_hvm_platform,
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/xen/irq.c linux-libre-2.6.38-gnu1/arch/x86/xen/irq.c
--- linux-libre-2.6.37-gnu1/arch/x86/xen/irq.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/xen/irq.c	2011-03-14 21:20:32.000000000 -0400
@@ -126,7 +126,7 @@ static const struct pv_irq_ops xen_irq_o
 #endif
 };
 
-void __init xen_init_irq_ops()
+void __init xen_init_irq_ops(void)
 {
 	pv_irq_ops = xen_irq_ops;
 	x86_init.irqs.intr_init = xen_init_IRQ;
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/xen/Makefile linux-libre-2.6.38-gnu1/arch/x86/xen/Makefile
--- linux-libre-2.6.37-gnu1/arch/x86/xen/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/xen/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -12,7 +12,8 @@ CFLAGS_mmu.o			:= $(nostackp)
 
 obj-y		:= enlighten.o setup.o multicalls.o mmu.o irq.o \
 			time.o xen-asm.o xen-asm_$(BITS).o \
-			grant-table.o suspend.o platform-pci-unplug.o
+			grant-table.o suspend.o platform-pci-unplug.o \
+			p2m.o
 
 obj-$(CONFIG_SMP)		+= smp.o
 obj-$(CONFIG_PARAVIRT_SPINLOCKS)+= spinlock.o
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/xen/mmu.c linux-libre-2.6.38-gnu1/arch/x86/xen/mmu.c
--- linux-libre-2.6.37-gnu1/arch/x86/xen/mmu.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/xen/mmu.c	2011-03-14 21:20:32.000000000 -0400
@@ -173,371 +173,6 @@ DEFINE_PER_CPU(unsigned long, xen_curren
  */
 #define USER_LIMIT	((STACK_TOP_MAX + PGDIR_SIZE - 1) & PGDIR_MASK)
 
-/*
- * Xen leaves the responsibility for maintaining p2m mappings to the
- * guests themselves, but it must also access and update the p2m array
- * during suspend/resume when all the pages are reallocated.
- *
- * The p2m table is logically a flat array, but we implement it as a
- * three-level tree to allow the address space to be sparse.
- *
- *                               Xen
- *                                |
- *     p2m_top              p2m_top_mfn
- *       /  \                   /   \
- * p2m_mid p2m_mid	p2m_mid_mfn p2m_mid_mfn
- *    / \      / \         /           /
- *  p2m p2m p2m p2m p2m p2m p2m ...
- *
- * The p2m_mid_mfn pages are mapped by p2m_top_mfn_p.
- *
- * The p2m_top and p2m_top_mfn levels are limited to 1 page, so the
- * maximum representable pseudo-physical address space is:
- *  P2M_TOP_PER_PAGE * P2M_MID_PER_PAGE * P2M_PER_PAGE pages
- *
- * P2M_PER_PAGE depends on the architecture, as a mfn is always
- * unsigned long (8 bytes on 64-bit, 4 bytes on 32), leading to
- * 512 and 1024 entries respectively. 
- */
-
-unsigned long xen_max_p2m_pfn __read_mostly;
-
-#define P2M_PER_PAGE		(PAGE_SIZE / sizeof(unsigned long))
-#define P2M_MID_PER_PAGE	(PAGE_SIZE / sizeof(unsigned long *))
-#define P2M_TOP_PER_PAGE	(PAGE_SIZE / sizeof(unsigned long **))
-
-#define MAX_P2M_PFN		(P2M_TOP_PER_PAGE * P2M_MID_PER_PAGE * P2M_PER_PAGE)
-
-/* Placeholders for holes in the address space */
-static RESERVE_BRK_ARRAY(unsigned long, p2m_missing, P2M_PER_PAGE);
-static RESERVE_BRK_ARRAY(unsigned long *, p2m_mid_missing, P2M_MID_PER_PAGE);
-static RESERVE_BRK_ARRAY(unsigned long, p2m_mid_missing_mfn, P2M_MID_PER_PAGE);
-
-static RESERVE_BRK_ARRAY(unsigned long **, p2m_top, P2M_TOP_PER_PAGE);
-static RESERVE_BRK_ARRAY(unsigned long, p2m_top_mfn, P2M_TOP_PER_PAGE);
-static RESERVE_BRK_ARRAY(unsigned long *, p2m_top_mfn_p, P2M_TOP_PER_PAGE);
-
-RESERVE_BRK(p2m_mid, PAGE_SIZE * (MAX_DOMAIN_PAGES / (P2M_PER_PAGE * P2M_MID_PER_PAGE)));
-RESERVE_BRK(p2m_mid_mfn, PAGE_SIZE * (MAX_DOMAIN_PAGES / (P2M_PER_PAGE * P2M_MID_PER_PAGE)));
-
-static inline unsigned p2m_top_index(unsigned long pfn)
-{
-	BUG_ON(pfn >= MAX_P2M_PFN);
-	return pfn / (P2M_MID_PER_PAGE * P2M_PER_PAGE);
-}
-
-static inline unsigned p2m_mid_index(unsigned long pfn)
-{
-	return (pfn / P2M_PER_PAGE) % P2M_MID_PER_PAGE;
-}
-
-static inline unsigned p2m_index(unsigned long pfn)
-{
-	return pfn % P2M_PER_PAGE;
-}
-
-static void p2m_top_init(unsigned long ***top)
-{
-	unsigned i;
-
-	for (i = 0; i < P2M_TOP_PER_PAGE; i++)
-		top[i] = p2m_mid_missing;
-}
-
-static void p2m_top_mfn_init(unsigned long *top)
-{
-	unsigned i;
-
-	for (i = 0; i < P2M_TOP_PER_PAGE; i++)
-		top[i] = virt_to_mfn(p2m_mid_missing_mfn);
-}
-
-static void p2m_top_mfn_p_init(unsigned long **top)
-{
-	unsigned i;
-
-	for (i = 0; i < P2M_TOP_PER_PAGE; i++)
-		top[i] = p2m_mid_missing_mfn;
-}
-
-static void p2m_mid_init(unsigned long **mid)
-{
-	unsigned i;
-
-	for (i = 0; i < P2M_MID_PER_PAGE; i++)
-		mid[i] = p2m_missing;
-}
-
-static void p2m_mid_mfn_init(unsigned long *mid)
-{
-	unsigned i;
-
-	for (i = 0; i < P2M_MID_PER_PAGE; i++)
-		mid[i] = virt_to_mfn(p2m_missing);
-}
-
-static void p2m_init(unsigned long *p2m)
-{
-	unsigned i;
-
-	for (i = 0; i < P2M_MID_PER_PAGE; i++)
-		p2m[i] = INVALID_P2M_ENTRY;
-}
-
-/*
- * Build the parallel p2m_top_mfn and p2m_mid_mfn structures
- *
- * This is called both at boot time, and after resuming from suspend:
- * - At boot time we're called very early, and must use extend_brk()
- *   to allocate memory.
- *
- * - After resume we're called from within stop_machine, but the mfn
- *   tree should alreay be completely allocated.
- */
-void xen_build_mfn_list_list(void)
-{
-	unsigned long pfn;
-
-	/* Pre-initialize p2m_top_mfn to be completely missing */
-	if (p2m_top_mfn == NULL) {
-		p2m_mid_missing_mfn = extend_brk(PAGE_SIZE, PAGE_SIZE);
-		p2m_mid_mfn_init(p2m_mid_missing_mfn);
-
-		p2m_top_mfn_p = extend_brk(PAGE_SIZE, PAGE_SIZE);
-		p2m_top_mfn_p_init(p2m_top_mfn_p);
-
-		p2m_top_mfn = extend_brk(PAGE_SIZE, PAGE_SIZE);
-		p2m_top_mfn_init(p2m_top_mfn);
-	} else {
-		/* Reinitialise, mfn's all change after migration */
-		p2m_mid_mfn_init(p2m_mid_missing_mfn);
-	}
-
-	for (pfn = 0; pfn < xen_max_p2m_pfn; pfn += P2M_PER_PAGE) {
-		unsigned topidx = p2m_top_index(pfn);
-		unsigned mididx = p2m_mid_index(pfn);
-		unsigned long **mid;
-		unsigned long *mid_mfn_p;
-
-		mid = p2m_top[topidx];
-		mid_mfn_p = p2m_top_mfn_p[topidx];
-
-		/* Don't bother allocating any mfn mid levels if
-		 * they're just missing, just update the stored mfn,
-		 * since all could have changed over a migrate.
-		 */
-		if (mid == p2m_mid_missing) {
-			BUG_ON(mididx);
-			BUG_ON(mid_mfn_p != p2m_mid_missing_mfn);
-			p2m_top_mfn[topidx] = virt_to_mfn(p2m_mid_missing_mfn);
-			pfn += (P2M_MID_PER_PAGE - 1) * P2M_PER_PAGE;
-			continue;
-		}
-
-		if (mid_mfn_p == p2m_mid_missing_mfn) {
-			/*
-			 * XXX boot-time only!  We should never find
-			 * missing parts of the mfn tree after
-			 * runtime.  extend_brk() will BUG if we call
-			 * it too late.
-			 */
-			mid_mfn_p = extend_brk(PAGE_SIZE, PAGE_SIZE);
-			p2m_mid_mfn_init(mid_mfn_p);
-
-			p2m_top_mfn_p[topidx] = mid_mfn_p;
-		}
-
-		p2m_top_mfn[topidx] = virt_to_mfn(mid_mfn_p);
-		mid_mfn_p[mididx] = virt_to_mfn(mid[mididx]);
-	}
-}
-
-void xen_setup_mfn_list_list(void)
-{
-	BUG_ON(HYPERVISOR_shared_info == &xen_dummy_shared_info);
-
-	HYPERVISOR_shared_info->arch.pfn_to_mfn_frame_list_list =
-		virt_to_mfn(p2m_top_mfn);
-	HYPERVISOR_shared_info->arch.max_pfn = xen_max_p2m_pfn;
-}
-
-/* Set up p2m_top to point to the domain-builder provided p2m pages */
-void __init xen_build_dynamic_phys_to_machine(void)
-{
-	unsigned long *mfn_list = (unsigned long *)xen_start_info->mfn_list;
-	unsigned long max_pfn = min(MAX_DOMAIN_PAGES, xen_start_info->nr_pages);
-	unsigned long pfn;
-
-	xen_max_p2m_pfn = max_pfn;
-
-	p2m_missing = extend_brk(PAGE_SIZE, PAGE_SIZE);
-	p2m_init(p2m_missing);
-
-	p2m_mid_missing = extend_brk(PAGE_SIZE, PAGE_SIZE);
-	p2m_mid_init(p2m_mid_missing);
-
-	p2m_top = extend_brk(PAGE_SIZE, PAGE_SIZE);
-	p2m_top_init(p2m_top);
-
-	/*
-	 * The domain builder gives us a pre-constructed p2m array in
-	 * mfn_list for all the pages initially given to us, so we just
-	 * need to graft that into our tree structure.
-	 */
-	for (pfn = 0; pfn < max_pfn; pfn += P2M_PER_PAGE) {
-		unsigned topidx = p2m_top_index(pfn);
-		unsigned mididx = p2m_mid_index(pfn);
-
-		if (p2m_top[topidx] == p2m_mid_missing) {
-			unsigned long **mid = extend_brk(PAGE_SIZE, PAGE_SIZE);
-			p2m_mid_init(mid);
-
-			p2m_top[topidx] = mid;
-		}
-
-		p2m_top[topidx][mididx] = &mfn_list[pfn];
-	}
-}
-
-unsigned long get_phys_to_machine(unsigned long pfn)
-{
-	unsigned topidx, mididx, idx;
-
-	if (unlikely(pfn >= MAX_P2M_PFN))
-		return INVALID_P2M_ENTRY;
-
-	topidx = p2m_top_index(pfn);
-	mididx = p2m_mid_index(pfn);
-	idx = p2m_index(pfn);
-
-	return p2m_top[topidx][mididx][idx];
-}
-EXPORT_SYMBOL_GPL(get_phys_to_machine);
-
-static void *alloc_p2m_page(void)
-{
-	return (void *)__get_free_page(GFP_KERNEL | __GFP_REPEAT);
-}
-
-static void free_p2m_page(void *p)
-{
-	free_page((unsigned long)p);
-}
-
-/* 
- * Fully allocate the p2m structure for a given pfn.  We need to check
- * that both the top and mid levels are allocated, and make sure the
- * parallel mfn tree is kept in sync.  We may race with other cpus, so
- * the new pages are installed with cmpxchg; if we lose the race then
- * simply free the page we allocated and use the one that's there.
- */
-static bool alloc_p2m(unsigned long pfn)
-{
-	unsigned topidx, mididx;
-	unsigned long ***top_p, **mid;
-	unsigned long *top_mfn_p, *mid_mfn;
-
-	topidx = p2m_top_index(pfn);
-	mididx = p2m_mid_index(pfn);
-
-	top_p = &p2m_top[topidx];
-	mid = *top_p;
-
-	if (mid == p2m_mid_missing) {
-		/* Mid level is missing, allocate a new one */
-		mid = alloc_p2m_page();
-		if (!mid)
-			return false;
-
-		p2m_mid_init(mid);
-
-		if (cmpxchg(top_p, p2m_mid_missing, mid) != p2m_mid_missing)
-			free_p2m_page(mid);
-	}
-
-	top_mfn_p = &p2m_top_mfn[topidx];
-	mid_mfn = p2m_top_mfn_p[topidx];
-
-	BUG_ON(virt_to_mfn(mid_mfn) != *top_mfn_p);
-
-	if (mid_mfn == p2m_mid_missing_mfn) {
-		/* Separately check the mid mfn level */
-		unsigned long missing_mfn;
-		unsigned long mid_mfn_mfn;
-
-		mid_mfn = alloc_p2m_page();
-		if (!mid_mfn)
-			return false;
-
-		p2m_mid_mfn_init(mid_mfn);
-
-		missing_mfn = virt_to_mfn(p2m_mid_missing_mfn);
-		mid_mfn_mfn = virt_to_mfn(mid_mfn);
-		if (cmpxchg(top_mfn_p, missing_mfn, mid_mfn_mfn) != missing_mfn)
-			free_p2m_page(mid_mfn);
-		else
-			p2m_top_mfn_p[topidx] = mid_mfn;
-	}
-
-	if (p2m_top[topidx][mididx] == p2m_missing) {
-		/* p2m leaf page is missing */
-		unsigned long *p2m;
-
-		p2m = alloc_p2m_page();
-		if (!p2m)
-			return false;
-
-		p2m_init(p2m);
-
-		if (cmpxchg(&mid[mididx], p2m_missing, p2m) != p2m_missing)
-			free_p2m_page(p2m);
-		else
-			mid_mfn[mididx] = virt_to_mfn(p2m);
-	}
-
-	return true;
-}
-
-/* Try to install p2m mapping; fail if intermediate bits missing */
-bool __set_phys_to_machine(unsigned long pfn, unsigned long mfn)
-{
-	unsigned topidx, mididx, idx;
-
-	if (unlikely(pfn >= MAX_P2M_PFN)) {
-		BUG_ON(mfn != INVALID_P2M_ENTRY);
-		return true;
-	}
-
-	topidx = p2m_top_index(pfn);
-	mididx = p2m_mid_index(pfn);
-	idx = p2m_index(pfn);
-
-	if (p2m_top[topidx][mididx] == p2m_missing)
-		return mfn == INVALID_P2M_ENTRY;
-
-	p2m_top[topidx][mididx][idx] = mfn;
-
-	return true;
-}
-
-bool set_phys_to_machine(unsigned long pfn, unsigned long mfn)
-{
-	if (unlikely(xen_feature(XENFEAT_auto_translated_physmap))) {
-		BUG_ON(pfn != mfn && mfn != INVALID_P2M_ENTRY);
-		return true;
-	}
-
-	if (unlikely(!__set_phys_to_machine(pfn, mfn)))  {
-		if (!alloc_p2m(pfn))
-			return false;
-
-		if (!__set_phys_to_machine(pfn, mfn))
-			return false;
-	}
-
-	return true;
-}
-
 unsigned long arbitrary_virt_to_mfn(void *vaddr)
 {
 	xmaddr_t maddr = arbitrary_virt_to_machine(vaddr);
@@ -566,6 +201,7 @@ xmaddr_t arbitrary_virt_to_machine(void
 	offset = address & ~PAGE_MASK;
 	return XMADDR(((phys_addr_t)pte_mfn(*pte) << PAGE_SHIFT) + offset);
 }
+EXPORT_SYMBOL_GPL(arbitrary_virt_to_machine);
 
 void make_lowmem_page_readonly(void *vaddr)
 {
@@ -1350,10 +986,9 @@ static void xen_pgd_pin(struct mm_struct
  */
 void xen_mm_pin_all(void)
 {
-	unsigned long flags;
 	struct page *page;
 
-	spin_lock_irqsave(&pgd_lock, flags);
+	spin_lock(&pgd_lock);
 
 	list_for_each_entry(page, &pgd_list, lru) {
 		if (!PagePinned(page)) {
@@ -1362,7 +997,7 @@ void xen_mm_pin_all(void)
 		}
 	}
 
-	spin_unlock_irqrestore(&pgd_lock, flags);
+	spin_unlock(&pgd_lock);
 }
 
 /*
@@ -1463,10 +1098,9 @@ static void xen_pgd_unpin(struct mm_stru
  */
 void xen_mm_unpin_all(void)
 {
-	unsigned long flags;
 	struct page *page;
 
-	spin_lock_irqsave(&pgd_lock, flags);
+	spin_lock(&pgd_lock);
 
 	list_for_each_entry(page, &pgd_list, lru) {
 		if (PageSavePinned(page)) {
@@ -1476,7 +1110,7 @@ void xen_mm_unpin_all(void)
 		}
 	}
 
-	spin_unlock_irqrestore(&pgd_lock, flags);
+	spin_unlock(&pgd_lock);
 }
 
 void xen_activate_mm(struct mm_struct *prev, struct mm_struct *next)
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/xen/multicalls.h linux-libre-2.6.38-gnu1/arch/x86/xen/multicalls.h
--- linux-libre-2.6.37-gnu1/arch/x86/xen/multicalls.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/xen/multicalls.h	2011-03-14 21:20:32.000000000 -0400
@@ -22,7 +22,7 @@ static inline void xen_mc_batch(void)
 	unsigned long flags;
 	/* need to disable interrupts until this entry is complete */
 	local_irq_save(flags);
-	__get_cpu_var(xen_mc_irq_flags) = flags;
+	__this_cpu_write(xen_mc_irq_flags, flags);
 }
 
 static inline struct multicall_space xen_mc_entry(size_t args)
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/xen/p2m.c linux-libre-2.6.38-gnu1/arch/x86/xen/p2m.c
--- linux-libre-2.6.37-gnu1/arch/x86/xen/p2m.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/xen/p2m.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,522 @@
+/*
+ * Xen leaves the responsibility for maintaining p2m mappings to the
+ * guests themselves, but it must also access and update the p2m array
+ * during suspend/resume when all the pages are reallocated.
+ *
+ * The p2m table is logically a flat array, but we implement it as a
+ * three-level tree to allow the address space to be sparse.
+ *
+ *                               Xen
+ *                                |
+ *     p2m_top              p2m_top_mfn
+ *       /  \                   /   \
+ * p2m_mid p2m_mid	p2m_mid_mfn p2m_mid_mfn
+ *    / \      / \         /           /
+ *  p2m p2m p2m p2m p2m p2m p2m ...
+ *
+ * The p2m_mid_mfn pages are mapped by p2m_top_mfn_p.
+ *
+ * The p2m_top and p2m_top_mfn levels are limited to 1 page, so the
+ * maximum representable pseudo-physical address space is:
+ *  P2M_TOP_PER_PAGE * P2M_MID_PER_PAGE * P2M_PER_PAGE pages
+ *
+ * P2M_PER_PAGE depends on the architecture, as a mfn is always
+ * unsigned long (8 bytes on 64-bit, 4 bytes on 32), leading to
+ * 512 and 1024 entries respectively. 
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/list.h>
+#include <linux/hash.h>
+#include <linux/sched.h>
+
+#include <asm/cache.h>
+#include <asm/setup.h>
+
+#include <asm/xen/page.h>
+#include <asm/xen/hypercall.h>
+#include <asm/xen/hypervisor.h>
+
+#include "xen-ops.h"
+
+static void __init m2p_override_init(void);
+
+unsigned long xen_max_p2m_pfn __read_mostly;
+
+#define P2M_PER_PAGE		(PAGE_SIZE / sizeof(unsigned long))
+#define P2M_MID_PER_PAGE	(PAGE_SIZE / sizeof(unsigned long *))
+#define P2M_TOP_PER_PAGE	(PAGE_SIZE / sizeof(unsigned long **))
+
+#define MAX_P2M_PFN		(P2M_TOP_PER_PAGE * P2M_MID_PER_PAGE * P2M_PER_PAGE)
+
+/* Placeholders for holes in the address space */
+static RESERVE_BRK_ARRAY(unsigned long, p2m_missing, P2M_PER_PAGE);
+static RESERVE_BRK_ARRAY(unsigned long *, p2m_mid_missing, P2M_MID_PER_PAGE);
+static RESERVE_BRK_ARRAY(unsigned long, p2m_mid_missing_mfn, P2M_MID_PER_PAGE);
+
+static RESERVE_BRK_ARRAY(unsigned long **, p2m_top, P2M_TOP_PER_PAGE);
+static RESERVE_BRK_ARRAY(unsigned long, p2m_top_mfn, P2M_TOP_PER_PAGE);
+static RESERVE_BRK_ARRAY(unsigned long *, p2m_top_mfn_p, P2M_TOP_PER_PAGE);
+
+RESERVE_BRK(p2m_mid, PAGE_SIZE * (MAX_DOMAIN_PAGES / (P2M_PER_PAGE * P2M_MID_PER_PAGE)));
+RESERVE_BRK(p2m_mid_mfn, PAGE_SIZE * (MAX_DOMAIN_PAGES / (P2M_PER_PAGE * P2M_MID_PER_PAGE)));
+
+static inline unsigned p2m_top_index(unsigned long pfn)
+{
+	BUG_ON(pfn >= MAX_P2M_PFN);
+	return pfn / (P2M_MID_PER_PAGE * P2M_PER_PAGE);
+}
+
+static inline unsigned p2m_mid_index(unsigned long pfn)
+{
+	return (pfn / P2M_PER_PAGE) % P2M_MID_PER_PAGE;
+}
+
+static inline unsigned p2m_index(unsigned long pfn)
+{
+	return pfn % P2M_PER_PAGE;
+}
+
+static void p2m_top_init(unsigned long ***top)
+{
+	unsigned i;
+
+	for (i = 0; i < P2M_TOP_PER_PAGE; i++)
+		top[i] = p2m_mid_missing;
+}
+
+static void p2m_top_mfn_init(unsigned long *top)
+{
+	unsigned i;
+
+	for (i = 0; i < P2M_TOP_PER_PAGE; i++)
+		top[i] = virt_to_mfn(p2m_mid_missing_mfn);
+}
+
+static void p2m_top_mfn_p_init(unsigned long **top)
+{
+	unsigned i;
+
+	for (i = 0; i < P2M_TOP_PER_PAGE; i++)
+		top[i] = p2m_mid_missing_mfn;
+}
+
+static void p2m_mid_init(unsigned long **mid)
+{
+	unsigned i;
+
+	for (i = 0; i < P2M_MID_PER_PAGE; i++)
+		mid[i] = p2m_missing;
+}
+
+static void p2m_mid_mfn_init(unsigned long *mid)
+{
+	unsigned i;
+
+	for (i = 0; i < P2M_MID_PER_PAGE; i++)
+		mid[i] = virt_to_mfn(p2m_missing);
+}
+
+static void p2m_init(unsigned long *p2m)
+{
+	unsigned i;
+
+	for (i = 0; i < P2M_MID_PER_PAGE; i++)
+		p2m[i] = INVALID_P2M_ENTRY;
+}
+
+/*
+ * Build the parallel p2m_top_mfn and p2m_mid_mfn structures
+ *
+ * This is called both at boot time, and after resuming from suspend:
+ * - At boot time we're called very early, and must use extend_brk()
+ *   to allocate memory.
+ *
+ * - After resume we're called from within stop_machine, but the mfn
+ *   tree should alreay be completely allocated.
+ */
+void xen_build_mfn_list_list(void)
+{
+	unsigned long pfn;
+
+	/* Pre-initialize p2m_top_mfn to be completely missing */
+	if (p2m_top_mfn == NULL) {
+		p2m_mid_missing_mfn = extend_brk(PAGE_SIZE, PAGE_SIZE);
+		p2m_mid_mfn_init(p2m_mid_missing_mfn);
+
+		p2m_top_mfn_p = extend_brk(PAGE_SIZE, PAGE_SIZE);
+		p2m_top_mfn_p_init(p2m_top_mfn_p);
+
+		p2m_top_mfn = extend_brk(PAGE_SIZE, PAGE_SIZE);
+		p2m_top_mfn_init(p2m_top_mfn);
+	} else {
+		/* Reinitialise, mfn's all change after migration */
+		p2m_mid_mfn_init(p2m_mid_missing_mfn);
+	}
+
+	for (pfn = 0; pfn < xen_max_p2m_pfn; pfn += P2M_PER_PAGE) {
+		unsigned topidx = p2m_top_index(pfn);
+		unsigned mididx = p2m_mid_index(pfn);
+		unsigned long **mid;
+		unsigned long *mid_mfn_p;
+
+		mid = p2m_top[topidx];
+		mid_mfn_p = p2m_top_mfn_p[topidx];
+
+		/* Don't bother allocating any mfn mid levels if
+		 * they're just missing, just update the stored mfn,
+		 * since all could have changed over a migrate.
+		 */
+		if (mid == p2m_mid_missing) {
+			BUG_ON(mididx);
+			BUG_ON(mid_mfn_p != p2m_mid_missing_mfn);
+			p2m_top_mfn[topidx] = virt_to_mfn(p2m_mid_missing_mfn);
+			pfn += (P2M_MID_PER_PAGE - 1) * P2M_PER_PAGE;
+			continue;
+		}
+
+		if (mid_mfn_p == p2m_mid_missing_mfn) {
+			/*
+			 * XXX boot-time only!  We should never find
+			 * missing parts of the mfn tree after
+			 * runtime.  extend_brk() will BUG if we call
+			 * it too late.
+			 */
+			mid_mfn_p = extend_brk(PAGE_SIZE, PAGE_SIZE);
+			p2m_mid_mfn_init(mid_mfn_p);
+
+			p2m_top_mfn_p[topidx] = mid_mfn_p;
+		}
+
+		p2m_top_mfn[topidx] = virt_to_mfn(mid_mfn_p);
+		mid_mfn_p[mididx] = virt_to_mfn(mid[mididx]);
+	}
+}
+
+void xen_setup_mfn_list_list(void)
+{
+	BUG_ON(HYPERVISOR_shared_info == &xen_dummy_shared_info);
+
+	HYPERVISOR_shared_info->arch.pfn_to_mfn_frame_list_list =
+		virt_to_mfn(p2m_top_mfn);
+	HYPERVISOR_shared_info->arch.max_pfn = xen_max_p2m_pfn;
+}
+
+/* Set up p2m_top to point to the domain-builder provided p2m pages */
+void __init xen_build_dynamic_phys_to_machine(void)
+{
+	unsigned long *mfn_list = (unsigned long *)xen_start_info->mfn_list;
+	unsigned long max_pfn = min(MAX_DOMAIN_PAGES, xen_start_info->nr_pages);
+	unsigned long pfn;
+
+	xen_max_p2m_pfn = max_pfn;
+
+	p2m_missing = extend_brk(PAGE_SIZE, PAGE_SIZE);
+	p2m_init(p2m_missing);
+
+	p2m_mid_missing = extend_brk(PAGE_SIZE, PAGE_SIZE);
+	p2m_mid_init(p2m_mid_missing);
+
+	p2m_top = extend_brk(PAGE_SIZE, PAGE_SIZE);
+	p2m_top_init(p2m_top);
+
+	/*
+	 * The domain builder gives us a pre-constructed p2m array in
+	 * mfn_list for all the pages initially given to us, so we just
+	 * need to graft that into our tree structure.
+	 */
+	for (pfn = 0; pfn < max_pfn; pfn += P2M_PER_PAGE) {
+		unsigned topidx = p2m_top_index(pfn);
+		unsigned mididx = p2m_mid_index(pfn);
+
+		if (p2m_top[topidx] == p2m_mid_missing) {
+			unsigned long **mid = extend_brk(PAGE_SIZE, PAGE_SIZE);
+			p2m_mid_init(mid);
+
+			p2m_top[topidx] = mid;
+		}
+
+		/*
+		 * As long as the mfn_list has enough entries to completely
+		 * fill a p2m page, pointing into the array is ok. But if
+		 * not the entries beyond the last pfn will be undefined.
+		 */
+		if (unlikely(pfn + P2M_PER_PAGE > max_pfn)) {
+			unsigned long p2midx;
+
+			p2midx = max_pfn % P2M_PER_PAGE;
+			for ( ; p2midx < P2M_PER_PAGE; p2midx++)
+				mfn_list[pfn + p2midx] = INVALID_P2M_ENTRY;
+		}
+		p2m_top[topidx][mididx] = &mfn_list[pfn];
+	}
+
+	m2p_override_init();
+}
+
+unsigned long get_phys_to_machine(unsigned long pfn)
+{
+	unsigned topidx, mididx, idx;
+
+	if (unlikely(pfn >= MAX_P2M_PFN))
+		return INVALID_P2M_ENTRY;
+
+	topidx = p2m_top_index(pfn);
+	mididx = p2m_mid_index(pfn);
+	idx = p2m_index(pfn);
+
+	return p2m_top[topidx][mididx][idx];
+}
+EXPORT_SYMBOL_GPL(get_phys_to_machine);
+
+static void *alloc_p2m_page(void)
+{
+	return (void *)__get_free_page(GFP_KERNEL | __GFP_REPEAT);
+}
+
+static void free_p2m_page(void *p)
+{
+	free_page((unsigned long)p);
+}
+
+/* 
+ * Fully allocate the p2m structure for a given pfn.  We need to check
+ * that both the top and mid levels are allocated, and make sure the
+ * parallel mfn tree is kept in sync.  We may race with other cpus, so
+ * the new pages are installed with cmpxchg; if we lose the race then
+ * simply free the page we allocated and use the one that's there.
+ */
+static bool alloc_p2m(unsigned long pfn)
+{
+	unsigned topidx, mididx;
+	unsigned long ***top_p, **mid;
+	unsigned long *top_mfn_p, *mid_mfn;
+
+	topidx = p2m_top_index(pfn);
+	mididx = p2m_mid_index(pfn);
+
+	top_p = &p2m_top[topidx];
+	mid = *top_p;
+
+	if (mid == p2m_mid_missing) {
+		/* Mid level is missing, allocate a new one */
+		mid = alloc_p2m_page();
+		if (!mid)
+			return false;
+
+		p2m_mid_init(mid);
+
+		if (cmpxchg(top_p, p2m_mid_missing, mid) != p2m_mid_missing)
+			free_p2m_page(mid);
+	}
+
+	top_mfn_p = &p2m_top_mfn[topidx];
+	mid_mfn = p2m_top_mfn_p[topidx];
+
+	BUG_ON(virt_to_mfn(mid_mfn) != *top_mfn_p);
+
+	if (mid_mfn == p2m_mid_missing_mfn) {
+		/* Separately check the mid mfn level */
+		unsigned long missing_mfn;
+		unsigned long mid_mfn_mfn;
+
+		mid_mfn = alloc_p2m_page();
+		if (!mid_mfn)
+			return false;
+
+		p2m_mid_mfn_init(mid_mfn);
+
+		missing_mfn = virt_to_mfn(p2m_mid_missing_mfn);
+		mid_mfn_mfn = virt_to_mfn(mid_mfn);
+		if (cmpxchg(top_mfn_p, missing_mfn, mid_mfn_mfn) != missing_mfn)
+			free_p2m_page(mid_mfn);
+		else
+			p2m_top_mfn_p[topidx] = mid_mfn;
+	}
+
+	if (p2m_top[topidx][mididx] == p2m_missing) {
+		/* p2m leaf page is missing */
+		unsigned long *p2m;
+
+		p2m = alloc_p2m_page();
+		if (!p2m)
+			return false;
+
+		p2m_init(p2m);
+
+		if (cmpxchg(&mid[mididx], p2m_missing, p2m) != p2m_missing)
+			free_p2m_page(p2m);
+		else
+			mid_mfn[mididx] = virt_to_mfn(p2m);
+	}
+
+	return true;
+}
+
+/* Try to install p2m mapping; fail if intermediate bits missing */
+bool __set_phys_to_machine(unsigned long pfn, unsigned long mfn)
+{
+	unsigned topidx, mididx, idx;
+
+	if (unlikely(pfn >= MAX_P2M_PFN)) {
+		BUG_ON(mfn != INVALID_P2M_ENTRY);
+		return true;
+	}
+
+	topidx = p2m_top_index(pfn);
+	mididx = p2m_mid_index(pfn);
+	idx = p2m_index(pfn);
+
+	if (p2m_top[topidx][mididx] == p2m_missing)
+		return mfn == INVALID_P2M_ENTRY;
+
+	p2m_top[topidx][mididx][idx] = mfn;
+
+	return true;
+}
+
+bool set_phys_to_machine(unsigned long pfn, unsigned long mfn)
+{
+	if (unlikely(xen_feature(XENFEAT_auto_translated_physmap))) {
+		BUG_ON(pfn != mfn && mfn != INVALID_P2M_ENTRY);
+		return true;
+	}
+
+	if (unlikely(!__set_phys_to_machine(pfn, mfn)))  {
+		if (!alloc_p2m(pfn))
+			return false;
+
+		if (!__set_phys_to_machine(pfn, mfn))
+			return false;
+	}
+
+	return true;
+}
+
+#define M2P_OVERRIDE_HASH_SHIFT	10
+#define M2P_OVERRIDE_HASH	(1 << M2P_OVERRIDE_HASH_SHIFT)
+
+static RESERVE_BRK_ARRAY(struct list_head, m2p_overrides, M2P_OVERRIDE_HASH);
+static DEFINE_SPINLOCK(m2p_override_lock);
+
+static void __init m2p_override_init(void)
+{
+	unsigned i;
+
+	m2p_overrides = extend_brk(sizeof(*m2p_overrides) * M2P_OVERRIDE_HASH,
+				   sizeof(unsigned long));
+
+	for (i = 0; i < M2P_OVERRIDE_HASH; i++)
+		INIT_LIST_HEAD(&m2p_overrides[i]);
+}
+
+static unsigned long mfn_hash(unsigned long mfn)
+{
+	return hash_long(mfn, M2P_OVERRIDE_HASH_SHIFT);
+}
+
+/* Add an MFN override for a particular page */
+int m2p_add_override(unsigned long mfn, struct page *page)
+{
+	unsigned long flags;
+	unsigned long pfn;
+	unsigned long address;
+	unsigned level;
+	pte_t *ptep = NULL;
+
+	pfn = page_to_pfn(page);
+	if (!PageHighMem(page)) {
+		address = (unsigned long)__va(pfn << PAGE_SHIFT);
+		ptep = lookup_address(address, &level);
+
+		if (WARN(ptep == NULL || level != PG_LEVEL_4K,
+					"m2p_add_override: pfn %lx not mapped", pfn))
+			return -EINVAL;
+	}
+
+	page->private = mfn;
+	page->index = pfn_to_mfn(pfn);
+
+	__set_phys_to_machine(pfn, FOREIGN_FRAME(mfn));
+	if (!PageHighMem(page))
+		/* Just zap old mapping for now */
+		pte_clear(&init_mm, address, ptep);
+
+	spin_lock_irqsave(&m2p_override_lock, flags);
+	list_add(&page->lru,  &m2p_overrides[mfn_hash(mfn)]);
+	spin_unlock_irqrestore(&m2p_override_lock, flags);
+
+	return 0;
+}
+
+int m2p_remove_override(struct page *page)
+{
+	unsigned long flags;
+	unsigned long mfn;
+	unsigned long pfn;
+	unsigned long address;
+	unsigned level;
+	pte_t *ptep = NULL;
+
+	pfn = page_to_pfn(page);
+	mfn = get_phys_to_machine(pfn);
+	if (mfn == INVALID_P2M_ENTRY || !(mfn & FOREIGN_FRAME_BIT))
+		return -EINVAL;
+
+	if (!PageHighMem(page)) {
+		address = (unsigned long)__va(pfn << PAGE_SHIFT);
+		ptep = lookup_address(address, &level);
+
+		if (WARN(ptep == NULL || level != PG_LEVEL_4K,
+					"m2p_remove_override: pfn %lx not mapped", pfn))
+			return -EINVAL;
+	}
+
+	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);
+
+	if (!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. */
+
+	return 0;
+}
+
+struct page *m2p_find_override(unsigned long mfn)
+{
+	unsigned long flags;
+	struct list_head *bucket = &m2p_overrides[mfn_hash(mfn)];
+	struct page *p, *ret;
+
+	ret = NULL;
+
+	spin_lock_irqsave(&m2p_override_lock, flags);
+
+	list_for_each_entry(p, bucket, lru) {
+		if (p->private == mfn) {
+			ret = p;
+			break;
+		}
+	}
+
+	spin_unlock_irqrestore(&m2p_override_lock, flags);
+
+	return ret;
+}
+
+unsigned long m2p_find_override_pfn(unsigned long mfn, unsigned long pfn)
+{
+	struct page *p = m2p_find_override(mfn);
+	unsigned long ret = pfn;
+
+	if (p)
+		ret = page_to_pfn(p);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(m2p_find_override_pfn);
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/xen/setup.c linux-libre-2.6.38-gnu1/arch/x86/xen/setup.c
--- linux-libre-2.6.37-gnu1/arch/x86/xen/setup.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/xen/setup.c	2011-03-14 21:20:32.000000000 -0400
@@ -179,8 +179,13 @@ char * __init xen_memory_setup(void)
 	e820.nr_map = 0;
 	xen_extra_mem_start = mem_end;
 	for (i = 0; i < memmap.nr_entries; i++) {
-		unsigned long long end = map[i].addr + map[i].size;
+		unsigned long long end;
+
+		/* Guard against non-page aligned E820 entries. */
+		if (map[i].type == E820_RAM)
+			map[i].size -= (map[i].size + map[i].addr) % PAGE_SIZE;
 
+		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);
@@ -350,6 +355,7 @@ void __init xen_arch_setup(void)
 	boot_cpu_data.hlt_works_ok = 1;
 #endif
 	pm_idle = default_idle;
+	boot_option_idle_override = IDLE_HALT;
 
 	fiddle_vdso();
 }
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/xen/spinlock.c linux-libre-2.6.38-gnu1/arch/x86/xen/spinlock.c
--- linux-libre-2.6.37-gnu1/arch/x86/xen/spinlock.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/xen/spinlock.c	2011-03-14 21:20:32.000000000 -0400
@@ -159,8 +159,8 @@ static inline struct xen_spinlock *spinn
 {
 	struct xen_spinlock *prev;
 
-	prev = __get_cpu_var(lock_spinners);
-	__get_cpu_var(lock_spinners) = xl;
+	prev = __this_cpu_read(lock_spinners);
+	__this_cpu_write(lock_spinners, xl);
 
 	wmb();			/* set lock of interest before count */
 
@@ -179,14 +179,14 @@ static inline void unspinning_lock(struc
 	asm(LOCK_PREFIX " decw %0"
 	    : "+m" (xl->spinners) : : "memory");
 	wmb();			/* decrement count before restoring lock */
-	__get_cpu_var(lock_spinners) = prev;
+	__this_cpu_write(lock_spinners, prev);
 }
 
 static noinline int xen_spin_lock_slow(struct arch_spinlock *lock, bool irq_enable)
 {
 	struct xen_spinlock *xl = (struct xen_spinlock *)lock;
 	struct xen_spinlock *prev;
-	int irq = __get_cpu_var(lock_kicker_irq);
+	int irq = __this_cpu_read(lock_kicker_irq);
 	int ret;
 	u64 start;
 
diff -druNp linux-libre-2.6.37-gnu1/arch/x86/xen/time.c linux-libre-2.6.38-gnu1/arch/x86/xen/time.c
--- linux-libre-2.6.37-gnu1/arch/x86/xen/time.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/x86/xen/time.c	2011-03-14 21:20:32.000000000 -0400
@@ -135,24 +135,24 @@ static void do_stolen_accounting(void)
 
 	/* Add the appropriate number of ticks of stolen time,
 	   including any left-overs from last time. */
-	stolen = runnable + offline + __get_cpu_var(xen_residual_stolen);
+	stolen = runnable + offline + __this_cpu_read(xen_residual_stolen);
 
 	if (stolen < 0)
 		stolen = 0;
 
 	ticks = iter_div_u64_rem(stolen, NS_PER_TICK, &stolen);
-	__get_cpu_var(xen_residual_stolen) = stolen;
+	__this_cpu_write(xen_residual_stolen, stolen);
 	account_steal_ticks(ticks);
 
 	/* Add the appropriate number of ticks of blocked time,
 	   including any left-overs from last time. */
-	blocked += __get_cpu_var(xen_residual_blocked);
+	blocked += __this_cpu_read(xen_residual_blocked);
 
 	if (blocked < 0)
 		blocked = 0;
 
 	ticks = iter_div_u64_rem(blocked, NS_PER_TICK, &blocked);
-	__get_cpu_var(xen_residual_blocked) = blocked;
+	__this_cpu_write(xen_residual_blocked, blocked);
 	account_idle_ticks(ticks);
 }
 
diff -druNp linux-libre-2.6.37-gnu1/arch/xtensa/configs/common_defconfig linux-libre-2.6.38-gnu1/arch/xtensa/configs/common_defconfig
--- linux-libre-2.6.37-gnu1/arch/xtensa/configs/common_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/xtensa/configs/common_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -32,7 +32,7 @@ CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_HOTPLUG is not set
 CONFIG_KOBJECT_UEVENT=y
 # CONFIG_IKCONFIG is not set
-# CONFIG_EMBEDDED is not set
+# CONFIG_EXPERT is not set
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/xtensa/configs/iss_defconfig linux-libre-2.6.38-gnu1/arch/xtensa/configs/iss_defconfig
--- linux-libre-2.6.37-gnu1/arch/xtensa/configs/iss_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/xtensa/configs/iss_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -55,7 +55,7 @@ CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_SYSCTL=y
 CONFIG_ANON_INODES=y
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/xtensa/configs/s6105_defconfig linux-libre-2.6.38-gnu1/arch/xtensa/configs/s6105_defconfig
--- linux-libre-2.6.37-gnu1/arch/xtensa/configs/s6105_defconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/xtensa/configs/s6105_defconfig	2011-03-14 21:20:32.000000000 -0400
@@ -55,7 +55,7 @@ CONFIG_BLK_DEV_INITRD=y
 CONFIG_INITRAMFS_SOURCE=""
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 CONFIG_SYSCTL=y
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
diff -druNp linux-libre-2.6.37-gnu1/arch/xtensa/include/asm/ioctls.h linux-libre-2.6.38-gnu1/arch/xtensa/include/asm/ioctls.h
--- linux-libre-2.6.37-gnu1/arch/xtensa/include/asm/ioctls.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/xtensa/include/asm/ioctls.h	2011-03-14 21:20:32.000000000 -0400
@@ -98,6 +98,7 @@
 #define TCSETSF2	_IOW('T', 45, struct termios2)
 #define TIOCGPTN	_IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
 #define TIOCSPTLCK	_IOW('T',0x31, int)  /* Lock/unlock Pty */
+#define TIOCGDEV	_IOR('T',0x32, unsigned int) /* Get primary device node of /dev/console */
 #define TIOCSIG		_IOW('T',0x36, int)  /* Generate signal on Pty slave */
 
 #define TIOCSERCONFIG	_IO('T', 83)
diff -druNp linux-libre-2.6.37-gnu1/arch/xtensa/include/asm/mman.h linux-libre-2.6.38-gnu1/arch/xtensa/include/asm/mman.h
--- linux-libre-2.6.37-gnu1/arch/xtensa/include/asm/mman.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/arch/xtensa/include/asm/mman.h	2011-03-14 21:20:32.000000000 -0400
@@ -83,6 +83,9 @@
 #define MADV_MERGEABLE   12		/* KSM may merge identical pages */
 #define MADV_UNMERGEABLE 13		/* KSM may not merge identical pages */
 
+#define MADV_HUGEPAGE	14		/* Worth backing with hugepages */
+#define MADV_NOHUGEPAGE	15		/* Not worth backing with hugepages */
+
 /* compatibility flags */
 #define MAP_FILE	0
 
diff -druNp linux-libre-2.6.37-gnu1/block/blk-cgroup.c linux-libre-2.6.38-gnu1/block/blk-cgroup.c
--- linux-libre-2.6.37-gnu1/block/blk-cgroup.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/block/blk-cgroup.c	2011-03-14 21:20:32.000000000 -0400
@@ -1452,10 +1452,6 @@ blkiocg_create(struct cgroup_subsys *sub
 		goto done;
 	}
 
-	/* Currently we do not support hierarchy deeper than two level (0,1) */
-	if (parent != cgroup->top_cgroup)
-		return ERR_PTR(-EPERM);
-
 	blkcg = kzalloc(sizeof(*blkcg), GFP_KERNEL);
 	if (!blkcg)
 		return ERR_PTR(-ENOMEM);
diff -druNp linux-libre-2.6.37-gnu1/block/blk-core.c linux-libre-2.6.38-gnu1/block/blk-core.c
--- linux-libre-2.6.37-gnu1/block/blk-core.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/block/blk-core.c	2011-03-14 21:20:32.000000000 -0400
@@ -33,7 +33,7 @@
 
 #include "blk.h"
 
-EXPORT_TRACEPOINT_SYMBOL_GPL(block_remap);
+EXPORT_TRACEPOINT_SYMBOL_GPL(block_bio_remap);
 EXPORT_TRACEPOINT_SYMBOL_GPL(block_rq_remap);
 EXPORT_TRACEPOINT_SYMBOL_GPL(block_bio_complete);
 
@@ -64,13 +64,27 @@ static void drive_stat_acct(struct reque
 		return;
 
 	cpu = part_stat_lock();
-	part = disk_map_sector_rcu(rq->rq_disk, blk_rq_pos(rq));
 
-	if (!new_io)
+	if (!new_io) {
+		part = rq->part;
 		part_stat_inc(cpu, part, merges[rw]);
-	else {
+	} else {
+		part = disk_map_sector_rcu(rq->rq_disk, blk_rq_pos(rq));
+		if (!hd_struct_try_get(part)) {
+			/*
+			 * The partition is already being removed,
+			 * the request will be accounted on the disk only
+			 *
+			 * We take a reference on disk->part0 although that
+			 * partition will never be deleted, so we can treat
+			 * it as any other partition.
+			 */
+			part = &rq->rq_disk->part0;
+			hd_struct_get(part);
+		}
 		part_round_stats(cpu, part);
 		part_inc_in_flight(part, rw);
+		rq->part = part;
 	}
 
 	part_stat_unlock();
@@ -128,6 +142,7 @@ void blk_rq_init(struct request_queue *q
 	rq->ref_count = 1;
 	rq->start_time = jiffies;
 	set_start_time_ns(rq);
+	rq->part = NULL;
 }
 EXPORT_SYMBOL(blk_rq_init);
 
@@ -337,7 +352,7 @@ void blk_start_queue(struct request_queu
 	WARN_ON(!irqs_disabled());
 
 	queue_flag_clear(QUEUE_FLAG_STOPPED, q);
-	__blk_run_queue(q);
+	__blk_run_queue(q, false);
 }
 EXPORT_SYMBOL(blk_start_queue);
 
@@ -388,13 +403,14 @@ EXPORT_SYMBOL(blk_sync_queue);
 /**
  * __blk_run_queue - run a single device queue
  * @q:	The queue to run
+ * @force_kblockd: Don't run @q->request_fn directly.  Use kblockd.
  *
  * Description:
  *    See @blk_run_queue. This variant must be called with the queue lock
  *    held and interrupts disabled.
  *
  */
-void __blk_run_queue(struct request_queue *q)
+void __blk_run_queue(struct request_queue *q, bool force_kblockd)
 {
 	blk_remove_plug(q);
 
@@ -408,7 +424,7 @@ void __blk_run_queue(struct request_queu
 	 * Only recurse once to avoid overrunning the stack, let the unplug
 	 * handling reinvoke the handler shortly if we already got there.
 	 */
-	if (!queue_flag_test_and_set(QUEUE_FLAG_REENTER, q)) {
+	if (!force_kblockd && !queue_flag_test_and_set(QUEUE_FLAG_REENTER, q)) {
 		q->request_fn(q);
 		queue_flag_clear(QUEUE_FLAG_REENTER, q);
 	} else {
@@ -431,7 +447,7 @@ void blk_run_queue(struct request_queue
 	unsigned long flags;
 
 	spin_lock_irqsave(q->queue_lock, flags);
-	__blk_run_queue(q);
+	__blk_run_queue(q, false);
 	spin_unlock_irqrestore(q->queue_lock, flags);
 }
 EXPORT_SYMBOL(blk_run_queue);
@@ -1038,7 +1054,7 @@ void blk_insert_request(struct request_q
 
 	drive_stat_acct(rq, 1);
 	__elv_add_request(q, rq, where, 0);
-	__blk_run_queue(q);
+	__blk_run_queue(q, false);
 	spin_unlock_irqrestore(q->queue_lock, flags);
 }
 EXPORT_SYMBOL(blk_insert_request);
@@ -1329,9 +1345,9 @@ static inline void blk_partition_remap(s
 		bio->bi_sector += p->start_sect;
 		bio->bi_bdev = bdev->bd_contains;
 
-		trace_block_remap(bdev_get_queue(bio->bi_bdev), bio,
-				    bdev->bd_dev,
-				    bio->bi_sector - p->start_sect);
+		trace_block_bio_remap(bdev_get_queue(bio->bi_bdev), bio,
+				      bdev->bd_dev,
+				      bio->bi_sector - p->start_sect);
 	}
 }
 
@@ -1500,7 +1516,7 @@ static inline void __generic_make_reques
 			goto end_io;
 
 		if (old_sector != -1)
-			trace_block_remap(q, bio, old_dev, old_sector);
+			trace_block_bio_remap(q, bio, old_dev, old_sector);
 
 		old_sector = bio->bi_sector;
 		old_dev = bio->bi_bdev->bd_dev;
@@ -1776,7 +1792,7 @@ static void blk_account_io_completion(st
 		int cpu;
 
 		cpu = part_stat_lock();
-		part = disk_map_sector_rcu(req->rq_disk, blk_rq_pos(req));
+		part = req->part;
 		part_stat_add(cpu, part, sectors[rw], bytes >> 9);
 		part_stat_unlock();
 	}
@@ -1796,13 +1812,14 @@ static void blk_account_io_done(struct r
 		int cpu;
 
 		cpu = part_stat_lock();
-		part = disk_map_sector_rcu(req->rq_disk, blk_rq_pos(req));
+		part = req->part;
 
 		part_stat_inc(cpu, part, ios[rw]);
 		part_stat_add(cpu, part, ticks[rw], duration);
 		part_round_stats(cpu, part);
 		part_dec_in_flight(part, rw);
 
+		hd_struct_put(part);
 		part_stat_unlock();
 	}
 }
@@ -2594,19 +2611,14 @@ int kblockd_schedule_work(struct request
 }
 EXPORT_SYMBOL(kblockd_schedule_work);
 
-int kblockd_schedule_delayed_work(struct request_queue *q,
-			struct delayed_work *dwork, unsigned long delay)
-{
-	return queue_delayed_work(kblockd_workqueue, dwork, delay);
-}
-EXPORT_SYMBOL(kblockd_schedule_delayed_work);
-
 int __init blk_dev_init(void)
 {
 	BUILD_BUG_ON(__REQ_NR_BITS > 8 *
 			sizeof(((struct request *)0)->cmd_flags));
 
-	kblockd_workqueue = create_workqueue("kblockd");
+	/* used for unplugging and affects IO latency/throughput - HIGHPRI */
+	kblockd_workqueue = alloc_workqueue("kblockd",
+					    WQ_MEM_RECLAIM | WQ_HIGHPRI, 0);
 	if (!kblockd_workqueue)
 		panic("Failed to create kblockd\n");
 
diff -druNp linux-libre-2.6.37-gnu1/block/blk-flush.c linux-libre-2.6.38-gnu1/block/blk-flush.c
--- linux-libre-2.6.37-gnu1/block/blk-flush.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/block/blk-flush.c	2011-03-14 21:20:32.000000000 -0400
@@ -66,10 +66,12 @@ static void blk_flush_complete_seq_end_i
 
 	/*
 	 * Moving a request silently to empty queue_head may stall the
-	 * queue.  Kick the queue in those cases.
+	 * queue.  Kick the queue in those cases.  This function is called
+	 * from request completion path and calling directly into
+	 * request_fn may confuse the driver.  Always use kblockd.
 	 */
 	if (was_empty && next_rq)
-		__blk_run_queue(q);
+		__blk_run_queue(q, true);
 }
 
 static void pre_flush_end_io(struct request *rq, int error)
@@ -130,7 +132,7 @@ static struct request *queue_next_fseq(s
 		BUG();
 	}
 
-	elv_insert(q, rq, ELEVATOR_INSERT_FRONT);
+	elv_insert(q, rq, ELEVATOR_INSERT_REQUEUE);
 	return rq;
 }
 
diff -druNp linux-libre-2.6.37-gnu1/block/blk-ioc.c linux-libre-2.6.38-gnu1/block/blk-ioc.c
--- linux-libre-2.6.37-gnu1/block/blk-ioc.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/block/blk-ioc.c	2011-03-14 21:20:32.000000000 -0400
@@ -64,7 +64,7 @@ static void cfq_exit(struct io_context *
 	rcu_read_unlock();
 }
 
-/* Called by the exitting task */
+/* Called by the exiting task */
 void exit_io_context(struct task_struct *task)
 {
 	struct io_context *ioc;
@@ -74,10 +74,9 @@ void exit_io_context(struct task_struct
 	task->io_context = NULL;
 	task_unlock(task);
 
-	if (atomic_dec_and_test(&ioc->nr_tasks)) {
+	if (atomic_dec_and_test(&ioc->nr_tasks))
 		cfq_exit(ioc);
 
-	}
 	put_io_context(ioc);
 }
 
diff -druNp linux-libre-2.6.37-gnu1/block/blk-lib.c linux-libre-2.6.38-gnu1/block/blk-lib.c
--- linux-libre-2.6.37-gnu1/block/blk-lib.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/block/blk-lib.c	2011-03-14 21:20:32.000000000 -0400
@@ -109,7 +109,6 @@ struct bio_batch
 	atomic_t 		done;
 	unsigned long 		flags;
 	struct completion 	*wait;
-	bio_end_io_t		*end_io;
 };
 
 static void bio_batch_end_io(struct bio *bio, int err)
@@ -122,17 +121,14 @@ static void bio_batch_end_io(struct bio
 		else
 			clear_bit(BIO_UPTODATE, &bb->flags);
 	}
-	if (bb) {
-		if (bb->end_io)
-			bb->end_io(bio, err);
-		atomic_inc(&bb->done);
-		complete(bb->wait);
-	}
+	if (bb)
+		if (atomic_dec_and_test(&bb->done))
+			complete(bb->wait);
 	bio_put(bio);
 }
 
 /**
- * blkdev_issue_zeroout generate number of zero filed write bios
+ * blkdev_issue_zeroout - generate number of zero filed write bios
  * @bdev:	blockdev to issue
  * @sector:	start sector
  * @nr_sects:	number of sectors to write
@@ -150,13 +146,12 @@ int blkdev_issue_zeroout(struct block_de
 	int ret;
 	struct bio *bio;
 	struct bio_batch bb;
-	unsigned int sz, issued = 0;
+	unsigned int sz;
 	DECLARE_COMPLETION_ONSTACK(wait);
 
-	atomic_set(&bb.done, 0);
+	atomic_set(&bb.done, 1);
 	bb.flags = 1 << BIO_UPTODATE;
 	bb.wait = &wait;
-	bb.end_io = NULL;
 
 submit:
 	ret = 0;
@@ -185,12 +180,12 @@ submit:
 				break;
 		}
 		ret = 0;
-		issued++;
+		atomic_inc(&bb.done);
 		submit_bio(WRITE, bio);
 	}
 
 	/* Wait for bios in-flight */
-	while (issued != atomic_read(&bb.done))
+	if (!atomic_dec_and_test(&bb.done))
 		wait_for_completion(&wait);
 
 	if (!test_bit(BIO_UPTODATE, &bb.flags))
diff -druNp linux-libre-2.6.37-gnu1/block/blk-merge.c linux-libre-2.6.38-gnu1/block/blk-merge.c
--- linux-libre-2.6.37-gnu1/block/blk-merge.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/block/blk-merge.c	2011-03-14 21:20:32.000000000 -0400
@@ -351,11 +351,12 @@ static void blk_account_io_merge(struct
 		int cpu;
 
 		cpu = part_stat_lock();
-		part = disk_map_sector_rcu(req->rq_disk, blk_rq_pos(req));
+		part = req->part;
 
 		part_round_stats(cpu, part);
 		part_dec_in_flight(part, rq_data_dir(req));
 
+		hd_struct_put(part);
 		part_stat_unlock();
 	}
 }
diff -druNp linux-libre-2.6.37-gnu1/block/blk-throttle.c linux-libre-2.6.38-gnu1/block/blk-throttle.c
--- linux-libre-2.6.37-gnu1/block/blk-throttle.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/block/blk-throttle.c	2011-03-14 21:20:32.000000000 -0400
@@ -20,6 +20,11 @@ static int throtl_quantum = 32;
 /* Throttling is performed over 100ms slice and after that slice is renewed */
 static unsigned long throtl_slice = HZ/10;	/* 100 ms */
 
+/* A workqueue to queue throttle related work */
+static struct workqueue_struct *kthrotld_workqueue;
+static void throtl_schedule_delayed_work(struct throtl_data *td,
+				unsigned long delay);
+
 struct throtl_rb_root {
 	struct rb_root rb;
 	struct rb_node *left;
@@ -168,7 +173,15 @@ static struct throtl_grp * throtl_find_a
 	 * tree of blkg (instead of traversing through hash list all
 	 * the time.
 	 */
-	tg = tg_of_blkg(blkiocg_lookup_group(blkcg, key));
+
+	/*
+	 * This is the common case when there are no blkio cgroups.
+ 	 * Avoid lookup in this case
+ 	 */
+	if (blkcg == &blkio_root_cgroup)
+		tg = &td->root_tg;
+	else
+		tg = tg_of_blkg(blkiocg_lookup_group(blkcg, key));
 
 	/* Fill in device details for root group */
 	if (tg && !tg->blkg.dev && bdi->dev && dev_name(bdi->dev)) {
@@ -337,10 +350,9 @@ static void throtl_schedule_next_dispatc
 	update_min_dispatch_time(st);
 
 	if (time_before_eq(st->min_disptime, jiffies))
-		throtl_schedule_delayed_work(td->queue, 0);
+		throtl_schedule_delayed_work(td, 0);
 	else
-		throtl_schedule_delayed_work(td->queue,
-				(st->min_disptime - jiffies));
+		throtl_schedule_delayed_work(td, (st->min_disptime - jiffies));
 }
 
 static inline void
@@ -807,10 +819,10 @@ void blk_throtl_work(struct work_struct
 }
 
 /* Call with queue lock held */
-void throtl_schedule_delayed_work(struct request_queue *q, unsigned long delay)
+static void
+throtl_schedule_delayed_work(struct throtl_data *td, unsigned long delay)
 {
 
-	struct throtl_data *td = q->td;
 	struct delayed_work *dwork = &td->throtl_work;
 
 	if (total_nr_queued(td) > 0) {
@@ -819,12 +831,11 @@ void throtl_schedule_delayed_work(struct
 		 * Cancel that and schedule a new one.
 		 */
 		__cancel_delayed_work(dwork);
-		kblockd_schedule_delayed_work(q, dwork, delay);
+		queue_delayed_work(kthrotld_workqueue, dwork, delay);
 		throtl_log(td, "schedule work. delay=%lu jiffies=%lu",
 				delay, jiffies);
 	}
 }
-EXPORT_SYMBOL(throtl_schedule_delayed_work);
 
 static void
 throtl_destroy_tg(struct throtl_data *td, struct throtl_grp *tg)
@@ -912,7 +923,7 @@ static void throtl_update_blkio_group_re
 	smp_mb__after_atomic_inc();
 
 	/* Schedule a work now to process the limit change */
-	throtl_schedule_delayed_work(td->queue, 0);
+	throtl_schedule_delayed_work(td, 0);
 }
 
 static void throtl_update_blkio_group_write_bps(void *key,
@@ -926,7 +937,7 @@ static void throtl_update_blkio_group_wr
 	smp_mb__before_atomic_inc();
 	atomic_inc(&td->limits_changed);
 	smp_mb__after_atomic_inc();
-	throtl_schedule_delayed_work(td->queue, 0);
+	throtl_schedule_delayed_work(td, 0);
 }
 
 static void throtl_update_blkio_group_read_iops(void *key,
@@ -940,7 +951,7 @@ static void throtl_update_blkio_group_re
 	smp_mb__before_atomic_inc();
 	atomic_inc(&td->limits_changed);
 	smp_mb__after_atomic_inc();
-	throtl_schedule_delayed_work(td->queue, 0);
+	throtl_schedule_delayed_work(td, 0);
 }
 
 static void throtl_update_blkio_group_write_iops(void *key,
@@ -954,7 +965,7 @@ static void throtl_update_blkio_group_wr
 	smp_mb__before_atomic_inc();
 	atomic_inc(&td->limits_changed);
 	smp_mb__after_atomic_inc();
-	throtl_schedule_delayed_work(td->queue, 0);
+	throtl_schedule_delayed_work(td, 0);
 }
 
 void throtl_shutdown_timer_wq(struct request_queue *q)
@@ -1127,6 +1138,10 @@ void blk_throtl_exit(struct request_queu
 
 static int __init throtl_init(void)
 {
+	kthrotld_workqueue = alloc_workqueue("kthrotld", WQ_MEM_RECLAIM, 0);
+	if (!kthrotld_workqueue)
+		panic("Failed to create kthrotld\n");
+
 	blkio_policy_register(&blkio_policy_throtl);
 	return 0;
 }
diff -druNp linux-libre-2.6.37-gnu1/block/cfq-iosched.c linux-libre-2.6.38-gnu1/block/cfq-iosched.c
--- linux-libre-2.6.37-gnu1/block/cfq-iosched.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/block/cfq-iosched.c	2011-03-14 21:20:32.000000000 -0400
@@ -87,7 +87,6 @@ struct cfq_rb_root {
 	unsigned count;
 	unsigned total_weight;
 	u64 min_vdisktime;
-	struct rb_node *active;
 };
 #define CFQ_RB_ROOT	(struct cfq_rb_root) { .rb = RB_ROOT, .left = NULL, \
 			.count = 0, .min_vdisktime = 0, }
@@ -97,7 +96,7 @@ struct cfq_rb_root {
  */
 struct cfq_queue {
 	/* reference count */
-	atomic_t ref;
+	int ref;
 	/* various state flags, see below */
 	unsigned int flags;
 	/* parent cfq_data */
@@ -180,7 +179,6 @@ struct cfq_group {
 	/* group service_tree key */
 	u64 vdisktime;
 	unsigned int weight;
-	bool on_st;
 
 	/* number of cfqq currently on this group */
 	int nr_cfqq;
@@ -209,7 +207,7 @@ struct cfq_group {
 	struct blkio_group blkg;
 #ifdef CONFIG_CFQ_GROUP_IOSCHED
 	struct hlist_node cfqd_node;
-	atomic_t ref;
+	int ref;
 #endif
 	/* number of requests that are on the dispatch list or inside driver */
 	int dispatched;
@@ -563,11 +561,6 @@ static void update_min_vdisktime(struct
 	u64 vdisktime = st->min_vdisktime;
 	struct cfq_group *cfqg;
 
-	if (st->active) {
-		cfqg = rb_entry_cfqg(st->active);
-		vdisktime = cfqg->vdisktime;
-	}
-
 	if (st->left) {
 		cfqg = rb_entry_cfqg(st->left);
 		vdisktime = min_vdisktime(vdisktime, cfqg->vdisktime);
@@ -605,8 +598,8 @@ cfq_group_slice(struct cfq_data *cfqd, s
 	return cfq_target_latency * cfqg->weight / st->total_weight;
 }
 
-static inline void
-cfq_set_prio_slice(struct cfq_data *cfqd, struct cfq_queue *cfqq)
+static inline unsigned
+cfq_scaled_cfqq_slice(struct cfq_data *cfqd, struct cfq_queue *cfqq)
 {
 	unsigned slice = cfq_prio_to_slice(cfqd, cfqq);
 	if (cfqd->cfq_latency) {
@@ -632,6 +625,14 @@ cfq_set_prio_slice(struct cfq_data *cfqd
 				    low_slice);
 		}
 	}
+	return slice;
+}
+
+static inline void
+cfq_set_prio_slice(struct cfq_data *cfqd, struct cfq_queue *cfqq)
+{
+	unsigned slice = cfq_scaled_cfqq_slice(cfqd, cfqq);
+
 	cfqq->slice_start = jiffies;
 	cfqq->slice_end = jiffies + slice;
 	cfqq->allocated_slice = slice;
@@ -646,11 +647,11 @@ cfq_set_prio_slice(struct cfq_data *cfqd
 static inline bool cfq_slice_used(struct cfq_queue *cfqq)
 {
 	if (cfq_cfqq_slice_new(cfqq))
-		return 0;
+		return false;
 	if (time_before(jiffies, cfqq->slice_end))
-		return 0;
+		return false;
 
-	return 1;
+	return true;
 }
 
 /*
@@ -869,7 +870,7 @@ cfq_group_service_tree_add(struct cfq_da
 	struct rb_node *n;
 
 	cfqg->nr_cfqq++;
-	if (cfqg->on_st)
+	if (!RB_EMPTY_NODE(&cfqg->rb_node))
 		return;
 
 	/*
@@ -885,7 +886,6 @@ cfq_group_service_tree_add(struct cfq_da
 		cfqg->vdisktime = st->min_vdisktime;
 
 	__cfq_group_service_tree_add(st, cfqg);
-	cfqg->on_st = true;
 	st->total_weight += cfqg->weight;
 }
 
@@ -894,9 +894,6 @@ cfq_group_service_tree_del(struct cfq_da
 {
 	struct cfq_rb_root *st = &cfqd->grp_service_tree;
 
-	if (st->active == &cfqg->rb_node)
-		st->active = NULL;
-
 	BUG_ON(cfqg->nr_cfqq < 1);
 	cfqg->nr_cfqq--;
 
@@ -905,7 +902,6 @@ cfq_group_service_tree_del(struct cfq_da
 		return;
 
 	cfq_log_cfqg(cfqd, cfqg, "del_from_rr group");
-	cfqg->on_st = false;
 	st->total_weight -= cfqg->weight;
 	if (!RB_EMPTY_NODE(&cfqg->rb_node))
 		cfq_rb_erase(&cfqg->rb_node, st);
@@ -1026,11 +1022,11 @@ cfq_find_alloc_cfqg(struct cfq_data *cfq
 	 * elevator which will be dropped by either elevator exit
 	 * or cgroup deletion path depending on who is exiting first.
 	 */
-	atomic_set(&cfqg->ref, 1);
+	cfqg->ref = 1;
 
 	/*
 	 * Add group onto cgroup list. It might happen that bdi->dev is
-	 * not initiliazed yet. Initialize this new group without major
+	 * not initialized yet. Initialize this new group without major
 	 * and minor info and this info will be filled in once a new thread
 	 * comes for IO. See code above.
 	 */
@@ -1071,7 +1067,7 @@ static struct cfq_group *cfq_get_cfqg(st
 
 static inline struct cfq_group *cfq_ref_get_cfqg(struct cfq_group *cfqg)
 {
-	atomic_inc(&cfqg->ref);
+	cfqg->ref++;
 	return cfqg;
 }
 
@@ -1083,7 +1079,7 @@ static void cfq_link_cfqq_cfqg(struct cf
 
 	cfqq->cfqg = cfqg;
 	/* cfqq reference on cfqg */
-	atomic_inc(&cfqq->cfqg->ref);
+	cfqq->cfqg->ref++;
 }
 
 static void cfq_put_cfqg(struct cfq_group *cfqg)
@@ -1091,11 +1087,12 @@ static void cfq_put_cfqg(struct cfq_grou
 	struct cfq_rb_root *st;
 	int i, j;
 
-	BUG_ON(atomic_read(&cfqg->ref) <= 0);
-	if (!atomic_dec_and_test(&cfqg->ref))
+	BUG_ON(cfqg->ref <= 0);
+	cfqg->ref--;
+	if (cfqg->ref)
 		return;
 	for_each_cfqg_st(cfqg, i, j, st)
-		BUG_ON(!RB_EMPTY_ROOT(&st->rb) || st->active != NULL);
+		BUG_ON(!RB_EMPTY_ROOT(&st->rb));
 	kfree(cfqg);
 }
 
@@ -1200,7 +1197,7 @@ static void cfq_service_tree_add(struct
 			cfq_group_service_tree_del(cfqd, cfqq->cfqg);
 		cfqq->orig_cfqg = cfqq->cfqg;
 		cfqq->cfqg = &cfqd->root_group;
-		atomic_inc(&cfqd->root_group.ref);
+		cfqd->root_group.ref++;
 		group_changed = 1;
 	} else if (!cfqd->cfq_group_isolation
 		   && cfqq_type(cfqq) == SYNC_WORKLOAD && cfqq->orig_cfqg) {
@@ -1672,8 +1669,11 @@ __cfq_slice_expired(struct cfq_data *cfq
 	/*
 	 * store what was left of this slice, if the queue idled/timed out
 	 */
-	if (timed_out && !cfq_cfqq_slice_new(cfqq)) {
-		cfqq->slice_resid = cfqq->slice_end - jiffies;
+	if (timed_out) {
+		if (cfq_cfqq_slice_new(cfqq))
+			cfqq->slice_resid = cfq_scaled_cfqq_slice(cfqd, cfqq);
+		else
+			cfqq->slice_resid = cfqq->slice_end - jiffies;
 		cfq_log_cfqq(cfqd, cfqq, "resid=%ld", cfqq->slice_resid);
 	}
 
@@ -1687,9 +1687,6 @@ __cfq_slice_expired(struct cfq_data *cfq
 	if (cfqq == cfqd->active_queue)
 		cfqd->active_queue = NULL;
 
-	if (&cfqq->cfqg->rb_node == cfqd->grp_service_tree.active)
-		cfqd->grp_service_tree.active = NULL;
-
 	if (cfqd->active_cic) {
 		put_io_context(cfqd->active_cic->ioc);
 		cfqd->active_cic = NULL;
@@ -1901,10 +1898,10 @@ static bool cfq_should_idle(struct cfq_d
 	 * in their service tree.
 	 */
 	if (service_tree->count == 1 && cfq_cfqq_sync(cfqq))
-		return 1;
+		return true;
 	cfq_log_cfqq(cfqd, cfqq, "Not idling. st->count:%d",
 			service_tree->count);
-	return 0;
+	return false;
 }
 
 static void cfq_arm_slice_timer(struct cfq_data *cfqd)
@@ -2040,7 +2037,7 @@ static int cfqq_process_refs(struct cfq_
 	int process_refs, io_refs;
 
 	io_refs = cfqq->allocated[READ] + cfqq->allocated[WRITE];
-	process_refs = atomic_read(&cfqq->ref) - io_refs;
+	process_refs = cfqq->ref - io_refs;
 	BUG_ON(process_refs < 0);
 	return process_refs;
 }
@@ -2080,10 +2077,10 @@ static void cfq_setup_merge(struct cfq_q
 	 */
 	if (new_process_refs >= process_refs) {
 		cfqq->new_cfqq = new_cfqq;
-		atomic_add(process_refs, &new_cfqq->ref);
+		new_cfqq->ref += process_refs;
 	} else {
 		new_cfqq->new_cfqq = cfqq;
-		atomic_add(new_process_refs, &cfqq->ref);
+		cfqq->ref += new_process_refs;
 	}
 }
 
@@ -2116,12 +2113,7 @@ static void choose_service_tree(struct c
 	unsigned count;
 	struct cfq_rb_root *st;
 	unsigned group_slice;
-
-	if (!cfqg) {
-		cfqd->serving_prio = IDLE_WORKLOAD;
-		cfqd->workload_expires = jiffies + 1;
-		return;
-	}
+	enum wl_prio_t original_prio = cfqd->serving_prio;
 
 	/* Choose next priority. RT > BE > IDLE */
 	if (cfq_group_busy_queues_wl(RT_WORKLOAD, cfqd, cfqg))
@@ -2134,6 +2126,9 @@ static void choose_service_tree(struct c
 		return;
 	}
 
+	if (original_prio != cfqd->serving_prio)
+		goto new_workload;
+
 	/*
 	 * For RT and BE, we have to choose also the type
 	 * (SYNC, SYNC_NOIDLE, ASYNC), and to compute a workload
@@ -2148,6 +2143,7 @@ static void choose_service_tree(struct c
 	if (count && !time_after(jiffies, cfqd->workload_expires))
 		return;
 
+new_workload:
 	/* otherwise select new workload type */
 	cfqd->serving_type =
 		cfq_choose_wl(cfqd, cfqg, cfqd->serving_prio);
@@ -2199,7 +2195,6 @@ static struct cfq_group *cfq_get_next_cf
 	if (RB_EMPTY_ROOT(&st->rb))
 		return NULL;
 	cfqg = cfq_rb_first_group(st);
-	st->active = &cfqg->rb_node;
 	update_min_vdisktime(st);
 	return cfqg;
 }
@@ -2293,6 +2288,17 @@ static struct cfq_queue *cfq_select_queu
 		goto keep_queue;
 	}
 
+	/*
+	 * This is a deep seek queue, but the device is much faster than
+	 * the queue can deliver, don't idle
+	 **/
+	if (CFQQ_SEEKY(cfqq) && cfq_cfqq_idle_window(cfqq) &&
+	    (cfq_cfqq_slice_new(cfqq) ||
+	    (cfqq->slice_end - jiffies > jiffies - cfqq->slice_start))) {
+		cfq_clear_cfqq_deep(cfqq);
+		cfq_clear_cfqq_idle_window(cfqq);
+	}
+
 	if (cfqq->dispatched && cfq_should_idle(cfqd, cfqq)) {
 		cfqq = NULL;
 		goto keep_queue;
@@ -2367,12 +2373,12 @@ static inline bool cfq_slice_used_soon(s
 {
 	/* the queue hasn't finished any request, can't estimate */
 	if (cfq_cfqq_slice_new(cfqq))
-		return 1;
+		return true;
 	if (time_after(jiffies + cfqd->cfq_slice_idle * cfqq->dispatched,
 		cfqq->slice_end))
-		return 1;
+		return true;
 
-	return 0;
+	return false;
 }
 
 static bool cfq_may_dispatch(struct cfq_data *cfqd, struct cfq_queue *cfqq)
@@ -2538,9 +2544,10 @@ static void cfq_put_queue(struct cfq_que
 	struct cfq_data *cfqd = cfqq->cfqd;
 	struct cfq_group *cfqg, *orig_cfqg;
 
-	BUG_ON(atomic_read(&cfqq->ref) <= 0);
+	BUG_ON(cfqq->ref <= 0);
 
-	if (!atomic_dec_and_test(&cfqq->ref))
+	cfqq->ref--;
+	if (cfqq->ref)
 		return;
 
 	cfq_log_cfqq(cfqd, cfqq, "put_queue");
@@ -2843,7 +2850,7 @@ static void cfq_init_cfqq(struct cfq_dat
 	RB_CLEAR_NODE(&cfqq->p_node);
 	INIT_LIST_HEAD(&cfqq->fifo);
 
-	atomic_set(&cfqq->ref, 0);
+	cfqq->ref = 0;
 	cfqq->cfqd = cfqd;
 
 	cfq_mark_cfqq_prio_changed(cfqq);
@@ -2979,11 +2986,11 @@ cfq_get_queue(struct cfq_data *cfqd, boo
 	 * pin the queue now that it's allocated, scheduler exit will prune it
 	 */
 	if (!is_sync && !(*async_cfqq)) {
-		atomic_inc(&cfqq->ref);
+		cfqq->ref++;
 		*async_cfqq = cfqq;
 	}
 
-	atomic_inc(&cfqq->ref);
+	cfqq->ref++;
 	return cfqq;
 }
 
@@ -3265,6 +3272,10 @@ cfq_should_preempt(struct cfq_data *cfqd
 	if (cfq_class_rt(new_cfqq) && !cfq_class_rt(cfqq))
 		return true;
 
+	/* An idle queue should not be idle now for some reason */
+	if (RB_EMPTY_ROOT(&cfqq->sort_list) && !cfq_should_idle(cfqd, cfqq))
+		return true;
+
 	if (!cfqd->active_cic || !cfq_cfqq_wait_request(cfqq))
 		return false;
 
@@ -3284,10 +3295,19 @@ cfq_should_preempt(struct cfq_data *cfqd
  */
 static void cfq_preempt_queue(struct cfq_data *cfqd, struct cfq_queue *cfqq)
 {
+	struct cfq_queue *old_cfqq = cfqd->active_queue;
+
 	cfq_log_cfqq(cfqd, cfqq, "preempt");
 	cfq_slice_expired(cfqd, 1);
 
 	/*
+	 * workload type is changed, don't save slice, otherwise preempt
+	 * doesn't happen
+	 */
+	if (cfqq_type(old_cfqq) != cfqq_type(cfqq))
+		cfqq->cfqg->saved_workload_slice = 0;
+
+	/*
 	 * Put the new queue at the front of the of the current list,
 	 * so we know that it will be selected next.
 	 */
@@ -3335,7 +3355,7 @@ cfq_rq_enqueued(struct cfq_data *cfqd, s
 			    cfqd->busy_queues > 1) {
 				cfq_del_timer(cfqd, cfqq);
 				cfq_clear_cfqq_wait_request(cfqq);
-				__blk_run_queue(cfqd->queue);
+				__blk_run_queue(cfqd->queue, false);
 			} else {
 				cfq_blkiocg_update_idle_time_stats(
 						&cfqq->cfqg->blkg);
@@ -3350,7 +3370,7 @@ cfq_rq_enqueued(struct cfq_data *cfqd, s
 		 * this new queue is RT and the current one is BE
 		 */
 		cfq_preempt_queue(cfqd, cfqq);
-		__blk_run_queue(cfqd->queue);
+		__blk_run_queue(cfqd->queue, false);
 	}
 }
 
@@ -3412,6 +3432,10 @@ static bool cfq_should_wait_busy(struct
 {
 	struct cfq_io_context *cic = cfqd->active_cic;
 
+	/* If the queue already has requests, don't wait */
+	if (!RB_EMPTY_ROOT(&cfqq->sort_list))
+		return false;
+
 	/* If there are other queues in the group, don't wait */
 	if (cfqq->cfqg->nr_cfqq > 1)
 		return false;
@@ -3681,13 +3705,13 @@ new_queue:
 	}
 
 	cfqq->allocated[rw]++;
-	atomic_inc(&cfqq->ref);
-
-	spin_unlock_irqrestore(q->queue_lock, flags);
-
+	cfqq->ref++;
 	rq->elevator_private = cic;
 	rq->elevator_private2 = cfqq;
 	rq->elevator_private3 = cfq_ref_get_cfqg(cfqq->cfqg);
+
+	spin_unlock_irqrestore(q->queue_lock, flags);
+
 	return 0;
 
 queue_fail:
@@ -3707,7 +3731,7 @@ static void cfq_kick_queue(struct work_s
 	struct request_queue *q = cfqd->queue;
 
 	spin_lock_irq(q->queue_lock);
-	__blk_run_queue(cfqd->queue);
+	__blk_run_queue(cfqd->queue, false);
 	spin_unlock_irq(q->queue_lock);
 }
 
@@ -3862,6 +3886,10 @@ static void *cfq_init_queue(struct reque
 	if (!cfqd)
 		return NULL;
 
+	/*
+	 * Don't need take queue_lock in the routine, since we are
+	 * initializing the ioscheduler, and nobody is using cfqd
+	 */
 	cfqd->cic_index = i;
 
 	/* Init root service tree */
@@ -3881,7 +3909,7 @@ static void *cfq_init_queue(struct reque
 	 * Take a reference to root group which we never drop. This is just
 	 * to make sure that cfq_put_cfqg() does not try to kfree root group
 	 */
-	atomic_set(&cfqg->ref, 1);
+	cfqg->ref = 1;
 	rcu_read_lock();
 	cfq_blkiocg_add_blkio_group(&blkio_root_cgroup, &cfqg->blkg,
 					(void *)cfqd, 0);
@@ -3901,7 +3929,7 @@ static void *cfq_init_queue(struct reque
 	 * will not attempt to free it.
 	 */
 	cfq_init_cfqq(cfqd, &cfqd->oom_cfqq, 1, 0);
-	atomic_inc(&cfqd->oom_cfqq.ref);
+	cfqd->oom_cfqq.ref++;
 	cfq_link_cfqq_cfqg(&cfqd->oom_cfqq, &cfqd->root_group);
 
 	INIT_LIST_HEAD(&cfqd->cic_list);
diff -druNp linux-libre-2.6.37-gnu1/block/elevator.c linux-libre-2.6.38-gnu1/block/elevator.c
--- linux-libre-2.6.37-gnu1/block/elevator.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/block/elevator.c	2011-03-14 21:20:32.000000000 -0400
@@ -602,7 +602,7 @@ void elv_quiesce_start(struct request_qu
 	 */
 	elv_drain_elevator(q);
 	while (q->rq.elvpriv) {
-		__blk_run_queue(q);
+		__blk_run_queue(q, false);
 		spin_unlock_irq(q->queue_lock);
 		msleep(10);
 		spin_lock_irq(q->queue_lock);
@@ -651,7 +651,7 @@ void elv_insert(struct request_queue *q,
 		 *   with anything.  There's no point in delaying queue
 		 *   processing.
 		 */
-		__blk_run_queue(q);
+		__blk_run_queue(q, false);
 		break;
 
 	case ELEVATOR_INSERT_SORT:
diff -druNp linux-libre-2.6.37-gnu1/block/genhd.c linux-libre-2.6.38-gnu1/block/genhd.c
--- linux-libre-2.6.37-gnu1/block/genhd.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/block/genhd.c	2011-03-14 21:20:32.000000000 -0400
@@ -18,6 +18,7 @@
 #include <linux/buffer_head.h>
 #include <linux/mutex.h>
 #include <linux/idr.h>
+#include <linux/log2.h>
 
 #include "blk.h"
 
@@ -35,6 +36,10 @@ static DEFINE_IDR(ext_devt_idr);
 
 static struct device_type disk_type;
 
+static void disk_add_events(struct gendisk *disk);
+static void disk_del_events(struct gendisk *disk);
+static void disk_release_events(struct gendisk *disk);
+
 /**
  * disk_get_part - get partition
  * @disk: disk to look partition from
@@ -239,7 +244,7 @@ static struct blk_major_name {
 } *major_names[BLKDEV_MAJOR_HASH_SIZE];
 
 /* index in the above - for now: assume no multimajor ranges */
-static inline int major_to_index(int major)
+static inline int major_to_index(unsigned major)
 {
 	return major % BLKDEV_MAJOR_HASH_SIZE;
 }
@@ -502,6 +507,64 @@ static int exact_lock(dev_t devt, void *
 	return 0;
 }
 
+void register_disk(struct gendisk *disk)
+{
+	struct device *ddev = disk_to_dev(disk);
+	struct block_device *bdev;
+	struct disk_part_iter piter;
+	struct hd_struct *part;
+	int err;
+
+	ddev->parent = disk->driverfs_dev;
+
+	dev_set_name(ddev, disk->disk_name);
+
+	/* delay uevents, until we scanned partition table */
+	dev_set_uevent_suppress(ddev, 1);
+
+	if (device_add(ddev))
+		return;
+	if (!sysfs_deprecated) {
+		err = sysfs_create_link(block_depr, &ddev->kobj,
+					kobject_name(&ddev->kobj));
+		if (err) {
+			device_del(ddev);
+			return;
+		}
+	}
+	disk->part0.holder_dir = kobject_create_and_add("holders", &ddev->kobj);
+	disk->slave_dir = kobject_create_and_add("slaves", &ddev->kobj);
+
+	/* No minors to use for partitions */
+	if (!disk_partitionable(disk))
+		goto exit;
+
+	/* No such device (e.g., media were just removed) */
+	if (!get_capacity(disk))
+		goto exit;
+
+	bdev = bdget_disk(disk, 0);
+	if (!bdev)
+		goto exit;
+
+	bdev->bd_invalidated = 1;
+	err = blkdev_get(bdev, FMODE_READ, NULL);
+	if (err < 0)
+		goto exit;
+	blkdev_put(bdev, FMODE_READ);
+
+exit:
+	/* announce disk after possible partitions are created */
+	dev_set_uevent_suppress(ddev, 0);
+	kobject_uevent(&ddev->kobj, KOBJ_ADD);
+
+	/* announce possible partitions */
+	disk_part_iter_init(&piter, disk, 0);
+	while ((part = disk_part_iter_next(&piter)))
+		kobject_uevent(&part_to_dev(part)->kobj, KOBJ_ADD);
+	disk_part_iter_exit(&piter);
+}
+
 /**
  * add_disk - add partitioning information to kernel list
  * @disk: per-device partitioning information
@@ -551,18 +614,48 @@ void add_disk(struct gendisk *disk)
 	retval = sysfs_create_link(&disk_to_dev(disk)->kobj, &bdi->dev->kobj,
 				   "bdi");
 	WARN_ON(retval);
-}
 
+	disk_add_events(disk);
+}
 EXPORT_SYMBOL(add_disk);
-EXPORT_SYMBOL(del_gendisk);	/* in partitions/check.c */
 
-void unlink_gendisk(struct gendisk *disk)
+void del_gendisk(struct gendisk *disk)
 {
+	struct disk_part_iter piter;
+	struct hd_struct *part;
+
+	disk_del_events(disk);
+
+	/* invalidate stuff */
+	disk_part_iter_init(&piter, disk,
+			     DISK_PITER_INCL_EMPTY | DISK_PITER_REVERSE);
+	while ((part = disk_part_iter_next(&piter))) {
+		invalidate_partition(disk, part->partno);
+		delete_partition(disk, part->partno);
+	}
+	disk_part_iter_exit(&piter);
+
+	invalidate_partition(disk, 0);
+	blk_free_devt(disk_to_dev(disk)->devt);
+	set_capacity(disk, 0);
+	disk->flags &= ~GENHD_FL_UP;
+
 	sysfs_remove_link(&disk_to_dev(disk)->kobj, "bdi");
 	bdi_unregister(&disk->queue->backing_dev_info);
 	blk_unregister_queue(disk);
 	blk_unregister_region(disk_devt(disk), disk->minors);
+
+	part_stat_set_all(&disk->part0, 0);
+	disk->part0.stamp = 0;
+
+	kobject_put(disk->part0.holder_dir);
+	kobject_put(disk->slave_dir);
+	disk->driverfs_dev = NULL;
+	if (!sysfs_deprecated)
+		sysfs_remove_link(block_depr, dev_name(disk_to_dev(disk)));
+	device_del(disk_to_dev(disk));
 }
+EXPORT_SYMBOL(del_gendisk);
 
 /**
  * get_gendisk - get partitioning information for a given device
@@ -735,7 +828,7 @@ static void *show_partition_start(struct
 	static void *p;
 
 	p = disk_seqf_start(seqf, pos);
-	if (!IS_ERR(p) && p && !*pos)
+	if (!IS_ERR_OR_NULL(p) && !*pos)
 		seq_puts(seqf, "major minor  #blocks  name\n\n");
 	return p;
 }
@@ -1005,6 +1098,7 @@ static void disk_release(struct device *
 {
 	struct gendisk *disk = dev_to_disk(dev);
 
+	disk_release_events(disk);
 	kfree(disk->random);
 	disk_replace_part_tbl(disk, NULL);
 	free_part_stats(&disk->part0);
@@ -1110,29 +1204,6 @@ static int __init proc_genhd_init(void)
 module_init(proc_genhd_init);
 #endif /* CONFIG_PROC_FS */
 
-static void media_change_notify_thread(struct work_struct *work)
-{
-	struct gendisk *gd = container_of(work, struct gendisk, async_notify);
-	char event[] = "MEDIA_CHANGE=1";
-	char *envp[] = { event, NULL };
-
-	/*
-	 * set enviroment vars to indicate which event this is for
-	 * so that user space will know to go check the media status.
-	 */
-	kobject_uevent_env(&disk_to_dev(gd)->kobj, KOBJ_CHANGE, envp);
-	put_device(gd->driverfs_dev);
-}
-
-#if 0
-void genhd_media_change_notify(struct gendisk *disk)
-{
-	get_device(disk->driverfs_dev);
-	schedule_work(&disk->async_notify);
-}
-EXPORT_SYMBOL_GPL(genhd_media_change_notify);
-#endif  /*  0  */
-
 dev_t blk_lookup_devt(const char *name, int partno)
 {
 	dev_t devt = MKDEV(0, 0);
@@ -1193,13 +1264,13 @@ struct gendisk *alloc_disk_node(int mino
 		}
 		disk->part_tbl->part[0] = &disk->part0;
 
+		hd_ref_init(&disk->part0);
+
 		disk->minors = minors;
 		rand_initialize_disk(disk);
 		disk_to_dev(disk)->class = &block_class;
 		disk_to_dev(disk)->type = &disk_type;
 		device_initialize(disk_to_dev(disk));
-		INIT_WORK(&disk->async_notify,
-			media_change_notify_thread);
 	}
 	return disk;
 }
@@ -1284,10 +1355,429 @@ int invalidate_partition(struct gendisk
 	struct block_device *bdev = bdget_disk(disk, partno);
 	if (bdev) {
 		fsync_bdev(bdev);
-		res = __invalidate_device(bdev);
+		res = __invalidate_device(bdev, true);
 		bdput(bdev);
 	}
 	return res;
 }
 
 EXPORT_SYMBOL(invalidate_partition);
+
+/*
+ * Disk events - monitor disk events like media change and eject request.
+ */
+struct disk_events {
+	struct list_head	node;		/* all disk_event's */
+	struct gendisk		*disk;		/* the associated disk */
+	spinlock_t		lock;
+
+	int			block;		/* event blocking depth */
+	unsigned int		pending;	/* events already sent out */
+	unsigned int		clearing;	/* events being cleared */
+
+	long			poll_msecs;	/* interval, -1 for default */
+	struct delayed_work	dwork;
+};
+
+static const char *disk_events_strs[] = {
+	[ilog2(DISK_EVENT_MEDIA_CHANGE)]	= "media_change",
+	[ilog2(DISK_EVENT_EJECT_REQUEST)]	= "eject_request",
+};
+
+static char *disk_uevents[] = {
+	[ilog2(DISK_EVENT_MEDIA_CHANGE)]	= "DISK_MEDIA_CHANGE=1",
+	[ilog2(DISK_EVENT_EJECT_REQUEST)]	= "DISK_EJECT_REQUEST=1",
+};
+
+/* list of all disk_events */
+static DEFINE_MUTEX(disk_events_mutex);
+static LIST_HEAD(disk_events);
+
+/* disable in-kernel polling by default */
+static unsigned long disk_events_dfl_poll_msecs	= 0;
+
+static unsigned long disk_events_poll_jiffies(struct gendisk *disk)
+{
+	struct disk_events *ev = disk->ev;
+	long intv_msecs = 0;
+
+	/*
+	 * If device-specific poll interval is set, always use it.  If
+	 * the default is being used, poll iff there are events which
+	 * can't be monitored asynchronously.
+	 */
+	if (ev->poll_msecs >= 0)
+		intv_msecs = ev->poll_msecs;
+	else if (disk->events & ~disk->async_events)
+		intv_msecs = disk_events_dfl_poll_msecs;
+
+	return msecs_to_jiffies(intv_msecs);
+}
+
+static void __disk_block_events(struct gendisk *disk, bool sync)
+{
+	struct disk_events *ev = disk->ev;
+	unsigned long flags;
+	bool cancel;
+
+	spin_lock_irqsave(&ev->lock, flags);
+	cancel = !ev->block++;
+	spin_unlock_irqrestore(&ev->lock, flags);
+
+	if (cancel) {
+		if (sync)
+			cancel_delayed_work_sync(&disk->ev->dwork);
+		else
+			cancel_delayed_work(&disk->ev->dwork);
+	}
+}
+
+static void __disk_unblock_events(struct gendisk *disk, bool check_now)
+{
+	struct disk_events *ev = disk->ev;
+	unsigned long intv;
+	unsigned long flags;
+
+	spin_lock_irqsave(&ev->lock, flags);
+
+	if (WARN_ON_ONCE(ev->block <= 0))
+		goto out_unlock;
+
+	if (--ev->block)
+		goto out_unlock;
+
+	/*
+	 * Not exactly a latency critical operation, set poll timer
+	 * slack to 25% and kick event check.
+	 */
+	intv = disk_events_poll_jiffies(disk);
+	set_timer_slack(&ev->dwork.timer, intv / 4);
+	if (check_now)
+		queue_delayed_work(system_nrt_wq, &ev->dwork, 0);
+	else if (intv)
+		queue_delayed_work(system_nrt_wq, &ev->dwork, intv);
+out_unlock:
+	spin_unlock_irqrestore(&ev->lock, flags);
+}
+
+/**
+ * disk_block_events - block and flush disk event checking
+ * @disk: disk to block events for
+ *
+ * On return from this function, it is guaranteed that event checking
+ * isn't in progress and won't happen until unblocked by
+ * disk_unblock_events().  Events blocking is counted and the actual
+ * unblocking happens after the matching number of unblocks are done.
+ *
+ * Note that this intentionally does not block event checking from
+ * disk_clear_events().
+ *
+ * CONTEXT:
+ * Might sleep.
+ */
+void disk_block_events(struct gendisk *disk)
+{
+	if (disk->ev)
+		__disk_block_events(disk, true);
+}
+
+/**
+ * disk_unblock_events - unblock disk event checking
+ * @disk: disk to unblock events for
+ *
+ * Undo disk_block_events().  When the block count reaches zero, it
+ * starts events polling if configured.
+ *
+ * CONTEXT:
+ * Don't care.  Safe to call from irq context.
+ */
+void disk_unblock_events(struct gendisk *disk)
+{
+	if (disk->ev)
+		__disk_unblock_events(disk, true);
+}
+
+/**
+ * disk_check_events - schedule immediate event checking
+ * @disk: disk to check events for
+ *
+ * Schedule immediate event checking on @disk if not blocked.
+ *
+ * CONTEXT:
+ * Don't care.  Safe to call from irq context.
+ */
+void disk_check_events(struct gendisk *disk)
+{
+	if (disk->ev) {
+		__disk_block_events(disk, false);
+		__disk_unblock_events(disk, true);
+	}
+}
+EXPORT_SYMBOL_GPL(disk_check_events);
+
+/**
+ * disk_clear_events - synchronously check, clear and return pending events
+ * @disk: disk to fetch and clear events from
+ * @mask: mask of events to be fetched and clearted
+ *
+ * Disk events are synchronously checked and pending events in @mask
+ * are cleared and returned.  This ignores the block count.
+ *
+ * CONTEXT:
+ * Might sleep.
+ */
+unsigned int disk_clear_events(struct gendisk *disk, unsigned int mask)
+{
+	const struct block_device_operations *bdops = disk->fops;
+	struct disk_events *ev = disk->ev;
+	unsigned int pending;
+
+	if (!ev) {
+		/* for drivers still using the old ->media_changed method */
+		if ((mask & DISK_EVENT_MEDIA_CHANGE) &&
+		    bdops->media_changed && bdops->media_changed(disk))
+			return DISK_EVENT_MEDIA_CHANGE;
+		return 0;
+	}
+
+	/* tell the workfn about the events being cleared */
+	spin_lock_irq(&ev->lock);
+	ev->clearing |= mask;
+	spin_unlock_irq(&ev->lock);
+
+	/* uncondtionally schedule event check and wait for it to finish */
+	__disk_block_events(disk, true);
+	queue_delayed_work(system_nrt_wq, &ev->dwork, 0);
+	flush_delayed_work(&ev->dwork);
+	__disk_unblock_events(disk, false);
+
+	/* then, fetch and clear pending events */
+	spin_lock_irq(&ev->lock);
+	WARN_ON_ONCE(ev->clearing & mask);	/* cleared by workfn */
+	pending = ev->pending & mask;
+	ev->pending &= ~mask;
+	spin_unlock_irq(&ev->lock);
+
+	return pending;
+}
+
+static void disk_events_workfn(struct work_struct *work)
+{
+	struct delayed_work *dwork = to_delayed_work(work);
+	struct disk_events *ev = container_of(dwork, struct disk_events, dwork);
+	struct gendisk *disk = ev->disk;
+	char *envp[ARRAY_SIZE(disk_uevents) + 1] = { };
+	unsigned int clearing = ev->clearing;
+	unsigned int events;
+	unsigned long intv;
+	int nr_events = 0, i;
+
+	/* check events */
+	events = disk->fops->check_events(disk, clearing);
+
+	/* accumulate pending events and schedule next poll if necessary */
+	spin_lock_irq(&ev->lock);
+
+	events &= ~ev->pending;
+	ev->pending |= events;
+	ev->clearing &= ~clearing;
+
+	intv = disk_events_poll_jiffies(disk);
+	if (!ev->block && intv)
+		queue_delayed_work(system_nrt_wq, &ev->dwork, intv);
+
+	spin_unlock_irq(&ev->lock);
+
+	/* tell userland about new events */
+	for (i = 0; i < ARRAY_SIZE(disk_uevents); i++)
+		if (events & (1 << i))
+			envp[nr_events++] = disk_uevents[i];
+
+	if (nr_events)
+		kobject_uevent_env(&disk_to_dev(disk)->kobj, KOBJ_CHANGE, envp);
+}
+
+/*
+ * A disk events enabled device has the following sysfs nodes under
+ * its /sys/block/X/ directory.
+ *
+ * events		: list of all supported events
+ * events_async		: list of events which can be detected w/o polling
+ * events_poll_msecs	: polling interval, 0: disable, -1: system default
+ */
+static ssize_t __disk_events_show(unsigned int events, char *buf)
+{
+	const char *delim = "";
+	ssize_t pos = 0;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(disk_events_strs); i++)
+		if (events & (1 << i)) {
+			pos += sprintf(buf + pos, "%s%s",
+				       delim, disk_events_strs[i]);
+			delim = " ";
+		}
+	if (pos)
+		pos += sprintf(buf + pos, "\n");
+	return pos;
+}
+
+static ssize_t disk_events_show(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct gendisk *disk = dev_to_disk(dev);
+
+	return __disk_events_show(disk->events, buf);
+}
+
+static ssize_t disk_events_async_show(struct device *dev,
+				      struct device_attribute *attr, char *buf)
+{
+	struct gendisk *disk = dev_to_disk(dev);
+
+	return __disk_events_show(disk->async_events, buf);
+}
+
+static ssize_t disk_events_poll_msecs_show(struct device *dev,
+					   struct device_attribute *attr,
+					   char *buf)
+{
+	struct gendisk *disk = dev_to_disk(dev);
+
+	return sprintf(buf, "%ld\n", disk->ev->poll_msecs);
+}
+
+static ssize_t disk_events_poll_msecs_store(struct device *dev,
+					    struct device_attribute *attr,
+					    const char *buf, size_t count)
+{
+	struct gendisk *disk = dev_to_disk(dev);
+	long intv;
+
+	if (!count || !sscanf(buf, "%ld", &intv))
+		return -EINVAL;
+
+	if (intv < 0 && intv != -1)
+		return -EINVAL;
+
+	__disk_block_events(disk, true);
+	disk->ev->poll_msecs = intv;
+	__disk_unblock_events(disk, true);
+
+	return count;
+}
+
+static const DEVICE_ATTR(events, S_IRUGO, disk_events_show, NULL);
+static const DEVICE_ATTR(events_async, S_IRUGO, disk_events_async_show, NULL);
+static const DEVICE_ATTR(events_poll_msecs, S_IRUGO|S_IWUSR,
+			 disk_events_poll_msecs_show,
+			 disk_events_poll_msecs_store);
+
+static const struct attribute *disk_events_attrs[] = {
+	&dev_attr_events.attr,
+	&dev_attr_events_async.attr,
+	&dev_attr_events_poll_msecs.attr,
+	NULL,
+};
+
+/*
+ * The default polling interval can be specified by the kernel
+ * parameter block.events_dfl_poll_msecs which defaults to 0
+ * (disable).  This can also be modified runtime by writing to
+ * /sys/module/block/events_dfl_poll_msecs.
+ */
+static int disk_events_set_dfl_poll_msecs(const char *val,
+					  const struct kernel_param *kp)
+{
+	struct disk_events *ev;
+	int ret;
+
+	ret = param_set_ulong(val, kp);
+	if (ret < 0)
+		return ret;
+
+	mutex_lock(&disk_events_mutex);
+
+	list_for_each_entry(ev, &disk_events, node)
+		disk_check_events(ev->disk);
+
+	mutex_unlock(&disk_events_mutex);
+
+	return 0;
+}
+
+static const struct kernel_param_ops disk_events_dfl_poll_msecs_param_ops = {
+	.set	= disk_events_set_dfl_poll_msecs,
+	.get	= param_get_ulong,
+};
+
+#undef MODULE_PARAM_PREFIX
+#define MODULE_PARAM_PREFIX	"block."
+
+module_param_cb(events_dfl_poll_msecs, &disk_events_dfl_poll_msecs_param_ops,
+		&disk_events_dfl_poll_msecs, 0644);
+
+/*
+ * disk_{add|del|release}_events - initialize and destroy disk_events.
+ */
+static void disk_add_events(struct gendisk *disk)
+{
+	struct disk_events *ev;
+
+	if (!disk->fops->check_events || !(disk->events | disk->async_events))
+		return;
+
+	ev = kzalloc(sizeof(*ev), GFP_KERNEL);
+	if (!ev) {
+		pr_warn("%s: failed to initialize events\n", disk->disk_name);
+		return;
+	}
+
+	if (sysfs_create_files(&disk_to_dev(disk)->kobj,
+			       disk_events_attrs) < 0) {
+		pr_warn("%s: failed to create sysfs files for events\n",
+			disk->disk_name);
+		kfree(ev);
+		return;
+	}
+
+	disk->ev = ev;
+
+	INIT_LIST_HEAD(&ev->node);
+	ev->disk = disk;
+	spin_lock_init(&ev->lock);
+	ev->block = 1;
+	ev->poll_msecs = -1;
+	INIT_DELAYED_WORK(&ev->dwork, disk_events_workfn);
+
+	mutex_lock(&disk_events_mutex);
+	list_add_tail(&ev->node, &disk_events);
+	mutex_unlock(&disk_events_mutex);
+
+	/*
+	 * Block count is initialized to 1 and the following initial
+	 * unblock kicks it into action.
+	 */
+	__disk_unblock_events(disk, true);
+}
+
+static void disk_del_events(struct gendisk *disk)
+{
+	if (!disk->ev)
+		return;
+
+	__disk_block_events(disk, true);
+
+	mutex_lock(&disk_events_mutex);
+	list_del_init(&disk->ev->node);
+	mutex_unlock(&disk_events_mutex);
+
+	sysfs_remove_files(&disk_to_dev(disk)->kobj, disk_events_attrs);
+}
+
+static void disk_release_events(struct gendisk *disk)
+{
+	/* the block count should be 1 from disk_del_events() */
+	WARN_ON_ONCE(disk->ev && disk->ev->block != 1);
+	kfree(disk->ev);
+}
diff -druNp linux-libre-2.6.37-gnu1/block/ioctl.c linux-libre-2.6.38-gnu1/block/ioctl.c
--- linux-libre-2.6.37-gnu1/block/ioctl.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/block/ioctl.c	2011-03-14 21:20:32.000000000 -0400
@@ -294,11 +294,14 @@ int blkdev_ioctl(struct block_device *bd
 			return -EINVAL;
 		if (get_user(n, (int __user *) arg))
 			return -EFAULT;
-		if (!(mode & FMODE_EXCL) && bd_claim(bdev, &bdev) < 0)
-			return -EBUSY;
+		if (!(mode & FMODE_EXCL)) {
+			bdgrab(bdev);
+			if (blkdev_get(bdev, mode | FMODE_EXCL, &bdev) < 0)
+				return -EBUSY;
+		}
 		ret = set_blocksize(bdev, n);
 		if (!(mode & FMODE_EXCL))
-			bd_release(bdev);
+			blkdev_put(bdev, mode | FMODE_EXCL);
 		return ret;
 	case BLKPG:
 		ret = blkpg_ioctl(bdev, (struct blkpg_ioctl_arg __user *) arg);
diff -druNp linux-libre-2.6.37-gnu1/block/Kconfig linux-libre-2.6.38-gnu1/block/Kconfig
--- linux-libre-2.6.37-gnu1/block/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/block/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -2,7 +2,7 @@
 # Block layer core configuration
 #
 menuconfig BLOCK
-       bool "Enable the block layer" if EMBEDDED
+       bool "Enable the block layer" if EXPERT
        default y
        help
 	 Provide block layer support for the kernel.
diff -druNp linux-libre-2.6.37-gnu1/CREDITS linux-libre-2.6.38-gnu1/CREDITS
--- linux-libre-2.6.37-gnu1/CREDITS	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/CREDITS	2011-03-14 21:20:32.000000000 -0400
@@ -2365,8 +2365,6 @@ E: acme@redhat.com
 W: http://oops.ghostprotocols.net:81/blog/
 P: 1024D/9224DF01 D5DF E3BB E3C8 BCBB F8AD  841A B6AB 4681 9224 DF01
 D: IPX, LLC, DCCP, cyc2x, wl3501_cs, net/ hacks
-S: R. Brasílio Itiberê, 4270/1010 - Água Verde
-S: 80240-060 - Curitiba - Paraná
 S: Brazil
 
 N: Karsten Merker
@@ -2813,8 +2811,8 @@ D: CDROM driver "sonycd535" (Sony CDU-53
 N: Stelian Pop
 E: stelian@popies.net
 P: 1024D/EDBB6147 7B36 0E07 04BC 11DC A7A0  D3F7 7185 9E7A EDBB 6147
-D: sonypi, meye drivers, mct_u232 usb serial hacks
-S: Paris, France
+D: random kernel hacks
+S: Paimpont, France
 
 N: Pete Popov
 E: pete_popov@yahoo.com
diff -druNp linux-libre-2.6.37-gnu1/crypto/af_alg.c linux-libre-2.6.38-gnu1/crypto/af_alg.c
--- linux-libre-2.6.37-gnu1/crypto/af_alg.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/crypto/af_alg.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,483 @@
+/*
+ * af_alg: User-space algorithm interface
+ *
+ * This file provides the user-space API for algorithms.
+ *
+ * Copyright (c) 2010 Herbert Xu <herbert@gondor.apana.org.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 <asm/atomic.h>
+#include <crypto/if_alg.h>
+#include <linux/crypto.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/net.h>
+#include <linux/rwsem.h>
+
+struct alg_type_list {
+	const struct af_alg_type *type;
+	struct list_head list;
+};
+
+static atomic_long_t alg_memory_allocated;
+
+static struct proto alg_proto = {
+	.name			= "ALG",
+	.owner			= THIS_MODULE,
+	.memory_allocated	= &alg_memory_allocated,
+	.obj_size		= sizeof(struct alg_sock),
+};
+
+static LIST_HEAD(alg_types);
+static DECLARE_RWSEM(alg_types_sem);
+
+static const struct af_alg_type *alg_get_type(const char *name)
+{
+	const struct af_alg_type *type = ERR_PTR(-ENOENT);
+	struct alg_type_list *node;
+
+	down_read(&alg_types_sem);
+	list_for_each_entry(node, &alg_types, list) {
+		if (strcmp(node->type->name, name))
+			continue;
+
+		if (try_module_get(node->type->owner))
+			type = node->type;
+		break;
+	}
+	up_read(&alg_types_sem);
+
+	return type;
+}
+
+int af_alg_register_type(const struct af_alg_type *type)
+{
+	struct alg_type_list *node;
+	int err = -EEXIST;
+
+	down_write(&alg_types_sem);
+	list_for_each_entry(node, &alg_types, list) {
+		if (!strcmp(node->type->name, type->name))
+			goto unlock;
+	}
+
+	node = kmalloc(sizeof(*node), GFP_KERNEL);
+	err = -ENOMEM;
+	if (!node)
+		goto unlock;
+
+	type->ops->owner = THIS_MODULE;
+	node->type = type;
+	list_add(&node->list, &alg_types);
+	err = 0;
+
+unlock:
+	up_write(&alg_types_sem);
+
+	return err;
+}
+EXPORT_SYMBOL_GPL(af_alg_register_type);
+
+int af_alg_unregister_type(const struct af_alg_type *type)
+{
+	struct alg_type_list *node;
+	int err = -ENOENT;
+
+	down_write(&alg_types_sem);
+	list_for_each_entry(node, &alg_types, list) {
+		if (strcmp(node->type->name, type->name))
+			continue;
+
+		list_del(&node->list);
+		kfree(node);
+		err = 0;
+		break;
+	}
+	up_write(&alg_types_sem);
+
+	return err;
+}
+EXPORT_SYMBOL_GPL(af_alg_unregister_type);
+
+static void alg_do_release(const struct af_alg_type *type, void *private)
+{
+	if (!type)
+		return;
+
+	type->release(private);
+	module_put(type->owner);
+}
+
+int af_alg_release(struct socket *sock)
+{
+	if (sock->sk)
+		sock_put(sock->sk);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(af_alg_release);
+
+static int alg_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
+{
+	struct sock *sk = sock->sk;
+	struct alg_sock *ask = alg_sk(sk);
+	struct sockaddr_alg *sa = (void *)uaddr;
+	const struct af_alg_type *type;
+	void *private;
+
+	if (sock->state == SS_CONNECTED)
+		return -EINVAL;
+
+	if (addr_len != sizeof(*sa))
+		return -EINVAL;
+
+	sa->salg_type[sizeof(sa->salg_type) - 1] = 0;
+	sa->salg_name[sizeof(sa->salg_name) - 1] = 0;
+
+	type = alg_get_type(sa->salg_type);
+	if (IS_ERR(type) && PTR_ERR(type) == -ENOENT) {
+		request_module("algif-%s", sa->salg_type);
+		type = alg_get_type(sa->salg_type);
+	}
+
+	if (IS_ERR(type))
+		return PTR_ERR(type);
+
+	private = type->bind(sa->salg_name, sa->salg_feat, sa->salg_mask);
+	if (IS_ERR(private)) {
+		module_put(type->owner);
+		return PTR_ERR(private);
+	}
+
+	lock_sock(sk);
+
+	swap(ask->type, type);
+	swap(ask->private, private);
+
+	release_sock(sk);
+
+	alg_do_release(type, private);
+
+	return 0;
+}
+
+static int alg_setkey(struct sock *sk, char __user *ukey,
+		      unsigned int keylen)
+{
+	struct alg_sock *ask = alg_sk(sk);
+	const struct af_alg_type *type = ask->type;
+	u8 *key;
+	int err;
+
+	key = sock_kmalloc(sk, keylen, GFP_KERNEL);
+	if (!key)
+		return -ENOMEM;
+
+	err = -EFAULT;
+	if (copy_from_user(key, ukey, keylen))
+		goto out;
+
+	err = type->setkey(ask->private, key, keylen);
+
+out:
+	sock_kfree_s(sk, key, keylen);
+
+	return err;
+}
+
+static int alg_setsockopt(struct socket *sock, int level, int optname,
+			  char __user *optval, unsigned int optlen)
+{
+	struct sock *sk = sock->sk;
+	struct alg_sock *ask = alg_sk(sk);
+	const struct af_alg_type *type;
+	int err = -ENOPROTOOPT;
+
+	lock_sock(sk);
+	type = ask->type;
+
+	if (level != SOL_ALG || !type)
+		goto unlock;
+
+	switch (optname) {
+	case ALG_SET_KEY:
+		if (sock->state == SS_CONNECTED)
+			goto unlock;
+		if (!type->setkey)
+			goto unlock;
+
+		err = alg_setkey(sk, optval, optlen);
+	}
+
+unlock:
+	release_sock(sk);
+
+	return err;
+}
+
+int af_alg_accept(struct sock *sk, struct socket *newsock)
+{
+	struct alg_sock *ask = alg_sk(sk);
+	const struct af_alg_type *type;
+	struct sock *sk2;
+	int err;
+
+	lock_sock(sk);
+	type = ask->type;
+
+	err = -EINVAL;
+	if (!type)
+		goto unlock;
+
+	sk2 = sk_alloc(sock_net(sk), PF_ALG, GFP_KERNEL, &alg_proto);
+	err = -ENOMEM;
+	if (!sk2)
+		goto unlock;
+
+	sock_init_data(newsock, sk2);
+	sock_graft(sk2, newsock);
+
+	err = type->accept(ask->private, sk2);
+	if (err) {
+		sk_free(sk2);
+		goto unlock;
+	}
+
+	sk2->sk_family = PF_ALG;
+
+	sock_hold(sk);
+	alg_sk(sk2)->parent = sk;
+	alg_sk(sk2)->type = type;
+
+	newsock->ops = type->ops;
+	newsock->state = SS_CONNECTED;
+
+	err = 0;
+
+unlock:
+	release_sock(sk);
+
+	return err;
+}
+EXPORT_SYMBOL_GPL(af_alg_accept);
+
+static int alg_accept(struct socket *sock, struct socket *newsock, int flags)
+{
+	return af_alg_accept(sock->sk, newsock);
+}
+
+static const struct proto_ops alg_proto_ops = {
+	.family		=	PF_ALG,
+	.owner		=	THIS_MODULE,
+
+	.connect	=	sock_no_connect,
+	.socketpair	=	sock_no_socketpair,
+	.getname	=	sock_no_getname,
+	.ioctl		=	sock_no_ioctl,
+	.listen		=	sock_no_listen,
+	.shutdown	=	sock_no_shutdown,
+	.getsockopt	=	sock_no_getsockopt,
+	.mmap		=	sock_no_mmap,
+	.sendpage	=	sock_no_sendpage,
+	.sendmsg	=	sock_no_sendmsg,
+	.recvmsg	=	sock_no_recvmsg,
+	.poll		=	sock_no_poll,
+
+	.bind		=	alg_bind,
+	.release	=	af_alg_release,
+	.setsockopt	=	alg_setsockopt,
+	.accept		=	alg_accept,
+};
+
+static void alg_sock_destruct(struct sock *sk)
+{
+	struct alg_sock *ask = alg_sk(sk);
+
+	alg_do_release(ask->type, ask->private);
+}
+
+static int alg_create(struct net *net, struct socket *sock, int protocol,
+		      int kern)
+{
+	struct sock *sk;
+	int err;
+
+	if (sock->type != SOCK_SEQPACKET)
+		return -ESOCKTNOSUPPORT;
+	if (protocol != 0)
+		return -EPROTONOSUPPORT;
+
+	err = -ENOMEM;
+	sk = sk_alloc(net, PF_ALG, GFP_KERNEL, &alg_proto);
+	if (!sk)
+		goto out;
+
+	sock->ops = &alg_proto_ops;
+	sock_init_data(sock, sk);
+
+	sk->sk_family = PF_ALG;
+	sk->sk_destruct = alg_sock_destruct;
+
+	return 0;
+out:
+	return err;
+}
+
+static const struct net_proto_family alg_family = {
+	.family	=	PF_ALG,
+	.create	=	alg_create,
+	.owner	=	THIS_MODULE,
+};
+
+int af_alg_make_sg(struct af_alg_sgl *sgl, void __user *addr, int len,
+		   int write)
+{
+	unsigned long from = (unsigned long)addr;
+	unsigned long npages;
+	unsigned off;
+	int err;
+	int i;
+
+	err = -EFAULT;
+	if (!access_ok(write ? VERIFY_READ : VERIFY_WRITE, addr, len))
+		goto out;
+
+	off = from & ~PAGE_MASK;
+	npages = (off + len + PAGE_SIZE - 1) >> PAGE_SHIFT;
+	if (npages > ALG_MAX_PAGES)
+		npages = ALG_MAX_PAGES;
+
+	err = get_user_pages_fast(from, npages, write, sgl->pages);
+	if (err < 0)
+		goto out;
+
+	npages = err;
+	err = -EINVAL;
+	if (WARN_ON(npages == 0))
+		goto out;
+
+	err = 0;
+
+	sg_init_table(sgl->sg, npages);
+
+	for (i = 0; i < npages; i++) {
+		int plen = min_t(int, len, PAGE_SIZE - off);
+
+		sg_set_page(sgl->sg + i, sgl->pages[i], plen, off);
+
+		off = 0;
+		len -= plen;
+		err += plen;
+	}
+
+out:
+	return err;
+}
+EXPORT_SYMBOL_GPL(af_alg_make_sg);
+
+void af_alg_free_sg(struct af_alg_sgl *sgl)
+{
+	int i;
+
+	i = 0;
+	do {
+		put_page(sgl->pages[i]);
+	} while (!sg_is_last(sgl->sg + (i++)));
+}
+EXPORT_SYMBOL_GPL(af_alg_free_sg);
+
+int af_alg_cmsg_send(struct msghdr *msg, struct af_alg_control *con)
+{
+	struct cmsghdr *cmsg;
+
+	for (cmsg = CMSG_FIRSTHDR(msg); cmsg; cmsg = CMSG_NXTHDR(msg, cmsg)) {
+		if (!CMSG_OK(msg, cmsg))
+			return -EINVAL;
+		if (cmsg->cmsg_level != SOL_ALG)
+			continue;
+
+		switch(cmsg->cmsg_type) {
+		case ALG_SET_IV:
+			if (cmsg->cmsg_len < CMSG_LEN(sizeof(*con->iv)))
+				return -EINVAL;
+			con->iv = (void *)CMSG_DATA(cmsg);
+			if (cmsg->cmsg_len < CMSG_LEN(con->iv->ivlen +
+						      sizeof(*con->iv)))
+				return -EINVAL;
+			break;
+
+		case ALG_SET_OP:
+			if (cmsg->cmsg_len < CMSG_LEN(sizeof(u32)))
+				return -EINVAL;
+			con->op = *(u32 *)CMSG_DATA(cmsg);
+			break;
+
+		default:
+			return -EINVAL;
+		}
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(af_alg_cmsg_send);
+
+int af_alg_wait_for_completion(int err, struct af_alg_completion *completion)
+{
+	switch (err) {
+	case -EINPROGRESS:
+	case -EBUSY:
+		wait_for_completion(&completion->completion);
+		INIT_COMPLETION(completion->completion);
+		err = completion->err;
+		break;
+	};
+
+	return err;
+}
+EXPORT_SYMBOL_GPL(af_alg_wait_for_completion);
+
+void af_alg_complete(struct crypto_async_request *req, int err)
+{
+	struct af_alg_completion *completion = req->data;
+
+	completion->err = err;
+	complete(&completion->completion);
+}
+EXPORT_SYMBOL_GPL(af_alg_complete);
+
+static int __init af_alg_init(void)
+{
+	int err = proto_register(&alg_proto, 0);
+
+	if (err)
+		goto out;
+
+	err = sock_register(&alg_family);
+	if (err != 0)
+		goto out_unregister_proto;
+
+out:
+	return err;
+
+out_unregister_proto:
+	proto_unregister(&alg_proto);
+	goto out;
+}
+
+static void __exit af_alg_exit(void)
+{
+	sock_unregister(PF_ALG);
+	proto_unregister(&alg_proto);
+}
+
+module_init(af_alg_init);
+module_exit(af_alg_exit);
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_NETPROTO(AF_ALG);
diff -druNp linux-libre-2.6.37-gnu1/crypto/algif_hash.c linux-libre-2.6.38-gnu1/crypto/algif_hash.c
--- linux-libre-2.6.37-gnu1/crypto/algif_hash.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/crypto/algif_hash.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,319 @@
+/*
+ * algif_hash: User-space interface for hash algorithms
+ *
+ * This file provides the user-space API for hash algorithms.
+ *
+ * Copyright (c) 2010 Herbert Xu <herbert@gondor.apana.org.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 <crypto/hash.h>
+#include <crypto/if_alg.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/net.h>
+#include <net/sock.h>
+
+struct hash_ctx {
+	struct af_alg_sgl sgl;
+
+	u8 *result;
+
+	struct af_alg_completion completion;
+
+	unsigned int len;
+	bool more;
+
+	struct ahash_request req;
+};
+
+static int hash_sendmsg(struct kiocb *unused, struct socket *sock,
+			struct msghdr *msg, size_t ignored)
+{
+	int limit = ALG_MAX_PAGES * PAGE_SIZE;
+	struct sock *sk = sock->sk;
+	struct alg_sock *ask = alg_sk(sk);
+	struct hash_ctx *ctx = ask->private;
+	unsigned long iovlen;
+	struct iovec *iov;
+	long copied = 0;
+	int err;
+
+	if (limit > sk->sk_sndbuf)
+		limit = sk->sk_sndbuf;
+
+	lock_sock(sk);
+	if (!ctx->more) {
+		err = crypto_ahash_init(&ctx->req);
+		if (err)
+			goto unlock;
+	}
+
+	ctx->more = 0;
+
+	for (iov = msg->msg_iov, iovlen = msg->msg_iovlen; iovlen > 0;
+	     iovlen--, iov++) {
+		unsigned long seglen = iov->iov_len;
+		char __user *from = iov->iov_base;
+
+		while (seglen) {
+			int len = min_t(unsigned long, seglen, limit);
+			int newlen;
+
+			newlen = af_alg_make_sg(&ctx->sgl, from, len, 0);
+			if (newlen < 0)
+				goto unlock;
+
+			ahash_request_set_crypt(&ctx->req, ctx->sgl.sg, NULL,
+						newlen);
+
+			err = af_alg_wait_for_completion(
+				crypto_ahash_update(&ctx->req),
+				&ctx->completion);
+
+			af_alg_free_sg(&ctx->sgl);
+
+			if (err)
+				goto unlock;
+
+			seglen -= newlen;
+			from += newlen;
+			copied += newlen;
+		}
+	}
+
+	err = 0;
+
+	ctx->more = msg->msg_flags & MSG_MORE;
+	if (!ctx->more) {
+		ahash_request_set_crypt(&ctx->req, NULL, ctx->result, 0);
+		err = af_alg_wait_for_completion(crypto_ahash_final(&ctx->req),
+						 &ctx->completion);
+	}
+
+unlock:
+	release_sock(sk);
+
+	return err ?: copied;
+}
+
+static ssize_t hash_sendpage(struct socket *sock, struct page *page,
+			     int offset, size_t size, int flags)
+{
+	struct sock *sk = sock->sk;
+	struct alg_sock *ask = alg_sk(sk);
+	struct hash_ctx *ctx = ask->private;
+	int err;
+
+	lock_sock(sk);
+	sg_init_table(ctx->sgl.sg, 1);
+	sg_set_page(ctx->sgl.sg, page, size, offset);
+
+	ahash_request_set_crypt(&ctx->req, ctx->sgl.sg, ctx->result, size);
+
+	if (!(flags & MSG_MORE)) {
+		if (ctx->more)
+			err = crypto_ahash_finup(&ctx->req);
+		else
+			err = crypto_ahash_digest(&ctx->req);
+	} else {
+		if (!ctx->more) {
+			err = crypto_ahash_init(&ctx->req);
+			if (err)
+				goto unlock;
+		}
+
+		err = crypto_ahash_update(&ctx->req);
+	}
+
+	err = af_alg_wait_for_completion(err, &ctx->completion);
+	if (err)
+		goto unlock;
+
+	ctx->more = flags & MSG_MORE;
+
+unlock:
+	release_sock(sk);
+
+	return err ?: size;
+}
+
+static int hash_recvmsg(struct kiocb *unused, struct socket *sock,
+			struct msghdr *msg, size_t len, int flags)
+{
+	struct sock *sk = sock->sk;
+	struct alg_sock *ask = alg_sk(sk);
+	struct hash_ctx *ctx = ask->private;
+	unsigned ds = crypto_ahash_digestsize(crypto_ahash_reqtfm(&ctx->req));
+	int err;
+
+	if (len > ds)
+		len = ds;
+	else if (len < ds)
+		msg->msg_flags |= MSG_TRUNC;
+
+	lock_sock(sk);
+	if (ctx->more) {
+		ctx->more = 0;
+		ahash_request_set_crypt(&ctx->req, NULL, ctx->result, 0);
+		err = af_alg_wait_for_completion(crypto_ahash_final(&ctx->req),
+						 &ctx->completion);
+		if (err)
+			goto unlock;
+	}
+
+	err = memcpy_toiovec(msg->msg_iov, ctx->result, len);
+
+unlock:
+	release_sock(sk);
+
+	return err ?: len;
+}
+
+static int hash_accept(struct socket *sock, struct socket *newsock, int flags)
+{
+	struct sock *sk = sock->sk;
+	struct alg_sock *ask = alg_sk(sk);
+	struct hash_ctx *ctx = ask->private;
+	struct ahash_request *req = &ctx->req;
+	char state[crypto_ahash_statesize(crypto_ahash_reqtfm(req))];
+	struct sock *sk2;
+	struct alg_sock *ask2;
+	struct hash_ctx *ctx2;
+	int err;
+
+	err = crypto_ahash_export(req, state);
+	if (err)
+		return err;
+
+	err = af_alg_accept(ask->parent, newsock);
+	if (err)
+		return err;
+
+	sk2 = newsock->sk;
+	ask2 = alg_sk(sk2);
+	ctx2 = ask2->private;
+	ctx2->more = 1;
+
+	err = crypto_ahash_import(&ctx2->req, state);
+	if (err) {
+		sock_orphan(sk2);
+		sock_put(sk2);
+	}
+
+	return err;
+}
+
+static struct proto_ops algif_hash_ops = {
+	.family		=	PF_ALG,
+
+	.connect	=	sock_no_connect,
+	.socketpair	=	sock_no_socketpair,
+	.getname	=	sock_no_getname,
+	.ioctl		=	sock_no_ioctl,
+	.listen		=	sock_no_listen,
+	.shutdown	=	sock_no_shutdown,
+	.getsockopt	=	sock_no_getsockopt,
+	.mmap		=	sock_no_mmap,
+	.bind		=	sock_no_bind,
+	.setsockopt	=	sock_no_setsockopt,
+	.poll		=	sock_no_poll,
+
+	.release	=	af_alg_release,
+	.sendmsg	=	hash_sendmsg,
+	.sendpage	=	hash_sendpage,
+	.recvmsg	=	hash_recvmsg,
+	.accept		=	hash_accept,
+};
+
+static void *hash_bind(const char *name, u32 type, u32 mask)
+{
+	return crypto_alloc_ahash(name, type, mask);
+}
+
+static void hash_release(void *private)
+{
+	crypto_free_ahash(private);
+}
+
+static int hash_setkey(void *private, const u8 *key, unsigned int keylen)
+{
+	return crypto_ahash_setkey(private, key, keylen);
+}
+
+static void hash_sock_destruct(struct sock *sk)
+{
+	struct alg_sock *ask = alg_sk(sk);
+	struct hash_ctx *ctx = ask->private;
+
+	sock_kfree_s(sk, ctx->result,
+		     crypto_ahash_digestsize(crypto_ahash_reqtfm(&ctx->req)));
+	sock_kfree_s(sk, ctx, ctx->len);
+	af_alg_release_parent(sk);
+}
+
+static int hash_accept_parent(void *private, struct sock *sk)
+{
+	struct hash_ctx *ctx;
+	struct alg_sock *ask = alg_sk(sk);
+	unsigned len = sizeof(*ctx) + crypto_ahash_reqsize(private);
+	unsigned ds = crypto_ahash_digestsize(private);
+
+	ctx = sock_kmalloc(sk, len, GFP_KERNEL);
+	if (!ctx)
+		return -ENOMEM;
+
+	ctx->result = sock_kmalloc(sk, ds, GFP_KERNEL);
+	if (!ctx->result) {
+		sock_kfree_s(sk, ctx, len);
+		return -ENOMEM;
+	}
+
+	memset(ctx->result, 0, ds);
+
+	ctx->len = len;
+	ctx->more = 0;
+	af_alg_init_completion(&ctx->completion);
+
+	ask->private = ctx;
+
+	ahash_request_set_tfm(&ctx->req, private);
+	ahash_request_set_callback(&ctx->req, CRYPTO_TFM_REQ_MAY_BACKLOG,
+				   af_alg_complete, &ctx->completion);
+
+	sk->sk_destruct = hash_sock_destruct;
+
+	return 0;
+}
+
+static const struct af_alg_type algif_type_hash = {
+	.bind		=	hash_bind,
+	.release	=	hash_release,
+	.setkey		=	hash_setkey,
+	.accept		=	hash_accept_parent,
+	.ops		=	&algif_hash_ops,
+	.name		=	"hash",
+	.owner		=	THIS_MODULE
+};
+
+static int __init algif_hash_init(void)
+{
+	return af_alg_register_type(&algif_type_hash);
+}
+
+static void __exit algif_hash_exit(void)
+{
+	int err = af_alg_unregister_type(&algif_type_hash);
+	BUG_ON(err);
+}
+
+module_init(algif_hash_init);
+module_exit(algif_hash_exit);
+MODULE_LICENSE("GPL");
diff -druNp linux-libre-2.6.37-gnu1/crypto/algif_skcipher.c linux-libre-2.6.38-gnu1/crypto/algif_skcipher.c
--- linux-libre-2.6.37-gnu1/crypto/algif_skcipher.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/crypto/algif_skcipher.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,632 @@
+/*
+ * algif_skcipher: User-space interface for skcipher algorithms
+ *
+ * This file provides the user-space API for symmetric key ciphers.
+ *
+ * Copyright (c) 2010 Herbert Xu <herbert@gondor.apana.org.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 <crypto/scatterwalk.h>
+#include <crypto/skcipher.h>
+#include <crypto/if_alg.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/net.h>
+#include <net/sock.h>
+
+struct skcipher_sg_list {
+	struct list_head list;
+
+	int cur;
+
+	struct scatterlist sg[0];
+};
+
+struct skcipher_ctx {
+	struct list_head tsgl;
+	struct af_alg_sgl rsgl;
+
+	void *iv;
+
+	struct af_alg_completion completion;
+
+	unsigned used;
+
+	unsigned int len;
+	bool more;
+	bool merge;
+	bool enc;
+
+	struct ablkcipher_request req;
+};
+
+#define MAX_SGL_ENTS ((PAGE_SIZE - sizeof(struct skcipher_sg_list)) / \
+		      sizeof(struct scatterlist) - 1)
+
+static inline int skcipher_sndbuf(struct sock *sk)
+{
+	struct alg_sock *ask = alg_sk(sk);
+	struct skcipher_ctx *ctx = ask->private;
+
+	return max_t(int, max_t(int, sk->sk_sndbuf & PAGE_MASK, PAGE_SIZE) -
+			  ctx->used, 0);
+}
+
+static inline bool skcipher_writable(struct sock *sk)
+{
+	return PAGE_SIZE <= skcipher_sndbuf(sk);
+}
+
+static int skcipher_alloc_sgl(struct sock *sk)
+{
+	struct alg_sock *ask = alg_sk(sk);
+	struct skcipher_ctx *ctx = ask->private;
+	struct skcipher_sg_list *sgl;
+	struct scatterlist *sg = NULL;
+
+	sgl = list_entry(ctx->tsgl.prev, struct skcipher_sg_list, list);
+	if (!list_empty(&ctx->tsgl))
+		sg = sgl->sg;
+
+	if (!sg || sgl->cur >= MAX_SGL_ENTS) {
+		sgl = sock_kmalloc(sk, sizeof(*sgl) +
+				       sizeof(sgl->sg[0]) * (MAX_SGL_ENTS + 1),
+				   GFP_KERNEL);
+		if (!sgl)
+			return -ENOMEM;
+
+		sg_init_table(sgl->sg, MAX_SGL_ENTS + 1);
+		sgl->cur = 0;
+
+		if (sg)
+			scatterwalk_sg_chain(sg, MAX_SGL_ENTS + 1, sgl->sg);
+
+		list_add_tail(&sgl->list, &ctx->tsgl);
+	}
+
+	return 0;
+}
+
+static void skcipher_pull_sgl(struct sock *sk, int used)
+{
+	struct alg_sock *ask = alg_sk(sk);
+	struct skcipher_ctx *ctx = ask->private;
+	struct skcipher_sg_list *sgl;
+	struct scatterlist *sg;
+	int i;
+
+	while (!list_empty(&ctx->tsgl)) {
+		sgl = list_first_entry(&ctx->tsgl, struct skcipher_sg_list,
+				       list);
+		sg = sgl->sg;
+
+		for (i = 0; i < sgl->cur; i++) {
+			int plen = min_t(int, used, sg[i].length);
+
+			if (!sg_page(sg + i))
+				continue;
+
+			sg[i].length -= plen;
+			sg[i].offset += plen;
+
+			used -= plen;
+			ctx->used -= plen;
+
+			if (sg[i].length)
+				return;
+
+			put_page(sg_page(sg + i));
+			sg_assign_page(sg + i, NULL);
+		}
+
+		list_del(&sgl->list);
+		sock_kfree_s(sk, sgl,
+			     sizeof(*sgl) + sizeof(sgl->sg[0]) *
+					    (MAX_SGL_ENTS + 1));
+	}
+
+	if (!ctx->used)
+		ctx->merge = 0;
+}
+
+static void skcipher_free_sgl(struct sock *sk)
+{
+	struct alg_sock *ask = alg_sk(sk);
+	struct skcipher_ctx *ctx = ask->private;
+
+	skcipher_pull_sgl(sk, ctx->used);
+}
+
+static int skcipher_wait_for_wmem(struct sock *sk, unsigned flags)
+{
+	long timeout;
+	DEFINE_WAIT(wait);
+	int err = -ERESTARTSYS;
+
+	if (flags & MSG_DONTWAIT)
+		return -EAGAIN;
+
+	set_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags);
+
+	for (;;) {
+		if (signal_pending(current))
+			break;
+		prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
+		timeout = MAX_SCHEDULE_TIMEOUT;
+		if (sk_wait_event(sk, &timeout, skcipher_writable(sk))) {
+			err = 0;
+			break;
+		}
+	}
+	finish_wait(sk_sleep(sk), &wait);
+
+	return err;
+}
+
+static void skcipher_wmem_wakeup(struct sock *sk)
+{
+	struct socket_wq *wq;
+
+	if (!skcipher_writable(sk))
+		return;
+
+	rcu_read_lock();
+	wq = rcu_dereference(sk->sk_wq);
+	if (wq_has_sleeper(wq))
+		wake_up_interruptible_sync_poll(&wq->wait, POLLIN |
+							   POLLRDNORM |
+							   POLLRDBAND);
+	sk_wake_async(sk, SOCK_WAKE_WAITD, POLL_IN);
+	rcu_read_unlock();
+}
+
+static int skcipher_wait_for_data(struct sock *sk, unsigned flags)
+{
+	struct alg_sock *ask = alg_sk(sk);
+	struct skcipher_ctx *ctx = ask->private;
+	long timeout;
+	DEFINE_WAIT(wait);
+	int err = -ERESTARTSYS;
+
+	if (flags & MSG_DONTWAIT) {
+		return -EAGAIN;
+	}
+
+	set_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags);
+
+	for (;;) {
+		if (signal_pending(current))
+			break;
+		prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
+		timeout = MAX_SCHEDULE_TIMEOUT;
+		if (sk_wait_event(sk, &timeout, ctx->used)) {
+			err = 0;
+			break;
+		}
+	}
+	finish_wait(sk_sleep(sk), &wait);
+
+	clear_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags);
+
+	return err;
+}
+
+static void skcipher_data_wakeup(struct sock *sk)
+{
+	struct alg_sock *ask = alg_sk(sk);
+	struct skcipher_ctx *ctx = ask->private;
+	struct socket_wq *wq;
+
+	if (!ctx->used)
+		return;
+
+	rcu_read_lock();
+	wq = rcu_dereference(sk->sk_wq);
+	if (wq_has_sleeper(wq))
+		wake_up_interruptible_sync_poll(&wq->wait, POLLOUT |
+							   POLLRDNORM |
+							   POLLRDBAND);
+	sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT);
+	rcu_read_unlock();
+}
+
+static int skcipher_sendmsg(struct kiocb *unused, struct socket *sock,
+			    struct msghdr *msg, size_t size)
+{
+	struct sock *sk = sock->sk;
+	struct alg_sock *ask = alg_sk(sk);
+	struct skcipher_ctx *ctx = ask->private;
+	struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(&ctx->req);
+	unsigned ivsize = crypto_ablkcipher_ivsize(tfm);
+	struct skcipher_sg_list *sgl;
+	struct af_alg_control con = {};
+	long copied = 0;
+	bool enc = 0;
+	int err;
+	int i;
+
+	if (msg->msg_controllen) {
+		err = af_alg_cmsg_send(msg, &con);
+		if (err)
+			return err;
+
+		switch (con.op) {
+		case ALG_OP_ENCRYPT:
+			enc = 1;
+			break;
+		case ALG_OP_DECRYPT:
+			enc = 0;
+			break;
+		default:
+			return -EINVAL;
+		}
+
+		if (con.iv && con.iv->ivlen != ivsize)
+			return -EINVAL;
+	}
+
+	err = -EINVAL;
+
+	lock_sock(sk);
+	if (!ctx->more && ctx->used)
+		goto unlock;
+
+	if (!ctx->used) {
+		ctx->enc = enc;
+		if (con.iv)
+			memcpy(ctx->iv, con.iv->iv, ivsize);
+	}
+
+	while (size) {
+		struct scatterlist *sg;
+		unsigned long len = size;
+		int plen;
+
+		if (ctx->merge) {
+			sgl = list_entry(ctx->tsgl.prev,
+					 struct skcipher_sg_list, list);
+			sg = sgl->sg + sgl->cur - 1;
+			len = min_t(unsigned long, len,
+				    PAGE_SIZE - sg->offset - sg->length);
+
+			err = memcpy_fromiovec(page_address(sg_page(sg)) +
+					       sg->offset + sg->length,
+					       msg->msg_iov, len);
+			if (err)
+				goto unlock;
+
+			sg->length += len;
+			ctx->merge = (sg->offset + sg->length) &
+				     (PAGE_SIZE - 1);
+
+			ctx->used += len;
+			copied += len;
+			size -= len;
+			continue;
+		}
+
+		if (!skcipher_writable(sk)) {
+			err = skcipher_wait_for_wmem(sk, msg->msg_flags);
+			if (err)
+				goto unlock;
+		}
+
+		len = min_t(unsigned long, len, skcipher_sndbuf(sk));
+
+		err = skcipher_alloc_sgl(sk);
+		if (err)
+			goto unlock;
+
+		sgl = list_entry(ctx->tsgl.prev, struct skcipher_sg_list, list);
+		sg = sgl->sg;
+		do {
+			i = sgl->cur;
+			plen = min_t(int, len, PAGE_SIZE);
+
+			sg_assign_page(sg + i, alloc_page(GFP_KERNEL));
+			err = -ENOMEM;
+			if (!sg_page(sg + i))
+				goto unlock;
+
+			err = memcpy_fromiovec(page_address(sg_page(sg + i)),
+					       msg->msg_iov, plen);
+			if (err) {
+				__free_page(sg_page(sg + i));
+				sg_assign_page(sg + i, NULL);
+				goto unlock;
+			}
+
+			sg[i].length = plen;
+			len -= plen;
+			ctx->used += plen;
+			copied += plen;
+			size -= plen;
+			sgl->cur++;
+		} while (len && sgl->cur < MAX_SGL_ENTS);
+
+		ctx->merge = plen & (PAGE_SIZE - 1);
+	}
+
+	err = 0;
+
+	ctx->more = msg->msg_flags & MSG_MORE;
+	if (!ctx->more && !list_empty(&ctx->tsgl))
+		sgl = list_entry(ctx->tsgl.prev, struct skcipher_sg_list, list);
+
+unlock:
+	skcipher_data_wakeup(sk);
+	release_sock(sk);
+
+	return copied ?: err;
+}
+
+static ssize_t skcipher_sendpage(struct socket *sock, struct page *page,
+				 int offset, size_t size, int flags)
+{
+	struct sock *sk = sock->sk;
+	struct alg_sock *ask = alg_sk(sk);
+	struct skcipher_ctx *ctx = ask->private;
+	struct skcipher_sg_list *sgl;
+	int err = -EINVAL;
+
+	lock_sock(sk);
+	if (!ctx->more && ctx->used)
+		goto unlock;
+
+	if (!size)
+		goto done;
+
+	if (!skcipher_writable(sk)) {
+		err = skcipher_wait_for_wmem(sk, flags);
+		if (err)
+			goto unlock;
+	}
+
+	err = skcipher_alloc_sgl(sk);
+	if (err)
+		goto unlock;
+
+	ctx->merge = 0;
+	sgl = list_entry(ctx->tsgl.prev, struct skcipher_sg_list, list);
+
+	get_page(page);
+	sg_set_page(sgl->sg + sgl->cur, page, size, offset);
+	sgl->cur++;
+	ctx->used += size;
+
+done:
+	ctx->more = flags & MSG_MORE;
+	if (!ctx->more && !list_empty(&ctx->tsgl))
+		sgl = list_entry(ctx->tsgl.prev, struct skcipher_sg_list, list);
+
+unlock:
+	skcipher_data_wakeup(sk);
+	release_sock(sk);
+
+	return err ?: size;
+}
+
+static int skcipher_recvmsg(struct kiocb *unused, struct socket *sock,
+			    struct msghdr *msg, size_t ignored, int flags)
+{
+	struct sock *sk = sock->sk;
+	struct alg_sock *ask = alg_sk(sk);
+	struct skcipher_ctx *ctx = ask->private;
+	unsigned bs = crypto_ablkcipher_blocksize(crypto_ablkcipher_reqtfm(
+		&ctx->req));
+	struct skcipher_sg_list *sgl;
+	struct scatterlist *sg;
+	unsigned long iovlen;
+	struct iovec *iov;
+	int err = -EAGAIN;
+	int used;
+	long copied = 0;
+
+	lock_sock(sk);
+	for (iov = msg->msg_iov, iovlen = msg->msg_iovlen; iovlen > 0;
+	     iovlen--, iov++) {
+		unsigned long seglen = iov->iov_len;
+		char __user *from = iov->iov_base;
+
+		while (seglen) {
+			sgl = list_first_entry(&ctx->tsgl,
+					       struct skcipher_sg_list, list);
+			sg = sgl->sg;
+
+			while (!sg->length)
+				sg++;
+
+			used = ctx->used;
+			if (!used) {
+				err = skcipher_wait_for_data(sk, flags);
+				if (err)
+					goto unlock;
+			}
+
+			used = min_t(unsigned long, used, seglen);
+
+			used = af_alg_make_sg(&ctx->rsgl, from, used, 1);
+			err = used;
+			if (err < 0)
+				goto unlock;
+
+			if (ctx->more || used < ctx->used)
+				used -= used % bs;
+
+			err = -EINVAL;
+			if (!used)
+				goto free;
+
+			ablkcipher_request_set_crypt(&ctx->req, sg,
+						     ctx->rsgl.sg, used,
+						     ctx->iv);
+
+			err = af_alg_wait_for_completion(
+				ctx->enc ?
+					crypto_ablkcipher_encrypt(&ctx->req) :
+					crypto_ablkcipher_decrypt(&ctx->req),
+				&ctx->completion);
+
+free:
+			af_alg_free_sg(&ctx->rsgl);
+
+			if (err)
+				goto unlock;
+
+			copied += used;
+			from += used;
+			seglen -= used;
+			skcipher_pull_sgl(sk, used);
+		}
+	}
+
+	err = 0;
+
+unlock:
+	skcipher_wmem_wakeup(sk);
+	release_sock(sk);
+
+	return copied ?: err;
+}
+
+
+static unsigned int skcipher_poll(struct file *file, struct socket *sock,
+				  poll_table *wait)
+{
+	struct sock *sk = sock->sk;
+	struct alg_sock *ask = alg_sk(sk);
+	struct skcipher_ctx *ctx = ask->private;
+	unsigned int mask;
+
+	sock_poll_wait(file, sk_sleep(sk), wait);
+	mask = 0;
+
+	if (ctx->used)
+		mask |= POLLIN | POLLRDNORM;
+
+	if (skcipher_writable(sk))
+		mask |= POLLOUT | POLLWRNORM | POLLWRBAND;
+
+	return mask;
+}
+
+static struct proto_ops algif_skcipher_ops = {
+	.family		=	PF_ALG,
+
+	.connect	=	sock_no_connect,
+	.socketpair	=	sock_no_socketpair,
+	.getname	=	sock_no_getname,
+	.ioctl		=	sock_no_ioctl,
+	.listen		=	sock_no_listen,
+	.shutdown	=	sock_no_shutdown,
+	.getsockopt	=	sock_no_getsockopt,
+	.mmap		=	sock_no_mmap,
+	.bind		=	sock_no_bind,
+	.accept		=	sock_no_accept,
+	.setsockopt	=	sock_no_setsockopt,
+
+	.release	=	af_alg_release,
+	.sendmsg	=	skcipher_sendmsg,
+	.sendpage	=	skcipher_sendpage,
+	.recvmsg	=	skcipher_recvmsg,
+	.poll		=	skcipher_poll,
+};
+
+static void *skcipher_bind(const char *name, u32 type, u32 mask)
+{
+	return crypto_alloc_ablkcipher(name, type, mask);
+}
+
+static void skcipher_release(void *private)
+{
+	crypto_free_ablkcipher(private);
+}
+
+static int skcipher_setkey(void *private, const u8 *key, unsigned int keylen)
+{
+	return crypto_ablkcipher_setkey(private, key, keylen);
+}
+
+static void skcipher_sock_destruct(struct sock *sk)
+{
+	struct alg_sock *ask = alg_sk(sk);
+	struct skcipher_ctx *ctx = ask->private;
+	struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(&ctx->req);
+
+	skcipher_free_sgl(sk);
+	sock_kfree_s(sk, ctx->iv, crypto_ablkcipher_ivsize(tfm));
+	sock_kfree_s(sk, ctx, ctx->len);
+	af_alg_release_parent(sk);
+}
+
+static int skcipher_accept_parent(void *private, struct sock *sk)
+{
+	struct skcipher_ctx *ctx;
+	struct alg_sock *ask = alg_sk(sk);
+	unsigned int len = sizeof(*ctx) + crypto_ablkcipher_reqsize(private);
+
+	ctx = sock_kmalloc(sk, len, GFP_KERNEL);
+	if (!ctx)
+		return -ENOMEM;
+
+	ctx->iv = sock_kmalloc(sk, crypto_ablkcipher_ivsize(private),
+			       GFP_KERNEL);
+	if (!ctx->iv) {
+		sock_kfree_s(sk, ctx, len);
+		return -ENOMEM;
+	}
+
+	memset(ctx->iv, 0, crypto_ablkcipher_ivsize(private));
+
+	INIT_LIST_HEAD(&ctx->tsgl);
+	ctx->len = len;
+	ctx->used = 0;
+	ctx->more = 0;
+	ctx->merge = 0;
+	ctx->enc = 0;
+	af_alg_init_completion(&ctx->completion);
+
+	ask->private = ctx;
+
+	ablkcipher_request_set_tfm(&ctx->req, private);
+	ablkcipher_request_set_callback(&ctx->req, CRYPTO_TFM_REQ_MAY_BACKLOG,
+					af_alg_complete, &ctx->completion);
+
+	sk->sk_destruct = skcipher_sock_destruct;
+
+	return 0;
+}
+
+static const struct af_alg_type algif_type_skcipher = {
+	.bind		=	skcipher_bind,
+	.release	=	skcipher_release,
+	.setkey		=	skcipher_setkey,
+	.accept		=	skcipher_accept_parent,
+	.ops		=	&algif_skcipher_ops,
+	.name		=	"skcipher",
+	.owner		=	THIS_MODULE
+};
+
+static int __init algif_skcipher_init(void)
+{
+	return af_alg_register_type(&algif_type_skcipher);
+}
+
+static void __exit algif_skcipher_exit(void)
+{
+	int err = af_alg_unregister_type(&algif_type_skcipher);
+	BUG_ON(err);
+}
+
+module_init(algif_skcipher_init);
+module_exit(algif_skcipher_exit);
+MODULE_LICENSE("GPL");
diff -druNp linux-libre-2.6.37-gnu1/crypto/authenc.c linux-libre-2.6.38-gnu1/crypto/authenc.c
--- linux-libre-2.6.37-gnu1/crypto/authenc.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/crypto/authenc.c	2011-03-14 21:20:32.000000000 -0400
@@ -107,20 +107,6 @@ badkey:
 	goto out;
 }
 
-static void authenc_chain(struct scatterlist *head, struct scatterlist *sg,
-			  int chain)
-{
-	if (chain) {
-		head->length += sg->length;
-		sg = scatterwalk_sg_next(sg);
-	}
-
-	if (sg)
-		scatterwalk_sg_chain(head, 2, sg);
-	else
-		sg_mark_end(head);
-}
-
 static void authenc_geniv_ahash_update_done(struct crypto_async_request *areq,
 					    int err)
 {
@@ -345,7 +331,7 @@ static int crypto_authenc_genicv(struct
 	if (ivsize) {
 		sg_init_table(cipher, 2);
 		sg_set_buf(cipher, iv, ivsize);
-		authenc_chain(cipher, dst, vdst == iv + ivsize);
+		scatterwalk_crypto_chain(cipher, dst, vdst == iv + ivsize, 2);
 		dst = cipher;
 		cryptlen += ivsize;
 	}
@@ -354,7 +340,7 @@ static int crypto_authenc_genicv(struct
 		authenc_ahash_fn = crypto_authenc_ahash;
 		sg_init_table(asg, 2);
 		sg_set_page(asg, sg_page(assoc), assoc->length, assoc->offset);
-		authenc_chain(asg, dst, 0);
+		scatterwalk_crypto_chain(asg, dst, 0, 2);
 		dst = asg;
 		cryptlen += req->assoclen;
 	}
@@ -499,7 +485,7 @@ static int crypto_authenc_iverify(struct
 	if (ivsize) {
 		sg_init_table(cipher, 2);
 		sg_set_buf(cipher, iv, ivsize);
-		authenc_chain(cipher, src, vsrc == iv + ivsize);
+		scatterwalk_crypto_chain(cipher, src, vsrc == iv + ivsize, 2);
 		src = cipher;
 		cryptlen += ivsize;
 	}
@@ -508,7 +494,7 @@ static int crypto_authenc_iverify(struct
 		authenc_ahash_fn = crypto_authenc_ahash;
 		sg_init_table(asg, 2);
 		sg_set_page(asg, sg_page(assoc), assoc->length, assoc->offset);
-		authenc_chain(asg, src, 0);
+		scatterwalk_crypto_chain(asg, src, 0, 2);
 		src = asg;
 		cryptlen += req->assoclen;
 	}
diff -druNp linux-libre-2.6.37-gnu1/crypto/cast5.c linux-libre-2.6.38-gnu1/crypto/cast5.c
--- linux-libre-2.6.37-gnu1/crypto/cast5.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/crypto/cast5.c	2011-03-14 21:20:32.000000000 -0400
@@ -604,36 +604,23 @@ static void cast5_encrypt(struct crypto_
 	 * Rounds 3, 6, 9, 12, and 15 use f function Type 3.
 	 */
 
+	t = l; l = r; r = t ^ F1(r, Km[0], Kr[0]);
+	t = l; l = r; r = t ^ F2(r, Km[1], Kr[1]);
+	t = l; l = r; r = t ^ F3(r, Km[2], Kr[2]);
+	t = l; l = r; r = t ^ F1(r, Km[3], Kr[3]);
+	t = l; l = r; r = t ^ F2(r, Km[4], Kr[4]);
+	t = l; l = r; r = t ^ F3(r, Km[5], Kr[5]);
+	t = l; l = r; r = t ^ F1(r, Km[6], Kr[6]);
+	t = l; l = r; r = t ^ F2(r, Km[7], Kr[7]);
+	t = l; l = r; r = t ^ F3(r, Km[8], Kr[8]);
+	t = l; l = r; r = t ^ F1(r, Km[9], Kr[9]);
+	t = l; l = r; r = t ^ F2(r, Km[10], Kr[10]);
+	t = l; l = r; r = t ^ F3(r, Km[11], Kr[11]);
 	if (!(c->rr)) {
-		t = l; l = r; r = t ^ F1(r, Km[0], Kr[0]);
-		t = l; l = r; r = t ^ F2(r, Km[1], Kr[1]);
-		t = l; l = r; r = t ^ F3(r, Km[2], Kr[2]);
-		t = l; l = r; r = t ^ F1(r, Km[3], Kr[3]);
-		t = l; l = r; r = t ^ F2(r, Km[4], Kr[4]);
-		t = l; l = r; r = t ^ F3(r, Km[5], Kr[5]);
-		t = l; l = r; r = t ^ F1(r, Km[6], Kr[6]);
-		t = l; l = r; r = t ^ F2(r, Km[7], Kr[7]);
-		t = l; l = r; r = t ^ F3(r, Km[8], Kr[8]);
-		t = l; l = r; r = t ^ F1(r, Km[9], Kr[9]);
-		t = l; l = r; r = t ^ F2(r, Km[10], Kr[10]);
-		t = l; l = r; r = t ^ F3(r, Km[11], Kr[11]);
 		t = l; l = r; r = t ^ F1(r, Km[12], Kr[12]);
 		t = l; l = r; r = t ^ F2(r, Km[13], Kr[13]);
 		t = l; l = r; r = t ^ F3(r, Km[14], Kr[14]);
 		t = l; l = r; r = t ^ F1(r, Km[15], Kr[15]);
-	} else {
-		t = l; l = r; r = t ^ F1(r, Km[0], Kr[0]);
-		t = l; l = r; r = t ^ F2(r, Km[1], Kr[1]);
-		t = l; l = r; r = t ^ F3(r, Km[2], Kr[2]);
-		t = l; l = r; r = t ^ F1(r, Km[3], Kr[3]);
-		t = l; l = r; r = t ^ F2(r, Km[4], Kr[4]);
-		t = l; l = r; r = t ^ F3(r, Km[5], Kr[5]);
-		t = l; l = r; r = t ^ F1(r, Km[6], Kr[6]);
-		t = l; l = r; r = t ^ F2(r, Km[7], Kr[7]);
-		t = l; l = r; r = t ^ F3(r, Km[8], Kr[8]);
-		t = l; l = r; r = t ^ F1(r, Km[9], Kr[9]);
-		t = l; l = r; r = t ^ F2(r, Km[10], Kr[10]);
-		t = l; l = r; r = t ^ F3(r, Km[11], Kr[11]);
 	}
 
 	/* c1...c64 <-- (R16,L16).  (Exchange final blocks L16, R16 and
@@ -663,32 +650,19 @@ static void cast5_decrypt(struct crypto_
 		t = l; l = r; r = t ^ F3(r, Km[14], Kr[14]);
 		t = l; l = r; r = t ^ F2(r, Km[13], Kr[13]);
 		t = l; l = r; r = t ^ F1(r, Km[12], Kr[12]);
-		t = l; l = r; r = t ^ F3(r, Km[11], Kr[11]);
-		t = l; l = r; r = t ^ F2(r, Km[10], Kr[10]);
-		t = l; l = r; r = t ^ F1(r, Km[9], Kr[9]);
-		t = l; l = r; r = t ^ F3(r, Km[8], Kr[8]);
-		t = l; l = r; r = t ^ F2(r, Km[7], Kr[7]);
-		t = l; l = r; r = t ^ F1(r, Km[6], Kr[6]);
-		t = l; l = r; r = t ^ F3(r, Km[5], Kr[5]);
-		t = l; l = r; r = t ^ F2(r, Km[4], Kr[4]);
-		t = l; l = r; r = t ^ F1(r, Km[3], Kr[3]);
-		t = l; l = r; r = t ^ F3(r, Km[2], Kr[2]);
-		t = l; l = r; r = t ^ F2(r, Km[1], Kr[1]);
-		t = l; l = r; r = t ^ F1(r, Km[0], Kr[0]);
-	} else {
-		t = l; l = r; r = t ^ F3(r, Km[11], Kr[11]);
-		t = l; l = r; r = t ^ F2(r, Km[10], Kr[10]);
-		t = l; l = r; r = t ^ F1(r, Km[9], Kr[9]);
-		t = l; l = r; r = t ^ F3(r, Km[8], Kr[8]);
-		t = l; l = r; r = t ^ F2(r, Km[7], Kr[7]);
-		t = l; l = r; r = t ^ F1(r, Km[6], Kr[6]);
-		t = l; l = r; r = t ^ F3(r, Km[5], Kr[5]);
-		t = l; l = r; r = t ^ F2(r, Km[4], Kr[4]);
-		t = l; l = r; r = t ^ F1(r, Km[3], Kr[3]);
-		t = l; l = r; r = t ^ F3(r, Km[2], Kr[2]);
-		t = l; l = r; r = t ^ F2(r, Km[1], Kr[1]);
-		t = l; l = r; r = t ^ F1(r, Km[0], Kr[0]);
 	}
+	t = l; l = r; r = t ^ F3(r, Km[11], Kr[11]);
+	t = l; l = r; r = t ^ F2(r, Km[10], Kr[10]);
+	t = l; l = r; r = t ^ F1(r, Km[9], Kr[9]);
+	t = l; l = r; r = t ^ F3(r, Km[8], Kr[8]);
+	t = l; l = r; r = t ^ F2(r, Km[7], Kr[7]);
+	t = l; l = r; r = t ^ F1(r, Km[6], Kr[6]);
+	t = l; l = r; r = t ^ F3(r, Km[5], Kr[5]);
+	t = l; l = r; r = t ^ F2(r, Km[4], Kr[4]);
+	t = l; l = r; r = t ^ F1(r, Km[3], Kr[3]);
+	t = l; l = r; r = t ^ F3(r, Km[2], Kr[2]);
+	t = l; l = r; r = t ^ F2(r, Km[1], Kr[1]);
+	t = l; l = r; r = t ^ F1(r, Km[0], Kr[0]);
 
 	dst[0] = cpu_to_be32(r);
 	dst[1] = cpu_to_be32(l);
diff -druNp linux-libre-2.6.37-gnu1/crypto/crypto_wq.c linux-libre-2.6.38-gnu1/crypto/crypto_wq.c
--- linux-libre-2.6.37-gnu1/crypto/crypto_wq.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/crypto/crypto_wq.c	2011-03-14 21:20:32.000000000 -0400
@@ -20,7 +20,8 @@ EXPORT_SYMBOL_GPL(kcrypto_wq);
 
 static int __init crypto_wq_init(void)
 {
-	kcrypto_wq = create_workqueue("crypto");
+	kcrypto_wq = alloc_workqueue("crypto",
+				     WQ_MEM_RECLAIM | WQ_CPU_INTENSIVE, 1);
 	if (unlikely(!kcrypto_wq))
 		return -ENOMEM;
 	return 0;
diff -druNp linux-libre-2.6.37-gnu1/crypto/deflate.c linux-libre-2.6.38-gnu1/crypto/deflate.c
--- linux-libre-2.6.37-gnu1/crypto/deflate.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/crypto/deflate.c	2011-03-14 21:20:32.000000000 -0400
@@ -48,12 +48,11 @@ static int deflate_comp_init(struct defl
 	int ret = 0;
 	struct z_stream_s *stream = &ctx->comp_stream;
 
-	stream->workspace = vmalloc(zlib_deflate_workspacesize());
+	stream->workspace = vzalloc(zlib_deflate_workspacesize());
 	if (!stream->workspace) {
 		ret = -ENOMEM;
 		goto out;
 	}
-	memset(stream->workspace, 0, zlib_deflate_workspacesize());
 	ret = zlib_deflateInit2(stream, DEFLATE_DEF_LEVEL, Z_DEFLATED,
 	                        -DEFLATE_DEF_WINBITS, DEFLATE_DEF_MEMLEVEL,
 	                        Z_DEFAULT_STRATEGY);
diff -druNp linux-libre-2.6.37-gnu1/crypto/eseqiv.c linux-libre-2.6.38-gnu1/crypto/eseqiv.c
--- linux-libre-2.6.37-gnu1/crypto/eseqiv.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/crypto/eseqiv.c	2011-03-14 21:20:32.000000000 -0400
@@ -62,20 +62,6 @@ out:
 	skcipher_givcrypt_complete(req, err);
 }
 
-static void eseqiv_chain(struct scatterlist *head, struct scatterlist *sg,
-			 int chain)
-{
-	if (chain) {
-		head->length += sg->length;
-		sg = scatterwalk_sg_next(sg);
-	}
-
-	if (sg)
-		scatterwalk_sg_chain(head, 2, sg);
-	else
-		sg_mark_end(head);
-}
-
 static int eseqiv_givencrypt(struct skcipher_givcrypt_request *req)
 {
 	struct crypto_ablkcipher *geniv = skcipher_givcrypt_reqtfm(req);
@@ -124,13 +110,13 @@ static int eseqiv_givencrypt(struct skci
 
 	sg_init_table(reqctx->src, 2);
 	sg_set_buf(reqctx->src, giv, ivsize);
-	eseqiv_chain(reqctx->src, osrc, vsrc == giv + ivsize);
+	scatterwalk_crypto_chain(reqctx->src, osrc, vsrc == giv + ivsize, 2);
 
 	dst = reqctx->src;
 	if (osrc != odst) {
 		sg_init_table(reqctx->dst, 2);
 		sg_set_buf(reqctx->dst, giv, ivsize);
-		eseqiv_chain(reqctx->dst, odst, vdst == giv + ivsize);
+		scatterwalk_crypto_chain(reqctx->dst, odst, vdst == giv + ivsize, 2);
 
 		dst = reqctx->dst;
 	}
diff -druNp linux-libre-2.6.37-gnu1/crypto/gcm.c linux-libre-2.6.38-gnu1/crypto/gcm.c
--- linux-libre-2.6.37-gnu1/crypto/gcm.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/crypto/gcm.c	2011-03-14 21:20:32.000000000 -0400
@@ -1102,21 +1102,6 @@ static int crypto_rfc4543_setauthsize(st
 	return crypto_aead_setauthsize(ctx->child, authsize);
 }
 
-/* this is the same as crypto_authenc_chain */
-static void crypto_rfc4543_chain(struct scatterlist *head,
-				 struct scatterlist *sg, int chain)
-{
-	if (chain) {
-		head->length += sg->length;
-		sg = scatterwalk_sg_next(sg);
-	}
-
-	if (sg)
-		scatterwalk_sg_chain(head, 2, sg);
-	else
-		sg_mark_end(head);
-}
-
 static struct aead_request *crypto_rfc4543_crypt(struct aead_request *req,
 						 int enc)
 {
@@ -1154,13 +1139,13 @@ static struct aead_request *crypto_rfc45
 
 	sg_init_table(payload, 2);
 	sg_set_buf(payload, req->iv, 8);
-	crypto_rfc4543_chain(payload, dst, vdst == req->iv + 8);
+	scatterwalk_crypto_chain(payload, dst, vdst == req->iv + 8, 2);
 	assoclen += 8 + req->cryptlen - (enc ? 0 : authsize);
 
 	sg_init_table(assoc, 2);
 	sg_set_page(assoc, sg_page(req->assoc), req->assoc->length,
 		    req->assoc->offset);
-	crypto_rfc4543_chain(assoc, payload, 0);
+	scatterwalk_crypto_chain(assoc, payload, 0, 2);
 
 	aead_request_set_tfm(subreq, ctx->child);
 	aead_request_set_callback(subreq, req->base.flags, req->base.complete,
diff -druNp linux-libre-2.6.37-gnu1/crypto/Kconfig linux-libre-2.6.38-gnu1/crypto/Kconfig
--- linux-libre-2.6.37-gnu1/crypto/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/crypto/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -110,7 +110,6 @@ config CRYPTO_MANAGER_DISABLE_TESTS
 
 config CRYPTO_GF128MUL
 	tristate "GF(2^128) multiplication functions (EXPERIMENTAL)"
-	depends on EXPERIMENTAL
 	help
 	  Efficient table driven implementation of multiplications in the
 	  field GF(2^128).  This is needed by some cypher modes. This
@@ -539,8 +538,9 @@ config CRYPTO_AES_X86_64
 
 config CRYPTO_AES_NI_INTEL
 	tristate "AES cipher algorithms (AES-NI)"
-	depends on (X86 || UML_X86) && 64BIT
-	select CRYPTO_AES_X86_64
+	depends on (X86 || UML_X86)
+	select CRYPTO_AES_X86_64 if 64BIT
+	select CRYPTO_AES_586 if !64BIT
 	select CRYPTO_CRYPTD
 	select CRYPTO_ALGAPI
 	select CRYPTO_FPU
@@ -563,9 +563,10 @@ config CRYPTO_AES_NI_INTEL
 
 	  See <http://csrc.nist.gov/encryption/aes/> for more information.
 
-	  In addition to AES cipher algorithm support, the
-	  acceleration for some popular block cipher mode is supported
-	  too, including ECB, CBC, CTR, LRW, PCBC, XTS.
+	  In addition to AES cipher algorithm support, the acceleration
+	  for some popular block cipher mode is supported too, including
+	  ECB, CBC, LRW, PCBC, XTS. The 64 bit version has additional
+	  acceleration for CTR.
 
 config CRYPTO_ANUBIS
 	tristate "Anubis cipher algorithm"
@@ -841,6 +842,27 @@ config CRYPTO_ANSI_CPRNG
 	  ANSI X9.31 A.2.4. Note that this option must be enabled if
 	  CRYPTO_FIPS is selected
 
+config CRYPTO_USER_API
+	tristate
+
+config CRYPTO_USER_API_HASH
+	tristate "User-space interface for hash algorithms"
+	depends on NET
+	select CRYPTO_HASH
+	select CRYPTO_USER_API
+	help
+	  This option enables the user-spaces interface for hash
+	  algorithms.
+
+config CRYPTO_USER_API_SKCIPHER
+	tristate "User-space interface for symmetric key cipher algorithms"
+	depends on NET
+	select CRYPTO_BLKCIPHER
+	select CRYPTO_USER_API
+	help
+	  This option enables the user-spaces interface for symmetric
+	  key cipher algorithms.
+
 source "drivers/crypto/Kconfig"
 
 endif	# if CRYPTO
diff -druNp linux-libre-2.6.37-gnu1/crypto/Makefile linux-libre-2.6.38-gnu1/crypto/Makefile
--- linux-libre-2.6.37-gnu1/crypto/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/crypto/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -3,32 +3,32 @@
 #
 
 obj-$(CONFIG_CRYPTO) += crypto.o
-crypto-objs := api.o cipher.o compress.o
+crypto-y := api.o cipher.o compress.o
 
 obj-$(CONFIG_CRYPTO_WORKQUEUE) += crypto_wq.o
 
 obj-$(CONFIG_CRYPTO_FIPS) += fips.o
 
 crypto_algapi-$(CONFIG_PROC_FS) += proc.o
-crypto_algapi-objs := algapi.o scatterwalk.o $(crypto_algapi-y)
+crypto_algapi-y := algapi.o scatterwalk.o $(crypto_algapi-y)
 obj-$(CONFIG_CRYPTO_ALGAPI2) += crypto_algapi.o
 
 obj-$(CONFIG_CRYPTO_AEAD2) += aead.o
 
-crypto_blkcipher-objs := ablkcipher.o
-crypto_blkcipher-objs += blkcipher.o
+crypto_blkcipher-y := ablkcipher.o
+crypto_blkcipher-y += blkcipher.o
 obj-$(CONFIG_CRYPTO_BLKCIPHER2) += crypto_blkcipher.o
 obj-$(CONFIG_CRYPTO_BLKCIPHER2) += chainiv.o
 obj-$(CONFIG_CRYPTO_BLKCIPHER2) += eseqiv.o
 obj-$(CONFIG_CRYPTO_SEQIV) += seqiv.o
 
-crypto_hash-objs += ahash.o
-crypto_hash-objs += shash.o
+crypto_hash-y += ahash.o
+crypto_hash-y += shash.o
 obj-$(CONFIG_CRYPTO_HASH2) += crypto_hash.o
 
 obj-$(CONFIG_CRYPTO_PCOMP2) += pcompress.o
 
-cryptomgr-objs := algboss.o testmgr.o
+cryptomgr-y := algboss.o testmgr.o
 
 obj-$(CONFIG_CRYPTO_MANAGER2) += cryptomgr.o
 obj-$(CONFIG_CRYPTO_HMAC) += hmac.o
@@ -85,6 +85,9 @@ obj-$(CONFIG_CRYPTO_RNG2) += krng.o
 obj-$(CONFIG_CRYPTO_ANSI_CPRNG) += ansi_cprng.o
 obj-$(CONFIG_CRYPTO_TEST) += tcrypt.o
 obj-$(CONFIG_CRYPTO_GHASH) += ghash-generic.o
+obj-$(CONFIG_CRYPTO_USER_API) += af_alg.o
+obj-$(CONFIG_CRYPTO_USER_API_HASH) += algif_hash.o
+obj-$(CONFIG_CRYPTO_USER_API_SKCIPHER) += algif_skcipher.o
 
 #
 # generic algorithms and the async_tx api
diff -druNp linux-libre-2.6.37-gnu1/crypto/pcrypt.c linux-libre-2.6.38-gnu1/crypto/pcrypt.c
--- linux-libre-2.6.37-gnu1/crypto/pcrypt.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/crypto/pcrypt.c	2011-03-14 21:20:32.000000000 -0400
@@ -455,7 +455,8 @@ static int pcrypt_init_padata(struct pad
 
 	get_online_cpus();
 
-	pcrypt->wq = create_workqueue(name);
+	pcrypt->wq = alloc_workqueue(name,
+				     WQ_MEM_RECLAIM | WQ_CPU_INTENSIVE, 1);
 	if (!pcrypt->wq)
 		goto err;
 
diff -druNp linux-libre-2.6.37-gnu1/crypto/rmd128.c linux-libre-2.6.38-gnu1/crypto/rmd128.c
--- linux-libre-2.6.37-gnu1/crypto/rmd128.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/crypto/rmd128.c	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  *
  * Based on the reference implementation by Antoon Bosselaers, ESAT-COSIC
  *
- * Copyright (c) 2008 Adrian-Ken Rueegsegger <rueegsegger (at) swiss-it.ch>
+ * Copyright (c) 2008 Adrian-Ken Rueegsegger <ken@codelabs.ch>
  *
  * 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
@@ -325,4 +325,5 @@ module_init(rmd128_mod_init);
 module_exit(rmd128_mod_fini);
 
 MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Adrian-Ken Rueegsegger <ken@codelabs.ch>");
 MODULE_DESCRIPTION("RIPEMD-128 Message Digest");
diff -druNp linux-libre-2.6.37-gnu1/crypto/rmd160.c linux-libre-2.6.38-gnu1/crypto/rmd160.c
--- linux-libre-2.6.37-gnu1/crypto/rmd160.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/crypto/rmd160.c	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  *
  * Based on the reference implementation by Antoon Bosselaers, ESAT-COSIC
  *
- * Copyright (c) 2008 Adrian-Ken Rueegsegger <rueegsegger (at) swiss-it.ch>
+ * Copyright (c) 2008 Adrian-Ken Rueegsegger <ken@codelabs.ch>
  *
  * 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
@@ -369,4 +369,5 @@ module_init(rmd160_mod_init);
 module_exit(rmd160_mod_fini);
 
 MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Adrian-Ken Rueegsegger <ken@codelabs.ch>");
 MODULE_DESCRIPTION("RIPEMD-160 Message Digest");
diff -druNp linux-libre-2.6.37-gnu1/crypto/rmd256.c linux-libre-2.6.38-gnu1/crypto/rmd256.c
--- linux-libre-2.6.37-gnu1/crypto/rmd256.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/crypto/rmd256.c	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  *
  * Based on the reference implementation by Antoon Bosselaers, ESAT-COSIC
  *
- * Copyright (c) 2008 Adrian-Ken Rueegsegger <rueegsegger (at) swiss-it.ch>
+ * Copyright (c) 2008 Adrian-Ken Rueegsegger <ken@codelabs.ch>
  *
  * 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
@@ -344,4 +344,5 @@ module_init(rmd256_mod_init);
 module_exit(rmd256_mod_fini);
 
 MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Adrian-Ken Rueegsegger <ken@codelabs.ch>");
 MODULE_DESCRIPTION("RIPEMD-256 Message Digest");
diff -druNp linux-libre-2.6.37-gnu1/crypto/rmd320.c linux-libre-2.6.38-gnu1/crypto/rmd320.c
--- linux-libre-2.6.37-gnu1/crypto/rmd320.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/crypto/rmd320.c	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  *
  * Based on the reference implementation by Antoon Bosselaers, ESAT-COSIC
  *
- * Copyright (c) 2008 Adrian-Ken Rueegsegger <rueegsegger (at) swiss-it.ch>
+ * Copyright (c) 2008 Adrian-Ken Rueegsegger <ken@codelabs.ch>
  *
  * 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
@@ -393,4 +393,5 @@ module_init(rmd320_mod_init);
 module_exit(rmd320_mod_fini);
 
 MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Adrian-Ken Rueegsegger <ken@codelabs.ch>");
 MODULE_DESCRIPTION("RIPEMD-320 Message Digest");
diff -druNp linux-libre-2.6.37-gnu1/crypto/shash.c linux-libre-2.6.38-gnu1/crypto/shash.c
--- linux-libre-2.6.37-gnu1/crypto/shash.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/crypto/shash.c	2011-03-14 21:20:32.000000000 -0400
@@ -310,7 +310,13 @@ static int shash_async_export(struct aha
 
 static int shash_async_import(struct ahash_request *req, const void *in)
 {
-	return crypto_shash_import(ahash_request_ctx(req), in);
+	struct crypto_shash **ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req));
+	struct shash_desc *desc = ahash_request_ctx(req);
+
+	desc->tfm = *ctx;
+	desc->flags = req->base.flags;
+
+	return crypto_shash_import(desc, in);
 }
 
 static void crypto_exit_shash_ops_async(struct crypto_tfm *tfm)
diff -druNp linux-libre-2.6.37-gnu1/crypto/tcrypt.c linux-libre-2.6.38-gnu1/crypto/tcrypt.c
--- linux-libre-2.6.37-gnu1/crypto/tcrypt.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/crypto/tcrypt.c	2011-03-14 21:20:32.000000000 -0400
@@ -8,6 +8,13 @@
  * Copyright (c) 2002 Jean-Francois Dive <jef@linuxbe.org>
  * Copyright (c) 2007 Nokia Siemens Networks
  *
+ * Updated RFC4106 AES-GCM testing.
+ *    Authors: Aidan O'Mahony (aidan.o.mahony@intel.com)
+ *             Adrian Hoban <adrian.hoban@intel.com>
+ *             Gabriele Paoloni <gabriele.paoloni@intel.com>
+ *             Tadeusz Struk (tadeusz.struk@intel.com)
+ *             Copyright (c) 2010, 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)
@@ -980,6 +987,10 @@ static int do_test(int m)
 		ret += tcrypt_test("ansi_cprng");
 		break;
 
+	case 151:
+		ret += tcrypt_test("rfc4106(gcm(aes))");
+		break;
+
 	case 200:
 		test_cipher_speed("ecb(aes)", ENCRYPT, sec, NULL, 0,
 				speed_template_16_24_32);
diff -druNp linux-libre-2.6.37-gnu1/crypto/testmgr.c linux-libre-2.6.38-gnu1/crypto/testmgr.c
--- linux-libre-2.6.37-gnu1/crypto/testmgr.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/crypto/testmgr.c	2011-03-14 21:20:32.000000000 -0400
@@ -6,6 +6,13 @@
  * Copyright (c) 2007 Nokia Siemens Networks
  * Copyright (c) 2008 Herbert Xu <herbert@gondor.apana.org.au>
  *
+ * Updated RFC4106 AES-GCM testing.
+ *    Authors: Aidan O'Mahony (aidan.o.mahony@intel.com)
+ *             Adrian Hoban <adrian.hoban@intel.com>
+ *             Gabriele Paoloni <gabriele.paoloni@intel.com>
+ *             Tadeusz Struk (tadeusz.struk@intel.com)
+ *    Copyright (c) 2010, 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)
@@ -2242,6 +2249,23 @@ static const struct alg_test_desc alg_te
 			}
 		}
 	}, {
+		.alg = "rfc4106(gcm(aes))",
+		.test = alg_test_aead,
+		.suite = {
+			.aead = {
+				.enc = {
+					.vecs = aes_gcm_rfc4106_enc_tv_template,
+					.count = AES_GCM_4106_ENC_TEST_VECTORS
+				},
+				.dec = {
+					.vecs = aes_gcm_rfc4106_dec_tv_template,
+					.count = AES_GCM_4106_DEC_TEST_VECTORS
+				}
+			}
+		}
+	}, {
+
+
 		.alg = "rfc4309(ccm(aes))",
 		.test = alg_test_aead,
 		.fips_allowed = 1,
diff -druNp linux-libre-2.6.37-gnu1/crypto/testmgr.h linux-libre-2.6.38-gnu1/crypto/testmgr.h
--- linux-libre-2.6.37-gnu1/crypto/testmgr.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/crypto/testmgr.h	2011-03-14 21:20:32.000000000 -0400
@@ -6,6 +6,15 @@
  * Copyright (c) 2007 Nokia Siemens Networks
  * Copyright (c) 2008 Herbert Xu <herbert@gondor.apana.org.au>
  *
+ * Updated RFC4106 AES-GCM testing. Some test vectors were taken from
+ * http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/
+ * gcm/gcm-test-vectors.tar.gz
+ *     Authors: Aidan O'Mahony (aidan.o.mahony@intel.com)
+ *              Adrian Hoban <adrian.hoban@intel.com>
+ *              Gabriele Paoloni <gabriele.paoloni@intel.com>
+ *              Tadeusz Struk (tadeusz.struk@intel.com)
+ *     Copyright (c) 2010, 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)
@@ -2947,6 +2956,8 @@ static struct cipher_testvec cast6_dec_t
 #define AES_CTR_3686_DEC_TEST_VECTORS 6
 #define AES_GCM_ENC_TEST_VECTORS 9
 #define AES_GCM_DEC_TEST_VECTORS 8
+#define AES_GCM_4106_ENC_TEST_VECTORS 7
+#define AES_GCM_4106_DEC_TEST_VECTORS 7
 #define AES_CCM_ENC_TEST_VECTORS 7
 #define AES_CCM_DEC_TEST_VECTORS 7
 #define AES_CCM_4309_ENC_TEST_VECTORS 7
@@ -5829,6 +5840,356 @@ static struct aead_testvec aes_gcm_dec_t
 	}
 };
 
+static struct aead_testvec aes_gcm_rfc4106_enc_tv_template[] = {
+        { /* Generated using Crypto++ */
+		.key    = zeroed_string,
+		.klen	= 20,
+                .iv     = zeroed_string,
+                .input  = zeroed_string,
+                .ilen   = 16,
+                .assoc  = zeroed_string,
+                .alen   = 8,
+		.result	= "\x03\x88\xDA\xCE\x60\xB6\xA3\x92"
+                          "\xF3\x28\xC2\xB9\x71\xB2\xFE\x78"
+                          "\x97\xFE\x4C\x23\x37\x42\x01\xE0"
+                          "\x81\x9F\x8D\xC5\xD7\x41\xA0\x1B",
+		.rlen	= 32,
+        },{
+		.key    = "\xfe\xff\xe9\x92\x86\x65\x73\x1c"
+			  "\x6d\x6a\x8f\x94\x67\x30\x83\x08"
+                          "\x00\x00\x00\x00",
+		.klen	= 20,
+                .iv     = "\x00\x00\x00\x00\x00\x00\x00\x01"
+                          "\x00\x00\x00\x00",
+                .input  = zeroed_string,
+                .ilen   = 16,
+                .assoc  = zeroed_string,
+                .alen   = 8,
+		.result	= "\xC0\x0D\x8B\x42\x0F\x8F\x34\x18"
+                          "\x88\xB1\xC5\xBC\xC5\xB6\xD6\x28"
+                          "\x6A\x9D\xDF\x11\x5E\xFE\x5E\x9D"
+                          "\x2F\x70\x44\x92\xF7\xF2\xE3\xEF",
+		.rlen	= 32,
+
+        }, {
+		.key    = "\xfe\xff\xe9\x92\x86\x65\x73\x1c"
+			  "\x6d\x6a\x8f\x94\x67\x30\x83\x08"
+                          "\x00\x00\x00\x00",
+		.klen	= 20,
+                .iv     = zeroed_string,
+                .input  = "\x01\x01\x01\x01\x01\x01\x01\x01"
+                          "\x01\x01\x01\x01\x01\x01\x01\x01",
+                .ilen   = 16,
+                .assoc  = zeroed_string,
+                .alen   = 8,
+		.result	= "\x4B\xB1\xB5\xE3\x25\x71\x70\xDE"
+                          "\x7F\xC9\x9C\xA5\x14\x19\xF2\xAC"
+                          "\x0B\x8F\x88\x69\x17\xE6\xB4\x3C"
+                          "\xB1\x68\xFD\x14\x52\x64\x61\xB2",
+		.rlen	= 32,
+        }, {
+		.key    = "\xfe\xff\xe9\x92\x86\x65\x73\x1c"
+			  "\x6d\x6a\x8f\x94\x67\x30\x83\x08"
+                          "\x00\x00\x00\x00",
+		.klen	= 20,
+                .iv     = zeroed_string,
+                .input  = "\x01\x01\x01\x01\x01\x01\x01\x01"
+                          "\x01\x01\x01\x01\x01\x01\x01\x01",
+                .ilen   = 16,
+                .assoc  = "\x01\x01\x01\x01\x01\x01\x01\x01",
+                .alen   = 8,
+		.result	= "\x4B\xB1\xB5\xE3\x25\x71\x70\xDE"
+                          "\x7F\xC9\x9C\xA5\x14\x19\xF2\xAC"
+                          "\x90\x92\xB7\xE3\x5F\xA3\x9A\x63"
+                          "\x7E\xD7\x1F\xD8\xD3\x7C\x4B\xF5",
+		.rlen	= 32,
+        }, {
+		.key    = "\xfe\xff\xe9\x92\x86\x65\x73\x1c"
+			  "\x6d\x6a\x8f\x94\x67\x30\x83\x08"
+                          "\x00\x00\x00\x00",
+		.klen	= 20,
+                .iv     = "\x00\x00\x00\x00\x00\x00\x00\x01"
+                          "\x00\x00\x00\x00",
+                .input  = "\x01\x01\x01\x01\x01\x01\x01\x01"
+                          "\x01\x01\x01\x01\x01\x01\x01\x01",
+                .ilen   = 16,
+                .assoc  = "\x01\x01\x01\x01\x01\x01\x01\x01",
+                .alen   = 8,
+		.result	= "\xC1\x0C\x8A\x43\x0E\x8E\x35\x19"
+                          "\x89\xB0\xC4\xBD\xC4\xB7\xD7\x29"
+                          "\x64\x50\xF9\x32\x13\xFB\x74\x61"
+                          "\xF4\xED\x52\xD3\xC5\x10\x55\x3C",
+		.rlen	= 32,
+        }, {
+		.key    = "\xfe\xff\xe9\x92\x86\x65\x73\x1c"
+			  "\x6d\x6a\x8f\x94\x67\x30\x83\x08"
+                          "\x00\x00\x00\x00",
+		.klen	= 20,
+                .iv     = "\x00\x00\x00\x00\x00\x00\x00\x01"
+                          "\x00\x00\x00\x00",
+                .input  = "\x01\x01\x01\x01\x01\x01\x01\x01"
+                          "\x01\x01\x01\x01\x01\x01\x01\x01"
+                          "\x01\x01\x01\x01\x01\x01\x01\x01"
+                          "\x01\x01\x01\x01\x01\x01\x01\x01"
+                          "\x01\x01\x01\x01\x01\x01\x01\x01"
+                          "\x01\x01\x01\x01\x01\x01\x01\x01"
+                          "\x01\x01\x01\x01\x01\x01\x01\x01"
+                          "\x01\x01\x01\x01\x01\x01\x01\x01",
+                .ilen   = 64,
+                .assoc  = "\x01\x01\x01\x01\x01\x01\x01\x01",
+                .alen   = 8,
+		.result	= "\xC1\x0C\x8A\x43\x0E\x8E\x35\x19"
+                          "\x89\xB0\xC4\xBD\xC4\xB7\xD7\x29"
+                          "\x98\x14\xA1\x42\x37\x80\xFD\x90"
+                          "\x68\x12\x01\xA8\x91\x89\xB9\x83"
+                          "\x5B\x11\x77\x12\x9B\xFF\x24\x89"
+                          "\x94\x5F\x18\x12\xBA\x27\x09\x39"
+                          "\x99\x96\x76\x42\x15\x1C\xCD\xCB"
+                          "\xDC\xD3\xDA\x65\x73\xAF\x80\xCD"
+                          "\xD2\xB6\xC2\x4A\x76\xC2\x92\x85"
+                          "\xBD\xCF\x62\x98\x58\x14\xE5\xBD",
+		.rlen	= 80,
+        }, {
+		.key    = "\x00\x01\x02\x03\x04\x05\x06\x07"
+			  "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
+                          "\x00\x00\x00\x00",
+		.klen	= 20,
+                .iv     = "\x00\x00\x45\x67\x89\xab\xcd\xef"
+                          "\x00\x00\x00\x00",
+                .input  = "\xff\xff\xff\xff\xff\xff\xff\xff"
+                          "\xff\xff\xff\xff\xff\xff\xff\xff"
+                          "\xff\xff\xff\xff\xff\xff\xff\xff"
+                          "\xff\xff\xff\xff\xff\xff\xff\xff"
+                          "\xff\xff\xff\xff\xff\xff\xff\xff"
+                          "\xff\xff\xff\xff\xff\xff\xff\xff"
+                          "\xff\xff\xff\xff\xff\xff\xff\xff"
+                          "\xff\xff\xff\xff\xff\xff\xff\xff"
+                          "\xff\xff\xff\xff\xff\xff\xff\xff"
+                          "\xff\xff\xff\xff\xff\xff\xff\xff"
+                          "\xff\xff\xff\xff\xff\xff\xff\xff"
+                          "\xff\xff\xff\xff\xff\xff\xff\xff"
+                          "\xff\xff\xff\xff\xff\xff\xff\xff"
+                          "\xff\xff\xff\xff\xff\xff\xff\xff"
+                          "\xff\xff\xff\xff\xff\xff\xff\xff"
+                          "\xff\xff\xff\xff\xff\xff\xff\xff"
+                          "\xff\xff\xff\xff\xff\xff\xff\xff"
+                          "\xff\xff\xff\xff\xff\xff\xff\xff"
+                          "\xff\xff\xff\xff\xff\xff\xff\xff"
+                          "\xff\xff\xff\xff\xff\xff\xff\xff"
+                          "\xff\xff\xff\xff\xff\xff\xff\xff"
+                          "\xff\xff\xff\xff\xff\xff\xff\xff"
+                          "\xff\xff\xff\xff\xff\xff\xff\xff"
+                          "\xff\xff\xff\xff\xff\xff\xff\xff",
+                .ilen   = 192,
+                .assoc  = "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                          "\xaa\xaa\xaa\xaa",
+                .alen   = 12,
+		.result	= "\xC1\x76\x33\x85\xE2\x9B\x5F\xDE"
+			  "\xDE\x89\x3D\x42\xE7\xC9\x69\x8A"
+			  "\x44\x6D\xC3\x88\x46\x2E\xC2\x01"
+			  "\x5E\xF6\x0C\x39\xF0\xC4\xA5\x82"
+			  "\xCD\xE8\x31\xCC\x0A\x4C\xE4\x44"
+			  "\x41\xA9\x82\x6F\x22\xA1\x23\x1A"
+			  "\xA8\xE3\x16\xFD\x31\x5C\x27\x31"
+			  "\xF1\x7F\x01\x63\xA3\xAF\x70\xA1"
+			  "\xCF\x07\x57\x41\x67\xD0\xC4\x42"
+			  "\xDB\x18\xC6\x4C\x4C\xE0\x3D\x9F"
+			  "\x05\x07\xFB\x13\x7D\x4A\xCA\x5B"
+			  "\xF0\xBF\x64\x7E\x05\xB1\x72\xEE"
+			  "\x7C\x3B\xD4\xCD\x14\x03\xB2\x2C"
+			  "\xD3\xA9\xEE\xFA\x17\xFC\x9C\xDF"
+			  "\xC7\x75\x40\xFF\xAE\xAD\x1E\x59"
+			  "\x2F\x30\x24\xFB\xAD\x6B\x10\xFA"
+			  "\x6C\x9F\x5B\xE7\x25\xD5\xD0\x25"
+			  "\xAC\x4A\x4B\xDA\xFC\x7A\x85\x1B"
+			  "\x7E\x13\x06\x82\x08\x17\xA4\x35"
+			  "\xEC\xC5\x8D\x63\x96\x81\x0A\x8F"
+			  "\xA3\x05\x38\x95\x20\x1A\x47\x04"
+			  "\x6F\x6D\xDA\x8F\xEF\xC1\x76\x35"
+			  "\x6B\xC7\x4D\x0F\x94\x12\xCA\x3E"
+			  "\x2E\xD5\x03\x2E\x86\x7E\xAA\x3B"
+			  "\x37\x08\x1C\xCF\xBA\x5D\x71\x46"
+			  "\x80\x72\xB0\x4C\x82\x0D\x60\x3C",
+		.rlen	= 208,
+	}
+};
+
+static struct aead_testvec aes_gcm_rfc4106_dec_tv_template[] = {
+        { /* Generated using Crypto++ */
+		.key    = zeroed_string,
+		.klen	= 20,
+                .iv     = zeroed_string,
+		.input	= "\x03\x88\xDA\xCE\x60\xB6\xA3\x92"
+                          "\xF3\x28\xC2\xB9\x71\xB2\xFE\x78"
+                          "\x97\xFE\x4C\x23\x37\x42\x01\xE0"
+                          "\x81\x9F\x8D\xC5\xD7\x41\xA0\x1B",
+		.ilen	= 32,
+                .assoc  = zeroed_string,
+                .alen   = 8,
+                .result = zeroed_string,
+                .rlen   = 16,
+
+        },{
+		.key    = "\xfe\xff\xe9\x92\x86\x65\x73\x1c"
+			  "\x6d\x6a\x8f\x94\x67\x30\x83\x08"
+                          "\x00\x00\x00\x00",
+		.klen	= 20,
+                .iv     = "\x00\x00\x00\x00\x00\x00\x00\x01"
+                          "\x00\x00\x00\x00",
+		.input	= "\xC0\x0D\x8B\x42\x0F\x8F\x34\x18"
+                          "\x88\xB1\xC5\xBC\xC5\xB6\xD6\x28"
+                          "\x6A\x9D\xDF\x11\x5E\xFE\x5E\x9D"
+                          "\x2F\x70\x44\x92\xF7\xF2\xE3\xEF",
+		.ilen	= 32,
+                .assoc  = zeroed_string,
+                .alen   = 8,
+                .result = zeroed_string,
+                .rlen   = 16,
+        }, {
+		.key    = "\xfe\xff\xe9\x92\x86\x65\x73\x1c"
+			  "\x6d\x6a\x8f\x94\x67\x30\x83\x08"
+                          "\x00\x00\x00\x00",
+		.klen	= 20,
+                .iv     = zeroed_string,
+		.input	= "\x4B\xB1\xB5\xE3\x25\x71\x70\xDE"
+                          "\x7F\xC9\x9C\xA5\x14\x19\xF2\xAC"
+                          "\x0B\x8F\x88\x69\x17\xE6\xB4\x3C"
+                          "\xB1\x68\xFD\x14\x52\x64\x61\xB2",
+		.ilen	= 32,
+                .assoc  = zeroed_string,
+                .alen   = 8,
+                .result = "\x01\x01\x01\x01\x01\x01\x01\x01"
+                          "\x01\x01\x01\x01\x01\x01\x01\x01",
+                .rlen   = 16,
+        }, {
+		.key    = "\xfe\xff\xe9\x92\x86\x65\x73\x1c"
+			  "\x6d\x6a\x8f\x94\x67\x30\x83\x08"
+                          "\x00\x00\x00\x00",
+		.klen	= 20,
+                .iv     = zeroed_string,
+		.input	= "\x4B\xB1\xB5\xE3\x25\x71\x70\xDE"
+                          "\x7F\xC9\x9C\xA5\x14\x19\xF2\xAC"
+                          "\x90\x92\xB7\xE3\x5F\xA3\x9A\x63"
+                          "\x7E\xD7\x1F\xD8\xD3\x7C\x4B\xF5",
+		.ilen	= 32,
+                .assoc  = "\x01\x01\x01\x01\x01\x01\x01\x01",
+                .alen   = 8,
+                .result = "\x01\x01\x01\x01\x01\x01\x01\x01"
+                          "\x01\x01\x01\x01\x01\x01\x01\x01",
+                .rlen   = 16,
+
+        }, {
+		.key    = "\xfe\xff\xe9\x92\x86\x65\x73\x1c"
+			  "\x6d\x6a\x8f\x94\x67\x30\x83\x08"
+                          "\x00\x00\x00\x00",
+		.klen	= 20,
+                .iv     = "\x00\x00\x00\x00\x00\x00\x00\x01"
+                          "\x00\x00\x00\x00",
+		.input	= "\xC1\x0C\x8A\x43\x0E\x8E\x35\x19"
+                          "\x89\xB0\xC4\xBD\xC4\xB7\xD7\x29"
+                          "\x64\x50\xF9\x32\x13\xFB\x74\x61"
+                          "\xF4\xED\x52\xD3\xC5\x10\x55\x3C",
+		.ilen	= 32,
+                .assoc  = "\x01\x01\x01\x01\x01\x01\x01\x01",
+                .alen   = 8,
+                .result = "\x01\x01\x01\x01\x01\x01\x01\x01"
+                          "\x01\x01\x01\x01\x01\x01\x01\x01",
+                .rlen   = 16,
+        }, {
+		.key    = "\xfe\xff\xe9\x92\x86\x65\x73\x1c"
+			  "\x6d\x6a\x8f\x94\x67\x30\x83\x08"
+                          "\x00\x00\x00\x00",
+		.klen	= 20,
+                .iv     = "\x00\x00\x00\x00\x00\x00\x00\x01"
+                          "\x00\x00\x00\x00",
+		.input	= "\xC1\x0C\x8A\x43\x0E\x8E\x35\x19"
+                          "\x89\xB0\xC4\xBD\xC4\xB7\xD7\x29"
+                          "\x98\x14\xA1\x42\x37\x80\xFD\x90"
+                          "\x68\x12\x01\xA8\x91\x89\xB9\x83"
+                          "\x5B\x11\x77\x12\x9B\xFF\x24\x89"
+                          "\x94\x5F\x18\x12\xBA\x27\x09\x39"
+                          "\x99\x96\x76\x42\x15\x1C\xCD\xCB"
+                          "\xDC\xD3\xDA\x65\x73\xAF\x80\xCD"
+                          "\xD2\xB6\xC2\x4A\x76\xC2\x92\x85"
+                          "\xBD\xCF\x62\x98\x58\x14\xE5\xBD",
+		.ilen	= 80,
+                .assoc  = "\x01\x01\x01\x01\x01\x01\x01\x01",
+                .alen   = 8,
+                .result = "\x01\x01\x01\x01\x01\x01\x01\x01"
+                          "\x01\x01\x01\x01\x01\x01\x01\x01"
+                          "\x01\x01\x01\x01\x01\x01\x01\x01"
+                          "\x01\x01\x01\x01\x01\x01\x01\x01"
+                          "\x01\x01\x01\x01\x01\x01\x01\x01"
+                          "\x01\x01\x01\x01\x01\x01\x01\x01"
+                          "\x01\x01\x01\x01\x01\x01\x01\x01"
+                          "\x01\x01\x01\x01\x01\x01\x01\x01",
+                .rlen   = 64,
+        }, {
+		.key    = "\x00\x01\x02\x03\x04\x05\x06\x07"
+			  "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
+                          "\x00\x00\x00\x00",
+		.klen	= 20,
+                .iv     = "\x00\x00\x45\x67\x89\xab\xcd\xef"
+                          "\x00\x00\x00\x00",
+		.input	= "\xC1\x76\x33\x85\xE2\x9B\x5F\xDE"
+			  "\xDE\x89\x3D\x42\xE7\xC9\x69\x8A"
+			  "\x44\x6D\xC3\x88\x46\x2E\xC2\x01"
+			  "\x5E\xF6\x0C\x39\xF0\xC4\xA5\x82"
+			  "\xCD\xE8\x31\xCC\x0A\x4C\xE4\x44"
+			  "\x41\xA9\x82\x6F\x22\xA1\x23\x1A"
+			  "\xA8\xE3\x16\xFD\x31\x5C\x27\x31"
+			  "\xF1\x7F\x01\x63\xA3\xAF\x70\xA1"
+			  "\xCF\x07\x57\x41\x67\xD0\xC4\x42"
+			  "\xDB\x18\xC6\x4C\x4C\xE0\x3D\x9F"
+			  "\x05\x07\xFB\x13\x7D\x4A\xCA\x5B"
+			  "\xF0\xBF\x64\x7E\x05\xB1\x72\xEE"
+			  "\x7C\x3B\xD4\xCD\x14\x03\xB2\x2C"
+			  "\xD3\xA9\xEE\xFA\x17\xFC\x9C\xDF"
+			  "\xC7\x75\x40\xFF\xAE\xAD\x1E\x59"
+			  "\x2F\x30\x24\xFB\xAD\x6B\x10\xFA"
+			  "\x6C\x9F\x5B\xE7\x25\xD5\xD0\x25"
+			  "\xAC\x4A\x4B\xDA\xFC\x7A\x85\x1B"
+			  "\x7E\x13\x06\x82\x08\x17\xA4\x35"
+			  "\xEC\xC5\x8D\x63\x96\x81\x0A\x8F"
+			  "\xA3\x05\x38\x95\x20\x1A\x47\x04"
+			  "\x6F\x6D\xDA\x8F\xEF\xC1\x76\x35"
+			  "\x6B\xC7\x4D\x0F\x94\x12\xCA\x3E"
+			  "\x2E\xD5\x03\x2E\x86\x7E\xAA\x3B"
+			  "\x37\x08\x1C\xCF\xBA\x5D\x71\x46"
+			  "\x80\x72\xB0\x4C\x82\x0D\x60\x3C",
+		.ilen	= 208,
+                .assoc  = "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                          "\xaa\xaa\xaa\xaa",
+                .alen   = 12,
+                .result = "\xff\xff\xff\xff\xff\xff\xff\xff"
+                          "\xff\xff\xff\xff\xff\xff\xff\xff"
+                          "\xff\xff\xff\xff\xff\xff\xff\xff"
+                          "\xff\xff\xff\xff\xff\xff\xff\xff"
+                          "\xff\xff\xff\xff\xff\xff\xff\xff"
+                          "\xff\xff\xff\xff\xff\xff\xff\xff"
+                          "\xff\xff\xff\xff\xff\xff\xff\xff"
+                          "\xff\xff\xff\xff\xff\xff\xff\xff"
+                          "\xff\xff\xff\xff\xff\xff\xff\xff"
+                          "\xff\xff\xff\xff\xff\xff\xff\xff"
+                          "\xff\xff\xff\xff\xff\xff\xff\xff"
+                          "\xff\xff\xff\xff\xff\xff\xff\xff"
+                          "\xff\xff\xff\xff\xff\xff\xff\xff"
+                          "\xff\xff\xff\xff\xff\xff\xff\xff"
+                          "\xff\xff\xff\xff\xff\xff\xff\xff"
+                          "\xff\xff\xff\xff\xff\xff\xff\xff"
+                          "\xff\xff\xff\xff\xff\xff\xff\xff"
+                          "\xff\xff\xff\xff\xff\xff\xff\xff"
+                          "\xff\xff\xff\xff\xff\xff\xff\xff"
+                          "\xff\xff\xff\xff\xff\xff\xff\xff"
+                          "\xff\xff\xff\xff\xff\xff\xff\xff"
+                          "\xff\xff\xff\xff\xff\xff\xff\xff"
+                          "\xff\xff\xff\xff\xff\xff\xff\xff"
+                          "\xff\xff\xff\xff\xff\xff\xff\xff",
+                .rlen   = 192,
+
+	}
+};
+
 static struct aead_testvec aes_ccm_enc_tv_template[] = {
 	{ /* From RFC 3610 */
 		.key	= "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7"
diff -druNp linux-libre-2.6.37-gnu1/crypto/zlib.c linux-libre-2.6.38-gnu1/crypto/zlib.c
--- linux-libre-2.6.37-gnu1/crypto/zlib.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/crypto/zlib.c	2011-03-14 21:20:32.000000000 -0400
@@ -95,11 +95,10 @@ static int zlib_compress_setup(struct cr
 	zlib_comp_exit(ctx);
 
 	workspacesize = zlib_deflate_workspacesize();
-	stream->workspace = vmalloc(workspacesize);
+	stream->workspace = vzalloc(workspacesize);
 	if (!stream->workspace)
 		return -ENOMEM;
 
-	memset(stream->workspace, 0, workspacesize);
 	ret = zlib_deflateInit2(stream,
 				tb[ZLIB_COMP_LEVEL]
 					? nla_get_u32(tb[ZLIB_COMP_LEVEL])
diff -druNp linux-libre-2.6.37-gnu1/Documentation/ABI/stable/thermal-notification linux-libre-2.6.38-gnu1/Documentation/ABI/stable/thermal-notification
--- linux-libre-2.6.37-gnu1/Documentation/ABI/stable/thermal-notification	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/ABI/stable/thermal-notification	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,4 @@
+What:		A notification mechanism for thermal related events
+Description:
+	This interface enables notification for thermal related events.
+	The notification is in the form of a netlink event.
diff -druNp linux-libre-2.6.37-gnu1/Documentation/ABI/testing/sysfs-class-led linux-libre-2.6.38-gnu1/Documentation/ABI/testing/sysfs-class-led
--- linux-libre-2.6.37-gnu1/Documentation/ABI/testing/sysfs-class-led	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/ABI/testing/sysfs-class-led	2011-03-14 21:20:32.000000000 -0400
@@ -26,3 +26,12 @@ Description:
 		scheduler is chosen. Trigger specific parameters can appear in
 		/sys/class/leds/<led> once a given trigger is selected.
 
+What:		/sys/class/leds/<led>/inverted
+Date:		January 2011
+KernelVersion:	2.6.38
+Contact:	Richard Purdie <rpurdie@rpsys.net>
+Description:
+		Invert the LED on/off state. This parameter is specific to
+		gpio and backlight triggers. In case of the backlight trigger,
+		it is usefull when driving a LED which is intended to indicate
+		a device in a standby like state.
diff -druNp linux-libre-2.6.37-gnu1/Documentation/ABI/testing/sysfs-class-net-batman-adv linux-libre-2.6.38-gnu1/Documentation/ABI/testing/sysfs-class-net-batman-adv
--- linux-libre-2.6.37-gnu1/Documentation/ABI/testing/sysfs-class-net-batman-adv	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/ABI/testing/sysfs-class-net-batman-adv	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,14 @@
+
+What:           /sys/class/net/<iface>/batman-adv/mesh_iface
+Date:           May 2010
+Contact:        Marek Lindner <lindner_marek@yahoo.de>
+Description:
+                The /sys/class/net/<iface>/batman-adv/mesh_iface file
+                displays the batman mesh interface this <iface>
+                currently is associated with.
+
+What:           /sys/class/net/<iface>/batman-adv/iface_status
+Date:           May 2010
+Contact:        Marek Lindner <lindner_marek@yahoo.de>
+Description:
+                Indicates the status of <iface> as it is seen by batman.
diff -druNp linux-libre-2.6.37-gnu1/Documentation/ABI/testing/sysfs-class-net-mesh linux-libre-2.6.38-gnu1/Documentation/ABI/testing/sysfs-class-net-mesh
--- linux-libre-2.6.37-gnu1/Documentation/ABI/testing/sysfs-class-net-mesh	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/ABI/testing/sysfs-class-net-mesh	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,69 @@
+
+What:           /sys/class/net/<mesh_iface>/mesh/aggregated_ogms
+Date:           May 2010
+Contact:        Marek Lindner <lindner_marek@yahoo.de>
+Description:
+                Indicates whether the batman protocol messages of the
+                mesh <mesh_iface> shall be aggregated or not.
+
+What:           /sys/class/net/<mesh_iface>/mesh/bonding
+Date:           June 2010
+Contact:        Simon Wunderlich <siwu@hrz.tu-chemnitz.de>
+Description:
+                Indicates whether the data traffic going through the
+                mesh will be sent using multiple interfaces at the
+                same time (if available).
+
+What:           /sys/class/net/<mesh_iface>/mesh/fragmentation
+Date:           October 2010
+Contact:        Andreas Langer <an.langer@gmx.de>
+Description:
+                Indicates whether the data traffic going through the
+                mesh will be fragmented or silently discarded if the
+                packet size exceeds the outgoing interface MTU.
+
+What:           /sys/class/net/<mesh_iface>/mesh/gw_bandwidth
+Date:           October 2010
+Contact:        Marek Lindner <lindner_marek@yahoo.de>
+Description:
+                Defines the bandwidth which is propagated by this
+                node if gw_mode was set to 'server'.
+
+What:           /sys/class/net/<mesh_iface>/mesh/gw_mode
+Date:           October 2010
+Contact:        Marek Lindner <lindner_marek@yahoo.de>
+Description:
+                Defines the state of the gateway features. Can be
+                either 'off', 'client' or 'server'.
+
+What:           /sys/class/net/<mesh_iface>/mesh/gw_sel_class
+Date:           October 2010
+Contact:        Marek Lindner <lindner_marek@yahoo.de>
+Description:
+                Defines the selection criteria this node will use
+                to choose a gateway if gw_mode was set to 'client'.
+
+What:           /sys/class/net/<mesh_iface>/mesh/orig_interval
+Date:           May 2010
+Contact:        Marek Lindner <lindner_marek@yahoo.de>
+Description:
+                Defines the interval in milliseconds in which batman
+                sends its protocol messages.
+
+What:           /sys/class/net/<mesh_iface>/mesh/hop_penalty
+Date:           Oct 2010
+Contact:        Linus Lüssing <linus.luessing@web.de>
+Description:
+		Defines the penalty which will be applied to an
+		originator message's tq-field on every hop.
+
+What:           /sys/class/net/<mesh_iface>/mesh/vis_mode
+Date:           May 2010
+Contact:        Marek Lindner <lindner_marek@yahoo.de>
+Description:
+                Each batman node only maintains information about its
+                own local neighborhood, therefore generating graphs
+                showing the topology of the entire mesh is not easily
+                feasible without having a central instance to collect
+                the local topologies from all nodes. This file allows
+                to activate the collecting (server) mode.
diff -druNp linux-libre-2.6.37-gnu1/Documentation/ABI/testing/sysfs-driver-hid-roccat-kone linux-libre-2.6.38-gnu1/Documentation/ABI/testing/sysfs-driver-hid-roccat-kone
--- linux-libre-2.6.37-gnu1/Documentation/ABI/testing/sysfs-driver-hid-roccat-kone	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/ABI/testing/sysfs-driver-hid-roccat-kone	2011-03-14 21:20:32.000000000 -0400
@@ -1,4 +1,4 @@
-What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/actual_dpi
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kone/roccatkone<minor>/actual_dpi
 Date:		March 2010
 Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
 Description:	It is possible to switch the dpi setting of the mouse with the
@@ -17,13 +17,13 @@ Description:	It is possible to switch th
 
 		This file is readonly.
 
-What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/actual_profile
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kone/roccatkone<minor>/actual_profile
 Date:		March 2010
 Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
 Description:	When read, this file returns the number of the actual profile.
 		This file is readonly.
 
-What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/firmware_version
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kone/roccatkone<minor>/firmware_version
 Date:		March 2010
 Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
 Description:	When read, this file returns the raw integer version number of the
@@ -33,7 +33,7 @@ Description:	When read, this file return
 		left. E.g. a returned value of 138 means 1.38
 		This file is readonly.
 
-What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/profile[1-5]
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kone/roccatkone<minor>/profile[1-5]
 Date:		March 2010
 Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
 Description:	The mouse can store 5 profiles which can be switched by the
@@ -48,7 +48,7 @@ Description:	The mouse can store 5 profi
 		stored in the profile doesn't need to fit the number of the
 		store.
 
-What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/settings
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kone/roccatkone<minor>/settings
 Date:		March 2010
 Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
 Description:	When read, this file returns the settings stored in the mouse.
@@ -58,7 +58,7 @@ Description:	When read, this file return
 		The data has to be 36 bytes long. The mouse will reject invalid
 		data.
 
-What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/startup_profile
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kone/roccatkone<minor>/startup_profile
 Date:		March 2010
 Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
 Description:	The integer value of this attribute ranges from 1 to 5.
@@ -67,7 +67,7 @@ Description:	The integer value of this a
 		When written, this file sets the number of the startup profile
 		and the mouse activates this profile immediately.
 
-What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/tcu
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kone/roccatkone<minor>/tcu
 Date:		March 2010
 Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
 Description:	The mouse has a "Tracking Control Unit" which lets the user
@@ -78,7 +78,7 @@ Description:	The mouse has a "Tracking C
 		Writing 1 in this file will start the calibration which takes
 		around 6 seconds to complete and activates the TCU.
 
-What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/weight
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kone/roccatkone<minor>/weight
 Date:		March 2010
 Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
 Description:	The mouse can be equipped with one of four supplied weights
diff -druNp linux-libre-2.6.37-gnu1/Documentation/ABI/testing/sysfs-driver-hid-roccat-koneplus linux-libre-2.6.38-gnu1/Documentation/ABI/testing/sysfs-driver-hid-roccat-koneplus
--- linux-libre-2.6.37-gnu1/Documentation/ABI/testing/sysfs-driver-hid-roccat-koneplus	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/ABI/testing/sysfs-driver-hid-roccat-koneplus	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,108 @@
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/actual_profile
+Date:		October 2010
+Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:	When read, this file returns the number of the actual profile in
+		range 0-4.
+		This file is readonly.
+
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/firmware_version
+Date:		October 2010
+Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:	When read, this file returns the raw integer version number of the
+		firmware reported by the mouse. Using the integer value eases
+		further usage in other programs. To receive the real version
+		number the decimal point has to be shifted 2 positions to the
+		left. E.g. a returned value of 121 means 1.21
+		This file is readonly.
+
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/macro
+Date:		October 2010
+Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:	The mouse can store a macro with max 500 key/button strokes
+		internally.
+		When written, this file lets one set the sequence for a specific
+		button for a specific profile. Button and profile numbers are
+		included in written data. The data has to be 2082 bytes long.
+		This file is writeonly.
+
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/profile_buttons
+Date:		August 2010
+Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:	The mouse can store 5 profiles which can be switched by the
+		press of a button. A profile is split in settings and buttons.
+		profile_buttons holds informations about button layout.
+		When written, this file lets one write the respective profile
+		buttons back to the mouse. The data has to be 77 bytes long.
+		The mouse will reject invalid data.
+		Which profile to write is determined by the profile number
+		contained in the data.
+		This file is writeonly.
+
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/profile[1-5]_buttons
+Date:		August 2010
+Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:	The mouse can store 5 profiles which can be switched by the
+		press of a button. A profile is split in settings and buttons.
+		profile_buttons holds informations about button layout.
+		When read, these files return the respective profile buttons.
+		The returned data is 77 bytes in size.
+		This file is readonly.
+
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/profile_settings
+Date:		October 2010
+Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:	The mouse can store 5 profiles which can be switched by the
+		press of a button. A profile is split in settings and buttons.
+		profile_settings holds informations like resolution, sensitivity
+		and light effects.
+		When written, this file lets one write the respective profile
+		settings back to the mouse. The data has to be 43 bytes long.
+		The mouse will reject invalid data.
+		Which profile to write is determined by the profile number
+		contained in the data.
+		This file is writeonly.
+
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/profile[1-5]_settings
+Date:		August 2010
+Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:	The mouse can store 5 profiles which can be switched by the
+		press of a button. A profile is split in settings and buttons.
+		profile_settings holds informations like resolution, sensitivity
+		and light effects.
+		When read, these files return the respective profile settings.
+		The returned data is 43 bytes in size.
+		This file is readonly.
+
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/sensor
+Date:		October 2010
+Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:	The mouse has a tracking- and a distance-control-unit. These
+		can be activated/deactivated and the lift-off distance can be
+		set. The data has to be 6 bytes long.
+		This file is writeonly.
+
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/startup_profile
+Date:		October 2010
+Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:	The integer value of this attribute ranges from 0-4.
+                When read, this attribute returns the number of the profile
+                that's active when the mouse is powered on.
+		When written, this file sets the number of the startup profile
+		and the mouse activates this profile immediately.
+
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/tcu
+Date:		October 2010
+Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:	When written a calibration process for the tracking control unit
+		can be initiated/cancelled.
+		The data has to be 3 bytes long.
+		This file is writeonly.
+
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/tcu_image
+Date:		October 2010
+Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:	When read the mouse returns a 30x30 pixel image of the
+		sampled underground. This works only in the course of a
+		calibration process initiated with tcu.
+		The returned data is 1028 bytes in size.
+		This file is readonly.
diff -druNp linux-libre-2.6.37-gnu1/Documentation/ABI/testing/sysfs-driver-hid-roccat-pyra linux-libre-2.6.38-gnu1/Documentation/ABI/testing/sysfs-driver-hid-roccat-pyra
--- linux-libre-2.6.37-gnu1/Documentation/ABI/testing/sysfs-driver-hid-roccat-pyra	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/ABI/testing/sysfs-driver-hid-roccat-pyra	2011-03-14 21:20:32.000000000 -0400
@@ -1,4 +1,4 @@
-What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/actual_cpi
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/actual_cpi
 Date:		August 2010
 Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
 Description:	It is possible to switch the cpi setting of the mouse with the
@@ -14,14 +14,14 @@ Description:	It is possible to switch th
 
 		This file is readonly.
 
-What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/actual_profile
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/actual_profile
 Date:		August 2010
 Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
 Description:	When read, this file returns the number of the actual profile in
 		range 0-4.
 		This file is readonly.
 
-What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/firmware_version
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/firmware_version
 Date:		August 2010
 Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
 Description:	When read, this file returns the raw integer version number of the
@@ -31,7 +31,7 @@ Description:	When read, this file return
 		left. E.g. a returned value of 138 means 1.38
 		This file is readonly.
 
-What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/profile_settings
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/profile_settings
 Date:		August 2010
 Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
 Description:	The mouse can store 5 profiles which can be switched by the
@@ -45,7 +45,7 @@ Description:	The mouse can store 5 profi
 		contained in the data.
 		This file is writeonly.
 
-What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/profile[1-5]_settings
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/profile[1-5]_settings
 Date:		August 2010
 Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
 Description:	The mouse can store 5 profiles which can be switched by the
@@ -56,7 +56,7 @@ Description:	The mouse can store 5 profi
 		The returned data is 13 bytes in size.
 		This file is readonly.
 
-What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/profile_buttons
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/profile_buttons
 Date:		August 2010
 Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
 Description:	The mouse can store 5 profiles which can be switched by the
@@ -69,7 +69,7 @@ Description:	The mouse can store 5 profi
 		contained in the data.
 		This file is writeonly.
 
-What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/profile[1-5]_buttons
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/profile[1-5]_buttons
 Date:		August 2010
 Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
 Description:	The mouse can store 5 profiles which can be switched by the
@@ -79,7 +79,7 @@ Description:	The mouse can store 5 profi
 		The returned data is 19 bytes in size.
 		This file is readonly.
 
-What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/startup_profile
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/startup_profile
 Date:		August 2010
 Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
 Description:	The integer value of this attribute ranges from 0-4.
@@ -87,7 +87,7 @@ Description:	The integer value of this a
                 that's active when the mouse is powered on.
 		This file is readonly.
 
-What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/settings
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/settings
 Date:		August 2010
 Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
 Description:	When read, this file returns the settings stored in the mouse.
diff -druNp linux-libre-2.6.37-gnu1/Documentation/ABI/testing/sysfs-platform-at91 linux-libre-2.6.38-gnu1/Documentation/ABI/testing/sysfs-platform-at91
--- linux-libre-2.6.37-gnu1/Documentation/ABI/testing/sysfs-platform-at91	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/ABI/testing/sysfs-platform-at91	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,25 @@
+What:		/sys/devices/platform/at91_can/net/<iface>/mb0_id
+Date:		January 2011
+KernelVersion:	2.6.38
+Contact:	Marc Kleine-Budde <kernel@pengutronix.de>
+Description:
+		Value representing the can_id of mailbox 0.
+
+		Default: 0x7ff (standard frame)
+
+		Due to a chip bug (errata 50.2.6.3 & 50.3.5.3 in
+		"AT91SAM9263 Preliminary 6249H-ATARM-27-Jul-09") the
+		contents of mailbox 0 may be send under certain
+		conditions (even if disabled or in rx mode).
+
+		The workaround in the errata suggests not to use the
+		mailbox and load it with an unused identifier.
+
+		In order to use an extended can_id add the
+		CAN_EFF_FLAG (0x80000000U) to the can_id. Example:
+
+		- standard id 0x7ff:
+		echo 0x7ff      > /sys/class/net/can0/mb0_id
+
+		- extended id 0x1fffffff:
+		echo 0x9fffffff > /sys/class/net/can0/mb0_id
diff -druNp linux-libre-2.6.37-gnu1/Documentation/ABI/testing/sysfs-platform-ideapad-laptop linux-libre-2.6.38-gnu1/Documentation/ABI/testing/sysfs-platform-ideapad-laptop
--- linux-libre-2.6.37-gnu1/Documentation/ABI/testing/sysfs-platform-ideapad-laptop	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/ABI/testing/sysfs-platform-ideapad-laptop	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,6 @@
+What:		/sys/devices/platform/ideapad/camera_power
+Date:		Dec 2010
+KernelVersion:	2.6.37
+Contact:	"Ike Panhc <ike.pan@canonical.com>"
+Description:
+		Control the power of camera module. 1 means on, 0 means off.
diff -druNp linux-libre-2.6.37-gnu1/Documentation/ABI/testing/sysfs-tty linux-libre-2.6.38-gnu1/Documentation/ABI/testing/sysfs-tty
--- linux-libre-2.6.37-gnu1/Documentation/ABI/testing/sysfs-tty	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/ABI/testing/sysfs-tty	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,19 @@
+What:		/sys/class/tty/console/active
+Date:		Nov 2010
+Contact:	Kay Sievers <kay.sievers@vrfy.org>
+Description:
+		 Shows the list of currently configured
+		 console devices, like 'tty1 ttyS0'.
+		 The last entry in the file is the active
+		 device connected to /dev/console.
+		 The file supports poll() to detect virtual
+		 console switches.
+
+What:		/sys/class/tty/tty0/active
+Date:		Nov 2010
+Contact:	Kay Sievers <kay.sievers@vrfy.org>
+Description:
+		 Shows the currently active virtual console
+		 device, like 'tty1'.
+		 The file supports poll() to detect virtual
+		 console switches.
diff -druNp linux-libre-2.6.37-gnu1/Documentation/acpi/apei/output_format.txt linux-libre-2.6.38-gnu1/Documentation/acpi/apei/output_format.txt
--- linux-libre-2.6.37-gnu1/Documentation/acpi/apei/output_format.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/acpi/apei/output_format.txt	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,122 @@
+                     APEI output format
+                     ~~~~~~~~~~~~~~~~~~
+
+APEI uses printk as hardware error reporting interface, the output
+format is as follow.
+
+<error record> :=
+APEI generic hardware error status
+severity: <integer>, <severity string>
+section: <integer>, severity: <integer>, <severity string>
+flags: <integer>
+<section flags strings>
+fru_id: <uuid string>
+fru_text: <string>
+section_type: <section type string>
+<section data>
+
+<severity string>* := recoverable | fatal | corrected | info
+
+<section flags strings># :=
+[primary][, containment warning][, reset][, threshold exceeded]\
+[, resource not accessible][, latent error]
+
+<section type string> := generic processor error | memory error | \
+PCIe error | unknown, <uuid string>
+
+<section data> :=
+<generic processor section data> | <memory section data> | \
+<pcie section data> | <null>
+
+<generic processor section data> :=
+[processor_type: <integer>, <proc type string>]
+[processor_isa: <integer>, <proc isa string>]
+[error_type: <integer>
+<proc error type strings>]
+[operation: <integer>, <proc operation string>]
+[flags: <integer>
+<proc flags strings>]
+[level: <integer>]
+[version_info: <integer>]
+[processor_id: <integer>]
+[target_address: <integer>]
+[requestor_id: <integer>]
+[responder_id: <integer>]
+[IP: <integer>]
+
+<proc type string>* := IA32/X64 | IA64
+
+<proc isa string>* := IA32 | IA64 | X64
+
+<processor error type strings># :=
+[cache error][, TLB error][, bus error][, micro-architectural error]
+
+<proc operation string>* := unknown or generic | data read | data write | \
+instruction execution
+
+<proc flags strings># :=
+[restartable][, precise IP][, overflow][, corrected]
+
+<memory section data> :=
+[error_status: <integer>]
+[physical_address: <integer>]
+[physical_address_mask: <integer>]
+[node: <integer>]
+[card: <integer>]
+[module: <integer>]
+[bank: <integer>]
+[device: <integer>]
+[row: <integer>]
+[column: <integer>]
+[bit_position: <integer>]
+[requestor_id: <integer>]
+[responder_id: <integer>]
+[target_id: <integer>]
+[error_type: <integer>, <mem error type string>]
+
+<mem error type string>* :=
+unknown | no error | single-bit ECC | multi-bit ECC | \
+single-symbol chipkill ECC | multi-symbol chipkill ECC | master abort | \
+target abort | parity error | watchdog timeout | invalid address | \
+mirror Broken | memory sparing | scrub corrected error | \
+scrub uncorrected error
+
+<pcie section data> :=
+[port_type: <integer>, <pcie port type string>]
+[version: <integer>.<integer>]
+[command: <integer>, status: <integer>]
+[device_id: <integer>:<integer>:<integer>.<integer>
+slot: <integer>
+secondary_bus: <integer>
+vendor_id: <integer>, device_id: <integer>
+class_code: <integer>]
+[serial number: <integer>, <integer>]
+[bridge: secondary_status: <integer>, control: <integer>]
+
+<pcie port type string>* := PCIe end point | legacy PCI end point | \
+unknown | unknown | root port | upstream switch port | \
+downstream switch port | PCIe to PCI/PCI-X bridge | \
+PCI/PCI-X to PCIe bridge | root complex integrated endpoint device | \
+root complex event collector
+
+Where, [] designate corresponding content is optional
+
+All <field string> description with * has the following format:
+
+field: <integer>, <field string>
+
+Where value of <integer> should be the position of "string" in <field
+string> description. Otherwise, <field string> will be "unknown".
+
+All <field strings> description with # has the following format:
+
+field: <integer>
+<field strings>
+
+Where each string in <fields strings> corresponding to one set bit of
+<integer>. The bit position is the position of "string" in <field
+strings> description.
+
+For more detailed explanation of every field, please refer to UEFI
+specification version 2.3 or later, section Appendix N: Common
+Platform Error Record.
diff -druNp linux-libre-2.6.37-gnu1/Documentation/arm/00-INDEX linux-libre-2.6.38-gnu1/Documentation/arm/00-INDEX
--- linux-libre-2.6.37-gnu1/Documentation/arm/00-INDEX	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/arm/00-INDEX	2011-03-14 21:20:32.000000000 -0400
@@ -34,3 +34,5 @@ memory.txt
 	- description of the virtual memory layout
 nwfpe/
 	- NWFPE floating point emulator documentation
+swp_emulation
+	- SWP/SWPB emulation handler/logging description
diff -druNp linux-libre-2.6.37-gnu1/Documentation/arm/OMAP/omap_pm linux-libre-2.6.38-gnu1/Documentation/arm/OMAP/omap_pm
--- linux-libre-2.6.37-gnu1/Documentation/arm/OMAP/omap_pm	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/arm/OMAP/omap_pm	2011-03-14 21:20:32.000000000 -0400
@@ -127,3 +127,28 @@ implementation needs:
 10. (*pdata->cpu_set_freq)(unsigned long f)
 
 11. (*pdata->cpu_get_freq)(void)
+
+Customizing OPP for platform
+============================
+Defining CONFIG_PM should enable OPP layer for the silicon
+and the registration of OPP table should take place automatically.
+However, in special cases, the default OPP table may need to be
+tweaked, for e.g.:
+ * enable default OPPs which are disabled by default, but which
+   could be enabled on a platform
+ * Disable an unsupported OPP on the platform
+ * Define and add a custom opp table entry
+in these cases, the board file needs to do additional steps as follows:
+arch/arm/mach-omapx/board-xyz.c
+	#include "pm.h"
+	....
+	static void __init omap_xyz_init_irq(void)
+	{
+		....
+		/* Initialize the default table */
+		omapx_opp_init();
+		/* Do customization to the defaults */
+		....
+	}
+NOTE: omapx_opp_init will be omap3_opp_init or as required
+based on the omap family.
diff -druNp linux-libre-2.6.37-gnu1/Documentation/arm/swp_emulation linux-libre-2.6.38-gnu1/Documentation/arm/swp_emulation
--- linux-libre-2.6.37-gnu1/Documentation/arm/swp_emulation	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/arm/swp_emulation	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,27 @@
+Software emulation of deprecated SWP instruction (CONFIG_SWP_EMULATE)
+---------------------------------------------------------------------
+
+ARMv6 architecture deprecates use of the SWP/SWPB instructions, and recommeds
+moving to the load-locked/store-conditional instructions LDREX and STREX.
+
+ARMv7 multiprocessing extensions introduce the ability to disable these
+instructions, triggering an undefined instruction exception when executed.
+Trapped instructions are emulated using an LDREX/STREX or LDREXB/STREXB
+sequence. If a memory access fault (an abort) occurs, a segmentation fault is
+signalled to the triggering process.
+
+/proc/cpu/swp_emulation holds some statistics/information, including the PID of
+the last process to trigger the emulation to be invocated. For example:
+---
+Emulated SWP:		12
+Emulated SWPB:		0
+Aborted SWP{B}:		1
+Last process:		314
+---
+
+NOTE: when accessing uncached shared regions, LDREX/STREX rely on an external
+transaction monitoring block called a global monitor to maintain update
+atomicity. If your system does not implement a global monitor, this option can
+cause programs that perform SWP operations to uncached memory to deadlock, as
+the STREX operation will always fail.
+
diff -druNp linux-libre-2.6.37-gnu1/Documentation/cgroups/blkio-controller.txt linux-libre-2.6.38-gnu1/Documentation/cgroups/blkio-controller.txt
--- linux-libre-2.6.37-gnu1/Documentation/cgroups/blkio-controller.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/cgroups/blkio-controller.txt	2011-03-14 21:20:32.000000000 -0400
@@ -89,6 +89,33 @@ Throttling/Upper Limit policy
 
  Limits for writes can be put using blkio.write_bps_device file.
 
+Hierarchical Cgroups
+====================
+- Currently none of the IO control policy supports hierarhical groups. But
+  cgroup interface does allow creation of hierarhical cgroups and internally
+  IO policies treat them as flat hierarchy.
+
+  So this patch will allow creation of cgroup hierarhcy but at the backend
+  everything will be treated as flat. So if somebody created a hierarchy like
+  as follows.
+
+			root
+			/  \
+		     test1 test2
+			|
+		     test3
+
+  CFQ and throttling will practically treat all groups at same level.
+
+				pivot
+			     /  |   \  \
+			root  test1 test2  test3
+
+  Down the line we can implement hierarchical accounting/control support
+  and also introduce a new cgroup file "use_hierarchy" which will control
+  whether cgroup hierarchy is viewed as flat or hierarchical by the policy..
+  This is how memory controller also has implemented the things.
+
 Various user visible config options
 ===================================
 CONFIG_BLK_CGROUP
diff -druNp linux-libre-2.6.37-gnu1/Documentation/cgroups/cgroup_event_listener.c linux-libre-2.6.38-gnu1/Documentation/cgroups/cgroup_event_listener.c
--- linux-libre-2.6.37-gnu1/Documentation/cgroups/cgroup_event_listener.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/cgroups/cgroup_event_listener.c	2011-03-14 21:20:32.000000000 -0400
@@ -91,7 +91,7 @@ int main(int argc, char **argv)
 
 		if (ret == -1) {
 			perror("cgroup.event_control "
-					"is not accessable any more");
+					"is not accessible any more");
 			break;
 		}
 
diff -druNp linux-libre-2.6.37-gnu1/Documentation/cgroups/cgroups.txt linux-libre-2.6.38-gnu1/Documentation/cgroups/cgroups.txt
--- linux-libre-2.6.37-gnu1/Documentation/cgroups/cgroups.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/cgroups/cgroups.txt	2011-03-14 21:20:32.000000000 -0400
@@ -355,13 +355,13 @@ subsystems, type:
 
 To change the set of subsystems bound to a mounted hierarchy, just
 remount with different options:
-# mount -o remount,cpuset,ns hier1 /dev/cgroup
+# mount -o remount,cpuset,blkio hier1 /dev/cgroup
 
-Now memory is removed from the hierarchy and ns is added.
+Now memory is removed from the hierarchy and blkio is added.
 
-Note this will add ns to the hierarchy but won't remove memory or
+Note this will add blkio to the hierarchy but won't remove memory or
 cpuset, because the new options are appended to the old ones:
-# mount -o remount,ns /dev/cgroup
+# mount -o remount,blkio /dev/cgroup
 
 To Specify a hierarchy's release_agent:
 # mount -t cgroup -o cpuset,release_agent="/sbin/cpuset_release_agent" \
diff -druNp linux-libre-2.6.37-gnu1/Documentation/cgroups/memcg_test.txt linux-libre-2.6.38-gnu1/Documentation/cgroups/memcg_test.txt
--- linux-libre-2.6.37-gnu1/Documentation/cgroups/memcg_test.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/cgroups/memcg_test.txt	2011-03-14 21:20:32.000000000 -0400
@@ -398,7 +398,7 @@ Under below explanation, we assume CONFI
 	written to move_charge_at_immigrate.
 
  9.10 Memory thresholds
-	Memory controler implements memory thresholds using cgroups notification
+	Memory controller implements memory thresholds using cgroups notification
 	API. You can use Documentation/cgroups/cgroup_event_listener.c to test
 	it.
 
diff -druNp linux-libre-2.6.37-gnu1/Documentation/coccinelle.txt linux-libre-2.6.38-gnu1/Documentation/coccinelle.txt
--- linux-libre-2.6.37-gnu1/Documentation/coccinelle.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/coccinelle.txt	2011-03-14 21:20:32.000000000 -0400
@@ -36,6 +36,10 @@ as a regular user, and install it with
 
         sudo make install
 
+The semantic patches in the kernel will work best with Coccinelle version
+0.2.4 or later.  Using earlier versions may incur some parse errors in the
+semantic patch code, but any results that are obtained should still be
+correct.
 
  Using Coccinelle on the Linux kernel
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff -druNp linux-libre-2.6.37-gnu1/Documentation/device-mapper/dm-crypt.txt linux-libre-2.6.38-gnu1/Documentation/device-mapper/dm-crypt.txt
--- linux-libre-2.6.37-gnu1/Documentation/device-mapper/dm-crypt.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/device-mapper/dm-crypt.txt	2011-03-14 21:20:32.000000000 -0400
@@ -8,7 +8,7 @@ Parameters: <cipher> <key> <iv_offset> <
 
 <cipher>
     Encryption cipher and an optional IV generation mode.
-    (In format cipher-chainmode-ivopts:ivmode).
+    (In format cipher[:keycount]-chainmode-ivopts:ivmode).
     Examples:
        des
        aes-cbc-essiv:sha256
@@ -20,6 +20,11 @@ Parameters: <cipher> <key> <iv_offset> <
     Key used for encryption. It is encoded as a hexadecimal number.
     You can only use key sizes that are valid for the selected cipher.
 
+<keycount>
+    Multi-key compatibility mode. You can define <keycount> keys and
+    then sectors are encrypted according to their offsets (sector 0 uses key0;
+    sector 1 uses key1 etc.).  <keycount> must be a power of two.
+
 <iv_offset>
     The IV offset is a sector count that is added to the sector number
     before creating the IV.
diff -druNp linux-libre-2.6.37-gnu1/Documentation/device-mapper/dm-raid.txt linux-libre-2.6.38-gnu1/Documentation/device-mapper/dm-raid.txt
--- linux-libre-2.6.37-gnu1/Documentation/device-mapper/dm-raid.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/device-mapper/dm-raid.txt	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,70 @@
+Device-mapper RAID (dm-raid) is a bridge from DM to MD.  It
+provides a way to use device-mapper interfaces to access the MD RAID
+drivers.
+
+As with all device-mapper targets, the nominal public interfaces are the
+constructor (CTR) tables and the status outputs (both STATUSTYPE_INFO
+and STATUSTYPE_TABLE).  The CTR table looks like the following:
+
+1: <s> <l> raid \
+2:      <raid_type> <#raid_params> <raid_params> \
+3:      <#raid_devs> <meta_dev1> <dev1> .. <meta_devN> <devN>
+
+Line 1 contains the standard first three arguments to any device-mapper
+target - the start, length, and target type fields.  The target type in
+this case is "raid".
+
+Line 2 contains the arguments that define the particular raid
+type/personality/level, the required arguments for that raid type, and
+any optional arguments.  Possible raid types include: raid4, raid5_la,
+raid5_ls, raid5_rs, raid6_zr, raid6_nr, and raid6_nc.  (raid1 is
+planned for the future.)  The list of required and optional parameters
+is the same for all the current raid types.  The required parameters are
+positional, while the optional parameters are given as key/value pairs.
+The possible parameters are as follows:
+ <chunk_size>           Chunk size in sectors.
+ [[no]sync]             Force/Prevent RAID initialization
+ [rebuild <idx>]        Rebuild the drive indicated by the index
+ [daemon_sleep <ms>]    Time between bitmap daemon work to clear bits
+ [min_recovery_rate <kB/sec/disk>]      Throttle RAID initialization
+ [max_recovery_rate <kB/sec/disk>]      Throttle RAID initialization
+ [max_write_behind <sectors>]           See '-write-behind=' (man mdadm)
+ [stripe_cache <sectors>]               Stripe cache size for higher RAIDs
+
+Line 3 contains the list of devices that compose the array in
+metadata/data device pairs.  If the metadata is stored separately, a '-'
+is given for the metadata device position.  If a drive has failed or is
+missing at creation time, a '-' can be given for both the metadata and
+data drives for a given position.
+
+NB. Currently all metadata devices must be specified as '-'.
+
+Examples:
+# RAID4 - 4 data drives, 1 parity
+# No metadata devices specified to hold superblock/bitmap info
+# Chunk size of 1MiB
+# (Lines separated for easy reading)
+0 1960893648 raid \
+        raid4 1 2048 \
+        5 - 8:17 - 8:33 - 8:49 - 8:65 - 8:81
+
+# RAID4 - 4 data drives, 1 parity (no metadata devices)
+# Chunk size of 1MiB, force RAID initialization,
+#       min recovery rate at 20 kiB/sec/disk
+0 1960893648 raid \
+        raid4 4 2048 min_recovery_rate 20 sync\
+        5 - 8:17 - 8:33 - 8:49 - 8:65 - 8:81
+
+Performing a 'dmsetup table' should display the CTR table used to
+construct the mapping (with possible reordering of optional
+parameters).
+
+Performing a 'dmsetup status' will yield information on the state and
+health of the array.  The output is as follows:
+1: <s> <l> raid \
+2:      <raid_type> <#devices> <1 health char for each dev> <resync_ratio>
+
+Line 1 is standard DM output.  Line 2 is best shown by example:
+        0 1960893648 raid raid4 5 AAAAA 2/490221568
+Here we can see the RAID type is raid4, there are 5 devices - all of
+which are 'A'live, and the array is 2/490221568 complete with recovery.
diff -druNp linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/ata/fsl-sata.txt linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/ata/fsl-sata.txt
--- linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/ata/fsl-sata.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/ata/fsl-sata.txt	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,29 @@
+* Freescale 8xxx/3.0 Gb/s SATA nodes
+
+SATA nodes are defined to describe on-chip Serial ATA controllers.
+Each SATA port should have its own node.
+
+Required properties:
+- compatible        : compatible list, contains 2 entries, first is
+		 "fsl,CHIP-sata", where CHIP is the processor
+		 (mpc8315, mpc8379, etc.) and the second is
+		 "fsl,pq-sata"
+- interrupts        : <interrupt mapping for SATA IRQ>
+- cell-index        : controller index.
+                          1 for controller @ 0x18000
+                          2 for controller @ 0x19000
+                          3 for controller @ 0x1a000
+                          4 for controller @ 0x1b000
+
+Optional properties:
+- interrupt-parent  : optional, if needed for interrupt mapping
+- reg               : <registers mapping>
+
+Example:
+	sata@18000 {
+		compatible = "fsl,mpc8379-sata", "fsl,pq-sata";
+		reg = <0x18000 0x1000>;
+		cell-index = <1>;
+		interrupts = <2c 8>;
+		interrupt-parent = < &ipic >;
+	};
diff -druNp linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/eeprom.txt linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/eeprom.txt
--- linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/eeprom.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/eeprom.txt	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,28 @@
+EEPROMs (I2C)
+
+Required properties:
+
+  - compatible : should be "<manufacturer>,<type>"
+		 If there is no specific driver for <manufacturer>, a generic
+		 driver based on <type> is selected. Possible types are:
+		 24c00, 24c01, 24c02, 24c04, 24c08, 24c16, 24c32, 24c64,
+		 24c128, 24c256, 24c512, 24c1024, spd
+
+  - reg : the I2C address of the EEPROM
+
+Optional properties:
+
+  - pagesize : the length of the pagesize for writing. Please consult the
+               manual of your device, that value varies a lot. A wrong value
+	       may result in data loss! If not specified, a safety value of
+	       '1' is used which will be very slow.
+
+  - read-only: this parameterless property disables writes to the eeprom
+
+Example:
+
+eeprom@52 {
+	compatible = "atmel,24c32";
+	reg = <0x52>;
+	pagesize = <32>;
+};
diff -druNp linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/gpio/8xxx_gpio.txt linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/gpio/8xxx_gpio.txt
--- linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/gpio/8xxx_gpio.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/gpio/8xxx_gpio.txt	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,60 @@
+GPIO controllers on MPC8xxx SoCs
+
+This is for the non-QE/CPM/GUTs GPIO controllers as found on
+8349, 8572, 8610 and compatible.
+
+Every GPIO controller node must have #gpio-cells property defined,
+this information will be used to translate gpio-specifiers.
+
+Required properties:
+- compatible : "fsl,<CHIP>-gpio" followed by "fsl,mpc8349-gpio" for
+  83xx, "fsl,mpc8572-gpio" for 85xx and "fsl,mpc8610-gpio" for 86xx.
+- #gpio-cells : Should be two. The first cell is the pin number and the
+  second cell is used to specify optional parameters (currently unused).
+ - interrupts : Interrupt mapping for GPIO IRQ.
+ - interrupt-parent : Phandle for the interrupt controller that
+   services interrupts for this device.
+- gpio-controller : Marks the port as GPIO controller.
+
+Example of gpio-controller nodes for a MPC8347 SoC:
+
+	gpio1: gpio-controller@c00 {
+		#gpio-cells = <2>;
+		compatible = "fsl,mpc8347-gpio", "fsl,mpc8349-gpio";
+		reg = <0xc00 0x100>;
+		interrupts = <74 0x8>;
+		interrupt-parent = <&ipic>;
+		gpio-controller;
+	};
+
+	gpio2: gpio-controller@d00 {
+		#gpio-cells = <2>;
+		compatible = "fsl,mpc8347-gpio", "fsl,mpc8349-gpio";
+		reg = <0xd00 0x100>;
+		interrupts = <75 0x8>;
+		interrupt-parent = <&ipic>;
+		gpio-controller;
+	};
+
+See booting-without-of.txt for details of how to specify GPIO
+information for devices.
+
+To use GPIO pins as interrupt sources for peripherals, specify the
+GPIO controller as the interrupt parent and define GPIO number +
+trigger mode using the interrupts property, which is defined like
+this:
+
+interrupts = <number trigger>, where:
+ - number: GPIO pin (0..31)
+ - trigger: trigger mode:
+	2 = trigger on falling edge
+	3 = trigger on both edges
+
+Example of device using this is:
+
+	funkyfpga@0 {
+		compatible = "funky-fpga";
+		...
+		interrupts = <4 3>;
+		interrupt-parent = <&gpio1>;
+	};
diff -druNp linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/gpio/gpio.txt linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/gpio/gpio.txt
--- linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/gpio/gpio.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/gpio/gpio.txt	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,50 @@
+Specifying GPIO information for devices
+============================================
+
+1) gpios property
+-----------------
+
+Nodes that makes use of GPIOs should define them using `gpios' property,
+format of which is: <&gpio-controller1-phandle gpio1-specifier
+		     &gpio-controller2-phandle gpio2-specifier
+		     0 /* holes are permitted, means no GPIO 3 */
+		     &gpio-controller4-phandle gpio4-specifier
+		     ...>;
+
+Note that gpio-specifier length is controller dependent.
+
+gpio-specifier may encode: bank, pin position inside the bank,
+whether pin is open-drain and whether pin is logically inverted.
+
+Example of the node using GPIOs:
+
+	node {
+		gpios = <&qe_pio_e 18 0>;
+	};
+
+In this example gpio-specifier is "18 0" and encodes GPIO pin number,
+and empty GPIO flags as accepted by the "qe_pio_e" gpio-controller.
+
+2) gpio-controller nodes
+------------------------
+
+Every GPIO controller node must have #gpio-cells property defined,
+this information will be used to translate gpio-specifiers.
+
+Example of two SOC GPIO banks defined as gpio-controller nodes:
+
+	qe_pio_a: gpio-controller@1400 {
+		#gpio-cells = <2>;
+		compatible = "fsl,qe-pario-bank-a", "fsl,qe-pario-bank";
+		reg = <0x1400 0x18>;
+		gpio-controller;
+	};
+
+	qe_pio_e: gpio-controller@1460 {
+		#gpio-cells = <2>;
+		compatible = "fsl,qe-pario-bank-e", "fsl,qe-pario-bank";
+		reg = <0x1460 0x18>;
+		gpio-controller;
+	};
+
+
diff -druNp linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/gpio/led.txt linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/gpio/led.txt
--- linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/gpio/led.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/gpio/led.txt	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,58 @@
+LEDs connected to GPIO lines
+
+Required properties:
+- compatible : should be "gpio-leds".
+
+Each LED is represented as a sub-node of the gpio-leds device.  Each
+node's name represents the name of the corresponding LED.
+
+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
+  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).
+- linux,default-trigger :  (optional) This parameter, if present, is a
+  string defining the trigger assigned to the LED.  Current triggers are:
+    "backlight" - LED will act as a back-light, controlled by the framebuffer
+		  system
+    "default-on" - LED will turn on, but see "default-state" below
+    "heartbeat" - LED "double" flashes at a load average based rate
+    "ide-disk" - LED indicates disk activity
+    "timer" - LED flashes at a fixed, configurable rate
+- default-state:  (optional) The initial state of the LED.  Valid
+  values are "on", "off", and "keep".  If the LED is already on or off
+  and the default-state property is set the to same value, then no
+  glitch should be produced where the LED momentarily turns off (or
+  on).  The "keep" setting will keep the LED at whatever its current
+  state is, without producing a glitch.  The default is off if this
+  property is not present.
+
+Examples:
+
+leds {
+	compatible = "gpio-leds";
+	hdd {
+		label = "IDE Activity";
+		gpios = <&mcu_pio 0 1>; /* Active low */
+		linux,default-trigger = "ide-disk";
+	};
+
+	fault {
+		gpios = <&mcu_pio 1 0>;
+		/* Keep LED on if BIOS detected hardware fault */
+		default-state = "keep";
+	};
+};
+
+run-control {
+	compatible = "gpio-leds";
+	red {
+		gpios = <&mpc8572 6 0>;
+		default-state = "off";
+	};
+	green {
+		gpios = <&mpc8572 7 0>;
+		default-state = "on";
+	};
+}
diff -druNp linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/i2c/fsl-i2c.txt linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/i2c/fsl-i2c.txt
--- linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/i2c/fsl-i2c.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/i2c/fsl-i2c.txt	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,64 @@
+* I2C
+
+Required properties :
+
+ - reg : Offset and length of the register set for the device
+ - compatible : should be "fsl,CHIP-i2c" where CHIP is the name of a
+   compatible processor, e.g. mpc8313, mpc8543, mpc8544, mpc5121,
+   mpc5200 or mpc5200b. For the mpc5121, an additional node
+   "fsl,mpc5121-i2c-ctrl" is required as shown in the example below.
+
+Recommended properties :
+
+ - interrupts : <a b> where a is the interrupt number and b is a
+   field that represents an encoding of the sense and level
+   information for the interrupt.  This should be encoded based on
+   the information in section 2) depending on the type of interrupt
+   controller you have.
+ - interrupt-parent : the phandle for the interrupt controller that
+   services interrupts for this device.
+ - fsl,preserve-clocking : boolean; if defined, the clock settings
+   from the bootloader are preserved (not touched).
+ - clock-frequency : desired I2C bus clock frequency in Hz.
+ - fsl,timeout : I2C bus timeout in microseconds.
+
+Examples :
+
+	/* MPC5121 based board */
+	i2c@1740 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "fsl,mpc5121-i2c", "fsl-i2c";
+		reg = <0x1740 0x20>;
+		interrupts = <11 0x8>;
+		interrupt-parent = <&ipic>;
+		clock-frequency = <100000>;
+	};
+
+	i2ccontrol@1760 {
+		compatible = "fsl,mpc5121-i2c-ctrl";
+		reg = <0x1760 0x8>;
+	};
+
+	/* MPC5200B based board */
+	i2c@3d00 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "fsl,mpc5200b-i2c","fsl,mpc5200-i2c","fsl-i2c";
+		reg = <0x3d00 0x40>;
+		interrupts = <2 15 0>;
+		interrupt-parent = <&mpc5200_pic>;
+		fsl,preserve-clocking;
+	};
+
+	/* MPC8544 base board */
+	i2c@3100 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "fsl,mpc8544-i2c", "fsl-i2c";
+		reg = <0x3100 0x100>;
+		interrupts = <43 2>;
+		interrupt-parent = <&mpic>;
+		clock-frequency = <400000>;
+		fsl,timeout = <10000>;
+	};
diff -druNp linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/marvell.txt linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/marvell.txt
--- linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/marvell.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/marvell.txt	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,521 @@
+Marvell Discovery mv64[345]6x System Controller chips
+===========================================================
+
+The Marvell mv64[345]60 series of system controller chips contain
+many of the peripherals needed to implement a complete computer
+system.  In this section, we define device tree nodes to describe
+the system controller chip itself and each of the peripherals
+which it contains.  Compatible string values for each node are
+prefixed with the string "marvell,", for Marvell Technology Group Ltd.
+
+1) The /system-controller node
+
+  This node is used to represent the system-controller and must be
+  present when the system uses a system controller chip. The top-level
+  system-controller node contains information that is global to all
+  devices within the system controller chip. The node name begins
+  with "system-controller" followed by the unit address, which is
+  the base address of the memory-mapped register set for the system
+  controller chip.
+
+  Required properties:
+
+    - ranges : Describes the translation of system controller addresses
+      for memory mapped registers.
+    - clock-frequency: Contains the main clock frequency for the system
+      controller chip.
+    - reg : This property defines the address and size of the
+      memory-mapped registers contained within the system controller
+      chip.  The address specified in the "reg" property should match
+      the unit address of the system-controller node.
+    - #address-cells : Address representation for system controller
+      devices.  This field represents the number of cells needed to
+      represent the address of the memory-mapped registers of devices
+      within the system controller chip.
+    - #size-cells : Size representation for the memory-mapped
+      registers within the system controller chip.
+    - #interrupt-cells : Defines the width of cells used to represent
+      interrupts.
+
+  Optional properties:
+
+    - model : The specific model of the system controller chip.  Such
+      as, "mv64360", "mv64460", or "mv64560".
+    - compatible : A string identifying the compatibility identifiers
+      of the system controller chip.
+
+  The system-controller node contains child nodes for each system
+  controller device that the platform uses.  Nodes should not be created
+  for devices which exist on the system controller chip but are not used
+
+  Example Marvell Discovery mv64360 system-controller node:
+
+    system-controller@f1000000 { /* Marvell Discovery mv64360 */
+	    #address-cells = <1>;
+	    #size-cells = <1>;
+	    model = "mv64360";                      /* Default */
+	    compatible = "marvell,mv64360";
+	    clock-frequency = <133333333>;
+	    reg = <0xf1000000 0x10000>;
+	    virtual-reg = <0xf1000000>;
+	    ranges = <0x88000000 0x88000000 0x1000000 /* PCI 0 I/O Space */
+		    0x80000000 0x80000000 0x8000000 /* PCI 0 MEM Space */
+		    0xa0000000 0xa0000000 0x4000000 /* User FLASH */
+		    0x00000000 0xf1000000 0x0010000 /* Bridge's regs */
+		    0xf2000000 0xf2000000 0x0040000>;/* Integrated SRAM */
+
+	    [ child node definitions... ]
+    }
+
+2) Child nodes of /system-controller
+
+   a) Marvell Discovery MDIO bus
+
+   The MDIO is a bus to which the PHY devices are connected.  For each
+   device that exists on this bus, a child node should be created.  See
+   the definition of the PHY node below for an example of how to define
+   a PHY.
+
+   Required properties:
+     - #address-cells : Should be <1>
+     - #size-cells : Should be <0>
+     - device_type : Should be "mdio"
+     - compatible : Should be "marvell,mv64360-mdio"
+
+   Example:
+
+     mdio {
+	     #address-cells = <1>;
+	     #size-cells = <0>;
+	     device_type = "mdio";
+	     compatible = "marvell,mv64360-mdio";
+
+	     ethernet-phy@0 {
+		     ......
+	     };
+     };
+
+
+   b) Marvell Discovery ethernet controller
+
+   The Discover ethernet controller is described with two levels
+   of nodes.  The first level describes an ethernet silicon block
+   and the second level describes up to 3 ethernet nodes within
+   that block.  The reason for the multiple levels is that the
+   registers for the node are interleaved within a single set
+   of registers.  The "ethernet-block" level describes the
+   shared register set, and the "ethernet" nodes describe ethernet
+   port-specific properties.
+
+   Ethernet block node
+
+   Required properties:
+     - #address-cells : <1>
+     - #size-cells : <0>
+     - compatible : "marvell,mv64360-eth-block"
+     - reg : Offset and length of the register set for this block
+
+   Example Discovery Ethernet block node:
+     ethernet-block@2000 {
+	     #address-cells = <1>;
+	     #size-cells = <0>;
+	     compatible = "marvell,mv64360-eth-block";
+	     reg = <0x2000 0x2000>;
+	     ethernet@0 {
+		     .......
+	     };
+     };
+
+   Ethernet port node
+
+   Required properties:
+     - device_type : Should be "network".
+     - compatible : Should be "marvell,mv64360-eth".
+     - reg : Should be <0>, <1>, or <2>, according to which registers
+       within the silicon block the device uses.
+     - interrupts : <a> where a is the interrupt number for the port.
+     - interrupt-parent : the phandle for the interrupt controller
+       that services interrupts for this device.
+     - phy : the phandle for the PHY connected to this ethernet
+       controller.
+     - local-mac-address : 6 bytes, MAC address
+
+   Example Discovery Ethernet port node:
+     ethernet@0 {
+	     device_type = "network";
+	     compatible = "marvell,mv64360-eth";
+	     reg = <0>;
+	     interrupts = <32>;
+	     interrupt-parent = <&PIC>;
+	     phy = <&PHY0>;
+	     local-mac-address = [ 00 00 00 00 00 00 ];
+     };
+
+
+
+   c) Marvell Discovery PHY nodes
+
+   Required properties:
+     - device_type : Should be "ethernet-phy"
+     - interrupts : <a> where a is the interrupt number for this phy.
+     - interrupt-parent : the phandle for the interrupt controller that
+       services interrupts for this device.
+     - reg : The ID number for the phy, usually a small integer
+
+   Example Discovery PHY node:
+     ethernet-phy@1 {
+	     device_type = "ethernet-phy";
+	     compatible = "broadcom,bcm5421";
+	     interrupts = <76>;      /* GPP 12 */
+	     interrupt-parent = <&PIC>;
+	     reg = <1>;
+     };
+
+
+   d) Marvell Discovery SDMA nodes
+
+   Represent DMA hardware associated with the MPSC (multiprotocol
+   serial controllers).
+
+   Required properties:
+     - compatible : "marvell,mv64360-sdma"
+     - reg : Offset and length of the register set for this device
+     - interrupts : <a> where a is the interrupt number for the DMA
+       device.
+     - interrupt-parent : the phandle for the interrupt controller
+       that services interrupts for this device.
+
+   Example Discovery SDMA node:
+     sdma@4000 {
+	     compatible = "marvell,mv64360-sdma";
+	     reg = <0x4000 0xc18>;
+	     virtual-reg = <0xf1004000>;
+	     interrupts = <36>;
+	     interrupt-parent = <&PIC>;
+     };
+
+
+   e) Marvell Discovery BRG nodes
+
+   Represent baud rate generator hardware associated with the MPSC
+   (multiprotocol serial controllers).
+
+   Required properties:
+     - compatible : "marvell,mv64360-brg"
+     - reg : Offset and length of the register set for this device
+     - clock-src : A value from 0 to 15 which selects the clock
+       source for the baud rate generator.  This value corresponds
+       to the CLKS value in the BRGx configuration register.  See
+       the mv64x60 User's Manual.
+     - clock-frequence : The frequency (in Hz) of the baud rate
+       generator's input clock.
+     - current-speed : The current speed setting (presumably by
+       firmware) of the baud rate generator.
+
+   Example Discovery BRG node:
+     brg@b200 {
+	     compatible = "marvell,mv64360-brg";
+	     reg = <0xb200 0x8>;
+	     clock-src = <8>;
+	     clock-frequency = <133333333>;
+	     current-speed = <9600>;
+     };
+
+
+   f) Marvell Discovery CUNIT nodes
+
+   Represent the Serial Communications Unit device hardware.
+
+   Required properties:
+     - reg : Offset and length of the register set for this device
+
+   Example Discovery CUNIT node:
+     cunit@f200 {
+	     reg = <0xf200 0x200>;
+     };
+
+
+   g) Marvell Discovery MPSCROUTING nodes
+
+   Represent the Discovery's MPSC routing hardware
+
+   Required properties:
+     - reg : Offset and length of the register set for this device
+
+   Example Discovery CUNIT node:
+     mpscrouting@b500 {
+	     reg = <0xb400 0xc>;
+     };
+
+
+   h) Marvell Discovery MPSCINTR nodes
+
+   Represent the Discovery's MPSC DMA interrupt hardware registers
+   (SDMA cause and mask registers).
+
+   Required properties:
+     - reg : Offset and length of the register set for this device
+
+   Example Discovery MPSCINTR node:
+     mpsintr@b800 {
+	     reg = <0xb800 0x100>;
+     };
+
+
+   i) Marvell Discovery MPSC nodes
+
+   Represent the Discovery's MPSC (Multiprotocol Serial Controller)
+   serial port.
+
+   Required properties:
+     - device_type : "serial"
+     - compatible : "marvell,mv64360-mpsc"
+     - reg : Offset and length of the register set for this device
+     - sdma : the phandle for the SDMA node used by this port
+     - brg : the phandle for the BRG node used by this port
+     - cunit : the phandle for the CUNIT node used by this port
+     - mpscrouting : the phandle for the MPSCROUTING node used by this port
+     - mpscintr : the phandle for the MPSCINTR node used by this port
+     - cell-index : the hardware index of this cell in the MPSC core
+     - max_idle : value needed for MPSC CHR3 (Maximum Frame Length)
+       register
+     - interrupts : <a> where a is the interrupt number for the MPSC.
+     - interrupt-parent : the phandle for the interrupt controller
+       that services interrupts for this device.
+
+   Example Discovery MPSCINTR node:
+     mpsc@8000 {
+	     device_type = "serial";
+	     compatible = "marvell,mv64360-mpsc";
+	     reg = <0x8000 0x38>;
+	     virtual-reg = <0xf1008000>;
+	     sdma = <&SDMA0>;
+	     brg = <&BRG0>;
+	     cunit = <&CUNIT>;
+	     mpscrouting = <&MPSCROUTING>;
+	     mpscintr = <&MPSCINTR>;
+	     cell-index = <0>;
+	     max_idle = <40>;
+	     interrupts = <40>;
+	     interrupt-parent = <&PIC>;
+     };
+
+
+   j) Marvell Discovery Watch Dog Timer nodes
+
+   Represent the Discovery's watchdog timer hardware
+
+   Required properties:
+     - compatible : "marvell,mv64360-wdt"
+     - reg : Offset and length of the register set for this device
+
+   Example Discovery Watch Dog Timer node:
+     wdt@b410 {
+	     compatible = "marvell,mv64360-wdt";
+	     reg = <0xb410 0x8>;
+     };
+
+
+   k) Marvell Discovery I2C nodes
+
+   Represent the Discovery's I2C hardware
+
+   Required properties:
+     - device_type : "i2c"
+     - compatible : "marvell,mv64360-i2c"
+     - reg : Offset and length of the register set for this device
+     - interrupts : <a> where a is the interrupt number for the I2C.
+     - interrupt-parent : the phandle for the interrupt controller
+       that services interrupts for this device.
+
+   Example Discovery I2C node:
+	     compatible = "marvell,mv64360-i2c";
+	     reg = <0xc000 0x20>;
+	     virtual-reg = <0xf100c000>;
+	     interrupts = <37>;
+	     interrupt-parent = <&PIC>;
+     };
+
+
+   l) Marvell Discovery PIC (Programmable Interrupt Controller) nodes
+
+   Represent the Discovery's PIC hardware
+
+   Required properties:
+     - #interrupt-cells : <1>
+     - #address-cells : <0>
+     - compatible : "marvell,mv64360-pic"
+     - reg : Offset and length of the register set for this device
+     - interrupt-controller
+
+   Example Discovery PIC node:
+     pic {
+	     #interrupt-cells = <1>;
+	     #address-cells = <0>;
+	     compatible = "marvell,mv64360-pic";
+	     reg = <0x0 0x88>;
+	     interrupt-controller;
+     };
+
+
+   m) Marvell Discovery MPP (Multipurpose Pins) multiplexing nodes
+
+   Represent the Discovery's MPP hardware
+
+   Required properties:
+     - compatible : "marvell,mv64360-mpp"
+     - reg : Offset and length of the register set for this device
+
+   Example Discovery MPP node:
+     mpp@f000 {
+	     compatible = "marvell,mv64360-mpp";
+	     reg = <0xf000 0x10>;
+     };
+
+
+   n) Marvell Discovery GPP (General Purpose Pins) nodes
+
+   Represent the Discovery's GPP hardware
+
+   Required properties:
+     - compatible : "marvell,mv64360-gpp"
+     - reg : Offset and length of the register set for this device
+
+   Example Discovery GPP node:
+     gpp@f000 {
+	     compatible = "marvell,mv64360-gpp";
+	     reg = <0xf100 0x20>;
+     };
+
+
+   o) Marvell Discovery PCI host bridge node
+
+   Represents the Discovery's PCI host bridge device.  The properties
+   for this node conform to Rev 2.1 of the PCI Bus Binding to IEEE
+   1275-1994.  A typical value for the compatible property is
+   "marvell,mv64360-pci".
+
+   Example Discovery PCI host bridge node
+     pci@80000000 {
+	     #address-cells = <3>;
+	     #size-cells = <2>;
+	     #interrupt-cells = <1>;
+	     device_type = "pci";
+	     compatible = "marvell,mv64360-pci";
+	     reg = <0xcf8 0x8>;
+	     ranges = <0x01000000 0x0        0x0
+			     0x88000000 0x0 0x01000000
+		       0x02000000 0x0 0x80000000
+			     0x80000000 0x0 0x08000000>;
+	     bus-range = <0 255>;
+	     clock-frequency = <66000000>;
+	     interrupt-parent = <&PIC>;
+	     interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+	     interrupt-map = <
+		     /* IDSEL 0x0a */
+		     0x5000 0 0 1 &PIC 80
+		     0x5000 0 0 2 &PIC 81
+		     0x5000 0 0 3 &PIC 91
+		     0x5000 0 0 4 &PIC 93
+
+		     /* IDSEL 0x0b */
+		     0x5800 0 0 1 &PIC 91
+		     0x5800 0 0 2 &PIC 93
+		     0x5800 0 0 3 &PIC 80
+		     0x5800 0 0 4 &PIC 81
+
+		     /* IDSEL 0x0c */
+		     0x6000 0 0 1 &PIC 91
+		     0x6000 0 0 2 &PIC 93
+		     0x6000 0 0 3 &PIC 80
+		     0x6000 0 0 4 &PIC 81
+
+		     /* IDSEL 0x0d */
+		     0x6800 0 0 1 &PIC 93
+		     0x6800 0 0 2 &PIC 80
+		     0x6800 0 0 3 &PIC 81
+		     0x6800 0 0 4 &PIC 91
+	     >;
+     };
+
+
+   p) Marvell Discovery CPU Error nodes
+
+   Represent the Discovery's CPU error handler device.
+
+   Required properties:
+     - compatible : "marvell,mv64360-cpu-error"
+     - reg : Offset and length of the register set for this device
+     - interrupts : the interrupt number for this device
+     - interrupt-parent : the phandle for the interrupt controller
+       that services interrupts for this device.
+
+   Example Discovery CPU Error node:
+     cpu-error@0070 {
+	     compatible = "marvell,mv64360-cpu-error";
+	     reg = <0x70 0x10 0x128 0x28>;
+	     interrupts = <3>;
+	     interrupt-parent = <&PIC>;
+     };
+
+
+   q) Marvell Discovery SRAM Controller nodes
+
+   Represent the Discovery's SRAM controller device.
+
+   Required properties:
+     - compatible : "marvell,mv64360-sram-ctrl"
+     - reg : Offset and length of the register set for this device
+     - interrupts : the interrupt number for this device
+     - interrupt-parent : the phandle for the interrupt controller
+       that services interrupts for this device.
+
+   Example Discovery SRAM Controller node:
+     sram-ctrl@0380 {
+	     compatible = "marvell,mv64360-sram-ctrl";
+	     reg = <0x380 0x80>;
+	     interrupts = <13>;
+	     interrupt-parent = <&PIC>;
+     };
+
+
+   r) Marvell Discovery PCI Error Handler nodes
+
+   Represent the Discovery's PCI error handler device.
+
+   Required properties:
+     - compatible : "marvell,mv64360-pci-error"
+     - reg : Offset and length of the register set for this device
+     - interrupts : the interrupt number for this device
+     - interrupt-parent : the phandle for the interrupt controller
+       that services interrupts for this device.
+
+   Example Discovery PCI Error Handler node:
+     pci-error@1d40 {
+	     compatible = "marvell,mv64360-pci-error";
+	     reg = <0x1d40 0x40 0xc28 0x4>;
+	     interrupts = <12>;
+	     interrupt-parent = <&PIC>;
+     };
+
+
+   s) Marvell Discovery Memory Controller nodes
+
+   Represent the Discovery's memory controller device.
+
+   Required properties:
+     - compatible : "marvell,mv64360-mem-ctrl"
+     - reg : Offset and length of the register set for this device
+     - interrupts : the interrupt number for this device
+     - interrupt-parent : the phandle for the interrupt controller
+       that services interrupts for this device.
+
+   Example Discovery Memory Controller node:
+     mem-ctrl@1400 {
+	     compatible = "marvell,mv64360-mem-ctrl";
+	     reg = <0x1400 0x60>;
+	     interrupts = <17>;
+	     interrupt-parent = <&PIC>;
+     };
+
+
diff -druNp linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/mmc/fsl-esdhc.txt linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/mmc/fsl-esdhc.txt
--- linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/mmc/fsl-esdhc.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/mmc/fsl-esdhc.txt	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,29 @@
+* Freescale Enhanced Secure Digital Host Controller (eSDHC)
+
+The Enhanced Secure Digital Host Controller provides an interface
+for MMC, SD, and SDIO types of memory cards.
+
+Required properties:
+  - compatible : should be
+    "fsl,<chip>-esdhc", "fsl,esdhc"
+  - reg : should contain eSDHC registers location and length.
+  - interrupts : should contain eSDHC interrupt.
+  - interrupt-parent : interrupt source phandle.
+  - clock-frequency : specifies eSDHC base clock frequency.
+  - sdhci,wp-inverted : (optional) specifies that eSDHC controller
+    reports inverted write-protect state;
+  - sdhci,1-bit-only : (optional) specifies that a controller can
+    only handle 1-bit data transfers.
+  - sdhci,auto-cmd12: (optional) specifies that a controller can
+    only handle auto CMD12.
+
+Example:
+
+sdhci@2e000 {
+	compatible = "fsl,mpc8378-esdhc", "fsl,esdhc";
+	reg = <0x2e000 0x1000>;
+	interrupts = <42 0x8>;
+	interrupt-parent = <&ipic>;
+	/* Filled in by U-Boot */
+	clock-frequency = <0>;
+};
diff -druNp linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/mmc/mmc-spi-slot.txt linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/mmc/mmc-spi-slot.txt
--- linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/mmc/mmc-spi-slot.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/mmc/mmc-spi-slot.txt	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,23 @@
+MMC/SD/SDIO slot directly connected to a SPI bus
+
+Required properties:
+- compatible : should be "mmc-spi-slot".
+- reg : should specify SPI address (chip-select number).
+- spi-max-frequency : maximum frequency for this device (Hz).
+- voltage-ranges : two cells are required, first cell specifies minimum
+  slot voltage (mV), second cell specifies maximum slot voltage (mV).
+  Several ranges could be specified.
+- gpios : (optional) may specify GPIOs in this order: Card-Detect GPIO,
+  Write-Protect GPIO.
+
+Example:
+
+	mmc-slot@0 {
+		compatible = "fsl,mpc8323rdb-mmc-slot",
+			     "mmc-spi-slot";
+		reg = <0>;
+		gpios = <&qe_pio_d 14 1
+			 &qe_pio_d 15 0>;
+		voltage-ranges = <3300 3300>;
+		spi-max-frequency = <50000000>;
+	};
diff -druNp linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/mtd/fsl-upm-nand.txt linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/mtd/fsl-upm-nand.txt
--- linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/mtd/fsl-upm-nand.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/mtd/fsl-upm-nand.txt	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,63 @@
+Freescale Localbus UPM programmed to work with NAND flash
+
+Required properties:
+- compatible : "fsl,upm-nand".
+- reg : should specify localbus chip select and size used for the chip.
+- fsl,upm-addr-offset : UPM pattern offset for the address latch.
+- fsl,upm-cmd-offset : UPM pattern offset for the command latch.
+
+Optional properties:
+- fsl,upm-wait-flags : add chip-dependent short delays after running the
+	UPM pattern (0x1), after writing a data byte (0x2) or after
+	writing out a buffer (0x4).
+- fsl,upm-addr-line-cs-offsets : address offsets for multi-chip support.
+	The corresponding address lines are used to select the chip.
+- gpios : may specify optional GPIOs connected to the Ready-Not-Busy pins
+	(R/B#). For multi-chip devices, "n" GPIO definitions are required
+	according to the number of chips.
+- chip-delay : chip dependent delay for transfering data from array to
+	read registers (tR). Required if property "gpios" is not used
+	(R/B# pins not connected).
+
+Examples:
+
+upm@1,0 {
+	compatible = "fsl,upm-nand";
+	reg = <1 0 1>;
+	fsl,upm-addr-offset = <16>;
+	fsl,upm-cmd-offset = <8>;
+	gpios = <&qe_pio_e 18 0>;
+
+	flash {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "...";
+
+		partition@0 {
+			...
+		};
+	};
+};
+
+upm@3,0 {
+	#address-cells = <0>;
+	#size-cells = <0>;
+	compatible = "tqc,tqm8548-upm-nand", "fsl,upm-nand";
+	reg = <3 0x0 0x800>;
+	fsl,upm-addr-offset = <0x10>;
+	fsl,upm-cmd-offset = <0x08>;
+	/* Multi-chip NAND device */
+	fsl,upm-addr-line-cs-offsets = <0x0 0x200>;
+	fsl,upm-wait-flags = <0x5>;
+	chip-delay = <25>; // in micro-seconds
+
+	nand@0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		partition@0 {
+			    label = "fs";
+			    reg = <0x00000000 0x10000000>;
+		};
+	};
+};
diff -druNp linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/mtd/mtd-physmap.txt linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/mtd/mtd-physmap.txt
--- linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/mtd/mtd-physmap.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/mtd/mtd-physmap.txt	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,90 @@
+CFI or JEDEC memory-mapped NOR flash, MTD-RAM (NVRAM...)
+
+Flash chips (Memory Technology Devices) are often used for solid state
+file systems on embedded devices.
+
+ - compatible : should contain the specific model of mtd chip(s)
+   used, if known, followed by either "cfi-flash", "jedec-flash"
+   or "mtd-ram".
+ - reg : Address range(s) of the mtd chip(s)
+   It's possible to (optionally) define multiple "reg" tuples so that
+   non-identical chips can be described in one node.
+ - bank-width : Width (in bytes) of the bank.  Equal to the
+   device width times the number of interleaved chips.
+ - device-width : (optional) Width of a single mtd chip.  If
+   omitted, assumed to be equal to 'bank-width'.
+ - #address-cells, #size-cells : Must be present if the device has
+   sub-nodes representing partitions (see below).  In this case
+   both #address-cells and #size-cells must be equal to 1.
+
+For JEDEC compatible devices, the following additional properties
+are defined:
+
+ - vendor-id : Contains the flash chip's vendor id (1 byte).
+ - device-id : Contains the flash chip's device id (1 byte).
+
+In addition to the information on the mtd bank itself, the
+device tree may optionally contain additional information
+describing partitions of the address space.  This can be
+used on platforms which have strong conventions about which
+portions of a flash are used for what purposes, but which don't
+use an on-flash partition table such as RedBoot.
+
+Each partition is represented as a sub-node of the mtd device.
+Each node's name represents the name of the corresponding
+partition of the mtd device.
+
+Flash partitions
+ - reg : The partition's offset and size within the mtd bank.
+ - label : (optional) The label / name for this partition.
+   If omitted, the label is taken from the node name (excluding
+   the unit address).
+ - read-only : (optional) This parameter, if present, is a hint to
+   Linux that this partition should only be mounted
+   read-only.  This is usually used for flash partitions
+   containing early-boot firmware images or data which should not
+   be clobbered.
+
+Example:
+
+	flash@ff000000 {
+		compatible = "amd,am29lv128ml", "cfi-flash";
+		reg = <ff000000 01000000>;
+		bank-width = <4>;
+		device-width = <1>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		fs@0 {
+			label = "fs";
+			reg = <0 f80000>;
+		};
+		firmware@f80000 {
+			label ="firmware";
+			reg = <f80000 80000>;
+			read-only;
+		};
+	};
+
+Here an example with multiple "reg" tuples:
+
+	flash@f0000000,0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "intel,PC48F4400P0VB", "cfi-flash";
+		reg = <0 0x00000000 0x02000000
+		       0 0x02000000 0x02000000>;
+		bank-width = <2>;
+		partition@0 {
+			label = "test-part1";
+			reg = <0 0x04000000>;
+		};
+	};
+
+An example using SRAM:
+
+	sram@2,0 {
+		compatible = "samsung,k6f1616u6a", "mtd-ram";
+		reg = <2 0 0x00200000>;
+		bank-width = <2>;
+	};
+
diff -druNp linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/net/can/mpc5xxx-mscan.txt linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/net/can/mpc5xxx-mscan.txt
--- linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/net/can/mpc5xxx-mscan.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/net/can/mpc5xxx-mscan.txt	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,53 @@
+CAN Device Tree Bindings
+------------------------
+
+(c) 2006-2009 Secret Lab Technologies Ltd
+Grant Likely <grant.likely@secretlab.ca>
+
+fsl,mpc5200-mscan nodes
+-----------------------
+In addition to the required compatible-, reg- and interrupt-properties, you can
+also specify which clock source shall be used for the controller:
+
+- fsl,mscan-clock-source : a string describing the clock source. Valid values
+			   are:	"ip" for ip bus clock
+				 "ref" for reference clock (XTAL)
+			   "ref" is default in case this property is not
+			   present.
+
+fsl,mpc5121-mscan nodes
+-----------------------
+In addition to the required compatible-, reg- and interrupt-properties, you can
+also specify which clock source and divider shall be used for the controller:
+
+- fsl,mscan-clock-source : a string describing the clock source. Valid values
+			   are:	"ip" for ip bus clock
+				"ref" for reference clock
+				"sys" for system clock
+			   If this property is not present, an optimal CAN
+			   clock source and frequency based on the system
+			   clock will be selected. If this is not possible,
+			   the reference clock will be used.
+
+- fsl,mscan-clock-divider: for the reference and system clock, an additional
+			   clock divider can be specified. By default, a
+			   value of 1 is used.
+
+Note that the MPC5121 Rev. 1 processor is not supported.
+
+Examples:
+	can@1300 {
+		compatible = "fsl,mpc5121-mscan";
+		interrupts = <12 0x8>;
+		interrupt-parent = <&ipic>;
+		reg = <0x1300 0x80>;
+	};
+
+	can@1380 {
+		compatible = "fsl,mpc5121-mscan";
+		interrupts = <13 0x8>;
+		interrupt-parent = <&ipic>;
+		reg = <0x1380 0x80>;
+		fsl,mscan-clock-source = "ref";
+		fsl,mscan-clock-divider = <3>;
+	};
diff -druNp linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/net/can/sja1000.txt linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/net/can/sja1000.txt
--- linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/net/can/sja1000.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/net/can/sja1000.txt	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,53 @@
+Memory mapped SJA1000 CAN controller from NXP (formerly Philips)
+
+Required properties:
+
+- compatible : should be "nxp,sja1000".
+
+- reg : should specify the chip select, address offset and size required
+	to map the registers of the SJA1000. The size is usually 0x80.
+
+- interrupts: property with a value describing the interrupt source
+	(number and sensitivity) required for the SJA1000.
+
+Optional properties:
+
+- nxp,external-clock-frequency : Frequency of the external oscillator
+	clock in Hz. Note that the internal clock frequency used by the
+	SJA1000 is half of that value. If not specified, a default value
+	of 16000000 (16 MHz) is used.
+
+- nxp,tx-output-mode : operation mode of the TX output control logic:
+	<0x0> : bi-phase output mode
+	<0x1> : normal output mode (default)
+	<0x2> : test output mode
+	<0x3> : clock output mode
+
+- nxp,tx-output-config : TX output pin configuration:
+	<0x01> : TX0 invert
+	<0x02> : TX0 pull-down (default)
+	<0x04> : TX0 pull-up
+	<0x06> : TX0 push-pull
+	<0x08> : TX1 invert
+	<0x10> : TX1 pull-down
+	<0x20> : TX1 pull-up
+	<0x30> : TX1 push-pull
+
+- nxp,clock-out-frequency : clock frequency in Hz on the CLKOUT pin.
+	If not specified or if the specified value is 0, the CLKOUT pin
+	will be disabled.
+
+- nxp,no-comparator-bypass : Allows to disable the CAN input comperator.
+
+For futher information, please have a look to the SJA1000 data sheet.
+
+Examples:
+
+can@3,100 {
+	compatible = "nxp,sja1000";
+	reg = <3 0x100 0x80>;
+	interrupts = <2 0>;
+	interrupt-parent = <&mpic>;
+	nxp,external-clock-frequency = <16000000>;
+};
+
diff -druNp linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/net/fsl-tsec-phy.txt linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/net/fsl-tsec-phy.txt
--- linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/net/fsl-tsec-phy.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/net/fsl-tsec-phy.txt	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,76 @@
+* MDIO IO device
+
+The MDIO is a bus to which the PHY devices are connected.  For each
+device that exists on this bus, a child node should be created.  See
+the definition of the PHY node in booting-without-of.txt for an example
+of how to define a PHY.
+
+Required properties:
+  - reg : Offset and length of the register set for the device
+  - compatible : Should define the compatible device type for the
+    mdio.  Currently, this is most likely to be "fsl,gianfar-mdio"
+
+Example:
+
+	mdio@24520 {
+		reg = <24520 20>;
+		compatible = "fsl,gianfar-mdio";
+
+		ethernet-phy@0 {
+			......
+		};
+	};
+
+* TBI Internal MDIO bus
+
+As of this writing, every tsec is associated with an internal TBI PHY.
+This PHY is accessed through the local MDIO bus.  These buses are defined
+similarly to the mdio buses, except they are compatible with "fsl,gianfar-tbi".
+The TBI PHYs underneath them are similar to normal PHYs, but the reg property
+is considered instructive, rather than descriptive.  The reg property should
+be chosen so it doesn't interfere with other PHYs on the bus.
+
+* Gianfar-compatible ethernet nodes
+
+Properties:
+
+  - device_type : Should be "network"
+  - model : Model of the device.  Can be "TSEC", "eTSEC", or "FEC"
+  - compatible : Should be "gianfar"
+  - reg : Offset and length of the register set for the device
+  - local-mac-address : List of bytes representing the ethernet address of
+    this controller
+  - interrupts : For FEC devices, the first interrupt is the device's
+    interrupt.  For TSEC and eTSEC devices, the first interrupt is
+    transmit, the second is receive, and the third is error.
+  - phy-handle : The phandle for the PHY connected to this ethernet
+    controller.
+  - fixed-link : <a b c d e> where a is emulated phy id - choose any,
+    but unique to the all specified fixed-links, b is duplex - 0 half,
+    1 full, c is link speed - d#10/d#100/d#1000, d is pause - 0 no
+    pause, 1 pause, e is asym_pause - 0 no asym_pause, 1 asym_pause.
+  - phy-connection-type : a string naming the controller/PHY interface type,
+    i.e., "mii" (default), "rmii", "gmii", "rgmii", "rgmii-id", "sgmii",
+    "tbi", or "rtbi".  This property is only really needed if the connection
+    is of type "rgmii-id", as all other connection types are detected by
+    hardware.
+  - fsl,magic-packet : If present, indicates that the hardware supports
+    waking up via magic packet.
+  - bd-stash : If present, indicates that the hardware supports stashing
+    buffer descriptors in the L2.
+  - rx-stash-len : Denotes the number of bytes of a received buffer to stash
+    in the L2.
+  - rx-stash-idx : Denotes the index of the first byte from the received
+    buffer to stash in the L2.
+
+Example:
+	ethernet@24000 {
+		device_type = "network";
+		model = "TSEC";
+		compatible = "gianfar";
+		reg = <0x24000 0x1000>;
+		local-mac-address = [ 00 E0 0C 00 73 00 ];
+		interrupts = <29 2 30 2 34 2>;
+		interrupt-parent = <&mpic>;
+		phy-handle = <&phy0>
+	};
diff -druNp linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/net/mdio-gpio.txt linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/net/mdio-gpio.txt
--- linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/net/mdio-gpio.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/net/mdio-gpio.txt	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,19 @@
+MDIO on GPIOs
+
+Currently defined compatibles:
+- virtual,gpio-mdio
+
+MDC and MDIO lines connected to GPIO controllers are listed in the
+gpios property as described in section VIII.1 in the following order:
+
+MDC, MDIO.
+
+Example:
+
+mdio {
+	compatible = "virtual,mdio-gpio";
+	#address-cells = <1>;
+	#size-cells = <0>;
+	gpios = <&qe_pio_a 11
+		 &qe_pio_c 6>;
+};
diff -druNp linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/net/phy.txt linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/net/phy.txt
--- linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/net/phy.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/net/phy.txt	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,25 @@
+PHY nodes
+
+Required properties:
+
+ - device_type : Should be "ethernet-phy"
+ - interrupts : <a b> where a is the interrupt number and b is a
+   field that represents an encoding of the sense and level
+   information for the interrupt.  This should be encoded based on
+   the information in section 2) depending on the type of interrupt
+   controller you have.
+ - interrupt-parent : the phandle for the interrupt controller that
+   services interrupts for this device.
+ - reg : The ID number for the phy, usually a small integer
+ - linux,phandle :  phandle for this node; likely referenced by an
+   ethernet controller node.
+
+Example:
+
+ethernet-phy@0 {
+	linux,phandle = <2452000>
+	interrupt-parent = <40000>;
+	interrupts = <35 1>;
+	reg = <0>;
+	device_type = "ethernet-phy";
+};
diff -druNp linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/pci/83xx-512x-pci.txt linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/pci/83xx-512x-pci.txt
--- linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/pci/83xx-512x-pci.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/pci/83xx-512x-pci.txt	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,40 @@
+* Freescale 83xx and 512x PCI bridges
+
+Freescale 83xx and 512x SOCs include the same pci bridge core.
+
+83xx/512x specific notes:
+- reg: should contain two address length tuples
+    The first is for the internal pci bridge registers
+    The second is for the pci config space access registers
+
+Example (MPC8313ERDB)
+	pci0: pci@e0008500 {
+		cell-index = <1>;
+		interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+		interrupt-map = <
+				/* IDSEL 0x0E -mini PCI */
+				 0x7000 0x0 0x0 0x1 &ipic 18 0x8
+				 0x7000 0x0 0x0 0x2 &ipic 18 0x8
+				 0x7000 0x0 0x0 0x3 &ipic 18 0x8
+				 0x7000 0x0 0x0 0x4 &ipic 18 0x8
+
+				/* IDSEL 0x0F - PCI slot */
+				 0x7800 0x0 0x0 0x1 &ipic 17 0x8
+				 0x7800 0x0 0x0 0x2 &ipic 18 0x8
+				 0x7800 0x0 0x0 0x3 &ipic 17 0x8
+				 0x7800 0x0 0x0 0x4 &ipic 18 0x8>;
+		interrupt-parent = <&ipic>;
+		interrupts = <66 0x8>;
+		bus-range = <0x0 0x0>;
+		ranges = <0x02000000 0x0 0x90000000 0x90000000 0x0 0x10000000
+			  0x42000000 0x0 0x80000000 0x80000000 0x0 0x10000000
+			  0x01000000 0x0 0x00000000 0xe2000000 0x0 0x00100000>;
+		clock-frequency = <66666666>;
+		#interrupt-cells = <1>;
+		#size-cells = <2>;
+		#address-cells = <3>;
+		reg = <0xe0008500 0x100		/* internal registers */
+		       0xe0008300 0x8>;		/* config space access registers */
+		compatible = "fsl,mpc8349-pci";
+		device_type = "pci";
+	};
diff -druNp linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/powerpc/4xx/cpm.txt linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/powerpc/4xx/cpm.txt
--- linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/powerpc/4xx/cpm.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/powerpc/4xx/cpm.txt	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,52 @@
+PPC4xx Clock Power Management (CPM) node
+
+Required properties:
+	- compatible		: compatible list, currently only "ibm,cpm"
+	- dcr-access-method	: "native"
+	- dcr-reg		: < DCR register range >
+
+Optional properties:
+	- er-offset		: All 4xx SoCs with a CPM controller have
+				  one of two different order for the CPM
+				  registers. Some have the CPM registers
+				  in the following order (ER,FR,SR). The
+				  others have them in the following order
+				  (SR,ER,FR). For the second case set
+				  er-offset = <1>.
+	- unused-units		: specifier consist of one cell. For each
+				  bit in the cell, the corresponding bit
+				  in CPM will be set to turn off unused
+				  devices.
+	- idle-doze		: specifier consist of one cell. For each
+				  bit in the cell, the corresponding bit
+				  in CPM will be set to turn off unused
+				  devices. This is usually just CPM[CPU].
+	- standby		: specifier consist of one cell. For each
+				  bit in the cell, the corresponding bit
+				  in CPM will be set on standby and
+				  restored on resume.
+	- suspend		: specifier consist of one cell. For each
+				  bit in the cell, the corresponding bit
+				  in CPM will be set on suspend (mem) and
+				  restored on resume. Note, for standby
+				  and suspend the corresponding bits can
+				  be different or the same. Usually for
+				  standby only class 2 and 3 units are set.
+				  However, the interface does not care.
+				  If they are the same, the additional
+				  power saving will be seeing if support
+				  is available to put the DDR in self
+				  refresh mode and any additional power
+				  saving techniques for the specific SoC.
+
+Example:
+	CPM0: cpm {
+		compatible = "ibm,cpm";
+		dcr-access-method = "native";
+		dcr-reg = <0x160 0x003>;
+		er-offset = <0>;
+		unused-units = <0x00000100>;
+		idle-doze = <0x02000000>;
+		standby = <0xfeff0000>;
+		suspend = <0xfeff791d>;
+};
diff -druNp linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/powerpc/4xx/emac.txt linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/powerpc/4xx/emac.txt
--- linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/powerpc/4xx/emac.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/powerpc/4xx/emac.txt	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,148 @@
+    4xx/Axon EMAC ethernet nodes
+
+    The EMAC ethernet controller in IBM and AMCC 4xx chips, and also
+    the Axon bridge.  To operate this needs to interact with a ths
+    special McMAL DMA controller, and sometimes an RGMII or ZMII
+    interface.  In addition to the nodes and properties described
+    below, the node for the OPB bus on which the EMAC sits must have a
+    correct clock-frequency property.
+
+      i) The EMAC node itself
+
+    Required properties:
+    - device_type       : "network"
+
+    - compatible        : compatible list, contains 2 entries, first is
+			  "ibm,emac-CHIP" where CHIP is the host ASIC (440gx,
+			  405gp, Axon) and second is either "ibm,emac" or
+			  "ibm,emac4".  For Axon, thus, we have: "ibm,emac-axon",
+			  "ibm,emac4"
+    - interrupts        : <interrupt mapping for EMAC IRQ and WOL IRQ>
+    - interrupt-parent  : optional, if needed for interrupt mapping
+    - reg               : <registers mapping>
+    - local-mac-address : 6 bytes, MAC address
+    - mal-device        : phandle of the associated McMAL node
+    - mal-tx-channel    : 1 cell, index of the tx channel on McMAL associated
+			  with this EMAC
+    - mal-rx-channel    : 1 cell, index of the rx channel on McMAL associated
+			  with this EMAC
+    - cell-index        : 1 cell, hardware index of the EMAC cell on a given
+			  ASIC (typically 0x0 and 0x1 for EMAC0 and EMAC1 on
+			  each Axon chip)
+    - max-frame-size    : 1 cell, maximum frame size supported in bytes
+    - rx-fifo-size      : 1 cell, Rx fifo size in bytes for 10 and 100 Mb/sec
+			  operations.
+			  For Axon, 2048
+    - tx-fifo-size      : 1 cell, Tx fifo size in bytes for 10 and 100 Mb/sec
+			  operations.
+			  For Axon, 2048.
+    - fifo-entry-size   : 1 cell, size of a fifo entry (used to calculate
+			  thresholds).
+			  For Axon, 0x00000010
+    - mal-burst-size    : 1 cell, MAL burst size (used to calculate thresholds)
+			  in bytes.
+			  For Axon, 0x00000100 (I think ...)
+    - phy-mode          : string, mode of operations of the PHY interface.
+			  Supported values are: "mii", "rmii", "smii", "rgmii",
+			  "tbi", "gmii", rtbi", "sgmii".
+			  For Axon on CAB, it is "rgmii"
+    - mdio-device       : 1 cell, required iff using shared MDIO registers
+			  (440EP).  phandle of the EMAC to use to drive the
+			  MDIO lines for the PHY used by this EMAC.
+    - zmii-device       : 1 cell, required iff connected to a ZMII.  phandle of
+			  the ZMII device node
+    - zmii-channel      : 1 cell, required iff connected to a ZMII.  Which ZMII
+			  channel or 0xffffffff if ZMII is only used for MDIO.
+    - rgmii-device      : 1 cell, required iff connected to an RGMII. phandle
+			  of the RGMII device node.
+			  For Axon: phandle of plb5/plb4/opb/rgmii
+    - rgmii-channel     : 1 cell, required iff connected to an RGMII.  Which
+			  RGMII channel is used by this EMAC.
+			  Fox Axon: present, whatever value is appropriate for each
+			  EMAC, that is the content of the current (bogus) "phy-port"
+			  property.
+
+    Optional properties:
+    - phy-address       : 1 cell, optional, MDIO address of the PHY. If absent,
+			  a search is performed.
+    - phy-map           : 1 cell, optional, bitmap of addresses to probe the PHY
+			  for, used if phy-address is absent. bit 0x00000001 is
+			  MDIO address 0.
+			  For Axon it can be absent, though my current driver
+			  doesn't handle phy-address yet so for now, keep
+			  0x00ffffff in it.
+    - rx-fifo-size-gige : 1 cell, Rx fifo size in bytes for 1000 Mb/sec
+			  operations (if absent the value is the same as
+			  rx-fifo-size).  For Axon, either absent or 2048.
+    - tx-fifo-size-gige : 1 cell, Tx fifo size in bytes for 1000 Mb/sec
+			  operations (if absent the value is the same as
+			  tx-fifo-size). For Axon, either absent or 2048.
+    - tah-device        : 1 cell, optional. If connected to a TAH engine for
+			  offload, phandle of the TAH device node.
+    - tah-channel       : 1 cell, optional. If appropriate, channel used on the
+			  TAH engine.
+
+    Example:
+
+	EMAC0: ethernet@40000800 {
+		device_type = "network";
+		compatible = "ibm,emac-440gp", "ibm,emac";
+		interrupt-parent = <&UIC1>;
+		interrupts = <1c 4 1d 4>;
+		reg = <40000800 70>;
+		local-mac-address = [00 04 AC E3 1B 1E];
+		mal-device = <&MAL0>;
+		mal-tx-channel = <0 1>;
+		mal-rx-channel = <0>;
+		cell-index = <0>;
+		max-frame-size = <5dc>;
+		rx-fifo-size = <1000>;
+		tx-fifo-size = <800>;
+		phy-mode = "rmii";
+		phy-map = <00000001>;
+		zmii-device = <&ZMII0>;
+		zmii-channel = <0>;
+	};
+
+      ii) McMAL node
+
+    Required properties:
+    - device_type        : "dma-controller"
+    - compatible         : compatible list, containing 2 entries, first is
+			   "ibm,mcmal-CHIP" where CHIP is the host ASIC (like
+			   emac) and the second is either "ibm,mcmal" or
+			   "ibm,mcmal2".
+			   For Axon, "ibm,mcmal-axon","ibm,mcmal2"
+    - interrupts         : <interrupt mapping for the MAL interrupts sources:
+                           5 sources: tx_eob, rx_eob, serr, txde, rxde>.
+                           For Axon: This is _different_ from the current
+			   firmware.  We use the "delayed" interrupts for txeob
+			   and rxeob. Thus we end up with mapping those 5 MPIC
+			   interrupts, all level positive sensitive: 10, 11, 32,
+			   33, 34 (in decimal)
+    - dcr-reg            : < DCR registers range >
+    - dcr-parent         : if needed for dcr-reg
+    - num-tx-chans       : 1 cell, number of Tx channels
+    - num-rx-chans       : 1 cell, number of Rx channels
+
+      iii) ZMII node
+
+    Required properties:
+    - compatible         : compatible list, containing 2 entries, first is
+			   "ibm,zmii-CHIP" where CHIP is the host ASIC (like
+			   EMAC) and the second is "ibm,zmii".
+			   For Axon, there is no ZMII node.
+    - reg                : <registers mapping>
+
+      iv) RGMII node
+
+    Required properties:
+    - compatible         : compatible list, containing 2 entries, first is
+			   "ibm,rgmii-CHIP" where CHIP is the host ASIC (like
+			   EMAC) and the second is "ibm,rgmii".
+                           For Axon, "ibm,rgmii-axon","ibm,rgmii"
+    - reg                : <registers mapping>
+    - revision           : as provided by the RGMII new version register if
+			   available.
+			   For Axon: 0x0000012a
+
diff -druNp linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/powerpc/4xx/ndfc.txt linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/powerpc/4xx/ndfc.txt
--- linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/powerpc/4xx/ndfc.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/powerpc/4xx/ndfc.txt	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,39 @@
+AMCC NDFC (NanD Flash Controller)
+
+Required properties:
+- compatible : "ibm,ndfc".
+- reg : should specify chip select and size used for the chip (0x2000).
+
+Optional properties:
+- ccr : NDFC config and control register value (default 0).
+- bank-settings : NDFC bank configuration register value (default 0).
+
+Notes:
+- partition(s) - follows the OF MTD standard for partitions
+
+Example:
+
+ndfc@1,0 {
+	compatible = "ibm,ndfc";
+	reg = <0x00000001 0x00000000 0x00002000>;
+	ccr = <0x00001000>;
+	bank-settings = <0x80002222>;
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	nand {
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		partition@0 {
+			label = "kernel";
+			reg = <0x00000000 0x00200000>;
+		};
+		partition@200000 {
+			label = "root";
+			reg = <0x00200000 0x03E00000>;
+		};
+	};
+};
+
+
diff -druNp linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/powerpc/4xx/ppc440spe-adma.txt linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/powerpc/4xx/ppc440spe-adma.txt
--- linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/powerpc/4xx/ppc440spe-adma.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/powerpc/4xx/ppc440spe-adma.txt	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,93 @@
+PPC440SPe DMA/XOR (DMA Controller and XOR Accelerator)
+
+Device nodes needed for operation of the ppc440spe-adma driver
+are specified hereby. These are I2O/DMA, DMA and XOR nodes
+for DMA engines and Memory Queue Module node. The latter is used
+by ADMA driver for configuration of RAID-6 H/W capabilities of
+the PPC440SPe. In addition to the nodes and properties described
+below, the ranges property of PLB node must specify ranges for
+DMA devices.
+
+ i) The I2O node
+
+ Required properties:
+
+ - compatible		: "ibm,i2o-440spe";
+ - reg			: <registers mapping>
+ - dcr-reg		: <DCR registers range>
+
+ Example:
+
+	I2O: i2o@400100000 {
+		compatible = "ibm,i2o-440spe";
+		reg = <0x00000004 0x00100000 0x100>;
+		dcr-reg = <0x060 0x020>;
+	};
+
+
+ ii) The DMA node
+
+ Required properties:
+
+ - compatible		: "ibm,dma-440spe";
+ - cell-index		: 1 cell, hardware index of the DMA engine
+			  (typically 0x0 and 0x1 for DMA0 and DMA1)
+ - reg			: <registers mapping>
+ - dcr-reg		: <DCR registers range>
+ - interrupts		: <interrupt mapping for DMA0/1 interrupts sources:
+			   2 sources: DMAx CS FIFO Needs Service IRQ (on UIC0)
+			   and DMA Error IRQ (on UIC1). The latter is common
+			   for both DMA engines>.
+ - interrupt-parent	: needed for interrupt mapping
+
+ Example:
+
+	DMA0: dma0@400100100 {
+		compatible = "ibm,dma-440spe";
+		cell-index = <0>;
+		reg = <0x00000004 0x00100100 0x100>;
+		dcr-reg = <0x060 0x020>;
+		interrupt-parent = <&DMA0>;
+		interrupts = <0 1>;
+		#interrupt-cells = <1>;
+		#address-cells = <0>;
+		#size-cells = <0>;
+		interrupt-map = <
+			0 &UIC0 0x14 4
+			1 &UIC1 0x16 4>;
+	};
+
+
+ iii) XOR Accelerator node
+
+ Required properties:
+
+ - compatible		: "amcc,xor-accelerator";
+ - reg			: <registers mapping>
+ - interrupts		: <interrupt mapping for XOR interrupt source>
+ - interrupt-parent	: for interrupt mapping
+
+ Example:
+
+	xor-accel@400200000 {
+		compatible = "amcc,xor-accelerator";
+		reg = <0x00000004 0x00200000 0x400>;
+		interrupt-parent = <&UIC1>;
+		interrupts = <0x1f 4>;
+	};
+
+
+ iv) Memory Queue Module node
+
+ Required properties:
+
+ - compatible		: "ibm,mq-440spe";
+ - dcr-reg		: <DCR registers range>
+
+ Example:
+
+	MQ0: mq {
+		compatible = "ibm,mq-440spe";
+		dcr-reg = <0x040 0x020>;
+	};
+
diff -druNp linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/powerpc/4xx/reboot.txt linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/powerpc/4xx/reboot.txt
--- linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/powerpc/4xx/reboot.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/powerpc/4xx/reboot.txt	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,18 @@
+Reboot property to control system reboot on PPC4xx systems:
+
+By setting "reset_type" to one of the following values, the default
+software reset mechanism may be overidden. Here the possible values of
+"reset_type":
+
+      1 - PPC4xx core reset
+      2 - PPC4xx chip reset
+      3 - PPC4xx system reset (default)
+
+Example:
+
+		cpu@0 {
+			device_type = "cpu";
+			model = "PowerPC,440SPe";
+			...
+			reset-type = <2>;	/* Use chip-reset */
+		};
diff -druNp linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/powerpc/fsl/board.txt linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/powerpc/fsl/board.txt
--- linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/powerpc/fsl/board.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/powerpc/fsl/board.txt	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,63 @@
+* Board Control and Status (BCSR)
+
+Required properties:
+
+ - compatible : Should be "fsl,<board>-bcsr"
+ - reg : Offset and length of the register set for the device
+
+Example:
+
+	bcsr@f8000000 {
+		compatible = "fsl,mpc8360mds-bcsr";
+		reg = <f8000000 8000>;
+	};
+
+* 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.
+- interrupt-parent: should specify phandle for the interrupt controller.
+- interrupts : should specify event (wakeup) IRQ.
+
+Example (MPC8610HPCD):
+
+	board-control@e8000000 {
+		compatible = "fsl,fpga-pixis";
+		reg = <0xe8000000 32>;
+		interrupt-parent = <&mpic>;
+		interrupts = <8 8>;
+	};
+
+* Freescale BCSR GPIO banks
+
+Some BCSR registers act as simple GPIO controllers, each such
+register can be represented by the gpio-controller node.
+
+Required properities:
+- compatible : Should be "fsl,<board>-bcsr-gpio".
+- reg : Should contain the address and the length of the GPIO bank
+  register.
+- #gpio-cells : Should be two. The first cell is the pin number and the
+  second cell is used to specify optional parameters (currently unused).
+- gpio-controller : Marks the port as GPIO controller.
+
+Example:
+
+	bcsr@1,0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "fsl,mpc8360mds-bcsr";
+		reg = <1 0 0x8000>;
+		ranges = <0 1 0 0x8000>;
+
+		bcsr13: gpio-controller@d {
+			#gpio-cells = <2>;
+			compatible = "fsl,mpc8360mds-bcsr-gpio";
+			reg = <0xd 1>;
+			gpio-controller;
+		};
+	};
diff -druNp linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/powerpc/fsl/cpm_qe/cpm/brg.txt linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/powerpc/fsl/cpm_qe/cpm/brg.txt
--- linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/powerpc/fsl/cpm_qe/cpm/brg.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/powerpc/fsl/cpm_qe/cpm/brg.txt	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,21 @@
+* Baud Rate Generators
+
+Currently defined compatibles:
+fsl,cpm-brg
+fsl,cpm1-brg
+fsl,cpm2-brg
+
+Properties:
+- reg : There may be an arbitrary number of reg resources; BRG
+  numbers are assigned to these in order.
+- clock-frequency : Specifies the base frequency driving
+  the BRG.
+
+Example:
+	brg@119f0 {
+		compatible = "fsl,mpc8272-brg",
+			     "fsl,cpm2-brg",
+			     "fsl,cpm-brg";
+		reg = <119f0 10 115f0 10>;
+		clock-frequency = <d#25000000>;
+	};
diff -druNp linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/powerpc/fsl/cpm_qe/cpm/i2c.txt linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/powerpc/fsl/cpm_qe/cpm/i2c.txt
--- linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/powerpc/fsl/cpm_qe/cpm/i2c.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/powerpc/fsl/cpm_qe/cpm/i2c.txt	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,41 @@
+* I2C
+
+The I2C controller is expressed as a bus under the CPM node.
+
+Properties:
+- compatible : "fsl,cpm1-i2c", "fsl,cpm2-i2c"
+- reg : On CPM2 devices, the second resource doesn't specify the I2C
+  Parameter RAM itself, but the I2C_BASE field of the CPM2 Parameter RAM
+  (typically 0x8afc 0x2).
+- #address-cells : Should be one. The cell is the i2c device address with
+  the r/w bit set to zero.
+- #size-cells : Should be zero.
+- clock-frequency : Can be used to set the i2c clock frequency. If
+  unspecified, a default frequency of 60kHz is being used.
+The following two properties are deprecated. They are only used by legacy
+i2c drivers to find the bus to probe:
+- linux,i2c-index : Can be used to hard code an i2c bus number. By default,
+  the bus number is dynamically assigned by the i2c core.
+- linux,i2c-class : Can be used to override the i2c class. The class is used
+  by legacy i2c device drivers to find a bus in a specific context like
+  system management, video or sound. By default, I2C_CLASS_HWMON (1) is
+  being used. The definition of the classes can be found in
+  include/i2c/i2c.h
+
+Example, based on mpc823:
+
+	i2c@860 {
+		compatible = "fsl,mpc823-i2c",
+			     "fsl,cpm1-i2c";
+		reg = <0x860 0x20 0x3c80 0x30>;
+		interrupts = <16>;
+		interrupt-parent = <&CPM_PIC>;
+		fsl,cpm-command = <0x10>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		rtc@68 {
+			compatible = "dallas,ds1307";
+			reg = <0x68>;
+		};
+	};
diff -druNp linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/powerpc/fsl/cpm_qe/cpm/pic.txt linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/powerpc/fsl/cpm_qe/cpm/pic.txt
--- linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/powerpc/fsl/cpm_qe/cpm/pic.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/powerpc/fsl/cpm_qe/cpm/pic.txt	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,18 @@
+* Interrupt Controllers
+
+Currently defined compatibles:
+- fsl,cpm1-pic
+  - only one interrupt cell
+- fsl,pq1-pic
+- fsl,cpm2-pic
+  - second interrupt cell is level/sense:
+    - 2 is falling edge
+    - 8 is active low
+
+Example:
+	interrupt-controller@10c00 {
+		#interrupt-cells = <2>;
+		interrupt-controller;
+		reg = <10c00 80>;
+		compatible = "mpc8272-pic", "fsl,cpm2-pic";
+	};
diff -druNp linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/powerpc/fsl/cpm_qe/cpm/usb.txt linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/powerpc/fsl/cpm_qe/cpm/usb.txt
--- linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/powerpc/fsl/cpm_qe/cpm/usb.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/powerpc/fsl/cpm_qe/cpm/usb.txt	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,15 @@
+* USB (Universal Serial Bus Controller)
+
+Properties:
+- compatible : "fsl,cpm1-usb", "fsl,cpm2-usb", "fsl,qe-usb"
+
+Example:
+	usb@11bc0 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "fsl,cpm2-usb";
+		reg = <11b60 18 8b00 100>;
+		interrupts = <b 8>;
+		interrupt-parent = <&PIC>;
+		fsl,cpm-command = <2e600000>;
+	};
diff -druNp linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/powerpc/fsl/cpm_qe/cpm.txt linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/powerpc/fsl/cpm_qe/cpm.txt
--- linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/powerpc/fsl/cpm_qe/cpm.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/powerpc/fsl/cpm_qe/cpm.txt	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,67 @@
+* Freescale Communications Processor Module
+
+NOTE: This is an interim binding, and will likely change slightly,
+as more devices are supported.  The QE bindings especially are
+incomplete.
+
+* Root CPM node
+
+Properties:
+- compatible : "fsl,cpm1", "fsl,cpm2", or "fsl,qe".
+- reg : A 48-byte region beginning with CPCR.
+
+Example:
+     cpm@119c0 {
+	#address-cells = <1>;
+	#size-cells = <1>;
+	#interrupt-cells = <2>;
+	compatible = "fsl,mpc8272-cpm", "fsl,cpm2";
+	reg = <119c0 30>;
+     }
+
+* Properties common to multiple CPM/QE devices
+
+- fsl,cpm-command : This value is ORed with the opcode and command flag
+                    to specify the device on which a CPM command operates.
+
+- fsl,cpm-brg : Indicates which baud rate generator the device
+                is associated with.  If absent, an unused BRG
+                should be dynamically allocated.  If zero, the
+                device uses an external clock rather than a BRG.
+
+- reg : Unless otherwise specified, the first resource represents the
+        scc/fcc/ucc registers, and the second represents the device's
+        parameter RAM region (if it has one).
+
+* Multi-User RAM (MURAM)
+
+The multi-user/dual-ported RAM is expressed as a bus under the CPM node.
+
+Ranges must be set up subject to the following restrictions:
+
+- Children's reg nodes must be offsets from the start of all muram, even
+  if the user-data area does not begin at zero.
+- If multiple range entries are used, the difference between the parent
+  address and the child address must be the same in all, so that a single
+  mapping can cover them all while maintaining the ability to determine
+  CPM-side offsets with pointer subtraction.  It is recommended that
+  multiple range entries not be used.
+- A child address of zero must be translatable, even if no reg resources
+  contain it.
+
+A child "data" node must exist, compatible with "fsl,cpm-muram-data", to
+indicate the portion of muram that is usable by the OS for arbitrary
+purposes.  The data node may have an arbitrary number of reg resources,
+all of which contribute to the allocatable muram pool.
+
+Example, based on mpc8272:
+	muram@0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges = <0 0 10000>;
+
+		data@0 {
+			compatible = "fsl,cpm-muram-data";
+			reg = <0 2000 9800 800>;
+		};
+	};
diff -druNp linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/powerpc/fsl/cpm_qe/gpio.txt linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/powerpc/fsl/cpm_qe/gpio.txt
--- linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/powerpc/fsl/cpm_qe/gpio.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/powerpc/fsl/cpm_qe/gpio.txt	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,38 @@
+Every GPIO controller node must have #gpio-cells property defined,
+this information will be used to translate gpio-specifiers.
+
+On CPM1 devices, all ports are using slightly different register layouts.
+Ports A, C and D are 16bit ports and Ports B and E are 32bit ports.
+
+On CPM2 devices, all ports are 32bit ports and use a common register layout.
+
+Required properties:
+- compatible : "fsl,cpm1-pario-bank-a", "fsl,cpm1-pario-bank-b",
+  "fsl,cpm1-pario-bank-c", "fsl,cpm1-pario-bank-d",
+  "fsl,cpm1-pario-bank-e", "fsl,cpm2-pario-bank"
+- #gpio-cells : Should be two. The first cell is the pin number and the
+  second cell is used to specify optional parameters (currently unused).
+- gpio-controller : Marks the port as GPIO controller.
+
+Example of three SOC GPIO banks defined as gpio-controller nodes:
+
+	CPM1_PIO_A: gpio-controller@950 {
+		#gpio-cells = <2>;
+		compatible = "fsl,cpm1-pario-bank-a";
+		reg = <0x950 0x10>;
+		gpio-controller;
+	};
+
+	CPM1_PIO_B: gpio-controller@ab8 {
+		#gpio-cells = <2>;
+		compatible = "fsl,cpm1-pario-bank-b";
+		reg = <0xab8 0x10>;
+		gpio-controller;
+	};
+
+	CPM1_PIO_E: gpio-controller@ac8 {
+		#gpio-cells = <2>;
+		compatible = "fsl,cpm1-pario-bank-e";
+		reg = <0xac8 0x18>;
+		gpio-controller;
+	};
diff -druNp linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/powerpc/fsl/cpm_qe/network.txt linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/powerpc/fsl/cpm_qe/network.txt
--- linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/powerpc/fsl/cpm_qe/network.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/powerpc/fsl/cpm_qe/network.txt	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,45 @@
+* Network
+
+Currently defined compatibles:
+- fsl,cpm1-scc-enet
+- fsl,cpm2-scc-enet
+- fsl,cpm1-fec-enet
+- fsl,cpm2-fcc-enet (third resource is GFEMR)
+- fsl,qe-enet
+
+Example:
+
+	ethernet@11300 {
+		device_type = "network";
+		compatible = "fsl,mpc8272-fcc-enet",
+			     "fsl,cpm2-fcc-enet";
+		reg = <11300 20 8400 100 11390 1>;
+		local-mac-address = [ 00 00 00 00 00 00 ];
+		interrupts = <20 8>;
+		interrupt-parent = <&PIC>;
+		phy-handle = <&PHY0>;
+		fsl,cpm-command = <12000300>;
+	};
+
+* MDIO
+
+Currently defined compatibles:
+fsl,pq1-fec-mdio (reg is same as first resource of FEC device)
+fsl,cpm2-mdio-bitbang (reg is port C registers)
+
+Properties for fsl,cpm2-mdio-bitbang:
+fsl,mdio-pin : pin of port C controlling mdio data
+fsl,mdc-pin : pin of port C controlling mdio clock
+
+Example:
+	mdio@10d40 {
+		device_type = "mdio";
+		compatible = "fsl,mpc8272ads-mdio-bitbang",
+			     "fsl,mpc8272-mdio-bitbang",
+			     "fsl,cpm2-mdio-bitbang";
+		reg = <10d40 14>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		fsl,mdio-pin = <12>;
+		fsl,mdc-pin = <13>;
+	};
diff -druNp linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/powerpc/fsl/cpm_qe/qe/firmware.txt linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/powerpc/fsl/cpm_qe/qe/firmware.txt
--- linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/powerpc/fsl/cpm_qe/qe/firmware.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/powerpc/fsl/cpm_qe/qe/firmware.txt	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,24 @@
+* Uploaded QE firmware
+
+      If a new firmware has been uploaded to the QE (usually by the
+      boot loader), then a 'firmware' child node should be added to the QE
+      node.  This node provides information on the uploaded firmware that
+      device drivers may need.
+
+      Required properties:
+      - id: The string name of the firmware.  This is taken from the 'id'
+            member of the qe_firmware structure of the uploaded firmware.
+            Device drivers can search this string to determine if the
+            firmware they want is already present.
+      - extended-modes: The Extended Modes bitfield, taken from the
+		   firmware binary.  It is a 64-bit number represented
+		   as an array of two 32-bit numbers.
+      - virtual-traps: The virtual traps, taken from the firmware binary.
+		  It is an array of 8 32-bit numbers.
+
+Example:
+	firmware {
+		id = "Soft-UART";
+		extended-modes = <0 0>;
+		virtual-traps = <0 0 0 0 0 0 0 0>;
+	};
diff -druNp linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/powerpc/fsl/cpm_qe/qe/par_io.txt linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/powerpc/fsl/cpm_qe/qe/par_io.txt
--- linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/powerpc/fsl/cpm_qe/qe/par_io.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/powerpc/fsl/cpm_qe/qe/par_io.txt	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,51 @@
+* Parallel I/O Ports
+
+This node configures Parallel I/O ports for CPUs with QE support.
+The node should reside in the "soc" node of the tree.  For each
+device that using parallel I/O ports, a child node should be created.
+See the definition of the Pin configuration nodes below for more
+information.
+
+Required properties:
+- device_type : should be "par_io".
+- reg : offset to the register set and its length.
+- num-ports : number of Parallel I/O ports
+
+Example:
+par_io@1400 {
+	reg = <1400 100>;
+	#address-cells = <1>;
+	#size-cells = <0>;
+	device_type = "par_io";
+	num-ports = <7>;
+	ucc_pin@01 {
+		......
+	};
+
+Note that "par_io" nodes are obsolete, and should not be used for
+the new device trees. Instead, each Par I/O bank should be represented
+via its own gpio-controller node:
+
+Required properties:
+- #gpio-cells : should be "2".
+- compatible : should be "fsl,<chip>-qe-pario-bank",
+  "fsl,mpc8323-qe-pario-bank".
+- reg : offset to the register set and its length.
+- gpio-controller : node to identify gpio controllers.
+
+Example:
+	qe_pio_a: gpio-controller@1400 {
+		#gpio-cells = <2>;
+		compatible = "fsl,mpc8360-qe-pario-bank",
+		"fsl,mpc8323-qe-pario-bank";
+		reg = <0x1400 0x18>;
+		gpio-controller;
+	  };
+
+	qe_pio_e: gpio-controller@1460 {
+		#gpio-cells = <2>;
+		compatible = "fsl,mpc8360-qe-pario-bank",
+			     "fsl,mpc8323-qe-pario-bank";
+		reg = <0x1460 0x18>;
+		gpio-controller;
+	  };
diff -druNp linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/powerpc/fsl/cpm_qe/qe/pincfg.txt linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/powerpc/fsl/cpm_qe/qe/pincfg.txt
--- linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/powerpc/fsl/cpm_qe/qe/pincfg.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/powerpc/fsl/cpm_qe/qe/pincfg.txt	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,60 @@
+* Pin configuration nodes
+
+Required properties:
+- linux,phandle : phandle of this node; likely referenced by a QE
+  device.
+- pio-map : array of pin configurations.  Each pin is defined by 6
+  integers.  The six numbers are respectively: port, pin, dir,
+  open_drain, assignment, has_irq.
+  - port : port number of the pin; 0-6 represent port A-G in UM.
+  - pin : pin number in the port.
+  - dir : direction of the pin, should encode as follows:
+
+     0 = The pin is disabled
+     1 = The pin is an output
+     2 = The pin is an input
+     3 = The pin is I/O
+
+  - open_drain : indicates the pin is normal or wired-OR:
+
+     0 = The pin is actively driven as an output
+     1 = The pin is an open-drain driver. As an output, the pin is
+         driven active-low, otherwise it is three-stated.
+
+  - assignment : function number of the pin according to the Pin Assignment
+    tables in User Manual.  Each pin can have up to 4 possible functions in
+    QE and two options for CPM.
+  - has_irq : indicates if the pin is used as source of external
+    interrupts.
+
+Example:
+     ucc_pin@01 {
+	linux,phandle = <140001>;
+	pio-map = <
+	/* port  pin  dir  open_drain  assignment  has_irq */
+		0  3  1  0  1  0 	/* TxD0 */
+		0  4  1  0  1  0 	/* TxD1 */
+		0  5  1  0  1  0 	/* TxD2 */
+		0  6  1  0  1  0 	/* TxD3 */
+		1  6  1  0  3  0 	/* TxD4 */
+		1  7  1  0  1  0 	/* TxD5 */
+		1  9  1  0  2  0 	/* TxD6 */
+		1  a  1  0  2  0 	/* TxD7 */
+		0  9  2  0  1  0 	/* RxD0 */
+		0  a  2  0  1  0 	/* RxD1 */
+		0  b  2  0  1  0 	/* RxD2 */
+		0  c  2  0  1  0 	/* RxD3 */
+		0  d  2  0  1  0 	/* RxD4 */
+		1  1  2  0  2  0 	/* RxD5 */
+		1  0  2  0  2  0 	/* RxD6 */
+		1  4  2  0  2  0 	/* RxD7 */
+		0  7  1  0  1  0 	/* TX_EN */
+		0  8  1  0  1  0 	/* TX_ER */
+		0  f  2  0  1  0 	/* RX_DV */
+		0  10 2  0  1  0 	/* RX_ER */
+		0  0  2  0  1  0 	/* RX_CLK */
+		2  9  1  0  3  0 	/* GTX_CLK - CLK10 */
+		2  8  2  0  1  0>;	/* GTX125 - CLK9 */
+     };
+
+
diff -druNp linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/powerpc/fsl/cpm_qe/qe/ucc.txt linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/powerpc/fsl/cpm_qe/qe/ucc.txt
--- linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/powerpc/fsl/cpm_qe/qe/ucc.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/powerpc/fsl/cpm_qe/qe/ucc.txt	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,70 @@
+* UCC (Unified Communications Controllers)
+
+Required properties:
+- device_type : should be "network", "hldc", "uart", "transparent"
+  "bisync", "atm", or "serial".
+- compatible : could be "ucc_geth" or "fsl_atm" and so on.
+- cell-index : the ucc number(1-8), corresponding to UCCx in UM.
+- reg : Offset and length of the register set for the device
+- interrupts : <a b> where a is the interrupt number and b is a
+  field that represents an encoding of the sense and level
+  information for the interrupt.  This should be encoded based on
+  the information in section 2) depending on the type of interrupt
+  controller you have.
+- interrupt-parent : the phandle for the interrupt controller that
+  services interrupts for this device.
+- pio-handle : The phandle for the Parallel I/O port configuration.
+- port-number : for UART drivers, the port number to use, between 0 and 3.
+  This usually corresponds to the /dev/ttyQE device, e.g. <0> = /dev/ttyQE0.
+  The port number is added to the minor number of the device.  Unlike the
+  CPM UART driver, the port-number is required for the QE UART driver.
+- soft-uart : for UART drivers, if specified this means the QE UART device
+  driver should use "Soft-UART" mode, which is needed on some SOCs that have
+  broken UART hardware.  Soft-UART is provided via a microcode upload.
+- rx-clock-name: the UCC receive clock source
+  "none": clock source is disabled
+  "brg1" through "brg16": clock source is BRG1-BRG16, respectively
+  "clk1" through "clk24": clock source is CLK1-CLK24, respectively
+- tx-clock-name: the UCC transmit clock source
+  "none": clock source is disabled
+  "brg1" through "brg16": clock source is BRG1-BRG16, respectively
+  "clk1" through "clk24": clock source is CLK1-CLK24, respectively
+The following two properties are deprecated.  rx-clock has been replaced
+with rx-clock-name, and tx-clock has been replaced with tx-clock-name.
+Drivers that currently use the deprecated properties should continue to
+do so, in order to support older device trees, but they should be updated
+to check for the new properties first.
+- rx-clock : represents the UCC receive clock source.
+  0x00 : clock source is disabled;
+  0x1~0x10 : clock source is BRG1~BRG16 respectively;
+  0x11~0x28: clock source is QE_CLK1~QE_CLK24 respectively.
+- tx-clock: represents the UCC transmit clock source;
+  0x00 : clock source is disabled;
+  0x1~0x10 : clock source is BRG1~BRG16 respectively;
+  0x11~0x28: clock source is QE_CLK1~QE_CLK24 respectively.
+
+Required properties for network device_type:
+- mac-address : list of bytes representing the ethernet address.
+- phy-handle : The phandle for the PHY connected to this controller.
+
+Recommended properties:
+- phy-connection-type : a string naming the controller/PHY interface type,
+  i.e., "mii" (default), "rmii", "gmii", "rgmii", "rgmii-id" (Internal
+  Delay), "rgmii-txid" (delay on TX only), "rgmii-rxid" (delay on RX only),
+  "tbi", or "rtbi".
+
+Example:
+	ucc@2000 {
+		device_type = "network";
+		compatible = "ucc_geth";
+		cell-index = <1>;
+		reg = <2000 200>;
+		interrupts = <a0 0>;
+		interrupt-parent = <700>;
+		mac-address = [ 00 04 9f 00 23 23 ];
+		rx-clock = "none";
+		tx-clock = "clk9";
+		phy-handle = <212000>;
+		phy-connection-type = "gmii";
+		pio-handle = <140001>;
+	};
diff -druNp linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/powerpc/fsl/cpm_qe/qe/usb.txt linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/powerpc/fsl/cpm_qe/qe/usb.txt
--- linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/powerpc/fsl/cpm_qe/qe/usb.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/powerpc/fsl/cpm_qe/qe/usb.txt	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,37 @@
+Freescale QUICC Engine USB Controller
+
+Required properties:
+- compatible : should be "fsl,<chip>-qe-usb", "fsl,mpc8323-qe-usb".
+- reg : the first two cells should contain usb registers location and
+  length, the next two two cells should contain PRAM location and
+  length.
+- interrupts : should contain USB interrupt.
+- interrupt-parent : interrupt source phandle.
+- fsl,fullspeed-clock : specifies the full speed USB clock source:
+  "none": clock source is disabled
+  "brg1" through "brg16": clock source is BRG1-BRG16, respectively
+  "clk1" through "clk24": clock source is CLK1-CLK24, respectively
+- fsl,lowspeed-clock : specifies the low speed USB clock source:
+  "none": clock source is disabled
+  "brg1" through "brg16": clock source is BRG1-BRG16, respectively
+  "clk1" through "clk24": clock source is CLK1-CLK24, respectively
+- hub-power-budget : USB power budget for the root hub, in mA.
+- gpios : should specify GPIOs in this order: USBOE, USBTP, USBTN, USBRP,
+  USBRN, SPEED (optional), and POWER (optional).
+
+Example:
+
+usb@6c0 {
+	compatible = "fsl,mpc8360-qe-usb", "fsl,mpc8323-qe-usb";
+	reg = <0x6c0 0x40 0x8b00 0x100>;
+	interrupts = <11>;
+	interrupt-parent = <&qeic>;
+	fsl,fullspeed-clock = "clk21";
+	gpios = <&qe_pio_b  2 0 /* USBOE */
+		 &qe_pio_b  3 0 /* USBTP */
+		 &qe_pio_b  8 0 /* USBTN */
+		 &qe_pio_b  9 0 /* USBRP */
+		 &qe_pio_b 11 0 /* USBRN */
+		 &qe_pio_e 20 0 /* SPEED */
+		 &qe_pio_e 21 0 /* POWER */>;
+};
diff -druNp linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/powerpc/fsl/cpm_qe/qe.txt linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/powerpc/fsl/cpm_qe/qe.txt
--- linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/powerpc/fsl/cpm_qe/qe.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/powerpc/fsl/cpm_qe/qe.txt	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,115 @@
+* Freescale QUICC Engine module (QE)
+This represents qe module that is installed on PowerQUICC II Pro.
+
+NOTE:  This is an interim binding; it should be updated to fit
+in with the CPM binding later in this document.
+
+Basically, it is a bus of devices, that could act more or less
+as a complete entity (UCC, USB etc ). All of them should be siblings on
+the "root" qe node, using the common properties from there.
+The description below applies to the qe of MPC8360 and
+more nodes and properties would be extended in the future.
+
+i) Root QE device
+
+Required properties:
+- compatible : should be "fsl,qe";
+- model : precise model of the QE, Can be "QE", "CPM", or "CPM2"
+- reg : offset and length of the device registers.
+- bus-frequency : the clock frequency for QUICC Engine.
+- fsl,qe-num-riscs: define how many RISC engines the QE has.
+- fsl,qe-num-snums: define how many serial number(SNUM) the QE can use for the
+  threads.
+
+Optional properties:
+- fsl,firmware-phandle:
+    Usage: required only if there is no fsl,qe-firmware child node
+    Value type: <phandle>
+    Definition: Points to a firmware node (see "QE Firmware Node" below)
+        that contains the firmware that should be uploaded for this QE.
+        The compatible property for the firmware node should say,
+        "fsl,qe-firmware".
+
+Recommended properties
+- brg-frequency : the internal clock source frequency for baud-rate
+  generators in Hz.
+
+Example:
+     qe@e0100000 {
+	#address-cells = <1>;
+	#size-cells = <1>;
+	#interrupt-cells = <2>;
+	compatible = "fsl,qe";
+	ranges = <0 e0100000 00100000>;
+	reg = <e0100000 480>;
+	brg-frequency = <0>;
+	bus-frequency = <179A7B00>;
+     }
+
+* Multi-User RAM (MURAM)
+
+Required properties:
+- compatible : should be "fsl,qe-muram", "fsl,cpm-muram".
+- mode : the could be "host" or "slave".
+- ranges : Should be defined as specified in 1) to describe the
+   translation of MURAM addresses.
+- data-only : sub-node which defines the address area under MURAM
+   bus that can be allocated as data/parameter
+
+Example:
+
+     muram@10000 {
+	compatible = "fsl,qe-muram", "fsl,cpm-muram";
+	ranges = <0 00010000 0000c000>;
+
+	data-only@0{
+		compatible = "fsl,qe-muram-data",
+			     "fsl,cpm-muram-data";
+		reg = <0 c000>;
+	};
+     };
+
+* QE Firmware Node
+
+This node defines a firmware binary that is embedded in the device tree, for
+the purpose of passing the firmware from bootloader to the kernel, or from
+the hypervisor to the guest.
+
+The firmware node itself contains the firmware binary contents, a compatible
+property, and any firmware-specific properties.  The node should be placed
+inside a QE node that needs it.  Doing so eliminates the need for a
+fsl,firmware-phandle property.  Other QE nodes that need the same firmware
+should define an fsl,firmware-phandle property that points to the firmware node
+in the first QE node.
+
+The fsl,firmware property can be specified in the DTS (possibly using incbin)
+or can be inserted by the boot loader at boot time.
+
+Required properties:
+  - compatible
+      Usage: required
+      Value type: <string>
+      Definition: A standard property.  Specify a string that indicates what
+          kind of firmware it is.  For QE, this should be "fsl,qe-firmware".
+
+   - fsl,firmware
+      Usage: required
+      Value type: <prop-encoded-array>, encoded as an array of bytes
+      Definition: A standard property.  This property contains the firmware
+          binary "blob".
+
+Example:
+	qe1@e0080000 {
+		compatible = "fsl,qe";
+		qe_firmware:qe-firmware {
+			compatible = "fsl,qe-firmware";
+			fsl,firmware = [0x70 0xcd 0x00 0x00 0x01 0x46 0x45 ...];
+		};
+		...
+	};
+
+	qe2@e0090000 {
+		compatible = "fsl,qe";
+		fsl,firmware-phandle = <&qe_firmware>;
+		...
+	};
diff -druNp linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/powerpc/fsl/cpm_qe/serial.txt linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/powerpc/fsl/cpm_qe/serial.txt
--- linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/powerpc/fsl/cpm_qe/serial.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/powerpc/fsl/cpm_qe/serial.txt	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,32 @@
+* Serial
+
+Currently defined compatibles:
+- fsl,cpm1-smc-uart
+- fsl,cpm2-smc-uart
+- fsl,cpm1-scc-uart
+- fsl,cpm2-scc-uart
+- fsl,qe-uart
+
+Modem control lines connected to GPIO controllers are listed in the gpios
+property as described in booting-without-of.txt, section IX.1 in the following
+order:
+
+CTS, RTS, DCD, DSR, DTR, and RI.
+
+The gpios property is optional and can be left out when control lines are
+not used.
+
+Example:
+
+	serial@11a00 {
+		device_type = "serial";
+		compatible = "fsl,mpc8272-scc-uart",
+			     "fsl,cpm2-scc-uart";
+		reg = <11a00 20 8000 100>;
+		interrupts = <28 8>;
+		interrupt-parent = <&PIC>;
+		fsl,cpm-brg = <1>;
+		fsl,cpm-command = <00800000>;
+		gpios = <&gpio_c 15 0
+			 &gpio_d 29 0>;
+	};
diff -druNp linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/powerpc/fsl/diu.txt linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/powerpc/fsl/diu.txt
--- linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/powerpc/fsl/diu.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/powerpc/fsl/diu.txt	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,34 @@
+* Freescale Display Interface Unit
+
+The Freescale DIU is a LCD controller, with proper hardware, it can also
+drive DVI monitors.
+
+Required properties:
+- compatible : should be "fsl,diu" or "fsl,mpc5121-diu".
+- reg : should contain at least address and length of the DIU register
+  set.
+- interrupts : one DIU interrupt should be described here.
+- interrupt-parent : the phandle for the interrupt controller that
+  services interrupts for this device.
+
+Optional properties:
+- edid : verbatim EDID data block describing attached display.
+  Data from the detailed timing descriptor will be used to
+  program the display controller.
+
+Example (MPC8610HPCD):
+	display@2c000 {
+		compatible = "fsl,diu";
+		reg = <0x2c000 100>;
+		interrupts = <72 2>;
+		interrupt-parent = <&mpic>;
+	};
+
+Example for MPC5121:
+	display@2100 {
+		compatible = "fsl,mpc5121-diu";
+		reg = <0x2100 0x100>;
+		interrupts = <64 0x8>;
+		interrupt-parent = <&ipic>;
+		edid = [edid-data];
+	};
diff -druNp linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/powerpc/fsl/dma.txt linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/powerpc/fsl/dma.txt
--- linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/powerpc/fsl/dma.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/powerpc/fsl/dma.txt	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,144 @@
+* Freescale 83xx DMA Controller
+
+Freescale PowerPC 83xx have on chip general purpose DMA controllers.
+
+Required properties:
+
+- compatible        : compatible list, contains 2 entries, first is
+		 "fsl,CHIP-dma", where CHIP is the processor
+		 (mpc8349, mpc8360, etc.) and the second is
+		 "fsl,elo-dma"
+- reg               : <registers mapping for DMA general status reg>
+- ranges		: Should be defined as specified in 1) to describe the
+		  DMA controller channels.
+- cell-index        : controller index.  0 for controller @ 0x8100
+- interrupts        : <interrupt mapping for DMA IRQ>
+- interrupt-parent  : optional, if needed for interrupt mapping
+
+
+- DMA channel nodes:
+        - compatible        : compatible list, contains 2 entries, first is
+			 "fsl,CHIP-dma-channel", where CHIP is the processor
+			 (mpc8349, mpc8350, etc.) and the second is
+			 "fsl,elo-dma-channel". However, see note below.
+        - reg               : <registers mapping for channel>
+        - cell-index        : dma channel index starts at 0.
+
+Optional properties:
+        - interrupts        : <interrupt mapping for DMA channel IRQ>
+			  (on 83xx this is expected to be identical to
+			   the interrupts property of the parent node)
+        - interrupt-parent  : optional, if needed for interrupt mapping
+
+Example:
+	dma@82a8 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "fsl,mpc8349-dma", "fsl,elo-dma";
+		reg = <0x82a8 4>;
+		ranges = <0 0x8100 0x1a4>;
+		interrupt-parent = <&ipic>;
+		interrupts = <71 8>;
+		cell-index = <0>;
+		dma-channel@0 {
+			compatible = "fsl,mpc8349-dma-channel", "fsl,elo-dma-channel";
+			cell-index = <0>;
+			reg = <0 0x80>;
+			interrupt-parent = <&ipic>;
+			interrupts = <71 8>;
+		};
+		dma-channel@80 {
+			compatible = "fsl,mpc8349-dma-channel", "fsl,elo-dma-channel";
+			cell-index = <1>;
+			reg = <0x80 0x80>;
+			interrupt-parent = <&ipic>;
+			interrupts = <71 8>;
+		};
+		dma-channel@100 {
+			compatible = "fsl,mpc8349-dma-channel", "fsl,elo-dma-channel";
+			cell-index = <2>;
+			reg = <0x100 0x80>;
+			interrupt-parent = <&ipic>;
+			interrupts = <71 8>;
+		};
+		dma-channel@180 {
+			compatible = "fsl,mpc8349-dma-channel", "fsl,elo-dma-channel";
+			cell-index = <3>;
+			reg = <0x180 0x80>;
+			interrupt-parent = <&ipic>;
+			interrupts = <71 8>;
+		};
+	};
+
+* Freescale 85xx/86xx DMA Controller
+
+Freescale PowerPC 85xx/86xx have on chip general purpose DMA controllers.
+
+Required properties:
+
+- compatible        : compatible list, contains 2 entries, first is
+		 "fsl,CHIP-dma", where CHIP is the processor
+		 (mpc8540, mpc8540, etc.) and the second is
+		 "fsl,eloplus-dma"
+- reg               : <registers mapping for DMA general status reg>
+- cell-index        : controller index.  0 for controller @ 0x21000,
+                                         1 for controller @ 0xc000
+- ranges		: Should be defined as specified in 1) to describe the
+		  DMA controller channels.
+
+- DMA channel nodes:
+        - compatible        : compatible list, contains 2 entries, first is
+			 "fsl,CHIP-dma-channel", where CHIP is the processor
+			 (mpc8540, mpc8560, etc.) and the second is
+			 "fsl,eloplus-dma-channel". However, see note below.
+        - cell-index        : dma channel index starts at 0.
+        - reg               : <registers mapping for channel>
+        - interrupts        : <interrupt mapping for DMA channel IRQ>
+        - interrupt-parent  : optional, if needed for interrupt mapping
+
+Example:
+	dma@21300 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "fsl,mpc8540-dma", "fsl,eloplus-dma";
+		reg = <0x21300 4>;
+		ranges = <0 0x21100 0x200>;
+		cell-index = <0>;
+		dma-channel@0 {
+			compatible = "fsl,mpc8540-dma-channel", "fsl,eloplus-dma-channel";
+			reg = <0 0x80>;
+			cell-index = <0>;
+			interrupt-parent = <&mpic>;
+			interrupts = <20 2>;
+		};
+		dma-channel@80 {
+			compatible = "fsl,mpc8540-dma-channel", "fsl,eloplus-dma-channel";
+			reg = <0x80 0x80>;
+			cell-index = <1>;
+			interrupt-parent = <&mpic>;
+			interrupts = <21 2>;
+		};
+		dma-channel@100 {
+			compatible = "fsl,mpc8540-dma-channel", "fsl,eloplus-dma-channel";
+			reg = <0x100 0x80>;
+			cell-index = <2>;
+			interrupt-parent = <&mpic>;
+			interrupts = <22 2>;
+		};
+		dma-channel@180 {
+			compatible = "fsl,mpc8540-dma-channel", "fsl,eloplus-dma-channel";
+			reg = <0x180 0x80>;
+			cell-index = <3>;
+			interrupt-parent = <&mpic>;
+			interrupts = <23 2>;
+		};
+	};
+
+Note on DMA channel compatible properties: The compatible property must say
+"fsl,elo-dma-channel" or "fsl,eloplus-dma-channel" to be used by the Elo DMA
+driver (fsldma).  Any DMA channel used by fsldma cannot be used by another
+DMA driver, such as the SSI sound drivers for the MPC8610.  Therefore, any DMA
+channel that should be used for another driver should not use
+"fsl,elo-dma-channel" or "fsl,eloplus-dma-channel".  For the SSI drivers, for
+example, the compatible property should be "fsl,ssi-dma-channel".  See ssi.txt
+for more information.
diff -druNp linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/powerpc/fsl/ecm.txt linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/powerpc/fsl/ecm.txt
--- linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/powerpc/fsl/ecm.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/powerpc/fsl/ecm.txt	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,64 @@
+=====================================================================
+E500 LAW & Coherency Module Device Tree Binding
+Copyright (C) 2009 Freescale Semiconductor Inc.
+=====================================================================
+
+Local Access Window (LAW) Node
+
+The LAW node represents the region of CCSR space where local access
+windows are configured.  For ECM based devices this is the first 4k
+of CCSR space that includes CCSRBAR, ALTCBAR, ALTCAR, BPTR, and some
+number of local access windows as specified by fsl,num-laws.
+
+PROPERTIES
+
+  - compatible
+      Usage: required
+      Value type: <string>
+      Definition: Must include "fsl,ecm-law"
+
+  - reg
+      Usage: required
+      Value type: <prop-encoded-array>
+      Definition: A standard property.  The value specifies the
+          physical address offset and length of the CCSR space
+          registers.
+
+  - fsl,num-laws
+      Usage: required
+      Value type: <u32>
+      Definition: The value specifies the number of local access
+          windows for this device.
+
+=====================================================================
+
+E500 Coherency Module Node
+
+The E500 LAW node represents the region of CCSR space where ECM config
+and error reporting registers exist, this is the second 4k (0x1000)
+of CCSR space.
+
+PROPERTIES
+
+  - compatible
+      Usage: required
+      Value type: <string>
+      Definition: Must include "fsl,CHIP-ecm", "fsl,ecm" where
+      CHIP is the processor (mpc8572, mpc8544, etc.)
+
+  - reg
+      Usage: required
+      Value type: <prop-encoded-array>
+      Definition: A standard property.  The value specifies the
+          physical address offset and length of the CCSR space
+          registers.
+
+   - interrupts
+      Usage: required
+      Value type: <prop-encoded-array>
+
+   - interrupt-parent
+      Usage: required
+      Value type: <phandle>
+
+=====================================================================
diff -druNp linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/powerpc/fsl/gtm.txt linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/powerpc/fsl/gtm.txt
--- linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/powerpc/fsl/gtm.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/powerpc/fsl/gtm.txt	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,31 @@
+* Freescale General-purpose Timers Module
+
+Required properties:
+  - compatible : should be
+    "fsl,<chip>-gtm", "fsl,gtm" for SOC GTMs
+    "fsl,<chip>-qe-gtm", "fsl,qe-gtm", "fsl,gtm" for QE GTMs
+    "fsl,<chip>-cpm2-gtm", "fsl,cpm2-gtm", "fsl,gtm" for CPM2 GTMs
+  - reg : should contain gtm registers location and length (0x40).
+  - interrupts : should contain four interrupts.
+  - interrupt-parent : interrupt source phandle.
+  - clock-frequency : specifies the frequency driving the timer.
+
+Example:
+
+timer@500 {
+	compatible = "fsl,mpc8360-gtm", "fsl,gtm";
+	reg = <0x500 0x40>;
+	interrupts = <90 8 78 8 84 8 72 8>;
+	interrupt-parent = <&ipic>;
+	/* filled by u-boot */
+	clock-frequency = <0>;
+};
+
+timer@440 {
+	compatible = "fsl,mpc8360-qe-gtm", "fsl,qe-gtm", "fsl,gtm";
+	reg = <0x440 0x40>;
+	interrupts = <12 13 14 15>;
+	interrupt-parent = <&qeic>;
+	/* filled by u-boot */
+	clock-frequency = <0>;
+};
diff -druNp linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/powerpc/fsl/guts.txt linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/powerpc/fsl/guts.txt
--- linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/powerpc/fsl/guts.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/powerpc/fsl/guts.txt	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,25 @@
+* Global Utilities Block
+
+The global utilities block controls power management, I/O device
+enabling, power-on-reset configuration monitoring, general-purpose
+I/O signal configuration, alternate function selection for multiplexed
+signals, and clock control.
+
+Required properties:
+
+ - compatible : Should define the compatible device type for
+   global-utilities.
+ - reg : Offset and length of the register set for the device.
+
+Recommended properties:
+
+ - fsl,has-rstcr : Indicates that the global utilities register set
+   contains a functioning "reset control register" (i.e. the board
+   is wired to reset upon setting the HRESET_REQ bit in this register).
+
+Example:
+	global-utilities@e0000 {	/* global utilities block */
+		compatible = "fsl,mpc8548-guts";
+		reg = <e0000 1000>;
+		fsl,has-rstcr;
+	};
diff -druNp linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/powerpc/fsl/lbc.txt linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/powerpc/fsl/lbc.txt
--- linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/powerpc/fsl/lbc.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/powerpc/fsl/lbc.txt	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,35 @@
+* Chipselect/Local Bus
+
+Properties:
+- name : Should be localbus
+- #address-cells : Should be either two or three.  The first cell is the
+                   chipselect number, and the remaining cells are the
+                   offset into the chipselect.
+- #size-cells : Either one or two, depending on how large each chipselect
+                can be.
+- ranges : Each range corresponds to a single chipselect, and cover
+           the entire access window as configured.
+
+Example:
+	localbus@f0010100 {
+		compatible = "fsl,mpc8272-localbus",
+			   "fsl,pq2-localbus";
+		#address-cells = <2>;
+		#size-cells = <1>;
+		reg = <f0010100 40>;
+
+		ranges = <0 0 fe000000 02000000
+			  1 0 f4500000 00008000>;
+
+		flash@0,0 {
+			compatible = "jedec-flash";
+			reg = <0 0 2000000>;
+			bank-width = <4>;
+			device-width = <1>;
+		};
+
+		board-control@1,0 {
+			reg = <1 0 20>;
+			compatible = "fsl,mpc8272ads-bcsr";
+		};
+	};
diff -druNp linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/powerpc/fsl/mcm.txt linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/powerpc/fsl/mcm.txt
--- linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/powerpc/fsl/mcm.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/powerpc/fsl/mcm.txt	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,64 @@
+=====================================================================
+MPX LAW & Coherency Module Device Tree Binding
+Copyright (C) 2009 Freescale Semiconductor Inc.
+=====================================================================
+
+Local Access Window (LAW) Node
+
+The LAW node represents the region of CCSR space where local access
+windows are configured.  For MCM based devices this is the first 4k
+of CCSR space that includes CCSRBAR, ALTCBAR, ALTCAR, BPTR, and some
+number of local access windows as specified by fsl,num-laws.
+
+PROPERTIES
+
+  - compatible
+      Usage: required
+      Value type: <string>
+      Definition: Must include "fsl,mcm-law"
+
+  - reg
+      Usage: required
+      Value type: <prop-encoded-array>
+      Definition: A standard property.  The value specifies the
+          physical address offset and length of the CCSR space
+          registers.
+
+  - fsl,num-laws
+      Usage: required
+      Value type: <u32>
+      Definition: The value specifies the number of local access
+          windows for this device.
+
+=====================================================================
+
+MPX Coherency Module Node
+
+The MPX LAW node represents the region of CCSR space where MCM config
+and error reporting registers exist, this is the second 4k (0x1000)
+of CCSR space.
+
+PROPERTIES
+
+  - compatible
+      Usage: required
+      Value type: <string>
+      Definition: Must include "fsl,CHIP-mcm", "fsl,mcm" where
+      CHIP is the processor (mpc8641, mpc8610, etc.)
+
+  - reg
+      Usage: required
+      Value type: <prop-encoded-array>
+      Definition: A standard property.  The value specifies the
+          physical address offset and length of the CCSR space
+          registers.
+
+   - interrupts
+      Usage: required
+      Value type: <prop-encoded-array>
+
+   - interrupt-parent
+      Usage: required
+      Value type: <phandle>
+
+=====================================================================
diff -druNp linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/powerpc/fsl/mcu-mpc8349emitx.txt linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/powerpc/fsl/mcu-mpc8349emitx.txt
--- linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/powerpc/fsl/mcu-mpc8349emitx.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/powerpc/fsl/mcu-mpc8349emitx.txt	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,17 @@
+Freescale MPC8349E-mITX-compatible Power Management Micro Controller Unit (MCU)
+
+Required properties:
+- compatible : "fsl,<mcu-chip>-<board>", "fsl,mcu-mpc8349emitx".
+- reg : should specify I2C address (0x0a).
+- #gpio-cells : should be 2.
+- gpio-controller : should be present.
+
+Example:
+
+mcu@0a {
+	#gpio-cells = <2>;
+	compatible = "fsl,mc9s08qg8-mpc8349emitx",
+		     "fsl,mcu-mpc8349emitx";
+	reg = <0x0a>;
+	gpio-controller;
+};
diff -druNp linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/powerpc/fsl/mpc5121-psc.txt linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/powerpc/fsl/mpc5121-psc.txt
--- linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/powerpc/fsl/mpc5121-psc.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/powerpc/fsl/mpc5121-psc.txt	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,70 @@
+MPC5121 PSC Device Tree Bindings
+
+PSC in UART mode
+----------------
+
+For PSC in UART mode the needed PSC serial devices
+are specified by fsl,mpc5121-psc-uart nodes in the
+fsl,mpc5121-immr SoC node. Additionally the PSC FIFO
+Controller node fsl,mpc5121-psc-fifo is requered there:
+
+fsl,mpc5121-psc-uart nodes
+--------------------------
+
+Required properties :
+ - compatible : Should contain "fsl,mpc5121-psc-uart" and "fsl,mpc5121-psc"
+ - cell-index : Index of the PSC in hardware
+ - reg : Offset and length of the register set for the PSC device
+ - interrupts : <a b> where a is the interrupt number of the
+   PSC FIFO Controller and b is a field that represents an
+   encoding of the sense and level information for the interrupt.
+ - interrupt-parent : the phandle for the interrupt controller that
+   services interrupts for this device.
+
+Recommended properties :
+ - fsl,rx-fifo-size : the size of the RX fifo slice (a multiple of 4)
+ - fsl,tx-fifo-size : the size of the TX fifo slice (a multiple of 4)
+
+
+fsl,mpc5121-psc-fifo node
+-------------------------
+
+Required properties :
+ - compatible : Should be "fsl,mpc5121-psc-fifo"
+ - reg : Offset and length of the register set for the PSC
+         FIFO Controller
+ - interrupts : <a b> where a is the interrupt number of the
+   PSC FIFO Controller and b is a field that represents an
+   encoding of the sense and level information for the interrupt.
+ - interrupt-parent : the phandle for the interrupt controller that
+   services interrupts for this device.
+
+
+Example for a board using PSC0 and PSC1 devices in serial mode:
+
+serial@11000 {
+	compatible = "fsl,mpc5121-psc-uart", "fsl,mpc5121-psc";
+	cell-index = <0>;
+	reg = <0x11000 0x100>;
+	interrupts = <40 0x8>;
+	interrupt-parent = < &ipic >;
+	fsl,rx-fifo-size = <16>;
+	fsl,tx-fifo-size = <16>;
+};
+
+serial@11100 {
+	compatible = "fsl,mpc5121-psc-uart", "fsl,mpc5121-psc";
+	cell-index = <1>;
+	reg = <0x11100 0x100>;
+	interrupts = <40 0x8>;
+	interrupt-parent = < &ipic >;
+	fsl,rx-fifo-size = <16>;
+	fsl,tx-fifo-size = <16>;
+};
+
+pscfifo@11f00 {
+	compatible = "fsl,mpc5121-psc-fifo";
+	reg = <0x11f00 0x100>;
+	interrupts = <40 0x8>;
+	interrupt-parent = < &ipic >;
+};
diff -druNp linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/powerpc/fsl/mpc5200.txt linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/powerpc/fsl/mpc5200.txt
--- linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/powerpc/fsl/mpc5200.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/powerpc/fsl/mpc5200.txt	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,198 @@
+MPC5200 Device Tree Bindings
+----------------------------
+
+(c) 2006-2009 Secret Lab Technologies Ltd
+Grant Likely <grant.likely@secretlab.ca>
+
+Naming conventions
+------------------
+For mpc5200 on-chip devices, the format for each compatible value is
+<chip>-<device>[-<mode>].  The OS should be able to match a device driver
+to the device based solely on the compatible value.  If two drivers
+match on the compatible list; the 'most compatible' driver should be
+selected.
+
+The split between the MPC5200 and the MPC5200B leaves a bit of a
+conundrum.  How should the compatible property be set up to provide
+maximum compatibility information; but still accurately describe the
+chip?  For the MPC5200; the answer is easy.  Most of the SoC devices
+originally appeared on the MPC5200.  Since they didn't exist anywhere
+else; the 5200 compatible properties will contain only one item;
+"fsl,mpc5200-<device>".
+
+The 5200B is almost the same as the 5200, but not quite.  It fixes
+silicon bugs and it adds a small number of enhancements.  Most of the
+devices either provide exactly the same interface as on the 5200.  A few
+devices have extra functions but still have a backwards compatible mode.
+To express this information as completely as possible, 5200B device trees
+should have two items in the compatible list:
+	compatible = "fsl,mpc5200b-<device>","fsl,mpc5200-<device>";
+
+It is *strongly* recommended that 5200B device trees follow this convention
+(instead of only listing the base mpc5200 item).
+
+ie. ethernet on mpc5200: compatible = "fsl,mpc5200-fec";
+    ethernet on mpc5200b: compatible = "fsl,mpc5200b-fec", "fsl,mpc5200-fec";
+
+Modal devices, like PSCs, also append the configured function to the
+end of the compatible field.  ie. A PSC in i2s mode would specify
+"fsl,mpc5200-psc-i2s", not "fsl,mpc5200-i2s".  This convention is chosen to
+avoid naming conflicts with non-psc devices providing the same
+function.  For example, "fsl,mpc5200-spi" and "fsl,mpc5200-psc-spi" describe
+the mpc5200 simple spi device and a PSC spi mode respectively.
+
+At the time of writing, exact chip may be either 'fsl,mpc5200' or
+'fsl,mpc5200b'.
+
+The soc node
+------------
+This node describes the on chip SOC peripherals.  Every mpc5200 based
+board will have this node, and as such there is a common naming
+convention for SOC devices.
+
+Required properties:
+name			description
+----			-----------
+ranges			Memory range of the internal memory mapped registers.
+			Should be <0 [baseaddr] 0xc000>
+reg			Should be <[baseaddr] 0x100>
+compatible		mpc5200: "fsl,mpc5200-immr"
+			mpc5200b: "fsl,mpc5200b-immr"
+system-frequency	'fsystem' frequency in Hz; XLB, IPB, USB and PCI
+			clocks are derived from the fsystem clock.
+bus-frequency		IPB bus frequency in Hz.  Clock rate
+			used by most of the soc devices.
+
+soc child nodes
+---------------
+Any on chip SOC devices available to Linux must appear as soc5200 child nodes.
+
+Note: The tables below show the value for the mpc5200.  A mpc5200b device
+tree should use the "fsl,mpc5200b-<device>","fsl,mpc5200-<device>" form.
+
+Required soc5200 child nodes:
+name				compatible		Description
+----				----------		-----------
+cdm@<addr>			fsl,mpc5200-cdm		Clock Distribution
+interrupt-controller@<addr>	fsl,mpc5200-pic		need an interrupt
+							controller to boot
+bestcomm@<addr>			fsl,mpc5200-bestcomm	Bestcomm DMA controller
+
+Recommended soc5200 child nodes; populate as needed for your board
+name		compatible		Description
+----		----------		-----------
+timer@<addr>	fsl,mpc5200-gpt		 General purpose timers
+gpio@<addr>	fsl,mpc5200-gpio	 MPC5200 simple gpio controller
+gpio@<addr>	fsl,mpc5200-gpio-wkup	 MPC5200 wakeup gpio controller
+rtc@<addr>	fsl,mpc5200-rtc		 Real time clock
+mscan@<addr>	fsl,mpc5200-mscan	 CAN bus controller
+pci@<addr>	fsl,mpc5200-pci		 PCI bridge
+serial@<addr>	fsl,mpc5200-psc-uart	 PSC in serial mode
+i2s@<addr>	fsl,mpc5200-psc-i2s	 PSC in i2s mode
+ac97@<addr>	fsl,mpc5200-psc-ac97	 PSC in ac97 mode
+spi@<addr>	fsl,mpc5200-psc-spi	 PSC in spi mode
+irda@<addr>	fsl,mpc5200-psc-irda	 PSC in IrDA mode
+spi@<addr>	fsl,mpc5200-spi		 MPC5200 spi device
+ethernet@<addr>	fsl,mpc5200-fec		 MPC5200 ethernet device
+ata@<addr>	fsl,mpc5200-ata		 IDE ATA interface
+i2c@<addr>	fsl,mpc5200-i2c		 I2C controller
+usb@<addr>	fsl,mpc5200-ohci,ohci-be USB controller
+xlb@<addr>	fsl,mpc5200-xlb		 XLB arbitrator
+
+fsl,mpc5200-gpt nodes
+---------------------
+On the mpc5200 and 5200b, GPT0 has a watchdog timer function.  If the board
+design supports the internal wdt, then the device node for GPT0 should
+include the empty property 'fsl,has-wdt'.  Note that this does not activate
+the watchdog.  The timer will function as a GPT if the timer api is used, and
+it will function as watchdog if the watchdog device is used.  The watchdog
+mode has priority over the gpt mode, i.e. if the watchdog is activated, any
+gpt api call to this timer will fail with -EBUSY.
+
+If you add the property
+	fsl,wdt-on-boot = <n>;
+GPT0 will be marked as in-use watchdog, i.e. blocking every gpt access to it.
+If n>0, the watchdog is started with a timeout of n seconds.  If n=0, the
+configuration of the watchdog is not touched.  This is useful in two cases:
+- just mark GPT0 as watchdog, blocking gpt accesses, and configure it later;
+- do not touch a configuration assigned by the boot loader which supervises
+  the boot process itself.
+
+The watchdog will respect the CONFIG_WATCHDOG_NOWAYOUT option.
+
+An mpc5200-gpt can be used as a single line GPIO controller.  To do so,
+add the following properties to the gpt node:
+	gpio-controller;
+	#gpio-cells = <2>;
+When referencing the GPIO line from another node, the first cell must always
+be zero and the second cell represents the gpio flags and described in the
+gpio device tree binding.
+
+An mpc5200-gpt can be used as a single line edge sensitive interrupt
+controller.  To do so, add the following properties to the gpt node:
+	interrupt-controller;
+	#interrupt-cells = <1>;
+When referencing the IRQ line from another node, the cell represents the
+sense mode; 1 for edge rising, 2 for edge falling.
+
+fsl,mpc5200-psc nodes
+---------------------
+The PSCs should include a cell-index which is the index of the PSC in
+hardware.  cell-index is used to determine which shared SoC registers to
+use when setting up PSC clocking.  cell-index number starts at '0'.  ie:
+	PSC1 has 'cell-index = <0>'
+	PSC4 has 'cell-index = <3>'
+
+PSC in i2s mode:  The mpc5200 and mpc5200b PSCs are not compatible when in
+i2s mode.  An 'mpc5200b-psc-i2s' node cannot include 'mpc5200-psc-i2s' in the
+compatible field.
+
+
+fsl,mpc5200-gpio and fsl,mpc5200-gpio-wkup nodes
+------------------------------------------------
+Each GPIO controller node should have the empty property gpio-controller and
+#gpio-cells set to 2. First cell is the GPIO number which is interpreted
+according to the bit numbers in the GPIO control registers. The second cell
+is for flags which is currently unused.
+
+fsl,mpc5200-fec nodes
+---------------------
+The FEC node can specify one of the following properties to configure
+the MII link:
+- fsl,7-wire-mode - An empty property that specifies the link uses 7-wire
+                    mode instead of MII
+- current-speed   - Specifies that the MII should be configured for a fixed
+                    speed.  This property should contain two cells.  The
+                    first cell specifies the speed in Mbps and the second
+                    should be '0' for half duplex and '1' for full duplex
+- phy-handle      - Contains a phandle to an Ethernet PHY.
+
+Interrupt controller (fsl,mpc5200-pic) node
+-------------------------------------------
+The mpc5200 pic binding splits hardware IRQ numbers into two levels.  The
+split reflects the layout of the PIC hardware itself, which groups
+interrupts into one of three groups; CRIT, MAIN or PERP.  Also, the
+Bestcomm dma engine has it's own set of interrupt sources which are
+cascaded off of peripheral interrupt 0, which the driver interprets as a
+fourth group, SDMA.
+
+The interrupts property for device nodes using the mpc5200 pic consists
+of three cells; <L1 L2 level>
+
+    L1 := [CRIT=0, MAIN=1, PERP=2, SDMA=3]
+    L2 := interrupt number; directly mapped from the value in the
+          "ICTL PerStat, MainStat, CritStat Encoded Register"
+    level := [LEVEL_HIGH=0, EDGE_RISING=1, EDGE_FALLING=2, LEVEL_LOW=3]
+
+For external IRQs, use the following interrupt property values (how to
+specify external interrupts is a frequently asked question):
+External interrupts:
+	external irq0:	interrupts = <0 0 n>;
+	external irq1:	interrupts = <1 1 n>;
+	external irq2:	interrupts = <1 2 n>;
+	external irq3:	interrupts = <1 3 n>;
+'n' is sense (0: level high, 1: edge rising, 2: edge falling 3: level low)
+
+fsl,mpc5200-mscan nodes
+-----------------------
+See file can.txt in this directory.
diff -druNp linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/powerpc/fsl/mpic.txt linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/powerpc/fsl/mpic.txt
--- linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/powerpc/fsl/mpic.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/powerpc/fsl/mpic.txt	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,42 @@
+* OpenPIC and its interrupt numbers on Freescale's e500/e600 cores
+
+The OpenPIC specification does not specify which interrupt source has to
+become which interrupt number. This is up to the software implementation
+of the interrupt controller. The only requirement is that every
+interrupt source has to have an unique interrupt number / vector number.
+To accomplish this the current implementation assigns the number zero to
+the first source, the number one to the second source and so on until
+all interrupt sources have their unique number.
+Usually the assigned vector number equals the interrupt number mentioned
+in the documentation for a given core / CPU. This is however not true
+for the e500 cores (MPC85XX CPUs) where the documentation distinguishes
+between internal and external interrupt sources and starts counting at
+zero for both of them.
+
+So what to write for external interrupt source X or internal interrupt
+source Y into the device tree? Here is an example:
+
+The memory map for the interrupt controller in the MPC8544[0] shows,
+that the first interrupt source starts at 0x5_0000 (PIC Register Address
+Map-Interrupt Source Configuration Registers). This source becomes the
+number zero therefore:
+ External interrupt 0 = interrupt number 0
+ External interrupt 1 = interrupt number 1
+ External interrupt 2 = interrupt number 2
+ ...
+Every interrupt number allocates 0x20 bytes register space. So to get
+its number it is sufficient to shift the lower 16bits to right by five.
+So for the external interrupt 10 we have:
+  0x0140 >> 5 = 10
+
+After the external sources, the internal sources follow. The in core I2C
+controller on the MPC8544 for instance has the internal source number
+27. Oo obtain its interrupt number we take the lower 16bits of its memory
+address (0x5_0560) and shift it right:
+ 0x0560 >> 5 = 43
+
+Therefore the I2C device node for the MPC8544 CPU has to have the
+interrupt number 43 specified in the device tree.
+
+[0] MPC8544E PowerQUICCTM III, Integrated Host Processor Family Reference Manual
+    MPC8544ERM Rev. 1 10/2007
diff -druNp linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/powerpc/fsl/msi-pic.txt linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/powerpc/fsl/msi-pic.txt
--- linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/powerpc/fsl/msi-pic.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/powerpc/fsl/msi-pic.txt	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,36 @@
+* Freescale MSI interrupt controller
+
+Required properties:
+- compatible : compatible list, contains 2 entries,
+  first is "fsl,CHIP-msi", where CHIP is the processor(mpc8610, mpc8572,
+  etc.) and the second is "fsl,mpic-msi" or "fsl,ipic-msi" depending on
+  the parent type.
+- reg : should contain the address and the length of the shared message
+  interrupt register set.
+- msi-available-ranges: use <start count> style section to define which
+  msi interrupt can be used in the 256 msi interrupts. This property is
+  optional, without this, all the 256 MSI interrupts can be used.
+- interrupts : each one of the interrupts here is one entry per 32 MSIs,
+  and routed to the host interrupt controller. the interrupts should
+  be set as edge sensitive.
+- interrupt-parent: the phandle for the interrupt controller
+  that services interrupts for this device. for 83xx cpu, the interrupts
+  are routed to IPIC, and for 85xx/86xx cpu the interrupts are routed
+  to MPIC.
+
+Example:
+	msi@41600 {
+		compatible = "fsl,mpc8610-msi", "fsl,mpic-msi";
+		reg = <0x41600 0x80>;
+		msi-available-ranges = <0 0x100>;
+		interrupts = <
+			0xe0 0
+			0xe1 0
+			0xe2 0
+			0xe3 0
+			0xe4 0
+			0xe5 0
+			0xe6 0
+			0xe7 0>;
+		interrupt-parent = <&mpic>;
+	};
diff -druNp linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/powerpc/fsl/pmc.txt linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/powerpc/fsl/pmc.txt
--- linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/powerpc/fsl/pmc.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/powerpc/fsl/pmc.txt	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,63 @@
+* Power Management Controller
+
+Properties:
+- compatible: "fsl,<chip>-pmc".
+
+  "fsl,mpc8349-pmc" should be listed for any chip whose PMC is
+  compatible.  "fsl,mpc8313-pmc" should also be listed for any chip
+  whose PMC is compatible, and implies deep-sleep capability.
+
+  "fsl,mpc8548-pmc" should be listed for any chip whose PMC is
+  compatible.  "fsl,mpc8536-pmc" should also be listed for any chip
+  whose PMC is compatible, and implies deep-sleep capability.
+
+  "fsl,mpc8641d-pmc" should be listed for any chip whose PMC is
+  compatible; all statements below that apply to "fsl,mpc8548-pmc" also
+  apply to "fsl,mpc8641d-pmc".
+
+  Compatibility does not include bit assignments in SCCR/PMCDR/DEVDISR; these
+  bit assignments are indicated via the sleep specifier in each device's
+  sleep property.
+
+- reg: For devices compatible with "fsl,mpc8349-pmc", the first resource
+  is the PMC block, and the second resource is the Clock Configuration
+  block.
+
+  For devices compatible with "fsl,mpc8548-pmc", the first resource
+  is a 32-byte block beginning with DEVDISR.
+
+- interrupts: For "fsl,mpc8349-pmc"-compatible devices, the first
+  resource is the PMC block interrupt.
+
+- fsl,mpc8313-wakeup-timer: For "fsl,mpc8313-pmc"-compatible devices,
+  this is a phandle to an "fsl,gtm" node on which timer 4 can be used as
+  a wakeup source from deep sleep.
+
+Sleep specifiers:
+
+  fsl,mpc8349-pmc: Sleep specifiers consist of one cell.  For each bit
+  that is set in the cell, the corresponding bit in SCCR will be saved
+  and cleared on suspend, and restored on resume.  This sleep controller
+  supports disabling and resuming devices at any time.
+
+  fsl,mpc8536-pmc: Sleep specifiers consist of three cells, the third of
+  which will be ORed into PMCDR upon suspend, and cleared from PMCDR
+  upon resume.  The first two cells are as described for fsl,mpc8578-pmc.
+  This sleep controller only supports disabling devices during system
+  sleep, or permanently.
+
+  fsl,mpc8548-pmc: Sleep specifiers consist of one or two cells, the
+  first of which will be ORed into DEVDISR (and the second into
+  DEVDISR2, if present -- this cell should be zero or absent if the
+  hardware does not have DEVDISR2) upon a request for permanent device
+  disabling.  This sleep controller does not support configuring devices
+  to disable during system sleep (unless supported by another compatible
+  match), or dynamically.
+
+Example:
+
+	power@b00 {
+		compatible = "fsl,mpc8313-pmc", "fsl,mpc8349-pmc";
+		reg = <0xb00 0x100 0xa00 0x100>;
+		interrupts = <80 8>;
+	};
diff -druNp linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/powerpc/fsl/sec.txt linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/powerpc/fsl/sec.txt
--- linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/powerpc/fsl/sec.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/powerpc/fsl/sec.txt	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,68 @@
+Freescale SoC SEC Security Engines
+
+Required properties:
+
+- compatible : Should contain entries for this and backward compatible
+  SEC versions, high to low, e.g., "fsl,sec2.1", "fsl,sec2.0"
+- reg : Offset and length of the register set for the device
+- interrupts : the SEC's interrupt number
+- fsl,num-channels : An integer representing the number of channels
+  available.
+- fsl,channel-fifo-len : An integer representing the number of
+  descriptor pointers each channel fetch fifo can hold.
+- fsl,exec-units-mask : The bitmask representing what execution units
+  (EUs) are available. It's a single 32-bit cell. EU information
+  should be encoded following the SEC's Descriptor Header Dword
+  EU_SEL0 field documentation, i.e. as follows:
+
+	bit 0  = reserved - should be 0
+	bit 1  = set if SEC has the ARC4 EU (AFEU)
+	bit 2  = set if SEC has the DES/3DES EU (DEU)
+	bit 3  = set if SEC has the message digest EU (MDEU/MDEU-A)
+	bit 4  = set if SEC has the random number generator EU (RNG)
+	bit 5  = set if SEC has the public key EU (PKEU)
+	bit 6  = set if SEC has the AES EU (AESU)
+	bit 7  = set if SEC has the Kasumi EU (KEU)
+	bit 8  = set if SEC has the CRC EU (CRCU)
+	bit 11 = set if SEC has the message digest EU extended alg set (MDEU-B)
+
+remaining bits are reserved for future SEC EUs.
+
+- fsl,descriptor-types-mask : The bitmask representing what descriptors
+  are available. It's a single 32-bit cell. Descriptor type information
+  should be encoded following the SEC's Descriptor Header Dword DESC_TYPE
+  field documentation, i.e. as follows:
+
+	bit 0  = set if SEC supports the aesu_ctr_nonsnoop desc. type
+	bit 1  = set if SEC supports the ipsec_esp descriptor type
+	bit 2  = set if SEC supports the common_nonsnoop desc. type
+	bit 3  = set if SEC supports the 802.11i AES ccmp desc. type
+	bit 4  = set if SEC supports the hmac_snoop_no_afeu desc. type
+	bit 5  = set if SEC supports the srtp descriptor type
+	bit 6  = set if SEC supports the non_hmac_snoop_no_afeu desc.type
+	bit 7  = set if SEC supports the pkeu_assemble descriptor type
+	bit 8  = set if SEC supports the aesu_key_expand_output desc.type
+	bit 9  = set if SEC supports the pkeu_ptmul descriptor type
+	bit 10 = set if SEC supports the common_nonsnoop_afeu desc. type
+	bit 11 = set if SEC supports the pkeu_ptadd_dbl descriptor type
+
+  ..and so on and so forth.
+
+Optional properties:
+
+- interrupt-parent : the phandle for the interrupt controller that
+  services interrupts for this device.
+
+Example:
+
+	/* MPC8548E */
+	crypto@30000 {
+		compatible = "fsl,sec2.1", "fsl,sec2.0";
+		reg = <0x30000 0x10000>;
+		interrupts = <29 2>;
+		interrupt-parent = <&mpic>;
+		fsl,num-channels = <4>;
+		fsl,channel-fifo-len = <24>;
+		fsl,exec-units-mask = <0xfe>;
+		fsl,descriptor-types-mask = <0x12b0ebf>;
+	};
diff -druNp linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/powerpc/fsl/ssi.txt linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/powerpc/fsl/ssi.txt
--- linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/powerpc/fsl/ssi.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/powerpc/fsl/ssi.txt	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,73 @@
+Freescale Synchronous Serial Interface
+
+The SSI is a serial device that communicates with audio codecs.  It can
+be programmed in AC97, I2S, left-justified, or right-justified modes.
+
+Required properties:
+- compatible:       Compatible list, contains "fsl,ssi".
+- cell-index:       The SSI, <0> = SSI1, <1> = SSI2, and so on.
+- reg:              Offset and length of the register set for the device.
+- interrupts:       <a b> where a is the interrupt number and b is a
+                    field that represents an encoding of the sense and
+                    level information for the interrupt.  This should be
+                    encoded based on the information in section 2)
+                    depending on the type of interrupt controller you
+                    have.
+- interrupt-parent: The phandle for the interrupt controller that
+                    services interrupts for this device.
+- fsl,mode:         The operating mode for the SSI interface.
+                    "i2s-slave" - I2S mode, SSI is clock slave
+                    "i2s-master" - I2S mode, SSI is clock master
+                    "lj-slave" - left-justified mode, SSI is clock slave
+                    "lj-master" - l.j. mode, SSI is clock master
+                    "rj-slave" - right-justified mode, SSI is clock slave
+                    "rj-master" - r.j., SSI is clock master
+                    "ac97-slave" - AC97 mode, SSI is clock slave
+                    "ac97-master" - AC97 mode, SSI is clock master
+- fsl,playback-dma: Phandle to a node for the DMA channel to use for
+                    playback of audio.  This is typically dictated by SOC
+                    design.  See the notes below.
+- fsl,capture-dma:  Phandle to a node for the DMA channel to use for
+                    capture (recording) of audio.  This is typically dictated
+                    by SOC design.  See the notes below.
+- fsl,fifo-depth:   The number of elements in the transmit and receive FIFOs.
+                    This number is the maximum allowed value for SFCSR[TFWM0].
+- fsl,ssi-asynchronous:
+                    If specified, the SSI is to be programmed in asynchronous
+                    mode.  In this mode, pins SRCK, STCK, SRFS, and STFS must
+                    all be connected to valid signals.  In synchronous mode,
+                    SRCK and SRFS are ignored.  Asynchronous mode allows
+                    playback and capture to use different sample sizes and
+                    sample rates.  Some drivers may require that SRCK and STCK
+                    be connected together, and SRFS and STFS be connected
+                    together.  This would still allow different sample sizes,
+                    but not different sample rates.
+
+Optional properties:
+- codec-handle:     Phandle to a 'codec' node that defines an audio
+                    codec connected to this SSI.  This node is typically
+                    a child of an I2C or other control node.
+
+Child 'codec' node required properties:
+- compatible:       Compatible list, contains the name of the codec
+
+Child 'codec' node optional properties:
+- clock-frequency:  The frequency of the input clock, which typically comes
+                    from an on-board dedicated oscillator.
+
+Notes on fsl,playback-dma and fsl,capture-dma:
+
+On SOCs that have an SSI, specific DMA channels are hard-wired for playback
+and capture.  On the MPC8610, for example, SSI1 must use DMA channel 0 for
+playback and DMA channel 1 for capture.  SSI2 must use DMA channel 2 for
+playback and DMA channel 3 for capture.  The developer can choose which
+DMA controller to use, but the channels themselves are hard-wired.  The
+purpose of these two properties is to represent this hardware design.
+
+The device tree nodes for the DMA channels that are referenced by
+"fsl,playback-dma" and "fsl,capture-dma" must be marked as compatible with
+"fsl,ssi-dma-channel".  The SOC-specific compatible string (e.g.
+"fsl,mpc8610-dma-channel") can remain.  If these nodes are left as
+"fsl,elo-dma-channel" or "fsl,eloplus-dma-channel", then the generic Elo DMA
+drivers (fsldma) will attempt to use them, and it will conflict with the
+sound drivers.
diff -druNp linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/powerpc/nintendo/gamecube.txt linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/powerpc/nintendo/gamecube.txt
--- linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/powerpc/nintendo/gamecube.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/powerpc/nintendo/gamecube.txt	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,109 @@
+
+Nintendo GameCube device tree
+=============================
+
+1) The "flipper" node
+
+  This node represents the multi-function "Flipper" chip, which packages
+  many of the devices found in the Nintendo GameCube.
+
+  Required properties:
+
+   - compatible : Should be "nintendo,flipper"
+
+1.a) The Video Interface (VI) node
+
+  Represents the interface between the graphics processor and a external
+  video encoder.
+
+  Required properties:
+
+   - compatible : should be "nintendo,flipper-vi"
+   - reg : should contain the VI registers location and length
+   - interrupts : should contain the VI interrupt
+
+1.b) The Processor Interface (PI) node
+
+  Represents the data and control interface between the main processor
+  and graphics and audio processor.
+
+  Required properties:
+
+  - compatible : should be "nintendo,flipper-pi"
+  - reg : should contain the PI registers location and length
+
+1.b.i) The "Flipper" interrupt controller node
+
+  Represents the interrupt controller within the "Flipper" chip.
+  The node for the "Flipper" interrupt controller must be placed under
+  the PI node.
+
+  Required properties:
+
+  - compatible : should be "nintendo,flipper-pic"
+
+1.c) The Digital Signal Procesor (DSP) node
+
+  Represents the digital signal processor interface, designed to offload
+  audio related tasks.
+
+  Required properties:
+
+   - compatible : should be "nintendo,flipper-dsp"
+   - reg : should contain the DSP registers location and length
+   - interrupts : should contain the DSP interrupt
+
+1.c.i) The Auxiliary RAM (ARAM) node
+
+  Represents the non cpu-addressable ram designed mainly to store audio
+  related information.
+  The ARAM node must be placed under the DSP node.
+
+  Required properties:
+
+   - compatible : should be "nintendo,flipper-aram"
+   - reg : should contain the ARAM start (zero-based) and length
+
+1.d) The Disk Interface (DI) node
+
+  Represents the interface used to communicate with mass storage devices.
+
+  Required properties:
+
+   - compatible : should be "nintendo,flipper-di"
+   - reg : should contain the DI registers location and length
+   - interrupts : should contain the DI interrupt
+
+1.e) The Audio Interface (AI) node
+
+  Represents the interface to the external 16-bit stereo digital-to-analog
+  converter.
+
+  Required properties:
+
+   - compatible : should be "nintendo,flipper-ai"
+   - reg : should contain the AI registers location and length
+   - interrupts : should contain the AI interrupt
+
+1.f) The Serial Interface (SI) node
+
+  Represents the interface to the four single bit serial interfaces.
+  The SI is a proprietary serial interface used normally to control gamepads.
+  It's NOT a RS232-type interface.
+
+  Required properties:
+
+   - compatible : should be "nintendo,flipper-si"
+   - reg : should contain the SI registers location and length
+   - interrupts : should contain the SI interrupt
+
+1.g) The External Interface (EXI) node
+
+  Represents the multi-channel SPI-like interface.
+
+  Required properties:
+
+   - compatible : should be "nintendo,flipper-exi"
+   - reg : should contain the EXI registers location and length
+   - interrupts : should contain the EXI interrupt
+
diff -druNp linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/powerpc/nintendo/wii.txt linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/powerpc/nintendo/wii.txt
--- linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/powerpc/nintendo/wii.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/powerpc/nintendo/wii.txt	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,184 @@
+
+Nintendo Wii device tree
+========================
+
+0) The root node
+
+  This node represents the Nintendo Wii video game console.
+
+  Required properties:
+
+   - model : Should be "nintendo,wii"
+   - compatible : Should be "nintendo,wii"
+
+1) The "hollywood" node
+
+  This node represents the multi-function "Hollywood" chip, which packages
+  many of the devices found in the Nintendo Wii.
+
+  Required properties:
+
+   - compatible : Should be "nintendo,hollywood"
+
+1.a) The Video Interface (VI) node
+
+  Represents the interface between the graphics processor and a external
+  video encoder.
+
+  Required properties:
+
+   - compatible : should be "nintendo,hollywood-vi","nintendo,flipper-vi"
+   - reg : should contain the VI registers location and length
+   - interrupts : should contain the VI interrupt
+
+1.b) The Processor Interface (PI) node
+
+  Represents the data and control interface between the main processor
+  and graphics and audio processor.
+
+  Required properties:
+
+  - compatible : should be "nintendo,hollywood-pi","nintendo,flipper-pi"
+  - reg : should contain the PI registers location and length
+
+1.b.i) The "Flipper" interrupt controller node
+
+  Represents the "Flipper" interrupt controller within the "Hollywood" chip.
+  The node for the "Flipper" interrupt controller must be placed under
+  the PI node.
+
+  Required properties:
+
+  - #interrupt-cells : <1>
+  - compatible : should be "nintendo,flipper-pic"
+  - interrupt-controller
+
+1.c) The Digital Signal Procesor (DSP) node
+
+  Represents the digital signal processor interface, designed to offload
+  audio related tasks.
+
+  Required properties:
+
+   - compatible : should be "nintendo,hollywood-dsp","nintendo,flipper-dsp"
+   - reg : should contain the DSP registers location and length
+   - interrupts : should contain the DSP interrupt
+
+1.d) The Serial Interface (SI) node
+
+  Represents the interface to the four single bit serial interfaces.
+  The SI is a proprietary serial interface used normally to control gamepads.
+  It's NOT a RS232-type interface.
+
+  Required properties:
+
+   - compatible : should be "nintendo,hollywood-si","nintendo,flipper-si"
+   - reg : should contain the SI registers location and length
+   - interrupts : should contain the SI interrupt
+
+1.e) The Audio Interface (AI) node
+
+  Represents the interface to the external 16-bit stereo digital-to-analog
+  converter.
+
+  Required properties:
+
+   - compatible : should be "nintendo,hollywood-ai","nintendo,flipper-ai"
+   - reg : should contain the AI registers location and length
+   - interrupts : should contain the AI interrupt
+
+1.f) The External Interface (EXI) node
+
+  Represents the multi-channel SPI-like interface.
+
+  Required properties:
+
+   - compatible : should be "nintendo,hollywood-exi","nintendo,flipper-exi"
+   - reg : should contain the EXI registers location and length
+   - interrupts : should contain the EXI interrupt
+
+1.g) The Open Host Controller Interface (OHCI) nodes
+
+  Represent the USB 1.x Open Host Controller Interfaces.
+
+  Required properties:
+
+   - compatible : should be "nintendo,hollywood-usb-ohci","usb-ohci"
+   - reg : should contain the OHCI registers location and length
+   - interrupts : should contain the OHCI interrupt
+
+1.h) The Enhanced Host Controller Interface (EHCI) node
+
+  Represents the USB 2.0 Enhanced Host Controller Interface.
+
+  Required properties:
+
+   - compatible : should be "nintendo,hollywood-usb-ehci","usb-ehci"
+   - reg : should contain the EHCI registers location and length
+   - interrupts : should contain the EHCI interrupt
+
+1.i) The Secure Digital Host Controller Interface (SDHCI) nodes
+
+  Represent the Secure Digital Host Controller Interfaces.
+
+  Required properties:
+
+   - compatible : should be "nintendo,hollywood-sdhci","sdhci"
+   - reg : should contain the SDHCI registers location and length
+   - interrupts : should contain the SDHCI interrupt
+
+1.j) The Inter-Processsor Communication (IPC) node
+
+  Represent the Inter-Processor Communication interface. This interface
+  enables communications between the Broadway and the Starlet processors.
+
+   - compatible : should be "nintendo,hollywood-ipc"
+   - reg : should contain the IPC registers location and length
+   - interrupts : should contain the IPC interrupt
+
+1.k) The "Hollywood" interrupt controller node
+
+  Represents the "Hollywood" interrupt controller within the
+  "Hollywood" chip.
+
+  Required properties:
+
+  - #interrupt-cells : <1>
+  - compatible : should be "nintendo,hollywood-pic"
+  - reg : should contain the controller registers location and length
+  - interrupt-controller
+  - interrupts : should contain the cascade interrupt of the "flipper" pic
+  - interrupt-parent: should contain the phandle of the "flipper" pic
+
+1.l) The General Purpose I/O (GPIO) controller node
+
+  Represents the dual access 32 GPIO controller interface.
+
+  Required properties:
+
+  - #gpio-cells : <2>
+  - compatible : should be "nintendo,hollywood-gpio"
+  - reg : should contain the IPC registers location and length
+  - gpio-controller
+
+1.m) The control node
+
+  Represents the control interface used to setup several miscellaneous
+  settings of the "Hollywood" chip like boot memory mappings, resets,
+  disk interface mode, etc.
+
+  Required properties:
+
+   - compatible : should be "nintendo,hollywood-control"
+   - reg : should contain the control registers location and length
+
+1.n) The Disk Interface (DI) node
+
+  Represents the interface used to communicate with mass storage devices.
+
+  Required properties:
+
+   - compatible : should be "nintendo,hollywood-di"
+   - reg : should contain the DI registers location and length
+   - interrupts : should contain the DI interrupt
+
diff -druNp linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/spi/fsl-spi.txt linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/spi/fsl-spi.txt
--- linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/spi/fsl-spi.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/spi/fsl-spi.txt	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,53 @@
+* SPI (Serial Peripheral Interface)
+
+Required properties:
+- cell-index : QE SPI subblock index.
+		0: QE subblock SPI1
+		1: QE subblock SPI2
+- compatible : should be "fsl,spi".
+- mode : the SPI operation mode, it can be "cpu" or "cpu-qe".
+- reg : Offset and length of the register set for the device
+- interrupts : <a b> where a is the interrupt number and b is a
+  field that represents an encoding of the sense and level
+  information for the interrupt.  This should be encoded based on
+  the information in section 2) depending on the type of interrupt
+  controller you have.
+- interrupt-parent : the phandle for the interrupt controller that
+  services interrupts for this device.
+
+Optional properties:
+- gpios : specifies the gpio pins to be 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.
+
+Example:
+	spi@4c0 {
+		cell-index = <0>;
+		compatible = "fsl,spi";
+		reg = <4c0 40>;
+		interrupts = <82 0>;
+		interrupt-parent = <700>;
+		mode = "cpu";
+		gpios = <&gpio 18 1	// device reg=<0>
+			 &gpio 19 1>;	// device reg=<1>
+	};
+
+
+* eSPI (Enhanced Serial Peripheral Interface)
+
+Required properties:
+- compatible : should be "fsl,mpc8536-espi".
+- reg : Offset and length of the register set for the device.
+- interrupts : should contain eSPI interrupt, the device has one interrupt.
+- fsl,espi-num-chipselects : the number of the chipselect signals.
+
+Example:
+	spi@110000 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "fsl,mpc8536-espi";
+		reg = <0x110000 0x1000>;
+		interrupts = <53 0x2>;
+		interrupt-parent = <&mpic>;
+		fsl,espi-num-chipselects = <4>;
+	};
diff -druNp linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/spi/spi-bus.txt linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/spi/spi-bus.txt
--- linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/spi/spi-bus.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/spi/spi-bus.txt	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,57 @@
+SPI (Serial Peripheral Interface) busses
+
+SPI busses can be described with a node for the SPI master device
+and a set of child nodes for each SPI slave on the bus.  For this
+discussion, it is assumed that the system's SPI controller is in
+SPI master mode.  This binding does not describe SPI controllers
+in slave mode.
+
+The SPI master node requires the following properties:
+- #address-cells  - number of cells required to define a chip select
+    		address on the SPI bus.
+- #size-cells     - should be zero.
+- compatible      - name of SPI bus controller following generic names
+    		recommended practice.
+No other properties are required in the SPI bus node.  It is assumed
+that a driver for an SPI bus device will understand that it is an SPI bus.
+However, the binding does not attempt to define the specific method for
+assigning chip select numbers.  Since SPI chip select configuration is
+flexible and non-standardized, it is left out of this binding with the
+assumption that board specific platform code will be used to manage
+chip selects.  Individual drivers can define additional properties to
+support describing the chip select layout.
+
+SPI slave nodes must be children of the SPI master node and can
+contain the following properties.
+- reg             - (required) chip select address of device.
+- compatible      - (required) name of SPI device following generic names
+    		recommended practice
+- spi-max-frequency - (required) Maximum SPI clocking speed of device in Hz
+- spi-cpol        - (optional) Empty property indicating device requires
+    		inverse clock polarity (CPOL) mode
+- spi-cpha        - (optional) Empty property indicating device requires
+    		shifted clock phase (CPHA) mode
+- spi-cs-high     - (optional) Empty property indicating device requires
+    		chip select active high
+
+SPI example for an MPC5200 SPI bus:
+	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>;
+		interrupt-parent = <&mpc5200_pic>;
+
+		ethernet-switch@0 {
+			compatible = "micrel,ks8995m";
+			spi-max-frequency = <1000000>;
+			reg = <0>;
+		};
+
+		codec@1 {
+			compatible = "ti,tlv320aic26";
+			spi-max-frequency = <100000>;
+			reg = <1>;
+		};
+	};
diff -druNp linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/usb/fsl-usb.txt linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/usb/fsl-usb.txt
--- linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/usb/fsl-usb.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/usb/fsl-usb.txt	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,81 @@
+Freescale SOC USB controllers
+
+The device node for a USB controller that is part of a Freescale
+SOC is as described in the document "Open Firmware Recommended
+Practice : Universal Serial Bus" with the following modifications
+and additions :
+
+Required properties :
+ - compatible : Should be "fsl-usb2-mph" for multi port host USB
+   controllers, or "fsl-usb2-dr" for dual role USB controllers
+   or "fsl,mpc5121-usb2-dr" for dual role USB controllers of MPC5121
+ - phy_type : For multi port host USB controllers, should be one of
+   "ulpi", or "serial". For dual role USB controllers, should be
+   one of "ulpi", "utmi", "utmi_wide", or "serial".
+ - reg : Offset and length of the register set for the device
+ - port0 : boolean; if defined, indicates port0 is connected for
+   fsl-usb2-mph compatible controllers.  Either this property or
+   "port1" (or both) must be defined for "fsl-usb2-mph" compatible
+   controllers.
+ - port1 : boolean; if defined, indicates port1 is connected for
+   fsl-usb2-mph compatible controllers.  Either this property or
+   "port0" (or both) must be defined for "fsl-usb2-mph" compatible
+   controllers.
+ - dr_mode : indicates the working mode for "fsl-usb2-dr" compatible
+   controllers.  Can be "host", "peripheral", or "otg".  Default to
+   "host" if not defined for backward compatibility.
+
+Recommended properties :
+ - interrupts : <a b> where a is the interrupt number and b is a
+   field that represents an encoding of the sense and level
+   information for the interrupt.  This should be encoded based on
+   the information in section 2) depending on the type of interrupt
+   controller you have.
+ - interrupt-parent : the phandle for the interrupt controller that
+   services interrupts for this device.
+
+Optional properties :
+ - fsl,invert-drvvbus : boolean; for MPC5121 USB0 only. Indicates the
+   port power polarity of internal PHY signal DRVVBUS is inverted.
+ - fsl,invert-pwr-fault : boolean; for MPC5121 USB0 only. Indicates
+   the PWR_FAULT signal polarity is inverted.
+
+Example multi port host USB controller device node :
+	usb@22000 {
+		compatible = "fsl-usb2-mph";
+		reg = <22000 1000>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		interrupt-parent = <700>;
+		interrupts = <27 1>;
+		phy_type = "ulpi";
+		port0;
+		port1;
+	};
+
+Example dual role USB controller device node :
+	usb@23000 {
+		compatible = "fsl-usb2-dr";
+		reg = <23000 1000>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		interrupt-parent = <700>;
+		interrupts = <26 1>;
+		dr_mode = "otg";
+		phy = "ulpi";
+	};
+
+Example dual role USB controller device node for MPC5121ADS:
+
+	usb@4000 {
+		compatible = "fsl,mpc5121-usb2-dr";
+		reg = <0x4000 0x1000>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		interrupt-parent = < &ipic >;
+		interrupts = <44 0x8>;
+		dr_mode = "otg";
+		phy_type = "utmi_wide";
+		fsl,invert-drvvbus;
+		fsl,invert-pwr-fault;
+	};
diff -druNp linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/usb/usb-ehci.txt linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/usb/usb-ehci.txt
--- linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/usb/usb-ehci.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/usb/usb-ehci.txt	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,25 @@
+USB EHCI controllers
+
+Required properties:
+  - compatible : should be "usb-ehci".
+  - reg : should contain at least address and length of the standard EHCI
+    register set for the device. Optional platform-dependent registers
+    (debug-port or other) can be also specified here, but only after
+    definition of standard EHCI registers.
+  - interrupts : one EHCI interrupt should be described here.
+If device registers are implemented in big endian mode, the device
+node should have "big-endian-regs" property.
+If controller implementation operates with big endian descriptors,
+"big-endian-desc" property should be specified.
+If both big endian registers and descriptors are used by the controller
+implementation, "big-endian" property can be specified instead of having
+both "big-endian-regs" and "big-endian-desc".
+
+Example (Sequoia 440EPx):
+    ehci@e0000300 {
+	   compatible = "ibm,usb-ehci-440epx", "usb-ehci";
+	   interrupt-parent = <&UIC0>;
+	   interrupts = <1a 4>;
+	   reg = <0 e0000300 90 0 e0000390 70>;
+	   big-endian;
+   };
diff -druNp linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/xilinx.txt linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/xilinx.txt
--- linux-libre-2.6.37-gnu1/Documentation/devicetree/bindings/xilinx.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/devicetree/bindings/xilinx.txt	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,306 @@
+   d) Xilinx IP cores
+
+   The Xilinx EDK toolchain ships with a set of IP cores (devices) for use
+   in Xilinx Spartan and Virtex FPGAs.  The devices cover the whole range
+   of standard device types (network, serial, etc.) and miscellaneous
+   devices (gpio, LCD, spi, etc).  Also, since these devices are
+   implemented within the fpga fabric every instance of the device can be
+   synthesised with different options that change the behaviour.
+
+   Each IP-core has a set of parameters which the FPGA designer can use to
+   control how the core is synthesized.  Historically, the EDK tool would
+   extract the device parameters relevant to device drivers and copy them
+   into an 'xparameters.h' in the form of #define symbols.  This tells the
+   device drivers how the IP cores are configured, but it requires the kernel
+   to be recompiled every time the FPGA bitstream is resynthesized.
+
+   The new approach is to export the parameters into the device tree and
+   generate a new device tree each time the FPGA bitstream changes.  The
+   parameters which used to be exported as #defines will now become
+   properties of the device node.  In general, device nodes for IP-cores
+   will take the following form:
+
+	(name): (generic-name)@(base-address) {
+		compatible = "xlnx,(ip-core-name)-(HW_VER)"
+			     [, (list of compatible devices), ...];
+		reg = <(baseaddr) (size)>;
+		interrupt-parent = <&interrupt-controller-phandle>;
+		interrupts = < ... >;
+		xlnx,(parameter1) = "(string-value)";
+		xlnx,(parameter2) = <(int-value)>;
+	};
+
+	(generic-name):   an open firmware-style name that describes the
+			generic class of device.  Preferably, this is one word, such
+			as 'serial' or 'ethernet'.
+	(ip-core-name):	the name of the ip block (given after the BEGIN
+			directive in system.mhs).  Should be in lowercase
+			and all underscores '_' converted to dashes '-'.
+	(name):		is derived from the "PARAMETER INSTANCE" value.
+	(parameter#):	C_* parameters from system.mhs.  The C_ prefix is
+			dropped from the parameter name, the name is converted
+			to lowercase and all underscore '_' characters are
+			converted to dashes '-'.
+	(baseaddr):	the baseaddr parameter value (often named C_BASEADDR).
+	(HW_VER):	from the HW_VER parameter.
+	(size):		the address range size (often C_HIGHADDR - C_BASEADDR + 1).
+
+   Typically, the compatible list will include the exact IP core version
+   followed by an older IP core version which implements the same
+   interface or any other device with the same interface.
+
+   'reg', 'interrupt-parent' and 'interrupts' are all optional properties.
+
+   For example, the following block from system.mhs:
+
+	BEGIN opb_uartlite
+		PARAMETER INSTANCE = opb_uartlite_0
+		PARAMETER HW_VER = 1.00.b
+		PARAMETER C_BAUDRATE = 115200
+		PARAMETER C_DATA_BITS = 8
+		PARAMETER C_ODD_PARITY = 0
+		PARAMETER C_USE_PARITY = 0
+		PARAMETER C_CLK_FREQ = 50000000
+		PARAMETER C_BASEADDR = 0xEC100000
+		PARAMETER C_HIGHADDR = 0xEC10FFFF
+		BUS_INTERFACE SOPB = opb_7
+		PORT OPB_Clk = CLK_50MHz
+		PORT Interrupt = opb_uartlite_0_Interrupt
+		PORT RX = opb_uartlite_0_RX
+		PORT TX = opb_uartlite_0_TX
+		PORT OPB_Rst = sys_bus_reset_0
+	END
+
+   becomes the following device tree node:
+
+	opb_uartlite_0: serial@ec100000 {
+		device_type = "serial";
+		compatible = "xlnx,opb-uartlite-1.00.b";
+		reg = <ec100000 10000>;
+		interrupt-parent = <&opb_intc_0>;
+		interrupts = <1 0>; // got this from the opb_intc parameters
+		current-speed = <d#115200>;	// standard serial device prop
+		clock-frequency = <d#50000000>;	// standard serial device prop
+		xlnx,data-bits = <8>;
+		xlnx,odd-parity = <0>;
+		xlnx,use-parity = <0>;
+	};
+
+   Some IP cores actually implement 2 or more logical devices.  In
+   this case, the device should still describe the whole IP core with
+   a single node and add a child node for each logical device.  The
+   ranges property can be used to translate from parent IP-core to the
+   registers of each device.  In addition, the parent node should be
+   compatible with the bus type 'xlnx,compound', and should contain
+   #address-cells and #size-cells, as with any other bus.  (Note: this
+   makes the assumption that both logical devices have the same bus
+   binding.  If this is not true, then separate nodes should be used
+   for each logical device).  The 'cell-index' property can be used to
+   enumerate logical devices within an IP core.  For example, the
+   following is the system.mhs entry for the dual ps2 controller found
+   on the ml403 reference design.
+
+	BEGIN opb_ps2_dual_ref
+		PARAMETER INSTANCE = opb_ps2_dual_ref_0
+		PARAMETER HW_VER = 1.00.a
+		PARAMETER C_BASEADDR = 0xA9000000
+		PARAMETER C_HIGHADDR = 0xA9001FFF
+		BUS_INTERFACE SOPB = opb_v20_0
+		PORT Sys_Intr1 = ps2_1_intr
+		PORT Sys_Intr2 = ps2_2_intr
+		PORT Clkin1 = ps2_clk_rx_1
+		PORT Clkin2 = ps2_clk_rx_2
+		PORT Clkpd1 = ps2_clk_tx_1
+		PORT Clkpd2 = ps2_clk_tx_2
+		PORT Rx1 = ps2_d_rx_1
+		PORT Rx2 = ps2_d_rx_2
+		PORT Txpd1 = ps2_d_tx_1
+		PORT Txpd2 = ps2_d_tx_2
+	END
+
+   It would result in the following device tree nodes:
+
+	opb_ps2_dual_ref_0: opb-ps2-dual-ref@a9000000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "xlnx,compound";
+		ranges = <0 a9000000 2000>;
+		// If this device had extra parameters, then they would
+		// go here.
+		ps2@0 {
+			compatible = "xlnx,opb-ps2-dual-ref-1.00.a";
+			reg = <0 40>;
+			interrupt-parent = <&opb_intc_0>;
+			interrupts = <3 0>;
+			cell-index = <0>;
+		};
+		ps2@1000 {
+			compatible = "xlnx,opb-ps2-dual-ref-1.00.a";
+			reg = <1000 40>;
+			interrupt-parent = <&opb_intc_0>;
+			interrupts = <3 0>;
+			cell-index = <0>;
+		};
+	};
+
+   Also, the system.mhs file defines bus attachments from the processor
+   to the devices.  The device tree structure should reflect the bus
+   attachments.  Again an example; this system.mhs fragment:
+
+	BEGIN ppc405_virtex4
+		PARAMETER INSTANCE = ppc405_0
+		PARAMETER HW_VER = 1.01.a
+		BUS_INTERFACE DPLB = plb_v34_0
+		BUS_INTERFACE IPLB = plb_v34_0
+	END
+
+	BEGIN opb_intc
+		PARAMETER INSTANCE = opb_intc_0
+		PARAMETER HW_VER = 1.00.c
+		PARAMETER C_BASEADDR = 0xD1000FC0
+		PARAMETER C_HIGHADDR = 0xD1000FDF
+		BUS_INTERFACE SOPB = opb_v20_0
+	END
+
+	BEGIN opb_uart16550
+		PARAMETER INSTANCE = opb_uart16550_0
+		PARAMETER HW_VER = 1.00.d
+		PARAMETER C_BASEADDR = 0xa0000000
+		PARAMETER C_HIGHADDR = 0xa0001FFF
+		BUS_INTERFACE SOPB = opb_v20_0
+	END
+
+	BEGIN plb_v34
+		PARAMETER INSTANCE = plb_v34_0
+		PARAMETER HW_VER = 1.02.a
+	END
+
+	BEGIN plb_bram_if_cntlr
+		PARAMETER INSTANCE = plb_bram_if_cntlr_0
+		PARAMETER HW_VER = 1.00.b
+		PARAMETER C_BASEADDR = 0xFFFF0000
+		PARAMETER C_HIGHADDR = 0xFFFFFFFF
+		BUS_INTERFACE SPLB = plb_v34_0
+	END
+
+	BEGIN plb2opb_bridge
+		PARAMETER INSTANCE = plb2opb_bridge_0
+		PARAMETER HW_VER = 1.01.a
+		PARAMETER C_RNG0_BASEADDR = 0x20000000
+		PARAMETER C_RNG0_HIGHADDR = 0x3FFFFFFF
+		PARAMETER C_RNG1_BASEADDR = 0x60000000
+		PARAMETER C_RNG1_HIGHADDR = 0x7FFFFFFF
+		PARAMETER C_RNG2_BASEADDR = 0x80000000
+		PARAMETER C_RNG2_HIGHADDR = 0xBFFFFFFF
+		PARAMETER C_RNG3_BASEADDR = 0xC0000000
+		PARAMETER C_RNG3_HIGHADDR = 0xDFFFFFFF
+		BUS_INTERFACE SPLB = plb_v34_0
+		BUS_INTERFACE MOPB = opb_v20_0
+	END
+
+   Gives this device tree (some properties removed for clarity):
+
+	plb@0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "xlnx,plb-v34-1.02.a";
+		device_type = "ibm,plb";
+		ranges; // 1:1 translation
+
+		plb_bram_if_cntrl_0: bram@ffff0000 {
+			reg = <ffff0000 10000>;
+		}
+
+		opb@20000000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <20000000 20000000 20000000
+				  60000000 60000000 20000000
+				  80000000 80000000 40000000
+				  c0000000 c0000000 20000000>;
+
+			opb_uart16550_0: serial@a0000000 {
+				reg = <a00000000 2000>;
+			};
+
+			opb_intc_0: interrupt-controller@d1000fc0 {
+				reg = <d1000fc0 20>;
+			};
+		};
+	};
+
+   That covers the general approach to binding xilinx IP cores into the
+   device tree.  The following are bindings for specific devices:
+
+      i) Xilinx ML300 Framebuffer
+
+      Simple framebuffer device from the ML300 reference design (also on the
+      ML403 reference design as well as others).
+
+      Optional properties:
+       - resolution = <xres yres> : pixel resolution of framebuffer.  Some
+                                    implementations use a different resolution.
+                                    Default is <d#640 d#480>
+       - virt-resolution = <xvirt yvirt> : Size of framebuffer in memory.
+                                           Default is <d#1024 d#480>.
+       - rotate-display (empty) : rotate display 180 degrees.
+
+      ii) Xilinx SystemACE
+
+      The Xilinx SystemACE device is used to program FPGAs from an FPGA
+      bitstream stored on a CF card.  It can also be used as a generic CF
+      interface device.
+
+      Optional properties:
+       - 8-bit (empty) : Set this property for SystemACE in 8 bit mode
+
+      iii) Xilinx EMAC and Xilinx TEMAC
+
+      Xilinx Ethernet devices.  In addition to general xilinx properties
+      listed above, nodes for these devices should include a phy-handle
+      property, and may include other common network device properties
+      like local-mac-address.
+
+      iv) Xilinx Uartlite
+
+      Xilinx uartlite devices are simple fixed speed serial ports.
+
+      Required properties:
+       - current-speed : Baud rate of uartlite
+
+      v) Xilinx hwicap
+
+		Xilinx hwicap devices provide access to the configuration logic
+		of the FPGA through the Internal Configuration Access Port
+		(ICAP).  The ICAP enables partial reconfiguration of the FPGA,
+		readback of the configuration information, and some control over
+		'warm boots' of the FPGA fabric.
+
+		Required properties:
+		- xlnx,family : The family of the FPGA, necessary since the
+                      capabilities of the underlying ICAP hardware
+                      differ between different families.  May be
+                      'virtex2p', 'virtex4', or 'virtex5'.
+
+      vi) Xilinx Uart 16550
+
+      Xilinx UART 16550 devices are very similar to the NS16550 but with
+      different register spacing and an offset from the base address.
+
+      Required properties:
+       - clock-frequency : Frequency of the clock input
+       - reg-offset : A value of 3 is required
+       - reg-shift : A value of 2 is required
+
+      vii) Xilinx USB Host controller
+
+      The Xilinx USB host controller is EHCI compatible but with a different
+      base address for the EHCI registers, and it is always a big-endian
+      USB Host controller. The hardware can be configured as high speed only,
+      or high speed/full speed hybrid.
+
+      Required properties:
+      - xlnx,support-usb-fs: A value 0 means the core is built as high speed
+                             only. A value 1 means the core also supports
+                             full speed devices.
+
diff -druNp linux-libre-2.6.37-gnu1/Documentation/devicetree/booting-without-of.txt linux-libre-2.6.38-gnu1/Documentation/devicetree/booting-without-of.txt
--- linux-libre-2.6.37-gnu1/Documentation/devicetree/booting-without-of.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/devicetree/booting-without-of.txt	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,1390 @@
+           Booting the Linux/ppc kernel without Open Firmware
+           --------------------------------------------------
+
+(c) 2005 Benjamin Herrenschmidt <benh at kernel.crashing.org>,
+    IBM Corp.
+(c) 2005 Becky Bruce <becky.bruce at freescale.com>,
+    Freescale Semiconductor, FSL SOC and 32-bit additions
+(c) 2006 MontaVista Software, Inc.
+    Flash chip node definition
+
+Table of Contents
+=================
+
+  I - Introduction
+    1) Entry point for arch/powerpc
+
+  II - The DT block format
+    1) Header
+    2) Device tree generalities
+    3) Device tree "structure" block
+    4) Device tree "strings" block
+
+  III - Required content of the device tree
+    1) Note about cells and address representation
+    2) Note about "compatible" properties
+    3) Note about "name" properties
+    4) Note about node and property names and character set
+    5) Required nodes and properties
+      a) The root node
+      b) The /cpus node
+      c) The /cpus/* nodes
+      d) the /memory node(s)
+      e) The /chosen node
+      f) the /soc<SOCname> node
+
+  IV - "dtc", the device tree compiler
+
+  V - Recommendations for a bootloader
+
+  VI - System-on-a-chip devices and nodes
+    1) Defining child nodes of an SOC
+    2) Representing devices without a current OF specification
+
+  VII - Specifying interrupt information for devices
+    1) interrupts property
+    2) interrupt-parent property
+    3) OpenPIC Interrupt Controllers
+    4) ISA Interrupt Controllers
+
+  VIII - Specifying device power management information (sleep property)
+
+  Appendix A - Sample SOC node for MPC8540
+
+
+Revision Information
+====================
+
+   May 18, 2005: Rev 0.1 - Initial draft, no chapter III yet.
+
+   May 19, 2005: Rev 0.2 - Add chapter III and bits & pieces here or
+                           clarifies the fact that a lot of things are
+                           optional, the kernel only requires a very
+                           small device tree, though it is encouraged
+                           to provide an as complete one as possible.
+
+   May 24, 2005: Rev 0.3 - Precise that DT block has to be in RAM
+			 - Misc fixes
+			 - Define version 3 and new format version 16
+			   for the DT block (version 16 needs kernel
+			   patches, will be fwd separately).
+			   String block now has a size, and full path
+			   is replaced by unit name for more
+			   compactness.
+			   linux,phandle is made optional, only nodes
+			   that are referenced by other nodes need it.
+			   "name" property is now automatically
+			   deduced from the unit name
+
+   June 1, 2005: Rev 0.4 - Correct confusion between OF_DT_END and
+                           OF_DT_END_NODE in structure definition.
+                         - Change version 16 format to always align
+                           property data to 4 bytes. Since tokens are
+                           already aligned, that means no specific
+                           required alignment between property size
+                           and property data. The old style variable
+                           alignment would make it impossible to do
+                           "simple" insertion of properties using
+                           memmove (thanks Milton for
+                           noticing). Updated kernel patch as well
+			 - Correct a few more alignment constraints
+			 - Add a chapter about the device-tree
+                           compiler and the textural representation of
+                           the tree that can be "compiled" by dtc.
+
+   November 21, 2005: Rev 0.5
+			 - Additions/generalizations for 32-bit
+			 - Changed to reflect the new arch/powerpc
+			   structure
+			 - Added chapter VI
+
+
+ ToDo:
+	- Add some definitions of interrupt tree (simple/complex)
+	- Add some definitions for PCI host bridges
+	- Add some common address format examples
+	- Add definitions for standard properties and "compatible"
+	  names for cells that are not already defined by the existing
+	  OF spec.
+	- Compare FSL SOC use of PCI to standard and make sure no new
+	  node definition required.
+	- Add more information about node definitions for SOC devices
+  	  that currently have no standard, like the FSL CPM.
+
+
+I - Introduction
+================
+
+During the development of the Linux/ppc64 kernel, and more
+specifically, the addition of new platform types outside of the old
+IBM pSeries/iSeries pair, it was decided to enforce some strict rules
+regarding the kernel entry and bootloader <-> kernel interfaces, in
+order to avoid the degeneration that had become the ppc32 kernel entry
+point and the way a new platform should be added to the kernel. The
+legacy iSeries platform breaks those rules as it predates this scheme,
+but no new board support will be accepted in the main tree that
+doesn't follow them properly.  In addition, since the advent of the
+arch/powerpc merged architecture for ppc32 and ppc64, new 32-bit
+platforms and 32-bit platforms which move into arch/powerpc will be
+required to use these rules as well.
+
+The main requirement that will be defined in more detail below is
+the presence of a device-tree whose format is defined after Open
+Firmware specification. However, in order to make life easier
+to embedded board vendors, the kernel doesn't require the device-tree
+to represent every device in the system and only requires some nodes
+and properties to be present. This will be described in detail in
+section III, but, for example, the kernel does not require you to
+create a node for every PCI device in the system. It is a requirement
+to have a node for PCI host bridges in order to provide interrupt
+routing informations and memory/IO ranges, among others. It is also
+recommended to define nodes for on chip devices and other buses that
+don't specifically fit in an existing OF specification. This creates a
+great flexibility in the way the kernel can then probe those and match
+drivers to device, without having to hard code all sorts of tables. It
+also makes it more flexible for board vendors to do minor hardware
+upgrades without significantly impacting the kernel code or cluttering
+it with special cases.
+
+
+1) Entry point for arch/powerpc
+-------------------------------
+
+   There is one single entry point to the kernel, at the start
+   of the kernel image. That entry point supports two calling
+   conventions:
+
+        a) Boot from Open Firmware. If your firmware is compatible
+        with Open Firmware (IEEE 1275) or provides an OF compatible
+        client interface API (support for "interpret" callback of
+        forth words isn't required), you can enter the kernel with:
+
+              r5 : OF callback pointer as defined by IEEE 1275
+              bindings to powerpc. Only the 32-bit client interface
+              is currently supported
+
+              r3, r4 : address & length of an initrd if any or 0
+
+              The MMU is either on or off; the kernel will run the
+              trampoline located in arch/powerpc/kernel/prom_init.c to
+              extract the device-tree and other information from open
+              firmware and build a flattened device-tree as described
+              in b). prom_init() will then re-enter the kernel using
+              the second method. This trampoline code runs in the
+              context of the firmware, which is supposed to handle all
+              exceptions during that time.
+
+        b) Direct entry with a flattened device-tree block. This entry
+        point is called by a) after the OF trampoline and can also be
+        called directly by a bootloader that does not support the Open
+        Firmware client interface. It is also used by "kexec" to
+        implement "hot" booting of a new kernel from a previous
+        running one. This method is what I will describe in more
+        details in this document, as method a) is simply standard Open
+        Firmware, and thus should be implemented according to the
+        various standard documents defining it and its binding to the
+        PowerPC platform. The entry point definition then becomes:
+
+                r3 : physical pointer to the device-tree block
+                (defined in chapter II) in RAM
+
+                r4 : physical pointer to the kernel itself. This is
+                used by the assembly code to properly disable the MMU
+                in case you are entering the kernel with MMU enabled
+                and a non-1:1 mapping.
+
+                r5 : NULL (as to differentiate with method a)
+
+        Note about SMP entry: Either your firmware puts your other
+        CPUs in some sleep loop or spin loop in ROM where you can get
+        them out via a soft reset or some other means, in which case
+        you don't need to care, or you'll have to enter the kernel
+        with all CPUs. The way to do that with method b) will be
+        described in a later revision of this document.
+
+   Board supports (platforms) are not exclusive config options. An
+   arbitrary set of board supports can be built in a single kernel
+   image. The kernel will "know" what set of functions to use for a
+   given platform based on the content of the device-tree. Thus, you
+   should:
+
+        a) add your platform support as a _boolean_ option in
+        arch/powerpc/Kconfig, following the example of PPC_PSERIES,
+        PPC_PMAC and PPC_MAPLE. The later is probably a good
+        example of a board support to start from.
+
+        b) create your main platform file as
+        "arch/powerpc/platforms/myplatform/myboard_setup.c" and add it
+        to the Makefile under the condition of your CONFIG_
+        option. This file will define a structure of type "ppc_md"
+        containing the various callbacks that the generic code will
+        use to get to your platform specific code
+
+  A kernel image may support multiple platforms, but only if the
+  platforms feature the same core architecture.  A single kernel build
+  cannot support both configurations with Book E and configurations
+  with classic Powerpc architectures.
+
+
+II - The DT block format
+========================
+
+
+This chapter defines the actual format of the flattened device-tree
+passed to the kernel. The actual content of it and kernel requirements
+are described later. You can find example of code manipulating that
+format in various places, including arch/powerpc/kernel/prom_init.c
+which will generate a flattened device-tree from the Open Firmware
+representation, or the fs2dt utility which is part of the kexec tools
+which will generate one from a filesystem representation. It is
+expected that a bootloader like uboot provides a bit more support,
+that will be discussed later as well.
+
+Note: The block has to be in main memory. It has to be accessible in
+both real mode and virtual mode with no mapping other than main
+memory. If you are writing a simple flash bootloader, it should copy
+the block to RAM before passing it to the kernel.
+
+
+1) Header
+---------
+
+   The kernel is passed the physical address pointing to an area of memory
+   that is roughly described in include/linux/of_fdt.h by the structure
+   boot_param_header:
+
+struct boot_param_header {
+        u32     magic;                  /* magic word OF_DT_HEADER */
+        u32     totalsize;              /* total size of DT block */
+        u32     off_dt_struct;          /* offset to structure */
+        u32     off_dt_strings;         /* offset to strings */
+        u32     off_mem_rsvmap;         /* offset to memory reserve map
+                                           */
+        u32     version;                /* format version */
+        u32     last_comp_version;      /* last compatible version */
+
+        /* version 2 fields below */
+        u32     boot_cpuid_phys;        /* Which physical CPU id we're
+                                           booting on */
+        /* version 3 fields below */
+        u32     size_dt_strings;        /* size of the strings block */
+
+        /* version 17 fields below */
+        u32	size_dt_struct;		/* size of the DT structure block */
+};
+
+   Along with the constants:
+
+/* Definitions used by the flattened device tree */
+#define OF_DT_HEADER            0xd00dfeed      /* 4: version,
+						   4: total size */
+#define OF_DT_BEGIN_NODE        0x1             /* Start node: full name
+						   */
+#define OF_DT_END_NODE          0x2             /* End node */
+#define OF_DT_PROP              0x3             /* Property: name off,
+                                                   size, content */
+#define OF_DT_END               0x9
+
+   All values in this header are in big endian format, the various
+   fields in this header are defined more precisely below. All
+   "offset" values are in bytes from the start of the header; that is
+   from the physical base address of the device tree block.
+
+   - magic
+
+     This is a magic value that "marks" the beginning of the
+     device-tree block header. It contains the value 0xd00dfeed and is
+     defined by the constant OF_DT_HEADER
+
+   - totalsize
+
+     This is the total size of the DT block including the header. The
+     "DT" block should enclose all data structures defined in this
+     chapter (who are pointed to by offsets in this header). That is,
+     the device-tree structure, strings, and the memory reserve map.
+
+   - off_dt_struct
+
+     This is an offset from the beginning of the header to the start
+     of the "structure" part the device tree. (see 2) device tree)
+
+   - off_dt_strings
+
+     This is an offset from the beginning of the header to the start
+     of the "strings" part of the device-tree
+
+   - off_mem_rsvmap
+
+     This is an offset from the beginning of the header to the start
+     of the reserved memory map. This map is a list of pairs of 64-
+     bit integers. Each pair is a physical address and a size. The
+     list is terminated by an entry of size 0. This map provides the
+     kernel with a list of physical memory areas that are "reserved"
+     and thus not to be used for memory allocations, especially during
+     early initialization. The kernel needs to allocate memory during
+     boot for things like un-flattening the device-tree, allocating an
+     MMU hash table, etc... Those allocations must be done in such a
+     way to avoid overriding critical things like, on Open Firmware
+     capable machines, the RTAS instance, or on some pSeries, the TCE
+     tables used for the iommu. Typically, the reserve map should
+     contain _at least_ this DT block itself (header,total_size). If
+     you are passing an initrd to the kernel, you should reserve it as
+     well. You do not need to reserve the kernel image itself. The map
+     should be 64-bit aligned.
+
+   - version
+
+     This is the version of this structure. Version 1 stops
+     here. Version 2 adds an additional field boot_cpuid_phys.
+     Version 3 adds the size of the strings block, allowing the kernel
+     to reallocate it easily at boot and free up the unused flattened
+     structure after expansion. Version 16 introduces a new more
+     "compact" format for the tree itself that is however not backward
+     compatible. Version 17 adds an additional field, size_dt_struct,
+     allowing it to be reallocated or moved more easily (this is
+     particularly useful for bootloaders which need to make
+     adjustments to a device tree based on probed information). You
+     should always generate a structure of the highest version defined
+     at the time of your implementation. Currently that is version 17,
+     unless you explicitly aim at being backward compatible.
+
+   - last_comp_version
+
+     Last compatible version. This indicates down to what version of
+     the DT block you are backward compatible. For example, version 2
+     is backward compatible with version 1 (that is, a kernel build
+     for version 1 will be able to boot with a version 2 format). You
+     should put a 1 in this field if you generate a device tree of
+     version 1 to 3, or 16 if you generate a tree of version 16 or 17
+     using the new unit name format.
+
+   - boot_cpuid_phys
+
+     This field only exist on version 2 headers. It indicate which
+     physical CPU ID is calling the kernel entry point. This is used,
+     among others, by kexec. If you are on an SMP system, this value
+     should match the content of the "reg" property of the CPU node in
+     the device-tree corresponding to the CPU calling the kernel entry
+     point (see further chapters for more informations on the required
+     device-tree contents)
+
+   - size_dt_strings
+
+     This field only exists on version 3 and later headers.  It
+     gives the size of the "strings" section of the device tree (which
+     starts at the offset given by off_dt_strings).
+
+   - size_dt_struct
+
+     This field only exists on version 17 and later headers.  It gives
+     the size of the "structure" section of the device tree (which
+     starts at the offset given by off_dt_struct).
+
+   So the typical layout of a DT block (though the various parts don't
+   need to be in that order) looks like this (addresses go from top to
+   bottom):
+
+
+             ------------------------------
+     base -> |  struct boot_param_header  |
+             ------------------------------
+             |      (alignment gap) (*)   |
+             ------------------------------
+             |      memory reserve map    |
+             ------------------------------
+             |      (alignment gap)       |
+             ------------------------------
+             |                            |
+             |    device-tree structure   |
+             |                            |
+             ------------------------------
+             |      (alignment gap)       |
+             ------------------------------
+             |                            |
+             |     device-tree strings    |
+             |                            |
+      -----> ------------------------------
+      |
+      |
+      --- (base + totalsize)
+
+  (*) The alignment gaps are not necessarily present; their presence
+      and size are dependent on the various alignment requirements of
+      the individual data blocks.
+
+
+2) Device tree generalities
+---------------------------
+
+This device-tree itself is separated in two different blocks, a
+structure block and a strings block. Both need to be aligned to a 4
+byte boundary.
+
+First, let's quickly describe the device-tree concept before detailing
+the storage format. This chapter does _not_ describe the detail of the
+required types of nodes & properties for the kernel, this is done
+later in chapter III.
+
+The device-tree layout is strongly inherited from the definition of
+the Open Firmware IEEE 1275 device-tree. It's basically a tree of
+nodes, each node having two or more named properties. A property can
+have a value or not.
+
+It is a tree, so each node has one and only one parent except for the
+root node who has no parent.
+
+A node has 2 names. The actual node name is generally contained in a
+property of type "name" in the node property list whose value is a
+zero terminated string and is mandatory for version 1 to 3 of the
+format definition (as it is in Open Firmware). Version 16 makes it
+optional as it can generate it from the unit name defined below.
+
+There is also a "unit name" that is used to differentiate nodes with
+the same name at the same level, it is usually made of the node
+names, the "@" sign, and a "unit address", which definition is
+specific to the bus type the node sits on.
+
+The unit name doesn't exist as a property per-se but is included in
+the device-tree structure. It is typically used to represent "path" in
+the device-tree. More details about the actual format of these will be
+below.
+
+The kernel generic code does not make any formal use of the
+unit address (though some board support code may do) so the only real
+requirement here for the unit address is to ensure uniqueness of
+the node unit name at a given level of the tree. Nodes with no notion
+of address and no possible sibling of the same name (like /memory or
+/cpus) may omit the unit address in the context of this specification,
+or use the "@0" default unit address. The unit name is used to define
+a node "full path", which is the concatenation of all parent node
+unit names separated with "/".
+
+The root node doesn't have a defined name, and isn't required to have
+a name property either if you are using version 3 or earlier of the
+format. It also has no unit address (no @ symbol followed by a unit
+address). The root node unit name is thus an empty string. The full
+path to the root node is "/".
+
+Every node which actually represents an actual device (that is, a node
+which isn't only a virtual "container" for more nodes, like "/cpus"
+is) is also required to have a "compatible" property indicating the
+specific hardware and an optional list of devices it is fully
+backwards compatible with.
+
+Finally, every node that can be referenced from a property in another
+node is required to have either a "phandle" or a "linux,phandle"
+property. Real Open Firmware implementations provide a unique
+"phandle" value for every node that the "prom_init()" trampoline code
+turns into "linux,phandle" properties. However, this is made optional
+if the flattened device tree is used directly. An example of a node
+referencing another node via "phandle" is when laying out the
+interrupt tree which will be described in a further version of this
+document.
+
+The "phandle" property is a 32-bit value that uniquely
+identifies a node. You are free to use whatever values or system of
+values, internal pointers, or whatever to generate these, the only
+requirement is that every node for which you provide that property has
+a unique value for it.
+
+Here is an example of a simple device-tree. In this example, an "o"
+designates a node followed by the node unit name. Properties are
+presented with their name followed by their content. "content"
+represents an ASCII string (zero terminated) value, while <content>
+represents a 32-bit hexadecimal value. The various nodes in this
+example will be discussed in a later chapter. At this point, it is
+only meant to give you a idea of what a device-tree looks like. I have
+purposefully kept the "name" and "linux,phandle" properties which
+aren't necessary in order to give you a better idea of what the tree
+looks like in practice.
+
+  / o device-tree
+      |- name = "device-tree"
+      |- model = "MyBoardName"
+      |- compatible = "MyBoardFamilyName"
+      |- #address-cells = <2>
+      |- #size-cells = <2>
+      |- linux,phandle = <0>
+      |
+      o cpus
+      | | - name = "cpus"
+      | | - linux,phandle = <1>
+      | | - #address-cells = <1>
+      | | - #size-cells = <0>
+      | |
+      | o PowerPC,970@0
+      |   |- name = "PowerPC,970"
+      |   |- device_type = "cpu"
+      |   |- reg = <0>
+      |   |- clock-frequency = <5f5e1000>
+      |   |- 64-bit
+      |   |- linux,phandle = <2>
+      |
+      o memory@0
+      | |- name = "memory"
+      | |- device_type = "memory"
+      | |- reg = <00000000 00000000 00000000 20000000>
+      | |- linux,phandle = <3>
+      |
+      o chosen
+        |- name = "chosen"
+        |- bootargs = "root=/dev/sda2"
+        |- linux,phandle = <4>
+
+This tree is almost a minimal tree. It pretty much contains the
+minimal set of required nodes and properties to boot a linux kernel;
+that is, some basic model informations at the root, the CPUs, and the
+physical memory layout.  It also includes misc information passed
+through /chosen, like in this example, the platform type (mandatory)
+and the kernel command line arguments (optional).
+
+The /cpus/PowerPC,970@0/64-bit property is an example of a
+property without a value. All other properties have a value. The
+significance of the #address-cells and #size-cells properties will be
+explained in chapter IV which defines precisely the required nodes and
+properties and their content.
+
+
+3) Device tree "structure" block
+
+The structure of the device tree is a linearized tree structure. The
+"OF_DT_BEGIN_NODE" token starts a new node, and the "OF_DT_END_NODE"
+ends that node definition. Child nodes are simply defined before
+"OF_DT_END_NODE" (that is nodes within the node). A 'token' is a 32
+bit value. The tree has to be "finished" with a OF_DT_END token
+
+Here's the basic structure of a single node:
+
+     * token OF_DT_BEGIN_NODE (that is 0x00000001)
+     * for version 1 to 3, this is the node full path as a zero
+       terminated string, starting with "/". For version 16 and later,
+       this is the node unit name only (or an empty string for the
+       root node)
+     * [align gap to next 4 bytes boundary]
+     * for each property:
+        * token OF_DT_PROP (that is 0x00000003)
+        * 32-bit value of property value size in bytes (or 0 if no
+          value)
+        * 32-bit value of offset in string block of property name
+        * property value data if any
+        * [align gap to next 4 bytes boundary]
+     * [child nodes if any]
+     * token OF_DT_END_NODE (that is 0x00000002)
+
+So the node content can be summarized as a start token, a full path,
+a list of properties, a list of child nodes, and an end token. Every
+child node is a full node structure itself as defined above.
+
+NOTE: The above definition requires that all property definitions for
+a particular node MUST precede any subnode definitions for that node.
+Although the structure would not be ambiguous if properties and
+subnodes were intermingled, the kernel parser requires that the
+properties come first (up until at least 2.6.22).  Any tools
+manipulating a flattened tree must take care to preserve this
+constraint.
+
+4) Device tree "strings" block
+
+In order to save space, property names, which are generally redundant,
+are stored separately in the "strings" block. This block is simply the
+whole bunch of zero terminated strings for all property names
+concatenated together. The device-tree property definitions in the
+structure block will contain offset values from the beginning of the
+strings block.
+
+
+III - Required content of the device tree
+=========================================
+
+WARNING: All "linux,*" properties defined in this document apply only
+to a flattened device-tree. If your platform uses a real
+implementation of Open Firmware or an implementation compatible with
+the Open Firmware client interface, those properties will be created
+by the trampoline code in the kernel's prom_init() file. For example,
+that's where you'll have to add code to detect your board model and
+set the platform number. However, when using the flattened device-tree
+entry point, there is no prom_init() pass, and thus you have to
+provide those properties yourself.
+
+
+1) Note about cells and address representation
+----------------------------------------------
+
+The general rule is documented in the various Open Firmware
+documentations. If you choose to describe a bus with the device-tree
+and there exist an OF bus binding, then you should follow the
+specification. However, the kernel does not require every single
+device or bus to be described by the device tree.
+
+In general, the format of an address for a device is defined by the
+parent bus type, based on the #address-cells and #size-cells
+properties.  Note that the parent's parent definitions of #address-cells
+and #size-cells are not inherited so every node with children must specify
+them.  The kernel requires the root node to have those properties defining
+addresses format for devices directly mapped on the processor bus.
+
+Those 2 properties define 'cells' for representing an address and a
+size. A "cell" is a 32-bit number. For example, if both contain 2
+like the example tree given above, then an address and a size are both
+composed of 2 cells, and each is a 64-bit number (cells are
+concatenated and expected to be in big endian format). Another example
+is the way Apple firmware defines them, with 2 cells for an address
+and one cell for a size.  Most 32-bit implementations should define
+#address-cells and #size-cells to 1, which represents a 32-bit value.
+Some 32-bit processors allow for physical addresses greater than 32
+bits; these processors should define #address-cells as 2.
+
+"reg" properties are always a tuple of the type "address size" where
+the number of cells of address and size is specified by the bus
+#address-cells and #size-cells. When a bus supports various address
+spaces and other flags relative to a given address allocation (like
+prefetchable, etc...) those flags are usually added to the top level
+bits of the physical address. For example, a PCI physical address is
+made of 3 cells, the bottom two containing the actual address itself
+while the top cell contains address space indication, flags, and pci
+bus & device numbers.
+
+For buses that support dynamic allocation, it's the accepted practice
+to then not provide the address in "reg" (keep it 0) though while
+providing a flag indicating the address is dynamically allocated, and
+then, to provide a separate "assigned-addresses" property that
+contains the fully allocated addresses. See the PCI OF bindings for
+details.
+
+In general, a simple bus with no address space bits and no dynamic
+allocation is preferred if it reflects your hardware, as the existing
+kernel address parsing functions will work out of the box. If you
+define a bus type with a more complex address format, including things
+like address space bits, you'll have to add a bus translator to the
+prom_parse.c file of the recent kernels for your bus type.
+
+The "reg" property only defines addresses and sizes (if #size-cells is
+non-0) within a given bus. In order to translate addresses upward
+(that is into parent bus addresses, and possibly into CPU physical
+addresses), all buses must contain a "ranges" property. If the
+"ranges" property is missing at a given level, it's assumed that
+translation isn't possible, i.e., the registers are not visible on the
+parent bus.  The format of the "ranges" property for a bus is a list
+of:
+
+	bus address, parent bus address, size
+
+"bus address" is in the format of the bus this bus node is defining,
+that is, for a PCI bridge, it would be a PCI address. Thus, (bus
+address, size) defines a range of addresses for child devices. "parent
+bus address" is in the format of the parent bus of this bus. For
+example, for a PCI host controller, that would be a CPU address. For a
+PCI<->ISA bridge, that would be a PCI address. It defines the base
+address in the parent bus where the beginning of that range is mapped.
+
+For new 64-bit board support, I recommend either the 2/2 format or
+Apple's 2/1 format which is slightly more compact since sizes usually
+fit in a single 32-bit word.   New 32-bit board support should use a
+1/1 format, unless the processor supports physical addresses greater
+than 32-bits, in which case a 2/1 format is recommended.
+
+Alternatively, the "ranges" property may be empty, indicating that the
+registers are visible on the parent bus using an identity mapping
+translation.  In other words, the parent bus address space is the same
+as the child bus address space.
+
+2) Note about "compatible" properties
+-------------------------------------
+
+These properties are optional, but recommended in devices and the root
+node. The format of a "compatible" property is a list of concatenated
+zero terminated strings. They allow a device to express its
+compatibility with a family of similar devices, in some cases,
+allowing a single driver to match against several devices regardless
+of their actual names.
+
+3) Note about "name" properties
+-------------------------------
+
+While earlier users of Open Firmware like OldWorld macintoshes tended
+to use the actual device name for the "name" property, it's nowadays
+considered a good practice to use a name that is closer to the device
+class (often equal to device_type). For example, nowadays, Ethernet
+controllers are named "ethernet", an additional "model" property
+defining precisely the chip type/model, and "compatible" property
+defining the family in case a single driver can driver more than one
+of these chips. However, the kernel doesn't generally put any
+restriction on the "name" property; it is simply considered good
+practice to follow the standard and its evolutions as closely as
+possible.
+
+Note also that the new format version 16 makes the "name" property
+optional. If it's absent for a node, then the node's unit name is then
+used to reconstruct the name. That is, the part of the unit name
+before the "@" sign is used (or the entire unit name if no "@" sign
+is present).
+
+4) Note about node and property names and character set
+-------------------------------------------------------
+
+While Open Firmware provides more flexible usage of 8859-1, this
+specification enforces more strict rules. Nodes and properties should
+be comprised only of ASCII characters 'a' to 'z', '0' to
+'9', ',', '.', '_', '+', '#', '?', and '-'. Node names additionally
+allow uppercase characters 'A' to 'Z' (property names should be
+lowercase. The fact that vendors like Apple don't respect this rule is
+irrelevant here). Additionally, node and property names should always
+begin with a character in the range 'a' to 'z' (or 'A' to 'Z' for node
+names).
+
+The maximum number of characters for both nodes and property names
+is 31. In the case of node names, this is only the leftmost part of
+a unit name (the pure "name" property), it doesn't include the unit
+address which can extend beyond that limit.
+
+
+5) Required nodes and properties
+--------------------------------
+  These are all that are currently required. However, it is strongly
+  recommended that you expose PCI host bridges as documented in the
+  PCI binding to Open Firmware, and your interrupt tree as documented
+  in OF interrupt tree specification.
+
+  a) The root node
+
+  The root node requires some properties to be present:
+
+    - model : this is your board name/model
+    - #address-cells : address representation for "root" devices
+    - #size-cells: the size representation for "root" devices
+    - compatible : the board "family" generally finds its way here,
+      for example, if you have 2 board models with a similar layout,
+      that typically get driven by the same platform code in the
+      kernel, you would specify the exact board model in the
+      compatible property followed by an entry that represents the SoC
+      model.
+
+  The root node is also generally where you add additional properties
+  specific to your board like the serial number if any, that sort of
+  thing. It is recommended that if you add any "custom" property whose
+  name may clash with standard defined ones, you prefix them with your
+  vendor name and a comma.
+
+  b) The /cpus node
+
+  This node is the parent of all individual CPU nodes. It doesn't
+  have any specific requirements, though it's generally good practice
+  to have at least:
+
+               #address-cells = <00000001>
+               #size-cells    = <00000000>
+
+  This defines that the "address" for a CPU is a single cell, and has
+  no meaningful size. This is not necessary but the kernel will assume
+  that format when reading the "reg" properties of a CPU node, see
+  below
+
+  c) The /cpus/* nodes
+
+  So under /cpus, you are supposed to create a node for every CPU on
+  the machine. There is no specific restriction on the name of the
+  CPU, though it's common to call it <architecture>,<core>. For
+  example, Apple uses PowerPC,G5 while IBM uses PowerPC,970FX.
+  However, the Generic Names convention suggests that it would be
+  better to simply use 'cpu' for each cpu node and use the compatible
+  property to identify the specific cpu core.
+
+  Required properties:
+
+    - device_type : has to be "cpu"
+    - reg : This is the physical CPU number, it's a single 32-bit cell
+      and is also used as-is as the unit number for constructing the
+      unit name in the full path. For example, with 2 CPUs, you would
+      have the full path:
+        /cpus/PowerPC,970FX@0
+        /cpus/PowerPC,970FX@1
+      (unit addresses do not require leading zeroes)
+    - d-cache-block-size : one cell, L1 data cache block size in bytes (*)
+    - i-cache-block-size : one cell, L1 instruction cache block size in
+      bytes
+    - d-cache-size : one cell, size of L1 data cache in bytes
+    - i-cache-size : one cell, size of L1 instruction cache in bytes
+
+(*) The cache "block" size is the size on which the cache management
+instructions operate. Historically, this document used the cache
+"line" size here which is incorrect. The kernel will prefer the cache
+block size and will fallback to cache line size for backward
+compatibility.
+
+  Recommended properties:
+
+    - timebase-frequency : a cell indicating the frequency of the
+      timebase in Hz. This is not directly used by the generic code,
+      but you are welcome to copy/paste the pSeries code for setting
+      the kernel timebase/decrementer calibration based on this
+      value.
+    - clock-frequency : a cell indicating the CPU core clock frequency
+      in Hz. A new property will be defined for 64-bit values, but if
+      your frequency is < 4Ghz, one cell is enough. Here as well as
+      for the above, the common code doesn't use that property, but
+      you are welcome to re-use the pSeries or Maple one. A future
+      kernel version might provide a common function for this.
+    - d-cache-line-size : one cell, L1 data cache line size in bytes
+      if different from the block size
+    - i-cache-line-size : one cell, L1 instruction cache line size in
+      bytes if different from the block size
+
+  You are welcome to add any property you find relevant to your board,
+  like some information about the mechanism used to soft-reset the
+  CPUs. For example, Apple puts the GPIO number for CPU soft reset
+  lines in there as a "soft-reset" property since they start secondary
+  CPUs by soft-resetting them.
+
+
+  d) the /memory node(s)
+
+  To define the physical memory layout of your board, you should
+  create one or more memory node(s). You can either create a single
+  node with all memory ranges in its reg property, or you can create
+  several nodes, as you wish. The unit address (@ part) used for the
+  full path is the address of the first range of memory defined by a
+  given node. If you use a single memory node, this will typically be
+  @0.
+
+  Required properties:
+
+    - device_type : has to be "memory"
+    - reg : This property contains all the physical memory ranges of
+      your board. It's a list of addresses/sizes concatenated
+      together, with the number of cells of each defined by the
+      #address-cells and #size-cells of the root node. For example,
+      with both of these properties being 2 like in the example given
+      earlier, a 970 based machine with 6Gb of RAM could typically
+      have a "reg" property here that looks like:
+
+      00000000 00000000 00000000 80000000
+      00000001 00000000 00000001 00000000
+
+      That is a range starting at 0 of 0x80000000 bytes and a range
+      starting at 0x100000000 and of 0x100000000 bytes. You can see
+      that there is no memory covering the IO hole between 2Gb and
+      4Gb. Some vendors prefer splitting those ranges into smaller
+      segments, but the kernel doesn't care.
+
+  e) The /chosen node
+
+  This node is a bit "special". Normally, that's where Open Firmware
+  puts some variable environment information, like the arguments, or
+  the default input/output devices.
+
+  This specification makes a few of these mandatory, but also defines
+  some linux-specific properties that would be normally constructed by
+  the prom_init() trampoline when booting with an OF client interface,
+  but that you have to provide yourself when using the flattened format.
+
+  Recommended properties:
+
+    - bootargs : This zero-terminated string is passed as the kernel
+      command line
+    - linux,stdout-path : This is the full path to your standard
+      console device if any. Typically, if you have serial devices on
+      your board, you may want to put the full path to the one set as
+      the default console in the firmware here, for the kernel to pick
+      it up as its own default console.
+
+  Note that u-boot creates and fills in the chosen node for platforms
+  that use it.
+
+  (Note: a practice that is now obsolete was to include a property
+  under /chosen called interrupt-controller which had a phandle value
+  that pointed to the main interrupt controller)
+
+  f) the /soc<SOCname> node
+
+  This node is used to represent a system-on-a-chip (SoC) and must be
+  present if the processor is a SoC. The top-level soc node contains
+  information that is global to all devices on the SoC. The node name
+  should contain a unit address for the SoC, which is the base address
+  of the memory-mapped register set for the SoC. The name of an SoC
+  node should start with "soc", and the remainder of the name should
+  represent the part number for the soc.  For example, the MPC8540's
+  soc node would be called "soc8540".
+
+  Required properties:
+
+    - ranges : Should be defined as specified in 1) to describe the
+      translation of SoC addresses for memory mapped SoC registers.
+    - bus-frequency: Contains the bus frequency for the SoC node.
+      Typically, the value of this field is filled in by the boot
+      loader.
+    - compatible : Exact model of the SoC
+
+
+  Recommended properties:
+
+    - reg : This property defines the address and size of the
+      memory-mapped registers that are used for the SOC node itself.
+      It does not include the child device registers - these will be
+      defined inside each child node.  The address specified in the
+      "reg" property should match the unit address of the SOC node.
+    - #address-cells : Address representation for "soc" devices.  The
+      format of this field may vary depending on whether or not the
+      device registers are memory mapped.  For memory mapped
+      registers, this field represents the number of cells needed to
+      represent the address of the registers.  For SOCs that do not
+      use MMIO, a special address format should be defined that
+      contains enough cells to represent the required information.
+      See 1) above for more details on defining #address-cells.
+    - #size-cells : Size representation for "soc" devices
+    - #interrupt-cells : Defines the width of cells used to represent
+       interrupts.  Typically this value is <2>, which includes a
+       32-bit number that represents the interrupt number, and a
+       32-bit number that represents the interrupt sense and level.
+       This field is only needed if the SOC contains an interrupt
+       controller.
+
+  The SOC node may contain child nodes for each SOC device that the
+  platform uses.  Nodes should not be created for devices which exist
+  on the SOC but are not used by a particular platform. See chapter VI
+  for more information on how to specify devices that are part of a SOC.
+
+  Example SOC node for the MPC8540:
+
+	soc8540@e0000000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		#interrupt-cells = <2>;
+		device_type = "soc";
+		ranges = <00000000 e0000000 00100000>
+		reg = <e0000000 00003000>;
+		bus-frequency = <0>;
+	}
+
+
+
+IV - "dtc", the device tree compiler
+====================================
+
+
+dtc source code can be found at
+<http://git.jdl.com/gitweb/?p=dtc.git>
+
+WARNING: This version is still in early development stage; the
+resulting device-tree "blobs" have not yet been validated with the
+kernel. The current generated block lacks a useful reserve map (it will
+be fixed to generate an empty one, it's up to the bootloader to fill
+it up) among others. The error handling needs work, bugs are lurking,
+etc...
+
+dtc basically takes a device-tree in a given format and outputs a
+device-tree in another format. The currently supported formats are:
+
+  Input formats:
+  -------------
+
+     - "dtb": "blob" format, that is a flattened device-tree block
+       with
+        header all in a binary blob.
+     - "dts": "source" format. This is a text file containing a
+       "source" for a device-tree. The format is defined later in this
+        chapter.
+     - "fs" format. This is a representation equivalent to the
+        output of /proc/device-tree, that is nodes are directories and
+	properties are files
+
+ Output formats:
+ ---------------
+
+     - "dtb": "blob" format
+     - "dts": "source" format
+     - "asm": assembly language file. This is a file that can be
+       sourced by gas to generate a device-tree "blob". That file can
+       then simply be added to your Makefile. Additionally, the
+       assembly file exports some symbols that can be used.
+
+
+The syntax of the dtc tool is
+
+    dtc [-I <input-format>] [-O <output-format>]
+        [-o output-filename] [-V output_version] input_filename
+
+
+The "output_version" defines what version of the "blob" format will be
+generated. Supported versions are 1,2,3 and 16. The default is
+currently version 3 but that may change in the future to version 16.
+
+Additionally, dtc performs various sanity checks on the tree, like the
+uniqueness of linux, phandle properties, validity of strings, etc...
+
+The format of the .dts "source" file is "C" like, supports C and C++
+style comments.
+
+/ {
+}
+
+The above is the "device-tree" definition. It's the only statement
+supported currently at the toplevel.
+
+/ {
+  property1 = "string_value";	/* define a property containing a 0
+                                 * terminated string
+				 */
+
+  property2 = <1234abcd>;	/* define a property containing a
+                                 * numerical 32-bit value (hexadecimal)
+				 */
+
+  property3 = <12345678 12345678 deadbeef>;
+                                /* define a property containing 3
+                                 * numerical 32-bit values (cells) in
+                                 * hexadecimal
+				 */
+  property4 = [0a 0b 0c 0d de ea ad be ef];
+                                /* define a property whose content is
+                                 * an arbitrary array of bytes
+                                 */
+
+  childnode@address {	/* define a child node named "childnode"
+                                 * whose unit name is "childnode at
+				 * address"
+                                 */
+
+    childprop = "hello\n";      /* define a property "childprop" of
+                                 * childnode (in this case, a string)
+                                 */
+  };
+};
+
+Nodes can contain other nodes etc... thus defining the hierarchical
+structure of the tree.
+
+Strings support common escape sequences from C: "\n", "\t", "\r",
+"\(octal value)", "\x(hex value)".
+
+It is also suggested that you pipe your source file through cpp (gcc
+preprocessor) so you can use #include's, #define for constants, etc...
+
+Finally, various options are planned but not yet implemented, like
+automatic generation of phandles, labels (exported to the asm file so
+you can point to a property content and change it easily from whatever
+you link the device-tree with), label or path instead of numeric value
+in some cells to "point" to a node (replaced by a phandle at compile
+time), export of reserve map address to the asm file, ability to
+specify reserve map content at compile time, etc...
+
+We may provide a .h include file with common definitions of that
+proves useful for some properties (like building PCI properties or
+interrupt maps) though it may be better to add a notion of struct
+definitions to the compiler...
+
+
+V - Recommendations for a bootloader
+====================================
+
+
+Here are some various ideas/recommendations that have been proposed
+while all this has been defined and implemented.
+
+  - The bootloader may want to be able to use the device-tree itself
+    and may want to manipulate it (to add/edit some properties,
+    like physical memory size or kernel arguments). At this point, 2
+    choices can be made. Either the bootloader works directly on the
+    flattened format, or the bootloader has its own internal tree
+    representation with pointers (similar to the kernel one) and
+    re-flattens the tree when booting the kernel. The former is a bit
+    more difficult to edit/modify, the later requires probably a bit
+    more code to handle the tree structure. Note that the structure
+    format has been designed so it's relatively easy to "insert"
+    properties or nodes or delete them by just memmoving things
+    around. It contains no internal offsets or pointers for this
+    purpose.
+
+  - An example of code for iterating nodes & retrieving properties
+    directly from the flattened tree format can be found in the kernel
+    file drivers/of/fdt.c.  Look at the of_scan_flat_dt() function,
+    its usage in early_init_devtree(), and the corresponding various
+    early_init_dt_scan_*() callbacks. That code can be re-used in a
+    GPL bootloader, and as the author of that code, I would be happy
+    to discuss possible free licensing to any vendor who wishes to
+    integrate all or part of this code into a non-GPL bootloader.
+    (reference needed; who is 'I' here? ---gcl Jan 31, 2011)
+
+
+
+VI - System-on-a-chip devices and nodes
+=======================================
+
+Many companies are now starting to develop system-on-a-chip
+processors, where the processor core (CPU) and many peripheral devices
+exist on a single piece of silicon.  For these SOCs, an SOC node
+should be used that defines child nodes for the devices that make
+up the SOC. While platforms are not required to use this model in
+order to boot the kernel, it is highly encouraged that all SOC
+implementations define as complete a flat-device-tree as possible to
+describe the devices on the SOC.  This will allow for the
+genericization of much of the kernel code.
+
+
+1) Defining child nodes of an SOC
+---------------------------------
+
+Each device that is part of an SOC may have its own node entry inside
+the SOC node.  For each device that is included in the SOC, the unit
+address property represents the address offset for this device's
+memory-mapped registers in the parent's address space.  The parent's
+address space is defined by the "ranges" property in the top-level soc
+node. The "reg" property for each node that exists directly under the
+SOC node should contain the address mapping from the child address space
+to the parent SOC address space and the size of the device's
+memory-mapped register file.
+
+For many devices that may exist inside an SOC, there are predefined
+specifications for the format of the device tree node.  All SOC child
+nodes should follow these specifications, except where noted in this
+document.
+
+See appendix A for an example partial SOC node definition for the
+MPC8540.
+
+
+2) Representing devices without a current OF specification
+----------------------------------------------------------
+
+Currently, there are many devices on SoCs that do not have a standard
+representation defined as part of the Open Firmware specifications,
+mainly because the boards that contain these SoCs are not currently
+booted using Open Firmware.  Binding documentation for new devices
+should be added to the Documentation/devicetree/bindings directory.
+That directory will expand as device tree support is added to more and
+more SoCs.
+
+
+VII - Specifying interrupt information for devices
+===================================================
+
+The device tree represents the buses and devices of a hardware
+system in a form similar to the physical bus topology of the
+hardware.
+
+In addition, a logical 'interrupt tree' exists which represents the
+hierarchy and routing of interrupts in the hardware.
+
+The interrupt tree model is fully described in the
+document "Open Firmware Recommended Practice: Interrupt
+Mapping Version 0.9".  The document is available at:
+<http://playground.sun.com/1275/practice>.
+
+1) interrupts property
+----------------------
+
+Devices that generate interrupts to a single interrupt controller
+should use the conventional OF representation described in the
+OF interrupt mapping documentation.
+
+Each device which generates interrupts must have an 'interrupt'
+property.  The interrupt property value is an arbitrary number of
+of 'interrupt specifier' values which describe the interrupt or
+interrupts for the device.
+
+The encoding of an interrupt specifier is determined by the
+interrupt domain in which the device is located in the
+interrupt tree.  The root of an interrupt domain specifies in
+its #interrupt-cells property the number of 32-bit cells
+required to encode an interrupt specifier.  See the OF interrupt
+mapping documentation for a detailed description of domains.
+
+For example, the binding for the OpenPIC interrupt controller
+specifies  an #interrupt-cells value of 2 to encode the interrupt
+number and level/sense information. All interrupt children in an
+OpenPIC interrupt domain use 2 cells per interrupt in their interrupts
+property.
+
+The PCI bus binding specifies a #interrupt-cell value of 1 to encode
+which interrupt pin (INTA,INTB,INTC,INTD) is used.
+
+2) interrupt-parent property
+----------------------------
+
+The interrupt-parent property is specified to define an explicit
+link between a device node and its interrupt parent in
+the interrupt tree.  The value of interrupt-parent is the
+phandle of the parent node.
+
+If the interrupt-parent property is not defined for a node, its
+interrupt parent is assumed to be an ancestor in the node's
+_device tree_ hierarchy.
+
+3) OpenPIC Interrupt Controllers
+--------------------------------
+
+OpenPIC interrupt controllers require 2 cells to encode
+interrupt information.  The first cell defines the interrupt
+number.  The second cell defines the sense and level
+information.
+
+Sense and level information should be encoded as follows:
+
+	0 = low to high edge sensitive type enabled
+	1 = active low level sensitive type enabled
+	2 = active high level sensitive type enabled
+	3 = high to low edge sensitive type enabled
+
+4) ISA Interrupt Controllers
+----------------------------
+
+ISA PIC interrupt controllers require 2 cells to encode
+interrupt information.  The first cell defines the interrupt
+number.  The second cell defines the sense and level
+information.
+
+ISA PIC interrupt controllers should adhere to the ISA PIC
+encodings listed below:
+
+	0 =  active low level sensitive type enabled
+	1 =  active high level sensitive type enabled
+	2 =  high to low edge sensitive type enabled
+	3 =  low to high edge sensitive type enabled
+
+VIII - Specifying Device Power Management Information (sleep property)
+===================================================================
+
+Devices on SOCs often have mechanisms for placing devices into low-power
+states that are decoupled from the devices' own register blocks.  Sometimes,
+this information is more complicated than a cell-index property can
+reasonably describe.  Thus, each device controlled in such a manner
+may contain a "sleep" property which describes these connections.
+
+The sleep property consists of one or more sleep resources, each of
+which consists of a phandle to a sleep controller, followed by a
+controller-specific sleep specifier of zero or more cells.
+
+The semantics of what type of low power modes are possible are defined
+by the sleep controller.  Some examples of the types of low power modes
+that may be supported are:
+
+ - Dynamic: The device may be disabled or enabled at any time.
+ - System Suspend: The device may request to be disabled or remain
+   awake during system suspend, but will not be disabled until then.
+ - Permanent: The device is disabled permanently (until the next hard
+   reset).
+
+Some devices may share a clock domain with each other, such that they should
+only be suspended when none of the devices are in use.  Where reasonable,
+such nodes should be placed on a virtual bus, where the bus has the sleep
+property.  If the clock domain is shared among devices that cannot be
+reasonably grouped in this manner, then create a virtual sleep controller
+(similar to an interrupt nexus, except that defining a standardized
+sleep-map should wait until its necessity is demonstrated).
+
+Appendix A - Sample SOC node for MPC8540
+========================================
+
+	soc@e0000000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "fsl,mpc8540-ccsr", "simple-bus";
+		device_type = "soc";
+		ranges = <0x00000000 0xe0000000 0x00100000>
+		bus-frequency = <0>;
+		interrupt-parent = <&pic>;
+
+		ethernet@24000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			device_type = "network";
+			model = "TSEC";
+			compatible = "gianfar", "simple-bus";
+			reg = <0x24000 0x1000>;
+			local-mac-address = [ 00 E0 0C 00 73 00 ];
+			interrupts = <29 2 30 2 34 2>;
+			phy-handle = <&phy0>;
+			sleep = <&pmc 00000080>;
+			ranges;
+
+			mdio@24520 {
+				reg = <0x24520 0x20>;
+				compatible = "fsl,gianfar-mdio";
+
+				phy0: ethernet-phy@0 {
+					interrupts = <5 1>;
+					reg = <0>;
+					device_type = "ethernet-phy";
+				};
+
+				phy1: ethernet-phy@1 {
+					interrupts = <5 1>;
+					reg = <1>;
+					device_type = "ethernet-phy";
+				};
+
+				phy3: ethernet-phy@3 {
+					interrupts = <7 1>;
+					reg = <3>;
+					device_type = "ethernet-phy";
+				};
+			};
+		};
+
+		ethernet@25000 {
+			device_type = "network";
+			model = "TSEC";
+			compatible = "gianfar";
+			reg = <0x25000 0x1000>;
+			local-mac-address = [ 00 E0 0C 00 73 01 ];
+			interrupts = <13 2 14 2 18 2>;
+			phy-handle = <&phy1>;
+			sleep = <&pmc 00000040>;
+		};
+
+		ethernet@26000 {
+			device_type = "network";
+			model = "FEC";
+			compatible = "gianfar";
+			reg = <0x26000 0x1000>;
+			local-mac-address = [ 00 E0 0C 00 73 02 ];
+			interrupts = <41 2>;
+			phy-handle = <&phy3>;
+			sleep = <&pmc 00000020>;
+		};
+
+		serial@4500 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "fsl,mpc8540-duart", "simple-bus";
+			sleep = <&pmc 00000002>;
+			ranges;
+
+			serial@4500 {
+				device_type = "serial";
+				compatible = "ns16550";
+				reg = <0x4500 0x100>;
+				clock-frequency = <0>;
+				interrupts = <42 2>;
+			};
+
+			serial@4600 {
+				device_type = "serial";
+				compatible = "ns16550";
+				reg = <0x4600 0x100>;
+				clock-frequency = <0>;
+				interrupts = <42 2>;
+			};
+		};
+
+		pic: pic@40000 {
+			interrupt-controller;
+			#address-cells = <0>;
+			#interrupt-cells = <2>;
+			reg = <0x40000 0x40000>;
+			compatible = "chrp,open-pic";
+			device_type = "open-pic";
+		};
+
+		i2c@3000 {
+			interrupts = <43 2>;
+			reg = <0x3000 0x100>;
+			compatible  = "fsl-i2c";
+			dfsrr;
+			sleep = <&pmc 00000004>;
+		};
+
+		pmc: power@e0070 {
+			compatible = "fsl,mpc8540-pmc", "fsl,mpc8548-pmc";
+			reg = <0xe0070 0x20>;
+		};
+	};
diff -druNp linux-libre-2.6.37-gnu1/Documentation/DocBook/80211.tmpl linux-libre-2.6.38-gnu1/Documentation/DocBook/80211.tmpl
--- linux-libre-2.6.37-gnu1/Documentation/DocBook/80211.tmpl	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/DocBook/80211.tmpl	2011-03-14 21:20:32.000000000 -0400
@@ -146,6 +146,7 @@
 !Finclude/net/cfg80211.h cfg80211_rx_mgmt
 !Finclude/net/cfg80211.h cfg80211_mgmt_tx_status
 !Finclude/net/cfg80211.h cfg80211_cqm_rssi_notify
+!Finclude/net/cfg80211.h cfg80211_cqm_pktloss_notify
 !Finclude/net/cfg80211.h cfg80211_michael_mic_failure
       </chapter>
       <chapter>
@@ -267,10 +268,6 @@
 !Finclude/net/mac80211.h ieee80211_ops
 !Finclude/net/mac80211.h ieee80211_alloc_hw
 !Finclude/net/mac80211.h ieee80211_register_hw
-!Finclude/net/mac80211.h ieee80211_get_tx_led_name
-!Finclude/net/mac80211.h ieee80211_get_rx_led_name
-!Finclude/net/mac80211.h ieee80211_get_assoc_led_name
-!Finclude/net/mac80211.h ieee80211_get_radio_led_name
 !Finclude/net/mac80211.h ieee80211_unregister_hw
 !Finclude/net/mac80211.h ieee80211_free_hw
       </chapter>
@@ -332,10 +329,16 @@
           <title>functions/definitions</title>
 !Finclude/net/mac80211.h ieee80211_rx_status
 !Finclude/net/mac80211.h mac80211_rx_flags
+!Finclude/net/mac80211.h mac80211_tx_control_flags
+!Finclude/net/mac80211.h mac80211_rate_control_flags
+!Finclude/net/mac80211.h ieee80211_tx_rate
 !Finclude/net/mac80211.h ieee80211_tx_info
+!Finclude/net/mac80211.h ieee80211_tx_info_clear_status
 !Finclude/net/mac80211.h ieee80211_rx
+!Finclude/net/mac80211.h ieee80211_rx_ni
 !Finclude/net/mac80211.h ieee80211_rx_irqsafe
 !Finclude/net/mac80211.h ieee80211_tx_status
+!Finclude/net/mac80211.h ieee80211_tx_status_ni
 !Finclude/net/mac80211.h ieee80211_tx_status_irqsafe
 !Finclude/net/mac80211.h ieee80211_rts_get
 !Finclude/net/mac80211.h ieee80211_rts_duration
@@ -346,6 +349,7 @@
 !Finclude/net/mac80211.h ieee80211_stop_queue
 !Finclude/net/mac80211.h ieee80211_wake_queues
 !Finclude/net/mac80211.h ieee80211_stop_queues
+!Finclude/net/mac80211.h ieee80211_queue_stopped
         </sect1>
       </chapter>
 
@@ -354,6 +358,13 @@
 !Pinclude/net/mac80211.h Frame filtering
 !Finclude/net/mac80211.h ieee80211_filter_flags
       </chapter>
+
+      <chapter id="workqueue">
+        <title>The mac80211 workqueue</title>
+!Pinclude/net/mac80211.h mac80211 workqueue
+!Finclude/net/mac80211.h ieee80211_queue_work
+!Finclude/net/mac80211.h ieee80211_queue_delayed_work
+      </chapter>
     </part>
 
     <part id="advanced">
@@ -367,6 +378,23 @@
         </para>
       </partintro>
 
+      <chapter id="led-support">
+        <title>LED support</title>
+        <para>
+         Mac80211 supports various ways of blinking LEDs. Wherever possible,
+         device LEDs should be exposed as LED class devices and hooked up to
+         the appropriate trigger, which will then be triggered appropriately
+         by mac80211.
+        </para>
+!Finclude/net/mac80211.h ieee80211_get_tx_led_name
+!Finclude/net/mac80211.h ieee80211_get_rx_led_name
+!Finclude/net/mac80211.h ieee80211_get_assoc_led_name
+!Finclude/net/mac80211.h ieee80211_get_radio_led_name
+!Finclude/net/mac80211.h ieee80211_tpt_blink
+!Finclude/net/mac80211.h ieee80211_tpt_led_trigger_flags
+!Finclude/net/mac80211.h ieee80211_create_tpt_led_trigger
+      </chapter>
+
       <chapter id="hardware-crypto-offload">
         <title>Hardware crypto acceleration</title>
 !Pinclude/net/mac80211.h Hardware crypto acceleration
@@ -374,6 +402,9 @@
 !Finclude/net/mac80211.h set_key_cmd
 !Finclude/net/mac80211.h ieee80211_key_conf
 !Finclude/net/mac80211.h ieee80211_key_flags
+!Finclude/net/mac80211.h ieee80211_tkip_key_type
+!Finclude/net/mac80211.h ieee80211_get_tkip_key
+!Finclude/net/mac80211.h ieee80211_key_removed
       </chapter>
 
       <chapter id="powersave">
@@ -417,6 +448,18 @@
           supported by mac80211, add notes about supporting hw crypto
           with it.
         </para>
+!Finclude/net/mac80211.h ieee80211_iterate_active_interfaces
+!Finclude/net/mac80211.h ieee80211_iterate_active_interfaces_atomic
+      </chapter>
+
+      <chapter id="station-handling">
+        <title>Station handling</title>
+        <para>TODO</para>
+!Finclude/net/mac80211.h ieee80211_sta
+!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">
@@ -424,6 +467,28 @@
         <para>TBD</para>
 !Finclude/net/mac80211.h ieee80211_scan_completed
       </chapter>
+
+      <chapter id="aggregation">
+        <title>Aggregation</title>
+        <sect1>
+          <title>TX A-MPDU aggregation</title>
+!Pnet/mac80211/agg-tx.c TX A-MPDU aggregation
+!Cnet/mac80211/agg-tx.c
+        </sect1>
+        <sect1>
+          <title>RX A-MPDU aggregation</title>
+!Pnet/mac80211/agg-rx.c RX A-MPDU aggregation
+!Cnet/mac80211/agg-rx.c
+        </sect1>
+!Finclude/net/mac80211.h ieee80211_ampdu_mlme_action
+      </chapter>
+
+      <chapter id="smps">
+        <title>Spatial Multiplexing Powersave (SMPS)</title>
+!Pinclude/net/mac80211.h Spatial multiplexing power save
+!Finclude/net/mac80211.h ieee80211_request_smps
+!Finclude/net/mac80211.h ieee80211_smps_mode
+      </chapter>
     </part>
 
     <part id="rate-control">
@@ -435,9 +500,16 @@
          interface and how it relates to mac80211 and drivers.
         </para>
       </partintro>
-      <chapter id="dummy">
-        <title>dummy chapter</title>
+      <chapter id="ratecontrol-api">
+        <title>Rate Control API</title>
         <para>TBD</para>
+!Finclude/net/mac80211.h ieee80211_start_tx_ba_session
+!Finclude/net/mac80211.h ieee80211_start_tx_ba_cb_irqsafe
+!Finclude/net/mac80211.h ieee80211_stop_tx_ba_session
+!Finclude/net/mac80211.h ieee80211_stop_tx_ba_cb_irqsafe
+!Finclude/net/mac80211.h rate_control_changed
+!Finclude/net/mac80211.h ieee80211_tx_rate_control
+!Finclude/net/mac80211.h rate_control_send_low
       </chapter>
     </part>
 
@@ -485,6 +557,13 @@
         </sect1>
       </chapter>
 
+      <chapter id="aggregation-internals">
+        <title>Aggregation</title>
+!Fnet/mac80211/sta_info.h sta_ampdu_mlme
+!Fnet/mac80211/sta_info.h tid_ampdu_tx
+!Fnet/mac80211/sta_info.h tid_ampdu_rx
+      </chapter>
+
       <chapter id="synchronisation">
         <title>Synchronisation</title>
         <para>TBD</para>
diff -druNp linux-libre-2.6.37-gnu1/Documentation/DocBook/device-drivers.tmpl linux-libre-2.6.38-gnu1/Documentation/DocBook/device-drivers.tmpl
--- linux-libre-2.6.37-gnu1/Documentation/DocBook/device-drivers.tmpl	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/DocBook/device-drivers.tmpl	2011-03-14 21:20:32.000000000 -0400
@@ -217,8 +217,8 @@ X!Isound/sound_firmware.c
   <chapter id="uart16x50">
      <title>16x50 UART Driver</title>
 !Iinclude/linux/serial_core.h
-!Edrivers/serial/serial_core.c
-!Edrivers/serial/8250.c
+!Edrivers/tty/serial/serial_core.c
+!Edrivers/tty/serial/8250.c
   </chapter>
 
   <chapter id="fbdev">
@@ -304,6 +304,10 @@ X!Idrivers/video/console/fonts.c
 !Edrivers/input/ff-core.c
 !Edrivers/input/ff-memless.c
      </sect1>
+     <sect1><title>Multitouch Library</title>
+!Iinclude/linux/input/mt.h
+!Edrivers/input/input-mt.c
+     </sect1>
      <sect1><title>Polled input devices</title>
 !Iinclude/linux/input-polldev.h
 !Edrivers/input/input-polldev.c
diff -druNp linux-libre-2.6.37-gnu1/Documentation/DocBook/drm.tmpl linux-libre-2.6.38-gnu1/Documentation/DocBook/drm.tmpl
--- linux-libre-2.6.37-gnu1/Documentation/DocBook/drm.tmpl	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/DocBook/drm.tmpl	2011-03-14 21:20:32.000000000 -0400
@@ -73,8 +73,8 @@
       services.
     </para>
     <para>
-      The core of every DRM driver is struct drm_device.  Drivers
-      will typically statically initialize a drm_device structure,
+      The core of every DRM driver is struct drm_driver.  Drivers
+      will typically statically initialize a drm_driver structure,
       then pass it to drm_init() at load time.
     </para>
 
@@ -84,7 +84,7 @@
     <title>Driver initialization</title>
     <para>
       Before calling the DRM initialization routines, the driver must
-      first create and fill out a struct drm_device structure.
+      first create and fill out a struct drm_driver structure.
     </para>
     <programlisting>
       static struct drm_driver driver = {
diff -druNp linux-libre-2.6.37-gnu1/Documentation/DocBook/dvb/dvbapi.xml linux-libre-2.6.38-gnu1/Documentation/DocBook/dvb/dvbapi.xml
--- linux-libre-2.6.37-gnu1/Documentation/DocBook/dvb/dvbapi.xml	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/DocBook/dvb/dvbapi.xml	2011-03-14 21:20:32.000000000 -0400
@@ -28,7 +28,7 @@
 	<holder>Convergence GmbH</holder>
 </copyright>
 <copyright>
-	<year>2009-2010</year>
+	<year>2009-2011</year>
 	<holder>Mauro Carvalho Chehab</holder>
 </copyright>
 
diff -druNp linux-libre-2.6.37-gnu1/Documentation/DocBook/filesystems.tmpl linux-libre-2.6.38-gnu1/Documentation/DocBook/filesystems.tmpl
--- linux-libre-2.6.37-gnu1/Documentation/DocBook/filesystems.tmpl	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/DocBook/filesystems.tmpl	2011-03-14 21:20:32.000000000 -0400
@@ -82,6 +82,11 @@
      </sect1>
   </chapter>
 
+  <chapter id="fs_events">
+     <title>Events based on file descriptors</title>
+!Efs/eventfd.c
+  </chapter>
+
   <chapter id="sysfs">
      <title>The Filesystem for Exporting Kernel Objects</title>
 !Efs/sysfs/file.c
diff -druNp linux-libre-2.6.37-gnu1/Documentation/DocBook/media.tmpl linux-libre-2.6.38-gnu1/Documentation/DocBook/media.tmpl
--- linux-libre-2.6.37-gnu1/Documentation/DocBook/media.tmpl	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/DocBook/media.tmpl	2011-03-14 21:20:32.000000000 -0400
@@ -28,7 +28,7 @@
 <title>LINUX MEDIA INFRASTRUCTURE API</title>
 
 <copyright>
-	<year>2009-2010</year>
+	<year>2009-2011</year>
 	<holder>LinuxTV Developers</holder>
 </copyright>
 
@@ -86,7 +86,7 @@ Foundation. A copy of the license is inc
 </author>
 </authorgroup>
 <copyright>
-	<year>2009-2010</year>
+	<year>2009-2011</year>
 	<holder>Mauro Carvalho Chehab</holder>
 </copyright>
 
diff -druNp linux-libre-2.6.37-gnu1/Documentation/DocBook/mtdnand.tmpl linux-libre-2.6.38-gnu1/Documentation/DocBook/mtdnand.tmpl
--- linux-libre-2.6.37-gnu1/Documentation/DocBook/mtdnand.tmpl	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/DocBook/mtdnand.tmpl	2011-03-14 21:20:32.000000000 -0400
@@ -250,7 +250,7 @@ static void board_hwcontrol(struct mtd_i
 		<title>Device ready function</title>
 		<para>
 			If the hardware interface has the ready busy pin of the NAND chip connected to a
-			GPIO or other accesible I/O pin, this function is used to read back the state of the
+			GPIO or other accessible I/O pin, this function is used to read back the state of the
 			pin. The function has no arguments and should return 0, if the device is busy (R/B pin 
 			is low) and 1, if the device is ready (R/B pin is high).
 			If the hardware interface does not give access to the ready busy pin, then
diff -druNp linux-libre-2.6.37-gnu1/Documentation/DocBook/v4l/dev-rds.xml linux-libre-2.6.38-gnu1/Documentation/DocBook/v4l/dev-rds.xml
--- linux-libre-2.6.37-gnu1/Documentation/DocBook/v4l/dev-rds.xml	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/DocBook/v4l/dev-rds.xml	2011-03-14 21:20:32.000000000 -0400
@@ -75,6 +75,7 @@ as follows:</para>
   </section>
 
   <section>
+    <title>RDS datastructures</title>
     <table frame="none" pgwide="1" id="v4l2-rds-data">
       <title>struct
 <structname>v4l2_rds_data</structname></title>
@@ -129,10 +130,11 @@ as follows:</para>
 
     <table frame="none" pgwide="1" id="v4l2-rds-block-codes">
       <title>Block defines</title>
-      <tgroup cols="3">
+      <tgroup cols="4">
 	<colspec colname="c1" colwidth="1*" />
 	<colspec colname="c2" colwidth="1*" />
-	<colspec colname="c3" colwidth="5*" />
+	<colspec colname="c3" colwidth="1*" />
+	<colspec colname="c4" colwidth="5*" />
 	<tbody valign="top">
 	  <row>
 	    <entry>V4L2_RDS_BLOCK_MSK</entry>
diff -druNp linux-libre-2.6.37-gnu1/Documentation/DocBook/v4l/func-ioctl.xml linux-libre-2.6.38-gnu1/Documentation/DocBook/v4l/func-ioctl.xml
--- linux-libre-2.6.37-gnu1/Documentation/DocBook/v4l/func-ioctl.xml	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/DocBook/v4l/func-ioctl.xml	2011-03-14 21:20:32.000000000 -0400
@@ -34,8 +34,7 @@
       <varlistentry>
 	<term><parameter>request</parameter></term>
 	<listitem>
-	  <para>V4L2 ioctl request code as defined in the <link
-linkend="videodev">videodev.h</link> header file, for example
+	  <para>V4L2 ioctl request code as defined in the <filename>videodev2.h</filename> header file, for example
 VIDIOC_QUERYCAP.</para>
 	</listitem>
       </varlistentry>
@@ -57,7 +56,7 @@ file descriptor. An ioctl <parameter>req
 in it whether the argument is an input, output or read/write
 parameter, and the size of the argument <parameter>argp</parameter> in
 bytes. Macros and defines specifying V4L2 ioctl requests are located
-in the <link linkend="videodev">videodev.h</link> header file.
+in the <filename>videodev2.h</filename> header file.
 Applications should use their own copy, not include the version in the
 kernel sources on the system they compile on. All V4L2 ioctl requests,
 their respective function and parameters are specified in <xref
diff -druNp linux-libre-2.6.37-gnu1/Documentation/DocBook/v4l/pixfmt.xml linux-libre-2.6.38-gnu1/Documentation/DocBook/v4l/pixfmt.xml
--- linux-libre-2.6.37-gnu1/Documentation/DocBook/v4l/pixfmt.xml	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/DocBook/v4l/pixfmt.xml	2011-03-14 21:20:32.000000000 -0400
@@ -142,8 +142,8 @@ leftmost pixel of the second row from th
 has just as many pad bytes after it as the other rows.</para>
 
     <para>In V4L2 each format has an identifier which looks like
-<constant>PIX_FMT_XXX</constant>, defined in the <link
-linkend="videodev">videodev.h</link> header file. These identifiers
+<constant>PIX_FMT_XXX</constant>, defined in the <filename>videodev2.h</filename>
+header file. These identifiers
 represent <link linkend="v4l2-fourcc">four character codes</link>
 which are also listed below, however they are not the same as those
 used in the Windows world.</para>
diff -druNp linux-libre-2.6.37-gnu1/Documentation/DocBook/v4l/v4l2.xml linux-libre-2.6.38-gnu1/Documentation/DocBook/v4l/v4l2.xml
--- linux-libre-2.6.37-gnu1/Documentation/DocBook/v4l/v4l2.xml	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/DocBook/v4l/v4l2.xml	2011-03-14 21:20:32.000000000 -0400
@@ -100,6 +100,7 @@ Remote Controller chapter.</contrib>
       <year>2008</year>
       <year>2009</year>
       <year>2010</year>
+      <year>2011</year>
       <holder>Bill Dirks, Michael H. Schimek, Hans Verkuil, Martin
 Rubli, Andy Walls, Muralidharan Karicheri, Mauro Carvalho Chehab</holder>
     </copyright>
@@ -381,7 +382,7 @@ and discussions on the V4L mailing list.
 </partinfo>
 
 <title>Video for Linux Two API Specification</title>
- <subtitle>Revision 2.6.33</subtitle>
+ <subtitle>Revision 2.6.38</subtitle>
 
   <chapter id="common">
     &sub-common;
diff -druNp linux-libre-2.6.37-gnu1/Documentation/dontdiff linux-libre-2.6.38-gnu1/Documentation/dontdiff
--- linux-libre-2.6.37-gnu1/Documentation/dontdiff	2013-05-03 03:54:18.000000000 -0400
+++ linux-libre-2.6.38-gnu1/Documentation/dontdiff	2013-05-03 01:53:16.000000000 -0400
@@ -62,6 +62,10 @@ aic7*reg_print.c*
 aic7*seq.h*
 aicasm
 aicdb.h*
+altivec1.c
+altivec2.c
+altivec4.c
+altivec8.c
 asm-offsets.h
 asm_offsets.h
 autoconf.h*
@@ -76,6 +80,7 @@ btfixupprep
 build
 bvmlinux
 bzImage*
+capflags.c
 classlist.h*
 comp*.log
 compile.h*
@@ -94,6 +99,7 @@ devlist.h*
 docproc
 elf2ecoff
 elfconfig.h*
+evergreen_reg_safe.h
 fixdep
 flask.h
 fore200e_mkfirm
@@ -108,9 +114,16 @@ genksyms
 *_gray256.c
 ihex2fw
 ikconfig.h*
+inat-tables.c
 initramfs_data.cpio
 initramfs_data.cpio.gz
 initramfs_list
+int16.c
+int1.c
+int2.c
+int32.c
+int4.c
+int8.c
 kallsyms
 kconfig
 keywords.c
@@ -140,6 +153,7 @@ mkprep
 mktables
 mktree
 modpost
+modules.builtin
 modules.order
 modversions.h*
 ncscope.*
@@ -153,14 +167,23 @@ patches*
 /*(DEBLOBBED)*/
 piggy.gz
 piggyback
+piggy.S
 pnmtologo
 ppc_defs.h*
 pss_boot.h
 qconf
+r100_reg_safe.h
+r200_reg_safe.h
+r300_reg_safe.h
+r420_reg_safe.h
+r600_reg_safe.h
 raid6altivec*.c
 raid6int*.c
 raid6tables.c
 relocs
+rn50_reg_safe.h
+rs600_reg_safe.h
+rv515_reg_safe.h
 series
 setup
 setup.bin
@@ -169,6 +192,7 @@ sImage
 sm_tbl*
 split-include
 syscalltab.h
+tables.c
 tags
 tftpboot.img
 timeconst.h
@@ -190,6 +214,7 @@ vmlinux
 vmlinux-*
 vmlinux.aout
 vmlinux.lds
+voffset.h
 vsyscall.lds
 vsyscall_32.lds
 wanxlfw.inc
@@ -200,3 +225,4 @@ wakeup.elf
 wakeup.lds
 zImage*
 zconf.hash.c
+zoffset.h
diff -druNp linux-libre-2.6.37-gnu1/Documentation/email-clients.txt linux-libre-2.6.38-gnu1/Documentation/email-clients.txt
--- linux-libre-2.6.37-gnu1/Documentation/email-clients.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/email-clients.txt	2011-03-14 21:20:32.000000000 -0400
@@ -104,6 +104,13 @@ Then from the "Message" menu item, selec
 As an added bonus you can customise the message creation toolbar menu
 and put the "insert file" icon there.
 
+Make the the composer window wide enough so that no lines wrap. As of
+KMail 1.13.5 (KDE 4.5.4), KMail will apply word wrapping when sending
+the email if the lines wrap in the composer window. Having word wrapping
+disabled in the Options menu isn't enough. Thus, if your patch has very
+long lines, you must make the composer window very wide before sending
+the email. See: https://bugs.kde.org/show_bug.cgi?id=174034
+
 You can safely GPG sign attachments, but inlined text is preferred for
 patches so do not GPG sign them.  Signing patches that have been inserted
 as inlined text will make them tricky to extract from their 7-bit encoding.
@@ -179,26 +186,8 @@ Sylpheed (GUI)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 Thunderbird (GUI)
 
-By default, thunderbird likes to mangle text, but there are ways to
-coerce it into being nice.
-
-- Under account settings, composition and addressing, uncheck "Compose
-  messages in HTML format".
-
-- Edit your Thunderbird config settings to tell it not to wrap lines:
-      user_pref("mailnews.wraplength", 0);
-
-- Edit your Thunderbird config settings so that it won't use format=flowed:
-      user_pref("mailnews.send_plaintext_flowed", false);
-
-- You need to get Thunderbird into preformat mode:
-. If you compose HTML messages by default, it's not too hard. Just select
-  "Preformat" from the drop-down box just under the subject line.
-. If you compose in text by default, you have to tell it to compose a new
-  message in HTML (just as a one-off), and then force it from there back to
-  text, else it will wrap lines. To do this, use shift-click on the Write
-  icon to compose to get HTML compose mode, then select "Preformat" from
-  the drop-down box just under the subject line.
+Thunderbird is an Outlook clone that likes to mangle text, but there are ways
+to coerce it into behaving.
 
 - Allows use of an external editor:
   The easiest thing to do with Thunderbird and patches is to use an
@@ -208,6 +197,27 @@ coerce it into being nice.
   View->Toolbars->Customize... and finally just click on it when in the
   Compose dialog.
 
+To beat some sense out of the internal editor, do this:
+
+- Under account settings, composition and addressing, uncheck "Compose
+  messages in HTML format".
+
+- Edit your Thunderbird config settings so that it won't use format=flowed.
+  Go to "edit->preferences->advanced->config editor" to bring up the
+  thunderbird's registry editor, and set "mailnews.send_plaintext_flowed" to
+  "false".
+
+- Enable "preformat" mode: Shft-click on the Write icon to bring up the HTML
+  composer, select "Preformat" from the drop-down box just under the subject
+  line, then close the message without saving.  (This setting also applies to
+  the text composer, but the only control for it is in the HTML composer.)
+
+- Install the "toggle wordwrap" extension.  Download the file from:
+    https://addons.mozilla.org/thunderbird/addon/2351/
+  Then go to "tools->add ons", select "install" at the bottom of the screen,
+  and browse to where you saved the .xul file.  This adds an "Enable
+  Wordwrap" entry under the Options menu of the message composer.
+
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 TkRat (GUI)
 
diff -druNp linux-libre-2.6.37-gnu1/Documentation/fb/udlfb.txt linux-libre-2.6.38-gnu1/Documentation/fb/udlfb.txt
--- linux-libre-2.6.37-gnu1/Documentation/fb/udlfb.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/fb/udlfb.txt	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,144 @@
+
+What is udlfb?
+===============
+
+This is a driver for DisplayLink USB 2.0 era graphics chips.
+
+DisplayLink chips provide simple hline/blit operations with some compression,
+pairing that with a hardware framebuffer (16MB) on the other end of the
+USB wire.  That hardware framebuffer is able to drive the VGA, DVI, or HDMI
+monitor with no CPU involvement until a pixel has to change.
+
+The CPU or other local resource does all the rendering; optinally compares the
+result with a local shadow of the remote hardware framebuffer to identify
+the minimal set of pixels that have changed; and compresses and sends those
+pixels line-by-line via USB bulk transfers.
+
+Because of the efficiency of bulk transfers and a protocol on top that
+does not require any acks - the effect is very low latency that
+can support surprisingly high resolutions with good performance for
+non-gaming and non-video applications.
+
+Mode setting, EDID read, etc are other bulk or control transfers. Mode
+setting is very flexible - able to set nearly arbitrary modes from any timing.
+
+Advantages of USB graphics in general:
+
+ * Ability to add a nearly arbitrary number of displays to any USB 2.0
+   capable system. On Linux, number of displays is limited by fbdev interface
+   (FB_MAX is currently 32). Of course, all USB devices on the same
+   host controller share the same 480Mbs USB 2.0 interface.
+
+Advantages of supporting DisplayLink chips with kernel framebuffer interface:
+
+ * The actual hardware functionality of DisplayLink chips matches nearly
+   one-to-one with the fbdev interface, making the driver quite small and
+   tight relative to the functionality it provides.
+ * X servers and other applications can use the standard fbdev interface
+   from user mode to talk to the device, without needing to know anything
+   about USB or DisplayLink's protocol at all. A "displaylink" X driver
+   and a slightly modified "fbdev" X driver are among those that already do.
+
+Disadvantages:
+
+ * Fbdev's mmap interface assumes a real hardware framebuffer is mapped.
+   In the case of USB graphics, it is just an allocated (virtual) buffer.
+   Writes need to be detected and encoded into USB bulk transfers by the CPU.
+   Accurate damage/changed area notifications work around this problem.
+   In the future, hopefully fbdev will be enhanced with an small standard
+   interface to allow mmap clients to report damage, for the benefit
+   of virtual or remote framebuffers.
+ * Fbdev does not arbitrate client ownership of the framebuffer well.
+ * Fbcon assumes the first framebuffer it finds should be consumed for console.
+ * It's not clear what the future of fbdev is, given the rise of KMS/DRM.
+
+How to use it?
+==============
+
+Udlfb, when loaded as a module, will match against all USB 2.0 generation
+DisplayLink chips (Alex and Ollie family). It will then attempt to read the EDID
+of the monitor, and set the best common mode between the DisplayLink device
+and the monitor's capabilities.
+
+If the DisplayLink device is successful, it will paint a "green screen" which
+means that from a hardware and fbdev software perspective, everything is good.
+
+At that point, a /dev/fb? interface will be present for user-mode applications
+to open and begin writing to the framebuffer of the DisplayLink device using
+standard fbdev calls.  Note that if mmap() is used, by default the user mode
+application must send down damage notifcations to trigger repaints of the
+changed regions.  Alternatively, udlfb can be recompiled with experimental
+defio support enabled, to support a page-fault based detection mechanism
+that can work without explicit notifcation.
+
+The most common client of udlfb is xf86-video-displaylink or a modified
+xf86-video-fbdev X server. These servers have no real DisplayLink specific
+code. They write to the standard framebuffer interface and rely on udlfb
+to do its thing.  The one extra feature they have is the ability to report
+rectangles from the X DAMAGE protocol extension down to udlfb via udlfb's
+damage interface (which will hopefully be standardized for all virtual
+framebuffers that need damage info). These damage notifications allow
+udlfb to efficiently process the changed pixels.
+
+Module Options
+==============
+
+Special configuration for udlfb is usually unnecessary. There are a few
+options, however.
+
+From the command line, pass options to modprobe
+modprobe udlfb defio=1 console=1
+
+Or for permanent option, create file like /etc/modprobe.d/options with text
+options udlfb defio=1 console=1
+
+Accepted 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.
+
+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.
+
+Sysfs Attributes
+================
+
+Udlfb creates several files in /sys/class/graphics/fb?
+Where ? is the sequential framebuffer id of the particular DisplayLink device
+
+edid	       		If a valid EDID blob is written to this file (typically
+			by a udev rule), then udlfb will use this EDID as a
+			backup in case reading the actual EDID of the monitor
+			attached to the DisplayLink device fails. This is
+			especially useful for fixed panels, etc. that cannot
+			communicate their capabilities via EDID. Reading
+			this file returns the current EDID of the attached
+			monitor (or last backup value written). This is
+			useful to get the EDID of the attached monitor,
+			which can be passed to utilities like parse-edid.
+
+metrics_bytes_rendered	32-bit count of pixel bytes rendered
+
+metrics_bytes_identical 32-bit count of how many of those bytes were found to be
+			unchanged, based on a shadow framebuffer check
+
+metrics_bytes_sent	32-bit count of how many bytes were transferred over
+			USB to communicate the resulting changed pixels to the
+			hardware. Includes compression and protocol overhead
+
+metrics_cpu_kcycles_used 32-bit count of CPU cycles used in processing the
+			above pixels (in thousands of cycles).
+
+metrics_reset		Write-only. Any write to this file resets all metrics
+			above to zero.  Note that the 32-bit counters above
+			roll over very quickly. To get reliable results, design
+			performance tests to start and finish in a very short
+			period of time (one minute or less is safe).
+
+--
+Bernie Thompson <bernie@plugable.com>
diff -druNp linux-libre-2.6.37-gnu1/Documentation/feature-removal-schedule.txt linux-libre-2.6.38-gnu1/Documentation/feature-removal-schedule.txt
--- linux-libre-2.6.37-gnu1/Documentation/feature-removal-schedule.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/feature-removal-schedule.txt	2011-03-14 21:20:32.000000000 -0400
@@ -97,36 +97,38 @@ Who:	Pavel Machek <pavel@ucw.cz>
 
 ---------------------------
 
-What:	Video4Linux API 1 ioctls and from Video devices.
-When:	kernel 2.6.38
-Files:	include/linux/videodev.h
-Check:	include/linux/videodev.h
-Why:	V4L1 AP1 was replaced by V4L2 API during migration from 2.4 to 2.6
-	series. The old API have lots of drawbacks and don't provide enough
-	means to work with all video and audio standards. The newer API is
-	already available on the main drivers and should be used instead.
-	Newer drivers should use v4l_compat_translate_ioctl function to handle
-	old calls, replacing to newer ones.
-	Decoder iocts are using internally to allow video drivers to
-	communicate with video decoders. This should also be improved to allow
-	V4L2 calls being translated into compatible internal ioctls.
-	Compatibility ioctls will be provided, for a while, via 
-	v4l1-compat module. 
-Who:	Mauro Carvalho Chehab <mchehab@infradead.org>
-
----------------------------
-
 What:	Video4Linux obsolete drivers using V4L1 API
-When:	kernel 2.6.38
-Files:	drivers/staging/cpia/* drivers/staging/stradis/*
-Check:	drivers/staging/cpia/cpia.c drivers/staging/stradis/stradis.c
+When:	kernel 2.6.39
+Files:	drivers/staging/se401/* drivers/staging/usbvideo/*
+Check:	drivers/staging/se401/se401.c drivers/staging/usbvideo/usbvideo.c
 Why:	There are some drivers still using V4L1 API, despite all efforts we've done
 	to migrate. Those drivers are for obsolete hardware that the old maintainer
 	didn't care (or not have the hardware anymore), and that no other developer
 	could find any hardware to buy. They probably have no practical usage today,
 	and people with such old hardware could probably keep using an older version
-	of the kernel. Those drivers will be moved to staging on 2.6.37 and, if nobody
-	care enough to port and test them with V4L2 API, they'll be removed on 2.6.38.
+	of the kernel. Those drivers will be moved to staging on 2.6.38 and, if nobody
+	cares enough to port and test them with V4L2 API, they'll be removed on 2.6.39.
+Who:	Mauro Carvalho Chehab <mchehab@infradead.org>
+
+---------------------------
+
+What:	Video4Linux: Remove obsolete ioctl's
+When:	kernel 2.6.39
+Files:	include/media/videodev2.h
+Why:	Some ioctl's were defined wrong on 2.6.2 and 2.6.6, using the wrong
+	type of R/W arguments. They were fixed, but the old ioctl names are
+	still there, maintained to avoid breaking binary compatibility:
+	  #define VIDIOC_OVERLAY_OLD   	_IOWR('V', 14, int)
+	  #define VIDIOC_S_PARM_OLD	_IOW('V', 22, struct v4l2_streamparm)
+	  #define VIDIOC_S_CTRL_OLD	_IOW('V', 28, struct v4l2_control)
+	  #define VIDIOC_G_AUDIO_OLD	_IOWR('V', 33, struct v4l2_audio)
+	  #define VIDIOC_G_AUDOUT_OLD	_IOWR('V', 49, struct v4l2_audioout)
+	  #define VIDIOC_CROPCAP_OLD	_IOR('V', 58, struct v4l2_cropcap)
+	There's no sense on preserving those forever, as it is very doubtful
+	that someone would try to use a such old binary with a modern kernel.
+	Removing them will allow us to remove some magic done at the V4L ioctl
+	handler.
+
 Who:	Mauro Carvalho Chehab <mchehab@infradead.org>
 
 ---------------------------
@@ -191,6 +193,20 @@ Why:	/proc/<pid>/oom_adj allows userspac
 
 ---------------------------
 
+What:	CS5535/CS5536 obsolete GPIO driver
+When:	June 2011
+Files:	drivers/staging/cs5535_gpio/*
+Check:	drivers/staging/cs5535_gpio/cs5535_gpio.c
+Why:	A newer driver replaces this; it is drivers/gpio/cs5535-gpio.c, and
+	integrates with the Linux GPIO subsystem.  The old driver has been
+	moved to staging, and will be removed altogether around 2.6.40.
+	Please test the new driver, and ensure that the functionality you
+	need and any bugfixes from the old driver are available in the new
+	one.
+Who:	Andres Salomon <dilinger@queued.net>
+
+--------------------------
+
 What:	remove EXPORT_SYMBOL(kernel_thread)
 When:	August 2006
 Files:	arch/*/kernel/*_ksyms.c
@@ -232,6 +248,17 @@ Who:	Zhang Rui <rui.zhang@intel.com>
 
 ---------------------------
 
+What:	CONFIG_ACPI_PROCFS_POWER
+When:	2.6.39
+Why:	sysfs I/F for ACPI power devices, including AC and Battery,
+        has been working in upstream kenrel since 2.6.24, Sep 2007.
+	In 2.6.37, we make the sysfs I/F always built in and this option
+	disabled by default.
+	Remove this option and the ACPI power procfs interface in 2.6.39.
+Who:	Zhang Rui <rui.zhang@intel.com>
+
+---------------------------
+
 What:	/proc/acpi/button
 When:	August 2007
 Why:	/proc/acpi/button has been replaced by events to the input layer
@@ -330,14 +357,6 @@ Who:	Dave Jones <davej@redhat.com>, Matt
 
 -----------------------------
 
-What:	__do_IRQ all in one fits nothing interrupt handler
-When:	2.6.32
-Why:	__do_IRQ was kept for easy migration to the type flow handlers.
-	More than two years of migration time is enough.
-Who:	Thomas Gleixner <tglx@linutronix.de>
-
------------------------------
-
 What:	fakephp and associated sysfs files in /sys/bus/pci/slots/
 When:	2011
 Why:	In 2.6.27, the semantics of /sys/bus/pci/slots was redefined to
@@ -564,3 +583,39 @@ Why:	This field is deprecated. I2C devic
 Who:	Jean Delvare <khali@linux-fr.org>
 
 ----------------------------
+
+What:	cancel_rearming_delayed_work[queue]()
+When:	2.6.39
+
+Why:	The functions have been superceded by cancel_delayed_work_sync()
+	quite some time ago.  The conversion is trivial and there is no
+	in-kernel user left.
+Who:	Tejun Heo <tj@kernel.org>
+
+----------------------------
+
+What:	Legacy, non-standard chassis intrusion detection interface.
+When:	June 2011
+Why:	The adm9240, w83792d and w83793 hardware monitoring drivers have
+	legacy interfaces for chassis intrusion detection. A standard
+	interface has been added to each driver, so the legacy interface
+	can be removed.
+Who:	Jean Delvare <khali@linux-fr.org>
+
+----------------------------
+
+What:	noswapaccount kernel command line parameter
+When:	2.6.40
+Why:	The original implementation of memsw feature enabled by
+	CONFIG_CGROUP_MEM_RES_CTLR_SWAP could be disabled by the noswapaccount
+	kernel parameter (introduced in 2.6.29-rc1). Later on, this decision
+	turned out to be not ideal because we cannot have the feature compiled
+	in and disabled by default and let only interested to enable it
+	(e.g. general distribution kernels might need it). Therefore we have
+	added swapaccount[=0|1] parameter (introduced in 2.6.37) which provides
+	the both possibilities. If we remove noswapaccount we will have
+	less command line parameters with the same functionality and we
+	can also cleanup the parameter handling a bit ().
+Who:	Michal Hocko <mhocko@suse.cz>
+
+----------------------------
diff -druNp linux-libre-2.6.37-gnu1/Documentation/filesystems/dentry-locking.txt linux-libre-2.6.38-gnu1/Documentation/filesystems/dentry-locking.txt
--- linux-libre-2.6.37-gnu1/Documentation/filesystems/dentry-locking.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/filesystems/dentry-locking.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,174 +0,0 @@
-RCU-based dcache locking model
-==============================
-
-On many workloads, the most common operation on dcache is to look up a
-dentry, given a parent dentry and the name of the child. Typically,
-for every open(), stat() etc., the dentry corresponding to the
-pathname will be looked up by walking the tree starting with the first
-component of the pathname and using that dentry along with the next
-component to look up the next level and so on. Since it is a frequent
-operation for workloads like multiuser environments and web servers,
-it is important to optimize this path.
-
-Prior to 2.5.10, dcache_lock was acquired in d_lookup and thus in
-every component during path look-up. Since 2.5.10 onwards, fast-walk
-algorithm changed this by holding the dcache_lock at the beginning and
-walking as many cached path component dentries as possible. This
-significantly decreases the number of acquisition of
-dcache_lock. However it also increases the lock hold time
-significantly and affects performance in large SMP machines. Since
-2.5.62 kernel, dcache has been using a new locking model that uses RCU
-to make dcache look-up lock-free.
-
-The current dcache locking model is not very different from the
-existing dcache locking model. Prior to 2.5.62 kernel, dcache_lock
-protected the hash chain, d_child, d_alias, d_lru lists as well as
-d_inode and several other things like mount look-up. RCU-based changes
-affect only the way the hash chain is protected. For everything else
-the dcache_lock must be taken for both traversing as well as
-updating. The hash chain updates too take the dcache_lock.  The
-significant change is the way d_lookup traverses the hash chain, it
-doesn't acquire the dcache_lock for this and rely on RCU to ensure
-that the dentry has not been *freed*.
-
-
-Dcache locking details
-======================
-
-For many multi-user workloads, open() and stat() on files are very
-frequently occurring operations. Both involve walking of path names to
-find the dentry corresponding to the concerned file. In 2.4 kernel,
-dcache_lock was held during look-up of each path component. Contention
-and cache-line bouncing of this global lock caused significant
-scalability problems. With the introduction of RCU in Linux kernel,
-this was worked around by making the look-up of path components during
-path walking lock-free.
-
-
-Safe lock-free look-up of dcache hash table
-===========================================
-
-Dcache is a complex data structure with the hash table entries also
-linked together in other lists. In 2.4 kernel, dcache_lock protected
-all the lists. We applied RCU only on hash chain walking. The rest of
-the lists are still protected by dcache_lock.  Some of the important
-changes are :
-
-1. The deletion from hash chain is done using hlist_del_rcu() macro
-   which doesn't initialize next pointer of the deleted dentry and
-   this allows us to walk safely lock-free while a deletion is
-   happening.
-
-2. Insertion of a dentry into the hash table is done using
-   hlist_add_head_rcu() which take care of ordering the writes - the
-   writes to the dentry must be visible before the dentry is
-   inserted. This works in conjunction with hlist_for_each_rcu(),
-   which has since been replaced by hlist_for_each_entry_rcu(), while
-   walking the hash chain. The only requirement is that all
-   initialization to the dentry must be done before
-   hlist_add_head_rcu() since we don't have dcache_lock protection
-   while traversing the hash chain. This isn't different from the
-   existing code.
-
-3. The dentry looked up without holding dcache_lock by cannot be
-   returned for walking if it is unhashed. It then may have a NULL
-   d_inode or other bogosity since RCU doesn't protect the other
-   fields in the dentry. We therefore use a flag DCACHE_UNHASHED to
-   indicate unhashed dentries and use this in conjunction with a
-   per-dentry lock (d_lock). Once looked up without the dcache_lock,
-   we acquire the per-dentry lock (d_lock) and check if the dentry is
-   unhashed. If so, the look-up is failed. If not, the reference count
-   of the dentry is increased and the dentry is returned.
-
-4. Once a dentry is looked up, it must be ensured during the path walk
-   for that component it doesn't go away. In pre-2.5.10 code, this was
-   done holding a reference to the dentry. dcache_rcu does the same.
-   In some sense, dcache_rcu path walking looks like the pre-2.5.10
-   version.
-
-5. All dentry hash chain updates must take the dcache_lock as well as
-   the per-dentry lock in that order. dput() does this to ensure that
-   a dentry that has just been looked up in another CPU doesn't get
-   deleted before dget() can be done on it.
-
-6. There are several ways to do reference counting of RCU protected
-   objects. One such example is in ipv4 route cache where deferred
-   freeing (using call_rcu()) is done as soon as the reference count
-   goes to zero. This cannot be done in the case of dentries because
-   tearing down of dentries require blocking (dentry_iput()) which
-   isn't supported from RCU callbacks. Instead, tearing down of
-   dentries happen synchronously in dput(), but actual freeing happens
-   later when RCU grace period is over. This allows safe lock-free
-   walking of the hash chains, but a matched dentry may have been
-   partially torn down. The checking of DCACHE_UNHASHED flag with
-   d_lock held detects such dentries and prevents them from being
-   returned from look-up.
-
-
-Maintaining POSIX rename semantics
-==================================
-
-Since look-up of dentries is lock-free, it can race against a
-concurrent rename operation. For example, during rename of file A to
-B, look-up of either A or B must succeed.  So, if look-up of B happens
-after A has been removed from the hash chain but not added to the new
-hash chain, it may fail.  Also, a comparison while the name is being
-written concurrently by a rename may result in false positive matches
-violating rename semantics.  Issues related to race with rename are
-handled as described below :
-
-1. Look-up can be done in two ways - d_lookup() which is safe from
-   simultaneous renames and __d_lookup() which is not.  If
-   __d_lookup() fails, it must be followed up by a d_lookup() to
-   correctly determine whether a dentry is in the hash table or
-   not. d_lookup() protects look-ups using a sequence lock
-   (rename_lock).
-
-2. The name associated with a dentry (d_name) may be changed if a
-   rename is allowed to happen simultaneously. To avoid memcmp() in
-   __d_lookup() go out of bounds due to a rename and false positive
-   comparison, the name comparison is done while holding the
-   per-dentry lock. This prevents concurrent renames during this
-   operation.
-
-3. Hash table walking during look-up may move to a different bucket as
-   the current dentry is moved to a different bucket due to rename.
-   But we use hlists in dcache hash table and they are
-   null-terminated.  So, even if a dentry moves to a different bucket,
-   hash chain walk will terminate. [with a list_head list, it may not
-   since termination is when the list_head in the original bucket is
-   reached].  Since we redo the d_parent check and compare name while
-   holding d_lock, lock-free look-up will not race against d_move().
-
-4. There can be a theoretical race when a dentry keeps coming back to
-   original bucket due to double moves. Due to this look-up may
-   consider that it has never moved and can end up in a infinite loop.
-   But this is not any worse that theoretical livelocks we already
-   have in the kernel.
-
-
-Important guidelines for filesystem developers related to dcache_rcu
-====================================================================
-
-1. Existing dcache interfaces (pre-2.5.62) exported to filesystem
-   don't change. Only dcache internal implementation changes. However
-   filesystems *must not* delete from the dentry hash chains directly
-   using the list macros like allowed earlier. They must use dcache
-   APIs like d_drop() or __d_drop() depending on the situation.
-
-2. d_flags is now protected by a per-dentry lock (d_lock). All access
-   to d_flags must be protected by it.
-
-3. For a hashed dentry, checking of d_count needs to be protected by
-   d_lock.
-
-
-Papers and other documentation on dcache locking
-================================================
-
-1. Scaling dcache with RCU (http://linuxjournal.com/article.php?sid=7124).
-
-2. http://lse.sourceforge.net/locking/dcache/dcache.html
-
-
-
diff -druNp linux-libre-2.6.37-gnu1/Documentation/filesystems/Locking linux-libre-2.6.38-gnu1/Documentation/filesystems/Locking
--- linux-libre-2.6.37-gnu1/Documentation/filesystems/Locking	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/filesystems/Locking	2011-03-14 21:20:32.000000000 -0400
@@ -9,23 +9,30 @@ be able to use diff(1).
 
 --------------------------- dentry_operations --------------------------
 prototypes:
-	int (*d_revalidate)(struct dentry *, int);
-	int (*d_hash) (struct dentry *, struct qstr *);
-	int (*d_compare) (struct dentry *, struct qstr *, struct qstr *);
+	int (*d_revalidate)(struct dentry *, struct nameidata *);
+	int (*d_hash)(const struct dentry *, const struct inode *,
+			struct qstr *);
+	int (*d_compare)(const struct dentry *, const struct inode *,
+			const struct dentry *, const struct inode *,
+			unsigned int, const char *, const struct qstr *);
 	int (*d_delete)(struct dentry *);
 	void (*d_release)(struct dentry *);
 	void (*d_iput)(struct dentry *, struct inode *);
 	char *(*d_dname)((struct dentry *dentry, char *buffer, int buflen);
+	struct vfsmount *(*d_automount)(struct path *path);
+	int (*d_manage)(struct dentry *, bool);
 
 locking rules:
-		dcache_lock	rename_lock	->d_lock	may block
-d_revalidate:	no		no		no		yes
-d_hash		no		no		no		yes
-d_compare:	no		yes		no		no 
-d_delete:	yes		no		yes		no
-d_release:	no		no		no		yes
-d_iput:		no		no		no		yes
+		rename_lock	->d_lock	may block	rcu-walk
+d_revalidate:	no		no		yes (ref-walk)	maybe
+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_iput:		no		no		yes		no
 d_dname:	no		no		no		no
+d_automount:	no		no		yes		no
+d_manage:	no		no		yes (ref-walk)	maybe
 
 --------------------------- inode_operations --------------------------- 
 prototypes:
@@ -44,8 +51,8 @@ ata *);
 	void * (*follow_link) (struct dentry *, struct nameidata *);
 	void (*put_link) (struct dentry *, struct nameidata *, void *);
 	void (*truncate) (struct inode *);
-	int (*permission) (struct inode *, int, struct nameidata *);
-	int (*check_acl)(struct inode *, int);
+	int (*permission) (struct inode *, int, unsigned int);
+	int (*check_acl)(struct inode *, int, unsigned int);
 	int (*setattr) (struct dentry *, struct iattr *);
 	int (*getattr) (struct vfsmount *, struct dentry *, struct kstat *);
 	int (*setxattr) (struct dentry *, const char *,const void *,size_t,int);
@@ -53,7 +60,6 @@ ata *);
 	ssize_t (*listxattr) (struct dentry *, char *, size_t);
 	int (*removexattr) (struct dentry *, const char *);
 	void (*truncate_range)(struct inode *, loff_t, loff_t);
-	long (*fallocate)(struct inode *inode, int mode, loff_t offset, loff_t len);
 	int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start, u64 len);
 
 locking rules:
@@ -73,7 +79,7 @@ follow_link:	no
 put_link:	no
 truncate:	yes		(see below)
 setattr:	yes
-permission:	no
+permission:	no (may not block if called in rcu-walk mode)
 check_acl:	no
 getattr:	no
 setxattr:	yes
@@ -81,7 +87,6 @@ getxattr:	no
 listxattr:	no
 removexattr:	yes
 truncate_range:	yes
-fallocate:	no
 fiemap:		no
 	Additionally, ->rmdir(), ->unlink() and ->rename() have ->i_mutex on
 victim.
@@ -340,7 +345,6 @@ prototypes:
 	int (*fl_grant)(struct file_lock *, struct file_lock *, int);
 	void (*fl_release_private)(struct file_lock *);
 	void (*fl_break)(struct file_lock *); /* break_lease callback */
-	int (*fl_mylease)(struct file_lock *, struct file_lock *);
 	int (*fl_change)(struct file_lock **, int);
 
 locking rules:
@@ -350,7 +354,6 @@ fl_notify:		yes		no
 fl_grant:		no		no
 fl_release_private:	maybe		no
 fl_break:		yes		no
-fl_mylease:		yes		no
 fl_change		yes		no
 
 --------------------------- buffer_head -----------------------------------
@@ -432,6 +435,7 @@ prototypes:
 	ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *,
 			size_t, unsigned int);
 	int (*setlease)(struct file *, long, struct file_lock **);
+	long (*fallocate)(struct file *, int, loff_t, loff_t);
 };
 
 locking rules:
diff -druNp linux-libre-2.6.37-gnu1/Documentation/filesystems/ntfs.txt linux-libre-2.6.38-gnu1/Documentation/filesystems/ntfs.txt
--- linux-libre-2.6.37-gnu1/Documentation/filesystems/ntfs.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/filesystems/ntfs.txt	2011-03-14 21:20:32.000000000 -0400
@@ -457,6 +457,11 @@ ChangeLog
 
 Note, a technical ChangeLog aimed at kernel hackers is in fs/ntfs/ChangeLog.
 
+2.1.30:
+	- Fix writev() (it kept writing the first segment over and over again
+	  instead of moving onto subsequent segments).
+	- Fix crash in ntfs_mft_record_alloc() when mapping the new extent mft
+	  record failed.
 2.1.29:
 	- Fix a deadlock when mounting read-write.
 2.1.28:
diff -druNp linux-libre-2.6.37-gnu1/Documentation/filesystems/path-lookup.txt linux-libre-2.6.38-gnu1/Documentation/filesystems/path-lookup.txt
--- linux-libre-2.6.37-gnu1/Documentation/filesystems/path-lookup.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/filesystems/path-lookup.txt	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,382 @@
+Path walking and name lookup locking
+====================================
+
+Path resolution is the finding a dentry corresponding to a path name string, by
+performing a path walk. Typically, for every open(), stat() etc., the path name
+will be resolved. Paths are resolved by walking the namespace tree, starting
+with the first component of the pathname (eg. root or cwd) with a known dentry,
+then finding the child of that dentry, which is named the next component in the
+path string. Then repeating the lookup from the child dentry and finding its
+child with the next element, and so on.
+
+Since it is a frequent operation for workloads like multiuser environments and
+web servers, it is important to optimize this code.
+
+Path walking synchronisation history:
+Prior to 2.5.10, dcache_lock was acquired in d_lookup (dcache hash lookup) and
+thus in every component during path look-up. Since 2.5.10 onwards, fast-walk
+algorithm changed this by holding the dcache_lock at the beginning and walking
+as many cached path component dentries as possible. This significantly
+decreases the number of acquisition of dcache_lock. However it also increases
+the lock hold time significantly and affects performance in large SMP machines.
+Since 2.5.62 kernel, dcache has been using a new locking model that uses RCU to
+make dcache look-up lock-free.
+
+All the above algorithms required taking a lock and reference count on the
+dentry that was looked up, so that may be used as the basis for walking the
+next path element. This is inefficient and unscalable. It is inefficient
+because of the locks and atomic operations required for every dentry element
+slows things down. It is not scalable because many parallel applications that
+are path-walk intensive tend to do path lookups starting from a common dentry
+(usually, the root "/" or current working directory). So contention on these
+common path elements causes lock and cacheline queueing.
+
+Since 2.6.38, RCU is used to make a significant part of the entire path walk
+(including dcache look-up) completely "store-free" (so, no locks, atomics, or
+even stores into cachelines of common dentries). This is known as "rcu-walk"
+path walking.
+
+Path walking overview
+=====================
+
+A name string specifies a start (root directory, cwd, fd-relative) and a
+sequence of elements (directory entry names), which together refer to a path in
+the namespace. A path is represented as a (dentry, vfsmount) tuple. The name
+elements are sub-strings, seperated by '/'.
+
+Name lookups will want to find a particular path that a name string refers to
+(usually the final element, or parent of final element). This is done by taking
+the path given by the name's starting point (which we know in advance -- eg.
+current->fs->cwd or current->fs->root) as the first parent of the lookup. Then
+iteratively for each subsequent name element, look up the child of the current
+parent with the given name and if it is not the desired entry, make it the
+parent for the next lookup.
+
+A parent, of course, must be a directory, and we must have appropriate
+permissions on the parent inode to be able to walk into it.
+
+Turning the child into a parent for the next lookup requires more checks and
+procedures. Symlinks essentially substitute the symlink name for the target
+name in the name string, and require some recursive path walking.  Mount points
+must be followed into (thus changing the vfsmount that subsequent path elements
+refer to), switching from the mount point path to the root of the particular
+mounted vfsmount. These behaviours are variously modified depending on the
+exact path walking flags.
+
+Path walking then must, broadly, do several particular things:
+- find the start point of the walk;
+- perform permissions and validity checks on inodes;
+- perform dcache hash name lookups on (parent, name element) tuples;
+- traverse mount points;
+- traverse symlinks;
+- lookup and create missing parts of the path on demand.
+
+Safe store-free look-up of dcache hash table
+============================================
+
+Dcache name lookup
+------------------
+In order to lookup a dcache (parent, name) tuple, we take a hash on the tuple
+and use that to select a bucket in the dcache-hash table. The list of entries
+in that bucket is then walked, and we do a full comparison of each entry
+against our (parent, name) tuple.
+
+The hash lists are RCU protected, so list walking is not serialised with
+concurrent updates (insertion, deletion from the hash). This is a standard RCU
+list application with the exception of renames, which will be covered below.
+
+Parent and name members of a dentry, as well as its membership in the dcache
+hash, and its inode are protected by the per-dentry d_lock spinlock. A
+reference is taken on the dentry (while the fields are verified under d_lock),
+and this stabilises its d_inode pointer and actual inode. This gives a stable
+point to perform the next step of our path walk against.
+
+These members are also protected by d_seq seqlock, although this offers
+read-only protection and no durability of results, so care must be taken when
+using d_seq for synchronisation (see seqcount based lookups, below).
+
+Renames
+-------
+Back to the rename case. In usual RCU protected lists, the only operations that
+will happen to an object is insertion, and then eventually removal from the
+list. The object will not be reused until an RCU grace period is complete.
+This ensures the RCU list traversal primitives can run over the object without
+problems (see RCU documentation for how this works).
+
+However when a dentry is renamed, its hash value can change, requiring it to be
+moved to a new hash list. Allocating and inserting a new alias would be
+expensive and also problematic for directory dentries. Latency would be far to
+high to wait for a grace period after removing the dentry and before inserting
+it in the new hash bucket. So what is done is to insert the dentry into the
+new list immediately.
+
+However, when the dentry's list pointers are updated to point to objects in the
+new list before waiting for a grace period, this can result in a concurrent RCU
+lookup of the old list veering off into the new (incorrect) list and missing
+the remaining dentries on the list.
+
+There is no fundamental problem with walking down the wrong list, because the
+dentry comparisons will never match. However it is fatal to miss a matching
+dentry. So a seqlock is used to detect when a rename has occurred, and so the
+lookup can be retried.
+
+         1      2      3
+        +---+  +---+  +---+
+hlist-->| N-+->| N-+->| N-+->
+head <--+-P |<-+-P |<-+-P |
+        +---+  +---+  +---+
+
+Rename of dentry 2 may require it deleted from the above list, and inserted
+into a new list. Deleting 2 gives the following list.
+
+         1             3
+        +---+         +---+     (don't worry, the longer pointers do not
+hlist-->| N-+-------->| N-+->    impose a measurable performance overhead
+head <--+-P |<--------+-P |      on modern CPUs)
+        +---+         +---+
+          ^      2      ^
+          |    +---+    |
+          |    | N-+----+
+          +----+-P |
+               +---+
+
+This is a standard RCU-list deletion, which leaves the deleted object's
+pointers intact, so a concurrent list walker that is currently looking at
+object 2 will correctly continue to object 3 when it is time to traverse the
+next object.
+
+However, when inserting object 2 onto a new list, we end up with this:
+
+         1             3
+        +---+         +---+
+hlist-->| N-+-------->| N-+->
+head <--+-P |<--------+-P |
+        +---+         +---+
+                 2
+               +---+
+               | N-+---->
+          <----+-P |
+               +---+
+
+Because we didn't wait for a grace period, there may be a concurrent lookup
+still at 2. Now when it follows 2's 'next' pointer, it will walk off into
+another list without ever having checked object 3.
+
+A related, but distinctly different, issue is that of rename atomicity versus
+lookup operations. If a file is renamed from 'A' to 'B', a lookup must only
+find either 'A' or 'B'. So if a lookup of 'A' returns NULL, a subsequent lookup
+of 'B' must succeed (note the reverse is not true).
+
+Between deleting the dentry from the old hash list, and inserting it on the new
+hash list, a lookup may find neither 'A' nor 'B' matching the dentry. The same
+rename seqlock is also used to cover this race in much the same way, by
+retrying a negative lookup result if a rename was in progress.
+
+Seqcount based lookups
+----------------------
+In refcount based dcache lookups, d_lock is used to serialise access to
+the dentry, stabilising it while comparing its name and parent and then
+taking a reference count (the reference count then gives a stable place to
+start the next part of the path walk from).
+
+As explained above, we would like to do path walking without taking locks or
+reference counts on intermediate dentries along the path. To do this, a per
+dentry seqlock (d_seq) is used to take a "coherent snapshot" of what the dentry
+looks like (its name, parent, and inode). That snapshot is then used to start
+the next part of the path walk. When loading the coherent snapshot under d_seq,
+care must be taken to load the members up-front, and use those pointers rather
+than reloading from the dentry later on (otherwise we'd have interesting things
+like d_inode going NULL underneath us, if the name was unlinked).
+
+Also important is to avoid performing any destructive operations (pretty much:
+no non-atomic stores to shared data), and to recheck the seqcount when we are
+"done" with the operation. Retry or abort if the seqcount does not match.
+Avoiding destructive or changing operations means we can easily unwind from
+failure.
+
+What this means is that a caller, provided they are holding RCU lock to
+protect the dentry object from disappearing, can perform a seqcount based
+lookup which does not increment the refcount on the dentry or write to
+it in any way. This returned dentry can be used for subsequent operations,
+provided that d_seq is rechecked after that operation is complete.
+
+Inodes are also rcu freed, so the seqcount lookup dentry's inode may also be
+queried for permissions.
+
+With this two parts of the puzzle, we can do path lookups without taking
+locks or refcounts on dentry elements.
+
+RCU-walk path walking design
+============================
+
+Path walking code now has two distinct modes, ref-walk and rcu-walk. ref-walk
+is the traditional[*] way of performing dcache lookups using d_lock to
+serialise concurrent modifications to the dentry and take a reference count on
+it. ref-walk is simple and obvious, and may sleep, take locks, etc while path
+walking is operating on each dentry. rcu-walk uses seqcount based dentry
+lookups, and can perform lookup of intermediate elements without any stores to
+shared data in the dentry or inode. rcu-walk can not be applied to all cases,
+eg. if the filesystem must sleep or perform non trivial operations, rcu-walk
+must be switched to ref-walk mode.
+
+[*] RCU is still used for the dentry hash lookup in ref-walk, but not the full
+    path walk.
+
+Where ref-walk uses a stable, refcounted ``parent'' to walk the remaining
+path string, rcu-walk uses a d_seq protected snapshot. When looking up a
+child of this parent snapshot, we open d_seq critical section on the child
+before closing d_seq critical section on the parent. This gives an interlocking
+ladder of snapshots to walk down.
+
+
+     proc 101
+      /----------------\
+     / comm:    "vi"    \
+    /  fs.root: dentry0  \
+    \  fs.cwd:  dentry2  /
+     \                  /
+      \----------------/
+
+So when vi wants to open("/home/npiggin/test.c", O_RDWR), then it will
+start from current->fs->root, which is a pinned dentry. Alternatively,
+"./test.c" would start from cwd; both names refer to the same path in
+the context of proc101.
+
+     dentry 0
+    +---------------------+   rcu-walk begins here, we note d_seq, check the
+    | name:    "/"        |   inode's permission, and then look up the next
+    | inode:   10         |   path element which is "home"...
+    | children:"home", ...|
+    +---------------------+
+              |
+     dentry 1 V
+    +---------------------+   ... which brings us here. We find dentry1 via
+    | name:    "home"     |   hash lookup, then note d_seq and compare name
+    | inode:   678        |   string and parent pointer. When we have a match,
+    | children:"npiggin"  |   we now recheck the d_seq of dentry0. Then we
+    +---------------------+   check inode and look up the next element.
+              |
+     dentry2  V
+    +---------------------+   Note: if dentry0 is now modified, lookup is
+    | name:    "npiggin"  |   not necessarily invalid, so we need only keep a
+    | inode:   543        |   parent for d_seq verification, and grandparents
+    | children:"a.c", ... |   can be forgotten.
+    +---------------------+
+              |
+     dentry3  V
+    +---------------------+   At this point we have our destination dentry.
+    | name:    "a.c"      |   We now take its d_lock, verify d_seq of this
+    | inode:   14221      |   dentry. If that checks out, we can increment
+    | children:NULL       |   its refcount because we're holding d_lock.
+    +---------------------+
+
+Taking a refcount on a dentry from rcu-walk mode, by taking its d_lock,
+re-checking its d_seq, and then incrementing its refcount is called
+"dropping rcu" or dropping from rcu-walk into ref-walk mode.
+
+It is, in some sense, a bit of a house of cards. If the seqcount check of the
+parent snapshot fails, the house comes down, because we had closed the d_seq
+section on the grandparent, so we have nothing left to stand on. In that case,
+the path walk must be fully restarted (which we do in ref-walk mode, to avoid
+live locks). It is costly to have a full restart, but fortunately they are
+quite rare.
+
+When we reach a point where sleeping is required, or a filesystem callout
+requires ref-walk, then instead of restarting the walk, we attempt to drop rcu
+at the last known good dentry we have. Avoiding a full restart in ref-walk in
+these cases is fundamental for performance and scalability because blocking
+operations such as creates and unlinks are not uncommon.
+
+The detailed design for rcu-walk is like this:
+* LOOKUP_RCU is set in nd->flags, which distinguishes rcu-walk from ref-walk.
+* Take the RCU lock for the entire path walk, starting with the acquiring
+  of the starting path (eg. root/cwd/fd-path). So now dentry refcounts are
+  not required for dentry persistence.
+* synchronize_rcu is called when unregistering a filesystem, so we can
+  access d_ops and i_ops during rcu-walk.
+* Similarly take the vfsmount lock for the entire path walk. So now mnt
+  refcounts are not required for persistence. Also we are free to perform mount
+  lookups, and to assume dentry mount points and mount roots are stable up and
+  down the path.
+* Have a per-dentry seqlock to protect the dentry name, parent, and inode,
+  so we can load this tuple atomically, and also check whether any of its
+  members have changed.
+* Dentry lookups (based on parent, candidate string tuple) recheck the parent
+  sequence after the child is found in case anything changed in the parent
+  during the path walk.
+* inode is also RCU protected so we can load d_inode and use the inode for
+  limited things.
+* i_mode, i_uid, i_gid can be tested for exec permissions during path walk.
+* i_op can be loaded.
+* When the destination dentry is reached, drop rcu there (ie. take d_lock,
+  verify d_seq, increment refcount).
+* If seqlock verification fails anywhere along the path, do a full restart
+  of the path lookup in ref-walk mode. -ECHILD tends to be used (for want of
+  a better errno) to signal an rcu-walk failure.
+
+The cases where rcu-walk cannot continue are:
+* NULL dentry (ie. any uncached path element)
+* Following links
+
+It may be possible eventually to make following links rcu-walk aware.
+
+Uncached path elements will always require dropping to ref-walk mode, at the
+very least because i_mutex needs to be grabbed, and objects allocated.
+
+Final note:
+"store-free" path walking is not strictly store free. We take vfsmount lock
+and refcounts (both of which can be made per-cpu), and we also store to the
+stack (which is essentially CPU-local), and we also have to take locks and
+refcount on final dentry.
+
+The point is that shared data, where practically possible, is not locked
+or stored into. The result is massive improvements in performance and
+scalability of path resolution.
+
+
+Interesting statistics
+======================
+
+The following table gives rcu lookup statistics for a few simple workloads
+(2s12c24t Westmere, debian non-graphical system). Ungraceful are attempts to
+drop rcu that fail due to d_seq failure and requiring the entire path lookup
+again. Other cases are successful rcu-drops that are required before the final
+element, nodentry for missing dentry, revalidate for filesystem revalidate
+routine requiring rcu drop, permission for permission check requiring drop,
+and link for symlink traversal requiring drop.
+
+     rcu-lookups     restart  nodentry          link  revalidate  permission
+bootup     47121           0      4624          1010       10283        7852
+dbench  25386793           0   6778659(26.7%)     55         549        1156
+kbuild   2696672          10     64442(2.3%)  108764(4.0%)     1        1590
+git diff   39605           0        28             2           0         106
+vfstest 24185492        4945    708725(2.9%) 1076136(4.4%)     0        2651
+
+What this shows is that failed rcu-walk lookups, ie. ones that are restarted
+entirely with ref-walk, are quite rare. Even the "vfstest" case which
+specifically has concurrent renames/mkdir/rmdir/ creat/unlink/etc to excercise
+such races is not showing a huge amount of restarts.
+
+Dropping from rcu-walk to ref-walk mean that we have encountered a dentry where
+the reference count needs to be taken for some reason. This is either because
+we have reached the target of the path walk, or because we have encountered a
+condition that can't be resolved in rcu-walk mode.  Ideally, we drop rcu-walk
+only when we have reached the target dentry, so the other statistics show where
+this does not happen.
+
+Note that a graceful drop from rcu-walk mode due to something such as the
+dentry not existing (which can be common) is not necessarily a failure of
+rcu-walk scheme, because some elements of the path may have been walked in
+rcu-walk mode. The further we get from common path elements (such as cwd or
+root), the less contended the dentry is likely to be. The closer we are to
+common path elements, the more likely they will exist in dentry cache.
+
+
+Papers and other documentation on dcache locking
+================================================
+
+1. Scaling dcache with RCU (http://linuxjournal.com/article.php?sid=7124).
+
+2. http://lse.sourceforge.net/locking/dcache/dcache.html
+
+
diff -druNp linux-libre-2.6.37-gnu1/Documentation/filesystems/porting linux-libre-2.6.38-gnu1/Documentation/filesystems/porting
--- linux-libre-2.6.37-gnu1/Documentation/filesystems/porting	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/filesystems/porting	2011-03-14 21:20:32.000000000 -0400
@@ -216,7 +216,6 @@ had ->revalidate()) add calls in ->follo
 ->d_parent changes are not protected by BKL anymore.  Read access is safe
 if at least one of the following is true:
 	* filesystem has no cross-directory rename()
-	* dcache_lock is held
 	* we know that parent had been locked (e.g. we are looking at
 ->d_parent of ->lookup() argument).
 	* we are called from ->rename().
@@ -318,3 +317,80 @@ if it's zero is not *and* *never* *had*
 may happen while the inode is in the middle of ->write_inode(); e.g. if you blindly
 free the on-disk inode, you may end up doing that while ->write_inode() is writing
 to it.
+
+---
+[mandatory]
+
+	.d_delete() now only advises the dcache as to whether or not to cache
+unreferenced dentries, and is now only called when the dentry refcount goes to
+0. Even on 0 refcount transition, it must be able to tolerate being called 0,
+1, or more times (eg. constant, idempotent).
+
+---
+[mandatory]
+
+	.d_compare() calling convention and locking rules are significantly
+changed. Read updated documentation in Documentation/filesystems/vfs.txt (and
+look at examples of other filesystems) for guidance.
+
+---
+[mandatory]
+
+	.d_hash() calling convention and locking rules are significantly
+changed. Read updated documentation in Documentation/filesystems/vfs.txt (and
+look at examples of other filesystems) for guidance.
+
+---
+[mandatory]
+	dcache_lock is gone, replaced by fine grained locks. See fs/dcache.c
+for details of what locks to replace dcache_lock with in order to protect
+particular things. Most of the time, a filesystem only needs ->d_lock, which
+protects *all* the dcache state of a given dentry.
+
+--
+[mandatory]
+
+	Filesystems must RCU-free their inodes, if they can have been accessed
+via rcu-walk path walk (basically, if the file can have had a path name in the
+vfs namespace).
+
+	i_dentry and i_rcu share storage in a union, and the vfs expects
+i_dentry to be reinitialized before it is freed, so an:
+
+  INIT_LIST_HEAD(&inode->i_dentry);
+
+must be done in the RCU callback.
+
+--
+[recommended]
+	vfs now tries to do path walking in "rcu-walk mode", which avoids
+atomic operations and scalability hazards on dentries and inodes (see
+Documentation/filesystems/path-lookup.txt). d_hash and d_compare changes
+(above) are examples of the changes required to support this. For more complex
+filesystem callbacks, the vfs drops out of rcu-walk mode before the fs call, so
+no changes are required to the filesystem. However, this is costly and loses
+the benefits of rcu-walk mode. We will begin to add filesystem callbacks that
+are rcu-walk aware, shown below. Filesystems should take advantage of this
+where possible.
+
+--
+[mandatory]
+	d_revalidate is a callback that is made on every path element (if
+the filesystem provides it), which requires dropping out of rcu-walk mode. This
+may now be called in rcu-walk mode (nd->flags & LOOKUP_RCU). -ECHILD should be
+returned if the filesystem cannot handle rcu-walk. See
+Documentation/filesystems/vfs.txt for more details.
+
+	permission and check_acl are inode permission checks that are called
+on many or all directory inodes on the way down a path walk (to check for
+exec permission). These must now be rcu-walk aware (flags & IPERM_FLAG_RCU).
+See Documentation/filesystems/vfs.txt for more details.
+ 
+--
+[mandatory]
+	In ->fallocate() you must check the mode option passed in.  If your
+filesystem does not support hole punching (deallocating space in the middle of a
+file) you must return -EOPNOTSUPP if FALLOC_FL_PUNCH_HOLE is set in mode.
+Currently you can only have FALLOC_FL_PUNCH_HOLE with FALLOC_FL_KEEP_SIZE set,
+so the i_size should not change when hole punching, even when puching the end of
+a file off.
diff -druNp linux-libre-2.6.37-gnu1/Documentation/filesystems/proc.txt linux-libre-2.6.38-gnu1/Documentation/filesystems/proc.txt
--- linux-libre-2.6.37-gnu1/Documentation/filesystems/proc.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/filesystems/proc.txt	2011-03-14 21:20:32.000000000 -0400
@@ -375,6 +375,7 @@ Anonymous:             0 kB
 Swap:                  0 kB
 KernelPageSize:        4 kB
 MMUPageSize:           4 kB
+Locked:              374 kB
 
 The first of these lines shows the same information as is displayed for the
 mapping in /proc/PID/maps.  The remaining lines show the size of the mapping
@@ -670,6 +671,8 @@ varies by architecture and compile optio
 
 > cat /proc/meminfo
 
+The "Locked" indicates whether the mapping is locked in memory or not.
+
 
 MemTotal:     16344972 kB
 MemFree:      13634064 kB
@@ -1181,6 +1184,30 @@ Table 1-12: Files in /proc/fs/ext4/<devn
  mb_groups       details of multiblock allocator buddy cache of free blocks
 ..............................................................................
 
+2.0 /proc/consoles
+------------------
+Shows registered system console lines.
+
+To see which character device lines are currently used for the system console
+/dev/console, you may simply look into the file /proc/consoles:
+
+  > cat /proc/consoles
+  tty0                 -WU (ECp)       4:7
+  ttyS0                -W- (Ep)        4:64
+
+The columns are:
+
+  device               name of the device
+  operations           R = can do read operations
+                       W = can do write operations
+                       U = can do unblank
+  flags                E = it is enabled
+                       C = it is prefered console
+                       B = it is primary boot console
+                       p = it is used for printk buffer
+                       b = it is not a TTY but a Braille device
+                       a = it is safe to use when cpu is offline
+  major:minor          major and minor number of the device separated by a colon
 
 ------------------------------------------------------------------------------
 Summary
@@ -1296,6 +1323,10 @@ scaled linearly with /proc/<pid>/oom_sco
 Writing to /proc/<pid>/oom_score_adj or /proc/<pid>/oom_adj will change the
 other with its scaled value.
 
+The value of /proc/<pid>/oom_score_adj may be reduced no lower than the last
+value set by a CAP_SYS_RESOURCE process. To reduce the value any lower
+requires CAP_SYS_RESOURCE.
+
 NOTICE: /proc/<pid>/oom_adj is deprecated and will be removed, please see
 Documentation/feature-removal-schedule.txt.
 
diff -druNp linux-libre-2.6.37-gnu1/Documentation/filesystems/vfs.txt linux-libre-2.6.38-gnu1/Documentation/filesystems/vfs.txt
--- linux-libre-2.6.37-gnu1/Documentation/filesystems/vfs.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/filesystems/vfs.txt	2011-03-14 21:20:32.000000000 -0400
@@ -325,7 +325,8 @@ struct inode_operations {
         void * (*follow_link) (struct dentry *, struct nameidata *);
         void (*put_link) (struct dentry *, struct nameidata *, void *);
 	void (*truncate) (struct inode *);
-	int (*permission) (struct inode *, int, struct nameidata *);
+	int (*permission) (struct inode *, int, unsigned int);
+	int (*check_acl)(struct inode *, int, unsigned int);
 	int (*setattr) (struct dentry *, struct iattr *);
 	int (*getattr) (struct vfsmount *mnt, struct dentry *, struct kstat *);
 	int (*setxattr) (struct dentry *, const char *,const void *,size_t,int);
@@ -414,6 +415,13 @@ otherwise noted.
   permission: called by the VFS to check for access rights on a POSIX-like
   	filesystem.
 
+	May be called in rcu-walk mode (flags & IPERM_FLAG_RCU). If in rcu-walk
+        mode, the filesystem must check the permission without blocking or
+	storing to the inode.
+
+	If a situation is encountered that rcu-walk cannot handle, return
+	-ECHILD and it will be called again in ref-walk mode.
+
   setattr: called by the VFS to set attributes for a file. This method
   	is called by chmod(2) and related system calls.
 
@@ -847,12 +855,17 @@ defined:
 
 struct dentry_operations {
 	int (*d_revalidate)(struct dentry *, struct nameidata *);
-	int (*d_hash) (struct dentry *, struct qstr *);
-	int (*d_compare) (struct dentry *, struct qstr *, struct qstr *);
-	int (*d_delete)(struct dentry *);
+	int (*d_hash)(const struct dentry *, const struct inode *,
+			struct qstr *);
+	int (*d_compare)(const struct dentry *, const struct inode *,
+			const struct dentry *, const struct inode *,
+			unsigned int, const char *, const struct qstr *);
+	int (*d_delete)(const struct dentry *);
 	void (*d_release)(struct dentry *);
 	void (*d_iput)(struct dentry *, struct inode *);
 	char *(*d_dname)(struct dentry *, char *, int);
+	struct vfsmount *(*d_automount)(struct path *);
+	int (*d_manage)(struct dentry *, bool, bool);
 };
 
   d_revalidate: called when the VFS needs to revalidate a dentry. This
@@ -860,13 +873,45 @@ struct dentry_operations {
 	dcache. Most filesystems leave this as NULL, because all their
 	dentries in the dcache are valid
 
-  d_hash: called when the VFS adds a dentry to the hash table
+	d_revalidate may be called in rcu-walk mode (nd->flags & LOOKUP_RCU).
+	If in rcu-walk mode, the filesystem must revalidate the dentry without
+	blocking or storing to the dentry, d_parent and d_inode should not be
+	used without care (because they can go NULL), instead nd->inode should
+	be used.
 
-  d_compare: called when a dentry should be compared with another
+	If a situation is encountered that rcu-walk cannot handle, return
+	-ECHILD and it will be called again in ref-walk mode.
 
-  d_delete: called when the last reference to a dentry is
-	deleted. This means no-one is using the dentry, however it is
-	still valid and in the dcache
+  d_hash: called when the VFS adds a dentry to the hash table. The first
+	dentry passed to d_hash is the parent directory that the name is
+	to be hashed into. The inode is the dentry's inode.
+
+	Same locking and synchronisation rules as d_compare regarding
+	what is safe to dereference etc.
+
+  d_compare: called to compare a dentry name with a given name. The first
+	dentry is the parent of the dentry to be compared, the second is
+	the parent's inode, then the dentry and inode (may be NULL) of the
+	child dentry. len and name string are properties of the dentry to be
+	compared. qstr is the name to compare it with.
+
+	Must be constant and idempotent, and should not take locks if
+	possible, and should not or store into the dentry or inodes.
+	Should not dereference pointers outside the dentry or inodes without
+	lots of care (eg.  d_parent, d_inode, d_name should not be used).
+
+	However, our vfsmount is pinned, and RCU held, so the dentries and
+	inodes won't disappear, neither will our sb or filesystem module.
+	->i_sb and ->d_sb may be used.
+
+	It is a tricky calling convention because it needs to be called under
+	"rcu-walk", ie. without any locks or references on things.
+
+  d_delete: called when the last reference to a dentry is dropped and the
+	dcache is deciding whether or not to cache it. Return 1 to delete
+	immediately, or 0 to cache the dentry. Default is NULL which means to
+	always cache a reachable dentry. d_delete must be constant and
+	idempotent.
 
   d_release: called when a dentry is really deallocated
 
@@ -887,6 +932,47 @@ struct dentry_operations {
 	at the end of the buffer, and returns a pointer to the first char.
 	dynamic_dname() helper function is provided to take care of this.
 
+  d_automount: called when an automount dentry is to be traversed (optional).
+	This should create a new VFS mount record and return the record to the
+	caller.  The caller is supplied with a path parameter giving the
+	automount directory to describe the automount target and the parent
+	VFS mount record to provide inheritable mount parameters.  NULL should
+	be returned if someone else managed to make the automount first.  If
+	the vfsmount creation failed, then an error code should be returned.
+	If -EISDIR is returned, then the directory will be treated as an
+	ordinary directory and returned to pathwalk to continue walking.
+
+	If a vfsmount is returned, the caller will attempt to mount it on the
+	mountpoint and will remove the vfsmount from its expiration list in
+	the case of failure.  The vfsmount should be returned with 2 refs on
+	it to prevent automatic expiration - the caller will clean up the
+	additional ref.
+
+	This function is only used if DCACHE_NEED_AUTOMOUNT is set on the
+	dentry.  This is set by __d_instantiate() if S_AUTOMOUNT is set on the
+	inode being added.
+
+  d_manage: called to allow the filesystem to manage the transition from a
+	dentry (optional).  This allows autofs, for example, to hold up clients
+	waiting to explore behind a 'mountpoint' whilst letting the daemon go
+	past and construct the subtree there.  0 should be returned to let the
+	calling process continue.  -EISDIR can be returned to tell pathwalk to
+	use this directory as an ordinary directory and to ignore anything
+	mounted on it and not to check the automount flag.  Any other error
+	code will abort pathwalk completely.
+
+	If the 'mounting_here' parameter is true, then namespace_sem is being
+	held by the caller and the function should not initiate any mounts or
+	unmounts that it will then wait for.
+
+	If the 'rcu_walk' parameter is true, then the caller is doing a
+	pathwalk in RCU-walk mode.  Sleeping is not permitted in this mode,
+	and the caller can be asked to leave it and call again by returing
+	-ECHILD.
+
+	This function is only used if DCACHE_MANAGE_TRANSIT is set on the
+	dentry being transited from.
+
 Example :
 
 static char *pipefs_dname(struct dentry *dent, char *buffer, int buflen)
@@ -910,14 +996,11 @@ manipulate dentries:
 	the usage count)
 
   dput: close a handle for a dentry (decrements the usage count). If
-	the usage count drops to 0, the "d_delete" method is called
-	and the dentry is placed on the unused list if the dentry is
-	still in its parents hash list. Putting the dentry on the
-	unused list just means that if the system needs some RAM, it
-	goes through the unused list of dentries and deallocates them.
-	If the dentry has already been unhashed and the usage count
-	drops to 0, in this case the dentry is deallocated after the
-	"d_delete" method is called
+	the usage count drops to 0, and the dentry is still in its
+	parent's hash, the "d_delete" method is called to check whether
+	it should be cached. If it should not be cached, or if the dentry
+	is not hashed, it is deleted. Otherwise cached dentries are put
+	into an LRU list to be reclaimed on memory shortage.
 
   d_drop: this unhashes a dentry from its parents hash list. A
 	subsequent call to dput() will deallocate the dentry if its
diff -druNp linux-libre-2.6.37-gnu1/Documentation/hwmon/adm9240 linux-libre-2.6.38-gnu1/Documentation/hwmon/adm9240
--- linux-libre-2.6.37-gnu1/Documentation/hwmon/adm9240	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/hwmon/adm9240	2011-03-14 21:20:32.000000000 -0400
@@ -155,7 +155,7 @@ connected to a normally open switch.
 The ADM9240 provides an internal open drain on this line, and may output
 a 20 ms active low pulse to reset an external Chassis Intrusion latch.
 
-Clear the CI latch by writing value 1 to the sysfs chassis_clear file.
+Clear the CI latch by writing value 0 to the sysfs intrusion0_alarm file.
 
 Alarm flags reported as 16-bit word
 
diff -druNp linux-libre-2.6.37-gnu1/Documentation/hwmon/ads7828 linux-libre-2.6.38-gnu1/Documentation/hwmon/ads7828
--- linux-libre-2.6.37-gnu1/Documentation/hwmon/ads7828	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/hwmon/ads7828	2011-03-14 21:20:32.000000000 -0400
@@ -9,7 +9,7 @@ Supported chips:
                http://focus.ti.com/lit/ds/symlink/ads7828.pdf
 
 Authors:
-        Steve Hardy <steve@linuxrealtime.co.uk>
+        Steve Hardy <shardy@redhat.com>
 
 Module Parameters
 -----------------
diff -druNp linux-libre-2.6.37-gnu1/Documentation/hwmon/dme1737 linux-libre-2.6.38-gnu1/Documentation/hwmon/dme1737
--- linux-libre-2.6.37-gnu1/Documentation/hwmon/dme1737	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/hwmon/dme1737	2011-03-14 21:20:32.000000000 -0400
@@ -42,7 +42,7 @@ Description
 This driver implements support for the hardware monitoring capabilities of the
 SMSC DME1737 and Asus A8000 (which are the same), SMSC SCH5027, SCH311x,
 and SCH5127 Super-I/O chips. These chips feature monitoring of 3 temp sensors
-temp[1-3] (2 remote diodes and 1 internal), 7 voltages in[0-6] (6 external and
+temp[1-3] (2 remote diodes and 1 internal), 8 voltages in[0-7] (7 external and
 1 internal) and up to 6 fan speeds fan[1-6]. Additionally, the chips implement
 up to 5 PWM outputs pwm[1-3,5-6] for controlling fan speeds both manually and
 automatically.
@@ -105,6 +105,7 @@ SCH5127:
 	in4: V1_IN				0V - 1.5V
 	in5: VTR	(+3.3V standby)		0V - 4.38V
 	in6: Vbat	(+3.0V)			0V - 4.38V
+	in7: Vtrip	(+1.5V)			0V - 1.99V
 
 Each voltage input has associated min and max limits which trigger an alarm
 when crossed.
@@ -217,10 +218,10 @@ cpu0_vid			RO	CPU core reference voltage
 vrm				RW	Voltage regulator module version
 					number.
 
-in[0-6]_input			RO	Measured voltage in millivolts.
-in[0-6]_min			RW	Low limit for voltage input.
-in[0-6]_max			RW	High limit for voltage input.
-in[0-6]_alarm			RO	Voltage input alarm. Returns 1 if
+in[0-7]_input			RO	Measured voltage in millivolts.
+in[0-7]_min			RW	Low limit for voltage input.
+in[0-7]_max			RW	High limit for voltage input.
+in[0-7]_alarm			RO	Voltage input alarm. Returns 1 if
 					voltage input is or went outside the
 					associated min-max range, 0 otherwise.
 
@@ -324,3 +325,4 @@ fan5			opt		opt
 pwm5			opt		opt
 fan6			opt		opt
 pwm6			opt		opt
+in7						yes
diff -druNp linux-libre-2.6.37-gnu1/Documentation/hwmon/ds620 linux-libre-2.6.38-gnu1/Documentation/hwmon/ds620
--- linux-libre-2.6.37-gnu1/Documentation/hwmon/ds620	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/hwmon/ds620	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,34 @@
+Kernel driver ds620
+===================
+
+Supported chips:
+  * Dallas Semiconductor DS620
+    Prefix: 'ds620'
+    Datasheet: Publicly available at the Dallas Semiconductor website
+               http://www.dalsemi.com/
+
+Authors:
+        Roland Stigge <stigge@antcom.de>
+        based on ds1621.c by
+        Christian W. Zuckschwerdt <zany@triq.net>
+
+Description
+-----------
+
+The DS620 is a (one instance) digital thermometer and thermostat. It has both
+high and low temperature limits which can be user defined (i.e.  programmed
+into non-volatile on-chip registers). Temperature range is -55 degree Celsius
+to +125. Between 0 and 70 degree Celsius, accuracy is 0.5 Kelvin. The value
+returned via sysfs displays post decimal positions.
+
+The thermostat function works as follows: When configured via platform_data
+(struct ds620_platform_data) .pomode == 0 (default), the thermostat output pin
+PO is always low. If .pomode == 1, the thermostat is in PO_LOW mode. I.e., the
+output pin PO becomes active when the temperature falls below temp1_min and
+stays active until the temperature goes above temp1_max.
+
+Likewise, with .pomode == 2, the thermostat is in PO_HIGH mode. I.e., the PO
+output pin becomes active when the temperature goes above temp1_max and stays
+active until the temperature falls below temp1_min.
+
+The PO output pin of the DS620 operates active-low.
diff -druNp linux-libre-2.6.37-gnu1/Documentation/hwmon/jc42 linux-libre-2.6.38-gnu1/Documentation/hwmon/jc42
--- linux-libre-2.6.37-gnu1/Documentation/hwmon/jc42	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/hwmon/jc42	2011-03-14 21:20:32.000000000 -0400
@@ -51,7 +51,8 @@ Supported chips:
   * JEDEC JC 42.4 compliant temperature sensor chips
     Prefix: 'jc42'
     Addresses scanned: I2C 0x18 - 0x1f
-    Datasheet: -
+    Datasheet:
+	http://www.jedec.org/sites/default/files/docs/4_01_04R19.pdf
 
 Author:
 	Guenter Roeck <guenter.roeck@ericsson.com>
@@ -60,7 +61,11 @@ Author:
 Description
 -----------
 
-This driver implements support for JEDEC JC 42.4 compliant temperature sensors.
+This driver implements support for JEDEC JC 42.4 compliant temperature sensors,
+which are used on many DDR3 memory modules for mobile devices and servers. Some
+systems use the sensor to prevent memory overheating by automatically throttling
+the memory controller.
+
 The driver auto-detects the chips listed above, but can be manually instantiated
 to support other JC 42.4 compliant chips.
 
@@ -81,15 +86,19 @@ limits. The chip supports only a single
 which applies to all limits. This register can be written by writing into
 temp1_crit_hyst. Other hysteresis attributes are read-only.
 
+If the BIOS has configured the sensor for automatic temperature management, it
+is likely that it has locked the registers, i.e., that the temperature limits
+cannot be changed.
+
 Sysfs entries
 -------------
 
 temp1_input		Temperature (RO)
-temp1_min		Minimum temperature (RW)
-temp1_max		Maximum temperature (RW)
-temp1_crit		Critical high temperature (RW)
+temp1_min		Minimum temperature (RO or RW)
+temp1_max		Maximum temperature (RO or RW)
+temp1_crit		Critical high temperature (RO or RW)
 
-temp1_crit_hyst		Critical hysteresis temperature (RW)
+temp1_crit_hyst		Critical hysteresis temperature (RO or RW)
 temp1_max_hyst		Maximum hysteresis temperature (RO)
 
 temp1_min_alarm		Temperature low alarm
diff -druNp linux-libre-2.6.37-gnu1/Documentation/hwmon/k10temp linux-libre-2.6.38-gnu1/Documentation/hwmon/k10temp
--- linux-libre-2.6.37-gnu1/Documentation/hwmon/k10temp	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/hwmon/k10temp	2011-03-14 21:20:32.000000000 -0400
@@ -9,6 +9,8 @@ Supported chips:
   Socket S1G3: Athlon II, Sempron, Turion II
 * AMD Family 11h processors:
   Socket S1G2: Athlon (X2), Sempron (X2), Turion X2 (Ultra)
+* AMD Family 12h processors: "Llano"
+* AMD Family 14h processors: "Brazos" (C/E/G-Series)
 
   Prefix: 'k10temp'
   Addresses scanned: PCI space
@@ -17,10 +19,14 @@ Supported chips:
     http://support.amd.com/us/Processor_TechDocs/31116.pdf
   BIOS and Kernel Developer's Guide (BKDG) for AMD Family 11h Processors:
     http://support.amd.com/us/Processor_TechDocs/41256.pdf
+  BIOS and Kernel Developer's Guide (BKDG) for AMD Family 14h Models 00h-0Fh Processors:
+    http://support.amd.com/us/Processor_TechDocs/43170.pdf
   Revision Guide for AMD Family 10h Processors:
     http://support.amd.com/us/Processor_TechDocs/41322.pdf
   Revision Guide for AMD Family 11h Processors:
     http://support.amd.com/us/Processor_TechDocs/41788.pdf
+  Revision Guide for AMD Family 14h Models 00h-0Fh Processors:
+    http://support.amd.com/us/Processor_TechDocs/47534.pdf
   AMD Family 11h Processor Power and Thermal Data Sheet for Notebooks:
     http://support.amd.com/us/Processor_TechDocs/43373.pdf
   AMD Family 10h Server and Workstation Processor Power and Thermal Data Sheet:
@@ -34,7 +40,7 @@ Description
 -----------
 
 This driver permits reading of the internal temperature sensor of AMD
-Family 10h and 11h processors.
+Family 10h/11h/12h/14h processors.
 
 All these processors have a sensor, but on those for Socket F or AM2+,
 the sensor may return inconsistent values (erratum 319).  The driver
diff -druNp linux-libre-2.6.37-gnu1/Documentation/hwmon/lm93 linux-libre-2.6.38-gnu1/Documentation/hwmon/lm93
--- linux-libre-2.6.37-gnu1/Documentation/hwmon/lm93	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/hwmon/lm93	2011-03-14 21:20:32.000000000 -0400
@@ -6,6 +6,10 @@ Supported chips:
     Prefix 'lm93'
     Addresses scanned: I2C 0x2c-0x2e
     Datasheet: http://www.national.com/ds.cgi/LM/LM93.pdf
+  * National Semiconductor LM94
+    Prefix 'lm94'
+    Addresses scanned: I2C 0x2c-0x2e
+    Datasheet: http://www.national.com/ds.cgi/LM/LM94.pdf
 
 Authors:
 	Mark M. Hoffman <mhoffman@lightlink.com>
@@ -56,6 +60,9 @@ previous motherboard management ASICs an
 for dynamic Vccp monitoring and PROCHOT. It is designed to monitor a dual
 processor Xeon class motherboard with a minimum of external components.
 
+LM94 is also supported in LM93 compatible mode. Extra sensors and features of
+LM94 are not supported.
+
 
 User Interface
 --------------
diff -druNp linux-libre-2.6.37-gnu1/Documentation/hwmon/sht21 linux-libre-2.6.38-gnu1/Documentation/hwmon/sht21
--- linux-libre-2.6.37-gnu1/Documentation/hwmon/sht21	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/hwmon/sht21	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,49 @@
+Kernel driver sht21
+===================
+
+Supported chips:
+  * Sensirion SHT21
+    Prefix: 'sht21'
+    Addresses scanned: none
+    Datasheet: Publicly available at the Sensirion website
+    http://www.sensirion.com/en/pdf/product_information/Datasheet-humidity-sensor-SHT21.pdf
+
+  * Sensirion SHT25
+    Prefix: 'sht21'
+    Addresses scanned: none
+    Datasheet: Publicly available at the Sensirion website
+    http://www.sensirion.com/en/pdf/product_information/Datasheet-humidity-sensor-SHT25.pdf
+
+Author:
+  Urs Fleisch <urs.fleisch@sensirion.com>
+
+Description
+-----------
+
+The SHT21 and SHT25 are humidity and temperature sensors in a DFN package of
+only 3 x 3 mm footprint and 1.1 mm height. The difference between the two
+devices is the higher level of precision of the SHT25 (1.8% relative humidity,
+0.2 degree Celsius) compared with the SHT21 (2.0% relative humidity,
+0.3 degree Celsius).
+
+The devices communicate with the I2C protocol. All sensors are set to the same
+I2C address 0x40, so an entry with I2C_BOARD_INFO("sht21", 0x40) can be used
+in the board setup code.
+
+sysfs-Interface
+---------------
+
+temp1_input - temperature input
+humidity1_input - humidity input
+
+Notes
+-----
+
+The driver uses the default resolution settings of 12 bit for humidity and 14
+bit for temperature, which results in typical measurement times of 22 ms for
+humidity and 66 ms for temperature. To keep self heating below 0.1 degree
+Celsius, the device should not be active for more than 10% of the time,
+e.g. maximum two measurements per second at the given resolution.
+
+Different resolutions, the on-chip heater, using the CRC checksum and reading
+the serial number are not supported yet.
diff -druNp linux-libre-2.6.37-gnu1/Documentation/hwmon/sysfs-interface linux-libre-2.6.38-gnu1/Documentation/hwmon/sysfs-interface
--- linux-libre-2.6.37-gnu1/Documentation/hwmon/sysfs-interface	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/hwmon/sysfs-interface	2011-03-14 21:20:32.000000000 -0400
@@ -384,10 +384,20 @@ curr[1-*]_min	Current min value.
 		Unit: milliampere
 		RW
 
+curr[1-*]_lcrit	Current critical low value
+		Unit: milliampere
+		RW
+
+curr[1-*]_crit	Current critical high value.
+		Unit: milliampere
+		RW
+
 curr[1-*]_input	Current input value
 		Unit: milliampere
 		RO
 
+Also see the Alarms section for status flags associated with currents.
+
 *********
 * Power *
 *********
@@ -450,13 +460,6 @@ power[1-*]_accuracy		Accuracy of the pow
 				Unit: Percent
 				RO
 
-power[1-*]_alarm		1 if the system is drawing more power than the
-				cap allows; 0 otherwise.  A poll notification is
-				sent to this file when the power use exceeds the
-				cap.  This file only appears if the cap is known
-				to be enforced by hardware.
-				RO
-
 power[1-*]_cap			If power use rises above this limit, the
 				system should take action to reduce power use.
 				A poll notification is sent to this file if the
@@ -479,6 +482,20 @@ power[1-*]_cap_min		Minimum cap that can
 				Unit: microWatt
 				RO
 
+power[1-*]_max			Maximum power.
+				Unit: microWatt
+				RW
+
+power[1-*]_crit			Critical maximum power.
+				If power rises to or above this limit, the
+				system is expected take drastic action to reduce
+				power consumption, such as a system shutdown or
+				a forced powerdown of some devices.
+				Unit: microWatt
+				RW
+
+Also see the Alarms section for status flags associated with power readings.
+
 **********
 * Energy *
 **********
@@ -488,6 +505,15 @@ energy[1-*]_input		Cumulative energy use
 				RO
 
 
+************
+* Humidity *
+************
+
+humidity[1-*]_input		Humidity
+				Unit: milli-percent (per cent mille, pcm)
+				RO
+
+
 **********
 * Alarms *
 **********
@@ -501,6 +527,7 @@ implementation.
 
 in[0-*]_alarm
 curr[1-*]_alarm
+power[1-*]_alarm
 fan[1-*]_alarm
 temp[1-*]_alarm
 		Channel alarm
@@ -512,12 +539,20 @@ OR
 
 in[0-*]_min_alarm
 in[0-*]_max_alarm
+in[0-*]_lcrit_alarm
+in[0-*]_crit_alarm
 curr[1-*]_min_alarm
 curr[1-*]_max_alarm
+curr[1-*]_lcrit_alarm
+curr[1-*]_crit_alarm
+power[1-*]_cap_alarm
+power[1-*]_max_alarm
+power[1-*]_crit_alarm
 fan[1-*]_min_alarm
 fan[1-*]_max_alarm
 temp[1-*]_min_alarm
 temp[1-*]_max_alarm
+temp[1-*]_lcrit_alarm
 temp[1-*]_crit_alarm
 temp[1-*]_emergency_alarm
 		Limit alarm
diff -druNp linux-libre-2.6.37-gnu1/Documentation/hwmon/w83627hf linux-libre-2.6.38-gnu1/Documentation/hwmon/w83627hf
--- linux-libre-2.6.37-gnu1/Documentation/hwmon/w83627hf	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/hwmon/w83627hf	2011-03-14 21:20:32.000000000 -0400
@@ -91,3 +91,25 @@ isaset -y -f 0x2e 0xaa
 
 The above sequence assumes a Super-I/O config space at 0x2e/0x2f, but
 0x4e/0x4f is also possible.
+
+Voltage pin mapping
+-------------------
+
+Here is a summary of the voltage pin mapping for the W83627THF. This
+can be useful to convert data provided by board manufacturers into
+working libsensors configuration statements.
+
+    W83627THF		|
+  Pin	| Name		| Register	| Sysfs attribute
+-----------------------------------------------------
+  100	| CPUVCORE	| 20h		| in0
+   99	| VIN0		| 21h		| in1
+   98	| VIN1		| 22h		| in2
+   97	| VIN2		| 24h		| in4
+  114	| AVCC		| 23h		| in3
+   61	| 5VSB		| 50h (bank 5)	| in7
+   74	| VBAT		| 51h (bank 5)	| in8
+
+For other supported devices, you'll have to take the hard path and
+look up the information in the datasheet yourself (and then add it
+to this document please.)
diff -druNp linux-libre-2.6.37-gnu1/Documentation/hwmon/w83793 linux-libre-2.6.38-gnu1/Documentation/hwmon/w83793
--- linux-libre-2.6.37-gnu1/Documentation/hwmon/w83793	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/hwmon/w83793	2011-03-14 21:20:32.000000000 -0400
@@ -92,7 +92,7 @@ This driver implements support for Winbo
 
 * Chassis
   If the case open alarm triggers, it will stay in this state unless cleared
-  by any write to the sysfs file "chassis".
+  by writing 0 to the sysfs file "intrusion0_alarm".
 
 * VID and VRM
   The VRM version is detected automatically, don't modify the it unless you
diff -druNp linux-libre-2.6.37-gnu1/Documentation/i2c/muxes/gpio-i2cmux linux-libre-2.6.38-gnu1/Documentation/i2c/muxes/gpio-i2cmux
--- linux-libre-2.6.37-gnu1/Documentation/i2c/muxes/gpio-i2cmux	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/i2c/muxes/gpio-i2cmux	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,65 @@
+Kernel driver gpio-i2cmux
+
+Author: Peter Korsgaard <peter.korsgaard@barco.com>
+
+Description
+-----------
+
+gpio-i2cmux is an i2c mux driver providing access to I2C bus segments
+from a master I2C bus and a hardware MUX controlled through GPIO pins.
+
+E.G.:
+
+  ----------              ----------  Bus segment 1   - - - - -
+ |          | SCL/SDA    |          |-------------- |           |
+ |          |------------|          |
+ |          |            |          | Bus segment 2 |           |
+ |  Linux   | GPIO 1..N  |   MUX    |---------------   Devices
+ |          |------------|          |               |           |
+ |          |            |          | Bus segment M
+ |          |            |          |---------------|           |
+  ----------              ----------                  - - - - -
+
+SCL/SDA of the master I2C bus is multiplexed to bus segment 1..M
+according to the settings of the GPIO pins 1..N.
+
+Usage
+-----
+
+gpio-i2cmux uses the platform bus, so you need to provide a struct
+platform_device with the platform_data pointing to a struct
+gpio_i2cmux_platform_data with the I2C adapter number of the master
+bus, the number of bus segments to create and the GPIO pins used
+to control it. See include/linux/gpio-i2cmux.h for details.
+
+E.G. something like this for a MUX providing 4 bus segments
+controlled through 3 GPIO pins:
+
+#include <linux/gpio-i2cmux.h>
+#include <linux/platform_device.h>
+
+static const unsigned myboard_gpiomux_gpios[] = {
+	AT91_PIN_PC26, AT91_PIN_PC25, AT91_PIN_PC24
+};
+
+static const unsigned myboard_gpiomux_values[] = {
+	0, 1, 2, 3
+};
+
+static struct gpio_i2cmux_platform_data myboard_i2cmux_data = {
+	.parent		= 1,
+	.base_nr	= 2, /* optional */
+	.values		= myboard_gpiomux_values,
+	.n_values	= ARRAY_SIZE(myboard_gpiomux_values),
+	.gpios		= myboard_gpiomux_gpios,
+	.n_gpios	= ARRAY_SIZE(myboard_gpiomux_gpios),
+	.idle		= 4, /* optional */
+};
+
+static struct platform_device myboard_i2cmux = {
+	.name		= "gpio-i2cmux",
+	.id		= 0,
+	.dev		= {
+		.platform_data	= &myboard_i2cmux_data,
+	},
+};
diff -druNp linux-libre-2.6.37-gnu1/Documentation/input/cma3000_d0x.txt linux-libre-2.6.38-gnu1/Documentation/input/cma3000_d0x.txt
--- linux-libre-2.6.37-gnu1/Documentation/input/cma3000_d0x.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/input/cma3000_d0x.txt	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,115 @@
+Kernel driver for CMA3000-D0x
+============================
+
+Supported chips:
+* VTI CMA3000-D0x
+Datasheet:
+  CMA3000-D0X Product Family Specification 8281000A.02.pdf
+  <http://www.vti.fi/en/>
+
+Author: Hemanth V <hemanthv@ti.com>
+
+
+Description
+-----------
+CMA3000 Tri-axis accelerometer supports Motion detect, Measurement and
+Free fall modes.
+
+Motion Detect Mode: Its the low power mode where interrupts are generated only
+when motion exceeds the defined thresholds.
+
+Measurement Mode: This mode is used to read the acceleration data on X,Y,Z
+axis and supports 400, 100, 40 Hz sample frequency.
+
+Free fall Mode: This mode is intended to save system resources.
+
+Threshold values: Chip supports defining threshold values for above modes
+which includes time and g value. Refer product specifications for more details.
+
+CMA3000 chip supports mutually exclusive I2C and SPI interfaces for
+communication, currently the driver supports I2C based communication only.
+Initial configuration for bus mode is set in non volatile memory and can later
+be modified through bus interface command.
+
+Driver reports acceleration data through input subsystem. It generates ABS_MISC
+event with value 1 when free fall is detected.
+
+Platform data need to be configured for initial default values.
+
+Platform Data
+-------------
+fuzz_x: Noise on X Axis
+
+fuzz_y: Noise on Y Axis
+
+fuzz_z: Noise on Z Axis
+
+g_range: G range in milli g i.e 2000 or 8000
+
+mode: Default Operating mode
+
+mdthr: Motion detect g range threshold value
+
+mdfftmr: Motion detect and free fall time threshold value
+
+ffthr: Free fall g range threshold value
+
+Input Interface
+--------------
+Input driver version is 1.0.0
+Input device ID: bus 0x18 vendor 0x0 product 0x0 version 0x0
+Input device name: "cma3000-accelerometer"
+Supported events:
+  Event type 0 (Sync)
+  Event type 3 (Absolute)
+    Event code 0 (X)
+      Value     47
+      Min    -8000
+      Max     8000
+      Fuzz     200
+    Event code 1 (Y)
+      Value    -28
+      Min    -8000
+      Max     8000
+      Fuzz     200
+    Event code 2 (Z)
+      Value    905
+      Min    -8000
+      Max     8000
+      Fuzz     200
+    Event code 40 (Misc)
+      Value      0
+      Min        0
+      Max        1
+  Event type 4 (Misc)
+
+
+Register/Platform parameters Description
+----------------------------------------
+
+mode:
+	0: power down mode
+	1: 100 Hz Measurement mode
+	2: 400 Hz Measurement mode
+	3: 40 Hz Measurement mode
+	4: Motion Detect mode (default)
+	5: 100 Hz Free fall mode
+	6: 40 Hz Free fall mode
+	7: Power off mode
+
+grange:
+	2000: 2000 mg or 2G Range
+	8000: 8000 mg or 8G Range
+
+mdthr:
+	X: X * 71mg (8G Range)
+	X: X * 18mg (2G Range)
+
+mdfftmr:
+	X: (X & 0x70) * 100 ms (MDTMR)
+	   (X & 0x0F) * 2.5 ms (FFTMR 400 Hz)
+	   (X & 0x0F) * 10 ms  (FFTMR 100 Hz)
+
+ffthr:
+       X: (X >> 2) * 18mg (2G Range)
+       X: (X & 0x0F) * 71 mg (8G Range)
diff -druNp linux-libre-2.6.37-gnu1/Documentation/input/ff.txt linux-libre-2.6.38-gnu1/Documentation/input/ff.txt
--- linux-libre-2.6.37-gnu1/Documentation/input/ff.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/input/ff.txt	2011-03-14 21:20:32.000000000 -0400
@@ -49,7 +49,9 @@ This information is subject to change.
 #include <linux/input.h>
 #include <sys/ioctl.h>
 
-unsigned long features[1 + FF_MAX/sizeof(unsigned long)];
+#define BITS_TO_LONGS(x) \
+	(((x) + 8 * sizeof (unsigned long) - 1) / (8 * sizeof (unsigned long)))
+unsigned long features[BITS_TO_LONGS(FF_CNT)];
 int ioctl(int file_descriptor, int request, unsigned long *features);
 
 "request" must be EVIOCGBIT(EV_FF, size of features array in bytes )
diff -druNp linux-libre-2.6.37-gnu1/Documentation/input/multi-touch-protocol.txt linux-libre-2.6.38-gnu1/Documentation/input/multi-touch-protocol.txt
--- linux-libre-2.6.37-gnu1/Documentation/input/multi-touch-protocol.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/input/multi-touch-protocol.txt	2011-03-14 21:20:32.000000000 -0400
@@ -1,6 +1,6 @@
 Multi-touch (MT) Protocol
 -------------------------
-	Copyright (C) 2009	Henrik Rydberg <rydberg@euromail.se>
+	Copyright (C) 2009-2010	Henrik Rydberg <rydberg@euromail.se>
 
 
 Introduction
@@ -161,19 +161,24 @@ against the glass. The inner region will
 ratio ABS_MT_TOUCH_MAJOR / ABS_MT_WIDTH_MAJOR, which is always smaller than
 unity, is related to the contact pressure. For pressure-based devices,
 ABS_MT_PRESSURE may be used to provide the pressure on the contact area
-instead.
+instead. Devices capable of contact hovering can use ABS_MT_DISTANCE to
+indicate the distance between the contact and the surface.
 
 In addition to the MAJOR parameters, the oval shape of the contact can be
 described by adding the MINOR parameters, such that MAJOR and MINOR are the
 major and minor axis of an ellipse. Finally, the orientation of the oval
 shape can be describe with the ORIENTATION parameter.
 
+For type A devices, further specification of the touch shape is possible
+via ABS_MT_BLOB_ID.
+
 The ABS_MT_TOOL_TYPE may be used to specify whether the touching tool is a
-contact or a pen or something else.  Devices with more granular information
-may specify general shapes as blobs, i.e., as a sequence of rectangular
-shapes grouped together by an ABS_MT_BLOB_ID. Finally, for the few devices
-that currently support it, the ABS_MT_TRACKING_ID event may be used to
-report contact tracking from hardware [5].
+finger or a pen or something else. Finally, the ABS_MT_TRACKING_ID event
+may be used to track identified contacts over time [5].
+
+In the type B protocol, ABS_MT_TOOL_TYPE and ABS_MT_TRACKING_ID are
+implicitly handled by input core; drivers should instead call
+input_mt_report_slot_state().
 
 
 Event Semantics
@@ -213,6 +218,12 @@ The pressure, in arbitrary units, on the
 of TOUCH and WIDTH for pressure-based devices or any device with a spatial
 signal intensity distribution.
 
+ABS_MT_DISTANCE
+
+The distance, in surface units, between the contact and the surface. Zero
+distance means the contact is touching the surface. A positive number means
+the contact is hovering above the surface.
+
 ABS_MT_ORIENTATION
 
 The orientation of the ellipse. The value should describe a signed quarter
@@ -240,21 +251,24 @@ ABS_MT_TOOL_TYPE
 The type of approaching tool. A lot of kernel drivers cannot distinguish
 between different tool types, such as a finger or a pen. In such cases, the
 event should be omitted. The protocol currently supports MT_TOOL_FINGER and
-MT_TOOL_PEN [2].
+MT_TOOL_PEN [2]. For type B devices, this event is handled by input core;
+drivers should instead use input_mt_report_slot_state().
 
 ABS_MT_BLOB_ID
 
 The BLOB_ID groups several packets together into one arbitrarily shaped
-contact. This is a low-level anonymous grouping for type A devices, and
+contact. The sequence of points forms a polygon which defines the shape of
+the contact. This is a low-level anonymous grouping for type A devices, and
 should not be confused with the high-level trackingID [5]. Most type A
 devices do not have blob capability, so drivers can safely omit this event.
 
 ABS_MT_TRACKING_ID
 
 The TRACKING_ID identifies an initiated contact throughout its life cycle
-[5]. This event is mandatory for type B devices. The value range of the
-TRACKING_ID should be large enough to ensure unique identification of a
-contact maintained over an extended period of time.
+[5]. The value range of the TRACKING_ID should be large enough to ensure
+unique identification of a contact maintained over an extended period of
+time. For type B devices, this event is handled by input core; drivers
+should instead use input_mt_report_slot_state().
 
 
 Event Computation
@@ -301,18 +315,19 @@ and with ORIENTATION, one can detect twi
 Notes
 -----
 
-In order to stay compatible with existing applications, the data
-reported in a finger packet must not be recognized as single-touch
-events. In addition, all finger data must bypass input filtering,
-since subsequent events of the same type refer to different fingers.
+In order to stay compatible with existing applications, the data reported
+in a finger packet must not be recognized as single-touch events.
 
-The first kernel driver to utilize the MT protocol is the bcm5974 driver,
-where examples can be found.
+For type A devices, all finger data bypasses input filtering, since
+subsequent events of the same type refer to different fingers.
+
+For example usage of the type A protocol, see the bcm5974 driver. For
+example usage of the type B protocol, see the hid-egalax driver.
 
 [1] With the extension ABS_MT_APPROACH_X and ABS_MT_APPROACH_Y, the
 difference between the contact position and the approaching tool position
 could be used to derive tilt.
 [2] The list can of course be extended.
-[3] Multitouch X driver project: http://bitmath.org/code/multitouch/.
+[3] The mtdev project: http://bitmath.org/code/mtdev/.
 [4] See the section on event computation.
 [5] See the section on finger tracking.
diff -druNp linux-libre-2.6.37-gnu1/Documentation/ioctl/ioctl-number.txt linux-libre-2.6.38-gnu1/Documentation/ioctl/ioctl-number.txt
--- linux-libre-2.6.37-gnu1/Documentation/ioctl/ioctl-number.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/ioctl/ioctl-number.txt	2011-03-14 21:20:32.000000000 -0400
@@ -155,7 +155,6 @@ Code  Seq#(hex)	Include File		Comments
 'Q'	all	linux/soundcard.h
 'R'	00-1F	linux/random.h		conflict!
 'R'	01	linux/rfkill.h		conflict!
-'R'	01-0F	media/rds.h		conflict!
 'R'	C0-DF	net/bluetooth/rfcomm.h
 'S'	all	linux/cdrom.h		conflict!
 'S'	80-81	scsi/scsi_ioctl.h	conflict!
@@ -194,7 +193,6 @@ Code  Seq#(hex)	Include File		Comments
 					<http://lrcwww.epfl.ch/>
 'b'	00-FF				conflict! bit3 vme host bridge
 					<mailto:natalia@nikhefk.nikhef.nl>
-'b'	00-0F	media/bt819.h		conflict!
 'c'	all	linux/cm4000_cs.h	conflict!
 'c'	00-7F	linux/comstats.h	conflict!
 'c'	00-7F	linux/coda.h		conflict!
@@ -249,7 +247,7 @@ Code  Seq#(hex)	Include File		Comments
 'p'	40-7F	linux/nvram.h
 'p'	80-9F	linux/ppdev.h		user-space parport
 					<mailto:tim@cyberelk.net>
-'p'	A1-A4	linux/pps.h		LinuxPPS
+'p'	A1-A5	linux/pps.h		LinuxPPS
 					<mailto:giometti@linux.it>
 'q'	00-1F	linux/serio.h
 'q'	80-FF	linux/telephony.h	Internet PhoneJACK, Internet LineJACK
@@ -260,14 +258,11 @@ Code  Seq#(hex)	Include File		Comments
 't'	80-8F	linux/isdn_ppp.h
 't'	90	linux/toshiba.h
 'u'	00-1F	linux/smb_fs.h		gone
-'v'	all	linux/videodev.h	conflict!
 'v'	00-1F	linux/ext2_fs.h		conflict!
 'v'	00-1F	linux/fs.h		conflict!
 'v'	00-0F	linux/sonypi.h		conflict!
-'v'	C0-CF	drivers/media/video/ov511.h	conflict!
 'v'	C0-DF	media/pwc-ioctl.h	conflict!
 'v'	C0-FF	linux/meye.h		conflict!
-'v'	C0-CF	drivers/media/video/zoran/zoran.h	conflict!
 'v'	D0-DF	drivers/media/video/cpia2/cpia2dev.h	conflict!
 'w'	all				CERN SCI driver
 'y'	00-1F				packet based user level communications
@@ -278,7 +273,6 @@ Code  Seq#(hex)	Include File		Comments
 					<mailto:oe@port.de>
 'z'	10-4F	drivers/s390/crypto/zcrypt_api.h	conflict!
 0x80	00-1F	linux/fb.h
-0x88	00-3F	media/ovcamchip.h
 0x89	00-06	arch/x86/include/asm/sockios.h
 0x89	0B-DF	linux/sockios.h
 0x89	E0-EF	linux/sockios.h		SIOCPROTOPRIVATE range
diff -druNp linux-libre-2.6.37-gnu1/Documentation/iostats.txt linux-libre-2.6.38-gnu1/Documentation/iostats.txt
--- linux-libre-2.6.37-gnu1/Documentation/iostats.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/iostats.txt	2011-03-14 21:20:32.000000000 -0400
@@ -81,7 +81,7 @@ Field  9 -- # of I/Os currently in progr
     The only field that should go to zero. Incremented as requests are
     given to appropriate struct request_queue and decremented as they finish.
 Field 10 -- # of milliseconds spent doing I/Os
-    This field is increases so long as field 9 is nonzero.
+    This field increases so long as field 9 is nonzero.
 Field 11 -- weighted # of milliseconds spent doing I/Os
     This field is incremented at each I/O start, I/O completion, I/O
     merge, or read of these stats by the number of I/Os in progress
diff -druNp linux-libre-2.6.37-gnu1/Documentation/IPMI.txt linux-libre-2.6.38-gnu1/Documentation/IPMI.txt
--- linux-libre-2.6.37-gnu1/Documentation/IPMI.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/IPMI.txt	2011-03-14 21:20:32.000000000 -0400
@@ -533,6 +533,33 @@ completion during sending a panic event.
 Other Pieces
 ------------
 
+Get the detailed info related with the IPMI device
+--------------------------------------------------
+
+Some users need more detailed information about a device, like where
+the address came from or the raw base device for the IPMI interface.
+You can use the IPMI smi_watcher to catch the IPMI interfaces as they
+come or go, and to grab the information, you can use the function
+ipmi_get_smi_info(), which returns the following structure:
+
+struct ipmi_smi_info {
+	enum ipmi_addr_src addr_src;
+	struct device *dev;
+	union {
+		struct {
+			void *acpi_handle;
+		} acpi_info;
+	} addr_info;
+};
+
+Currently special info for only for SI_ACPI address sources is
+returned.  Others may be added as necessary.
+
+Note that the dev pointer is included in the above structure, and
+assuming ipmi_smi_get_info returns success, you must call put_device
+on the dev pointer.
+
+
 Watchdog
 --------
 
diff -druNp linux-libre-2.6.37-gnu1/Documentation/kbuild/kbuild.txt linux-libre-2.6.38-gnu1/Documentation/kbuild/kbuild.txt
--- linux-libre-2.6.37-gnu1/Documentation/kbuild/kbuild.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/kbuild/kbuild.txt	2011-03-14 21:20:32.000000000 -0400
@@ -73,6 +73,14 @@ Specify the output directory when buildi
 The output directory can also be specified using "O=...".
 Setting "O=..." takes precedence over KBUILD_OUTPUT.
 
+KBUILD_DEBARCH
+--------------------------------------------------
+For the deb-pkg target, allows overriding the normal heuristics deployed by
+deb-pkg. Normally deb-pkg attempts to guess the right architecture based on
+the UTS_MACHINE variable, and on some architectures also the kernel config.
+The value of KBUILD_DEBARCH is assumed (not checked) to be a valid Debian
+architecture.
+
 ARCH
 --------------------------------------------------
 Set ARCH to the architecture to be built.
diff -druNp linux-libre-2.6.37-gnu1/Documentation/kbuild/kconfig-language.txt linux-libre-2.6.38-gnu1/Documentation/kbuild/kconfig-language.txt
--- linux-libre-2.6.37-gnu1/Documentation/kbuild/kconfig-language.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/kbuild/kconfig-language.txt	2011-03-14 21:20:32.000000000 -0400
@@ -112,7 +112,6 @@ applicable everywhere (see syntax).
 	(no prompts anywhere) and for symbols with no dependencies.
 	That will limit the usefulness but on the other hand avoid
 	the illegal configurations all over.
-	kconfig should one day warn about such things.
 
 - numerical ranges: "range" <symbol> <symbol> ["if" <expr>]
   This allows to limit the range of possible input values for int
@@ -268,7 +267,7 @@ separate list of options.
 
 choices:
 
-	"choice"
+	"choice" [symbol]
 	<choice options>
 	<choice block>
 	"endchoice"
@@ -282,6 +281,10 @@ single driver can be compiled/loaded int
 can be compiled as modules.
 A choice accepts another option "optional", which allows to set the
 choice to 'n' and no entry needs to be selected.
+If no [symbol] is associated with a choice, then you can not have multiple
+definitions of that choice. If a [symbol] is associated to the choice,
+then you may define the same choice (ie. with the same entries) in another
+place.
 
 comment:
 
diff -druNp linux-libre-2.6.37-gnu1/Documentation/kbuild/makefiles.txt linux-libre-2.6.38-gnu1/Documentation/kbuild/makefiles.txt
--- linux-libre-2.6.37-gnu1/Documentation/kbuild/makefiles.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/kbuild/makefiles.txt	2011-03-14 21:20:32.000000000 -0400
@@ -1136,6 +1136,21 @@ When kbuild executes, the following step
 	      resulting in the target file being recompiled for no
 	      obvious reason.
 
+    dtc
+	Create flattend device tree blob object suitable for linking
+	into vmlinux. Device tree blobs linked into vmlinux are placed
+	in an init section in the image. Platform code *must* copy the
+	blob to non-init memory prior to calling unflatten_device_tree().
+
+	Example:
+		#arch/x86/platform/ce4100/Makefile
+		clean-files := *dtb.S
+
+		DTC_FLAGS := -p 1024
+		obj-y += foo.dtb.o
+
+		$(obj)/%.dtb: $(src)/%.dts
+			$(call cmd,dtc)
 
 --- 6.7 Custom kbuild commands
 
diff -druNp linux-libre-2.6.37-gnu1/Documentation/kdump/kdump.txt linux-libre-2.6.38-gnu1/Documentation/kdump/kdump.txt
--- linux-libre-2.6.37-gnu1/Documentation/kdump/kdump.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/kdump/kdump.txt	2011-03-14 21:20:32.000000000 -0400
@@ -65,18 +65,21 @@ Install kexec-tools
 
 2) Download the kexec-tools user-space package from the following URL:
 
-http://www.kernel.org/pub/linux/kernel/people/horms/kexec-tools/kexec-tools.tar.gz
+http://kernel.org/pub/linux/utils/kernel/kexec/kexec-tools.tar.gz
 
 This is a symlink to the latest version.
 
 The latest kexec-tools git tree is available at:
 
-git://git.kernel.org/pub/scm/linux/kernel/git/horms/kexec-tools.git
-or
-http://www.kernel.org/git/?p=linux/kernel/git/horms/kexec-tools.git
+git://git.kernel.org/pub/scm/utils/kernel/kexec/kexec-tools.git
+and
+http://www.kernel.org/pub/scm/utils/kernel/kexec/kexec-tools.git
+
+There is also a gitweb interface available at
+http://www.kernel.org/git/?p=utils/kernel/kexec/kexec-tools.git
 
 More information about kexec-tools can be found at
-http://www.kernel.org/pub/linux/kernel/people/horms/kexec-tools/README.html
+http://www.kernel.org/pub/linux/utils/kernel/kexec/README.html
 
 3) Unpack the tarball with the tar command, as follows:
 
@@ -439,6 +442,6 @@ To Do
 Contact
 =======
 
-Vivek Goyal (vgoyal@in.ibm.com)
+Vivek Goyal (vgoyal@redhat.com)
 Maneesh Soni (maneesh@in.ibm.com)
 
diff -druNp linux-libre-2.6.37-gnu1/Documentation/kernel-docs.txt linux-libre-2.6.38-gnu1/Documentation/kernel-docs.txt
--- linux-libre-2.6.37-gnu1/Documentation/kernel-docs.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/kernel-docs.txt	2011-03-14 21:20:32.000000000 -0400
@@ -537,7 +537,7 @@
        Notes: Further information in
        http://www.oreilly.com/catalog/linuxdrive2/
 
-     * Title: "Linux Device Drivers, 3nd Edition"
+     * Title: "Linux Device Drivers, 3rd Edition"
        Authors: Jonathan Corbet, Alessandro Rubini, and Greg Kroah-Hartman
        Publisher: O'Reilly & Associates.
        Date: 2005.
@@ -592,14 +592,6 @@
        Pages: 600.
        ISBN: 0-13-101908-2
 
-     * Title:  "The  Design  and Implementation of the 4.4 BSD UNIX
-       Operating System"
-       Author: Marshall Kirk McKusick, Keith Bostic, Michael J. Karels,
-       John S. Quarterman.
-       Publisher: Addison-Wesley.
-       Date: 1996.
-       ISBN: 0-201-54979-4
-
      * Title: "Programming for the real world - POSIX.4"
        Author: Bill O. Gallmeister.
        Publisher: O'Reilly & Associates, Inc..
@@ -610,28 +602,13 @@
        POSIX. Good reference.
 
      * Title:  "UNIX  Systems  for  Modern Architectures: Symmetric
-       Multiprocesssing and Caching for Kernel Programmers"
+       Multiprocessing and Caching for Kernel Programmers"
        Author: Curt Schimmel.
        Publisher: Addison Wesley.
        Date: June, 1994.
        Pages: 432.
        ISBN: 0-201-63338-8
 
-     * Title:  "The  Design  and Implementation of the 4.3 BSD UNIX
-       Operating System"
-       Author: Samuel J. Leffler, Marshall Kirk McKusick, Michael J.
-       Karels, John S. Quarterman.
-       Publisher: Addison-Wesley.
-       Date: 1989 (reprinted with corrections on October, 1990).
-       ISBN: 0-201-06196-1
-
-     * Title: "The Design of the UNIX Operating System"
-       Author: Maurice J. Bach.
-       Publisher: Prentice Hall.
-       Date: 1986.
-       Pages: 471.
-       ISBN: 0-13-201757-1
-
      MISCELLANEOUS:
 
      * Name: linux/Documentation
diff -druNp linux-libre-2.6.37-gnu1/Documentation/kernel-parameters.txt linux-libre-2.6.38-gnu1/Documentation/kernel-parameters.txt
--- linux-libre-2.6.37-gnu1/Documentation/kernel-parameters.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/kernel-parameters.txt	2011-03-14 21:20:32.000000000 -0400
@@ -43,11 +43,11 @@ parameter is applicable:
 	AVR32	AVR32 architecture is enabled.
 	AX25	Appropriate AX.25 support is enabled.
 	BLACKFIN Blackfin architecture is enabled.
+	DRM	Direct Rendering Management support is enabled.
+	DYNAMIC_DEBUG Build in debug messages and enable them at runtime
 	EDD	BIOS Enhanced Disk Drive Services (EDD) is enabled
 	EFI	EFI Partitioning (GPT) is enabled
 	EIDE	EIDE/ATAPI support is enabled.
-	DRM	Direct Rendering Management support is enabled.
-	DYNAMIC_DEBUG Build in debug messages and enable them at runtime
 	FB	The frame buffer device is enabled.
 	GCOV	GCOV profiling is enabled.
 	HW	Appropriate hardware is enabled.
@@ -144,6 +144,11 @@ a fixed number of characters. This limit
 and is between 256 and 4096 characters. It is defined in the file
 ./include/asm/setup.h as COMMAND_LINE_SIZE.
 
+Finally, the [KMG] suffix is commonly described after a number of kernel
+parameter values. These 'K', 'M', and 'G' letters represent the _binary_
+multipliers 'Kilo', 'Mega', and 'Giga', equalling 2^10, 2^20, and 2^30
+bytes respectively. Such letter suffixes can also be entirely omitted.
+
 
 	acpi=		[HW,ACPI,X86]
 			Advanced Configuration and Power Interface
@@ -199,11 +204,6 @@ and is between 256 and 4096 characters.
 			unusable.  The "log_buf_len" parameter may be useful
 			if you need to capture more output.
 
-	acpi_display_output=	[HW,ACPI]
-			acpi_display_output=vendor
-			acpi_display_output=video
-			See above.
-
 	acpi_irq_balance [HW,ACPI]
 			ACPI will balance active IRQs
 			default in APIC mode
@@ -403,6 +403,10 @@ and is between 256 and 4096 characters.
 	bttv.pll=	See Documentation/video4linux/bttv/Insmod-options
 	bttv.tuner=	and Documentation/video4linux/bttv/CARDLIST
 
+	bulk_remove=off	[PPC]  This parameter disables the use of the pSeries
+			firmware feature for flushing multiple hpte entries
+			at a time.
+
 	c101=		[NET] Moxa C101 synchronous serial card
 
 	cachesize=	[BUGS=X86-32] Override level 2 CPU cache size detection.
@@ -546,16 +550,20 @@ and is between 256 and 4096 characters.
 			Format:
 			<first_slot>,<last_slot>,<port>,<enum_bit>[,<debug>]
 
-	crashkernel=nn[KMG]@ss[KMG]
-			[KNL] Reserve a chunk of physical memory to
-			hold a kernel to switch to with kexec on panic.
+	crashkernel=size[KMG][@offset[KMG]]
+			[KNL] Using kexec, Linux can switch to a 'crash kernel'
+			upon panic. This parameter reserves the physical
+			memory region [offset, offset + size] for that kernel
+			image. If '@offset' is omitted, then a suitable offset
+			is selected automatically. Check
+			Documentation/kdump/kdump.txt for further details.
 
 	crashkernel=range1:size1[,range2:size2,...][@offset]
 			[KNL] Same as above, but depends on the memory
 			in the running system. The syntax of range is
 			start-[end] where start and end are both
 			a memory unit (amount[KMG]). See also
-			Documentation/kdump/kdump.txt for a example.
+			Documentation/kdump/kdump.txt for an example.
 
 	cs89x0_dma=	[HW,NET]
 			Format: <dma>
@@ -655,11 +663,6 @@ and is between 256 and 4096 characters.
 
 	dscc4.setup=	[NET]
 
-	dynamic_printk	Enables pr_debug()/dev_dbg() calls if
-			CONFIG_DYNAMIC_PRINTK_DEBUG has been enabled.
-			These can also be switched on/off via
-			<debugfs>/dynamic_printk/modules
-
 	earlycon=	[KNL] Output early console device and options.
 		uart[8250],io,<addr>[,options]
 		uart[8250],mmio,<addr>[,options]
@@ -884,6 +887,7 @@ and is between 256 and 4096 characters.
 			     controller
 	i8042.nopnp	[HW] Don't use ACPIPnP / PnPBIOS to discover KBD/AUX
 			     controllers
+	i8042.notimeout	[HW] Ignore timeout condition signalled by conroller
 	i8042.reset	[HW] Reset the controller during init and cleanup
 	i8042.unlock	[HW] Unlock (ignore) the keylock
 
@@ -1267,10 +1271,9 @@ and is between 256 and 4096 characters.
 			6 (KERN_INFO)		informational
 			7 (KERN_DEBUG)		debug-level messages
 
-	log_buf_len=n	Sets the size of the printk ring buffer, in bytes.
-			Format: { n | nk | nM }
-			n must be a power of two.  The default size
-			is set in the kernel config file.
+	log_buf_len=n[KMG]	Sets the size of the printk ring buffer,
+			in bytes.  n must be a power of two.  The default
+			size is set in the kernel config file.
 
 	logo.nologo	[FB] Disables display of the built-in Linux logo.
 			This may be used to provide more screen space for
@@ -1490,6 +1493,10 @@ and is between 256 and 4096 characters.
 	mtdparts=	[MTD]
 			See drivers/mtd/cmdlinepart.c.
 
+	multitce=off	[PPC]  This parameter disables the use of the pSeries
+			firmware feature for updating multiple TCE entries
+			at a time.
+
 	onenand.bdry=	[HW,MTD] Flex-OneNAND Boundary Configuration
 
 			Format: [die0_boundary][,die0_lock][,die1_boundary][,die1_lock]
@@ -1579,20 +1586,12 @@ and is between 256 and 4096 characters.
 
 	nmi_watchdog=	[KNL,BUGS=X86] Debugging features for SMP kernels
 			Format: [panic,][num]
-			Valid num: 0,1,2
+			Valid num: 0
 			0 - turn nmi_watchdog off
-			1 - use the IO-APIC timer for the NMI watchdog
-			2 - use the local APIC for the NMI watchdog using
-			a performance counter. Note: This will use one
-			performance counter and the local APIC's performance
-			vector.
 			When panic is specified, panic when an NMI watchdog
 			timeout occurs.
 			This is useful when you use a panic=... timeout and
 			need the box quickly up again.
-			Instead of 1 and 2 it is possible to use the following
-			symbolic names: lapic and ioapic
-			Example: nmi_watchdog=2 or nmi_watchdog=panic,lapic
 
 	netpoll.carrier_timeout=
 			[NET] Specifies amount of time (in seconds) that
@@ -1622,6 +1621,8 @@ and is between 256 and 4096 characters.
 	noapic		[SMP,APIC] Tells the kernel to not make use of any
 			IOAPICs that may be present in the system.
 
+	noautogroup	Disable scheduler automatic task group creation.
+
 	nobats		[PPC] Do not use BATs for mapping kernel lowmem
 			on "Classic" PPC cores.
 
@@ -1707,6 +1708,9 @@ and is between 256 and 4096 characters.
 
 	no-kvmclock	[X86,KVM] Disable paravirtualized KVM clock driver
 
+	no-kvmapf	[X86,KVM] Disable paravirtualized asynchronous page
+			fault handling.
+
 	nolapic		[X86-32,APIC] Do not enable or use the local APIC.
 
 	nolapic_timer	[X86-32,APIC] Do not use the local APIC timer.
@@ -2467,12 +2471,13 @@ and is between 256 and 4096 characters.
 			to facilitate early boot debugging.
 			See also Documentation/trace/events.txt
 
-	tsc=		Disable clocksource-must-verify flag for TSC.
+	tsc=		Disable clocksource stability checks for TSC.
 			Format: <string>
 			[x86] reliable: mark tsc clocksource as reliable, this
-			disables clocksource verification at runtime.
-			Used to enable high-resolution timer mode on older
-			hardware, and in virtualized environment.
+			disables clocksource verification at runtime, as well
+			as the stability checks done at bootup.	Used to enable
+			high-resolution timer mode on older hardware, and in
+			virtualized environment.
 			[x86] noirqtime: Do not use TSC to do irq accounting.
 			Used to run time disable IRQ_TIME_ACCOUNTING on any
 			platforms where RDTSC is slow and this accounting
diff -druNp linux-libre-2.6.37-gnu1/Documentation/keys-trusted-encrypted.txt linux-libre-2.6.38-gnu1/Documentation/keys-trusted-encrypted.txt
--- linux-libre-2.6.37-gnu1/Documentation/keys-trusted-encrypted.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/keys-trusted-encrypted.txt	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,145 @@
+			Trusted and Encrypted Keys
+
+Trusted and Encrypted Keys are two new key types added to the existing kernel
+key ring service.  Both of these new types are variable length symmetic keys,
+and in both cases all keys are created in the kernel, and user space sees,
+stores, and loads only encrypted blobs.  Trusted Keys require the availability
+of a Trusted Platform Module (TPM) chip for greater security, while Encrypted
+Keys can be used on any system.  All user level blobs, are displayed and loaded
+in hex ascii for convenience, and are integrity verified.
+
+Trusted Keys use a TPM both to generate and to seal the keys.  Keys are sealed
+under a 2048 bit RSA key in the TPM, and optionally sealed to specified PCR
+(integrity measurement) values, and only unsealed by the TPM, if PCRs and blob
+integrity verifications match.  A loaded Trusted Key can be updated with new
+(future) PCR values, so keys are easily migrated to new pcr values, such as
+when the kernel and initramfs are updated.  The same key can have many saved
+blobs under different PCR values, so multiple boots are easily supported.
+
+By default, trusted keys are sealed under the SRK, which has the default
+authorization value (20 zeros).  This can be set at takeownership time with the
+trouser's utility: "tpm_takeownership -u -z".
+
+Usage:
+    keyctl add trusted name "new keylen [options]" ring
+    keyctl add trusted name "load hex_blob [pcrlock=pcrnum]" ring
+    keyctl update key "update [options]"
+    keyctl print keyid
+
+    options:
+       keyhandle= ascii hex value of sealing key default 0x40000000 (SRK)
+       keyauth=	  ascii hex auth for sealing key default 0x00...i
+		  (40 ascii zeros)
+       blobauth=  ascii hex auth for sealed data default 0x00...
+		  (40 ascii zeros)
+       blobauth=  ascii hex auth for sealed data default 0x00...
+		  (40 ascii zeros)
+       pcrinfo=	  ascii hex of PCR_INFO or PCR_INFO_LONG (no default)
+       pcrlock=	  pcr number to be extended to "lock" blob
+       migratable= 0|1 indicating permission to reseal to new PCR values,
+                   default 1 (resealing allowed)
+
+"keyctl print" returns an ascii hex copy of the sealed key, which is in standard
+TPM_STORED_DATA format.  The key length for new keys are always in bytes.
+Trusted Keys can be 32 - 128 bytes (256 - 1024 bits), the upper limit is to fit
+within the 2048 bit SRK (RSA) keylength, with all necessary structure/padding.
+
+Encrypted keys do not depend on a TPM, and are faster, as they use AES for
+encryption/decryption.  New keys are created from kernel generated random
+numbers, and are encrypted/decrypted using a specified 'master' key.  The
+'master' key can either be a trusted-key or user-key type.  The main
+disadvantage of encrypted keys is that if they are not rooted in a trusted key,
+they are only as secure as the user key encrypting them.  The master user key
+should therefore be loaded in as secure a way as possible, preferably early in
+boot.
+
+Usage:
+  keyctl add encrypted name "new key-type:master-key-name keylen" ring
+  keyctl add encrypted name "load hex_blob" ring
+  keyctl update keyid "update key-type:master-key-name"
+
+where 'key-type' is either 'trusted' or 'user'.
+
+Examples of trusted and encrypted key usage:
+
+Create and save a trusted key named "kmk" of length 32 bytes:
+
+    $ keyctl add trusted kmk "new 32" @u
+    440502848
+
+    $ keyctl show
+    Session Keyring
+           -3 --alswrv    500   500  keyring: _ses
+     97833714 --alswrv    500    -1   \_ keyring: _uid.500
+    440502848 --alswrv    500   500       \_ trusted: kmk
+
+    $ keyctl print 440502848
+    0101000000000000000001005d01b7e3f4a6be5709930f3b70a743cbb42e0cc95e18e915
+    3f60da455bbf1144ad12e4f92b452f966929f6105fd29ca28e4d4d5a031d068478bacb0b
+    27351119f822911b0a11ba3d3498ba6a32e50dac7f32894dd890eb9ad578e4e292c83722
+    a52e56a097e6a68b3f56f7a52ece0cdccba1eb62cad7d817f6dc58898b3ac15f36026fec
+    d568bd4a706cb60bb37be6d8f1240661199d640b66fb0fe3b079f97f450b9ef9c22c6d5d
+    dd379f0facd1cd020281dfa3c70ba21a3fa6fc2471dc6d13ecf8298b946f65345faa5ef0
+    f1f8fff03ad0acb083725535636addb08d73dedb9832da198081e5deae84bfaf0409c22b
+    e4a8aea2b607ec96931e6f4d4fe563ba
+
+    $ keyctl pipe 440502848 > kmk.blob
+
+Load a trusted key from the saved blob:
+
+    $ keyctl add trusted kmk "load `cat kmk.blob`" @u
+    268728824
+
+    $ keyctl print 268728824
+    0101000000000000000001005d01b7e3f4a6be5709930f3b70a743cbb42e0cc95e18e915
+    3f60da455bbf1144ad12e4f92b452f966929f6105fd29ca28e4d4d5a031d068478bacb0b
+    27351119f822911b0a11ba3d3498ba6a32e50dac7f32894dd890eb9ad578e4e292c83722
+    a52e56a097e6a68b3f56f7a52ece0cdccba1eb62cad7d817f6dc58898b3ac15f36026fec
+    d568bd4a706cb60bb37be6d8f1240661199d640b66fb0fe3b079f97f450b9ef9c22c6d5d
+    dd379f0facd1cd020281dfa3c70ba21a3fa6fc2471dc6d13ecf8298b946f65345faa5ef0
+    f1f8fff03ad0acb083725535636addb08d73dedb9832da198081e5deae84bfaf0409c22b
+    e4a8aea2b607ec96931e6f4d4fe563ba
+
+Reseal a trusted key under new pcr values:
+
+    $ keyctl update 268728824 "update pcrinfo=`cat pcr.blob`"
+    $ keyctl print 268728824
+    010100000000002c0002800093c35a09b70fff26e7a98ae786c641e678ec6ffb6b46d805
+    77c8a6377aed9d3219c6dfec4b23ffe3000001005d37d472ac8a44023fbb3d18583a4f73
+    d3a076c0858f6f1dcaa39ea0f119911ff03f5406df4f7f27f41da8d7194f45c9f4e00f2e
+    df449f266253aa3f52e55c53de147773e00f0f9aca86c64d94c95382265968c354c5eab4
+    9638c5ae99c89de1e0997242edfb0b501744e11ff9762dfd951cffd93227cc513384e7e6
+    e782c29435c7ec2edafaa2f4c1fe6e7a781b59549ff5296371b42133777dcc5b8b971610
+    94bc67ede19e43ddb9dc2baacad374a36feaf0314d700af0a65c164b7082401740e489c9
+    7ef6a24defe4846104209bf0c3eced7fa1a672ed5b125fc9d8cd88b476a658a4434644ef
+    df8ae9a178e9f83ba9f08d10fa47e4226b98b0702f06b3b8
+
+Create and save an encrypted key "evm" using the above trusted key "kmk":
+
+    $ keyctl add encrypted evm "new trusted:kmk 32" @u
+    159771175
+
+    $ keyctl print 159771175
+    trusted:kmk 32 2375725ad57798846a9bbd240de8906f006e66c03af53b1b382dbbc55
+    be2a44616e4959430436dc4f2a7a9659aa60bb4652aeb2120f149ed197c564e024717c64
+    5972dcb82ab2dde83376d82b2e3c09ffc
+
+    $ keyctl pipe 159771175 > evm.blob
+
+Load an encrypted key "evm" from saved blob:
+
+    $ keyctl add encrypted evm "load `cat evm.blob`" @u
+    831684262
+
+    $ keyctl print 831684262
+    trusted:kmk 32 2375725ad57798846a9bbd240de8906f006e66c03af53b1b382dbbc55
+    be2a44616e4959430436dc4f2a7a9659aa60bb4652aeb2120f149ed197c564e024717c64
+    5972dcb82ab2dde83376d82b2e3c09ffc
+
+
+The initial consumer of trusted keys is EVM, which at boot time needs a high
+quality symmetric key for HMAC protection of file metadata.  The use of a
+trusted key provides strong guarantees that the EVM key has not been
+compromised by a user level problem, and when sealed to specific boot PCR
+values, protects against boot and offline attacks.  Other uses for trusted and
+encrypted keys, such as for disk and file encryption are anticipated.
diff -druNp linux-libre-2.6.37-gnu1/Documentation/ko_KR/HOWTO linux-libre-2.6.38-gnu1/Documentation/ko_KR/HOWTO
--- linux-libre-2.6.37-gnu1/Documentation/ko_KR/HOWTO	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/ko_KR/HOWTO	2011-03-14 21:20:32.000000000 -0400
@@ -391,8 +391,8 @@ bugme-new 메일링 리스트나(새로�
 bugme-janitor 메일링 리스트(bugzilla에 모든 변화들이 여기서 메일로 전해진다)
 에 등록하면 된다.
 
-      http://lists.osdl.org/mailman/listinfo/bugme-new
-      http://lists.osdl.org/mailman/listinfo/bugme-janitors
+      https://lists.linux-foundation.org/mailman/listinfo/bugme-new
+      https://lists.linux-foundation.org/mailman/listinfo/bugme-janitors
 
 
 
diff -druNp linux-libre-2.6.37-gnu1/Documentation/kprobes.txt linux-libre-2.6.38-gnu1/Documentation/kprobes.txt
--- linux-libre-2.6.37-gnu1/Documentation/kprobes.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/kprobes.txt	2011-03-14 21:20:32.000000000 -0400
@@ -598,7 +598,7 @@ a 5-byte jump instruction. So there are
 a) The instructions in DCR must be relocatable.
 b) The instructions in DCR must not include a call instruction.
 c) JTPR must not be targeted by any jump or call instruction.
-d) DCR must not straddle the border betweeen functions.
+d) DCR must not straddle the border between functions.
 
 Anyway, these limitations are checked by the in-kernel instruction
 decoder, so you don't need to worry about that.
diff -druNp linux-libre-2.6.37-gnu1/Documentation/kvm/api.txt linux-libre-2.6.38-gnu1/Documentation/kvm/api.txt
--- linux-libre-2.6.37-gnu1/Documentation/kvm/api.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/kvm/api.txt	2011-03-14 21:20:32.000000000 -0400
@@ -874,7 +874,7 @@ Possible values are:
  - KVM_MP_STATE_HALTED:          the vcpu has executed a HLT instruction and
                                  is waiting for an interrupt
  - KVM_MP_STATE_SIPI_RECEIVED:   the vcpu has just received a SIPI (vector
-                                 accesible via KVM_GET_VCPU_EVENTS)
+                                 accessible via KVM_GET_VCPU_EVENTS)
 
 This ioctl is only useful after KVM_CREATE_IRQCHIP.  Without an in-kernel
 irqchip, the multiprocessing state must be maintained by userspace.
@@ -1085,6 +1085,184 @@ of 4 instructions that make up a hyperca
 If any additional field gets added to this structure later on, a bit for that
 additional piece of information will be set in the flags bitmap.
 
+4.47 KVM_ASSIGN_PCI_DEVICE
+
+Capability: KVM_CAP_DEVICE_ASSIGNMENT
+Architectures: x86 ia64
+Type: vm ioctl
+Parameters: struct kvm_assigned_pci_dev (in)
+Returns: 0 on success, -1 on error
+
+Assigns a host PCI device to the VM.
+
+struct kvm_assigned_pci_dev {
+	__u32 assigned_dev_id;
+	__u32 busnr;
+	__u32 devfn;
+	__u32 flags;
+	__u32 segnr;
+	union {
+		__u32 reserved[11];
+	};
+};
+
+The PCI device is specified by the triple segnr, busnr, and devfn.
+Identification in succeeding service requests is done via assigned_dev_id. The
+following flags are specified:
+
+/* Depends on KVM_CAP_IOMMU */
+#define KVM_DEV_ASSIGN_ENABLE_IOMMU	(1 << 0)
+
+4.48 KVM_DEASSIGN_PCI_DEVICE
+
+Capability: KVM_CAP_DEVICE_DEASSIGNMENT
+Architectures: x86 ia64
+Type: vm ioctl
+Parameters: struct kvm_assigned_pci_dev (in)
+Returns: 0 on success, -1 on error
+
+Ends PCI device assignment, releasing all associated resources.
+
+See KVM_CAP_DEVICE_ASSIGNMENT for the data structure. Only assigned_dev_id is
+used in kvm_assigned_pci_dev to identify the device.
+
+4.49 KVM_ASSIGN_DEV_IRQ
+
+Capability: KVM_CAP_ASSIGN_DEV_IRQ
+Architectures: x86 ia64
+Type: vm ioctl
+Parameters: struct kvm_assigned_irq (in)
+Returns: 0 on success, -1 on error
+
+Assigns an IRQ to a passed-through device.
+
+struct kvm_assigned_irq {
+	__u32 assigned_dev_id;
+	__u32 host_irq;
+	__u32 guest_irq;
+	__u32 flags;
+	union {
+		struct {
+			__u32 addr_lo;
+			__u32 addr_hi;
+			__u32 data;
+		} guest_msi;
+		__u32 reserved[12];
+	};
+};
+
+The following flags are defined:
+
+#define KVM_DEV_IRQ_HOST_INTX    (1 << 0)
+#define KVM_DEV_IRQ_HOST_MSI     (1 << 1)
+#define KVM_DEV_IRQ_HOST_MSIX    (1 << 2)
+
+#define KVM_DEV_IRQ_GUEST_INTX   (1 << 8)
+#define KVM_DEV_IRQ_GUEST_MSI    (1 << 9)
+#define KVM_DEV_IRQ_GUEST_MSIX   (1 << 10)
+
+It is not valid to specify multiple types per host or guest IRQ. However, the
+IRQ type of host and guest can differ or can even be null.
+
+4.50 KVM_DEASSIGN_DEV_IRQ
+
+Capability: KVM_CAP_ASSIGN_DEV_IRQ
+Architectures: x86 ia64
+Type: vm ioctl
+Parameters: struct kvm_assigned_irq (in)
+Returns: 0 on success, -1 on error
+
+Ends an IRQ assignment to a passed-through device.
+
+See KVM_ASSIGN_DEV_IRQ for the data structure. The target device is specified
+by assigned_dev_id, flags must correspond to the IRQ type specified on
+KVM_ASSIGN_DEV_IRQ. Partial deassignment of host or guest IRQ is allowed.
+
+4.51 KVM_SET_GSI_ROUTING
+
+Capability: KVM_CAP_IRQ_ROUTING
+Architectures: x86 ia64
+Type: vm ioctl
+Parameters: struct kvm_irq_routing (in)
+Returns: 0 on success, -1 on error
+
+Sets the GSI routing table entries, overwriting any previously set entries.
+
+struct kvm_irq_routing {
+	__u32 nr;
+	__u32 flags;
+	struct kvm_irq_routing_entry entries[0];
+};
+
+No flags are specified so far, the corresponding field must be set to zero.
+
+struct kvm_irq_routing_entry {
+	__u32 gsi;
+	__u32 type;
+	__u32 flags;
+	__u32 pad;
+	union {
+		struct kvm_irq_routing_irqchip irqchip;
+		struct kvm_irq_routing_msi msi;
+		__u32 pad[8];
+	} u;
+};
+
+/* gsi routing entry types */
+#define KVM_IRQ_ROUTING_IRQCHIP 1
+#define KVM_IRQ_ROUTING_MSI 2
+
+No flags are specified so far, the corresponding field must be set to zero.
+
+struct kvm_irq_routing_irqchip {
+	__u32 irqchip;
+	__u32 pin;
+};
+
+struct kvm_irq_routing_msi {
+	__u32 address_lo;
+	__u32 address_hi;
+	__u32 data;
+	__u32 pad;
+};
+
+4.52 KVM_ASSIGN_SET_MSIX_NR
+
+Capability: KVM_CAP_DEVICE_MSIX
+Architectures: x86 ia64
+Type: vm ioctl
+Parameters: struct kvm_assigned_msix_nr (in)
+Returns: 0 on success, -1 on error
+
+Set the number of MSI-X interrupts for an assigned device. This service can
+only be called once in the lifetime of an assigned device.
+
+struct kvm_assigned_msix_nr {
+	__u32 assigned_dev_id;
+	__u16 entry_nr;
+	__u16 padding;
+};
+
+#define KVM_MAX_MSIX_PER_DEV		256
+
+4.53 KVM_ASSIGN_SET_MSIX_ENTRY
+
+Capability: KVM_CAP_DEVICE_MSIX
+Architectures: x86 ia64
+Type: vm ioctl
+Parameters: struct kvm_assigned_msix_entry (in)
+Returns: 0 on success, -1 on error
+
+Specifies the routing of an MSI-X assigned device interrupt to a GSI. Setting
+the GSI vector to zero means disabling the interrupt.
+
+struct kvm_assigned_msix_entry {
+	__u32 assigned_dev_id;
+	__u32 gsi;
+	__u16 entry; /* The index of entry in the MSI-X table */
+	__u16 padding[3];
+};
+
 5. The kvm_run structure
 
 Application code obtains a pointer to the kvm_run structure by
diff -druNp linux-libre-2.6.37-gnu1/Documentation/kvm/cpuid.txt linux-libre-2.6.38-gnu1/Documentation/kvm/cpuid.txt
--- linux-libre-2.6.37-gnu1/Documentation/kvm/cpuid.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/kvm/cpuid.txt	2011-03-14 21:20:32.000000000 -0400
@@ -36,6 +36,9 @@ KVM_FEATURE_MMU_OP                 ||
 KVM_FEATURE_CLOCKSOURCE2           ||     3 || kvmclock available at msrs
                                    ||       || 0x4b564d00 and 0x4b564d01
 ------------------------------------------------------------------------------
+KVM_FEATURE_ASYNC_PF               ||     4 || async pf can be enabled by
+                                   ||       || writing to msr 0x4b564d02
+------------------------------------------------------------------------------
 KVM_FEATURE_CLOCKSOURCE_STABLE_BIT ||    24 || host will warn if no guest-side
                                    ||       || per-cpu warps are expected in
                                    ||       || kvmclock.
diff -druNp linux-libre-2.6.37-gnu1/Documentation/kvm/msr.txt linux-libre-2.6.38-gnu1/Documentation/kvm/msr.txt
--- linux-libre-2.6.37-gnu1/Documentation/kvm/msr.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/kvm/msr.txt	2011-03-14 21:20:32.000000000 -0400
@@ -3,7 +3,6 @@ Glauber Costa <glommer@redhat.com>, Red
 =====================================================
 
 KVM makes use of some custom MSRs to service some requests.
-At present, this facility is only used by kvmclock.
 
 Custom MSRs have a range reserved for them, that goes from
 0x4b564d00 to 0x4b564dff. There are MSRs outside this area,
@@ -151,3 +150,38 @@ MSR_KVM_SYSTEM_TIME: 0x12
 			return PRESENT;
 		} else
 			return NON_PRESENT;
+
+MSR_KVM_ASYNC_PF_EN: 0x4b564d02
+	data: Bits 63-6 hold 64-byte aligned physical address of a
+	64 byte memory area which must be in guest RAM and must be
+	zeroed. Bits 5-2 are reserved and should be zero. Bit 0 is 1
+	when asynchronous page faults are enabled on the vcpu 0 when
+	disabled. Bit 2 is 1 if asynchronous page faults can be injected
+	when vcpu is in cpl == 0.
+
+	First 4 byte of 64 byte memory location will be written to by
+	the hypervisor at the time of asynchronous page fault (APF)
+	injection to indicate type of asynchronous page fault. Value
+	of 1 means that the page referred to by the page fault is not
+	present. Value 2 means that the page is now available. Disabling
+	interrupt inhibits APFs. Guest must not enable interrupt
+	before the reason is read, or it may be overwritten by another
+	APF. Since APF uses the same exception vector as regular page
+	fault guest must reset the reason to 0 before it does
+	something that can generate normal page fault.  If during page
+	fault APF reason is 0 it means that this is regular page
+	fault.
+
+	During delivery of type 1 APF cr2 contains a token that will
+	be used to notify a guest when missing page becomes
+	available. When page becomes available type 2 APF is sent with
+	cr2 set to the token associated with the page. There is special
+	kind of token 0xffffffff which tells vcpu that it should wake
+	up all processes waiting for APFs and no individual type 2 APFs
+	will be sent.
+
+	If APF is disabled while there are outstanding APFs, they will
+	not be delivered.
+
+	Currently type 2 APF will be always delivered on the same vcpu as
+	type 1 was, but guest should not rely on that.
diff -druNp linux-libre-2.6.37-gnu1/Documentation/lguest/lguest.c linux-libre-2.6.38-gnu1/Documentation/lguest/lguest.c
--- linux-libre-2.6.37-gnu1/Documentation/lguest/lguest.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/lguest/lguest.c	2011-03-14 21:20:32.000000000 -0400
@@ -39,6 +39,9 @@
 #include <limits.h>
 #include <stddef.h>
 #include <signal.h>
+#include <pwd.h>
+#include <grp.h>
+
 #include <linux/virtio_config.h>
 #include <linux/virtio_net.h>
 #include <linux/virtio_blk.h>
@@ -298,20 +301,27 @@ static void *map_zeroed_pages(unsigned i
 
 	/*
 	 * We use a private mapping (ie. if we write to the page, it will be
-	 * copied).
+	 * copied). We allocate an extra two pages PROT_NONE to act as guard
+	 * pages against read/write attempts that exceed allocated space.
 	 */
-	addr = mmap(NULL, getpagesize() * num,
-		    PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE, fd, 0);
+	addr = mmap(NULL, getpagesize() * (num+2),
+		    PROT_NONE, MAP_PRIVATE, fd, 0);
+
 	if (addr == MAP_FAILED)
 		err(1, "Mmapping %u pages of /dev/zero", num);
 
+	if (mprotect(addr + getpagesize(), getpagesize() * num,
+		     PROT_READ|PROT_WRITE) == -1)
+		err(1, "mprotect rw %u pages failed", num);
+
 	/*
 	 * One neat mmap feature is that you can close the fd, and it
 	 * stays mapped.
 	 */
 	close(fd);
 
-	return addr;
+	/* Return address after PROT_NONE page */
+	return addr + getpagesize();
 }
 
 /* Get some more pages for a device. */
@@ -343,7 +353,7 @@ static void map_at(int fd, void *addr, u
 	 * done to it.  This allows us to share untouched memory between
 	 * Guests.
 	 */
-	if (mmap(addr, len, PROT_READ|PROT_WRITE|PROT_EXEC,
+	if (mmap(addr, len, PROT_READ|PROT_WRITE,
 		 MAP_FIXED|MAP_PRIVATE, fd, offset) != MAP_FAILED)
 		return;
 
@@ -573,10 +583,10 @@ static void *_check_pointer(unsigned lon
 			    unsigned int line)
 {
 	/*
-	 * We have to separately check addr and addr+size, because size could
-	 * be huge and addr + size might wrap around.
+	 * Check if the requested address and size exceeds the allocated memory,
+	 * or addr + size wraps around.
 	 */
-	if (addr >= guest_limit || addr + size >= guest_limit)
+	if ((addr + size) > guest_limit || (addr + size) < addr)
 		errx(1, "%s:%i: Invalid address %#lx", __FILE__, line, addr);
 	/*
 	 * We return a pointer for the caller's convenience, now we know it's
@@ -1872,6 +1882,8 @@ static struct option opts[] = {
 	{ "block", 1, NULL, 'b' },
 	{ "rng", 0, NULL, 'r' },
 	{ "initrd", 1, NULL, 'i' },
+	{ "username", 1, NULL, 'u' },
+	{ "chroot", 1, NULL, 'c' },
 	{ NULL },
 };
 static void usage(void)
@@ -1894,6 +1906,12 @@ int main(int argc, char *argv[])
 	/* If they specify an initrd file to load. */
 	const char *initrd_name = NULL;
 
+	/* Password structure for initgroups/setres[gu]id */
+	struct passwd *user_details = NULL;
+
+	/* Directory to chroot to */
+	char *chroot_path = NULL;
+
 	/* Save the args: we "reboot" by execing ourselves again. */
 	main_args = argv;
 
@@ -1950,6 +1968,14 @@ int main(int argc, char *argv[])
 		case 'i':
 			initrd_name = optarg;
 			break;
+		case 'u':
+			user_details = getpwnam(optarg);
+			if (!user_details)
+				err(1, "getpwnam failed, incorrect username?");
+			break;
+		case 'c':
+			chroot_path = optarg;
+			break;
 		default:
 			warnx("Unknown argument %s", argv[optind]);
 			usage();
@@ -2021,6 +2047,37 @@ int main(int argc, char *argv[])
 	/* If we exit via err(), this kills all the threads, restores tty. */
 	atexit(cleanup_devices);
 
+	/* If requested, chroot to a directory */
+	if (chroot_path) {
+		if (chroot(chroot_path) != 0)
+			err(1, "chroot(\"%s\") failed", chroot_path);
+
+		if (chdir("/") != 0)
+			err(1, "chdir(\"/\") failed");
+
+		verbose("chroot done\n");
+	}
+
+	/* If requested, drop privileges */
+	if (user_details) {
+		uid_t u;
+		gid_t g;
+
+		u = user_details->pw_uid;
+		g = user_details->pw_gid;
+
+		if (initgroups(user_details->pw_name, g) != 0)
+			err(1, "initgroups failed");
+
+		if (setresgid(g, g, g) != 0)
+			err(1, "setresgid failed");
+
+		if (setresuid(u, u, u) != 0)
+			err(1, "setresuid failed");
+
+		verbose("Dropping privileges completed\n");
+	}
+
 	/* Finally, run the Guest.  This doesn't return. */
 	run_guest();
 }
diff -druNp linux-libre-2.6.37-gnu1/Documentation/lguest/lguest.txt linux-libre-2.6.38-gnu1/Documentation/lguest/lguest.txt
--- linux-libre-2.6.37-gnu1/Documentation/lguest/lguest.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/lguest/lguest.txt	2011-03-14 21:20:32.000000000 -0400
@@ -111,8 +111,16 @@ Running Lguest:
 
   Then use --tunnet=bridge:lg0 when launching the guest.
 
-  See http://linux-net.osdl.org/index.php/Bridge for general information
-  on how to get bridging working.
+  See:
+  
+    http://www.linuxfoundation.org/collaborate/workgroups/networking/bridge
+    
+  for general information on how to get bridging to work.
+
+- Random number generation. Using the --rng option will provide a
+  /dev/hwrng in the guest that will read from the host's /dev/random.
+  Use this option in conjunction with rng-tools (see ../hw_random.txt)
+  to provide entropy to the guest kernel's /dev/random.
 
 There is a helpful mailing list at http://ozlabs.org/mailman/listinfo/lguest
 
diff -druNp linux-libre-2.6.37-gnu1/Documentation/magic-number.txt linux-libre-2.6.38-gnu1/Documentation/magic-number.txt
--- linux-libre-2.6.37-gnu1/Documentation/magic-number.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/magic-number.txt	2011-03-14 21:20:32.000000000 -0400
@@ -150,7 +150,7 @@ NBD_REPLY_MAGIC       0x96744668  nbd_re
 STL_BOARDMAGIC        0xa2267f52  stlbrd            include/linux/stallion.h
 ENI155_MAGIC          0xa54b872d  midway_eprom	    drivers/atm/eni.h
 SCI_MAGIC             0xbabeface  gs_port           drivers/char/sh-sci.h
-CODA_MAGIC            0xC0DAC0DA  coda_file_info    include/linux/coda_fs_i.h
+CODA_MAGIC            0xC0DAC0DA  coda_file_info    fs/coda/coda_fs_i.h
 DPMEM_MAGIC           0xc0ffee11  gdt_pci_sram      drivers/scsi/gdth.h
 STLI_PORTMAGIC        0xe671c7a1  stliport          include/linux/istallion.h
 YAM_MAGIC             0xF10A7654  yam_port          drivers/net/hamradio/yam.c
diff -druNp linux-libre-2.6.37-gnu1/Documentation/make/headers_install.txt linux-libre-2.6.38-gnu1/Documentation/make/headers_install.txt
--- linux-libre-2.6.37-gnu1/Documentation/make/headers_install.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/make/headers_install.txt	2011-03-14 21:20:32.000000000 -0400
@@ -39,8 +39,9 @@ INSTALL_HDR_PATH indicates where to inst
 The command "make headers_install_all" exports headers for all architectures
 simultaneously.  (This is mostly of interest to distribution maintainers,
 who create an architecture-independent tarball from the resulting include
-directory.)  Remember to provide the appropriate linux/asm directory via "mv"
-or "ln -s" before building a C library with headers exported this way.
+directory.)  You also can use HDR_ARCH_LIST to specify list of architectures.
+Remember to provide the appropriate linux/asm directory via "mv" or "ln -s"
+before building a C library with headers exported this way.
 
 The kernel header export infrastructure is maintained by David Woodhouse
 <dwmw2@infradead.org>.
diff -druNp linux-libre-2.6.37-gnu1/Documentation/Makefile linux-libre-2.6.38-gnu1/Documentation/Makefile
--- linux-libre-2.6.37-gnu1/Documentation/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -1,3 +1,3 @@
 obj-m := DocBook/ accounting/ auxdisplay/ connector/ \
 	filesystems/ filesystems/configfs/ ia64/ laptops/ networking/ \
-	pcmcia/ spi/ timers/ video4linux/ vm/ watchdog/src/
+	pcmcia/ spi/ timers/ vm/ watchdog/src/
diff -druNp linux-libre-2.6.37-gnu1/Documentation/networking/00-INDEX linux-libre-2.6.38-gnu1/Documentation/networking/00-INDEX
--- linux-libre-2.6.37-gnu1/Documentation/networking/00-INDEX	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/networking/00-INDEX	2011-03-14 21:20:32.000000000 -0400
@@ -40,8 +40,6 @@ decnet.txt
 	- info on using the DECnet networking layer in Linux.
 depca.txt
 	- the Digital DEPCA/EtherWORKS DE1?? and DE2?? LANCE Ethernet driver
-dgrs.txt
-	- the Digi International RightSwitch SE-X Ethernet driver
 dmfe.txt
 	- info on the Davicom DM9102(A)/DM9132/DM9801 fast ethernet driver.
 e100.txt
@@ -50,8 +48,6 @@ e1000.txt
 	- info on Intel's E1000 line of gigabit ethernet boards
 eql.txt
 	- serial IP load balancing
-ethertap.txt
-	- the Ethertap user space packet reception and transmission driver
 ewrk3.txt
 	- the Digital EtherWORKS 3 DE203/4/5 Ethernet driver
 filter.txt
@@ -104,8 +100,6 @@ tuntap.txt
 	- TUN/TAP device driver, allowing user space Rx/Tx of packets.
 vortex.txt
 	- info on using 3Com Vortex (3c590, 3c592, 3c595, 3c597) Ethernet cards.
-wavelan.txt
-	- AT&T GIS (nee NCR) WaveLAN card: An Ethernet-like radio transceiver
 x25.txt
 	- general info on X.25 development.
 x25-iface.txt
diff -druNp linux-libre-2.6.37-gnu1/Documentation/networking/batman-adv.txt linux-libre-2.6.38-gnu1/Documentation/networking/batman-adv.txt
--- linux-libre-2.6.37-gnu1/Documentation/networking/batman-adv.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/networking/batman-adv.txt	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,240 @@
+[state: 21-11-2010]
+
+BATMAN-ADV
+----------
+
+Batman  advanced  is  a new approach to wireless networking which
+does no longer operate on the IP basis. Unlike the batman daemon,
+which  exchanges  information  using UDP packets and sets routing
+tables, batman-advanced operates on ISO/OSI Layer 2 only and uses
+and  routes  (or  better: bridges) Ethernet Frames. It emulates a
+virtual network switch of all nodes participating.  Therefore all
+nodes  appear  to be link local, thus all higher operating proto-
+cols won't be affected by any changes within the network. You can
+run almost any protocol above batman advanced, prominent examples
+are: IPv4, IPv6, DHCP, IPX.
+
+Batman advanced was implemented as a Linux kernel driver  to  re-
+duce the overhead to a minimum. It does not depend on any (other)
+network driver, and can be used on wifi as well as ethernet  lan,
+vpn,  etc ... (anything with ethernet-style layer 2).
+
+CONFIGURATION
+-------------
+
+Load the batman-adv module into your kernel:
+
+# insmod batman-adv.ko
+
+The  module  is now waiting for activation. You must add some in-
+terfaces on which batman can operate. After  loading  the  module
+batman  advanced  will scan your systems interfaces to search for
+compatible interfaces. Once found, it will create  subfolders  in
+the /sys directories of each supported interface, e.g.
+
+# ls /sys/class/net/eth0/batman_adv/
+# iface_status  mesh_iface
+
+If an interface does not have the "batman_adv" subfolder it prob-
+ably is not supported. Not supported  interfaces  are:  loopback,
+non-ethernet and batman's own interfaces.
+
+Note:  After the module was loaded it will continuously watch for
+new interfaces to verify the compatibility. There is no  need  to
+reload the module if you plug your USB wifi adapter into your ma-
+chine after batman advanced was initially loaded.
+
+To activate a  given  interface  simply  write  "bat0"  into  its
+"mesh_iface" file inside the batman_adv subfolder:
+
+# echo bat0 > /sys/class/net/eth0/batman_adv/mesh_iface
+
+Repeat  this step for all interfaces you wish to add.  Now batman
+starts using/broadcasting on this/these interface(s).
+
+By reading the "iface_status" file you can check its status:
+
+# cat /sys/class/net/eth0/batman_adv/iface_status
+# active
+
+To deactivate an interface you have  to  write  "none"  into  its
+"mesh_iface" file:
+
+# echo none > /sys/class/net/eth0/batman_adv/mesh_iface
+
+
+All  mesh  wide  settings  can be found in batman's own interface
+folder:
+
+#  ls  /sys/class/net/bat0/mesh/
+#  aggregated_ogms  bonding  fragmentation  orig_interval
+#  vis_mode
+
+
+There is a special folder for debugging informations:
+
+#  ls /sys/kernel/debug/batman_adv/bat0/
+#  originators  socket  transtable_global  transtable_local
+#  vis_data
+
+
+Some of the files contain all sort of status information  regard-
+ing  the  mesh  network.  For  example, you can view the table of
+originators (mesh participants) with:
+
+# cat /sys/kernel/debug/batman_adv/bat0/originators
+
+Other files allow to change batman's behaviour to better fit your
+requirements.  For instance, you can check the current originator
+interval (value in milliseconds which determines how often batman
+sends its broadcast packets):
+
+# cat /sys/class/net/bat0/mesh/orig_interval
+# 1000
+
+and also change its value:
+
+# echo 3000 > /sys/class/net/bat0/mesh/orig_interval
+
+In very mobile scenarios, you might want to adjust the originator
+interval to a lower value. This will make the mesh  more  respon-
+sive to topology changes, but will also increase the overhead.
+
+
+USAGE
+-----
+
+To  make use of your newly created mesh, batman advanced provides
+a new interface "bat0" which you should use from this  point  on.
+All  interfaces  added  to  batman  advanced are not relevant any
+longer because batman handles them for you. Basically, one "hands
+over" the data by using the batman interface and batman will make
+sure it reaches its destination.
+
+The "bat0" interface can be used like any  other  regular  inter-
+face.  It needs an IP address which can be either statically con-
+figured or dynamically (by using DHCP or similar services):
+
+# NodeA: ifconfig bat0 192.168.0.1
+# NodeB: ifconfig bat0 192.168.0.2
+# NodeB: ping 192.168.0.1
+
+Note:  In  order to avoid problems remove all IP addresses previ-
+ously assigned to interfaces now used by batman advanced, e.g.
+
+# ifconfig eth0 0.0.0.0
+
+
+VISUALIZATION
+-------------
+
+If you want topology visualization, at least one mesh  node  must
+be configured as VIS-server:
+
+# echo "server" > /sys/class/net/bat0/mesh/vis_mode
+
+Each  node  is  either configured as "server" or as "client" (de-
+fault: "client").  Clients send their topology data to the server
+next to them, and server synchronize with other servers. If there
+is no server configured (default) within the  mesh,  no  topology
+information   will  be  transmitted.  With  these  "synchronizing
+servers", there can be 1 or more vis servers sharing the same (or
+at least very similar) data.
+
+When  configured  as  server,  you can get a topology snapshot of
+your mesh:
+
+# cat /sys/kernel/debug/batman_adv/bat0/vis_data
+
+This raw output is intended to be easily parsable and convertable
+with  other tools. Have a look at the batctl README if you want a
+vis output in dot or json format for instance and how those  out-
+puts could then be visualised in an image.
+
+The raw format consists of comma separated values per entry where
+each entry is giving information about a  certain  source  inter-
+face.  Each  entry can/has to have the following values:
+-> "mac" - mac address of an originator's source interface
+           (each line begins with it)
+-> "TQ mac  value"  -  src mac's link quality towards mac address
+                       of a neighbor originator's interface which
+                       is being used for routing
+-> "HNA mac" - HNA announced by source mac
+-> "PRIMARY" - this  is a primary interface
+-> "SEC mac" - secondary mac address of source
+               (requires preceding PRIMARY)
+
+The TQ value has a range from 4 to 255 with 255 being  the  best.
+The HNA entries are showing which hosts are connected to the mesh
+via bat0 or being bridged into the mesh network.  The PRIMARY/SEC
+values are only applied on primary interfaces
+
+
+LOGGING/DEBUGGING
+-----------------
+
+All error messages, warnings and information messages are sent to
+the kernel log. Depending on your operating  system  distribution
+this  can  be read in one of a number of ways. Try using the com-
+mands: dmesg, logread, or looking in the files  /var/log/kern.log
+or  /var/log/syslog.  All  batman-adv  messages are prefixed with
+"batman-adv:" So to see just these messages try
+
+# dmesg | grep batman-adv
+
+When investigating problems with your mesh network  it  is  some-
+times  necessary  to see more detail debug messages. This must be
+enabled when compiling the batman-adv module. When building  bat-
+man-adv  as  part of kernel, use "make menuconfig" and enable the
+option "B.A.T.M.A.N. debugging".
+
+Those additional  debug messages can be accessed  using a special
+file in debugfs
+
+# cat /sys/kernel/debug/batman_adv/bat0/log
+
+The additional debug output is by default disabled. It can be en-
+abled  during run time. Following log_levels are defined:
+
+0 - All  debug  output  disabled
+1 - Enable messages related to routing / flooding / broadcasting
+2 - Enable route or hna added / changed / deleted
+3 - Enable all messages
+
+The debug output can be changed at runtime  using  the  file
+/sys/class/net/bat0/mesh/log_level. e.g.
+
+# echo 2 > /sys/class/net/bat0/mesh/log_level
+
+will enable debug messages for when routes or HNAs change.
+
+
+BATCTL
+------
+
+As batman advanced operates on layer 2 all hosts participating in
+the  virtual switch are completely transparent for all  protocols
+above layer 2. Therefore the common diagnosis tools do  not  work
+as  expected.  To  overcome these problems batctl was created. At
+the  moment the  batctl contains ping,  traceroute,  tcpdump  and
+interfaces to the kernel module settings.
+
+For more information, please see the manpage (man batctl).
+
+batctl is available on http://www.open-mesh.org/
+
+
+CONTACT
+-------
+
+Please send us comments, experiences, questions, anything :)
+
+IRC:            #batman   on   irc.freenode.org
+Mailing-list:   b.a.t.m.a.n@b.a.t.m.a.n@lists.open-mesh.org
+                (optional   subscription   at
+                 https://lists.open-mesh.org/mm/listinfo/b.a.t.m.a.n)
+
+You can also contact the Authors:
+
+Marek  Lindner  <lindner_marek@yahoo.de>
+Simon  Wunderlich  <siwu@hrz.tu-chemnitz.de>
diff -druNp linux-libre-2.6.37-gnu1/Documentation/networking/bonding.txt linux-libre-2.6.38-gnu1/Documentation/networking/bonding.txt
--- linux-libre-2.6.37-gnu1/Documentation/networking/bonding.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/networking/bonding.txt	2011-03-14 21:20:32.000000000 -0400
@@ -49,7 +49,8 @@ Table of Contents
 3.3	Configuring Bonding Manually with Ifenslave
 3.3.1		Configuring Multiple Bonds Manually
 3.4	Configuring Bonding Manually via Sysfs
-3.5	Overriding Configuration for Special Cases
+3.5	Configuration with Interfaces Support
+3.6	Overriding Configuration for Special Cases
 
 4. Querying Bonding Configuration
 4.1	Bonding Configuration
@@ -161,8 +162,8 @@ onwards) do not have /usr/include/linux
 default kernel source include directory.
 
 SECOND IMPORTANT NOTE:
-	If you plan to configure bonding using sysfs, you do not need
-to use ifenslave.
+	If you plan to configure bonding using sysfs or using the
+/etc/network/interfaces file, you do not need to use ifenslave.
 
 2. Bonding Driver Options
 =========================
@@ -779,22 +780,26 @@ resend_igmp
 
 	You can configure bonding using either your distro's network
 initialization scripts, or manually using either ifenslave or the
-sysfs interface.  Distros generally use one of two packages for the
-network initialization scripts: initscripts or sysconfig.  Recent
-versions of these packages have support for bonding, while older
+sysfs interface.  Distros generally use one of three packages for the
+network initialization scripts: initscripts, sysconfig or interfaces.
+Recent versions of these packages have support for bonding, while older
 versions do not.
 
 	We will first describe the options for configuring bonding for
-distros using versions of initscripts and sysconfig with full or
-partial support for bonding, then provide information on enabling
+distros using versions of initscripts, sysconfig and interfaces with full
+or partial support for bonding, then provide information on enabling
 bonding without support from the network initialization scripts (i.e.,
 older versions of initscripts or sysconfig).
 
-	If you're unsure whether your distro uses sysconfig or
-initscripts, or don't know if it's new enough, have no fear.
+	If you're unsure whether your distro uses sysconfig,
+initscripts or interfaces, or don't know if it's new enough, have no fear.
 Determining this is fairly straightforward.
 
-	First, issue the command:
+	First, look for a file called interfaces in /etc/network directory.
+If this file is present in your system, then your system use interfaces. See
+Configuration with Interfaces Support.
+
+	Else, issue the command:
 
 $ rpm -qf /sbin/ifup
 
@@ -1327,8 +1332,62 @@ echo 2000 > /sys/class/net/bond1/bonding
 echo +eth2 > /sys/class/net/bond1/bonding/slaves
 echo +eth3 > /sys/class/net/bond1/bonding/slaves
 
-3.5 Overriding Configuration for Special Cases
+3.5 Configuration with Interfaces Support
+-----------------------------------------
+
+        This section applies to distros which use /etc/network/interfaces file
+to describe network interface configuration, most notably Debian and it's
+derivatives.
+
+	The ifup and ifdown commands on Debian don't support bonding out of
+the box. The ifenslave-2.6 package should be installed to provide bonding
+support.  Once installed, this package will provide bond-* options to be used
+into /etc/network/interfaces.
+
+	Note that ifenslave-2.6 package will load the bonding module and use
+the ifenslave command when appropriate.
+
+Example Configurations
+----------------------
+
+In /etc/network/interfaces, the following stanza will configure bond0, in
+active-backup mode, with eth0 and eth1 as slaves.
+
+auto bond0
+iface bond0 inet dhcp
+	bond-slaves eth0 eth1
+	bond-mode active-backup
+	bond-miimon 100
+	bond-primary eth0 eth1
+
+If the above configuration doesn't work, you might have a system using
+upstart for system startup. This is most notably true for recent
+Ubuntu versions. The following stanza in /etc/network/interfaces will
+produce the same result on those systems.
+
+auto bond0
+iface bond0 inet dhcp
+	bond-slaves none
+	bond-mode active-backup
+	bond-miimon 100
+
+auto eth0
+iface eth0 inet manual
+	bond-master bond0
+	bond-primary eth0 eth1
+
+auto eth1
+iface eth1 inet manual
+	bond-master bond0
+	bond-primary eth0 eth1
+
+For a full list of bond-* supported options in /etc/network/interfaces and some
+more advanced examples tailored to you particular distros, see the files in
+/usr/share/doc/ifenslave-2.6.
+
+3.6 Overriding Configuration for Special Cases
 ----------------------------------------------
+
 When using the bonding driver, the physical port which transmits a frame is
 typically selected by the bonding driver, and is not relevant to the user or
 system administrator.  The output port is simply selected using the policies of
diff -druNp linux-libre-2.6.37-gnu1/Documentation/networking/bridge.txt linux-libre-2.6.38-gnu1/Documentation/networking/bridge.txt
--- linux-libre-2.6.37-gnu1/Documentation/networking/bridge.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/networking/bridge.txt	2011-03-14 21:20:32.000000000 -0400
@@ -1,8 +1,8 @@
 In order to use the Ethernet bridging functionality, you'll need the
 userspace tools. These programs and documentation are available
-at http://www.linux-foundation.org/en/Net:Bridge.  The download page is
+at http://www.linuxfoundation.org/en/Net:Bridge.  The download page is
 http://prdownloads.sourceforge.net/bridge.
 
 If you still have questions, don't hesitate to post to the mailing list 
-(more info http://lists.osdl.org/mailman/listinfo/bridge).
+(more info https://lists.linux-foundation.org/mailman/listinfo/bridge).
 
diff -druNp linux-libre-2.6.37-gnu1/Documentation/networking/caif/spi_porting.txt linux-libre-2.6.38-gnu1/Documentation/networking/caif/spi_porting.txt
--- linux-libre-2.6.37-gnu1/Documentation/networking/caif/spi_porting.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/networking/caif/spi_porting.txt	2011-03-14 21:20:32.000000000 -0400
@@ -32,7 +32,7 @@ the physical hardware, both with regard
 	This function is called by the CAIF SPI interface to give
 	you a chance to set up your hardware to be ready to receive
 	a stream of data from the master. The xfer structure contains
-	both physical and logical adresses, as well as the total length
+	both physical and logical addresses, as well as the total length
 	of the transfer in both directions.The dev parameter can be used
 	to map to different CAIF SPI slave devices.
 
diff -druNp linux-libre-2.6.37-gnu1/Documentation/networking/dccp.txt linux-libre-2.6.38-gnu1/Documentation/networking/dccp.txt
--- linux-libre-2.6.37-gnu1/Documentation/networking/dccp.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/networking/dccp.txt	2011-03-14 21:20:32.000000000 -0400
@@ -38,15 +38,35 @@ The Linux DCCP implementation does not c
 specified in RFCs 4340...42.
 
 The known bugs are at:
-	http://linux-net.osdl.org/index.php/TODO#DCCP
+	http://www.linuxfoundation.org/collaborate/workgroups/networking/todo#DCCP
 
 For more up-to-date versions of the DCCP implementation, please consider using
 the experimental DCCP test tree; instructions for checking this out are on:
-http://linux-net.osdl.org/index.php/DCCP_Testing#Experimental_DCCP_source_tree
+http://www.linuxfoundation.org/collaborate/workgroups/networking/dccp_testing#Experimental_DCCP_source_tree
 
 
 Socket options
 ==============
+DCCP_SOCKOPT_QPOLICY_ID sets the dequeuing policy for outgoing packets. It takes
+a policy ID as argument and can only be set before the connection (i.e. changes
+during an established connection are not supported). Currently, two policies are
+defined: the "simple" policy (DCCPQ_POLICY_SIMPLE), which does nothing special,
+and a priority-based variant (DCCPQ_POLICY_PRIO). The latter allows to pass an
+u32 priority value as ancillary data to sendmsg(), where higher numbers indicate
+a higher packet priority (similar to SO_PRIORITY). This ancillary data needs to
+be formatted using a cmsg(3) message header filled in as follows:
+	cmsg->cmsg_level = SOL_DCCP;
+	cmsg->cmsg_type	 = DCCP_SCM_PRIORITY;
+	cmsg->cmsg_len	 = CMSG_LEN(sizeof(uint32_t));	/* or CMSG_LEN(4) */
+
+DCCP_SOCKOPT_QPOLICY_TXQLEN sets the maximum length of the output queue. A zero
+value is always interpreted as unbounded queue length. If different from zero,
+the interpretation of this parameter depends on the current dequeuing policy
+(see above): the "simple" policy will enforce a fixed queue size by returning
+EAGAIN, whereas the "prio" policy enforces a fixed queue length by dropping the
+lowest-priority packet first. The default value for this parameter is
+initialised from /proc/sys/net/dccp/default/tx_qlen.
+
 DCCP_SOCKOPT_SERVICE sets the service. The specification mandates use of
 service codes (RFC 4340, sec. 8.1.2); if this socket option is not set,
 the socket will fall back to 0 (which means that no meaningful service code
@@ -147,6 +167,7 @@ rx_ccid = 2
 seq_window = 100
 	The initial sequence window (sec. 7.5.2) of the sender. This influences
 	the local ackno validity and the remote seqno validity windows (7.5.1).
+	Values in the range Wmin = 32 (RFC 4340, 7.5.2) up to 2^32-1 can be set.
 
 tx_qlen = 5
 	The size of the transmit buffer in packets. A value of 0 corresponds
diff -druNp linux-libre-2.6.37-gnu1/Documentation/networking/dns_resolver.txt linux-libre-2.6.38-gnu1/Documentation/networking/dns_resolver.txt
--- linux-libre-2.6.37-gnu1/Documentation/networking/dns_resolver.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/networking/dns_resolver.txt	2011-03-14 21:20:32.000000000 -0400
@@ -61,7 +61,6 @@ before the more general line given above
 	create	dns_resolver  	foo:*	*	/usr/sbin/dns.foo %k
 
 
-
 =====
 USAGE
 =====
@@ -104,6 +103,14 @@ implemented in the module can be called
      returned also.
 
 
+===============================
+READING DNS KEYS FROM USERSPACE
+===============================
+
+Keys of dns_resolver type can be read from userspace using keyctl_read() or
+"keyctl read/print/pipe".
+
+
 =========
 MECHANISM
 =========
diff -druNp linux-libre-2.6.37-gnu1/Documentation/networking/e1000e.txt linux-libre-2.6.38-gnu1/Documentation/networking/e1000e.txt
--- linux-libre-2.6.37-gnu1/Documentation/networking/e1000e.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/networking/e1000e.txt	2011-03-14 21:20:32.000000000 -0400
@@ -1,5 +1,5 @@
 Linux* Driver for Intel(R) Network Connection
-===============================================================
+=============================================
 
 Intel Gigabit Linux driver.
 Copyright(c) 1999 - 2010 Intel Corporation.
@@ -61,6 +61,12 @@ per second, even if more packets have co
 load on the system and can lower CPU utilization under heavy load,
 but will increase latency as packets are not processed as quickly.
 
+The default behaviour of the driver previously assumed a static
+InterruptThrottleRate value of 8000, providing a good fallback value for
+all traffic types, but lacking in small packet performance and latency.
+The hardware can handle many more small packets per second however, and
+for this reason an adaptive interrupt moderation algorithm was implemented.
+
 The driver has two adaptive modes (setting 1 or 3) in which
 it dynamically adjusts the InterruptThrottleRate value based on the traffic
 that it receives. After determining the type of incoming traffic in the last
@@ -86,8 +92,8 @@ InterruptThrottleRate is set to mode 1.
 the same as mode 3, the InterruptThrottleRate will be increased stepwise to
 70000 for traffic in class "Lowest latency".
 
-In simplified mode the interrupt rate is based on the ratio of Tx and
-Rx traffic.  If the bytes per second rate is approximately equal the
+In simplified mode the interrupt rate is based on the ratio of TX and
+RX traffic.  If the bytes per second rate is approximately equal, the
 interrupt rate will drop as low as 2000 interrupts per second.  If the
 traffic is mostly transmit or mostly receive, the interrupt rate could
 be as high as 8000.
@@ -177,7 +183,7 @@ Copybreak
 Valid Range:   0-xxxxxxx (0=off)
 Default Value: 256
 
-Driver copies all packets below or equaling this size to a fresh Rx
+Driver copies all packets below or equaling this size to a fresh RX
 buffer before handing it up the stack.
 
 This parameter is different than other parameters, in that it is a
@@ -223,17 +229,17 @@ loading or enabling the driver, try disa
 
 WriteProtectNVM
 ---------------
-Valid Range: 0-1
-Default Value: 1 (enabled)
-
-Set the hardware to ignore all write/erase cycles to the GbE region in the
-ICHx NVM (non-volatile memory).  This feature can be disabled by the
-WriteProtectNVM module parameter (enabled by default) only after a hardware
-reset, but the machine must be power cycled before trying to enable writes.
+Valid Range: 0,1
+Default Value: 1
 
-Note: the kernel boot option iomem=relaxed may need to be set if the kernel
-config option CONFIG_STRICT_DEVMEM=y, if the root user wants to write the
-NVM from user space via ethtool.
+If set to 1, configure the hardware to ignore all write/erase cycles to the
+GbE region in the ICHx NVM (in order to prevent accidental corruption of the
+NVM). This feature can be disabled by setting the parameter to 0 during initial
+driver load.
+NOTE: The machine must be power cycled (full off/on) when enabling NVM writes
+via setting the parameter to zero. Once the NVM has been locked (via the
+parameter at 1 when the driver loads) it cannot be unlocked except via power
+cycle.
 
 Additional Configurations
 =========================
@@ -259,32 +265,30 @@ Additional Configurations
   - Some adapters limit Jumbo Frames sized packets to a maximum of
     4096 bytes and some adapters do not support Jumbo Frames.
 
-
   Ethtool
   -------
   The driver utilizes the ethtool interface for driver configuration and
   diagnostics, as well as displaying statistical information.  We
-  strongly recommend downloading the latest version of Ethtool at:
+  strongly recommend downloading the latest version of ethtool at:
 
-  http://sourceforge.net/projects/gkernel.
+  http://ftp.kernel.org/pub/software/network/ethtool/
 
   Speed and Duplex
   ----------------
-  Speed and Duplex are configured through the Ethtool* utility. For
-  instructions,  refer to the Ethtool man page.
+  Speed and Duplex are configured through the ethtool* utility. For
+  instructions,  refer to the ethtool man page.
 
   Enabling Wake on LAN* (WoL)
   ---------------------------
-  WoL is configured through the Ethtool* utility. For instructions on
-  enabling WoL with Ethtool, refer to the Ethtool man page.
+  WoL is configured through the ethtool* utility. For instructions on
+  enabling WoL with ethtool, refer to the ethtool man page.
 
   WoL will be enabled on the system during the next shut down or reboot.
   For this driver version, in order to enable WoL, the e1000e driver must be
   loaded when shutting down or rebooting the system.
 
   In most cases Wake On LAN is only supported on port A for multiple port
-  adapters. To verify if a port supports Wake on LAN run ethtool eth<X>.
-
+  adapters. To verify if a port supports Wake on Lan run ethtool eth<X>.
 
 Support
 =======
diff -druNp linux-libre-2.6.37-gnu1/Documentation/networking/e1000.txt linux-libre-2.6.38-gnu1/Documentation/networking/e1000.txt
--- linux-libre-2.6.37-gnu1/Documentation/networking/e1000.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/networking/e1000.txt	2011-03-14 21:20:32.000000000 -0400
@@ -79,7 +79,7 @@ InterruptThrottleRate
 ---------------------
 (not supported on Intel(R) 82542, 82543 or 82544-based adapters)
 Valid Range:   0,1,3,4,100-100000 (0=off, 1=dynamic, 3=dynamic conservative,
-                                   4=simplified balancing)
+                                 4=simplified balancing)
 Default Value: 3
 
 The driver can limit the amount of interrupts per second that the adapter
@@ -124,8 +124,8 @@ InterruptThrottleRate is set to mode 1.
 the same as mode 3, the InterruptThrottleRate will be increased stepwise to
 70000 for traffic in class "Lowest latency".
 
-In simplified mode the interrupt rate is based on the ratio of Tx and
-Rx traffic.  If the bytes per second rate is approximately equal, the
+In simplified mode the interrupt rate is based on the ratio of TX and
+RX traffic.  If the bytes per second rate is approximately equal, the
 interrupt rate will drop as low as 2000 interrupts per second.  If the
 traffic is mostly transmit or mostly receive, the interrupt rate could
 be as high as 8000.
@@ -245,7 +245,7 @@ NOTE:  Depending on the available system
 TxDescriptorStep
 ----------------
 Valid Range:    1 (use every Tx Descriptor)
-		4 (use every 4th Tx Descriptor)
+                4 (use every 4th Tx Descriptor)
 
 Default Value:  1 (use every Tx Descriptor)
 
@@ -312,7 +312,7 @@ Valid Range:   0-xxxxxxx (0=off)
 Default Value: 256
 Usage: insmod e1000.ko copybreak=128
 
-Driver copies all packets below or equaling this size to a fresh Rx
+Driver copies all packets below or equaling this size to a fresh RX
 buffer before handing it up the stack.
 
 This parameter is different than other parameters, in that it is a
@@ -431,15 +431,15 @@ Additional Configurations
   Ethtool
   -------
   The driver utilizes the ethtool interface for driver configuration and
-  diagnostics, as well as displaying statistical information.  Ethtool
+  diagnostics, as well as displaying statistical information.  The ethtool
   version 1.6 or later is required for this functionality.
 
   The latest release of ethtool can be found from
-  http://sourceforge.net/projects/gkernel.
+  http://ftp.kernel.org/pub/software/network/ethtool/
 
   Enabling Wake on LAN* (WoL)
   ---------------------------
-  WoL is configured through the Ethtool* utility.
+  WoL is configured through the ethtool* utility.
 
   WoL will be enabled on the system during the next shut down or reboot.
   For this driver version, in order to enable WoL, the e1000 driver must be
diff -druNp linux-libre-2.6.37-gnu1/Documentation/networking/e100.txt linux-libre-2.6.38-gnu1/Documentation/networking/e100.txt
--- linux-libre-2.6.37-gnu1/Documentation/networking/e100.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/networking/e100.txt	2011-03-14 21:20:32.000000000 -0400
@@ -72,7 +72,7 @@ Tx Descriptors: Number of transmit descr
    ethtool -G eth? tx n, where n is the number of desired tx descriptors.
 
 Speed/Duplex: The driver auto-negotiates the link speed and duplex settings by
-   default. Ethtool can be used as follows to force speed/duplex.
+   default. The ethtool utility can be used as follows to force speed/duplex.
 
    ethtool -s eth?  autoneg off speed {10|100} duplex {full|half}
 
@@ -126,30 +126,21 @@ Additional Configurations
   -------
 
   The driver utilizes the ethtool interface for driver configuration and
-  diagnostics, as well as displaying statistical information.  Ethtool
+  diagnostics, as well as displaying statistical information.  The ethtool
   version 1.6 or later is required for this functionality.
 
   The latest release of ethtool can be found from
-  http://sourceforge.net/projects/gkernel.
-
-  NOTE: Ethtool 1.6 only supports a limited set of ethtool options. Support
-  for a more complete ethtool feature set can be enabled by upgrading
-  ethtool to ethtool-1.8.1.
-
+  http://ftp.kernel.org/pub/software/network/ethtool/
 
   Enabling Wake on LAN* (WoL)
   ---------------------------
-  WoL is provided through the Ethtool* utility. Ethtool is included with Red
-  Hat* 8.0. For other Linux distributions, download and install Ethtool from
-  the following website: http://sourceforge.net/projects/gkernel.
-
-  For instructions on enabling WoL with Ethtool, refer to the Ethtool man page.
+  WoL is provided through the ethtool* utility.  For instructions on enabling
+  WoL with ethtool, refer to the ethtool man page.
 
   WoL will be enabled on the system during the next shut down or reboot. For
   this driver version, in order to enable WoL, the e100 driver must be
   loaded when shutting down or rebooting the system.
 
-
   NAPI
   ----
 
diff -druNp linux-libre-2.6.37-gnu1/Documentation/networking/generic_netlink.txt linux-libre-2.6.38-gnu1/Documentation/networking/generic_netlink.txt
--- linux-libre-2.6.37-gnu1/Documentation/networking/generic_netlink.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/networking/generic_netlink.txt	2011-03-14 21:20:32.000000000 -0400
@@ -1,3 +1,3 @@
 A wiki document on how to use Generic Netlink can be found here:
 
- * http://linux-net.osdl.org/index.php/Generic_Netlink_HOWTO
+ * http://www.linuxfoundation.org/collaborate/workgroups/networking/generic_netlink_howto
diff -druNp linux-libre-2.6.37-gnu1/Documentation/networking/igb.txt linux-libre-2.6.38-gnu1/Documentation/networking/igb.txt
--- linux-libre-2.6.37-gnu1/Documentation/networking/igb.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/networking/igb.txt	2011-03-14 21:20:32.000000000 -0400
@@ -36,6 +36,7 @@ Default Value: 0
 This parameter adds support for SR-IOV.  It causes the driver to spawn up to
 max_vfs worth of virtual function.
 
+
 Additional Configurations
 =========================
 
@@ -60,15 +61,16 @@ Additional Configurations
   Ethtool
   -------
   The driver utilizes the ethtool interface for driver configuration and
-  diagnostics, as well as displaying statistical information.
+  diagnostics, as well as displaying statistical information. The latest
+  version of ethtool can be found at:
 
-  http://sourceforge.net/projects/gkernel.
+  http://ftp.kernel.org/pub/software/network/ethtool/
 
   Enabling Wake on LAN* (WoL)
   ---------------------------
-  WoL is configured through the Ethtool* utility.
+  WoL is configured through the ethtool* utility.
 
-  For instructions on enabling WoL with Ethtool, refer to the Ethtool man page.
+  For instructions on enabling WoL with ethtool, refer to the ethtool man page.
 
   WoL will be enabled on the system during the next shut down or reboot.
   For this driver version, in order to enable WoL, the igb driver must be
@@ -91,31 +93,6 @@ Additional Configurations
   REQUIREMENTS: MSI-X support is required for Multiqueue. If MSI-X is not
   found, the system will fallback to MSI or to Legacy interrupts.
 
-  LRO
-  ---
-  Large Receive Offload (LRO) is a technique for increasing inbound throughput
-  of high-bandwidth network connections by reducing CPU overhead. It works by
-  aggregating multiple incoming packets from a single stream into a larger
-  buffer before they are passed higher up the networking stack, thus reducing
-  the number of packets that have to be processed. LRO combines multiple
-  Ethernet frames into a single receive in the stack, thereby potentially
-  decreasing CPU utilization for receives.
-
-  NOTE: You need to have inet_lro enabled via either the CONFIG_INET_LRO or
-  CONFIG_INET_LRO_MODULE kernel config option. Additionally, if
-  CONFIG_INET_LRO_MODULE is used, the inet_lro module needs to be loaded
-  before the igb driver.
-
-  You can verify that the driver is using LRO by looking at these counters in
-  Ethtool:
-
-  lro_aggregated - count of total packets that were combined
-  lro_flushed - counts the number of packets flushed out of LRO
-  lro_no_desc - counts the number of times an LRO descriptor was not available
-  for the LRO packet
-
-  NOTE: IPv6 and UDP are not supported by LRO.
-
 Support
 =======
 
diff -druNp linux-libre-2.6.37-gnu1/Documentation/networking/igbvf.txt linux-libre-2.6.38-gnu1/Documentation/networking/igbvf.txt
--- linux-libre-2.6.37-gnu1/Documentation/networking/igbvf.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/networking/igbvf.txt	2011-03-14 21:20:32.000000000 -0400
@@ -58,9 +58,11 @@ Additional Configurations
   Ethtool
   -------
   The driver utilizes the ethtool interface for driver configuration and
-  diagnostics, as well as displaying statistical information.
+  diagnostics, as well as displaying statistical information.  The ethtool
+  version 3.0 or later is required for this functionality, although we
+  strongly recommend downloading the latest version at:
 
-  http://sourceforge.net/projects/gkernel.
+  http://ftp.kernel.org/pub/software/network/ethtool/
 
 Support
 =======
diff -druNp linux-libre-2.6.37-gnu1/Documentation/networking/ip-sysctl.txt linux-libre-2.6.38-gnu1/Documentation/networking/ip-sysctl.txt
--- linux-libre-2.6.37-gnu1/Documentation/networking/ip-sysctl.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/networking/ip-sysctl.txt	2011-03-14 21:20:32.000000000 -0400
@@ -11,7 +11,9 @@ ip_forward - BOOLEAN
 	for routers)
 
 ip_default_ttl - INTEGER
-	default 64
+	Default value of TTL field (Time To Live) for outgoing (but not
+	forwarded) IP packets. Should be between 1 and 255 inclusive.
+	Default: 64 (as recommended by RFC1700)
 
 ip_no_pmtu_disc - BOOLEAN
 	Disable Path MTU Discovery.
@@ -185,7 +187,7 @@ tcp_cookie_size - INTEGER
 tcp_dsack - BOOLEAN
 	Allows TCP to send "duplicate" SACKs.
 
-tcp_ecn - BOOLEAN
+tcp_ecn - INTEGER
 	Enable Explicit Congestion Notification (ECN) in TCP. ECN is only
 	used when both ends of the TCP flow support it. It is useful to
 	avoid losses due to congestion (when the bottleneck router supports
@@ -708,10 +710,28 @@ igmp_max_memberships - INTEGER
 	Change the maximum number of multicast groups we can subscribe to.
 	Default: 20
 
-conf/interface/*  changes special settings per interface (where "interface" is
-		  the name of your network interface)
-conf/all/*	  is special, changes the settings for all interfaces
+	Theoretical maximum value is bounded by having to send a membership
+	report in a single datagram (i.e. the report can't span multiple
+	datagrams, or risk confusing the switch and leaving groups you don't
+	intend to).
+
+	The number of supported groups 'M' is bounded by the number of group
+	report entries you can fit into a single datagram of 65535 bytes.
+
+	M = 65536-sizeof (ip header)/(sizeof(Group record))
+
+	Group records are variable length, with a minimum of 12 bytes.
+	So net.ipv4.igmp_max_memberships should not be set higher than:
+
+	(65536-24) / 12 = 5459
 
+	The value 5459 assumes no IP header options, so in practice
+	this number may be lower.
+
+	conf/interface/*  changes special settings per interface (where
+	"interface" is the name of your network interface)
+
+	conf/all/*	  is special, changes the settings for all interfaces
 
 log_martians - BOOLEAN
 	Log packets with impossible addresses to kernel log.
diff -druNp linux-libre-2.6.37-gnu1/Documentation/networking/ixgbe.txt linux-libre-2.6.38-gnu1/Documentation/networking/ixgbe.txt
--- linux-libre-2.6.37-gnu1/Documentation/networking/ixgbe.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/networking/ixgbe.txt	2011-03-14 21:20:32.000000000 -0400
@@ -1,107 +1,126 @@
 Linux Base Driver for 10 Gigabit PCI Express Intel(R) Network Connection
 ========================================================================
 
-March 10, 2009
-
+Intel Gigabit Linux driver.
+Copyright(c) 1999 - 2010 Intel Corporation.
 
 Contents
 ========
 
-- In This Release
 - Identifying Your Adapter
-- Building and Installation
 - Additional Configurations
+- Performance Tuning
+- Known Issues
 - Support
 
+Identifying Your Adapter
+========================
 
+The driver in this release is compatible with 82598 and 82599-based Intel
+Network Connections.
 
-In This Release
-===============
+For more information on how to identify your adapter, go to the Adapter &
+Driver ID Guide at:
 
-This file describes the ixgbe Linux Base Driver for the 10 Gigabit PCI
-Express Intel(R) Network Connection.  This driver includes support for
-Itanium(R)2-based systems.
+    http://support.intel.com/support/network/sb/CS-012904.htm
 
-For questions related to hardware requirements, refer to the documentation
-supplied with your 10 Gigabit adapter.  All hardware requirements listed apply
-to use with Linux.
+SFP+ Devices with Pluggable Optics
+----------------------------------
 
-The following features are available in this kernel:
- - Native VLANs
- - Channel Bonding (teaming)
- - SNMP
- - Generic Receive Offload
- - Data Center Bridging
+82599-BASED ADAPTERS
 
-Channel Bonding documentation can be found in the Linux kernel source:
-/Documentation/networking/bonding.txt
+NOTES: If your 82599-based Intel(R) Network Adapter came with Intel optics, or
+is an Intel(R) Ethernet Server Adapter X520-2, then it only supports Intel
+optics and/or the direct attach cables listed below.
 
-Ethtool, lspci, and ifconfig can be used to display device and driver
-specific information.
+When 82599-based SFP+ devices are connected back to back, they should be set to
+the same Speed setting via ethtool. Results may vary if you mix speed settings.
+82598-based adapters support all passive direct attach cables that comply
+with SFF-8431 v4.1 and SFF-8472 v10.4 specifications. Active direct attach
+cables are not supported.
 
+Supplier    Type                                             Part Numbers
 
-Identifying Your Adapter
-========================
+SR Modules
+Intel       DUAL RATE 1G/10G SFP+ SR (bailed)                FTLX8571D3BCV-IT
+Intel       DUAL RATE 1G/10G SFP+ SR (bailed)                AFBR-703SDDZ-IN1
+Intel       DUAL RATE 1G/10G SFP+ SR (bailed)                AFBR-703SDZ-IN2
+LR Modules
+Intel       DUAL RATE 1G/10G SFP+ LR (bailed)                FTLX1471D3BCV-IT
+Intel       DUAL RATE 1G/10G SFP+ LR (bailed)                AFCT-701SDDZ-IN1
+Intel       DUAL RATE 1G/10G SFP+ LR (bailed)                AFCT-701SDZ-IN2
 
-This driver supports devices based on the 82598 controller and the 82599
-controller.
+The following is a list of 3rd party SFP+ modules and direct attach cables that
+have received some testing. Not all modules are applicable to all devices.
 
-For specific information on identifying which adapter you have, please visit:
+Supplier   Type                                              Part Numbers
 
-    http://support.intel.com/support/network/sb/CS-008441.htm
+Finisar    SFP+ SR bailed, 10g single rate                   FTLX8571D3BCL
+Avago      SFP+ SR bailed, 10g single rate                   AFBR-700SDZ
+Finisar    SFP+ LR bailed, 10g single rate                   FTLX1471D3BCL
 
+Finisar    DUAL RATE 1G/10G SFP+ SR (No Bail)                FTLX8571D3QCV-IT
+Avago      DUAL RATE 1G/10G SFP+ SR (No Bail)                AFBR-703SDZ-IN1
+Finisar    DUAL RATE 1G/10G SFP+ LR (No Bail)                FTLX1471D3QCV-IT
+Avago      DUAL RATE 1G/10G SFP+ LR (No Bail)                AFCT-701SDZ-IN1
+Finistar   1000BASE-T SFP                                    FCLF8522P2BTL
+Avago      1000BASE-T SFP                                    ABCU-5710RZ
 
-Building and Installation
-=========================
+82599-based adapters support all passive and active limiting direct attach
+cables that comply with SFF-8431 v4.1 and SFF-8472 v10.4 specifications.
 
-select m for "Intel(R) 10GbE PCI Express adapters support" located at:
-      Location:
-        -> Device Drivers
-          -> Network device support (NETDEVICES [=y])
-            -> Ethernet (10000 Mbit) (NETDEV_10000 [=y])
+Laser turns off for SFP+ when ifconfig down
+-------------------------------------------
+"ifconfig down" turns off the laser for 82599-based SFP+ fiber adapters.
+"ifconfig up" turns on the later.
 
-1. make modules & make modules_install
 
-2. Load the module:
+82598-BASED ADAPTERS
 
-# modprobe ixgbe
+NOTES for 82598-Based Adapters:
+- Intel(R) Network Adapters that support removable optical modules only support
+  their original module type (i.e., the Intel(R) 10 Gigabit SR Dual Port
+  Express Module only supports SR optical modules). If you plug in a different
+  type of module, the driver will not load.
+- Hot Swapping/hot plugging optical modules is not supported.
+- Only single speed, 10 gigabit modules are supported.
+- LAN on Motherboard (LOMs) may support DA, SR, or LR modules. Other module
+  types are not supported. Please see your system documentation for details.
 
-   The insmod command can be used if the full
-   path to the driver module is specified.  For example:
+The following is a list of 3rd party SFP+ modules and direct attach cables that
+have received some testing. Not all modules are applicable to all devices.
 
-     insmod /lib/modules/<KERNEL VERSION>/kernel/drivers/net/ixgbe/ixgbe.ko
+Supplier   Type                                              Part Numbers
 
-   With 2.6 based kernels also make sure that older ixgbe drivers are
-   removed from the kernel, before loading the new module:
+Finisar    SFP+ SR bailed, 10g single rate                   FTLX8571D3BCL
+Avago      SFP+ SR bailed, 10g single rate                   AFBR-700SDZ
+Finisar    SFP+ LR bailed, 10g single rate                   FTLX1471D3BCL
 
-     rmmod ixgbe; modprobe ixgbe
+82598-based adapters support all passive direct attach cables that comply
+with SFF-8431 v4.1 and SFF-8472 v10.4 specifications. Active direct attach
+cables are not supported.
 
-3. Assign an IP address to the interface by entering the following, where
-   x is the interface number:
 
-     ifconfig ethx <IP_address>
+Flow Control
+------------
+Ethernet Flow Control (IEEE 802.3x) can be configured with ethtool to enable
+receiving and transmitting pause frames for ixgbe. When TX is enabled, PAUSE
+frames are generated when the receive packet buffer crosses a predefined
+threshold.  When rx is enabled, the transmit unit will halt for the time delay
+specified when a PAUSE frame is received.
 
-4. Verify that the interface works. Enter the following, where <IP_address>
-   is the IP address for another machine on the same subnet as the interface
-   that is being tested:
+Flow Control is enabled by default. If you want to disable a flow control
+capable link partner, use ethtool:
 
-     ping  <IP_address>
+     ethtool -A eth? autoneg off RX off TX off
 
+NOTE: For 82598 backplane cards entering 1 gig mode, flow control default
+behavior is changed to off.  Flow control in 1 gig mode on these devices can
+lead to Tx hangs.
 
 Additional Configurations
 =========================
 
-  Viewing Link Messages
-  ---------------------
-  Link messages will not be displayed to the console if the distribution is
-  restricting system messages. In order to see network driver link messages on
-  your console, set dmesg to eight by entering the following:
-
-       dmesg -n 8
-
-  NOTE: This setting is not saved across reboots.
-
-
   Jumbo Frames
   ------------
   The driver supports Jumbo Frames for all adapters. Jumbo Frames support is
@@ -123,13 +142,8 @@ Additional Configurations
   other protocols besides TCP.  It's also safe to use with configurations that
   are problematic for LRO, namely bridging and iSCSI.
 
-  GRO is enabled by default in the driver.  Future versions of ethtool will
-  support disabling and re-enabling GRO on the fly.
-
-
   Data Center Bridging, aka DCB
   -----------------------------
-
   DCB is a configuration Quality of Service implementation in hardware.
   It uses the VLAN priority tag (802.1p) to filter traffic.  That means
   that there are 8 different priorities that traffic can be filtered into.
@@ -163,24 +177,71 @@ Additional Configurations
 
         http://e1000.sf.net
 
-
   Ethtool
   -------
   The driver utilizes the ethtool interface for driver configuration and
-  diagnostics, as well as displaying statistical information.  Ethtool
-  version 3.0 or later is required for this functionality.
+  diagnostics, as well as displaying statistical information. The latest
+  ethtool version is required for this functionality.
 
   The latest release of ethtool can be found from
-  http://sourceforge.net/projects/gkernel.
-
+  http://ftp.kernel.org/pub/software/network/ethtool/
 
-  NAPI
+  FCoE
   ----
+  This release of the ixgbe driver contains new code to enable users to use
+  Fiber Channel over Ethernet (FCoE) and Data Center Bridging (DCB)
+  functionality that is supported by the 82598-based hardware.  This code has
+  no default effect on the regular driver operation, and configuring DCB and
+  FCoE is outside the scope of this driver README. Refer to
+  http://www.open-fcoe.org/ for FCoE project information and contact
+  e1000-eedc@lists.sourceforge.net for DCB information.
 
-  NAPI (Rx polling mode) is supported in the ixgbe driver.  NAPI is enabled
-  by default in the driver.
+  MAC and VLAN anti-spoofing feature
+  ----------------------------------
+  When a malicious driver attempts to send a spoofed packet, it is dropped by
+  the hardware and not transmitted.  An interrupt is sent to the PF driver
+  notifying it of the spoof attempt.
 
-  See www.cyberus.ca/~hadi/usenix-paper.tgz for more information on NAPI.
+  When a spoofed packet is detected the PF driver will send the following
+  message to the system log (displayed by  the "dmesg" command):
+
+  Spoof event(s) detected on VF (n)
+
+  Where n=the VF that attempted to do the spoofing.
+
+
+Performance Tuning
+==================
+
+An excellent article on performance tuning can be found at:
+
+http://www.redhat.com/promo/summit/2008/downloads/pdf/Thursday/Mark_Wagner.pdf
+
+
+Known Issues
+============
+
+  Enabling SR-IOV in a 32-bit Microsoft* Windows* Server 2008 Guest OS using
+  Intel (R) 82576-based GbE or Intel (R) 82599-based 10GbE controller under KVM
+  -----------------------------------------------------------------------------
+  KVM Hypervisor/VMM supports direct assignment of a PCIe device to a VM.  This
+  includes traditional PCIe devices, as well as SR-IOV-capable devices using
+  Intel 82576-based and 82599-based controllers.
+
+  While direct assignment of a PCIe device or an SR-IOV Virtual Function (VF)
+  to a Linux-based VM running 2.6.32 or later kernel works fine, there is a
+  known issue with Microsoft Windows Server 2008 VM that results in a "yellow
+  bang" error. This problem is within the KVM VMM itself, not the Intel driver,
+  or the SR-IOV logic of the VMM, but rather that KVM emulates an older CPU
+  model for the guests, and this older CPU model does not support MSI-X
+  interrupts, which is a requirement for Intel SR-IOV.
+
+  If you wish to use the Intel 82576 or 82599-based controllers in SR-IOV mode
+  with KVM and a Microsoft Windows Server 2008 guest try the following
+  workaround. The workaround is to tell KVM to emulate a different model of CPU
+  when using qemu to create the KVM guest:
+
+       "-cpu qemu64,model=13"
 
 
 Support
diff -druNp linux-libre-2.6.37-gnu1/Documentation/networking/ixgbevf.txt linux-libre-2.6.38-gnu1/Documentation/networking/ixgbevf.txt
--- linux-libre-2.6.37-gnu1/Documentation/networking/ixgbevf.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/networking/ixgbevf.txt	2011-03-14 21:20:32.000000000 -0400
@@ -35,10 +35,6 @@ Driver ID Guide at:
 Known Issues/Troubleshooting
 ============================
 
-  Unloading Physical Function (PF) Driver Causes System Reboots When VM is
-  Running and VF is Loaded on the VM
-  ------------------------------------------------------------------------
-  Do not unload the PF driver (ixgbe) while VFs are assigned to guests.
 
 Support
 =======
diff -druNp linux-libre-2.6.37-gnu1/Documentation/networking/ixgb.txt linux-libre-2.6.38-gnu1/Documentation/networking/ixgb.txt
--- linux-libre-2.6.37-gnu1/Documentation/networking/ixgb.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/networking/ixgb.txt	2011-03-14 21:20:32.000000000 -0400
@@ -309,15 +309,15 @@ Additional Configurations
   Ethtool
   -------
   The driver utilizes the ethtool interface for driver configuration and
-  diagnostics, as well as displaying statistical information.  Ethtool
+  diagnostics, as well as displaying statistical information.  The ethtool
   version 1.6 or later is required for this functionality.
 
   The latest release of ethtool can be found from
-  http://sourceforge.net/projects/gkernel
+  http://ftp.kernel.org/pub/software/network/ethtool/
 
-  NOTE: Ethtool 1.6 only supports a limited set of ethtool options. Support
-        for a more complete ethtool feature set can be enabled by upgrading
-        to the latest version.
+  NOTE: The ethtool version 1.6 only supports a limited set of ethtool options.
+        Support for a more complete ethtool feature set can be enabled by
+        upgrading to the latest version.
 
 
   NAPI
diff -druNp linux-libre-2.6.37-gnu1/Documentation/networking/LICENSE.qlcnic linux-libre-2.6.38-gnu1/Documentation/networking/LICENSE.qlcnic
--- linux-libre-2.6.37-gnu1/Documentation/networking/LICENSE.qlcnic	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/networking/LICENSE.qlcnic	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,327 @@
+Copyright (c) 2009-2010 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
+
+ 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-2.6.37-gnu1/Documentation/networking/Makefile linux-libre-2.6.38-gnu1/Documentation/networking/Makefile
--- linux-libre-2.6.37-gnu1/Documentation/networking/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/networking/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -4,6 +4,8 @@ obj- := dummy.o
 # List of programs to build
 hostprogs-y := ifenslave
 
+HOSTCFLAGS_ifenslave.o += -I$(objtree)/usr/include
+
 # Tell kbuild to always build the programs
 always := $(hostprogs-y)
 
diff -druNp linux-libre-2.6.37-gnu1/Documentation/networking/stmmac.txt linux-libre-2.6.38-gnu1/Documentation/networking/stmmac.txt
--- linux-libre-2.6.37-gnu1/Documentation/networking/stmmac.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/networking/stmmac.txt	2011-03-14 21:20:32.000000000 -0400
@@ -7,7 +7,7 @@ This is the driver for the MAC 10/100/10
 (Synopsys IP blocks); it has been fully tested on STLinux platforms.
 
 Currently this network device driver is for all STM embedded MAC/GMAC
-(7xxx SoCs).
+(7xxx SoCs). Other platforms start using it i.e. ARM SPEAr.
 
 DWC Ether MAC 10/100/1000 Universal version 3.41a and DWC Ether MAC 10/100
 Universal version 4.0 have been used for developing the first code
@@ -95,9 +95,14 @@ Several information came from the platfo
 driver's Header file in include/linux directory.
 
 struct plat_stmmacenet_data {
-        int bus_id;
-        int pbl;
-        int has_gmac;
+	int bus_id;
+	int pbl;
+	int clk_csr;
+	int has_gmac;
+	int enh_desc;
+	int tx_coe;
+	int bugged_jumbo;
+	int pmt;
         void (*fix_mac_speed)(void *priv, unsigned int speed);
         void (*bus_setup)(unsigned long ioaddr);
 #ifdef CONFIG_STM_DRIVERS
@@ -114,6 +119,12 @@ Where:
   registers (on STM platforms);
 - has_gmac: GMAC core is on board (get it at run-time in the next step);
 - bus_id: bus identifier.
+- tx_coe: core is able to perform the tx csum in HW.
+- enh_desc: if sets the MAC will use the enhanced descriptor structure.
+- clk_csr: CSR Clock range selection.
+- bugged_jumbo: some HWs are not able to perform the csum in HW for
+  over-sized frames due to limited buffer sizes. Setting this
+  flag the csum will be done in SW on JUMBO frames.
 
 struct plat_stmmacphy_data {
         int bus_id;
@@ -131,13 +142,28 @@ Where:
 - interface: physical MII interface mode;
 - phy_reset: hook to reset HW function.
 
+SOURCES:
+- Kconfig
+- Makefile
+- stmmac_main.c: main network device driver;
+- stmmac_mdio.c: mdio functions;
+- stmmac_ethtool.c: ethtool support;
+- stmmac_timer.[ch]: timer code used for mitigating the driver dma interrupts
+  Only tested on ST40 platforms based.
+- stmmac.h: private driver structure;
+- common.h: common definitions and VFTs;
+- descs.h: descriptor structure definitions;
+- dwmac1000_core.c: GMAC core functions;
+- dwmac1000_dma.c:  dma functions for the GMAC chip;
+- dwmac1000.h: specific header file for the GMAC;
+- dwmac100_core: MAC 100 core and dma code;
+- dwmac100_dma.c: dma funtions for the MAC chip;
+- dwmac1000.h: specific header file for the MAC;
+- dwmac_lib.c: generic DMA functions shared among chips
+- enh_desc.c: functions for handling enhanced descriptors
+- norm_desc.c: functions for handling normal descriptors
+
 TODO:
-- Continue to make the driver more generic and suitable for other Synopsys
-  Ethernet controllers used on other architectures (i.e. ARM).
-- 10G controllers are not supported.
-- MAC uses Normal descriptors and GMAC uses enhanced ones.
-  This is a limit that should be reviewed. MAC could want to
-  use the enhanced structure.
-- Checksumming: Rx/Tx csum is done in HW in case of GMAC only.
+- XGMAC controller is not supported.
 - Review the timer optimisation code to use an embedded device that seems to be
   available in new chip generations.
diff -druNp linux-libre-2.6.37-gnu1/Documentation/nfc/nfc-pn544.txt linux-libre-2.6.38-gnu1/Documentation/nfc/nfc-pn544.txt
--- linux-libre-2.6.37-gnu1/Documentation/nfc/nfc-pn544.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/nfc/nfc-pn544.txt	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,114 @@
+Kernel driver for the NXP Semiconductors PN544 Near Field
+Communication chip
+
+Author: Jari Vanhala
+Contact: Matti Aaltonen (matti.j.aaltonen at nokia.com)
+
+General
+-------
+
+The PN544 is an integrated transmission module for contactless
+communication. The driver goes under drives/nfc/ and is compiled as a
+module named "pn544". It registers a misc device and creates a device
+file named "/dev/pn544".
+
+Host Interfaces: I2C, SPI and HSU, this driver supports currently only I2C.
+
+The Interface
+-------------
+
+The driver offers a sysfs interface for a hardware test and an IOCTL
+interface for selecting between two operating modes. There are read,
+write and poll functions for transferring messages. The two operating
+modes are the normal (HCI) mode and the firmware update mode.
+
+PN544 is controlled by sending messages from the userspace to the
+chip. The main function of the driver is just to pass those messages
+without caring about the message content.
+
+
+Protocols
+---------
+
+In the normal (HCI) mode and in the firmware update mode read and
+write functions behave a bit differently because the message formats
+or the protocols are different.
+
+In the normal (HCI) mode the protocol used is derived from the ETSI
+HCI specification. The firmware is updated using a specific protocol,
+which is different from HCI.
+
+HCI messages consist of an eight bit header and the message body. The
+header contains the message length. Maximum size for an HCI message is
+33. In HCI mode sent messages are tested for a correct
+checksum. Firmware update messages have the length in the second (MSB)
+and third (LSB) bytes of the message. The maximum FW message length is
+1024 bytes.
+
+For the ETSI HCI specification see
+http://www.etsi.org/WebSite/Technologies/ProtocolSpecification.aspx
+
+The Hardware Test
+-----------------
+
+The idea of the test is that it can performed by reading from the
+corresponding sysfs file. The test is implemented in the board file
+and it should test that PN544 can be put into the firmware update
+mode. If the test is not implemented the sysfs file does not get
+created.
+
+Example:
+> cat /sys/module/pn544/drivers/i2c\:pn544/3-002b/nfc_test
+1
+
+Normal Operation
+----------------
+
+PN544 is powered up when the device file is opened, otherwise it's
+turned off. Only one instance can use the device at a time.
+
+Userspace applications control PN544 with HCI messages. The hardware
+sends an interrupt when data is available for reading. Data is
+physically read when the read function is called by a userspace
+application. Poll() checks the read interrupt state. Configuration and
+self testing are also done from the userspace using read and write.
+
+Example platform data:
+
+static int rx71_pn544_nfc_request_resources(struct i2c_client *client)
+{
+	/* Get and setup the HW resources for the device */
+}
+
+static void rx71_pn544_nfc_free_resources(void)
+{
+	/* Release the HW resources */
+}
+
+static void rx71_pn544_nfc_enable(int fw)
+{
+	/* Turn the device on */
+}
+
+static int rx71_pn544_nfc_test(void)
+{
+	/*
+	 * Put the device into the FW update mode
+	 * and then back to the normal mode.
+	 * Check the behavior and return one on success,
+	 * zero on failure.
+	 */
+}
+
+static void rx71_pn544_nfc_disable(void)
+{
+	/* turn the power off */
+}
+
+static struct pn544_nfc_platform_data rx71_nfc_data = {
+	.request_resources = rx71_pn544_nfc_request_resources,
+	.free_resources = rx71_pn544_nfc_free_resources,
+	.enable = rx71_pn544_nfc_enable,
+	.test = rx71_pn544_nfc_test,
+	.disable = rx71_pn544_nfc_disable,
+};
diff -druNp linux-libre-2.6.37-gnu1/Documentation/power/drivers-testing.txt linux-libre-2.6.38-gnu1/Documentation/power/drivers-testing.txt
--- linux-libre-2.6.37-gnu1/Documentation/power/drivers-testing.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/power/drivers-testing.txt	2011-03-14 21:20:32.000000000 -0400
@@ -23,10 +23,10 @@ Once you have resolved the suspend/resum
 without the new driver, you are ready to test it:
 
 a) Build the driver as a module, load it and try the test modes of hibernation
-   (see: Documents/power/basic-pm-debugging.txt, 1).
+   (see: Documentation/power/basic-pm-debugging.txt, 1).
 
 b) Load the driver and attempt to hibernate in the "reboot", "shutdown" and
-   "platform" modes (see: Documents/power/basic-pm-debugging.txt, 1).
+   "platform" modes (see: Documentation/power/basic-pm-debugging.txt, 1).
 
 c) Compile the driver directly into the kernel and try the test modes of
    hibernation.
@@ -34,12 +34,12 @@ c) Compile the driver directly into the
 d) Attempt to hibernate with the driver compiled directly into the kernel
    in the "reboot", "shutdown" and "platform" modes.
 
-e) Try the test modes of suspend (see: Documents/power/basic-pm-debugging.txt,
+e) Try the test modes of suspend (see: Documentation/power/basic-pm-debugging.txt,
    2).  [As far as the STR tests are concerned, it should not matter whether or
    not the driver is built as a module.]
 
 f) Attempt to suspend to RAM using the s2ram tool with the driver loaded
-   (see: Documents/power/basic-pm-debugging.txt, 2).
+   (see: Documentation/power/basic-pm-debugging.txt, 2).
 
 Each of the above tests should be repeated several times and the STD tests
 should be mixed with the STR tests.  If any of them fails, the driver cannot be
diff -druNp linux-libre-2.6.37-gnu1/Documentation/power/runtime_pm.txt linux-libre-2.6.38-gnu1/Documentation/power/runtime_pm.txt
--- linux-libre-2.6.37-gnu1/Documentation/power/runtime_pm.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/power/runtime_pm.txt	2011-03-14 21:20:32.000000000 -0400
@@ -50,6 +50,15 @@ type's callbacks are not defined) of giv
 and device 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
+(->runtime_idle() is still invoked the default way).  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.
+
 The subsystem-level suspend callback is _entirely_ _responsible_ for handling
 the suspend of the device as appropriate, which may, but need not include
 executing the device driver's own ->runtime_suspend() callback (from the
@@ -237,6 +246,10 @@ defined in include/linux/pm.h:
       Section 8); it may be modified only by the pm_runtime_no_callbacks()
       helper function
 
+  unsigned int irq_safe;
+    - indicates that the ->runtime_suspend() and ->runtime_resume() callbacks
+      will be invoked with the spinlock held and interrupts disabled
+
   unsigned int use_autosuspend;
     - indicates that the device's driver supports delayed autosuspend (see
       Section 9); it may be modified only by the
@@ -344,6 +357,10 @@ drivers/base/power/runtime.c and include
     - decrement the device's usage counter; if the result is 0 then run
       pm_runtime_idle(dev) and return its result
 
+  int pm_runtime_put_sync_suspend(struct device *dev);
+    - decrement the device's usage counter; if the result is 0 then run
+      pm_runtime_suspend(dev) and return its result
+
   int pm_runtime_put_sync_autosuspend(struct device *dev);
     - decrement the device's usage counter; if the result is 0 then run
       pm_runtime_autosuspend(dev) and return its result
@@ -397,6 +414,11 @@ drivers/base/power/runtime.c and include
       PM attributes from /sys/devices/.../power (or prevent them from being
       added when the device is registered)
 
+  void pm_runtime_irq_safe(struct device *dev);
+    - set the power.irq_safe flag for the device, causing the runtime-PM
+      suspend and resume callbacks (but not the idle callback) to be invoked
+      with interrupts disabled
+
   void pm_runtime_mark_last_busy(struct device *dev);
     - set the power.last_busy field to the current time
 
@@ -438,6 +460,15 @@ pm_runtime_suspended()
 pm_runtime_mark_last_busy()
 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_suspend()
+pm_runtime_autosuspend()
+pm_runtime_resume()
+pm_runtime_get_sync()
+pm_runtime_put_sync_suspend()
+
 5. Run-time PM Initialization, Device Probing and Removal
 
 Initially, the run-time PM is disabled for all devices, which means that the
diff -druNp linux-libre-2.6.37-gnu1/Documentation/powerpc/booting-without-of.txt linux-libre-2.6.38-gnu1/Documentation/powerpc/booting-without-of.txt
--- linux-libre-2.6.37-gnu1/Documentation/powerpc/booting-without-of.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/powerpc/booting-without-of.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,1447 +0,0 @@
-           Booting the Linux/ppc kernel without Open Firmware
-           --------------------------------------------------
-
-(c) 2005 Benjamin Herrenschmidt <benh at kernel.crashing.org>,
-    IBM Corp.
-(c) 2005 Becky Bruce <becky.bruce at freescale.com>,
-    Freescale Semiconductor, FSL SOC and 32-bit additions
-(c) 2006 MontaVista Software, Inc.
-    Flash chip node definition
-
-Table of Contents
-=================
-
-  I - Introduction
-    1) Entry point for arch/powerpc
-    2) Board support
-
-  II - The DT block format
-    1) Header
-    2) Device tree generalities
-    3) Device tree "structure" block
-    4) Device tree "strings" block
-
-  III - Required content of the device tree
-    1) Note about cells and address representation
-    2) Note about "compatible" properties
-    3) Note about "name" properties
-    4) Note about node and property names and character set
-    5) Required nodes and properties
-      a) The root node
-      b) The /cpus node
-      c) The /cpus/* nodes
-      d) the /memory node(s)
-      e) The /chosen node
-      f) the /soc<SOCname> node
-
-  IV - "dtc", the device tree compiler
-
-  V - Recommendations for a bootloader
-
-  VI - System-on-a-chip devices and nodes
-    1) Defining child nodes of an SOC
-    2) Representing devices without a current OF specification
-      a) PHY nodes
-      b) Interrupt controllers
-      c) 4xx/Axon EMAC ethernet nodes
-      d) Xilinx IP cores
-      e) USB EHCI controllers
-      f) MDIO on GPIOs
-      g) SPI busses
-
-  VII - Specifying interrupt information for devices
-    1) interrupts property
-    2) interrupt-parent property
-    3) OpenPIC Interrupt Controllers
-    4) ISA Interrupt Controllers
-
-  VIII - Specifying device power management information (sleep property)
-
-  Appendix A - Sample SOC node for MPC8540
-
-
-Revision Information
-====================
-
-   May 18, 2005: Rev 0.1 - Initial draft, no chapter III yet.
-
-   May 19, 2005: Rev 0.2 - Add chapter III and bits & pieces here or
-                           clarifies the fact that a lot of things are
-                           optional, the kernel only requires a very
-                           small device tree, though it is encouraged
-                           to provide an as complete one as possible.
-
-   May 24, 2005: Rev 0.3 - Precise that DT block has to be in RAM
-			 - Misc fixes
-			 - Define version 3 and new format version 16
-			   for the DT block (version 16 needs kernel
-			   patches, will be fwd separately).
-			   String block now has a size, and full path
-			   is replaced by unit name for more
-			   compactness.
-			   linux,phandle is made optional, only nodes
-			   that are referenced by other nodes need it.
-			   "name" property is now automatically
-			   deduced from the unit name
-
-   June 1, 2005: Rev 0.4 - Correct confusion between OF_DT_END and
-                           OF_DT_END_NODE in structure definition.
-                         - Change version 16 format to always align
-                           property data to 4 bytes. Since tokens are
-                           already aligned, that means no specific
-                           required alignment between property size
-                           and property data. The old style variable
-                           alignment would make it impossible to do
-                           "simple" insertion of properties using
-                           memmove (thanks Milton for
-                           noticing). Updated kernel patch as well
-			 - Correct a few more alignment constraints
-			 - Add a chapter about the device-tree
-                           compiler and the textural representation of
-                           the tree that can be "compiled" by dtc.
-
-   November 21, 2005: Rev 0.5
-			 - Additions/generalizations for 32-bit
-			 - Changed to reflect the new arch/powerpc
-			   structure
-			 - Added chapter VI
-
-
- ToDo:
-	- Add some definitions of interrupt tree (simple/complex)
-	- Add some definitions for PCI host bridges
-	- Add some common address format examples
-	- Add definitions for standard properties and "compatible"
-	  names for cells that are not already defined by the existing
-	  OF spec.
-	- Compare FSL SOC use of PCI to standard and make sure no new
-	  node definition required.
-	- Add more information about node definitions for SOC devices
-  	  that currently have no standard, like the FSL CPM.
-
-
-I - Introduction
-================
-
-During the recent development of the Linux/ppc64 kernel, and more
-specifically, the addition of new platform types outside of the old
-IBM pSeries/iSeries pair, it was decided to enforce some strict rules
-regarding the kernel entry and bootloader <-> kernel interfaces, in
-order to avoid the degeneration that had become the ppc32 kernel entry
-point and the way a new platform should be added to the kernel. The
-legacy iSeries platform breaks those rules as it predates this scheme,
-but no new board support will be accepted in the main tree that
-doesn't follows them properly.  In addition, since the advent of the
-arch/powerpc merged architecture for ppc32 and ppc64, new 32-bit
-platforms and 32-bit platforms which move into arch/powerpc will be
-required to use these rules as well.
-
-The main requirement that will be defined in more detail below is
-the presence of a device-tree whose format is defined after Open
-Firmware specification. However, in order to make life easier
-to embedded board vendors, the kernel doesn't require the device-tree
-to represent every device in the system and only requires some nodes
-and properties to be present. This will be described in detail in
-section III, but, for example, the kernel does not require you to
-create a node for every PCI device in the system. It is a requirement
-to have a node for PCI host bridges in order to provide interrupt
-routing informations and memory/IO ranges, among others. It is also
-recommended to define nodes for on chip devices and other busses that
-don't specifically fit in an existing OF specification. This creates a
-great flexibility in the way the kernel can then probe those and match
-drivers to device, without having to hard code all sorts of tables. It
-also makes it more flexible for board vendors to do minor hardware
-upgrades without significantly impacting the kernel code or cluttering
-it with special cases.
-
-
-1) Entry point for arch/powerpc
--------------------------------
-
-   There is one and one single entry point to the kernel, at the start
-   of the kernel image. That entry point supports two calling
-   conventions:
-
-        a) Boot from Open Firmware. If your firmware is compatible
-        with Open Firmware (IEEE 1275) or provides an OF compatible
-        client interface API (support for "interpret" callback of
-        forth words isn't required), you can enter the kernel with:
-
-              r5 : OF callback pointer as defined by IEEE 1275
-              bindings to powerpc. Only the 32-bit client interface
-              is currently supported
-
-              r3, r4 : address & length of an initrd if any or 0
-
-              The MMU is either on or off; the kernel will run the
-              trampoline located in arch/powerpc/kernel/prom_init.c to
-              extract the device-tree and other information from open
-              firmware and build a flattened device-tree as described
-              in b). prom_init() will then re-enter the kernel using
-              the second method. This trampoline code runs in the
-              context of the firmware, which is supposed to handle all
-              exceptions during that time.
-
-        b) Direct entry with a flattened device-tree block. This entry
-        point is called by a) after the OF trampoline and can also be
-        called directly by a bootloader that does not support the Open
-        Firmware client interface. It is also used by "kexec" to
-        implement "hot" booting of a new kernel from a previous
-        running one. This method is what I will describe in more
-        details in this document, as method a) is simply standard Open
-        Firmware, and thus should be implemented according to the
-        various standard documents defining it and its binding to the
-        PowerPC platform. The entry point definition then becomes:
-
-                r3 : physical pointer to the device-tree block
-                (defined in chapter II) in RAM
-
-                r4 : physical pointer to the kernel itself. This is
-                used by the assembly code to properly disable the MMU
-                in case you are entering the kernel with MMU enabled
-                and a non-1:1 mapping.
-
-                r5 : NULL (as to differentiate with method a)
-
-        Note about SMP entry: Either your firmware puts your other
-        CPUs in some sleep loop or spin loop in ROM where you can get
-        them out via a soft reset or some other means, in which case
-        you don't need to care, or you'll have to enter the kernel
-        with all CPUs. The way to do that with method b) will be
-        described in a later revision of this document.
-
-
-2) Board support
-----------------
-
-64-bit kernels:
-
-   Board supports (platforms) are not exclusive config options. An
-   arbitrary set of board supports can be built in a single kernel
-   image. The kernel will "know" what set of functions to use for a
-   given platform based on the content of the device-tree. Thus, you
-   should:
-
-        a) add your platform support as a _boolean_ option in
-        arch/powerpc/Kconfig, following the example of PPC_PSERIES,
-        PPC_PMAC and PPC_MAPLE. The later is probably a good
-        example of a board support to start from.
-
-        b) create your main platform file as
-        "arch/powerpc/platforms/myplatform/myboard_setup.c" and add it
-        to the Makefile under the condition of your CONFIG_
-        option. This file will define a structure of type "ppc_md"
-        containing the various callbacks that the generic code will
-        use to get to your platform specific code
-
-        c) Add a reference to your "ppc_md" structure in the
-        "machines" table in arch/powerpc/kernel/setup_64.c if you are
-        a 64-bit platform.
-
-        d) request and get assigned a platform number (see PLATFORM_*
-        constants in arch/powerpc/include/asm/processor.h
-
-32-bit embedded kernels:
-
-  Currently, board support is essentially an exclusive config option.
-  The kernel is configured for a single platform.  Part of the reason
-  for this is to keep kernels on embedded systems small and efficient;
-  part of this is due to the fact the code is already that way. In the
-  future, a kernel may support multiple platforms, but only if the
-  platforms feature the same core architecture.  A single kernel build
-  cannot support both configurations with Book E and configurations
-  with classic Powerpc architectures.
-
-  32-bit embedded platforms that are moved into arch/powerpc using a
-  flattened device tree should adopt the merged tree practice of
-  setting ppc_md up dynamically, even though the kernel is currently
-  built with support for only a single platform at a time.  This allows
-  unification of the setup code, and will make it easier to go to a
-  multiple-platform-support model in the future.
-
-NOTE: I believe the above will be true once Ben's done with the merge
-of the boot sequences.... someone speak up if this is wrong!
-
-  To add a 32-bit embedded platform support, follow the instructions
-  for 64-bit platforms above, with the exception that the Kconfig
-  option should be set up such that the kernel builds exclusively for
-  the platform selected.  The processor type for the platform should
-  enable another config option to select the specific board
-  supported.
-
-NOTE: If Ben doesn't merge the setup files, may need to change this to
-point to setup_32.c
-
-
-   I will describe later the boot process and various callbacks that
-   your platform should implement.
-
-
-II - The DT block format
-========================
-
-
-This chapter defines the actual format of the flattened device-tree
-passed to the kernel. The actual content of it and kernel requirements
-are described later. You can find example of code manipulating that
-format in various places, including arch/powerpc/kernel/prom_init.c
-which will generate a flattened device-tree from the Open Firmware
-representation, or the fs2dt utility which is part of the kexec tools
-which will generate one from a filesystem representation. It is
-expected that a bootloader like uboot provides a bit more support,
-that will be discussed later as well.
-
-Note: The block has to be in main memory. It has to be accessible in
-both real mode and virtual mode with no mapping other than main
-memory. If you are writing a simple flash bootloader, it should copy
-the block to RAM before passing it to the kernel.
-
-
-1) Header
----------
-
-   The kernel is entered with r3 pointing to an area of memory that is
-   roughly described in arch/powerpc/include/asm/prom.h by the structure
-   boot_param_header:
-
-struct boot_param_header {
-        u32     magic;                  /* magic word OF_DT_HEADER */
-        u32     totalsize;              /* total size of DT block */
-        u32     off_dt_struct;          /* offset to structure */
-        u32     off_dt_strings;         /* offset to strings */
-        u32     off_mem_rsvmap;         /* offset to memory reserve map
-                                           */
-        u32     version;                /* format version */
-        u32     last_comp_version;      /* last compatible version */
-
-        /* version 2 fields below */
-        u32     boot_cpuid_phys;        /* Which physical CPU id we're
-                                           booting on */
-        /* version 3 fields below */
-        u32     size_dt_strings;        /* size of the strings block */
-
-        /* version 17 fields below */
-        u32	size_dt_struct;		/* size of the DT structure block */
-};
-
-   Along with the constants:
-
-/* Definitions used by the flattened device tree */
-#define OF_DT_HEADER            0xd00dfeed      /* 4: version,
-						   4: total size */
-#define OF_DT_BEGIN_NODE        0x1             /* Start node: full name
-						   */
-#define OF_DT_END_NODE          0x2             /* End node */
-#define OF_DT_PROP              0x3             /* Property: name off,
-                                                   size, content */
-#define OF_DT_END               0x9
-
-   All values in this header are in big endian format, the various
-   fields in this header are defined more precisely below. All
-   "offset" values are in bytes from the start of the header; that is
-   from the value of r3.
-
-   - magic
-
-     This is a magic value that "marks" the beginning of the
-     device-tree block header. It contains the value 0xd00dfeed and is
-     defined by the constant OF_DT_HEADER
-
-   - totalsize
-
-     This is the total size of the DT block including the header. The
-     "DT" block should enclose all data structures defined in this
-     chapter (who are pointed to by offsets in this header). That is,
-     the device-tree structure, strings, and the memory reserve map.
-
-   - off_dt_struct
-
-     This is an offset from the beginning of the header to the start
-     of the "structure" part the device tree. (see 2) device tree)
-
-   - off_dt_strings
-
-     This is an offset from the beginning of the header to the start
-     of the "strings" part of the device-tree
-
-   - off_mem_rsvmap
-
-     This is an offset from the beginning of the header to the start
-     of the reserved memory map. This map is a list of pairs of 64-
-     bit integers. Each pair is a physical address and a size. The
-     list is terminated by an entry of size 0. This map provides the
-     kernel with a list of physical memory areas that are "reserved"
-     and thus not to be used for memory allocations, especially during
-     early initialization. The kernel needs to allocate memory during
-     boot for things like un-flattening the device-tree, allocating an
-     MMU hash table, etc... Those allocations must be done in such a
-     way to avoid overriding critical things like, on Open Firmware
-     capable machines, the RTAS instance, or on some pSeries, the TCE
-     tables used for the iommu. Typically, the reserve map should
-     contain _at least_ this DT block itself (header,total_size). If
-     you are passing an initrd to the kernel, you should reserve it as
-     well. You do not need to reserve the kernel image itself. The map
-     should be 64-bit aligned.
-
-   - version
-
-     This is the version of this structure. Version 1 stops
-     here. Version 2 adds an additional field boot_cpuid_phys.
-     Version 3 adds the size of the strings block, allowing the kernel
-     to reallocate it easily at boot and free up the unused flattened
-     structure after expansion. Version 16 introduces a new more
-     "compact" format for the tree itself that is however not backward
-     compatible. Version 17 adds an additional field, size_dt_struct,
-     allowing it to be reallocated or moved more easily (this is
-     particularly useful for bootloaders which need to make
-     adjustments to a device tree based on probed information). You
-     should always generate a structure of the highest version defined
-     at the time of your implementation. Currently that is version 17,
-     unless you explicitly aim at being backward compatible.
-
-   - last_comp_version
-
-     Last compatible version. This indicates down to what version of
-     the DT block you are backward compatible. For example, version 2
-     is backward compatible with version 1 (that is, a kernel build
-     for version 1 will be able to boot with a version 2 format). You
-     should put a 1 in this field if you generate a device tree of
-     version 1 to 3, or 16 if you generate a tree of version 16 or 17
-     using the new unit name format.
-
-   - boot_cpuid_phys
-
-     This field only exist on version 2 headers. It indicate which
-     physical CPU ID is calling the kernel entry point. This is used,
-     among others, by kexec. If you are on an SMP system, this value
-     should match the content of the "reg" property of the CPU node in
-     the device-tree corresponding to the CPU calling the kernel entry
-     point (see further chapters for more informations on the required
-     device-tree contents)
-
-   - size_dt_strings
-
-     This field only exists on version 3 and later headers.  It
-     gives the size of the "strings" section of the device tree (which
-     starts at the offset given by off_dt_strings).
-
-   - size_dt_struct
-
-     This field only exists on version 17 and later headers.  It gives
-     the size of the "structure" section of the device tree (which
-     starts at the offset given by off_dt_struct).
-
-   So the typical layout of a DT block (though the various parts don't
-   need to be in that order) looks like this (addresses go from top to
-   bottom):
-
-
-             ------------------------------
-       r3 -> |  struct boot_param_header  |
-             ------------------------------
-             |      (alignment gap) (*)   |
-             ------------------------------
-             |      memory reserve map    |
-             ------------------------------
-             |      (alignment gap)       |
-             ------------------------------
-             |                            |
-             |    device-tree structure   |
-             |                            |
-             ------------------------------
-             |      (alignment gap)       |
-             ------------------------------
-             |                            |
-             |     device-tree strings    |
-             |                            |
-      -----> ------------------------------
-      |
-      |
-      --- (r3 + totalsize)
-
-  (*) The alignment gaps are not necessarily present; their presence
-      and size are dependent on the various alignment requirements of
-      the individual data blocks.
-
-
-2) Device tree generalities
----------------------------
-
-This device-tree itself is separated in two different blocks, a
-structure block and a strings block. Both need to be aligned to a 4
-byte boundary.
-
-First, let's quickly describe the device-tree concept before detailing
-the storage format. This chapter does _not_ describe the detail of the
-required types of nodes & properties for the kernel, this is done
-later in chapter III.
-
-The device-tree layout is strongly inherited from the definition of
-the Open Firmware IEEE 1275 device-tree. It's basically a tree of
-nodes, each node having two or more named properties. A property can
-have a value or not.
-
-It is a tree, so each node has one and only one parent except for the
-root node who has no parent.
-
-A node has 2 names. The actual node name is generally contained in a
-property of type "name" in the node property list whose value is a
-zero terminated string and is mandatory for version 1 to 3 of the
-format definition (as it is in Open Firmware). Version 16 makes it
-optional as it can generate it from the unit name defined below.
-
-There is also a "unit name" that is used to differentiate nodes with
-the same name at the same level, it is usually made of the node
-names, the "@" sign, and a "unit address", which definition is
-specific to the bus type the node sits on.
-
-The unit name doesn't exist as a property per-se but is included in
-the device-tree structure. It is typically used to represent "path" in
-the device-tree. More details about the actual format of these will be
-below.
-
-The kernel powerpc generic code does not make any formal use of the
-unit address (though some board support code may do) so the only real
-requirement here for the unit address is to ensure uniqueness of
-the node unit name at a given level of the tree. Nodes with no notion
-of address and no possible sibling of the same name (like /memory or
-/cpus) may omit the unit address in the context of this specification,
-or use the "@0" default unit address. The unit name is used to define
-a node "full path", which is the concatenation of all parent node
-unit names separated with "/".
-
-The root node doesn't have a defined name, and isn't required to have
-a name property either if you are using version 3 or earlier of the
-format. It also has no unit address (no @ symbol followed by a unit
-address). The root node unit name is thus an empty string. The full
-path to the root node is "/".
-
-Every node which actually represents an actual device (that is, a node
-which isn't only a virtual "container" for more nodes, like "/cpus"
-is) is also required to have a "device_type" property indicating the
-type of node .
-
-Finally, every node that can be referenced from a property in another
-node is required to have a "linux,phandle" property. Real open
-firmware implementations provide a unique "phandle" value for every
-node that the "prom_init()" trampoline code turns into
-"linux,phandle" properties. However, this is made optional if the
-flattened device tree is used directly. An example of a node
-referencing another node via "phandle" is when laying out the
-interrupt tree which will be described in a further version of this
-document.
-
-This "linux, phandle" property is a 32-bit value that uniquely
-identifies a node. You are free to use whatever values or system of
-values, internal pointers, or whatever to generate these, the only
-requirement is that every node for which you provide that property has
-a unique value for it.
-
-Here is an example of a simple device-tree. In this example, an "o"
-designates a node followed by the node unit name. Properties are
-presented with their name followed by their content. "content"
-represents an ASCII string (zero terminated) value, while <content>
-represents a 32-bit hexadecimal value. The various nodes in this
-example will be discussed in a later chapter. At this point, it is
-only meant to give you a idea of what a device-tree looks like. I have
-purposefully kept the "name" and "linux,phandle" properties which
-aren't necessary in order to give you a better idea of what the tree
-looks like in practice.
-
-  / o device-tree
-      |- name = "device-tree"
-      |- model = "MyBoardName"
-      |- compatible = "MyBoardFamilyName"
-      |- #address-cells = <2>
-      |- #size-cells = <2>
-      |- linux,phandle = <0>
-      |
-      o cpus
-      | | - name = "cpus"
-      | | - linux,phandle = <1>
-      | | - #address-cells = <1>
-      | | - #size-cells = <0>
-      | |
-      | o PowerPC,970@0
-      |   |- name = "PowerPC,970"
-      |   |- device_type = "cpu"
-      |   |- reg = <0>
-      |   |- clock-frequency = <5f5e1000>
-      |   |- 64-bit
-      |   |- linux,phandle = <2>
-      |
-      o memory@0
-      | |- name = "memory"
-      | |- device_type = "memory"
-      | |- reg = <00000000 00000000 00000000 20000000>
-      | |- linux,phandle = <3>
-      |
-      o chosen
-        |- name = "chosen"
-        |- bootargs = "root=/dev/sda2"
-        |- linux,phandle = <4>
-
-This tree is almost a minimal tree. It pretty much contains the
-minimal set of required nodes and properties to boot a linux kernel;
-that is, some basic model informations at the root, the CPUs, and the
-physical memory layout.  It also includes misc information passed
-through /chosen, like in this example, the platform type (mandatory)
-and the kernel command line arguments (optional).
-
-The /cpus/PowerPC,970@0/64-bit property is an example of a
-property without a value. All other properties have a value. The
-significance of the #address-cells and #size-cells properties will be
-explained in chapter IV which defines precisely the required nodes and
-properties and their content.
-
-
-3) Device tree "structure" block
-
-The structure of the device tree is a linearized tree structure. The
-"OF_DT_BEGIN_NODE" token starts a new node, and the "OF_DT_END_NODE"
-ends that node definition. Child nodes are simply defined before
-"OF_DT_END_NODE" (that is nodes within the node). A 'token' is a 32
-bit value. The tree has to be "finished" with a OF_DT_END token
-
-Here's the basic structure of a single node:
-
-     * token OF_DT_BEGIN_NODE (that is 0x00000001)
-     * for version 1 to 3, this is the node full path as a zero
-       terminated string, starting with "/". For version 16 and later,
-       this is the node unit name only (or an empty string for the
-       root node)
-     * [align gap to next 4 bytes boundary]
-     * for each property:
-        * token OF_DT_PROP (that is 0x00000003)
-        * 32-bit value of property value size in bytes (or 0 if no
-          value)
-        * 32-bit value of offset in string block of property name
-        * property value data if any
-        * [align gap to next 4 bytes boundary]
-     * [child nodes if any]
-     * token OF_DT_END_NODE (that is 0x00000002)
-
-So the node content can be summarized as a start token, a full path,
-a list of properties, a list of child nodes, and an end token. Every
-child node is a full node structure itself as defined above.
-
-NOTE: The above definition requires that all property definitions for
-a particular node MUST precede any subnode definitions for that node.
-Although the structure would not be ambiguous if properties and
-subnodes were intermingled, the kernel parser requires that the
-properties come first (up until at least 2.6.22).  Any tools
-manipulating a flattened tree must take care to preserve this
-constraint.
-
-4) Device tree "strings" block
-
-In order to save space, property names, which are generally redundant,
-are stored separately in the "strings" block. This block is simply the
-whole bunch of zero terminated strings for all property names
-concatenated together. The device-tree property definitions in the
-structure block will contain offset values from the beginning of the
-strings block.
-
-
-III - Required content of the device tree
-=========================================
-
-WARNING: All "linux,*" properties defined in this document apply only
-to a flattened device-tree. If your platform uses a real
-implementation of Open Firmware or an implementation compatible with
-the Open Firmware client interface, those properties will be created
-by the trampoline code in the kernel's prom_init() file. For example,
-that's where you'll have to add code to detect your board model and
-set the platform number. However, when using the flattened device-tree
-entry point, there is no prom_init() pass, and thus you have to
-provide those properties yourself.
-
-
-1) Note about cells and address representation
-----------------------------------------------
-
-The general rule is documented in the various Open Firmware
-documentations. If you choose to describe a bus with the device-tree
-and there exist an OF bus binding, then you should follow the
-specification. However, the kernel does not require every single
-device or bus to be described by the device tree.
-
-In general, the format of an address for a device is defined by the
-parent bus type, based on the #address-cells and #size-cells
-properties.  Note that the parent's parent definitions of #address-cells
-and #size-cells are not inherited so every node with children must specify
-them.  The kernel requires the root node to have those properties defining
-addresses format for devices directly mapped on the processor bus.
-
-Those 2 properties define 'cells' for representing an address and a
-size. A "cell" is a 32-bit number. For example, if both contain 2
-like the example tree given above, then an address and a size are both
-composed of 2 cells, and each is a 64-bit number (cells are
-concatenated and expected to be in big endian format). Another example
-is the way Apple firmware defines them, with 2 cells for an address
-and one cell for a size.  Most 32-bit implementations should define
-#address-cells and #size-cells to 1, which represents a 32-bit value.
-Some 32-bit processors allow for physical addresses greater than 32
-bits; these processors should define #address-cells as 2.
-
-"reg" properties are always a tuple of the type "address size" where
-the number of cells of address and size is specified by the bus
-#address-cells and #size-cells. When a bus supports various address
-spaces and other flags relative to a given address allocation (like
-prefetchable, etc...) those flags are usually added to the top level
-bits of the physical address. For example, a PCI physical address is
-made of 3 cells, the bottom two containing the actual address itself
-while the top cell contains address space indication, flags, and pci
-bus & device numbers.
-
-For busses that support dynamic allocation, it's the accepted practice
-to then not provide the address in "reg" (keep it 0) though while
-providing a flag indicating the address is dynamically allocated, and
-then, to provide a separate "assigned-addresses" property that
-contains the fully allocated addresses. See the PCI OF bindings for
-details.
-
-In general, a simple bus with no address space bits and no dynamic
-allocation is preferred if it reflects your hardware, as the existing
-kernel address parsing functions will work out of the box. If you
-define a bus type with a more complex address format, including things
-like address space bits, you'll have to add a bus translator to the
-prom_parse.c file of the recent kernels for your bus type.
-
-The "reg" property only defines addresses and sizes (if #size-cells is
-non-0) within a given bus. In order to translate addresses upward
-(that is into parent bus addresses, and possibly into CPU physical
-addresses), all busses must contain a "ranges" property. If the
-"ranges" property is missing at a given level, it's assumed that
-translation isn't possible, i.e., the registers are not visible on the
-parent bus.  The format of the "ranges" property for a bus is a list
-of:
-
-	bus address, parent bus address, size
-
-"bus address" is in the format of the bus this bus node is defining,
-that is, for a PCI bridge, it would be a PCI address. Thus, (bus
-address, size) defines a range of addresses for child devices. "parent
-bus address" is in the format of the parent bus of this bus. For
-example, for a PCI host controller, that would be a CPU address. For a
-PCI<->ISA bridge, that would be a PCI address. It defines the base
-address in the parent bus where the beginning of that range is mapped.
-
-For a new 64-bit powerpc board, I recommend either the 2/2 format or
-Apple's 2/1 format which is slightly more compact since sizes usually
-fit in a single 32-bit word.   New 32-bit powerpc boards should use a
-1/1 format, unless the processor supports physical addresses greater
-than 32-bits, in which case a 2/1 format is recommended.
-
-Alternatively, the "ranges" property may be empty, indicating that the
-registers are visible on the parent bus using an identity mapping
-translation.  In other words, the parent bus address space is the same
-as the child bus address space.
-
-2) Note about "compatible" properties
--------------------------------------
-
-These properties are optional, but recommended in devices and the root
-node. The format of a "compatible" property is a list of concatenated
-zero terminated strings. They allow a device to express its
-compatibility with a family of similar devices, in some cases,
-allowing a single driver to match against several devices regardless
-of their actual names.
-
-3) Note about "name" properties
--------------------------------
-
-While earlier users of Open Firmware like OldWorld macintoshes tended
-to use the actual device name for the "name" property, it's nowadays
-considered a good practice to use a name that is closer to the device
-class (often equal to device_type). For example, nowadays, ethernet
-controllers are named "ethernet", an additional "model" property
-defining precisely the chip type/model, and "compatible" property
-defining the family in case a single driver can driver more than one
-of these chips. However, the kernel doesn't generally put any
-restriction on the "name" property; it is simply considered good
-practice to follow the standard and its evolutions as closely as
-possible.
-
-Note also that the new format version 16 makes the "name" property
-optional. If it's absent for a node, then the node's unit name is then
-used to reconstruct the name. That is, the part of the unit name
-before the "@" sign is used (or the entire unit name if no "@" sign
-is present).
-
-4) Note about node and property names and character set
--------------------------------------------------------
-
-While open firmware provides more flexible usage of 8859-1, this
-specification enforces more strict rules. Nodes and properties should
-be comprised only of ASCII characters 'a' to 'z', '0' to
-'9', ',', '.', '_', '+', '#', '?', and '-'. Node names additionally
-allow uppercase characters 'A' to 'Z' (property names should be
-lowercase. The fact that vendors like Apple don't respect this rule is
-irrelevant here). Additionally, node and property names should always
-begin with a character in the range 'a' to 'z' (or 'A' to 'Z' for node
-names).
-
-The maximum number of characters for both nodes and property names
-is 31. In the case of node names, this is only the leftmost part of
-a unit name (the pure "name" property), it doesn't include the unit
-address which can extend beyond that limit.
-
-
-5) Required nodes and properties
---------------------------------
-  These are all that are currently required. However, it is strongly
-  recommended that you expose PCI host bridges as documented in the
-  PCI binding to open firmware, and your interrupt tree as documented
-  in OF interrupt tree specification.
-
-  a) The root node
-
-  The root node requires some properties to be present:
-
-    - model : this is your board name/model
-    - #address-cells : address representation for "root" devices
-    - #size-cells: the size representation for "root" devices
-    - device_type : This property shouldn't be necessary. However, if
-      you decide to create a device_type for your root node, make sure it
-      is _not_ "chrp" unless your platform is a pSeries or PAPR compliant
-      one for 64-bit, or a CHRP-type machine for 32-bit as this will
-      matched by the kernel this way.
-
-  Additionally, some recommended properties are:
-
-    - compatible : the board "family" generally finds its way here,
-      for example, if you have 2 board models with a similar layout,
-      that typically get driven by the same platform code in the
-      kernel, you would use a different "model" property but put a
-      value in "compatible". The kernel doesn't directly use that
-      value but it is generally useful.
-
-  The root node is also generally where you add additional properties
-  specific to your board like the serial number if any, that sort of
-  thing. It is recommended that if you add any "custom" property whose
-  name may clash with standard defined ones, you prefix them with your
-  vendor name and a comma.
-
-  b) The /cpus node
-
-  This node is the parent of all individual CPU nodes. It doesn't
-  have any specific requirements, though it's generally good practice
-  to have at least:
-
-               #address-cells = <00000001>
-               #size-cells    = <00000000>
-
-  This defines that the "address" for a CPU is a single cell, and has
-  no meaningful size. This is not necessary but the kernel will assume
-  that format when reading the "reg" properties of a CPU node, see
-  below
-
-  c) The /cpus/* nodes
-
-  So under /cpus, you are supposed to create a node for every CPU on
-  the machine. There is no specific restriction on the name of the
-  CPU, though It's common practice to call it PowerPC,<name>. For
-  example, Apple uses PowerPC,G5 while IBM uses PowerPC,970FX.
-
-  Required properties:
-
-    - device_type : has to be "cpu"
-    - reg : This is the physical CPU number, it's a single 32-bit cell
-      and is also used as-is as the unit number for constructing the
-      unit name in the full path. For example, with 2 CPUs, you would
-      have the full path:
-        /cpus/PowerPC,970FX@0
-        /cpus/PowerPC,970FX@1
-      (unit addresses do not require leading zeroes)
-    - d-cache-block-size : one cell, L1 data cache block size in bytes (*)
-    - i-cache-block-size : one cell, L1 instruction cache block size in
-      bytes
-    - d-cache-size : one cell, size of L1 data cache in bytes
-    - i-cache-size : one cell, size of L1 instruction cache in bytes
-
-(*) The cache "block" size is the size on which the cache management
-instructions operate. Historically, this document used the cache
-"line" size here which is incorrect. The kernel will prefer the cache
-block size and will fallback to cache line size for backward
-compatibility.
-
-  Recommended properties:
-
-    - timebase-frequency : a cell indicating the frequency of the
-      timebase in Hz. This is not directly used by the generic code,
-      but you are welcome to copy/paste the pSeries code for setting
-      the kernel timebase/decrementer calibration based on this
-      value.
-    - clock-frequency : a cell indicating the CPU core clock frequency
-      in Hz. A new property will be defined for 64-bit values, but if
-      your frequency is < 4Ghz, one cell is enough. Here as well as
-      for the above, the common code doesn't use that property, but
-      you are welcome to re-use the pSeries or Maple one. A future
-      kernel version might provide a common function for this.
-    - d-cache-line-size : one cell, L1 data cache line size in bytes
-      if different from the block size
-    - i-cache-line-size : one cell, L1 instruction cache line size in
-      bytes if different from the block size
-
-  You are welcome to add any property you find relevant to your board,
-  like some information about the mechanism used to soft-reset the
-  CPUs. For example, Apple puts the GPIO number for CPU soft reset
-  lines in there as a "soft-reset" property since they start secondary
-  CPUs by soft-resetting them.
-
-
-  d) the /memory node(s)
-
-  To define the physical memory layout of your board, you should
-  create one or more memory node(s). You can either create a single
-  node with all memory ranges in its reg property, or you can create
-  several nodes, as you wish. The unit address (@ part) used for the
-  full path is the address of the first range of memory defined by a
-  given node. If you use a single memory node, this will typically be
-  @0.
-
-  Required properties:
-
-    - device_type : has to be "memory"
-    - reg : This property contains all the physical memory ranges of
-      your board. It's a list of addresses/sizes concatenated
-      together, with the number of cells of each defined by the
-      #address-cells and #size-cells of the root node. For example,
-      with both of these properties being 2 like in the example given
-      earlier, a 970 based machine with 6Gb of RAM could typically
-      have a "reg" property here that looks like:
-
-      00000000 00000000 00000000 80000000
-      00000001 00000000 00000001 00000000
-
-      That is a range starting at 0 of 0x80000000 bytes and a range
-      starting at 0x100000000 and of 0x100000000 bytes. You can see
-      that there is no memory covering the IO hole between 2Gb and
-      4Gb. Some vendors prefer splitting those ranges into smaller
-      segments, but the kernel doesn't care.
-
-  e) The /chosen node
-
-  This node is a bit "special". Normally, that's where open firmware
-  puts some variable environment information, like the arguments, or
-  the default input/output devices.
-
-  This specification makes a few of these mandatory, but also defines
-  some linux-specific properties that would be normally constructed by
-  the prom_init() trampoline when booting with an OF client interface,
-  but that you have to provide yourself when using the flattened format.
-
-  Recommended properties:
-
-    - bootargs : This zero-terminated string is passed as the kernel
-      command line
-    - linux,stdout-path : This is the full path to your standard
-      console device if any. Typically, if you have serial devices on
-      your board, you may want to put the full path to the one set as
-      the default console in the firmware here, for the kernel to pick
-      it up as its own default console. If you look at the function
-      set_preferred_console() in arch/ppc64/kernel/setup.c, you'll see
-      that the kernel tries to find out the default console and has
-      knowledge of various types like 8250 serial ports. You may want
-      to extend this function to add your own.
-
-  Note that u-boot creates and fills in the chosen node for platforms
-  that use it.
-
-  (Note: a practice that is now obsolete was to include a property
-  under /chosen called interrupt-controller which had a phandle value
-  that pointed to the main interrupt controller)
-
-  f) the /soc<SOCname> node
-
-  This node is used to represent a system-on-a-chip (SOC) and must be
-  present if the processor is a SOC. The top-level soc node contains
-  information that is global to all devices on the SOC. The node name
-  should contain a unit address for the SOC, which is the base address
-  of the memory-mapped register set for the SOC. The name of an soc
-  node should start with "soc", and the remainder of the name should
-  represent the part number for the soc.  For example, the MPC8540's
-  soc node would be called "soc8540".
-
-  Required properties:
-
-    - device_type : Should be "soc"
-    - ranges : Should be defined as specified in 1) to describe the
-      translation of SOC addresses for memory mapped SOC registers.
-    - bus-frequency: Contains the bus frequency for the SOC node.
-      Typically, the value of this field is filled in by the boot
-      loader.
-
-
-  Recommended properties:
-
-    - reg : This property defines the address and size of the
-      memory-mapped registers that are used for the SOC node itself.
-      It does not include the child device registers - these will be
-      defined inside each child node.  The address specified in the
-      "reg" property should match the unit address of the SOC node.
-    - #address-cells : Address representation for "soc" devices.  The
-      format of this field may vary depending on whether or not the
-      device registers are memory mapped.  For memory mapped
-      registers, this field represents the number of cells needed to
-      represent the address of the registers.  For SOCs that do not
-      use MMIO, a special address format should be defined that
-      contains enough cells to represent the required information.
-      See 1) above for more details on defining #address-cells.
-    - #size-cells : Size representation for "soc" devices
-    - #interrupt-cells : Defines the width of cells used to represent
-       interrupts.  Typically this value is <2>, which includes a
-       32-bit number that represents the interrupt number, and a
-       32-bit number that represents the interrupt sense and level.
-       This field is only needed if the SOC contains an interrupt
-       controller.
-
-  The SOC node may contain child nodes for each SOC device that the
-  platform uses.  Nodes should not be created for devices which exist
-  on the SOC but are not used by a particular platform. See chapter VI
-  for more information on how to specify devices that are part of a SOC.
-
-  Example SOC node for the MPC8540:
-
-	soc8540@e0000000 {
-		#address-cells = <1>;
-		#size-cells = <1>;
-		#interrupt-cells = <2>;
-		device_type = "soc";
-		ranges = <00000000 e0000000 00100000>
-		reg = <e0000000 00003000>;
-		bus-frequency = <0>;
-	}
-
-
-
-IV - "dtc", the device tree compiler
-====================================
-
-
-dtc source code can be found at
-<http://git.jdl.com/gitweb/?p=dtc.git>
-
-WARNING: This version is still in early development stage; the
-resulting device-tree "blobs" have not yet been validated with the
-kernel. The current generated bloc lacks a useful reserve map (it will
-be fixed to generate an empty one, it's up to the bootloader to fill
-it up) among others. The error handling needs work, bugs are lurking,
-etc...
-
-dtc basically takes a device-tree in a given format and outputs a
-device-tree in another format. The currently supported formats are:
-
-  Input formats:
-  -------------
-
-     - "dtb": "blob" format, that is a flattened device-tree block
-       with
-        header all in a binary blob.
-     - "dts": "source" format. This is a text file containing a
-       "source" for a device-tree. The format is defined later in this
-        chapter.
-     - "fs" format. This is a representation equivalent to the
-        output of /proc/device-tree, that is nodes are directories and
-	properties are files
-
- Output formats:
- ---------------
-
-     - "dtb": "blob" format
-     - "dts": "source" format
-     - "asm": assembly language file. This is a file that can be
-       sourced by gas to generate a device-tree "blob". That file can
-       then simply be added to your Makefile. Additionally, the
-       assembly file exports some symbols that can be used.
-
-
-The syntax of the dtc tool is
-
-    dtc [-I <input-format>] [-O <output-format>]
-        [-o output-filename] [-V output_version] input_filename
-
-
-The "output_version" defines what version of the "blob" format will be
-generated. Supported versions are 1,2,3 and 16. The default is
-currently version 3 but that may change in the future to version 16.
-
-Additionally, dtc performs various sanity checks on the tree, like the
-uniqueness of linux, phandle properties, validity of strings, etc...
-
-The format of the .dts "source" file is "C" like, supports C and C++
-style comments.
-
-/ {
-}
-
-The above is the "device-tree" definition. It's the only statement
-supported currently at the toplevel.
-
-/ {
-  property1 = "string_value";	/* define a property containing a 0
-                                 * terminated string
-				 */
-
-  property2 = <1234abcd>;	/* define a property containing a
-                                 * numerical 32-bit value (hexadecimal)
-				 */
-
-  property3 = <12345678 12345678 deadbeef>;
-                                /* define a property containing 3
-                                 * numerical 32-bit values (cells) in
-                                 * hexadecimal
-				 */
-  property4 = [0a 0b 0c 0d de ea ad be ef];
-                                /* define a property whose content is
-                                 * an arbitrary array of bytes
-                                 */
-
-  childnode@addresss {	/* define a child node named "childnode"
-                                 * whose unit name is "childnode at
-				 * address"
-                                 */
-
-    childprop = "hello\n";      /* define a property "childprop" of
-                                 * childnode (in this case, a string)
-                                 */
-  };
-};
-
-Nodes can contain other nodes etc... thus defining the hierarchical
-structure of the tree.
-
-Strings support common escape sequences from C: "\n", "\t", "\r",
-"\(octal value)", "\x(hex value)".
-
-It is also suggested that you pipe your source file through cpp (gcc
-preprocessor) so you can use #include's, #define for constants, etc...
-
-Finally, various options are planned but not yet implemented, like
-automatic generation of phandles, labels (exported to the asm file so
-you can point to a property content and change it easily from whatever
-you link the device-tree with), label or path instead of numeric value
-in some cells to "point" to a node (replaced by a phandle at compile
-time), export of reserve map address to the asm file, ability to
-specify reserve map content at compile time, etc...
-
-We may provide a .h include file with common definitions of that
-proves useful for some properties (like building PCI properties or
-interrupt maps) though it may be better to add a notion of struct
-definitions to the compiler...
-
-
-V - Recommendations for a bootloader
-====================================
-
-
-Here are some various ideas/recommendations that have been proposed
-while all this has been defined and implemented.
-
-  - The bootloader may want to be able to use the device-tree itself
-    and may want to manipulate it (to add/edit some properties,
-    like physical memory size or kernel arguments). At this point, 2
-    choices can be made. Either the bootloader works directly on the
-    flattened format, or the bootloader has its own internal tree
-    representation with pointers (similar to the kernel one) and
-    re-flattens the tree when booting the kernel. The former is a bit
-    more difficult to edit/modify, the later requires probably a bit
-    more code to handle the tree structure. Note that the structure
-    format has been designed so it's relatively easy to "insert"
-    properties or nodes or delete them by just memmoving things
-    around. It contains no internal offsets or pointers for this
-    purpose.
-
-  - An example of code for iterating nodes & retrieving properties
-    directly from the flattened tree format can be found in the kernel
-    file arch/ppc64/kernel/prom.c, look at scan_flat_dt() function,
-    its usage in early_init_devtree(), and the corresponding various
-    early_init_dt_scan_*() callbacks. That code can be re-used in a
-    GPL bootloader, and as the author of that code, I would be happy
-    to discuss possible free licensing to any vendor who wishes to
-    integrate all or part of this code into a non-GPL bootloader.
-
-
-
-VI - System-on-a-chip devices and nodes
-=======================================
-
-Many companies are now starting to develop system-on-a-chip
-processors, where the processor core (CPU) and many peripheral devices
-exist on a single piece of silicon.  For these SOCs, an SOC node
-should be used that defines child nodes for the devices that make
-up the SOC. While platforms are not required to use this model in
-order to boot the kernel, it is highly encouraged that all SOC
-implementations define as complete a flat-device-tree as possible to
-describe the devices on the SOC.  This will allow for the
-genericization of much of the kernel code.
-
-
-1) Defining child nodes of an SOC
----------------------------------
-
-Each device that is part of an SOC may have its own node entry inside
-the SOC node.  For each device that is included in the SOC, the unit
-address property represents the address offset for this device's
-memory-mapped registers in the parent's address space.  The parent's
-address space is defined by the "ranges" property in the top-level soc
-node. The "reg" property for each node that exists directly under the
-SOC node should contain the address mapping from the child address space
-to the parent SOC address space and the size of the device's
-memory-mapped register file.
-
-For many devices that may exist inside an SOC, there are predefined
-specifications for the format of the device tree node.  All SOC child
-nodes should follow these specifications, except where noted in this
-document.
-
-See appendix A for an example partial SOC node definition for the
-MPC8540.
-
-
-2) Representing devices without a current OF specification
-----------------------------------------------------------
-
-Currently, there are many devices on SOCs that do not have a standard
-representation pre-defined as part of the open firmware
-specifications, mainly because the boards that contain these SOCs are
-not currently booted using open firmware.   This section contains
-descriptions for the SOC devices for which new nodes have been
-defined; this list will expand as more and more SOC-containing
-platforms are moved over to use the flattened-device-tree model.
-
-VII - Specifying interrupt information for devices
-===================================================
-
-The device tree represents the busses and devices of a hardware
-system in a form similar to the physical bus topology of the
-hardware.
-
-In addition, a logical 'interrupt tree' exists which represents the
-hierarchy and routing of interrupts in the hardware.
-
-The interrupt tree model is fully described in the
-document "Open Firmware Recommended Practice: Interrupt
-Mapping Version 0.9".  The document is available at:
-<http://playground.sun.com/1275/practice>.
-
-1) interrupts property
-----------------------
-
-Devices that generate interrupts to a single interrupt controller
-should use the conventional OF representation described in the
-OF interrupt mapping documentation.
-
-Each device which generates interrupts must have an 'interrupt'
-property.  The interrupt property value is an arbitrary number of
-of 'interrupt specifier' values which describe the interrupt or
-interrupts for the device.
-
-The encoding of an interrupt specifier is determined by the
-interrupt domain in which the device is located in the
-interrupt tree.  The root of an interrupt domain specifies in
-its #interrupt-cells property the number of 32-bit cells
-required to encode an interrupt specifier.  See the OF interrupt
-mapping documentation for a detailed description of domains.
-
-For example, the binding for the OpenPIC interrupt controller
-specifies  an #interrupt-cells value of 2 to encode the interrupt
-number and level/sense information. All interrupt children in an
-OpenPIC interrupt domain use 2 cells per interrupt in their interrupts
-property.
-
-The PCI bus binding specifies a #interrupt-cell value of 1 to encode
-which interrupt pin (INTA,INTB,INTC,INTD) is used.
-
-2) interrupt-parent property
-----------------------------
-
-The interrupt-parent property is specified to define an explicit
-link between a device node and its interrupt parent in
-the interrupt tree.  The value of interrupt-parent is the
-phandle of the parent node.
-
-If the interrupt-parent property is not defined for a node, its
-interrupt parent is assumed to be an ancestor in the node's
-_device tree_ hierarchy.
-
-3) OpenPIC Interrupt Controllers
---------------------------------
-
-OpenPIC interrupt controllers require 2 cells to encode
-interrupt information.  The first cell defines the interrupt
-number.  The second cell defines the sense and level
-information.
-
-Sense and level information should be encoded as follows:
-
-	0 = low to high edge sensitive type enabled
-	1 = active low level sensitive type enabled
-	2 = active high level sensitive type enabled
-	3 = high to low edge sensitive type enabled
-
-4) ISA Interrupt Controllers
-----------------------------
-
-ISA PIC interrupt controllers require 2 cells to encode
-interrupt information.  The first cell defines the interrupt
-number.  The second cell defines the sense and level
-information.
-
-ISA PIC interrupt controllers should adhere to the ISA PIC
-encodings listed below:
-
-	0 =  active low level sensitive type enabled
-	1 =  active high level sensitive type enabled
-	2 =  high to low edge sensitive type enabled
-	3 =  low to high edge sensitive type enabled
-
-VIII - Specifying Device Power Management Information (sleep property)
-===================================================================
-
-Devices on SOCs often have mechanisms for placing devices into low-power
-states that are decoupled from the devices' own register blocks.  Sometimes,
-this information is more complicated than a cell-index property can
-reasonably describe.  Thus, each device controlled in such a manner
-may contain a "sleep" property which describes these connections.
-
-The sleep property consists of one or more sleep resources, each of
-which consists of a phandle to a sleep controller, followed by a
-controller-specific sleep specifier of zero or more cells.
-
-The semantics of what type of low power modes are possible are defined
-by the sleep controller.  Some examples of the types of low power modes
-that may be supported are:
-
- - Dynamic: The device may be disabled or enabled at any time.
- - System Suspend: The device may request to be disabled or remain
-   awake during system suspend, but will not be disabled until then.
- - Permanent: The device is disabled permanently (until the next hard
-   reset).
-
-Some devices may share a clock domain with each other, such that they should
-only be suspended when none of the devices are in use.  Where reasonable,
-such nodes should be placed on a virtual bus, where the bus has the sleep
-property.  If the clock domain is shared among devices that cannot be
-reasonably grouped in this manner, then create a virtual sleep controller
-(similar to an interrupt nexus, except that defining a standardized
-sleep-map should wait until its necessity is demonstrated).
-
-Appendix A - Sample SOC node for MPC8540
-========================================
-
-	soc@e0000000 {
-		#address-cells = <1>;
-		#size-cells = <1>;
-		compatible = "fsl,mpc8540-ccsr", "simple-bus";
-		device_type = "soc";
-		ranges = <0x00000000 0xe0000000 0x00100000>
-		bus-frequency = <0>;
-		interrupt-parent = <&pic>;
-
-		ethernet@24000 {
-			#address-cells = <1>;
-			#size-cells = <1>;
-			device_type = "network";
-			model = "TSEC";
-			compatible = "gianfar", "simple-bus";
-			reg = <0x24000 0x1000>;
-			local-mac-address = [ 00 E0 0C 00 73 00 ];
-			interrupts = <29 2 30 2 34 2>;
-			phy-handle = <&phy0>;
-			sleep = <&pmc 00000080>;
-			ranges;
-
-			mdio@24520 {
-				reg = <0x24520 0x20>;
-				compatible = "fsl,gianfar-mdio";
-
-				phy0: ethernet-phy@0 {
-					interrupts = <5 1>;
-					reg = <0>;
-					device_type = "ethernet-phy";
-				};
-
-				phy1: ethernet-phy@1 {
-					interrupts = <5 1>;
-					reg = <1>;
-					device_type = "ethernet-phy";
-				};
-
-				phy3: ethernet-phy@3 {
-					interrupts = <7 1>;
-					reg = <3>;
-					device_type = "ethernet-phy";
-				};
-			};
-		};
-
-		ethernet@25000 {
-			device_type = "network";
-			model = "TSEC";
-			compatible = "gianfar";
-			reg = <0x25000 0x1000>;
-			local-mac-address = [ 00 E0 0C 00 73 01 ];
-			interrupts = <13 2 14 2 18 2>;
-			phy-handle = <&phy1>;
-			sleep = <&pmc 00000040>;
-		};
-
-		ethernet@26000 {
-			device_type = "network";
-			model = "FEC";
-			compatible = "gianfar";
-			reg = <0x26000 0x1000>;
-			local-mac-address = [ 00 E0 0C 00 73 02 ];
-			interrupts = <41 2>;
-			phy-handle = <&phy3>;
-			sleep = <&pmc 00000020>;
-		};
-
-		serial@4500 {
-			#address-cells = <1>;
-			#size-cells = <1>;
-			compatible = "fsl,mpc8540-duart", "simple-bus";
-			sleep = <&pmc 00000002>;
-			ranges;
-
-			serial@4500 {
-				device_type = "serial";
-				compatible = "ns16550";
-				reg = <0x4500 0x100>;
-				clock-frequency = <0>;
-				interrupts = <42 2>;
-			};
-
-			serial@4600 {
-				device_type = "serial";
-				compatible = "ns16550";
-				reg = <0x4600 0x100>;
-				clock-frequency = <0>;
-				interrupts = <42 2>;
-			};
-		};
-
-		pic: pic@40000 {
-			interrupt-controller;
-			#address-cells = <0>;
-			#interrupt-cells = <2>;
-			reg = <0x40000 0x40000>;
-			compatible = "chrp,open-pic";
-			device_type = "open-pic";
-		};
-
-		i2c@3000 {
-			interrupts = <43 2>;
-			reg = <0x3000 0x100>;
-			compatible  = "fsl-i2c";
-			dfsrr;
-			sleep = <&pmc 00000004>;
-		};
-
-		pmc: power@e0070 {
-			compatible = "fsl,mpc8540-pmc", "fsl,mpc8548-pmc";
-			reg = <0xe0070 0x20>;
-		};
-	};
diff -druNp linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/4xx/emac.txt linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/4xx/emac.txt
--- linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/4xx/emac.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/4xx/emac.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,148 +0,0 @@
-    4xx/Axon EMAC ethernet nodes
-
-    The EMAC ethernet controller in IBM and AMCC 4xx chips, and also
-    the Axon bridge.  To operate this needs to interact with a ths
-    special McMAL DMA controller, and sometimes an RGMII or ZMII
-    interface.  In addition to the nodes and properties described
-    below, the node for the OPB bus on which the EMAC sits must have a
-    correct clock-frequency property.
-
-      i) The EMAC node itself
-
-    Required properties:
-    - device_type       : "network"
-
-    - compatible        : compatible list, contains 2 entries, first is
-			  "ibm,emac-CHIP" where CHIP is the host ASIC (440gx,
-			  405gp, Axon) and second is either "ibm,emac" or
-			  "ibm,emac4".  For Axon, thus, we have: "ibm,emac-axon",
-			  "ibm,emac4"
-    - interrupts        : <interrupt mapping for EMAC IRQ and WOL IRQ>
-    - interrupt-parent  : optional, if needed for interrupt mapping
-    - reg               : <registers mapping>
-    - local-mac-address : 6 bytes, MAC address
-    - mal-device        : phandle of the associated McMAL node
-    - mal-tx-channel    : 1 cell, index of the tx channel on McMAL associated
-			  with this EMAC
-    - mal-rx-channel    : 1 cell, index of the rx channel on McMAL associated
-			  with this EMAC
-    - cell-index        : 1 cell, hardware index of the EMAC cell on a given
-			  ASIC (typically 0x0 and 0x1 for EMAC0 and EMAC1 on
-			  each Axon chip)
-    - max-frame-size    : 1 cell, maximum frame size supported in bytes
-    - rx-fifo-size      : 1 cell, Rx fifo size in bytes for 10 and 100 Mb/sec
-			  operations.
-			  For Axon, 2048
-    - tx-fifo-size      : 1 cell, Tx fifo size in bytes for 10 and 100 Mb/sec
-			  operations.
-			  For Axon, 2048.
-    - fifo-entry-size   : 1 cell, size of a fifo entry (used to calculate
-			  thresholds).
-			  For Axon, 0x00000010
-    - mal-burst-size    : 1 cell, MAL burst size (used to calculate thresholds)
-			  in bytes.
-			  For Axon, 0x00000100 (I think ...)
-    - phy-mode          : string, mode of operations of the PHY interface.
-			  Supported values are: "mii", "rmii", "smii", "rgmii",
-			  "tbi", "gmii", rtbi", "sgmii".
-			  For Axon on CAB, it is "rgmii"
-    - mdio-device       : 1 cell, required iff using shared MDIO registers
-			  (440EP).  phandle of the EMAC to use to drive the
-			  MDIO lines for the PHY used by this EMAC.
-    - zmii-device       : 1 cell, required iff connected to a ZMII.  phandle of
-			  the ZMII device node
-    - zmii-channel      : 1 cell, required iff connected to a ZMII.  Which ZMII
-			  channel or 0xffffffff if ZMII is only used for MDIO.
-    - rgmii-device      : 1 cell, required iff connected to an RGMII. phandle
-			  of the RGMII device node.
-			  For Axon: phandle of plb5/plb4/opb/rgmii
-    - rgmii-channel     : 1 cell, required iff connected to an RGMII.  Which
-			  RGMII channel is used by this EMAC.
-			  Fox Axon: present, whatever value is appropriate for each
-			  EMAC, that is the content of the current (bogus) "phy-port"
-			  property.
-
-    Optional properties:
-    - phy-address       : 1 cell, optional, MDIO address of the PHY. If absent,
-			  a search is performed.
-    - phy-map           : 1 cell, optional, bitmap of addresses to probe the PHY
-			  for, used if phy-address is absent. bit 0x00000001 is
-			  MDIO address 0.
-			  For Axon it can be absent, though my current driver
-			  doesn't handle phy-address yet so for now, keep
-			  0x00ffffff in it.
-    - rx-fifo-size-gige : 1 cell, Rx fifo size in bytes for 1000 Mb/sec
-			  operations (if absent the value is the same as
-			  rx-fifo-size).  For Axon, either absent or 2048.
-    - tx-fifo-size-gige : 1 cell, Tx fifo size in bytes for 1000 Mb/sec
-			  operations (if absent the value is the same as
-			  tx-fifo-size). For Axon, either absent or 2048.
-    - tah-device        : 1 cell, optional. If connected to a TAH engine for
-			  offload, phandle of the TAH device node.
-    - tah-channel       : 1 cell, optional. If appropriate, channel used on the
-			  TAH engine.
-
-    Example:
-
-	EMAC0: ethernet@40000800 {
-		device_type = "network";
-		compatible = "ibm,emac-440gp", "ibm,emac";
-		interrupt-parent = <&UIC1>;
-		interrupts = <1c 4 1d 4>;
-		reg = <40000800 70>;
-		local-mac-address = [00 04 AC E3 1B 1E];
-		mal-device = <&MAL0>;
-		mal-tx-channel = <0 1>;
-		mal-rx-channel = <0>;
-		cell-index = <0>;
-		max-frame-size = <5dc>;
-		rx-fifo-size = <1000>;
-		tx-fifo-size = <800>;
-		phy-mode = "rmii";
-		phy-map = <00000001>;
-		zmii-device = <&ZMII0>;
-		zmii-channel = <0>;
-	};
-
-      ii) McMAL node
-
-    Required properties:
-    - device_type        : "dma-controller"
-    - compatible         : compatible list, containing 2 entries, first is
-			   "ibm,mcmal-CHIP" where CHIP is the host ASIC (like
-			   emac) and the second is either "ibm,mcmal" or
-			   "ibm,mcmal2".
-			   For Axon, "ibm,mcmal-axon","ibm,mcmal2"
-    - interrupts         : <interrupt mapping for the MAL interrupts sources:
-                           5 sources: tx_eob, rx_eob, serr, txde, rxde>.
-                           For Axon: This is _different_ from the current
-			   firmware.  We use the "delayed" interrupts for txeob
-			   and rxeob. Thus we end up with mapping those 5 MPIC
-			   interrupts, all level positive sensitive: 10, 11, 32,
-			   33, 34 (in decimal)
-    - dcr-reg            : < DCR registers range >
-    - dcr-parent         : if needed for dcr-reg
-    - num-tx-chans       : 1 cell, number of Tx channels
-    - num-rx-chans       : 1 cell, number of Rx channels
-
-      iii) ZMII node
-
-    Required properties:
-    - compatible         : compatible list, containing 2 entries, first is
-			   "ibm,zmii-CHIP" where CHIP is the host ASIC (like
-			   EMAC) and the second is "ibm,zmii".
-			   For Axon, there is no ZMII node.
-    - reg                : <registers mapping>
-
-      iv) RGMII node
-
-    Required properties:
-    - compatible         : compatible list, containing 2 entries, first is
-			   "ibm,rgmii-CHIP" where CHIP is the host ASIC (like
-			   EMAC) and the second is "ibm,rgmii".
-                           For Axon, "ibm,rgmii-axon","ibm,rgmii"
-    - reg                : <registers mapping>
-    - revision           : as provided by the RGMII new version register if
-			   available.
-			   For Axon: 0x0000012a
-
diff -druNp linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/4xx/ndfc.txt linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/4xx/ndfc.txt
--- linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/4xx/ndfc.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/4xx/ndfc.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,39 +0,0 @@
-AMCC NDFC (NanD Flash Controller)
-
-Required properties:
-- compatible : "ibm,ndfc".
-- reg : should specify chip select and size used for the chip (0x2000).
-
-Optional properties:
-- ccr : NDFC config and control register value (default 0).
-- bank-settings : NDFC bank configuration register value (default 0).
-
-Notes:
-- partition(s) - follows the OF MTD standard for partitions
-
-Example:
-
-ndfc@1,0 {
-	compatible = "ibm,ndfc";
-	reg = <0x00000001 0x00000000 0x00002000>;
-	ccr = <0x00001000>;
-	bank-settings = <0x80002222>;
-	#address-cells = <1>;
-	#size-cells = <1>;
-
-	nand {
-		#address-cells = <1>;
-		#size-cells = <1>;
-
-		partition@0 {
-			label = "kernel";
-			reg = <0x00000000 0x00200000>;
-		};
-		partition@200000 {
-			label = "root";
-			reg = <0x00200000 0x03E00000>;
-		};
-	};
-};
-
-
diff -druNp linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/4xx/ppc440spe-adma.txt linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/4xx/ppc440spe-adma.txt
--- linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/4xx/ppc440spe-adma.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/4xx/ppc440spe-adma.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,93 +0,0 @@
-PPC440SPe DMA/XOR (DMA Controller and XOR Accelerator)
-
-Device nodes needed for operation of the ppc440spe-adma driver
-are specified hereby. These are I2O/DMA, DMA and XOR nodes
-for DMA engines and Memory Queue Module node. The latter is used
-by ADMA driver for configuration of RAID-6 H/W capabilities of
-the PPC440SPe. In addition to the nodes and properties described
-below, the ranges property of PLB node must specify ranges for
-DMA devices.
-
- i) The I2O node
-
- Required properties:
-
- - compatible		: "ibm,i2o-440spe";
- - reg			: <registers mapping>
- - dcr-reg		: <DCR registers range>
-
- Example:
-
-	I2O: i2o@400100000 {
-		compatible = "ibm,i2o-440spe";
-		reg = <0x00000004 0x00100000 0x100>;
-		dcr-reg = <0x060 0x020>;
-	};
-
-
- ii) The DMA node
-
- Required properties:
-
- - compatible		: "ibm,dma-440spe";
- - cell-index		: 1 cell, hardware index of the DMA engine
-			  (typically 0x0 and 0x1 for DMA0 and DMA1)
- - reg			: <registers mapping>
- - dcr-reg		: <DCR registers range>
- - interrupts		: <interrupt mapping for DMA0/1 interrupts sources:
-			   2 sources: DMAx CS FIFO Needs Service IRQ (on UIC0)
-			   and DMA Error IRQ (on UIC1). The latter is common
-			   for both DMA engines>.
- - interrupt-parent	: needed for interrupt mapping
-
- Example:
-
-	DMA0: dma0@400100100 {
-		compatible = "ibm,dma-440spe";
-		cell-index = <0>;
-		reg = <0x00000004 0x00100100 0x100>;
-		dcr-reg = <0x060 0x020>;
-		interrupt-parent = <&DMA0>;
-		interrupts = <0 1>;
-		#interrupt-cells = <1>;
-		#address-cells = <0>;
-		#size-cells = <0>;
-		interrupt-map = <
-			0 &UIC0 0x14 4
-			1 &UIC1 0x16 4>;
-	};
-
-
- iii) XOR Accelerator node
-
- Required properties:
-
- - compatible		: "amcc,xor-accelerator";
- - reg			: <registers mapping>
- - interrupts		: <interrupt mapping for XOR interrupt source>
- - interrupt-parent	: for interrupt mapping
-
- Example:
-
-	xor-accel@400200000 {
-		compatible = "amcc,xor-accelerator";
-		reg = <0x00000004 0x00200000 0x400>;
-		interrupt-parent = <&UIC1>;
-		interrupts = <0x1f 4>;
-	};
-
-
- iv) Memory Queue Module node
-
- Required properties:
-
- - compatible		: "ibm,mq-440spe";
- - dcr-reg		: <DCR registers range>
-
- Example:
-
-	MQ0: mq {
-		compatible = "ibm,mq-440spe";
-		dcr-reg = <0x040 0x020>;
-	};
-
diff -druNp linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/4xx/reboot.txt linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/4xx/reboot.txt
--- linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/4xx/reboot.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/4xx/reboot.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,18 +0,0 @@
-Reboot property to control system reboot on PPC4xx systems:
-
-By setting "reset_type" to one of the following values, the default
-software reset mechanism may be overidden. Here the possible values of
-"reset_type":
-
-      1 - PPC4xx core reset
-      2 - PPC4xx chip reset
-      3 - PPC4xx system reset (default)
-
-Example:
-
-		cpu@0 {
-			device_type = "cpu";
-			model = "PowerPC,440SPe";
-			...
-			reset-type = <2>;	/* Use chip-reset */
-		};
diff -druNp linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/can/sja1000.txt linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/can/sja1000.txt
--- linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/can/sja1000.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/can/sja1000.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,53 +0,0 @@
-Memory mapped SJA1000 CAN controller from NXP (formerly Philips)
-
-Required properties:
-
-- compatible : should be "nxp,sja1000".
-
-- reg : should specify the chip select, address offset and size required
-	to map the registers of the SJA1000. The size is usually 0x80.
-
-- interrupts: property with a value describing the interrupt source
-	(number and sensitivity) required for the SJA1000.
-
-Optional properties:
-
-- nxp,external-clock-frequency : Frequency of the external oscillator
-	clock in Hz. Note that the internal clock frequency used by the
-	SJA1000 is half of that value. If not specified, a default value
-	of 16000000 (16 MHz) is used.
-
-- nxp,tx-output-mode : operation mode of the TX output control logic:
-	<0x0> : bi-phase output mode
-	<0x1> : normal output mode (default)
-	<0x2> : test output mode
-	<0x3> : clock output mode
-
-- nxp,tx-output-config : TX output pin configuration:
-	<0x01> : TX0 invert
-	<0x02> : TX0 pull-down (default)
-	<0x04> : TX0 pull-up
-	<0x06> : TX0 push-pull
-	<0x08> : TX1 invert
-	<0x10> : TX1 pull-down
-	<0x20> : TX1 pull-up
-	<0x30> : TX1 push-pull
-
-- nxp,clock-out-frequency : clock frequency in Hz on the CLKOUT pin.
-	If not specified or if the specified value is 0, the CLKOUT pin
-	will be disabled.
-
-- nxp,no-comparator-bypass : Allows to disable the CAN input comperator.
-
-For futher information, please have a look to the SJA1000 data sheet.
-
-Examples:
-
-can@3,100 {
-	compatible = "nxp,sja1000";
-	reg = <3 0x100 0x80>;
-	interrupts = <2 0>;
-	interrupt-parent = <&mpic>;
-	nxp,external-clock-frequency = <16000000>;
-};
-
diff -druNp linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/ecm.txt linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/ecm.txt
--- linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/ecm.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/ecm.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,64 +0,0 @@
-=====================================================================
-E500 LAW & Coherency Module Device Tree Binding
-Copyright (C) 2009 Freescale Semiconductor Inc.
-=====================================================================
-
-Local Access Window (LAW) Node
-
-The LAW node represents the region of CCSR space where local access
-windows are configured.  For ECM based devices this is the first 4k
-of CCSR space that includes CCSRBAR, ALTCBAR, ALTCAR, BPTR, and some
-number of local access windows as specified by fsl,num-laws.
-
-PROPERTIES
-
-  - compatible
-      Usage: required
-      Value type: <string>
-      Definition: Must include "fsl,ecm-law"
-
-  - reg
-      Usage: required
-      Value type: <prop-encoded-array>
-      Definition: A standard property.  The value specifies the
-          physical address offset and length of the CCSR space
-          registers.
-
-  - fsl,num-laws
-      Usage: required
-      Value type: <u32>
-      Definition: The value specifies the number of local access
-          windows for this device.
-
-=====================================================================
-
-E500 Coherency Module Node
-
-The E500 LAW node represents the region of CCSR space where ECM config
-and error reporting registers exist, this is the second 4k (0x1000)
-of CCSR space.
-
-PROPERTIES
-
-  - compatible
-      Usage: required
-      Value type: <string>
-      Definition: Must include "fsl,CHIP-ecm", "fsl,ecm" where
-      CHIP is the processor (mpc8572, mpc8544, etc.)
-
-  - reg
-      Usage: required
-      Value type: <prop-encoded-array>
-      Definition: A standard property.  The value specifies the
-          physical address offset and length of the CCSR space
-          registers.
-
-   - interrupts
-      Usage: required
-      Value type: <prop-encoded-array>
-
-   - interrupt-parent
-      Usage: required
-      Value type: <phandle>
-
-=====================================================================
diff -druNp linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/fsl/83xx-512x-pci.txt linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/fsl/83xx-512x-pci.txt
--- linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/fsl/83xx-512x-pci.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/fsl/83xx-512x-pci.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,40 +0,0 @@
-* Freescale 83xx and 512x PCI bridges
-
-Freescale 83xx and 512x SOCs include the same pci bridge core.
-
-83xx/512x specific notes:
-- reg: should contain two address length tuples
-    The first is for the internal pci bridge registers
-    The second is for the pci config space access registers
-
-Example (MPC8313ERDB)
-	pci0: pci@e0008500 {
-		cell-index = <1>;
-		interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
-		interrupt-map = <
-				/* IDSEL 0x0E -mini PCI */
-				 0x7000 0x0 0x0 0x1 &ipic 18 0x8
-				 0x7000 0x0 0x0 0x2 &ipic 18 0x8
-				 0x7000 0x0 0x0 0x3 &ipic 18 0x8
-				 0x7000 0x0 0x0 0x4 &ipic 18 0x8
-
-				/* IDSEL 0x0F - PCI slot */
-				 0x7800 0x0 0x0 0x1 &ipic 17 0x8
-				 0x7800 0x0 0x0 0x2 &ipic 18 0x8
-				 0x7800 0x0 0x0 0x3 &ipic 17 0x8
-				 0x7800 0x0 0x0 0x4 &ipic 18 0x8>;
-		interrupt-parent = <&ipic>;
-		interrupts = <66 0x8>;
-		bus-range = <0x0 0x0>;
-		ranges = <0x02000000 0x0 0x90000000 0x90000000 0x0 0x10000000
-			  0x42000000 0x0 0x80000000 0x80000000 0x0 0x10000000
-			  0x01000000 0x0 0x00000000 0xe2000000 0x0 0x00100000>;
-		clock-frequency = <66666666>;
-		#interrupt-cells = <1>;
-		#size-cells = <2>;
-		#address-cells = <3>;
-		reg = <0xe0008500 0x100		/* internal registers */
-		       0xe0008300 0x8>;		/* config space access registers */
-		compatible = "fsl,mpc8349-pci";
-		device_type = "pci";
-	};
diff -druNp linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/fsl/8xxx_gpio.txt linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/fsl/8xxx_gpio.txt
--- linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/fsl/8xxx_gpio.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/fsl/8xxx_gpio.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,60 +0,0 @@
-GPIO controllers on MPC8xxx SoCs
-
-This is for the non-QE/CPM/GUTs GPIO controllers as found on
-8349, 8572, 8610 and compatible.
-
-Every GPIO controller node must have #gpio-cells property defined,
-this information will be used to translate gpio-specifiers.
-
-Required properties:
-- compatible : "fsl,<CHIP>-gpio" followed by "fsl,mpc8349-gpio" for
-  83xx, "fsl,mpc8572-gpio" for 85xx and "fsl,mpc8610-gpio" for 86xx.
-- #gpio-cells : Should be two. The first cell is the pin number and the
-  second cell is used to specify optional parameters (currently unused).
- - interrupts : Interrupt mapping for GPIO IRQ.
- - interrupt-parent : Phandle for the interrupt controller that
-   services interrupts for this device.
-- gpio-controller : Marks the port as GPIO controller.
-
-Example of gpio-controller nodes for a MPC8347 SoC:
-
-	gpio1: gpio-controller@c00 {
-		#gpio-cells = <2>;
-		compatible = "fsl,mpc8347-gpio", "fsl,mpc8349-gpio";
-		reg = <0xc00 0x100>;
-		interrupts = <74 0x8>;
-		interrupt-parent = <&ipic>;
-		gpio-controller;
-	};
-
-	gpio2: gpio-controller@d00 {
-		#gpio-cells = <2>;
-		compatible = "fsl,mpc8347-gpio", "fsl,mpc8349-gpio";
-		reg = <0xd00 0x100>;
-		interrupts = <75 0x8>;
-		interrupt-parent = <&ipic>;
-		gpio-controller;
-	};
-
-See booting-without-of.txt for details of how to specify GPIO
-information for devices.
-
-To use GPIO pins as interrupt sources for peripherals, specify the
-GPIO controller as the interrupt parent and define GPIO number +
-trigger mode using the interrupts property, which is defined like
-this:
-
-interrupts = <number trigger>, where:
- - number: GPIO pin (0..31)
- - trigger: trigger mode:
-	2 = trigger on falling edge
-	3 = trigger on both edges
-
-Example of device using this is:
-
-	funkyfpga@0 {
-		compatible = "funky-fpga";
-		...
-		interrupts = <4 3>;
-		interrupt-parent = <&gpio1>;
-	};
diff -druNp linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/fsl/board.txt linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/fsl/board.txt
--- linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/fsl/board.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/fsl/board.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,63 +0,0 @@
-* Board Control and Status (BCSR)
-
-Required properties:
-
- - compatible : Should be "fsl,<board>-bcsr"
- - reg : Offset and length of the register set for the device
-
-Example:
-
-	bcsr@f8000000 {
-		compatible = "fsl,mpc8360mds-bcsr";
-		reg = <f8000000 8000>;
-	};
-
-* 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.
-- interrupt-parent: should specify phandle for the interrupt controller.
-- interrupts : should specify event (wakeup) IRQ.
-
-Example (MPC8610HPCD):
-
-	board-control@e8000000 {
-		compatible = "fsl,fpga-pixis";
-		reg = <0xe8000000 32>;
-		interrupt-parent = <&mpic>;
-		interrupts = <8 8>;
-	};
-
-* Freescale BCSR GPIO banks
-
-Some BCSR registers act as simple GPIO controllers, each such
-register can be represented by the gpio-controller node.
-
-Required properities:
-- compatible : Should be "fsl,<board>-bcsr-gpio".
-- reg : Should contain the address and the length of the GPIO bank
-  register.
-- #gpio-cells : Should be two. The first cell is the pin number and the
-  second cell is used to specify optional parameters (currently unused).
-- gpio-controller : Marks the port as GPIO controller.
-
-Example:
-
-	bcsr@1,0 {
-		#address-cells = <1>;
-		#size-cells = <1>;
-		compatible = "fsl,mpc8360mds-bcsr";
-		reg = <1 0 0x8000>;
-		ranges = <0 1 0 0x8000>;
-
-		bcsr13: gpio-controller@d {
-			#gpio-cells = <2>;
-			compatible = "fsl,mpc8360mds-bcsr-gpio";
-			reg = <0xd 1>;
-			gpio-controller;
-		};
-	};
diff -druNp linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/fsl/can.txt linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/fsl/can.txt
--- linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/fsl/can.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/fsl/can.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,53 +0,0 @@
-CAN Device Tree Bindings
-------------------------
-
-(c) 2006-2009 Secret Lab Technologies Ltd
-Grant Likely <grant.likely@secretlab.ca>
-
-fsl,mpc5200-mscan nodes
------------------------
-In addition to the required compatible-, reg- and interrupt-properties, you can
-also specify which clock source shall be used for the controller:
-
-- fsl,mscan-clock-source : a string describing the clock source. Valid values
-			   are:	"ip" for ip bus clock
-				 "ref" for reference clock (XTAL)
-			   "ref" is default in case this property is not
-			   present.
-
-fsl,mpc5121-mscan nodes
------------------------
-In addition to the required compatible-, reg- and interrupt-properties, you can
-also specify which clock source and divider shall be used for the controller:
-
-- fsl,mscan-clock-source : a string describing the clock source. Valid values
-			   are:	"ip" for ip bus clock
-				"ref" for reference clock
-				"sys" for system clock
-			   If this property is not present, an optimal CAN
-			   clock source and frequency based on the system
-			   clock will be selected. If this is not possible,
-			   the reference clock will be used.
-
-- fsl,mscan-clock-divider: for the reference and system clock, an additional
-			   clock divider can be specified. By default, a
-			   value of 1 is used.
-
-Note that the MPC5121 Rev. 1 processor is not supported.
-
-Examples:
-	can@1300 {
-		compatible = "fsl,mpc5121-mscan";
-		interrupts = <12 0x8>;
-		interrupt-parent = <&ipic>;
-		reg = <0x1300 0x80>;
-	};
-
-	can@1380 {
-		compatible = "fsl,mpc5121-mscan";
-		interrupts = <13 0x8>;
-		interrupt-parent = <&ipic>;
-		reg = <0x1380 0x80>;
-		fsl,mscan-clock-source = "ref";
-		fsl,mscan-clock-divider = <3>;
-	};
diff -druNp linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/fsl/cpm_qe/cpm/brg.txt linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/fsl/cpm_qe/cpm/brg.txt
--- linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/fsl/cpm_qe/cpm/brg.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/fsl/cpm_qe/cpm/brg.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,21 +0,0 @@
-* Baud Rate Generators
-
-Currently defined compatibles:
-fsl,cpm-brg
-fsl,cpm1-brg
-fsl,cpm2-brg
-
-Properties:
-- reg : There may be an arbitrary number of reg resources; BRG
-  numbers are assigned to these in order.
-- clock-frequency : Specifies the base frequency driving
-  the BRG.
-
-Example:
-	brg@119f0 {
-		compatible = "fsl,mpc8272-brg",
-			     "fsl,cpm2-brg",
-			     "fsl,cpm-brg";
-		reg = <119f0 10 115f0 10>;
-		clock-frequency = <d#25000000>;
-	};
diff -druNp linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/fsl/cpm_qe/cpm/i2c.txt linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/fsl/cpm_qe/cpm/i2c.txt
--- linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/fsl/cpm_qe/cpm/i2c.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/fsl/cpm_qe/cpm/i2c.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,41 +0,0 @@
-* I2C
-
-The I2C controller is expressed as a bus under the CPM node.
-
-Properties:
-- compatible : "fsl,cpm1-i2c", "fsl,cpm2-i2c"
-- reg : On CPM2 devices, the second resource doesn't specify the I2C
-  Parameter RAM itself, but the I2C_BASE field of the CPM2 Parameter RAM
-  (typically 0x8afc 0x2).
-- #address-cells : Should be one. The cell is the i2c device address with
-  the r/w bit set to zero.
-- #size-cells : Should be zero.
-- clock-frequency : Can be used to set the i2c clock frequency. If
-  unspecified, a default frequency of 60kHz is being used.
-The following two properties are deprecated. They are only used by legacy
-i2c drivers to find the bus to probe:
-- linux,i2c-index : Can be used to hard code an i2c bus number. By default,
-  the bus number is dynamically assigned by the i2c core.
-- linux,i2c-class : Can be used to override the i2c class. The class is used
-  by legacy i2c device drivers to find a bus in a specific context like
-  system management, video or sound. By default, I2C_CLASS_HWMON (1) is
-  being used. The definition of the classes can be found in
-  include/i2c/i2c.h
-
-Example, based on mpc823:
-
-	i2c@860 {
-		compatible = "fsl,mpc823-i2c",
-			     "fsl,cpm1-i2c";
-		reg = <0x860 0x20 0x3c80 0x30>;
-		interrupts = <16>;
-		interrupt-parent = <&CPM_PIC>;
-		fsl,cpm-command = <0x10>;
-		#address-cells = <1>;
-		#size-cells = <0>;
-
-		rtc@68 {
-			compatible = "dallas,ds1307";
-			reg = <0x68>;
-		};
-	};
diff -druNp linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/fsl/cpm_qe/cpm/pic.txt linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/fsl/cpm_qe/cpm/pic.txt
--- linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/fsl/cpm_qe/cpm/pic.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/fsl/cpm_qe/cpm/pic.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,18 +0,0 @@
-* Interrupt Controllers
-
-Currently defined compatibles:
-- fsl,cpm1-pic
-  - only one interrupt cell
-- fsl,pq1-pic
-- fsl,cpm2-pic
-  - second interrupt cell is level/sense:
-    - 2 is falling edge
-    - 8 is active low
-
-Example:
-	interrupt-controller@10c00 {
-		#interrupt-cells = <2>;
-		interrupt-controller;
-		reg = <10c00 80>;
-		compatible = "mpc8272-pic", "fsl,cpm2-pic";
-	};
diff -druNp linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/fsl/cpm_qe/cpm/usb.txt linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/fsl/cpm_qe/cpm/usb.txt
--- linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/fsl/cpm_qe/cpm/usb.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/fsl/cpm_qe/cpm/usb.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,15 +0,0 @@
-* USB (Universal Serial Bus Controller)
-
-Properties:
-- compatible : "fsl,cpm1-usb", "fsl,cpm2-usb", "fsl,qe-usb"
-
-Example:
-	usb@11bc0 {
-		#address-cells = <1>;
-		#size-cells = <0>;
-		compatible = "fsl,cpm2-usb";
-		reg = <11b60 18 8b00 100>;
-		interrupts = <b 8>;
-		interrupt-parent = <&PIC>;
-		fsl,cpm-command = <2e600000>;
-	};
diff -druNp linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/fsl/cpm_qe/cpm.txt linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/fsl/cpm_qe/cpm.txt
--- linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/fsl/cpm_qe/cpm.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/fsl/cpm_qe/cpm.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,67 +0,0 @@
-* Freescale Communications Processor Module
-
-NOTE: This is an interim binding, and will likely change slightly,
-as more devices are supported.  The QE bindings especially are
-incomplete.
-
-* Root CPM node
-
-Properties:
-- compatible : "fsl,cpm1", "fsl,cpm2", or "fsl,qe".
-- reg : A 48-byte region beginning with CPCR.
-
-Example:
-     cpm@119c0 {
-	#address-cells = <1>;
-	#size-cells = <1>;
-	#interrupt-cells = <2>;
-	compatible = "fsl,mpc8272-cpm", "fsl,cpm2";
-	reg = <119c0 30>;
-     }
-
-* Properties common to multiple CPM/QE devices
-
-- fsl,cpm-command : This value is ORed with the opcode and command flag
-                    to specify the device on which a CPM command operates.
-
-- fsl,cpm-brg : Indicates which baud rate generator the device
-                is associated with.  If absent, an unused BRG
-                should be dynamically allocated.  If zero, the
-                device uses an external clock rather than a BRG.
-
-- reg : Unless otherwise specified, the first resource represents the
-        scc/fcc/ucc registers, and the second represents the device's
-        parameter RAM region (if it has one).
-
-* Multi-User RAM (MURAM)
-
-The multi-user/dual-ported RAM is expressed as a bus under the CPM node.
-
-Ranges must be set up subject to the following restrictions:
-
-- Children's reg nodes must be offsets from the start of all muram, even
-  if the user-data area does not begin at zero.
-- If multiple range entries are used, the difference between the parent
-  address and the child address must be the same in all, so that a single
-  mapping can cover them all while maintaining the ability to determine
-  CPM-side offsets with pointer subtraction.  It is recommended that
-  multiple range entries not be used.
-- A child address of zero must be translatable, even if no reg resources
-  contain it.
-
-A child "data" node must exist, compatible with "fsl,cpm-muram-data", to
-indicate the portion of muram that is usable by the OS for arbitrary
-purposes.  The data node may have an arbitrary number of reg resources,
-all of which contribute to the allocatable muram pool.
-
-Example, based on mpc8272:
-	muram@0 {
-		#address-cells = <1>;
-		#size-cells = <1>;
-		ranges = <0 0 10000>;
-
-		data@0 {
-			compatible = "fsl,cpm-muram-data";
-			reg = <0 2000 9800 800>;
-		};
-	};
diff -druNp linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/fsl/cpm_qe/gpio.txt linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/fsl/cpm_qe/gpio.txt
--- linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/fsl/cpm_qe/gpio.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/fsl/cpm_qe/gpio.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,38 +0,0 @@
-Every GPIO controller node must have #gpio-cells property defined,
-this information will be used to translate gpio-specifiers.
-
-On CPM1 devices, all ports are using slightly different register layouts.
-Ports A, C and D are 16bit ports and Ports B and E are 32bit ports.
-
-On CPM2 devices, all ports are 32bit ports and use a common register layout.
-
-Required properties:
-- compatible : "fsl,cpm1-pario-bank-a", "fsl,cpm1-pario-bank-b",
-  "fsl,cpm1-pario-bank-c", "fsl,cpm1-pario-bank-d",
-  "fsl,cpm1-pario-bank-e", "fsl,cpm2-pario-bank"
-- #gpio-cells : Should be two. The first cell is the pin number and the
-  second cell is used to specify optional parameters (currently unused).
-- gpio-controller : Marks the port as GPIO controller.
-
-Example of three SOC GPIO banks defined as gpio-controller nodes:
-
-	CPM1_PIO_A: gpio-controller@950 {
-		#gpio-cells = <2>;
-		compatible = "fsl,cpm1-pario-bank-a";
-		reg = <0x950 0x10>;
-		gpio-controller;
-	};
-
-	CPM1_PIO_B: gpio-controller@ab8 {
-		#gpio-cells = <2>;
-		compatible = "fsl,cpm1-pario-bank-b";
-		reg = <0xab8 0x10>;
-		gpio-controller;
-	};
-
-	CPM1_PIO_E: gpio-controller@ac8 {
-		#gpio-cells = <2>;
-		compatible = "fsl,cpm1-pario-bank-e";
-		reg = <0xac8 0x18>;
-		gpio-controller;
-	};
diff -druNp linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/fsl/cpm_qe/network.txt linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/fsl/cpm_qe/network.txt
--- linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/fsl/cpm_qe/network.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/fsl/cpm_qe/network.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,45 +0,0 @@
-* Network
-
-Currently defined compatibles:
-- fsl,cpm1-scc-enet
-- fsl,cpm2-scc-enet
-- fsl,cpm1-fec-enet
-- fsl,cpm2-fcc-enet (third resource is GFEMR)
-- fsl,qe-enet
-
-Example:
-
-	ethernet@11300 {
-		device_type = "network";
-		compatible = "fsl,mpc8272-fcc-enet",
-			     "fsl,cpm2-fcc-enet";
-		reg = <11300 20 8400 100 11390 1>;
-		local-mac-address = [ 00 00 00 00 00 00 ];
-		interrupts = <20 8>;
-		interrupt-parent = <&PIC>;
-		phy-handle = <&PHY0>;
-		fsl,cpm-command = <12000300>;
-	};
-
-* MDIO
-
-Currently defined compatibles:
-fsl,pq1-fec-mdio (reg is same as first resource of FEC device)
-fsl,cpm2-mdio-bitbang (reg is port C registers)
-
-Properties for fsl,cpm2-mdio-bitbang:
-fsl,mdio-pin : pin of port C controlling mdio data
-fsl,mdc-pin : pin of port C controlling mdio clock
-
-Example:
-	mdio@10d40 {
-		device_type = "mdio";
-		compatible = "fsl,mpc8272ads-mdio-bitbang",
-			     "fsl,mpc8272-mdio-bitbang",
-			     "fsl,cpm2-mdio-bitbang";
-		reg = <10d40 14>;
-		#address-cells = <1>;
-		#size-cells = <0>;
-		fsl,mdio-pin = <12>;
-		fsl,mdc-pin = <13>;
-	};
diff -druNp linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/fsl/cpm_qe/qe/firmware.txt linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/fsl/cpm_qe/qe/firmware.txt
--- linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/fsl/cpm_qe/qe/firmware.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/fsl/cpm_qe/qe/firmware.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,24 +0,0 @@
-* Uploaded QE firmware
-
-      If a new firmware has been uploaded to the QE (usually by the
-      boot loader), then a 'firmware' child node should be added to the QE
-      node.  This node provides information on the uploaded firmware that
-      device drivers may need.
-
-      Required properties:
-      - id: The string name of the firmware.  This is taken from the 'id'
-            member of the qe_firmware structure of the uploaded firmware.
-            Device drivers can search this string to determine if the
-            firmware they want is already present.
-      - extended-modes: The Extended Modes bitfield, taken from the
-		   firmware binary.  It is a 64-bit number represented
-		   as an array of two 32-bit numbers.
-      - virtual-traps: The virtual traps, taken from the firmware binary.
-		  It is an array of 8 32-bit numbers.
-
-Example:
-	firmware {
-		id = "Soft-UART";
-		extended-modes = <0 0>;
-		virtual-traps = <0 0 0 0 0 0 0 0>;
-	};
diff -druNp linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/fsl/cpm_qe/qe/par_io.txt linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/fsl/cpm_qe/qe/par_io.txt
--- linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/fsl/cpm_qe/qe/par_io.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/fsl/cpm_qe/qe/par_io.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,51 +0,0 @@
-* Parallel I/O Ports
-
-This node configures Parallel I/O ports for CPUs with QE support.
-The node should reside in the "soc" node of the tree.  For each
-device that using parallel I/O ports, a child node should be created.
-See the definition of the Pin configuration nodes below for more
-information.
-
-Required properties:
-- device_type : should be "par_io".
-- reg : offset to the register set and its length.
-- num-ports : number of Parallel I/O ports
-
-Example:
-par_io@1400 {
-	reg = <1400 100>;
-	#address-cells = <1>;
-	#size-cells = <0>;
-	device_type = "par_io";
-	num-ports = <7>;
-	ucc_pin@01 {
-		......
-	};
-
-Note that "par_io" nodes are obsolete, and should not be used for
-the new device trees. Instead, each Par I/O bank should be represented
-via its own gpio-controller node:
-
-Required properties:
-- #gpio-cells : should be "2".
-- compatible : should be "fsl,<chip>-qe-pario-bank",
-  "fsl,mpc8323-qe-pario-bank".
-- reg : offset to the register set and its length.
-- gpio-controller : node to identify gpio controllers.
-
-Example:
-	qe_pio_a: gpio-controller@1400 {
-		#gpio-cells = <2>;
-		compatible = "fsl,mpc8360-qe-pario-bank",
-		"fsl,mpc8323-qe-pario-bank";
-		reg = <0x1400 0x18>;
-		gpio-controller;
-	  };
-
-	qe_pio_e: gpio-controller@1460 {
-		#gpio-cells = <2>;
-		compatible = "fsl,mpc8360-qe-pario-bank",
-			     "fsl,mpc8323-qe-pario-bank";
-		reg = <0x1460 0x18>;
-		gpio-controller;
-	  };
diff -druNp linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/fsl/cpm_qe/qe/pincfg.txt linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/fsl/cpm_qe/qe/pincfg.txt
--- linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/fsl/cpm_qe/qe/pincfg.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/fsl/cpm_qe/qe/pincfg.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,60 +0,0 @@
-* Pin configuration nodes
-
-Required properties:
-- linux,phandle : phandle of this node; likely referenced by a QE
-  device.
-- pio-map : array of pin configurations.  Each pin is defined by 6
-  integers.  The six numbers are respectively: port, pin, dir,
-  open_drain, assignment, has_irq.
-  - port : port number of the pin; 0-6 represent port A-G in UM.
-  - pin : pin number in the port.
-  - dir : direction of the pin, should encode as follows:
-
-     0 = The pin is disabled
-     1 = The pin is an output
-     2 = The pin is an input
-     3 = The pin is I/O
-
-  - open_drain : indicates the pin is normal or wired-OR:
-
-     0 = The pin is actively driven as an output
-     1 = The pin is an open-drain driver. As an output, the pin is
-         driven active-low, otherwise it is three-stated.
-
-  - assignment : function number of the pin according to the Pin Assignment
-    tables in User Manual.  Each pin can have up to 4 possible functions in
-    QE and two options for CPM.
-  - has_irq : indicates if the pin is used as source of external
-    interrupts.
-
-Example:
-     ucc_pin@01 {
-	linux,phandle = <140001>;
-	pio-map = <
-	/* port  pin  dir  open_drain  assignment  has_irq */
-		0  3  1  0  1  0 	/* TxD0 */
-		0  4  1  0  1  0 	/* TxD1 */
-		0  5  1  0  1  0 	/* TxD2 */
-		0  6  1  0  1  0 	/* TxD3 */
-		1  6  1  0  3  0 	/* TxD4 */
-		1  7  1  0  1  0 	/* TxD5 */
-		1  9  1  0  2  0 	/* TxD6 */
-		1  a  1  0  2  0 	/* TxD7 */
-		0  9  2  0  1  0 	/* RxD0 */
-		0  a  2  0  1  0 	/* RxD1 */
-		0  b  2  0  1  0 	/* RxD2 */
-		0  c  2  0  1  0 	/* RxD3 */
-		0  d  2  0  1  0 	/* RxD4 */
-		1  1  2  0  2  0 	/* RxD5 */
-		1  0  2  0  2  0 	/* RxD6 */
-		1  4  2  0  2  0 	/* RxD7 */
-		0  7  1  0  1  0 	/* TX_EN */
-		0  8  1  0  1  0 	/* TX_ER */
-		0  f  2  0  1  0 	/* RX_DV */
-		0  10 2  0  1  0 	/* RX_ER */
-		0  0  2  0  1  0 	/* RX_CLK */
-		2  9  1  0  3  0 	/* GTX_CLK - CLK10 */
-		2  8  2  0  1  0>;	/* GTX125 - CLK9 */
-     };
-
-
diff -druNp linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/fsl/cpm_qe/qe/ucc.txt linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/fsl/cpm_qe/qe/ucc.txt
--- linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/fsl/cpm_qe/qe/ucc.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/fsl/cpm_qe/qe/ucc.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,70 +0,0 @@
-* UCC (Unified Communications Controllers)
-
-Required properties:
-- device_type : should be "network", "hldc", "uart", "transparent"
-  "bisync", "atm", or "serial".
-- compatible : could be "ucc_geth" or "fsl_atm" and so on.
-- cell-index : the ucc number(1-8), corresponding to UCCx in UM.
-- reg : Offset and length of the register set for the device
-- interrupts : <a b> where a is the interrupt number and b is a
-  field that represents an encoding of the sense and level
-  information for the interrupt.  This should be encoded based on
-  the information in section 2) depending on the type of interrupt
-  controller you have.
-- interrupt-parent : the phandle for the interrupt controller that
-  services interrupts for this device.
-- pio-handle : The phandle for the Parallel I/O port configuration.
-- port-number : for UART drivers, the port number to use, between 0 and 3.
-  This usually corresponds to the /dev/ttyQE device, e.g. <0> = /dev/ttyQE0.
-  The port number is added to the minor number of the device.  Unlike the
-  CPM UART driver, the port-number is required for the QE UART driver.
-- soft-uart : for UART drivers, if specified this means the QE UART device
-  driver should use "Soft-UART" mode, which is needed on some SOCs that have
-  broken UART hardware.  Soft-UART is provided via a microcode upload.
-- rx-clock-name: the UCC receive clock source
-  "none": clock source is disabled
-  "brg1" through "brg16": clock source is BRG1-BRG16, respectively
-  "clk1" through "clk24": clock source is CLK1-CLK24, respectively
-- tx-clock-name: the UCC transmit clock source
-  "none": clock source is disabled
-  "brg1" through "brg16": clock source is BRG1-BRG16, respectively
-  "clk1" through "clk24": clock source is CLK1-CLK24, respectively
-The following two properties are deprecated.  rx-clock has been replaced
-with rx-clock-name, and tx-clock has been replaced with tx-clock-name.
-Drivers that currently use the deprecated properties should continue to
-do so, in order to support older device trees, but they should be updated
-to check for the new properties first.
-- rx-clock : represents the UCC receive clock source.
-  0x00 : clock source is disabled;
-  0x1~0x10 : clock source is BRG1~BRG16 respectively;
-  0x11~0x28: clock source is QE_CLK1~QE_CLK24 respectively.
-- tx-clock: represents the UCC transmit clock source;
-  0x00 : clock source is disabled;
-  0x1~0x10 : clock source is BRG1~BRG16 respectively;
-  0x11~0x28: clock source is QE_CLK1~QE_CLK24 respectively.
-
-Required properties for network device_type:
-- mac-address : list of bytes representing the ethernet address.
-- phy-handle : The phandle for the PHY connected to this controller.
-
-Recommended properties:
-- phy-connection-type : a string naming the controller/PHY interface type,
-  i.e., "mii" (default), "rmii", "gmii", "rgmii", "rgmii-id" (Internal
-  Delay), "rgmii-txid" (delay on TX only), "rgmii-rxid" (delay on RX only),
-  "tbi", or "rtbi".
-
-Example:
-	ucc@2000 {
-		device_type = "network";
-		compatible = "ucc_geth";
-		cell-index = <1>;
-		reg = <2000 200>;
-		interrupts = <a0 0>;
-		interrupt-parent = <700>;
-		mac-address = [ 00 04 9f 00 23 23 ];
-		rx-clock = "none";
-		tx-clock = "clk9";
-		phy-handle = <212000>;
-		phy-connection-type = "gmii";
-		pio-handle = <140001>;
-	};
diff -druNp linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/fsl/cpm_qe/qe/usb.txt linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/fsl/cpm_qe/qe/usb.txt
--- linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/fsl/cpm_qe/qe/usb.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/fsl/cpm_qe/qe/usb.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,37 +0,0 @@
-Freescale QUICC Engine USB Controller
-
-Required properties:
-- compatible : should be "fsl,<chip>-qe-usb", "fsl,mpc8323-qe-usb".
-- reg : the first two cells should contain usb registers location and
-  length, the next two two cells should contain PRAM location and
-  length.
-- interrupts : should contain USB interrupt.
-- interrupt-parent : interrupt source phandle.
-- fsl,fullspeed-clock : specifies the full speed USB clock source:
-  "none": clock source is disabled
-  "brg1" through "brg16": clock source is BRG1-BRG16, respectively
-  "clk1" through "clk24": clock source is CLK1-CLK24, respectively
-- fsl,lowspeed-clock : specifies the low speed USB clock source:
-  "none": clock source is disabled
-  "brg1" through "brg16": clock source is BRG1-BRG16, respectively
-  "clk1" through "clk24": clock source is CLK1-CLK24, respectively
-- hub-power-budget : USB power budget for the root hub, in mA.
-- gpios : should specify GPIOs in this order: USBOE, USBTP, USBTN, USBRP,
-  USBRN, SPEED (optional), and POWER (optional).
-
-Example:
-
-usb@6c0 {
-	compatible = "fsl,mpc8360-qe-usb", "fsl,mpc8323-qe-usb";
-	reg = <0x6c0 0x40 0x8b00 0x100>;
-	interrupts = <11>;
-	interrupt-parent = <&qeic>;
-	fsl,fullspeed-clock = "clk21";
-	gpios = <&qe_pio_b  2 0 /* USBOE */
-		 &qe_pio_b  3 0 /* USBTP */
-		 &qe_pio_b  8 0 /* USBTN */
-		 &qe_pio_b  9 0 /* USBRP */
-		 &qe_pio_b 11 0 /* USBRN */
-		 &qe_pio_e 20 0 /* SPEED */
-		 &qe_pio_e 21 0 /* POWER */>;
-};
diff -druNp linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/fsl/cpm_qe/qe.txt linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/fsl/cpm_qe/qe.txt
--- linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/fsl/cpm_qe/qe.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/fsl/cpm_qe/qe.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,115 +0,0 @@
-* Freescale QUICC Engine module (QE)
-This represents qe module that is installed on PowerQUICC II Pro.
-
-NOTE:  This is an interim binding; it should be updated to fit
-in with the CPM binding later in this document.
-
-Basically, it is a bus of devices, that could act more or less
-as a complete entity (UCC, USB etc ). All of them should be siblings on
-the "root" qe node, using the common properties from there.
-The description below applies to the qe of MPC8360 and
-more nodes and properties would be extended in the future.
-
-i) Root QE device
-
-Required properties:
-- compatible : should be "fsl,qe";
-- model : precise model of the QE, Can be "QE", "CPM", or "CPM2"
-- reg : offset and length of the device registers.
-- bus-frequency : the clock frequency for QUICC Engine.
-- fsl,qe-num-riscs: define how many RISC engines the QE has.
-- fsl,qe-num-snums: define how many serial number(SNUM) the QE can use for the
-  threads.
-
-Optional properties:
-- fsl,firmware-phandle:
-    Usage: required only if there is no fsl,qe-firmware child node
-    Value type: <phandle>
-    Definition: Points to a firmware node (see "QE Firmware Node" below)
-        that contains the firmware that should be uploaded for this QE.
-        The compatible property for the firmware node should say,
-        "fsl,qe-firmware".
-
-Recommended properties
-- brg-frequency : the internal clock source frequency for baud-rate
-  generators in Hz.
-
-Example:
-     qe@e0100000 {
-	#address-cells = <1>;
-	#size-cells = <1>;
-	#interrupt-cells = <2>;
-	compatible = "fsl,qe";
-	ranges = <0 e0100000 00100000>;
-	reg = <e0100000 480>;
-	brg-frequency = <0>;
-	bus-frequency = <179A7B00>;
-     }
-
-* Multi-User RAM (MURAM)
-
-Required properties:
-- compatible : should be "fsl,qe-muram", "fsl,cpm-muram".
-- mode : the could be "host" or "slave".
-- ranges : Should be defined as specified in 1) to describe the
-   translation of MURAM addresses.
-- data-only : sub-node which defines the address area under MURAM
-   bus that can be allocated as data/parameter
-
-Example:
-
-     muram@10000 {
-	compatible = "fsl,qe-muram", "fsl,cpm-muram";
-	ranges = <0 00010000 0000c000>;
-
-	data-only@0{
-		compatible = "fsl,qe-muram-data",
-			     "fsl,cpm-muram-data";
-		reg = <0 c000>;
-	};
-     };
-
-* QE Firmware Node
-
-This node defines a firmware binary that is embedded in the device tree, for
-the purpose of passing the firmware from bootloader to the kernel, or from
-the hypervisor to the guest.
-
-The firmware node itself contains the firmware binary contents, a compatible
-property, and any firmware-specific properties.  The node should be placed
-inside a QE node that needs it.  Doing so eliminates the need for a
-fsl,firmware-phandle property.  Other QE nodes that need the same firmware
-should define an fsl,firmware-phandle property that points to the firmware node
-in the first QE node.
-
-The fsl,firmware property can be specified in the DTS (possibly using incbin)
-or can be inserted by the boot loader at boot time.
-
-Required properties:
-  - compatible
-      Usage: required
-      Value type: <string>
-      Definition: A standard property.  Specify a string that indicates what
-          kind of firmware it is.  For QE, this should be "fsl,qe-firmware".
-
-   - fsl,firmware
-      Usage: required
-      Value type: <prop-encoded-array>, encoded as an array of bytes
-      Definition: A standard property.  This property contains the firmware
-          binary "blob".
-
-Example:
-	qe1@e0080000 {
-		compatible = "fsl,qe";
-		qe_firmware:qe-firmware {
-			compatible = "fsl,qe-firmware";
-			fsl,firmware = [0x70 0xcd 0x00 0x00 0x01 0x46 0x45 ...];
-		};
-		...
-	};
-
-	qe2@e0090000 {
-		compatible = "fsl,qe";
-		fsl,firmware-phandle = <&qe_firmware>;
-		...
-	};
diff -druNp linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/fsl/cpm_qe/serial.txt linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/fsl/cpm_qe/serial.txt
--- linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/fsl/cpm_qe/serial.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/fsl/cpm_qe/serial.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,32 +0,0 @@
-* Serial
-
-Currently defined compatibles:
-- fsl,cpm1-smc-uart
-- fsl,cpm2-smc-uart
-- fsl,cpm1-scc-uart
-- fsl,cpm2-scc-uart
-- fsl,qe-uart
-
-Modem control lines connected to GPIO controllers are listed in the gpios
-property as described in booting-without-of.txt, section IX.1 in the following
-order:
-
-CTS, RTS, DCD, DSR, DTR, and RI.
-
-The gpios property is optional and can be left out when control lines are
-not used.
-
-Example:
-
-	serial@11a00 {
-		device_type = "serial";
-		compatible = "fsl,mpc8272-scc-uart",
-			     "fsl,cpm2-scc-uart";
-		reg = <11a00 20 8000 100>;
-		interrupts = <28 8>;
-		interrupt-parent = <&PIC>;
-		fsl,cpm-brg = <1>;
-		fsl,cpm-command = <00800000>;
-		gpios = <&gpio_c 15 0
-			 &gpio_d 29 0>;
-	};
diff -druNp linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/fsl/diu.txt linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/fsl/diu.txt
--- linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/fsl/diu.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/fsl/diu.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,34 +0,0 @@
-* Freescale Display Interface Unit
-
-The Freescale DIU is a LCD controller, with proper hardware, it can also
-drive DVI monitors.
-
-Required properties:
-- compatible : should be "fsl,diu" or "fsl,mpc5121-diu".
-- reg : should contain at least address and length of the DIU register
-  set.
-- interrupts : one DIU interrupt should be described here.
-- interrupt-parent : the phandle for the interrupt controller that
-  services interrupts for this device.
-
-Optional properties:
-- edid : verbatim EDID data block describing attached display.
-  Data from the detailed timing descriptor will be used to
-  program the display controller.
-
-Example (MPC8610HPCD):
-	display@2c000 {
-		compatible = "fsl,diu";
-		reg = <0x2c000 100>;
-		interrupts = <72 2>;
-		interrupt-parent = <&mpic>;
-	};
-
-Example for MPC5121:
-	display@2100 {
-		compatible = "fsl,mpc5121-diu";
-		reg = <0x2100 0x100>;
-		interrupts = <64 0x8>;
-		interrupt-parent = <&ipic>;
-		edid = [edid-data];
-	};
diff -druNp linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/fsl/dma.txt linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/fsl/dma.txt
--- linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/fsl/dma.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/fsl/dma.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,144 +0,0 @@
-* Freescale 83xx DMA Controller
-
-Freescale PowerPC 83xx have on chip general purpose DMA controllers.
-
-Required properties:
-
-- compatible        : compatible list, contains 2 entries, first is
-		 "fsl,CHIP-dma", where CHIP is the processor
-		 (mpc8349, mpc8360, etc.) and the second is
-		 "fsl,elo-dma"
-- reg               : <registers mapping for DMA general status reg>
-- ranges		: Should be defined as specified in 1) to describe the
-		  DMA controller channels.
-- cell-index        : controller index.  0 for controller @ 0x8100
-- interrupts        : <interrupt mapping for DMA IRQ>
-- interrupt-parent  : optional, if needed for interrupt mapping
-
-
-- DMA channel nodes:
-        - compatible        : compatible list, contains 2 entries, first is
-			 "fsl,CHIP-dma-channel", where CHIP is the processor
-			 (mpc8349, mpc8350, etc.) and the second is
-			 "fsl,elo-dma-channel". However, see note below.
-        - reg               : <registers mapping for channel>
-        - cell-index        : dma channel index starts at 0.
-
-Optional properties:
-        - interrupts        : <interrupt mapping for DMA channel IRQ>
-			  (on 83xx this is expected to be identical to
-			   the interrupts property of the parent node)
-        - interrupt-parent  : optional, if needed for interrupt mapping
-
-Example:
-	dma@82a8 {
-		#address-cells = <1>;
-		#size-cells = <1>;
-		compatible = "fsl,mpc8349-dma", "fsl,elo-dma";
-		reg = <0x82a8 4>;
-		ranges = <0 0x8100 0x1a4>;
-		interrupt-parent = <&ipic>;
-		interrupts = <71 8>;
-		cell-index = <0>;
-		dma-channel@0 {
-			compatible = "fsl,mpc8349-dma-channel", "fsl,elo-dma-channel";
-			cell-index = <0>;
-			reg = <0 0x80>;
-			interrupt-parent = <&ipic>;
-			interrupts = <71 8>;
-		};
-		dma-channel@80 {
-			compatible = "fsl,mpc8349-dma-channel", "fsl,elo-dma-channel";
-			cell-index = <1>;
-			reg = <0x80 0x80>;
-			interrupt-parent = <&ipic>;
-			interrupts = <71 8>;
-		};
-		dma-channel@100 {
-			compatible = "fsl,mpc8349-dma-channel", "fsl,elo-dma-channel";
-			cell-index = <2>;
-			reg = <0x100 0x80>;
-			interrupt-parent = <&ipic>;
-			interrupts = <71 8>;
-		};
-		dma-channel@180 {
-			compatible = "fsl,mpc8349-dma-channel", "fsl,elo-dma-channel";
-			cell-index = <3>;
-			reg = <0x180 0x80>;
-			interrupt-parent = <&ipic>;
-			interrupts = <71 8>;
-		};
-	};
-
-* Freescale 85xx/86xx DMA Controller
-
-Freescale PowerPC 85xx/86xx have on chip general purpose DMA controllers.
-
-Required properties:
-
-- compatible        : compatible list, contains 2 entries, first is
-		 "fsl,CHIP-dma", where CHIP is the processor
-		 (mpc8540, mpc8540, etc.) and the second is
-		 "fsl,eloplus-dma"
-- reg               : <registers mapping for DMA general status reg>
-- cell-index        : controller index.  0 for controller @ 0x21000,
-                                         1 for controller @ 0xc000
-- ranges		: Should be defined as specified in 1) to describe the
-		  DMA controller channels.
-
-- DMA channel nodes:
-        - compatible        : compatible list, contains 2 entries, first is
-			 "fsl,CHIP-dma-channel", where CHIP is the processor
-			 (mpc8540, mpc8560, etc.) and the second is
-			 "fsl,eloplus-dma-channel". However, see note below.
-        - cell-index        : dma channel index starts at 0.
-        - reg               : <registers mapping for channel>
-        - interrupts        : <interrupt mapping for DMA channel IRQ>
-        - interrupt-parent  : optional, if needed for interrupt mapping
-
-Example:
-	dma@21300 {
-		#address-cells = <1>;
-		#size-cells = <1>;
-		compatible = "fsl,mpc8540-dma", "fsl,eloplus-dma";
-		reg = <0x21300 4>;
-		ranges = <0 0x21100 0x200>;
-		cell-index = <0>;
-		dma-channel@0 {
-			compatible = "fsl,mpc8540-dma-channel", "fsl,eloplus-dma-channel";
-			reg = <0 0x80>;
-			cell-index = <0>;
-			interrupt-parent = <&mpic>;
-			interrupts = <20 2>;
-		};
-		dma-channel@80 {
-			compatible = "fsl,mpc8540-dma-channel", "fsl,eloplus-dma-channel";
-			reg = <0x80 0x80>;
-			cell-index = <1>;
-			interrupt-parent = <&mpic>;
-			interrupts = <21 2>;
-		};
-		dma-channel@100 {
-			compatible = "fsl,mpc8540-dma-channel", "fsl,eloplus-dma-channel";
-			reg = <0x100 0x80>;
-			cell-index = <2>;
-			interrupt-parent = <&mpic>;
-			interrupts = <22 2>;
-		};
-		dma-channel@180 {
-			compatible = "fsl,mpc8540-dma-channel", "fsl,eloplus-dma-channel";
-			reg = <0x180 0x80>;
-			cell-index = <3>;
-			interrupt-parent = <&mpic>;
-			interrupts = <23 2>;
-		};
-	};
-
-Note on DMA channel compatible properties: The compatible property must say
-"fsl,elo-dma-channel" or "fsl,eloplus-dma-channel" to be used by the Elo DMA
-driver (fsldma).  Any DMA channel used by fsldma cannot be used by another
-DMA driver, such as the SSI sound drivers for the MPC8610.  Therefore, any DMA
-channel that should be used for another driver should not use
-"fsl,elo-dma-channel" or "fsl,eloplus-dma-channel".  For the SSI drivers, for
-example, the compatible property should be "fsl,ssi-dma-channel".  See ssi.txt
-for more information.
diff -druNp linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/fsl/esdhc.txt linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/fsl/esdhc.txt
--- linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/fsl/esdhc.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/fsl/esdhc.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,29 +0,0 @@
-* Freescale Enhanced Secure Digital Host Controller (eSDHC)
-
-The Enhanced Secure Digital Host Controller provides an interface
-for MMC, SD, and SDIO types of memory cards.
-
-Required properties:
-  - compatible : should be
-    "fsl,<chip>-esdhc", "fsl,esdhc"
-  - reg : should contain eSDHC registers location and length.
-  - interrupts : should contain eSDHC interrupt.
-  - interrupt-parent : interrupt source phandle.
-  - clock-frequency : specifies eSDHC base clock frequency.
-  - sdhci,wp-inverted : (optional) specifies that eSDHC controller
-    reports inverted write-protect state;
-  - sdhci,1-bit-only : (optional) specifies that a controller can
-    only handle 1-bit data transfers.
-  - sdhci,auto-cmd12: (optional) specifies that a controller can
-    only handle auto CMD12.
-
-Example:
-
-sdhci@2e000 {
-	compatible = "fsl,mpc8378-esdhc", "fsl,esdhc";
-	reg = <0x2e000 0x1000>;
-	interrupts = <42 0x8>;
-	interrupt-parent = <&ipic>;
-	/* Filled in by U-Boot */
-	clock-frequency = <0>;
-};
diff -druNp linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/fsl/gtm.txt linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/fsl/gtm.txt
--- linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/fsl/gtm.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/fsl/gtm.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,31 +0,0 @@
-* Freescale General-purpose Timers Module
-
-Required properties:
-  - compatible : should be
-    "fsl,<chip>-gtm", "fsl,gtm" for SOC GTMs
-    "fsl,<chip>-qe-gtm", "fsl,qe-gtm", "fsl,gtm" for QE GTMs
-    "fsl,<chip>-cpm2-gtm", "fsl,cpm2-gtm", "fsl,gtm" for CPM2 GTMs
-  - reg : should contain gtm registers location and length (0x40).
-  - interrupts : should contain four interrupts.
-  - interrupt-parent : interrupt source phandle.
-  - clock-frequency : specifies the frequency driving the timer.
-
-Example:
-
-timer@500 {
-	compatible = "fsl,mpc8360-gtm", "fsl,gtm";
-	reg = <0x500 0x40>;
-	interrupts = <90 8 78 8 84 8 72 8>;
-	interrupt-parent = <&ipic>;
-	/* filled by u-boot */
-	clock-frequency = <0>;
-};
-
-timer@440 {
-	compatible = "fsl,mpc8360-qe-gtm", "fsl,qe-gtm", "fsl,gtm";
-	reg = <0x440 0x40>;
-	interrupts = <12 13 14 15>;
-	interrupt-parent = <&qeic>;
-	/* filled by u-boot */
-	clock-frequency = <0>;
-};
diff -druNp linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/fsl/guts.txt linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/fsl/guts.txt
--- linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/fsl/guts.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/fsl/guts.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,25 +0,0 @@
-* Global Utilities Block
-
-The global utilities block controls power management, I/O device
-enabling, power-on-reset configuration monitoring, general-purpose
-I/O signal configuration, alternate function selection for multiplexed
-signals, and clock control.
-
-Required properties:
-
- - compatible : Should define the compatible device type for
-   global-utilities.
- - reg : Offset and length of the register set for the device.
-
-Recommended properties:
-
- - fsl,has-rstcr : Indicates that the global utilities register set
-   contains a functioning "reset control register" (i.e. the board
-   is wired to reset upon setting the HRESET_REQ bit in this register).
-
-Example:
-	global-utilities@e0000 {	/* global utilities block */
-		compatible = "fsl,mpc8548-guts";
-		reg = <e0000 1000>;
-		fsl,has-rstcr;
-	};
diff -druNp linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/fsl/i2c.txt linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/fsl/i2c.txt
--- linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/fsl/i2c.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/fsl/i2c.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,64 +0,0 @@
-* I2C
-
-Required properties :
-
- - reg : Offset and length of the register set for the device
- - compatible : should be "fsl,CHIP-i2c" where CHIP is the name of a
-   compatible processor, e.g. mpc8313, mpc8543, mpc8544, mpc5121,
-   mpc5200 or mpc5200b. For the mpc5121, an additional node
-   "fsl,mpc5121-i2c-ctrl" is required as shown in the example below.
-
-Recommended properties :
-
- - interrupts : <a b> where a is the interrupt number and b is a
-   field that represents an encoding of the sense and level
-   information for the interrupt.  This should be encoded based on
-   the information in section 2) depending on the type of interrupt
-   controller you have.
- - interrupt-parent : the phandle for the interrupt controller that
-   services interrupts for this device.
- - fsl,preserve-clocking : boolean; if defined, the clock settings
-   from the bootloader are preserved (not touched).
- - clock-frequency : desired I2C bus clock frequency in Hz.
- - fsl,timeout : I2C bus timeout in microseconds.
-
-Examples :
-
-	/* MPC5121 based board */
-	i2c@1740 {
-		#address-cells = <1>;
-		#size-cells = <0>;
-		compatible = "fsl,mpc5121-i2c", "fsl-i2c";
-		reg = <0x1740 0x20>;
-		interrupts = <11 0x8>;
-		interrupt-parent = <&ipic>;
-		clock-frequency = <100000>;
-	};
-
-	i2ccontrol@1760 {
-		compatible = "fsl,mpc5121-i2c-ctrl";
-		reg = <0x1760 0x8>;
-	};
-
-	/* MPC5200B based board */
-	i2c@3d00 {
-		#address-cells = <1>;
-		#size-cells = <0>;
-		compatible = "fsl,mpc5200b-i2c","fsl,mpc5200-i2c","fsl-i2c";
-		reg = <0x3d00 0x40>;
-		interrupts = <2 15 0>;
-		interrupt-parent = <&mpc5200_pic>;
-		fsl,preserve-clocking;
-	};
-
-	/* MPC8544 base board */
-	i2c@3100 {
-		#address-cells = <1>;
-		#size-cells = <0>;
-		compatible = "fsl,mpc8544-i2c", "fsl-i2c";
-		reg = <0x3100 0x100>;
-		interrupts = <43 2>;
-		interrupt-parent = <&mpic>;
-		clock-frequency = <400000>;
-		fsl,timeout = <10000>;
-	};
diff -druNp linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/fsl/lbc.txt linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/fsl/lbc.txt
--- linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/fsl/lbc.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/fsl/lbc.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,35 +0,0 @@
-* Chipselect/Local Bus
-
-Properties:
-- name : Should be localbus
-- #address-cells : Should be either two or three.  The first cell is the
-                   chipselect number, and the remaining cells are the
-                   offset into the chipselect.
-- #size-cells : Either one or two, depending on how large each chipselect
-                can be.
-- ranges : Each range corresponds to a single chipselect, and cover
-           the entire access window as configured.
-
-Example:
-	localbus@f0010100 {
-		compatible = "fsl,mpc8272-localbus",
-			   "fsl,pq2-localbus";
-		#address-cells = <2>;
-		#size-cells = <1>;
-		reg = <f0010100 40>;
-
-		ranges = <0 0 fe000000 02000000
-			  1 0 f4500000 00008000>;
-
-		flash@0,0 {
-			compatible = "jedec-flash";
-			reg = <0 0 2000000>;
-			bank-width = <4>;
-			device-width = <1>;
-		};
-
-		board-control@1,0 {
-			reg = <1 0 20>;
-			compatible = "fsl,mpc8272ads-bcsr";
-		};
-	};
diff -druNp linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/fsl/mcm.txt linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/fsl/mcm.txt
--- linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/fsl/mcm.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/fsl/mcm.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,64 +0,0 @@
-=====================================================================
-MPX LAW & Coherency Module Device Tree Binding
-Copyright (C) 2009 Freescale Semiconductor Inc.
-=====================================================================
-
-Local Access Window (LAW) Node
-
-The LAW node represents the region of CCSR space where local access
-windows are configured.  For MCM based devices this is the first 4k
-of CCSR space that includes CCSRBAR, ALTCBAR, ALTCAR, BPTR, and some
-number of local access windows as specified by fsl,num-laws.
-
-PROPERTIES
-
-  - compatible
-      Usage: required
-      Value type: <string>
-      Definition: Must include "fsl,mcm-law"
-
-  - reg
-      Usage: required
-      Value type: <prop-encoded-array>
-      Definition: A standard property.  The value specifies the
-          physical address offset and length of the CCSR space
-          registers.
-
-  - fsl,num-laws
-      Usage: required
-      Value type: <u32>
-      Definition: The value specifies the number of local access
-          windows for this device.
-
-=====================================================================
-
-MPX Coherency Module Node
-
-The MPX LAW node represents the region of CCSR space where MCM config
-and error reporting registers exist, this is the second 4k (0x1000)
-of CCSR space.
-
-PROPERTIES
-
-  - compatible
-      Usage: required
-      Value type: <string>
-      Definition: Must include "fsl,CHIP-mcm", "fsl,mcm" where
-      CHIP is the processor (mpc8641, mpc8610, etc.)
-
-  - reg
-      Usage: required
-      Value type: <prop-encoded-array>
-      Definition: A standard property.  The value specifies the
-          physical address offset and length of the CCSR space
-          registers.
-
-   - interrupts
-      Usage: required
-      Value type: <prop-encoded-array>
-
-   - interrupt-parent
-      Usage: required
-      Value type: <phandle>
-
-=====================================================================
diff -druNp linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/fsl/mcu-mpc8349emitx.txt linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/fsl/mcu-mpc8349emitx.txt
--- linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/fsl/mcu-mpc8349emitx.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/fsl/mcu-mpc8349emitx.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,17 +0,0 @@
-Freescale MPC8349E-mITX-compatible Power Management Micro Controller Unit (MCU)
-
-Required properties:
-- compatible : "fsl,<mcu-chip>-<board>", "fsl,mcu-mpc8349emitx".
-- reg : should specify I2C address (0x0a).
-- #gpio-cells : should be 2.
-- gpio-controller : should be present.
-
-Example:
-
-mcu@0a {
-	#gpio-cells = <2>;
-	compatible = "fsl,mc9s08qg8-mpc8349emitx",
-		     "fsl,mcu-mpc8349emitx";
-	reg = <0x0a>;
-	gpio-controller;
-};
diff -druNp linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/fsl/mpc5121-psc.txt linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/fsl/mpc5121-psc.txt
--- linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/fsl/mpc5121-psc.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/fsl/mpc5121-psc.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,70 +0,0 @@
-MPC5121 PSC Device Tree Bindings
-
-PSC in UART mode
-----------------
-
-For PSC in UART mode the needed PSC serial devices
-are specified by fsl,mpc5121-psc-uart nodes in the
-fsl,mpc5121-immr SoC node. Additionally the PSC FIFO
-Controller node fsl,mpc5121-psc-fifo is requered there:
-
-fsl,mpc5121-psc-uart nodes
---------------------------
-
-Required properties :
- - compatible : Should contain "fsl,mpc5121-psc-uart" and "fsl,mpc5121-psc"
- - cell-index : Index of the PSC in hardware
- - reg : Offset and length of the register set for the PSC device
- - interrupts : <a b> where a is the interrupt number of the
-   PSC FIFO Controller and b is a field that represents an
-   encoding of the sense and level information for the interrupt.
- - interrupt-parent : the phandle for the interrupt controller that
-   services interrupts for this device.
-
-Recommended properties :
- - fsl,rx-fifo-size : the size of the RX fifo slice (a multiple of 4)
- - fsl,tx-fifo-size : the size of the TX fifo slice (a multiple of 4)
-
-
-fsl,mpc5121-psc-fifo node
--------------------------
-
-Required properties :
- - compatible : Should be "fsl,mpc5121-psc-fifo"
- - reg : Offset and length of the register set for the PSC
-         FIFO Controller
- - interrupts : <a b> where a is the interrupt number of the
-   PSC FIFO Controller and b is a field that represents an
-   encoding of the sense and level information for the interrupt.
- - interrupt-parent : the phandle for the interrupt controller that
-   services interrupts for this device.
-
-
-Example for a board using PSC0 and PSC1 devices in serial mode:
-
-serial@11000 {
-	compatible = "fsl,mpc5121-psc-uart", "fsl,mpc5121-psc";
-	cell-index = <0>;
-	reg = <0x11000 0x100>;
-	interrupts = <40 0x8>;
-	interrupt-parent = < &ipic >;
-	fsl,rx-fifo-size = <16>;
-	fsl,tx-fifo-size = <16>;
-};
-
-serial@11100 {
-	compatible = "fsl,mpc5121-psc-uart", "fsl,mpc5121-psc";
-	cell-index = <1>;
-	reg = <0x11100 0x100>;
-	interrupts = <40 0x8>;
-	interrupt-parent = < &ipic >;
-	fsl,rx-fifo-size = <16>;
-	fsl,tx-fifo-size = <16>;
-};
-
-pscfifo@11f00 {
-	compatible = "fsl,mpc5121-psc-fifo";
-	reg = <0x11f00 0x100>;
-	interrupts = <40 0x8>;
-	interrupt-parent = < &ipic >;
-};
diff -druNp linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/fsl/mpc5200.txt linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/fsl/mpc5200.txt
--- linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/fsl/mpc5200.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/fsl/mpc5200.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,198 +0,0 @@
-MPC5200 Device Tree Bindings
-----------------------------
-
-(c) 2006-2009 Secret Lab Technologies Ltd
-Grant Likely <grant.likely@secretlab.ca>
-
-Naming conventions
-------------------
-For mpc5200 on-chip devices, the format for each compatible value is
-<chip>-<device>[-<mode>].  The OS should be able to match a device driver
-to the device based solely on the compatible value.  If two drivers
-match on the compatible list; the 'most compatible' driver should be
-selected.
-
-The split between the MPC5200 and the MPC5200B leaves a bit of a
-conundrum.  How should the compatible property be set up to provide
-maximum compatibility information; but still accurately describe the
-chip?  For the MPC5200; the answer is easy.  Most of the SoC devices
-originally appeared on the MPC5200.  Since they didn't exist anywhere
-else; the 5200 compatible properties will contain only one item;
-"fsl,mpc5200-<device>".
-
-The 5200B is almost the same as the 5200, but not quite.  It fixes
-silicon bugs and it adds a small number of enhancements.  Most of the
-devices either provide exactly the same interface as on the 5200.  A few
-devices have extra functions but still have a backwards compatible mode.
-To express this information as completely as possible, 5200B device trees
-should have two items in the compatible list:
-	compatible = "fsl,mpc5200b-<device>","fsl,mpc5200-<device>";
-
-It is *strongly* recommended that 5200B device trees follow this convention
-(instead of only listing the base mpc5200 item).
-
-ie. ethernet on mpc5200: compatible = "fsl,mpc5200-fec";
-    ethernet on mpc5200b: compatible = "fsl,mpc5200b-fec", "fsl,mpc5200-fec";
-
-Modal devices, like PSCs, also append the configured function to the
-end of the compatible field.  ie. A PSC in i2s mode would specify
-"fsl,mpc5200-psc-i2s", not "fsl,mpc5200-i2s".  This convention is chosen to
-avoid naming conflicts with non-psc devices providing the same
-function.  For example, "fsl,mpc5200-spi" and "fsl,mpc5200-psc-spi" describe
-the mpc5200 simple spi device and a PSC spi mode respectively.
-
-At the time of writing, exact chip may be either 'fsl,mpc5200' or
-'fsl,mpc5200b'.
-
-The soc node
-------------
-This node describes the on chip SOC peripherals.  Every mpc5200 based
-board will have this node, and as such there is a common naming
-convention for SOC devices.
-
-Required properties:
-name			description
-----			-----------
-ranges			Memory range of the internal memory mapped registers.
-			Should be <0 [baseaddr] 0xc000>
-reg			Should be <[baseaddr] 0x100>
-compatible		mpc5200: "fsl,mpc5200-immr"
-			mpc5200b: "fsl,mpc5200b-immr"
-system-frequency	'fsystem' frequency in Hz; XLB, IPB, USB and PCI
-			clocks are derived from the fsystem clock.
-bus-frequency		IPB bus frequency in Hz.  Clock rate
-			used by most of the soc devices.
-
-soc child nodes
----------------
-Any on chip SOC devices available to Linux must appear as soc5200 child nodes.
-
-Note: The tables below show the value for the mpc5200.  A mpc5200b device
-tree should use the "fsl,mpc5200b-<device>","fsl,mpc5200-<device>" form.
-
-Required soc5200 child nodes:
-name				compatible		Description
-----				----------		-----------
-cdm@<addr>			fsl,mpc5200-cdm		Clock Distribution
-interrupt-controller@<addr>	fsl,mpc5200-pic		need an interrupt
-							controller to boot
-bestcomm@<addr>			fsl,mpc5200-bestcomm	Bestcomm DMA controller
-
-Recommended soc5200 child nodes; populate as needed for your board
-name		compatible		Description
-----		----------		-----------
-timer@<addr>	fsl,mpc5200-gpt		 General purpose timers
-gpio@<addr>	fsl,mpc5200-gpio	 MPC5200 simple gpio controller
-gpio@<addr>	fsl,mpc5200-gpio-wkup	 MPC5200 wakeup gpio controller
-rtc@<addr>	fsl,mpc5200-rtc		 Real time clock
-mscan@<addr>	fsl,mpc5200-mscan	 CAN bus controller
-pci@<addr>	fsl,mpc5200-pci		 PCI bridge
-serial@<addr>	fsl,mpc5200-psc-uart	 PSC in serial mode
-i2s@<addr>	fsl,mpc5200-psc-i2s	 PSC in i2s mode
-ac97@<addr>	fsl,mpc5200-psc-ac97	 PSC in ac97 mode
-spi@<addr>	fsl,mpc5200-psc-spi	 PSC in spi mode
-irda@<addr>	fsl,mpc5200-psc-irda	 PSC in IrDA mode
-spi@<addr>	fsl,mpc5200-spi		 MPC5200 spi device
-ethernet@<addr>	fsl,mpc5200-fec		 MPC5200 ethernet device
-ata@<addr>	fsl,mpc5200-ata		 IDE ATA interface
-i2c@<addr>	fsl,mpc5200-i2c		 I2C controller
-usb@<addr>	fsl,mpc5200-ohci,ohci-be USB controller
-xlb@<addr>	fsl,mpc5200-xlb		 XLB arbitrator
-
-fsl,mpc5200-gpt nodes
----------------------
-On the mpc5200 and 5200b, GPT0 has a watchdog timer function.  If the board
-design supports the internal wdt, then the device node for GPT0 should
-include the empty property 'fsl,has-wdt'.  Note that this does not activate
-the watchdog.  The timer will function as a GPT if the timer api is used, and
-it will function as watchdog if the watchdog device is used.  The watchdog
-mode has priority over the gpt mode, i.e. if the watchdog is activated, any
-gpt api call to this timer will fail with -EBUSY.
-
-If you add the property
-	fsl,wdt-on-boot = <n>;
-GPT0 will be marked as in-use watchdog, i.e. blocking every gpt access to it.
-If n>0, the watchdog is started with a timeout of n seconds.  If n=0, the
-configuration of the watchdog is not touched.  This is useful in two cases:
-- just mark GPT0 as watchdog, blocking gpt accesses, and configure it later;
-- do not touch a configuration assigned by the boot loader which supervises
-  the boot process itself.
-
-The watchdog will respect the CONFIG_WATCHDOG_NOWAYOUT option.
-
-An mpc5200-gpt can be used as a single line GPIO controller.  To do so,
-add the following properties to the gpt node:
-	gpio-controller;
-	#gpio-cells = <2>;
-When referencing the GPIO line from another node, the first cell must always
-be zero and the second cell represents the gpio flags and described in the
-gpio device tree binding.
-
-An mpc5200-gpt can be used as a single line edge sensitive interrupt
-controller.  To do so, add the following properties to the gpt node:
-	interrupt-controller;
-	#interrupt-cells = <1>;
-When referencing the IRQ line from another node, the cell represents the
-sense mode; 1 for edge rising, 2 for edge falling.
-
-fsl,mpc5200-psc nodes
----------------------
-The PSCs should include a cell-index which is the index of the PSC in
-hardware.  cell-index is used to determine which shared SoC registers to
-use when setting up PSC clocking.  cell-index number starts at '0'.  ie:
-	PSC1 has 'cell-index = <0>'
-	PSC4 has 'cell-index = <3>'
-
-PSC in i2s mode:  The mpc5200 and mpc5200b PSCs are not compatible when in
-i2s mode.  An 'mpc5200b-psc-i2s' node cannot include 'mpc5200-psc-i2s' in the
-compatible field.
-
-
-fsl,mpc5200-gpio and fsl,mpc5200-gpio-wkup nodes
-------------------------------------------------
-Each GPIO controller node should have the empty property gpio-controller and
-#gpio-cells set to 2. First cell is the GPIO number which is interpreted
-according to the bit numbers in the GPIO control registers. The second cell
-is for flags which is currently unused.
-
-fsl,mpc5200-fec nodes
----------------------
-The FEC node can specify one of the following properties to configure
-the MII link:
-- fsl,7-wire-mode - An empty property that specifies the link uses 7-wire
-                    mode instead of MII
-- current-speed   - Specifies that the MII should be configured for a fixed
-                    speed.  This property should contain two cells.  The
-                    first cell specifies the speed in Mbps and the second
-                    should be '0' for half duplex and '1' for full duplex
-- phy-handle      - Contains a phandle to an Ethernet PHY.
-
-Interrupt controller (fsl,mpc5200-pic) node
--------------------------------------------
-The mpc5200 pic binding splits hardware IRQ numbers into two levels.  The
-split reflects the layout of the PIC hardware itself, which groups
-interrupts into one of three groups; CRIT, MAIN or PERP.  Also, the
-Bestcomm dma engine has it's own set of interrupt sources which are
-cascaded off of peripheral interrupt 0, which the driver interprets as a
-fourth group, SDMA.
-
-The interrupts property for device nodes using the mpc5200 pic consists
-of three cells; <L1 L2 level>
-
-    L1 := [CRIT=0, MAIN=1, PERP=2, SDMA=3]
-    L2 := interrupt number; directly mapped from the value in the
-          "ICTL PerStat, MainStat, CritStat Encoded Register"
-    level := [LEVEL_HIGH=0, EDGE_RISING=1, EDGE_FALLING=2, LEVEL_LOW=3]
-
-For external IRQs, use the following interrupt property values (how to
-specify external interrupts is a frequently asked question):
-External interrupts:
-	external irq0:	interrupts = <0 0 n>;
-	external irq1:	interrupts = <1 1 n>;
-	external irq2:	interrupts = <1 2 n>;
-	external irq3:	interrupts = <1 3 n>;
-'n' is sense (0: level high, 1: edge rising, 2: edge falling 3: level low)
-
-fsl,mpc5200-mscan nodes
------------------------
-See file can.txt in this directory.
diff -druNp linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/fsl/mpic.txt linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/fsl/mpic.txt
--- linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/fsl/mpic.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/fsl/mpic.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,42 +0,0 @@
-* OpenPIC and its interrupt numbers on Freescale's e500/e600 cores
-
-The OpenPIC specification does not specify which interrupt source has to
-become which interrupt number. This is up to the software implementation
-of the interrupt controller. The only requirement is that every
-interrupt source has to have an unique interrupt number / vector number.
-To accomplish this the current implementation assigns the number zero to
-the first source, the number one to the second source and so on until
-all interrupt sources have their unique number.
-Usually the assigned vector number equals the interrupt number mentioned
-in the documentation for a given core / CPU. This is however not true
-for the e500 cores (MPC85XX CPUs) where the documentation distinguishes
-between internal and external interrupt sources and starts counting at
-zero for both of them.
-
-So what to write for external interrupt source X or internal interrupt
-source Y into the device tree? Here is an example:
-
-The memory map for the interrupt controller in the MPC8544[0] shows,
-that the first interrupt source starts at 0x5_0000 (PIC Register Address
-Map-Interrupt Source Configuration Registers). This source becomes the
-number zero therefore:
- External interrupt 0 = interrupt number 0
- External interrupt 1 = interrupt number 1
- External interrupt 2 = interrupt number 2
- ...
-Every interrupt number allocates 0x20 bytes register space. So to get
-its number it is sufficient to shift the lower 16bits to right by five.
-So for the external interrupt 10 we have:
-  0x0140 >> 5 = 10
-
-After the external sources, the internal sources follow. The in core I2C
-controller on the MPC8544 for instance has the internal source number
-27. Oo obtain its interrupt number we take the lower 16bits of its memory
-address (0x5_0560) and shift it right:
- 0x0560 >> 5 = 43
-
-Therefore the I2C device node for the MPC8544 CPU has to have the
-interrupt number 43 specified in the device tree.
-
-[0] MPC8544E PowerQUICCTM III, Integrated Host Processor Family Reference Manual
-    MPC8544ERM Rev. 1 10/2007
diff -druNp linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/fsl/msi-pic.txt linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/fsl/msi-pic.txt
--- linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/fsl/msi-pic.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/fsl/msi-pic.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,36 +0,0 @@
-* Freescale MSI interrupt controller
-
-Required properties:
-- compatible : compatible list, contains 2 entries,
-  first is "fsl,CHIP-msi", where CHIP is the processor(mpc8610, mpc8572,
-  etc.) and the second is "fsl,mpic-msi" or "fsl,ipic-msi" depending on
-  the parent type.
-- reg : should contain the address and the length of the shared message
-  interrupt register set.
-- msi-available-ranges: use <start count> style section to define which
-  msi interrupt can be used in the 256 msi interrupts. This property is
-  optional, without this, all the 256 MSI interrupts can be used.
-- interrupts : each one of the interrupts here is one entry per 32 MSIs,
-  and routed to the host interrupt controller. the interrupts should
-  be set as edge sensitive.
-- interrupt-parent: the phandle for the interrupt controller
-  that services interrupts for this device. for 83xx cpu, the interrupts
-  are routed to IPIC, and for 85xx/86xx cpu the interrupts are routed
-  to MPIC.
-
-Example:
-	msi@41600 {
-		compatible = "fsl,mpc8610-msi", "fsl,mpic-msi";
-		reg = <0x41600 0x80>;
-		msi-available-ranges = <0 0x100>;
-		interrupts = <
-			0xe0 0
-			0xe1 0
-			0xe2 0
-			0xe3 0
-			0xe4 0
-			0xe5 0
-			0xe6 0
-			0xe7 0>;
-		interrupt-parent = <&mpic>;
-	};
diff -druNp linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/fsl/pmc.txt linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/fsl/pmc.txt
--- linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/fsl/pmc.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/fsl/pmc.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,63 +0,0 @@
-* Power Management Controller
-
-Properties:
-- compatible: "fsl,<chip>-pmc".
-
-  "fsl,mpc8349-pmc" should be listed for any chip whose PMC is
-  compatible.  "fsl,mpc8313-pmc" should also be listed for any chip
-  whose PMC is compatible, and implies deep-sleep capability.
-
-  "fsl,mpc8548-pmc" should be listed for any chip whose PMC is
-  compatible.  "fsl,mpc8536-pmc" should also be listed for any chip
-  whose PMC is compatible, and implies deep-sleep capability.
-
-  "fsl,mpc8641d-pmc" should be listed for any chip whose PMC is
-  compatible; all statements below that apply to "fsl,mpc8548-pmc" also
-  apply to "fsl,mpc8641d-pmc".
-
-  Compatibility does not include bit assignments in SCCR/PMCDR/DEVDISR; these
-  bit assignments are indicated via the sleep specifier in each device's
-  sleep property.
-
-- reg: For devices compatible with "fsl,mpc8349-pmc", the first resource
-  is the PMC block, and the second resource is the Clock Configuration
-  block.
-
-  For devices compatible with "fsl,mpc8548-pmc", the first resource
-  is a 32-byte block beginning with DEVDISR.
-
-- interrupts: For "fsl,mpc8349-pmc"-compatible devices, the first
-  resource is the PMC block interrupt.
-
-- fsl,mpc8313-wakeup-timer: For "fsl,mpc8313-pmc"-compatible devices,
-  this is a phandle to an "fsl,gtm" node on which timer 4 can be used as
-  a wakeup source from deep sleep.
-
-Sleep specifiers:
-
-  fsl,mpc8349-pmc: Sleep specifiers consist of one cell.  For each bit
-  that is set in the cell, the corresponding bit in SCCR will be saved
-  and cleared on suspend, and restored on resume.  This sleep controller
-  supports disabling and resuming devices at any time.
-
-  fsl,mpc8536-pmc: Sleep specifiers consist of three cells, the third of
-  which will be ORed into PMCDR upon suspend, and cleared from PMCDR
-  upon resume.  The first two cells are as described for fsl,mpc8578-pmc.
-  This sleep controller only supports disabling devices during system
-  sleep, or permanently.
-
-  fsl,mpc8548-pmc: Sleep specifiers consist of one or two cells, the
-  first of which will be ORed into DEVDISR (and the second into
-  DEVDISR2, if present -- this cell should be zero or absent if the
-  hardware does not have DEVDISR2) upon a request for permanent device
-  disabling.  This sleep controller does not support configuring devices
-  to disable during system sleep (unless supported by another compatible
-  match), or dynamically.
-
-Example:
-
-	power@b00 {
-		compatible = "fsl,mpc8313-pmc", "fsl,mpc8349-pmc";
-		reg = <0xb00 0x100 0xa00 0x100>;
-		interrupts = <80 8>;
-	};
diff -druNp linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/fsl/sata.txt linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/fsl/sata.txt
--- linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/fsl/sata.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/fsl/sata.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,29 +0,0 @@
-* Freescale 8xxx/3.0 Gb/s SATA nodes
-
-SATA nodes are defined to describe on-chip Serial ATA controllers.
-Each SATA port should have its own node.
-
-Required properties:
-- compatible        : compatible list, contains 2 entries, first is
-		 "fsl,CHIP-sata", where CHIP is the processor
-		 (mpc8315, mpc8379, etc.) and the second is
-		 "fsl,pq-sata"
-- interrupts        : <interrupt mapping for SATA IRQ>
-- cell-index        : controller index.
-                          1 for controller @ 0x18000
-                          2 for controller @ 0x19000
-                          3 for controller @ 0x1a000
-                          4 for controller @ 0x1b000
-
-Optional properties:
-- interrupt-parent  : optional, if needed for interrupt mapping
-- reg               : <registers mapping>
-
-Example:
-	sata@18000 {
-		compatible = "fsl,mpc8379-sata", "fsl,pq-sata";
-		reg = <0x18000 0x1000>;
-		cell-index = <1>;
-		interrupts = <2c 8>;
-		interrupt-parent = < &ipic >;
-	};
diff -druNp linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/fsl/sec.txt linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/fsl/sec.txt
--- linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/fsl/sec.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/fsl/sec.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,68 +0,0 @@
-Freescale SoC SEC Security Engines
-
-Required properties:
-
-- compatible : Should contain entries for this and backward compatible
-  SEC versions, high to low, e.g., "fsl,sec2.1", "fsl,sec2.0"
-- reg : Offset and length of the register set for the device
-- interrupts : the SEC's interrupt number
-- fsl,num-channels : An integer representing the number of channels
-  available.
-- fsl,channel-fifo-len : An integer representing the number of
-  descriptor pointers each channel fetch fifo can hold.
-- fsl,exec-units-mask : The bitmask representing what execution units
-  (EUs) are available. It's a single 32-bit cell. EU information
-  should be encoded following the SEC's Descriptor Header Dword
-  EU_SEL0 field documentation, i.e. as follows:
-
-	bit 0  = reserved - should be 0
-	bit 1  = set if SEC has the ARC4 EU (AFEU)
-	bit 2  = set if SEC has the DES/3DES EU (DEU)
-	bit 3  = set if SEC has the message digest EU (MDEU/MDEU-A)
-	bit 4  = set if SEC has the random number generator EU (RNG)
-	bit 5  = set if SEC has the public key EU (PKEU)
-	bit 6  = set if SEC has the AES EU (AESU)
-	bit 7  = set if SEC has the Kasumi EU (KEU)
-	bit 8  = set if SEC has the CRC EU (CRCU)
-	bit 11 = set if SEC has the message digest EU extended alg set (MDEU-B)
-
-remaining bits are reserved for future SEC EUs.
-
-- fsl,descriptor-types-mask : The bitmask representing what descriptors
-  are available. It's a single 32-bit cell. Descriptor type information
-  should be encoded following the SEC's Descriptor Header Dword DESC_TYPE
-  field documentation, i.e. as follows:
-
-	bit 0  = set if SEC supports the aesu_ctr_nonsnoop desc. type
-	bit 1  = set if SEC supports the ipsec_esp descriptor type
-	bit 2  = set if SEC supports the common_nonsnoop desc. type
-	bit 3  = set if SEC supports the 802.11i AES ccmp desc. type
-	bit 4  = set if SEC supports the hmac_snoop_no_afeu desc. type
-	bit 5  = set if SEC supports the srtp descriptor type
-	bit 6  = set if SEC supports the non_hmac_snoop_no_afeu desc.type
-	bit 7  = set if SEC supports the pkeu_assemble descriptor type
-	bit 8  = set if SEC supports the aesu_key_expand_output desc.type
-	bit 9  = set if SEC supports the pkeu_ptmul descriptor type
-	bit 10 = set if SEC supports the common_nonsnoop_afeu desc. type
-	bit 11 = set if SEC supports the pkeu_ptadd_dbl descriptor type
-
-  ..and so on and so forth.
-
-Optional properties:
-
-- interrupt-parent : the phandle for the interrupt controller that
-  services interrupts for this device.
-
-Example:
-
-	/* MPC8548E */
-	crypto@30000 {
-		compatible = "fsl,sec2.1", "fsl,sec2.0";
-		reg = <0x30000 0x10000>;
-		interrupts = <29 2>;
-		interrupt-parent = <&mpic>;
-		fsl,num-channels = <4>;
-		fsl,channel-fifo-len = <24>;
-		fsl,exec-units-mask = <0xfe>;
-		fsl,descriptor-types-mask = <0x12b0ebf>;
-	};
diff -druNp linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/fsl/spi.txt linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/fsl/spi.txt
--- linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/fsl/spi.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/fsl/spi.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,53 +0,0 @@
-* SPI (Serial Peripheral Interface)
-
-Required properties:
-- cell-index : QE SPI subblock index.
-		0: QE subblock SPI1
-		1: QE subblock SPI2
-- compatible : should be "fsl,spi".
-- mode : the SPI operation mode, it can be "cpu" or "cpu-qe".
-- reg : Offset and length of the register set for the device
-- interrupts : <a b> where a is the interrupt number and b is a
-  field that represents an encoding of the sense and level
-  information for the interrupt.  This should be encoded based on
-  the information in section 2) depending on the type of interrupt
-  controller you have.
-- interrupt-parent : the phandle for the interrupt controller that
-  services interrupts for this device.
-
-Optional properties:
-- gpios : specifies the gpio pins to be 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.
-
-Example:
-	spi@4c0 {
-		cell-index = <0>;
-		compatible = "fsl,spi";
-		reg = <4c0 40>;
-		interrupts = <82 0>;
-		interrupt-parent = <700>;
-		mode = "cpu";
-		gpios = <&gpio 18 1	// device reg=<0>
-			 &gpio 19 1>;	// device reg=<1>
-	};
-
-
-* eSPI (Enhanced Serial Peripheral Interface)
-
-Required properties:
-- compatible : should be "fsl,mpc8536-espi".
-- reg : Offset and length of the register set for the device.
-- interrupts : should contain eSPI interrupt, the device has one interrupt.
-- fsl,espi-num-chipselects : the number of the chipselect signals.
-
-Example:
-	spi@110000 {
-		#address-cells = <1>;
-		#size-cells = <0>;
-		compatible = "fsl,mpc8536-espi";
-		reg = <0x110000 0x1000>;
-		interrupts = <53 0x2>;
-		interrupt-parent = <&mpic>;
-		fsl,espi-num-chipselects = <4>;
-	};
diff -druNp linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/fsl/ssi.txt linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/fsl/ssi.txt
--- linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/fsl/ssi.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/fsl/ssi.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,73 +0,0 @@
-Freescale Synchronous Serial Interface
-
-The SSI is a serial device that communicates with audio codecs.  It can
-be programmed in AC97, I2S, left-justified, or right-justified modes.
-
-Required properties:
-- compatible:       Compatible list, contains "fsl,ssi".
-- cell-index:       The SSI, <0> = SSI1, <1> = SSI2, and so on.
-- reg:              Offset and length of the register set for the device.
-- interrupts:       <a b> where a is the interrupt number and b is a
-                    field that represents an encoding of the sense and
-                    level information for the interrupt.  This should be
-                    encoded based on the information in section 2)
-                    depending on the type of interrupt controller you
-                    have.
-- interrupt-parent: The phandle for the interrupt controller that
-                    services interrupts for this device.
-- fsl,mode:         The operating mode for the SSI interface.
-                    "i2s-slave" - I2S mode, SSI is clock slave
-                    "i2s-master" - I2S mode, SSI is clock master
-                    "lj-slave" - left-justified mode, SSI is clock slave
-                    "lj-master" - l.j. mode, SSI is clock master
-                    "rj-slave" - right-justified mode, SSI is clock slave
-                    "rj-master" - r.j., SSI is clock master
-                    "ac97-slave" - AC97 mode, SSI is clock slave
-                    "ac97-master" - AC97 mode, SSI is clock master
-- fsl,playback-dma: Phandle to a node for the DMA channel to use for
-                    playback of audio.  This is typically dictated by SOC
-                    design.  See the notes below.
-- fsl,capture-dma:  Phandle to a node for the DMA channel to use for
-                    capture (recording) of audio.  This is typically dictated
-                    by SOC design.  See the notes below.
-- fsl,fifo-depth:   The number of elements in the transmit and receive FIFOs.
-                    This number is the maximum allowed value for SFCSR[TFWM0].
-- fsl,ssi-asynchronous:
-                    If specified, the SSI is to be programmed in asynchronous
-                    mode.  In this mode, pins SRCK, STCK, SRFS, and STFS must
-                    all be connected to valid signals.  In synchronous mode,
-                    SRCK and SRFS are ignored.  Asynchronous mode allows
-                    playback and capture to use different sample sizes and
-                    sample rates.  Some drivers may require that SRCK and STCK
-                    be connected together, and SRFS and STFS be connected
-                    together.  This would still allow different sample sizes,
-                    but not different sample rates.
-
-Optional properties:
-- codec-handle:     Phandle to a 'codec' node that defines an audio
-                    codec connected to this SSI.  This node is typically
-                    a child of an I2C or other control node.
-
-Child 'codec' node required properties:
-- compatible:       Compatible list, contains the name of the codec
-
-Child 'codec' node optional properties:
-- clock-frequency:  The frequency of the input clock, which typically comes
-                    from an on-board dedicated oscillator.
-
-Notes on fsl,playback-dma and fsl,capture-dma:
-
-On SOCs that have an SSI, specific DMA channels are hard-wired for playback
-and capture.  On the MPC8610, for example, SSI1 must use DMA channel 0 for
-playback and DMA channel 1 for capture.  SSI2 must use DMA channel 2 for
-playback and DMA channel 3 for capture.  The developer can choose which
-DMA controller to use, but the channels themselves are hard-wired.  The
-purpose of these two properties is to represent this hardware design.
-
-The device tree nodes for the DMA channels that are referenced by
-"fsl,playback-dma" and "fsl,capture-dma" must be marked as compatible with
-"fsl,ssi-dma-channel".  The SOC-specific compatible string (e.g.
-"fsl,mpc8610-dma-channel") can remain.  If these nodes are left as
-"fsl,elo-dma-channel" or "fsl,eloplus-dma-channel", then the generic Elo DMA
-drivers (fsldma) will attempt to use them, and it will conflict with the
-sound drivers.
diff -druNp linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/fsl/tsec.txt linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/fsl/tsec.txt
--- linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/fsl/tsec.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/fsl/tsec.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,76 +0,0 @@
-* MDIO IO device
-
-The MDIO is a bus to which the PHY devices are connected.  For each
-device that exists on this bus, a child node should be created.  See
-the definition of the PHY node in booting-without-of.txt for an example
-of how to define a PHY.
-
-Required properties:
-  - reg : Offset and length of the register set for the device
-  - compatible : Should define the compatible device type for the
-    mdio.  Currently, this is most likely to be "fsl,gianfar-mdio"
-
-Example:
-
-	mdio@24520 {
-		reg = <24520 20>;
-		compatible = "fsl,gianfar-mdio";
-
-		ethernet-phy@0 {
-			......
-		};
-	};
-
-* TBI Internal MDIO bus
-
-As of this writing, every tsec is associated with an internal TBI PHY.
-This PHY is accessed through the local MDIO bus.  These buses are defined
-similarly to the mdio buses, except they are compatible with "fsl,gianfar-tbi".
-The TBI PHYs underneath them are similar to normal PHYs, but the reg property
-is considered instructive, rather than descriptive.  The reg property should
-be chosen so it doesn't interfere with other PHYs on the bus.
-
-* Gianfar-compatible ethernet nodes
-
-Properties:
-
-  - device_type : Should be "network"
-  - model : Model of the device.  Can be "TSEC", "eTSEC", or "FEC"
-  - compatible : Should be "gianfar"
-  - reg : Offset and length of the register set for the device
-  - local-mac-address : List of bytes representing the ethernet address of
-    this controller
-  - interrupts : For FEC devices, the first interrupt is the device's
-    interrupt.  For TSEC and eTSEC devices, the first interrupt is
-    transmit, the second is receive, and the third is error.
-  - phy-handle : The phandle for the PHY connected to this ethernet
-    controller.
-  - fixed-link : <a b c d e> where a is emulated phy id - choose any,
-    but unique to the all specified fixed-links, b is duplex - 0 half,
-    1 full, c is link speed - d#10/d#100/d#1000, d is pause - 0 no
-    pause, 1 pause, e is asym_pause - 0 no asym_pause, 1 asym_pause.
-  - phy-connection-type : a string naming the controller/PHY interface type,
-    i.e., "mii" (default), "rmii", "gmii", "rgmii", "rgmii-id", "sgmii",
-    "tbi", or "rtbi".  This property is only really needed if the connection
-    is of type "rgmii-id", as all other connection types are detected by
-    hardware.
-  - fsl,magic-packet : If present, indicates that the hardware supports
-    waking up via magic packet.
-  - bd-stash : If present, indicates that the hardware supports stashing
-    buffer descriptors in the L2.
-  - rx-stash-len : Denotes the number of bytes of a received buffer to stash
-    in the L2.
-  - rx-stash-idx : Denotes the index of the first byte from the received
-    buffer to stash in the L2.
-
-Example:
-	ethernet@24000 {
-		device_type = "network";
-		model = "TSEC";
-		compatible = "gianfar";
-		reg = <0x24000 0x1000>;
-		local-mac-address = [ 00 E0 0C 00 73 00 ];
-		interrupts = <29 2 30 2 34 2>;
-		interrupt-parent = <&mpic>;
-		phy-handle = <&phy0>
-	};
diff -druNp linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/fsl/upm-nand.txt linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/fsl/upm-nand.txt
--- linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/fsl/upm-nand.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/fsl/upm-nand.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,63 +0,0 @@
-Freescale Localbus UPM programmed to work with NAND flash
-
-Required properties:
-- compatible : "fsl,upm-nand".
-- reg : should specify localbus chip select and size used for the chip.
-- fsl,upm-addr-offset : UPM pattern offset for the address latch.
-- fsl,upm-cmd-offset : UPM pattern offset for the command latch.
-
-Optional properties:
-- fsl,upm-wait-flags : add chip-dependent short delays after running the
-	UPM pattern (0x1), after writing a data byte (0x2) or after
-	writing out a buffer (0x4).
-- fsl,upm-addr-line-cs-offsets : address offsets for multi-chip support.
-	The corresponding address lines are used to select the chip.
-- gpios : may specify optional GPIOs connected to the Ready-Not-Busy pins
-	(R/B#). For multi-chip devices, "n" GPIO definitions are required
-	according to the number of chips.
-- chip-delay : chip dependent delay for transfering data from array to
-	read registers (tR). Required if property "gpios" is not used
-	(R/B# pins not connected).
-
-Examples:
-
-upm@1,0 {
-	compatible = "fsl,upm-nand";
-	reg = <1 0 1>;
-	fsl,upm-addr-offset = <16>;
-	fsl,upm-cmd-offset = <8>;
-	gpios = <&qe_pio_e 18 0>;
-
-	flash {
-		#address-cells = <1>;
-		#size-cells = <1>;
-		compatible = "...";
-
-		partition@0 {
-			...
-		};
-	};
-};
-
-upm@3,0 {
-	#address-cells = <0>;
-	#size-cells = <0>;
-	compatible = "tqc,tqm8548-upm-nand", "fsl,upm-nand";
-	reg = <3 0x0 0x800>;
-	fsl,upm-addr-offset = <0x10>;
-	fsl,upm-cmd-offset = <0x08>;
-	/* Multi-chip NAND device */
-	fsl,upm-addr-line-cs-offsets = <0x0 0x200>;
-	fsl,upm-wait-flags = <0x5>;
-	chip-delay = <25>; // in micro-seconds
-
-	nand@0 {
-		#address-cells = <1>;
-		#size-cells = <1>;
-
-		partition@0 {
-			    label = "fs";
-			    reg = <0x00000000 0x10000000>;
-		};
-	};
-};
diff -druNp linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/fsl/usb.txt linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/fsl/usb.txt
--- linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/fsl/usb.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/fsl/usb.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,81 +0,0 @@
-Freescale SOC USB controllers
-
-The device node for a USB controller that is part of a Freescale
-SOC is as described in the document "Open Firmware Recommended
-Practice : Universal Serial Bus" with the following modifications
-and additions :
-
-Required properties :
- - compatible : Should be "fsl-usb2-mph" for multi port host USB
-   controllers, or "fsl-usb2-dr" for dual role USB controllers
-   or "fsl,mpc5121-usb2-dr" for dual role USB controllers of MPC5121
- - phy_type : For multi port host USB controllers, should be one of
-   "ulpi", or "serial". For dual role USB controllers, should be
-   one of "ulpi", "utmi", "utmi_wide", or "serial".
- - reg : Offset and length of the register set for the device
- - port0 : boolean; if defined, indicates port0 is connected for
-   fsl-usb2-mph compatible controllers.  Either this property or
-   "port1" (or both) must be defined for "fsl-usb2-mph" compatible
-   controllers.
- - port1 : boolean; if defined, indicates port1 is connected for
-   fsl-usb2-mph compatible controllers.  Either this property or
-   "port0" (or both) must be defined for "fsl-usb2-mph" compatible
-   controllers.
- - dr_mode : indicates the working mode for "fsl-usb2-dr" compatible
-   controllers.  Can be "host", "peripheral", or "otg".  Default to
-   "host" if not defined for backward compatibility.
-
-Recommended properties :
- - interrupts : <a b> where a is the interrupt number and b is a
-   field that represents an encoding of the sense and level
-   information for the interrupt.  This should be encoded based on
-   the information in section 2) depending on the type of interrupt
-   controller you have.
- - interrupt-parent : the phandle for the interrupt controller that
-   services interrupts for this device.
-
-Optional properties :
- - fsl,invert-drvvbus : boolean; for MPC5121 USB0 only. Indicates the
-   port power polarity of internal PHY signal DRVVBUS is inverted.
- - fsl,invert-pwr-fault : boolean; for MPC5121 USB0 only. Indicates
-   the PWR_FAULT signal polarity is inverted.
-
-Example multi port host USB controller device node :
-	usb@22000 {
-		compatible = "fsl-usb2-mph";
-		reg = <22000 1000>;
-		#address-cells = <1>;
-		#size-cells = <0>;
-		interrupt-parent = <700>;
-		interrupts = <27 1>;
-		phy_type = "ulpi";
-		port0;
-		port1;
-	};
-
-Example dual role USB controller device node :
-	usb@23000 {
-		compatible = "fsl-usb2-dr";
-		reg = <23000 1000>;
-		#address-cells = <1>;
-		#size-cells = <0>;
-		interrupt-parent = <700>;
-		interrupts = <26 1>;
-		dr_mode = "otg";
-		phy = "ulpi";
-	};
-
-Example dual role USB controller device node for MPC5121ADS:
-
-	usb@4000 {
-		compatible = "fsl,mpc5121-usb2-dr";
-		reg = <0x4000 0x1000>;
-		#address-cells = <1>;
-		#size-cells = <0>;
-		interrupt-parent = < &ipic >;
-		interrupts = <44 0x8>;
-		dr_mode = "otg";
-		phy_type = "utmi_wide";
-		fsl,invert-drvvbus;
-		fsl,invert-pwr-fault;
-	};
diff -druNp linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/gpio/gpio.txt linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/gpio/gpio.txt
--- linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/gpio/gpio.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/gpio/gpio.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,50 +0,0 @@
-Specifying GPIO information for devices
-============================================
-
-1) gpios property
------------------
-
-Nodes that makes use of GPIOs should define them using `gpios' property,
-format of which is: <&gpio-controller1-phandle gpio1-specifier
-		     &gpio-controller2-phandle gpio2-specifier
-		     0 /* holes are permitted, means no GPIO 3 */
-		     &gpio-controller4-phandle gpio4-specifier
-		     ...>;
-
-Note that gpio-specifier length is controller dependent.
-
-gpio-specifier may encode: bank, pin position inside the bank,
-whether pin is open-drain and whether pin is logically inverted.
-
-Example of the node using GPIOs:
-
-	node {
-		gpios = <&qe_pio_e 18 0>;
-	};
-
-In this example gpio-specifier is "18 0" and encodes GPIO pin number,
-and empty GPIO flags as accepted by the "qe_pio_e" gpio-controller.
-
-2) gpio-controller nodes
-------------------------
-
-Every GPIO controller node must have #gpio-cells property defined,
-this information will be used to translate gpio-specifiers.
-
-Example of two SOC GPIO banks defined as gpio-controller nodes:
-
-	qe_pio_a: gpio-controller@1400 {
-		#gpio-cells = <2>;
-		compatible = "fsl,qe-pario-bank-a", "fsl,qe-pario-bank";
-		reg = <0x1400 0x18>;
-		gpio-controller;
-	};
-
-	qe_pio_e: gpio-controller@1460 {
-		#gpio-cells = <2>;
-		compatible = "fsl,qe-pario-bank-e", "fsl,qe-pario-bank";
-		reg = <0x1460 0x18>;
-		gpio-controller;
-	};
-
-
diff -druNp linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/gpio/led.txt linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/gpio/led.txt
--- linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/gpio/led.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/gpio/led.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,58 +0,0 @@
-LEDs connected to GPIO lines
-
-Required properties:
-- compatible : should be "gpio-leds".
-
-Each LED is represented as a sub-node of the gpio-leds device.  Each
-node's name represents the name of the corresponding LED.
-
-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
-  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).
-- linux,default-trigger :  (optional) This parameter, if present, is a
-  string defining the trigger assigned to the LED.  Current triggers are:
-    "backlight" - LED will act as a back-light, controlled by the framebuffer
-		  system
-    "default-on" - LED will turn on, but see "default-state" below
-    "heartbeat" - LED "double" flashes at a load average based rate
-    "ide-disk" - LED indicates disk activity
-    "timer" - LED flashes at a fixed, configurable rate
-- default-state:  (optional) The initial state of the LED.  Valid
-  values are "on", "off", and "keep".  If the LED is already on or off
-  and the default-state property is set the to same value, then no
-  glitch should be produced where the LED momentarily turns off (or
-  on).  The "keep" setting will keep the LED at whatever its current
-  state is, without producing a glitch.  The default is off if this
-  property is not present.
-
-Examples:
-
-leds {
-	compatible = "gpio-leds";
-	hdd {
-		label = "IDE Activity";
-		gpios = <&mcu_pio 0 1>; /* Active low */
-		linux,default-trigger = "ide-disk";
-	};
-
-	fault {
-		gpios = <&mcu_pio 1 0>;
-		/* Keep LED on if BIOS detected hardware fault */
-		default-state = "keep";
-	};
-};
-
-run-control {
-	compatible = "gpio-leds";
-	red {
-		gpios = <&mpc8572 6 0>;
-		default-state = "off";
-	};
-	green {
-		gpios = <&mpc8572 7 0>;
-		default-state = "on";
-	};
-}
diff -druNp linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/gpio/mdio.txt linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/gpio/mdio.txt
--- linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/gpio/mdio.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/gpio/mdio.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,19 +0,0 @@
-MDIO on GPIOs
-
-Currently defined compatibles:
-- virtual,gpio-mdio
-
-MDC and MDIO lines connected to GPIO controllers are listed in the
-gpios property as described in section VIII.1 in the following order:
-
-MDC, MDIO.
-
-Example:
-
-mdio {
-	compatible = "virtual,mdio-gpio";
-	#address-cells = <1>;
-	#size-cells = <0>;
-	gpios = <&qe_pio_a 11
-		 &qe_pio_c 6>;
-};
diff -druNp linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/marvell.txt linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/marvell.txt
--- linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/marvell.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/marvell.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,521 +0,0 @@
-Marvell Discovery mv64[345]6x System Controller chips
-===========================================================
-
-The Marvell mv64[345]60 series of system controller chips contain
-many of the peripherals needed to implement a complete computer
-system.  In this section, we define device tree nodes to describe
-the system controller chip itself and each of the peripherals
-which it contains.  Compatible string values for each node are
-prefixed with the string "marvell,", for Marvell Technology Group Ltd.
-
-1) The /system-controller node
-
-  This node is used to represent the system-controller and must be
-  present when the system uses a system controller chip. The top-level
-  system-controller node contains information that is global to all
-  devices within the system controller chip. The node name begins
-  with "system-controller" followed by the unit address, which is
-  the base address of the memory-mapped register set for the system
-  controller chip.
-
-  Required properties:
-
-    - ranges : Describes the translation of system controller addresses
-      for memory mapped registers.
-    - clock-frequency: Contains the main clock frequency for the system
-      controller chip.
-    - reg : This property defines the address and size of the
-      memory-mapped registers contained within the system controller
-      chip.  The address specified in the "reg" property should match
-      the unit address of the system-controller node.
-    - #address-cells : Address representation for system controller
-      devices.  This field represents the number of cells needed to
-      represent the address of the memory-mapped registers of devices
-      within the system controller chip.
-    - #size-cells : Size representation for the memory-mapped
-      registers within the system controller chip.
-    - #interrupt-cells : Defines the width of cells used to represent
-      interrupts.
-
-  Optional properties:
-
-    - model : The specific model of the system controller chip.  Such
-      as, "mv64360", "mv64460", or "mv64560".
-    - compatible : A string identifying the compatibility identifiers
-      of the system controller chip.
-
-  The system-controller node contains child nodes for each system
-  controller device that the platform uses.  Nodes should not be created
-  for devices which exist on the system controller chip but are not used
-
-  Example Marvell Discovery mv64360 system-controller node:
-
-    system-controller@f1000000 { /* Marvell Discovery mv64360 */
-	    #address-cells = <1>;
-	    #size-cells = <1>;
-	    model = "mv64360";                      /* Default */
-	    compatible = "marvell,mv64360";
-	    clock-frequency = <133333333>;
-	    reg = <0xf1000000 0x10000>;
-	    virtual-reg = <0xf1000000>;
-	    ranges = <0x88000000 0x88000000 0x1000000 /* PCI 0 I/O Space */
-		    0x80000000 0x80000000 0x8000000 /* PCI 0 MEM Space */
-		    0xa0000000 0xa0000000 0x4000000 /* User FLASH */
-		    0x00000000 0xf1000000 0x0010000 /* Bridge's regs */
-		    0xf2000000 0xf2000000 0x0040000>;/* Integrated SRAM */
-
-	    [ child node definitions... ]
-    }
-
-2) Child nodes of /system-controller
-
-   a) Marvell Discovery MDIO bus
-
-   The MDIO is a bus to which the PHY devices are connected.  For each
-   device that exists on this bus, a child node should be created.  See
-   the definition of the PHY node below for an example of how to define
-   a PHY.
-
-   Required properties:
-     - #address-cells : Should be <1>
-     - #size-cells : Should be <0>
-     - device_type : Should be "mdio"
-     - compatible : Should be "marvell,mv64360-mdio"
-
-   Example:
-
-     mdio {
-	     #address-cells = <1>;
-	     #size-cells = <0>;
-	     device_type = "mdio";
-	     compatible = "marvell,mv64360-mdio";
-
-	     ethernet-phy@0 {
-		     ......
-	     };
-     };
-
-
-   b) Marvell Discovery ethernet controller
-
-   The Discover ethernet controller is described with two levels
-   of nodes.  The first level describes an ethernet silicon block
-   and the second level describes up to 3 ethernet nodes within
-   that block.  The reason for the multiple levels is that the
-   registers for the node are interleaved within a single set
-   of registers.  The "ethernet-block" level describes the
-   shared register set, and the "ethernet" nodes describe ethernet
-   port-specific properties.
-
-   Ethernet block node
-
-   Required properties:
-     - #address-cells : <1>
-     - #size-cells : <0>
-     - compatible : "marvell,mv64360-eth-block"
-     - reg : Offset and length of the register set for this block
-
-   Example Discovery Ethernet block node:
-     ethernet-block@2000 {
-	     #address-cells = <1>;
-	     #size-cells = <0>;
-	     compatible = "marvell,mv64360-eth-block";
-	     reg = <0x2000 0x2000>;
-	     ethernet@0 {
-		     .......
-	     };
-     };
-
-   Ethernet port node
-
-   Required properties:
-     - device_type : Should be "network".
-     - compatible : Should be "marvell,mv64360-eth".
-     - reg : Should be <0>, <1>, or <2>, according to which registers
-       within the silicon block the device uses.
-     - interrupts : <a> where a is the interrupt number for the port.
-     - interrupt-parent : the phandle for the interrupt controller
-       that services interrupts for this device.
-     - phy : the phandle for the PHY connected to this ethernet
-       controller.
-     - local-mac-address : 6 bytes, MAC address
-
-   Example Discovery Ethernet port node:
-     ethernet@0 {
-	     device_type = "network";
-	     compatible = "marvell,mv64360-eth";
-	     reg = <0>;
-	     interrupts = <32>;
-	     interrupt-parent = <&PIC>;
-	     phy = <&PHY0>;
-	     local-mac-address = [ 00 00 00 00 00 00 ];
-     };
-
-
-
-   c) Marvell Discovery PHY nodes
-
-   Required properties:
-     - device_type : Should be "ethernet-phy"
-     - interrupts : <a> where a is the interrupt number for this phy.
-     - interrupt-parent : the phandle for the interrupt controller that
-       services interrupts for this device.
-     - reg : The ID number for the phy, usually a small integer
-
-   Example Discovery PHY node:
-     ethernet-phy@1 {
-	     device_type = "ethernet-phy";
-	     compatible = "broadcom,bcm5421";
-	     interrupts = <76>;      /* GPP 12 */
-	     interrupt-parent = <&PIC>;
-	     reg = <1>;
-     };
-
-
-   d) Marvell Discovery SDMA nodes
-
-   Represent DMA hardware associated with the MPSC (multiprotocol
-   serial controllers).
-
-   Required properties:
-     - compatible : "marvell,mv64360-sdma"
-     - reg : Offset and length of the register set for this device
-     - interrupts : <a> where a is the interrupt number for the DMA
-       device.
-     - interrupt-parent : the phandle for the interrupt controller
-       that services interrupts for this device.
-
-   Example Discovery SDMA node:
-     sdma@4000 {
-	     compatible = "marvell,mv64360-sdma";
-	     reg = <0x4000 0xc18>;
-	     virtual-reg = <0xf1004000>;
-	     interrupts = <36>;
-	     interrupt-parent = <&PIC>;
-     };
-
-
-   e) Marvell Discovery BRG nodes
-
-   Represent baud rate generator hardware associated with the MPSC
-   (multiprotocol serial controllers).
-
-   Required properties:
-     - compatible : "marvell,mv64360-brg"
-     - reg : Offset and length of the register set for this device
-     - clock-src : A value from 0 to 15 which selects the clock
-       source for the baud rate generator.  This value corresponds
-       to the CLKS value in the BRGx configuration register.  See
-       the mv64x60 User's Manual.
-     - clock-frequence : The frequency (in Hz) of the baud rate
-       generator's input clock.
-     - current-speed : The current speed setting (presumably by
-       firmware) of the baud rate generator.
-
-   Example Discovery BRG node:
-     brg@b200 {
-	     compatible = "marvell,mv64360-brg";
-	     reg = <0xb200 0x8>;
-	     clock-src = <8>;
-	     clock-frequency = <133333333>;
-	     current-speed = <9600>;
-     };
-
-
-   f) Marvell Discovery CUNIT nodes
-
-   Represent the Serial Communications Unit device hardware.
-
-   Required properties:
-     - reg : Offset and length of the register set for this device
-
-   Example Discovery CUNIT node:
-     cunit@f200 {
-	     reg = <0xf200 0x200>;
-     };
-
-
-   g) Marvell Discovery MPSCROUTING nodes
-
-   Represent the Discovery's MPSC routing hardware
-
-   Required properties:
-     - reg : Offset and length of the register set for this device
-
-   Example Discovery CUNIT node:
-     mpscrouting@b500 {
-	     reg = <0xb400 0xc>;
-     };
-
-
-   h) Marvell Discovery MPSCINTR nodes
-
-   Represent the Discovery's MPSC DMA interrupt hardware registers
-   (SDMA cause and mask registers).
-
-   Required properties:
-     - reg : Offset and length of the register set for this device
-
-   Example Discovery MPSCINTR node:
-     mpsintr@b800 {
-	     reg = <0xb800 0x100>;
-     };
-
-
-   i) Marvell Discovery MPSC nodes
-
-   Represent the Discovery's MPSC (Multiprotocol Serial Controller)
-   serial port.
-
-   Required properties:
-     - device_type : "serial"
-     - compatible : "marvell,mv64360-mpsc"
-     - reg : Offset and length of the register set for this device
-     - sdma : the phandle for the SDMA node used by this port
-     - brg : the phandle for the BRG node used by this port
-     - cunit : the phandle for the CUNIT node used by this port
-     - mpscrouting : the phandle for the MPSCROUTING node used by this port
-     - mpscintr : the phandle for the MPSCINTR node used by this port
-     - cell-index : the hardware index of this cell in the MPSC core
-     - max_idle : value needed for MPSC CHR3 (Maximum Frame Length)
-       register
-     - interrupts : <a> where a is the interrupt number for the MPSC.
-     - interrupt-parent : the phandle for the interrupt controller
-       that services interrupts for this device.
-
-   Example Discovery MPSCINTR node:
-     mpsc@8000 {
-	     device_type = "serial";
-	     compatible = "marvell,mv64360-mpsc";
-	     reg = <0x8000 0x38>;
-	     virtual-reg = <0xf1008000>;
-	     sdma = <&SDMA0>;
-	     brg = <&BRG0>;
-	     cunit = <&CUNIT>;
-	     mpscrouting = <&MPSCROUTING>;
-	     mpscintr = <&MPSCINTR>;
-	     cell-index = <0>;
-	     max_idle = <40>;
-	     interrupts = <40>;
-	     interrupt-parent = <&PIC>;
-     };
-
-
-   j) Marvell Discovery Watch Dog Timer nodes
-
-   Represent the Discovery's watchdog timer hardware
-
-   Required properties:
-     - compatible : "marvell,mv64360-wdt"
-     - reg : Offset and length of the register set for this device
-
-   Example Discovery Watch Dog Timer node:
-     wdt@b410 {
-	     compatible = "marvell,mv64360-wdt";
-	     reg = <0xb410 0x8>;
-     };
-
-
-   k) Marvell Discovery I2C nodes
-
-   Represent the Discovery's I2C hardware
-
-   Required properties:
-     - device_type : "i2c"
-     - compatible : "marvell,mv64360-i2c"
-     - reg : Offset and length of the register set for this device
-     - interrupts : <a> where a is the interrupt number for the I2C.
-     - interrupt-parent : the phandle for the interrupt controller
-       that services interrupts for this device.
-
-   Example Discovery I2C node:
-	     compatible = "marvell,mv64360-i2c";
-	     reg = <0xc000 0x20>;
-	     virtual-reg = <0xf100c000>;
-	     interrupts = <37>;
-	     interrupt-parent = <&PIC>;
-     };
-
-
-   l) Marvell Discovery PIC (Programmable Interrupt Controller) nodes
-
-   Represent the Discovery's PIC hardware
-
-   Required properties:
-     - #interrupt-cells : <1>
-     - #address-cells : <0>
-     - compatible : "marvell,mv64360-pic"
-     - reg : Offset and length of the register set for this device
-     - interrupt-controller
-
-   Example Discovery PIC node:
-     pic {
-	     #interrupt-cells = <1>;
-	     #address-cells = <0>;
-	     compatible = "marvell,mv64360-pic";
-	     reg = <0x0 0x88>;
-	     interrupt-controller;
-     };
-
-
-   m) Marvell Discovery MPP (Multipurpose Pins) multiplexing nodes
-
-   Represent the Discovery's MPP hardware
-
-   Required properties:
-     - compatible : "marvell,mv64360-mpp"
-     - reg : Offset and length of the register set for this device
-
-   Example Discovery MPP node:
-     mpp@f000 {
-	     compatible = "marvell,mv64360-mpp";
-	     reg = <0xf000 0x10>;
-     };
-
-
-   n) Marvell Discovery GPP (General Purpose Pins) nodes
-
-   Represent the Discovery's GPP hardware
-
-   Required properties:
-     - compatible : "marvell,mv64360-gpp"
-     - reg : Offset and length of the register set for this device
-
-   Example Discovery GPP node:
-     gpp@f000 {
-	     compatible = "marvell,mv64360-gpp";
-	     reg = <0xf100 0x20>;
-     };
-
-
-   o) Marvell Discovery PCI host bridge node
-
-   Represents the Discovery's PCI host bridge device.  The properties
-   for this node conform to Rev 2.1 of the PCI Bus Binding to IEEE
-   1275-1994.  A typical value for the compatible property is
-   "marvell,mv64360-pci".
-
-   Example Discovery PCI host bridge node
-     pci@80000000 {
-	     #address-cells = <3>;
-	     #size-cells = <2>;
-	     #interrupt-cells = <1>;
-	     device_type = "pci";
-	     compatible = "marvell,mv64360-pci";
-	     reg = <0xcf8 0x8>;
-	     ranges = <0x01000000 0x0        0x0
-			     0x88000000 0x0 0x01000000
-		       0x02000000 0x0 0x80000000
-			     0x80000000 0x0 0x08000000>;
-	     bus-range = <0 255>;
-	     clock-frequency = <66000000>;
-	     interrupt-parent = <&PIC>;
-	     interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
-	     interrupt-map = <
-		     /* IDSEL 0x0a */
-		     0x5000 0 0 1 &PIC 80
-		     0x5000 0 0 2 &PIC 81
-		     0x5000 0 0 3 &PIC 91
-		     0x5000 0 0 4 &PIC 93
-
-		     /* IDSEL 0x0b */
-		     0x5800 0 0 1 &PIC 91
-		     0x5800 0 0 2 &PIC 93
-		     0x5800 0 0 3 &PIC 80
-		     0x5800 0 0 4 &PIC 81
-
-		     /* IDSEL 0x0c */
-		     0x6000 0 0 1 &PIC 91
-		     0x6000 0 0 2 &PIC 93
-		     0x6000 0 0 3 &PIC 80
-		     0x6000 0 0 4 &PIC 81
-
-		     /* IDSEL 0x0d */
-		     0x6800 0 0 1 &PIC 93
-		     0x6800 0 0 2 &PIC 80
-		     0x6800 0 0 3 &PIC 81
-		     0x6800 0 0 4 &PIC 91
-	     >;
-     };
-
-
-   p) Marvell Discovery CPU Error nodes
-
-   Represent the Discovery's CPU error handler device.
-
-   Required properties:
-     - compatible : "marvell,mv64360-cpu-error"
-     - reg : Offset and length of the register set for this device
-     - interrupts : the interrupt number for this device
-     - interrupt-parent : the phandle for the interrupt controller
-       that services interrupts for this device.
-
-   Example Discovery CPU Error node:
-     cpu-error@0070 {
-	     compatible = "marvell,mv64360-cpu-error";
-	     reg = <0x70 0x10 0x128 0x28>;
-	     interrupts = <3>;
-	     interrupt-parent = <&PIC>;
-     };
-
-
-   q) Marvell Discovery SRAM Controller nodes
-
-   Represent the Discovery's SRAM controller device.
-
-   Required properties:
-     - compatible : "marvell,mv64360-sram-ctrl"
-     - reg : Offset and length of the register set for this device
-     - interrupts : the interrupt number for this device
-     - interrupt-parent : the phandle for the interrupt controller
-       that services interrupts for this device.
-
-   Example Discovery SRAM Controller node:
-     sram-ctrl@0380 {
-	     compatible = "marvell,mv64360-sram-ctrl";
-	     reg = <0x380 0x80>;
-	     interrupts = <13>;
-	     interrupt-parent = <&PIC>;
-     };
-
-
-   r) Marvell Discovery PCI Error Handler nodes
-
-   Represent the Discovery's PCI error handler device.
-
-   Required properties:
-     - compatible : "marvell,mv64360-pci-error"
-     - reg : Offset and length of the register set for this device
-     - interrupts : the interrupt number for this device
-     - interrupt-parent : the phandle for the interrupt controller
-       that services interrupts for this device.
-
-   Example Discovery PCI Error Handler node:
-     pci-error@1d40 {
-	     compatible = "marvell,mv64360-pci-error";
-	     reg = <0x1d40 0x40 0xc28 0x4>;
-	     interrupts = <12>;
-	     interrupt-parent = <&PIC>;
-     };
-
-
-   s) Marvell Discovery Memory Controller nodes
-
-   Represent the Discovery's memory controller device.
-
-   Required properties:
-     - compatible : "marvell,mv64360-mem-ctrl"
-     - reg : Offset and length of the register set for this device
-     - interrupts : the interrupt number for this device
-     - interrupt-parent : the phandle for the interrupt controller
-       that services interrupts for this device.
-
-   Example Discovery Memory Controller node:
-     mem-ctrl@1400 {
-	     compatible = "marvell,mv64360-mem-ctrl";
-	     reg = <0x1400 0x60>;
-	     interrupts = <17>;
-	     interrupt-parent = <&PIC>;
-     };
-
-
diff -druNp linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/mmc-spi-slot.txt linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/mmc-spi-slot.txt
--- linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/mmc-spi-slot.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/mmc-spi-slot.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,23 +0,0 @@
-MMC/SD/SDIO slot directly connected to a SPI bus
-
-Required properties:
-- compatible : should be "mmc-spi-slot".
-- reg : should specify SPI address (chip-select number).
-- spi-max-frequency : maximum frequency for this device (Hz).
-- voltage-ranges : two cells are required, first cell specifies minimum
-  slot voltage (mV), second cell specifies maximum slot voltage (mV).
-  Several ranges could be specified.
-- gpios : (optional) may specify GPIOs in this order: Card-Detect GPIO,
-  Write-Protect GPIO.
-
-Example:
-
-	mmc-slot@0 {
-		compatible = "fsl,mpc8323rdb-mmc-slot",
-			     "mmc-spi-slot";
-		reg = <0>;
-		gpios = <&qe_pio_d 14 1
-			 &qe_pio_d 15 0>;
-		voltage-ranges = <3300 3300>;
-		spi-max-frequency = <50000000>;
-	};
diff -druNp linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/mtd-physmap.txt linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/mtd-physmap.txt
--- linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/mtd-physmap.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/mtd-physmap.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,90 +0,0 @@
-CFI or JEDEC memory-mapped NOR flash, MTD-RAM (NVRAM...)
-
-Flash chips (Memory Technology Devices) are often used for solid state
-file systems on embedded devices.
-
- - compatible : should contain the specific model of mtd chip(s)
-   used, if known, followed by either "cfi-flash", "jedec-flash"
-   or "mtd-ram".
- - reg : Address range(s) of the mtd chip(s)
-   It's possible to (optionally) define multiple "reg" tuples so that
-   non-identical chips can be described in one node.
- - bank-width : Width (in bytes) of the bank.  Equal to the
-   device width times the number of interleaved chips.
- - device-width : (optional) Width of a single mtd chip.  If
-   omitted, assumed to be equal to 'bank-width'.
- - #address-cells, #size-cells : Must be present if the device has
-   sub-nodes representing partitions (see below).  In this case
-   both #address-cells and #size-cells must be equal to 1.
-
-For JEDEC compatible devices, the following additional properties
-are defined:
-
- - vendor-id : Contains the flash chip's vendor id (1 byte).
- - device-id : Contains the flash chip's device id (1 byte).
-
-In addition to the information on the mtd bank itself, the
-device tree may optionally contain additional information
-describing partitions of the address space.  This can be
-used on platforms which have strong conventions about which
-portions of a flash are used for what purposes, but which don't
-use an on-flash partition table such as RedBoot.
-
-Each partition is represented as a sub-node of the mtd device.
-Each node's name represents the name of the corresponding
-partition of the mtd device.
-
-Flash partitions
- - reg : The partition's offset and size within the mtd bank.
- - label : (optional) The label / name for this partition.
-   If omitted, the label is taken from the node name (excluding
-   the unit address).
- - read-only : (optional) This parameter, if present, is a hint to
-   Linux that this partition should only be mounted
-   read-only.  This is usually used for flash partitions
-   containing early-boot firmware images or data which should not
-   be clobbered.
-
-Example:
-
-	flash@ff000000 {
-		compatible = "amd,am29lv128ml", "cfi-flash";
-		reg = <ff000000 01000000>;
-		bank-width = <4>;
-		device-width = <1>;
-		#address-cells = <1>;
-		#size-cells = <1>;
-		fs@0 {
-			label = "fs";
-			reg = <0 f80000>;
-		};
-		firmware@f80000 {
-			label ="firmware";
-			reg = <f80000 80000>;
-			read-only;
-		};
-	};
-
-Here an example with multiple "reg" tuples:
-
-	flash@f0000000,0 {
-		#address-cells = <1>;
-		#size-cells = <1>;
-		compatible = "intel,PC48F4400P0VB", "cfi-flash";
-		reg = <0 0x00000000 0x02000000
-		       0 0x02000000 0x02000000>;
-		bank-width = <2>;
-		partition@0 {
-			label = "test-part1";
-			reg = <0 0x04000000>;
-		};
-	};
-
-An example using SRAM:
-
-	sram@2,0 {
-		compatible = "samsung,k6f1616u6a", "mtd-ram";
-		reg = <2 0 0x00200000>;
-		bank-width = <2>;
-	};
-
diff -druNp linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/nintendo/gamecube.txt linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/nintendo/gamecube.txt
--- linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/nintendo/gamecube.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/nintendo/gamecube.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,109 +0,0 @@
-
-Nintendo GameCube device tree
-=============================
-
-1) The "flipper" node
-
-  This node represents the multi-function "Flipper" chip, which packages
-  many of the devices found in the Nintendo GameCube.
-
-  Required properties:
-
-   - compatible : Should be "nintendo,flipper"
-
-1.a) The Video Interface (VI) node
-
-  Represents the interface between the graphics processor and a external
-  video encoder.
-
-  Required properties:
-
-   - compatible : should be "nintendo,flipper-vi"
-   - reg : should contain the VI registers location and length
-   - interrupts : should contain the VI interrupt
-
-1.b) The Processor Interface (PI) node
-
-  Represents the data and control interface between the main processor
-  and graphics and audio processor.
-
-  Required properties:
-
-  - compatible : should be "nintendo,flipper-pi"
-  - reg : should contain the PI registers location and length
-
-1.b.i) The "Flipper" interrupt controller node
-
-  Represents the interrupt controller within the "Flipper" chip.
-  The node for the "Flipper" interrupt controller must be placed under
-  the PI node.
-
-  Required properties:
-
-  - compatible : should be "nintendo,flipper-pic"
-
-1.c) The Digital Signal Procesor (DSP) node
-
-  Represents the digital signal processor interface, designed to offload
-  audio related tasks.
-
-  Required properties:
-
-   - compatible : should be "nintendo,flipper-dsp"
-   - reg : should contain the DSP registers location and length
-   - interrupts : should contain the DSP interrupt
-
-1.c.i) The Auxiliary RAM (ARAM) node
-
-  Represents the non cpu-addressable ram designed mainly to store audio
-  related information.
-  The ARAM node must be placed under the DSP node.
-
-  Required properties:
-
-   - compatible : should be "nintendo,flipper-aram"
-   - reg : should contain the ARAM start (zero-based) and length
-
-1.d) The Disk Interface (DI) node
-
-  Represents the interface used to communicate with mass storage devices.
-
-  Required properties:
-
-   - compatible : should be "nintendo,flipper-di"
-   - reg : should contain the DI registers location and length
-   - interrupts : should contain the DI interrupt
-
-1.e) The Audio Interface (AI) node
-
-  Represents the interface to the external 16-bit stereo digital-to-analog
-  converter.
-
-  Required properties:
-
-   - compatible : should be "nintendo,flipper-ai"
-   - reg : should contain the AI registers location and length
-   - interrupts : should contain the AI interrupt
-
-1.f) The Serial Interface (SI) node
-
-  Represents the interface to the four single bit serial interfaces.
-  The SI is a proprietary serial interface used normally to control gamepads.
-  It's NOT a RS232-type interface.
-
-  Required properties:
-
-   - compatible : should be "nintendo,flipper-si"
-   - reg : should contain the SI registers location and length
-   - interrupts : should contain the SI interrupt
-
-1.g) The External Interface (EXI) node
-
-  Represents the multi-channel SPI-like interface.
-
-  Required properties:
-
-   - compatible : should be "nintendo,flipper-exi"
-   - reg : should contain the EXI registers location and length
-   - interrupts : should contain the EXI interrupt
-
diff -druNp linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/nintendo/wii.txt linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/nintendo/wii.txt
--- linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/nintendo/wii.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/nintendo/wii.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,184 +0,0 @@
-
-Nintendo Wii device tree
-========================
-
-0) The root node
-
-  This node represents the Nintendo Wii video game console.
-
-  Required properties:
-
-   - model : Should be "nintendo,wii"
-   - compatible : Should be "nintendo,wii"
-
-1) The "hollywood" node
-
-  This node represents the multi-function "Hollywood" chip, which packages
-  many of the devices found in the Nintendo Wii.
-
-  Required properties:
-
-   - compatible : Should be "nintendo,hollywood"
-
-1.a) The Video Interface (VI) node
-
-  Represents the interface between the graphics processor and a external
-  video encoder.
-
-  Required properties:
-
-   - compatible : should be "nintendo,hollywood-vi","nintendo,flipper-vi"
-   - reg : should contain the VI registers location and length
-   - interrupts : should contain the VI interrupt
-
-1.b) The Processor Interface (PI) node
-
-  Represents the data and control interface between the main processor
-  and graphics and audio processor.
-
-  Required properties:
-
-  - compatible : should be "nintendo,hollywood-pi","nintendo,flipper-pi"
-  - reg : should contain the PI registers location and length
-
-1.b.i) The "Flipper" interrupt controller node
-
-  Represents the "Flipper" interrupt controller within the "Hollywood" chip.
-  The node for the "Flipper" interrupt controller must be placed under
-  the PI node.
-
-  Required properties:
-
-  - #interrupt-cells : <1>
-  - compatible : should be "nintendo,flipper-pic"
-  - interrupt-controller
-
-1.c) The Digital Signal Procesor (DSP) node
-
-  Represents the digital signal processor interface, designed to offload
-  audio related tasks.
-
-  Required properties:
-
-   - compatible : should be "nintendo,hollywood-dsp","nintendo,flipper-dsp"
-   - reg : should contain the DSP registers location and length
-   - interrupts : should contain the DSP interrupt
-
-1.d) The Serial Interface (SI) node
-
-  Represents the interface to the four single bit serial interfaces.
-  The SI is a proprietary serial interface used normally to control gamepads.
-  It's NOT a RS232-type interface.
-
-  Required properties:
-
-   - compatible : should be "nintendo,hollywood-si","nintendo,flipper-si"
-   - reg : should contain the SI registers location and length
-   - interrupts : should contain the SI interrupt
-
-1.e) The Audio Interface (AI) node
-
-  Represents the interface to the external 16-bit stereo digital-to-analog
-  converter.
-
-  Required properties:
-
-   - compatible : should be "nintendo,hollywood-ai","nintendo,flipper-ai"
-   - reg : should contain the AI registers location and length
-   - interrupts : should contain the AI interrupt
-
-1.f) The External Interface (EXI) node
-
-  Represents the multi-channel SPI-like interface.
-
-  Required properties:
-
-   - compatible : should be "nintendo,hollywood-exi","nintendo,flipper-exi"
-   - reg : should contain the EXI registers location and length
-   - interrupts : should contain the EXI interrupt
-
-1.g) The Open Host Controller Interface (OHCI) nodes
-
-  Represent the USB 1.x Open Host Controller Interfaces.
-
-  Required properties:
-
-   - compatible : should be "nintendo,hollywood-usb-ohci","usb-ohci"
-   - reg : should contain the OHCI registers location and length
-   - interrupts : should contain the OHCI interrupt
-
-1.h) The Enhanced Host Controller Interface (EHCI) node
-
-  Represents the USB 2.0 Enhanced Host Controller Interface.
-
-  Required properties:
-
-   - compatible : should be "nintendo,hollywood-usb-ehci","usb-ehci"
-   - reg : should contain the EHCI registers location and length
-   - interrupts : should contain the EHCI interrupt
-
-1.i) The Secure Digital Host Controller Interface (SDHCI) nodes
-
-  Represent the Secure Digital Host Controller Interfaces.
-
-  Required properties:
-
-   - compatible : should be "nintendo,hollywood-sdhci","sdhci"
-   - reg : should contain the SDHCI registers location and length
-   - interrupts : should contain the SDHCI interrupt
-
-1.j) The Inter-Processsor Communication (IPC) node
-
-  Represent the Inter-Processor Communication interface. This interface
-  enables communications between the Broadway and the Starlet processors.
-
-   - compatible : should be "nintendo,hollywood-ipc"
-   - reg : should contain the IPC registers location and length
-   - interrupts : should contain the IPC interrupt
-
-1.k) The "Hollywood" interrupt controller node
-
-  Represents the "Hollywood" interrupt controller within the
-  "Hollywood" chip.
-
-  Required properties:
-
-  - #interrupt-cells : <1>
-  - compatible : should be "nintendo,hollywood-pic"
-  - reg : should contain the controller registers location and length
-  - interrupt-controller
-  - interrupts : should contain the cascade interrupt of the "flipper" pic
-  - interrupt-parent: should contain the phandle of the "flipper" pic
-
-1.l) The General Purpose I/O (GPIO) controller node
-
-  Represents the dual access 32 GPIO controller interface.
-
-  Required properties:
-
-  - #gpio-cells : <2>
-  - compatible : should be "nintendo,hollywood-gpio"
-  - reg : should contain the IPC registers location and length
-  - gpio-controller
-
-1.m) The control node
-
-  Represents the control interface used to setup several miscellaneous
-  settings of the "Hollywood" chip like boot memory mappings, resets,
-  disk interface mode, etc.
-
-  Required properties:
-
-   - compatible : should be "nintendo,hollywood-control"
-   - reg : should contain the control registers location and length
-
-1.n) The Disk Interface (DI) node
-
-  Represents the interface used to communicate with mass storage devices.
-
-  Required properties:
-
-   - compatible : should be "nintendo,hollywood-di"
-   - reg : should contain the DI registers location and length
-   - interrupts : should contain the DI interrupt
-
diff -druNp linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/phy.txt linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/phy.txt
--- linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/phy.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/phy.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,25 +0,0 @@
-PHY nodes
-
-Required properties:
-
- - device_type : Should be "ethernet-phy"
- - interrupts : <a b> where a is the interrupt number and b is a
-   field that represents an encoding of the sense and level
-   information for the interrupt.  This should be encoded based on
-   the information in section 2) depending on the type of interrupt
-   controller you have.
- - interrupt-parent : the phandle for the interrupt controller that
-   services interrupts for this device.
- - reg : The ID number for the phy, usually a small integer
- - linux,phandle :  phandle for this node; likely referenced by an
-   ethernet controller node.
-
-Example:
-
-ethernet-phy@0 {
-	linux,phandle = <2452000>
-	interrupt-parent = <40000>;
-	interrupts = <35 1>;
-	reg = <0>;
-	device_type = "ethernet-phy";
-};
diff -druNp linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/spi-bus.txt linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/spi-bus.txt
--- linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/spi-bus.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/spi-bus.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,57 +0,0 @@
-SPI (Serial Peripheral Interface) busses
-
-SPI busses can be described with a node for the SPI master device
-and a set of child nodes for each SPI slave on the bus.  For this
-discussion, it is assumed that the system's SPI controller is in
-SPI master mode.  This binding does not describe SPI controllers
-in slave mode.
-
-The SPI master node requires the following properties:
-- #address-cells  - number of cells required to define a chip select
-    		address on the SPI bus.
-- #size-cells     - should be zero.
-- compatible      - name of SPI bus controller following generic names
-    		recommended practice.
-No other properties are required in the SPI bus node.  It is assumed
-that a driver for an SPI bus device will understand that it is an SPI bus.
-However, the binding does not attempt to define the specific method for
-assigning chip select numbers.  Since SPI chip select configuration is
-flexible and non-standardized, it is left out of this binding with the
-assumption that board specific platform code will be used to manage
-chip selects.  Individual drivers can define additional properties to
-support describing the chip select layout.
-
-SPI slave nodes must be children of the SPI master node and can
-contain the following properties.
-- reg             - (required) chip select address of device.
-- compatible      - (required) name of SPI device following generic names
-    		recommended practice
-- spi-max-frequency - (required) Maximum SPI clocking speed of device in Hz
-- spi-cpol        - (optional) Empty property indicating device requires
-    		inverse clock polarity (CPOL) mode
-- spi-cpha        - (optional) Empty property indicating device requires
-    		shifted clock phase (CPHA) mode
-- spi-cs-high     - (optional) Empty property indicating device requires
-    		chip select active high
-
-SPI example for an MPC5200 SPI bus:
-	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>;
-		interrupt-parent = <&mpc5200_pic>;
-
-		ethernet-switch@0 {
-			compatible = "micrel,ks8995m";
-			spi-max-frequency = <1000000>;
-			reg = <0>;
-		};
-
-		codec@1 {
-			compatible = "ti,tlv320aic26";
-			spi-max-frequency = <100000>;
-			reg = <1>;
-		};
-	};
diff -druNp linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/usb-ehci.txt linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/usb-ehci.txt
--- linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/usb-ehci.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/usb-ehci.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,25 +0,0 @@
-USB EHCI controllers
-
-Required properties:
-  - compatible : should be "usb-ehci".
-  - reg : should contain at least address and length of the standard EHCI
-    register set for the device. Optional platform-dependent registers
-    (debug-port or other) can be also specified here, but only after
-    definition of standard EHCI registers.
-  - interrupts : one EHCI interrupt should be described here.
-If device registers are implemented in big endian mode, the device
-node should have "big-endian-regs" property.
-If controller implementation operates with big endian descriptors,
-"big-endian-desc" property should be specified.
-If both big endian registers and descriptors are used by the controller
-implementation, "big-endian" property can be specified instead of having
-both "big-endian-regs" and "big-endian-desc".
-
-Example (Sequoia 440EPx):
-    ehci@e0000300 {
-	   compatible = "ibm,usb-ehci-440epx", "usb-ehci";
-	   interrupt-parent = <&UIC0>;
-	   interrupts = <1a 4>;
-	   reg = <0 e0000300 90 0 e0000390 70>;
-	   big-endian;
-   };
diff -druNp linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/xilinx.txt linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/xilinx.txt
--- linux-libre-2.6.37-gnu1/Documentation/powerpc/dts-bindings/xilinx.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/powerpc/dts-bindings/xilinx.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,306 +0,0 @@
-   d) Xilinx IP cores
-
-   The Xilinx EDK toolchain ships with a set of IP cores (devices) for use
-   in Xilinx Spartan and Virtex FPGAs.  The devices cover the whole range
-   of standard device types (network, serial, etc.) and miscellaneous
-   devices (gpio, LCD, spi, etc).  Also, since these devices are
-   implemented within the fpga fabric every instance of the device can be
-   synthesised with different options that change the behaviour.
-
-   Each IP-core has a set of parameters which the FPGA designer can use to
-   control how the core is synthesized.  Historically, the EDK tool would
-   extract the device parameters relevant to device drivers and copy them
-   into an 'xparameters.h' in the form of #define symbols.  This tells the
-   device drivers how the IP cores are configured, but it requires the kernel
-   to be recompiled every time the FPGA bitstream is resynthesized.
-
-   The new approach is to export the parameters into the device tree and
-   generate a new device tree each time the FPGA bitstream changes.  The
-   parameters which used to be exported as #defines will now become
-   properties of the device node.  In general, device nodes for IP-cores
-   will take the following form:
-
-	(name): (generic-name)@(base-address) {
-		compatible = "xlnx,(ip-core-name)-(HW_VER)"
-			     [, (list of compatible devices), ...];
-		reg = <(baseaddr) (size)>;
-		interrupt-parent = <&interrupt-controller-phandle>;
-		interrupts = < ... >;
-		xlnx,(parameter1) = "(string-value)";
-		xlnx,(parameter2) = <(int-value)>;
-	};
-
-	(generic-name):   an open firmware-style name that describes the
-			generic class of device.  Preferably, this is one word, such
-			as 'serial' or 'ethernet'.
-	(ip-core-name):	the name of the ip block (given after the BEGIN
-			directive in system.mhs).  Should be in lowercase
-			and all underscores '_' converted to dashes '-'.
-	(name):		is derived from the "PARAMETER INSTANCE" value.
-	(parameter#):	C_* parameters from system.mhs.  The C_ prefix is
-			dropped from the parameter name, the name is converted
-			to lowercase and all underscore '_' characters are
-			converted to dashes '-'.
-	(baseaddr):	the baseaddr parameter value (often named C_BASEADDR).
-	(HW_VER):	from the HW_VER parameter.
-	(size):		the address range size (often C_HIGHADDR - C_BASEADDR + 1).
-
-   Typically, the compatible list will include the exact IP core version
-   followed by an older IP core version which implements the same
-   interface or any other device with the same interface.
-
-   'reg', 'interrupt-parent' and 'interrupts' are all optional properties.
-
-   For example, the following block from system.mhs:
-
-	BEGIN opb_uartlite
-		PARAMETER INSTANCE = opb_uartlite_0
-		PARAMETER HW_VER = 1.00.b
-		PARAMETER C_BAUDRATE = 115200
-		PARAMETER C_DATA_BITS = 8
-		PARAMETER C_ODD_PARITY = 0
-		PARAMETER C_USE_PARITY = 0
-		PARAMETER C_CLK_FREQ = 50000000
-		PARAMETER C_BASEADDR = 0xEC100000
-		PARAMETER C_HIGHADDR = 0xEC10FFFF
-		BUS_INTERFACE SOPB = opb_7
-		PORT OPB_Clk = CLK_50MHz
-		PORT Interrupt = opb_uartlite_0_Interrupt
-		PORT RX = opb_uartlite_0_RX
-		PORT TX = opb_uartlite_0_TX
-		PORT OPB_Rst = sys_bus_reset_0
-	END
-
-   becomes the following device tree node:
-
-	opb_uartlite_0: serial@ec100000 {
-		device_type = "serial";
-		compatible = "xlnx,opb-uartlite-1.00.b";
-		reg = <ec100000 10000>;
-		interrupt-parent = <&opb_intc_0>;
-		interrupts = <1 0>; // got this from the opb_intc parameters
-		current-speed = <d#115200>;	// standard serial device prop
-		clock-frequency = <d#50000000>;	// standard serial device prop
-		xlnx,data-bits = <8>;
-		xlnx,odd-parity = <0>;
-		xlnx,use-parity = <0>;
-	};
-
-   Some IP cores actually implement 2 or more logical devices.  In
-   this case, the device should still describe the whole IP core with
-   a single node and add a child node for each logical device.  The
-   ranges property can be used to translate from parent IP-core to the
-   registers of each device.  In addition, the parent node should be
-   compatible with the bus type 'xlnx,compound', and should contain
-   #address-cells and #size-cells, as with any other bus.  (Note: this
-   makes the assumption that both logical devices have the same bus
-   binding.  If this is not true, then separate nodes should be used
-   for each logical device).  The 'cell-index' property can be used to
-   enumerate logical devices within an IP core.  For example, the
-   following is the system.mhs entry for the dual ps2 controller found
-   on the ml403 reference design.
-
-	BEGIN opb_ps2_dual_ref
-		PARAMETER INSTANCE = opb_ps2_dual_ref_0
-		PARAMETER HW_VER = 1.00.a
-		PARAMETER C_BASEADDR = 0xA9000000
-		PARAMETER C_HIGHADDR = 0xA9001FFF
-		BUS_INTERFACE SOPB = opb_v20_0
-		PORT Sys_Intr1 = ps2_1_intr
-		PORT Sys_Intr2 = ps2_2_intr
-		PORT Clkin1 = ps2_clk_rx_1
-		PORT Clkin2 = ps2_clk_rx_2
-		PORT Clkpd1 = ps2_clk_tx_1
-		PORT Clkpd2 = ps2_clk_tx_2
-		PORT Rx1 = ps2_d_rx_1
-		PORT Rx2 = ps2_d_rx_2
-		PORT Txpd1 = ps2_d_tx_1
-		PORT Txpd2 = ps2_d_tx_2
-	END
-
-   It would result in the following device tree nodes:
-
-	opb_ps2_dual_ref_0: opb-ps2-dual-ref@a9000000 {
-		#address-cells = <1>;
-		#size-cells = <1>;
-		compatible = "xlnx,compound";
-		ranges = <0 a9000000 2000>;
-		// If this device had extra parameters, then they would
-		// go here.
-		ps2@0 {
-			compatible = "xlnx,opb-ps2-dual-ref-1.00.a";
-			reg = <0 40>;
-			interrupt-parent = <&opb_intc_0>;
-			interrupts = <3 0>;
-			cell-index = <0>;
-		};
-		ps2@1000 {
-			compatible = "xlnx,opb-ps2-dual-ref-1.00.a";
-			reg = <1000 40>;
-			interrupt-parent = <&opb_intc_0>;
-			interrupts = <3 0>;
-			cell-index = <0>;
-		};
-	};
-
-   Also, the system.mhs file defines bus attachments from the processor
-   to the devices.  The device tree structure should reflect the bus
-   attachments.  Again an example; this system.mhs fragment:
-
-	BEGIN ppc405_virtex4
-		PARAMETER INSTANCE = ppc405_0
-		PARAMETER HW_VER = 1.01.a
-		BUS_INTERFACE DPLB = plb_v34_0
-		BUS_INTERFACE IPLB = plb_v34_0
-	END
-
-	BEGIN opb_intc
-		PARAMETER INSTANCE = opb_intc_0
-		PARAMETER HW_VER = 1.00.c
-		PARAMETER C_BASEADDR = 0xD1000FC0
-		PARAMETER C_HIGHADDR = 0xD1000FDF
-		BUS_INTERFACE SOPB = opb_v20_0
-	END
-
-	BEGIN opb_uart16550
-		PARAMETER INSTANCE = opb_uart16550_0
-		PARAMETER HW_VER = 1.00.d
-		PARAMETER C_BASEADDR = 0xa0000000
-		PARAMETER C_HIGHADDR = 0xa0001FFF
-		BUS_INTERFACE SOPB = opb_v20_0
-	END
-
-	BEGIN plb_v34
-		PARAMETER INSTANCE = plb_v34_0
-		PARAMETER HW_VER = 1.02.a
-	END
-
-	BEGIN plb_bram_if_cntlr
-		PARAMETER INSTANCE = plb_bram_if_cntlr_0
-		PARAMETER HW_VER = 1.00.b
-		PARAMETER C_BASEADDR = 0xFFFF0000
-		PARAMETER C_HIGHADDR = 0xFFFFFFFF
-		BUS_INTERFACE SPLB = plb_v34_0
-	END
-
-	BEGIN plb2opb_bridge
-		PARAMETER INSTANCE = plb2opb_bridge_0
-		PARAMETER HW_VER = 1.01.a
-		PARAMETER C_RNG0_BASEADDR = 0x20000000
-		PARAMETER C_RNG0_HIGHADDR = 0x3FFFFFFF
-		PARAMETER C_RNG1_BASEADDR = 0x60000000
-		PARAMETER C_RNG1_HIGHADDR = 0x7FFFFFFF
-		PARAMETER C_RNG2_BASEADDR = 0x80000000
-		PARAMETER C_RNG2_HIGHADDR = 0xBFFFFFFF
-		PARAMETER C_RNG3_BASEADDR = 0xC0000000
-		PARAMETER C_RNG3_HIGHADDR = 0xDFFFFFFF
-		BUS_INTERFACE SPLB = plb_v34_0
-		BUS_INTERFACE MOPB = opb_v20_0
-	END
-
-   Gives this device tree (some properties removed for clarity):
-
-	plb@0 {
-		#address-cells = <1>;
-		#size-cells = <1>;
-		compatible = "xlnx,plb-v34-1.02.a";
-		device_type = "ibm,plb";
-		ranges; // 1:1 translation
-
-		plb_bram_if_cntrl_0: bram@ffff0000 {
-			reg = <ffff0000 10000>;
-		}
-
-		opb@20000000 {
-			#address-cells = <1>;
-			#size-cells = <1>;
-			ranges = <20000000 20000000 20000000
-				  60000000 60000000 20000000
-				  80000000 80000000 40000000
-				  c0000000 c0000000 20000000>;
-
-			opb_uart16550_0: serial@a0000000 {
-				reg = <a00000000 2000>;
-			};
-
-			opb_intc_0: interrupt-controller@d1000fc0 {
-				reg = <d1000fc0 20>;
-			};
-		};
-	};
-
-   That covers the general approach to binding xilinx IP cores into the
-   device tree.  The following are bindings for specific devices:
-
-      i) Xilinx ML300 Framebuffer
-
-      Simple framebuffer device from the ML300 reference design (also on the
-      ML403 reference design as well as others).
-
-      Optional properties:
-       - resolution = <xres yres> : pixel resolution of framebuffer.  Some
-                                    implementations use a different resolution.
-                                    Default is <d#640 d#480>
-       - virt-resolution = <xvirt yvirt> : Size of framebuffer in memory.
-                                           Default is <d#1024 d#480>.
-       - rotate-display (empty) : rotate display 180 degrees.
-
-      ii) Xilinx SystemACE
-
-      The Xilinx SystemACE device is used to program FPGAs from an FPGA
-      bitstream stored on a CF card.  It can also be used as a generic CF
-      interface device.
-
-      Optional properties:
-       - 8-bit (empty) : Set this property for SystemACE in 8 bit mode
-
-      iii) Xilinx EMAC and Xilinx TEMAC
-
-      Xilinx Ethernet devices.  In addition to general xilinx properties
-      listed above, nodes for these devices should include a phy-handle
-      property, and may include other common network device properties
-      like local-mac-address.
-
-      iv) Xilinx Uartlite
-
-      Xilinx uartlite devices are simple fixed speed serial ports.
-
-      Required properties:
-       - current-speed : Baud rate of uartlite
-
-      v) Xilinx hwicap
-
-		Xilinx hwicap devices provide access to the configuration logic
-		of the FPGA through the Internal Configuration Access Port
-		(ICAP).  The ICAP enables partial reconfiguration of the FPGA,
-		readback of the configuration information, and some control over
-		'warm boots' of the FPGA fabric.
-
-		Required properties:
-		- xlnx,family : The family of the FPGA, necessary since the
-                      capabilities of the underlying ICAP hardware
-                      differ between different families.  May be
-                      'virtex2p', 'virtex4', or 'virtex5'.
-
-      vi) Xilinx Uart 16550
-
-      Xilinx UART 16550 devices are very similar to the NS16550 but with
-      different register spacing and an offset from the base address.
-
-      Required properties:
-       - clock-frequency : Frequency of the clock input
-       - reg-offset : A value of 3 is required
-       - reg-shift : A value of 2 is required
-
-      vii) Xilinx USB Host controller
-
-      The Xilinx USB host controller is EHCI compatible but with a different
-      base address for the EHCI registers, and it is always a big-endian
-      USB Host controller. The hardware can be configured as high speed only,
-      or high speed/full speed hybrid.
-
-      Required properties:
-      - xlnx,support-usb-fs: A value 0 means the core is built as high speed
-                             only. A value 1 means the core also supports
-                             full speed devices.
-
diff -druNp linux-libre-2.6.37-gnu1/Documentation/pps/pps.txt linux-libre-2.6.38-gnu1/Documentation/pps/pps.txt
--- linux-libre-2.6.37-gnu1/Documentation/pps/pps.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/pps/pps.txt	2011-03-14 21:20:32.000000000 -0400
@@ -170,3 +170,49 @@ and the run ppstest as follow:
 
 Please, note that to compile userland programs you need the file timepps.h
 (see Documentation/pps/).
+
+
+Generators
+----------
+
+Sometimes one needs to be able not only to catch PPS signals but to produce
+them also. For example, running a distributed simulation, which requires
+computers' clock to be synchronized very tightly. One way to do this is to
+invent some complicated hardware solutions but it may be neither necessary
+nor affordable. The cheap way is to load a PPS generator on one of the
+computers (master) and PPS clients on others (slaves), and use very simple
+cables to deliver signals using parallel ports, for example.
+
+Parallel port cable pinout:
+pin	name	master      slave
+1	STROBE	  *------     *
+2	D0	  *     |     *
+3	D1	  *     |     *
+4	D2	  *     |     *
+5	D3	  *     |     *
+6	D4	  *     |     *
+7	D5	  *     |     *
+8	D6	  *     |     *
+9	D7	  *     |     *
+10	ACK	  *     ------*
+11	BUSY	  *           *
+12	PE	  *           *
+13	SEL	  *           *
+14	AUTOFD	  *           *
+15	ERROR	  *           *
+16	INIT	  *           *
+17	SELIN	  *           *
+18-25	GND	  *-----------*
+
+Please note that parallel port interrupt occurs only on high->low transition,
+so it is used for PPS assert edge. PPS clear edge can be determined only
+using polling in the interrupt handler which actually can be done way more
+precisely because interrupt handling delays can be quite big and random. So
+current parport PPS generator implementation (pps_gen_parport module) is
+geared towards using the clear edge for time synchronization.
+
+Clear edge polling is done with disabled interrupts so it's better to select
+delay between assert and clear edge as small as possible to reduce system
+latencies. But if it is too small slave won't be able to capture clear edge
+transition. The default of 30us should be good enough in most situations.
+The delay can be selected using 'delay' pps_gen_parport module parameter.
diff -druNp linux-libre-2.6.37-gnu1/Documentation/RCU/trace.txt linux-libre-2.6.38-gnu1/Documentation/RCU/trace.txt
--- linux-libre-2.6.37-gnu1/Documentation/RCU/trace.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/RCU/trace.txt	2011-03-14 21:20:32.000000000 -0400
@@ -1,18 +1,22 @@
 CONFIG_RCU_TRACE debugfs Files and Formats
 
 
-The rcutree implementation of RCU provides debugfs trace output that
-summarizes counters and state.  This information is useful for debugging
-RCU itself, and can sometimes also help to debug abuses of RCU.
-The following sections describe the debugfs files and formats.
+The rcutree and rcutiny implementations of RCU provide debugfs trace
+output that summarizes counters and state.  This information is useful for
+debugging RCU itself, and can sometimes also help to debug abuses of RCU.
+The following sections describe the debugfs files and formats, first
+for rcutree and next for rcutiny.
 
 
-Hierarchical RCU debugfs Files and Formats
+CONFIG_TREE_RCU and CONFIG_TREE_PREEMPT_RCU debugfs Files and Formats
 
-This implementation of RCU provides three debugfs files under the
+These implementations of RCU provides five debugfs files under the
 top-level directory RCU: rcu/rcudata (which displays fields in struct
-rcu_data), rcu/rcugp (which displays grace-period counters), and
-rcu/rcuhier (which displays the struct rcu_node hierarchy).
+rcu_data), rcu/rcudata.csv (which is a .csv spreadsheet version of
+rcu/rcudata), rcu/rcugp (which displays grace-period counters),
+rcu/rcuhier (which displays the struct rcu_node hierarchy), and
+rcu/rcu_pending (which displays counts of the reasons that the
+rcu_pending() function decided that there was core RCU work to do).
 
 The output of "cat rcu/rcudata" looks as follows:
 
@@ -130,7 +134,8 @@ o	"ci" is the number of RCU callbacks th
 	been registered in absence of CPU-hotplug activity.
 
 o	"co" is the number of RCU callbacks that have been orphaned due to
-	this CPU going offline.
+	this CPU going offline.  These orphaned callbacks have been moved
+	to an arbitrarily chosen online CPU.
 
 o	"ca" is the number of RCU callbacks that have been adopted due to
 	other CPUs going offline.  Note that ci+co-ca+ql is the number of
@@ -168,12 +173,12 @@ o	"gpnum" is the number of grace periods
 
 The output of "cat rcu/rcuhier" looks as follows, with very long lines:
 
-c=6902 g=6903 s=2 jfq=3 j=72c7 nfqs=13142/nfqsng=0(13142) fqlh=6 oqlen=0
+c=6902 g=6903 s=2 jfq=3 j=72c7 nfqs=13142/nfqsng=0(13142) fqlh=6
 1/1 .>. 0:127 ^0    
 3/3 .>. 0:35 ^0    0/0 .>. 36:71 ^1    0/0 .>. 72:107 ^2    0/0 .>. 108:127 ^3    
 3/3f .>. 0:5 ^0    2/3 .>. 6:11 ^1    0/0 .>. 12:17 ^2    0/0 .>. 18:23 ^3    0/0 .>. 24:29 ^4    0/0 .>. 30:35 ^5    0/0 .>. 36:41 ^0    0/0 .>. 42:47 ^1    0/0 .>. 48:53 ^2    0/0 .>. 54:59 ^3    0/0 .>. 60:65 ^4    0/0 .>. 66:71 ^5    0/0 .>. 72:77 ^0    0/0 .>. 78:83 ^1    0/0 .>. 84:89 ^2    0/0 .>. 90:95 ^3    0/0 .>. 96:101 ^4    0/0 .>. 102:107 ^5    0/0 .>. 108:113 ^0    0/0 .>. 114:119 ^1    0/0 .>. 120:125 ^2    0/0 .>. 126:127 ^3    
 rcu_bh:
-c=-226 g=-226 s=1 jfq=-5701 j=72c7 nfqs=88/nfqsng=0(88) fqlh=0 oqlen=0
+c=-226 g=-226 s=1 jfq=-5701 j=72c7 nfqs=88/nfqsng=0(88) fqlh=0
 0/1 .>. 0:127 ^0    
 0/3 .>. 0:35 ^0    0/0 .>. 36:71 ^1    0/0 .>. 72:107 ^2    0/0 .>. 108:127 ^3    
 0/3f .>. 0:5 ^0    0/3 .>. 6:11 ^1    0/0 .>. 12:17 ^2    0/0 .>. 18:23 ^3    0/0 .>. 24:29 ^4    0/0 .>. 30:35 ^5    0/0 .>. 36:41 ^0    0/0 .>. 42:47 ^1    0/0 .>. 48:53 ^2    0/0 .>. 54:59 ^3    0/0 .>. 60:65 ^4    0/0 .>. 66:71 ^5    0/0 .>. 72:77 ^0    0/0 .>. 78:83 ^1    0/0 .>. 84:89 ^2    0/0 .>. 90:95 ^3    0/0 .>. 96:101 ^4    0/0 .>. 102:107 ^5    0/0 .>. 108:113 ^0    0/0 .>. 114:119 ^1    0/0 .>. 120:125 ^2    0/0 .>. 126:127 ^3
@@ -212,11 +217,6 @@ o	"fqlh" is the number of calls to force
 	exited immediately (without even being counted in nfqs above)
 	due to contention on ->fqslock.
 
-o	"oqlen" is the number of callbacks on the "orphan" callback
-	list.  RCU callbacks are placed on this list by CPUs going
-	offline, and are "adopted" either by the CPU helping the outgoing
-	CPU or by the next rcu_barrier*() call, whichever comes first.
-
 o	Each element of the form "1/1 0:127 ^0" represents one struct
 	rcu_node.  Each line represents one level of the hierarchy, from
 	root to leaves.  It is best to think of the rcu_data structures
@@ -326,3 +326,115 @@ o	"nn" is the number of times that this
 	readers will note that the rcu "nn" number for a given CPU very
 	closely matches the rcu_bh "np" number for that same CPU.  This
 	is due to short-circuit evaluation in rcu_pending().
+
+
+CONFIG_TINY_RCU and CONFIG_TINY_PREEMPT_RCU debugfs Files and Formats
+
+These implementations of RCU provides a single debugfs file under the
+top-level directory RCU, namely rcu/rcudata, which displays fields in
+rcu_bh_ctrlblk, rcu_sched_ctrlblk and, for CONFIG_TINY_PREEMPT_RCU,
+rcu_preempt_ctrlblk.
+
+The output of "cat rcu/rcudata" is as follows:
+
+rcu_preempt: qlen=24 gp=1097669 g197/p197/c197 tasks=...
+             ttb=. btg=no ntb=184 neb=0 nnb=183 j=01f7 bt=0274
+             normal balk: nt=1097669 gt=0 bt=371 b=0 ny=25073378 nos=0
+             exp balk: bt=0 nos=0
+rcu_sched: qlen: 0
+rcu_bh: qlen: 0
+
+This is split into rcu_preempt, rcu_sched, and rcu_bh sections, with the
+rcu_preempt section appearing only in CONFIG_TINY_PREEMPT_RCU builds.
+The last three lines of the rcu_preempt section appear only in
+CONFIG_RCU_BOOST kernel builds.  The fields are as follows:
+
+o	"qlen" is the number of RCU callbacks currently waiting either
+	for an RCU grace period or waiting to be invoked.  This is the
+	only field present for rcu_sched and rcu_bh, due to the
+	short-circuiting of grace period in those two cases.
+
+o	"gp" is the number of grace periods that have completed.
+
+o	"g197/p197/c197" displays the grace-period state, with the
+	"g" number being the number of grace periods that have started
+	(mod 256), the "p" number being the number of grace periods
+	that the CPU has responded to (also mod 256), and the "c"
+	number being the number of grace periods that have completed
+	(once again mode 256).
+
+	Why have both "gp" and "g"?  Because the data flowing into
+	"gp" is only present in a CONFIG_RCU_TRACE kernel.
+
+o	"tasks" is a set of bits.  The first bit is "T" if there are
+	currently tasks that have recently blocked within an RCU
+	read-side critical section, the second bit is "N" if any of the
+	aforementioned tasks are blocking the current RCU grace period,
+	and the third bit is "E" if any of the aforementioned tasks are
+	blocking the current expedited grace period.  Each bit is "."
+	if the corresponding condition does not hold.
+
+o	"ttb" is a single bit.  It is "B" if any of the blocked tasks
+	need to be priority boosted and "." otherwise.
+
+o	"btg" indicates whether boosting has been carried out during
+	the current grace period, with "exp" indicating that boosting
+	is in progress for an expedited grace period, "no" indicating
+	that boosting has not yet started for a normal grace period,
+	"begun" indicating that boosting has bebug for a normal grace
+	period, and "done" indicating that boosting has completed for
+	a normal grace period.
+
+o	"ntb" is the total number of tasks subjected to RCU priority boosting
+	periods since boot.
+
+o	"neb" is the number of expedited grace periods that have had
+	to resort to RCU priority boosting since boot.
+
+o	"nnb" is the number of normal grace periods that have had
+	to resort to RCU priority boosting since boot.
+
+o	"j" is the low-order 12 bits of the jiffies counter in hexadecimal.
+
+o	"bt" is the low-order 12 bits of the value that the jiffies counter
+	will have at the next time that boosting is scheduled to begin.
+
+o	In the line beginning with "normal balk", the fields are as follows:
+
+	o	"nt" is the number of times that the system balked from
+		boosting because there were no blocked tasks to boost.
+		Note that the system will balk from boosting even if the
+		grace period is overdue when the currently running task
+		is looping within an RCU read-side critical section.
+		There is no point in boosting in this case, because
+		boosting a running task won't make it run any faster.
+
+	o	"gt" is the number of times that the system balked
+		from boosting because, although there were blocked tasks,
+		none of them were preventing the current grace period
+		from completing.
+
+	o	"bt" is the number of times that the system balked
+		from boosting because boosting was already in progress.
+
+	o	"b" is the number of times that the system balked from
+		boosting because boosting had already completed for
+		the grace period in question.
+
+	o	"ny" is the number of times that the system balked from
+		boosting because it was not yet time to start boosting
+		the grace period in question.
+
+	o	"nos" is the number of times that the system balked from
+		boosting for inexplicable ("not otherwise specified")
+		reasons.  This can actually happen due to races involving
+		increments of the jiffies counter.
+
+o	In the line beginning with "exp balk", the fields are as follows:
+
+	o	"bt" is the number of times that the system balked from
+		boosting because there were no blocked tasks to boost.
+
+	o	"nos" is the number of times that the system balked from
+		 boosting for inexplicable ("not otherwise specified")
+		 reasons.
diff -druNp linux-libre-2.6.37-gnu1/Documentation/scheduler/00-INDEX linux-libre-2.6.38-gnu1/Documentation/scheduler/00-INDEX
--- linux-libre-2.6.37-gnu1/Documentation/scheduler/00-INDEX	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/scheduler/00-INDEX	2011-03-14 21:20:32.000000000 -0400
@@ -3,7 +3,7 @@
 sched-arch.txt
 	- CPU Scheduler implementation hints for architecture specific code.
 sched-design-CFS.txt
-	- goals, design and implementation of the Complete Fair Scheduler.
+	- goals, design and implementation of the Completely Fair Scheduler.
 sched-domains.txt
 	- information on scheduling domains.
 sched-nice-design.txt
diff -druNp linux-libre-2.6.37-gnu1/Documentation/scheduler/sched-stats.txt linux-libre-2.6.38-gnu1/Documentation/scheduler/sched-stats.txt
--- linux-libre-2.6.37-gnu1/Documentation/scheduler/sched-stats.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/scheduler/sched-stats.txt	2011-03-14 21:20:32.000000000 -0400
@@ -1,3 +1,7 @@
+Version 15 of schedstats dropped counters for some sched_yield:
+yld_exp_empty, yld_act_empty and yld_both_empty. Otherwise, it is
+identical to version 14.
+
 Version 14 of schedstats includes support for sched_domains, which hit the
 mainline kernel in 2.6.20 although it is identical to the stats from version
 12 which was in the kernel from 2.6.13-2.6.19 (version 13 never saw a kernel
@@ -28,32 +32,25 @@ to write their own scripts, the fields a
 
 CPU statistics
 --------------
-cpu<N> 1 2 3 4 5 6 7 8 9 10 11 12
-
-NOTE: In the sched_yield() statistics, the active queue is considered empty
-    if it has only one process in it, since obviously the process calling
-    sched_yield() is that process.
+cpu<N> 1 2 3 4 5 6 7 8 9
 
-First four fields are sched_yield() statistics:
-     1) # of times both the active and the expired queue were empty
-     2) # of times just the active queue was empty
-     3) # of times just the expired queue was empty
-     4) # of times sched_yield() was called
+First field is a sched_yield() statistic:
+     1) # of times sched_yield() was called
 
 Next three are schedule() statistics:
-     5) # of times we switched to the expired queue and reused it
-     6) # of times schedule() was called
-     7) # of times schedule() left the processor idle
+     2) # of times we switched to the expired queue and reused it
+     3) # of times schedule() was called
+     4) # of times schedule() left the processor idle
 
 Next two are try_to_wake_up() statistics:
-     8) # of times try_to_wake_up() was called
-     9) # of times try_to_wake_up() was called to wake up the local cpu
+     5) # of times try_to_wake_up() was called
+     6) # of times try_to_wake_up() was called to wake up the local cpu
 
 Next three are statistics describing scheduling latency:
-    10) sum of all time spent running by tasks on this processor (in jiffies)
-    11) sum of all time spent waiting to run by tasks on this processor (in
+     7) sum of all time spent running by tasks on this processor (in jiffies)
+     8) sum of all time spent waiting to run by tasks on this processor (in
         jiffies)
-    12) # of timeslices run on this cpu
+     9) # of timeslices run on this cpu
 
 
 Domain statistics
diff -druNp linux-libre-2.6.37-gnu1/Documentation/scsi/ChangeLog.lpfc linux-libre-2.6.38-gnu1/Documentation/scsi/ChangeLog.lpfc
--- linux-libre-2.6.37-gnu1/Documentation/scsi/ChangeLog.lpfc	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/scsi/ChangeLog.lpfc	2011-03-14 21:20:32.000000000 -0400
@@ -573,7 +573,7 @@ Changes from 20041018 to 20041123
 	* Backround nodev_timeout processing to DPC This enables us to
 	  unblock (stop dev_loss_tmo) when appopriate.
 	* Fix array discovery with multiple luns.  The max_luns was 0 at
-	  the time the host structure was intialized.  lpfc_cfg_params
+	  the time the host structure was initialized.  lpfc_cfg_params
 	  then set the max_luns to the correct value afterwards.
 	* Remove unused define LPFC_MAX_LUN and set the default value of
 	  lpfc_max_lun parameter to 512.
diff -druNp linux-libre-2.6.37-gnu1/Documentation/scsi/ChangeLog.megaraid_sas linux-libre-2.6.38-gnu1/Documentation/scsi/ChangeLog.megaraid_sas
--- linux-libre-2.6.37-gnu1/Documentation/scsi/ChangeLog.megaraid_sas	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/scsi/ChangeLog.megaraid_sas	2011-03-14 21:20:32.000000000 -0400
@@ -1,3 +1,25 @@
+Release Date    : Tues.  Dec 14, 2010 17:00:00 PST 2010 -
+			(emaild-id:megaraidlinux@lsi.com)
+			Adam Radford
+Current Version : 00.00.05.29-rc1
+Old Version     : 00.00.04.31-rc1
+    1. Rename megaraid_sas.c to megaraid_sas_base.c.
+    2. Update GPL headers.
+    3. Add MSI-X support and 'msix_disable' module parameter.
+    4. Use lowest memory bar (for SR-IOV VF support).
+    5. Add struct megasas_instance_temlate changes, and change all code to use
+       new instance entries:
+
+       irqreturn_t (*service_isr )(int irq, void *devp);
+       void (*tasklet)(unsigned long);
+       u32 (*init_adapter)(struct megasas_instance *);
+       u32 (*build_and_issue_cmd) (struct megasas_instance *,
+       struct scsi_cmnd *);
+       void (*issue_dcmd) (struct megasas_instance *instance,
+                              struct megasas_cmd *cmd);
+
+   6. Add code to support MegaRAID 9265/9285 controllers device id (0x5b).
+-------------------------------------------------------------------------------
 1 Release Date    : Thur.  May 03, 2010 09:12:45 PST 2009 -
 			(emaild-id:megaraidlinux@lsi.com)
 			Bo Yang
diff -druNp linux-libre-2.6.37-gnu1/Documentation/serial/00-INDEX linux-libre-2.6.38-gnu1/Documentation/serial/00-INDEX
--- linux-libre-2.6.37-gnu1/Documentation/serial/00-INDEX	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/serial/00-INDEX	2011-03-14 21:20:32.000000000 -0400
@@ -14,6 +14,8 @@ riscom8.txt
 	- notes on using the RISCom/8 multi-port serial driver.
 rocket.txt
 	- info on the Comtrol RocketPort multiport serial driver.
+serial-rs485.txt
+	- info about RS485 structures and support in the kernel.
 specialix.txt
 	- info on hardware/driver for specialix IO8+ multiport serial card.
 stallion.txt
diff -druNp linux-libre-2.6.37-gnu1/Documentation/serial/serial-rs485.txt linux-libre-2.6.38-gnu1/Documentation/serial/serial-rs485.txt
--- linux-libre-2.6.37-gnu1/Documentation/serial/serial-rs485.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/serial/serial-rs485.txt	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,120 @@
+                        RS485 SERIAL COMMUNICATIONS
+
+1. INTRODUCTION
+
+   EIA-485, also known as TIA/EIA-485 or RS-485, is a standard defining the
+   electrical characteristics of drivers and receivers for use in balanced
+   digital multipoint systems.
+   This standard is widely used for communications in industrial automation
+   because it can be used effectively over long distances and in electrically
+   noisy environments.
+
+2. HARDWARE-RELATED CONSIDERATIONS
+
+   Some CPUs/UARTs (e.g., Atmel AT91 or 16C950 UART) contain a built-in
+   half-duplex mode capable of automatically controlling line direction by
+   toggling RTS or DTR signals. That can be used to control external
+   half-duplex hardware like an RS485 transceiver or any RS232-connected
+   half-duplex devices like some modems.
+
+   For these microcontrollers, the Linux driver should be made capable of
+   working in both modes, and proper ioctls (see later) should be made
+   available at user-level to allow switching from one mode to the other, and
+   vice versa.
+
+3. DATA STRUCTURES ALREADY AVAILABLE IN THE KERNEL
+
+   The Linux kernel provides the serial_rs485 structure (see [1]) to handle
+   RS485 communications. This data structure is used to set and configure RS485
+   parameters in the platform data and in ioctls.
+
+   Any driver for devices capable of working both as RS232 and RS485 should
+   provide at least the following ioctls:
+
+    - TIOCSRS485 (typically associated with number 0x542F). This ioctl is used
+      to enable/disable RS485 mode from user-space
+
+    - TIOCGRS485 (typically associated with number 0x542E). This ioctl is used
+      to get RS485 mode from kernel-space (i.e., driver) to user-space.
+
+   In other words, the serial driver should contain a code similar to the next
+   one:
+
+	static struct uart_ops atmel_pops = {
+		/* ... */
+		.ioctl		= handle_ioctl,
+	};
+
+	static int handle_ioctl(struct uart_port *port,
+		unsigned int cmd,
+		unsigned long arg)
+	{
+		struct serial_rs485 rs485conf;
+
+		switch (cmd) {
+		case TIOCSRS485:
+			if (copy_from_user(&rs485conf,
+				(struct serial_rs485 *) arg,
+				sizeof(rs485conf)))
+					return -EFAULT;
+
+			/* ... */
+			break;
+
+		case TIOCGRS485:
+			if (copy_to_user((struct serial_rs485 *) arg,
+				...,
+				sizeof(rs485conf)))
+					return -EFAULT;
+			/* ... */
+			break;
+
+		/* ... */
+		}
+	}
+
+
+4. USAGE FROM USER-LEVEL
+
+   From user-level, RS485 configuration can be get/set using the previous
+   ioctls. For instance, to set RS485 you can use the following code:
+
+	#include <linux/serial.h>
+
+	/* Driver-specific ioctls: */
+	#define TIOCGRS485      0x542E
+	#define TIOCSRS485      0x542F
+
+	/* Open your specific device (e.g., /dev/mydevice): */
+	int fd = open ("/dev/mydevice", O_RDWR);
+	if (fd < 0) {
+		/* Error handling. See errno. */
+	}
+
+	struct serial_rs485 rs485conf;
+
+	/* Set RS485 mode: */
+	rs485conf.flags |= SER_RS485_ENABLED;
+
+	/* 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 = ...;
+
+	if (ioctl (fd, TIOCSRS485, &rs485conf) < 0) {
+		/* Error handling. See errno. */
+	}
+
+	/* Use read() and write() syscalls here... */
+
+	/* Close the device when finished: */
+	if (close (fd) < 0) {
+		/* Error handling. See errno. */
+	}
+
+5. REFERENCES
+
+ [1]	include/linux/serial.h
diff -druNp linux-libre-2.6.37-gnu1/Documentation/serial/tty.txt linux-libre-2.6.38-gnu1/Documentation/serial/tty.txt
--- linux-libre-2.6.37-gnu1/Documentation/serial/tty.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/serial/tty.txt	2011-03-14 21:20:32.000000000 -0400
@@ -107,7 +107,7 @@ write_wakeup()	-	May be called at any po
 
 dcd_change()	-	Report to the tty line the current DCD pin status
 			changes and the relative timestamp. The timestamp
-			can be NULL.
+			cannot be NULL.
 
 
 Driver Access
diff -druNp linux-libre-2.6.37-gnu1/Documentation/sound/alsa/ALSA-Configuration.txt linux-libre-2.6.38-gnu1/Documentation/sound/alsa/ALSA-Configuration.txt
--- linux-libre-2.6.37-gnu1/Documentation/sound/alsa/ALSA-Configuration.txt	2013-05-03 04:06:41.000000000 -0400
+++ linux-libre-2.6.38-gnu1/Documentation/sound/alsa/ALSA-Configuration.txt	2013-05-03 02:09:59.000000000 -0400
@@ -974,13 +974,6 @@ Prior to version 0.9.0rc4 options had a
 
     See hdspm.txt for details.
 
-  Module snd-hifier
-  -----------------
-
-    Module for the MediaTek/TempoTec HiFier Fantasia sound card.
-
-    This module supports autoprobe and multiple cards.
-
   Module snd-ice1712
   ------------------
 
@@ -1531,15 +1524,20 @@ Prior to version 0.9.0rc4 options had a
   Module snd-oxygen
   -----------------
 
-    Module for sound cards based on the C-Media CMI8788 chip:
+    Module for sound cards based on the C-Media CMI8786/8787/8788 chip:
     * Asound A-8788
+    * Asus Xonar DG
     * AuzenTech X-Meridian
+    * AuzenTech X-Meridian 2G
     * Bgears b-Enspirer
     * Club3D Theatron DTS
     * HT-Omega Claro (plus)
     * HT-Omega Claro halo (XT)
+    * Kuroutoshikou CMI8787-HG2PCI
     * Razer Barracuda AC-1
     * Sondigo Inferno
+    * TempoTec HiFier Fantasia
+    * TempoTec HiFier Serenade
 
     This module supports autoprobe and multiple cards.
 
@@ -1997,9 +1995,9 @@ Prior to version 0.9.0rc4 options had a
   Module snd-virtuoso
   -------------------
 
-    Module for sound cards based on the Asus AV100/AV200 chips,
-    i.e., Xonar D1, DX, D2, D2X, DS, HDAV1.3 (Deluxe), Essence ST
-    (Deluxe) and Essence STX.
+    Module for sound cards based on the Asus AV66/AV100/AV200 chips,
+    i.e., Xonar D1, DX, D2, D2X, DS, Essence ST (Deluxe), Essence STX,
+    HDAV1.3 (Deluxe), and HDAV1.3 Slim.
 
     This module supports autoprobe and multiple cards.
 
diff -druNp linux-libre-2.6.37-gnu1/Documentation/sound/alsa/HD-Audio-Models.txt linux-libre-2.6.38-gnu1/Documentation/sound/alsa/HD-Audio-Models.txt
--- linux-libre-2.6.37-gnu1/Documentation/sound/alsa/HD-Audio-Models.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/sound/alsa/HD-Audio-Models.txt	2011-03-14 21:20:32.000000000 -0400
@@ -149,7 +149,6 @@ ALC882/883/885/888/889
   acer-aspire-7730g Acer Aspire 7730G
   acer-aspire-8930g Acer Aspire 8930G
   medion	Medion Laptops
-  medion-md2	Medion MD2
   targa-dig	Targa/MSI
   targa-2ch-dig	Targa/MSI with 2-channel
   targa-8ch-dig Targa/MSI with 8-channel (MSI GX620)
@@ -297,6 +296,7 @@ Conexant 5066
 =============
   laptop	Basic Laptop config (default)
   hp-laptop	HP laptops, e g G60
+  asus		Asus K52JU, Lenovo G560
   dell-laptop	Dell laptops
   dell-vostro	Dell Vostro
   olpc-xo-1_5	OLPC XO 1.5
diff -druNp linux-libre-2.6.37-gnu1/Documentation/sound/alsa/soc/codec.txt linux-libre-2.6.38-gnu1/Documentation/sound/alsa/soc/codec.txt
--- linux-libre-2.6.37-gnu1/Documentation/sound/alsa/soc/codec.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/sound/alsa/soc/codec.txt	2011-03-14 21:20:32.000000000 -0400
@@ -27,42 +27,38 @@ ASoC Codec driver breakdown
 
 1 - Codec DAI and PCM configuration
 -----------------------------------
-Each codec driver must have a struct snd_soc_codec_dai to define its DAI and
+Each codec driver must have a struct snd_soc_dai_driver to define its DAI and
 PCM capabilities and operations. This struct is exported so that it can be
 registered with the core by your machine driver.
 
 e.g.
 
-struct snd_soc_codec_dai wm8731_dai = {
-	.name = "WM8731",
-	/* playback capabilities */
+static struct snd_soc_dai_ops wm8731_dai_ops = {
+	.prepare	= wm8731_pcm_prepare,
+	.hw_params	= wm8731_hw_params,
+	.shutdown	= wm8731_shutdown,
+	.digital_mute	= wm8731_mute,
+	.set_sysclk	= wm8731_set_dai_sysclk,
+	.set_fmt	= wm8731_set_dai_fmt,
+};
+
+struct snd_soc_dai_driver wm8731_dai = {
+	.name = "wm8731-hifi",
 	.playback = {
 		.stream_name = "Playback",
 		.channels_min = 1,
 		.channels_max = 2,
 		.rates = WM8731_RATES,
 		.formats = WM8731_FORMATS,},
-	/* capture capabilities */
 	.capture = {
 		.stream_name = "Capture",
 		.channels_min = 1,
 		.channels_max = 2,
 		.rates = WM8731_RATES,
 		.formats = WM8731_FORMATS,},
-	/* pcm operations - see section 4 below */
-	.ops = {
-		.prepare = wm8731_pcm_prepare,
-		.hw_params = wm8731_hw_params,
-		.shutdown = wm8731_shutdown,
-	},
-	/* DAI operations - see DAI.txt */
-	.dai_ops = {
-		.digital_mute = wm8731_mute,
-		.set_sysclk = wm8731_set_dai_sysclk,
-		.set_fmt = wm8731_set_dai_fmt,
-	}
+	.ops = &wm8731_dai_ops,
+	.symmetric_rates = 1,
 };
-EXPORT_SYMBOL_GPL(wm8731_dai);
 
 
 2 - Codec control IO
@@ -186,13 +182,14 @@ when the mute is applied or freed.
 
 i.e.
 
-static int wm8974_mute(struct snd_soc_codec *codec,
-	struct snd_soc_codec_dai *dai, int mute)
+static int wm8974_mute(struct snd_soc_dai *dai, int mute)
 {
-	u16 mute_reg = wm8974_read_reg_cache(codec, WM8974_DAC) & 0xffbf;
-	if(mute)
-		wm8974_write(codec, WM8974_DAC, mute_reg | 0x40);
+	struct snd_soc_codec *codec = dai->codec;
+	u16 mute_reg = snd_soc_read(codec, WM8974_DAC) & 0xffbf;
+
+	if (mute)
+		snd_soc_write(codec, WM8974_DAC, mute_reg | 0x40);
 	else
-		wm8974_write(codec, WM8974_DAC, mute_reg);
+		snd_soc_write(codec, WM8974_DAC, mute_reg);
 	return 0;
 }
diff -druNp linux-libre-2.6.37-gnu1/Documentation/sound/alsa/soc/machine.txt linux-libre-2.6.38-gnu1/Documentation/sound/alsa/soc/machine.txt
--- linux-libre-2.6.37-gnu1/Documentation/sound/alsa/soc/machine.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/sound/alsa/soc/machine.txt	2011-03-14 21:20:32.000000000 -0400
@@ -12,6 +12,8 @@ the following struct:-
 struct snd_soc_card {
 	char *name;
 
+	...
+
 	int (*probe)(struct platform_device *pdev);
 	int (*remove)(struct platform_device *pdev);
 
@@ -22,12 +24,13 @@ struct snd_soc_card {
 	int (*resume_pre)(struct platform_device *pdev);
 	int (*resume_post)(struct platform_device *pdev);
 
-	/* machine stream operations */
-	struct snd_soc_ops *ops;
+	...
 
 	/* CPU <--> Codec DAI links  */
 	struct snd_soc_dai_link *dai_link;
 	int num_links;
+
+	...
 };
 
 probe()/remove()
@@ -42,11 +45,6 @@ of any machine audio tasks that have to
 and DMA is suspended and resumed. Optional.
 
 
-Machine operations
-------------------
-The machine specific audio operations can be set here. Again this is optional.
-
-
 Machine DAI Configuration
 -------------------------
 The machine DAI configuration glues all the codec and CPU DAIs together. It can
@@ -61,8 +59,10 @@ struct snd_soc_dai_link is used to set u
 static struct snd_soc_dai_link corgi_dai = {
 	.name = "WM8731",
 	.stream_name = "WM8731",
-	.cpu_dai = &pxa_i2s_dai,
-	.codec_dai = &wm8731_dai,
+	.cpu_dai_name = "pxa-is2-dai",
+	.codec_dai_name = "wm8731-hifi",
+	.platform_name = "pxa-pcm-audio",
+	.codec_name = "wm8713-codec.0-001a",
 	.init = corgi_wm8731_init,
 	.ops = &corgi_ops,
 };
@@ -77,26 +77,6 @@ static struct snd_soc_card snd_soc_corgi
 };
 
 
-Machine Audio Subsystem
------------------------
-
-The machine soc device glues the platform, machine and codec driver together.
-Private data can also be set here. e.g.
-
-/* corgi audio private data */
-static struct wm8731_setup_data corgi_wm8731_setup = {
-	.i2c_address = 0x1b,
-};
-
-/* corgi audio subsystem */
-static struct snd_soc_device corgi_snd_devdata = {
-	.machine = &snd_soc_corgi,
-	.platform = &pxa2xx_soc_platform,
-	.codec_dev = &soc_codec_dev_wm8731,
-	.codec_data = &corgi_wm8731_setup,
-};
-
-
 Machine Power Map
 -----------------
 
diff -druNp linux-libre-2.6.37-gnu1/Documentation/sound/alsa/soc/platform.txt linux-libre-2.6.38-gnu1/Documentation/sound/alsa/soc/platform.txt
--- linux-libre-2.6.37-gnu1/Documentation/sound/alsa/soc/platform.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/sound/alsa/soc/platform.txt	2011-03-14 21:20:32.000000000 -0400
@@ -20,9 +20,10 @@ struct snd_soc_ops {
 	int (*trigger)(struct snd_pcm_substream *, int);
 };
 
-The platform driver exports its DMA functionality via struct snd_soc_platform:-
+The platform driver exports its DMA functionality via struct
+snd_soc_platform_driver:-
 
-struct snd_soc_platform {
+struct snd_soc_platform_driver {
 	char *name;
 
 	int (*probe)(struct platform_device *pdev);
@@ -34,6 +35,13 @@ struct snd_soc_platform {
 	int (*pcm_new)(struct snd_card *, struct snd_soc_codec_dai *, struct snd_pcm *);
 	void (*pcm_free)(struct snd_pcm *);
 
+	/*
+	 * For platform caused delay reporting.
+	 * Optional.
+	 */
+	snd_pcm_sframes_t (*delay)(struct snd_pcm_substream *,
+		struct snd_soc_dai *);
+
 	/* platform stream ops */
 	struct snd_pcm_ops *pcm_ops;
 };
diff -druNp linux-libre-2.6.37-gnu1/Documentation/spi/pxa2xx linux-libre-2.6.38-gnu1/Documentation/spi/pxa2xx
--- linux-libre-2.6.37-gnu1/Documentation/spi/pxa2xx	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/spi/pxa2xx	2011-03-14 21:20:32.000000000 -0400
@@ -19,7 +19,7 @@ Declaring PXA2xx Master Controllers
 -----------------------------------
 Typically a SPI master is defined in the arch/.../mach-*/board-*.c as a
 "platform device".  The master configuration is passed to the driver via a table
-found in arch/arm/mach-pxa/include/mach/pxa2xx_spi.h:
+found in include/linux/spi/pxa2xx_spi.h:
 
 struct pxa2xx_spi_master {
 	enum pxa_ssp_type ssp_type;
@@ -94,7 +94,7 @@ using the "spi_board_info" structure fou
 
 Each slave device attached to the PXA must provide slave specific configuration
 information via the structure "pxa2xx_spi_chip" found in
-"arch/arm/mach-pxa/include/mach/pxa2xx_spi.h".  The pxa2xx_spi master controller driver
+"include/linux/spi/pxa2xx_spi.h".  The pxa2xx_spi master controller driver
 will uses the configuration whenever the driver communicates with the slave
 device. All fields are optional.
 
diff -druNp linux-libre-2.6.37-gnu1/Documentation/sysctl/00-INDEX linux-libre-2.6.38-gnu1/Documentation/sysctl/00-INDEX
--- linux-libre-2.6.37-gnu1/Documentation/sysctl/00-INDEX	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/sysctl/00-INDEX	2011-03-14 21:20:32.000000000 -0400
@@ -4,8 +4,6 @@ README
 	- general information about /proc/sys/ sysctl files.
 abi.txt
 	- documentation for /proc/sys/abi/*.
-ctl_unnumbered.txt
-	- explanation of why one should not add new binary sysctl numbers.
 fs.txt
 	- documentation for /proc/sys/fs/*.
 kernel.txt
diff -druNp linux-libre-2.6.37-gnu1/Documentation/sysctl/kernel.txt linux-libre-2.6.38-gnu1/Documentation/sysctl/kernel.txt
--- linux-libre-2.6.37-gnu1/Documentation/sysctl/kernel.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/sysctl/kernel.txt	2011-03-14 21:20:32.000000000 -0400
@@ -34,6 +34,7 @@ show up in /proc/sys/kernel:
 - hotplug
 - java-appletviewer           [ binfmt_java, obsolete ]
 - java-interpreter            [ binfmt_java, obsolete ]
+- kptr_restrict
 - kstack_depth_to_print       [ X86 only ]
 - l2cr                        [ PPC only ]
 - modprobe                    ==> Documentation/debugging-modules.txt
@@ -219,7 +220,7 @@ dmesg_restrict:
 This toggle indicates whether unprivileged users are prevented from using
 dmesg(8) to view messages from the kernel's log buffer.  When
 dmesg_restrict is set to (0) there are no restrictions.  When
-dmesg_restrict is set set to (1), users must have CAP_SYS_ADMIN to use
+dmesg_restrict is set set to (1), users must have CAP_SYSLOG to use
 dmesg(8).
 
 The kernel config option CONFIG_SECURITY_DMESG_RESTRICT sets the default
@@ -261,6 +262,19 @@ This flag controls the L2 cache of G3 pr
 
 ==============================================================
 
+kptr_restrict:
+
+This toggle indicates whether restrictions are placed on
+exposing kernel addresses via /proc and other interfaces.  When
+kptr_restrict is set to (0), there are no restrictions.  When
+kptr_restrict is set to (1), the default, kernel pointers
+printed using the %pK format specifier will be replaced with 0's
+unless the user has CAP_SYSLOG.  When kptr_restrict is set to
+(2), kernel pointers printed using %pK will be replaced with 0's
+regardless of privileges.
+
+==============================================================
+
 kstack_depth_to_print: (X86 only)
 
 Controls the number of words to print when dumping the raw
diff -druNp linux-libre-2.6.37-gnu1/Documentation/target/tcm_mod_builder.py linux-libre-2.6.38-gnu1/Documentation/target/tcm_mod_builder.py
--- linux-libre-2.6.37-gnu1/Documentation/target/tcm_mod_builder.py	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/target/tcm_mod_builder.py	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,1094 @@
+#!/usr/bin/python
+# The TCM v4 multi-protocol fabric module generation script for drivers/target/$NEW_MOD
+#
+# Copyright (c) 2010 Rising Tide Systems
+# Copyright (c) 2010 Linux-iSCSI.org
+#
+# Author: nab@kernel.org
+#
+import os, sys
+import subprocess as sub
+import string
+import re
+import optparse
+
+tcm_dir = ""
+
+fabric_ops = []
+fabric_mod_dir = ""
+fabric_mod_port = ""
+fabric_mod_init_port = ""
+
+def tcm_mod_err(msg):
+	print msg
+	sys.exit(1)
+
+def tcm_mod_create_module_subdir(fabric_mod_dir_var):
+
+	if os.path.isdir(fabric_mod_dir_var) == True:
+		return 1
+
+	print "Creating fabric_mod_dir: " + fabric_mod_dir_var
+	ret = os.mkdir(fabric_mod_dir_var)
+	if ret:
+		tcm_mod_err("Unable to mkdir " + fabric_mod_dir_var)
+
+	return
+
+def tcm_mod_build_FC_include(fabric_mod_dir_var, fabric_mod_name):
+	global fabric_mod_port
+	global fabric_mod_init_port
+	buf = ""
+
+	f = fabric_mod_dir_var + "/" + fabric_mod_name + "_base.h"
+	print "Writing file: " + f
+
+	p = open(f, 'w');
+	if not p:
+		tcm_mod_err("Unable to open file: " + f)
+
+	buf = "#define " + fabric_mod_name.upper() + "_VERSION	\"v0.1\"\n"
+	buf += "#define " + fabric_mod_name.upper() + "_NAMELEN	32\n"
+	buf += "\n"
+	buf += "struct " + fabric_mod_name + "_nacl {\n"
+	buf += "	/* Binary World Wide unique Port Name for FC Initiator Nport */\n"
+	buf += "	u64 nport_wwpn;\n"
+	buf += "	/* ASCII formatted WWPN for FC Initiator Nport */\n"
+	buf += "	char nport_name[" + fabric_mod_name.upper() + "_NAMELEN];\n"
+	buf += "	/* Returned by " + fabric_mod_name + "_make_nodeacl() */\n"
+	buf += "	struct se_node_acl se_node_acl;\n"
+	buf += "};\n"
+	buf += "\n"
+	buf += "struct " + fabric_mod_name + "_tpg {\n"
+	buf += "	/* FC lport target portal group tag for TCM */\n"
+	buf += "	u16 lport_tpgt;\n"
+	buf += "	/* Pointer back to " + fabric_mod_name + "_lport */\n"
+	buf += "	struct " + fabric_mod_name + "_lport *lport;\n"
+	buf += "	/* Returned by " + fabric_mod_name + "_make_tpg() */\n"
+	buf += "	struct se_portal_group se_tpg;\n"
+	buf += "};\n"
+	buf += "\n"
+	buf += "struct " + fabric_mod_name + "_lport {\n"
+	buf += "	/* SCSI protocol the lport is providing */\n"
+	buf += "	u8 lport_proto_id;\n"
+	buf += "	/* Binary World Wide unique Port Name for FC Target Lport */\n"
+	buf += "	u64 lport_wwpn;\n"
+	buf += "	/* ASCII formatted WWPN for FC Target Lport */\n"
+	buf += "	char lport_name[" + fabric_mod_name.upper() + "_NAMELEN];\n"
+	buf += "	/* Returned by " + fabric_mod_name + "_make_lport() */\n"
+	buf += "	struct se_wwn lport_wwn;\n"
+	buf += "};\n"
+
+	ret = p.write(buf)
+	if ret:
+		tcm_mod_err("Unable to write f: " + f)
+
+	p.close()
+
+	fabric_mod_port = "lport"
+	fabric_mod_init_port = "nport"
+
+	return
+
+def tcm_mod_build_SAS_include(fabric_mod_dir_var, fabric_mod_name):
+	global fabric_mod_port
+	global fabric_mod_init_port
+	buf = ""
+
+	f = fabric_mod_dir_var + "/" + fabric_mod_name + "_base.h"
+	print "Writing file: " + f
+
+	p = open(f, 'w');
+	if not p:
+		tcm_mod_err("Unable to open file: " + f)
+
+	buf = "#define " + fabric_mod_name.upper() + "_VERSION  \"v0.1\"\n"
+	buf += "#define " + fabric_mod_name.upper() + "_NAMELEN 32\n"
+	buf += "\n"
+	buf += "struct " + fabric_mod_name + "_nacl {\n"
+	buf += "	/* Binary World Wide unique Port Name for SAS Initiator port */\n"
+	buf += "	u64 iport_wwpn;\n"
+	buf += "	/* ASCII formatted WWPN for Sas Initiator port */\n"
+	buf += "	char iport_name[" + fabric_mod_name.upper() + "_NAMELEN];\n"
+	buf += "	/* Returned by " + fabric_mod_name + "_make_nodeacl() */\n"
+	buf += "	struct se_node_acl se_node_acl;\n"
+	buf += "};\n\n"
+	buf += "struct " + fabric_mod_name + "_tpg {\n"
+	buf += "	/* SAS port target portal group tag for TCM */\n"
+	buf += "	u16 tport_tpgt;\n"
+	buf += "	/* Pointer back to " + fabric_mod_name + "_tport */\n"
+	buf += "	struct " + fabric_mod_name + "_tport *tport;\n"
+	buf += "	/* Returned by " + fabric_mod_name + "_make_tpg() */\n"
+	buf += "	struct se_portal_group se_tpg;\n"
+	buf += "};\n\n"
+	buf += "struct " + fabric_mod_name + "_tport {\n"
+	buf += "	/* SCSI protocol the tport is providing */\n"
+	buf += "	u8 tport_proto_id;\n"
+	buf += "	/* Binary World Wide unique Port Name for SAS Target port */\n"
+	buf += "	u64 tport_wwpn;\n"
+	buf += "	/* ASCII formatted WWPN for SAS Target port */\n"
+	buf += "	char tport_name[" + fabric_mod_name.upper() + "_NAMELEN];\n"
+	buf += "	/* Returned by " + fabric_mod_name + "_make_tport() */\n"
+	buf += "	struct se_wwn tport_wwn;\n"
+	buf += "};\n"
+
+	ret = p.write(buf)
+	if ret:
+		tcm_mod_err("Unable to write f: " + f)
+
+	p.close()
+
+	fabric_mod_port = "tport"
+	fabric_mod_init_port = "iport"
+
+	return
+
+def tcm_mod_build_iSCSI_include(fabric_mod_dir_var, fabric_mod_name):
+	global fabric_mod_port
+	global fabric_mod_init_port
+	buf = ""
+
+	f = fabric_mod_dir_var + "/" + fabric_mod_name + "_base.h"
+	print "Writing file: " + f
+
+	p = open(f, 'w');
+	if not p:
+		tcm_mod_err("Unable to open file: " + f)
+
+	buf = "#define " + fabric_mod_name.upper() + "_VERSION  \"v0.1\"\n"
+	buf += "#define " + fabric_mod_name.upper() + "_NAMELEN 32\n"
+	buf += "\n"
+	buf += "struct " + fabric_mod_name + "_nacl {\n"
+	buf += "	/* ASCII formatted InitiatorName */\n"
+	buf += "	char iport_name[" + fabric_mod_name.upper() + "_NAMELEN];\n"
+	buf += "	/* Returned by " + fabric_mod_name + "_make_nodeacl() */\n"
+	buf += "	struct se_node_acl se_node_acl;\n"
+	buf += "};\n\n"
+	buf += "struct " + fabric_mod_name + "_tpg {\n"
+	buf += "	/* iSCSI target portal group tag for TCM */\n"
+	buf += "	u16 tport_tpgt;\n"
+	buf += "	/* Pointer back to " + fabric_mod_name + "_tport */\n"
+	buf += "	struct " + fabric_mod_name + "_tport *tport;\n"
+	buf += "	/* Returned by " + fabric_mod_name + "_make_tpg() */\n"
+	buf += "	struct se_portal_group se_tpg;\n"
+	buf += "};\n\n"
+	buf += "struct " + fabric_mod_name + "_tport {\n"
+	buf += "	/* SCSI protocol the tport is providing */\n"
+	buf += "	u8 tport_proto_id;\n"
+	buf += "	/* ASCII formatted TargetName for IQN */\n"
+	buf += "	char tport_name[" + fabric_mod_name.upper() + "_NAMELEN];\n"
+	buf += "	/* Returned by " + fabric_mod_name + "_make_tport() */\n"
+	buf += "	struct se_wwn tport_wwn;\n"
+	buf += "};\n"
+
+	ret = p.write(buf)
+	if ret:
+		tcm_mod_err("Unable to write f: " + f)
+
+	p.close()
+
+	fabric_mod_port = "tport"
+	fabric_mod_init_port = "iport"
+
+	return
+
+def tcm_mod_build_base_includes(proto_ident, fabric_mod_dir_val, fabric_mod_name):
+
+	if proto_ident == "FC":
+		tcm_mod_build_FC_include(fabric_mod_dir_val, fabric_mod_name)
+	elif proto_ident == "SAS":
+		tcm_mod_build_SAS_include(fabric_mod_dir_val, fabric_mod_name)
+	elif proto_ident == "iSCSI":
+		tcm_mod_build_iSCSI_include(fabric_mod_dir_val, fabric_mod_name)
+	else:
+		print "Unsupported proto_ident: " + proto_ident
+		sys.exit(1)
+
+	return
+
+def tcm_mod_build_configfs(proto_ident, fabric_mod_dir_var, fabric_mod_name):
+	buf = ""
+
+	f = fabric_mod_dir_var + "/" + fabric_mod_name + "_configfs.c"
+	print "Writing file: " + f
+
+        p = open(f, 'w');
+        if not p:
+                tcm_mod_err("Unable to open file: " + f)
+
+	buf = "#include <linux/module.h>\n"
+	buf += "#include <linux/moduleparam.h>\n"
+	buf += "#include <linux/version.h>\n"
+	buf += "#include <generated/utsrelease.h>\n"
+	buf += "#include <linux/utsname.h>\n"
+	buf += "#include <linux/init.h>\n"
+	buf += "#include <linux/slab.h>\n"
+	buf += "#include <linux/kthread.h>\n"
+	buf += "#include <linux/types.h>\n"
+	buf += "#include <linux/string.h>\n"
+	buf += "#include <linux/configfs.h>\n"
+	buf += "#include <linux/ctype.h>\n"
+	buf += "#include <asm/unaligned.h>\n\n"
+	buf += "#include <target/target_core_base.h>\n"
+	buf += "#include <target/target_core_transport.h>\n"
+	buf += "#include <target/target_core_fabric_ops.h>\n"
+	buf += "#include <target/target_core_fabric_configfs.h>\n"
+	buf += "#include <target/target_core_fabric_lib.h>\n"
+	buf += "#include <target/target_core_device.h>\n"
+	buf += "#include <target/target_core_tpg.h>\n"
+	buf += "#include <target/target_core_configfs.h>\n"
+	buf += "#include <target/target_core_base.h>\n"
+	buf += "#include <target/configfs_macros.h>\n\n"
+	buf += "#include <" + fabric_mod_name + "_base.h>\n"
+	buf += "#include <" + fabric_mod_name + "_fabric.h>\n\n"
+
+	buf += "/* Local pointer to allocated TCM configfs fabric module */\n"
+	buf += "struct target_fabric_configfs *" + fabric_mod_name + "_fabric_configfs;\n\n"
+
+	buf += "static struct se_node_acl *" + fabric_mod_name + "_make_nodeacl(\n"
+	buf += "	struct se_portal_group *se_tpg,\n"
+	buf += "	struct config_group *group,\n"
+	buf += "	const char *name)\n"
+	buf += "{\n"
+	buf += "	struct se_node_acl *se_nacl, *se_nacl_new;\n"
+	buf += "	struct " + fabric_mod_name + "_nacl *nacl;\n"
+
+	if proto_ident == "FC" or proto_ident == "SAS":
+		buf += "	u64 wwpn = 0;\n"
+
+	buf += "	u32 nexus_depth;\n\n"
+	buf += "	/* " + fabric_mod_name + "_parse_wwn(name, &wwpn, 1) < 0)\n"
+	buf += "		return ERR_PTR(-EINVAL); */\n"
+	buf += "	se_nacl_new = " + fabric_mod_name + "_alloc_fabric_acl(se_tpg);\n"
+	buf += "	if (!(se_nacl_new))\n"
+	buf += "		return ERR_PTR(-ENOMEM);\n"
+	buf += "//#warning FIXME: Hardcoded nexus depth in " + fabric_mod_name + "_make_nodeacl()\n"
+	buf += "	nexus_depth = 1;\n"
+	buf += "	/*\n"
+	buf += "	 * se_nacl_new may be released by core_tpg_add_initiator_node_acl()\n"
+	buf += "	 * when converting a NodeACL from demo mode -> explict\n"
+	buf += "	 */\n"
+	buf += "	se_nacl = core_tpg_add_initiator_node_acl(se_tpg, se_nacl_new,\n"
+	buf += "				name, nexus_depth);\n"
+	buf += "	if (IS_ERR(se_nacl)) {\n"
+	buf += "		" + fabric_mod_name + "_release_fabric_acl(se_tpg, se_nacl_new);\n"
+	buf += "		return se_nacl;\n"
+	buf += "	}\n"
+	buf += "	/*\n"
+	buf += "	 * Locate our struct " + fabric_mod_name + "_nacl and set the FC Nport WWPN\n"
+	buf += "	 */\n"
+	buf += "	nacl = container_of(se_nacl, struct " + fabric_mod_name + "_nacl, se_node_acl);\n"
+
+	if proto_ident == "FC" or proto_ident == "SAS":
+		buf += "	nacl->" + fabric_mod_init_port + "_wwpn = wwpn;\n"
+
+	buf += "	/* " + fabric_mod_name + "_format_wwn(&nacl->" + fabric_mod_init_port + "_name[0], " + fabric_mod_name.upper() + "_NAMELEN, wwpn); */\n\n"
+	buf += "	return se_nacl;\n"
+	buf += "}\n\n"
+	buf += "static void " + fabric_mod_name + "_drop_nodeacl(struct se_node_acl *se_acl)\n"
+	buf += "{\n"
+	buf += "	struct " + fabric_mod_name + "_nacl *nacl = container_of(se_acl,\n"
+	buf += "				struct " + fabric_mod_name + "_nacl, se_node_acl);\n"
+	buf += "	kfree(nacl);\n"
+	buf += "}\n\n"
+
+	buf += "static struct se_portal_group *" + fabric_mod_name + "_make_tpg(\n"
+	buf += "	struct se_wwn *wwn,\n"
+	buf += "	struct config_group *group,\n"
+	buf += "	const char *name)\n"
+	buf += "{\n"
+	buf += "	struct " + fabric_mod_name + "_" + fabric_mod_port + "*" + fabric_mod_port + " = container_of(wwn,\n"
+	buf += "			struct " + fabric_mod_name + "_" + fabric_mod_port + ", " + fabric_mod_port + "_wwn);\n\n"
+	buf += "	struct " + fabric_mod_name + "_tpg *tpg;\n"
+	buf += "	unsigned long tpgt;\n"
+	buf += "	int ret;\n\n"
+	buf += "	if (strstr(name, \"tpgt_\") != name)\n"
+	buf += "		return ERR_PTR(-EINVAL);\n"
+	buf += "	if (strict_strtoul(name + 5, 10, &tpgt) || tpgt > UINT_MAX)\n"
+	buf += "		return ERR_PTR(-EINVAL);\n\n"
+	buf += "	tpg = kzalloc(sizeof(struct " + fabric_mod_name + "_tpg), GFP_KERNEL);\n"
+	buf += "	if (!(tpg)) {\n"
+	buf += "		printk(KERN_ERR \"Unable to allocate struct " + fabric_mod_name + "_tpg\");\n"
+	buf += "		return ERR_PTR(-ENOMEM);\n"
+	buf += "	}\n"
+	buf += "	tpg->" + fabric_mod_port + " = " + fabric_mod_port + ";\n"
+	buf += "	tpg->" + fabric_mod_port + "_tpgt = tpgt;\n\n"
+	buf += "	ret = core_tpg_register(&" + fabric_mod_name + "_fabric_configfs->tf_ops, wwn,\n"
+	buf += "				&tpg->se_tpg, (void *)tpg,\n"
+	buf += "				TRANSPORT_TPG_TYPE_NORMAL);\n"
+	buf += "	if (ret < 0) {\n"
+	buf += "		kfree(tpg);\n"
+	buf += "		return NULL;\n"
+	buf += "	}\n"
+	buf += "	return &tpg->se_tpg;\n"
+	buf += "}\n\n"
+	buf += "static void " + fabric_mod_name + "_drop_tpg(struct se_portal_group *se_tpg)\n"
+	buf += "{\n"
+	buf += "	struct " + fabric_mod_name + "_tpg *tpg = container_of(se_tpg,\n"
+	buf += "				struct " + fabric_mod_name + "_tpg, se_tpg);\n\n"
+	buf += "	core_tpg_deregister(se_tpg);\n"
+	buf += "	kfree(tpg);\n"
+	buf += "}\n\n"
+
+	buf += "static struct se_wwn *" + fabric_mod_name + "_make_" + fabric_mod_port + "(\n"
+	buf += "	struct target_fabric_configfs *tf,\n"
+	buf += "	struct config_group *group,\n"
+	buf += "	const char *name)\n"
+	buf += "{\n"
+	buf += "	struct " + fabric_mod_name + "_" + fabric_mod_port + " *" + fabric_mod_port + ";\n"
+
+	if proto_ident == "FC" or proto_ident == "SAS":
+		buf += "	u64 wwpn = 0;\n\n"
+
+	buf += "	/* if (" + fabric_mod_name + "_parse_wwn(name, &wwpn, 1) < 0)\n"
+	buf += "		return ERR_PTR(-EINVAL); */\n\n"
+	buf += "	" + fabric_mod_port + " = kzalloc(sizeof(struct " + fabric_mod_name + "_" + fabric_mod_port + "), GFP_KERNEL);\n"
+	buf += "	if (!(" + fabric_mod_port + ")) {\n"
+	buf += "		printk(KERN_ERR \"Unable to allocate struct " + fabric_mod_name + "_" + fabric_mod_port + "\");\n"
+	buf += "		return ERR_PTR(-ENOMEM);\n"
+	buf += "	}\n"
+
+	if proto_ident == "FC" or proto_ident == "SAS":
+		buf += "	" + fabric_mod_port + "->" + fabric_mod_port + "_wwpn = wwpn;\n"
+
+	buf += "	/* " + fabric_mod_name + "_format_wwn(&" + fabric_mod_port + "->" + fabric_mod_port + "_name[0], " + fabric_mod_name.upper() + "__NAMELEN, wwpn); */\n\n"
+	buf += "	return &" + fabric_mod_port + "->" + fabric_mod_port + "_wwn;\n"
+	buf += "}\n\n"
+	buf += "static void " + fabric_mod_name + "_drop_" + fabric_mod_port + "(struct se_wwn *wwn)\n"
+	buf += "{\n"
+	buf += "	struct " + fabric_mod_name + "_" + fabric_mod_port + " *" + fabric_mod_port + " = container_of(wwn,\n"
+	buf += "				struct " + fabric_mod_name + "_" + fabric_mod_port + ", " + fabric_mod_port + "_wwn);\n"
+	buf += "	kfree(" + fabric_mod_port + ");\n"
+	buf += "}\n\n"
+	buf += "static ssize_t " + fabric_mod_name + "_wwn_show_attr_version(\n"
+	buf += "	struct target_fabric_configfs *tf,\n"
+	buf += "	char *page)\n"
+	buf += "{\n"
+	buf += "	return sprintf(page, \"" + fabric_mod_name.upper() + " fabric module %s on %s/%s\"\n"
+	buf += "		\"on \"UTS_RELEASE\"\\n\", " + fabric_mod_name.upper() + "_VERSION, utsname()->sysname,\n"
+	buf += "		utsname()->machine);\n"
+	buf += "}\n\n"
+	buf += "TF_WWN_ATTR_RO(" + fabric_mod_name + ", version);\n\n"
+	buf += "static struct configfs_attribute *" + fabric_mod_name + "_wwn_attrs[] = {\n"
+	buf += "	&" + fabric_mod_name + "_wwn_version.attr,\n"
+	buf += "	NULL,\n"
+	buf += "};\n\n"
+
+	buf += "static struct target_core_fabric_ops " + fabric_mod_name + "_ops = {\n"
+	buf += "	.get_fabric_name		= " + fabric_mod_name + "_get_fabric_name,\n"
+	buf += "	.get_fabric_proto_ident		= " + fabric_mod_name + "_get_fabric_proto_ident,\n"
+	buf += "	.tpg_get_wwn			= " + fabric_mod_name + "_get_fabric_wwn,\n"
+	buf += "	.tpg_get_tag			= " + fabric_mod_name + "_get_tag,\n"
+	buf += "	.tpg_get_default_depth		= " + fabric_mod_name + "_get_default_depth,\n"
+	buf += "	.tpg_get_pr_transport_id	= " + fabric_mod_name + "_get_pr_transport_id,\n"
+	buf += "	.tpg_get_pr_transport_id_len	= " + fabric_mod_name + "_get_pr_transport_id_len,\n"
+	buf += "	.tpg_parse_pr_out_transport_id	= " + fabric_mod_name + "_parse_pr_out_transport_id,\n"
+	buf += "	.tpg_check_demo_mode		= " + fabric_mod_name + "_check_false,\n"
+	buf += "	.tpg_check_demo_mode_cache	= " + fabric_mod_name + "_check_true,\n"
+	buf += "	.tpg_check_demo_mode_write_protect = " + fabric_mod_name + "_check_true,\n"
+	buf += "	.tpg_check_prod_mode_write_protect = " + fabric_mod_name + "_check_false,\n"
+	buf += "	.tpg_alloc_fabric_acl		= " + fabric_mod_name + "_alloc_fabric_acl,\n"
+	buf += "	.tpg_release_fabric_acl		= " + fabric_mod_name + "_release_fabric_acl,\n"
+	buf += "	.tpg_get_inst_index		= " + fabric_mod_name + "_tpg_get_inst_index,\n"
+	buf += "	.release_cmd_to_pool		= " + fabric_mod_name + "_release_cmd,\n"
+	buf += "	.release_cmd_direct		= " + fabric_mod_name + "_release_cmd,\n"
+	buf += "	.shutdown_session		= " + fabric_mod_name + "_shutdown_session,\n"
+	buf += "	.close_session			= " + fabric_mod_name + "_close_session,\n"
+	buf += "	.stop_session			= " + fabric_mod_name + "_stop_session,\n"
+	buf += "	.fall_back_to_erl0		= " + fabric_mod_name + "_reset_nexus,\n"
+	buf += "	.sess_logged_in			= " + fabric_mod_name + "_sess_logged_in,\n"
+	buf += "	.sess_get_index			= " + fabric_mod_name + "_sess_get_index,\n"
+	buf += "	.sess_get_initiator_sid		= NULL,\n"
+	buf += "	.write_pending			= " + fabric_mod_name + "_write_pending,\n"
+	buf += "	.write_pending_status		= " + fabric_mod_name + "_write_pending_status,\n"
+	buf += "	.set_default_node_attributes	= " + fabric_mod_name + "_set_default_node_attrs,\n"
+	buf += "	.get_task_tag			= " + fabric_mod_name + "_get_task_tag,\n"
+	buf += "	.get_cmd_state			= " + fabric_mod_name + "_get_cmd_state,\n"
+	buf += "	.new_cmd_failure		= " + fabric_mod_name + "_new_cmd_failure,\n"
+	buf += "	.queue_data_in			= " + fabric_mod_name + "_queue_data_in,\n"
+	buf += "	.queue_status			= " + fabric_mod_name + "_queue_status,\n"
+	buf += "	.queue_tm_rsp			= " + fabric_mod_name + "_queue_tm_rsp,\n"
+	buf += "	.get_fabric_sense_len		= " + fabric_mod_name + "_get_fabric_sense_len,\n"
+	buf += "	.set_fabric_sense_len		= " + fabric_mod_name + "_set_fabric_sense_len,\n"
+	buf += "	.is_state_remove		= " + fabric_mod_name + "_is_state_remove,\n"
+	buf += "	.pack_lun			= " + fabric_mod_name + "_pack_lun,\n"
+	buf += "	/*\n"
+	buf += "	 * Setup function pointers for generic logic in target_core_fabric_configfs.c\n"
+	buf += "	 */\n"
+	buf += "	.fabric_make_wwn		= " + fabric_mod_name + "_make_" + fabric_mod_port + ",\n"
+	buf += "	.fabric_drop_wwn		= " + fabric_mod_name + "_drop_" + fabric_mod_port + ",\n"
+	buf += "	.fabric_make_tpg		= " + fabric_mod_name + "_make_tpg,\n"
+	buf += "	.fabric_drop_tpg		= " + fabric_mod_name + "_drop_tpg,\n"
+	buf += "	.fabric_post_link		= NULL,\n"
+	buf += "	.fabric_pre_unlink		= NULL,\n"
+	buf += "	.fabric_make_np			= NULL,\n"
+	buf += "	.fabric_drop_np			= NULL,\n"
+	buf += "	.fabric_make_nodeacl		= " + fabric_mod_name + "_make_nodeacl,\n"
+	buf += "	.fabric_drop_nodeacl		= " + fabric_mod_name + "_drop_nodeacl,\n"
+	buf += "};\n\n"
+
+	buf += "static int " + fabric_mod_name + "_register_configfs(void)\n"
+	buf += "{\n"
+	buf += "	struct target_fabric_configfs *fabric;\n"
+	buf += "	int ret;\n\n"
+	buf += "	printk(KERN_INFO \"" + fabric_mod_name.upper() + " fabric module %s on %s/%s\"\n"
+	buf += "		\" on \"UTS_RELEASE\"\\n\"," + fabric_mod_name.upper() + "_VERSION, utsname()->sysname,\n"
+	buf += "		utsname()->machine);\n"
+	buf += "	/*\n"
+	buf += "	 * Register the top level struct config_item_type with TCM core\n"
+	buf += "	 */\n"
+	buf += "	fabric = target_fabric_configfs_init(THIS_MODULE, \"" + fabric_mod_name[4:] + "\");\n"
+	buf += "	if (!(fabric)) {\n"
+	buf += "		printk(KERN_ERR \"target_fabric_configfs_init() failed\\n\");\n"
+	buf += "		return -ENOMEM;\n"
+	buf += "	}\n"
+	buf += "	/*\n"
+	buf += "	 * Setup fabric->tf_ops from our local " + fabric_mod_name + "_ops\n"
+	buf += "	 */\n"
+	buf += "	fabric->tf_ops = " + fabric_mod_name + "_ops;\n"
+	buf += "	/*\n"
+	buf += "	 * Setup default attribute lists for various fabric->tf_cit_tmpl\n"
+	buf += "	 */\n"
+	buf += "	TF_CIT_TMPL(fabric)->tfc_wwn_cit.ct_attrs = " + fabric_mod_name + "_wwn_attrs;\n"
+	buf += "	TF_CIT_TMPL(fabric)->tfc_tpg_base_cit.ct_attrs = NULL;\n"
+	buf += "	TF_CIT_TMPL(fabric)->tfc_tpg_attrib_cit.ct_attrs = NULL;\n"
+	buf += "	TF_CIT_TMPL(fabric)->tfc_tpg_param_cit.ct_attrs = NULL;\n"
+	buf += "	TF_CIT_TMPL(fabric)->tfc_tpg_np_base_cit.ct_attrs = NULL;\n"
+	buf += "	TF_CIT_TMPL(fabric)->tfc_tpg_nacl_base_cit.ct_attrs = NULL;\n"
+	buf += "	TF_CIT_TMPL(fabric)->tfc_tpg_nacl_attrib_cit.ct_attrs = NULL;\n"
+	buf += "	TF_CIT_TMPL(fabric)->tfc_tpg_nacl_auth_cit.ct_attrs = NULL;\n"
+	buf += "	TF_CIT_TMPL(fabric)->tfc_tpg_nacl_param_cit.ct_attrs = NULL;\n"
+	buf += "	/*\n"
+	buf += "	 * Register the fabric for use within TCM\n"
+	buf += "	 */\n"
+	buf += "	ret = target_fabric_configfs_register(fabric);\n"
+	buf += "	if (ret < 0) {\n"
+	buf += "		printk(KERN_ERR \"target_fabric_configfs_register() failed\"\n"
+	buf += "				\" for " + fabric_mod_name.upper() + "\\n\");\n"
+	buf += "		return ret;\n"
+	buf += "	}\n"
+	buf += "	/*\n"
+	buf += "	 * Setup our local pointer to *fabric\n"
+	buf += "	 */\n"
+	buf += "	" + fabric_mod_name + "_fabric_configfs = fabric;\n"
+	buf += "	printk(KERN_INFO \"" +  fabric_mod_name.upper() + "[0] - Set fabric -> " + fabric_mod_name + "_fabric_configfs\\n\");\n"
+	buf += "	return 0;\n"
+	buf += "};\n\n"
+	buf += "static void " + fabric_mod_name + "_deregister_configfs(void)\n"
+	buf += "{\n"
+	buf += "	if (!(" + fabric_mod_name + "_fabric_configfs))\n"
+	buf += "		return;\n\n"
+	buf += "	target_fabric_configfs_deregister(" + fabric_mod_name + "_fabric_configfs);\n"
+	buf += "	" + fabric_mod_name + "_fabric_configfs = NULL;\n"
+	buf += "	printk(KERN_INFO \"" +  fabric_mod_name.upper() + "[0] - Cleared " + fabric_mod_name + "_fabric_configfs\\n\");\n"
+	buf += "};\n\n"
+
+	buf += "static int __init " + fabric_mod_name + "_init(void)\n"
+	buf += "{\n"
+	buf += "	int ret;\n\n"
+	buf += "	ret = " + fabric_mod_name + "_register_configfs();\n"
+	buf += "	if (ret < 0)\n"
+	buf += "		return ret;\n\n"
+	buf += "	return 0;\n"
+	buf += "};\n\n"
+	buf += "static void " + fabric_mod_name + "_exit(void)\n"
+	buf += "{\n"
+	buf += "	" + fabric_mod_name + "_deregister_configfs();\n"
+	buf += "};\n\n"
+
+	buf += "#ifdef MODULE\n"
+	buf += "MODULE_DESCRIPTION(\"" + fabric_mod_name.upper() + " series fabric driver\");\n"
+	buf += "MODULE_LICENSE(\"GPL\");\n"
+	buf += "module_init(" + fabric_mod_name + "_init);\n"
+	buf += "module_exit(" + fabric_mod_name + "_exit);\n"
+	buf += "#endif\n"
+
+	ret = p.write(buf)
+	if ret:
+		tcm_mod_err("Unable to write f: " + f)
+
+	p.close()
+
+	return
+
+def tcm_mod_scan_fabric_ops(tcm_dir):
+
+	fabric_ops_api = tcm_dir + "include/target/target_core_fabric_ops.h"
+
+	print "Using tcm_mod_scan_fabric_ops: " + fabric_ops_api
+	process_fo = 0;
+
+	p = open(fabric_ops_api, 'r')
+
+	line = p.readline()
+	while line:
+		if process_fo == 0 and re.search('struct target_core_fabric_ops {', line):
+			line = p.readline()
+			continue
+
+		if process_fo == 0:
+			process_fo = 1;
+			line = p.readline()
+			# Search for function pointer
+			if not re.search('\(\*', line):
+				continue
+
+			fabric_ops.append(line.rstrip())
+			continue
+
+		line = p.readline()
+		# Search for function pointer
+		if not re.search('\(\*', line):
+			continue
+
+		fabric_ops.append(line.rstrip())
+
+	p.close()
+	return
+
+def tcm_mod_dump_fabric_ops(proto_ident, fabric_mod_dir_var, fabric_mod_name):
+	buf = ""
+	bufi = ""
+
+	f = fabric_mod_dir_var + "/" + fabric_mod_name + "_fabric.c"
+	print "Writing file: " + f
+
+	p = open(f, 'w')
+	if not p:
+		tcm_mod_err("Unable to open file: " + f)
+
+	fi = fabric_mod_dir_var + "/" + fabric_mod_name + "_fabric.h"
+	print "Writing file: " + fi
+
+	pi = open(fi, 'w')
+	if not pi:
+		tcm_mod_err("Unable to open file: " + fi)
+
+	buf = "#include <linux/slab.h>\n"
+	buf += "#include <linux/kthread.h>\n"
+	buf += "#include <linux/types.h>\n"
+	buf += "#include <linux/list.h>\n"
+	buf += "#include <linux/types.h>\n"
+	buf += "#include <linux/string.h>\n"
+	buf += "#include <linux/ctype.h>\n"
+	buf += "#include <asm/unaligned.h>\n"
+	buf += "#include <scsi/scsi.h>\n"
+	buf += "#include <scsi/scsi_host.h>\n"
+	buf += "#include <scsi/scsi_device.h>\n"
+	buf += "#include <scsi/scsi_cmnd.h>\n"
+	buf += "#include <scsi/libfc.h>\n\n"
+	buf += "#include <target/target_core_base.h>\n"
+	buf += "#include <target/target_core_transport.h>\n"
+	buf += "#include <target/target_core_fabric_ops.h>\n"
+	buf += "#include <target/target_core_fabric_lib.h>\n"
+	buf += "#include <target/target_core_device.h>\n"
+	buf += "#include <target/target_core_tpg.h>\n"
+	buf += "#include <target/target_core_configfs.h>\n"
+	buf += "#include <" + fabric_mod_name + "_base.h>\n"
+	buf += "#include <" + fabric_mod_name + "_fabric.h>\n\n"
+
+	buf += "int " + fabric_mod_name + "_check_true(struct se_portal_group *se_tpg)\n"
+	buf += "{\n"
+	buf += "	return 1;\n"
+	buf += "}\n\n"
+	bufi += "int " + fabric_mod_name + "_check_true(struct se_portal_group *);\n"
+
+	buf += "int " + fabric_mod_name + "_check_false(struct se_portal_group *se_tpg)\n"
+	buf += "{\n"
+	buf += "	return 0;\n"
+	buf += "}\n\n"
+	bufi += "int " + fabric_mod_name + "_check_false(struct se_portal_group *);\n"
+
+	total_fabric_ops = len(fabric_ops)
+	i = 0
+
+	while i < total_fabric_ops:
+		fo = fabric_ops[i]
+		i += 1
+#		print "fabric_ops: " + fo
+
+		if re.search('get_fabric_name', fo):
+			buf += "char *" + fabric_mod_name + "_get_fabric_name(void)\n"
+			buf += "{\n"
+			buf += "	return \"" + fabric_mod_name[4:] + "\";\n"
+			buf += "}\n\n"
+			bufi += "char *" + fabric_mod_name + "_get_fabric_name(void);\n"
+			continue
+
+		if re.search('get_fabric_proto_ident', fo):
+			buf += "u8 " + fabric_mod_name + "_get_fabric_proto_ident(struct se_portal_group *se_tpg)\n"
+			buf += "{\n"
+			buf += "	struct " + fabric_mod_name + "_tpg *tpg = container_of(se_tpg,\n"
+			buf += "				struct " + fabric_mod_name + "_tpg, se_tpg);\n"
+			buf += "	struct " + fabric_mod_name + "_" + fabric_mod_port + " *" + fabric_mod_port + " = tpg->" + fabric_mod_port + ";\n"
+			buf += "	u8 proto_id;\n\n"
+			buf += "	switch (" + fabric_mod_port + "->" + fabric_mod_port + "_proto_id) {\n"
+			if proto_ident == "FC":
+				buf += "	case SCSI_PROTOCOL_FCP:\n"
+				buf += "	default:\n"
+				buf += "		proto_id = fc_get_fabric_proto_ident(se_tpg);\n"
+				buf += "		break;\n"
+			elif proto_ident == "SAS":
+				buf += "	case SCSI_PROTOCOL_SAS:\n"
+				buf += "	default:\n"
+				buf += "		proto_id = sas_get_fabric_proto_ident(se_tpg);\n"
+				buf += "		break;\n"
+			elif proto_ident == "iSCSI":
+				buf += "	case SCSI_PROTOCOL_ISCSI:\n"
+				buf += "	default:\n"
+				buf += "		proto_id = iscsi_get_fabric_proto_ident(se_tpg);\n"
+				buf += "		break;\n"
+
+			buf += "	}\n\n"
+			buf += "	return proto_id;\n"
+			buf += "}\n\n"
+			bufi += "u8 " + fabric_mod_name + "_get_fabric_proto_ident(struct se_portal_group *);\n"
+
+		if re.search('get_wwn', fo):
+			buf += "char *" + fabric_mod_name + "_get_fabric_wwn(struct se_portal_group *se_tpg)\n"
+			buf += "{\n"
+			buf += "	struct " + fabric_mod_name + "_tpg *tpg = container_of(se_tpg,\n"
+			buf += "				struct " + fabric_mod_name + "_tpg, se_tpg);\n"
+			buf += "	struct " + fabric_mod_name + "_" + fabric_mod_port + " *" + fabric_mod_port + " = tpg->" + fabric_mod_port + ";\n\n"
+			buf += "	return &" + fabric_mod_port + "->" + fabric_mod_port + "_name[0];\n"
+			buf += "}\n\n"
+			bufi += "char *" + fabric_mod_name + "_get_fabric_wwn(struct se_portal_group *);\n"
+
+		if re.search('get_tag', fo):
+			buf += "u16 " + fabric_mod_name + "_get_tag(struct se_portal_group *se_tpg)\n"
+			buf += "{\n"
+			buf += "	struct " + fabric_mod_name + "_tpg *tpg = container_of(se_tpg,\n"
+			buf += "				struct " + fabric_mod_name + "_tpg, se_tpg);\n"
+			buf += "	return tpg->" + fabric_mod_port + "_tpgt;\n"
+			buf += "}\n\n"
+			bufi += "u16 " + fabric_mod_name + "_get_tag(struct se_portal_group *);\n"
+
+		if re.search('get_default_depth', fo):
+			buf += "u32 " + fabric_mod_name + "_get_default_depth(struct se_portal_group *se_tpg)\n"
+			buf += "{\n"
+			buf += "	return 1;\n"
+			buf += "}\n\n"
+			bufi += "u32 " + fabric_mod_name + "_get_default_depth(struct se_portal_group *);\n"
+
+		if re.search('get_pr_transport_id\)\(', fo):
+			buf += "u32 " + fabric_mod_name + "_get_pr_transport_id(\n"
+			buf += "	struct se_portal_group *se_tpg,\n"
+			buf += "	struct se_node_acl *se_nacl,\n"
+			buf += "	struct t10_pr_registration *pr_reg,\n"
+			buf += "	int *format_code,\n"
+			buf += "	unsigned char *buf)\n"
+			buf += "{\n"
+			buf += "	struct " + fabric_mod_name + "_tpg *tpg = container_of(se_tpg,\n"
+			buf += "				struct " + fabric_mod_name + "_tpg, se_tpg);\n"
+			buf += "	struct " + fabric_mod_name + "_" + fabric_mod_port + " *" + fabric_mod_port + " = tpg->" + fabric_mod_port + ";\n"
+			buf += "	int ret = 0;\n\n"
+			buf += "	switch (" + fabric_mod_port + "->" + fabric_mod_port + "_proto_id) {\n"
+			if proto_ident == "FC":
+				buf += "	case SCSI_PROTOCOL_FCP:\n"
+				buf += "	default:\n"
+				buf += "		ret = fc_get_pr_transport_id(se_tpg, se_nacl, pr_reg,\n"
+				buf += "					format_code, buf);\n"
+				buf += "		break;\n"
+			elif proto_ident == "SAS":
+				buf += "	case SCSI_PROTOCOL_SAS:\n"
+				buf += "	default:\n"
+				buf += "		ret = sas_get_pr_transport_id(se_tpg, se_nacl, pr_reg,\n"
+				buf += "					format_code, buf);\n"
+				buf += "		break;\n"
+			elif proto_ident == "iSCSI":
+				buf += "	case SCSI_PROTOCOL_ISCSI:\n"
+				buf += "	default:\n"
+				buf += "		ret = iscsi_get_pr_transport_id(se_tpg, se_nacl, pr_reg,\n"
+				buf += "					format_code, buf);\n"
+				buf += "		break;\n"
+
+			buf += "	}\n\n"
+			buf += "	return ret;\n"
+			buf += "}\n\n"
+			bufi += "u32 " + fabric_mod_name + "_get_pr_transport_id(struct se_portal_group *,\n"
+			bufi += "			struct se_node_acl *, struct t10_pr_registration *,\n"
+			bufi += "			int *, unsigned char *);\n"
+
+		if re.search('get_pr_transport_id_len\)\(', fo):
+			buf += "u32 " + fabric_mod_name + "_get_pr_transport_id_len(\n"
+			buf += "	struct se_portal_group *se_tpg,\n"
+			buf += "	struct se_node_acl *se_nacl,\n"
+			buf += "	struct t10_pr_registration *pr_reg,\n"
+			buf += "	int *format_code)\n"
+			buf += "{\n"
+			buf += "	struct " + fabric_mod_name + "_tpg *tpg = container_of(se_tpg,\n"
+			buf += "				struct " + fabric_mod_name + "_tpg, se_tpg);\n"
+			buf += "	struct " + fabric_mod_name + "_" + fabric_mod_port + " *" + fabric_mod_port + " = tpg->" + fabric_mod_port + ";\n"
+			buf += "	int ret = 0;\n\n"
+			buf += "	switch (" + fabric_mod_port + "->" + fabric_mod_port + "_proto_id) {\n"
+			if proto_ident == "FC":
+				buf += "	case SCSI_PROTOCOL_FCP:\n"
+				buf += "	default:\n"
+				buf += "		ret = fc_get_pr_transport_id_len(se_tpg, se_nacl, pr_reg,\n"
+				buf += "					format_code);\n"
+				buf += "		break;\n"
+			elif proto_ident == "SAS":
+				buf += "	case SCSI_PROTOCOL_SAS:\n"
+				buf += "	default:\n"
+				buf += "		ret = sas_get_pr_transport_id_len(se_tpg, se_nacl, pr_reg,\n"
+				buf += "					format_code);\n"
+				buf += "		break;\n"
+			elif proto_ident == "iSCSI":
+				buf += "	case SCSI_PROTOCOL_ISCSI:\n"
+				buf += "	default:\n"
+				buf += "		ret = iscsi_get_pr_transport_id_len(se_tpg, se_nacl, pr_reg,\n"
+				buf += "					format_code);\n"
+				buf += "		break;\n"
+
+
+			buf += "	}\n\n"
+			buf += "	return ret;\n"
+			buf += "}\n\n"
+			bufi += "u32 " + fabric_mod_name + "_get_pr_transport_id_len(struct se_portal_group *,\n"
+			bufi += "			struct se_node_acl *, struct t10_pr_registration *,\n"
+			bufi += "			int *);\n"
+
+		if re.search('parse_pr_out_transport_id\)\(', fo):
+			buf += "char *" + fabric_mod_name + "_parse_pr_out_transport_id(\n"
+			buf += "	struct se_portal_group *se_tpg,\n"
+			buf += "	const char *buf,\n"
+			buf += "	u32 *out_tid_len,\n"
+			buf += "	char **port_nexus_ptr)\n"
+			buf += "{\n"
+			buf += "	struct " + fabric_mod_name + "_tpg *tpg = container_of(se_tpg,\n"
+			buf += "				struct " + fabric_mod_name + "_tpg, se_tpg);\n"
+			buf += "	struct " + fabric_mod_name + "_" + fabric_mod_port + " *" + fabric_mod_port + " = tpg->" + fabric_mod_port + ";\n"
+			buf += "	char *tid = NULL;\n\n"
+			buf += "	switch (" + fabric_mod_port + "->" + fabric_mod_port + "_proto_id) {\n"
+			if proto_ident == "FC":
+				buf += "	case SCSI_PROTOCOL_FCP:\n"
+				buf += "	default:\n"
+				buf += "		tid = fc_parse_pr_out_transport_id(se_tpg, buf, out_tid_len,\n"
+				buf += "					port_nexus_ptr);\n"
+			elif proto_ident == "SAS":
+				buf += "	case SCSI_PROTOCOL_SAS:\n"
+				buf += "	default:\n"
+				buf += "		tid = sas_parse_pr_out_transport_id(se_tpg, buf, out_tid_len,\n"
+				buf += "					port_nexus_ptr);\n"
+			elif proto_ident == "iSCSI":
+				buf += "	case SCSI_PROTOCOL_ISCSI:\n"
+				buf += "	default:\n"
+				buf += "		tid = iscsi_parse_pr_out_transport_id(se_tpg, buf, out_tid_len,\n"
+				buf += "					port_nexus_ptr);\n"
+
+			buf += "	}\n\n"
+			buf += "	return tid;\n"
+			buf += "}\n\n"
+			bufi += "char *" + fabric_mod_name + "_parse_pr_out_transport_id(struct se_portal_group *,\n"
+			bufi +=	"			const char *, u32 *, char **);\n"
+
+		if re.search('alloc_fabric_acl\)\(', fo):
+			buf += "struct se_node_acl *" + fabric_mod_name + "_alloc_fabric_acl(struct se_portal_group *se_tpg)\n"
+			buf += "{\n"
+			buf += "	struct " + fabric_mod_name + "_nacl *nacl;\n\n"
+			buf += "	nacl = kzalloc(sizeof(struct " + fabric_mod_name + "_nacl), GFP_KERNEL);\n"
+			buf += "	if (!(nacl)) {\n"
+			buf += "		printk(KERN_ERR \"Unable to alocate struct " + fabric_mod_name + "_nacl\\n\");\n"
+			buf += "		return NULL;\n"
+			buf += "	}\n\n"
+			buf += "	return &nacl->se_node_acl;\n"
+			buf += "}\n\n"
+			bufi += "struct se_node_acl *" + fabric_mod_name + "_alloc_fabric_acl(struct se_portal_group *);\n"
+
+		if re.search('release_fabric_acl\)\(', fo):
+			buf += "void " + fabric_mod_name + "_release_fabric_acl(\n"
+			buf += "	struct se_portal_group *se_tpg,\n"
+			buf += "	struct se_node_acl *se_nacl)\n"
+			buf += "{\n"
+			buf += "	struct " + fabric_mod_name + "_nacl *nacl = container_of(se_nacl,\n"
+			buf += "			struct " + fabric_mod_name + "_nacl, se_node_acl);\n"
+			buf += "	kfree(nacl);\n"
+			buf += "}\n\n"
+			bufi += "void " + fabric_mod_name + "_release_fabric_acl(struct se_portal_group *,\n"
+			bufi +=	"			struct se_node_acl *);\n"
+
+		if re.search('tpg_get_inst_index\)\(', fo):
+			buf += "u32 " + fabric_mod_name + "_tpg_get_inst_index(struct se_portal_group *se_tpg)\n"
+			buf += "{\n"
+			buf += "	return 1;\n"
+			buf += "}\n\n"
+			bufi += "u32 " + fabric_mod_name + "_tpg_get_inst_index(struct se_portal_group *);\n"
+
+		if re.search('release_cmd_to_pool', fo):
+			buf += "void " + fabric_mod_name + "_release_cmd(struct se_cmd *se_cmd)\n"
+			buf += "{\n"
+			buf += "	return;\n"
+			buf += "}\n\n"
+			bufi += "void " + fabric_mod_name + "_release_cmd(struct se_cmd *);\n"
+
+		if re.search('shutdown_session\)\(', fo):
+			buf += "int " + fabric_mod_name + "_shutdown_session(struct se_session *se_sess)\n"
+			buf += "{\n"
+			buf += "	return 0;\n"
+			buf += "}\n\n"
+			bufi += "int " + fabric_mod_name + "_shutdown_session(struct se_session *);\n"
+
+		if re.search('close_session\)\(', fo):
+			buf += "void " + fabric_mod_name + "_close_session(struct se_session *se_sess)\n"
+			buf += "{\n"
+			buf += "	return;\n"
+			buf += "}\n\n"
+			bufi += "void " + fabric_mod_name + "_close_session(struct se_session *);\n"
+
+		if re.search('stop_session\)\(', fo):
+			buf += "void " + fabric_mod_name + "_stop_session(struct se_session *se_sess, int sess_sleep , int conn_sleep)\n"
+			buf += "{\n"
+			buf += "	return;\n"
+			buf += "}\n\n"
+			bufi += "void " + fabric_mod_name + "_stop_session(struct se_session *, int, int);\n"
+
+		if re.search('fall_back_to_erl0\)\(', fo):
+			buf += "void " + fabric_mod_name + "_reset_nexus(struct se_session *se_sess)\n"
+			buf += "{\n"
+			buf += "	return;\n"
+			buf += "}\n\n"
+			bufi += "void " + fabric_mod_name + "_reset_nexus(struct se_session *);\n"
+
+		if re.search('sess_logged_in\)\(', fo):
+			buf += "int " + fabric_mod_name + "_sess_logged_in(struct se_session *se_sess)\n"
+			buf += "{\n"
+			buf += "	return 0;\n"
+			buf += "}\n\n"
+			bufi += "int " + fabric_mod_name + "_sess_logged_in(struct se_session *);\n"
+
+		if re.search('sess_get_index\)\(', fo):
+			buf += "u32 " + fabric_mod_name + "_sess_get_index(struct se_session *se_sess)\n"
+			buf += "{\n"
+			buf += "	return 0;\n"
+			buf += "}\n\n"
+			bufi += "u32 " + fabric_mod_name + "_sess_get_index(struct se_session *);\n"
+
+		if re.search('write_pending\)\(', fo):
+			buf += "int " + fabric_mod_name + "_write_pending(struct se_cmd *se_cmd)\n"
+			buf += "{\n"
+			buf += "	return 0;\n"
+			buf += "}\n\n"
+			bufi += "int " + fabric_mod_name + "_write_pending(struct se_cmd *);\n"
+
+		if re.search('write_pending_status\)\(', fo):
+			buf += "int " + fabric_mod_name + "_write_pending_status(struct se_cmd *se_cmd)\n"
+			buf += "{\n"
+			buf += "	return 0;\n"
+			buf += "}\n\n"
+			bufi += "int " + fabric_mod_name + "_write_pending_status(struct se_cmd *);\n"
+
+		if re.search('set_default_node_attributes\)\(', fo):
+			buf += "void " + fabric_mod_name + "_set_default_node_attrs(struct se_node_acl *nacl)\n"
+			buf += "{\n"
+			buf += "	return;\n"
+			buf += "}\n\n"
+			bufi += "void " + fabric_mod_name + "_set_default_node_attrs(struct se_node_acl *);\n"
+
+		if re.search('get_task_tag\)\(', fo):
+			buf += "u32 " + fabric_mod_name + "_get_task_tag(struct se_cmd *se_cmd)\n"
+			buf += "{\n"
+			buf += "	return 0;\n"
+			buf += "}\n\n"
+			bufi += "u32 " + fabric_mod_name + "_get_task_tag(struct se_cmd *);\n"
+
+		if re.search('get_cmd_state\)\(', fo):
+			buf += "int " + fabric_mod_name + "_get_cmd_state(struct se_cmd *se_cmd)\n"
+			buf += "{\n"
+			buf += "	return 0;\n"
+			buf += "}\n\n"
+			bufi += "int " + fabric_mod_name + "_get_cmd_state(struct se_cmd *);\n"
+
+		if re.search('new_cmd_failure\)\(', fo):
+			buf += "void " + fabric_mod_name + "_new_cmd_failure(struct se_cmd *se_cmd)\n"
+			buf += "{\n"
+			buf += "	return;\n"
+			buf += "}\n\n"
+			bufi += "void " + fabric_mod_name + "_new_cmd_failure(struct se_cmd *);\n"
+
+		if re.search('queue_data_in\)\(', fo):
+			buf += "int " + fabric_mod_name + "_queue_data_in(struct se_cmd *se_cmd)\n"
+			buf += "{\n"
+			buf += "	return 0;\n"
+			buf += "}\n\n"
+			bufi += "int " + fabric_mod_name + "_queue_data_in(struct se_cmd *);\n"
+
+		if re.search('queue_status\)\(', fo):
+			buf += "int " + fabric_mod_name + "_queue_status(struct se_cmd *se_cmd)\n"
+			buf += "{\n"
+			buf += "	return 0;\n"
+			buf += "}\n\n"
+			bufi += "int " + fabric_mod_name + "_queue_status(struct se_cmd *);\n"
+
+		if re.search('queue_tm_rsp\)\(', fo):
+			buf += "int " + fabric_mod_name + "_queue_tm_rsp(struct se_cmd *se_cmd)\n"
+			buf += "{\n"
+			buf += "	return 0;\n"
+			buf += "}\n\n"
+			bufi += "int " + fabric_mod_name + "_queue_tm_rsp(struct se_cmd *);\n"
+
+		if re.search('get_fabric_sense_len\)\(', fo):
+			buf += "u16 " + fabric_mod_name + "_get_fabric_sense_len(void)\n"
+			buf += "{\n"
+			buf += "	return 0;\n"
+			buf += "}\n\n"
+			bufi += "u16 " + fabric_mod_name + "_get_fabric_sense_len(void);\n"
+
+		if re.search('set_fabric_sense_len\)\(', fo):
+			buf += "u16 " + fabric_mod_name + "_set_fabric_sense_len(struct se_cmd *se_cmd, u32 sense_length)\n"
+			buf += "{\n"
+			buf += "	return 0;\n"
+			buf += "}\n\n"
+			bufi += "u16 " + fabric_mod_name + "_set_fabric_sense_len(struct se_cmd *, u32);\n"
+
+		if re.search('is_state_remove\)\(', fo):
+			buf += "int " + fabric_mod_name + "_is_state_remove(struct se_cmd *se_cmd)\n"
+			buf += "{\n"
+			buf += "	return 0;\n"
+			buf += "}\n\n"
+			bufi += "int " + fabric_mod_name + "_is_state_remove(struct se_cmd *);\n"
+
+		if re.search('pack_lun\)\(', fo):
+			buf += "u64 " + fabric_mod_name + "_pack_lun(unsigned int lun)\n"
+			buf += "{\n"
+			buf += "	WARN_ON(lun >= 256);\n"
+			buf += "	/* Caller wants this byte-swapped */\n"
+			buf += "	return cpu_to_le64((lun & 0xff) << 8);\n"
+			buf += "}\n\n"
+			bufi += "u64 " + fabric_mod_name + "_pack_lun(unsigned int);\n"
+
+
+	ret = p.write(buf)
+	if ret:
+		tcm_mod_err("Unable to write f: " + f)
+
+	p.close()
+
+	ret = pi.write(bufi)
+	if ret:
+		tcm_mod_err("Unable to write fi: " + fi)
+
+	pi.close()
+	return
+
+def tcm_mod_build_kbuild(fabric_mod_dir_var, fabric_mod_name):
+
+	buf = ""
+	f = fabric_mod_dir_var + "/Kbuild"
+	print "Writing file: " + f
+
+	p = open(f, 'w')
+	if not p:
+		tcm_mod_err("Unable to open file: " + f)
+
+	buf = "EXTRA_CFLAGS += -I$(srctree)/drivers/target/ -I$(srctree)/include/ -I$(srctree)/drivers/scsi/ -I$(srctree)/include/scsi/ -I$(srctree)/drivers/target/" + fabric_mod_name + "\n\n"
+	buf += fabric_mod_name + "-objs			:= " + fabric_mod_name + "_fabric.o \\\n"
+	buf += "					   " + fabric_mod_name + "_configfs.o\n"
+	buf += "obj-$(CONFIG_" + fabric_mod_name.upper() + ")		+= " + fabric_mod_name + ".o\n"
+
+	ret = p.write(buf)
+	if ret:
+		tcm_mod_err("Unable to write f: " + f)
+
+	p.close()
+	return
+
+def tcm_mod_build_kconfig(fabric_mod_dir_var, fabric_mod_name):
+
+	buf = ""
+	f = fabric_mod_dir_var + "/Kconfig"
+	print "Writing file: " + f
+
+	p = open(f, 'w')
+	if not p:
+		tcm_mod_err("Unable to open file: " + f)
+
+	buf = "config " + fabric_mod_name.upper() + "\n"
+	buf += "	tristate \"" + fabric_mod_name.upper() + " fabric module\"\n"
+	buf += "	depends on TARGET_CORE && CONFIGFS_FS\n"
+	buf += "	default n\n"
+	buf += "	---help---\n"
+	buf += "	Say Y here to enable the " + fabric_mod_name.upper() + " fabric module\n"
+
+	ret = p.write(buf)
+	if ret:
+		tcm_mod_err("Unable to write f: " + f)
+
+	p.close()
+	return
+
+def tcm_mod_add_kbuild(tcm_dir, fabric_mod_name):
+	buf = "obj-$(CONFIG_" + fabric_mod_name.upper() + ")	+= " + fabric_mod_name.lower() + "/\n"
+	kbuild = tcm_dir + "/drivers/target/Kbuild"
+
+	f = open(kbuild, 'a')
+	f.write(buf)
+	f.close()
+	return
+
+def tcm_mod_add_kconfig(tcm_dir, fabric_mod_name):
+	buf = "source \"drivers/target/" + fabric_mod_name.lower() + "/Kconfig\"\n"
+	kconfig = tcm_dir + "/drivers/target/Kconfig"
+
+	f = open(kconfig, 'a')
+	f.write(buf)
+	f.close()
+	return
+
+def main(modname, proto_ident):
+#	proto_ident = "FC"
+#	proto_ident = "SAS"
+#	proto_ident = "iSCSI"
+
+	tcm_dir = os.getcwd();
+	tcm_dir += "/../../"
+	print "tcm_dir: " + tcm_dir
+	fabric_mod_name = modname
+	fabric_mod_dir = tcm_dir + "drivers/target/" + fabric_mod_name
+	print "Set fabric_mod_name: " + fabric_mod_name
+	print "Set fabric_mod_dir: " + fabric_mod_dir
+	print "Using proto_ident: " + proto_ident
+
+	if proto_ident != "FC" and proto_ident != "SAS" and proto_ident != "iSCSI":
+		print "Unsupported proto_ident: " + proto_ident
+		sys.exit(1)
+
+	ret = tcm_mod_create_module_subdir(fabric_mod_dir)
+	if ret:
+		print "tcm_mod_create_module_subdir() failed because module already exists!"
+		sys.exit(1)
+
+	tcm_mod_build_base_includes(proto_ident, fabric_mod_dir, fabric_mod_name)
+	tcm_mod_scan_fabric_ops(tcm_dir)
+	tcm_mod_dump_fabric_ops(proto_ident, fabric_mod_dir, fabric_mod_name)
+	tcm_mod_build_configfs(proto_ident, fabric_mod_dir, fabric_mod_name)
+	tcm_mod_build_kbuild(fabric_mod_dir, fabric_mod_name)
+	tcm_mod_build_kconfig(fabric_mod_dir, fabric_mod_name)
+
+	input = raw_input("Would you like to add " + fabric_mod_name + "to drivers/target/Kbuild..? [yes,no]: ")
+	if input == "yes" or input == "y":
+		tcm_mod_add_kbuild(tcm_dir, fabric_mod_name)
+
+	input = raw_input("Would you like to add " + fabric_mod_name + "to drivers/target/Kconfig..? [yes,no]: ")
+	if input == "yes" or input == "y":
+		tcm_mod_add_kconfig(tcm_dir, fabric_mod_name)
+
+	return
+
+parser = optparse.OptionParser()
+parser.add_option('-m', '--modulename', help='Module name', dest='modname',
+		action='store', nargs=1, type='string')
+parser.add_option('-p', '--protoident', help='Protocol Ident', dest='protoident',
+		action='store', nargs=1, type='string')
+
+(opts, args) = parser.parse_args()
+
+mandatories = ['modname', 'protoident']
+for m in mandatories:
+	if not opts.__dict__[m]:
+		print "mandatory option is missing\n"
+		parser.print_help()
+		exit(-1)
+
+if __name__ == "__main__":
+
+	main(str(opts.modname), opts.protoident)
diff -druNp linux-libre-2.6.37-gnu1/Documentation/target/tcm_mod_builder.txt linux-libre-2.6.38-gnu1/Documentation/target/tcm_mod_builder.txt
--- linux-libre-2.6.37-gnu1/Documentation/target/tcm_mod_builder.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/target/tcm_mod_builder.txt	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,145 @@
+>>>>>>>>>> The TCM v4 fabric module script generator <<<<<<<<<<
+
+Greetings all,
+
+This document is intended to be a mini-HOWTO for using the tcm_mod_builder.py
+script to generate a brand new functional TCM v4 fabric .ko module of your very own,
+that once built can be immediately be loaded to start access the new TCM/ConfigFS
+fabric skeleton, by simply using:
+
+	modprobe $TCM_NEW_MOD
+	mkdir -p /sys/kernel/config/target/$TCM_NEW_MOD
+
+This script will create a new drivers/target/$TCM_NEW_MOD/, and will do the following
+
+	*) Generate new API callers for drivers/target/target_core_fabric_configs.c logic
+	   ->make_nodeacl(), ->drop_nodeacl(), ->make_tpg(), ->drop_tpg()
+	   ->make_wwn(), ->drop_wwn().  These are created into $TCM_NEW_MOD/$TCM_NEW_MOD_configfs.c
+	*) Generate basic infrastructure for loading/unloading LKMs and TCM/ConfigFS fabric module
+	   using a skeleton struct target_core_fabric_ops API template.
+	*) Based on user defined T10 Proto_Ident for the new fabric module being built,
+	   the TransportID / Initiator and Target WWPN related handlers for
+	   SPC-3 persistent reservation are automatically generated in $TCM_NEW_MOD/$TCM_NEW_MOD_fabric.c
+	   using drivers/target/target_core_fabric_lib.c logic.
+	*) NOP API calls for all other Data I/O path and fabric dependent attribute logic
+	   in $TCM_NEW_MOD/$TCM_NEW_MOD_fabric.c
+
+tcm_mod_builder.py depends upon the mandatory '-p $PROTO_IDENT' and '-m
+$FABRIC_MOD_name' parameters, and actually running the script looks like:
+
+target:/mnt/sdb/lio-core-2.6.git/Documentation/target# python tcm_mod_builder.py -p iSCSI -m tcm_nab5000
+tcm_dir: /mnt/sdb/lio-core-2.6.git/Documentation/target/../../
+Set fabric_mod_name: tcm_nab5000
+Set fabric_mod_dir:
+/mnt/sdb/lio-core-2.6.git/Documentation/target/../../drivers/target/tcm_nab5000
+Using proto_ident: iSCSI
+Creating fabric_mod_dir:
+/mnt/sdb/lio-core-2.6.git/Documentation/target/../../drivers/target/tcm_nab5000
+Writing file:
+/mnt/sdb/lio-core-2.6.git/Documentation/target/../../drivers/target/tcm_nab5000/tcm_nab5000_base.h
+Using tcm_mod_scan_fabric_ops:
+/mnt/sdb/lio-core-2.6.git/Documentation/target/../../include/target/target_core_fabric_ops.h
+Writing file:
+/mnt/sdb/lio-core-2.6.git/Documentation/target/../../drivers/target/tcm_nab5000/tcm_nab5000_fabric.c
+Writing file:
+/mnt/sdb/lio-core-2.6.git/Documentation/target/../../drivers/target/tcm_nab5000/tcm_nab5000_fabric.h
+Writing file:
+/mnt/sdb/lio-core-2.6.git/Documentation/target/../../drivers/target/tcm_nab5000/tcm_nab5000_configfs.c
+Writing file:
+/mnt/sdb/lio-core-2.6.git/Documentation/target/../../drivers/target/tcm_nab5000/Kbuild
+Writing file:
+/mnt/sdb/lio-core-2.6.git/Documentation/target/../../drivers/target/tcm_nab5000/Kconfig
+Would you like to add tcm_nab5000to drivers/target/Kbuild..? [yes,no]: yes
+Would you like to add tcm_nab5000to drivers/target/Kconfig..? [yes,no]: yes
+
+At the end of tcm_mod_builder.py. the script will ask to add the following
+line to drivers/target/Kbuild:
+
+	obj-$(CONFIG_TCM_NAB5000)       += tcm_nab5000/
+
+and the same for drivers/target/Kconfig:
+
+	source "drivers/target/tcm_nab5000/Kconfig"
+
+*) Run 'make menuconfig' and select the new CONFIG_TCM_NAB5000 item:
+
+	<M>   TCM_NAB5000 fabric module
+
+*) Build using 'make modules', once completed you will have:
+
+target:/mnt/sdb/lio-core-2.6.git# ls -la drivers/target/tcm_nab5000/
+total 1348
+drwxr-xr-x 2 root root   4096 2010-10-05 03:23 .
+drwxr-xr-x 9 root root   4096 2010-10-05 03:22 ..
+-rw-r--r-- 1 root root    282 2010-10-05 03:22 Kbuild
+-rw-r--r-- 1 root root    171 2010-10-05 03:22 Kconfig
+-rw-r--r-- 1 root root     49 2010-10-05 03:23 modules.order
+-rw-r--r-- 1 root root    738 2010-10-05 03:22 tcm_nab5000_base.h
+-rw-r--r-- 1 root root   9096 2010-10-05 03:22 tcm_nab5000_configfs.c
+-rw-r--r-- 1 root root 191200 2010-10-05 03:23 tcm_nab5000_configfs.o
+-rw-r--r-- 1 root root  40504 2010-10-05 03:23 .tcm_nab5000_configfs.o.cmd
+-rw-r--r-- 1 root root   5414 2010-10-05 03:22 tcm_nab5000_fabric.c
+-rw-r--r-- 1 root root   2016 2010-10-05 03:22 tcm_nab5000_fabric.h
+-rw-r--r-- 1 root root 190932 2010-10-05 03:23 tcm_nab5000_fabric.o
+-rw-r--r-- 1 root root  40713 2010-10-05 03:23 .tcm_nab5000_fabric.o.cmd
+-rw-r--r-- 1 root root 401861 2010-10-05 03:23 tcm_nab5000.ko
+-rw-r--r-- 1 root root    265 2010-10-05 03:23 .tcm_nab5000.ko.cmd
+-rw-r--r-- 1 root root    459 2010-10-05 03:23 tcm_nab5000.mod.c
+-rw-r--r-- 1 root root  23896 2010-10-05 03:23 tcm_nab5000.mod.o
+-rw-r--r-- 1 root root  22655 2010-10-05 03:23 .tcm_nab5000.mod.o.cmd
+-rw-r--r-- 1 root root 379022 2010-10-05 03:23 tcm_nab5000.o
+-rw-r--r-- 1 root root    211 2010-10-05 03:23 .tcm_nab5000.o.cmd
+
+*) Load the new module, create a lun_0 configfs group, and add new TCM Core
+   IBLOCK backstore symlink to port:
+
+target:/mnt/sdb/lio-core-2.6.git# insmod drivers/target/tcm_nab5000.ko
+target:/mnt/sdb/lio-core-2.6.git# mkdir -p /sys/kernel/config/target/nab5000/iqn.foo/tpgt_1/lun/lun_0
+target:/mnt/sdb/lio-core-2.6.git# cd /sys/kernel/config/target/nab5000/iqn.foo/tpgt_1/lun/lun_0/
+target:/sys/kernel/config/target/nab5000/iqn.foo/tpgt_1/lun/lun_0# ln -s /sys/kernel/config/target/core/iblock_0/lvm_test0 nab5000_port
+
+target:/sys/kernel/config/target/nab5000/iqn.foo/tpgt_1/lun/lun_0# cd -
+target:/mnt/sdb/lio-core-2.6.git# tree /sys/kernel/config/target/nab5000/
+/sys/kernel/config/target/nab5000/
+|-- discovery_auth
+|-- iqn.foo
+|   `-- tpgt_1
+|       |-- acls
+|       |-- attrib
+|       |-- lun
+|       |   `-- lun_0
+|       |       |-- alua_tg_pt_gp
+|       |       |-- alua_tg_pt_offline
+|       |       |-- alua_tg_pt_status
+|       |       |-- alua_tg_pt_write_md
+|	|	`-- nab5000_port -> ../../../../../../target/core/iblock_0/lvm_test0
+|       |-- np
+|       `-- param
+`-- version
+
+target:/mnt/sdb/lio-core-2.6.git# lsmod
+Module                  Size  Used by
+tcm_nab5000             3935  4
+iscsi_target_mod      193211  0
+target_core_stgt        8090  0
+target_core_pscsi      11122  1
+target_core_file        9172  2
+target_core_iblock      9280  1
+target_core_mod       228575  31
+tcm_nab5000,iscsi_target_mod,target_core_stgt,target_core_pscsi,target_core_file,target_core_iblock
+libfc                  73681  0
+scsi_debug             56265  0
+scsi_tgt                8666  1 target_core_stgt
+configfs               20644  2 target_core_mod
+
+----------------------------------------------------------------------
+
+Future TODO items:
+
+	*) Add more T10 proto_idents
+	*) Make tcm_mod_dump_fabric_ops() smarter and generate function pointer
+	   defs directly from include/target/target_core_fabric_ops.h:struct target_core_fabric_ops
+	   structure members.
+
+October 5th, 2010
+Nicholas A. Bellinger <nab@linux-iscsi.org>
diff -druNp linux-libre-2.6.37-gnu1/Documentation/thermal/sysfs-api.txt linux-libre-2.6.38-gnu1/Documentation/thermal/sysfs-api.txt
--- linux-libre-2.6.37-gnu1/Documentation/thermal/sysfs-api.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/thermal/sysfs-api.txt	2011-03-14 21:20:32.000000000 -0400
@@ -278,3 +278,15 @@ method, the sys I/F structure will be bu
     |---name:			acpitz
     |---temp1_input:		37000
     |---temp1_crit:		100000
+
+4. Event Notification
+
+The framework includes a simple notification mechanism, in the form of a
+netlink event. Netlink socket initialization is done during the _init_
+of the framework. Drivers which intend to use the notification mechanism
+just need to call generate_netlink_event() with two arguments viz
+(originator, event). Typically the originator will be an integer assigned
+to a thermal_zone_device when it registers itself with the framework. The
+event will be one of:{THERMAL_AUX0, THERMAL_AUX1, THERMAL_CRITICAL,
+THERMAL_DEV_FAULT}. Notification can be sent when the current temperature
+crosses any of the configured thresholds.
diff -druNp linux-libre-2.6.37-gnu1/Documentation/timers/timer_stats.txt linux-libre-2.6.38-gnu1/Documentation/timers/timer_stats.txt
--- linux-libre-2.6.37-gnu1/Documentation/timers/timer_stats.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/timers/timer_stats.txt	2011-03-14 21:20:32.000000000 -0400
@@ -19,7 +19,7 @@ Linux system over a sample period:
 
 - the pid of the task(process) which initialized the timer
 - the name of the process which initialized the timer
-- the function where the timer was intialized
+- the function where the timer was initialized
 - the callback function which is associated to the timer
 - the number of events (callbacks)
 
diff -druNp linux-libre-2.6.37-gnu1/Documentation/trace/events-power.txt linux-libre-2.6.38-gnu1/Documentation/trace/events-power.txt
--- linux-libre-2.6.37-gnu1/Documentation/trace/events-power.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/trace/events-power.txt	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,90 @@
+
+			Subsystem Trace Points: power
+
+The power tracing system captures events related to power transitions
+within the kernel. Broadly speaking there are three major subheadings:
+
+  o Power state switch which reports events related to suspend (S-states),
+     cpuidle (C-states) and cpufreq (P-states)
+  o System clock related changes
+  o Power domains related changes and transitions
+
+This document describes what each of the tracepoints is and why they
+might be useful.
+
+Cf. include/trace/events/power.h for the events definitions.
+
+1. Power state switch events
+============================
+
+1.1 New trace API
+-----------------
+
+A 'cpu' event class gathers the CPU-related events: cpuidle and
+cpufreq.
+
+cpu_idle		"state=%lu cpu_id=%lu"
+cpu_frequency		"state=%lu cpu_id=%lu"
+
+A suspend event is used to indicate the system going in and out of the
+suspend mode:
+
+machine_suspend		"state=%lu"
+
+
+Note: the value of '-1' or '4294967295' for state means an exit from the current state,
+i.e. trace_cpu_idle(4, smp_processor_id()) means that the system
+enters the idle state 4, while trace_cpu_idle(PWR_EVENT_EXIT, smp_processor_id())
+means that the system exits the previous idle state.
+
+The event which has 'state=4294967295' in the trace is very important to the user
+space tools which are using it to detect the end of the current state, and so to
+correctly draw the states diagrams and to calculate accurate statistics etc.
+
+1.2 DEPRECATED trace API
+------------------------
+
+A new Kconfig option CONFIG_EVENT_POWER_TRACING_DEPRECATED with the default value of
+'y' has been created. This allows the legacy trace power API to be used conjointly
+with the new trace API.
+The Kconfig option, the old trace API (in include/trace/events/power.h) and the
+old trace points will disappear in a future release (namely 2.6.41).
+
+power_start		"type=%lu state=%lu cpu_id=%lu"
+power_frequency		"type=%lu state=%lu cpu_id=%lu"
+power_end		"cpu_id=%lu"
+
+The 'type' parameter takes one of those macros:
+ . POWER_NONE	= 0,
+ . POWER_CSTATE	= 1,	/* C-State */
+ . POWER_PSTATE	= 2,	/* Fequency change or DVFS */
+
+The 'state' parameter is set depending on the type:
+ . Target C-state for type=POWER_CSTATE,
+ . Target frequency for type=POWER_PSTATE,
+
+power_end is used to indicate the exit of a state, corresponding to the latest
+power_start event.
+
+2. Clocks events
+================
+The clock events are used for clock enable/disable and for
+clock rate change.
+
+clock_enable		"%s state=%lu cpu_id=%lu"
+clock_disable		"%s state=%lu cpu_id=%lu"
+clock_set_rate		"%s state=%lu cpu_id=%lu"
+
+The first parameter gives the clock name (e.g. "gpio1_iclk").
+The second parameter is '1' for enable, '0' for disable, the target
+clock rate for set_rate.
+
+3. Power domains events
+=======================
+The power domain events are used for power domains transitions
+
+power_domain_target	"%s state=%lu cpu_id=%lu"
+
+The first parameter gives the power domain name (e.g. "mpu_pwrdm").
+The second parameter is the power domain target state.
+
diff -druNp linux-libre-2.6.37-gnu1/Documentation/trace/events.txt linux-libre-2.6.38-gnu1/Documentation/trace/events.txt
--- linux-libre-2.6.37-gnu1/Documentation/trace/events.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/trace/events.txt	2011-03-14 21:20:32.000000000 -0400
@@ -125,7 +125,7 @@ is the size of the data item, in bytes.
 For example, here's the information displayed for the 'sched_wakeup'
 event:
 
-# cat /debug/tracing/events/sched/sched_wakeup/format
+# cat /sys/kernel/debug/tracing/events/sched/sched_wakeup/format
 
 name: sched_wakeup
 ID: 60
@@ -201,19 +201,19 @@ to the 'filter' file for the given event
 
 For example:
 
-# cd /debug/tracing/events/sched/sched_wakeup
+# cd /sys/kernel/debug/tracing/events/sched/sched_wakeup
 # echo "common_preempt_count > 4" > filter
 
 A slightly more involved example:
 
-# cd /debug/tracing/events/sched/sched_signal_send
+# cd /sys/kernel/debug/tracing/events/signal/signal_generate
 # echo "((sig >= 10 && sig < 15) || sig == 17) && comm != bash" > filter
 
 If there is an error in the expression, you'll get an 'Invalid
 argument' error when setting it, and the erroneous string along with
 an error message can be seen by looking at the filter e.g.:
 
-# cd /debug/tracing/events/sched/sched_signal_send
+# cd /sys/kernel/debug/tracing/events/signal/signal_generate
 # echo "((sig >= 10 && sig < 15) || dsig == 17) && comm != bash" > filter
 -bash: echo: write error: Invalid argument
 # cat filter
diff -druNp linux-libre-2.6.37-gnu1/Documentation/usb/power-management.txt linux-libre-2.6.38-gnu1/Documentation/usb/power-management.txt
--- linux-libre-2.6.37-gnu1/Documentation/usb/power-management.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/usb/power-management.txt	2011-03-14 21:20:32.000000000 -0400
@@ -2,7 +2,7 @@
 
 		 Alan Stern <stern@rowland.harvard.edu>
 
-			    December 11, 2009
+			    October 28, 2010
 
 
 
@@ -107,9 +107,14 @@ allowed to issue dynamic suspends.
 The user interface for controlling dynamic PM 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 are: wakeup, control, and autosuspend.
-(There may also be a file named "level"; this file was deprecated
-as of the 2.6.35 kernel and replaced by the "control" file.)
+relevant attribute files are: wakeup, control, and
+autosuspend_delay_ms.  (There may also be a file named "level"; this
+file was deprecated as of the 2.6.35 kernel and replaced by the
+"control" file.  In 2.6.38 the "autosuspend" file will be deprecated
+and replaced by the "autosuspend_delay_ms" file.  The only difference
+is that the newer file expresses the delay in milliseconds whereas the
+older file uses seconds.  Confusingly, both files are present in 2.6.37
+but only "autosuspend" works.)
 
 	power/wakeup
 
@@ -140,33 +145,36 @@ as of the 2.6.35 kernel and replaced by
 		suspended and autoresume was not allowed.  This
 		setting is no longer supported.)
 
-	power/autosuspend
+	power/autosuspend_delay_ms
 
 		This file contains an integer value, which is the
-		number of seconds the device should remain idle before
-		the kernel will autosuspend it (the idle-delay time).
-		The default is 2.  0 means to autosuspend as soon as
-		the device becomes idle, and negative values mean
-		never to autosuspend.  You can write a number to the
-		file to change the autosuspend idle-delay time.
+		number of milliseconds the device should remain idle
+		before the kernel will autosuspend it (the idle-delay
+		time).  The default is 2000.  0 means to autosuspend
+		as soon as the device becomes idle, and negative
+		values mean never to autosuspend.  You can write a
+		number to the file to change the autosuspend
+		idle-delay time.
 
-Writing "-1" to power/autosuspend and writing "on" to power/control do
-essentially the same thing -- they both prevent the device from being
-autosuspended.  Yes, this is a redundancy in the API.
+Writing "-1" to power/autosuspend_delay_ms and writing "on" to
+power/control do essentially the same thing -- they both prevent the
+device from being autosuspended.  Yes, this is a redundancy in the
+API.
 
 (In 2.6.21 writing "0" to power/autosuspend would prevent the device
 from being autosuspended; the behavior was changed in 2.6.22.  The
 power/autosuspend attribute did not exist prior to 2.6.21, and the
 power/level attribute did not exist prior to 2.6.22.  power/control
-was added in 2.6.34.)
+was added in 2.6.34, and power/autosuspend_delay_ms was added in
+2.6.37 but did not become functional until 2.6.38.)
 
 
 	Changing the default idle-delay time
 	------------------------------------
 
-The default autosuspend idle-delay time is controlled by a module
-parameter in usbcore.  You can specify the value when usbcore is
-loaded.  For example, to set it to 5 seconds instead of 2 you would
+The default autosuspend idle-delay time (in seconds) is controlled by
+a module parameter in usbcore.  You can specify the value when usbcore
+is loaded.  For example, to set it to 5 seconds instead of 2 you would
 do:
 
 	modprobe usbcore autosuspend=5
@@ -234,25 +242,23 @@ every device.
 
 If a driver knows that its device has proper suspend/resume support,
 it can enable autosuspend all by itself.  For example, the video
-driver for a laptop's webcam might do this, since these devices are
-rarely used and so should normally be autosuspended.
+driver for a laptop's webcam might do this (in recent kernels they
+do), since these devices are rarely used and so should normally be
+autosuspended.
 
 Sometimes it turns out that even when a device does work okay with
-autosuspend there are still problems.  For example, there are
-experimental patches adding autosuspend support to the usbhid driver,
-which manages keyboards and mice, among other things.  Tests with a
-number of keyboards showed that typing on a suspended keyboard, while
-causing the keyboard to do a remote wakeup all right, would
-nonetheless frequently result in lost keystrokes.  Tests with mice
-showed that some of them would issue a remote-wakeup request in
-response to button presses but not to motion, and some in response to
-neither.
+autosuspend there are still problems.  For example, the usbhid driver,
+which manages keyboards and mice, has autosuspend support.  Tests with
+a number of keyboards show that typing on a suspended keyboard, while
+causing the keyboard to do a remote wakeup all right, will nonetheless
+frequently result in lost keystrokes.  Tests with mice show that some
+of them will issue a remote-wakeup request in response to button
+presses but not to motion, and some in response to neither.
 
 The kernel will not prevent you from enabling autosuspend on devices
 that can't handle it.  It is even possible in theory to damage a
-device by suspending it at the wrong time -- for example, suspending a
-USB hard disk might cause it to spin down without parking the heads.
-(Highly unlikely, but possible.)  Take care.
+device by suspending it at the wrong time.  (Highly unlikely, but
+possible.)  Take care.
 
 
 	The driver interface for Power Management
@@ -336,10 +342,6 @@ autosuspend the interface's device.  Whe
 then the interface is considered to be idle, and the kernel may
 autosuspend the device.
 
-(There is a similar usage counter field in struct usb_device,
-associated with the device itself rather than any of its interfaces.
-This counter is used only by the USB core.)
-
 Drivers need not be concerned about balancing changes to the usage
 counter; the USB core will undo any remaining "get"s when a driver
 is unbound from its interface.  As a corollary, drivers must not call
@@ -409,11 +411,11 @@ during autosuspend.  For example, there'
 autosuspending a keyboard if the user can't cause the keyboard to do a
 remote wakeup by typing on it.  If the driver sets
 intf->needs_remote_wakeup to 1, the kernel won't autosuspend the
-device if remote wakeup isn't available or has been disabled through
-the power/wakeup attribute.  (If the device is already autosuspended,
-though, setting this flag won't cause the kernel to autoresume it.
-Normally a driver would set this flag in its probe method, at which
-time the device is guaranteed not to be autosuspended.)
+device if remote wakeup isn't available.  (If the device is already
+autosuspended, though, setting this flag won't cause the kernel to
+autoresume it.  Normally a driver would set this flag in its probe
+method, at which time the device is guaranteed not to be
+autosuspended.)
 
 If a driver does its I/O asynchronously in interrupt context, it
 should call usb_autopm_get_interface_async() before starting output and
@@ -422,20 +424,19 @@ it receives an input event, it should ca
 
 	usb_mark_last_busy(struct usb_device *udev);
 
-in the event handler.  This sets udev->last_busy to the current time.
-udev->last_busy is the field used for idle-delay calculations;
-updating it will cause any pending autosuspend to be moved back.  Most
-of the usb_autopm_* routines will also set the last_busy field to the
-current time.
+in the event handler.  This tells the PM core that the device was just
+busy and therefore the next autosuspend idle-delay expiration should
+be pushed back.  Many of the usb_autopm_* routines also make this call,
+so drivers need to worry only when interrupt-driven input arrives.
 
 Asynchronous operation is always subject to races.  For example, a
-driver may call one of the usb_autopm_*_interface_async() routines at
-a time when the core has just finished deciding the device has been
-idle for long enough but not yet gotten around to calling the driver's
-suspend method.  The suspend method must be responsible for
-synchronizing with the output request routine and the URB completion
-handler; it should cause autosuspends to fail with -EBUSY if the
-driver needs to use the device.
+driver may call the usb_autopm_get_interface_async() routine at a time
+when the core has just finished deciding the device has been idle for
+long enough but not yet gotten around to calling the driver's suspend
+method.  The suspend method must be responsible for synchronizing with
+the I/O request routine and the URB completion handler; it should
+cause autosuspends to fail with -EBUSY if the driver needs to use the
+device.
 
 External suspend calls should never be allowed to fail in this way,
 only autosuspend calls.  The driver can tell them apart by checking
@@ -472,7 +473,9 @@ Firstly, a device may already be autosus
 occurs.  Since system suspends are supposed to be as transparent as
 possible, the device should remain suspended following the system
 resume.  But this theory may not work out well in practice; over time
-the kernel's behavior in this regard has changed.
+the kernel's behavior in this regard has changed.  As of 2.6.37 the
+policy is to resume all devices during a system resume and let them
+handle their own runtime suspends afterward.
 
 Secondly, a dynamic power-management event may occur as a system
 suspend is underway.  The window for this is short, since system
diff -druNp linux-libre-2.6.37-gnu1/Documentation/video4linux/bttv/Cards linux-libre-2.6.38-gnu1/Documentation/video4linux/bttv/Cards
--- linux-libre-2.6.37-gnu1/Documentation/video4linux/bttv/Cards	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/video4linux/bttv/Cards	2011-03-14 21:20:32.000000000 -0400
@@ -464,10 +464,6 @@ Siemens
 -------
    Multimedia eXtension Board (MXB) (SAA7146, SAA7111)
 
-Stradis
--------
-   SDM275,SDM250,SDM026,SDM025 (SAA7146, IBMMPEG2): MPEG2 decoder only
-
 Powercolor
 ----------
    MTV878
diff -druNp linux-libre-2.6.37-gnu1/Documentation/video4linux/CARDLIST.em28xx linux-libre-2.6.38-gnu1/Documentation/video4linux/CARDLIST.em28xx
--- linux-libre-2.6.37-gnu1/Documentation/video4linux/CARDLIST.em28xx	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/video4linux/CARDLIST.em28xx	2011-03-14 21:20:32.000000000 -0400
@@ -1,5 +1,5 @@
   0 -> Unknown EM2800 video grabber             (em2800)        [eb1a:2800]
-  1 -> Unknown EM2750/28xx video grabber        (em2820/em2840) [eb1a:2710,eb1a:2820,eb1a:2821,eb1a:2860,eb1a:2861,eb1a:2862,eb1a:2863,eb1a:2870,eb1a:2881,eb1a:2883,eb1a:2868]
+  1 -> Unknown EM2750/28xx video grabber        (em2820/em2840) [eb1a:2710,eb1a:2820,eb1a:2821,eb1a:2860,eb1a:2861,eb1a:2862,eb1a:2863,eb1a:2870,eb1a:2881,eb1a:2883,eb1a:2868,eb1a:2875]
   2 -> Terratec Cinergy 250 USB                 (em2820/em2840) [0ccd:0036]
   3 -> Pinnacle PCTV USB 2                      (em2820/em2840) [2304:0208]
   4 -> Hauppauge WinTV USB 2                    (em2820/em2840) [2040:4200,2040:4201]
@@ -9,7 +9,7 @@
   8 -> Kworld USB2800                           (em2800)
   9 -> Pinnacle Dazzle DVC 90/100/101/107 / Kaiser Baas Video to DVD maker  (em2820/em2840) [1b80:e302,1b80:e304,2304:0207,2304:021a]
  10 -> Hauppauge WinTV HVR 900                  (em2880)        [2040:6500]
- 11 -> Terratec Hybrid XS                       (em2880)        [0ccd:0042]
+ 11 -> Terratec Hybrid XS                       (em2880)
  12 -> Kworld PVR TV 2800 RF                    (em2820/em2840)
  13 -> Terratec Prodigy XS                      (em2880)        [0ccd:0047]
  14 -> SIIG AVTuner-PVR / Pixelview Prolink PlayTV USB 2.0 (em2820/em2840)
@@ -53,7 +53,7 @@
  52 -> DNT DA2 Hybrid                           (em2881)
  53 -> Pinnacle Hybrid Pro                      (em2881)
  54 -> Kworld VS-DVB-T 323UR                    (em2882)        [eb1a:e323]
- 55 -> Terratec Hybrid XS (em2882)              (em2882)        [0ccd:005e]
+ 55 -> Terratec Cinnergy Hybrid T USB XS (em2882) (em2882)        [0ccd:005e,0ccd:0042]
  56 -> Pinnacle Hybrid Pro (2)                  (em2882)        [2304:0226]
  57 -> Kworld PlusTV HD Hybrid 330              (em2883)        [eb1a:a316]
  58 -> Compro VideoMate ForYou/Stereo           (em2820/em2840) [185b:2041]
diff -druNp linux-libre-2.6.37-gnu1/Documentation/video4linux/CARDLIST.saa7134 linux-libre-2.6.38-gnu1/Documentation/video4linux/CARDLIST.saa7134
--- linux-libre-2.6.37-gnu1/Documentation/video4linux/CARDLIST.saa7134	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/video4linux/CARDLIST.saa7134	2011-03-14 21:20:32.000000000 -0400
@@ -180,3 +180,5 @@
 179 -> Beholder BeholdTV A7                     [5ace:7090]
 180 -> Avermedia PCI M733A                      [1461:4155,1461:4255]
 181 -> TechoTrend TT-budget T-3000              [13c2:2804]
+182 -> Kworld PCI SBTVD/ISDB-T Full-Seg Hybrid  [17de:b136]
+183 -> Compro VideoMate Vista M1F               [185b:c900]
diff -druNp linux-libre-2.6.37-gnu1/Documentation/video4linux/gspca.txt linux-libre-2.6.38-gnu1/Documentation/video4linux/gspca.txt
--- linux-libre-2.6.37-gnu1/Documentation/video4linux/gspca.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/video4linux/gspca.txt	2011-03-14 21:20:32.000000000 -0400
@@ -366,6 +366,7 @@ t613		17a1:0128	TASCORP JPEG Webcam, NGS
 vc032x		17ef:4802	Lenovo Vc0323+MI1310_SOC
 pac207		2001:f115	D-Link DSB-C120
 sq905c		2770:9050	Disney pix micro (CIF)
+sq905c		2770:9051	Lego Bionicle
 sq905c		2770:9052	Disney pix micro 2 (VGA)
 sq905c		2770:905c	All 11 known cameras with this ID
 sq905		2770:9120	All 24 known cameras with this ID
diff -druNp linux-libre-2.6.37-gnu1/Documentation/video4linux/Makefile linux-libre-2.6.38-gnu1/Documentation/video4linux/Makefile
--- linux-libre-2.6.37-gnu1/Documentation/video4linux/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/video4linux/Makefile	1969-12-31 19:00:00.000000000 -0500
@@ -1,8 +0,0 @@
-# kbuild trick to avoid linker error. Can be omitted if a module is built.
-obj- := dummy.o
-
-# List of programs to build
-hostprogs-y := v4lgrab
-
-# Tell kbuild to always build the programs
-always := $(hostprogs-y)
diff -druNp linux-libre-2.6.37-gnu1/Documentation/video4linux/meye.txt linux-libre-2.6.38-gnu1/Documentation/video4linux/meye.txt
--- linux-libre-2.6.37-gnu1/Documentation/video4linux/meye.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/video4linux/meye.txt	2011-03-14 21:20:32.000000000 -0400
@@ -45,8 +45,6 @@ module argument syntax (<param>=<value>
 module or meye.<param>=<value> on the kernel boot line when meye is
 statically linked into the kernel). Those options are:
 
-	forcev4l1:	force use of V4L1 API instead of V4L2
-
 	gbuffers:	number of capture buffers, default is 2 (32 max)
 
 	gbufsize:	size of each capture buffer, default is 614400
@@ -79,9 +77,8 @@ Usage:
 Private API:
 ------------
 
-	The driver supports frame grabbing with the video4linux API
-	(either v4l1 or v4l2), so all video4linux tools (like xawtv)
-	should work with this driver.
+	The driver supports frame grabbing with the video4linux API,
+	so all video4linux tools (like xawtv) should work with this driver.
 
 	Besides the video4linux interface, the driver has a private interface
 	for accessing the Motion Eye extended parameters (camera sharpness,
@@ -123,7 +120,4 @@ Private API:
 Bugs / Todo:
 ------------
 
-	- the driver could be much cleaned up by removing the v4l1 support.
-	  However, this means all v4l1-only applications will stop working.
-
 	- 'motioneye' still uses the meye private v4l1 API extensions.
diff -druNp linux-libre-2.6.37-gnu1/Documentation/video4linux/README.cpia linux-libre-2.6.38-gnu1/Documentation/video4linux/README.cpia
--- linux-libre-2.6.37-gnu1/Documentation/video4linux/README.cpia	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/video4linux/README.cpia	1969-12-31 19:00:00.000000000 -0500
@@ -1,191 +0,0 @@
-This is a driver for the CPiA PPC2 driven parallel connected
-Camera. For example the Creative WebcamII is CPiA driven.
-
-   ) [1]Peter Pregler, Linz 2000, published under the [2]GNU GPL
-
----------------------------------------------------------------------------
-
-USAGE:
-
-General:
-========
-
-1) Make sure you have created the video devices (/dev/video*):
-
-- if you have a recent MAKEDEV do a 'cd /dev;./MAKEDEV video'
-- otherwise do a:
-
-cd /dev
-mknod video0 c 81 0
-ln -s video0 video
-
-2) Compile the kernel (see below for the list of options to use),
-   configure your parport and reboot.
-
-3) If all worked well you should get messages similar
-   to the following (your versions may be different) on the console:
-
-V4L-Driver for Vision CPiA based cameras v0.7.4
-parport0: read2 timeout.
-parport0: Multimedia device, VLSI Vision Ltd PPC2
-Parallel port driver for Vision CPiA based camera
-  CPIA Version: 1.20 (2.0)
-  CPIA PnP-ID: 0553:0002:0100
-  VP-Version: 1.0 0100
-  1 camera(s) found
-
-
-As modules:
-===========
-
-Make sure you have selected the following kernel options (you can
-select all stuff as modules):
-
-The cpia-stuff is in the section 'Character devices -> Video For Linux'.
-
-CONFIG_PARPORT=m
-CONFIG_PARPORT_PC=m
-CONFIG_PARPORT_PC_FIFO=y
-CONFIG_PARPORT_1284=y
-CONFIG_VIDEO_DEV=m
-CONFIG_VIDEO_CPIA=m
-CONFIG_VIDEO_CPIA_PP=m
-
-For autoloading of all those modules you need to tell module-init-tools
-some stuff. Add the following line to your module-init-tools config-file
-(e.g. /etc/modprobe.conf or wherever your distribution does store that
-stuff):
-
-options parport_pc io=0x378 irq=7 dma=3
-alias char-major-81 cpia_pp
-
-The first line tells the dma/irq channels to use. Those _must_ match
-the settings of your BIOS. Do NOT simply use the values above.  See
-Documentation/parport.txt for more information about this. The second
-line associates the video-device file with the driver. Of cause you
-can also load the modules once upon boot (usually done in /etc/modules).
-
-Linked into the kernel:
-=======================
-
-Make sure you have selected the following kernel options. Note that
-you cannot compile the parport-stuff as modules and the cpia-driver
-statically (the other way round is okay though).
-
-The cpia-stuff is in the section 'Character devices -> Video For Linux'.
-
-CONFIG_PARPORT=y
-CONFIG_PARPORT_PC=y
-CONFIG_PARPORT_PC_FIFO=y
-CONFIG_PARPORT_1284=y
-CONFIG_VIDEO_DEV=y
-CONFIG_VIDEO_CPIA=y
-CONFIG_VIDEO_CPIA_PP=y
-
-To use DMA/irq you will need to tell the kernel upon boot time the
-hardware configuration of the parport. You can give the boot-parameter
-at the LILO-prompt or specify it in lilo.conf. I use the following
-append-line in lilo.conf:
-
-	append="parport=0x378,7,3"
-
-See Documentation/parport.txt for more information about the
-configuration of the parport and the values given above. Do not simply
-use the values given above.
-
----------------------------------------------------------------------------
-FEATURES:
-
-- mmap/read v4l-interface (but no overlay)
-- image formats: CIF/QCIF, SIF/QSIF, various others used by isabel;
-  note: all sizes except CIF/QCIF are implemented by clipping, i.e.
-  pixels are not uploaded from the camera
-- palettes: VIDEO_PALETTE_GRAY, VIDEO_PALETTE_RGB565, VIDEO_PALETTE_RGB555,
-  VIDEO_PALETTE_RGB24, VIDEO_PALETTE_RGB32, VIDEO_PALETTE_YUYV,
-  VIDEO_PALETTE_UYVY, VIDEO_PALETTE_YUV422
-- state information (color balance, exposure, ...) is preserved between
-  device opens
-- complete control over camera via proc-interface (_all_ camera settings are
-  supported), there is also a python-gtk application available for this [3]
-- works under SMP (but the driver is completely serialized and synchronous)
-  so you get no benefit from SMP, but at least it does not crash your box
-- might work for non-Intel architecture, let us know about this
-
----------------------------------------------------------------------------
-TESTED APPLICATIONS:
-
-- a simple test application based on Xt is available at [3]
-- another test-application based on gqcam-0.4 (uses GTK)
-- gqcam-0.6 should work
-- xawtv-3.x (also the webcam software)
-- xawtv-2.46
-- w3cam (cgi-interface and vidcat, e.g. you may try out 'vidcat  |xv
-  -maxpect -root -quit +noresetroot -rmode 5 -')
-- vic, the MBONE video conferencing tool (version 2.8ucl4-1)
-- isabel 3R4beta (barely working, but AFAICT all the problems are on
-  their side)
-- camserv-0.40
-
-See [3] for pointers to v4l-applications.
-
----------------------------------------------------------------------------
-KNOWN PROBLEMS:
-
-- some applications do not handle the image format correctly, you will
-  see strange horizontal stripes instead of a nice picture -> make sure
-  your application does use a supported image size or queries the driver
-  for the actually used size (reason behind this: the camera cannot
-  provide any image format, so if size NxM is requested the driver will
-  use a format to the closest fitting N1xM1, the application should now
-  query for this granted size, most applications do not).
-- all the todo ;)
-- if there is not enough light and the picture is too dark try to
-  adjust the SetSensorFPS setting, automatic frame rate adjustment
-  has its price
-- do not try out isabel 3R4beta (built 135), you will be disappointed
-
----------------------------------------------------------------------------
-TODO:
-
-- multiple camera support (struct camera or something) - This should work,
-  but hasn't been tested yet.
-- architecture independence?
-- SMP-safe asynchronous mmap interface
-- nibble mode for old parport interfaces
-- streaming capture, this should give a performance gain
-
----------------------------------------------------------------------------
-IMPLEMENTATION NOTES:
-
-The camera can act in two modes, streaming or grabbing. Right now a
-polling grab-scheme is used. Maybe interrupt driven streaming will be
-used for a asynchronous mmap interface in the next major release of the
-driver. This might give a better frame rate.
-
----------------------------------------------------------------------------
-THANKS (in no particular order):
-
-- Scott J. Bertin <sbertin@mindspring.com> for cleanups, the proc-filesystem
-  and much more
-- Henry Bruce <whb@vvl.co.uk> for providing developers information about
-  the CPiA chip, I wish all companies would treat Linux as seriously
-- Karoly Erdei <Karoly.Erdei@risc.uni-linz.ac.at> and RISC-Linz for being
-  my boss ;) resp. my employer and for providing me the hardware and
-  allow me to devote some working time to this project
-- Manuel J. Petit de Gabriel <mpetit@dit.upm.es> for providing help
-  with Isabel (http://isabel.dit.upm.es/)
-- Bas Huisman <bhuism@cs.utwente.nl> for writing the initial parport code
-- Jarl Totland <Jarl.Totland@bdc.no> for setting up the mailing list
-  and maintaining the web-server[3]
-- Chris Whiteford <Chris@informinteractive.com> for fixes related to the
-  1.02 firmware
-- special kudos to all the tester whose machines crashed and/or
-  will crash. :)
-
----------------------------------------------------------------------------
-REFERENCES
-
-   1. http://www.risc.uni-linz.ac.at/
-      mailto:Peter_Pregler@email.com
-   2. see the file COPYING in the top directory of the kernel tree
-   3. http://webcam.sourceforge.net/
diff -druNp linux-libre-2.6.37-gnu1/Documentation/video4linux/v4l2-controls.txt linux-libre-2.6.38-gnu1/Documentation/video4linux/v4l2-controls.txt
--- linux-libre-2.6.37-gnu1/Documentation/video4linux/v4l2-controls.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/video4linux/v4l2-controls.txt	2011-03-14 21:20:32.000000000 -0400
@@ -285,6 +285,9 @@ implement g_volatile_ctrl like this:
 The 'new value' union is not used in g_volatile_ctrl. In general controls
 that need to implement g_volatile_ctrl are read-only controls.
 
+Note that if one or more controls in a control cluster are marked as volatile,
+then all the controls in the cluster are seen as volatile.
+
 To mark a control as volatile you have to set the is_volatile flag:
 
 	ctrl = v4l2_ctrl_new_std(&sd->ctrl_handler, ...);
@@ -462,6 +465,15 @@ pointer to the v4l2_ctrl_ops struct that
 Obviously, all controls in the cluster array must be initialized to either
 a valid control or to NULL.
 
+In rare cases you might want to know which controls of a cluster actually
+were set explicitly by the user. For this you can check the 'is_new' flag of
+each control. For example, in the case of a volume/mute cluster the 'is_new'
+flag of the mute control would be set if the user called VIDIOC_S_CTRL for
+mute only. If the user would call VIDIOC_S_EXT_CTRLS for both mute and volume
+controls, then the 'is_new' flag would be 1 for both controls.
+
+The 'is_new' flag is always 1 when called from v4l2_ctrl_handler_setup().
+
 
 VIDIOC_LOG_STATUS Support
 =========================
diff -druNp linux-libre-2.6.37-gnu1/Documentation/video4linux/v4lgrab.c linux-libre-2.6.38-gnu1/Documentation/video4linux/v4lgrab.c
--- linux-libre-2.6.37-gnu1/Documentation/video4linux/v4lgrab.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/video4linux/v4lgrab.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,201 +0,0 @@
-/* Simple Video4Linux image grabber. */
-/*
- *	Video4Linux Driver Test/Example Framegrabbing Program
- *
- *	Compile with:
- *		gcc -s -Wall -Wstrict-prototypes v4lgrab.c -o v4lgrab
- *	Use as:
- *		v4lgrab >image.ppm
- *
- *	Copyright (C) 1998-05-03, Phil Blundell <philb@gnu.org>
- *	Copied from http://www.tazenda.demon.co.uk/phil/vgrabber.c
- *	with minor modifications (Dave Forrest, drf5n@virginia.edu).
- *
- *
- *	For some cameras you may need to pre-load libv4l to perform
- *	the necessary decompression, e.g.:
- *
- *	export LD_PRELOAD=/usr/lib/libv4l/v4l1compat.so
- *	./v4lgrab >image.ppm
- *
- *	see http://hansdegoede.livejournal.com/3636.html for details.
- *
- */
-
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <sys/ioctl.h>
-#include <stdlib.h>
-
-#include <linux/types.h>
-#include <linux/videodev.h>
-
-#define VIDEO_DEV "/dev/video0"
-
-/* Stole this from tvset.c */
-
-#define READ_VIDEO_PIXEL(buf, format, depth, r, g, b)                   \
-{                                                                       \
-	switch (format)                                                 \
-	{                                                               \
-		case VIDEO_PALETTE_GREY:                                \
-			switch (depth)                                  \
-			{                                               \
-				case 4:                                 \
-				case 6:                                 \
-				case 8:                                 \
-					(r) = (g) = (b) = (*buf++ << 8);\
-					break;                          \
-									\
-				case 16:                                \
-					(r) = (g) = (b) =               \
-						*((unsigned short *) buf);      \
-					buf += 2;                       \
-					break;                          \
-			}                                               \
-			break;                                          \
-									\
-									\
-		case VIDEO_PALETTE_RGB565:                              \
-		{                                                       \
-			unsigned short tmp = *(unsigned short *)buf;    \
-			(r) = tmp&0xF800;                               \
-			(g) = (tmp<<5)&0xFC00;                          \
-			(b) = (tmp<<11)&0xF800;                         \
-			buf += 2;                                       \
-		}                                                       \
-		break;                                                  \
-									\
-		case VIDEO_PALETTE_RGB555:                              \
-			(r) = (buf[0]&0xF8)<<8;                         \
-			(g) = ((buf[0] << 5 | buf[1] >> 3)&0xF8)<<8;    \
-			(b) = ((buf[1] << 2 ) & 0xF8)<<8;               \
-			buf += 2;                                       \
-			break;                                          \
-									\
-		case VIDEO_PALETTE_RGB24:                               \
-			(r) = buf[0] << 8; (g) = buf[1] << 8;           \
-			(b) = buf[2] << 8;                              \
-			buf += 3;                                       \
-			break;                                          \
-									\
-		default:                                                \
-			fprintf(stderr,                                 \
-				"Format %d not yet supported\n",        \
-				format);                                \
-	}                                                               \
-}
-
-static int get_brightness_adj(unsigned char *image, long size, int *brightness) {
-  long i, tot = 0;
-  for (i=0;i<size*3;i++)
-    tot += image[i];
-  *brightness = (128 - tot/(size*3))/3;
-  return !((tot/(size*3)) >= 126 && (tot/(size*3)) <= 130);
-}
-
-int main(int argc, char ** argv)
-{
-  int fd = open(VIDEO_DEV, O_RDONLY), f;
-  struct video_capability cap;
-  struct video_window win;
-  struct video_picture vpic;
-
-  unsigned char *buffer, *src;
-  int bpp = 24, r = 0, g = 0, b = 0;
-  unsigned int i, src_depth = 16;
-
-  if (fd < 0) {
-    perror(VIDEO_DEV);
-    exit(1);
-  }
-
-  if (ioctl(fd, VIDIOCGCAP, &cap) < 0) {
-    perror("VIDIOGCAP");
-    fprintf(stderr, "(" VIDEO_DEV " not a video4linux device?)\n");
-    close(fd);
-    exit(1);
-  }
-
-  if (ioctl(fd, VIDIOCGWIN, &win) < 0) {
-    perror("VIDIOCGWIN");
-    close(fd);
-    exit(1);
-  }
-
-  if (ioctl(fd, VIDIOCGPICT, &vpic) < 0) {
-    perror("VIDIOCGPICT");
-    close(fd);
-    exit(1);
-  }
-
-  if (cap.type & VID_TYPE_MONOCHROME) {
-    vpic.depth=8;
-    vpic.palette=VIDEO_PALETTE_GREY;    /* 8bit grey */
-    if(ioctl(fd, VIDIOCSPICT, &vpic) < 0) {
-      vpic.depth=6;
-      if(ioctl(fd, VIDIOCSPICT, &vpic) < 0) {
-	vpic.depth=4;
-	if(ioctl(fd, VIDIOCSPICT, &vpic) < 0) {
-	  fprintf(stderr, "Unable to find a supported capture format.\n");
-	  close(fd);
-	  exit(1);
-	}
-      }
-    }
-  } else {
-    vpic.depth=24;
-    vpic.palette=VIDEO_PALETTE_RGB24;
-
-    if(ioctl(fd, VIDIOCSPICT, &vpic) < 0) {
-      vpic.palette=VIDEO_PALETTE_RGB565;
-      vpic.depth=16;
-
-      if(ioctl(fd, VIDIOCSPICT, &vpic)==-1) {
-	vpic.palette=VIDEO_PALETTE_RGB555;
-	vpic.depth=15;
-
-	if(ioctl(fd, VIDIOCSPICT, &vpic)==-1) {
-	  fprintf(stderr, "Unable to find a supported capture format.\n");
-	  return -1;
-	}
-      }
-    }
-  }
-
-  buffer = malloc(win.width * win.height * bpp);
-  if (!buffer) {
-    fprintf(stderr, "Out of memory.\n");
-    exit(1);
-  }
-
-  do {
-    int newbright;
-    read(fd, buffer, win.width * win.height * bpp);
-    f = get_brightness_adj(buffer, win.width * win.height, &newbright);
-    if (f) {
-      vpic.brightness += (newbright << 8);
-      if(ioctl(fd, VIDIOCSPICT, &vpic)==-1) {
-	perror("VIDIOSPICT");
-	break;
-      }
-    }
-  } while (f);
-
-  fprintf(stdout, "P6\n%d %d 255\n", win.width, win.height);
-
-  src = buffer;
-
-  for (i = 0; i < win.width * win.height; i++) {
-    READ_VIDEO_PIXEL(src, vpic.palette, src_depth, r, g, b);
-    fputc(r>>8, stdout);
-    fputc(g>>8, stdout);
-    fputc(b>>8, stdout);
-  }
-
-  close(fd);
-  return 0;
-}
diff -druNp linux-libre-2.6.37-gnu1/Documentation/video4linux/videobuf linux-libre-2.6.38-gnu1/Documentation/video4linux/videobuf
--- linux-libre-2.6.37-gnu1/Documentation/video4linux/videobuf	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/video4linux/videobuf	2011-03-14 21:20:32.000000000 -0400
@@ -247,8 +247,6 @@ calls.  The relevant helper functions ar
 		       int nonblocking);
     int videobuf_streamon(struct videobuf_queue *q);
     int videobuf_streamoff(struct videobuf_queue *q);
-    int videobuf_cgmbuf(struct videobuf_queue *q, struct video_mbuf *mbuf,
-			int count);
 
 So, for example, a VIDIOC_REQBUFS call turns into a call to the driver's
 vidioc_reqbufs() callback which, in turn, usually only needs to locate the
@@ -258,10 +256,7 @@ boilerplate in a lot of V4L2 drivers.
 
 The vidioc_streamon() and vidioc_streamoff() functions will be a bit more
 complex, of course, since they will also need to deal with starting and
-stopping the capture engine.  videobuf_cgmbuf(), called from the driver's
-vidiocgmbuf() function, only exists if the V4L1 compatibility module has
-been selected with CONFIG_VIDEO_V4L1_COMPAT, so its use must be surrounded
-with #ifdef directives.
+stopping the capture engine.
 
 Buffer allocation
 
diff -druNp linux-libre-2.6.37-gnu1/Documentation/video4linux/Zoran linux-libre-2.6.38-gnu1/Documentation/video4linux/Zoran
--- linux-libre-2.6.37-gnu1/Documentation/video4linux/Zoran	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/video4linux/Zoran	2011-03-14 21:20:32.000000000 -0400
@@ -322,76 +322,11 @@ your IRQs and make sure the card has its
 
 4. Programming interface
 
-This driver conforms to video4linux and video4linux2, both can be used to
-use the driver. Since video4linux didn't provide adequate calls to fully
-use the cards' features, we've introduced several programming extensions,
-which are currently officially accepted in the 2.4.x branch of the kernel.
-These extensions are known as the v4l/mjpeg extensions. See zoran.h for
-details (structs/ioctls).
-
-Information - video4linux:
-http://linux.bytesex.org/v4l2/API.html
-Documentation/video4linux/API.html
-/usr/include/linux/videodev.h
-
-Information - video4linux/mjpeg extensions:
-./zoran.h
-(also see below)
-
-Information - video4linux2:
-http://linuxtv.org
-http://v4l2spec.bytesex.org/
-/usr/include/linux/videodev2.h
-
-More information on the video4linux/mjpeg extensions, by Serguei
-Miridonovi and Rainer Johanni:
---
-The ioctls for that interface are as follows:
-
-BUZIOC_G_PARAMS
-BUZIOC_S_PARAMS
-
-Get and set the parameters of the buz. The user should always do a
-BUZIOC_G_PARAMS (with a struct buz_params) to obtain the default
-settings, change what he likes and then make a BUZIOC_S_PARAMS call.
-
-BUZIOC_REQBUFS
-
-Before being able to capture/playback, the user has to request
-the buffers he is wanting to use. Fill the structure
-zoran_requestbuffers with the size (recommended: 256*1024) and
-the number (recommended 32 up to 256). There are no such restrictions
-as for the Video for Linux buffers, you should LEAVE SUFFICIENT
-MEMORY for your system however, else strange things will happen ....
-On return, the zoran_requestbuffers structure contains number and
-size of the actually allocated buffers.
-You should use these numbers for doing a mmap of the buffers
-into the user space.
-The BUZIOC_REQBUFS ioctl also makes it happen, that the next mmap
-maps the MJPEG buffer instead of the V4L buffers.
-
-BUZIOC_QBUF_CAPT
-BUZIOC_QBUF_PLAY
-
-Queue a buffer for capture or playback. The first call also starts
-streaming capture. When streaming capture is going on, you may
-only queue further buffers or issue syncs until streaming
-capture is switched off again with a argument of -1 to
-a BUZIOC_QBUF_CAPT/BUZIOC_QBUF_PLAY ioctl.
-
-BUZIOC_SYNC
-
-Issue this ioctl when all buffers are queued. This ioctl will
-block until the first buffer becomes free for saving its
-data to disk (after BUZIOC_QBUF_CAPT) or for reuse (after BUZIOC_QBUF_PLAY).
-
-BUZIOC_G_STATUS
-
-Get the status of the input lines (video source connected/norm).
+This driver conforms to video4linux2. Support for V4L1 and for the custom
+zoran ioctls has been removed in kernel 2.6.38.
 
 For programming example, please, look at lavrec.c and lavplay.c code in
-lavtools-1.2p2 package (URL: http://www.cicese.mx/)
-and the 'examples' directory in the original Buz driver distribution.
+the MJPEG-tools (http://mjpeg.sf.net/).
 
 Additional notes for software developers:
 
@@ -402,9 +337,6 @@ Additional notes for software developers
    standard is "more constant" for current country than geometry
    settings of a variety of TV capture cards which may work in ITU or
    square pixel format.
---
-Please note that lavplay/lavrec are also included in the MJPEG-tools
-(http://mjpeg.sf.net/).
 
 ===========================
 
diff -druNp linux-libre-2.6.37-gnu1/Documentation/vm/Makefile linux-libre-2.6.38-gnu1/Documentation/vm/Makefile
--- linux-libre-2.6.37-gnu1/Documentation/vm/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/vm/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -2,7 +2,7 @@
 obj- := dummy.o
 
 # List of programs to build
-hostprogs-y := slabinfo page-types hugepage-mmap hugepage-shm map_hugetlb
+hostprogs-y := page-types hugepage-mmap hugepage-shm map_hugetlb
 
 # Tell kbuild to always build the programs
 always := $(hostprogs-y)
diff -druNp linux-libre-2.6.37-gnu1/Documentation/vm/slabinfo.c linux-libre-2.6.38-gnu1/Documentation/vm/slabinfo.c
--- linux-libre-2.6.37-gnu1/Documentation/vm/slabinfo.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/vm/slabinfo.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1364 +0,0 @@
-/*
- * Slabinfo: Tool to get reports about slabs
- *
- * (C) 2007 sgi, Christoph Lameter
- *
- * Compile by:
- *
- * gcc -o slabinfo slabinfo.c
- */
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <dirent.h>
-#include <strings.h>
-#include <string.h>
-#include <unistd.h>
-#include <stdarg.h>
-#include <getopt.h>
-#include <regex.h>
-#include <errno.h>
-
-#define MAX_SLABS 500
-#define MAX_ALIASES 500
-#define MAX_NODES 1024
-
-struct slabinfo {
-	char *name;
-	int alias;
-	int refs;
-	int aliases, align, cache_dma, cpu_slabs, destroy_by_rcu;
-	int hwcache_align, object_size, objs_per_slab;
-	int sanity_checks, slab_size, store_user, trace;
-	int order, poison, reclaim_account, red_zone;
-	unsigned long partial, objects, slabs, objects_partial, objects_total;
-	unsigned long alloc_fastpath, alloc_slowpath;
-	unsigned long free_fastpath, free_slowpath;
-	unsigned long free_frozen, free_add_partial, free_remove_partial;
-	unsigned long alloc_from_partial, alloc_slab, free_slab, alloc_refill;
-	unsigned long cpuslab_flush, deactivate_full, deactivate_empty;
-	unsigned long deactivate_to_head, deactivate_to_tail;
-	unsigned long deactivate_remote_frees, order_fallback;
-	int numa[MAX_NODES];
-	int numa_partial[MAX_NODES];
-} slabinfo[MAX_SLABS];
-
-struct aliasinfo {
-	char *name;
-	char *ref;
-	struct slabinfo *slab;
-} aliasinfo[MAX_ALIASES];
-
-int slabs = 0;
-int actual_slabs = 0;
-int aliases = 0;
-int alias_targets = 0;
-int highest_node = 0;
-
-char buffer[4096];
-
-int show_empty = 0;
-int show_report = 0;
-int show_alias = 0;
-int show_slab = 0;
-int skip_zero = 1;
-int show_numa = 0;
-int show_track = 0;
-int show_first_alias = 0;
-int validate = 0;
-int shrink = 0;
-int show_inverted = 0;
-int show_single_ref = 0;
-int show_totals = 0;
-int sort_size = 0;
-int sort_active = 0;
-int set_debug = 0;
-int show_ops = 0;
-int show_activity = 0;
-
-/* Debug options */
-int sanity = 0;
-int redzone = 0;
-int poison = 0;
-int tracking = 0;
-int tracing = 0;
-
-int page_size;
-
-regex_t pattern;
-
-static void fatal(const char *x, ...)
-{
-	va_list ap;
-
-	va_start(ap, x);
-	vfprintf(stderr, x, ap);
-	va_end(ap);
-	exit(EXIT_FAILURE);
-}
-
-static void usage(void)
-{
-	printf("slabinfo 5/7/2007. (c) 2007 sgi.\n\n"
-		"slabinfo [-ahnpvtsz] [-d debugopts] [slab-regexp]\n"
-		"-a|--aliases           Show aliases\n"
-		"-A|--activity          Most active slabs first\n"
-		"-d<options>|--debug=<options> Set/Clear Debug options\n"
-		"-D|--display-active    Switch line format to activity\n"
-		"-e|--empty             Show empty slabs\n"
-		"-f|--first-alias       Show first alias\n"
-		"-h|--help              Show usage information\n"
-		"-i|--inverted          Inverted list\n"
-		"-l|--slabs             Show slabs\n"
-		"-n|--numa              Show NUMA information\n"
-		"-o|--ops		Show kmem_cache_ops\n"
-		"-s|--shrink            Shrink slabs\n"
-		"-r|--report		Detailed report on single slabs\n"
-		"-S|--Size              Sort by size\n"
-		"-t|--tracking          Show alloc/free information\n"
-		"-T|--Totals            Show summary information\n"
-		"-v|--validate          Validate slabs\n"
-		"-z|--zero              Include empty slabs\n"
-		"-1|--1ref              Single reference\n"
-		"\nValid debug options (FZPUT may be combined)\n"
-		"a / A          Switch on all debug options (=FZUP)\n"
-		"-              Switch off all debug options\n"
-		"f / F          Sanity Checks (SLAB_DEBUG_FREE)\n"
-		"z / Z          Redzoning\n"
-		"p / P          Poisoning\n"
-		"u / U          Tracking\n"
-		"t / T          Tracing\n"
-	);
-}
-
-static unsigned long read_obj(const char *name)
-{
-	FILE *f = fopen(name, "r");
-
-	if (!f)
-		buffer[0] = 0;
-	else {
-		if (!fgets(buffer, sizeof(buffer), f))
-			buffer[0] = 0;
-		fclose(f);
-		if (buffer[strlen(buffer)] == '\n')
-			buffer[strlen(buffer)] = 0;
-	}
-	return strlen(buffer);
-}
-
-
-/*
- * Get the contents of an attribute
- */
-static unsigned long get_obj(const char *name)
-{
-	if (!read_obj(name))
-		return 0;
-
-	return atol(buffer);
-}
-
-static unsigned long get_obj_and_str(const char *name, char **x)
-{
-	unsigned long result = 0;
-	char *p;
-
-	*x = NULL;
-
-	if (!read_obj(name)) {
-		x = NULL;
-		return 0;
-	}
-	result = strtoul(buffer, &p, 10);
-	while (*p == ' ')
-		p++;
-	if (*p)
-		*x = strdup(p);
-	return result;
-}
-
-static void set_obj(struct slabinfo *s, const char *name, int n)
-{
-	char x[100];
-	FILE *f;
-
-	snprintf(x, 100, "%s/%s", s->name, name);
-	f = fopen(x, "w");
-	if (!f)
-		fatal("Cannot write to %s\n", x);
-
-	fprintf(f, "%d\n", n);
-	fclose(f);
-}
-
-static unsigned long read_slab_obj(struct slabinfo *s, const char *name)
-{
-	char x[100];
-	FILE *f;
-	size_t l;
-
-	snprintf(x, 100, "%s/%s", s->name, name);
-	f = fopen(x, "r");
-	if (!f) {
-		buffer[0] = 0;
-		l = 0;
-	} else {
-		l = fread(buffer, 1, sizeof(buffer), f);
-		buffer[l] = 0;
-		fclose(f);
-	}
-	return l;
-}
-
-
-/*
- * Put a size string together
- */
-static int store_size(char *buffer, unsigned long value)
-{
-	unsigned long divisor = 1;
-	char trailer = 0;
-	int n;
-
-	if (value > 1000000000UL) {
-		divisor = 100000000UL;
-		trailer = 'G';
-	} else if (value > 1000000UL) {
-		divisor = 100000UL;
-		trailer = 'M';
-	} else if (value > 1000UL) {
-		divisor = 100;
-		trailer = 'K';
-	}
-
-	value /= divisor;
-	n = sprintf(buffer, "%ld",value);
-	if (trailer) {
-		buffer[n] = trailer;
-		n++;
-		buffer[n] = 0;
-	}
-	if (divisor != 1) {
-		memmove(buffer + n - 2, buffer + n - 3, 4);
-		buffer[n-2] = '.';
-		n++;
-	}
-	return n;
-}
-
-static void decode_numa_list(int *numa, char *t)
-{
-	int node;
-	int nr;
-
-	memset(numa, 0, MAX_NODES * sizeof(int));
-
-	if (!t)
-		return;
-
-	while (*t == 'N') {
-		t++;
-		node = strtoul(t, &t, 10);
-		if (*t == '=') {
-			t++;
-			nr = strtoul(t, &t, 10);
-			numa[node] = nr;
-			if (node > highest_node)
-				highest_node = node;
-		}
-		while (*t == ' ')
-			t++;
-	}
-}
-
-static void slab_validate(struct slabinfo *s)
-{
-	if (strcmp(s->name, "*") == 0)
-		return;
-
-	set_obj(s, "validate", 1);
-}
-
-static void slab_shrink(struct slabinfo *s)
-{
-	if (strcmp(s->name, "*") == 0)
-		return;
-
-	set_obj(s, "shrink", 1);
-}
-
-int line = 0;
-
-static void first_line(void)
-{
-	if (show_activity)
-		printf("Name                   Objects      Alloc       Free   %%Fast Fallb O\n");
-	else
-		printf("Name                   Objects Objsize    Space "
-			"Slabs/Part/Cpu  O/S O %%Fr %%Ef Flg\n");
-}
-
-/*
- * Find the shortest alias of a slab
- */
-static struct aliasinfo *find_one_alias(struct slabinfo *find)
-{
-	struct aliasinfo *a;
-	struct aliasinfo *best = NULL;
-
-	for(a = aliasinfo;a < aliasinfo + aliases; a++) {
-		if (a->slab == find &&
-			(!best || strlen(best->name) < strlen(a->name))) {
-				best = a;
-				if (strncmp(a->name,"kmall", 5) == 0)
-					return best;
-			}
-	}
-	return best;
-}
-
-static unsigned long slab_size(struct slabinfo *s)
-{
-	return 	s->slabs * (page_size << s->order);
-}
-
-static unsigned long slab_activity(struct slabinfo *s)
-{
-	return 	s->alloc_fastpath + s->free_fastpath +
-		s->alloc_slowpath + s->free_slowpath;
-}
-
-static void slab_numa(struct slabinfo *s, int mode)
-{
-	int node;
-
-	if (strcmp(s->name, "*") == 0)
-		return;
-
-	if (!highest_node) {
-		printf("\n%s: No NUMA information available.\n", s->name);
-		return;
-	}
-
-	if (skip_zero && !s->slabs)
-		return;
-
-	if (!line) {
-		printf("\n%-21s:", mode ? "NUMA nodes" : "Slab");
-		for(node = 0; node <= highest_node; node++)
-			printf(" %4d", node);
-		printf("\n----------------------");
-		for(node = 0; node <= highest_node; node++)
-			printf("-----");
-		printf("\n");
-	}
-	printf("%-21s ", mode ? "All slabs" : s->name);
-	for(node = 0; node <= highest_node; node++) {
-		char b[20];
-
-		store_size(b, s->numa[node]);
-		printf(" %4s", b);
-	}
-	printf("\n");
-	if (mode) {
-		printf("%-21s ", "Partial slabs");
-		for(node = 0; node <= highest_node; node++) {
-			char b[20];
-
-			store_size(b, s->numa_partial[node]);
-			printf(" %4s", b);
-		}
-		printf("\n");
-	}
-	line++;
-}
-
-static void show_tracking(struct slabinfo *s)
-{
-	printf("\n%s: Kernel object allocation\n", s->name);
-	printf("-----------------------------------------------------------------------\n");
-	if (read_slab_obj(s, "alloc_calls"))
-		printf(buffer);
-	else
-		printf("No Data\n");
-
-	printf("\n%s: Kernel object freeing\n", s->name);
-	printf("------------------------------------------------------------------------\n");
-	if (read_slab_obj(s, "free_calls"))
-		printf(buffer);
-	else
-		printf("No Data\n");
-
-}
-
-static void ops(struct slabinfo *s)
-{
-	if (strcmp(s->name, "*") == 0)
-		return;
-
-	if (read_slab_obj(s, "ops")) {
-		printf("\n%s: kmem_cache operations\n", s->name);
-		printf("--------------------------------------------\n");
-		printf(buffer);
-	} else
-		printf("\n%s has no kmem_cache operations\n", s->name);
-}
-
-static const char *onoff(int x)
-{
-	if (x)
-		return "On ";
-	return "Off";
-}
-
-static void slab_stats(struct slabinfo *s)
-{
-	unsigned long total_alloc;
-	unsigned long total_free;
-	unsigned long total;
-
-	if (!s->alloc_slab)
-		return;
-
-	total_alloc = s->alloc_fastpath + s->alloc_slowpath;
-	total_free = s->free_fastpath + s->free_slowpath;
-
-	if (!total_alloc)
-		return;
-
-	printf("\n");
-	printf("Slab Perf Counter       Alloc     Free %%Al %%Fr\n");
-	printf("--------------------------------------------------\n");
-	printf("Fastpath             %8lu %8lu %3lu %3lu\n",
-		s->alloc_fastpath, s->free_fastpath,
-		s->alloc_fastpath * 100 / total_alloc,
-		s->free_fastpath * 100 / total_free);
-	printf("Slowpath             %8lu %8lu %3lu %3lu\n",
-		total_alloc - s->alloc_fastpath, s->free_slowpath,
-		(total_alloc - s->alloc_fastpath) * 100 / total_alloc,
-		s->free_slowpath * 100 / total_free);
-	printf("Page Alloc           %8lu %8lu %3lu %3lu\n",
-		s->alloc_slab, s->free_slab,
-		s->alloc_slab * 100 / total_alloc,
-		s->free_slab * 100 / total_free);
-	printf("Add partial          %8lu %8lu %3lu %3lu\n",
-		s->deactivate_to_head + s->deactivate_to_tail,
-		s->free_add_partial,
-		(s->deactivate_to_head + s->deactivate_to_tail) * 100 / total_alloc,
-		s->free_add_partial * 100 / total_free);
-	printf("Remove partial       %8lu %8lu %3lu %3lu\n",
-		s->alloc_from_partial, s->free_remove_partial,
-		s->alloc_from_partial * 100 / total_alloc,
-		s->free_remove_partial * 100 / total_free);
-
-	printf("RemoteObj/SlabFrozen %8lu %8lu %3lu %3lu\n",
-		s->deactivate_remote_frees, s->free_frozen,
-		s->deactivate_remote_frees * 100 / total_alloc,
-		s->free_frozen * 100 / total_free);
-
-	printf("Total                %8lu %8lu\n\n", total_alloc, total_free);
-
-	if (s->cpuslab_flush)
-		printf("Flushes %8lu\n", s->cpuslab_flush);
-
-	if (s->alloc_refill)
-		printf("Refill %8lu\n", s->alloc_refill);
-
-	total = s->deactivate_full + s->deactivate_empty +
-			s->deactivate_to_head + s->deactivate_to_tail;
-
-	if (total)
-		printf("Deactivate Full=%lu(%lu%%) Empty=%lu(%lu%%) "
-			"ToHead=%lu(%lu%%) ToTail=%lu(%lu%%)\n",
-			s->deactivate_full, (s->deactivate_full * 100) / total,
-			s->deactivate_empty, (s->deactivate_empty * 100) / total,
-			s->deactivate_to_head, (s->deactivate_to_head * 100) / total,
-			s->deactivate_to_tail, (s->deactivate_to_tail * 100) / total);
-}
-
-static void report(struct slabinfo *s)
-{
-	if (strcmp(s->name, "*") == 0)
-		return;
-
-	printf("\nSlabcache: %-20s  Aliases: %2d Order : %2d Objects: %lu\n",
-		s->name, s->aliases, s->order, s->objects);
-	if (s->hwcache_align)
-		printf("** Hardware cacheline aligned\n");
-	if (s->cache_dma)
-		printf("** Memory is allocated in a special DMA zone\n");
-	if (s->destroy_by_rcu)
-		printf("** Slabs are destroyed via RCU\n");
-	if (s->reclaim_account)
-		printf("** Reclaim accounting active\n");
-
-	printf("\nSizes (bytes)     Slabs              Debug                Memory\n");
-	printf("------------------------------------------------------------------------\n");
-	printf("Object : %7d  Total  : %7ld   Sanity Checks : %s  Total: %7ld\n",
-			s->object_size, s->slabs, onoff(s->sanity_checks),
-			s->slabs * (page_size << s->order));
-	printf("SlabObj: %7d  Full   : %7ld   Redzoning     : %s  Used : %7ld\n",
-			s->slab_size, s->slabs - s->partial - s->cpu_slabs,
-			onoff(s->red_zone), s->objects * s->object_size);
-	printf("SlabSiz: %7d  Partial: %7ld   Poisoning     : %s  Loss : %7ld\n",
-			page_size << s->order, s->partial, onoff(s->poison),
-			s->slabs * (page_size << s->order) - s->objects * s->object_size);
-	printf("Loss   : %7d  CpuSlab: %7d   Tracking      : %s  Lalig: %7ld\n",
-			s->slab_size - s->object_size, s->cpu_slabs, onoff(s->store_user),
-			(s->slab_size - s->object_size) * s->objects);
-	printf("Align  : %7d  Objects: %7d   Tracing       : %s  Lpadd: %7ld\n",
-			s->align, s->objs_per_slab, onoff(s->trace),
-			((page_size << s->order) - s->objs_per_slab * s->slab_size) *
-			s->slabs);
-
-	ops(s);
-	show_tracking(s);
-	slab_numa(s, 1);
-	slab_stats(s);
-}
-
-static void slabcache(struct slabinfo *s)
-{
-	char size_str[20];
-	char dist_str[40];
-	char flags[20];
-	char *p = flags;
-
-	if (strcmp(s->name, "*") == 0)
-		return;
-
-	if (actual_slabs == 1) {
-		report(s);
-		return;
-	}
-
-	if (skip_zero && !show_empty && !s->slabs)
-		return;
-
-	if (show_empty && s->slabs)
-		return;
-
-	store_size(size_str, slab_size(s));
-	snprintf(dist_str, 40, "%lu/%lu/%d", s->slabs - s->cpu_slabs,
-						s->partial, s->cpu_slabs);
-
-	if (!line++)
-		first_line();
-
-	if (s->aliases)
-		*p++ = '*';
-	if (s->cache_dma)
-		*p++ = 'd';
-	if (s->hwcache_align)
-		*p++ = 'A';
-	if (s->poison)
-		*p++ = 'P';
-	if (s->reclaim_account)
-		*p++ = 'a';
-	if (s->red_zone)
-		*p++ = 'Z';
-	if (s->sanity_checks)
-		*p++ = 'F';
-	if (s->store_user)
-		*p++ = 'U';
-	if (s->trace)
-		*p++ = 'T';
-
-	*p = 0;
-	if (show_activity) {
-		unsigned long total_alloc;
-		unsigned long total_free;
-
-		total_alloc = s->alloc_fastpath + s->alloc_slowpath;
-		total_free = s->free_fastpath + s->free_slowpath;
-
-		printf("%-21s %8ld %10ld %10ld %3ld %3ld %5ld %1d\n",
-			s->name, s->objects,
-			total_alloc, total_free,
-			total_alloc ? (s->alloc_fastpath * 100 / total_alloc) : 0,
-			total_free ? (s->free_fastpath * 100 / total_free) : 0,
-			s->order_fallback, s->order);
-	}
-	else
-		printf("%-21s %8ld %7d %8s %14s %4d %1d %3ld %3ld %s\n",
-			s->name, s->objects, s->object_size, size_str, dist_str,
-			s->objs_per_slab, s->order,
-			s->slabs ? (s->partial * 100) / s->slabs : 100,
-			s->slabs ? (s->objects * s->object_size * 100) /
-				(s->slabs * (page_size << s->order)) : 100,
-			flags);
-}
-
-/*
- * Analyze debug options. Return false if something is amiss.
- */
-static int debug_opt_scan(char *opt)
-{
-	if (!opt || !opt[0] || strcmp(opt, "-") == 0)
-		return 1;
-
-	if (strcasecmp(opt, "a") == 0) {
-		sanity = 1;
-		poison = 1;
-		redzone = 1;
-		tracking = 1;
-		return 1;
-	}
-
-	for ( ; *opt; opt++)
-	 	switch (*opt) {
-		case 'F' : case 'f':
-			if (sanity)
-				return 0;
-			sanity = 1;
-			break;
-		case 'P' : case 'p':
-			if (poison)
-				return 0;
-			poison = 1;
-			break;
-
-		case 'Z' : case 'z':
-			if (redzone)
-				return 0;
-			redzone = 1;
-			break;
-
-		case 'U' : case 'u':
-			if (tracking)
-				return 0;
-			tracking = 1;
-			break;
-
-		case 'T' : case 't':
-			if (tracing)
-				return 0;
-			tracing = 1;
-			break;
-		default:
-			return 0;
-		}
-	return 1;
-}
-
-static int slab_empty(struct slabinfo *s)
-{
-	if (s->objects > 0)
-		return 0;
-
-	/*
-	 * We may still have slabs even if there are no objects. Shrinking will
-	 * remove them.
-	 */
-	if (s->slabs != 0)
-		set_obj(s, "shrink", 1);
-
-	return 1;
-}
-
-static void slab_debug(struct slabinfo *s)
-{
-	if (strcmp(s->name, "*") == 0)
-		return;
-
-	if (sanity && !s->sanity_checks) {
-		set_obj(s, "sanity", 1);
-	}
-	if (!sanity && s->sanity_checks) {
-		if (slab_empty(s))
-			set_obj(s, "sanity", 0);
-		else
-			fprintf(stderr, "%s not empty cannot disable sanity checks\n", s->name);
-	}
-	if (redzone && !s->red_zone) {
-		if (slab_empty(s))
-			set_obj(s, "red_zone", 1);
-		else
-			fprintf(stderr, "%s not empty cannot enable redzoning\n", s->name);
-	}
-	if (!redzone && s->red_zone) {
-		if (slab_empty(s))
-			set_obj(s, "red_zone", 0);
-		else
-			fprintf(stderr, "%s not empty cannot disable redzoning\n", s->name);
-	}
-	if (poison && !s->poison) {
-		if (slab_empty(s))
-			set_obj(s, "poison", 1);
-		else
-			fprintf(stderr, "%s not empty cannot enable poisoning\n", s->name);
-	}
-	if (!poison && s->poison) {
-		if (slab_empty(s))
-			set_obj(s, "poison", 0);
-		else
-			fprintf(stderr, "%s not empty cannot disable poisoning\n", s->name);
-	}
-	if (tracking && !s->store_user) {
-		if (slab_empty(s))
-			set_obj(s, "store_user", 1);
-		else
-			fprintf(stderr, "%s not empty cannot enable tracking\n", s->name);
-	}
-	if (!tracking && s->store_user) {
-		if (slab_empty(s))
-			set_obj(s, "store_user", 0);
-		else
-			fprintf(stderr, "%s not empty cannot disable tracking\n", s->name);
-	}
-	if (tracing && !s->trace) {
-		if (slabs == 1)
-			set_obj(s, "trace", 1);
-		else
-			fprintf(stderr, "%s can only enable trace for one slab at a time\n", s->name);
-	}
-	if (!tracing && s->trace)
-		set_obj(s, "trace", 1);
-}
-
-static void totals(void)
-{
-	struct slabinfo *s;
-
-	int used_slabs = 0;
-	char b1[20], b2[20], b3[20], b4[20];
-	unsigned long long max = 1ULL << 63;
-
-	/* Object size */
-	unsigned long long min_objsize = max, max_objsize = 0, avg_objsize;
-
-	/* Number of partial slabs in a slabcache */
-	unsigned long long min_partial = max, max_partial = 0,
-				avg_partial, total_partial = 0;
-
-	/* Number of slabs in a slab cache */
-	unsigned long long min_slabs = max, max_slabs = 0,
-				avg_slabs, total_slabs = 0;
-
-	/* Size of the whole slab */
-	unsigned long long min_size = max, max_size = 0,
-				avg_size, total_size = 0;
-
-	/* Bytes used for object storage in a slab */
-	unsigned long long min_used = max, max_used = 0,
-				avg_used, total_used = 0;
-
-	/* Waste: Bytes used for alignment and padding */
-	unsigned long long min_waste = max, max_waste = 0,
-				avg_waste, total_waste = 0;
-	/* Number of objects in a slab */
-	unsigned long long min_objects = max, max_objects = 0,
-				avg_objects, total_objects = 0;
-	/* Waste per object */
-	unsigned long long min_objwaste = max,
-				max_objwaste = 0, avg_objwaste,
-				total_objwaste = 0;
-
-	/* Memory per object */
-	unsigned long long min_memobj = max,
-				max_memobj = 0, avg_memobj,
-				total_objsize = 0;
-
-	/* Percentage of partial slabs per slab */
-	unsigned long min_ppart = 100, max_ppart = 0,
-				avg_ppart, total_ppart = 0;
-
-	/* Number of objects in partial slabs */
-	unsigned long min_partobj = max, max_partobj = 0,
-				avg_partobj, total_partobj = 0;
-
-	/* Percentage of partial objects of all objects in a slab */
-	unsigned long min_ppartobj = 100, max_ppartobj = 0,
-				avg_ppartobj, total_ppartobj = 0;
-
-
-	for (s = slabinfo; s < slabinfo + slabs; s++) {
-		unsigned long long size;
-		unsigned long used;
-		unsigned long long wasted;
-		unsigned long long objwaste;
-		unsigned long percentage_partial_slabs;
-		unsigned long percentage_partial_objs;
-
-		if (!s->slabs || !s->objects)
-			continue;
-
-		used_slabs++;
-
-		size = slab_size(s);
-		used = s->objects * s->object_size;
-		wasted = size - used;
-		objwaste = s->slab_size - s->object_size;
-
-		percentage_partial_slabs = s->partial * 100 / s->slabs;
-		if (percentage_partial_slabs > 100)
-			percentage_partial_slabs = 100;
-
-		percentage_partial_objs = s->objects_partial * 100
-							/ s->objects;
-
-		if (percentage_partial_objs > 100)
-			percentage_partial_objs = 100;
-
-		if (s->object_size < min_objsize)
-			min_objsize = s->object_size;
-		if (s->partial < min_partial)
-			min_partial = s->partial;
-		if (s->slabs < min_slabs)
-			min_slabs = s->slabs;
-		if (size < min_size)
-			min_size = size;
-		if (wasted < min_waste)
-			min_waste = wasted;
-		if (objwaste < min_objwaste)
-			min_objwaste = objwaste;
-		if (s->objects < min_objects)
-			min_objects = s->objects;
-		if (used < min_used)
-			min_used = used;
-		if (s->objects_partial < min_partobj)
-			min_partobj = s->objects_partial;
-		if (percentage_partial_slabs < min_ppart)
-			min_ppart = percentage_partial_slabs;
-		if (percentage_partial_objs < min_ppartobj)
-			min_ppartobj = percentage_partial_objs;
-		if (s->slab_size < min_memobj)
-			min_memobj = s->slab_size;
-
-		if (s->object_size > max_objsize)
-			max_objsize = s->object_size;
-		if (s->partial > max_partial)
-			max_partial = s->partial;
-		if (s->slabs > max_slabs)
-			max_slabs = s->slabs;
-		if (size > max_size)
-			max_size = size;
-		if (wasted > max_waste)
-			max_waste = wasted;
-		if (objwaste > max_objwaste)
-			max_objwaste = objwaste;
-		if (s->objects > max_objects)
-			max_objects = s->objects;
-		if (used > max_used)
-			max_used = used;
-		if (s->objects_partial > max_partobj)
-			max_partobj = s->objects_partial;
-		if (percentage_partial_slabs > max_ppart)
-			max_ppart = percentage_partial_slabs;
-		if (percentage_partial_objs > max_ppartobj)
-			max_ppartobj = percentage_partial_objs;
-		if (s->slab_size > max_memobj)
-			max_memobj = s->slab_size;
-
-		total_partial += s->partial;
-		total_slabs += s->slabs;
-		total_size += size;
-		total_waste += wasted;
-
-		total_objects += s->objects;
-		total_used += used;
-		total_partobj += s->objects_partial;
-		total_ppart += percentage_partial_slabs;
-		total_ppartobj += percentage_partial_objs;
-
-		total_objwaste += s->objects * objwaste;
-		total_objsize += s->objects * s->slab_size;
-	}
-
-	if (!total_objects) {
-		printf("No objects\n");
-		return;
-	}
-	if (!used_slabs) {
-		printf("No slabs\n");
-		return;
-	}
-
-	/* Per slab averages */
-	avg_partial = total_partial / used_slabs;
-	avg_slabs = total_slabs / used_slabs;
-	avg_size = total_size / used_slabs;
-	avg_waste = total_waste / used_slabs;
-
-	avg_objects = total_objects / used_slabs;
-	avg_used = total_used / used_slabs;
-	avg_partobj = total_partobj / used_slabs;
-	avg_ppart = total_ppart / used_slabs;
-	avg_ppartobj = total_ppartobj / used_slabs;
-
-	/* Per object object sizes */
-	avg_objsize = total_used / total_objects;
-	avg_objwaste = total_objwaste / total_objects;
-	avg_partobj = total_partobj * 100 / total_objects;
-	avg_memobj = total_objsize / total_objects;
-
-	printf("Slabcache Totals\n");
-	printf("----------------\n");
-	printf("Slabcaches : %3d      Aliases  : %3d->%-3d Active: %3d\n",
-			slabs, aliases, alias_targets, used_slabs);
-
-	store_size(b1, total_size);store_size(b2, total_waste);
-	store_size(b3, total_waste * 100 / total_used);
-	printf("Memory used: %6s   # Loss   : %6s   MRatio:%6s%%\n", b1, b2, b3);
-
-	store_size(b1, total_objects);store_size(b2, total_partobj);
-	store_size(b3, total_partobj * 100 / total_objects);
-	printf("# Objects  : %6s   # PartObj: %6s   ORatio:%6s%%\n", b1, b2, b3);
-
-	printf("\n");
-	printf("Per Cache    Average         Min         Max       Total\n");
-	printf("---------------------------------------------------------\n");
-
-	store_size(b1, avg_objects);store_size(b2, min_objects);
-	store_size(b3, max_objects);store_size(b4, total_objects);
-	printf("#Objects  %10s  %10s  %10s  %10s\n",
-			b1,	b2,	b3,	b4);
-
-	store_size(b1, avg_slabs);store_size(b2, min_slabs);
-	store_size(b3, max_slabs);store_size(b4, total_slabs);
-	printf("#Slabs    %10s  %10s  %10s  %10s\n",
-			b1,	b2,	b3,	b4);
-
-	store_size(b1, avg_partial);store_size(b2, min_partial);
-	store_size(b3, max_partial);store_size(b4, total_partial);
-	printf("#PartSlab %10s  %10s  %10s  %10s\n",
-			b1,	b2,	b3,	b4);
-	store_size(b1, avg_ppart);store_size(b2, min_ppart);
-	store_size(b3, max_ppart);
-	store_size(b4, total_partial * 100  / total_slabs);
-	printf("%%PartSlab%10s%% %10s%% %10s%% %10s%%\n",
-			b1,	b2,	b3,	b4);
-
-	store_size(b1, avg_partobj);store_size(b2, min_partobj);
-	store_size(b3, max_partobj);
-	store_size(b4, total_partobj);
-	printf("PartObjs  %10s  %10s  %10s  %10s\n",
-			b1,	b2,	b3,	b4);
-
-	store_size(b1, avg_ppartobj);store_size(b2, min_ppartobj);
-	store_size(b3, max_ppartobj);
-	store_size(b4, total_partobj * 100 / total_objects);
-	printf("%% PartObj%10s%% %10s%% %10s%% %10s%%\n",
-			b1,	b2,	b3,	b4);
-
-	store_size(b1, avg_size);store_size(b2, min_size);
-	store_size(b3, max_size);store_size(b4, total_size);
-	printf("Memory    %10s  %10s  %10s  %10s\n",
-			b1,	b2,	b3,	b4);
-
-	store_size(b1, avg_used);store_size(b2, min_used);
-	store_size(b3, max_used);store_size(b4, total_used);
-	printf("Used      %10s  %10s  %10s  %10s\n",
-			b1,	b2,	b3,	b4);
-
-	store_size(b1, avg_waste);store_size(b2, min_waste);
-	store_size(b3, max_waste);store_size(b4, total_waste);
-	printf("Loss      %10s  %10s  %10s  %10s\n",
-			b1,	b2,	b3,	b4);
-
-	printf("\n");
-	printf("Per Object   Average         Min         Max\n");
-	printf("---------------------------------------------\n");
-
-	store_size(b1, avg_memobj);store_size(b2, min_memobj);
-	store_size(b3, max_memobj);
-	printf("Memory    %10s  %10s  %10s\n",
-			b1,	b2,	b3);
-	store_size(b1, avg_objsize);store_size(b2, min_objsize);
-	store_size(b3, max_objsize);
-	printf("User      %10s  %10s  %10s\n",
-			b1,	b2,	b3);
-
-	store_size(b1, avg_objwaste);store_size(b2, min_objwaste);
-	store_size(b3, max_objwaste);
-	printf("Loss      %10s  %10s  %10s\n",
-			b1,	b2,	b3);
-}
-
-static void sort_slabs(void)
-{
-	struct slabinfo *s1,*s2;
-
-	for (s1 = slabinfo; s1 < slabinfo + slabs; s1++) {
-		for (s2 = s1 + 1; s2 < slabinfo + slabs; s2++) {
-			int result;
-
-			if (sort_size)
-				result = slab_size(s1) < slab_size(s2);
-			else if (sort_active)
-				result = slab_activity(s1) < slab_activity(s2);
-			else
-				result = strcasecmp(s1->name, s2->name);
-
-			if (show_inverted)
-				result = -result;
-
-			if (result > 0) {
-				struct slabinfo t;
-
-				memcpy(&t, s1, sizeof(struct slabinfo));
-				memcpy(s1, s2, sizeof(struct slabinfo));
-				memcpy(s2, &t, sizeof(struct slabinfo));
-			}
-		}
-	}
-}
-
-static void sort_aliases(void)
-{
-	struct aliasinfo *a1,*a2;
-
-	for (a1 = aliasinfo; a1 < aliasinfo + aliases; a1++) {
-		for (a2 = a1 + 1; a2 < aliasinfo + aliases; a2++) {
-			char *n1, *n2;
-
-			n1 = a1->name;
-			n2 = a2->name;
-			if (show_alias && !show_inverted) {
-				n1 = a1->ref;
-				n2 = a2->ref;
-			}
-			if (strcasecmp(n1, n2) > 0) {
-				struct aliasinfo t;
-
-				memcpy(&t, a1, sizeof(struct aliasinfo));
-				memcpy(a1, a2, sizeof(struct aliasinfo));
-				memcpy(a2, &t, sizeof(struct aliasinfo));
-			}
-		}
-	}
-}
-
-static void link_slabs(void)
-{
-	struct aliasinfo *a;
-	struct slabinfo *s;
-
-	for (a = aliasinfo; a < aliasinfo + aliases; a++) {
-
-		for (s = slabinfo; s < slabinfo + slabs; s++)
-			if (strcmp(a->ref, s->name) == 0) {
-				a->slab = s;
-				s->refs++;
-				break;
-			}
-		if (s == slabinfo + slabs)
-			fatal("Unresolved alias %s\n", a->ref);
-	}
-}
-
-static void alias(void)
-{
-	struct aliasinfo *a;
-	char *active = NULL;
-
-	sort_aliases();
-	link_slabs();
-
-	for(a = aliasinfo; a < aliasinfo + aliases; a++) {
-
-		if (!show_single_ref && a->slab->refs == 1)
-			continue;
-
-		if (!show_inverted) {
-			if (active) {
-				if (strcmp(a->slab->name, active) == 0) {
-					printf(" %s", a->name);
-					continue;
-				}
-			}
-			printf("\n%-12s <- %s", a->slab->name, a->name);
-			active = a->slab->name;
-		}
-		else
-			printf("%-20s -> %s\n", a->name, a->slab->name);
-	}
-	if (active)
-		printf("\n");
-}
-
-
-static void rename_slabs(void)
-{
-	struct slabinfo *s;
-	struct aliasinfo *a;
-
-	for (s = slabinfo; s < slabinfo + slabs; s++) {
-		if (*s->name != ':')
-			continue;
-
-		if (s->refs > 1 && !show_first_alias)
-			continue;
-
-		a = find_one_alias(s);
-
-		if (a)
-			s->name = a->name;
-		else {
-			s->name = "*";
-			actual_slabs--;
-		}
-	}
-}
-
-static int slab_mismatch(char *slab)
-{
-	return regexec(&pattern, slab, 0, NULL, 0);
-}
-
-static void read_slab_dir(void)
-{
-	DIR *dir;
-	struct dirent *de;
-	struct slabinfo *slab = slabinfo;
-	struct aliasinfo *alias = aliasinfo;
-	char *p;
-	char *t;
-	int count;
-
-	if (chdir("/sys/kernel/slab") && chdir("/sys/slab"))
-		fatal("SYSFS support for SLUB not active\n");
-
-	dir = opendir(".");
-	while ((de = readdir(dir))) {
-		if (de->d_name[0] == '.' ||
-			(de->d_name[0] != ':' && slab_mismatch(de->d_name)))
-				continue;
-		switch (de->d_type) {
-		   case DT_LNK:
-		   	alias->name = strdup(de->d_name);
-			count = readlink(de->d_name, buffer, sizeof(buffer));
-
-			if (count < 0)
-				fatal("Cannot read symlink %s\n", de->d_name);
-
-			buffer[count] = 0;
-			p = buffer + count;
-			while (p > buffer && p[-1] != '/')
-				p--;
-			alias->ref = strdup(p);
-			alias++;
-			break;
-		   case DT_DIR:
-			if (chdir(de->d_name))
-				fatal("Unable to access slab %s\n", slab->name);
-		   	slab->name = strdup(de->d_name);
-			slab->alias = 0;
-			slab->refs = 0;
-			slab->aliases = get_obj("aliases");
-			slab->align = get_obj("align");
-			slab->cache_dma = get_obj("cache_dma");
-			slab->cpu_slabs = get_obj("cpu_slabs");
-			slab->destroy_by_rcu = get_obj("destroy_by_rcu");
-			slab->hwcache_align = get_obj("hwcache_align");
-			slab->object_size = get_obj("object_size");
-			slab->objects = get_obj("objects");
-			slab->objects_partial = get_obj("objects_partial");
-			slab->objects_total = get_obj("objects_total");
-			slab->objs_per_slab = get_obj("objs_per_slab");
-			slab->order = get_obj("order");
-			slab->partial = get_obj("partial");
-			slab->partial = get_obj_and_str("partial", &t);
-			decode_numa_list(slab->numa_partial, t);
-			free(t);
-			slab->poison = get_obj("poison");
-			slab->reclaim_account = get_obj("reclaim_account");
-			slab->red_zone = get_obj("red_zone");
-			slab->sanity_checks = get_obj("sanity_checks");
-			slab->slab_size = get_obj("slab_size");
-			slab->slabs = get_obj_and_str("slabs", &t);
-			decode_numa_list(slab->numa, t);
-			free(t);
-			slab->store_user = get_obj("store_user");
-			slab->trace = get_obj("trace");
-			slab->alloc_fastpath = get_obj("alloc_fastpath");
-			slab->alloc_slowpath = get_obj("alloc_slowpath");
-			slab->free_fastpath = get_obj("free_fastpath");
-			slab->free_slowpath = get_obj("free_slowpath");
-			slab->free_frozen= get_obj("free_frozen");
-			slab->free_add_partial = get_obj("free_add_partial");
-			slab->free_remove_partial = get_obj("free_remove_partial");
-			slab->alloc_from_partial = get_obj("alloc_from_partial");
-			slab->alloc_slab = get_obj("alloc_slab");
-			slab->alloc_refill = get_obj("alloc_refill");
-			slab->free_slab = get_obj("free_slab");
-			slab->cpuslab_flush = get_obj("cpuslab_flush");
-			slab->deactivate_full = get_obj("deactivate_full");
-			slab->deactivate_empty = get_obj("deactivate_empty");
-			slab->deactivate_to_head = get_obj("deactivate_to_head");
-			slab->deactivate_to_tail = get_obj("deactivate_to_tail");
-			slab->deactivate_remote_frees = get_obj("deactivate_remote_frees");
-			slab->order_fallback = get_obj("order_fallback");
-			chdir("..");
-			if (slab->name[0] == ':')
-				alias_targets++;
-			slab++;
-			break;
-		   default :
-			fatal("Unknown file type %lx\n", de->d_type);
-		}
-	}
-	closedir(dir);
-	slabs = slab - slabinfo;
-	actual_slabs = slabs;
-	aliases = alias - aliasinfo;
-	if (slabs > MAX_SLABS)
-		fatal("Too many slabs\n");
-	if (aliases > MAX_ALIASES)
-		fatal("Too many aliases\n");
-}
-
-static void output_slabs(void)
-{
-	struct slabinfo *slab;
-
-	for (slab = slabinfo; slab < slabinfo + slabs; slab++) {
-
-		if (slab->alias)
-			continue;
-
-
-		if (show_numa)
-			slab_numa(slab, 0);
-		else if (show_track)
-			show_tracking(slab);
-		else if (validate)
-			slab_validate(slab);
-		else if (shrink)
-			slab_shrink(slab);
-		else if (set_debug)
-			slab_debug(slab);
-		else if (show_ops)
-			ops(slab);
-		else if (show_slab)
-			slabcache(slab);
-		else if (show_report)
-			report(slab);
-	}
-}
-
-struct option opts[] = {
-	{ "aliases", 0, NULL, 'a' },
-	{ "activity", 0, NULL, 'A' },
-	{ "debug", 2, NULL, 'd' },
-	{ "display-activity", 0, NULL, 'D' },
-	{ "empty", 0, NULL, 'e' },
-	{ "first-alias", 0, NULL, 'f' },
-	{ "help", 0, NULL, 'h' },
-	{ "inverted", 0, NULL, 'i'},
-	{ "numa", 0, NULL, 'n' },
-	{ "ops", 0, NULL, 'o' },
-	{ "report", 0, NULL, 'r' },
-	{ "shrink", 0, NULL, 's' },
-	{ "slabs", 0, NULL, 'l' },
-	{ "track", 0, NULL, 't'},
-	{ "validate", 0, NULL, 'v' },
-	{ "zero", 0, NULL, 'z' },
-	{ "1ref", 0, NULL, '1'},
-	{ NULL, 0, NULL, 0 }
-};
-
-int main(int argc, char *argv[])
-{
-	int c;
-	int err;
-	char *pattern_source;
-
-	page_size = getpagesize();
-
-	while ((c = getopt_long(argc, argv, "aAd::Defhil1noprstvzTS",
-						opts, NULL)) != -1)
-		switch (c) {
-		case '1':
-			show_single_ref = 1;
-			break;
-		case 'a':
-			show_alias = 1;
-			break;
-		case 'A':
-			sort_active = 1;
-			break;
-		case 'd':
-			set_debug = 1;
-			if (!debug_opt_scan(optarg))
-				fatal("Invalid debug option '%s'\n", optarg);
-			break;
-		case 'D':
-			show_activity = 1;
-			break;
-		case 'e':
-			show_empty = 1;
-			break;
-		case 'f':
-			show_first_alias = 1;
-			break;
-		case 'h':
-			usage();
-			return 0;
-		case 'i':
-			show_inverted = 1;
-			break;
-		case 'n':
-			show_numa = 1;
-			break;
-		case 'o':
-			show_ops = 1;
-			break;
-		case 'r':
-			show_report = 1;
-			break;
-		case 's':
-			shrink = 1;
-			break;
-		case 'l':
-			show_slab = 1;
-			break;
-		case 't':
-			show_track = 1;
-			break;
-		case 'v':
-			validate = 1;
-			break;
-		case 'z':
-			skip_zero = 0;
-			break;
-		case 'T':
-			show_totals = 1;
-			break;
-		case 'S':
-			sort_size = 1;
-			break;
-
-		default:
-			fatal("%s: Invalid option '%c'\n", argv[0], optopt);
-
-	}
-
-	if (!show_slab && !show_alias && !show_track && !show_report
-		&& !validate && !shrink && !set_debug && !show_ops)
-			show_slab = 1;
-
-	if (argc > optind)
-		pattern_source = argv[optind];
-	else
-		pattern_source = ".*";
-
-	err = regcomp(&pattern, pattern_source, REG_ICASE|REG_NOSUB);
-	if (err)
-		fatal("%s: Invalid pattern '%s' code %d\n",
-			argv[0], pattern_source, err);
-	read_slab_dir();
-	if (show_alias)
-		alias();
-	else
-	if (show_totals)
-		totals();
-	else {
-		link_slabs();
-		rename_slabs();
-		sort_slabs();
-		output_slabs();
-	}
-	return 0;
-}
diff -druNp linux-libre-2.6.37-gnu1/Documentation/vm/transhuge.txt linux-libre-2.6.38-gnu1/Documentation/vm/transhuge.txt
--- linux-libre-2.6.37-gnu1/Documentation/vm/transhuge.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/vm/transhuge.txt	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,298 @@
+= Transparent Hugepage Support =
+
+== Objective ==
+
+Performance critical computing applications dealing with large memory
+working sets are already running on top of libhugetlbfs and in turn
+hugetlbfs. Transparent Hugepage Support is an alternative means of
+using huge pages for the backing of virtual memory with huge pages
+that supports the automatic promotion and demotion of page sizes and
+without the shortcomings of hugetlbfs.
+
+Currently it only works for anonymous memory mappings but in the
+future it can expand over the pagecache layer starting with tmpfs.
+
+The reason applications are running faster is because of two
+factors. The first factor is almost completely irrelevant and it's not
+of significant interest because it'll also have the downside of
+requiring larger clear-page copy-page in page faults which is a
+potentially negative effect. The first factor consists in taking a
+single page fault for each 2M virtual region touched by userland (so
+reducing the enter/exit kernel frequency by a 512 times factor). This
+only matters the first time the memory is accessed for the lifetime of
+a memory mapping. The second long lasting and much more important
+factor will affect all subsequent accesses to the memory for the whole
+runtime of the application. The second factor consist of two
+components: 1) the TLB miss will run faster (especially with
+virtualization using nested pagetables but almost always also on bare
+metal without virtualization) and 2) a single TLB entry will be
+mapping a much larger amount of virtual memory in turn reducing the
+number of TLB misses. With virtualization and nested pagetables the
+TLB can be mapped of larger size only if both KVM and the Linux guest
+are using hugepages but a significant speedup already happens if only
+one of the two is using hugepages just because of the fact the TLB
+miss is going to run faster.
+
+== Design ==
+
+- "graceful fallback": mm components which don't have transparent
+  hugepage knowledge fall back to breaking a transparent hugepage and
+  working on the regular pages and their respective regular pmd/pte
+  mappings
+
+- if a hugepage allocation fails because of memory fragmentation,
+  regular pages should be gracefully allocated instead and mixed in
+  the same vma without any failure or significant delay and without
+  userland noticing
+
+- if some task quits and more hugepages become available (either
+  immediately in the buddy or through the VM), guest physical memory
+  backed by regular pages should be relocated on hugepages
+  automatically (with khugepaged)
+
+- it doesn't require memory reservation and in turn it uses hugepages
+  whenever possible (the only possible reservation here is kernelcore=
+  to avoid unmovable pages to fragment all the memory but such a tweak
+  is not specific to transparent hugepage support and it's a generic
+  feature that applies to all dynamic high order allocations in the
+  kernel)
+
+- this initial support only offers the feature in the anonymous memory
+  regions but it'd be ideal to move it to tmpfs and the pagecache
+  later
+
+Transparent Hugepage Support maximizes the usefulness of free memory
+if compared to the reservation approach of hugetlbfs by allowing all
+unused memory to be used as cache or other movable (or even unmovable
+entities). It doesn't require reservation to prevent hugepage
+allocation failures to be noticeable from userland. It allows paging
+and all other advanced VM features to be available on the
+hugepages. It requires no modifications for applications to take
+advantage of it.
+
+Applications however can be further optimized to take advantage of
+this feature, like for example they've been optimized before to avoid
+a flood of mmap system calls for every malloc(4k). Optimizing userland
+is by far not mandatory and khugepaged already can take care of long
+lived page allocations even for hugepage unaware applications that
+deals with large amounts of memory.
+
+In certain cases when hugepages are enabled system wide, application
+may end up allocating more memory resources. An application may mmap a
+large region but only touch 1 byte of it, in that case a 2M page might
+be allocated instead of a 4k page for no good. This is why it's
+possible to disable hugepages system-wide and to only have them inside
+MADV_HUGEPAGE madvise regions.
+
+Embedded systems should enable hugepages only inside madvise regions
+to eliminate any risk of wasting any precious byte of memory and to
+only run faster.
+
+Applications that gets a lot of benefit from hugepages and that don't
+risk to lose memory by using hugepages, should use
+madvise(MADV_HUGEPAGE) on their critical mmapped regions.
+
+== sysfs ==
+
+Transparent Hugepage Support can be entirely disabled (mostly for
+debugging purposes) or only enabled inside MADV_HUGEPAGE regions (to
+avoid the risk of consuming more memory resources) or enabled system
+wide. This can be achieved with one of:
+
+echo always >/sys/kernel/mm/transparent_hugepage/enabled
+echo madvise >/sys/kernel/mm/transparent_hugepage/enabled
+echo never >/sys/kernel/mm/transparent_hugepage/enabled
+
+It's also possible to limit defrag efforts in the VM to generate
+hugepages in case they're not immediately free to madvise regions or
+to never try to defrag memory and simply fallback to regular pages
+unless hugepages are immediately available. Clearly if we spend CPU
+time to defrag memory, we would expect to gain even more by the fact
+we use hugepages later instead of regular pages. This isn't always
+guaranteed, but it may be more likely in case the allocation is for a
+MADV_HUGEPAGE region.
+
+echo always >/sys/kernel/mm/transparent_hugepage/defrag
+echo madvise >/sys/kernel/mm/transparent_hugepage/defrag
+echo never >/sys/kernel/mm/transparent_hugepage/defrag
+
+khugepaged will be automatically started when
+transparent_hugepage/enabled is set to "always" or "madvise, and it'll
+be automatically shutdown if it's set to "never".
+
+khugepaged runs usually at low frequency so while one may not want to
+invoke defrag algorithms synchronously during the page faults, it
+should be worth invoking defrag at least in khugepaged. However it's
+also possible to disable defrag in khugepaged:
+
+echo yes >/sys/kernel/mm/transparent_hugepage/khugepaged/defrag
+echo no >/sys/kernel/mm/transparent_hugepage/khugepaged/defrag
+
+You can also control how many pages khugepaged should scan at each
+pass:
+
+/sys/kernel/mm/transparent_hugepage/khugepaged/pages_to_scan
+
+and how many milliseconds to wait in khugepaged between each pass (you
+can set this to 0 to run khugepaged at 100% utilization of one core):
+
+/sys/kernel/mm/transparent_hugepage/khugepaged/scan_sleep_millisecs
+
+and how many milliseconds to wait in khugepaged if there's an hugepage
+allocation failure to throttle the next allocation attempt.
+
+/sys/kernel/mm/transparent_hugepage/khugepaged/alloc_sleep_millisecs
+
+The khugepaged progress can be seen in the number of pages collapsed:
+
+/sys/kernel/mm/transparent_hugepage/khugepaged/pages_collapsed
+
+for each pass:
+
+/sys/kernel/mm/transparent_hugepage/khugepaged/full_scans
+
+== Boot parameter ==
+
+You can change the sysfs boot time defaults of Transparent Hugepage
+Support by passing the parameter "transparent_hugepage=always" or
+"transparent_hugepage=madvise" or "transparent_hugepage=never"
+(without "") to the kernel command line.
+
+== Need of application restart ==
+
+The transparent_hugepage/enabled values only affect future
+behavior. So to make them effective you need to restart any
+application that could have been using hugepages. This also applies to
+the regions registered in khugepaged.
+
+== get_user_pages and follow_page ==
+
+get_user_pages and follow_page if run on a hugepage, will return the
+head or tail pages as usual (exactly as they would do on
+hugetlbfs). Most gup users will only care about the actual physical
+address of the page and its temporary pinning to release after the I/O
+is complete, so they won't ever notice the fact the page is huge. But
+if any driver is going to mangle over the page structure of the tail
+page (like for checking page->mapping or other bits that are relevant
+for the head page and not the tail page), it should be updated to jump
+to check head page instead (while serializing properly against
+split_huge_page() to avoid the head and tail pages to disappear from
+under it, see the futex code to see an example of that, hugetlbfs also
+needed special handling in futex code for similar reasons).
+
+NOTE: these aren't new constraints to the GUP API, and they match the
+same constrains that applies to hugetlbfs too, so any driver capable
+of handling GUP on hugetlbfs will also work fine on transparent
+hugepage backed mappings.
+
+In case you can't handle compound pages if they're returned by
+follow_page, the FOLL_SPLIT bit can be specified as parameter to
+follow_page, so that it will split the hugepages before returning
+them. Migration for example passes FOLL_SPLIT as parameter to
+follow_page because it's not hugepage aware and in fact it can't work
+at all on hugetlbfs (but it instead works fine on transparent
+hugepages thanks to FOLL_SPLIT). migration simply can't deal with
+hugepages being returned (as it's not only checking the pfn of the
+page and pinning it during the copy but it pretends to migrate the
+memory in regular page sizes and with regular pte/pmd mappings).
+
+== Optimizing the applications ==
+
+To be guaranteed that the kernel will map a 2M page immediately in any
+memory region, the mmap region has to be hugepage naturally
+aligned. posix_memalign() can provide that guarantee.
+
+== Hugetlbfs ==
+
+You can use hugetlbfs on a kernel that has transparent hugepage
+support enabled just fine as always. No difference can be noted in
+hugetlbfs other than there will be less overall fragmentation. All
+usual features belonging to hugetlbfs are preserved and
+unaffected. libhugetlbfs will also work fine as usual.
+
+== Graceful fallback ==
+
+Code walking pagetables but unware about huge pmds can simply call
+split_huge_page_pmd(mm, pmd) where the pmd is the one returned by
+pmd_offset. It's trivial to make the code transparent hugepage aware
+by just grepping for "pmd_offset" and adding split_huge_page_pmd where
+missing after pmd_offset returns the pmd. Thanks to the graceful
+fallback design, with a one liner change, you can avoid to write
+hundred if not thousand of lines of complex code to make your code
+hugepage aware.
+
+If you're not walking pagetables but you run into a physical hugepage
+but you can't handle it natively in your code, you can split it by
+calling split_huge_page(page). This is what the Linux VM does before
+it tries to swapout the hugepage for example.
+
+Example to make mremap.c transparent hugepage aware with a one liner
+change:
+
+diff --git a/mm/mremap.c b/mm/mremap.c
+--- a/mm/mremap.c
++++ b/mm/mremap.c
+@@ -41,6 +41,7 @@ static pmd_t *get_old_pmd(struct mm_stru
+		return NULL;
+
+	pmd = pmd_offset(pud, addr);
++	split_huge_page_pmd(mm, pmd);
+	if (pmd_none_or_clear_bad(pmd))
+		return NULL;
+
+== Locking in hugepage aware code ==
+
+We want as much code as possible hugepage aware, as calling
+split_huge_page() or split_huge_page_pmd() has a cost.
+
+To make pagetable walks huge pmd aware, all you need to do is to call
+pmd_trans_huge() on the pmd returned by pmd_offset. You must hold the
+mmap_sem in read (or write) mode to be sure an huge pmd cannot be
+created from under you by khugepaged (khugepaged collapse_huge_page
+takes the mmap_sem in write mode in addition to the anon_vma lock). If
+pmd_trans_huge returns false, you just fallback in the old code
+paths. If instead pmd_trans_huge returns true, you have to take the
+mm->page_table_lock and re-run pmd_trans_huge. Taking the
+page_table_lock will prevent the huge pmd to be converted into a
+regular pmd from under you (split_huge_page can run in parallel to the
+pagetable walk). If the second pmd_trans_huge returns false, you
+should just drop the page_table_lock and fallback to the old code as
+before. Otherwise you should run pmd_trans_splitting on the pmd. In
+case pmd_trans_splitting returns true, it means split_huge_page is
+already in the middle of splitting the page. So if pmd_trans_splitting
+returns true it's enough to drop the page_table_lock and call
+wait_split_huge_page and then fallback the old code paths. You are
+guaranteed by the time wait_split_huge_page returns, the pmd isn't
+huge anymore. If pmd_trans_splitting returns false, you can proceed to
+process the huge pmd and the hugepage natively. Once finished you can
+drop the page_table_lock.
+
+== compound_lock, get_user_pages and put_page ==
+
+split_huge_page internally has to distribute the refcounts in the head
+page to the tail pages before clearing all PG_head/tail bits from the
+page structures. It can do that easily for refcounts taken by huge pmd
+mappings. But the GUI API as created by hugetlbfs (that returns head
+and tail pages if running get_user_pages on an address backed by any
+hugepage), requires the refcount to be accounted on the tail pages and
+not only in the head pages, if we want to be able to run
+split_huge_page while there are gup pins established on any tail
+page. Failure to be able to run split_huge_page if there's any gup pin
+on any tail page, would mean having to split all hugepages upfront in
+get_user_pages which is unacceptable as too many gup users are
+performance critical and they must work natively on hugepages like
+they work natively on hugetlbfs already (hugetlbfs is simpler because
+hugetlbfs pages cannot be splitted so there wouldn't be requirement of
+accounting the pins on the tail pages for hugetlbfs). If we wouldn't
+account the gup refcounts on the tail pages during gup, we won't know
+anymore which tail page is pinned by gup and which is not while we run
+split_huge_page. But we still have to add the gup pin to the head page
+too, to know when we can free the compound page in case it's never
+splitted during its lifetime. That requires changing not just
+get_page, but put_page as well so that when put_page runs on a tail
+page (and only on a tail page) it will find its respective head page,
+and then it will decrease the head page refcount in addition to the
+tail page refcount. To obtain a head page reliably and to decrease its
+refcount without race conditions, put_page has to serialize against
+__split_huge_page_refcount using a special per-page lock called
+compound_lock.
diff -druNp linux-libre-2.6.37-gnu1/Documentation/w1/slaves/00-INDEX linux-libre-2.6.38-gnu1/Documentation/w1/slaves/00-INDEX
--- linux-libre-2.6.37-gnu1/Documentation/w1/slaves/00-INDEX	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/w1/slaves/00-INDEX	2011-03-14 21:20:32.000000000 -0400
@@ -2,3 +2,5 @@
 	- This file
 w1_therm
 	- The Maxim/Dallas Semiconductor ds18*20 temperature sensor.
+w1_ds2423
+	- The Maxim/Dallas Semiconductor ds2423 counter device.
diff -druNp linux-libre-2.6.37-gnu1/Documentation/w1/slaves/w1_ds2423 linux-libre-2.6.38-gnu1/Documentation/w1/slaves/w1_ds2423
--- linux-libre-2.6.37-gnu1/Documentation/w1/slaves/w1_ds2423	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/w1/slaves/w1_ds2423	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,47 @@
+Kernel driver w1_ds2423
+=======================
+
+Supported chips:
+  * Maxim DS2423 based counter devices.
+
+supported family codes:
+	W1_THERM_DS2423	0x1D
+
+Author: Mika Laitio <lamikr@pilppa.org>
+
+Description
+-----------
+
+Support is provided through the sysfs w1_slave file. Each opening and
+read sequence of w1_slave file initiates the read of counters and ram
+available in DS2423 pages 12 - 15.
+
+Result of each page is provided as an ASCII output where each counter
+value and associated ram buffer is outpputed to own line.
+
+Each lines will contain the values of 42 bytes read from the counter and
+memory page along the crc=YES or NO for indicating whether the read operation
+was successfull and CRC matched.
+If the operation was successfull, there is also in the end of each line
+a counter value expressed as an integer after c=
+
+Meaning of 42 bytes represented is following:
+ - 1 byte from ram page
+ - 4 bytes for the counter value
+ - 4 zero bytes
+ - 2 bytes for crc16 which was calculated from the data read since the previous crc bytes
+ - 31 remaining bytes from the ram page
+ - crc=YES/NO indicating whether read was ok and crc matched
+ - c=<int> current counter value
+
+example from the successfull read:
+00 02 00 00 00 00 00 00 00 6d 38 00 ff ff 00 00 fe ff 00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff crc=YES c=2
+00 02 00 00 00 00 00 00 00 e0 1f 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff crc=YES c=2
+00 29 c6 5d 18 00 00 00 00 04 37 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff crc=YES c=408798761
+00 05 00 00 00 00 00 00 00 8d 39 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff crc=YES c=5
+
+example from the read with crc errors:
+00 02 00 00 00 00 00 00 00 6d 38 00 ff ff 00 00 fe ff 00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff crc=YES c=2
+00 02 00 00 22 00 00 00 00 e0 1f 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff crc=NO
+00 e1 61 5d 19 00 00 00 00 df 0b 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff crc=NO
+00 05 00 00 20 00 00 00 00 8d 39 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff crc=NO
diff -druNp linux-libre-2.6.37-gnu1/Documentation/workqueue.txt linux-libre-2.6.38-gnu1/Documentation/workqueue.txt
--- linux-libre-2.6.37-gnu1/Documentation/workqueue.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/workqueue.txt	2011-03-14 21:20:32.000000000 -0400
@@ -190,9 +190,9 @@ resources, scheduled and executed.
 	* Long running CPU intensive workloads which can be better
 	  managed by the system scheduler.
 
-  WQ_FREEZEABLE
+  WQ_FREEZABLE
 
-	A freezeable wq participates in the freeze phase of the system
+	A freezable wq participates in the freeze phase of the system
 	suspend operations.  Work items on the wq are drained and no
 	new work item starts execution until thawed.
 
diff -druNp linux-libre-2.6.37-gnu1/Documentation/x86/boot.txt linux-libre-2.6.38-gnu1/Documentation/x86/boot.txt
--- linux-libre-2.6.37-gnu1/Documentation/x86/boot.txt	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/x86/boot.txt	2011-03-14 21:20:32.000000000 -0400
@@ -600,6 +600,7 @@ Protocol:	2.07+
   0x00000001	lguest
   0x00000002	Xen
   0x00000003	Moorestown MID
+  0x00000004	CE4100 TV Platform
 
 Field name:	hardware_subarch_data
 Type:		write (subarch-dependent)
@@ -621,9 +622,9 @@ Protocol:	2.08+
   The payload may be compressed. The format of both the compressed and
   uncompressed data should be determined using the standard magic
   numbers.  The currently supported compression formats are gzip
-  (magic numbers 1F 8B or 1F 9E), bzip2 (magic number 42 5A) and LZMA
-  (magic number 5D 00).  The uncompressed payload is currently always ELF
-  (magic number 7F 45 4C 46).
+  (magic numbers 1F 8B or 1F 9E), bzip2 (magic number 42 5A), LZMA
+  (magic number 5D 00), and XZ (magic number FD 37).  The uncompressed
+  payload is currently always ELF (magic number 7F 45 4C 46).
   
 Field name:	payload_length
 Type:		read
diff -druNp linux-libre-2.6.37-gnu1/Documentation/xz.txt linux-libre-2.6.38-gnu1/Documentation/xz.txt
--- linux-libre-2.6.37-gnu1/Documentation/xz.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/xz.txt	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,121 @@
+
+XZ data compression in Linux
+============================
+
+Introduction
+
+    XZ is a general purpose data compression format with high compression
+    ratio and relatively fast decompression. The primary compression
+    algorithm (filter) is LZMA2. Additional filters can be used to improve
+    compression ratio even further. E.g. Branch/Call/Jump (BCJ) filters
+    improve compression ratio of executable data.
+
+    The XZ decompressor in Linux is called XZ Embedded. It supports
+    the LZMA2 filter and optionally also BCJ filters. CRC32 is supported
+    for integrity checking. The home page of XZ Embedded is at
+    <http://tukaani.org/xz/embedded.html>, where you can find the
+    latest version and also information about using the code outside
+    the Linux kernel.
+
+    For userspace, XZ Utils provide a zlib-like compression library
+    and a gzip-like command line tool. XZ Utils can be downloaded from
+    <http://tukaani.org/xz/>.
+
+XZ related components in the kernel
+
+    The xz_dec module provides XZ decompressor with single-call (buffer
+    to buffer) and multi-call (stateful) APIs. The usage of the xz_dec
+    module is documented in include/linux/xz.h.
+
+    The xz_dec_test module is for testing xz_dec. xz_dec_test is not
+    useful unless you are hacking the XZ decompressor. xz_dec_test
+    allocates a char device major dynamically to which one can write
+    .xz files from userspace. The decompressed output is thrown away.
+    Keep an eye on dmesg to see diagnostics printed by xz_dec_test.
+    See the xz_dec_test source code for the details.
+
+    For decompressing the kernel image, initramfs, and initrd, there
+    is a wrapper function in lib/decompress_unxz.c. Its API is the
+    same as in other decompress_*.c files, which is defined in
+    include/linux/decompress/generic.h.
+
+    scripts/xz_wrap.sh is a wrapper for the xz command line tool found
+    from XZ Utils. The wrapper sets compression options to values suitable
+    for compressing the kernel image.
+
+    For kernel makefiles, two commands are provided for use with
+    $(call if_needed). The kernel image should be compressed with
+    $(call if_needed,xzkern) which will use a BCJ filter and a big LZMA2
+    dictionary. It will also append a four-byte trailer containing the
+    uncompressed size of the file, which is needed by the boot code.
+    Other things should be compressed with $(call if_needed,xzmisc)
+    which will use no BCJ filter and 1 MiB LZMA2 dictionary.
+
+Notes on compression options
+
+    Since the XZ Embedded supports only streams with no integrity check or
+    CRC32, make sure that you don't use some other integrity check type
+    when encoding files that are supposed to be decoded by the kernel. With
+    liblzma, you need to use either LZMA_CHECK_NONE or LZMA_CHECK_CRC32
+    when encoding. With the xz command line tool, use --check=none or
+    --check=crc32.
+
+    Using CRC32 is strongly recommended unless there is some other layer
+    which will verify the integrity of the uncompressed data anyway.
+    Double checking the integrity would probably be waste of CPU cycles.
+    Note that the headers will always have a CRC32 which will be validated
+    by the decoder; you can only change the integrity check type (or
+    disable it) for the actual uncompressed data.
+
+    In userspace, LZMA2 is typically used with dictionary sizes of several
+    megabytes. The decoder needs to have the dictionary in RAM, thus big
+    dictionaries cannot be used for files that are intended to be decoded
+    by the kernel. 1 MiB is probably the maximum reasonable dictionary
+    size for in-kernel use (maybe more is OK for initramfs). The presets
+    in XZ Utils may not be optimal when creating files for the kernel,
+    so don't hesitate to use custom settings. Example:
+
+        xz --check=crc32 --lzma2=dict=512KiB inputfile
+
+    An exception to above dictionary size limitation is when the decoder
+    is used in single-call mode. Decompressing the kernel itself is an
+    example of this situation. In single-call mode, the memory usage
+    doesn't depend on the dictionary size, and it is perfectly fine to
+    use a big dictionary: for maximum compression, the dictionary should
+    be at least as big as the uncompressed data itself.
+
+Future plans
+
+    Creating a limited XZ encoder may be considered if people think it is
+    useful. LZMA2 is slower to compress than e.g. Deflate or LZO even at
+    the fastest settings, so it isn't clear if LZMA2 encoder is wanted
+    into the kernel.
+
+    Support for limited random-access reading is planned for the
+    decompression code. I don't know if it could have any use in the
+    kernel, but I know that it would be useful in some embedded projects
+    outside the Linux kernel.
+
+Conformance to the .xz file format specification
+
+    There are a couple of corner cases where things have been simplified
+    at expense of detecting errors as early as possible. These should not
+    matter in practice all, since they don't cause security issues. But
+    it is good to know this if testing the code e.g. with the test files
+    from XZ Utils.
+
+Reporting bugs
+
+    Before reporting a bug, please check that it's not fixed already
+    at upstream. See <http://tukaani.org/xz/embedded.html> to get the
+    latest code.
+
+    Report bugs to <lasse.collin@tukaani.org> or visit #tukaani on
+    Freenode and talk to Larhzu. I don't actively read LKML or other
+    kernel-related mailing lists, so if there's something I should know,
+    you should email to me personally or use IRC.
+
+    Don't bother Igor Pavlov with questions about the XZ implementation
+    in the kernel or about XZ Utils. While these two implementations
+    include essential code that is directly based on Igor Pavlov's code,
+    these implementations aren't maintained nor supported by him.
diff -druNp linux-libre-2.6.37-gnu1/Documentation/zh_CN/HOWTO linux-libre-2.6.38-gnu1/Documentation/zh_CN/HOWTO
--- linux-libre-2.6.37-gnu1/Documentation/zh_CN/HOWTO	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/zh_CN/HOWTO	2011-03-14 21:20:32.000000000 -0400
@@ -347,8 +347,8 @@ 要尝试修改已知的bug，请访问h
 最新bug的通知，可以订阅bugme-new邮件列表（只有新的bug报告会被寄到这里）
 或者订阅bugme-janitor邮件列表（所有bugzilla的变动都会被寄到这里）。
 
-	http://lists.osdl.org/mailman/listinfo/bugme-new
-	http://lists.osdl.org/mailman/listinfo/bugme-janitors
+	https://lists.linux-foundation.org/mailman/listinfo/bugme-new
+	https://lists.linux-foundation.org/mailman/listinfo/bugme-janitors
 
 
 邮件列表
diff -druNp linux-libre-2.6.37-gnu1/Documentation/zh_CN/SubmittingDrivers linux-libre-2.6.38-gnu1/Documentation/zh_CN/SubmittingDrivers
--- linux-libre-2.6.37-gnu1/Documentation/zh_CN/SubmittingDrivers	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/Documentation/zh_CN/SubmittingDrivers	2011-03-14 21:20:32.000000000 -0400
@@ -61,7 +61,7 @@ Linux 2.4:
 Linux 2.6:
 	除了遵循和 2.4 版内核同样的规则外，你还需要在 linux-kernel 邮件
 	列表上跟踪最新的 API 变化。向 Linux 2.6 内核提交驱动的顶级联系人
-	是 Andrew Morton <akpm@osdl.org>。
+	是 Andrew Morton <akpm@linux-foundation.org>。
 
 决定设备驱动能否被接受的条件
 ----------------------------
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/ac.c linux-libre-2.6.38-gnu1/drivers/acpi/ac.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/ac.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/ac.c	2011-03-14 21:20:32.000000000 -0400
@@ -197,7 +197,8 @@ static int acpi_ac_add_fs(struct acpi_de
 {
 	struct proc_dir_entry *entry = NULL;
 
-
+	printk(KERN_WARNING PREFIX "Deprecated procfs I/F for AC is loaded,"
+			" please retry with CONFIG_ACPI_PROCFS_POWER cleared\n");
 	if (!acpi_device_dir(device)) {
 		acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
 						     acpi_ac_dir);
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/accommon.h linux-libre-2.6.38-gnu1/drivers/acpi/acpica/accommon.h
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/accommon.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/accommon.h	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/acconfig.h linux-libre-2.6.38-gnu1/drivers/acpi/acpica/acconfig.h
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/acconfig.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/acconfig.h	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/acdebug.h linux-libre-2.6.38-gnu1/drivers/acpi/acpica/acdebug.h
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/acdebug.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/acdebug.h	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/acdispat.h linux-libre-2.6.38-gnu1/drivers/acpi/acpica/acdispat.h
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/acdispat.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/acdispat.h	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/acevents.h linux-libre-2.6.38-gnu1/drivers/acpi/acpica/acevents.h
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/acevents.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/acevents.h	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -51,8 +51,6 @@ acpi_status acpi_ev_initialize_events(vo
 
 acpi_status acpi_ev_install_xrupt_handlers(void);
 
-acpi_status acpi_ev_install_fadt_gpes(void);
-
 u32 acpi_ev_fixed_event_detect(void);
 
 /*
@@ -82,9 +80,9 @@ acpi_ev_update_gpe_enable_mask(struct ac
 
 acpi_status acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info);
 
-acpi_status acpi_raw_enable_gpe(struct acpi_gpe_event_info *gpe_event_info);
+acpi_status acpi_ev_add_gpe_reference(struct acpi_gpe_event_info *gpe_event_info);
 
-acpi_status acpi_raw_disable_gpe(struct acpi_gpe_event_info *gpe_event_info);
+acpi_status acpi_ev_remove_gpe_reference(struct acpi_gpe_event_info *gpe_event_info);
 
 struct acpi_gpe_event_info *acpi_ev_get_gpe_event_info(acpi_handle gpe_device,
 						       u32 gpe_number);
@@ -93,6 +91,8 @@ struct acpi_gpe_event_info *acpi_ev_low_
 						     struct acpi_gpe_block_info
 						     *gpe_block);
 
+acpi_status acpi_ev_finish_gpe(struct acpi_gpe_event_info *gpe_event_info);
+
 /*
  * evgpeblk - Upper-level GPE block support
  */
@@ -107,12 +107,13 @@ acpi_ev_create_gpe_block(struct acpi_nam
 acpi_status
 acpi_ev_initialize_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
 			     struct acpi_gpe_block_info *gpe_block,
-			     void *ignored);
+			     void *context);
 
 acpi_status acpi_ev_delete_gpe_block(struct acpi_gpe_block_info *gpe_block);
 
 u32
-acpi_ev_gpe_dispatch(struct acpi_gpe_event_info *gpe_event_info,
+acpi_ev_gpe_dispatch(struct acpi_namespace_node *gpe_device,
+		     struct acpi_gpe_event_info *gpe_event_info,
 		     u32 gpe_number);
 
 /*
@@ -126,10 +127,6 @@ acpi_status
 acpi_ev_match_gpe_method(acpi_handle obj_handle,
 			 u32 level, void *context, void **return_value);
 
-acpi_status
-acpi_ev_match_prw_and_gpe(acpi_handle obj_handle,
-			  u32 level, void *context, void **return_value);
-
 /*
  * evgpeutil - GPE utilities
  */
@@ -138,6 +135,10 @@ acpi_ev_walk_gpe_list(acpi_gpe_callback
 
 u8 acpi_ev_valid_gpe_event(struct acpi_gpe_event_info *gpe_event_info);
 
+acpi_status
+acpi_ev_get_gpe_device(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
+		       struct acpi_gpe_block_info *gpe_block, void *context);
+
 struct acpi_gpe_xrupt_info *acpi_ev_get_gpe_xrupt_block(u32 interrupt_number);
 
 acpi_status acpi_ev_delete_gpe_xrupt(struct acpi_gpe_xrupt_info *gpe_xrupt);
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/acglobal.h linux-libre-2.6.38-gnu1/drivers/acpi/acpica/acglobal.h
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/acglobal.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/acglobal.h	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -146,6 +146,9 @@ u8 acpi_gbl_system_awake_and_running;
 
 extern u32 acpi_gbl_nesting_level;
 
+ACPI_EXTERN u32 acpi_gpe_count;
+ACPI_EXTERN u32 acpi_fixed_event_count[ACPI_NUM_FIXED_EVENTS];
+
 /* Support for dynamic control method tracing mechanism */
 
 ACPI_EXTERN u32 acpi_gbl_original_dbg_level;
@@ -225,8 +228,10 @@ ACPI_EXTERN u8 acpi_gbl_global_lock_pres
  */
 ACPI_EXTERN spinlock_t _acpi_gbl_gpe_lock;	/* For GPE data structs and registers */
 ACPI_EXTERN spinlock_t _acpi_gbl_hardware_lock;	/* For ACPI H/W except GPE registers */
+ACPI_EXTERN spinlock_t _acpi_ev_global_lock_pending_lock; /* For global lock */
 #define acpi_gbl_gpe_lock	&_acpi_gbl_gpe_lock
 #define acpi_gbl_hardware_lock	&_acpi_gbl_hardware_lock
+#define acpi_ev_global_lock_pending_lock &_acpi_ev_global_lock_pending_lock
 
 /*****************************************************************************
  *
@@ -370,7 +375,9 @@ ACPI_EXTERN struct acpi_fixed_event_hand
 ACPI_EXTERN struct acpi_gpe_xrupt_info *acpi_gbl_gpe_xrupt_list_head;
 ACPI_EXTERN struct acpi_gpe_block_info
 *acpi_gbl_gpe_fadt_blocks[ACPI_MAX_GPE_BLOCKS];
-ACPI_EXTERN u8 acpi_all_gpes_initialized;
+ACPI_EXTERN u8 acpi_gbl_all_gpes_initialized;
+ACPI_EXTERN ACPI_GBL_EVENT_HANDLER acpi_gbl_global_event_handler;
+ACPI_EXTERN void *acpi_gbl_global_event_handler_context;
 
 /*****************************************************************************
  *
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/achware.h linux-libre-2.6.38-gnu1/drivers/acpi/acpica/achware.h
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/achware.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/achware.h	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -94,7 +94,7 @@ u32 acpi_hw_get_gpe_register_bit(struct
 			     struct acpi_gpe_register_info *gpe_register_info);
 
 acpi_status
-acpi_hw_low_set_gpe(struct acpi_gpe_event_info *gpe_event_info, u8 action);
+acpi_hw_low_set_gpe(struct acpi_gpe_event_info *gpe_event_info, u32 action);
 
 acpi_status
 acpi_hw_disable_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/acinterp.h linux-libre-2.6.38-gnu1/drivers/acpi/acpica/acinterp.h
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/acinterp.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/acinterp.h	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/aclocal.h linux-libre-2.6.38-gnu1/drivers/acpi/acpica/aclocal.h
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/aclocal.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/aclocal.h	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -408,17 +408,23 @@ struct acpi_predefined_data {
 
 /* Dispatch info for each GPE -- either a method or handler, cannot be both */
 
-struct acpi_handler_info {
-	acpi_event_handler address;	/* Address of handler, if any */
+struct acpi_gpe_handler_info {
+	acpi_gpe_handler address;	/* Address of handler, if any */
 	void *context;		/* Context to be passed to handler */
 	struct acpi_namespace_node *method_node;	/* Method node for this GPE level (saved) */
-	u8 orig_flags;		/* Original misc info about this GPE */
-	u8 orig_enabled;	/* Set if the GPE was originally enabled */
+	u8 original_flags;      /* Original (pre-handler) GPE info */
+	u8 originally_enabled;  /* True if GPE was originally enabled */
+};
+
+struct acpi_gpe_notify_object {
+	struct acpi_namespace_node *node;
+	struct acpi_gpe_notify_object *next;
 };
 
 union acpi_gpe_dispatch_info {
 	struct acpi_namespace_node *method_node;	/* Method node for this GPE level */
-	struct acpi_handler_info *handler;
+	struct acpi_gpe_handler_info *handler;  /* Installed GPE handler */
+	struct acpi_gpe_notify_object device;   /* List of _PRW devices for implicit notify */
 };
 
 /*
@@ -458,7 +464,7 @@ struct acpi_gpe_block_info {
 	u32 register_count;	/* Number of register pairs in block */
 	u16 gpe_count;		/* Number of individual GPEs in block */
 	u8 block_base_number;	/* Base GPE number for this block */
-	u8 initialized;         /* If set, the GPE block has been initialized */
+	u8 initialized;         /* TRUE if this block is initialized */
 };
 
 /* Information about GPE interrupt handlers, one per each interrupt level used for GPEs */
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/acmacros.h linux-libre-2.6.38-gnu1/drivers/acpi/acpica/acmacros.h
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/acmacros.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/acmacros.h	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/acnamesp.h linux-libre-2.6.38-gnu1/drivers/acpi/acpica/acnamesp.h
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/acnamesp.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/acnamesp.h	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/acobject.h linux-libre-2.6.38-gnu1/drivers/acpi/acpica/acobject.h
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/acobject.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/acobject.h	2011-03-14 21:20:32.000000000 -0400
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -93,12 +93,10 @@
 
 #define AOPOBJ_AML_CONSTANT         0x01	/* Integer is an AML constant */
 #define AOPOBJ_STATIC_POINTER       0x02	/* Data is part of an ACPI table, don't delete */
-#define AOPOBJ_DATA_VALID           0x04	/* Object is intialized and data is valid */
+#define AOPOBJ_DATA_VALID           0x04	/* Object is initialized and data is valid */
 #define AOPOBJ_OBJECT_INITIALIZED   0x08	/* Region is initialized, _REG was run */
 #define AOPOBJ_SETUP_COMPLETE       0x10	/* Region setup is complete */
 #define AOPOBJ_INVALID              0x20	/* Host OS won't allow a Region address */
-#define AOPOBJ_MODULE_LEVEL         0x40	/* Method is actually module-level code */
-#define AOPOBJ_MODIFIED_NAMESPACE   0x80	/* Method modified the namespace */
 
 /******************************************************************************
  *
@@ -175,7 +173,7 @@ struct acpi_object_region {
 };
 
 struct acpi_object_method {
-	ACPI_OBJECT_COMMON_HEADER u8 method_flags;
+	ACPI_OBJECT_COMMON_HEADER u8 info_flags;
 	u8 param_count;
 	u8 sync_level;
 	union acpi_operand_object *mutex;
@@ -183,13 +181,21 @@ struct acpi_object_method {
 	union {
 		ACPI_INTERNAL_METHOD implementation;
 		union acpi_operand_object *handler;
-	} extra;
+	} dispatch;
 
 	u32 aml_length;
 	u8 thread_count;
 	acpi_owner_id owner_id;
 };
 
+/* Flags for info_flags field above */
+
+#define ACPI_METHOD_MODULE_LEVEL        0x01	/* Method is actually module-level code */
+#define ACPI_METHOD_INTERNAL_ONLY       0x02	/* Method is implemented internally (_OSI) */
+#define ACPI_METHOD_SERIALIZED          0x04	/* Method is serialized */
+#define ACPI_METHOD_SERIALIZED_PENDING  0x08	/* Method is to be marked serialized */
+#define ACPI_METHOD_MODIFIED_NAMESPACE  0x10	/* Method modified the namespace */
+
 /******************************************************************************
  *
  * Objects that can be notified.  All share a common notify_info area.
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/acopcode.h linux-libre-2.6.38-gnu1/drivers/acpi/acpica/acopcode.h
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/acopcode.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/acopcode.h	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/acparser.h linux-libre-2.6.38-gnu1/drivers/acpi/acpica/acparser.h
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/acparser.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/acparser.h	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/acpredef.h linux-libre-2.6.38-gnu1/drivers/acpi/acpica/acpredef.h
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/acpredef.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/acpredef.h	2011-03-14 21:20:32.000000000 -0400
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/acresrc.h linux-libre-2.6.38-gnu1/drivers/acpi/acpica/acresrc.h
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/acresrc.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/acresrc.h	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/acstruct.h linux-libre-2.6.38-gnu1/drivers/acpi/acpica/acstruct.h
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/acstruct.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/acstruct.h	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/actables.h linux-libre-2.6.38-gnu1/drivers/acpi/acpica/actables.h
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/actables.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/actables.h	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/acutils.h linux-libre-2.6.38-gnu1/drivers/acpi/acpica/acutils.h
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/acutils.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/acutils.h	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/amlcode.h linux-libre-2.6.38-gnu1/drivers/acpi/acpica/amlcode.h
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/amlcode.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/amlcode.h	2011-03-14 21:20:32.000000000 -0400
@@ -7,7 +7,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -480,16 +480,10 @@ typedef enum {
 	AML_FIELD_ATTRIB_SMB_BLOCK_CALL = 0x0D
 } AML_ACCESS_ATTRIBUTE;
 
-/* Bit fields in method_flags byte */
+/* Bit fields in the AML method_flags byte */
 
 #define AML_METHOD_ARG_COUNT        0x07
 #define AML_METHOD_SERIALIZED       0x08
 #define AML_METHOD_SYNC_LEVEL       0xF0
 
-/* METHOD_FLAGS_ARG_COUNT is not used internally, define additional flags */
-
-#define AML_METHOD_INTERNAL_ONLY    0x01
-#define AML_METHOD_RESERVED1        0x02
-#define AML_METHOD_RESERVED2        0x04
-
 #endif				/* __AMLCODE_H__ */
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/amlresrc.h linux-libre-2.6.38-gnu1/drivers/acpi/acpica/amlresrc.h
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/amlresrc.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/amlresrc.h	2011-03-14 21:20:32.000000000 -0400
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/dsfield.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/dsfield.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/dsfield.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/dsfield.c	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/dsinit.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/dsinit.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/dsinit.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/dsinit.c	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/dsmethod.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/dsmethod.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/dsmethod.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/dsmethod.c	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -43,7 +43,6 @@
 
 #include <acpi/acpi.h>
 #include "accommon.h"
-#include "amlcode.h"
 #include "acdispat.h"
 #include "acinterp.h"
 #include "acnamesp.h"
@@ -201,7 +200,7 @@ acpi_ds_begin_method_execution(struct ac
 	/*
 	 * If this method is serialized, we need to acquire the method mutex.
 	 */
-	if (obj_desc->method.method_flags & AML_METHOD_SERIALIZED) {
+	if (obj_desc->method.info_flags & ACPI_METHOD_SERIALIZED) {
 		/*
 		 * Create a mutex for the method if it is defined to be Serialized
 		 * and a mutex has not already been created. We defer the mutex creation
@@ -413,8 +412,9 @@ acpi_ds_call_control_method(struct acpi_
 
 	/* Invoke an internal method if necessary */
 
-	if (obj_desc->method.method_flags & AML_METHOD_INTERNAL_ONLY) {
-		status = obj_desc->method.extra.implementation(next_walk_state);
+	if (obj_desc->method.info_flags & ACPI_METHOD_INTERNAL_ONLY) {
+		status =
+		    obj_desc->method.dispatch.implementation(next_walk_state);
 		if (status == AE_OK) {
 			status = AE_CTRL_TERMINATE;
 		}
@@ -579,11 +579,14 @@ acpi_ds_terminate_control_method(union a
 
 		/*
 		 * Delete any namespace objects created anywhere within the
-		 * namespace by the execution of this method. Unless this method
-		 * is a module-level executable code method, in which case we
-		 * want make the objects permanent.
+		 * namespace by the execution of this method. Unless:
+		 * 1) This method is a module-level executable code method, in which
+		 *    case we want make the objects permanent.
+		 * 2) There are other threads executing the method, in which case we
+		 *    will wait until the last thread has completed.
 		 */
-		if (!(method_desc->method.flags & AOPOBJ_MODULE_LEVEL)) {
+		if (!(method_desc->method.info_flags & ACPI_METHOD_MODULE_LEVEL)
+		    && (method_desc->method.thread_count == 1)) {
 
 			/* Delete any direct children of (created by) this method */
 
@@ -593,12 +596,17 @@ acpi_ds_terminate_control_method(union a
 			/*
 			 * Delete any objects that were created by this method
 			 * elsewhere in the namespace (if any were created).
+			 * Use of the ACPI_METHOD_MODIFIED_NAMESPACE optimizes the
+			 * deletion such that we don't have to perform an entire
+			 * namespace walk for every control method execution.
 			 */
 			if (method_desc->method.
-			    flags & AOPOBJ_MODIFIED_NAMESPACE) {
+			    info_flags & ACPI_METHOD_MODIFIED_NAMESPACE) {
 				acpi_ns_delete_namespace_by_owner(method_desc->
 								  method.
 								  owner_id);
+				method_desc->method.info_flags &=
+				    ~ACPI_METHOD_MODIFIED_NAMESPACE;
 			}
 		}
 	}
@@ -629,19 +637,43 @@ acpi_ds_terminate_control_method(union a
 		 * Serialized if it appears that the method is incorrectly written and
 		 * does not support multiple thread execution. The best example of this
 		 * is if such a method creates namespace objects and blocks. A second
-		 * thread will fail with an AE_ALREADY_EXISTS exception
+		 * thread will fail with an AE_ALREADY_EXISTS exception.
 		 *
 		 * This code is here because we must wait until the last thread exits
-		 * before creating the synchronization semaphore.
+		 * before marking the method as serialized.
 		 */
-		if ((method_desc->method.method_flags & AML_METHOD_SERIALIZED)
-		    && (!method_desc->method.mutex)) {
-			(void)acpi_ds_create_method_mutex(method_desc);
+		if (method_desc->method.
+		    info_flags & ACPI_METHOD_SERIALIZED_PENDING) {
+			if (walk_state) {
+				ACPI_INFO((AE_INFO,
+					   "Marking method %4.4s as Serialized because of AE_ALREADY_EXISTS error",
+					   walk_state->method_node->name.
+					   ascii));
+			}
+
+			/*
+			 * Method tried to create an object twice and was marked as
+			 * "pending serialized". The probable cause is that the method
+			 * cannot handle reentrancy.
+			 *
+			 * The method was created as not_serialized, but it tried to create
+			 * a named object and then blocked, causing the second thread
+			 * entrance to begin and then fail. Workaround this problem by
+			 * marking the method permanently as Serialized when the last
+			 * thread exits here.
+			 */
+			method_desc->method.info_flags &=
+			    ~ACPI_METHOD_SERIALIZED_PENDING;
+			method_desc->method.info_flags |=
+			    ACPI_METHOD_SERIALIZED;
+			method_desc->method.sync_level = 0;
 		}
 
 		/* No more threads, we can free the owner_id */
 
-		if (!(method_desc->method.flags & AOPOBJ_MODULE_LEVEL)) {
+		if (!
+		    (method_desc->method.
+		     info_flags & ACPI_METHOD_MODULE_LEVEL)) {
 			acpi_ut_release_owner_id(&method_desc->method.owner_id);
 		}
 	}
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/dsmthdat.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/dsmthdat.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/dsmthdat.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/dsmthdat.c	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/dsobject.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/dsobject.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/dsobject.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/dsobject.c	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/dsopcode.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/dsopcode.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/dsopcode.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/dsopcode.c	2011-03-14 21:20:32.000000000 -0400
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/dsutils.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/dsutils.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/dsutils.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/dsutils.c	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/dswexec.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/dswexec.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/dswexec.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/dswexec.c	2011-03-14 21:20:32.000000000 -0400
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/dswload.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/dswload.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/dswload.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/dswload.c	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/dswscope.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/dswscope.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/dswscope.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/dswscope.c	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/dswstate.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/dswstate.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/dswstate.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/dswstate.c	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/evevent.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/evevent.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/evevent.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/evevent.c	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -217,9 +217,17 @@ u32 acpi_ev_fixed_event_detect(void)
 		     status_bit_mask)
 		    && (fixed_enable & acpi_gbl_fixed_event_info[i].
 			enable_bit_mask)) {
+			/*
+			 * Found an active (signalled) event. Invoke global event
+			 * handler if present.
+			 */
+			acpi_fixed_event_count[i]++;
+			if (acpi_gbl_global_event_handler) {
+				acpi_gbl_global_event_handler
+				    (ACPI_EVENT_TYPE_FIXED, NULL, i,
+				     acpi_gbl_global_event_handler_context);
+			}
 
-			/* Found an active (signalled) event */
-			acpi_os_fixed_event_count(i);
 			int_status |= acpi_ev_fixed_event_dispatch(i);
 		}
 	}
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/evgpeblk.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/evgpeblk.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/evgpeblk.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/evgpeblk.c	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -361,9 +361,9 @@ acpi_ev_create_gpe_block(struct acpi_nam
 
 	gpe_block->node = gpe_device;
 	gpe_block->gpe_count = (u16)(register_count * ACPI_GPE_REGISTER_WIDTH);
+	gpe_block->initialized = FALSE;
 	gpe_block->register_count = register_count;
 	gpe_block->block_base_number = gpe_block_base_number;
-	gpe_block->initialized = FALSE;
 
 	ACPI_MEMCPY(&gpe_block->block_address, gpe_block_address,
 		    sizeof(struct acpi_generic_address));
@@ -386,7 +386,7 @@ acpi_ev_create_gpe_block(struct acpi_nam
 		return_ACPI_STATUS(status);
 	}
 
-	acpi_all_gpes_initialized = FALSE;
+	acpi_gbl_all_gpes_initialized = FALSE;
 
 	/* Find all GPE methods (_Lxx or_Exx) for this block */
 
@@ -423,14 +423,12 @@ acpi_ev_create_gpe_block(struct acpi_nam
  *
  * FUNCTION:    acpi_ev_initialize_gpe_block
  *
- * PARAMETERS:  gpe_device          - Handle to the parent GPE block
- *              gpe_block           - Gpe Block info
+ * PARAMETERS:  acpi_gpe_callback
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Initialize and enable a GPE block. First find and run any
- *              _PRT methods associated with the block, then enable the
- *              appropriate GPEs.
+ * DESCRIPTION: Initialize and enable a GPE block. Enable GPEs that have
+ *              associated methods.
  *              Note: Assumes namespace is locked.
  *
  ******************************************************************************/
@@ -450,8 +448,8 @@ acpi_ev_initialize_gpe_block(struct acpi
 	ACPI_FUNCTION_TRACE(ev_initialize_gpe_block);
 
 	/*
-	 * Ignore a null GPE block (e.g., if no GPE block 1 exists) and
-	 * GPE blocks that have been initialized already.
+	 * Ignore a null GPE block (e.g., if no GPE block 1 exists), and
+	 * any GPE blocks that have been initialized already.
 	 */
 	if (!gpe_block || gpe_block->initialized) {
 		return_ACPI_STATUS(AE_OK);
@@ -459,8 +457,8 @@ acpi_ev_initialize_gpe_block(struct acpi
 
 	/*
 	 * Enable all GPEs that have a corresponding method and have the
-	 * ACPI_GPE_CAN_WAKE flag unset.  Any other GPEs within this block must
-	 * be enabled via the acpi_enable_gpe() interface.
+	 * ACPI_GPE_CAN_WAKE flag unset. Any other GPEs within this block
+	 * must be enabled via the acpi_enable_gpe() interface.
 	 */
 	gpe_enabled_count = 0;
 
@@ -472,14 +470,19 @@ acpi_ev_initialize_gpe_block(struct acpi
 			gpe_index = (i * ACPI_GPE_REGISTER_WIDTH) + j;
 			gpe_event_info = &gpe_block->event_info[gpe_index];
 
-			/* Ignore GPEs that have no corresponding _Lxx/_Exx method */
-
-			if (!(gpe_event_info->flags & ACPI_GPE_DISPATCH_METHOD)
+			/*
+			 * Ignore GPEs that have no corresponding _Lxx/_Exx method
+			 * and GPEs that are used to wake the system
+			 */
+			if (((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) ==
+			     ACPI_GPE_DISPATCH_NONE)
+			    || ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK)
+				== ACPI_GPE_DISPATCH_HANDLER)
 			    || (gpe_event_info->flags & ACPI_GPE_CAN_WAKE)) {
 				continue;
 			}
 
-			status = acpi_raw_enable_gpe(gpe_event_info);
+			status = acpi_ev_add_gpe_reference(gpe_event_info);
 			if (ACPI_FAILURE(status)) {
 				ACPI_EXCEPTION((AE_INFO, status,
 					"Could not enable GPE 0x%02X",
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/evgpe.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/evgpe.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/evgpe.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/evgpe.c	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -52,6 +52,8 @@ ACPI_MODULE_NAME("evgpe")
 /* Local prototypes */
 static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context);
 
+static void ACPI_SYSTEM_XFACE acpi_ev_asynch_enable_gpe(void *context);
+
 /*******************************************************************************
  *
  * FUNCTION:    acpi_ev_update_gpe_enable_mask
@@ -102,7 +104,7 @@ acpi_ev_update_gpe_enable_mask(struct ac
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Clear the given GPE from stale events and enable it.
+ * DESCRIPTION: Clear a GPE of stale events and enable it.
  *
  ******************************************************************************/
 acpi_status
@@ -113,12 +115,13 @@ acpi_ev_enable_gpe(struct acpi_gpe_event
 	ACPI_FUNCTION_TRACE(ev_enable_gpe);
 
 	/*
-	 * We will only allow a GPE to be enabled if it has either an
-	 * associated method (_Lxx/_Exx) or a handler. Otherwise, the
-	 * GPE will be immediately disabled by acpi_ev_gpe_dispatch the
-	 * first time it fires.
+	 * We will only allow a GPE to be enabled if it has either an associated
+	 * method (_Lxx/_Exx) or a handler, or is using the implicit notify
+	 * feature. Otherwise, the GPE will be immediately disabled by
+	 * acpi_ev_gpe_dispatch the first time it fires.
 	 */
-	if (!(gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK)) {
+	if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) ==
+	    ACPI_GPE_DISPATCH_NONE) {
 		return_ACPI_STATUS(AE_NO_HANDLER);
 	}
 
@@ -137,9 +140,9 @@ acpi_ev_enable_gpe(struct acpi_gpe_event
 
 /*******************************************************************************
  *
- * FUNCTION:    acpi_raw_enable_gpe
+ * FUNCTION:    acpi_ev_add_gpe_reference
  *
- * PARAMETERS:  gpe_event_info  - GPE to enable
+ * PARAMETERS:  gpe_event_info          - Add a reference to this GPE
  *
  * RETURN:      Status
  *
@@ -148,16 +151,21 @@ acpi_ev_enable_gpe(struct acpi_gpe_event
  *
  ******************************************************************************/
 
-acpi_status acpi_raw_enable_gpe(struct acpi_gpe_event_info *gpe_event_info)
+acpi_status acpi_ev_add_gpe_reference(struct acpi_gpe_event_info *gpe_event_info)
 {
 	acpi_status status = AE_OK;
 
+	ACPI_FUNCTION_TRACE(ev_add_gpe_reference);
+
 	if (gpe_event_info->runtime_count == ACPI_UINT8_MAX) {
 		return_ACPI_STATUS(AE_LIMIT);
 	}
 
 	gpe_event_info->runtime_count++;
 	if (gpe_event_info->runtime_count == 1) {
+
+		/* Enable on first reference */
+
 		status = acpi_ev_update_gpe_enable_mask(gpe_event_info);
 		if (ACPI_SUCCESS(status)) {
 			status = acpi_ev_enable_gpe(gpe_event_info);
@@ -173,9 +181,9 @@ acpi_status acpi_raw_enable_gpe(struct a
 
 /*******************************************************************************
  *
- * FUNCTION:    acpi_raw_disable_gpe
+ * FUNCTION:    acpi_ev_remove_gpe_reference
  *
- * PARAMETERS:  gpe_event_info  - GPE to disable
+ * PARAMETERS:  gpe_event_info          - Remove a reference to this GPE
  *
  * RETURN:      Status
  *
@@ -184,16 +192,21 @@ acpi_status acpi_raw_enable_gpe(struct a
  *
  ******************************************************************************/
 
-acpi_status acpi_raw_disable_gpe(struct acpi_gpe_event_info *gpe_event_info)
+acpi_status acpi_ev_remove_gpe_reference(struct acpi_gpe_event_info *gpe_event_info)
 {
 	acpi_status status = AE_OK;
 
+	ACPI_FUNCTION_TRACE(ev_remove_gpe_reference);
+
 	if (!gpe_event_info->runtime_count) {
 		return_ACPI_STATUS(AE_LIMIT);
 	}
 
 	gpe_event_info->runtime_count--;
 	if (!gpe_event_info->runtime_count) {
+
+		/* Disable on last reference */
+
 		status = acpi_ev_update_gpe_enable_mask(gpe_event_info);
 		if (ACPI_SUCCESS(status)) {
 			status = acpi_hw_low_set_gpe(gpe_event_info,
@@ -379,7 +392,7 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_x
 			}
 
 			ACPI_DEBUG_PRINT((ACPI_DB_INTERRUPTS,
-					  "Read GPE Register at GPE%X: Status=%02X, Enable=%02X\n",
+					  "Read GPE Register at GPE%02X: Status=%02X, Enable=%02X\n",
 					  gpe_register_info->base_gpe_number,
 					  status_reg, enable_reg));
 
@@ -405,7 +418,9 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_x
 					 * or method.
 					 */
 					int_status |=
-					    acpi_ev_gpe_dispatch(&gpe_block->
+					    acpi_ev_gpe_dispatch(gpe_block->
+								 node,
+								 &gpe_block->
 						event_info[((acpi_size) i * ACPI_GPE_REGISTER_WIDTH) + j], j + gpe_register_info->base_gpe_number);
 				}
 			}
@@ -435,19 +450,29 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_x
  *              an interrupt handler.
  *
  ******************************************************************************/
-static void acpi_ev_asynch_enable_gpe(void *context);
 
 static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context)
 {
-	struct acpi_gpe_event_info *gpe_event_info = (void *)context;
+	struct acpi_gpe_event_info *gpe_event_info = context;
 	acpi_status status;
-	struct acpi_gpe_event_info local_gpe_event_info;
+	struct acpi_gpe_event_info *local_gpe_event_info;
 	struct acpi_evaluate_info *info;
+	struct acpi_gpe_notify_object *notify_object;
 
 	ACPI_FUNCTION_TRACE(ev_asynch_execute_gpe_method);
 
+	/* Allocate a local GPE block */
+
+	local_gpe_event_info =
+	    ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_gpe_event_info));
+	if (!local_gpe_event_info) {
+		ACPI_EXCEPTION((AE_INFO, AE_NO_MEMORY, "while handling a GPE"));
+		return_VOID;
+	}
+
 	status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
 	if (ACPI_FAILURE(status)) {
+		ACPI_FREE(local_gpe_event_info);
 		return_VOID;
 	}
 
@@ -455,6 +480,7 @@ static void ACPI_SYSTEM_XFACE acpi_ev_as
 
 	if (!acpi_ev_valid_gpe_event(gpe_event_info)) {
 		status = acpi_ut_release_mutex(ACPI_MTX_EVENTS);
+		ACPI_FREE(local_gpe_event_info);
 		return_VOID;
 	}
 
@@ -462,7 +488,7 @@ static void ACPI_SYSTEM_XFACE acpi_ev_as
 	 * Take a snapshot of the GPE info for this level - we copy the info to
 	 * prevent a race condition with remove_handler/remove_block.
 	 */
-	ACPI_MEMCPY(&local_gpe_event_info, gpe_event_info,
+	ACPI_MEMCPY(local_gpe_event_info, gpe_event_info,
 		    sizeof(struct acpi_gpe_event_info));
 
 	status = acpi_ut_release_mutex(ACPI_MTX_EVENTS);
@@ -470,12 +496,34 @@ static void ACPI_SYSTEM_XFACE acpi_ev_as
 		return_VOID;
 	}
 
-	/*
-	 * Must check for control method type dispatch one more time to avoid a
-	 * race with ev_gpe_install_handler
-	 */
-	if ((local_gpe_event_info.flags & ACPI_GPE_DISPATCH_MASK) ==
-	    ACPI_GPE_DISPATCH_METHOD) {
+	/* Do the correct dispatch - normal method or implicit notify */
+
+	switch (local_gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) {
+	case ACPI_GPE_DISPATCH_NOTIFY:
+
+		/*
+		 * Implicit notify.
+		 * Dispatch a DEVICE_WAKE notify to the appropriate handler.
+		 * NOTE: the request is queued for execution after this method
+		 * completes. The notify handlers are NOT invoked synchronously
+		 * from this thread -- because handlers may in turn run other
+		 * control methods.
+		 */
+		status = acpi_ev_queue_notify_request(
+				local_gpe_event_info->dispatch.device.node,
+				ACPI_NOTIFY_DEVICE_WAKE);
+
+		notify_object = local_gpe_event_info->dispatch.device.next;
+		while (ACPI_SUCCESS(status) && notify_object) {
+			status = acpi_ev_queue_notify_request(
+					notify_object->node,
+					ACPI_NOTIFY_DEVICE_WAKE);
+			notify_object = notify_object->next;
+		}
+
+		break;
+
+	case ACPI_GPE_DISPATCH_METHOD:
 
 		/* Allocate the evaluation information block */
 
@@ -488,7 +536,7 @@ static void ACPI_SYSTEM_XFACE acpi_ev_as
 			 * control method that corresponds to this GPE
 			 */
 			info->prefix_node =
-			    local_gpe_event_info.dispatch.method_node;
+			    local_gpe_event_info->dispatch.method_node;
 			info->flags = ACPI_IGNORE_RETURN_VALUE;
 
 			status = acpi_ns_evaluate(info);
@@ -499,46 +547,98 @@ static void ACPI_SYSTEM_XFACE acpi_ev_as
 			ACPI_EXCEPTION((AE_INFO, status,
 					"while evaluating GPE method [%4.4s]",
 					acpi_ut_get_node_name
-					(local_gpe_event_info.dispatch.
+					(local_gpe_event_info->dispatch.
 					 method_node)));
 		}
+
+		break;
+
+	default:
+		return_VOID;    /* Should never happen */
 	}
+
 	/* Defer enabling of GPE until all notify handlers are done */
-	acpi_os_execute(OSL_NOTIFY_HANDLER, acpi_ev_asynch_enable_gpe,
-				gpe_event_info);
+
+	status = acpi_os_execute(OSL_NOTIFY_HANDLER,
+				 acpi_ev_asynch_enable_gpe,
+				 local_gpe_event_info);
+	if (ACPI_FAILURE(status)) {
+		ACPI_FREE(local_gpe_event_info);
+	}
 	return_VOID;
 }
 
-static void acpi_ev_asynch_enable_gpe(void *context)
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ev_asynch_enable_gpe
+ *
+ * PARAMETERS:  Context (gpe_event_info) - Info for this GPE
+ *              Callback from acpi_os_execute
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Asynchronous clear/enable for GPE. This allows the GPE to
+ *              complete (i.e., finish execution of Notify)
+ *
+ ******************************************************************************/
+
+static void ACPI_SYSTEM_XFACE acpi_ev_asynch_enable_gpe(void *context)
 {
 	struct acpi_gpe_event_info *gpe_event_info = context;
+
+	(void)acpi_ev_finish_gpe(gpe_event_info);
+
+	ACPI_FREE(gpe_event_info);
+	return;
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ev_finish_gpe
+ *
+ * PARAMETERS:  gpe_event_info      - Info for this GPE
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Clear/Enable a GPE. Common code that is used after execution
+ *              of a GPE method or a synchronous or asynchronous GPE handler.
+ *
+ ******************************************************************************/
+
+acpi_status acpi_ev_finish_gpe(struct acpi_gpe_event_info *gpe_event_info)
+{
 	acpi_status status;
+
 	if ((gpe_event_info->flags & ACPI_GPE_XRUPT_TYPE_MASK) ==
 	    ACPI_GPE_LEVEL_TRIGGERED) {
 		/*
-		 * GPE is level-triggered, we clear the GPE status bit after handling
-		 * the event.
+		 * GPE is level-triggered, we clear the GPE status bit after
+		 * handling the event.
 		 */
 		status = acpi_hw_clear_gpe(gpe_event_info);
 		if (ACPI_FAILURE(status)) {
-			return_VOID;
+			return (status);
 		}
 	}
 
 	/*
-	 * Enable this GPE, conditionally. This means that the GPE will only be
-	 * physically enabled if the enable_for_run bit is set in the event_info
+	 * Enable this GPE, conditionally. This means that the GPE will
+	 * only be physically enabled if the enable_for_run bit is set
+	 * in the event_info.
 	 */
-	(void)acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_COND_ENABLE);
-
-	return_VOID;
+	(void)acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_CONDITIONAL_ENABLE);
+	return (AE_OK);
 }
 
+
 /*******************************************************************************
  *
  * FUNCTION:    acpi_ev_gpe_dispatch
  *
- * PARAMETERS:  gpe_event_info  - Info for this GPE
+ * PARAMETERS:  gpe_device      - Device node. NULL for GPE0/GPE1
+ *              gpe_event_info  - Info for this GPE
  *              gpe_number      - Number relative to the parent GPE block
  *
  * RETURN:      INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
@@ -551,13 +651,22 @@ static void acpi_ev_asynch_enable_gpe(vo
  ******************************************************************************/
 
 u32
-acpi_ev_gpe_dispatch(struct acpi_gpe_event_info *gpe_event_info, u32 gpe_number)
+acpi_ev_gpe_dispatch(struct acpi_namespace_node *gpe_device,
+		    struct acpi_gpe_event_info *gpe_event_info, u32 gpe_number)
 {
 	acpi_status status;
+	u32 return_value;
 
 	ACPI_FUNCTION_TRACE(ev_gpe_dispatch);
 
-	acpi_os_gpe_count(gpe_number);
+	/* Invoke global event handler if present */
+
+	acpi_gpe_count++;
+	if (acpi_gbl_global_event_handler) {
+		acpi_gbl_global_event_handler(ACPI_EVENT_TYPE_GPE, gpe_device,
+					      gpe_number,
+					      acpi_gbl_global_event_handler_context);
+	}
 
 	/*
 	 * If edge-triggered, clear the GPE status bit now. Note that
@@ -568,59 +677,55 @@ acpi_ev_gpe_dispatch(struct acpi_gpe_eve
 		status = acpi_hw_clear_gpe(gpe_event_info);
 		if (ACPI_FAILURE(status)) {
 			ACPI_EXCEPTION((AE_INFO, status,
-					"Unable to clear GPE[0x%2X]",
-					gpe_number));
+					"Unable to clear GPE%02X", gpe_number));
 			return_UINT32(ACPI_INTERRUPT_NOT_HANDLED);
 		}
 	}
 
 	/*
-	 * Dispatch the GPE to either an installed handler, or the control method
-	 * associated with this GPE (_Lxx or _Exx). If a handler exists, we invoke
-	 * it and do not attempt to run the method. If there is neither a handler
-	 * nor a method, we disable this GPE to prevent further such pointless
-	 * events from firing.
+	 * Always disable the GPE so that it does not keep firing before
+	 * any asynchronous activity completes (either from the execution
+	 * of a GPE method or an asynchronous GPE handler.)
+	 *
+	 * If there is no handler or method to run, just disable the
+	 * GPE and leave it disabled permanently to prevent further such
+	 * pointless events from firing.
+	 */
+	status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_DISABLE);
+	if (ACPI_FAILURE(status)) {
+		ACPI_EXCEPTION((AE_INFO, status,
+				"Unable to disable GPE%02X", gpe_number));
+		return_UINT32(ACPI_INTERRUPT_NOT_HANDLED);
+	}
+
+	/*
+	 * Dispatch the GPE to either an installed handler or the control
+	 * method associated with this GPE (_Lxx or _Exx). If a handler
+	 * exists, we invoke it and do not attempt to run the method.
+	 * If there is neither a handler nor a method, leave the GPE
+	 * disabled.
 	 */
 	switch (gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) {
 	case ACPI_GPE_DISPATCH_HANDLER:
 
-		/*
-		 * Invoke the installed handler (at interrupt level)
-		 * Ignore return status for now.
-		 * TBD: leave GPE disabled on error?
-		 */
-		(void)gpe_event_info->dispatch.handler->address(gpe_event_info->
-								dispatch.
-								handler->
-								context);
+		/* Invoke the installed handler (at interrupt level) */
 
-		/* It is now safe to clear level-triggered events. */
+		return_value =
+		    gpe_event_info->dispatch.handler->address(gpe_device,
+							      gpe_number,
+							      gpe_event_info->
+							      dispatch.handler->
+							      context);
 
-		if ((gpe_event_info->flags & ACPI_GPE_XRUPT_TYPE_MASK) ==
-		    ACPI_GPE_LEVEL_TRIGGERED) {
-			status = acpi_hw_clear_gpe(gpe_event_info);
-			if (ACPI_FAILURE(status)) {
-				ACPI_EXCEPTION((AE_INFO, status,
-					"Unable to clear GPE[0x%2X]",
-						gpe_number));
-				return_UINT32(ACPI_INTERRUPT_NOT_HANDLED);
-			}
+		/* If requested, clear (if level-triggered) and reenable the GPE */
+
+		if (return_value & ACPI_REENABLE_GPE) {
+			(void)acpi_ev_finish_gpe(gpe_event_info);
 		}
 		break;
 
 	case ACPI_GPE_DISPATCH_METHOD:
-
-		/*
-		 * Disable the GPE, so it doesn't keep firing before the method has a
-		 * chance to run (it runs asynchronously with interrupts enabled).
-		 */
-		status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_DISABLE);
-		if (ACPI_FAILURE(status)) {
-			ACPI_EXCEPTION((AE_INFO, status,
-					"Unable to disable GPE[0x%2X]",
-					gpe_number));
-			return_UINT32(ACPI_INTERRUPT_NOT_HANDLED);
-		}
+	case ACPI_GPE_DISPATCH_NOTIFY:
 
 		/*
 		 * Execute the method associated with the GPE
@@ -631,7 +736,7 @@ acpi_ev_gpe_dispatch(struct acpi_gpe_eve
 					 gpe_event_info);
 		if (ACPI_FAILURE(status)) {
 			ACPI_EXCEPTION((AE_INFO, status,
-					"Unable to queue handler for GPE[0x%2X] - event disabled",
+					"Unable to queue handler for GPE%2X - event disabled",
 					gpe_number));
 		}
 		break;
@@ -644,20 +749,9 @@ acpi_ev_gpe_dispatch(struct acpi_gpe_eve
 		 * a GPE to be enabled if it has no handler or method.
 		 */
 		ACPI_ERROR((AE_INFO,
-			    "No handler or method for GPE[0x%2X], disabling event",
+			    "No handler or method for GPE%02X, disabling event",
 			    gpe_number));
 
-		/*
-		 * Disable the GPE. The GPE will remain disabled a handler
-		 * is installed or ACPICA is restarted.
-		 */
-		status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_DISABLE);
-		if (ACPI_FAILURE(status)) {
-			ACPI_EXCEPTION((AE_INFO, status,
-					"Unable to disable GPE[0x%2X]",
-					gpe_number));
-			return_UINT32(ACPI_INTERRUPT_NOT_HANDLED);
-		}
 		break;
 	}
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/evgpeinit.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/evgpeinit.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/evgpeinit.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/evgpeinit.c	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -45,11 +45,27 @@
 #include "accommon.h"
 #include "acevents.h"
 #include "acnamesp.h"
-#include "acinterp.h"
 
 #define _COMPONENT          ACPI_EVENTS
 ACPI_MODULE_NAME("evgpeinit")
 
+/*
+ * Note: History of _PRW support in ACPICA
+ *
+ * Originally (2000 - 2010), the GPE initialization code performed a walk of
+ * the entire namespace to execute the _PRW methods and detect all GPEs
+ * capable of waking the system.
+ *
+ * As of 10/2010, the _PRW method execution has been removed since it is
+ * actually unnecessary. The host OS must in fact execute all _PRW methods
+ * in order to identify the device/power-resource dependencies. We now put
+ * the onus on the host OS to identify the wake GPEs as part of this process
+ * and to inform ACPICA of these GPEs via the acpi_setup_gpe_for_wake interface. This
+ * not only reduces the complexity of the ACPICA initialization code, but in
+ * some cases (on systems with very large namespaces) it should reduce the
+ * kernel boot time as well.
+ */
+
 /*******************************************************************************
  *
  * FUNCTION:    acpi_ev_gpe_initialize
@@ -222,7 +238,7 @@ void acpi_ev_update_gpes(acpi_owner_id t
 	acpi_status status = AE_OK;
 
 	/*
-	 * 2) Find any _Lxx/_Exx GPE methods that have just been loaded.
+	 * Find any _Lxx/_Exx GPE methods that have just been loaded.
 	 *
 	 * Any GPEs that correspond to new _Lxx/_Exx methods are immediately
 	 * enabled.
@@ -235,9 +251,9 @@ void acpi_ev_update_gpes(acpi_owner_id t
 		return;
 	}
 
+	walk_info.count = 0;
 	walk_info.owner_id = table_owner_id;
 	walk_info.execute_by_owner_id = TRUE;
-	walk_info.count = 0;
 
 	/* Walk the interrupt level descriptor list */
 
@@ -298,7 +314,7 @@ void acpi_ev_update_gpes(acpi_owner_id t
  *                  xx     - is the GPE number [in HEX]
  *
  * If walk_info->execute_by_owner_id is TRUE, we only execute examine GPE methods
- *    with that owner.
+ * with that owner.
  *
  ******************************************************************************/
 
@@ -415,6 +431,7 @@ acpi_ev_match_gpe_method(acpi_handle obj
 	 * Add the GPE information from above to the gpe_event_info block for
 	 * use during dispatch of this GPE.
 	 */
+	gpe_event_info->flags &= ~(ACPI_GPE_DISPATCH_MASK);
 	gpe_event_info->flags |= (u8)(type | ACPI_GPE_DISPATCH_METHOD);
 	gpe_event_info->dispatch.method_node = method_node;
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/evgpeutil.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/evgpeutil.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/evgpeutil.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/evgpeutil.c	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -153,6 +153,45 @@ u8 acpi_ev_valid_gpe_event(struct acpi_g
 }
 
 /*******************************************************************************
+ *
+ * FUNCTION:    acpi_ev_get_gpe_device
+ *
+ * PARAMETERS:  GPE_WALK_CALLBACK
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Matches the input GPE index (0-current_gpe_count) with a GPE
+ *              block device. NULL if the GPE is one of the FADT-defined GPEs.
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ev_get_gpe_device(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
+		       struct acpi_gpe_block_info *gpe_block, void *context)
+{
+	struct acpi_gpe_device_info *info = context;
+
+	/* Increment Index by the number of GPEs in this block */
+
+	info->next_block_base_index += gpe_block->gpe_count;
+
+	if (info->index < info->next_block_base_index) {
+		/*
+		 * The GPE index is within this block, get the node. Leave the node
+		 * NULL for the FADT-defined GPEs
+		 */
+		if ((gpe_block->node)->type == ACPI_TYPE_DEVICE) {
+			info->gpe_device = gpe_block->node;
+		}
+
+		info->status = AE_OK;
+		return (AE_CTRL_END);
+	}
+
+	return (AE_OK);
+}
+
+/*******************************************************************************
  *
  * FUNCTION:    acpi_ev_get_gpe_xrupt_block
  *
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/evmisc.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/evmisc.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/evmisc.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/evmisc.c	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -284,41 +284,39 @@ static void ACPI_SYSTEM_XFACE acpi_ev_no
  * RETURN:      ACPI_INTERRUPT_HANDLED
  *
  * DESCRIPTION: Invoked directly from the SCI handler when a global lock
- *              release interrupt occurs. Attempt to acquire the global lock,
- *              if successful, signal the thread waiting for the lock.
+ *              release interrupt occurs.  If there's a thread waiting for
+ *              the global lock, signal it.
  *
  * NOTE: Assumes that the semaphore can be signaled from interrupt level. If
  * this is not possible for some reason, a separate thread will have to be
  * scheduled to do this.
  *
  ******************************************************************************/
+static u8 acpi_ev_global_lock_pending;
 
 static u32 acpi_ev_global_lock_handler(void *context)
 {
-	u8 acquired = FALSE;
+	acpi_status status;
+	acpi_cpu_flags flags;
 
-	/*
-	 * Attempt to get the lock.
-	 *
-	 * If we don't get it now, it will be marked pending and we will
-	 * take another interrupt when it becomes free.
-	 */
-	ACPI_ACQUIRE_GLOBAL_LOCK(acpi_gbl_FACS, acquired);
-	if (acquired) {
+	flags = acpi_os_acquire_lock(acpi_ev_global_lock_pending_lock);
 
-		/* Got the lock, now wake all threads waiting for it */
+	if (!acpi_ev_global_lock_pending) {
+		goto out;
+	}
 
-		acpi_gbl_global_lock_acquired = TRUE;
-		/* Send a unit to the semaphore */
+	/* Send a unit to the semaphore */
 
-		if (ACPI_FAILURE
-		    (acpi_os_signal_semaphore
-		     (acpi_gbl_global_lock_semaphore, 1))) {
-			ACPI_ERROR((AE_INFO,
-				    "Could not signal Global Lock semaphore"));
-		}
+	status = acpi_os_signal_semaphore(acpi_gbl_global_lock_semaphore, 1);
+	if (ACPI_FAILURE(status)) {
+		ACPI_ERROR((AE_INFO, "Could not signal Global Lock semaphore"));
 	}
 
+	acpi_ev_global_lock_pending = FALSE;
+
+ out:
+	acpi_os_release_lock(acpi_ev_global_lock_pending_lock, flags);
+
 	return (ACPI_INTERRUPT_HANDLED);
 }
 
@@ -415,6 +413,7 @@ static int acpi_ev_global_lock_acquired;
 
 acpi_status acpi_ev_acquire_global_lock(u16 timeout)
 {
+	acpi_cpu_flags flags;
 	acpi_status status = AE_OK;
 	u8 acquired = FALSE;
 
@@ -467,32 +466,47 @@ acpi_status acpi_ev_acquire_global_lock(
 		return_ACPI_STATUS(AE_OK);
 	}
 
-	/* Attempt to acquire the actual hardware lock */
+	flags = acpi_os_acquire_lock(acpi_ev_global_lock_pending_lock);
 
-	ACPI_ACQUIRE_GLOBAL_LOCK(acpi_gbl_FACS, acquired);
-	if (acquired) {
+	do {
 
-		/* We got the lock */
+		/* Attempt to acquire the actual hardware lock */
+
+		ACPI_ACQUIRE_GLOBAL_LOCK(acpi_gbl_FACS, acquired);
+		if (acquired) {
+			acpi_gbl_global_lock_acquired = TRUE;
+
+			ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+					  "Acquired hardware Global Lock\n"));
+			break;
+		}
+
+		acpi_ev_global_lock_pending = TRUE;
 
+		acpi_os_release_lock(acpi_ev_global_lock_pending_lock, flags);
+
+		/*
+		 * Did not get the lock. The pending bit was set above, and we
+		 * must wait until we get the global lock released interrupt.
+		 */
 		ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
-				  "Acquired hardware Global Lock\n"));
+				  "Waiting for hardware Global Lock\n"));
 
-		acpi_gbl_global_lock_acquired = TRUE;
-		return_ACPI_STATUS(AE_OK);
-	}
+		/*
+		 * Wait for handshake with the global lock interrupt handler.
+		 * This interface releases the interpreter if we must wait.
+		 */
+		status = acpi_ex_system_wait_semaphore(
+						acpi_gbl_global_lock_semaphore,
+						ACPI_WAIT_FOREVER);
 
-	/*
-	 * Did not get the lock. The pending bit was set above, and we must now
-	 * wait until we get the global lock released interrupt.
-	 */
-	ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Waiting for hardware Global Lock\n"));
+		flags = acpi_os_acquire_lock(acpi_ev_global_lock_pending_lock);
 
-	/*
-	 * Wait for handshake with the global lock interrupt handler.
-	 * This interface releases the interpreter if we must wait.
-	 */
-	status = acpi_ex_system_wait_semaphore(acpi_gbl_global_lock_semaphore,
-					       ACPI_WAIT_FOREVER);
+	} while (ACPI_SUCCESS(status));
+
+	acpi_ev_global_lock_pending = FALSE;
+
+	acpi_os_release_lock(acpi_ev_global_lock_pending_lock, flags);
 
 	return_ACPI_STATUS(status);
 }
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/evregion.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/evregion.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/evregion.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/evregion.c	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/evrgnini.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/evrgnini.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/evrgnini.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/evrgnini.c	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -590,9 +590,9 @@ acpi_ev_initialize_region(union acpi_ope
 				 * See acpi_ns_exec_module_code
 				 */
 				if (obj_desc->method.
-				    flags & AOPOBJ_MODULE_LEVEL) {
+				    info_flags & ACPI_METHOD_MODULE_LEVEL) {
 					handler_obj =
-					    obj_desc->method.extra.handler;
+					    obj_desc->method.dispatch.handler;
 				}
 				break;
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/evsci.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/evsci.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/evsci.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/evsci.c	2011-03-14 21:20:32.000000000 -0400
@@ -6,7 +6,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/evxface.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/evxface.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/evxface.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/evxface.c	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -92,6 +92,57 @@ acpi_status acpi_install_exception_handl
 
 ACPI_EXPORT_SYMBOL(acpi_install_exception_handler)
 #endif				/*  ACPI_FUTURE_USAGE  */
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_install_global_event_handler
+ *
+ * PARAMETERS:  Handler         - Pointer to the global event handler function
+ *              Context         - Value passed to the handler on each event
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Saves the pointer to the handler function. The global handler
+ *              is invoked upon each incoming GPE and Fixed Event. It is
+ *              invoked at interrupt level at the time of the event dispatch.
+ *              Can be used to update event counters, etc.
+ *
+ ******************************************************************************/
+acpi_status
+acpi_install_global_event_handler(ACPI_GBL_EVENT_HANDLER handler, void *context)
+{
+	acpi_status status;
+
+	ACPI_FUNCTION_TRACE(acpi_install_global_event_handler);
+
+	/* Parameter validation */
+
+	if (!handler) {
+		return_ACPI_STATUS(AE_BAD_PARAMETER);
+	}
+
+	status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
+	if (ACPI_FAILURE(status)) {
+		return_ACPI_STATUS(status);
+	}
+
+	/* Don't allow two handlers. */
+
+	if (acpi_gbl_global_event_handler) {
+		status = AE_ALREADY_EXISTS;
+		goto cleanup;
+	}
+
+	acpi_gbl_global_event_handler = handler;
+	acpi_gbl_global_event_handler_context = context;
+
+      cleanup:
+	(void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
+	return_ACPI_STATUS(status);
+}
+
+ACPI_EXPORT_SYMBOL(acpi_install_global_event_handler)
+
 /*******************************************************************************
  *
  * FUNCTION:    acpi_install_fixed_event_handler
@@ -671,10 +722,10 @@ ACPI_EXPORT_SYMBOL(acpi_remove_notify_ha
 acpi_status
 acpi_install_gpe_handler(acpi_handle gpe_device,
 			 u32 gpe_number,
-			 u32 type, acpi_event_handler address, void *context)
+			 u32 type, acpi_gpe_handler address, void *context)
 {
 	struct acpi_gpe_event_info *gpe_event_info;
-	struct acpi_handler_info *handler;
+	struct acpi_gpe_handler_info *handler;
 	acpi_status status;
 	acpi_cpu_flags flags;
 
@@ -693,7 +744,7 @@ acpi_install_gpe_handler(acpi_handle gpe
 
 	/* Allocate memory for the handler object */
 
-	handler = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_handler_info));
+	handler = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_gpe_handler_info));
 	if (!handler) {
 		status = AE_NO_MEMORY;
 		goto unlock_and_exit;
@@ -722,7 +773,7 @@ acpi_install_gpe_handler(acpi_handle gpe
 	handler->address = address;
 	handler->context = context;
 	handler->method_node = gpe_event_info->dispatch.method_node;
-	handler->orig_flags = gpe_event_info->flags &
+	handler->original_flags = gpe_event_info->flags &
 			(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK);
 
 	/*
@@ -731,10 +782,10 @@ acpi_install_gpe_handler(acpi_handle gpe
 	 * disabled now to avoid spurious execution of the handler.
 	 */
 
-	if ((handler->orig_flags & ACPI_GPE_DISPATCH_METHOD)
+	if ((handler->original_flags & ACPI_GPE_DISPATCH_METHOD)
 	    && gpe_event_info->runtime_count) {
-		handler->orig_enabled = 1;
-		(void)acpi_raw_disable_gpe(gpe_event_info);
+		handler->originally_enabled = 1;
+		(void)acpi_ev_remove_gpe_reference(gpe_event_info);
 	}
 
 	/* Install the handler */
@@ -777,10 +828,10 @@ ACPI_EXPORT_SYMBOL(acpi_install_gpe_hand
  ******************************************************************************/
 acpi_status
 acpi_remove_gpe_handler(acpi_handle gpe_device,
-			u32 gpe_number, acpi_event_handler address)
+			u32 gpe_number, acpi_gpe_handler address)
 {
 	struct acpi_gpe_event_info *gpe_event_info;
-	struct acpi_handler_info *handler;
+	struct acpi_gpe_handler_info *handler;
 	acpi_status status;
 	acpi_cpu_flags flags;
 
@@ -835,7 +886,7 @@ acpi_remove_gpe_handler(acpi_handle gpe_
 	gpe_event_info->dispatch.method_node = handler->method_node;
 	gpe_event_info->flags &=
 		~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK);
-	gpe_event_info->flags |= handler->orig_flags;
+	gpe_event_info->flags |= handler->original_flags;
 
 	/*
 	 * If the GPE was previously associated with a method and it was
@@ -843,9 +894,9 @@ acpi_remove_gpe_handler(acpi_handle gpe_
 	 * post-initialization configuration.
 	 */
 
-	if ((handler->orig_flags & ACPI_GPE_DISPATCH_METHOD)
-	    && handler->orig_enabled)
-		(void)acpi_raw_enable_gpe(gpe_event_info);
+	if ((handler->original_flags & ACPI_GPE_DISPATCH_METHOD)
+	    && handler->originally_enabled)
+		(void)acpi_ev_add_gpe_reference(gpe_event_info);
 
 	/* Now we can free the handler object */
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/evxfevnt.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/evxfevnt.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/evxfevnt.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/evxfevnt.c	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -43,18 +43,11 @@
 
 #include <acpi/acpi.h>
 #include "accommon.h"
-#include "acevents.h"
-#include "acnamesp.h"
 #include "actables.h"
 
 #define _COMPONENT          ACPI_EVENTS
 ACPI_MODULE_NAME("evxfevnt")
 
-/* Local prototypes */
-static acpi_status
-acpi_ev_get_gpe_device(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
-		       struct acpi_gpe_block_info *gpe_block, void *context);
-
 /*******************************************************************************
  *
  * FUNCTION:    acpi_enable
@@ -213,185 +206,6 @@ ACPI_EXPORT_SYMBOL(acpi_enable_event)
 
 /*******************************************************************************
  *
- * FUNCTION:    acpi_gpe_wakeup
- *
- * PARAMETERS:  gpe_device      - Parent GPE Device. NULL for GPE0/GPE1
- *              gpe_number      - GPE level within the GPE block
- *              Action          - Enable or Disable
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Set or clear the GPE's wakeup enable mask bit.
- *
- ******************************************************************************/
-acpi_status acpi_gpe_wakeup(acpi_handle gpe_device, u32 gpe_number, u8 action)
-{
-	acpi_status status = AE_OK;
-	struct acpi_gpe_event_info *gpe_event_info;
-	struct acpi_gpe_register_info *gpe_register_info;
-	acpi_cpu_flags flags;
-	u32 register_bit;
-
-	ACPI_FUNCTION_TRACE(acpi_gpe_wakeup);
-
-	flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
-
-	/* Ensure that we have a valid GPE number */
-
-	gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
-	if (!gpe_event_info || !(gpe_event_info->flags & ACPI_GPE_CAN_WAKE)) {
-		status = AE_BAD_PARAMETER;
-		goto unlock_and_exit;
-	}
-
-	gpe_register_info = gpe_event_info->register_info;
-	if (!gpe_register_info) {
-		status = AE_NOT_EXIST;
-		goto unlock_and_exit;
-	}
-
-	register_bit =
-	    acpi_hw_get_gpe_register_bit(gpe_event_info, gpe_register_info);
-
-	/* Perform the action */
-
-	switch (action) {
-	case ACPI_GPE_ENABLE:
-		ACPI_SET_BIT(gpe_register_info->enable_for_wake,
-			     (u8)register_bit);
-		break;
-
-	case ACPI_GPE_DISABLE:
-		ACPI_CLEAR_BIT(gpe_register_info->enable_for_wake,
-			       (u8)register_bit);
-		break;
-
-	default:
-		ACPI_ERROR((AE_INFO, "%u, Invalid action", action));
-		status = AE_BAD_PARAMETER;
-		break;
-	}
-
-unlock_and_exit:
-	acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
-	return_ACPI_STATUS(status);
-}
-
-ACPI_EXPORT_SYMBOL(acpi_gpe_wakeup)
-
-/*******************************************************************************
- *
- * FUNCTION:    acpi_enable_gpe
- *
- * PARAMETERS:  gpe_device      - Parent GPE Device. NULL for GPE0/GPE1
- *              gpe_number      - GPE level within the GPE block
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Add a reference to a GPE. On the first reference, the GPE is
- *              hardware-enabled.
- *
- ******************************************************************************/
-acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number)
-{
-	acpi_status status = AE_BAD_PARAMETER;
-	struct acpi_gpe_event_info *gpe_event_info;
-	acpi_cpu_flags flags;
-
-	ACPI_FUNCTION_TRACE(acpi_enable_gpe);
-
-	flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
-
-	/* Ensure that we have a valid GPE number */
-
-	gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
-	if (gpe_event_info) {
-		status = acpi_raw_enable_gpe(gpe_event_info);
-	}
-
-	acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
-	return_ACPI_STATUS(status);
-}
-ACPI_EXPORT_SYMBOL(acpi_enable_gpe)
-
-/*******************************************************************************
- *
- * FUNCTION:    acpi_disable_gpe
- *
- * PARAMETERS:  gpe_device      - Parent GPE Device. NULL for GPE0/GPE1
- *              gpe_number      - GPE level within the GPE block
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Remove a reference to a GPE. When the last reference is
- *              removed, only then is the GPE disabled (for runtime GPEs), or
- *              the GPE mask bit disabled (for wake GPEs)
- *
- ******************************************************************************/
-acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number)
-{
-	acpi_status status = AE_BAD_PARAMETER;
-	struct acpi_gpe_event_info *gpe_event_info;
-	acpi_cpu_flags flags;
-
-	ACPI_FUNCTION_TRACE(acpi_disable_gpe);
-
-	flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
-
-	/* Ensure that we have a valid GPE number */
-
-	gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
-	if (gpe_event_info) {
-		status = acpi_raw_disable_gpe(gpe_event_info) ;
-	}
-
-	acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
-	return_ACPI_STATUS(status);
-}
-ACPI_EXPORT_SYMBOL(acpi_disable_gpe)
-
-/*******************************************************************************
- *
- * FUNCTION:    acpi_gpe_can_wake
- *
- * PARAMETERS:  gpe_device      - Parent GPE Device. NULL for GPE0/GPE1
- *              gpe_number      - GPE level within the GPE block
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Set the ACPI_GPE_CAN_WAKE flag for the given GPE.  If the GPE
- *              has a corresponding method and is currently enabled, disable it
- *              (GPEs with corresponding methods are enabled unconditionally
- *              during initialization, but GPEs that can wake up are expected
- *              to be initially disabled).
- *
- ******************************************************************************/
-acpi_status acpi_gpe_can_wake(acpi_handle gpe_device, u32 gpe_number)
-{
-	acpi_status status = AE_OK;
-	struct acpi_gpe_event_info *gpe_event_info;
-	acpi_cpu_flags flags;
-
-	ACPI_FUNCTION_TRACE(acpi_gpe_can_wake);
-
-	flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
-
-	/* Ensure that we have a valid GPE number */
-
-	gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
-	if (gpe_event_info) {
-		gpe_event_info->flags |= ACPI_GPE_CAN_WAKE;
-	} else {
-		status = AE_BAD_PARAMETER;
-	}
-
-	acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
-	return_ACPI_STATUS(status);
-}
-ACPI_EXPORT_SYMBOL(acpi_gpe_can_wake)
-
-/*******************************************************************************
- *
  * FUNCTION:    acpi_disable_event
  *
  * PARAMETERS:  Event           - The fixed eventto be enabled
@@ -483,44 +297,6 @@ ACPI_EXPORT_SYMBOL(acpi_clear_event)
 
 /*******************************************************************************
  *
- * FUNCTION:    acpi_clear_gpe
- *
- * PARAMETERS:  gpe_device      - Parent GPE Device. NULL for GPE0/GPE1
- *              gpe_number      - GPE level within the GPE block
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Clear an ACPI event (general purpose)
- *
- ******************************************************************************/
-acpi_status acpi_clear_gpe(acpi_handle gpe_device, u32 gpe_number)
-{
-	acpi_status status = AE_OK;
-	struct acpi_gpe_event_info *gpe_event_info;
-	acpi_cpu_flags flags;
-
-	ACPI_FUNCTION_TRACE(acpi_clear_gpe);
-
-	flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
-
-	/* Ensure that we have a valid GPE number */
-
-	gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
-	if (!gpe_event_info) {
-		status = AE_BAD_PARAMETER;
-		goto unlock_and_exit;
-	}
-
-	status = acpi_hw_clear_gpe(gpe_event_info);
-
-      unlock_and_exit:
-	acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
-	return_ACPI_STATUS(status);
-}
-
-ACPI_EXPORT_SYMBOL(acpi_clear_gpe)
-/*******************************************************************************
- *
  * FUNCTION:    acpi_get_event_status
  *
  * PARAMETERS:  Event           - The fixed event
@@ -575,379 +351,3 @@ acpi_status acpi_get_event_status(u32 ev
 }
 
 ACPI_EXPORT_SYMBOL(acpi_get_event_status)
-
-/*******************************************************************************
- *
- * FUNCTION:    acpi_get_gpe_status
- *
- * PARAMETERS:  gpe_device      - Parent GPE Device. NULL for GPE0/GPE1
- *              gpe_number      - GPE level within the GPE block
- *              event_status    - Where the current status of the event will
- *                                be returned
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Get status of an event (general purpose)
- *
- ******************************************************************************/
-acpi_status
-acpi_get_gpe_status(acpi_handle gpe_device,
-		    u32 gpe_number, acpi_event_status *event_status)
-{
-	acpi_status status = AE_OK;
-	struct acpi_gpe_event_info *gpe_event_info;
-	acpi_cpu_flags flags;
-
-	ACPI_FUNCTION_TRACE(acpi_get_gpe_status);
-
-	flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
-
-	/* Ensure that we have a valid GPE number */
-
-	gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
-	if (!gpe_event_info) {
-		status = AE_BAD_PARAMETER;
-		goto unlock_and_exit;
-	}
-
-	/* Obtain status on the requested GPE number */
-
-	status = acpi_hw_get_gpe_status(gpe_event_info, event_status);
-
-	if (gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK)
-		*event_status |= ACPI_EVENT_FLAG_HANDLE;
-
-      unlock_and_exit:
-	acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
-	return_ACPI_STATUS(status);
-}
-
-ACPI_EXPORT_SYMBOL(acpi_get_gpe_status)
-/*******************************************************************************
- *
- * FUNCTION:    acpi_install_gpe_block
- *
- * PARAMETERS:  gpe_device          - Handle to the parent GPE Block Device
- *              gpe_block_address   - Address and space_iD
- *              register_count      - Number of GPE register pairs in the block
- *              interrupt_number    - H/W interrupt for the block
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Create and Install a block of GPE registers
- *
- ******************************************************************************/
-acpi_status
-acpi_install_gpe_block(acpi_handle gpe_device,
-		       struct acpi_generic_address *gpe_block_address,
-		       u32 register_count, u32 interrupt_number)
-{
-	acpi_status status = AE_OK;
-	union acpi_operand_object *obj_desc;
-	struct acpi_namespace_node *node;
-	struct acpi_gpe_block_info *gpe_block;
-
-	ACPI_FUNCTION_TRACE(acpi_install_gpe_block);
-
-	if ((!gpe_device) || (!gpe_block_address) || (!register_count)) {
-		return_ACPI_STATUS(AE_BAD_PARAMETER);
-	}
-
-	status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
-	if (ACPI_FAILURE(status)) {
-		return (status);
-	}
-
-	node = acpi_ns_validate_handle(gpe_device);
-	if (!node) {
-		status = AE_BAD_PARAMETER;
-		goto unlock_and_exit;
-	}
-
-	/*
-	 * For user-installed GPE Block Devices, the gpe_block_base_number
-	 * is always zero
-	 */
-	status =
-	    acpi_ev_create_gpe_block(node, gpe_block_address, register_count, 0,
-				     interrupt_number, &gpe_block);
-	if (ACPI_FAILURE(status)) {
-		goto unlock_and_exit;
-	}
-
-	/* Install block in the device_object attached to the node */
-
-	obj_desc = acpi_ns_get_attached_object(node);
-	if (!obj_desc) {
-
-		/*
-		 * No object, create a new one (Device nodes do not always have
-		 * an attached object)
-		 */
-		obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_DEVICE);
-		if (!obj_desc) {
-			status = AE_NO_MEMORY;
-			goto unlock_and_exit;
-		}
-
-		status =
-		    acpi_ns_attach_object(node, obj_desc, ACPI_TYPE_DEVICE);
-
-		/* Remove local reference to the object */
-
-		acpi_ut_remove_reference(obj_desc);
-
-		if (ACPI_FAILURE(status)) {
-			goto unlock_and_exit;
-		}
-	}
-
-	/* Now install the GPE block in the device_object */
-
-	obj_desc->device.gpe_block = gpe_block;
-
-      unlock_and_exit:
-	(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
-	return_ACPI_STATUS(status);
-}
-
-ACPI_EXPORT_SYMBOL(acpi_install_gpe_block)
-
-/*******************************************************************************
- *
- * FUNCTION:    acpi_remove_gpe_block
- *
- * PARAMETERS:  gpe_device          - Handle to the parent GPE Block Device
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Remove a previously installed block of GPE registers
- *
- ******************************************************************************/
-acpi_status acpi_remove_gpe_block(acpi_handle gpe_device)
-{
-	union acpi_operand_object *obj_desc;
-	acpi_status status;
-	struct acpi_namespace_node *node;
-
-	ACPI_FUNCTION_TRACE(acpi_remove_gpe_block);
-
-	if (!gpe_device) {
-		return_ACPI_STATUS(AE_BAD_PARAMETER);
-	}
-
-	status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
-	if (ACPI_FAILURE(status)) {
-		return (status);
-	}
-
-	node = acpi_ns_validate_handle(gpe_device);
-	if (!node) {
-		status = AE_BAD_PARAMETER;
-		goto unlock_and_exit;
-	}
-
-	/* Get the device_object attached to the node */
-
-	obj_desc = acpi_ns_get_attached_object(node);
-	if (!obj_desc || !obj_desc->device.gpe_block) {
-		return_ACPI_STATUS(AE_NULL_OBJECT);
-	}
-
-	/* Delete the GPE block (but not the device_object) */
-
-	status = acpi_ev_delete_gpe_block(obj_desc->device.gpe_block);
-	if (ACPI_SUCCESS(status)) {
-		obj_desc->device.gpe_block = NULL;
-	}
-
-      unlock_and_exit:
-	(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
-	return_ACPI_STATUS(status);
-}
-
-ACPI_EXPORT_SYMBOL(acpi_remove_gpe_block)
-
-/*******************************************************************************
- *
- * FUNCTION:    acpi_get_gpe_device
- *
- * PARAMETERS:  Index               - System GPE index (0-current_gpe_count)
- *              gpe_device          - Where the parent GPE Device is returned
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Obtain the GPE device associated with the input index. A NULL
- *              gpe device indicates that the gpe number is contained in one of
- *              the FADT-defined gpe blocks. Otherwise, the GPE block device.
- *
- ******************************************************************************/
-acpi_status
-acpi_get_gpe_device(u32 index, acpi_handle *gpe_device)
-{
-	struct acpi_gpe_device_info info;
-	acpi_status status;
-
-	ACPI_FUNCTION_TRACE(acpi_get_gpe_device);
-
-	if (!gpe_device) {
-		return_ACPI_STATUS(AE_BAD_PARAMETER);
-	}
-
-	if (index >= acpi_current_gpe_count) {
-		return_ACPI_STATUS(AE_NOT_EXIST);
-	}
-
-	/* Setup and walk the GPE list */
-
-	info.index = index;
-	info.status = AE_NOT_EXIST;
-	info.gpe_device = NULL;
-	info.next_block_base_index = 0;
-
-	status = acpi_ev_walk_gpe_list(acpi_ev_get_gpe_device, &info);
-	if (ACPI_FAILURE(status)) {
-		return_ACPI_STATUS(status);
-	}
-
-	*gpe_device = info.gpe_device;
-	return_ACPI_STATUS(info.status);
-}
-
-ACPI_EXPORT_SYMBOL(acpi_get_gpe_device)
-
-/*******************************************************************************
- *
- * FUNCTION:    acpi_ev_get_gpe_device
- *
- * PARAMETERS:  GPE_WALK_CALLBACK
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Matches the input GPE index (0-current_gpe_count) with a GPE
- *              block device. NULL if the GPE is one of the FADT-defined GPEs.
- *
- ******************************************************************************/
-static acpi_status
-acpi_ev_get_gpe_device(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
-		       struct acpi_gpe_block_info *gpe_block, void *context)
-{
-	struct acpi_gpe_device_info *info = context;
-
-	/* Increment Index by the number of GPEs in this block */
-
-	info->next_block_base_index += gpe_block->gpe_count;
-
-	if (info->index < info->next_block_base_index) {
-		/*
-		 * The GPE index is within this block, get the node. Leave the node
-		 * NULL for the FADT-defined GPEs
-		 */
-		if ((gpe_block->node)->type == ACPI_TYPE_DEVICE) {
-			info->gpe_device = gpe_block->node;
-		}
-
-		info->status = AE_OK;
-		return (AE_CTRL_END);
-	}
-
-	return (AE_OK);
-}
-
-/******************************************************************************
- *
- * FUNCTION:    acpi_disable_all_gpes
- *
- * PARAMETERS:  None
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Disable and clear all GPEs in all GPE blocks
- *
- ******************************************************************************/
-
-acpi_status acpi_disable_all_gpes(void)
-{
-	acpi_status status;
-
-	ACPI_FUNCTION_TRACE(acpi_disable_all_gpes);
-
-	status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
-	if (ACPI_FAILURE(status)) {
-		return_ACPI_STATUS(status);
-	}
-
-	status = acpi_hw_disable_all_gpes();
-	(void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
-
-	return_ACPI_STATUS(status);
-}
-
-/******************************************************************************
- *
- * FUNCTION:    acpi_enable_all_runtime_gpes
- *
- * PARAMETERS:  None
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Enable all "runtime" GPEs, in all GPE blocks
- *
- ******************************************************************************/
-
-acpi_status acpi_enable_all_runtime_gpes(void)
-{
-	acpi_status status;
-
-	ACPI_FUNCTION_TRACE(acpi_enable_all_runtime_gpes);
-
-	status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
-	if (ACPI_FAILURE(status)) {
-		return_ACPI_STATUS(status);
-	}
-
-	status = acpi_hw_enable_all_runtime_gpes();
-	(void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
-
-	return_ACPI_STATUS(status);
-}
-
-/******************************************************************************
- *
- * FUNCTION:    acpi_update_gpes
- *
- * PARAMETERS:  None
- *
- * RETURN:      None
- *
- * DESCRIPTION: Enable all GPEs that have associated _Lxx or _Exx methods and
- *              are not pointed to by any device _PRW methods indicating that
- *              these GPEs are generally intended for system or device wakeup
- *              (such GPEs have to be enabled directly when the devices whose
- *              _PRW methods point to them are set up for wakeup signaling).
- *
- ******************************************************************************/
-
-acpi_status acpi_update_gpes(void)
-{
-	acpi_status status;
-
-	ACPI_FUNCTION_TRACE(acpi_update_gpes);
-
-	status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
-	if (ACPI_FAILURE(status)) {
-		return_ACPI_STATUS(status);
-	} else if (acpi_all_gpes_initialized) {
-		goto unlock;
-	}
-
-	status = acpi_ev_walk_gpe_list(acpi_ev_initialize_gpe_block, NULL);
-	if (ACPI_SUCCESS(status)) {
-		acpi_all_gpes_initialized = TRUE;
-	}
-
-unlock:
-	(void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
-
-	return_ACPI_STATUS(status);
-}
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/evxfgpe.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/evxfgpe.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/evxfgpe.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/evxfgpe.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,696 @@
+/******************************************************************************
+ *
+ * Module Name: evxfgpe - External Interfaces for General Purpose Events (GPEs)
+ *
+ *****************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2011, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions, and the following disclaimer,
+ *    without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ *    substantially similar to the "NO WARRANTY" disclaimer below
+ *    ("Disclaimer") and any redistribution must be conditioned upon
+ *    including a substantially similar Disclaimer requirement for further
+ *    binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ *    of any 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") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ */
+
+#include <acpi/acpi.h>
+#include "accommon.h"
+#include "acevents.h"
+#include "acnamesp.h"
+
+#define _COMPONENT          ACPI_EVENTS
+ACPI_MODULE_NAME("evxfgpe")
+
+/******************************************************************************
+ *
+ * FUNCTION:    acpi_update_all_gpes
+ *
+ * PARAMETERS:  None
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Complete GPE initialization and enable all GPEs that have
+ *              associated _Lxx or _Exx methods and are not pointed to by any
+ *              device _PRW methods (this indicates that these GPEs are
+ *              generally intended for system or device wakeup. Such GPEs
+ *              have to be enabled directly when the devices whose _PRW
+ *              methods point to them are set up for wakeup signaling.)
+ *
+ * NOTE: Should be called after any GPEs are added to the system. Primarily,
+ * after the system _PRW methods have been run, but also after a GPE Block
+ * Device has been added or if any new GPE methods have been added via a
+ * dynamic table load.
+ *
+ ******************************************************************************/
+
+acpi_status acpi_update_all_gpes(void)
+{
+	acpi_status status;
+
+	ACPI_FUNCTION_TRACE(acpi_update_all_gpes);
+
+	status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
+	if (ACPI_FAILURE(status)) {
+		return_ACPI_STATUS(status);
+	}
+
+	if (acpi_gbl_all_gpes_initialized) {
+		goto unlock_and_exit;
+	}
+
+	status = acpi_ev_walk_gpe_list(acpi_ev_initialize_gpe_block, NULL);
+	if (ACPI_SUCCESS(status)) {
+		acpi_gbl_all_gpes_initialized = TRUE;
+	}
+
+unlock_and_exit:
+	(void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
+
+	return_ACPI_STATUS(status);
+}
+
+ACPI_EXPORT_SYMBOL(acpi_update_all_gpes)
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_enable_gpe
+ *
+ * PARAMETERS:  gpe_device      - Parent GPE Device. NULL for GPE0/GPE1
+ *              gpe_number      - GPE level within the GPE block
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Add a reference to a GPE. On the first reference, the GPE is
+ *              hardware-enabled.
+ *
+ ******************************************************************************/
+
+acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number)
+{
+	acpi_status status = AE_BAD_PARAMETER;
+	struct acpi_gpe_event_info *gpe_event_info;
+	acpi_cpu_flags flags;
+
+	ACPI_FUNCTION_TRACE(acpi_enable_gpe);
+
+	flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
+
+	/* Ensure that we have a valid GPE number */
+
+	gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
+	if (gpe_event_info) {
+		status = acpi_ev_add_gpe_reference(gpe_event_info);
+	}
+
+	acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
+	return_ACPI_STATUS(status);
+}
+ACPI_EXPORT_SYMBOL(acpi_enable_gpe)
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_disable_gpe
+ *
+ * PARAMETERS:  gpe_device      - Parent GPE Device. NULL for GPE0/GPE1
+ *              gpe_number      - GPE level within the GPE block
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Remove a reference to a GPE. When the last reference is
+ *              removed, only then is the GPE disabled (for runtime GPEs), or
+ *              the GPE mask bit disabled (for wake GPEs)
+ *
+ ******************************************************************************/
+
+acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number)
+{
+	acpi_status status = AE_BAD_PARAMETER;
+	struct acpi_gpe_event_info *gpe_event_info;
+	acpi_cpu_flags flags;
+
+	ACPI_FUNCTION_TRACE(acpi_disable_gpe);
+
+	flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
+
+	/* Ensure that we have a valid GPE number */
+
+	gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
+	if (gpe_event_info) {
+		status = acpi_ev_remove_gpe_reference(gpe_event_info) ;
+	}
+
+	acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
+	return_ACPI_STATUS(status);
+}
+ACPI_EXPORT_SYMBOL(acpi_disable_gpe)
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_setup_gpe_for_wake
+ *
+ * PARAMETERS:  wake_device         - Device associated with the GPE (via _PRW)
+ *              gpe_device          - Parent GPE Device. NULL for GPE0/GPE1
+ *              gpe_number          - GPE level within the GPE block
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Mark a GPE as having the ability to wake the system. This
+ *              interface is intended to be used as the host executes the
+ *              _PRW methods (Power Resources for Wake) in the system tables.
+ *              Each _PRW appears under a Device Object (The wake_device), and
+ *              contains the info for the wake GPE associated with the
+ *              wake_device.
+ *
+ ******************************************************************************/
+acpi_status
+acpi_setup_gpe_for_wake(acpi_handle wake_device,
+			acpi_handle gpe_device, u32 gpe_number)
+{
+	acpi_status status = AE_BAD_PARAMETER;
+	struct acpi_gpe_event_info *gpe_event_info;
+	struct acpi_namespace_node *device_node;
+	struct acpi_gpe_notify_object *notify_object;
+	acpi_cpu_flags flags;
+	u8 gpe_dispatch_mask;
+
+	ACPI_FUNCTION_TRACE(acpi_setup_gpe_for_wake);
+
+	/* Parameter Validation */
+
+	if (!wake_device) {
+		/*
+		 * By forcing wake_device to be valid, we automatically enable the
+		 * implicit notify feature on all hosts.
+		 */
+		return_ACPI_STATUS(AE_BAD_PARAMETER);
+	}
+
+	flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
+
+	/* Ensure that we have a valid GPE number */
+
+	gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
+	if (!gpe_event_info) {
+		goto unlock_and_exit;
+	}
+
+	if (wake_device == ACPI_ROOT_OBJECT) {
+		goto out;
+	}
+
+	/*
+	 * If there is no method or handler for this GPE, then the
+	 * wake_device will be notified whenever this GPE fires (aka
+	 * "implicit notify") Note: The GPE is assumed to be
+	 * level-triggered (for windows compatibility).
+	 */
+	gpe_dispatch_mask = gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK;
+	if (gpe_dispatch_mask != ACPI_GPE_DISPATCH_NONE
+	    && gpe_dispatch_mask != ACPI_GPE_DISPATCH_NOTIFY) {
+		goto out;
+	}
+
+	/* Validate wake_device is of type Device */
+
+	device_node = ACPI_CAST_PTR(struct acpi_namespace_node, wake_device);
+	if (device_node->type != ACPI_TYPE_DEVICE) {
+		goto unlock_and_exit;
+	}
+
+	if (gpe_dispatch_mask == ACPI_GPE_DISPATCH_NONE) {
+		gpe_event_info->flags = (ACPI_GPE_DISPATCH_NOTIFY |
+					 ACPI_GPE_LEVEL_TRIGGERED);
+		gpe_event_info->dispatch.device.node = device_node;
+		gpe_event_info->dispatch.device.next = NULL;
+	} else {
+		/* There are multiple devices to notify implicitly. */
+
+		notify_object = ACPI_ALLOCATE_ZEROED(sizeof(*notify_object));
+		if (!notify_object) {
+			status = AE_NO_MEMORY;
+			goto unlock_and_exit;
+		}
+
+		notify_object->node = device_node;
+		notify_object->next = gpe_event_info->dispatch.device.next;
+		gpe_event_info->dispatch.device.next = notify_object;
+	}
+
+ out:
+	gpe_event_info->flags |= ACPI_GPE_CAN_WAKE;
+	status = AE_OK;
+
+ unlock_and_exit:
+	acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
+	return_ACPI_STATUS(status);
+}
+ACPI_EXPORT_SYMBOL(acpi_setup_gpe_for_wake)
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_set_gpe_wake_mask
+ *
+ * PARAMETERS:  gpe_device      - Parent GPE Device. NULL for GPE0/GPE1
+ *              gpe_number      - GPE level within the GPE block
+ *              Action          - Enable or Disable
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Set or clear the GPE's wakeup enable mask bit. The GPE must
+ *              already be marked as a WAKE GPE.
+ *
+ ******************************************************************************/
+
+acpi_status acpi_set_gpe_wake_mask(acpi_handle gpe_device, u32 gpe_number, u8 action)
+{
+	acpi_status status = AE_OK;
+	struct acpi_gpe_event_info *gpe_event_info;
+	struct acpi_gpe_register_info *gpe_register_info;
+	acpi_cpu_flags flags;
+	u32 register_bit;
+
+	ACPI_FUNCTION_TRACE(acpi_set_gpe_wake_mask);
+
+	flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
+
+	/*
+	 * Ensure that we have a valid GPE number and that this GPE is in
+	 * fact a wake GPE
+	 */
+	gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
+	if (!gpe_event_info) {
+		status = AE_BAD_PARAMETER;
+		goto unlock_and_exit;
+	}
+
+	if (!(gpe_event_info->flags & ACPI_GPE_CAN_WAKE)) {
+		status = AE_TYPE;
+		goto unlock_and_exit;
+	}
+
+	gpe_register_info = gpe_event_info->register_info;
+	if (!gpe_register_info) {
+		status = AE_NOT_EXIST;
+		goto unlock_and_exit;
+	}
+
+	register_bit =
+	    acpi_hw_get_gpe_register_bit(gpe_event_info, gpe_register_info);
+
+	/* Perform the action */
+
+	switch (action) {
+	case ACPI_GPE_ENABLE:
+		ACPI_SET_BIT(gpe_register_info->enable_for_wake,
+			     (u8)register_bit);
+		break;
+
+	case ACPI_GPE_DISABLE:
+		ACPI_CLEAR_BIT(gpe_register_info->enable_for_wake,
+			       (u8)register_bit);
+		break;
+
+	default:
+		ACPI_ERROR((AE_INFO, "%u, Invalid action", action));
+		status = AE_BAD_PARAMETER;
+		break;
+	}
+
+unlock_and_exit:
+	acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
+	return_ACPI_STATUS(status);
+}
+
+ACPI_EXPORT_SYMBOL(acpi_set_gpe_wake_mask)
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_clear_gpe
+ *
+ * PARAMETERS:  gpe_device      - Parent GPE Device. NULL for GPE0/GPE1
+ *              gpe_number      - GPE level within the GPE block
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Clear an ACPI event (general purpose)
+ *
+ ******************************************************************************/
+acpi_status acpi_clear_gpe(acpi_handle gpe_device, u32 gpe_number)
+{
+	acpi_status status = AE_OK;
+	struct acpi_gpe_event_info *gpe_event_info;
+	acpi_cpu_flags flags;
+
+	ACPI_FUNCTION_TRACE(acpi_clear_gpe);
+
+	flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
+
+	/* Ensure that we have a valid GPE number */
+
+	gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
+	if (!gpe_event_info) {
+		status = AE_BAD_PARAMETER;
+		goto unlock_and_exit;
+	}
+
+	status = acpi_hw_clear_gpe(gpe_event_info);
+
+      unlock_and_exit:
+	acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
+	return_ACPI_STATUS(status);
+}
+
+ACPI_EXPORT_SYMBOL(acpi_clear_gpe)
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_get_gpe_status
+ *
+ * PARAMETERS:  gpe_device      - Parent GPE Device. NULL for GPE0/GPE1
+ *              gpe_number      - GPE level within the GPE block
+ *              event_status    - Where the current status of the event will
+ *                                be returned
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Get the current status of a GPE (signalled/not_signalled)
+ *
+ ******************************************************************************/
+acpi_status
+acpi_get_gpe_status(acpi_handle gpe_device,
+		    u32 gpe_number, acpi_event_status *event_status)
+{
+	acpi_status status = AE_OK;
+	struct acpi_gpe_event_info *gpe_event_info;
+	acpi_cpu_flags flags;
+
+	ACPI_FUNCTION_TRACE(acpi_get_gpe_status);
+
+	flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
+
+	/* Ensure that we have a valid GPE number */
+
+	gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
+	if (!gpe_event_info) {
+		status = AE_BAD_PARAMETER;
+		goto unlock_and_exit;
+	}
+
+	/* Obtain status on the requested GPE number */
+
+	status = acpi_hw_get_gpe_status(gpe_event_info, event_status);
+
+	if (gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK)
+		*event_status |= ACPI_EVENT_FLAG_HANDLE;
+
+      unlock_and_exit:
+	acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
+	return_ACPI_STATUS(status);
+}
+
+ACPI_EXPORT_SYMBOL(acpi_get_gpe_status)
+
+/******************************************************************************
+ *
+ * FUNCTION:    acpi_disable_all_gpes
+ *
+ * PARAMETERS:  None
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Disable and clear all GPEs in all GPE blocks
+ *
+ ******************************************************************************/
+
+acpi_status acpi_disable_all_gpes(void)
+{
+	acpi_status status;
+
+	ACPI_FUNCTION_TRACE(acpi_disable_all_gpes);
+
+	status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
+	if (ACPI_FAILURE(status)) {
+		return_ACPI_STATUS(status);
+	}
+
+	status = acpi_hw_disable_all_gpes();
+	(void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
+
+	return_ACPI_STATUS(status);
+}
+
+ACPI_EXPORT_SYMBOL(acpi_disable_all_gpes)
+
+/******************************************************************************
+ *
+ * FUNCTION:    acpi_enable_all_runtime_gpes
+ *
+ * PARAMETERS:  None
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Enable all "runtime" GPEs, in all GPE blocks
+ *
+ ******************************************************************************/
+
+acpi_status acpi_enable_all_runtime_gpes(void)
+{
+	acpi_status status;
+
+	ACPI_FUNCTION_TRACE(acpi_enable_all_runtime_gpes);
+
+	status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
+	if (ACPI_FAILURE(status)) {
+		return_ACPI_STATUS(status);
+	}
+
+	status = acpi_hw_enable_all_runtime_gpes();
+	(void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
+
+	return_ACPI_STATUS(status);
+}
+
+ACPI_EXPORT_SYMBOL(acpi_enable_all_runtime_gpes)
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_install_gpe_block
+ *
+ * PARAMETERS:  gpe_device          - Handle to the parent GPE Block Device
+ *              gpe_block_address   - Address and space_iD
+ *              register_count      - Number of GPE register pairs in the block
+ *              interrupt_number    - H/W interrupt for the block
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Create and Install a block of GPE registers. The GPEs are not
+ *              enabled here.
+ *
+ ******************************************************************************/
+acpi_status
+acpi_install_gpe_block(acpi_handle gpe_device,
+		       struct acpi_generic_address *gpe_block_address,
+		       u32 register_count, u32 interrupt_number)
+{
+	acpi_status status;
+	union acpi_operand_object *obj_desc;
+	struct acpi_namespace_node *node;
+	struct acpi_gpe_block_info *gpe_block;
+
+	ACPI_FUNCTION_TRACE(acpi_install_gpe_block);
+
+	if ((!gpe_device) || (!gpe_block_address) || (!register_count)) {
+		return_ACPI_STATUS(AE_BAD_PARAMETER);
+	}
+
+	status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+	if (ACPI_FAILURE(status)) {
+		return (status);
+	}
+
+	node = acpi_ns_validate_handle(gpe_device);
+	if (!node) {
+		status = AE_BAD_PARAMETER;
+		goto unlock_and_exit;
+	}
+
+	/*
+	 * For user-installed GPE Block Devices, the gpe_block_base_number
+	 * is always zero
+	 */
+	status =
+	    acpi_ev_create_gpe_block(node, gpe_block_address, register_count, 0,
+				     interrupt_number, &gpe_block);
+	if (ACPI_FAILURE(status)) {
+		goto unlock_and_exit;
+	}
+
+	/* Install block in the device_object attached to the node */
+
+	obj_desc = acpi_ns_get_attached_object(node);
+	if (!obj_desc) {
+
+		/*
+		 * No object, create a new one (Device nodes do not always have
+		 * an attached object)
+		 */
+		obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_DEVICE);
+		if (!obj_desc) {
+			status = AE_NO_MEMORY;
+			goto unlock_and_exit;
+		}
+
+		status =
+		    acpi_ns_attach_object(node, obj_desc, ACPI_TYPE_DEVICE);
+
+		/* Remove local reference to the object */
+
+		acpi_ut_remove_reference(obj_desc);
+
+		if (ACPI_FAILURE(status)) {
+			goto unlock_and_exit;
+		}
+	}
+
+	/* Now install the GPE block in the device_object */
+
+	obj_desc->device.gpe_block = gpe_block;
+
+      unlock_and_exit:
+	(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
+	return_ACPI_STATUS(status);
+}
+
+ACPI_EXPORT_SYMBOL(acpi_install_gpe_block)
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_remove_gpe_block
+ *
+ * PARAMETERS:  gpe_device          - Handle to the parent GPE Block Device
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Remove a previously installed block of GPE registers
+ *
+ ******************************************************************************/
+acpi_status acpi_remove_gpe_block(acpi_handle gpe_device)
+{
+	union acpi_operand_object *obj_desc;
+	acpi_status status;
+	struct acpi_namespace_node *node;
+
+	ACPI_FUNCTION_TRACE(acpi_remove_gpe_block);
+
+	if (!gpe_device) {
+		return_ACPI_STATUS(AE_BAD_PARAMETER);
+	}
+
+	status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+	if (ACPI_FAILURE(status)) {
+		return (status);
+	}
+
+	node = acpi_ns_validate_handle(gpe_device);
+	if (!node) {
+		status = AE_BAD_PARAMETER;
+		goto unlock_and_exit;
+	}
+
+	/* Get the device_object attached to the node */
+
+	obj_desc = acpi_ns_get_attached_object(node);
+	if (!obj_desc || !obj_desc->device.gpe_block) {
+		return_ACPI_STATUS(AE_NULL_OBJECT);
+	}
+
+	/* Delete the GPE block (but not the device_object) */
+
+	status = acpi_ev_delete_gpe_block(obj_desc->device.gpe_block);
+	if (ACPI_SUCCESS(status)) {
+		obj_desc->device.gpe_block = NULL;
+	}
+
+      unlock_and_exit:
+	(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
+	return_ACPI_STATUS(status);
+}
+
+ACPI_EXPORT_SYMBOL(acpi_remove_gpe_block)
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_get_gpe_device
+ *
+ * PARAMETERS:  Index               - System GPE index (0-current_gpe_count)
+ *              gpe_device          - Where the parent GPE Device is returned
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Obtain the GPE device associated with the input index. A NULL
+ *              gpe device indicates that the gpe number is contained in one of
+ *              the FADT-defined gpe blocks. Otherwise, the GPE block device.
+ *
+ ******************************************************************************/
+acpi_status
+acpi_get_gpe_device(u32 index, acpi_handle *gpe_device)
+{
+	struct acpi_gpe_device_info info;
+	acpi_status status;
+
+	ACPI_FUNCTION_TRACE(acpi_get_gpe_device);
+
+	if (!gpe_device) {
+		return_ACPI_STATUS(AE_BAD_PARAMETER);
+	}
+
+	if (index >= acpi_current_gpe_count) {
+		return_ACPI_STATUS(AE_NOT_EXIST);
+	}
+
+	/* Setup and walk the GPE list */
+
+	info.index = index;
+	info.status = AE_NOT_EXIST;
+	info.gpe_device = NULL;
+	info.next_block_base_index = 0;
+
+	status = acpi_ev_walk_gpe_list(acpi_ev_get_gpe_device, &info);
+	if (ACPI_FAILURE(status)) {
+		return_ACPI_STATUS(status);
+	}
+
+	*gpe_device = ACPI_CAST_PTR(acpi_handle, info.gpe_device);
+	return_ACPI_STATUS(info.status);
+}
+
+ACPI_EXPORT_SYMBOL(acpi_get_gpe_device)
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/evxfregn.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/evxfregn.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/evxfregn.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/evxfregn.c	2011-03-14 21:20:32.000000000 -0400
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/exconfig.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/exconfig.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/exconfig.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/exconfig.c	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/exconvrt.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/exconvrt.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/exconvrt.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/exconvrt.c	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/excreate.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/excreate.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/excreate.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/excreate.c	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -482,13 +482,11 @@ acpi_ex_create_method(u8 * aml_start,
 	obj_desc->method.aml_length = aml_length;
 
 	/*
-	 * Disassemble the method flags. Split off the Arg Count
-	 * for efficiency
+	 * Disassemble the method flags. Split off the arg_count, Serialized
+	 * flag, and sync_level for efficiency.
 	 */
 	method_flags = (u8) operand[1]->integer.value;
 
-	obj_desc->method.method_flags =
-	    (u8) (method_flags & ~AML_METHOD_ARG_COUNT);
 	obj_desc->method.param_count =
 	    (u8) (method_flags & AML_METHOD_ARG_COUNT);
 
@@ -497,6 +495,8 @@ acpi_ex_create_method(u8 * aml_start,
 	 * created for this method when it is parsed.
 	 */
 	if (method_flags & AML_METHOD_SERIALIZED) {
+		obj_desc->method.info_flags = ACPI_METHOD_SERIALIZED;
+
 		/*
 		 * ACPI 1.0: sync_level = 0
 		 * ACPI 2.0: sync_level = sync_level in method declaration
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/exdebug.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/exdebug.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/exdebug.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/exdebug.c	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/exdump.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/exdump.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/exdump.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/exdump.c	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -122,7 +122,7 @@ static struct acpi_exdump_info acpi_ex_d
 
 static struct acpi_exdump_info acpi_ex_dump_method[9] = {
 	{ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_method), NULL},
-	{ACPI_EXD_UINT8, ACPI_EXD_OFFSET(method.method_flags), "Method Flags"},
+	{ACPI_EXD_UINT8, ACPI_EXD_OFFSET(method.info_flags), "Info Flags"},
 	{ACPI_EXD_UINT8, ACPI_EXD_OFFSET(method.param_count),
 	 "Parameter Count"},
 	{ACPI_EXD_UINT8, ACPI_EXD_OFFSET(method.sync_level), "Sync Level"},
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/exfield.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/exfield.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/exfield.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/exfield.c	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/exfldio.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/exfldio.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/exfldio.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/exfldio.c	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/exmisc.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/exmisc.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/exmisc.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/exmisc.c	2011-03-14 21:20:32.000000000 -0400
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/exmutex.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/exmutex.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/exmutex.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/exmutex.c	2011-03-14 21:20:32.000000000 -0400
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/exnames.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/exnames.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/exnames.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/exnames.c	2011-03-14 21:20:32.000000000 -0400
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/exoparg1.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/exoparg1.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/exoparg1.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/exoparg1.c	2011-03-14 21:20:32.000000000 -0400
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/exoparg2.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/exoparg2.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/exoparg2.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/exoparg2.c	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/exoparg3.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/exoparg3.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/exoparg3.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/exoparg3.c	2011-03-14 21:20:32.000000000 -0400
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/exoparg6.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/exoparg6.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/exoparg6.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/exoparg6.c	2011-03-14 21:20:32.000000000 -0400
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/exprep.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/exprep.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/exprep.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/exprep.c	2011-03-14 21:20:32.000000000 -0400
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/exregion.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/exregion.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/exregion.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/exregion.c	2011-03-14 21:20:32.000000000 -0400
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/exresnte.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/exresnte.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/exresnte.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/exresnte.c	2011-03-14 21:20:32.000000000 -0400
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/exresolv.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/exresolv.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/exresolv.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/exresolv.c	2011-03-14 21:20:32.000000000 -0400
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/exresop.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/exresop.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/exresop.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/exresop.c	2011-03-14 21:20:32.000000000 -0400
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/exstore.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/exstore.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/exstore.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/exstore.c	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/exstoren.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/exstoren.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/exstoren.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/exstoren.c	2011-03-14 21:20:32.000000000 -0400
@@ -7,7 +7,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/exstorob.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/exstorob.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/exstorob.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/exstorob.c	2011-03-14 21:20:32.000000000 -0400
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/exsystem.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/exsystem.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/exsystem.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/exsystem.c	2011-03-14 21:20:32.000000000 -0400
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/exutils.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/exutils.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/exutils.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/exutils.c	2011-03-14 21:20:32.000000000 -0400
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/hwacpi.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/hwacpi.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/hwacpi.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/hwacpi.c	2011-03-14 21:20:32.000000000 -0400
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/hwgpe.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/hwgpe.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/hwgpe.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/hwgpe.c	2011-03-14 21:20:32.000000000 -0400
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -62,10 +62,10 @@ acpi_hw_enable_wakeup_gpe_block(struct a
  * PARAMETERS:	gpe_event_info	    - Info block for the GPE
  *		gpe_register_info   - Info block for the GPE register
  *
- * RETURN:	Status
+ * RETURN:	Register mask with a one in the GPE bit position
  *
- * DESCRIPTION:	Compute GPE enable mask with one bit corresponding to the given
- *		GPE set.
+ * DESCRIPTION: Compute the register mask for this GPE. One bit is set in the
+ *              correct position for the input GPE.
  *
  ******************************************************************************/
 
@@ -85,12 +85,12 @@ u32 acpi_hw_get_gpe_register_bit(struct
  *
  * RETURN:	Status
  *
- * DESCRIPTION: Enable or disable a single GPE in its enable register.
+ * DESCRIPTION: Enable or disable a single GPE in the parent enable register.
  *
  ******************************************************************************/
 
 acpi_status
-acpi_hw_low_set_gpe(struct acpi_gpe_event_info *gpe_event_info, u8 action)
+acpi_hw_low_set_gpe(struct acpi_gpe_event_info *gpe_event_info, u32 action)
 {
 	struct acpi_gpe_register_info *gpe_register_info;
 	acpi_status status;
@@ -113,14 +113,20 @@ acpi_hw_low_set_gpe(struct acpi_gpe_even
 		return (status);
 	}
 
-	/* Set ot clear just the bit that corresponds to this GPE */
+	/* Set or clear just the bit that corresponds to this GPE */
 
 	register_bit = acpi_hw_get_gpe_register_bit(gpe_event_info,
 						gpe_register_info);
 	switch (action) {
-	case ACPI_GPE_COND_ENABLE:
-		if (!(register_bit & gpe_register_info->enable_for_run))
+	case ACPI_GPE_CONDITIONAL_ENABLE:
+
+		/* Only enable if the enable_for_run bit is set */
+
+		if (!(register_bit & gpe_register_info->enable_for_run)) {
 			return (AE_BAD_PARAMETER);
+		}
+
+		/*lint -fallthrough */
 
 	case ACPI_GPE_ENABLE:
 		ACPI_SET_BIT(enable_mask, register_bit);
@@ -131,7 +137,7 @@ acpi_hw_low_set_gpe(struct acpi_gpe_even
 		break;
 
 	default:
-		ACPI_ERROR((AE_INFO, "Invalid action\n"));
+		ACPI_ERROR((AE_INFO, "Invalid GPE Action, %u\n", action));
 		return (AE_BAD_PARAMETER);
 	}
 
@@ -168,13 +174,13 @@ acpi_status acpi_hw_clear_gpe(struct acp
 		return (AE_NOT_EXIST);
 	}
 
-	register_bit = acpi_hw_get_gpe_register_bit(gpe_event_info,
-						gpe_register_info);
-
 	/*
 	 * Write a one to the appropriate bit in the status register to
 	 * clear this GPE.
 	 */
+	register_bit =
+	    acpi_hw_get_gpe_register_bit(gpe_event_info, gpe_register_info);
+
 	status = acpi_hw_write(register_bit,
 			       &gpe_register_info->status_address);
 
@@ -201,8 +207,8 @@ acpi_hw_get_gpe_status(struct acpi_gpe_e
 	u32 in_byte;
 	u32 register_bit;
 	struct acpi_gpe_register_info *gpe_register_info;
-	acpi_status status;
 	acpi_event_status local_event_status = 0;
+	acpi_status status;
 
 	ACPI_FUNCTION_ENTRY();
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/hwpci.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/hwpci.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/hwpci.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/hwpci.c	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/hwregs.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/hwregs.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/hwregs.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/hwregs.c	2011-03-14 21:20:32.000000000 -0400
@@ -7,7 +7,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/hwsleep.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/hwsleep.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/hwsleep.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/hwsleep.c	2011-03-14 21:20:32.000000000 -0400
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/hwtimer.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/hwtimer.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/hwtimer.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/hwtimer.c	2011-03-14 21:20:32.000000000 -0400
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/hwvalid.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/hwvalid.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/hwvalid.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/hwvalid.c	2011-03-14 21:20:32.000000000 -0400
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/hwxface.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/hwxface.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/hwxface.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/hwxface.c	2011-03-14 21:20:32.000000000 -0400
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/Makefile linux-libre-2.6.38-gnu1/drivers/acpi/acpica/Makefile
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -14,7 +14,7 @@ acpi-y := dsfield.o   dsmthdat.o  dsopco
 
 acpi-y += evevent.o  evregion.o  evsci.o    evxfevnt.o \
 	 evmisc.o   evrgnini.o  evxface.o  evxfregn.o \
-	 evgpe.o    evgpeblk.o evgpeinit.o  evgpeutil.o
+	 evgpe.o    evgpeblk.o evgpeinit.o  evgpeutil.o evxfgpe.o
 
 acpi-y += exconfig.o  exfield.o  exnames.o   exoparg6.o  exresolv.o  exstorob.o\
 	 exconvrt.o  exfldio.o  exoparg1.o  exprep.o    exresop.o   exsystem.o\
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/nsaccess.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/nsaccess.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/nsaccess.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/nsaccess.c	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -163,9 +163,9 @@ acpi_status acpi_ns_root_initialize(void
 #else
 				/* Mark this as a very SPECIAL method */
 
-				obj_desc->method.method_flags =
-				    AML_METHOD_INTERNAL_ONLY;
-				obj_desc->method.extra.implementation =
+				obj_desc->method.info_flags =
+				    ACPI_METHOD_INTERNAL_ONLY;
+				obj_desc->method.dispatch.implementation =
 				    acpi_ut_osi_implementation;
 #endif
 				break;
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/nsalloc.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/nsalloc.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/nsalloc.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/nsalloc.c	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -234,8 +234,8 @@ void acpi_ns_install_node(struct acpi_wa
 			 * modified the namespace. This is used for cleanup when the
 			 * method exits.
 			 */
-			walk_state->method_desc->method.flags |=
-			    AOPOBJ_MODIFIED_NAMESPACE;
+			walk_state->method_desc->method.info_flags |=
+			    ACPI_METHOD_MODIFIED_NAMESPACE;
 		}
 	}
 
@@ -341,6 +341,7 @@ void acpi_ns_delete_namespace_subtree(st
 {
 	struct acpi_namespace_node *child_node = NULL;
 	u32 level = 1;
+	acpi_status status;
 
 	ACPI_FUNCTION_TRACE(ns_delete_namespace_subtree);
 
@@ -348,6 +349,13 @@ void acpi_ns_delete_namespace_subtree(st
 		return_VOID;
 	}
 
+	/* Lock namespace for possible update */
+
+	status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+	if (ACPI_FAILURE(status)) {
+		return_VOID;
+	}
+
 	/*
 	 * Traverse the tree of objects until we bubble back up
 	 * to where we started.
@@ -397,6 +405,7 @@ void acpi_ns_delete_namespace_subtree(st
 		}
 	}
 
+	(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
 	return_VOID;
 }
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/nsdump.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/nsdump.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/nsdump.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/nsdump.c	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -624,9 +624,22 @@ acpi_ns_dump_objects(acpi_object_type ty
 		     acpi_owner_id owner_id, acpi_handle start_handle)
 {
 	struct acpi_walk_info info;
+	acpi_status status;
 
 	ACPI_FUNCTION_ENTRY();
 
+	/*
+	 * Just lock the entire namespace for the duration of the dump.
+	 * We don't want any changes to the namespace during this time,
+	 * especially the temporary nodes since we are going to display
+	 * them also.
+	 */
+	status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+	if (ACPI_FAILURE(status)) {
+		acpi_os_printf("Could not acquire namespace mutex\n");
+		return;
+	}
+
 	info.debug_level = ACPI_LV_TABLES;
 	info.owner_id = owner_id;
 	info.display_type = display_type;
@@ -636,6 +649,8 @@ acpi_ns_dump_objects(acpi_object_type ty
 				     ACPI_NS_WALK_TEMP_NODES,
 				     acpi_ns_dump_one_object, NULL,
 				     (void *)&info, NULL);
+
+	(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
 }
 #endif				/* ACPI_FUTURE_USAGE */
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/nsdumpdv.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/nsdumpdv.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/nsdumpdv.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/nsdumpdv.c	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/nseval.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/nseval.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/nseval.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/nseval.c	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -389,7 +389,7 @@ acpi_ns_exec_module_code(union acpi_oper
 	 * acpi_gbl_root_node->Object is NULL at PASS1.
 	 */
 	if ((type == ACPI_TYPE_DEVICE) && parent_node->object) {
-		method_obj->method.extra.handler =
+		method_obj->method.dispatch.handler =
 		    parent_node->object->device.handler;
 	}
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/nsinit.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/nsinit.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/nsinit.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/nsinit.c	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -577,9 +577,7 @@ acpi_ns_init_one_device(acpi_handle obj_
 	 * as possible (without an NMI being received in the middle of
 	 * this) - so disable NMIs and initialize the device:
 	 */
-	acpi_nmi_disable();
 	status = acpi_ns_evaluate(info);
-	acpi_nmi_enable();
 
 	if (ACPI_SUCCESS(status)) {
 		walk_info->num_INI++;
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/nsload.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/nsload.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/nsload.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/nsload.c	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/nsnames.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/nsnames.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/nsnames.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/nsnames.c	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/nsobject.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/nsobject.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/nsobject.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/nsobject.c	2011-03-14 21:20:32.000000000 -0400
@@ -6,7 +6,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/nsparse.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/nsparse.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/nsparse.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/nsparse.c	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/nspredef.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/nspredef.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/nspredef.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/nspredef.c	2011-03-14 21:20:32.000000000 -0400
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/nsrepair2.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/nsrepair2.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/nsrepair2.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/nsrepair2.c	2011-03-14 21:20:32.000000000 -0400
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/nsrepair.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/nsrepair.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/nsrepair.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/nsrepair.c	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/nssearch.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/nssearch.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/nssearch.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/nssearch.c	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/nsutils.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/nsutils.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/nsutils.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/nsutils.c	2011-03-14 21:20:32.000000000 -0400
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/nswalk.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/nswalk.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/nswalk.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/nswalk.c	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/nsxfeval.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/nsxfeval.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/nsxfeval.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/nsxfeval.c	2011-03-14 21:20:32.000000000 -0400
@@ -6,7 +6,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/nsxfname.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/nsxfname.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/nsxfname.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/nsxfname.c	2011-03-14 21:20:32.000000000 -0400
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -603,10 +603,9 @@ acpi_status acpi_install_method(u8 *buff
 	method_obj->method.param_count = (u8)
 	    (method_flags & AML_METHOD_ARG_COUNT);
 
-	method_obj->method.method_flags = (u8)
-	    (method_flags & ~AML_METHOD_ARG_COUNT);
-
 	if (method_flags & AML_METHOD_SERIALIZED) {
+		method_obj->method.info_flags = ACPI_METHOD_SERIALIZED;
+
 		method_obj->method.sync_level = (u8)
 		    ((method_flags & AML_METHOD_SYNC_LEVEL) >> 4);
 	}
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/nsxfobj.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/nsxfobj.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/nsxfobj.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/nsxfobj.c	2011-03-14 21:20:32.000000000 -0400
@@ -6,7 +6,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/psargs.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/psargs.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/psargs.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/psargs.c	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/psloop.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/psloop.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/psloop.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/psloop.c	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -655,7 +655,7 @@ acpi_ps_link_module_code(union acpi_pars
 		method_obj->method.aml_start = aml_start;
 		method_obj->method.aml_length = aml_length;
 		method_obj->method.owner_id = owner_id;
-		method_obj->method.flags |= AOPOBJ_MODULE_LEVEL;
+		method_obj->method.info_flags |= ACPI_METHOD_MODULE_LEVEL;
 
 		/*
 		 * Save the parent node in next_object. This is cheating, but we
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/psopcode.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/psopcode.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/psopcode.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/psopcode.c	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/psparse.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/psparse.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/psparse.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/psparse.c	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -55,7 +55,6 @@
 #include "acparser.h"
 #include "acdispat.h"
 #include "amlcode.h"
-#include "acnamesp.h"
 #include "acinterp.h"
 
 #define _COMPONENT          ACPI_PARSER
@@ -539,24 +538,16 @@ acpi_status acpi_ps_parse_aml(struct acp
 			/* Check for possible multi-thread reentrancy problem */
 
 			if ((status == AE_ALREADY_EXISTS) &&
-			    (!walk_state->method_desc->method.mutex)) {
-				ACPI_INFO((AE_INFO,
-					   "Marking method %4.4s as Serialized because of AE_ALREADY_EXISTS error",
-					   walk_state->method_node->name.
-					   ascii));
-
+			    (!(walk_state->method_desc->method.
+			       info_flags & ACPI_METHOD_SERIALIZED))) {
 				/*
-				 * Method tried to create an object twice. The probable cause is
-				 * that the method cannot handle reentrancy.
-				 *
-				 * The method is marked not_serialized, but it tried to create
-				 * a named object, causing the second thread entrance to fail.
-				 * Workaround this problem by marking the method permanently
-				 * as Serialized.
+				 * Method is not serialized and tried to create an object
+				 * twice. The probable cause is that the method cannot
+				 * handle reentrancy. Mark as "pending serialized" now, and
+				 * then mark "serialized" when the last thread exits.
 				 */
-				walk_state->method_desc->method.method_flags |=
-				    AML_METHOD_SERIALIZED;
-				walk_state->method_desc->method.sync_level = 0;
+				walk_state->method_desc->method.info_flags |=
+				    ACPI_METHOD_SERIALIZED_PENDING;
 			}
 		}
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/psscope.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/psscope.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/psscope.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/psscope.c	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/pstree.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/pstree.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/pstree.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/pstree.c	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/psutils.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/psutils.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/psutils.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/psutils.c	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/pswalk.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/pswalk.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/pswalk.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/pswalk.c	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/psxface.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/psxface.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/psxface.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/psxface.c	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -47,7 +47,6 @@
 #include "acdispat.h"
 #include "acinterp.h"
 #include "actables.h"
-#include "amlcode.h"
 
 #define _COMPONENT          ACPI_PARSER
 ACPI_MODULE_NAME("psxface")
@@ -285,15 +284,15 @@ acpi_status acpi_ps_execute_method(struc
 		goto cleanup;
 	}
 
-	if (info->obj_desc->method.flags & AOPOBJ_MODULE_LEVEL) {
+	if (info->obj_desc->method.info_flags & ACPI_METHOD_MODULE_LEVEL) {
 		walk_state->parse_flags |= ACPI_PARSE_MODULE_LEVEL;
 	}
 
 	/* Invoke an internal method if necessary */
 
-	if (info->obj_desc->method.method_flags & AML_METHOD_INTERNAL_ONLY) {
+	if (info->obj_desc->method.info_flags & ACPI_METHOD_INTERNAL_ONLY) {
 		status =
-		    info->obj_desc->method.extra.implementation(walk_state);
+		    info->obj_desc->method.dispatch.implementation(walk_state);
 		info->return_object = walk_state->return_desc;
 
 		/* Cleanup states */
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/rsaddr.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/rsaddr.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/rsaddr.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/rsaddr.c	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/rscalc.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/rscalc.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/rscalc.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/rscalc.c	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/rscreate.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/rscreate.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/rscreate.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/rscreate.c	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/rsdump.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/rsdump.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/rsdump.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/rsdump.c	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/rsinfo.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/rsinfo.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/rsinfo.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/rsinfo.c	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/rsio.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/rsio.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/rsio.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/rsio.c	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/rsirq.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/rsirq.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/rsirq.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/rsirq.c	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/rslist.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/rslist.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/rslist.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/rslist.c	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/rsmemory.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/rsmemory.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/rsmemory.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/rsmemory.c	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/rsmisc.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/rsmisc.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/rsmisc.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/rsmisc.c	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/rsutils.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/rsutils.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/rsutils.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/rsutils.c	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/rsxface.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/rsxface.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/rsxface.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/rsxface.c	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/tbfadt.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/tbfadt.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/tbfadt.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/tbfadt.c	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/tbfind.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/tbfind.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/tbfind.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/tbfind.c	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/tbinstal.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/tbinstal.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/tbinstal.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/tbinstal.c	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/tbutils.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/tbutils.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/tbutils.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/tbutils.c	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/tbxface.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/tbxface.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/tbxface.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/tbxface.c	2011-03-14 21:20:32.000000000 -0400
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/tbxfroot.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/tbxfroot.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/tbxfroot.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/tbxfroot.c	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/utalloc.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/utalloc.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/utalloc.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/utalloc.c	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/utcopy.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/utcopy.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/utcopy.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/utcopy.c	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/utdebug.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/utdebug.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/utdebug.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/utdebug.c	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/utdelete.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/utdelete.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/utdelete.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/utdelete.c	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/uteval.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/uteval.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/uteval.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/uteval.c	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/utglobal.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/utglobal.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/utglobal.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/utglobal.c	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -768,7 +768,7 @@ acpi_status acpi_ut_init_globals(void)
 	acpi_gbl_gpe_fadt_blocks[0] = NULL;
 	acpi_gbl_gpe_fadt_blocks[1] = NULL;
 	acpi_current_gpe_count = 0;
-	acpi_all_gpes_initialized = FALSE;
+	acpi_gbl_all_gpes_initialized = FALSE;
 
 	/* Global handlers */
 
@@ -778,6 +778,7 @@ acpi_status acpi_ut_init_globals(void)
 	acpi_gbl_init_handler = NULL;
 	acpi_gbl_table_handler = NULL;
 	acpi_gbl_interface_handler = NULL;
+	acpi_gbl_global_event_handler = NULL;
 
 	/* Global Lock support */
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/utids.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/utids.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/utids.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/utids.c	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/utinit.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/utinit.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/utinit.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/utinit.c	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/utlock.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/utlock.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/utlock.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/utlock.c	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/utmath.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/utmath.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/utmath.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/utmath.c	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/utmisc.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/utmisc.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/utmisc.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/utmisc.c	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/utmutex.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/utmutex.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/utmutex.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/utmutex.c	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -85,6 +85,7 @@ acpi_status acpi_ut_mutex_initialize(voi
 
 	spin_lock_init(acpi_gbl_gpe_lock);
 	spin_lock_init(acpi_gbl_hardware_lock);
+	spin_lock_init(acpi_ev_global_lock_pending_lock);
 
 	/* Mutex for _OSI support */
 	status = acpi_os_create_mutex(&acpi_gbl_osi_mutex);
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/utobject.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/utobject.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/utobject.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/utobject.c	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/utosi.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/utosi.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/utosi.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/utosi.c	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/utresrc.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/utresrc.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/utresrc.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/utresrc.c	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/utstate.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/utstate.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/utstate.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/utstate.c	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/utxface.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/utxface.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/utxface.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/utxface.c	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpica/utxferror.c linux-libre-2.6.38-gnu1/drivers/acpi/acpica/utxferror.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpica/utxferror.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpica/utxferror.c	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
  ******************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/acpi_ipmi.c linux-libre-2.6.38-gnu1/drivers/acpi/acpi_ipmi.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/acpi_ipmi.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/acpi_ipmi.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,525 @@
+/*
+ *  acpi_ipmi.c - ACPI IPMI opregion
+ *
+ *  Copyright (C) 2010 Intel Corporation
+ *  Copyright (C) 2010 Zhao Yakui <yakui.zhao@intel.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/module.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/delay.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/io.h>
+#include <acpi/acpi_bus.h>
+#include <acpi/acpi_drivers.h>
+#include <linux/ipmi.h>
+#include <linux/device.h>
+#include <linux/pnp.h>
+
+MODULE_AUTHOR("Zhao Yakui");
+MODULE_DESCRIPTION("ACPI IPMI Opregion driver");
+MODULE_LICENSE("GPL");
+
+#define IPMI_FLAGS_HANDLER_INSTALL	0
+
+#define ACPI_IPMI_OK			0
+#define ACPI_IPMI_TIMEOUT		0x10
+#define ACPI_IPMI_UNKNOWN		0x07
+/* the IPMI timeout is 5s */
+#define IPMI_TIMEOUT			(5 * HZ)
+
+struct acpi_ipmi_device {
+	/* the device list attached to driver_data.ipmi_devices */
+	struct list_head head;
+	/* the IPMI request message list */
+	struct list_head tx_msg_list;
+	struct mutex	tx_msg_lock;
+	acpi_handle handle;
+	struct pnp_dev *pnp_dev;
+	ipmi_user_t	user_interface;
+	int ipmi_ifnum; /* IPMI interface number */
+	long curr_msgid;
+	unsigned long flags;
+	struct ipmi_smi_info smi_data;
+};
+
+struct ipmi_driver_data {
+	struct list_head	ipmi_devices;
+	struct ipmi_smi_watcher	bmc_events;
+	struct ipmi_user_hndl	ipmi_hndlrs;
+	struct mutex		ipmi_lock;
+};
+
+struct acpi_ipmi_msg {
+	struct list_head head;
+	/*
+	 * General speaking the addr type should be SI_ADDR_TYPE. And
+	 * the addr channel should be BMC.
+	 * In fact it can also be IPMB type. But we will have to
+	 * parse it from the Netfn command buffer. It is so complex
+	 * that it is skipped.
+	 */
+	struct ipmi_addr addr;
+	long tx_msgid;
+	/* it is used to track whether the IPMI message is finished */
+	struct completion tx_complete;
+	struct kernel_ipmi_msg tx_message;
+	int	msg_done;
+	/* tx data . And copy it from ACPI object buffer */
+	u8	tx_data[64];
+	int	tx_len;
+	u8	rx_data[64];
+	int	rx_len;
+	struct acpi_ipmi_device *device;
+};
+
+/* IPMI request/response buffer per ACPI 4.0, sec 5.5.2.4.3.2 */
+struct acpi_ipmi_buffer {
+	u8 status;
+	u8 length;
+	u8 data[64];
+};
+
+static void ipmi_register_bmc(int iface, struct device *dev);
+static void ipmi_bmc_gone(int iface);
+static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data);
+static void acpi_add_ipmi_device(struct acpi_ipmi_device *ipmi_device);
+static void acpi_remove_ipmi_device(struct acpi_ipmi_device *ipmi_device);
+
+static struct ipmi_driver_data driver_data = {
+	.ipmi_devices = LIST_HEAD_INIT(driver_data.ipmi_devices),
+	.bmc_events = {
+		.owner = THIS_MODULE,
+		.new_smi = ipmi_register_bmc,
+		.smi_gone = ipmi_bmc_gone,
+	},
+	.ipmi_hndlrs = {
+		.ipmi_recv_hndl = ipmi_msg_handler,
+	},
+};
+
+static struct acpi_ipmi_msg *acpi_alloc_ipmi_msg(struct acpi_ipmi_device *ipmi)
+{
+	struct acpi_ipmi_msg *ipmi_msg;
+	struct pnp_dev *pnp_dev = ipmi->pnp_dev;
+
+	ipmi_msg = kzalloc(sizeof(struct acpi_ipmi_msg), GFP_KERNEL);
+	if (!ipmi_msg)	{
+		dev_warn(&pnp_dev->dev, "Can't allocate memory for ipmi_msg\n");
+		return NULL;
+	}
+	init_completion(&ipmi_msg->tx_complete);
+	INIT_LIST_HEAD(&ipmi_msg->head);
+	ipmi_msg->device = ipmi;
+	return ipmi_msg;
+}
+
+#define		IPMI_OP_RGN_NETFN(offset)	((offset >> 8) & 0xff)
+#define		IPMI_OP_RGN_CMD(offset)		(offset & 0xff)
+static void acpi_format_ipmi_msg(struct acpi_ipmi_msg *tx_msg,
+				acpi_physical_address address,
+				acpi_integer *value)
+{
+	struct kernel_ipmi_msg *msg;
+	struct acpi_ipmi_buffer *buffer;
+	struct acpi_ipmi_device *device;
+
+	msg = &tx_msg->tx_message;
+	/*
+	 * IPMI network function and command are encoded in the address
+	 * within the IPMI OpRegion; see ACPI 4.0, sec 5.5.2.4.3.
+	 */
+	msg->netfn = IPMI_OP_RGN_NETFN(address);
+	msg->cmd = IPMI_OP_RGN_CMD(address);
+	msg->data = tx_msg->tx_data;
+	/*
+	 * value is the parameter passed by the IPMI opregion space handler.
+	 * It points to the IPMI request message buffer
+	 */
+	buffer = (struct acpi_ipmi_buffer *)value;
+	/* copy the tx message data */
+	msg->data_len = buffer->length;
+	memcpy(tx_msg->tx_data, buffer->data, msg->data_len);
+	/*
+	 * now the default type is SYSTEM_INTERFACE and channel type is BMC.
+	 * If the netfn is APP_REQUEST and the cmd is SEND_MESSAGE,
+	 * the addr type should be changed to IPMB. Then we will have to parse
+	 * the IPMI request message buffer to get the IPMB address.
+	 * If so, please fix me.
+	 */
+	tx_msg->addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
+	tx_msg->addr.channel = IPMI_BMC_CHANNEL;
+	tx_msg->addr.data[0] = 0;
+
+	/* Get the msgid */
+	device = tx_msg->device;
+	mutex_lock(&device->tx_msg_lock);
+	device->curr_msgid++;
+	tx_msg->tx_msgid = device->curr_msgid;
+	mutex_unlock(&device->tx_msg_lock);
+}
+
+static void acpi_format_ipmi_response(struct acpi_ipmi_msg *msg,
+		acpi_integer *value, int rem_time)
+{
+	struct acpi_ipmi_buffer *buffer;
+
+	/*
+	 * value is also used as output parameter. It represents the response
+	 * IPMI message returned by IPMI command.
+	 */
+	buffer = (struct acpi_ipmi_buffer *)value;
+	if (!rem_time && !msg->msg_done) {
+		buffer->status = ACPI_IPMI_TIMEOUT;
+		return;
+	}
+	/*
+	 * If the flag of msg_done is not set or the recv length is zero, it
+	 * means that the IPMI command is not executed correctly.
+	 * The status code will be ACPI_IPMI_UNKNOWN.
+	 */
+	if (!msg->msg_done || !msg->rx_len) {
+		buffer->status = ACPI_IPMI_UNKNOWN;
+		return;
+	}
+	/*
+	 * If the IPMI response message is obtained correctly, the status code
+	 * will be ACPI_IPMI_OK
+	 */
+	buffer->status = ACPI_IPMI_OK;
+	buffer->length = msg->rx_len;
+	memcpy(buffer->data, msg->rx_data, msg->rx_len);
+}
+
+static void ipmi_flush_tx_msg(struct acpi_ipmi_device *ipmi)
+{
+	struct acpi_ipmi_msg *tx_msg, *temp;
+	int count = HZ / 10;
+	struct pnp_dev *pnp_dev = ipmi->pnp_dev;
+
+	list_for_each_entry_safe(tx_msg, temp, &ipmi->tx_msg_list, head) {
+		/* wake up the sleep thread on the Tx msg */
+		complete(&tx_msg->tx_complete);
+	}
+
+	/* wait for about 100ms to flush the tx message list */
+	while (count--) {
+		if (list_empty(&ipmi->tx_msg_list))
+			break;
+		schedule_timeout(1);
+	}
+	if (!list_empty(&ipmi->tx_msg_list))
+		dev_warn(&pnp_dev->dev, "tx msg list is not NULL\n");
+}
+
+static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data)
+{
+	struct acpi_ipmi_device *ipmi_device = user_msg_data;
+	int msg_found = 0;
+	struct acpi_ipmi_msg *tx_msg;
+	struct pnp_dev *pnp_dev = ipmi_device->pnp_dev;
+
+	if (msg->user != ipmi_device->user_interface) {
+		dev_warn(&pnp_dev->dev, "Unexpected response is returned. "
+			"returned user %p, expected user %p\n",
+			msg->user, ipmi_device->user_interface);
+		ipmi_free_recv_msg(msg);
+		return;
+	}
+	mutex_lock(&ipmi_device->tx_msg_lock);
+	list_for_each_entry(tx_msg, &ipmi_device->tx_msg_list, head) {
+		if (msg->msgid == tx_msg->tx_msgid) {
+			msg_found = 1;
+			break;
+		}
+	}
+
+	mutex_unlock(&ipmi_device->tx_msg_lock);
+	if (!msg_found) {
+		dev_warn(&pnp_dev->dev, "Unexpected response (msg id %ld) is "
+			"returned.\n", msg->msgid);
+		ipmi_free_recv_msg(msg);
+		return;
+	}
+
+	if (msg->msg.data_len) {
+		/* copy the response data to Rx_data buffer */
+		memcpy(tx_msg->rx_data, msg->msg_data, msg->msg.data_len);
+		tx_msg->rx_len = msg->msg.data_len;
+		tx_msg->msg_done = 1;
+	}
+	complete(&tx_msg->tx_complete);
+	ipmi_free_recv_msg(msg);
+};
+
+static void ipmi_register_bmc(int iface, struct device *dev)
+{
+	struct acpi_ipmi_device *ipmi_device, *temp;
+	struct pnp_dev *pnp_dev;
+	ipmi_user_t		user;
+	int err;
+	struct ipmi_smi_info smi_data;
+	acpi_handle handle;
+
+	err = ipmi_get_smi_info(iface, &smi_data);
+
+	if (err)
+		return;
+
+	if (smi_data.addr_src != SI_ACPI) {
+		put_device(smi_data.dev);
+		return;
+	}
+
+	handle = smi_data.addr_info.acpi_info.acpi_handle;
+
+	mutex_lock(&driver_data.ipmi_lock);
+	list_for_each_entry(temp, &driver_data.ipmi_devices, head) {
+		/*
+		 * if the corresponding ACPI handle is already added
+		 * to the device list, don't add it again.
+		 */
+		if (temp->handle == handle)
+			goto out;
+	}
+
+	ipmi_device = kzalloc(sizeof(*ipmi_device), GFP_KERNEL);
+
+	if (!ipmi_device)
+		goto out;
+
+	pnp_dev = to_pnp_dev(smi_data.dev);
+	ipmi_device->handle = handle;
+	ipmi_device->pnp_dev = pnp_dev;
+
+	err = ipmi_create_user(iface, &driver_data.ipmi_hndlrs,
+					ipmi_device, &user);
+	if (err) {
+		dev_warn(&pnp_dev->dev, "Can't create IPMI user interface\n");
+		kfree(ipmi_device);
+		goto out;
+	}
+	acpi_add_ipmi_device(ipmi_device);
+	ipmi_device->user_interface = user;
+	ipmi_device->ipmi_ifnum = iface;
+	mutex_unlock(&driver_data.ipmi_lock);
+	memcpy(&ipmi_device->smi_data, &smi_data, sizeof(struct ipmi_smi_info));
+	return;
+
+out:
+	mutex_unlock(&driver_data.ipmi_lock);
+	put_device(smi_data.dev);
+	return;
+}
+
+static void ipmi_bmc_gone(int iface)
+{
+	struct acpi_ipmi_device *ipmi_device, *temp;
+
+	mutex_lock(&driver_data.ipmi_lock);
+	list_for_each_entry_safe(ipmi_device, temp,
+				&driver_data.ipmi_devices, head) {
+		if (ipmi_device->ipmi_ifnum != iface)
+			continue;
+
+		acpi_remove_ipmi_device(ipmi_device);
+		put_device(ipmi_device->smi_data.dev);
+		kfree(ipmi_device);
+		break;
+	}
+	mutex_unlock(&driver_data.ipmi_lock);
+}
+/* --------------------------------------------------------------------------
+ *			Address Space Management
+ * -------------------------------------------------------------------------- */
+/*
+ * This is the IPMI opregion space handler.
+ * @function: indicates the read/write. In fact as the IPMI message is driven
+ * by command, only write is meaningful.
+ * @address: This contains the netfn/command of IPMI request message.
+ * @bits   : not used.
+ * @value  : it is an in/out parameter. It points to the IPMI message buffer.
+ *	     Before the IPMI message is sent, it represents the actual request
+ *	     IPMI message. After the IPMI message is finished, it represents
+ *	     the response IPMI message returned by IPMI command.
+ * @handler_context: IPMI device context.
+ */
+
+static acpi_status
+acpi_ipmi_space_handler(u32 function, acpi_physical_address address,
+		      u32 bits, acpi_integer *value,
+		      void *handler_context, void *region_context)
+{
+	struct acpi_ipmi_msg *tx_msg;
+	struct acpi_ipmi_device *ipmi_device = handler_context;
+	int err, rem_time;
+	acpi_status status;
+	/*
+	 * IPMI opregion message.
+	 * IPMI message is firstly written to the BMC and system software
+	 * can get the respsonse. So it is unmeaningful for the read access
+	 * of IPMI opregion.
+	 */
+	if ((function & ACPI_IO_MASK) == ACPI_READ)
+		return AE_TYPE;
+
+	if (!ipmi_device->user_interface)
+		return AE_NOT_EXIST;
+
+	tx_msg = acpi_alloc_ipmi_msg(ipmi_device);
+	if (!tx_msg)
+		return AE_NO_MEMORY;
+
+	acpi_format_ipmi_msg(tx_msg, address, value);
+	mutex_lock(&ipmi_device->tx_msg_lock);
+	list_add_tail(&tx_msg->head, &ipmi_device->tx_msg_list);
+	mutex_unlock(&ipmi_device->tx_msg_lock);
+	err = ipmi_request_settime(ipmi_device->user_interface,
+					&tx_msg->addr,
+					tx_msg->tx_msgid,
+					&tx_msg->tx_message,
+					NULL, 0, 0, 0);
+	if (err) {
+		status = AE_ERROR;
+		goto end_label;
+	}
+	rem_time = wait_for_completion_timeout(&tx_msg->tx_complete,
+					IPMI_TIMEOUT);
+	acpi_format_ipmi_response(tx_msg, value, rem_time);
+	status = AE_OK;
+
+end_label:
+	mutex_lock(&ipmi_device->tx_msg_lock);
+	list_del(&tx_msg->head);
+	mutex_unlock(&ipmi_device->tx_msg_lock);
+	kfree(tx_msg);
+	return status;
+}
+
+static void ipmi_remove_space_handler(struct acpi_ipmi_device *ipmi)
+{
+	if (!test_bit(IPMI_FLAGS_HANDLER_INSTALL, &ipmi->flags))
+		return;
+
+	acpi_remove_address_space_handler(ipmi->handle,
+				ACPI_ADR_SPACE_IPMI, &acpi_ipmi_space_handler);
+
+	clear_bit(IPMI_FLAGS_HANDLER_INSTALL, &ipmi->flags);
+}
+
+static int ipmi_install_space_handler(struct acpi_ipmi_device *ipmi)
+{
+	acpi_status status;
+
+	if (test_bit(IPMI_FLAGS_HANDLER_INSTALL, &ipmi->flags))
+		return 0;
+
+	status = acpi_install_address_space_handler(ipmi->handle,
+						    ACPI_ADR_SPACE_IPMI,
+						    &acpi_ipmi_space_handler,
+						    NULL, ipmi);
+	if (ACPI_FAILURE(status)) {
+		struct pnp_dev *pnp_dev = ipmi->pnp_dev;
+		dev_warn(&pnp_dev->dev, "Can't register IPMI opregion space "
+			"handle\n");
+		return -EINVAL;
+	}
+	set_bit(IPMI_FLAGS_HANDLER_INSTALL, &ipmi->flags);
+	return 0;
+}
+
+static void acpi_add_ipmi_device(struct acpi_ipmi_device *ipmi_device)
+{
+
+	INIT_LIST_HEAD(&ipmi_device->head);
+
+	mutex_init(&ipmi_device->tx_msg_lock);
+	INIT_LIST_HEAD(&ipmi_device->tx_msg_list);
+	ipmi_install_space_handler(ipmi_device);
+
+	list_add_tail(&ipmi_device->head, &driver_data.ipmi_devices);
+}
+
+static void acpi_remove_ipmi_device(struct acpi_ipmi_device *ipmi_device)
+{
+	/*
+	 * If the IPMI user interface is created, it should be
+	 * destroyed.
+	 */
+	if (ipmi_device->user_interface) {
+		ipmi_destroy_user(ipmi_device->user_interface);
+		ipmi_device->user_interface = NULL;
+	}
+	/* flush the Tx_msg list */
+	if (!list_empty(&ipmi_device->tx_msg_list))
+		ipmi_flush_tx_msg(ipmi_device);
+
+	list_del(&ipmi_device->head);
+	ipmi_remove_space_handler(ipmi_device);
+}
+
+static int __init acpi_ipmi_init(void)
+{
+	int result = 0;
+
+	if (acpi_disabled)
+		return result;
+
+	mutex_init(&driver_data.ipmi_lock);
+
+	result = ipmi_smi_watcher_register(&driver_data.bmc_events);
+
+	return result;
+}
+
+static void __exit acpi_ipmi_exit(void)
+{
+	struct acpi_ipmi_device *ipmi_device, *temp;
+
+	if (acpi_disabled)
+		return;
+
+	ipmi_smi_watcher_unregister(&driver_data.bmc_events);
+
+	/*
+	 * When one smi_watcher is unregistered, it is only deleted
+	 * from the smi_watcher list. But the smi_gone callback function
+	 * is not called. So explicitly uninstall the ACPI IPMI oregion
+	 * handler and free it.
+	 */
+	mutex_lock(&driver_data.ipmi_lock);
+	list_for_each_entry_safe(ipmi_device, temp,
+				&driver_data.ipmi_devices, head) {
+		acpi_remove_ipmi_device(ipmi_device);
+		put_device(ipmi_device->smi_data.dev);
+		kfree(ipmi_device);
+	}
+	mutex_unlock(&driver_data.ipmi_lock);
+}
+
+module_init(acpi_ipmi_init);
+module_exit(acpi_ipmi_exit);
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/apei/apei-internal.h linux-libre-2.6.38-gnu1/drivers/acpi/apei/apei-internal.h
--- linux-libre-2.6.37-gnu1/drivers/acpi/apei/apei-internal.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/apei/apei-internal.h	2011-03-14 21:20:32.000000000 -0400
@@ -109,6 +109,8 @@ static inline u32 apei_estatus_len(struc
 		return sizeof(*estatus) + estatus->data_length;
 }
 
+void apei_estatus_print(const char *pfx,
+			const struct acpi_hest_generic_status *estatus);
 int apei_estatus_check_header(const struct acpi_hest_generic_status *estatus);
 int apei_estatus_check(const struct acpi_hest_generic_status *estatus);
 #endif
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/apei/cper.c linux-libre-2.6.38-gnu1/drivers/acpi/apei/cper.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/apei/cper.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/apei/cper.c	2011-03-14 21:20:32.000000000 -0400
@@ -46,6 +46,317 @@ u64 cper_next_record_id(void)
 }
 EXPORT_SYMBOL_GPL(cper_next_record_id);
 
+static const char *cper_severity_strs[] = {
+	"recoverable",
+	"fatal",
+	"corrected",
+	"info",
+};
+
+static const char *cper_severity_str(unsigned int severity)
+{
+	return severity < ARRAY_SIZE(cper_severity_strs) ?
+		cper_severity_strs[severity] : "unknown";
+}
+
+/*
+ * cper_print_bits - print strings for set bits
+ * @pfx: prefix for each line, including log level and prefix string
+ * @bits: bit mask
+ * @strs: string array, indexed by bit position
+ * @strs_size: size of the string array: @strs
+ *
+ * For each set bit in @bits, print the corresponding string in @strs.
+ * If the output length is longer than 80, multiple line will be
+ * printed, with @pfx is printed at the beginning of each line.
+ */
+static void cper_print_bits(const char *pfx, unsigned int bits,
+			    const char *strs[], unsigned int strs_size)
+{
+	int i, len = 0;
+	const char *str;
+	char buf[84];
+
+	for (i = 0; i < strs_size; i++) {
+		if (!(bits & (1U << i)))
+			continue;
+		str = strs[i];
+		if (len && len + strlen(str) + 2 > 80) {
+			printk("%s\n", buf);
+			len = 0;
+		}
+		if (!len)
+			len = snprintf(buf, sizeof(buf), "%s%s", pfx, str);
+		else
+			len += snprintf(buf+len, sizeof(buf)-len, ", %s", str);
+	}
+	if (len)
+		printk("%s\n", buf);
+}
+
+static const char *cper_proc_type_strs[] = {
+	"IA32/X64",
+	"IA64",
+};
+
+static const char *cper_proc_isa_strs[] = {
+	"IA32",
+	"IA64",
+	"X64",
+};
+
+static const char *cper_proc_error_type_strs[] = {
+	"cache error",
+	"TLB error",
+	"bus error",
+	"micro-architectural error",
+};
+
+static const char *cper_proc_op_strs[] = {
+	"unknown or generic",
+	"data read",
+	"data write",
+	"instruction execution",
+};
+
+static const char *cper_proc_flag_strs[] = {
+	"restartable",
+	"precise IP",
+	"overflow",
+	"corrected",
+};
+
+static void cper_print_proc_generic(const char *pfx,
+				    const struct cper_sec_proc_generic *proc)
+{
+	if (proc->validation_bits & CPER_PROC_VALID_TYPE)
+		printk("%s""processor_type: %d, %s\n", pfx, proc->proc_type,
+		       proc->proc_type < ARRAY_SIZE(cper_proc_type_strs) ?
+		       cper_proc_type_strs[proc->proc_type] : "unknown");
+	if (proc->validation_bits & CPER_PROC_VALID_ISA)
+		printk("%s""processor_isa: %d, %s\n", pfx, proc->proc_isa,
+		       proc->proc_isa < ARRAY_SIZE(cper_proc_isa_strs) ?
+		       cper_proc_isa_strs[proc->proc_isa] : "unknown");
+	if (proc->validation_bits & CPER_PROC_VALID_ERROR_TYPE) {
+		printk("%s""error_type: 0x%02x\n", pfx, proc->proc_error_type);
+		cper_print_bits(pfx, proc->proc_error_type,
+				cper_proc_error_type_strs,
+				ARRAY_SIZE(cper_proc_error_type_strs));
+	}
+	if (proc->validation_bits & CPER_PROC_VALID_OPERATION)
+		printk("%s""operation: %d, %s\n", pfx, proc->operation,
+		       proc->operation < ARRAY_SIZE(cper_proc_op_strs) ?
+		       cper_proc_op_strs[proc->operation] : "unknown");
+	if (proc->validation_bits & CPER_PROC_VALID_FLAGS) {
+		printk("%s""flags: 0x%02x\n", pfx, proc->flags);
+		cper_print_bits(pfx, proc->flags, cper_proc_flag_strs,
+				ARRAY_SIZE(cper_proc_flag_strs));
+	}
+	if (proc->validation_bits & CPER_PROC_VALID_LEVEL)
+		printk("%s""level: %d\n", pfx, proc->level);
+	if (proc->validation_bits & CPER_PROC_VALID_VERSION)
+		printk("%s""version_info: 0x%016llx\n", pfx, proc->cpu_version);
+	if (proc->validation_bits & CPER_PROC_VALID_ID)
+		printk("%s""processor_id: 0x%016llx\n", pfx, proc->proc_id);
+	if (proc->validation_bits & CPER_PROC_VALID_TARGET_ADDRESS)
+		printk("%s""target_address: 0x%016llx\n",
+		       pfx, proc->target_addr);
+	if (proc->validation_bits & CPER_PROC_VALID_REQUESTOR_ID)
+		printk("%s""requestor_id: 0x%016llx\n",
+		       pfx, proc->requestor_id);
+	if (proc->validation_bits & CPER_PROC_VALID_RESPONDER_ID)
+		printk("%s""responder_id: 0x%016llx\n",
+		       pfx, proc->responder_id);
+	if (proc->validation_bits & CPER_PROC_VALID_IP)
+		printk("%s""IP: 0x%016llx\n", pfx, proc->ip);
+}
+
+static const char *cper_mem_err_type_strs[] = {
+	"unknown",
+	"no error",
+	"single-bit ECC",
+	"multi-bit ECC",
+	"single-symbol chipkill ECC",
+	"multi-symbol chipkill ECC",
+	"master abort",
+	"target abort",
+	"parity error",
+	"watchdog timeout",
+	"invalid address",
+	"mirror Broken",
+	"memory sparing",
+	"scrub corrected error",
+	"scrub uncorrected error",
+};
+
+static void cper_print_mem(const char *pfx, const struct cper_sec_mem_err *mem)
+{
+	if (mem->validation_bits & CPER_MEM_VALID_ERROR_STATUS)
+		printk("%s""error_status: 0x%016llx\n", pfx, mem->error_status);
+	if (mem->validation_bits & CPER_MEM_VALID_PHYSICAL_ADDRESS)
+		printk("%s""physical_address: 0x%016llx\n",
+		       pfx, mem->physical_addr);
+	if (mem->validation_bits & CPER_MEM_VALID_PHYSICAL_ADDRESS_MASK)
+		printk("%s""physical_address_mask: 0x%016llx\n",
+		       pfx, mem->physical_addr_mask);
+	if (mem->validation_bits & CPER_MEM_VALID_NODE)
+		printk("%s""node: %d\n", pfx, mem->node);
+	if (mem->validation_bits & CPER_MEM_VALID_CARD)
+		printk("%s""card: %d\n", pfx, mem->card);
+	if (mem->validation_bits & CPER_MEM_VALID_MODULE)
+		printk("%s""module: %d\n", pfx, mem->module);
+	if (mem->validation_bits & CPER_MEM_VALID_BANK)
+		printk("%s""bank: %d\n", pfx, mem->bank);
+	if (mem->validation_bits & CPER_MEM_VALID_DEVICE)
+		printk("%s""device: %d\n", pfx, mem->device);
+	if (mem->validation_bits & CPER_MEM_VALID_ROW)
+		printk("%s""row: %d\n", pfx, mem->row);
+	if (mem->validation_bits & CPER_MEM_VALID_COLUMN)
+		printk("%s""column: %d\n", pfx, mem->column);
+	if (mem->validation_bits & CPER_MEM_VALID_BIT_POSITION)
+		printk("%s""bit_position: %d\n", pfx, mem->bit_pos);
+	if (mem->validation_bits & CPER_MEM_VALID_REQUESTOR_ID)
+		printk("%s""requestor_id: 0x%016llx\n", pfx, mem->requestor_id);
+	if (mem->validation_bits & CPER_MEM_VALID_RESPONDER_ID)
+		printk("%s""responder_id: 0x%016llx\n", pfx, mem->responder_id);
+	if (mem->validation_bits & CPER_MEM_VALID_TARGET_ID)
+		printk("%s""target_id: 0x%016llx\n", pfx, mem->target_id);
+	if (mem->validation_bits & CPER_MEM_VALID_ERROR_TYPE) {
+		u8 etype = mem->error_type;
+		printk("%s""error_type: %d, %s\n", pfx, etype,
+		       etype < ARRAY_SIZE(cper_mem_err_type_strs) ?
+		       cper_mem_err_type_strs[etype] : "unknown");
+	}
+}
+
+static const char *cper_pcie_port_type_strs[] = {
+	"PCIe end point",
+	"legacy PCI end point",
+	"unknown",
+	"unknown",
+	"root port",
+	"upstream switch port",
+	"downstream switch port",
+	"PCIe to PCI/PCI-X bridge",
+	"PCI/PCI-X to PCIe bridge",
+	"root complex integrated endpoint device",
+	"root complex event collector",
+};
+
+static void cper_print_pcie(const char *pfx, const struct cper_sec_pcie *pcie)
+{
+	if (pcie->validation_bits & CPER_PCIE_VALID_PORT_TYPE)
+		printk("%s""port_type: %d, %s\n", pfx, pcie->port_type,
+		       pcie->port_type < ARRAY_SIZE(cper_pcie_port_type_strs) ?
+		       cper_pcie_port_type_strs[pcie->port_type] : "unknown");
+	if (pcie->validation_bits & CPER_PCIE_VALID_VERSION)
+		printk("%s""version: %d.%d\n", pfx,
+		       pcie->version.major, pcie->version.minor);
+	if (pcie->validation_bits & CPER_PCIE_VALID_COMMAND_STATUS)
+		printk("%s""command: 0x%04x, status: 0x%04x\n", pfx,
+		       pcie->command, pcie->status);
+	if (pcie->validation_bits & CPER_PCIE_VALID_DEVICE_ID) {
+		const __u8 *p;
+		printk("%s""device_id: %04x:%02x:%02x.%x\n", pfx,
+		       pcie->device_id.segment, pcie->device_id.bus,
+		       pcie->device_id.device, pcie->device_id.function);
+		printk("%s""slot: %d\n", pfx,
+		       pcie->device_id.slot >> CPER_PCIE_SLOT_SHIFT);
+		printk("%s""secondary_bus: 0x%02x\n", pfx,
+		       pcie->device_id.secondary_bus);
+		printk("%s""vendor_id: 0x%04x, device_id: 0x%04x\n", pfx,
+		       pcie->device_id.vendor_id, pcie->device_id.device_id);
+		p = pcie->device_id.class_code;
+		printk("%s""class_code: %02x%02x%02x\n", pfx, p[0], p[1], p[2]);
+	}
+	if (pcie->validation_bits & CPER_PCIE_VALID_SERIAL_NUMBER)
+		printk("%s""serial number: 0x%04x, 0x%04x\n", pfx,
+		       pcie->serial_number.lower, pcie->serial_number.upper);
+	if (pcie->validation_bits & CPER_PCIE_VALID_BRIDGE_CONTROL_STATUS)
+		printk(
+	"%s""bridge: secondary_status: 0x%04x, control: 0x%04x\n",
+	pfx, pcie->bridge.secondary_status, pcie->bridge.control);
+}
+
+static const char *apei_estatus_section_flag_strs[] = {
+	"primary",
+	"containment warning",
+	"reset",
+	"threshold exceeded",
+	"resource not accessible",
+	"latent error",
+};
+
+static void apei_estatus_print_section(
+	const char *pfx, const struct acpi_hest_generic_data *gdata, int sec_no)
+{
+	uuid_le *sec_type = (uuid_le *)gdata->section_type;
+	__u16 severity;
+
+	severity = gdata->error_severity;
+	printk("%s""section: %d, severity: %d, %s\n", pfx, sec_no, severity,
+	       cper_severity_str(severity));
+	printk("%s""flags: 0x%02x\n", pfx, gdata->flags);
+	cper_print_bits(pfx, gdata->flags, apei_estatus_section_flag_strs,
+			ARRAY_SIZE(apei_estatus_section_flag_strs));
+	if (gdata->validation_bits & CPER_SEC_VALID_FRU_ID)
+		printk("%s""fru_id: %pUl\n", pfx, (uuid_le *)gdata->fru_id);
+	if (gdata->validation_bits & CPER_SEC_VALID_FRU_TEXT)
+		printk("%s""fru_text: %.20s\n", pfx, gdata->fru_text);
+
+	if (!uuid_le_cmp(*sec_type, CPER_SEC_PROC_GENERIC)) {
+		struct cper_sec_proc_generic *proc_err = (void *)(gdata + 1);
+		printk("%s""section_type: general processor error\n", pfx);
+		if (gdata->error_data_length >= sizeof(*proc_err))
+			cper_print_proc_generic(pfx, proc_err);
+		else
+			goto err_section_too_small;
+	} else if (!uuid_le_cmp(*sec_type, CPER_SEC_PLATFORM_MEM)) {
+		struct cper_sec_mem_err *mem_err = (void *)(gdata + 1);
+		printk("%s""section_type: memory error\n", pfx);
+		if (gdata->error_data_length >= sizeof(*mem_err))
+			cper_print_mem(pfx, mem_err);
+		else
+			goto err_section_too_small;
+	} else if (!uuid_le_cmp(*sec_type, CPER_SEC_PCIE)) {
+		struct cper_sec_pcie *pcie = (void *)(gdata + 1);
+		printk("%s""section_type: PCIe error\n", pfx);
+		if (gdata->error_data_length >= sizeof(*pcie))
+			cper_print_pcie(pfx, pcie);
+		else
+			goto err_section_too_small;
+	} else
+		printk("%s""section type: unknown, %pUl\n", pfx, sec_type);
+
+	return;
+
+err_section_too_small:
+	pr_err(FW_WARN "error section length is too small\n");
+}
+
+void apei_estatus_print(const char *pfx,
+			const struct acpi_hest_generic_status *estatus)
+{
+	struct acpi_hest_generic_data *gdata;
+	unsigned int data_len, gedata_len;
+	int sec_no = 0;
+	__u16 severity;
+
+	printk("%s""APEI generic hardware error status\n", pfx);
+	severity = estatus->error_severity;
+	printk("%s""severity: %d, %s\n", pfx, severity,
+	       cper_severity_str(severity));
+	data_len = estatus->data_length;
+	gdata = (struct acpi_hest_generic_data *)(estatus + 1);
+	while (data_len > sizeof(*gdata)) {
+		gedata_len = gdata->error_data_length;
+		apei_estatus_print_section(pfx, gdata, sec_no);
+		data_len -= gedata_len + sizeof(*gdata);
+		sec_no++;
+	}
+}
+EXPORT_SYMBOL_GPL(apei_estatus_print);
+
 int apei_estatus_check_header(const struct acpi_hest_generic_status *estatus)
 {
 	if (estatus->data_length &&
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/apei/einj.c linux-libre-2.6.38-gnu1/drivers/acpi/apei/einj.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/apei/einj.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/apei/einj.c	2011-03-14 21:20:32.000000000 -0400
@@ -39,7 +39,7 @@
 #define EINJ_PFX "EINJ: "
 
 #define SPIN_UNIT		100			/* 100ns */
-/* Firmware should respond within 1 miliseconds */
+/* Firmware should respond within 1 milliseconds */
 #define FIRMWARE_TIMEOUT	(1 * NSEC_PER_MSEC)
 
 /*
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/apei/erst.c linux-libre-2.6.38-gnu1/drivers/acpi/apei/erst.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/apei/erst.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/apei/erst.c	2011-03-14 21:20:32.000000000 -0400
@@ -53,7 +53,7 @@
 				     sizeof(struct acpi_table_erst)))
 
 #define SPIN_UNIT		100			/* 100ns */
-/* Firmware should respond within 1 miliseconds */
+/* Firmware should respond within 1 milliseconds */
 #define FIRMWARE_TIMEOUT	(1 * NSEC_PER_MSEC)
 #define FIRMWARE_MAX_STALL	50			/* 50us */
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/apei/ghes.c linux-libre-2.6.38-gnu1/drivers/acpi/apei/ghes.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/apei/ghes.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/apei/ghes.c	2011-03-14 21:20:32.000000000 -0400
@@ -12,10 +12,6 @@
  * For more information about Generic Hardware Error Source, please
  * refer to ACPI Specification version 4.0, section 17.3.2.6
  *
- * Now, only SCI notification type and memory errors are
- * supported. More notification type and hardware error type will be
- * added later.
- *
  * Copyright 2010 Intel Corp.
  *   Author: Huang Ying <ying.huang@intel.com>
  *
@@ -39,14 +35,18 @@
 #include <linux/acpi.h>
 #include <linux/io.h>
 #include <linux/interrupt.h>
+#include <linux/timer.h>
 #include <linux/cper.h>
 #include <linux/kdebug.h>
 #include <linux/platform_device.h>
 #include <linux/mutex.h>
+#include <linux/ratelimit.h>
+#include <linux/vmalloc.h>
 #include <acpi/apei.h>
 #include <acpi/atomicio.h>
 #include <acpi/hed.h>
 #include <asm/mce.h>
+#include <asm/tlbflush.h>
 
 #include "apei-internal.h"
 
@@ -55,42 +55,131 @@
 #define GHES_ESTATUS_MAX_SIZE		65536
 
 /*
- * One struct ghes is created for each generic hardware error
- * source.
- *
+ * One struct ghes is created for each generic hardware error source.
  * It provides the context for APEI hardware error timer/IRQ/SCI/NMI
- * handler. Handler for one generic hardware error source is only
- * triggered after the previous one is done. So handler can uses
- * struct ghes without locking.
+ * handler.
  *
  * estatus: memory buffer for error status block, allocated during
  * HEST parsing.
  */
 #define GHES_TO_CLEAR		0x0001
+#define GHES_EXITING		0x0002
 
 struct ghes {
 	struct acpi_hest_generic *generic;
 	struct acpi_hest_generic_status *estatus;
-	struct list_head list;
 	u64 buffer_paddr;
 	unsigned long flags;
+	union {
+		struct list_head list;
+		struct timer_list timer;
+		unsigned int irq;
+	};
 };
 
+static int ghes_panic_timeout	__read_mostly = 30;
+
 /*
- * Error source lists, one list for each notification method. The
- * members in lists are struct ghes.
- *
- * The list members are only added in HEST parsing and deleted during
- * module_exit, that is, single-threaded. So no lock is needed for
- * that.
+ * All error sources notified with SCI shares one notifier function,
+ * so they need to be linked and checked one by one.  This is applied
+ * to NMI too.
  *
- * But the mutual exclusion is needed between members adding/deleting
- * and timer/IRQ/SCI/NMI handler, which may traverse the list. RCU is
- * used for that.
+ * RCU is used for these lists, so ghes_list_mutex is only used for
+ * list changing, not for traversing.
  */
 static LIST_HEAD(ghes_sci);
+static LIST_HEAD(ghes_nmi);
 static DEFINE_MUTEX(ghes_list_mutex);
 
+/*
+ * NMI may be triggered on any CPU, so ghes_nmi_lock is used for
+ * mutual exclusion.
+ */
+static DEFINE_RAW_SPINLOCK(ghes_nmi_lock);
+
+/*
+ * Because the memory area used to transfer hardware error information
+ * from BIOS to Linux can be determined only in NMI, IRQ or timer
+ * handler, but general ioremap can not be used in atomic context, so
+ * a special version of atomic ioremap is implemented for that.
+ */
+
+/*
+ * Two virtual pages are used, one for NMI context, the other for
+ * IRQ/PROCESS context
+ */
+#define GHES_IOREMAP_PAGES		2
+#define GHES_IOREMAP_NMI_PAGE(base)	(base)
+#define GHES_IOREMAP_IRQ_PAGE(base)	((base) + PAGE_SIZE)
+
+/* virtual memory area for atomic ioremap */
+static struct vm_struct *ghes_ioremap_area;
+/*
+ * These 2 spinlock is used to prevent atomic ioremap virtual memory
+ * area from being mapped simultaneously.
+ */
+static DEFINE_RAW_SPINLOCK(ghes_ioremap_lock_nmi);
+static DEFINE_SPINLOCK(ghes_ioremap_lock_irq);
+
+static int ghes_ioremap_init(void)
+{
+	ghes_ioremap_area = __get_vm_area(PAGE_SIZE * GHES_IOREMAP_PAGES,
+		VM_IOREMAP, VMALLOC_START, VMALLOC_END);
+	if (!ghes_ioremap_area) {
+		pr_err(GHES_PFX "Failed to allocate virtual memory area for atomic ioremap.\n");
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+static void ghes_ioremap_exit(void)
+{
+	free_vm_area(ghes_ioremap_area);
+}
+
+static void __iomem *ghes_ioremap_pfn_nmi(u64 pfn)
+{
+	unsigned long vaddr;
+
+	vaddr = (unsigned long)GHES_IOREMAP_NMI_PAGE(ghes_ioremap_area->addr);
+	ioremap_page_range(vaddr, vaddr + PAGE_SIZE,
+			   pfn << PAGE_SHIFT, PAGE_KERNEL);
+
+	return (void __iomem *)vaddr;
+}
+
+static void __iomem *ghes_ioremap_pfn_irq(u64 pfn)
+{
+	unsigned long vaddr;
+
+	vaddr = (unsigned long)GHES_IOREMAP_IRQ_PAGE(ghes_ioremap_area->addr);
+	ioremap_page_range(vaddr, vaddr + PAGE_SIZE,
+			   pfn << PAGE_SHIFT, PAGE_KERNEL);
+
+	return (void __iomem *)vaddr;
+}
+
+static void ghes_iounmap_nmi(void __iomem *vaddr_ptr)
+{
+	unsigned long vaddr = (unsigned long __force)vaddr_ptr;
+	void *base = ghes_ioremap_area->addr;
+
+	BUG_ON(vaddr != (unsigned long)GHES_IOREMAP_NMI_PAGE(base));
+	unmap_kernel_range_noflush(vaddr, PAGE_SIZE);
+	__flush_tlb_one(vaddr);
+}
+
+static void ghes_iounmap_irq(void __iomem *vaddr_ptr)
+{
+	unsigned long vaddr = (unsigned long __force)vaddr_ptr;
+	void *base = ghes_ioremap_area->addr;
+
+	BUG_ON(vaddr != (unsigned long)GHES_IOREMAP_IRQ_PAGE(base));
+	unmap_kernel_range_noflush(vaddr, PAGE_SIZE);
+	__flush_tlb_one(vaddr);
+}
+
 static struct ghes *ghes_new(struct acpi_hest_generic *generic)
 {
 	struct ghes *ghes;
@@ -101,7 +190,6 @@ static struct ghes *ghes_new(struct acpi
 	if (!ghes)
 		return ERR_PTR(-ENOMEM);
 	ghes->generic = generic;
-	INIT_LIST_HEAD(&ghes->list);
 	rc = acpi_pre_map_gar(&generic->error_status_address);
 	if (rc)
 		goto err_free;
@@ -158,22 +246,41 @@ static inline int ghes_severity(int seve
 	}
 }
 
-/* SCI handler run in work queue, so ioremap can be used here */
-static int ghes_copy_tofrom_phys(void *buffer, u64 paddr, u32 len,
-				 int from_phys)
+static void ghes_copy_tofrom_phys(void *buffer, u64 paddr, u32 len,
+				  int from_phys)
 {
-	void *vaddr;
-
-	vaddr = ioremap_cache(paddr, len);
-	if (!vaddr)
-		return -ENOMEM;
-	if (from_phys)
-		memcpy(buffer, vaddr, len);
-	else
-		memcpy(vaddr, buffer, len);
-	iounmap(vaddr);
+	void __iomem *vaddr;
+	unsigned long flags = 0;
+	int in_nmi = in_nmi();
+	u64 offset;
+	u32 trunk;
 
-	return 0;
+	while (len > 0) {
+		offset = paddr - (paddr & PAGE_MASK);
+		if (in_nmi) {
+			raw_spin_lock(&ghes_ioremap_lock_nmi);
+			vaddr = ghes_ioremap_pfn_nmi(paddr >> PAGE_SHIFT);
+		} else {
+			spin_lock_irqsave(&ghes_ioremap_lock_irq, flags);
+			vaddr = ghes_ioremap_pfn_irq(paddr >> PAGE_SHIFT);
+		}
+		trunk = PAGE_SIZE - offset;
+		trunk = min(trunk, len);
+		if (from_phys)
+			memcpy_fromio(buffer, vaddr + offset, trunk);
+		else
+			memcpy_toio(vaddr + offset, buffer, trunk);
+		len -= trunk;
+		paddr += trunk;
+		buffer += trunk;
+		if (in_nmi) {
+			ghes_iounmap_nmi(vaddr);
+			raw_spin_unlock(&ghes_ioremap_lock_nmi);
+		} else {
+			ghes_iounmap_irq(vaddr);
+			spin_unlock_irqrestore(&ghes_ioremap_lock_irq, flags);
+		}
+	}
 }
 
 static int ghes_read_estatus(struct ghes *ghes, int silent)
@@ -194,10 +301,8 @@ static int ghes_read_estatus(struct ghes
 	if (!buf_paddr)
 		return -ENOENT;
 
-	rc = ghes_copy_tofrom_phys(ghes->estatus, buf_paddr,
-				   sizeof(*ghes->estatus), 1);
-	if (rc)
-		return rc;
+	ghes_copy_tofrom_phys(ghes->estatus, buf_paddr,
+			      sizeof(*ghes->estatus), 1);
 	if (!ghes->estatus->block_status)
 		return -ENOENT;
 
@@ -212,17 +317,15 @@ static int ghes_read_estatus(struct ghes
 		goto err_read_block;
 	if (apei_estatus_check_header(ghes->estatus))
 		goto err_read_block;
-	rc = ghes_copy_tofrom_phys(ghes->estatus + 1,
-				   buf_paddr + sizeof(*ghes->estatus),
-				   len - sizeof(*ghes->estatus), 1);
-	if (rc)
-		return rc;
+	ghes_copy_tofrom_phys(ghes->estatus + 1,
+			      buf_paddr + sizeof(*ghes->estatus),
+			      len - sizeof(*ghes->estatus), 1);
 	if (apei_estatus_check(ghes->estatus))
 		goto err_read_block;
 	rc = 0;
 
 err_read_block:
-	if (rc && !silent)
+	if (rc && !silent && printk_ratelimit())
 		pr_warning(FW_WARN GHES_PFX
 			   "Failed to read error status block!\n");
 	return rc;
@@ -255,11 +358,26 @@ static void ghes_do_proc(struct ghes *gh
 		}
 #endif
 	}
+}
 
-	if (!processed && printk_ratelimit())
-		pr_warning(GHES_PFX
-		"Unknown error record from generic hardware error source: %d\n",
-			   ghes->generic->header.source_id);
+static void ghes_print_estatus(const char *pfx, struct ghes *ghes)
+{
+	/* Not more than 2 messages every 5 seconds */
+	static DEFINE_RATELIMIT_STATE(ratelimit, 5*HZ, 2);
+
+	if (pfx == NULL) {
+		if (ghes_severity(ghes->estatus->error_severity) <=
+		    GHES_SEV_CORRECTED)
+			pfx = KERN_WARNING HW_ERR;
+		else
+			pfx = KERN_ERR HW_ERR;
+	}
+	if (__ratelimit(&ratelimit)) {
+		printk(
+	"%s""Hardware error from APEI Generic Hardware Error Source: %d\n",
+	pfx, ghes->generic->header.source_id);
+		apei_estatus_print(pfx, ghes->estatus);
+	}
 }
 
 static int ghes_proc(struct ghes *ghes)
@@ -269,6 +387,7 @@ static int ghes_proc(struct ghes *ghes)
 	rc = ghes_read_estatus(ghes, 0);
 	if (rc)
 		goto out;
+	ghes_print_estatus(NULL, ghes);
 	ghes_do_proc(ghes);
 
 out:
@@ -276,6 +395,42 @@ out:
 	return 0;
 }
 
+static void ghes_add_timer(struct ghes *ghes)
+{
+	struct acpi_hest_generic *g = ghes->generic;
+	unsigned long expire;
+
+	if (!g->notify.poll_interval) {
+		pr_warning(FW_WARN GHES_PFX "Poll interval is 0 for generic hardware error source: %d, disabled.\n",
+			   g->header.source_id);
+		return;
+	}
+	expire = jiffies + msecs_to_jiffies(g->notify.poll_interval);
+	ghes->timer.expires = round_jiffies_relative(expire);
+	add_timer(&ghes->timer);
+}
+
+static void ghes_poll_func(unsigned long data)
+{
+	struct ghes *ghes = (void *)data;
+
+	ghes_proc(ghes);
+	if (!(ghes->flags & GHES_EXITING))
+		ghes_add_timer(ghes);
+}
+
+static irqreturn_t ghes_irq_func(int irq, void *data)
+{
+	struct ghes *ghes = data;
+	int rc;
+
+	rc = ghes_proc(ghes);
+	if (rc)
+		return IRQ_NONE;
+
+	return IRQ_HANDLED;
+}
+
 static int ghes_notify_sci(struct notifier_block *this,
 				  unsigned long event, void *data)
 {
@@ -292,10 +447,63 @@ static int ghes_notify_sci(struct notifi
 	return ret;
 }
 
+static int ghes_notify_nmi(struct notifier_block *this,
+				  unsigned long cmd, void *data)
+{
+	struct ghes *ghes, *ghes_global = NULL;
+	int sev, sev_global = -1;
+	int ret = NOTIFY_DONE;
+
+	if (cmd != DIE_NMI)
+		return ret;
+
+	raw_spin_lock(&ghes_nmi_lock);
+	list_for_each_entry_rcu(ghes, &ghes_nmi, list) {
+		if (ghes_read_estatus(ghes, 1)) {
+			ghes_clear_estatus(ghes);
+			continue;
+		}
+		sev = ghes_severity(ghes->estatus->error_severity);
+		if (sev > sev_global) {
+			sev_global = sev;
+			ghes_global = ghes;
+		}
+		ret = NOTIFY_STOP;
+	}
+
+	if (ret == NOTIFY_DONE)
+		goto out;
+
+	if (sev_global >= GHES_SEV_PANIC) {
+		oops_begin();
+		ghes_print_estatus(KERN_EMERG HW_ERR, ghes_global);
+		/* reboot to log the error! */
+		if (panic_timeout == 0)
+			panic_timeout = ghes_panic_timeout;
+		panic("Fatal hardware error!");
+	}
+
+	list_for_each_entry_rcu(ghes, &ghes_nmi, list) {
+		if (!(ghes->flags & GHES_TO_CLEAR))
+			continue;
+		/* Do not print estatus because printk is not NMI safe */
+		ghes_do_proc(ghes);
+		ghes_clear_estatus(ghes);
+	}
+
+out:
+	raw_spin_unlock(&ghes_nmi_lock);
+	return ret;
+}
+
 static struct notifier_block ghes_notifier_sci = {
 	.notifier_call = ghes_notify_sci,
 };
 
+static struct notifier_block ghes_notifier_nmi = {
+	.notifier_call = ghes_notify_nmi,
+};
+
 static int __devinit ghes_probe(struct platform_device *ghes_dev)
 {
 	struct acpi_hest_generic *generic;
@@ -306,18 +514,27 @@ static int __devinit ghes_probe(struct p
 	if (!generic->enabled)
 		return -ENODEV;
 
-	if (generic->error_block_length <
-	    sizeof(struct acpi_hest_generic_status)) {
-		pr_warning(FW_BUG GHES_PFX
-"Invalid error block length: %u for generic hardware error source: %d\n",
-			   generic->error_block_length,
+	switch (generic->notify.type) {
+	case ACPI_HEST_NOTIFY_POLLED:
+	case ACPI_HEST_NOTIFY_EXTERNAL:
+	case ACPI_HEST_NOTIFY_SCI:
+	case ACPI_HEST_NOTIFY_NMI:
+		break;
+	case ACPI_HEST_NOTIFY_LOCAL:
+		pr_warning(GHES_PFX "Generic hardware error source: %d notified via local interrupt is not supported!\n",
 			   generic->header.source_id);
 		goto err;
+	default:
+		pr_warning(FW_WARN GHES_PFX "Unknown notification type: %u for generic hardware error source: %d\n",
+			   generic->notify.type, generic->header.source_id);
+		goto err;
 	}
-	if (generic->records_to_preallocate == 0) {
-		pr_warning(FW_BUG GHES_PFX
-"Invalid records to preallocate: %u for generic hardware error source: %d\n",
-			   generic->records_to_preallocate,
+
+	rc = -EIO;
+	if (generic->error_block_length <
+	    sizeof(struct acpi_hest_generic_status)) {
+		pr_warning(FW_BUG GHES_PFX "Invalid error block length: %u for generic hardware error source: %d\n",
+			   generic->error_block_length,
 			   generic->header.source_id);
 		goto err;
 	}
@@ -327,38 +544,43 @@ static int __devinit ghes_probe(struct p
 		ghes = NULL;
 		goto err;
 	}
-	if (generic->notify.type == ACPI_HEST_NOTIFY_SCI) {
+	switch (generic->notify.type) {
+	case ACPI_HEST_NOTIFY_POLLED:
+		ghes->timer.function = ghes_poll_func;
+		ghes->timer.data = (unsigned long)ghes;
+		init_timer_deferrable(&ghes->timer);
+		ghes_add_timer(ghes);
+		break;
+	case ACPI_HEST_NOTIFY_EXTERNAL:
+		/* External interrupt vector is GSI */
+		if (acpi_gsi_to_irq(generic->notify.vector, &ghes->irq)) {
+			pr_err(GHES_PFX "Failed to map GSI to IRQ for generic hardware error source: %d\n",
+			       generic->header.source_id);
+			goto err;
+		}
+		if (request_irq(ghes->irq, ghes_irq_func,
+				0, "GHES IRQ", ghes)) {
+			pr_err(GHES_PFX "Failed to register IRQ for generic hardware error source: %d\n",
+			       generic->header.source_id);
+			goto err;
+		}
+		break;
+	case ACPI_HEST_NOTIFY_SCI:
 		mutex_lock(&ghes_list_mutex);
 		if (list_empty(&ghes_sci))
 			register_acpi_hed_notifier(&ghes_notifier_sci);
 		list_add_rcu(&ghes->list, &ghes_sci);
 		mutex_unlock(&ghes_list_mutex);
-	} else {
-		unsigned char *notify = NULL;
-
-		switch (generic->notify.type) {
-		case ACPI_HEST_NOTIFY_POLLED:
-			notify = "POLL";
-			break;
-		case ACPI_HEST_NOTIFY_EXTERNAL:
-		case ACPI_HEST_NOTIFY_LOCAL:
-			notify = "IRQ";
-			break;
-		case ACPI_HEST_NOTIFY_NMI:
-			notify = "NMI";
-			break;
-		}
-		if (notify) {
-			pr_warning(GHES_PFX
-"Generic hardware error source: %d notified via %s is not supported!\n",
-				   generic->header.source_id, notify);
-		} else {
-			pr_warning(FW_WARN GHES_PFX
-"Unknown notification type: %u for generic hardware error source: %d\n",
-			generic->notify.type, generic->header.source_id);
-		}
-		rc = -ENODEV;
-		goto err;
+		break;
+	case ACPI_HEST_NOTIFY_NMI:
+		mutex_lock(&ghes_list_mutex);
+		if (list_empty(&ghes_nmi))
+			register_die_notifier(&ghes_notifier_nmi);
+		list_add_rcu(&ghes->list, &ghes_nmi);
+		mutex_unlock(&ghes_list_mutex);
+		break;
+	default:
+		BUG();
 	}
 	platform_set_drvdata(ghes_dev, ghes);
 
@@ -379,7 +601,14 @@ static int __devexit ghes_remove(struct
 	ghes = platform_get_drvdata(ghes_dev);
 	generic = ghes->generic;
 
+	ghes->flags |= GHES_EXITING;
 	switch (generic->notify.type) {
+	case ACPI_HEST_NOTIFY_POLLED:
+		del_timer_sync(&ghes->timer);
+		break;
+	case ACPI_HEST_NOTIFY_EXTERNAL:
+		free_irq(ghes->irq, ghes);
+		break;
 	case ACPI_HEST_NOTIFY_SCI:
 		mutex_lock(&ghes_list_mutex);
 		list_del_rcu(&ghes->list);
@@ -387,12 +616,23 @@ static int __devexit ghes_remove(struct
 			unregister_acpi_hed_notifier(&ghes_notifier_sci);
 		mutex_unlock(&ghes_list_mutex);
 		break;
+	case ACPI_HEST_NOTIFY_NMI:
+		mutex_lock(&ghes_list_mutex);
+		list_del_rcu(&ghes->list);
+		if (list_empty(&ghes_nmi))
+			unregister_die_notifier(&ghes_notifier_nmi);
+		mutex_unlock(&ghes_list_mutex);
+		/*
+		 * To synchronize with NMI handler, ghes can only be
+		 * freed after NMI handler finishes.
+		 */
+		synchronize_rcu();
+		break;
 	default:
 		BUG();
 		break;
 	}
 
-	synchronize_rcu();
 	ghes_fini(ghes);
 	kfree(ghes);
 
@@ -412,6 +652,8 @@ static struct platform_driver ghes_platf
 
 static int __init ghes_init(void)
 {
+	int rc;
+
 	if (acpi_disabled)
 		return -ENODEV;
 
@@ -420,12 +662,25 @@ static int __init ghes_init(void)
 		return -EINVAL;
 	}
 
-	return platform_driver_register(&ghes_platform_driver);
+	rc = ghes_ioremap_init();
+	if (rc)
+		goto err;
+
+	rc = platform_driver_register(&ghes_platform_driver);
+	if (rc)
+		goto err_ioremap_exit;
+
+	return 0;
+err_ioremap_exit:
+	ghes_ioremap_exit();
+err:
+	return rc;
 }
 
 static void __exit ghes_exit(void)
 {
 	platform_driver_unregister(&ghes_platform_driver);
+	ghes_ioremap_exit();
 }
 
 module_init(ghes_init);
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/apei/hest.c linux-libre-2.6.38-gnu1/drivers/acpi/apei/hest.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/apei/hest.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/apei/hest.c	2011-03-14 21:20:32.000000000 -0400
@@ -195,24 +195,24 @@ static int __init setup_hest_disable(cha
 
 __setup("hest_disable", setup_hest_disable);
 
-static int __init hest_init(void)
+void __init acpi_hest_init(void)
 {
 	acpi_status status;
 	int rc = -ENODEV;
 	unsigned int ghes_count = 0;
 
-	if (acpi_disabled)
-		goto err;
-
 	if (hest_disable) {
-		pr_info(HEST_PFX "HEST tabling parsing is disabled.\n");
-		goto err;
+		pr_info(HEST_PFX "Table parsing disabled.\n");
+		return;
 	}
 
+	if (acpi_disabled)
+		goto err;
+
 	status = acpi_get_table(ACPI_SIG_HEST, 0,
 				(struct acpi_table_header **)&hest_tab);
 	if (status == AE_NOT_FOUND) {
-		pr_info(HEST_PFX "Table is not found!\n");
+		pr_info(HEST_PFX "Table not found.\n");
 		goto err;
 	} else if (ACPI_FAILURE(status)) {
 		const char *msg = acpi_format_exception(status);
@@ -226,15 +226,11 @@ static int __init hest_init(void)
 		goto err;
 
 	rc = hest_ghes_dev_register(ghes_count);
-	if (rc)
-		goto err;
-
-	pr_info(HEST_PFX "HEST table parsing is initialized.\n");
+	if (!rc) {
+		pr_info(HEST_PFX "Table parsing has been initialized.\n");
+		return;
+	}
 
-	return 0;
 err:
 	hest_disable = 1;
-	return rc;
 }
-
-subsys_initcall(hest_init);
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/battery.c linux-libre-2.6.38-gnu1/drivers/acpi/battery.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/battery.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/battery.c	2011-03-14 21:20:32.000000000 -0400
@@ -631,6 +631,17 @@ static int acpi_battery_update(struct ac
 	return result;
 }
 
+static void acpi_battery_refresh(struct acpi_battery *battery)
+{
+	if (!battery->bat.dev)
+		return;
+
+	acpi_battery_get_info(battery);
+	/* The battery may have changed its reporting units. */
+	sysfs_remove_battery(battery);
+	sysfs_add_battery(battery);
+}
+
 /* --------------------------------------------------------------------------
                               FS Interface (/proc)
    -------------------------------------------------------------------------- */
@@ -868,6 +879,8 @@ static int acpi_battery_add_fs(struct ac
 	struct proc_dir_entry *entry = NULL;
 	int i;
 
+	printk(KERN_WARNING PREFIX "Deprecated procfs I/F for battery is loaded,"
+			" please retry with CONFIG_ACPI_PROCFS_POWER cleared\n");
 	if (!acpi_device_dir(device)) {
 		acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
 						     acpi_battery_dir);
@@ -914,6 +927,8 @@ static void acpi_battery_notify(struct a
 	if (!battery)
 		return;
 	old = battery->bat.dev;
+	if (event == ACPI_BATTERY_NOTIFY_INFO)
+		acpi_battery_refresh(battery);
 	acpi_battery_update(battery);
 	acpi_bus_generate_proc_event(device, event,
 				     acpi_battery_present(battery));
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/bus.c linux-libre-2.6.38-gnu1/drivers/acpi/bus.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/bus.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/bus.c	2011-03-14 21:20:32.000000000 -0400
@@ -52,22 +52,6 @@ EXPORT_SYMBOL(acpi_root_dir);
 
 #define STRUCT_TO_INT(s)	(*((int*)&s))
 
-static int set_power_nocheck(const struct dmi_system_id *id)
-{
-	printk(KERN_NOTICE PREFIX "%s detected - "
-		"disable power check in power transition\n", id->ident);
-	acpi_power_nocheck = 1;
-	return 0;
-}
-static struct dmi_system_id __cpuinitdata power_nocheck_dmi_table[] = {
-	{
-	set_power_nocheck, "HP Pavilion 05", {
-	DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
-	DMI_MATCH(DMI_SYS_VENDOR, "HP Pavilion 05"),
-	DMI_MATCH(DMI_PRODUCT_VERSION, "2001211RE101GLEND") }, NULL},
-	{},
-};
-
 
 #ifdef CONFIG_X86
 static int set_copy_dsdt(const struct dmi_system_id *id)
@@ -196,33 +180,24 @@ EXPORT_SYMBOL(acpi_bus_get_private_data)
                                  Power Management
    -------------------------------------------------------------------------- */
 
-int acpi_bus_get_power(acpi_handle handle, int *state)
+static int __acpi_bus_get_power(struct acpi_device *device, int *state)
 {
 	int result = 0;
 	acpi_status status = 0;
-	struct acpi_device *device = NULL;
 	unsigned long long psc = 0;
 
-
-	result = acpi_bus_get_device(handle, &device);
-	if (result)
-		return result;
+	if (!device || !state)
+		return -EINVAL;
 
 	*state = ACPI_STATE_UNKNOWN;
 
-	if (!device->flags.power_manageable) {
-		/* TBD: Non-recursive algorithm for walking up hierarchy */
-		if (device->parent)
-			*state = device->parent->power.state;
-		else
-			*state = ACPI_STATE_D0;
-	} else {
+	if (device->flags.power_manageable) {
 		/*
 		 * Get the device's power state either directly (via _PSC) or
 		 * indirectly (via power resources).
 		 */
 		if (device->power.flags.power_resources) {
-			result = acpi_power_get_inferred_state(device);
+			result = acpi_power_get_inferred_state(device, state);
 			if (result)
 				return result;
 		} else if (device->power.flags.explicit_get) {
@@ -230,59 +205,33 @@ int acpi_bus_get_power(acpi_handle handl
 						       NULL, &psc);
 			if (ACPI_FAILURE(status))
 				return -ENODEV;
-			device->power.state = (int)psc;
+			*state = (int)psc;
 		}
-
-		*state = device->power.state;
+	} else {
+		/* TBD: Non-recursive algorithm for walking up hierarchy. */
+		*state = device->parent ?
+			device->parent->power.state : ACPI_STATE_D0;
 	}
 
 	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] power state is D%d\n",
-			  device->pnp.bus_id, device->power.state));
+			  device->pnp.bus_id, *state));
 
 	return 0;
 }
 
-EXPORT_SYMBOL(acpi_bus_get_power);
 
-int acpi_bus_set_power(acpi_handle handle, int state)
+static int __acpi_bus_set_power(struct acpi_device *device, int state)
 {
 	int result = 0;
 	acpi_status status = AE_OK;
-	struct acpi_device *device = NULL;
 	char object_name[5] = { '_', 'P', 'S', '0' + state, '\0' };
 
-
-	result = acpi_bus_get_device(handle, &device);
-	if (result)
-		return result;
-
-	if ((state < ACPI_STATE_D0) || (state > ACPI_STATE_D3))
+	if (!device || (state < ACPI_STATE_D0) || (state > ACPI_STATE_D3))
 		return -EINVAL;
 
 	/* Make sure this is a valid target state */
 
-	if (!device->flags.power_manageable) {
-		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device `[%s]' is not power manageable\n",
-				kobject_name(&device->dev.kobj)));
-		return -ENODEV;
-	}
-	/*
-	 * Get device's current power state
-	 */
-	if (!acpi_power_nocheck) {
-		/*
-		 * Maybe the incorrect power state is returned on the bogus
-		 * bios, which is different with the real power state.
-		 * For example: the bios returns D0 state and the real power
-		 * state is D3. OS expects to set the device to D0 state. In
-		 * such case if OS uses the power state returned by the BIOS,
-		 * the device can't be transisted to the correct power state.
-		 * So if the acpi_power_nocheck is set, it is unnecessary to
-		 * get the power state by calling acpi_bus_get_power.
-		 */
-		acpi_bus_get_power(device->handle, &device->power.state);
-	}
-	if ((state == device->power.state) && !device->flags.force_power_state) {
+	if (state == device->power.state) {
 		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device is already at D%d\n",
 				  state));
 		return 0;
@@ -351,8 +300,75 @@ int acpi_bus_set_power(acpi_handle handl
 	return result;
 }
 
+
+int acpi_bus_set_power(acpi_handle handle, int state)
+{
+	struct acpi_device *device;
+	int result;
+
+	result = acpi_bus_get_device(handle, &device);
+	if (result)
+		return result;
+
+	if (!device->flags.power_manageable) {
+		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+				"Device [%s] is not power manageable\n",
+				dev_name(&device->dev)));
+		return -ENODEV;
+	}
+
+	return __acpi_bus_set_power(device, state);
+}
 EXPORT_SYMBOL(acpi_bus_set_power);
 
+
+int acpi_bus_init_power(struct acpi_device *device)
+{
+	int state;
+	int result;
+
+	if (!device)
+		return -EINVAL;
+
+	device->power.state = ACPI_STATE_UNKNOWN;
+
+	result = __acpi_bus_get_power(device, &state);
+	if (result)
+		return result;
+
+	if (device->power.flags.power_resources)
+		result = acpi_power_on_resources(device, state);
+
+	if (!result)
+		device->power.state = state;
+
+	return result;
+}
+
+
+int acpi_bus_update_power(acpi_handle handle, int *state_p)
+{
+	struct acpi_device *device;
+	int state;
+	int result;
+
+	result = acpi_bus_get_device(handle, &device);
+	if (result)
+		return result;
+
+	result = __acpi_bus_get_power(device, &state);
+	if (result)
+		return result;
+
+	result = __acpi_bus_set_power(device, state);
+	if (!result && state_p)
+		*state_p = state;
+
+	return result;
+}
+EXPORT_SYMBOL_GPL(acpi_bus_update_power);
+
+
 bool acpi_bus_power_manageable(acpi_handle handle)
 {
 	struct acpi_device *device;
@@ -1023,15 +1039,8 @@ static int __init acpi_init(void)
 	if (acpi_disabled)
 		return result;
 
-	/*
-	 * If the laptop falls into the DMI check table, the power state check
-	 * will be disabled in the course of device power transition.
-	 */
-	dmi_check_system(power_nocheck_dmi_table);
-
 	acpi_scan_init();
 	acpi_ec_init();
-	acpi_power_init();
 	acpi_debugfs_init();
 	acpi_sleep_proc_init();
 	acpi_wakeup_device_init();
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/button.c linux-libre-2.6.38-gnu1/drivers/acpi/button.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/button.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/button.c	2011-03-14 21:20:32.000000000 -0400
@@ -279,6 +279,9 @@ static int acpi_lid_send_state(struct ac
 	input_report_switch(button->input, SW_LID, !state);
 	input_sync(button->input);
 
+	if (state)
+		pm_wakeup_event(&device->dev, 0);
+
 	ret = blocking_notifier_call_chain(&acpi_lid_notifier, state, device);
 	if (ret == NOTIFY_DONE)
 		ret = blocking_notifier_call_chain(&acpi_lid_notifier, state,
@@ -314,6 +317,8 @@ static void acpi_button_notify(struct ac
 			input_sync(input);
 			input_report_key(input, keycode, 0);
 			input_sync(input);
+
+			pm_wakeup_event(&device->dev, 0);
 		}
 
 		acpi_bus_generate_proc_event(device, event, ++button->pushed);
@@ -426,7 +431,7 @@ static int acpi_button_add(struct acpi_d
 		acpi_enable_gpe(device->wakeup.gpe_device,
 				device->wakeup.gpe_number);
 		device->wakeup.run_wake_count++;
-		device->wakeup.state.enabled = 1;
+		device_set_wakeup_enable(&device->dev, true);
 	}
 
 	printk(KERN_INFO PREFIX "%s [%s]\n", name, acpi_device_bid(device));
@@ -449,7 +454,7 @@ static int acpi_button_remove(struct acp
 		acpi_disable_gpe(device->wakeup.gpe_device,
 				device->wakeup.gpe_number);
 		device->wakeup.run_wake_count--;
-		device->wakeup.state.enabled = 0;
+		device_set_wakeup_enable(&device->dev, false);
 	}
 
 	acpi_button_remove_fs(device);
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/debugfs.c linux-libre-2.6.38-gnu1/drivers/acpi/debugfs.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/debugfs.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/debugfs.c	2011-03-14 21:20:32.000000000 -0400
@@ -26,7 +26,9 @@ static ssize_t cm_write(struct file *fil
 			size_t count, loff_t *ppos)
 {
 	static char *buf;
-	static int uncopied_bytes;
+	static u32 max_size;
+	static u32 uncopied_bytes;
+
 	struct acpi_table_header table;
 	acpi_status status;
 
@@ -37,19 +39,24 @@ static ssize_t cm_write(struct file *fil
 		if (copy_from_user(&table, user_buf,
 				   sizeof(struct acpi_table_header)))
 			return -EFAULT;
-		uncopied_bytes = table.length;
-		buf = kzalloc(uncopied_bytes, GFP_KERNEL);
+		uncopied_bytes = max_size = table.length;
+		buf = kzalloc(max_size, GFP_KERNEL);
 		if (!buf)
 			return -ENOMEM;
 	}
 
-	if (uncopied_bytes < count) {
-		kfree(buf);
+	if (buf == NULL)
+		return -EINVAL;
+
+	if ((*ppos > max_size) ||
+	    (*ppos + count > max_size) ||
+	    (*ppos + count < count) ||
+	    (count > uncopied_bytes))
 		return -EINVAL;
-	}
 
 	if (copy_from_user(buf + (*ppos), user_buf, count)) {
 		kfree(buf);
+		buf = NULL;
 		return -EFAULT;
 	}
 
@@ -59,6 +66,7 @@ static ssize_t cm_write(struct file *fil
 	if (!uncopied_bytes) {
 		status = acpi_install_method(buf);
 		kfree(buf);
+		buf = NULL;
 		if (ACPI_FAILURE(status))
 			return -EINVAL;
 		add_taint(TAINT_OVERRIDDEN_ACPI_TABLE);
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/dock.c linux-libre-2.6.38-gnu1/drivers/acpi/dock.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/dock.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/dock.c	2011-03-14 21:20:32.000000000 -0400
@@ -725,7 +725,7 @@ static void dock_notify(acpi_handle hand
 			complete_dock(ds);
 			dock_event(ds, event, DOCK_EVENT);
 			dock_lock(ds, 1);
-			acpi_update_gpes();
+			acpi_update_all_gpes();
 			break;
 		}
 		if (dock_present(ds) || dock_in_progress(ds))
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/ec.c linux-libre-2.6.38-gnu1/drivers/acpi/ec.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/ec.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/ec.c	2011-03-14 21:20:32.000000000 -0400
@@ -606,7 +606,8 @@ static int ec_check_sci(struct acpi_ec *
 	return 0;
 }
 
-static u32 acpi_ec_gpe_handler(void *data)
+static u32 acpi_ec_gpe_handler(acpi_handle gpe_device,
+	u32 gpe_number, void *data)
 {
 	struct acpi_ec *ec = data;
 
@@ -618,7 +619,7 @@ static u32 acpi_ec_gpe_handler(void *dat
 		wake_up(&ec->wait);
 		ec_check_sci(ec, acpi_ec_read_status(ec));
 	}
-	return ACPI_INTERRUPT_HANDLED;
+	return ACPI_INTERRUPT_HANDLED | ACPI_REENABLE_GPE;
 }
 
 /* --------------------------------------------------------------------------
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/fan.c linux-libre-2.6.38-gnu1/drivers/acpi/fan.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/fan.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/fan.c	2011-03-14 21:20:32.000000000 -0400
@@ -86,7 +86,7 @@ static int fan_get_cur_state(struct ther
 	if (!device)
 		return -EINVAL;
 
-	result = acpi_bus_get_power(device->handle, &acpi_state);
+	result = acpi_bus_update_power(device->handle, &acpi_state);
 	if (result)
 		return result;
 
@@ -123,7 +123,6 @@ static struct thermal_cooling_device_ops
 static int acpi_fan_add(struct acpi_device *device)
 {
 	int result = 0;
-	int state = 0;
 	struct thermal_cooling_device *cdev;
 
 	if (!device)
@@ -132,16 +131,12 @@ static int acpi_fan_add(struct acpi_devi
 	strcpy(acpi_device_name(device), "Fan");
 	strcpy(acpi_device_class(device), ACPI_FAN_CLASS);
 
-	result = acpi_bus_get_power(device->handle, &state);
+	result = acpi_bus_update_power(device->handle, NULL);
 	if (result) {
-		printk(KERN_ERR PREFIX "Reading power state\n");
+		printk(KERN_ERR PREFIX "Setting initial power state\n");
 		goto end;
 	}
 
-	device->flags.force_power_state = 1;
-	acpi_bus_set_power(device->handle, state);
-	device->flags.force_power_state = 0;
-
 	cdev = thermal_cooling_device_register("Fan", device,
 						&fan_cooling_ops);
 	if (IS_ERR(cdev)) {
@@ -200,22 +195,14 @@ static int acpi_fan_suspend(struct acpi_
 
 static int acpi_fan_resume(struct acpi_device *device)
 {
-	int result = 0;
-	int power_state = 0;
+	int result;
 
 	if (!device)
 		return -EINVAL;
 
-	result = acpi_bus_get_power(device->handle, &power_state);
-	if (result) {
-		printk(KERN_ERR PREFIX
-				  "Error reading fan power state\n");
-		return result;
-	}
-
-	device->flags.force_power_state = 1;
-	acpi_bus_set_power(device->handle, power_state);
-	device->flags.force_power_state = 0;
+	result = acpi_bus_update_power(device->handle, NULL);
+	if (result)
+		printk(KERN_ERR PREFIX "Error updating fan power state\n");
 
 	return result;
 }
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/glue.c linux-libre-2.6.38-gnu1/drivers/acpi/glue.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/glue.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/glue.c	2011-03-14 21:20:32.000000000 -0400
@@ -167,11 +167,8 @@ static int acpi_bind_one(struct device *
 				"firmware_node");
 		ret = sysfs_create_link(&acpi_dev->dev.kobj, &dev->kobj,
 				"physical_node");
-		if (acpi_dev->wakeup.flags.valid) {
+		if (acpi_dev->wakeup.flags.valid)
 			device_set_wakeup_capable(dev, true);
-			device_set_wakeup_enable(dev,
-						acpi_dev->wakeup.state.enabled);
-		}
 	}
 
 	return 0;
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/internal.h linux-libre-2.6.38-gnu1/drivers/acpi/internal.h
--- linux-libre-2.6.37-gnu1/drivers/acpi/internal.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/internal.h	2011-03-14 21:20:32.000000000 -0400
@@ -41,9 +41,10 @@ static inline int acpi_debugfs_init(void
 int acpi_power_init(void);
 int acpi_device_sleep_wake(struct acpi_device *dev,
                            int enable, int sleep_state, int dev_state);
-int acpi_power_get_inferred_state(struct acpi_device *device);
+int acpi_power_get_inferred_state(struct acpi_device *device, int *state);
+int acpi_power_on_resources(struct acpi_device *device, int state);
 int acpi_power_transition(struct acpi_device *device, int state);
-extern int acpi_power_nocheck;
+int acpi_bus_init_power(struct acpi_device *device);
 
 int acpi_wakeup_device_init(void);
 void acpi_early_processor_set_pdc(void);
@@ -82,8 +83,16 @@ extern int acpi_sleep_init(void);
 
 #ifdef CONFIG_ACPI_SLEEP
 int acpi_sleep_proc_init(void);
+int suspend_nvs_alloc(void);
+void suspend_nvs_free(void);
+int suspend_nvs_save(void);
+void suspend_nvs_restore(void);
 #else
 static inline int acpi_sleep_proc_init(void) { return 0; }
+static inline int suspend_nvs_alloc(void) { return 0; }
+static inline void suspend_nvs_free(void) {}
+static inline int suspend_nvs_save(void) { return 0; }
+static inline void suspend_nvs_restore(void) {}
 #endif
 
 #endif /* _ACPI_INTERNAL_H_ */
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/Kconfig linux-libre-2.6.38-gnu1/drivers/acpi/Kconfig
--- linux-libre-2.6.37-gnu1/drivers/acpi/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -51,12 +51,7 @@ config ACPI_PROCFS
 	  For backwards compatibility, this option allows
 	  deprecated /proc/acpi/ files to exist, even when
 	  they have been replaced by functions in /sys.
-	  The deprecated files (and their replacements) include:
 
-	  /proc/acpi/processor/*/throttling (/sys/class/thermal/
-		cooling_device*/*)
-	  /proc/acpi/video/*/brightness (/sys/class/backlight/)
-	  /proc/acpi/thermal_zone/*/* (/sys/class/thermal/)
 	  This option has no effect on /proc/acpi/ files
 	  and functions which do not yet exist in /sys.
 
@@ -74,6 +69,8 @@ config ACPI_PROCFS_POWER
 	  /proc/acpi/ac_adapter/* (sys/class/power_supply/*)
 	  This option has no effect on /proc/acpi/ directories
 	  and functions, which do not yet exist in /sys
+	  This option, together with the proc directories, will be
+	  deleted in 2.6.39.
 
 	  Say N to delete power /proc/acpi/ directories that have moved to /sys/
 
@@ -209,6 +206,17 @@ config ACPI_PROCESSOR
 
 	  To compile this driver as a module, choose M here:
 	  the module will be called processor.
+config ACPI_IPMI
+	tristate "IPMI"
+	depends on EXPERIMENTAL && IPMI_SI && IPMI_HANDLER
+	default n
+	help
+	  This driver enables the ACPI to access the BMC controller. And it
+	  uses the IPMI request/response message to communicate with BMC
+	  controller, which can be found on on the server.
+
+	  To compile this driver as a module, choose M here:
+	  the module will be called as acpi_ipmi.
 
 config ACPI_HOTPLUG_CPU
 	bool
@@ -310,7 +318,7 @@ config ACPI_PCI_SLOT
 	  the module will be called pci_slot.
 
 config X86_PM_TIMER
-	bool "Power Management Timer Support" if EMBEDDED
+	bool "Power Management Timer Support" if EXPERT
 	depends on X86
 	default y
 	help
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/Makefile linux-libre-2.6.38-gnu1/drivers/acpi/Makefile
--- linux-libre-2.6.37-gnu1/drivers/acpi/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -24,7 +24,7 @@ acpi-y				+= atomicio.o
 # sleep related files
 acpi-y				+= wakeup.o
 acpi-y				+= sleep.o
-acpi-$(CONFIG_ACPI_SLEEP)	+= proc.o
+acpi-$(CONFIG_ACPI_SLEEP)	+= proc.o nvs.o
 
 
 #
@@ -69,5 +69,6 @@ processor-y			+= processor_idle.o proces
 processor-$(CONFIG_CPU_FREQ)	+= processor_perflib.o
 
 obj-$(CONFIG_ACPI_PROCESSOR_AGGREGATOR) += acpi_pad.o
+obj-$(CONFIG_ACPI_IPMI)		+= acpi_ipmi.o
 
 obj-$(CONFIG_ACPI_APEI)		+= apei/
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/numa.c linux-libre-2.6.38-gnu1/drivers/acpi/numa.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/numa.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/numa.c	2011-03-14 21:20:32.000000000 -0400
@@ -276,12 +276,18 @@ int __init acpi_numa_init(void)
 {
 	int ret = 0;
 
+	/*
+	 * Should not limit number with cpu num that is from NR_CPUS or nr_cpus=
+	 * SRAT cpu entries could have different order with that in MADT.
+	 * So go over all cpu entries in SRAT to get apicid to node mapping.
+	 */
+
 	/* SRAT: Static Resource Affinity Table */
 	if (!acpi_table_parse(ACPI_SIG_SRAT, acpi_parse_srat)) {
 		acpi_table_parse_srat(ACPI_SRAT_TYPE_X2APIC_CPU_AFFINITY,
-				     acpi_parse_x2apic_affinity, nr_cpu_ids);
+				     acpi_parse_x2apic_affinity, 0);
 		acpi_table_parse_srat(ACPI_SRAT_TYPE_CPU_AFFINITY,
-				     acpi_parse_processor_affinity, nr_cpu_ids);
+				     acpi_parse_processor_affinity, 0);
 		ret = acpi_table_parse_srat(ACPI_SRAT_TYPE_MEMORY_AFFINITY,
 					    acpi_parse_memory_affinity,
 					    NR_NODE_MEMBLKS);
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/nvs.c linux-libre-2.6.38-gnu1/drivers/acpi/nvs.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/nvs.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/nvs.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,145 @@
+/*
+ * nvs.c - Routines for saving and restoring ACPI NVS memory region
+ *
+ * Copyright (C) 2008-2011 Rafael J. Wysocki <rjw@sisk.pl>, Novell Inc.
+ *
+ * This file is released under the GPLv2.
+ */
+
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/acpi.h>
+#include <linux/acpi_io.h>
+#include <acpi/acpiosxf.h>
+
+/*
+ * Platforms, like ACPI, may want us to save some memory used by them during
+ * suspend and to restore the contents of this memory during the subsequent
+ * resume.  The code below implements a mechanism allowing us to do that.
+ */
+
+struct nvs_page {
+	unsigned long phys_start;
+	unsigned int size;
+	void *kaddr;
+	void *data;
+	struct list_head node;
+};
+
+static LIST_HEAD(nvs_list);
+
+/**
+ *	suspend_nvs_register - register platform NVS memory region to save
+ *	@start - physical address of the region
+ *	@size - size of the region
+ *
+ *	The NVS region need not be page-aligned (both ends) and we arrange
+ *	things so that the data from page-aligned addresses in this region will
+ *	be copied into separate RAM pages.
+ */
+int suspend_nvs_register(unsigned long start, unsigned long size)
+{
+	struct nvs_page *entry, *next;
+
+	while (size > 0) {
+		unsigned int nr_bytes;
+
+		entry = kzalloc(sizeof(struct nvs_page), GFP_KERNEL);
+		if (!entry)
+			goto Error;
+
+		list_add_tail(&entry->node, &nvs_list);
+		entry->phys_start = start;
+		nr_bytes = PAGE_SIZE - (start & ~PAGE_MASK);
+		entry->size = (size < nr_bytes) ? size : nr_bytes;
+
+		start += entry->size;
+		size -= entry->size;
+	}
+	return 0;
+
+ Error:
+	list_for_each_entry_safe(entry, next, &nvs_list, node) {
+		list_del(&entry->node);
+		kfree(entry);
+	}
+	return -ENOMEM;
+}
+
+/**
+ *	suspend_nvs_free - free data pages allocated for saving NVS regions
+ */
+void suspend_nvs_free(void)
+{
+	struct nvs_page *entry;
+
+	list_for_each_entry(entry, &nvs_list, node)
+		if (entry->data) {
+			free_page((unsigned long)entry->data);
+			entry->data = NULL;
+			if (entry->kaddr) {
+				iounmap(entry->kaddr);
+				entry->kaddr = NULL;
+			}
+		}
+}
+
+/**
+ *	suspend_nvs_alloc - allocate memory necessary for saving NVS regions
+ */
+int suspend_nvs_alloc(void)
+{
+	struct nvs_page *entry;
+
+	list_for_each_entry(entry, &nvs_list, node) {
+		entry->data = (void *)__get_free_page(GFP_KERNEL);
+		if (!entry->data) {
+			suspend_nvs_free();
+			return -ENOMEM;
+		}
+	}
+	return 0;
+}
+
+/**
+ *	suspend_nvs_save - save NVS memory regions
+ */
+int suspend_nvs_save(void)
+{
+	struct nvs_page *entry;
+
+	printk(KERN_INFO "PM: Saving platform NVS memory\n");
+
+	list_for_each_entry(entry, &nvs_list, node)
+		if (entry->data) {
+			entry->kaddr = acpi_os_ioremap(entry->phys_start,
+						    entry->size);
+			if (!entry->kaddr) {
+				suspend_nvs_free();
+				return -ENOMEM;
+			}
+			memcpy(entry->data, entry->kaddr, entry->size);
+		}
+
+	return 0;
+}
+
+/**
+ *	suspend_nvs_restore - restore NVS memory regions
+ *
+ *	This function is going to be called with interrupts disabled, so it
+ *	cannot iounmap the virtual addresses used to access the NVS region.
+ */
+void suspend_nvs_restore(void)
+{
+	struct nvs_page *entry;
+
+	printk(KERN_INFO "PM: Restoring platform NVS memory\n");
+
+	list_for_each_entry(entry, &nvs_list, node)
+		if (entry->data)
+			memcpy(entry->kaddr, entry->data, entry->size);
+}
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/osl.c linux-libre-2.6.38-gnu1/drivers/acpi/osl.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/osl.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/osl.c	2011-03-14 21:20:32.000000000 -0400
@@ -38,6 +38,7 @@
 #include <linux/workqueue.h>
 #include <linux/nmi.h>
 #include <linux/acpi.h>
+#include <linux/acpi_io.h>
 #include <linux/efi.h>
 #include <linux/ioport.h>
 #include <linux/list.h>
@@ -302,9 +303,10 @@ void __iomem *__init_refok
 acpi_os_map_memory(acpi_physical_address phys, acpi_size size)
 {
 	struct acpi_ioremap *map, *tmp_map;
-	unsigned long flags, pg_sz;
+	unsigned long flags;
 	void __iomem *virt;
-	phys_addr_t pg_off;
+	acpi_physical_address pg_off;
+	acpi_size pg_sz;
 
 	if (phys > ULONG_MAX) {
 		printk(KERN_ERR PREFIX "Cannot map memory that high\n");
@@ -320,7 +322,7 @@ acpi_os_map_memory(acpi_physical_address
 
 	pg_off = round_down(phys, PAGE_SIZE);
 	pg_sz = round_up(phys + size, PAGE_SIZE) - pg_off;
-	virt = ioremap(pg_off, pg_sz);
+	virt = acpi_os_ioremap(pg_off, pg_sz);
 	if (!virt) {
 		kfree(map);
 		return NULL;
@@ -634,17 +636,21 @@ EXPORT_SYMBOL(acpi_os_write_port);
 acpi_status
 acpi_os_read_memory(acpi_physical_address phys_addr, u32 * value, u32 width)
 {
-	u32 dummy;
 	void __iomem *virt_addr;
-	int size = width / 8, unmap = 0;
+	unsigned int size = width / 8;
+	bool unmap = false;
+	u32 dummy;
 
 	rcu_read_lock();
 	virt_addr = acpi_map_vaddr_lookup(phys_addr, size);
-	rcu_read_unlock();
 	if (!virt_addr) {
-		virt_addr = ioremap(phys_addr, size);
-		unmap = 1;
+		rcu_read_unlock();
+		virt_addr = acpi_os_ioremap(phys_addr, size);
+		if (!virt_addr)
+			return AE_BAD_ADDRESS;
+		unmap = true;
 	}
+
 	if (!value)
 		value = &dummy;
 
@@ -664,6 +670,8 @@ acpi_os_read_memory(acpi_physical_addres
 
 	if (unmap)
 		iounmap(virt_addr);
+	else
+		rcu_read_unlock();
 
 	return AE_OK;
 }
@@ -672,14 +680,17 @@ acpi_status
 acpi_os_write_memory(acpi_physical_address phys_addr, u32 value, u32 width)
 {
 	void __iomem *virt_addr;
-	int size = width / 8, unmap = 0;
+	unsigned int size = width / 8;
+	bool unmap = false;
 
 	rcu_read_lock();
 	virt_addr = acpi_map_vaddr_lookup(phys_addr, size);
-	rcu_read_unlock();
 	if (!virt_addr) {
-		virt_addr = ioremap(phys_addr, size);
-		unmap = 1;
+		rcu_read_unlock();
+		virt_addr = acpi_os_ioremap(phys_addr, size);
+		if (!virt_addr)
+			return AE_BAD_ADDRESS;
+		unmap = true;
 	}
 
 	switch (width) {
@@ -698,6 +709,8 @@ acpi_os_write_memory(acpi_physical_addre
 
 	if (unmap)
 		iounmap(virt_addr);
+	else
+		rcu_read_unlock();
 
 	return AE_OK;
 }
@@ -1233,8 +1246,7 @@ __setup("acpi_enforce_resources=", acpi_
 int acpi_check_resource_conflict(const struct resource *res)
 {
 	struct acpi_res_list *res_list_elem;
-	int ioport;
-	int clash = 0;
+	int ioport = 0, clash = 0;
 
 	if (acpi_enforce_resources == ENFORCE_RESOURCES_NO)
 		return 0;
@@ -1264,9 +1276,13 @@ int acpi_check_resource_conflict(const s
 	if (clash) {
 		if (acpi_enforce_resources != ENFORCE_RESOURCES_NO) {
 			printk(KERN_WARNING "ACPI: resource %s %pR"
-			       " conflicts with ACPI region %s %pR\n",
+			       " conflicts with ACPI region %s "
+			       "[%s 0x%zx-0x%zx]\n",
 			       res->name, res, res_list_elem->name,
-			       res_list_elem);
+			       (res_list_elem->resource_type ==
+				ACPI_ADR_SPACE_SYSTEM_IO) ? "io" : "mem",
+			       (size_t) res_list_elem->start,
+			       (size_t) res_list_elem->end);
 			if (acpi_enforce_resources == ENFORCE_RESOURCES_LAX)
 				printk(KERN_NOTICE "ACPI: This conflict may"
 				       " cause random problems and system"
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/pci_root.c linux-libre-2.6.38-gnu1/drivers/acpi/pci_root.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/pci_root.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/pci_root.c	2011-03-14 21:20:32.000000000 -0400
@@ -36,6 +36,7 @@
 #include <linux/slab.h>
 #include <acpi/acpi_bus.h>
 #include <acpi/acpi_drivers.h>
+#include <acpi/apei.h>
 
 #define PREFIX "ACPI: "
 
@@ -47,6 +48,11 @@ static int acpi_pci_root_add(struct acpi
 static int acpi_pci_root_remove(struct acpi_device *device, int type);
 static int acpi_pci_root_start(struct acpi_device *device);
 
+#define ACPI_PCIE_REQ_SUPPORT (OSC_EXT_PCI_CONFIG_SUPPORT \
+				| OSC_ACTIVE_STATE_PWR_SUPPORT \
+				| OSC_CLOCK_PWR_CAPABILITY_SUPPORT \
+				| OSC_MSI_SUPPORT)
+
 static const struct acpi_device_id root_device_ids[] = {
 	{"PNP0A03", 0},
 	{"", 0},
@@ -566,6 +572,33 @@ static int __devinit acpi_pci_root_add(s
 	if (flags != base_flags)
 		acpi_pci_osc_support(root, flags);
 
+	if (!pcie_ports_disabled
+	    && (flags & ACPI_PCIE_REQ_SUPPORT) == ACPI_PCIE_REQ_SUPPORT) {
+		flags = OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL
+			| OSC_PCI_EXPRESS_NATIVE_HP_CONTROL
+			| OSC_PCI_EXPRESS_PME_CONTROL;
+
+		if (pci_aer_available()) {
+			if (aer_acpi_firmware_first())
+				dev_dbg(root->bus->bridge,
+					"PCIe errors handled by BIOS.\n");
+			else
+				flags |= OSC_PCI_EXPRESS_AER_CONTROL;
+		}
+
+		dev_info(root->bus->bridge,
+			"Requesting ACPI _OSC control (0x%02x)\n", flags);
+
+		status = acpi_pci_osc_control_set(device->handle, &flags,
+					OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL);
+		if (ACPI_SUCCESS(status))
+			dev_info(root->bus->bridge,
+				"ACPI _OSC control (0x%02x) granted\n", flags);
+		else
+			dev_dbg(root->bus->bridge,
+				"ACPI _OSC request failed (code %d)\n", status);
+	}
+
 	pci_acpi_add_bus_pm_notifier(device, root->bus);
 	if (device->wakeup.flags.run_wake)
 		device_set_run_wake(root->bus->bridge, true);
@@ -600,6 +633,8 @@ static int acpi_pci_root_remove(struct a
 
 static int __init acpi_pci_root_init(void)
 {
+	acpi_hest_init();
+
 	if (acpi_pci_disabled)
 		return 0;
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/power.c linux-libre-2.6.38-gnu1/drivers/acpi/power.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/power.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/power.c	2011-03-14 21:20:32.000000000 -0400
@@ -56,9 +56,6 @@ ACPI_MODULE_NAME("power");
 #define ACPI_POWER_RESOURCE_STATE_ON	0x01
 #define ACPI_POWER_RESOURCE_STATE_UNKNOWN 0xFF
 
-int acpi_power_nocheck;
-module_param_named(power_nocheck, acpi_power_nocheck, bool, 000);
-
 static int acpi_power_add(struct acpi_device *device);
 static int acpi_power_remove(struct acpi_device *device, int type);
 static int acpi_power_resume(struct acpi_device *device);
@@ -148,9 +145,8 @@ static int acpi_power_get_state(acpi_han
 
 static int acpi_power_get_list_state(struct acpi_handle_list *list, int *state)
 {
-	int result = 0, state1;
-	u32 i = 0;
-
+	int cur_state;
+	int i = 0;
 
 	if (!list || !state)
 		return -EINVAL;
@@ -158,25 +154,33 @@ static int acpi_power_get_list_state(str
 	/* The state of the list is 'on' IFF all resources are 'on'. */
 
 	for (i = 0; i < list->count; i++) {
-		/*
-		 * The state of the power resource can be obtained by
-		 * using the ACPI handle. In such case it is unnecessary to
-		 * get the Power resource first and then get its state again.
-		 */
-		result = acpi_power_get_state(list->handles[i], &state1);
+		struct acpi_power_resource *resource;
+		acpi_handle handle = list->handles[i];
+		int result;
+
+		result = acpi_power_get_context(handle, &resource);
 		if (result)
 			return result;
 
-		*state = state1;
+		mutex_lock(&resource->resource_lock);
 
-		if (*state != ACPI_POWER_RESOURCE_STATE_ON)
+		result = acpi_power_get_state(handle, &cur_state);
+
+		mutex_unlock(&resource->resource_lock);
+
+		if (result)
+			return result;
+
+		if (cur_state != ACPI_POWER_RESOURCE_STATE_ON)
 			break;
 	}
 
 	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource list is %s\n",
-			  *state ? "on" : "off"));
+			  cur_state ? "on" : "off"));
 
-	return result;
+	*state = cur_state;
+
+	return 0;
 }
 
 static int __acpi_power_on(struct acpi_power_resource *resource)
@@ -222,7 +226,7 @@ static int acpi_power_on(acpi_handle han
 	return result;
 }
 
-static int acpi_power_off_device(acpi_handle handle)
+static int acpi_power_off(acpi_handle handle)
 {
 	int result = 0;
 	acpi_status status = AE_OK;
@@ -266,6 +270,35 @@ static int acpi_power_off_device(acpi_ha
 	return result;
 }
 
+static void __acpi_power_off_list(struct acpi_handle_list *list, int num_res)
+{
+	int i;
+
+	for (i = num_res - 1; i >= 0 ; i--)
+		acpi_power_off(list->handles[i]);
+}
+
+static void acpi_power_off_list(struct acpi_handle_list *list)
+{
+	__acpi_power_off_list(list, list->count);
+}
+
+static int acpi_power_on_list(struct acpi_handle_list *list)
+{
+	int result = 0;
+	int i;
+
+	for (i = 0; i < list->count; i++) {
+		result = acpi_power_on(list->handles[i]);
+		if (result) {
+			__acpi_power_off_list(list, i);
+			break;
+		}
+	}
+
+	return result;
+}
+
 /**
  * acpi_device_sleep_wake - execute _DSW (Device Sleep Wake) or (deprecated in
  *                          ACPI 3.0) _PSW (Power State Wake)
@@ -404,8 +437,7 @@ int acpi_disable_wakeup_device_power(str
 
 	/* Close power resource */
 	for (i = 0; i < dev->wakeup.resources.count; i++) {
-		int ret = acpi_power_off_device(
-				dev->wakeup.resources.handles[i]);
+		int ret = acpi_power_off(dev->wakeup.resources.handles[i]);
 		if (ret) {
 			printk(KERN_ERR PREFIX "Transition power state\n");
 			dev->wakeup.flags.valid = 0;
@@ -423,19 +455,16 @@ int acpi_disable_wakeup_device_power(str
                              Device Power Management
    -------------------------------------------------------------------------- */
 
-int acpi_power_get_inferred_state(struct acpi_device *device)
+int acpi_power_get_inferred_state(struct acpi_device *device, int *state)
 {
 	int result = 0;
 	struct acpi_handle_list *list = NULL;
 	int list_state = 0;
 	int i = 0;
 
-
-	if (!device)
+	if (!device || !state)
 		return -EINVAL;
 
-	device->power.state = ACPI_STATE_UNKNOWN;
-
 	/*
 	 * We know a device's inferred power state when all the resources
 	 * required for a given D-state are 'on'.
@@ -450,22 +479,26 @@ int acpi_power_get_inferred_state(struct
 			return result;
 
 		if (list_state == ACPI_POWER_RESOURCE_STATE_ON) {
-			device->power.state = i;
+			*state = i;
 			return 0;
 		}
 	}
 
-	device->power.state = ACPI_STATE_D3;
-
+	*state = ACPI_STATE_D3;
 	return 0;
 }
 
+int acpi_power_on_resources(struct acpi_device *device, int state)
+{
+	if (!device || state < ACPI_STATE_D0 || state > ACPI_STATE_D3)
+		return -EINVAL;
+
+	return acpi_power_on_list(&device->power.states[state].resources);
+}
+
 int acpi_power_transition(struct acpi_device *device, int state)
 {
-	int result = 0;
-	struct acpi_handle_list *cl = NULL;	/* Current Resources */
-	struct acpi_handle_list *tl = NULL;	/* Target Resources */
-	int i = 0;
+	int result;
 
 	if (!device || (state < ACPI_STATE_D0) || (state > ACPI_STATE_D3))
 		return -EINVAL;
@@ -477,37 +510,20 @@ int acpi_power_transition(struct acpi_de
 	    || (device->power.state > ACPI_STATE_D3))
 		return -ENODEV;
 
-	cl = &device->power.states[device->power.state].resources;
-	tl = &device->power.states[state].resources;
-
 	/* TBD: Resources must be ordered. */
 
 	/*
 	 * First we reference all power resources required in the target list
-	 * (e.g. so the device doesn't lose power while transitioning).
-	 */
-	for (i = 0; i < tl->count; i++) {
-		result = acpi_power_on(tl->handles[i]);
-		if (result)
-			goto end;
-	}
-
-	/*
-	 * Then we dereference all power resources used in the current list.
+	 * (e.g. so the device doesn't lose power while transitioning).  Then,
+	 * we dereference all power resources used in the current list.
 	 */
-	for (i = 0; i < cl->count; i++) {
-		result = acpi_power_off_device(cl->handles[i]);
-		if (result)
-			goto end;
-	}
+	result = acpi_power_on_list(&device->power.states[state].resources);
+	if (!result)
+		acpi_power_off_list(
+			&device->power.states[device->power.state].resources);
 
-     end:
-	if (result)
-		device->power.state = ACPI_STATE_UNKNOWN;
-	else {
-	/* We shouldn't change the state till all above operations succeed */
-		device->power.state = state;
-	}
+	/* We shouldn't change the state unless the above operations succeed. */
+	device->power.state = result ? ACPI_STATE_UNKNOWN : state;
 
 	return result;
 }
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/proc.c linux-libre-2.6.38-gnu1/drivers/acpi/proc.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/proc.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/proc.c	2011-03-14 21:20:32.000000000 -0400
@@ -311,7 +311,9 @@ acpi_system_wakeup_device_seq_show(struc
 			   dev->pnp.bus_id,
 			   (u32) dev->wakeup.sleep_state,
 			   dev->wakeup.flags.run_wake ? '*' : ' ',
-			   dev->wakeup.state.enabled ? "enabled" : "disabled");
+			   (device_may_wakeup(&dev->dev)
+			     || (ldev && device_may_wakeup(ldev))) ?
+			       "enabled" : "disabled");
 		if (ldev)
 			seq_printf(seq, "%s:%s",
 				   ldev->bus ? ldev->bus->name : "no-bus",
@@ -328,8 +330,10 @@ static void physical_device_enable_wakeu
 {
 	struct device *dev = acpi_get_physical_device(adev->handle);
 
-	if (dev && device_can_wakeup(dev))
-		device_set_wakeup_enable(dev, adev->wakeup.state.enabled);
+	if (dev && device_can_wakeup(dev)) {
+		bool enable = !device_may_wakeup(dev);
+		device_set_wakeup_enable(dev, enable);
+	}
 }
 
 static ssize_t
@@ -341,7 +345,6 @@ acpi_system_write_wakeup_device(struct f
 	char strbuf[5];
 	char str[5] = "";
 	unsigned int len = count;
-	struct acpi_device *found_dev = NULL;
 
 	if (len > 4)
 		len = 4;
@@ -361,33 +364,13 @@ acpi_system_write_wakeup_device(struct f
 			continue;
 
 		if (!strncmp(dev->pnp.bus_id, str, 4)) {
-			dev->wakeup.state.enabled =
-			    dev->wakeup.state.enabled ? 0 : 1;
-			found_dev = dev;
-			break;
-		}
-	}
-	if (found_dev) {
-		physical_device_enable_wakeup(found_dev);
-		list_for_each_safe(node, next, &acpi_wakeup_device_list) {
-			struct acpi_device *dev = container_of(node,
-							       struct
-							       acpi_device,
-							       wakeup_list);
-
-			if ((dev != found_dev) &&
-			    (dev->wakeup.gpe_number ==
-			     found_dev->wakeup.gpe_number)
-			    && (dev->wakeup.gpe_device ==
-				found_dev->wakeup.gpe_device)) {
-				printk(KERN_WARNING
-				       "ACPI: '%s' and '%s' have the same GPE, "
-				       "can't disable/enable one separately\n",
-				       dev->pnp.bus_id, found_dev->pnp.bus_id);
-				dev->wakeup.state.enabled =
-				    found_dev->wakeup.state.enabled;
+			if (device_can_wakeup(&dev->dev)) {
+				bool enable = !device_may_wakeup(&dev->dev);
+				device_set_wakeup_enable(&dev->dev, enable);
+			} else {
 				physical_device_enable_wakeup(dev);
 			}
+			break;
 		}
 	}
 	mutex_unlock(&acpi_device_lock);
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/processor_core.c linux-libre-2.6.38-gnu1/drivers/acpi/processor_core.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/processor_core.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/processor_core.c	2011-03-14 21:20:32.000000000 -0400
@@ -23,7 +23,7 @@ static int set_no_mwait(const struct dmi
 {
 	printk(KERN_NOTICE PREFIX "%s detected - "
 		"disabling mwait for CPU C-states\n", id->ident);
-	idle_nomwait = 1;
+	boot_option_idle_override = IDLE_NOMWAIT;
 	return 0;
 }
 
@@ -283,7 +283,7 @@ acpi_processor_eval_pdc(acpi_handle hand
 {
 	acpi_status status = AE_OK;
 
-	if (idle_nomwait) {
+	if (boot_option_idle_override == IDLE_NOMWAIT) {
 		/*
 		 * If mwait is disabled for CPU C-states, the C2C3_FFH access
 		 * mode will be disabled in the parameter of _PDC object.
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/processor_driver.c linux-libre-2.6.38-gnu1/drivers/acpi/processor_driver.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/processor_driver.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/processor_driver.c	2011-03-14 21:20:32.000000000 -0400
@@ -40,10 +40,6 @@
 #include <linux/pm.h>
 #include <linux/cpufreq.h>
 #include <linux/cpu.h>
-#ifdef CONFIG_ACPI_PROCFS
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
-#endif
 #include <linux/dmi.h>
 #include <linux/moduleparam.h>
 #include <linux/cpuidle.h>
@@ -246,53 +242,6 @@ static int acpi_processor_errata(struct
 	return result;
 }
 
-#ifdef CONFIG_ACPI_PROCFS
-static struct proc_dir_entry *acpi_processor_dir = NULL;
-
-static int __cpuinit acpi_processor_add_fs(struct acpi_device *device)
-{
-	struct proc_dir_entry *entry = NULL;
-
-
-	if (!acpi_device_dir(device)) {
-		acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
-						     acpi_processor_dir);
-		if (!acpi_device_dir(device))
-			return -ENODEV;
-	}
-
-	/* 'throttling' [R/W] */
-	entry = proc_create_data(ACPI_PROCESSOR_FILE_THROTTLING,
-				 S_IFREG | S_IRUGO | S_IWUSR,
-				 acpi_device_dir(device),
-				 &acpi_processor_throttling_fops,
-				 acpi_driver_data(device));
-	if (!entry)
-		return -EIO;
-	return 0;
-}
-static int acpi_processor_remove_fs(struct acpi_device *device)
-{
-
-	if (acpi_device_dir(device)) {
-		remove_proc_entry(ACPI_PROCESSOR_FILE_THROTTLING,
-				  acpi_device_dir(device));
-		remove_proc_entry(acpi_device_bid(device), acpi_processor_dir);
-		acpi_device_dir(device) = NULL;
-	}
-
-	return 0;
-}
-#else
-static inline int acpi_processor_add_fs(struct acpi_device *device)
-{
-	return 0;
-}
-static inline int acpi_processor_remove_fs(struct acpi_device *device)
-{
-	return 0;
-}
-#endif
 /* --------------------------------------------------------------------------
                                  Driver Interface
    -------------------------------------------------------------------------- */
@@ -478,8 +427,13 @@ 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_reevaluate_tstate(pr, action);
 		acpi_processor_tstate_has_changed(pr);
 	}
+	if (action == CPU_DEAD && pr) {
+		/* invalidate the flag.throttling after one CPU is offline */
+		acpi_processor_reevaluate_tstate(pr, action);
+	}
 	return NOTIFY_OK;
 }
 
@@ -537,14 +491,10 @@ static int __cpuinit acpi_processor_add(
 
 	per_cpu(processors, pr->id) = pr;
 
-	result = acpi_processor_add_fs(device);
-	if (result)
-		goto err_free_cpumask;
-
 	sysdev = get_cpu_sysdev(pr->id);
 	if (sysfs_create_link(&device->dev.kobj, &sysdev->kobj, "sysdev")) {
 		result = -EFAULT;
-		goto err_remove_fs;
+		goto err_free_cpumask;
 	}
 
 #ifdef CONFIG_CPU_FREQ
@@ -590,8 +540,6 @@ err_thermal_unregister:
 	thermal_cooling_device_unregister(pr->cdev);
 err_power_exit:
 	acpi_processor_power_exit(pr, device);
-err_remove_fs:
-	acpi_processor_remove_fs(device);
 err_free_cpumask:
 	free_cpumask_var(pr->throttling.shared_cpu_map);
 
@@ -620,8 +568,6 @@ static int acpi_processor_remove(struct
 
 	sysfs_remove_link(&device->dev.kobj, "sysdev");
 
-	acpi_processor_remove_fs(device);
-
 	if (pr->cdev) {
 		sysfs_remove_link(&device->dev.kobj, "thermal_cooling");
 		sysfs_remove_link(&pr->cdev->device.kobj, "device");
@@ -854,12 +800,6 @@ static int __init acpi_processor_init(vo
 
 	memset(&errata, 0, sizeof(errata));
 
-#ifdef CONFIG_ACPI_PROCFS
-	acpi_processor_dir = proc_mkdir(ACPI_PROCESSOR_CLASS, acpi_root_dir);
-	if (!acpi_processor_dir)
-		return -ENOMEM;
-#endif
-
 	if (!cpuidle_register_driver(&acpi_idle_driver)) {
 		printk(KERN_DEBUG "ACPI: %s registered with cpuidle\n",
 			acpi_idle_driver.name);
@@ -885,10 +825,6 @@ static int __init acpi_processor_init(vo
 out_cpuidle:
 	cpuidle_unregister_driver(&acpi_idle_driver);
 
-#ifdef CONFIG_ACPI_PROCFS
-	remove_proc_entry(ACPI_PROCESSOR_CLASS, acpi_root_dir);
-#endif
-
 	return result;
 }
 
@@ -907,10 +843,6 @@ static void __exit acpi_processor_exit(v
 
 	cpuidle_unregister_driver(&acpi_idle_driver);
 
-#ifdef CONFIG_ACPI_PROCFS
-	remove_proc_entry(ACPI_PROCESSOR_CLASS, acpi_root_dir);
-#endif
-
 	return;
 }
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/processor_idle.c linux-libre-2.6.38-gnu1/drivers/acpi/processor_idle.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/processor_idle.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/processor_idle.c	2011-03-14 21:20:32.000000000 -0400
@@ -79,6 +79,13 @@ module_param(bm_check_disable, uint, 000
 static unsigned int latency_factor __read_mostly = 2;
 module_param(latency_factor, uint, 0644);
 
+static int disabled_by_idle_boot_param(void)
+{
+	return boot_option_idle_override == IDLE_POLL ||
+		boot_option_idle_override == IDLE_FORCE_MWAIT ||
+		boot_option_idle_override == IDLE_HALT;
+}
+
 /*
  * IBM ThinkPad R40e crashes mysteriously when going into C2 or C3.
  * For now disable this. Probably a bug somewhere else.
@@ -455,7 +462,7 @@ static int acpi_processor_get_power_info
 				continue;
 			}
 			if (cx.type == ACPI_STATE_C1 &&
-					(idle_halt || idle_nomwait)) {
+			    (boot_option_idle_override == IDLE_NOMWAIT)) {
 				/*
 				 * In most cases the C1 space_id obtained from
 				 * _CST object is FIXED_HARDWARE access mode.
@@ -746,7 +753,7 @@ static int acpi_idle_enter_c1(struct cpu
 	struct acpi_processor *pr;
 	struct acpi_processor_cx *cx = cpuidle_get_statedata(state);
 
-	pr = __get_cpu_var(processors);
+	pr = __this_cpu_read(processors);
 
 	if (unlikely(!pr))
 		return 0;
@@ -787,7 +794,7 @@ static int acpi_idle_enter_simple(struct
 	s64 idle_time_ns;
 	s64 idle_time;
 
-	pr = __get_cpu_var(processors);
+	pr = __this_cpu_read(processors);
 
 	if (unlikely(!pr))
 		return 0;
@@ -864,7 +871,7 @@ static int acpi_idle_enter_bm(struct cpu
 	s64 idle_time;
 
 
-	pr = __get_cpu_var(processors);
+	pr = __this_cpu_read(processors);
 
 	if (unlikely(!pr))
 		return 0;
@@ -1016,7 +1023,6 @@ static int acpi_processor_setup_cpuidle(
 		state->flags = 0;
 		switch (cx->type) {
 			case ACPI_STATE_C1:
-			state->flags |= CPUIDLE_FLAG_SHALLOW;
 			if (cx->entry_method == ACPI_CSTATE_FFH)
 				state->flags |= CPUIDLE_FLAG_TIME_VALID;
 
@@ -1025,16 +1031,13 @@ static int acpi_processor_setup_cpuidle(
 			break;
 
 			case ACPI_STATE_C2:
-			state->flags |= CPUIDLE_FLAG_BALANCED;
 			state->flags |= CPUIDLE_FLAG_TIME_VALID;
 			state->enter = acpi_idle_enter_simple;
 			dev->safe_state = state;
 			break;
 
 			case ACPI_STATE_C3:
-			state->flags |= CPUIDLE_FLAG_DEEP;
 			state->flags |= CPUIDLE_FLAG_TIME_VALID;
-			state->flags |= CPUIDLE_FLAG_CHECK_BM;
 			state->enter = pr->flags.bm_check ?
 					acpi_idle_enter_bm :
 					acpi_idle_enter_simple;
@@ -1058,7 +1061,7 @@ int acpi_processor_cst_has_changed(struc
 {
 	int ret = 0;
 
-	if (boot_option_idle_override)
+	if (disabled_by_idle_boot_param())
 		return 0;
 
 	if (!pr)
@@ -1089,19 +1092,10 @@ int __cpuinit acpi_processor_power_init(
 	acpi_status status = 0;
 	static int first_run;
 
-	if (boot_option_idle_override)
+	if (disabled_by_idle_boot_param())
 		return 0;
 
 	if (!first_run) {
-		if (idle_halt) {
-			/*
-			 * When the boot option of "idle=halt" is added, halt
-			 * is used for CPU IDLE.
-			 * In such case C2/C3 is meaningless. So the max_cstate
-			 * is set to one.
-			 */
-			max_cstate = 1;
-		}
 		dmi_check_system(processor_power_dmi_table);
 		max_cstate = acpi_processor_cstate_check(max_cstate);
 		if (max_cstate < ACPI_C_STATES_MAX)
@@ -1142,7 +1136,7 @@ int __cpuinit acpi_processor_power_init(
 int acpi_processor_power_exit(struct acpi_processor *pr,
 			      struct acpi_device *device)
 {
-	if (boot_option_idle_override)
+	if (disabled_by_idle_boot_param())
 		return 0;
 
 	cpuidle_unregister_device(&pr->power.dev);
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/processor_throttling.c linux-libre-2.6.38-gnu1/drivers/acpi/processor_throttling.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/processor_throttling.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/processor_throttling.c	2011-03-14 21:20:32.000000000 -0400
@@ -32,10 +32,6 @@
 #include <linux/init.h>
 #include <linux/sched.h>
 #include <linux/cpufreq.h>
-#ifdef CONFIG_ACPI_PROCFS
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
-#endif
 
 #include <asm/io.h>
 #include <asm/uaccess.h>
@@ -370,6 +366,58 @@ int acpi_processor_tstate_has_changed(st
 }
 
 /*
+ * This function is used to reevaluate whether the T-state is valid
+ * after one CPU is onlined/offlined.
+ * It is noted that it won't reevaluate the following properties for
+ * the T-state.
+ *	1. Control method.
+ *	2. the number of supported T-state
+ *	3. TSD domain
+ */
+void acpi_processor_reevaluate_tstate(struct acpi_processor *pr,
+					unsigned long action)
+{
+	int result = 0;
+
+	if (action == CPU_DEAD) {
+		/* When one CPU is offline, the T-state throttling
+		 * will be invalidated.
+		 */
+		pr->flags.throttling = 0;
+		return;
+	}
+	/* the following is to recheck whether the T-state is valid for
+	 * the online CPU
+	 */
+	if (!pr->throttling.state_count) {
+		/* If the number of T-state is invalid, it is
+		 * invalidated.
+		 */
+		pr->flags.throttling = 0;
+		return;
+	}
+	pr->flags.throttling = 1;
+
+	/* Disable throttling (if enabled).  We'll let subsequent
+	 * policy (e.g.thermal) decide to lower performance if it
+	 * so chooses, but for now we'll crank up the speed.
+	 */
+
+	result = acpi_processor_get_throttling(pr);
+	if (result)
+		goto end;
+
+	if (pr->throttling.state) {
+		result = acpi_processor_set_throttling(pr, 0, false);
+		if (result)
+			goto end;
+	}
+
+end:
+	if (result)
+		pr->flags.throttling = 0;
+}
+/*
  * _PTC - Processor Throttling Control (and status) register location
  */
 static int acpi_processor_get_throttling_control(struct acpi_processor *pr)
@@ -876,7 +924,11 @@ static int acpi_processor_get_throttling
 	 */
 	cpumask_copy(saved_mask, &current->cpus_allowed);
 	/* FIXME: use work_on_cpu() */
-	set_cpus_allowed_ptr(current, cpumask_of(pr->id));
+	if (set_cpus_allowed_ptr(current, cpumask_of(pr->id))) {
+		/* Can't migrate to the target pr->id CPU. Exit */
+		free_cpumask_var(saved_mask);
+		return -ENODEV;
+	}
 	ret = pr->throttling.acpi_processor_get_throttling(pr);
 	/* restore the previous state */
 	set_cpus_allowed_ptr(current, saved_mask);
@@ -1051,6 +1103,14 @@ int acpi_processor_set_throttling(struct
 		return -ENOMEM;
 	}
 
+	if (cpu_is_offline(pr->id)) {
+		/*
+		 * the cpu pointed by pr->id is offline. Unnecessary to change
+		 * the throttling state any more.
+		 */
+		return -ENODEV;
+	}
+
 	cpumask_copy(saved_mask, &current->cpus_allowed);
 	t_state.target_state = state;
 	p_throttling = &(pr->throttling);
@@ -1074,7 +1134,11 @@ int acpi_processor_set_throttling(struct
 	 */
 	if (p_throttling->shared_type == DOMAIN_COORD_TYPE_SW_ANY) {
 		/* FIXME: use work_on_cpu() */
-		set_cpus_allowed_ptr(current, cpumask_of(pr->id));
+		if (set_cpus_allowed_ptr(current, cpumask_of(pr->id))) {
+			/* Can't migrate to the pr->id CPU. Exit */
+			ret = -ENODEV;
+			goto exit;
+		}
 		ret = p_throttling->acpi_processor_set_throttling(pr,
 						t_state.target_state, force);
 	} else {
@@ -1106,7 +1170,8 @@ int acpi_processor_set_throttling(struct
 			}
 			t_state.cpu = i;
 			/* FIXME: use work_on_cpu() */
-			set_cpus_allowed_ptr(current, cpumask_of(i));
+			if (set_cpus_allowed_ptr(current, cpumask_of(i)))
+				continue;
 			ret = match_pr->throttling.
 				acpi_processor_set_throttling(
 				match_pr, t_state.target_state, force);
@@ -1126,6 +1191,7 @@ int acpi_processor_set_throttling(struct
 	/* restore the previous state */
 	/* FIXME: use work_on_cpu() */
 	set_cpus_allowed_ptr(current, saved_mask);
+exit:
 	free_cpumask_var(online_throttling_cpus);
 	free_cpumask_var(saved_mask);
 	return ret;
@@ -1216,113 +1282,3 @@ int acpi_processor_get_throttling_info(s
 	return result;
 }
 
-#ifdef CONFIG_ACPI_PROCFS
-/* proc interface */
-static int acpi_processor_throttling_seq_show(struct seq_file *seq,
-					      void *offset)
-{
-	struct acpi_processor *pr = seq->private;
-	int i = 0;
-	int result = 0;
-
-	if (!pr)
-		goto end;
-
-	if (!(pr->throttling.state_count > 0)) {
-		seq_puts(seq, "<not supported>\n");
-		goto end;
-	}
-
-	result = acpi_processor_get_throttling(pr);
-
-	if (result) {
-		seq_puts(seq,
-			 "Could not determine current throttling state.\n");
-		goto end;
-	}
-
-	seq_printf(seq, "state count:             %d\n"
-		   "active state:            T%d\n"
-		   "state available: T%d to T%d\n",
-		   pr->throttling.state_count, pr->throttling.state,
-		   pr->throttling_platform_limit,
-		   pr->throttling.state_count - 1);
-
-	seq_puts(seq, "states:\n");
-	if (pr->throttling.acpi_processor_get_throttling ==
-			acpi_processor_get_throttling_fadt) {
-		for (i = 0; i < pr->throttling.state_count; i++)
-			seq_printf(seq, "   %cT%d:                  %02d%%\n",
-				   (i == pr->throttling.state ? '*' : ' '), i,
-				   (pr->throttling.states[i].performance ? pr->
-				    throttling.states[i].performance / 10 : 0));
-	} else {
-		for (i = 0; i < pr->throttling.state_count; i++)
-			seq_printf(seq, "   %cT%d:                  %02d%%\n",
-				   (i == pr->throttling.state ? '*' : ' '), i,
-				   (int)pr->throttling.states_tss[i].
-				   freqpercentage);
-	}
-
-      end:
-	return 0;
-}
-
-static int acpi_processor_throttling_open_fs(struct inode *inode,
-					     struct file *file)
-{
-	return single_open(file, acpi_processor_throttling_seq_show,
-			   PDE(inode)->data);
-}
-
-static ssize_t acpi_processor_write_throttling(struct file *file,
-					       const char __user * buffer,
-					       size_t count, loff_t * data)
-{
-	int result = 0;
-	struct seq_file *m = file->private_data;
-	struct acpi_processor *pr = m->private;
-	char state_string[5] = "";
-	char *charp = NULL;
-	size_t state_val = 0;
-	char tmpbuf[5] = "";
-
-	if (!pr || (count > sizeof(state_string) - 1))
-		return -EINVAL;
-
-	if (copy_from_user(state_string, buffer, count))
-		return -EFAULT;
-
-	state_string[count] = '\0';
-	if ((count > 0) && (state_string[count-1] == '\n'))
-		state_string[count-1] = '\0';
-
-	charp = state_string;
-	if ((state_string[0] == 't') || (state_string[0] == 'T'))
-		charp++;
-
-	state_val = simple_strtoul(charp, NULL, 0);
-	if (state_val >= pr->throttling.state_count)
-		return -EINVAL;
-
-	snprintf(tmpbuf, 5, "%zu", state_val);
-
-	if (strcmp(tmpbuf, charp) != 0)
-		return -EINVAL;
-
-	result = acpi_processor_set_throttling(pr, state_val, false);
-	if (result)
-		return result;
-
-	return count;
-}
-
-const struct file_operations acpi_processor_throttling_fops = {
-	.owner = THIS_MODULE,
-	.open = acpi_processor_throttling_open_fs,
-	.read = seq_read,
-	.write = acpi_processor_write_throttling,
-	.llseek = seq_lseek,
-	.release = single_release,
-};
-#endif
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/sbs.c linux-libre-2.6.38-gnu1/drivers/acpi/sbs.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/sbs.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/sbs.c	2011-03-14 21:20:32.000000000 -0400
@@ -484,6 +484,8 @@ acpi_sbs_add_fs(struct proc_dir_entry **
 		const struct file_operations *state_fops,
 		const struct file_operations *alarm_fops, void *data)
 {
+	printk(KERN_WARNING PREFIX "Deprecated procfs I/F for SBS is loaded,"
+			" please retry with CONFIG_ACPI_PROCFS_POWER cleared\n");
 	if (!*dir) {
 		*dir = proc_mkdir(dir_name, parent_dir);
 		if (!*dir) {
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/scan.c linux-libre-2.6.38-gnu1/drivers/acpi/scan.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/scan.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/scan.c	2011-03-14 21:20:32.000000000 -0400
@@ -778,7 +778,7 @@ acpi_bus_extract_wakeup_device_power_pac
 		wakeup->resources.handles[i] = element->reference.handle;
 	}
 
-	acpi_gpe_can_wake(wakeup->gpe_device, wakeup->gpe_number);
+	acpi_setup_gpe_for_wake(handle, wakeup->gpe_device, wakeup->gpe_number);
 
  out:
 	kfree(buffer.pointer);
@@ -803,7 +803,7 @@ static void acpi_bus_set_run_wake_flags(
 	/* Power button, Lid switch always enable wakeup */
 	if (!acpi_match_device_ids(device, button_device_ids)) {
 		device->wakeup.flags.run_wake = 1;
-		device->wakeup.flags.always_enabled = 1;
+		device_set_wakeup_capable(&device->dev, true);
 		return;
 	}
 
@@ -815,16 +815,22 @@ static void acpi_bus_set_run_wake_flags(
 				!!(event_status & ACPI_EVENT_FLAG_HANDLE);
 }
 
-static int acpi_bus_get_wakeup_device_flags(struct acpi_device *device)
+static void acpi_bus_get_wakeup_device_flags(struct acpi_device *device)
 {
+	acpi_handle temp;
 	acpi_status status = 0;
 	int psw_error;
 
+	/* Presence of _PRW indicates wake capable */
+	status = acpi_get_handle(device->handle, "_PRW", &temp);
+	if (ACPI_FAILURE(status))
+		return;
+
 	status = acpi_bus_extract_wakeup_device_power_package(device->handle,
 							      &device->wakeup);
 	if (ACPI_FAILURE(status)) {
 		ACPI_EXCEPTION((AE_INFO, status, "Extracting _PRW package"));
-		goto end;
+		return;
 	}
 
 	device->wakeup.flags.valid = 1;
@@ -840,13 +846,10 @@ static int acpi_bus_get_wakeup_device_fl
 	if (psw_error)
 		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
 				"error in _DSW or _PSW evaluation\n"));
-
-end:
-	if (ACPI_FAILURE(status))
-		device->flags.wake_capable = 0;
-	return 0;
 }
 
+static void acpi_bus_add_power_resource(acpi_handle handle);
+
 static int acpi_bus_get_power_flags(struct acpi_device *device)
 {
 	acpi_status status = 0;
@@ -875,8 +878,12 @@ static int acpi_bus_get_power_flags(stru
 		acpi_evaluate_reference(device->handle, object_name, NULL,
 					&ps->resources);
 		if (ps->resources.count) {
+			int j;
+
 			device->power.flags.power_resources = 1;
 			ps->flags.valid = 1;
+			for (j = 0; j < ps->resources.count; j++)
+				acpi_bus_add_power_resource(ps->resources.handles[j]);
 		}
 
 		/* Evaluate "_PSx" to see if we can do explicit sets */
@@ -901,10 +908,7 @@ static int acpi_bus_get_power_flags(stru
 	device->power.states[ACPI_STATE_D3].flags.valid = 1;
 	device->power.states[ACPI_STATE_D3].power = 0;
 
-	/* TBD: System wake support and resource requirements. */
-
-	device->power.state = ACPI_STATE_UNKNOWN;
-	acpi_bus_get_power(device->handle, &(device->power.state));
+	acpi_bus_init_power(device);
 
 	return 0;
 }
@@ -947,11 +951,6 @@ static int acpi_bus_get_flags(struct acp
 	if (ACPI_SUCCESS(status))
 		device->flags.power_manageable = 1;
 
-	/* Presence of _PRW indicates wake capable */
-	status = acpi_get_handle(device->handle, "_PRW", &temp);
-	if (ACPI_SUCCESS(status))
-		device->flags.wake_capable = 1;
-
 	/* TBD: Performance management */
 
 	return 0;
@@ -1278,11 +1277,7 @@ static int acpi_add_single_object(struct
 	 * Wakeup device management
 	 *-----------------------
 	 */
-	if (device->flags.wake_capable) {
-		result = acpi_bus_get_wakeup_device_flags(device);
-		if (result)
-			goto end;
-	}
+	acpi_bus_get_wakeup_device_flags(device);
 
 	/*
 	 * Performance Management
@@ -1326,6 +1321,20 @@ end:
 #define ACPI_STA_DEFAULT (ACPI_STA_DEVICE_PRESENT | ACPI_STA_DEVICE_ENABLED | \
 			  ACPI_STA_DEVICE_UI      | ACPI_STA_DEVICE_FUNCTIONING)
 
+static void acpi_bus_add_power_resource(acpi_handle handle)
+{
+	struct acpi_bus_ops ops = {
+		.acpi_op_add = 1,
+		.acpi_op_start = 1,
+	};
+	struct acpi_device *device = NULL;
+
+	acpi_bus_get_device(handle, &device);
+	if (!device)
+		acpi_add_single_object(&device, handle, ACPI_BUS_TYPE_POWER,
+					ACPI_STA_DEFAULT, &ops);
+}
+
 static int acpi_bus_type_and_status(acpi_handle handle, int *type,
 				    unsigned long long *sta)
 {
@@ -1371,7 +1380,6 @@ static acpi_status acpi_bus_check_add(ac
 	struct acpi_bus_ops *ops = context;
 	int type;
 	unsigned long long sta;
-	struct acpi_device_wakeup wakeup;
 	struct acpi_device *device;
 	acpi_status status;
 	int result;
@@ -1382,7 +1390,13 @@ static acpi_status acpi_bus_check_add(ac
 
 	if (!(sta & ACPI_STA_DEVICE_PRESENT) &&
 	    !(sta & ACPI_STA_DEVICE_FUNCTIONING)) {
-		acpi_bus_extract_wakeup_device_power_package(handle, &wakeup);
+		struct acpi_device_wakeup wakeup;
+		acpi_handle temp;
+
+		status = acpi_get_handle(handle, "_PRW", &temp);
+		if (ACPI_SUCCESS(status))
+			acpi_bus_extract_wakeup_device_power_package(handle,
+								     &wakeup);
 		return AE_CTRL_DEPTH;
 	}
 
@@ -1467,7 +1481,7 @@ int acpi_bus_start(struct acpi_device *d
 
 	result = acpi_bus_scan(device->handle, &ops, NULL);
 
-	acpi_update_gpes();
+	acpi_update_all_gpes();
 
 	return result;
 }
@@ -1573,6 +1587,8 @@ int __init acpi_scan_init(void)
 		printk(KERN_ERR PREFIX "Could not register bus type\n");
 	}
 
+	acpi_power_init();
+
 	/*
 	 * Enumerate devices in the ACPI namespace.
 	 */
@@ -1584,7 +1600,7 @@ int __init acpi_scan_init(void)
 	if (result)
 		acpi_device_unregister(acpi_root, ACPI_BUS_REMOVAL_NORMAL);
 	else
-		acpi_update_gpes();
+		acpi_update_all_gpes();
 
 	return result;
 }
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/sleep.c linux-libre-2.6.38-gnu1/drivers/acpi/sleep.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/sleep.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/sleep.c	2011-03-14 21:20:32.000000000 -0400
@@ -124,8 +124,7 @@ static int acpi_pm_freeze(void)
 static int acpi_pm_pre_suspend(void)
 {
 	acpi_pm_freeze();
-	suspend_nvs_save();
-	return 0;
+	return suspend_nvs_save();
 }
 
 /**
@@ -151,7 +150,7 @@ static int acpi_pm_prepare(void)
 {
 	int error = __acpi_pm_prepare();
 	if (!error)
-		acpi_pm_pre_suspend();
+		error = acpi_pm_pre_suspend();
 
 	return error;
 }
@@ -167,6 +166,7 @@ static void acpi_pm_finish(void)
 	u32 acpi_state = acpi_target_sleep_state;
 
 	acpi_ec_unblock_transactions();
+	suspend_nvs_free();
 
 	if (acpi_state == ACPI_STATE_S0)
 		return;
@@ -187,7 +187,6 @@ static void acpi_pm_finish(void)
  */
 static void acpi_pm_end(void)
 {
-	suspend_nvs_free();
 	/*
 	 * This is necessary in case acpi_pm_finish() is not called during a
 	 * failing transition to a sleep state.
@@ -319,7 +318,7 @@ static int acpi_suspend_state_valid(susp
 	}
 }
 
-static struct platform_suspend_ops acpi_suspend_ops = {
+static const struct platform_suspend_ops acpi_suspend_ops = {
 	.valid = acpi_suspend_state_valid,
 	.begin = acpi_suspend_begin,
 	.prepare_late = acpi_pm_prepare,
@@ -347,7 +346,7 @@ static int acpi_suspend_begin_old(suspen
  * The following callbacks are used if the pre-ACPI 2.0 suspend ordering has
  * been requested.
  */
-static struct platform_suspend_ops acpi_suspend_ops_old = {
+static const struct platform_suspend_ops acpi_suspend_ops_old = {
 	.valid = acpi_suspend_state_valid,
 	.begin = acpi_suspend_begin_old,
 	.prepare_late = acpi_pm_pre_suspend,
@@ -435,6 +434,14 @@ static struct dmi_system_id __initdata a
 		DMI_MATCH(DMI_PRODUCT_NAME, "VGN-NW130D"),
 		},
 	},
+	{
+	.callback = init_nvs_nosave,
+	.ident = "Averatec AV1020-ED2",
+	.matches = {
+		DMI_MATCH(DMI_SYS_VENDOR, "AVERATEC"),
+		DMI_MATCH(DMI_PRODUCT_NAME, "1000 Series"),
+		},
+	},
 	{},
 };
 #endif /* CONFIG_SUSPEND */
@@ -506,7 +513,7 @@ static void acpi_pm_thaw(void)
 	acpi_enable_all_runtime_gpes();
 }
 
-static struct platform_hibernation_ops acpi_hibernation_ops = {
+static const struct platform_hibernation_ops acpi_hibernation_ops = {
 	.begin = acpi_hibernation_begin,
 	.end = acpi_pm_end,
 	.pre_snapshot = acpi_pm_prepare,
@@ -549,7 +556,7 @@ static int acpi_hibernation_begin_old(vo
  * The following callbacks are used if the pre-ACPI 2.0 suspend ordering has
  * been requested.
  */
-static struct platform_hibernation_ops acpi_hibernation_ops_old = {
+static const struct platform_hibernation_ops acpi_hibernation_ops_old = {
 	.begin = acpi_hibernation_begin_old,
 	.end = acpi_pm_end,
 	.pre_snapshot = acpi_pm_pre_suspend,
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/sysfs.c linux-libre-2.6.38-gnu1/drivers/acpi/sysfs.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/sysfs.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/sysfs.c	2011-03-14 21:20:32.000000000 -0400
@@ -438,7 +438,7 @@ static void delete_gpe_attr_array(void)
 	return;
 }
 
-void acpi_os_gpe_count(u32 gpe_number)
+static void gpe_count(u32 gpe_number)
 {
 	acpi_gpe_count++;
 
@@ -454,7 +454,7 @@ void acpi_os_gpe_count(u32 gpe_number)
 	return;
 }
 
-void acpi_os_fixed_event_count(u32 event_number)
+static void fixed_event_count(u32 event_number)
 {
 	if (!all_counters)
 		return;
@@ -468,6 +468,16 @@ void acpi_os_fixed_event_count(u32 event
 	return;
 }
 
+static void acpi_gbl_event_handler(u32 event_type, acpi_handle device,
+	u32 event_number, void *context)
+{
+	if (event_type == ACPI_EVENT_TYPE_GPE)
+		gpe_count(event_number);
+
+	if (event_type == ACPI_EVENT_TYPE_FIXED)
+		fixed_event_count(event_number);
+}
+
 static int get_status(u32 index, acpi_event_status *status,
 		      acpi_handle *handle)
 {
@@ -601,6 +611,7 @@ end:
 
 void acpi_irq_stats_init(void)
 {
+	acpi_status status;
 	int i;
 
 	if (all_counters)
@@ -619,6 +630,10 @@ void acpi_irq_stats_init(void)
 	if (all_counters == NULL)
 		goto fail;
 
+	status = acpi_install_global_event_handler(acpi_gbl_event_handler, NULL);
+	if (ACPI_FAILURE(status))
+		goto fail;
+
 	counter_attrs = kzalloc(sizeof(struct kobj_attribute) * (num_counters),
 				GFP_KERNEL);
 	if (counter_attrs == NULL)
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/thermal.c linux-libre-2.6.38-gnu1/drivers/acpi/thermal.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/thermal.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/thermal.c	2011-03-14 21:20:32.000000000 -0400
@@ -1059,8 +1059,9 @@ static int acpi_thermal_resume(struct ac
 			break;
 		tz->trips.active[i].flags.enabled = 1;
 		for (j = 0; j < tz->trips.active[i].devices.count; j++) {
-			result = acpi_bus_get_power(tz->trips.active[i].devices.
-			    handles[j], &power_state);
+			result = acpi_bus_update_power(
+					tz->trips.active[i].devices.handles[j],
+					&power_state);
 			if (result || (power_state != ACPI_STATE_D0)) {
 				tz->trips.active[i].flags.enabled = 0;
 				break;
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/video.c linux-libre-2.6.38-gnu1/drivers/acpi/video.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/video.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/video.c	2011-03-14 21:20:32.000000000 -0400
@@ -33,7 +33,6 @@
 #include <linux/input.h>
 #include <linux/backlight.h>
 #include <linux/thermal.h>
-#include <linux/video_output.h>
 #include <linux/sort.h>
 #include <linux/pci.h>
 #include <linux/pci_ids.h>
@@ -81,6 +80,13 @@ module_param(brightness_switch_enabled,
 static int allow_duplicates;
 module_param(allow_duplicates, bool, 0644);
 
+/*
+ * Some BIOSes claim they use minimum backlight at boot,
+ * and this may bring dimming screen after boot
+ */
+static int use_bios_initial_backlight = 1;
+module_param(use_bios_initial_backlight, bool, 0644);
+
 static int register_count = 0;
 static int acpi_video_bus_add(struct acpi_device *device);
 static int acpi_video_bus_remove(struct acpi_device *device, int type);
@@ -172,9 +178,6 @@ struct acpi_video_device_cap {
 	u8 _BQC:1;		/* Get current brightness level */
 	u8 _BCQ:1;		/* Some buggy BIOS uses _BCQ instead of _BQC */
 	u8 _DDC:1;		/*Return the EDID for this device */
-	u8 _DCS:1;		/*Return status of output device */
-	u8 _DGS:1;		/*Query graphics state */
-	u8 _DSS:1;		/*Device state set */
 };
 
 struct acpi_video_brightness_flags {
@@ -202,7 +205,6 @@ struct acpi_video_device {
 	struct acpi_video_device_brightness *brightness;
 	struct backlight_device *backlight;
 	struct thermal_cooling_device *cooling_dev;
-	struct output_device *output_dev;
 };
 
 static const char device_decode[][30] = {
@@ -226,10 +228,6 @@ static int acpi_video_get_next_level(str
 				     u32 level_current, u32 event);
 static int acpi_video_switch_brightness(struct acpi_video_device *device,
 					 int event);
-static int acpi_video_device_get_state(struct acpi_video_device *device,
-			    unsigned long long *state);
-static int acpi_video_output_get(struct output_device *od);
-static int acpi_video_device_set_state(struct acpi_video_device *device, int state);
 
 /*backlight device sysfs support*/
 static int acpi_video_get_brightness(struct backlight_device *bd)
@@ -260,35 +258,11 @@ static int acpi_video_set_brightness(str
 				vd->brightness->levels[request_level]);
 }
 
-static struct backlight_ops acpi_backlight_ops = {
+static const struct backlight_ops acpi_backlight_ops = {
 	.get_brightness = acpi_video_get_brightness,
 	.update_status  = acpi_video_set_brightness,
 };
 
-/*video output device sysfs support*/
-static int acpi_video_output_get(struct output_device *od)
-{
-	unsigned long long state;
-	struct acpi_video_device *vd =
-		(struct acpi_video_device *)dev_get_drvdata(&od->dev);
-	acpi_video_device_get_state(vd, &state);
-	return (int)state;
-}
-
-static int acpi_video_output_set(struct output_device *od)
-{
-	unsigned long state = od->request_state;
-	struct acpi_video_device *vd=
-		(struct acpi_video_device *)dev_get_drvdata(&od->dev);
-	return acpi_video_device_set_state(vd, state);
-}
-
-static struct output_properties acpi_output_properties = {
-	.set_state = acpi_video_output_set,
-	.get_status = acpi_video_output_get,
-};
-
-
 /* thermal cooling device callbacks */
 static int video_get_max_state(struct thermal_cooling_device *cooling_dev, unsigned
 			       long *state)
@@ -344,34 +318,6 @@ static struct thermal_cooling_device_ops
                                Video Management
    -------------------------------------------------------------------------- */
 
-/* device */
-
-static int
-acpi_video_device_get_state(struct acpi_video_device *device,
-			    unsigned long long *state)
-{
-	int status;
-
-	status = acpi_evaluate_integer(device->dev->handle, "_DCS", NULL, state);
-
-	return status;
-}
-
-static int
-acpi_video_device_set_state(struct acpi_video_device *device, int state)
-{
-	int status;
-	union acpi_object arg0 = { ACPI_TYPE_INTEGER };
-	struct acpi_object_list args = { 1, &arg0 };
-	unsigned long long ret;
-
-
-	arg0.integer.value = state;
-	status = acpi_evaluate_integer(device->dev->handle, "_DSS", &args, &ret);
-
-	return status;
-}
-
 static int
 acpi_video_device_lcd_query_levels(struct acpi_video_device *device,
 				   union acpi_object **levels)
@@ -766,9 +712,11 @@ acpi_video_init_brightness(struct acpi_v
 		 * when invoked for the first time, i.e. level_old is invalid.
 		 * set the backlight to max_level in this case
 		 */
-		for (i = 2; i < br->count; i++)
-			if (level_old == br->levels[i])
-				level = level_old;
+		if (use_bios_initial_backlight) {
+			for (i = 2; i < br->count; i++)
+				if (level_old == br->levels[i])
+					level = level_old;
+		}
 		goto set_level;
 	}
 
@@ -831,15 +779,6 @@ static void acpi_video_device_find_cap(s
 	if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle, "_DDC", &h_dummy1))) {
 		device->cap._DDC = 1;
 	}
-	if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle, "_DCS", &h_dummy1))) {
-		device->cap._DCS = 1;
-	}
-	if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle, "_DGS", &h_dummy1))) {
-		device->cap._DGS = 1;
-	}
-	if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle, "_DSS", &h_dummy1))) {
-		device->cap._DSS = 1;
-	}
 
 	if (acpi_video_backlight_support()) {
 		struct backlight_properties props;
@@ -904,21 +843,6 @@ static void acpi_video_device_find_cap(s
 			printk(KERN_ERR PREFIX "Create sysfs link\n");
 
 	}
-
-	if (acpi_video_display_switch_support()) {
-
-		if (device->cap._DCS && device->cap._DSS) {
-			static int count;
-			char *name;
-			name = kasprintf(GFP_KERNEL, "acpi_video%d", count);
-			if (!name)
-				return;
-			count++;
-			device->output_dev = video_output_register(name,
-					NULL, device, &acpi_output_properties);
-			kfree(name);
-		}
-	}
 }
 
 /*
@@ -1360,6 +1284,9 @@ int acpi_video_get_edid(struct acpi_devi
 		if (!video_device)
 			continue;
 
+		if (!video_device->cap._DDC)
+			continue;
+
 		if (type) {
 			switch (type) {
 			case ACPI_VIDEO_DISPLAY_CRT:
@@ -1452,7 +1379,6 @@ static int acpi_video_bus_put_one_device
 		thermal_cooling_device_unregister(device->cooling_dev);
 		device->cooling_dev = NULL;
 	}
-	video_output_unregister(device->output_dev);
 
 	return 0;
 }
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/video_detect.c linux-libre-2.6.38-gnu1/drivers/acpi/video_detect.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/video_detect.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/video_detect.c	2011-03-14 21:20:32.000000000 -0400
@@ -17,15 +17,14 @@
  * capabilities the graphics cards plugged in support. The check for general
  * video capabilities will be triggered by the first caller of
  * acpi_video_get_capabilities(NULL); which will happen when the first
- * backlight (or display output) switching supporting driver calls:
+ * backlight switching supporting driver calls:
  * acpi_video_backlight_support();
  *
  * Depending on whether ACPI graphics extensions (cmp. ACPI spec Appendix B)
  * are available, video.ko should be used to handle the device.
  *
  * Otherwise vendor specific drivers like thinkpad_acpi, asus_acpi,
- * sony_acpi,... can take care about backlight brightness and display output
- * switching.
+ * sony_acpi,... can take care about backlight brightness.
  *
  * If CONFIG_ACPI_VIDEO is neither set as "compiled in" (y) nor as a module (m)
  * this file will not be compiled, acpi_video_get_capabilities() and
@@ -161,8 +160,6 @@ long acpi_video_get_capabilities(acpi_ha
 		 *
 		 *   if (dmi_name_in_vendors("XY")) {
 		 *	acpi_video_support |=
-		 *		ACPI_VIDEO_OUTPUT_SWITCHING_DMI_VENDOR;
-		 *	acpi_video_support |=
 		 *		ACPI_VIDEO_BACKLIGHT_DMI_VENDOR;
 		 *}
 		 */
@@ -212,33 +209,8 @@ int acpi_video_backlight_support(void)
 EXPORT_SYMBOL(acpi_video_backlight_support);
 
 /*
- * Returns true if video.ko can do display output switching.
- * This does not work well/at all with binary graphics drivers
- * which disable system io ranges and do it on their own.
- */
-int acpi_video_display_switch_support(void)
-{
-	if (!acpi_video_caps_checked)
-		acpi_video_get_capabilities(NULL);
-
-	if (acpi_video_support & ACPI_VIDEO_OUTPUT_SWITCHING_FORCE_VENDOR)
-		return 0;
-	else if (acpi_video_support & ACPI_VIDEO_OUTPUT_SWITCHING_FORCE_VIDEO)
-		return 1;
-
-	if (acpi_video_support & ACPI_VIDEO_OUTPUT_SWITCHING_DMI_VENDOR)
-		return 0;
-	else if (acpi_video_support & ACPI_VIDEO_OUTPUT_SWITCHING_DMI_VIDEO)
-		return 1;
-
-	return acpi_video_support & ACPI_VIDEO_OUTPUT_SWITCHING;
-}
-EXPORT_SYMBOL(acpi_video_display_switch_support);
-
-/*
- * Use acpi_display_output=vendor/video or acpi_backlight=vendor/video
- * To force that backlight or display output switching is processed by vendor
- * specific acpi drivers or video.ko driver.
+ * Use acpi_backlight=vendor/video to force that backlight switching
+ * is processed by vendor specific acpi drivers or video.ko driver.
  */
 static int __init acpi_backlight(char *str)
 {
@@ -255,19 +227,3 @@ static int __init acpi_backlight(char *s
 	return 1;
 }
 __setup("acpi_backlight=", acpi_backlight);
-
-static int __init acpi_display_output(char *str)
-{
-	if (str == NULL || *str == '\0')
-		return 1;
-	else {
-		if (!strcmp("vendor", str))
-			acpi_video_support |=
-				ACPI_VIDEO_OUTPUT_SWITCHING_FORCE_VENDOR;
-		if (!strcmp("video", str))
-			acpi_video_support |=
-				ACPI_VIDEO_OUTPUT_SWITCHING_FORCE_VIDEO;
-	}
-	return 1;
-}
-__setup("acpi_display_output=", acpi_display_output);
diff -druNp linux-libre-2.6.37-gnu1/drivers/acpi/wakeup.c linux-libre-2.6.38-gnu1/drivers/acpi/wakeup.c
--- linux-libre-2.6.37-gnu1/drivers/acpi/wakeup.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/acpi/wakeup.c	2011-03-14 21:20:32.000000000 -0400
@@ -37,15 +37,16 @@ void acpi_enable_wakeup_devices(u8 sleep
 			container_of(node, struct acpi_device, wakeup_list);
 
 		if (!dev->wakeup.flags.valid
-		    || !(dev->wakeup.state.enabled || dev->wakeup.prepare_count)
-		    || sleep_state > (u32) dev->wakeup.sleep_state)
+		    || sleep_state > (u32) dev->wakeup.sleep_state
+		    || !(device_may_wakeup(&dev->dev)
+		        || dev->wakeup.prepare_count))
 			continue;
 
-		if (dev->wakeup.state.enabled)
+		if (device_may_wakeup(&dev->dev))
 			acpi_enable_wakeup_device_power(dev, sleep_state);
 
 		/* The wake-up power should have been enabled already. */
-		acpi_gpe_wakeup(dev->wakeup.gpe_device, dev->wakeup.gpe_number,
+		acpi_set_gpe_wake_mask(dev->wakeup.gpe_device, dev->wakeup.gpe_number,
 				ACPI_GPE_ENABLE);
 	}
 }
@@ -63,14 +64,15 @@ void acpi_disable_wakeup_devices(u8 slee
 			container_of(node, struct acpi_device, wakeup_list);
 
 		if (!dev->wakeup.flags.valid
-		    || !(dev->wakeup.state.enabled || dev->wakeup.prepare_count)
-		    || (sleep_state > (u32) dev->wakeup.sleep_state))
+		    || sleep_state > (u32) dev->wakeup.sleep_state
+		    || !(device_may_wakeup(&dev->dev)
+		        || dev->wakeup.prepare_count))
 			continue;
 
-		acpi_gpe_wakeup(dev->wakeup.gpe_device, dev->wakeup.gpe_number,
+		acpi_set_gpe_wake_mask(dev->wakeup.gpe_device, dev->wakeup.gpe_number,
 				ACPI_GPE_DISABLE);
 
-		if (dev->wakeup.state.enabled)
+		if (device_may_wakeup(&dev->dev))
 			acpi_disable_wakeup_device_power(dev);
 	}
 }
@@ -84,8 +86,12 @@ int __init acpi_wakeup_device_init(void)
 		struct acpi_device *dev = container_of(node,
 						       struct acpi_device,
 						       wakeup_list);
-		if (dev->wakeup.flags.always_enabled)
-			dev->wakeup.state.enabled = 1;
+		if (device_can_wakeup(&dev->dev)) {
+			/* Button GPEs are supposed to be always enabled. */
+			acpi_enable_gpe(dev->wakeup.gpe_device,
+					dev->wakeup.gpe_number);
+			device_set_wakeup_enable(&dev->dev, true);
+		}
 	}
 	mutex_unlock(&acpi_device_lock);
 	return 0;
diff -druNp linux-libre-2.6.37-gnu1/drivers/amba/bus.c linux-libre-2.6.38-gnu1/drivers/amba/bus.c
--- linux-libre-2.6.37-gnu1/drivers/amba/bus.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/amba/bus.c	2011-03-14 21:20:32.000000000 -0400
@@ -147,6 +147,39 @@ static void amba_put_disable_pclk(struct
 	clk_put(pclk);
 }
 
+static int amba_get_enable_vcore(struct amba_device *pcdev)
+{
+	struct regulator *vcore = regulator_get(&pcdev->dev, "vcore");
+	int ret;
+
+	pcdev->vcore = vcore;
+
+	if (IS_ERR(vcore)) {
+		/* It is OK not to supply a vcore regulator */
+		if (PTR_ERR(vcore) == -ENODEV)
+			return 0;
+		return PTR_ERR(vcore);
+	}
+
+	ret = regulator_enable(vcore);
+	if (ret) {
+		regulator_put(vcore);
+		pcdev->vcore = ERR_PTR(-ENODEV);
+	}
+
+	return ret;
+}
+
+static void amba_put_disable_vcore(struct amba_device *pcdev)
+{
+	struct regulator *vcore = pcdev->vcore;
+
+	if (!IS_ERR(vcore)) {
+		regulator_disable(vcore);
+		regulator_put(vcore);
+	}
+}
+
 /*
  * These are the device model conversion veneers; they convert the
  * device model structures to our more specific structures.
@@ -159,6 +192,10 @@ static int amba_probe(struct device *dev
 	int ret;
 
 	do {
+		ret = amba_get_enable_vcore(pcdev);
+		if (ret)
+			break;
+
 		ret = amba_get_enable_pclk(pcdev);
 		if (ret)
 			break;
@@ -168,6 +205,7 @@ static int amba_probe(struct device *dev
 			break;
 
 		amba_put_disable_pclk(pcdev);
+		amba_put_disable_vcore(pcdev);
 	} while (0);
 
 	return ret;
@@ -180,6 +218,7 @@ static int amba_remove(struct device *de
 	int ret = drv->remove(pcdev);
 
 	amba_put_disable_pclk(pcdev);
+	amba_put_disable_vcore(pcdev);
 
 	return ret;
 }
diff -druNp linux-libre-2.6.37-gnu1/drivers/ata/acard-ahci.c linux-libre-2.6.38-gnu1/drivers/ata/acard-ahci.c
--- linux-libre-2.6.37-gnu1/drivers/ata/acard-ahci.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/ata/acard-ahci.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,528 @@
+
+/*
+ *  acard-ahci.c - ACard AHCI SATA support
+ *
+ *  Maintained by:  Jeff Garzik <jgarzik@pobox.com>
+ *		    Please ALWAYS copy linux-ide@vger.kernel.org
+ *		    on emails.
+ *
+ *  Copyright 2010 Red Hat, 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, 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; see the file COPYING.  If not, write to
+ *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ * libata documentation is available via 'make {ps|pdf}docs',
+ * as Documentation/DocBook/libata.*
+ *
+ * AHCI hardware documentation:
+ * http://www.intel.com/technology/serialata/pdf/rev1_0.pdf
+ * http://www.intel.com/technology/serialata/pdf/rev1_1.pdf
+ *
+ */
+
+#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 <linux/interrupt.h>
+#include <linux/dma-mapping.h>
+#include <linux/device.h>
+#include <linux/dmi.h>
+#include <linux/gfp.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_cmnd.h>
+#include <linux/libata.h>
+#include "ahci.h"
+
+#define DRV_NAME	"acard-ahci"
+#define DRV_VERSION	"1.0"
+
+/*
+  Received FIS structure limited to 80h.
+*/
+
+#define ACARD_AHCI_RX_FIS_SZ 128
+
+enum {
+	AHCI_PCI_BAR		= 5,
+};
+
+enum board_ids {
+	board_acard_ahci,
+};
+
+struct acard_sg {
+	__le32			addr;
+	__le32			addr_hi;
+	__le32			reserved;
+	__le32			size;	 /* bit 31 (EOT) max==0x10000 (64k) */
+};
+
+static void acard_ahci_qc_prep(struct ata_queued_cmd *qc);
+static bool acard_ahci_qc_fill_rtf(struct ata_queued_cmd *qc);
+static int acard_ahci_port_start(struct ata_port *ap);
+static int acard_ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
+
+#ifdef CONFIG_PM
+static int acard_ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg);
+static int acard_ahci_pci_device_resume(struct pci_dev *pdev);
+#endif
+
+static struct scsi_host_template acard_ahci_sht = {
+	AHCI_SHT("acard-ahci"),
+};
+
+static struct ata_port_operations acard_ops = {
+	.inherits		= &ahci_ops,
+	.qc_prep		= acard_ahci_qc_prep,
+	.qc_fill_rtf		= acard_ahci_qc_fill_rtf,
+	.port_start             = acard_ahci_port_start,
+};
+
+#define AHCI_HFLAGS(flags)	.private_data	= (void *)(flags)
+
+static const struct ata_port_info acard_ahci_port_info[] = {
+	[board_acard_ahci] =
+	{
+		AHCI_HFLAGS	(AHCI_HFLAG_NO_NCQ),
+		.flags		= AHCI_FLAG_COMMON,
+		.pio_mask	= ATA_PIO4,
+		.udma_mask	= ATA_UDMA6,
+		.port_ops	= &acard_ops,
+	},
+};
+
+static const struct pci_device_id acard_ahci_pci_tbl[] = {
+	/* ACard */
+	{ PCI_VDEVICE(ARTOP, 0x000d), board_acard_ahci }, /* ATP8620 */
+
+	{ }    /* terminate list */
+};
+
+static struct pci_driver acard_ahci_pci_driver = {
+	.name			= DRV_NAME,
+	.id_table		= acard_ahci_pci_tbl,
+	.probe			= acard_ahci_init_one,
+	.remove			= ata_pci_remove_one,
+#ifdef CONFIG_PM
+	.suspend		= acard_ahci_pci_device_suspend,
+	.resume			= acard_ahci_pci_device_resume,
+#endif
+};
+
+#ifdef CONFIG_PM
+static int acard_ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg)
+{
+	struct ata_host *host = dev_get_drvdata(&pdev->dev);
+	struct ahci_host_priv *hpriv = host->private_data;
+	void __iomem *mmio = hpriv->mmio;
+	u32 ctl;
+
+	if (mesg.event & PM_EVENT_SUSPEND &&
+	    hpriv->flags & AHCI_HFLAG_NO_SUSPEND) {
+		dev_printk(KERN_ERR, &pdev->dev,
+			   "BIOS update required for suspend/resume\n");
+		return -EIO;
+	}
+
+	if (mesg.event & PM_EVENT_SLEEP) {
+		/* AHCI spec rev1.1 section 8.3.3:
+		 * Software must disable interrupts prior to requesting a
+		 * transition of the HBA to D3 state.
+		 */
+		ctl = readl(mmio + HOST_CTL);
+		ctl &= ~HOST_IRQ_EN;
+		writel(ctl, mmio + HOST_CTL);
+		readl(mmio + HOST_CTL); /* flush */
+	}
+
+	return ata_pci_device_suspend(pdev, mesg);
+}
+
+static int acard_ahci_pci_device_resume(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;
+
+	if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) {
+		rc = ahci_reset_controller(host);
+		if (rc)
+			return rc;
+
+		ahci_init_controller(host);
+	}
+
+	ata_host_resume(host);
+
+	return 0;
+}
+#endif
+
+static int acard_ahci_configure_dma_masks(struct pci_dev *pdev, int using_dac)
+{
+	int rc;
+
+	if (using_dac &&
+	    !pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) {
+		rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));
+		if (rc) {
+			rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
+			if (rc) {
+				dev_printk(KERN_ERR, &pdev->dev,
+					   "64-bit DMA enable failed\n");
+				return rc;
+			}
+		}
+	} else {
+		rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
+		if (rc) {
+			dev_printk(KERN_ERR, &pdev->dev,
+				   "32-bit DMA enable failed\n");
+			return rc;
+		}
+		rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
+		if (rc) {
+			dev_printk(KERN_ERR, &pdev->dev,
+				   "32-bit consistent DMA enable failed\n");
+			return rc;
+		}
+	}
+	return 0;
+}
+
+static void acard_ahci_pci_print_info(struct ata_host *host)
+{
+	struct pci_dev *pdev = to_pci_dev(host->dev);
+	u16 cc;
+	const char *scc_s;
+
+	pci_read_config_word(pdev, 0x0a, &cc);
+	if (cc == PCI_CLASS_STORAGE_IDE)
+		scc_s = "IDE";
+	else if (cc == PCI_CLASS_STORAGE_SATA)
+		scc_s = "SATA";
+	else if (cc == PCI_CLASS_STORAGE_RAID)
+		scc_s = "RAID";
+	else
+		scc_s = "unknown";
+
+	ahci_print_info(host, scc_s);
+}
+
+static unsigned int acard_ahci_fill_sg(struct ata_queued_cmd *qc, void *cmd_tbl)
+{
+	struct scatterlist *sg;
+	struct acard_sg *acard_sg = cmd_tbl + AHCI_CMD_TBL_HDR_SZ;
+	unsigned int si, last_si = 0;
+
+	VPRINTK("ENTER\n");
+
+	/*
+	 * Next, the S/G list.
+	 */
+	for_each_sg(qc->sg, sg, qc->n_elem, si) {
+		dma_addr_t addr = sg_dma_address(sg);
+		u32 sg_len = sg_dma_len(sg);
+
+		/*
+		 * ACard note:
+		 * We must set an end-of-table (EOT) bit,
+		 * and the segment cannot exceed 64k (0x10000)
+		 */
+		acard_sg[si].addr = cpu_to_le32(addr & 0xffffffff);
+		acard_sg[si].addr_hi = cpu_to_le32((addr >> 16) >> 16);
+		acard_sg[si].size = cpu_to_le32(sg_len);
+		last_si = si;
+	}
+
+	acard_sg[last_si].size |= cpu_to_le32(1 << 31);	/* set EOT */
+
+	return si;
+}
+
+static void acard_ahci_qc_prep(struct ata_queued_cmd *qc)
+{
+	struct ata_port *ap = qc->ap;
+	struct ahci_port_priv *pp = ap->private_data;
+	int is_atapi = ata_is_atapi(qc->tf.protocol);
+	void *cmd_tbl;
+	u32 opts;
+	const u32 cmd_fis_len = 5; /* five dwords */
+	unsigned int n_elem;
+
+	/*
+	 * Fill in command table information.  First, the header,
+	 * a SATA Register - Host to Device command FIS.
+	 */
+	cmd_tbl = pp->cmd_tbl + qc->tag * AHCI_CMD_TBL_SZ;
+
+	ata_tf_to_fis(&qc->tf, qc->dev->link->pmp, 1, cmd_tbl);
+	if (is_atapi) {
+		memset(cmd_tbl + AHCI_CMD_TBL_CDB, 0, 32);
+		memcpy(cmd_tbl + AHCI_CMD_TBL_CDB, qc->cdb, qc->dev->cdb_len);
+	}
+
+	n_elem = 0;
+	if (qc->flags & ATA_QCFLAG_DMAMAP)
+		n_elem = acard_ahci_fill_sg(qc, cmd_tbl);
+
+	/*
+	 * Fill in command slot information.
+	 *
+	 * ACard note: prd table length not filled in
+	 */
+	opts = cmd_fis_len | (qc->dev->link->pmp << 12);
+	if (qc->tf.flags & ATA_TFLAG_WRITE)
+		opts |= AHCI_CMD_WRITE;
+	if (is_atapi)
+		opts |= AHCI_CMD_ATAPI | AHCI_CMD_PREFETCH;
+
+	ahci_fill_cmd_slot(pp, qc->tag, opts);
+}
+
+static bool acard_ahci_qc_fill_rtf(struct ata_queued_cmd *qc)
+{
+	struct ahci_port_priv *pp = qc->ap->private_data;
+	u8 *rx_fis = pp->rx_fis;
+
+	if (pp->fbs_enabled)
+		rx_fis += qc->dev->link->pmp * ACARD_AHCI_RX_FIS_SZ;
+
+	/*
+	 * After a successful execution of an ATA PIO data-in command,
+	 * the device doesn't send D2H Reg FIS to update the TF and
+	 * the host should take TF and E_Status from the preceding PIO
+	 * Setup FIS.
+	 */
+	if (qc->tf.protocol == ATA_PROT_PIO && qc->dma_dir == DMA_FROM_DEVICE &&
+	    !(qc->flags & ATA_QCFLAG_FAILED)) {
+		ata_tf_from_fis(rx_fis + RX_FIS_PIO_SETUP, &qc->result_tf);
+		qc->result_tf.command = (rx_fis + RX_FIS_PIO_SETUP)[15];
+	} else
+		ata_tf_from_fis(rx_fis + RX_FIS_D2H_REG, &qc->result_tf);
+
+	return true;
+}
+
+static int acard_ahci_port_start(struct ata_port *ap)
+{
+	struct ahci_host_priv *hpriv = ap->host->private_data;
+	struct device *dev = ap->host->dev;
+	struct ahci_port_priv *pp;
+	void *mem;
+	dma_addr_t mem_dma;
+	size_t dma_sz, rx_fis_sz;
+
+	pp = devm_kzalloc(dev, sizeof(*pp), GFP_KERNEL);
+	if (!pp)
+		return -ENOMEM;
+
+	/* check FBS capability */
+	if ((hpriv->cap & HOST_CAP_FBS) && sata_pmp_supported(ap)) {
+		void __iomem *port_mmio = ahci_port_base(ap);
+		u32 cmd = readl(port_mmio + PORT_CMD);
+		if (cmd & PORT_CMD_FBSCP)
+			pp->fbs_supported = true;
+		else if (hpriv->flags & AHCI_HFLAG_YES_FBS) {
+			dev_printk(KERN_INFO, dev,
+				   "port %d can do FBS, forcing FBSCP\n",
+				   ap->port_no);
+			pp->fbs_supported = true;
+		} else
+			dev_printk(KERN_WARNING, dev,
+				   "port %d is not capable of FBS\n",
+				   ap->port_no);
+	}
+
+	if (pp->fbs_supported) {
+		dma_sz = AHCI_PORT_PRIV_FBS_DMA_SZ;
+		rx_fis_sz = ACARD_AHCI_RX_FIS_SZ * 16;
+	} else {
+		dma_sz = AHCI_PORT_PRIV_DMA_SZ;
+		rx_fis_sz = ACARD_AHCI_RX_FIS_SZ;
+	}
+
+	mem = dmam_alloc_coherent(dev, dma_sz, &mem_dma, GFP_KERNEL);
+	if (!mem)
+		return -ENOMEM;
+	memset(mem, 0, dma_sz);
+
+	/*
+	 * First item in chunk of DMA memory: 32-slot command table,
+	 * 32 bytes each in size
+	 */
+	pp->cmd_slot = mem;
+	pp->cmd_slot_dma = mem_dma;
+
+	mem += AHCI_CMD_SLOT_SZ;
+	mem_dma += AHCI_CMD_SLOT_SZ;
+
+	/*
+	 * Second item: Received-FIS area
+	 */
+	pp->rx_fis = mem;
+	pp->rx_fis_dma = mem_dma;
+
+	mem += rx_fis_sz;
+	mem_dma += rx_fis_sz;
+
+	/*
+	 * Third item: data area for storing a single command
+	 * and its scatter-gather table
+	 */
+	pp->cmd_tbl = mem;
+	pp->cmd_tbl_dma = mem_dma;
+
+	/*
+	 * Save off initial list of interrupts to be enabled.
+	 * This could be changed later
+	 */
+	pp->intr_mask = DEF_PORT_IRQ;
+
+	ap->private_data = pp;
+
+	/* engage engines, captain */
+	return ahci_port_resume(ap);
+}
+
+static int acard_ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+	static int printed_version;
+	unsigned int board_id = ent->driver_data;
+	struct ata_port_info pi = acard_ahci_port_info[board_id];
+	const struct ata_port_info *ppi[] = { &pi, NULL };
+	struct device *dev = &pdev->dev;
+	struct ahci_host_priv *hpriv;
+	struct ata_host *host;
+	int n_ports, i, rc;
+
+	VPRINTK("ENTER\n");
+
+	WARN_ON(ATA_MAX_QUEUE > AHCI_MAX_CMDS);
+
+	if (!printed_version++)
+		dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
+
+	/* acquire resources */
+	rc = pcim_enable_device(pdev);
+	if (rc)
+		return rc;
+
+	/* AHCI controllers often implement SFF compatible interface.
+	 * Grab all PCI BARs just in case.
+	 */
+	rc = pcim_iomap_regions_request_all(pdev, 1 << AHCI_PCI_BAR, DRV_NAME);
+	if (rc == -EBUSY)
+		pcim_pin_device(pdev);
+	if (rc)
+		return rc;
+
+	hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL);
+	if (!hpriv)
+		return -ENOMEM;
+	hpriv->flags |= (unsigned long)pi.private_data;
+
+	if (!(hpriv->flags & AHCI_HFLAG_NO_MSI))
+		pci_enable_msi(pdev);
+
+	hpriv->mmio = pcim_iomap_table(pdev)[AHCI_PCI_BAR];
+
+	/* save initial config */
+	ahci_save_initial_config(&pdev->dev, hpriv, 0, 0);
+
+	/* prepare host */
+	if (hpriv->cap & HOST_CAP_NCQ)
+		pi.flags |= ATA_FLAG_NCQ;
+
+	if (hpriv->cap & HOST_CAP_PMP)
+		pi.flags |= ATA_FLAG_PMP;
+
+	ahci_set_em_messages(hpriv, &pi);
+
+	/* CAP.NP sometimes indicate the index of the last enabled
+	 * port, at other times, that of the last possible port, so
+	 * determining the maximum port number requires looking at
+	 * both CAP.NP and port_map.
+	 */
+	n_ports = max(ahci_nr_ports(hpriv->cap), fls(hpriv->port_map));
+
+	host = ata_host_alloc_pinfo(&pdev->dev, ppi, n_ports);
+	if (!host)
+		return -ENOMEM;
+	host->private_data = hpriv;
+
+	if (!(hpriv->cap & HOST_CAP_SSS) || ahci_ignore_sss)
+		host->flags |= ATA_HOST_PARALLEL_SCAN;
+	else
+		printk(KERN_INFO "ahci: SSS flag set, parallel bus scan disabled\n");
+
+	for (i = 0; i < host->n_ports; i++) {
+		struct ata_port *ap = host->ports[i];
+
+		ata_port_pbar_desc(ap, AHCI_PCI_BAR, -1, "abar");
+		ata_port_pbar_desc(ap, AHCI_PCI_BAR,
+				   0x100 + ap->port_no * 0x80, "port");
+
+		/* set initial link pm policy */
+		/*
+		ap->pm_policy = NOT_AVAILABLE;
+		*/
+		/* disabled/not-implemented port */
+		if (!(hpriv->port_map & (1 << i)))
+			ap->ops = &ata_dummy_port_ops;
+	}
+
+	/* initialize adapter */
+	rc = acard_ahci_configure_dma_masks(pdev, hpriv->cap & HOST_CAP_64);
+	if (rc)
+		return rc;
+
+	rc = ahci_reset_controller(host);
+	if (rc)
+		return rc;
+
+	ahci_init_controller(host);
+	acard_ahci_pci_print_info(host);
+
+	pci_set_master(pdev);
+	return ata_host_activate(host, pdev->irq, ahci_interrupt, IRQF_SHARED,
+				 &acard_ahci_sht);
+}
+
+static int __init acard_ahci_init(void)
+{
+	return pci_register_driver(&acard_ahci_pci_driver);
+}
+
+static void __exit acard_ahci_exit(void)
+{
+	pci_unregister_driver(&acard_ahci_pci_driver);
+}
+
+MODULE_AUTHOR("Jeff Garzik");
+MODULE_DESCRIPTION("ACard AHCI SATA low-level driver");
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(pci, acard_ahci_pci_tbl);
+MODULE_VERSION(DRV_VERSION);
+
+module_init(acard_ahci_init);
+module_exit(acard_ahci_exit);
diff -druNp linux-libre-2.6.37-gnu1/drivers/ata/ahci.c linux-libre-2.6.38-gnu1/drivers/ata/ahci.c
--- linux-libre-2.6.37-gnu1/drivers/ata/ahci.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/ata/ahci.c	2011-03-14 21:20:32.000000000 -0400
@@ -260,6 +260,7 @@ static const struct pci_device_id ahci_p
 	{ PCI_VDEVICE(INTEL, 0x1d02), board_ahci }, /* PBG AHCI */
 	{ PCI_VDEVICE(INTEL, 0x1d04), board_ahci }, /* PBG RAID */
 	{ PCI_VDEVICE(INTEL, 0x1d06), board_ahci }, /* PBG RAID */
+	{ PCI_VDEVICE(INTEL, 0x2323), board_ahci }, /* DH89xxCC AHCI */
 
 	/* JMicron 360/1/3/5/6, match class to avoid IDE function */
 	{ PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
@@ -379,6 +380,8 @@ static const struct pci_device_id ahci_p
 	{ PCI_VDEVICE(MARVELL, 0x6145), board_ahci_mv },	/* 6145 */
 	{ PCI_VDEVICE(MARVELL, 0x6121), board_ahci_mv },	/* 6121 */
 	{ PCI_DEVICE(0x1b4b, 0x9123),
+	  .class = PCI_CLASS_STORAGE_SATA_AHCI,
+	  .class_mask = 0xffffff,
 	  .driver_data = board_ahci_yes_fbs },			/* 88se9128 */
 
 	/* Promise */
diff -druNp linux-libre-2.6.37-gnu1/drivers/ata/ahci.h linux-libre-2.6.38-gnu1/drivers/ata/ahci.h
--- linux-libre-2.6.37-gnu1/drivers/ata/ahci.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/ata/ahci.h	2011-03-14 21:20:32.000000000 -0400
@@ -311,6 +311,8 @@ extern struct device_attribute *ahci_sde
 
 extern struct ata_port_operations ahci_ops;
 
+void ahci_fill_cmd_slot(struct ahci_port_priv *pp, unsigned int tag,
+			u32 opts);
 void ahci_save_initial_config(struct device *dev,
 			      struct ahci_host_priv *hpriv,
 			      unsigned int force_port_map,
@@ -326,6 +328,7 @@ int ahci_stop_engine(struct ata_port *ap
 void ahci_start_engine(struct ata_port *ap);
 int ahci_check_ready(struct ata_link *link);
 int ahci_kick_engine(struct ata_port *ap);
+int ahci_port_resume(struct ata_port *ap);
 void ahci_set_em_messages(struct ahci_host_priv *hpriv,
 			  struct ata_port_info *pi);
 int ahci_reset_em(struct ata_host *host);
diff -druNp linux-libre-2.6.37-gnu1/drivers/ata/Kconfig linux-libre-2.6.38-gnu1/drivers/ata/Kconfig
--- linux-libre-2.6.37-gnu1/drivers/ata/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/ata/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -2,6 +2,14 @@
 # SATA/PATA driver configuration
 #
 
+config HAVE_PATA_PLATFORM
+	bool
+	help
+	  This is an internal configuration node for any machine that
+	  uses pata-platform driver to enable the relevant driver in the
+	  configuration structure without having to submit endless patches
+	  to update the PATA_PLATFORM entry.
+
 menuconfig ATA
 	tristate "Serial ATA and Parallel ATA drivers"
 	depends on HAS_IOMEM
@@ -90,6 +98,14 @@ config SATA_INIC162X
 	help
 	  This option enables support for Initio 162x Serial ATA.
 
+config SATA_ACARD_AHCI
+	tristate "ACard AHCI variant (ATP 8620)"
+	depends on PCI
+	help
+	  This option enables support for Acard.
+
+	  If unsure, say N.
+
 config SATA_SIL24
 	tristate "Silicon Image 3124/3132 SATA support"
 	depends on PCI
@@ -400,11 +416,11 @@ config PATA_HPT37X
 	  If unsure, say N.
 
 config PATA_HPT3X2N
-	tristate "HPT 372N/302N PATA support"
+	tristate "HPT 371N/372N/302N PATA support"
 	depends on PCI
 	help
 	  This option enables support for the N variant HPT PATA
-	  controllers via the new ATA layer
+	  controllers via the new ATA layer.
 
 	  If unsure, say N.
 
@@ -765,17 +781,9 @@ config PATA_PCMCIA
 
 	  If unsure, say N.
 
-config HAVE_PATA_PLATFORM
-	bool
-	help
-	  This is an internal configuration node for any machine that
-	  uses pata-platform driver to enable the relevant driver in the
-	  configuration structure without having to submit endless patches
-	  to update the PATA_PLATFORM entry.
-
 config PATA_PLATFORM
 	tristate "Generic platform device PATA support"
-	depends on EMBEDDED || PPC || HAVE_PATA_PLATFORM
+	depends on EXPERT || PPC || HAVE_PATA_PLATFORM
 	help
 	  This option enables support for generic directly connected ATA
 	  devices commonly found on embedded systems.
diff -druNp linux-libre-2.6.37-gnu1/drivers/ata/libahci.c linux-libre-2.6.38-gnu1/drivers/ata/libahci.c
--- linux-libre-2.6.37-gnu1/drivers/ata/libahci.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/ata/libahci.c	2011-03-14 21:20:32.000000000 -0400
@@ -87,10 +87,7 @@ static int ahci_hardreset(struct ata_lin
 static void ahci_postreset(struct ata_link *link, unsigned int *class);
 static void ahci_error_handler(struct ata_port *ap);
 static void ahci_post_internal_cmd(struct ata_queued_cmd *qc);
-static int ahci_port_resume(struct ata_port *ap);
 static void ahci_dev_config(struct ata_device *dev);
-static void ahci_fill_cmd_slot(struct ahci_port_priv *pp, unsigned int tag,
-			       u32 opts);
 #ifdef CONFIG_PM
 static int ahci_port_suspend(struct ata_port *ap, pm_message_t mesg);
 #endif
@@ -1133,8 +1130,8 @@ static unsigned int ahci_dev_classify(st
 	return ata_dev_classify(&tf);
 }
 
-static void ahci_fill_cmd_slot(struct ahci_port_priv *pp, unsigned int tag,
-			       u32 opts)
+void ahci_fill_cmd_slot(struct ahci_port_priv *pp, unsigned int tag,
+			u32 opts)
 {
 	dma_addr_t cmd_tbl_dma;
 
@@ -1145,6 +1142,7 @@ static void ahci_fill_cmd_slot(struct ah
 	pp->cmd_slot[tag].tbl_addr = cpu_to_le32(cmd_tbl_dma & 0xffffffff);
 	pp->cmd_slot[tag].tbl_addr_hi = cpu_to_le32((cmd_tbl_dma >> 16) >> 16);
 }
+EXPORT_SYMBOL_GPL(ahci_fill_cmd_slot);
 
 int ahci_kick_engine(struct ata_port *ap)
 {
@@ -1918,7 +1916,7 @@ static void ahci_pmp_detach(struct ata_p
 	writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
 }
 
-static int ahci_port_resume(struct ata_port *ap)
+int ahci_port_resume(struct ata_port *ap)
 {
 	ahci_power_up(ap);
 	ahci_start_port(ap);
@@ -1930,6 +1928,7 @@ static int ahci_port_resume(struct ata_p
 
 	return 0;
 }
+EXPORT_SYMBOL_GPL(ahci_port_resume);
 
 #ifdef CONFIG_PM
 static int ahci_port_suspend(struct ata_port *ap, pm_message_t mesg)
diff -druNp linux-libre-2.6.37-gnu1/drivers/ata/libata-core.c linux-libre-2.6.38-gnu1/drivers/ata/libata-core.c
--- linux-libre-2.6.37-gnu1/drivers/ata/libata-core.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/ata/libata-core.c	2011-03-14 21:20:32.000000000 -0400
@@ -2240,7 +2240,7 @@ int ata_dev_configure(struct ata_device
 			if (id[ATA_ID_CFA_KEY_MGMT] & 1)
 				ata_dev_printk(dev, KERN_WARNING,
 					       "supports DRM functions and may "
-					       "not be fully accessable.\n");
+					       "not be fully accessible.\n");
 			snprintf(revbuf, 7, "CFA");
 		} else {
 			snprintf(revbuf, 7, "ATA-%d", ata_id_major_version(id));
@@ -2248,7 +2248,7 @@ int ata_dev_configure(struct ata_device
 			if (ata_id_has_tpm(id))
 				ata_dev_printk(dev, KERN_WARNING,
 					       "supports DRM functions and may "
-					       "not be fully accessable.\n");
+					       "not be fully accessible.\n");
 		}
 
 		dev->n_sectors = ata_id_n_sectors(id);
@@ -4138,6 +4138,7 @@ static const struct ata_blacklist_entry
 	 * device and controller are SATA.
 	 */
 	{ "PIONEER DVD-RW  DVRTD08",	"1.00",	ATA_HORKAGE_NOSETXFER },
+	{ "PIONEER DVD-RW  DVR-212D",	"1.28", ATA_HORKAGE_NOSETXFER },
 
 	/* End Marker */
 	{ }
@@ -6128,7 +6129,7 @@ static void ata_port_detach(struct ata_p
 	/* it better be dead now */
 	WARN_ON(!(ap->pflags & ATA_PFLAG_UNLOADED));
 
-	cancel_rearming_delayed_work(&ap->hotplug_task);
+	cancel_delayed_work_sync(&ap->hotplug_task);
 
  skip_eh:
 	if (ap->pmp_link) {
diff -druNp linux-libre-2.6.37-gnu1/drivers/ata/libata-scsi.c linux-libre-2.6.38-gnu1/drivers/ata/libata-scsi.c
--- linux-libre-2.6.37-gnu1/drivers/ata/libata-scsi.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/ata/libata-scsi.c	2011-03-14 21:20:32.000000000 -0400
@@ -346,12 +346,11 @@ struct device_attribute *ata_common_sdev
 };
 EXPORT_SYMBOL_GPL(ata_common_sdev_attrs);
 
-static void ata_scsi_invalid_field(struct scsi_cmnd *cmd,
-				   void (*done)(struct scsi_cmnd *))
+static void ata_scsi_invalid_field(struct scsi_cmnd *cmd)
 {
 	ata_scsi_set_sense(cmd, ILLEGAL_REQUEST, 0x24, 0x0);
 	/* "Invalid field in cbd" */
-	done(cmd);
+	cmd->scsi_done(cmd);
 }
 
 /**
@@ -719,7 +718,6 @@ EXPORT_SYMBOL_GPL(ata_scsi_ioctl);
  *	ata_scsi_qc_new - acquire new ata_queued_cmd reference
  *	@dev: ATA device to which the new command is attached
  *	@cmd: SCSI command that originated this ATA command
- *	@done: SCSI command completion function
  *
  *	Obtain a reference to an unused ata_queued_cmd structure,
  *	which is the basic libata structure representing a single
@@ -736,21 +734,20 @@ EXPORT_SYMBOL_GPL(ata_scsi_ioctl);
  *	Command allocated, or %NULL if none available.
  */
 static struct ata_queued_cmd *ata_scsi_qc_new(struct ata_device *dev,
-					      struct scsi_cmnd *cmd,
-					      void (*done)(struct scsi_cmnd *))
+					      struct scsi_cmnd *cmd)
 {
 	struct ata_queued_cmd *qc;
 
 	qc = ata_qc_new_init(dev);
 	if (qc) {
 		qc->scsicmd = cmd;
-		qc->scsidone = done;
+		qc->scsidone = cmd->scsi_done;
 
 		qc->sg = scsi_sglist(cmd);
 		qc->n_elem = scsi_sg_count(cmd);
 	} else {
 		cmd->result = (DID_OK << 16) | (QUEUE_FULL << 1);
-		done(cmd);
+		cmd->scsi_done(cmd);
 	}
 
 	return qc;
@@ -1102,9 +1099,9 @@ static int ata_scsi_dev_config(struct sc
 		struct request_queue *q = sdev->request_queue;
 		void *buf;
 
-		/* set the min alignment and padding */
-		blk_queue_update_dma_alignment(sdev->request_queue,
-					       ATA_DMA_PAD_SZ - 1);
+		sdev->sector_size = ATA_SECT_SIZE;
+
+		/* set DMA padding */
 		blk_queue_update_dma_pad(sdev->request_queue,
 					 ATA_DMA_PAD_SZ - 1);
 
@@ -1118,13 +1115,25 @@ static int ata_scsi_dev_config(struct sc
 
 		blk_queue_dma_drain(q, atapi_drain_needed, buf, ATAPI_MAX_DRAIN);
 	} else {
-		/* ATA devices must be sector aligned */
 		sdev->sector_size = ata_id_logical_sector_size(dev->id);
-		blk_queue_update_dma_alignment(sdev->request_queue,
-					       sdev->sector_size - 1);
 		sdev->manage_start_stop = 1;
 	}
 
+	/*
+	 * ata_pio_sectors() expects buffer for each sector to not cross
+	 * page boundary.  Enforce it by requiring buffers to be sector
+	 * aligned, which works iff sector_size is not larger than
+	 * PAGE_SIZE.  ATAPI devices also need the alignment as
+	 * IDENTIFY_PACKET is executed as ATA_PROT_PIO.
+	 */
+	if (sdev->sector_size > PAGE_SIZE)
+		ata_dev_printk(dev, KERN_WARNING,
+			"sector_size=%u > PAGE_SIZE, PIO may malfunction\n",
+			sdev->sector_size);
+
+	blk_queue_update_dma_alignment(sdev->request_queue,
+				       sdev->sector_size - 1);
+
 	if (dev->flags & ATA_DFLAG_AN)
 		set_bit(SDEV_EVT_MEDIA_CHANGE, sdev->supported_events);
 
@@ -1735,7 +1744,6 @@ static void ata_scsi_qc_complete(struct
  *	ata_scsi_translate - Translate then issue SCSI command to ATA device
  *	@dev: ATA device to which the command is addressed
  *	@cmd: SCSI command to execute
- *	@done: SCSI command completion function
  *	@xlat_func: Actor which translates @cmd to an ATA taskfile
  *
  *	Our ->queuecommand() function has decided that the SCSI
@@ -1759,7 +1767,6 @@ static void ata_scsi_qc_complete(struct
  *	needs to be deferred.
  */
 static int ata_scsi_translate(struct ata_device *dev, struct scsi_cmnd *cmd,
-			      void (*done)(struct scsi_cmnd *),
 			      ata_xlat_func_t xlat_func)
 {
 	struct ata_port *ap = dev->link->ap;
@@ -1768,7 +1775,7 @@ static int ata_scsi_translate(struct ata
 
 	VPRINTK("ENTER\n");
 
-	qc = ata_scsi_qc_new(dev, cmd, done);
+	qc = ata_scsi_qc_new(dev, cmd);
 	if (!qc)
 		goto err_mem;
 
@@ -1804,14 +1811,14 @@ static int ata_scsi_translate(struct ata
 
 early_finish:
 	ata_qc_free(qc);
-	qc->scsidone(cmd);
+	cmd->scsi_done(cmd);
 	DPRINTK("EXIT - early finish (good or error)\n");
 	return 0;
 
 err_did:
 	ata_qc_free(qc);
 	cmd->result = (DID_ERROR << 16);
-	qc->scsidone(cmd);
+	cmd->scsi_done(cmd);
 err_mem:
 	DPRINTK("EXIT - internal\n");
 	return 0;
@@ -3116,7 +3123,6 @@ static inline void ata_scsi_dump_cdb(str
 }
 
 static inline int __ata_scsi_queuecmd(struct scsi_cmnd *scmd,
-				      void (*done)(struct scsi_cmnd *),
 				      struct ata_device *dev)
 {
 	u8 scsi_op = scmd->cmnd[0];
@@ -3150,9 +3156,9 @@ static inline int __ata_scsi_queuecmd(st
 	}
 
 	if (xlat_func)
-		rc = ata_scsi_translate(dev, scmd, done, xlat_func);
+		rc = ata_scsi_translate(dev, scmd, xlat_func);
 	else
-		ata_scsi_simulate(dev, scmd, done);
+		ata_scsi_simulate(dev, scmd);
 
 	return rc;
 
@@ -3160,7 +3166,7 @@ static inline int __ata_scsi_queuecmd(st
 	DPRINTK("bad CDB len=%u, scsi_op=0x%02x, max=%u\n",
 		scmd->cmd_len, scsi_op, dev->cdb_len);
 	scmd->result = DID_ERROR << 16;
-	done(scmd);
+	scmd->scsi_done(scmd);
 	return 0;
 }
 
@@ -3199,7 +3205,7 @@ int ata_scsi_queuecmd(struct Scsi_Host *
 
 	dev = ata_scsi_find_dev(ap, scsidev);
 	if (likely(dev))
-		rc = __ata_scsi_queuecmd(cmd, cmd->scsi_done, dev);
+		rc = __ata_scsi_queuecmd(cmd, dev);
 	else {
 		cmd->result = (DID_BAD_TARGET << 16);
 		cmd->scsi_done(cmd);
@@ -3214,7 +3220,6 @@ int ata_scsi_queuecmd(struct Scsi_Host *
  *	ata_scsi_simulate - simulate SCSI command on ATA device
  *	@dev: the target device
  *	@cmd: SCSI command being sent to device.
- *	@done: SCSI command completion function.
  *
  *	Interprets and directly executes a select list of SCSI commands
  *	that can be handled internally.
@@ -3223,8 +3228,7 @@ int ata_scsi_queuecmd(struct Scsi_Host *
  *	spin_lock_irqsave(host lock)
  */
 
-void ata_scsi_simulate(struct ata_device *dev, struct scsi_cmnd *cmd,
-		      void (*done)(struct scsi_cmnd *))
+void ata_scsi_simulate(struct ata_device *dev, struct scsi_cmnd *cmd)
 {
 	struct ata_scsi_args args;
 	const u8 *scsicmd = cmd->cmnd;
@@ -3233,17 +3237,17 @@ void ata_scsi_simulate(struct ata_device
 	args.dev = dev;
 	args.id = dev->id;
 	args.cmd = cmd;
-	args.done = done;
+	args.done = cmd->scsi_done;
 
 	switch(scsicmd[0]) {
 	/* TODO: worth improving? */
 	case FORMAT_UNIT:
-		ata_scsi_invalid_field(cmd, done);
+		ata_scsi_invalid_field(cmd);
 		break;
 
 	case INQUIRY:
 		if (scsicmd[1] & 2)	           /* is CmdDt set?  */
-			ata_scsi_invalid_field(cmd, done);
+			ata_scsi_invalid_field(cmd);
 		else if ((scsicmd[1] & 1) == 0)    /* is EVPD clear? */
 			ata_scsi_rbuf_fill(&args, ata_scsiop_inq_std);
 		else switch (scsicmd[2]) {
@@ -3269,7 +3273,7 @@ void ata_scsi_simulate(struct ata_device
 			ata_scsi_rbuf_fill(&args, ata_scsiop_inq_b2);
 			break;
 		default:
-			ata_scsi_invalid_field(cmd, done);
+			ata_scsi_invalid_field(cmd);
 			break;
 		}
 		break;
@@ -3281,7 +3285,7 @@ void ata_scsi_simulate(struct ata_device
 
 	case MODE_SELECT:	/* unconditionally return */
 	case MODE_SELECT_10:	/* bad-field-in-cdb */
-		ata_scsi_invalid_field(cmd, done);
+		ata_scsi_invalid_field(cmd);
 		break;
 
 	case READ_CAPACITY:
@@ -3292,7 +3296,7 @@ void ata_scsi_simulate(struct ata_device
 		if ((scsicmd[1] & 0x1f) == SAI_READ_CAPACITY_16)
 			ata_scsi_rbuf_fill(&args, ata_scsiop_read_cap);
 		else
-			ata_scsi_invalid_field(cmd, done);
+			ata_scsi_invalid_field(cmd);
 		break;
 
 	case REPORT_LUNS:
@@ -3302,7 +3306,7 @@ void ata_scsi_simulate(struct ata_device
 	case REQUEST_SENSE:
 		ata_scsi_set_sense(cmd, 0, 0, 0);
 		cmd->result = (DRIVER_SENSE << 24);
-		done(cmd);
+		cmd->scsi_done(cmd);
 		break;
 
 	/* if we reach this, then writeback caching is disabled,
@@ -3324,14 +3328,14 @@ void ata_scsi_simulate(struct ata_device
 		if ((tmp8 == 0x4) && (!scsicmd[3]) && (!scsicmd[4]))
 			ata_scsi_rbuf_fill(&args, ata_scsiop_noop);
 		else
-			ata_scsi_invalid_field(cmd, done);
+			ata_scsi_invalid_field(cmd);
 		break;
 
 	/* all other commands */
 	default:
 		ata_scsi_set_sense(cmd, ILLEGAL_REQUEST, 0x20, 0x0);
 		/* "Invalid command operation code" */
-		done(cmd);
+		cmd->scsi_done(cmd);
 		break;
 	}
 }
@@ -3858,7 +3862,6 @@ EXPORT_SYMBOL_GPL(ata_sas_slave_configur
 /**
  *	ata_sas_queuecmd - Issue SCSI cdb to libata-managed device
  *	@cmd: SCSI command to be sent
- *	@done: Completion function, called when command is complete
  *	@ap:	ATA port to which the command is being sent
  *
  *	RETURNS:
@@ -3866,18 +3869,17 @@ EXPORT_SYMBOL_GPL(ata_sas_slave_configur
  *	0 otherwise.
  */
 
-int ata_sas_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *),
-		     struct ata_port *ap)
+int ata_sas_queuecmd(struct scsi_cmnd *cmd, struct ata_port *ap)
 {
 	int rc = 0;
 
 	ata_scsi_dump_cdb(ap, cmd);
 
 	if (likely(ata_dev_enabled(ap->link.device)))
-		rc = __ata_scsi_queuecmd(cmd, done, ap->link.device);
+		rc = __ata_scsi_queuecmd(cmd, ap->link.device);
 	else {
 		cmd->result = (DID_BAD_TARGET << 16);
-		done(cmd);
+		cmd->scsi_done(cmd);
 	}
 	return rc;
 }
diff -druNp linux-libre-2.6.37-gnu1/drivers/ata/libata-sff.c linux-libre-2.6.38-gnu1/drivers/ata/libata-sff.c
--- linux-libre-2.6.37-gnu1/drivers/ata/libata-sff.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/ata/libata-sff.c	2011-03-14 21:20:32.000000000 -0400
@@ -1320,7 +1320,7 @@ void ata_sff_flush_pio_task(struct ata_p
 {
 	DPRINTK("ENTER\n");
 
-	cancel_rearming_delayed_work(&ap->sff_pio_task);
+	cancel_delayed_work_sync(&ap->sff_pio_task);
 	ap->hsm_task_state = HSM_ST_IDLE;
 
 	if (ata_msg_ctl(ap))
diff -druNp linux-libre-2.6.37-gnu1/drivers/ata/Makefile linux-libre-2.6.38-gnu1/drivers/ata/Makefile
--- linux-libre-2.6.37-gnu1/drivers/ata/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/ata/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -3,6 +3,7 @@ obj-$(CONFIG_ATA)		+= libata.o
 
 # non-SFF interface
 obj-$(CONFIG_SATA_AHCI)		+= ahci.o libahci.o
+obj-$(CONFIG_SATA_ACARD_AHCI)	+= acard-ahci.o libahci.o
 obj-$(CONFIG_SATA_AHCI_PLATFORM) += ahci_platform.o libahci.o
 obj-$(CONFIG_SATA_FSL)		+= sata_fsl.o
 obj-$(CONFIG_SATA_INIC162X)	+= sata_inic162x.o
diff -druNp linux-libre-2.6.37-gnu1/drivers/ata/pata_hpt366.c linux-libre-2.6.38-gnu1/drivers/ata/pata_hpt366.c
--- linux-libre-2.6.37-gnu1/drivers/ata/pata_hpt366.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/ata/pata_hpt366.c	2011-03-14 21:20:32.000000000 -0400
@@ -25,7 +25,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME	"pata_hpt366"
-#define DRV_VERSION	"0.6.8"
+#define DRV_VERSION	"0.6.10"
 
 struct hpt_clock {
 	u8	xfer_mode;
@@ -110,18 +110,23 @@ static const struct hpt_clock hpt366_25[
 	{	0,		0x01208585	}
 };
 
-static const char *bad_ata33[] = {
-	"Maxtor 92720U8", "Maxtor 92040U6", "Maxtor 91360U4", "Maxtor 91020U3", "Maxtor 90845U3", "Maxtor 90650U2",
-	"Maxtor 91360D8", "Maxtor 91190D7", "Maxtor 91020D6", "Maxtor 90845D5", "Maxtor 90680D4", "Maxtor 90510D3", "Maxtor 90340D2",
-	"Maxtor 91152D8", "Maxtor 91008D7", "Maxtor 90845D6", "Maxtor 90840D6", "Maxtor 90720D5", "Maxtor 90648D5", "Maxtor 90576D4",
+static const char * const bad_ata33[] = {
+	"Maxtor 92720U8", "Maxtor 92040U6", "Maxtor 91360U4", "Maxtor 91020U3",
+	"Maxtor 90845U3", "Maxtor 90650U2",
+	"Maxtor 91360D8", "Maxtor 91190D7", "Maxtor 91020D6", "Maxtor 90845D5",
+	"Maxtor 90680D4", "Maxtor 90510D3", "Maxtor 90340D2",
+	"Maxtor 91152D8", "Maxtor 91008D7", "Maxtor 90845D6", "Maxtor 90840D6",
+	"Maxtor 90720D5", "Maxtor 90648D5", "Maxtor 90576D4",
 	"Maxtor 90510D4",
 	"Maxtor 90432D3", "Maxtor 90288D2", "Maxtor 90256D2",
-	"Maxtor 91000D8", "Maxtor 90910D8", "Maxtor 90875D7", "Maxtor 90840D7", "Maxtor 90750D6", "Maxtor 90625D5", "Maxtor 90500D4",
-	"Maxtor 91728D8", "Maxtor 91512D7", "Maxtor 91303D6", "Maxtor 91080D5", "Maxtor 90845D4", "Maxtor 90680D4", "Maxtor 90648D3", "Maxtor 90432D2",
+	"Maxtor 91000D8", "Maxtor 90910D8", "Maxtor 90875D7", "Maxtor 90840D7",
+	"Maxtor 90750D6", "Maxtor 90625D5", "Maxtor 90500D4",
+	"Maxtor 91728D8", "Maxtor 91512D7", "Maxtor 91303D6", "Maxtor 91080D5",
+	"Maxtor 90845D4", "Maxtor 90680D4", "Maxtor 90648D3", "Maxtor 90432D2",
 	NULL
 };
 
-static const char *bad_ata66_4[] = {
+static const char * const bad_ata66_4[] = {
 	"IBM-DTLA-307075",
 	"IBM-DTLA-307060",
 	"IBM-DTLA-307045",
@@ -140,12 +145,13 @@ static const char *bad_ata66_4[] = {
 	NULL
 };
 
-static const char *bad_ata66_3[] = {
+static const char * const bad_ata66_3[] = {
 	"WDC AC310200R",
 	NULL
 };
 
-static int hpt_dma_blacklisted(const struct ata_device *dev, char *modestr, const char *list[])
+static int hpt_dma_blacklisted(const struct ata_device *dev, char *modestr,
+			       const char * const list[])
 {
 	unsigned char model_num[ATA_ID_PROD_LEN + 1];
 	int i = 0;
@@ -154,8 +160,8 @@ static int hpt_dma_blacklisted(const str
 
 	while (list[i] != NULL) {
 		if (!strcmp(list[i], model_num)) {
-			printk(KERN_WARNING DRV_NAME ": %s is not supported for %s.\n",
-				modestr, list[i]);
+			pr_warning(DRV_NAME ": %s is not supported for %s.\n",
+				   modestr, list[i]);
 			return 1;
 		}
 		i++;
@@ -288,6 +294,7 @@ static struct ata_port_operations hpt366
 static void hpt36x_init_chipset(struct pci_dev *dev)
 {
 	u8 drive_fast;
+
 	pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, (L1_CACHE_BYTES / 4));
 	pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x78);
 	pci_write_config_byte(dev, PCI_MIN_GNT, 0x08);
@@ -349,16 +356,16 @@ static int hpt36x_init_one(struct pci_de
 
 	/* PCI clocking determines the ATA timing values to use */
 	/* info_hpt366 is safe against re-entry so we can scribble on it */
-	switch((reg1 & 0x700) >> 8) {
-		case 9:
-			hpriv = &hpt366_40;
-			break;
-		case 5:
-			hpriv = &hpt366_25;
-			break;
-		default:
-			hpriv = &hpt366_33;
-			break;
+	switch ((reg1 & 0x700) >> 8) {
+	case 9:
+		hpriv = &hpt366_40;
+		break;
+	case 5:
+		hpriv = &hpt366_25;
+		break;
+	default:
+		hpriv = &hpt366_33;
+		break;
 	}
 	/* Now kick off ATA set up */
 	return ata_pci_bmdma_init_one(dev, ppi, &hpt36x_sht, hpriv, 0);
@@ -385,9 +392,9 @@ static const struct pci_device_id hpt36x
 };
 
 static struct pci_driver hpt36x_pci_driver = {
-	.name 		= DRV_NAME,
+	.name		= DRV_NAME,
 	.id_table	= hpt36x,
-	.probe 		= hpt36x_init_one,
+	.probe		= hpt36x_init_one,
 	.remove		= ata_pci_remove_one,
 #ifdef CONFIG_PM
 	.suspend	= ata_pci_device_suspend,
diff -druNp linux-libre-2.6.37-gnu1/drivers/ata/pata_hpt37x.c linux-libre-2.6.38-gnu1/drivers/ata/pata_hpt37x.c
--- linux-libre-2.6.37-gnu1/drivers/ata/pata_hpt37x.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/ata/pata_hpt37x.c	2011-03-14 21:20:32.000000000 -0400
@@ -8,7 +8,7 @@
  * Copyright (C) 1999-2003		Andre Hedrick <andre@linux-ide.org>
  * Portions Copyright (C) 2001	        Sun Microsystems, Inc.
  * Portions Copyright (C) 2003		Red Hat Inc
- * Portions Copyright (C) 2005-2009	MontaVista Software, Inc.
+ * Portions Copyright (C) 2005-2010	MontaVista Software, Inc.
  *
  * TODO
  *	Look into engine reset on timeout errors. Should not be	required.
@@ -24,7 +24,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME	"pata_hpt37x"
-#define DRV_VERSION	"0.6.15"
+#define DRV_VERSION	"0.6.22"
 
 struct hpt_clock {
 	u8	xfer_speed;
@@ -210,7 +210,7 @@ static u32 hpt37x_find_mode(struct ata_p
 {
 	struct hpt_clock *clocks = ap->host->private_data;
 
-	while(clocks->xfer_speed) {
+	while (clocks->xfer_speed) {
 		if (clocks->xfer_speed == speed)
 			return clocks->timing;
 		clocks++;
@@ -219,7 +219,8 @@ static u32 hpt37x_find_mode(struct ata_p
 	return 0xffffffffU;	/* silence compiler warning */
 }
 
-static int hpt_dma_blacklisted(const struct ata_device *dev, char *modestr, const char *list[])
+static int hpt_dma_blacklisted(const struct ata_device *dev, char *modestr,
+			       const char * const list[])
 {
 	unsigned char model_num[ATA_ID_PROD_LEN + 1];
 	int i = 0;
@@ -228,8 +229,8 @@ static int hpt_dma_blacklisted(const str
 
 	while (list[i] != NULL) {
 		if (!strcmp(list[i], model_num)) {
-			printk(KERN_WARNING DRV_NAME ": %s is not supported for %s.\n",
-				modestr, list[i]);
+			pr_warning(DRV_NAME ": %s is not supported for %s.\n",
+				   modestr, list[i]);
 			return 1;
 		}
 		i++;
@@ -237,18 +238,23 @@ static int hpt_dma_blacklisted(const str
 	return 0;
 }
 
-static const char *bad_ata33[] = {
-	"Maxtor 92720U8", "Maxtor 92040U6", "Maxtor 91360U4", "Maxtor 91020U3", "Maxtor 90845U3", "Maxtor 90650U2",
-	"Maxtor 91360D8", "Maxtor 91190D7", "Maxtor 91020D6", "Maxtor 90845D5", "Maxtor 90680D4", "Maxtor 90510D3", "Maxtor 90340D2",
-	"Maxtor 91152D8", "Maxtor 91008D7", "Maxtor 90845D6", "Maxtor 90840D6", "Maxtor 90720D5", "Maxtor 90648D5", "Maxtor 90576D4",
+static const char * const bad_ata33[] = {
+	"Maxtor 92720U8", "Maxtor 92040U6", "Maxtor 91360U4", "Maxtor 91020U3",
+	"Maxtor 90845U3", "Maxtor 90650U2",
+	"Maxtor 91360D8", "Maxtor 91190D7", "Maxtor 91020D6", "Maxtor 90845D5",
+	"Maxtor 90680D4", "Maxtor 90510D3", "Maxtor 90340D2",
+	"Maxtor 91152D8", "Maxtor 91008D7", "Maxtor 90845D6", "Maxtor 90840D6",
+	"Maxtor 90720D5", "Maxtor 90648D5", "Maxtor 90576D4",
 	"Maxtor 90510D4",
 	"Maxtor 90432D3", "Maxtor 90288D2", "Maxtor 90256D2",
-	"Maxtor 91000D8", "Maxtor 90910D8", "Maxtor 90875D7", "Maxtor 90840D7", "Maxtor 90750D6", "Maxtor 90625D5", "Maxtor 90500D4",
-	"Maxtor 91728D8", "Maxtor 91512D7", "Maxtor 91303D6", "Maxtor 91080D5", "Maxtor 90845D4", "Maxtor 90680D4", "Maxtor 90648D3", "Maxtor 90432D2",
+	"Maxtor 91000D8", "Maxtor 90910D8", "Maxtor 90875D7", "Maxtor 90840D7",
+	"Maxtor 90750D6", "Maxtor 90625D5", "Maxtor 90500D4",
+	"Maxtor 91728D8", "Maxtor 91512D7", "Maxtor 91303D6", "Maxtor 91080D5",
+	"Maxtor 90845D4", "Maxtor 90680D4", "Maxtor 90648D3", "Maxtor 90432D2",
 	NULL
 };
 
-static const char *bad_ata100_5[] = {
+static const char * const bad_ata100_5[] = {
 	"IBM-DTLA-307075",
 	"IBM-DTLA-307060",
 	"IBM-DTLA-307045",
@@ -302,6 +308,22 @@ static unsigned long hpt370a_filter(stru
 }
 
 /**
+ *	hpt372_filter	-	mode selection filter
+ *	@adev: ATA device
+ *	@mask: mode mask
+ *
+ *	The Marvell bridge chips used on the HighPoint SATA cards do not seem
+ *	to support the UltraDMA modes 1, 2, and 3 as well as any MWDMA modes...
+ */
+static unsigned long hpt372_filter(struct ata_device *adev, unsigned long mask)
+{
+	if (ata_id_is_sata(adev->id))
+		mask &= ~((0xE << ATA_SHIFT_UDMA) | ATA_MASK_MWDMA);
+
+	return mask;
+}
+
+/**
  *	hpt37x_cable_detect	-	Detect the cable type
  *	@ap: ATA port to detect on
  *
@@ -373,6 +395,7 @@ static int hpt37x_pre_reset(struct ata_l
 		{ 0x50, 1, 0x04, 0x04 },
 		{ 0x54, 1, 0x04, 0x04 }
 	};
+
 	if (!pci_test_config_bits(pdev, &hpt37x_enable_bits[ap->port_no]))
 		return -ENOENT;
 
@@ -586,11 +609,11 @@ static struct ata_port_operations hpt370
 };
 
 /*
- *	Configuration for HPT372, HPT371, HPT302. Slightly different PIO
- *	and DMA mode setting functionality.
+ *	Configuration for HPT371 and HPT302. Slightly different PIO and DMA
+ *	mode setting functionality.
  */
 
-static struct ata_port_operations hpt372_port_ops = {
+static struct ata_port_operations hpt302_port_ops = {
 	.inherits	= &ata_bmdma_port_ops,
 
 	.bmdma_stop	= hpt37x_bmdma_stop,
@@ -602,14 +625,23 @@ static struct ata_port_operations hpt372
 };
 
 /*
- *	Configuration for HPT374. Mode setting works like 372 and friends
+ *	Configuration for HPT372. Mode setting works like 371 and 302
+ *	but we have a mode filter.
+ */
+
+static struct ata_port_operations hpt372_port_ops = {
+	.inherits	= &hpt302_port_ops,
+	.mode_filter	= hpt372_filter,
+};
+
+/*
+ *	Configuration for HPT374. Mode setting and filtering works like 372
  *	but we have a different cable detection procedure for function 1.
  */
 
 static struct ata_port_operations hpt374_fn1_port_ops = {
 	.inherits	= &hpt372_port_ops,
 	.cable_detect	= hpt374_fn1_cable_detect,
-	.prereset	= hpt37x_pre_reset,
 };
 
 /**
@@ -647,12 +679,12 @@ static int hpt37x_calibrate_dpll(struct
 	u32 reg5c;
 	int tries;
 
-	for(tries = 0; tries < 0x5000; tries++) {
+	for (tries = 0; tries < 0x5000; tries++) {
 		udelay(50);
 		pci_read_config_byte(dev, 0x5b, &reg5b);
 		if (reg5b & 0x80) {
 			/* See if it stays set */
-			for(tries = 0; tries < 0x1000; tries ++) {
+			for (tries = 0; tries < 0x1000; tries++) {
 				pci_read_config_byte(dev, 0x5b, &reg5b);
 				/* Failed ? */
 				if ((reg5b & 0x80) == 0)
@@ -660,7 +692,7 @@ static int hpt37x_calibrate_dpll(struct
 			}
 			/* Turn off tuning, we have the DPLL set */
 			pci_read_config_dword(dev, 0x5c, &reg5c);
-			pci_write_config_dword(dev, 0x5c, reg5c & ~ 0x100);
+			pci_write_config_dword(dev, 0x5c, reg5c & ~0x100);
 			return 1;
 		}
 	}
@@ -672,6 +704,7 @@ static u32 hpt374_read_freq(struct pci_d
 {
 	u32 freq;
 	unsigned long io_base = pci_resource_start(pdev, 4);
+
 	if (PCI_FUNC(pdev->devfn) & 1) {
 		struct pci_dev *pdev_0;
 
@@ -737,23 +770,23 @@ static int hpt37x_init_one(struct pci_de
 		.udma_mask = ATA_UDMA5,
 		.port_ops = &hpt370a_port_ops
 	};
-	/* HPT370 - UDMA100 */
+	/* HPT370 - UDMA66 */
 	static const struct ata_port_info info_hpt370_33 = {
 		.flags = ATA_FLAG_SLAVE_POSS,
 		.pio_mask = ATA_PIO4,
 		.mwdma_mask = ATA_MWDMA2,
-		.udma_mask = ATA_UDMA5,
+		.udma_mask = ATA_UDMA4,
 		.port_ops = &hpt370_port_ops
 	};
-	/* HPT370A - UDMA100 */
+	/* HPT370A - UDMA66 */
 	static const struct ata_port_info info_hpt370a_33 = {
 		.flags = ATA_FLAG_SLAVE_POSS,
 		.pio_mask = ATA_PIO4,
 		.mwdma_mask = ATA_MWDMA2,
-		.udma_mask = ATA_UDMA5,
+		.udma_mask = ATA_UDMA4,
 		.port_ops = &hpt370a_port_ops
 	};
-	/* HPT371, 372 and friends - UDMA133 */
+	/* HPT372 - UDMA133 */
 	static const struct ata_port_info info_hpt372 = {
 		.flags = ATA_FLAG_SLAVE_POSS,
 		.pio_mask = ATA_PIO4,
@@ -761,7 +794,15 @@ static int hpt37x_init_one(struct pci_de
 		.udma_mask = ATA_UDMA6,
 		.port_ops = &hpt372_port_ops
 	};
-	/* HPT374 - UDMA100, function 1 uses different prereset method */
+	/* HPT371, 302 - UDMA133 */
+	static const struct ata_port_info info_hpt302 = {
+		.flags = ATA_FLAG_SLAVE_POSS,
+		.pio_mask = ATA_PIO4,
+		.mwdma_mask = ATA_MWDMA2,
+		.udma_mask = ATA_UDMA6,
+		.port_ops = &hpt302_port_ops
+	};
+	/* HPT374 - UDMA100, function 1 uses different cable_detect method */
 	static const struct ata_port_info info_hpt374_fn0 = {
 		.flags = ATA_FLAG_SLAVE_POSS,
 		.pio_mask = ATA_PIO4,
@@ -796,7 +837,8 @@ static int hpt37x_init_one(struct pci_de
 	if (rc)
 		return rc;
 
-	if (dev->device == PCI_DEVICE_ID_TTI_HPT366) {
+	switch (dev->device) {
+	case PCI_DEVICE_ID_TTI_HPT366:
 		/* May be a later chip in disguise. Check */
 		/* Older chips are in the HPT366 driver. Ignore them */
 		if (rev < 3)
@@ -805,66 +847,66 @@ static int hpt37x_init_one(struct pci_de
 		if (rev == 6)
 			return -ENODEV;
 
-		switch(rev) {
-			case 3:
-				ppi[0] = &info_hpt370;
-				chip_table = &hpt370;
-				prefer_dpll = 0;
-				break;
-			case 4:
-				ppi[0] = &info_hpt370a;
-				chip_table = &hpt370a;
-				prefer_dpll = 0;
-				break;
-			case 5:
-				ppi[0] = &info_hpt372;
-				chip_table = &hpt372;
-				break;
-			default:
-				printk(KERN_ERR "pata_hpt37x: Unknown HPT366 "
-				       "subtype, please report (%d).\n", rev);
-				return -ENODEV;
-		}
-	} else {
-		switch(dev->device) {
-			case PCI_DEVICE_ID_TTI_HPT372:
-				/* 372N if rev >= 2*/
-				if (rev >= 2)
-					return -ENODEV;
-				ppi[0] = &info_hpt372;
-				chip_table = &hpt372a;
-				break;
-			case PCI_DEVICE_ID_TTI_HPT302:
-				/* 302N if rev > 1 */
-				if (rev > 1)
-					return -ENODEV;
-				ppi[0] = &info_hpt372;
-				/* Check this */
-				chip_table = &hpt302;
-				break;
-			case PCI_DEVICE_ID_TTI_HPT371:
-				if (rev > 1)
-					return -ENODEV;
-				ppi[0] = &info_hpt372;
-				chip_table = &hpt371;
-				/* Single channel device, master is not present
-				   but the BIOS (or us for non x86) must mark it
-				   absent */
-				pci_read_config_byte(dev, 0x50, &mcr1);
-				mcr1 &= ~0x04;
-				pci_write_config_byte(dev, 0x50, mcr1);
-				break;
-			case PCI_DEVICE_ID_TTI_HPT374:
-				chip_table = &hpt374;
-				if (!(PCI_FUNC(dev->devfn) & 1))
-					*ppi = &info_hpt374_fn0;
-				else
-					*ppi = &info_hpt374_fn1;
-				break;
-			default:
-				printk(KERN_ERR "pata_hpt37x: PCI table is bogus please report (%d).\n", dev->device);
-				return -ENODEV;
+		switch (rev) {
+		case 3:
+			ppi[0] = &info_hpt370;
+			chip_table = &hpt370;
+			prefer_dpll = 0;
+			break;
+		case 4:
+			ppi[0] = &info_hpt370a;
+			chip_table = &hpt370a;
+			prefer_dpll = 0;
+			break;
+		case 5:
+			ppi[0] = &info_hpt372;
+			chip_table = &hpt372;
+			break;
+		default:
+			pr_err(DRV_NAME ": Unknown HPT366 subtype, "
+			       "please report (%d).\n", rev);
+			return -ENODEV;
 		}
+		break;
+	case PCI_DEVICE_ID_TTI_HPT372:
+		/* 372N if rev >= 2 */
+		if (rev >= 2)
+			return -ENODEV;
+		ppi[0] = &info_hpt372;
+		chip_table = &hpt372a;
+		break;
+	case PCI_DEVICE_ID_TTI_HPT302:
+		/* 302N if rev > 1 */
+		if (rev > 1)
+			return -ENODEV;
+		ppi[0] = &info_hpt302;
+		/* Check this */
+		chip_table = &hpt302;
+		break;
+	case PCI_DEVICE_ID_TTI_HPT371:
+		if (rev > 1)
+			return -ENODEV;
+		ppi[0] = &info_hpt302;
+		chip_table = &hpt371;
+		/*
+		 * Single channel device, master is not present but the BIOS
+		 * (or us for non x86) must mark it absent
+		 */
+		pci_read_config_byte(dev, 0x50, &mcr1);
+		mcr1 &= ~0x04;
+		pci_write_config_byte(dev, 0x50, mcr1);
+		break;
+	case PCI_DEVICE_ID_TTI_HPT374:
+		chip_table = &hpt374;
+		if (!(PCI_FUNC(dev->devfn) & 1))
+			*ppi = &info_hpt374_fn0;
+		else
+			*ppi = &info_hpt374_fn1;
+		break;
+	default:
+		pr_err(DRV_NAME ": PCI table is bogus, please report (%d).\n",
+		       dev->device);
+		return -ENODEV;
 	}
 	/* Ok so this is a chip we support */
 
@@ -893,9 +935,11 @@ static int hpt37x_init_one(struct pci_de
 	if (chip_table == &hpt372a)
 		outb(0x0e, iobase + 0x9c);
 
-	/* Some devices do not let this value be accessed via PCI space
-	   according to the old driver. In addition we must use the value
-	   from FN 0 on the HPT374 */
+	/*
+	 * Some devices do not let this value be accessed via PCI space
+	 * according to the old driver. In addition we must use the value
+	 * from FN 0 on the HPT374.
+	 */
 
 	if (chip_table == &hpt374) {
 		freq = hpt374_read_freq(dev);
@@ -909,10 +953,10 @@ static int hpt37x_init_one(struct pci_de
 		u8 sr;
 		u32 total = 0;
 
-		printk(KERN_WARNING "pata_hpt37x: BIOS has not set timing clocks.\n");
+		pr_warning(DRV_NAME ": BIOS has not set timing clocks.\n");
 
 		/* This is the process the HPT371 BIOS is reported to use */
-		for(i = 0; i < 128; i++) {
+		for (i = 0; i < 128; i++) {
 			pci_read_config_byte(dev, 0x78, &sr);
 			total += sr & 0x1FF;
 			udelay(15);
@@ -947,20 +991,25 @@ static int hpt37x_init_one(struct pci_de
 
 		/* Select the DPLL clock. */
 		pci_write_config_byte(dev, 0x5b, 0x21);
-		pci_write_config_dword(dev, 0x5C, (f_high << 16) | f_low | 0x100);
+		pci_write_config_dword(dev, 0x5C,
+				       (f_high << 16) | f_low | 0x100);
 
-		for(adjust = 0; adjust < 8; adjust++) {
+		for (adjust = 0; adjust < 8; adjust++) {
 			if (hpt37x_calibrate_dpll(dev))
 				break;
-			/* See if it'll settle at a fractionally different clock */
+			/*
+			 * See if it'll settle at a fractionally
+			 * different clock
+			 */
 			if (adjust & 1)
 				f_low -= adjust >> 1;
 			else
 				f_high += adjust >> 1;
-			pci_write_config_dword(dev, 0x5C, (f_high << 16) | f_low | 0x100);
+			pci_write_config_dword(dev, 0x5C,
+					       (f_high << 16) | f_low | 0x100);
 		}
 		if (adjust == 8) {
-			printk(KERN_ERR "pata_hpt37x: DPLL did not stabilize!\n");
+			pr_err(DRV_NAME ": DPLL did not stabilize!\n");
 			return -ENODEV;
 		}
 		if (dpll == 3)
@@ -968,22 +1017,23 @@ static int hpt37x_init_one(struct pci_de
 		else
 			private_data = (void *)hpt37x_timings_50;
 
-		printk(KERN_INFO "pata_hpt37x: bus clock %dMHz, using %dMHz DPLL.\n",
-		       MHz[clock_slot], MHz[dpll]);
+		pr_info(DRV_NAME ": bus clock %dMHz, using %dMHz DPLL.\n",
+			MHz[clock_slot], MHz[dpll]);
 	} else {
 		private_data = (void *)chip_table->clocks[clock_slot];
 		/*
 		 *	Perform a final fixup. Note that we will have used the
 		 *	DPLL on the HPT372 which means we don't have to worry
 		 *	about lack of UDMA133 support on lower clocks
- 		 */
+		 */
 
 		if (clock_slot < 2 && ppi[0] == &info_hpt370)
 			ppi[0] = &info_hpt370_33;
 		if (clock_slot < 2 && ppi[0] == &info_hpt370a)
 			ppi[0] = &info_hpt370a_33;
-		printk(KERN_INFO "pata_hpt37x: %s using %dMHz bus clock.\n",
-		       chip_table->name, MHz[clock_slot]);
+
+		pr_info(DRV_NAME ": %s using %dMHz bus clock.\n",
+			chip_table->name, MHz[clock_slot]);
 	}
 
 	/* Now kick off ATA set up */
@@ -1001,9 +1051,9 @@ static const struct pci_device_id hpt37x
 };
 
 static struct pci_driver hpt37x_pci_driver = {
-	.name 		= DRV_NAME,
+	.name		= DRV_NAME,
 	.id_table	= hpt37x,
-	.probe 		= hpt37x_init_one,
+	.probe		= hpt37x_init_one,
 	.remove		= ata_pci_remove_one
 };
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/ata/pata_hpt3x2n.c linux-libre-2.6.38-gnu1/drivers/ata/pata_hpt3x2n.c
--- linux-libre-2.6.37-gnu1/drivers/ata/pata_hpt3x2n.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/ata/pata_hpt3x2n.c	2011-03-14 21:20:32.000000000 -0400
@@ -1,5 +1,5 @@
 /*
- * Libata driver for the highpoint 372N and 302N UDMA66 ATA controllers.
+ * Libata driver for the HighPoint 371N, 372N, and 302N UDMA66 ATA controllers.
  *
  * This driver is heavily based upon:
  *
@@ -8,7 +8,7 @@
  * Copyright (C) 1999-2003		Andre Hedrick <andre@linux-ide.org>
  * Portions Copyright (C) 2001	        Sun Microsystems, Inc.
  * Portions Copyright (C) 2003		Red Hat Inc
- * Portions Copyright (C) 2005-2009	MontaVista Software, Inc.
+ * Portions Copyright (C) 2005-2010	MontaVista Software, Inc.
  *
  *
  * TODO
@@ -25,7 +25,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME	"pata_hpt3x2n"
-#define DRV_VERSION	"0.3.10"
+#define DRV_VERSION	"0.3.14"
 
 enum {
 	HPT_PCI_FAST	=	(1 << 31),
@@ -103,7 +103,7 @@ static u32 hpt3x2n_find_mode(struct ata_
 {
 	struct hpt_clock *clocks = hpt3x2n_clocks;
 
-	while(clocks->xfer_speed) {
+	while (clocks->xfer_speed) {
 		if (clocks->xfer_speed == speed)
 			return clocks->timing;
 		clocks++;
@@ -113,6 +113,22 @@ static u32 hpt3x2n_find_mode(struct ata_
 }
 
 /**
+ *	hpt372n_filter	-	mode selection filter
+ *	@adev: ATA device
+ *	@mask: mode mask
+ *
+ *	The Marvell bridge chips used on the HighPoint SATA cards do not seem
+ *	to support the UltraDMA modes 1, 2, and 3 as well as any MWDMA modes...
+ */
+static unsigned long hpt372n_filter(struct ata_device *adev, unsigned long mask)
+{
+	if (ata_id_is_sata(adev->id))
+		mask &= ~((0xE << ATA_SHIFT_UDMA) | ATA_MASK_MWDMA);
+
+	return mask;
+}
+
+/**
  *	hpt3x2n_cable_detect	-	Detect the cable type
  *	@ap: ATA port to detect on
  *
@@ -153,6 +169,7 @@ static int hpt3x2n_pre_reset(struct ata_
 {
 	struct ata_port *ap = link->ap;
 	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+
 	/* Reset the state machine */
 	pci_write_config_byte(pdev, 0x50 + 4 * ap->port_no, 0x37);
 	udelay(100);
@@ -328,10 +345,10 @@ static struct scsi_host_template hpt3x2n
 };
 
 /*
- *	Configuration for HPT3x2n.
+ *	Configuration for HPT302N/371N.
  */
 
-static struct ata_port_operations hpt3x2n_port_ops = {
+static struct ata_port_operations hpt3xxn_port_ops = {
 	.inherits	= &ata_bmdma_port_ops,
 
 	.bmdma_stop	= hpt3x2n_bmdma_stop,
@@ -345,6 +362,15 @@ static struct ata_port_operations hpt3x2
 	.prereset	= hpt3x2n_pre_reset,
 };
 
+/*
+ *	Configuration for HPT372N. Same as 302N/371N but we have a mode filter.
+ */
+
+static struct ata_port_operations hpt372n_port_ops = {
+	.inherits	= &hpt3xxn_port_ops,
+	.mode_filter	= &hpt372n_filter,
+};
+
 /**
  *	hpt3xn_calibrate_dpll		-	Calibrate the DPLL loop
  *	@dev: PCI device
@@ -359,12 +385,12 @@ static int hpt3xn_calibrate_dpll(struct
 	u32 reg5c;
 	int tries;
 
-	for(tries = 0; tries < 0x5000; tries++) {
+	for (tries = 0; tries < 0x5000; tries++) {
 		udelay(50);
 		pci_read_config_byte(dev, 0x5b, &reg5b);
 		if (reg5b & 0x80) {
 			/* See if it stays set */
-			for(tries = 0; tries < 0x1000; tries ++) {
+			for (tries = 0; tries < 0x1000; tries++) {
 				pci_read_config_byte(dev, 0x5b, &reg5b);
 				/* Failed ? */
 				if ((reg5b & 0x80) == 0)
@@ -372,7 +398,7 @@ static int hpt3xn_calibrate_dpll(struct
 			}
 			/* Turn off tuning, we have the DPLL set */
 			pci_read_config_dword(dev, 0x5c, &reg5c);
-			pci_write_config_dword(dev, 0x5c, reg5c & ~ 0x100);
+			pci_write_config_dword(dev, 0x5c, reg5c & ~0x100);
 			return 1;
 		}
 	}
@@ -388,8 +414,19 @@ static int hpt3x2n_pci_clock(struct pci_
 
 	fcnt = inl(iobase + 0x90);	/* Not PCI readable for some chips */
 	if ((fcnt >> 12) != 0xABCDE) {
-		printk(KERN_WARNING "hpt3xn: BIOS clock data not set.\n");
-		return 33;	/* Not BIOS set */
+		int i;
+		u16 sr;
+		u32 total = 0;
+
+		pr_warning(DRV_NAME ": BIOS clock data not set.\n");
+
+		/* This is the process the HPT371 BIOS is reported to use */
+		for (i = 0; i < 128; i++) {
+			pci_read_config_word(pdev, 0x78, &sr);
+			total += sr & 0x1FF;
+			udelay(15);
+		}
+		fcnt = total / 128;
 	}
 	fcnt &= 0x1FF;
 
@@ -431,21 +468,27 @@ static int hpt3x2n_pci_clock(struct pci_
  *	HPT372N			9 (HPT372N)	*	UDMA133
  *
  *	(1) UDMA133 support depends on the bus clock
- *
- *	To pin down		HPT371N
  */
 
 static int hpt3x2n_init_one(struct pci_dev *dev, const struct pci_device_id *id)
 {
-	/* HPT372N and friends - UDMA133 */
-	static const struct ata_port_info info = {
+	/* HPT372N - UDMA133 */
+	static const struct ata_port_info info_hpt372n = {
 		.flags = ATA_FLAG_SLAVE_POSS,
 		.pio_mask = ATA_PIO4,
 		.mwdma_mask = ATA_MWDMA2,
 		.udma_mask = ATA_UDMA6,
-		.port_ops = &hpt3x2n_port_ops
+		.port_ops = &hpt372n_port_ops
 	};
-	const struct ata_port_info *ppi[] = { &info, NULL };
+	/* HPT302N and HPT371N - UDMA133 */
+	static const struct ata_port_info info_hpt3xxn = {
+		.flags = ATA_FLAG_SLAVE_POSS,
+		.pio_mask = ATA_PIO4,
+		.mwdma_mask = ATA_MWDMA2,
+		.udma_mask = ATA_UDMA6,
+		.port_ops = &hpt3xxn_port_ops
+	};
+	const struct ata_port_info *ppi[] = { &info_hpt3xxn, NULL };
 	u8 rev = dev->revision;
 	u8 irqmask;
 	unsigned int pci_mhz;
@@ -459,30 +502,35 @@ static int hpt3x2n_init_one(struct pci_d
 	if (rc)
 		return rc;
 
-	switch(dev->device) {
-		case PCI_DEVICE_ID_TTI_HPT366:
-			if (rev < 6)
-				return -ENODEV;
-			break;
-		case PCI_DEVICE_ID_TTI_HPT371:
-			if (rev < 2)
-				return -ENODEV;
-			/* 371N if rev > 1 */
-			break;
-		case PCI_DEVICE_ID_TTI_HPT372:
-			/* 372N if rev >= 2*/
-			if (rev < 2)
-				return -ENODEV;
-			break;
-		case PCI_DEVICE_ID_TTI_HPT302:
-			if (rev < 2)
-				return -ENODEV;
-			break;
-		case PCI_DEVICE_ID_TTI_HPT372N:
-			break;
-		default:
-			printk(KERN_ERR "pata_hpt3x2n: PCI table is bogus please report (%d).\n", dev->device);
+	switch (dev->device) {
+	case PCI_DEVICE_ID_TTI_HPT366:
+		/* 372N if rev >= 6 */
+		if (rev < 6)
 			return -ENODEV;
+		goto hpt372n;
+	case PCI_DEVICE_ID_TTI_HPT371:
+		/* 371N if rev >= 2 */
+		if (rev < 2)
+			return -ENODEV;
+		break;
+	case PCI_DEVICE_ID_TTI_HPT372:
+		/* 372N if rev >= 2 */
+		if (rev < 2)
+			return -ENODEV;
+		goto hpt372n;
+	case PCI_DEVICE_ID_TTI_HPT302:
+		/* 302N if rev >= 2 */
+		if (rev < 2)
+			return -ENODEV;
+		break;
+	case PCI_DEVICE_ID_TTI_HPT372N:
+hpt372n:
+		ppi[0] = &info_hpt372n;
+		break;
+	default:
+		pr_err(DRV_NAME ": PCI table is bogus, please report (%d).\n",
+		       dev->device);
+		return -ENODEV;
 	}
 
 	/* Ok so this is a chip we support */
@@ -509,8 +557,10 @@ static int hpt3x2n_init_one(struct pci_d
 		pci_write_config_byte(dev, 0x50, mcr1);
 	}
 
-	/* Tune the PLL. HPT recommend using 75 for SATA, 66 for UDMA133 or
-	   50 for UDMA100. Right now we always use 66 */
+	/*
+	 * Tune the PLL. HPT recommend using 75 for SATA, 66 for UDMA133 or
+	 * 50 for UDMA100. Right now we always use 66
+	 */
 
 	pci_mhz = hpt3x2n_pci_clock(dev);
 
@@ -522,20 +572,22 @@ static int hpt3x2n_init_one(struct pci_d
 	pci_write_config_byte(dev, 0x5B, 0x21);
 
 	/* Unlike the 37x we don't try jiggling the frequency */
-	for(adjust = 0; adjust < 8; adjust++) {
+	for (adjust = 0; adjust < 8; adjust++) {
 		if (hpt3xn_calibrate_dpll(dev))
 			break;
 		pci_write_config_dword(dev, 0x5C, (f_high << 16) | f_low);
 	}
 	if (adjust == 8) {
-		printk(KERN_ERR "pata_hpt3x2n: DPLL did not stabilize!\n");
+		pr_err(DRV_NAME ": DPLL did not stabilize!\n");
 		return -ENODEV;
 	}
 
-	printk(KERN_INFO "pata_hpt37x: bus clock %dMHz, using 66MHz DPLL.\n",
-	       pci_mhz);
-	/* Set our private data up. We only need a few flags so we use
-	   it directly */
+	pr_info(DRV_NAME ": bus clock %dMHz, using 66MHz DPLL.\n", pci_mhz);
+
+	/*
+	 * Set our private data up. We only need a few flags
+	 * so we use it directly.
+	 */
 	if (pci_mhz > 60)
 		hpriv = (void *)(PCI66 | USE_DPLL);
 
@@ -562,9 +614,9 @@ static const struct pci_device_id hpt3x2
 };
 
 static struct pci_driver hpt3x2n_pci_driver = {
-	.name 		= DRV_NAME,
+	.name		= DRV_NAME,
 	.id_table	= hpt3x2n,
-	.probe 		= hpt3x2n_init_one,
+	.probe		= hpt3x2n_init_one,
 	.remove		= ata_pci_remove_one
 };
 
@@ -579,7 +631,7 @@ static void __exit hpt3x2n_exit(void)
 }
 
 MODULE_AUTHOR("Alan Cox");
-MODULE_DESCRIPTION("low-level driver for the Highpoint HPT3x2n/30x");
+MODULE_DESCRIPTION("low-level driver for the Highpoint HPT3xxN");
 MODULE_LICENSE("GPL");
 MODULE_DEVICE_TABLE(pci, hpt3x2n);
 MODULE_VERSION(DRV_VERSION);
diff -druNp linux-libre-2.6.37-gnu1/drivers/ata/pata_mpc52xx.c linux-libre-2.6.38-gnu1/drivers/ata/pata_mpc52xx.c
--- linux-libre-2.6.37-gnu1/drivers/ata/pata_mpc52xx.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/ata/pata_mpc52xx.c	2011-03-14 21:20:32.000000000 -0400
@@ -610,7 +610,7 @@ static struct scsi_host_template mpc52xx
 };
 
 static struct ata_port_operations mpc52xx_ata_port_ops = {
-	.inherits		= &ata_sff_port_ops,
+	.inherits		= &ata_bmdma_port_ops,
 	.sff_dev_select		= mpc52xx_ata_dev_select,
 	.set_piomode		= mpc52xx_ata_set_piomode,
 	.set_dmamode		= mpc52xx_ata_set_dmamode,
diff -druNp linux-libre-2.6.37-gnu1/drivers/ata/sata_vsc.c linux-libre-2.6.38-gnu1/drivers/ata/sata_vsc.c
--- linux-libre-2.6.37-gnu1/drivers/ata/sata_vsc.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/ata/sata_vsc.c	2011-03-14 21:20:32.000000000 -0400
@@ -370,7 +370,7 @@ static int __devinit vsc_sata_init_one(s
 	if (pci_resource_len(pdev, 0) == 0)
 		return -ENODEV;
 
-	/* map IO regions and intialize host accordingly */
+	/* map IO regions and initialize host accordingly */
 	rc = pcim_iomap_regions(pdev, 1 << VSC_MMIO_BAR, DRV_NAME);
 	if (rc == -EBUSY)
 		pcim_pin_device(pdev);
diff -druNp linux-libre-2.6.37-gnu1/drivers/atm/ambassador.c linux-libre-2.6.38-gnu1/drivers/atm/ambassador.c
--- linux-libre-2.6.37-gnu1/drivers/atm/ambassador.c	2013-05-03 03:54:04.000000000 -0400
+++ linux-libre-2.6.38-gnu1/drivers/atm/ambassador.c	2013-05-03 01:52:59.000000000 -0400
@@ -1926,8 +1926,9 @@ static int __devinit ucode_init (loader_
   const struct firmware *fw;
   unsigned long start_address;
   const struct ihex_binrec *rec;
+  const char *errmsg = 0;
   int res;
-  
+
   res = reject_firmware(&fw, "/*(DEBLOBBED)*/", &dev->pci_dev->dev);
   if (res) {
     PRINTK (KERN_ERR, "Cannot load microcode data");
@@ -1937,8 +1938,8 @@ static int __devinit ucode_init (loader_
   /* First record contains just the start address */
   rec = (const struct ihex_binrec *)fw->data;
   if (be16_to_cpu(rec->len) != sizeof(__be32) || be32_to_cpu(rec->addr)) {
-    PRINTK (KERN_ERR, "Bad microcode data (no start record)");
-    return -EINVAL;
+    errmsg = "no start record";
+    goto fail;
   }
   start_address = be32_to_cpup((__be32 *)rec->data);
 
@@ -1950,12 +1951,12 @@ static int __devinit ucode_init (loader_
     PRINTD (DBG_LOAD, "starting region (%x, %u)", be32_to_cpu(rec->addr),
 	    be16_to_cpu(rec->len));
     if (be16_to_cpu(rec->len) > 4 * MAX_TRANSFER_DATA) {
-	    PRINTK (KERN_ERR, "Bad microcode data (record too long)");
-	    return -EINVAL;
+	    errmsg = "record too long";
+	    goto fail;
     }
     if (be16_to_cpu(rec->len) & 3) {
-	    PRINTK (KERN_ERR, "Bad microcode data (odd number of bytes)");
-	    return -EINVAL;
+	    errmsg = "odd number of bytes";
+	    goto fail;
     }
     res = loader_write(lb, dev, rec);
     if (res)
@@ -1970,6 +1971,10 @@ static int __devinit ucode_init (loader_
     res = loader_start(lb, dev, start_address);
 
   return res;
+fail:
+  release_firmware(fw);
+  PRINTK(KERN_ERR, "Bad microcode data (%s)", errmsg);
+  return -EINVAL;
 }
 
 /********** give adapter parameters **********/
diff -druNp linux-libre-2.6.37-gnu1/drivers/atm/fore200e.c linux-libre-2.6.38-gnu1/drivers/atm/fore200e.c
--- linux-libre-2.6.37-gnu1/drivers/atm/fore200e.c	2013-05-03 03:54:11.000000000 -0400
+++ linux-libre-2.6.38-gnu1/drivers/atm/fore200e.c	2013-05-03 01:53:08.000000000 -0400
@@ -92,7 +92,7 @@
 
 #define FORE200E_INDEX(virt_addr, type, index)     (&((type *)(virt_addr))[ index ])
 
-#define FORE200E_NEXT_ENTRY(index, modulo)         (index = ++(index) % (modulo))
+#define FORE200E_NEXT_ENTRY(index, modulo)         (index = ((index) + 1) % (modulo))
 
 #if 1
 #define ASSERT(expr)     if (!(expr)) { \
diff -druNp linux-libre-2.6.37-gnu1/drivers/atm/idt77105.c linux-libre-2.6.38-gnu1/drivers/atm/idt77105.c
--- linux-libre-2.6.37-gnu1/drivers/atm/idt77105.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/atm/idt77105.c	2011-03-14 21:20:32.000000000 -0400
@@ -151,7 +151,7 @@ static int fetch_stats(struct atm_dev *d
 	spin_unlock_irqrestore(&idt77105_priv_lock, flags);
 	if (arg == NULL)
 		return 0;
-	return copy_to_user(arg, &PRIV(dev)->stats,
+	return copy_to_user(arg, &stats,
 		    sizeof(struct idt77105_stats)) ? -EFAULT : 0;
 }
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/atm/idt77252.h linux-libre-2.6.38-gnu1/drivers/atm/idt77252.h
--- linux-libre-2.6.37-gnu1/drivers/atm/idt77252.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/atm/idt77252.h	2011-03-14 21:20:32.000000000 -0400
@@ -572,7 +572,7 @@ struct idt77252_dev
 #define SAR_STAT_TSQF       0x00001000 /* Transmit Status Queue full      */
 #define SAR_STAT_TMROF      0x00000800 /* Timer overflow                  */
 #define SAR_STAT_PHYI       0x00000400 /* PHY device Interrupt flag       */
-#define SAR_STAT_CMDBZ      0x00000200 /* ABR SAR Comand Busy Flag        */
+#define SAR_STAT_CMDBZ      0x00000200 /* ABR SAR Command Busy Flag       */
 #define SAR_STAT_FBQ3A      0x00000100 /* Free Buffer Queue 3 Attention   */
 #define SAR_STAT_FBQ2A      0x00000080 /* Free Buffer Queue 2 Attention   */
 #define SAR_STAT_RSQF       0x00000040 /* Receive Status Queue full       */
diff -druNp linux-libre-2.6.37-gnu1/drivers/atm/iphase.c linux-libre-2.6.38-gnu1/drivers/atm/iphase.c
--- linux-libre-2.6.37-gnu1/drivers/atm/iphase.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/atm/iphase.c	2011-03-14 21:20:32.000000000 -0400
@@ -2063,7 +2063,7 @@ static int tx_init(struct atm_dev *dev)
 		- UBR Table size is 4K  
 		- UBR wait queue is 4K  
 	   since the table and wait queues are contiguous, all the bytes   
-	   can be initialized by one memeset.  
+	   can be initialized by one memeset.
 	*/  
         
         vcsize_sel = 0;
@@ -2089,7 +2089,7 @@ static int tx_init(struct atm_dev *dev)
 		- ABR Table size is 2K  
 		- ABR wait queue is 2K  
 	   since the table and wait queues are contiguous, all the bytes   
-	   can be intialized by one memeset.  
+	   can be initialized by one memeset.
 	*/  
         i = ABR_SCHED_TABLE * iadev->memSize;
         writew((i >> 11) & 0xffff, iadev->seg_reg+ABR_SBPTR_BASE);
diff -druNp linux-libre-2.6.37-gnu1/drivers/atm/lanai.c linux-libre-2.6.38-gnu1/drivers/atm/lanai.c
--- linux-libre-2.6.37-gnu1/drivers/atm/lanai.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/atm/lanai.c	2011-03-14 21:20:32.000000000 -0400
@@ -2241,11 +2241,8 @@ static int __devinit lanai_dev_open(stru
 	memcpy(atmdev->esi, eeprom_mac(lanai), ESI_LEN);
 	lanai_timed_poll_start(lanai);
 	printk(KERN_NOTICE DEV_LABEL "(itf %d): rev.%d, base=0x%lx, irq=%u "
-	    "(%02X-%02X-%02X-%02X-%02X-%02X)\n", lanai->number,
-	    (int) lanai->pci->revision, (unsigned long) lanai->base,
-	    lanai->pci->irq,
-	    atmdev->esi[0], atmdev->esi[1], atmdev->esi[2],
-	    atmdev->esi[3], atmdev->esi[4], atmdev->esi[5]);
+		"(%pMF)\n", lanai->number, (int) lanai->pci->revision,
+		(unsigned long) lanai->base, lanai->pci->irq, atmdev->esi);
 	printk(KERN_NOTICE DEV_LABEL "(itf %d): LANAI%s, serialno=%u(0x%X), "
 	    "board_rev=%d\n", lanai->number,
 	    lanai->type==lanai2 ? "2" : "HB", (unsigned int) lanai->serialno,
diff -druNp linux-libre-2.6.37-gnu1/drivers/atm/solos-pci.c linux-libre-2.6.38-gnu1/drivers/atm/solos-pci.c
--- linux-libre-2.6.37-gnu1/drivers/atm/solos-pci.c	2013-05-03 03:54:22.000000000 -0400
+++ linux-libre-2.6.38-gnu1/drivers/atm/solos-pci.c	2013-05-03 01:53:20.000000000 -0400
@@ -864,8 +864,9 @@ static int popen(struct atm_vcc *vcc)
 	}
 
 	skb = alloc_skb(sizeof(*header), GFP_ATOMIC);
-	if (!skb && net_ratelimit()) {
-		dev_warn(&card->dev->dev, "Failed to allocate sk_buff in popen()\n");
+	if (!skb) {
+		if (net_ratelimit())
+			dev_warn(&card->dev->dev, "Failed to allocate sk_buff in popen()\n");
 		return -ENOMEM;
 	}
 	header = (void *)skb_put(skb, sizeof(*header));
diff -druNp linux-libre-2.6.37-gnu1/drivers/base/base.h linux-libre-2.6.38-gnu1/drivers/base/base.h
--- linux-libre-2.6.37-gnu1/drivers/base/base.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/base/base.h	2011-03-14 21:20:32.000000000 -0400
@@ -1,31 +1,46 @@
 
 /**
- * struct bus_type_private - structure to hold the private to the driver core portions of the bus_type structure.
+ * struct subsys_private - structure to hold the private to the driver core portions of the bus_type/class structure.
  *
- * @subsys - the struct kset that defines this bus.  This is the main kobject
- * @drivers_kset - the list of drivers associated with this bus
- * @devices_kset - the list of devices associated with this bus
+ * @subsys - the struct kset that defines this subsystem
+ * @devices_kset - the list of devices associated
+ *
+ * @drivers_kset - the list of drivers associated
  * @klist_devices - the klist to iterate over the @devices_kset
  * @klist_drivers - the klist to iterate over the @drivers_kset
  * @bus_notifier - the bus notifier list for anything that cares about things
- * on this bus.
+ *                 on this bus.
  * @bus - pointer back to the struct bus_type that this structure is associated
- * with.
+ *        with.
+ *
+ * @class_interfaces - list of class_interfaces associated
+ * @glue_dirs - "glue" directory to put in-between the parent device to
+ *              avoid namespace conflicts
+ * @class_mutex - mutex to protect the children, devices, and interfaces lists.
+ * @class - pointer back to the struct class that this structure is associated
+ *          with.
  *
  * This structure is the one that is the actual kobject allowing struct
- * bus_type to be statically allocated safely.  Nothing outside of the driver
- * core should ever touch these fields.
+ * bus_type/class to be statically allocated safely.  Nothing outside of the
+ * driver core should ever touch these fields.
  */
-struct bus_type_private {
+struct subsys_private {
 	struct kset subsys;
-	struct kset *drivers_kset;
 	struct kset *devices_kset;
+
+	struct kset *drivers_kset;
 	struct klist klist_devices;
 	struct klist klist_drivers;
 	struct blocking_notifier_head bus_notifier;
 	unsigned int drivers_autoprobe:1;
 	struct bus_type *bus;
+
+	struct list_head class_interfaces;
+	struct kset glue_dirs;
+	struct mutex class_mutex;
+	struct class *class;
 };
+#define to_subsys_private(obj) container_of(obj, struct subsys_private, subsys.kobj)
 
 struct driver_private {
 	struct kobject kobj;
@@ -36,33 +51,6 @@ struct driver_private {
 };
 #define to_driver(obj) container_of(obj, struct driver_private, kobj)
 
-
-/**
- * struct class_private - structure to hold the private to the driver core portions of the class structure.
- *
- * @class_subsys - the struct kset that defines this class.  This is the main kobject
- * @class_devices - list of devices associated with this class
- * @class_interfaces - list of class_interfaces associated with this class
- * @class_dirs - "glue" directory for virtual devices associated with this class
- * @class_mutex - mutex to protect the children, devices, and interfaces lists.
- * @class - pointer back to the struct class that this structure is associated
- * with.
- *
- * This structure is the one that is the actual kobject allowing struct
- * class to be statically allocated safely.  Nothing outside of the driver
- * core should ever touch these fields.
- */
-struct class_private {
-	struct kset class_subsys;
-	struct klist class_devices;
-	struct list_head class_interfaces;
-	struct kset class_dirs;
-	struct mutex class_mutex;
-	struct class *class;
-};
-#define to_class(obj)	\
-	container_of(obj, struct class_private, class_subsys.kobj)
-
 /**
  * struct device_private - structure to hold the private to the driver core portions of the device structure.
  *
diff -druNp linux-libre-2.6.37-gnu1/drivers/base/bus.c linux-libre-2.6.38-gnu1/drivers/base/bus.c
--- linux-libre-2.6.37-gnu1/drivers/base/bus.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/base/bus.c	2011-03-14 21:20:32.000000000 -0400
@@ -20,7 +20,6 @@
 #include "power/power.h"
 
 #define to_bus_attr(_attr) container_of(_attr, struct bus_attribute, attr)
-#define to_bus(obj) container_of(obj, struct bus_type_private, subsys.kobj)
 
 /*
  * sysfs bindings for drivers
@@ -96,11 +95,11 @@ static ssize_t bus_attr_show(struct kobj
 			     char *buf)
 {
 	struct bus_attribute *bus_attr = to_bus_attr(attr);
-	struct bus_type_private *bus_priv = to_bus(kobj);
+	struct subsys_private *subsys_priv = to_subsys_private(kobj);
 	ssize_t ret = 0;
 
 	if (bus_attr->show)
-		ret = bus_attr->show(bus_priv->bus, buf);
+		ret = bus_attr->show(subsys_priv->bus, buf);
 	return ret;
 }
 
@@ -108,11 +107,11 @@ static ssize_t bus_attr_store(struct kob
 			      const char *buf, size_t count)
 {
 	struct bus_attribute *bus_attr = to_bus_attr(attr);
-	struct bus_type_private *bus_priv = to_bus(kobj);
+	struct subsys_private *subsys_priv = to_subsys_private(kobj);
 	ssize_t ret = 0;
 
 	if (bus_attr->store)
-		ret = bus_attr->store(bus_priv->bus, buf, count);
+		ret = bus_attr->store(subsys_priv->bus, buf, count);
 	return ret;
 }
 
@@ -858,9 +857,9 @@ static BUS_ATTR(uevent, S_IWUSR, NULL, b
 int bus_register(struct bus_type *bus)
 {
 	int retval;
-	struct bus_type_private *priv;
+	struct subsys_private *priv;
 
-	priv = kzalloc(sizeof(struct bus_type_private), GFP_KERNEL);
+	priv = kzalloc(sizeof(struct subsys_private), GFP_KERNEL);
 	if (!priv)
 		return -ENOMEM;
 
@@ -976,7 +975,7 @@ struct klist *bus_get_device_klist(struc
 EXPORT_SYMBOL_GPL(bus_get_device_klist);
 
 /*
- * Yes, this forcably breaks the klist abstraction temporarily.  It
+ * Yes, this forcibly breaks the klist abstraction temporarily.  It
  * just wants to sort the klist, not change reference counts and
  * take/drop locks rapidly in the process.  It does all this while
  * holding the lock for the list, so objects can't otherwise be
diff -druNp linux-libre-2.6.37-gnu1/drivers/base/class.c linux-libre-2.6.38-gnu1/drivers/base/class.c
--- linux-libre-2.6.37-gnu1/drivers/base/class.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/base/class.c	2011-03-14 21:20:32.000000000 -0400
@@ -27,7 +27,7 @@ static ssize_t class_attr_show(struct ko
 			       char *buf)
 {
 	struct class_attribute *class_attr = to_class_attr(attr);
-	struct class_private *cp = to_class(kobj);
+	struct subsys_private *cp = to_subsys_private(kobj);
 	ssize_t ret = -EIO;
 
 	if (class_attr->show)
@@ -39,7 +39,7 @@ static ssize_t class_attr_store(struct k
 				const char *buf, size_t count)
 {
 	struct class_attribute *class_attr = to_class_attr(attr);
-	struct class_private *cp = to_class(kobj);
+	struct subsys_private *cp = to_subsys_private(kobj);
 	ssize_t ret = -EIO;
 
 	if (class_attr->store)
@@ -49,7 +49,7 @@ static ssize_t class_attr_store(struct k
 
 static void class_release(struct kobject *kobj)
 {
-	struct class_private *cp = to_class(kobj);
+	struct subsys_private *cp = to_subsys_private(kobj);
 	struct class *class = cp->class;
 
 	pr_debug("class '%s': release.\n", class->name);
@@ -65,7 +65,7 @@ static void class_release(struct kobject
 
 static const struct kobj_ns_type_operations *class_child_ns_type(struct kobject *kobj)
 {
-	struct class_private *cp = to_class(kobj);
+	struct subsys_private *cp = to_subsys_private(kobj);
 	struct class *class = cp->class;
 
 	return class->ns_type;
@@ -82,7 +82,7 @@ static struct kobj_type class_ktype = {
 	.child_ns_type	= class_child_ns_type,
 };
 
-/* Hotplug events for classes go to the class class_subsys */
+/* Hotplug events for classes go to the class subsys */
 static struct kset *class_kset;
 
 
@@ -90,7 +90,7 @@ int class_create_file(struct class *cls,
 {
 	int error;
 	if (cls)
-		error = sysfs_create_file(&cls->p->class_subsys.kobj,
+		error = sysfs_create_file(&cls->p->subsys.kobj,
 					  &attr->attr);
 	else
 		error = -EINVAL;
@@ -100,20 +100,20 @@ int class_create_file(struct class *cls,
 void class_remove_file(struct class *cls, const struct class_attribute *attr)
 {
 	if (cls)
-		sysfs_remove_file(&cls->p->class_subsys.kobj, &attr->attr);
+		sysfs_remove_file(&cls->p->subsys.kobj, &attr->attr);
 }
 
 static struct class *class_get(struct class *cls)
 {
 	if (cls)
-		kset_get(&cls->p->class_subsys);
+		kset_get(&cls->p->subsys);
 	return cls;
 }
 
 static void class_put(struct class *cls)
 {
 	if (cls)
-		kset_put(&cls->p->class_subsys);
+		kset_put(&cls->p->subsys);
 }
 
 static int add_class_attrs(struct class *cls)
@@ -162,7 +162,7 @@ static void klist_class_dev_put(struct k
 
 int __class_register(struct class *cls, struct lock_class_key *key)
 {
-	struct class_private *cp;
+	struct subsys_private *cp;
 	int error;
 
 	pr_debug("device class '%s': registering\n", cls->name);
@@ -170,11 +170,11 @@ int __class_register(struct class *cls,
 	cp = kzalloc(sizeof(*cp), GFP_KERNEL);
 	if (!cp)
 		return -ENOMEM;
-	klist_init(&cp->class_devices, klist_class_dev_get, klist_class_dev_put);
+	klist_init(&cp->klist_devices, klist_class_dev_get, klist_class_dev_put);
 	INIT_LIST_HEAD(&cp->class_interfaces);
-	kset_init(&cp->class_dirs);
+	kset_init(&cp->glue_dirs);
 	__mutex_init(&cp->class_mutex, "struct class mutex", key);
-	error = kobject_set_name(&cp->class_subsys.kobj, "%s", cls->name);
+	error = kobject_set_name(&cp->subsys.kobj, "%s", cls->name);
 	if (error) {
 		kfree(cp);
 		return error;
@@ -187,15 +187,15 @@ int __class_register(struct class *cls,
 #if defined(CONFIG_BLOCK)
 	/* let the block class directory show up in the root of sysfs */
 	if (!sysfs_deprecated || cls != &block_class)
-		cp->class_subsys.kobj.kset = class_kset;
+		cp->subsys.kobj.kset = class_kset;
 #else
-	cp->class_subsys.kobj.kset = class_kset;
+	cp->subsys.kobj.kset = class_kset;
 #endif
-	cp->class_subsys.kobj.ktype = &class_ktype;
+	cp->subsys.kobj.ktype = &class_ktype;
 	cp->class = cls;
 	cls->p = cp;
 
-	error = kset_register(&cp->class_subsys);
+	error = kset_register(&cp->subsys);
 	if (error) {
 		kfree(cp);
 		return error;
@@ -210,7 +210,7 @@ void class_unregister(struct class *cls)
 {
 	pr_debug("device class '%s': unregistering\n", cls->name);
 	remove_class_attrs(cls);
-	kset_unregister(&cls->p->class_subsys);
+	kset_unregister(&cls->p->subsys);
 }
 
 static void class_create_release(struct class *cls)
@@ -295,7 +295,7 @@ void class_dev_iter_init(struct class_de
 
 	if (start)
 		start_knode = &start->knode_class;
-	klist_iter_init_node(&class->p->class_devices, &iter->ki, start_knode);
+	klist_iter_init_node(&class->p->klist_devices, &iter->ki, start_knode);
 	iter->type = type;
 }
 EXPORT_SYMBOL_GPL(class_dev_iter_init);
@@ -482,8 +482,8 @@ void class_interface_unregister(struct c
 	class_put(parent);
 }
 
-ssize_t show_class_attr_string(struct class *class, struct class_attribute *attr,
-                        	char *buf)
+ssize_t show_class_attr_string(struct class *class,
+			       struct class_attribute *attr, char *buf)
 {
 	struct class_attribute_string *cs;
 	cs = container_of(attr, struct class_attribute_string, attr);
diff -druNp linux-libre-2.6.37-gnu1/drivers/base/core.c linux-libre-2.6.38-gnu1/drivers/base/core.c
--- linux-libre-2.6.37-gnu1/drivers/base/core.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/base/core.c	2011-03-14 21:20:32.000000000 -0400
@@ -338,6 +338,35 @@ static void device_remove_attributes(str
 			device_remove_file(dev, &attrs[i]);
 }
 
+static int device_add_bin_attributes(struct device *dev,
+				     struct bin_attribute *attrs)
+{
+	int error = 0;
+	int i;
+
+	if (attrs) {
+		for (i = 0; attr_name(attrs[i]); i++) {
+			error = device_create_bin_file(dev, &attrs[i]);
+			if (error)
+				break;
+		}
+		if (error)
+			while (--i >= 0)
+				device_remove_bin_file(dev, &attrs[i]);
+	}
+	return error;
+}
+
+static void device_remove_bin_attributes(struct device *dev,
+					 struct bin_attribute *attrs)
+{
+	int i;
+
+	if (attrs)
+		for (i = 0; attr_name(attrs[i]); i++)
+			device_remove_bin_file(dev, &attrs[i]);
+}
+
 static int device_add_groups(struct device *dev,
 			     const struct attribute_group **groups)
 {
@@ -378,12 +407,15 @@ static int device_add_attrs(struct devic
 		error = device_add_attributes(dev, class->dev_attrs);
 		if (error)
 			return error;
+		error = device_add_bin_attributes(dev, class->dev_bin_attrs);
+		if (error)
+			goto err_remove_class_attrs;
 	}
 
 	if (type) {
 		error = device_add_groups(dev, type->groups);
 		if (error)
-			goto err_remove_class_attrs;
+			goto err_remove_class_bin_attrs;
 	}
 
 	error = device_add_groups(dev, dev->groups);
@@ -395,6 +427,9 @@ static int device_add_attrs(struct devic
  err_remove_type_groups:
 	if (type)
 		device_remove_groups(dev, type->groups);
+ err_remove_class_bin_attrs:
+	if (class)
+		device_remove_bin_attributes(dev, class->dev_bin_attrs);
  err_remove_class_attrs:
 	if (class)
 		device_remove_attributes(dev, class->dev_attrs);
@@ -412,8 +447,10 @@ static void device_remove_attrs(struct d
 	if (type)
 		device_remove_groups(dev, type->groups);
 
-	if (class)
+	if (class) {
 		device_remove_attributes(dev, class->dev_attrs);
+		device_remove_bin_attributes(dev, class->dev_bin_attrs);
+	}
 }
 
 
@@ -610,7 +647,7 @@ class_dir_create_and_add(struct class *c
 	dir->class = class;
 	kobject_init(&dir->kobj, &class_dir_ktype);
 
-	dir->kobj.kset = &class->p->class_dirs;
+	dir->kobj.kset = &class->p->glue_dirs;
 
 	retval = kobject_add(&dir->kobj, parent_kobj, "%s", class->name);
 	if (retval < 0) {
@@ -635,7 +672,7 @@ static struct kobject *get_device_parent
 		if (sysfs_deprecated && dev->class == &block_class) {
 			if (parent && parent->class == &block_class)
 				return &parent->kobj;
-			return &block_class.p->class_subsys.kobj;
+			return &block_class.p->subsys.kobj;
 		}
 #endif
 
@@ -654,13 +691,13 @@ static struct kobject *get_device_parent
 		mutex_lock(&gdp_mutex);
 
 		/* find our class-directory at the parent and reference it */
-		spin_lock(&dev->class->p->class_dirs.list_lock);
-		list_for_each_entry(k, &dev->class->p->class_dirs.list, entry)
+		spin_lock(&dev->class->p->glue_dirs.list_lock);
+		list_for_each_entry(k, &dev->class->p->glue_dirs.list, entry)
 			if (k->parent == parent_kobj) {
 				kobj = kobject_get(k);
 				break;
 			}
-		spin_unlock(&dev->class->p->class_dirs.list_lock);
+		spin_unlock(&dev->class->p->glue_dirs.list_lock);
 		if (kobj) {
 			mutex_unlock(&gdp_mutex);
 			return kobj;
@@ -682,7 +719,7 @@ static void cleanup_glue_dir(struct devi
 {
 	/* see if we live in a "glue" directory */
 	if (!glue_dir || !dev->class ||
-	    glue_dir->kset != &dev->class->p->class_dirs)
+	    glue_dir->kset != &dev->class->p->glue_dirs)
 		return;
 
 	kobject_put(glue_dir);
@@ -709,7 +746,7 @@ static int device_add_class_symlinks(str
 		return 0;
 
 	error = sysfs_create_link(&dev->kobj,
-				  &dev->class->p->class_subsys.kobj,
+				  &dev->class->p->subsys.kobj,
 				  "subsystem");
 	if (error)
 		goto out;
@@ -728,7 +765,7 @@ static int device_add_class_symlinks(str
 #endif
 
 	/* link in the class directory pointing to the device */
-	error = sysfs_create_link(&dev->class->p->class_subsys.kobj,
+	error = sysfs_create_link(&dev->class->p->subsys.kobj,
 				  &dev->kobj, dev_name(dev));
 	if (error)
 		goto out_device;
@@ -756,7 +793,7 @@ static void device_remove_class_symlinks
 	if (sysfs_deprecated && dev->class == &block_class)
 		return;
 #endif
-	sysfs_delete_link(&dev->class->p->class_subsys.kobj, &dev->kobj, dev_name(dev));
+	sysfs_delete_link(&dev->class->p->subsys.kobj, &dev->kobj, dev_name(dev));
 }
 
 /**
@@ -947,7 +984,7 @@ int device_add(struct device *dev)
 		mutex_lock(&dev->class->p->class_mutex);
 		/* tie the class to the device */
 		klist_add_tail(&dev->knode_class,
-			       &dev->class->p->class_devices);
+			       &dev->class->p->klist_devices);
 
 		/* notify any interfaces that the device is here */
 		list_for_each_entry(class_intf,
@@ -1513,6 +1550,8 @@ EXPORT_SYMBOL_GPL(device_destroy);
  * exclusion between two different calls of device_rename
  * on the same device to ensure that new_name is valid and
  * won't conflict with other devices.
+ *
+ * "Never use this function, bad things will happen" - gregkh
  */
 int device_rename(struct device *dev, const char *new_name)
 {
@@ -1535,7 +1574,7 @@ int device_rename(struct device *dev, co
 	}
 
 	if (dev->class) {
-		error = sysfs_rename_link(&dev->class->p->class_subsys.kobj,
+		error = sysfs_rename_link(&dev->class->p->subsys.kobj,
 			&dev->kobj, old_device_name, new_name);
 		if (error)
 			goto out;
diff -druNp linux-libre-2.6.37-gnu1/drivers/base/Kconfig linux-libre-2.6.38-gnu1/drivers/base/Kconfig
--- linux-libre-2.6.37-gnu1/drivers/base/Kconfig	2013-05-03 04:06:50.000000000 -0400
+++ linux-libre-2.6.38-gnu1/drivers/base/Kconfig	2013-05-03 02:10:13.000000000 -0400
@@ -70,7 +70,7 @@ config PREVENT_FIRMWARE_BUILD
 	  If unsure say Y here.
 
 config FW_LOADER
-	tristate "Userspace firmware loading support" if EMBEDDED
+	tristate "Userspace firmware loading support" if EXPERT
 	default y
 	---help---
 	  This option is provided for the case where no in-kernel-tree modules
diff -druNp linux-libre-2.6.37-gnu1/drivers/base/node.c linux-libre-2.6.38-gnu1/drivers/base/node.c
--- linux-libre-2.6.37-gnu1/drivers/base/node.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/base/node.c	2011-03-14 21:20:32.000000000 -0400
@@ -117,12 +117,21 @@ static ssize_t node_read_meminfo(struct
 		       "Node %d WritebackTmp:   %8lu kB\n"
 		       "Node %d Slab:           %8lu kB\n"
 		       "Node %d SReclaimable:   %8lu kB\n"
-		       "Node %d SUnreclaim:     %8lu kB\n",
+		       "Node %d SUnreclaim:     %8lu kB\n"
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
+		       "Node %d AnonHugePages:  %8lu kB\n"
+#endif
+			,
 		       nid, K(node_page_state(nid, NR_FILE_DIRTY)),
 		       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)),
+		       nid, K(node_page_state(nid, NR_ANON_PAGES)
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
+			+ node_page_state(nid, NR_ANON_TRANSPARENT_HUGEPAGES) *
+			HPAGE_PMD_NR
+#endif
+		       ),
 		       nid, K(node_page_state(nid, NR_SHMEM)),
 		       nid, node_page_state(nid, NR_KERNEL_STACK) *
 				THREAD_SIZE / 1024,
@@ -133,7 +142,13 @@ 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)));
+		       nid, K(node_page_state(nid, NR_SLAB_UNRECLAIMABLE))
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
+			, nid,
+			K(node_page_state(nid, NR_ANON_TRANSPARENT_HUGEPAGES) *
+			HPAGE_PMD_NR)
+#endif
+		       );
 	n += hugetlb_report_node_meminfo(nid, buf + n);
 	return n;
 }
diff -druNp linux-libre-2.6.37-gnu1/drivers/base/power/generic_ops.c linux-libre-2.6.38-gnu1/drivers/base/power/generic_ops.c
--- linux-libre-2.6.37-gnu1/drivers/base/power/generic_ops.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/base/power/generic_ops.c	2011-03-14 21:20:32.000000000 -0400
@@ -39,7 +39,7 @@ EXPORT_SYMBOL_GPL(pm_generic_runtime_idl
  *
  * If PM operations are defined for the @dev's driver and they include
  * ->runtime_suspend(), execute it and return its error code.  Otherwise,
- * return -EINVAL.
+ * return 0.
  */
 int pm_generic_runtime_suspend(struct device *dev)
 {
@@ -58,7 +58,7 @@ EXPORT_SYMBOL_GPL(pm_generic_runtime_sus
  *
  * If PM operations are defined for the @dev's driver and they include
  * ->runtime_resume(), execute it and return its error code.  Otherwise,
- * return -EINVAL.
+ * return 0.
  */
 int pm_generic_runtime_resume(struct device *dev)
 {
@@ -185,7 +185,7 @@ static int __pm_generic_resume(struct de
 		return 0;
 
 	ret = callback(dev);
-	if (!ret) {
+	if (!ret && pm_runtime_enabled(dev)) {
 		pm_runtime_disable(dev);
 		pm_runtime_set_active(dev);
 		pm_runtime_enable(dev);
diff -druNp linux-libre-2.6.37-gnu1/drivers/base/power/main.c linux-libre-2.6.38-gnu1/drivers/base/power/main.c
--- linux-libre-2.6.37-gnu1/drivers/base/power/main.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/base/power/main.c	2011-03-14 21:20:32.000000000 -0400
@@ -8,7 +8,7 @@
  *
  *
  * The driver model core calls device_pm_add() when a device is registered.
- * This will intialize the embedded device_pm_info object in the device
+ * This will initialize the embedded device_pm_info object in the device
  * and add it to the list of power-controlled devices. sysfs entries for
  * controlling device power management will also be added.
  *
@@ -26,6 +26,7 @@
 #include <linux/interrupt.h>
 #include <linux/sched.h>
 #include <linux/async.h>
+#include <linux/suspend.h>
 
 #include "../base.h"
 #include "power.h"
@@ -41,16 +42,13 @@
  */
 
 LIST_HEAD(dpm_list);
+LIST_HEAD(dpm_prepared_list);
+LIST_HEAD(dpm_suspended_list);
+LIST_HEAD(dpm_noirq_list);
 
 static DEFINE_MUTEX(dpm_list_mtx);
 static pm_message_t pm_transition;
 
-/*
- * Set once the preparation of devices for a PM transition has started, reset
- * before starting to resume devices.  Protected by dpm_list_mtx.
- */
-static bool transition_started;
-
 static int async_error;
 
 /**
@@ -59,7 +57,7 @@ static int async_error;
  */
 void device_pm_init(struct device *dev)
 {
-	dev->power.status = DPM_ON;
+	dev->power.in_suspend = false;
 	init_completion(&dev->power.completion);
 	complete_all(&dev->power.completion);
 	dev->power.wakeup = NULL;
@@ -90,22 +88,11 @@ void device_pm_unlock(void)
 void device_pm_add(struct device *dev)
 {
 	pr_debug("PM: Adding info for %s:%s\n",
-		 dev->bus ? dev->bus->name : "No Bus",
-		 kobject_name(&dev->kobj));
+		 dev->bus ? dev->bus->name : "No Bus", dev_name(dev));
 	mutex_lock(&dpm_list_mtx);
-	if (dev->parent) {
-		if (dev->parent->power.status >= DPM_SUSPENDING)
-			dev_warn(dev, "parent %s should not be sleeping\n",
-				 dev_name(dev->parent));
-	} else if (transition_started) {
-		/*
-		 * We refuse to register parentless devices while a PM
-		 * transition is in progress in order to avoid leaving them
-		 * unhandled down the road
-		 */
-		dev_WARN(dev, "Parentless device registered during a PM transaction\n");
-	}
-
+	if (dev->parent && dev->parent->power.in_suspend)
+		dev_warn(dev, "parent %s should not be sleeping\n",
+			dev_name(dev->parent));
 	list_add_tail(&dev->power.entry, &dpm_list);
 	mutex_unlock(&dpm_list_mtx);
 }
@@ -117,8 +104,7 @@ void device_pm_add(struct device *dev)
 void device_pm_remove(struct device *dev)
 {
 	pr_debug("PM: Removing info for %s:%s\n",
-		 dev->bus ? dev->bus->name : "No Bus",
-		 kobject_name(&dev->kobj));
+		 dev->bus ? dev->bus->name : "No Bus", dev_name(dev));
 	complete_all(&dev->power.completion);
 	mutex_lock(&dpm_list_mtx);
 	list_del_init(&dev->power.entry);
@@ -135,10 +121,8 @@ void device_pm_remove(struct device *dev
 void device_pm_move_before(struct device *deva, struct device *devb)
 {
 	pr_debug("PM: Moving %s:%s before %s:%s\n",
-		 deva->bus ? deva->bus->name : "No Bus",
-		 kobject_name(&deva->kobj),
-		 devb->bus ? devb->bus->name : "No Bus",
-		 kobject_name(&devb->kobj));
+		 deva->bus ? deva->bus->name : "No Bus", dev_name(deva),
+		 devb->bus ? devb->bus->name : "No Bus", dev_name(devb));
 	/* Delete deva from dpm_list and reinsert before devb. */
 	list_move_tail(&deva->power.entry, &devb->power.entry);
 }
@@ -151,10 +135,8 @@ void device_pm_move_before(struct device
 void device_pm_move_after(struct device *deva, struct device *devb)
 {
 	pr_debug("PM: Moving %s:%s after %s:%s\n",
-		 deva->bus ? deva->bus->name : "No Bus",
-		 kobject_name(&deva->kobj),
-		 devb->bus ? devb->bus->name : "No Bus",
-		 kobject_name(&devb->kobj));
+		 deva->bus ? deva->bus->name : "No Bus", dev_name(deva),
+		 devb->bus ? devb->bus->name : "No Bus", dev_name(devb));
 	/* Delete deva from dpm_list and reinsert after devb. */
 	list_move(&deva->power.entry, &devb->power.entry);
 }
@@ -166,8 +148,7 @@ void device_pm_move_after(struct device
 void device_pm_move_last(struct device *dev)
 {
 	pr_debug("PM: Moving %s:%s to end of list\n",
-		 dev->bus ? dev->bus->name : "No Bus",
-		 kobject_name(&dev->kobj));
+		 dev->bus ? dev->bus->name : "No Bus", dev_name(dev));
 	list_move_tail(&dev->power.entry, &dpm_list);
 }
 
@@ -303,7 +284,7 @@ static int pm_noirq_op(struct device *de
 			pm_message_t state)
 {
 	int error = 0;
-	ktime_t calltime, delta, rettime;
+	ktime_t calltime = ktime_set(0, 0), delta, rettime;
 
 	if (initcall_debug) {
 		pr_info("calling  %s+ @ %i, parent: %s\n",
@@ -405,7 +386,7 @@ static void pm_dev_err(struct device *de
 			int error)
 {
 	printk(KERN_ERR "PM: Device %s failed to %s%s: error %d\n",
-		kobject_name(&dev->kobj), pm_verb(state.event), info, error);
+		dev_name(dev), pm_verb(state.event), info, error);
 }
 
 static void dpm_show_time(ktime_t starttime, pm_message_t state, char *info)
@@ -475,33 +456,24 @@ End:
  */
 void dpm_resume_noirq(pm_message_t state)
 {
-	struct list_head list;
 	ktime_t starttime = ktime_get();
 
-	INIT_LIST_HEAD(&list);
 	mutex_lock(&dpm_list_mtx);
-	transition_started = false;
-	while (!list_empty(&dpm_list)) {
-		struct device *dev = to_device(dpm_list.next);
+	while (!list_empty(&dpm_noirq_list)) {
+		struct device *dev = to_device(dpm_noirq_list.next);
+		int error;
 
 		get_device(dev);
-		if (dev->power.status > DPM_OFF) {
-			int error;
-
-			dev->power.status = DPM_OFF;
-			mutex_unlock(&dpm_list_mtx);
+		list_move_tail(&dev->power.entry, &dpm_suspended_list);
+		mutex_unlock(&dpm_list_mtx);
 
-			error = device_resume_noirq(dev, state);
+		error = device_resume_noirq(dev, state);
+		if (error)
+			pm_dev_err(dev, state, " early", error);
 
-			mutex_lock(&dpm_list_mtx);
-			if (error)
-				pm_dev_err(dev, state, " early", error);
-		}
-		if (!list_empty(&dev->power.entry))
-			list_move_tail(&dev->power.entry, &list);
+		mutex_lock(&dpm_list_mtx);
 		put_device(dev);
 	}
-	list_splice(&list, &dpm_list);
 	mutex_unlock(&dpm_list_mtx);
 	dpm_show_time(starttime, state, "early");
 	resume_device_irqs();
@@ -544,7 +516,7 @@ static int device_resume(struct device *
 	dpm_wait(dev->parent, async);
 	device_lock(dev);
 
-	dev->power.status = DPM_RESUMING;
+	dev->power.in_suspend = false;
 
 	if (dev->bus) {
 		if (dev->bus->pm) {
@@ -610,19 +582,14 @@ static bool is_async(struct device *dev)
  */
 static void dpm_resume(pm_message_t state)
 {
-	struct list_head list;
 	struct device *dev;
 	ktime_t starttime = ktime_get();
 
-	INIT_LIST_HEAD(&list);
 	mutex_lock(&dpm_list_mtx);
 	pm_transition = state;
 	async_error = 0;
 
-	list_for_each_entry(dev, &dpm_list, power.entry) {
-		if (dev->power.status < DPM_OFF)
-			continue;
-
+	list_for_each_entry(dev, &dpm_suspended_list, power.entry) {
 		INIT_COMPLETION(dev->power.completion);
 		if (is_async(dev)) {
 			get_device(dev);
@@ -630,28 +597,24 @@ static void dpm_resume(pm_message_t stat
 		}
 	}
 
-	while (!list_empty(&dpm_list)) {
-		dev = to_device(dpm_list.next);
+	while (!list_empty(&dpm_suspended_list)) {
+		dev = to_device(dpm_suspended_list.next);
 		get_device(dev);
-		if (dev->power.status >= DPM_OFF && !is_async(dev)) {
+		if (!is_async(dev)) {
 			int error;
 
 			mutex_unlock(&dpm_list_mtx);
 
 			error = device_resume(dev, state, false);
-
-			mutex_lock(&dpm_list_mtx);
 			if (error)
 				pm_dev_err(dev, state, "", error);
-		} else if (dev->power.status == DPM_SUSPENDING) {
-			/* Allow new children of the device to be registered */
-			dev->power.status = DPM_RESUMING;
+
+			mutex_lock(&dpm_list_mtx);
 		}
 		if (!list_empty(&dev->power.entry))
-			list_move_tail(&dev->power.entry, &list);
+			list_move_tail(&dev->power.entry, &dpm_prepared_list);
 		put_device(dev);
 	}
-	list_splice(&list, &dpm_list);
 	mutex_unlock(&dpm_list_mtx);
 	async_synchronize_full();
 	dpm_show_time(starttime, state, NULL);
@@ -697,22 +660,18 @@ static void dpm_complete(pm_message_t st
 
 	INIT_LIST_HEAD(&list);
 	mutex_lock(&dpm_list_mtx);
-	transition_started = false;
-	while (!list_empty(&dpm_list)) {
-		struct device *dev = to_device(dpm_list.prev);
+	while (!list_empty(&dpm_prepared_list)) {
+		struct device *dev = to_device(dpm_prepared_list.prev);
 
 		get_device(dev);
-		if (dev->power.status > DPM_ON) {
-			dev->power.status = DPM_ON;
-			mutex_unlock(&dpm_list_mtx);
+		dev->power.in_suspend = false;
+		list_move(&dev->power.entry, &list);
+		mutex_unlock(&dpm_list_mtx);
 
-			device_complete(dev, state);
-			pm_runtime_put_sync(dev);
+		device_complete(dev, state);
+		pm_runtime_put_sync(dev);
 
-			mutex_lock(&dpm_list_mtx);
-		}
-		if (!list_empty(&dev->power.entry))
-			list_move(&dev->power.entry, &list);
+		mutex_lock(&dpm_list_mtx);
 		put_device(dev);
 	}
 	list_splice(&list, &dpm_list);
@@ -802,15 +761,13 @@ End:
  */
 int dpm_suspend_noirq(pm_message_t state)
 {
-	struct list_head list;
 	ktime_t starttime = ktime_get();
 	int error = 0;
 
-	INIT_LIST_HEAD(&list);
 	suspend_device_irqs();
 	mutex_lock(&dpm_list_mtx);
-	while (!list_empty(&dpm_list)) {
-		struct device *dev = to_device(dpm_list.prev);
+	while (!list_empty(&dpm_suspended_list)) {
+		struct device *dev = to_device(dpm_suspended_list.prev);
 
 		get_device(dev);
 		mutex_unlock(&dpm_list_mtx);
@@ -823,12 +780,10 @@ int dpm_suspend_noirq(pm_message_t state
 			put_device(dev);
 			break;
 		}
-		dev->power.status = DPM_OFF_IRQ;
 		if (!list_empty(&dev->power.entry))
-			list_move(&dev->power.entry, &list);
+			list_move(&dev->power.entry, &dpm_noirq_list);
 		put_device(dev);
 	}
-	list_splice_tail(&list, &dpm_list);
 	mutex_unlock(&dpm_list_mtx);
 	if (error)
 		dpm_resume_noirq(resume_event(state));
@@ -876,6 +831,11 @@ static int __device_suspend(struct devic
 	if (async_error)
 		goto End;
 
+	if (pm_wakeup_pending()) {
+		async_error = -EBUSY;
+		goto End;
+	}
+
 	if (dev->class) {
 		if (dev->class->pm) {
 			pm_dev_dbg(dev, state, "class ");
@@ -907,9 +867,6 @@ static int __device_suspend(struct devic
 		}
 	}
 
-	if (!error)
-		dev->power.status = DPM_OFF;
-
  End:
 	device_unlock(dev);
 	complete_all(&dev->power.completion);
@@ -951,16 +908,14 @@ static int device_suspend(struct device
  */
 static int dpm_suspend(pm_message_t state)
 {
-	struct list_head list;
 	ktime_t starttime = ktime_get();
 	int error = 0;
 
-	INIT_LIST_HEAD(&list);
 	mutex_lock(&dpm_list_mtx);
 	pm_transition = state;
 	async_error = 0;
-	while (!list_empty(&dpm_list)) {
-		struct device *dev = to_device(dpm_list.prev);
+	while (!list_empty(&dpm_prepared_list)) {
+		struct device *dev = to_device(dpm_prepared_list.prev);
 
 		get_device(dev);
 		mutex_unlock(&dpm_list_mtx);
@@ -974,12 +929,11 @@ static int dpm_suspend(pm_message_t stat
 			break;
 		}
 		if (!list_empty(&dev->power.entry))
-			list_move(&dev->power.entry, &list);
+			list_move(&dev->power.entry, &dpm_suspended_list);
 		put_device(dev);
 		if (async_error)
 			break;
 	}
-	list_splice(&list, dpm_list.prev);
 	mutex_unlock(&dpm_list_mtx);
 	async_synchronize_full();
 	if (!error)
@@ -1038,22 +992,20 @@ static int device_prepare(struct device
  */
 static int dpm_prepare(pm_message_t state)
 {
-	struct list_head list;
 	int error = 0;
 
-	INIT_LIST_HEAD(&list);
 	mutex_lock(&dpm_list_mtx);
-	transition_started = true;
 	while (!list_empty(&dpm_list)) {
 		struct device *dev = to_device(dpm_list.next);
 
 		get_device(dev);
-		dev->power.status = DPM_PREPARING;
 		mutex_unlock(&dpm_list_mtx);
 
 		pm_runtime_get_noresume(dev);
-		if (pm_runtime_barrier(dev) && device_may_wakeup(dev)) {
-			/* Wake-up requested during system sleep transition. */
+		if (pm_runtime_barrier(dev) && device_may_wakeup(dev))
+			pm_wakeup_event(dev, 0);
+
+		if (pm_wakeup_pending()) {
 			pm_runtime_put_sync(dev);
 			error = -EBUSY;
 		} else {
@@ -1062,24 +1014,22 @@ static int dpm_prepare(pm_message_t stat
 
 		mutex_lock(&dpm_list_mtx);
 		if (error) {
-			dev->power.status = DPM_ON;
 			if (error == -EAGAIN) {
 				put_device(dev);
 				error = 0;
 				continue;
 			}
-			printk(KERN_ERR "PM: Failed to prepare device %s "
-				"for power transition: error %d\n",
-				kobject_name(&dev->kobj), error);
+			printk(KERN_INFO "PM: Device %s not prepared "
+				"for power transition: code %d\n",
+				dev_name(dev), error);
 			put_device(dev);
 			break;
 		}
-		dev->power.status = DPM_SUSPENDING;
+		dev->power.in_suspend = true;
 		if (!list_empty(&dev->power.entry))
-			list_move_tail(&dev->power.entry, &list);
+			list_move_tail(&dev->power.entry, &dpm_prepared_list);
 		put_device(dev);
 	}
-	list_splice(&list, &dpm_list);
 	mutex_unlock(&dpm_list_mtx);
 	return error;
 }
diff -druNp linux-libre-2.6.37-gnu1/drivers/base/power/runtime.c linux-libre-2.6.38-gnu1/drivers/base/power/runtime.c
--- linux-libre-2.6.37-gnu1/drivers/base/power/runtime.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/base/power/runtime.c	2011-03-14 21:20:32.000000000 -0400
@@ -250,13 +250,16 @@ static int rpm_callback(int (*cb)(struct
 	if (!cb)
 		return -ENOSYS;
 
-	spin_unlock_irq(&dev->power.lock);
+	if (dev->power.irq_safe) {
+		retval = cb(dev);
+	} else {
+		spin_unlock_irq(&dev->power.lock);
 
-	retval = cb(dev);
+		retval = cb(dev);
 
-	spin_lock_irq(&dev->power.lock);
+		spin_lock_irq(&dev->power.lock);
+	}
 	dev->power.runtime_error = retval;
-
 	return retval;
 }
 
@@ -404,12 +407,15 @@ static int rpm_suspend(struct device *de
 		goto out;
 	}
 
-	if (parent && !parent->power.ignore_children) {
-		spin_unlock_irq(&dev->power.lock);
+	/* Maybe the parent is now able to suspend. */
+	if (parent && !parent->power.ignore_children && !dev->power.irq_safe) {
+		spin_unlock(&dev->power.lock);
 
-		pm_request_idle(parent);
+		spin_lock(&parent->power.lock);
+		rpm_idle(parent, RPM_ASYNC);
+		spin_unlock(&parent->power.lock);
 
-		spin_lock_irq(&dev->power.lock);
+		spin_lock(&dev->power.lock);
 	}
 
  out:
@@ -527,10 +533,13 @@ static int rpm_resume(struct device *dev
 
 	if (!parent && dev->parent) {
 		/*
-		 * Increment the parent's resume counter and resume it if
-		 * necessary.
+		 * Increment the parent's usage counter and resume it if
+		 * necessary.  Not needed if dev is irq-safe; then the
+		 * parent is permanently resumed.
 		 */
 		parent = dev->parent;
+		if (dev->power.irq_safe)
+			goto skip_parent;
 		spin_unlock(&dev->power.lock);
 
 		pm_runtime_get_noresume(parent);
@@ -553,6 +562,7 @@ static int rpm_resume(struct device *dev
 			goto out;
 		goto repeat;
 	}
+ skip_parent:
 
 	if (dev->power.no_callbacks)
 		goto no_callback;	/* Assume success. */
@@ -584,7 +594,7 @@ static int rpm_resume(struct device *dev
 		rpm_idle(dev, RPM_ASYNC);
 
  out:
-	if (parent) {
+	if (parent && !dev->power.irq_safe) {
 		spin_unlock_irq(&dev->power.lock);
 
 		pm_runtime_put(parent);
@@ -1065,7 +1075,6 @@ EXPORT_SYMBOL_GPL(pm_runtime_allow);
  * Set the power.no_callbacks flag, which tells the PM core that this
  * device is power-managed through its parent and has no run-time PM
  * callbacks of its own.  The run-time sysfs attributes will be removed.
- *
  */
 void pm_runtime_no_callbacks(struct device *dev)
 {
@@ -1078,6 +1087,27 @@ void pm_runtime_no_callbacks(struct devi
 EXPORT_SYMBOL_GPL(pm_runtime_no_callbacks);
 
 /**
+ * pm_runtime_irq_safe - Leave interrupts disabled during callbacks.
+ * @dev: Device to handle
+ *
+ * Set the power.irq_safe flag, which tells the PM core that the
+ * ->runtime_suspend() and ->runtime_resume() callbacks for this device should
+ * always be invoked with the spinlock held and interrupts disabled.  It also
+ * causes the parent's usage counter to be permanently incremented, preventing
+ * the parent from runtime suspending -- otherwise an irq-safe child might have
+ * to wait for a non-irq-safe parent.
+ */
+void pm_runtime_irq_safe(struct device *dev)
+{
+	if (dev->parent)
+		pm_runtime_get_sync(dev->parent);
+	spin_lock_irq(&dev->power.lock);
+	dev->power.irq_safe = 1;
+	spin_unlock_irq(&dev->power.lock);
+}
+EXPORT_SYMBOL_GPL(pm_runtime_irq_safe);
+
+/**
  * update_autosuspend - Handle a change to a device's autosuspend settings.
  * @dev: Device to handle.
  * @old_delay: The former autosuspend_delay value.
@@ -1199,4 +1229,6 @@ void pm_runtime_remove(struct device *de
 	/* Change the status back to 'suspended' to match the initial status. */
 	if (dev->power.runtime_status == RPM_ACTIVE)
 		pm_runtime_set_suspended(dev);
+	if (dev->power.irq_safe && dev->parent)
+		pm_runtime_put_sync(dev->parent);
 }
diff -druNp linux-libre-2.6.37-gnu1/drivers/base/power/wakeup.c linux-libre-2.6.38-gnu1/drivers/base/power/wakeup.c
--- linux-libre-2.6.37-gnu1/drivers/base/power/wakeup.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/base/power/wakeup.c	2011-03-14 21:20:32.000000000 -0400
@@ -542,26 +542,26 @@ static void pm_wakeup_update_hit_counts(
 }
 
 /**
- * pm_check_wakeup_events - Check for new wakeup events.
+ * pm_wakeup_pending - Check if power transition in progress should be aborted.
  *
  * Compare the current number of registered wakeup events with its preserved
- * value from the past to check if new wakeup events have been registered since
- * the old value was stored.  Check if the current number of wakeup events being
- * processed is zero.
+ * value from the past and return true if new wakeup events have been registered
+ * since the old value was stored.  Also return true if the current number of
+ * wakeup events being processed is different from zero.
  */
-bool pm_check_wakeup_events(void)
+bool pm_wakeup_pending(void)
 {
 	unsigned long flags;
-	bool ret = true;
+	bool ret = false;
 
 	spin_lock_irqsave(&events_lock, flags);
 	if (events_check_enabled) {
-		ret = ((unsigned int)atomic_read(&event_count) == saved_count)
-			&& !atomic_read(&events_in_progress);
-		events_check_enabled = ret;
+		ret = ((unsigned int)atomic_read(&event_count) != saved_count)
+			|| atomic_read(&events_in_progress);
+		events_check_enabled = !ret;
 	}
 	spin_unlock_irqrestore(&events_lock, flags);
-	if (!ret)
+	if (ret)
 		pm_wakeup_update_hit_counts();
 	return ret;
 }
diff -druNp linux-libre-2.6.37-gnu1/drivers/block/aoe/aoecmd.c linux-libre-2.6.38-gnu1/drivers/block/aoe/aoecmd.c
--- linux-libre-2.6.37-gnu1/drivers/block/aoe/aoecmd.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/block/aoe/aoecmd.c	2011-03-14 21:20:32.000000000 -0400
@@ -297,8 +297,8 @@ aoecmd_cfg_pkts(ushort aoemajor, unsigne
 	struct sk_buff *skb;
 	struct net_device *ifp;
 
-	read_lock(&dev_base_lock);
-	for_each_netdev(&init_net, ifp) {
+	rcu_read_lock();
+	for_each_netdev_rcu(&init_net, ifp) {
 		dev_hold(ifp);
 		if (!is_aoe_netif(ifp))
 			goto cont;
@@ -325,7 +325,7 @@ aoecmd_cfg_pkts(ushort aoemajor, unsigne
 cont:
 		dev_put(ifp);
 	}
-	read_unlock(&dev_base_lock);
+	rcu_read_unlock();
 }
 
 static void
diff -druNp linux-libre-2.6.37-gnu1/drivers/block/aoe/Makefile linux-libre-2.6.38-gnu1/drivers/block/aoe/Makefile
--- linux-libre-2.6.37-gnu1/drivers/block/aoe/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/block/aoe/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -3,4 +3,4 @@
 #
 
 obj-$(CONFIG_ATA_OVER_ETH)	+= aoe.o
-aoe-objs := aoeblk.o aoechr.o aoecmd.o aoedev.o aoemain.o aoenet.o
+aoe-y := aoeblk.o aoechr.o aoecmd.o aoedev.o aoemain.o aoenet.o
diff -druNp linux-libre-2.6.37-gnu1/drivers/block/cciss.c linux-libre-2.6.38-gnu1/drivers/block/cciss.c
--- linux-libre-2.6.37-gnu1/drivers/block/cciss.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/block/cciss.c	2011-03-14 21:20:32.000000000 -0400
@@ -238,9 +238,9 @@ static void set_performant_mode(ctlr_inf
 /*
  * Enqueuing and dequeuing functions for cmdlists.
  */
-static inline void addQ(struct hlist_head *list, CommandList_struct *c)
+static inline void addQ(struct list_head *list, CommandList_struct *c)
 {
-	hlist_add_head(&c->list, list);
+	list_add_tail(&c->list, list);
 }
 
 static inline void removeQ(CommandList_struct *c)
@@ -253,12 +253,12 @@ static inline void removeQ(CommandList_s
 	 * them off as 'stale' to prevent the driver from
 	 * falling over.
 	 */
-	if (WARN_ON(hlist_unhashed(&c->list))) {
+	if (WARN_ON(list_empty(&c->list))) {
 		c->cmd_type = CMD_MSG_STALE;
 		return;
 	}
 
-	hlist_del_init(&c->list);
+	list_del_init(&c->list);
 }
 
 static void enqueue_cmd_and_start_io(ctlr_info_t *h,
@@ -905,7 +905,7 @@ static CommandList_struct *cmd_alloc(ctl
 
 	c->cmdindex = i;
 
-	INIT_HLIST_NODE(&c->list);
+	INIT_LIST_HEAD(&c->list);
 	c->busaddr = (__u32) cmd_dma_handle;
 	temp64.val = (__u64) err_dma_handle;
 	c->ErrDesc.Addr.lower = temp64.val32.lower;
@@ -944,7 +944,7 @@ static CommandList_struct *cmd_special_a
 	}
 	memset(c->err_info, 0, sizeof(ErrorInfo_struct));
 
-	INIT_HLIST_NODE(&c->list);
+	INIT_LIST_HEAD(&c->list);
 	c->busaddr = (__u32) cmd_dma_handle;
 	temp64.val = (__u64) err_dma_handle;
 	c->ErrDesc.Addr.lower = temp64.val32.lower;
@@ -2833,7 +2833,7 @@ static int cciss_revalidate(struct gendi
 	sector_t total_size;
 	InquiryData_struct *inq_buff = NULL;
 
-	for (logvol = 0; logvol < CISS_MAX_LUN; logvol++) {
+	for (logvol = 0; logvol <= h->highest_lun; logvol++) {
 		if (!h->drv[logvol])
 			continue;
 		if (memcmp(h->drv[logvol]->LunID, drv->LunID,
@@ -2888,8 +2888,8 @@ static void start_io(ctlr_info_t *h)
 {
 	CommandList_struct *c;
 
-	while (!hlist_empty(&h->reqQ)) {
-		c = hlist_entry(h->reqQ.first, CommandList_struct, list);
+	while (!list_empty(&h->reqQ)) {
+		c = list_entry(h->reqQ.next, CommandList_struct, list);
 		/* can't do anything if fifo is full */
 		if ((h->access.fifo_full(h))) {
 			dev_warn(&h->pdev->dev, "fifo full\n");
@@ -3402,11 +3402,10 @@ static inline u32 process_nonindexed_cmd
 {
 	u32 tag;
 	CommandList_struct *c = NULL;
-	struct hlist_node *tmp;
 	__u32 busaddr_masked, tag_masked;
 
 	tag = cciss_tag_discard_error_bits(raw_tag);
-	hlist_for_each_entry(c, tmp, &h->cmpQ, list) {
+	list_for_each_entry(c, &h->cmpQ, list) {
 		busaddr_masked = cciss_tag_discard_error_bits(c->busaddr);
 		tag_masked = cciss_tag_discard_error_bits(tag);
 		if (busaddr_masked == tag_masked) {
@@ -4572,8 +4571,8 @@ static int __devinit cciss_init_one(stru
 	h = hba[i];
 	h->pdev = pdev;
 	h->busy_initializing = 1;
-	INIT_HLIST_HEAD(&h->cmpQ);
-	INIT_HLIST_HEAD(&h->reqQ);
+	INIT_LIST_HEAD(&h->cmpQ);
+	INIT_LIST_HEAD(&h->reqQ);
 	mutex_init(&h->busy_shutting_down);
 
 	if (cciss_pci_init(h) != 0)
diff -druNp linux-libre-2.6.37-gnu1/drivers/block/cciss_cmd.h linux-libre-2.6.38-gnu1/drivers/block/cciss_cmd.h
--- linux-libre-2.6.37-gnu1/drivers/block/cciss_cmd.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/block/cciss_cmd.h	2011-03-14 21:20:32.000000000 -0400
@@ -195,7 +195,7 @@ typedef struct _CommandList_struct {
   int			   ctlr;
   int			   cmd_type; 
   long			   cmdindex;
-  struct hlist_node list;
+  struct list_head list;
   struct request *	   rq;
   struct completion *waiting;
   int	 retry_count;
diff -druNp linux-libre-2.6.37-gnu1/drivers/block/cciss.h linux-libre-2.6.38-gnu1/drivers/block/cciss.h
--- linux-libre-2.6.37-gnu1/drivers/block/cciss.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/block/cciss.h	2011-03-14 21:20:32.000000000 -0400
@@ -103,8 +103,8 @@ struct ctlr_info
 	struct access_method access;
 
 	/* queue and queue Info */ 
-	struct hlist_head reqQ;
-	struct hlist_head cmpQ;
+	struct list_head reqQ;
+	struct list_head cmpQ;
 	unsigned int Qdepth;
 	unsigned int maxQsinceinit;
 	unsigned int maxSG;
diff -druNp linux-libre-2.6.37-gnu1/drivers/block/drbd/drbd_int.h linux-libre-2.6.38-gnu1/drivers/block/drbd/drbd_int.h
--- linux-libre-2.6.37-gnu1/drivers/block/drbd/drbd_int.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/block/drbd/drbd_int.h	2011-03-14 21:20:32.000000000 -0400
@@ -911,8 +911,6 @@ struct drbd_md {
 struct drbd_backing_dev {
 	struct block_device *backing_bdev;
 	struct block_device *md_bdev;
-	struct file *lo_file;
-	struct file *md_file;
 	struct drbd_md md;
 	struct disk_conf dc; /* The user provided config... */
 	sector_t known_size; /* last known size of that backing device */
diff -druNp linux-libre-2.6.37-gnu1/drivers/block/drbd/drbd_main.c linux-libre-2.6.38-gnu1/drivers/block/drbd/drbd_main.c
--- linux-libre-2.6.37-gnu1/drivers/block/drbd/drbd_main.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/block/drbd/drbd_main.c	2011-03-14 21:20:32.000000000 -0400
@@ -3372,11 +3372,8 @@ void drbd_free_bc(struct drbd_backing_de
 	if (ldev == NULL)
 		return;
 
-	bd_release(ldev->backing_bdev);
-	bd_release(ldev->md_bdev);
-
-	fput(ldev->lo_file);
-	fput(ldev->md_file);
+	blkdev_put(ldev->backing_bdev, FMODE_READ | FMODE_WRITE | FMODE_EXCL);
+	blkdev_put(ldev->md_bdev, FMODE_READ | FMODE_WRITE | FMODE_EXCL);
 
 	kfree(ldev);
 }
diff -druNp linux-libre-2.6.37-gnu1/drivers/block/drbd/drbd_nl.c linux-libre-2.6.38-gnu1/drivers/block/drbd/drbd_nl.c
--- linux-libre-2.6.37-gnu1/drivers/block/drbd/drbd_nl.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/block/drbd/drbd_nl.c	2011-03-14 21:20:32.000000000 -0400
@@ -855,7 +855,7 @@ static int drbd_nl_disk_conf(struct drbd
 	sector_t max_possible_sectors;
 	sector_t min_md_device_sectors;
 	struct drbd_backing_dev *nbc = NULL; /* new_backing_conf */
-	struct inode *inode, *inode2;
+	struct block_device *bdev;
 	struct lru_cache *resync_lru = NULL;
 	union drbd_state ns, os;
 	unsigned int max_seg_s;
@@ -907,46 +907,40 @@ static int drbd_nl_disk_conf(struct drbd
 		}
 	}
 
-	nbc->lo_file = filp_open(nbc->dc.backing_dev, O_RDWR, 0);
-	if (IS_ERR(nbc->lo_file)) {
+	bdev = blkdev_get_by_path(nbc->dc.backing_dev,
+				  FMODE_READ | FMODE_WRITE | FMODE_EXCL, mdev);
+	if (IS_ERR(bdev)) {
 		dev_err(DEV, "open(\"%s\") failed with %ld\n", nbc->dc.backing_dev,
-		    PTR_ERR(nbc->lo_file));
-		nbc->lo_file = NULL;
+			PTR_ERR(bdev));
 		retcode = ERR_OPEN_DISK;
 		goto fail;
 	}
+	nbc->backing_bdev = bdev;
 
-	inode = nbc->lo_file->f_dentry->d_inode;
-
-	if (!S_ISBLK(inode->i_mode)) {
-		retcode = ERR_DISK_NOT_BDEV;
-		goto fail;
-	}
-
-	nbc->md_file = filp_open(nbc->dc.meta_dev, O_RDWR, 0);
-	if (IS_ERR(nbc->md_file)) {
+	/*
+	 * meta_dev_idx >= 0: external fixed size, possibly multiple
+	 * drbd sharing one meta device.  TODO in that case, paranoia
+	 * check that [md_bdev, meta_dev_idx] is not yet used by some
+	 * other drbd minor!  (if you use drbd.conf + drbdadm, that
+	 * should check it for you already; but if you don't, or
+	 * someone fooled it, we need to double check here)
+	 */
+	bdev = blkdev_get_by_path(nbc->dc.meta_dev,
+				  FMODE_READ | FMODE_WRITE | FMODE_EXCL,
+				  (nbc->dc.meta_dev_idx < 0) ?
+				  (void *)mdev : (void *)drbd_m_holder);
+	if (IS_ERR(bdev)) {
 		dev_err(DEV, "open(\"%s\") failed with %ld\n", nbc->dc.meta_dev,
-		    PTR_ERR(nbc->md_file));
-		nbc->md_file = NULL;
+			PTR_ERR(bdev));
 		retcode = ERR_OPEN_MD_DISK;
 		goto fail;
 	}
+	nbc->md_bdev = bdev;
 
-	inode2 = nbc->md_file->f_dentry->d_inode;
-
-	if (!S_ISBLK(inode2->i_mode)) {
-		retcode = ERR_MD_NOT_BDEV;
-		goto fail;
-	}
-
-	nbc->backing_bdev = inode->i_bdev;
-	if (bd_claim(nbc->backing_bdev, mdev)) {
-		printk(KERN_ERR "drbd: bd_claim(%p,%p); failed [%p;%p;%u]\n",
-		       nbc->backing_bdev, mdev,
-		       nbc->backing_bdev->bd_holder,
-		       nbc->backing_bdev->bd_contains->bd_holder,
-		       nbc->backing_bdev->bd_holders);
-		retcode = ERR_BDCLAIM_DISK;
+	if ((nbc->backing_bdev == nbc->md_bdev) !=
+	    (nbc->dc.meta_dev_idx == DRBD_MD_INDEX_INTERNAL ||
+	     nbc->dc.meta_dev_idx == DRBD_MD_INDEX_FLEX_INT)) {
+		retcode = ERR_MD_IDX_INVALID;
 		goto fail;
 	}
 
@@ -955,28 +949,7 @@ static int drbd_nl_disk_conf(struct drbd
 			offsetof(struct bm_extent, lce));
 	if (!resync_lru) {
 		retcode = ERR_NOMEM;
-		goto release_bdev_fail;
-	}
-
-	/* meta_dev_idx >= 0: external fixed size,
-	 * possibly multiple drbd sharing one meta device.
-	 * TODO in that case, paranoia check that [md_bdev, meta_dev_idx] is
-	 * not yet used by some other drbd minor!
-	 * (if you use drbd.conf + drbdadm,
-	 * that should check it for you already; but if you don't, or someone
-	 * fooled it, we need to double check here) */
-	nbc->md_bdev = inode2->i_bdev;
-	if (bd_claim(nbc->md_bdev, (nbc->dc.meta_dev_idx < 0) ? (void *)mdev
-				: (void *) drbd_m_holder)) {
-		retcode = ERR_BDCLAIM_MD_DISK;
-		goto release_bdev_fail;
-	}
-
-	if ((nbc->backing_bdev == nbc->md_bdev) !=
-	    (nbc->dc.meta_dev_idx == DRBD_MD_INDEX_INTERNAL ||
-	     nbc->dc.meta_dev_idx == DRBD_MD_INDEX_FLEX_INT)) {
-		retcode = ERR_MD_IDX_INVALID;
-		goto release_bdev2_fail;
+		goto fail;
 	}
 
 	/* RT - for drbd_get_max_capacity() DRBD_MD_INDEX_FLEX_INT */
@@ -987,7 +960,7 @@ static int drbd_nl_disk_conf(struct drbd
 			(unsigned long long) drbd_get_max_capacity(nbc),
 			(unsigned long long) nbc->dc.disk_size);
 		retcode = ERR_DISK_TO_SMALL;
-		goto release_bdev2_fail;
+		goto fail;
 	}
 
 	if (nbc->dc.meta_dev_idx < 0) {
@@ -1004,7 +977,7 @@ static int drbd_nl_disk_conf(struct drbd
 		dev_warn(DEV, "refusing attach: md-device too small, "
 		     "at least %llu sectors needed for this meta-disk type\n",
 		     (unsigned long long) min_md_device_sectors);
-		goto release_bdev2_fail;
+		goto fail;
 	}
 
 	/* Make sure the new disk is big enough
@@ -1012,7 +985,7 @@ static int drbd_nl_disk_conf(struct drbd
 	if (drbd_get_max_capacity(nbc) <
 	    drbd_get_capacity(mdev->this_bdev)) {
 		retcode = ERR_DISK_TO_SMALL;
-		goto release_bdev2_fail;
+		goto fail;
 	}
 
 	nbc->known_size = drbd_get_capacity(nbc->backing_bdev);
@@ -1035,7 +1008,7 @@ static int drbd_nl_disk_conf(struct drbd
 	retcode = _drbd_request_state(mdev, NS(disk, D_ATTACHING), CS_VERBOSE);
 	drbd_resume_io(mdev);
 	if (retcode < SS_SUCCESS)
-		goto release_bdev2_fail;
+		goto fail;
 
 	if (!get_ldev_if_state(mdev, D_ATTACHING))
 		goto force_diskless;
@@ -1269,18 +1242,14 @@ static int drbd_nl_disk_conf(struct drbd
  force_diskless:
 	drbd_force_state(mdev, NS(disk, D_FAILED));
 	drbd_md_sync(mdev);
- release_bdev2_fail:
-	if (nbc)
-		bd_release(nbc->md_bdev);
- release_bdev_fail:
-	if (nbc)
-		bd_release(nbc->backing_bdev);
  fail:
 	if (nbc) {
-		if (nbc->lo_file)
-			fput(nbc->lo_file);
-		if (nbc->md_file)
-			fput(nbc->md_file);
+		if (nbc->backing_bdev)
+			blkdev_put(nbc->backing_bdev,
+				   FMODE_READ | FMODE_WRITE | FMODE_EXCL);
+		if (nbc->md_bdev)
+			blkdev_put(nbc->md_bdev,
+				   FMODE_READ | FMODE_WRITE | FMODE_EXCL);
 		kfree(nbc);
 	}
 	lc_destroy(resync_lru);
diff -druNp linux-libre-2.6.37-gnu1/drivers/block/floppy.c linux-libre-2.6.38-gnu1/drivers/block/floppy.c
--- linux-libre-2.6.37-gnu1/drivers/block/floppy.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/block/floppy.c	2011-03-14 21:20:32.000000000 -0400
@@ -597,6 +597,11 @@ static unsigned char fsector_t;	/* secto
 static unsigned char in_sector_offset;	/* offset within physical sector,
 					 * expressed in units of 512 bytes */
 
+static inline bool drive_no_geom(int drive)
+{
+	return !current_type[drive] && !ITYPE(UDRS->fd_device);
+}
+
 #ifndef fd_eject
 static inline int fd_eject(int drive)
 {
@@ -3276,7 +3281,7 @@ static int set_geometry(unsigned int cmd
 			struct block_device *bdev = opened_bdev[cnt];
 			if (!bdev || ITYPE(drive_state[cnt].fd_device) != type)
 				continue;
-			__invalidate_device(bdev);
+			__invalidate_device(bdev, true);
 		}
 		mutex_unlock(&open_lock);
 	} else {
@@ -3782,7 +3787,7 @@ static int check_floppy_change(struct ge
 	if (test_bit(FD_DISK_CHANGED_BIT, &UDRS->flags) ||
 	    test_bit(FD_VERIFY_BIT, &UDRS->flags) ||
 	    test_bit(drive, &fake_change) ||
-	    (!ITYPE(UDRS->fd_device) && !current_type[drive]))
+	    drive_no_geom(drive))
 		return 1;
 	return 0;
 }
@@ -3848,13 +3853,13 @@ static int __floppy_read_block_0(struct
 static int floppy_revalidate(struct gendisk *disk)
 {
 	int drive = (long)disk->private_data;
-#define NO_GEOM (!current_type[drive] && !ITYPE(UDRS->fd_device))
 	int cf;
 	int res = 0;
 
 	if (test_bit(FD_DISK_CHANGED_BIT, &UDRS->flags) ||
 	    test_bit(FD_VERIFY_BIT, &UDRS->flags) ||
-	    test_bit(drive, &fake_change) || NO_GEOM) {
+	    test_bit(drive, &fake_change) ||
+	    drive_no_geom(drive)) {
 		if (WARN(atomic_read(&usage_count) == 0,
 			 "VFS: revalidate called on non-open device.\n"))
 			return -EFAULT;
@@ -3862,7 +3867,7 @@ static int floppy_revalidate(struct gend
 		lock_fdc(drive, false);
 		cf = (test_bit(FD_DISK_CHANGED_BIT, &UDRS->flags) ||
 		      test_bit(FD_VERIFY_BIT, &UDRS->flags));
-		if (!(cf || test_bit(drive, &fake_change) || NO_GEOM)) {
+		if (!(cf || test_bit(drive, &fake_change) || drive_no_geom(drive))) {
 			process_fd_request();	/*already done by another thread */
 			return 0;
 		}
@@ -3874,7 +3879,7 @@ static int floppy_revalidate(struct gend
 		clear_bit(FD_DISK_CHANGED_BIT, &UDRS->flags);
 		if (cf)
 			UDRS->generation++;
-		if (NO_GEOM) {
+		if (drive_no_geom(drive)) {
 			/* auto-sensing */
 			res = __floppy_read_block_0(opened_bdev[drive]);
 		} else {
@@ -4352,7 +4357,7 @@ static int __init floppy_init(void)
 out_unreg_platform_dev:
 	platform_device_unregister(&floppy_device[drive]);
 out_flush_work:
-	flush_scheduled_work();
+	flush_work_sync(&floppy_work);
 	if (atomic_read(&usage_count))
 		floppy_release_irq_and_dma();
 out_unreg_region:
@@ -4422,7 +4427,7 @@ static int floppy_grab_irq_and_dma(void)
 	 * We might have scheduled a free_irq(), wait it to
 	 * drain first:
 	 */
-	flush_scheduled_work();
+	flush_work_sync(&floppy_work);
 
 	if (fd_request_irq()) {
 		DPRINT("Unable to grab IRQ%d for the floppy driver\n",
diff -druNp linux-libre-2.6.37-gnu1/drivers/block/Kconfig linux-libre-2.6.38-gnu1/drivers/block/Kconfig
--- linux-libre-2.6.37-gnu1/drivers/block/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/block/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -464,6 +464,7 @@ config XEN_BLKDEV_FRONTEND
 	tristate "Xen virtual block device support"
 	depends on XEN
 	default y
+	select XEN_XENBUS_FRONTEND
 	help
 	  This driver implements the front-end of the Xen virtual
 	  block device driver.  It communicates with a back-end driver
diff -druNp linux-libre-2.6.37-gnu1/drivers/block/loop.c linux-libre-2.6.38-gnu1/drivers/block/loop.c
--- linux-libre-2.6.37-gnu1/drivers/block/loop.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/block/loop.c	2011-03-14 21:20:32.000000000 -0400
@@ -78,7 +78,6 @@
 
 #include <asm/uaccess.h>
 
-static DEFINE_MUTEX(loop_mutex);
 static LIST_HEAD(loop_devices);
 static DEFINE_MUTEX(loop_devices_mutex);
 
@@ -395,11 +394,7 @@ lo_splice_actor(struct pipe_inode_info *
 	struct loop_device *lo = p->lo;
 	struct page *page = buf->page;
 	sector_t IV;
-	int size, ret;
-
-	ret = buf->ops->confirm(pipe, buf);
-	if (unlikely(ret))
-		return ret;
+	int size;
 
 	IV = ((sector_t) page->index << (PAGE_CACHE_SHIFT - 9)) +
 							(buf->offset >> 9);
@@ -1505,11 +1500,9 @@ static int lo_open(struct block_device *
 {
 	struct loop_device *lo = bdev->bd_disk->private_data;
 
-	mutex_lock(&loop_mutex);
 	mutex_lock(&lo->lo_ctl_mutex);
 	lo->lo_refcnt++;
 	mutex_unlock(&lo->lo_ctl_mutex);
-	mutex_unlock(&loop_mutex);
 
 	return 0;
 }
@@ -1519,7 +1512,6 @@ static int lo_release(struct gendisk *di
 	struct loop_device *lo = disk->private_data;
 	int err;
 
-	mutex_lock(&loop_mutex);
 	mutex_lock(&lo->lo_ctl_mutex);
 
 	if (--lo->lo_refcnt)
@@ -1544,7 +1536,6 @@ static int lo_release(struct gendisk *di
 out:
 	mutex_unlock(&lo->lo_ctl_mutex);
 out_unlocked:
-	mutex_unlock(&loop_mutex);
 	return 0;
 }
 
@@ -1645,6 +1636,9 @@ out:
 
 static void loop_free(struct loop_device *lo)
 {
+	if (!lo->lo_queue->queue_lock)
+		lo->lo_queue->queue_lock = &lo->lo_queue->__queue_lock;
+
 	blk_cleanup_queue(lo->lo_queue);
 	put_disk(lo->lo_disk);
 	list_del(&lo->lo_list);
diff -druNp linux-libre-2.6.37-gnu1/drivers/block/Makefile linux-libre-2.6.38-gnu1/drivers/block/Makefile
--- linux-libre-2.6.37-gnu1/drivers/block/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/block/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -39,4 +39,4 @@ obj-$(CONFIG_XEN_BLKDEV_FRONTEND)	+= xen
 obj-$(CONFIG_BLK_DEV_DRBD)     += drbd/
 obj-$(CONFIG_BLK_DEV_RBD)     += rbd.o
 
-swim_mod-objs	:= swim.o swim_asm.o
+swim_mod-y	:= swim.o swim_asm.o
diff -druNp linux-libre-2.6.37-gnu1/drivers/block/nbd.c linux-libre-2.6.38-gnu1/drivers/block/nbd.c
--- linux-libre-2.6.37-gnu1/drivers/block/nbd.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/block/nbd.c	2011-03-14 21:20:32.000000000 -0400
@@ -53,7 +53,6 @@
 #define DBG_BLKDEV      0x0100
 #define DBG_RX          0x0200
 #define DBG_TX          0x0400
-static DEFINE_MUTEX(nbd_mutex);
 static unsigned int debugflags;
 #endif /* NDEBUG */
 
@@ -718,11 +717,9 @@ static int nbd_ioctl(struct block_device
 	dprintk(DBG_IOCTL, "%s: nbd_ioctl cmd=%s(0x%x) arg=%lu\n",
 			lo->disk->disk_name, ioctl_cmd_to_ascii(cmd), cmd, arg);
 
-	mutex_lock(&nbd_mutex);
 	mutex_lock(&lo->tx_lock);
 	error = __nbd_ioctl(bdev, lo, cmd, arg);
 	mutex_unlock(&lo->tx_lock);
-	mutex_unlock(&nbd_mutex);
 
 	return error;
 }
diff -druNp linux-libre-2.6.37-gnu1/drivers/block/pktcdvd.c linux-libre-2.6.38-gnu1/drivers/block/pktcdvd.c
--- linux-libre-2.6.37-gnu1/drivers/block/pktcdvd.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/block/pktcdvd.c	2011-03-14 21:20:32.000000000 -0400
@@ -2296,15 +2296,12 @@ static int pkt_open_dev(struct pktcdvd_d
 	 * so bdget() can't fail.
 	 */
 	bdget(pd->bdev->bd_dev);
-	if ((ret = blkdev_get(pd->bdev, FMODE_READ)))
+	if ((ret = blkdev_get(pd->bdev, FMODE_READ | FMODE_EXCL, pd)))
 		goto out;
 
-	if ((ret = bd_claim(pd->bdev, pd)))
-		goto out_putdev;
-
 	if ((ret = pkt_get_last_written(pd, &lba))) {
 		printk(DRIVER_NAME": pkt_get_last_written failed\n");
-		goto out_unclaim;
+		goto out_putdev;
 	}
 
 	set_capacity(pd->disk, lba << 2);
@@ -2314,7 +2311,7 @@ static int pkt_open_dev(struct pktcdvd_d
 	q = bdev_get_queue(pd->bdev);
 	if (write) {
 		if ((ret = pkt_open_write(pd)))
-			goto out_unclaim;
+			goto out_putdev;
 		/*
 		 * Some CDRW drives can not handle writes larger than one packet,
 		 * even if the size is a multiple of the packet size.
@@ -2329,23 +2326,21 @@ static int pkt_open_dev(struct pktcdvd_d
 	}
 
 	if ((ret = pkt_set_segment_merging(pd, q)))
-		goto out_unclaim;
+		goto out_putdev;
 
 	if (write) {
 		if (!pkt_grow_pktlist(pd, CONFIG_CDROM_PKTCDVD_BUFFERS)) {
 			printk(DRIVER_NAME": not enough memory for buffers\n");
 			ret = -ENOMEM;
-			goto out_unclaim;
+			goto out_putdev;
 		}
 		printk(DRIVER_NAME": %lukB available on disc\n", lba << 1);
 	}
 
 	return 0;
 
-out_unclaim:
-	bd_release(pd->bdev);
 out_putdev:
-	blkdev_put(pd->bdev, FMODE_READ);
+	blkdev_put(pd->bdev, FMODE_READ | FMODE_EXCL);
 out:
 	return ret;
 }
@@ -2362,8 +2357,7 @@ static void pkt_release_dev(struct pktcd
 	pkt_lock_door(pd, 0);
 
 	pkt_set_speed(pd, MAX_SPEED, MAX_SPEED);
-	bd_release(pd->bdev);
-	blkdev_put(pd->bdev, FMODE_READ);
+	blkdev_put(pd->bdev, FMODE_READ | FMODE_EXCL);
 
 	pkt_shrink_pktlist(pd);
 }
@@ -2733,7 +2727,7 @@ static int pkt_new_dev(struct pktcdvd_de
 	bdev = bdget(dev);
 	if (!bdev)
 		return -ENOMEM;
-	ret = blkdev_get(bdev, FMODE_READ | FMODE_NDELAY);
+	ret = blkdev_get(bdev, FMODE_READ | FMODE_NDELAY, NULL);
 	if (ret)
 		return ret;
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/block/rbd.c linux-libre-2.6.38-gnu1/drivers/block/rbd.c
--- linux-libre-2.6.37-gnu1/drivers/block/rbd.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/block/rbd.c	2011-03-14 21:20:32.000000000 -0400
@@ -1790,18 +1790,29 @@ static ssize_t rbd_add(struct bus_type *
 
 	rc = rbd_bus_add_dev(rbd_dev);
 	if (rc)
-		goto err_out_disk;
+		goto err_out_blkdev;
+
 	/* set up and announce blkdev mapping */
 	rc = rbd_init_disk(rbd_dev);
 	if (rc)
-		goto err_out_blkdev;
+		goto err_out_bus;
 
 	return count;
 
+err_out_bus:
+	mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
+	list_del_init(&rbd_dev->node);
+	mutex_unlock(&ctl_mutex);
+
+	/* this will also clean up rest of rbd_dev stuff */
+
+	rbd_bus_del_dev(rbd_dev);
+	kfree(options);
+	kfree(mon_dev_name);
+	return rc;
+
 err_out_blkdev:
 	unregister_blkdev(rbd_dev->major, rbd_dev->name);
-err_out_disk:
-	rbd_free_disk(rbd_dev);
 err_out_client:
 	rbd_put_client(rbd_dev);
 	mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
diff -druNp linux-libre-2.6.37-gnu1/drivers/block/xen-blkfront.c linux-libre-2.6.38-gnu1/drivers/block/xen-blkfront.c
--- linux-libre-2.6.37-gnu1/drivers/block/xen-blkfront.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/block/xen-blkfront.c	2011-03-14 21:20:32.000000000 -0400
@@ -547,7 +547,7 @@ static void xlvbd_release_gendisk(struct
 	spin_unlock_irqrestore(&blkif_io_lock, flags);
 
 	/* Flush gnttab callback work. Must be done with no locks held. */
-	flush_scheduled_work();
+	flush_work_sync(&info->work);
 
 	del_gendisk(info->gd);
 
@@ -596,7 +596,7 @@ static void blkif_free(struct blkfront_i
 	spin_unlock_irq(&blkif_io_lock);
 
 	/* Flush gnttab callback work. Must be done with no locks held. */
-	flush_scheduled_work();
+	flush_work_sync(&info->work);
 
 	/* Free resources associated with old device channel. */
 	if (info->ring_ref != GRANT_INVALID_REF) {
diff -druNp linux-libre-2.6.37-gnu1/drivers/bluetooth/ath3k.c linux-libre-2.6.38-gnu1/drivers/bluetooth/ath3k.c
--- linux-libre-2.6.37-gnu1/drivers/bluetooth/ath3k.c	2013-05-03 04:02:40.000000000 -0400
+++ linux-libre-2.6.38-gnu1/drivers/bluetooth/ath3k.c	2013-05-03 02:03:33.000000000 -0400
@@ -39,6 +39,11 @@ static struct usb_device_id ath3k_table[
 	/* Atheros AR3011 with sflash firmware*/
 	{ USB_DEVICE(0x0CF3, 0x3002) },
 
+	/* Atheros AR9285 Malbec with sflash firmware */
+	{ USB_DEVICE(0x03F0, 0x311D) },
+
+	/* Atheros AR5BBU12 with sflash firmware */
+	{ USB_DEVICE(0x0489, 0xE02C) },
 	{ }	/* Terminating entry */
 };
 
@@ -47,46 +52,40 @@ MODULE_DEVICE_TABLE(usb, ath3k_table);
 #define USB_REQ_DFU_DNLOAD	1
 #define BULK_SIZE		4096
 
-struct ath3k_data {
-	struct usb_device *udev;
-	u8 *fw_data;
-	u32 fw_size;
-	u32 fw_sent;
-};
-
-static int ath3k_load_firmware(struct ath3k_data *data,
-				unsigned char *firmware,
-				int count)
+static int ath3k_load_firmware(struct usb_device *udev,
+				const struct firmware *firmware)
 {
 	u8 *send_buf;
 	int err, pipe, len, size, sent = 0;
+	int count = firmware->size;
 
-	BT_DBG("ath3k %p udev %p", data, data->udev);
+	BT_DBG("udev %p", udev);
 
-	pipe = usb_sndctrlpipe(data->udev, 0);
+	pipe = usb_sndctrlpipe(udev, 0);
 
-	if ((usb_control_msg(data->udev, pipe,
+	send_buf = kmalloc(BULK_SIZE, GFP_ATOMIC);
+	if (!send_buf) {
+		BT_ERR("Can't allocate memory chunk for firmware");
+		return -ENOMEM;
+	}
+
+	memcpy(send_buf, firmware->data, 20);
+	if ((err = usb_control_msg(udev, pipe,
 				USB_REQ_DFU_DNLOAD,
 				USB_TYPE_VENDOR, 0, 0,
-				firmware, 20, USB_CTRL_SET_TIMEOUT)) < 0) {
+				send_buf, 20, USB_CTRL_SET_TIMEOUT)) < 0) {
 		BT_ERR("Can't change to loading configuration err");
-		return -EBUSY;
+		goto error;
 	}
 	sent += 20;
 	count -= 20;
 
-	send_buf = kmalloc(BULK_SIZE, GFP_ATOMIC);
-	if (!send_buf) {
-		BT_ERR("Can't allocate memory chunk for firmware");
-		return -ENOMEM;
-	}
-
 	while (count) {
 		size = min_t(uint, count, BULK_SIZE);
-		pipe = usb_sndbulkpipe(data->udev, 0x02);
-		memcpy(send_buf, firmware + sent, size);
+		pipe = usb_sndbulkpipe(udev, 0x02);
+		memcpy(send_buf, firmware->data + sent, size);
 
-		err = usb_bulk_msg(data->udev, pipe, send_buf, size,
+		err = usb_bulk_msg(udev, pipe, send_buf, size,
 					&len, 3000);
 
 		if (err || (len != size)) {
@@ -112,57 +111,28 @@ static int ath3k_probe(struct usb_interf
 {
 	const struct firmware *firmware;
 	struct usb_device *udev = interface_to_usbdev(intf);
-	struct ath3k_data *data;
-	int size;
 
 	BT_DBG("intf %p id %p", intf, id);
 
 	if (intf->cur_altsetting->desc.bInterfaceNumber != 0)
 		return -ENODEV;
 
-	data = kzalloc(sizeof(*data), GFP_KERNEL);
-	if (!data)
-		return -ENOMEM;
-
-	data->udev = udev;
-
 	if (reject_firmware(&firmware, "/*(DEBLOBBED)*/", &udev->dev) < 0) {
-		kfree(data);
 		return -EIO;
 	}
 
-	size = max_t(uint, firmware->size, 4096);
-	data->fw_data = kmalloc(size, GFP_KERNEL);
-	if (!data->fw_data) {
+	if (ath3k_load_firmware(udev, firmware)) {
 		release_firmware(firmware);
-		kfree(data);
-		return -ENOMEM;
-	}
-
-	memcpy(data->fw_data, firmware->data, firmware->size);
-	data->fw_size = firmware->size;
-	data->fw_sent = 0;
-	release_firmware(firmware);
-
-	usb_set_intfdata(intf, data);
-	if (ath3k_load_firmware(data, data->fw_data, data->fw_size)) {
-		usb_set_intfdata(intf, NULL);
-		kfree(data->fw_data);
-		kfree(data);
 		return -EIO;
 	}
+	release_firmware(firmware);
 
 	return 0;
 }
 
 static void ath3k_disconnect(struct usb_interface *intf)
 {
-	struct ath3k_data *data = usb_get_intfdata(intf);
-
 	BT_DBG("ath3k_disconnect intf %p", intf);
-
-	kfree(data->fw_data);
-	kfree(data);
 }
 
 static struct usb_driver ath3k_driver = {
diff -druNp linux-libre-2.6.37-gnu1/drivers/bluetooth/btusb.c linux-libre-2.6.38-gnu1/drivers/bluetooth/btusb.c
--- linux-libre-2.6.37-gnu1/drivers/bluetooth/btusb.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/bluetooth/btusb.c	2011-03-14 21:20:32.000000000 -0400
@@ -102,6 +102,12 @@ static struct usb_device_id blacklist_ta
 	/* Atheros 3011 with sflash firmware */
 	{ USB_DEVICE(0x0cf3, 0x3002), .driver_info = BTUSB_IGNORE },
 
+	/* Atheros AR9285 Malbec with sflash firmware */
+	{ USB_DEVICE(0x03f0, 0x311d), .driver_info = BTUSB_IGNORE },
+
+	/* Atheros AR5BBU12 with sflash firmware */
+	{ USB_DEVICE(0x0489, 0xe02c), .driver_info = BTUSB_IGNORE },
+
 	/* Broadcom BCM2035 */
 	{ USB_DEVICE(0x0a5c, 0x2035), .driver_info = BTUSB_WRONG_SCO_MTU },
 	{ USB_DEVICE(0x0a5c, 0x200a), .driver_info = BTUSB_WRONG_SCO_MTU },
@@ -826,7 +832,7 @@ static void btusb_work(struct work_struc
 
 	if (hdev->conn_hash.sco_num > 0) {
 		if (!test_bit(BTUSB_DID_ISO_RESUME, &data->flags)) {
-			err = usb_autopm_get_interface(data->isoc);
+			err = usb_autopm_get_interface(data->isoc ? data->isoc : data->intf);
 			if (err < 0) {
 				clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
 				usb_kill_anchored_urbs(&data->isoc_anchor);
@@ -855,7 +861,7 @@ static void btusb_work(struct work_struc
 
 		__set_isoc_interface(hdev, 0);
 		if (test_and_clear_bit(BTUSB_DID_ISO_RESUME, &data->flags))
-			usb_autopm_put_interface(data->isoc);
+			usb_autopm_put_interface(data->isoc ? data->isoc : data->intf);
 	}
 }
 
@@ -1038,8 +1044,6 @@ static int btusb_probe(struct usb_interf
 
 	usb_set_intfdata(intf, data);
 
-	usb_enable_autosuspend(interface_to_usbdev(intf));
-
 	return 0;
 }
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/cdrom/cdrom.c linux-libre-2.6.38-gnu1/drivers/cdrom/cdrom.c
--- linux-libre-2.6.37-gnu1/drivers/cdrom/cdrom.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/cdrom/cdrom.c	2011-03-14 21:20:32.000000000 -0400
@@ -409,7 +409,8 @@ int register_cdrom(struct cdrom_device_i
 	}
 
 	ENSURE(drive_status, CDC_DRIVE_STATUS );
-	ENSURE(media_changed, CDC_MEDIA_CHANGED);
+	if (cdo->check_events == NULL && cdo->media_changed == NULL)
+		*change_capability = ~(CDC_MEDIA_CHANGED | CDC_SELECT_DISC);
 	ENSURE(tray_move, CDC_CLOSE_TRAY | CDC_OPEN_TRAY);
 	ENSURE(lock_door, CDC_LOCK);
 	ENSURE(select_speed, CDC_SELECT_SPEED);
@@ -1348,7 +1349,10 @@ static int cdrom_select_disc(struct cdro
 	if (!CDROM_CAN(CDC_SELECT_DISC))
 		return -EDRIVE_CANT_DO_THIS;
 
-	(void) cdi->ops->media_changed(cdi, slot);
+	if (cdi->ops->check_events)
+		cdi->ops->check_events(cdi, 0, slot);
+	else
+		cdi->ops->media_changed(cdi, slot);
 
 	if (slot == CDSL_NONE) {
 		/* set media changed bits, on both queues */
@@ -1392,6 +1396,42 @@ static int cdrom_select_disc(struct cdro
 	return slot;
 }
 
+/*
+ * As cdrom implements an extra ioctl consumer for media changed
+ * event, it needs to buffer ->check_events() output, such that event
+ * is not lost for both the usual VFS and ioctl paths.
+ * cdi->{vfs|ioctl}_events are used to buffer pending events for each
+ * path.
+ *
+ * XXX: Locking is non-existent.  cdi->ops->check_events() can be
+ * called in parallel and buffering fields are accessed without any
+ * exclusion.  The original media_changed code had the same problem.
+ * It might be better to simply deprecate CDROM_MEDIA_CHANGED ioctl
+ * and remove this cruft altogether.  It doesn't have much usefulness
+ * at this point.
+ */
+static void cdrom_update_events(struct cdrom_device_info *cdi,
+				unsigned int clearing)
+{
+	unsigned int events;
+
+	events = cdi->ops->check_events(cdi, clearing, CDSL_CURRENT);
+	cdi->vfs_events |= events;
+	cdi->ioctl_events |= events;
+}
+
+unsigned int cdrom_check_events(struct cdrom_device_info *cdi,
+				unsigned int clearing)
+{
+	unsigned int events;
+
+	cdrom_update_events(cdi, clearing);
+	events = cdi->vfs_events;
+	cdi->vfs_events = 0;
+	return events;
+}
+EXPORT_SYMBOL(cdrom_check_events);
+
 /* We want to make media_changed accessible to the user through an
  * ioctl. The main problem now is that we must double-buffer the
  * low-level implementation, to assure that the VFS and the user both
@@ -1403,15 +1443,26 @@ int media_changed(struct cdrom_device_in
 {
 	unsigned int mask = (1 << (queue & 1));
 	int ret = !!(cdi->mc_flags & mask);
+	bool changed;
 
 	if (!CDROM_CAN(CDC_MEDIA_CHANGED))
-	    return ret;
+		return ret;
+
 	/* changed since last call? */
-	if (cdi->ops->media_changed(cdi, CDSL_CURRENT)) {
+	if (cdi->ops->check_events) {
+		BUG_ON(!queue);	/* shouldn't be called from VFS path */
+		cdrom_update_events(cdi, DISK_EVENT_MEDIA_CHANGE);
+		changed = cdi->ioctl_events & DISK_EVENT_MEDIA_CHANGE;
+		cdi->ioctl_events = 0;
+	} else
+		changed = cdi->ops->media_changed(cdi, CDSL_CURRENT);
+
+	if (changed) {
 		cdi->mc_flags = 0x3;    /* set bit on both queues */
 		ret |= 1;
 		cdi->media_written = 0;
 	}
+
 	cdi->mc_flags &= ~mask;         /* clear bit */
 	return ret;
 }
diff -druNp linux-libre-2.6.37-gnu1/drivers/cdrom/gdrom.c linux-libre-2.6.38-gnu1/drivers/cdrom/gdrom.c
--- linux-libre-2.6.37-gnu1/drivers/cdrom/gdrom.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/cdrom/gdrom.c	2011-03-14 21:20:32.000000000 -0400
@@ -837,7 +837,7 @@ probe_fail_no_mem:
 
 static int __devexit remove_gdrom(struct platform_device *devptr)
 {
-	flush_scheduled_work();
+	flush_work_sync(&work);
 	blk_cleanup_queue(gd.gdrom_rq);
 	free_irq(HW_EVENT_GDROM_CMD, &gd);
 	free_irq(HW_EVENT_GDROM_DMA, &gd);
diff -druNp linux-libre-2.6.37-gnu1/drivers/char/agp/agp.h linux-libre-2.6.38-gnu1/drivers/char/agp/agp.h
--- linux-libre-2.6.37-gnu1/drivers/char/agp/agp.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/char/agp/agp.h	2011-03-14 21:20:32.000000000 -0400
@@ -120,7 +120,6 @@ struct agp_bridge_driver {
 	void (*agp_destroy_page)(struct page *, int flags);
 	void (*agp_destroy_pages)(struct agp_memory *);
 	int (*agp_type_to_mask_type) (struct agp_bridge_data *, int);
-	void (*chipset_flush)(struct agp_bridge_data *);
 };
 
 struct agp_bridge_data {
diff -druNp linux-libre-2.6.37-gnu1/drivers/char/agp/amd64-agp.c linux-libre-2.6.38-gnu1/drivers/char/agp/amd64-agp.c
--- linux-libre-2.6.37-gnu1/drivers/char/agp/amd64-agp.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/char/agp/amd64-agp.c	2011-03-14 21:20:32.000000000 -0400
@@ -38,7 +38,7 @@ static int agp_bridges_found;
 
 static void amd64_tlbflush(struct agp_memory *temp)
 {
-	k8_flush_garts();
+	amd_flush_garts();
 }
 
 static int amd64_insert_memory(struct agp_memory *mem, off_t pg_start, int type)
@@ -124,7 +124,7 @@ static int amd64_fetch_size(void)
 	u32 temp;
 	struct aper_size_info_32 *values;
 
-	dev = k8_northbridges.nb_misc[0];
+	dev = node_to_amd_nb(0)->misc;
 	if (dev==NULL)
 		return 0;
 
@@ -181,16 +181,15 @@ static int amd_8151_configure(void)
 	unsigned long gatt_bus = virt_to_phys(agp_bridge->gatt_table_real);
 	int i;
 
-	if (!k8_northbridges.gart_supported)
+	if (!amd_nb_has_feature(AMD_NB_GART))
 		return 0;
 
 	/* Configure AGP regs in each x86-64 host bridge. */
-	for (i = 0; i < k8_northbridges.num; i++) {
+	for (i = 0; i < amd_nb_num(); i++) {
 		agp_bridge->gart_bus_addr =
-				amd64_configure(k8_northbridges.nb_misc[i],
-						gatt_bus);
+			amd64_configure(node_to_amd_nb(i)->misc, gatt_bus);
 	}
-	k8_flush_garts();
+	amd_flush_garts();
 	return 0;
 }
 
@@ -200,11 +199,11 @@ static void amd64_cleanup(void)
 	u32 tmp;
 	int i;
 
-	if (!k8_northbridges.gart_supported)
+	if (!amd_nb_has_feature(AMD_NB_GART))
 		return;
 
-	for (i = 0; i < k8_northbridges.num; i++) {
-		struct pci_dev *dev = k8_northbridges.nb_misc[i];
+	for (i = 0; i < amd_nb_num(); i++) {
+		struct pci_dev *dev = node_to_amd_nb(i)->misc;
 		/* disable gart translation */
 		pci_read_config_dword(dev, AMD64_GARTAPERTURECTL, &tmp);
 		tmp &= ~GARTEN;
@@ -331,15 +330,15 @@ static __devinit int cache_nbs(struct pc
 {
 	int i;
 
-	if (cache_k8_northbridges() < 0)
+	if (amd_cache_northbridges() < 0)
 		return -ENODEV;
 
-	if (!k8_northbridges.gart_supported)
+	if (!amd_nb_has_feature(AMD_NB_GART))
 		return -ENODEV;
 
 	i = 0;
-	for (i = 0; i < k8_northbridges.num; i++) {
-		struct pci_dev *dev = k8_northbridges.nb_misc[i];
+	for (i = 0; i < amd_nb_num(); i++) {
+		struct pci_dev *dev = node_to_amd_nb(i)->misc;
 		if (fix_northbridge(dev, pdev, cap_ptr) < 0) {
 			dev_err(&dev->dev, "no usable aperture found\n");
 #ifdef __x86_64__
@@ -416,7 +415,7 @@ static int __devinit uli_agp_init(struct
 	}
 
 	/* shadow x86-64 registers into ULi registers */
-	pci_read_config_dword (k8_northbridges.nb_misc[0], AMD64_GARTAPERTUREBASE,
+	pci_read_config_dword (node_to_amd_nb(0)->misc, AMD64_GARTAPERTUREBASE,
 			       &httfea);
 
 	/* if x86-64 aperture base is beyond 4G, exit here */
@@ -484,7 +483,7 @@ static int nforce3_agp_init(struct pci_d
 	pci_write_config_dword(dev1, NVIDIA_X86_64_1_APSIZE, tmp);
 
 	/* shadow x86-64 registers into NVIDIA registers */
-	pci_read_config_dword (k8_northbridges.nb_misc[0], AMD64_GARTAPERTUREBASE,
+	pci_read_config_dword (node_to_amd_nb(0)->misc, AMD64_GARTAPERTUREBASE,
 			       &apbase);
 
 	/* if x86-64 aperture base is beyond 4G, exit here */
@@ -774,18 +773,23 @@ int __init agp_amd64_init(void)
 #else
 			printk(KERN_INFO PFX "You can boot with agp=try_unsupported\n");
 #endif
+			pci_unregister_driver(&agp_amd64_pci_driver);
 			return -ENODEV;
 		}
 
 		/* First check that we have at least one AMD64 NB */
-		if (!pci_dev_present(k8_nb_ids))
+		if (!pci_dev_present(amd_nb_misc_ids)) {
+			pci_unregister_driver(&agp_amd64_pci_driver);
 			return -ENODEV;
+		}
 
 		/* Look for any AGP bridge */
 		agp_amd64_pci_driver.id_table = agp_amd64_pci_promisc_table;
 		err = driver_attach(&agp_amd64_pci_driver.driver);
-		if (err == 0 && agp_bridges_found == 0)
+		if (err == 0 && agp_bridges_found == 0) {
+			pci_unregister_driver(&agp_amd64_pci_driver);
 			err = -ENODEV;
+		}
 	}
 	return err;
 }
diff -druNp linux-libre-2.6.37-gnu1/drivers/char/agp/amd-k7-agp.c linux-libre-2.6.38-gnu1/drivers/char/agp/amd-k7-agp.c
--- linux-libre-2.6.37-gnu1/drivers/char/agp/amd-k7-agp.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/char/agp/amd-k7-agp.c	2011-03-14 21:20:32.000000000 -0400
@@ -41,22 +41,8 @@ static int amd_create_page_map(struct am
 	if (page_map->real == NULL)
 		return -ENOMEM;
 
-#ifndef CONFIG_X86
-	SetPageReserved(virt_to_page(page_map->real));
-	global_cache_flush();
-	page_map->remapped = ioremap_nocache(virt_to_phys(page_map->real),
-					    PAGE_SIZE);
-	if (page_map->remapped == NULL) {
-		ClearPageReserved(virt_to_page(page_map->real));
-		free_page((unsigned long) page_map->real);
-		page_map->real = NULL;
-		return -ENOMEM;
-	}
-	global_cache_flush();
-#else
 	set_memory_uc((unsigned long)page_map->real, 1);
 	page_map->remapped = page_map->real;
-#endif
 
 	for (i = 0; i < PAGE_SIZE / sizeof(unsigned long); i++) {
 		writel(agp_bridge->scratch_page, page_map->remapped+i);
@@ -68,12 +54,7 @@ static int amd_create_page_map(struct am
 
 static void amd_free_page_map(struct amd_page_map *page_map)
 {
-#ifndef CONFIG_X86
-	iounmap(page_map->remapped);
-	ClearPageReserved(virt_to_page(page_map->real));
-#else
 	set_memory_wb((unsigned long)page_map->real, 1);
-#endif
 	free_page((unsigned long) page_map->real);
 }
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/char/agp/compat_ioctl.c linux-libre-2.6.38-gnu1/drivers/char/agp/compat_ioctl.c
--- linux-libre-2.6.37-gnu1/drivers/char/agp/compat_ioctl.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/char/agp/compat_ioctl.c	2011-03-14 21:20:32.000000000 -0400
@@ -276,7 +276,6 @@ long compat_agp_ioctl(struct file *file,
 		break;
 
 	case AGPIOC_CHIPSET_FLUSH32:
-		ret_val = agpioc_chipset_flush_wrap(curr_priv);
 		break;
 	}
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/char/agp/compat_ioctl.h linux-libre-2.6.38-gnu1/drivers/char/agp/compat_ioctl.h
--- linux-libre-2.6.37-gnu1/drivers/char/agp/compat_ioctl.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/char/agp/compat_ioctl.h	2011-03-14 21:20:32.000000000 -0400
@@ -102,6 +102,5 @@ void agp_free_memory_wrap(struct agp_mem
 struct agp_memory *agp_allocate_memory_wrap(size_t pg_count, u32 type);
 struct agp_memory *agp_find_mem_by_key(int key);
 struct agp_client *agp_find_client_by_pid(pid_t id);
-int agpioc_chipset_flush_wrap(struct agp_file_private *priv);
 
 #endif /* _AGP_COMPAT_H */
diff -druNp linux-libre-2.6.37-gnu1/drivers/char/agp/frontend.c linux-libre-2.6.38-gnu1/drivers/char/agp/frontend.c
--- linux-libre-2.6.37-gnu1/drivers/char/agp/frontend.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/char/agp/frontend.c	2011-03-14 21:20:32.000000000 -0400
@@ -957,13 +957,6 @@ static int agpioc_unbind_wrap(struct agp
 	return agp_unbind_memory(memory);
 }
 
-int agpioc_chipset_flush_wrap(struct agp_file_private *priv)
-{
-	DBG("");
-	agp_flush_chipset(agp_bridge);
-	return 0;
-}
-
 static long agp_ioctl(struct file *file,
 		     unsigned int cmd, unsigned long arg)
 {
@@ -1039,7 +1032,6 @@ static long agp_ioctl(struct file *file,
 		break;
 	       
 	case AGPIOC_CHIPSET_FLUSH:
-		ret_val = agpioc_chipset_flush_wrap(curr_priv);
 		break;
 	}
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/char/agp/generic.c linux-libre-2.6.38-gnu1/drivers/char/agp/generic.c
--- linux-libre-2.6.37-gnu1/drivers/char/agp/generic.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/char/agp/generic.c	2011-03-14 21:20:32.000000000 -0400
@@ -81,13 +81,6 @@ static int agp_get_key(void)
 	return -1;
 }
 
-void agp_flush_chipset(struct agp_bridge_data *bridge)
-{
-	if (bridge->driver->chipset_flush)
-		bridge->driver->chipset_flush(bridge);
-}
-EXPORT_SYMBOL(agp_flush_chipset);
-
 /*
  * Use kmalloc if possible for the page list. Otherwise fall back to
  * vmalloc. This speeds things up and also saves memory for small AGP
@@ -487,26 +480,6 @@ int agp_unbind_memory(struct agp_memory
 }
 EXPORT_SYMBOL(agp_unbind_memory);
 
-/**
- *	agp_rebind_emmory  -  Rewrite the entire GATT, useful on resume
- */
-int agp_rebind_memory(void)
-{
-	struct agp_memory *curr;
-	int ret_val = 0;
-
-	spin_lock(&agp_bridge->mapped_lock);
-	list_for_each_entry(curr, &agp_bridge->mapped_list, mapped_list) {
-		ret_val = curr->bridge->driver->insert_memory(curr,
-							      curr->pg_start,
-							      curr->type);
-		if (ret_val != 0)
-			break;
-	}
-	spin_unlock(&agp_bridge->mapped_lock);
-	return ret_val;
-}
-EXPORT_SYMBOL(agp_rebind_memory);
 
 /* End - Routines for handling swapping of agp_memory into the GATT */
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/char/agp/intel-agp.c linux-libre-2.6.38-gnu1/drivers/char/agp/intel-agp.c
--- linux-libre-2.6.37-gnu1/drivers/char/agp/intel-agp.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/char/agp/intel-agp.c	2011-03-14 21:20:32.000000000 -0400
@@ -717,8 +717,8 @@ static const struct intel_agp_driver_des
 	{ PCI_DEVICE_ID_INTEL_82820_UP_HB, "i820", &intel_820_driver },
 	{ PCI_DEVICE_ID_INTEL_82830_HB, "830M", &intel_830mp_driver },
 	{ PCI_DEVICE_ID_INTEL_82840_HB, "i840", &intel_840_driver },
-	{ PCI_DEVICE_ID_INTEL_82845_HB, "845G", &intel_845_driver },
-	{ PCI_DEVICE_ID_INTEL_82845G_HB, "830M", &intel_845_driver },
+	{ PCI_DEVICE_ID_INTEL_82845_HB, "i845", &intel_845_driver },
+	{ PCI_DEVICE_ID_INTEL_82845G_HB, "845G", &intel_845_driver },
 	{ PCI_DEVICE_ID_INTEL_82850_HB, "i850", &intel_850_driver },
 	{ PCI_DEVICE_ID_INTEL_82854_HB, "854", &intel_845_driver },
 	{ PCI_DEVICE_ID_INTEL_82855PM_HB, "855PM", &intel_845_driver },
@@ -774,20 +774,14 @@ static int __devinit agp_intel_probe(str
 	dev_info(&pdev->dev, "Intel %s Chipset\n", intel_agp_chipsets[i].name);
 
 	/*
-	* If the device has not been properly setup, the following will catch
-	* the problem and should stop the system from crashing.
-	* 20030610 - hamish@zot.org
-	*/
-	if (pci_enable_device(pdev)) {
-		dev_err(&pdev->dev, "can't enable PCI device\n");
-		agp_put_bridge(bridge);
-		return -ENODEV;
-	}
-
-	/*
 	* The following fixes the case where the BIOS has "forgotten" to
 	* provide an address range for the GART.
 	* 20030610 - hamish@zot.org
+	* This happens before pci_enable_device() intentionally;
+	* calling pci_enable_device() before assigning the resource
+	* will result in the GART being disabled on machines with such
+	* BIOSs (the GART ends up with a BAR starting at 0, which
+	* conflicts a lot of other devices).
 	*/
 	r = &pdev->resource[0];
 	if (!r->start && r->end) {
@@ -798,6 +792,17 @@ static int __devinit agp_intel_probe(str
 		}
 	}
 
+	/*
+	* If the device has not been properly setup, the following will catch
+	* the problem and should stop the system from crashing.
+	* 20030610 - hamish@zot.org
+	*/
+	if (pci_enable_device(pdev)) {
+		dev_err(&pdev->dev, "can't enable PCI device\n");
+		agp_put_bridge(bridge);
+		return -ENODEV;
+	}
+
 	/* Fill in the mode register */
 	if (cap_ptr) {
 		pci_read_config_dword(pdev,
@@ -828,14 +833,9 @@ static void __devexit agp_intel_remove(s
 static int agp_intel_resume(struct pci_dev *pdev)
 {
 	struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
-	int ret_val;
 
 	bridge->driver->configure();
 
-	ret_val = agp_rebind_memory();
-	if (ret_val != 0)
-		return ret_val;
-
 	return 0;
 }
 #endif
diff -druNp linux-libre-2.6.37-gnu1/drivers/char/agp/intel-agp.h linux-libre-2.6.38-gnu1/drivers/char/agp/intel-agp.h
--- linux-libre-2.6.37-gnu1/drivers/char/agp/intel-agp.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/char/agp/intel-agp.h	2011-03-14 21:20:32.000000000 -0400
@@ -75,6 +75,8 @@
 #define I810_GMS_DISABLE	0x00000000
 #define I810_PGETBL_CTL		0x2020
 #define I810_PGETBL_ENABLED	0x00000001
+/* Note: PGETBL_CTL2 has a different offset on G33. */
+#define I965_PGETBL_CTL2	0x20c4
 #define I965_PGETBL_SIZE_MASK	0x0000000e
 #define I965_PGETBL_SIZE_512KB	(0 << 1)
 #define I965_PGETBL_SIZE_256KB	(1 << 1)
@@ -82,9 +84,17 @@
 #define I965_PGETBL_SIZE_1MB	(3 << 1)
 #define I965_PGETBL_SIZE_2MB	(4 << 1)
 #define I965_PGETBL_SIZE_1_5MB	(5 << 1)
-#define G33_PGETBL_SIZE_MASK    (3 << 8)
-#define G33_PGETBL_SIZE_1M      (1 << 8)
-#define G33_PGETBL_SIZE_2M      (2 << 8)
+#define G33_GMCH_SIZE_MASK	(3 << 8)
+#define G33_GMCH_SIZE_1M	(1 << 8)
+#define G33_GMCH_SIZE_2M	(2 << 8)
+#define G4x_GMCH_SIZE_MASK	(0xf << 8)
+#define G4x_GMCH_SIZE_1M	(0x1 << 8)
+#define G4x_GMCH_SIZE_2M	(0x3 << 8)
+#define G4x_GMCH_SIZE_VT_1M	(0x9 << 8)
+#define G4x_GMCH_SIZE_VT_1_5M	(0xa << 8)
+#define G4x_GMCH_SIZE_VT_2M	(0xc << 8)
+
+#define GFX_FLSH_CNTL		0x2170 /* 915+ */
 
 #define I810_DRAM_CTL		0x3000
 #define I810_DRAM_ROW_0		0x00000001
@@ -120,6 +130,7 @@
 #define INTEL_GMCH_GMS_STOLEN_352M	(0xd << 4)
 
 #define I915_IFPADDR    0x60
+#define I830_HIC        0x70
 
 /* Intel 965G registers */
 #define I965_MSAC 0x62
diff -druNp linux-libre-2.6.37-gnu1/drivers/char/agp/intel-gtt.c linux-libre-2.6.38-gnu1/drivers/char/agp/intel-gtt.c
--- linux-libre-2.6.37-gnu1/drivers/char/agp/intel-gtt.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/char/agp/intel-gtt.c	2011-03-14 21:20:32.000000000 -0400
@@ -21,10 +21,10 @@
 #include <linux/kernel.h>
 #include <linux/pagemap.h>
 #include <linux/agp_backend.h>
+#include <linux/delay.h>
 #include <asm/smp.h>
 #include "agp.h"
 #include "intel-agp.h"
-#include <linux/intel-gtt.h>
 #include <drm/intel-gtt.h>
 
 /*
@@ -39,40 +39,12 @@
 #define USE_PCI_DMA_API 0
 #endif
 
-/* Max amount of stolen space, anything above will be returned to Linux */
-int intel_max_stolen = 32 * 1024 * 1024;
-
-static const struct aper_size_info_fixed intel_i810_sizes[] =
-{
-	{64, 16384, 4},
-	/* The 32M mode still requires a 64k gatt */
-	{32, 8192, 4}
-};
-
-#define AGP_DCACHE_MEMORY	1
-#define AGP_PHYS_MEMORY		2
-#define INTEL_AGP_CACHED_MEMORY 3
-
-static struct gatt_mask intel_i810_masks[] =
-{
-	{.mask = I810_PTE_VALID, .type = 0},
-	{.mask = (I810_PTE_VALID | I810_PTE_LOCAL), .type = AGP_DCACHE_MEMORY},
-	{.mask = I810_PTE_VALID, .type = 0},
-	{.mask = I810_PTE_VALID | I830_PTE_SYSTEM_CACHED,
-	 .type = INTEL_AGP_CACHED_MEMORY}
-};
-
-#define INTEL_AGP_UNCACHED_MEMORY              0
-#define INTEL_AGP_CACHED_MEMORY_LLC            1
-#define INTEL_AGP_CACHED_MEMORY_LLC_GFDT       2
-#define INTEL_AGP_CACHED_MEMORY_LLC_MLC        3
-#define INTEL_AGP_CACHED_MEMORY_LLC_MLC_GFDT   4
-
 struct intel_gtt_driver {
 	unsigned int gen : 8;
 	unsigned int is_g33 : 1;
 	unsigned int is_pineview : 1;
 	unsigned int is_ironlake : 1;
+	unsigned int has_pgtbl_enable : 1;
 	unsigned int dma_mask_size : 8;
 	/* Chipset specific GTT setup */
 	int (*setup)(void);
@@ -95,14 +67,12 @@ static struct _intel_private {
 	u8 __iomem *registers;
 	phys_addr_t gtt_bus_addr;
 	phys_addr_t gma_bus_addr;
-	phys_addr_t pte_bus_addr;
+	u32 PGETBL_save;
 	u32 __iomem *gtt;		/* I915G */
+	bool clear_fake_agp; /* on first access via agp, fill with scratch */
 	int num_dcache_entries;
-	union {
-		void __iomem *i9xx_flush_page;
-		void *i8xx_flush_page;
-	};
-	struct page *i8xx_page;
+	void __iomem *i9xx_flush_page;
+	char *i81x_gtt_table;
 	struct resource ifp_resource;
 	int resource_valid;
 	struct page *scratch_page;
@@ -113,42 +83,31 @@ static struct _intel_private {
 #define IS_G33		intel_private.driver->is_g33
 #define IS_PINEVIEW	intel_private.driver->is_pineview
 #define IS_IRONLAKE	intel_private.driver->is_ironlake
+#define HAS_PGTBL_EN	intel_private.driver->has_pgtbl_enable
 
-static void intel_agp_free_sglist(struct agp_memory *mem)
-{
-	struct sg_table st;
-
-	st.sgl = mem->sg_list;
-	st.orig_nents = st.nents = mem->page_count;
-
-	sg_free_table(&st);
-
-	mem->sg_list = NULL;
-	mem->num_sg = 0;
-}
-
-static int intel_agp_map_memory(struct agp_memory *mem)
+int intel_gtt_map_memory(struct page **pages, unsigned int num_entries,
+			 struct scatterlist **sg_list, int *num_sg)
 {
 	struct sg_table st;
 	struct scatterlist *sg;
 	int i;
 
-	if (mem->sg_list)
+	if (*sg_list)
 		return 0; /* already mapped (for e.g. resume */
 
-	DBG("try mapping %lu pages\n", (unsigned long)mem->page_count);
+	DBG("try mapping %lu pages\n", (unsigned long)num_entries);
 
-	if (sg_alloc_table(&st, mem->page_count, GFP_KERNEL))
+	if (sg_alloc_table(&st, num_entries, GFP_KERNEL))
 		goto err;
 
-	mem->sg_list = sg = st.sgl;
+	*sg_list = sg = st.sgl;
 
-	for (i = 0 ; i < mem->page_count; i++, sg = sg_next(sg))
-		sg_set_page(sg, mem->pages[i], PAGE_SIZE, 0);
+	for (i = 0 ; i < num_entries; i++, sg = sg_next(sg))
+		sg_set_page(sg, pages[i], PAGE_SIZE, 0);
 
-	mem->num_sg = pci_map_sg(intel_private.pcidev, mem->sg_list,
-				 mem->page_count, PCI_DMA_BIDIRECTIONAL);
-	if (unlikely(!mem->num_sg))
+	*num_sg = pci_map_sg(intel_private.pcidev, *sg_list,
+				 num_entries, PCI_DMA_BIDIRECTIONAL);
+	if (unlikely(!*num_sg))
 		goto err;
 
 	return 0;
@@ -157,90 +116,22 @@ err:
 	sg_free_table(&st);
 	return -ENOMEM;
 }
+EXPORT_SYMBOL(intel_gtt_map_memory);
 
-static void intel_agp_unmap_memory(struct agp_memory *mem)
+void intel_gtt_unmap_memory(struct scatterlist *sg_list, int num_sg)
 {
+	struct sg_table st;
 	DBG("try unmapping %lu pages\n", (unsigned long)mem->page_count);
 
-	pci_unmap_sg(intel_private.pcidev, mem->sg_list,
-		     mem->page_count, PCI_DMA_BIDIRECTIONAL);
-	intel_agp_free_sglist(mem);
-}
-
-static int intel_i810_fetch_size(void)
-{
-	u32 smram_miscc;
-	struct aper_size_info_fixed *values;
-
-	pci_read_config_dword(intel_private.bridge_dev,
-			      I810_SMRAM_MISCC, &smram_miscc);
-	values = A_SIZE_FIX(agp_bridge->driver->aperture_sizes);
-
-	if ((smram_miscc & I810_GMS) == I810_GMS_DISABLE) {
-		dev_warn(&intel_private.bridge_dev->dev, "i810 is disabled\n");
-		return 0;
-	}
-	if ((smram_miscc & I810_GFX_MEM_WIN_SIZE) == I810_GFX_MEM_WIN_32M) {
-		agp_bridge->current_size = (void *) (values + 1);
-		agp_bridge->aperture_size_idx = 1;
-		return values[1].size;
-	} else {
-		agp_bridge->current_size = (void *) (values);
-		agp_bridge->aperture_size_idx = 0;
-		return values[0].size;
-	}
-
-	return 0;
-}
-
-static int intel_i810_configure(void)
-{
-	struct aper_size_info_fixed *current_size;
-	u32 temp;
-	int i;
-
-	current_size = A_SIZE_FIX(agp_bridge->current_size);
-
-	if (!intel_private.registers) {
-		pci_read_config_dword(intel_private.pcidev, I810_MMADDR, &temp);
-		temp &= 0xfff80000;
-
-		intel_private.registers = ioremap(temp, 128 * 4096);
-		if (!intel_private.registers) {
-			dev_err(&intel_private.pcidev->dev,
-				"can't remap memory\n");
-			return -ENOMEM;
-		}
-	}
-
-	if ((readl(intel_private.registers+I810_DRAM_CTL)
-		& I810_DRAM_ROW_0) == I810_DRAM_ROW_0_SDRAM) {
-		/* This will need to be dynamically assigned */
-		dev_info(&intel_private.pcidev->dev,
-			 "detected 4MB dedicated video ram\n");
-		intel_private.num_dcache_entries = 1024;
-	}
-	pci_read_config_dword(intel_private.pcidev, I810_GMADDR, &temp);
-	agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
-	writel(agp_bridge->gatt_bus_addr | I810_PGETBL_ENABLED, intel_private.registers+I810_PGETBL_CTL);
-	readl(intel_private.registers+I810_PGETBL_CTL);	/* PCI Posting. */
+	pci_unmap_sg(intel_private.pcidev, sg_list,
+		     num_sg, PCI_DMA_BIDIRECTIONAL);
 
-	if (agp_bridge->driver->needs_scratch_page) {
-		for (i = 0; i < current_size->num_entries; i++) {
-			writel(agp_bridge->scratch_page, intel_private.registers+I810_PTE_BASE+(i*4));
-		}
-		readl(intel_private.registers+I810_PTE_BASE+((i-1)*4));	/* PCI posting. */
-	}
-	global_cache_flush();
-	return 0;
-}
+	st.sgl = sg_list;
+	st.orig_nents = st.nents = num_sg;
 
-static void intel_i810_cleanup(void)
-{
-	writel(0, intel_private.registers+I810_PGETBL_CTL);
-	readl(intel_private.registers);	/* PCI Posting. */
-	iounmap(intel_private.registers);
+	sg_free_table(&st);
 }
+EXPORT_SYMBOL(intel_gtt_unmap_memory);
 
 static void intel_fake_agp_enable(struct agp_bridge_data *bridge, u32 mode)
 {
@@ -277,80 +168,64 @@ static void i8xx_destroy_pages(struct pa
 	atomic_dec(&agp_bridge->current_memory_agp);
 }
 
-static int intel_i810_insert_entries(struct agp_memory *mem, off_t pg_start,
-				int type)
+#define I810_GTT_ORDER 4
+static int i810_setup(void)
 {
-	int i, j, num_entries;
-	void *temp;
-	int ret = -EINVAL;
-	int mask_type;
-
-	if (mem->page_count == 0)
-		goto out;
-
-	temp = agp_bridge->current_size;
-	num_entries = A_SIZE_FIX(temp)->num_entries;
+	u32 reg_addr;
+	char *gtt_table;
 
-	if ((pg_start + mem->page_count) > num_entries)
-		goto out_err;
+	/* i81x does not preallocate the gtt. It's always 64kb in size. */
+	gtt_table = alloc_gatt_pages(I810_GTT_ORDER);
+	if (gtt_table == NULL)
+		return -ENOMEM;
+	intel_private.i81x_gtt_table = gtt_table;
 
+	pci_read_config_dword(intel_private.pcidev, I810_MMADDR, &reg_addr);
+	reg_addr &= 0xfff80000;
 
-	for (j = pg_start; j < (pg_start + mem->page_count); j++) {
-		if (!PGE_EMPTY(agp_bridge, readl(agp_bridge->gatt_table+j))) {
-			ret = -EBUSY;
-			goto out_err;
-		}
-	}
+	intel_private.registers = ioremap(reg_addr, KB(64));
+	if (!intel_private.registers)
+		return -ENOMEM;
 
-	if (type != mem->type)
-		goto out_err;
+	writel(virt_to_phys(gtt_table) | I810_PGETBL_ENABLED,
+	       intel_private.registers+I810_PGETBL_CTL);
 
-	mask_type = agp_bridge->driver->agp_type_to_mask_type(agp_bridge, type);
+	intel_private.gtt_bus_addr = reg_addr + I810_PTE_BASE;
 
-	switch (mask_type) {
-	case AGP_DCACHE_MEMORY:
-		if (!mem->is_flushed)
-			global_cache_flush();
-		for (i = pg_start; i < (pg_start + mem->page_count); i++) {
-			writel((i*4096)|I810_PTE_LOCAL|I810_PTE_VALID,
-			       intel_private.registers+I810_PTE_BASE+(i*4));
-		}
-		readl(intel_private.registers+I810_PTE_BASE+((i-1)*4));
-		break;
-	case AGP_PHYS_MEMORY:
-	case AGP_NORMAL_MEMORY:
-		if (!mem->is_flushed)
-			global_cache_flush();
-		for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
-			writel(agp_bridge->driver->mask_memory(agp_bridge,
-					page_to_phys(mem->pages[i]), mask_type),
-			       intel_private.registers+I810_PTE_BASE+(j*4));
-		}
-		readl(intel_private.registers+I810_PTE_BASE+((j-1)*4));
-		break;
-	default:
-		goto out_err;
+	if ((readl(intel_private.registers+I810_DRAM_CTL)
+		& I810_DRAM_ROW_0) == I810_DRAM_ROW_0_SDRAM) {
+		dev_info(&intel_private.pcidev->dev,
+			 "detected 4MB dedicated video ram\n");
+		intel_private.num_dcache_entries = 1024;
 	}
 
-out:
-	ret = 0;
-out_err:
-	mem->is_flushed = true;
-	return ret;
+	return 0;
 }
 
-static int intel_i810_remove_entries(struct agp_memory *mem, off_t pg_start,
-				int type)
+static void i810_cleanup(void)
+{
+	writel(0, intel_private.registers+I810_PGETBL_CTL);
+	free_gatt_pages(intel_private.i81x_gtt_table, I810_GTT_ORDER);
+}
+
+static int i810_insert_dcache_entries(struct agp_memory *mem, off_t pg_start,
+				      int type)
 {
 	int i;
 
-	if (mem->page_count == 0)
-		return 0;
+	if ((pg_start + mem->page_count)
+			> intel_private.num_dcache_entries)
+		return -EINVAL;
 
-	for (i = pg_start; i < (mem->page_count + pg_start); i++) {
-		writel(agp_bridge->scratch_page, intel_private.registers+I810_PTE_BASE+(i*4));
+	if (!mem->is_flushed)
+		global_cache_flush();
+
+	for (i = pg_start; i < (pg_start + mem->page_count); i++) {
+		dma_addr_t addr = i << PAGE_SHIFT;
+		intel_private.driver->write_entry(addr,
+						  i, type);
 	}
-	readl(intel_private.registers+I810_PTE_BASE+((i-1)*4));
+	readl(intel_private.gtt+i-1);
 
 	return 0;
 }
@@ -397,29 +272,6 @@ static struct agp_memory *alloc_agpphysm
 	return new;
 }
 
-static struct agp_memory *intel_i810_alloc_by_type(size_t pg_count, int type)
-{
-	struct agp_memory *new;
-
-	if (type == AGP_DCACHE_MEMORY) {
-		if (pg_count != intel_private.num_dcache_entries)
-			return NULL;
-
-		new = agp_create_memory(1);
-		if (new == NULL)
-			return NULL;
-
-		new->type = AGP_DCACHE_MEMORY;
-		new->page_count = pg_count;
-		new->num_scratch_pages = 0;
-		agp_free_page_array(new);
-		return new;
-	}
-	if (type == AGP_PHYS_MEMORY)
-		return alloc_agpphysmem_i8xx(pg_count, type);
-	return NULL;
-}
-
 static void intel_i810_free_by_type(struct agp_memory *curr)
 {
 	agp_free_key(curr->key);
@@ -437,13 +289,6 @@ static void intel_i810_free_by_type(stru
 	kfree(curr);
 }
 
-static unsigned long intel_i810_mask_memory(struct agp_bridge_data *bridge,
-					    dma_addr_t addr, int type)
-{
-	/* Type checking must be done elsewhere */
-	return addr | bridge->driver->masks[type].mask;
-}
-
 static int intel_gtt_setup_scratch_page(void)
 {
 	struct page *page;
@@ -455,7 +300,7 @@ static int intel_gtt_setup_scratch_page(
 	get_page(page);
 	set_pages_uc(page, 1);
 
-	if (USE_PCI_DMA_API && INTEL_GTT_GEN > 2) {
+	if (intel_private.base.needs_dmar) {
 		dma_addr = pci_map_page(intel_private.pcidev, page, 0,
 				    PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
 		if (pci_dma_mapping_error(intel_private.pcidev, dma_addr))
@@ -470,34 +315,45 @@ static int intel_gtt_setup_scratch_page(
 	return 0;
 }
 
-static const struct aper_size_info_fixed const intel_fake_agp_sizes[] = {
+static void i810_write_entry(dma_addr_t addr, unsigned int entry,
+			     unsigned int flags)
+{
+	u32 pte_flags = I810_PTE_VALID;
+
+	switch (flags) {
+	case AGP_DCACHE_MEMORY:
+		pte_flags |= I810_PTE_LOCAL;
+		break;
+	case AGP_USER_CACHED_MEMORY:
+		pte_flags |= I830_PTE_SYSTEM_CACHED;
+		break;
+	}
+
+	writel(addr | pte_flags, intel_private.gtt + entry);
+}
+
+static const struct aper_size_info_fixed intel_fake_agp_sizes[] = {
+	{32, 8192, 3},
+	{64, 16384, 4},
 	{128, 32768, 5},
-	/* The 64M mode still requires a 128k gatt */
-	{64, 16384, 5},
 	{256, 65536, 6},
 	{512, 131072, 7},
 };
 
-static unsigned int intel_gtt_stolen_entries(void)
+static unsigned int intel_gtt_stolen_size(void)
 {
 	u16 gmch_ctrl;
 	u8 rdct;
 	int local = 0;
 	static const int ddt[4] = { 0, 16, 32, 64 };
-	unsigned int overhead_entries, stolen_entries;
 	unsigned int stolen_size = 0;
 
+	if (INTEL_GTT_GEN == 1)
+		return 0; /* no stolen mem on i81x */
+
 	pci_read_config_word(intel_private.bridge_dev,
 			     I830_GMCH_CTRL, &gmch_ctrl);
 
-	if (INTEL_GTT_GEN > 4 || IS_PINEVIEW)
-		overhead_entries = 0;
-	else
-		overhead_entries = intel_private.base.gtt_mappable_entries
-			/ 1024;
-
-	overhead_entries += 1; /* BIOS popup */
-
 	if (intel_private.bridge_dev->device == PCI_DEVICE_ID_INTEL_82830_HB ||
 	    intel_private.bridge_dev->device == PCI_DEVICE_ID_INTEL_82845G_HB) {
 		switch (gmch_ctrl & I830_GMCH_GMS_MASK) {
@@ -623,12 +479,7 @@ static unsigned int intel_gtt_stolen_ent
 		}
 	}
 
-	if (!local && stolen_size > intel_max_stolen) {
-		dev_info(&intel_private.bridge_dev->dev,
-			 "detected %dK stolen memory, trimming to %dK\n",
-			 stolen_size / KB(1), intel_max_stolen / KB(1));
-		stolen_size = intel_max_stolen;
-	} else if (stolen_size > 0) {
+	if (stolen_size > 0) {
 		dev_info(&intel_private.bridge_dev->dev, "detected %dK %s memory\n",
 		       stolen_size / KB(1), local ? "local" : "stolen");
 	} else {
@@ -637,46 +488,88 @@ static unsigned int intel_gtt_stolen_ent
 		stolen_size = 0;
 	}
 
-	stolen_entries = stolen_size/KB(4) - overhead_entries;
+	return stolen_size;
+}
 
-	return stolen_entries;
+static void i965_adjust_pgetbl_size(unsigned int size_flag)
+{
+	u32 pgetbl_ctl, pgetbl_ctl2;
+
+	/* ensure that ppgtt is disabled */
+	pgetbl_ctl2 = readl(intel_private.registers+I965_PGETBL_CTL2);
+	pgetbl_ctl2 &= ~I810_PGETBL_ENABLED;
+	writel(pgetbl_ctl2, intel_private.registers+I965_PGETBL_CTL2);
+
+	/* write the new ggtt size */
+	pgetbl_ctl = readl(intel_private.registers+I810_PGETBL_CTL);
+	pgetbl_ctl &= ~I965_PGETBL_SIZE_MASK;
+	pgetbl_ctl |= size_flag;
+	writel(pgetbl_ctl, intel_private.registers+I810_PGETBL_CTL);
 }
 
-static unsigned int intel_gtt_total_entries(void)
+static unsigned int i965_gtt_total_entries(void)
 {
 	int size;
+	u32 pgetbl_ctl;
+	u16 gmch_ctl;
 
-	if (IS_G33 || INTEL_GTT_GEN == 4 || INTEL_GTT_GEN == 5) {
-		u32 pgetbl_ctl;
-		pgetbl_ctl = readl(intel_private.registers+I810_PGETBL_CTL);
+	pci_read_config_word(intel_private.bridge_dev,
+			     I830_GMCH_CTRL, &gmch_ctl);
 
-		switch (pgetbl_ctl & I965_PGETBL_SIZE_MASK) {
-		case I965_PGETBL_SIZE_128KB:
-			size = KB(128);
-			break;
-		case I965_PGETBL_SIZE_256KB:
-			size = KB(256);
-			break;
-		case I965_PGETBL_SIZE_512KB:
-			size = KB(512);
-			break;
-		case I965_PGETBL_SIZE_1MB:
-			size = KB(1024);
+	if (INTEL_GTT_GEN == 5) {
+		switch (gmch_ctl & G4x_GMCH_SIZE_MASK) {
+		case G4x_GMCH_SIZE_1M:
+		case G4x_GMCH_SIZE_VT_1M:
+			i965_adjust_pgetbl_size(I965_PGETBL_SIZE_1MB);
 			break;
-		case I965_PGETBL_SIZE_2MB:
-			size = KB(2048);
+		case G4x_GMCH_SIZE_VT_1_5M:
+			i965_adjust_pgetbl_size(I965_PGETBL_SIZE_1_5MB);
 			break;
-		case I965_PGETBL_SIZE_1_5MB:
-			size = KB(1024 + 512);
+		case G4x_GMCH_SIZE_2M:
+		case G4x_GMCH_SIZE_VT_2M:
+			i965_adjust_pgetbl_size(I965_PGETBL_SIZE_2MB);
 			break;
-		default:
-			dev_info(&intel_private.pcidev->dev,
-				 "unknown page table size, assuming 512KB\n");
-			size = KB(512);
 		}
+	}
 
-		return size/4;
-	} else if (INTEL_GTT_GEN == 6) {
+	pgetbl_ctl = readl(intel_private.registers+I810_PGETBL_CTL);
+
+	switch (pgetbl_ctl & I965_PGETBL_SIZE_MASK) {
+	case I965_PGETBL_SIZE_128KB:
+		size = KB(128);
+		break;
+	case I965_PGETBL_SIZE_256KB:
+		size = KB(256);
+		break;
+	case I965_PGETBL_SIZE_512KB:
+		size = KB(512);
+		break;
+	/* GTT pagetable sizes bigger than 512KB are not possible on G33! */
+	case I965_PGETBL_SIZE_1MB:
+		size = KB(1024);
+		break;
+	case I965_PGETBL_SIZE_2MB:
+		size = KB(2048);
+		break;
+	case I965_PGETBL_SIZE_1_5MB:
+		size = KB(1024 + 512);
+		break;
+	default:
+		dev_info(&intel_private.pcidev->dev,
+			 "unknown page table size, assuming 512KB\n");
+		size = KB(512);
+	}
+
+	return size/4;
+}
+
+static unsigned int intel_gtt_total_entries(void)
+{
+	int size;
+
+	if (IS_G33 || INTEL_GTT_GEN == 4 || INTEL_GTT_GEN == 5)
+		return i965_gtt_total_entries();
+	else if (INTEL_GTT_GEN == 6) {
 		u16 snb_gmch_ctl;
 
 		pci_read_config_word(intel_private.pcidev, SNB_GMCH_CTRL, &snb_gmch_ctl);
@@ -706,7 +599,18 @@ static unsigned int intel_gtt_mappable_e
 {
 	unsigned int aperture_size;
 
-	if (INTEL_GTT_GEN == 2) {
+	if (INTEL_GTT_GEN == 1) {
+		u32 smram_miscc;
+
+		pci_read_config_dword(intel_private.bridge_dev,
+				      I810_SMRAM_MISCC, &smram_miscc);
+
+		if ((smram_miscc & I810_GFX_MEM_WIN_SIZE)
+				== I810_GFX_MEM_WIN_32M)
+			aperture_size = MB(32);
+		else
+			aperture_size = MB(64);
+	} else if (INTEL_GTT_GEN == 2) {
 		u16 gmch_ctrl;
 
 		pci_read_config_word(intel_private.bridge_dev,
@@ -739,7 +643,7 @@ static void intel_gtt_cleanup(void)
 
 	iounmap(intel_private.gtt);
 	iounmap(intel_private.registers);
-	
+
 	intel_gtt_teardown_scratch_page();
 }
 
@@ -755,6 +659,14 @@ static int intel_gtt_init(void)
 	intel_private.base.gtt_mappable_entries = intel_gtt_mappable_entries();
 	intel_private.base.gtt_total_entries = intel_gtt_total_entries();
 
+	/* save the PGETBL reg for resume */
+	intel_private.PGETBL_save =
+		readl(intel_private.registers+I810_PGETBL_CTL)
+			& ~I810_PGETBL_ENABLED;
+	/* we only ever restore the register when enabling the PGTBL... */
+	if (HAS_PGTBL_EN)
+		intel_private.PGETBL_save |= I810_PGETBL_ENABLED;
+
 	dev_info(&intel_private.bridge_dev->dev,
 			"detected gtt size: %dK total, %dK mappable\n",
 			intel_private.base.gtt_total_entries * 4,
@@ -772,14 +684,9 @@ static int intel_gtt_init(void)
 
 	global_cache_flush();   /* FIXME: ? */
 
-	/* we have to call this as early as possible after the MMIO base address is known */
-	intel_private.base.gtt_stolen_entries = intel_gtt_stolen_entries();
-	if (intel_private.base.gtt_stolen_entries == 0) {
-		intel_private.driver->cleanup();
-		iounmap(intel_private.registers);
-		iounmap(intel_private.gtt);
-		return -ENOMEM;
-	}
+	intel_private.base.stolen_size = intel_gtt_stolen_size();
+
+	intel_private.base.needs_dmar = USE_PCI_DMA_API && INTEL_GTT_GEN > 2;
 
 	ret = intel_gtt_setup_scratch_page();
 	if (ret != 0) {
@@ -812,28 +719,6 @@ static int intel_fake_agp_fetch_size(voi
 
 static void i830_cleanup(void)
 {
-	if (intel_private.i8xx_flush_page) {
-		kunmap(intel_private.i8xx_flush_page);
-		intel_private.i8xx_flush_page = NULL;
-	}
-
-	__free_page(intel_private.i8xx_page);
-	intel_private.i8xx_page = NULL;
-}
-
-static void intel_i830_setup_flush(void)
-{
-	/* return if we've already set the flush mechanism up */
-	if (intel_private.i8xx_page)
-		return;
-
-	intel_private.i8xx_page = alloc_page(GFP_KERNEL);
-	if (!intel_private.i8xx_page)
-		return;
-
-	intel_private.i8xx_flush_page = kmap(intel_private.i8xx_page);
-	if (!intel_private.i8xx_flush_page)
-		i830_cleanup();
 }
 
 /* The chipset_flush interface needs to get data that has already been
@@ -848,39 +733,46 @@ static void intel_i830_setup_flush(void)
  */
 static void i830_chipset_flush(void)
 {
-	unsigned int *pg = intel_private.i8xx_flush_page;
+	unsigned long timeout = jiffies + msecs_to_jiffies(1000);
 
-	memset(pg, 0, 1024);
+	/* Forcibly evict everything from the CPU write buffers.
+	 * clflush appears to be insufficient.
+	 */
+	wbinvd_on_all_cpus();
 
-	if (cpu_has_clflush)
-		clflush_cache_range(pg, 1024);
-	else if (wbinvd_on_all_cpus() != 0)
-		printk(KERN_ERR "Timed out waiting for cache flush.\n");
+	/* Now we've only seen documents for this magic bit on 855GM,
+	 * we hope it exists for the other gen2 chipsets...
+	 *
+	 * Also works as advertised on my 845G.
+	 */
+	writel(readl(intel_private.registers+I830_HIC) | (1<<31),
+	       intel_private.registers+I830_HIC);
+
+	while (readl(intel_private.registers+I830_HIC) & (1<<31)) {
+		if (time_after(jiffies, timeout))
+			break;
+
+		udelay(50);
+	}
 }
 
 static void i830_write_entry(dma_addr_t addr, unsigned int entry,
 			     unsigned int flags)
 {
 	u32 pte_flags = I810_PTE_VALID;
-	
-	switch (flags) {
-	case AGP_DCACHE_MEMORY:
-		pte_flags |= I810_PTE_LOCAL;
-		break;
-	case AGP_USER_CACHED_MEMORY:
+
+	if (flags ==  AGP_USER_CACHED_MEMORY)
 		pte_flags |= I830_PTE_SYSTEM_CACHED;
-		break;
-	}
 
 	writel(addr | pte_flags, intel_private.gtt + entry);
 }
 
-static void intel_enable_gtt(void)
+static bool intel_enable_gtt(void)
 {
 	u32 gma_addr;
-	u16 gmch_ctrl;
+	u8 __iomem *reg;
 
-	if (INTEL_GTT_GEN == 2)
+	if (INTEL_GTT_GEN <= 2)
 		pci_read_config_dword(intel_private.pcidev, I810_GMADDR,
 				      &gma_addr);
 	else
@@ -889,13 +781,47 @@ static void intel_enable_gtt(void)
 
 	intel_private.gma_bus_addr = (gma_addr & PCI_BASE_ADDRESS_MEM_MASK);
 
-	pci_read_config_word(intel_private.bridge_dev, I830_GMCH_CTRL, &gmch_ctrl);
-	gmch_ctrl |= I830_GMCH_ENABLED;
-	pci_write_config_word(intel_private.bridge_dev, I830_GMCH_CTRL, gmch_ctrl);
+	if (INTEL_GTT_GEN >= 6)
+	    return true;
 
-	writel(intel_private.pte_bus_addr|I810_PGETBL_ENABLED,
-	       intel_private.registers+I810_PGETBL_CTL);
-	readl(intel_private.registers+I810_PGETBL_CTL);	/* PCI Posting. */
+	if (INTEL_GTT_GEN == 2) {
+		u16 gmch_ctrl;
+
+		pci_read_config_word(intel_private.bridge_dev,
+				     I830_GMCH_CTRL, &gmch_ctrl);
+		gmch_ctrl |= I830_GMCH_ENABLED;
+		pci_write_config_word(intel_private.bridge_dev,
+				      I830_GMCH_CTRL, gmch_ctrl);
+
+		pci_read_config_word(intel_private.bridge_dev,
+				     I830_GMCH_CTRL, &gmch_ctrl);
+		if ((gmch_ctrl & I830_GMCH_ENABLED) == 0) {
+			dev_err(&intel_private.pcidev->dev,
+				"failed to enable the GTT: GMCH_CTRL=%x\n",
+				gmch_ctrl);
+			return false;
+		}
+	}
+
+	/* On the resume path we may be adjusting the PGTBL value, so
+	 * be paranoid and flush all chipset write buffers...
+	 */
+	if (INTEL_GTT_GEN >= 3)
+		writel(0, intel_private.registers+GFX_FLSH_CNTL);
+
+	reg = intel_private.registers+I810_PGETBL_CTL;
+	writel(intel_private.PGETBL_save, reg);
+	if (HAS_PGTBL_EN && (readl(reg) & I810_PGETBL_ENABLED) == 0) {
+		dev_err(&intel_private.pcidev->dev,
+			"failed to enable the GTT: PGETBL=%x [expected %x]\n",
+			readl(reg), intel_private.PGETBL_save);
+		return false;
+	}
+
+	if (INTEL_GTT_GEN >= 3)
+		writel(0, intel_private.registers+GFX_FLSH_CNTL);
+
+	return true;
 }
 
 static int i830_setup(void)
@@ -910,10 +836,6 @@ static int i830_setup(void)
 		return -ENOMEM;
 
 	intel_private.gtt_bus_addr = reg_addr + I810_PTE_BASE;
-	intel_private.pte_bus_addr =
-		readl(intel_private.registers+I810_PGETBL_CTL) & 0xfffff000;
-
-	intel_i830_setup_flush();
 
 	return 0;
 }
@@ -934,21 +856,12 @@ static int intel_fake_agp_free_gatt_tabl
 
 static int intel_fake_agp_configure(void)
 {
-	int i;
-
-	intel_enable_gtt();
+	if (!intel_enable_gtt())
+	    return -EIO;
 
+	intel_private.clear_fake_agp = true;
 	agp_bridge->gart_bus_addr = intel_private.gma_bus_addr;
 
-	for (i = intel_private.base.gtt_stolen_entries;
-			i < intel_private.base.gtt_total_entries; i++) {
-		intel_private.driver->write_entry(intel_private.scratch_page_dma,
-						  i, 0);
-	}
-	readl(intel_private.gtt+i-1);	/* PCI Posting. */
-
-	global_cache_flush();
-
 	return 0;
 }
 
@@ -965,10 +878,10 @@ static bool i830_check_flags(unsigned in
 	return false;
 }
 
-static void intel_gtt_insert_sg_entries(struct scatterlist *sg_list,
-					unsigned int sg_len,
-					unsigned int pg_start,
-					unsigned int flags)
+void intel_gtt_insert_sg_entries(struct scatterlist *sg_list,
+				 unsigned int sg_len,
+				 unsigned int pg_start,
+				 unsigned int flags)
 {
 	struct scatterlist *sg;
 	unsigned int len, m;
@@ -989,27 +902,41 @@ static void intel_gtt_insert_sg_entries(
 	}
 	readl(intel_private.gtt+j-1);
 }
+EXPORT_SYMBOL(intel_gtt_insert_sg_entries);
+
+void intel_gtt_insert_pages(unsigned int first_entry, unsigned int num_entries,
+			    struct page **pages, unsigned int flags)
+{
+	int i, j;
+
+	for (i = 0, j = first_entry; i < num_entries; i++, j++) {
+		dma_addr_t addr = page_to_phys(pages[i]);
+		intel_private.driver->write_entry(addr,
+						  j, flags);
+	}
+	readl(intel_private.gtt+j-1);
+}
+EXPORT_SYMBOL(intel_gtt_insert_pages);
 
 static int intel_fake_agp_insert_entries(struct agp_memory *mem,
 					 off_t pg_start, int type)
 {
-	int i, j;
 	int ret = -EINVAL;
 
-	if (mem->page_count == 0)
-		goto out;
+	if (intel_private.clear_fake_agp) {
+		int start = intel_private.base.stolen_size / PAGE_SIZE;
+		int end = intel_private.base.gtt_mappable_entries;
+		intel_gtt_clear_range(start, end - start);
+		intel_private.clear_fake_agp = false;
+	}
 
-	if (pg_start < intel_private.base.gtt_stolen_entries) {
-		dev_printk(KERN_DEBUG, &intel_private.pcidev->dev,
-			   "pg_start == 0x%.8lx, gtt_stolen_entries == 0x%.8x\n",
-			   pg_start, intel_private.base.gtt_stolen_entries);
+	if (INTEL_GTT_GEN == 1 && type == AGP_DCACHE_MEMORY)
+		return i810_insert_dcache_entries(mem, pg_start, type);
 
-		dev_info(&intel_private.pcidev->dev,
-			 "trying to insert into local/stolen memory\n");
-		goto out_err;
-	}
+	if (mem->page_count == 0)
+		goto out;
 
-	if ((pg_start + mem->page_count) > intel_private.base.gtt_total_entries)
+	if (pg_start + mem->page_count > intel_private.base.gtt_total_entries)
 		goto out_err;
 
 	if (type != mem->type)
@@ -1021,21 +948,17 @@ static int intel_fake_agp_insert_entries
 	if (!mem->is_flushed)
 		global_cache_flush();
 
-	if (USE_PCI_DMA_API && INTEL_GTT_GEN > 2) {
-		ret = intel_agp_map_memory(mem);
+	if (intel_private.base.needs_dmar) {
+		ret = intel_gtt_map_memory(mem->pages, mem->page_count,
+					   &mem->sg_list, &mem->num_sg);
 		if (ret != 0)
 			return ret;
 
 		intel_gtt_insert_sg_entries(mem->sg_list, mem->num_sg,
 					    pg_start, type);
-	} else {
-		for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
-			dma_addr_t addr = page_to_phys(mem->pages[i]);
-			intel_private.driver->write_entry(addr,
-							  j, type);
-		}
-		readl(intel_private.gtt+j-1);
-	}
+	} else
+		intel_gtt_insert_pages(pg_start, mem->page_count, mem->pages,
+				       type);
 
 out:
 	ret = 0;
@@ -1044,40 +967,54 @@ out_err:
 	return ret;
 }
 
+void intel_gtt_clear_range(unsigned int first_entry, unsigned int num_entries)
+{
+	unsigned int i;
+
+	for (i = first_entry; i < (first_entry + num_entries); i++) {
+		intel_private.driver->write_entry(intel_private.scratch_page_dma,
+						  i, 0);
+	}
+	readl(intel_private.gtt+i-1);
+}
+EXPORT_SYMBOL(intel_gtt_clear_range);
+
 static int intel_fake_agp_remove_entries(struct agp_memory *mem,
 					 off_t pg_start, int type)
 {
-	int i;
-
 	if (mem->page_count == 0)
 		return 0;
 
-	if (pg_start < intel_private.base.gtt_stolen_entries) {
-		dev_info(&intel_private.pcidev->dev,
-			 "trying to disable local/stolen memory\n");
-		return -EINVAL;
-	}
-
-	if (USE_PCI_DMA_API && INTEL_GTT_GEN > 2)
-		intel_agp_unmap_memory(mem);
+	intel_gtt_clear_range(pg_start, mem->page_count);
 
-	for (i = pg_start; i < (mem->page_count + pg_start); i++) {
-		intel_private.driver->write_entry(intel_private.scratch_page_dma,
-						  i, 0);
+	if (intel_private.base.needs_dmar) {
+		intel_gtt_unmap_memory(mem->sg_list, mem->num_sg);
+		mem->sg_list = NULL;
+		mem->num_sg = 0;
 	}
-	readl(intel_private.gtt+i-1);
 
 	return 0;
 }
 
-static void intel_fake_agp_chipset_flush(struct agp_bridge_data *bridge)
-{
-	intel_private.driver->chipset_flush();
-}
-
 static struct agp_memory *intel_fake_agp_alloc_by_type(size_t pg_count,
 						       int type)
 {
+	struct agp_memory *new;
+
+	if (type == AGP_DCACHE_MEMORY && INTEL_GTT_GEN == 1) {
+		if (pg_count != intel_private.num_dcache_entries)
+			return NULL;
+
+		new = agp_create_memory(1);
+		if (new == NULL)
+			return NULL;
+
+		new->type = AGP_DCACHE_MEMORY;
+		new->page_count = pg_count;
+		new->num_scratch_pages = 0;
+		agp_free_page_array(new);
+		return new;
+	}
 	if (type == AGP_PHYS_MEMORY)
 		return alloc_agpphysmem_i8xx(pg_count, type);
 	/* always return NULL for other allocation types for now */
@@ -1274,40 +1211,11 @@ static int i9xx_setup(void)
 		intel_private.gtt_bus_addr = reg_addr + gtt_offset;
 	}
 
-	intel_private.pte_bus_addr =
-		readl(intel_private.registers+I810_PGETBL_CTL) & 0xfffff000;
-
 	intel_i9xx_setup_flush();
 
 	return 0;
 }
 
-static const struct agp_bridge_driver intel_810_driver = {
-	.owner			= THIS_MODULE,
-	.aperture_sizes		= intel_i810_sizes,
-	.size_type		= FIXED_APER_SIZE,
-	.num_aperture_sizes	= 2,
-	.needs_scratch_page	= true,
-	.configure		= intel_i810_configure,
-	.fetch_size		= intel_i810_fetch_size,
-	.cleanup		= intel_i810_cleanup,
-	.mask_memory		= intel_i810_mask_memory,
-	.masks			= intel_i810_masks,
-	.agp_enable		= intel_fake_agp_enable,
-	.cache_flush		= global_cache_flush,
-	.create_gatt_table	= agp_generic_create_gatt_table,
-	.free_gatt_table	= agp_generic_free_gatt_table,
-	.insert_memory		= intel_i810_insert_entries,
-	.remove_memory		= intel_i810_remove_entries,
-	.alloc_by_type		= intel_i810_alloc_by_type,
-	.free_by_type		= intel_i810_free_by_type,
-	.agp_alloc_page		= agp_generic_alloc_page,
-	.agp_alloc_pages        = agp_generic_alloc_pages,
-	.agp_destroy_page	= agp_generic_destroy_page,
-	.agp_destroy_pages      = agp_generic_destroy_pages,
-	.agp_type_to_mask_type  = agp_generic_type_to_mask_type,
-};
-
 static const struct agp_bridge_driver intel_fake_agp_driver = {
 	.owner			= THIS_MODULE,
 	.size_type		= FIXED_APER_SIZE,
@@ -1328,15 +1236,20 @@ static const struct agp_bridge_driver in
 	.agp_alloc_pages        = agp_generic_alloc_pages,
 	.agp_destroy_page	= agp_generic_destroy_page,
 	.agp_destroy_pages      = agp_generic_destroy_pages,
-	.chipset_flush		= intel_fake_agp_chipset_flush,
 };
 
 static const struct intel_gtt_driver i81x_gtt_driver = {
 	.gen = 1,
+	.has_pgtbl_enable = 1,
 	.dma_mask_size = 32,
+	.setup = i810_setup,
+	.cleanup = i810_cleanup,
+	.check_flags = i830_check_flags,
+	.write_entry = i810_write_entry,
 };
 static const struct intel_gtt_driver i8xx_gtt_driver = {
 	.gen = 2,
+	.has_pgtbl_enable = 1,
 	.setup = i830_setup,
 	.cleanup = i830_cleanup,
 	.write_entry = i830_write_entry,
@@ -1346,10 +1259,11 @@ static const struct intel_gtt_driver i8x
 };
 static const struct intel_gtt_driver i915_gtt_driver = {
 	.gen = 3,
+	.has_pgtbl_enable = 1,
 	.setup = i9xx_setup,
 	.cleanup = i9xx_cleanup,
 	/* i945 is the last gpu to need phys mem (for overlay and cursors). */
-	.write_entry = i830_write_entry, 
+	.write_entry = i830_write_entry,
 	.dma_mask_size = 32,
 	.check_flags = i830_check_flags,
 	.chipset_flush = i9xx_chipset_flush,
@@ -1376,6 +1290,7 @@ static const struct intel_gtt_driver pin
 };
 static const struct intel_gtt_driver i965_gtt_driver = {
 	.gen = 4,
+	.has_pgtbl_enable = 1,
 	.setup = i9xx_setup,
 	.cleanup = i9xx_cleanup,
 	.write_entry = i965_write_entry,
@@ -1419,93 +1334,92 @@ static const struct intel_gtt_driver san
 static const struct intel_gtt_driver_description {
 	unsigned int gmch_chip_id;
 	char *name;
-	const struct agp_bridge_driver *gmch_driver;
 	const struct intel_gtt_driver *gtt_driver;
 } intel_gtt_chipsets[] = {
-	{ PCI_DEVICE_ID_INTEL_82810_IG1, "i810", &intel_810_driver,
+	{ PCI_DEVICE_ID_INTEL_82810_IG1, "i810",
 		&i81x_gtt_driver},
-	{ PCI_DEVICE_ID_INTEL_82810_IG3, "i810", &intel_810_driver,
+	{ PCI_DEVICE_ID_INTEL_82810_IG3, "i810",
 		&i81x_gtt_driver},
-	{ PCI_DEVICE_ID_INTEL_82810E_IG, "i810", &intel_810_driver,
+	{ PCI_DEVICE_ID_INTEL_82810E_IG, "i810",
 		&i81x_gtt_driver},
-	{ PCI_DEVICE_ID_INTEL_82815_CGC, "i815", &intel_810_driver,
+	{ PCI_DEVICE_ID_INTEL_82815_CGC, "i815",
 		&i81x_gtt_driver},
 	{ PCI_DEVICE_ID_INTEL_82830_CGC, "830M",
-		&intel_fake_agp_driver, &i8xx_gtt_driver},
-	{ PCI_DEVICE_ID_INTEL_82845G_IG, "830M",
-		&intel_fake_agp_driver, &i8xx_gtt_driver},
+		&i8xx_gtt_driver},
+	{ PCI_DEVICE_ID_INTEL_82845G_IG, "845G",
+		&i8xx_gtt_driver},
 	{ PCI_DEVICE_ID_INTEL_82854_IG, "854",
-		&intel_fake_agp_driver, &i8xx_gtt_driver},
+		&i8xx_gtt_driver},
 	{ PCI_DEVICE_ID_INTEL_82855GM_IG, "855GM",
-		&intel_fake_agp_driver, &i8xx_gtt_driver},
+		&i8xx_gtt_driver},
 	{ PCI_DEVICE_ID_INTEL_82865_IG, "865",
-		&intel_fake_agp_driver, &i8xx_gtt_driver},
+		&i8xx_gtt_driver},
 	{ PCI_DEVICE_ID_INTEL_E7221_IG, "E7221 (i915)",
-		&intel_fake_agp_driver, &i915_gtt_driver },
+		&i915_gtt_driver },
 	{ PCI_DEVICE_ID_INTEL_82915G_IG, "915G",
-		&intel_fake_agp_driver, &i915_gtt_driver },
+		&i915_gtt_driver },
 	{ PCI_DEVICE_ID_INTEL_82915GM_IG, "915GM",
-		&intel_fake_agp_driver, &i915_gtt_driver },
+		&i915_gtt_driver },
 	{ PCI_DEVICE_ID_INTEL_82945G_IG, "945G",
-		&intel_fake_agp_driver, &i915_gtt_driver },
+		&i915_gtt_driver },
 	{ PCI_DEVICE_ID_INTEL_82945GM_IG, "945GM",
-		&intel_fake_agp_driver, &i915_gtt_driver },
+		&i915_gtt_driver },
 	{ PCI_DEVICE_ID_INTEL_82945GME_IG, "945GME",
-		&intel_fake_agp_driver, &i915_gtt_driver },
+		&i915_gtt_driver },
 	{ PCI_DEVICE_ID_INTEL_82946GZ_IG, "946GZ",
-		&intel_fake_agp_driver, &i965_gtt_driver },
+		&i965_gtt_driver },
 	{ PCI_DEVICE_ID_INTEL_82G35_IG, "G35",
-		&intel_fake_agp_driver, &i965_gtt_driver },
+		&i965_gtt_driver },
 	{ PCI_DEVICE_ID_INTEL_82965Q_IG, "965Q",
-		&intel_fake_agp_driver, &i965_gtt_driver },
+		&i965_gtt_driver },
 	{ PCI_DEVICE_ID_INTEL_82965G_IG, "965G",
-		&intel_fake_agp_driver, &i965_gtt_driver },
+		&i965_gtt_driver },
 	{ PCI_DEVICE_ID_INTEL_82965GM_IG, "965GM",
-		&intel_fake_agp_driver, &i965_gtt_driver },
+		&i965_gtt_driver },
 	{ PCI_DEVICE_ID_INTEL_82965GME_IG, "965GME/GLE",
-		&intel_fake_agp_driver, &i965_gtt_driver },
+		&i965_gtt_driver },
 	{ PCI_DEVICE_ID_INTEL_G33_IG, "G33",
-		&intel_fake_agp_driver, &g33_gtt_driver },
+		&g33_gtt_driver },
 	{ PCI_DEVICE_ID_INTEL_Q35_IG, "Q35",
-		&intel_fake_agp_driver, &g33_gtt_driver },
+		&g33_gtt_driver },
 	{ PCI_DEVICE_ID_INTEL_Q33_IG, "Q33",
-		&intel_fake_agp_driver, &g33_gtt_driver },
+		&g33_gtt_driver },
 	{ PCI_DEVICE_ID_INTEL_PINEVIEW_M_IG, "GMA3150",
-		&intel_fake_agp_driver, &pineview_gtt_driver },
+		&pineview_gtt_driver },
 	{ PCI_DEVICE_ID_INTEL_PINEVIEW_IG, "GMA3150",
-		&intel_fake_agp_driver, &pineview_gtt_driver },
+		&pineview_gtt_driver },
 	{ PCI_DEVICE_ID_INTEL_GM45_IG, "GM45",
-		&intel_fake_agp_driver, &g4x_gtt_driver },
+		&g4x_gtt_driver },
 	{ PCI_DEVICE_ID_INTEL_EAGLELAKE_IG, "Eaglelake",
-		&intel_fake_agp_driver, &g4x_gtt_driver },
+		&g4x_gtt_driver },
 	{ PCI_DEVICE_ID_INTEL_Q45_IG, "Q45/Q43",
-		&intel_fake_agp_driver, &g4x_gtt_driver },
+		&g4x_gtt_driver },
 	{ PCI_DEVICE_ID_INTEL_G45_IG, "G45/G43",
-		&intel_fake_agp_driver, &g4x_gtt_driver },
+		&g4x_gtt_driver },
 	{ PCI_DEVICE_ID_INTEL_B43_IG, "B43",
-		&intel_fake_agp_driver, &g4x_gtt_driver },
+		&g4x_gtt_driver },
 	{ PCI_DEVICE_ID_INTEL_B43_1_IG, "B43",
-		&intel_fake_agp_driver, &g4x_gtt_driver },
+		&g4x_gtt_driver },
 	{ PCI_DEVICE_ID_INTEL_G41_IG, "G41",
-		&intel_fake_agp_driver, &g4x_gtt_driver },
+		&g4x_gtt_driver },
 	{ PCI_DEVICE_ID_INTEL_IRONLAKE_D_IG,
-	    "HD Graphics", &intel_fake_agp_driver, &ironlake_gtt_driver },
+	    "HD Graphics", &ironlake_gtt_driver },
 	{ PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG,
-	    "HD Graphics", &intel_fake_agp_driver, &ironlake_gtt_driver },
+	    "HD Graphics", &ironlake_gtt_driver },
 	{ PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT1_IG,
-	    "Sandybridge", &intel_fake_agp_driver, &sandybridge_gtt_driver },
+	    "Sandybridge", &sandybridge_gtt_driver },
 	{ PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT2_IG,
-	    "Sandybridge", &intel_fake_agp_driver, &sandybridge_gtt_driver },
+	    "Sandybridge", &sandybridge_gtt_driver },
 	{ PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT2_PLUS_IG,
-	    "Sandybridge", &intel_fake_agp_driver, &sandybridge_gtt_driver },
+	    "Sandybridge", &sandybridge_gtt_driver },
 	{ PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT1_IG,
-	    "Sandybridge", &intel_fake_agp_driver, &sandybridge_gtt_driver },
+	    "Sandybridge", &sandybridge_gtt_driver },
 	{ PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT2_IG,
-	    "Sandybridge", &intel_fake_agp_driver, &sandybridge_gtt_driver },
+	    "Sandybridge", &sandybridge_gtt_driver },
 	{ PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT2_PLUS_IG,
-	    "Sandybridge", &intel_fake_agp_driver, &sandybridge_gtt_driver },
+	    "Sandybridge", &sandybridge_gtt_driver },
 	{ PCI_DEVICE_ID_INTEL_SANDYBRIDGE_S_IG,
-	    "Sandybridge", &intel_fake_agp_driver, &sandybridge_gtt_driver },
+	    "Sandybridge", &sandybridge_gtt_driver },
 	{ 0, NULL, NULL }
 };
 
@@ -1530,21 +1444,20 @@ int intel_gmch_probe(struct pci_dev *pde
 				      struct agp_bridge_data *bridge)
 {
 	int i, mask;
-	bridge->driver = NULL;
+	intel_private.driver = NULL;
 
 	for (i = 0; intel_gtt_chipsets[i].name != NULL; i++) {
 		if (find_gmch(intel_gtt_chipsets[i].gmch_chip_id)) {
-			bridge->driver =
-				intel_gtt_chipsets[i].gmch_driver;
-			intel_private.driver = 
+			intel_private.driver =
 				intel_gtt_chipsets[i].gtt_driver;
 			break;
 		}
 	}
 
-	if (!bridge->driver)
+	if (!intel_private.driver)
 		return 0;
 
+	bridge->driver = &intel_fake_agp_driver;
 	bridge->dev_private_data = &intel_private;
 	bridge->dev = pdev;
 
@@ -1560,8 +1473,8 @@ int intel_gmch_probe(struct pci_dev *pde
 		pci_set_consistent_dma_mask(intel_private.pcidev,
 					    DMA_BIT_MASK(mask));
 
-	if (bridge->driver == &intel_810_driver)
-		return 1;
+	/*if (bridge->driver == &intel_810_driver)
+		return 1;*/
 
 	if (intel_gtt_init() != 0)
 		return 0;
@@ -1570,12 +1483,19 @@ int intel_gmch_probe(struct pci_dev *pde
 }
 EXPORT_SYMBOL(intel_gmch_probe);
 
-struct intel_gtt *intel_gtt_get(void)
+const struct intel_gtt *intel_gtt_get(void)
 {
 	return &intel_private.base;
 }
 EXPORT_SYMBOL(intel_gtt_get);
 
+void intel_gtt_chipset_flush(void)
+{
+	if (intel_private.driver->chipset_flush)
+		intel_private.driver->chipset_flush();
+}
+EXPORT_SYMBOL(intel_gtt_chipset_flush);
+
 void intel_gmch_remove(struct pci_dev *pdev)
 {
 	if (intel_private.pcidev)
diff -druNp linux-libre-2.6.37-gnu1/drivers/char/agp/Kconfig linux-libre-2.6.38-gnu1/drivers/char/agp/Kconfig
--- linux-libre-2.6.37-gnu1/drivers/char/agp/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/char/agp/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -50,7 +50,7 @@ config AGP_ATI
 
 config AGP_AMD
 	tristate "AMD Irongate, 761, and 762 chipset support"
-	depends on AGP && (X86_32 || ALPHA)
+	depends on AGP && X86_32
 	help
 	  This option gives you AGP support for the GLX component of
 	  X on AMD Irongate, 761, and 762 chipsets.
diff -druNp linux-libre-2.6.37-gnu1/drivers/char/bfin_jtag_comm.c linux-libre-2.6.38-gnu1/drivers/char/bfin_jtag_comm.c
--- linux-libre-2.6.37-gnu1/drivers/char/bfin_jtag_comm.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/char/bfin_jtag_comm.c	2011-03-14 21:20:32.000000000 -0400
@@ -183,16 +183,16 @@ bfin_jc_circ_write(const unsigned char *
 }
 
 #ifndef CONFIG_BFIN_JTAG_COMM_CONSOLE
-# define acquire_console_sem()
-# define release_console_sem()
+# define console_lock()
+# define console_unlock()
 #endif
 static int
 bfin_jc_write(struct tty_struct *tty, const unsigned char *buf, int count)
 {
 	int i;
-	acquire_console_sem();
+	console_lock();
 	i = bfin_jc_circ_write(buf, count);
-	release_console_sem();
+	console_unlock();
 	wake_up_process(bfin_jc_kthread);
 	return i;
 }
diff -druNp linux-libre-2.6.37-gnu1/drivers/char/cs5535_gpio.c linux-libre-2.6.38-gnu1/drivers/char/cs5535_gpio.c
--- linux-libre-2.6.37-gnu1/drivers/char/cs5535_gpio.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/char/cs5535_gpio.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,259 +0,0 @@
-/*
- * AMD CS5535/CS5536 GPIO driver.
- * Allows a user space process to play with the GPIO pins.
- *
- * Copyright (c) 2005 Ben Gardner <bgardner@wabtec.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the smems of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- */
-
-#include <linux/fs.h>
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/cdev.h>
-#include <linux/ioport.h>
-#include <linux/pci.h>
-
-#include <asm/uaccess.h>
-#include <asm/io.h>
-
-
-#define NAME			"cs5535_gpio"
-
-MODULE_AUTHOR("Ben Gardner <bgardner@wabtec.com>");
-MODULE_DESCRIPTION("AMD CS5535/CS5536 GPIO Pin Driver");
-MODULE_LICENSE("GPL");
-
-static int major;
-module_param(major, int, 0);
-MODULE_PARM_DESC(major, "Major device number");
-
-static ulong mask;
-module_param(mask, ulong, 0);
-MODULE_PARM_DESC(mask, "GPIO channel mask");
-
-#define MSR_LBAR_GPIO		0x5140000C
-
-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);
-
-static struct cdev cs5535_gpio_cdev;
-
-/* reserve 32 entries even though some aren't usable */
-#define CS5535_GPIO_COUNT	32
-
-/* IO block size */
-#define CS5535_GPIO_SIZE	256
-
-struct gpio_regmap {
-	u32	rd_offset;
-	u32	wr_offset;
-	char	on;
-	char	off;
-};
-static struct gpio_regmap rm[] =
-{
-	{ 0x30, 0x00, '1', '0' },	/* GPIOx_READ_BACK / GPIOx_OUT_VAL */
-	{ 0x20, 0x20, 'I', 'i' },	/* GPIOx_IN_EN */
-	{ 0x04, 0x04, 'O', 'o' },	/* GPIOx_OUT_EN */
-	{ 0x08, 0x08, 't', 'T' },	/* GPIOx_OUT_OD_EN */
-	{ 0x18, 0x18, 'P', 'p' },	/* GPIOx_OUT_PU_EN */
-	{ 0x1c, 0x1c, 'D', 'd' },	/* GPIOx_OUT_PD_EN */
-};
-
-
-/**
- * Gets the register offset for the GPIO bank.
- * Low (0-15) starts at 0x00, high (16-31) starts at 0x80
- */
-static inline u32 cs5535_lowhigh_base(int reg)
-{
-	return (reg & 0x10) << 3;
-}
-
-static ssize_t cs5535_gpio_write(struct file *file, const char __user *data,
-				 size_t len, loff_t *ppos)
-{
-	u32	m = iminor(file->f_path.dentry->d_inode);
-	int	i, j;
-	u32	base = gpio_base + cs5535_lowhigh_base(m);
-	u32	m0, m1;
-	char	c;
-
-	/**
-	 * Creates the mask for atomic bit programming.
-	 * The high 16 bits and the low 16 bits are used to set the mask.
-	 * For example, GPIO 15 maps to 31,15: 0,1 => On; 1,0=> Off
-	 */
-	m1 = 1 << (m & 0x0F);
-	m0 = m1 << 16;
-
-	for (i = 0; i < len; ++i) {
-		if (get_user(c, data+i))
-			return -EFAULT;
-
-		for (j = 0; j < ARRAY_SIZE(rm); j++) {
-			if (c == rm[j].on) {
-				outl(m1, base + rm[j].wr_offset);
-				/* If enabling output, turn off AUX 1 and AUX 2 */
-				if (c == 'O') {
-					outl(m0, base + 0x10);
-					outl(m0, base + 0x14);
-				}
-				break;
-			} else if (c == rm[j].off) {
-				outl(m0, base + rm[j].wr_offset);
-				break;
-			}
-		}
-	}
-	*ppos = 0;
-	return len;
-}
-
-static ssize_t cs5535_gpio_read(struct file *file, char __user *buf,
-				size_t len, loff_t *ppos)
-{
-	u32	m = iminor(file->f_path.dentry->d_inode);
-	u32	base = gpio_base + cs5535_lowhigh_base(m);
-	int	rd_bit = 1 << (m & 0x0f);
-	int	i;
-	char	ch;
-	ssize_t	count = 0;
-
-	if (*ppos >= ARRAY_SIZE(rm))
-		return 0;
-
-	for (i = *ppos; (i < (*ppos + len)) && (i < ARRAY_SIZE(rm)); i++) {
-		ch = (inl(base + rm[i].rd_offset) & rd_bit) ?
-		     rm[i].on : rm[i].off;
-
-		if (put_user(ch, buf+count))
-			return -EFAULT;
-
-		count++;
-	}
-
-	/* add a line-feed if there is room */
-	if ((i == ARRAY_SIZE(rm)) && (count < len)) {
-		put_user('\n', buf + count);
-		count++;
-	}
-
-	*ppos += count;
-	return count;
-}
-
-static int cs5535_gpio_open(struct inode *inode, struct file *file)
-{
-	u32 m = iminor(inode);
-
-	/* the mask says which pins are usable by this driver */
-	if ((mask & (1 << m)) == 0)
-		return -EINVAL;
-
-	return nonseekable_open(inode, file);
-}
-
-static const struct file_operations cs5535_gpio_fops = {
-	.owner	= THIS_MODULE,
-	.write	= cs5535_gpio_write,
-	.read	= cs5535_gpio_read,
-	.open	= cs5535_gpio_open,
-	.llseek = no_llseek,
-};
-
-static int __init cs5535_gpio_init(void)
-{
-	dev_t	dev_id;
-	u32	low, hi;
-	int	retval;
-
-	if (pci_dev_present(divil_pci) == 0) {
-		printk(KERN_WARNING NAME ": 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 NAME ": GPIO not enabled\n");
-		return -ENODEV;
-	}
-
-	/* Mask off the IO base address */
-	gpio_base = low & 0x0000ff00;
-
-	/**
-	 * Some GPIO pins
-	 *  31-29,23 : reserved (always mask out)
-	 *  28       : Power Button
-	 *  26       : PME#
-	 *  22-16    : LPC
-	 *  14,15    : SMBus
-	 *  9,8      : UART1
-	 *  7        : PCI INTB
-	 *  3,4      : UART2/DDC
-	 *  2        : IDE_IRQ0
-	 *  0        : PCI INTA
-	 *
-	 * If a mask was not specified, be conservative and only allow:
-	 *  1,2,5,6,10-13,24,25,27
-	 */
-	if (mask != 0)
-		mask &= 0x1f7fffff;
-	else
-		mask = 0x0b003c66;
-
-	if (!request_region(gpio_base, CS5535_GPIO_SIZE, NAME)) {
-		printk(KERN_ERR NAME ": can't allocate I/O for GPIO\n");
-		return -ENODEV;
-	}
-
-	if (major) {
-		dev_id = MKDEV(major, 0);
-		retval = register_chrdev_region(dev_id, CS5535_GPIO_COUNT,
-						NAME);
-	} else {
-		retval = alloc_chrdev_region(&dev_id, 0, CS5535_GPIO_COUNT,
-					     NAME);
-		major = MAJOR(dev_id);
-	}
-
-	if (retval) {
-		release_region(gpio_base, CS5535_GPIO_SIZE);
-		return -1;
-	}
-
-	printk(KERN_DEBUG NAME ": base=%#x mask=%#lx major=%d\n",
-	       gpio_base, mask, major);
-
-	cdev_init(&cs5535_gpio_cdev, &cs5535_gpio_fops);
-	cdev_add(&cs5535_gpio_cdev, dev_id, CS5535_GPIO_COUNT);
-
-	return 0;
-}
-
-static void __exit cs5535_gpio_cleanup(void)
-{
-	dev_t dev_id = MKDEV(major, 0);
-
-	cdev_del(&cs5535_gpio_cdev);
-	unregister_chrdev_region(dev_id, CS5535_GPIO_COUNT);
-	release_region(gpio_base, CS5535_GPIO_SIZE);
-}
-
-module_init(cs5535_gpio_init);
-module_exit(cs5535_gpio_cleanup);
diff -druNp linux-libre-2.6.37-gnu1/drivers/char/hvc_beat.c linux-libre-2.6.38-gnu1/drivers/char/hvc_beat.c
--- linux-libre-2.6.37-gnu1/drivers/char/hvc_beat.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/char/hvc_beat.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,134 +0,0 @@
-/*
- * Beat hypervisor console driver
- *
- * (C) Copyright 2006 TOSHIBA CORPORATION
- *
- * This code is based on drivers/char/hvc_rtas.c:
- * (C) Copyright IBM Corporation 2001-2005
- * (C) Copyright Red Hat, Inc. 2005
- *
- * 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 <linux/init.h>
-#include <linux/err.h>
-#include <linux/string.h>
-#include <linux/console.h>
-#include <asm/prom.h>
-#include <asm/hvconsole.h>
-#include <asm/firmware.h>
-
-#include "hvc_console.h"
-
-extern int64_t beat_get_term_char(uint64_t, uint64_t *, uint64_t *, uint64_t *);
-extern int64_t beat_put_term_char(uint64_t, uint64_t, uint64_t, uint64_t);
-
-struct hvc_struct *hvc_beat_dev = NULL;
-
-/* bug: only one queue is available regardless of vtermno */
-static int hvc_beat_get_chars(uint32_t vtermno, char *buf, int cnt)
-{
-	static unsigned char q[sizeof(unsigned long) * 2]
-		__attribute__((aligned(sizeof(unsigned long))));
-	static int qlen = 0;
-	u64 got;
-
-again:
-	if (qlen) {
-		if (qlen > cnt) {
-			memcpy(buf, q, cnt);
-			qlen -= cnt;
-			memmove(q + cnt, q, qlen);
-			return cnt;
-		} else {	/* qlen <= cnt */
-			int	r;
-
-			memcpy(buf, q, qlen);
-			r = qlen;
-			qlen = 0;
-			return r;
-		}
-	}
-	if (beat_get_term_char(vtermno, &got,
-		((u64 *)q), ((u64 *)q) + 1) == 0) {
-		qlen = got;
-		goto again;
-	}
-	return 0;
-}
-
-static int hvc_beat_put_chars(uint32_t vtermno, const char *buf, int cnt)
-{
-	unsigned long kb[2];
-	int rest, nlen;
-
-	for (rest = cnt; rest > 0; rest -= nlen) {
-		nlen = (rest > 16) ? 16 : rest;
-		memcpy(kb, buf, nlen);
-		beat_put_term_char(vtermno, nlen, kb[0], kb[1]);
-		buf += nlen;
-	}
-	return cnt;
-}
-
-static const struct hv_ops hvc_beat_get_put_ops = {
-	.get_chars = hvc_beat_get_chars,
-	.put_chars = hvc_beat_put_chars,
-};
-
-static int hvc_beat_useit = 1;
-
-static int hvc_beat_config(char *p)
-{
-	hvc_beat_useit = simple_strtoul(p, NULL, 0);
-	return 0;
-}
-
-static int __init hvc_beat_console_init(void)
-{
-	if (hvc_beat_useit && of_machine_is_compatible("Beat")) {
-		hvc_instantiate(0, 0, &hvc_beat_get_put_ops);
-	}
-	return 0;
-}
-
-/* temp */
-static int __init hvc_beat_init(void)
-{
-	struct hvc_struct *hp;
-
-	if (!firmware_has_feature(FW_FEATURE_BEAT))
-		return -ENODEV;
-
-	hp = hvc_alloc(0, NO_IRQ, &hvc_beat_get_put_ops, 16);
-	if (IS_ERR(hp))
-		return PTR_ERR(hp);
-	hvc_beat_dev = hp;
-	return 0;
-}
-
-static void __exit hvc_beat_exit(void)
-{
-	if (hvc_beat_dev)
-		hvc_remove(hvc_beat_dev);
-}
-
-module_init(hvc_beat_init);
-module_exit(hvc_beat_exit);
-
-__setup("hvc_beat=", hvc_beat_config);
-
-console_initcall(hvc_beat_console_init);
diff -druNp linux-libre-2.6.37-gnu1/drivers/char/hvc_console.c linux-libre-2.6.38-gnu1/drivers/char/hvc_console.c
--- linux-libre-2.6.37-gnu1/drivers/char/hvc_console.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/char/hvc_console.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,914 +0,0 @@
-/*
- * Copyright (C) 2001 Anton Blanchard <anton@au.ibm.com>, IBM
- * Copyright (C) 2001 Paul Mackerras <paulus@au.ibm.com>, IBM
- * Copyright (C) 2004 Benjamin Herrenschmidt <benh@kernel.crashing.org>, IBM Corp.
- * Copyright (C) 2004 IBM Corporation
- *
- * Additional Author(s):
- *  Ryan S. Arnold <rsa@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/console.h>
-#include <linux/cpumask.h>
-#include <linux/init.h>
-#include <linux/kbd_kern.h>
-#include <linux/kernel.h>
-#include <linux/kthread.h>
-#include <linux/list.h>
-#include <linux/module.h>
-#include <linux/major.h>
-#include <linux/sysrq.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/sched.h>
-#include <linux/spinlock.h>
-#include <linux/delay.h>
-#include <linux/freezer.h>
-#include <linux/slab.h>
-
-#include <asm/uaccess.h>
-
-#include "hvc_console.h"
-
-#define HVC_MAJOR	229
-#define HVC_MINOR	0
-
-/*
- * Wait this long per iteration while trying to push buffered data to the
- * hypervisor before allowing the tty to complete a close operation.
- */
-#define HVC_CLOSE_WAIT (HZ/100) /* 1/10 of a second */
-
-/*
- * These sizes are most efficient for vio, because they are the
- * native transfer size. We could make them selectable in the
- * future to better deal with backends that want other buffer sizes.
- */
-#define N_OUTBUF	16
-#define N_INBUF		16
-
-#define __ALIGNED__ __attribute__((__aligned__(sizeof(long))))
-
-static struct tty_driver *hvc_driver;
-static struct task_struct *hvc_task;
-
-/* Picks up late kicks after list walk but before schedule() */
-static int hvc_kicked;
-
-static int hvc_init(void);
-
-#ifdef CONFIG_MAGIC_SYSRQ
-static int sysrq_pressed;
-#endif
-
-/* dynamic list of hvc_struct instances */
-static LIST_HEAD(hvc_structs);
-
-/*
- * Protect the list of hvc_struct instances from inserts and removals during
- * list traversal.
- */
-static DEFINE_SPINLOCK(hvc_structs_lock);
-
-/*
- * This value is used to assign a tty->index value to a hvc_struct based
- * upon order of exposure via hvc_probe(), when we can not match it to
- * a console candidate registered with hvc_instantiate().
- */
-static int last_hvc = -1;
-
-/*
- * Do not call this function with either the hvc_structs_lock or the hvc_struct
- * lock held.  If successful, this function increments the kref reference
- * count against the target hvc_struct so it should be released when finished.
- */
-static struct hvc_struct *hvc_get_by_index(int index)
-{
-	struct hvc_struct *hp;
-	unsigned long flags;
-
-	spin_lock(&hvc_structs_lock);
-
-	list_for_each_entry(hp, &hvc_structs, next) {
-		spin_lock_irqsave(&hp->lock, flags);
-		if (hp->index == index) {
-			kref_get(&hp->kref);
-			spin_unlock_irqrestore(&hp->lock, flags);
-			spin_unlock(&hvc_structs_lock);
-			return hp;
-		}
-		spin_unlock_irqrestore(&hp->lock, flags);
-	}
-	hp = NULL;
-
-	spin_unlock(&hvc_structs_lock);
-	return hp;
-}
-
-
-/*
- * Initial console vtermnos for console API usage prior to full console
- * initialization.  Any vty adapter outside this range will not have usable
- * console interfaces but can still be used as a tty device.  This has to be
- * static because kmalloc will not work during early console init.
- */
-static const struct hv_ops *cons_ops[MAX_NR_HVC_CONSOLES];
-static uint32_t vtermnos[MAX_NR_HVC_CONSOLES] =
-	{[0 ... MAX_NR_HVC_CONSOLES - 1] = -1};
-
-/*
- * Console APIs, NOT TTY.  These APIs are available immediately when
- * hvc_console_setup() finds adapters.
- */
-
-static void hvc_console_print(struct console *co, const char *b,
-			      unsigned count)
-{
-	char c[N_OUTBUF] __ALIGNED__;
-	unsigned i = 0, n = 0;
-	int r, donecr = 0, index = co->index;
-
-	/* Console access attempt outside of acceptable console range. */
-	if (index >= MAX_NR_HVC_CONSOLES)
-		return;
-
-	/* This console adapter was removed so it is not usable. */
-	if (vtermnos[index] == -1)
-		return;
-
-	while (count > 0 || i > 0) {
-		if (count > 0 && i < sizeof(c)) {
-			if (b[n] == '\n' && !donecr) {
-				c[i++] = '\r';
-				donecr = 1;
-			} else {
-				c[i++] = b[n++];
-				donecr = 0;
-				--count;
-			}
-		} else {
-			r = cons_ops[index]->put_chars(vtermnos[index], c, i);
-			if (r <= 0) {
-				/* throw away chars on error */
-				i = 0;
-			} else if (r > 0) {
-				i -= r;
-				if (i > 0)
-					memmove(c, c+r, i);
-			}
-		}
-	}
-}
-
-static struct tty_driver *hvc_console_device(struct console *c, int *index)
-{
-	if (vtermnos[c->index] == -1)
-		return NULL;
-
-	*index = c->index;
-	return hvc_driver;
-}
-
-static int __init hvc_console_setup(struct console *co, char *options)
-{
-	if (co->index < 0 || co->index >= MAX_NR_HVC_CONSOLES)
-		return -ENODEV;
-
-	if (vtermnos[co->index] == -1)
-		return -ENODEV;
-
-	return 0;
-}
-
-static struct console hvc_console = {
-	.name		= "hvc",
-	.write		= hvc_console_print,
-	.device		= hvc_console_device,
-	.setup		= hvc_console_setup,
-	.flags		= CON_PRINTBUFFER,
-	.index		= -1,
-};
-
-/*
- * Early console initialization.  Precedes driver initialization.
- *
- * (1) we are first, and the user specified another driver
- * -- index will remain -1
- * (2) we are first and the user specified no driver
- * -- index will be set to 0, then we will fail setup.
- * (3)  we are first and the user specified our driver
- * -- index will be set to user specified driver, and we will fail
- * (4) we are after driver, and this initcall will register us
- * -- if the user didn't specify a driver then the console will match
- *
- * Note that for cases 2 and 3, we will match later when the io driver
- * calls hvc_instantiate() and call register again.
- */
-static int __init hvc_console_init(void)
-{
-	register_console(&hvc_console);
-	return 0;
-}
-console_initcall(hvc_console_init);
-
-/* callback when the kboject ref count reaches zero. */
-static void destroy_hvc_struct(struct kref *kref)
-{
-	struct hvc_struct *hp = container_of(kref, struct hvc_struct, kref);
-	unsigned long flags;
-
-	spin_lock(&hvc_structs_lock);
-
-	spin_lock_irqsave(&hp->lock, flags);
-	list_del(&(hp->next));
-	spin_unlock_irqrestore(&hp->lock, flags);
-
-	spin_unlock(&hvc_structs_lock);
-
-	kfree(hp);
-}
-
-/*
- * hvc_instantiate() is an early console discovery method which locates
- * consoles * prior to the vio subsystem discovering them.  Hotplugged
- * vty adapters do NOT get an hvc_instantiate() callback since they
- * appear after early console init.
- */
-int hvc_instantiate(uint32_t vtermno, int index, const struct hv_ops *ops)
-{
-	struct hvc_struct *hp;
-
-	if (index < 0 || index >= MAX_NR_HVC_CONSOLES)
-		return -1;
-
-	if (vtermnos[index] != -1)
-		return -1;
-
-	/* make sure no no tty has been registered in this index */
-	hp = hvc_get_by_index(index);
-	if (hp) {
-		kref_put(&hp->kref, destroy_hvc_struct);
-		return -1;
-	}
-
-	vtermnos[index] = vtermno;
-	cons_ops[index] = ops;
-
-	/* reserve all indices up to and including this index */
-	if (last_hvc < index)
-		last_hvc = index;
-
-	/* if this index is what the user requested, then register
-	 * now (setup won't fail at this point).  It's ok to just
-	 * call register again if previously .setup failed.
-	 */
-	if (index == hvc_console.index)
-		register_console(&hvc_console);
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(hvc_instantiate);
-
-/* Wake the sleeping khvcd */
-void hvc_kick(void)
-{
-	hvc_kicked = 1;
-	wake_up_process(hvc_task);
-}
-EXPORT_SYMBOL_GPL(hvc_kick);
-
-static void hvc_unthrottle(struct tty_struct *tty)
-{
-	hvc_kick();
-}
-
-/*
- * The TTY interface won't be used until after the vio layer has exposed the vty
- * adapter to the kernel.
- */
-static int hvc_open(struct tty_struct *tty, struct file * filp)
-{
-	struct hvc_struct *hp;
-	unsigned long flags;
-	int rc = 0;
-
-	/* Auto increments kref reference if found. */
-	if (!(hp = hvc_get_by_index(tty->index)))
-		return -ENODEV;
-
-	spin_lock_irqsave(&hp->lock, flags);
-	/* Check and then increment for fast path open. */
-	if (hp->count++ > 0) {
-		tty_kref_get(tty);
-		spin_unlock_irqrestore(&hp->lock, flags);
-		hvc_kick();
-		return 0;
-	} /* else count == 0 */
-
-	tty->driver_data = hp;
-
-	hp->tty = tty_kref_get(tty);
-
-	spin_unlock_irqrestore(&hp->lock, flags);
-
-	if (hp->ops->notifier_add)
-		rc = hp->ops->notifier_add(hp, hp->data);
-
-	/*
-	 * If the notifier fails we return an error.  The tty layer
-	 * will call hvc_close() after a failed open but we don't want to clean
-	 * up there so we'll clean up here and clear out the previously set
-	 * tty fields and return the kref reference.
-	 */
-	if (rc) {
-		spin_lock_irqsave(&hp->lock, flags);
-		hp->tty = NULL;
-		spin_unlock_irqrestore(&hp->lock, flags);
-		tty_kref_put(tty);
-		tty->driver_data = NULL;
-		kref_put(&hp->kref, destroy_hvc_struct);
-		printk(KERN_ERR "hvc_open: request_irq failed with rc %d.\n", rc);
-	}
-	/* Force wakeup of the polling thread */
-	hvc_kick();
-
-	return rc;
-}
-
-static void hvc_close(struct tty_struct *tty, struct file * filp)
-{
-	struct hvc_struct *hp;
-	unsigned long flags;
-
-	if (tty_hung_up_p(filp))
-		return;
-
-	/*
-	 * No driver_data means that this close was issued after a failed
-	 * hvc_open by the tty layer's release_dev() function and we can just
-	 * exit cleanly because the kref reference wasn't made.
-	 */
-	if (!tty->driver_data)
-		return;
-
-	hp = tty->driver_data;
-
-	spin_lock_irqsave(&hp->lock, flags);
-
-	if (--hp->count == 0) {
-		/* We are done with the tty pointer now. */
-		hp->tty = NULL;
-		spin_unlock_irqrestore(&hp->lock, flags);
-
-		if (hp->ops->notifier_del)
-			hp->ops->notifier_del(hp, hp->data);
-
-		/* cancel pending tty resize work */
-		cancel_work_sync(&hp->tty_resize);
-
-		/*
-		 * Chain calls chars_in_buffer() and returns immediately if
-		 * there is no buffered data otherwise sleeps on a wait queue
-		 * waking periodically to check chars_in_buffer().
-		 */
-		tty_wait_until_sent(tty, HVC_CLOSE_WAIT);
-	} else {
-		if (hp->count < 0)
-			printk(KERN_ERR "hvc_close %X: oops, count is %d\n",
-				hp->vtermno, hp->count);
-		spin_unlock_irqrestore(&hp->lock, flags);
-	}
-
-	tty_kref_put(tty);
-	kref_put(&hp->kref, destroy_hvc_struct);
-}
-
-static void hvc_hangup(struct tty_struct *tty)
-{
-	struct hvc_struct *hp = tty->driver_data;
-	unsigned long flags;
-	int temp_open_count;
-
-	if (!hp)
-		return;
-
-	/* cancel pending tty resize work */
-	cancel_work_sync(&hp->tty_resize);
-
-	spin_lock_irqsave(&hp->lock, flags);
-
-	/*
-	 * The N_TTY line discipline has problems such that in a close vs
-	 * open->hangup case this can be called after the final close so prevent
-	 * that from happening for now.
-	 */
-	if (hp->count <= 0) {
-		spin_unlock_irqrestore(&hp->lock, flags);
-		return;
-	}
-
-	temp_open_count = hp->count;
-	hp->count = 0;
-	hp->n_outbuf = 0;
-	hp->tty = NULL;
-
-	spin_unlock_irqrestore(&hp->lock, flags);
-
-	if (hp->ops->notifier_hangup)
-		hp->ops->notifier_hangup(hp, hp->data);
-
-	while(temp_open_count) {
-		--temp_open_count;
-		tty_kref_put(tty);
-		kref_put(&hp->kref, destroy_hvc_struct);
-	}
-}
-
-/*
- * Push buffered characters whether they were just recently buffered or waiting
- * on a blocked hypervisor.  Call this function with hp->lock held.
- */
-static int hvc_push(struct hvc_struct *hp)
-{
-	int n;
-
-	n = hp->ops->put_chars(hp->vtermno, hp->outbuf, hp->n_outbuf);
-	if (n <= 0) {
-		if (n == 0) {
-			hp->do_wakeup = 1;
-			return 0;
-		}
-		/* throw away output on error; this happens when
-		   there is no session connected to the vterm. */
-		hp->n_outbuf = 0;
-	} else
-		hp->n_outbuf -= n;
-	if (hp->n_outbuf > 0)
-		memmove(hp->outbuf, hp->outbuf + n, hp->n_outbuf);
-	else
-		hp->do_wakeup = 1;
-
-	return n;
-}
-
-static int hvc_write(struct tty_struct *tty, const unsigned char *buf, int count)
-{
-	struct hvc_struct *hp = tty->driver_data;
-	unsigned long flags;
-	int rsize, written = 0;
-
-	/* This write was probably executed during a tty close. */
-	if (!hp)
-		return -EPIPE;
-
-	if (hp->count <= 0)
-		return -EIO;
-
-	spin_lock_irqsave(&hp->lock, flags);
-
-	/* Push pending writes */
-	if (hp->n_outbuf > 0)
-		hvc_push(hp);
-
-	while (count > 0 && (rsize = hp->outbuf_size - hp->n_outbuf) > 0) {
-		if (rsize > count)
-			rsize = count;
-		memcpy(hp->outbuf + hp->n_outbuf, buf, rsize);
-		count -= rsize;
-		buf += rsize;
-		hp->n_outbuf += rsize;
-		written += rsize;
-		hvc_push(hp);
-	}
-	spin_unlock_irqrestore(&hp->lock, flags);
-
-	/*
-	 * Racy, but harmless, kick thread if there is still pending data.
-	 */
-	if (hp->n_outbuf)
-		hvc_kick();
-
-	return written;
-}
-
-/**
- * hvc_set_winsz() - Resize the hvc tty terminal window.
- * @work:	work structure.
- *
- * The routine shall not be called within an atomic context because it
- * might sleep.
- *
- * Locking:	hp->lock
- */
-static void hvc_set_winsz(struct work_struct *work)
-{
-	struct hvc_struct *hp;
-	unsigned long hvc_flags;
-	struct tty_struct *tty;
-	struct winsize ws;
-
-	hp = container_of(work, struct hvc_struct, tty_resize);
-
-	spin_lock_irqsave(&hp->lock, hvc_flags);
-	if (!hp->tty) {
-		spin_unlock_irqrestore(&hp->lock, hvc_flags);
-		return;
-	}
-	ws  = hp->ws;
-	tty = tty_kref_get(hp->tty);
-	spin_unlock_irqrestore(&hp->lock, hvc_flags);
-
-	tty_do_resize(tty, &ws);
-	tty_kref_put(tty);
-}
-
-/*
- * This is actually a contract between the driver and the tty layer outlining
- * how much write room the driver can guarantee will be sent OR BUFFERED.  This
- * driver MUST honor the return value.
- */
-static int hvc_write_room(struct tty_struct *tty)
-{
-	struct hvc_struct *hp = tty->driver_data;
-
-	if (!hp)
-		return -1;
-
-	return hp->outbuf_size - hp->n_outbuf;
-}
-
-static int hvc_chars_in_buffer(struct tty_struct *tty)
-{
-	struct hvc_struct *hp = tty->driver_data;
-
-	if (!hp)
-		return 0;
-	return hp->n_outbuf;
-}
-
-/*
- * timeout will vary between the MIN and MAX values defined here.  By default
- * and during console activity we will use a default MIN_TIMEOUT of 10.  When
- * the console is idle, we increase the timeout value on each pass through
- * msleep until we reach the max.  This may be noticeable as a brief (average
- * one second) delay on the console before the console responds to input when
- * there has been no input for some time.
- */
-#define MIN_TIMEOUT		(10)
-#define MAX_TIMEOUT		(2000)
-static u32 timeout = MIN_TIMEOUT;
-
-#define HVC_POLL_READ	0x00000001
-#define HVC_POLL_WRITE	0x00000002
-
-int hvc_poll(struct hvc_struct *hp)
-{
-	struct tty_struct *tty;
-	int i, n, poll_mask = 0;
-	char buf[N_INBUF] __ALIGNED__;
-	unsigned long flags;
-	int read_total = 0;
-	int written_total = 0;
-
-	spin_lock_irqsave(&hp->lock, flags);
-
-	/* Push pending writes */
-	if (hp->n_outbuf > 0)
-		written_total = hvc_push(hp);
-
-	/* Reschedule us if still some write pending */
-	if (hp->n_outbuf > 0) {
-		poll_mask |= HVC_POLL_WRITE;
-		/* If hvc_push() was not able to write, sleep a few msecs */
-		timeout = (written_total) ? 0 : MIN_TIMEOUT;
-	}
-
-	/* No tty attached, just skip */
-	tty = tty_kref_get(hp->tty);
-	if (tty == NULL)
-		goto bail;
-
-	/* Now check if we can get data (are we throttled ?) */
-	if (test_bit(TTY_THROTTLED, &tty->flags))
-		goto throttled;
-
-	/* If we aren't notifier driven and aren't throttled, we always
-	 * request a reschedule
-	 */
-	if (!hp->irq_requested)
-		poll_mask |= HVC_POLL_READ;
-
-	/* Read data if any */
-	for (;;) {
-		int count = tty_buffer_request_room(tty, N_INBUF);
-
-		/* If flip is full, just reschedule a later read */
-		if (count == 0) {
-			poll_mask |= HVC_POLL_READ;
-			break;
-		}
-
-		n = hp->ops->get_chars(hp->vtermno, buf, count);
-		if (n <= 0) {
-			/* Hangup the tty when disconnected from host */
-			if (n == -EPIPE) {
-				spin_unlock_irqrestore(&hp->lock, flags);
-				tty_hangup(tty);
-				spin_lock_irqsave(&hp->lock, flags);
-			} else if ( n == -EAGAIN ) {
-				/*
-				 * Some back-ends can only ensure a certain min
-				 * num of bytes read, which may be > 'count'.
-				 * Let the tty clear the flip buff to make room.
-				 */
-				poll_mask |= HVC_POLL_READ;
-			}
-			break;
-		}
-		for (i = 0; i < n; ++i) {
-#ifdef CONFIG_MAGIC_SYSRQ
-			if (hp->index == hvc_console.index) {
-				/* Handle the SysRq Hack */
-				/* XXX should support a sequence */
-				if (buf[i] == '\x0f') {	/* ^O */
-					/* if ^O is pressed again, reset
-					 * sysrq_pressed and flip ^O char */
-					sysrq_pressed = !sysrq_pressed;
-					if (sysrq_pressed)
-						continue;
-				} else if (sysrq_pressed) {
-					handle_sysrq(buf[i]);
-					sysrq_pressed = 0;
-					continue;
-				}
-			}
-#endif /* CONFIG_MAGIC_SYSRQ */
-			tty_insert_flip_char(tty, buf[i], 0);
-		}
-
-		read_total += n;
-	}
- throttled:
-	/* Wakeup write queue if necessary */
-	if (hp->do_wakeup) {
-		hp->do_wakeup = 0;
-		tty_wakeup(tty);
-	}
- bail:
-	spin_unlock_irqrestore(&hp->lock, flags);
-
-	if (read_total) {
-		/* Activity is occurring, so reset the polling backoff value to
-		   a minimum for performance. */
-		timeout = MIN_TIMEOUT;
-
-		tty_flip_buffer_push(tty);
-	}
-	if (tty)
-		tty_kref_put(tty);
-
-	return poll_mask;
-}
-EXPORT_SYMBOL_GPL(hvc_poll);
-
-/**
- * __hvc_resize() - Update terminal window size information.
- * @hp:		HVC console pointer
- * @ws:		Terminal window size structure
- *
- * Stores the specified window size information in the hvc structure of @hp.
- * The function schedule the tty resize update.
- *
- * Locking:	Locking free; the function MUST be called holding hp->lock
- */
-void __hvc_resize(struct hvc_struct *hp, struct winsize ws)
-{
-	hp->ws = ws;
-	schedule_work(&hp->tty_resize);
-}
-EXPORT_SYMBOL_GPL(__hvc_resize);
-
-/*
- * This kthread is either polling or interrupt driven.  This is determined by
- * calling hvc_poll() who determines whether a console adapter support
- * interrupts.
- */
-static int khvcd(void *unused)
-{
-	int poll_mask;
-	struct hvc_struct *hp;
-
-	set_freezable();
-	do {
-		poll_mask = 0;
-		hvc_kicked = 0;
-		try_to_freeze();
-		wmb();
-		if (!cpus_are_in_xmon()) {
-			spin_lock(&hvc_structs_lock);
-			list_for_each_entry(hp, &hvc_structs, next) {
-				poll_mask |= hvc_poll(hp);
-			}
-			spin_unlock(&hvc_structs_lock);
-		} else
-			poll_mask |= HVC_POLL_READ;
-		if (hvc_kicked)
-			continue;
-		set_current_state(TASK_INTERRUPTIBLE);
-		if (!hvc_kicked) {
-			if (poll_mask == 0)
-				schedule();
-			else {
-				if (timeout < MAX_TIMEOUT)
-					timeout += (timeout >> 6) + 1;
-
-				msleep_interruptible(timeout);
-			}
-		}
-		__set_current_state(TASK_RUNNING);
-	} while (!kthread_should_stop());
-
-	return 0;
-}
-
-static const struct tty_operations hvc_ops = {
-	.open = hvc_open,
-	.close = hvc_close,
-	.write = hvc_write,
-	.hangup = hvc_hangup,
-	.unthrottle = hvc_unthrottle,
-	.write_room = hvc_write_room,
-	.chars_in_buffer = hvc_chars_in_buffer,
-};
-
-struct hvc_struct *hvc_alloc(uint32_t vtermno, int data,
-			     const struct hv_ops *ops,
-			     int outbuf_size)
-{
-	struct hvc_struct *hp;
-	int i;
-
-	/* We wait until a driver actually comes along */
-	if (!hvc_driver) {
-		int err = hvc_init();
-		if (err)
-			return ERR_PTR(err);
-	}
-
-	hp = kzalloc(ALIGN(sizeof(*hp), sizeof(long)) + outbuf_size,
-			GFP_KERNEL);
-	if (!hp)
-		return ERR_PTR(-ENOMEM);
-
-	hp->vtermno = vtermno;
-	hp->data = data;
-	hp->ops = ops;
-	hp->outbuf_size = outbuf_size;
-	hp->outbuf = &((char *)hp)[ALIGN(sizeof(*hp), sizeof(long))];
-
-	kref_init(&hp->kref);
-
-	INIT_WORK(&hp->tty_resize, hvc_set_winsz);
-	spin_lock_init(&hp->lock);
-	spin_lock(&hvc_structs_lock);
-
-	/*
-	 * find index to use:
-	 * see if this vterm id matches one registered for console.
-	 */
-	for (i=0; i < MAX_NR_HVC_CONSOLES; i++)
-		if (vtermnos[i] == hp->vtermno &&
-		    cons_ops[i] == hp->ops)
-			break;
-
-	/* no matching slot, just use a counter */
-	if (i >= MAX_NR_HVC_CONSOLES)
-		i = ++last_hvc;
-
-	hp->index = i;
-
-	list_add_tail(&(hp->next), &hvc_structs);
-	spin_unlock(&hvc_structs_lock);
-
-	return hp;
-}
-EXPORT_SYMBOL_GPL(hvc_alloc);
-
-int hvc_remove(struct hvc_struct *hp)
-{
-	unsigned long flags;
-	struct tty_struct *tty;
-
-	spin_lock_irqsave(&hp->lock, flags);
-	tty = tty_kref_get(hp->tty);
-
-	if (hp->index < MAX_NR_HVC_CONSOLES)
-		vtermnos[hp->index] = -1;
-
-	/* Don't whack hp->irq because tty_hangup() will need to free the irq. */
-
-	spin_unlock_irqrestore(&hp->lock, flags);
-
-	/*
-	 * We 'put' the instance that was grabbed when the kref instance
-	 * was initialized using kref_init().  Let the last holder of this
-	 * kref cause it to be removed, which will probably be the tty_vhangup
-	 * below.
-	 */
-	kref_put(&hp->kref, destroy_hvc_struct);
-
-	/*
-	 * This function call will auto chain call hvc_hangup.
-	 */
-	if (tty) {
-		tty_vhangup(tty);
-		tty_kref_put(tty);
-	}
-	return 0;
-}
-EXPORT_SYMBOL_GPL(hvc_remove);
-
-/* Driver initialization: called as soon as someone uses hvc_alloc(). */
-static int hvc_init(void)
-{
-	struct tty_driver *drv;
-	int err;
-
-	/* We need more than hvc_count adapters due to hotplug additions. */
-	drv = alloc_tty_driver(HVC_ALLOC_TTY_ADAPTERS);
-	if (!drv) {
-		err = -ENOMEM;
-		goto out;
-	}
-
-	drv->owner = THIS_MODULE;
-	drv->driver_name = "hvc";
-	drv->name = "hvc";
-	drv->major = HVC_MAJOR;
-	drv->minor_start = HVC_MINOR;
-	drv->type = TTY_DRIVER_TYPE_SYSTEM;
-	drv->init_termios = tty_std_termios;
-	drv->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_RESET_TERMIOS;
-	tty_set_operations(drv, &hvc_ops);
-
-	/* Always start the kthread because there can be hotplug vty adapters
-	 * added later. */
-	hvc_task = kthread_run(khvcd, NULL, "khvcd");
-	if (IS_ERR(hvc_task)) {
-		printk(KERN_ERR "Couldn't create kthread for console.\n");
-		err = PTR_ERR(hvc_task);
-		goto put_tty;
-	}
-
-	err = tty_register_driver(drv);
-	if (err) {
-		printk(KERN_ERR "Couldn't register hvc console driver\n");
-		goto stop_thread;
-	}
-
-	/*
-	 * Make sure tty is fully registered before allowing it to be
-	 * found by hvc_console_device.
-	 */
-	smp_mb();
-	hvc_driver = drv;
-	return 0;
-
-stop_thread:
-	kthread_stop(hvc_task);
-	hvc_task = NULL;
-put_tty:
-	put_tty_driver(drv);
-out:
-	return err;
-}
-
-/* This isn't particularly necessary due to this being a console driver
- * but it is nice to be thorough.
- */
-static void __exit hvc_exit(void)
-{
-	if (hvc_driver) {
-		kthread_stop(hvc_task);
-
-		tty_unregister_driver(hvc_driver);
-		/* return tty_struct instances allocated in hvc_init(). */
-		put_tty_driver(hvc_driver);
-		unregister_console(&hvc_console);
-	}
-}
-module_exit(hvc_exit);
diff -druNp linux-libre-2.6.37-gnu1/drivers/char/hvc_console.h linux-libre-2.6.38-gnu1/drivers/char/hvc_console.h
--- linux-libre-2.6.37-gnu1/drivers/char/hvc_console.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/char/hvc_console.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,119 +0,0 @@
-/*
- * hvc_console.h
- * Copyright (C) 2005 IBM Corporation
- *
- * Author(s):
- * 	Ryan S. Arnold <rsa@us.ibm.com>
- *
- * hvc_console header information:
- *      moved here from arch/powerpc/include/asm/hvconsole.h
- *      and drivers/char/hvc_console.c
- *
- * 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 HVC_CONSOLE_H
-#define HVC_CONSOLE_H
-#include <linux/kref.h>
-#include <linux/tty.h>
-#include <linux/spinlock.h>
-
-/*
- * This is the max number of console adapters that can/will be found as
- * console devices on first stage console init.  Any number beyond this range
- * can't be used as a console device but is still a valid tty device.
- */
-#define MAX_NR_HVC_CONSOLES	16
-
-/*
- * The Linux TTY code does not support dynamic addition of tty derived devices
- * so we need to know how many tty devices we might need when space is allocated
- * for the tty device.  Since this driver supports hotplug of vty adapters we
- * need to make sure we have enough allocated.
- */
-#define HVC_ALLOC_TTY_ADAPTERS	8
-
-struct hvc_struct {
-	spinlock_t lock;
-	int index;
-	struct tty_struct *tty;
-	int count;
-	int do_wakeup;
-	char *outbuf;
-	int outbuf_size;
-	int n_outbuf;
-	uint32_t vtermno;
-	const struct hv_ops *ops;
-	int irq_requested;
-	int data;
-	struct winsize ws;
-	struct work_struct tty_resize;
-	struct list_head next;
-	struct kref kref; /* ref count & hvc_struct lifetime */
-};
-
-/* implemented by a low level driver */
-struct hv_ops {
-	int (*get_chars)(uint32_t vtermno, char *buf, int count);
-	int (*put_chars)(uint32_t vtermno, const char *buf, int count);
-
-	/* Callbacks for notification. Called in open, close and hangup */
-	int (*notifier_add)(struct hvc_struct *hp, int irq);
-	void (*notifier_del)(struct hvc_struct *hp, int irq);
-	void (*notifier_hangup)(struct hvc_struct *hp, int irq);
-};
-
-/* Register a vterm and a slot index for use as a console (console_init) */
-extern int hvc_instantiate(uint32_t vtermno, int index,
-			   const struct hv_ops *ops);
-
-/* register a vterm for hvc tty operation (module_init or hotplug add) */
-extern struct hvc_struct * hvc_alloc(uint32_t vtermno, int data,
-				     const struct hv_ops *ops, int outbuf_size);
-/* remove a vterm from hvc tty operation (module_exit or hotplug remove) */
-extern int hvc_remove(struct hvc_struct *hp);
-
-/* data available */
-int hvc_poll(struct hvc_struct *hp);
-void hvc_kick(void);
-
-/* Resize hvc tty terminal window */
-extern void __hvc_resize(struct hvc_struct *hp, struct winsize ws);
-
-static inline void hvc_resize(struct hvc_struct *hp, struct winsize ws)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&hp->lock, flags);
-	__hvc_resize(hp, ws);
-	spin_unlock_irqrestore(&hp->lock, flags);
-}
-
-/* default notifier for irq based notification */
-extern int notifier_add_irq(struct hvc_struct *hp, int data);
-extern void notifier_del_irq(struct hvc_struct *hp, int data);
-extern void notifier_hangup_irq(struct hvc_struct *hp, int data);
-
-
-#if defined(CONFIG_XMON) && defined(CONFIG_SMP)
-#include <asm/xmon.h>
-#else
-static inline int cpus_are_in_xmon(void)
-{
-	return 0;
-}
-#endif
-
-#endif // HVC_CONSOLE_H
diff -druNp linux-libre-2.6.37-gnu1/drivers/char/hvc_irq.c linux-libre-2.6.38-gnu1/drivers/char/hvc_irq.c
--- linux-libre-2.6.37-gnu1/drivers/char/hvc_irq.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/char/hvc_irq.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,49 +0,0 @@
-/*
- * Copyright IBM Corp. 2001,2008
- *
- * This file contains the IRQ specific code for hvc_console
- *
- */
-
-#include <linux/interrupt.h>
-
-#include "hvc_console.h"
-
-static irqreturn_t hvc_handle_interrupt(int irq, void *dev_instance)
-{
-	/* if hvc_poll request a repoll, then kick the hvcd thread */
-	if (hvc_poll(dev_instance))
-		hvc_kick();
-	return IRQ_HANDLED;
-}
-
-/*
- * For IRQ based systems these callbacks can be used
- */
-int notifier_add_irq(struct hvc_struct *hp, int irq)
-{
-	int rc;
-
-	if (!irq) {
-		hp->irq_requested = 0;
-		return 0;
-	}
-	rc = request_irq(irq, hvc_handle_interrupt, IRQF_DISABLED,
-			   "hvc_console", hp);
-	if (!rc)
-		hp->irq_requested = 1;
-	return rc;
-}
-
-void notifier_del_irq(struct hvc_struct *hp, int irq)
-{
-	if (!hp->irq_requested)
-		return;
-	free_irq(irq, hp);
-	hp->irq_requested = 0;
-}
-
-void notifier_hangup_irq(struct hvc_struct *hp, int irq)
-{
-	notifier_del_irq(hp, irq);
-}
diff -druNp linux-libre-2.6.37-gnu1/drivers/char/hvc_iseries.c linux-libre-2.6.38-gnu1/drivers/char/hvc_iseries.c
--- linux-libre-2.6.37-gnu1/drivers/char/hvc_iseries.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/char/hvc_iseries.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,598 +0,0 @@
-/*
- * iSeries vio driver interface to hvc_console.c
- *
- * This code is based heavily on hvc_vio.c and viocons.c
- *
- * Copyright (C) 2006 Stephen Rothwell, 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.
- *
- * 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 <stdarg.h>
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/spinlock.h>
-#include <linux/console.h>
-
-#include <asm/hvconsole.h>
-#include <asm/vio.h>
-#include <asm/prom.h>
-#include <asm/firmware.h>
-#include <asm/iseries/vio.h>
-#include <asm/iseries/hv_call.h>
-#include <asm/iseries/hv_lp_config.h>
-#include <asm/iseries/hv_lp_event.h>
-
-#include "hvc_console.h"
-
-#define VTTY_PORTS 10
-
-static DEFINE_SPINLOCK(consolelock);
-static DEFINE_SPINLOCK(consoleloglock);
-
-static const char hvc_driver_name[] = "hvc_console";
-
-#define IN_BUF_SIZE	200
-
-/*
- * Our port information.
- */
-static struct port_info {
-	HvLpIndex lp;
-	u64 seq;	/* sequence number of last HV send */
-	u64 ack;	/* last ack from HV */
-	struct hvc_struct *hp;
-	int in_start;
-	int in_end;
-	unsigned char in_buf[IN_BUF_SIZE];
-} port_info[VTTY_PORTS] = {
-	[ 0 ... VTTY_PORTS - 1 ] = {
-		.lp = HvLpIndexInvalid
-	}
-};
-
-#define viochar_is_console(pi)	((pi) == &port_info[0])
-
-static struct vio_device_id hvc_driver_table[] __devinitdata = {
-	{"serial", "IBM,iSeries-vty"},
-	{ "", "" }
-};
-MODULE_DEVICE_TABLE(vio, hvc_driver_table);
-
-static void hvlog(char *fmt, ...)
-{
-	int i;
-	unsigned long flags;
-	va_list args;
-	static char buf[256];
-
-	spin_lock_irqsave(&consoleloglock, flags);
-	va_start(args, fmt);
-	i = vscnprintf(buf, sizeof(buf) - 1, fmt, args);
-	va_end(args);
-	buf[i++] = '\r';
-	HvCall_writeLogBuffer(buf, i);
-	spin_unlock_irqrestore(&consoleloglock, flags);
-}
-
-/*
- * Initialize the common fields in a charLpEvent
- */
-static void init_data_event(struct viocharlpevent *viochar, HvLpIndex lp)
-{
-	struct HvLpEvent *hev = &viochar->event;
-
-	memset(viochar, 0, sizeof(struct viocharlpevent));
-
-	hev->flags = HV_LP_EVENT_VALID | HV_LP_EVENT_DEFERRED_ACK |
-		HV_LP_EVENT_INT;
-	hev->xType = HvLpEvent_Type_VirtualIo;
-	hev->xSubtype = viomajorsubtype_chario | viochardata;
-	hev->xSourceLp = HvLpConfig_getLpIndex();
-	hev->xTargetLp = lp;
-	hev->xSizeMinus1 = sizeof(struct viocharlpevent);
-	hev->xSourceInstanceId = viopath_sourceinst(lp);
-	hev->xTargetInstanceId = viopath_targetinst(lp);
-}
-
-static int get_chars(uint32_t vtermno, char *buf, int count)
-{
-	struct port_info *pi;
-	int n = 0;
-	unsigned long flags;
-
-	if (vtermno >= VTTY_PORTS)
-		return -EINVAL;
-	if (count == 0)
-		return 0;
-
-	pi = &port_info[vtermno];
-	spin_lock_irqsave(&consolelock, flags);
-
-	if (pi->in_end == 0)
-		goto done;
-
-	n = pi->in_end - pi->in_start;
-	if (n > count)
-		n = count;
-	memcpy(buf, &pi->in_buf[pi->in_start], n);
-	pi->in_start += n;
-	if (pi->in_start == pi->in_end) {
-		pi->in_start = 0;
-		pi->in_end = 0;
-	}
-done:
-	spin_unlock_irqrestore(&consolelock, flags);
-	return n;
-}
-
-static int put_chars(uint32_t vtermno, const char *buf, int count)
-{
-	struct viocharlpevent *viochar;
-	struct port_info *pi;
-	HvLpEvent_Rc hvrc;
-	unsigned long flags;
-	int sent = 0;
-
-	if (vtermno >= VTTY_PORTS)
-		return -EINVAL;
-
-	pi = &port_info[vtermno];
-
-	spin_lock_irqsave(&consolelock, flags);
-
-	if (viochar_is_console(pi) && !viopath_isactive(pi->lp)) {
-		HvCall_writeLogBuffer(buf, count);
-		sent = count;
-		goto done;
-	}
-
-	viochar = vio_get_event_buffer(viomajorsubtype_chario);
-	if (viochar == NULL) {
-		hvlog("\n\rviocons: Can't get viochar buffer.");
-		goto done;
-	}
-
-	while ((count > 0) && ((pi->seq - pi->ack) < VIOCHAR_WINDOW)) {
-		int len;
-
-		len = (count > VIOCHAR_MAX_DATA) ? VIOCHAR_MAX_DATA : count;
-
-		if (viochar_is_console(pi))
-			HvCall_writeLogBuffer(buf, len);
-
-		init_data_event(viochar, pi->lp);
-
-		viochar->len = len;
-		viochar->event.xCorrelationToken = pi->seq++;
-		viochar->event.xSizeMinus1 =
-			offsetof(struct viocharlpevent, data) + len;
-
-		memcpy(viochar->data, buf, len);
-
-		hvrc = HvCallEvent_signalLpEvent(&viochar->event);
-		if (hvrc)
-			hvlog("\n\rerror sending event! return code %d\n\r",
-				(int)hvrc);
-		sent += len;
-		count -= len;
-		buf += len;
-	}
-
-	vio_free_event_buffer(viomajorsubtype_chario, viochar);
-done:
-	spin_unlock_irqrestore(&consolelock, flags);
-	return sent;
-}
-
-static const struct hv_ops hvc_get_put_ops = {
-	.get_chars = get_chars,
-	.put_chars = put_chars,
-	.notifier_add = notifier_add_irq,
-	.notifier_del = notifier_del_irq,
-	.notifier_hangup = notifier_hangup_irq,
-};
-
-static int __devinit hvc_vio_probe(struct vio_dev *vdev,
-			const struct vio_device_id *id)
-{
-	struct hvc_struct *hp;
-	struct port_info *pi;
-
-	/* probed with invalid parameters. */
-	if (!vdev || !id)
-		return -EPERM;
-
-	if (vdev->unit_address >= VTTY_PORTS)
-		return -ENODEV;
-
-	pi = &port_info[vdev->unit_address];
-
-	hp = hvc_alloc(vdev->unit_address, vdev->irq, &hvc_get_put_ops,
-			VIOCHAR_MAX_DATA);
-	if (IS_ERR(hp))
-		return PTR_ERR(hp);
-	pi->hp = hp;
-	dev_set_drvdata(&vdev->dev, pi);
-
-	return 0;
-}
-
-static int __devexit hvc_vio_remove(struct vio_dev *vdev)
-{
-	struct port_info *pi = dev_get_drvdata(&vdev->dev);
-	struct hvc_struct *hp = pi->hp;
-
-	return hvc_remove(hp);
-}
-
-static struct vio_driver hvc_vio_driver = {
-	.id_table	= hvc_driver_table,
-	.probe		= hvc_vio_probe,
-	.remove		= __devexit_p(hvc_vio_remove),
-	.driver		= {
-		.name	= hvc_driver_name,
-		.owner	= THIS_MODULE,
-	}
-};
-
-static void hvc_open_event(struct HvLpEvent *event)
-{
-	unsigned long flags;
-	struct viocharlpevent *cevent = (struct viocharlpevent *)event;
-	u8 port = cevent->virtual_device;
-	struct port_info *pi;
-	int reject = 0;
-
-	if (hvlpevent_is_ack(event)) {
-		if (port >= VTTY_PORTS)
-			return;
-
-		spin_lock_irqsave(&consolelock, flags);
-
-		pi = &port_info[port];
-		if (event->xRc == HvLpEvent_Rc_Good) {
-			pi->seq = pi->ack = 0;
-			/*
-			 * This line allows connections from the primary
-			 * partition but once one is connected from the
-			 * primary partition nothing short of a reboot
-			 * of linux will allow access from the hosting
-			 * partition again without a required iSeries fix.
-			 */
-			pi->lp = event->xTargetLp;
-		}
-
-		spin_unlock_irqrestore(&consolelock, flags);
-		if (event->xRc != HvLpEvent_Rc_Good)
-			printk(KERN_WARNING
-			       "hvc: handle_open_event: event->xRc == (%d).\n",
-			       event->xRc);
-
-		if (event->xCorrelationToken != 0) {
-			atomic_t *aptr= (atomic_t *)event->xCorrelationToken;
-			atomic_set(aptr, 1);
-		} else
-			printk(KERN_WARNING
-			       "hvc: weird...got open ack without atomic\n");
-		return;
-	}
-
-	/* This had better require an ack, otherwise complain */
-	if (!hvlpevent_need_ack(event)) {
-		printk(KERN_WARNING "hvc: viocharopen without ack bit!\n");
-		return;
-	}
-
-	spin_lock_irqsave(&consolelock, flags);
-
-	/* Make sure this is a good virtual tty */
-	if (port >= VTTY_PORTS) {
-		event->xRc = HvLpEvent_Rc_SubtypeError;
-		cevent->subtype_result_code = viorc_openRejected;
-		/*
-		 * Flag state here since we can't printk while holding
-		 * the consolelock spinlock.
-		 */
-		reject = 1;
-	} else {
-		pi = &port_info[port];
-		if ((pi->lp != HvLpIndexInvalid) &&
-				(pi->lp != event->xSourceLp)) {
-			/*
-			 * If this is tty is already connected to a different
-			 * partition, fail.
-			 */
-			event->xRc = HvLpEvent_Rc_SubtypeError;
-			cevent->subtype_result_code = viorc_openRejected;
-			reject = 2;
-		} else {
-			pi->lp = event->xSourceLp;
-			event->xRc = HvLpEvent_Rc_Good;
-			cevent->subtype_result_code = viorc_good;
-			pi->seq = pi->ack = 0;
-		}
-	}
-
-	spin_unlock_irqrestore(&consolelock, flags);
-
-	if (reject == 1)
-		printk(KERN_WARNING "hvc: open rejected: bad virtual tty.\n");
-	else if (reject == 2)
-		printk(KERN_WARNING "hvc: open rejected: console in exclusive "
-				"use by another partition.\n");
-
-	/* Return the acknowledgement */
-	HvCallEvent_ackLpEvent(event);
-}
-
-/*
- * Handle a close charLpEvent.  This should ONLY be an Interrupt because the
- * virtual console should never actually issue a close event to the hypervisor
- * because the virtual console never goes away.  A close event coming from the
- * hypervisor simply means that there are no client consoles connected to the
- * virtual console.
- */
-static void hvc_close_event(struct HvLpEvent *event)
-{
-	unsigned long flags;
-	struct viocharlpevent *cevent = (struct viocharlpevent *)event;
-	u8 port = cevent->virtual_device;
-
-	if (!hvlpevent_is_int(event)) {
-		printk(KERN_WARNING
-			"hvc: got unexpected close acknowledgement\n");
-		return;
-	}
-
-	if (port >= VTTY_PORTS) {
-		printk(KERN_WARNING
-			"hvc: close message from invalid virtual device.\n");
-		return;
-	}
-
-	/* For closes, just mark the console partition invalid */
-	spin_lock_irqsave(&consolelock, flags);
-
-	if (port_info[port].lp == event->xSourceLp)
-		port_info[port].lp = HvLpIndexInvalid;
-
-	spin_unlock_irqrestore(&consolelock, flags);
-}
-
-static void hvc_data_event(struct HvLpEvent *event)
-{
-	unsigned long flags;
-	struct viocharlpevent *cevent = (struct viocharlpevent *)event;
-	struct port_info *pi;
-	int n;
-	u8 port = cevent->virtual_device;
-
-	if (port >= VTTY_PORTS) {
-		printk(KERN_WARNING "hvc: data on invalid virtual device %d\n",
-				port);
-		return;
-	}
-	if (cevent->len == 0)
-		return;
-
-	/*
-	 * Change 05/01/2003 - Ryan Arnold: If a partition other than
-	 * the current exclusive partition tries to send us data
-	 * events then just drop them on the floor because we don't
-	 * want his stinking data.  He isn't authorized to receive
-	 * data because he wasn't the first one to get the console,
-	 * therefore he shouldn't be allowed to send data either.
-	 * This will work without an iSeries fix.
-	 */
-	pi = &port_info[port];
-	if (pi->lp != event->xSourceLp)
-		return;
-
-	spin_lock_irqsave(&consolelock, flags);
-
-	n = IN_BUF_SIZE - pi->in_end;
-	if (n > cevent->len)
-		n = cevent->len;
-	if (n > 0) {
-		memcpy(&pi->in_buf[pi->in_end], cevent->data, n);
-		pi->in_end += n;
-	}
-	spin_unlock_irqrestore(&consolelock, flags);
-	if (n == 0)
-		printk(KERN_WARNING "hvc: input buffer overflow\n");
-}
-
-static void hvc_ack_event(struct HvLpEvent *event)
-{
-	struct viocharlpevent *cevent = (struct viocharlpevent *)event;
-	unsigned long flags;
-	u8 port = cevent->virtual_device;
-
-	if (port >= VTTY_PORTS) {
-		printk(KERN_WARNING "hvc: data on invalid virtual device\n");
-		return;
-	}
-
-	spin_lock_irqsave(&consolelock, flags);
-	port_info[port].ack = event->xCorrelationToken;
-	spin_unlock_irqrestore(&consolelock, flags);
-}
-
-static void hvc_config_event(struct HvLpEvent *event)
-{
-	struct viocharlpevent *cevent = (struct viocharlpevent *)event;
-
-	if (cevent->data[0] == 0x01)
-		printk(KERN_INFO "hvc: window resized to %d: %d: %d: %d\n",
-		       cevent->data[1], cevent->data[2],
-		       cevent->data[3], cevent->data[4]);
-	else
-		printk(KERN_WARNING "hvc: unknown config event\n");
-}
-
-static void hvc_handle_event(struct HvLpEvent *event)
-{
-	int charminor;
-
-	if (event == NULL)
-		return;
-
-	charminor = event->xSubtype & VIOMINOR_SUBTYPE_MASK;
-	switch (charminor) {
-	case viocharopen:
-		hvc_open_event(event);
-		break;
-	case viocharclose:
-		hvc_close_event(event);
-		break;
-	case viochardata:
-		hvc_data_event(event);
-		break;
-	case viocharack:
-		hvc_ack_event(event);
-		break;
-	case viocharconfig:
-		hvc_config_event(event);
-		break;
-	default:
-		if (hvlpevent_is_int(event) && hvlpevent_need_ack(event)) {
-			event->xRc = HvLpEvent_Rc_InvalidSubtype;
-			HvCallEvent_ackLpEvent(event);
-		}
-	}
-}
-
-static int __init send_open(HvLpIndex remoteLp, void *sem)
-{
-	return HvCallEvent_signalLpEventFast(remoteLp,
-			HvLpEvent_Type_VirtualIo,
-			viomajorsubtype_chario | viocharopen,
-			HvLpEvent_AckInd_DoAck, HvLpEvent_AckType_ImmediateAck,
-			viopath_sourceinst(remoteLp),
-			viopath_targetinst(remoteLp),
-			(u64)(unsigned long)sem, VIOVERSION << 16,
-			0, 0, 0, 0);
-}
-
-static int __init hvc_vio_init(void)
-{
-	atomic_t wait_flag;
-	int rc;
-
-	if (!firmware_has_feature(FW_FEATURE_ISERIES))
-		return -EIO;
-
-	/* +2 for fudge */
-	rc = viopath_open(HvLpConfig_getPrimaryLpIndex(),
-			viomajorsubtype_chario, VIOCHAR_WINDOW + 2);
-	if (rc)
-		printk(KERN_WARNING "hvc: error opening to primary %d\n", rc);
-
-	if (viopath_hostLp == HvLpIndexInvalid)
-		vio_set_hostlp();
-
-	/*
-	 * And if the primary is not the same as the hosting LP, open to the
-	 * hosting lp
-	 */
-	if ((viopath_hostLp != HvLpIndexInvalid) &&
-	    (viopath_hostLp != HvLpConfig_getPrimaryLpIndex())) {
-		printk(KERN_INFO "hvc: open path to hosting (%d)\n",
-				viopath_hostLp);
-		rc = viopath_open(viopath_hostLp, viomajorsubtype_chario,
-				VIOCHAR_WINDOW + 2);	/* +2 for fudge */
-		if (rc)
-			printk(KERN_WARNING
-				"error opening to partition %d: %d\n",
-				viopath_hostLp, rc);
-	}
-
-	if (vio_setHandler(viomajorsubtype_chario, hvc_handle_event) < 0)
-		printk(KERN_WARNING
-			"hvc: error seting handler for console events!\n");
-
-	/*
-	 * First, try to open the console to the hosting lp.
-	 * Wait on a semaphore for the response.
-	 */
-	atomic_set(&wait_flag, 0);
-	if ((viopath_isactive(viopath_hostLp)) &&
-	    (send_open(viopath_hostLp, &wait_flag) == 0)) {
-		printk(KERN_INFO "hvc: hosting partition %d\n", viopath_hostLp);
-		while (atomic_read(&wait_flag) == 0)
-			mb();
-		atomic_set(&wait_flag, 0);
-	}
-
-	/*
-	 * If we don't have an active console, try the primary
-	 */
-	if ((!viopath_isactive(port_info[0].lp)) &&
-	    (viopath_isactive(HvLpConfig_getPrimaryLpIndex())) &&
-	    (send_open(HvLpConfig_getPrimaryLpIndex(), &wait_flag) == 0)) {
-		printk(KERN_INFO "hvc: opening console to primary partition\n");
-		while (atomic_read(&wait_flag) == 0)
-			mb();
-	}
-
-	/* Register as a vio device to receive callbacks */
-	rc = vio_register_driver(&hvc_vio_driver);
-
-	return rc;
-}
-module_init(hvc_vio_init); /* after drivers/char/hvc_console.c */
-
-static void __exit hvc_vio_exit(void)
-{
-	vio_unregister_driver(&hvc_vio_driver);
-}
-module_exit(hvc_vio_exit);
-
-/* the device tree order defines our numbering */
-static int __init hvc_find_vtys(void)
-{
-	struct device_node *vty;
-	int num_found = 0;
-
-	for (vty = of_find_node_by_name(NULL, "vty"); vty != NULL;
-			vty = of_find_node_by_name(vty, "vty")) {
-		const uint32_t *vtermno;
-
-		/* We have statically defined space for only a certain number
-		 * of console adapters.
-		 */
-		if ((num_found >= MAX_NR_HVC_CONSOLES) ||
-				(num_found >= VTTY_PORTS)) {
-			of_node_put(vty);
-			break;
-		}
-
-		vtermno = of_get_property(vty, "reg", NULL);
-		if (!vtermno)
-			continue;
-
-		if (!of_device_is_compatible(vty, "IBM,iSeries-vty"))
-			continue;
-
-		if (num_found == 0)
-			add_preferred_console("hvc", 0, NULL);
-		hvc_instantiate(*vtermno, num_found, &hvc_get_put_ops);
-		++num_found;
-	}
-
-	return num_found;
-}
-console_initcall(hvc_find_vtys);
diff -druNp linux-libre-2.6.37-gnu1/drivers/char/hvc_iucv.c linux-libre-2.6.38-gnu1/drivers/char/hvc_iucv.c
--- linux-libre-2.6.37-gnu1/drivers/char/hvc_iucv.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/char/hvc_iucv.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1337 +0,0 @@
-/*
- * hvc_iucv.c - z/VM IUCV hypervisor console (HVC) device driver
- *
- * This HVC device driver provides terminal access using
- * z/VM IUCV communication paths.
- *
- * Copyright IBM Corp. 2008, 2009
- *
- * Author(s):	Hendrik Brueckner <brueckner@linux.vnet.ibm.com>
- */
-#define KMSG_COMPONENT		"hvc_iucv"
-#define pr_fmt(fmt)		KMSG_COMPONENT ": " fmt
-
-#include <linux/types.h>
-#include <linux/slab.h>
-#include <asm/ebcdic.h>
-#include <linux/ctype.h>
-#include <linux/delay.h>
-#include <linux/device.h>
-#include <linux/init.h>
-#include <linux/mempool.h>
-#include <linux/moduleparam.h>
-#include <linux/tty.h>
-#include <linux/wait.h>
-#include <net/iucv/iucv.h>
-
-#include "hvc_console.h"
-
-
-/* General device driver settings */
-#define HVC_IUCV_MAGIC		0xc9e4c3e5
-#define MAX_HVC_IUCV_LINES	HVC_ALLOC_TTY_ADAPTERS
-#define MEMPOOL_MIN_NR		(PAGE_SIZE / sizeof(struct iucv_tty_buffer)/4)
-
-/* IUCV TTY message  */
-#define MSG_VERSION		0x02	/* Message version */
-#define MSG_TYPE_ERROR		0x01	/* Error message */
-#define MSG_TYPE_TERMENV	0x02	/* Terminal environment variable */
-#define MSG_TYPE_TERMIOS	0x04	/* Terminal IO struct update */
-#define MSG_TYPE_WINSIZE	0x08	/* Terminal window size update */
-#define MSG_TYPE_DATA		0x10	/* Terminal data */
-
-struct iucv_tty_msg {
-	u8	version;		/* Message version */
-	u8	type;			/* Message type */
-#define MSG_MAX_DATALEN		((u16)(~0))
-	u16	datalen;		/* Payload length */
-	u8	data[];			/* Payload buffer */
-} __attribute__((packed));
-#define MSG_SIZE(s)		((s) + offsetof(struct iucv_tty_msg, data))
-
-enum iucv_state_t {
-	IUCV_DISCONN	= 0,
-	IUCV_CONNECTED	= 1,
-	IUCV_SEVERED	= 2,
-};
-
-enum tty_state_t {
-	TTY_CLOSED	= 0,
-	TTY_OPENED	= 1,
-};
-
-struct hvc_iucv_private {
-	struct hvc_struct	*hvc;		/* HVC struct reference */
-	u8			srv_name[8];	/* IUCV service name (ebcdic) */
-	unsigned char		is_console;	/* Linux console usage flag */
-	enum iucv_state_t	iucv_state;	/* IUCV connection status */
-	enum tty_state_t	tty_state;	/* TTY status */
-	struct iucv_path	*path;		/* IUCV path pointer */
-	spinlock_t		lock;		/* hvc_iucv_private lock */
-#define SNDBUF_SIZE		(PAGE_SIZE)	/* must be < MSG_MAX_DATALEN */
-	void			*sndbuf;	/* send buffer		  */
-	size_t			sndbuf_len;	/* length of send buffer  */
-#define QUEUE_SNDBUF_DELAY	(HZ / 25)
-	struct delayed_work	sndbuf_work;	/* work: send iucv msg(s) */
-	wait_queue_head_t	sndbuf_waitq;	/* wait for send completion */
-	struct list_head	tty_outqueue;	/* outgoing IUCV messages */
-	struct list_head	tty_inqueue;	/* incoming IUCV messages */
-	struct device		*dev;		/* device structure */
-};
-
-struct iucv_tty_buffer {
-	struct list_head	list;	/* list pointer */
-	struct iucv_message	msg;	/* store an IUCV message */
-	size_t			offset;	/* data buffer offset */
-	struct iucv_tty_msg	*mbuf;	/* buffer to store input/output data */
-};
-
-/* IUCV callback handler */
-static	int hvc_iucv_path_pending(struct iucv_path *, u8[8], u8[16]);
-static void hvc_iucv_path_severed(struct iucv_path *, u8[16]);
-static void hvc_iucv_msg_pending(struct iucv_path *, struct iucv_message *);
-static void hvc_iucv_msg_complete(struct iucv_path *, struct iucv_message *);
-
-
-/* Kernel module parameter: use one terminal device as default */
-static unsigned long hvc_iucv_devices = 1;
-
-/* Array of allocated hvc iucv tty lines... */
-static struct hvc_iucv_private *hvc_iucv_table[MAX_HVC_IUCV_LINES];
-#define IUCV_HVC_CON_IDX	(0)
-/* List of z/VM user ID filter entries (struct iucv_vmid_filter) */
-#define MAX_VMID_FILTER		(500)
-static size_t hvc_iucv_filter_size;
-static void *hvc_iucv_filter;
-static const char *hvc_iucv_filter_string;
-static DEFINE_RWLOCK(hvc_iucv_filter_lock);
-
-/* Kmem cache and mempool for iucv_tty_buffer elements */
-static struct kmem_cache *hvc_iucv_buffer_cache;
-static mempool_t *hvc_iucv_mempool;
-
-/* IUCV handler callback functions */
-static struct iucv_handler hvc_iucv_handler = {
-	.path_pending  = hvc_iucv_path_pending,
-	.path_severed  = hvc_iucv_path_severed,
-	.message_complete = hvc_iucv_msg_complete,
-	.message_pending  = hvc_iucv_msg_pending,
-};
-
-
-/**
- * hvc_iucv_get_private() - Return a struct hvc_iucv_private instance.
- * @num:	The HVC virtual terminal number (vtermno)
- *
- * This function returns the struct hvc_iucv_private instance that corresponds
- * to the HVC virtual terminal number specified as parameter @num.
- */
-struct hvc_iucv_private *hvc_iucv_get_private(uint32_t num)
-{
-	if ((num < HVC_IUCV_MAGIC) || (num - HVC_IUCV_MAGIC > hvc_iucv_devices))
-		return NULL;
-	return hvc_iucv_table[num - HVC_IUCV_MAGIC];
-}
-
-/**
- * alloc_tty_buffer() - Return a new struct iucv_tty_buffer element.
- * @size:	Size of the internal buffer used to store data.
- * @flags:	Memory allocation flags passed to mempool.
- *
- * This function allocates a new struct iucv_tty_buffer element and, optionally,
- * allocates an internal data buffer with the specified size @size.
- * The internal data buffer is always allocated with GFP_DMA which is
- * required for receiving and sending data with IUCV.
- * Note: The total message size arises from the internal buffer size and the
- *	 members of the iucv_tty_msg structure.
- * The function returns NULL if memory allocation has failed.
- */
-static struct iucv_tty_buffer *alloc_tty_buffer(size_t size, gfp_t flags)
-{
-	struct iucv_tty_buffer *bufp;
-
-	bufp = mempool_alloc(hvc_iucv_mempool, flags);
-	if (!bufp)
-		return NULL;
-	memset(bufp, 0, sizeof(*bufp));
-
-	if (size > 0) {
-		bufp->msg.length = MSG_SIZE(size);
-		bufp->mbuf = kmalloc(bufp->msg.length, flags | GFP_DMA);
-		if (!bufp->mbuf) {
-			mempool_free(bufp, hvc_iucv_mempool);
-			return NULL;
-		}
-		bufp->mbuf->version = MSG_VERSION;
-		bufp->mbuf->type    = MSG_TYPE_DATA;
-		bufp->mbuf->datalen = (u16) size;
-	}
-	return bufp;
-}
-
-/**
- * destroy_tty_buffer() - destroy struct iucv_tty_buffer element.
- * @bufp:	Pointer to a struct iucv_tty_buffer element, SHALL NOT be NULL.
- */
-static void destroy_tty_buffer(struct iucv_tty_buffer *bufp)
-{
-	kfree(bufp->mbuf);
-	mempool_free(bufp, hvc_iucv_mempool);
-}
-
-/**
- * destroy_tty_buffer_list() - call destroy_tty_buffer() for each list element.
- * @list:	List containing struct iucv_tty_buffer elements.
- */
-static void destroy_tty_buffer_list(struct list_head *list)
-{
-	struct iucv_tty_buffer *ent, *next;
-
-	list_for_each_entry_safe(ent, next, list, list) {
-		list_del(&ent->list);
-		destroy_tty_buffer(ent);
-	}
-}
-
-/**
- * hvc_iucv_write() - Receive IUCV message & write data to HVC buffer.
- * @priv:		Pointer to struct hvc_iucv_private
- * @buf:		HVC buffer for writing received terminal data.
- * @count:		HVC buffer size.
- * @has_more_data:	Pointer to an int variable.
- *
- * The function picks up pending messages from the input queue and receives
- * the message data that is then written to the specified buffer @buf.
- * If the buffer size @count is less than the data message size, the
- * message is kept on the input queue and @has_more_data is set to 1.
- * If all message data has been written, the message is removed from
- * the input queue.
- *
- * The function returns the number of bytes written to the terminal, zero if
- * there are no pending data messages available or if there is no established
- * IUCV path.
- * If the IUCV path has been severed, then -EPIPE is returned to cause a
- * hang up (that is issued by the HVC layer).
- */
-static int hvc_iucv_write(struct hvc_iucv_private *priv,
-			  char *buf, int count, int *has_more_data)
-{
-	struct iucv_tty_buffer *rb;
-	int written;
-	int rc;
-
-	/* immediately return if there is no IUCV connection */
-	if (priv->iucv_state == IUCV_DISCONN)
-		return 0;
-
-	/* if the IUCV path has been severed, return -EPIPE to inform the
-	 * HVC layer to hang up the tty device. */
-	if (priv->iucv_state == IUCV_SEVERED)
-		return -EPIPE;
-
-	/* check if there are pending messages */
-	if (list_empty(&priv->tty_inqueue))
-		return 0;
-
-	/* receive an iucv message and flip data to the tty (ldisc) */
-	rb = list_first_entry(&priv->tty_inqueue, struct iucv_tty_buffer, list);
-
-	written = 0;
-	if (!rb->mbuf) { /* message not yet received ... */
-		/* allocate mem to store msg data; if no memory is available
-		 * then leave the buffer on the list and re-try later */
-		rb->mbuf = kmalloc(rb->msg.length, GFP_ATOMIC | GFP_DMA);
-		if (!rb->mbuf)
-			return -ENOMEM;
-
-		rc = __iucv_message_receive(priv->path, &rb->msg, 0,
-					    rb->mbuf, rb->msg.length, NULL);
-		switch (rc) {
-		case 0: /* Successful	    */
-			break;
-		case 2:	/* No message found */
-		case 9: /* Message purged   */
-			break;
-		default:
-			written = -EIO;
-		}
-		/* remove buffer if an error has occured or received data
-		 * is not correct */
-		if (rc || (rb->mbuf->version != MSG_VERSION) ||
-			  (rb->msg.length    != MSG_SIZE(rb->mbuf->datalen)))
-			goto out_remove_buffer;
-	}
-
-	switch (rb->mbuf->type) {
-	case MSG_TYPE_DATA:
-		written = min_t(int, rb->mbuf->datalen - rb->offset, count);
-		memcpy(buf, rb->mbuf->data + rb->offset, written);
-		if (written < (rb->mbuf->datalen - rb->offset)) {
-			rb->offset += written;
-			*has_more_data = 1;
-			goto out_written;
-		}
-		break;
-
-	case MSG_TYPE_WINSIZE:
-		if (rb->mbuf->datalen != sizeof(struct winsize))
-			break;
-		/* The caller must ensure that the hvc is locked, which
-		 * is the case when called from hvc_iucv_get_chars() */
-		__hvc_resize(priv->hvc, *((struct winsize *) rb->mbuf->data));
-		break;
-
-	case MSG_TYPE_ERROR:	/* ignored ... */
-	case MSG_TYPE_TERMENV:	/* ignored ... */
-	case MSG_TYPE_TERMIOS:	/* ignored ... */
-		break;
-	}
-
-out_remove_buffer:
-	list_del(&rb->list);
-	destroy_tty_buffer(rb);
-	*has_more_data = !list_empty(&priv->tty_inqueue);
-
-out_written:
-	return written;
-}
-
-/**
- * hvc_iucv_get_chars() - HVC get_chars operation.
- * @vtermno:	HVC virtual terminal number.
- * @buf:	Pointer to a buffer to store data
- * @count:	Size of buffer available for writing
- *
- * The HVC thread calls this method to read characters from the back-end.
- * If an IUCV communication path has been established, pending IUCV messages
- * are received and data is copied into buffer @buf up to @count bytes.
- *
- * Locking:	The routine gets called under an irqsave() spinlock; and
- *		the routine locks the struct hvc_iucv_private->lock to call
- *		helper functions.
- */
-static int hvc_iucv_get_chars(uint32_t vtermno, char *buf, int count)
-{
-	struct hvc_iucv_private *priv = hvc_iucv_get_private(vtermno);
-	int written;
-	int has_more_data;
-
-	if (count <= 0)
-		return 0;
-
-	if (!priv)
-		return -ENODEV;
-
-	spin_lock(&priv->lock);
-	has_more_data = 0;
-	written = hvc_iucv_write(priv, buf, count, &has_more_data);
-	spin_unlock(&priv->lock);
-
-	/* if there are still messages on the queue... schedule another run */
-	if (has_more_data)
-		hvc_kick();
-
-	return written;
-}
-
-/**
- * hvc_iucv_queue() - Buffer terminal data for sending.
- * @priv:	Pointer to struct hvc_iucv_private instance.
- * @buf:	Buffer containing data to send.
- * @count:	Size of buffer and amount of data to send.
- *
- * The function queues data for sending. To actually send the buffered data,
- * a work queue function is scheduled (with QUEUE_SNDBUF_DELAY).
- * The function returns the number of data bytes that has been buffered.
- *
- * If the device is not connected, data is ignored and the function returns
- * @count.
- * If the buffer is full, the function returns 0.
- * If an existing IUCV communicaton path has been severed, -EPIPE is returned
- * (that can be passed to HVC layer to cause a tty hangup).
- */
-static int hvc_iucv_queue(struct hvc_iucv_private *priv, const char *buf,
-			  int count)
-{
-	size_t len;
-
-	if (priv->iucv_state == IUCV_DISCONN)
-		return count;			/* ignore data */
-
-	if (priv->iucv_state == IUCV_SEVERED)
-		return -EPIPE;
-
-	len = min_t(size_t, count, SNDBUF_SIZE - priv->sndbuf_len);
-	if (!len)
-		return 0;
-
-	memcpy(priv->sndbuf + priv->sndbuf_len, buf, len);
-	priv->sndbuf_len += len;
-
-	if (priv->iucv_state == IUCV_CONNECTED)
-		schedule_delayed_work(&priv->sndbuf_work, QUEUE_SNDBUF_DELAY);
-
-	return len;
-}
-
-/**
- * hvc_iucv_send() - Send an IUCV message containing terminal data.
- * @priv:	Pointer to struct hvc_iucv_private instance.
- *
- * If an IUCV communication path has been established, the buffered output data
- * is sent via an IUCV message and the number of bytes sent is returned.
- * Returns 0 if there is no established IUCV communication path or
- * -EPIPE if an existing IUCV communicaton path has been severed.
- */
-static int hvc_iucv_send(struct hvc_iucv_private *priv)
-{
-	struct iucv_tty_buffer *sb;
-	int rc, len;
-
-	if (priv->iucv_state == IUCV_SEVERED)
-		return -EPIPE;
-
-	if (priv->iucv_state == IUCV_DISCONN)
-		return -EIO;
-
-	if (!priv->sndbuf_len)
-		return 0;
-
-	/* allocate internal buffer to store msg data and also compute total
-	 * message length */
-	sb = alloc_tty_buffer(priv->sndbuf_len, GFP_ATOMIC);
-	if (!sb)
-		return -ENOMEM;
-
-	memcpy(sb->mbuf->data, priv->sndbuf, priv->sndbuf_len);
-	sb->mbuf->datalen = (u16) priv->sndbuf_len;
-	sb->msg.length = MSG_SIZE(sb->mbuf->datalen);
-
-	list_add_tail(&sb->list, &priv->tty_outqueue);
-
-	rc = __iucv_message_send(priv->path, &sb->msg, 0, 0,
-				 (void *) sb->mbuf, sb->msg.length);
-	if (rc) {
-		/* drop the message here; however we might want to handle
-		 * 0x03 (msg limit reached) by trying again... */
-		list_del(&sb->list);
-		destroy_tty_buffer(sb);
-	}
-	len = priv->sndbuf_len;
-	priv->sndbuf_len = 0;
-
-	return len;
-}
-
-/**
- * hvc_iucv_sndbuf_work() - Send buffered data over IUCV
- * @work:	Work structure.
- *
- * This work queue function sends buffered output data over IUCV and,
- * if not all buffered data could be sent, reschedules itself.
- */
-static void hvc_iucv_sndbuf_work(struct work_struct *work)
-{
-	struct hvc_iucv_private *priv;
-
-	priv = container_of(work, struct hvc_iucv_private, sndbuf_work.work);
-	if (!priv)
-		return;
-
-	spin_lock_bh(&priv->lock);
-	hvc_iucv_send(priv);
-	spin_unlock_bh(&priv->lock);
-}
-
-/**
- * hvc_iucv_put_chars() - HVC put_chars operation.
- * @vtermno:	HVC virtual terminal number.
- * @buf:	Pointer to an buffer to read data from
- * @count:	Size of buffer available for reading
- *
- * The HVC thread calls this method to write characters to the back-end.
- * The function calls hvc_iucv_queue() to queue terminal data for sending.
- *
- * Locking:	The method gets called under an irqsave() spinlock; and
- *		locks struct hvc_iucv_private->lock.
- */
-static int hvc_iucv_put_chars(uint32_t vtermno, const char *buf, int count)
-{
-	struct hvc_iucv_private *priv = hvc_iucv_get_private(vtermno);
-	int queued;
-
-	if (count <= 0)
-		return 0;
-
-	if (!priv)
-		return -ENODEV;
-
-	spin_lock(&priv->lock);
-	queued = hvc_iucv_queue(priv, buf, count);
-	spin_unlock(&priv->lock);
-
-	return queued;
-}
-
-/**
- * hvc_iucv_notifier_add() - HVC notifier for opening a TTY for the first time.
- * @hp:	Pointer to the HVC device (struct hvc_struct)
- * @id:	Additional data (originally passed to hvc_alloc): the index of an struct
- *	hvc_iucv_private instance.
- *
- * The function sets the tty state to TTY_OPENED for the struct hvc_iucv_private
- * instance that is derived from @id. Always returns 0.
- *
- * Locking:	struct hvc_iucv_private->lock, spin_lock_bh
- */
-static int hvc_iucv_notifier_add(struct hvc_struct *hp, int id)
-{
-	struct hvc_iucv_private *priv;
-
-	priv = hvc_iucv_get_private(id);
-	if (!priv)
-		return 0;
-
-	spin_lock_bh(&priv->lock);
-	priv->tty_state = TTY_OPENED;
-	spin_unlock_bh(&priv->lock);
-
-	return 0;
-}
-
-/**
- * hvc_iucv_cleanup() - Clean up and reset a z/VM IUCV HVC instance.
- * @priv:	Pointer to the struct hvc_iucv_private instance.
- */
-static void hvc_iucv_cleanup(struct hvc_iucv_private *priv)
-{
-	destroy_tty_buffer_list(&priv->tty_outqueue);
-	destroy_tty_buffer_list(&priv->tty_inqueue);
-
-	priv->tty_state = TTY_CLOSED;
-	priv->iucv_state = IUCV_DISCONN;
-
-	priv->sndbuf_len = 0;
-}
-
-/**
- * tty_outqueue_empty() - Test if the tty outq is empty
- * @priv:	Pointer to struct hvc_iucv_private instance.
- */
-static inline int tty_outqueue_empty(struct hvc_iucv_private *priv)
-{
-	int rc;
-
-	spin_lock_bh(&priv->lock);
-	rc = list_empty(&priv->tty_outqueue);
-	spin_unlock_bh(&priv->lock);
-
-	return rc;
-}
-
-/**
- * flush_sndbuf_sync() - Flush send buffer and wait for completion
- * @priv:	Pointer to struct hvc_iucv_private instance.
- *
- * The routine cancels a pending sndbuf work, calls hvc_iucv_send()
- * to flush any buffered terminal output data and waits for completion.
- */
-static void flush_sndbuf_sync(struct hvc_iucv_private *priv)
-{
-	int sync_wait;
-
-	cancel_delayed_work_sync(&priv->sndbuf_work);
-
-	spin_lock_bh(&priv->lock);
-	hvc_iucv_send(priv);		/* force sending buffered data */
-	sync_wait = !list_empty(&priv->tty_outqueue); /* anything queued ? */
-	spin_unlock_bh(&priv->lock);
-
-	if (sync_wait)
-		wait_event_timeout(priv->sndbuf_waitq,
-				   tty_outqueue_empty(priv), HZ/10);
-}
-
-/**
- * hvc_iucv_hangup() - Sever IUCV path and schedule hvc tty hang up
- * @priv:	Pointer to hvc_iucv_private structure
- *
- * This routine severs an existing IUCV communication path and hangs
- * up the underlying HVC terminal device.
- * The hang-up occurs only if an IUCV communication path is established;
- * otherwise there is no need to hang up the terminal device.
- *
- * The IUCV HVC hang-up is separated into two steps:
- * 1. After the IUCV path has been severed, the iucv_state is set to
- *    IUCV_SEVERED.
- * 2. Later, when the HVC thread calls hvc_iucv_get_chars(), the
- *    IUCV_SEVERED state causes the tty hang-up in the HVC layer.
- *
- * If the tty has not yet been opened, clean up the hvc_iucv_private
- * structure to allow re-connects.
- * If the tty has been opened, let get_chars() return -EPIPE to signal
- * the HVC layer to hang up the tty and, if so, wake up the HVC thread
- * to call get_chars()...
- *
- * Special notes on hanging up a HVC terminal instantiated as console:
- * Hang-up:	1. do_tty_hangup() replaces file ops (= hung_up_tty_fops)
- *		2. do_tty_hangup() calls tty->ops->close() for console_filp
- *			=> no hangup notifier is called by HVC (default)
- *		2. hvc_close() returns because of tty_hung_up_p(filp)
- *			=> no delete notifier is called!
- * Finally, the back-end is not being notified, thus, the tty session is
- * kept active (TTY_OPEN) to be ready for re-connects.
- *
- * Locking:	spin_lock(&priv->lock) w/o disabling bh
- */
-static void hvc_iucv_hangup(struct hvc_iucv_private *priv)
-{
-	struct iucv_path *path;
-
-	path = NULL;
-	spin_lock(&priv->lock);
-	if (priv->iucv_state == IUCV_CONNECTED) {
-		path = priv->path;
-		priv->path = NULL;
-		priv->iucv_state = IUCV_SEVERED;
-		if (priv->tty_state == TTY_CLOSED)
-			hvc_iucv_cleanup(priv);
-		else
-			/* console is special (see above) */
-			if (priv->is_console) {
-				hvc_iucv_cleanup(priv);
-				priv->tty_state = TTY_OPENED;
-			} else
-				hvc_kick();
-	}
-	spin_unlock(&priv->lock);
-
-	/* finally sever path (outside of priv->lock due to lock ordering) */
-	if (path) {
-		iucv_path_sever(path, NULL);
-		iucv_path_free(path);
-	}
-}
-
-/**
- * hvc_iucv_notifier_hangup() - HVC notifier for TTY hangups.
- * @hp:		Pointer to the HVC device (struct hvc_struct)
- * @id:		Additional data (originally passed to hvc_alloc):
- *		the index of an struct hvc_iucv_private instance.
- *
- * This routine notifies the HVC back-end that a tty hangup (carrier loss,
- * virtual or otherwise) has occured.
- * The z/VM IUCV HVC device driver ignores virtual hangups (vhangup())
- * to keep an existing IUCV communication path established.
- * (Background: vhangup() is called from user space (by getty or login) to
- *		disable writing to the tty by other applications).
- * If the tty has been opened and an established IUCV path has been severed
- * (we caused the tty hangup), the function calls hvc_iucv_cleanup().
- *
- * Locking:	struct hvc_iucv_private->lock
- */
-static void hvc_iucv_notifier_hangup(struct hvc_struct *hp, int id)
-{
-	struct hvc_iucv_private *priv;
-
-	priv = hvc_iucv_get_private(id);
-	if (!priv)
-		return;
-
-	flush_sndbuf_sync(priv);
-
-	spin_lock_bh(&priv->lock);
-	/* NOTE: If the hangup was scheduled by ourself (from the iucv
-	 *	 path_servered callback [IUCV_SEVERED]), we have to clean up
-	 *	 our structure and to set state to TTY_CLOSED.
-	 *	 If the tty was hung up otherwise (e.g. vhangup()), then we
-	 *	 ignore this hangup and keep an established IUCV path open...
-	 *	 (...the reason is that we are not able to connect back to the
-	 *	 client if we disconnect on hang up) */
-	priv->tty_state = TTY_CLOSED;
-
-	if (priv->iucv_state == IUCV_SEVERED)
-		hvc_iucv_cleanup(priv);
-	spin_unlock_bh(&priv->lock);
-}
-
-/**
- * hvc_iucv_notifier_del() - HVC notifier for closing a TTY for the last time.
- * @hp:		Pointer to the HVC device (struct hvc_struct)
- * @id:		Additional data (originally passed to hvc_alloc):
- *		the index of an struct hvc_iucv_private instance.
- *
- * This routine notifies the HVC back-end that the last tty device fd has been
- * closed.  The function calls hvc_iucv_cleanup() to clean up the struct
- * hvc_iucv_private instance.
- *
- * Locking:	struct hvc_iucv_private->lock
- */
-static void hvc_iucv_notifier_del(struct hvc_struct *hp, int id)
-{
-	struct hvc_iucv_private *priv;
-	struct iucv_path	*path;
-
-	priv = hvc_iucv_get_private(id);
-	if (!priv)
-		return;
-
-	flush_sndbuf_sync(priv);
-
-	spin_lock_bh(&priv->lock);
-	path = priv->path;		/* save reference to IUCV path */
-	priv->path = NULL;
-	hvc_iucv_cleanup(priv);
-	spin_unlock_bh(&priv->lock);
-
-	/* sever IUCV path outside of priv->lock due to lock ordering of:
-	 * priv->lock <--> iucv_table_lock */
-	if (path) {
-		iucv_path_sever(path, NULL);
-		iucv_path_free(path);
-	}
-}
-
-/**
- * hvc_iucv_filter_connreq() - Filter connection request based on z/VM user ID
- * @ipvmid:	Originating z/VM user ID (right padded with blanks)
- *
- * Returns 0 if the z/VM user ID @ipvmid is allowed to connection, otherwise
- * non-zero.
- */
-static int hvc_iucv_filter_connreq(u8 ipvmid[8])
-{
-	size_t i;
-
-	/* Note: default policy is ACCEPT if no filter is set */
-	if (!hvc_iucv_filter_size)
-		return 0;
-
-	for (i = 0; i < hvc_iucv_filter_size; i++)
-		if (0 == memcmp(ipvmid, hvc_iucv_filter + (8 * i), 8))
-			return 0;
-	return 1;
-}
-
-/**
- * hvc_iucv_path_pending() - IUCV handler to process a connection request.
- * @path:	Pending path (struct iucv_path)
- * @ipvmid:	z/VM system identifier of originator
- * @ipuser:	User specified data for this path
- *		(AF_IUCV: port/service name and originator port)
- *
- * The function uses the @ipuser data to determine if the pending path belongs
- * to a terminal managed by this device driver.
- * If the path belongs to this driver, ensure that the terminal is not accessed
- * multiple times (only one connection to a terminal is allowed).
- * If the terminal is not yet connected, the pending path is accepted and is
- * associated to the appropriate struct hvc_iucv_private instance.
- *
- * Returns 0 if @path belongs to a terminal managed by the this device driver;
- * otherwise returns -ENODEV in order to dispatch this path to other handlers.
- *
- * Locking:	struct hvc_iucv_private->lock
- */
-static	int hvc_iucv_path_pending(struct iucv_path *path,
-				  u8 ipvmid[8], u8 ipuser[16])
-{
-	struct hvc_iucv_private *priv;
-	u8 nuser_data[16];
-	u8 vm_user_id[9];
-	int i, rc;
-
-	priv = NULL;
-	for (i = 0; i < hvc_iucv_devices; i++)
-		if (hvc_iucv_table[i] &&
-		    (0 == memcmp(hvc_iucv_table[i]->srv_name, ipuser, 8))) {
-			priv = hvc_iucv_table[i];
-			break;
-		}
-	if (!priv)
-		return -ENODEV;
-
-	/* Enforce that ipvmid is allowed to connect to us */
-	read_lock(&hvc_iucv_filter_lock);
-	rc = hvc_iucv_filter_connreq(ipvmid);
-	read_unlock(&hvc_iucv_filter_lock);
-	if (rc) {
-		iucv_path_sever(path, ipuser);
-		iucv_path_free(path);
-		memcpy(vm_user_id, ipvmid, 8);
-		vm_user_id[8] = 0;
-		pr_info("A connection request from z/VM user ID %s "
-			"was refused\n", vm_user_id);
-		return 0;
-	}
-
-	spin_lock(&priv->lock);
-
-	/* If the terminal is already connected or being severed, then sever
-	 * this path to enforce that there is only ONE established communication
-	 * path per terminal. */
-	if (priv->iucv_state != IUCV_DISCONN) {
-		iucv_path_sever(path, ipuser);
-		iucv_path_free(path);
-		goto out_path_handled;
-	}
-
-	/* accept path */
-	memcpy(nuser_data, ipuser + 8, 8);  /* remote service (for af_iucv) */
-	memcpy(nuser_data + 8, ipuser, 8);  /* local service  (for af_iucv) */
-	path->msglim = 0xffff;		    /* IUCV MSGLIMIT */
-	path->flags &= ~IUCV_IPRMDATA;	    /* TODO: use IUCV_IPRMDATA */
-	rc = iucv_path_accept(path, &hvc_iucv_handler, nuser_data, priv);
-	if (rc) {
-		iucv_path_sever(path, ipuser);
-		iucv_path_free(path);
-		goto out_path_handled;
-	}
-	priv->path = path;
-	priv->iucv_state = IUCV_CONNECTED;
-
-	/* flush buffered output data... */
-	schedule_delayed_work(&priv->sndbuf_work, 5);
-
-out_path_handled:
-	spin_unlock(&priv->lock);
-	return 0;
-}
-
-/**
- * hvc_iucv_path_severed() - IUCV handler to process a path sever.
- * @path:	Pending path (struct iucv_path)
- * @ipuser:	User specified data for this path
- *		(AF_IUCV: port/service name and originator port)
- *
- * This function calls the hvc_iucv_hangup() function for the
- * respective IUCV HVC terminal.
- *
- * Locking:	struct hvc_iucv_private->lock
- */
-static void hvc_iucv_path_severed(struct iucv_path *path, u8 ipuser[16])
-{
-	struct hvc_iucv_private *priv = path->private;
-
-	hvc_iucv_hangup(priv);
-}
-
-/**
- * hvc_iucv_msg_pending() - IUCV handler to process an incoming IUCV message.
- * @path:	Pending path (struct iucv_path)
- * @msg:	Pointer to the IUCV message
- *
- * The function puts an incoming message on the input queue for later
- * processing (by hvc_iucv_get_chars() / hvc_iucv_write()).
- * If the tty has not yet been opened, the message is rejected.
- *
- * Locking:	struct hvc_iucv_private->lock
- */
-static void hvc_iucv_msg_pending(struct iucv_path *path,
-				 struct iucv_message *msg)
-{
-	struct hvc_iucv_private *priv = path->private;
-	struct iucv_tty_buffer *rb;
-
-	/* reject messages that exceed max size of iucv_tty_msg->datalen */
-	if (msg->length > MSG_SIZE(MSG_MAX_DATALEN)) {
-		iucv_message_reject(path, msg);
-		return;
-	}
-
-	spin_lock(&priv->lock);
-
-	/* reject messages if tty has not yet been opened */
-	if (priv->tty_state == TTY_CLOSED) {
-		iucv_message_reject(path, msg);
-		goto unlock_return;
-	}
-
-	/* allocate tty buffer to save iucv msg only */
-	rb = alloc_tty_buffer(0, GFP_ATOMIC);
-	if (!rb) {
-		iucv_message_reject(path, msg);
-		goto unlock_return;	/* -ENOMEM */
-	}
-	rb->msg = *msg;
-
-	list_add_tail(&rb->list, &priv->tty_inqueue);
-
-	hvc_kick();	/* wake up hvc thread */
-
-unlock_return:
-	spin_unlock(&priv->lock);
-}
-
-/**
- * hvc_iucv_msg_complete() - IUCV handler to process message completion
- * @path:	Pending path (struct iucv_path)
- * @msg:	Pointer to the IUCV message
- *
- * The function is called upon completion of message delivery to remove the
- * message from the outqueue. Additional delivery information can be found
- * msg->audit: rejected messages (0x040000 (IPADRJCT)), and
- *	       purged messages	 (0x010000 (IPADPGNR)).
- *
- * Locking:	struct hvc_iucv_private->lock
- */
-static void hvc_iucv_msg_complete(struct iucv_path *path,
-				  struct iucv_message *msg)
-{
-	struct hvc_iucv_private *priv = path->private;
-	struct iucv_tty_buffer	*ent, *next;
-	LIST_HEAD(list_remove);
-
-	spin_lock(&priv->lock);
-	list_for_each_entry_safe(ent, next, &priv->tty_outqueue, list)
-		if (ent->msg.id == msg->id) {
-			list_move(&ent->list, &list_remove);
-			break;
-		}
-	wake_up(&priv->sndbuf_waitq);
-	spin_unlock(&priv->lock);
-	destroy_tty_buffer_list(&list_remove);
-}
-
-/**
- * hvc_iucv_pm_freeze() - Freeze PM callback
- * @dev:	IUVC HVC terminal device
- *
- * Sever an established IUCV communication path and
- * trigger a hang-up of the underlying HVC terminal.
- */
-static int hvc_iucv_pm_freeze(struct device *dev)
-{
-	struct hvc_iucv_private *priv = dev_get_drvdata(dev);
-
-	local_bh_disable();
-	hvc_iucv_hangup(priv);
-	local_bh_enable();
-
-	return 0;
-}
-
-/**
- * hvc_iucv_pm_restore_thaw() - Thaw and restore PM callback
- * @dev:	IUVC HVC terminal device
- *
- * Wake up the HVC thread to trigger hang-up and respective
- * HVC back-end notifier invocations.
- */
-static int hvc_iucv_pm_restore_thaw(struct device *dev)
-{
-	hvc_kick();
-	return 0;
-}
-
-
-/* HVC operations */
-static const struct hv_ops hvc_iucv_ops = {
-	.get_chars = hvc_iucv_get_chars,
-	.put_chars = hvc_iucv_put_chars,
-	.notifier_add = hvc_iucv_notifier_add,
-	.notifier_del = hvc_iucv_notifier_del,
-	.notifier_hangup = hvc_iucv_notifier_hangup,
-};
-
-/* Suspend / resume device operations */
-static const struct dev_pm_ops hvc_iucv_pm_ops = {
-	.freeze	  = hvc_iucv_pm_freeze,
-	.thaw	  = hvc_iucv_pm_restore_thaw,
-	.restore  = hvc_iucv_pm_restore_thaw,
-};
-
-/* IUCV HVC device driver */
-static struct device_driver hvc_iucv_driver = {
-	.name = KMSG_COMPONENT,
-	.bus  = &iucv_bus,
-	.pm   = &hvc_iucv_pm_ops,
-};
-
-/**
- * hvc_iucv_alloc() - Allocates a new struct hvc_iucv_private instance
- * @id:			hvc_iucv_table index
- * @is_console:		Flag if the instance is used as Linux console
- *
- * This function allocates a new hvc_iucv_private structure and stores
- * the instance in hvc_iucv_table at index @id.
- * Returns 0 on success; otherwise non-zero.
- */
-static int __init hvc_iucv_alloc(int id, unsigned int is_console)
-{
-	struct hvc_iucv_private *priv;
-	char name[9];
-	int rc;
-
-	priv = kzalloc(sizeof(struct hvc_iucv_private), GFP_KERNEL);
-	if (!priv)
-		return -ENOMEM;
-
-	spin_lock_init(&priv->lock);
-	INIT_LIST_HEAD(&priv->tty_outqueue);
-	INIT_LIST_HEAD(&priv->tty_inqueue);
-	INIT_DELAYED_WORK(&priv->sndbuf_work, hvc_iucv_sndbuf_work);
-	init_waitqueue_head(&priv->sndbuf_waitq);
-
-	priv->sndbuf = (void *) get_zeroed_page(GFP_KERNEL);
-	if (!priv->sndbuf) {
-		kfree(priv);
-		return -ENOMEM;
-	}
-
-	/* set console flag */
-	priv->is_console = is_console;
-
-	/* allocate hvc device */
-	priv->hvc = hvc_alloc(HVC_IUCV_MAGIC + id, /*		  PAGE_SIZE */
-			      HVC_IUCV_MAGIC + id, &hvc_iucv_ops, 256);
-	if (IS_ERR(priv->hvc)) {
-		rc = PTR_ERR(priv->hvc);
-		goto out_error_hvc;
-	}
-
-	/* notify HVC thread instead of using polling */
-	priv->hvc->irq_requested = 1;
-
-	/* setup iucv related information */
-	snprintf(name, 9, "lnxhvc%-2d", id);
-	memcpy(priv->srv_name, name, 8);
-	ASCEBC(priv->srv_name, 8);
-
-	/* create and setup device */
-	priv->dev = kzalloc(sizeof(*priv->dev), GFP_KERNEL);
-	if (!priv->dev) {
-		rc = -ENOMEM;
-		goto out_error_dev;
-	}
-	dev_set_name(priv->dev, "hvc_iucv%d", id);
-	dev_set_drvdata(priv->dev, priv);
-	priv->dev->bus = &iucv_bus;
-	priv->dev->parent = iucv_root;
-	priv->dev->driver = &hvc_iucv_driver;
-	priv->dev->release = (void (*)(struct device *)) kfree;
-	rc = device_register(priv->dev);
-	if (rc) {
-		put_device(priv->dev);
-		goto out_error_dev;
-	}
-
-	hvc_iucv_table[id] = priv;
-	return 0;
-
-out_error_dev:
-	hvc_remove(priv->hvc);
-out_error_hvc:
-	free_page((unsigned long) priv->sndbuf);
-	kfree(priv);
-
-	return rc;
-}
-
-/**
- * hvc_iucv_destroy() - Destroy and free hvc_iucv_private instances
- */
-static void __init hvc_iucv_destroy(struct hvc_iucv_private *priv)
-{
-	hvc_remove(priv->hvc);
-	device_unregister(priv->dev);
-	free_page((unsigned long) priv->sndbuf);
-	kfree(priv);
-}
-
-/**
- * hvc_iucv_parse_filter() - Parse filter for a single z/VM user ID
- * @filter:	String containing a comma-separated list of z/VM user IDs
- */
-static const char *hvc_iucv_parse_filter(const char *filter, char *dest)
-{
-	const char *nextdelim, *residual;
-	size_t len;
-
-	nextdelim = strchr(filter, ',');
-	if (nextdelim) {
-		len = nextdelim - filter;
-		residual = nextdelim + 1;
-	} else {
-		len = strlen(filter);
-		residual = filter + len;
-	}
-
-	if (len == 0)
-		return ERR_PTR(-EINVAL);
-
-	/* check for '\n' (if called from sysfs) */
-	if (filter[len - 1] == '\n')
-		len--;
-
-	if (len > 8)
-		return ERR_PTR(-EINVAL);
-
-	/* pad with blanks and save upper case version of user ID */
-	memset(dest, ' ', 8);
-	while (len--)
-		dest[len] = toupper(filter[len]);
-	return residual;
-}
-
-/**
- * hvc_iucv_setup_filter() - Set up z/VM user ID filter
- * @filter:	String consisting of a comma-separated list of z/VM user IDs
- *
- * The function parses the @filter string and creates an array containing
- * the list of z/VM user ID filter entries.
- * Return code 0 means success, -EINVAL if the filter is syntactically
- * incorrect, -ENOMEM if there was not enough memory to allocate the
- * filter list array, or -ENOSPC if too many z/VM user IDs have been specified.
- */
-static int hvc_iucv_setup_filter(const char *val)
-{
-	const char *residual;
-	int err;
-	size_t size, count;
-	void *array, *old_filter;
-
-	count = strlen(val);
-	if (count == 0 || (count == 1 && val[0] == '\n')) {
-		size  = 0;
-		array = NULL;
-		goto out_replace_filter;	/* clear filter */
-	}
-
-	/* count user IDs in order to allocate sufficient memory */
-	size = 1;
-	residual = val;
-	while ((residual = strchr(residual, ',')) != NULL) {
-		residual++;
-		size++;
-	}
-
-	/* check if the specified list exceeds the filter limit */
-	if (size > MAX_VMID_FILTER)
-		return -ENOSPC;
-
-	array = kzalloc(size * 8, GFP_KERNEL);
-	if (!array)
-		return -ENOMEM;
-
-	count = size;
-	residual = val;
-	while (*residual && count) {
-		residual = hvc_iucv_parse_filter(residual,
-						 array + ((size - count) * 8));
-		if (IS_ERR(residual)) {
-			err = PTR_ERR(residual);
-			kfree(array);
-			goto out_err;
-		}
-		count--;
-	}
-
-out_replace_filter:
-	write_lock_bh(&hvc_iucv_filter_lock);
-	old_filter = hvc_iucv_filter;
-	hvc_iucv_filter_size = size;
-	hvc_iucv_filter = array;
-	write_unlock_bh(&hvc_iucv_filter_lock);
-	kfree(old_filter);
-
-	err = 0;
-out_err:
-	return err;
-}
-
-/**
- * param_set_vmidfilter() - Set z/VM user ID filter parameter
- * @val:	String consisting of a comma-separated list of z/VM user IDs
- * @kp:		Kernel parameter pointing to hvc_iucv_filter array
- *
- * The function sets up the z/VM user ID filter specified as comma-separated
- * list of user IDs in @val.
- * Note: If it is called early in the boot process, @val is stored and
- *	 parsed later in hvc_iucv_init().
- */
-static int param_set_vmidfilter(const char *val, const struct kernel_param *kp)
-{
-	int rc;
-
-	if (!MACHINE_IS_VM || !hvc_iucv_devices)
-		return -ENODEV;
-
-	if (!val)
-		return -EINVAL;
-
-	rc = 0;
-	if (slab_is_available())
-		rc = hvc_iucv_setup_filter(val);
-	else
-		hvc_iucv_filter_string = val;	/* defer... */
-	return rc;
-}
-
-/**
- * param_get_vmidfilter() - Get z/VM user ID filter
- * @buffer:	Buffer to store z/VM user ID filter,
- *		(buffer size assumption PAGE_SIZE)
- * @kp:		Kernel parameter pointing to the hvc_iucv_filter array
- *
- * The function stores the filter as a comma-separated list of z/VM user IDs
- * in @buffer. Typically, sysfs routines call this function for attr show.
- */
-static int param_get_vmidfilter(char *buffer, const struct kernel_param *kp)
-{
-	int rc;
-	size_t index, len;
-	void *start, *end;
-
-	if (!MACHINE_IS_VM || !hvc_iucv_devices)
-		return -ENODEV;
-
-	rc = 0;
-	read_lock_bh(&hvc_iucv_filter_lock);
-	for (index = 0; index < hvc_iucv_filter_size; index++) {
-		start = hvc_iucv_filter + (8 * index);
-		end   = memchr(start, ' ', 8);
-		len   = (end) ? end - start : 8;
-		memcpy(buffer + rc, start, len);
-		rc += len;
-		buffer[rc++] = ',';
-	}
-	read_unlock_bh(&hvc_iucv_filter_lock);
-	if (rc)
-		buffer[--rc] = '\0';	/* replace last comma and update rc */
-	return rc;
-}
-
-#define param_check_vmidfilter(name, p) __param_check(name, p, void)
-
-static struct kernel_param_ops param_ops_vmidfilter = {
-	.set = param_set_vmidfilter,
-	.get = param_get_vmidfilter,
-};
-
-/**
- * hvc_iucv_init() - z/VM IUCV HVC device driver initialization
- */
-static int __init hvc_iucv_init(void)
-{
-	int rc;
-	unsigned int i;
-
-	if (!hvc_iucv_devices)
-		return -ENODEV;
-
-	if (!MACHINE_IS_VM) {
-		pr_notice("The z/VM IUCV HVC device driver cannot "
-			   "be used without z/VM\n");
-		rc = -ENODEV;
-		goto out_error;
-	}
-
-	if (hvc_iucv_devices > MAX_HVC_IUCV_LINES) {
-		pr_err("%lu is not a valid value for the hvc_iucv= "
-			"kernel parameter\n", hvc_iucv_devices);
-		rc = -EINVAL;
-		goto out_error;
-	}
-
-	/* register IUCV HVC device driver */
-	rc = driver_register(&hvc_iucv_driver);
-	if (rc)
-		goto out_error;
-
-	/* parse hvc_iucv_allow string and create z/VM user ID filter list */
-	if (hvc_iucv_filter_string) {
-		rc = hvc_iucv_setup_filter(hvc_iucv_filter_string);
-		switch (rc) {
-		case 0:
-			break;
-		case -ENOMEM:
-			pr_err("Allocating memory failed with "
-				"reason code=%d\n", 3);
-			goto out_error;
-		case -EINVAL:
-			pr_err("hvc_iucv_allow= does not specify a valid "
-				"z/VM user ID list\n");
-			goto out_error;
-		case -ENOSPC:
-			pr_err("hvc_iucv_allow= specifies too many "
-				"z/VM user IDs\n");
-			goto out_error;
-		default:
-			goto out_error;
-		}
-	}
-
-	hvc_iucv_buffer_cache = kmem_cache_create(KMSG_COMPONENT,
-					   sizeof(struct iucv_tty_buffer),
-					   0, 0, NULL);
-	if (!hvc_iucv_buffer_cache) {
-		pr_err("Allocating memory failed with reason code=%d\n", 1);
-		rc = -ENOMEM;
-		goto out_error;
-	}
-
-	hvc_iucv_mempool = mempool_create_slab_pool(MEMPOOL_MIN_NR,
-						    hvc_iucv_buffer_cache);
-	if (!hvc_iucv_mempool) {
-		pr_err("Allocating memory failed with reason code=%d\n", 2);
-		kmem_cache_destroy(hvc_iucv_buffer_cache);
-		rc = -ENOMEM;
-		goto out_error;
-	}
-
-	/* register the first terminal device as console
-	 * (must be done before allocating hvc terminal devices) */
-	rc = hvc_instantiate(HVC_IUCV_MAGIC, IUCV_HVC_CON_IDX, &hvc_iucv_ops);
-	if (rc) {
-		pr_err("Registering HVC terminal device as "
-		       "Linux console failed\n");
-		goto out_error_memory;
-	}
-
-	/* allocate hvc_iucv_private structs */
-	for (i = 0; i < hvc_iucv_devices; i++) {
-		rc = hvc_iucv_alloc(i, (i == IUCV_HVC_CON_IDX) ? 1 : 0);
-		if (rc) {
-			pr_err("Creating a new HVC terminal device "
-				"failed with error code=%d\n", rc);
-			goto out_error_hvc;
-		}
-	}
-
-	/* register IUCV callback handler */
-	rc = iucv_register(&hvc_iucv_handler, 0);
-	if (rc) {
-		pr_err("Registering IUCV handlers failed with error code=%d\n",
-			rc);
-		goto out_error_hvc;
-	}
-
-	return 0;
-
-out_error_hvc:
-	for (i = 0; i < hvc_iucv_devices; i++)
-		if (hvc_iucv_table[i])
-			hvc_iucv_destroy(hvc_iucv_table[i]);
-out_error_memory:
-	mempool_destroy(hvc_iucv_mempool);
-	kmem_cache_destroy(hvc_iucv_buffer_cache);
-out_error:
-	if (hvc_iucv_filter)
-		kfree(hvc_iucv_filter);
-	hvc_iucv_devices = 0; /* ensure that we do not provide any device */
-	return rc;
-}
-
-/**
- * hvc_iucv_config() - Parsing of hvc_iucv=  kernel command line parameter
- * @val:	Parameter value (numeric)
- */
-static	int __init hvc_iucv_config(char *val)
-{
-	 return strict_strtoul(val, 10, &hvc_iucv_devices);
-}
-
-
-device_initcall(hvc_iucv_init);
-__setup("hvc_iucv=", hvc_iucv_config);
-core_param(hvc_iucv_allow, hvc_iucv_filter, vmidfilter, 0640);
diff -druNp linux-libre-2.6.37-gnu1/drivers/char/hvc_rtas.c linux-libre-2.6.38-gnu1/drivers/char/hvc_rtas.c
--- linux-libre-2.6.37-gnu1/drivers/char/hvc_rtas.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/char/hvc_rtas.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,133 +0,0 @@
-/*
- * IBM RTAS driver interface to hvc_console.c
- *
- * (C) Copyright IBM Corporation 2001-2005
- * (C) Copyright Red Hat, Inc. 2005
- *
- * Author(s): Maximino Augilar <IBM STI Design Center>
- *	    : Ryan S. Arnold <rsa@us.ibm.com>
- *	    : Utz Bacher <utz.bacher@de.ibm.com>
- *	    : David Woodhouse <dwmw2@infradead.org>
- *
- *    inspired by drivers/char/hvc_console.c
- *    written by Anton Blanchard and Paul Mackerras
- *
- * 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/console.h>
-#include <linux/delay.h>
-#include <linux/err.h>
-#include <linux/init.h>
-#include <linux/moduleparam.h>
-#include <linux/types.h>
-
-#include <asm/irq.h>
-#include <asm/rtas.h>
-#include "hvc_console.h"
-
-#define hvc_rtas_cookie 0x67781e15
-struct hvc_struct *hvc_rtas_dev;
-
-static int rtascons_put_char_token = RTAS_UNKNOWN_SERVICE;
-static int rtascons_get_char_token = RTAS_UNKNOWN_SERVICE;
-
-static inline int hvc_rtas_write_console(uint32_t vtermno, const char *buf,
-		int count)
-{
-	int i;
-
-	for (i = 0; i < count; i++) {
-		if (rtas_call(rtascons_put_char_token, 1, 1, NULL, buf[i]))
-			break;
-	}
-
-	return i;
-}
-
-static int hvc_rtas_read_console(uint32_t vtermno, char *buf, int count)
-{
-	int i, c;
-
-	for (i = 0; i < count; i++) {
-		if (rtas_call(rtascons_get_char_token, 0, 2, &c))
-			break;
-
-		buf[i] = c;
-	}
-
-	return i;
-}
-
-static const struct hv_ops hvc_rtas_get_put_ops = {
-	.get_chars = hvc_rtas_read_console,
-	.put_chars = hvc_rtas_write_console,
-};
-
-static int __init hvc_rtas_init(void)
-{
-	struct hvc_struct *hp;
-
-	if (rtascons_put_char_token == RTAS_UNKNOWN_SERVICE)
-		rtascons_put_char_token = rtas_token("put-term-char");
-	if (rtascons_put_char_token == RTAS_UNKNOWN_SERVICE)
-		return -EIO;
-
-	if (rtascons_get_char_token == RTAS_UNKNOWN_SERVICE)
-		rtascons_get_char_token = rtas_token("get-term-char");
-	if (rtascons_get_char_token == RTAS_UNKNOWN_SERVICE)
-		return -EIO;
-
-	BUG_ON(hvc_rtas_dev);
-
-	/* Allocate an hvc_struct for the console device we instantiated
-	 * earlier.  Save off hp so that we can return it on exit */
-	hp = hvc_alloc(hvc_rtas_cookie, NO_IRQ, &hvc_rtas_get_put_ops, 16);
-	if (IS_ERR(hp))
-		return PTR_ERR(hp);
-
-	hvc_rtas_dev = hp;
-
-	return 0;
-}
-module_init(hvc_rtas_init);
-
-/* This will tear down the tty portion of the driver */
-static void __exit hvc_rtas_exit(void)
-{
-	/* Really the fun isn't over until the worker thread breaks down and
-	 * the tty cleans up */
-	if (hvc_rtas_dev)
-		hvc_remove(hvc_rtas_dev);
-}
-module_exit(hvc_rtas_exit);
-
-/* This will happen prior to module init.  There is no tty at this time? */
-static int __init hvc_rtas_console_init(void)
-{
-	rtascons_put_char_token = rtas_token("put-term-char");
-	if (rtascons_put_char_token == RTAS_UNKNOWN_SERVICE)
-		return -EIO;
-
-	rtascons_get_char_token = rtas_token("get-term-char");
-	if (rtascons_get_char_token == RTAS_UNKNOWN_SERVICE)
-		return -EIO;
-
-	hvc_instantiate(hvc_rtas_cookie, 0, &hvc_rtas_get_put_ops);
-	add_preferred_console("hvc", 0, NULL);
-
-	return 0;
-}
-console_initcall(hvc_rtas_console_init);
diff -druNp linux-libre-2.6.37-gnu1/drivers/char/hvcs.c linux-libre-2.6.38-gnu1/drivers/char/hvcs.c
--- linux-libre-2.6.37-gnu1/drivers/char/hvcs.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/char/hvcs.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1604 +0,0 @@
-/*
- * IBM eServer Hypervisor Virtual Console Server Device Driver
- * Copyright (C) 2003, 2004 IBM Corp.
- *  Ryan S. Arnold (rsa@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
- *
- * Author(s) :  Ryan S. Arnold <rsa@us.ibm.com>
- *
- * This is the device driver for the IBM Hypervisor Virtual Console Server,
- * "hvcs".  The IBM hvcs provides a tty driver interface to allow Linux
- * user space applications access to the system consoles of logically
- * partitioned operating systems, e.g. Linux, running on the same partitioned
- * Power5 ppc64 system.  Physical hardware consoles per partition are not
- * practical on this hardware so system consoles are accessed by this driver
- * using inter-partition firmware interfaces to virtual terminal devices.
- *
- * A vty is known to the HMC as a "virtual serial server adapter".  It is a
- * virtual terminal device that is created by firmware upon partition creation
- * to act as a partitioned OS's console device.
- *
- * Firmware dynamically (via hotplug) exposes vty-servers to a running ppc64
- * Linux system upon their creation by the HMC or their exposure during boot.
- * The non-user interactive backend of this driver is implemented as a vio
- * device driver so that it can receive notification of vty-server lifetimes
- * after it registers with the vio bus to handle vty-server probe and remove
- * callbacks.
- *
- * Many vty-servers can be configured to connect to one vty, but a vty can
- * only be actively connected to by a single vty-server, in any manner, at one
- * time.  If the HMC is currently hosting the console for a target Linux
- * partition; attempts to open the tty device to the partition's console using
- * the hvcs on any partition will return -EBUSY with every open attempt until
- * the HMC frees the connection between its vty-server and the desired
- * partition's vty device.  Conversely, a vty-server may only be connected to
- * a single vty at one time even though it may have several configured vty
- * partner possibilities.
- *
- * Firmware does not provide notification of vty partner changes to this
- * driver.  This means that an HMC Super Admin may add or remove partner vtys
- * from a vty-server's partner list but the changes will not be signaled to
- * the vty-server.  Firmware only notifies the driver when a vty-server is
- * added or removed from the system.  To compensate for this deficiency, this
- * driver implements a sysfs update attribute which provides a method for
- * rescanning partner information upon a user's request.
- *
- * Each vty-server, prior to being exposed to this driver is reference counted
- * using the 2.6 Linux kernel kref construct.
- *
- * For direction on installation and usage of this driver please reference
- * Documentation/powerpc/hvcs.txt.
- */
-
-#include <linux/device.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <linux/kref.h>
-#include <linux/kthread.h>
-#include <linux/list.h>
-#include <linux/major.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/spinlock.h>
-#include <linux/stat.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <asm/hvconsole.h>
-#include <asm/hvcserver.h>
-#include <asm/uaccess.h>
-#include <asm/vio.h>
-
-/*
- * 1.3.0 -> 1.3.1 In hvcs_open memset(..,0x00,..) instead of memset(..,0x3F,00).
- * Removed braces around single statements following conditionals.  Removed '=
- * 0' after static int declarations since these default to zero.  Removed
- * list_for_each_safe() and replaced with list_for_each_entry() in
- * hvcs_get_by_index().  The 'safe' version is un-needed now that the driver is
- * using spinlocks.  Changed spin_lock_irqsave() to spin_lock() when locking
- * hvcs_structs_lock and hvcs_pi_lock since these are not touched in an int
- * handler.  Initialized hvcs_structs_lock and hvcs_pi_lock to
- * SPIN_LOCK_UNLOCKED at declaration time rather than in hvcs_module_init().
- * Added spin_lock around list_del() in destroy_hvcs_struct() to protect the
- * list traversals from a deletion.  Removed '= NULL' from pointer declaration
- * statements since they are initialized NULL by default.  Removed wmb()
- * instances from hvcs_try_write().  They probably aren't needed with locking in
- * place.  Added check and cleanup for hvcs_pi_buff = kmalloc() in
- * hvcs_module_init().  Exposed hvcs_struct.index via a sysfs attribute so that
- * the coupling between /dev/hvcs* and a vty-server can be automatically
- * determined.  Moved kobject_put() in hvcs_open outside of the
- * spin_unlock_irqrestore().
- *
- * 1.3.1 -> 1.3.2 Changed method for determining hvcs_struct->index and had it
- * align with how the tty layer always assigns the lowest index available.  This
- * change resulted in a list of ints that denotes which indexes are available.
- * Device additions and removals use the new hvcs_get_index() and
- * hvcs_return_index() helper functions.  The list is created with
- * hvsc_alloc_index_list() and it is destroyed with hvcs_free_index_list().
- * Without these fixes hotplug vty-server adapter support goes crazy with this
- * driver if the user removes a vty-server adapter.  Moved free_irq() outside of
- * the hvcs_final_close() function in order to get it out of the spinlock.
- * Rearranged hvcs_close().  Cleaned up some printks and did some housekeeping
- * on the changelog.  Removed local CLC_LENGTH and used HVCS_CLC_LENGTH from
- * arch/powerepc/include/asm/hvcserver.h
- *
- * 1.3.2 -> 1.3.3 Replaced yield() in hvcs_close() with tty_wait_until_sent() to
- * prevent possible lockup with realtime scheduling as similarily pointed out by
- * akpm in hvc_console.  Changed resulted in the removal of hvcs_final_close()
- * to reorder cleanup operations and prevent discarding of pending data during
- * an hvcs_close().  Removed spinlock protection of hvcs_struct data members in
- * hvcs_write_room() and hvcs_chars_in_buffer() because they aren't needed.
- */
-
-#define HVCS_DRIVER_VERSION "1.3.3"
-
-MODULE_AUTHOR("Ryan S. Arnold <rsa@us.ibm.com>");
-MODULE_DESCRIPTION("IBM hvcs (Hypervisor Virtual Console Server) Driver");
-MODULE_LICENSE("GPL");
-MODULE_VERSION(HVCS_DRIVER_VERSION);
-
-/*
- * Wait this long per iteration while trying to push buffered data to the
- * hypervisor before allowing the tty to complete a close operation.
- */
-#define HVCS_CLOSE_WAIT (HZ/100) /* 1/10 of a second */
-
-/*
- * Since the Linux TTY code does not currently (2-04-2004) support dynamic
- * addition of tty derived devices and we shouldn't allocate thousands of
- * tty_device pointers when the number of vty-server & vty partner connections
- * will most often be much lower than this, we'll arbitrarily allocate
- * HVCS_DEFAULT_SERVER_ADAPTERS tty_structs and cdev's by default when we
- * register the tty_driver. This can be overridden using an insmod parameter.
- */
-#define HVCS_DEFAULT_SERVER_ADAPTERS	64
-
-/*
- * The user can't insmod with more than HVCS_MAX_SERVER_ADAPTERS hvcs device
- * nodes as a sanity check.  Theoretically there can be over 1 Billion
- * vty-server & vty partner connections.
- */
-#define HVCS_MAX_SERVER_ADAPTERS	1024
-
-/*
- * We let Linux assign us a major number and we start the minors at zero.  There
- * is no intuitive mapping between minor number and the target vty-server
- * adapter except that each new vty-server adapter is always assigned to the
- * smallest minor number available.
- */
-#define HVCS_MINOR_START	0
-
-/*
- * The hcall interface involves putting 8 chars into each of two registers.
- * We load up those 2 registers (in arch/powerpc/platforms/pseries/hvconsole.c)
- * by casting char[16] to long[2].  It would work without __ALIGNED__, but a 
- * little (tiny) bit slower because an unaligned load is slower than aligned 
- * load.
- */
-#define __ALIGNED__	__attribute__((__aligned__(8)))
-
-/*
- * How much data can firmware send with each hvc_put_chars()?  Maybe this
- * should be moved into an architecture specific area.
- */
-#define HVCS_BUFF_LEN	16
-
-/*
- * This is the maximum amount of data we'll let the user send us (hvcs_write) at
- * once in a chunk as a sanity check.
- */
-#define HVCS_MAX_FROM_USER	4096
-
-/*
- * Be careful when adding flags to this line discipline.  Don't add anything
- * that will cause echoing or we'll go into recursive loop echoing chars back
- * and forth with the console drivers.
- */
-static struct ktermios hvcs_tty_termios = {
-	.c_iflag = IGNBRK | IGNPAR,
-	.c_oflag = OPOST,
-	.c_cflag = B38400 | CS8 | CREAD | HUPCL,
-	.c_cc = INIT_C_CC,
-	.c_ispeed = 38400,
-	.c_ospeed = 38400
-};
-
-/*
- * This value is used to take the place of a command line parameter when the
- * module is inserted.  It starts as -1 and stays as such if the user doesn't
- * specify a module insmod parameter.  If they DO specify one then it is set to
- * the value of the integer passed in.
- */
-static int hvcs_parm_num_devs = -1;
-module_param(hvcs_parm_num_devs, int, 0);
-
-static const char hvcs_driver_name[] = "hvcs";
-static const char hvcs_device_node[] = "hvcs";
-static const char hvcs_driver_string[]
-	= "IBM hvcs (Hypervisor Virtual Console Server) Driver";
-
-/* Status of partner info rescan triggered via sysfs. */
-static int hvcs_rescan_status;
-
-static struct tty_driver *hvcs_tty_driver;
-
-/*
- * In order to be somewhat sane this driver always associates the hvcs_struct
- * index element with the numerically equal tty->index.  This means that a
- * hotplugged vty-server adapter will always map to the lowest index valued
- * device node.  If vty-servers were hotplug removed from the system and then
- * new ones added the new vty-server may have the largest slot number of all
- * the vty-server adapters in the partition but it may have the lowest dev node
- * index of all the adapters due to the hole left by the hotplug removed
- * adapter.  There are a set of functions provided to get the lowest index for
- * a new device as well as return the index to the list.  This list is allocated
- * with a number of elements equal to the number of device nodes requested when
- * the module was inserted.
- */
-static int *hvcs_index_list;
-
-/*
- * How large is the list?  This is kept for traversal since the list is
- * dynamically created.
- */
-static int hvcs_index_count;
-
-/*
- * Used by the khvcsd to pick up I/O operations when the kernel_thread is
- * already awake but potentially shifted to TASK_INTERRUPTIBLE state.
- */
-static int hvcs_kicked;
-
-/*
- * Use by the kthread construct for task operations like waking the sleeping
- * thread and stopping the kthread.
- */
-static struct task_struct *hvcs_task;
-
-/*
- * We allocate this for the use of all of the hvcs_structs when they fetch
- * partner info.
- */
-static unsigned long *hvcs_pi_buff;
-
-/* Only allow one hvcs_struct to use the hvcs_pi_buff at a time. */
-static DEFINE_SPINLOCK(hvcs_pi_lock);
-
-/* One vty-server per hvcs_struct */
-struct hvcs_struct {
-	spinlock_t lock;
-
-	/*
-	 * This index identifies this hvcs device as the complement to a
-	 * specific tty index.
-	 */
-	unsigned int index;
-
-	struct tty_struct *tty;
-	int open_count;
-
-	/*
-	 * Used to tell the driver kernel_thread what operations need to take
-	 * place upon this hvcs_struct instance.
-	 */
-	int todo_mask;
-
-	/*
-	 * This buffer is required so that when hvcs_write_room() reports that
-	 * it can send HVCS_BUFF_LEN characters that it will buffer the full
-	 * HVCS_BUFF_LEN characters if need be.  This is essential for opost
-	 * writes since they do not do high level buffering and expect to be
-	 * able to send what the driver commits to sending buffering
-	 * [e.g. tab to space conversions in n_tty.c opost()].
-	 */
-	char buffer[HVCS_BUFF_LEN];
-	int chars_in_buffer;
-
-	/*
-	 * Any variable below the kref is valid before a tty is connected and
-	 * stays valid after the tty is disconnected.  These shouldn't be
-	 * whacked until the koject refcount reaches zero though some entries
-	 * may be changed via sysfs initiatives.
-	 */
-	struct kref kref; /* ref count & hvcs_struct lifetime */
-	int connected; /* is the vty-server currently connected to a vty? */
-	uint32_t p_unit_address; /* partner unit address */
-	uint32_t p_partition_ID; /* partner partition ID */
-	char p_location_code[HVCS_CLC_LENGTH + 1]; /* CLC + Null Term */
-	struct list_head next; /* list management */
-	struct vio_dev *vdev;
-};
-
-/* Required to back map a kref to its containing object */
-#define from_kref(k) container_of(k, struct hvcs_struct, kref)
-
-static LIST_HEAD(hvcs_structs);
-static DEFINE_SPINLOCK(hvcs_structs_lock);
-
-static void hvcs_unthrottle(struct tty_struct *tty);
-static void hvcs_throttle(struct tty_struct *tty);
-static irqreturn_t hvcs_handle_interrupt(int irq, void *dev_instance);
-
-static int hvcs_write(struct tty_struct *tty,
-		const unsigned char *buf, int count);
-static int hvcs_write_room(struct tty_struct *tty);
-static int hvcs_chars_in_buffer(struct tty_struct *tty);
-
-static int hvcs_has_pi(struct hvcs_struct *hvcsd);
-static void hvcs_set_pi(struct hvcs_partner_info *pi,
-		struct hvcs_struct *hvcsd);
-static int hvcs_get_pi(struct hvcs_struct *hvcsd);
-static int hvcs_rescan_devices_list(void);
-
-static int hvcs_partner_connect(struct hvcs_struct *hvcsd);
-static void hvcs_partner_free(struct hvcs_struct *hvcsd);
-
-static int hvcs_enable_device(struct hvcs_struct *hvcsd,
-		uint32_t unit_address, unsigned int irq, struct vio_dev *dev);
-
-static int hvcs_open(struct tty_struct *tty, struct file *filp);
-static void hvcs_close(struct tty_struct *tty, struct file *filp);
-static void hvcs_hangup(struct tty_struct * tty);
-
-static int __devinit hvcs_probe(struct vio_dev *dev,
-		const struct vio_device_id *id);
-static int __devexit hvcs_remove(struct vio_dev *dev);
-static int __init hvcs_module_init(void);
-static void __exit hvcs_module_exit(void);
-
-#define HVCS_SCHED_READ	0x00000001
-#define HVCS_QUICK_READ	0x00000002
-#define HVCS_TRY_WRITE	0x00000004
-#define HVCS_READ_MASK	(HVCS_SCHED_READ | HVCS_QUICK_READ)
-
-static inline struct hvcs_struct *from_vio_dev(struct vio_dev *viod)
-{
-	return dev_get_drvdata(&viod->dev);
-}
-/* The sysfs interface for the driver and devices */
-
-static ssize_t hvcs_partner_vtys_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
-	struct vio_dev *viod = to_vio_dev(dev);
-	struct hvcs_struct *hvcsd = from_vio_dev(viod);
-	unsigned long flags;
-	int retval;
-
-	spin_lock_irqsave(&hvcsd->lock, flags);
-	retval = sprintf(buf, "%X\n", hvcsd->p_unit_address);
-	spin_unlock_irqrestore(&hvcsd->lock, flags);
-	return retval;
-}
-static DEVICE_ATTR(partner_vtys, S_IRUGO, hvcs_partner_vtys_show, NULL);
-
-static ssize_t hvcs_partner_clcs_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
-	struct vio_dev *viod = to_vio_dev(dev);
-	struct hvcs_struct *hvcsd = from_vio_dev(viod);
-	unsigned long flags;
-	int retval;
-
-	spin_lock_irqsave(&hvcsd->lock, flags);
-	retval = sprintf(buf, "%s\n", &hvcsd->p_location_code[0]);
-	spin_unlock_irqrestore(&hvcsd->lock, flags);
-	return retval;
-}
-static DEVICE_ATTR(partner_clcs, S_IRUGO, hvcs_partner_clcs_show, NULL);
-
-static ssize_t hvcs_current_vty_store(struct device *dev, struct device_attribute *attr, const char * buf,
-		size_t count)
-{
-	/*
-	 * Don't need this feature at the present time because firmware doesn't
-	 * yet support multiple partners.
-	 */
-	printk(KERN_INFO "HVCS: Denied current_vty change: -EPERM.\n");
-	return -EPERM;
-}
-
-static ssize_t hvcs_current_vty_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
-	struct vio_dev *viod = to_vio_dev(dev);
-	struct hvcs_struct *hvcsd = from_vio_dev(viod);
-	unsigned long flags;
-	int retval;
-
-	spin_lock_irqsave(&hvcsd->lock, flags);
-	retval = sprintf(buf, "%s\n", &hvcsd->p_location_code[0]);
-	spin_unlock_irqrestore(&hvcsd->lock, flags);
-	return retval;
-}
-
-static DEVICE_ATTR(current_vty,
-	S_IRUGO | S_IWUSR, hvcs_current_vty_show, hvcs_current_vty_store);
-
-static ssize_t hvcs_vterm_state_store(struct device *dev, struct device_attribute *attr, const char *buf,
-		size_t count)
-{
-	struct vio_dev *viod = to_vio_dev(dev);
-	struct hvcs_struct *hvcsd = from_vio_dev(viod);
-	unsigned long flags;
-
-	/* writing a '0' to this sysfs entry will result in the disconnect. */
-	if (simple_strtol(buf, NULL, 0) != 0)
-		return -EINVAL;
-
-	spin_lock_irqsave(&hvcsd->lock, flags);
-
-	if (hvcsd->open_count > 0) {
-		spin_unlock_irqrestore(&hvcsd->lock, flags);
-		printk(KERN_INFO "HVCS: vterm state unchanged.  "
-				"The hvcs device node is still in use.\n");
-		return -EPERM;
-	}
-
-	if (hvcsd->connected == 0) {
-		spin_unlock_irqrestore(&hvcsd->lock, flags);
-		printk(KERN_INFO "HVCS: vterm state unchanged. The"
-				" vty-server is not connected to a vty.\n");
-		return -EPERM;
-	}
-
-	hvcs_partner_free(hvcsd);
-	printk(KERN_INFO "HVCS: Closed vty-server@%X and"
-			" partner vty@%X:%d connection.\n",
-			hvcsd->vdev->unit_address,
-			hvcsd->p_unit_address,
-			(uint32_t)hvcsd->p_partition_ID);
-
-	spin_unlock_irqrestore(&hvcsd->lock, flags);
-	return count;
-}
-
-static ssize_t hvcs_vterm_state_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
-	struct vio_dev *viod = to_vio_dev(dev);
-	struct hvcs_struct *hvcsd = from_vio_dev(viod);
-	unsigned long flags;
-	int retval;
-
-	spin_lock_irqsave(&hvcsd->lock, flags);
-	retval = sprintf(buf, "%d\n", hvcsd->connected);
-	spin_unlock_irqrestore(&hvcsd->lock, flags);
-	return retval;
-}
-static DEVICE_ATTR(vterm_state, S_IRUGO | S_IWUSR,
-		hvcs_vterm_state_show, hvcs_vterm_state_store);
-
-static ssize_t hvcs_index_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
-	struct vio_dev *viod = to_vio_dev(dev);
-	struct hvcs_struct *hvcsd = from_vio_dev(viod);
-	unsigned long flags;
-	int retval;
-
-	spin_lock_irqsave(&hvcsd->lock, flags);
-	retval = sprintf(buf, "%d\n", hvcsd->index);
-	spin_unlock_irqrestore(&hvcsd->lock, flags);
-	return retval;
-}
-
-static DEVICE_ATTR(index, S_IRUGO, hvcs_index_show, NULL);
-
-static struct attribute *hvcs_attrs[] = {
-	&dev_attr_partner_vtys.attr,
-	&dev_attr_partner_clcs.attr,
-	&dev_attr_current_vty.attr,
-	&dev_attr_vterm_state.attr,
-	&dev_attr_index.attr,
-	NULL,
-};
-
-static struct attribute_group hvcs_attr_group = {
-	.attrs = hvcs_attrs,
-};
-
-static ssize_t hvcs_rescan_show(struct device_driver *ddp, char *buf)
-{
-	/* A 1 means it is updating, a 0 means it is done updating */
-	return snprintf(buf, PAGE_SIZE, "%d\n", hvcs_rescan_status);
-}
-
-static ssize_t hvcs_rescan_store(struct device_driver *ddp, const char * buf,
-		size_t count)
-{
-	if ((simple_strtol(buf, NULL, 0) != 1)
-		&& (hvcs_rescan_status != 0))
-		return -EINVAL;
-
-	hvcs_rescan_status = 1;
-	printk(KERN_INFO "HVCS: rescanning partner info for all"
-		" vty-servers.\n");
-	hvcs_rescan_devices_list();
-	hvcs_rescan_status = 0;
-	return count;
-}
-
-static DRIVER_ATTR(rescan,
-	S_IRUGO | S_IWUSR, hvcs_rescan_show, hvcs_rescan_store);
-
-static void hvcs_kick(void)
-{
-	hvcs_kicked = 1;
-	wmb();
-	wake_up_process(hvcs_task);
-}
-
-static void hvcs_unthrottle(struct tty_struct *tty)
-{
-	struct hvcs_struct *hvcsd = tty->driver_data;
-	unsigned long flags;
-
-	spin_lock_irqsave(&hvcsd->lock, flags);
-	hvcsd->todo_mask |= HVCS_SCHED_READ;
-	spin_unlock_irqrestore(&hvcsd->lock, flags);
-	hvcs_kick();
-}
-
-static void hvcs_throttle(struct tty_struct *tty)
-{
-	struct hvcs_struct *hvcsd = tty->driver_data;
-	unsigned long flags;
-
-	spin_lock_irqsave(&hvcsd->lock, flags);
-	vio_disable_interrupts(hvcsd->vdev);
-	spin_unlock_irqrestore(&hvcsd->lock, flags);
-}
-
-/*
- * If the device is being removed we don't have to worry about this interrupt
- * handler taking any further interrupts because they are disabled which means
- * the hvcs_struct will always be valid in this handler.
- */
-static irqreturn_t hvcs_handle_interrupt(int irq, void *dev_instance)
-{
-	struct hvcs_struct *hvcsd = dev_instance;
-
-	spin_lock(&hvcsd->lock);
-	vio_disable_interrupts(hvcsd->vdev);
-	hvcsd->todo_mask |= HVCS_SCHED_READ;
-	spin_unlock(&hvcsd->lock);
-	hvcs_kick();
-
-	return IRQ_HANDLED;
-}
-
-/* This function must be called with the hvcsd->lock held */
-static void hvcs_try_write(struct hvcs_struct *hvcsd)
-{
-	uint32_t unit_address = hvcsd->vdev->unit_address;
-	struct tty_struct *tty = hvcsd->tty;
-	int sent;
-
-	if (hvcsd->todo_mask & HVCS_TRY_WRITE) {
-		/* won't send partial writes */
-		sent = hvc_put_chars(unit_address,
-				&hvcsd->buffer[0],
-				hvcsd->chars_in_buffer );
-		if (sent > 0) {
-			hvcsd->chars_in_buffer = 0;
-			/* wmb(); */
-			hvcsd->todo_mask &= ~(HVCS_TRY_WRITE);
-			/* wmb(); */
-
-			/*
-			 * We are still obligated to deliver the data to the
-			 * hypervisor even if the tty has been closed because
-			 * we commited to delivering it.  But don't try to wake
-			 * a non-existent tty.
-			 */
-			if (tty) {
-				tty_wakeup(tty);
-			}
-		}
-	}
-}
-
-static int hvcs_io(struct hvcs_struct *hvcsd)
-{
-	uint32_t unit_address;
-	struct tty_struct *tty;
-	char buf[HVCS_BUFF_LEN] __ALIGNED__;
-	unsigned long flags;
-	int got = 0;
-
-	spin_lock_irqsave(&hvcsd->lock, flags);
-
-	unit_address = hvcsd->vdev->unit_address;
-	tty = hvcsd->tty;
-
-	hvcs_try_write(hvcsd);
-
-	if (!tty || test_bit(TTY_THROTTLED, &tty->flags)) {
-		hvcsd->todo_mask &= ~(HVCS_READ_MASK);
-		goto bail;
-	} else if (!(hvcsd->todo_mask & (HVCS_READ_MASK)))
-		goto bail;
-
-	/* remove the read masks */
-	hvcsd->todo_mask &= ~(HVCS_READ_MASK);
-
-	if (tty_buffer_request_room(tty, HVCS_BUFF_LEN) >= HVCS_BUFF_LEN) {
-		got = hvc_get_chars(unit_address,
-				&buf[0],
-				HVCS_BUFF_LEN);
-		tty_insert_flip_string(tty, buf, got);
-	}
-
-	/* Give the TTY time to process the data we just sent. */
-	if (got)
-		hvcsd->todo_mask |= HVCS_QUICK_READ;
-
-	spin_unlock_irqrestore(&hvcsd->lock, flags);
-	/* This is synch because tty->low_latency == 1 */
-	if(got)
-		tty_flip_buffer_push(tty);
-
-	if (!got) {
-		/* Do this _after_ the flip_buffer_push */
-		spin_lock_irqsave(&hvcsd->lock, flags);
-		vio_enable_interrupts(hvcsd->vdev);
-		spin_unlock_irqrestore(&hvcsd->lock, flags);
-	}
-
-	return hvcsd->todo_mask;
-
- bail:
-	spin_unlock_irqrestore(&hvcsd->lock, flags);
-	return hvcsd->todo_mask;
-}
-
-static int khvcsd(void *unused)
-{
-	struct hvcs_struct *hvcsd;
-	int hvcs_todo_mask;
-
-	__set_current_state(TASK_RUNNING);
-
-	do {
-		hvcs_todo_mask = 0;
-		hvcs_kicked = 0;
-		wmb();
-
-		spin_lock(&hvcs_structs_lock);
-		list_for_each_entry(hvcsd, &hvcs_structs, next) {
-			hvcs_todo_mask |= hvcs_io(hvcsd);
-		}
-		spin_unlock(&hvcs_structs_lock);
-
-		/*
-		 * If any of the hvcs adapters want to try a write or quick read
-		 * don't schedule(), yield a smidgen then execute the hvcs_io
-		 * thread again for those that want the write.
-		 */
-		 if (hvcs_todo_mask & (HVCS_TRY_WRITE | HVCS_QUICK_READ)) {
-			yield();
-			continue;
-		}
-
-		set_current_state(TASK_INTERRUPTIBLE);
-		if (!hvcs_kicked)
-			schedule();
-		__set_current_state(TASK_RUNNING);
-	} while (!kthread_should_stop());
-
-	return 0;
-}
-
-static struct vio_device_id hvcs_driver_table[] __devinitdata= {
-	{"serial-server", "hvterm2"},
-	{ "", "" }
-};
-MODULE_DEVICE_TABLE(vio, hvcs_driver_table);
-
-static void hvcs_return_index(int index)
-{
-	/* Paranoia check */
-	if (!hvcs_index_list)
-		return;
-	if (index < 0 || index >= hvcs_index_count)
-		return;
-	if (hvcs_index_list[index] == -1)
-		return;
-	else
-		hvcs_index_list[index] = -1;
-}
-
-/* callback when the kref ref count reaches zero */
-static void destroy_hvcs_struct(struct kref *kref)
-{
-	struct hvcs_struct *hvcsd = from_kref(kref);
-	struct vio_dev *vdev;
-	unsigned long flags;
-
-	spin_lock(&hvcs_structs_lock);
-	spin_lock_irqsave(&hvcsd->lock, flags);
-
-	/* the list_del poisons the pointers */
-	list_del(&(hvcsd->next));
-
-	if (hvcsd->connected == 1) {
-		hvcs_partner_free(hvcsd);
-		printk(KERN_INFO "HVCS: Closed vty-server@%X and"
-				" partner vty@%X:%d connection.\n",
-				hvcsd->vdev->unit_address,
-				hvcsd->p_unit_address,
-				(uint32_t)hvcsd->p_partition_ID);
-	}
-	printk(KERN_INFO "HVCS: Destroyed hvcs_struct for vty-server@%X.\n",
-			hvcsd->vdev->unit_address);
-
-	vdev = hvcsd->vdev;
-	hvcsd->vdev = NULL;
-
-	hvcsd->p_unit_address = 0;
-	hvcsd->p_partition_ID = 0;
-	hvcs_return_index(hvcsd->index);
-	memset(&hvcsd->p_location_code[0], 0x00, HVCS_CLC_LENGTH + 1);
-
-	spin_unlock_irqrestore(&hvcsd->lock, flags);
-	spin_unlock(&hvcs_structs_lock);
-
-	sysfs_remove_group(&vdev->dev.kobj, &hvcs_attr_group);
-
-	kfree(hvcsd);
-}
-
-static int hvcs_get_index(void)
-{
-	int i;
-	/* Paranoia check */
-	if (!hvcs_index_list) {
-		printk(KERN_ERR "HVCS: hvcs_index_list NOT valid!.\n");
-		return -EFAULT;
-	}
-	/* Find the numerically lowest first free index. */
-	for(i = 0; i < hvcs_index_count; i++) {
-		if (hvcs_index_list[i] == -1) {
-			hvcs_index_list[i] = 0;
-			return i;
-		}
-	}
-	return -1;
-}
-
-static int __devinit hvcs_probe(
-	struct vio_dev *dev,
-	const struct vio_device_id *id)
-{
-	struct hvcs_struct *hvcsd;
-	int index;
-	int retval;
-
-	if (!dev || !id) {
-		printk(KERN_ERR "HVCS: probed with invalid parameter.\n");
-		return -EPERM;
-	}
-
-	/* early to avoid cleanup on failure */
-	index = hvcs_get_index();
-	if (index < 0) {
-		return -EFAULT;
-	}
-
-	hvcsd = kzalloc(sizeof(*hvcsd), GFP_KERNEL);
-	if (!hvcsd)
-		return -ENODEV;
-
-
-	spin_lock_init(&hvcsd->lock);
-	/* Automatically incs the refcount the first time */
-	kref_init(&hvcsd->kref);
-
-	hvcsd->vdev = dev;
-	dev_set_drvdata(&dev->dev, hvcsd);
-
-	hvcsd->index = index;
-
-	/* hvcsd->index = ++hvcs_struct_count; */
-	hvcsd->chars_in_buffer = 0;
-	hvcsd->todo_mask = 0;
-	hvcsd->connected = 0;
-
-	/*
-	 * This will populate the hvcs_struct's partner info fields for the
-	 * first time.
-	 */
-	if (hvcs_get_pi(hvcsd)) {
-		printk(KERN_ERR "HVCS: Failed to fetch partner"
-			" info for vty-server@%X on device probe.\n",
-			hvcsd->vdev->unit_address);
-	}
-
-	/*
-	 * If a user app opens a tty that corresponds to this vty-server before
-	 * the hvcs_struct has been added to the devices list then the user app
-	 * will get -ENODEV.
-	 */
-	spin_lock(&hvcs_structs_lock);
-	list_add_tail(&(hvcsd->next), &hvcs_structs);
-	spin_unlock(&hvcs_structs_lock);
-
-	retval = sysfs_create_group(&dev->dev.kobj, &hvcs_attr_group);
-	if (retval) {
-		printk(KERN_ERR "HVCS: Can't create sysfs attrs for vty-server@%X\n",
-		       hvcsd->vdev->unit_address);
-		return retval;
-	}
-
-	printk(KERN_INFO "HVCS: vty-server@%X added to the vio bus.\n", dev->unit_address);
-
-	/*
-	 * DON'T enable interrupts here because there is no user to receive the
-	 * data.
-	 */
-	return 0;
-}
-
-static int __devexit hvcs_remove(struct vio_dev *dev)
-{
-	struct hvcs_struct *hvcsd = dev_get_drvdata(&dev->dev);
-	unsigned long flags;
-	struct tty_struct *tty;
-
-	if (!hvcsd)
-		return -ENODEV;
-
-	/* By this time the vty-server won't be getting any more interrupts */
-
-	spin_lock_irqsave(&hvcsd->lock, flags);
-
-	tty = hvcsd->tty;
-
-	spin_unlock_irqrestore(&hvcsd->lock, flags);
-
-	/*
-	 * Let the last holder of this object cause it to be removed, which
-	 * would probably be tty_hangup below.
-	 */
-	kref_put(&hvcsd->kref, destroy_hvcs_struct);
-
-	/*
-	 * The hangup is a scheduled function which will auto chain call
-	 * hvcs_hangup.  The tty should always be valid at this time unless a
-	 * simultaneous tty close already cleaned up the hvcs_struct.
-	 */
-	if (tty)
-		tty_hangup(tty);
-
-	printk(KERN_INFO "HVCS: vty-server@%X removed from the"
-			" vio bus.\n", dev->unit_address);
-	return 0;
-};
-
-static struct vio_driver hvcs_vio_driver = {
-	.id_table	= hvcs_driver_table,
-	.probe		= hvcs_probe,
-	.remove		= __devexit_p(hvcs_remove),
-	.driver		= {
-		.name	= hvcs_driver_name,
-		.owner	= THIS_MODULE,
-	}
-};
-
-/* Only called from hvcs_get_pi please */
-static void hvcs_set_pi(struct hvcs_partner_info *pi, struct hvcs_struct *hvcsd)
-{
-	int clclength;
-
-	hvcsd->p_unit_address = pi->unit_address;
-	hvcsd->p_partition_ID  = pi->partition_ID;
-	clclength = strlen(&pi->location_code[0]);
-	if (clclength > HVCS_CLC_LENGTH)
-		clclength = HVCS_CLC_LENGTH;
-
-	/* copy the null-term char too */
-	strncpy(&hvcsd->p_location_code[0],
-			&pi->location_code[0], clclength + 1);
-}
-
-/*
- * Traverse the list and add the partner info that is found to the hvcs_struct
- * struct entry. NOTE: At this time I know that partner info will return a
- * single entry but in the future there may be multiple partner info entries per
- * vty-server and you'll want to zero out that list and reset it.  If for some
- * reason you have an old version of this driver but there IS more than one
- * partner info then hvcsd->p_* will hold the last partner info data from the
- * firmware query.  A good way to update this code would be to replace the three
- * partner info fields in hvcs_struct with a list of hvcs_partner_info
- * instances.
- *
- * This function must be called with the hvcsd->lock held.
- */
-static int hvcs_get_pi(struct hvcs_struct *hvcsd)
-{
-	struct hvcs_partner_info *pi;
-	uint32_t unit_address = hvcsd->vdev->unit_address;
-	struct list_head head;
-	int retval;
-
-	spin_lock(&hvcs_pi_lock);
-	if (!hvcs_pi_buff) {
-		spin_unlock(&hvcs_pi_lock);
-		return -EFAULT;
-	}
-	retval = hvcs_get_partner_info(unit_address, &head, hvcs_pi_buff);
-	spin_unlock(&hvcs_pi_lock);
-	if (retval) {
-		printk(KERN_ERR "HVCS: Failed to fetch partner"
-			" info for vty-server@%x.\n", unit_address);
-		return retval;
-	}
-
-	/* nixes the values if the partner vty went away */
-	hvcsd->p_unit_address = 0;
-	hvcsd->p_partition_ID = 0;
-
-	list_for_each_entry(pi, &head, node)
-		hvcs_set_pi(pi, hvcsd);
-
-	hvcs_free_partner_info(&head);
-	return 0;
-}
-
-/*
- * This function is executed by the driver "rescan" sysfs entry.  It shouldn't
- * be executed elsewhere, in order to prevent deadlock issues.
- */
-static int hvcs_rescan_devices_list(void)
-{
-	struct hvcs_struct *hvcsd;
-	unsigned long flags;
-
-	spin_lock(&hvcs_structs_lock);
-
-	list_for_each_entry(hvcsd, &hvcs_structs, next) {
-		spin_lock_irqsave(&hvcsd->lock, flags);
-		hvcs_get_pi(hvcsd);
-		spin_unlock_irqrestore(&hvcsd->lock, flags);
-	}
-
-	spin_unlock(&hvcs_structs_lock);
-
-	return 0;
-}
-
-/*
- * Farm this off into its own function because it could be more complex once
- * multiple partners support is added. This function should be called with
- * the hvcsd->lock held.
- */
-static int hvcs_has_pi(struct hvcs_struct *hvcsd)
-{
-	if ((!hvcsd->p_unit_address) || (!hvcsd->p_partition_ID))
-		return 0;
-	return 1;
-}
-
-/*
- * NOTE: It is possible that the super admin removed a partner vty and then
- * added a different vty as the new partner.
- *
- * This function must be called with the hvcsd->lock held.
- */
-static int hvcs_partner_connect(struct hvcs_struct *hvcsd)
-{
-	int retval;
-	unsigned int unit_address = hvcsd->vdev->unit_address;
-
-	/*
-	 * If there wasn't any pi when the device was added it doesn't meant
-	 * there isn't any now.  This driver isn't notified when a new partner
-	 * vty is added to a vty-server so we discover changes on our own.
-	 * Please see comments in hvcs_register_connection() for justification
-	 * of this bizarre code.
-	 */
-	retval = hvcs_register_connection(unit_address,
-			hvcsd->p_partition_ID,
-			hvcsd->p_unit_address);
-	if (!retval) {
-		hvcsd->connected = 1;
-		return 0;
-	} else if (retval != -EINVAL)
-		return retval;
-
-	/*
-	 * As per the spec re-get the pi and try again if -EINVAL after the
-	 * first connection attempt.
-	 */
-	if (hvcs_get_pi(hvcsd))
-		return -ENOMEM;
-
-	if (!hvcs_has_pi(hvcsd))
-		return -ENODEV;
-
-	retval = hvcs_register_connection(unit_address,
-			hvcsd->p_partition_ID,
-			hvcsd->p_unit_address);
-	if (retval != -EINVAL) {
-		hvcsd->connected = 1;
-		return retval;
-	}
-
-	/*
-	 * EBUSY is the most likely scenario though the vty could have been
-	 * removed or there really could be an hcall error due to the parameter
-	 * data but thanks to ambiguous firmware return codes we can't really
-	 * tell.
-	 */
-	printk(KERN_INFO "HVCS: vty-server or partner"
-			" vty is busy.  Try again later.\n");
-	return -EBUSY;
-}
-
-/* This function must be called with the hvcsd->lock held */
-static void hvcs_partner_free(struct hvcs_struct *hvcsd)
-{
-	int retval;
-	do {
-		retval = hvcs_free_connection(hvcsd->vdev->unit_address);
-	} while (retval == -EBUSY);
-	hvcsd->connected = 0;
-}
-
-/* This helper function must be called WITHOUT the hvcsd->lock held */
-static int hvcs_enable_device(struct hvcs_struct *hvcsd, uint32_t unit_address,
-		unsigned int irq, struct vio_dev *vdev)
-{
-	unsigned long flags;
-	int rc;
-
-	/*
-	 * It is possible that the vty-server was removed between the time that
-	 * the conn was registered and now.
-	 */
-	if (!(rc = request_irq(irq, &hvcs_handle_interrupt,
-				IRQF_DISABLED, "ibmhvcs", hvcsd))) {
-		/*
-		 * It is possible the vty-server was removed after the irq was
-		 * requested but before we have time to enable interrupts.
-		 */
-		if (vio_enable_interrupts(vdev) == H_SUCCESS)
-			return 0;
-		else {
-			printk(KERN_ERR "HVCS: int enable failed for"
-					" vty-server@%X.\n", unit_address);
-			free_irq(irq, hvcsd);
-		}
-	} else
-		printk(KERN_ERR "HVCS: irq req failed for"
-				" vty-server@%X.\n", unit_address);
-
-	spin_lock_irqsave(&hvcsd->lock, flags);
-	hvcs_partner_free(hvcsd);
-	spin_unlock_irqrestore(&hvcsd->lock, flags);
-
-	return rc;
-
-}
-
-/*
- * This always increments the kref ref count if the call is successful.
- * Please remember to dec when you are done with the instance.
- *
- * NOTICE: Do NOT hold either the hvcs_struct.lock or hvcs_structs_lock when
- * calling this function or you will get deadlock.
- */
-static struct hvcs_struct *hvcs_get_by_index(int index)
-{
-	struct hvcs_struct *hvcsd = NULL;
-	unsigned long flags;
-
-	spin_lock(&hvcs_structs_lock);
-	/* We can immediately discard OOB requests */
-	if (index >= 0 && index < HVCS_MAX_SERVER_ADAPTERS) {
-		list_for_each_entry(hvcsd, &hvcs_structs, next) {
-			spin_lock_irqsave(&hvcsd->lock, flags);
-			if (hvcsd->index == index) {
-				kref_get(&hvcsd->kref);
-				spin_unlock_irqrestore(&hvcsd->lock, flags);
-				spin_unlock(&hvcs_structs_lock);
-				return hvcsd;
-			}
-			spin_unlock_irqrestore(&hvcsd->lock, flags);
-		}
-		hvcsd = NULL;
-	}
-
-	spin_unlock(&hvcs_structs_lock);
-	return hvcsd;
-}
-
-/*
- * This is invoked via the tty_open interface when a user app connects to the
- * /dev node.
- */
-static int hvcs_open(struct tty_struct *tty, struct file *filp)
-{
-	struct hvcs_struct *hvcsd;
-	int rc, retval = 0;
-	unsigned long flags;
-	unsigned int irq;
-	struct vio_dev *vdev;
-	unsigned long unit_address;
-
-	if (tty->driver_data)
-		goto fast_open;
-
-	/*
-	 * Is there a vty-server that shares the same index?
-	 * This function increments the kref index.
-	 */
-	if (!(hvcsd = hvcs_get_by_index(tty->index))) {
-		printk(KERN_WARNING "HVCS: open failed, no device associated"
-				" with tty->index %d.\n", tty->index);
-		return -ENODEV;
-	}
-
-	spin_lock_irqsave(&hvcsd->lock, flags);
-
-	if (hvcsd->connected == 0)
-		if ((retval = hvcs_partner_connect(hvcsd)))
-			goto error_release;
-
-	hvcsd->open_count = 1;
-	hvcsd->tty = tty;
-	tty->driver_data = hvcsd;
-
-	memset(&hvcsd->buffer[0], 0x00, HVCS_BUFF_LEN);
-
-	/*
-	 * Save these in the spinlock for the enable operations that need them
-	 * outside of the spinlock.
-	 */
-	irq = hvcsd->vdev->irq;
-	vdev = hvcsd->vdev;
-	unit_address = hvcsd->vdev->unit_address;
-
-	hvcsd->todo_mask |= HVCS_SCHED_READ;
-	spin_unlock_irqrestore(&hvcsd->lock, flags);
-
-	/*
-	 * This must be done outside of the spinlock because it requests irqs
-	 * and will grab the spinlock and free the connection if it fails.
-	 */
-	if (((rc = hvcs_enable_device(hvcsd, unit_address, irq, vdev)))) {
-		kref_put(&hvcsd->kref, destroy_hvcs_struct);
-		printk(KERN_WARNING "HVCS: enable device failed.\n");
-		return rc;
-	}
-
-	goto open_success;
-
-fast_open:
-	hvcsd = tty->driver_data;
-
-	spin_lock_irqsave(&hvcsd->lock, flags);
-	kref_get(&hvcsd->kref);
-	hvcsd->open_count++;
-	hvcsd->todo_mask |= HVCS_SCHED_READ;
-	spin_unlock_irqrestore(&hvcsd->lock, flags);
-
-open_success:
-	hvcs_kick();
-
-	printk(KERN_INFO "HVCS: vty-server@%X connection opened.\n",
-		hvcsd->vdev->unit_address );
-
-	return 0;
-
-error_release:
-	spin_unlock_irqrestore(&hvcsd->lock, flags);
-	kref_put(&hvcsd->kref, destroy_hvcs_struct);
-
-	printk(KERN_WARNING "HVCS: partner connect failed.\n");
-	return retval;
-}
-
-static void hvcs_close(struct tty_struct *tty, struct file *filp)
-{
-	struct hvcs_struct *hvcsd;
-	unsigned long flags;
-	int irq = NO_IRQ;
-
-	/*
-	 * Is someone trying to close the file associated with this device after
-	 * we have hung up?  If so tty->driver_data wouldn't be valid.
-	 */
-	if (tty_hung_up_p(filp))
-		return;
-
-	/*
-	 * No driver_data means that this close was probably issued after a
-	 * failed hvcs_open by the tty layer's release_dev() api and we can just
-	 * exit cleanly.
-	 */
-	if (!tty->driver_data)
-		return;
-
-	hvcsd = tty->driver_data;
-
-	spin_lock_irqsave(&hvcsd->lock, flags);
-	if (--hvcsd->open_count == 0) {
-
-		vio_disable_interrupts(hvcsd->vdev);
-
-		/*
-		 * NULL this early so that the kernel_thread doesn't try to
-		 * execute any operations on the TTY even though it is obligated
-		 * to deliver any pending I/O to the hypervisor.
-		 */
-		hvcsd->tty = NULL;
-
-		irq = hvcsd->vdev->irq;
-		spin_unlock_irqrestore(&hvcsd->lock, flags);
-
-		tty_wait_until_sent(tty, HVCS_CLOSE_WAIT);
-
-		/*
-		 * This line is important because it tells hvcs_open that this
-		 * device needs to be re-configured the next time hvcs_open is
-		 * called.
-		 */
-		tty->driver_data = NULL;
-
-		free_irq(irq, hvcsd);
-		kref_put(&hvcsd->kref, destroy_hvcs_struct);
-		return;
-	} else if (hvcsd->open_count < 0) {
-		printk(KERN_ERR "HVCS: vty-server@%X open_count: %d"
-				" is missmanaged.\n",
-		hvcsd->vdev->unit_address, hvcsd->open_count);
-	}
-
-	spin_unlock_irqrestore(&hvcsd->lock, flags);
-	kref_put(&hvcsd->kref, destroy_hvcs_struct);
-}
-
-static void hvcs_hangup(struct tty_struct * tty)
-{
-	struct hvcs_struct *hvcsd = tty->driver_data;
-	unsigned long flags;
-	int temp_open_count;
-	int irq = NO_IRQ;
-
-	spin_lock_irqsave(&hvcsd->lock, flags);
-	/* Preserve this so that we know how many kref refs to put */
-	temp_open_count = hvcsd->open_count;
-
-	/*
-	 * Don't kref put inside the spinlock because the destruction
-	 * callback may use the spinlock and it may get called before the
-	 * spinlock has been released.
-	 */
-	vio_disable_interrupts(hvcsd->vdev);
-
-	hvcsd->todo_mask = 0;
-
-	/* I don't think the tty needs the hvcs_struct pointer after a hangup */
-	hvcsd->tty->driver_data = NULL;
-	hvcsd->tty = NULL;
-
-	hvcsd->open_count = 0;
-
-	/* This will drop any buffered data on the floor which is OK in a hangup
-	 * scenario. */
-	memset(&hvcsd->buffer[0], 0x00, HVCS_BUFF_LEN);
-	hvcsd->chars_in_buffer = 0;
-
-	irq = hvcsd->vdev->irq;
-
-	spin_unlock_irqrestore(&hvcsd->lock, flags);
-
-	free_irq(irq, hvcsd);
-
-	/*
-	 * We need to kref_put() for every open_count we have since the
-	 * tty_hangup() function doesn't invoke a close per open connection on a
-	 * non-console device.
-	 */
-	while(temp_open_count) {
-		--temp_open_count;
-		/*
-		 * The final put will trigger destruction of the hvcs_struct.
-		 * NOTE:  If this hangup was signaled from user space then the
-		 * final put will never happen.
-		 */
-		kref_put(&hvcsd->kref, destroy_hvcs_struct);
-	}
-}
-
-/*
- * NOTE: This is almost always from_user since user level apps interact with the
- * /dev nodes. I'm trusting that if hvcs_write gets called and interrupted by
- * hvcs_remove (which removes the target device and executes tty_hangup()) that
- * tty_hangup will allow hvcs_write time to complete execution before it
- * terminates our device.
- */
-static int hvcs_write(struct tty_struct *tty,
-		const unsigned char *buf, int count)
-{
-	struct hvcs_struct *hvcsd = tty->driver_data;
-	unsigned int unit_address;
-	const unsigned char *charbuf;
-	unsigned long flags;
-	int total_sent = 0;
-	int tosend = 0;
-	int result = 0;
-
-	/*
-	 * If they don't check the return code off of their open they may
-	 * attempt this even if there is no connected device.
-	 */
-	if (!hvcsd)
-		return -ENODEV;
-
-	/* Reasonable size to prevent user level flooding */
-	if (count > HVCS_MAX_FROM_USER) {
-		printk(KERN_WARNING "HVCS write: count being truncated to"
-				" HVCS_MAX_FROM_USER.\n");
-		count = HVCS_MAX_FROM_USER;
-	}
-
-	charbuf = buf;
-
-	spin_lock_irqsave(&hvcsd->lock, flags);
-
-	/*
-	 * Somehow an open succedded but the device was removed or the
-	 * connection terminated between the vty-server and partner vty during
-	 * the middle of a write operation?  This is a crummy place to do this
-	 * but we want to keep it all in the spinlock.
-	 */
-	if (hvcsd->open_count <= 0) {
-		spin_unlock_irqrestore(&hvcsd->lock, flags);
-		return -ENODEV;
-	}
-
-	unit_address = hvcsd->vdev->unit_address;
-
-	while (count > 0) {
-		tosend = min(count, (HVCS_BUFF_LEN - hvcsd->chars_in_buffer));
-		/*
-		 * No more space, this probably means that the last call to
-		 * hvcs_write() didn't succeed and the buffer was filled up.
-		 */
-		if (!tosend)
-			break;
-
-		memcpy(&hvcsd->buffer[hvcsd->chars_in_buffer],
-				&charbuf[total_sent],
-				tosend);
-
-		hvcsd->chars_in_buffer += tosend;
-
-		result = 0;
-
-		/*
-		 * If this is true then we don't want to try writing to the
-		 * hypervisor because that is the kernel_threads job now.  We'll
-		 * just add to the buffer.
-		 */
-		if (!(hvcsd->todo_mask & HVCS_TRY_WRITE))
-			/* won't send partial writes */
-			result = hvc_put_chars(unit_address,
-					&hvcsd->buffer[0],
-					hvcsd->chars_in_buffer);
-
-		/*
-		 * Since we know we have enough room in hvcsd->buffer for
-		 * tosend we record that it was sent regardless of whether the
-		 * hypervisor actually took it because we have it buffered.
-		 */
-		total_sent+=tosend;
-		count-=tosend;
-		if (result == 0) {
-			hvcsd->todo_mask |= HVCS_TRY_WRITE;
-			hvcs_kick();
-			break;
-		}
-
-		hvcsd->chars_in_buffer = 0;
-		/*
-		 * Test after the chars_in_buffer reset otherwise this could
-		 * deadlock our writes if hvc_put_chars fails.
-		 */
-		if (result < 0)
-			break;
-	}
-
-	spin_unlock_irqrestore(&hvcsd->lock, flags);
-
-	if (result == -1)
-		return -EIO;
-	else
-		return total_sent;
-}
-
-/*
- * This is really asking how much can we guarentee that we can send or that we
- * absolutely WILL BUFFER if we can't send it.  This driver MUST honor the
- * return value, hence the reason for hvcs_struct buffering.
- */
-static int hvcs_write_room(struct tty_struct *tty)
-{
-	struct hvcs_struct *hvcsd = tty->driver_data;
-
-	if (!hvcsd || hvcsd->open_count <= 0)
-		return 0;
-
-	return HVCS_BUFF_LEN - hvcsd->chars_in_buffer;
-}
-
-static int hvcs_chars_in_buffer(struct tty_struct *tty)
-{
-	struct hvcs_struct *hvcsd = tty->driver_data;
-
-	return hvcsd->chars_in_buffer;
-}
-
-static const struct tty_operations hvcs_ops = {
-	.open = hvcs_open,
-	.close = hvcs_close,
-	.hangup = hvcs_hangup,
-	.write = hvcs_write,
-	.write_room = hvcs_write_room,
-	.chars_in_buffer = hvcs_chars_in_buffer,
-	.unthrottle = hvcs_unthrottle,
-	.throttle = hvcs_throttle,
-};
-
-static int hvcs_alloc_index_list(int n)
-{
-	int i;
-
-	hvcs_index_list = kmalloc(n * sizeof(hvcs_index_count),GFP_KERNEL);
-	if (!hvcs_index_list)
-		return -ENOMEM;
-	hvcs_index_count = n;
-	for (i = 0; i < hvcs_index_count; i++)
-		hvcs_index_list[i] = -1;
-	return 0;
-}
-
-static void hvcs_free_index_list(void)
-{
-	/* Paranoia check to be thorough. */
-	kfree(hvcs_index_list);
-	hvcs_index_list = NULL;
-	hvcs_index_count = 0;
-}
-
-static int __init hvcs_module_init(void)
-{
-	int rc;
-	int num_ttys_to_alloc;
-
-	printk(KERN_INFO "Initializing %s\n", hvcs_driver_string);
-
-	/* Has the user specified an overload with an insmod param? */
-	if (hvcs_parm_num_devs <= 0 ||
-		(hvcs_parm_num_devs > HVCS_MAX_SERVER_ADAPTERS)) {
-		num_ttys_to_alloc = HVCS_DEFAULT_SERVER_ADAPTERS;
-	} else
-		num_ttys_to_alloc = hvcs_parm_num_devs;
-
-	hvcs_tty_driver = alloc_tty_driver(num_ttys_to_alloc);
-	if (!hvcs_tty_driver)
-		return -ENOMEM;
-
-	if (hvcs_alloc_index_list(num_ttys_to_alloc)) {
-		rc = -ENOMEM;
-		goto index_fail;
-	}
-
-	hvcs_tty_driver->owner = THIS_MODULE;
-
-	hvcs_tty_driver->driver_name = hvcs_driver_name;
-	hvcs_tty_driver->name = hvcs_device_node;
-
-	/*
-	 * We'll let the system assign us a major number, indicated by leaving
-	 * it blank.
-	 */
-
-	hvcs_tty_driver->minor_start = HVCS_MINOR_START;
-	hvcs_tty_driver->type = TTY_DRIVER_TYPE_SYSTEM;
-
-	/*
-	 * We role our own so that we DONT ECHO.  We can't echo because the
-	 * device we are connecting to already echoes by default and this would
-	 * throw us into a horrible recursive echo-echo-echo loop.
-	 */
-	hvcs_tty_driver->init_termios = hvcs_tty_termios;
-	hvcs_tty_driver->flags = TTY_DRIVER_REAL_RAW;
-
-	tty_set_operations(hvcs_tty_driver, &hvcs_ops);
-
-	/*
-	 * The following call will result in sysfs entries that denote the
-	 * dynamically assigned major and minor numbers for our devices.
-	 */
-	if (tty_register_driver(hvcs_tty_driver)) {
-		printk(KERN_ERR "HVCS: registration as a tty driver failed.\n");
-		rc = -EIO;
-		goto register_fail;
-	}
-
-	hvcs_pi_buff = kmalloc(PAGE_SIZE, GFP_KERNEL);
-	if (!hvcs_pi_buff) {
-		rc = -ENOMEM;
-		goto buff_alloc_fail;
-	}
-
-	hvcs_task = kthread_run(khvcsd, NULL, "khvcsd");
-	if (IS_ERR(hvcs_task)) {
-		printk(KERN_ERR "HVCS: khvcsd creation failed.  Driver not loaded.\n");
-		rc = -EIO;
-		goto kthread_fail;
-	}
-
-	rc = vio_register_driver(&hvcs_vio_driver);
-	if (rc) {
-		printk(KERN_ERR "HVCS: can't register vio driver\n");
-		goto vio_fail;
-	}
-
-	/*
-	 * This needs to be done AFTER the vio_register_driver() call or else
-	 * the kobjects won't be initialized properly.
-	 */
-	rc = driver_create_file(&(hvcs_vio_driver.driver), &driver_attr_rescan);
-	if (rc) {
-		printk(KERN_ERR "HVCS: sysfs attr create failed\n");
-		goto attr_fail;
-	}
-
-	printk(KERN_INFO "HVCS: driver module inserted.\n");
-
-	return 0;
-
-attr_fail:
-	vio_unregister_driver(&hvcs_vio_driver);
-vio_fail:
-	kthread_stop(hvcs_task);
-kthread_fail:
-	kfree(hvcs_pi_buff);
-buff_alloc_fail:
-	tty_unregister_driver(hvcs_tty_driver);
-register_fail:
-	hvcs_free_index_list();
-index_fail:
-	put_tty_driver(hvcs_tty_driver);
-	hvcs_tty_driver = NULL;
-	return rc;
-}
-
-static void __exit hvcs_module_exit(void)
-{
-	/*
-	 * This driver receives hvcs_remove callbacks for each device upon
-	 * module removal.
-	 */
-
-	/*
-	 * This synchronous operation  will wake the khvcsd kthread if it is
-	 * asleep and will return when khvcsd has terminated.
-	 */
-	kthread_stop(hvcs_task);
-
-	spin_lock(&hvcs_pi_lock);
-	kfree(hvcs_pi_buff);
-	hvcs_pi_buff = NULL;
-	spin_unlock(&hvcs_pi_lock);
-
-	driver_remove_file(&hvcs_vio_driver.driver, &driver_attr_rescan);
-
-	vio_unregister_driver(&hvcs_vio_driver);
-
-	tty_unregister_driver(hvcs_tty_driver);
-
-	hvcs_free_index_list();
-
-	put_tty_driver(hvcs_tty_driver);
-
-	printk(KERN_INFO "HVCS: driver module removed.\n");
-}
-
-module_init(hvcs_module_init);
-module_exit(hvcs_module_exit);
diff -druNp linux-libre-2.6.37-gnu1/drivers/char/hvc_tile.c linux-libre-2.6.38-gnu1/drivers/char/hvc_tile.c
--- linux-libre-2.6.37-gnu1/drivers/char/hvc_tile.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/char/hvc_tile.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,68 +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.
- *
- * Tilera TILE Processor hypervisor console
- */
-
-#include <linux/console.h>
-#include <linux/delay.h>
-#include <linux/err.h>
-#include <linux/init.h>
-#include <linux/moduleparam.h>
-#include <linux/types.h>
-
-#include <hv/hypervisor.h>
-
-#include "hvc_console.h"
-
-static int hvc_tile_put_chars(uint32_t vt, const char *buf, int count)
-{
-	return hv_console_write((HV_VirtAddr)buf, count);
-}
-
-static int hvc_tile_get_chars(uint32_t vt, char *buf, int count)
-{
-	int i, c;
-
-	for (i = 0; i < count; ++i) {
-		c = hv_console_read_if_ready();
-		if (c < 0)
-			break;
-		buf[i] = c;
-	}
-
-	return i;
-}
-
-static const struct hv_ops hvc_tile_get_put_ops = {
-	.get_chars = hvc_tile_get_chars,
-	.put_chars = hvc_tile_put_chars,
-};
-
-static int __init hvc_tile_console_init(void)
-{
-	extern void disable_early_printk(void);
-	hvc_instantiate(0, 0, &hvc_tile_get_put_ops);
-	add_preferred_console("hvc", 0, NULL);
-	disable_early_printk();
-	return 0;
-}
-console_initcall(hvc_tile_console_init);
-
-static int __init hvc_tile_init(void)
-{
-	struct hvc_struct *s;
-	s = hvc_alloc(0, 0, &hvc_tile_get_put_ops, 128);
-	return IS_ERR(s) ? PTR_ERR(s) : 0;
-}
-device_initcall(hvc_tile_init);
diff -druNp linux-libre-2.6.37-gnu1/drivers/char/hvc_udbg.c linux-libre-2.6.38-gnu1/drivers/char/hvc_udbg.c
--- linux-libre-2.6.37-gnu1/drivers/char/hvc_udbg.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/char/hvc_udbg.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,96 +0,0 @@
-/*
- * udbg interface to hvc_console.c
- *
- * (C) Copyright David Gibson, IBM Corporation 2008.
- *
- * 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/console.h>
-#include <linux/delay.h>
-#include <linux/err.h>
-#include <linux/init.h>
-#include <linux/moduleparam.h>
-#include <linux/types.h>
-#include <linux/irq.h>
-
-#include <asm/udbg.h>
-
-#include "hvc_console.h"
-
-struct hvc_struct *hvc_udbg_dev;
-
-static int hvc_udbg_put(uint32_t vtermno, const char *buf, int count)
-{
-	int i;
-
-	for (i = 0; i < count; i++)
-		udbg_putc(buf[i]);
-
-	return i;
-}
-
-static int hvc_udbg_get(uint32_t vtermno, char *buf, int count)
-{
-	int i, c;
-
-	if (!udbg_getc_poll)
-		return 0;
-
-	for (i = 0; i < count; i++) {
-		if ((c = udbg_getc_poll()) == -1)
-			break;
-		buf[i] = c;
-	}
-
-	return i;
-}
-
-static const struct hv_ops hvc_udbg_ops = {
-	.get_chars = hvc_udbg_get,
-	.put_chars = hvc_udbg_put,
-};
-
-static int __init hvc_udbg_init(void)
-{
-	struct hvc_struct *hp;
-
-	BUG_ON(hvc_udbg_dev);
-
-	hp = hvc_alloc(0, NO_IRQ, &hvc_udbg_ops, 16);
-	if (IS_ERR(hp))
-		return PTR_ERR(hp);
-
-	hvc_udbg_dev = hp;
-
-	return 0;
-}
-module_init(hvc_udbg_init);
-
-static void __exit hvc_udbg_exit(void)
-{
-	if (hvc_udbg_dev)
-		hvc_remove(hvc_udbg_dev);
-}
-module_exit(hvc_udbg_exit);
-
-static int __init hvc_udbg_console_init(void)
-{
-	hvc_instantiate(0, 0, &hvc_udbg_ops);
-	add_preferred_console("hvc", 0, NULL);
-
-	return 0;
-}
-console_initcall(hvc_udbg_console_init);
diff -druNp linux-libre-2.6.37-gnu1/drivers/char/hvc_vio.c linux-libre-2.6.38-gnu1/drivers/char/hvc_vio.c
--- linux-libre-2.6.37-gnu1/drivers/char/hvc_vio.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/char/hvc_vio.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,173 +0,0 @@
-/*
- * vio driver interface to hvc_console.c
- *
- * This code was moved here to allow the remaing code to be reused as a
- * generic polling mode with semi-reliable transport driver core to the
- * console and tty subsystems.
- *
- *
- * Copyright (C) 2001 Anton Blanchard <anton@au.ibm.com>, IBM
- * Copyright (C) 2001 Paul Mackerras <paulus@au.ibm.com>, IBM
- * Copyright (C) 2004 Benjamin Herrenschmidt <benh@kernel.crashing.org>, IBM Corp.
- * Copyright (C) 2004 IBM Corporation
- *
- * Additional Author(s):
- *  Ryan S. Arnold <rsa@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/types.h>
-#include <linux/init.h>
-
-#include <asm/hvconsole.h>
-#include <asm/vio.h>
-#include <asm/prom.h>
-#include <asm/firmware.h>
-
-#include "hvc_console.h"
-
-char hvc_driver_name[] = "hvc_console";
-
-static struct vio_device_id hvc_driver_table[] __devinitdata = {
-	{"serial", "hvterm1"},
-	{ "", "" }
-};
-MODULE_DEVICE_TABLE(vio, hvc_driver_table);
-
-static int filtered_get_chars(uint32_t vtermno, char *buf, int count)
-{
-	unsigned long got;
-	int i;
-
-	/*
-	 * Vio firmware will read up to SIZE_VIO_GET_CHARS at its own discretion
-	 * so we play safe and avoid the situation where got > count which could
-	 * overload the flip buffer.
-	 */
-	if (count < SIZE_VIO_GET_CHARS)
-		return -EAGAIN;
-
-	got = hvc_get_chars(vtermno, buf, count);
-
-	/*
-	 * Work around a HV bug where it gives us a null
-	 * after every \r.  -- paulus
-	 */
-	for (i = 1; i < got; ++i) {
-		if (buf[i] == 0 && buf[i-1] == '\r') {
-			--got;
-			if (i < got)
-				memmove(&buf[i], &buf[i+1],
-					got - i);
-		}
-	}
-	return got;
-}
-
-static const struct hv_ops hvc_get_put_ops = {
-	.get_chars = filtered_get_chars,
-	.put_chars = hvc_put_chars,
-	.notifier_add = notifier_add_irq,
-	.notifier_del = notifier_del_irq,
-	.notifier_hangup = notifier_hangup_irq,
-};
-
-static int __devinit hvc_vio_probe(struct vio_dev *vdev,
-				const struct vio_device_id *id)
-{
-	struct hvc_struct *hp;
-
-	/* probed with invalid parameters. */
-	if (!vdev || !id)
-		return -EPERM;
-
-	hp = hvc_alloc(vdev->unit_address, vdev->irq, &hvc_get_put_ops,
-			MAX_VIO_PUT_CHARS);
-	if (IS_ERR(hp))
-		return PTR_ERR(hp);
-	dev_set_drvdata(&vdev->dev, hp);
-
-	return 0;
-}
-
-static int __devexit hvc_vio_remove(struct vio_dev *vdev)
-{
-	struct hvc_struct *hp = dev_get_drvdata(&vdev->dev);
-
-	return hvc_remove(hp);
-}
-
-static struct vio_driver hvc_vio_driver = {
-	.id_table	= hvc_driver_table,
-	.probe		= hvc_vio_probe,
-	.remove		= __devexit_p(hvc_vio_remove),
-	.driver		= {
-		.name	= hvc_driver_name,
-		.owner	= THIS_MODULE,
-	}
-};
-
-static int __init hvc_vio_init(void)
-{
-	int rc;
-
-	if (firmware_has_feature(FW_FEATURE_ISERIES))
-		return -EIO;
-
-	/* Register as a vio device to receive callbacks */
-	rc = vio_register_driver(&hvc_vio_driver);
-
-	return rc;
-}
-module_init(hvc_vio_init); /* after drivers/char/hvc_console.c */
-
-static void __exit hvc_vio_exit(void)
-{
-	vio_unregister_driver(&hvc_vio_driver);
-}
-module_exit(hvc_vio_exit);
-
-/* the device tree order defines our numbering */
-static int hvc_find_vtys(void)
-{
-	struct device_node *vty;
-	int num_found = 0;
-
-	for (vty = of_find_node_by_name(NULL, "vty"); vty != NULL;
-			vty = of_find_node_by_name(vty, "vty")) {
-		const uint32_t *vtermno;
-
-		/* We have statically defined space for only a certain number
-		 * of console adapters.
-		 */
-		if (num_found >= MAX_NR_HVC_CONSOLES) {
-			of_node_put(vty);
-			break;
-		}
-
-		vtermno = of_get_property(vty, "reg", NULL);
-		if (!vtermno)
-			continue;
-
-		if (of_device_is_compatible(vty, "hvterm1")) {
-			hvc_instantiate(*vtermno, num_found, &hvc_get_put_ops);
-			++num_found;
-		}
-	}
-
-	return num_found;
-}
-console_initcall(hvc_find_vtys);
diff -druNp linux-libre-2.6.37-gnu1/drivers/char/hvc_xen.c linux-libre-2.6.38-gnu1/drivers/char/hvc_xen.c
--- linux-libre-2.6.37-gnu1/drivers/char/hvc_xen.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/char/hvc_xen.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,271 +0,0 @@
-/*
- * xen console driver interface to hvc_console.c
- *
- * (c) 2007 Gerd Hoffmann <kraxel@suse.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., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
- */
-
-#include <linux/console.h>
-#include <linux/delay.h>
-#include <linux/err.h>
-#include <linux/init.h>
-#include <linux/types.h>
-
-#include <asm/xen/hypervisor.h>
-
-#include <xen/xen.h>
-#include <xen/page.h>
-#include <xen/events.h>
-#include <xen/interface/io/console.h>
-#include <xen/hvc-console.h>
-
-#include "hvc_console.h"
-
-#define HVC_COOKIE   0x58656e /* "Xen" in hex */
-
-static struct hvc_struct *hvc;
-static int xencons_irq;
-
-/* ------------------------------------------------------------------ */
-
-static unsigned long console_pfn = ~0ul;
-
-static inline struct xencons_interface *xencons_interface(void)
-{
-	if (console_pfn == ~0ul)
-		return mfn_to_virt(xen_start_info->console.domU.mfn);
-	else
-		return __va(console_pfn << PAGE_SHIFT);
-}
-
-static inline void notify_daemon(void)
-{
-	/* Use evtchn: this is called early, before irq is set up. */
-	notify_remote_via_evtchn(xen_start_info->console.domU.evtchn);
-}
-
-static int __write_console(const char *data, int len)
-{
-	struct xencons_interface *intf = xencons_interface();
-	XENCONS_RING_IDX cons, prod;
-	int sent = 0;
-
-	cons = intf->out_cons;
-	prod = intf->out_prod;
-	mb();			/* update queue values before going on */
-	BUG_ON((prod - cons) > sizeof(intf->out));
-
-	while ((sent < len) && ((prod - cons) < sizeof(intf->out)))
-		intf->out[MASK_XENCONS_IDX(prod++, intf->out)] = data[sent++];
-
-	wmb();			/* write ring before updating pointer */
-	intf->out_prod = prod;
-
-	if (sent)
-		notify_daemon();
-	return sent;
-}
-
-static int domU_write_console(uint32_t vtermno, const char *data, int len)
-{
-	int ret = len;
-
-	/*
-	 * Make sure the whole buffer is emitted, polling if
-	 * necessary.  We don't ever want to rely on the hvc daemon
-	 * because the most interesting console output is when the
-	 * kernel is crippled.
-	 */
-	while (len) {
-		int sent = __write_console(data, len);
-		
-		data += sent;
-		len -= sent;
-
-		if (unlikely(len))
-			HYPERVISOR_sched_op(SCHEDOP_yield, NULL);
-	}
-
-	return ret;
-}
-
-static int domU_read_console(uint32_t vtermno, char *buf, int len)
-{
-	struct xencons_interface *intf = xencons_interface();
-	XENCONS_RING_IDX cons, prod;
-	int recv = 0;
-
-	cons = intf->in_cons;
-	prod = intf->in_prod;
-	mb();			/* get pointers before reading ring */
-	BUG_ON((prod - cons) > sizeof(intf->in));
-
-	while (cons != prod && recv < len)
-		buf[recv++] = intf->in[MASK_XENCONS_IDX(cons++, intf->in)];
-
-	mb();			/* read ring before consuming */
-	intf->in_cons = cons;
-
-	notify_daemon();
-	return recv;
-}
-
-static struct hv_ops domU_hvc_ops = {
-	.get_chars = domU_read_console,
-	.put_chars = domU_write_console,
-	.notifier_add = notifier_add_irq,
-	.notifier_del = notifier_del_irq,
-	.notifier_hangup = notifier_hangup_irq,
-};
-
-static int dom0_read_console(uint32_t vtermno, char *buf, int len)
-{
-	return HYPERVISOR_console_io(CONSOLEIO_read, len, buf);
-}
-
-/*
- * Either for a dom0 to write to the system console, or a domU with a
- * debug version of Xen
- */
-static int dom0_write_console(uint32_t vtermno, const char *str, int len)
-{
-	int rc = HYPERVISOR_console_io(CONSOLEIO_write, len, (char *)str);
-	if (rc < 0)
-		return 0;
-
-	return len;
-}
-
-static struct hv_ops dom0_hvc_ops = {
-	.get_chars = dom0_read_console,
-	.put_chars = dom0_write_console,
-	.notifier_add = notifier_add_irq,
-	.notifier_del = notifier_del_irq,
-	.notifier_hangup = notifier_hangup_irq,
-};
-
-static int __init xen_hvc_init(void)
-{
-	struct hvc_struct *hp;
-	struct hv_ops *ops;
-
-	if (!xen_pv_domain())
-		return -ENODEV;
-
-	if (xen_initial_domain()) {
-		ops = &dom0_hvc_ops;
-		xencons_irq = bind_virq_to_irq(VIRQ_CONSOLE, 0);
-	} else {
-		if (!xen_start_info->console.domU.evtchn)
-			return -ENODEV;
-
-		ops = &domU_hvc_ops;
-		xencons_irq = bind_evtchn_to_irq(xen_start_info->console.domU.evtchn);
-	}
-	if (xencons_irq < 0)
-		xencons_irq = 0; /* NO_IRQ */
-
-	hp = hvc_alloc(HVC_COOKIE, xencons_irq, ops, 256);
-	if (IS_ERR(hp))
-		return PTR_ERR(hp);
-
-	hvc = hp;
-
-	console_pfn = mfn_to_pfn(xen_start_info->console.domU.mfn);
-
-	return 0;
-}
-
-void xen_console_resume(void)
-{
-	if (xencons_irq)
-		rebind_evtchn_irq(xen_start_info->console.domU.evtchn, xencons_irq);
-}
-
-static void __exit xen_hvc_fini(void)
-{
-	if (hvc)
-		hvc_remove(hvc);
-}
-
-static int xen_cons_init(void)
-{
-	struct hv_ops *ops;
-
-	if (!xen_pv_domain())
-		return 0;
-
-	if (xen_initial_domain())
-		ops = &dom0_hvc_ops;
-	else
-		ops = &domU_hvc_ops;
-
-	hvc_instantiate(HVC_COOKIE, 0, ops);
-	return 0;
-}
-
-module_init(xen_hvc_init);
-module_exit(xen_hvc_fini);
-console_initcall(xen_cons_init);
-
-#ifdef CONFIG_EARLY_PRINTK
-static void xenboot_write_console(struct console *console, const char *string,
-				  unsigned len)
-{
-	unsigned int linelen, off = 0;
-	const char *pos;
-
-	dom0_write_console(0, string, len);
-
-	if (xen_initial_domain())
-		return;
-
-	domU_write_console(0, "(early) ", 8);
-	while (off < len && NULL != (pos = strchr(string+off, '\n'))) {
-		linelen = pos-string+off;
-		if (off + linelen > len)
-			break;
-		domU_write_console(0, string+off, linelen);
-		domU_write_console(0, "\r\n", 2);
-		off += linelen + 1;
-	}
-	if (off < len)
-		domU_write_console(0, string+off, len-off);
-}
-
-struct console xenboot_console = {
-	.name		= "xenboot",
-	.write		= xenboot_write_console,
-	.flags		= CON_PRINTBUFFER | CON_BOOT | CON_ANYTIME,
-};
-#endif	/* CONFIG_EARLY_PRINTK */
-
-void xen_raw_console_write(const char *str)
-{
-	dom0_write_console(0, str, strlen(str));
-}
-
-void xen_raw_printk(const char *fmt, ...)
-{
-	static char buf[512];
-	va_list ap;
-
-	va_start(ap, fmt);
-	vsnprintf(buf, sizeof(buf), fmt, ap);
-	va_end(ap);
-
-	xen_raw_console_write(buf);
-}
diff -druNp linux-libre-2.6.37-gnu1/drivers/char/hvsi.c linux-libre-2.6.38-gnu1/drivers/char/hvsi.c
--- linux-libre-2.6.37-gnu1/drivers/char/hvsi.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/char/hvsi.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1314 +0,0 @@
-/*
- * Copyright (C) 2004 Hollis Blanchard <hollisb@us.ibm.com>, IBM
- *
- * 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
- */
-
-/* Host Virtual Serial Interface (HVSI) is a protocol between the hosted OS
- * and the service processor on IBM pSeries servers. On these servers, there
- * are no serial ports under the OS's control, and sometimes there is no other
- * console available either. However, the service processor has two standard
- * serial ports, so this over-complicated protocol allows the OS to control
- * those ports by proxy.
- *
- * Besides data, the procotol supports the reading/writing of the serial
- * port's DTR line, and the reading of the CD line. This is to allow the OS to
- * control a modem attached to the service processor's serial port. Note that
- * the OS cannot change the speed of the port through this protocol.
- */
-
-#undef DEBUG
-
-#include <linux/console.h>
-#include <linux/ctype.h>
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/module.h>
-#include <linux/major.h>
-#include <linux/kernel.h>
-#include <linux/spinlock.h>
-#include <linux/sysrq.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <asm/hvcall.h>
-#include <asm/hvconsole.h>
-#include <asm/prom.h>
-#include <asm/uaccess.h>
-#include <asm/vio.h>
-#include <asm/param.h>
-
-#define HVSI_MAJOR	229
-#define HVSI_MINOR	128
-#define MAX_NR_HVSI_CONSOLES 4
-
-#define HVSI_TIMEOUT (5*HZ)
-#define HVSI_VERSION 1
-#define HVSI_MAX_PACKET 256
-#define HVSI_MAX_READ 16
-#define HVSI_MAX_OUTGOING_DATA 12
-#define N_OUTBUF 12
-
-/*
- * we pass data via two 8-byte registers, so we would like our char arrays
- * properly aligned for those loads.
- */
-#define __ALIGNED__	__attribute__((__aligned__(sizeof(long))))
-
-struct hvsi_struct {
-	struct delayed_work writer;
-	struct work_struct handshaker;
-	wait_queue_head_t emptyq; /* woken when outbuf is emptied */
-	wait_queue_head_t stateq; /* woken when HVSI state changes */
-	spinlock_t lock;
-	int index;
-	struct tty_struct *tty;
-	int count;
-	uint8_t throttle_buf[128];
-	uint8_t outbuf[N_OUTBUF]; /* to implement write_room and chars_in_buffer */
-	/* inbuf is for packet reassembly. leave a little room for leftovers. */
-	uint8_t inbuf[HVSI_MAX_PACKET + HVSI_MAX_READ];
-	uint8_t *inbuf_end;
-	int n_throttle;
-	int n_outbuf;
-	uint32_t vtermno;
-	uint32_t virq;
-	atomic_t seqno; /* HVSI packet sequence number */
-	uint16_t mctrl;
-	uint8_t state;  /* HVSI protocol state */
-	uint8_t flags;
-#ifdef CONFIG_MAGIC_SYSRQ
-	uint8_t sysrq;
-#endif /* CONFIG_MAGIC_SYSRQ */
-};
-static struct hvsi_struct hvsi_ports[MAX_NR_HVSI_CONSOLES];
-
-static struct tty_driver *hvsi_driver;
-static int hvsi_count;
-static int (*hvsi_wait)(struct hvsi_struct *hp, int state);
-
-enum HVSI_PROTOCOL_STATE {
-	HVSI_CLOSED,
-	HVSI_WAIT_FOR_VER_RESPONSE,
-	HVSI_WAIT_FOR_VER_QUERY,
-	HVSI_OPEN,
-	HVSI_WAIT_FOR_MCTRL_RESPONSE,
-	HVSI_FSP_DIED,
-};
-#define HVSI_CONSOLE 0x1
-
-#define VS_DATA_PACKET_HEADER           0xff
-#define VS_CONTROL_PACKET_HEADER        0xfe
-#define VS_QUERY_PACKET_HEADER          0xfd
-#define VS_QUERY_RESPONSE_PACKET_HEADER 0xfc
-
-/* control verbs */
-#define VSV_SET_MODEM_CTL    1 /* to service processor only */
-#define VSV_MODEM_CTL_UPDATE 2 /* from service processor only */
-#define VSV_CLOSE_PROTOCOL   3
-
-/* query verbs */
-#define VSV_SEND_VERSION_NUMBER 1
-#define VSV_SEND_MODEM_CTL_STATUS 2
-
-/* yes, these masks are not consecutive. */
-#define HVSI_TSDTR 0x01
-#define HVSI_TSCD  0x20
-
-struct hvsi_header {
-	uint8_t  type;
-	uint8_t  len;
-	uint16_t seqno;
-} __attribute__((packed));
-
-struct hvsi_data {
-	uint8_t  type;
-	uint8_t  len;
-	uint16_t seqno;
-	uint8_t  data[HVSI_MAX_OUTGOING_DATA];
-} __attribute__((packed));
-
-struct hvsi_control {
-	uint8_t  type;
-	uint8_t  len;
-	uint16_t seqno;
-	uint16_t verb;
-	/* optional depending on verb: */
-	uint32_t word;
-	uint32_t mask;
-} __attribute__((packed));
-
-struct hvsi_query {
-	uint8_t  type;
-	uint8_t  len;
-	uint16_t seqno;
-	uint16_t verb;
-} __attribute__((packed));
-
-struct hvsi_query_response {
-	uint8_t  type;
-	uint8_t  len;
-	uint16_t seqno;
-	uint16_t verb;
-	uint16_t query_seqno;
-	union {
-		uint8_t  version;
-		uint32_t mctrl_word;
-	} u;
-} __attribute__((packed));
-
-
-
-static inline int is_console(struct hvsi_struct *hp)
-{
-	return hp->flags & HVSI_CONSOLE;
-}
-
-static inline int is_open(struct hvsi_struct *hp)
-{
-	/* if we're waiting for an mctrl then we're already open */
-	return (hp->state == HVSI_OPEN)
-			|| (hp->state == HVSI_WAIT_FOR_MCTRL_RESPONSE);
-}
-
-static inline void print_state(struct hvsi_struct *hp)
-{
-#ifdef DEBUG
-	static const char *state_names[] = {
-		"HVSI_CLOSED",
-		"HVSI_WAIT_FOR_VER_RESPONSE",
-		"HVSI_WAIT_FOR_VER_QUERY",
-		"HVSI_OPEN",
-		"HVSI_WAIT_FOR_MCTRL_RESPONSE",
-		"HVSI_FSP_DIED",
-	};
-	const char *name = (hp->state < ARRAY_SIZE(state_names))
-		? state_names[hp->state] : "UNKNOWN";
-
-	pr_debug("hvsi%i: state = %s\n", hp->index, name);
-#endif /* DEBUG */
-}
-
-static inline void __set_state(struct hvsi_struct *hp, int state)
-{
-	hp->state = state;
-	print_state(hp);
-	wake_up_all(&hp->stateq);
-}
-
-static inline void set_state(struct hvsi_struct *hp, int state)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&hp->lock, flags);
-	__set_state(hp, state);
-	spin_unlock_irqrestore(&hp->lock, flags);
-}
-
-static inline int len_packet(const uint8_t *packet)
-{
-	return (int)((struct hvsi_header *)packet)->len;
-}
-
-static inline int is_header(const uint8_t *packet)
-{
-	struct hvsi_header *header = (struct hvsi_header *)packet;
-	return header->type >= VS_QUERY_RESPONSE_PACKET_HEADER;
-}
-
-static inline int got_packet(const struct hvsi_struct *hp, uint8_t *packet)
-{
-	if (hp->inbuf_end < packet + sizeof(struct hvsi_header))
-		return 0; /* don't even have the packet header */
-
-	if (hp->inbuf_end < (packet + len_packet(packet)))
-		return 0; /* don't have the rest of the packet */
-
-	return 1;
-}
-
-/* shift remaining bytes in packetbuf down */
-static void compact_inbuf(struct hvsi_struct *hp, uint8_t *read_to)
-{
-	int remaining = (int)(hp->inbuf_end - read_to);
-
-	pr_debug("%s: %i chars remain\n", __func__, remaining);
-
-	if (read_to != hp->inbuf)
-		memmove(hp->inbuf, read_to, remaining);
-
-	hp->inbuf_end = hp->inbuf + remaining;
-}
-
-#ifdef DEBUG
-#define dbg_dump_packet(packet) dump_packet(packet)
-#define dbg_dump_hex(data, len) dump_hex(data, len)
-#else
-#define dbg_dump_packet(packet) do { } while (0)
-#define dbg_dump_hex(data, len) do { } while (0)
-#endif
-
-static void dump_hex(const uint8_t *data, int len)
-{
-	int i;
-
-	printk("    ");
-	for (i=0; i < len; i++)
-		printk("%.2x", data[i]);
-
-	printk("\n    ");
-	for (i=0; i < len; i++) {
-		if (isprint(data[i]))
-			printk("%c", data[i]);
-		else
-			printk(".");
-	}
-	printk("\n");
-}
-
-static void dump_packet(uint8_t *packet)
-{
-	struct hvsi_header *header = (struct hvsi_header *)packet;
-
-	printk("type 0x%x, len %i, seqno %i:\n", header->type, header->len,
-			header->seqno);
-
-	dump_hex(packet, header->len);
-}
-
-static int hvsi_read(struct hvsi_struct *hp, char *buf, int count)
-{
-	unsigned long got;
-
-	got = hvc_get_chars(hp->vtermno, buf, count);
-
-	return got;
-}
-
-static void hvsi_recv_control(struct hvsi_struct *hp, uint8_t *packet,
-	struct tty_struct **to_hangup, struct hvsi_struct **to_handshake)
-{
-	struct hvsi_control *header = (struct hvsi_control *)packet;
-
-	switch (header->verb) {
-		case VSV_MODEM_CTL_UPDATE:
-			if ((header->word & HVSI_TSCD) == 0) {
-				/* CD went away; no more connection */
-				pr_debug("hvsi%i: CD dropped\n", hp->index);
-				hp->mctrl &= TIOCM_CD;
-				/* If userland hasn't done an open(2) yet, hp->tty is NULL. */
-				if (hp->tty && !(hp->tty->flags & CLOCAL))
-					*to_hangup = hp->tty;
-			}
-			break;
-		case VSV_CLOSE_PROTOCOL:
-			pr_debug("hvsi%i: service processor came back\n", hp->index);
-			if (hp->state != HVSI_CLOSED) {
-				*to_handshake = hp;
-			}
-			break;
-		default:
-			printk(KERN_WARNING "hvsi%i: unknown HVSI control packet: ",
-				hp->index);
-			dump_packet(packet);
-			break;
-	}
-}
-
-static void hvsi_recv_response(struct hvsi_struct *hp, uint8_t *packet)
-{
-	struct hvsi_query_response *resp = (struct hvsi_query_response *)packet;
-
-	switch (hp->state) {
-		case HVSI_WAIT_FOR_VER_RESPONSE:
-			__set_state(hp, HVSI_WAIT_FOR_VER_QUERY);
-			break;
-		case HVSI_WAIT_FOR_MCTRL_RESPONSE:
-			hp->mctrl = 0;
-			if (resp->u.mctrl_word & HVSI_TSDTR)
-				hp->mctrl |= TIOCM_DTR;
-			if (resp->u.mctrl_word & HVSI_TSCD)
-				hp->mctrl |= TIOCM_CD;
-			__set_state(hp, HVSI_OPEN);
-			break;
-		default:
-			printk(KERN_ERR "hvsi%i: unexpected query response: ", hp->index);
-			dump_packet(packet);
-			break;
-	}
-}
-
-/* respond to service processor's version query */
-static int hvsi_version_respond(struct hvsi_struct *hp, uint16_t query_seqno)
-{
-	struct hvsi_query_response packet __ALIGNED__;
-	int wrote;
-
-	packet.type = VS_QUERY_RESPONSE_PACKET_HEADER;
-	packet.len = sizeof(struct hvsi_query_response);
-	packet.seqno = atomic_inc_return(&hp->seqno);
-	packet.verb = VSV_SEND_VERSION_NUMBER;
-	packet.u.version = HVSI_VERSION;
-	packet.query_seqno = query_seqno+1;
-
-	pr_debug("%s: sending %i bytes\n", __func__, packet.len);
-	dbg_dump_hex((uint8_t*)&packet, packet.len);
-
-	wrote = hvc_put_chars(hp->vtermno, (char *)&packet, packet.len);
-	if (wrote != packet.len) {
-		printk(KERN_ERR "hvsi%i: couldn't send query response!\n",
-			hp->index);
-		return -EIO;
-	}
-
-	return 0;
-}
-
-static void hvsi_recv_query(struct hvsi_struct *hp, uint8_t *packet)
-{
-	struct hvsi_query *query = (struct hvsi_query *)packet;
-
-	switch (hp->state) {
-		case HVSI_WAIT_FOR_VER_QUERY:
-			hvsi_version_respond(hp, query->seqno);
-			__set_state(hp, HVSI_OPEN);
-			break;
-		default:
-			printk(KERN_ERR "hvsi%i: unexpected query: ", hp->index);
-			dump_packet(packet);
-			break;
-	}
-}
-
-static void hvsi_insert_chars(struct hvsi_struct *hp, const char *buf, int len)
-{
-	int i;
-
-	for (i=0; i < len; i++) {
-		char c = buf[i];
-#ifdef CONFIG_MAGIC_SYSRQ
-		if (c == '\0') {
-			hp->sysrq = 1;
-			continue;
-		} else if (hp->sysrq) {
-			handle_sysrq(c);
-			hp->sysrq = 0;
-			continue;
-		}
-#endif /* CONFIG_MAGIC_SYSRQ */
-		tty_insert_flip_char(hp->tty, c, 0);
-	}
-}
-
-/*
- * We could get 252 bytes of data at once here. But the tty layer only
- * throttles us at TTY_THRESHOLD_THROTTLE (128) bytes, so we could overflow
- * it. Accordingly we won't send more than 128 bytes at a time to the flip
- * buffer, which will give the tty buffer a chance to throttle us. Should the
- * value of TTY_THRESHOLD_THROTTLE change in n_tty.c, this code should be
- * revisited.
- */
-#define TTY_THRESHOLD_THROTTLE 128
-static struct tty_struct *hvsi_recv_data(struct hvsi_struct *hp,
-		const uint8_t *packet)
-{
-	const struct hvsi_header *header = (const struct hvsi_header *)packet;
-	const uint8_t *data = packet + sizeof(struct hvsi_header);
-	int datalen = header->len - sizeof(struct hvsi_header);
-	int overflow = datalen - TTY_THRESHOLD_THROTTLE;
-
-	pr_debug("queueing %i chars '%.*s'\n", datalen, datalen, data);
-
-	if (datalen == 0)
-		return NULL;
-
-	if (overflow > 0) {
-		pr_debug("%s: got >TTY_THRESHOLD_THROTTLE bytes\n", __func__);
-		datalen = TTY_THRESHOLD_THROTTLE;
-	}
-
-	hvsi_insert_chars(hp, data, datalen);
-
-	if (overflow > 0) {
-		/*
-		 * we still have more data to deliver, so we need to save off the
-		 * overflow and send it later
-		 */
-		pr_debug("%s: deferring overflow\n", __func__);
-		memcpy(hp->throttle_buf, data + TTY_THRESHOLD_THROTTLE, overflow);
-		hp->n_throttle = overflow;
-	}
-
-	return hp->tty;
-}
-
-/*
- * Returns true/false indicating data successfully read from hypervisor.
- * Used both to get packets for tty connections and to advance the state
- * machine during console handshaking (in which case tty = NULL and we ignore
- * incoming data).
- */
-static int hvsi_load_chunk(struct hvsi_struct *hp, struct tty_struct **flip,
-		struct tty_struct **hangup, struct hvsi_struct **handshake)
-{
-	uint8_t *packet = hp->inbuf;
-	int chunklen;
-
-	*flip = NULL;
-	*hangup = NULL;
-	*handshake = NULL;
-
-	chunklen = hvsi_read(hp, hp->inbuf_end, HVSI_MAX_READ);
-	if (chunklen == 0) {
-		pr_debug("%s: 0-length read\n", __func__);
-		return 0;
-	}
-
-	pr_debug("%s: got %i bytes\n", __func__, chunklen);
-	dbg_dump_hex(hp->inbuf_end, chunklen);
-
-	hp->inbuf_end += chunklen;
-
-	/* handle all completed packets */
-	while ((packet < hp->inbuf_end) && got_packet(hp, packet)) {
-		struct hvsi_header *header = (struct hvsi_header *)packet;
-
-		if (!is_header(packet)) {
-			printk(KERN_ERR "hvsi%i: got malformed packet\n", hp->index);
-			/* skip bytes until we find a header or run out of data */
-			while ((packet < hp->inbuf_end) && (!is_header(packet)))
-				packet++;
-			continue;
-		}
-
-		pr_debug("%s: handling %i-byte packet\n", __func__,
-				len_packet(packet));
-		dbg_dump_packet(packet);
-
-		switch (header->type) {
-			case VS_DATA_PACKET_HEADER:
-				if (!is_open(hp))
-					break;
-				if (hp->tty == NULL)
-					break; /* no tty buffer to put data in */
-				*flip = hvsi_recv_data(hp, packet);
-				break;
-			case VS_CONTROL_PACKET_HEADER:
-				hvsi_recv_control(hp, packet, hangup, handshake);
-				break;
-			case VS_QUERY_RESPONSE_PACKET_HEADER:
-				hvsi_recv_response(hp, packet);
-				break;
-			case VS_QUERY_PACKET_HEADER:
-				hvsi_recv_query(hp, packet);
-				break;
-			default:
-				printk(KERN_ERR "hvsi%i: unknown HVSI packet type 0x%x\n",
-						hp->index, header->type);
-				dump_packet(packet);
-				break;
-		}
-
-		packet += len_packet(packet);
-
-		if (*hangup || *handshake) {
-			pr_debug("%s: hangup or handshake\n", __func__);
-			/*
-			 * we need to send the hangup now before receiving any more data.
-			 * If we get "data, hangup, data", we can't deliver the second
-			 * data before the hangup.
-			 */
-			break;
-		}
-	}
-
-	compact_inbuf(hp, packet);
-
-	return 1;
-}
-
-static void hvsi_send_overflow(struct hvsi_struct *hp)
-{
-	pr_debug("%s: delivering %i bytes overflow\n", __func__,
-			hp->n_throttle);
-
-	hvsi_insert_chars(hp, hp->throttle_buf, hp->n_throttle);
-	hp->n_throttle = 0;
-}
-
-/*
- * must get all pending data because we only get an irq on empty->non-empty
- * transition
- */
-static irqreturn_t hvsi_interrupt(int irq, void *arg)
-{
-	struct hvsi_struct *hp = (struct hvsi_struct *)arg;
-	struct tty_struct *flip;
-	struct tty_struct *hangup;
-	struct hvsi_struct *handshake;
-	unsigned long flags;
-	int again = 1;
-
-	pr_debug("%s\n", __func__);
-
-	while (again) {
-		spin_lock_irqsave(&hp->lock, flags);
-		again = hvsi_load_chunk(hp, &flip, &hangup, &handshake);
-		spin_unlock_irqrestore(&hp->lock, flags);
-
-		/*
-		 * we have to call tty_flip_buffer_push() and tty_hangup() outside our
-		 * spinlock. But we also have to keep going until we've read all the
-		 * available data.
-		 */
-
-		if (flip) {
-			/* there was data put in the tty flip buffer */
-			tty_flip_buffer_push(flip);
-			flip = NULL;
-		}
-
-		if (hangup) {
-			tty_hangup(hangup);
-		}
-
-		if (handshake) {
-			pr_debug("hvsi%i: attempting re-handshake\n", handshake->index);
-			schedule_work(&handshake->handshaker);
-		}
-	}
-
-	spin_lock_irqsave(&hp->lock, flags);
-	if (hp->tty && hp->n_throttle
-			&& (!test_bit(TTY_THROTTLED, &hp->tty->flags))) {
-		/* we weren't hung up and we weren't throttled, so we can deliver the
-		 * rest now */
-		flip = hp->tty;
-		hvsi_send_overflow(hp);
-	}
-	spin_unlock_irqrestore(&hp->lock, flags);
-
-	if (flip) {
-		tty_flip_buffer_push(flip);
-	}
-
-	return IRQ_HANDLED;
-}
-
-/* for boot console, before the irq handler is running */
-static int __init poll_for_state(struct hvsi_struct *hp, int state)
-{
-	unsigned long end_jiffies = jiffies + HVSI_TIMEOUT;
-
-	for (;;) {
-		hvsi_interrupt(hp->virq, (void *)hp); /* get pending data */
-
-		if (hp->state == state)
-			return 0;
-
-		mdelay(5);
-		if (time_after(jiffies, end_jiffies))
-			return -EIO;
-	}
-}
-
-/* wait for irq handler to change our state */
-static int wait_for_state(struct hvsi_struct *hp, int state)
-{
-	int ret = 0;
-
-	if (!wait_event_timeout(hp->stateq, (hp->state == state), HVSI_TIMEOUT))
-		ret = -EIO;
-
-	return ret;
-}
-
-static int hvsi_query(struct hvsi_struct *hp, uint16_t verb)
-{
-	struct hvsi_query packet __ALIGNED__;
-	int wrote;
-
-	packet.type = VS_QUERY_PACKET_HEADER;
-	packet.len = sizeof(struct hvsi_query);
-	packet.seqno = atomic_inc_return(&hp->seqno);
-	packet.verb = verb;
-
-	pr_debug("%s: sending %i bytes\n", __func__, packet.len);
-	dbg_dump_hex((uint8_t*)&packet, packet.len);
-
-	wrote = hvc_put_chars(hp->vtermno, (char *)&packet, packet.len);
-	if (wrote != packet.len) {
-		printk(KERN_ERR "hvsi%i: couldn't send query (%i)!\n", hp->index,
-			wrote);
-		return -EIO;
-	}
-
-	return 0;
-}
-
-static int hvsi_get_mctrl(struct hvsi_struct *hp)
-{
-	int ret;
-
-	set_state(hp, HVSI_WAIT_FOR_MCTRL_RESPONSE);
-	hvsi_query(hp, VSV_SEND_MODEM_CTL_STATUS);
-
-	ret = hvsi_wait(hp, HVSI_OPEN);
-	if (ret < 0) {
-		printk(KERN_ERR "hvsi%i: didn't get modem flags\n", hp->index);
-		set_state(hp, HVSI_OPEN);
-		return ret;
-	}
-
-	pr_debug("%s: mctrl 0x%x\n", __func__, hp->mctrl);
-
-	return 0;
-}
-
-/* note that we can only set DTR */
-static int hvsi_set_mctrl(struct hvsi_struct *hp, uint16_t mctrl)
-{
-	struct hvsi_control packet __ALIGNED__;
-	int wrote;
-
-	packet.type = VS_CONTROL_PACKET_HEADER,
-	packet.seqno = atomic_inc_return(&hp->seqno);
-	packet.len = sizeof(struct hvsi_control);
-	packet.verb = VSV_SET_MODEM_CTL;
-	packet.mask = HVSI_TSDTR;
-
-	if (mctrl & TIOCM_DTR)
-		packet.word = HVSI_TSDTR;
-
-	pr_debug("%s: sending %i bytes\n", __func__, packet.len);
-	dbg_dump_hex((uint8_t*)&packet, packet.len);
-
-	wrote = hvc_put_chars(hp->vtermno, (char *)&packet, packet.len);
-	if (wrote != packet.len) {
-		printk(KERN_ERR "hvsi%i: couldn't set DTR!\n", hp->index);
-		return -EIO;
-	}
-
-	return 0;
-}
-
-static void hvsi_drain_input(struct hvsi_struct *hp)
-{
-	uint8_t buf[HVSI_MAX_READ] __ALIGNED__;
-	unsigned long end_jiffies = jiffies + HVSI_TIMEOUT;
-
-	while (time_before(end_jiffies, jiffies))
-		if (0 == hvsi_read(hp, buf, HVSI_MAX_READ))
-			break;
-}
-
-static int hvsi_handshake(struct hvsi_struct *hp)
-{
-	int ret;
-
-	/*
-	 * We could have a CLOSE or other data waiting for us before we even try
-	 * to open; try to throw it all away so we don't get confused. (CLOSE
-	 * is the first message sent up the pipe when the FSP comes online. We
-	 * need to distinguish between "it came up a while ago and we're the first
-	 * user" and "it was just reset before it saw our handshake packet".)
-	 */
-	hvsi_drain_input(hp);
-
-	set_state(hp, HVSI_WAIT_FOR_VER_RESPONSE);
-	ret = hvsi_query(hp, VSV_SEND_VERSION_NUMBER);
-	if (ret < 0) {
-		printk(KERN_ERR "hvsi%i: couldn't send version query\n", hp->index);
-		return ret;
-	}
-
-	ret = hvsi_wait(hp, HVSI_OPEN);
-	if (ret < 0)
-		return ret;
-
-	return 0;
-}
-
-static void hvsi_handshaker(struct work_struct *work)
-{
-	struct hvsi_struct *hp =
-		container_of(work, struct hvsi_struct, handshaker);
-
-	if (hvsi_handshake(hp) >= 0)
-		return;
-
-	printk(KERN_ERR "hvsi%i: re-handshaking failed\n", hp->index);
-	if (is_console(hp)) {
-		/*
-		 * ttys will re-attempt the handshake via hvsi_open, but
-		 * the console will not.
-		 */
-		printk(KERN_ERR "hvsi%i: lost console!\n", hp->index);
-	}
-}
-
-static int hvsi_put_chars(struct hvsi_struct *hp, const char *buf, int count)
-{
-	struct hvsi_data packet __ALIGNED__;
-	int ret;
-
-	BUG_ON(count > HVSI_MAX_OUTGOING_DATA);
-
-	packet.type = VS_DATA_PACKET_HEADER;
-	packet.seqno = atomic_inc_return(&hp->seqno);
-	packet.len = count + sizeof(struct hvsi_header);
-	memcpy(&packet.data, buf, count);
-
-	ret = hvc_put_chars(hp->vtermno, (char *)&packet, packet.len);
-	if (ret == packet.len) {
-		/* return the number of chars written, not the packet length */
-		return count;
-	}
-	return ret; /* return any errors */
-}
-
-static void hvsi_close_protocol(struct hvsi_struct *hp)
-{
-	struct hvsi_control packet __ALIGNED__;
-
-	packet.type = VS_CONTROL_PACKET_HEADER;
-	packet.seqno = atomic_inc_return(&hp->seqno);
-	packet.len = 6;
-	packet.verb = VSV_CLOSE_PROTOCOL;
-
-	pr_debug("%s: sending %i bytes\n", __func__, packet.len);
-	dbg_dump_hex((uint8_t*)&packet, packet.len);
-
-	hvc_put_chars(hp->vtermno, (char *)&packet, packet.len);
-}
-
-static int hvsi_open(struct tty_struct *tty, struct file *filp)
-{
-	struct hvsi_struct *hp;
-	unsigned long flags;
-	int line = tty->index;
-	int ret;
-
-	pr_debug("%s\n", __func__);
-
-	if (line < 0 || line >= hvsi_count)
-		return -ENODEV;
-	hp = &hvsi_ports[line];
-
-	tty->driver_data = hp;
-
-	mb();
-	if (hp->state == HVSI_FSP_DIED)
-		return -EIO;
-
-	spin_lock_irqsave(&hp->lock, flags);
-	hp->tty = tty;
-	hp->count++;
-	atomic_set(&hp->seqno, 0);
-	h_vio_signal(hp->vtermno, VIO_IRQ_ENABLE);
-	spin_unlock_irqrestore(&hp->lock, flags);
-
-	if (is_console(hp))
-		return 0; /* this has already been handshaked as the console */
-
-	ret = hvsi_handshake(hp);
-	if (ret < 0) {
-		printk(KERN_ERR "%s: HVSI handshaking failed\n", tty->name);
-		return ret;
-	}
-
-	ret = hvsi_get_mctrl(hp);
-	if (ret < 0) {
-		printk(KERN_ERR "%s: couldn't get initial modem flags\n", tty->name);
-		return ret;
-	}
-
-	ret = hvsi_set_mctrl(hp, hp->mctrl | TIOCM_DTR);
-	if (ret < 0) {
-		printk(KERN_ERR "%s: couldn't set DTR\n", tty->name);
-		return ret;
-	}
-
-	return 0;
-}
-
-/* wait for hvsi_write_worker to empty hp->outbuf */
-static void hvsi_flush_output(struct hvsi_struct *hp)
-{
-	wait_event_timeout(hp->emptyq, (hp->n_outbuf <= 0), HVSI_TIMEOUT);
-
-	/* 'writer' could still be pending if it didn't see n_outbuf = 0 yet */
-	cancel_delayed_work(&hp->writer);
-	flush_scheduled_work();
-
-	/*
-	 * it's also possible that our timeout expired and hvsi_write_worker
-	 * didn't manage to push outbuf. poof.
-	 */
-	hp->n_outbuf = 0;
-}
-
-static void hvsi_close(struct tty_struct *tty, struct file *filp)
-{
-	struct hvsi_struct *hp = tty->driver_data;
-	unsigned long flags;
-
-	pr_debug("%s\n", __func__);
-
-	if (tty_hung_up_p(filp))
-		return;
-
-	spin_lock_irqsave(&hp->lock, flags);
-
-	if (--hp->count == 0) {
-		hp->tty = NULL;
-		hp->inbuf_end = hp->inbuf; /* discard remaining partial packets */
-
-		/* only close down connection if it is not the console */
-		if (!is_console(hp)) {
-			h_vio_signal(hp->vtermno, VIO_IRQ_DISABLE); /* no more irqs */
-			__set_state(hp, HVSI_CLOSED);
-			/*
-			 * any data delivered to the tty layer after this will be
-			 * discarded (except for XON/XOFF)
-			 */
-			tty->closing = 1;
-
-			spin_unlock_irqrestore(&hp->lock, flags);
-
-			/* let any existing irq handlers finish. no more will start. */
-			synchronize_irq(hp->virq);
-
-			/* hvsi_write_worker will re-schedule until outbuf is empty. */
-			hvsi_flush_output(hp);
-
-			/* tell FSP to stop sending data */
-			hvsi_close_protocol(hp);
-
-			/*
-			 * drain anything FSP is still in the middle of sending, and let
-			 * hvsi_handshake drain the rest on the next open.
-			 */
-			hvsi_drain_input(hp);
-
-			spin_lock_irqsave(&hp->lock, flags);
-		}
-	} else if (hp->count < 0)
-		printk(KERN_ERR "hvsi_close %lu: oops, count is %d\n",
-		       hp - hvsi_ports, hp->count);
-
-	spin_unlock_irqrestore(&hp->lock, flags);
-}
-
-static void hvsi_hangup(struct tty_struct *tty)
-{
-	struct hvsi_struct *hp = tty->driver_data;
-	unsigned long flags;
-
-	pr_debug("%s\n", __func__);
-
-	spin_lock_irqsave(&hp->lock, flags);
-
-	hp->count = 0;
-	hp->n_outbuf = 0;
-	hp->tty = NULL;
-
-	spin_unlock_irqrestore(&hp->lock, flags);
-}
-
-/* called with hp->lock held */
-static void hvsi_push(struct hvsi_struct *hp)
-{
-	int n;
-
-	if (hp->n_outbuf <= 0)
-		return;
-
-	n = hvsi_put_chars(hp, hp->outbuf, hp->n_outbuf);
-	if (n > 0) {
-		/* success */
-		pr_debug("%s: wrote %i chars\n", __func__, n);
-		hp->n_outbuf = 0;
-	} else if (n == -EIO) {
-		__set_state(hp, HVSI_FSP_DIED);
-		printk(KERN_ERR "hvsi%i: service processor died\n", hp->index);
-	}
-}
-
-/* hvsi_write_worker will keep rescheduling itself until outbuf is empty */
-static void hvsi_write_worker(struct work_struct *work)
-{
-	struct hvsi_struct *hp =
-		container_of(work, struct hvsi_struct, writer.work);
-	unsigned long flags;
-#ifdef DEBUG
-	static long start_j = 0;
-
-	if (start_j == 0)
-		start_j = jiffies;
-#endif /* DEBUG */
-
-	spin_lock_irqsave(&hp->lock, flags);
-
-	pr_debug("%s: %i chars in buffer\n", __func__, hp->n_outbuf);
-
-	if (!is_open(hp)) {
-		/*
-		 * We could have a non-open connection if the service processor died
-		 * while we were busily scheduling ourselves. In that case, it could
-		 * be minutes before the service processor comes back, so only try
-		 * again once a second.
-		 */
-		schedule_delayed_work(&hp->writer, HZ);
-		goto out;
-	}
-
-	hvsi_push(hp);
-	if (hp->n_outbuf > 0)
-		schedule_delayed_work(&hp->writer, 10);
-	else {
-#ifdef DEBUG
-		pr_debug("%s: outbuf emptied after %li jiffies\n", __func__,
-				jiffies - start_j);
-		start_j = 0;
-#endif /* DEBUG */
-		wake_up_all(&hp->emptyq);
-		tty_wakeup(hp->tty);
-	}
-
-out:
-	spin_unlock_irqrestore(&hp->lock, flags);
-}
-
-static int hvsi_write_room(struct tty_struct *tty)
-{
-	struct hvsi_struct *hp = tty->driver_data;
-
-	return N_OUTBUF - hp->n_outbuf;
-}
-
-static int hvsi_chars_in_buffer(struct tty_struct *tty)
-{
-	struct hvsi_struct *hp = tty->driver_data;
-
-	return hp->n_outbuf;
-}
-
-static int hvsi_write(struct tty_struct *tty,
-		     const unsigned char *buf, int count)
-{
-	struct hvsi_struct *hp = tty->driver_data;
-	const char *source = buf;
-	unsigned long flags;
-	int total = 0;
-	int origcount = count;
-
-	spin_lock_irqsave(&hp->lock, flags);
-
-	pr_debug("%s: %i chars in buffer\n", __func__, hp->n_outbuf);
-
-	if (!is_open(hp)) {
-		/* we're either closing or not yet open; don't accept data */
-		pr_debug("%s: not open\n", __func__);
-		goto out;
-	}
-
-	/*
-	 * when the hypervisor buffer (16K) fills, data will stay in hp->outbuf
-	 * and hvsi_write_worker will be scheduled. subsequent hvsi_write() calls
-	 * will see there is no room in outbuf and return.
-	 */
-	while ((count > 0) && (hvsi_write_room(hp->tty) > 0)) {
-		int chunksize = min(count, hvsi_write_room(hp->tty));
-
-		BUG_ON(hp->n_outbuf < 0);
-		memcpy(hp->outbuf + hp->n_outbuf, source, chunksize);
-		hp->n_outbuf += chunksize;
-
-		total += chunksize;
-		source += chunksize;
-		count -= chunksize;
-		hvsi_push(hp);
-	}
-
-	if (hp->n_outbuf > 0) {
-		/*
-		 * we weren't able to write it all to the hypervisor.
-		 * schedule another push attempt.
-		 */
-		schedule_delayed_work(&hp->writer, 10);
-	}
-
-out:
-	spin_unlock_irqrestore(&hp->lock, flags);
-
-	if (total != origcount)
-		pr_debug("%s: wanted %i, only wrote %i\n", __func__, origcount,
-			total);
-
-	return total;
-}
-
-/*
- * I have never seen throttle or unthrottle called, so this little throttle
- * buffering scheme may or may not work.
- */
-static void hvsi_throttle(struct tty_struct *tty)
-{
-	struct hvsi_struct *hp = tty->driver_data;
-
-	pr_debug("%s\n", __func__);
-
-	h_vio_signal(hp->vtermno, VIO_IRQ_DISABLE);
-}
-
-static void hvsi_unthrottle(struct tty_struct *tty)
-{
-	struct hvsi_struct *hp = tty->driver_data;
-	unsigned long flags;
-	int shouldflip = 0;
-
-	pr_debug("%s\n", __func__);
-
-	spin_lock_irqsave(&hp->lock, flags);
-	if (hp->n_throttle) {
-		hvsi_send_overflow(hp);
-		shouldflip = 1;
-	}
-	spin_unlock_irqrestore(&hp->lock, flags);
-
-	if (shouldflip)
-		tty_flip_buffer_push(hp->tty);
-
-	h_vio_signal(hp->vtermno, VIO_IRQ_ENABLE);
-}
-
-static int hvsi_tiocmget(struct tty_struct *tty, struct file *file)
-{
-	struct hvsi_struct *hp = tty->driver_data;
-
-	hvsi_get_mctrl(hp);
-	return hp->mctrl;
-}
-
-static int hvsi_tiocmset(struct tty_struct *tty, struct file *file,
-		unsigned int set, unsigned int clear)
-{
-	struct hvsi_struct *hp = tty->driver_data;
-	unsigned long flags;
-	uint16_t new_mctrl;
-
-	/* we can only alter DTR */
-	clear &= TIOCM_DTR;
-	set &= TIOCM_DTR;
-
-	spin_lock_irqsave(&hp->lock, flags);
-
-	new_mctrl = (hp->mctrl & ~clear) | set;
-
-	if (hp->mctrl != new_mctrl) {
-		hvsi_set_mctrl(hp, new_mctrl);
-		hp->mctrl = new_mctrl;
-	}
-	spin_unlock_irqrestore(&hp->lock, flags);
-
-	return 0;
-}
-
-
-static const struct tty_operations hvsi_ops = {
-	.open = hvsi_open,
-	.close = hvsi_close,
-	.write = hvsi_write,
-	.hangup = hvsi_hangup,
-	.write_room = hvsi_write_room,
-	.chars_in_buffer = hvsi_chars_in_buffer,
-	.throttle = hvsi_throttle,
-	.unthrottle = hvsi_unthrottle,
-	.tiocmget = hvsi_tiocmget,
-	.tiocmset = hvsi_tiocmset,
-};
-
-static int __init hvsi_init(void)
-{
-	int i;
-
-	hvsi_driver = alloc_tty_driver(hvsi_count);
-	if (!hvsi_driver)
-		return -ENOMEM;
-
-	hvsi_driver->owner = THIS_MODULE;
-	hvsi_driver->driver_name = "hvsi";
-	hvsi_driver->name = "hvsi";
-	hvsi_driver->major = HVSI_MAJOR;
-	hvsi_driver->minor_start = HVSI_MINOR;
-	hvsi_driver->type = TTY_DRIVER_TYPE_SYSTEM;
-	hvsi_driver->init_termios = tty_std_termios;
-	hvsi_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL;
-	hvsi_driver->init_termios.c_ispeed = 9600;
-	hvsi_driver->init_termios.c_ospeed = 9600;
-	hvsi_driver->flags = TTY_DRIVER_REAL_RAW;
-	tty_set_operations(hvsi_driver, &hvsi_ops);
-
-	for (i=0; i < hvsi_count; i++) {
-		struct hvsi_struct *hp = &hvsi_ports[i];
-		int ret = 1;
-
-		ret = request_irq(hp->virq, hvsi_interrupt, IRQF_DISABLED, "hvsi", hp);
-		if (ret)
-			printk(KERN_ERR "HVSI: couldn't reserve irq 0x%x (error %i)\n",
-				hp->virq, ret);
-	}
-	hvsi_wait = wait_for_state; /* irqs active now */
-
-	if (tty_register_driver(hvsi_driver))
-		panic("Couldn't register hvsi console driver\n");
-
-	printk(KERN_DEBUG "HVSI: registered %i devices\n", hvsi_count);
-
-	return 0;
-}
-device_initcall(hvsi_init);
-
-/***** console (not tty) code: *****/
-
-static void hvsi_console_print(struct console *console, const char *buf,
-		unsigned int count)
-{
-	struct hvsi_struct *hp = &hvsi_ports[console->index];
-	char c[HVSI_MAX_OUTGOING_DATA] __ALIGNED__;
-	unsigned int i = 0, n = 0;
-	int ret, donecr = 0;
-
-	mb();
-	if (!is_open(hp))
-		return;
-
-	/*
-	 * ugh, we have to translate LF -> CRLF ourselves, in place.
-	 * copied from hvc_console.c:
-	 */
-	while (count > 0 || i > 0) {
-		if (count > 0 && i < sizeof(c)) {
-			if (buf[n] == '\n' && !donecr) {
-				c[i++] = '\r';
-				donecr = 1;
-			} else {
-				c[i++] = buf[n++];
-				donecr = 0;
-				--count;
-			}
-		} else {
-			ret = hvsi_put_chars(hp, c, i);
-			if (ret < 0)
-				i = 0;
-			i -= ret;
-		}
-	}
-}
-
-static struct tty_driver *hvsi_console_device(struct console *console,
-	int *index)
-{
-	*index = console->index;
-	return hvsi_driver;
-}
-
-static int __init hvsi_console_setup(struct console *console, char *options)
-{
-	struct hvsi_struct *hp;
-	int ret;
-
-	if (console->index < 0 || console->index >= hvsi_count)
-		return -1;
-	hp = &hvsi_ports[console->index];
-
-	/* give the FSP a chance to change the baud rate when we re-open */
-	hvsi_close_protocol(hp);
-
-	ret = hvsi_handshake(hp);
-	if (ret < 0)
-		return ret;
-
-	ret = hvsi_get_mctrl(hp);
-	if (ret < 0)
-		return ret;
-
-	ret = hvsi_set_mctrl(hp, hp->mctrl | TIOCM_DTR);
-	if (ret < 0)
-		return ret;
-
-	hp->flags |= HVSI_CONSOLE;
-
-	return 0;
-}
-
-static struct console hvsi_console = {
-	.name		= "hvsi",
-	.write		= hvsi_console_print,
-	.device		= hvsi_console_device,
-	.setup		= hvsi_console_setup,
-	.flags		= CON_PRINTBUFFER,
-	.index		= -1,
-};
-
-static int __init hvsi_console_init(void)
-{
-	struct device_node *vty;
-
-	hvsi_wait = poll_for_state; /* no irqs yet; must poll */
-
-	/* search device tree for vty nodes */
-	for (vty = of_find_compatible_node(NULL, "serial", "hvterm-protocol");
-			vty != NULL;
-			vty = of_find_compatible_node(vty, "serial", "hvterm-protocol")) {
-		struct hvsi_struct *hp;
-		const uint32_t *vtermno, *irq;
-
-		vtermno = of_get_property(vty, "reg", NULL);
-		irq = of_get_property(vty, "interrupts", NULL);
-		if (!vtermno || !irq)
-			continue;
-
-		if (hvsi_count >= MAX_NR_HVSI_CONSOLES) {
-			of_node_put(vty);
-			break;
-		}
-
-		hp = &hvsi_ports[hvsi_count];
-		INIT_DELAYED_WORK(&hp->writer, hvsi_write_worker);
-		INIT_WORK(&hp->handshaker, hvsi_handshaker);
-		init_waitqueue_head(&hp->emptyq);
-		init_waitqueue_head(&hp->stateq);
-		spin_lock_init(&hp->lock);
-		hp->index = hvsi_count;
-		hp->inbuf_end = hp->inbuf;
-		hp->state = HVSI_CLOSED;
-		hp->vtermno = *vtermno;
-		hp->virq = irq_create_mapping(NULL, irq[0]);
-		if (hp->virq == NO_IRQ) {
-			printk(KERN_ERR "%s: couldn't create irq mapping for 0x%x\n",
-				__func__, irq[0]);
-			continue;
-		}
-
-		hvsi_count++;
-	}
-
-	if (hvsi_count)
-		register_console(&hvsi_console);
-	return 0;
-}
-console_initcall(hvsi_console_init);
diff -druNp linux-libre-2.6.37-gnu1/drivers/char/hw_random/via-rng.c linux-libre-2.6.38-gnu1/drivers/char/hw_random/via-rng.c
--- linux-libre-2.6.37-gnu1/drivers/char/hw_random/via-rng.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/char/hw_random/via-rng.c	2011-03-14 21:20:32.000000000 -0400
@@ -24,6 +24,7 @@
  * warranty of any kind, whether express or implied.
  */
 
+#include <crypto/padlock.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/hw_random.h>
@@ -34,7 +35,6 @@
 #include <asm/i387.h>
 
 
-#define PFX	KBUILD_MODNAME ": "
 
 
 enum {
@@ -81,8 +81,7 @@ static inline u32 xstore(u32 *addr, u32
 	ts_state = irq_ts_save();
 
 	asm(".byte 0x0F,0xA7,0xC0 /* xstore %%edi (addr=%0) */"
-		:"=m"(*addr), "=a"(eax_out)
-		:"D"(addr), "d"(edx_in));
+		: "=m" (*addr), "=a" (eax_out), "+d" (edx_in), "+D" (addr));
 
 	irq_ts_restore(ts_state);
 	return eax_out;
@@ -90,8 +89,10 @@ static inline u32 xstore(u32 *addr, u32
 
 static int via_rng_data_present(struct hwrng *rng, int wait)
 {
+	char buf[16 + PADLOCK_ALIGNMENT - STACK_ALIGN] __attribute__
+		((aligned(STACK_ALIGN)));
+	u32 *via_rng_datum = (u32 *)PTR_ALIGN(&buf[0], PADLOCK_ALIGNMENT);
 	u32 bytes_out;
-	u32 *via_rng_datum = (u32 *)(&rng->priv);
 	int i;
 
 	/* We choose the recommended 1-byte-per-instruction RNG rate,
@@ -115,6 +116,7 @@ static int via_rng_data_present(struct h
 			break;
 		udelay(10);
 	}
+	rng->priv = *via_rng_datum;
 	return bytes_out ? 1 : 0;
 }
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/char/ip2/ip2main.c linux-libre-2.6.38-gnu1/drivers/char/ip2/ip2main.c
--- linux-libre-2.6.37-gnu1/drivers/char/ip2/ip2main.c	2013-05-03 03:54:27.000000000 -0400
+++ linux-libre-2.6.38-gnu1/drivers/char/ip2/ip2main.c	2013-05-03 01:53:24.000000000 -0400
@@ -3224,7 +3224,7 @@ ip2trace (unsigned short pn, unsigned ch
 
 MODULE_LICENSE("GPL");
 
-static struct pci_device_id ip2main_pci_tbl[] __devinitdata = {
+static struct pci_device_id ip2main_pci_tbl[] __devinitdata __used = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_COMPUTONE, PCI_DEVICE_ID_COMPUTONE_IP2EX) },
 	{ }
 };
diff -druNp linux-libre-2.6.37-gnu1/drivers/char/ipmi/ipmi_msghandler.c linux-libre-2.6.38-gnu1/drivers/char/ipmi/ipmi_msghandler.c
--- linux-libre-2.6.37-gnu1/drivers/char/ipmi/ipmi_msghandler.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/char/ipmi/ipmi_msghandler.c	2011-03-14 21:20:32.000000000 -0400
@@ -970,6 +970,33 @@ out_kfree:
 }
 EXPORT_SYMBOL(ipmi_create_user);
 
+int ipmi_get_smi_info(int if_num, struct ipmi_smi_info *data)
+{
+	int           rv = 0;
+	ipmi_smi_t    intf;
+	struct ipmi_smi_handlers *handlers;
+
+	mutex_lock(&ipmi_interfaces_mutex);
+	list_for_each_entry_rcu(intf, &ipmi_interfaces, link) {
+		if (intf->intf_num == if_num)
+			goto found;
+	}
+	/* Not found, return an error */
+	rv = -EINVAL;
+	mutex_unlock(&ipmi_interfaces_mutex);
+	return rv;
+
+found:
+	handlers = intf->handlers;
+	rv = -ENOSYS;
+	if (handlers->get_smi_info)
+		rv = handlers->get_smi_info(intf->send_info, data);
+	mutex_unlock(&ipmi_interfaces_mutex);
+
+	return rv;
+}
+EXPORT_SYMBOL(ipmi_get_smi_info);
+
 static void free_user(struct kref *ref)
 {
 	ipmi_user_t user = container_of(ref, struct ipmi_user, refcount);
diff -druNp linux-libre-2.6.37-gnu1/drivers/char/ipmi/ipmi_si_intf.c linux-libre-2.6.38-gnu1/drivers/char/ipmi/ipmi_si_intf.c
--- linux-libre-2.6.37-gnu1/drivers/char/ipmi/ipmi_si_intf.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/char/ipmi/ipmi_si_intf.c	2011-03-14 21:20:32.000000000 -0400
@@ -57,6 +57,7 @@
 #include <asm/irq.h>
 #include <linux/interrupt.h>
 #include <linux/rcupdate.h>
+#include <linux/ipmi.h>
 #include <linux/ipmi_smi.h>
 #include <asm/io.h>
 #include "ipmi_si_sm.h"
@@ -69,6 +70,8 @@
 #ifdef CONFIG_PPC_OF
 #include <linux/of_device.h>
 #include <linux/of_platform.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
 #endif
 
 #define PFX "ipmi_si: "
@@ -107,10 +110,6 @@ enum si_type {
 };
 static char *si_to_str[] = { "kcs", "smic", "bt" };
 
-enum ipmi_addr_src {
-	SI_INVALID = 0, SI_HOTMOD, SI_HARDCODED, SI_SPMI, SI_ACPI, SI_SMBIOS,
-	SI_PCI,	SI_DEVICETREE, SI_DEFAULT
-};
 static char *ipmi_addr_src_to_str[] = { NULL, "hotmod", "hardcoded", "SPMI",
 					"ACPI", "SMBIOS", "PCI",
 					"device-tree", "default" };
@@ -291,6 +290,7 @@ struct smi_info {
 	struct task_struct *thread;
 
 	struct list_head link;
+	union ipmi_smi_info_union addr_info;
 };
 
 #define smi_inc_stat(smi, stat) \
@@ -320,6 +320,7 @@ static int unload_when_empty = 1;
 static int add_smi(struct smi_info *smi);
 static int try_smi_init(struct smi_info *smi);
 static void cleanup_one_si(struct smi_info *to_clean);
+static void cleanup_ipmi_si(void);
 
 static ATOMIC_NOTIFIER_HEAD(xaction_notifier_list);
 static int register_xaction_notifier(struct notifier_block *nb)
@@ -899,6 +900,14 @@ static void sender(void                *
 	printk("**Enqueue: %d.%9.9d\n", t.tv_sec, t.tv_usec);
 #endif
 
+	/*
+	 * last_timeout_jiffies is updated here to avoid
+	 * smi_timeout() handler passing very large time_diff
+	 * value to smi_event_handler() that causes
+	 * the send command to abort.
+	 */
+	smi_info->last_timeout_jiffies = jiffies;
+
 	mod_timer(&smi_info->si_timer, jiffies + SI_TIMEOUT_JIFFIES);
 
 	if (smi_info->thread)
@@ -1186,6 +1195,18 @@ static int smi_start_processing(void
 	return 0;
 }
 
+static int get_smi_info(void *send_info, struct ipmi_smi_info *data)
+{
+	struct smi_info *smi = send_info;
+
+	data->addr_src = smi->addr_source;
+	data->dev = smi->dev;
+	data->addr_info = smi->addr_info;
+	get_device(smi->dev);
+
+	return 0;
+}
+
 static void set_maintenance_mode(void *send_info, int enable)
 {
 	struct smi_info   *smi_info = send_info;
@@ -1197,6 +1218,7 @@ static void set_maintenance_mode(void *s
 static struct ipmi_smi_handlers handlers = {
 	.owner                  = THIS_MODULE,
 	.start_processing       = smi_start_processing,
+	.get_smi_info		= get_smi_info,
 	.sender			= sender,
 	.request_events		= request_events,
 	.set_maintenance_mode   = set_maintenance_mode,
@@ -1928,7 +1950,8 @@ static void __devinit hardcode_find_bmc(
 static int acpi_failure;
 
 /* For GPE-type interrupts. */
-static u32 ipmi_acpi_gpe(void *context)
+static u32 ipmi_acpi_gpe(acpi_handle gpe_device,
+	u32 gpe_number, void *context)
 {
 	struct smi_info *smi_info = context;
 	unsigned long   flags;
@@ -2156,6 +2179,7 @@ static int __devinit ipmi_pnp_probe(stru
 	printk(KERN_INFO PFX "probing via ACPI\n");
 
 	handle = acpi_dev->handle;
+	info->addr_info.acpi_info.acpi_handle = handle;
 
 	/* _IFT tells us the interface type: KCS, BT, etc */
 	status = acpi_evaluate_integer(handle, "_IFT", NULL, &tmp);
@@ -2546,7 +2570,7 @@ static int __devinit ipmi_of_probe(struc
 {
 	struct smi_info *info;
 	struct resource resource;
-	const int *regsize, *regspacing, *regshift;
+	const __be32 *regsize, *regspacing, *regshift;
 	struct device_node *np = dev->dev.of_node;
 	int ret;
 	int proplen;
@@ -2599,9 +2623,9 @@ static int __devinit ipmi_of_probe(struc
 
 	info->io.addr_data	= resource.start;
 
-	info->io.regsize	= regsize ? *regsize : DEFAULT_REGSIZE;
-	info->io.regspacing	= regspacing ? *regspacing : DEFAULT_REGSPACING;
-	info->io.regshift	= regshift ? *regshift : 0;
+	info->io.regsize	= regsize ? be32_to_cpup(regsize) : DEFAULT_REGSIZE;
+	info->io.regspacing	= regspacing ? be32_to_cpup(regspacing) : DEFAULT_REGSPACING;
+	info->io.regshift	= regshift ? be32_to_cpup(regshift) : 0;
 
 	info->irq		= irq_of_parse_and_map(dev->dev.of_node, 0);
 	info->dev		= &dev->dev;
@@ -3435,16 +3459,7 @@ static int __devinit init_ipmi_si(void)
 	mutex_lock(&smi_infos_lock);
 	if (unload_when_empty && list_empty(&smi_infos)) {
 		mutex_unlock(&smi_infos_lock);
-#ifdef CONFIG_PCI
-		if (pci_registered)
-			pci_unregister_driver(&ipmi_pci_driver);
-#endif
-
-#ifdef CONFIG_PPC_OF
-		if (of_registered)
-			of_unregister_platform_driver(&ipmi_of_platform_driver);
-#endif
-		driver_unregister(&ipmi_driver.driver);
+		cleanup_ipmi_si();
 		printk(KERN_WARNING PFX
 		       "Unable to find any System Interface(s)\n");
 		return -ENODEV;
diff -druNp linux-libre-2.6.37-gnu1/drivers/char/ipmi/ipmi_watchdog.c linux-libre-2.6.38-gnu1/drivers/char/ipmi/ipmi_watchdog.c
--- linux-libre-2.6.37-gnu1/drivers/char/ipmi/ipmi_watchdog.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/char/ipmi/ipmi_watchdog.c	2011-03-14 21:20:32.000000000 -0400
@@ -1081,7 +1081,7 @@ ipmi_nmi(struct notifier_block *self, un
 {
 	struct die_args *args = data;
 
-	if (val != DIE_NMI)
+	if (val != DIE_NMIUNKNOWN)
 		return NOTIFY_OK;
 
 	/* Hack, if it's a memory or I/O error, ignore it. */
diff -druNp linux-libre-2.6.37-gnu1/drivers/char/Kconfig linux-libre-2.6.38-gnu1/drivers/char/Kconfig
--- linux-libre-2.6.37-gnu1/drivers/char/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/char/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
 menu "Character devices"
 
 config VT
-	bool "Virtual terminal" if EMBEDDED
+	bool "Virtual terminal" if EXPERT
 	depends on !S390
 	select INPUT
 	default y
@@ -39,13 +39,13 @@ config VT
 config CONSOLE_TRANSLATIONS
 	depends on VT
 	default y
-	bool "Enable character translations in console" if EMBEDDED
+	bool "Enable character translations in console" if EXPERT
 	---help---
 	  This enables support for font mapping and Unicode translation
 	  on virtual consoles.
 
 config VT_CONSOLE
-	bool "Support for console on virtual terminal" if EMBEDDED
+	bool "Support for console on virtual terminal" if EXPERT
 	depends on VT
 	default y
 	---help---
@@ -426,10 +426,10 @@ config SGI_MBCS
          If you have an SGI Altix with an attached SABrick
          say Y or M here, otherwise say N.
 
-source "drivers/serial/Kconfig"
+source "drivers/tty/serial/Kconfig"
 
 config UNIX98_PTYS
-	bool "Unix98 PTY support" if EMBEDDED
+	bool "Unix98 PTY support" if EXPERT
 	default y
 	---help---
 	  A pseudo terminal (PTY) is a software device consisting of two
@@ -495,7 +495,7 @@ config LEGACY_PTY_COUNT
 
 config TTY_PRINTK
 	bool "TTY driver to output user messages via printk"
-	depends on EMBEDDED
+	depends on EXPERT
 	default n
 	---help---
 	  If you say Y here, the support for writing user messages (i.e.
@@ -682,6 +682,15 @@ config HVC_UDBG
        select HVC_DRIVER
        default n
 
+config HVC_DCC
+       bool "ARM JTAG DCC console"
+       depends on ARM
+       select HVC_DRIVER
+       help
+         This console uses the JTAG DCC on ARM to create a console under the HVC
+	 driver. This console is used through a JTAG only on ARM. If you don't have
+	 a JTAG then you probably don't want this option.
+
 config VIRTIO_CONSOLE
 	tristate "Virtio console"
 	depends on VIRTIO
@@ -1038,15 +1047,6 @@ config NSC_GPIO
 	  pc8736x_gpio drivers.  If those drivers are built as
 	  modules, this one will be too, named nsc_gpio
 
-config CS5535_GPIO
-	tristate "AMD CS5535/CS5536 GPIO (Geode Companion Device)"
-	depends on X86_32
-	help
-	  Give userspace access to the GPIO pins on the AMD CS5535 and
-	  CS5536 Geode companion devices.
-
-	  If compiled as a module, it will be called cs5535_gpio.
-
 config RAW_DRIVER
 	tristate "RAW driver (/dev/raw/rawN)"
 	depends on BLOCK
diff -druNp linux-libre-2.6.37-gnu1/drivers/char/Makefile linux-libre-2.6.38-gnu1/drivers/char/Makefile
--- linux-libre-2.6.37-gnu1/drivers/char/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/char/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -30,16 +30,6 @@ obj-$(CONFIG_SYNCLINK_GT)	+= synclink_gt
 obj-$(CONFIG_AMIGA_BUILTIN_SERIAL) += amiserial.o
 obj-$(CONFIG_SX)		+= sx.o generic_serial.o
 obj-$(CONFIG_RIO)		+= rio/ generic_serial.o
-obj-$(CONFIG_HVC_CONSOLE)	+= hvc_vio.o hvsi.o
-obj-$(CONFIG_HVC_ISERIES)	+= hvc_iseries.o
-obj-$(CONFIG_HVC_RTAS)		+= hvc_rtas.o
-obj-$(CONFIG_HVC_TILE)		+= hvc_tile.o
-obj-$(CONFIG_HVC_BEAT)		+= hvc_beat.o
-obj-$(CONFIG_HVC_DRIVER)	+= hvc_console.o
-obj-$(CONFIG_HVC_IRQ)		+= hvc_irq.o
-obj-$(CONFIG_HVC_XEN)		+= hvc_xen.o
-obj-$(CONFIG_HVC_IUCV)		+= hvc_iucv.o
-obj-$(CONFIG_HVC_UDBG)		+= hvc_udbg.o
 obj-$(CONFIG_VIRTIO_CONSOLE)	+= virtio_console.o
 obj-$(CONFIG_RAW_DRIVER)	+= raw.o
 obj-$(CONFIG_SGI_SNSC)		+= snsc.o snsc_event.o
@@ -47,7 +37,6 @@ obj-$(CONFIG_MSPEC)		+= mspec.o
 obj-$(CONFIG_MMTIMER)		+= mmtimer.o
 obj-$(CONFIG_UV_MMTIMER)	+= uv_mmtimer.o
 obj-$(CONFIG_VIOTAPE)		+= viotape.o
-obj-$(CONFIG_HVCS)		+= hvcs.o
 obj-$(CONFIG_IBM_BSR)		+= bsr.o
 obj-$(CONFIG_SGI_MBCS)		+= mbcs.o
 obj-$(CONFIG_BRIQ_PANEL)	+= briq_panel.o
@@ -81,7 +70,6 @@ obj-$(CONFIG_NWFLASH)		+= nwflash.o
 obj-$(CONFIG_SCx200_GPIO)	+= scx200_gpio.o
 obj-$(CONFIG_PC8736x_GPIO)	+= pc8736x_gpio.o
 obj-$(CONFIG_NSC_GPIO)		+= nsc_gpio.o
-obj-$(CONFIG_CS5535_GPIO)	+= cs5535_gpio.o
 obj-$(CONFIG_GPIO_TB0219)	+= tb0219.o
 obj-$(CONFIG_TELCLOCK)		+= tlclk.o
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/char/pcmcia/cm4000_cs.c linux-libre-2.6.38-gnu1/drivers/char/pcmcia/cm4000_cs.c
--- linux-libre-2.6.37-gnu1/drivers/char/pcmcia/cm4000_cs.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/char/pcmcia/cm4000_cs.c	2011-03-14 21:20:32.000000000 -0400
@@ -830,8 +830,7 @@ static void monitor_card(unsigned long p
 			    test_bit(IS_ANY_T1, &dev->flags))) {
 				DEBUGP(4, dev, "Perform AUTOPPS\n");
 				set_bit(IS_AUTOPPS_ACT, &dev->flags);
-				ptsreq.protocol = ptsreq.protocol =
-				    (0x01 << dev->proto);
+				ptsreq.protocol = (0x01 << dev->proto);
 				ptsreq.flags = 0x01;
 				ptsreq.pts1 = 0x00;
 				ptsreq.pts2 = 0x00;
diff -druNp linux-libre-2.6.37-gnu1/drivers/char/pcmcia/ipwireless/hardware.c linux-libre-2.6.38-gnu1/drivers/char/pcmcia/ipwireless/hardware.c
--- linux-libre-2.6.37-gnu1/drivers/char/pcmcia/ipwireless/hardware.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/char/pcmcia/ipwireless/hardware.c	2011-03-14 21:20:32.000000000 -0400
@@ -1729,7 +1729,7 @@ void ipwireless_hardware_free(struct ipw
 
 	ipwireless_stop_interrupts(hw);
 
-	flush_scheduled_work();
+	flush_work_sync(&hw->work_rx);
 
 	for (i = 0; i < NL_NUM_OF_ADDRESSES; i++)
 		if (hw->packet_assembler[i] != NULL)
diff -druNp linux-libre-2.6.37-gnu1/drivers/char/pcmcia/ipwireless/main.c linux-libre-2.6.38-gnu1/drivers/char/pcmcia/ipwireless/main.c
--- linux-libre-2.6.37-gnu1/drivers/char/pcmcia/ipwireless/main.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/char/pcmcia/ipwireless/main.c	2011-03-14 21:20:32.000000000 -0400
@@ -78,7 +78,6 @@ static void signalled_reboot_callback(vo
 static int ipwireless_probe(struct pcmcia_device *p_dev, void *priv_data)
 {
 	struct ipw_dev *ipw = priv_data;
-	struct resource *io_resource;
 	int ret;
 
 	p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
@@ -92,9 +91,12 @@ static int ipwireless_probe(struct pcmci
 	if (ret)
 		return ret;
 
-	io_resource = request_region(p_dev->resource[0]->start,
-				resource_size(p_dev->resource[0]),
-				IPWIRELESS_PCCARD_NAME);
+	if (!request_region(p_dev->resource[0]->start,
+			    resource_size(p_dev->resource[0]),
+			    IPWIRELESS_PCCARD_NAME)) {
+		ret = -EBUSY;
+		goto exit;
+	}
 
 	p_dev->resource[2]->flags |=
 		WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_CM | WIN_ENABLE;
@@ -105,22 +107,25 @@ static int ipwireless_probe(struct pcmci
 
 	ret = pcmcia_map_mem_page(p_dev, p_dev->resource[2], p_dev->card_addr);
 	if (ret != 0)
-		goto exit2;
+		goto exit1;
 
 	ipw->is_v2_card = resource_size(p_dev->resource[2]) == 0x100;
 
-	ipw->attr_memory = ioremap(p_dev->resource[2]->start,
+	ipw->common_memory = ioremap(p_dev->resource[2]->start,
 				resource_size(p_dev->resource[2]));
-	request_mem_region(p_dev->resource[2]->start,
-			resource_size(p_dev->resource[2]),
-			IPWIRELESS_PCCARD_NAME);
+	if (!request_mem_region(p_dev->resource[2]->start,
+				resource_size(p_dev->resource[2]),
+				IPWIRELESS_PCCARD_NAME)) {
+		ret = -EBUSY;
+		goto exit2;
+	}
 
 	p_dev->resource[3]->flags |= WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_AM |
 					WIN_ENABLE;
 	p_dev->resource[3]->end = 0; /* this used to be 0x1000 */
 	ret = pcmcia_request_window(p_dev, p_dev->resource[3], 0);
 	if (ret != 0)
-		goto exit2;
+		goto exit3;
 
 	ret = pcmcia_map_mem_page(p_dev, p_dev->resource[3], 0);
 	if (ret != 0)
@@ -128,23 +133,28 @@ static int ipwireless_probe(struct pcmci
 
 	ipw->attr_memory = ioremap(p_dev->resource[3]->start,
 				resource_size(p_dev->resource[3]));
-	request_mem_region(p_dev->resource[3]->start,
-			resource_size(p_dev->resource[3]),
-			IPWIRELESS_PCCARD_NAME);
+	if (!request_mem_region(p_dev->resource[3]->start,
+				resource_size(p_dev->resource[3]),
+				IPWIRELESS_PCCARD_NAME)) {
+		ret = -EBUSY;
+		goto exit4;
+	}
 
 	return 0;
 
+exit4:
+	iounmap(ipw->attr_memory);
 exit3:
+	release_mem_region(p_dev->resource[2]->start,
+			resource_size(p_dev->resource[2]));
 exit2:
-	if (ipw->common_memory) {
-		release_mem_region(p_dev->resource[2]->start,
-				resource_size(p_dev->resource[2]));
-		iounmap(ipw->common_memory);
-	}
+	iounmap(ipw->common_memory);
 exit1:
-	release_resource(io_resource);
+	release_region(p_dev->resource[0]->start,
+		       resource_size(p_dev->resource[0]));
+exit:
 	pcmcia_disable_device(p_dev);
-	return -1;
+	return ret;
 }
 
 static int config_ipwireless(struct ipw_dev *ipw)
@@ -219,6 +229,8 @@ exit:
 
 static void release_ipwireless(struct ipw_dev *ipw)
 {
+	release_region(ipw->link->resource[0]->start,
+		       resource_size(ipw->link->resource[0]));
 	if (ipw->common_memory) {
 		release_mem_region(ipw->link->resource[2]->start,
 				resource_size(ipw->link->resource[2]));
diff -druNp linux-libre-2.6.37-gnu1/drivers/char/pcmcia/ipwireless/network.c linux-libre-2.6.38-gnu1/drivers/char/pcmcia/ipwireless/network.c
--- linux-libre-2.6.37-gnu1/drivers/char/pcmcia/ipwireless/network.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/char/pcmcia/ipwireless/network.c	2011-03-14 21:20:32.000000000 -0400
@@ -430,7 +430,8 @@ void ipwireless_network_free(struct ipw_
 	network->shutting_down = 1;
 
 	ipwireless_ppp_close(network);
-	flush_scheduled_work();
+	flush_work_sync(&network->work_go_online);
+	flush_work_sync(&network->work_go_offline);
 
 	ipwireless_stop_interrupts(network->hardware);
 	ipwireless_associate_network(network->hardware, NULL);
diff -druNp linux-libre-2.6.37-gnu1/drivers/char/pcmcia/ipwireless/tty.c linux-libre-2.6.38-gnu1/drivers/char/pcmcia/ipwireless/tty.c
--- linux-libre-2.6.37-gnu1/drivers/char/pcmcia/ipwireless/tty.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/char/pcmcia/ipwireless/tty.c	2011-03-14 21:20:32.000000000 -0400
@@ -577,7 +577,7 @@ void ipwireless_tty_free(struct ipw_tty
 				mutex_unlock(&ttyj->ipw_tty_mutex);
 				tty_hangup(ttyj->linux_tty);
 				/* Wait till the tty_hangup has completed */
-				flush_scheduled_work();
+				flush_work_sync(&ttyj->linux_tty->hangup_work);
 				/* FIXME: Exactly how is the tty object locked here
 				   against a parallel ioctl etc */
 				mutex_lock(&ttyj->ipw_tty_mutex);
diff -druNp linux-libre-2.6.37-gnu1/drivers/char/ramoops.c linux-libre-2.6.38-gnu1/drivers/char/ramoops.c
--- linux-libre-2.6.37-gnu1/drivers/char/ramoops.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/char/ramoops.c	2011-03-14 21:20:32.000000000 -0400
@@ -30,7 +30,7 @@
 
 #define RAMOOPS_KERNMSG_HDR "===="
 
-#define RECORD_SIZE 4096
+#define RECORD_SIZE 4096UL
 
 static ulong mem_address;
 module_param(mem_address, ulong, 0400);
@@ -68,11 +68,16 @@ static void ramoops_do_dump(struct kmsg_
 	char *buf, *buf_orig;
 	struct timeval timestamp;
 
+	if (reason != KMSG_DUMP_OOPS &&
+	    reason != KMSG_DUMP_PANIC &&
+	    reason != KMSG_DUMP_KEXEC)
+		return;
+
 	/* Only dump oopses if dump_oops is set */
 	if (reason == KMSG_DUMP_OOPS && !dump_oops)
 		return;
 
-	buf = (char *)(cxt->virt_addr + (cxt->count * RECORD_SIZE));
+	buf = cxt->virt_addr + (cxt->count * RECORD_SIZE);
 	buf_orig = buf;
 
 	memset(buf, '\0', RECORD_SIZE);
@@ -83,8 +88,8 @@ static void ramoops_do_dump(struct kmsg_
 	buf += res;
 
 	hdr_size = buf - buf_orig;
-	l2_cpy = min(l2, (unsigned long)(RECORD_SIZE - hdr_size));
-	l1_cpy = min(l1, (unsigned long)(RECORD_SIZE - hdr_size) - l2_cpy);
+	l2_cpy = min(l2, RECORD_SIZE - hdr_size);
+	l1_cpy = min(l1, RECORD_SIZE - hdr_size - l2_cpy);
 
 	s2_start = l2 - l2_cpy;
 	s1_start = l1 - l1_cpy;
diff -druNp linux-libre-2.6.37-gnu1/drivers/char/random.c linux-libre-2.6.38-gnu1/drivers/char/random.c
--- linux-libre-2.6.37-gnu1/drivers/char/random.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/char/random.c	2011-03-14 21:20:32.000000000 -0400
@@ -626,7 +626,7 @@ static void add_timer_randomness(struct
 	preempt_disable();
 	/* if over the trickle threshold, use only 1 in 4096 samples */
 	if (input_pool.entropy_count > trickle_thresh &&
-	    (__get_cpu_var(trickle_count)++ & 0xfff))
+	    ((__this_cpu_inc_return(trickle_count) - 1) & 0xfff))
 		goto out;
 
 	sample.jiffies = jiffies;
diff -druNp linux-libre-2.6.37-gnu1/drivers/char/raw.c linux-libre-2.6.38-gnu1/drivers/char/raw.c
--- linux-libre-2.6.37-gnu1/drivers/char/raw.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/char/raw.c	2011-03-14 21:20:32.000000000 -0400
@@ -65,15 +65,12 @@ static int raw_open(struct inode *inode,
 	if (!bdev)
 		goto out;
 	igrab(bdev->bd_inode);
-	err = blkdev_get(bdev, filp->f_mode);
+	err = blkdev_get(bdev, filp->f_mode | FMODE_EXCL, raw_open);
 	if (err)
 		goto out;
-	err = bd_claim(bdev, raw_open);
-	if (err)
-		goto out1;
 	err = set_blocksize(bdev, bdev_logical_block_size(bdev));
 	if (err)
-		goto out2;
+		goto out1;
 	filp->f_flags |= O_DIRECT;
 	filp->f_mapping = bdev->bd_inode->i_mapping;
 	if (++raw_devices[minor].inuse == 1)
@@ -83,10 +80,8 @@ static int raw_open(struct inode *inode,
 	mutex_unlock(&raw_mutex);
 	return 0;
 
-out2:
-	bd_release(bdev);
 out1:
-	blkdev_put(bdev, filp->f_mode);
+	blkdev_put(bdev, filp->f_mode | FMODE_EXCL);
 out:
 	mutex_unlock(&raw_mutex);
 	return err;
@@ -110,8 +105,7 @@ static int raw_release(struct inode *ino
 	}
 	mutex_unlock(&raw_mutex);
 
-	bd_release(bdev);
-	blkdev_put(bdev, filp->f_mode);
+	blkdev_put(bdev, filp->f_mode | FMODE_EXCL);
 	return 0;
 }
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/char/rocket.c linux-libre-2.6.38-gnu1/drivers/char/rocket.c
--- linux-libre-2.6.37-gnu1/drivers/char/rocket.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/char/rocket.c	2011-03-14 21:20:32.000000000 -0400
@@ -1764,7 +1764,7 @@ static void rp_flush_buffer(struct tty_s
 
 #ifdef CONFIG_PCI
 
-static struct pci_device_id __devinitdata rocket_pci_ids[] = {
+static struct pci_device_id __devinitdata __used rocket_pci_ids[] = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_RP, PCI_ANY_ID) },
 	{ }
 };
diff -druNp linux-libre-2.6.37-gnu1/drivers/char/snsc.h linux-libre-2.6.38-gnu1/drivers/char/snsc.h
--- linux-libre-2.6.37-gnu1/drivers/char/snsc.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/char/snsc.h	2011-03-14 21:20:32.000000000 -0400
@@ -19,7 +19,6 @@
 #include <linux/types.h>
 #include <linux/spinlock.h>
 #include <linux/wait.h>
-#include <linux/kobject.h>
 #include <linux/fs.h>
 #include <linux/cdev.h>
 #include <linux/semaphore.h>
diff -druNp linux-libre-2.6.37-gnu1/drivers/char/sonypi.c linux-libre-2.6.38-gnu1/drivers/char/sonypi.c
--- linux-libre-2.6.37-gnu1/drivers/char/sonypi.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/char/sonypi.c	2011-03-14 21:20:32.000000000 -0400
@@ -1434,7 +1434,7 @@ static int __devexit sonypi_remove(struc
 	sonypi_disable();
 
 	synchronize_irq(sonypi_device.irq);
-	flush_scheduled_work();
+	flush_work_sync(&sonypi_device.input_work);
 
 	if (useinput) {
 		input_unregister_device(sonypi_device.input_key_dev);
diff -druNp linux-libre-2.6.37-gnu1/drivers/char/specialix.c linux-libre-2.6.38-gnu1/drivers/char/specialix.c
--- linux-libre-2.6.37-gnu1/drivers/char/specialix.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/char/specialix.c	2011-03-14 21:20:32.000000000 -0400
@@ -2355,7 +2355,7 @@ static void __exit specialix_exit_module
 	func_exit();
 }
 
-static struct pci_device_id specialx_pci_tbl[] __devinitdata = {
+static struct pci_device_id specialx_pci_tbl[] __devinitdata __used = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_SPECIALIX_IO8) },
 	{ }
 };
diff -druNp linux-libre-2.6.37-gnu1/drivers/char/tpm/tpm.c linux-libre-2.6.38-gnu1/drivers/char/tpm/tpm.c
--- linux-libre-2.6.37-gnu1/drivers/char/tpm/tpm.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/char/tpm/tpm.c	2011-03-14 21:20:32.000000000 -0400
@@ -736,7 +736,7 @@ int tpm_pcr_read(u32 chip_num, int pcr_i
 	if (chip == NULL)
 		return -ENODEV;
 	rc = __tpm_pcr_read(chip, pcr_idx, res_buf);
-	module_put(chip->dev->driver->owner);
+	tpm_chip_put(chip);
 	return rc;
 }
 EXPORT_SYMBOL_GPL(tpm_pcr_read);
@@ -775,11 +775,27 @@ int tpm_pcr_extend(u32 chip_num, int pcr
 	rc = transmit_cmd(chip, &cmd, EXTEND_PCR_RESULT_SIZE,
 			  "attempting extend a PCR value");
 
-	module_put(chip->dev->driver->owner);
+	tpm_chip_put(chip);
 	return rc;
 }
 EXPORT_SYMBOL_GPL(tpm_pcr_extend);
 
+int tpm_send(u32 chip_num, void *cmd, size_t buflen)
+{
+	struct tpm_chip *chip;
+	int rc;
+
+	chip = tpm_chip_find_get(chip_num);
+	if (chip == NULL)
+		return -ENODEV;
+
+	rc = transmit_cmd(chip, cmd, buflen, "attempting tpm_cmd");
+
+	tpm_chip_put(chip);
+	return rc;
+}
+EXPORT_SYMBOL_GPL(tpm_send);
+
 ssize_t tpm_show_pcrs(struct device *dev, struct device_attribute *attr,
 		      char *buf)
 {
@@ -986,7 +1002,7 @@ int tpm_release(struct inode *inode, str
 	struct tpm_chip *chip = file->private_data;
 
 	del_singleshot_timer_sync(&chip->user_read_timer);
-	flush_scheduled_work();
+	flush_work_sync(&chip->work);
 	file->private_data = NULL;
 	atomic_set(&chip->data_pending, 0);
 	kfree(chip->data_buffer);
@@ -1038,7 +1054,7 @@ ssize_t tpm_read(struct file *file, char
 	ssize_t ret_size;
 
 	del_singleshot_timer_sync(&chip->user_read_timer);
-	flush_scheduled_work();
+	flush_work_sync(&chip->work);
 	ret_size = atomic_read(&chip->data_pending);
 	atomic_set(&chip->data_pending, 0);
 	if (ret_size > 0) {	/* relay data */
diff -druNp linux-libre-2.6.37-gnu1/drivers/char/tpm/tpm.h linux-libre-2.6.38-gnu1/drivers/char/tpm/tpm.h
--- linux-libre-2.6.37-gnu1/drivers/char/tpm/tpm.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/char/tpm/tpm.h	2011-03-14 21:20:32.000000000 -0400
@@ -113,6 +113,11 @@ struct tpm_chip {
 
 #define to_tpm_chip(n) container_of(n, struct tpm_chip, vendor)
 
+static inline void tpm_chip_put(struct tpm_chip *chip)
+{
+	module_put(chip->dev->driver->owner);
+}
+
 static inline int tpm_read_index(int base, int index)
 {
 	outb(index, base);
diff -druNp linux-libre-2.6.37-gnu1/drivers/char/tpm/tpm_tis.c linux-libre-2.6.38-gnu1/drivers/char/tpm/tpm_tis.c
--- linux-libre-2.6.37-gnu1/drivers/char/tpm/tpm_tis.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/char/tpm/tpm_tis.c	2011-03-14 21:20:32.000000000 -0400
@@ -493,9 +493,6 @@ static int tpm_tis_init(struct device *d
 		 "1.2 TPM (device-id 0x%X, rev-id %d)\n",
 		 vendor >> 16, ioread8(chip->vendor.iobase + TPM_RID(0)));
 
-	if (is_itpm(to_pnp_dev(dev)))
-		itpm = 1;
-
 	if (itpm)
 		dev_info(dev, "Intel iTPM workaround enabled\n");
 
@@ -637,6 +634,9 @@ static int __devinit tpm_tis_pnp_init(st
 	else
 		interrupts = 0;
 
+	if (is_itpm(pnp_dev))
+		itpm = 1;
+
 	return tpm_tis_init(&pnp_dev->dev, start, len, irq);
 }
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/char/virtio_console.c linux-libre-2.6.38-gnu1/drivers/char/virtio_console.c
--- linux-libre-2.6.37-gnu1/drivers/char/virtio_console.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/char/virtio_console.c	2011-03-14 21:20:32.000000000 -0400
@@ -1,6 +1,7 @@
 /*
  * Copyright (C) 2006, 2007, 2009 Rusty Russell, IBM Corporation
- * Copyright (C) 2009, 2010 Red Hat, Inc.
+ * Copyright (C) 2009, 2010, 2011 Red Hat, Inc.
+ * Copyright (C) 2009, 2010, 2011 Amit Shah <amit.shah@redhat.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
@@ -31,7 +32,7 @@
 #include <linux/virtio_console.h>
 #include <linux/wait.h>
 #include <linux/workqueue.h>
-#include "hvc_console.h"
+#include "../tty/hvc/hvc_console.h"
 
 /*
  * This is a global struct for storing common data for all the devices
@@ -387,6 +388,10 @@ static void discard_port_data(struct por
 	unsigned int len;
 	int ret;
 
+	if (!port->portdev) {
+		/* Device has been unplugged.  vqs are already gone. */
+		return;
+	}
 	vq = port->in_vq;
 	if (port->inbuf)
 		buf = port->inbuf;
@@ -469,6 +474,10 @@ static void reclaim_consumed_buffers(str
 	void *buf;
 	unsigned int len;
 
+	if (!port->portdev) {
+		/* Device has been unplugged.  vqs are already gone. */
+		return;
+	}
 	while ((buf = virtqueue_get_buf(port->out_vq, &len))) {
 		kfree(buf);
 		port->outvq_full = false;
@@ -1462,6 +1471,17 @@ static void control_work_handler(struct
 	spin_unlock(&portdev->cvq_lock);
 }
 
+static void out_intr(struct virtqueue *vq)
+{
+	struct port *port;
+
+	port = find_port_by_vq(vq->vdev->priv, vq);
+	if (!port)
+		return;
+
+	wake_up_interruptible(&port->waitqueue);
+}
+
 static void in_intr(struct virtqueue *vq)
 {
 	struct port *port;
@@ -1566,7 +1586,7 @@ static int init_vqs(struct ports_device
 	 */
 	j = 0;
 	io_callbacks[j] = in_intr;
-	io_callbacks[j + 1] = NULL;
+	io_callbacks[j + 1] = out_intr;
 	io_names[j] = "input";
 	io_names[j + 1] = "output";
 	j += 2;
@@ -1580,7 +1600,7 @@ static int init_vqs(struct ports_device
 		for (i = 1; i < nr_ports; i++) {
 			j += 2;
 			io_callbacks[j] = in_intr;
-			io_callbacks[j + 1] = NULL;
+			io_callbacks[j + 1] = out_intr;
 			io_names[j] = "input";
 			io_names[j + 1] = "output";
 		}
diff -druNp linux-libre-2.6.37-gnu1/drivers/clk/clkdev.c linux-libre-2.6.38-gnu1/drivers/clk/clkdev.c
--- linux-libre-2.6.37-gnu1/drivers/clk/clkdev.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/clk/clkdev.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,176 @@
+/*
+ * drivers/clk/clkdev.c
+ *
+ *  Copyright (C) 2008 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.
+ *
+ * Helper for the clk API to assist looking up a struct clk.
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/list.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/string.h>
+#include <linux/mutex.h>
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+
+static LIST_HEAD(clocks);
+static DEFINE_MUTEX(clocks_mutex);
+
+/*
+ * Find the correct struct clk for the device and connection ID.
+ * We do slightly fuzzy matching here:
+ *  An entry with a NULL ID is assumed to be a wildcard.
+ *  If an entry has a device ID, it must match
+ *  If an entry has a connection ID, it must match
+ * Then we take the most specific entry - with the following
+ * order of precedence: dev+con > dev only > con only.
+ */
+static struct clk *clk_find(const char *dev_id, const char *con_id)
+{
+	struct clk_lookup *p;
+	struct clk *clk = NULL;
+	int match, best = 0;
+
+	list_for_each_entry(p, &clocks, node) {
+		match = 0;
+		if (p->dev_id) {
+			if (!dev_id || strcmp(p->dev_id, dev_id))
+				continue;
+			match += 2;
+		}
+		if (p->con_id) {
+			if (!con_id || strcmp(p->con_id, con_id))
+				continue;
+			match += 1;
+		}
+
+		if (match > best) {
+			clk = p->clk;
+			if (match != 3)
+				best = match;
+			else
+				break;
+		}
+	}
+	return clk;
+}
+
+struct clk *clk_get_sys(const char *dev_id, const char *con_id)
+{
+	struct clk *clk;
+
+	mutex_lock(&clocks_mutex);
+	clk = clk_find(dev_id, con_id);
+	if (clk && !__clk_get(clk))
+		clk = NULL;
+	mutex_unlock(&clocks_mutex);
+
+	return clk ? clk : ERR_PTR(-ENOENT);
+}
+EXPORT_SYMBOL(clk_get_sys);
+
+struct clk *clk_get(struct device *dev, const char *con_id)
+{
+	const char *dev_id = dev ? dev_name(dev) : NULL;
+
+	return clk_get_sys(dev_id, con_id);
+}
+EXPORT_SYMBOL(clk_get);
+
+void clk_put(struct clk *clk)
+{
+	__clk_put(clk);
+}
+EXPORT_SYMBOL(clk_put);
+
+void clkdev_add(struct clk_lookup *cl)
+{
+	mutex_lock(&clocks_mutex);
+	list_add_tail(&cl->node, &clocks);
+	mutex_unlock(&clocks_mutex);
+}
+EXPORT_SYMBOL(clkdev_add);
+
+void __init clkdev_add_table(struct clk_lookup *cl, size_t num)
+{
+	mutex_lock(&clocks_mutex);
+	while (num--) {
+		list_add_tail(&cl->node, &clocks);
+		cl++;
+	}
+	mutex_unlock(&clocks_mutex);
+}
+
+#define MAX_DEV_ID	20
+#define MAX_CON_ID	16
+
+struct clk_lookup_alloc {
+	struct clk_lookup cl;
+	char	dev_id[MAX_DEV_ID];
+	char	con_id[MAX_CON_ID];
+};
+
+struct clk_lookup * __init_refok
+clkdev_alloc(struct clk *clk, const char *con_id, const char *dev_fmt, ...)
+{
+	struct clk_lookup_alloc *cla;
+
+	cla = __clkdev_alloc(sizeof(*cla));
+	if (!cla)
+		return NULL;
+
+	cla->cl.clk = clk;
+	if (con_id) {
+		strlcpy(cla->con_id, con_id, sizeof(cla->con_id));
+		cla->cl.con_id = cla->con_id;
+	}
+
+	if (dev_fmt) {
+		va_list ap;
+
+		va_start(ap, dev_fmt);
+		vscnprintf(cla->dev_id, sizeof(cla->dev_id), dev_fmt, ap);
+		cla->cl.dev_id = cla->dev_id;
+		va_end(ap);
+	}
+
+	return &cla->cl;
+}
+EXPORT_SYMBOL(clkdev_alloc);
+
+int clk_add_alias(const char *alias, const char *alias_dev_name, char *id,
+	struct device *dev)
+{
+	struct clk *r = clk_get(dev, id);
+	struct clk_lookup *l;
+
+	if (IS_ERR(r))
+		return PTR_ERR(r);
+
+	l = clkdev_alloc(r, alias, alias_dev_name);
+	clk_put(r);
+	if (!l)
+		return -ENODEV;
+	clkdev_add(l);
+	return 0;
+}
+EXPORT_SYMBOL(clk_add_alias);
+
+/*
+ * clkdev_drop - remove a clock dynamically allocated
+ */
+void clkdev_drop(struct clk_lookup *cl)
+{
+	mutex_lock(&clocks_mutex);
+	list_del(&cl->node);
+	mutex_unlock(&clocks_mutex);
+	kfree(cl);
+}
+EXPORT_SYMBOL(clkdev_drop);
diff -druNp linux-libre-2.6.37-gnu1/drivers/clk/Kconfig linux-libre-2.6.38-gnu1/drivers/clk/Kconfig
--- linux-libre-2.6.37-gnu1/drivers/clk/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/clk/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,4 @@
+
+config CLKDEV_LOOKUP
+	bool
+	select HAVE_CLK
diff -druNp linux-libre-2.6.37-gnu1/drivers/clk/Makefile linux-libre-2.6.38-gnu1/drivers/clk/Makefile
--- linux-libre-2.6.37-gnu1/drivers/clk/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/clk/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,2 @@
+
+obj-$(CONFIG_CLKDEV_LOOKUP)	+= clkdev.o
diff -druNp linux-libre-2.6.37-gnu1/drivers/clocksource/acpi_pm.c linux-libre-2.6.38-gnu1/drivers/clocksource/acpi_pm.c
--- linux-libre-2.6.37-gnu1/drivers/clocksource/acpi_pm.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/clocksource/acpi_pm.c	2011-03-14 21:20:32.000000000 -0400
@@ -202,17 +202,21 @@ static int __init init_acpi_pm_clocksour
 			printk(KERN_INFO "PM-Timer had inconsistent results:"
 			       " 0x%#llx, 0x%#llx - aborting.\n",
 			       value1, value2);
+			pmtmr_ioport = 0;
 			return -EINVAL;
 		}
 		if (i == ACPI_PM_READ_CHECKS) {
 			printk(KERN_INFO "PM-Timer failed consistency check "
 			       " (0x%#llx) - aborting.\n", value1);
+			pmtmr_ioport = 0;
 			return -ENODEV;
 		}
 	}
 
-	if (verify_pmtmr_rate() != 0)
+	if (verify_pmtmr_rate() != 0){
+		pmtmr_ioport = 0;
 		return -ENODEV;
+	}
 
 	return clocksource_register_hz(&clocksource_acpi_pm,
 						PMTMR_TICKS_PER_SEC);
diff -druNp linux-libre-2.6.37-gnu1/drivers/clocksource/tcb_clksrc.c linux-libre-2.6.38-gnu1/drivers/clocksource/tcb_clksrc.c
--- linux-libre-2.6.37-gnu1/drivers/clocksource/tcb_clksrc.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/clocksource/tcb_clksrc.c	2011-03-14 21:20:32.000000000 -0400
@@ -196,9 +196,9 @@ static void __init setup_clkevents(struc
 	clkevt.clkevt.min_delta_ns = clockevent_delta2ns(1, &clkevt.clkevt) + 1;
 	clkevt.clkevt.cpumask = cpumask_of(0);
 
-	setup_irq(irq, &tc_irqaction);
-
 	clockevents_register_device(&clkevt.clkevt);
+
+	setup_irq(irq, &tc_irqaction);
 }
 
 #else /* !CONFIG_GENERIC_CLOCKEVENTS */
diff -druNp linux-libre-2.6.37-gnu1/drivers/connector/cn_proc.c linux-libre-2.6.38-gnu1/drivers/connector/cn_proc.c
--- linux-libre-2.6.37-gnu1/drivers/connector/cn_proc.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/connector/cn_proc.c	2011-03-14 21:20:32.000000000 -0400
@@ -43,9 +43,10 @@ static DEFINE_PER_CPU(__u32, proc_event_
 
 static inline void get_seq(__u32 *ts, int *cpu)
 {
-	*ts = get_cpu_var(proc_event_counts)++;
+	preempt_disable();
+	*ts = __this_cpu_inc_return(proc_event_counts) -1;
 	*cpu = smp_processor_id();
-	put_cpu_var(proc_event_counts);
+	preempt_enable();
 }
 
 void proc_fork_connector(struct task_struct *task)
diff -druNp linux-libre-2.6.37-gnu1/drivers/cpufreq/cpufreq.c linux-libre-2.6.38-gnu1/drivers/cpufreq/cpufreq.c
--- linux-libre-2.6.37-gnu1/drivers/cpufreq/cpufreq.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/cpufreq/cpufreq.c	2011-03-14 21:20:32.000000000 -0400
@@ -355,6 +355,7 @@ void cpufreq_notify_transition(struct cp
 		dprintk("FREQ: %lu - CPU: %lu", (unsigned long)freqs->new,
 			(unsigned long)freqs->cpu);
 		trace_power_frequency(POWER_PSTATE, freqs->new, freqs->cpu);
+		trace_cpu_frequency(freqs->new, freqs->cpu);
 		srcu_notifier_call_chain(&cpufreq_transition_notifier_list,
 				CPUFREQ_POSTCHANGE, freqs);
 		if (likely(policy) && likely(policy->cpu == freqs->cpu))
@@ -1918,8 +1919,10 @@ int cpufreq_register_driver(struct cpufr
 
 	ret = sysdev_driver_register(&cpu_sysdev_class,
 					&cpufreq_sysdev_driver);
+	if (ret)
+		goto err_null_driver;
 
-	if ((!ret) && !(cpufreq_driver->flags & CPUFREQ_STICKY)) {
+	if (!(cpufreq_driver->flags & CPUFREQ_STICKY)) {
 		int i;
 		ret = -ENODEV;
 
@@ -1934,21 +1937,22 @@ int cpufreq_register_driver(struct cpufr
 		if (ret) {
 			dprintk("no CPU initialized for driver %s\n",
 							driver_data->name);
-			sysdev_driver_unregister(&cpu_sysdev_class,
-						&cpufreq_sysdev_driver);
-
-			spin_lock_irqsave(&cpufreq_driver_lock, flags);
-			cpufreq_driver = NULL;
-			spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
+			goto err_sysdev_unreg;
 		}
 	}
 
-	if (!ret) {
-		register_hotcpu_notifier(&cpufreq_cpu_notifier);
-		dprintk("driver %s up and running\n", driver_data->name);
-		cpufreq_debug_enable_ratelimit();
-	}
+	register_hotcpu_notifier(&cpufreq_cpu_notifier);
+	dprintk("driver %s up and running\n", driver_data->name);
+	cpufreq_debug_enable_ratelimit();
 
+	return 0;
+err_sysdev_unreg:
+	sysdev_driver_unregister(&cpu_sysdev_class,
+			&cpufreq_sysdev_driver);
+err_null_driver:
+	spin_lock_irqsave(&cpufreq_driver_lock, flags);
+	cpufreq_driver = NULL;
+	spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
 	return ret;
 }
 EXPORT_SYMBOL_GPL(cpufreq_register_driver);
diff -druNp linux-libre-2.6.37-gnu1/drivers/cpufreq/Kconfig linux-libre-2.6.38-gnu1/drivers/cpufreq/Kconfig
--- linux-libre-2.6.37-gnu1/drivers/cpufreq/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/cpufreq/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -71,7 +71,7 @@ config CPU_FREQ_DEFAULT_GOV_PERFORMANCE
 
 config CPU_FREQ_DEFAULT_GOV_POWERSAVE
 	bool "powersave"
-	depends on EMBEDDED
+	depends on EXPERT
 	select CPU_FREQ_GOV_POWERSAVE
 	help
 	  Use the CPUFreq governor 'powersave' as default. This sets
diff -druNp linux-libre-2.6.37-gnu1/drivers/cpuidle/cpuidle.c linux-libre-2.6.38-gnu1/drivers/cpuidle/cpuidle.c
--- linux-libre-2.6.37-gnu1/drivers/cpuidle/cpuidle.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/cpuidle/cpuidle.c	2011-03-14 21:20:32.000000000 -0400
@@ -49,7 +49,7 @@ static int __cpuidle_register_device(str
  */
 static void cpuidle_idle_call(void)
 {
-	struct cpuidle_device *dev = __get_cpu_var(cpuidle_devices);
+	struct cpuidle_device *dev = __this_cpu_read(cpuidle_devices);
 	struct cpuidle_state *target_state;
 	int next_state;
 
@@ -96,7 +96,15 @@ static void cpuidle_idle_call(void)
 
 	/* enter the state and update stats */
 	dev->last_state = target_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);
+
+	trace_power_end(dev->cpu);
+	trace_cpu_idle(PWR_EVENT_EXIT, dev->cpu);
+
 	if (dev->last_state)
 		target_state = dev->last_state;
 
@@ -106,7 +114,6 @@ static void cpuidle_idle_call(void)
 	/* give the governor an opportunity to reflect on the outcome */
 	if (cpuidle_curr_governor->reflect)
 		cpuidle_curr_governor->reflect(dev);
-	trace_power_end(smp_processor_id());
 }
 
 /**
@@ -154,6 +161,45 @@ 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)
+{
+	ktime_t	t1, t2;
+	s64 diff;
+	int ret;
+
+	t1 = ktime_get();
+	local_irq_enable();
+	while (!need_resched())
+		cpu_relax();
+
+	t2 = ktime_get();
+	diff = ktime_to_us(ktime_sub(t2, t1));
+	if (diff > INT_MAX)
+		diff = INT_MAX;
+
+	ret = (int) diff;
+	return ret;
+}
+
+static void poll_idle_init(struct cpuidle_device *dev)
+{
+	struct cpuidle_state *state = &dev->states[0];
+
+	cpuidle_set_statedata(state, NULL);
+
+	snprintf(state->name, CPUIDLE_NAME_LEN, "POLL");
+	snprintf(state->desc, CPUIDLE_DESC_LEN, "CPUIDLE CORE POLL IDLE");
+	state->exit_latency = 0;
+	state->target_residency = 0;
+	state->power_usage = -1;
+	state->flags = 0;
+	state->enter = poll_idle;
+}
+#else
+static void poll_idle_init(struct cpuidle_device *dev) {}
+#endif /* CONFIG_ARCH_HAS_CPU_RELAX */
+
 /**
  * cpuidle_enable_device - enables idle PM for a CPU
  * @dev: the CPU
@@ -178,6 +224,8 @@ int cpuidle_enable_device(struct cpuidle
 			return ret;
 	}
 
+	poll_idle_init(dev);
+
 	if ((ret = cpuidle_add_state_sysfs(dev)))
 		return ret;
 
@@ -232,45 +280,6 @@ void cpuidle_disable_device(struct cpuid
 
 EXPORT_SYMBOL_GPL(cpuidle_disable_device);
 
-#ifdef CONFIG_ARCH_HAS_CPU_RELAX
-static int poll_idle(struct cpuidle_device *dev, struct cpuidle_state *st)
-{
-	ktime_t	t1, t2;
-	s64 diff;
-	int ret;
-
-	t1 = ktime_get();
-	local_irq_enable();
-	while (!need_resched())
-		cpu_relax();
-
-	t2 = ktime_get();
-	diff = ktime_to_us(ktime_sub(t2, t1));
-	if (diff > INT_MAX)
-		diff = INT_MAX;
-
-	ret = (int) diff;
-	return ret;
-}
-
-static void poll_idle_init(struct cpuidle_device *dev)
-{
-	struct cpuidle_state *state = &dev->states[0];
-
-	cpuidle_set_statedata(state, NULL);
-
-	snprintf(state->name, CPUIDLE_NAME_LEN, "C0");
-	snprintf(state->desc, CPUIDLE_DESC_LEN, "CPUIDLE CORE POLL IDLE");
-	state->exit_latency = 0;
-	state->target_residency = 0;
-	state->power_usage = -1;
-	state->flags = CPUIDLE_FLAG_POLL;
-	state->enter = poll_idle;
-}
-#else
-static void poll_idle_init(struct cpuidle_device *dev) {}
-#endif /* CONFIG_ARCH_HAS_CPU_RELAX */
-
 /**
  * __cpuidle_register_device - internal register function called before register
  * and enable routines
@@ -291,8 +300,6 @@ static int __cpuidle_register_device(str
 
 	init_completion(&dev->kobj_unregister);
 
-	poll_idle_init(dev);
-
 	/*
 	 * cpuidle driver should set the dev->power_specified bit
 	 * before registering the device if the driver provides
diff -druNp linux-libre-2.6.37-gnu1/drivers/crypto/mv_cesa.c linux-libre-2.6.38-gnu1/drivers/crypto/mv_cesa.c
--- linux-libre-2.6.37-gnu1/drivers/crypto/mv_cesa.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/crypto/mv_cesa.c	2011-03-14 21:20:32.000000000 -0400
@@ -857,7 +857,7 @@ static int mv_cra_hash_init(struct crypt
 			printk(KERN_WARNING MV_CESA
 			       "Base driver '%s' could not be loaded!\n",
 			       base_hash_name);
-			err = PTR_ERR(fallback_tfm);
+			err = PTR_ERR(base_hash);
 			goto err_bad_base;
 		}
 	}
diff -druNp linux-libre-2.6.37-gnu1/drivers/crypto/n2_core.c linux-libre-2.6.38-gnu1/drivers/crypto/n2_core.c
--- linux-libre-2.6.37-gnu1/drivers/crypto/n2_core.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/crypto/n2_core.c	2011-03-14 21:20:32.000000000 -0400
@@ -1542,7 +1542,7 @@ out:
 	return err;
 }
 
-static void __exit n2_unregister_algs(void)
+static void __devexit n2_unregister_algs(void)
 {
 	mutex_lock(&spu_lock);
 	if (!--algs_registered)
diff -druNp linux-libre-2.6.37-gnu1/drivers/crypto/omap-aes.c linux-libre-2.6.38-gnu1/drivers/crypto/omap-aes.c
--- linux-libre-2.6.37-gnu1/drivers/crypto/omap-aes.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/crypto/omap-aes.c	2011-03-14 21:20:32.000000000 -0400
@@ -74,11 +74,9 @@
 #define FLAGS_CBC		BIT(1)
 #define FLAGS_GIV		BIT(2)
 
-#define FLAGS_NEW_KEY		BIT(4)
-#define FLAGS_NEW_IV		BIT(5)
-#define FLAGS_INIT		BIT(6)
-#define FLAGS_FAST		BIT(7)
-#define FLAGS_BUSY		8
+#define FLAGS_INIT		BIT(4)
+#define FLAGS_FAST		BIT(5)
+#define FLAGS_BUSY		BIT(6)
 
 struct omap_aes_ctx {
 	struct omap_aes_dev *dd;
@@ -98,19 +96,18 @@ struct omap_aes_reqctx {
 struct omap_aes_dev {
 	struct list_head	list;
 	unsigned long		phys_base;
-	void __iomem 		*io_base;
+	void __iomem		*io_base;
 	struct clk		*iclk;
 	struct omap_aes_ctx	*ctx;
 	struct device		*dev;
 	unsigned long		flags;
+	int			err;
 
-	u32			*iv;
-	u32			ctrl;
-
-	spinlock_t			lock;
-	struct crypto_queue		queue;
+	spinlock_t		lock;
+	struct crypto_queue	queue;
 
-	struct tasklet_struct		task;
+	struct tasklet_struct	done_task;
+	struct tasklet_struct	queue_task;
 
 	struct ablkcipher_request	*req;
 	size_t				total;
@@ -179,9 +176,13 @@ static int omap_aes_wait(struct omap_aes
 
 static int omap_aes_hw_init(struct omap_aes_dev *dd)
 {
-	int err = 0;
-
+	/*
+	 * clocks are enabled when request starts and disabled when finished.
+	 * It may be long delays between requests.
+	 * Device might go to off mode to save power.
+	 */
 	clk_enable(dd->iclk);
+
 	if (!(dd->flags & FLAGS_INIT)) {
 		/* is it necessary to reset before every operation? */
 		omap_aes_write_mask(dd, AES_REG_MASK, AES_REG_MASK_SOFTRESET,
@@ -193,39 +194,26 @@ static int omap_aes_hw_init(struct omap_
 		__asm__ __volatile__("nop");
 		__asm__ __volatile__("nop");
 
-		err = omap_aes_wait(dd, AES_REG_SYSSTATUS,
-				AES_REG_SYSSTATUS_RESETDONE);
-		if (!err)
-			dd->flags |= FLAGS_INIT;
-	}
+		if (omap_aes_wait(dd, AES_REG_SYSSTATUS,
+				AES_REG_SYSSTATUS_RESETDONE))
+			return -ETIMEDOUT;
 
-	return err;
-}
+		dd->flags |= FLAGS_INIT;
+		dd->err = 0;
+	}
 
-static void omap_aes_hw_cleanup(struct omap_aes_dev *dd)
-{
-	clk_disable(dd->iclk);
+	return 0;
 }
 
-static void omap_aes_write_ctrl(struct omap_aes_dev *dd)
+static int omap_aes_write_ctrl(struct omap_aes_dev *dd)
 {
 	unsigned int key32;
-	int i;
+	int i, err;
 	u32 val, mask;
 
-	val = FLD_VAL(((dd->ctx->keylen >> 3) - 1), 4, 3);
-	if (dd->flags & FLAGS_CBC)
-		val |= AES_REG_CTRL_CBC;
-	if (dd->flags & FLAGS_ENCRYPT)
-		val |= AES_REG_CTRL_DIRECTION;
-
-	if (dd->ctrl == val && !(dd->flags & FLAGS_NEW_IV) &&
-		   !(dd->ctx->flags & FLAGS_NEW_KEY))
-		goto out;
-
-	/* only need to write control registers for new settings */
-
-	dd->ctrl = val;
+	err = omap_aes_hw_init(dd);
+	if (err)
+		return err;
 
 	val = 0;
 	if (dd->dma_lch_out >= 0)
@@ -237,30 +225,43 @@ static void omap_aes_write_ctrl(struct o
 
 	omap_aes_write_mask(dd, AES_REG_MASK, val, mask);
 
-	pr_debug("Set key\n");
 	key32 = dd->ctx->keylen / sizeof(u32);
-	/* set a key */
+
+	/* it seems a key should always be set even if it has not changed */
 	for (i = 0; i < key32; i++) {
 		omap_aes_write(dd, AES_REG_KEY(i),
 			__le32_to_cpu(dd->ctx->key[i]));
 	}
-	dd->ctx->flags &= ~FLAGS_NEW_KEY;
 
-	if (dd->flags & FLAGS_NEW_IV) {
-		pr_debug("Set IV\n");
-		omap_aes_write_n(dd, AES_REG_IV(0), dd->iv, 4);
-		dd->flags &= ~FLAGS_NEW_IV;
-	}
+	if ((dd->flags & FLAGS_CBC) && dd->req->info)
+		omap_aes_write_n(dd, AES_REG_IV(0), dd->req->info, 4);
+
+	val = FLD_VAL(((dd->ctx->keylen >> 3) - 1), 4, 3);
+	if (dd->flags & FLAGS_CBC)
+		val |= AES_REG_CTRL_CBC;
+	if (dd->flags & FLAGS_ENCRYPT)
+		val |= AES_REG_CTRL_DIRECTION;
 
 	mask = AES_REG_CTRL_CBC | AES_REG_CTRL_DIRECTION |
 			AES_REG_CTRL_KEY_SIZE;
 
-	omap_aes_write_mask(dd, AES_REG_CTRL, dd->ctrl, mask);
+	omap_aes_write_mask(dd, AES_REG_CTRL, val, mask);
 
-out:
-	/* start DMA or disable idle mode */
-	omap_aes_write_mask(dd, AES_REG_MASK, AES_REG_MASK_START,
-			    AES_REG_MASK_START);
+	/* IN */
+	omap_set_dma_dest_params(dd->dma_lch_in, 0, OMAP_DMA_AMODE_CONSTANT,
+				 dd->phys_base + AES_REG_DATA, 0, 4);
+
+	omap_set_dma_dest_burst_mode(dd->dma_lch_in, OMAP_DMA_DATA_BURST_4);
+	omap_set_dma_src_burst_mode(dd->dma_lch_in, OMAP_DMA_DATA_BURST_4);
+
+	/* OUT */
+	omap_set_dma_src_params(dd->dma_lch_out, 0, OMAP_DMA_AMODE_CONSTANT,
+				dd->phys_base + AES_REG_DATA, 0, 4);
+
+	omap_set_dma_src_burst_mode(dd->dma_lch_out, OMAP_DMA_DATA_BURST_4);
+	omap_set_dma_dest_burst_mode(dd->dma_lch_out, OMAP_DMA_DATA_BURST_4);
+
+	return 0;
 }
 
 static struct omap_aes_dev *omap_aes_find_dev(struct omap_aes_ctx *ctx)
@@ -288,8 +289,16 @@ static void omap_aes_dma_callback(int lc
 {
 	struct omap_aes_dev *dd = data;
 
-	if (lch == dd->dma_lch_out)
-		tasklet_schedule(&dd->task);
+	if (ch_status != OMAP_DMA_BLOCK_IRQ) {
+		pr_err("omap-aes DMA error status: 0x%hx\n", ch_status);
+		dd->err = -EIO;
+		dd->flags &= ~FLAGS_INIT; /* request to re-initialize */
+	} else if (lch == dd->dma_lch_in) {
+		return;
+	}
+
+	/* dma_lch_out - completed */
+	tasklet_schedule(&dd->done_task);
 }
 
 static int omap_aes_dma_init(struct omap_aes_dev *dd)
@@ -339,18 +348,6 @@ static int omap_aes_dma_init(struct omap
 		goto err_dma_out;
 	}
 
-	omap_set_dma_dest_params(dd->dma_lch_in, 0, OMAP_DMA_AMODE_CONSTANT,
-				 dd->phys_base + AES_REG_DATA, 0, 4);
-
-	omap_set_dma_dest_burst_mode(dd->dma_lch_in, OMAP_DMA_DATA_BURST_4);
-	omap_set_dma_src_burst_mode(dd->dma_lch_in, OMAP_DMA_DATA_BURST_4);
-
-	omap_set_dma_src_params(dd->dma_lch_out, 0, OMAP_DMA_AMODE_CONSTANT,
-				dd->phys_base + AES_REG_DATA, 0, 4);
-
-	omap_set_dma_src_burst_mode(dd->dma_lch_out, OMAP_DMA_DATA_BURST_4);
-	omap_set_dma_dest_burst_mode(dd->dma_lch_out, OMAP_DMA_DATA_BURST_4);
-
 	return 0;
 
 err_dma_out:
@@ -406,6 +403,11 @@ static int sg_copy(struct scatterlist **
 		if (!count)
 			return off;
 
+		/*
+		 * buflen and total are AES_BLOCK_SIZE size aligned,
+		 * so count should be also aligned
+		 */
+
 		sg_copy_buf(buf + off, *sg, *offset, count, out);
 
 		off += count;
@@ -461,7 +463,9 @@ static int omap_aes_crypt_dma(struct cry
 	omap_start_dma(dd->dma_lch_in);
 	omap_start_dma(dd->dma_lch_out);
 
-	omap_aes_write_ctrl(dd);
+	/* start DMA or disable idle mode */
+	omap_aes_write_mask(dd, AES_REG_MASK, AES_REG_MASK_START,
+			    AES_REG_MASK_START);
 
 	return 0;
 }
@@ -488,8 +492,10 @@ static int omap_aes_crypt_dma_start(stru
 		count = min(dd->total, sg_dma_len(dd->in_sg));
 		count = min(count, sg_dma_len(dd->out_sg));
 
-		if (count != dd->total)
+		if (count != dd->total) {
+			pr_err("request length != buffer length\n");
 			return -EINVAL;
+		}
 
 		pr_debug("fast\n");
 
@@ -525,23 +531,25 @@ static int omap_aes_crypt_dma_start(stru
 
 	dd->total -= count;
 
-	err = omap_aes_hw_init(dd);
-
 	err = omap_aes_crypt_dma(tfm, addr_in, addr_out, count);
+	if (err) {
+		dma_unmap_sg(dd->dev, dd->in_sg, 1, DMA_TO_DEVICE);
+		dma_unmap_sg(dd->dev, dd->out_sg, 1, DMA_TO_DEVICE);
+	}
 
 	return err;
 }
 
 static void omap_aes_finish_req(struct omap_aes_dev *dd, int err)
 {
-	struct omap_aes_ctx *ctx;
+	struct ablkcipher_request *req = dd->req;
 
 	pr_debug("err: %d\n", err);
 
-	ctx = crypto_ablkcipher_ctx(crypto_ablkcipher_reqtfm(dd->req));
+	clk_disable(dd->iclk);
+	dd->flags &= ~FLAGS_BUSY;
 
-	if (!dd->total)
-		dd->req->base.complete(&dd->req->base, err);
+	req->base.complete(&req->base, err);
 }
 
 static int omap_aes_crypt_dma_stop(struct omap_aes_dev *dd)
@@ -553,8 +561,6 @@ static int omap_aes_crypt_dma_stop(struc
 
 	omap_aes_write_mask(dd, AES_REG_MASK, 0, AES_REG_MASK_START);
 
-	omap_aes_hw_cleanup(dd);
-
 	omap_stop_dma(dd->dma_lch_in);
 	omap_stop_dma(dd->dma_lch_out);
 
@@ -574,40 +580,39 @@ static int omap_aes_crypt_dma_stop(struc
 		}
 	}
 
-	if (err || !dd->total)
-		omap_aes_finish_req(dd, err);
-
 	return err;
 }
 
-static int omap_aes_handle_req(struct omap_aes_dev *dd)
+static int omap_aes_handle_queue(struct omap_aes_dev *dd,
+			       struct ablkcipher_request *req)
 {
 	struct crypto_async_request *async_req, *backlog;
 	struct omap_aes_ctx *ctx;
 	struct omap_aes_reqctx *rctx;
-	struct ablkcipher_request *req;
 	unsigned long flags;
-
-	if (dd->total)
-		goto start;
+	int err, ret = 0;
 
 	spin_lock_irqsave(&dd->lock, flags);
+	if (req)
+		ret = ablkcipher_enqueue_request(&dd->queue, req);
+	if (dd->flags & FLAGS_BUSY) {
+		spin_unlock_irqrestore(&dd->lock, flags);
+		return ret;
+	}
 	backlog = crypto_get_backlog(&dd->queue);
 	async_req = crypto_dequeue_request(&dd->queue);
-	if (!async_req)
-		clear_bit(FLAGS_BUSY, &dd->flags);
+	if (async_req)
+		dd->flags |= FLAGS_BUSY;
 	spin_unlock_irqrestore(&dd->lock, flags);
 
 	if (!async_req)
-		return 0;
+		return ret;
 
 	if (backlog)
 		backlog->complete(backlog, -EINPROGRESS);
 
 	req = ablkcipher_request_cast(async_req);
 
-	pr_debug("get new req\n");
-
 	/* assign new request to device */
 	dd->req = req;
 	dd->total = req->nbytes;
@@ -621,27 +626,22 @@ static int omap_aes_handle_req(struct om
 	rctx->mode &= FLAGS_MODE_MASK;
 	dd->flags = (dd->flags & ~FLAGS_MODE_MASK) | rctx->mode;
 
-	dd->iv = req->info;
-	if ((dd->flags & FLAGS_CBC) && dd->iv)
-		dd->flags |= FLAGS_NEW_IV;
-	else
-		dd->flags &= ~FLAGS_NEW_IV;
-
+	dd->ctx = ctx;
 	ctx->dd = dd;
-	if (dd->ctx != ctx) {
-		/* assign new context to device */
-		dd->ctx = ctx;
-		ctx->flags |= FLAGS_NEW_KEY;
-	}
 
-	if (!IS_ALIGNED(req->nbytes, AES_BLOCK_SIZE))
-		pr_err("request size is not exact amount of AES blocks\n");
+	err = omap_aes_write_ctrl(dd);
+	if (!err)
+		err = omap_aes_crypt_dma_start(dd);
+	if (err) {
+		/* aes_task will not finish it, so do it here */
+		omap_aes_finish_req(dd, err);
+		tasklet_schedule(&dd->queue_task);
+	}
 
-start:
-	return omap_aes_crypt_dma_start(dd);
+	return ret; /* return ret, which is enqueue return value */
 }
 
-static void omap_aes_task(unsigned long data)
+static void omap_aes_done_task(unsigned long data)
 {
 	struct omap_aes_dev *dd = (struct omap_aes_dev *)data;
 	int err;
@@ -650,40 +650,50 @@ static void omap_aes_task(unsigned long
 
 	err = omap_aes_crypt_dma_stop(dd);
 
-	err = omap_aes_handle_req(dd);
+	err = dd->err ? : err;
+
+	if (dd->total && !err) {
+		err = omap_aes_crypt_dma_start(dd);
+		if (!err)
+			return; /* DMA started. Not fininishing. */
+	}
+
+	omap_aes_finish_req(dd, err);
+	omap_aes_handle_queue(dd, NULL);
 
 	pr_debug("exit\n");
 }
 
+static void omap_aes_queue_task(unsigned long data)
+{
+	struct omap_aes_dev *dd = (struct omap_aes_dev *)data;
+
+	omap_aes_handle_queue(dd, NULL);
+}
+
 static int omap_aes_crypt(struct ablkcipher_request *req, unsigned long mode)
 {
 	struct omap_aes_ctx *ctx = crypto_ablkcipher_ctx(
 			crypto_ablkcipher_reqtfm(req));
 	struct omap_aes_reqctx *rctx = ablkcipher_request_ctx(req);
 	struct omap_aes_dev *dd;
-	unsigned long flags;
-	int err;
 
 	pr_debug("nbytes: %d, enc: %d, cbc: %d\n", req->nbytes,
 		  !!(mode & FLAGS_ENCRYPT),
 		  !!(mode & FLAGS_CBC));
 
+	if (!IS_ALIGNED(req->nbytes, AES_BLOCK_SIZE)) {
+		pr_err("request size is not exact amount of AES blocks\n");
+		return -EINVAL;
+	}
+
 	dd = omap_aes_find_dev(ctx);
 	if (!dd)
 		return -ENODEV;
 
 	rctx->mode = mode;
 
-	spin_lock_irqsave(&dd->lock, flags);
-	err = ablkcipher_enqueue_request(&dd->queue, req);
-	spin_unlock_irqrestore(&dd->lock, flags);
-
-	if (!test_and_set_bit(FLAGS_BUSY, &dd->flags))
-		omap_aes_handle_req(dd);
-
-	pr_debug("exit\n");
-
-	return err;
+	return omap_aes_handle_queue(dd, req);
 }
 
 /* ********************** ALG API ************************************ */
@@ -701,7 +711,6 @@ static int omap_aes_setkey(struct crypto
 
 	memcpy(ctx->key, key, keylen);
 	ctx->keylen = keylen;
-	ctx->flags |= FLAGS_NEW_KEY;
 
 	return 0;
 }
@@ -750,7 +759,7 @@ static struct crypto_alg algs[] = {
 	.cra_flags		= CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
 	.cra_blocksize		= AES_BLOCK_SIZE,
 	.cra_ctxsize		= sizeof(struct omap_aes_ctx),
-	.cra_alignmask	 	= 0,
+	.cra_alignmask		= 0,
 	.cra_type		= &crypto_ablkcipher_type,
 	.cra_module		= THIS_MODULE,
 	.cra_init		= omap_aes_cra_init,
@@ -770,7 +779,7 @@ static struct crypto_alg algs[] = {
 	.cra_flags		= CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
 	.cra_blocksize		= AES_BLOCK_SIZE,
 	.cra_ctxsize		= sizeof(struct omap_aes_ctx),
-	.cra_alignmask	 	= 0,
+	.cra_alignmask		= 0,
 	.cra_type		= &crypto_ablkcipher_type,
 	.cra_module		= THIS_MODULE,
 	.cra_init		= omap_aes_cra_init,
@@ -849,7 +858,8 @@ static int omap_aes_probe(struct platfor
 		 (reg & AES_REG_REV_MAJOR) >> 4, reg & AES_REG_REV_MINOR);
 	clk_disable(dd->iclk);
 
-	tasklet_init(&dd->task, omap_aes_task, (unsigned long)dd);
+	tasklet_init(&dd->done_task, omap_aes_done_task, (unsigned long)dd);
+	tasklet_init(&dd->queue_task, omap_aes_queue_task, (unsigned long)dd);
 
 	err = omap_aes_dma_init(dd);
 	if (err)
@@ -876,7 +886,8 @@ err_algs:
 		crypto_unregister_alg(&algs[j]);
 	omap_aes_dma_cleanup(dd);
 err_dma:
-	tasklet_kill(&dd->task);
+	tasklet_kill(&dd->done_task);
+	tasklet_kill(&dd->queue_task);
 	iounmap(dd->io_base);
 err_io:
 	clk_put(dd->iclk);
@@ -903,7 +914,8 @@ static int omap_aes_remove(struct platfo
 	for (i = 0; i < ARRAY_SIZE(algs); i++)
 		crypto_unregister_alg(&algs[i]);
 
-	tasklet_kill(&dd->task);
+	tasklet_kill(&dd->done_task);
+	tasklet_kill(&dd->queue_task);
 	omap_aes_dma_cleanup(dd);
 	iounmap(dd->io_base);
 	clk_put(dd->iclk);
diff -druNp linux-libre-2.6.37-gnu1/drivers/crypto/omap-sham.c linux-libre-2.6.38-gnu1/drivers/crypto/omap-sham.c
--- linux-libre-2.6.37-gnu1/drivers/crypto/omap-sham.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/crypto/omap-sham.c	2011-03-14 21:20:32.000000000 -0400
@@ -72,10 +72,9 @@
 
 #define DEFAULT_TIMEOUT_INTERVAL	HZ
 
-#define FLAGS_FIRST		0x0001
 #define FLAGS_FINUP		0x0002
 #define FLAGS_FINAL		0x0004
-#define FLAGS_FAST		0x0008
+#define FLAGS_SG		0x0008
 #define FLAGS_SHA1		0x0010
 #define FLAGS_DMA_ACTIVE	0x0020
 #define FLAGS_OUTPUT_READY	0x0040
@@ -83,13 +82,17 @@
 #define FLAGS_INIT		0x0100
 #define FLAGS_CPU		0x0200
 #define FLAGS_HMAC		0x0400
-
-/* 3rd byte */
-#define FLAGS_BUSY		16
+#define FLAGS_ERROR		0x0800
+#define FLAGS_BUSY		0x1000
 
 #define OP_UPDATE	1
 #define OP_FINAL	2
 
+#define OMAP_ALIGN_MASK		(sizeof(u32)-1)
+#define OMAP_ALIGNED		__attribute__((aligned(sizeof(u32))))
+
+#define BUFLEN		PAGE_SIZE
+
 struct omap_sham_dev;
 
 struct omap_sham_reqctx {
@@ -97,8 +100,8 @@ struct omap_sham_reqctx {
 	unsigned long		flags;
 	unsigned long		op;
 
+	u8			digest[SHA1_DIGEST_SIZE] OMAP_ALIGNED;
 	size_t			digcnt;
-	u8			*buffer;
 	size_t			bufcnt;
 	size_t			buflen;
 	dma_addr_t		dma_addr;
@@ -107,6 +110,8 @@ struct omap_sham_reqctx {
 	struct scatterlist	*sg;
 	unsigned int		offset;	/* offset in current sg */
 	unsigned int		total;	/* total request */
+
+	u8			buffer[0] OMAP_ALIGNED;
 };
 
 struct omap_sham_hmac_ctx {
@@ -136,6 +141,7 @@ struct omap_sham_dev {
 	int			irq;
 	struct clk		*iclk;
 	spinlock_t		lock;
+	int			err;
 	int			dma;
 	int			dma_lch;
 	struct tasklet_struct	done_task;
@@ -194,53 +200,68 @@ static inline int omap_sham_wait(struct
 static void omap_sham_copy_hash(struct ahash_request *req, int out)
 {
 	struct omap_sham_reqctx *ctx = ahash_request_ctx(req);
+	u32 *hash = (u32 *)ctx->digest;
+	int i;
+
+	/* MD5 is almost unused. So copy sha1 size to reduce code */
+	for (i = 0; i < SHA1_DIGEST_SIZE / sizeof(u32); i++) {
+		if (out)
+			hash[i] = omap_sham_read(ctx->dd,
+						SHA_REG_DIGEST(i));
+		else
+			omap_sham_write(ctx->dd,
+					SHA_REG_DIGEST(i), hash[i]);
+	}
+}
+
+static void omap_sham_copy_ready_hash(struct ahash_request *req)
+{
+	struct omap_sham_reqctx *ctx = ahash_request_ctx(req);
+	u32 *in = (u32 *)ctx->digest;
 	u32 *hash = (u32 *)req->result;
 	int i;
 
+	if (!hash)
+		return;
+
 	if (likely(ctx->flags & FLAGS_SHA1)) {
 		/* SHA1 results are in big endian */
 		for (i = 0; i < SHA1_DIGEST_SIZE / sizeof(u32); i++)
-			if (out)
-				hash[i] = be32_to_cpu(omap_sham_read(ctx->dd,
-							SHA_REG_DIGEST(i)));
-			else
-				omap_sham_write(ctx->dd, SHA_REG_DIGEST(i),
-							cpu_to_be32(hash[i]));
+			hash[i] = be32_to_cpu(in[i]);
 	} else {
 		/* MD5 results are in little endian */
 		for (i = 0; i < MD5_DIGEST_SIZE / sizeof(u32); i++)
-			if (out)
-				hash[i] = le32_to_cpu(omap_sham_read(ctx->dd,
-							SHA_REG_DIGEST(i)));
-			else
-				omap_sham_write(ctx->dd, SHA_REG_DIGEST(i),
-							cpu_to_le32(hash[i]));
+			hash[i] = le32_to_cpu(in[i]);
 	}
 }
 
-static int omap_sham_write_ctrl(struct omap_sham_dev *dd, size_t length,
-				 int final, int dma)
+static int omap_sham_hw_init(struct omap_sham_dev *dd)
 {
-	struct omap_sham_reqctx *ctx = ahash_request_ctx(dd->req);
-	u32 val = length << 5, mask;
+	clk_enable(dd->iclk);
 
-	if (unlikely(!ctx->digcnt)) {
+	if (!(dd->flags & FLAGS_INIT)) {
+		omap_sham_write_mask(dd, SHA_REG_MASK,
+			SHA_REG_MASK_SOFTRESET, SHA_REG_MASK_SOFTRESET);
 
-		clk_enable(dd->iclk);
+		if (omap_sham_wait(dd, SHA_REG_SYSSTATUS,
+					SHA_REG_SYSSTATUS_RESETDONE))
+			return -ETIMEDOUT;
 
-		if (!(dd->flags & FLAGS_INIT)) {
-			omap_sham_write_mask(dd, SHA_REG_MASK,
-				SHA_REG_MASK_SOFTRESET, SHA_REG_MASK_SOFTRESET);
+		dd->flags |= FLAGS_INIT;
+		dd->err = 0;
+	}
 
-			if (omap_sham_wait(dd, SHA_REG_SYSSTATUS,
-						SHA_REG_SYSSTATUS_RESETDONE))
-				return -ETIMEDOUT;
+	return 0;
+}
 
-			dd->flags |= FLAGS_INIT;
-		}
-	} else {
+static void omap_sham_write_ctrl(struct omap_sham_dev *dd, size_t length,
+				 int final, int dma)
+{
+	struct omap_sham_reqctx *ctx = ahash_request_ctx(dd->req);
+	u32 val = length << 5, mask;
+
+	if (likely(ctx->digcnt))
 		omap_sham_write(dd, SHA_REG_DIGCNT, ctx->digcnt);
-	}
 
 	omap_sham_write_mask(dd, SHA_REG_MASK,
 		SHA_REG_MASK_IT_EN | (dma ? SHA_REG_MASK_DMA_EN : 0),
@@ -260,29 +281,26 @@ static int omap_sham_write_ctrl(struct o
 			SHA_REG_CTRL_ALGO | SHA_REG_CTRL_LENGTH;
 
 	omap_sham_write_mask(dd, SHA_REG_CTRL, val, mask);
-
-	return 0;
 }
 
 static int omap_sham_xmit_cpu(struct omap_sham_dev *dd, const u8 *buf,
 			      size_t length, int final)
 {
 	struct omap_sham_reqctx *ctx = ahash_request_ctx(dd->req);
-	int err, count, len32;
+	int count, len32;
 	const u32 *buffer = (const u32 *)buf;
 
 	dev_dbg(dd->dev, "xmit_cpu: digcnt: %d, length: %d, final: %d\n",
 						ctx->digcnt, length, final);
 
-	err = omap_sham_write_ctrl(dd, length, final, 0);
-	if (err)
-		return err;
+	omap_sham_write_ctrl(dd, length, final, 0);
+
+	/* should be non-zero before next lines to disable clocks later */
+	ctx->digcnt += length;
 
 	if (omap_sham_wait(dd, SHA_REG_CTRL, SHA_REG_CTRL_INPUT_READY))
 		return -ETIMEDOUT;
 
-	ctx->digcnt += length;
-
 	if (final)
 		ctx->flags |= FLAGS_FINAL; /* catch last interrupt */
 
@@ -298,16 +316,11 @@ static int omap_sham_xmit_dma(struct oma
 			      size_t length, int final)
 {
 	struct omap_sham_reqctx *ctx = ahash_request_ctx(dd->req);
-	int err, len32;
+	int len32;
 
 	dev_dbg(dd->dev, "xmit_dma: digcnt: %d, length: %d, final: %d\n",
 						ctx->digcnt, length, final);
 
-	/* flush cache entries related to our page */
-	if (dma_addr == ctx->dma_addr)
-		dma_sync_single_for_device(dd->dev, dma_addr, length,
-					   DMA_TO_DEVICE);
-
 	len32 = DIV_ROUND_UP(length, sizeof(u32));
 
 	omap_set_dma_transfer_params(dd->dma_lch, OMAP_DMA_DATA_TYPE_S32, len32,
@@ -317,9 +330,7 @@ static int omap_sham_xmit_dma(struct oma
 	omap_set_dma_src_params(dd->dma_lch, 0, OMAP_DMA_AMODE_POST_INC,
 				dma_addr, 0, 0);
 
-	err = omap_sham_write_ctrl(dd, length, final, 1);
-	if (err)
-		return err;
+	omap_sham_write_ctrl(dd, length, final, 1);
 
 	ctx->digcnt += length;
 
@@ -371,15 +382,29 @@ static size_t omap_sham_append_sg(struct
 	return 0;
 }
 
+static int omap_sham_xmit_dma_map(struct omap_sham_dev *dd,
+					struct omap_sham_reqctx *ctx,
+					size_t length, int final)
+{
+	ctx->dma_addr = dma_map_single(dd->dev, ctx->buffer, ctx->buflen,
+				       DMA_TO_DEVICE);
+	if (dma_mapping_error(dd->dev, ctx->dma_addr)) {
+		dev_err(dd->dev, "dma %u bytes error\n", ctx->buflen);
+		return -EINVAL;
+	}
+
+	ctx->flags &= ~FLAGS_SG;
+
+	/* next call does not fail... so no unmap in the case of error */
+	return omap_sham_xmit_dma(dd, ctx->dma_addr, length, final);
+}
+
 static int omap_sham_update_dma_slow(struct omap_sham_dev *dd)
 {
 	struct omap_sham_reqctx *ctx = ahash_request_ctx(dd->req);
 	unsigned int final;
 	size_t count;
 
-	if (!ctx->total)
-		return 0;
-
 	omap_sham_append_sg(ctx);
 
 	final = (ctx->flags & FLAGS_FINUP) && !ctx->total;
@@ -390,30 +415,68 @@ static int omap_sham_update_dma_slow(str
 	if (final || (ctx->bufcnt == ctx->buflen && ctx->total)) {
 		count = ctx->bufcnt;
 		ctx->bufcnt = 0;
-		return omap_sham_xmit_dma(dd, ctx->dma_addr, count, final);
+		return omap_sham_xmit_dma_map(dd, ctx, count, final);
 	}
 
 	return 0;
 }
 
-static int omap_sham_update_dma_fast(struct omap_sham_dev *dd)
+/* Start address alignment */
+#define SG_AA(sg)	(IS_ALIGNED(sg->offset, sizeof(u32)))
+/* SHA1 block size alignment */
+#define SG_SA(sg)	(IS_ALIGNED(sg->length, SHA1_MD5_BLOCK_SIZE))
+
+static int omap_sham_update_dma_start(struct omap_sham_dev *dd)
 {
 	struct omap_sham_reqctx *ctx = ahash_request_ctx(dd->req);
-	unsigned int length;
+	unsigned int length, final, tail;
+	struct scatterlist *sg;
 
-	ctx->flags |= FLAGS_FAST;
+	if (!ctx->total)
+		return 0;
 
-	length = min(ctx->total, sg_dma_len(ctx->sg));
-	ctx->total = length;
+	if (ctx->bufcnt || ctx->offset)
+		return omap_sham_update_dma_slow(dd);
+
+	dev_dbg(dd->dev, "fast: digcnt: %d, bufcnt: %u, total: %u\n",
+			ctx->digcnt, ctx->bufcnt, ctx->total);
+
+	sg = ctx->sg;
+
+	if (!SG_AA(sg))
+		return omap_sham_update_dma_slow(dd);
+
+	if (!sg_is_last(sg) && !SG_SA(sg))
+		/* size is not SHA1_BLOCK_SIZE aligned */
+		return omap_sham_update_dma_slow(dd);
+
+	length = min(ctx->total, sg->length);
+
+	if (sg_is_last(sg)) {
+		if (!(ctx->flags & FLAGS_FINUP)) {
+			/* not last sg must be SHA1_MD5_BLOCK_SIZE aligned */
+			tail = length & (SHA1_MD5_BLOCK_SIZE - 1);
+			/* without finup() we need one block to close hash */
+			if (!tail)
+				tail = SHA1_MD5_BLOCK_SIZE;
+			length -= tail;
+		}
+	}
 
 	if (!dma_map_sg(dd->dev, ctx->sg, 1, DMA_TO_DEVICE)) {
 		dev_err(dd->dev, "dma_map_sg  error\n");
 		return -EINVAL;
 	}
 
+	ctx->flags |= FLAGS_SG;
+
 	ctx->total -= length;
+	ctx->offset = length; /* offset where to start slow */
 
-	return omap_sham_xmit_dma(dd, sg_dma_address(ctx->sg), length, 1);
+	final = (ctx->flags & FLAGS_FINUP) && !ctx->total;
+
+	/* next call does not fail... so no unmap in the case of error */
+	return omap_sham_xmit_dma(dd, sg_dma_address(ctx->sg), length, final);
 }
 
 static int omap_sham_update_cpu(struct omap_sham_dev *dd)
@@ -433,8 +496,17 @@ static int omap_sham_update_dma_stop(str
 	struct omap_sham_reqctx *ctx = ahash_request_ctx(dd->req);
 
 	omap_stop_dma(dd->dma_lch);
-	if (ctx->flags & FLAGS_FAST)
+	if (ctx->flags & FLAGS_SG) {
 		dma_unmap_sg(dd->dev, ctx->sg, 1, DMA_TO_DEVICE);
+		if (ctx->sg->length == ctx->offset) {
+			ctx->sg = sg_next(ctx->sg);
+			if (ctx->sg)
+				ctx->offset = 0;
+		}
+	} else {
+		dma_unmap_single(dd->dev, ctx->dma_addr, ctx->buflen,
+				 DMA_TO_DEVICE);
+	}
 
 	return 0;
 }
@@ -454,14 +526,7 @@ static void omap_sham_cleanup(struct aha
 	spin_unlock_irqrestore(&dd->lock, flags);
 
 	if (ctx->digcnt)
-		clk_disable(dd->iclk);
-
-	if (ctx->dma_addr)
-		dma_unmap_single(dd->dev, ctx->dma_addr, ctx->buflen,
-				 DMA_TO_DEVICE);
-
-	if (ctx->buffer)
-		free_page((unsigned long)ctx->buffer);
+		omap_sham_copy_ready_hash(req);
 
 	dev_dbg(dd->dev, "digcnt: %d, bufcnt: %d\n", ctx->digcnt, ctx->bufcnt);
 }
@@ -489,8 +554,6 @@ static int omap_sham_init(struct ahash_r
 
 	ctx->flags = 0;
 
-	ctx->flags |= FLAGS_FIRST;
-
 	dev_dbg(dd->dev, "init: digest size: %d\n",
 		crypto_ahash_digestsize(tfm));
 
@@ -499,21 +562,7 @@ static int omap_sham_init(struct ahash_r
 
 	ctx->bufcnt = 0;
 	ctx->digcnt = 0;
-
-	ctx->buflen = PAGE_SIZE;
-	ctx->buffer = (void *)__get_free_page(
-				(req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP) ?
-				GFP_KERNEL : GFP_ATOMIC);
-	if (!ctx->buffer)
-		return -ENOMEM;
-
-	ctx->dma_addr = dma_map_single(dd->dev, ctx->buffer, ctx->buflen,
-					DMA_TO_DEVICE);
-	if (dma_mapping_error(dd->dev, ctx->dma_addr)) {
-		dev_err(dd->dev, "dma %u bytes error\n", ctx->buflen);
-		free_page((unsigned long)ctx->buffer);
-		return -EINVAL;
-	}
+	ctx->buflen = BUFLEN;
 
 	if (tctx->flags & FLAGS_HMAC) {
 		struct omap_sham_hmac_ctx *bctx = tctx->base;
@@ -538,10 +587,8 @@ static int omap_sham_update_req(struct o
 
 	if (ctx->flags & FLAGS_CPU)
 		err = omap_sham_update_cpu(dd);
-	else if (ctx->flags & FLAGS_FAST)
-		err = omap_sham_update_dma_fast(dd);
 	else
-		err = omap_sham_update_dma_slow(dd);
+		err = omap_sham_update_dma_start(dd);
 
 	/* wait for dma completion before can take more data */
 	dev_dbg(dd->dev, "update: err: %d, digcnt: %d\n", err, ctx->digcnt);
@@ -560,15 +607,12 @@ static int omap_sham_final_req(struct om
 		use_dma = 0;
 
 	if (use_dma)
-		err = omap_sham_xmit_dma(dd, ctx->dma_addr, ctx->bufcnt, 1);
+		err = omap_sham_xmit_dma_map(dd, ctx, ctx->bufcnt, 1);
 	else
 		err = omap_sham_xmit_cpu(dd, ctx->buffer, ctx->bufcnt, 1);
 
 	ctx->bufcnt = 0;
 
-	if (err != -EINPROGRESS)
-		omap_sham_cleanup(req);
-
 	dev_dbg(dd->dev, "final_req: err: %d\n", err);
 
 	return err;
@@ -576,6 +620,7 @@ static int omap_sham_final_req(struct om
 
 static int omap_sham_finish_req_hmac(struct ahash_request *req)
 {
+	struct omap_sham_reqctx *ctx = ahash_request_ctx(req);
 	struct omap_sham_ctx *tctx = crypto_tfm_ctx(req->base.tfm);
 	struct omap_sham_hmac_ctx *bctx = tctx->base;
 	int bs = crypto_shash_blocksize(bctx->shash);
@@ -590,48 +635,56 @@ static int omap_sham_finish_req_hmac(str
 
 	return crypto_shash_init(&desc.shash) ?:
 	       crypto_shash_update(&desc.shash, bctx->opad, bs) ?:
-	       crypto_shash_finup(&desc.shash, req->result, ds, req->result);
+	       crypto_shash_finup(&desc.shash, ctx->digest, ds, ctx->digest);
 }
 
 static void omap_sham_finish_req(struct ahash_request *req, int err)
 {
 	struct omap_sham_reqctx *ctx = ahash_request_ctx(req);
+	struct omap_sham_dev *dd = ctx->dd;
 
 	if (!err) {
 		omap_sham_copy_hash(ctx->dd->req, 1);
 		if (ctx->flags & FLAGS_HMAC)
 			err = omap_sham_finish_req_hmac(req);
+	} else {
+		ctx->flags |= FLAGS_ERROR;
 	}
 
-	if (ctx->flags & FLAGS_FINAL)
+	if ((ctx->flags & FLAGS_FINAL) || err)
 		omap_sham_cleanup(req);
 
-	clear_bit(FLAGS_BUSY, &ctx->dd->flags);
+	clk_disable(dd->iclk);
+	dd->flags &= ~FLAGS_BUSY;
 
 	if (req->base.complete)
 		req->base.complete(&req->base, err);
 }
 
-static int omap_sham_handle_queue(struct omap_sham_dev *dd)
+static int omap_sham_handle_queue(struct omap_sham_dev *dd,
+				  struct ahash_request *req)
 {
 	struct crypto_async_request *async_req, *backlog;
 	struct omap_sham_reqctx *ctx;
-	struct ahash_request *req, *prev_req;
+	struct ahash_request *prev_req;
 	unsigned long flags;
-	int err = 0;
-
-	if (test_and_set_bit(FLAGS_BUSY, &dd->flags))
-		return 0;
+	int err = 0, ret = 0;
 
 	spin_lock_irqsave(&dd->lock, flags);
+	if (req)
+		ret = ahash_enqueue_request(&dd->queue, req);
+	if (dd->flags & FLAGS_BUSY) {
+		spin_unlock_irqrestore(&dd->lock, flags);
+		return ret;
+	}
 	backlog = crypto_get_backlog(&dd->queue);
 	async_req = crypto_dequeue_request(&dd->queue);
-	if (!async_req)
-		clear_bit(FLAGS_BUSY, &dd->flags);
+	if (async_req)
+		dd->flags |= FLAGS_BUSY;
 	spin_unlock_irqrestore(&dd->lock, flags);
 
 	if (!async_req)
-		return 0;
+		return ret;
 
 	if (backlog)
 		backlog->complete(backlog, -EINPROGRESS);
@@ -646,7 +699,22 @@ static int omap_sham_handle_queue(struct
 	dev_dbg(dd->dev, "handling new req, op: %lu, nbytes: %d\n",
 						ctx->op, req->nbytes);
 
-	if (req != prev_req && ctx->digcnt)
+
+	err = omap_sham_hw_init(dd);
+	if (err)
+		goto err1;
+
+	omap_set_dma_dest_params(dd->dma_lch, 0,
+			OMAP_DMA_AMODE_CONSTANT,
+			dd->phys_base + SHA_REG_DIN(0), 0, 16);
+
+	omap_set_dma_dest_burst_mode(dd->dma_lch,
+			OMAP_DMA_DATA_BURST_16);
+
+	omap_set_dma_src_burst_mode(dd->dma_lch,
+			OMAP_DMA_DATA_BURST_4);
+
+	if (ctx->digcnt)
 		/* request has changed - restore hash */
 		omap_sham_copy_hash(req, 0);
 
@@ -658,7 +726,7 @@ static int omap_sham_handle_queue(struct
 	} else if (ctx->op == OP_FINAL) {
 		err = omap_sham_final_req(dd);
 	}
-
+err1:
 	if (err != -EINPROGRESS) {
 		/* done_task will not finish it, so do it here */
 		omap_sham_finish_req(req, err);
@@ -667,7 +735,7 @@ static int omap_sham_handle_queue(struct
 
 	dev_dbg(dd->dev, "exit, err: %d\n", err);
 
-	return err;
+	return ret;
 }
 
 static int omap_sham_enqueue(struct ahash_request *req, unsigned int op)
@@ -675,18 +743,10 @@ static int omap_sham_enqueue(struct ahas
 	struct omap_sham_reqctx *ctx = ahash_request_ctx(req);
 	struct omap_sham_ctx *tctx = crypto_tfm_ctx(req->base.tfm);
 	struct omap_sham_dev *dd = tctx->dd;
-	unsigned long flags;
-	int err;
 
 	ctx->op = op;
 
-	spin_lock_irqsave(&dd->lock, flags);
-	err = ahash_enqueue_request(&dd->queue, req);
-	spin_unlock_irqrestore(&dd->lock, flags);
-
-	omap_sham_handle_queue(dd);
-
-	return err;
+	return omap_sham_handle_queue(dd, req);
 }
 
 static int omap_sham_update(struct ahash_request *req)
@@ -709,21 +769,13 @@ static int omap_sham_update(struct ahash
 			*/
 			omap_sham_append_sg(ctx);
 			return 0;
-		} else if (ctx->bufcnt + ctx->total <= 64) {
+		} else if (ctx->bufcnt + ctx->total <= SHA1_MD5_BLOCK_SIZE) {
+			/*
+			* faster to use CPU for short transfers
+			*/
 			ctx->flags |= FLAGS_CPU;
-		} else if (!ctx->bufcnt && sg_is_last(ctx->sg)) {
-			/* may be can use faster functions */
-			int aligned = IS_ALIGNED((u32)ctx->sg->offset,
-								sizeof(u32));
-
-			if (aligned && (ctx->flags & FLAGS_FIRST))
-				/* digest: first and final */
-				ctx->flags |= FLAGS_FAST;
-
-			ctx->flags &= ~FLAGS_FIRST;
 		}
-	} else if (ctx->bufcnt + ctx->total <= ctx->buflen) {
-		/* if not finaup -> not fast */
+	} else if (ctx->bufcnt + ctx->total < ctx->buflen) {
 		omap_sham_append_sg(ctx);
 		return 0;
 	}
@@ -761,12 +813,14 @@ static int omap_sham_final(struct ahash_
 
 	ctx->flags |= FLAGS_FINUP;
 
-	/* OMAP HW accel works only with buffers >= 9 */
-	/* HMAC is always >= 9 because of ipad */
-	if ((ctx->digcnt + ctx->bufcnt) < 9)
-		err = omap_sham_final_shash(req);
-	else if (ctx->bufcnt)
-		return omap_sham_enqueue(req, OP_FINAL);
+	if (!(ctx->flags & FLAGS_ERROR)) {
+		/* OMAP HW accel works only with buffers >= 9 */
+		/* HMAC is always >= 9 because of ipad */
+		if ((ctx->digcnt + ctx->bufcnt) < 9)
+			err = omap_sham_final_shash(req);
+		else if (ctx->bufcnt)
+			return omap_sham_enqueue(req, OP_FINAL);
+	}
 
 	omap_sham_cleanup(req);
 
@@ -836,6 +890,8 @@ static int omap_sham_cra_init_alg(struct
 	struct omap_sham_ctx *tctx = crypto_tfm_ctx(tfm);
 	const char *alg_name = crypto_tfm_alg_name(tfm);
 
+	pr_info("enter\n");
+
 	/* Allocate a fallback and abort if it failed. */
 	tctx->fallback = crypto_alloc_shash(alg_name, 0,
 					    CRYPTO_ALG_NEED_FALLBACK);
@@ -846,7 +902,7 @@ static int omap_sham_cra_init_alg(struct
 	}
 
 	crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm),
-				 sizeof(struct omap_sham_reqctx));
+				 sizeof(struct omap_sham_reqctx) + BUFLEN);
 
 	if (alg_base) {
 		struct omap_sham_hmac_ctx *bctx = tctx->base;
@@ -932,7 +988,7 @@ static struct ahash_alg algs[] = {
 						CRYPTO_ALG_NEED_FALLBACK,
 		.cra_blocksize		= SHA1_BLOCK_SIZE,
 		.cra_ctxsize		= sizeof(struct omap_sham_ctx),
-		.cra_alignmask		= 0,
+		.cra_alignmask		= OMAP_ALIGN_MASK,
 		.cra_module		= THIS_MODULE,
 		.cra_init		= omap_sham_cra_init,
 		.cra_exit		= omap_sham_cra_exit,
@@ -956,7 +1012,7 @@ static struct ahash_alg algs[] = {
 		.cra_blocksize		= SHA1_BLOCK_SIZE,
 		.cra_ctxsize		= sizeof(struct omap_sham_ctx) +
 					sizeof(struct omap_sham_hmac_ctx),
-		.cra_alignmask		= 0,
+		.cra_alignmask		= OMAP_ALIGN_MASK,
 		.cra_module		= THIS_MODULE,
 		.cra_init		= omap_sham_cra_sha1_init,
 		.cra_exit		= omap_sham_cra_exit,
@@ -980,7 +1036,7 @@ static struct ahash_alg algs[] = {
 		.cra_blocksize		= SHA1_BLOCK_SIZE,
 		.cra_ctxsize		= sizeof(struct omap_sham_ctx) +
 					sizeof(struct omap_sham_hmac_ctx),
-		.cra_alignmask		= 0,
+		.cra_alignmask		= OMAP_ALIGN_MASK,
 		.cra_module		= THIS_MODULE,
 		.cra_init		= omap_sham_cra_md5_init,
 		.cra_exit		= omap_sham_cra_exit,
@@ -993,7 +1049,7 @@ static void omap_sham_done_task(unsigned
 	struct omap_sham_dev *dd = (struct omap_sham_dev *)data;
 	struct ahash_request *req = dd->req;
 	struct omap_sham_reqctx *ctx = ahash_request_ctx(req);
-	int ready = 1;
+	int ready = 0, err = 0;
 
 	if (ctx->flags & FLAGS_OUTPUT_READY) {
 		ctx->flags &= ~FLAGS_OUTPUT_READY;
@@ -1003,15 +1059,18 @@ static void omap_sham_done_task(unsigned
 	if (dd->flags & FLAGS_DMA_ACTIVE) {
 		dd->flags &= ~FLAGS_DMA_ACTIVE;
 		omap_sham_update_dma_stop(dd);
-		omap_sham_update_dma_slow(dd);
+		if (!dd->err)
+			err = omap_sham_update_dma_start(dd);
 	}
 
-	if (ready && !(dd->flags & FLAGS_DMA_ACTIVE)) {
-		dev_dbg(dd->dev, "update done\n");
+	err = dd->err ? : err;
+
+	if (err != -EINPROGRESS && (ready || err)) {
+		dev_dbg(dd->dev, "update done: err: %d\n", err);
 		/* finish curent request */
-		omap_sham_finish_req(req, 0);
+		omap_sham_finish_req(req, err);
 		/* start new request */
-		omap_sham_handle_queue(dd);
+		omap_sham_handle_queue(dd, NULL);
 	}
 }
 
@@ -1019,7 +1078,7 @@ static void omap_sham_queue_task(unsigne
 {
 	struct omap_sham_dev *dd = (struct omap_sham_dev *)data;
 
-	omap_sham_handle_queue(dd);
+	omap_sham_handle_queue(dd, NULL);
 }
 
 static irqreturn_t omap_sham_irq(int irq, void *dev_id)
@@ -1041,6 +1100,7 @@ static irqreturn_t omap_sham_irq(int irq
 	omap_sham_read(dd, SHA_REG_CTRL);
 
 	ctx->flags |= FLAGS_OUTPUT_READY;
+	dd->err = 0;
 	tasklet_schedule(&dd->done_task);
 
 	return IRQ_HANDLED;
@@ -1050,8 +1110,13 @@ static void omap_sham_dma_callback(int l
 {
 	struct omap_sham_dev *dd = data;
 
-	if (likely(lch == dd->dma_lch))
-		tasklet_schedule(&dd->done_task);
+	if (ch_status != OMAP_DMA_BLOCK_IRQ) {
+		pr_err("omap-sham DMA error status: 0x%hx\n", ch_status);
+		dd->err = -EIO;
+		dd->flags &= ~FLAGS_INIT; /* request to re-initialize */
+	}
+
+	tasklet_schedule(&dd->done_task);
 }
 
 static int omap_sham_dma_init(struct omap_sham_dev *dd)
@@ -1066,15 +1131,6 @@ static int omap_sham_dma_init(struct oma
 		dev_err(dd->dev, "Unable to request DMA channel\n");
 		return err;
 	}
-	omap_set_dma_dest_params(dd->dma_lch, 0,
-			OMAP_DMA_AMODE_CONSTANT,
-			dd->phys_base + SHA_REG_DIN(0), 0, 16);
-
-	omap_set_dma_dest_burst_mode(dd->dma_lch,
-			OMAP_DMA_DATA_BURST_16);
-
-	omap_set_dma_src_burst_mode(dd->dma_lch,
-			OMAP_DMA_DATA_BURST_4);
 
 	return 0;
 }
diff -druNp linux-libre-2.6.37-gnu1/drivers/crypto/padlock-aes.c linux-libre-2.6.38-gnu1/drivers/crypto/padlock-aes.c
--- linux-libre-2.6.37-gnu1/drivers/crypto/padlock-aes.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/crypto/padlock-aes.c	2011-03-14 21:20:32.000000000 -0400
@@ -9,6 +9,7 @@
 
 #include <crypto/algapi.h>
 #include <crypto/aes.h>
+#include <crypto/padlock.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/types.h>
@@ -21,7 +22,6 @@
 #include <asm/byteorder.h>
 #include <asm/processor.h>
 #include <asm/i387.h>
-#include "padlock.h"
 
 /*
  * Number of data blocks actually fetched for each xcrypt insn.
diff -druNp linux-libre-2.6.37-gnu1/drivers/crypto/padlock.h linux-libre-2.6.38-gnu1/drivers/crypto/padlock.h
--- linux-libre-2.6.37-gnu1/drivers/crypto/padlock.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/crypto/padlock.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,23 +0,0 @@
-/*
- * Driver for VIA PadLock
- *
- * Copyright (c) 2004 Michal Ludvig <michal@logix.cz>
- *
- * 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 _CRYPTO_PADLOCK_H
-#define _CRYPTO_PADLOCK_H
-
-#define PADLOCK_ALIGNMENT 16
-
-#define PFX	"padlock: "
-
-#define PADLOCK_CRA_PRIORITY	300
-#define PADLOCK_COMPOSITE_PRIORITY 400
-
-#endif	/* _CRYPTO_PADLOCK_H */
diff -druNp linux-libre-2.6.37-gnu1/drivers/crypto/padlock-sha.c linux-libre-2.6.38-gnu1/drivers/crypto/padlock-sha.c
--- linux-libre-2.6.37-gnu1/drivers/crypto/padlock-sha.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/crypto/padlock-sha.c	2011-03-14 21:20:32.000000000 -0400
@@ -13,6 +13,7 @@
  */
 
 #include <crypto/internal/hash.h>
+#include <crypto/padlock.h>
 #include <crypto/sha.h>
 #include <linux/err.h>
 #include <linux/module.h>
@@ -22,13 +23,6 @@
 #include <linux/kernel.h>
 #include <linux/scatterlist.h>
 #include <asm/i387.h>
-#include "padlock.h"
-
-#ifdef CONFIG_64BIT
-#define STACK_ALIGN 16
-#else
-#define STACK_ALIGN 4
-#endif
 
 struct padlock_sha_desc {
 	struct shash_desc fallback;
diff -druNp linux-libre-2.6.37-gnu1/drivers/dca/dca-core.c linux-libre-2.6.38-gnu1/drivers/dca/dca-core.c
--- linux-libre-2.6.37-gnu1/drivers/dca/dca-core.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/dca/dca-core.c	2011-03-14 21:20:32.000000000 -0400
@@ -110,8 +110,6 @@ static void unregister_dca_providers(voi
 
 	/* at this point only one domain in the list is expected */
 	domain = list_first_entry(&dca_domains, struct dca_domain, node);
-	if (!domain)
-		return;
 
 	list_for_each_entry_safe(dca, _dca, &domain->dca_providers, node) {
 		list_del(&dca->node);
diff -druNp linux-libre-2.6.37-gnu1/drivers/dma/amba-pl08x.c linux-libre-2.6.38-gnu1/drivers/dma/amba-pl08x.c
--- linux-libre-2.6.37-gnu1/drivers/dma/amba-pl08x.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/dma/amba-pl08x.c	2011-03-14 21:20:32.000000000 -0400
@@ -19,14 +19,14 @@
  * this program; if not, write to the Free Software Foundation, Inc., 59
  * Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  *
- * The full GNU General Public License is iin this distribution in the
- * file called COPYING.
+ * The full GNU General Public License is in this distribution in the file
+ * called COPYING.
  *
  * Documentation: ARM DDI 0196G == PL080
- * Documentation: ARM DDI 0218E	== PL081
+ * Documentation: ARM DDI 0218E == PL081
  *
- * PL080 & PL081 both have 16 sets of DMA signals that can be routed to
- * any channel.
+ * PL080 & PL081 both have 16 sets of DMA signals that can be routed to any
+ * channel.
  *
  * The PL080 has 8 channels available for simultaneous use, and the PL081
  * has only two channels. So on these DMA controllers the number of channels
@@ -53,7 +53,23 @@
  *
  * ASSUMES default (little) endianness for DMA transfers
  *
- * Only DMAC flow control is implemented
+ * The PL08x has two flow control settings:
+ *  - DMAC flow control: the transfer size defines the number of transfers
+ *    which occur for the current LLI entry, and the DMAC raises TC at the
+ *    end of every LLI entry.  Observed behaviour shows the DMAC listening
+ *    to both the BREQ and SREQ signals (contrary to documented),
+ *    transferring data if either is active.  The LBREQ and LSREQ signals
+ *    are ignored.
+ *
+ *  - Peripheral flow control: the transfer size is ignored (and should be
+ *    zero).  The data is transferred from the current LLI entry, until
+ *    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
@@ -61,50 +77,40 @@
 #include <linux/device.h>
 #include <linux/init.h>
 #include <linux/module.h>
-#include <linux/pci.h>
 #include <linux/interrupt.h>
 #include <linux/slab.h>
+#include <linux/delay.h>
 #include <linux/dmapool.h>
-#include <linux/amba/bus.h>
 #include <linux/dmaengine.h>
+#include <linux/amba/bus.h>
 #include <linux/amba/pl08x.h>
 #include <linux/debugfs.h>
 #include <linux/seq_file.h>
 
 #include <asm/hardware/pl080.h>
-#include <asm/dma.h>
-#include <asm/mach/dma.h>
-#include <asm/atomic.h>
-#include <asm/processor.h>
-#include <asm/cacheflush.h>
 
 #define DRIVER_NAME	"pl08xdmac"
 
 /**
- * struct vendor_data - vendor-specific config parameters
- * for PL08x derivates
- * @name: the name of this specific variant
+ * struct vendor_data - vendor-specific config parameters for PL08x derivatives
  * @channels: the number of channels available in this variant
- * @dualmaster: whether this version supports dual AHB masters
- * or not.
+ * @dualmaster: whether this version supports dual AHB masters or not.
  */
 struct vendor_data {
-	char *name;
 	u8 channels;
 	bool dualmaster;
 };
 
 /*
  * PL08X private data structures
- * An LLI struct - see pl08x TRM
- * Note that next uses bit[0] as a bus bit,
- * start & end do not - their bus bit info
- * is in cctl
+ * An LLI struct - see PL08x TRM.  Note that next uses bit[0] as a bus bit,
+ * start & end do not - their bus bit info is in cctl.  Also note that these
+ * are fixed 32-bit quantities.
  */
-struct lli {
-	dma_addr_t src;
-	dma_addr_t dst;
-	dma_addr_t next;
+struct pl08x_lli {
+	u32 src;
+	u32 dst;
+	u32 lli;
 	u32 cctl;
 };
 
@@ -119,6 +125,8 @@ struct 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
+ * @mem_buses: set to indicate memory transfers on AHB2.
  * @lock: a spinlock for this struct
  */
 struct pl08x_driver_data {
@@ -126,11 +134,13 @@ struct pl08x_driver_data {
 	struct dma_device memcpy;
 	void __iomem *base;
 	struct amba_device *adev;
-	struct vendor_data *vd;
+	const struct vendor_data *vd;
 	struct pl08x_platform_data *pd;
 	struct pl08x_phy_chan *phy_chans;
 	struct dma_pool *pool;
 	int pool_ctr;
+	u8 lli_buses;
+	u8 mem_buses;
 	spinlock_t lock;
 };
 
@@ -152,9 +162,9 @@ struct pl08x_driver_data {
 /* Size (bytes) of each LLI buffer allocated for one transfer */
 # define PL08X_LLI_TSFR_SIZE	0x2000
 
-/* Maximimum times we call dma_pool_alloc on this pool without freeing */
+/* Maximum times we call dma_pool_alloc on this pool without freeing */
 #define PL08X_MAX_ALLOCS	0x40
-#define MAX_NUM_TSFR_LLIS	(PL08X_LLI_TSFR_SIZE/sizeof(struct lli))
+#define MAX_NUM_TSFR_LLIS	(PL08X_LLI_TSFR_SIZE/sizeof(struct pl08x_lli))
 #define PL08X_ALIGN		8
 
 static inline struct pl08x_dma_chan *to_pl08x_chan(struct dma_chan *chan)
@@ -162,6 +172,11 @@ static inline struct pl08x_dma_chan *to_
 	return container_of(chan, struct pl08x_dma_chan, chan);
 }
 
+static inline struct pl08x_txd *to_pl08x_txd(struct dma_async_tx_descriptor *tx)
+{
+	return container_of(tx, struct pl08x_txd, tx);
+}
+
 /*
  * Physical channel handling
  */
@@ -177,103 +192,63 @@ static int pl08x_phy_channel_busy(struct
 
 /*
  * Set the initial DMA register values i.e. those for the first LLI
- * The next lli pointer and the configuration interrupt bit have
- * been set when the LLIs were constructed
+ * The next LLI pointer and the configuration interrupt bit have
+ * been set when the LLIs were constructed.  Poke them into the hardware
+ * and start the transfer.
  */
-static void pl08x_set_cregs(struct pl08x_driver_data *pl08x,
-			    struct pl08x_phy_chan *ch)
-{
-	/* Wait for channel inactive */
-	while (pl08x_phy_channel_busy(ch))
-		;
-
-	dev_vdbg(&pl08x->adev->dev,
-		"WRITE channel %d: csrc=%08x, cdst=%08x, "
-		 "cctl=%08x, clli=%08x, ccfg=%08x\n",
-		ch->id,
-		ch->csrc,
-		ch->cdst,
-		ch->cctl,
-		ch->clli,
-		ch->ccfg);
-
-	writel(ch->csrc, ch->base + PL080_CH_SRC_ADDR);
-	writel(ch->cdst, ch->base + PL080_CH_DST_ADDR);
-	writel(ch->clli, ch->base + PL080_CH_LLI);
-	writel(ch->cctl, ch->base + PL080_CH_CONTROL);
-	writel(ch->ccfg, ch->base + PL080_CH_CONFIG);
-}
-
-static inline void pl08x_config_phychan_for_txd(struct pl08x_dma_chan *plchan)
+static void pl08x_start_txd(struct pl08x_dma_chan *plchan,
+	struct pl08x_txd *txd)
 {
-	struct pl08x_channel_data *cd = plchan->cd;
+	struct pl08x_driver_data *pl08x = plchan->host;
 	struct pl08x_phy_chan *phychan = plchan->phychan;
-	struct pl08x_txd *txd = plchan->at;
+	struct pl08x_lli *lli = &txd->llis_va[0];
+	u32 val;
 
-	/* Copy the basic control register calculated at transfer config */
-	phychan->csrc = txd->csrc;
-	phychan->cdst = txd->cdst;
-	phychan->clli = txd->clli;
-	phychan->cctl = txd->cctl;
+	plchan->at = txd;
 
-	/* Assign the signal to the proper control registers */
-	phychan->ccfg = cd->ccfg;
-	phychan->ccfg &= ~PL080_CONFIG_SRC_SEL_MASK;
-	phychan->ccfg &= ~PL080_CONFIG_DST_SEL_MASK;
-	/* If it wasn't set from AMBA, ignore it */
-	if (txd->direction == DMA_TO_DEVICE)
-		/* Select signal as destination */
-		phychan->ccfg |=
-			(phychan->signal << PL080_CONFIG_DST_SEL_SHIFT);
-	else if (txd->direction == DMA_FROM_DEVICE)
-		/* Select signal as source */
-		phychan->ccfg |=
-			(phychan->signal << PL080_CONFIG_SRC_SEL_SHIFT);
-	/* Always enable error interrupts */
-	phychan->ccfg |= PL080_CONFIG_ERR_IRQ_MASK;
-	/* Always enable terminal interrupts */
-	phychan->ccfg |= PL080_CONFIG_TC_IRQ_MASK;
-}
+	/* Wait for channel inactive */
+	while (pl08x_phy_channel_busy(phychan))
+		cpu_relax();
 
-/*
- * Enable the DMA channel
- * Assumes all other configuration bits have been set
- * as desired before this code is called
- */
-static void pl08x_enable_phy_chan(struct pl08x_driver_data *pl08x,
-				  struct pl08x_phy_chan *ch)
-{
-	u32 val;
+	dev_vdbg(&pl08x->adev->dev,
+		"WRITE channel %d: csrc=0x%08x, cdst=0x%08x, "
+		"clli=0x%08x, cctl=0x%08x, ccfg=0x%08x\n",
+		phychan->id, lli->src, lli->dst, lli->lli, lli->cctl,
+		txd->ccfg);
 
-	/*
-	 * Do not access config register until channel shows as disabled
-	 */
-	while (readl(pl08x->base + PL080_EN_CHAN) & (1 << ch->id))
-		;
+	writel(lli->src, phychan->base + PL080_CH_SRC_ADDR);
+	writel(lli->dst, phychan->base + PL080_CH_DST_ADDR);
+	writel(lli->lli, phychan->base + PL080_CH_LLI);
+	writel(lli->cctl, phychan->base + PL080_CH_CONTROL);
+	writel(txd->ccfg, phychan->base + PL080_CH_CONFIG);
 
-	/*
-	 * Do not access config register until channel shows as inactive
-	 */
-	val = readl(ch->base + PL080_CH_CONFIG);
+	/* Enable the DMA channel */
+	/* Do not access config register until channel shows as disabled */
+	while (readl(pl08x->base + PL080_EN_CHAN) & (1 << phychan->id))
+		cpu_relax();
+
+	/* Do not access config register until channel shows as inactive */
+	val = readl(phychan->base + PL080_CH_CONFIG);
 	while ((val & PL080_CONFIG_ACTIVE) || (val & PL080_CONFIG_ENABLE))
-		val = readl(ch->base + PL080_CH_CONFIG);
+		val = readl(phychan->base + PL080_CH_CONFIG);
 
-	writel(val | PL080_CONFIG_ENABLE, ch->base + PL080_CH_CONFIG);
+	writel(val | PL080_CONFIG_ENABLE, phychan->base + PL080_CH_CONFIG);
 }
 
 /*
- * Overall DMAC remains enabled always.
- *
- * Disabling individual channels could lose data.
+ * Pause the channel by setting the HALT bit.
  *
- * Disable the peripheral DMA after disabling the DMAC
- * in order to allow the DMAC FIFO to drain, and
- * hence allow the channel to show inactive
+ * For M->P transfers, pause the DMAC first and then stop the peripheral -
+ * the FIFO can only drain if the peripheral is still requesting data.
+ * (note: this can still timeout if the DMAC FIFO never drains of data.)
  *
+ * For P->M transfers, disable the peripheral first to stop it filling
+ * the DMAC FIFO, and then pause the DMAC.
  */
 static void pl08x_pause_phy_chan(struct pl08x_phy_chan *ch)
 {
 	u32 val;
+	int timeout;
 
 	/* Set the HALT bit and wait for the FIFO to drain */
 	val = readl(ch->base + PL080_CH_CONFIG);
@@ -281,8 +256,13 @@ static void pl08x_pause_phy_chan(struct
 	writel(val, ch->base + PL080_CH_CONFIG);
 
 	/* Wait for channel inactive */
-	while (pl08x_phy_channel_busy(ch))
-		;
+	for (timeout = 1000; timeout; timeout--) {
+		if (!pl08x_phy_channel_busy(ch))
+			break;
+		udelay(1);
+	}
+	if (pl08x_phy_channel_busy(ch))
+		pr_err("pl08x: channel%u timeout waiting for pause\n", ch->id);
 }
 
 static void pl08x_resume_phy_chan(struct pl08x_phy_chan *ch)
@@ -296,19 +276,24 @@ static void pl08x_resume_phy_chan(struct
 }
 
 
-/* Stops the channel */
-static void pl08x_stop_phy_chan(struct pl08x_phy_chan *ch)
+/*
+ * pl08x_terminate_phy_chan() stops the channel, clears the FIFO and
+ * clears any pending interrupt status.  This should not be used for
+ * an on-going transfer, but as a method of shutting down a channel
+ * (eg, when it's no longer used) or terminating a transfer.
+ */
+static void pl08x_terminate_phy_chan(struct pl08x_driver_data *pl08x,
+	struct pl08x_phy_chan *ch)
 {
-	u32 val;
+	u32 val = readl(ch->base + PL080_CH_CONFIG);
 
-	pl08x_pause_phy_chan(ch);
+	val &= ~(PL080_CONFIG_ENABLE | PL080_CONFIG_ERR_IRQ_MASK |
+	         PL080_CONFIG_TC_IRQ_MASK);
 
-	/* Disable channel */
-	val = readl(ch->base + PL080_CH_CONFIG);
-	val &= ~PL080_CONFIG_ENABLE;
-	val &= ~PL080_CONFIG_ERR_IRQ_MASK;
-	val &= ~PL080_CONFIG_TC_IRQ_MASK;
 	writel(val, ch->base + PL080_CH_CONFIG);
+
+	writel(1 << ch->id, pl08x->base + PL080_ERR_CLEAR);
+	writel(1 << ch->id, pl08x->base + PL080_TC_CLEAR);
 }
 
 static inline u32 get_bytes_in_cctl(u32 cctl)
@@ -333,54 +318,56 @@ static inline u32 get_bytes_in_cctl(u32
 static u32 pl08x_getbytes_chan(struct pl08x_dma_chan *plchan)
 {
 	struct pl08x_phy_chan *ch;
-	struct pl08x_txd *txdi = NULL;
 	struct pl08x_txd *txd;
 	unsigned long flags;
-	u32 bytes = 0;
+	size_t bytes = 0;
 
 	spin_lock_irqsave(&plchan->lock, flags);
-
 	ch = plchan->phychan;
 	txd = plchan->at;
 
 	/*
-	 * Next follow the LLIs to get the number of pending bytes in the
-	 * currently active transaction.
+	 * Follow the LLIs to get the number of remaining
+	 * bytes in the currently active transaction.
 	 */
 	if (ch && txd) {
-		struct lli *llis_va = txd->llis_va;
-		struct lli *llis_bus = (struct lli *) txd->llis_bus;
-		u32 clli = readl(ch->base + PL080_CH_LLI);
+		u32 clli = readl(ch->base + PL080_CH_LLI) & ~PL080_LLI_LM_AHB2;
 
-		/* First get the bytes in the current active LLI */
+		/* First get the remaining bytes in the active transfer */
 		bytes = get_bytes_in_cctl(readl(ch->base + PL080_CH_CONTROL));
 
 		if (clli) {
-			int i = 0;
+			struct pl08x_lli *llis_va = txd->llis_va;
+			dma_addr_t llis_bus = txd->llis_bus;
+			int index;
 
-			/* Forward to the LLI pointed to by clli */
-			while ((clli != (u32) &(llis_bus[i])) &&
-			       (i < MAX_NUM_TSFR_LLIS))
-				i++;
+			BUG_ON(clli < llis_bus || clli >= llis_bus +
+				sizeof(struct pl08x_lli) * MAX_NUM_TSFR_LLIS);
+
+			/*
+			 * Locate the next LLI - as this is an array,
+			 * it's simple maths to find.
+			 */
+			index = (clli - llis_bus) / sizeof(struct pl08x_lli);
+
+			for (; index < MAX_NUM_TSFR_LLIS; index++) {
+				bytes += get_bytes_in_cctl(llis_va[index].cctl);
 
-			while (clli) {
-				bytes += get_bytes_in_cctl(llis_va[i].cctl);
 				/*
-				 * A clli of 0x00000000 will terminate the
-				 * LLI list
+				 * A LLI pointer of 0 terminates the LLI list
 				 */
-				clli = llis_va[i].next;
-				i++;
+				if (!llis_va[index].lli)
+					break;
 			}
 		}
 	}
 
 	/* Sum up all queued transactions */
-	if (!list_empty(&plchan->desc_list)) {
-		list_for_each_entry(txdi, &plchan->desc_list, node) {
+	if (!list_empty(&plchan->pend_list)) {
+		struct pl08x_txd *txdi;
+		list_for_each_entry(txdi, &plchan->pend_list, node) {
 			bytes += txdi->len;
 		}
-
 	}
 
 	spin_unlock_irqrestore(&plchan->lock, flags);
@@ -390,6 +377,10 @@ static u32 pl08x_getbytes_chan(struct pl
 
 /*
  * Allocate a physical channel for a virtual channel
+ *
+ * Try to locate a physical channel to be used for this transfer. If all
+ * are taken return NULL and the requester will have to cope by using
+ * some fallback PIO mode or retrying later.
  */
 static struct pl08x_phy_chan *
 pl08x_get_phy_channel(struct pl08x_driver_data *pl08x,
@@ -399,12 +390,6 @@ pl08x_get_phy_channel(struct pl08x_drive
 	unsigned long flags;
 	int i;
 
-	/*
-	 * Try to locate a physical channel to be used for
-	 * this transfer. If all are taken return NULL and
-	 * the requester will have to cope by using some fallback
-	 * PIO mode or retrying later.
-	 */
 	for (i = 0; i < pl08x->vd->channels; i++) {
 		ch = &pl08x->phy_chans[i];
 
@@ -433,13 +418,12 @@ static inline void pl08x_put_phy_channel
 {
 	unsigned long flags;
 
+	spin_lock_irqsave(&ch->lock, flags);
+
 	/* Stop the channel and clear its interrupts */
-	pl08x_stop_phy_chan(ch);
-	writel((1 << ch->id), pl08x->base + PL080_ERR_CLEAR);
-	writel((1 << ch->id), pl08x->base + PL080_TC_CLEAR);
+	pl08x_terminate_phy_chan(pl08x, ch);
 
 	/* Mark it as free */
-	spin_lock_irqsave(&ch->lock, flags);
 	ch->serving = NULL;
 	spin_unlock_irqrestore(&ch->lock, flags);
 }
@@ -465,11 +449,11 @@ static inline unsigned int pl08x_get_byt
 }
 
 static inline u32 pl08x_cctl_bits(u32 cctl, u8 srcwidth, u8 dstwidth,
-				  u32 tsize)
+				  size_t tsize)
 {
 	u32 retbits = cctl;
 
-	/* Remove all src, dst and transfersize bits */
+	/* Remove all src, dst and transfer size bits */
 	retbits &= ~PL080_CONTROL_DWIDTH_MASK;
 	retbits &= ~PL080_CONTROL_SWIDTH_MASK;
 	retbits &= ~PL080_CONTROL_TRANSFER_SIZE_MASK;
@@ -509,95 +493,87 @@ static inline u32 pl08x_cctl_bits(u32 cc
 	return retbits;
 }
 
+struct pl08x_lli_build_data {
+	struct pl08x_txd *txd;
+	struct pl08x_driver_data *pl08x;
+	struct pl08x_bus_data srcbus;
+	struct pl08x_bus_data dstbus;
+	size_t remainder;
+};
+
 /*
- * 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 this prefers the
+ * destination bus if both available if fixed address on one bus the
+ * other will be chosen
  */
-void pl08x_choose_master_bus(struct pl08x_bus_data *src_bus,
-	struct pl08x_bus_data *dst_bus, struct pl08x_bus_data **mbus,
-	struct pl08x_bus_data **sbus, u32 cctl)
+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 = src_bus;
-		*sbus = dst_bus;
+		*mbus = &bd->srcbus;
+		*sbus = &bd->dstbus;
 	} else if (!(cctl & PL080_CONTROL_SRC_INCR)) {
-		*mbus = dst_bus;
-		*sbus = src_bus;
+		*mbus = &bd->dstbus;
+		*sbus = &bd->srcbus;
 	} else {
-		if (dst_bus->buswidth == 4) {
-			*mbus = dst_bus;
-			*sbus = src_bus;
-		} else if (src_bus->buswidth == 4) {
-			*mbus = src_bus;
-			*sbus = dst_bus;
-		} else if (dst_bus->buswidth == 2) {
-			*mbus = dst_bus;
-			*sbus = src_bus;
-		} else if (src_bus->buswidth == 2) {
-			*mbus = src_bus;
-			*sbus = dst_bus;
+		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) {
+			*mbus = &bd->dstbus;
+			*sbus = &bd->srcbus;
+		} else if (bd->srcbus.buswidth == 2) {
+			*mbus = &bd->srcbus;
+			*sbus = &bd->dstbus;
 		} else {
-			/* src_bus->buswidth == 1 */
-			*mbus = dst_bus;
-			*sbus = src_bus;
+			/* bd->srcbus.buswidth == 1 */
+			*mbus = &bd->dstbus;
+			*sbus = &bd->srcbus;
 		}
 	}
 }
 
 /*
- * Fills in one LLI for a certain transfer descriptor
- * and advance the counter
+ * Fills in one LLI for a certain transfer descriptor and advance the counter
  */
-int pl08x_fill_lli_for_desc(struct pl08x_driver_data *pl08x,
-			    struct pl08x_txd *txd, int num_llis, int len,
-			    u32 cctl, u32 *remainder)
+static void pl08x_fill_lli_for_desc(struct pl08x_lli_build_data *bd,
+	int num_llis, int len, u32 cctl)
 {
-	struct lli *llis_va = txd->llis_va;
-	struct lli *llis_bus = (struct lli *) txd->llis_bus;
+	struct pl08x_lli *llis_va = bd->txd->llis_va;
+	dma_addr_t llis_bus = bd->txd->llis_bus;
 
 	BUG_ON(num_llis >= MAX_NUM_TSFR_LLIS);
 
-	llis_va[num_llis].cctl		= cctl;
-	llis_va[num_llis].src		= txd->srcbus.addr;
-	llis_va[num_llis].dst		= txd->dstbus.addr;
-
-	/*
-	 * On versions with dual masters, you can optionally AND on
-	 * PL080_LLI_LM_AHB2 to the LLI to tell the hardware to read
-	 * in new LLIs with that controller, but we always try to
-	 * choose AHB1 to point into memory. The idea is to have AHB2
-	 * fixed on the peripheral and AHB1 messing around in the
-	 * memory. So we don't manipulate this bit currently.
-	 */
-
-	llis_va[num_llis].next =
-		(dma_addr_t)((u32) &(llis_bus[num_llis + 1]));
+	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);
+	if (bd->pl08x->lli_buses & PL08X_AHB2)
+		llis_va[num_llis].lli |= PL080_LLI_LM_AHB2;
 
 	if (cctl & PL080_CONTROL_SRC_INCR)
-		txd->srcbus.addr += len;
+		bd->srcbus.addr += len;
 	if (cctl & PL080_CONTROL_DST_INCR)
-		txd->dstbus.addr += len;
+		bd->dstbus.addr += len;
 
-	*remainder -= len;
+	BUG_ON(bd->remainder < len);
 
-	return num_llis + 1;
+	bd->remainder -= len;
 }
 
 /*
- * Return number of bytes to fill to boundary, or len
+ * Return number of bytes to fill to boundary, or len.
+ * This calculation works for any value of addr.
  */
-static inline u32 pl08x_pre_boundary(u32 addr, u32 len)
+static inline size_t pl08x_pre_boundary(u32 addr, size_t len)
 {
-	u32 boundary;
-
-	boundary = ((addr >> PL08X_BOUNDARY_SHIFT) + 1)
-		<< PL08X_BOUNDARY_SHIFT;
+	size_t boundary_len = PL08X_BOUNDARY_SIZE -
+			(addr & (PL08X_BOUNDARY_SIZE - 1));
 
-	if (boundary < addr + len)
-		return boundary - addr;
-	else
-		return len;
+	return min(boundary_len, len);
 }
 
 /*
@@ -608,20 +584,13 @@ static inline u32 pl08x_pre_boundary(u32
 static int pl08x_fill_llis_for_desc(struct pl08x_driver_data *pl08x,
 			      struct pl08x_txd *txd)
 {
-	struct pl08x_channel_data *cd = txd->cd;
 	struct pl08x_bus_data *mbus, *sbus;
-	u32 remainder;
+	struct pl08x_lli_build_data bd;
 	int num_llis = 0;
 	u32 cctl;
-	int max_bytes_per_lli;
-	int total_bytes = 0;
-	struct lli *llis_va;
-	struct lli *llis_bus;
-
-	if (!txd) {
-		dev_err(&pl08x->adev->dev, "%s no descriptor\n", __func__);
-		return 0;
-	}
+	size_t max_bytes_per_lli;
+	size_t total_bytes = 0;
+	struct pl08x_lli *llis_va;
 
 	txd->llis_va = dma_pool_alloc(pl08x->pool, GFP_NOWAIT,
 				      &txd->llis_bus);
@@ -632,121 +601,79 @@ static int pl08x_fill_llis_for_desc(stru
 
 	pl08x->pool_ctr++;
 
-	/*
-	 * Initialize bus values for this transfer
-	 * from the passed optimal values
-	 */
-	if (!cd) {
-		dev_err(&pl08x->adev->dev, "%s no channel data\n", __func__);
-		return 0;
-	}
-
-	/* Get the default CCTL from the platform data */
-	cctl = cd->cctl;
+	/* Get the default CCTL */
+	cctl = txd->cctl;
 
-	/*
-	 * On the PL080 we have two bus masters and we
-	 * should select one for source and one for
-	 * destination. We try to use AHB2 for the
-	 * bus which does not increment (typically the
-	 * peripheral) else we just choose something.
-	 */
-	cctl &= ~(PL080_CONTROL_DST_AHB2 | PL080_CONTROL_SRC_AHB2);
-	if (pl08x->vd->dualmaster) {
-		if (cctl & PL080_CONTROL_SRC_INCR)
-			/* Source increments, use AHB2 for destination */
-			cctl |= PL080_CONTROL_DST_AHB2;
-		else if (cctl & PL080_CONTROL_DST_INCR)
-			/* Destination increments, use AHB2 for source */
-			cctl |= PL080_CONTROL_SRC_AHB2;
-		else
-			/* Just pick something, source AHB1 dest AHB2 */
-			cctl |= PL080_CONTROL_DST_AHB2;
-	}
+	bd.txd = txd;
+	bd.pl08x = pl08x;
+	bd.srcbus.addr = txd->src_addr;
+	bd.dstbus.addr = txd->dst_addr;
 
 	/* Find maximum width of the source bus */
-	txd->srcbus.maxwidth =
+	bd.srcbus.maxwidth =
 		pl08x_get_bytes_for_cctl((cctl & PL080_CONTROL_SWIDTH_MASK) >>
 				       PL080_CONTROL_SWIDTH_SHIFT);
 
 	/* Find maximum width of the destination bus */
-	txd->dstbus.maxwidth =
+	bd.dstbus.maxwidth =
 		pl08x_get_bytes_for_cctl((cctl & PL080_CONTROL_DWIDTH_MASK) >>
 				       PL080_CONTROL_DWIDTH_SHIFT);
 
 	/* Set up the bus widths to the maximum */
-	txd->srcbus.buswidth = txd->srcbus.maxwidth;
-	txd->dstbus.buswidth = txd->dstbus.maxwidth;
+	bd.srcbus.buswidth = bd.srcbus.maxwidth;
+	bd.dstbus.buswidth = bd.dstbus.maxwidth;
 	dev_vdbg(&pl08x->adev->dev,
 		 "%s source bus is %d bytes wide, dest bus is %d bytes wide\n",
-		 __func__, txd->srcbus.buswidth, txd->dstbus.buswidth);
+		 __func__, bd.srcbus.buswidth, bd.dstbus.buswidth);
 
 
 	/*
 	 * Bytes transferred == tsize * MIN(buswidths), not max(buswidths)
 	 */
-	max_bytes_per_lli = min(txd->srcbus.buswidth, txd->dstbus.buswidth) *
+	max_bytes_per_lli = min(bd.srcbus.buswidth, bd.dstbus.buswidth) *
 		PL080_CONTROL_TRANSFER_SIZE_MASK;
 	dev_vdbg(&pl08x->adev->dev,
-		 "%s max bytes per lli = %d\n",
+		 "%s max bytes per lli = %zu\n",
 		 __func__, max_bytes_per_lli);
 
 	/* We need to count this down to zero */
-	remainder = txd->len;
+	bd.remainder = txd->len;
 	dev_vdbg(&pl08x->adev->dev,
-		 "%s remainder = %d\n",
-		 __func__, remainder);
+		 "%s remainder = %zu\n",
+		 __func__, bd.remainder);
 
 	/*
 	 * Choose bus to align to
 	 * - prefers destination bus if both available
 	 * - if fixed address on one bus chooses other
-	 * - modifies cctl to choose an apropriate master
-	 */
-	pl08x_choose_master_bus(&txd->srcbus, &txd->dstbus,
-				&mbus, &sbus, cctl);
-
-
-	/*
-	 * The lowest bit of the LLI register
-	 * is also used to indicate which master to
-	 * use for reading the LLIs.
 	 */
+	pl08x_choose_master_bus(&bd, &mbus, &sbus, cctl);
 
 	if (txd->len < mbus->buswidth) {
-		/*
-		 * Less than a bus width available
-		 * - send as single bytes
-		 */
-		while (remainder) {
+		/* 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 %08x)\n",
-				 __func__, remainder);
+				 "less than a bus width (remain 0x%08x)\n",
+				 __func__, bd.remainder);
 			cctl = pl08x_cctl_bits(cctl, 1, 1, 1);
-			num_llis =
-				pl08x_fill_lli_for_desc(pl08x, txd, num_llis, 1,
-					cctl, &remainder);
+			pl08x_fill_lli_for_desc(&bd, num_llis++, 1, cctl);
 			total_bytes++;
 		}
 	} else {
-		/*
-		 *  Make one byte LLIs until master bus is aligned
-		 *  - slave will then be aligned also
-		 */
+		/* 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 %08x)\n",
-				 __func__, remainder);
+				 "(remain 0x%08x)\n",
+				 __func__, bd.remainder);
 			cctl = pl08x_cctl_bits(cctl, 1, 1, 1);
-			num_llis = pl08x_fill_lli_for_desc
-				(pl08x, txd, num_llis, 1, cctl, &remainder);
+			pl08x_fill_lli_for_desc(&bd, num_llis++, 1, cctl);
 			total_bytes++;
 		}
 
 		/*
-		 *  Master now aligned
+		 * Master now aligned
 		 * - if slave is not then we must set its width down
 		 */
 		if (sbus->addr % sbus->buswidth) {
@@ -761,63 +688,51 @@ static int pl08x_fill_llis_for_desc(stru
 		 * Make largest possible LLIs until less than one bus
 		 * width left
 		 */
-		while (remainder > (mbus->buswidth - 1)) {
-			int lli_len, target_len;
-			int tsize;
-			int odd_bytes;
+		while (bd.remainder > (mbus->buswidth - 1)) {
+			size_t lli_len, target_len, tsize, odd_bytes;
 
 			/*
 			 * If enough left try to send max possible,
 			 * otherwise try to send the remainder
 			 */
-			target_len = remainder;
-			if (remainder > max_bytes_per_lli)
-				target_len = max_bytes_per_lli;
+			target_len = min(bd.remainder, max_bytes_per_lli);
 
 			/*
-			 * Set bus lengths for incrementing busses
-			 * to number of bytes which fill to next memory
-			 * boundary
+			 * Set bus lengths for incrementing buses to the
+			 * number of bytes which fill to next memory boundary,
+			 * limiting on the target length calculated above.
 			 */
 			if (cctl & PL080_CONTROL_SRC_INCR)
-				txd->srcbus.fill_bytes =
-					pl08x_pre_boundary(
-						txd->srcbus.addr,
-						remainder);
+				bd.srcbus.fill_bytes =
+					pl08x_pre_boundary(bd.srcbus.addr,
+						target_len);
 			else
-				txd->srcbus.fill_bytes =
-					max_bytes_per_lli;
+				bd.srcbus.fill_bytes = target_len;
 
 			if (cctl & PL080_CONTROL_DST_INCR)
-				txd->dstbus.fill_bytes =
-					pl08x_pre_boundary(
-						txd->dstbus.addr,
-						remainder);
+				bd.dstbus.fill_bytes =
+					pl08x_pre_boundary(bd.dstbus.addr,
+						target_len);
 			else
-				txd->dstbus.fill_bytes =
-						max_bytes_per_lli;
+				bd.dstbus.fill_bytes = target_len;
 
-			/*
-			 *  Find the nearest
-			 */
-			lli_len	= min(txd->srcbus.fill_bytes,
-				txd->dstbus.fill_bytes);
+			/* Find the nearest */
+			lli_len	= min(bd.srcbus.fill_bytes,
+				      bd.dstbus.fill_bytes);
 
-			BUG_ON(lli_len > remainder);
+			BUG_ON(lli_len > bd.remainder);
 
 			if (lli_len <= 0) {
 				dev_err(&pl08x->adev->dev,
-					"%s lli_len is %d, <= 0\n",
+					"%s lli_len is %zu, <= 0\n",
 						__func__, lli_len);
 				return 0;
 			}
 
 			if (lli_len == target_len) {
 				/*
-				 * Can send what we wanted
-				 */
-				/*
-				 *  Maintain alignment
+				 * Can send what we wanted.
+				 * Maintain alignment
 				 */
 				lli_len	= (lli_len/mbus->buswidth) *
 							mbus->buswidth;
@@ -825,17 +740,14 @@ static int pl08x_fill_llis_for_desc(stru
 			} 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
+				 * 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.
 				 */
 				odd_bytes = lli_len % mbus->buswidth;
-				/*
-				 * - and that we are working in multiples
-				 *   of the bus widths
-				 */
 				lli_len -= odd_bytes;
 
 			}
@@ -855,41 +767,38 @@ static int pl08x_fill_llis_for_desc(stru
 
 				if (target_len != lli_len) {
 					dev_vdbg(&pl08x->adev->dev,
-					"%s can't send what we want. Desired %08x, lli of %08x bytes in txd of %08x\n",
+					"%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,
-						       txd->srcbus.buswidth,
-						       txd->dstbus.buswidth,
+						       bd.srcbus.buswidth,
+						       bd.dstbus.buswidth,
 						       tsize);
 
 				dev_vdbg(&pl08x->adev->dev,
-					"%s fill lli with single lli chunk of size %08x (remainder %08x)\n",
-					__func__, lli_len, remainder);
-				num_llis = pl08x_fill_lli_for_desc(pl08x, txd,
-						num_llis, lli_len, cctl,
-						&remainder);
+					"%s fill lli with single lli chunk of size 0x%08zx (remainder 0x%08zx)\n",
+					__func__, lli_len, bd.remainder);
+				pl08x_fill_lli_for_desc(&bd, num_llis++,
+					lli_len, cctl);
 				total_bytes += lli_len;
 			}
 
 
 			if (odd_bytes) {
 				/*
-				 * Creep past the boundary,
-				 * maintaining master alignment
+				 * Creep past the boundary, maintaining
+				 * master alignment
 				 */
 				int j;
 				for (j = 0; (j < mbus->buswidth)
-						&& (remainder); j++) {
+						&& (bd.remainder); j++) {
 					cctl = pl08x_cctl_bits(cctl, 1, 1, 1);
 					dev_vdbg(&pl08x->adev->dev,
-						"%s align with boundardy, single byte (remain %08x)\n",
-						__func__, remainder);
-					num_llis =
-						pl08x_fill_lli_for_desc(pl08x,
-							txd, num_llis, 1,
-							cctl, &remainder);
+						"%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++;
 				}
 			}
@@ -898,25 +807,18 @@ static int pl08x_fill_llis_for_desc(stru
 		/*
 		 * Send any odd bytes
 		 */
-		if (remainder < 0) {
-			dev_err(&pl08x->adev->dev, "%s remainder not fitted 0x%08x bytes\n",
-					__func__, remainder);
-			return 0;
-		}
-
-		while (remainder) {
+		while (bd.remainder) {
 			cctl = pl08x_cctl_bits(cctl, 1, 1, 1);
 			dev_vdbg(&pl08x->adev->dev,
-				"%s align with boundardy, single odd byte (remain %d)\n",
-				__func__, remainder);
-			num_llis = pl08x_fill_lli_for_desc(pl08x, txd, num_llis,
-					1, cctl, &remainder);
+				"%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 != txd->len) {
 		dev_err(&pl08x->adev->dev,
-			"%s size of encoded lli:s don't match total txd, transferred 0x%08x from size 0x%08x\n",
+			"%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;
 	}
@@ -927,41 +829,12 @@ static int pl08x_fill_llis_for_desc(stru
 			__func__, (u32) MAX_NUM_TSFR_LLIS);
 		return 0;
 	}
-	/*
-	 * Decide whether this is a loop or a terminated transfer
-	 */
-	llis_va = txd->llis_va;
-	llis_bus = (struct lli *) txd->llis_bus;
-
-	if (cd->circular_buffer) {
-		/*
-		 * Loop the circular buffer so that the next element
-		 * points back to the beginning of the LLI.
-		 */
-		llis_va[num_llis - 1].next =
-			(dma_addr_t)((unsigned int)&(llis_bus[0]));
-	} else {
-		/*
-		 * On non-circular buffers, the final LLI terminates
-		 * the LLI.
-		 */
-		llis_va[num_llis - 1].next = 0;
-		/*
-		 * The final LLI element shall also fire an interrupt
-		 */
-		llis_va[num_llis - 1].cctl |= PL080_CONTROL_TC_IRQ_EN;
-	}
-
-	/* Now store the channel register values */
-	txd->csrc = llis_va[0].src;
-	txd->cdst = llis_va[0].dst;
-	if (num_llis > 1)
-		txd->clli = llis_va[0].next;
-	else
-		txd->clli = 0;
 
-	txd->cctl = llis_va[0].cctl;
-	/* ccfg will be set at physical channel allocation time */
+	llis_va = txd->llis_va;
+	/* The final LLI terminates the LLI. */
+	llis_va[num_llis - 1].lli = 0;
+	/* The final LLI element shall also fire an interrupt. */
+	llis_va[num_llis - 1].cctl |= PL080_CONTROL_TC_IRQ_EN;
 
 #ifdef VERBOSE_DEBUG
 	{
@@ -969,13 +842,13 @@ static int pl08x_fill_llis_for_desc(stru
 
 		for (i = 0; i < num_llis; i++) {
 			dev_vdbg(&pl08x->adev->dev,
-				 "lli %d @%p: csrc=%08x, cdst=%08x, cctl=%08x, clli=%08x\n",
+				 "lli %d @%p: csrc=0x%08x, cdst=0x%08x, cctl=0x%08x, clli=0x%08x\n",
 				 i,
 				 &llis_va[i],
 				 llis_va[i].src,
 				 llis_va[i].dst,
 				 llis_va[i].cctl,
-				 llis_va[i].next
+				 llis_va[i].lli
 				);
 		}
 	}
@@ -988,14 +861,8 @@ static int pl08x_fill_llis_for_desc(stru
 static void pl08x_free_txd(struct pl08x_driver_data *pl08x,
 			   struct pl08x_txd *txd)
 {
-	if (!txd)
-		dev_err(&pl08x->adev->dev,
-			"%s no descriptor to free\n",
-			__func__);
-
 	/* Free the LLI */
-	dma_pool_free(pl08x->pool, txd->llis_va,
-		      txd->llis_bus);
+	dma_pool_free(pl08x->pool, txd->llis_va, txd->llis_bus);
 
 	pl08x->pool_ctr--;
 
@@ -1008,13 +875,12 @@ static void pl08x_free_txd_list(struct p
 	struct pl08x_txd *txdi = NULL;
 	struct pl08x_txd *next;
 
-	if (!list_empty(&plchan->desc_list)) {
+	if (!list_empty(&plchan->pend_list)) {
 		list_for_each_entry_safe(txdi,
-					 next, &plchan->desc_list, node) {
+					 next, &plchan->pend_list, node) {
 			list_del(&txdi->node);
 			pl08x_free_txd(pl08x, txdi);
 		}
-
 	}
 }
 
@@ -1069,6 +935,12 @@ static int prep_phy_channel(struct pl08x
 			return -EBUSY;
 		}
 		ch->signal = ret;
+
+		/* Assign the flow control signal to this channel */
+		if (txd->direction == DMA_TO_DEVICE)
+			txd->ccfg |= ch->signal << PL080_CONFIG_DST_SEL_SHIFT;
+		else if (txd->direction == DMA_FROM_DEVICE)
+			txd->ccfg |= ch->signal << PL080_CONFIG_SRC_SEL_SHIFT;
 	}
 
 	dev_dbg(&pl08x->adev->dev, "allocated physical channel %d and signal %d for xfer on %s\n",
@@ -1076,19 +948,54 @@ static int prep_phy_channel(struct pl08x
 		 ch->signal,
 		 plchan->name);
 
+	plchan->phychan_hold++;
 	plchan->phychan = ch;
 
 	return 0;
 }
 
+static void release_phy_channel(struct pl08x_dma_chan *plchan)
+{
+	struct pl08x_driver_data *pl08x = plchan->host;
+
+	if ((plchan->phychan->signal >= 0) && pl08x->pd->put_signal) {
+		pl08x->pd->put_signal(plchan);
+		plchan->phychan->signal = -1;
+	}
+	pl08x_put_phy_channel(pl08x, plchan->phychan);
+	plchan->phychan = NULL;
+}
+
 static dma_cookie_t pl08x_tx_submit(struct dma_async_tx_descriptor *tx)
 {
 	struct pl08x_dma_chan *plchan = to_pl08x_chan(tx->chan);
+	struct pl08x_txd *txd = to_pl08x_txd(tx);
+	unsigned long flags;
 
-	atomic_inc(&plchan->last_issued);
-	tx->cookie = atomic_read(&plchan->last_issued);
-	/* This unlock follows the lock in the prep() function */
-	spin_unlock_irqrestore(&plchan->lock, plchan->lockflags);
+	spin_lock_irqsave(&plchan->lock, flags);
+
+	plchan->chan.cookie += 1;
+	if (plchan->chan.cookie < 0)
+		plchan->chan.cookie = 1;
+	tx->cookie = plchan->chan.cookie;
+
+	/* Put this onto the pending list */
+	list_add_tail(&txd->node, &plchan->pend_list);
+
+	/*
+	 * If there was no physical channel available for this memcpy,
+	 * stack the request up and indicate that the channel is waiting
+	 * for a free physical channel.
+	 */
+	if (!plchan->slave && !plchan->phychan) {
+		/* Do this memcpy whenever there is a channel ready */
+		plchan->state = PL08X_CHAN_WAITING;
+		plchan->waiting = txd;
+	} else {
+		plchan->phychan_hold--;
+	}
+
+	spin_unlock_irqrestore(&plchan->lock, flags);
 
 	return tx->cookie;
 }
@@ -1102,10 +1009,9 @@ static struct dma_async_tx_descriptor *p
 }
 
 /*
- * Code accessing dma_async_is_complete() in a tight loop
- * may give problems - could schedule where indicated.
- * If slaves are relying on interrupts to signal completion this
- * function must not be called with interrupts disabled
+ * Code accessing dma_async_is_complete() in a tight loop may give problems.
+ * 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,
@@ -1118,7 +1024,7 @@ pl08x_dma_tx_status(struct dma_chan *cha
 	enum dma_status ret;
 	u32 bytesleft = 0;
 
-	last_used = atomic_read(&plchan->last_issued);
+	last_used = plchan->chan.cookie;
 	last_complete = plchan->lc;
 
 	ret = dma_async_is_complete(cookie, last_complete, last_used);
@@ -1128,13 +1034,9 @@ pl08x_dma_tx_status(struct dma_chan *cha
 	}
 
 	/*
-	 * schedule(); could be inserted here
-	 */
-
-	/*
 	 * This cookie not complete yet
 	 */
-	last_used = atomic_read(&plchan->last_issued);
+	last_used = plchan->chan.cookie;
 	last_complete = plchan->lc;
 
 	/* Get number of bytes left in the active transactions and queue */
@@ -1199,37 +1101,35 @@ static const struct burst_table burst_si
 	},
 };
 
-static void dma_set_runtime_config(struct dma_chan *chan,
-			       struct dma_slave_config *config)
+static int dma_set_runtime_config(struct dma_chan *chan,
+				  struct dma_slave_config *config)
 {
 	struct pl08x_dma_chan *plchan = to_pl08x_chan(chan);
 	struct pl08x_driver_data *pl08x = plchan->host;
 	struct pl08x_channel_data *cd = plchan->cd;
 	enum dma_slave_buswidth addr_width;
+	dma_addr_t addr;
 	u32 maxburst;
 	u32 cctl = 0;
-	/* Mask out all except src and dst channel */
-	u32 ccfg = cd->ccfg & 0x000003DEU;
-	int i = 0;
+	int i;
+
+	if (!plchan->slave)
+		return -EINVAL;
 
 	/* Transfer direction */
 	plchan->runtime_direction = config->direction;
 	if (config->direction == DMA_TO_DEVICE) {
-		plchan->runtime_addr = config->dst_addr;
-		cctl |= PL080_CONTROL_SRC_INCR;
-		ccfg |= PL080_FLOW_MEM2PER << PL080_CONFIG_FLOW_CONTROL_SHIFT;
+		addr = config->dst_addr;
 		addr_width = config->dst_addr_width;
 		maxburst = config->dst_maxburst;
 	} else if (config->direction == DMA_FROM_DEVICE) {
-		plchan->runtime_addr = config->src_addr;
-		cctl |= PL080_CONTROL_DST_INCR;
-		ccfg |= PL080_FLOW_PER2MEM << PL080_CONFIG_FLOW_CONTROL_SHIFT;
+		addr = config->src_addr;
 		addr_width = config->src_addr_width;
 		maxburst = config->src_maxburst;
 	} else {
 		dev_err(&pl08x->adev->dev,
 			"bad runtime_config: alien transfer direction\n");
-		return;
+		return -EINVAL;
 	}
 
 	switch (addr_width) {
@@ -1248,42 +1148,40 @@ static void dma_set_runtime_config(struc
 	default:
 		dev_err(&pl08x->adev->dev,
 			"bad runtime_config: alien address width\n");
-		return;
+		return -EINVAL;
 	}
 
 	/*
 	 * Now decide on a maxburst:
-	 * If this channel will only request single transfers, set
-	 * this down to ONE element.
+	 * If this channel will only request single transfers, set this
+	 * down to ONE element.  Also select one element if no maxburst
+	 * is specified.
 	 */
-	if (plchan->cd->single) {
+	if (plchan->cd->single || maxburst == 0) {
 		cctl |= (PL080_BSIZE_1 << PL080_CONTROL_SB_SIZE_SHIFT) |
 			(PL080_BSIZE_1 << PL080_CONTROL_DB_SIZE_SHIFT);
 	} else {
-		while (i < ARRAY_SIZE(burst_sizes)) {
+		for (i = 0; i < ARRAY_SIZE(burst_sizes); i++)
 			if (burst_sizes[i].burstwords <= maxburst)
 				break;
-			i++;
-		}
 		cctl |= burst_sizes[i].reg;
 	}
 
-	/* Access the cell in privileged mode, non-bufferable, non-cacheable */
-	cctl &= ~PL080_CONTROL_PROT_MASK;
-	cctl |= PL080_CONTROL_PROT_SYS;
+	plchan->runtime_addr = addr;
 
 	/* Modify the default channel data to fit PrimeCell request */
 	cd->cctl = cctl;
-	cd->ccfg = ccfg;
 
 	dev_dbg(&pl08x->adev->dev,
 		"configured channel %s (%s) for %s, data width %d, "
-		"maxburst %d words, LE, CCTL=%08x, CCFG=%08x\n",
+		"maxburst %d words, LE, CCTL=0x%08x\n",
 		dma_chan_name(chan), plchan->name,
 		(config->direction == DMA_FROM_DEVICE) ? "RX" : "TX",
 		addr_width,
 		maxburst,
-		cctl, ccfg);
+		cctl);
+
+	return 0;
 }
 
 /*
@@ -1293,35 +1191,26 @@ static void dma_set_runtime_config(struc
 static void pl08x_issue_pending(struct dma_chan *chan)
 {
 	struct pl08x_dma_chan *plchan = to_pl08x_chan(chan);
-	struct pl08x_driver_data *pl08x = plchan->host;
 	unsigned long flags;
 
 	spin_lock_irqsave(&plchan->lock, flags);
-	/* Something is already active */
-	if (plchan->at) {
-			spin_unlock_irqrestore(&plchan->lock, flags);
-			return;
-	}
-
-	/* Didn't get a physical channel so waiting for it ... */
-	if (plchan->state == PL08X_CHAN_WAITING)
+	/* Something is already active, or we're waiting for a channel... */
+	if (plchan->at || plchan->state == PL08X_CHAN_WAITING) {
+		spin_unlock_irqrestore(&plchan->lock, flags);
 		return;
+	}
 
 	/* Take the first element in the queue and execute it */
-	if (!list_empty(&plchan->desc_list)) {
+	if (!list_empty(&plchan->pend_list)) {
 		struct pl08x_txd *next;
 
-		next = list_first_entry(&plchan->desc_list,
+		next = list_first_entry(&plchan->pend_list,
 					struct pl08x_txd,
 					node);
 		list_del(&next->node);
-		plchan->at = next;
 		plchan->state = PL08X_CHAN_RUNNING;
 
-		/* Configure the physical channel for the active txd */
-		pl08x_config_phychan_for_txd(plchan);
-		pl08x_set_cregs(pl08x, plchan->phychan);
-		pl08x_enable_phy_chan(pl08x, plchan->phychan);
+		pl08x_start_txd(plchan, next);
 	}
 
 	spin_unlock_irqrestore(&plchan->lock, flags);
@@ -1330,30 +1219,17 @@ static void pl08x_issue_pending(struct d
 static int pl08x_prep_channel_resources(struct pl08x_dma_chan *plchan,
 					struct pl08x_txd *txd)
 {
-	int num_llis;
 	struct pl08x_driver_data *pl08x = plchan->host;
-	int ret;
+	unsigned long flags;
+	int num_llis, ret;
 
 	num_llis = pl08x_fill_llis_for_desc(pl08x, txd);
-
-	if (!num_llis)
+	if (!num_llis) {
+		kfree(txd);
 		return -EINVAL;
+	}
 
-	spin_lock_irqsave(&plchan->lock, plchan->lockflags);
-
-	/*
-	 * If this device is not using a circular buffer then
-	 * queue this new descriptor for transfer.
-	 * The descriptor for a circular buffer continues
-	 * to be used until the channel is freed.
-	 */
-	if (txd->cd->circular_buffer)
-		dev_err(&pl08x->adev->dev,
-			"%s attempting to queue a circular buffer\n",
-			__func__);
-	else
-		list_add_tail(&txd->node,
-			      &plchan->desc_list);
+	spin_lock_irqsave(&plchan->lock, flags);
 
 	/*
 	 * See if we already have a physical channel allocated,
@@ -1362,45 +1238,74 @@ static int pl08x_prep_channel_resources(
 	ret = prep_phy_channel(plchan, txd);
 	if (ret) {
 		/*
-		 * No physical channel available, we will
-		 * stack up the memcpy channels until there is a channel
-		 * available to handle it whereas slave transfers may
-		 * have been denied due to platform channel muxing restrictions
-		 * and since there is no guarantee that this will ever be
-		 * resolved, and since the signal must be aquired AFTER
-		 * aquiring the physical channel, we will let them be NACK:ed
-		 * with -EBUSY here. The drivers can alway retry the prep()
-		 * call if they are eager on doing this using DMA.
+		 * No physical channel was available.
+		 *
+		 * memcpy transfers can be sorted out at submission time.
+		 *
+		 * Slave transfers may have been denied due to platform
+		 * channel muxing restrictions.  Since there is no guarantee
+		 * that this will ever be resolved, and the signal must be
+		 * acquired AFTER acquiring the physical channel, we will let
+		 * them be NACK:ed with -EBUSY here. The drivers can retry
+		 * the prep() call if they are eager on doing this using DMA.
 		 */
 		if (plchan->slave) {
 			pl08x_free_txd_list(pl08x, plchan);
-			spin_unlock_irqrestore(&plchan->lock, plchan->lockflags);
+			pl08x_free_txd(pl08x, txd);
+			spin_unlock_irqrestore(&plchan->lock, flags);
 			return -EBUSY;
 		}
-		/* Do this memcpy whenever there is a channel ready */
-		plchan->state = PL08X_CHAN_WAITING;
-		plchan->waiting = txd;
 	} else
 		/*
-		 * Else we're all set, paused and ready to roll,
-		 * status will switch to PL08X_CHAN_RUNNING when
-		 * we call issue_pending(). If there is something
-		 * running on the channel already we don't change
-		 * its state.
+		 * Else we're all set, paused and ready to roll, status
+		 * will switch to PL08X_CHAN_RUNNING when we call
+		 * issue_pending(). If there is something running on the
+		 * channel already we don't change its state.
 		 */
 		if (plchan->state == PL08X_CHAN_IDLE)
 			plchan->state = PL08X_CHAN_PAUSED;
 
-	/*
-	 * Notice that we leave plchan->lock locked on purpose:
-	 * it will be unlocked in the subsequent tx_submit()
-	 * call. This is a consequence of the current API.
-	 */
+	spin_unlock_irqrestore(&plchan->lock, flags);
 
 	return 0;
 }
 
 /*
+ * Given the source and destination available bus masks, select which
+ * will be routed to each port.  We try to have source and destination
+ * on separate ports, but always respect the allowable settings.
+ */
+static u32 pl08x_select_bus(struct pl08x_driver_data *pl08x, u8 src, u8 dst)
+{
+	u32 cctl = 0;
+
+	if (!(dst & PL08X_AHB1) || ((dst & PL08X_AHB2) && (src & PL08X_AHB1)))
+		cctl |= PL080_CONTROL_DST_AHB2;
+	if (!(src & PL08X_AHB1) || ((src & PL08X_AHB2) && !(dst & PL08X_AHB2)))
+		cctl |= PL080_CONTROL_SRC_AHB2;
+
+	return cctl;
+}
+
+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);
+
+	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);
+
+		/* Always enable error and terminal interrupts */
+		txd->ccfg = PL080_CONFIG_ERR_IRQ_MASK |
+			    PL080_CONFIG_TC_IRQ_MASK;
+	}
+	return txd;
+}
+
+/*
  * Initialize a descriptor to be used by memcpy submit
  */
 static struct dma_async_tx_descriptor *pl08x_prep_dma_memcpy(
@@ -1412,40 +1317,38 @@ static struct dma_async_tx_descriptor *p
 	struct pl08x_txd *txd;
 	int ret;
 
-	txd = kzalloc(sizeof(struct pl08x_txd), GFP_NOWAIT);
+	txd = pl08x_get_txd(plchan, flags);
 	if (!txd) {
 		dev_err(&pl08x->adev->dev,
 			"%s no memory for descriptor\n", __func__);
 		return NULL;
 	}
 
-	dma_async_tx_descriptor_init(&txd->tx, chan);
 	txd->direction = DMA_NONE;
-	txd->srcbus.addr = src;
-	txd->dstbus.addr = dest;
+	txd->src_addr = src;
+	txd->dst_addr = dest;
+	txd->len = len;
 
 	/* Set platform data for m2m */
-	txd->cd = &pl08x->pd->memcpy_channel;
+	txd->ccfg |= PL080_FLOW_MEM2MEM << PL080_CONFIG_FLOW_CONTROL_SHIFT;
+	txd->cctl = pl08x->pd->memcpy_channel.cctl &
+			~(PL080_CONTROL_DST_AHB2 | PL080_CONTROL_SRC_AHB2);
+
 	/* Both to be incremented or the code will break */
-	txd->cd->cctl |= PL080_CONTROL_SRC_INCR | PL080_CONTROL_DST_INCR;
-	txd->tx.tx_submit = pl08x_tx_submit;
-	txd->tx.callback = NULL;
-	txd->tx.callback_param = NULL;
-	txd->len = len;
+	txd->cctl |= PL080_CONTROL_SRC_INCR | PL080_CONTROL_DST_INCR;
+
+	if (pl08x->vd->dualmaster)
+		txd->cctl |= pl08x_select_bus(pl08x,
+					pl08x->mem_buses, pl08x->mem_buses);
 
-	INIT_LIST_HEAD(&txd->node);
 	ret = pl08x_prep_channel_resources(plchan, txd);
 	if (ret)
 		return NULL;
-	/*
-	 * NB: the channel lock is held at this point so tx_submit()
-	 * must be called in direct succession.
-	 */
 
 	return &txd->tx;
 }
 
-struct dma_async_tx_descriptor *pl08x_prep_slave_sg(
+static struct dma_async_tx_descriptor *pl08x_prep_slave_sg(
 		struct dma_chan *chan, struct scatterlist *sgl,
 		unsigned int sg_len, enum dma_data_direction direction,
 		unsigned long flags)
@@ -1453,6 +1356,7 @@ struct dma_async_tx_descriptor *pl08x_pr
 	struct pl08x_dma_chan *plchan = to_pl08x_chan(chan);
 	struct pl08x_driver_data *pl08x = plchan->host;
 	struct pl08x_txd *txd;
+	u8 src_buses, dst_buses;
 	int ret;
 
 	/*
@@ -1467,14 +1371,12 @@ struct dma_async_tx_descriptor *pl08x_pr
 	dev_dbg(&pl08x->adev->dev, "%s prepare transaction of %d bytes from %s\n",
 		__func__, sgl->length, plchan->name);
 
-	txd = kzalloc(sizeof(struct pl08x_txd), GFP_NOWAIT);
+	txd = pl08x_get_txd(plchan, flags);
 	if (!txd) {
 		dev_err(&pl08x->adev->dev, "%s no txd\n", __func__);
 		return NULL;
 	}
 
-	dma_async_tx_descriptor_init(&txd->tx, chan);
-
 	if (direction != plchan->runtime_direction)
 		dev_err(&pl08x->adev->dev, "%s DMA setup does not match "
 			"the direction configured for the PrimeCell\n",
@@ -1486,37 +1388,47 @@ struct dma_async_tx_descriptor *pl08x_pr
 	 * channel target address dynamically at runtime.
 	 */
 	txd->direction = direction;
+	txd->len = sgl->length;
+
+	txd->cctl = plchan->cd->cctl &
+			~(PL080_CONTROL_SRC_AHB2 | PL080_CONTROL_DST_AHB2 |
+			  PL080_CONTROL_SRC_INCR | PL080_CONTROL_DST_INCR |
+			  PL080_CONTROL_PROT_MASK);
+
+	/* Access the cell in privileged mode, non-bufferable, non-cacheable */
+	txd->cctl |= PL080_CONTROL_PROT_SYS;
+
 	if (direction == DMA_TO_DEVICE) {
-		txd->srcbus.addr = sgl->dma_address;
+		txd->ccfg |= PL080_FLOW_MEM2PER << PL080_CONFIG_FLOW_CONTROL_SHIFT;
+		txd->cctl |= PL080_CONTROL_SRC_INCR;
+		txd->src_addr = sgl->dma_address;
 		if (plchan->runtime_addr)
-			txd->dstbus.addr = plchan->runtime_addr;
+			txd->dst_addr = plchan->runtime_addr;
 		else
-			txd->dstbus.addr = plchan->cd->addr;
+			txd->dst_addr = plchan->cd->addr;
+		src_buses = pl08x->mem_buses;
+		dst_buses = plchan->cd->periph_buses;
 	} else if (direction == DMA_FROM_DEVICE) {
+		txd->ccfg |= PL080_FLOW_PER2MEM << PL080_CONFIG_FLOW_CONTROL_SHIFT;
+		txd->cctl |= PL080_CONTROL_DST_INCR;
 		if (plchan->runtime_addr)
-			txd->srcbus.addr = plchan->runtime_addr;
+			txd->src_addr = plchan->runtime_addr;
 		else
-			txd->srcbus.addr = plchan->cd->addr;
-		txd->dstbus.addr = sgl->dma_address;
+			txd->src_addr = plchan->cd->addr;
+		txd->dst_addr = sgl->dma_address;
+		src_buses = plchan->cd->periph_buses;
+		dst_buses = pl08x->mem_buses;
 	} else {
 		dev_err(&pl08x->adev->dev,
 			"%s direction unsupported\n", __func__);
 		return NULL;
 	}
-	txd->cd = plchan->cd;
-	txd->tx.tx_submit = pl08x_tx_submit;
-	txd->tx.callback = NULL;
-	txd->tx.callback_param = NULL;
-	txd->len = sgl->length;
-	INIT_LIST_HEAD(&txd->node);
+
+	txd->cctl |= pl08x_select_bus(pl08x, src_buses, dst_buses);
 
 	ret = pl08x_prep_channel_resources(plchan, txd);
 	if (ret)
 		return NULL;
-	/*
-	 * NB: the channel lock is held at this point so tx_submit()
-	 * must be called in direct succession.
-	 */
 
 	return &txd->tx;
 }
@@ -1531,10 +1443,8 @@ static int pl08x_control(struct dma_chan
 
 	/* Controls applicable to inactive channels */
 	if (cmd == DMA_SLAVE_CONFIG) {
-		dma_set_runtime_config(chan,
-				       (struct dma_slave_config *)
-				       arg);
-		return 0;
+		return dma_set_runtime_config(chan,
+					      (struct dma_slave_config *)arg);
 	}
 
 	/*
@@ -1552,22 +1462,14 @@ static int pl08x_control(struct dma_chan
 		plchan->state = PL08X_CHAN_IDLE;
 
 		if (plchan->phychan) {
-			pl08x_stop_phy_chan(plchan->phychan);
+			pl08x_terminate_phy_chan(pl08x, plchan->phychan);
 
 			/*
 			 * Mark physical channel as free and free any slave
 			 * signal
 			 */
-			if ((plchan->phychan->signal >= 0) &&
-			    pl08x->pd->put_signal) {
-				pl08x->pd->put_signal(plchan);
-				plchan->phychan->signal = -1;
-			}
-			pl08x_put_phy_channel(pl08x, plchan->phychan);
-			plchan->phychan = NULL;
+			release_phy_channel(plchan);
 		}
-		/* Stop any pending tasklet */
-		tasklet_disable(&plchan->tasklet);
 		/* Dequeue jobs and free LLIs */
 		if (plchan->at) {
 			pl08x_free_txd(pl08x, plchan->at);
@@ -1609,10 +1511,9 @@ bool pl08x_filter_id(struct dma_chan *ch
 
 /*
  * Just check that the device is there and active
- * TODO: turn this bit on/off depending on the number of
- * physical channels actually used, if it is zero... well
- * shut it off. That will save some power. Cut the clock
- * at the same time.
+ * TODO: turn this bit on/off depending on the number of physical channels
+ * actually used, if it is zero... well shut it off. That will save some
+ * power. Cut the clock at the same time.
  */
 static void pl08x_ensure_on(struct pl08x_driver_data *pl08x)
 {
@@ -1620,78 +1521,66 @@ static void pl08x_ensure_on(struct pl08x
 
 	val = readl(pl08x->base + PL080_CONFIG);
 	val &= ~(PL080_CONFIG_M2_BE | PL080_CONFIG_M1_BE | PL080_CONFIG_ENABLE);
-	/* We implictly clear bit 1 and that means little-endian mode */
+	/* We implicitly clear bit 1 and that means little-endian mode */
 	val |= PL080_CONFIG_ENABLE;
 	writel(val, pl08x->base + PL080_CONFIG);
 }
 
+static void pl08x_unmap_buffers(struct pl08x_txd *txd)
+{
+	struct device *dev = txd->tx.chan->device->dev;
+
+	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);
+	}
+	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);
+		else
+			dma_unmap_page(dev, txd->dst_addr, txd->len,
+				DMA_FROM_DEVICE);
+	}
+}
+
 static void pl08x_tasklet(unsigned long data)
 {
 	struct pl08x_dma_chan *plchan = (struct pl08x_dma_chan *) data;
-	struct pl08x_phy_chan *phychan = plchan->phychan;
 	struct pl08x_driver_data *pl08x = plchan->host;
+	struct pl08x_txd *txd;
+	unsigned long flags;
 
-	if (!plchan)
-		BUG();
-
-	spin_lock(&plchan->lock);
-
-	if (plchan->at) {
-		dma_async_tx_callback callback =
-			plchan->at->tx.callback;
-		void *callback_param =
-			plchan->at->tx.callback_param;
-
-		/*
-		 * Update last completed
-		 */
-		plchan->lc =
-			(plchan->at->tx.cookie);
-
-		/*
-		 * Callback to signal completion
-		 */
-		if (callback)
-			callback(callback_param);
+	spin_lock_irqsave(&plchan->lock, flags);
 
-		/*
-		 * Device callbacks should NOT clear
-		 * the current transaction on the channel
-		 * Linus: sometimes they should?
-		 */
-		if (!plchan->at)
-			BUG();
+	txd = plchan->at;
+	plchan->at = NULL;
 
-		/*
-		 * Free the descriptor if it's not for a device
-		 * using a circular buffer
-		 */
-		if (!plchan->at->cd->circular_buffer) {
-			pl08x_free_txd(pl08x, plchan->at);
-			plchan->at = NULL;
-		}
-		/*
-		 * else descriptor for circular
-		 * buffers only freed when
-		 * client has disabled dma
-		 */
+	if (txd) {
+		/* Update last completed */
+		plchan->lc = txd->tx.cookie;
 	}
-	/*
-	 * If a new descriptor is queued, set it up
-	 * plchan->at is NULL here
-	 */
-	if (!list_empty(&plchan->desc_list)) {
+
+	/* If a new descriptor is queued, set it up plchan->at is NULL here */
+	if (!list_empty(&plchan->pend_list)) {
 		struct pl08x_txd *next;
 
-		next = list_first_entry(&plchan->desc_list,
+		next = list_first_entry(&plchan->pend_list,
 					struct pl08x_txd,
 					node);
 		list_del(&next->node);
-		plchan->at = next;
-		/* Configure the physical channel for the next txd */
-		pl08x_config_phychan_for_txd(plchan);
-		pl08x_set_cregs(pl08x, plchan->phychan);
-		pl08x_enable_phy_chan(pl08x, plchan->phychan);
+
+		pl08x_start_txd(plchan, next);
+	} else if (plchan->phychan_hold) {
+		/*
+		 * This channel is still in use - we have a new txd being
+		 * prepared and will soon be queued.  Don't give up the
+		 * physical channel.
+		 */
 	} else {
 		struct pl08x_dma_chan *waiting = NULL;
 
@@ -1699,20 +1588,14 @@ static void pl08x_tasklet(unsigned long
 		 * No more jobs, so free up the physical channel
 		 * Free any allocated signal on slave transfers too
 		 */
-		if ((phychan->signal >= 0) && pl08x->pd->put_signal) {
-			pl08x->pd->put_signal(plchan);
-			phychan->signal = -1;
-		}
-		pl08x_put_phy_channel(pl08x, phychan);
-		plchan->phychan = NULL;
+		release_phy_channel(plchan);
 		plchan->state = PL08X_CHAN_IDLE;
 
 		/*
-		 * And NOW before anyone else can grab that free:d
-		 * up physical channel, see if there is some memcpy
-		 * pending that seriously needs to start because of
-		 * being stacked up while we were choking the
-		 * physical channels with data.
+		 * And NOW before anyone else can grab that free:d up
+		 * physical channel, see if there is some memcpy pending
+		 * that seriously needs to start because of being stacked
+		 * up while we were choking the physical channels with data.
 		 */
 		list_for_each_entry(waiting, &pl08x->memcpy.channels,
 				    chan.device_node) {
@@ -1724,6 +1607,7 @@ static void pl08x_tasklet(unsigned long
 				ret = prep_phy_channel(waiting,
 						       waiting->waiting);
 				BUG_ON(ret);
+				waiting->phychan_hold--;
 				waiting->state = PL08X_CHAN_RUNNING;
 				waiting->waiting = NULL;
 				pl08x_issue_pending(&waiting->chan);
@@ -1732,7 +1616,25 @@ static void pl08x_tasklet(unsigned long
 		}
 	}
 
-	spin_unlock(&plchan->lock);
+	spin_unlock_irqrestore(&plchan->lock, flags);
+
+	if (txd) {
+		dma_async_tx_callback callback = txd->tx.callback;
+		void *callback_param = txd->tx.callback_param;
+
+		/* Don't try to unmap buffers on slave channels */
+		if (!plchan->slave)
+			pl08x_unmap_buffers(txd);
+
+		/* Free the descriptor */
+		spin_lock_irqsave(&plchan->lock, flags);
+		pl08x_free_txd(pl08x, txd);
+		spin_unlock_irqrestore(&plchan->lock, flags);
+
+		/* Callback to signal completion */
+		if (callback)
+			callback(callback_param);
+	}
 }
 
 static irqreturn_t pl08x_irq(int irq, void *dev)
@@ -1744,9 +1646,7 @@ static irqreturn_t pl08x_irq(int irq, vo
 
 	val = readl(pl08x->base + PL080_ERR_STATUS);
 	if (val) {
-		/*
-		 * An error interrupt (on one or more channels)
-		 */
+		/* An error interrupt (on one or more channels) */
 		dev_err(&pl08x->adev->dev,
 			"%s error interrupt, register value 0x%08x\n",
 				__func__, val);
@@ -1770,9 +1670,7 @@ static irqreturn_t pl08x_irq(int irq, vo
 			mask |= (1 << i);
 		}
 	}
-	/*
-	 * Clear only the terminal interrupts on channels we processed
-	 */
+	/* Clear only the terminal interrupts on channels we processed */
 	writel(mask, pl08x->base + PL080_TC_CLEAR);
 
 	return mask ? IRQ_HANDLED : IRQ_NONE;
@@ -1791,6 +1689,7 @@ static int pl08x_dma_init_virtual_channe
 	int i;
 
 	INIT_LIST_HEAD(&dmadev->channels);
+
 	/*
 	 * Register as many many memcpy as we have physical channels,
 	 * we won't always be able to use all but the code will have
@@ -1819,16 +1718,23 @@ static int pl08x_dma_init_virtual_channe
 				return -ENOMEM;
 			}
 		}
+		if (chan->cd->circular_buffer) {
+			dev_err(&pl08x->adev->dev,
+				"channel %s: circular buffers not supported\n",
+				chan->name);
+			kfree(chan);
+			continue;
+		}
 		dev_info(&pl08x->adev->dev,
 			 "initialize virtual channel \"%s\"\n",
 			 chan->name);
 
 		chan->chan.device = dmadev;
-		atomic_set(&chan->last_issued, 0);
-		chan->lc = atomic_read(&chan->last_issued);
+		chan->chan.cookie = 0;
+		chan->lc = 0;
 
 		spin_lock_init(&chan->lock);
-		INIT_LIST_HEAD(&chan->desc_list);
+		INIT_LIST_HEAD(&chan->pend_list);
 		tasklet_init(&chan->tasklet, pl08x_tasklet,
 			     (unsigned long) chan);
 
@@ -1898,7 +1804,7 @@ static int pl08x_debugfs_show(struct seq
 	seq_printf(s, "CHANNEL:\tSTATE:\n");
 	seq_printf(s, "--------\t------\n");
 	list_for_each_entry(chan, &pl08x->memcpy.channels, chan.device_node) {
-		seq_printf(s, "%s\t\t\%s\n", chan->name,
+		seq_printf(s, "%s\t\t%s\n", chan->name,
 			   pl08x_state_str(chan->state));
 	}
 
@@ -1906,7 +1812,7 @@ static int pl08x_debugfs_show(struct seq
 	seq_printf(s, "CHANNEL:\tSTATE:\n");
 	seq_printf(s, "--------\t------\n");
 	list_for_each_entry(chan, &pl08x->slave.channels, chan.device_node) {
-		seq_printf(s, "%s\t\t\%s\n", chan->name,
+		seq_printf(s, "%s\t\t%s\n", chan->name,
 			   pl08x_state_str(chan->state));
 	}
 
@@ -1942,7 +1848,7 @@ static inline void init_pl08x_debugfs(st
 static int pl08x_probe(struct amba_device *adev, struct amba_id *id)
 {
 	struct pl08x_driver_data *pl08x;
-	struct vendor_data *vd = id->data;
+	const struct vendor_data *vd = id->data;
 	int ret = 0;
 	int i;
 
@@ -1990,6 +1896,14 @@ static int pl08x_probe(struct amba_devic
 	pl08x->adev = adev;
 	pl08x->vd = vd;
 
+	/* By default, AHB1 only.  If dualmaster, from platform */
+	pl08x->lli_buses = PL08X_AHB1;
+	pl08x->mem_buses = PL08X_AHB1;
+	if (pl08x->vd->dualmaster) {
+		pl08x->lli_buses = pl08x->pd->lli_buses;
+		pl08x->mem_buses = pl08x->pd->mem_buses;
+	}
+
 	/* A DMA memory pool for LLIs, align on 1-byte boundary */
 	pl08x->pool = dma_pool_create(DRIVER_NAME, &pl08x->adev->dev,
 			PL08X_LLI_TSFR_SIZE, PL08X_ALIGN, 0);
@@ -2009,14 +1923,12 @@ static int pl08x_probe(struct amba_devic
 	/* Turn on the PL08x */
 	pl08x_ensure_on(pl08x);
 
-	/*
-	 * Attach the interrupt handler
-	 */
+	/* Attach the interrupt handler */
 	writel(0x000000FF, pl08x->base + PL080_ERR_CLEAR);
 	writel(0x000000FF, pl08x->base + PL080_TC_CLEAR);
 
 	ret = request_irq(adev->irq[0], pl08x_irq, IRQF_DISABLED,
-			  vd->name, pl08x);
+			  DRIVER_NAME, pl08x);
 	if (ret) {
 		dev_err(&adev->dev, "%s failed to request interrupt %d\n",
 			__func__, adev->irq[0]);
@@ -2087,8 +1999,9 @@ static int pl08x_probe(struct amba_devic
 
 	amba_set_drvdata(adev, pl08x);
 	init_pl08x_debugfs(pl08x);
-	dev_info(&pl08x->adev->dev, "ARM(R) %s DMA block initialized @%08x\n",
-		vd->name, adev->res.start);
+	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]);
 	return 0;
 
 out_no_slave_reg:
@@ -2115,13 +2028,11 @@ out_no_pl08x:
 
 /* PL080 has 8 channels and the PL080 have just 2 */
 static struct vendor_data vendor_pl080 = {
-	.name = "PL080",
 	.channels = 8,
 	.dualmaster = true,
 };
 
 static struct vendor_data vendor_pl081 = {
-	.name = "PL081",
 	.channels = 2,
 	.dualmaster = false,
 };
@@ -2160,7 +2071,7 @@ static int __init pl08x_init(void)
 	retval = amba_driver_register(&pl08x_amba_driver);
 	if (retval)
 		printk(KERN_WARNING DRIVER_NAME
-		       "failed to register as an amba device (%d)\n",
+		       "failed to register as an AMBA device (%d)\n",
 		       retval);
 	return retval;
 }
diff -druNp linux-libre-2.6.37-gnu1/drivers/dma/at_hdmac.c linux-libre-2.6.38-gnu1/drivers/dma/at_hdmac.c
--- linux-libre-2.6.37-gnu1/drivers/dma/at_hdmac.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/dma/at_hdmac.c	2011-03-14 21:20:32.000000000 -0400
@@ -253,7 +253,7 @@ atc_chain_complete(struct at_dma_chan *a
 	/* move myself to free_list */
 	list_move(&desc->desc_node, &atchan->free_list);
 
-	/* unmap dma addresses */
+	/* unmap dma addresses (not on slave channels) */
 	if (!atchan->chan_common.private) {
 		struct device *parent = chan2parent(&atchan->chan_common);
 		if (!(txd->flags & DMA_COMPL_SKIP_DEST_UNMAP)) {
@@ -583,7 +583,6 @@ atc_prep_dma_memcpy(struct dma_chan *cha
 		desc->lli.ctrlb = ctrlb;
 
 		desc->txd.cookie = 0;
-		async_tx_ack(&desc->txd);
 
 		if (!first) {
 			first = desc;
@@ -604,7 +603,7 @@ atc_prep_dma_memcpy(struct dma_chan *cha
 	/* set end-of-link to the last link descriptor of list*/
 	set_desc_eol(desc);
 
-	desc->txd.flags = flags; /* client is in control of this ack */
+	first->txd.flags = flags; /* client is in control of this ack */
 
 	return &first->txd;
 
@@ -670,7 +669,7 @@ atc_prep_slave_sg(struct dma_chan *chan,
 			if (!desc)
 				goto err_desc_get;
 
-			mem = sg_phys(sg);
+			mem = sg_dma_address(sg);
 			len = sg_dma_len(sg);
 			mem_width = 2;
 			if (unlikely(mem & 3 || len & 3))
@@ -712,7 +711,7 @@ atc_prep_slave_sg(struct dma_chan *chan,
 			if (!desc)
 				goto err_desc_get;
 
-			mem = sg_phys(sg);
+			mem = sg_dma_address(sg);
 			len = sg_dma_len(sg);
 			mem_width = 2;
 			if (unlikely(mem & 3 || len & 3))
@@ -749,8 +748,8 @@ atc_prep_slave_sg(struct dma_chan *chan,
 	first->txd.cookie = -EBUSY;
 	first->len = total_len;
 
-	/* last link descriptor of list is responsible of flags */
-	prev->txd.flags = flags; /* client is in control of this ack */
+	/* first link descriptor of list is responsible of flags */
+	first->txd.flags = flags; /* client is in control of this ack */
 
 	return &first->txd;
 
@@ -854,11 +853,11 @@ static void atc_issue_pending(struct dma
 
 	dev_vdbg(chan2dev(chan), "issue_pending\n");
 
+	spin_lock_bh(&atchan->lock);
 	if (!atc_chan_is_enabled(atchan)) {
-		spin_lock_bh(&atchan->lock);
 		atc_advance_work(atchan);
-		spin_unlock_bh(&atchan->lock);
 	}
+	spin_unlock_bh(&atchan->lock);
 }
 
 /**
@@ -1210,7 +1209,7 @@ static int __init at_dma_init(void)
 {
 	return platform_driver_probe(&at_dma_driver, at_dma_probe);
 }
-module_init(at_dma_init);
+subsys_initcall(at_dma_init);
 
 static void __exit at_dma_exit(void)
 {
diff -druNp linux-libre-2.6.37-gnu1/drivers/dma/fsldma.c linux-libre-2.6.38-gnu1/drivers/dma/fsldma.c
--- linux-libre-2.6.37-gnu1/drivers/dma/fsldma.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/dma/fsldma.c	2011-03-14 21:20:32.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  * Freescale MPC85xx, MPC83xx DMA Engine support
  *
- * Copyright (C) 2007 Freescale Semiconductor, Inc. All rights reserved.
+ * Copyright (C) 2007-2010 Freescale Semiconductor, Inc. All rights reserved.
  *
  * Author:
  *   Zhang Wei <wei.zhang@freescale.com>, Jul 2007
@@ -1324,6 +1324,8 @@ static int __devinit fsldma_of_probe(str
 	fdev->common.device_control = fsl_dma_device_control;
 	fdev->common.dev = &op->dev;
 
+	dma_set_mask(&(op->dev), DMA_BIT_MASK(36));
+
 	dev_set_drvdata(&op->dev, fdev);
 
 	/*
diff -druNp linux-libre-2.6.37-gnu1/drivers/dma/imx-dma.c linux-libre-2.6.38-gnu1/drivers/dma/imx-dma.c
--- linux-libre-2.6.37-gnu1/drivers/dma/imx-dma.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/dma/imx-dma.c	2011-03-14 21:20:32.000000000 -0400
@@ -49,6 +49,7 @@ struct imxdma_channel {
 
 struct imxdma_engine {
 	struct device			*dev;
+	struct device_dma_parameters	dma_parms;
 	struct dma_device		dma_device;
 	struct imxdma_channel		channel[MAX_DMA_CHANNELS];
 };
@@ -242,6 +243,21 @@ static struct dma_async_tx_descriptor *i
 	else
 		dmamode = DMA_MODE_WRITE;
 
+	switch (imxdmac->word_size) {
+	case DMA_SLAVE_BUSWIDTH_4_BYTES:
+		if (sgl->length & 3 || sgl->dma_address & 3)
+			return NULL;
+		break;
+	case DMA_SLAVE_BUSWIDTH_2_BYTES:
+		if (sgl->length & 1 || sgl->dma_address & 1)
+			return NULL;
+		break;
+	case DMA_SLAVE_BUSWIDTH_1_BYTE:
+		break;
+	default:
+		return NULL;
+	}
+
 	ret = imx_dma_setup_sg(imxdmac->imxdma_channel, sgl, sg_len,
 		 dma_length, imxdmac->per_address, dmamode);
 	if (ret)
@@ -329,6 +345,9 @@ static int __init imxdma_probe(struct pl
 
 	INIT_LIST_HEAD(&imxdma->dma_device.channels);
 
+	dma_cap_set(DMA_SLAVE, imxdma->dma_device.cap_mask);
+	dma_cap_set(DMA_CYCLIC, imxdma->dma_device.cap_mask);
+
 	/* Initialize channel parameters */
 	for (i = 0; i < MAX_DMA_CHANNELS; i++) {
 		struct imxdma_channel *imxdmac = &imxdma->channel[i];
@@ -346,11 +365,7 @@ static int __init imxdma_probe(struct pl
 		imxdmac->imxdma = imxdma;
 		spin_lock_init(&imxdmac->lock);
 
-		dma_cap_set(DMA_SLAVE, imxdma->dma_device.cap_mask);
-		dma_cap_set(DMA_CYCLIC, imxdma->dma_device.cap_mask);
-
 		imxdmac->chan.device = &imxdma->dma_device;
-		imxdmac->chan.chan_id = i;
 		imxdmac->channel = i;
 
 		/* Add the channel to the DMAC list */
@@ -370,6 +385,9 @@ static int __init imxdma_probe(struct pl
 
 	platform_set_drvdata(pdev, imxdma);
 
+	imxdma->dma_device.dev->dma_parms = &imxdma->dma_parms;
+	dma_set_max_seg_size(imxdma->dma_device.dev, 0xffffff);
+
 	ret = dma_async_device_register(&imxdma->dma_device);
 	if (ret) {
 		dev_err(&pdev->dev, "unable to register\n");
diff -druNp linux-libre-2.6.37-gnu1/drivers/dma/imx-sdma.c linux-libre-2.6.38-gnu1/drivers/dma/imx-sdma.c
--- linux-libre-2.6.37-gnu1/drivers/dma/imx-sdma.c	2013-05-03 03:54:56.000000000 -0400
+++ linux-libre-2.6.38-gnu1/drivers/dma/imx-sdma.c	2013-05-03 01:54:12.000000000 -0400
@@ -230,7 +230,7 @@ struct sdma_engine;
  * struct sdma_channel - housekeeping for a SDMA channel
  *
  * @sdma		pointer to the SDMA engine for this channel
- * @channel		the channel number, matches dmaengine chan_id
+ * @channel		the channel number, matches dmaengine chan_id + 1
  * @direction		transfer type. Needed for setting SDMA script
  * @peripheral_type	Peripheral type. Needed for setting SDMA script
  * @event_id0		aka dma request line
@@ -273,50 +273,6 @@ struct sdma_channel {
 #define MXC_SDMA_MIN_PRIORITY 1
 #define MXC_SDMA_MAX_PRIORITY 7
 
-/**
- * struct sdma_script_start_addrs - SDMA script start pointers
- *
- * start addresses of the different functions in the physical
- * address space of the SDMA engine.
- */
-struct sdma_script_start_addrs {
-	u32 ap_2_ap_addr;
-	u32 ap_2_bp_addr;
-	u32 ap_2_ap_fixed_addr;
-	u32 bp_2_ap_addr;
-	u32 loopback_on_dsp_side_addr;
-	u32 mcu_interrupt_only_addr;
-	u32 firi_2_per_addr;
-	u32 firi_2_mcu_addr;
-	u32 per_2_firi_addr;
-	u32 mcu_2_firi_addr;
-	u32 uart_2_per_addr;
-	u32 uart_2_mcu_addr;
-	u32 per_2_app_addr;
-	u32 mcu_2_app_addr;
-	u32 per_2_per_addr;
-	u32 uartsh_2_per_addr;
-	u32 uartsh_2_mcu_addr;
-	u32 per_2_shp_addr;
-	u32 mcu_2_shp_addr;
-	u32 ata_2_mcu_addr;
-	u32 mcu_2_ata_addr;
-	u32 app_2_per_addr;
-	u32 app_2_mcu_addr;
-	u32 shp_2_per_addr;
-	u32 shp_2_mcu_addr;
-	u32 mshc_2_mcu_addr;
-	u32 mcu_2_mshc_addr;
-	u32 spdif_2_mcu_addr;
-	u32 mcu_2_spdif_addr;
-	u32 asrc_2_mcu_addr;
-	u32 ext_mem_2_ipu_addr;
-	u32 descrambler_addr;
-	u32 dptc_dvfs_addr;
-	u32 utra_addr;
-	u32 ram_code_start_addr;
-};
-
 #define SDMA_FIRMWARE_MAGIC 0x414d4453
 
 /**
@@ -345,6 +301,7 @@ struct sdma_firmware_header {
 
 struct sdma_engine {
 	struct device			*dev;
+	struct device_dma_parameters	dma_parms;
 	struct sdma_channel		channel[MAX_DMA_CHANNELS];
 	struct sdma_channel_control	*channel_control;
 	void __iomem			*regs;
@@ -493,7 +450,7 @@ static void sdma_handle_channel_loop(str
 		if (bd->mode.status & BD_RROR)
 			sdmac->status = DMA_ERROR;
 		else
-			sdmac->status = DMA_SUCCESS;
+			sdmac->status = DMA_IN_PROGRESS;
 
 		bd->mode.status |= BD_DONE;
 		sdmac->buf_tail++;
@@ -814,15 +771,15 @@ static void sdma_enable_channel(struct s
 	__raw_writel(1 << channel, sdma->regs + SDMA_H_START);
 }
 
-static dma_cookie_t sdma_assign_cookie(struct sdma_channel *sdma)
+static dma_cookie_t sdma_assign_cookie(struct sdma_channel *sdmac)
 {
-	dma_cookie_t cookie = sdma->chan.cookie;
+	dma_cookie_t cookie = sdmac->chan.cookie;
 
 	if (++cookie < 0)
 		cookie = 1;
 
-	sdma->chan.cookie = cookie;
-	sdma->desc.cookie = cookie;
+	sdmac->chan.cookie = cookie;
+	sdmac->desc.cookie = cookie;
 
 	return cookie;
 }
@@ -842,7 +799,7 @@ static dma_cookie_t sdma_tx_submit(struc
 
 	cookie = sdma_assign_cookie(sdmac);
 
-	sdma_enable_channel(sdma, tx->chan->chan_id);
+	sdma_enable_channel(sdma, sdmac->channel);
 
 	spin_unlock_irq(&sdmac->lock);
 
@@ -855,10 +812,6 @@ static int sdma_alloc_chan_resources(str
 	struct imx_dma_data *data = chan->private;
 	int prio, ret;
 
-	/* No need to execute this for internal channel 0 */
-	if (chan->chan_id == 0)
-		return 0;
-
 	if (!data)
 		return -EINVAL;
 
@@ -923,7 +876,7 @@ static struct dma_async_tx_descriptor *s
 	struct sdma_channel *sdmac = to_sdma_chan(chan);
 	struct sdma_engine *sdma = sdmac->sdma;
 	int ret, i, count;
-	int channel = chan->chan_id;
+	int channel = sdmac->channel;
 	struct scatterlist *sg;
 
 	if (sdmac->status == DMA_IN_PROGRESS)
@@ -968,22 +921,33 @@ static struct dma_async_tx_descriptor *s
 			ret =  -EINVAL;
 			goto err_out;
 		}
-		if (sdmac->word_size == DMA_SLAVE_BUSWIDTH_4_BYTES)
+
+		switch (sdmac->word_size) {
+		case DMA_SLAVE_BUSWIDTH_4_BYTES:
 			bd->mode.command = 0;
-		else
-			bd->mode.command = sdmac->word_size;
+			if (count & 3 || sg->dma_address & 3)
+				return NULL;
+			break;
+		case DMA_SLAVE_BUSWIDTH_2_BYTES:
+			bd->mode.command = 2;
+			if (count & 1 || sg->dma_address & 1)
+				return NULL;
+			break;
+		case DMA_SLAVE_BUSWIDTH_1_BYTE:
+			bd->mode.command = 1;
+			break;
+		default:
+			return NULL;
+		}
 
 		param = BD_DONE | BD_EXTD | BD_CONT;
 
-		if (sdmac->flags & IMX_DMA_SG_LOOP) {
+		if (i + 1 == sg_len) {
 			param |= BD_INTR;
-			if (i + 1 == sg_len)
-				param |= BD_WRAP;
+			param |= BD_LAST;
+			param &= ~BD_CONT;
 		}
 
-		if (i + 1 == sg_len)
-			param |= BD_INTR;
-
 		dev_dbg(sdma->dev, "entry %d: count: %d dma: 0x%08x %s%s\n",
 				i, count, sg->dma_address,
 				param & BD_WRAP ? "wrap" : "",
@@ -997,6 +961,7 @@ static struct dma_async_tx_descriptor *s
 
 	return &sdmac->desc;
 err_out:
+	sdmac->status = DMA_ERROR;
 	return NULL;
 }
 
@@ -1007,7 +972,7 @@ static struct dma_async_tx_descriptor *s
 	struct sdma_channel *sdmac = to_sdma_chan(chan);
 	struct sdma_engine *sdma = sdmac->sdma;
 	int num_periods = buf_len / period_len;
-	int channel = chan->chan_id;
+	int channel = sdmac->channel;
 	int ret, i = 0, buf = 0;
 
 	dev_dbg(sdma->dev, "%s channel: %d\n", __func__, channel);
@@ -1110,14 +1075,12 @@ static enum dma_status sdma_tx_status(st
 {
 	struct sdma_channel *sdmac = to_sdma_chan(chan);
 	dma_cookie_t last_used;
-	enum dma_status ret;
 
 	last_used = chan->cookie;
 
-	ret = dma_async_is_complete(cookie, sdmac->last_completed, last_used);
 	dma_set_tx_state(txstate, sdmac->last_completed, last_used, 0);
 
-	return ret;
+	return sdmac->status;
 }
 
 static void sdma_issue_pending(struct dma_chan *chan)
@@ -1127,8 +1090,74 @@ static void sdma_issue_pending(struct dm
 	 */
 }
 
-static int __init sdma_init(struct sdma_engine *sdma,
-		void *ram_code, int ram_code_size)
+#define SDMA_SCRIPT_ADDRS_ARRAY_SIZE_V1	34
+
+static void sdma_add_scripts(struct sdma_engine *sdma,
+		const struct sdma_script_start_addrs *addr)
+{
+	s32 *addr_arr = (u32 *)addr;
+	s32 *saddr_arr = (u32 *)sdma->script_addrs;
+	int i;
+
+	for (i = 0; i < SDMA_SCRIPT_ADDRS_ARRAY_SIZE_V1; i++)
+		if (addr_arr[i] > 0)
+			saddr_arr[i] = addr_arr[i];
+}
+
+static int __init sdma_get_firmware(struct sdma_engine *sdma,
+		const char *cpu_name, int to_version)
+{
+	const struct firmware *fw;
+	char *fwname;
+	const struct sdma_firmware_header *header;
+	int ret;
+	const struct sdma_script_start_addrs *addr;
+	unsigned short *ram_code;
+
+	fwname = kasprintf(GFP_KERNEL, "/*(DEBLOBBED)*/", cpu_name, to_version);
+	if (!fwname)
+		return -ENOMEM;
+
+	ret = reject_firmware(&fw, fwname, sdma->dev);
+	if (ret) {
+		kfree(fwname);
+		return ret;
+	}
+	kfree(fwname);
+
+	if (fw->size < sizeof(*header))
+		goto err_firmware;
+
+	header = (struct sdma_firmware_header *)fw->data;
+
+	if (header->magic != SDMA_FIRMWARE_MAGIC)
+		goto err_firmware;
+	if (header->ram_code_start + header->ram_code_size > fw->size)
+		goto err_firmware;
+
+	addr = (void *)header + header->script_addrs_start;
+	ram_code = (void *)header + header->ram_code_start;
+
+	clk_enable(sdma->clk);
+	/* download the RAM image for SDMA */
+	sdma_load_script(sdma, ram_code,
+			header->ram_code_size,
+			addr->ram_code_start_addr);
+	clk_disable(sdma->clk);
+
+	sdma_add_scripts(sdma, addr);
+
+	dev_info(sdma->dev, "loaded firmware %d.%d\n",
+			header->version_major,
+			header->version_minor);
+
+err_firmware:
+	release_firmware(fw);
+
+	return ret;
+}
+
+static int __init sdma_init(struct sdma_engine *sdma)
 {
 	int i, ret;
 	dma_addr_t ccb_phys;
@@ -1192,11 +1221,6 @@ static int __init sdma_init(struct sdma_
 
 	__raw_writel(ccb_phys, sdma->regs + SDMA_H_C0PTR);
 
-	/* download the RAM image for SDMA */
-	sdma_load_script(sdma, ram_code,
-			ram_code_size,
-			sdma->script_addrs->ram_code_start_addr);
-
 	/* Set bits of CONFIG register with given context switching mode */
 	__raw_writel(SDMA_H_CONFIG_CSM, sdma->regs + SDMA_H_CONFIG);
 
@@ -1216,16 +1240,10 @@ err_dma_alloc:
 static int __init sdma_probe(struct platform_device *pdev)
 {
 	int ret;
-	const struct firmware *fw;
-	const struct sdma_firmware_header *header;
-	const struct sdma_script_start_addrs *addr;
 	int irq;
-	unsigned short *ram_code;
 	struct resource *iores;
 	struct sdma_platform_data *pdata = pdev->dev.platform_data;
-	char *fwname;
 	int i;
-	dma_cap_mask_t mask;
 	struct sdma_engine *sdma;
 
 	sdma = kzalloc(sizeof(*sdma), GFP_KERNEL);
@@ -1262,41 +1280,15 @@ static int __init sdma_probe(struct plat
 	if (ret)
 		goto err_request_irq;
 
-	fwname = kasprintf(GFP_KERNEL, "/*(DEBLOBBED)*/",
-			pdata->cpu_name, pdata->to_version);
-	if (!fwname) {
-		ret = -ENOMEM;
-		goto err_cputype;
-	}
-
-	ret = reject_firmware(&fw, fwname, &pdev->dev);
-	if (ret) {
-		dev_err(&pdev->dev, "request firmware \"%s\" failed with %d\n",
-				fwname, ret);
-		kfree(fwname);
-		goto err_cputype;
-	}
-	kfree(fwname);
-
-	if (fw->size < sizeof(*header))
-		goto err_firmware;
-
-	header = (struct sdma_firmware_header *)fw->data;
-
-	if (header->magic != SDMA_FIRMWARE_MAGIC)
-		goto err_firmware;
-	if (header->ram_code_start + header->ram_code_size > fw->size)
-		goto err_firmware;
-
-	addr = (void *)header + header->script_addrs_start;
-	ram_code = (void *)header + header->ram_code_start;
-	sdma->script_addrs = kmalloc(sizeof(*addr), GFP_KERNEL);
+	sdma->script_addrs = kzalloc(sizeof(*sdma->script_addrs), GFP_KERNEL);
 	if (!sdma->script_addrs)
-		goto err_firmware;
-	memcpy(sdma->script_addrs, addr, sizeof(*addr));
+		goto err_alloc;
 
 	sdma->version = pdata->sdma_version;
 
+	dma_cap_set(DMA_SLAVE, sdma->dma_device.cap_mask);
+	dma_cap_set(DMA_CYCLIC, sdma->dma_device.cap_mask);
+
 	INIT_LIST_HEAD(&sdma->dma_device.channels);
 	/* Initialize channel parameters */
 	for (i = 0; i < MAX_DMA_CHANNELS; i++) {
@@ -1305,21 +1297,28 @@ static int __init sdma_probe(struct plat
 		sdmac->sdma = sdma;
 		spin_lock_init(&sdmac->lock);
 
-		dma_cap_set(DMA_SLAVE, sdma->dma_device.cap_mask);
-		dma_cap_set(DMA_CYCLIC, sdma->dma_device.cap_mask);
-
 		sdmac->chan.device = &sdma->dma_device;
-		sdmac->chan.chan_id = i;
 		sdmac->channel = i;
 
-		/* Add the channel to the DMAC list */
-		list_add_tail(&sdmac->chan.device_node, &sdma->dma_device.channels);
+		/*
+		 * Add the channel to the DMAC list. Do not add channel 0 though
+		 * because we need it internally in the SDMA driver. This also means
+		 * that channel 0 in dmaengine counting matches sdma channel 1.
+		 */
+		if (i)
+			list_add_tail(&sdmac->chan.device_node,
+					&sdma->dma_device.channels);
 	}
 
-	ret = sdma_init(sdma, ram_code, header->ram_code_size);
+	ret = sdma_init(sdma);
 	if (ret)
 		goto err_init;
 
+	if (pdata->script_addrs)
+		sdma_add_scripts(sdma, pdata->script_addrs);
+
+	sdma_get_firmware(sdma, pdata->cpu_name, pdata->to_version);
+
 	sdma->dma_device.dev = &pdev->dev;
 
 	sdma->dma_device.device_alloc_chan_resources = sdma_alloc_chan_resources;
@@ -1329,6 +1328,8 @@ static int __init sdma_probe(struct plat
 	sdma->dma_device.device_prep_dma_cyclic = sdma_prep_dma_cyclic;
 	sdma->dma_device.device_control = sdma_control;
 	sdma->dma_device.device_issue_pending = sdma_issue_pending;
+	sdma->dma_device.dev->dma_parms = &sdma->dma_parms;
+	dma_set_max_seg_size(sdma->dma_device.dev, 65535);
 
 	ret = dma_async_device_register(&sdma->dma_device);
 	if (ret) {
@@ -1336,26 +1337,13 @@ static int __init sdma_probe(struct plat
 		goto err_init;
 	}
 
-	dev_info(&pdev->dev, "initialized (firmware %d.%d)\n",
-			header->version_major,
-			header->version_minor);
-
-	/* request channel 0. This is an internal control channel
-	 * to the SDMA engine and not available to clients.
-	 */
-	dma_cap_zero(mask);
-	dma_cap_set(DMA_SLAVE, mask);
-	dma_request_channel(mask, NULL, NULL);
-
-	release_firmware(fw);
+	dev_info(sdma->dev, "initialized\n");
 
 	return 0;
 
 err_init:
 	kfree(sdma->script_addrs);
-err_firmware:
-	release_firmware(fw);
-err_cputype:
+err_alloc:
 	free_irq(irq, sdma);
 err_request_irq:
 	iounmap(sdma->regs);
@@ -1366,7 +1354,7 @@ err_clk:
 err_request_region:
 err_irq:
 	kfree(sdma);
-	return 0;
+	return ret;
 }
 
 static int __exit sdma_remove(struct platform_device *pdev)
diff -druNp linux-libre-2.6.37-gnu1/drivers/dma/intel_mid_dma.c linux-libre-2.6.38-gnu1/drivers/dma/intel_mid_dma.c
--- linux-libre-2.6.37-gnu1/drivers/dma/intel_mid_dma.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/dma/intel_mid_dma.c	2011-03-14 21:20:32.000000000 -0400
@@ -664,11 +664,20 @@ static struct dma_async_tx_descriptor *i
 	/*calculate CTL_LO*/
 	ctl_lo.ctl_lo = 0;
 	ctl_lo.ctlx.int_en = 1;
-	ctl_lo.ctlx.dst_tr_width = mids->dma_slave.dst_addr_width;
-	ctl_lo.ctlx.src_tr_width = mids->dma_slave.src_addr_width;
 	ctl_lo.ctlx.dst_msize = mids->dma_slave.src_maxburst;
 	ctl_lo.ctlx.src_msize = mids->dma_slave.dst_maxburst;
 
+	/*
+	 * Here we need some translation from "enum dma_slave_buswidth"
+	 * to the format for our dma controller
+	 *		standard	intel_mid_dmac's format
+	 *		 1 Byte			0b000
+	 *		 2 Bytes		0b001
+	 *		 4 Bytes		0b010
+	 */
+	ctl_lo.ctlx.dst_tr_width = mids->dma_slave.dst_addr_width / 2;
+	ctl_lo.ctlx.src_tr_width = mids->dma_slave.src_addr_width / 2;
+
 	if (mids->cfg_mode == LNW_DMA_MEM_TO_MEM) {
 		ctl_lo.ctlx.tt_fc = 0;
 		ctl_lo.ctlx.sinc = 0;
@@ -746,8 +755,18 @@ static struct dma_async_tx_descriptor *i
 	BUG_ON(!mids);
 
 	if (!midc->dma->pimr_mask) {
-		pr_debug("MDMA: SG list is not supported by this controller\n");
-		return  NULL;
+		/* We can still handle sg list with only one item */
+		if (sg_len == 1) {
+			txd = intel_mid_dma_prep_memcpy(chan,
+						mids->dma_slave.dst_addr,
+						mids->dma_slave.src_addr,
+						sgl->length,
+						flags);
+			return txd;
+		} else {
+			pr_warn("MDMA: SG list is not supported by this controller\n");
+			return  NULL;
+		}
 	}
 
 	pr_debug("MDMA: SG Length = %d, direction = %d, Flags = %#lx\n",
@@ -758,6 +777,7 @@ static struct dma_async_tx_descriptor *i
 		pr_err("MDMA: Prep memcpy failed\n");
 		return NULL;
 	}
+
 	desc = to_intel_mid_dma_desc(txd);
 	desc->dirn = direction;
 	ctl_lo.ctl_lo = desc->ctl_lo;
@@ -1021,11 +1041,6 @@ static irqreturn_t intel_mid_dma_interru
 
 	/*DMA Interrupt*/
 	pr_debug("MDMA:Got an interrupt on irq %d\n", irq);
-	if (!mid) {
-		pr_err("ERR_MDMA:null pointer mid\n");
-		return -EINVAL;
-	}
-
 	pr_debug("MDMA: Status %x, Mask %x\n", tfr_status, mid->intr_mask);
 	tfr_status &= mid->intr_mask;
 	if (tfr_status) {
@@ -1060,8 +1075,8 @@ static irqreturn_t intel_mid_dma_interru
  * mid_setup_dma -	Setup the DMA controller
  * @pdev: Controller PCI device structure
  *
- * Initilize the DMA controller, channels, registers with DMA engine,
- * ISR. Initilize DMA controller channels.
+ * Initialize the DMA controller, channels, registers with DMA engine,
+ * ISR. Initialize DMA controller channels.
  */
 static int mid_setup_dma(struct pci_dev *pdev)
 {
@@ -1217,7 +1232,7 @@ static void middma_shutdown(struct pci_d
  * @pdev: Controller PCI device structure
  * @id: pci device id structure
  *
- * Initilize the PCI device, map BARs, query driver data.
+ * Initialize the PCI device, map BARs, query driver data.
  * Call setup_dma to complete contoller and chan initilzation
  */
 static int __devinit intel_mid_dma_probe(struct pci_dev *pdev,
diff -druNp linux-libre-2.6.37-gnu1/drivers/dma/iop-adma.c linux-libre-2.6.38-gnu1/drivers/dma/iop-adma.c
--- linux-libre-2.6.37-gnu1/drivers/dma/iop-adma.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/dma/iop-adma.c	2011-03-14 21:20:32.000000000 -0400
@@ -1261,7 +1261,7 @@ out:
 	return err;
 }
 
-#ifdef CONFIG_MD_RAID6_PQ
+#ifdef CONFIG_RAID6_PQ
 static int __devinit
 iop_adma_pq_zero_sum_self_test(struct iop_adma_device *device)
 {
@@ -1584,7 +1584,7 @@ static int __devinit iop_adma_probe(stru
 
 	if (dma_has_cap(DMA_PQ, dma_dev->cap_mask) &&
 	    dma_has_cap(DMA_PQ_VAL, dma_dev->cap_mask)) {
-		#ifdef CONFIG_MD_RAID6_PQ
+		#ifdef CONFIG_RAID6_PQ
 		ret = iop_adma_pq_zero_sum_self_test(adev);
 		dev_dbg(&pdev->dev, "pq self test returned %d\n", ret);
 		#else
diff -druNp linux-libre-2.6.37-gnu1/drivers/dma/ipu/ipu_idmac.c linux-libre-2.6.38-gnu1/drivers/dma/ipu/ipu_idmac.c
--- linux-libre-2.6.37-gnu1/drivers/dma/ipu/ipu_idmac.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/dma/ipu/ipu_idmac.c	2011-03-14 21:20:32.000000000 -0400
@@ -1145,29 +1145,6 @@ static int ipu_disable_channel(struct id
 	reg = idmac_read_icreg(ipu, IDMAC_CHA_EN);
 	idmac_write_icreg(ipu, reg & ~chan_mask, IDMAC_CHA_EN);
 
-	/*
-	 * Problem (observed with channel DMAIC_7): after enabling the channel
-	 * and initialising buffers, there comes an interrupt with current still
-	 * pointing at buffer 0, whereas it should use buffer 0 first and only
-	 * generate an interrupt when it is done, then current should already
-	 * point to buffer 1. This spurious interrupt also comes on channel
-	 * DMASDC_0. With DMAIC_7 normally, is we just leave the ISR after the
-	 * first interrupt, there comes the second with current correctly
-	 * pointing to buffer 1 this time. But sometimes this second interrupt
-	 * doesn't come and the channel hangs. Clearing BUFx_RDY when disabling
-	 * the channel seems to prevent the channel from hanging, but it doesn't
-	 * prevent the spurious interrupt. This might also be unsafe. Think
-	 * about the IDMAC controller trying to switch to a buffer, when we
-	 * clear the ready bit, and re-enable it a moment later.
-	 */
-	reg = idmac_read_ipureg(ipu, IPU_CHA_BUF0_RDY);
-	idmac_write_ipureg(ipu, 0, IPU_CHA_BUF0_RDY);
-	idmac_write_ipureg(ipu, reg & ~(1UL << channel), IPU_CHA_BUF0_RDY);
-
-	reg = idmac_read_ipureg(ipu, IPU_CHA_BUF1_RDY);
-	idmac_write_ipureg(ipu, 0, IPU_CHA_BUF1_RDY);
-	idmac_write_ipureg(ipu, reg & ~(1UL << channel), IPU_CHA_BUF1_RDY);
-
 	spin_unlock_irqrestore(&ipu->lock, flags);
 
 	return 0;
@@ -1246,33 +1223,6 @@ static irqreturn_t idmac_interrupt(int i
 
 	/* Other interrupts do not interfere with this channel */
 	spin_lock(&ichan->lock);
-	if (unlikely(chan_id != IDMAC_SDC_0 && chan_id != IDMAC_SDC_1 &&
-		     ((curbuf >> chan_id) & 1) == ichan->active_buffer &&
-		     !list_is_last(ichan->queue.next, &ichan->queue))) {
-		int i = 100;
-
-		/* This doesn't help. See comment in ipu_disable_channel() */
-		while (--i) {
-			curbuf = idmac_read_ipureg(&ipu_data, IPU_CHA_CUR_BUF);
-			if (((curbuf >> chan_id) & 1) != ichan->active_buffer)
-				break;
-			cpu_relax();
-		}
-
-		if (!i) {
-			spin_unlock(&ichan->lock);
-			dev_dbg(dev,
-				"IRQ on active buffer on channel %x, active "
-				"%d, ready %x, %x, current %x!\n", chan_id,
-				ichan->active_buffer, ready0, ready1, curbuf);
-			return IRQ_NONE;
-		} else
-			dev_dbg(dev,
-				"Buffer deactivated on channel %x, active "
-				"%d, ready %x, %x, current %x, rest %d!\n", chan_id,
-				ichan->active_buffer, ready0, ready1, curbuf, i);
-	}
-
 	if (unlikely((ichan->active_buffer && (ready1 >> chan_id) & 1) ||
 		     (!ichan->active_buffer && (ready0 >> chan_id) & 1)
 		     )) {
diff -druNp linux-libre-2.6.37-gnu1/drivers/dma/Kconfig linux-libre-2.6.38-gnu1/drivers/dma/Kconfig
--- linux-libre-2.6.37-gnu1/drivers/dma/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/dma/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -109,7 +109,7 @@ config FSL_DMA
 
 config MPC512X_DMA
 	tristate "Freescale MPC512x built-in DMA engine support"
-	depends on PPC_MPC512x
+	depends on PPC_MPC512x || PPC_MPC831x
 	select DMA_ENGINE
 	---help---
 	  Enable support for the Freescale MPC512x built-in DMA engine.
@@ -200,11 +200,16 @@ config PL330_DMA
 	  platform_data for a dma-pl330 device.
 
 config PCH_DMA
-	tristate "Topcliff (Intel EG20T) PCH DMA support"
+	tristate "Intel EG20T PCH / OKI SEMICONDUCTOR ML7213 IOH DMA support"
 	depends on PCI && X86
 	select DMA_ENGINE
 	help
-	  Enable support for the Topcliff (Intel EG20T) PCH DMA engine.
+	  Enable support for Intel EG20T PCH DMA engine.
+
+	  This driver also can be used for OKI SEMICONDUCTOR ML7213 IOH(Input/
+	  Output Hub) which is for IVI(In-Vehicle Infotainment) use.
+	  ML7213 is companion chip for Intel Atom E6xx series.
+	  ML7213 is completely compatible for Intel EG20T PCH.
 
 config IMX_SDMA
 	tristate "i.MX SDMA support"
diff -druNp linux-libre-2.6.37-gnu1/drivers/dma/mpc512x_dma.c linux-libre-2.6.38-gnu1/drivers/dma/mpc512x_dma.c
--- linux-libre-2.6.37-gnu1/drivers/dma/mpc512x_dma.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/dma/mpc512x_dma.c	2011-03-14 21:20:32.000000000 -0400
@@ -1,6 +1,7 @@
 /*
  * Copyright (C) Freescale Semicondutor, Inc. 2007, 2008.
  * Copyright (C) Semihalf 2009
+ * Copyright (C) Ilya Yanok, Emcraft Systems 2010
  *
  * Written by Piotr Ziecik <kosmo@semihalf.com>. Hardware description
  * (defines, structures and comments) was taken from MPC5121 DMA driver
@@ -70,6 +71,8 @@
 #define MPC_DMA_DMAES_SBE	(1 << 1)
 #define MPC_DMA_DMAES_DBE	(1 << 0)
 
+#define MPC_DMA_DMAGPOR_SNOOP_ENABLE	(1 << 6)
+
 #define MPC_DMA_TSIZE_1		0x00
 #define MPC_DMA_TSIZE_2		0x01
 #define MPC_DMA_TSIZE_4		0x02
@@ -104,7 +107,10 @@ struct __attribute__ ((__packed__)) mpc_
 	/* 0x30 */
 	u32 dmahrsh;		/* DMA hw request status high(ch63~32) */
 	u32 dmahrsl;		/* DMA hardware request status low(ch31~0) */
-	u32 dmaihsa;		/* DMA interrupt high select AXE(ch63~32) */
+	union {
+		u32 dmaihsa;	/* DMA interrupt high select AXE(ch63~32) */
+		u32 dmagpor;	/* (General purpose register on MPC8308) */
+	};
 	u32 dmailsa;		/* DMA interrupt low select AXE(ch31~0) */
 	/* 0x40 ~ 0xff */
 	u32 reserve0[48];	/* Reserved */
@@ -195,7 +201,9 @@ struct mpc_dma {
 	struct mpc_dma_regs __iomem	*regs;
 	struct mpc_dma_tcd __iomem	*tcd;
 	int				irq;
+	int				irq2;
 	uint				error_status;
+	int				is_mpc8308;
 
 	/* Lock for error_status field in this structure */
 	spinlock_t			error_status_lock;
@@ -252,11 +260,13 @@ static void mpc_dma_execute(struct mpc_d
 		prev = mdesc;
 	}
 
-	prev->tcd->start = 0;
 	prev->tcd->int_maj = 1;
 
 	/* Send first descriptor in chain into hardware */
 	memcpy_toio(&mdma->tcd[cid], first->tcd, sizeof(struct mpc_dma_tcd));
+
+	if (first != prev)
+		mdma->tcd[cid].e_sg = 1;
 	out_8(&mdma->regs->dmassrt, cid);
 }
 
@@ -274,6 +284,9 @@ static void mpc_dma_irq_process(struct m
 
 		spin_lock(&mchan->lock);
 
+		out_8(&mdma->regs->dmacint, ch + off);
+		out_8(&mdma->regs->dmacerr, ch + off);
+
 		/* Check error status */
 		if (es & (1 << ch))
 			list_for_each_entry(mdesc, &mchan->active, node)
@@ -302,36 +315,68 @@ static irqreturn_t mpc_dma_irq(int irq,
 	spin_unlock(&mdma->error_status_lock);
 
 	/* Handle interrupt on each channel */
-	mpc_dma_irq_process(mdma, in_be32(&mdma->regs->dmainth),
+	if (mdma->dma.chancnt > 32) {
+		mpc_dma_irq_process(mdma, in_be32(&mdma->regs->dmainth),
 					in_be32(&mdma->regs->dmaerrh), 32);
+	}
 	mpc_dma_irq_process(mdma, in_be32(&mdma->regs->dmaintl),
 					in_be32(&mdma->regs->dmaerrl), 0);
 
-	/* Ack interrupt on all channels */
-	out_be32(&mdma->regs->dmainth, 0xFFFFFFFF);
-	out_be32(&mdma->regs->dmaintl, 0xFFFFFFFF);
-	out_be32(&mdma->regs->dmaerrh, 0xFFFFFFFF);
-	out_be32(&mdma->regs->dmaerrl, 0xFFFFFFFF);
-
 	/* Schedule tasklet */
 	tasklet_schedule(&mdma->tasklet);
 
 	return IRQ_HANDLED;
 }
 
-/* DMA Tasklet */
-static void mpc_dma_tasklet(unsigned long data)
+/* proccess completed descriptors */
+static void mpc_dma_process_completed(struct mpc_dma *mdma)
 {
-	struct mpc_dma *mdma = (void *)data;
 	dma_cookie_t last_cookie = 0;
 	struct mpc_dma_chan *mchan;
 	struct mpc_dma_desc *mdesc;
 	struct dma_async_tx_descriptor *desc;
 	unsigned long flags;
 	LIST_HEAD(list);
-	uint es;
 	int i;
 
+	for (i = 0; i < mdma->dma.chancnt; i++) {
+		mchan = &mdma->channels[i];
+
+		/* Get all completed descriptors */
+		spin_lock_irqsave(&mchan->lock, flags);
+		if (!list_empty(&mchan->completed))
+			list_splice_tail_init(&mchan->completed, &list);
+		spin_unlock_irqrestore(&mchan->lock, flags);
+
+		if (list_empty(&list))
+			continue;
+
+		/* Execute callbacks and run dependencies */
+		list_for_each_entry(mdesc, &list, node) {
+			desc = &mdesc->desc;
+
+			if (desc->callback)
+				desc->callback(desc->callback_param);
+
+			last_cookie = desc->cookie;
+			dma_run_dependencies(desc);
+		}
+
+		/* Free descriptors */
+		spin_lock_irqsave(&mchan->lock, flags);
+		list_splice_tail_init(&list, &mchan->free);
+		mchan->completed_cookie = last_cookie;
+		spin_unlock_irqrestore(&mchan->lock, flags);
+	}
+}
+
+/* DMA Tasklet */
+static void mpc_dma_tasklet(unsigned long data)
+{
+	struct mpc_dma *mdma = (void *)data;
+	unsigned long flags;
+	uint es;
+
 	spin_lock_irqsave(&mdma->error_status_lock, flags);
 	es = mdma->error_status;
 	mdma->error_status = 0;
@@ -370,35 +415,7 @@ static void mpc_dma_tasklet(unsigned lon
 			dev_err(mdma->dma.dev, "- Destination Bus Error\n");
 	}
 
-	for (i = 0; i < mdma->dma.chancnt; i++) {
-		mchan = &mdma->channels[i];
-
-		/* Get all completed descriptors */
-		spin_lock_irqsave(&mchan->lock, flags);
-		if (!list_empty(&mchan->completed))
-			list_splice_tail_init(&mchan->completed, &list);
-		spin_unlock_irqrestore(&mchan->lock, flags);
-
-		if (list_empty(&list))
-			continue;
-
-		/* Execute callbacks and run dependencies */
-		list_for_each_entry(mdesc, &list, node) {
-			desc = &mdesc->desc;
-
-			if (desc->callback)
-				desc->callback(desc->callback_param);
-
-			last_cookie = desc->cookie;
-			dma_run_dependencies(desc);
-		}
-
-		/* Free descriptors */
-		spin_lock_irqsave(&mchan->lock, flags);
-		list_splice_tail_init(&list, &mchan->free);
-		mchan->completed_cookie = last_cookie;
-		spin_unlock_irqrestore(&mchan->lock, flags);
-	}
+	mpc_dma_process_completed(mdma);
 }
 
 /* Submit descriptor to hardware */
@@ -563,6 +580,7 @@ static struct dma_async_tx_descriptor *
 mpc_dma_prep_memcpy(struct dma_chan *chan, dma_addr_t dst, dma_addr_t src,
 					size_t len, unsigned long flags)
 {
+	struct mpc_dma *mdma = dma_chan_to_mpc_dma(chan);
 	struct mpc_dma_chan *mchan = dma_chan_to_mpc_dma_chan(chan);
 	struct mpc_dma_desc *mdesc = NULL;
 	struct mpc_dma_tcd *tcd;
@@ -577,8 +595,11 @@ mpc_dma_prep_memcpy(struct dma_chan *cha
 	}
 	spin_unlock_irqrestore(&mchan->lock, iflags);
 
-	if (!mdesc)
+	if (!mdesc) {
+		/* try to free completed descriptors */
+		mpc_dma_process_completed(mdma);
 		return NULL;
+	}
 
 	mdesc->error = 0;
 	tcd = mdesc->tcd;
@@ -591,7 +612,8 @@ mpc_dma_prep_memcpy(struct dma_chan *cha
 		tcd->dsize = MPC_DMA_TSIZE_32;
 		tcd->soff = 32;
 		tcd->doff = 32;
-	} else if (IS_ALIGNED(src | dst | len, 16)) {
+	} else if (!mdma->is_mpc8308 && IS_ALIGNED(src | dst | len, 16)) {
+		/* MPC8308 doesn't support 16 byte transfers */
 		tcd->ssize = MPC_DMA_TSIZE_16;
 		tcd->dsize = MPC_DMA_TSIZE_16;
 		tcd->soff = 16;
@@ -651,6 +673,15 @@ static int __devinit mpc_dma_probe(struc
 		return -EINVAL;
 	}
 
+	if (of_device_is_compatible(dn, "fsl,mpc8308-dma")) {
+		mdma->is_mpc8308 = 1;
+		mdma->irq2 = irq_of_parse_and_map(dn, 1);
+		if (mdma->irq2 == NO_IRQ) {
+			dev_err(dev, "Error mapping IRQ!\n");
+			return -EINVAL;
+		}
+	}
+
 	retval = of_address_to_resource(dn, 0, &res);
 	if (retval) {
 		dev_err(dev, "Error parsing memory region!\n");
@@ -681,11 +712,23 @@ static int __devinit mpc_dma_probe(struc
 		return -EINVAL;
 	}
 
+	if (mdma->is_mpc8308) {
+		retval = devm_request_irq(dev, mdma->irq2, &mpc_dma_irq, 0,
+				DRV_NAME, mdma);
+		if (retval) {
+			dev_err(dev, "Error requesting IRQ2!\n");
+			return -EINVAL;
+		}
+	}
+
 	spin_lock_init(&mdma->error_status_lock);
 
 	dma = &mdma->dma;
 	dma->dev = dev;
-	dma->chancnt = MPC_DMA_CHANNELS;
+	if (!mdma->is_mpc8308)
+		dma->chancnt = MPC_DMA_CHANNELS;
+	else
+		dma->chancnt = 16; /* MPC8308 DMA has only 16 channels */
 	dma->device_alloc_chan_resources = mpc_dma_alloc_chan_resources;
 	dma->device_free_chan_resources = mpc_dma_free_chan_resources;
 	dma->device_issue_pending = mpc_dma_issue_pending;
@@ -721,26 +764,40 @@ static int __devinit mpc_dma_probe(struc
 	 * - Round-robin group arbitration,
 	 * - Round-robin channel arbitration.
 	 */
-	out_be32(&mdma->regs->dmacr, MPC_DMA_DMACR_EDCG |
-				MPC_DMA_DMACR_ERGA | MPC_DMA_DMACR_ERCA);
+	if (!mdma->is_mpc8308) {
+		out_be32(&mdma->regs->dmacr, MPC_DMA_DMACR_EDCG |
+					MPC_DMA_DMACR_ERGA | MPC_DMA_DMACR_ERCA);
 
-	/* Disable hardware DMA requests */
-	out_be32(&mdma->regs->dmaerqh, 0);
-	out_be32(&mdma->regs->dmaerql, 0);
+		/* Disable hardware DMA requests */
+		out_be32(&mdma->regs->dmaerqh, 0);
+		out_be32(&mdma->regs->dmaerql, 0);
 
-	/* Disable error interrupts */
-	out_be32(&mdma->regs->dmaeeih, 0);
-	out_be32(&mdma->regs->dmaeeil, 0);
+		/* Disable error interrupts */
+		out_be32(&mdma->regs->dmaeeih, 0);
+		out_be32(&mdma->regs->dmaeeil, 0);
 
-	/* Clear interrupts status */
-	out_be32(&mdma->regs->dmainth, 0xFFFFFFFF);
-	out_be32(&mdma->regs->dmaintl, 0xFFFFFFFF);
-	out_be32(&mdma->regs->dmaerrh, 0xFFFFFFFF);
-	out_be32(&mdma->regs->dmaerrl, 0xFFFFFFFF);
+		/* Clear interrupts status */
+		out_be32(&mdma->regs->dmainth, 0xFFFFFFFF);
+		out_be32(&mdma->regs->dmaintl, 0xFFFFFFFF);
+		out_be32(&mdma->regs->dmaerrh, 0xFFFFFFFF);
+		out_be32(&mdma->regs->dmaerrl, 0xFFFFFFFF);
 
-	/* Route interrupts to IPIC */
-	out_be32(&mdma->regs->dmaihsa, 0);
-	out_be32(&mdma->regs->dmailsa, 0);
+		/* Route interrupts to IPIC */
+		out_be32(&mdma->regs->dmaihsa, 0);
+		out_be32(&mdma->regs->dmailsa, 0);
+	} else {
+		/* MPC8308 has 16 channels and lacks some registers */
+		out_be32(&mdma->regs->dmacr, MPC_DMA_DMACR_ERCA);
+
+		/* enable snooping */
+		out_be32(&mdma->regs->dmagpor, MPC_DMA_DMAGPOR_SNOOP_ENABLE);
+		/* Disable error interrupts */
+		out_be32(&mdma->regs->dmaeeil, 0);
+
+		/* Clear interrupts status */
+		out_be32(&mdma->regs->dmaintl, 0xFFFF);
+		out_be32(&mdma->regs->dmaerrl, 0xFFFF);
+	}
 
 	/* Register DMA engine */
 	dev_set_drvdata(dev, mdma);
diff -druNp linux-libre-2.6.37-gnu1/drivers/dma/pch_dma.c linux-libre-2.6.38-gnu1/drivers/dma/pch_dma.c
--- linux-libre-2.6.37-gnu1/drivers/dma/pch_dma.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/dma/pch_dma.c	2011-03-14 21:20:32.000000000 -0400
@@ -1,6 +1,7 @@
 /*
  * Topcliff PCH DMA controller driver
  * Copyright (c) 2010 Intel Corporation
+ * Copyright (C) 2011 OKI SEMICONDUCTOR 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
@@ -921,12 +922,19 @@ static void __devexit pch_dma_remove(str
 }
 
 /* PCI Device ID of DMA device */
-#define PCI_DEVICE_ID_PCH_DMA_8CH        0x8810
-#define PCI_DEVICE_ID_PCH_DMA_4CH        0x8815
+#define PCI_VENDOR_ID_ROHM             0x10DB
+#define PCI_DEVICE_ID_EG20T_PCH_DMA_8CH        0x8810
+#define PCI_DEVICE_ID_EG20T_PCH_DMA_4CH        0x8815
+#define PCI_DEVICE_ID_ML7213_DMA1_8CH	0x8026
+#define PCI_DEVICE_ID_ML7213_DMA2_8CH	0x802B
+#define PCI_DEVICE_ID_ML7213_DMA3_4CH	0x8034
 
 static const struct pci_device_id pch_dma_id_table[] = {
-	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_PCH_DMA_8CH), 8 },
-	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_PCH_DMA_4CH), 4 },
+	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_EG20T_PCH_DMA_8CH), 8 },
+	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_EG20T_PCH_DMA_4CH), 4 },
+	{ PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ML7213_DMA1_8CH), 8}, /* UART Video */
+	{ PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ML7213_DMA2_8CH), 8}, /* PCMIF SPI */
+	{ PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ML7213_DMA3_4CH), 4}, /* FPGA */
 	{ 0, },
 };
 
@@ -954,6 +962,7 @@ static void __exit pch_dma_exit(void)
 module_init(pch_dma_init);
 module_exit(pch_dma_exit);
 
-MODULE_DESCRIPTION("Topcliff PCH DMA controller driver");
+MODULE_DESCRIPTION("Intel EG20T PCH / OKI SEMICONDUCTOR ML7213 IOH "
+		   "DMA controller driver");
 MODULE_AUTHOR("Yong Wang <yong.y.wang@intel.com>");
 MODULE_LICENSE("GPL v2");
diff -druNp linux-libre-2.6.37-gnu1/drivers/dma/shdma.c linux-libre-2.6.38-gnu1/drivers/dma/shdma.c
--- linux-libre-2.6.37-gnu1/drivers/dma/shdma.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/dma/shdma.c	2011-03-14 21:20:32.000000000 -0400
@@ -27,7 +27,10 @@
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
 #include <linux/sh_dma.h>
-
+#include <linux/notifier.h>
+#include <linux/kdebug.h>
+#include <linux/spinlock.h>
+#include <linux/rculist.h>
 #include "shdma.h"
 
 /* DMA descriptor control */
@@ -43,6 +46,13 @@ enum sh_dmae_desc_status {
 /* Default MEMCPY transfer size = 2^2 = 4 bytes */
 #define LOG2_DEFAULT_XFER_SIZE	2
 
+/*
+ * Used for write-side mutual exclusion for the global device list,
+ * read-side synchronization by way of RCU.
+ */
+static DEFINE_SPINLOCK(sh_dmae_lock);
+static LIST_HEAD(sh_dmae_devices);
+
 /* A bitmask with bits enough for enum sh_dmae_slave_chan_id */
 static unsigned long sh_dmae_slave_used[BITS_TO_LONGS(SH_DMA_SLAVE_NUMBER)];
 
@@ -817,10 +827,9 @@ static irqreturn_t sh_dmae_interrupt(int
 	return ret;
 }
 
-#if defined(CONFIG_CPU_SH4) || defined(CONFIG_ARCH_SHMOBILE)
-static irqreturn_t sh_dmae_err(int irq, void *data)
+static unsigned int sh_dmae_reset(struct sh_dmae_device *shdev)
 {
-	struct sh_dmae_device *shdev = (struct sh_dmae_device *)data;
+	unsigned int handled = 0;
 	int i;
 
 	/* halt the dma controller */
@@ -829,25 +838,35 @@ static irqreturn_t sh_dmae_err(int irq,
 	/* We cannot detect, which channel caused the error, have to reset all */
 	for (i = 0; i < SH_DMAC_MAX_CHANNELS; i++) {
 		struct sh_dmae_chan *sh_chan = shdev->chan[i];
-		if (sh_chan) {
-			struct sh_desc *desc;
-			/* Stop the channel */
-			dmae_halt(sh_chan);
-			/* Complete all  */
-			list_for_each_entry(desc, &sh_chan->ld_queue, node) {
-				struct dma_async_tx_descriptor *tx = &desc->async_tx;
-				desc->mark = DESC_IDLE;
-				if (tx->callback)
-					tx->callback(tx->callback_param);
-			}
-			list_splice_init(&sh_chan->ld_queue, &sh_chan->ld_free);
+		struct sh_desc *desc;
+
+		if (!sh_chan)
+			continue;
+
+		/* Stop the channel */
+		dmae_halt(sh_chan);
+
+		/* Complete all  */
+		list_for_each_entry(desc, &sh_chan->ld_queue, node) {
+			struct dma_async_tx_descriptor *tx = &desc->async_tx;
+			desc->mark = DESC_IDLE;
+			if (tx->callback)
+				tx->callback(tx->callback_param);
 		}
+
+		list_splice_init(&sh_chan->ld_queue, &sh_chan->ld_free);
+		handled++;
 	}
+
 	sh_dmae_rst(shdev);
 
-	return IRQ_HANDLED;
+	return !!handled;
+}
+
+static irqreturn_t sh_dmae_err(int irq, void *data)
+{
+	return IRQ_RETVAL(sh_dmae_reset(data));
 }
-#endif
 
 static void dmae_do_tasklet(unsigned long data)
 {
@@ -876,6 +895,60 @@ static void dmae_do_tasklet(unsigned lon
 	sh_dmae_chan_ld_cleanup(sh_chan, false);
 }
 
+static bool sh_dmae_nmi_notify(struct sh_dmae_device *shdev)
+{
+	unsigned int handled;
+
+	/* Fast path out if NMIF is not asserted for this controller */
+	if ((dmaor_read(shdev) & DMAOR_NMIF) == 0)
+		return false;
+
+	handled = sh_dmae_reset(shdev);
+	if (handled)
+		return true;
+
+	return false;
+}
+
+static int sh_dmae_nmi_handler(struct notifier_block *self,
+			       unsigned long cmd, void *data)
+{
+	struct sh_dmae_device *shdev;
+	int ret = NOTIFY_DONE;
+	bool triggered;
+
+	/*
+	 * Only concern ourselves with NMI events.
+	 *
+	 * Normally we would check the die chain value, but as this needs
+	 * to be architecture independent, check for NMI context instead.
+	 */
+	if (!in_nmi())
+		return NOTIFY_DONE;
+
+	rcu_read_lock();
+	list_for_each_entry_rcu(shdev, &sh_dmae_devices, node) {
+		/*
+		 * Only stop if one of the controllers has NMIF asserted,
+		 * we do not want to interfere with regular address error
+		 * handling or NMI events that don't concern the DMACs.
+		 */
+		triggered = sh_dmae_nmi_notify(shdev);
+		if (triggered == true)
+			ret = NOTIFY_OK;
+	}
+	rcu_read_unlock();
+
+	return ret;
+}
+
+static struct notifier_block sh_dmae_nmi_notifier __read_mostly = {
+	.notifier_call	= sh_dmae_nmi_handler,
+
+	/* Run before NMI debug handler and KGDB */
+	.priority	= 1,
+};
+
 static int __devinit sh_dmae_chan_probe(struct sh_dmae_device *shdev, int id,
 					int irq, unsigned long flags)
 {
@@ -967,6 +1040,7 @@ static int __init sh_dmae_probe(struct p
 	struct sh_dmae_pdata *pdata = pdev->dev.platform_data;
 	unsigned long irqflags = IRQF_DISABLED,
 		chan_flag[SH_DMAC_MAX_CHANNELS] = {};
+	unsigned long flags;
 	int errirq, chan_irq[SH_DMAC_MAX_CHANNELS];
 	int err, i, irq_cnt = 0, irqres = 0;
 	struct sh_dmae_device *shdev;
@@ -1032,6 +1106,10 @@ static int __init sh_dmae_probe(struct p
 	pm_runtime_enable(&pdev->dev);
 	pm_runtime_get_sync(&pdev->dev);
 
+	spin_lock_irqsave(&sh_dmae_lock, flags);
+	list_add_tail_rcu(&shdev->node, &sh_dmae_devices);
+	spin_unlock_irqrestore(&sh_dmae_lock, flags);
+
 	/* reset dma controller */
 	err = sh_dmae_rst(shdev);
 	if (err)
@@ -1135,6 +1213,10 @@ eirqres:
 eirq_err:
 #endif
 rst_err:
+	spin_lock_irqsave(&sh_dmae_lock, flags);
+	list_del_rcu(&shdev->node);
+	spin_unlock_irqrestore(&sh_dmae_lock, flags);
+
 	pm_runtime_put(&pdev->dev);
 	if (dmars)
 		iounmap(shdev->dmars);
@@ -1155,6 +1237,7 @@ static int __exit sh_dmae_remove(struct
 {
 	struct sh_dmae_device *shdev = platform_get_drvdata(pdev);
 	struct resource *res;
+	unsigned long flags;
 	int errirq = platform_get_irq(pdev, 0);
 
 	dma_async_device_unregister(&shdev->common);
@@ -1162,6 +1245,10 @@ static int __exit sh_dmae_remove(struct
 	if (errirq > 0)
 		free_irq(errirq, shdev);
 
+	spin_lock_irqsave(&sh_dmae_lock, flags);
+	list_del_rcu(&shdev->node);
+	spin_unlock_irqrestore(&sh_dmae_lock, flags);
+
 	/* channel data remove */
 	sh_dmae_chan_remove(shdev);
 
@@ -1200,6 +1287,11 @@ static struct platform_driver sh_dmae_dr
 
 static int __init sh_dmae_init(void)
 {
+	/* Wire up NMI handling */
+	int err = register_die_notifier(&sh_dmae_nmi_notifier);
+	if (err)
+		return err;
+
 	return platform_driver_probe(&sh_dmae_driver, sh_dmae_probe);
 }
 module_init(sh_dmae_init);
@@ -1207,6 +1299,8 @@ module_init(sh_dmae_init);
 static void __exit sh_dmae_exit(void)
 {
 	platform_driver_unregister(&sh_dmae_driver);
+
+	unregister_die_notifier(&sh_dmae_nmi_notifier);
 }
 module_exit(sh_dmae_exit);
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/dma/shdma.h linux-libre-2.6.38-gnu1/drivers/dma/shdma.h
--- linux-libre-2.6.37-gnu1/drivers/dma/shdma.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/dma/shdma.h	2011-03-14 21:20:32.000000000 -0400
@@ -43,6 +43,7 @@ struct sh_dmae_device {
 	struct dma_device common;
 	struct sh_dmae_chan *chan[SH_DMAC_MAX_CHANNELS];
 	struct sh_dmae_pdata *pdata;
+	struct list_head node;
 	u32 __iomem *chan_reg;
 	u16 __iomem *dmars;
 };
diff -druNp linux-libre-2.6.37-gnu1/drivers/dma/ste_dma40.c linux-libre-2.6.38-gnu1/drivers/dma/ste_dma40.c
--- linux-libre-2.6.37-gnu1/drivers/dma/ste_dma40.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/dma/ste_dma40.c	2011-03-14 21:20:32.000000000 -0400
@@ -1,5 +1,6 @@
 /*
- * Copyright (C) ST-Ericsson SA 2007-2010
+ * Copyright (C) Ericsson AB 2007-2008
+ * Copyright (C) ST-Ericsson SA 2008-2010
  * Author: Per Forlin <per.forlin@stericsson.com> for ST-Ericsson
  * Author: Jonas Aaberg <jonas.aberg@stericsson.com> for ST-Ericsson
  * License terms: GNU General Public License (GPL) version 2
@@ -554,8 +555,66 @@ static struct d40_desc *d40_last_queued(
 	return d;
 }
 
-/* Support functions for logical channels */
+static int d40_psize_2_burst_size(bool is_log, int psize)
+{
+	if (is_log) {
+		if (psize == STEDMA40_PSIZE_LOG_1)
+			return 1;
+	} else {
+		if (psize == STEDMA40_PSIZE_PHY_1)
+			return 1;
+	}
+
+	return 2 << psize;
+}
+
+/*
+ * The dma only supports transmitting packages up to
+ * STEDMA40_MAX_SEG_SIZE << data_width. Calculate the total number of
+ * dma elements required to send the entire sg list
+ */
+static int d40_size_2_dmalen(int size, u32 data_width1, u32 data_width2)
+{
+	int dmalen;
+	u32 max_w = max(data_width1, data_width2);
+	u32 min_w = min(data_width1, data_width2);
+	u32 seg_max = ALIGN(STEDMA40_MAX_SEG_SIZE << min_w, 1 << max_w);
+
+	if (seg_max > STEDMA40_MAX_SEG_SIZE)
+		seg_max -= (1 << max_w);
+
+	if (!IS_ALIGNED(size, 1 << max_w))
+		return -EINVAL;
+
+	if (size <= seg_max)
+		dmalen = 1;
+	else {
+		dmalen = size / seg_max;
+		if (dmalen * seg_max < size)
+			dmalen++;
+	}
+	return dmalen;
+}
+
+static int d40_sg_2_dmalen(struct scatterlist *sgl, int sg_len,
+			   u32 data_width1, u32 data_width2)
+{
+	struct scatterlist *sg;
+	int i;
+	int len = 0;
+	int ret;
+
+	for_each_sg(sgl, sg, sg_len, i) {
+		ret = d40_size_2_dmalen(sg_dma_len(sg),
+					data_width1, data_width2);
+		if (ret < 0)
+			return ret;
+		len += ret;
+	}
+	return len;
+}
 
+/* Support functions for logical channels */
 
 static int d40_channel_execute_command(struct d40_chan *d40c,
 				       enum d40_command command)
@@ -1241,6 +1300,21 @@ static int d40_validate_conf(struct d40_
 		res = -EINVAL;
 	}
 
+	if (d40_psize_2_burst_size(is_log, conf->src_info.psize) *
+	    (1 << conf->src_info.data_width) !=
+	    d40_psize_2_burst_size(is_log, conf->dst_info.psize) *
+	    (1 << conf->dst_info.data_width)) {
+		/*
+		 * The DMAC hardware only supports
+		 * src (burst x width) == dst (burst x width)
+		 */
+
+		dev_err(&d40c->chan.dev->device,
+			"[%s] src (burst x width) != dst (burst x width)\n",
+			__func__);
+		res = -EINVAL;
+	}
+
 	return res;
 }
 
@@ -1638,13 +1712,21 @@ struct dma_async_tx_descriptor *stedma40
 	if (d40d == NULL)
 		goto err;
 
-	d40d->lli_len = sgl_len;
+	d40d->lli_len = d40_sg_2_dmalen(sgl_dst, sgl_len,
+					d40c->dma_cfg.src_info.data_width,
+					d40c->dma_cfg.dst_info.data_width);
+	if (d40d->lli_len < 0) {
+		dev_err(&d40c->chan.dev->device,
+			"[%s] Unaligned size\n", __func__);
+		goto err;
+	}
+
 	d40d->lli_current = 0;
 	d40d->txd.flags = dma_flags;
 
 	if (d40c->log_num != D40_PHY_CHAN) {
 
-		if (d40_pool_lli_alloc(d40d, sgl_len, true) < 0) {
+		if (d40_pool_lli_alloc(d40d, d40d->lli_len, true) < 0) {
 			dev_err(&d40c->chan.dev->device,
 				"[%s] Out of memory\n", __func__);
 			goto err;
@@ -1654,15 +1736,17 @@ struct dma_async_tx_descriptor *stedma40
 					 sgl_len,
 					 d40d->lli_log.src,
 					 d40c->log_def.lcsp1,
-					 d40c->dma_cfg.src_info.data_width);
+					 d40c->dma_cfg.src_info.data_width,
+					 d40c->dma_cfg.dst_info.data_width);
 
 		(void) d40_log_sg_to_lli(sgl_dst,
 					 sgl_len,
 					 d40d->lli_log.dst,
 					 d40c->log_def.lcsp3,
-					 d40c->dma_cfg.dst_info.data_width);
+					 d40c->dma_cfg.dst_info.data_width,
+					 d40c->dma_cfg.src_info.data_width);
 	} else {
-		if (d40_pool_lli_alloc(d40d, sgl_len, false) < 0) {
+		if (d40_pool_lli_alloc(d40d, d40d->lli_len, false) < 0) {
 			dev_err(&d40c->chan.dev->device,
 				"[%s] Out of memory\n", __func__);
 			goto err;
@@ -1675,6 +1759,7 @@ struct dma_async_tx_descriptor *stedma40
 					virt_to_phys(d40d->lli_phy.src),
 					d40c->src_def_cfg,
 					d40c->dma_cfg.src_info.data_width,
+					d40c->dma_cfg.dst_info.data_width,
 					d40c->dma_cfg.src_info.psize);
 
 		if (res < 0)
@@ -1687,6 +1772,7 @@ struct dma_async_tx_descriptor *stedma40
 					virt_to_phys(d40d->lli_phy.dst),
 					d40c->dst_def_cfg,
 					d40c->dma_cfg.dst_info.data_width,
+					d40c->dma_cfg.src_info.data_width,
 					d40c->dma_cfg.dst_info.psize);
 
 		if (res < 0)
@@ -1826,7 +1912,6 @@ static struct dma_async_tx_descriptor *d
 	struct d40_chan *d40c = container_of(chan, struct d40_chan,
 					     chan);
 	unsigned long flags;
-	int err = 0;
 
 	if (d40c->phy_chan == NULL) {
 		dev_err(&d40c->chan.dev->device,
@@ -1844,6 +1929,15 @@ static struct dma_async_tx_descriptor *d
 	}
 
 	d40d->txd.flags = dma_flags;
+	d40d->lli_len = d40_size_2_dmalen(size,
+					  d40c->dma_cfg.src_info.data_width,
+					  d40c->dma_cfg.dst_info.data_width);
+	if (d40d->lli_len < 0) {
+		dev_err(&d40c->chan.dev->device,
+			"[%s] Unaligned size\n", __func__);
+		goto err;
+	}
+
 
 	dma_async_tx_descriptor_init(&d40d->txd, chan);
 
@@ -1851,37 +1945,40 @@ static struct dma_async_tx_descriptor *d
 
 	if (d40c->log_num != D40_PHY_CHAN) {
 
-		if (d40_pool_lli_alloc(d40d, 1, true) < 0) {
+		if (d40_pool_lli_alloc(d40d, d40d->lli_len, true) < 0) {
 			dev_err(&d40c->chan.dev->device,
 				"[%s] Out of memory\n", __func__);
 			goto err;
 		}
-		d40d->lli_len = 1;
 		d40d->lli_current = 0;
 
-		d40_log_fill_lli(d40d->lli_log.src,
-				 src,
-				 size,
-				 d40c->log_def.lcsp1,
-				 d40c->dma_cfg.src_info.data_width,
-				 true);
+		if (d40_log_buf_to_lli(d40d->lli_log.src,
+				       src,
+				       size,
+				       d40c->log_def.lcsp1,
+				       d40c->dma_cfg.src_info.data_width,
+				       d40c->dma_cfg.dst_info.data_width,
+				       true) == NULL)
+			goto err;
 
-		d40_log_fill_lli(d40d->lli_log.dst,
-				 dst,
-				 size,
-				 d40c->log_def.lcsp3,
-				 d40c->dma_cfg.dst_info.data_width,
-				 true);
+		if (d40_log_buf_to_lli(d40d->lli_log.dst,
+				       dst,
+				       size,
+				       d40c->log_def.lcsp3,
+				       d40c->dma_cfg.dst_info.data_width,
+				       d40c->dma_cfg.src_info.data_width,
+				       true) == NULL)
+			goto err;
 
 	} else {
 
-		if (d40_pool_lli_alloc(d40d, 1, false) < 0) {
+		if (d40_pool_lli_alloc(d40d, d40d->lli_len, false) < 0) {
 			dev_err(&d40c->chan.dev->device,
 				"[%s] Out of memory\n", __func__);
 			goto err;
 		}
 
-		err = d40_phy_fill_lli(d40d->lli_phy.src,
+		if (d40_phy_buf_to_lli(d40d->lli_phy.src,
 				       src,
 				       size,
 				       d40c->dma_cfg.src_info.psize,
@@ -1889,11 +1986,11 @@ static struct dma_async_tx_descriptor *d
 				       d40c->src_def_cfg,
 				       true,
 				       d40c->dma_cfg.src_info.data_width,
-				       false);
-		if (err)
-			goto err_fill_lli;
+				       d40c->dma_cfg.dst_info.data_width,
+				       false) == NULL)
+			goto err;
 
-		err = d40_phy_fill_lli(d40d->lli_phy.dst,
+		if (d40_phy_buf_to_lli(d40d->lli_phy.dst,
 				       dst,
 				       size,
 				       d40c->dma_cfg.dst_info.psize,
@@ -1901,10 +1998,9 @@ static struct dma_async_tx_descriptor *d
 				       d40c->dst_def_cfg,
 				       true,
 				       d40c->dma_cfg.dst_info.data_width,
-				       false);
-
-		if (err)
-			goto err_fill_lli;
+				       d40c->dma_cfg.src_info.data_width,
+				       false) == NULL)
+			goto err;
 
 		(void) dma_map_single(d40c->base->dev, d40d->lli_phy.src,
 				      d40d->lli_pool.size, DMA_TO_DEVICE);
@@ -1913,9 +2009,6 @@ static struct dma_async_tx_descriptor *d
 	spin_unlock_irqrestore(&d40c->lock, flags);
 	return &d40d->txd;
 
-err_fill_lli:
-	dev_err(&d40c->chan.dev->device,
-		"[%s] Failed filling in PHY LLI\n", __func__);
 err:
 	if (d40d)
 		d40_desc_free(d40c, d40d);
@@ -1945,13 +2038,21 @@ static int d40_prep_slave_sg_log(struct
 	dma_addr_t dev_addr = 0;
 	int total_size;
 
-	if (d40_pool_lli_alloc(d40d, sg_len, true) < 0) {
+	d40d->lli_len = d40_sg_2_dmalen(sgl, sg_len,
+					d40c->dma_cfg.src_info.data_width,
+					d40c->dma_cfg.dst_info.data_width);
+	if (d40d->lli_len < 0) {
+		dev_err(&d40c->chan.dev->device,
+			"[%s] Unaligned size\n", __func__);
+		return -EINVAL;
+	}
+
+	if (d40_pool_lli_alloc(d40d, d40d->lli_len, true) < 0) {
 		dev_err(&d40c->chan.dev->device,
 			"[%s] Out of memory\n", __func__);
 		return -ENOMEM;
 	}
 
-	d40d->lli_len = sg_len;
 	d40d->lli_current = 0;
 
 	if (direction == DMA_FROM_DEVICE)
@@ -1993,13 +2094,21 @@ static int d40_prep_slave_sg_phy(struct
 	dma_addr_t dst_dev_addr;
 	int res;
 
-	if (d40_pool_lli_alloc(d40d, sgl_len, false) < 0) {
+	d40d->lli_len = d40_sg_2_dmalen(sgl, sgl_len,
+					d40c->dma_cfg.src_info.data_width,
+					d40c->dma_cfg.dst_info.data_width);
+	if (d40d->lli_len < 0) {
+		dev_err(&d40c->chan.dev->device,
+			"[%s] Unaligned size\n", __func__);
+		return -EINVAL;
+	}
+
+	if (d40_pool_lli_alloc(d40d, d40d->lli_len, false) < 0) {
 		dev_err(&d40c->chan.dev->device,
 			"[%s] Out of memory\n", __func__);
 		return -ENOMEM;
 	}
 
-	d40d->lli_len = sgl_len;
 	d40d->lli_current = 0;
 
 	if (direction == DMA_FROM_DEVICE) {
@@ -2024,6 +2133,7 @@ static int d40_prep_slave_sg_phy(struct
 				virt_to_phys(d40d->lli_phy.src),
 				d40c->src_def_cfg,
 				d40c->dma_cfg.src_info.data_width,
+				d40c->dma_cfg.dst_info.data_width,
 				d40c->dma_cfg.src_info.psize);
 	if (res < 0)
 		return res;
@@ -2035,6 +2145,7 @@ static int d40_prep_slave_sg_phy(struct
 				virt_to_phys(d40d->lli_phy.dst),
 				d40c->dst_def_cfg,
 				d40c->dma_cfg.dst_info.data_width,
+				d40c->dma_cfg.src_info.data_width,
 				d40c->dma_cfg.dst_info.psize);
 	if (res < 0)
 		return res;
@@ -2244,6 +2355,8 @@ static void d40_set_runtime_config(struc
 			psize = STEDMA40_PSIZE_PHY_8;
 		else if (config_maxburst >= 4)
 			psize = STEDMA40_PSIZE_PHY_4;
+		else if (config_maxburst >= 2)
+			psize = STEDMA40_PSIZE_PHY_2;
 		else
 			psize = STEDMA40_PSIZE_PHY_1;
 	}
diff -druNp linux-libre-2.6.37-gnu1/drivers/dma/ste_dma40_ll.c linux-libre-2.6.38-gnu1/drivers/dma/ste_dma40_ll.c
--- linux-libre-2.6.37-gnu1/drivers/dma/ste_dma40_ll.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/dma/ste_dma40_ll.c	2011-03-14 21:20:32.000000000 -0400
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) ST-Ericsson SA 2007-2010
- * Author: Per Friden <per.friden@stericsson.com> for ST-Ericsson
+ * Author: Per Forlin <per.forlin@stericsson.com> for ST-Ericsson
  * Author: Jonas Aaberg <jonas.aberg@stericsson.com> for ST-Ericsson
  * License terms: GNU General Public License (GPL) version 2
  */
@@ -122,15 +122,15 @@ void d40_phy_cfg(struct stedma40_chan_cf
 	*dst_cfg = dst;
 }
 
-int d40_phy_fill_lli(struct d40_phy_lli *lli,
-		     dma_addr_t data,
-		     u32 data_size,
-		     int psize,
-		     dma_addr_t next_lli,
-		     u32 reg_cfg,
-		     bool term_int,
-		     u32 data_width,
-		     bool is_device)
+static int d40_phy_fill_lli(struct d40_phy_lli *lli,
+			    dma_addr_t data,
+			    u32 data_size,
+			    int psize,
+			    dma_addr_t next_lli,
+			    u32 reg_cfg,
+			    bool term_int,
+			    u32 data_width,
+			    bool is_device)
 {
 	int num_elems;
 
@@ -139,13 +139,6 @@ int d40_phy_fill_lli(struct d40_phy_lli
 	else
 		num_elems = 2 << psize;
 
-	/*
-	 * Size is 16bit. data_width is 8, 16, 32 or 64 bit
-	 * Block large than 64 KiB must be split.
-	 */
-	if (data_size > (0xffff << data_width))
-		return -EINVAL;
-
 	/* Must be aligned */
 	if (!IS_ALIGNED(data, 0x1 << data_width))
 		return -EINVAL;
@@ -187,55 +180,118 @@ int d40_phy_fill_lli(struct d40_phy_lli
 	return 0;
 }
 
+static int d40_seg_size(int size, int data_width1, int data_width2)
+{
+	u32 max_w = max(data_width1, data_width2);
+	u32 min_w = min(data_width1, data_width2);
+	u32 seg_max = ALIGN(STEDMA40_MAX_SEG_SIZE << min_w, 1 << max_w);
+
+	if (seg_max > STEDMA40_MAX_SEG_SIZE)
+		seg_max -= (1 << max_w);
+
+	if (size <= seg_max)
+		return size;
+
+	if (size <= 2 * seg_max)
+		return ALIGN(size / 2, 1 << max_w);
+
+	return seg_max;
+}
+
+struct d40_phy_lli *d40_phy_buf_to_lli(struct d40_phy_lli *lli,
+				       dma_addr_t addr,
+				       u32 size,
+				       int psize,
+				       dma_addr_t lli_phys,
+				       u32 reg_cfg,
+				       bool term_int,
+				       u32 data_width1,
+				       u32 data_width2,
+				       bool is_device)
+{
+	int err;
+	dma_addr_t next = lli_phys;
+	int size_rest = size;
+	int size_seg = 0;
+
+	do {
+		size_seg = d40_seg_size(size_rest, data_width1, data_width2);
+		size_rest -= size_seg;
+
+		if (term_int && size_rest == 0)
+			next = 0;
+		else
+			next = ALIGN(next + sizeof(struct d40_phy_lli),
+				     D40_LLI_ALIGN);
+
+		err = d40_phy_fill_lli(lli,
+				       addr,
+				       size_seg,
+				       psize,
+				       next,
+				       reg_cfg,
+				       !next,
+				       data_width1,
+				       is_device);
+
+		if (err)
+			goto err;
+
+		lli++;
+		if (!is_device)
+			addr += size_seg;
+	} while (size_rest);
+
+	return lli;
+
+ err:
+	return NULL;
+}
+
 int d40_phy_sg_to_lli(struct scatterlist *sg,
 		      int sg_len,
 		      dma_addr_t target,
-		      struct d40_phy_lli *lli,
+		      struct d40_phy_lli *lli_sg,
 		      dma_addr_t lli_phys,
 		      u32 reg_cfg,
-		      u32 data_width,
+		      u32 data_width1,
+		      u32 data_width2,
 		      int psize)
 {
 	int total_size = 0;
 	int i;
 	struct scatterlist *current_sg = sg;
-	dma_addr_t next_lli_phys;
 	dma_addr_t dst;
-	int err = 0;
+	struct d40_phy_lli *lli = lli_sg;
+	dma_addr_t l_phys = lli_phys;
 
 	for_each_sg(sg, current_sg, sg_len, i) {
 
 		total_size += sg_dma_len(current_sg);
 
-		/* If this scatter list entry is the last one, no next link */
-		if (sg_len - 1 == i)
-			next_lli_phys = 0;
-		else
-			next_lli_phys = ALIGN(lli_phys + (i + 1) *
-					      sizeof(struct d40_phy_lli),
-					      D40_LLI_ALIGN);
-
 		if (target)
 			dst = target;
 		else
 			dst = sg_phys(current_sg);
 
-		err = d40_phy_fill_lli(&lli[i],
-				       dst,
-				       sg_dma_len(current_sg),
-				       psize,
-				       next_lli_phys,
-				       reg_cfg,
-				       !next_lli_phys,
-				       data_width,
-				       target == dst);
-		if (err)
-			goto err;
+		l_phys = ALIGN(lli_phys + (lli - lli_sg) *
+			       sizeof(struct d40_phy_lli), D40_LLI_ALIGN);
+
+		lli = d40_phy_buf_to_lli(lli,
+					 dst,
+					 sg_dma_len(current_sg),
+					 psize,
+					 l_phys,
+					 reg_cfg,
+					 sg_len - 1 == i,
+					 data_width1,
+					 data_width2,
+					 target == dst);
+		if (lli == NULL)
+			return -EINVAL;
 	}
 
 	return total_size;
-err:
-	return err;
 }
 
 
@@ -315,17 +371,20 @@ void d40_log_lli_lcla_write(struct d40_l
 	writel(lli_dst->lcsp13, &lcla[1].lcsp13);
 }
 
-void d40_log_fill_lli(struct d40_log_lli *lli,
-		      dma_addr_t data, u32 data_size,
-		      u32 reg_cfg,
-		      u32 data_width,
-		      bool addr_inc)
+static void d40_log_fill_lli(struct d40_log_lli *lli,
+			     dma_addr_t data, u32 data_size,
+			     u32 reg_cfg,
+			     u32 data_width,
+			     bool addr_inc)
 {
 	lli->lcsp13 = reg_cfg;
 
 	/* The number of elements to transfer */
 	lli->lcsp02 = ((data_size >> data_width) <<
 		       D40_MEM_LCSP0_ECNT_POS) & D40_MEM_LCSP0_ECNT_MASK;
+
+	BUG_ON((data_size >> data_width) > STEDMA40_MAX_SEG_SIZE);
+
 	/* 16 LSBs address of the current element */
 	lli->lcsp02 |= data & D40_MEM_LCSP0_SPTR_MASK;
 	/* 16 MSBs address of the current element */
@@ -348,55 +407,94 @@ int d40_log_sg_to_dev(struct scatterlist
 	int total_size = 0;
 	struct scatterlist *current_sg = sg;
 	int i;
+	struct d40_log_lli *lli_src = lli->src;
+	struct d40_log_lli *lli_dst = lli->dst;
 
 	for_each_sg(sg, current_sg, sg_len, i) {
 		total_size += sg_dma_len(current_sg);
 
 		if (direction == DMA_TO_DEVICE) {
-			d40_log_fill_lli(&lli->src[i],
-					 sg_phys(current_sg),
-					 sg_dma_len(current_sg),
-					 lcsp->lcsp1, src_data_width,
-					 true);
-			d40_log_fill_lli(&lli->dst[i],
-					 dev_addr,
-					 sg_dma_len(current_sg),
-					 lcsp->lcsp3, dst_data_width,
-					 false);
+			lli_src =
+				d40_log_buf_to_lli(lli_src,
+						   sg_phys(current_sg),
+						   sg_dma_len(current_sg),
+						   lcsp->lcsp1, src_data_width,
+						   dst_data_width,
+						   true);
+			lli_dst =
+				d40_log_buf_to_lli(lli_dst,
+						   dev_addr,
+						   sg_dma_len(current_sg),
+						   lcsp->lcsp3, dst_data_width,
+						   src_data_width,
+						   false);
 		} else {
-			d40_log_fill_lli(&lli->dst[i],
-					 sg_phys(current_sg),
-					 sg_dma_len(current_sg),
-					 lcsp->lcsp3, dst_data_width,
-					 true);
-			d40_log_fill_lli(&lli->src[i],
-					 dev_addr,
-					 sg_dma_len(current_sg),
-					 lcsp->lcsp1, src_data_width,
-					 false);
+			lli_dst =
+				d40_log_buf_to_lli(lli_dst,
+						   sg_phys(current_sg),
+						   sg_dma_len(current_sg),
+						   lcsp->lcsp3, dst_data_width,
+						   src_data_width,
+						   true);
+			lli_src =
+				d40_log_buf_to_lli(lli_src,
+						   dev_addr,
+						   sg_dma_len(current_sg),
+						   lcsp->lcsp1, src_data_width,
+						   dst_data_width,
+						   false);
 		}
 	}
 	return total_size;
 }
 
+struct d40_log_lli *d40_log_buf_to_lli(struct d40_log_lli *lli_sg,
+				       dma_addr_t addr,
+				       int size,
+				       u32 lcsp13, /* src or dst*/
+				       u32 data_width1,
+				       u32 data_width2,
+				       bool addr_inc)
+{
+	struct d40_log_lli *lli = lli_sg;
+	int size_rest = size;
+	int size_seg = 0;
+
+	do {
+		size_seg = d40_seg_size(size_rest, data_width1, data_width2);
+		size_rest -= size_seg;
+
+		d40_log_fill_lli(lli,
+				 addr,
+				 size_seg,
+				 lcsp13, data_width1,
+				 addr_inc);
+		if (addr_inc)
+			addr += size_seg;
+		lli++;
+	} while (size_rest);
+
+	return lli;
+}
+
 int d40_log_sg_to_lli(struct scatterlist *sg,
 		      int sg_len,
 		      struct d40_log_lli *lli_sg,
 		      u32 lcsp13, /* src or dst*/
-		      u32 data_width)
+		      u32 data_width1, u32 data_width2)
 {
 	int total_size = 0;
 	struct scatterlist *current_sg = sg;
 	int i;
+	struct d40_log_lli *lli = lli_sg;
 
 	for_each_sg(sg, current_sg, sg_len, i) {
 		total_size += sg_dma_len(current_sg);
-
-		d40_log_fill_lli(&lli_sg[i],
-				 sg_phys(current_sg),
-				 sg_dma_len(current_sg),
-				 lcsp13, data_width,
-				 true);
+		lli = d40_log_buf_to_lli(lli,
+					 sg_phys(current_sg),
+					 sg_dma_len(current_sg),
+					 lcsp13,
+					 data_width1, data_width2, true);
 	}
 	return total_size;
 }
diff -druNp linux-libre-2.6.37-gnu1/drivers/dma/ste_dma40_ll.h linux-libre-2.6.38-gnu1/drivers/dma/ste_dma40_ll.h
--- linux-libre-2.6.37-gnu1/drivers/dma/ste_dma40_ll.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/dma/ste_dma40_ll.h	2011-03-14 21:20:32.000000000 -0400
@@ -292,18 +292,20 @@ int d40_phy_sg_to_lli(struct scatterlist
 		      struct d40_phy_lli *lli,
 		      dma_addr_t lli_phys,
 		      u32 reg_cfg,
-		      u32 data_width,
+		      u32 data_width1,
+		      u32 data_width2,
 		      int psize);
 
-int d40_phy_fill_lli(struct d40_phy_lli *lli,
-		     dma_addr_t data,
-		     u32 data_size,
-		     int psize,
-		     dma_addr_t next_lli,
-		     u32 reg_cfg,
-		     bool term_int,
-		     u32 data_width,
-		     bool is_device);
+struct d40_phy_lli *d40_phy_buf_to_lli(struct d40_phy_lli *lli,
+				       dma_addr_t data,
+				       u32 data_size,
+				       int psize,
+				       dma_addr_t next_lli,
+				       u32 reg_cfg,
+				       bool term_int,
+				       u32 data_width1,
+				       u32 data_width2,
+				       bool is_device);
 
 void d40_phy_lli_write(void __iomem *virtbase,
 		       u32 phy_chan_num,
@@ -312,12 +314,12 @@ void d40_phy_lli_write(void __iomem *vir
 
 /* Logical channels */
 
-void d40_log_fill_lli(struct d40_log_lli *lli,
-		      dma_addr_t data,
-		      u32 data_size,
-		      u32 reg_cfg,
-		      u32 data_width,
-		      bool addr_inc);
+struct d40_log_lli *d40_log_buf_to_lli(struct d40_log_lli *lli_sg,
+				       dma_addr_t addr,
+				       int size,
+				       u32 lcsp13, /* src or dst*/
+				       u32 data_width1, u32 data_width2,
+				       bool addr_inc);
 
 int d40_log_sg_to_dev(struct scatterlist *sg,
 		      int sg_len,
@@ -332,7 +334,7 @@ int d40_log_sg_to_lli(struct scatterlist
 		      int sg_len,
 		      struct d40_log_lli *lli_sg,
 		      u32 lcsp13, /* src or dst*/
-		      u32 data_width);
+		      u32 data_width1, u32 data_width2);
 
 void d40_log_lli_lcpa_write(struct d40_log_lli_full *lcpa,
 			    struct d40_log_lli *lli_dst,
diff -druNp linux-libre-2.6.37-gnu1/drivers/edac/amd64_edac.c linux-libre-2.6.38-gnu1/drivers/edac/amd64_edac.c
--- linux-libre-2.6.37-gnu1/drivers/edac/amd64_edac.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/edac/amd64_edac.c	2011-03-14 21:20:32.000000000 -0400
@@ -15,10 +15,14 @@ module_param(ecc_enable_override, int, 0
 
 static struct msr __percpu *msrs;
 
-/* Lookup table for all possible MC control instances */
-struct amd64_pvt;
-static struct mem_ctl_info *mci_lookup[EDAC_MAX_NUMNODES];
-static struct amd64_pvt *pvt_lookup[EDAC_MAX_NUMNODES];
+/*
+ * count successfully initialized driver instances for setup_pci_device()
+ */
+static atomic_t drv_instances = ATOMIC_INIT(0);
+
+/* Per-node driver instances */
+static struct mem_ctl_info **mcis;
+static struct ecc_settings **ecc_stngs;
 
 /*
  * Address to DRAM bank mapping: see F2x80 for K8 and F2x[1,0]80 for Fam10 and
@@ -62,7 +66,7 @@ static int ddr3_dbam[] = { [0]		= -1,
 			   [5 ... 6]	= 1024,
 			   [7 ... 8]	= 2048,
 			   [9 ... 10]	= 4096,
-			   [11]	= 8192,
+			   [11]		= 8192,
 };
 
 /*
@@ -73,7 +77,11 @@ static int ddr3_dbam[] = { [0]		= -1,
  *FIXME: Produce a better mapping/linearisation.
  */
 
-struct scrubrate scrubrates[] = {
+
+struct scrubrate {
+       u32 scrubval;           /* bit pattern for scrub rate */
+       u32 bandwidth;          /* bandwidth consumed (bytes/sec) */
+} scrubrates[] = {
 	{ 0x01, 1600000000UL},
 	{ 0x02, 800000000UL},
 	{ 0x03, 400000000UL},
@@ -117,8 +125,7 @@ struct scrubrate scrubrates[] = {
  * scan the scrub rate mapping table for a close or matching bandwidth value to
  * issue. If requested is too big, then use last maximum value found.
  */
-static int amd64_search_set_scrub_rate(struct pci_dev *ctl, u32 new_bw,
-				       u32 min_scrubrate)
+static int __amd64_set_scrub_rate(struct pci_dev *ctl, u32 new_bw, u32 min_rate)
 {
 	u32 scrubval;
 	int i;
@@ -134,7 +141,7 @@ static int amd64_search_set_scrub_rate(s
 		 * skip scrub rates which aren't recommended
 		 * (see F10 BKDG, F3x58)
 		 */
-		if (scrubrates[i].scrubval < min_scrubrate)
+		if (scrubrates[i].scrubval < min_rate)
 			continue;
 
 		if (scrubrates[i].bandwidth <= new_bw)
@@ -148,64 +155,41 @@ static int amd64_search_set_scrub_rate(s
 	}
 
 	scrubval = scrubrates[i].scrubval;
-	if (scrubval)
-		edac_printk(KERN_DEBUG, EDAC_MC,
-			    "Setting scrub rate bandwidth: %u\n",
-			    scrubrates[i].bandwidth);
-	else
-		edac_printk(KERN_DEBUG, EDAC_MC, "Turning scrubbing off.\n");
 
 	pci_write_bits32(ctl, K8_SCRCTRL, scrubval, 0x001F);
 
+	if (scrubval)
+		return scrubrates[i].bandwidth;
+
 	return 0;
 }
 
-static int amd64_set_scrub_rate(struct mem_ctl_info *mci, u32 bandwidth)
+static int amd64_set_scrub_rate(struct mem_ctl_info *mci, u32 bw)
 {
 	struct amd64_pvt *pvt = mci->pvt_info;
-	u32 min_scrubrate = 0x0;
 
-	switch (boot_cpu_data.x86) {
-	case 0xf:
-		min_scrubrate = K8_MIN_SCRUB_RATE_BITS;
-		break;
-	case 0x10:
-		min_scrubrate = F10_MIN_SCRUB_RATE_BITS;
-		break;
-	case 0x11:
-		min_scrubrate = F11_MIN_SCRUB_RATE_BITS;
-		break;
-
-	default:
-		amd64_printk(KERN_ERR, "Unsupported family!\n");
-		return -EINVAL;
-	}
-	return amd64_search_set_scrub_rate(pvt->misc_f3_ctl, bandwidth,
-					   min_scrubrate);
+	return __amd64_set_scrub_rate(pvt->F3, bw, pvt->min_scrubrate);
 }
 
-static int amd64_get_scrub_rate(struct mem_ctl_info *mci, u32 *bw)
+static int amd64_get_scrub_rate(struct mem_ctl_info *mci)
 {
 	struct amd64_pvt *pvt = mci->pvt_info;
 	u32 scrubval = 0;
-	int status = -1, i;
+	int i, retval = -EINVAL;
 
-	amd64_read_pci_cfg(pvt->misc_f3_ctl, K8_SCRCTRL, &scrubval);
+	amd64_read_pci_cfg(pvt->F3, K8_SCRCTRL, &scrubval);
 
 	scrubval = scrubval & 0x001F;
 
-	edac_printk(KERN_DEBUG, EDAC_MC,
-		    "pci-read, sdram scrub control value: %d \n", scrubval);
+	amd64_debug("pci-read, sdram scrub control value: %d\n", scrubval);
 
 	for (i = 0; i < ARRAY_SIZE(scrubrates); i++) {
 		if (scrubrates[i].scrubval == scrubval) {
-			*bw = scrubrates[i].bandwidth;
-			status = 0;
+			retval = scrubrates[i].bandwidth;
 			break;
 		}
 	}
-
-	return status;
+	return retval;
 }
 
 /* Map from a CSROW entry to the mask entry that operates on it */
@@ -314,9 +298,7 @@ static struct mem_ctl_info *find_mc_by_s
 	if (unlikely((intlv_en != 0x01) &&
 		     (intlv_en != 0x03) &&
 		     (intlv_en != 0x07))) {
-		amd64_printk(KERN_WARNING, "junk value of 0x%x extracted from "
-			     "IntlvEn field of DRAM Base Register for node 0: "
-			     "this probably indicates a BIOS bug.\n", intlv_en);
+		amd64_warn("DRAM Base[IntlvEn] junk value: 0x%x, BIOS bug?\n", intlv_en);
 		return NULL;
 	}
 
@@ -332,11 +314,9 @@ static struct mem_ctl_info *find_mc_by_s
 
 	/* sanity test for sys_addr */
 	if (unlikely(!amd64_base_limit_match(pvt, sys_addr, node_id))) {
-		amd64_printk(KERN_WARNING,
-			     "%s(): sys_addr 0x%llx falls outside base/limit "
-			     "address range for node %d with node interleaving "
-			     "enabled.\n",
-			     __func__, sys_addr, node_id);
+		amd64_warn("%s: sys_addr 0x%llx falls outside base/limit address"
+			   "range for node %d with node interleaving enabled.\n",
+			   __func__, sys_addr, node_id);
 		return NULL;
 	}
 
@@ -788,9 +768,8 @@ static int sys_addr_to_csrow(struct mem_
 	csrow = input_addr_to_csrow(mci, sys_addr_to_input_addr(mci, sys_addr));
 
 	if (csrow == -1)
-		amd64_mc_printk(mci, KERN_ERR,
-			     "Failed to translate InputAddr to csrow for "
-			     "address 0x%lx\n", (unsigned long)sys_addr);
+		amd64_mc_err(mci, "Failed to translate InputAddr to csrow for "
+				  "address 0x%lx\n", (unsigned long)sys_addr);
 	return csrow;
 }
 
@@ -801,21 +780,6 @@ static u16 extract_syndrome(struct err_r
 	return ((err->nbsh >> 15) & 0xff) | ((err->nbsl >> 16) & 0xff00);
 }
 
-static void amd64_cpu_display_info(struct amd64_pvt *pvt)
-{
-	if (boot_cpu_data.x86 == 0x11)
-		edac_printk(KERN_DEBUG, EDAC_MC, "F11h CPU detected\n");
-	else if (boot_cpu_data.x86 == 0x10)
-		edac_printk(KERN_DEBUG, EDAC_MC, "F10h CPU detected\n");
-	else if (boot_cpu_data.x86 == 0xf)
-		edac_printk(KERN_DEBUG, EDAC_MC, "%s detected\n",
-			(pvt->ext_model >= K8_REV_F) ?
-			"Rev F or later" : "Rev E or earlier");
-	else
-		/* we'll hardly ever ever get here */
-		edac_printk(KERN_ERR, EDAC_MC, "Unknown cpu!\n");
-}
-
 /*
  * Determine if the DIMMs have ECC enabled. ECC is enabled ONLY if all the DIMMs
  * are ECC capable.
@@ -862,8 +826,6 @@ static void amd64_dump_dramcfg_low(u32 d
 /* Display and decode various NB registers for debug purposes. */
 static void amd64_dump_misc_regs(struct amd64_pvt *pvt)
 {
-	int ganged;
-
 	debugf1("F3xE8 (NB Cap): 0x%08x\n", pvt->nbcap);
 
 	debugf1("  NB two channel DRAM capable: %s\n",
@@ -887,38 +849,28 @@ static void amd64_dump_misc_regs(struct
 	debugf1("  DramHoleValid: %s\n",
 		(pvt->dhar & DHAR_VALID) ? "yes" : "no");
 
+	amd64_debug_display_dimm_sizes(0, pvt);
+
 	/* everything below this point is Fam10h and above */
-	if (boot_cpu_data.x86 == 0xf) {
-		amd64_debug_display_dimm_sizes(0, pvt);
+	if (boot_cpu_data.x86 == 0xf)
 		return;
-	}
 
-	amd64_printk(KERN_INFO, "using %s syndromes.\n",
-		     ((pvt->syn_type == 8) ? "x8" : "x4"));
+	amd64_debug_display_dimm_sizes(1, pvt);
+
+	amd64_info("using %s syndromes.\n", ((pvt->syn_type == 8) ? "x8" : "x4"));
 
 	/* Only if NOT ganged does dclr1 have valid info */
 	if (!dct_ganging_enabled(pvt))
 		amd64_dump_dramcfg_low(pvt->dclr1, 1);
-
-	/*
-	 * Determine if ganged and then dump memory sizes for first controller,
-	 * and if NOT ganged dump info for 2nd controller.
-	 */
-	ganged = dct_ganging_enabled(pvt);
-
-	amd64_debug_display_dimm_sizes(0, pvt);
-
-	if (!ganged)
-		amd64_debug_display_dimm_sizes(1, pvt);
 }
 
 /* Read in both of DBAM registers */
 static void amd64_read_dbam_reg(struct amd64_pvt *pvt)
 {
-	amd64_read_pci_cfg(pvt->dram_f2_ctl, DBAM0, &pvt->dbam0);
+	amd64_read_pci_cfg(pvt->F2, DBAM0, &pvt->dbam0);
 
 	if (boot_cpu_data.x86 >= 0x10)
-		amd64_read_pci_cfg(pvt->dram_f2_ctl, DBAM1, &pvt->dbam1);
+		amd64_read_pci_cfg(pvt->F2, DBAM1, &pvt->dbam1);
 }
 
 /*
@@ -965,14 +917,8 @@ static void amd64_set_dct_base_and_mask(
 		pvt->dcsm_mask		= REV_F_F1Xh_DCSM_MASK_BITS;
 		pvt->dcs_mask_notused	= REV_F_F1Xh_DCS_NOTUSED_BITS;
 		pvt->dcs_shift		= REV_F_F1Xh_DCS_SHIFT;
-
-		if (boot_cpu_data.x86 == 0x11) {
-			pvt->cs_count = 4;
-			pvt->num_dcsm = 2;
-		} else {
-			pvt->cs_count = 8;
-			pvt->num_dcsm = 4;
-		}
+		pvt->cs_count		= 8;
+		pvt->num_dcsm		= 4;
 	}
 }
 
@@ -987,14 +933,14 @@ static void amd64_read_dct_base_mask(str
 
 	for (cs = 0; cs < pvt->cs_count; cs++) {
 		reg = K8_DCSB0 + (cs * 4);
-		if (!amd64_read_pci_cfg(pvt->dram_f2_ctl, reg, &pvt->dcsb0[cs]))
+		if (!amd64_read_pci_cfg(pvt->F2, reg, &pvt->dcsb0[cs]))
 			debugf0("  DCSB0[%d]=0x%08x reg: F2x%x\n",
 				cs, pvt->dcsb0[cs], reg);
 
 		/* If DCT are NOT ganged, then read in DCT1's base */
 		if (boot_cpu_data.x86 >= 0x10 && !dct_ganging_enabled(pvt)) {
 			reg = F10_DCSB1 + (cs * 4);
-			if (!amd64_read_pci_cfg(pvt->dram_f2_ctl, reg,
+			if (!amd64_read_pci_cfg(pvt->F2, reg,
 						&pvt->dcsb1[cs]))
 				debugf0("  DCSB1[%d]=0x%08x reg: F2x%x\n",
 					cs, pvt->dcsb1[cs], reg);
@@ -1005,14 +951,14 @@ static void amd64_read_dct_base_mask(str
 
 	for (cs = 0; cs < pvt->num_dcsm; cs++) {
 		reg = K8_DCSM0 + (cs * 4);
-		if (!amd64_read_pci_cfg(pvt->dram_f2_ctl, reg, &pvt->dcsm0[cs]))
+		if (!amd64_read_pci_cfg(pvt->F2, reg, &pvt->dcsm0[cs]))
 			debugf0("    DCSM0[%d]=0x%08x reg: F2x%x\n",
 				cs, pvt->dcsm0[cs], reg);
 
 		/* If DCT are NOT ganged, then read in DCT1's mask */
 		if (boot_cpu_data.x86 >= 0x10 && !dct_ganging_enabled(pvt)) {
 			reg = F10_DCSM1 + (cs * 4);
-			if (!amd64_read_pci_cfg(pvt->dram_f2_ctl, reg,
+			if (!amd64_read_pci_cfg(pvt->F2, reg,
 						&pvt->dcsm1[cs]))
 				debugf0("    DCSM1[%d]=0x%08x reg: F2x%x\n",
 					cs, pvt->dcsm1[cs], reg);
@@ -1022,7 +968,7 @@ static void amd64_read_dct_base_mask(str
 	}
 }
 
-static enum mem_type amd64_determine_memory_type(struct amd64_pvt *pvt)
+static enum mem_type amd64_determine_memory_type(struct amd64_pvt *pvt, int cs)
 {
 	enum mem_type type;
 
@@ -1035,7 +981,7 @@ static enum mem_type amd64_determine_mem
 		type = (pvt->dclr0 & BIT(18)) ? MEM_DDR : MEM_RDDR;
 	}
 
-	debugf1("  Memory type is: %s\n", edac_mem_types[type]);
+	amd64_info("CS%d: %s\n", cs, edac_mem_types[type]);
 
 	return type;
 }
@@ -1053,17 +999,16 @@ static int k8_early_channel_count(struct
 {
 	int flag, err = 0;
 
-	err = amd64_read_pci_cfg(pvt->dram_f2_ctl, F10_DCLR_0, &pvt->dclr0);
+	err = amd64_read_pci_cfg(pvt->F2, F10_DCLR_0, &pvt->dclr0);
 	if (err)
 		return err;
 
-	if ((boot_cpu_data.x86_model >> 4) >= K8_REV_F) {
+	if (pvt->ext_model >= K8_REV_F)
 		/* RevF (NPT) and later */
 		flag = pvt->dclr0 & F10_WIDTH_128;
-	} else {
+	else
 		/* RevE and earlier */
 		flag = pvt->dclr0 & REVE_WIDTH_128;
-	}
 
 	/* not used */
 	pvt->dclr1 = 0;
@@ -1090,14 +1035,14 @@ static void k8_read_dram_base_limit(stru
 	u32 low;
 	u32 off = dram << 3;	/* 8 bytes between DRAM entries */
 
-	amd64_read_pci_cfg(pvt->addr_f1_ctl, K8_DRAM_BASE_LOW + off, &low);
+	amd64_read_pci_cfg(pvt->F1, K8_DRAM_BASE_LOW + off, &low);
 
 	/* Extract parts into separate data entries */
 	pvt->dram_base[dram] = ((u64) low & 0xFFFF0000) << 8;
 	pvt->dram_IntlvEn[dram] = (low >> 8) & 0x7;
 	pvt->dram_rw_en[dram] = (low & 0x3);
 
-	amd64_read_pci_cfg(pvt->addr_f1_ctl, K8_DRAM_LIMIT_LOW + off, &low);
+	amd64_read_pci_cfg(pvt->F1, K8_DRAM_LIMIT_LOW + off, &low);
 
 	/*
 	 * Extract parts into separate data entries. Limit is the HIGHEST memory
@@ -1127,9 +1072,8 @@ static void k8_map_sysaddr_to_csrow(stru
 			 * 2 DIMMs is in error. So we need to ID 'both' of them
 			 * as suspect.
 			 */
-			amd64_mc_printk(mci, KERN_WARNING,
-					"unknown syndrome 0x%04x - possible "
-					"error reporting race\n", syndrome);
+			amd64_mc_warn(mci, "unknown syndrome 0x%04x - possible "
+					   "error reporting race\n", syndrome);
 			edac_mc_handle_ce_no_info(mci, EDAC_MOD_STR);
 			return;
 		}
@@ -1151,8 +1095,7 @@ static void k8_map_sysaddr_to_csrow(stru
 	 */
 	src_mci = find_mc_by_sys_addr(mci, sys_addr);
 	if (!src_mci) {
-		amd64_mc_printk(mci, KERN_ERR,
-			     "failed to map error address 0x%lx to a node\n",
+		amd64_mc_err(mci, "failed to map error addr 0x%lx to a node\n",
 			     (unsigned long)sys_addr);
 		edac_mc_handle_ce_no_info(mci, EDAC_MOD_STR);
 		return;
@@ -1220,7 +1163,7 @@ static int f10_early_channel_count(struc
 	 * both controllers since DIMMs can be placed in either one.
 	 */
 	for (i = 0; i < ARRAY_SIZE(dbams); i++) {
-		if (amd64_read_pci_cfg(pvt->dram_f2_ctl, dbams[i], &dbam))
+		if (amd64_read_pci_cfg(pvt->F2, dbams[i], &dbam))
 			goto err_reg;
 
 		for (j = 0; j < 4; j++) {
@@ -1234,7 +1177,7 @@ static int f10_early_channel_count(struc
 	if (channels > 2)
 		channels = 2;
 
-	debugf0("MCT channel count: %d\n", channels);
+	amd64_info("MCT channel count: %d\n", channels);
 
 	return channels;
 
@@ -1255,31 +1198,6 @@ static int f10_dbam_to_chip_select(struc
 	return dbam_map[cs_mode];
 }
 
-/* Enable extended configuration access via 0xCF8 feature */
-static void amd64_setup(struct amd64_pvt *pvt)
-{
-	u32 reg;
-
-	amd64_read_pci_cfg(pvt->misc_f3_ctl, F10_NB_CFG_HIGH, &reg);
-
-	pvt->flags.cf8_extcfg = !!(reg & F10_NB_CFG_LOW_ENABLE_EXT_CFG);
-	reg |= F10_NB_CFG_LOW_ENABLE_EXT_CFG;
-	pci_write_config_dword(pvt->misc_f3_ctl, F10_NB_CFG_HIGH, reg);
-}
-
-/* Restore the extended configuration access via 0xCF8 feature */
-static void amd64_teardown(struct amd64_pvt *pvt)
-{
-	u32 reg;
-
-	amd64_read_pci_cfg(pvt->misc_f3_ctl, F10_NB_CFG_HIGH, &reg);
-
-	reg &= ~F10_NB_CFG_LOW_ENABLE_EXT_CFG;
-	if (pvt->flags.cf8_extcfg)
-		reg |= F10_NB_CFG_LOW_ENABLE_EXT_CFG;
-	pci_write_config_dword(pvt->misc_f3_ctl, F10_NB_CFG_HIGH, reg);
-}
-
 static u64 f10_get_error_address(struct mem_ctl_info *mci,
 			struct err_regs *info)
 {
@@ -1301,10 +1219,8 @@ static void f10_read_dram_base_limit(str
 	high_offset = F10_DRAM_BASE_HIGH + (dram << 3);
 
 	/* read the 'raw' DRAM BASE Address register */
-	amd64_read_pci_cfg(pvt->addr_f1_ctl, low_offset, &low_base);
-
-	/* Read from the ECS data register */
-	amd64_read_pci_cfg(pvt->addr_f1_ctl, high_offset, &high_base);
+	amd64_read_pci_cfg(pvt->F1, low_offset, &low_base);
+	amd64_read_pci_cfg(pvt->F1, high_offset, &high_base);
 
 	/* Extract parts into separate data entries */
 	pvt->dram_rw_en[dram] = (low_base & 0x3);
@@ -1321,10 +1237,8 @@ static void f10_read_dram_base_limit(str
 	high_offset = F10_DRAM_LIMIT_HIGH + (dram << 3);
 
 	/* read the 'raw' LIMIT registers */
-	amd64_read_pci_cfg(pvt->addr_f1_ctl, low_offset, &low_limit);
-
-	/* Read from the ECS data register for the HIGH portion */
-	amd64_read_pci_cfg(pvt->addr_f1_ctl, high_offset, &high_limit);
+	amd64_read_pci_cfg(pvt->F1, low_offset, &low_limit);
+	amd64_read_pci_cfg(pvt->F1, high_offset, &high_limit);
 
 	pvt->dram_DstNode[dram] = (low_limit & 0x7);
 	pvt->dram_IntlvSel[dram] = (low_limit >> 8) & 0x7;
@@ -1341,7 +1255,7 @@ static void f10_read_dram_base_limit(str
 static void f10_read_dram_ctl_register(struct amd64_pvt *pvt)
 {
 
-	if (!amd64_read_pci_cfg(pvt->dram_f2_ctl, F10_DCTL_SEL_LOW,
+	if (!amd64_read_pci_cfg(pvt->F2, F10_DCTL_SEL_LOW,
 				&pvt->dram_ctl_select_low)) {
 		debugf0("F2x110 (DCTL Sel. Low): 0x%08x, "
 			"High range addresses at: 0x%x\n",
@@ -1367,7 +1281,7 @@ static void f10_read_dram_ctl_register(s
 			dct_sel_interleave_addr(pvt));
 	}
 
-	amd64_read_pci_cfg(pvt->dram_f2_ctl, F10_DCTL_SEL_HIGH,
+	amd64_read_pci_cfg(pvt->F2, F10_DCTL_SEL_HIGH,
 			   &pvt->dram_ctl_select_high);
 }
 
@@ -1496,7 +1410,7 @@ static int f10_lookup_addr_in_dct(u32 in
 	int cs_found = -EINVAL;
 	int csrow;
 
-	mci = mci_lookup[nid];
+	mci = mcis[nid];
 	if (!mci)
 		return cs_found;
 
@@ -1719,11 +1633,10 @@ static void amd64_debug_display_dimm_siz
 		       WARN_ON(ctrl != 0);
 	}
 
-	debugf1("F2x%d80 (DRAM Bank Address Mapping): 0x%08x\n",
-		ctrl, ctrl ? pvt->dbam1 : pvt->dbam0);
+	dbam = (ctrl && !dct_ganging_enabled(pvt)) ? pvt->dbam1 : pvt->dbam0;
+	dcsb = (ctrl && !dct_ganging_enabled(pvt)) ? pvt->dcsb1 : pvt->dcsb0;
 
-	dbam = ctrl ? pvt->dbam1 : pvt->dbam0;
-	dcsb = ctrl ? pvt->dcsb1 : pvt->dcsb0;
+	debugf1("F2x%d80 (DRAM Bank Address Mapping): 0x%08x\n", ctrl, dbam);
 
 	edac_printk(KERN_DEBUG, EDAC_MC, "DCT%d chip selects:\n", ctrl);
 
@@ -1738,28 +1651,17 @@ static void amd64_debug_display_dimm_siz
 		if (dcsb[dimm*2 + 1] & K8_DCSB_CS_ENABLE)
 			size1 = pvt->ops->dbam_to_cs(pvt, DBAM_DIMM(dimm, dbam));
 
-		edac_printk(KERN_DEBUG, EDAC_MC, " %d: %5dMB %d: %5dMB\n",
-			    dimm * 2,     size0 << factor,
-			    dimm * 2 + 1, size1 << factor);
+		amd64_info(EDAC_MC ": %d: %5dMB %d: %5dMB\n",
+				dimm * 2,     size0 << factor,
+				dimm * 2 + 1, size1 << factor);
 	}
 }
 
-/*
- * There currently are 3 types type of MC devices for AMD Athlon/Opterons
- * (as per PCI DEVICE_IDs):
- *
- * Family K8: That is the Athlon64 and Opteron CPUs. They all have the same PCI
- * DEVICE ID, even though there is differences between the different Revisions
- * (CG,D,E,F).
- *
- * Family F10h and F11h.
- *
- */
 static struct amd64_family_type amd64_family_types[] = {
 	[K8_CPUS] = {
-		.ctl_name = "RevF",
-		.addr_f1_ctl = PCI_DEVICE_ID_AMD_K8_NB_ADDRMAP,
-		.misc_f3_ctl = PCI_DEVICE_ID_AMD_K8_NB_MISC,
+		.ctl_name = "K8",
+		.f1_id = PCI_DEVICE_ID_AMD_K8_NB_ADDRMAP,
+		.f3_id = PCI_DEVICE_ID_AMD_K8_NB_MISC,
 		.ops = {
 			.early_channel_count	= k8_early_channel_count,
 			.get_error_address	= k8_get_error_address,
@@ -1769,22 +1671,9 @@ static struct amd64_family_type amd64_fa
 		}
 	},
 	[F10_CPUS] = {
-		.ctl_name = "Family 10h",
-		.addr_f1_ctl = PCI_DEVICE_ID_AMD_10H_NB_MAP,
-		.misc_f3_ctl = PCI_DEVICE_ID_AMD_10H_NB_MISC,
-		.ops = {
-			.early_channel_count	= f10_early_channel_count,
-			.get_error_address	= f10_get_error_address,
-			.read_dram_base_limit	= f10_read_dram_base_limit,
-			.read_dram_ctl_register	= f10_read_dram_ctl_register,
-			.map_sysaddr_to_csrow	= f10_map_sysaddr_to_csrow,
-			.dbam_to_cs		= f10_dbam_to_chip_select,
-		}
-	},
-	[F11_CPUS] = {
-		.ctl_name = "Family 11h",
-		.addr_f1_ctl = PCI_DEVICE_ID_AMD_11H_NB_MAP,
-		.misc_f3_ctl = PCI_DEVICE_ID_AMD_11H_NB_MISC,
+		.ctl_name = "F10h",
+		.f1_id = PCI_DEVICE_ID_AMD_10H_NB_MAP,
+		.f3_id = PCI_DEVICE_ID_AMD_10H_NB_MISC,
 		.ops = {
 			.early_channel_count	= f10_early_channel_count,
 			.get_error_address	= f10_get_error_address,
@@ -1970,8 +1859,7 @@ static int get_channel_from_ecc_syndrome
 					  ARRAY_SIZE(x4_vectors),
 					  pvt->syn_type);
 	else {
-		amd64_printk(KERN_WARNING, "%s: Illegal syndrome type: %u\n",
-					   __func__, pvt->syn_type);
+		amd64_warn("Illegal syndrome type: %u\n", pvt->syn_type);
 		return err_sym;
 	}
 
@@ -1989,17 +1877,15 @@ static void amd64_handle_ce(struct mem_c
 	u64 sys_addr;
 
 	/* Ensure that the Error Address is VALID */
-	if ((info->nbsh & K8_NBSH_VALID_ERROR_ADDR) == 0) {
-		amd64_mc_printk(mci, KERN_ERR,
-			"HW has no ERROR_ADDRESS available\n");
+	if (!(info->nbsh & K8_NBSH_VALID_ERROR_ADDR)) {
+		amd64_mc_err(mci, "HW has no ERROR_ADDRESS available\n");
 		edac_mc_handle_ce_no_info(mci, EDAC_MOD_STR);
 		return;
 	}
 
 	sys_addr = pvt->ops->get_error_address(mci, info);
 
-	amd64_mc_printk(mci, KERN_ERR,
-		"CE ERROR_ADDRESS= 0x%llx\n", sys_addr);
+	amd64_mc_err(mci, "CE ERROR_ADDRESS= 0x%llx\n", sys_addr);
 
 	pvt->ops->map_sysaddr_to_csrow(mci, info, sys_addr);
 }
@@ -2016,9 +1902,8 @@ static void amd64_handle_ue(struct mem_c
 
 	log_mci = mci;
 
-	if ((info->nbsh & K8_NBSH_VALID_ERROR_ADDR) == 0) {
-		amd64_mc_printk(mci, KERN_CRIT,
-			"HW has no ERROR_ADDRESS available\n");
+	if (!(info->nbsh & K8_NBSH_VALID_ERROR_ADDR)) {
+		amd64_mc_err(mci, "HW has no ERROR_ADDRESS available\n");
 		edac_mc_handle_ue_no_info(log_mci, EDAC_MOD_STR);
 		return;
 	}
@@ -2031,9 +1916,8 @@ static void amd64_handle_ue(struct mem_c
 	 */
 	src_mci = find_mc_by_sys_addr(mci, sys_addr);
 	if (!src_mci) {
-		amd64_mc_printk(mci, KERN_CRIT,
-			"ERROR ADDRESS (0x%lx) value NOT mapped to a MC\n",
-			(unsigned long)sys_addr);
+		amd64_mc_err(mci, "ERROR ADDRESS (0x%lx) NOT mapped to a MC\n",
+				  (unsigned long)sys_addr);
 		edac_mc_handle_ue_no_info(log_mci, EDAC_MOD_STR);
 		return;
 	}
@@ -2042,9 +1926,8 @@ static void amd64_handle_ue(struct mem_c
 
 	csrow = sys_addr_to_csrow(log_mci, sys_addr);
 	if (csrow < 0) {
-		amd64_mc_printk(mci, KERN_CRIT,
-			"ERROR_ADDRESS (0x%lx) value NOT mapped to 'csrow'\n",
-			(unsigned long)sys_addr);
+		amd64_mc_err(mci, "ERROR_ADDRESS (0x%lx) NOT mapped to CS\n",
+				  (unsigned long)sys_addr);
 		edac_mc_handle_ue_no_info(log_mci, EDAC_MOD_STR);
 	} else {
 		error_address_to_page_and_offset(sys_addr, &page, &offset);
@@ -2055,8 +1938,8 @@ static void amd64_handle_ue(struct mem_c
 static inline void __amd64_decode_bus_error(struct mem_ctl_info *mci,
 					    struct err_regs *info)
 {
-	u32 ec  = ERROR_CODE(info->nbsl);
-	u32 xec = EXT_ERROR_CODE(info->nbsl);
+	u16 ec = EC(info->nbsl);
+	u8 xec = XEC(info->nbsl, 0x1f);
 	int ecc_type = (info->nbsh >> 13) & 0x3;
 
 	/* Bail early out if this was an 'observed' error */
@@ -2075,7 +1958,7 @@ static inline void __amd64_decode_bus_er
 
 void amd64_decode_bus_error(int node_id, struct mce *m, u32 nbcfg)
 {
-	struct mem_ctl_info *mci = mci_lookup[node_id];
+	struct mem_ctl_info *mci = mcis[node_id];
 	struct err_regs regs;
 
 	regs.nbsl  = (u32) m->status;
@@ -2099,75 +1982,50 @@ void amd64_decode_bus_error(int node_id,
 }
 
 /*
- * Input:
- *	1) struct amd64_pvt which contains pvt->dram_f2_ctl pointer
- *	2) AMD Family index value
- *
- * Ouput:
- *	Upon return of 0, the following filled in:
- *
- *		struct pvt->addr_f1_ctl
- *		struct pvt->misc_f3_ctl
- *
- *	Filled in with related device funcitions of 'dram_f2_ctl'
- *	These devices are "reserved" via the pci_get_device()
- *
- *	Upon return of 1 (error status):
- *
- *		Nothing reserved
+ * Use pvt->F2 which contains the F2 CPU PCI device to get the related
+ * F1 (AddrMap) and F3 (Misc) devices. Return negative value on error.
  */
-static int amd64_reserve_mc_sibling_devices(struct amd64_pvt *pvt, int mc_idx)
+static int reserve_mc_sibling_devs(struct amd64_pvt *pvt, u16 f1_id, u16 f3_id)
 {
-	const struct amd64_family_type *amd64_dev = &amd64_family_types[mc_idx];
-
 	/* Reserve the ADDRESS MAP Device */
-	pvt->addr_f1_ctl = pci_get_related_function(pvt->dram_f2_ctl->vendor,
-						    amd64_dev->addr_f1_ctl,
-						    pvt->dram_f2_ctl);
-
-	if (!pvt->addr_f1_ctl) {
-		amd64_printk(KERN_ERR, "error address map device not found: "
-			     "vendor %x device 0x%x (broken BIOS?)\n",
-			     PCI_VENDOR_ID_AMD, amd64_dev->addr_f1_ctl);
-		return 1;
+	pvt->F1 = pci_get_related_function(pvt->F2->vendor, f1_id, pvt->F2);
+	if (!pvt->F1) {
+		amd64_err("error address map device not found: "
+			  "vendor %x device 0x%x (broken BIOS?)\n",
+			  PCI_VENDOR_ID_AMD, f1_id);
+		return -ENODEV;
 	}
 
 	/* Reserve the MISC Device */
-	pvt->misc_f3_ctl = pci_get_related_function(pvt->dram_f2_ctl->vendor,
-						    amd64_dev->misc_f3_ctl,
-						    pvt->dram_f2_ctl);
+	pvt->F3 = pci_get_related_function(pvt->F2->vendor, f3_id, pvt->F2);
+	if (!pvt->F3) {
+		pci_dev_put(pvt->F1);
+		pvt->F1 = NULL;
 
-	if (!pvt->misc_f3_ctl) {
-		pci_dev_put(pvt->addr_f1_ctl);
-		pvt->addr_f1_ctl = NULL;
+		amd64_err("error F3 device not found: "
+			  "vendor %x device 0x%x (broken BIOS?)\n",
+			  PCI_VENDOR_ID_AMD, f3_id);
 
-		amd64_printk(KERN_ERR, "error miscellaneous device not found: "
-			     "vendor %x device 0x%x (broken BIOS?)\n",
-			     PCI_VENDOR_ID_AMD, amd64_dev->misc_f3_ctl);
-		return 1;
+		return -ENODEV;
 	}
-
-	debugf1("    Addr Map device PCI Bus ID:\t%s\n",
-		pci_name(pvt->addr_f1_ctl));
-	debugf1("    DRAM MEM-CTL PCI Bus ID:\t%s\n",
-		pci_name(pvt->dram_f2_ctl));
-	debugf1("    Misc device PCI Bus ID:\t%s\n",
-		pci_name(pvt->misc_f3_ctl));
+	debugf1("F1: %s\n", pci_name(pvt->F1));
+	debugf1("F2: %s\n", pci_name(pvt->F2));
+	debugf1("F3: %s\n", pci_name(pvt->F3));
 
 	return 0;
 }
 
-static void amd64_free_mc_sibling_devices(struct amd64_pvt *pvt)
+static void free_mc_sibling_devs(struct amd64_pvt *pvt)
 {
-	pci_dev_put(pvt->addr_f1_ctl);
-	pci_dev_put(pvt->misc_f3_ctl);
+	pci_dev_put(pvt->F1);
+	pci_dev_put(pvt->F3);
 }
 
 /*
  * Retrieve the hardware registers of the memory controller (this includes the
  * 'Address Map' and 'Misc' device regs)
  */
-static void amd64_read_mc_registers(struct amd64_pvt *pvt)
+static void read_mc_regs(struct amd64_pvt *pvt)
 {
 	u64 msr_val;
 	u32 tmp;
@@ -2188,9 +2046,7 @@ static void amd64_read_mc_registers(stru
 	} else
 		debugf0("  TOP_MEM2 disabled.\n");
 
-	amd64_cpu_display_info(pvt);
-
-	amd64_read_pci_cfg(pvt->misc_f3_ctl, K8_NBCAP, &pvt->nbcap);
+	amd64_read_pci_cfg(pvt->F3, K8_NBCAP, &pvt->nbcap);
 
 	if (pvt->ops->read_dram_ctl_register)
 		pvt->ops->read_dram_ctl_register(pvt);
@@ -2227,21 +2083,20 @@ static void amd64_read_mc_registers(stru
 
 	amd64_read_dct_base_mask(pvt);
 
-	amd64_read_pci_cfg(pvt->addr_f1_ctl, K8_DHAR, &pvt->dhar);
+	amd64_read_pci_cfg(pvt->F1, K8_DHAR, &pvt->dhar);
 	amd64_read_dbam_reg(pvt);
 
-	amd64_read_pci_cfg(pvt->misc_f3_ctl,
-			   F10_ONLINE_SPARE, &pvt->online_spare);
+	amd64_read_pci_cfg(pvt->F3, F10_ONLINE_SPARE, &pvt->online_spare);
 
-	amd64_read_pci_cfg(pvt->dram_f2_ctl, F10_DCLR_0, &pvt->dclr0);
-	amd64_read_pci_cfg(pvt->dram_f2_ctl, F10_DCHR_0, &pvt->dchr0);
+	amd64_read_pci_cfg(pvt->F2, F10_DCLR_0, &pvt->dclr0);
+	amd64_read_pci_cfg(pvt->F2, F10_DCHR_0, &pvt->dchr0);
 
 	if (boot_cpu_data.x86 >= 0x10) {
 		if (!dct_ganging_enabled(pvt)) {
-			amd64_read_pci_cfg(pvt->dram_f2_ctl, F10_DCLR_1, &pvt->dclr1);
-			amd64_read_pci_cfg(pvt->dram_f2_ctl, F10_DCHR_1, &pvt->dchr1);
+			amd64_read_pci_cfg(pvt->F2, F10_DCLR_1, &pvt->dclr1);
+			amd64_read_pci_cfg(pvt->F2, F10_DCHR_1, &pvt->dchr1);
 		}
-		amd64_read_pci_cfg(pvt->misc_f3_ctl, EXT_NB_MCA_CFG, &tmp);
+		amd64_read_pci_cfg(pvt->F3, EXT_NB_MCA_CFG, &tmp);
 	}
 
 	if (boot_cpu_data.x86 == 0x10 &&
@@ -2321,21 +2176,22 @@ static u32 amd64_csrow_nr_pages(int csro
  * Initialize the array of csrow attribute instances, based on the values
  * from pci config hardware registers.
  */
-static int amd64_init_csrows(struct mem_ctl_info *mci)
+static int init_csrows(struct mem_ctl_info *mci)
 {
 	struct csrow_info *csrow;
-	struct amd64_pvt *pvt;
+	struct amd64_pvt *pvt = mci->pvt_info;
 	u64 input_addr_min, input_addr_max, sys_addr;
+	u32 val;
 	int i, empty = 1;
 
-	pvt = mci->pvt_info;
+	amd64_read_pci_cfg(pvt->F3, K8_NBCFG, &val);
 
-	amd64_read_pci_cfg(pvt->misc_f3_ctl, K8_NBCFG, &pvt->nbcfg);
+	pvt->nbcfg = val;
+	pvt->ctl_error_info.nbcfg = val;
 
-	debugf0("NBCFG= 0x%x  CHIPKILL= %s DRAM ECC= %s\n", pvt->nbcfg,
-		(pvt->nbcfg & K8_NBCFG_CHIPKILL) ? "Enabled" : "Disabled",
-		(pvt->nbcfg & K8_NBCFG_ECC_ENABLE) ? "Enabled" : "Disabled"
-		);
+	debugf0("node %d, NBCFG=0x%08x[ChipKillEccCap: %d|DramEccEn: %d]\n",
+		pvt->mc_node_id, val,
+		!!(val & K8_NBCFG_CHIPKILL), !!(val & K8_NBCFG_ECC_ENABLE));
 
 	for (i = 0; i < pvt->cs_count; i++) {
 		csrow = &mci->csrows[i];
@@ -2359,7 +2215,7 @@ static int amd64_init_csrows(struct mem_
 		csrow->page_mask = ~mask_from_dct_mask(pvt, i);
 		/* 8 bytes of resolution */
 
-		csrow->mtype = amd64_determine_memory_type(pvt);
+		csrow->mtype = amd64_determine_memory_type(pvt, i);
 
 		debugf1("  for MC node %d csrow %d:\n", pvt->mc_node_id, i);
 		debugf1("    input_addr_min: 0x%lx input_addr_max: 0x%lx\n",
@@ -2404,8 +2260,7 @@ static bool amd64_nb_mce_bank_enabled_on
 	bool ret = false;
 
 	if (!zalloc_cpumask_var(&mask, GFP_KERNEL)) {
-		amd64_printk(KERN_WARNING, "%s: error allocating mask\n",
-			     __func__);
+		amd64_warn("%s: Error allocating mask\n", __func__);
 		return false;
 	}
 
@@ -2431,18 +2286,17 @@ out:
 	return ret;
 }
 
-static int amd64_toggle_ecc_err_reporting(struct amd64_pvt *pvt, bool on)
+static int toggle_ecc_err_reporting(struct ecc_settings *s, u8 nid, bool on)
 {
 	cpumask_var_t cmask;
 	int cpu;
 
 	if (!zalloc_cpumask_var(&cmask, GFP_KERNEL)) {
-		amd64_printk(KERN_WARNING, "%s: error allocating mask\n",
-			     __func__);
+		amd64_warn("%s: error allocating mask\n", __func__);
 		return false;
 	}
 
-	get_cpus_on_this_dct_cpumask(cmask, pvt->mc_node_id);
+	get_cpus_on_this_dct_cpumask(cmask, nid);
 
 	rdmsr_on_cpus(cmask, MSR_IA32_MCG_CTL, msrs);
 
@@ -2452,14 +2306,14 @@ static int amd64_toggle_ecc_err_reportin
 
 		if (on) {
 			if (reg->l & K8_MSR_MCGCTL_NBE)
-				pvt->flags.nb_mce_enable = 1;
+				s->flags.nb_mce_enable = 1;
 
 			reg->l |= K8_MSR_MCGCTL_NBE;
 		} else {
 			/*
 			 * Turn off NB MCE reporting only when it was off before
 			 */
-			if (!pvt->flags.nb_mce_enable)
+			if (!s->flags.nb_mce_enable)
 				reg->l &= ~K8_MSR_MCGCTL_NBE;
 		}
 	}
@@ -2470,92 +2324,92 @@ static int amd64_toggle_ecc_err_reportin
 	return 0;
 }
 
-static void amd64_enable_ecc_error_reporting(struct mem_ctl_info *mci)
+static bool enable_ecc_error_reporting(struct ecc_settings *s, u8 nid,
+				       struct pci_dev *F3)
 {
-	struct amd64_pvt *pvt = mci->pvt_info;
+	bool ret = true;
 	u32 value, mask = K8_NBCTL_CECCEn | K8_NBCTL_UECCEn;
 
-	amd64_read_pci_cfg(pvt->misc_f3_ctl, K8_NBCTL, &value);
+	if (toggle_ecc_err_reporting(s, nid, ON)) {
+		amd64_warn("Error enabling ECC reporting over MCGCTL!\n");
+		return false;
+	}
 
-	/* turn on UECCn and CECCEn bits */
-	pvt->old_nbctl = value & mask;
-	pvt->nbctl_mcgctl_saved = 1;
+	amd64_read_pci_cfg(F3, K8_NBCTL, &value);
 
-	value |= mask;
-	pci_write_config_dword(pvt->misc_f3_ctl, K8_NBCTL, value);
+	/* turn on UECCEn and CECCEn bits */
+	s->old_nbctl   = value & mask;
+	s->nbctl_valid = true;
 
-	if (amd64_toggle_ecc_err_reporting(pvt, ON))
-		amd64_printk(KERN_WARNING, "Error enabling ECC reporting over "
-					   "MCGCTL!\n");
+	value |= mask;
+	pci_write_config_dword(F3, K8_NBCTL, value);
 
-	amd64_read_pci_cfg(pvt->misc_f3_ctl, K8_NBCFG, &value);
+	amd64_read_pci_cfg(F3, K8_NBCFG, &value);
 
-	debugf0("NBCFG(1)= 0x%x  CHIPKILL= %s ECC_ENABLE= %s\n", value,
-		(value & K8_NBCFG_CHIPKILL) ? "Enabled" : "Disabled",
-		(value & K8_NBCFG_ECC_ENABLE) ? "Enabled" : "Disabled");
+	debugf0("1: node %d, NBCFG=0x%08x[ChipKillEccCap: %d|DramEccEn: %d]\n",
+		nid, value,
+		!!(value & K8_NBCFG_CHIPKILL), !!(value & K8_NBCFG_ECC_ENABLE));
 
 	if (!(value & K8_NBCFG_ECC_ENABLE)) {
-		amd64_printk(KERN_WARNING,
-			"This node reports that DRAM ECC is "
-			"currently Disabled; ENABLING now\n");
+		amd64_warn("DRAM ECC disabled on this node, enabling...\n");
 
-		pvt->flags.nb_ecc_prev = 0;
+		s->flags.nb_ecc_prev = 0;
 
 		/* Attempt to turn on DRAM ECC Enable */
 		value |= K8_NBCFG_ECC_ENABLE;
-		pci_write_config_dword(pvt->misc_f3_ctl, K8_NBCFG, value);
+		pci_write_config_dword(F3, K8_NBCFG, value);
 
-		amd64_read_pci_cfg(pvt->misc_f3_ctl, K8_NBCFG, &value);
+		amd64_read_pci_cfg(F3, K8_NBCFG, &value);
 
 		if (!(value & K8_NBCFG_ECC_ENABLE)) {
-			amd64_printk(KERN_WARNING,
-				"Hardware rejects Enabling DRAM ECC checking\n"
-				"Check memory DIMM configuration\n");
+			amd64_warn("Hardware rejected DRAM ECC enable,"
+				   "check memory DIMM configuration.\n");
+			ret = false;
 		} else {
-			amd64_printk(KERN_DEBUG,
-				"Hardware accepted DRAM ECC Enable\n");
+			amd64_info("Hardware accepted DRAM ECC Enable\n");
 		}
 	} else {
-		pvt->flags.nb_ecc_prev = 1;
+		s->flags.nb_ecc_prev = 1;
 	}
 
-	debugf0("NBCFG(2)= 0x%x  CHIPKILL= %s ECC_ENABLE= %s\n", value,
-		(value & K8_NBCFG_CHIPKILL) ? "Enabled" : "Disabled",
-		(value & K8_NBCFG_ECC_ENABLE) ? "Enabled" : "Disabled");
+	debugf0("2: node %d, NBCFG=0x%08x[ChipKillEccCap: %d|DramEccEn: %d]\n",
+		nid, value,
+		!!(value & K8_NBCFG_CHIPKILL), !!(value & K8_NBCFG_ECC_ENABLE));
 
-	pvt->ctl_error_info.nbcfg = value;
+	return ret;
 }
 
-static void amd64_restore_ecc_error_reporting(struct amd64_pvt *pvt)
+static void restore_ecc_error_reporting(struct ecc_settings *s, u8 nid,
+					struct pci_dev *F3)
 {
 	u32 value, mask = K8_NBCTL_CECCEn | K8_NBCTL_UECCEn;
 
-	if (!pvt->nbctl_mcgctl_saved)
+	if (!s->nbctl_valid)
 		return;
 
-	amd64_read_pci_cfg(pvt->misc_f3_ctl, K8_NBCTL, &value);
+	amd64_read_pci_cfg(F3, K8_NBCTL, &value);
 	value &= ~mask;
-	value |= pvt->old_nbctl;
+	value |= s->old_nbctl;
 
-	pci_write_config_dword(pvt->misc_f3_ctl, K8_NBCTL, value);
+	pci_write_config_dword(F3, K8_NBCTL, value);
 
-	/* restore previous BIOS DRAM ECC "off" setting which we force-enabled */
-	if (!pvt->flags.nb_ecc_prev) {
-		amd64_read_pci_cfg(pvt->misc_f3_ctl, K8_NBCFG, &value);
+	/* restore previous BIOS DRAM ECC "off" setting we force-enabled */
+	if (!s->flags.nb_ecc_prev) {
+		amd64_read_pci_cfg(F3, K8_NBCFG, &value);
 		value &= ~K8_NBCFG_ECC_ENABLE;
-		pci_write_config_dword(pvt->misc_f3_ctl, K8_NBCFG, value);
+		pci_write_config_dword(F3, K8_NBCFG, value);
 	}
 
 	/* restore the NB Enable MCGCTL bit */
-	if (amd64_toggle_ecc_err_reporting(pvt, OFF))
-		amd64_printk(KERN_WARNING, "Error restoring NB MCGCTL settings!\n");
+	if (toggle_ecc_err_reporting(s, nid, OFF))
+		amd64_warn("Error restoring NB MCGCTL settings!\n");
 }
 
 /*
- * EDAC requires that the BIOS have ECC enabled before taking over the
- * processing of ECC errors. This is because the BIOS can properly initialize
- * the memory system completely. A command line option allows to force-enable
- * hardware ECC later in amd64_enable_ecc_error_reporting().
+ * EDAC requires that the BIOS have ECC enabled before
+ * taking over the processing of ECC errors. A command line
+ * option allows to force-enable hardware ECC later in
+ * enable_ecc_error_reporting().
  */
 static const char *ecc_msg =
 	"ECC disabled in the BIOS or no ECC capability, module will not load.\n"
@@ -2563,38 +2417,28 @@ static const char *ecc_msg =
 	"'ecc_enable_override'.\n"
 	" (Note that use of the override may cause unknown side effects.)\n";
 
-static int amd64_check_ecc_enabled(struct amd64_pvt *pvt)
+static bool ecc_enabled(struct pci_dev *F3, u8 nid)
 {
 	u32 value;
-	u8 ecc_enabled = 0;
+	u8 ecc_en = 0;
 	bool nb_mce_en = false;
 
-	amd64_read_pci_cfg(pvt->misc_f3_ctl, K8_NBCFG, &value);
+	amd64_read_pci_cfg(F3, K8_NBCFG, &value);
 
-	ecc_enabled = !!(value & K8_NBCFG_ECC_ENABLE);
-	if (!ecc_enabled)
-		amd64_printk(KERN_NOTICE, "This node reports that Memory ECC "
-			     "is currently disabled, set F3x%x[22] (%s).\n",
-			     K8_NBCFG, pci_name(pvt->misc_f3_ctl));
-	else
-		amd64_printk(KERN_INFO, "ECC is enabled by BIOS.\n");
+	ecc_en = !!(value & K8_NBCFG_ECC_ENABLE);
+	amd64_info("DRAM ECC %s.\n", (ecc_en ? "enabled" : "disabled"));
 
-	nb_mce_en = amd64_nb_mce_bank_enabled_on_node(pvt->mc_node_id);
+	nb_mce_en = amd64_nb_mce_bank_enabled_on_node(nid);
 	if (!nb_mce_en)
-		amd64_printk(KERN_NOTICE, "NB MCE bank disabled, set MSR "
+		amd64_notice("NB MCE bank disabled, set MSR "
 			     "0x%08x[4] on node %d to enable.\n",
-			     MSR_IA32_MCG_CTL, pvt->mc_node_id);
+			     MSR_IA32_MCG_CTL, nid);
 
-	if (!ecc_enabled || !nb_mce_en) {
-		if (!ecc_enable_override) {
-			amd64_printk(KERN_NOTICE, "%s", ecc_msg);
-			return -ENODEV;
-		} else {
-			amd64_printk(KERN_WARNING, "Forcing ECC checking on!\n");
-		}
+	if (!ecc_en || !nb_mce_en) {
+		amd64_notice("%s", ecc_msg);
+		return false;
 	}
-
-	return 0;
+	return true;
 }
 
 struct mcidev_sysfs_attribute sysfs_attrs[ARRAY_SIZE(amd64_dbg_attrs) +
@@ -2603,22 +2447,23 @@ struct mcidev_sysfs_attribute sysfs_attr
 
 struct mcidev_sysfs_attribute terminator = { .attr = { .name = NULL } };
 
-static void amd64_set_mc_sysfs_attributes(struct mem_ctl_info *mci)
+static void set_mc_sysfs_attrs(struct mem_ctl_info *mci)
 {
 	unsigned int i = 0, j = 0;
 
 	for (; i < ARRAY_SIZE(amd64_dbg_attrs); i++)
 		sysfs_attrs[i] = amd64_dbg_attrs[i];
 
-	for (j = 0; j < ARRAY_SIZE(amd64_inj_attrs); j++, i++)
-		sysfs_attrs[i] = amd64_inj_attrs[j];
+	if (boot_cpu_data.x86 >= 0x10)
+		for (j = 0; j < ARRAY_SIZE(amd64_inj_attrs); j++, i++)
+			sysfs_attrs[i] = amd64_inj_attrs[j];
 
 	sysfs_attrs[i] = terminator;
 
 	mci->mc_driver_sysfs_attributes = sysfs_attrs;
 }
 
-static void amd64_setup_mci_misc_attributes(struct mem_ctl_info *mci)
+static void setup_mci_misc_attrs(struct mem_ctl_info *mci)
 {
 	struct amd64_pvt *pvt = mci->pvt_info;
 
@@ -2634,8 +2479,8 @@ static void amd64_setup_mci_misc_attribu
 	mci->edac_cap		= amd64_determine_edac_cap(pvt);
 	mci->mod_name		= EDAC_MOD_STR;
 	mci->mod_ver		= EDAC_AMD64_VERSION;
-	mci->ctl_name		= get_amd_family_name(pvt->mc_type_index);
-	mci->dev_name		= pci_name(pvt->dram_f2_ctl);
+	mci->ctl_name		= pvt->ctl_name;
+	mci->dev_name		= pci_name(pvt->F2);
 	mci->ctl_page_to_phys	= NULL;
 
 	/* memory scrubber interface */
@@ -2644,111 +2489,94 @@ static void amd64_setup_mci_misc_attribu
 }
 
 /*
- * Init stuff for this DRAM Controller device.
- *
- * Due to a hardware feature on Fam10h CPUs, the Enable Extended Configuration
- * Space feature MUST be enabled on ALL Processors prior to actually reading
- * from the ECS registers. Since the loading of the module can occur on any
- * 'core', and cores don't 'see' all the other processors ECS data when the
- * others are NOT enabled. Our solution is to first enable ECS access in this
- * routine on all processors, gather some data in a amd64_pvt structure and
- * later come back in a finish-setup function to perform that final
- * initialization. See also amd64_init_2nd_stage() for that.
+ * returns a pointer to the family descriptor on success, NULL otherwise.
  */
-static int amd64_probe_one_instance(struct pci_dev *dram_f2_ctl,
-				    int mc_type_index)
+static struct amd64_family_type *amd64_per_family_init(struct amd64_pvt *pvt)
+{
+	u8 fam = boot_cpu_data.x86;
+	struct amd64_family_type *fam_type = NULL;
+
+	switch (fam) {
+	case 0xf:
+		fam_type		= &amd64_family_types[K8_CPUS];
+		pvt->ops		= &amd64_family_types[K8_CPUS].ops;
+		pvt->ctl_name		= fam_type->ctl_name;
+		pvt->min_scrubrate	= K8_MIN_SCRUB_RATE_BITS;
+		break;
+	case 0x10:
+		fam_type		= &amd64_family_types[F10_CPUS];
+		pvt->ops		= &amd64_family_types[F10_CPUS].ops;
+		pvt->ctl_name		= fam_type->ctl_name;
+		pvt->min_scrubrate	= F10_MIN_SCRUB_RATE_BITS;
+		break;
+
+	default:
+		amd64_err("Unsupported family!\n");
+		return NULL;
+	}
+
+	pvt->ext_model = boot_cpu_data.x86_model >> 4;
+
+	amd64_info("%s %sdetected (node %d).\n", pvt->ctl_name,
+		     (fam == 0xf ?
+				(pvt->ext_model >= K8_REV_F  ? "revF or later "
+							     : "revE or earlier ")
+				 : ""), pvt->mc_node_id);
+	return fam_type;
+}
+
+static int amd64_init_one_instance(struct pci_dev *F2)
 {
 	struct amd64_pvt *pvt = NULL;
+	struct amd64_family_type *fam_type = NULL;
+	struct mem_ctl_info *mci = NULL;
 	int err = 0, ret;
+	u8 nid = get_node_id(F2);
 
 	ret = -ENOMEM;
 	pvt = kzalloc(sizeof(struct amd64_pvt), GFP_KERNEL);
 	if (!pvt)
-		goto err_exit;
+		goto err_ret;
 
-	pvt->mc_node_id = get_node_id(dram_f2_ctl);
+	pvt->mc_node_id	= nid;
+	pvt->F2 = F2;
 
-	pvt->dram_f2_ctl	= dram_f2_ctl;
-	pvt->ext_model		= boot_cpu_data.x86_model >> 4;
-	pvt->mc_type_index	= mc_type_index;
-	pvt->ops		= family_ops(mc_type_index);
+	ret = -EINVAL;
+	fam_type = amd64_per_family_init(pvt);
+	if (!fam_type)
+		goto err_free;
 
-	/*
-	 * We have the dram_f2_ctl device as an argument, now go reserve its
-	 * sibling devices from the PCI system.
-	 */
 	ret = -ENODEV;
-	err = amd64_reserve_mc_sibling_devices(pvt, mc_type_index);
+	err = reserve_mc_sibling_devs(pvt, fam_type->f1_id, fam_type->f3_id);
 	if (err)
 		goto err_free;
 
-	ret = -EINVAL;
-	err = amd64_check_ecc_enabled(pvt);
-	if (err)
-		goto err_put;
-
-	/*
-	 * Key operation here: setup of HW prior to performing ops on it. Some
-	 * setup is required to access ECS data. After this is performed, the
-	 * 'teardown' function must be called upon error and normal exit paths.
-	 */
-	if (boot_cpu_data.x86 >= 0x10)
-		amd64_setup(pvt);
-
-	/*
-	 * Save the pointer to the private data for use in 2nd initialization
-	 * stage
-	 */
-	pvt_lookup[pvt->mc_node_id] = pvt;
-
-	return 0;
-
-err_put:
-	amd64_free_mc_sibling_devices(pvt);
-
-err_free:
-	kfree(pvt);
-
-err_exit:
-	return ret;
-}
-
-/*
- * This is the finishing stage of the init code. Needs to be performed after all
- * MCs' hardware have been prepped for accessing extended config space.
- */
-static int amd64_init_2nd_stage(struct amd64_pvt *pvt)
-{
-	int node_id = pvt->mc_node_id;
-	struct mem_ctl_info *mci;
-	int ret = -ENODEV;
-
-	amd64_read_mc_registers(pvt);
+	read_mc_regs(pvt);
 
 	/*
 	 * We need to determine how many memory channels there are. Then use
 	 * that information for calculating the size of the dynamic instance
-	 * tables in the 'mci' structure
+	 * tables in the 'mci' structure.
 	 */
+	ret = -EINVAL;
 	pvt->channel_count = pvt->ops->early_channel_count(pvt);
 	if (pvt->channel_count < 0)
-		goto err_exit;
+		goto err_siblings;
 
 	ret = -ENOMEM;
-	mci = edac_mc_alloc(0, pvt->cs_count, pvt->channel_count, node_id);
+	mci = edac_mc_alloc(0, pvt->cs_count, pvt->channel_count, nid);
 	if (!mci)
-		goto err_exit;
+		goto err_siblings;
 
 	mci->pvt_info = pvt;
+	mci->dev = &pvt->F2->dev;
 
-	mci->dev = &pvt->dram_f2_ctl->dev;
-	amd64_setup_mci_misc_attributes(mci);
+	setup_mci_misc_attrs(mci);
 
-	if (amd64_init_csrows(mci))
+	if (init_csrows(mci))
 		mci->edac_cap = EDAC_FLAG_NONE;
 
-	amd64_enable_ecc_error_reporting(mci);
-	amd64_set_mc_sysfs_attributes(mci);
+	set_mc_sysfs_attrs(mci);
 
 	ret = -ENODEV;
 	if (edac_mc_add_mc(mci)) {
@@ -2756,61 +2584,87 @@ static int amd64_init_2nd_stage(struct a
 		goto err_add_mc;
 	}
 
-	mci_lookup[node_id] = mci;
-	pvt_lookup[node_id] = NULL;
-
 	/* register stuff with EDAC MCE */
 	if (report_gart_errors)
 		amd_report_gart_errors(true);
 
 	amd_register_ecc_decoder(amd64_decode_bus_error);
 
+	mcis[nid] = mci;
+
+	atomic_inc(&drv_instances);
+
 	return 0;
 
 err_add_mc:
 	edac_mc_free(mci);
 
-err_exit:
-	debugf0("failure to init 2nd stage: ret=%d\n", ret);
-
-	amd64_restore_ecc_error_reporting(pvt);
-
-	if (boot_cpu_data.x86 > 0xf)
-		amd64_teardown(pvt);
-
-	amd64_free_mc_sibling_devices(pvt);
+err_siblings:
+	free_mc_sibling_devs(pvt);
 
-	kfree(pvt_lookup[pvt->mc_node_id]);
-	pvt_lookup[node_id] = NULL;
+err_free:
+	kfree(pvt);
 
+err_ret:
 	return ret;
 }
 
-
-static int __devinit amd64_init_one_instance(struct pci_dev *pdev,
-				 const struct pci_device_id *mc_type)
+static int __devinit amd64_probe_one_instance(struct pci_dev *pdev,
+					     const struct pci_device_id *mc_type)
 {
+	u8 nid = get_node_id(pdev);
+	struct pci_dev *F3 = node_to_amd_nb(nid)->misc;
+	struct ecc_settings *s;
 	int ret = 0;
 
-	debugf0("(MC node=%d,mc_type='%s')\n", get_node_id(pdev),
-		get_amd_family_name(mc_type->driver_data));
-
 	ret = pci_enable_device(pdev);
-	if (ret < 0)
-		ret = -EIO;
-	else
-		ret = amd64_probe_one_instance(pdev, mc_type->driver_data);
-
-	if (ret < 0)
+	if (ret < 0) {
 		debugf0("ret=%d\n", ret);
+		return -EIO;
+	}
+
+	ret = -ENOMEM;
+	s = kzalloc(sizeof(struct ecc_settings), GFP_KERNEL);
+	if (!s)
+		goto err_out;
+
+	ecc_stngs[nid] = s;
+
+	if (!ecc_enabled(F3, nid)) {
+		ret = -ENODEV;
+
+		if (!ecc_enable_override)
+			goto err_enable;
+
+		amd64_warn("Forcing ECC on!\n");
+
+		if (!enable_ecc_error_reporting(s, nid, F3))
+			goto err_enable;
+	}
+
+	ret = amd64_init_one_instance(pdev);
+	if (ret < 0) {
+		amd64_err("Error probing instance: %d\n", nid);
+		restore_ecc_error_reporting(s, nid, F3);
+	}
 
 	return ret;
+
+err_enable:
+	kfree(s);
+	ecc_stngs[nid] = NULL;
+
+err_out:
+	return ret;
 }
 
 static void __devexit amd64_remove_one_instance(struct pci_dev *pdev)
 {
 	struct mem_ctl_info *mci;
 	struct amd64_pvt *pvt;
+	u8 nid = get_node_id(pdev);
+	struct pci_dev *F3 = node_to_amd_nb(nid)->misc;
+	struct ecc_settings *s = ecc_stngs[nid];
 
 	/* Remove from EDAC CORE tracking list */
 	mci = edac_mc_del_mc(&pdev->dev);
@@ -2819,20 +2673,20 @@ static void __devexit amd64_remove_one_i
 
 	pvt = mci->pvt_info;
 
-	amd64_restore_ecc_error_reporting(pvt);
-
-	if (boot_cpu_data.x86 > 0xf)
-		amd64_teardown(pvt);
+	restore_ecc_error_reporting(s, nid, F3);
 
-	amd64_free_mc_sibling_devices(pvt);
+	free_mc_sibling_devs(pvt);
 
 	/* unregister from EDAC MCE */
 	amd_report_gart_errors(false);
 	amd_unregister_ecc_decoder(amd64_decode_bus_error);
 
+	kfree(ecc_stngs[nid]);
+	ecc_stngs[nid] = NULL;
+
 	/* Free the EDAC CORE resources */
 	mci->pvt_info = NULL;
-	mci_lookup[pvt->mc_node_id] = NULL;
+	mcis[nid] = NULL;
 
 	kfree(pvt);
 	edac_mc_free(mci);
@@ -2851,7 +2705,6 @@ static const struct pci_device_id amd64_
 		.subdevice	= PCI_ANY_ID,
 		.class		= 0,
 		.class_mask	= 0,
-		.driver_data	= K8_CPUS
 	},
 	{
 		.vendor		= PCI_VENDOR_ID_AMD,
@@ -2860,16 +2713,6 @@ static const struct pci_device_id amd64_
 		.subdevice	= PCI_ANY_ID,
 		.class		= 0,
 		.class_mask	= 0,
-		.driver_data	= F10_CPUS
-	},
-	{
-		.vendor		= PCI_VENDOR_ID_AMD,
-		.device		= PCI_DEVICE_ID_AMD_11H_NB_DRAM,
-		.subvendor	= PCI_ANY_ID,
-		.subdevice	= PCI_ANY_ID,
-		.class		= 0,
-		.class_mask	= 0,
-		.driver_data	= F11_CPUS
 	},
 	{0, }
 };
@@ -2877,12 +2720,12 @@ MODULE_DEVICE_TABLE(pci, amd64_pci_table
 
 static struct pci_driver amd64_pci_driver = {
 	.name		= EDAC_MOD_STR,
-	.probe		= amd64_init_one_instance,
+	.probe		= amd64_probe_one_instance,
 	.remove		= __devexit_p(amd64_remove_one_instance),
 	.id_table	= amd64_pci_table,
 };
 
-static void amd64_setup_pci_device(void)
+static void setup_pci_device(void)
 {
 	struct mem_ctl_info *mci;
 	struct amd64_pvt *pvt;
@@ -2890,13 +2733,12 @@ static void amd64_setup_pci_device(void)
 	if (amd64_ctl_pci)
 		return;
 
-	mci = mci_lookup[0];
+	mci = mcis[0];
 	if (mci) {
 
 		pvt = mci->pvt_info;
 		amd64_ctl_pci =
-			edac_pci_create_generic_ctl(&pvt->dram_f2_ctl->dev,
-						    EDAC_MOD_STR);
+			edac_pci_create_generic_ctl(&pvt->F2->dev, EDAC_MOD_STR);
 
 		if (!amd64_ctl_pci) {
 			pr_warning("%s(): Unable to create PCI control\n",
@@ -2910,51 +2752,50 @@ static void amd64_setup_pci_device(void)
 
 static int __init amd64_edac_init(void)
 {
-	int nb, err = -ENODEV;
-	bool load_ok = false;
+	int err = -ENODEV;
 
 	edac_printk(KERN_INFO, EDAC_MOD_STR, EDAC_AMD64_VERSION "\n");
 
 	opstate_init();
 
-	if (cache_k8_northbridges() < 0)
+	if (amd_cache_northbridges() < 0)
+		goto err_ret;
+
+	err = -ENOMEM;
+	mcis	  = kzalloc(amd_nb_num() * sizeof(mcis[0]), GFP_KERNEL);
+	ecc_stngs = kzalloc(amd_nb_num() * sizeof(ecc_stngs[0]), GFP_KERNEL);
+	if (!(mcis && ecc_stngs))
 		goto err_ret;
 
 	msrs = msrs_alloc();
 	if (!msrs)
-		goto err_ret;
+		goto err_free;
 
 	err = pci_register_driver(&amd64_pci_driver);
 	if (err)
 		goto err_pci;
 
-	/*
-	 * At this point, the array 'pvt_lookup[]' contains pointers to alloc'd
-	 * amd64_pvt structs. These will be used in the 2nd stage init function
-	 * to finish initialization of the MC instances.
-	 */
 	err = -ENODEV;
-	for (nb = 0; nb < k8_northbridges.num; nb++) {
-		if (!pvt_lookup[nb])
-			continue;
-
-		err = amd64_init_2nd_stage(pvt_lookup[nb]);
-		if (err)
-			goto err_2nd_stage;
-
-		load_ok = true;
-	}
+	if (!atomic_read(&drv_instances))
+		goto err_no_instances;
 
-	if (load_ok) {
-		amd64_setup_pci_device();
-		return 0;
-	}
+	setup_pci_device();
+	return 0;
 
-err_2nd_stage:
+err_no_instances:
 	pci_unregister_driver(&amd64_pci_driver);
+
 err_pci:
 	msrs_free(msrs);
 	msrs = NULL;
+
+err_free:
+	kfree(mcis);
+	mcis = NULL;
+
+	kfree(ecc_stngs);
+	ecc_stngs = NULL;
+
 err_ret:
 	return err;
 }
@@ -2966,6 +2807,12 @@ static void __exit amd64_edac_exit(void)
 
 	pci_unregister_driver(&amd64_pci_driver);
 
+	kfree(ecc_stngs);
+	ecc_stngs = NULL;
+
+	kfree(mcis);
+	mcis = NULL;
+
 	msrs_free(msrs);
 	msrs = NULL;
 }
diff -druNp linux-libre-2.6.37-gnu1/drivers/edac/amd64_edac.h linux-libre-2.6.38-gnu1/drivers/edac/amd64_edac.h
--- linux-libre-2.6.37-gnu1/drivers/edac/amd64_edac.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/edac/amd64_edac.h	2011-03-14 21:20:32.000000000 -0400
@@ -74,11 +74,26 @@
 #include "edac_core.h"
 #include "mce_amd.h"
 
-#define amd64_printk(level, fmt, arg...) \
-	edac_printk(level, "amd64", fmt, ##arg)
+#define amd64_debug(fmt, arg...) \
+	edac_printk(KERN_DEBUG, "amd64", fmt, ##arg)
 
-#define amd64_mc_printk(mci, level, fmt, arg...) \
-	edac_mc_chipset_printk(mci, level, "amd64", fmt, ##arg)
+#define amd64_info(fmt, arg...) \
+	edac_printk(KERN_INFO, "amd64", fmt, ##arg)
+
+#define amd64_notice(fmt, arg...) \
+	edac_printk(KERN_NOTICE, "amd64", fmt, ##arg)
+
+#define amd64_warn(fmt, arg...) \
+	edac_printk(KERN_WARNING, "amd64", fmt, ##arg)
+
+#define amd64_err(fmt, arg...) \
+	edac_printk(KERN_ERR, "amd64", fmt, ##arg)
+
+#define amd64_mc_warn(mci, fmt, arg...) \
+	edac_mc_chipset_printk(mci, KERN_WARNING, "amd64", fmt, ##arg)
+
+#define amd64_mc_err(mci, fmt, arg...) \
+	edac_mc_chipset_printk(mci, KERN_ERR, "amd64", fmt, ##arg)
 
 /*
  * Throughout the comments in this code, the following terms are used:
@@ -129,11 +144,9 @@
  *         sections 3.5.4 and 3.5.5 for more information.
  */
 
-#define EDAC_AMD64_VERSION		" Ver: 3.3.0 " __DATE__
+#define EDAC_AMD64_VERSION		"v3.3.0"
 #define EDAC_MOD_STR			"amd64_edac"
 
-#define EDAC_MAX_NUMNODES		8
-
 /* Extended Model from CPUID, for CPU Revision numbers */
 #define K8_REV_D			1
 #define K8_REV_E			2
@@ -322,9 +335,6 @@
 #define K8_SCRCTRL			0x58
 
 #define F10_NB_CFG_LOW			0x88
-#define	F10_NB_CFG_LOW_ENABLE_EXT_CFG	BIT(14)
-
-#define F10_NB_CFG_HIGH			0x8C
 
 #define F10_ONLINE_SPARE		0xB0
 #define F10_ONLINE_SPARE_SWAPDONE0(x)	((x) & BIT(1))
@@ -373,7 +383,6 @@ static inline int get_node_id(struct pci
 enum amd64_chipset_families {
 	K8_CPUS = 0,
 	F10_CPUS,
-	F11_CPUS,
 };
 
 /* Error injection control structure */
@@ -384,16 +393,13 @@ struct error_injection {
 };
 
 struct amd64_pvt {
+	struct low_ops *ops;
+
 	/* pci_device handles which we utilize */
-	struct pci_dev *addr_f1_ctl;
-	struct pci_dev *dram_f2_ctl;
-	struct pci_dev *misc_f3_ctl;
+	struct pci_dev *F1, *F2, *F3;
 
 	int mc_node_id;		/* MC index of this MC node */
 	int ext_model;		/* extended model value of this node */
-
-	struct low_ops *ops;	/* pointer to per PCI Device ID func table */
-
 	int channel_count;
 
 	/* Raw registers */
@@ -455,27 +461,27 @@ struct amd64_pvt {
 	/* place to store error injection parameters prior to issue */
 	struct error_injection injection;
 
-	/* Save old hw registers' values before we modified them */
-	u32 nbctl_mcgctl_saved;		/* When true, following 2 are valid */
-	u32 old_nbctl;
+	/* DCT per-family scrubrate setting */
+	u32 min_scrubrate;
 
-	/* MC Type Index value: socket F vs Family 10h */
-	u32 mc_type_index;
+	/* family name this instance is running on */
+	const char *ctl_name;
+
+};
+
+/*
+ * per-node ECC settings descriptor
+ */
+struct ecc_settings {
+	u32 old_nbctl;
+	bool nbctl_valid;
 
-	/* misc settings */
 	struct flags {
-		unsigned long cf8_extcfg:1;
 		unsigned long nb_mce_enable:1;
 		unsigned long nb_ecc_prev:1;
 	} flags;
 };
 
-struct scrubrate {
-       u32 scrubval;           /* bit pattern for scrub rate */
-       u32 bandwidth;          /* bandwidth consumed (bytes/sec) */
-};
-
-extern struct scrubrate scrubrates[23];
 extern const char *tt_msgs[4];
 extern const char *ll_msgs[4];
 extern const char *rrrr_msgs[16];
@@ -517,23 +523,10 @@ struct low_ops {
 
 struct amd64_family_type {
 	const char *ctl_name;
-	u16 addr_f1_ctl;
-	u16 misc_f3_ctl;
+	u16 f1_id, f3_id;
 	struct low_ops ops;
 };
 
-static struct amd64_family_type amd64_family_types[];
-
-static inline const char *get_amd_family_name(int index)
-{
-	return amd64_family_types[index].ctl_name;
-}
-
-static inline struct low_ops *family_ops(int index)
-{
-	return &amd64_family_types[index].ops;
-}
-
 static inline int amd64_read_pci_cfg_dword(struct pci_dev *pdev, int offset,
 					   u32 *val, const char *func)
 {
@@ -541,8 +534,8 @@ static inline int amd64_read_pci_cfg_dwo
 
 	err = pci_read_config_dword(pdev, offset, val);
 	if (err)
-		amd64_printk(KERN_WARNING, "%s: error reading F%dx%x.\n",
-			     func, PCI_FUNC(pdev->devfn), offset);
+		amd64_warn("%s: error reading F%dx%x.\n",
+			   func, PCI_FUNC(pdev->devfn), offset);
 
 	return err;
 }
@@ -556,7 +549,6 @@ static inline int amd64_read_pci_cfg_dwo
  */
 #define K8_MIN_SCRUB_RATE_BITS	0x0
 #define F10_MIN_SCRUB_RATE_BITS	0x5
-#define F11_MIN_SCRUB_RATE_BITS	0x6
 
 int amd64_get_dram_hole_info(struct mem_ctl_info *mci, u64 *hole_base,
 			     u64 *hole_offset, u64 *hole_size);
diff -druNp linux-libre-2.6.37-gnu1/drivers/edac/amd64_edac_inj.c linux-libre-2.6.38-gnu1/drivers/edac/amd64_edac_inj.c
--- linux-libre-2.6.37-gnu1/drivers/edac/amd64_edac_inj.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/edac/amd64_edac_inj.c	2011-03-14 21:20:32.000000000 -0400
@@ -23,9 +23,7 @@ static ssize_t amd64_inject_section_stor
 	if (ret != -EINVAL) {
 
 		if (value > 3) {
-			amd64_printk(KERN_WARNING,
-				     "%s: invalid section 0x%lx\n",
-				     __func__, value);
+			amd64_warn("%s: invalid section 0x%lx\n", __func__, value);
 			return -EINVAL;
 		}
 
@@ -58,9 +56,7 @@ static ssize_t amd64_inject_word_store(s
 	if (ret != -EINVAL) {
 
 		if (value > 8) {
-			amd64_printk(KERN_WARNING,
-				     "%s: invalid word 0x%lx\n",
-				     __func__, value);
+			amd64_warn("%s: invalid word 0x%lx\n", __func__, value);
 			return -EINVAL;
 		}
 
@@ -92,9 +88,8 @@ static ssize_t amd64_inject_ecc_vector_s
 	if (ret != -EINVAL) {
 
 		if (value & 0xFFFF0000) {
-			amd64_printk(KERN_WARNING,
-				     "%s: invalid EccVector: 0x%lx\n",
-				     __func__, value);
+			amd64_warn("%s: invalid EccVector: 0x%lx\n",
+				   __func__, value);
 			return -EINVAL;
 		}
 
@@ -122,15 +117,13 @@ static ssize_t amd64_inject_read_store(s
 		/* Form value to choose 16-byte section of cacheline */
 		section = F10_NB_ARRAY_DRAM_ECC |
 				SET_NB_ARRAY_ADDRESS(pvt->injection.section);
-		pci_write_config_dword(pvt->misc_f3_ctl,
-					F10_NB_ARRAY_ADDR, section);
+		pci_write_config_dword(pvt->F3, F10_NB_ARRAY_ADDR, section);
 
 		word_bits = SET_NB_DRAM_INJECTION_READ(pvt->injection.word,
 						pvt->injection.bit_map);
 
 		/* Issue 'word' and 'bit' along with the READ request */
-		pci_write_config_dword(pvt->misc_f3_ctl,
-					F10_NB_ARRAY_DATA, word_bits);
+		pci_write_config_dword(pvt->F3, F10_NB_ARRAY_DATA, word_bits);
 
 		debugf0("section=0x%x word_bits=0x%x\n", section, word_bits);
 
@@ -157,15 +150,13 @@ static ssize_t amd64_inject_write_store(
 		/* Form value to choose 16-byte section of cacheline */
 		section = F10_NB_ARRAY_DRAM_ECC |
 				SET_NB_ARRAY_ADDRESS(pvt->injection.section);
-		pci_write_config_dword(pvt->misc_f3_ctl,
-					F10_NB_ARRAY_ADDR, section);
+		pci_write_config_dword(pvt->F3, F10_NB_ARRAY_ADDR, section);
 
 		word_bits = SET_NB_DRAM_INJECTION_WRITE(pvt->injection.word,
 						pvt->injection.bit_map);
 
 		/* Issue 'word' and 'bit' along with the READ request */
-		pci_write_config_dword(pvt->misc_f3_ctl,
-					F10_NB_ARRAY_DATA, word_bits);
+		pci_write_config_dword(pvt->F3, F10_NB_ARRAY_DATA, word_bits);
 
 		debugf0("section=0x%x word_bits=0x%x\n", section, word_bits);
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/edac/amd8131_edac.h linux-libre-2.6.38-gnu1/drivers/edac/amd8131_edac.h
--- linux-libre-2.6.37-gnu1/drivers/edac/amd8131_edac.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/edac/amd8131_edac.h	2011-03-14 21:20:32.000000000 -0400
@@ -99,7 +99,7 @@ struct amd8131_dev_info {
 
 /*
  * AMD8131 chipset has two pairs of PCIX Bridge and related IOAPIC
- * Controler, and ATCA-6101 has two AMD8131 chipsets, so there are
+ * Controller, and ATCA-6101 has two AMD8131 chipsets, so there are
  * four PCIX Bridges on ATCA-6101 altogether.
  *
  * These PCIX Bridges share the same PCI Device ID and are all of
diff -druNp linux-libre-2.6.37-gnu1/drivers/edac/cell_edac.c linux-libre-2.6.38-gnu1/drivers/edac/cell_edac.c
--- linux-libre-2.6.37-gnu1/drivers/edac/cell_edac.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/edac/cell_edac.c	2011-03-14 21:20:32.000000000 -0400
@@ -47,7 +47,7 @@ static void cell_edac_count_ce(struct me
 	offset = address & ~PAGE_MASK;
 	syndrome = (ar & 0x000000001fe00000ul) >> 21;
 
-	/* TODO: Decoding of the error addresss */
+	/* TODO: Decoding of the error address */
 	edac_mc_handle_ce(mci, csrow->first_page + pfn, offset,
 			  syndrome, 0, chan, "");
 }
@@ -68,7 +68,7 @@ static void cell_edac_count_ue(struct me
 	pfn = address >> PAGE_SHIFT;
 	offset = address & ~PAGE_MASK;
 
-	/* TODO: Decoding of the error addresss */
+	/* TODO: Decoding of the error address */
 	edac_mc_handle_ue(mci, csrow->first_page + pfn, offset, 0, "");
 }
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/edac/cpc925_edac.c linux-libre-2.6.38-gnu1/drivers/edac/cpc925_edac.c
--- linux-libre-2.6.37-gnu1/drivers/edac/cpc925_edac.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/edac/cpc925_edac.c	2011-03-14 21:20:32.000000000 -0400
@@ -818,9 +818,10 @@ static void cpc925_del_edac_devices(void
 }
 
 /* Convert current back-ground scrub rate into byte/sec bandwith */
-static int cpc925_get_sdram_scrub_rate(struct mem_ctl_info *mci, u32 *bw)
+static int cpc925_get_sdram_scrub_rate(struct mem_ctl_info *mci)
 {
 	struct cpc925_mc_pdata *pdata = mci->pvt_info;
+	int bw;
 	u32 mscr;
 	u8 si;
 
@@ -832,11 +833,11 @@ static int cpc925_get_sdram_scrub_rate(s
 	if (((mscr & MSCR_SCRUB_MOD_MASK) != MSCR_BACKGR_SCRUB) ||
 	    (si == 0)) {
 		cpc925_mc_printk(mci, KERN_INFO, "Scrub mode not enabled\n");
-		*bw = 0;
+		bw = 0;
 	} else
-		*bw = CPC925_SCRUB_BLOCK_SIZE * 0xFA67 / si;
+		bw = CPC925_SCRUB_BLOCK_SIZE * 0xFA67 / si;
 
-	return 0;
+	return bw;
 }
 
 /* Return 0 for single channel; 1 for dual channel */
diff -druNp linux-libre-2.6.37-gnu1/drivers/edac/e752x_edac.c linux-libre-2.6.38-gnu1/drivers/edac/e752x_edac.c
--- linux-libre-2.6.37-gnu1/drivers/edac/e752x_edac.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/edac/e752x_edac.c	2011-03-14 21:20:32.000000000 -0400
@@ -983,11 +983,11 @@ static int set_sdram_scrub_rate(struct m
 
 	pci_write_config_word(pdev, E752X_MCHSCRB, scrubrates[i].scrubval);
 
-	return 0;
+	return scrubrates[i].bandwidth;
 }
 
 /* Convert current scrub rate value into byte/sec bandwidth */
-static int get_sdram_scrub_rate(struct mem_ctl_info *mci, u32 *bw)
+static int get_sdram_scrub_rate(struct mem_ctl_info *mci)
 {
 	const struct scrubrate *scrubrates;
 	struct e752x_pvt *pvt = (struct e752x_pvt *) mci->pvt_info;
@@ -1013,10 +1013,8 @@ static int get_sdram_scrub_rate(struct m
 			"Invalid sdram scrub control value: 0x%x\n", scrubval);
 		return -1;
 	}
+	return scrubrates[i].bandwidth;
 
-	*bw = scrubrates[i].bandwidth;
-
-	return 0;
 }
 
 /* Return 1 if dual channel mode is active.  Else return 0. */
diff -druNp linux-libre-2.6.37-gnu1/drivers/edac/edac_core.h linux-libre-2.6.38-gnu1/drivers/edac/edac_core.h
--- linux-libre-2.6.37-gnu1/drivers/edac/edac_core.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/edac/edac_core.h	2011-03-14 21:20:32.000000000 -0400
@@ -68,9 +68,10 @@
 #define EDAC_PCI "PCI"
 #define EDAC_DEBUG "DEBUG"
 
+extern const char *edac_mem_types[];
+
 #ifdef CONFIG_EDAC_DEBUG
 extern int edac_debug_level;
-extern const char *edac_mem_types[];
 
 #define edac_debug_printk(level, fmt, arg...)                           \
 	do {                                                            \
@@ -258,7 +259,7 @@ enum scrub_type {
  *			for single channel are 64 bits, for dual channel 128
  *			bits.
  *
- * Single-Ranked stick:	A Single-ranked stick has 1 chip-select row of memmory.
+ * 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.
@@ -386,7 +387,7 @@ struct mem_ctl_info {
 	   representation and converts it to the closest matching
 	   bandwith in bytes/sec.
 	 */
-	int (*get_sdram_scrub_rate) (struct mem_ctl_info * mci, u32 * bw);
+	int (*get_sdram_scrub_rate) (struct mem_ctl_info * mci);
 
 
 	/* pointer to edac checking routine */
diff -druNp linux-libre-2.6.37-gnu1/drivers/edac/edac_mc.c linux-libre-2.6.38-gnu1/drivers/edac/edac_mc.c
--- linux-libre-2.6.37-gnu1/drivers/edac/edac_mc.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/edac/edac_mc.c	2011-03-14 21:20:32.000000000 -0400
@@ -76,6 +76,8 @@ static void edac_mc_dump_mci(struct mem_
 	debugf3("\tpvt_info = %p\n\n", mci->pvt_info);
 }
 
+#endif				/* CONFIG_EDAC_DEBUG */
+
 /*
  * keep those in sync with the enum mem_type
  */
@@ -100,8 +102,6 @@ const char *edac_mem_types[] = {
 };
 EXPORT_SYMBOL_GPL(edac_mem_types);
 
-#endif				/* CONFIG_EDAC_DEBUG */
-
 /* 'ptr' points to a possibly unaligned item X such that sizeof(X) is 'size'.
  * Adjust 'ptr' so that its alignment is at least as stringent as what the
  * compiler would provide for X and return the aligned result.
diff -druNp linux-libre-2.6.37-gnu1/drivers/edac/edac_mc_sysfs.c linux-libre-2.6.38-gnu1/drivers/edac/edac_mc_sysfs.c
--- linux-libre-2.6.37-gnu1/drivers/edac/edac_mc_sysfs.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/edac/edac_mc_sysfs.c	2011-03-14 21:20:32.000000000 -0400
@@ -436,56 +436,55 @@ static ssize_t mci_reset_counters_store(
 	return count;
 }
 
-/* memory scrubbing */
+/* Memory scrubbing interface:
+ *
+ * A MC driver can limit the scrubbing bandwidth based on the CPU type.
+ * Therefore, ->set_sdram_scrub_rate should be made to return the actual
+ * bandwidth that is accepted or 0 when scrubbing is to be disabled.
+ *
+ * Negative value still means that an error has occurred while setting
+ * the scrub rate.
+ */
 static ssize_t mci_sdram_scrub_rate_store(struct mem_ctl_info *mci,
 					  const char *data, size_t count)
 {
 	unsigned long bandwidth = 0;
-	int err;
+	int new_bw = 0;
 
-	if (!mci->set_sdram_scrub_rate) {
-		edac_printk(KERN_WARNING, EDAC_MC,
-			    "Memory scrub rate setting not implemented!\n");
+	if (!mci->set_sdram_scrub_rate)
 		return -EINVAL;
-	}
 
 	if (strict_strtoul(data, 10, &bandwidth) < 0)
 		return -EINVAL;
 
-	err = mci->set_sdram_scrub_rate(mci, (u32)bandwidth);
-	if (err) {
-		edac_printk(KERN_DEBUG, EDAC_MC,
-			    "Failed setting scrub rate to %lu\n", bandwidth);
-		return -EINVAL;
-	}
-	else {
-		edac_printk(KERN_DEBUG, EDAC_MC,
-			    "Scrub rate set to: %lu\n", bandwidth);
+	new_bw = mci->set_sdram_scrub_rate(mci, bandwidth);
+	if (new_bw >= 0) {
+		edac_printk(KERN_DEBUG, EDAC_MC, "Scrub rate set to %d\n", new_bw);
 		return count;
 	}
+
+	edac_printk(KERN_DEBUG, EDAC_MC, "Error setting scrub rate to: %lu\n", bandwidth);
+	return -EINVAL;
 }
 
+/*
+ * ->get_sdram_scrub_rate() return value semantics same as above.
+ */
 static ssize_t mci_sdram_scrub_rate_show(struct mem_ctl_info *mci, char *data)
 {
-	u32 bandwidth = 0;
-	int err;
+	int bandwidth = 0;
 
-	if (!mci->get_sdram_scrub_rate) {
-		edac_printk(KERN_WARNING, EDAC_MC,
-			    "Memory scrub rate reading not implemented\n");
+	if (!mci->get_sdram_scrub_rate)
 		return -EINVAL;
-	}
 
-	err = mci->get_sdram_scrub_rate(mci, &bandwidth);
-	if (err) {
+	bandwidth = mci->get_sdram_scrub_rate(mci);
+	if (bandwidth < 0) {
 		edac_printk(KERN_DEBUG, EDAC_MC, "Error reading scrub rate\n");
-		return err;
-	}
-	else {
-		edac_printk(KERN_DEBUG, EDAC_MC,
-			    "Read scrub rate: %d\n", bandwidth);
-		return sprintf(data, "%d\n", bandwidth);
+		return bandwidth;
 	}
+
+	edac_printk(KERN_DEBUG, EDAC_MC, "Read scrub rate: %d\n", bandwidth);
+	return sprintf(data, "%d\n", bandwidth);
 }
 
 /* default attribute files for the MCI object */
diff -druNp linux-libre-2.6.37-gnu1/drivers/edac/i5100_edac.c linux-libre-2.6.38-gnu1/drivers/edac/i5100_edac.c
--- linux-libre-2.6.37-gnu1/drivers/edac/i5100_edac.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/edac/i5100_edac.c	2011-03-14 21:20:32.000000000 -0400
@@ -611,20 +611,17 @@ static int i5100_set_scrub_rate(struct m
 
 	bandwidth = 5900000 * i5100_mc_scrben(dw);
 
-	return 0;
+	return bandwidth;
 }
 
-static int i5100_get_scrub_rate(struct mem_ctl_info *mci,
-				u32 *bandwidth)
+static int i5100_get_scrub_rate(struct mem_ctl_info *mci)
 {
 	struct i5100_priv *priv = mci->pvt_info;
 	u32 dw;
 
 	pci_read_config_dword(priv->mc, I5100_MC, &dw);
 
-	*bandwidth = 5900000 * i5100_mc_scrben(dw);
-
-	return 0;
+	return 5900000 * i5100_mc_scrben(dw);
 }
 
 static struct pci_dev *pci_get_device_func(unsigned vendor,
diff -druNp linux-libre-2.6.37-gnu1/drivers/edac/i7core_edac.c linux-libre-2.6.38-gnu1/drivers/edac/i7core_edac.c
--- linux-libre-2.6.37-gnu1/drivers/edac/i7core_edac.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/edac/i7core_edac.c	2011-03-14 21:20:32.000000000 -0400
@@ -1,6 +1,6 @@
 /* Intel i7 core/Nehalem Memory Controller kernel module
  *
- * This driver supports yhe memory controllers found on the Intel
+ * This driver supports the memory controllers found on the Intel
  * processor families i7core, i7core 7xx/8xx, i5core, Xeon 35xx,
  * Xeon 55xx and Xeon 56xx also known as Nehalem, Nehalem-EP, Lynnfield
  * and Westmere-EP.
@@ -1271,7 +1271,7 @@ static void __init i7core_xeon_pci_fixup
 	int i;
 
 	/*
-	 * On Xeon 55xx, the Intel Quckpath Arch Generic Non-core pci buses
+	 * On Xeon 55xx, the Intel Quick Path Arch Generic Non-core pci buses
 	 * aren't announced by acpi. So, we need to use a legacy scan probing
 	 * to detect them
 	 */
@@ -1864,7 +1864,7 @@ static int i7core_mce_check_error(void *
 	if (mce->mcgstatus & 1)
 		i7core_check_error(mci);
 
-	/* Advice mcelog that the error were handled */
+	/* Advise mcelog that the errors were handled */
 	return 1;
 }
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/edac/Kconfig linux-libre-2.6.38-gnu1/drivers/edac/Kconfig
--- linux-libre-2.6.37-gnu1/drivers/edac/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/edac/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -75,11 +75,11 @@ config EDAC_MCE
 	bool
 
 config EDAC_AMD64
-	tristate "AMD64 (Opteron, Athlon64) K8, F10h, F11h"
-	depends on EDAC_MM_EDAC && AMD_NB && X86_64 && PCI && EDAC_DECODE_MCE
+	tristate "AMD64 (Opteron, Athlon64) K8, F10h"
+	depends on EDAC_MM_EDAC && AMD_NB && X86_64 && EDAC_DECODE_MCE
 	help
-	  Support for error detection and correction on the AMD 64
-	  Families of Memory Controllers (K8, F10h and F11h)
+	  Support for error detection and correction of DRAM ECC errors on
+	  the AMD64 families of memory controllers (K8 and F10h)
 
 config EDAC_AMD64_ERROR_INJECTION
 	bool "Sysfs HW Error injection facilities"
diff -druNp linux-libre-2.6.37-gnu1/drivers/edac/mce_amd.c linux-libre-2.6.38-gnu1/drivers/edac/mce_amd.c
--- linux-libre-2.6.37-gnu1/drivers/edac/mce_amd.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/edac/mce_amd.c	2011-03-14 21:20:32.000000000 -0400
@@ -5,6 +5,7 @@
 
 static struct amd_decoder_ops *fam_ops;
 
+static u8 xec_mask	 = 0xf;
 static u8 nb_err_cpumask = 0xf;
 
 static bool report_gart_errors;
@@ -74,57 +75,104 @@ static const char *f10h_nb_mce_desc[] =
 	"ECC Error in the Probe Filter directory"
 };
 
-static bool f12h_dc_mce(u16 ec)
+static const char * const f15h_ic_mce_desc[] = {
+	"UC during a demand linefill from L2",
+	"Parity error during data load from IC",
+	"Parity error for IC valid bit",
+	"Main tag parity error",
+	"Parity error in prediction queue",
+	"PFB data/address parity error",
+	"Parity error in the branch status reg",
+	"PFB promotion address error",
+	"Tag error during probe/victimization",
+	"Parity error for IC probe tag valid bit",
+	"PFB non-cacheable bit parity error",
+	"PFB valid bit parity error",			/* xec = 0xd */
+	"patch RAM",					/* xec = 010 */
+	"uop queue",
+	"insn buffer",
+	"predecode buffer",
+	"fetch address FIFO"
+};
+
+static const char * const f15h_cu_mce_desc[] = {
+	"Fill ECC error on data fills",			/* xec = 0x4 */
+	"Fill parity error on insn fills",
+	"Prefetcher request FIFO parity error",
+	"PRQ address parity error",
+	"PRQ data parity error",
+	"WCC Tag ECC error",
+	"WCC Data ECC error",
+	"WCB Data parity error",
+	"VB Data/ECC error",
+	"L2 Tag ECC error",				/* xec = 0x10 */
+	"Hard L2 Tag ECC error",
+	"Multiple hits on L2 tag",
+	"XAB parity error",
+	"PRB address parity error"
+};
+
+static const char * const fr_ex_mce_desc[] = {
+	"CPU Watchdog timer expire",
+	"Wakeup array dest tag",
+	"AG payload array",
+	"EX payload array",
+	"IDRF array",
+	"Retire dispatch queue",
+	"Mapper checkpoint array",
+	"Physical register file EX0 port",
+	"Physical register file EX1 port",
+	"Physical register file AG0 port",
+	"Physical register file AG1 port",
+	"Flag register file",
+	"DE correctable error could not be corrected"
+};
+
+static bool f12h_dc_mce(u16 ec, u8 xec)
 {
 	bool ret = false;
 
 	if (MEM_ERROR(ec)) {
-		u8 ll = ec & 0x3;
+		u8 ll = LL(ec);
 		ret = true;
 
 		if (ll == LL_L2)
 			pr_cont("during L1 linefill from L2.\n");
 		else if (ll == LL_L1)
-			pr_cont("Data/Tag %s error.\n", RRRR_MSG(ec));
+			pr_cont("Data/Tag %s error.\n", R4_MSG(ec));
 		else
 			ret = false;
 	}
 	return ret;
 }
 
-static bool f10h_dc_mce(u16 ec)
+static bool f10h_dc_mce(u16 ec, u8 xec)
 {
-	u8 r4  = (ec >> 4) & 0xf;
-	u8 ll  = ec & 0x3;
-
-	if (r4 == R4_GEN && ll == LL_L1) {
+	if (R4(ec) == R4_GEN && LL(ec) == LL_L1) {
 		pr_cont("during data scrub.\n");
 		return true;
 	}
-	return f12h_dc_mce(ec);
+	return f12h_dc_mce(ec, xec);
 }
 
-static bool k8_dc_mce(u16 ec)
+static bool k8_dc_mce(u16 ec, u8 xec)
 {
 	if (BUS_ERROR(ec)) {
 		pr_cont("during system linefill.\n");
 		return true;
 	}
 
-	return f10h_dc_mce(ec);
+	return f10h_dc_mce(ec, xec);
 }
 
-static bool f14h_dc_mce(u16 ec)
+static bool f14h_dc_mce(u16 ec, u8 xec)
 {
-	u8 r4	 = (ec >> 4) & 0xf;
-	u8 ll	 = ec & 0x3;
-	u8 tt	 = (ec >> 2) & 0x3;
-	u8 ii	 = tt;
+	u8 r4	 = R4(ec);
 	bool ret = true;
 
 	if (MEM_ERROR(ec)) {
 
-		if (tt != TT_DATA || ll != LL_L1)
+		if (TT(ec) != TT_DATA || LL(ec) != LL_L1)
 			return false;
 
 		switch (r4) {
@@ -144,7 +192,7 @@ static bool f14h_dc_mce(u16 ec)
 		}
 	} else if (BUS_ERROR(ec)) {
 
-		if ((ii != II_MEM && ii != II_IO) || ll != LL_LG)
+		if ((II(ec) != II_MEM && II(ec) != II_IO) || LL(ec) != LL_LG)
 			return false;
 
 		pr_cont("System read data error on a ");
@@ -169,39 +217,78 @@ static bool f14h_dc_mce(u16 ec)
 	return ret;
 }
 
+static bool f15h_dc_mce(u16 ec, u8 xec)
+{
+	bool ret = true;
+
+	if (MEM_ERROR(ec)) {
+
+		switch (xec) {
+		case 0x0:
+			pr_cont("Data Array access error.\n");
+			break;
+
+		case 0x1:
+			pr_cont("UC error during a linefill from L2/NB.\n");
+			break;
+
+		case 0x2:
+		case 0x11:
+			pr_cont("STQ access error.\n");
+			break;
+
+		case 0x3:
+			pr_cont("SCB access error.\n");
+			break;
+
+		case 0x10:
+			pr_cont("Tag error.\n");
+			break;
+
+		case 0x12:
+			pr_cont("LDQ access error.\n");
+			break;
+
+		default:
+			ret = false;
+		}
+	} else if (BUS_ERROR(ec)) {
+
+		if (!xec)
+			pr_cont("during system linefill.\n");
+		else
+			pr_cont(" Internal %s condition.\n",
+				((xec == 1) ? "livelock" : "deadlock"));
+	} else
+		ret = false;
+
+	return ret;
+}
+
 static void amd_decode_dc_mce(struct mce *m)
 {
-	u16 ec = m->status & 0xffff;
-	u8 xec = (m->status >> 16) & 0xf;
+	u16 ec = EC(m->status);
+	u8 xec = XEC(m->status, xec_mask);
 
 	pr_emerg(HW_ERR "Data Cache Error: ");
 
 	/* TLB error signatures are the same across families */
 	if (TLB_ERROR(ec)) {
-		u8 tt = (ec >> 2) & 0x3;
-
-		if (tt == TT_DATA) {
+		if (TT(ec) == TT_DATA) {
 			pr_cont("%s TLB %s.\n", LL_MSG(ec),
-				(xec ? "multimatch" : "parity error"));
+				((xec == 2) ? "locked miss"
+					    : (xec ? "multimatch" : "parity")));
 			return;
 		}
-		else
-			goto wrong_dc_mce;
-	}
-
-	if (!fam_ops->dc_mce(ec))
-		goto wrong_dc_mce;
-
-	return;
-
-wrong_dc_mce:
-	pr_emerg(HW_ERR "Corrupted DC MCE info?\n");
+	} else if (fam_ops->dc_mce(ec, xec))
+		;
+	else
+		pr_emerg(HW_ERR "Corrupted DC MCE info?\n");
 }
 
-static bool k8_ic_mce(u16 ec)
+static bool k8_ic_mce(u16 ec, u8 xec)
 {
-	u8 ll	 = ec & 0x3;
-	u8 r4	 = (ec >> 4) & 0xf;
+	u8 ll	 = LL(ec);
 	bool ret = true;
 
 	if (!MEM_ERROR(ec))
@@ -210,7 +297,7 @@ static bool k8_ic_mce(u16 ec)
 	if (ll == 0x2)
 		pr_cont("during a linefill from L2.\n");
 	else if (ll == 0x1) {
-		switch (r4) {
+		switch (R4(ec)) {
 		case R4_IRD:
 			pr_cont("Parity error during data load.\n");
 			break;
@@ -233,15 +320,13 @@ static bool k8_ic_mce(u16 ec)
 	return ret;
 }
 
-static bool f14h_ic_mce(u16 ec)
+static bool f14h_ic_mce(u16 ec, u8 xec)
 {
-	u8 ll    = ec & 0x3;
-	u8 tt    = (ec >> 2) & 0x3;
-	u8 r4  = (ec >> 4) & 0xf;
+	u8 r4    = R4(ec);
 	bool ret = true;
 
 	if (MEM_ERROR(ec)) {
-		if (tt != 0 || ll != 1)
+		if (TT(ec) != 0 || LL(ec) != 1)
 			ret = false;
 
 		if (r4 == R4_IRD)
@@ -254,10 +339,36 @@ static bool f14h_ic_mce(u16 ec)
 	return ret;
 }
 
+static bool f15h_ic_mce(u16 ec, u8 xec)
+{
+	bool ret = true;
+
+	if (!MEM_ERROR(ec))
+		return false;
+
+	switch (xec) {
+	case 0x0 ... 0xa:
+		pr_cont("%s.\n", f15h_ic_mce_desc[xec]);
+		break;
+
+	case 0xd:
+		pr_cont("%s.\n", f15h_ic_mce_desc[xec-2]);
+		break;
+
+	case 0x10 ... 0x14:
+		pr_cont("Decoder %s parity error.\n", f15h_ic_mce_desc[xec-4]);
+		break;
+
+	default:
+		ret = false;
+	}
+	return ret;
+}
+
 static void amd_decode_ic_mce(struct mce *m)
 {
-	u16 ec = m->status & 0xffff;
-	u8 xec = (m->status >> 16) & 0xf;
+	u16 ec = EC(m->status);
+	u8 xec = XEC(m->status, xec_mask);
 
 	pr_emerg(HW_ERR "Instruction Cache Error: ");
 
@@ -268,7 +379,7 @@ static void amd_decode_ic_mce(struct mce
 		bool k8 = (boot_cpu_data.x86 == 0xf && (m->status & BIT_64(58)));
 
 		pr_cont("during %s.\n", (k8 ? "system linefill" : "NB data read"));
-	} else if (fam_ops->ic_mce(ec))
+	} else if (fam_ops->ic_mce(ec, xec))
 		;
 	else
 		pr_emerg(HW_ERR "Corrupted IC MCE info?\n");
@@ -276,8 +387,8 @@ static void amd_decode_ic_mce(struct mce
 
 static void amd_decode_bu_mce(struct mce *m)
 {
-	u32 ec = m->status & 0xffff;
-	u32 xec = (m->status >> 16) & 0xf;
+	u16 ec = EC(m->status);
+	u8 xec = XEC(m->status, xec_mask);
 
 	pr_emerg(HW_ERR "Bus Unit Error");
 
@@ -286,23 +397,23 @@ static void amd_decode_bu_mce(struct mce
 	else if (xec == 0x3)
 		pr_cont(" in the victim data buffers.\n");
 	else if (xec == 0x2 && MEM_ERROR(ec))
-		pr_cont(": %s error in the L2 cache tags.\n", RRRR_MSG(ec));
+		pr_cont(": %s error in the L2 cache tags.\n", R4_MSG(ec));
 	else if (xec == 0x0) {
 		if (TLB_ERROR(ec))
 			pr_cont(": %s error in a Page Descriptor Cache or "
 				"Guest TLB.\n", TT_MSG(ec));
 		else if (BUS_ERROR(ec))
 			pr_cont(": %s/ECC error in data read from NB: %s.\n",
-				RRRR_MSG(ec), PP_MSG(ec));
+				R4_MSG(ec), PP_MSG(ec));
 		else if (MEM_ERROR(ec)) {
-			u8 rrrr = (ec >> 4) & 0xf;
+			u8 r4 = R4(ec);
 
-			if (rrrr >= 0x7)
+			if (r4 >= 0x7)
 				pr_cont(": %s error during data copyback.\n",
-					RRRR_MSG(ec));
-			else if (rrrr <= 0x1)
+					R4_MSG(ec));
+			else if (r4 <= 0x1)
 				pr_cont(": %s parity/ECC error during data "
-					"access from L2.\n", RRRR_MSG(ec));
+					"access from L2.\n", R4_MSG(ec));
 			else
 				goto wrong_bu_mce;
 		} else
@@ -316,12 +427,52 @@ wrong_bu_mce:
 	pr_emerg(HW_ERR "Corrupted BU MCE info?\n");
 }
 
+static void amd_decode_cu_mce(struct mce *m)
+{
+	u16 ec = EC(m->status);
+	u8 xec = XEC(m->status, xec_mask);
+
+	pr_emerg(HW_ERR "Combined Unit Error: ");
+
+	if (TLB_ERROR(ec)) {
+		if (xec == 0x0)
+			pr_cont("Data parity TLB read error.\n");
+		else if (xec == 0x1)
+			pr_cont("Poison data provided for TLB fill.\n");
+		else
+			goto wrong_cu_mce;
+	} else if (BUS_ERROR(ec)) {
+		if (xec > 2)
+			goto wrong_cu_mce;
+
+		pr_cont("Error during attempted NB data read.\n");
+	} else if (MEM_ERROR(ec)) {
+		switch (xec) {
+		case 0x4 ... 0xc:
+			pr_cont("%s.\n", f15h_cu_mce_desc[xec - 0x4]);
+			break;
+
+		case 0x10 ... 0x14:
+			pr_cont("%s.\n", f15h_cu_mce_desc[xec - 0x7]);
+			break;
+
+		default:
+			goto wrong_cu_mce;
+		}
+	}
+
+	return;
+
+wrong_cu_mce:
+	pr_emerg(HW_ERR "Corrupted CU MCE info?\n");
+}
+
 static void amd_decode_ls_mce(struct mce *m)
 {
-	u16 ec = m->status & 0xffff;
-	u8 xec = (m->status >> 16) & 0xf;
+	u16 ec = EC(m->status);
+	u8 xec = XEC(m->status, xec_mask);
 
-	if (boot_cpu_data.x86 == 0x14) {
+	if (boot_cpu_data.x86 >= 0x14) {
 		pr_emerg("You shouldn't be seeing an LS MCE on this cpu family,"
 			 " please report on LKML.\n");
 		return;
@@ -330,12 +481,12 @@ static void amd_decode_ls_mce(struct mce
 	pr_emerg(HW_ERR "Load Store Error");
 
 	if (xec == 0x0) {
-		u8 r4 = (ec >> 4) & 0xf;
+		u8 r4 = R4(ec);
 
 		if (!BUS_ERROR(ec) || (r4 != R4_DRD && r4 != R4_DWR))
 			goto wrong_ls_mce;
 
-		pr_cont(" during %s.\n", RRRR_MSG(ec));
+		pr_cont(" during %s.\n", R4_MSG(ec));
 	} else
 		goto wrong_ls_mce;
 
@@ -410,6 +561,15 @@ static bool f10h_nb_mce(u16 ec, u8 xec)
 		goto out;
 		break;
 
+	case 0x19:
+		if (boot_cpu_data.x86 == 0x15)
+			pr_cont("Compute Unit Data Error.\n");
+		else
+			ret = false;
+
+		goto out;
+		break;
+
 	case 0x1c ... 0x1f:
 		offset = 24;
 		break;
@@ -434,27 +594,30 @@ static bool nb_noop_mce(u16 ec, u8 xec)
 
 void amd_decode_nb_mce(int node_id, struct mce *m, u32 nbcfg)
 {
-	u8 xec   = (m->status >> 16) & 0x1f;
-	u16 ec   = m->status & 0xffff;
+	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);
+	pr_emerg(HW_ERR "Northbridge Error (node %d", node_id);
 
-	/*
-	 * F10h, revD can disable ErrCpu[3:0] so check that first and also the
-	 * value encoding has changed so interpret those differently
-	 */
+	/* F10h, revD can disable ErrCpu[3:0] through ErrCpuVal */
 	if ((boot_cpu_data.x86 == 0x10) &&
 	    (boot_cpu_data.x86_model > 7)) {
 		if (nbsh & K8_NBSH_ERR_CPU_VAL)
-			pr_cont(", core: %u", (u8)(nbsh & nb_err_cpumask));
+			core = nbsh & nb_err_cpumask;
 	} else {
 		u8 assoc_cpus = nbsh & nb_err_cpumask;
 
 		if (assoc_cpus > 0)
-			pr_cont(", core: %d", fls(assoc_cpus) - 1);
+			core = fls(assoc_cpus) - 1;
 	}
 
+	if (core >= 0)
+		pr_cont(", core %d): ", core);
+	else
+		pr_cont("): ");
+
 	switch (xec) {
 	case 0x2:
 		pr_cont("Sync error (sync packets on HT link detected).\n");
@@ -496,35 +659,89 @@ EXPORT_SYMBOL_GPL(amd_decode_nb_mce);
 
 static void amd_decode_fr_mce(struct mce *m)
 {
-	if (boot_cpu_data.x86 == 0xf ||
-	    boot_cpu_data.x86 == 0x11)
+	struct cpuinfo_x86 *c = &boot_cpu_data;
+	u8 xec = XEC(m->status, xec_mask);
+
+	if (c->x86 == 0xf || c->x86 == 0x11)
 		goto wrong_fr_mce;
 
-	/* we have only one error signature so match all fields at once. */
-	if ((m->status & 0xffff) == 0x0f0f) {
-		pr_emerg(HW_ERR "FR Error: CPU Watchdog timer expire.\n");
-		return;
-	}
+	if (c->x86 != 0x15 && xec != 0x0)
+		goto wrong_fr_mce;
+
+	pr_emerg(HW_ERR "%s Error: ",
+		 (c->x86 == 0x15 ? "Execution Unit" : "FIROB"));
+
+	if (xec == 0x0 || xec == 0xc)
+		pr_cont("%s.\n", fr_ex_mce_desc[xec]);
+	else if (xec < 0xd)
+		pr_cont("%s parity error.\n", fr_ex_mce_desc[xec]);
+	else
+		goto wrong_fr_mce;
+
+	return;
 
 wrong_fr_mce:
 	pr_emerg(HW_ERR "Corrupted FR MCE info?\n");
 }
 
+static void amd_decode_fp_mce(struct mce *m)
+{
+	u8 xec = XEC(m->status, xec_mask);
+
+	pr_emerg(HW_ERR "Floating Point Unit Error: ");
+
+	switch (xec) {
+	case 0x1:
+		pr_cont("Free List");
+		break;
+
+	case 0x2:
+		pr_cont("Physical Register File");
+		break;
+
+	case 0x3:
+		pr_cont("Retire Queue");
+		break;
+
+	case 0x4:
+		pr_cont("Scheduler table");
+		break;
+
+	case 0x5:
+		pr_cont("Status Register File");
+		break;
+
+	default:
+		goto wrong_fp_mce;
+		break;
+	}
+
+	pr_cont(" parity error.\n");
+
+	return;
+
+wrong_fp_mce:
+	pr_emerg(HW_ERR "Corrupted FP MCE info?\n");
+}
+
 static inline void amd_decode_err_code(u16 ec)
 {
-	if (TLB_ERROR(ec)) {
-		pr_emerg(HW_ERR "Transaction: %s, Cache Level: %s\n",
-			 TT_MSG(ec), LL_MSG(ec));
-	} else if (MEM_ERROR(ec)) {
-		pr_emerg(HW_ERR "Transaction: %s, Type: %s, Cache Level: %s\n",
-			 RRRR_MSG(ec), TT_MSG(ec), LL_MSG(ec));
-	} else if (BUS_ERROR(ec)) {
-		pr_emerg(HW_ERR "Transaction: %s (%s), %s, Cache Level: %s, "
-			 "Participating Processor: %s\n",
-			  RRRR_MSG(ec), II_MSG(ec), TO_MSG(ec), LL_MSG(ec),
-			  PP_MSG(ec));
-	} else
-		pr_emerg(HW_ERR "Huh? Unknown MCE error 0x%x\n", ec);
+
+	pr_emerg(HW_ERR "cache level: %s", LL_MSG(ec));
+
+	if (BUS_ERROR(ec))
+		pr_cont(", mem/io: %s", II_MSG(ec));
+	else
+		pr_cont(", tx: %s", TT_MSG(ec));
+
+	if (MEM_ERROR(ec) || BUS_ERROR(ec)) {
+		pr_cont(", mem-tx: %s", R4_MSG(ec));
+
+		if (BUS_ERROR(ec))
+			pr_cont(", part-proc: %s (%s)", PP_MSG(ec), TO_MSG(ec));
+	}
+
+	pr_cont("\n");
 }
 
 /*
@@ -546,25 +763,32 @@ static bool amd_filter_mce(struct mce *m
 int amd_decode_mce(struct notifier_block *nb, unsigned long val, void *data)
 {
 	struct mce *m = (struct mce *)data;
+	struct cpuinfo_x86 *c = &boot_cpu_data;
 	int node, ecc;
 
 	if (amd_filter_mce(m))
 		return NOTIFY_STOP;
 
-	pr_emerg(HW_ERR "MC%d_STATUS: ", m->bank);
+	pr_emerg(HW_ERR "MC%d_STATUS[%s|%s|%s|%s|%s",
+		m->bank,
+		((m->status & MCI_STATUS_OVER)	? "Over"  : "-"),
+		((m->status & MCI_STATUS_UC)	? "UE"	  : "CE"),
+		((m->status & MCI_STATUS_MISCV)	? "MiscV" : "-"),
+		((m->status & MCI_STATUS_PCC)	? "PCC"	  : "-"),
+		((m->status & MCI_STATUS_ADDRV)	? "AddrV" : "-"));
 
-	pr_cont("%sorrected error, other errors lost: %s, "
-		 "CPU context corrupt: %s",
-		 ((m->status & MCI_STATUS_UC) ? "Unc"  : "C"),
-		 ((m->status & MCI_STATUS_OVER) ? "yes"  : "no"),
-		 ((m->status & MCI_STATUS_PCC) ? "yes" : "no"));
+	if (c->x86 == 0x15)
+		pr_cont("|%s|%s",
+			((m->status & BIT_64(44)) ? "Deferred" : "-"),
+			((m->status & BIT_64(43)) ? "Poison"   : "-"));
 
 	/* do the two bits[14:13] together */
 	ecc = (m->status >> 45) & 0x3;
 	if (ecc)
-		pr_cont(", %sECC Error", ((ecc == 2) ? "C" : "U"));
+		pr_cont("|%sECC", ((ecc == 2) ? "C" : "U"));
+
+	pr_cont("]: 0x%016llx\n", m->status);
 
-	pr_cont("\n");
 
 	switch (m->bank) {
 	case 0:
@@ -576,7 +800,10 @@ int amd_decode_mce(struct notifier_block
 		break;
 
 	case 2:
-		amd_decode_bu_mce(m);
+		if (c->x86 == 0x15)
+			amd_decode_cu_mce(m);
+		else
+			amd_decode_bu_mce(m);
 		break;
 
 	case 3:
@@ -592,6 +819,10 @@ int amd_decode_mce(struct notifier_block
 		amd_decode_fr_mce(m);
 		break;
 
+	case 6:
+		amd_decode_fp_mce(m);
+		break;
+
 	default:
 		break;
 	}
@@ -608,18 +839,21 @@ static struct notifier_block amd_mce_dec
 
 static int __init mce_amd_init(void)
 {
-	if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD)
+	struct cpuinfo_x86 *c = &boot_cpu_data;
+
+	if (c->x86_vendor != X86_VENDOR_AMD)
 		return 0;
 
-	if ((boot_cpu_data.x86 < 0xf || boot_cpu_data.x86 > 0x12) &&
-	    (boot_cpu_data.x86 != 0x14 || boot_cpu_data.x86_model > 0xf))
+	if ((c->x86 < 0xf || c->x86 > 0x12) &&
+	    (c->x86 != 0x14 || c->x86_model > 0xf) &&
+	    (c->x86 != 0x15 || c->x86_model > 0xf))
 		return 0;
 
 	fam_ops = kzalloc(sizeof(struct amd_decoder_ops), GFP_KERNEL);
 	if (!fam_ops)
 		return -ENOMEM;
 
-	switch (boot_cpu_data.x86) {
+	switch (c->x86) {
 	case 0xf:
 		fam_ops->dc_mce = k8_dc_mce;
 		fam_ops->ic_mce = k8_ic_mce;
@@ -651,9 +885,15 @@ static int __init mce_amd_init(void)
 		fam_ops->nb_mce = nb_noop_mce;
 		break;
 
+	case 0x15:
+		xec_mask = 0x1f;
+		fam_ops->dc_mce = f15h_dc_mce;
+		fam_ops->ic_mce = f15h_ic_mce;
+		fam_ops->nb_mce = f10h_nb_mce;
+		break;
+
 	default:
-		printk(KERN_WARNING "Huh? What family is that: %d?!\n",
-				    boot_cpu_data.x86);
+		printk(KERN_WARNING "Huh? What family is that: %d?!\n", c->x86);
 		kfree(fam_ops);
 		return -EINVAL;
 	}
diff -druNp linux-libre-2.6.37-gnu1/drivers/edac/mce_amd.h linux-libre-2.6.38-gnu1/drivers/edac/mce_amd.h
--- linux-libre-2.6.37-gnu1/drivers/edac/mce_amd.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/edac/mce_amd.h	2011-03-14 21:20:32.000000000 -0400
@@ -7,8 +7,8 @@
 
 #define BIT_64(n)			(U64_C(1) << (n))
 
-#define ERROR_CODE(x)			((x) & 0xffff)
-#define EXT_ERROR_CODE(x)		(((x) >> 16) & 0x1f)
+#define EC(x)				((x) & 0xffff)
+#define XEC(x, mask)			(((x) >> 16) & mask)
 
 #define LOW_SYNDROME(x)			(((x) >> 15) & 0xff)
 #define HIGH_SYNDROME(x)		(((x) >> 24) & 0xff)
@@ -21,15 +21,15 @@
 #define TT_MSG(x)			tt_msgs[TT(x)]
 #define II(x)				(((x) >> 2) & 0x3)
 #define II_MSG(x)			ii_msgs[II(x)]
-#define LL(x)				(((x) >> 0) & 0x3)
+#define LL(x)				((x) & 0x3)
 #define LL_MSG(x)			ll_msgs[LL(x)]
 #define TO(x)				(((x) >> 8) & 0x1)
 #define TO_MSG(x)			to_msgs[TO(x)]
 #define PP(x)				(((x) >> 9) & 0x3)
 #define PP_MSG(x)			pp_msgs[PP(x)]
 
-#define RRRR(x)				(((x) >> 4) & 0xf)
-#define RRRR_MSG(x)			((RRRR(x) < 9) ?  rrrr_msgs[RRRR(x)] : "Wrong R4!")
+#define R4(x)				(((x) >> 4) & 0xf)
+#define R4_MSG(x)			((R4(x) < 9) ?  rrrr_msgs[R4(x)] : "Wrong R4!")
 
 #define K8_NBSH				0x4C
 
@@ -100,8 +100,8 @@ struct err_regs {
  * per-family decoder ops
  */
 struct amd_decoder_ops {
-	bool (*dc_mce)(u16);
-	bool (*ic_mce)(u16);
+	bool (*dc_mce)(u16, u8);
+	bool (*ic_mce)(u16, u8);
 	bool (*nb_mce)(u16, u8);
 };
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/edac/mce_amd_inj.c linux-libre-2.6.38-gnu1/drivers/edac/mce_amd_inj.c
--- linux-libre-2.6.37-gnu1/drivers/edac/mce_amd_inj.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/edac/mce_amd_inj.c	2011-03-14 21:20:32.000000000 -0400
@@ -88,10 +88,11 @@ static ssize_t edac_inject_bank_store(st
 		return -EINVAL;
 	}
 
-	if (value > 5) {
-		printk(KERN_ERR "Non-existant MCE bank: %lu\n", value);
-		return -EINVAL;
-	}
+	if (value > 5)
+		if (boot_cpu_data.x86 != 0x15 || value > 6) {
+			printk(KERN_ERR "Non-existant MCE bank: %lu\n", value);
+			return -EINVAL;
+		}
 
 	i_mce.bank = value;
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/edac/ppc4xx_edac.c linux-libre-2.6.38-gnu1/drivers/edac/ppc4xx_edac.c
--- linux-libre-2.6.37-gnu1/drivers/edac/ppc4xx_edac.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/edac/ppc4xx_edac.c	2011-03-14 21:20:32.000000000 -0400
@@ -873,7 +873,7 @@ ppc4xx_edac_get_mtype(u32 mcopt1)
 }
 
 /**
- * ppc4xx_edac_init_csrows - intialize driver instance rows
+ * ppc4xx_edac_init_csrows - initialize driver instance rows
  * @mci: A pointer to the EDAC memory controller instance
  *       associated with the ibm,sdram-4xx-ddr2 controller for which
  *       the csrows (i.e. banks/ranks) are being initialized.
@@ -881,7 +881,7 @@ ppc4xx_edac_get_mtype(u32 mcopt1)
  *          currently set for the controller, from which bank width
  *          and memory typ information is derived.
  *
- * This routine intializes the virtual "chip select rows" associated
+ * This routine initializes the virtual "chip select rows" associated
  * with the EDAC memory controller instance. An ibm,sdram-4xx-ddr2
  * controller bank/rank is mapped to a row.
  *
@@ -992,7 +992,7 @@ ppc4xx_edac_init_csrows(struct mem_ctl_i
 }
 
 /**
- * ppc4xx_edac_mc_init - intialize driver instance
+ * ppc4xx_edac_mc_init - initialize driver instance
  * @mci: A pointer to the EDAC memory controller instance being
  *       initialized.
  * @op: A pointer to the OpenFirmware device tree node associated
diff -druNp linux-libre-2.6.37-gnu1/drivers/firewire/core-card.c linux-libre-2.6.38-gnu1/drivers/firewire/core-card.c
--- linux-libre-2.6.37-gnu1/drivers/firewire/core-card.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/firewire/core-card.c	2011-03-14 21:20:32.000000000 -0400
@@ -75,6 +75,8 @@ static size_t config_rom_length = 1 + 4
 #define BIB_IRMC		((1) << 31)
 #define NODE_CAPABILITIES	0x0c0083c0 /* per IEEE 1394 clause 8.3.2.6.5.2 */
 
+#define CANON_OUI		0x000085
+
 static void generate_config_rom(struct fw_card *card, __be32 *config_rom)
 {
 	struct fw_descriptor *desc;
@@ -284,6 +286,7 @@ static void bm_work(struct work_struct *
 	bool root_device_is_running;
 	bool root_device_is_cmc;
 	bool irm_is_1394_1995_only;
+	bool keep_this_irm;
 
 	spin_lock_irq(&card->lock);
 
@@ -305,6 +308,10 @@ static void bm_work(struct work_struct *
 	irm_is_1394_1995_only = irm_device && irm_device->config_rom &&
 			(irm_device->config_rom[2] & 0x000000f0) == 0;
 
+	/* Canon MV5i works unreliably if it is not root node. */
+	keep_this_irm = irm_device && irm_device->config_rom &&
+			irm_device->config_rom[3] >> 8 == CANON_OUI;
+
 	root_id  = root_node->node_id;
 	irm_id   = card->irm_node->node_id;
 	local_id = card->local_node->node_id;
@@ -333,7 +340,7 @@ static void bm_work(struct work_struct *
 			goto pick_me;
 		}
 
-		if (irm_is_1394_1995_only) {
+		if (irm_is_1394_1995_only && !keep_this_irm) {
 			new_root_id = local_id;
 			fw_notify("%s, making local node (%02x) root.\n",
 				  "IRM is not 1394a compliant", new_root_id);
@@ -382,7 +389,7 @@ static void bm_work(struct work_struct *
 
 		spin_lock_irq(&card->lock);
 
-		if (rcode != RCODE_COMPLETE) {
+		if (rcode != RCODE_COMPLETE && !keep_this_irm) {
 			/*
 			 * The lock request failed, maybe the IRM
 			 * isn't really IRM capable after all. Let's
diff -druNp linux-libre-2.6.37-gnu1/drivers/firewire/core-cdev.c linux-libre-2.6.38-gnu1/drivers/firewire/core-cdev.c
--- linux-libre-2.6.37-gnu1/drivers/firewire/core-cdev.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/firewire/core-cdev.c	2011-03-14 21:20:32.000000000 -0400
@@ -1501,9 +1501,10 @@ static int ioctl_send_phy_packet(struct
 	e->client		= client;
 	e->p.speed		= SCODE_100;
 	e->p.generation		= a->generation;
-	e->p.header[0]		= a->data[0];
-	e->p.header[1]		= a->data[1];
-	e->p.header_length	= 8;
+	e->p.header[0]		= TCODE_LINK_INTERNAL << 4;
+	e->p.header[1]		= a->data[0];
+	e->p.header[2]		= a->data[1];
+	e->p.header_length	= 12;
 	e->p.callback		= outbound_phy_packet_callback;
 	e->phy_packet.closure	= a->closure;
 	e->phy_packet.type	= FW_CDEV_EVENT_PHY_PACKET_SENT;
diff -druNp linux-libre-2.6.37-gnu1/drivers/firewire/core.h linux-libre-2.6.38-gnu1/drivers/firewire/core.h
--- linux-libre-2.6.37-gnu1/drivers/firewire/core.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/firewire/core.h	2011-03-14 21:20:32.000000000 -0400
@@ -215,9 +215,11 @@ static inline bool is_next_generation(in
 
 /* -transaction */
 
+#define TCODE_LINK_INTERNAL		0xe
+
 #define TCODE_IS_READ_REQUEST(tcode)	(((tcode) & ~1) == 4)
 #define TCODE_IS_BLOCK_PACKET(tcode)	(((tcode) &  1) != 0)
-#define TCODE_IS_LINK_INTERNAL(tcode)	((tcode) == 0xe)
+#define TCODE_IS_LINK_INTERNAL(tcode)	((tcode) == TCODE_LINK_INTERNAL)
 #define TCODE_IS_REQUEST(tcode)		(((tcode) &  2) == 0)
 #define TCODE_IS_RESPONSE(tcode)	(((tcode) &  2) != 0)
 #define TCODE_HAS_REQUEST_DATA(tcode)	(((tcode) & 12) != 4)
diff -druNp linux-libre-2.6.37-gnu1/drivers/firewire/core-transaction.c linux-libre-2.6.38-gnu1/drivers/firewire/core-transaction.c
--- linux-libre-2.6.37-gnu1/drivers/firewire/core-transaction.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/firewire/core-transaction.c	2011-03-14 21:20:32.000000000 -0400
@@ -72,6 +72,15 @@
 #define PHY_CONFIG_ROOT_ID(node_id)	((((node_id) & 0x3f) << 24) | (1 << 23))
 #define PHY_IDENTIFIER(id)		((id) << 30)
 
+/* returns 0 if the split timeout handler is already running */
+static int try_cancel_split_timeout(struct fw_transaction *t)
+{
+	if (t->is_split_transaction)
+		return del_timer(&t->split_timeout_timer);
+	else
+		return 1;
+}
+
 static int close_transaction(struct fw_transaction *transaction,
 			     struct fw_card *card, int rcode)
 {
@@ -81,7 +90,7 @@ static int close_transaction(struct fw_t
 	spin_lock_irqsave(&card->lock, flags);
 	list_for_each_entry(t, &card->transaction_list, link) {
 		if (t == transaction) {
-			if (!del_timer(&t->split_timeout_timer)) {
+			if (!try_cancel_split_timeout(t)) {
 				spin_unlock_irqrestore(&card->lock, flags);
 				goto timed_out;
 			}
@@ -141,16 +150,28 @@ static void split_transaction_timeout_ca
 	card->tlabel_mask &= ~(1ULL << t->tlabel);
 	spin_unlock_irqrestore(&card->lock, flags);
 
-	card->driver->cancel_packet(card, &t->packet);
-
-	/*
-	 * At this point cancel_packet will never call the transaction
-	 * callback, since we just took the transaction out of the list.
-	 * So do it here.
-	 */
 	t->callback(card, RCODE_CANCELLED, NULL, 0, t->callback_data);
 }
 
+static void start_split_transaction_timeout(struct fw_transaction *t,
+					    struct fw_card *card)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&card->lock, flags);
+
+	if (list_empty(&t->link) || WARN_ON(t->is_split_transaction)) {
+		spin_unlock_irqrestore(&card->lock, flags);
+		return;
+	}
+
+	t->is_split_transaction = true;
+	mod_timer(&t->split_timeout_timer,
+		  jiffies + card->split_timeout_jiffies);
+
+	spin_unlock_irqrestore(&card->lock, flags);
+}
+
 static void transmit_complete_callback(struct fw_packet *packet,
 				       struct fw_card *card, int status)
 {
@@ -162,7 +183,7 @@ static void transmit_complete_callback(s
 		close_transaction(t, card, RCODE_COMPLETE);
 		break;
 	case ACK_PENDING:
-		t->timestamp = packet->timestamp;
+		start_split_transaction_timeout(t, card);
 		break;
 	case ACK_BUSY_X:
 	case ACK_BUSY_A:
@@ -250,7 +271,7 @@ static void fw_fill_request(struct fw_pa
 		break;
 
 	default:
-		WARN(1, "wrong tcode %d", tcode);
+		WARN(1, "wrong tcode %d\n", tcode);
 	}
  common:
 	packet->speed = speed;
@@ -349,11 +370,9 @@ void fw_send_request(struct fw_card *car
 	t->node_id = destination_id;
 	t->tlabel = tlabel;
 	t->card = card;
+	t->is_split_transaction = false;
 	setup_timer(&t->split_timeout_timer,
 		    split_transaction_timeout_callback, (unsigned long)t);
-	/* FIXME: start this timer later, relative to t->timestamp */
-	mod_timer(&t->split_timeout_timer,
-		  jiffies + card->split_timeout_jiffies);
 	t->callback = callback;
 	t->callback_data = callback_data;
 
@@ -423,7 +442,8 @@ static void transmit_phy_packet_callback
 }
 
 static struct fw_packet phy_config_packet = {
-	.header_length	= 8,
+	.header_length	= 12,
+	.header[0]	= TCODE_LINK_INTERNAL << 4,
 	.payload_length	= 0,
 	.speed		= SCODE_100,
 	.callback	= transmit_phy_packet_callback,
@@ -451,8 +471,8 @@ void fw_send_phy_config(struct fw_card *
 
 	mutex_lock(&phy_config_mutex);
 
-	phy_config_packet.header[0] = data;
-	phy_config_packet.header[1] = ~data;
+	phy_config_packet.header[1] = data;
+	phy_config_packet.header[2] = ~data;
 	phy_config_packet.generation = generation;
 	INIT_COMPLETION(phy_config_done);
 
@@ -638,7 +658,7 @@ int fw_get_response_length(struct fw_req
 		}
 
 	default:
-		WARN(1, "wrong tcode %d", tcode);
+		WARN(1, "wrong tcode %d\n", tcode);
 		return 0;
 	}
 }
@@ -694,7 +714,7 @@ void fw_fill_response(struct fw_packet *
 		break;
 
 	default:
-		WARN(1, "wrong tcode %d", tcode);
+		WARN(1, "wrong tcode %d\n", tcode);
 	}
 
 	response->payload_mapped = false;
@@ -925,7 +945,7 @@ void fw_core_handle_response(struct fw_c
 	spin_lock_irqsave(&card->lock, flags);
 	list_for_each_entry(t, &card->transaction_list, link) {
 		if (t->node_id == source && t->tlabel == tlabel) {
-			if (!del_timer(&t->split_timeout_timer)) {
+			if (!try_cancel_split_timeout(t)) {
 				spin_unlock_irqrestore(&card->lock, flags);
 				goto timed_out;
 			}
diff -druNp linux-libre-2.6.37-gnu1/drivers/firewire/Kconfig linux-libre-2.6.38-gnu1/drivers/firewire/Kconfig
--- linux-libre-2.6.37-gnu1/drivers/firewire/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/firewire/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -19,7 +19,7 @@ config FIREWIRE
 
 config FIREWIRE_OHCI
 	tristate "OHCI-1394 controllers"
-	depends on PCI && FIREWIRE
+	depends on PCI && FIREWIRE && MMU
 	help
 	  Enable this driver if you have a FireWire controller based
 	  on the OHCI specification.  For all practical purposes, this
@@ -49,15 +49,13 @@ config FIREWIRE_SBP2
 	  configuration section.
 
 config FIREWIRE_NET
-	tristate "IP networking over 1394 (EXPERIMENTAL)"
-	depends on FIREWIRE && INET && EXPERIMENTAL
+	tristate "IP networking over 1394"
+	depends on FIREWIRE && INET
 	help
 	  This enables IPv4 over IEEE 1394, providing IP connectivity with
 	  other implementations of RFC 2734 as found on several operating
 	  systems.  Multicast support is currently limited.
 
-	  NOTE, this driver is not stable yet!
-
 	  To compile this driver as a module, say M here:  The module will be
 	  called firewire-net.
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/firewire/net.c linux-libre-2.6.38-gnu1/drivers/firewire/net.c
--- linux-libre-2.6.37-gnu1/drivers/firewire/net.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/firewire/net.c	2011-03-14 21:20:32.000000000 -0400
@@ -9,6 +9,7 @@
 #include <linux/bug.h>
 #include <linux/delay.h>
 #include <linux/device.h>
+#include <linux/ethtool.h>
 #include <linux/firewire.h>
 #include <linux/firewire-constants.h>
 #include <linux/highmem.h>
@@ -179,6 +180,7 @@ struct fwnet_device {
 	/* Number of tx datagrams that have been queued but not yet acked */
 	int queued_datagrams;
 
+	int peer_count;
 	struct list_head peer_list;
 	struct fw_card *card;
 	struct net_device *netdev;
@@ -189,6 +191,7 @@ struct fwnet_peer {
 	struct fwnet_device *dev;
 	u64 guid;
 	u64 fifo;
+	__be32 ip;
 
 	/* guarded by dev->lock */
 	struct list_head pd_list; /* received partial datagrams */
@@ -568,6 +571,8 @@ static int fwnet_finish_incoming_packet(
 				peer->speed = sspd;
 			if (peer->max_payload > max_payload)
 				peer->max_payload = max_payload;
+
+			peer->ip = arp1394->sip;
 		}
 		spin_unlock_irqrestore(&dev->lock, flags);
 
@@ -996,15 +1001,23 @@ static void fwnet_transmit_packet_failed
 static void fwnet_write_complete(struct fw_card *card, int rcode,
 				 void *payload, size_t length, void *data)
 {
-	struct fwnet_packet_task *ptask;
-
-	ptask = data;
+	struct fwnet_packet_task *ptask = data;
+	static unsigned long j;
+	static int last_rcode, errors_skipped;
 
 	if (rcode == RCODE_COMPLETE) {
 		fwnet_transmit_packet_done(ptask);
 	} else {
-		fw_error("fwnet_write_complete: failed: %x\n", rcode);
 		fwnet_transmit_packet_failed(ptask);
+
+		if (printk_timed_ratelimit(&j,  1000) || rcode != last_rcode) {
+			fw_error("fwnet_write_complete: "
+				"failed: %x (skipped %d)\n", rcode, errors_skipped);
+
+			errors_skipped = 0;
+			last_rcode = rcode;
+		} else
+			errors_skipped++;
 	}
 }
 
@@ -1213,6 +1226,14 @@ static int fwnet_broadcast_start(struct
 	return retval;
 }
 
+static void set_carrier_state(struct fwnet_device *dev)
+{
+	if (dev->peer_count > 1)
+		netif_carrier_on(dev->netdev);
+	else
+		netif_carrier_off(dev->netdev);
+}
+
 /* ifup */
 static int fwnet_open(struct net_device *net)
 {
@@ -1226,6 +1247,10 @@ static int fwnet_open(struct net_device
 	}
 	netif_start_queue(net);
 
+	spin_lock_irq(&dev->lock);
+	set_carrier_state(dev);
+	spin_unlock_irq(&dev->lock);
+
 	return 0;
 }
 
@@ -1397,6 +1422,10 @@ static int fwnet_change_mtu(struct net_d
 	return 0;
 }
 
+static const struct ethtool_ops fwnet_ethtool_ops = {
+	.get_link	= ethtool_op_get_link,
+};
+
 static const struct net_device_ops fwnet_netdev_ops = {
 	.ndo_open       = fwnet_open,
 	.ndo_stop	= fwnet_stop,
@@ -1415,6 +1444,7 @@ static void fwnet_init_dev(struct net_de
 	net->hard_header_len	= FWNET_HLEN;
 	net->type		= ARPHRD_IEEE1394;
 	net->tx_queue_len	= FWNET_TX_QUEUE_LEN;
+	net->ethtool_ops	= &fwnet_ethtool_ops;
 }
 
 /* caller must hold fwnet_device_mutex */
@@ -1443,6 +1473,7 @@ static int fwnet_add_peer(struct fwnet_d
 	peer->dev = dev;
 	peer->guid = (u64)device->config_rom[3] << 32 | device->config_rom[4];
 	peer->fifo = FWNET_NO_FIFO_ADDR;
+	peer->ip = 0;
 	INIT_LIST_HEAD(&peer->pd_list);
 	peer->pdg_size = 0;
 	peer->datagram_label = 0;
@@ -1455,6 +1486,8 @@ static int fwnet_add_peer(struct fwnet_d
 
 	spin_lock_irq(&dev->lock);
 	list_add_tail(&peer->peer_link, &dev->peer_list);
+	dev->peer_count++;
+	set_carrier_state(dev);
 	spin_unlock_irq(&dev->lock);
 
 	return 0;
@@ -1535,13 +1568,15 @@ static int fwnet_probe(struct device *_d
 	return ret;
 }
 
-static void fwnet_remove_peer(struct fwnet_peer *peer)
+static void fwnet_remove_peer(struct fwnet_peer *peer, struct fwnet_device *dev)
 {
 	struct fwnet_partial_datagram *pd, *pd_next;
 
-	spin_lock_irq(&peer->dev->lock);
+	spin_lock_irq(&dev->lock);
 	list_del(&peer->peer_link);
-	spin_unlock_irq(&peer->dev->lock);
+	dev->peer_count--;
+	set_carrier_state(dev);
+	spin_unlock_irq(&dev->lock);
 
 	list_for_each_entry_safe(pd, pd_next, &peer->pd_list, pd_link)
 		fwnet_pd_delete(pd);
@@ -1558,10 +1593,13 @@ static int fwnet_remove(struct device *_
 
 	mutex_lock(&fwnet_device_mutex);
 
-	fwnet_remove_peer(peer);
+	net = dev->netdev;
+	if (net && peer->ip)
+		arp_invalidate(net, peer->ip);
+
+	fwnet_remove_peer(peer, dev);
 
 	if (list_empty(&dev->peer_list)) {
-		net = dev->netdev;
 		unregister_netdev(net);
 
 		if (dev->local_fifo != FWNET_NO_FIFO_ADDR)
diff -druNp linux-libre-2.6.37-gnu1/drivers/firewire/nosy.c linux-libre-2.6.38-gnu1/drivers/firewire/nosy.c
--- linux-libre-2.6.37-gnu1/drivers/firewire/nosy.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/firewire/nosy.c	2011-03-14 21:20:32.000000000 -0400
@@ -302,7 +302,7 @@ nosy_open(struct inode *inode, struct fi
 
 	file->private_data = client;
 
-	return 0;
+	return nonseekable_open(inode, file);
 fail:
 	kfree(client);
 	lynx_put(lynx);
@@ -405,7 +405,6 @@ static const struct file_operations nosy
 	.poll =			nosy_poll,
 	.open =			nosy_open,
 	.release =		nosy_release,
-	.llseek =		noop_llseek,
 };
 
 #define PHY_PACKET_SIZE 12 /* 1 payload, 1 inverse, 1 ack = 3 quadlets */
diff -druNp linux-libre-2.6.37-gnu1/drivers/firewire/ohci.c linux-libre-2.6.38-gnu1/drivers/firewire/ohci.c
--- linux-libre-2.6.37-gnu1/drivers/firewire/ohci.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/firewire/ohci.c	2011-03-14 21:20:32.000000000 -0400
@@ -18,6 +18,7 @@
  * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  */
 
+#include <linux/bitops.h>
 #include <linux/bug.h>
 #include <linux/compiler.h>
 #include <linux/delay.h>
@@ -40,6 +41,7 @@
 #include <linux/spinlock.h>
 #include <linux/string.h>
 #include <linux/time.h>
+#include <linux/vmalloc.h>
 
 #include <asm/byteorder.h>
 #include <asm/page.h>
@@ -80,17 +82,23 @@ struct descriptor {
 #define COMMAND_PTR(regs)	((regs) + 12)
 #define CONTEXT_MATCH(regs)	((regs) + 16)
 
-struct ar_buffer {
-	struct descriptor descriptor;
-	struct ar_buffer *next;
-	__le32 data[0];
-};
+#define AR_BUFFER_SIZE	(32*1024)
+#define AR_BUFFERS_MIN	DIV_ROUND_UP(AR_BUFFER_SIZE, PAGE_SIZE)
+/* we need at least two pages for proper list management */
+#define AR_BUFFERS	(AR_BUFFERS_MIN >= 2 ? AR_BUFFERS_MIN : 2)
+
+#define MAX_ASYNC_PAYLOAD	4096
+#define MAX_AR_PACKET_SIZE	(16 + MAX_ASYNC_PAYLOAD + 4)
+#define AR_WRAPAROUND_PAGES	DIV_ROUND_UP(MAX_AR_PACKET_SIZE, PAGE_SIZE)
 
 struct ar_context {
 	struct fw_ohci *ohci;
-	struct ar_buffer *current_buffer;
-	struct ar_buffer *last_buffer;
+	struct page *pages[AR_BUFFERS];
+	void *buffer;
+	struct descriptor *descriptors;
+	dma_addr_t descriptors_bus;
 	void *pointer;
+	unsigned int last_buffer_index;
 	u32 regs;
 	struct tasklet_struct tasklet;
 };
@@ -117,6 +125,8 @@ struct context {
 	struct fw_ohci *ohci;
 	u32 regs;
 	int total_allocation;
+	bool running;
+	bool flushing;
 
 	/*
 	 * List of page-sized buffers for storing DMA descriptors.
@@ -161,6 +171,9 @@ struct iso_context {
 	int excess_bytes;
 	void *header;
 	size_t header_length;
+
+	u8 sync;
+	u8 tags;
 };
 
 #define CONFIG_ROM_SIZE 1024
@@ -177,7 +190,8 @@ struct fw_ohci {
 	u32 bus_time;
 	bool is_root;
 	bool csr_state_setclear_abdicate;
-
+	int n_ir;
+	int n_it;
 	/*
 	 * Spinlock for accessing fw_ohci data.  Never call out of
 	 * this driver with this lock held.
@@ -186,6 +200,9 @@ struct fw_ohci {
 
 	struct mutex phy_reg_mutex;
 
+	void *misc_buffer;
+	dma_addr_t misc_buffer_bus;
+
 	struct ar_context ar_request_ctx;
 	struct ar_context ar_response_ctx;
 	struct context at_request_ctx;
@@ -411,10 +428,6 @@ static const char *tcodes[] = {
 	[0xc] = "-reserved-",		[0xd] = "-reserved-",
 	[0xe] = "link internal",	[0xf] = "-reserved-",
 };
-static const char *phys[] = {
-	[0x0] = "phy config packet",	[0x1] = "link-on packet",
-	[0x2] = "self-id packet",	[0x3] = "-reserved-",
-};
 
 static void log_ar_at_event(char dir, int speed, u32 *header, int evt)
 {
@@ -433,12 +446,6 @@ static void log_ar_at_event(char dir, in
 		return;
 	}
 
-	if (header[0] == ~header[1]) {
-		fw_notify("A%c %s, %s, %08x\n",
-		    dir, evts[evt], phys[header[0] >> 30 & 0x3], header[0]);
-		return;
-	}
-
 	switch (tcode) {
 	case 0x0: case 0x6: case 0x8:
 		snprintf(specific, sizeof(specific), " = %08x",
@@ -453,9 +460,13 @@ static void log_ar_at_event(char dir, in
 	}
 
 	switch (tcode) {
-	case 0xe: case 0xa:
+	case 0xa:
 		fw_notify("A%c %s, %s\n", dir, evts[evt], tcodes[tcode]);
 		break;
+	case 0xe:
+		fw_notify("A%c %s, PHY %08x %08x\n",
+			  dir, evts[evt], header[1], header[2]);
+		break;
 	case 0x0: case 0x1: case 0x4: case 0x5: case 0x9:
 		fw_notify("A%c spd %x tl %02x, "
 		    "%04x -> %04x, %s, "
@@ -594,59 +605,150 @@ static int ohci_update_phy_reg(struct fw
 	return ret;
 }
 
-static void ar_context_link_page(struct ar_context *ctx,
-				 struct ar_buffer *ab, dma_addr_t ab_bus)
+static inline dma_addr_t ar_buffer_bus(struct ar_context *ctx, unsigned int i)
 {
-	size_t offset;
+	return page_private(ctx->pages[i]);
+}
 
-	ab->next = NULL;
-	memset(&ab->descriptor, 0, sizeof(ab->descriptor));
-	ab->descriptor.control        = cpu_to_le16(DESCRIPTOR_INPUT_MORE |
-						    DESCRIPTOR_STATUS |
-						    DESCRIPTOR_BRANCH_ALWAYS);
-	offset = offsetof(struct ar_buffer, data);
-	ab->descriptor.req_count      = cpu_to_le16(PAGE_SIZE - offset);
-	ab->descriptor.data_address   = cpu_to_le32(ab_bus + offset);
-	ab->descriptor.res_count      = cpu_to_le16(PAGE_SIZE - offset);
-	ab->descriptor.branch_address = 0;
+static void ar_context_link_page(struct ar_context *ctx, unsigned int index)
+{
+	struct descriptor *d;
+
+	d = &ctx->descriptors[index];
+	d->branch_address  &= cpu_to_le32(~0xf);
+	d->res_count       =  cpu_to_le16(PAGE_SIZE);
+	d->transfer_status =  0;
 
 	wmb(); /* finish init of new descriptors before branch_address update */
-	ctx->last_buffer->descriptor.branch_address = cpu_to_le32(ab_bus | 1);
-	ctx->last_buffer->next = ab;
-	ctx->last_buffer = ab;
+	d = &ctx->descriptors[ctx->last_buffer_index];
+	d->branch_address  |= cpu_to_le32(1);
+
+	ctx->last_buffer_index = index;
 
 	reg_write(ctx->ohci, CONTROL_SET(ctx->regs), CONTEXT_WAKE);
 	flush_writes(ctx->ohci);
 }
 
-static int ar_context_add_page(struct ar_context *ctx)
+static void ar_context_release(struct ar_context *ctx)
 {
-	struct device *dev = ctx->ohci->card.device;
-	struct ar_buffer *ab;
-	dma_addr_t uninitialized_var(ab_bus);
+	unsigned int i;
 
-	ab = dma_alloc_coherent(dev, PAGE_SIZE, &ab_bus, GFP_ATOMIC);
-	if (ab == NULL)
-		return -ENOMEM;
+	if (ctx->buffer)
+		vm_unmap_ram(ctx->buffer, AR_BUFFERS + AR_WRAPAROUND_PAGES);
 
-	ar_context_link_page(ctx, ab, ab_bus);
+	for (i = 0; i < AR_BUFFERS; i++)
+		if (ctx->pages[i]) {
+			dma_unmap_page(ctx->ohci->card.device,
+				       ar_buffer_bus(ctx, i),
+				       PAGE_SIZE, DMA_FROM_DEVICE);
+			__free_page(ctx->pages[i]);
+		}
+}
 
-	return 0;
+static void ar_context_abort(struct ar_context *ctx, const char *error_msg)
+{
+	if (reg_read(ctx->ohci, CONTROL_CLEAR(ctx->regs)) & CONTEXT_RUN) {
+		reg_write(ctx->ohci, CONTROL_CLEAR(ctx->regs), CONTEXT_RUN);
+		flush_writes(ctx->ohci);
+
+		fw_error("AR error: %s; DMA stopped\n", error_msg);
+	}
+	/* FIXME: restart? */
 }
 
-static void ar_context_release(struct ar_context *ctx)
+static inline unsigned int ar_next_buffer_index(unsigned int index)
 {
-	struct ar_buffer *ab, *ab_next;
-	size_t offset;
-	dma_addr_t ab_bus;
+	return (index + 1) % AR_BUFFERS;
+}
 
-	for (ab = ctx->current_buffer; ab; ab = ab_next) {
-		ab_next = ab->next;
-		offset = offsetof(struct ar_buffer, data);
-		ab_bus = le32_to_cpu(ab->descriptor.data_address) - offset;
-		dma_free_coherent(ctx->ohci->card.device, PAGE_SIZE,
-				  ab, ab_bus);
+static inline unsigned int ar_prev_buffer_index(unsigned int index)
+{
+	return (index - 1 + AR_BUFFERS) % AR_BUFFERS;
+}
+
+static inline unsigned int ar_first_buffer_index(struct ar_context *ctx)
+{
+	return ar_next_buffer_index(ctx->last_buffer_index);
+}
+
+/*
+ * We search for the buffer that contains the last AR packet DMA data written
+ * by the controller.
+ */
+static unsigned int ar_search_last_active_buffer(struct ar_context *ctx,
+						 unsigned int *buffer_offset)
+{
+	unsigned int i, next_i, last = ctx->last_buffer_index;
+	__le16 res_count, next_res_count;
+
+	i = ar_first_buffer_index(ctx);
+	res_count = ACCESS_ONCE(ctx->descriptors[i].res_count);
+
+	/* A buffer that is not yet completely filled must be the last one. */
+	while (i != last && res_count == 0) {
+
+		/* Peek at the next descriptor. */
+		next_i = ar_next_buffer_index(i);
+		rmb(); /* read descriptors in order */
+		next_res_count = ACCESS_ONCE(
+				ctx->descriptors[next_i].res_count);
+		/*
+		 * If the next descriptor is still empty, we must stop at this
+		 * descriptor.
+		 */
+		if (next_res_count == cpu_to_le16(PAGE_SIZE)) {
+			/*
+			 * The exception is when the DMA data for one packet is
+			 * split over three buffers; in this case, the middle
+			 * buffer's descriptor might be never updated by the
+			 * controller and look still empty, and we have to peek
+			 * at the third one.
+			 */
+			if (MAX_AR_PACKET_SIZE > PAGE_SIZE && i != last) {
+				next_i = ar_next_buffer_index(next_i);
+				rmb();
+				next_res_count = ACCESS_ONCE(
+					ctx->descriptors[next_i].res_count);
+				if (next_res_count != cpu_to_le16(PAGE_SIZE))
+					goto next_buffer_is_active;
+			}
+
+			break;
+		}
+
+next_buffer_is_active:
+		i = next_i;
+		res_count = next_res_count;
+	}
+
+	rmb(); /* read res_count before the DMA data */
+
+	*buffer_offset = PAGE_SIZE - le16_to_cpu(res_count);
+	if (*buffer_offset > PAGE_SIZE) {
+		*buffer_offset = 0;
+		ar_context_abort(ctx, "corrupted descriptor");
 	}
+
+	return i;
+}
+
+static void ar_sync_buffers_for_cpu(struct ar_context *ctx,
+				    unsigned int end_buffer_index,
+				    unsigned int end_buffer_offset)
+{
+	unsigned int i;
+
+	i = ar_first_buffer_index(ctx);
+	while (i != end_buffer_index) {
+		dma_sync_single_for_cpu(ctx->ohci->card.device,
+					ar_buffer_bus(ctx, i),
+					PAGE_SIZE, DMA_FROM_DEVICE);
+		i = ar_next_buffer_index(i);
+	}
+	if (end_buffer_offset > 0)
+		dma_sync_single_for_cpu(ctx->ohci->card.device,
+					ar_buffer_bus(ctx, i),
+					end_buffer_offset, DMA_FROM_DEVICE);
 }
 
 #if defined(CONFIG_PPC_PMAC) && defined(CONFIG_PPC32)
@@ -689,6 +791,10 @@ static __le32 *handle_ar_packet(struct a
 		p.header[3] = cond_le32_to_cpu(buffer[3]);
 		p.header_length = 16;
 		p.payload_length = p.header[3] >> 16;
+		if (p.payload_length > MAX_ASYNC_PAYLOAD) {
+			ar_context_abort(ctx, "invalid packet length");
+			return NULL;
+		}
 		break;
 
 	case TCODE_WRITE_RESPONSE:
@@ -699,9 +805,8 @@ static __le32 *handle_ar_packet(struct a
 		break;
 
 	default:
-		/* FIXME: Stop context, discard everything, and restart? */
-		p.header_length = 0;
-		p.payload_length = 0;
+		ar_context_abort(ctx, "invalid tcode");
+		return NULL;
 	}
 
 	p.payload = (void *) buffer + p.header_length;
@@ -751,121 +856,147 @@ static __le32 *handle_ar_packet(struct a
 	return buffer + length + 1;
 }
 
-static void ar_context_tasklet(unsigned long data)
+static void *handle_ar_packets(struct ar_context *ctx, void *p, void *end)
 {
-	struct ar_context *ctx = (struct ar_context *)data;
-	struct ar_buffer *ab;
-	struct descriptor *d;
-	void *buffer, *end;
-	__le16 res_count;
+	void *next;
 
-	ab = ctx->current_buffer;
-	d = &ab->descriptor;
+	while (p < end) {
+		next = handle_ar_packet(ctx, p);
+		if (!next)
+			return p;
+		p = next;
+	}
 
-	res_count = ACCESS_ONCE(d->res_count);
-	if (res_count == 0) {
-		size_t size, size2, rest, pktsize, size3, offset;
-		dma_addr_t start_bus;
-		void *start;
+	return p;
+}
 
-		/*
-		 * This descriptor is finished and we may have a
-		 * packet split across this and the next buffer. We
-		 * reuse the page for reassembling the split packet.
-		 */
+static void ar_recycle_buffers(struct ar_context *ctx, unsigned int end_buffer)
+{
+	unsigned int i;
 
-		offset = offsetof(struct ar_buffer, data);
-		start = ab;
-		start_bus = le32_to_cpu(ab->descriptor.data_address) - offset;
-		buffer = ab->data;
+	i = ar_first_buffer_index(ctx);
+	while (i != end_buffer) {
+		dma_sync_single_for_device(ctx->ohci->card.device,
+					   ar_buffer_bus(ctx, i),
+					   PAGE_SIZE, DMA_FROM_DEVICE);
+		ar_context_link_page(ctx, i);
+		i = ar_next_buffer_index(i);
+	}
+}
 
-		ab = ab->next;
-		d = &ab->descriptor;
-		size = start + PAGE_SIZE - ctx->pointer;
-		/* valid buffer data in the next page */
-		rest = le16_to_cpu(d->req_count) - le16_to_cpu(d->res_count);
-		/* what actually fits in this page */
-		size2 = min(rest, (size_t)PAGE_SIZE - offset - size);
-		memmove(buffer, ctx->pointer, size);
-		memcpy(buffer + size, ab->data, size2);
+static void ar_context_tasklet(unsigned long data)
+{
+	struct ar_context *ctx = (struct ar_context *)data;
+	unsigned int end_buffer_index, end_buffer_offset;
+	void *p, *end;
 
-		while (size > 0) {
-			void *next = handle_ar_packet(ctx, buffer);
-			pktsize = next - buffer;
-			if (pktsize >= size) {
-				/*
-				 * We have handled all the data that was
-				 * originally in this page, so we can now
-				 * continue in the next page.
-				 */
-				buffer = next;
-				break;
-			}
-			/* move the next packet to the start of the buffer */
-			memmove(buffer, next, size + size2 - pktsize);
-			size -= pktsize;
-			/* fill up this page again */
-			size3 = min(rest - size2,
-				    (size_t)PAGE_SIZE - offset - size - size2);
-			memcpy(buffer + size + size2,
-			       (void *) ab->data + size2, size3);
-			size2 += size3;
-		}
+	p = ctx->pointer;
+	if (!p)
+		return;
 
-		if (rest > 0) {
-			/* handle the packets that are fully in the next page */
-			buffer = (void *) ab->data +
-					(buffer - (start + offset + size));
-			end = (void *) ab->data + rest;
+	end_buffer_index = ar_search_last_active_buffer(ctx,
+							&end_buffer_offset);
+	ar_sync_buffers_for_cpu(ctx, end_buffer_index, end_buffer_offset);
+	end = ctx->buffer + end_buffer_index * PAGE_SIZE + end_buffer_offset;
 
-			while (buffer < end)
-				buffer = handle_ar_packet(ctx, buffer);
+	if (end_buffer_index < ar_first_buffer_index(ctx)) {
+		/*
+		 * The filled part of the overall buffer wraps around; handle
+		 * all packets up to the buffer end here.  If the last packet
+		 * wraps around, its tail will be visible after the buffer end
+		 * because the buffer start pages are mapped there again.
+		 */
+		void *buffer_end = ctx->buffer + AR_BUFFERS * PAGE_SIZE;
+		p = handle_ar_packets(ctx, p, buffer_end);
+		if (p < buffer_end)
+			goto error;
+		/* adjust p to point back into the actual buffer */
+		p -= AR_BUFFERS * PAGE_SIZE;
+	}
 
-			ctx->current_buffer = ab;
-			ctx->pointer = end;
+	p = handle_ar_packets(ctx, p, end);
+	if (p != end) {
+		if (p > end)
+			ar_context_abort(ctx, "inconsistent descriptor");
+		goto error;
+	}
 
-			ar_context_link_page(ctx, start, start_bus);
-		} else {
-			ctx->pointer = start + PAGE_SIZE;
-		}
-	} else {
-		buffer = ctx->pointer;
-		ctx->pointer = end =
-			(void *) ab + PAGE_SIZE - le16_to_cpu(res_count);
+	ctx->pointer = p;
+	ar_recycle_buffers(ctx, end_buffer_index);
 
-		while (buffer < end)
-			buffer = handle_ar_packet(ctx, buffer);
-	}
+	return;
+
+error:
+	ctx->pointer = NULL;
 }
 
-static int ar_context_init(struct ar_context *ctx,
-			   struct fw_ohci *ohci, u32 regs)
+static int ar_context_init(struct ar_context *ctx, struct fw_ohci *ohci,
+			   unsigned int descriptors_offset, u32 regs)
 {
-	struct ar_buffer ab;
+	unsigned int i;
+	dma_addr_t dma_addr;
+	struct page *pages[AR_BUFFERS + AR_WRAPAROUND_PAGES];
+	struct descriptor *d;
 
 	ctx->regs        = regs;
 	ctx->ohci        = ohci;
-	ctx->last_buffer = &ab;
 	tasklet_init(&ctx->tasklet, ar_context_tasklet, (unsigned long)ctx);
 
-	ar_context_add_page(ctx);
-	ar_context_add_page(ctx);
-	ctx->current_buffer = ab.next;
-	ctx->pointer = ctx->current_buffer->data;
+	for (i = 0; i < AR_BUFFERS; i++) {
+		ctx->pages[i] = alloc_page(GFP_KERNEL | GFP_DMA32);
+		if (!ctx->pages[i])
+			goto out_of_memory;
+		dma_addr = dma_map_page(ohci->card.device, ctx->pages[i],
+					0, PAGE_SIZE, DMA_FROM_DEVICE);
+		if (dma_mapping_error(ohci->card.device, dma_addr)) {
+			__free_page(ctx->pages[i]);
+			ctx->pages[i] = NULL;
+			goto out_of_memory;
+		}
+		set_page_private(ctx->pages[i], dma_addr);
+	}
+
+	for (i = 0; i < AR_BUFFERS; i++)
+		pages[i]              = ctx->pages[i];
+	for (i = 0; i < AR_WRAPAROUND_PAGES; i++)
+		pages[AR_BUFFERS + i] = ctx->pages[i];
+	ctx->buffer = vm_map_ram(pages, AR_BUFFERS + AR_WRAPAROUND_PAGES,
+				 -1, PAGE_KERNEL);
+	if (!ctx->buffer)
+		goto out_of_memory;
+
+	ctx->descriptors     = ohci->misc_buffer     + descriptors_offset;
+	ctx->descriptors_bus = ohci->misc_buffer_bus + descriptors_offset;
+
+	for (i = 0; i < AR_BUFFERS; i++) {
+		d = &ctx->descriptors[i];
+		d->req_count      = cpu_to_le16(PAGE_SIZE);
+		d->control        = cpu_to_le16(DESCRIPTOR_INPUT_MORE |
+						DESCRIPTOR_STATUS |
+						DESCRIPTOR_BRANCH_ALWAYS);
+		d->data_address   = cpu_to_le32(ar_buffer_bus(ctx, i));
+		d->branch_address = cpu_to_le32(ctx->descriptors_bus +
+			ar_next_buffer_index(i) * sizeof(struct descriptor));
+	}
 
 	return 0;
+
+out_of_memory:
+	ar_context_release(ctx);
+
+	return -ENOMEM;
 }
 
 static void ar_context_run(struct ar_context *ctx)
 {
-	struct ar_buffer *ab = ctx->current_buffer;
-	dma_addr_t ab_bus;
-	size_t offset;
+	unsigned int i;
 
-	offset = offsetof(struct ar_buffer, data);
-	ab_bus = le32_to_cpu(ab->descriptor.data_address) - offset;
+	for (i = 0; i < AR_BUFFERS; i++)
+		ar_context_link_page(ctx, i);
 
-	reg_write(ctx->ohci, COMMAND_PTR(ctx->regs), ab_bus | 1);
+	ctx->pointer = ctx->buffer;
+
+	reg_write(ctx->ohci, COMMAND_PTR(ctx->regs), ctx->descriptors_bus | 1);
 	reg_write(ctx->ohci, CONTROL_SET(ctx->regs), CONTEXT_RUN);
 	flush_writes(ctx->ohci);
 }
@@ -1042,6 +1173,7 @@ static void context_run(struct context *
 		  le32_to_cpu(ctx->last->branch_address));
 	reg_write(ohci, CONTROL_CLEAR(ctx->regs), ~0);
 	reg_write(ohci, CONTROL_SET(ctx->regs), CONTEXT_RUN | extra);
+	ctx->running = true;
 	flush_writes(ohci);
 }
 
@@ -1069,6 +1201,7 @@ static void context_stop(struct context
 	int i;
 
 	reg_write(ctx->ohci, CONTROL_CLEAR(ctx->regs), CONTEXT_RUN);
+	ctx->running = false;
 	flush_writes(ctx->ohci);
 
 	for (i = 0; i < 10; i++) {
@@ -1099,7 +1232,6 @@ static int at_context_queue_packet(struc
 	struct descriptor *d, *last;
 	__le32 *header;
 	int z, tcode;
-	u32 reg;
 
 	d = context_get_descriptors(ctx, 4, &d_bus);
 	if (d == NULL) {
@@ -1113,21 +1245,27 @@ static int at_context_queue_packet(struc
 	/*
 	 * The DMA format for asyncronous link packets is different
 	 * from the IEEE1394 layout, so shift the fields around
-	 * accordingly.  If header_length is 8, it's a PHY packet, to
-	 * which we need to prepend an extra quadlet.
+	 * accordingly.
 	 */
 
+	tcode = (packet->header[0] >> 4) & 0x0f;
 	header = (__le32 *) &d[1];
-	switch (packet->header_length) {
-	case 16:
-	case 12:
+	switch (tcode) {
+	case TCODE_WRITE_QUADLET_REQUEST:
+	case TCODE_WRITE_BLOCK_REQUEST:
+	case TCODE_WRITE_RESPONSE:
+	case TCODE_READ_QUADLET_REQUEST:
+	case TCODE_READ_BLOCK_REQUEST:
+	case TCODE_READ_QUADLET_RESPONSE:
+	case TCODE_READ_BLOCK_RESPONSE:
+	case TCODE_LOCK_REQUEST:
+	case TCODE_LOCK_RESPONSE:
 		header[0] = cpu_to_le32((packet->header[0] & 0xffff) |
 					(packet->speed << 16));
 		header[1] = cpu_to_le32((packet->header[1] & 0xffff) |
 					(packet->header[0] & 0xffff0000));
 		header[2] = cpu_to_le32(packet->header[2]);
 
-		tcode = (packet->header[0] >> 4) & 0x0f;
 		if (TCODE_IS_BLOCK_PACKET(tcode))
 			header[3] = cpu_to_le32(packet->header[3]);
 		else
@@ -1136,18 +1274,18 @@ static int at_context_queue_packet(struc
 		d[0].req_count = cpu_to_le16(packet->header_length);
 		break;
 
-	case 8:
+	case TCODE_LINK_INTERNAL:
 		header[0] = cpu_to_le32((OHCI1394_phy_tcode << 4) |
 					(packet->speed << 16));
-		header[1] = cpu_to_le32(packet->header[0]);
-		header[2] = cpu_to_le32(packet->header[1]);
+		header[1] = cpu_to_le32(packet->header[1]);
+		header[2] = cpu_to_le32(packet->header[2]);
 		d[0].req_count = cpu_to_le16(12);
 
-		if (is_ping_packet(packet->header))
+		if (is_ping_packet(&packet->header[1]))
 			d[0].control |= cpu_to_le16(DESCRIPTOR_PING);
 		break;
 
-	case 4:
+	case TCODE_STREAM_DATA:
 		header[0] = cpu_to_le32((packet->header[0] & 0xffff) |
 					(packet->speed << 16));
 		header[1] = cpu_to_le32(packet->header[0] & 0xffff0000);
@@ -1197,6 +1335,8 @@ static int at_context_queue_packet(struc
 	 * some controllers (like a JMicron JMB381 PCI-e) misbehave and wind
 	 * up stalling out.  So we just bail out in software and try again
 	 * later, and everyone is happy.
+	 * FIXME: Test of IntEvent.busReset may no longer be necessary since we
+	 *        flush AT queues in bus_reset_tasklet.
 	 * FIXME: Document how the locking works.
 	 */
 	if (ohci->generation != packet->generation ||
@@ -1210,14 +1350,23 @@ static int at_context_queue_packet(struc
 
 	context_append(ctx, d, z, 4 - z);
 
-	/* If the context isn't already running, start it up. */
-	reg = reg_read(ctx->ohci, CONTROL_SET(ctx->regs));
-	if ((reg & CONTEXT_RUN) == 0)
+	if (!ctx->running)
 		context_run(ctx, 0);
 
 	return 0;
 }
 
+static void at_context_flush(struct context *ctx)
+{
+	tasklet_disable(&ctx->tasklet);
+
+	ctx->flushing = true;
+	context_tasklet((unsigned long)ctx);
+	ctx->flushing = false;
+
+	tasklet_enable(&ctx->tasklet);
+}
+
 static int handle_at_packet(struct context *context,
 			    struct descriptor *d,
 			    struct descriptor *last)
@@ -1227,7 +1376,7 @@ static int handle_at_packet(struct conte
 	struct fw_ohci *ohci = context->ohci;
 	int evt;
 
-	if (last->transfer_status == 0)
+	if (last->transfer_status == 0 && !context->flushing)
 		/* This descriptor isn't done yet, stop iteration. */
 		return 0;
 
@@ -1261,11 +1410,15 @@ static int handle_at_packet(struct conte
 		break;
 
 	case OHCI1394_evt_missing_ack:
-		/*
-		 * Using a valid (current) generation count, but the
-		 * node is not on the bus or not sending acks.
-		 */
-		packet->ack = RCODE_NO_ACK;
+		if (context->flushing)
+			packet->ack = RCODE_GENERATION;
+		else {
+			/*
+			 * Using a valid (current) generation count, but the
+			 * node is not on the bus or not sending acks.
+			 */
+			packet->ack = RCODE_NO_ACK;
+		}
 		break;
 
 	case ACK_COMPLETE + 0x10:
@@ -1278,6 +1431,13 @@ static int handle_at_packet(struct conte
 		packet->ack = evt - 0x10;
 		break;
 
+	case OHCI1394_evt_no_status:
+		if (context->flushing) {
+			packet->ack = RCODE_GENERATION;
+			break;
+		}
+		/* fall through */
+
 	default:
 		packet->ack = RCODE_SEND_ERROR;
 		break;
@@ -1583,9 +1743,23 @@ static void bus_reset_tasklet(unsigned l
 	/* FIXME: Document how the locking works. */
 	spin_lock_irqsave(&ohci->lock, flags);
 
-	ohci->generation = generation;
+	ohci->generation = -1; /* prevent AT packet queueing */
 	context_stop(&ohci->at_request_ctx);
 	context_stop(&ohci->at_response_ctx);
+
+	spin_unlock_irqrestore(&ohci->lock, flags);
+
+	/*
+	 * Per OHCI 1.2 draft, clause 7.2.3.3, hardware may leave unsent
+	 * packets in the AT queues and software needs to drain them.
+	 * Some OHCI 1.1 controllers (JMicron) apparently require this too.
+	 */
+	at_context_flush(&ohci->at_request_ctx);
+	at_context_flush(&ohci->at_response_ctx);
+
+	spin_lock_irqsave(&ohci->lock, flags);
+
+	ohci->generation = generation;
 	reg_write(ohci, OHCI1394_IntEventClear, OHCI1394_busReset);
 
 	if (ohci->quirks & QUIRK_RESET_PACKET)
@@ -1653,8 +1827,12 @@ static irqreturn_t irq_handler(int irq,
 	if (!event || !~event)
 		return IRQ_NONE;
 
-	/* busReset must not be cleared yet, see OHCI 1.1 clause 7.2.3.2 */
-	reg_write(ohci, OHCI1394_IntEventClear, event & ~OHCI1394_busReset);
+	/*
+	 * busReset and postedWriteErr must not be cleared yet
+	 * (OHCI 1.1 clauses 7.2.3.2 and 13.2.8.1)
+	 */
+	reg_write(ohci, OHCI1394_IntEventClear,
+		  event & ~(OHCI1394_busReset | OHCI1394_postedWriteErr));
 	log_irqs(event);
 
 	if (event & OHCI1394_selfIDComplete)
@@ -1672,30 +1850,41 @@ static irqreturn_t irq_handler(int irq,
 	if (event & OHCI1394_respTxComplete)
 		tasklet_schedule(&ohci->at_response_ctx.tasklet);
 
-	iso_event = reg_read(ohci, OHCI1394_IsoRecvIntEventClear);
-	reg_write(ohci, OHCI1394_IsoRecvIntEventClear, iso_event);
+	if (event & OHCI1394_isochRx) {
+		iso_event = reg_read(ohci, OHCI1394_IsoRecvIntEventClear);
+		reg_write(ohci, OHCI1394_IsoRecvIntEventClear, iso_event);
 
-	while (iso_event) {
-		i = ffs(iso_event) - 1;
-		tasklet_schedule(&ohci->ir_context_list[i].context.tasklet);
-		iso_event &= ~(1 << i);
+		while (iso_event) {
+			i = ffs(iso_event) - 1;
+			tasklet_schedule(
+				&ohci->ir_context_list[i].context.tasklet);
+			iso_event &= ~(1 << i);
+		}
 	}
 
-	iso_event = reg_read(ohci, OHCI1394_IsoXmitIntEventClear);
-	reg_write(ohci, OHCI1394_IsoXmitIntEventClear, iso_event);
+	if (event & OHCI1394_isochTx) {
+		iso_event = reg_read(ohci, OHCI1394_IsoXmitIntEventClear);
+		reg_write(ohci, OHCI1394_IsoXmitIntEventClear, iso_event);
 
-	while (iso_event) {
-		i = ffs(iso_event) - 1;
-		tasklet_schedule(&ohci->it_context_list[i].context.tasklet);
-		iso_event &= ~(1 << i);
+		while (iso_event) {
+			i = ffs(iso_event) - 1;
+			tasklet_schedule(
+				&ohci->it_context_list[i].context.tasklet);
+			iso_event &= ~(1 << i);
+		}
 	}
 
 	if (unlikely(event & OHCI1394_regAccessFail))
 		fw_error("Register access failure - "
 			 "please notify linux1394-devel@lists.sf.net\n");
 
-	if (unlikely(event & OHCI1394_postedWriteErr))
+	if (unlikely(event & OHCI1394_postedWriteErr)) {
+		reg_read(ohci, OHCI1394_PostedWriteAddressHi);
+		reg_read(ohci, OHCI1394_PostedWriteAddressLo);
+		reg_write(ohci, OHCI1394_IntEventClear,
+			  OHCI1394_postedWriteErr);
 		fw_error("PCI posted write error\n");
+	}
 
 	if (unlikely(event & OHCI1394_cycleTooLong)) {
 		if (printk_ratelimit())
@@ -1719,7 +1908,8 @@ static irqreturn_t irq_handler(int irq,
 		spin_lock(&ohci->lock);
 		update_bus_time(ohci);
 		spin_unlock(&ohci->lock);
-	}
+	} else
+		flush_writes(ohci);
 
 	return IRQ_HANDLED;
 }
@@ -2495,6 +2685,10 @@ static int ohci_start_iso(struct fw_iso_
 		reg_write(ohci, OHCI1394_IsoRecvIntMaskSet, 1 << index);
 		reg_write(ohci, CONTEXT_MATCH(ctx->context.regs), match);
 		context_run(&ctx->context, control);
+
+		ctx->sync = sync;
+		ctx->tags = tags;
+
 		break;
 	}
 
@@ -2592,6 +2786,26 @@ static int ohci_set_iso_channels(struct
 	return ret;
 }
 
+#ifdef CONFIG_PM
+static void ohci_resume_iso_dma(struct fw_ohci *ohci)
+{
+	int i;
+	struct iso_context *ctx;
+
+	for (i = 0 ; i < ohci->n_ir ; i++) {
+		ctx = &ohci->ir_context_list[i];
+		if (ctx->context.running)
+			ohci_start_iso(&ctx->base, 0, ctx->sync, ctx->tags);
+	}
+
+	for (i = 0 ; i < ohci->n_it ; i++) {
+		ctx = &ohci->it_context_list[i];
+		if (ctx->context.running)
+			ohci_start_iso(&ctx->base, 0, ctx->sync, ctx->tags);
+	}
+}
+#endif
+
 static int queue_iso_transmit(struct iso_context *ctx,
 			      struct fw_iso_packet *packet,
 			      struct fw_iso_buffer *buffer,
@@ -2901,7 +3115,7 @@ static int __devinit pci_probe(struct pc
 	struct fw_ohci *ohci;
 	u32 bus_options, max_receive, link_speed, version;
 	u64 guid;
-	int i, err, n_ir, n_it;
+	int i, err;
 	size_t size;
 
 	ohci = kzalloc(sizeof(*ohci), GFP_KERNEL);
@@ -2955,31 +3169,55 @@ static int __devinit pci_probe(struct pc
 	if (param_quirks)
 		ohci->quirks = param_quirks;
 
-	ar_context_init(&ohci->ar_request_ctx, ohci,
-			OHCI1394_AsReqRcvContextControlSet);
+	/*
+	 * Because dma_alloc_coherent() allocates at least one page,
+	 * we save space by using a common buffer for the AR request/
+	 * response descriptors and the self IDs buffer.
+	 */
+	BUILD_BUG_ON(AR_BUFFERS * sizeof(struct descriptor) > PAGE_SIZE/4);
+	BUILD_BUG_ON(SELF_ID_BUF_SIZE > PAGE_SIZE/2);
+	ohci->misc_buffer = dma_alloc_coherent(ohci->card.device,
+					       PAGE_SIZE,
+					       &ohci->misc_buffer_bus,
+					       GFP_KERNEL);
+	if (!ohci->misc_buffer) {
+		err = -ENOMEM;
+		goto fail_iounmap;
+	}
 
-	ar_context_init(&ohci->ar_response_ctx, ohci,
-			OHCI1394_AsRspRcvContextControlSet);
+	err = ar_context_init(&ohci->ar_request_ctx, ohci, 0,
+			      OHCI1394_AsReqRcvContextControlSet);
+	if (err < 0)
+		goto fail_misc_buf;
 
-	context_init(&ohci->at_request_ctx, ohci,
-		     OHCI1394_AsReqTrContextControlSet, handle_at_packet);
+	err = ar_context_init(&ohci->ar_response_ctx, ohci, PAGE_SIZE/4,
+			      OHCI1394_AsRspRcvContextControlSet);
+	if (err < 0)
+		goto fail_arreq_ctx;
 
-	context_init(&ohci->at_response_ctx, ohci,
-		     OHCI1394_AsRspTrContextControlSet, handle_at_packet);
+	err = context_init(&ohci->at_request_ctx, ohci,
+			   OHCI1394_AsReqTrContextControlSet, handle_at_packet);
+	if (err < 0)
+		goto fail_arrsp_ctx;
+
+	err = context_init(&ohci->at_response_ctx, ohci,
+			   OHCI1394_AsRspTrContextControlSet, handle_at_packet);
+	if (err < 0)
+		goto fail_atreq_ctx;
 
 	reg_write(ohci, OHCI1394_IsoRecvIntMaskSet, ~0);
 	ohci->ir_context_channels = ~0ULL;
 	ohci->ir_context_mask = reg_read(ohci, OHCI1394_IsoRecvIntMaskSet);
 	reg_write(ohci, OHCI1394_IsoRecvIntMaskClear, ~0);
-	n_ir = hweight32(ohci->ir_context_mask);
-	size = sizeof(struct iso_context) * n_ir;
+	ohci->n_ir = hweight32(ohci->ir_context_mask);
+	size = sizeof(struct iso_context) * ohci->n_ir;
 	ohci->ir_context_list = kzalloc(size, GFP_KERNEL);
 
 	reg_write(ohci, OHCI1394_IsoXmitIntMaskSet, ~0);
 	ohci->it_context_mask = reg_read(ohci, OHCI1394_IsoXmitIntMaskSet);
 	reg_write(ohci, OHCI1394_IsoXmitIntMaskClear, ~0);
-	n_it = hweight32(ohci->it_context_mask);
-	size = sizeof(struct iso_context) * n_it;
+	ohci->n_it = hweight32(ohci->it_context_mask);
+	size = sizeof(struct iso_context) * ohci->n_it;
 	ohci->it_context_list = kzalloc(size, GFP_KERNEL);
 
 	if (ohci->it_context_list == NULL || ohci->ir_context_list == NULL) {
@@ -2987,15 +3225,8 @@ static int __devinit pci_probe(struct pc
 		goto fail_contexts;
 	}
 
-	/* self-id dma buffer allocation */
-	ohci->self_id_cpu = dma_alloc_coherent(ohci->card.device,
-					       SELF_ID_BUF_SIZE,
-					       &ohci->self_id_bus,
-					       GFP_KERNEL);
-	if (ohci->self_id_cpu == NULL) {
-		err = -ENOMEM;
-		goto fail_contexts;
-	}
+	ohci->self_id_cpu = ohci->misc_buffer     + PAGE_SIZE/2;
+	ohci->self_id_bus = ohci->misc_buffer_bus + PAGE_SIZE/2;
 
 	bus_options = reg_read(ohci, OHCI1394_BusOptions);
 	max_receive = (bus_options >> 12) & 0xf;
@@ -3005,26 +3236,30 @@ static int __devinit pci_probe(struct pc
 
 	err = fw_card_add(&ohci->card, max_receive, link_speed, guid);
 	if (err)
-		goto fail_self_id;
+		goto fail_contexts;
 
 	version = reg_read(ohci, OHCI1394_Version) & 0x00ff00ff;
 	fw_notify("Added fw-ohci device %s, OHCI v%x.%x, "
 		  "%d IR + %d IT contexts, quirks 0x%x\n",
 		  dev_name(&dev->dev), version >> 16, version & 0xff,
-		  n_ir, n_it, ohci->quirks);
+		  ohci->n_ir, ohci->n_it, ohci->quirks);
 
 	return 0;
 
- fail_self_id:
-	dma_free_coherent(ohci->card.device, SELF_ID_BUF_SIZE,
-			  ohci->self_id_cpu, ohci->self_id_bus);
  fail_contexts:
 	kfree(ohci->ir_context_list);
 	kfree(ohci->it_context_list);
 	context_release(&ohci->at_response_ctx);
+ fail_atreq_ctx:
 	context_release(&ohci->at_request_ctx);
+ fail_arrsp_ctx:
 	ar_context_release(&ohci->ar_response_ctx);
+ fail_arreq_ctx:
 	ar_context_release(&ohci->ar_request_ctx);
+ fail_misc_buf:
+	dma_free_coherent(ohci->card.device, PAGE_SIZE,
+			  ohci->misc_buffer, ohci->misc_buffer_bus);
+ fail_iounmap:
 	pci_iounmap(dev, ohci->registers);
  fail_iomem:
 	pci_release_region(dev, 0);
@@ -3063,10 +3298,10 @@ static void pci_remove(struct pci_dev *d
 	if (ohci->config_rom)
 		dma_free_coherent(ohci->card.device, CONFIG_ROM_SIZE,
 				  ohci->config_rom, ohci->config_rom_bus);
-	dma_free_coherent(ohci->card.device, SELF_ID_BUF_SIZE,
-			  ohci->self_id_cpu, ohci->self_id_bus);
 	ar_context_release(&ohci->ar_request_ctx);
 	ar_context_release(&ohci->ar_response_ctx);
+	dma_free_coherent(ohci->card.device, PAGE_SIZE,
+			  ohci->misc_buffer, ohci->misc_buffer_bus);
 	context_release(&ohci->at_request_ctx);
 	context_release(&ohci->at_response_ctx);
 	kfree(ohci->it_context_list);
@@ -3117,7 +3352,20 @@ static int pci_resume(struct pci_dev *de
 		return err;
 	}
 
-	return ohci_enable(&ohci->card, NULL, 0);
+	/* Some systems don't setup GUID register on resume from ram  */
+	if (!reg_read(ohci, OHCI1394_GUIDLo) &&
+					!reg_read(ohci, OHCI1394_GUIDHi)) {
+		reg_write(ohci, OHCI1394_GUIDLo, (u32)ohci->card.guid);
+		reg_write(ohci, OHCI1394_GUIDHi, (u32)(ohci->card.guid >> 32));
+	}
+
+	err = ohci_enable(&ohci->card, NULL, 0);
+	if (err)
+		return err;
+
+	ohci_resume_iso_dma(ohci);
+
+	return 0;
 }
 #endif
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/firmware/dmi_scan.c linux-libre-2.6.38-gnu1/drivers/firmware/dmi_scan.c
--- linux-libre-2.6.37-gnu1/drivers/firmware/dmi_scan.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/firmware/dmi_scan.c	2011-03-14 21:20:32.000000000 -0400
@@ -378,10 +378,17 @@ static void __init print_filtered(const
 
 static void __init dmi_dump_ids(void)
 {
+	const char *board;	/* Board Name is optional */
+
 	printk(KERN_DEBUG "DMI: ");
-	print_filtered(dmi_get_system_info(DMI_BOARD_NAME));
-	printk(KERN_CONT "/");
+	print_filtered(dmi_get_system_info(DMI_SYS_VENDOR));
+	printk(KERN_CONT " ");
 	print_filtered(dmi_get_system_info(DMI_PRODUCT_NAME));
+	board = dmi_get_system_info(DMI_BOARD_NAME);
+	if (board) {
+		printk(KERN_CONT "/");
+		print_filtered(board);
+	}
 	printk(KERN_CONT ", BIOS ");
 	print_filtered(dmi_get_system_info(DMI_BIOS_VERSION));
 	printk(KERN_CONT " ");
diff -druNp linux-libre-2.6.37-gnu1/drivers/firmware/Kconfig linux-libre-2.6.38-gnu1/drivers/firmware/Kconfig
--- linux-libre-2.6.37-gnu1/drivers/firmware/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/firmware/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -27,7 +27,7 @@ config EDD_OFF
 	  using the kernel parameter 'edd={on|skipmbr|off}'.
 
 config FIRMWARE_MEMMAP
-    bool "Add firmware-provided memory map to sysfs" if EMBEDDED
+    bool "Add firmware-provided memory map to sysfs" if EXPERT
     default X86
     help
       Add the firmware-provided (unmodified) memory map to /sys/firmware/memmap.
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpio/adp5588-gpio.c linux-libre-2.6.38-gnu1/drivers/gpio/adp5588-gpio.c
--- linux-libre-2.6.37-gnu1/drivers/gpio/adp5588-gpio.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpio/adp5588-gpio.c	2011-03-14 21:20:32.000000000 -0400
@@ -146,9 +146,10 @@ static int adp5588_gpio_to_irq(struct gp
 	return dev->irq_base + off;
 }
 
-static void adp5588_irq_bus_lock(unsigned int irq)
+static void adp5588_irq_bus_lock(struct irq_data *d)
 {
-	struct adp5588_gpio *dev = get_irq_chip_data(irq);
+	struct adp5588_gpio *dev = irq_data_get_irq_chip_data(d);
+
 	mutex_lock(&dev->irq_lock);
 }
 
@@ -160,9 +161,9 @@ static void adp5588_irq_bus_lock(unsigne
   * and unlocks the bus.
   */
 
-static void adp5588_irq_bus_sync_unlock(unsigned int irq)
+static void adp5588_irq_bus_sync_unlock(struct irq_data *d)
 {
-	struct adp5588_gpio *dev = get_irq_chip_data(irq);
+	struct adp5588_gpio *dev = irq_data_get_irq_chip_data(d);
 	int i;
 
 	for (i = 0; i <= ADP5588_BANK(ADP5588_MAXGPIO); i++)
@@ -175,31 +176,31 @@ static void adp5588_irq_bus_sync_unlock(
 	mutex_unlock(&dev->irq_lock);
 }
 
-static void adp5588_irq_mask(unsigned int irq)
+static void adp5588_irq_mask(struct irq_data *d)
 {
-	struct adp5588_gpio *dev = get_irq_chip_data(irq);
-	unsigned gpio = irq - dev->irq_base;
+	struct adp5588_gpio *dev = irq_data_get_irq_chip_data(d);
+	unsigned gpio = d->irq - dev->irq_base;
 
 	dev->irq_mask[ADP5588_BANK(gpio)] &= ~ADP5588_BIT(gpio);
 }
 
-static void adp5588_irq_unmask(unsigned int irq)
+static void adp5588_irq_unmask(struct irq_data *d)
 {
-	struct adp5588_gpio *dev = get_irq_chip_data(irq);
-	unsigned gpio = irq - dev->irq_base;
+	struct adp5588_gpio *dev = irq_data_get_irq_chip_data(d);
+	unsigned gpio = d->irq - dev->irq_base;
 
 	dev->irq_mask[ADP5588_BANK(gpio)] |= ADP5588_BIT(gpio);
 }
 
-static int adp5588_irq_set_type(unsigned int irq, unsigned int type)
+static int adp5588_irq_set_type(struct irq_data *d, unsigned int type)
 {
-	struct adp5588_gpio *dev = get_irq_chip_data(irq);
-	uint16_t gpio = irq - dev->irq_base;
+	struct adp5588_gpio *dev = irq_data_get_irq_chip_data(d);
+	uint16_t gpio = d->irq - dev->irq_base;
 	unsigned bank, bit;
 
 	if ((type & IRQ_TYPE_EDGE_BOTH)) {
 		dev_err(&dev->client->dev, "irq %d: unsupported type %d\n",
-			irq, type);
+			d->irq, type);
 		return -EINVAL;
 	}
 
@@ -222,11 +223,11 @@ static int adp5588_irq_set_type(unsigned
 
 static struct irq_chip adp5588_irq_chip = {
 	.name			= "adp5588",
-	.mask			= adp5588_irq_mask,
-	.unmask			= adp5588_irq_unmask,
-	.bus_lock		= adp5588_irq_bus_lock,
-	.bus_sync_unlock	= adp5588_irq_bus_sync_unlock,
-	.set_type		= adp5588_irq_set_type,
+	.irq_mask		= adp5588_irq_mask,
+	.irq_unmask		= adp5588_irq_unmask,
+	.irq_bus_lock		= adp5588_irq_bus_lock,
+	.irq_bus_sync_unlock	= adp5588_irq_bus_sync_unlock,
+	.irq_set_type		= adp5588_irq_set_type,
 };
 
 static int adp5588_gpio_read_intstat(struct i2c_client *client, u8 *buf)
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpio/cs5535-gpio.c linux-libre-2.6.38-gnu1/drivers/gpio/cs5535-gpio.c
--- linux-libre-2.6.37-gnu1/drivers/gpio/cs5535-gpio.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpio/cs5535-gpio.c	2011-03-14 21:20:32.000000000 -0400
@@ -11,13 +11,13 @@
 #include <linux/kernel.h>
 #include <linux/spinlock.h>
 #include <linux/module.h>
-#include <linux/pci.h>
+#include <linux/platform_device.h>
 #include <linux/gpio.h>
 #include <linux/io.h>
 #include <linux/cs5535.h>
+#include <asm/msr.h>
 
 #define DRV_NAME "cs5535-gpio"
-#define GPIO_BAR 1
 
 /*
  * Some GPIO pins
@@ -46,7 +46,7 @@ static struct cs5535_gpio_chip {
 	struct gpio_chip chip;
 	resource_size_t base;
 
-	struct pci_dev *pdev;
+	struct platform_device *pdev;
 	spinlock_t lock;
 } cs5535_gpio_chip;
 
@@ -144,6 +144,57 @@ int cs5535_gpio_isset(unsigned offset, u
 }
 EXPORT_SYMBOL_GPL(cs5535_gpio_isset);
 
+int cs5535_gpio_set_irq(unsigned group, unsigned irq)
+{
+	uint32_t lo, hi;
+
+	if (group > 7 || irq > 15)
+		return -EINVAL;
+
+	rdmsr(MSR_PIC_ZSEL_HIGH, lo, hi);
+
+	lo &= ~(0xF << (group * 4));
+	lo |= (irq & 0xF) << (group * 4);
+
+	wrmsr(MSR_PIC_ZSEL_HIGH, lo, hi);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(cs5535_gpio_set_irq);
+
+void cs5535_gpio_setup_event(unsigned offset, int pair, int pme)
+{
+	struct cs5535_gpio_chip *chip = &cs5535_gpio_chip;
+	uint32_t shift = (offset % 8) * 4;
+	unsigned long flags;
+	uint32_t val;
+
+	if (offset >= 24)
+		offset = GPIO_MAP_W;
+	else if (offset >= 16)
+		offset = GPIO_MAP_Z;
+	else if (offset >= 8)
+		offset = GPIO_MAP_Y;
+	else
+		offset = GPIO_MAP_X;
+
+	spin_lock_irqsave(&chip->lock, flags);
+	val = inl(chip->base + offset);
+
+	/* Clear whatever was there before */
+	val &= ~(0xF << shift);
+
+	/* Set the new value */
+	val |= ((pair & 7) << shift);
+
+	/* Set the PME bit if this is a PME event */
+	if (pme)
+		val |= (1 << (shift + 3));
+
+	outl(val, chip->base + offset);
+	spin_unlock_irqrestore(&chip->lock, flags);
+}
+EXPORT_SYMBOL_GPL(cs5535_gpio_setup_event);
+
 /*
  * Generic gpio_chip API support.
  */
@@ -249,10 +300,10 @@ static struct cs5535_gpio_chip cs5535_gp
 	},
 };
 
-static int __init cs5535_gpio_probe(struct pci_dev *pdev,
-		const struct pci_device_id *pci_id)
+static int __devinit cs5535_gpio_probe(struct platform_device *pdev)
 {
-	int err;
+	struct resource *res;
+	int err = -EIO;
 	ulong mask_orig = mask;
 
 	/* There are two ways to get the GPIO base address; one is by
@@ -262,25 +313,23 @@ static int __init cs5535_gpio_probe(stru
 	 * it turns out to be unreliable in the face of crappy BIOSes, we
 	 * can always go back to using MSRs.. */
 
-	err = pci_enable_device_io(pdev);
-	if (err) {
-		dev_err(&pdev->dev, "can't enable device IO\n");
+	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+	if (!res) {
+		dev_err(&pdev->dev, "can't fetch device resource info\n");
 		goto done;
 	}
 
-	err = pci_request_region(pdev, GPIO_BAR, DRV_NAME);
-	if (err) {
-		dev_err(&pdev->dev, "can't alloc PCI BAR #%d\n", GPIO_BAR);
+	if (!request_region(res->start, resource_size(res), pdev->name)) {
+		dev_err(&pdev->dev, "can't request region\n");
 		goto done;
 	}
 
 	/* set up the driver-specific struct */
-	cs5535_gpio_chip.base = pci_resource_start(pdev, GPIO_BAR);
+	cs5535_gpio_chip.base = res->start;
 	cs5535_gpio_chip.pdev = pdev;
 	spin_lock_init(&cs5535_gpio_chip.lock);
 
-	dev_info(&pdev->dev, "allocated PCI BAR #%d: base 0x%llx\n", GPIO_BAR,
-			(unsigned long long) cs5535_gpio_chip.base);
+	dev_info(&pdev->dev, "reserved resource region %pR\n", res);
 
 	/* mask out reserved pins */
 	mask &= 0x1F7FFFFF;
@@ -298,78 +347,49 @@ static int __init cs5535_gpio_probe(stru
 	if (err)
 		goto release_region;
 
-	dev_info(&pdev->dev, DRV_NAME ": GPIO support successfully loaded.\n");
+	dev_info(&pdev->dev, "GPIO support successfully loaded.\n");
 	return 0;
 
 release_region:
-	pci_release_region(pdev, GPIO_BAR);
+	release_region(res->start, resource_size(res));
 done:
 	return err;
 }
 
-static void __exit cs5535_gpio_remove(struct pci_dev *pdev)
+static int __devexit cs5535_gpio_remove(struct platform_device *pdev)
 {
+	struct resource *r;
 	int err;
 
 	err = gpiochip_remove(&cs5535_gpio_chip.chip);
 	if (err) {
 		/* uhh? */
 		dev_err(&pdev->dev, "unable to remove gpio_chip?\n");
-	}
-	pci_release_region(pdev, GPIO_BAR);
-}
-
-static struct pci_device_id cs5535_gpio_pci_tbl[] = {
-	{ PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_CS5535_ISA) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA) },
-	{ 0, },
-};
-MODULE_DEVICE_TABLE(pci, cs5535_gpio_pci_tbl);
-
-/*
- * We can't use the standard PCI driver registration stuff here, since
- * that allows only one driver to bind to each PCI device (and we want
- * multiple drivers to be able to bind to the device).  Instead, manually
- * scan for the PCI device, request a single region, and keep track of the
- * devices that we're using.
- */
-
-static int __init cs5535_gpio_scan_pci(void)
-{
-	struct pci_dev *pdev;
-	int err = -ENODEV;
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(cs5535_gpio_pci_tbl); i++) {
-		pdev = pci_get_device(cs5535_gpio_pci_tbl[i].vendor,
-				cs5535_gpio_pci_tbl[i].device, NULL);
-		if (pdev) {
-			err = cs5535_gpio_probe(pdev, &cs5535_gpio_pci_tbl[i]);
-			if (err)
-				pci_dev_put(pdev);
-
-			/* we only support a single CS5535/6 southbridge */
-			break;
-		}
+		return err;
 	}
 
-	return err;
+	r = platform_get_resource(pdev, IORESOURCE_IO, 0);
+	release_region(r->start, resource_size(r));
+	return 0;
 }
 
-static void __exit cs5535_gpio_free_pci(void)
-{
-	cs5535_gpio_remove(cs5535_gpio_chip.pdev);
-	pci_dev_put(cs5535_gpio_chip.pdev);
-}
+static struct platform_driver cs5535_gpio_drv = {
+	.driver = {
+		.name = DRV_NAME,
+		.owner = THIS_MODULE,
+	},
+	.probe = cs5535_gpio_probe,
+	.remove = __devexit_p(cs5535_gpio_remove),
+};
 
 static int __init cs5535_gpio_init(void)
 {
-	return cs5535_gpio_scan_pci();
+	return platform_driver_register(&cs5535_gpio_drv);
 }
 
 static void __exit cs5535_gpio_exit(void)
 {
-	cs5535_gpio_free_pci();
+	platform_driver_unregister(&cs5535_gpio_drv);
 }
 
 module_init(cs5535_gpio_init);
@@ -378,3 +398,4 @@ module_exit(cs5535_gpio_exit);
 MODULE_AUTHOR("Andres Salomon <dilinger@queued.net>");
 MODULE_DESCRIPTION("AMD CS5535/CS5536 GPIO driver");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" DRV_NAME);
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpio/Kconfig linux-libre-2.6.38-gnu1/drivers/gpio/Kconfig
--- linux-libre-2.6.37-gnu1/drivers/gpio/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpio/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -118,7 +118,7 @@ config GPIO_SCH
 
 config GPIO_VX855
 	tristate "VIA VX855/VX875 GPIO"
-	depends on GPIOLIB
+	depends on GPIOLIB && MFD_SUPPORT && PCI
 	select MFD_CORE
 	select MFD_VX855
 	help
@@ -230,11 +230,11 @@ config GPIO_STMPE
 	  This enables support for the GPIOs found on the STMPE I/O
 	  Expanders.
 
-config GPIO_TC35892
-	bool "TC35892 GPIOs"
-	depends on MFD_TC35892
+config GPIO_TC3589X
+	bool "TC3589X GPIOs"
+	depends on MFD_TC3589X
 	help
-	  This enables support for the GPIOs found on the TC35892
+	  This enables support for the GPIOs found on the TC3589X
 	  I/O Expander.
 
 config GPIO_TWL4030
@@ -295,7 +295,7 @@ comment "PCI GPIO expanders:"
 
 config GPIO_CS5535
 	tristate "AMD CS5535/CS5536 GPIO support"
-	depends on PCI && !CS5535_GPIO
+	depends on PCI && X86 && !CS5535_GPIO
 	help
 	  The AMD CS5535 and CS5536 southbridges support 28 GPIO pins that
 	  can be used for quite a number of things.  The CS5535/6 is found on
@@ -333,6 +333,15 @@ config GPIO_PCH
 	  which is an IOH(Input/Output Hub) for x86 embedded processor.
 	  This driver can access PCH GPIO device.
 
+config GPIO_ML_IOH
+	tristate "OKI SEMICONDUCTOR ML7213 IOH GPIO support"
+	depends on PCI
+	help
+	  ML7213 is companion chip for Intel Atom E6xx series.
+	  This driver can be used for OKI SEMICONDUCTOR ML7213 IOH(Input/Output
+	  Hub) which is for IVI(In-Vehicle Infotainment) use.
+	  This driver can access the IOH's GPIO device.
+
 config GPIO_TIMBERDALE
 	bool "Support for timberdale GPIO IP"
 	depends on MFD_TIMBERDALE && GPIOLIB && HAS_IOMEM
@@ -342,6 +351,7 @@ config GPIO_TIMBERDALE
 config GPIO_RDC321X
 	tristate "RDC R-321x GPIO support"
 	depends on PCI && GPIOLIB
+	select MFD_SUPPORT
 	select MFD_CORE
 	select MFD_RDC321X
 	help
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpio/langwell_gpio.c linux-libre-2.6.38-gnu1/drivers/gpio/langwell_gpio.c
--- linux-libre-2.6.37-gnu1/drivers/gpio/langwell_gpio.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpio/langwell_gpio.c	2011-03-14 21:20:32.000000000 -0400
@@ -134,10 +134,10 @@ static int lnw_gpio_to_irq(struct gpio_c
 	return lnw->irq_base + offset;
 }
 
-static int lnw_irq_type(unsigned irq, unsigned type)
+static int lnw_irq_type(struct irq_data *d, unsigned type)
 {
-	struct lnw_gpio *lnw = get_irq_chip_data(irq);
-	u32 gpio = irq - lnw->irq_base;
+	struct lnw_gpio *lnw = irq_data_get_irq_chip_data(d);
+	u32 gpio = d->irq - lnw->irq_base;
 	unsigned long flags;
 	u32 value;
 	void __iomem *grer = gpio_reg(&lnw->chip, gpio, GRER);
@@ -162,19 +162,19 @@ static int lnw_irq_type(unsigned irq, un
 	return 0;
 }
 
-static void lnw_irq_unmask(unsigned irq)
+static void lnw_irq_unmask(struct irq_data *d)
 {
 }
 
-static void lnw_irq_mask(unsigned irq)
+static void lnw_irq_mask(struct irq_data *d)
 {
 }
 
 static struct irq_chip lnw_irqchip = {
 	.name		= "LNW-GPIO",
-	.mask		= lnw_irq_mask,
-	.unmask		= lnw_irq_unmask,
-	.set_type	= lnw_irq_type,
+	.irq_mask	= lnw_irq_mask,
+	.irq_unmask	= lnw_irq_unmask,
+	.irq_set_type	= lnw_irq_type,
 };
 
 static DEFINE_PCI_DEVICE_TABLE(lnw_gpio_ids) = {   /* pin number */
@@ -187,7 +187,7 @@ MODULE_DEVICE_TABLE(pci, lnw_gpio_ids);
 
 static void lnw_irq_handler(unsigned irq, struct irq_desc *desc)
 {
-	struct lnw_gpio *lnw = (struct lnw_gpio *)get_irq_data(irq);
+	struct lnw_gpio *lnw = get_irq_data(irq);
 	u32 base, gpio;
 	void __iomem *gedr;
 	u32 gedr_v;
@@ -206,7 +206,12 @@ static void lnw_irq_handler(unsigned irq
 		/* clear the edge detect status bit */
 		writel(gedr_v, gedr);
 	}
-	desc->chip->eoi(irq);
+
+	if (desc->chip->irq_eoi)
+		desc->chip->irq_eoi(irq_get_irq_data(irq));
+	else
+		dev_warn(lnw->chip.dev, "missing EOI handler for irq %d\n", irq);
+
 }
 
 static int __devinit lnw_gpio_probe(struct pci_dev *pdev,
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpio/Makefile linux-libre-2.6.38-gnu1/drivers/gpio/Makefile
--- linux-libre-2.6.37-gnu1/drivers/gpio/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpio/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -24,7 +24,7 @@ obj-$(CONFIG_GPIO_PCF857X)	+= pcf857x.o
 obj-$(CONFIG_GPIO_PCH)		+= pch_gpio.o
 obj-$(CONFIG_GPIO_PL061)	+= pl061.o
 obj-$(CONFIG_GPIO_STMPE)	+= stmpe-gpio.o
-obj-$(CONFIG_GPIO_TC35892)	+= tc35892-gpio.o
+obj-$(CONFIG_GPIO_TC3589X)	+= tc3589x-gpio.o
 obj-$(CONFIG_GPIO_TIMBERDALE)	+= timbgpio.o
 obj-$(CONFIG_GPIO_TWL4030)	+= twl4030-gpio.o
 obj-$(CONFIG_GPIO_UCB1400)	+= ucb1400_gpio.o
@@ -41,3 +41,4 @@ obj-$(CONFIG_GPIO_RDC321X)	+= rdc321x-gp
 obj-$(CONFIG_GPIO_JANZ_TTL)	+= janz-ttl.o
 obj-$(CONFIG_GPIO_SX150X)	+= sx150x.o
 obj-$(CONFIG_GPIO_VX855)	+= vx855_gpio.o
+obj-$(CONFIG_GPIO_ML_IOH)	+= ml_ioh_gpio.o
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpio/max732x.c linux-libre-2.6.38-gnu1/drivers/gpio/max732x.c
--- linux-libre-2.6.37-gnu1/drivers/gpio/max732x.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpio/max732x.c	2011-03-14 21:20:32.000000000 -0400
@@ -327,40 +327,40 @@ static int max732x_gpio_to_irq(struct gp
 	return chip->irq_base + off;
 }
 
-static void max732x_irq_mask(unsigned int irq)
+static void max732x_irq_mask(struct irq_data *d)
 {
-	struct max732x_chip *chip = get_irq_chip_data(irq);
+	struct max732x_chip *chip = irq_data_get_irq_chip_data(d);
 
-	chip->irq_mask_cur &= ~(1 << (irq - chip->irq_base));
+	chip->irq_mask_cur &= ~(1 << (d->irq - chip->irq_base));
 }
 
-static void max732x_irq_unmask(unsigned int irq)
+static void max732x_irq_unmask(struct irq_data *d)
 {
-	struct max732x_chip *chip = get_irq_chip_data(irq);
+	struct max732x_chip *chip = irq_data_get_irq_chip_data(d);
 
-	chip->irq_mask_cur |= 1 << (irq - chip->irq_base);
+	chip->irq_mask_cur |= 1 << (d->irq - chip->irq_base);
 }
 
-static void max732x_irq_bus_lock(unsigned int irq)
+static void max732x_irq_bus_lock(struct irq_data *d)
 {
-	struct max732x_chip *chip = get_irq_chip_data(irq);
+	struct max732x_chip *chip = irq_data_get_irq_chip_data(d);
 
 	mutex_lock(&chip->irq_lock);
 	chip->irq_mask_cur = chip->irq_mask;
 }
 
-static void max732x_irq_bus_sync_unlock(unsigned int irq)
+static void max732x_irq_bus_sync_unlock(struct irq_data *d)
 {
-	struct max732x_chip *chip = get_irq_chip_data(irq);
+	struct max732x_chip *chip = irq_data_get_irq_chip_data(d);
 
 	max732x_irq_update_mask(chip);
 	mutex_unlock(&chip->irq_lock);
 }
 
-static int max732x_irq_set_type(unsigned int irq, unsigned int type)
+static int max732x_irq_set_type(struct irq_data *d, unsigned int type)
 {
-	struct max732x_chip *chip = get_irq_chip_data(irq);
-	uint16_t off = irq - chip->irq_base;
+	struct max732x_chip *chip = irq_data_get_irq_chip_data(d);
+	uint16_t off = d->irq - chip->irq_base;
 	uint16_t mask = 1 << off;
 
 	if (!(mask & chip->dir_input)) {
@@ -371,7 +371,7 @@ static int max732x_irq_set_type(unsigned
 
 	if (!(type & IRQ_TYPE_EDGE_BOTH)) {
 		dev_err(&chip->client->dev, "irq %d: unsupported type %d\n",
-			irq, type);
+			d->irq, type);
 		return -EINVAL;
 	}
 
@@ -390,11 +390,11 @@ static int max732x_irq_set_type(unsigned
 
 static struct irq_chip max732x_irq_chip = {
 	.name			= "max732x",
-	.mask			= max732x_irq_mask,
-	.unmask			= max732x_irq_unmask,
-	.bus_lock		= max732x_irq_bus_lock,
-	.bus_sync_unlock	= max732x_irq_bus_sync_unlock,
-	.set_type		= max732x_irq_set_type,
+	.irq_mask		= max732x_irq_mask,
+	.irq_unmask		= max732x_irq_unmask,
+	.irq_bus_lock		= max732x_irq_bus_lock,
+	.irq_bus_sync_unlock	= max732x_irq_bus_sync_unlock,
+	.irq_set_type		= max732x_irq_set_type,
 };
 
 static uint8_t max732x_irq_pending(struct max732x_chip *chip)
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpio/ml_ioh_gpio.c linux-libre-2.6.38-gnu1/drivers/gpio/ml_ioh_gpio.c
--- linux-libre-2.6.37-gnu1/drivers/gpio/ml_ioh_gpio.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpio/ml_ioh_gpio.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,353 @@
+/*
+ * Copyright (C) 2010 OKI SEMICONDUCTOR 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; 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/kernel.h>
+#include <linux/pci.h>
+#include <linux/gpio.h>
+
+#define PCI_VENDOR_ID_ROHM             0x10DB
+
+struct ioh_reg_comn {
+	u32	ien;
+	u32	istatus;
+	u32	idisp;
+	u32	iclr;
+	u32	imask;
+	u32	imaskclr;
+	u32	po;
+	u32	pi;
+	u32	pm;
+	u32	im_0;
+	u32	im_1;
+	u32	reserved;
+};
+
+struct ioh_regs {
+	struct ioh_reg_comn regs[8];
+	u32 reserve1[16];
+	u32 ioh_sel_reg[4];
+	u32 reserve2[11];
+	u32 srst;
+};
+
+/**
+ * struct ioh_gpio_reg_data - The register store data.
+ * @po_reg:	To store contents of PO register.
+ * @pm_reg:	To store contents of PM register.
+ */
+struct ioh_gpio_reg_data {
+	u32 po_reg;
+	u32 pm_reg;
+};
+
+/**
+ * struct ioh_gpio - GPIO private data structure.
+ * @base:			PCI base address of Memory mapped I/O register.
+ * @reg:			Memory mapped IOH GPIO register list.
+ * @dev:			Pointer to device structure.
+ * @gpio:			Data for GPIO infrastructure.
+ * @ioh_gpio_reg:		Memory mapped Register data is saved here
+ *				when suspend.
+ * @ch:				Indicate GPIO channel
+ */
+struct ioh_gpio {
+	void __iomem *base;
+	struct ioh_regs __iomem *reg;
+	struct device *dev;
+	struct gpio_chip gpio;
+	struct ioh_gpio_reg_data ioh_gpio_reg;
+	struct mutex lock;
+	int ch;
+};
+
+static const int num_ports[] = {6, 12, 16, 16, 15, 16, 16, 12};
+
+static void ioh_gpio_set(struct gpio_chip *gpio, unsigned nr, int val)
+{
+	u32 reg_val;
+	struct ioh_gpio *chip =	container_of(gpio, struct ioh_gpio, gpio);
+
+	mutex_lock(&chip->lock);
+	reg_val = ioread32(&chip->reg->regs[chip->ch].po);
+	if (val)
+		reg_val |= (1 << nr);
+	else
+		reg_val &= ~(1 << nr);
+
+	iowrite32(reg_val, &chip->reg->regs[chip->ch].po);
+	mutex_unlock(&chip->lock);
+}
+
+static int ioh_gpio_get(struct gpio_chip *gpio, unsigned nr)
+{
+	struct ioh_gpio *chip =	container_of(gpio, struct ioh_gpio, gpio);
+
+	return ioread32(&chip->reg->regs[chip->ch].pi) & (1 << nr);
+}
+
+static int ioh_gpio_direction_output(struct gpio_chip *gpio, unsigned nr,
+				     int val)
+{
+	struct ioh_gpio *chip =	container_of(gpio, struct ioh_gpio, gpio);
+	u32 pm;
+	u32 reg_val;
+
+	mutex_lock(&chip->lock);
+	pm = ioread32(&chip->reg->regs[chip->ch].pm) &
+					((1 << num_ports[chip->ch]) - 1);
+	pm |= (1 << nr);
+	iowrite32(pm, &chip->reg->regs[chip->ch].pm);
+
+	reg_val = ioread32(&chip->reg->regs[chip->ch].po);
+	if (val)
+		reg_val |= (1 << nr);
+	else
+		reg_val &= ~(1 << nr);
+
+	mutex_unlock(&chip->lock);
+
+	return 0;
+}
+
+static int ioh_gpio_direction_input(struct gpio_chip *gpio, unsigned nr)
+{
+	struct ioh_gpio *chip =	container_of(gpio, struct ioh_gpio, gpio);
+	u32 pm;
+
+	mutex_lock(&chip->lock);
+	pm = ioread32(&chip->reg->regs[chip->ch].pm) &
+				((1 << num_ports[chip->ch]) - 1);
+	pm &= ~(1 << nr);
+	iowrite32(pm, &chip->reg->regs[chip->ch].pm);
+	mutex_unlock(&chip->lock);
+
+	return 0;
+}
+
+/*
+ * Save register configuration and disable interrupts.
+ */
+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);
+}
+
+/*
+ * This function restores the register configuration of the GPIO device.
+ */
+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);
+}
+
+static void ioh_gpio_setup(struct ioh_gpio *chip, int num_port)
+{
+	struct gpio_chip *gpio = &chip->gpio;
+
+	gpio->label = dev_name(chip->dev);
+	gpio->owner = THIS_MODULE;
+	gpio->direction_input = ioh_gpio_direction_input;
+	gpio->get = ioh_gpio_get;
+	gpio->direction_output = ioh_gpio_direction_output;
+	gpio->set = ioh_gpio_set;
+	gpio->dbg_show = NULL;
+	gpio->base = -1;
+	gpio->ngpio = num_port;
+	gpio->can_sleep = 0;
+}
+
+static int __devinit ioh_gpio_probe(struct pci_dev *pdev,
+				    const struct pci_device_id *id)
+{
+	int ret;
+	int i;
+	struct ioh_gpio *chip;
+	void __iomem *base;
+	void __iomem *chip_save;
+
+	ret = pci_enable_device(pdev);
+	if (ret) {
+		dev_err(&pdev->dev, "%s : pci_enable_device failed", __func__);
+		goto err_pci_enable;
+	}
+
+	ret = pci_request_regions(pdev, KBUILD_MODNAME);
+	if (ret) {
+		dev_err(&pdev->dev, "pci_request_regions failed-%d", ret);
+		goto err_request_regions;
+	}
+
+	base = pci_iomap(pdev, 1, 0);
+	if (base == 0) {
+		dev_err(&pdev->dev, "%s : pci_iomap failed", __func__);
+		ret = -ENOMEM;
+		goto err_iomap;
+	}
+
+	chip_save = kzalloc(sizeof(*chip) * 8, GFP_KERNEL);
+	if (chip_save == NULL) {
+		dev_err(&pdev->dev, "%s : kzalloc failed", __func__);
+		ret = -ENOMEM;
+		goto err_kzalloc;
+	}
+
+	chip = chip_save;
+	for (i = 0; i < 8; i++, chip++) {
+		chip->dev = &pdev->dev;
+		chip->base = base;
+		chip->reg = chip->base;
+		chip->ch = i;
+		mutex_init(&chip->lock);
+		ioh_gpio_setup(chip, num_ports[i]);
+		ret = gpiochip_add(&chip->gpio);
+		if (ret) {
+			dev_err(&pdev->dev, "IOH gpio: Failed to register GPIO\n");
+			goto err_gpiochip_add;
+		}
+	}
+
+	chip = chip_save;
+	pci_set_drvdata(pdev, chip);
+
+	return 0;
+
+err_gpiochip_add:
+	for (; i != 0; i--) {
+		chip--;
+		ret = gpiochip_remove(&chip->gpio);
+		if (ret)
+			dev_err(&pdev->dev, "Failed gpiochip_remove(%d)\n", i);
+	}
+	kfree(chip_save);
+
+err_kzalloc:
+	pci_iounmap(pdev, base);
+
+err_iomap:
+	pci_release_regions(pdev);
+
+err_request_regions:
+	pci_disable_device(pdev);
+
+err_pci_enable:
+
+	dev_err(&pdev->dev, "%s Failed returns %d\n", __func__, ret);
+	return ret;
+}
+
+static void __devexit ioh_gpio_remove(struct pci_dev *pdev)
+{
+	int err;
+	int i;
+	struct ioh_gpio *chip = pci_get_drvdata(pdev);
+	void __iomem *chip_save;
+
+	chip_save = chip;
+	for (i = 0; i < 8; i++, chip++) {
+		err = gpiochip_remove(&chip->gpio);
+		if (err)
+			dev_err(&pdev->dev, "Failed gpiochip_remove\n");
+	}
+
+	chip = chip_save;
+	pci_iounmap(pdev, chip->base);
+	pci_release_regions(pdev);
+	pci_disable_device(pdev);
+	kfree(chip);
+}
+
+#ifdef CONFIG_PM
+static int ioh_gpio_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+	s32 ret;
+	struct ioh_gpio *chip = pci_get_drvdata(pdev);
+
+	ioh_gpio_save_reg_conf(chip);
+	ioh_gpio_restore_reg_conf(chip);
+
+	ret = pci_save_state(pdev);
+	if (ret) {
+		dev_err(&pdev->dev, "pci_save_state Failed-%d\n", ret);
+		return ret;
+	}
+	pci_disable_device(pdev);
+	pci_set_power_state(pdev, PCI_D0);
+	ret = pci_enable_wake(pdev, PCI_D0, 1);
+	if (ret)
+		dev_err(&pdev->dev, "pci_enable_wake Failed -%d\n", ret);
+
+	return 0;
+}
+
+static int ioh_gpio_resume(struct pci_dev *pdev)
+{
+	s32 ret;
+	struct ioh_gpio *chip = pci_get_drvdata(pdev);
+
+	ret = pci_enable_wake(pdev, PCI_D0, 0);
+
+	pci_set_power_state(pdev, PCI_D0);
+	ret = pci_enable_device(pdev);
+	if (ret) {
+		dev_err(&pdev->dev, "pci_enable_device Failed-%d ", ret);
+		return ret;
+	}
+	pci_restore_state(pdev);
+
+	iowrite32(0x01, &chip->reg->srst);
+	iowrite32(0x00, &chip->reg->srst);
+	ioh_gpio_restore_reg_conf(chip);
+
+	return 0;
+}
+#else
+#define ioh_gpio_suspend NULL
+#define ioh_gpio_resume NULL
+#endif
+
+static DEFINE_PCI_DEVICE_TABLE(ioh_gpio_pcidev_id) = {
+	{ PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x802E) },
+	{ 0, }
+};
+MODULE_DEVICE_TABLE(pci, ioh_gpio_pcidev_id);
+
+static struct pci_driver ioh_gpio_driver = {
+	.name = "ml_ioh_gpio",
+	.id_table = ioh_gpio_pcidev_id,
+	.probe = ioh_gpio_probe,
+	.remove = __devexit_p(ioh_gpio_remove),
+	.suspend = ioh_gpio_suspend,
+	.resume = ioh_gpio_resume
+};
+
+static int __init ioh_gpio_pci_init(void)
+{
+	return pci_register_driver(&ioh_gpio_driver);
+}
+module_init(ioh_gpio_pci_init);
+
+static void __exit ioh_gpio_pci_exit(void)
+{
+	pci_unregister_driver(&ioh_gpio_driver);
+}
+module_exit(ioh_gpio_pci_exit);
+
+MODULE_DESCRIPTION("OKI SEMICONDUCTOR ML-IOH series GPIO Driver");
+MODULE_LICENSE("GPL");
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpio/pca953x.c linux-libre-2.6.38-gnu1/drivers/gpio/pca953x.c
--- linux-libre-2.6.37-gnu1/drivers/gpio/pca953x.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpio/pca953x.c	2011-03-14 21:20:32.000000000 -0400
@@ -60,6 +60,7 @@ struct pca953x_chip {
 	unsigned gpio_start;
 	uint16_t reg_output;
 	uint16_t reg_direction;
+	struct mutex i2c_lock;
 
 #ifdef CONFIG_GPIO_PCA953X_IRQ
 	struct mutex irq_lock;
@@ -119,13 +120,17 @@ static int pca953x_gpio_direction_input(
 
 	chip = container_of(gc, struct pca953x_chip, gpio_chip);
 
+	mutex_lock(&chip->i2c_lock);
 	reg_val = chip->reg_direction | (1u << off);
 	ret = pca953x_write_reg(chip, PCA953X_DIRECTION, reg_val);
 	if (ret)
-		return ret;
+		goto exit;
 
 	chip->reg_direction = reg_val;
-	return 0;
+	ret = 0;
+exit:
+	mutex_unlock(&chip->i2c_lock);
+	return ret;
 }
 
 static int pca953x_gpio_direction_output(struct gpio_chip *gc,
@@ -137,6 +142,7 @@ static int pca953x_gpio_direction_output
 
 	chip = container_of(gc, struct pca953x_chip, gpio_chip);
 
+	mutex_lock(&chip->i2c_lock);
 	/* set output level */
 	if (val)
 		reg_val = chip->reg_output | (1u << off);
@@ -145,7 +151,7 @@ static int pca953x_gpio_direction_output
 
 	ret = pca953x_write_reg(chip, PCA953X_OUTPUT, reg_val);
 	if (ret)
-		return ret;
+		goto exit;
 
 	chip->reg_output = reg_val;
 
@@ -153,10 +159,13 @@ static int pca953x_gpio_direction_output
 	reg_val = chip->reg_direction & ~(1u << off);
 	ret = pca953x_write_reg(chip, PCA953X_DIRECTION, reg_val);
 	if (ret)
-		return ret;
+		goto exit;
 
 	chip->reg_direction = reg_val;
-	return 0;
+	ret = 0;
+exit:
+	mutex_unlock(&chip->i2c_lock);
+	return ret;
 }
 
 static int pca953x_gpio_get_value(struct gpio_chip *gc, unsigned off)
@@ -167,7 +176,9 @@ static int pca953x_gpio_get_value(struct
 
 	chip = container_of(gc, struct pca953x_chip, gpio_chip);
 
+	mutex_lock(&chip->i2c_lock);
 	ret = pca953x_read_reg(chip, PCA953X_INPUT, &reg_val);
+	mutex_unlock(&chip->i2c_lock);
 	if (ret < 0) {
 		/* NOTE:  diagnostic already emitted; that's all we should
 		 * do unless gpio_*_value_cansleep() calls become different
@@ -187,6 +198,7 @@ static void pca953x_gpio_set_value(struc
 
 	chip = container_of(gc, struct pca953x_chip, gpio_chip);
 
+	mutex_lock(&chip->i2c_lock);
 	if (val)
 		reg_val = chip->reg_output | (1u << off);
 	else
@@ -194,9 +206,11 @@ static void pca953x_gpio_set_value(struc
 
 	ret = pca953x_write_reg(chip, PCA953X_OUTPUT, reg_val);
 	if (ret)
-		return;
+		goto exit;
 
 	chip->reg_output = reg_val;
+exit:
+	mutex_unlock(&chip->i2c_lock);
 }
 
 static void pca953x_setup_gpio(struct pca953x_chip *chip, int gpios)
@@ -228,30 +242,30 @@ static int pca953x_gpio_to_irq(struct gp
 	return chip->irq_base + off;
 }
 
-static void pca953x_irq_mask(unsigned int irq)
+static void pca953x_irq_mask(struct irq_data *d)
 {
-	struct pca953x_chip *chip = get_irq_chip_data(irq);
+	struct pca953x_chip *chip = irq_data_get_irq_chip_data(d);
 
-	chip->irq_mask &= ~(1 << (irq - chip->irq_base));
+	chip->irq_mask &= ~(1 << (d->irq - chip->irq_base));
 }
 
-static void pca953x_irq_unmask(unsigned int irq)
+static void pca953x_irq_unmask(struct irq_data *d)
 {
-	struct pca953x_chip *chip = get_irq_chip_data(irq);
+	struct pca953x_chip *chip = irq_data_get_irq_chip_data(d);
 
-	chip->irq_mask |= 1 << (irq - chip->irq_base);
+	chip->irq_mask |= 1 << (d->irq - chip->irq_base);
 }
 
-static void pca953x_irq_bus_lock(unsigned int irq)
+static void pca953x_irq_bus_lock(struct irq_data *d)
 {
-	struct pca953x_chip *chip = get_irq_chip_data(irq);
+	struct pca953x_chip *chip = irq_data_get_irq_chip_data(d);
 
 	mutex_lock(&chip->irq_lock);
 }
 
-static void pca953x_irq_bus_sync_unlock(unsigned int irq)
+static void pca953x_irq_bus_sync_unlock(struct irq_data *d)
 {
-	struct pca953x_chip *chip = get_irq_chip_data(irq);
+	struct pca953x_chip *chip = irq_data_get_irq_chip_data(d);
 	uint16_t new_irqs;
 	uint16_t level;
 
@@ -268,15 +282,15 @@ static void pca953x_irq_bus_sync_unlock(
 	mutex_unlock(&chip->irq_lock);
 }
 
-static int pca953x_irq_set_type(unsigned int irq, unsigned int type)
+static int pca953x_irq_set_type(struct irq_data *d, unsigned int type)
 {
-	struct pca953x_chip *chip = get_irq_chip_data(irq);
-	uint16_t level = irq - chip->irq_base;
+	struct pca953x_chip *chip = irq_data_get_irq_chip_data(d);
+	uint16_t level = d->irq - chip->irq_base;
 	uint16_t mask = 1 << level;
 
 	if (!(type & IRQ_TYPE_EDGE_BOTH)) {
 		dev_err(&chip->client->dev, "irq %d: unsupported type %d\n",
-			irq, type);
+			d->irq, type);
 		return -EINVAL;
 	}
 
@@ -295,11 +309,11 @@ static int pca953x_irq_set_type(unsigned
 
 static struct irq_chip pca953x_irq_chip = {
 	.name			= "pca953x",
-	.mask			= pca953x_irq_mask,
-	.unmask			= pca953x_irq_unmask,
-	.bus_lock		= pca953x_irq_bus_lock,
-	.bus_sync_unlock	= pca953x_irq_bus_sync_unlock,
-	.set_type		= pca953x_irq_set_type,
+	.irq_mask		= pca953x_irq_mask,
+	.irq_unmask		= pca953x_irq_unmask,
+	.irq_bus_lock		= pca953x_irq_bus_lock,
+	.irq_bus_sync_unlock	= pca953x_irq_bus_sync_unlock,
+	.irq_set_type		= pca953x_irq_set_type,
 };
 
 static uint16_t pca953x_irq_pending(struct pca953x_chip *chip)
@@ -517,6 +531,8 @@ static int __devinit pca953x_probe(struc
 
 	chip->names = pdata->names;
 
+	mutex_init(&chip->i2c_lock);
+
 	/* initialize cached registers from their original values.
 	 * we can't share this chip with another i2c master.
 	 */
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpio/pch_gpio.c linux-libre-2.6.38-gnu1/drivers/gpio/pch_gpio.c
--- linux-libre-2.6.37-gnu1/drivers/gpio/pch_gpio.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpio/pch_gpio.c	2011-03-14 21:20:32.000000000 -0400
@@ -286,6 +286,7 @@ static DEFINE_PCI_DEVICE_TABLE(pch_gpio_
 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x8803) },
 	{ 0, }
 };
+MODULE_DEVICE_TABLE(pci, pch_gpio_pcidev_id);
 
 static struct pci_driver pch_gpio_driver = {
 	.name = "pch_gpio",
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpio/pl061.c linux-libre-2.6.38-gnu1/drivers/gpio/pl061.c
--- linux-libre-2.6.37-gnu1/drivers/gpio/pl061.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpio/pl061.c	2011-03-14 21:20:32.000000000 -0400
@@ -129,10 +129,10 @@ static int pl061_to_irq(struct gpio_chip
 /*
  * PL061 GPIO IRQ
  */
-static void pl061_irq_disable(unsigned irq)
+static void pl061_irq_disable(struct irq_data *d)
 {
-	struct pl061_gpio *chip = get_irq_chip_data(irq);
-	int offset = irq - chip->irq_base;
+	struct pl061_gpio *chip = irq_data_get_irq_chip_data(d);
+	int offset = d->irq - chip->irq_base;
 	unsigned long flags;
 	u8 gpioie;
 
@@ -143,10 +143,10 @@ static void pl061_irq_disable(unsigned i
 	spin_unlock_irqrestore(&chip->irq_lock, flags);
 }
 
-static void pl061_irq_enable(unsigned irq)
+static void pl061_irq_enable(struct irq_data *d)
 {
-	struct pl061_gpio *chip = get_irq_chip_data(irq);
-	int offset = irq - chip->irq_base;
+	struct pl061_gpio *chip = irq_data_get_irq_chip_data(d);
+	int offset = d->irq - chip->irq_base;
 	unsigned long flags;
 	u8 gpioie;
 
@@ -157,10 +157,10 @@ static void pl061_irq_enable(unsigned ir
 	spin_unlock_irqrestore(&chip->irq_lock, flags);
 }
 
-static int pl061_irq_type(unsigned irq, unsigned trigger)
+static int pl061_irq_type(struct irq_data *d, unsigned trigger)
 {
-	struct pl061_gpio *chip = get_irq_chip_data(irq);
-	int offset = irq - chip->irq_base;
+	struct pl061_gpio *chip = irq_data_get_irq_chip_data(d);
+	int offset = d->irq - chip->irq_base;
 	unsigned long flags;
 	u8 gpiois, gpioibe, gpioiev;
 
@@ -203,9 +203,9 @@ static int pl061_irq_type(unsigned irq,
 
 static struct irq_chip pl061_irqchip = {
 	.name		= "GPIO",
-	.enable		= pl061_irq_enable,
-	.disable	= pl061_irq_disable,
-	.set_type	= pl061_irq_type,
+	.irq_enable	= pl061_irq_enable,
+	.irq_disable	= pl061_irq_disable,
+	.irq_set_type	= pl061_irq_type,
 };
 
 static void pl061_irq_handler(unsigned irq, struct irq_desc *desc)
@@ -214,7 +214,7 @@ static void pl061_irq_handler(unsigned i
 	struct list_head *ptr;
 	struct pl061_gpio *chip;
 
-	desc->chip->ack(irq);
+	desc->irq_data.chip->irq_ack(&desc->irq_data);
 	list_for_each(ptr, chip_list) {
 		unsigned long pending;
 		int offset;
@@ -229,7 +229,7 @@ static void pl061_irq_handler(unsigned i
 		for_each_set_bit(offset, &pending, PL061_GPIO_NR)
 			generic_handle_irq(pl061_to_irq(&chip->gc, offset));
 	}
-	desc->chip->unmask(irq);
+	desc->irq_data.chip->irq_unmask(&desc->irq_data);
 }
 
 static int pl061_probe(struct amba_device *dev, struct amba_id *id)
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpio/stmpe-gpio.c linux-libre-2.6.38-gnu1/drivers/gpio/stmpe-gpio.c
--- linux-libre-2.6.37-gnu1/drivers/gpio/stmpe-gpio.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpio/stmpe-gpio.c	2011-03-14 21:20:32.000000000 -0400
@@ -122,10 +122,10 @@ static struct gpio_chip template_chip =
 	.can_sleep		= 1,
 };
 
-static int stmpe_gpio_irq_set_type(unsigned int irq, unsigned int type)
+static int stmpe_gpio_irq_set_type(struct irq_data *d, unsigned int type)
 {
-	struct stmpe_gpio *stmpe_gpio = get_irq_chip_data(irq);
-	int offset = irq - stmpe_gpio->irq_base;
+	struct stmpe_gpio *stmpe_gpio = irq_data_get_irq_chip_data(d);
+	int offset = d->irq - stmpe_gpio->irq_base;
 	int regoffset = offset / 8;
 	int mask = 1 << (offset % 8);
 
@@ -145,16 +145,16 @@ static int stmpe_gpio_irq_set_type(unsig
 	return 0;
 }
 
-static void stmpe_gpio_irq_lock(unsigned int irq)
+static void stmpe_gpio_irq_lock(struct irq_data *d)
 {
-	struct stmpe_gpio *stmpe_gpio = get_irq_chip_data(irq);
+	struct stmpe_gpio *stmpe_gpio = irq_data_get_irq_chip_data(d);
 
 	mutex_lock(&stmpe_gpio->irq_lock);
 }
 
-static void stmpe_gpio_irq_sync_unlock(unsigned int irq)
+static void stmpe_gpio_irq_sync_unlock(struct irq_data *d)
 {
-	struct stmpe_gpio *stmpe_gpio = get_irq_chip_data(irq);
+	struct stmpe_gpio *stmpe_gpio = irq_data_get_irq_chip_data(d);
 	struct stmpe *stmpe = stmpe_gpio->stmpe;
 	int num_banks = DIV_ROUND_UP(stmpe->num_gpios, 8);
 	static const u8 regmap[] = {
@@ -180,20 +180,20 @@ static void stmpe_gpio_irq_sync_unlock(u
 	mutex_unlock(&stmpe_gpio->irq_lock);
 }
 
-static void stmpe_gpio_irq_mask(unsigned int irq)
+static void stmpe_gpio_irq_mask(struct irq_data *d)
 {
-	struct stmpe_gpio *stmpe_gpio = get_irq_chip_data(irq);
-	int offset = irq - stmpe_gpio->irq_base;
+	struct stmpe_gpio *stmpe_gpio = irq_data_get_irq_chip_data(d);
+	int offset = d->irq - stmpe_gpio->irq_base;
 	int regoffset = offset / 8;
 	int mask = 1 << (offset % 8);
 
 	stmpe_gpio->regs[REG_IE][regoffset] &= ~mask;
 }
 
-static void stmpe_gpio_irq_unmask(unsigned int irq)
+static void stmpe_gpio_irq_unmask(struct irq_data *d)
 {
-	struct stmpe_gpio *stmpe_gpio = get_irq_chip_data(irq);
-	int offset = irq - stmpe_gpio->irq_base;
+	struct stmpe_gpio *stmpe_gpio = irq_data_get_irq_chip_data(d);
+	int offset = d->irq - stmpe_gpio->irq_base;
 	int regoffset = offset / 8;
 	int mask = 1 << (offset % 8);
 
@@ -202,11 +202,11 @@ static void stmpe_gpio_irq_unmask(unsign
 
 static struct irq_chip stmpe_gpio_irq_chip = {
 	.name			= "stmpe-gpio",
-	.bus_lock		= stmpe_gpio_irq_lock,
-	.bus_sync_unlock	= stmpe_gpio_irq_sync_unlock,
-	.mask			= stmpe_gpio_irq_mask,
-	.unmask			= stmpe_gpio_irq_unmask,
-	.set_type		= stmpe_gpio_irq_set_type,
+	.irq_bus_lock		= stmpe_gpio_irq_lock,
+	.irq_bus_sync_unlock	= stmpe_gpio_irq_sync_unlock,
+	.irq_mask		= stmpe_gpio_irq_mask,
+	.irq_unmask		= stmpe_gpio_irq_unmask,
+	.irq_set_type		= stmpe_gpio_irq_set_type,
 };
 
 static irqreturn_t stmpe_gpio_irq(int irq, void *dev)
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpio/sx150x.c linux-libre-2.6.38-gnu1/drivers/gpio/sx150x.c
--- linux-libre-2.6.37-gnu1/drivers/gpio/sx150x.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpio/sx150x.c	2011-03-14 21:20:32.000000000 -0400
@@ -304,36 +304,36 @@ static int sx150x_gpio_to_irq(struct gpi
 	return chip->irq_base + offset;
 }
 
-static void sx150x_irq_mask(unsigned int irq)
+static void sx150x_irq_mask(struct irq_data *d)
 {
-	struct irq_chip *ic = get_irq_chip(irq);
+	struct irq_chip *ic = irq_data_get_irq_chip(d);
 	struct sx150x_chip *chip;
 	unsigned n;
 
 	chip = container_of(ic, struct sx150x_chip, irq_chip);
-	n = irq - chip->irq_base;
+	n = d->irq - chip->irq_base;
 
 	sx150x_write_cfg(chip, n, 1, chip->dev_cfg->reg_irq_mask, 1);
 	sx150x_write_cfg(chip, n, 2, chip->dev_cfg->reg_sense, 0);
 }
 
-static void sx150x_irq_unmask(unsigned int irq)
+static void sx150x_irq_unmask(struct irq_data *d)
 {
-	struct irq_chip *ic = get_irq_chip(irq);
+	struct irq_chip *ic = irq_data_get_irq_chip(d);
 	struct sx150x_chip *chip;
 	unsigned n;
 
 	chip = container_of(ic, struct sx150x_chip, irq_chip);
-	n = irq - chip->irq_base;
+	n = d->irq - chip->irq_base;
 
 	sx150x_write_cfg(chip, n, 1, chip->dev_cfg->reg_irq_mask, 0);
 	sx150x_write_cfg(chip, n, 2, chip->dev_cfg->reg_sense,
 			 chip->irq_sense >> (n * 2));
 }
 
-static int sx150x_irq_set_type(unsigned int irq, unsigned int flow_type)
+static int sx150x_irq_set_type(struct irq_data *d, unsigned int flow_type)
 {
-	struct irq_chip *ic = get_irq_chip(irq);
+	struct irq_chip *ic = irq_data_get_irq_chip(d);
 	struct sx150x_chip *chip;
 	unsigned n, val = 0;
 
@@ -341,7 +341,7 @@ static int sx150x_irq_set_type(unsigned
 		return -EINVAL;
 
 	chip = container_of(ic, struct sx150x_chip, irq_chip);
-	n = irq - chip->irq_base;
+	n = d->irq - chip->irq_base;
 
 	if (flow_type & IRQ_TYPE_EDGE_RISING)
 		val |= 0x1;
@@ -386,9 +386,9 @@ static irqreturn_t sx150x_irq_thread_fn(
 	return (nhandled > 0 ? IRQ_HANDLED : IRQ_NONE);
 }
 
-static void sx150x_irq_bus_lock(unsigned int irq)
+static void sx150x_irq_bus_lock(struct irq_data *d)
 {
-	struct irq_chip *ic = get_irq_chip(irq);
+	struct irq_chip *ic = irq_data_get_irq_chip(d);
 	struct sx150x_chip *chip;
 
 	chip = container_of(ic, struct sx150x_chip, irq_chip);
@@ -396,9 +396,9 @@ static void sx150x_irq_bus_lock(unsigned
 	mutex_lock(&chip->lock);
 }
 
-static void sx150x_irq_bus_sync_unlock(unsigned int irq)
+static void sx150x_irq_bus_sync_unlock(struct irq_data *d)
 {
-	struct irq_chip *ic = get_irq_chip(irq);
+	struct irq_chip *ic = irq_data_get_irq_chip(d);
 	struct sx150x_chip *chip;
 	unsigned n;
 
@@ -437,16 +437,16 @@ static void sx150x_init_chip(struct sx15
 	if (pdata->oscio_is_gpo)
 		++chip->gpio_chip.ngpio;
 
-	chip->irq_chip.name            = client->name;
-	chip->irq_chip.mask            = sx150x_irq_mask;
-	chip->irq_chip.unmask          = sx150x_irq_unmask;
-	chip->irq_chip.set_type        = sx150x_irq_set_type;
-	chip->irq_chip.bus_lock        = sx150x_irq_bus_lock;
-	chip->irq_chip.bus_sync_unlock = sx150x_irq_bus_sync_unlock;
-	chip->irq_summary              = -1;
-	chip->irq_base                 = -1;
-	chip->irq_sense                = 0;
-	chip->irq_set_type_pending     = 0;
+	chip->irq_chip.name                = client->name;
+	chip->irq_chip.irq_mask            = sx150x_irq_mask;
+	chip->irq_chip.irq_unmask          = sx150x_irq_unmask;
+	chip->irq_chip.irq_set_type        = sx150x_irq_set_type;
+	chip->irq_chip.irq_bus_lock        = sx150x_irq_bus_lock;
+	chip->irq_chip.irq_bus_sync_unlock = sx150x_irq_bus_sync_unlock;
+	chip->irq_summary                  = -1;
+	chip->irq_base                     = -1;
+	chip->irq_sense                    = 0;
+	chip->irq_set_type_pending         = 0;
 }
 
 static int sx150x_init_io(struct sx150x_chip *chip, u8 base, u16 cfg)
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpio/tc35892-gpio.c linux-libre-2.6.38-gnu1/drivers/gpio/tc35892-gpio.c
--- linux-libre-2.6.37-gnu1/drivers/gpio/tc35892-gpio.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpio/tc35892-gpio.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,389 +0,0 @@
-/*
- * Copyright (C) ST-Ericsson SA 2010
- *
- * License Terms: GNU General Public License, version 2
- * Author: Hanumath Prasad <hanumath.prasad@stericsson.com> for ST-Ericsson
- * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-#include <linux/gpio.h>
-#include <linux/irq.h>
-#include <linux/interrupt.h>
-#include <linux/mfd/tc35892.h>
-
-/*
- * These registers are modified under the irq bus lock and cached to avoid
- * unnecessary writes in bus_sync_unlock.
- */
-enum { REG_IBE, REG_IEV, REG_IS, REG_IE };
-
-#define CACHE_NR_REGS	4
-#define CACHE_NR_BANKS	3
-
-struct tc35892_gpio {
-	struct gpio_chip chip;
-	struct tc35892 *tc35892;
-	struct device *dev;
-	struct mutex irq_lock;
-
-	int irq_base;
-
-	/* Caches of interrupt control registers for bus_lock */
-	u8 regs[CACHE_NR_REGS][CACHE_NR_BANKS];
-	u8 oldregs[CACHE_NR_REGS][CACHE_NR_BANKS];
-};
-
-static inline struct tc35892_gpio *to_tc35892_gpio(struct gpio_chip *chip)
-{
-	return container_of(chip, struct tc35892_gpio, chip);
-}
-
-static int tc35892_gpio_get(struct gpio_chip *chip, unsigned offset)
-{
-	struct tc35892_gpio *tc35892_gpio = to_tc35892_gpio(chip);
-	struct tc35892 *tc35892 = tc35892_gpio->tc35892;
-	u8 reg = TC35892_GPIODATA0 + (offset / 8) * 2;
-	u8 mask = 1 << (offset % 8);
-	int ret;
-
-	ret = tc35892_reg_read(tc35892, reg);
-	if (ret < 0)
-		return ret;
-
-	return ret & mask;
-}
-
-static void tc35892_gpio_set(struct gpio_chip *chip, unsigned offset, int val)
-{
-	struct tc35892_gpio *tc35892_gpio = to_tc35892_gpio(chip);
-	struct tc35892 *tc35892 = tc35892_gpio->tc35892;
-	u8 reg = TC35892_GPIODATA0 + (offset / 8) * 2;
-	unsigned pos = offset % 8;
-	u8 data[] = {!!val << pos, 1 << pos};
-
-	tc35892_block_write(tc35892, reg, ARRAY_SIZE(data), data);
-}
-
-static int tc35892_gpio_direction_output(struct gpio_chip *chip,
-					 unsigned offset, int val)
-{
-	struct tc35892_gpio *tc35892_gpio = to_tc35892_gpio(chip);
-	struct tc35892 *tc35892 = tc35892_gpio->tc35892;
-	u8 reg = TC35892_GPIODIR0 + offset / 8;
-	unsigned pos = offset % 8;
-
-	tc35892_gpio_set(chip, offset, val);
-
-	return tc35892_set_bits(tc35892, reg, 1 << pos, 1 << pos);
-}
-
-static int tc35892_gpio_direction_input(struct gpio_chip *chip,
-					unsigned offset)
-{
-	struct tc35892_gpio *tc35892_gpio = to_tc35892_gpio(chip);
-	struct tc35892 *tc35892 = tc35892_gpio->tc35892;
-	u8 reg = TC35892_GPIODIR0 + offset / 8;
-	unsigned pos = offset % 8;
-
-	return tc35892_set_bits(tc35892, reg, 1 << pos, 0);
-}
-
-static int tc35892_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
-{
-	struct tc35892_gpio *tc35892_gpio = to_tc35892_gpio(chip);
-
-	return tc35892_gpio->irq_base + offset;
-}
-
-static struct gpio_chip template_chip = {
-	.label			= "tc35892",
-	.owner			= THIS_MODULE,
-	.direction_input	= tc35892_gpio_direction_input,
-	.get			= tc35892_gpio_get,
-	.direction_output	= tc35892_gpio_direction_output,
-	.set			= tc35892_gpio_set,
-	.to_irq			= tc35892_gpio_to_irq,
-	.can_sleep		= 1,
-};
-
-static int tc35892_gpio_irq_set_type(unsigned int irq, unsigned int type)
-{
-	struct tc35892_gpio *tc35892_gpio = get_irq_chip_data(irq);
-	int offset = irq - tc35892_gpio->irq_base;
-	int regoffset = offset / 8;
-	int mask = 1 << (offset % 8);
-
-	if (type == IRQ_TYPE_EDGE_BOTH) {
-		tc35892_gpio->regs[REG_IBE][regoffset] |= mask;
-		return 0;
-	}
-
-	tc35892_gpio->regs[REG_IBE][regoffset] &= ~mask;
-
-	if (type == IRQ_TYPE_LEVEL_LOW || type == IRQ_TYPE_LEVEL_HIGH)
-		tc35892_gpio->regs[REG_IS][regoffset] |= mask;
-	else
-		tc35892_gpio->regs[REG_IS][regoffset] &= ~mask;
-
-	if (type == IRQ_TYPE_EDGE_RISING || type == IRQ_TYPE_LEVEL_HIGH)
-		tc35892_gpio->regs[REG_IEV][regoffset] |= mask;
-	else
-		tc35892_gpio->regs[REG_IEV][regoffset] &= ~mask;
-
-	return 0;
-}
-
-static void tc35892_gpio_irq_lock(unsigned int irq)
-{
-	struct tc35892_gpio *tc35892_gpio = get_irq_chip_data(irq);
-
-	mutex_lock(&tc35892_gpio->irq_lock);
-}
-
-static void tc35892_gpio_irq_sync_unlock(unsigned int irq)
-{
-	struct tc35892_gpio *tc35892_gpio = get_irq_chip_data(irq);
-	struct tc35892 *tc35892 = tc35892_gpio->tc35892;
-	static const u8 regmap[] = {
-		[REG_IBE]	= TC35892_GPIOIBE0,
-		[REG_IEV]	= TC35892_GPIOIEV0,
-		[REG_IS]	= TC35892_GPIOIS0,
-		[REG_IE]	= TC35892_GPIOIE0,
-	};
-	int i, j;
-
-	for (i = 0; i < CACHE_NR_REGS; i++) {
-		for (j = 0; j < CACHE_NR_BANKS; j++) {
-			u8 old = tc35892_gpio->oldregs[i][j];
-			u8 new = tc35892_gpio->regs[i][j];
-
-			if (new == old)
-				continue;
-
-			tc35892_gpio->oldregs[i][j] = new;
-			tc35892_reg_write(tc35892, regmap[i] + j * 8, new);
-		}
-	}
-
-	mutex_unlock(&tc35892_gpio->irq_lock);
-}
-
-static void tc35892_gpio_irq_mask(unsigned int irq)
-{
-	struct tc35892_gpio *tc35892_gpio = get_irq_chip_data(irq);
-	int offset = irq - tc35892_gpio->irq_base;
-	int regoffset = offset / 8;
-	int mask = 1 << (offset % 8);
-
-	tc35892_gpio->regs[REG_IE][regoffset] &= ~mask;
-}
-
-static void tc35892_gpio_irq_unmask(unsigned int irq)
-{
-	struct tc35892_gpio *tc35892_gpio = get_irq_chip_data(irq);
-	int offset = irq - tc35892_gpio->irq_base;
-	int regoffset = offset / 8;
-	int mask = 1 << (offset % 8);
-
-	tc35892_gpio->regs[REG_IE][regoffset] |= mask;
-}
-
-static struct irq_chip tc35892_gpio_irq_chip = {
-	.name			= "tc35892-gpio",
-	.bus_lock		= tc35892_gpio_irq_lock,
-	.bus_sync_unlock	= tc35892_gpio_irq_sync_unlock,
-	.mask			= tc35892_gpio_irq_mask,
-	.unmask			= tc35892_gpio_irq_unmask,
-	.set_type		= tc35892_gpio_irq_set_type,
-};
-
-static irqreturn_t tc35892_gpio_irq(int irq, void *dev)
-{
-	struct tc35892_gpio *tc35892_gpio = dev;
-	struct tc35892 *tc35892 = tc35892_gpio->tc35892;
-	u8 status[CACHE_NR_BANKS];
-	int ret;
-	int i;
-
-	ret = tc35892_block_read(tc35892, TC35892_GPIOMIS0,
-				 ARRAY_SIZE(status), status);
-	if (ret < 0)
-		return IRQ_NONE;
-
-	for (i = 0; i < ARRAY_SIZE(status); i++) {
-		unsigned int stat = status[i];
-		if (!stat)
-			continue;
-
-		while (stat) {
-			int bit = __ffs(stat);
-			int line = i * 8 + bit;
-
-			handle_nested_irq(tc35892_gpio->irq_base + line);
-			stat &= ~(1 << bit);
-		}
-
-		tc35892_reg_write(tc35892, TC35892_GPIOIC0 + i, status[i]);
-	}
-
-	return IRQ_HANDLED;
-}
-
-static int tc35892_gpio_irq_init(struct tc35892_gpio *tc35892_gpio)
-{
-	int base = tc35892_gpio->irq_base;
-	int irq;
-
-	for (irq = base; irq < base + tc35892_gpio->chip.ngpio; irq++) {
-		set_irq_chip_data(irq, tc35892_gpio);
-		set_irq_chip_and_handler(irq, &tc35892_gpio_irq_chip,
-					 handle_simple_irq);
-		set_irq_nested_thread(irq, 1);
-#ifdef CONFIG_ARM
-		set_irq_flags(irq, IRQF_VALID);
-#else
-		set_irq_noprobe(irq);
-#endif
-	}
-
-	return 0;
-}
-
-static void tc35892_gpio_irq_remove(struct tc35892_gpio *tc35892_gpio)
-{
-	int base = tc35892_gpio->irq_base;
-	int irq;
-
-	for (irq = base; irq < base + tc35892_gpio->chip.ngpio; irq++) {
-#ifdef CONFIG_ARM
-		set_irq_flags(irq, 0);
-#endif
-		set_irq_chip_and_handler(irq, NULL, NULL);
-		set_irq_chip_data(irq, NULL);
-	}
-}
-
-static int __devinit tc35892_gpio_probe(struct platform_device *pdev)
-{
-	struct tc35892 *tc35892 = dev_get_drvdata(pdev->dev.parent);
-	struct tc35892_gpio_platform_data *pdata;
-	struct tc35892_gpio *tc35892_gpio;
-	int ret;
-	int irq;
-
-	pdata = tc35892->pdata->gpio;
-	if (!pdata)
-		return -ENODEV;
-
-	irq = platform_get_irq(pdev, 0);
-	if (irq < 0)
-		return irq;
-
-	tc35892_gpio = kzalloc(sizeof(struct tc35892_gpio), GFP_KERNEL);
-	if (!tc35892_gpio)
-		return -ENOMEM;
-
-	mutex_init(&tc35892_gpio->irq_lock);
-
-	tc35892_gpio->dev = &pdev->dev;
-	tc35892_gpio->tc35892 = tc35892;
-
-	tc35892_gpio->chip = template_chip;
-	tc35892_gpio->chip.ngpio = tc35892->num_gpio;
-	tc35892_gpio->chip.dev = &pdev->dev;
-	tc35892_gpio->chip.base = pdata->gpio_base;
-
-	tc35892_gpio->irq_base = tc35892->irq_base + TC35892_INT_GPIO(0);
-
-	/* Bring the GPIO module out of reset */
-	ret = tc35892_set_bits(tc35892, TC35892_RSTCTRL,
-			       TC35892_RSTCTRL_GPIRST, 0);
-	if (ret < 0)
-		goto out_free;
-
-	ret = tc35892_gpio_irq_init(tc35892_gpio);
-	if (ret)
-		goto out_free;
-
-	ret = request_threaded_irq(irq, NULL, tc35892_gpio_irq, IRQF_ONESHOT,
-				   "tc35892-gpio", tc35892_gpio);
-	if (ret) {
-		dev_err(&pdev->dev, "unable to get irq: %d\n", ret);
-		goto out_removeirq;
-	}
-
-	ret = gpiochip_add(&tc35892_gpio->chip);
-	if (ret) {
-		dev_err(&pdev->dev, "unable to add gpiochip: %d\n", ret);
-		goto out_freeirq;
-	}
-
-	if (pdata->setup)
-		pdata->setup(tc35892, tc35892_gpio->chip.base);
-
-	platform_set_drvdata(pdev, tc35892_gpio);
-
-	return 0;
-
-out_freeirq:
-	free_irq(irq, tc35892_gpio);
-out_removeirq:
-	tc35892_gpio_irq_remove(tc35892_gpio);
-out_free:
-	kfree(tc35892_gpio);
-	return ret;
-}
-
-static int __devexit tc35892_gpio_remove(struct platform_device *pdev)
-{
-	struct tc35892_gpio *tc35892_gpio = platform_get_drvdata(pdev);
-	struct tc35892 *tc35892 = tc35892_gpio->tc35892;
-	struct tc35892_gpio_platform_data *pdata = tc35892->pdata->gpio;
-	int irq = platform_get_irq(pdev, 0);
-	int ret;
-
-	if (pdata->remove)
-		pdata->remove(tc35892, tc35892_gpio->chip.base);
-
-	ret = gpiochip_remove(&tc35892_gpio->chip);
-	if (ret < 0) {
-		dev_err(tc35892_gpio->dev,
-			"unable to remove gpiochip: %d\n", ret);
-		return ret;
-	}
-
-	free_irq(irq, tc35892_gpio);
-	tc35892_gpio_irq_remove(tc35892_gpio);
-
-	platform_set_drvdata(pdev, NULL);
-	kfree(tc35892_gpio);
-
-	return 0;
-}
-
-static struct platform_driver tc35892_gpio_driver = {
-	.driver.name	= "tc35892-gpio",
-	.driver.owner	= THIS_MODULE,
-	.probe		= tc35892_gpio_probe,
-	.remove		= __devexit_p(tc35892_gpio_remove),
-};
-
-static int __init tc35892_gpio_init(void)
-{
-	return platform_driver_register(&tc35892_gpio_driver);
-}
-subsys_initcall(tc35892_gpio_init);
-
-static void __exit tc35892_gpio_exit(void)
-{
-	platform_driver_unregister(&tc35892_gpio_driver);
-}
-module_exit(tc35892_gpio_exit);
-
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("TC35892 GPIO driver");
-MODULE_AUTHOR("Hanumath Prasad, Rabin Vincent");
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpio/tc3589x-gpio.c linux-libre-2.6.38-gnu1/drivers/gpio/tc3589x-gpio.c
--- linux-libre-2.6.37-gnu1/drivers/gpio/tc3589x-gpio.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpio/tc3589x-gpio.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,389 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * License Terms: GNU General Public License, version 2
+ * Author: Hanumath Prasad <hanumath.prasad@stericsson.com> for ST-Ericsson
+ * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/gpio.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/mfd/tc3589x.h>
+
+/*
+ * These registers are modified under the irq bus lock and cached to avoid
+ * unnecessary writes in bus_sync_unlock.
+ */
+enum { REG_IBE, REG_IEV, REG_IS, REG_IE };
+
+#define CACHE_NR_REGS	4
+#define CACHE_NR_BANKS	3
+
+struct tc3589x_gpio {
+	struct gpio_chip chip;
+	struct tc3589x *tc3589x;
+	struct device *dev;
+	struct mutex irq_lock;
+
+	int irq_base;
+
+	/* Caches of interrupt control registers for bus_lock */
+	u8 regs[CACHE_NR_REGS][CACHE_NR_BANKS];
+	u8 oldregs[CACHE_NR_REGS][CACHE_NR_BANKS];
+};
+
+static inline struct tc3589x_gpio *to_tc3589x_gpio(struct gpio_chip *chip)
+{
+	return container_of(chip, struct tc3589x_gpio, chip);
+}
+
+static int tc3589x_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+	struct tc3589x_gpio *tc3589x_gpio = to_tc3589x_gpio(chip);
+	struct tc3589x *tc3589x = tc3589x_gpio->tc3589x;
+	u8 reg = TC3589x_GPIODATA0 + (offset / 8) * 2;
+	u8 mask = 1 << (offset % 8);
+	int ret;
+
+	ret = tc3589x_reg_read(tc3589x, reg);
+	if (ret < 0)
+		return ret;
+
+	return ret & mask;
+}
+
+static void tc3589x_gpio_set(struct gpio_chip *chip, unsigned offset, int val)
+{
+	struct tc3589x_gpio *tc3589x_gpio = to_tc3589x_gpio(chip);
+	struct tc3589x *tc3589x = tc3589x_gpio->tc3589x;
+	u8 reg = TC3589x_GPIODATA0 + (offset / 8) * 2;
+	unsigned pos = offset % 8;
+	u8 data[] = {!!val << pos, 1 << pos};
+
+	tc3589x_block_write(tc3589x, reg, ARRAY_SIZE(data), data);
+}
+
+static int tc3589x_gpio_direction_output(struct gpio_chip *chip,
+					 unsigned offset, int val)
+{
+	struct tc3589x_gpio *tc3589x_gpio = to_tc3589x_gpio(chip);
+	struct tc3589x *tc3589x = tc3589x_gpio->tc3589x;
+	u8 reg = TC3589x_GPIODIR0 + offset / 8;
+	unsigned pos = offset % 8;
+
+	tc3589x_gpio_set(chip, offset, val);
+
+	return tc3589x_set_bits(tc3589x, reg, 1 << pos, 1 << pos);
+}
+
+static int tc3589x_gpio_direction_input(struct gpio_chip *chip,
+					unsigned offset)
+{
+	struct tc3589x_gpio *tc3589x_gpio = to_tc3589x_gpio(chip);
+	struct tc3589x *tc3589x = tc3589x_gpio->tc3589x;
+	u8 reg = TC3589x_GPIODIR0 + offset / 8;
+	unsigned pos = offset % 8;
+
+	return tc3589x_set_bits(tc3589x, reg, 1 << pos, 0);
+}
+
+static int tc3589x_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+	struct tc3589x_gpio *tc3589x_gpio = to_tc3589x_gpio(chip);
+
+	return tc3589x_gpio->irq_base + offset;
+}
+
+static struct gpio_chip template_chip = {
+	.label			= "tc3589x",
+	.owner			= THIS_MODULE,
+	.direction_input	= tc3589x_gpio_direction_input,
+	.get			= tc3589x_gpio_get,
+	.direction_output	= tc3589x_gpio_direction_output,
+	.set			= tc3589x_gpio_set,
+	.to_irq			= tc3589x_gpio_to_irq,
+	.can_sleep		= 1,
+};
+
+static int tc3589x_gpio_irq_set_type(struct irq_data *d, unsigned int type)
+{
+	struct tc3589x_gpio *tc3589x_gpio = irq_data_get_irq_chip_data(d);
+	int offset = d->irq - tc3589x_gpio->irq_base;
+	int regoffset = offset / 8;
+	int mask = 1 << (offset % 8);
+
+	if (type == IRQ_TYPE_EDGE_BOTH) {
+		tc3589x_gpio->regs[REG_IBE][regoffset] |= mask;
+		return 0;
+	}
+
+	tc3589x_gpio->regs[REG_IBE][regoffset] &= ~mask;
+
+	if (type == IRQ_TYPE_LEVEL_LOW || type == IRQ_TYPE_LEVEL_HIGH)
+		tc3589x_gpio->regs[REG_IS][regoffset] |= mask;
+	else
+		tc3589x_gpio->regs[REG_IS][regoffset] &= ~mask;
+
+	if (type == IRQ_TYPE_EDGE_RISING || type == IRQ_TYPE_LEVEL_HIGH)
+		tc3589x_gpio->regs[REG_IEV][regoffset] |= mask;
+	else
+		tc3589x_gpio->regs[REG_IEV][regoffset] &= ~mask;
+
+	return 0;
+}
+
+static void tc3589x_gpio_irq_lock(struct irq_data *d)
+{
+	struct tc3589x_gpio *tc3589x_gpio = irq_data_get_irq_chip_data(d);
+
+	mutex_lock(&tc3589x_gpio->irq_lock);
+}
+
+static void tc3589x_gpio_irq_sync_unlock(struct irq_data *d)
+{
+	struct tc3589x_gpio *tc3589x_gpio = irq_data_get_irq_chip_data(d);
+	struct tc3589x *tc3589x = tc3589x_gpio->tc3589x;
+	static const u8 regmap[] = {
+		[REG_IBE]	= TC3589x_GPIOIBE0,
+		[REG_IEV]	= TC3589x_GPIOIEV0,
+		[REG_IS]	= TC3589x_GPIOIS0,
+		[REG_IE]	= TC3589x_GPIOIE0,
+	};
+	int i, j;
+
+	for (i = 0; i < CACHE_NR_REGS; i++) {
+		for (j = 0; j < CACHE_NR_BANKS; j++) {
+			u8 old = tc3589x_gpio->oldregs[i][j];
+			u8 new = tc3589x_gpio->regs[i][j];
+
+			if (new == old)
+				continue;
+
+			tc3589x_gpio->oldregs[i][j] = new;
+			tc3589x_reg_write(tc3589x, regmap[i] + j * 8, new);
+		}
+	}
+
+	mutex_unlock(&tc3589x_gpio->irq_lock);
+}
+
+static void tc3589x_gpio_irq_mask(struct irq_data *d)
+{
+	struct tc3589x_gpio *tc3589x_gpio = irq_data_get_irq_chip_data(d);
+	int offset = d->irq - tc3589x_gpio->irq_base;
+	int regoffset = offset / 8;
+	int mask = 1 << (offset % 8);
+
+	tc3589x_gpio->regs[REG_IE][regoffset] &= ~mask;
+}
+
+static void tc3589x_gpio_irq_unmask(struct irq_data *d)
+{
+	struct tc3589x_gpio *tc3589x_gpio = irq_data_get_irq_chip_data(d);
+	int offset = d->irq - tc3589x_gpio->irq_base;
+	int regoffset = offset / 8;
+	int mask = 1 << (offset % 8);
+
+	tc3589x_gpio->regs[REG_IE][regoffset] |= mask;
+}
+
+static struct irq_chip tc3589x_gpio_irq_chip = {
+	.name			= "tc3589x-gpio",
+	.irq_bus_lock		= tc3589x_gpio_irq_lock,
+	.irq_bus_sync_unlock	= tc3589x_gpio_irq_sync_unlock,
+	.irq_mask		= tc3589x_gpio_irq_mask,
+	.irq_unmask		= tc3589x_gpio_irq_unmask,
+	.irq_set_type		= tc3589x_gpio_irq_set_type,
+};
+
+static irqreturn_t tc3589x_gpio_irq(int irq, void *dev)
+{
+	struct tc3589x_gpio *tc3589x_gpio = dev;
+	struct tc3589x *tc3589x = tc3589x_gpio->tc3589x;
+	u8 status[CACHE_NR_BANKS];
+	int ret;
+	int i;
+
+	ret = tc3589x_block_read(tc3589x, TC3589x_GPIOMIS0,
+				 ARRAY_SIZE(status), status);
+	if (ret < 0)
+		return IRQ_NONE;
+
+	for (i = 0; i < ARRAY_SIZE(status); i++) {
+		unsigned int stat = status[i];
+		if (!stat)
+			continue;
+
+		while (stat) {
+			int bit = __ffs(stat);
+			int line = i * 8 + bit;
+
+			handle_nested_irq(tc3589x_gpio->irq_base + line);
+			stat &= ~(1 << bit);
+		}
+
+		tc3589x_reg_write(tc3589x, TC3589x_GPIOIC0 + i, status[i]);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static int tc3589x_gpio_irq_init(struct tc3589x_gpio *tc3589x_gpio)
+{
+	int base = tc3589x_gpio->irq_base;
+	int irq;
+
+	for (irq = base; irq < base + tc3589x_gpio->chip.ngpio; irq++) {
+		set_irq_chip_data(irq, tc3589x_gpio);
+		set_irq_chip_and_handler(irq, &tc3589x_gpio_irq_chip,
+					 handle_simple_irq);
+		set_irq_nested_thread(irq, 1);
+#ifdef CONFIG_ARM
+		set_irq_flags(irq, IRQF_VALID);
+#else
+		set_irq_noprobe(irq);
+#endif
+	}
+
+	return 0;
+}
+
+static void tc3589x_gpio_irq_remove(struct tc3589x_gpio *tc3589x_gpio)
+{
+	int base = tc3589x_gpio->irq_base;
+	int irq;
+
+	for (irq = base; irq < base + tc3589x_gpio->chip.ngpio; irq++) {
+#ifdef CONFIG_ARM
+		set_irq_flags(irq, 0);
+#endif
+		set_irq_chip_and_handler(irq, NULL, NULL);
+		set_irq_chip_data(irq, NULL);
+	}
+}
+
+static int __devinit tc3589x_gpio_probe(struct platform_device *pdev)
+{
+	struct tc3589x *tc3589x = dev_get_drvdata(pdev->dev.parent);
+	struct tc3589x_gpio_platform_data *pdata;
+	struct tc3589x_gpio *tc3589x_gpio;
+	int ret;
+	int irq;
+
+	pdata = tc3589x->pdata->gpio;
+	if (!pdata)
+		return -ENODEV;
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0)
+		return irq;
+
+	tc3589x_gpio = kzalloc(sizeof(struct tc3589x_gpio), GFP_KERNEL);
+	if (!tc3589x_gpio)
+		return -ENOMEM;
+
+	mutex_init(&tc3589x_gpio->irq_lock);
+
+	tc3589x_gpio->dev = &pdev->dev;
+	tc3589x_gpio->tc3589x = tc3589x;
+
+	tc3589x_gpio->chip = template_chip;
+	tc3589x_gpio->chip.ngpio = tc3589x->num_gpio;
+	tc3589x_gpio->chip.dev = &pdev->dev;
+	tc3589x_gpio->chip.base = pdata->gpio_base;
+
+	tc3589x_gpio->irq_base = tc3589x->irq_base + TC3589x_INT_GPIO(0);
+
+	/* Bring the GPIO module out of reset */
+	ret = tc3589x_set_bits(tc3589x, TC3589x_RSTCTRL,
+			       TC3589x_RSTCTRL_GPIRST, 0);
+	if (ret < 0)
+		goto out_free;
+
+	ret = tc3589x_gpio_irq_init(tc3589x_gpio);
+	if (ret)
+		goto out_free;
+
+	ret = request_threaded_irq(irq, NULL, tc3589x_gpio_irq, IRQF_ONESHOT,
+				   "tc3589x-gpio", tc3589x_gpio);
+	if (ret) {
+		dev_err(&pdev->dev, "unable to get irq: %d\n", ret);
+		goto out_removeirq;
+	}
+
+	ret = gpiochip_add(&tc3589x_gpio->chip);
+	if (ret) {
+		dev_err(&pdev->dev, "unable to add gpiochip: %d\n", ret);
+		goto out_freeirq;
+	}
+
+	if (pdata->setup)
+		pdata->setup(tc3589x, tc3589x_gpio->chip.base);
+
+	platform_set_drvdata(pdev, tc3589x_gpio);
+
+	return 0;
+
+out_freeirq:
+	free_irq(irq, tc3589x_gpio);
+out_removeirq:
+	tc3589x_gpio_irq_remove(tc3589x_gpio);
+out_free:
+	kfree(tc3589x_gpio);
+	return ret;
+}
+
+static int __devexit tc3589x_gpio_remove(struct platform_device *pdev)
+{
+	struct tc3589x_gpio *tc3589x_gpio = platform_get_drvdata(pdev);
+	struct tc3589x *tc3589x = tc3589x_gpio->tc3589x;
+	struct tc3589x_gpio_platform_data *pdata = tc3589x->pdata->gpio;
+	int irq = platform_get_irq(pdev, 0);
+	int ret;
+
+	if (pdata->remove)
+		pdata->remove(tc3589x, tc3589x_gpio->chip.base);
+
+	ret = gpiochip_remove(&tc3589x_gpio->chip);
+	if (ret < 0) {
+		dev_err(tc3589x_gpio->dev,
+			"unable to remove gpiochip: %d\n", ret);
+		return ret;
+	}
+
+	free_irq(irq, tc3589x_gpio);
+	tc3589x_gpio_irq_remove(tc3589x_gpio);
+
+	platform_set_drvdata(pdev, NULL);
+	kfree(tc3589x_gpio);
+
+	return 0;
+}
+
+static struct platform_driver tc3589x_gpio_driver = {
+	.driver.name	= "tc3589x-gpio",
+	.driver.owner	= THIS_MODULE,
+	.probe		= tc3589x_gpio_probe,
+	.remove		= __devexit_p(tc3589x_gpio_remove),
+};
+
+static int __init tc3589x_gpio_init(void)
+{
+	return platform_driver_register(&tc3589x_gpio_driver);
+}
+subsys_initcall(tc3589x_gpio_init);
+
+static void __exit tc3589x_gpio_exit(void)
+{
+	platform_driver_unregister(&tc3589x_gpio_driver);
+}
+module_exit(tc3589x_gpio_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("TC3589x GPIO driver");
+MODULE_AUTHOR("Hanumath Prasad, Rabin Vincent");
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpio/timbgpio.c linux-libre-2.6.38-gnu1/drivers/gpio/timbgpio.c
--- linux-libre-2.6.37-gnu1/drivers/gpio/timbgpio.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpio/timbgpio.c	2011-03-14 21:20:32.000000000 -0400
@@ -109,10 +109,10 @@ static int timbgpio_to_irq(struct gpio_c
 /*
  * GPIO IRQ
  */
-static void timbgpio_irq_disable(unsigned irq)
+static void timbgpio_irq_disable(struct irq_data *d)
 {
-	struct timbgpio *tgpio = get_irq_chip_data(irq);
-	int offset = irq - tgpio->irq_base;
+	struct timbgpio *tgpio = irq_data_get_irq_chip_data(d);
+	int offset = d->irq - tgpio->irq_base;
 	unsigned long flags;
 
 	spin_lock_irqsave(&tgpio->lock, flags);
@@ -121,10 +121,10 @@ static void timbgpio_irq_disable(unsigne
 	spin_unlock_irqrestore(&tgpio->lock, flags);
 }
 
-static void timbgpio_irq_enable(unsigned irq)
+static void timbgpio_irq_enable(struct irq_data *d)
 {
-	struct timbgpio *tgpio = get_irq_chip_data(irq);
-	int offset = irq - tgpio->irq_base;
+	struct timbgpio *tgpio = irq_data_get_irq_chip_data(d);
+	int offset = d->irq - tgpio->irq_base;
 	unsigned long flags;
 
 	spin_lock_irqsave(&tgpio->lock, flags);
@@ -133,10 +133,10 @@ static void timbgpio_irq_enable(unsigned
 	spin_unlock_irqrestore(&tgpio->lock, flags);
 }
 
-static int timbgpio_irq_type(unsigned irq, unsigned trigger)
+static int timbgpio_irq_type(struct irq_data *d, unsigned trigger)
 {
-	struct timbgpio *tgpio = get_irq_chip_data(irq);
-	int offset = irq - tgpio->irq_base;
+	struct timbgpio *tgpio = irq_data_get_irq_chip_data(d);
+	int offset = d->irq - tgpio->irq_base;
 	unsigned long flags;
 	u32 lvr, flr, bflr = 0;
 	u32 ver;
@@ -199,7 +199,7 @@ static void timbgpio_irq(unsigned int ir
 	unsigned long ipr;
 	int offset;
 
-	desc->chip->ack(irq);
+	desc->irq_data.chip->irq_ack(irq_get_irq_data(irq));
 	ipr = ioread32(tgpio->membase + TGPIO_IPR);
 	iowrite32(ipr, tgpio->membase + TGPIO_ICR);
 
@@ -217,9 +217,9 @@ static void timbgpio_irq(unsigned int ir
 
 static struct irq_chip timbgpio_irqchip = {
 	.name		= "GPIO",
-	.enable		= timbgpio_irq_enable,
-	.disable	= timbgpio_irq_disable,
-	.set_type	= timbgpio_irq_type,
+	.irq_enable	= timbgpio_irq_enable,
+	.irq_disable	= timbgpio_irq_disable,
+	.irq_set_type	= timbgpio_irq_type,
 };
 
 static int __devinit timbgpio_probe(struct platform_device *pdev)
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpio/vr41xx_giu.c linux-libre-2.6.38-gnu1/drivers/gpio/vr41xx_giu.c
--- linux-libre-2.6.37-gnu1/drivers/gpio/vr41xx_giu.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpio/vr41xx_giu.c	2011-03-14 21:20:32.000000000 -0400
@@ -111,69 +111,69 @@ static inline u16 giu_clear(u16 offset,
 	return data;
 }
 
-static void ack_giuint_low(unsigned int irq)
+static void ack_giuint_low(struct irq_data *d)
 {
-	giu_write(GIUINTSTATL, 1 << GPIO_PIN_OF_IRQ(irq));
+	giu_write(GIUINTSTATL, 1 << GPIO_PIN_OF_IRQ(d->irq));
 }
 
-static void mask_giuint_low(unsigned int irq)
+static void mask_giuint_low(struct irq_data *d)
 {
-	giu_clear(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(irq));
+	giu_clear(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(d->irq));
 }
 
-static void mask_ack_giuint_low(unsigned int irq)
+static void mask_ack_giuint_low(struct irq_data *d)
 {
 	unsigned int pin;
 
-	pin = GPIO_PIN_OF_IRQ(irq);
+	pin = GPIO_PIN_OF_IRQ(d->irq);
 	giu_clear(GIUINTENL, 1 << pin);
 	giu_write(GIUINTSTATL, 1 << pin);
 }
 
-static void unmask_giuint_low(unsigned int irq)
+static void unmask_giuint_low(struct irq_data *d)
 {
-	giu_set(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(irq));
+	giu_set(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(d->irq));
 }
 
 static struct irq_chip giuint_low_irq_chip = {
 	.name		= "GIUINTL",
-	.ack		= ack_giuint_low,
-	.mask		= mask_giuint_low,
-	.mask_ack	= mask_ack_giuint_low,
-	.unmask		= unmask_giuint_low,
+	.irq_ack	= ack_giuint_low,
+	.irq_mask	= mask_giuint_low,
+	.irq_mask_ack	= mask_ack_giuint_low,
+	.irq_unmask	= unmask_giuint_low,
 };
 
-static void ack_giuint_high(unsigned int irq)
+static void ack_giuint_high(struct irq_data *d)
 {
 	giu_write(GIUINTSTATH,
-		  1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET));
+		  1 << (GPIO_PIN_OF_IRQ(d->irq) - GIUINT_HIGH_OFFSET));
 }
 
-static void mask_giuint_high(unsigned int irq)
+static void mask_giuint_high(struct irq_data *d)
 {
-	giu_clear(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET));
+	giu_clear(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(d->irq) - GIUINT_HIGH_OFFSET));
 }
 
-static void mask_ack_giuint_high(unsigned int irq)
+static void mask_ack_giuint_high(struct irq_data *d)
 {
 	unsigned int pin;
 
-	pin = GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET;
+	pin = GPIO_PIN_OF_IRQ(d->irq) - GIUINT_HIGH_OFFSET;
 	giu_clear(GIUINTENH, 1 << pin);
 	giu_write(GIUINTSTATH, 1 << pin);
 }
 
-static void unmask_giuint_high(unsigned int irq)
+static void unmask_giuint_high(struct irq_data *d)
 {
-	giu_set(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET));
+	giu_set(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(d->irq) - GIUINT_HIGH_OFFSET));
 }
 
 static struct irq_chip giuint_high_irq_chip = {
 	.name		= "GIUINTH",
-	.ack		= ack_giuint_high,
-	.mask		= mask_giuint_high,
-	.mask_ack	= mask_ack_giuint_high,
-	.unmask		= unmask_giuint_high,
+	.irq_ack	= ack_giuint_high,
+	.irq_mask	= mask_giuint_high,
+	.irq_mask_ack	= mask_ack_giuint_high,
+	.irq_unmask	= unmask_giuint_high,
 };
 
 static int giu_get_irq(unsigned int irq)
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpio/wm8994-gpio.c linux-libre-2.6.38-gnu1/drivers/gpio/wm8994-gpio.c
--- linux-libre-2.6.37-gnu1/drivers/gpio/wm8994-gpio.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpio/wm8994-gpio.c	2011-03-14 21:20:32.000000000 -0400
@@ -35,6 +35,29 @@ static inline struct wm8994_gpio *to_wm8
 	return container_of(chip, struct wm8994_gpio, gpio_chip);
 }
 
+static int wm8994_gpio_request(struct gpio_chip *chip, unsigned offset)
+{
+	struct wm8994_gpio *wm8994_gpio = to_wm8994_gpio(chip);
+	struct wm8994 *wm8994 = wm8994_gpio->wm8994;
+
+	switch (wm8994->type) {
+	case WM8958:
+		switch (offset) {
+		case 1:
+		case 2:
+		case 3:
+		case 4:
+		case 6:
+			return -EINVAL;
+		}
+		break;
+	default:
+		break;
+	}
+
+	return 0;
+}
+
 static int wm8994_gpio_direction_in(struct gpio_chip *chip, unsigned offset)
 {
 	struct wm8994_gpio *wm8994_gpio = to_wm8994_gpio(chip);
@@ -136,6 +159,7 @@ static void wm8994_gpio_dbg_show(struct
 static struct gpio_chip template_chip = {
 	.label			= "wm8994",
 	.owner			= THIS_MODULE,
+	.request		= wm8994_gpio_request,
 	.direction_input	= wm8994_gpio_direction_in,
 	.get			= wm8994_gpio_get,
 	.direction_output	= wm8994_gpio_direction_out,
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/drm_agpsupport.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/drm_agpsupport.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/drm_agpsupport.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/drm_agpsupport.c	2011-03-14 21:20:32.000000000 -0400
@@ -466,10 +466,4 @@ drm_agp_bind_pages(struct drm_device *de
 }
 EXPORT_SYMBOL(drm_agp_bind_pages);
 
-void drm_agp_chipset_flush(struct drm_device *dev)
-{
-	agp_flush_chipset(dev->agp->bridge);
-}
-EXPORT_SYMBOL(drm_agp_chipset_flush);
-
 #endif /* __OS_HAS_AGP */
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/drm_crtc.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/drm_crtc.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/drm_crtc.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/drm_crtc.c	2011-03-14 21:20:32.000000000 -0400
@@ -2674,3 +2674,23 @@ out:
 	mutex_unlock(&dev->mode_config.mutex);
 	return ret;
 }
+
+void drm_mode_config_reset(struct drm_device *dev)
+{
+	struct drm_crtc *crtc;
+	struct drm_encoder *encoder;
+	struct drm_connector *connector;
+
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
+		if (crtc->funcs->reset)
+			crtc->funcs->reset(crtc);
+
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head)
+		if (encoder->funcs->reset)
+			encoder->funcs->reset(encoder);
+
+	list_for_each_entry(connector, &dev->mode_config.connector_list, head)
+		if (connector->funcs->reset)
+			connector->funcs->reset(connector);
+}
+EXPORT_SYMBOL(drm_mode_config_reset);
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/drm_crtc_helper.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/drm_crtc_helper.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/drm_crtc_helper.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/drm_crtc_helper.c	2011-03-14 21:20:32.000000000 -0400
@@ -336,20 +336,20 @@ bool drm_crtc_helper_set_mode(struct drm
 			      struct drm_framebuffer *old_fb)
 {
 	struct drm_device *dev = crtc->dev;
-	struct drm_display_mode *adjusted_mode, saved_mode;
+	struct drm_display_mode *adjusted_mode, saved_mode, saved_hwmode;
 	struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
 	struct drm_encoder_helper_funcs *encoder_funcs;
 	int saved_x, saved_y;
 	struct drm_encoder *encoder;
 	bool ret = true;
 
-	adjusted_mode = drm_mode_duplicate(dev, mode);
-
 	crtc->enabled = drm_helper_crtc_in_use(crtc);
-
 	if (!crtc->enabled)
 		return true;
 
+	adjusted_mode = drm_mode_duplicate(dev, mode);
+
+	saved_hwmode = crtc->hwmode;
 	saved_mode = crtc->mode;
 	saved_x = crtc->x;
 	saved_y = crtc->y;
@@ -427,11 +427,20 @@ bool drm_crtc_helper_set_mode(struct drm
 
 	}
 
-	/* XXX free adjustedmode */
-	drm_mode_destroy(dev, adjusted_mode);
+	/* Store real post-adjustment hardware mode. */
+	crtc->hwmode = *adjusted_mode;
+
+	/* Calculate and store various constants which
+	 * are later needed by vblank and swap-completion
+	 * timestamping. They are derived from true hwmode.
+	 */
+	drm_calc_timestamping_constants(crtc);
+
 	/* FIXME: add subpixel order */
 done:
+	drm_mode_destroy(dev, adjusted_mode);
 	if (!ret) {
+		crtc->hwmode = saved_hwmode;
 		crtc->mode = saved_mode;
 		crtc->x = saved_x;
 		crtc->y = saved_y;
@@ -486,14 +495,17 @@ int drm_crtc_helper_set_config(struct dr
 
 	crtc_funcs = set->crtc->helper_private;
 
+	if (!set->mode)
+		set->fb = NULL;
+
 	if (set->fb) {
 		DRM_DEBUG_KMS("[CRTC:%d] [FB:%d] #connectors=%d (x y) (%i %i)\n",
 				set->crtc->base.id, set->fb->base.id,
 				(int)set->num_connectors, set->x, set->y);
 	} else {
-		DRM_DEBUG_KMS("[CRTC:%d] [NOFB] #connectors=%d (x y) (%i %i)\n",
-				set->crtc->base.id, (int)set->num_connectors,
-				set->x, set->y);
+		DRM_DEBUG_KMS("[CRTC:%d] [NOFB]\n", set->crtc->base.id);
+		set->mode = NULL;
+		set->num_connectors = 0;
 	}
 
 	dev = set->crtc->dev;
@@ -638,8 +650,8 @@ int drm_crtc_helper_set_config(struct dr
 		mode_changed = true;
 
 	if (mode_changed) {
-		set->crtc->enabled = (set->mode != NULL);
-		if (set->mode != NULL) {
+		set->crtc->enabled = drm_helper_crtc_in_use(set->crtc);
+		if (set->crtc->enabled) {
 			DRM_DEBUG_KMS("attempting to set mode from"
 					" userspace\n");
 			drm_mode_debug_printmodeline(set->mode);
@@ -650,9 +662,16 @@ int drm_crtc_helper_set_config(struct dr
 						      old_fb)) {
 				DRM_ERROR("failed to set mode on [CRTC:%d]\n",
 					  set->crtc->base.id);
+				set->crtc->fb = old_fb;
 				ret = -EINVAL;
 				goto fail;
 			}
+			DRM_DEBUG_KMS("Setting connector DPMS state to on\n");
+			for (i = 0; i < set->num_connectors; i++) {
+				DRM_DEBUG_KMS("\t[CONNECTOR:%d:%s] set DPMS on\n", set->connectors[i]->base.id,
+					      drm_get_connector_name(set->connectors[i]));
+				set->connectors[i]->dpms = DRM_MODE_DPMS_ON;
+			}
 		}
 		drm_helper_disable_unused_functions(dev);
 	} else if (fb_changed) {
@@ -664,14 +683,10 @@ int drm_crtc_helper_set_config(struct dr
 			set->crtc->fb = set->fb;
 		ret = crtc_funcs->mode_set_base(set->crtc,
 						set->x, set->y, old_fb);
-		if (ret != 0)
+		if (ret != 0) {
+			set->crtc->fb = old_fb;
 			goto fail;
-	}
-	DRM_DEBUG_KMS("Setting connector DPMS state to on\n");
-	for (i = 0; i < set->num_connectors; i++) {
-		DRM_DEBUG_KMS("\t[CONNECTOR:%d:%s] set DPMS on\n", set->connectors[i]->base.id,
-			      drm_get_connector_name(set->connectors[i]));
-		set->connectors[i]->dpms = DRM_MODE_DPMS_ON;
+		}
 	}
 
 	kfree(save_connectors);
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/drm_fb_helper.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/drm_fb_helper.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/drm_fb_helper.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/drm_fb_helper.c	2011-03-14 21:20:32.000000000 -0400
@@ -672,7 +672,7 @@ int drm_fb_helper_setcmap(struct fb_cmap
 	struct drm_crtc_helper_funcs *crtc_funcs;
 	u16 *red, *green, *blue, *transp;
 	struct drm_crtc *crtc;
-	int i, rc = 0;
+	int i, j, rc = 0;
 	int start;
 
 	for (i = 0; i < fb_helper->crtc_count; i++) {
@@ -685,7 +685,7 @@ int drm_fb_helper_setcmap(struct fb_cmap
 		transp = cmap->transp;
 		start = cmap->start;
 
-		for (i = 0; i < cmap->len; i++) {
+		for (j = 0; j < cmap->len; j++) {
 			u16 hred, hgreen, hblue, htransp = 0xffff;
 
 			hred = *red++;
@@ -985,6 +985,8 @@ void drm_fb_helper_fill_fix(struct fb_in
 	info->fix.type = FB_TYPE_PACKED_PIXELS;
 	info->fix.visual = depth == 8 ? FB_VISUAL_PSEUDOCOLOR :
 		FB_VISUAL_TRUECOLOR;
+	info->fix.mmio_start = 0;
+	info->fix.mmio_len = 0;
 	info->fix.type_aux = 0;
 	info->fix.xpanstep = 1; /* doing it in hw */
 	info->fix.ypanstep = 1; /* doing it in hw */
@@ -1005,6 +1007,7 @@ void drm_fb_helper_fill_var(struct fb_in
 	info->var.xres_virtual = fb->width;
 	info->var.yres_virtual = fb->height;
 	info->var.bits_per_pixel = fb->bits_per_pixel;
+	info->var.accel_flags = FB_ACCELF_TEXT;
 	info->var.xoffset = 0;
 	info->var.yoffset = 0;
 	info->var.activate = FB_ACTIVATE_NOW;
@@ -1530,3 +1533,24 @@ bool drm_fb_helper_hotplug_event(struct
 }
 EXPORT_SYMBOL(drm_fb_helper_hotplug_event);
 
+/* The Kconfig DRM_KMS_HELPER selects FRAMEBUFFER_CONSOLE (if !EXPERT)
+ * but the module doesn't depend on any fb console symbols.  At least
+ * attempt to load fbcon to avoid leaving the system without a usable console.
+ */
+#if defined(CONFIG_FRAMEBUFFER_CONSOLE_MODULE) && !defined(CONFIG_EXPERT)
+static int __init drm_fb_helper_modinit(void)
+{
+	const char *name = "fbcon";
+	struct module *fbcon;
+
+	mutex_lock(&module_mutex);
+	fbcon = find_module(name);
+	mutex_unlock(&module_mutex);
+
+	if (!fbcon)
+		request_module_nowait(name);
+	return 0;
+}
+
+module_init(drm_fb_helper_modinit);
+#endif
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/drm_fops.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/drm_fops.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/drm_fops.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/drm_fops.c	2011-03-14 21:20:32.000000000 -0400
@@ -236,6 +236,8 @@ static int drm_open_helper(struct inode
 		return -EBUSY;	/* No exclusive opens */
 	if (!drm_cpu_valid())
 		return -EINVAL;
+	if (dev->switch_power_state != DRM_SWITCH_POWER_ON)
+		return -EINVAL;
 
 	DRM_DEBUG("pid = %d, minor = %d\n", task_pid_nr(current), minor_id);
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/drm_info.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/drm_info.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/drm_info.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/drm_info.c	2011-03-14 21:20:32.000000000 -0400
@@ -283,17 +283,18 @@ int drm_vma_info(struct seq_file *m, voi
 #endif
 
 	mutex_lock(&dev->struct_mutex);
-	seq_printf(m, "vma use count: %d, high_memory = %p, 0x%08llx\n",
+	seq_printf(m, "vma use count: %d, high_memory = %pK, 0x%pK\n",
 		   atomic_read(&dev->vma_count),
-		   high_memory, (u64)virt_to_phys(high_memory));
+		   high_memory, (void *)virt_to_phys(high_memory));
 
 	list_for_each_entry(pt, &dev->vmalist, head) {
 		vma = pt->vma;
 		if (!vma)
 			continue;
 		seq_printf(m,
-			   "\n%5d 0x%08lx-0x%08lx %c%c%c%c%c%c 0x%08lx000",
-			   pt->pid, vma->vm_start, vma->vm_end,
+			   "\n%5d 0x%pK-0x%pK %c%c%c%c%c%c 0x%08lx000",
+			   pt->pid,
+			   (void *)vma->vm_start, (void *)vma->vm_end,
 			   vma->vm_flags & VM_READ ? 'r' : '-',
 			   vma->vm_flags & VM_WRITE ? 'w' : '-',
 			   vma->vm_flags & VM_EXEC ? 'x' : '-',
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/drm_irq.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/drm_irq.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/drm_irq.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/drm_irq.c	2011-03-14 21:20:32.000000000 -0400
@@ -40,6 +40,22 @@
 #include <linux/slab.h>
 
 #include <linux/vgaarb.h>
+
+/* Access macro for slots in vblank timestamp ringbuffer. */
+#define vblanktimestamp(dev, crtc, count) ( \
+	(dev)->_vblank_time[(crtc) * DRM_VBLANKTIME_RBSIZE + \
+	((count) % DRM_VBLANKTIME_RBSIZE)])
+
+/* Retry timestamp calculation up to 3 times to satisfy
+ * drm_timestamp_precision before giving up.
+ */
+#define DRM_TIMESTAMP_MAXRETRIES 3
+
+/* Threshold in nanoseconds for detection of redundant
+ * vblank irq in drm_handle_vblank(). 1 msec should be ok.
+ */
+#define DRM_REDUNDANT_VBLIRQ_THRESH_NS 1000000
+
 /**
  * Get interrupt from bus id.
  *
@@ -77,6 +93,89 @@ int drm_irq_by_busid(struct drm_device *
 	return 0;
 }
 
+/*
+ * Clear vblank timestamp buffer for a crtc.
+ */
+static void clear_vblank_timestamps(struct drm_device *dev, int crtc)
+{
+	memset(&dev->_vblank_time[crtc * DRM_VBLANKTIME_RBSIZE], 0,
+		DRM_VBLANKTIME_RBSIZE * sizeof(struct timeval));
+}
+
+/*
+ * Disable vblank irq's on crtc, make sure that last vblank count
+ * of hardware and corresponding consistent software vblank counter
+ * are preserved, even if there are any spurious vblank irq's after
+ * disable.
+ */
+static void vblank_disable_and_save(struct drm_device *dev, int crtc)
+{
+	unsigned long irqflags;
+	u32 vblcount;
+	s64 diff_ns;
+	int vblrc;
+	struct timeval tvblank;
+
+	/* 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);
+	dev->vblank_enabled[crtc] = 0;
+
+	/* No further vblank irq's will be processed after
+	 * this point. Get current hardware vblank count and
+	 * vblank timestamp, repeat until they are consistent.
+	 *
+	 * FIXME: There is still a race condition here and in
+	 * drm_update_vblank_count() which can cause off-by-one
+	 * reinitialization of software vblank counter. If gpu
+	 * vblank counter doesn't increment exactly at the leading
+	 * edge of a vblank interval, then we can lose 1 count if
+	 * we happen to execute between start of vblank and the
+	 * delayed gpu counter increment.
+	 */
+	do {
+		dev->last_vblank[crtc] = dev->driver->get_vblank_counter(dev, crtc);
+		vblrc = drm_get_last_vbltimestamp(dev, crtc, &tvblank, 0);
+	} while (dev->last_vblank[crtc] != dev->driver->get_vblank_counter(dev, crtc));
+
+	/* Compute time difference to stored timestamp of last vblank
+	 * as updated by last invocation of drm_handle_vblank() in vblank irq.
+	 */
+	vblcount = atomic_read(&dev->_vblank_count[crtc]);
+	diff_ns = timeval_to_ns(&tvblank) -
+		  timeval_to_ns(&vblanktimestamp(dev, crtc, vblcount));
+
+	/* If there is at least 1 msec difference between the last stored
+	 * timestamp and tvblank, then we are currently executing our
+	 * disable inside a new vblank interval, the tvblank timestamp
+	 * corresponds to this new vblank interval and the irq handler
+	 * for this vblank didn't run yet and won't run due to our disable.
+	 * Therefore we need to do the job of drm_handle_vblank() and
+	 * increment the vblank counter by one to account for this vblank.
+	 *
+	 * Skip this step if there isn't any high precision timestamp
+	 * available. In that case we can't account for this and just
+	 * hope for the best.
+	 */
+	if ((vblrc > 0) && (abs64(diff_ns) > 1000000)) {
+		atomic_inc(&dev->_vblank_count[crtc]);
+		smp_mb__after_atomic_inc();
+	}
+
+	/* Invalidate all timestamps while vblank irq's are off. */
+	clear_vblank_timestamps(dev, crtc);
+
+	spin_unlock_irqrestore(&dev->vblank_time_lock, irqflags);
+	preempt_enable();
+}
+
 static void vblank_disable_fn(unsigned long arg)
 {
 	struct drm_device *dev = (struct drm_device *)arg;
@@ -91,10 +190,7 @@ static void vblank_disable_fn(unsigned l
 		if (atomic_read(&dev->vblank_refcount[i]) == 0 &&
 		    dev->vblank_enabled[i]) {
 			DRM_DEBUG("disabling vblank on crtc %d\n", i);
-			dev->last_vblank[i] =
-				dev->driver->get_vblank_counter(dev, i);
-			dev->driver->disable_vblank(dev, i);
-			dev->vblank_enabled[i] = 0;
+			vblank_disable_and_save(dev, i);
 		}
 		spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
 	}
@@ -117,6 +213,7 @@ void drm_vblank_cleanup(struct drm_devic
 	kfree(dev->last_vblank);
 	kfree(dev->last_vblank_wait);
 	kfree(dev->vblank_inmodeset);
+	kfree(dev->_vblank_time);
 
 	dev->num_crtcs = 0;
 }
@@ -129,6 +226,8 @@ int drm_vblank_init(struct drm_device *d
 	setup_timer(&dev->vblank_disable_timer, vblank_disable_fn,
 		    (unsigned long)dev);
 	spin_lock_init(&dev->vbl_lock);
+	spin_lock_init(&dev->vblank_time_lock);
+
 	dev->num_crtcs = num_crtcs;
 
 	dev->vbl_queue = kmalloc(sizeof(wait_queue_head_t) * num_crtcs,
@@ -161,6 +260,19 @@ int drm_vblank_init(struct drm_device *d
 	if (!dev->vblank_inmodeset)
 		goto err;
 
+	dev->_vblank_time = kcalloc(num_crtcs * DRM_VBLANKTIME_RBSIZE,
+				    sizeof(struct timeval), GFP_KERNEL);
+	if (!dev->_vblank_time)
+		goto err;
+
+	DRM_INFO("Supports vblank timestamp caching Rev 1 (10.10.2010).\n");
+
+	/* Driver specific high-precision vblank timestamping supported? */
+	if (dev->driver->get_vblank_timestamp)
+		DRM_INFO("Driver supports precise vblank timestamp query.\n");
+	else
+		DRM_INFO("No driver support for vblank timestamp query.\n");
+
 	/* Zero per-crtc vblank stuff */
 	for (i = 0; i < num_crtcs; i++) {
 		init_waitqueue_head(&dev->vbl_queue[i]);
@@ -279,7 +391,7 @@ EXPORT_SYMBOL(drm_irq_install);
  *
  * Calls the driver's \c drm_driver_irq_uninstall() function, and stops the irq.
  */
-int drm_irq_uninstall(struct drm_device * dev)
+int drm_irq_uninstall(struct drm_device *dev)
 {
 	unsigned long irqflags;
 	int irq_enabled, i;
@@ -335,7 +447,9 @@ int drm_control(struct drm_device *dev,
 {
 	struct drm_control *ctl = data;
 
-	/* if we haven't irq we fallback for compatibility reasons - this used to be a separate function in drm_dma.h */
+	/* if we haven't irq we fallback for compatibility reasons -
+	 * this used to be a separate function in drm_dma.h
+	 */
 
 
 	switch (ctl->func) {
@@ -360,6 +474,285 @@ int drm_control(struct drm_device *dev,
 }
 
 /**
+ * drm_calc_timestamping_constants - Calculate and
+ * store various constants which are later needed by
+ * vblank and swap-completion timestamping, e.g, by
+ * drm_calc_vbltimestamp_from_scanoutpos().
+ * They are derived from crtc's true scanout timing,
+ * so they take things like panel scaling or other
+ * adjustments into account.
+ *
+ * @crtc drm_crtc whose timestamp constants should be updated.
+ *
+ */
+void drm_calc_timestamping_constants(struct drm_crtc *crtc)
+{
+	s64 linedur_ns = 0, pixeldur_ns = 0, framedur_ns = 0;
+	u64 dotclock;
+
+	/* Dot clock in Hz: */
+	dotclock = (u64) crtc->hwmode.clock * 1000;
+
+	/* Fields of interlaced scanout modes are only halve a frame duration.
+	 * Double the dotclock to get halve the frame-/line-/pixelduration.
+	 */
+	if (crtc->hwmode.flags & DRM_MODE_FLAG_INTERLACE)
+		dotclock *= 2;
+
+	/* Valid dotclock? */
+	if (dotclock > 0) {
+		/* Convert scanline length in pixels and video dot clock to
+		 * line duration, frame duration and pixel duration in
+		 * nanoseconds:
+		 */
+		pixeldur_ns = (s64) div64_u64(1000000000, dotclock);
+		linedur_ns  = (s64) div64_u64(((u64) crtc->hwmode.crtc_htotal *
+					      1000000000), dotclock);
+		framedur_ns = (s64) crtc->hwmode.crtc_vtotal * linedur_ns;
+	} else
+		DRM_ERROR("crtc %d: Can't calculate constants, dotclock = 0!\n",
+			  crtc->base.id);
+
+	crtc->pixeldur_ns = pixeldur_ns;
+	crtc->linedur_ns  = linedur_ns;
+	crtc->framedur_ns = framedur_ns;
+
+	DRM_DEBUG("crtc %d: hwmode: htotal %d, vtotal %d, vdisplay %d\n",
+		  crtc->base.id, crtc->hwmode.crtc_htotal,
+		  crtc->hwmode.crtc_vtotal, crtc->hwmode.crtc_vdisplay);
+	DRM_DEBUG("crtc %d: clock %d kHz framedur %d linedur %d, pixeldur %d\n",
+		  crtc->base.id, (int) dotclock/1000, (int) framedur_ns,
+		  (int) linedur_ns, (int) pixeldur_ns);
+}
+EXPORT_SYMBOL(drm_calc_timestamping_constants);
+
+/**
+ * drm_calc_vbltimestamp_from_scanoutpos - helper routine for kms
+ * drivers. Implements calculation of exact vblank timestamps from
+ * given drm_display_mode timings and current video scanout position
+ * of a crtc. This can be called from within get_vblank_timestamp()
+ * implementation of a kms driver to implement the actual timestamping.
+ *
+ * Should return timestamps conforming to the OML_sync_control OpenML
+ * extension specification. The timestamp corresponds to the end of
+ * the vblank interval, aka start of scanout of topmost-leftmost display
+ * pixel in the following video frame.
+ *
+ * Requires support for optional dev->driver->get_scanout_position()
+ * in kms driver, plus a bit of setup code to provide a drm_display_mode
+ * that corresponds to the true scanout timing.
+ *
+ * The current implementation only handles standard video modes. It
+ * returns as no operation if a doublescan or interlaced video mode is
+ * active. Higher level code is expected to handle this.
+ *
+ * @dev: DRM device.
+ * @crtc: Which crtc's vblank timestamp to retrieve.
+ * @max_error: Desired maximum allowable error in timestamps (nanosecs).
+ *             On return contains true maximum error of timestamp.
+ * @vblank_time: Pointer to struct timeval which should receive the timestamp.
+ * @flags: Flags to pass to driver:
+ *         0 = Default.
+ *         DRM_CALLED_FROM_VBLIRQ = If function is called from vbl irq handler.
+ * @refcrtc: drm_crtc* of crtc which defines scanout timing.
+ *
+ * Returns negative value on error, failure or if not supported in current
+ * video mode:
+ *
+ * -EINVAL   - Invalid crtc.
+ * -EAGAIN   - Temporary unavailable, e.g., called before initial modeset.
+ * -ENOTSUPP - Function not supported in current display mode.
+ * -EIO      - Failed, e.g., due to failed scanout position query.
+ *
+ * Returns or'ed positive status flags on success:
+ *
+ * DRM_VBLANKTIME_SCANOUTPOS_METHOD - Signal this method used for timestamping.
+ * DRM_VBLANKTIME_INVBL - Timestamp taken while scanout was in vblank interval.
+ *
+ */
+int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc,
+					  int *max_error,
+					  struct timeval *vblank_time,
+					  unsigned flags,
+					  struct drm_crtc *refcrtc)
+{
+	struct timeval stime, raw_time;
+	struct drm_display_mode *mode;
+	int vbl_status, vtotal, vdisplay;
+	int vpos, hpos, i;
+	s64 framedur_ns, linedur_ns, pixeldur_ns, delta_ns, duration_ns;
+	bool invbl;
+
+	if (crtc < 0 || crtc >= dev->num_crtcs) {
+		DRM_ERROR("Invalid crtc %d\n", crtc);
+		return -EINVAL;
+	}
+
+	/* Scanout position query not supported? Should not happen. */
+	if (!dev->driver->get_scanout_position) {
+		DRM_ERROR("Called from driver w/o get_scanout_position()!?\n");
+		return -EIO;
+	}
+
+	mode = &refcrtc->hwmode;
+	vtotal = mode->crtc_vtotal;
+	vdisplay = mode->crtc_vdisplay;
+
+	/* Durations of frames, lines, pixels in nanoseconds. */
+	framedur_ns = refcrtc->framedur_ns;
+	linedur_ns  = refcrtc->linedur_ns;
+	pixeldur_ns = refcrtc->pixeldur_ns;
+
+	/* If mode timing undefined, just return as no-op:
+	 * Happens during initial modesetting of a crtc.
+	 */
+	if (vtotal <= 0 || vdisplay <= 0 || framedur_ns == 0) {
+		DRM_DEBUG("crtc %d: Noop due to uninitialized mode.\n", crtc);
+		return -EAGAIN;
+	}
+
+	/* Get current scanout position with system timestamp.
+	 * Repeat query up to DRM_TIMESTAMP_MAXRETRIES times
+	 * if single query takes longer than max_error nanoseconds.
+	 *
+	 * This guarantees a tight bound on maximum error if
+	 * code gets preempted or delayed for some reason.
+	 */
+	for (i = 0; i < DRM_TIMESTAMP_MAXRETRIES; i++) {
+		/* Disable preemption to make it very likely to
+		 * succeed in the first iteration even on PREEMPT_RT kernel.
+		 */
+		preempt_disable();
+
+		/* Get system timestamp before query. */
+		do_gettimeofday(&stime);
+
+		/* Get vertical and horizontal scanout pos. vpos, hpos. */
+		vbl_status = dev->driver->get_scanout_position(dev, crtc, &vpos, &hpos);
+
+		/* Get system timestamp after query. */
+		do_gettimeofday(&raw_time);
+
+		preempt_enable();
+
+		/* Return as no-op if scanout query unsupported or failed. */
+		if (!(vbl_status & DRM_SCANOUTPOS_VALID)) {
+			DRM_DEBUG("crtc %d : scanoutpos query failed [%d].\n",
+				  crtc, vbl_status);
+			return -EIO;
+		}
+
+		duration_ns = timeval_to_ns(&raw_time) - timeval_to_ns(&stime);
+
+		/* Accept result with <  max_error nsecs timing uncertainty. */
+		if (duration_ns <= (s64) *max_error)
+			break;
+	}
+
+	/* Noisy system timing? */
+	if (i == DRM_TIMESTAMP_MAXRETRIES) {
+		DRM_DEBUG("crtc %d: Noisy timestamp %d us > %d us [%d reps].\n",
+			  crtc, (int) duration_ns/1000, *max_error/1000, i);
+	}
+
+	/* Return upper bound of timestamp precision error. */
+	*max_error = (int) duration_ns;
+
+	/* Check if in vblank area:
+	 * vpos is >=0 in video scanout area, but negative
+	 * within vblank area, counting down the number of lines until
+	 * start of scanout.
+	 */
+	invbl = vbl_status & DRM_SCANOUTPOS_INVBL;
+
+	/* Convert scanout position into elapsed time at raw_time query
+	 * since start of scanout at first display scanline. delta_ns
+	 * can be negative if start of scanout hasn't happened yet.
+	 */
+	delta_ns = (s64) vpos * linedur_ns + (s64) hpos * pixeldur_ns;
+
+	/* Is vpos outside nominal vblank area, but less than
+	 * 1/100 of a frame height away from start of vblank?
+	 * If so, assume this isn't a massively delayed vblank
+	 * interrupt, but a vblank interrupt that fired a few
+	 * microseconds before true start of vblank. Compensate
+	 * by adding a full frame duration to the final timestamp.
+	 * Happens, e.g., on ATI R500, R600.
+	 *
+	 * We only do this if DRM_CALLED_FROM_VBLIRQ.
+	 */
+	if ((flags & DRM_CALLED_FROM_VBLIRQ) && !invbl &&
+	    ((vdisplay - vpos) < vtotal / 100)) {
+		delta_ns = delta_ns - framedur_ns;
+
+		/* Signal this correction as "applied". */
+		vbl_status |= 0x8;
+	}
+
+	/* Subtract time delta from raw timestamp to get final
+	 * vblank_time timestamp for end of vblank.
+	 */
+	*vblank_time = ns_to_timeval(timeval_to_ns(&raw_time) - delta_ns);
+
+	DRM_DEBUG("crtc %d : v %d p(%d,%d)@ %d.%d -> %d.%d [e %d us, %d rep]\n",
+		  crtc, (int) vbl_status, hpos, vpos, raw_time.tv_sec,
+		  raw_time.tv_usec, vblank_time->tv_sec, vblank_time->tv_usec,
+		  (int) duration_ns/1000, i);
+
+	vbl_status = DRM_VBLANKTIME_SCANOUTPOS_METHOD;
+	if (invbl)
+		vbl_status |= DRM_VBLANKTIME_INVBL;
+
+	return vbl_status;
+}
+EXPORT_SYMBOL(drm_calc_vbltimestamp_from_scanoutpos);
+
+/**
+ * drm_get_last_vbltimestamp - retrieve raw timestamp for the most recent
+ * vblank interval.
+ *
+ * @dev: DRM device
+ * @crtc: which crtc's vblank timestamp to retrieve
+ * @tvblank: Pointer to target struct timeval which should receive the timestamp
+ * @flags: Flags to pass to driver:
+ *         0 = Default.
+ *         DRM_CALLED_FROM_VBLIRQ = If function is called from vbl irq handler.
+ *
+ * Fetches the system timestamp corresponding to the time of the most recent
+ * vblank interval on specified crtc. May call into kms-driver to
+ * compute the timestamp with a high-precision GPU specific method.
+ *
+ * Returns zero if timestamp originates from uncorrected do_gettimeofday()
+ * call, i.e., it isn't very precisely locked to the true vblank.
+ *
+ * Returns non-zero if timestamp is considered to be very precise.
+ */
+u32 drm_get_last_vbltimestamp(struct drm_device *dev, int crtc,
+			      struct timeval *tvblank, unsigned flags)
+{
+	int ret = 0;
+
+	/* Define requested maximum error on timestamps (nanoseconds). */
+	int max_error = (int) drm_timestamp_precision * 1000;
+
+	/* Query driver if possible and precision timestamping enabled. */
+	if (dev->driver->get_vblank_timestamp && (max_error > 0)) {
+		ret = dev->driver->get_vblank_timestamp(dev, crtc, &max_error,
+							tvblank, flags);
+		if (ret > 0)
+			return (u32) ret;
+	}
+
+	/* GPU high precision timestamp query unsupported or failed.
+	 * Return gettimeofday timestamp as best estimate.
+	 */
+	do_gettimeofday(tvblank);
+
+	return 0;
+}
+EXPORT_SYMBOL(drm_get_last_vbltimestamp);
+
+/**
  * drm_vblank_count - retrieve "cooked" vblank counter value
  * @dev: DRM device
  * @crtc: which counter to retrieve
@@ -375,6 +768,40 @@ u32 drm_vblank_count(struct drm_device *
 EXPORT_SYMBOL(drm_vblank_count);
 
 /**
+ * drm_vblank_count_and_time - retrieve "cooked" vblank counter value
+ * and the system timestamp corresponding to that vblank counter value.
+ *
+ * @dev: DRM device
+ * @crtc: which counter to retrieve
+ * @vblanktime: Pointer to struct timeval to receive the vblank timestamp.
+ *
+ * Fetches the "cooked" vblank count value that represents the number of
+ * vblank events since the system was booted, including lost events due to
+ * modesetting activity. Returns corresponding system timestamp of the time
+ * of the vblank interval that corresponds to the current value vblank counter
+ * value.
+ */
+u32 drm_vblank_count_and_time(struct drm_device *dev, int crtc,
+			      struct timeval *vblanktime)
+{
+	u32 cur_vblank;
+
+	/* Read timestamp from slot of _vblank_time ringbuffer
+	 * that corresponds to current vblank count. Retry if
+	 * count has incremented during readout. This works like
+	 * a seqlock.
+	 */
+	do {
+		cur_vblank = atomic_read(&dev->_vblank_count[crtc]);
+		*vblanktime = vblanktimestamp(dev, crtc, cur_vblank);
+		smp_rmb();
+	} while (cur_vblank != atomic_read(&dev->_vblank_count[crtc]));
+
+	return cur_vblank;
+}
+EXPORT_SYMBOL(drm_vblank_count_and_time);
+
+/**
  * drm_update_vblank_count - update the master vblank counter
  * @dev: DRM device
  * @crtc: counter to update
@@ -392,7 +819,8 @@ EXPORT_SYMBOL(drm_vblank_count);
  */
 static void drm_update_vblank_count(struct drm_device *dev, int crtc)
 {
-	u32 cur_vblank, diff;
+	u32 cur_vblank, diff, tslot, rc;
+	struct timeval t_vblank;
 
 	/*
 	 * Interrupts were disabled prior to this call, so deal with counter
@@ -400,8 +828,18 @@ static void drm_update_vblank_count(stru
 	 * NOTE!  It's possible we lost a full dev->max_vblank_count events
 	 * here if the register is small or we had vblank interrupts off for
 	 * a long time.
+	 *
+	 * We repeat the hardware vblank counter & timestamp query until
+	 * we get consistent results. This to prevent races between gpu
+	 * updating its hardware counter while we are retrieving the
+	 * corresponding vblank timestamp.
 	 */
-	cur_vblank = dev->driver->get_vblank_counter(dev, crtc);
+	do {
+		cur_vblank = dev->driver->get_vblank_counter(dev, crtc);
+		rc = drm_get_last_vbltimestamp(dev, crtc, &t_vblank, 0);
+	} while (cur_vblank != dev->driver->get_vblank_counter(dev, crtc));
+
+	/* Deal with counter wrap */
 	diff = cur_vblank - dev->last_vblank[crtc];
 	if (cur_vblank < dev->last_vblank[crtc]) {
 		diff += dev->max_vblank_count;
@@ -413,7 +851,18 @@ static void drm_update_vblank_count(stru
 	DRM_DEBUG("enabling vblank interrupts on crtc %d, missed %d\n",
 		  crtc, diff);
 
+	/* Reinitialize corresponding vblank timestamp if high-precision query
+	 * available. Skip this step if query unsupported or failed. Will
+	 * reinitialize delayed at next vblank interrupt in that case.
+	 */
+	if (rc) {
+		tslot = atomic_read(&dev->_vblank_count[crtc]) + diff;
+		vblanktimestamp(dev, crtc, tslot) = t_vblank;
+	}
+
+	smp_mb__before_atomic_inc();
 	atomic_add(diff, &dev->_vblank_count[crtc]);
+	smp_mb__after_atomic_inc();
 }
 
 /**
@@ -429,15 +878,27 @@ static void drm_update_vblank_count(stru
  */
 int drm_vblank_get(struct drm_device *dev, int crtc)
 {
-	unsigned long irqflags;
+	unsigned long irqflags, irqflags2;
 	int ret = 0;
 
 	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.
+			 * All vblank count & timestamp updates are held off
+			 * until we are done reinitializing master counter and
+			 * timestamps. Filtercode in drm_handle_vblank() will
+			 * prevent double-accounting of same vblank interval.
+			 */
 			ret = dev->driver->enable_vblank(dev, crtc);
-			DRM_DEBUG("enabling vblank on crtc %d, ret: %d\n", crtc, ret);
+			DRM_DEBUG("enabling vblank on crtc %d, ret: %d\n",
+				  crtc, ret);
 			if (ret)
 				atomic_dec(&dev->vblank_refcount[crtc]);
 			else {
@@ -445,6 +906,8 @@ int drm_vblank_get(struct drm_device *de
 				drm_update_vblank_count(dev, crtc);
 			}
 		}
+		spin_unlock_irqrestore(&dev->vblank_time_lock, irqflags2);
+		preempt_enable();
 	} else {
 		if (!dev->vblank_enabled[crtc]) {
 			atomic_dec(&dev->vblank_refcount[crtc]);
@@ -463,15 +926,17 @@ EXPORT_SYMBOL(drm_vblank_get);
  * @crtc: which counter to give up
  *
  * Release ownership of a given vblank counter, turning off interrupts
- * if possible.
+ * if possible. Disable interrupts after drm_vblank_offdelay milliseconds.
  */
 void drm_vblank_put(struct drm_device *dev, int crtc)
 {
-	BUG_ON (atomic_read (&dev->vblank_refcount[crtc]) == 0);
+	BUG_ON(atomic_read(&dev->vblank_refcount[crtc]) == 0);
 
 	/* Last user schedules interrupt disable */
-	if (atomic_dec_and_test(&dev->vblank_refcount[crtc]))
-		mod_timer(&dev->vblank_disable_timer, jiffies + 5*DRM_HZ);
+	if (atomic_dec_and_test(&dev->vblank_refcount[crtc]) &&
+	    (drm_vblank_offdelay > 0))
+		mod_timer(&dev->vblank_disable_timer,
+			  jiffies + ((drm_vblank_offdelay * DRM_HZ)/1000));
 }
 EXPORT_SYMBOL(drm_vblank_put);
 
@@ -480,10 +945,8 @@ void drm_vblank_off(struct drm_device *d
 	unsigned long irqflags;
 
 	spin_lock_irqsave(&dev->vbl_lock, irqflags);
-	dev->driver->disable_vblank(dev, crtc);
+	vblank_disable_and_save(dev, crtc);
 	DRM_WAKEUP(&dev->vbl_queue[crtc]);
-	dev->vblank_enabled[crtc] = 0;
-	dev->last_vblank[crtc] = dev->driver->get_vblank_counter(dev, crtc);
 	spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
 }
 EXPORT_SYMBOL(drm_vblank_off);
@@ -549,7 +1012,8 @@ int drm_modeset_ctl(struct drm_device *d
 		    struct drm_file *file_priv)
 {
 	struct drm_modeset_ctl *modeset = data;
-	int crtc, ret = 0;
+	int ret = 0;
+	unsigned int crtc;
 
 	/* If drm_vblank_init() hasn't been called yet, just no-op */
 	if (!dev->num_crtcs)
@@ -602,7 +1066,6 @@ static int drm_queue_vblank_event(struct
 	e->base.file_priv = file_priv;
 	e->base.destroy = (void (*) (struct drm_pending_event *)) kfree;
 
-	do_gettimeofday(&now);
 	spin_lock_irqsave(&dev->event_lock, flags);
 
 	if (file_priv->event_space < sizeof e->event) {
@@ -611,7 +1074,8 @@ static int drm_queue_vblank_event(struct
 	}
 
 	file_priv->event_space -= sizeof e->event;
-	seq = drm_vblank_count(dev, pipe);
+	seq = drm_vblank_count_and_time(dev, pipe, &now);
+
 	if ((vblwait->request.type & _DRM_VBLANK_NEXTONMISS) &&
 	    (seq - vblwait->request.sequence) <= (1 << 23)) {
 		vblwait->request.sequence = seq + 1;
@@ -626,15 +1090,18 @@ static int drm_queue_vblank_event(struct
 
 	e->event.sequence = vblwait->request.sequence;
 	if ((seq - vblwait->request.sequence) <= (1 << 23)) {
+		e->event.sequence = seq;
 		e->event.tv_sec = now.tv_sec;
 		e->event.tv_usec = now.tv_usec;
 		drm_vblank_put(dev, pipe);
 		list_add_tail(&e->base.link, &e->base.file_priv->event_list);
 		wake_up_interruptible(&e->base.file_priv->event_wait);
+		vblwait->reply.sequence = seq;
 		trace_drm_vblank_event_delivered(current->pid, pipe,
 						 vblwait->request.sequence);
 	} else {
 		list_add_tail(&e->base.link, &dev->vblank_event_list);
+		vblwait->reply.sequence = vblwait->request.sequence;
 	}
 
 	spin_unlock_irqrestore(&dev->event_lock, flags);
@@ -727,11 +1194,10 @@ int drm_wait_vblank(struct drm_device *d
 	if (ret != -EINTR) {
 		struct timeval now;
 
-		do_gettimeofday(&now);
-
+		vblwait->reply.sequence = drm_vblank_count_and_time(dev, crtc, &now);
 		vblwait->reply.tval_sec = now.tv_sec;
 		vblwait->reply.tval_usec = now.tv_usec;
-		vblwait->reply.sequence = drm_vblank_count(dev, crtc);
+
 		DRM_DEBUG("returning %d to client\n",
 			  vblwait->reply.sequence);
 	} else {
@@ -750,8 +1216,7 @@ void drm_handle_vblank_events(struct drm
 	unsigned long flags;
 	unsigned int seq;
 
-	do_gettimeofday(&now);
-	seq = drm_vblank_count(dev, crtc);
+	seq = drm_vblank_count_and_time(dev, crtc, &now);
 
 	spin_lock_irqsave(&dev->event_lock, flags);
 
@@ -787,13 +1252,68 @@ void drm_handle_vblank_events(struct drm
  * Drivers should call this routine in their vblank interrupt handlers to
  * update the vblank counter and send any signals that may be pending.
  */
-void drm_handle_vblank(struct drm_device *dev, int crtc)
+bool drm_handle_vblank(struct drm_device *dev, int crtc)
 {
+	u32 vblcount;
+	s64 diff_ns;
+	struct timeval tvblank;
+	unsigned long irqflags;
+
 	if (!dev->num_crtcs)
-		return;
+		return false;
+
+	/* Need timestamp lock to prevent concurrent execution with
+	 * vblank enable/disable, as this would cause inconsistent
+	 * or corrupted timestamps and vblank counts.
+	 */
+	spin_lock_irqsave(&dev->vblank_time_lock, irqflags);
+
+	/* Vblank irq handling disabled. Nothing to do. */
+	if (!dev->vblank_enabled[crtc]) {
+		spin_unlock_irqrestore(&dev->vblank_time_lock, irqflags);
+		return false;
+	}
+
+	/* Fetch corresponding timestamp for this vblank interval from
+	 * driver and store it in proper slot of timestamp ringbuffer.
+	 */
+
+	/* Get current timestamp and count. */
+	vblcount = atomic_read(&dev->_vblank_count[crtc]);
+	drm_get_last_vbltimestamp(dev, crtc, &tvblank, DRM_CALLED_FROM_VBLIRQ);
+
+	/* Compute time difference to timestamp of last vblank */
+	diff_ns = timeval_to_ns(&tvblank) -
+		  timeval_to_ns(&vblanktimestamp(dev, crtc, vblcount));
+
+	/* Update vblank timestamp and count if at least
+	 * DRM_REDUNDANT_VBLIRQ_THRESH_NS nanoseconds
+	 * difference between last stored timestamp and current
+	 * timestamp. A smaller difference means basically
+	 * identical timestamps. Happens if this vblank has
+	 * been already processed and this is a redundant call,
+	 * e.g., due to spurious vblank interrupts. We need to
+	 * ignore those for accounting.
+	 */
+	if (abs64(diff_ns) > DRM_REDUNDANT_VBLIRQ_THRESH_NS) {
+		/* Store new timestamp in ringbuffer. */
+		vblanktimestamp(dev, crtc, vblcount + 1) = tvblank;
+
+		/* Increment cooked vblank count. This also atomically commits
+		 * the timestamp computed above.
+		 */
+		smp_mb__before_atomic_inc();
+		atomic_inc(&dev->_vblank_count[crtc]);
+		smp_mb__after_atomic_inc();
+	} else {
+		DRM_DEBUG("crtc %d: Redundant vblirq ignored. diff_ns = %d\n",
+			  crtc, (int) diff_ns);
+	}
 
-	atomic_inc(&dev->_vblank_count[crtc]);
 	DRM_WAKEUP(&dev->vbl_queue[crtc]);
 	drm_handle_vblank_events(dev, crtc);
+
+	spin_unlock_irqrestore(&dev->vblank_time_lock, irqflags);
+	return true;
 }
 EXPORT_SYMBOL(drm_handle_vblank);
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/drm_mm.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/drm_mm.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/drm_mm.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/drm_mm.c	2011-03-14 21:20:32.000000000 -0400
@@ -392,10 +392,36 @@ void drm_mm_init_scan(struct drm_mm *mm,
 	mm->scanned_blocks = 0;
 	mm->scan_hit_start = 0;
 	mm->scan_hit_size = 0;
+	mm->scan_check_range = 0;
 }
 EXPORT_SYMBOL(drm_mm_init_scan);
 
 /**
+ * Initializa lru scanning.
+ *
+ * This simply sets up the scanning routines with the parameters for the desired
+ * hole. This version is for range-restricted scans.
+ *
+ * Warning: As long as the scan list is non-empty, no other operations than
+ * adding/removing nodes to/from the scan list are allowed.
+ */
+void drm_mm_init_scan_with_range(struct drm_mm *mm, unsigned long size,
+				 unsigned alignment,
+				 unsigned long start,
+				 unsigned long end)
+{
+	mm->scan_alignment = alignment;
+	mm->scan_size = size;
+	mm->scanned_blocks = 0;
+	mm->scan_hit_start = 0;
+	mm->scan_hit_size = 0;
+	mm->scan_start = start;
+	mm->scan_end = end;
+	mm->scan_check_range = 1;
+}
+EXPORT_SYMBOL(drm_mm_init_scan_with_range);
+
+/**
  * Add a node to the scan list that might be freed to make space for the desired
  * hole.
  *
@@ -406,6 +432,8 @@ int drm_mm_scan_add_block(struct drm_mm_
 	struct drm_mm *mm = node->mm;
 	struct list_head *prev_free, *next_free;
 	struct drm_mm_node *prev_node, *next_node;
+	unsigned long adj_start;
+	unsigned long adj_end;
 
 	mm->scanned_blocks++;
 
@@ -452,7 +480,17 @@ int drm_mm_scan_add_block(struct drm_mm_
 	node->free_stack.prev = prev_free;
 	node->free_stack.next = next_free;
 
-	if (check_free_hole(node->start, node->start + node->size,
+	if (mm->scan_check_range) {
+		adj_start = node->start < mm->scan_start ?
+			mm->scan_start : node->start;
+		adj_end = node->start + node->size > mm->scan_end ?
+			mm->scan_end : node->start + node->size;
+	} else {
+		adj_start = node->start;
+		adj_end = node->start + node->size;
+	}
+
+	if (check_free_hole(adj_start , adj_end,
 			    mm->scan_size, mm->scan_alignment)) {
 		mm->scan_hit_start = node->start;
 		mm->scan_hit_size = node->size;
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/drm_stub.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/drm_stub.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/drm_stub.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/drm_stub.c	2011-03-14 21:20:32.000000000 -0400
@@ -40,12 +40,22 @@
 unsigned int drm_debug = 0;	/* 1 to enable debug output */
 EXPORT_SYMBOL(drm_debug);
 
+unsigned int drm_vblank_offdelay = 5000;    /* Default to 5000 msecs. */
+EXPORT_SYMBOL(drm_vblank_offdelay);
+
+unsigned int drm_timestamp_precision = 20;  /* Default to 20 usecs. */
+EXPORT_SYMBOL(drm_timestamp_precision);
+
 MODULE_AUTHOR(CORE_AUTHOR);
 MODULE_DESCRIPTION(CORE_DESC);
 MODULE_LICENSE("GPL and additional rights");
 MODULE_PARM_DESC(debug, "Enable debug output");
+MODULE_PARM_DESC(vblankoffdelay, "Delay until vblank irq auto-disable [msecs]");
+MODULE_PARM_DESC(timestamp_precision_usec, "Max. error on timestamps [usecs]");
 
 module_param_named(debug, drm_debug, int, 0600);
+module_param_named(vblankoffdelay, drm_vblank_offdelay, int, 0600);
+module_param_named(timestamp_precision_usec, drm_timestamp_precision, int, 0600);
 
 struct idr drm_minors_idr;
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/i915/i915_debugfs.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/i915/i915_debugfs.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/i915/i915_debugfs.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/i915/i915_debugfs.c	2011-03-14 21:20:32.000000000 -0400
@@ -32,6 +32,7 @@
 #include "drmP.h"
 #include "drm.h"
 #include "intel_drv.h"
+#include "intel_ringbuffer.h"
 #include "i915_drm.h"
 #include "i915_drv.h"
 
@@ -72,7 +73,6 @@ static int i915_capabilities(struct seq_
 	B(is_broadwater);
 	B(is_crestline);
 	B(has_fbc);
-	B(has_rc6);
 	B(has_pipe_cxsr);
 	B(has_hotplug);
 	B(cursor_needs_physical);
@@ -86,19 +86,19 @@ static int i915_capabilities(struct seq_
 	return 0;
 }
 
-static const char *get_pin_flag(struct drm_i915_gem_object *obj_priv)
+static const char *get_pin_flag(struct drm_i915_gem_object *obj)
 {
-	if (obj_priv->user_pin_count > 0)
+	if (obj->user_pin_count > 0)
 		return "P";
-	else if (obj_priv->pin_count > 0)
+	else if (obj->pin_count > 0)
 		return "p";
 	else
 		return " ";
 }
 
-static const char *get_tiling_flag(struct drm_i915_gem_object *obj_priv)
+static const char *get_tiling_flag(struct drm_i915_gem_object *obj)
 {
-    switch (obj_priv->tiling_mode) {
+    switch (obj->tiling_mode) {
     default:
     case I915_TILING_NONE: return " ";
     case I915_TILING_X: return "X";
@@ -106,10 +106,19 @@ static const char *get_tiling_flag(struc
     }
 }
 
+static const char *agp_type_str(int type)
+{
+	switch (type) {
+	case 0: return " uncached";
+	case 1: return " snooped";
+	default: return "";
+	}
+}
+
 static void
 describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj)
 {
-	seq_printf(m, "%p: %s%s %8zd %08x %08x %d%s%s",
+	seq_printf(m, "%p: %s%s %8zd %04x %04x %d %d%s%s%s",
 		   &obj->base,
 		   get_pin_flag(obj),
 		   get_tiling_flag(obj),
@@ -117,6 +126,8 @@ describe_obj(struct seq_file *m, struct
 		   obj->base.read_domains,
 		   obj->base.write_domain,
 		   obj->last_rendering_seqno,
+		   obj->last_fenced_seqno,
+		   agp_type_str(obj->agp_type == AGP_USER_CACHED_MEMORY),
 		   obj->dirty ? " dirty" : "",
 		   obj->madv == I915_MADV_DONTNEED ? " purgeable" : "");
 	if (obj->base.name)
@@ -124,7 +135,17 @@ describe_obj(struct seq_file *m, struct
 	if (obj->fence_reg != I915_FENCE_REG_NONE)
 		seq_printf(m, " (fence: %d)", obj->fence_reg);
 	if (obj->gtt_space != NULL)
-		seq_printf(m, " (gtt_offset: %08x)", obj->gtt_offset);
+		seq_printf(m, " (gtt offset: %08x, size: %08x)",
+			   obj->gtt_offset, (unsigned int)obj->gtt_space->size);
+	if (obj->pin_mappable || obj->fault_mappable) {
+		char s[3], *t = s;
+		if (obj->pin_mappable)
+			*t++ = 'p';
+		if (obj->fault_mappable)
+			*t++ = 'f';
+		*t = '\0';
+		seq_printf(m, " (%s mappable)", s);
+	}
 	if (obj->ring != NULL)
 		seq_printf(m, " (%s)", obj->ring->name);
 }
@@ -136,7 +157,7 @@ static int i915_gem_object_list_info(str
 	struct list_head *head;
 	struct drm_device *dev = node->minor->dev;
 	drm_i915_private_t *dev_priv = dev->dev_private;
-	struct drm_i915_gem_object *obj_priv;
+	struct drm_i915_gem_object *obj;
 	size_t total_obj_size, total_gtt_size;
 	int count, ret;
 
@@ -171,12 +192,12 @@ static int i915_gem_object_list_info(str
 	}
 
 	total_obj_size = total_gtt_size = count = 0;
-	list_for_each_entry(obj_priv, head, mm_list) {
+	list_for_each_entry(obj, head, mm_list) {
 		seq_printf(m, "   ");
-		describe_obj(m, obj_priv);
+		describe_obj(m, obj);
 		seq_printf(m, "\n");
-		total_obj_size += obj_priv->base.size;
-		total_gtt_size += obj_priv->gtt_space->size;
+		total_obj_size += obj->base.size;
+		total_gtt_size += obj->gtt_space->size;
 		count++;
 	}
 	mutex_unlock(&dev->struct_mutex);
@@ -186,30 +207,116 @@ static int i915_gem_object_list_info(str
 	return 0;
 }
 
+#define count_objects(list, member) do { \
+	list_for_each_entry(obj, list, member) { \
+		size += obj->gtt_space->size; \
+		++count; \
+		if (obj->map_and_fenceable) { \
+			mappable_size += obj->gtt_space->size; \
+			++mappable_count; \
+		} \
+	} \
+} while(0)
+
 static int i915_gem_object_info(struct seq_file *m, void* data)
 {
 	struct drm_info_node *node = (struct drm_info_node *) m->private;
 	struct drm_device *dev = node->minor->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
+	u32 count, mappable_count;
+	size_t size, mappable_size;
+	struct drm_i915_gem_object *obj;
 	int ret;
 
 	ret = mutex_lock_interruptible(&dev->struct_mutex);
 	if (ret)
 		return ret;
 
-	seq_printf(m, "%u objects\n", dev_priv->mm.object_count);
-	seq_printf(m, "%zu object bytes\n", dev_priv->mm.object_memory);
-	seq_printf(m, "%u pinned\n", dev_priv->mm.pin_count);
-	seq_printf(m, "%zu pin bytes\n", dev_priv->mm.pin_memory);
-	seq_printf(m, "%u objects in gtt\n", dev_priv->mm.gtt_count);
-	seq_printf(m, "%zu gtt bytes\n", dev_priv->mm.gtt_memory);
-	seq_printf(m, "%zu gtt total\n", dev_priv->mm.gtt_total);
+	seq_printf(m, "%u objects, %zu bytes\n",
+		   dev_priv->mm.object_count,
+		   dev_priv->mm.object_memory);
+
+	size = count = mappable_size = mappable_count = 0;
+	count_objects(&dev_priv->mm.gtt_list, gtt_list);
+	seq_printf(m, "%u [%u] objects, %zu [%zu] bytes in gtt\n",
+		   count, mappable_count, size, mappable_size);
+
+	size = count = mappable_size = mappable_count = 0;
+	count_objects(&dev_priv->mm.active_list, mm_list);
+	count_objects(&dev_priv->mm.flushing_list, mm_list);
+	seq_printf(m, "  %u [%u] active objects, %zu [%zu] bytes\n",
+		   count, mappable_count, size, mappable_size);
+
+	size = count = mappable_size = mappable_count = 0;
+	count_objects(&dev_priv->mm.pinned_list, mm_list);
+	seq_printf(m, "  %u [%u] pinned objects, %zu [%zu] bytes\n",
+		   count, mappable_count, size, mappable_size);
+
+	size = count = mappable_size = mappable_count = 0;
+	count_objects(&dev_priv->mm.inactive_list, mm_list);
+	seq_printf(m, "  %u [%u] inactive objects, %zu [%zu] bytes\n",
+		   count, mappable_count, size, mappable_size);
+
+	size = count = mappable_size = mappable_count = 0;
+	count_objects(&dev_priv->mm.deferred_free_list, mm_list);
+	seq_printf(m, "  %u [%u] freed objects, %zu [%zu] bytes\n",
+		   count, mappable_count, size, mappable_size);
+
+	size = count = mappable_size = mappable_count = 0;
+	list_for_each_entry(obj, &dev_priv->mm.gtt_list, gtt_list) {
+		if (obj->fault_mappable) {
+			size += obj->gtt_space->size;
+			++count;
+		}
+		if (obj->pin_mappable) {
+			mappable_size += obj->gtt_space->size;
+			++mappable_count;
+		}
+	}
+	seq_printf(m, "%u pinned mappable objects, %zu bytes\n",
+		   mappable_count, mappable_size);
+	seq_printf(m, "%u fault mappable objects, %zu bytes\n",
+		   count, size);
+
+	seq_printf(m, "%zu [%zu] gtt total\n",
+		   dev_priv->mm.gtt_total, dev_priv->mm.mappable_gtt_total);
 
 	mutex_unlock(&dev->struct_mutex);
 
 	return 0;
 }
 
+static int i915_gem_gtt_info(struct seq_file *m, void* data)
+{
+	struct drm_info_node *node = (struct drm_info_node *) m->private;
+	struct drm_device *dev = node->minor->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_i915_gem_object *obj;
+	size_t total_obj_size, total_gtt_size;
+	int count, ret;
+
+	ret = mutex_lock_interruptible(&dev->struct_mutex);
+	if (ret)
+		return ret;
+
+	total_obj_size = total_gtt_size = count = 0;
+	list_for_each_entry(obj, &dev_priv->mm.gtt_list, gtt_list) {
+		seq_printf(m, "   ");
+		describe_obj(m, obj);
+		seq_printf(m, "\n");
+		total_obj_size += obj->base.size;
+		total_gtt_size += obj->gtt_space->size;
+		count++;
+	}
+
+	mutex_unlock(&dev->struct_mutex);
+
+	seq_printf(m, "Total %d objects, %zu bytes, %zu GTT size\n",
+		   count, total_obj_size, total_gtt_size);
+
+	return 0;
+}
+
 
 static int i915_gem_pageflip_info(struct seq_file *m, void *data)
 {
@@ -243,14 +350,14 @@ static int i915_gem_pageflip_info(struct
 			seq_printf(m, "%d prepares\n", work->pending);
 
 			if (work->old_fb_obj) {
-				struct drm_i915_gem_object *obj_priv = to_intel_bo(work->old_fb_obj);
-				if(obj_priv)
-					seq_printf(m, "Old framebuffer gtt_offset 0x%08x\n", obj_priv->gtt_offset );
+				struct drm_i915_gem_object *obj = work->old_fb_obj;
+				if (obj)
+					seq_printf(m, "Old framebuffer gtt_offset 0x%08x\n", obj->gtt_offset);
 			}
 			if (work->pending_flip_obj) {
-				struct drm_i915_gem_object *obj_priv = to_intel_bo(work->pending_flip_obj);
-				if(obj_priv)
-					seq_printf(m, "New framebuffer gtt_offset 0x%08x\n", obj_priv->gtt_offset );
+				struct drm_i915_gem_object *obj = work->pending_flip_obj;
+				if (obj)
+					seq_printf(m, "New framebuffer gtt_offset 0x%08x\n", obj->gtt_offset);
 			}
 		}
 		spin_unlock_irqrestore(&dev->event_lock, flags);
@@ -265,44 +372,80 @@ static int i915_gem_request_info(struct
 	struct drm_device *dev = node->minor->dev;
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	struct drm_i915_gem_request *gem_request;
-	int ret;
+	int ret, count;
 
 	ret = mutex_lock_interruptible(&dev->struct_mutex);
 	if (ret)
 		return ret;
 
-	seq_printf(m, "Request:\n");
-	list_for_each_entry(gem_request, &dev_priv->render_ring.request_list,
-			list) {
-		seq_printf(m, "    %d @ %d\n",
-			   gem_request->seqno,
-			   (int) (jiffies - gem_request->emitted_jiffies));
+	count = 0;
+	if (!list_empty(&dev_priv->ring[RCS].request_list)) {
+		seq_printf(m, "Render requests:\n");
+		list_for_each_entry(gem_request,
+				    &dev_priv->ring[RCS].request_list,
+				    list) {
+			seq_printf(m, "    %d @ %d\n",
+				   gem_request->seqno,
+				   (int) (jiffies - gem_request->emitted_jiffies));
+		}
+		count++;
+	}
+	if (!list_empty(&dev_priv->ring[VCS].request_list)) {
+		seq_printf(m, "BSD requests:\n");
+		list_for_each_entry(gem_request,
+				    &dev_priv->ring[VCS].request_list,
+				    list) {
+			seq_printf(m, "    %d @ %d\n",
+				   gem_request->seqno,
+				   (int) (jiffies - gem_request->emitted_jiffies));
+		}
+		count++;
+	}
+	if (!list_empty(&dev_priv->ring[BCS].request_list)) {
+		seq_printf(m, "BLT requests:\n");
+		list_for_each_entry(gem_request,
+				    &dev_priv->ring[BCS].request_list,
+				    list) {
+			seq_printf(m, "    %d @ %d\n",
+				   gem_request->seqno,
+				   (int) (jiffies - gem_request->emitted_jiffies));
+		}
+		count++;
 	}
 	mutex_unlock(&dev->struct_mutex);
 
+	if (count == 0)
+		seq_printf(m, "No requests\n");
+
 	return 0;
 }
 
+static void i915_ring_seqno_info(struct seq_file *m,
+				 struct intel_ring_buffer *ring)
+{
+	if (ring->get_seqno) {
+		seq_printf(m, "Current sequence (%s): %d\n",
+			   ring->name, ring->get_seqno(ring));
+		seq_printf(m, "Waiter sequence (%s):  %d\n",
+			   ring->name, ring->waiting_seqno);
+		seq_printf(m, "IRQ sequence (%s):     %d\n",
+			   ring->name, ring->irq_seqno);
+	}
+}
+
 static int i915_gem_seqno_info(struct seq_file *m, void *data)
 {
 	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;
+	int ret, i;
 
 	ret = mutex_lock_interruptible(&dev->struct_mutex);
 	if (ret)
 		return ret;
 
-	if (dev_priv->render_ring.status_page.page_addr != NULL) {
-		seq_printf(m, "Current sequence: %d\n",
-			   dev_priv->render_ring.get_seqno(dev, &dev_priv->render_ring));
-	} else {
-		seq_printf(m, "Current sequence: hws uninitialized\n");
-	}
-	seq_printf(m, "Waiter sequence:  %d\n",
-			dev_priv->mm.waiting_gem_seqno);
-	seq_printf(m, "IRQ sequence:     %d\n", dev_priv->mm.irq_gem_seqno);
+	for (i = 0; i < I915_NUM_RINGS; i++)
+		i915_ring_seqno_info(m, &dev_priv->ring[i]);
 
 	mutex_unlock(&dev->struct_mutex);
 
@@ -315,7 +458,7 @@ static int i915_interrupt_info(struct se
 	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;
+	int ret, i;
 
 	ret = mutex_lock_interruptible(&dev->struct_mutex);
 	if (ret)
@@ -354,16 +497,14 @@ static int i915_interrupt_info(struct se
 	}
 	seq_printf(m, "Interrupts received: %d\n",
 		   atomic_read(&dev_priv->irq_received));
-	if (dev_priv->render_ring.status_page.page_addr != NULL) {
-		seq_printf(m, "Current sequence:    %d\n",
-			   dev_priv->render_ring.get_seqno(dev, &dev_priv->render_ring));
-	} else {
-		seq_printf(m, "Current sequence:    hws uninitialized\n");
+	for (i = 0; i < I915_NUM_RINGS; i++) {
+		if (IS_GEN6(dev)) {
+			seq_printf(m, "Graphics Interrupt mask (%s):	%08x\n",
+				   dev_priv->ring[i].name,
+				   I915_READ_IMR(&dev_priv->ring[i]));
+		}
+		i915_ring_seqno_info(m, &dev_priv->ring[i]);
 	}
-	seq_printf(m, "Waiter sequence:     %d\n",
-		   dev_priv->mm.waiting_gem_seqno);
-	seq_printf(m, "IRQ sequence:        %d\n",
-		   dev_priv->mm.irq_gem_seqno);
 	mutex_unlock(&dev->struct_mutex);
 
 	return 0;
@@ -383,29 +524,17 @@ static int i915_gem_fence_regs_info(stru
 	seq_printf(m, "Reserved fences = %d\n", dev_priv->fence_reg_start);
 	seq_printf(m, "Total fences = %d\n", dev_priv->num_fence_regs);
 	for (i = 0; i < dev_priv->num_fence_regs; i++) {
-		struct drm_gem_object *obj = dev_priv->fence_regs[i].obj;
-
-		if (obj == NULL) {
-			seq_printf(m, "Fenced object[%2d] = unused\n", i);
-		} else {
-			struct drm_i915_gem_object *obj_priv;
+		struct drm_i915_gem_object *obj = dev_priv->fence_regs[i].obj;
 
-			obj_priv = to_intel_bo(obj);
-			seq_printf(m, "Fenced object[%2d] = %p: %s "
-				   "%08x %08zx %08x %s %08x %08x %d",
-				   i, obj, get_pin_flag(obj_priv),
-				   obj_priv->gtt_offset,
-				   obj->size, obj_priv->stride,
-				   get_tiling_flag(obj_priv),
-				   obj->read_domains, obj->write_domain,
-				   obj_priv->last_rendering_seqno);
-			if (obj->name)
-				seq_printf(m, " (name: %d)", obj->name);
-			seq_printf(m, "\n");
-		}
+		seq_printf(m, "Fenced object[%2d] = ", i);
+		if (obj == NULL)
+			seq_printf(m, "unused");
+		else
+			describe_obj(m, obj);
+		seq_printf(m, "\n");
 	}
-	mutex_unlock(&dev->struct_mutex);
 
+	mutex_unlock(&dev->struct_mutex);
 	return 0;
 }
 
@@ -414,10 +543,12 @@ static int i915_hws_info(struct seq_file
 	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 i;
+	struct intel_ring_buffer *ring;
 	volatile u32 *hws;
+	int i;
 
-	hws = (volatile u32 *)dev_priv->render_ring.status_page.page_addr;
+	ring = &dev_priv->ring[(uintptr_t)node->info_ent->data];
+	hws = (volatile u32 *)ring->status_page.page_addr;
 	if (hws == NULL)
 		return 0;
 
@@ -431,14 +562,14 @@ static int i915_hws_info(struct seq_file
 
 static void i915_dump_object(struct seq_file *m,
 			     struct io_mapping *mapping,
-			     struct drm_i915_gem_object *obj_priv)
+			     struct drm_i915_gem_object *obj)
 {
 	int page, page_count, i;
 
-	page_count = obj_priv->base.size / PAGE_SIZE;
+	page_count = obj->base.size / PAGE_SIZE;
 	for (page = 0; page < page_count; page++) {
 		u32 *mem = io_mapping_map_wc(mapping,
-					     obj_priv->gtt_offset + page * PAGE_SIZE);
+					     obj->gtt_offset + page * PAGE_SIZE);
 		for (i = 0; i < PAGE_SIZE; i += 4)
 			seq_printf(m, "%08x :  %08x\n", i, mem[i / 4]);
 		io_mapping_unmap(mem);
@@ -450,25 +581,21 @@ static int i915_batchbuffer_info(struct
 	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;
-	struct drm_gem_object *obj;
-	struct drm_i915_gem_object *obj_priv;
+	struct drm_i915_gem_object *obj;
 	int ret;
 
 	ret = mutex_lock_interruptible(&dev->struct_mutex);
 	if (ret)
 		return ret;
 
-	list_for_each_entry(obj_priv, &dev_priv->mm.active_list, mm_list) {
-		obj = &obj_priv->base;
-		if (obj->read_domains & I915_GEM_DOMAIN_COMMAND) {
-		    seq_printf(m, "--- gtt_offset = 0x%08x\n",
-			       obj_priv->gtt_offset);
-		    i915_dump_object(m, dev_priv->mm.gtt_mapping, obj_priv);
+	list_for_each_entry(obj, &dev_priv->mm.active_list, mm_list) {
+		if (obj->base.read_domains & I915_GEM_DOMAIN_COMMAND) {
+		    seq_printf(m, "--- gtt_offset = 0x%08x\n", obj->gtt_offset);
+		    i915_dump_object(m, dev_priv->mm.gtt_mapping, obj);
 		}
 	}
 
 	mutex_unlock(&dev->struct_mutex);
-
 	return 0;
 }
 
@@ -477,19 +604,21 @@ static int i915_ringbuffer_data(struct s
 	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;
+	struct intel_ring_buffer *ring;
 	int ret;
 
 	ret = mutex_lock_interruptible(&dev->struct_mutex);
 	if (ret)
 		return ret;
 
-	if (!dev_priv->render_ring.gem_object) {
+	ring = &dev_priv->ring[(uintptr_t)node->info_ent->data];
+	if (!ring->obj) {
 		seq_printf(m, "No ringbuffer setup\n");
 	} else {
-		u8 *virt = dev_priv->render_ring.virtual_start;
+		u8 *virt = ring->virtual_start;
 		uint32_t off;
 
-		for (off = 0; off < dev_priv->render_ring.size; off += 4) {
+		for (off = 0; off < ring->size; off += 4) {
 			uint32_t *ptr = (uint32_t *)(virt + off);
 			seq_printf(m, "%08x :  %08x\n", off, *ptr);
 		}
@@ -504,19 +633,38 @@ static int i915_ringbuffer_info(struct s
 	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;
-	unsigned int head, tail;
+	struct intel_ring_buffer *ring;
 
-	head = I915_READ(PRB0_HEAD) & HEAD_ADDR;
-	tail = I915_READ(PRB0_TAIL) & TAIL_ADDR;
+	ring = &dev_priv->ring[(uintptr_t)node->info_ent->data];
+	if (ring->size == 0)
+		return 0;
 
-	seq_printf(m, "RingHead :  %08x\n", head);
-	seq_printf(m, "RingTail :  %08x\n", tail);
-	seq_printf(m, "RingSize :  %08lx\n", dev_priv->render_ring.size);
-	seq_printf(m, "Acthd :     %08x\n", I915_READ(INTEL_INFO(dev)->gen >= 4 ? ACTHD_I965 : ACTHD));
+	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);
+	seq_printf(m, "  Size :    %08x\n", ring->size);
+	seq_printf(m, "  Active :  %08x\n", intel_ring_get_active_head(ring));
+	seq_printf(m, "  NOPID :   %08x\n", I915_READ_NOPID(ring));
+	if (IS_GEN6(dev)) {
+		seq_printf(m, "  Sync 0 :   %08x\n", I915_READ_SYNC_0(ring));
+		seq_printf(m, "  Sync 1 :   %08x\n", I915_READ_SYNC_1(ring));
+	}
+	seq_printf(m, "  Control : %08x\n", I915_READ_CTL(ring));
+	seq_printf(m, "  Start :   %08x\n", I915_READ_START(ring));
 
 	return 0;
 }
 
+static const char *ring_str(int ring)
+{
+	switch (ring) {
+	case RING_RENDER: return " render";
+	case RING_BSD: return " bsd";
+	case RING_BLT: return " blt";
+	default: return "";
+	}
+}
+
 static const char *pin_flag(int pinned)
 {
 	if (pinned > 0)
@@ -547,6 +695,37 @@ static const char *purgeable_flag(int pu
 	return purgeable ? " purgeable" : "";
 }
 
+static void print_error_buffers(struct seq_file *m,
+				const char *name,
+				struct drm_i915_error_buffer *err,
+				int count)
+{
+	seq_printf(m, "%s [%d]:\n", name, count);
+
+	while (count--) {
+		seq_printf(m, "  %08x %8u %04x %04x %08x%s%s%s%s%s%s",
+			   err->gtt_offset,
+			   err->size,
+			   err->read_domains,
+			   err->write_domain,
+			   err->seqno,
+			   pin_flag(err->pinned),
+			   tiling_flag(err->tiling),
+			   dirty_flag(err->dirty),
+			   purgeable_flag(err->purgeable),
+			   ring_str(err->ring),
+			   agp_type_str(err->agp_type));
+
+		if (err->name)
+			seq_printf(m, " (name: %d)", err->name);
+		if (err->fence_reg != I915_FENCE_REG_NONE)
+			seq_printf(m, " (fence: %d)", err->fence_reg);
+
+		seq_printf(m, "\n");
+		err++;
+	}
+}
+
 static int i915_error_state(struct seq_file *m, void *unused)
 {
 	struct drm_info_node *node = (struct drm_info_node *) m->private;
@@ -568,47 +747,54 @@ static int i915_error_state(struct seq_f
 		   error->time.tv_usec);
 	seq_printf(m, "PCI ID: 0x%04x\n", dev->pci_device);
 	seq_printf(m, "EIR: 0x%08x\n", error->eir);
-	seq_printf(m, "  PGTBL_ER: 0x%08x\n", error->pgtbl_er);
-	seq_printf(m, "  INSTPM: 0x%08x\n", error->instpm);
+	seq_printf(m, "PGTBL_ER: 0x%08x\n", error->pgtbl_er);
+	if (INTEL_INFO(dev)->gen >= 6) {
+		seq_printf(m, "ERROR: 0x%08x\n", error->error);
+		seq_printf(m, "Blitter command stream:\n");
+		seq_printf(m, "  ACTHD:    0x%08x\n", error->bcs_acthd);
+		seq_printf(m, "  IPEIR:    0x%08x\n", error->bcs_ipeir);
+		seq_printf(m, "  IPEHR:    0x%08x\n", error->bcs_ipehr);
+		seq_printf(m, "  INSTDONE: 0x%08x\n", error->bcs_instdone);
+		seq_printf(m, "  seqno:    0x%08x\n", error->bcs_seqno);
+		seq_printf(m, "Video (BSD) command stream:\n");
+		seq_printf(m, "  ACTHD:    0x%08x\n", error->vcs_acthd);
+		seq_printf(m, "  IPEIR:    0x%08x\n", error->vcs_ipeir);
+		seq_printf(m, "  IPEHR:    0x%08x\n", error->vcs_ipehr);
+		seq_printf(m, "  INSTDONE: 0x%08x\n", error->vcs_instdone);
+		seq_printf(m, "  seqno:    0x%08x\n", error->vcs_seqno);
+	}
+	seq_printf(m, "Render command stream:\n");
+	seq_printf(m, "  ACTHD: 0x%08x\n", error->acthd);
 	seq_printf(m, "  IPEIR: 0x%08x\n", error->ipeir);
 	seq_printf(m, "  IPEHR: 0x%08x\n", error->ipehr);
 	seq_printf(m, "  INSTDONE: 0x%08x\n", error->instdone);
-	seq_printf(m, "  ACTHD: 0x%08x\n", error->acthd);
 	if (INTEL_INFO(dev)->gen >= 4) {
-		seq_printf(m, "  INSTPS: 0x%08x\n", error->instps);
 		seq_printf(m, "  INSTDONE1: 0x%08x\n", error->instdone1);
+		seq_printf(m, "  INSTPS: 0x%08x\n", error->instps);
 	}
-	seq_printf(m, "seqno: 0x%08x\n", error->seqno);
-
-	if (error->active_bo_count) {
-		seq_printf(m, "Buffers [%d]:\n", error->active_bo_count);
+	seq_printf(m, "  INSTPM: 0x%08x\n", error->instpm);
+	seq_printf(m, "  seqno: 0x%08x\n", error->seqno);
 
-		for (i = 0; i < error->active_bo_count; i++) {
-			seq_printf(m, "  %08x %8zd %08x %08x %08x%s%s%s%s",
-				   error->active_bo[i].gtt_offset,
-				   error->active_bo[i].size,
-				   error->active_bo[i].read_domains,
-				   error->active_bo[i].write_domain,
-				   error->active_bo[i].seqno,
-				   pin_flag(error->active_bo[i].pinned),
-				   tiling_flag(error->active_bo[i].tiling),
-				   dirty_flag(error->active_bo[i].dirty),
-				   purgeable_flag(error->active_bo[i].purgeable));
+	for (i = 0; i < 16; i++)
+		seq_printf(m, "  fence[%d] = %08llx\n", i, error->fence[i]);
 
-			if (error->active_bo[i].name)
-				seq_printf(m, " (name: %d)", error->active_bo[i].name);
-			if (error->active_bo[i].fence_reg != I915_FENCE_REG_NONE)
-				seq_printf(m, " (fence: %d)", error->active_bo[i].fence_reg);
+	if (error->active_bo)
+		print_error_buffers(m, "Active",
+				    error->active_bo,
+				    error->active_bo_count);
 
-			seq_printf(m, "\n");
-		}
-	}
+	if (error->pinned_bo)
+		print_error_buffers(m, "Pinned",
+				    error->pinned_bo,
+				    error->pinned_bo_count);
 
 	for (i = 0; i < ARRAY_SIZE(error->batchbuffer); i++) {
 		if (error->batchbuffer[i]) {
 			struct drm_i915_error_object *obj = error->batchbuffer[i];
 
-			seq_printf(m, "--- gtt_offset = 0x%08x\n", obj->gtt_offset);
+			seq_printf(m, "%s --- gtt_offset = 0x%08x\n",
+				   dev_priv->ring[i].name,
+				   obj->gtt_offset);
 			offset = 0;
 			for (page = 0; page < obj->page_count; page++) {
 				for (elt = 0; elt < PAGE_SIZE/4; elt++) {
@@ -635,6 +821,9 @@ static int i915_error_state(struct seq_f
 	if (error->overlay)
 		intel_overlay_print_error_state(m, error->overlay);
 
+	if (error->display)
+		intel_display_print_error_state(m, dev, error->display);
+
 out:
 	spin_unlock_irqrestore(&dev_priv->error_lock, flags);
 
@@ -658,15 +847,51 @@ static int i915_cur_delayinfo(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 rgvswctl = I915_READ16(MEMSWCTL);
-	u16 rgvstat = I915_READ16(MEMSTAT_ILK);
 
-	seq_printf(m, "Requested P-state: %d\n", (rgvswctl >> 8) & 0xf);
-	seq_printf(m, "Requested VID: %d\n", rgvswctl & 0x3f);
-	seq_printf(m, "Current VID: %d\n", (rgvstat & MEMSTAT_VID_MASK) >>
-		   MEMSTAT_VID_SHIFT);
-	seq_printf(m, "Current P-state: %d\n",
-		   (rgvstat & MEMSTAT_PSTATE_MASK) >> MEMSTAT_PSTATE_SHIFT);
+	if (IS_GEN5(dev)) {
+		u16 rgvswctl = I915_READ16(MEMSWCTL);
+		u16 rgvstat = I915_READ16(MEMSTAT_ILK);
+
+		seq_printf(m, "Requested P-state: %d\n", (rgvswctl >> 8) & 0xf);
+		seq_printf(m, "Requested VID: %d\n", rgvswctl & 0x3f);
+		seq_printf(m, "Current VID: %d\n", (rgvstat & MEMSTAT_VID_MASK) >>
+			   MEMSTAT_VID_SHIFT);
+		seq_printf(m, "Current P-state: %d\n",
+			   (rgvstat & MEMSTAT_PSTATE_MASK) >> MEMSTAT_PSTATE_SHIFT);
+	} else if (IS_GEN6(dev)) {
+		u32 gt_perf_status = I915_READ(GEN6_GT_PERF_STATUS);
+		u32 rp_state_limits = I915_READ(GEN6_RP_STATE_LIMITS);
+		u32 rp_state_cap = I915_READ(GEN6_RP_STATE_CAP);
+		int max_freq;
+
+		/* RPSTAT1 is in the GT power well */
+		__gen6_gt_force_wake_get(dev_priv);
+
+		seq_printf(m, "GT_PERF_STATUS: 0x%08x\n", gt_perf_status);
+		seq_printf(m, "RPSTAT1: 0x%08x\n", I915_READ(GEN6_RPSTAT1));
+		seq_printf(m, "Render p-state ratio: %d\n",
+			   (gt_perf_status & 0xff00) >> 8);
+		seq_printf(m, "Render p-state VID: %d\n",
+			   gt_perf_status & 0xff);
+		seq_printf(m, "Render p-state limit: %d\n",
+			   rp_state_limits & 0xff);
+
+		max_freq = (rp_state_cap & 0xff0000) >> 16;
+		seq_printf(m, "Lowest (RPN) frequency: %dMHz\n",
+			   max_freq * 100);
+
+		max_freq = (rp_state_cap & 0xff00) >> 8;
+		seq_printf(m, "Nominal (RP1) frequency: %dMHz\n",
+			   max_freq * 100);
+
+		max_freq = rp_state_cap & 0xff;
+		seq_printf(m, "Max non-overclocked (RP0) frequency: %dMHz\n",
+			   max_freq * 100);
+
+		__gen6_gt_force_wake_put(dev_priv);
+	} else {
+		seq_printf(m, "no P-state info available\n");
+	}
 
 	return 0;
 }
@@ -715,7 +940,7 @@ static int i915_drpc_info(struct seq_fil
 	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(MCHBAR_RENDER_STANDBY);
+	u32 rstdbyctl = I915_READ(RSTDBYCTL);
 	u16 crstandvid = I915_READ16(CRSTANDVID);
 
 	seq_printf(m, "HD boost: %s\n", (rgvmodectl & MEMMODE_BOOST_EN) ?
@@ -738,6 +963,30 @@ static int i915_drpc_info(struct seq_fil
 	seq_printf(m, "RS2 VID: %d\n", ((crstandvid >> 8) & 0x3f));
 	seq_printf(m, "Render standby enabled: %s\n",
 		   (rstdbyctl & RCX_SW_EXIT) ? "no" : "yes");
+	seq_printf(m, "Current RS state: ");
+	switch (rstdbyctl & RSX_STATUS_MASK) {
+	case RSX_STATUS_ON:
+		seq_printf(m, "on\n");
+		break;
+	case RSX_STATUS_RC1:
+		seq_printf(m, "RC1\n");
+		break;
+	case RSX_STATUS_RC1E:
+		seq_printf(m, "RC1E\n");
+		break;
+	case RSX_STATUS_RS1:
+		seq_printf(m, "RS1\n");
+		break;
+	case RSX_STATUS_RS2:
+		seq_printf(m, "RS2 (RC6)\n");
+		break;
+	case RSX_STATUS_RS3:
+		seq_printf(m, "RC3 (RC6+)\n");
+		break;
+	default:
+		seq_printf(m, "unknown\n");
+		break;
+	}
 
 	return 0;
 }
@@ -794,7 +1043,7 @@ static int i915_sr_status(struct seq_fil
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	bool sr_enabled = false;
 
-	if (IS_GEN5(dev))
+	if (HAS_PCH_SPLIT(dev))
 		sr_enabled = I915_READ(WM1_LP_ILK) & WM1_LP_SR_EN;
 	else if (IS_CRESTLINE(dev) || IS_I945G(dev) || IS_I945GM(dev))
 		sr_enabled = I915_READ(FW_BLC_SELF) & FW_BLC_SELF_EN;
@@ -886,7 +1135,7 @@ static int i915_gem_framebuffer_info(str
 		   fb->base.height,
 		   fb->base.depth,
 		   fb->base.bits_per_pixel);
-	describe_obj(m, to_intel_bo(fb->obj));
+	describe_obj(m, fb->obj);
 	seq_printf(m, "\n");
 
 	list_for_each_entry(fb, &dev->mode_config.fb_list, base.head) {
@@ -898,7 +1147,7 @@ static int i915_gem_framebuffer_info(str
 			   fb->base.height,
 			   fb->base.depth,
 			   fb->base.bits_per_pixel);
-		describe_obj(m, to_intel_bo(fb->obj));
+		describe_obj(m, fb->obj);
 		seq_printf(m, "\n");
 	}
 
@@ -943,7 +1192,6 @@ i915_wedged_write(struct file *filp,
 		  loff_t *ppos)
 {
 	struct drm_device *dev = filp->private_data;
-	drm_i915_private_t *dev_priv = dev->dev_private;
 	char buf[20];
 	int val = 1;
 
@@ -959,12 +1207,7 @@ i915_wedged_write(struct file *filp,
 	}
 
 	DRM_INFO("Manually setting wedged to %d\n", val);
-
-	atomic_set(&dev_priv->mm.wedged, val);
-	if (val) {
-		wake_up_all(&dev_priv->irq_queue);
-		queue_work(dev_priv->wq, &dev_priv->error_work);
-	}
+	i915_handle_error(dev, val);
 
 	return cnt;
 }
@@ -1018,6 +1261,7 @@ static int i915_wedged_create(struct den
 static struct drm_info_list i915_debugfs_list[] = {
 	{"i915_capabilities", i915_capabilities, 0, 0},
 	{"i915_gem_objects", i915_gem_object_info, 0},
+	{"i915_gem_gtt", i915_gem_gtt_info, 0},
 	{"i915_gem_active", i915_gem_object_list_info, 0, (void *) ACTIVE_LIST},
 	{"i915_gem_flushing", i915_gem_object_list_info, 0, (void *) FLUSHING_LIST},
 	{"i915_gem_inactive", i915_gem_object_list_info, 0, (void *) INACTIVE_LIST},
@@ -1028,9 +1272,15 @@ static struct drm_info_list i915_debugfs
 	{"i915_gem_seqno", i915_gem_seqno_info, 0},
 	{"i915_gem_fence_regs", i915_gem_fence_regs_info, 0},
 	{"i915_gem_interrupt", i915_interrupt_info, 0},
-	{"i915_gem_hws", i915_hws_info, 0},
-	{"i915_ringbuffer_data", i915_ringbuffer_data, 0},
-	{"i915_ringbuffer_info", i915_ringbuffer_info, 0},
+	{"i915_gem_hws", i915_hws_info, 0, (void *)RCS},
+	{"i915_gem_hws_blt", i915_hws_info, 0, (void *)BCS},
+	{"i915_gem_hws_bsd", i915_hws_info, 0, (void *)VCS},
+	{"i915_ringbuffer_data", i915_ringbuffer_data, 0, (void *)RCS},
+	{"i915_ringbuffer_info", i915_ringbuffer_info, 0, (void *)RCS},
+	{"i915_bsd_ringbuffer_data", i915_ringbuffer_data, 0, (void *)VCS},
+	{"i915_bsd_ringbuffer_info", i915_ringbuffer_info, 0, (void *)VCS},
+	{"i915_blt_ringbuffer_data", i915_ringbuffer_data, 0, (void *)BCS},
+	{"i915_blt_ringbuffer_info", i915_ringbuffer_info, 0, (void *)BCS},
 	{"i915_batchbuffers", i915_batchbuffer_info, 0},
 	{"i915_error_state", i915_error_state, 0},
 	{"i915_rstdby_delays", i915_rstdby_delays, 0},
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/i915/i915_dma.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/i915/i915_dma.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/i915/i915_dma.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/i915/i915_dma.c	2011-03-14 21:20:32.000000000 -0400
@@ -50,6 +50,8 @@
 static int i915_init_phys_hws(struct drm_device *dev)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
+	struct intel_ring_buffer *ring = LP_RING(dev_priv);
+
 	/* Program Hardware Status Page */
 	dev_priv->status_page_dmah =
 		drm_pci_alloc(dev, PAGE_SIZE, PAGE_SIZE);
@@ -58,11 +60,10 @@ static int i915_init_phys_hws(struct drm
 		DRM_ERROR("Can not allocate hardware status page\n");
 		return -ENOMEM;
 	}
-	dev_priv->render_ring.status_page.page_addr
-		= dev_priv->status_page_dmah->vaddr;
+	ring->status_page.page_addr = dev_priv->status_page_dmah->vaddr;
 	dev_priv->dma_status_page = dev_priv->status_page_dmah->busaddr;
 
-	memset(dev_priv->render_ring.status_page.page_addr, 0, PAGE_SIZE);
+	memset(ring->status_page.page_addr, 0, PAGE_SIZE);
 
 	if (INTEL_INFO(dev)->gen >= 4)
 		dev_priv->dma_status_page |= (dev_priv->dma_status_page >> 28) &
@@ -80,13 +81,15 @@ static int i915_init_phys_hws(struct drm
 static void i915_free_hws(struct drm_device *dev)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
+	struct intel_ring_buffer *ring = LP_RING(dev_priv);
+
 	if (dev_priv->status_page_dmah) {
 		drm_pci_free(dev, dev_priv->status_page_dmah);
 		dev_priv->status_page_dmah = NULL;
 	}
 
-	if (dev_priv->render_ring.status_page.gfx_addr) {
-		dev_priv->render_ring.status_page.gfx_addr = 0;
+	if (ring->status_page.gfx_addr) {
+		ring->status_page.gfx_addr = 0;
 		drm_core_ioremapfree(&dev_priv->hws_map, dev);
 	}
 
@@ -98,7 +101,7 @@ void i915_kernel_lost_context(struct drm
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	struct drm_i915_master_private *master_priv;
-	struct intel_ring_buffer *ring = &dev_priv->render_ring;
+	struct intel_ring_buffer *ring = LP_RING(dev_priv);
 
 	/*
 	 * We should never lose context on the ring with modesetting
@@ -107,8 +110,8 @@ void i915_kernel_lost_context(struct drm
 	if (drm_core_check_feature(dev, DRIVER_MODESET))
 		return;
 
-	ring->head = I915_READ(PRB0_HEAD) & HEAD_ADDR;
-	ring->tail = I915_READ(PRB0_TAIL) & TAIL_ADDR;
+	ring->head = I915_READ_HEAD(ring) & HEAD_ADDR;
+	ring->tail = I915_READ_TAIL(ring) & TAIL_ADDR;
 	ring->space = ring->head - (ring->tail + 8);
 	if (ring->space < 0)
 		ring->space += ring->size;
@@ -124,6 +127,8 @@ void i915_kernel_lost_context(struct drm
 static int i915_dma_cleanup(struct drm_device * dev)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
+	int i;
+
 	/* Make sure interrupts are disabled here because the uninstall ioctl
 	 * may not have been called from userspace and after dev_private
 	 * is freed, it's too late.
@@ -132,9 +137,8 @@ static int i915_dma_cleanup(struct drm_d
 		drm_irq_uninstall(dev);
 
 	mutex_lock(&dev->struct_mutex);
-	intel_cleanup_ring_buffer(dev, &dev_priv->render_ring);
-	intel_cleanup_ring_buffer(dev, &dev_priv->bsd_ring);
-	intel_cleanup_ring_buffer(dev, &dev_priv->blt_ring);
+	for (i = 0; i < I915_NUM_RINGS; i++)
+		intel_cleanup_ring_buffer(&dev_priv->ring[i]);
 	mutex_unlock(&dev->struct_mutex);
 
 	/* Clear the HWS virtual address at teardown */
@@ -148,6 +152,7 @@ static int i915_initialize(struct drm_de
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
+	int ret;
 
 	master_priv->sarea = drm_getsarea(dev);
 	if (master_priv->sarea) {
@@ -158,33 +163,22 @@ static int i915_initialize(struct drm_de
 	}
 
 	if (init->ring_size != 0) {
-		if (dev_priv->render_ring.gem_object != NULL) {
+		if (LP_RING(dev_priv)->obj != NULL) {
 			i915_dma_cleanup(dev);
 			DRM_ERROR("Client tried to initialize ringbuffer in "
 				  "GEM mode\n");
 			return -EINVAL;
 		}
 
-		dev_priv->render_ring.size = init->ring_size;
-
-		dev_priv->render_ring.map.offset = init->ring_start;
-		dev_priv->render_ring.map.size = init->ring_size;
-		dev_priv->render_ring.map.type = 0;
-		dev_priv->render_ring.map.flags = 0;
-		dev_priv->render_ring.map.mtrr = 0;
-
-		drm_core_ioremap_wc(&dev_priv->render_ring.map, dev);
-
-		if (dev_priv->render_ring.map.handle == NULL) {
+		ret = intel_render_ring_init_dri(dev,
+						 init->ring_start,
+						 init->ring_size);
+		if (ret) {
 			i915_dma_cleanup(dev);
-			DRM_ERROR("can not ioremap virtual address for"
-				  " ring buffer\n");
-			return -ENOMEM;
+			return ret;
 		}
 	}
 
-	dev_priv->render_ring.virtual_start = dev_priv->render_ring.map.handle;
-
 	dev_priv->cpp = init->cpp;
 	dev_priv->back_offset = init->back_offset;
 	dev_priv->front_offset = init->front_offset;
@@ -202,12 +196,10 @@ static int i915_initialize(struct drm_de
 static int i915_dma_resume(struct drm_device * dev)
 {
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+	struct intel_ring_buffer *ring = LP_RING(dev_priv);
 
-	struct intel_ring_buffer *ring;
 	DRM_DEBUG_DRIVER("%s\n", __func__);
 
-	ring = &dev_priv->render_ring;
-
 	if (ring->map.handle == NULL) {
 		DRM_ERROR("can not ioremap virtual address for"
 			  " ring buffer\n");
@@ -222,7 +214,7 @@ static int i915_dma_resume(struct drm_de
 	DRM_DEBUG_DRIVER("hw status page @ %p\n",
 				ring->status_page.page_addr);
 	if (ring->status_page.gfx_addr != 0)
-		intel_ring_setup_status_page(dev, ring);
+		intel_ring_setup_status_page(ring);
 	else
 		I915_WRITE(HWS_PGA, dev_priv->dma_status_page);
 
@@ -264,7 +256,7 @@ static int i915_dma_init(struct drm_devi
  * instruction detected will be given a size of zero, which is a
  * signal to abort the rest of the buffer.
  */
-static int do_validate_cmd(int cmd)
+static int validate_cmd(int cmd)
 {
 	switch (((cmd >> 29) & 0x7)) {
 	case 0x0:
@@ -322,40 +314,27 @@ static int do_validate_cmd(int cmd)
 	return 0;
 }
 
-static int validate_cmd(int cmd)
-{
-	int ret = do_validate_cmd(cmd);
-
-/*	printk("validate_cmd( %x ): %d\n", cmd, ret); */
-
-	return ret;
-}
-
 static int i915_emit_cmds(struct drm_device * dev, int *buffer, int dwords)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
-	int i;
+	int i, ret;
 
-	if ((dwords+1) * sizeof(int) >= dev_priv->render_ring.size - 8)
+	if ((dwords+1) * sizeof(int) >= LP_RING(dev_priv)->size - 8)
 		return -EINVAL;
 
-	BEGIN_LP_RING((dwords+1)&~1);
-
 	for (i = 0; i < dwords;) {
-		int cmd, sz;
-
-		cmd = buffer[i];
-
-		if ((sz = validate_cmd(cmd)) == 0 || i + sz > dwords)
+		int sz = validate_cmd(buffer[i]);
+		if (sz == 0 || i + sz > dwords)
 			return -EINVAL;
-
-		OUT_RING(cmd);
-
-		while (++i, --sz) {
-			OUT_RING(buffer[i]);
-		}
+		i += sz;
 	}
 
+	ret = BEGIN_LP_RING((dwords+1)&~1);
+	if (ret)
+		return ret;
+
+	for (i = 0; i < dwords; i++)
+		OUT_RING(buffer[i]);
 	if (dwords & 1)
 		OUT_RING(0);
 
@@ -366,34 +345,41 @@ static int i915_emit_cmds(struct drm_dev
 
 int
 i915_emit_box(struct drm_device *dev,
-	      struct drm_clip_rect *boxes,
-	      int i, int DR1, int DR4)
+	      struct drm_clip_rect *box,
+	      int DR1, int DR4)
 {
-	struct drm_clip_rect box = boxes[i];
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	int ret;
 
-	if (box.y2 <= box.y1 || box.x2 <= box.x1 || box.y2 <= 0 || box.x2 <= 0) {
+	if (box->y2 <= box->y1 || box->x2 <= box->x1 ||
+	    box->y2 <= 0 || box->x2 <= 0) {
 		DRM_ERROR("Bad box %d,%d..%d,%d\n",
-			  box.x1, box.y1, box.x2, box.y2);
+			  box->x1, box->y1, box->x2, box->y2);
 		return -EINVAL;
 	}
 
 	if (INTEL_INFO(dev)->gen >= 4) {
-		BEGIN_LP_RING(4);
+		ret = BEGIN_LP_RING(4);
+		if (ret)
+			return ret;
+
 		OUT_RING(GFX_OP_DRAWRECT_INFO_I965);
-		OUT_RING((box.x1 & 0xffff) | (box.y1 << 16));
-		OUT_RING(((box.x2 - 1) & 0xffff) | ((box.y2 - 1) << 16));
+		OUT_RING((box->x1 & 0xffff) | (box->y1 << 16));
+		OUT_RING(((box->x2 - 1) & 0xffff) | ((box->y2 - 1) << 16));
 		OUT_RING(DR4);
-		ADVANCE_LP_RING();
 	} else {
-		BEGIN_LP_RING(6);
+		ret = BEGIN_LP_RING(6);
+		if (ret)
+			return ret;
+
 		OUT_RING(GFX_OP_DRAWRECT_INFO);
 		OUT_RING(DR1);
-		OUT_RING((box.x1 & 0xffff) | (box.y1 << 16));
-		OUT_RING(((box.x2 - 1) & 0xffff) | ((box.y2 - 1) << 16));
+		OUT_RING((box->x1 & 0xffff) | (box->y1 << 16));
+		OUT_RING(((box->x2 - 1) & 0xffff) | ((box->y2 - 1) << 16));
 		OUT_RING(DR4);
 		OUT_RING(0);
-		ADVANCE_LP_RING();
 	}
+	ADVANCE_LP_RING();
 
 	return 0;
 }
@@ -413,12 +399,13 @@ static void i915_emit_breadcrumb(struct
 	if (master_priv->sarea_priv)
 		master_priv->sarea_priv->last_enqueue = dev_priv->counter;
 
-	BEGIN_LP_RING(4);
-	OUT_RING(MI_STORE_DWORD_INDEX);
-	OUT_RING(I915_BREADCRUMB_INDEX << MI_STORE_DWORD_INDEX_SHIFT);
-	OUT_RING(dev_priv->counter);
-	OUT_RING(0);
-	ADVANCE_LP_RING();
+	if (BEGIN_LP_RING(4) == 0) {
+		OUT_RING(MI_STORE_DWORD_INDEX);
+		OUT_RING(I915_BREADCRUMB_INDEX << MI_STORE_DWORD_INDEX_SHIFT);
+		OUT_RING(dev_priv->counter);
+		OUT_RING(0);
+		ADVANCE_LP_RING();
+	}
 }
 
 static int i915_dispatch_cmdbuffer(struct drm_device * dev,
@@ -440,7 +427,7 @@ static int i915_dispatch_cmdbuffer(struc
 
 	for (i = 0; i < count; i++) {
 		if (i < nbox) {
-			ret = i915_emit_box(dev, cliprects, i,
+			ret = i915_emit_box(dev, &cliprects[i],
 					    cmd->DR1, cmd->DR4);
 			if (ret)
 				return ret;
@@ -459,8 +446,9 @@ static int i915_dispatch_batchbuffer(str
 				     drm_i915_batchbuffer_t * batch,
 				     struct drm_clip_rect *cliprects)
 {
+	struct drm_i915_private *dev_priv = dev->dev_private;
 	int nbox = batch->num_cliprects;
-	int i = 0, count;
+	int i, count, ret;
 
 	if ((batch->start | batch->used) & 0x7) {
 		DRM_ERROR("alignment");
@@ -470,17 +458,19 @@ static int i915_dispatch_batchbuffer(str
 	i915_kernel_lost_context(dev);
 
 	count = nbox ? nbox : 1;
-
 	for (i = 0; i < count; i++) {
 		if (i < nbox) {
-			int ret = i915_emit_box(dev, cliprects, i,
-						batch->DR1, batch->DR4);
+			ret = i915_emit_box(dev, &cliprects[i],
+					    batch->DR1, batch->DR4);
 			if (ret)
 				return ret;
 		}
 
 		if (!IS_I830(dev) && !IS_845G(dev)) {
-			BEGIN_LP_RING(2);
+			ret = BEGIN_LP_RING(2);
+			if (ret)
+				return ret;
+
 			if (INTEL_INFO(dev)->gen >= 4) {
 				OUT_RING(MI_BATCH_BUFFER_START | (2 << 6) | MI_BATCH_NON_SECURE_I965);
 				OUT_RING(batch->start);
@@ -488,26 +478,29 @@ static int i915_dispatch_batchbuffer(str
 				OUT_RING(MI_BATCH_BUFFER_START | (2 << 6));
 				OUT_RING(batch->start | MI_BATCH_NON_SECURE);
 			}
-			ADVANCE_LP_RING();
 		} else {
-			BEGIN_LP_RING(4);
+			ret = BEGIN_LP_RING(4);
+			if (ret)
+				return ret;
+
 			OUT_RING(MI_BATCH_BUFFER);
 			OUT_RING(batch->start | MI_BATCH_NON_SECURE);
 			OUT_RING(batch->start + batch->used - 4);
 			OUT_RING(0);
-			ADVANCE_LP_RING();
 		}
+		ADVANCE_LP_RING();
 	}
 
 
 	if (IS_G4X(dev) || IS_GEN5(dev)) {
-		BEGIN_LP_RING(2);
-		OUT_RING(MI_FLUSH | MI_NO_WRITE_FLUSH | MI_INVALIDATE_ISP);
-		OUT_RING(MI_NOOP);
-		ADVANCE_LP_RING();
+		if (BEGIN_LP_RING(2) == 0) {
+			OUT_RING(MI_FLUSH | MI_NO_WRITE_FLUSH | MI_INVALIDATE_ISP);
+			OUT_RING(MI_NOOP);
+			ADVANCE_LP_RING();
+		}
 	}
-	i915_emit_breadcrumb(dev);
 
+	i915_emit_breadcrumb(dev);
 	return 0;
 }
 
@@ -516,6 +509,7 @@ static int i915_dispatch_flip(struct drm
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	struct drm_i915_master_private *master_priv =
 		dev->primary->master->driver_priv;
+	int ret;
 
 	if (!master_priv->sarea_priv)
 		return -EINVAL;
@@ -527,12 +521,13 @@ static int i915_dispatch_flip(struct drm
 
 	i915_kernel_lost_context(dev);
 
-	BEGIN_LP_RING(2);
+	ret = BEGIN_LP_RING(10);
+	if (ret)
+		return ret;
+
 	OUT_RING(MI_FLUSH | MI_READ_FLUSH);
 	OUT_RING(0);
-	ADVANCE_LP_RING();
 
-	BEGIN_LP_RING(6);
 	OUT_RING(CMD_OP_DISPLAYBUFFER_INFO | ASYNC_FLIP);
 	OUT_RING(0);
 	if (dev_priv->current_page == 0) {
@@ -543,33 +538,32 @@ static int i915_dispatch_flip(struct drm
 		dev_priv->current_page = 0;
 	}
 	OUT_RING(0);
-	ADVANCE_LP_RING();
 
-	BEGIN_LP_RING(2);
 	OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_PLANE_A_FLIP);
 	OUT_RING(0);
+
 	ADVANCE_LP_RING();
 
 	master_priv->sarea_priv->last_enqueue = dev_priv->counter++;
 
-	BEGIN_LP_RING(4);
-	OUT_RING(MI_STORE_DWORD_INDEX);
-	OUT_RING(I915_BREADCRUMB_INDEX << MI_STORE_DWORD_INDEX_SHIFT);
-	OUT_RING(dev_priv->counter);
-	OUT_RING(0);
-	ADVANCE_LP_RING();
+	if (BEGIN_LP_RING(4) == 0) {
+		OUT_RING(MI_STORE_DWORD_INDEX);
+		OUT_RING(I915_BREADCRUMB_INDEX << MI_STORE_DWORD_INDEX_SHIFT);
+		OUT_RING(dev_priv->counter);
+		OUT_RING(0);
+		ADVANCE_LP_RING();
+	}
 
 	master_priv->sarea_priv->pf_current_page = dev_priv->current_page;
 	return 0;
 }
 
-static int i915_quiescent(struct drm_device * dev)
+static int i915_quiescent(struct drm_device *dev)
 {
-	drm_i915_private_t *dev_priv = dev->dev_private;
+	struct intel_ring_buffer *ring = LP_RING(dev->dev_private);
 
 	i915_kernel_lost_context(dev);
-	return intel_wait_ring_buffer(dev, &dev_priv->render_ring,
-				      dev_priv->render_ring.size - 8);
+	return intel_wait_ring_buffer(ring, ring->size - 8);
 }
 
 static int i915_flush_ioctl(struct drm_device *dev, void *data,
@@ -768,9 +762,15 @@ static int i915_getparam(struct drm_devi
 	case I915_PARAM_HAS_BLT:
 		value = HAS_BLT(dev);
 		break;
+	case I915_PARAM_HAS_RELAXED_FENCING:
+		value = 1;
+		break;
 	case I915_PARAM_HAS_COHERENT_RINGS:
 		value = 1;
 		break;
+	case I915_PARAM_HAS_EXEC_CONSTANTS:
+		value = INTEL_INFO(dev)->gen >= 4;
+		break;
 	default:
 		DRM_DEBUG_DRIVER("Unknown parameter %d\n",
 				 param->param);
@@ -826,7 +826,7 @@ static int i915_set_status_page(struct d
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	drm_i915_hws_addr_t *hws = data;
-	struct intel_ring_buffer *ring = &dev_priv->render_ring;
+	struct intel_ring_buffer *ring = LP_RING(dev_priv);
 
 	if (!I915_NEED_GFX_HWS(dev))
 		return -EINVAL;
@@ -1005,73 +1005,47 @@ intel_teardown_mchbar(struct drm_device
 #define PTE_VALID			(1 << 0)
 
 /**
- * i915_gtt_to_phys - take a GTT address and turn it into a physical one
+ * i915_stolen_to_phys - take an offset into stolen memory and turn it into
+ *                       a physical one
  * @dev: drm device
- * @gtt_addr: address to translate
+ * @offset: address to translate
  *
- * Some chip functions require allocations from stolen space but need the
- * physical address of the memory in question.  We use this routine
- * to get a physical address suitable for register programming from a given
- * GTT address.
+ * Some chip functions require allocations from stolen space and need the
+ * physical address of the memory in question.
  */
-static unsigned long i915_gtt_to_phys(struct drm_device *dev,
-				      unsigned long gtt_addr)
+static unsigned long i915_stolen_to_phys(struct drm_device *dev, u32 offset)
 {
-	unsigned long *gtt;
-	unsigned long entry, phys;
-	int gtt_bar = IS_GEN2(dev) ? 1 : 0;
-	int gtt_offset, gtt_size;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct pci_dev *pdev = dev_priv->bridge_dev;
+	u32 base;
 
-	if (INTEL_INFO(dev)->gen >= 4) {
-		if (IS_G4X(dev) || INTEL_INFO(dev)->gen > 4) {
-			gtt_offset = 2*1024*1024;
-			gtt_size = 2*1024*1024;
-		} else {
-			gtt_offset = 512*1024;
-			gtt_size = 512*1024;
-		}
+#if 0
+	/* On the machines I have tested the Graphics Base of Stolen Memory
+	 * is unreliable, so compute the base by subtracting the stolen memory
+	 * from the Top of Low Usable DRAM which is where the BIOS places
+	 * the graphics stolen memory.
+	 */
+	if (INTEL_INFO(dev)->gen > 3 || IS_G33(dev)) {
+		/* top 32bits are reserved = 0 */
+		pci_read_config_dword(pdev, 0xA4, &base);
 	} else {
-		gtt_bar = 3;
-		gtt_offset = 0;
-		gtt_size = pci_resource_len(dev->pdev, gtt_bar);
-	}
-
-	gtt = ioremap_wc(pci_resource_start(dev->pdev, gtt_bar) + gtt_offset,
-			 gtt_size);
-	if (!gtt) {
-		DRM_ERROR("ioremap of GTT failed\n");
-		return 0;
-	}
-
-	entry = *(volatile u32 *)(gtt + (gtt_addr / 1024));
-
-	DRM_DEBUG_DRIVER("GTT addr: 0x%08lx, PTE: 0x%08lx\n", gtt_addr, entry);
-
-	/* Mask out these reserved bits on this hardware. */
-	if (INTEL_INFO(dev)->gen < 4 && !IS_G33(dev))
-		entry &= ~PTE_ADDRESS_MASK_HIGH;
-
-	/* If it's not a mapping type we know, then bail. */
-	if ((entry & PTE_MAPPING_TYPE_MASK) != PTE_MAPPING_TYPE_UNCACHED &&
-	    (entry & PTE_MAPPING_TYPE_MASK) != PTE_MAPPING_TYPE_CACHED)	{
-		iounmap(gtt);
-		return 0;
+		/* XXX presume 8xx is the same as i915 */
+		pci_bus_read_config_dword(pdev->bus, 2, 0x5C, &base);
 	}
-
-	if (!(entry & PTE_VALID)) {
-		DRM_ERROR("bad GTT entry in stolen space\n");
-		iounmap(gtt);
-		return 0;
+#else
+	if (INTEL_INFO(dev)->gen > 3 || IS_G33(dev)) {
+		u16 val;
+		pci_read_config_word(pdev, 0xb0, &val);
+		base = val >> 4 << 20;
+	} else {
+		u8 val;
+		pci_read_config_byte(pdev, 0x9c, &val);
+		base = val >> 3 << 27;
 	}
+	base -= dev_priv->mm.gtt->stolen_size;
+#endif
 
-	iounmap(gtt);
-
-	phys =(entry & PTE_ADDRESS_MASK) |
-		((uint64_t)(entry & PTE_ADDRESS_MASK_HIGH) << (32 - 4));
-
-	DRM_DEBUG_DRIVER("GTT addr: 0x%08lx, phys addr: 0x%08lx\n", gtt_addr, phys);
-
-	return phys;
+	return base + offset;
 }
 
 static void i915_warn_stolen(struct drm_device *dev)
@@ -1087,54 +1061,35 @@ static void i915_setup_compression(struc
 	unsigned long cfb_base;
 	unsigned long ll_base = 0;
 
-	/* Leave 1M for line length buffer & misc. */
-	compressed_fb = drm_mm_search_free(&dev_priv->mm.vram, size, 4096, 0);
-	if (!compressed_fb) {
-		dev_priv->no_fbc_reason = FBC_STOLEN_TOO_SMALL;
-		i915_warn_stolen(dev);
-		return;
-	}
-
-	compressed_fb = drm_mm_get_block(compressed_fb, size, 4096);
-	if (!compressed_fb) {
-		i915_warn_stolen(dev);
-		dev_priv->no_fbc_reason = FBC_STOLEN_TOO_SMALL;
-		return;
-	}
-
-	cfb_base = i915_gtt_to_phys(dev, compressed_fb->start);
-	if (!cfb_base) {
-		DRM_ERROR("failed to get stolen phys addr, disabling FBC\n");
-		drm_mm_put_block(compressed_fb);
-	}
+	compressed_fb = drm_mm_search_free(&dev_priv->mm.stolen, size, 4096, 0);
+	if (compressed_fb)
+		compressed_fb = drm_mm_get_block(compressed_fb, size, 4096);
+	if (!compressed_fb)
+		goto err;
 
-	if (!(IS_GM45(dev) || IS_IRONLAKE_M(dev))) {
-		compressed_llb = drm_mm_search_free(&dev_priv->mm.vram, 4096,
-						    4096, 0);
-		if (!compressed_llb) {
-			i915_warn_stolen(dev);
-			return;
-		}
+	cfb_base = i915_stolen_to_phys(dev, compressed_fb->start);
+	if (!cfb_base)
+		goto err_fb;
 
-		compressed_llb = drm_mm_get_block(compressed_llb, 4096, 4096);
-		if (!compressed_llb) {
-			i915_warn_stolen(dev);
-			return;
-		}
+	if (!(IS_GM45(dev) || HAS_PCH_SPLIT(dev))) {
+		compressed_llb = drm_mm_search_free(&dev_priv->mm.stolen,
+						    4096, 4096, 0);
+		if (compressed_llb)
+			compressed_llb = drm_mm_get_block(compressed_llb,
+							  4096, 4096);
+		if (!compressed_llb)
+			goto err_fb;
 
-		ll_base = i915_gtt_to_phys(dev, compressed_llb->start);
-		if (!ll_base) {
-			DRM_ERROR("failed to get stolen phys addr, disabling FBC\n");
-			drm_mm_put_block(compressed_fb);
-			drm_mm_put_block(compressed_llb);
-		}
+		ll_base = i915_stolen_to_phys(dev, compressed_llb->start);
+		if (!ll_base)
+			goto err_llb;
 	}
 
 	dev_priv->cfb_size = size;
 
 	intel_disable_fbc(dev);
 	dev_priv->compressed_fb = compressed_fb;
-	if (IS_IRONLAKE_M(dev))
+	if (HAS_PCH_SPLIT(dev))
 		I915_WRITE(ILK_DPFC_CB_BASE, compressed_fb->start);
 	else if (IS_GM45(dev)) {
 		I915_WRITE(DPFC_CB_BASE, compressed_fb->start);
@@ -1144,8 +1099,17 @@ static void i915_setup_compression(struc
 		dev_priv->compressed_llb = compressed_llb;
 	}
 
-	DRM_DEBUG_KMS("FBC base 0x%08lx, ll base 0x%08lx, size %dM\n", cfb_base,
-		  ll_base, size >> 20);
+	DRM_DEBUG_KMS("FBC base 0x%08lx, ll base 0x%08lx, size %dM\n",
+		      cfb_base, ll_base, size >> 20);
+	return;
+
+err_llb:
+	drm_mm_put_block(compressed_llb);
+err_fb:
+	drm_mm_put_block(compressed_fb);
+err:
+	dev_priv->no_fbc_reason = FBC_STOLEN_TOO_SMALL;
+	i915_warn_stolen(dev);
 }
 
 static void i915_cleanup_compression(struct drm_device *dev)
@@ -1176,12 +1140,16 @@ static void i915_switcheroo_set_state(st
 	pm_message_t pmm = { .event = PM_EVENT_SUSPEND };
 	if (state == VGA_SWITCHEROO_ON) {
 		printk(KERN_INFO "i915: switched on\n");
+		dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
 		/* i915 resume handler doesn't set to D0 */
 		pci_set_power_state(dev->pdev, PCI_D0);
 		i915_resume(dev);
+		dev->switch_power_state = DRM_SWITCH_POWER_ON;
 	} else {
 		printk(KERN_ERR "i915: switched off\n");
+		dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
 		i915_suspend(dev, pmm);
+		dev->switch_power_state = DRM_SWITCH_POWER_OFF;
 	}
 }
 
@@ -1196,17 +1164,20 @@ static bool i915_switcheroo_can_switch(s
 	return can_switch;
 }
 
-static int i915_load_modeset_init(struct drm_device *dev,
-				  unsigned long prealloc_size,
-				  unsigned long agp_size)
+static int i915_load_modeset_init(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
+	unsigned long prealloc_size, gtt_size, mappable_size;
 	int ret = 0;
 
-	/* Basic memrange allocator for stolen space (aka mm.vram) */
-	drm_mm_init(&dev_priv->mm.vram, 0, prealloc_size);
+	prealloc_size = dev_priv->mm.gtt->stolen_size;
+	gtt_size = dev_priv->mm.gtt->gtt_total_entries << PAGE_SHIFT;
+	mappable_size = dev_priv->mm.gtt->gtt_mappable_entries << PAGE_SHIFT;
 
-	/* Let GEM Manage from end of prealloc space to end of aperture.
+	/* Basic memrange allocator for stolen space */
+	drm_mm_init(&dev_priv->mm.stolen, 0, prealloc_size);
+
+	/* Let GEM Manage all of the aperture.
 	 *
 	 * However, leave one page at the end still bound to the scratch page.
 	 * There are a number of places where the hardware apparently
@@ -1215,7 +1186,7 @@ static int i915_load_modeset_init(struct
 	 * at the last page of the aperture.  One page should be enough to
 	 * keep any prefetching inside of the aperture.
 	 */
-	i915_gem_do_init(dev, prealloc_size, agp_size - 4096);
+	i915_gem_do_init(dev, 0, mappable_size, gtt_size - PAGE_SIZE);
 
 	mutex_lock(&dev->struct_mutex);
 	ret = i915_gem_init_ringbuffer(dev);
@@ -1227,31 +1198,39 @@ static int i915_load_modeset_init(struct
 	if (I915_HAS_FBC(dev) && i915_powersave) {
 		int cfb_size;
 
-		/* Try to get an 8M buffer... */
-		if (prealloc_size > (9*1024*1024))
-			cfb_size = 8*1024*1024;
+		/* Leave 1M for line length buffer & misc. */
+
+		/* Try to get a 32M buffer... */
+		if (prealloc_size > (36*1024*1024))
+			cfb_size = 32*1024*1024;
 		else /* fall back to 7/8 of the stolen space */
 			cfb_size = prealloc_size * 7 / 8;
 		i915_setup_compression(dev, cfb_size);
 	}
 
-	/* Allow hardware batchbuffers unless told otherwise.
-	 */
+	/* Allow hardware batchbuffers unless told otherwise. */
 	dev_priv->allow_batchbuffer = 1;
 
 	ret = intel_parse_bios(dev);
 	if (ret)
 		DRM_INFO("failed to find VBIOS tables\n");
 
-	/* if we have > 1 VGA cards, then disable the radeon VGA resources */
+	/* If we have > 1 VGA cards, then we need to arbitrate access
+	 * to the common VGA resources.
+	 *
+	 * If we are a secondary display controller (!PCI_DISPLAY_CLASS_VGA),
+	 * then we do not take part in VGA arbitration and the
+	 * vga_client_register() fails with -ENODEV.
+	 */
 	ret = vga_client_register(dev->pdev, dev, NULL, i915_vga_set_decode);
-	if (ret)
+	if (ret && ret != -ENODEV)
 		goto cleanup_ringbuffer;
 
 	intel_register_dsm_handler();
 
 	ret = vga_switcheroo_register_client(dev->pdev,
 					     i915_switcheroo_set_state,
+					     NULL,
 					     i915_switcheroo_can_switch);
 	if (ret)
 		goto cleanup_vga_client;
@@ -1426,152 +1405,12 @@ static void i915_ironlake_get_mem_freq(s
 	}
 }
 
-struct v_table {
-	u8 vid;
-	unsigned long vd; /* in .1 mil */
-	unsigned long vm; /* in .1 mil */
-	u8 pvid;
-};
-
-static struct v_table v_table[] = {
-	{ 0, 16125, 15000, 0x7f, },
-	{ 1, 16000, 14875, 0x7e, },
-	{ 2, 15875, 14750, 0x7d, },
-	{ 3, 15750, 14625, 0x7c, },
-	{ 4, 15625, 14500, 0x7b, },
-	{ 5, 15500, 14375, 0x7a, },
-	{ 6, 15375, 14250, 0x79, },
-	{ 7, 15250, 14125, 0x78, },
-	{ 8, 15125, 14000, 0x77, },
-	{ 9, 15000, 13875, 0x76, },
-	{ 10, 14875, 13750, 0x75, },
-	{ 11, 14750, 13625, 0x74, },
-	{ 12, 14625, 13500, 0x73, },
-	{ 13, 14500, 13375, 0x72, },
-	{ 14, 14375, 13250, 0x71, },
-	{ 15, 14250, 13125, 0x70, },
-	{ 16, 14125, 13000, 0x6f, },
-	{ 17, 14000, 12875, 0x6e, },
-	{ 18, 13875, 12750, 0x6d, },
-	{ 19, 13750, 12625, 0x6c, },
-	{ 20, 13625, 12500, 0x6b, },
-	{ 21, 13500, 12375, 0x6a, },
-	{ 22, 13375, 12250, 0x69, },
-	{ 23, 13250, 12125, 0x68, },
-	{ 24, 13125, 12000, 0x67, },
-	{ 25, 13000, 11875, 0x66, },
-	{ 26, 12875, 11750, 0x65, },
-	{ 27, 12750, 11625, 0x64, },
-	{ 28, 12625, 11500, 0x63, },
-	{ 29, 12500, 11375, 0x62, },
-	{ 30, 12375, 11250, 0x61, },
-	{ 31, 12250, 11125, 0x60, },
-	{ 32, 12125, 11000, 0x5f, },
-	{ 33, 12000, 10875, 0x5e, },
-	{ 34, 11875, 10750, 0x5d, },
-	{ 35, 11750, 10625, 0x5c, },
-	{ 36, 11625, 10500, 0x5b, },
-	{ 37, 11500, 10375, 0x5a, },
-	{ 38, 11375, 10250, 0x59, },
-	{ 39, 11250, 10125, 0x58, },
-	{ 40, 11125, 10000, 0x57, },
-	{ 41, 11000, 9875, 0x56, },
-	{ 42, 10875, 9750, 0x55, },
-	{ 43, 10750, 9625, 0x54, },
-	{ 44, 10625, 9500, 0x53, },
-	{ 45, 10500, 9375, 0x52, },
-	{ 46, 10375, 9250, 0x51, },
-	{ 47, 10250, 9125, 0x50, },
-	{ 48, 10125, 9000, 0x4f, },
-	{ 49, 10000, 8875, 0x4e, },
-	{ 50, 9875, 8750, 0x4d, },
-	{ 51, 9750, 8625, 0x4c, },
-	{ 52, 9625, 8500, 0x4b, },
-	{ 53, 9500, 8375, 0x4a, },
-	{ 54, 9375, 8250, 0x49, },
-	{ 55, 9250, 8125, 0x48, },
-	{ 56, 9125, 8000, 0x47, },
-	{ 57, 9000, 7875, 0x46, },
-	{ 58, 8875, 7750, 0x45, },
-	{ 59, 8750, 7625, 0x44, },
-	{ 60, 8625, 7500, 0x43, },
-	{ 61, 8500, 7375, 0x42, },
-	{ 62, 8375, 7250, 0x41, },
-	{ 63, 8250, 7125, 0x40, },
-	{ 64, 8125, 7000, 0x3f, },
-	{ 65, 8000, 6875, 0x3e, },
-	{ 66, 7875, 6750, 0x3d, },
-	{ 67, 7750, 6625, 0x3c, },
-	{ 68, 7625, 6500, 0x3b, },
-	{ 69, 7500, 6375, 0x3a, },
-	{ 70, 7375, 6250, 0x39, },
-	{ 71, 7250, 6125, 0x38, },
-	{ 72, 7125, 6000, 0x37, },
-	{ 73, 7000, 5875, 0x36, },
-	{ 74, 6875, 5750, 0x35, },
-	{ 75, 6750, 5625, 0x34, },
-	{ 76, 6625, 5500, 0x33, },
-	{ 77, 6500, 5375, 0x32, },
-	{ 78, 6375, 5250, 0x31, },
-	{ 79, 6250, 5125, 0x30, },
-	{ 80, 6125, 5000, 0x2f, },
-	{ 81, 6000, 4875, 0x2e, },
-	{ 82, 5875, 4750, 0x2d, },
-	{ 83, 5750, 4625, 0x2c, },
-	{ 84, 5625, 4500, 0x2b, },
-	{ 85, 5500, 4375, 0x2a, },
-	{ 86, 5375, 4250, 0x29, },
-	{ 87, 5250, 4125, 0x28, },
-	{ 88, 5125, 4000, 0x27, },
-	{ 89, 5000, 3875, 0x26, },
-	{ 90, 4875, 3750, 0x25, },
-	{ 91, 4750, 3625, 0x24, },
-	{ 92, 4625, 3500, 0x23, },
-	{ 93, 4500, 3375, 0x22, },
-	{ 94, 4375, 3250, 0x21, },
-	{ 95, 4250, 3125, 0x20, },
-	{ 96, 4125, 3000, 0x1f, },
-	{ 97, 4125, 3000, 0x1e, },
-	{ 98, 4125, 3000, 0x1d, },
-	{ 99, 4125, 3000, 0x1c, },
-	{ 100, 4125, 3000, 0x1b, },
-	{ 101, 4125, 3000, 0x1a, },
-	{ 102, 4125, 3000, 0x19, },
-	{ 103, 4125, 3000, 0x18, },
-	{ 104, 4125, 3000, 0x17, },
-	{ 105, 4125, 3000, 0x16, },
-	{ 106, 4125, 3000, 0x15, },
-	{ 107, 4125, 3000, 0x14, },
-	{ 108, 4125, 3000, 0x13, },
-	{ 109, 4125, 3000, 0x12, },
-	{ 110, 4125, 3000, 0x11, },
-	{ 111, 4125, 3000, 0x10, },
-	{ 112, 4125, 3000, 0x0f, },
-	{ 113, 4125, 3000, 0x0e, },
-	{ 114, 4125, 3000, 0x0d, },
-	{ 115, 4125, 3000, 0x0c, },
-	{ 116, 4125, 3000, 0x0b, },
-	{ 117, 4125, 3000, 0x0a, },
-	{ 118, 4125, 3000, 0x09, },
-	{ 119, 4125, 3000, 0x08, },
-	{ 120, 1125, 0, 0x07, },
-	{ 121, 1000, 0, 0x06, },
-	{ 122, 875, 0, 0x05, },
-	{ 123, 750, 0, 0x04, },
-	{ 124, 625, 0, 0x03, },
-	{ 125, 500, 0, 0x02, },
-	{ 126, 375, 0, 0x01, },
-	{ 127, 0, 0, 0x00, },
-};
-
-struct cparams {
-	int i;
-	int t;
-	int m;
-	int c;
-};
-
-static struct cparams cparams[] = {
+static const struct cparams {
+	u16 i;
+	u16 t;
+	u16 m;
+	u16 c;
+} cparams[] = {
 	{ 1, 1333, 301, 28664 },
 	{ 1, 1066, 294, 24460 },
 	{ 1, 800, 294, 25192 },
@@ -1637,21 +1476,145 @@ unsigned long i915_mch_val(struct drm_i9
 	return ((m * x) / 127) - b;
 }
 
-static unsigned long pvid_to_extvid(struct drm_i915_private *dev_priv, u8 pxvid)
+static u16 pvid_to_extvid(struct drm_i915_private *dev_priv, u8 pxvid)
 {
-	unsigned long val = 0;
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(v_table); i++) {
-		if (v_table[i].pvid == pxvid) {
-			if (IS_MOBILE(dev_priv->dev))
-				val = v_table[i].vm;
-			else
-				val = v_table[i].vd;
-		}
-	}
-
-	return val;
+	static const struct v_table {
+		u16 vd; /* in .1 mil */
+		u16 vm; /* in .1 mil */
+	} v_table[] = {
+		{ 0, 0, },
+		{ 375, 0, },
+		{ 500, 0, },
+		{ 625, 0, },
+		{ 750, 0, },
+		{ 875, 0, },
+		{ 1000, 0, },
+		{ 1125, 0, },
+		{ 4125, 3000, },
+		{ 4125, 3000, },
+		{ 4125, 3000, },
+		{ 4125, 3000, },
+		{ 4125, 3000, },
+		{ 4125, 3000, },
+		{ 4125, 3000, },
+		{ 4125, 3000, },
+		{ 4125, 3000, },
+		{ 4125, 3000, },
+		{ 4125, 3000, },
+		{ 4125, 3000, },
+		{ 4125, 3000, },
+		{ 4125, 3000, },
+		{ 4125, 3000, },
+		{ 4125, 3000, },
+		{ 4125, 3000, },
+		{ 4125, 3000, },
+		{ 4125, 3000, },
+		{ 4125, 3000, },
+		{ 4125, 3000, },
+		{ 4125, 3000, },
+		{ 4125, 3000, },
+		{ 4125, 3000, },
+		{ 4250, 3125, },
+		{ 4375, 3250, },
+		{ 4500, 3375, },
+		{ 4625, 3500, },
+		{ 4750, 3625, },
+		{ 4875, 3750, },
+		{ 5000, 3875, },
+		{ 5125, 4000, },
+		{ 5250, 4125, },
+		{ 5375, 4250, },
+		{ 5500, 4375, },
+		{ 5625, 4500, },
+		{ 5750, 4625, },
+		{ 5875, 4750, },
+		{ 6000, 4875, },
+		{ 6125, 5000, },
+		{ 6250, 5125, },
+		{ 6375, 5250, },
+		{ 6500, 5375, },
+		{ 6625, 5500, },
+		{ 6750, 5625, },
+		{ 6875, 5750, },
+		{ 7000, 5875, },
+		{ 7125, 6000, },
+		{ 7250, 6125, },
+		{ 7375, 6250, },
+		{ 7500, 6375, },
+		{ 7625, 6500, },
+		{ 7750, 6625, },
+		{ 7875, 6750, },
+		{ 8000, 6875, },
+		{ 8125, 7000, },
+		{ 8250, 7125, },
+		{ 8375, 7250, },
+		{ 8500, 7375, },
+		{ 8625, 7500, },
+		{ 8750, 7625, },
+		{ 8875, 7750, },
+		{ 9000, 7875, },
+		{ 9125, 8000, },
+		{ 9250, 8125, },
+		{ 9375, 8250, },
+		{ 9500, 8375, },
+		{ 9625, 8500, },
+		{ 9750, 8625, },
+		{ 9875, 8750, },
+		{ 10000, 8875, },
+		{ 10125, 9000, },
+		{ 10250, 9125, },
+		{ 10375, 9250, },
+		{ 10500, 9375, },
+		{ 10625, 9500, },
+		{ 10750, 9625, },
+		{ 10875, 9750, },
+		{ 11000, 9875, },
+		{ 11125, 10000, },
+		{ 11250, 10125, },
+		{ 11375, 10250, },
+		{ 11500, 10375, },
+		{ 11625, 10500, },
+		{ 11750, 10625, },
+		{ 11875, 10750, },
+		{ 12000, 10875, },
+		{ 12125, 11000, },
+		{ 12250, 11125, },
+		{ 12375, 11250, },
+		{ 12500, 11375, },
+		{ 12625, 11500, },
+		{ 12750, 11625, },
+		{ 12875, 11750, },
+		{ 13000, 11875, },
+		{ 13125, 12000, },
+		{ 13250, 12125, },
+		{ 13375, 12250, },
+		{ 13500, 12375, },
+		{ 13625, 12500, },
+		{ 13750, 12625, },
+		{ 13875, 12750, },
+		{ 14000, 12875, },
+		{ 14125, 13000, },
+		{ 14250, 13125, },
+		{ 14375, 13250, },
+		{ 14500, 13375, },
+		{ 14625, 13500, },
+		{ 14750, 13625, },
+		{ 14875, 13750, },
+		{ 15000, 13875, },
+		{ 15125, 14000, },
+		{ 15250, 14125, },
+		{ 15375, 14250, },
+		{ 15500, 14375, },
+		{ 15625, 14500, },
+		{ 15750, 14625, },
+		{ 15875, 14750, },
+		{ 16000, 14875, },
+		{ 16125, 15000, },
+	};
+	if (dev_priv->info->is_mobile)
+		return v_table[pxvid].vm;
+	else
+		return v_table[pxvid].vd;
 }
 
 void i915_update_gfx_val(struct drm_i915_private *dev_priv)
@@ -1905,9 +1868,9 @@ ips_ping_for_i915_load(void)
 int i915_driver_load(struct drm_device *dev, unsigned long flags)
 {
 	struct drm_i915_private *dev_priv;
-	resource_size_t base, size;
 	int ret = 0, mmio_bar;
-	uint32_t agp_size, prealloc_size;
+	uint32_t agp_size;
+
 	/* i915 has 4 more counters */
 	dev->counters += 4;
 	dev->types[6] = _DRM_STAT_IRQ;
@@ -1923,11 +1886,6 @@ int i915_driver_load(struct drm_device *
 	dev_priv->dev = dev;
 	dev_priv->info = (struct intel_device_info *) flags;
 
-	/* Add register map (needed for suspend/resume) */
-	mmio_bar = IS_GEN2(dev) ? 1 : 0;
-	base = pci_resource_start(dev->pdev, mmio_bar);
-	size = pci_resource_len(dev->pdev, mmio_bar);
-
 	if (i915_get_bridge_dev(dev)) {
 		ret = -EIO;
 		goto free_priv;
@@ -1937,16 +1895,36 @@ int i915_driver_load(struct drm_device *
 	if (IS_GEN2(dev))
 		dma_set_coherent_mask(&dev->pdev->dev, DMA_BIT_MASK(30));
 
-	dev_priv->regs = ioremap(base, size);
+	/* 965GM sometimes incorrectly writes to hardware status page (HWS)
+	 * using 32bit addressing, overwriting memory if HWS is located
+	 * above 4GB.
+	 *
+	 * The documentation also mentions an issue with undefined
+	 * behaviour if any general state is accessed within a page above 4GB,
+	 * which also needs to be handled carefully.
+	 */
+	if (IS_BROADWATER(dev) || IS_CRESTLINE(dev))
+		dma_set_coherent_mask(&dev->pdev->dev, DMA_BIT_MASK(32));
+
+	mmio_bar = IS_GEN2(dev) ? 1 : 0;
+	dev_priv->regs = pci_iomap(dev->pdev, mmio_bar, 0);
 	if (!dev_priv->regs) {
 		DRM_ERROR("failed to map registers\n");
 		ret = -EIO;
 		goto put_bridge;
 	}
 
+	dev_priv->mm.gtt = intel_gtt_get();
+	if (!dev_priv->mm.gtt) {
+		DRM_ERROR("Failed to initialize GTT\n");
+		ret = -ENODEV;
+		goto out_iomapfree;
+	}
+
+	agp_size = dev_priv->mm.gtt->gtt_mappable_entries << PAGE_SHIFT;
+
         dev_priv->mm.gtt_mapping =
-		io_mapping_create_wc(dev->agp->base,
-				     dev->agp->agp_info.aper_size * 1024*1024);
+		io_mapping_create_wc(dev->agp->base, agp_size);
 	if (dev_priv->mm.gtt_mapping == NULL) {
 		ret = -EIO;
 		goto out_rmmap;
@@ -1958,24 +1936,13 @@ int i915_driver_load(struct drm_device *
 	 * MTRR if present.  Even if a UC MTRR isn't present.
 	 */
 	dev_priv->mm.gtt_mtrr = mtrr_add(dev->agp->base,
-					 dev->agp->agp_info.aper_size *
-					 1024 * 1024,
+					 agp_size,
 					 MTRR_TYPE_WRCOMB, 1);
 	if (dev_priv->mm.gtt_mtrr < 0) {
 		DRM_INFO("MTRR allocation failed.  Graphics "
 			 "performance may suffer.\n");
 	}
 
-	dev_priv->mm.gtt = intel_gtt_get();
-	if (!dev_priv->mm.gtt) {
-		DRM_ERROR("Failed to initialize GTT\n");
-		ret = -ENODEV;
-		goto out_iomapfree;
-	}
-
-	prealloc_size = dev_priv->mm.gtt->gtt_stolen_entries << PAGE_SHIFT;
-	agp_size = dev_priv->mm.gtt->gtt_mappable_entries << PAGE_SHIFT;
-
 	/* The i915 workqueue is primarily used for batched retirement of
 	 * requests (and thus managing bo) once the task has been completed
 	 * by the GPU. i915_gem_retire_requests() is called directly when we
@@ -1983,7 +1950,7 @@ int i915_driver_load(struct drm_device *
 	 * bo.
 	 *
 	 * It is also used for periodic low-priority events, such as
-	 * idle-timers and hangcheck.
+	 * idle-timers and recording error state.
 	 *
 	 * All tasks on the workqueue are expected to acquire the dev mutex
 	 * so there is no point in running more than one instance of the
@@ -2001,22 +1968,6 @@ int i915_driver_load(struct drm_device *
 	/* enable GEM by default */
 	dev_priv->has_gem = 1;
 
-	if (prealloc_size > agp_size * 3 / 4) {
-		DRM_ERROR("Detected broken video BIOS with %d/%dkB of video "
-			  "memory stolen.\n",
-			  prealloc_size / 1024, agp_size / 1024);
-		DRM_ERROR("Disabling GEM. (try reducing stolen memory or "
-			  "updating the BIOS to fix).\n");
-		dev_priv->has_gem = 0;
-	}
-
-	if (dev_priv->has_gem == 0 &&
-	    drm_core_check_feature(dev, DRIVER_MODESET)) {
-		DRM_ERROR("kernel modesetting requires GEM, disabling driver.\n");
-		ret = -ENODEV;
-		goto out_iomapfree;
-	}
-
 	dev->driver->get_vblank_counter = i915_get_vblank_counter;
 	dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */
 	if (IS_G4X(dev) || IS_GEN5(dev) || IS_GEN6(dev)) {
@@ -2037,8 +1988,8 @@ int i915_driver_load(struct drm_device *
 	/* Init HWS */
 	if (!I915_NEED_GFX_HWS(dev)) {
 		ret = i915_init_phys_hws(dev);
-		if (ret != 0)
-			goto out_workqueue_free;
+		if (ret)
+			goto out_gem_unload;
 	}
 
 	if (IS_PINEVIEW(dev))
@@ -2060,16 +2011,13 @@ int i915_driver_load(struct drm_device *
 	if (!IS_I945G(dev) && !IS_I945GM(dev))
 		pci_enable_msi(dev->pdev);
 
-	spin_lock_init(&dev_priv->user_irq_lock);
+	spin_lock_init(&dev_priv->irq_lock);
 	spin_lock_init(&dev_priv->error_lock);
 	dev_priv->trace_irq_seqno = 0;
 
 	ret = drm_vblank_init(dev, I915_NUM_PIPE);
-
-	if (ret) {
-		(void) i915_driver_unload(dev);
-		return ret;
-	}
+	if (ret)
+		goto out_gem_unload;
 
 	/* Start out suspended */
 	dev_priv->mm.suspended = 1;
@@ -2077,10 +2025,10 @@ int i915_driver_load(struct drm_device *
 	intel_detect_pch(dev);
 
 	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
-		ret = i915_load_modeset_init(dev, prealloc_size, agp_size);
+		ret = i915_load_modeset_init(dev);
 		if (ret < 0) {
 			DRM_ERROR("failed to init modeset\n");
-			goto out_workqueue_free;
+			goto out_gem_unload;
 		}
 	}
 
@@ -2100,12 +2048,17 @@ int i915_driver_load(struct drm_device *
 
 	return 0;
 
-out_workqueue_free:
+out_gem_unload:
+	if (dev->pdev->msi_enabled)
+		pci_disable_msi(dev->pdev);
+
+	intel_teardown_gmbus(dev);
+	intel_teardown_mchbar(dev);
 	destroy_workqueue(dev_priv->wq);
 out_iomapfree:
 	io_mapping_free(dev_priv->mm.gtt_mapping);
 out_rmmap:
-	iounmap(dev_priv->regs);
+	pci_iounmap(dev->pdev, dev_priv->regs);
 put_bridge:
 	pci_dev_put(dev_priv->bridge_dev);
 free_priv:
@@ -2122,6 +2075,9 @@ int i915_driver_unload(struct drm_device
 	i915_mch_dev = NULL;
 	spin_unlock(&mchdev_lock);
 
+	if (dev_priv->mm.inactive_shrinker.shrink)
+		unregister_shrinker(&dev_priv->mm.inactive_shrinker);
+
 	mutex_lock(&dev->struct_mutex);
 	ret = i915_gpu_idle(dev);
 	if (ret)
@@ -2179,7 +2135,7 @@ int i915_driver_unload(struct drm_device
 		mutex_unlock(&dev->struct_mutex);
 		if (I915_HAS_FBC(dev) && i915_powersave)
 			i915_cleanup_compression(dev);
-		drm_mm_takedown(&dev_priv->mm.vram);
+		drm_mm_takedown(&dev_priv->mm.stolen);
 
 		intel_cleanup_overlay(dev);
 
@@ -2188,7 +2144,7 @@ int i915_driver_unload(struct drm_device
 	}
 
 	if (dev_priv->regs != NULL)
-		iounmap(dev_priv->regs);
+		pci_iounmap(dev->pdev, dev_priv->regs);
 
 	intel_teardown_gmbus(dev);
 	intel_teardown_mchbar(dev);
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/i915/i915_drv.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/i915/i915_drv.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/i915/i915_drv.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/i915/i915_drv.c	2011-03-14 21:20:32.000000000 -0400
@@ -46,15 +46,27 @@ module_param_named(fbpercrtc, i915_fbper
 unsigned int i915_powersave = 1;
 module_param_named(powersave, i915_powersave, int, 0600);
 
+unsigned int i915_semaphores = 0;
+module_param_named(semaphores, i915_semaphores, int, 0600);
+
+unsigned int i915_enable_rc6 = 0;
+module_param_named(i915_enable_rc6, i915_enable_rc6, int, 0600);
+
 unsigned int i915_lvds_downclock = 0;
 module_param_named(lvds_downclock, i915_lvds_downclock, int, 0400);
 
+unsigned int i915_panel_use_ssc = 1;
+module_param_named(lvds_use_ssc, i915_panel_use_ssc, int, 0600);
+
+bool i915_try_reset = true;
+module_param_named(reset, i915_try_reset, bool, 0600);
+
 static struct drm_driver driver;
 extern int intel_agp_enabled;
 
 #define INTEL_VGA_DEVICE(id, info) {		\
 	.class = PCI_CLASS_DISPLAY_VGA << 8,	\
-	.class_mask = 0xffff00,			\
+	.class_mask = 0xff0000,			\
 	.vendor = 0x8086,			\
 	.device = id,				\
 	.subvendor = PCI_ANY_ID,		\
@@ -111,7 +123,7 @@ static const struct intel_device_info in
 
 static const struct intel_device_info intel_i965gm_info = {
 	.gen = 4, .is_crestline = 1,
-	.is_mobile = 1, .has_fbc = 1, .has_rc6 = 1, .has_hotplug = 1,
+	.is_mobile = 1, .has_fbc = 1, .has_hotplug = 1,
 	.has_overlay = 1,
 	.supports_tv = 1,
 };
@@ -130,7 +142,7 @@ static const struct intel_device_info in
 
 static const struct intel_device_info intel_gm45_info = {
 	.gen = 4, .is_g4x = 1,
-	.is_mobile = 1, .need_gfx_hws = 1, .has_fbc = 1, .has_rc6 = 1,
+	.is_mobile = 1, .need_gfx_hws = 1, .has_fbc = 1,
 	.has_pipe_cxsr = 1, .has_hotplug = 1,
 	.supports_tv = 1,
 	.has_bsd_ring = 1,
@@ -150,7 +162,7 @@ static const struct intel_device_info in
 
 static const struct intel_device_info intel_ironlake_m_info = {
 	.gen = 5, .is_mobile = 1,
-	.need_gfx_hws = 1, .has_rc6 = 1, .has_hotplug = 1,
+	.need_gfx_hws = 1, .has_hotplug = 1,
 	.has_fbc = 0, /* disabled due to buggy hardware */
 	.has_bsd_ring = 1,
 };
@@ -165,6 +177,7 @@ static const struct intel_device_info in
 static const struct intel_device_info intel_sandybridge_m_info = {
 	.gen = 6, .is_mobile = 1,
 	.need_gfx_hws = 1, .has_hotplug = 1,
+	.has_fbc = 1,
 	.has_bsd_ring = 1,
 	.has_blt_ring = 1,
 };
@@ -244,10 +257,44 @@ void intel_detect_pch (struct drm_device
 	}
 }
 
+void __gen6_gt_force_wake_get(struct drm_i915_private *dev_priv)
+{
+	int count;
+
+	count = 0;
+	while (count++ < 50 && (I915_READ_NOTRACE(FORCEWAKE_ACK) & 1))
+		udelay(10);
+
+	I915_WRITE_NOTRACE(FORCEWAKE, 1);
+	POSTING_READ(FORCEWAKE);
+
+	count = 0;
+	while (count++ < 50 && (I915_READ_NOTRACE(FORCEWAKE_ACK) & 1) == 0)
+		udelay(10);
+}
+
+void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv)
+{
+	I915_WRITE_NOTRACE(FORCEWAKE, 0);
+	POSTING_READ(FORCEWAKE);
+}
+
+void __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv)
+{
+	int loop = 500;
+	u32 fifo = I915_READ_NOTRACE(GT_FIFO_FREE_ENTRIES);
+	while (fifo < 20 && loop--) {
+		udelay(10);
+		fifo = I915_READ_NOTRACE(GT_FIFO_FREE_ENTRIES);
+	}
+}
+
 static int i915_drm_freeze(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
+	drm_kms_helper_poll_disable(dev);
+
 	pci_save_state(dev->pdev);
 
 	/* If KMS is active, we do the leavevt stuff here */
@@ -284,7 +331,9 @@ int i915_suspend(struct drm_device *dev,
 	if (state.event == PM_EVENT_PRETHAW)
 		return 0;
 
-	drm_kms_helper_poll_disable(dev);
+
+	if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)
+		return 0;
 
 	error = i915_drm_freeze(dev);
 	if (error)
@@ -304,6 +353,12 @@ static int i915_drm_thaw(struct drm_devi
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	int error = 0;
 
+	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
+		mutex_lock(&dev->struct_mutex);
+		i915_gem_restore_gtt_mappings(dev);
+		mutex_unlock(&dev->struct_mutex);
+	}
+
 	i915_restore_state(dev);
 	intel_opregion_setup(dev);
 
@@ -315,10 +370,14 @@ static int i915_drm_thaw(struct drm_devi
 		error = i915_gem_init_ringbuffer(dev);
 		mutex_unlock(&dev->struct_mutex);
 
+		drm_mode_config_reset(dev);
 		drm_irq_install(dev);
 
 		/* Resume the modeset for every activated CRTC */
 		drm_helper_resume_force_mode(dev);
+
+		if (IS_IRONLAKE_M(dev))
+			ironlake_enable_rc6(dev);
 	}
 
 	intel_opregion_init(dev);
@@ -332,6 +391,9 @@ int i915_resume(struct drm_device *dev)
 {
 	int ret;
 
+	if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)
+		return 0;
+
 	if (pci_enable_device(dev->pdev))
 		return -EIO;
 
@@ -405,6 +467,14 @@ static int ironlake_do_reset(struct drm_
 	return wait_for(I915_READ(MCHBAR_MIRROR_BASE + ILK_GDSR) & 0x1, 500);
 }
 
+static int gen6_do_reset(struct drm_device *dev, u8 flags)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	I915_WRITE(GEN6_GDRST, GEN6_GRDOM_FULL);
+	return wait_for((I915_READ(GEN6_GDRST) & GEN6_GRDOM_FULL) == 0, 500);
+}
+
 /**
  * i965_reset - reset chip after a hang
  * @dev: drm device to reset
@@ -431,7 +501,11 @@ int i915_reset(struct drm_device *dev, u
 	bool need_display = true;
 	int ret;
 
-	mutex_lock(&dev->struct_mutex);
+	if (!i915_try_reset)
+		return 0;
+
+	if (!mutex_trylock(&dev->struct_mutex))
+		return -EBUSY;
 
 	i915_gem_reset(dev);
 
@@ -439,6 +513,9 @@ int i915_reset(struct drm_device *dev, u
 	if (get_seconds() - dev_priv->last_gpu_reset < 5) {
 		DRM_ERROR("GPU hanging too fast, declaring wedged!\n");
 	} else switch (INTEL_INFO(dev)->gen) {
+	case 6:
+		ret = gen6_do_reset(dev, flags);
+		break;
 	case 5:
 		ret = ironlake_do_reset(dev, flags);
 		break;
@@ -472,11 +549,17 @@ int i915_reset(struct drm_device *dev, u
 	 */
 	if (drm_core_check_feature(dev, DRIVER_MODESET) ||
 			!dev_priv->mm.suspended) {
-		struct intel_ring_buffer *ring = &dev_priv->render_ring;
 		dev_priv->mm.suspended = 0;
-		ring->init(dev, ring);
+
+		dev_priv->ring[RCS].init(&dev_priv->ring[RCS]);
+		if (HAS_BSD(dev))
+		    dev_priv->ring[VCS].init(&dev_priv->ring[VCS]);
+		if (HAS_BLT(dev))
+		    dev_priv->ring[BCS].init(&dev_priv->ring[BCS]);
+
 		mutex_unlock(&dev->struct_mutex);
 		drm_irq_uninstall(dev);
+		drm_mode_config_reset(dev);
 		drm_irq_install(dev);
 		mutex_lock(&dev->struct_mutex);
 	}
@@ -501,6 +584,14 @@ int i915_reset(struct drm_device *dev, u
 static int __devinit
 i915_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
+	/* Only bind to function 0 of the device. Early generations
+	 * used function 1 as a placeholder for multi-head. This causes
+	 * us confusion instead, especially on the systems where both
+	 * functions have the same PCI-ID!
+	 */
+	if (PCI_FUNC(pdev->devfn))
+		return -ENODEV;
+
 	return drm_get_pci_dev(pdev, ent, &driver);
 }
 
@@ -523,6 +614,9 @@ static int i915_pm_suspend(struct device
 		return -ENODEV;
 	}
 
+	if (drm_dev->switch_power_state == DRM_SWITCH_POWER_OFF)
+		return 0;
+
 	error = i915_drm_freeze(drm_dev);
 	if (error)
 		return error;
@@ -606,6 +700,8 @@ static struct drm_driver driver = {
 	.device_is_agp = i915_driver_device_is_agp,
 	.enable_vblank = i915_enable_vblank,
 	.disable_vblank = i915_disable_vblank,
+	.get_vblank_timestamp = i915_get_vblank_timestamp,
+	.get_scanout_position = i915_get_crtc_scanoutpos,
 	.irq_preinstall = i915_driver_irq_preinstall,
 	.irq_postinstall = i915_driver_irq_postinstall,
 	.irq_uninstall = i915_driver_irq_uninstall,
@@ -661,8 +757,6 @@ static int __init i915_init(void)
 
 	driver.num_ioctls = i915_max_ioctl;
 
-	i915_gem_shrinker_init();
-
 	/*
 	 * If CONFIG_DRM_I915_KMS is set, default to KMS unless
 	 * explicitly disabled with the module pararmeter.
@@ -684,17 +778,14 @@ static int __init i915_init(void)
 		driver.driver_features &= ~DRIVER_MODESET;
 #endif
 
-	if (!(driver.driver_features & DRIVER_MODESET)) {
-		driver.suspend = i915_suspend;
-		driver.resume = i915_resume;
-	}
+	if (!(driver.driver_features & DRIVER_MODESET))
+		driver.get_vblank_timestamp = NULL;
 
 	return drm_init(&driver);
 }
 
 static void __exit i915_exit(void)
 {
-	i915_gem_shrinker_exit();
 	drm_exit(&driver);
 }
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/i915/i915_drv.h linux-libre-2.6.38-gnu1/drivers/gpu/drm/i915/i915_drv.h
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/i915/i915_drv.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/i915/i915_drv.h	2011-03-14 21:20:32.000000000 -0400
@@ -89,7 +89,7 @@ struct drm_i915_gem_phys_object {
 	int id;
 	struct page **page_list;
 	drm_dma_handle_t *handle;
-	struct drm_gem_object *cur_obj;
+	struct drm_i915_gem_object *cur_obj;
 };
 
 struct mem_block {
@@ -124,9 +124,9 @@ struct drm_i915_master_private {
 #define I915_FENCE_REG_NONE -1
 
 struct drm_i915_fence_reg {
-	struct drm_gem_object *obj;
 	struct list_head lru_list;
-	bool gpu;
+	struct drm_i915_gem_object *obj;
+	uint32_t setup_seqno;
 };
 
 struct sdvo_device_mapping {
@@ -139,6 +139,8 @@ struct sdvo_device_mapping {
 	u8 ddc_pin;
 };
 
+struct intel_display_error_state;
+
 struct drm_i915_error_state {
 	u32 eir;
 	u32 pgtbl_er;
@@ -148,32 +150,47 @@ struct drm_i915_error_state {
 	u32 ipehr;
 	u32 instdone;
 	u32 acthd;
+	u32 error; /* gen6+ */
+	u32 bcs_acthd; /* gen6+ blt engine */
+	u32 bcs_ipehr;
+	u32 bcs_ipeir;
+	u32 bcs_instdone;
+	u32 bcs_seqno;
+	u32 vcs_acthd; /* gen6+ bsd engine */
+	u32 vcs_ipehr;
+	u32 vcs_ipeir;
+	u32 vcs_instdone;
+	u32 vcs_seqno;
 	u32 instpm;
 	u32 instps;
 	u32 instdone1;
 	u32 seqno;
 	u64 bbaddr;
+	u64 fence[16];
 	struct timeval time;
 	struct drm_i915_error_object {
 		int page_count;
 		u32 gtt_offset;
 		u32 *pages[0];
-	} *ringbuffer, *batchbuffer[2];
+	} *ringbuffer, *batchbuffer[I915_NUM_RINGS];
 	struct drm_i915_error_buffer {
-		size_t size;
+		u32 size;
 		u32 name;
 		u32 seqno;
 		u32 gtt_offset;
 		u32 read_domains;
 		u32 write_domain;
-		u32 fence_reg;
+		s32 fence_reg:5;
 		s32 pinned:2;
 		u32 tiling:2;
 		u32 dirty:1;
 		u32 purgeable:1;
-	} *active_bo;
-	u32 active_bo_count;
+		u32 ring:4;
+		u32 agp_type:1;
+	} *active_bo, *pinned_bo;
+	u32 active_bo_count, pinned_bo_count;
 	struct intel_overlay_error_state *overlay;
+	struct intel_display_error_state *display;
 };
 
 struct drm_i915_display_funcs {
@@ -207,7 +224,6 @@ struct intel_device_info {
 	u8 is_broadwater : 1;
 	u8 is_crestline : 1;
 	u8 has_fbc : 1;
-	u8 has_rc6 : 1;
 	u8 has_pipe_cxsr : 1;
 	u8 has_hotplug : 1;
 	u8 cursor_needs_physical : 1;
@@ -243,6 +259,7 @@ typedef struct drm_i915_private {
 	const struct intel_device_info *info;
 
 	int has_gem;
+	int relative_constants_mode;
 
 	void __iomem *regs;
 
@@ -253,20 +270,15 @@ typedef struct drm_i915_private {
 	} *gmbus;
 
 	struct pci_dev *bridge_dev;
-	struct intel_ring_buffer render_ring;
-	struct intel_ring_buffer bsd_ring;
-	struct intel_ring_buffer blt_ring;
+	struct intel_ring_buffer ring[I915_NUM_RINGS];
 	uint32_t next_seqno;
 
 	drm_dma_handle_t *status_page_dmah;
-	void *seqno_page;
 	dma_addr_t dma_status_page;
 	uint32_t counter;
-	unsigned int seqno_gfx_addr;
 	drm_local_map_t hws_map;
-	struct drm_gem_object *seqno_obj;
-	struct drm_gem_object *pwrctx;
-	struct drm_gem_object *renderctx;
+	struct drm_i915_gem_object *pwrctx;
+	struct drm_i915_gem_object *renderctx;
 
 	struct resource mch_res;
 
@@ -275,25 +287,17 @@ typedef struct drm_i915_private {
 	int front_offset;
 	int current_page;
 	int page_flipping;
-#define I915_DEBUG_READ (1<<0)
-#define I915_DEBUG_WRITE (1<<1)
-	unsigned long debug_flags;
 
-	wait_queue_head_t irq_queue;
 	atomic_t irq_received;
-	/** Protects user_irq_refcount and irq_mask_reg */
-	spinlock_t user_irq_lock;
 	u32 trace_irq_seqno;
+
+	/* protects the irq masks */
+	spinlock_t irq_lock;
 	/** Cached value of IMR to avoid reads in updating the bitfield */
-	u32 irq_mask_reg;
 	u32 pipestat[2];
-	/** splitted irq regs for graphics and display engine on Ironlake,
-	    irq_mask_reg is still used for display irq. */
-	u32 gt_irq_mask_reg;
-	u32 gt_irq_enable_reg;
-	u32 de_irq_enable_reg;
-	u32 pch_irq_mask_reg;
-	u32 pch_irq_enable_reg;
+	u32 irq_mask;
+	u32 gt_irq_mask;
+	u32 pch_irq_mask;
 
 	u32 hotplug_supported_mask;
 	struct work_struct hotplug_work;
@@ -306,7 +310,7 @@ typedef struct drm_i915_private {
 	int num_pipe;
 
 	/* For hangcheck timer */
-#define DRM_I915_HANGCHECK_PERIOD 250 /* in ms */
+#define DRM_I915_HANGCHECK_PERIOD 1500 /* in ms */
 	struct timer_list hangcheck_timer;
 	int hangcheck_count;
 	uint32_t last_acthd;
@@ -329,6 +333,7 @@ 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 */
@@ -530,23 +535,24 @@ typedef struct drm_i915_private {
 
 	struct {
 		/** Bridge to intel-gtt-ko */
-		struct intel_gtt *gtt;
+		const struct intel_gtt *gtt;
 		/** Memory allocator for GTT stolen memory */
-		struct drm_mm vram;
+		struct drm_mm stolen;
 		/** Memory allocator for GTT */
 		struct drm_mm gtt_space;
+		/** List of all objects in gtt_space. Used to restore gtt
+		 * mappings on resume */
+		struct list_head gtt_list;
+
+		/** Usable portion of the GTT for GEM */
+		unsigned long gtt_start;
+		unsigned long gtt_mappable_end;
+		unsigned long gtt_end;
 
 		struct io_mapping *gtt_mapping;
 		int gtt_mtrr;
 
-		/**
-		 * Membership on list of all loaded devices, used to evict
-		 * inactive buffers under memory pressure.
-		 *
-		 * Modifications should only be done whilst holding the
-		 * shrink_list_lock spinlock.
-		 */
-		struct list_head shrink_list;
+		struct shrinker inactive_shrinker;
 
 		/**
 		 * List of objects currently involved in rendering.
@@ -609,16 +615,6 @@ typedef struct drm_i915_private {
 		struct delayed_work retire_work;
 
 		/**
-		 * Waiting sequence number, if any
-		 */
-		uint32_t waiting_gem_seqno;
-
-		/**
-		 * Last seq seen at irq time
-		 */
-		uint32_t irq_gem_seqno;
-
-		/**
 		 * Flag if the X Server, and thus DRM, is not currently in
 		 * control of the device.
 		 *
@@ -645,16 +641,11 @@ typedef struct drm_i915_private {
 		/* storage for physical objects */
 		struct drm_i915_gem_phys_object *phys_objs[I915_MAX_PHYS_OBJECT];
 
-		uint32_t flush_rings;
-
 		/* accounting, useful for userland debugging */
-		size_t object_memory;
-		size_t pin_memory;
-		size_t gtt_memory;
 		size_t gtt_total;
+		size_t mappable_gtt_total;
+		size_t object_memory;
 		u32 object_count;
-		u32 pin_count;
-		u32 gtt_count;
 	} mm;
 	struct sdvo_device_mapping sdvo_mappings[2];
 	/* indicate whether the LVDS_BORDER should be enabled or not */
@@ -688,14 +679,14 @@ typedef struct drm_i915_private {
 	u8 fmax;
 	u8 fstart;
 
- 	u64 last_count1;
- 	unsigned long last_time1;
- 	u64 last_count2;
- 	struct timespec last_time2;
- 	unsigned long gfx_power;
- 	int c_m;
- 	int r_t;
- 	u8 corr;
+	u64 last_count1;
+	unsigned long last_time1;
+	u64 last_count2;
+	struct timespec last_time2;
+	unsigned long gfx_power;
+	int c_m;
+	int r_t;
+	u8 corr;
 	spinlock_t *mchdev_lock;
 
 	enum no_fbc_reason no_fbc_reason;
@@ -709,20 +700,20 @@ typedef struct drm_i915_private {
 	struct intel_fbdev *fbdev;
 } drm_i915_private_t;
 
-/** driver private structure attached to each drm_gem_object */
 struct drm_i915_gem_object {
 	struct drm_gem_object base;
 
 	/** Current space allocated to this object in the GTT, if any. */
 	struct drm_mm_node *gtt_space;
+	struct list_head gtt_list;
 
 	/** This object's place on the active/flushing/inactive lists */
 	struct list_head ring_list;
 	struct list_head mm_list;
 	/** This object's place on GPU write list */
 	struct list_head gpu_write_list;
-	/** This object's place on eviction list */
-	struct list_head evict_list;
+	/** This object's place in the batchbuffer or on the eviction list */
+	struct list_head exec_list;
 
 	/**
 	 * This is set if the object is on the active or flushing lists
@@ -738,6 +729,12 @@ struct drm_i915_gem_object {
 	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;
+
+	/**
 	 * Fence register bits (if any) for this object.  Will be set
 	 * as needed when mapped into the GTT.
 	 * Protected by dev->struct_mutex.
@@ -747,29 +744,15 @@ struct drm_i915_gem_object {
 	signed int fence_reg : 5;
 
 	/**
-	 * Used for checking the object doesn't appear more than once
-	 * in an execbuffer object list.
-	 */
-	unsigned int in_execbuffer : 1;
-
-	/**
 	 * Advice: are the backing pages purgeable?
 	 */
 	unsigned int madv : 2;
 
 	/**
-	 * Refcount for the pages array. With the current locking scheme, there
-	 * are at most two concurrent users: Binding a bo to the gtt and
-	 * pwrite/pread using physical addresses. So two bits for a maximum
-	 * of two users are enough.
-	 */
-	unsigned int pages_refcount : 2;
-#define DRM_I915_GEM_OBJECT_MAX_PAGES_REFCOUNT 0x3
-
-	/**
 	 * Current tiling mode for the object.
 	 */
 	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
@@ -783,28 +766,55 @@ struct drm_i915_gem_object {
 	unsigned int pin_count : 4;
 #define DRM_I915_GEM_OBJECT_MAX_PIN_COUNT 0xf
 
-	/** AGP memory structure for our GTT binding. */
-	DRM_AGP_MEM *agp_mem;
+	/**
+	 * Is the object at the current location in the gtt mappable and
+	 * fenceable? Used to avoid costly recalculations.
+	 */
+	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;
+
+	/*
+	 * Is the GPU currently using a fence to access this buffer,
+	 */
+	unsigned int pending_fenced_gpu_access:1;
+	unsigned int fenced_gpu_access:1;
 
 	struct page **pages;
 
 	/**
-	 * Current offset of the object in GTT space.
-	 *
-	 * This is the same as gtt_space->start
+	 * DMAR support
 	 */
-	uint32_t gtt_offset;
+	struct scatterlist *sg_list;
+	int num_sg;
 
-	/* Which ring is refering to is this object */
-	struct intel_ring_buffer *ring;
+	/**
+	 * Used for performing relocations during execbuffer insertion.
+	 */
+	struct hlist_node exec_node;
+	unsigned long exec_handle;
+	struct drm_i915_gem_exec_object2 *exec_entry;
 
 	/**
-	 * Fake offset for use by mmap(2)
+	 * Current offset of the object in GTT space.
+	 *
+	 * This is the same as gtt_space->start
 	 */
-	uint64_t mmap_offset;
+	uint32_t gtt_offset;
 
 	/** Breadcrumb of last rendering to the buffer. */
 	uint32_t last_rendering_seqno;
+	struct intel_ring_buffer *ring;
+
+	/** Breadcrumb of last fenced GPU access to the buffer. */
+	uint32_t last_fenced_seqno;
+	struct intel_ring_buffer *last_fenced_ring;
 
 	/** Current tiling stride for the object, if it's tiled. */
 	uint32_t stride;
@@ -880,11 +890,76 @@ enum intel_chip_family {
 	CHIP_I965 = 0x08,
 };
 
+#define INTEL_INFO(dev)	(((struct drm_i915_private *) (dev)->dev_private)->info)
+
+#define IS_I830(dev)		((dev)->pci_device == 0x3577)
+#define IS_845G(dev)		((dev)->pci_device == 0x2562)
+#define IS_I85X(dev)		(INTEL_INFO(dev)->is_i85x)
+#define IS_I865G(dev)		((dev)->pci_device == 0x2572)
+#define IS_I915G(dev)		(INTEL_INFO(dev)->is_i915g)
+#define IS_I915GM(dev)		((dev)->pci_device == 0x2592)
+#define IS_I945G(dev)		((dev)->pci_device == 0x2772)
+#define IS_I945GM(dev)		(INTEL_INFO(dev)->is_i945gm)
+#define IS_BROADWATER(dev)	(INTEL_INFO(dev)->is_broadwater)
+#define IS_CRESTLINE(dev)	(INTEL_INFO(dev)->is_crestline)
+#define IS_GM45(dev)		((dev)->pci_device == 0x2A42)
+#define IS_G4X(dev)		(INTEL_INFO(dev)->is_g4x)
+#define IS_PINEVIEW_G(dev)	((dev)->pci_device == 0xa001)
+#define IS_PINEVIEW_M(dev)	((dev)->pci_device == 0xa011)
+#define IS_PINEVIEW(dev)	(INTEL_INFO(dev)->is_pineview)
+#define IS_G33(dev)		(INTEL_INFO(dev)->is_g33)
+#define IS_IRONLAKE_D(dev)	((dev)->pci_device == 0x0042)
+#define IS_IRONLAKE_M(dev)	((dev)->pci_device == 0x0046)
+#define IS_MOBILE(dev)		(INTEL_INFO(dev)->is_mobile)
+
+#define IS_GEN2(dev)	(INTEL_INFO(dev)->gen == 2)
+#define IS_GEN3(dev)	(INTEL_INFO(dev)->gen == 3)
+#define IS_GEN4(dev)	(INTEL_INFO(dev)->gen == 4)
+#define IS_GEN5(dev)	(INTEL_INFO(dev)->gen == 5)
+#define IS_GEN6(dev)	(INTEL_INFO(dev)->gen == 6)
+
+#define HAS_BSD(dev)            (INTEL_INFO(dev)->has_bsd_ring)
+#define HAS_BLT(dev)            (INTEL_INFO(dev)->has_blt_ring)
+#define I915_NEED_GFX_HWS(dev)	(INTEL_INFO(dev)->need_gfx_hws)
+
+#define HAS_OVERLAY(dev)		(INTEL_INFO(dev)->has_overlay)
+#define OVERLAY_NEEDS_PHYSICAL(dev)	(INTEL_INFO(dev)->overlay_needs_physical)
+
+/* With the 945 and later, Y tiling got adjusted so that it was 32 128-byte
+ * rows, which changed the alignment requirements and fence programming.
+ */
+#define HAS_128_BYTE_Y_TILING(dev) (!IS_GEN2(dev) && !(IS_I915G(dev) || \
+						      IS_I915GM(dev)))
+#define SUPPORTS_DIGITAL_OUTPUTS(dev)	(!IS_GEN2(dev) && !IS_PINEVIEW(dev))
+#define SUPPORTS_INTEGRATED_HDMI(dev)	(IS_G4X(dev) || IS_GEN5(dev))
+#define SUPPORTS_INTEGRATED_DP(dev)	(IS_G4X(dev) || IS_GEN5(dev))
+#define SUPPORTS_EDP(dev)		(IS_IRONLAKE_M(dev))
+#define SUPPORTS_TV(dev)		(INTEL_INFO(dev)->supports_tv)
+#define I915_HAS_HOTPLUG(dev)		 (INTEL_INFO(dev)->has_hotplug)
+/* dsparb controlled by hw only */
+#define DSPARB_HWCONTROL(dev) (IS_G4X(dev) || IS_IRONLAKE(dev))
+
+#define HAS_FW_BLC(dev) (INTEL_INFO(dev)->gen > 2)
+#define HAS_PIPE_CXSR(dev) (INTEL_INFO(dev)->has_pipe_cxsr)
+#define I915_HAS_FBC(dev) (INTEL_INFO(dev)->has_fbc)
+
+#define HAS_PCH_SPLIT(dev) (IS_GEN5(dev) || IS_GEN6(dev))
+#define HAS_PIPE_CONTROL(dev) (IS_GEN5(dev) || IS_GEN6(dev))
+
+#define INTEL_PCH_TYPE(dev) (((struct drm_i915_private *)(dev)->dev_private)->pch_type)
+#define HAS_PCH_CPT(dev) (INTEL_PCH_TYPE(dev) == PCH_CPT)
+#define HAS_PCH_IBX(dev) (INTEL_PCH_TYPE(dev) == PCH_IBX)
+
+#include "i915_trace.h"
+
 extern struct drm_ioctl_desc i915_ioctls[];
 extern int i915_max_ioctl;
 extern unsigned int i915_fbpercrtc;
 extern unsigned int i915_powersave;
+extern unsigned int i915_semaphores;
 extern unsigned int i915_lvds_downclock;
+extern unsigned int i915_panel_use_ssc;
+extern unsigned int i915_enable_rc6;
 
 extern int i915_suspend(struct drm_device *dev, pm_message_t state);
 extern int i915_resume(struct drm_device *dev);
@@ -907,8 +982,8 @@ extern int i915_driver_device_is_agp(str
 extern long i915_compat_ioctl(struct file *filp, unsigned int cmd,
 			      unsigned long arg);
 extern int i915_emit_box(struct drm_device *dev,
-			 struct drm_clip_rect *boxes,
-			 int i, int DR1, int DR4);
+			 struct drm_clip_rect *box,
+			 int DR1, int DR4);
 extern int i915_reset(struct drm_device *dev, u8 flags);
 extern unsigned long i915_chipset_val(struct drm_i915_private *dev_priv);
 extern unsigned long i915_mch_val(struct drm_i915_private *dev_priv);
@@ -918,6 +993,7 @@ extern void i915_update_gfx_val(struct d
 
 /* i915_irq.c */
 void i915_hangcheck_elapsed(unsigned long data);
+void i915_handle_error(struct drm_device *dev, bool wedged);
 extern int i915_irq_emit(struct drm_device *dev, void *data,
 			 struct drm_file *file_priv);
 extern int i915_irq_wait(struct drm_device *dev, void *data,
@@ -939,12 +1015,6 @@ extern u32 i915_get_vblank_counter(struc
 extern u32 gm45_get_vblank_counter(struct drm_device *dev, int crtc);
 extern int i915_vblank_swap(struct drm_device *dev, void *data,
 			    struct drm_file *file_priv);
-extern void i915_enable_irq(drm_i915_private_t *dev_priv, u32 mask);
-extern void i915_disable_irq(drm_i915_private_t *dev_priv, u32 mask);
-extern void ironlake_enable_graphics_irq(drm_i915_private_t *dev_priv,
-		u32 mask);
-extern void ironlake_disable_graphics_irq(drm_i915_private_t *dev_priv,
-		u32 mask);
 
 void
 i915_enable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask);
@@ -953,6 +1023,13 @@ void
 i915_disable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask);
 
 void intel_enable_asle (struct drm_device *dev);
+int i915_get_vblank_timestamp(struct drm_device *dev, int crtc,
+			      int *max_error,
+			      struct timeval *vblank_time,
+			      unsigned flags);
+
+int i915_get_crtc_scanoutpos(struct drm_device *dev, int pipe,
+			     int *vpos, int *hpos);
 
 #ifdef CONFIG_DEBUG_FS
 extern void i915_destroy_error_state(struct drm_device *dev);
@@ -1017,15 +1094,28 @@ int i915_gem_get_aperture_ioctl(struct d
 				struct drm_file *file_priv);
 void i915_gem_load(struct drm_device *dev);
 int i915_gem_init_object(struct drm_gem_object *obj);
-struct drm_gem_object * i915_gem_alloc_object(struct drm_device *dev,
-					      size_t size);
+int __must_check i915_gem_flush_ring(struct drm_device *dev,
+				     struct intel_ring_buffer *ring,
+				     uint32_t invalidate_domains,
+				     uint32_t flush_domains);
+struct drm_i915_gem_object *i915_gem_alloc_object(struct drm_device *dev,
+						  size_t size);
 void i915_gem_free_object(struct drm_gem_object *obj);
-int i915_gem_object_pin(struct drm_gem_object *obj, uint32_t alignment);
-void i915_gem_object_unpin(struct drm_gem_object *obj);
-int i915_gem_object_unbind(struct drm_gem_object *obj);
-void i915_gem_release_mmap(struct drm_gem_object *obj);
+int __must_check i915_gem_object_pin(struct drm_i915_gem_object *obj,
+				     uint32_t alignment,
+				     bool map_and_fenceable);
+void i915_gem_object_unpin(struct drm_i915_gem_object *obj);
+int __must_check i915_gem_object_unbind(struct drm_i915_gem_object *obj);
+void i915_gem_release_mmap(struct drm_i915_gem_object *obj);
 void i915_gem_lastclose(struct drm_device *dev);
 
+int __must_check i915_mutex_lock_interruptible(struct drm_device *dev);
+int __must_check i915_gem_object_wait_rendering(struct drm_i915_gem_object *obj,
+						bool interruptible);
+void i915_gem_object_move_to_active(struct drm_i915_gem_object *obj,
+				    struct intel_ring_buffer *ring,
+				    u32 seqno);
+
 /**
  * Returns true if seq1 is later than seq2.
  */
@@ -1035,73 +1125,91 @@ i915_seqno_passed(uint32_t seq1, uint32_
 	return (int32_t)(seq1 - seq2) >= 0;
 }
 
-int i915_gem_object_get_fence_reg(struct drm_gem_object *obj,
-				  bool interruptible);
-int i915_gem_object_put_fence_reg(struct drm_gem_object *obj,
-				  bool interruptible);
+static inline u32
+i915_gem_next_request_seqno(struct drm_device *dev,
+			    struct intel_ring_buffer *ring)
+{
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	return ring->outstanding_lazy_request = dev_priv->next_seqno;
+}
+
+int __must_check i915_gem_object_get_fence(struct drm_i915_gem_object *obj,
+					   struct intel_ring_buffer *pipelined,
+					   bool interruptible);
+int __must_check i915_gem_object_put_fence(struct drm_i915_gem_object *obj);
+
 void i915_gem_retire_requests(struct drm_device *dev);
 void i915_gem_reset(struct drm_device *dev);
-void i915_gem_clflush_object(struct drm_gem_object *obj);
-int i915_gem_object_set_domain(struct drm_gem_object *obj,
-			       uint32_t read_domains,
-			       uint32_t write_domain);
-int i915_gem_object_flush_gpu(struct drm_i915_gem_object *obj,
-			      bool interruptible);
-int i915_gem_init_ringbuffer(struct drm_device *dev);
+void i915_gem_clflush_object(struct drm_i915_gem_object *obj);
+int __must_check i915_gem_object_set_domain(struct drm_i915_gem_object *obj,
+					    uint32_t read_domains,
+					    uint32_t write_domain);
+int __must_check i915_gem_object_flush_gpu(struct drm_i915_gem_object *obj,
+					   bool interruptible);
+int __must_check i915_gem_init_ringbuffer(struct drm_device *dev);
 void i915_gem_cleanup_ringbuffer(struct drm_device *dev);
-int i915_gem_do_init(struct drm_device *dev, unsigned long start,
-		     unsigned long end);
-int i915_gpu_idle(struct drm_device *dev);
-int i915_gem_idle(struct drm_device *dev);
-uint32_t i915_add_request(struct drm_device *dev,
-			  struct drm_file *file_priv,
-			  struct drm_i915_gem_request *request,
-			  struct intel_ring_buffer *ring);
-int i915_do_wait_request(struct drm_device *dev,
-			 uint32_t seqno,
-			 bool interruptible,
-			 struct intel_ring_buffer *ring);
+void i915_gem_do_init(struct drm_device *dev,
+		      unsigned long start,
+		      unsigned long mappable_end,
+		      unsigned long end);
+int __must_check i915_gpu_idle(struct drm_device *dev);
+int __must_check i915_gem_idle(struct drm_device *dev);
+int __must_check i915_add_request(struct drm_device *dev,
+				  struct drm_file *file_priv,
+				  struct drm_i915_gem_request *request,
+				  struct intel_ring_buffer *ring);
+int __must_check i915_do_wait_request(struct drm_device *dev,
+				      uint32_t seqno,
+				      bool interruptible,
+				      struct intel_ring_buffer *ring);
 int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf);
-int i915_gem_object_set_to_gtt_domain(struct drm_gem_object *obj,
-				      int write);
-int i915_gem_object_set_to_display_plane(struct drm_gem_object *obj,
-					 bool pipelined);
+int __must_check
+i915_gem_object_set_to_gtt_domain(struct drm_i915_gem_object *obj,
+				  bool write);
+int __must_check
+i915_gem_object_set_to_display_plane(struct drm_i915_gem_object *obj,
+				     struct intel_ring_buffer *pipelined);
 int i915_gem_attach_phys_object(struct drm_device *dev,
-				struct drm_gem_object *obj,
+				struct drm_i915_gem_object *obj,
 				int id,
 				int align);
 void i915_gem_detach_phys_object(struct drm_device *dev,
-				 struct drm_gem_object *obj);
+				 struct drm_i915_gem_object *obj);
 void i915_gem_free_all_phys_object(struct drm_device *dev);
-void i915_gem_release(struct drm_device * dev, struct drm_file *file_priv);
+void i915_gem_release(struct drm_device *dev, struct drm_file *file);
 
-void i915_gem_shrinker_init(void);
-void i915_gem_shrinker_exit(void);
+uint32_t
+i915_gem_get_unfenced_gtt_alignment(struct drm_i915_gem_object *obj);
+
+/* i915_gem_gtt.c */
+void i915_gem_restore_gtt_mappings(struct drm_device *dev);
+int __must_check i915_gem_gtt_bind_object(struct drm_i915_gem_object *obj);
+void i915_gem_gtt_unbind_object(struct drm_i915_gem_object *obj);
 
 /* i915_gem_evict.c */
-int i915_gem_evict_something(struct drm_device *dev, int min_size, unsigned alignment);
-int i915_gem_evict_everything(struct drm_device *dev);
-int i915_gem_evict_inactive(struct drm_device *dev);
+int __must_check i915_gem_evict_something(struct drm_device *dev, int min_size,
+					  unsigned alignment, bool mappable);
+int __must_check i915_gem_evict_everything(struct drm_device *dev,
+					   bool purgeable_only);
+int __must_check i915_gem_evict_inactive(struct drm_device *dev,
+					 bool purgeable_only);
 
 /* i915_gem_tiling.c */
 void i915_gem_detect_bit_6_swizzle(struct drm_device *dev);
-void i915_gem_object_do_bit_17_swizzle(struct drm_gem_object *obj);
-void i915_gem_object_save_bit_17_swizzle(struct drm_gem_object *obj);
-bool i915_tiling_ok(struct drm_device *dev, int stride, int size,
-		    int tiling_mode);
-bool i915_gem_object_fence_offset_ok(struct drm_gem_object *obj,
-				     int tiling_mode);
+void i915_gem_object_do_bit_17_swizzle(struct drm_i915_gem_object *obj);
+void i915_gem_object_save_bit_17_swizzle(struct drm_i915_gem_object *obj);
 
 /* i915_gem_debug.c */
-void i915_gem_dump_object(struct drm_gem_object *obj, int len,
+void i915_gem_dump_object(struct drm_i915_gem_object *obj, int len,
 			  const char *where, uint32_t mark);
 #if WATCH_LISTS
 int i915_verify_lists(struct drm_device *dev);
 #else
 #define i915_verify_lists(dev) 0
 #endif
-void i915_gem_object_check_coherency(struct drm_gem_object *obj, int handle);
-void i915_gem_dump_object(struct drm_gem_object *obj, int len,
+void i915_gem_object_check_coherency(struct drm_i915_gem_object *obj,
+				     int handle);
+void i915_gem_dump_object(struct drm_i915_gem_object *obj, int len,
 			  const char *where, uint32_t mark);
 
 /* i915_debugfs.c */
@@ -1163,6 +1271,8 @@ extern void intel_disable_fbc(struct drm
 extern void intel_enable_fbc(struct drm_crtc *crtc, unsigned long interval);
 extern bool intel_fbc_enabled(struct drm_device *dev);
 extern bool ironlake_set_drps(struct drm_device *dev, u8 val);
+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);
 
@@ -1170,78 +1280,129 @@ extern int intel_trans_dp_port_sel (stru
 #ifdef CONFIG_DEBUG_FS
 extern struct intel_overlay_error_state *intel_overlay_capture_error_state(struct drm_device *dev);
 extern void intel_overlay_print_error_state(struct seq_file *m, struct intel_overlay_error_state *error);
+
+extern struct intel_display_error_state *intel_display_capture_error_state(struct drm_device *dev);
+extern void intel_display_print_error_state(struct seq_file *m,
+					    struct drm_device *dev,
+					    struct intel_display_error_state *error);
 #endif
 
+#define LP_RING(d) (&((struct drm_i915_private *)(d))->ring[RCS])
+
+#define BEGIN_LP_RING(n) \
+	intel_ring_begin(LP_RING(dev_priv), (n))
+
+#define OUT_RING(x) \
+	intel_ring_emit(LP_RING(dev_priv), x)
+
+#define ADVANCE_LP_RING() \
+	intel_ring_advance(LP_RING(dev_priv))
+
 /**
  * Lock test for when it's just for synchronization of ring access.
  *
  * In that case, we don't need to do it when GEM is initialized as nobody else
  * has access to the ring.
  */
-#define RING_LOCK_TEST_WITH_RETURN(dev, file_priv) do {			\
-	if (((drm_i915_private_t *)dev->dev_private)->render_ring.gem_object \
-			== NULL)					\
-		LOCK_TEST_WITH_RETURN(dev, file_priv);			\
+#define RING_LOCK_TEST_WITH_RETURN(dev, file) do {			\
+	if (LP_RING(dev->dev_private)->obj == NULL)			\
+		LOCK_TEST_WITH_RETURN(dev, file);			\
 } while (0)
 
-static inline u32 i915_read(struct drm_i915_private *dev_priv, u32 reg)
-{
-	u32 val;
 
-	val = readl(dev_priv->regs + reg);
-	if (dev_priv->debug_flags & I915_DEBUG_READ)
-		printk(KERN_ERR "read 0x%08x from 0x%08x\n", val, reg);
-	return val;
+#define __i915_read(x, y) \
+static inline u##x i915_read##x(struct drm_i915_private *dev_priv, u32 reg) { \
+	u##x val = read##y(dev_priv->regs + reg); \
+	trace_i915_reg_rw('R', 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
 
-static inline void i915_write(struct drm_i915_private *dev_priv, u32 reg,
-			      u32 val)
-{
-	writel(val, dev_priv->regs + reg);
-	if (dev_priv->debug_flags & I915_DEBUG_WRITE)
-		printk(KERN_ERR "wrote 0x%08x to 0x%08x\n", val, reg);
+#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('W', reg, val, sizeof(val)); \
+	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
 
-#define I915_READ(reg)          i915_read(dev_priv, (reg))
-#define I915_WRITE(reg, val)    i915_write(dev_priv, (reg), (val))
-#define I915_READ16(reg)	readw(dev_priv->regs + (reg))
-#define I915_WRITE16(reg, val)	writel(val, dev_priv->regs + (reg))
-#define I915_READ8(reg)		readb(dev_priv->regs + (reg))
-#define I915_WRITE8(reg, val)	writeb(val, dev_priv->regs + (reg))
-#define I915_WRITE64(reg, val)	writeq(val, dev_priv->regs + (reg))
-#define I915_READ64(reg)	readq(dev_priv->regs + (reg))
-#define POSTING_READ(reg)	(void)I915_READ(reg)
-#define POSTING_READ16(reg)	(void)I915_READ16(reg)
+#define I915_READ8(reg)		i915_read8(dev_priv, (reg))
+#define I915_WRITE8(reg, val)	i915_write8(dev_priv, (reg), (val))
 
-#define I915_DEBUG_ENABLE_IO() (dev_priv->debug_flags |= I915_DEBUG_READ | \
-				I915_DEBUG_WRITE)
-#define I915_DEBUG_DISABLE_IO() (dev_priv->debug_flags &= ~(I915_DEBUG_READ | \
-							    I915_DEBUG_WRITE))
+#define I915_READ16(reg)	i915_read16(dev_priv, (reg))
+#define I915_WRITE16(reg, val)	i915_write16(dev_priv, (reg), (val))
+#define I915_READ16_NOTRACE(reg)	readw(dev_priv->regs + (reg))
+#define I915_WRITE16_NOTRACE(reg, val)	writew(val, dev_priv->regs + (reg))
 
-#define I915_VERBOSE 0
+#define I915_READ(reg)		i915_read32(dev_priv, (reg))
+#define I915_WRITE(reg, val)	i915_write32(dev_priv, (reg), (val))
+#define I915_READ_NOTRACE(reg)		readl(dev_priv->regs + (reg))
+#define I915_WRITE_NOTRACE(reg, val)	writel(val, dev_priv->regs + (reg))
 
-#define BEGIN_LP_RING(n)  do { \
-	drm_i915_private_t *dev_priv__ = dev->dev_private;                \
-	if (I915_VERBOSE)						\
-		DRM_DEBUG("   BEGIN_LP_RING %x\n", (int)(n));		\
-	intel_ring_begin(dev, &dev_priv__->render_ring, (n));		\
-} while (0)
+#define I915_WRITE64(reg, val)	i915_write64(dev_priv, (reg), (val))
+#define I915_READ64(reg)	i915_read64(dev_priv, (reg))
 
+#define POSTING_READ(reg)	(void)I915_READ_NOTRACE(reg)
+#define POSTING_READ16(reg)	(void)I915_READ16_NOTRACE(reg)
 
-#define OUT_RING(x) do {						\
-	drm_i915_private_t *dev_priv__ = dev->dev_private;		\
-	if (I915_VERBOSE)						\
-		DRM_DEBUG("   OUT_RING %x\n", (int)(x));		\
-	intel_ring_emit(dev, &dev_priv__->render_ring, x);		\
-} while (0)
 
-#define ADVANCE_LP_RING() do {						\
-	drm_i915_private_t *dev_priv__ = dev->dev_private;                \
-	if (I915_VERBOSE)						\
-		DRM_DEBUG("ADVANCE_LP_RING %x\n",			\
-				dev_priv__->render_ring.tail);		\
-	intel_ring_advance(dev, &dev_priv__->render_ring);		\
-} while(0)
+/* On SNB platform, before reading ring registers forcewake bit
+ * must be set to prevent GT core from power down and stale values being
+ * returned.
+ */
+void __gen6_gt_force_wake_get(struct drm_i915_private *dev_priv);
+void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv);
+void __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv);
+
+static inline u32 i915_gt_read(struct drm_i915_private *dev_priv, u32 reg)
+{
+	u32 val;
+
+	if (dev_priv->info->gen >= 6) {
+		__gen6_gt_force_wake_get(dev_priv);
+		val = I915_READ(reg);
+		__gen6_gt_force_wake_put(dev_priv);
+	} else
+		val = I915_READ(reg);
+
+	return val;
+}
+
+static inline void i915_gt_write(struct drm_i915_private *dev_priv,
+				u32 reg, u32 val)
+{
+	if (dev_priv->info->gen >= 6)
+		__gen6_gt_wait_for_fifo(dev_priv);
+	I915_WRITE(reg, val);
+}
+
+static inline void
+i915_write(struct drm_i915_private *dev_priv, u32 reg, u64 val, int len)
+{
+       /* Trace down the write operation before the real write */
+       trace_i915_reg_rw('W', reg, val, len);
+       switch (len) {
+       case 8:
+               writeq(val, dev_priv->regs + reg);
+               break;
+       case 4:
+               writel(val, dev_priv->regs + reg);
+               break;
+       case 2:
+               writew(val, dev_priv->regs + reg);
+               break;
+       case 1:
+               writeb(val, dev_priv->regs + reg);
+               break;
+       }
+}
 
 /**
  * Reads a dword out of the status page, which is written to from the command
@@ -1259,72 +1420,9 @@ static inline void i915_write(struct drm
  * The area from dword 0x20 to 0x3ff is available for driver usage.
  */
 #define READ_HWSP(dev_priv, reg)  (((volatile u32 *)\
-			(dev_priv->render_ring.status_page.page_addr))[reg])
+			(LP_RING(dev_priv)->status_page.page_addr))[reg])
 #define READ_BREADCRUMB(dev_priv) READ_HWSP(dev_priv, I915_BREADCRUMB_INDEX)
 #define I915_GEM_HWS_INDEX		0x20
 #define I915_BREADCRUMB_INDEX		0x21
 
-#define INTEL_INFO(dev)	(((struct drm_i915_private *) (dev)->dev_private)->info)
-
-#define IS_I830(dev)		((dev)->pci_device == 0x3577)
-#define IS_845G(dev)		((dev)->pci_device == 0x2562)
-#define IS_I85X(dev)		(INTEL_INFO(dev)->is_i85x)
-#define IS_I865G(dev)		((dev)->pci_device == 0x2572)
-#define IS_I915G(dev)		(INTEL_INFO(dev)->is_i915g)
-#define IS_I915GM(dev)		((dev)->pci_device == 0x2592)
-#define IS_I945G(dev)		((dev)->pci_device == 0x2772)
-#define IS_I945GM(dev)		(INTEL_INFO(dev)->is_i945gm)
-#define IS_BROADWATER(dev)	(INTEL_INFO(dev)->is_broadwater)
-#define IS_CRESTLINE(dev)	(INTEL_INFO(dev)->is_crestline)
-#define IS_GM45(dev)		((dev)->pci_device == 0x2A42)
-#define IS_G4X(dev)		(INTEL_INFO(dev)->is_g4x)
-#define IS_PINEVIEW_G(dev)	((dev)->pci_device == 0xa001)
-#define IS_PINEVIEW_M(dev)	((dev)->pci_device == 0xa011)
-#define IS_PINEVIEW(dev)	(INTEL_INFO(dev)->is_pineview)
-#define IS_G33(dev)		(INTEL_INFO(dev)->is_g33)
-#define IS_IRONLAKE_D(dev)	((dev)->pci_device == 0x0042)
-#define IS_IRONLAKE_M(dev)	((dev)->pci_device == 0x0046)
-#define IS_MOBILE(dev)		(INTEL_INFO(dev)->is_mobile)
-
-#define IS_GEN2(dev)	(INTEL_INFO(dev)->gen == 2)
-#define IS_GEN3(dev)	(INTEL_INFO(dev)->gen == 3)
-#define IS_GEN4(dev)	(INTEL_INFO(dev)->gen == 4)
-#define IS_GEN5(dev)	(INTEL_INFO(dev)->gen == 5)
-#define IS_GEN6(dev)	(INTEL_INFO(dev)->gen == 6)
-
-#define HAS_BSD(dev)            (INTEL_INFO(dev)->has_bsd_ring)
-#define HAS_BLT(dev)            (INTEL_INFO(dev)->has_blt_ring)
-#define I915_NEED_GFX_HWS(dev)	(INTEL_INFO(dev)->need_gfx_hws)
-
-#define HAS_OVERLAY(dev) 		(INTEL_INFO(dev)->has_overlay)
-#define OVERLAY_NEEDS_PHYSICAL(dev)	(INTEL_INFO(dev)->overlay_needs_physical)
-
-/* With the 945 and later, Y tiling got adjusted so that it was 32 128-byte
- * rows, which changed the alignment requirements and fence programming.
- */
-#define HAS_128_BYTE_Y_TILING(dev) (!IS_GEN2(dev) && !(IS_I915G(dev) || \
-						      IS_I915GM(dev)))
-#define SUPPORTS_DIGITAL_OUTPUTS(dev)	(!IS_GEN2(dev) && !IS_PINEVIEW(dev))
-#define SUPPORTS_INTEGRATED_HDMI(dev)	(IS_G4X(dev) || IS_GEN5(dev))
-#define SUPPORTS_INTEGRATED_DP(dev)	(IS_G4X(dev) || IS_GEN5(dev))
-#define SUPPORTS_EDP(dev)		(IS_IRONLAKE_M(dev))
-#define SUPPORTS_TV(dev)		(INTEL_INFO(dev)->supports_tv)
-#define I915_HAS_HOTPLUG(dev)		 (INTEL_INFO(dev)->has_hotplug)
-/* dsparb controlled by hw only */
-#define DSPARB_HWCONTROL(dev) (IS_G4X(dev) || IS_IRONLAKE(dev))
-
-#define HAS_FW_BLC(dev) (INTEL_INFO(dev)->gen > 2)
-#define HAS_PIPE_CXSR(dev) (INTEL_INFO(dev)->has_pipe_cxsr)
-#define I915_HAS_FBC(dev) (INTEL_INFO(dev)->has_fbc)
-#define I915_HAS_RC6(dev) (INTEL_INFO(dev)->has_rc6)
-
-#define HAS_PCH_SPLIT(dev) (IS_GEN5(dev) || IS_GEN6(dev))
-#define HAS_PIPE_CONTROL(dev) (IS_GEN5(dev) || IS_GEN6(dev))
-
-#define INTEL_PCH_TYPE(dev) (((struct drm_i915_private *)(dev)->dev_private)->pch_type)
-#define HAS_PCH_CPT(dev) (INTEL_PCH_TYPE(dev) == PCH_CPT)
-#define HAS_PCH_IBX(dev) (INTEL_PCH_TYPE(dev) == PCH_IBX)
-
-#define PRIMARY_RINGBUFFER_SIZE         (128*1024)
-
 #endif
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/i915/i915_gem.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/i915/i915_gem.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/i915/i915_gem.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/i915/i915_gem.c	2011-03-14 21:20:32.000000000 -0400
@@ -34,38 +34,31 @@
 #include <linux/slab.h>
 #include <linux/swap.h>
 #include <linux/pci.h>
-#include <linux/intel-gtt.h>
-
-static uint32_t i915_gem_get_gtt_alignment(struct drm_gem_object *obj);
 
-static int i915_gem_object_flush_gpu_write_domain(struct drm_gem_object *obj);
-static void i915_gem_object_flush_gtt_write_domain(struct drm_gem_object *obj);
-static void i915_gem_object_flush_cpu_write_domain(struct drm_gem_object *obj);
-static int i915_gem_object_set_to_cpu_domain(struct drm_gem_object *obj,
-					     int write);
-static int i915_gem_object_set_cpu_read_domain_range(struct drm_gem_object *obj,
-						     uint64_t offset,
-						     uint64_t size);
-static void i915_gem_object_set_to_full_cpu_read_domain(struct drm_gem_object *obj);
-static int i915_gem_object_wait_rendering(struct drm_gem_object *obj,
-					  bool interruptible);
-static int i915_gem_object_bind_to_gtt(struct drm_gem_object *obj,
-					   unsigned alignment);
-static void i915_gem_clear_fence_reg(struct drm_gem_object *obj);
-static int i915_gem_phys_pwrite(struct drm_device *dev, struct drm_gem_object *obj,
+static __must_check int i915_gem_object_flush_gpu_write_domain(struct drm_i915_gem_object *obj);
+static void i915_gem_object_flush_gtt_write_domain(struct drm_i915_gem_object *obj);
+static void i915_gem_object_flush_cpu_write_domain(struct drm_i915_gem_object *obj);
+static __must_check int i915_gem_object_set_to_cpu_domain(struct drm_i915_gem_object *obj,
+							  bool write);
+static __must_check int i915_gem_object_set_cpu_read_domain_range(struct drm_i915_gem_object *obj,
+								  uint64_t offset,
+								  uint64_t size);
+static void i915_gem_object_set_to_full_cpu_read_domain(struct drm_i915_gem_object *obj);
+static __must_check int i915_gem_object_bind_to_gtt(struct drm_i915_gem_object *obj,
+						    unsigned alignment,
+						    bool map_and_fenceable);
+static void i915_gem_clear_fence_reg(struct drm_device *dev,
+				     struct drm_i915_fence_reg *reg);
+static int i915_gem_phys_pwrite(struct drm_device *dev,
+				struct drm_i915_gem_object *obj,
 				struct drm_i915_gem_pwrite *args,
-				struct drm_file *file_priv);
-static void i915_gem_free_object_tail(struct drm_gem_object *obj);
-
-static int
-i915_gem_object_get_pages(struct drm_gem_object *obj,
-			  gfp_t gfpmask);
+				struct drm_file *file);
+static void i915_gem_free_object_tail(struct drm_i915_gem_object *obj);
 
-static void
-i915_gem_object_put_pages(struct drm_gem_object *obj);
+static int i915_gem_inactive_shrink(struct shrinker *shrinker,
+				    int nr_to_scan,
+				    gfp_t gfp_mask);
 
-static LIST_HEAD(shrink_list);
-static DEFINE_SPINLOCK(shrink_list_lock);
 
 /* some bookkeeping */
 static void i915_gem_info_add_obj(struct drm_i915_private *dev_priv,
@@ -82,34 +75,6 @@ static void i915_gem_info_remove_obj(str
 	dev_priv->mm.object_memory -= size;
 }
 
-static void i915_gem_info_add_gtt(struct drm_i915_private *dev_priv,
-				  size_t size)
-{
-	dev_priv->mm.gtt_count++;
-	dev_priv->mm.gtt_memory += size;
-}
-
-static void i915_gem_info_remove_gtt(struct drm_i915_private *dev_priv,
-				     size_t size)
-{
-	dev_priv->mm.gtt_count--;
-	dev_priv->mm.gtt_memory -= size;
-}
-
-static void i915_gem_info_add_pin(struct drm_i915_private *dev_priv,
-				  size_t size)
-{
-	dev_priv->mm.pin_count++;
-	dev_priv->mm.pin_memory += size;
-}
-
-static void i915_gem_info_remove_pin(struct drm_i915_private *dev_priv,
-				     size_t size)
-{
-	dev_priv->mm.pin_count--;
-	dev_priv->mm.pin_memory -= size;
-}
-
 int
 i915_gem_check_is_wedged(struct drm_device *dev)
 {
@@ -140,7 +105,7 @@ i915_gem_check_is_wedged(struct drm_devi
 	return -EIO;
 }
 
-static int i915_mutex_lock_interruptible(struct drm_device *dev)
+int i915_mutex_lock_interruptible(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	int ret;
@@ -163,75 +128,80 @@ static int i915_mutex_lock_interruptible
 }
 
 static inline bool
-i915_gem_object_is_inactive(struct drm_i915_gem_object *obj_priv)
+i915_gem_object_is_inactive(struct drm_i915_gem_object *obj)
 {
-	return obj_priv->gtt_space &&
-		!obj_priv->active &&
-		obj_priv->pin_count == 0;
+	return obj->gtt_space && !obj->active && obj->pin_count == 0;
 }
 
-int i915_gem_do_init(struct drm_device *dev,
-		     unsigned long start,
-		     unsigned long end)
+void i915_gem_do_init(struct drm_device *dev,
+		      unsigned long start,
+		      unsigned long mappable_end,
+		      unsigned long end)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
 
-	if (start >= end ||
-	    (start & (PAGE_SIZE - 1)) != 0 ||
-	    (end & (PAGE_SIZE - 1)) != 0) {
-		return -EINVAL;
-	}
-
-	drm_mm_init(&dev_priv->mm.gtt_space, start,
-		    end - start);
+	drm_mm_init(&dev_priv->mm.gtt_space, start, end - start);
 
+	dev_priv->mm.gtt_start = start;
+	dev_priv->mm.gtt_mappable_end = mappable_end;
+	dev_priv->mm.gtt_end = end;
 	dev_priv->mm.gtt_total = end - start;
+	dev_priv->mm.mappable_gtt_total = min(end, mappable_end) - start;
 
-	return 0;
+	/* Take over this portion of the GTT */
+	intel_gtt_clear_range(start / PAGE_SIZE, (end-start) / PAGE_SIZE);
 }
 
 int
 i915_gem_init_ioctl(struct drm_device *dev, void *data,
-		    struct drm_file *file_priv)
+		    struct drm_file *file)
 {
 	struct drm_i915_gem_init *args = data;
-	int ret;
+
+	if (args->gtt_start >= args->gtt_end ||
+	    (args->gtt_end | args->gtt_start) & (PAGE_SIZE - 1))
+		return -EINVAL;
 
 	mutex_lock(&dev->struct_mutex);
-	ret = i915_gem_do_init(dev, args->gtt_start, args->gtt_end);
+	i915_gem_do_init(dev, args->gtt_start, args->gtt_end, args->gtt_end);
 	mutex_unlock(&dev->struct_mutex);
 
-	return ret;
+	return 0;
 }
 
 int
 i915_gem_get_aperture_ioctl(struct drm_device *dev, void *data,
-			    struct drm_file *file_priv)
+			    struct drm_file *file)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct drm_i915_gem_get_aperture *args = data;
+	struct drm_i915_gem_object *obj;
+	size_t pinned;
 
 	if (!(dev->driver->driver_features & DRIVER_GEM))
 		return -ENODEV;
 
+	pinned = 0;
 	mutex_lock(&dev->struct_mutex);
-	args->aper_size = dev_priv->mm.gtt_total;
-	args->aper_available_size = args->aper_size - dev_priv->mm.pin_memory;
+	list_for_each_entry(obj, &dev_priv->mm.pinned_list, mm_list)
+		pinned += obj->gtt_space->size;
 	mutex_unlock(&dev->struct_mutex);
 
+	args->aper_size = dev_priv->mm.gtt_total;
+	args->aper_available_size = args->aper_size -pinned;
+
 	return 0;
 }
 
-
 /**
  * Creates a new mm object and returns a handle to it.
  */
 int
 i915_gem_create_ioctl(struct drm_device *dev, void *data,
-		      struct drm_file *file_priv)
+		      struct drm_file *file)
 {
 	struct drm_i915_gem_create *args = data;
-	struct drm_gem_object *obj;
+	struct drm_i915_gem_object *obj;
 	int ret;
 	u32 handle;
 
@@ -242,45 +212,28 @@ i915_gem_create_ioctl(struct drm_device
 	if (obj == NULL)
 		return -ENOMEM;
 
-	ret = drm_gem_handle_create(file_priv, obj, &handle);
+	ret = drm_gem_handle_create(file, &obj->base, &handle);
 	if (ret) {
-		drm_gem_object_release(obj);
-		i915_gem_info_remove_obj(dev->dev_private, obj->size);
+		drm_gem_object_release(&obj->base);
+		i915_gem_info_remove_obj(dev->dev_private, obj->base.size);
 		kfree(obj);
 		return ret;
 	}
 
 	/* drop reference from allocate - handle holds it now */
-	drm_gem_object_unreference(obj);
+	drm_gem_object_unreference(&obj->base);
 	trace_i915_gem_object_create(obj);
 
 	args->handle = handle;
 	return 0;
 }
 
-static inline int
-fast_shmem_read(struct page **pages,
-		loff_t page_base, int page_offset,
-		char __user *data,
-		int length)
-{
-	char *vaddr;
-	int ret;
-
-	vaddr = kmap_atomic(pages[page_base >> PAGE_SHIFT]);
-	ret = __copy_to_user_inatomic(data, vaddr + page_offset, length);
-	kunmap_atomic(vaddr);
-
-	return ret;
-}
-
-static int i915_gem_object_needs_bit17_swizzle(struct drm_gem_object *obj)
+static int i915_gem_object_needs_bit17_swizzle(struct drm_i915_gem_object *obj)
 {
-	drm_i915_private_t *dev_priv = obj->dev->dev_private;
-	struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
+	drm_i915_private_t *dev_priv = obj->base.dev->dev_private;
 
 	return dev_priv->mm.bit_6_swizzle_x == I915_BIT_6_SWIZZLE_9_10_17 &&
-		obj_priv->tiling_mode != I915_TILING_NONE;
+		obj->tiling_mode != I915_TILING_NONE;
 }
 
 static inline void
@@ -356,38 +309,51 @@ slow_shmem_bit17_copy(struct page *gpu_p
  * fault, it fails so we can fall back to i915_gem_shmem_pwrite_slow().
  */
 static int
-i915_gem_shmem_pread_fast(struct drm_device *dev, struct drm_gem_object *obj,
+i915_gem_shmem_pread_fast(struct drm_device *dev,
+			  struct drm_i915_gem_object *obj,
 			  struct drm_i915_gem_pread *args,
-			  struct drm_file *file_priv)
+			  struct drm_file *file)
 {
-	struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
+	struct address_space *mapping = obj->base.filp->f_path.dentry->d_inode->i_mapping;
 	ssize_t remain;
-	loff_t offset, page_base;
+	loff_t offset;
 	char __user *user_data;
 	int page_offset, page_length;
 
 	user_data = (char __user *) (uintptr_t) args->data_ptr;
 	remain = args->size;
 
-	obj_priv = to_intel_bo(obj);
 	offset = args->offset;
 
 	while (remain > 0) {
+		struct page *page;
+		char *vaddr;
+		int ret;
+
 		/* Operation in this page
 		 *
-		 * page_base = page offset within aperture
 		 * page_offset = offset within page
 		 * page_length = bytes to copy for this page
 		 */
-		page_base = (offset & ~(PAGE_SIZE-1));
 		page_offset = offset & (PAGE_SIZE-1);
 		page_length = remain;
 		if ((page_offset + remain) > PAGE_SIZE)
 			page_length = PAGE_SIZE - page_offset;
 
-		if (fast_shmem_read(obj_priv->pages,
-				    page_base, page_offset,
-				    user_data, page_length))
+		page = read_cache_page_gfp(mapping, offset >> PAGE_SHIFT,
+					   GFP_HIGHUSER | __GFP_RECLAIMABLE);
+		if (IS_ERR(page))
+			return PTR_ERR(page);
+
+		vaddr = kmap_atomic(page);
+		ret = __copy_to_user_inatomic(user_data,
+					      vaddr + page_offset,
+					      page_length);
+		kunmap_atomic(vaddr);
+
+		mark_page_accessed(page);
+		page_cache_release(page);
+		if (ret)
 			return -EFAULT;
 
 		remain -= page_length;
@@ -398,30 +364,6 @@ i915_gem_shmem_pread_fast(struct drm_dev
 	return 0;
 }
 
-static int
-i915_gem_object_get_pages_or_evict(struct drm_gem_object *obj)
-{
-	int ret;
-
-	ret = i915_gem_object_get_pages(obj, __GFP_NORETRY | __GFP_NOWARN);
-
-	/* If we've insufficient memory to map in the pages, attempt
-	 * to make some space by throwing out some old buffers.
-	 */
-	if (ret == -ENOMEM) {
-		struct drm_device *dev = obj->dev;
-
-		ret = i915_gem_evict_something(dev, obj->size,
-					       i915_gem_get_gtt_alignment(obj));
-		if (ret)
-			return ret;
-
-		ret = i915_gem_object_get_pages(obj, 0);
-	}
-
-	return ret;
-}
-
 /**
  * This is the fallback shmem pread path, which allocates temporary storage
  * in kernel space to copy_to_user into outside of the struct_mutex, so we
@@ -429,18 +371,19 @@ i915_gem_object_get_pages_or_evict(struc
  * and not take page faults.
  */
 static int
-i915_gem_shmem_pread_slow(struct drm_device *dev, struct drm_gem_object *obj,
+i915_gem_shmem_pread_slow(struct drm_device *dev,
+			  struct drm_i915_gem_object *obj,
 			  struct drm_i915_gem_pread *args,
-			  struct drm_file *file_priv)
+			  struct drm_file *file)
 {
-	struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
+	struct address_space *mapping = obj->base.filp->f_path.dentry->d_inode->i_mapping;
 	struct mm_struct *mm = current->mm;
 	struct page **user_pages;
 	ssize_t remain;
 	loff_t offset, pinned_pages, i;
 	loff_t first_data_page, last_data_page, num_pages;
-	int shmem_page_index, shmem_page_offset;
-	int data_page_index,  data_page_offset;
+	int shmem_page_offset;
+	int data_page_index, data_page_offset;
 	int page_length;
 	int ret;
 	uint64_t data_ptr = args->data_ptr;
@@ -479,19 +422,18 @@ i915_gem_shmem_pread_slow(struct drm_dev
 
 	do_bit17_swizzling = i915_gem_object_needs_bit17_swizzle(obj);
 
-	obj_priv = to_intel_bo(obj);
 	offset = args->offset;
 
 	while (remain > 0) {
+		struct page *page;
+
 		/* Operation in this page
 		 *
-		 * shmem_page_index = page number within shmem file
 		 * shmem_page_offset = offset within page in shmem file
 		 * data_page_index = page number in get_user_pages return
 		 * data_page_offset = offset with data_page_index page.
 		 * page_length = bytes to copy for this page
 		 */
-		shmem_page_index = offset / PAGE_SIZE;
 		shmem_page_offset = offset & ~PAGE_MASK;
 		data_page_index = data_ptr / PAGE_SIZE - first_data_page;
 		data_page_offset = data_ptr & ~PAGE_MASK;
@@ -502,8 +444,13 @@ i915_gem_shmem_pread_slow(struct drm_dev
 		if ((data_page_offset + page_length) > PAGE_SIZE)
 			page_length = PAGE_SIZE - data_page_offset;
 
+		page = read_cache_page_gfp(mapping, offset >> PAGE_SHIFT,
+					   GFP_HIGHUSER | __GFP_RECLAIMABLE);
+		if (IS_ERR(page))
+			return PTR_ERR(page);
+
 		if (do_bit17_swizzling) {
-			slow_shmem_bit17_copy(obj_priv->pages[shmem_page_index],
+			slow_shmem_bit17_copy(page,
 					      shmem_page_offset,
 					      user_pages[data_page_index],
 					      data_page_offset,
@@ -512,11 +459,14 @@ i915_gem_shmem_pread_slow(struct drm_dev
 		} else {
 			slow_shmem_copy(user_pages[data_page_index],
 					data_page_offset,
-					obj_priv->pages[shmem_page_index],
+					page,
 					shmem_page_offset,
 					page_length);
 		}
 
+		mark_page_accessed(page);
+		page_cache_release(page);
+
 		remain -= page_length;
 		data_ptr += page_length;
 		offset += page_length;
@@ -525,6 +475,7 @@ i915_gem_shmem_pread_slow(struct drm_dev
 out:
 	for (i = 0; i < pinned_pages; i++) {
 		SetPageDirty(user_pages[i]);
+		mark_page_accessed(user_pages[i]);
 		page_cache_release(user_pages[i]);
 	}
 	drm_free_large(user_pages);
@@ -539,11 +490,10 @@ out:
  */
 int
 i915_gem_pread_ioctl(struct drm_device *dev, void *data,
-		     struct drm_file *file_priv)
+		     struct drm_file *file)
 {
 	struct drm_i915_gem_pread *args = data;
-	struct drm_gem_object *obj;
-	struct drm_i915_gem_object *obj_priv;
+	struct drm_i915_gem_object *obj;
 	int ret = 0;
 
 	if (args->size == 0)
@@ -563,39 +513,33 @@ i915_gem_pread_ioctl(struct drm_device *
 	if (ret)
 		return ret;
 
-	obj = drm_gem_object_lookup(dev, file_priv, args->handle);
+	obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle));
 	if (obj == NULL) {
 		ret = -ENOENT;
 		goto unlock;
 	}
-	obj_priv = to_intel_bo(obj);
 
 	/* Bounds check source.  */
-	if (args->offset > obj->size || args->size > obj->size - args->offset) {
+	if (args->offset > obj->base.size ||
+	    args->size > obj->base.size - args->offset) {
 		ret = -EINVAL;
 		goto out;
 	}
 
-	ret = i915_gem_object_get_pages_or_evict(obj);
-	if (ret)
-		goto out;
-
 	ret = i915_gem_object_set_cpu_read_domain_range(obj,
 							args->offset,
 							args->size);
 	if (ret)
-		goto out_put;
+		goto out;
 
 	ret = -EFAULT;
 	if (!i915_gem_object_needs_bit17_swizzle(obj))
-		ret = i915_gem_shmem_pread_fast(dev, obj, args, file_priv);
+		ret = i915_gem_shmem_pread_fast(dev, obj, args, file);
 	if (ret == -EFAULT)
-		ret = i915_gem_shmem_pread_slow(dev, obj, args, file_priv);
+		ret = i915_gem_shmem_pread_slow(dev, obj, args, file);
 
-out_put:
-	i915_gem_object_put_pages(obj);
 out:
-	drm_gem_object_unreference(obj);
+	drm_gem_object_unreference(&obj->base);
 unlock:
 	mutex_unlock(&dev->struct_mutex);
 	return ret;
@@ -645,32 +589,16 @@ slow_kernel_write(struct io_mapping *map
 	io_mapping_unmap(dst_vaddr);
 }
 
-static inline int
-fast_shmem_write(struct page **pages,
-		 loff_t page_base, int page_offset,
-		 char __user *data,
-		 int length)
-{
-	char *vaddr;
-	int ret;
-
-	vaddr = kmap_atomic(pages[page_base >> PAGE_SHIFT]);
-	ret = __copy_from_user_inatomic(vaddr + page_offset, data, length);
-	kunmap_atomic(vaddr);
-
-	return ret;
-}
-
 /**
  * This is the fast pwrite path, where we copy the data directly from the
  * user into the GTT, uncached.
  */
 static int
-i915_gem_gtt_pwrite_fast(struct drm_device *dev, struct drm_gem_object *obj,
+i915_gem_gtt_pwrite_fast(struct drm_device *dev,
+			 struct drm_i915_gem_object *obj,
 			 struct drm_i915_gem_pwrite *args,
-			 struct drm_file *file_priv)
+			 struct drm_file *file)
 {
-	struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	ssize_t remain;
 	loff_t offset, page_base;
@@ -680,8 +608,7 @@ i915_gem_gtt_pwrite_fast(struct drm_devi
 	user_data = (char __user *) (uintptr_t) args->data_ptr;
 	remain = args->size;
 
-	obj_priv = to_intel_bo(obj);
-	offset = obj_priv->gtt_offset + args->offset;
+	offset = obj->gtt_offset + args->offset;
 
 	while (remain > 0) {
 		/* Operation in this page
@@ -721,11 +648,11 @@ i915_gem_gtt_pwrite_fast(struct drm_devi
  * than using i915_gem_gtt_pwrite_fast on a G45 (32-bit).
  */
 static int
-i915_gem_gtt_pwrite_slow(struct drm_device *dev, struct drm_gem_object *obj,
+i915_gem_gtt_pwrite_slow(struct drm_device *dev,
+			 struct drm_i915_gem_object *obj,
 			 struct drm_i915_gem_pwrite *args,
-			 struct drm_file *file_priv)
+			 struct drm_file *file)
 {
-	struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	ssize_t remain;
 	loff_t gtt_page_base, offset;
@@ -762,12 +689,15 @@ i915_gem_gtt_pwrite_slow(struct drm_devi
 		goto out_unpin_pages;
 	}
 
-	ret = i915_gem_object_set_to_gtt_domain(obj, 1);
+	ret = i915_gem_object_set_to_gtt_domain(obj, true);
 	if (ret)
 		goto out_unpin_pages;
 
-	obj_priv = to_intel_bo(obj);
-	offset = obj_priv->gtt_offset + args->offset;
+	ret = i915_gem_object_put_fence(obj);
+	if (ret)
+		goto out_unpin_pages;
+
+	offset = obj->gtt_offset + args->offset;
 
 	while (remain > 0) {
 		/* Operation in this page
@@ -813,39 +743,58 @@ out_unpin_pages:
  * copy_from_user into the kmapped pages backing the object.
  */
 static int
-i915_gem_shmem_pwrite_fast(struct drm_device *dev, struct drm_gem_object *obj,
+i915_gem_shmem_pwrite_fast(struct drm_device *dev,
+			   struct drm_i915_gem_object *obj,
 			   struct drm_i915_gem_pwrite *args,
-			   struct drm_file *file_priv)
+			   struct drm_file *file)
 {
-	struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
+	struct address_space *mapping = obj->base.filp->f_path.dentry->d_inode->i_mapping;
 	ssize_t remain;
-	loff_t offset, page_base;
+	loff_t offset;
 	char __user *user_data;
 	int page_offset, page_length;
 
 	user_data = (char __user *) (uintptr_t) args->data_ptr;
 	remain = args->size;
 
-	obj_priv = to_intel_bo(obj);
 	offset = args->offset;
-	obj_priv->dirty = 1;
+	obj->dirty = 1;
 
 	while (remain > 0) {
+		struct page *page;
+		char *vaddr;
+		int ret;
+
 		/* Operation in this page
 		 *
-		 * page_base = page offset within aperture
 		 * page_offset = offset within page
 		 * page_length = bytes to copy for this page
 		 */
-		page_base = (offset & ~(PAGE_SIZE-1));
 		page_offset = offset & (PAGE_SIZE-1);
 		page_length = remain;
 		if ((page_offset + remain) > PAGE_SIZE)
 			page_length = PAGE_SIZE - page_offset;
 
-		if (fast_shmem_write(obj_priv->pages,
-				       page_base, page_offset,
-				       user_data, page_length))
+		page = read_cache_page_gfp(mapping, offset >> PAGE_SHIFT,
+					   GFP_HIGHUSER | __GFP_RECLAIMABLE);
+		if (IS_ERR(page))
+			return PTR_ERR(page);
+
+		vaddr = kmap_atomic(page, KM_USER0);
+		ret = __copy_from_user_inatomic(vaddr + page_offset,
+						user_data,
+						page_length);
+		kunmap_atomic(vaddr, KM_USER0);
+
+		set_page_dirty(page);
+		mark_page_accessed(page);
+		page_cache_release(page);
+
+		/* If we get a fault while copying data, then (presumably) our
+		 * source page isn't available.  Return the error and we'll
+		 * retry in the slow path.
+		 */
+		if (ret)
 			return -EFAULT;
 
 		remain -= page_length;
@@ -864,17 +813,18 @@ i915_gem_shmem_pwrite_fast(struct drm_de
  * struct_mutex is held.
  */
 static int
-i915_gem_shmem_pwrite_slow(struct drm_device *dev, struct drm_gem_object *obj,
+i915_gem_shmem_pwrite_slow(struct drm_device *dev,
+			   struct drm_i915_gem_object *obj,
 			   struct drm_i915_gem_pwrite *args,
-			   struct drm_file *file_priv)
+			   struct drm_file *file)
 {
-	struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
+	struct address_space *mapping = obj->base.filp->f_path.dentry->d_inode->i_mapping;
 	struct mm_struct *mm = current->mm;
 	struct page **user_pages;
 	ssize_t remain;
 	loff_t offset, pinned_pages, i;
 	loff_t first_data_page, last_data_page, num_pages;
-	int shmem_page_index, shmem_page_offset;
+	int shmem_page_offset;
 	int data_page_index,  data_page_offset;
 	int page_length;
 	int ret;
@@ -912,20 +862,19 @@ i915_gem_shmem_pwrite_slow(struct drm_de
 
 	do_bit17_swizzling = i915_gem_object_needs_bit17_swizzle(obj);
 
-	obj_priv = to_intel_bo(obj);
 	offset = args->offset;
-	obj_priv->dirty = 1;
+	obj->dirty = 1;
 
 	while (remain > 0) {
+		struct page *page;
+
 		/* Operation in this page
 		 *
-		 * shmem_page_index = page number within shmem file
 		 * shmem_page_offset = offset within page in shmem file
 		 * data_page_index = page number in get_user_pages return
 		 * data_page_offset = offset with data_page_index page.
 		 * page_length = bytes to copy for this page
 		 */
-		shmem_page_index = offset / PAGE_SIZE;
 		shmem_page_offset = offset & ~PAGE_MASK;
 		data_page_index = data_ptr / PAGE_SIZE - first_data_page;
 		data_page_offset = data_ptr & ~PAGE_MASK;
@@ -936,21 +885,32 @@ i915_gem_shmem_pwrite_slow(struct drm_de
 		if ((data_page_offset + page_length) > PAGE_SIZE)
 			page_length = PAGE_SIZE - data_page_offset;
 
+		page = read_cache_page_gfp(mapping, offset >> PAGE_SHIFT,
+					   GFP_HIGHUSER | __GFP_RECLAIMABLE);
+		if (IS_ERR(page)) {
+			ret = PTR_ERR(page);
+			goto out;
+		}
+
 		if (do_bit17_swizzling) {
-			slow_shmem_bit17_copy(obj_priv->pages[shmem_page_index],
+			slow_shmem_bit17_copy(page,
 					      shmem_page_offset,
 					      user_pages[data_page_index],
 					      data_page_offset,
 					      page_length,
 					      0);
 		} else {
-			slow_shmem_copy(obj_priv->pages[shmem_page_index],
+			slow_shmem_copy(page,
 					shmem_page_offset,
 					user_pages[data_page_index],
 					data_page_offset,
 					page_length);
 		}
 
+		set_page_dirty(page);
+		mark_page_accessed(page);
+		page_cache_release(page);
+
 		remain -= page_length;
 		data_ptr += page_length;
 		offset += page_length;
@@ -974,8 +934,7 @@ i915_gem_pwrite_ioctl(struct drm_device
 		      struct drm_file *file)
 {
 	struct drm_i915_gem_pwrite *args = data;
-	struct drm_gem_object *obj;
-	struct drm_i915_gem_object *obj_priv;
+	struct drm_i915_gem_object *obj;
 	int ret;
 
 	if (args->size == 0)
@@ -995,15 +954,15 @@ i915_gem_pwrite_ioctl(struct drm_device
 	if (ret)
 		return ret;
 
-	obj = drm_gem_object_lookup(dev, file, args->handle);
+	obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle));
 	if (obj == NULL) {
 		ret = -ENOENT;
 		goto unlock;
 	}
-	obj_priv = to_intel_bo(obj);
 
 	/* Bounds check destination. */
-	if (args->offset > obj->size || args->size > obj->size - args->offset) {
+	if (args->offset > obj->base.size ||
+	    args->size > obj->base.size - args->offset) {
 		ret = -EINVAL;
 		goto out;
 	}
@@ -1014,16 +973,19 @@ i915_gem_pwrite_ioctl(struct drm_device
 	 * pread/pwrite currently are reading and writing from the CPU
 	 * perspective, requiring manual detiling by the client.
 	 */
-	if (obj_priv->phys_obj)
+	if (obj->phys_obj)
 		ret = i915_gem_phys_pwrite(dev, obj, args, file);
-	else if (obj_priv->tiling_mode == I915_TILING_NONE &&
-		 obj_priv->gtt_space &&
-		 obj->write_domain != I915_GEM_DOMAIN_CPU) {
-		ret = i915_gem_object_pin(obj, 0);
+	else if (obj->gtt_space &&
+		 obj->base.write_domain != I915_GEM_DOMAIN_CPU) {
+		ret = i915_gem_object_pin(obj, 0, true);
 		if (ret)
 			goto out;
 
-		ret = i915_gem_object_set_to_gtt_domain(obj, 1);
+		ret = i915_gem_object_set_to_gtt_domain(obj, true);
+		if (ret)
+			goto out_unpin;
+
+		ret = i915_gem_object_put_fence(obj);
 		if (ret)
 			goto out_unpin;
 
@@ -1034,26 +996,19 @@ i915_gem_pwrite_ioctl(struct drm_device
 out_unpin:
 		i915_gem_object_unpin(obj);
 	} else {
-		ret = i915_gem_object_get_pages_or_evict(obj);
-		if (ret)
-			goto out;
-
 		ret = i915_gem_object_set_to_cpu_domain(obj, 1);
 		if (ret)
-			goto out_put;
+			goto out;
 
 		ret = -EFAULT;
 		if (!i915_gem_object_needs_bit17_swizzle(obj))
 			ret = i915_gem_shmem_pwrite_fast(dev, obj, args, file);
 		if (ret == -EFAULT)
 			ret = i915_gem_shmem_pwrite_slow(dev, obj, args, file);
-
-out_put:
-		i915_gem_object_put_pages(obj);
 	}
 
 out:
-	drm_gem_object_unreference(obj);
+	drm_gem_object_unreference(&obj->base);
 unlock:
 	mutex_unlock(&dev->struct_mutex);
 	return ret;
@@ -1065,12 +1020,10 @@ unlock:
  */
 int
 i915_gem_set_domain_ioctl(struct drm_device *dev, void *data,
-			  struct drm_file *file_priv)
+			  struct drm_file *file)
 {
-	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct drm_i915_gem_set_domain *args = data;
-	struct drm_gem_object *obj;
-	struct drm_i915_gem_object *obj_priv;
+	struct drm_i915_gem_object *obj;
 	uint32_t read_domains = args->read_domains;
 	uint32_t write_domain = args->write_domain;
 	int ret;
@@ -1095,28 +1048,15 @@ i915_gem_set_domain_ioctl(struct drm_dev
 	if (ret)
 		return ret;
 
-	obj = drm_gem_object_lookup(dev, file_priv, args->handle);
+	obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle));
 	if (obj == NULL) {
 		ret = -ENOENT;
 		goto unlock;
 	}
-	obj_priv = to_intel_bo(obj);
-
-	intel_mark_busy(dev, obj);
 
 	if (read_domains & I915_GEM_DOMAIN_GTT) {
 		ret = i915_gem_object_set_to_gtt_domain(obj, write_domain != 0);
 
-		/* Update the LRU on the fence for the CPU access that's
-		 * about to occur.
-		 */
-		if (obj_priv->fence_reg != I915_FENCE_REG_NONE) {
-			struct drm_i915_fence_reg *reg =
-				&dev_priv->fence_regs[obj_priv->fence_reg];
-			list_move_tail(&reg->lru_list,
-				       &dev_priv->mm.fence_list);
-		}
-
 		/* Silently promote "you're not bound, there was nothing to do"
 		 * to success, since the client was just asking us to
 		 * make sure everything was done.
@@ -1127,11 +1067,7 @@ i915_gem_set_domain_ioctl(struct drm_dev
 		ret = i915_gem_object_set_to_cpu_domain(obj, write_domain != 0);
 	}
 
-	/* Maintain LRU order of "inactive" objects */
-	if (ret == 0 && i915_gem_object_is_inactive(obj_priv))
-		list_move_tail(&obj_priv->mm_list, &dev_priv->mm.inactive_list);
-
-	drm_gem_object_unreference(obj);
+	drm_gem_object_unreference(&obj->base);
 unlock:
 	mutex_unlock(&dev->struct_mutex);
 	return ret;
@@ -1142,10 +1078,10 @@ unlock:
  */
 int
 i915_gem_sw_finish_ioctl(struct drm_device *dev, void *data,
-		      struct drm_file *file_priv)
+			 struct drm_file *file)
 {
 	struct drm_i915_gem_sw_finish *args = data;
-	struct drm_gem_object *obj;
+	struct drm_i915_gem_object *obj;
 	int ret = 0;
 
 	if (!(dev->driver->driver_features & DRIVER_GEM))
@@ -1155,17 +1091,17 @@ i915_gem_sw_finish_ioctl(struct drm_devi
 	if (ret)
 		return ret;
 
-	obj = drm_gem_object_lookup(dev, file_priv, args->handle);
+	obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle));
 	if (obj == NULL) {
 		ret = -ENOENT;
 		goto unlock;
 	}
 
 	/* Pinned buffers may be scanout, so flush the cache */
-	if (to_intel_bo(obj)->pin_count)
+	if (obj->pin_count)
 		i915_gem_object_flush_cpu_write_domain(obj);
 
-	drm_gem_object_unreference(obj);
+	drm_gem_object_unreference(&obj->base);
 unlock:
 	mutex_unlock(&dev->struct_mutex);
 	return ret;
@@ -1180,8 +1116,9 @@ unlock:
  */
 int
 i915_gem_mmap_ioctl(struct drm_device *dev, void *data,
-		   struct drm_file *file_priv)
+		    struct drm_file *file)
 {
+	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct drm_i915_gem_mmap *args = data;
 	struct drm_gem_object *obj;
 	loff_t offset;
@@ -1190,10 +1127,15 @@ i915_gem_mmap_ioctl(struct drm_device *d
 	if (!(dev->driver->driver_features & DRIVER_GEM))
 		return -ENODEV;
 
-	obj = drm_gem_object_lookup(dev, file_priv, args->handle);
+	obj = drm_gem_object_lookup(dev, file, args->handle);
 	if (obj == NULL)
 		return -ENOENT;
 
+	if (obj->size > dev_priv->mm.gtt_mappable_end) {
+		drm_gem_object_unreference_unlocked(obj);
+		return -E2BIG;
+	}
+
 	offset = args->offset;
 
 	down_write(&current->mm->mmap_sem);
@@ -1228,10 +1170,9 @@ i915_gem_mmap_ioctl(struct drm_device *d
  */
 int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 {
-	struct drm_gem_object *obj = vma->vm_private_data;
-	struct drm_device *dev = obj->dev;
+	struct drm_i915_gem_object *obj = to_intel_bo(vma->vm_private_data);
+	struct drm_device *dev = obj->base.dev;
 	drm_i915_private_t *dev_priv = dev->dev_private;
-	struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
 	pgoff_t page_offset;
 	unsigned long pfn;
 	int ret = 0;
@@ -1243,27 +1184,35 @@ int i915_gem_fault(struct vm_area_struct
 
 	/* Now bind it into the GTT if needed */
 	mutex_lock(&dev->struct_mutex);
-	if (!obj_priv->gtt_space) {
-		ret = i915_gem_object_bind_to_gtt(obj, 0);
-		if (ret)
-			goto unlock;
 
-		ret = i915_gem_object_set_to_gtt_domain(obj, write);
+	if (!obj->map_and_fenceable) {
+		ret = i915_gem_object_unbind(obj);
 		if (ret)
 			goto unlock;
 	}
-
-	/* Need a new fence register? */
-	if (obj_priv->tiling_mode != I915_TILING_NONE) {
-		ret = i915_gem_object_get_fence_reg(obj, true);
+	if (!obj->gtt_space) {
+		ret = i915_gem_object_bind_to_gtt(obj, 0, true);
 		if (ret)
 			goto unlock;
 	}
 
-	if (i915_gem_object_is_inactive(obj_priv))
-		list_move_tail(&obj_priv->mm_list, &dev_priv->mm.inactive_list);
+	ret = i915_gem_object_set_to_gtt_domain(obj, write);
+	if (ret)
+		goto unlock;
 
-	pfn = ((dev->agp->base + obj_priv->gtt_offset) >> PAGE_SHIFT) +
+	if (obj->tiling_mode == I915_TILING_NONE)
+		ret = i915_gem_object_put_fence(obj);
+	else
+		ret = i915_gem_object_get_fence(obj, NULL, true);
+	if (ret)
+		goto unlock;
+
+	if (i915_gem_object_is_inactive(obj))
+		list_move_tail(&obj->mm_list, &dev_priv->mm.inactive_list);
+
+	obj->fault_mappable = true;
+
+	pfn = ((dev->agp->base + obj->gtt_offset) >> PAGE_SHIFT) +
 		page_offset;
 
 	/* Finally, remap it using the new GTT offset */
@@ -1272,11 +1221,12 @@ unlock:
 	mutex_unlock(&dev->struct_mutex);
 
 	switch (ret) {
+	case -EAGAIN:
+		set_need_resched();
 	case 0:
 	case -ERESTARTSYS:
 		return VM_FAULT_NOPAGE;
 	case -ENOMEM:
-	case -EAGAIN:
 		return VM_FAULT_OOM;
 	default:
 		return VM_FAULT_SIGBUS;
@@ -1295,37 +1245,39 @@ unlock:
  * This routine allocates and attaches a fake offset for @obj.
  */
 static int
-i915_gem_create_mmap_offset(struct drm_gem_object *obj)
+i915_gem_create_mmap_offset(struct drm_i915_gem_object *obj)
 {
-	struct drm_device *dev = obj->dev;
+	struct drm_device *dev = obj->base.dev;
 	struct drm_gem_mm *mm = dev->mm_private;
-	struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
 	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 = &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->size;
+	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->size / PAGE_SIZE, 0, 0);
+						    obj->base.size / PAGE_SIZE,
+						    0, 0);
 	if (!list->file_offset_node) {
-		DRM_ERROR("failed to allocate offset for bo %d\n", obj->name);
+		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->size / PAGE_SIZE, 0);
+						  obj->base.size / PAGE_SIZE,
+						  0);
 	if (!list->file_offset_node) {
 		ret = -ENOMEM;
 		goto out_free_list;
@@ -1338,16 +1290,13 @@ i915_gem_create_mmap_offset(struct drm_g
 		goto out_free_mm;
 	}
 
-	/* By now we should be all set, any drm_mmap request on the offset
-	 * below will get to our mmap & fault handler */
-	obj_priv->mmap_offset = ((uint64_t) list->hash.key) << PAGE_SHIFT;
-
 	return 0;
 
 out_free_mm:
 	drm_mm_put_block(list->file_offset_node);
 out_free_list:
 	kfree(list->map);
+	list->map = NULL;
 
 	return ret;
 }
@@ -1367,38 +1316,51 @@ out_free_list:
  * fixup by i915_gem_fault().
  */
 void
-i915_gem_release_mmap(struct drm_gem_object *obj)
+i915_gem_release_mmap(struct drm_i915_gem_object *obj)
 {
-	struct drm_device *dev = obj->dev;
-	struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
+	if (!obj->fault_mappable)
+		return;
 
-	if (dev->dev_mapping)
-		unmap_mapping_range(dev->dev_mapping,
-				    obj_priv->mmap_offset, obj->size, 1);
+	unmap_mapping_range(obj->base.dev->dev_mapping,
+			    (loff_t)obj->base.map_list.hash.key<<PAGE_SHIFT,
+			    obj->base.size, 1);
+
+	obj->fault_mappable = false;
 }
 
 static void
-i915_gem_free_mmap_offset(struct drm_gem_object *obj)
+i915_gem_free_mmap_offset(struct drm_i915_gem_object *obj)
 {
-	struct drm_device *dev = obj->dev;
-	struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
+	struct drm_device *dev = obj->base.dev;
 	struct drm_gem_mm *mm = dev->mm_private;
-	struct drm_map_list *list;
+	struct drm_map_list *list = &obj->base.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;
+}
 
-	if (list->file_offset_node) {
-		drm_mm_put_block(list->file_offset_node);
-		list->file_offset_node = NULL;
-	}
+static uint32_t
+i915_gem_get_gtt_size(struct drm_i915_gem_object *obj)
+{
+	struct drm_device *dev = obj->base.dev;
+	uint32_t size;
 
-	if (list->map) {
-		kfree(list->map);
-		list->map = NULL;
-	}
+	if (INTEL_INFO(dev)->gen >= 4 ||
+	    obj->tiling_mode == I915_TILING_NONE)
+		return obj->base.size;
 
-	obj_priv->mmap_offset = 0;
+	/* Previous chips need a power-of-two fence region when tiling */
+	if (INTEL_INFO(dev)->gen == 3)
+		size = 1024*1024;
+	else
+		size = 512*1024;
+
+	while (size < obj->base.size)
+		size <<= 1;
+
+	return size;
 }
 
 /**
@@ -1406,42 +1368,68 @@ i915_gem_free_mmap_offset(struct drm_gem
  * @obj: object to check
  *
  * Return the required GTT alignment for an object, taking into account
- * potential fence register mapping if needed.
+ * potential fence register mapping.
  */
 static uint32_t
-i915_gem_get_gtt_alignment(struct drm_gem_object *obj)
+i915_gem_get_gtt_alignment(struct drm_i915_gem_object *obj)
 {
-	struct drm_device *dev = obj->dev;
-	struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
-	int start, i;
+	struct drm_device *dev = obj->base.dev;
 
 	/*
 	 * Minimum alignment is 4k (GTT page size), but might be greater
 	 * if a fence register is needed for the object.
 	 */
-	if (INTEL_INFO(dev)->gen >= 4 || obj_priv->tiling_mode == I915_TILING_NONE)
+	if (INTEL_INFO(dev)->gen >= 4 ||
+	    obj->tiling_mode == I915_TILING_NONE)
 		return 4096;
 
 	/*
 	 * Previous chips need to be aligned to the size of the smallest
 	 * fence register that can contain the object.
 	 */
-	if (INTEL_INFO(dev)->gen == 3)
-		start = 1024*1024;
-	else
-		start = 512*1024;
+	return i915_gem_get_gtt_size(obj);
+}
 
-	for (i = start; i < obj->size; i <<= 1)
-		;
+/**
+ * i915_gem_get_unfenced_gtt_alignment - return required GTT alignment for an
+ *					 unfenced object
+ * @obj: object to check
+ *
+ * Return the required GTT alignment for an object, only taking into account
+ * unfenced tiled surface requirements.
+ */
+uint32_t
+i915_gem_get_unfenced_gtt_alignment(struct drm_i915_gem_object *obj)
+{
+	struct drm_device *dev = obj->base.dev;
+	int tile_height;
 
-	return i;
+	/*
+	 * Minimum alignment is 4k (GTT page size) for sane hw.
+	 */
+	if (INTEL_INFO(dev)->gen >= 4 || IS_G33(dev) ||
+	    obj->tiling_mode == I915_TILING_NONE)
+		return 4096;
+
+	/*
+	 * Older chips need unfenced tiled buffers to be aligned to the left
+	 * edge of an even tile row (where tile rows are counted as if the bo is
+	 * placed in a fenced gtt region).
+	 */
+	if (IS_GEN2(dev) ||
+	    (obj->tiling_mode == I915_TILING_Y && HAS_128_BYTE_Y_TILING(dev)))
+		tile_height = 32;
+	else
+		tile_height = 8;
+
+	return tile_height * obj->stride * 2;
 }
 
 /**
  * i915_gem_mmap_gtt_ioctl - prepare an object for GTT mmap'ing
  * @dev: DRM device
  * @data: GTT mapping ioctl data
- * @file_priv: GEM object info
+ * @file: GEM object info
  *
  * Simply returns the fake offset to userspace so it can mmap it.
  * The mmap call will end up in drm_gem_mmap(), which will set things
@@ -1454,11 +1442,11 @@ i915_gem_get_gtt_alignment(struct drm_ge
  */
 int
 i915_gem_mmap_gtt_ioctl(struct drm_device *dev, void *data,
-			struct drm_file *file_priv)
+			struct drm_file *file)
 {
+	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct drm_i915_gem_mmap_gtt *args = data;
-	struct drm_gem_object *obj;
-	struct drm_i915_gem_object *obj_priv;
+	struct drm_i915_gem_object *obj;
 	int ret;
 
 	if (!(dev->driver->driver_features & DRIVER_GEM))
@@ -1468,130 +1456,196 @@ i915_gem_mmap_gtt_ioctl(struct drm_devic
 	if (ret)
 		return ret;
 
-	obj = drm_gem_object_lookup(dev, file_priv, args->handle);
+	obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle));
 	if (obj == NULL) {
 		ret = -ENOENT;
 		goto unlock;
 	}
-	obj_priv = to_intel_bo(obj);
 
-	if (obj_priv->madv != I915_MADV_WILLNEED) {
+	if (obj->base.size > dev_priv->mm.gtt_mappable_end) {
+		ret = -E2BIG;
+		goto unlock;
+	}
+
+	if (obj->madv != I915_MADV_WILLNEED) {
 		DRM_ERROR("Attempting to mmap a purgeable buffer\n");
 		ret = -EINVAL;
 		goto out;
 	}
 
-	if (!obj_priv->mmap_offset) {
+	if (!obj->base.map_list.map) {
 		ret = i915_gem_create_mmap_offset(obj);
 		if (ret)
 			goto out;
 	}
 
-	args->offset = obj_priv->mmap_offset;
-
-	/*
-	 * Pull it into the GTT so that we have a page list (makes the
-	 * initial fault faster and any subsequent flushing possible).
-	 */
-	if (!obj_priv->agp_mem) {
-		ret = i915_gem_object_bind_to_gtt(obj, 0);
-		if (ret)
-			goto out;
-	}
+	args->offset = (u64)obj->base.map_list.hash.key << PAGE_SHIFT;
 
 out:
-	drm_gem_object_unreference(obj);
+	drm_gem_object_unreference(&obj->base);
 unlock:
 	mutex_unlock(&dev->struct_mutex);
 	return ret;
 }
 
+static int
+i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj,
+			      gfp_t gfpmask)
+{
+	int page_count, i;
+	struct address_space *mapping;
+	struct inode *inode;
+	struct page *page;
+
+	/* Get the list of pages out of our struct file.  They'll be pinned
+	 * at this point until we release them.
+	 */
+	page_count = obj->base.size / PAGE_SIZE;
+	BUG_ON(obj->pages != NULL);
+	obj->pages = drm_malloc_ab(page_count, sizeof(struct page *));
+	if (obj->pages == NULL)
+		return -ENOMEM;
+
+	inode = obj->base.filp->f_path.dentry->d_inode;
+	mapping = inode->i_mapping;
+	for (i = 0; i < page_count; i++) {
+		page = read_cache_page_gfp(mapping, i,
+					   GFP_HIGHUSER |
+					   __GFP_COLD |
+					   __GFP_RECLAIMABLE |
+					   gfpmask);
+		if (IS_ERR(page))
+			goto err_pages;
+
+		obj->pages[i] = page;
+	}
+
+	if (obj->tiling_mode != I915_TILING_NONE)
+		i915_gem_object_do_bit_17_swizzle(obj);
+
+	return 0;
+
+err_pages:
+	while (i--)
+		page_cache_release(obj->pages[i]);
+
+	drm_free_large(obj->pages);
+	obj->pages = NULL;
+	return PTR_ERR(page);
+}
+
 static void
-i915_gem_object_put_pages(struct drm_gem_object *obj)
+i915_gem_object_put_pages_gtt(struct drm_i915_gem_object *obj)
 {
-	struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
-	int page_count = obj->size / PAGE_SIZE;
+	int page_count = obj->base.size / PAGE_SIZE;
 	int i;
 
-	BUG_ON(obj_priv->pages_refcount == 0);
-	BUG_ON(obj_priv->madv == __I915_MADV_PURGED);
-
-	if (--obj_priv->pages_refcount != 0)
-		return;
+	BUG_ON(obj->madv == __I915_MADV_PURGED);
 
-	if (obj_priv->tiling_mode != I915_TILING_NONE)
+	if (obj->tiling_mode != I915_TILING_NONE)
 		i915_gem_object_save_bit_17_swizzle(obj);
 
-	if (obj_priv->madv == I915_MADV_DONTNEED)
-		obj_priv->dirty = 0;
+	if (obj->madv == I915_MADV_DONTNEED)
+		obj->dirty = 0;
 
 	for (i = 0; i < page_count; i++) {
-		if (obj_priv->dirty)
-			set_page_dirty(obj_priv->pages[i]);
+		if (obj->dirty)
+			set_page_dirty(obj->pages[i]);
 
-		if (obj_priv->madv == I915_MADV_WILLNEED)
-			mark_page_accessed(obj_priv->pages[i]);
+		if (obj->madv == I915_MADV_WILLNEED)
+			mark_page_accessed(obj->pages[i]);
 
-		page_cache_release(obj_priv->pages[i]);
+		page_cache_release(obj->pages[i]);
 	}
-	obj_priv->dirty = 0;
-
-	drm_free_large(obj_priv->pages);
-	obj_priv->pages = NULL;
-}
-
-static uint32_t
-i915_gem_next_request_seqno(struct drm_device *dev,
-			    struct intel_ring_buffer *ring)
-{
-	drm_i915_private_t *dev_priv = dev->dev_private;
+	obj->dirty = 0;
 
-	ring->outstanding_lazy_request = true;
-	return dev_priv->next_seqno;
+	drm_free_large(obj->pages);
+	obj->pages = NULL;
 }
 
-static void
-i915_gem_object_move_to_active(struct drm_gem_object *obj,
-			       struct intel_ring_buffer *ring)
+void
+i915_gem_object_move_to_active(struct drm_i915_gem_object *obj,
+			       struct intel_ring_buffer *ring,
+			       u32 seqno)
 {
-	struct drm_device *dev = obj->dev;
+	struct drm_device *dev = obj->base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
-	uint32_t seqno = i915_gem_next_request_seqno(dev, ring);
 
 	BUG_ON(ring == NULL);
-	obj_priv->ring = ring;
+	obj->ring = ring;
 
 	/* Add a reference if we're newly entering the active list. */
-	if (!obj_priv->active) {
-		drm_gem_object_reference(obj);
-		obj_priv->active = 1;
+	if (!obj->active) {
+		drm_gem_object_reference(&obj->base);
+		obj->active = 1;
 	}
 
 	/* Move from whatever list we were on to the tail of execution. */
-	list_move_tail(&obj_priv->mm_list, &dev_priv->mm.active_list);
-	list_move_tail(&obj_priv->ring_list, &ring->active_list);
-	obj_priv->last_rendering_seqno = seqno;
+	list_move_tail(&obj->mm_list, &dev_priv->mm.active_list);
+	list_move_tail(&obj->ring_list, &ring->active_list);
+
+	obj->last_rendering_seqno = seqno;
+	if (obj->fenced_gpu_access) {
+		struct drm_i915_fence_reg *reg;
+
+		BUG_ON(obj->fence_reg == I915_FENCE_REG_NONE);
+
+		obj->last_fenced_seqno = seqno;
+		obj->last_fenced_ring = ring;
+
+		reg = &dev_priv->fence_regs[obj->fence_reg];
+		list_move_tail(&reg->lru_list, &dev_priv->mm.fence_list);
+	}
 }
 
 static void
-i915_gem_object_move_to_flushing(struct drm_gem_object *obj)
+i915_gem_object_move_off_active(struct drm_i915_gem_object *obj)
 {
-	struct drm_device *dev = obj->dev;
+	list_del_init(&obj->ring_list);
+	obj->last_rendering_seqno = 0;
+}
+
+static void
+i915_gem_object_move_to_flushing(struct drm_i915_gem_object *obj)
+{
+	struct drm_device *dev = obj->base.dev;
 	drm_i915_private_t *dev_priv = dev->dev_private;
-	struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
 
-	BUG_ON(!obj_priv->active);
-	list_move_tail(&obj_priv->mm_list, &dev_priv->mm.flushing_list);
-	list_del_init(&obj_priv->ring_list);
-	obj_priv->last_rendering_seqno = 0;
+	BUG_ON(!obj->active);
+	list_move_tail(&obj->mm_list, &dev_priv->mm.flushing_list);
+
+	i915_gem_object_move_off_active(obj);
+}
+
+static void
+i915_gem_object_move_to_inactive(struct drm_i915_gem_object *obj)
+{
+	struct drm_device *dev = obj->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	if (obj->pin_count != 0)
+		list_move_tail(&obj->mm_list, &dev_priv->mm.pinned_list);
+	else
+		list_move_tail(&obj->mm_list, &dev_priv->mm.inactive_list);
+
+	BUG_ON(!list_empty(&obj->gpu_write_list));
+	BUG_ON(!obj->active);
+	obj->ring = NULL;
+
+	i915_gem_object_move_off_active(obj);
+	obj->fenced_gpu_access = false;
+
+	obj->active = 0;
+	obj->pending_gpu_write = false;
+	drm_gem_object_unreference(&obj->base);
+
+	WARN_ON(i915_verify_lists(dev));
 }
 
 /* Immediately discard the backing storage */
 static void
-i915_gem_object_truncate(struct drm_gem_object *obj)
+i915_gem_object_truncate(struct drm_i915_gem_object *obj)
 {
-	struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
 	struct inode *inode;
 
 	/* Our goal here is to return as much of the memory as
@@ -1600,42 +1654,18 @@ i915_gem_object_truncate(struct drm_gem_
 	 * backing pages, *now*. Here we mirror the actions taken
 	 * when by shmem_delete_inode() to release the backing store.
 	 */
-	inode = obj->filp->f_path.dentry->d_inode;
+	inode = obj->base.filp->f_path.dentry->d_inode;
 	truncate_inode_pages(inode->i_mapping, 0);
 	if (inode->i_op->truncate_range)
 		inode->i_op->truncate_range(inode, 0, (loff_t)-1);
 
-	obj_priv->madv = __I915_MADV_PURGED;
+	obj->madv = __I915_MADV_PURGED;
 }
 
 static inline int
-i915_gem_object_is_purgeable(struct drm_i915_gem_object *obj_priv)
-{
-	return obj_priv->madv == I915_MADV_DONTNEED;
-}
-
-static void
-i915_gem_object_move_to_inactive(struct drm_gem_object *obj)
+i915_gem_object_is_purgeable(struct drm_i915_gem_object *obj)
 {
-	struct drm_device *dev = obj->dev;
-	drm_i915_private_t *dev_priv = dev->dev_private;
-	struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
-
-	if (obj_priv->pin_count != 0)
-		list_move_tail(&obj_priv->mm_list, &dev_priv->mm.pinned_list);
-	else
-		list_move_tail(&obj_priv->mm_list, &dev_priv->mm.inactive_list);
-	list_del_init(&obj_priv->ring_list);
-
-	BUG_ON(!list_empty(&obj_priv->gpu_write_list));
-
-	obj_priv->last_rendering_seqno = 0;
-	obj_priv->ring = NULL;
-	if (obj_priv->active) {
-		obj_priv->active = 0;
-		drm_gem_object_unreference(obj);
-	}
-	WARN_ON(i915_verify_lists(dev));
+	return obj->madv == I915_MADV_DONTNEED;
 }
 
 static void
@@ -1643,37 +1673,27 @@ i915_gem_process_flushing_list(struct dr
 			       uint32_t flush_domains,
 			       struct intel_ring_buffer *ring)
 {
-	drm_i915_private_t *dev_priv = dev->dev_private;
-	struct drm_i915_gem_object *obj_priv, *next;
+	struct drm_i915_gem_object *obj, *next;
 
-	list_for_each_entry_safe(obj_priv, next,
+	list_for_each_entry_safe(obj, next,
 				 &ring->gpu_write_list,
 				 gpu_write_list) {
-		struct drm_gem_object *obj = &obj_priv->base;
-
-		if (obj->write_domain & flush_domains) {
-			uint32_t old_write_domain = obj->write_domain;
-
-			obj->write_domain = 0;
-			list_del_init(&obj_priv->gpu_write_list);
-			i915_gem_object_move_to_active(obj, ring);
+		if (obj->base.write_domain & flush_domains) {
+			uint32_t old_write_domain = obj->base.write_domain;
 
-			/* update the fence lru list */
-			if (obj_priv->fence_reg != I915_FENCE_REG_NONE) {
-				struct drm_i915_fence_reg *reg =
-					&dev_priv->fence_regs[obj_priv->fence_reg];
-				list_move_tail(&reg->lru_list,
-						&dev_priv->mm.fence_list);
-			}
+			obj->base.write_domain = 0;
+			list_del_init(&obj->gpu_write_list);
+			i915_gem_object_move_to_active(obj, ring,
+						       i915_gem_next_request_seqno(dev, ring));
 
 			trace_i915_gem_object_change_domain(obj,
-							    obj->read_domains,
+							    obj->base.read_domains,
 							    old_write_domain);
 		}
 	}
 }
 
-uint32_t
+int
 i915_add_request(struct drm_device *dev,
 		 struct drm_file *file,
 		 struct drm_i915_gem_request *request,
@@ -1683,17 +1703,17 @@ i915_add_request(struct drm_device *dev,
 	struct drm_i915_file_private *file_priv = NULL;
 	uint32_t seqno;
 	int was_empty;
+	int ret;
+
+	BUG_ON(request == NULL);
 
 	if (file != NULL)
 		file_priv = file->driver_priv;
 
-	if (request == NULL) {
-		request = kzalloc(sizeof(*request), GFP_KERNEL);
-		if (request == NULL)
-			return 0;
-	}
+	ret = ring->add_request(ring, &seqno);
+	if (ret)
+	    return ret;
 
-	seqno = ring->add_request(dev, ring, 0);
 	ring->outstanding_lazy_request = false;
 
 	request->seqno = seqno;
@@ -1717,26 +1737,7 @@ i915_add_request(struct drm_device *dev,
 			queue_delayed_work(dev_priv->wq,
 					   &dev_priv->mm.retire_work, HZ);
 	}
-	return seqno;
-}
-
-/**
- * Command execution barrier
- *
- * Ensures that all commands in the ring are finished
- * before signalling the CPU
- */
-static void
-i915_retire_commands(struct drm_device *dev, struct intel_ring_buffer *ring)
-{
-	uint32_t flush_domains = 0;
-
-	/* The sampler always gets flushed on i965 (sigh) */
-	if (INTEL_INFO(dev)->gen >= 4)
-		flush_domains |= I915_GEM_DOMAIN_SAMPLER;
-
-	ring->flush(dev, ring,
-			I915_GEM_DOMAIN_COMMAND, flush_domains);
+	return 0;
 }
 
 static inline void
@@ -1769,62 +1770,76 @@ static void i915_gem_reset_ring_lists(st
 	}
 
 	while (!list_empty(&ring->active_list)) {
-		struct drm_i915_gem_object *obj_priv;
+		struct drm_i915_gem_object *obj;
 
-		obj_priv = list_first_entry(&ring->active_list,
-					    struct drm_i915_gem_object,
-					    ring_list);
+		obj = list_first_entry(&ring->active_list,
+				       struct drm_i915_gem_object,
+				       ring_list);
 
-		obj_priv->base.write_domain = 0;
-		list_del_init(&obj_priv->gpu_write_list);
-		i915_gem_object_move_to_inactive(&obj_priv->base);
+		obj->base.write_domain = 0;
+		list_del_init(&obj->gpu_write_list);
+		i915_gem_object_move_to_inactive(obj);
+	}
+}
+
+static void i915_gem_reset_fences(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	int i;
+
+	for (i = 0; i < 16; i++) {
+		struct drm_i915_fence_reg *reg = &dev_priv->fence_regs[i];
+		struct drm_i915_gem_object *obj = reg->obj;
+
+		if (!obj)
+			continue;
+
+		if (obj->tiling_mode)
+			i915_gem_release_mmap(obj);
+
+		reg->obj->fence_reg = I915_FENCE_REG_NONE;
+		reg->obj->fenced_gpu_access = false;
+		reg->obj->last_fenced_seqno = 0;
+		reg->obj->last_fenced_ring = NULL;
+		i915_gem_clear_fence_reg(dev, reg);
 	}
 }
 
 void i915_gem_reset(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct drm_i915_gem_object *obj_priv;
+	struct drm_i915_gem_object *obj;
 	int i;
 
-	i915_gem_reset_ring_lists(dev_priv, &dev_priv->render_ring);
-	i915_gem_reset_ring_lists(dev_priv, &dev_priv->bsd_ring);
-	i915_gem_reset_ring_lists(dev_priv, &dev_priv->blt_ring);
+	for (i = 0; i < I915_NUM_RINGS; i++)
+		i915_gem_reset_ring_lists(dev_priv, &dev_priv->ring[i]);
 
 	/* Remove anything from the flushing lists. The GPU cache is likely
 	 * to be lost on reset along with the data, so simply move the
 	 * lost bo to the inactive list.
 	 */
 	while (!list_empty(&dev_priv->mm.flushing_list)) {
-		obj_priv = list_first_entry(&dev_priv->mm.flushing_list,
-					    struct drm_i915_gem_object,
-					    mm_list);
+		obj= list_first_entry(&dev_priv->mm.flushing_list,
+				      struct drm_i915_gem_object,
+				      mm_list);
 
-		obj_priv->base.write_domain = 0;
-		list_del_init(&obj_priv->gpu_write_list);
-		i915_gem_object_move_to_inactive(&obj_priv->base);
+		obj->base.write_domain = 0;
+		list_del_init(&obj->gpu_write_list);
+		i915_gem_object_move_to_inactive(obj);
 	}
 
 	/* Move everything out of the GPU domains to ensure we do any
 	 * necessary invalidation upon reuse.
 	 */
-	list_for_each_entry(obj_priv,
+	list_for_each_entry(obj,
 			    &dev_priv->mm.inactive_list,
 			    mm_list)
 	{
-		obj_priv->base.read_domains &= ~I915_GEM_GPU_DOMAINS;
+		obj->base.read_domains &= ~I915_GEM_GPU_DOMAINS;
 	}
 
 	/* The fence registers are invalidated so clear them out */
-	for (i = 0; i < 16; i++) {
-		struct drm_i915_fence_reg *reg;
-
-		reg = &dev_priv->fence_regs[i];
-		if (!reg->obj)
-			continue;
-
-		i915_gem_clear_fence_reg(reg->obj);
-	}
+	i915_gem_reset_fences(dev);
 }
 
 /**
@@ -1836,6 +1851,7 @@ i915_gem_retire_requests_ring(struct drm
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	uint32_t seqno;
+	int i;
 
 	if (!ring->status_page.page_addr ||
 	    list_empty(&ring->request_list))
@@ -1843,7 +1859,12 @@ i915_gem_retire_requests_ring(struct drm
 
 	WARN_ON(i915_verify_lists(dev));
 
-	seqno = ring->get_seqno(dev, ring);
+	seqno = ring->get_seqno(ring);
+
+	for (i = 0; i < ARRAY_SIZE(ring->sync_seqno); i++)
+		if (seqno >= ring->sync_seqno[i])
+			ring->sync_seqno[i] = 0;
+
 	while (!list_empty(&ring->request_list)) {
 		struct drm_i915_gem_request *request;
 
@@ -1865,18 +1886,16 @@ i915_gem_retire_requests_ring(struct drm
 	 * by the ringbuffer to the flushing/inactive lists as appropriate.
 	 */
 	while (!list_empty(&ring->active_list)) {
-		struct drm_gem_object *obj;
-		struct drm_i915_gem_object *obj_priv;
+		struct drm_i915_gem_object *obj;
 
-		obj_priv = list_first_entry(&ring->active_list,
-					    struct drm_i915_gem_object,
-					    ring_list);
+		obj= list_first_entry(&ring->active_list,
+				      struct drm_i915_gem_object,
+				      ring_list);
 
-		if (!i915_seqno_passed(seqno, obj_priv->last_rendering_seqno))
+		if (!i915_seqno_passed(seqno, obj->last_rendering_seqno))
 			break;
 
-		obj = &obj_priv->base;
-		if (obj->write_domain != 0)
+		if (obj->base.write_domain != 0)
 			i915_gem_object_move_to_flushing(obj);
 		else
 			i915_gem_object_move_to_inactive(obj);
@@ -1884,7 +1903,7 @@ i915_gem_retire_requests_ring(struct drm
 
 	if (unlikely (dev_priv->trace_irq_seqno &&
 		      i915_seqno_passed(dev_priv->trace_irq_seqno, seqno))) {
-		ring->user_irq_put(dev, ring);
+		ring->irq_put(ring);
 		dev_priv->trace_irq_seqno = 0;
 	}
 
@@ -1895,24 +1914,24 @@ void
 i915_gem_retire_requests(struct drm_device *dev)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
+	int i;
 
 	if (!list_empty(&dev_priv->mm.deferred_free_list)) {
-	    struct drm_i915_gem_object *obj_priv, *tmp;
+	    struct drm_i915_gem_object *obj, *next;
 
 	    /* We must be careful that during unbind() we do not
 	     * accidentally infinitely recurse into retire requests.
 	     * Currently:
 	     *   retire -> free -> unbind -> wait -> retire_ring
 	     */
-	    list_for_each_entry_safe(obj_priv, tmp,
+	    list_for_each_entry_safe(obj, next,
 				     &dev_priv->mm.deferred_free_list,
 				     mm_list)
-		    i915_gem_free_object_tail(&obj_priv->base);
+		    i915_gem_free_object_tail(obj);
 	}
 
-	i915_gem_retire_requests_ring(dev, &dev_priv->render_ring);
-	i915_gem_retire_requests_ring(dev, &dev_priv->bsd_ring);
-	i915_gem_retire_requests_ring(dev, &dev_priv->blt_ring);
+	for (i = 0; i < I915_NUM_RINGS; i++)
+		i915_gem_retire_requests_ring(dev, &dev_priv->ring[i]);
 }
 
 static void
@@ -1920,6 +1939,8 @@ i915_gem_retire_work_handler(struct work
 {
 	drm_i915_private_t *dev_priv;
 	struct drm_device *dev;
+	bool idle;
+	int i;
 
 	dev_priv = container_of(work, drm_i915_private_t,
 				mm.retire_work.work);
@@ -1933,11 +1954,31 @@ i915_gem_retire_work_handler(struct work
 
 	i915_gem_retire_requests(dev);
 
-	if (!dev_priv->mm.suspended &&
-		(!list_empty(&dev_priv->render_ring.request_list) ||
-		 !list_empty(&dev_priv->bsd_ring.request_list) ||
-		 !list_empty(&dev_priv->blt_ring.request_list)))
+	/* Send a periodic flush down the ring so we don't hold onto GEM
+	 * objects indefinitely.
+	 */
+	idle = true;
+	for (i = 0; i < I915_NUM_RINGS; i++) {
+		struct intel_ring_buffer *ring = &dev_priv->ring[i];
+
+		if (!list_empty(&ring->gpu_write_list)) {
+			struct drm_i915_gem_request *request;
+			int ret;
+
+			ret = i915_gem_flush_ring(dev, ring, 0,
+						  I915_GEM_GPU_DOMAINS);
+			request = kzalloc(sizeof(*request), GFP_KERNEL);
+			if (ret || request == NULL ||
+			    i915_add_request(dev, NULL, request, ring))
+			    kfree(request);
+		}
+
+		idle &= list_empty(&ring->request_list);
+	}
+
+	if (!dev_priv->mm.suspended && !idle)
 		queue_delayed_work(dev_priv->wq, &dev_priv->mm.retire_work, HZ);
+
 	mutex_unlock(&dev->struct_mutex);
 }
 
@@ -1954,14 +1995,23 @@ i915_do_wait_request(struct drm_device *
 	if (atomic_read(&dev_priv->mm.wedged))
 		return -EAGAIN;
 
-	if (ring->outstanding_lazy_request) {
-		seqno = i915_add_request(dev, NULL, NULL, ring);
-		if (seqno == 0)
+	if (seqno == ring->outstanding_lazy_request) {
+		struct drm_i915_gem_request *request;
+
+		request = kzalloc(sizeof(*request), GFP_KERNEL);
+		if (request == NULL)
 			return -ENOMEM;
+
+		ret = i915_add_request(dev, NULL, request, ring);
+		if (ret) {
+			kfree(request);
+			return ret;
+		}
+
+		seqno = request->seqno;
 	}
-	BUG_ON(seqno == dev_priv->next_seqno);
 
-	if (!i915_seqno_passed(ring->get_seqno(dev, ring), seqno)) {
+	if (!i915_seqno_passed(ring->get_seqno(ring), seqno)) {
 		if (HAS_PCH_SPLIT(dev))
 			ier = I915_READ(DEIER) | I915_READ(GTIER);
 		else
@@ -1975,21 +2025,23 @@ i915_do_wait_request(struct drm_device *
 
 		trace_i915_gem_request_wait_begin(dev, seqno);
 
-		ring->waiting_gem_seqno = seqno;
-		ring->user_irq_get(dev, ring);
-		if (interruptible)
-			ret = wait_event_interruptible(ring->irq_queue,
-				i915_seqno_passed(
-					ring->get_seqno(dev, ring), seqno)
-				|| atomic_read(&dev_priv->mm.wedged));
-		else
-			wait_event(ring->irq_queue,
-				i915_seqno_passed(
-					ring->get_seqno(dev, ring), seqno)
-				|| atomic_read(&dev_priv->mm.wedged));
+		ring->waiting_seqno = seqno;
+		if (ring->irq_get(ring)) {
+			if (interruptible)
+				ret = wait_event_interruptible(ring->irq_queue,
+							       i915_seqno_passed(ring->get_seqno(ring), seqno)
+							       || atomic_read(&dev_priv->mm.wedged));
+			else
+				wait_event(ring->irq_queue,
+					   i915_seqno_passed(ring->get_seqno(ring), seqno)
+					   || atomic_read(&dev_priv->mm.wedged));
 
-		ring->user_irq_put(dev, ring);
-		ring->waiting_gem_seqno = 0;
+			ring->irq_put(ring);
+		} else if (wait_for(i915_seqno_passed(ring->get_seqno(ring),
+						      seqno) ||
+				    atomic_read(&dev_priv->mm.wedged), 3000))
+			ret = -EBUSY;
+		ring->waiting_seqno = 0;
 
 		trace_i915_gem_request_wait_end(dev, seqno);
 	}
@@ -1998,7 +2050,7 @@ i915_do_wait_request(struct drm_device *
 
 	if (ret && ret != -ERESTARTSYS)
 		DRM_ERROR("%s returns %d (awaiting %d at %d, next %d)\n",
-			  __func__, ret, seqno, ring->get_seqno(dev, ring),
+			  __func__, ret, seqno, ring->get_seqno(ring),
 			  dev_priv->next_seqno);
 
 	/* Directly dispatch request retiring.  While we have the work queue
@@ -2023,70 +2075,30 @@ i915_wait_request(struct drm_device *dev
 	return i915_do_wait_request(dev, seqno, 1, ring);
 }
 
-static void
-i915_gem_flush_ring(struct drm_device *dev,
-		    struct drm_file *file_priv,
-		    struct intel_ring_buffer *ring,
-		    uint32_t invalidate_domains,
-		    uint32_t flush_domains)
-{
-	ring->flush(dev, ring, invalidate_domains, flush_domains);
-	i915_gem_process_flushing_list(dev, flush_domains, ring);
-}
-
-static void
-i915_gem_flush(struct drm_device *dev,
-	       struct drm_file *file_priv,
-	       uint32_t invalidate_domains,
-	       uint32_t flush_domains,
-	       uint32_t flush_rings)
-{
-	drm_i915_private_t *dev_priv = dev->dev_private;
-
-	if (flush_domains & I915_GEM_DOMAIN_CPU)
-		drm_agp_chipset_flush(dev);
-
-	if ((flush_domains | invalidate_domains) & I915_GEM_GPU_DOMAINS) {
-		if (flush_rings & RING_RENDER)
-			i915_gem_flush_ring(dev, file_priv,
-					    &dev_priv->render_ring,
-					    invalidate_domains, flush_domains);
-		if (flush_rings & RING_BSD)
-			i915_gem_flush_ring(dev, file_priv,
-					    &dev_priv->bsd_ring,
-					    invalidate_domains, flush_domains);
-		if (flush_rings & RING_BLT)
-			i915_gem_flush_ring(dev, file_priv,
-					    &dev_priv->blt_ring,
-					    invalidate_domains, flush_domains);
-	}
-}
-
 /**
  * Ensures that all rendering to the object has completed and the object is
  * safe to unbind from the GTT or access from the CPU.
  */
-static int
-i915_gem_object_wait_rendering(struct drm_gem_object *obj,
+int
+i915_gem_object_wait_rendering(struct drm_i915_gem_object *obj,
 			       bool interruptible)
 {
-	struct drm_device *dev = obj->dev;
-	struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
+	struct drm_device *dev = obj->base.dev;
 	int ret;
 
 	/* This function only exists to support waiting for existing rendering,
 	 * not for emitting required flushes.
 	 */
-	BUG_ON((obj->write_domain & I915_GEM_GPU_DOMAINS) != 0);
+	BUG_ON((obj->base.write_domain & I915_GEM_GPU_DOMAINS) != 0);
 
 	/* If there is rendering queued on the buffer being evicted, wait for
 	 * it.
 	 */
-	if (obj_priv->active) {
+	if (obj->active) {
 		ret = i915_do_wait_request(dev,
-					   obj_priv->last_rendering_seqno,
+					   obj->last_rendering_seqno,
 					   interruptible,
-					   obj_priv->ring);
+					   obj->ring);
 		if (ret)
 			return ret;
 	}
@@ -2098,17 +2110,14 @@ i915_gem_object_wait_rendering(struct dr
  * Unbinds an object from the GTT aperture.
  */
 int
-i915_gem_object_unbind(struct drm_gem_object *obj)
+i915_gem_object_unbind(struct drm_i915_gem_object *obj)
 {
-	struct drm_device *dev = obj->dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
 	int ret = 0;
 
-	if (obj_priv->gtt_space == NULL)
+	if (obj->gtt_space == NULL)
 		return 0;
 
-	if (obj_priv->pin_count != 0) {
+	if (obj->pin_count != 0) {
 		DRM_ERROR("Attempting to unbind pinned buffer\n");
 		return -EINVAL;
 	}
@@ -2131,27 +2140,27 @@ i915_gem_object_unbind(struct drm_gem_ob
 	 */
 	if (ret) {
 		i915_gem_clflush_object(obj);
-		obj->read_domains = obj->write_domain = I915_GEM_DOMAIN_CPU;
+		obj->base.read_domains = obj->base.write_domain = I915_GEM_DOMAIN_CPU;
 	}
 
 	/* release the fence reg _after_ flushing */
-	if (obj_priv->fence_reg != I915_FENCE_REG_NONE)
-		i915_gem_clear_fence_reg(obj);
-
-	drm_unbind_agp(obj_priv->agp_mem);
-	drm_free_agp(obj_priv->agp_mem, obj->size / PAGE_SIZE);
+	ret = i915_gem_object_put_fence(obj);
+	if (ret == -ERESTARTSYS)
+		return ret;
 
-	i915_gem_object_put_pages(obj);
-	BUG_ON(obj_priv->pages_refcount);
+	i915_gem_gtt_unbind_object(obj);
+	i915_gem_object_put_pages_gtt(obj);
 
-	i915_gem_info_remove_gtt(dev_priv, obj->size);
-	list_del_init(&obj_priv->mm_list);
+	list_del_init(&obj->gtt_list);
+	list_del_init(&obj->mm_list);
+	/* Avoid an unnecessary call to unbind on rebind. */
+	obj->map_and_fenceable = true;
 
-	drm_mm_put_block(obj_priv->gtt_space);
-	obj_priv->gtt_space = NULL;
-	obj_priv->gtt_offset = 0;
+	drm_mm_put_block(obj->gtt_space);
+	obj->gtt_space = NULL;
+	obj->gtt_offset = 0;
 
-	if (i915_gem_object_is_purgeable(obj_priv))
+	if (i915_gem_object_is_purgeable(obj))
 		i915_gem_object_truncate(obj);
 
 	trace_i915_gem_object_unbind(obj);
@@ -2159,14 +2168,37 @@ i915_gem_object_unbind(struct drm_gem_ob
 	return ret;
 }
 
+int
+i915_gem_flush_ring(struct drm_device *dev,
+		    struct intel_ring_buffer *ring,
+		    uint32_t invalidate_domains,
+		    uint32_t flush_domains)
+{
+	int ret;
+
+	ret = ring->flush(ring, invalidate_domains, flush_domains);
+	if (ret)
+		return ret;
+
+	i915_gem_process_flushing_list(dev, flush_domains, ring);
+	return 0;
+}
+
 static int i915_ring_idle(struct drm_device *dev,
 			  struct intel_ring_buffer *ring)
 {
+	int ret;
+
 	if (list_empty(&ring->gpu_write_list) && list_empty(&ring->active_list))
 		return 0;
 
-	i915_gem_flush_ring(dev, NULL, ring,
-			    I915_GEM_GPU_DOMAINS, I915_GEM_GPU_DOMAINS);
+	if (!list_empty(&ring->gpu_write_list)) {
+		ret = i915_gem_flush_ring(dev, ring,
+				    I915_GEM_GPU_DOMAINS, I915_GEM_GPU_DOMAINS);
+		if (ret)
+			return ret;
+	}
+
 	return i915_wait_request(dev,
 				 i915_gem_next_request_seqno(dev, ring),
 				 ring);
@@ -2177,7 +2209,7 @@ i915_gpu_idle(struct drm_device *dev)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	bool lists_empty;
-	int ret;
+	int ret, i;
 
 	lists_empty = (list_empty(&dev_priv->mm.flushing_list) &&
 		       list_empty(&dev_priv->mm.active_list));
@@ -2185,258 +2217,305 @@ i915_gpu_idle(struct drm_device *dev)
 		return 0;
 
 	/* Flush everything onto the inactive list. */
-	ret = i915_ring_idle(dev, &dev_priv->render_ring);
-	if (ret)
-		return ret;
-
-	ret = i915_ring_idle(dev, &dev_priv->bsd_ring);
-	if (ret)
-		return ret;
-
-	ret = i915_ring_idle(dev, &dev_priv->blt_ring);
-	if (ret)
-		return ret;
-
-	return 0;
-}
-
-static int
-i915_gem_object_get_pages(struct drm_gem_object *obj,
-			  gfp_t gfpmask)
-{
-	struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
-	int page_count, i;
-	struct address_space *mapping;
-	struct inode *inode;
-	struct page *page;
-
-	BUG_ON(obj_priv->pages_refcount
-			== DRM_I915_GEM_OBJECT_MAX_PAGES_REFCOUNT);
-
-	if (obj_priv->pages_refcount++ != 0)
-		return 0;
-
-	/* Get the list of pages out of our struct file.  They'll be pinned
-	 * at this point until we release them.
-	 */
-	page_count = obj->size / PAGE_SIZE;
-	BUG_ON(obj_priv->pages != NULL);
-	obj_priv->pages = drm_calloc_large(page_count, sizeof(struct page *));
-	if (obj_priv->pages == NULL) {
-		obj_priv->pages_refcount--;
-		return -ENOMEM;
-	}
-
-	inode = obj->filp->f_path.dentry->d_inode;
-	mapping = inode->i_mapping;
-	for (i = 0; i < page_count; i++) {
-		page = read_cache_page_gfp(mapping, i,
-					   GFP_HIGHUSER |
-					   __GFP_COLD |
-					   __GFP_RECLAIMABLE |
-					   gfpmask);
-		if (IS_ERR(page))
-			goto err_pages;
-
-		obj_priv->pages[i] = page;
+	for (i = 0; i < I915_NUM_RINGS; i++) {
+		ret = i915_ring_idle(dev, &dev_priv->ring[i]);
+		if (ret)
+			return ret;
 	}
 
-	if (obj_priv->tiling_mode != I915_TILING_NONE)
-		i915_gem_object_do_bit_17_swizzle(obj);
-
 	return 0;
-
-err_pages:
-	while (i--)
-		page_cache_release(obj_priv->pages[i]);
-
-	drm_free_large(obj_priv->pages);
-	obj_priv->pages = NULL;
-	obj_priv->pages_refcount--;
-	return PTR_ERR(page);
 }
 
-static void sandybridge_write_fence_reg(struct drm_i915_fence_reg *reg)
+static int sandybridge_write_fence_reg(struct drm_i915_gem_object *obj,
+				       struct intel_ring_buffer *pipelined)
 {
-	struct drm_gem_object *obj = reg->obj;
-	struct drm_device *dev = obj->dev;
+	struct drm_device *dev = obj->base.dev;
 	drm_i915_private_t *dev_priv = dev->dev_private;
-	struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
-	int regnum = obj_priv->fence_reg;
+	u32 size = obj->gtt_space->size;
+	int regnum = obj->fence_reg;
 	uint64_t val;
 
-	val = (uint64_t)((obj_priv->gtt_offset + obj->size - 4096) &
-		    0xfffff000) << 32;
-	val |= obj_priv->gtt_offset & 0xfffff000;
-	val |= (uint64_t)((obj_priv->stride / 128) - 1) <<
+	val = (uint64_t)((obj->gtt_offset + size - 4096) &
+			 0xfffff000) << 32;
+	val |= obj->gtt_offset & 0xfffff000;
+	val |= (uint64_t)((obj->stride / 128) - 1) <<
 		SANDYBRIDGE_FENCE_PITCH_SHIFT;
 
-	if (obj_priv->tiling_mode == I915_TILING_Y)
+	if (obj->tiling_mode == I915_TILING_Y)
 		val |= 1 << I965_FENCE_TILING_Y_SHIFT;
 	val |= I965_FENCE_REG_VALID;
 
-	I915_WRITE64(FENCE_REG_SANDYBRIDGE_0 + (regnum * 8), val);
+	if (pipelined) {
+		int ret = intel_ring_begin(pipelined, 6);
+		if (ret)
+			return ret;
+
+		intel_ring_emit(pipelined, MI_NOOP);
+		intel_ring_emit(pipelined, MI_LOAD_REGISTER_IMM(2));
+		intel_ring_emit(pipelined, FENCE_REG_SANDYBRIDGE_0 + regnum*8);
+		intel_ring_emit(pipelined, (u32)val);
+		intel_ring_emit(pipelined, FENCE_REG_SANDYBRIDGE_0 + regnum*8 + 4);
+		intel_ring_emit(pipelined, (u32)(val >> 32));
+		intel_ring_advance(pipelined);
+	} else
+		I915_WRITE64(FENCE_REG_SANDYBRIDGE_0 + regnum * 8, val);
+
+	return 0;
 }
 
-static void i965_write_fence_reg(struct drm_i915_fence_reg *reg)
+static int i965_write_fence_reg(struct drm_i915_gem_object *obj,
+				struct intel_ring_buffer *pipelined)
 {
-	struct drm_gem_object *obj = reg->obj;
-	struct drm_device *dev = obj->dev;
+	struct drm_device *dev = obj->base.dev;
 	drm_i915_private_t *dev_priv = dev->dev_private;
-	struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
-	int regnum = obj_priv->fence_reg;
+	u32 size = obj->gtt_space->size;
+	int regnum = obj->fence_reg;
 	uint64_t val;
 
-	val = (uint64_t)((obj_priv->gtt_offset + obj->size - 4096) &
+	val = (uint64_t)((obj->gtt_offset + size - 4096) &
 		    0xfffff000) << 32;
-	val |= obj_priv->gtt_offset & 0xfffff000;
-	val |= ((obj_priv->stride / 128) - 1) << I965_FENCE_PITCH_SHIFT;
-	if (obj_priv->tiling_mode == I915_TILING_Y)
+	val |= obj->gtt_offset & 0xfffff000;
+	val |= ((obj->stride / 128) - 1) << I965_FENCE_PITCH_SHIFT;
+	if (obj->tiling_mode == I915_TILING_Y)
 		val |= 1 << I965_FENCE_TILING_Y_SHIFT;
 	val |= I965_FENCE_REG_VALID;
 
-	I915_WRITE64(FENCE_REG_965_0 + (regnum * 8), val);
+	if (pipelined) {
+		int ret = intel_ring_begin(pipelined, 6);
+		if (ret)
+			return ret;
+
+		intel_ring_emit(pipelined, MI_NOOP);
+		intel_ring_emit(pipelined, MI_LOAD_REGISTER_IMM(2));
+		intel_ring_emit(pipelined, FENCE_REG_965_0 + regnum*8);
+		intel_ring_emit(pipelined, (u32)val);
+		intel_ring_emit(pipelined, FENCE_REG_965_0 + regnum*8 + 4);
+		intel_ring_emit(pipelined, (u32)(val >> 32));
+		intel_ring_advance(pipelined);
+	} else
+		I915_WRITE64(FENCE_REG_965_0 + regnum * 8, val);
+
+	return 0;
 }
 
-static void i915_write_fence_reg(struct drm_i915_fence_reg *reg)
+static int i915_write_fence_reg(struct drm_i915_gem_object *obj,
+				struct intel_ring_buffer *pipelined)
 {
-	struct drm_gem_object *obj = reg->obj;
-	struct drm_device *dev = obj->dev;
+	struct drm_device *dev = obj->base.dev;
 	drm_i915_private_t *dev_priv = dev->dev_private;
-	struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
-	int regnum = obj_priv->fence_reg;
+	u32 size = obj->gtt_space->size;
+	u32 fence_reg, val, pitch_val;
 	int tile_width;
-	uint32_t fence_reg, val;
-	uint32_t pitch_val;
 
-	if ((obj_priv->gtt_offset & ~I915_FENCE_START_MASK) ||
-	    (obj_priv->gtt_offset & (obj->size - 1))) {
-		WARN(1, "%s: object 0x%08x not 1M or size (0x%zx) aligned\n",
-		     __func__, obj_priv->gtt_offset, obj->size);
-		return;
-	}
+	if (WARN((obj->gtt_offset & ~I915_FENCE_START_MASK) ||
+		 (size & -size) != size ||
+		 (obj->gtt_offset & (size - 1)),
+		 "object 0x%08x [fenceable? %d] not 1M or pot-size (0x%08x) aligned\n",
+		 obj->gtt_offset, obj->map_and_fenceable, size))
+		return -EINVAL;
 
-	if (obj_priv->tiling_mode == I915_TILING_Y &&
-	    HAS_128_BYTE_Y_TILING(dev))
+	if (obj->tiling_mode == I915_TILING_Y && HAS_128_BYTE_Y_TILING(dev))
 		tile_width = 128;
 	else
 		tile_width = 512;
 
 	/* Note: pitch better be a power of two tile widths */
-	pitch_val = obj_priv->stride / tile_width;
+	pitch_val = obj->stride / tile_width;
 	pitch_val = ffs(pitch_val) - 1;
 
-	if (obj_priv->tiling_mode == I915_TILING_Y &&
-	    HAS_128_BYTE_Y_TILING(dev))
-		WARN_ON(pitch_val > I830_FENCE_MAX_PITCH_VAL);
-	else
-		WARN_ON(pitch_val > I915_FENCE_MAX_PITCH_VAL);
-
-	val = obj_priv->gtt_offset;
-	if (obj_priv->tiling_mode == I915_TILING_Y)
+	val = obj->gtt_offset;
+	if (obj->tiling_mode == I915_TILING_Y)
 		val |= 1 << I830_FENCE_TILING_Y_SHIFT;
-	val |= I915_FENCE_SIZE_BITS(obj->size);
+	val |= I915_FENCE_SIZE_BITS(size);
 	val |= pitch_val << I830_FENCE_PITCH_SHIFT;
 	val |= I830_FENCE_REG_VALID;
 
-	if (regnum < 8)
-		fence_reg = FENCE_REG_830_0 + (regnum * 4);
+	fence_reg = obj->fence_reg;
+	if (fence_reg < 8)
+		fence_reg = FENCE_REG_830_0 + fence_reg * 4;
 	else
-		fence_reg = FENCE_REG_945_8 + ((regnum - 8) * 4);
-	I915_WRITE(fence_reg, val);
+		fence_reg = FENCE_REG_945_8 + (fence_reg - 8) * 4;
+
+	if (pipelined) {
+		int ret = intel_ring_begin(pipelined, 4);
+		if (ret)
+			return ret;
+
+		intel_ring_emit(pipelined, MI_NOOP);
+		intel_ring_emit(pipelined, MI_LOAD_REGISTER_IMM(1));
+		intel_ring_emit(pipelined, fence_reg);
+		intel_ring_emit(pipelined, val);
+		intel_ring_advance(pipelined);
+	} else
+		I915_WRITE(fence_reg, val);
+
+	return 0;
 }
 
-static void i830_write_fence_reg(struct drm_i915_fence_reg *reg)
+static int i830_write_fence_reg(struct drm_i915_gem_object *obj,
+				struct intel_ring_buffer *pipelined)
 {
-	struct drm_gem_object *obj = reg->obj;
-	struct drm_device *dev = obj->dev;
+	struct drm_device *dev = obj->base.dev;
 	drm_i915_private_t *dev_priv = dev->dev_private;
-	struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
-	int regnum = obj_priv->fence_reg;
+	u32 size = obj->gtt_space->size;
+	int regnum = obj->fence_reg;
 	uint32_t val;
 	uint32_t pitch_val;
-	uint32_t fence_size_bits;
 
-	if ((obj_priv->gtt_offset & ~I830_FENCE_START_MASK) ||
-	    (obj_priv->gtt_offset & (obj->size - 1))) {
-		WARN(1, "%s: object 0x%08x not 512K or size aligned\n",
-		     __func__, obj_priv->gtt_offset);
-		return;
-	}
+	if (WARN((obj->gtt_offset & ~I830_FENCE_START_MASK) ||
+		 (size & -size) != size ||
+		 (obj->gtt_offset & (size - 1)),
+		 "object 0x%08x not 512K or pot-size 0x%08x aligned\n",
+		 obj->gtt_offset, size))
+		return -EINVAL;
 
-	pitch_val = obj_priv->stride / 128;
+	pitch_val = obj->stride / 128;
 	pitch_val = ffs(pitch_val) - 1;
-	WARN_ON(pitch_val > I830_FENCE_MAX_PITCH_VAL);
 
-	val = obj_priv->gtt_offset;
-	if (obj_priv->tiling_mode == I915_TILING_Y)
+	val = obj->gtt_offset;
+	if (obj->tiling_mode == I915_TILING_Y)
 		val |= 1 << I830_FENCE_TILING_Y_SHIFT;
-	fence_size_bits = I830_FENCE_SIZE_BITS(obj->size);
-	WARN_ON(fence_size_bits & ~0x00000f00);
-	val |= fence_size_bits;
+	val |= I830_FENCE_SIZE_BITS(size);
 	val |= pitch_val << I830_FENCE_PITCH_SHIFT;
 	val |= I830_FENCE_REG_VALID;
 
-	I915_WRITE(FENCE_REG_830_0 + (regnum * 4), val);
+	if (pipelined) {
+		int ret = intel_ring_begin(pipelined, 4);
+		if (ret)
+			return ret;
+
+		intel_ring_emit(pipelined, MI_NOOP);
+		intel_ring_emit(pipelined, MI_LOAD_REGISTER_IMM(1));
+		intel_ring_emit(pipelined, FENCE_REG_830_0 + regnum*4);
+		intel_ring_emit(pipelined, val);
+		intel_ring_advance(pipelined);
+	} else
+		I915_WRITE(FENCE_REG_830_0 + regnum * 4, val);
+
+	return 0;
 }
 
-static int i915_find_fence_reg(struct drm_device *dev,
-			       bool interruptible)
+static bool ring_passed_seqno(struct intel_ring_buffer *ring, u32 seqno)
+{
+	return i915_seqno_passed(ring->get_seqno(ring), seqno);
+}
+
+static int
+i915_gem_object_flush_fence(struct drm_i915_gem_object *obj,
+			    struct intel_ring_buffer *pipelined,
+			    bool interruptible)
+{
+	int ret;
+
+	if (obj->fenced_gpu_access) {
+		if (obj->base.write_domain & I915_GEM_GPU_DOMAINS) {
+			ret = i915_gem_flush_ring(obj->base.dev,
+						  obj->last_fenced_ring,
+						  0, obj->base.write_domain);
+			if (ret)
+				return ret;
+		}
+
+		obj->fenced_gpu_access = false;
+	}
+
+	if (obj->last_fenced_seqno && pipelined != obj->last_fenced_ring) {
+		if (!ring_passed_seqno(obj->last_fenced_ring,
+				       obj->last_fenced_seqno)) {
+			ret = i915_do_wait_request(obj->base.dev,
+						   obj->last_fenced_seqno,
+						   interruptible,
+						   obj->last_fenced_ring);
+			if (ret)
+				return ret;
+		}
+
+		obj->last_fenced_seqno = 0;
+		obj->last_fenced_ring = NULL;
+	}
+
+	/* Ensure that all CPU reads are completed before installing a fence
+	 * and all writes before removing the fence.
+	 */
+	if (obj->base.read_domains & I915_GEM_DOMAIN_GTT)
+		mb();
+
+	return 0;
+}
+
+int
+i915_gem_object_put_fence(struct drm_i915_gem_object *obj)
+{
+	int ret;
+
+	if (obj->tiling_mode)
+		i915_gem_release_mmap(obj);
+
+	ret = i915_gem_object_flush_fence(obj, NULL, true);
+	if (ret)
+		return ret;
+
+	if (obj->fence_reg != I915_FENCE_REG_NONE) {
+		struct drm_i915_private *dev_priv = obj->base.dev->dev_private;
+		i915_gem_clear_fence_reg(obj->base.dev,
+					 &dev_priv->fence_regs[obj->fence_reg]);
+
+		obj->fence_reg = I915_FENCE_REG_NONE;
+	}
+
+	return 0;
+}
+
+static struct drm_i915_fence_reg *
+i915_find_fence_reg(struct drm_device *dev,
+		    struct intel_ring_buffer *pipelined)
 {
-	struct drm_i915_fence_reg *reg = NULL;
-	struct drm_i915_gem_object *obj_priv = NULL;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct drm_gem_object *obj = NULL;
-	int i, avail, ret;
+	struct drm_i915_fence_reg *reg, *first, *avail;
+	int i;
 
 	/* First try to find a free reg */
-	avail = 0;
+	avail = NULL;
 	for (i = dev_priv->fence_reg_start; i < dev_priv->num_fence_regs; i++) {
 		reg = &dev_priv->fence_regs[i];
 		if (!reg->obj)
-			return i;
+			return reg;
 
-		obj_priv = to_intel_bo(reg->obj);
-		if (!obj_priv->pin_count)
-		    avail++;
+		if (!reg->obj->pin_count)
+			avail = reg;
 	}
 
-	if (avail == 0)
-		return -ENOSPC;
+	if (avail == NULL)
+		return NULL;
 
 	/* None available, try to steal one or wait for a user to finish */
-	i = I915_FENCE_REG_NONE;
-	list_for_each_entry(reg, &dev_priv->mm.fence_list,
-			    lru_list) {
-		obj = reg->obj;
-		obj_priv = to_intel_bo(obj);
-
-		if (obj_priv->pin_count)
+	avail = first = NULL;
+	list_for_each_entry(reg, &dev_priv->mm.fence_list, lru_list) {
+		if (reg->obj->pin_count)
 			continue;
 
-		/* found one! */
-		i = obj_priv->fence_reg;
-		break;
-	}
+		if (first == NULL)
+			first = reg;
 
-	BUG_ON(i == I915_FENCE_REG_NONE);
+		if (!pipelined ||
+		    !reg->obj->last_fenced_ring ||
+		    reg->obj->last_fenced_ring == pipelined) {
+			avail = reg;
+			break;
+		}
+	}
 
-	/* We only have a reference on obj from the active list. put_fence_reg
-	 * might drop that one, causing a use-after-free in it. So hold a
-	 * private reference to obj like the other callers of put_fence_reg
-	 * (set_tiling ioctl) do. */
-	drm_gem_object_reference(obj);
-	ret = i915_gem_object_put_fence_reg(obj, interruptible);
-	drm_gem_object_unreference(obj);
-	if (ret != 0)
-		return ret;
+	if (avail == NULL)
+		avail = first;
 
-	return i;
+	return avail;
 }
 
 /**
- * i915_gem_object_get_fence_reg - set up a fence reg for an object
+ * i915_gem_object_get_fence - set up a fence reg for an object
  * @obj: object to map through a fence reg
+ * @pipelined: ring on which to queue the change, or NULL for CPU access
+ * @interruptible: must we wait uninterruptibly for the register to retire?
  *
  * When mapping objects through the GTT, userspace wants to be able to write
  * to them without having to worry about swizzling if the object is tiled.
@@ -2448,72 +2527,141 @@ static int i915_find_fence_reg(struct dr
  * and tiling format.
  */
 int
-i915_gem_object_get_fence_reg(struct drm_gem_object *obj,
-			      bool interruptible)
+i915_gem_object_get_fence(struct drm_i915_gem_object *obj,
+			  struct intel_ring_buffer *pipelined,
+			  bool interruptible)
 {
-	struct drm_device *dev = obj->dev;
+	struct drm_device *dev = obj->base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
-	struct drm_i915_fence_reg *reg = NULL;
+	struct drm_i915_fence_reg *reg;
 	int ret;
 
-	/* Just update our place in the LRU if our fence is getting used. */
-	if (obj_priv->fence_reg != I915_FENCE_REG_NONE) {
-		reg = &dev_priv->fence_regs[obj_priv->fence_reg];
+	/* XXX disable pipelining. There are bugs. Shocking. */
+	pipelined = NULL;
+
+	/* Just update our place in the LRU if our fence is getting reused. */
+	if (obj->fence_reg != I915_FENCE_REG_NONE) {
+		reg = &dev_priv->fence_regs[obj->fence_reg];
 		list_move_tail(&reg->lru_list, &dev_priv->mm.fence_list);
+
+		if (!obj->fenced_gpu_access && !obj->last_fenced_seqno)
+			pipelined = NULL;
+
+		if (!pipelined) {
+			if (reg->setup_seqno) {
+				if (!ring_passed_seqno(obj->last_fenced_ring,
+						       reg->setup_seqno)) {
+					ret = i915_do_wait_request(obj->base.dev,
+								   reg->setup_seqno,
+								   interruptible,
+								   obj->last_fenced_ring);
+					if (ret)
+						return ret;
+				}
+
+				reg->setup_seqno = 0;
+			}
+		} else if (obj->last_fenced_ring &&
+			   obj->last_fenced_ring != pipelined) {
+			ret = i915_gem_object_flush_fence(obj,
+							  pipelined,
+							  interruptible);
+			if (ret)
+				return ret;
+		} else if (obj->tiling_changed) {
+			if (obj->fenced_gpu_access) {
+				if (obj->base.write_domain & I915_GEM_GPU_DOMAINS) {
+					ret = i915_gem_flush_ring(obj->base.dev, obj->ring,
+								  0, obj->base.write_domain);
+					if (ret)
+						return ret;
+				}
+
+				obj->fenced_gpu_access = false;
+			}
+		}
+
+		if (!obj->fenced_gpu_access && !obj->last_fenced_seqno)
+			pipelined = NULL;
+		BUG_ON(!pipelined && reg->setup_seqno);
+
+		if (obj->tiling_changed) {
+			if (pipelined) {
+				reg->setup_seqno =
+					i915_gem_next_request_seqno(dev, pipelined);
+				obj->last_fenced_seqno = reg->setup_seqno;
+				obj->last_fenced_ring = pipelined;
+			}
+			goto update;
+		}
+
 		return 0;
 	}
 
-	switch (obj_priv->tiling_mode) {
-	case I915_TILING_NONE:
-		WARN(1, "allocating a fence for non-tiled object?\n");
-		break;
-	case I915_TILING_X:
-		if (!obj_priv->stride)
-			return -EINVAL;
-		WARN((obj_priv->stride & (512 - 1)),
-		     "object 0x%08x is X tiled but has non-512B pitch\n",
-		     obj_priv->gtt_offset);
-		break;
-	case I915_TILING_Y:
-		if (!obj_priv->stride)
-			return -EINVAL;
-		WARN((obj_priv->stride & (128 - 1)),
-		     "object 0x%08x is Y tiled but has non-128B pitch\n",
-		     obj_priv->gtt_offset);
-		break;
-	}
+	reg = i915_find_fence_reg(dev, pipelined);
+	if (reg == NULL)
+		return -ENOSPC;
 
-	ret = i915_find_fence_reg(dev, interruptible);
-	if (ret < 0)
+	ret = i915_gem_object_flush_fence(obj, pipelined, interruptible);
+	if (ret)
 		return ret;
 
-	obj_priv->fence_reg = ret;
-	reg = &dev_priv->fence_regs[obj_priv->fence_reg];
-	list_add_tail(&reg->lru_list, &dev_priv->mm.fence_list);
+	if (reg->obj) {
+		struct drm_i915_gem_object *old = reg->obj;
+
+		drm_gem_object_reference(&old->base);
+
+		if (old->tiling_mode)
+			i915_gem_release_mmap(old);
+
+		ret = i915_gem_object_flush_fence(old,
+						  pipelined,
+						  interruptible);
+		if (ret) {
+			drm_gem_object_unreference(&old->base);
+			return ret;
+		}
+
+		if (old->last_fenced_seqno == 0 && obj->last_fenced_seqno == 0)
+			pipelined = NULL;
+
+		old->fence_reg = I915_FENCE_REG_NONE;
+		old->last_fenced_ring = pipelined;
+		old->last_fenced_seqno =
+			pipelined ? i915_gem_next_request_seqno(dev, pipelined) : 0;
+
+		drm_gem_object_unreference(&old->base);
+	} else if (obj->last_fenced_seqno == 0)
+		pipelined = NULL;
 
 	reg->obj = obj;
+	list_move_tail(&reg->lru_list, &dev_priv->mm.fence_list);
+	obj->fence_reg = reg - dev_priv->fence_regs;
+	obj->last_fenced_ring = pipelined;
 
+	reg->setup_seqno =
+		pipelined ? i915_gem_next_request_seqno(dev, pipelined) : 0;
+	obj->last_fenced_seqno = reg->setup_seqno;
+
+update:
+	obj->tiling_changed = false;
 	switch (INTEL_INFO(dev)->gen) {
 	case 6:
-		sandybridge_write_fence_reg(reg);
+		ret = sandybridge_write_fence_reg(obj, pipelined);
 		break;
 	case 5:
 	case 4:
-		i965_write_fence_reg(reg);
+		ret = i965_write_fence_reg(obj, pipelined);
 		break;
 	case 3:
-		i915_write_fence_reg(reg);
+		ret = i915_write_fence_reg(obj, pipelined);
 		break;
 	case 2:
-		i830_write_fence_reg(reg);
+		ret = i830_write_fence_reg(obj, pipelined);
 		break;
 	}
 
-	trace_i915_gem_object_get_fence(obj, obj_priv->fence_reg,
-			obj_priv->tiling_mode);
-
-	return 0;
+	return ret;
 }
 
 /**
@@ -2521,154 +2669,125 @@ i915_gem_object_get_fence_reg(struct drm
  * @obj: object to clear
  *
  * Zeroes out the fence register itself and clears out the associated
- * data structures in dev_priv and obj_priv.
+ * data structures in dev_priv and obj.
  */
 static void
-i915_gem_clear_fence_reg(struct drm_gem_object *obj)
+i915_gem_clear_fence_reg(struct drm_device *dev,
+			 struct drm_i915_fence_reg *reg)
 {
-	struct drm_device *dev = obj->dev;
 	drm_i915_private_t *dev_priv = dev->dev_private;
-	struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
-	struct drm_i915_fence_reg *reg =
-		&dev_priv->fence_regs[obj_priv->fence_reg];
-	uint32_t fence_reg;
+	uint32_t fence_reg = reg - dev_priv->fence_regs;
 
 	switch (INTEL_INFO(dev)->gen) {
 	case 6:
-		I915_WRITE64(FENCE_REG_SANDYBRIDGE_0 +
-			     (obj_priv->fence_reg * 8), 0);
+		I915_WRITE64(FENCE_REG_SANDYBRIDGE_0 + fence_reg*8, 0);
 		break;
 	case 5:
 	case 4:
-		I915_WRITE64(FENCE_REG_965_0 + (obj_priv->fence_reg * 8), 0);
+		I915_WRITE64(FENCE_REG_965_0 + fence_reg*8, 0);
 		break;
 	case 3:
-		if (obj_priv->fence_reg >= 8)
-			fence_reg = FENCE_REG_945_8 + (obj_priv->fence_reg - 8) * 4;
+		if (fence_reg >= 8)
+			fence_reg = FENCE_REG_945_8 + (fence_reg - 8) * 4;
 		else
 	case 2:
-			fence_reg = FENCE_REG_830_0 + obj_priv->fence_reg * 4;
+			fence_reg = FENCE_REG_830_0 + fence_reg * 4;
 
 		I915_WRITE(fence_reg, 0);
 		break;
 	}
 
-	reg->obj = NULL;
-	obj_priv->fence_reg = I915_FENCE_REG_NONE;
 	list_del_init(&reg->lru_list);
-}
-
-/**
- * i915_gem_object_put_fence_reg - waits on outstanding fenced access
- * to the buffer to finish, and then resets the fence register.
- * @obj: tiled object holding a fence register.
- * @bool: whether the wait upon the fence is interruptible
- *
- * Zeroes out the fence register itself and clears out the associated
- * data structures in dev_priv and obj_priv.
- */
-int
-i915_gem_object_put_fence_reg(struct drm_gem_object *obj,
-			      bool interruptible)
-{
-	struct drm_device *dev = obj->dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
-	struct drm_i915_fence_reg *reg;
-
-	if (obj_priv->fence_reg == I915_FENCE_REG_NONE)
-		return 0;
-
-	/* If we've changed tiling, GTT-mappings of the object
-	 * need to re-fault to ensure that the correct fence register
-	 * setup is in place.
-	 */
-	i915_gem_release_mmap(obj);
-
-	/* On the i915, GPU access to tiled buffers is via a fence,
-	 * therefore we must wait for any outstanding access to complete
-	 * before clearing the fence.
-	 */
-	reg = &dev_priv->fence_regs[obj_priv->fence_reg];
-	if (reg->gpu) {
-		int ret;
-
-		ret = i915_gem_object_flush_gpu_write_domain(obj);
-		if (ret)
-			return ret;
-
-		ret = i915_gem_object_wait_rendering(obj, interruptible);
-		if (ret)
-			return ret;
-
-		reg->gpu = false;
-	}
-
-	i915_gem_object_flush_gtt_write_domain(obj);
-	i915_gem_clear_fence_reg(obj);
-
-	return 0;
+	reg->obj = NULL;
+	reg->setup_seqno = 0;
 }
 
 /**
  * Finds free space in the GTT aperture and binds the object there.
  */
 static int
-i915_gem_object_bind_to_gtt(struct drm_gem_object *obj, unsigned alignment)
+i915_gem_object_bind_to_gtt(struct drm_i915_gem_object *obj,
+			    unsigned alignment,
+			    bool map_and_fenceable)
 {
-	struct drm_device *dev = obj->dev;
+	struct drm_device *dev = obj->base.dev;
 	drm_i915_private_t *dev_priv = dev->dev_private;
-	struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
 	struct drm_mm_node *free_space;
-	gfp_t gfpmask =  __GFP_NORETRY | __GFP_NOWARN;
+	gfp_t gfpmask = __GFP_NORETRY | __GFP_NOWARN;
+	u32 size, fence_size, fence_alignment, unfenced_alignment;
+	bool mappable, fenceable;
 	int ret;
 
-	if (obj_priv->madv != I915_MADV_WILLNEED) {
+	if (obj->madv != I915_MADV_WILLNEED) {
 		DRM_ERROR("Attempting to bind a purgeable object\n");
 		return -EINVAL;
 	}
 
+	fence_size = i915_gem_get_gtt_size(obj);
+	fence_alignment = i915_gem_get_gtt_alignment(obj);
+	unfenced_alignment = i915_gem_get_unfenced_gtt_alignment(obj);
+
 	if (alignment == 0)
-		alignment = i915_gem_get_gtt_alignment(obj);
-	if (alignment & (i915_gem_get_gtt_alignment(obj) - 1)) {
+		alignment = map_and_fenceable ? fence_alignment :
+						unfenced_alignment;
+	if (map_and_fenceable && alignment & (fence_alignment - 1)) {
 		DRM_ERROR("Invalid object alignment requested %u\n", alignment);
 		return -EINVAL;
 	}
 
+	size = map_and_fenceable ? fence_size : obj->base.size;
+
 	/* If the object is bigger than the entire aperture, reject it early
 	 * before evicting everything in a vain attempt to find space.
 	 */
-	if (obj->size > dev_priv->mm.gtt_total) {
+	if (obj->base.size >
+	    (map_and_fenceable ? dev_priv->mm.gtt_mappable_end : dev_priv->mm.gtt_total)) {
 		DRM_ERROR("Attempting to bind an object larger than the aperture\n");
 		return -E2BIG;
 	}
 
  search_free:
-	free_space = drm_mm_search_free(&dev_priv->mm.gtt_space,
-					obj->size, alignment, 0);
-	if (free_space != NULL)
-		obj_priv->gtt_space = drm_mm_get_block(free_space, obj->size,
-						       alignment);
-	if (obj_priv->gtt_space == NULL) {
+	if (map_and_fenceable)
+		free_space =
+			drm_mm_search_free_in_range(&dev_priv->mm.gtt_space,
+						    size, alignment, 0,
+						    dev_priv->mm.gtt_mappable_end,
+						    0);
+	else
+		free_space = drm_mm_search_free(&dev_priv->mm.gtt_space,
+						size, alignment, 0);
+
+	if (free_space != NULL) {
+		if (map_and_fenceable)
+			obj->gtt_space =
+				drm_mm_get_block_range_generic(free_space,
+							       size, alignment, 0,
+							       dev_priv->mm.gtt_mappable_end,
+							       0);
+		else
+			obj->gtt_space =
+				drm_mm_get_block(free_space, size, alignment);
+	}
+	if (obj->gtt_space == NULL) {
 		/* If the gtt is empty and we're still having trouble
 		 * fitting our object in, we're out of memory.
 		 */
-		ret = i915_gem_evict_something(dev, obj->size, alignment);
+		ret = i915_gem_evict_something(dev, size, alignment,
+					       map_and_fenceable);
 		if (ret)
 			return ret;
 
 		goto search_free;
 	}
 
-	ret = i915_gem_object_get_pages(obj, gfpmask);
+	ret = i915_gem_object_get_pages_gtt(obj, gfpmask);
 	if (ret) {
-		drm_mm_put_block(obj_priv->gtt_space);
-		obj_priv->gtt_space = NULL;
+		drm_mm_put_block(obj->gtt_space);
+		obj->gtt_space = NULL;
 
 		if (ret == -ENOMEM) {
-			/* first try to clear up some space from the GTT */
-			ret = i915_gem_evict_something(dev, obj->size,
-						       alignment);
+			/* first try to reclaim some memory by clearing the GTT */
+			ret = i915_gem_evict_everything(dev, false);
 			if (ret) {
 				/* now try to shrink everyone else */
 				if (gfpmask) {
@@ -2676,7 +2795,7 @@ i915_gem_object_bind_to_gtt(struct drm_g
 					goto search_free;
 				}
 
-				return ret;
+				return -ENOMEM;
 			}
 
 			goto search_free;
@@ -2685,122 +2804,116 @@ i915_gem_object_bind_to_gtt(struct drm_g
 		return ret;
 	}
 
-	/* Create an AGP memory structure pointing at our pages, and bind it
-	 * into the GTT.
-	 */
-	obj_priv->agp_mem = drm_agp_bind_pages(dev,
-					       obj_priv->pages,
-					       obj->size >> PAGE_SHIFT,
-					       obj_priv->gtt_space->start,
-					       obj_priv->agp_type);
-	if (obj_priv->agp_mem == NULL) {
-		i915_gem_object_put_pages(obj);
-		drm_mm_put_block(obj_priv->gtt_space);
-		obj_priv->gtt_space = NULL;
+	ret = i915_gem_gtt_bind_object(obj);
+	if (ret) {
+		i915_gem_object_put_pages_gtt(obj);
+		drm_mm_put_block(obj->gtt_space);
+		obj->gtt_space = NULL;
 
-		ret = i915_gem_evict_something(dev, obj->size, alignment);
-		if (ret)
+		if (i915_gem_evict_everything(dev, false))
 			return ret;
 
 		goto search_free;
 	}
 
-	/* keep track of bounds object by adding it to the inactive list */
-	list_add_tail(&obj_priv->mm_list, &dev_priv->mm.inactive_list);
-	i915_gem_info_add_gtt(dev_priv, obj->size);
+	list_add_tail(&obj->gtt_list, &dev_priv->mm.gtt_list);
+	list_add_tail(&obj->mm_list, &dev_priv->mm.inactive_list);
 
 	/* Assert that the object is not currently in any GPU domain. As it
 	 * wasn't in the GTT, there shouldn't be any way it could have been in
 	 * a GPU cache
 	 */
-	BUG_ON(obj->read_domains & I915_GEM_GPU_DOMAINS);
-	BUG_ON(obj->write_domain & I915_GEM_GPU_DOMAINS);
+	BUG_ON(obj->base.read_domains & I915_GEM_GPU_DOMAINS);
+	BUG_ON(obj->base.write_domain & I915_GEM_GPU_DOMAINS);
 
-	obj_priv->gtt_offset = obj_priv->gtt_space->start;
-	trace_i915_gem_object_bind(obj, obj_priv->gtt_offset);
+	obj->gtt_offset = obj->gtt_space->start;
+
+	fenceable =
+		obj->gtt_space->size == fence_size &&
+		(obj->gtt_space->start & (fence_alignment -1)) == 0;
+
+	mappable =
+		obj->gtt_offset + obj->base.size <= dev_priv->mm.gtt_mappable_end;
 
+	obj->map_and_fenceable = mappable && fenceable;
+
+	trace_i915_gem_object_bind(obj, obj->gtt_offset, map_and_fenceable);
 	return 0;
 }
 
 void
-i915_gem_clflush_object(struct drm_gem_object *obj)
+i915_gem_clflush_object(struct drm_i915_gem_object *obj)
 {
-	struct drm_i915_gem_object	*obj_priv = to_intel_bo(obj);
-
 	/* If we don't have a page list set up, then we're not pinned
 	 * to GPU, and we can ignore the cache flush because it'll happen
 	 * again at bind time.
 	 */
-	if (obj_priv->pages == NULL)
+	if (obj->pages == NULL)
 		return;
 
 	trace_i915_gem_object_clflush(obj);
 
-	drm_clflush_pages(obj_priv->pages, obj->size / PAGE_SIZE);
+	drm_clflush_pages(obj->pages, obj->base.size / PAGE_SIZE);
 }
 
 /** Flushes any GPU write domain for the object if it's dirty. */
 static int
-i915_gem_object_flush_gpu_write_domain(struct drm_gem_object *obj)
+i915_gem_object_flush_gpu_write_domain(struct drm_i915_gem_object *obj)
 {
-	struct drm_device *dev = obj->dev;
-	uint32_t old_write_domain;
+	struct drm_device *dev = obj->base.dev;
 
-	if ((obj->write_domain & I915_GEM_GPU_DOMAINS) == 0)
+	if ((obj->base.write_domain & I915_GEM_GPU_DOMAINS) == 0)
 		return 0;
 
 	/* Queue the GPU write cache flushing we need. */
-	old_write_domain = obj->write_domain;
-	i915_gem_flush_ring(dev, NULL,
-			    to_intel_bo(obj)->ring,
-			    0, obj->write_domain);
-	BUG_ON(obj->write_domain);
-
-	trace_i915_gem_object_change_domain(obj,
-					    obj->read_domains,
-					    old_write_domain);
-
-	return 0;
+	return i915_gem_flush_ring(dev, obj->ring, 0, obj->base.write_domain);
 }
 
 /** Flushes the GTT write domain for the object if it's dirty. */
 static void
-i915_gem_object_flush_gtt_write_domain(struct drm_gem_object *obj)
+i915_gem_object_flush_gtt_write_domain(struct drm_i915_gem_object *obj)
 {
 	uint32_t old_write_domain;
 
-	if (obj->write_domain != I915_GEM_DOMAIN_GTT)
+	if (obj->base.write_domain != I915_GEM_DOMAIN_GTT)
 		return;
 
-	/* No actual flushing is required for the GTT write domain.   Writes
+	/* No actual flushing is required for the GTT write domain.  Writes
 	 * to it immediately go to main memory as far as we know, so there's
 	 * no chipset flush.  It also doesn't land in render cache.
+	 *
+	 * However, we do have to enforce the order so that all writes through
+	 * the GTT land before any writes to the device, such as updates to
+	 * the GATT itself.
 	 */
-	old_write_domain = obj->write_domain;
-	obj->write_domain = 0;
+	wmb();
+
+	i915_gem_release_mmap(obj);
+
+	old_write_domain = obj->base.write_domain;
+	obj->base.write_domain = 0;
 
 	trace_i915_gem_object_change_domain(obj,
-					    obj->read_domains,
+					    obj->base.read_domains,
 					    old_write_domain);
 }
 
 /** Flushes the CPU write domain for the object if it's dirty. */
 static void
-i915_gem_object_flush_cpu_write_domain(struct drm_gem_object *obj)
+i915_gem_object_flush_cpu_write_domain(struct drm_i915_gem_object *obj)
 {
-	struct drm_device *dev = obj->dev;
 	uint32_t old_write_domain;
 
-	if (obj->write_domain != I915_GEM_DOMAIN_CPU)
+	if (obj->base.write_domain != I915_GEM_DOMAIN_CPU)
 		return;
 
 	i915_gem_clflush_object(obj);
-	drm_agp_chipset_flush(dev);
-	old_write_domain = obj->write_domain;
-	obj->write_domain = 0;
+	intel_gtt_chipset_flush();
+	old_write_domain = obj->base.write_domain;
+	obj->base.write_domain = 0;
 
 	trace_i915_gem_object_change_domain(obj,
-					    obj->read_domains,
+					    obj->base.read_domains,
 					    old_write_domain);
 }
 
@@ -2811,37 +2924,39 @@ i915_gem_object_flush_cpu_write_domain(s
  * flushes to occur.
  */
 int
-i915_gem_object_set_to_gtt_domain(struct drm_gem_object *obj, int write)
+i915_gem_object_set_to_gtt_domain(struct drm_i915_gem_object *obj, bool write)
 {
-	struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
 	uint32_t old_write_domain, old_read_domains;
 	int ret;
 
 	/* Not valid to be called on unbound objects. */
-	if (obj_priv->gtt_space == NULL)
+	if (obj->gtt_space == NULL)
 		return -EINVAL;
 
 	ret = i915_gem_object_flush_gpu_write_domain(obj);
-	if (ret != 0)
-		return ret;
-	ret = i915_gem_object_wait_rendering(obj, true);
 	if (ret)
 		return ret;
 
+	if (obj->pending_gpu_write || write) {
+		ret = i915_gem_object_wait_rendering(obj, true);
+		if (ret)
+			return ret;
+	}
+
 	i915_gem_object_flush_cpu_write_domain(obj);
 
-	old_write_domain = obj->write_domain;
-	old_read_domains = obj->read_domains;
+	old_write_domain = obj->base.write_domain;
+	old_read_domains = obj->base.read_domains;
 
 	/* It should now be out of any other write domains, and we can update
 	 * the domain values for our changes.
 	 */
-	BUG_ON((obj->write_domain & ~I915_GEM_DOMAIN_GTT) != 0);
-	obj->read_domains |= I915_GEM_DOMAIN_GTT;
+	BUG_ON((obj->base.write_domain & ~I915_GEM_DOMAIN_GTT) != 0);
+	obj->base.read_domains |= I915_GEM_DOMAIN_GTT;
 	if (write) {
-		obj->read_domains = I915_GEM_DOMAIN_GTT;
-		obj->write_domain = I915_GEM_DOMAIN_GTT;
-		obj_priv->dirty = 1;
+		obj->base.read_domains = I915_GEM_DOMAIN_GTT;
+		obj->base.write_domain = I915_GEM_DOMAIN_GTT;
+		obj->dirty = 1;
 	}
 
 	trace_i915_gem_object_change_domain(obj,
@@ -2856,23 +2971,23 @@ i915_gem_object_set_to_gtt_domain(struct
  * wait, as in modesetting process we're not supposed to be interrupted.
  */
 int
-i915_gem_object_set_to_display_plane(struct drm_gem_object *obj,
-				     bool pipelined)
+i915_gem_object_set_to_display_plane(struct drm_i915_gem_object *obj,
+				     struct intel_ring_buffer *pipelined)
 {
-	struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
 	uint32_t old_read_domains;
 	int ret;
 
 	/* Not valid to be called on unbound objects. */
-	if (obj_priv->gtt_space == NULL)
+	if (obj->gtt_space == NULL)
 		return -EINVAL;
 
 	ret = i915_gem_object_flush_gpu_write_domain(obj);
 	if (ret)
 		return ret;
 
+
 	/* Currently, we are always called from an non-interruptible context. */
-	if (!pipelined) {
+	if (pipelined != obj->ring) {
 		ret = i915_gem_object_wait_rendering(obj, false);
 		if (ret)
 			return ret;
@@ -2880,12 +2995,12 @@ i915_gem_object_set_to_display_plane(str
 
 	i915_gem_object_flush_cpu_write_domain(obj);
 
-	old_read_domains = obj->read_domains;
-	obj->read_domains |= I915_GEM_DOMAIN_GTT;
+	old_read_domains = obj->base.read_domains;
+	obj->base.read_domains |= I915_GEM_DOMAIN_GTT;
 
 	trace_i915_gem_object_change_domain(obj,
 					    old_read_domains,
-					    obj->write_domain);
+					    obj->base.write_domain);
 
 	return 0;
 }
@@ -2894,14 +3009,19 @@ int
 i915_gem_object_flush_gpu(struct drm_i915_gem_object *obj,
 			  bool interruptible)
 {
+	int ret;
+
 	if (!obj->active)
 		return 0;
 
-	if (obj->base.write_domain & I915_GEM_GPU_DOMAINS)
-		i915_gem_flush_ring(obj->base.dev, NULL, obj->ring,
-				    0, obj->base.write_domain);
+	if (obj->base.write_domain & I915_GEM_GPU_DOMAINS) {
+		ret = i915_gem_flush_ring(obj->base.dev, obj->ring,
+					  0, obj->base.write_domain);
+		if (ret)
+			return ret;
+	}
 
-	return i915_gem_object_wait_rendering(&obj->base, interruptible);
+	return i915_gem_object_wait_rendering(obj, interruptible);
 }
 
 /**
@@ -2911,14 +3031,15 @@ i915_gem_object_flush_gpu(struct drm_i91
  * flushes to occur.
  */
 static int
-i915_gem_object_set_to_cpu_domain(struct drm_gem_object *obj, int write)
+i915_gem_object_set_to_cpu_domain(struct drm_i915_gem_object *obj, bool write)
 {
 	uint32_t old_write_domain, old_read_domains;
 	int ret;
 
 	ret = i915_gem_object_flush_gpu_write_domain(obj);
-	if (ret != 0)
+	if (ret)
 		return ret;
+
 	ret = i915_gem_object_wait_rendering(obj, true);
 	if (ret)
 		return ret;
@@ -2930,27 +3051,27 @@ i915_gem_object_set_to_cpu_domain(struct
 	 */
 	i915_gem_object_set_to_full_cpu_read_domain(obj);
 
-	old_write_domain = obj->write_domain;
-	old_read_domains = obj->read_domains;
+	old_write_domain = obj->base.write_domain;
+	old_read_domains = obj->base.read_domains;
 
 	/* Flush the CPU cache if it's still invalid. */
-	if ((obj->read_domains & I915_GEM_DOMAIN_CPU) == 0) {
+	if ((obj->base.read_domains & I915_GEM_DOMAIN_CPU) == 0) {
 		i915_gem_clflush_object(obj);
 
-		obj->read_domains |= I915_GEM_DOMAIN_CPU;
+		obj->base.read_domains |= I915_GEM_DOMAIN_CPU;
 	}
 
 	/* It should now be out of any other write domains, and we can update
 	 * the domain values for our changes.
 	 */
-	BUG_ON((obj->write_domain & ~I915_GEM_DOMAIN_CPU) != 0);
+	BUG_ON((obj->base.write_domain & ~I915_GEM_DOMAIN_CPU) != 0);
 
 	/* If we're writing through the CPU, then the GPU read domains will
 	 * need to be invalidated at next use.
 	 */
 	if (write) {
-		obj->read_domains = I915_GEM_DOMAIN_CPU;
-		obj->write_domain = I915_GEM_DOMAIN_CPU;
+		obj->base.read_domains = I915_GEM_DOMAIN_CPU;
+		obj->base.write_domain = I915_GEM_DOMAIN_CPU;
 	}
 
 	trace_i915_gem_object_change_domain(obj,
@@ -2960,184 +3081,6 @@ i915_gem_object_set_to_cpu_domain(struct
 	return 0;
 }
 
-/*
- * Set the next domain for the specified object. This
- * may not actually perform the necessary flushing/invaliding though,
- * as that may want to be batched with other set_domain operations
- *
- * This is (we hope) the only really tricky part of gem. The goal
- * is fairly simple -- track which caches hold bits of the object
- * and make sure they remain coherent. A few concrete examples may
- * help to explain how it works. For shorthand, we use the notation
- * (read_domains, write_domain), e.g. (CPU, CPU) to indicate the
- * a pair of read and write domain masks.
- *
- * Case 1: the batch buffer
- *
- *	1. Allocated
- *	2. Written by CPU
- *	3. Mapped to GTT
- *	4. Read by GPU
- *	5. Unmapped from GTT
- *	6. Freed
- *
- *	Let's take these a step at a time
- *
- *	1. Allocated
- *		Pages allocated from the kernel may still have
- *		cache contents, so we set them to (CPU, CPU) always.
- *	2. Written by CPU (using pwrite)
- *		The pwrite function calls set_domain (CPU, CPU) and
- *		this function does nothing (as nothing changes)
- *	3. Mapped by GTT
- *		This function asserts that the object is not
- *		currently in any GPU-based read or write domains
- *	4. Read by GPU
- *		i915_gem_execbuffer calls set_domain (COMMAND, 0).
- *		As write_domain is zero, this function adds in the
- *		current read domains (CPU+COMMAND, 0).
- *		flush_domains is set to CPU.
- *		invalidate_domains is set to COMMAND
- *		clflush is run to get data out of the CPU caches
- *		then i915_dev_set_domain calls i915_gem_flush to
- *		emit an MI_FLUSH and drm_agp_chipset_flush
- *	5. Unmapped from GTT
- *		i915_gem_object_unbind calls set_domain (CPU, CPU)
- *		flush_domains and invalidate_domains end up both zero
- *		so no flushing/invalidating happens
- *	6. Freed
- *		yay, done
- *
- * Case 2: The shared render buffer
- *
- *	1. Allocated
- *	2. Mapped to GTT
- *	3. Read/written by GPU
- *	4. set_domain to (CPU,CPU)
- *	5. Read/written by CPU
- *	6. Read/written by GPU
- *
- *	1. Allocated
- *		Same as last example, (CPU, CPU)
- *	2. Mapped to GTT
- *		Nothing changes (assertions find that it is not in the GPU)
- *	3. Read/written by GPU
- *		execbuffer calls set_domain (RENDER, RENDER)
- *		flush_domains gets CPU
- *		invalidate_domains gets GPU
- *		clflush (obj)
- *		MI_FLUSH and drm_agp_chipset_flush
- *	4. set_domain (CPU, CPU)
- *		flush_domains gets GPU
- *		invalidate_domains gets CPU
- *		wait_rendering (obj) to make sure all drawing is complete.
- *		This will include an MI_FLUSH to get the data from GPU
- *		to memory
- *		clflush (obj) to invalidate the CPU cache
- *		Another MI_FLUSH in i915_gem_flush (eliminate this somehow?)
- *	5. Read/written by CPU
- *		cache lines are loaded and dirtied
- *	6. Read written by GPU
- *		Same as last GPU access
- *
- * Case 3: The constant buffer
- *
- *	1. Allocated
- *	2. Written by CPU
- *	3. Read by GPU
- *	4. Updated (written) by CPU again
- *	5. Read by GPU
- *
- *	1. Allocated
- *		(CPU, CPU)
- *	2. Written by CPU
- *		(CPU, CPU)
- *	3. Read by GPU
- *		(CPU+RENDER, 0)
- *		flush_domains = CPU
- *		invalidate_domains = RENDER
- *		clflush (obj)
- *		MI_FLUSH
- *		drm_agp_chipset_flush
- *	4. Updated (written) by CPU again
- *		(CPU, CPU)
- *		flush_domains = 0 (no previous write domain)
- *		invalidate_domains = 0 (no new read domains)
- *	5. Read by GPU
- *		(CPU+RENDER, 0)
- *		flush_domains = CPU
- *		invalidate_domains = RENDER
- *		clflush (obj)
- *		MI_FLUSH
- *		drm_agp_chipset_flush
- */
-static void
-i915_gem_object_set_to_gpu_domain(struct drm_gem_object *obj,
-				  struct intel_ring_buffer *ring)
-{
-	struct drm_device		*dev = obj->dev;
-	struct drm_i915_private		*dev_priv = dev->dev_private;
-	struct drm_i915_gem_object	*obj_priv = to_intel_bo(obj);
-	uint32_t			invalidate_domains = 0;
-	uint32_t			flush_domains = 0;
-	uint32_t			old_read_domains;
-
-	intel_mark_busy(dev, obj);
-
-	/*
-	 * If the object isn't moving to a new write domain,
-	 * let the object stay in multiple read domains
-	 */
-	if (obj->pending_write_domain == 0)
-		obj->pending_read_domains |= obj->read_domains;
-	else
-		obj_priv->dirty = 1;
-
-	/*
-	 * Flush the current write domain if
-	 * the new read domains don't match. Invalidate
-	 * any read domains which differ from the old
-	 * write domain
-	 */
-	if (obj->write_domain &&
-	    (obj->write_domain != obj->pending_read_domains ||
-	     obj_priv->ring != ring)) {
-		flush_domains |= obj->write_domain;
-		invalidate_domains |=
-			obj->pending_read_domains & ~obj->write_domain;
-	}
-	/*
-	 * Invalidate any read caches which may have
-	 * stale data. That is, any new read domains.
-	 */
-	invalidate_domains |= obj->pending_read_domains & ~obj->read_domains;
-	if ((flush_domains | invalidate_domains) & I915_GEM_DOMAIN_CPU)
-		i915_gem_clflush_object(obj);
-
-	old_read_domains = obj->read_domains;
-
-	/* The actual obj->write_domain will be updated with
-	 * pending_write_domain after we emit the accumulated flush for all
-	 * of our domain changes in execbuffers (which clears objects'
-	 * write_domains).  So if we have a current write domain that we
-	 * aren't changing, set pending_write_domain to that.
-	 */
-	if (flush_domains == 0 && obj->pending_write_domain == 0)
-		obj->pending_write_domain = obj->write_domain;
-	obj->read_domains = obj->pending_read_domains;
-
-	dev->invalidate_domains |= invalidate_domains;
-	dev->flush_domains |= flush_domains;
-	if (flush_domains & I915_GEM_GPU_DOMAINS)
-		dev_priv->mm.flush_rings |= obj_priv->ring->id;
-	if (invalidate_domains & I915_GEM_GPU_DOMAINS)
-		dev_priv->mm.flush_rings |= ring->id;
-
-	trace_i915_gem_object_change_domain(obj,
-					    old_read_domains,
-					    obj->write_domain);
-}
-
 /**
  * Moves the object from a partially CPU read to a full one.
  *
@@ -3145,30 +3088,28 @@ i915_gem_object_set_to_gpu_domain(struct
  * and doesn't handle transitioning from !(read_domains & I915_GEM_DOMAIN_CPU).
  */
 static void
-i915_gem_object_set_to_full_cpu_read_domain(struct drm_gem_object *obj)
+i915_gem_object_set_to_full_cpu_read_domain(struct drm_i915_gem_object *obj)
 {
-	struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
-
-	if (!obj_priv->page_cpu_valid)
+	if (!obj->page_cpu_valid)
 		return;
 
 	/* If we're partially in the CPU read domain, finish moving it in.
 	 */
-	if (obj->read_domains & I915_GEM_DOMAIN_CPU) {
+	if (obj->base.read_domains & I915_GEM_DOMAIN_CPU) {
 		int i;
 
-		for (i = 0; i <= (obj->size - 1) / PAGE_SIZE; i++) {
-			if (obj_priv->page_cpu_valid[i])
+		for (i = 0; i <= (obj->base.size - 1) / PAGE_SIZE; i++) {
+			if (obj->page_cpu_valid[i])
 				continue;
-			drm_clflush_pages(obj_priv->pages + i, 1);
+			drm_clflush_pages(obj->pages + i, 1);
 		}
 	}
 
 	/* Free the page_cpu_valid mappings which are now stale, whether
 	 * or not we've got I915_GEM_DOMAIN_CPU.
 	 */
-	kfree(obj_priv->page_cpu_valid);
-	obj_priv->page_cpu_valid = NULL;
+	kfree(obj->page_cpu_valid);
+	obj->page_cpu_valid = NULL;
 }
 
 /**
@@ -3184,19 +3125,19 @@ i915_gem_object_set_to_full_cpu_read_dom
  * flushes to occur.
  */
 static int
-i915_gem_object_set_cpu_read_domain_range(struct drm_gem_object *obj,
+i915_gem_object_set_cpu_read_domain_range(struct drm_i915_gem_object *obj,
 					  uint64_t offset, uint64_t size)
 {
-	struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
 	uint32_t old_read_domains;
 	int i, ret;
 
-	if (offset == 0 && size == obj->size)
+	if (offset == 0 && size == obj->base.size)
 		return i915_gem_object_set_to_cpu_domain(obj, 0);
 
 	ret = i915_gem_object_flush_gpu_write_domain(obj);
-	if (ret != 0)
+	if (ret)
 		return ret;
+
 	ret = i915_gem_object_wait_rendering(obj, true);
 	if (ret)
 		return ret;
@@ -3204,457 +3145,45 @@ i915_gem_object_set_cpu_read_domain_rang
 	i915_gem_object_flush_gtt_write_domain(obj);
 
 	/* If we're already fully in the CPU read domain, we're done. */
-	if (obj_priv->page_cpu_valid == NULL &&
-	    (obj->read_domains & I915_GEM_DOMAIN_CPU) != 0)
+	if (obj->page_cpu_valid == NULL &&
+	    (obj->base.read_domains & I915_GEM_DOMAIN_CPU) != 0)
 		return 0;
 
 	/* Otherwise, create/clear the per-page CPU read domain flag if we're
 	 * newly adding I915_GEM_DOMAIN_CPU
 	 */
-	if (obj_priv->page_cpu_valid == NULL) {
-		obj_priv->page_cpu_valid = kzalloc(obj->size / PAGE_SIZE,
-						   GFP_KERNEL);
-		if (obj_priv->page_cpu_valid == NULL)
+	if (obj->page_cpu_valid == NULL) {
+		obj->page_cpu_valid = kzalloc(obj->base.size / PAGE_SIZE,
+					      GFP_KERNEL);
+		if (obj->page_cpu_valid == NULL)
 			return -ENOMEM;
-	} else if ((obj->read_domains & I915_GEM_DOMAIN_CPU) == 0)
-		memset(obj_priv->page_cpu_valid, 0, obj->size / PAGE_SIZE);
+	} else if ((obj->base.read_domains & I915_GEM_DOMAIN_CPU) == 0)
+		memset(obj->page_cpu_valid, 0, obj->base.size / PAGE_SIZE);
 
 	/* Flush the cache on any pages that are still invalid from the CPU's
 	 * perspective.
 	 */
 	for (i = offset / PAGE_SIZE; i <= (offset + size - 1) / PAGE_SIZE;
 	     i++) {
-		if (obj_priv->page_cpu_valid[i])
+		if (obj->page_cpu_valid[i])
 			continue;
 
-		drm_clflush_pages(obj_priv->pages + i, 1);
+		drm_clflush_pages(obj->pages + i, 1);
 
-		obj_priv->page_cpu_valid[i] = 1;
+		obj->page_cpu_valid[i] = 1;
 	}
 
 	/* It should now be out of any other write domains, and we can update
 	 * the domain values for our changes.
 	 */
-	BUG_ON((obj->write_domain & ~I915_GEM_DOMAIN_CPU) != 0);
+	BUG_ON((obj->base.write_domain & ~I915_GEM_DOMAIN_CPU) != 0);
 
-	old_read_domains = obj->read_domains;
-	obj->read_domains |= I915_GEM_DOMAIN_CPU;
+	old_read_domains = obj->base.read_domains;
+	obj->base.read_domains |= I915_GEM_DOMAIN_CPU;
 
 	trace_i915_gem_object_change_domain(obj,
 					    old_read_domains,
-					    obj->write_domain);
-
-	return 0;
-}
-
-static int
-i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj,
-				   struct drm_file *file_priv,
-				   struct drm_i915_gem_exec_object2 *entry,
-				   struct drm_i915_gem_relocation_entry *reloc)
-{
-	struct drm_device *dev = obj->base.dev;
-	struct drm_gem_object *target_obj;
-	uint32_t target_offset;
-	int ret = -EINVAL;
-
-	target_obj = drm_gem_object_lookup(dev, file_priv,
-					   reloc->target_handle);
-	if (target_obj == NULL)
-		return -ENOENT;
-
-	target_offset = to_intel_bo(target_obj)->gtt_offset;
-
-#if WATCH_RELOC
-	DRM_INFO("%s: obj %p offset %08x target %d "
-		 "read %08x write %08x gtt %08x "
-		 "presumed %08x delta %08x\n",
-		 __func__,
-		 obj,
-		 (int) reloc->offset,
-		 (int) reloc->target_handle,
-		 (int) reloc->read_domains,
-		 (int) reloc->write_domain,
-		 (int) target_offset,
-		 (int) reloc->presumed_offset,
-		 reloc->delta);
-#endif
-
-	/* The target buffer should have appeared before us in the
-	 * exec_object list, so it should have a GTT space bound by now.
-	 */
-	if (target_offset == 0) {
-		DRM_ERROR("No GTT space found for object %d\n",
-			  reloc->target_handle);
-		goto err;
-	}
-
-	/* Validate that the target is in a valid r/w GPU domain */
-	if (reloc->write_domain & (reloc->write_domain - 1)) {
-		DRM_ERROR("reloc with multiple write domains: "
-			  "obj %p target %d offset %d "
-			  "read %08x write %08x",
-			  obj, reloc->target_handle,
-			  (int) reloc->offset,
-			  reloc->read_domains,
-			  reloc->write_domain);
-		goto err;
-	}
-	if (reloc->write_domain & I915_GEM_DOMAIN_CPU ||
-	    reloc->read_domains & I915_GEM_DOMAIN_CPU) {
-		DRM_ERROR("reloc with read/write CPU domains: "
-			  "obj %p target %d offset %d "
-			  "read %08x write %08x",
-			  obj, reloc->target_handle,
-			  (int) reloc->offset,
-			  reloc->read_domains,
-			  reloc->write_domain);
-		goto err;
-	}
-	if (reloc->write_domain && target_obj->pending_write_domain &&
-	    reloc->write_domain != target_obj->pending_write_domain) {
-		DRM_ERROR("Write domain conflict: "
-			  "obj %p target %d offset %d "
-			  "new %08x old %08x\n",
-			  obj, reloc->target_handle,
-			  (int) reloc->offset,
-			  reloc->write_domain,
-			  target_obj->pending_write_domain);
-		goto err;
-	}
-
-	target_obj->pending_read_domains |= reloc->read_domains;
-	target_obj->pending_write_domain |= reloc->write_domain;
-
-	/* If the relocation already has the right value in it, no
-	 * more work needs to be done.
-	 */
-	if (target_offset == reloc->presumed_offset)
-		goto out;
-
-	/* Check that the relocation address is valid... */
-	if (reloc->offset > obj->base.size - 4) {
-		DRM_ERROR("Relocation beyond object bounds: "
-			  "obj %p target %d offset %d size %d.\n",
-			  obj, reloc->target_handle,
-			  (int) reloc->offset,
-			  (int) obj->base.size);
-		goto err;
-	}
-	if (reloc->offset & 3) {
-		DRM_ERROR("Relocation not 4-byte aligned: "
-			  "obj %p target %d offset %d.\n",
-			  obj, reloc->target_handle,
-			  (int) reloc->offset);
-		goto err;
-	}
-
-	/* and points to somewhere within the target object. */
-	if (reloc->delta >= target_obj->size) {
-		DRM_ERROR("Relocation beyond target object bounds: "
-			  "obj %p target %d delta %d size %d.\n",
-			  obj, reloc->target_handle,
-			  (int) reloc->delta,
-			  (int) target_obj->size);
-		goto err;
-	}
-
-	reloc->delta += target_offset;
-	if (obj->base.write_domain == I915_GEM_DOMAIN_CPU) {
-		uint32_t page_offset = reloc->offset & ~PAGE_MASK;
-		char *vaddr;
-
-		vaddr = kmap_atomic(obj->pages[reloc->offset >> PAGE_SHIFT]);
-		*(uint32_t *)(vaddr + page_offset) = reloc->delta;
-		kunmap_atomic(vaddr);
-	} else {
-		struct drm_i915_private *dev_priv = dev->dev_private;
-		uint32_t __iomem *reloc_entry;
-		void __iomem *reloc_page;
-
-		ret = i915_gem_object_set_to_gtt_domain(&obj->base, 1);
-		if (ret)
-			goto err;
-
-		/* Map the page containing the relocation we're going to perform.  */
-		reloc->offset += obj->gtt_offset;
-		reloc_page = io_mapping_map_atomic_wc(dev_priv->mm.gtt_mapping,
-						      reloc->offset & PAGE_MASK);
-		reloc_entry = (uint32_t __iomem *)
-			(reloc_page + (reloc->offset & ~PAGE_MASK));
-		iowrite32(reloc->delta, reloc_entry);
-		io_mapping_unmap_atomic(reloc_page);
-	}
-
-	/* and update the user's relocation entry */
-	reloc->presumed_offset = target_offset;
-
-out:
-	ret = 0;
-err:
-	drm_gem_object_unreference(target_obj);
-	return ret;
-}
-
-static int
-i915_gem_execbuffer_relocate_object(struct drm_i915_gem_object *obj,
-				    struct drm_file *file_priv,
-				    struct drm_i915_gem_exec_object2 *entry)
-{
-	struct drm_i915_gem_relocation_entry __user *user_relocs;
-	int i, ret;
-
-	user_relocs = (void __user *)(uintptr_t)entry->relocs_ptr;
-	for (i = 0; i < entry->relocation_count; i++) {
-		struct drm_i915_gem_relocation_entry reloc;
-
-		if (__copy_from_user_inatomic(&reloc,
-					      user_relocs+i,
-					      sizeof(reloc)))
-			return -EFAULT;
-
-		ret = i915_gem_execbuffer_relocate_entry(obj, file_priv, entry, &reloc);
-		if (ret)
-			return ret;
-
-		if (__copy_to_user_inatomic(&user_relocs[i].presumed_offset,
-					    &reloc.presumed_offset,
-					    sizeof(reloc.presumed_offset)))
-			return -EFAULT;
-	}
-
-	return 0;
-}
-
-static int
-i915_gem_execbuffer_relocate_object_slow(struct drm_i915_gem_object *obj,
-					 struct drm_file *file_priv,
-					 struct drm_i915_gem_exec_object2 *entry,
-					 struct drm_i915_gem_relocation_entry *relocs)
-{
-	int i, ret;
-
-	for (i = 0; i < entry->relocation_count; i++) {
-		ret = i915_gem_execbuffer_relocate_entry(obj, file_priv, entry, &relocs[i]);
-		if (ret)
-			return ret;
-	}
-
-	return 0;
-}
-
-static int
-i915_gem_execbuffer_relocate(struct drm_device *dev,
-			     struct drm_file *file,
-			     struct drm_gem_object **object_list,
-			     struct drm_i915_gem_exec_object2 *exec_list,
-			     int count)
-{
-	int i, ret;
-
-	for (i = 0; i < count; i++) {
-		struct drm_i915_gem_object *obj = to_intel_bo(object_list[i]);
-		obj->base.pending_read_domains = 0;
-		obj->base.pending_write_domain = 0;
-		ret = i915_gem_execbuffer_relocate_object(obj, file,
-							  &exec_list[i]);
-		if (ret)
-			return ret;
-	}
-
-	return 0;
-}
-
-static int
-i915_gem_execbuffer_reserve(struct drm_device *dev,
-			    struct drm_file *file,
-			    struct drm_gem_object **object_list,
-			    struct drm_i915_gem_exec_object2 *exec_list,
-			    int count)
-{
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	int ret, i, retry;
-
-	/* attempt to pin all of the buffers into the GTT */
-	for (retry = 0; retry < 2; retry++) {
-		ret = 0;
-		for (i = 0; i < count; i++) {
-			struct drm_i915_gem_exec_object2 *entry = &exec_list[i];
-			struct drm_i915_gem_object *obj= to_intel_bo(object_list[i]);
-			bool need_fence =
-				entry->flags & EXEC_OBJECT_NEEDS_FENCE &&
-				obj->tiling_mode != I915_TILING_NONE;
-
-			/* Check fence reg constraints and rebind if necessary */
-			if (need_fence &&
-			    !i915_gem_object_fence_offset_ok(&obj->base,
-							     obj->tiling_mode)) {
-				ret = i915_gem_object_unbind(&obj->base);
-				if (ret)
-					break;
-			}
-
-			ret = i915_gem_object_pin(&obj->base, entry->alignment);
-			if (ret)
-				break;
-
-			/*
-			 * Pre-965 chips need a fence register set up in order
-			 * to properly handle blits to/from tiled surfaces.
-			 */
-			if (need_fence) {
-				ret = i915_gem_object_get_fence_reg(&obj->base, true);
-				if (ret) {
-					i915_gem_object_unpin(&obj->base);
-					break;
-				}
-
-				dev_priv->fence_regs[obj->fence_reg].gpu = true;
-			}
-
-			entry->offset = obj->gtt_offset;
-		}
-
-		while (i--)
-			i915_gem_object_unpin(object_list[i]);
-
-		if (ret == 0)
-			break;
-
-		if (ret != -ENOSPC || retry)
-			return ret;
-
-		ret = i915_gem_evict_everything(dev);
-		if (ret)
-			return ret;
-	}
-
-	return 0;
-}
-
-static int
-i915_gem_execbuffer_relocate_slow(struct drm_device *dev,
-				  struct drm_file *file,
-				  struct drm_gem_object **object_list,
-				  struct drm_i915_gem_exec_object2 *exec_list,
-				  int count)
-{
-	struct drm_i915_gem_relocation_entry *reloc;
-	int i, total, ret;
-
-	for (i = 0; i < count; i++) {
-		struct drm_i915_gem_object *obj = to_intel_bo(object_list[i]);
-		obj->in_execbuffer = false;
-	}
-
-	mutex_unlock(&dev->struct_mutex);
-
-	total = 0;
-	for (i = 0; i < count; i++)
-		total += exec_list[i].relocation_count;
-
-	reloc = drm_malloc_ab(total, sizeof(*reloc));
-	if (reloc == NULL) {
-		mutex_lock(&dev->struct_mutex);
-		return -ENOMEM;
-	}
-
-	total = 0;
-	for (i = 0; i < count; i++) {
-		struct drm_i915_gem_relocation_entry __user *user_relocs;
-
-		user_relocs = (void __user *)(uintptr_t)exec_list[i].relocs_ptr;
-
-		if (copy_from_user(reloc+total, user_relocs,
-				   exec_list[i].relocation_count *
-				   sizeof(*reloc))) {
-			ret = -EFAULT;
-			mutex_lock(&dev->struct_mutex);
-			goto err;
-		}
-
-		total += exec_list[i].relocation_count;
-	}
-
-	ret = i915_mutex_lock_interruptible(dev);
-	if (ret) {
-		mutex_lock(&dev->struct_mutex);
-		goto err;
-	}
-
-	ret = i915_gem_execbuffer_reserve(dev, file,
-					  object_list, exec_list,
-					  count);
-	if (ret)
-		goto err;
-
-	total = 0;
-	for (i = 0; i < count; i++) {
-		struct drm_i915_gem_object *obj = to_intel_bo(object_list[i]);
-		obj->base.pending_read_domains = 0;
-		obj->base.pending_write_domain = 0;
-		ret = i915_gem_execbuffer_relocate_object_slow(obj, file,
-							       &exec_list[i],
-							       reloc + total);
-		if (ret)
-			goto err;
-
-		total += exec_list[i].relocation_count;
-	}
-
-	/* Leave the user relocations as are, this is the painfully slow path,
-	 * and we want to avoid the complication of dropping the lock whilst
-	 * having buffers reserved in the aperture and so causing spurious
-	 * ENOSPC for random operations.
-	 */
-
-err:
-	drm_free_large(reloc);
-	return ret;
-}
-
-static int
-i915_gem_execbuffer_move_to_gpu(struct drm_device *dev,
-				struct drm_file *file,
-				struct intel_ring_buffer *ring,
-				struct drm_gem_object **objects,
-				int count)
-{
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	int ret, i;
-
-	/* Zero the global flush/invalidate flags. These
-	 * will be modified as new domains are computed
-	 * for each object
-	 */
-	dev->invalidate_domains = 0;
-	dev->flush_domains = 0;
-	dev_priv->mm.flush_rings = 0;
-	for (i = 0; i < count; i++)
-		i915_gem_object_set_to_gpu_domain(objects[i], ring);
-
-	if (dev->invalidate_domains | dev->flush_domains) {
-#if WATCH_EXEC
-		DRM_INFO("%s: invalidate_domains %08x flush_domains %08x\n",
-			  __func__,
-			 dev->invalidate_domains,
-			 dev->flush_domains);
-#endif
-		i915_gem_flush(dev, file,
-			       dev->invalidate_domains,
-			       dev->flush_domains,
-			       dev_priv->mm.flush_rings);
-	}
-
-	for (i = 0; i < count; i++) {
-		struct drm_i915_gem_object *obj = to_intel_bo(objects[i]);
-		/* XXX replace with semaphores */
-		if (obj->ring && ring != obj->ring) {
-			ret = i915_gem_object_wait_rendering(&obj->base, true);
-			if (ret)
-				return ret;
-		}
-	}
+					    obj->base.write_domain);
 
 	return 0;
 }
@@ -3694,20 +3223,21 @@ i915_gem_ring_throttle(struct drm_device
 		return 0;
 
 	ret = 0;
-	if (!i915_seqno_passed(ring->get_seqno(dev, ring), seqno)) {
+	if (!i915_seqno_passed(ring->get_seqno(ring), seqno)) {
 		/* And wait for the seqno passing without holding any locks and
 		 * causing extra latency for others. This is safe as the irq
 		 * generation is designed to be run atomically and so is
 		 * lockless.
 		 */
-		ring->user_irq_get(dev, ring);
-		ret = wait_event_interruptible(ring->irq_queue,
-					       i915_seqno_passed(ring->get_seqno(dev, ring), seqno)
-					       || atomic_read(&dev_priv->mm.wedged));
-		ring->user_irq_put(dev, ring);
+		if (ring->irq_get(ring)) {
+			ret = wait_event_interruptible(ring->irq_queue,
+						       i915_seqno_passed(ring->get_seqno(ring), seqno)
+						       || atomic_read(&dev_priv->mm.wedged));
+			ring->irq_put(ring);
 
-		if (ret == 0 && atomic_read(&dev_priv->mm.wedged))
-			ret = -EIO;
+			if (ret == 0 && atomic_read(&dev_priv->mm.wedged))
+				ret = -EIO;
+		}
 	}
 
 	if (ret == 0)
@@ -3716,577 +3246,106 @@ i915_gem_ring_throttle(struct drm_device
 	return ret;
 }
 
-static int
-i915_gem_check_execbuffer(struct drm_i915_gem_execbuffer2 *exec,
-			  uint64_t exec_offset)
-{
-	uint32_t exec_start, exec_len;
-
-	exec_start = (uint32_t) exec_offset + exec->batch_start_offset;
-	exec_len = (uint32_t) exec->batch_len;
-
-	if ((exec_start | exec_len) & 0x7)
-		return -EINVAL;
-
-	if (!exec_start)
-		return -EINVAL;
-
-	return 0;
-}
-
-static int
-validate_exec_list(struct drm_i915_gem_exec_object2 *exec,
-		   int count)
-{
-	int i;
-
-	for (i = 0; i < count; i++) {
-		char __user *ptr = (char __user *)(uintptr_t)exec[i].relocs_ptr;
-		int length; /* limited by fault_in_pages_readable() */
-
-		/* First check for malicious input causing overflow */
-		if (exec[i].relocation_count >
-		    INT_MAX / sizeof(struct drm_i915_gem_relocation_entry))
-			return -EINVAL;
-
-		length = exec[i].relocation_count *
-			sizeof(struct drm_i915_gem_relocation_entry);
-		if (!access_ok(VERIFY_READ, ptr, length))
-			return -EFAULT;
-
-		/* we may also need to update the presumed offsets */
-		if (!access_ok(VERIFY_WRITE, ptr, length))
-			return -EFAULT;
-
-		if (fault_in_pages_readable(ptr, length))
-			return -EFAULT;
-	}
-
-	return 0;
-}
-
-static int
-i915_gem_do_execbuffer(struct drm_device *dev, void *data,
-		       struct drm_file *file,
-		       struct drm_i915_gem_execbuffer2 *args,
-		       struct drm_i915_gem_exec_object2 *exec_list)
-{
-	drm_i915_private_t *dev_priv = dev->dev_private;
-	struct drm_gem_object **object_list = NULL;
-	struct drm_gem_object *batch_obj;
-	struct drm_i915_gem_object *obj_priv;
-	struct drm_clip_rect *cliprects = NULL;
-	struct drm_i915_gem_request *request = NULL;
-	int ret, i, flips;
-	uint64_t exec_offset;
-
-	struct intel_ring_buffer *ring = NULL;
-
-	ret = i915_gem_check_is_wedged(dev);
-	if (ret)
-		return ret;
-
-	ret = validate_exec_list(exec_list, args->buffer_count);
-	if (ret)
-		return ret;
-
-#if WATCH_EXEC
-	DRM_INFO("buffers_ptr %d buffer_count %d len %08x\n",
-		  (int) args->buffers_ptr, args->buffer_count, args->batch_len);
-#endif
-	switch (args->flags & I915_EXEC_RING_MASK) {
-	case I915_EXEC_DEFAULT:
-	case I915_EXEC_RENDER:
-		ring = &dev_priv->render_ring;
-		break;
-	case I915_EXEC_BSD:
-		if (!HAS_BSD(dev)) {
-			DRM_ERROR("execbuf with invalid ring (BSD)\n");
-			return -EINVAL;
-		}
-		ring = &dev_priv->bsd_ring;
-		break;
-	case I915_EXEC_BLT:
-		if (!HAS_BLT(dev)) {
-			DRM_ERROR("execbuf with invalid ring (BLT)\n");
-			return -EINVAL;
-		}
-		ring = &dev_priv->blt_ring;
-		break;
-	default:
-		DRM_ERROR("execbuf with unknown ring: %d\n",
-			  (int)(args->flags & I915_EXEC_RING_MASK));
-		return -EINVAL;
-	}
-
-	if (args->buffer_count < 1) {
-		DRM_ERROR("execbuf with %d buffers\n", args->buffer_count);
-		return -EINVAL;
-	}
-	object_list = drm_malloc_ab(sizeof(*object_list), args->buffer_count);
-	if (object_list == NULL) {
-		DRM_ERROR("Failed to allocate object list for %d buffers\n",
-			  args->buffer_count);
-		ret = -ENOMEM;
-		goto pre_mutex_err;
-	}
-
-	if (args->num_cliprects != 0) {
-		cliprects = kcalloc(args->num_cliprects, sizeof(*cliprects),
-				    GFP_KERNEL);
-		if (cliprects == NULL) {
-			ret = -ENOMEM;
-			goto pre_mutex_err;
-		}
-
-		ret = copy_from_user(cliprects,
-				     (struct drm_clip_rect __user *)
-				     (uintptr_t) args->cliprects_ptr,
-				     sizeof(*cliprects) * args->num_cliprects);
-		if (ret != 0) {
-			DRM_ERROR("copy %d cliprects failed: %d\n",
-				  args->num_cliprects, ret);
-			ret = -EFAULT;
-			goto pre_mutex_err;
-		}
-	}
-
-	request = kzalloc(sizeof(*request), GFP_KERNEL);
-	if (request == NULL) {
-		ret = -ENOMEM;
-		goto pre_mutex_err;
-	}
-
-	ret = i915_mutex_lock_interruptible(dev);
-	if (ret)
-		goto pre_mutex_err;
-
-	if (dev_priv->mm.suspended) {
-		mutex_unlock(&dev->struct_mutex);
-		ret = -EBUSY;
-		goto pre_mutex_err;
-	}
-
-	/* Look up object handles */
-	for (i = 0; i < args->buffer_count; i++) {
-		object_list[i] = drm_gem_object_lookup(dev, file,
-						       exec_list[i].handle);
-		if (object_list[i] == NULL) {
-			DRM_ERROR("Invalid object handle %d at index %d\n",
-				   exec_list[i].handle, i);
-			/* prevent error path from reading uninitialized data */
-			args->buffer_count = i + 1;
-			ret = -ENOENT;
-			goto err;
-		}
-
-		obj_priv = to_intel_bo(object_list[i]);
-		if (obj_priv->in_execbuffer) {
-			DRM_ERROR("Object %p appears more than once in object list\n",
-				   object_list[i]);
-			/* prevent error path from reading uninitialized data */
-			args->buffer_count = i + 1;
-			ret = -EINVAL;
-			goto err;
-		}
-		obj_priv->in_execbuffer = true;
-	}
-
-	/* Move the objects en-masse into the GTT, evicting if necessary. */
-	ret = i915_gem_execbuffer_reserve(dev, file,
-					  object_list, exec_list,
-					  args->buffer_count);
-	if (ret)
-		goto err;
-
-	/* The objects are in their final locations, apply the relocations. */
-	ret = i915_gem_execbuffer_relocate(dev, file,
-					   object_list, exec_list,
-					   args->buffer_count);
-	if (ret) {
-		if (ret == -EFAULT) {
-			ret = i915_gem_execbuffer_relocate_slow(dev, file,
-								object_list,
-								exec_list,
-								args->buffer_count);
-			BUG_ON(!mutex_is_locked(&dev->struct_mutex));
-		}
-		if (ret)
-			goto err;
-	}
-
-	/* Set the pending read domains for the batch buffer to COMMAND */
-	batch_obj = object_list[args->buffer_count-1];
-	if (batch_obj->pending_write_domain) {
-		DRM_ERROR("Attempting to use self-modifying batch buffer\n");
-		ret = -EINVAL;
-		goto err;
-	}
-	batch_obj->pending_read_domains |= I915_GEM_DOMAIN_COMMAND;
-
-	/* Sanity check the batch buffer */
-	exec_offset = to_intel_bo(batch_obj)->gtt_offset;
-	ret = i915_gem_check_execbuffer(args, exec_offset);
-	if (ret != 0) {
-		DRM_ERROR("execbuf with invalid offset/length\n");
-		goto err;
-	}
-
-	ret = i915_gem_execbuffer_move_to_gpu(dev, file, ring,
-					      object_list, args->buffer_count);
-	if (ret)
-		goto err;
-
-	for (i = 0; i < args->buffer_count; i++) {
-		struct drm_gem_object *obj = object_list[i];
-		uint32_t old_write_domain = obj->write_domain;
-		obj->write_domain = obj->pending_write_domain;
-		trace_i915_gem_object_change_domain(obj,
-						    obj->read_domains,
-						    old_write_domain);
-	}
-
-#if WATCH_COHERENCY
-	for (i = 0; i < args->buffer_count; i++) {
-		i915_gem_object_check_coherency(object_list[i],
-						exec_list[i].handle);
-	}
-#endif
-
-#if WATCH_EXEC
-	i915_gem_dump_object(batch_obj,
-			      args->batch_len,
-			      __func__,
-			      ~0);
-#endif
-
-	/* Check for any pending flips. As we only maintain a flip queue depth
-	 * of 1, we can simply insert a WAIT for the next display flip prior
-	 * to executing the batch and avoid stalling the CPU.
-	 */
-	flips = 0;
-	for (i = 0; i < args->buffer_count; i++) {
-		if (object_list[i]->write_domain)
-			flips |= atomic_read(&to_intel_bo(object_list[i])->pending_flip);
-	}
-	if (flips) {
-		int plane, flip_mask;
-
-		for (plane = 0; flips >> plane; plane++) {
-			if (((flips >> plane) & 1) == 0)
-				continue;
-
-			if (plane)
-				flip_mask = MI_WAIT_FOR_PLANE_B_FLIP;
-			else
-				flip_mask = MI_WAIT_FOR_PLANE_A_FLIP;
-
-			intel_ring_begin(dev, ring, 2);
-			intel_ring_emit(dev, ring,
-					MI_WAIT_FOR_EVENT | flip_mask);
-			intel_ring_emit(dev, ring, MI_NOOP);
-			intel_ring_advance(dev, ring);
-		}
-	}
-
-	/* Exec the batchbuffer */
-	ret = ring->dispatch_gem_execbuffer(dev, ring, args,
-					    cliprects, exec_offset);
-	if (ret) {
-		DRM_ERROR("dispatch failed %d\n", ret);
-		goto err;
-	}
-
-	/*
-	 * Ensure that the commands in the batch buffer are
-	 * finished before the interrupt fires
-	 */
-	i915_retire_commands(dev, ring);
-
-	for (i = 0; i < args->buffer_count; i++) {
-		struct drm_gem_object *obj = object_list[i];
-
-		i915_gem_object_move_to_active(obj, ring);
-		if (obj->write_domain)
-			list_move_tail(&to_intel_bo(obj)->gpu_write_list,
-				       &ring->gpu_write_list);
-	}
-
-	i915_add_request(dev, file, request, ring);
-	request = NULL;
-
-err:
-	for (i = 0; i < args->buffer_count; i++) {
-		if (object_list[i]) {
-			obj_priv = to_intel_bo(object_list[i]);
-			obj_priv->in_execbuffer = false;
-		}
-		drm_gem_object_unreference(object_list[i]);
-	}
-
-	mutex_unlock(&dev->struct_mutex);
-
-pre_mutex_err:
-	drm_free_large(object_list);
-	kfree(cliprects);
-	kfree(request);
-
-	return ret;
-}
-
-/*
- * Legacy execbuffer just creates an exec2 list from the original exec object
- * list array and passes it to the real function.
- */
-int
-i915_gem_execbuffer(struct drm_device *dev, void *data,
-		    struct drm_file *file_priv)
-{
-	struct drm_i915_gem_execbuffer *args = data;
-	struct drm_i915_gem_execbuffer2 exec2;
-	struct drm_i915_gem_exec_object *exec_list = NULL;
-	struct drm_i915_gem_exec_object2 *exec2_list = NULL;
-	int ret, i;
-
-#if WATCH_EXEC
-	DRM_INFO("buffers_ptr %d buffer_count %d len %08x\n",
-		  (int) args->buffers_ptr, args->buffer_count, args->batch_len);
-#endif
-
-	if (args->buffer_count < 1) {
-		DRM_ERROR("execbuf with %d buffers\n", args->buffer_count);
-		return -EINVAL;
-	}
-
-	/* Copy in the exec list from userland */
-	exec_list = drm_malloc_ab(sizeof(*exec_list), args->buffer_count);
-	exec2_list = drm_malloc_ab(sizeof(*exec2_list), args->buffer_count);
-	if (exec_list == NULL || exec2_list == NULL) {
-		DRM_ERROR("Failed to allocate exec list for %d buffers\n",
-			  args->buffer_count);
-		drm_free_large(exec_list);
-		drm_free_large(exec2_list);
-		return -ENOMEM;
-	}
-	ret = copy_from_user(exec_list,
-			     (struct drm_i915_relocation_entry __user *)
-			     (uintptr_t) args->buffers_ptr,
-			     sizeof(*exec_list) * args->buffer_count);
-	if (ret != 0) {
-		DRM_ERROR("copy %d exec entries failed %d\n",
-			  args->buffer_count, ret);
-		drm_free_large(exec_list);
-		drm_free_large(exec2_list);
-		return -EFAULT;
-	}
-
-	for (i = 0; i < args->buffer_count; i++) {
-		exec2_list[i].handle = exec_list[i].handle;
-		exec2_list[i].relocation_count = exec_list[i].relocation_count;
-		exec2_list[i].relocs_ptr = exec_list[i].relocs_ptr;
-		exec2_list[i].alignment = exec_list[i].alignment;
-		exec2_list[i].offset = exec_list[i].offset;
-		if (INTEL_INFO(dev)->gen < 4)
-			exec2_list[i].flags = EXEC_OBJECT_NEEDS_FENCE;
-		else
-			exec2_list[i].flags = 0;
-	}
-
-	exec2.buffers_ptr = args->buffers_ptr;
-	exec2.buffer_count = args->buffer_count;
-	exec2.batch_start_offset = args->batch_start_offset;
-	exec2.batch_len = args->batch_len;
-	exec2.DR1 = args->DR1;
-	exec2.DR4 = args->DR4;
-	exec2.num_cliprects = args->num_cliprects;
-	exec2.cliprects_ptr = args->cliprects_ptr;
-	exec2.flags = I915_EXEC_RENDER;
-
-	ret = i915_gem_do_execbuffer(dev, data, file_priv, &exec2, exec2_list);
-	if (!ret) {
-		/* Copy the new buffer offsets back to the user's exec list. */
-		for (i = 0; i < args->buffer_count; i++)
-			exec_list[i].offset = exec2_list[i].offset;
-		/* ... and back out to userspace */
-		ret = copy_to_user((struct drm_i915_relocation_entry __user *)
-				   (uintptr_t) args->buffers_ptr,
-				   exec_list,
-				   sizeof(*exec_list) * args->buffer_count);
-		if (ret) {
-			ret = -EFAULT;
-			DRM_ERROR("failed to copy %d exec entries "
-				  "back to user (%d)\n",
-				  args->buffer_count, ret);
-		}
-	}
-
-	drm_free_large(exec_list);
-	drm_free_large(exec2_list);
-	return ret;
-}
-
 int
-i915_gem_execbuffer2(struct drm_device *dev, void *data,
-		     struct drm_file *file_priv)
-{
-	struct drm_i915_gem_execbuffer2 *args = data;
-	struct drm_i915_gem_exec_object2 *exec2_list = NULL;
-	int ret;
-
-#if WATCH_EXEC
-	DRM_INFO("buffers_ptr %d buffer_count %d len %08x\n",
-		  (int) args->buffers_ptr, args->buffer_count, args->batch_len);
-#endif
-
-	if (args->buffer_count < 1) {
-		DRM_ERROR("execbuf2 with %d buffers\n", args->buffer_count);
-		return -EINVAL;
-	}
-
-	exec2_list = drm_malloc_ab(sizeof(*exec2_list), args->buffer_count);
-	if (exec2_list == NULL) {
-		DRM_ERROR("Failed to allocate exec list for %d buffers\n",
-			  args->buffer_count);
-		return -ENOMEM;
-	}
-	ret = copy_from_user(exec2_list,
-			     (struct drm_i915_relocation_entry __user *)
-			     (uintptr_t) args->buffers_ptr,
-			     sizeof(*exec2_list) * args->buffer_count);
-	if (ret != 0) {
-		DRM_ERROR("copy %d exec entries failed %d\n",
-			  args->buffer_count, ret);
-		drm_free_large(exec2_list);
-		return -EFAULT;
-	}
-
-	ret = i915_gem_do_execbuffer(dev, data, file_priv, args, exec2_list);
-	if (!ret) {
-		/* Copy the new buffer offsets back to the user's exec list. */
-		ret = copy_to_user((struct drm_i915_relocation_entry __user *)
-				   (uintptr_t) args->buffers_ptr,
-				   exec2_list,
-				   sizeof(*exec2_list) * args->buffer_count);
-		if (ret) {
-			ret = -EFAULT;
-			DRM_ERROR("failed to copy %d exec entries "
-				  "back to user (%d)\n",
-				  args->buffer_count, ret);
-		}
-	}
-
-	drm_free_large(exec2_list);
-	return ret;
-}
-
-int
-i915_gem_object_pin(struct drm_gem_object *obj, uint32_t alignment)
+i915_gem_object_pin(struct drm_i915_gem_object *obj,
+		    uint32_t alignment,
+		    bool map_and_fenceable)
 {
-	struct drm_device *dev = obj->dev;
+	struct drm_device *dev = obj->base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
 	int ret;
 
-	BUG_ON(obj_priv->pin_count == DRM_I915_GEM_OBJECT_MAX_PIN_COUNT);
+	BUG_ON(obj->pin_count == DRM_I915_GEM_OBJECT_MAX_PIN_COUNT);
 	WARN_ON(i915_verify_lists(dev));
 
-	if (obj_priv->gtt_space != NULL) {
-		if (alignment == 0)
-			alignment = i915_gem_get_gtt_alignment(obj);
-		if (obj_priv->gtt_offset & (alignment - 1)) {
-			WARN(obj_priv->pin_count,
-			     "bo is already pinned with incorrect alignment: offset=%x, req.alignment=%x\n",
-			     obj_priv->gtt_offset, alignment);
+	if (obj->gtt_space != NULL) {
+		if ((alignment && obj->gtt_offset & (alignment - 1)) ||
+		    (map_and_fenceable && !obj->map_and_fenceable)) {
+			WARN(obj->pin_count,
+			     "bo is already pinned with incorrect alignment:"
+			     " offset=%x, req.alignment=%x, req.map_and_fenceable=%d,"
+			     " obj->map_and_fenceable=%d\n",
+			     obj->gtt_offset, alignment,
+			     map_and_fenceable,
+			     obj->map_and_fenceable);
 			ret = i915_gem_object_unbind(obj);
 			if (ret)
 				return ret;
 		}
 	}
 
-	if (obj_priv->gtt_space == NULL) {
-		ret = i915_gem_object_bind_to_gtt(obj, alignment);
+	if (obj->gtt_space == NULL) {
+		ret = i915_gem_object_bind_to_gtt(obj, alignment,
+						  map_and_fenceable);
 		if (ret)
 			return ret;
 	}
 
-	obj_priv->pin_count++;
-
-	/* If the object is not active and not pending a flush,
-	 * remove it from the inactive list
-	 */
-	if (obj_priv->pin_count == 1) {
-		i915_gem_info_add_pin(dev_priv, obj->size);
-		if (!obj_priv->active)
-			list_move_tail(&obj_priv->mm_list,
+	if (obj->pin_count++ == 0) {
+		if (!obj->active)
+			list_move_tail(&obj->mm_list,
 				       &dev_priv->mm.pinned_list);
 	}
+	obj->pin_mappable |= map_and_fenceable;
 
 	WARN_ON(i915_verify_lists(dev));
 	return 0;
 }
 
 void
-i915_gem_object_unpin(struct drm_gem_object *obj)
+i915_gem_object_unpin(struct drm_i915_gem_object *obj)
 {
-	struct drm_device *dev = obj->dev;
+	struct drm_device *dev = obj->base.dev;
 	drm_i915_private_t *dev_priv = dev->dev_private;
-	struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
 
 	WARN_ON(i915_verify_lists(dev));
-	obj_priv->pin_count--;
-	BUG_ON(obj_priv->pin_count < 0);
-	BUG_ON(obj_priv->gtt_space == NULL);
+	BUG_ON(obj->pin_count == 0);
+	BUG_ON(obj->gtt_space == NULL);
 
-	/* If the object is no longer pinned, and is
-	 * neither active nor being flushed, then stick it on
-	 * the inactive list
-	 */
-	if (obj_priv->pin_count == 0) {
-		if (!obj_priv->active)
-			list_move_tail(&obj_priv->mm_list,
+	if (--obj->pin_count == 0) {
+		if (!obj->active)
+			list_move_tail(&obj->mm_list,
 				       &dev_priv->mm.inactive_list);
-		i915_gem_info_remove_pin(dev_priv, obj->size);
+		obj->pin_mappable = false;
 	}
 	WARN_ON(i915_verify_lists(dev));
 }
 
 int
 i915_gem_pin_ioctl(struct drm_device *dev, void *data,
-		   struct drm_file *file_priv)
+		   struct drm_file *file)
 {
 	struct drm_i915_gem_pin *args = data;
-	struct drm_gem_object *obj;
-	struct drm_i915_gem_object *obj_priv;
+	struct drm_i915_gem_object *obj;
 	int ret;
 
 	ret = i915_mutex_lock_interruptible(dev);
 	if (ret)
 		return ret;
 
-	obj = drm_gem_object_lookup(dev, file_priv, args->handle);
+	obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle));
 	if (obj == NULL) {
 		ret = -ENOENT;
 		goto unlock;
 	}
-	obj_priv = to_intel_bo(obj);
 
-	if (obj_priv->madv != I915_MADV_WILLNEED) {
+	if (obj->madv != I915_MADV_WILLNEED) {
 		DRM_ERROR("Attempting to pin a purgeable buffer\n");
 		ret = -EINVAL;
 		goto out;
 	}
 
-	if (obj_priv->pin_filp != NULL && obj_priv->pin_filp != file_priv) {
+	if (obj->pin_filp != NULL && obj->pin_filp != file) {
 		DRM_ERROR("Already pinned in i915_gem_pin_ioctl(): %d\n",
 			  args->handle);
 		ret = -EINVAL;
 		goto out;
 	}
 
-	obj_priv->user_pin_count++;
-	obj_priv->pin_filp = file_priv;
-	if (obj_priv->user_pin_count == 1) {
-		ret = i915_gem_object_pin(obj, args->alignment);
+	obj->user_pin_count++;
+	obj->pin_filp = file;
+	if (obj->user_pin_count == 1) {
+		ret = i915_gem_object_pin(obj, args->alignment, true);
 		if (ret)
 			goto out;
 	}
@@ -4295,9 +3354,9 @@ i915_gem_pin_ioctl(struct drm_device *de
 	 * as the X server doesn't manage domains yet
 	 */
 	i915_gem_object_flush_cpu_write_domain(obj);
-	args->offset = obj_priv->gtt_offset;
+	args->offset = obj->gtt_offset;
 out:
-	drm_gem_object_unreference(obj);
+	drm_gem_object_unreference(&obj->base);
 unlock:
 	mutex_unlock(&dev->struct_mutex);
 	return ret;
@@ -4305,38 +3364,36 @@ unlock:
 
 int
 i915_gem_unpin_ioctl(struct drm_device *dev, void *data,
-		     struct drm_file *file_priv)
+		     struct drm_file *file)
 {
 	struct drm_i915_gem_pin *args = data;
-	struct drm_gem_object *obj;
-	struct drm_i915_gem_object *obj_priv;
+	struct drm_i915_gem_object *obj;
 	int ret;
 
 	ret = i915_mutex_lock_interruptible(dev);
 	if (ret)
 		return ret;
 
-	obj = drm_gem_object_lookup(dev, file_priv, args->handle);
+	obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle));
 	if (obj == NULL) {
 		ret = -ENOENT;
 		goto unlock;
 	}
-	obj_priv = to_intel_bo(obj);
 
-	if (obj_priv->pin_filp != file_priv) {
+	if (obj->pin_filp != file) {
 		DRM_ERROR("Not pinned by caller in i915_gem_pin_ioctl(): %d\n",
 			  args->handle);
 		ret = -EINVAL;
 		goto out;
 	}
-	obj_priv->user_pin_count--;
-	if (obj_priv->user_pin_count == 0) {
-		obj_priv->pin_filp = NULL;
+	obj->user_pin_count--;
+	if (obj->user_pin_count == 0) {
+		obj->pin_filp = NULL;
 		i915_gem_object_unpin(obj);
 	}
 
 out:
-	drm_gem_object_unreference(obj);
+	drm_gem_object_unreference(&obj->base);
 unlock:
 	mutex_unlock(&dev->struct_mutex);
 	return ret;
@@ -4344,48 +3401,50 @@ unlock:
 
 int
 i915_gem_busy_ioctl(struct drm_device *dev, void *data,
-		    struct drm_file *file_priv)
+		    struct drm_file *file)
 {
 	struct drm_i915_gem_busy *args = data;
-	struct drm_gem_object *obj;
-	struct drm_i915_gem_object *obj_priv;
+	struct drm_i915_gem_object *obj;
 	int ret;
 
 	ret = i915_mutex_lock_interruptible(dev);
 	if (ret)
 		return ret;
 
-	obj = drm_gem_object_lookup(dev, file_priv, args->handle);
+	obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle));
 	if (obj == NULL) {
 		ret = -ENOENT;
 		goto unlock;
 	}
-	obj_priv = to_intel_bo(obj);
 
 	/* Count all active objects as busy, even if they are currently not used
 	 * by the gpu. Users of this interface expect objects to eventually
 	 * become non-busy without any further actions, therefore emit any
 	 * necessary flushes here.
 	 */
-	args->busy = obj_priv->active;
+	args->busy = obj->active;
 	if (args->busy) {
 		/* Unconditionally flush objects, even when the gpu still uses this
 		 * object. Userspace calling this function indicates that it wants to
 		 * use this buffer rather sooner than later, so issuing the required
 		 * flush earlier is beneficial.
 		 */
-		if (obj->write_domain & I915_GEM_GPU_DOMAINS) {
-			i915_gem_flush_ring(dev, file_priv,
-					    obj_priv->ring,
-					    0, obj->write_domain);
-		} else if (obj_priv->ring->outstanding_lazy_request) {
+		if (obj->base.write_domain & I915_GEM_GPU_DOMAINS) {
+			ret = i915_gem_flush_ring(dev, obj->ring,
+						  0, obj->base.write_domain);
+		} else if (obj->ring->outstanding_lazy_request ==
+			   obj->last_rendering_seqno) {
+			struct drm_i915_gem_request *request;
+
 			/* This ring is not being cleared by active usage,
 			 * so emit a request to do so.
 			 */
-			u32 seqno = i915_add_request(dev,
-						     NULL, NULL,
-						     obj_priv->ring);
-			if (seqno == 0)
+			request = kzalloc(sizeof(*request), GFP_KERNEL);
+			if (request)
+				ret = i915_add_request(dev,
+						       NULL, request,
+						       obj->ring);
+			else
 				ret = -ENOMEM;
 		}
 
@@ -4394,12 +3453,12 @@ i915_gem_busy_ioctl(struct drm_device *d
 		 * are actually unmasked, and our working set ends up being
 		 * larger than required.
 		 */
-		i915_gem_retire_requests_ring(dev, obj_priv->ring);
+		i915_gem_retire_requests_ring(dev, obj->ring);
 
-		args->busy = obj_priv->active;
+		args->busy = obj->active;
 	}
 
-	drm_gem_object_unreference(obj);
+	drm_gem_object_unreference(&obj->base);
 unlock:
 	mutex_unlock(&dev->struct_mutex);
 	return ret;
@@ -4417,8 +3476,7 @@ i915_gem_madvise_ioctl(struct drm_device
 		       struct drm_file *file_priv)
 {
 	struct drm_i915_gem_madvise *args = data;
-	struct drm_gem_object *obj;
-	struct drm_i915_gem_object *obj_priv;
+	struct drm_i915_gem_object *obj;
 	int ret;
 
 	switch (args->madv) {
@@ -4433,37 +3491,36 @@ i915_gem_madvise_ioctl(struct drm_device
 	if (ret)
 		return ret;
 
-	obj = drm_gem_object_lookup(dev, file_priv, args->handle);
+	obj = to_intel_bo(drm_gem_object_lookup(dev, file_priv, args->handle));
 	if (obj == NULL) {
 		ret = -ENOENT;
 		goto unlock;
 	}
-	obj_priv = to_intel_bo(obj);
 
-	if (obj_priv->pin_count) {
+	if (obj->pin_count) {
 		ret = -EINVAL;
 		goto out;
 	}
 
-	if (obj_priv->madv != __I915_MADV_PURGED)
-		obj_priv->madv = args->madv;
+	if (obj->madv != __I915_MADV_PURGED)
+		obj->madv = args->madv;
 
 	/* if the object is no longer bound, discard its backing storage */
-	if (i915_gem_object_is_purgeable(obj_priv) &&
-	    obj_priv->gtt_space == NULL)
+	if (i915_gem_object_is_purgeable(obj) &&
+	    obj->gtt_space == NULL)
 		i915_gem_object_truncate(obj);
 
-	args->retained = obj_priv->madv != __I915_MADV_PURGED;
+	args->retained = obj->madv != __I915_MADV_PURGED;
 
 out:
-	drm_gem_object_unreference(obj);
+	drm_gem_object_unreference(&obj->base);
 unlock:
 	mutex_unlock(&dev->struct_mutex);
 	return ret;
 }
 
-struct drm_gem_object * i915_gem_alloc_object(struct drm_device *dev,
-					      size_t size)
+struct drm_i915_gem_object *i915_gem_alloc_object(struct drm_device *dev,
+						  size_t size)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct drm_i915_gem_object *obj;
@@ -4486,11 +3543,15 @@ struct drm_gem_object * i915_gem_alloc_o
 	obj->base.driver_private = NULL;
 	obj->fence_reg = I915_FENCE_REG_NONE;
 	INIT_LIST_HEAD(&obj->mm_list);
+	INIT_LIST_HEAD(&obj->gtt_list);
 	INIT_LIST_HEAD(&obj->ring_list);
+	INIT_LIST_HEAD(&obj->exec_list);
 	INIT_LIST_HEAD(&obj->gpu_write_list);
 	obj->madv = I915_MADV_WILLNEED;
+	/* Avoid an unnecessary call to unbind on the first bind. */
+	obj->map_and_fenceable = true;
 
-	return &obj->base;
+	return obj;
 }
 
 int i915_gem_init_object(struct drm_gem_object *obj)
@@ -4500,42 +3561,41 @@ int i915_gem_init_object(struct drm_gem_
 	return 0;
 }
 
-static void i915_gem_free_object_tail(struct drm_gem_object *obj)
+static void i915_gem_free_object_tail(struct drm_i915_gem_object *obj)
 {
-	struct drm_device *dev = obj->dev;
+	struct drm_device *dev = obj->base.dev;
 	drm_i915_private_t *dev_priv = dev->dev_private;
-	struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
 	int ret;
 
 	ret = i915_gem_object_unbind(obj);
 	if (ret == -ERESTARTSYS) {
-		list_move(&obj_priv->mm_list,
+		list_move(&obj->mm_list,
 			  &dev_priv->mm.deferred_free_list);
 		return;
 	}
 
-	if (obj_priv->mmap_offset)
+	if (obj->base.map_list.map)
 		i915_gem_free_mmap_offset(obj);
 
-	drm_gem_object_release(obj);
-	i915_gem_info_remove_obj(dev_priv, obj->size);
+	drm_gem_object_release(&obj->base);
+	i915_gem_info_remove_obj(dev_priv, obj->base.size);
 
-	kfree(obj_priv->page_cpu_valid);
-	kfree(obj_priv->bit_17);
-	kfree(obj_priv);
+	kfree(obj->page_cpu_valid);
+	kfree(obj->bit_17);
+	kfree(obj);
 }
 
-void i915_gem_free_object(struct drm_gem_object *obj)
+void i915_gem_free_object(struct drm_gem_object *gem_obj)
 {
-	struct drm_device *dev = obj->dev;
-	struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
+	struct drm_i915_gem_object *obj = to_intel_bo(gem_obj);
+	struct drm_device *dev = obj->base.dev;
 
 	trace_i915_gem_object_destroy(obj);
 
-	while (obj_priv->pin_count > 0)
+	while (obj->pin_count > 0)
 		i915_gem_object_unpin(obj);
 
-	if (obj_priv->phys_obj)
+	if (obj->phys_obj)
 		i915_gem_detach_phys_object(dev, obj);
 
 	i915_gem_free_object_tail(obj);
@@ -4562,13 +3622,15 @@ i915_gem_idle(struct drm_device *dev)
 
 	/* Under UMS, be paranoid and evict. */
 	if (!drm_core_check_feature(dev, DRIVER_MODESET)) {
-		ret = i915_gem_evict_inactive(dev);
+		ret = i915_gem_evict_inactive(dev, false);
 		if (ret) {
 			mutex_unlock(&dev->struct_mutex);
 			return ret;
 		}
 	}
 
+	i915_gem_reset_fences(dev);
+
 	/* Hack!  Don't let anybody do execbuf while we don't control the chip.
 	 * We need to replace this with a semaphore, or something.
 	 * And not confound mm.suspended!
@@ -4587,82 +3649,15 @@ i915_gem_idle(struct drm_device *dev)
 	return 0;
 }
 
-/*
- * 965+ support PIPE_CONTROL commands, which provide finer grained control
- * over cache flushing.
- */
-static int
-i915_gem_init_pipe_control(struct drm_device *dev)
-{
-	drm_i915_private_t *dev_priv = dev->dev_private;
-	struct drm_gem_object *obj;
-	struct drm_i915_gem_object *obj_priv;
-	int ret;
-
-	obj = i915_gem_alloc_object(dev, 4096);
-	if (obj == NULL) {
-		DRM_ERROR("Failed to allocate seqno page\n");
-		ret = -ENOMEM;
-		goto err;
-	}
-	obj_priv = to_intel_bo(obj);
-	obj_priv->agp_type = AGP_USER_CACHED_MEMORY;
-
-	ret = i915_gem_object_pin(obj, 4096);
-	if (ret)
-		goto err_unref;
-
-	dev_priv->seqno_gfx_addr = obj_priv->gtt_offset;
-	dev_priv->seqno_page =  kmap(obj_priv->pages[0]);
-	if (dev_priv->seqno_page == NULL)
-		goto err_unpin;
-
-	dev_priv->seqno_obj = obj;
-	memset(dev_priv->seqno_page, 0, PAGE_SIZE);
-
-	return 0;
-
-err_unpin:
-	i915_gem_object_unpin(obj);
-err_unref:
-	drm_gem_object_unreference(obj);
-err:
-	return ret;
-}
-
-
-static void
-i915_gem_cleanup_pipe_control(struct drm_device *dev)
-{
-	drm_i915_private_t *dev_priv = dev->dev_private;
-	struct drm_gem_object *obj;
-	struct drm_i915_gem_object *obj_priv;
-
-	obj = dev_priv->seqno_obj;
-	obj_priv = to_intel_bo(obj);
-	kunmap(obj_priv->pages[0]);
-	i915_gem_object_unpin(obj);
-	drm_gem_object_unreference(obj);
-	dev_priv->seqno_obj = NULL;
-
-	dev_priv->seqno_page = NULL;
-}
-
 int
 i915_gem_init_ringbuffer(struct drm_device *dev)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	int ret;
 
-	if (HAS_PIPE_CONTROL(dev)) {
-		ret = i915_gem_init_pipe_control(dev);
-		if (ret)
-			return ret;
-	}
-
 	ret = intel_init_render_ring_buffer(dev);
 	if (ret)
-		goto cleanup_pipe_control;
+		return ret;
 
 	if (HAS_BSD(dev)) {
 		ret = intel_init_bsd_ring_buffer(dev);
@@ -4681,12 +3676,9 @@ i915_gem_init_ringbuffer(struct drm_devi
 	return 0;
 
 cleanup_bsd_ring:
-	intel_cleanup_ring_buffer(dev, &dev_priv->bsd_ring);
+	intel_cleanup_ring_buffer(&dev_priv->ring[VCS]);
 cleanup_render_ring:
-	intel_cleanup_ring_buffer(dev, &dev_priv->render_ring);
-cleanup_pipe_control:
-	if (HAS_PIPE_CONTROL(dev))
-		i915_gem_cleanup_pipe_control(dev);
+	intel_cleanup_ring_buffer(&dev_priv->ring[RCS]);
 	return ret;
 }
 
@@ -4694,12 +3686,10 @@ void
 i915_gem_cleanup_ringbuffer(struct drm_device *dev)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
+	int i;
 
-	intel_cleanup_ring_buffer(dev, &dev_priv->render_ring);
-	intel_cleanup_ring_buffer(dev, &dev_priv->bsd_ring);
-	intel_cleanup_ring_buffer(dev, &dev_priv->blt_ring);
-	if (HAS_PIPE_CONTROL(dev))
-		i915_gem_cleanup_pipe_control(dev);
+	for (i = 0; i < I915_NUM_RINGS; i++)
+		intel_cleanup_ring_buffer(&dev_priv->ring[i]);
 }
 
 int
@@ -4707,7 +3697,7 @@ i915_gem_entervt_ioctl(struct drm_device
 		       struct drm_file *file_priv)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
-	int ret;
+	int ret, i;
 
 	if (drm_core_check_feature(dev, DRIVER_MODESET))
 		return 0;
@@ -4727,14 +3717,12 @@ i915_gem_entervt_ioctl(struct drm_device
 	}
 
 	BUG_ON(!list_empty(&dev_priv->mm.active_list));
-	BUG_ON(!list_empty(&dev_priv->render_ring.active_list));
-	BUG_ON(!list_empty(&dev_priv->bsd_ring.active_list));
-	BUG_ON(!list_empty(&dev_priv->blt_ring.active_list));
 	BUG_ON(!list_empty(&dev_priv->mm.flushing_list));
 	BUG_ON(!list_empty(&dev_priv->mm.inactive_list));
-	BUG_ON(!list_empty(&dev_priv->render_ring.request_list));
-	BUG_ON(!list_empty(&dev_priv->bsd_ring.request_list));
-	BUG_ON(!list_empty(&dev_priv->blt_ring.request_list));
+	for (i = 0; i < I915_NUM_RINGS; i++) {
+		BUG_ON(!list_empty(&dev_priv->ring[i].active_list));
+		BUG_ON(!list_empty(&dev_priv->ring[i].request_list));
+	}
 	mutex_unlock(&dev->struct_mutex);
 
 	ret = drm_irq_install(dev);
@@ -4796,17 +3784,14 @@ i915_gem_load(struct drm_device *dev)
 	INIT_LIST_HEAD(&dev_priv->mm.pinned_list);
 	INIT_LIST_HEAD(&dev_priv->mm.fence_list);
 	INIT_LIST_HEAD(&dev_priv->mm.deferred_free_list);
-	init_ring_lists(&dev_priv->render_ring);
-	init_ring_lists(&dev_priv->bsd_ring);
-	init_ring_lists(&dev_priv->blt_ring);
+	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++)
 		INIT_LIST_HEAD(&dev_priv->fence_regs[i].lru_list);
 	INIT_DELAYED_WORK(&dev_priv->mm.retire_work,
 			  i915_gem_retire_work_handler);
 	init_completion(&dev_priv->error_completion);
-	spin_lock(&shrink_list_lock);
-	list_add(&dev_priv->mm.shrink_list, &shrink_list);
-	spin_unlock(&shrink_list_lock);
 
 	/* On GEN3 we really need to make sure the ARB C3 LP bit is set */
 	if (IS_GEN3(dev)) {
@@ -4818,6 +3803,8 @@ i915_gem_load(struct drm_device *dev)
 		}
 	}
 
+	dev_priv->relative_constants_mode = I915_EXEC_CONSTANTS_REL_GENERAL;
+
 	/* Old X drivers will take 0-2 for front, back, depth buffers */
 	if (!drm_core_check_feature(dev, DRIVER_MODESET))
 		dev_priv->fence_reg_start = 3;
@@ -4849,6 +3836,10 @@ i915_gem_load(struct drm_device *dev)
 	}
 	i915_gem_detect_bit_6_swizzle(dev);
 	init_waitqueue_head(&dev_priv->pending_flip_queue);
+
+	dev_priv->mm.inactive_shrinker.shrink = i915_gem_inactive_shrink;
+	dev_priv->mm.inactive_shrinker.seeks = DEFAULT_SEEKS;
+	register_shrinker(&dev_priv->mm.inactive_shrinker);
 }
 
 /*
@@ -4918,47 +3909,47 @@ void i915_gem_free_all_phys_object(struc
 }
 
 void i915_gem_detach_phys_object(struct drm_device *dev,
-				 struct drm_gem_object *obj)
+				 struct drm_i915_gem_object *obj)
 {
-	struct drm_i915_gem_object *obj_priv;
+	struct address_space *mapping = obj->base.filp->f_path.dentry->d_inode->i_mapping;
+	char *vaddr;
 	int i;
-	int ret;
 	int page_count;
 
-	obj_priv = to_intel_bo(obj);
-	if (!obj_priv->phys_obj)
+	if (!obj->phys_obj)
 		return;
+	vaddr = obj->phys_obj->handle->vaddr;
 
-	ret = i915_gem_object_get_pages(obj, 0);
-	if (ret)
-		goto out;
-
-	page_count = obj->size / PAGE_SIZE;
-
+	page_count = obj->base.size / PAGE_SIZE;
 	for (i = 0; i < page_count; i++) {
-		char *dst = kmap_atomic(obj_priv->pages[i]);
-		char *src = obj_priv->phys_obj->handle->vaddr + (i * PAGE_SIZE);
+		struct page *page = read_cache_page_gfp(mapping, i,
+							GFP_HIGHUSER | __GFP_RECLAIMABLE);
+		if (!IS_ERR(page)) {
+			char *dst = kmap_atomic(page);
+			memcpy(dst, vaddr + i*PAGE_SIZE, PAGE_SIZE);
+			kunmap_atomic(dst);
 
-		memcpy(dst, src, PAGE_SIZE);
-		kunmap_atomic(dst);
+			drm_clflush_pages(&page, 1);
+
+			set_page_dirty(page);
+			mark_page_accessed(page);
+			page_cache_release(page);
+		}
 	}
-	drm_clflush_pages(obj_priv->pages, page_count);
-	drm_agp_chipset_flush(dev);
+	intel_gtt_chipset_flush();
 
-	i915_gem_object_put_pages(obj);
-out:
-	obj_priv->phys_obj->cur_obj = NULL;
-	obj_priv->phys_obj = NULL;
+	obj->phys_obj->cur_obj = NULL;
+	obj->phys_obj = NULL;
 }
 
 int
 i915_gem_attach_phys_object(struct drm_device *dev,
-			    struct drm_gem_object *obj,
+			    struct drm_i915_gem_object *obj,
 			    int id,
 			    int align)
 {
+	struct address_space *mapping = obj->base.filp->f_path.dentry->d_inode->i_mapping;
 	drm_i915_private_t *dev_priv = dev->dev_private;
-	struct drm_i915_gem_object *obj_priv;
 	int ret = 0;
 	int page_count;
 	int i;
@@ -4966,10 +3957,8 @@ i915_gem_attach_phys_object(struct drm_d
 	if (id > I915_MAX_PHYS_OBJECT)
 		return -EINVAL;
 
-	obj_priv = to_intel_bo(obj);
-
-	if (obj_priv->phys_obj) {
-		if (obj_priv->phys_obj->id == id)
+	if (obj->phys_obj) {
+		if (obj->phys_obj->id == id)
 			return 0;
 		i915_gem_detach_phys_object(dev, obj);
 	}
@@ -4977,51 +3966,50 @@ i915_gem_attach_phys_object(struct drm_d
 	/* create a new object */
 	if (!dev_priv->mm.phys_objs[id - 1]) {
 		ret = i915_gem_init_phys_object(dev, id,
-						obj->size, align);
+						obj->base.size, align);
 		if (ret) {
-			DRM_ERROR("failed to init phys object %d size: %zu\n", id, obj->size);
-			goto out;
+			DRM_ERROR("failed to init phys object %d size: %zu\n",
+				  id, obj->base.size);
+			return ret;
 		}
 	}
 
 	/* bind to the object */
-	obj_priv->phys_obj = dev_priv->mm.phys_objs[id - 1];
-	obj_priv->phys_obj->cur_obj = obj;
-
-	ret = i915_gem_object_get_pages(obj, 0);
-	if (ret) {
-		DRM_ERROR("failed to get page list\n");
-		goto out;
-	}
+	obj->phys_obj = dev_priv->mm.phys_objs[id - 1];
+	obj->phys_obj->cur_obj = obj;
 
-	page_count = obj->size / PAGE_SIZE;
+	page_count = obj->base.size / PAGE_SIZE;
 
 	for (i = 0; i < page_count; i++) {
-		char *src = kmap_atomic(obj_priv->pages[i]);
-		char *dst = obj_priv->phys_obj->handle->vaddr + (i * PAGE_SIZE);
+		struct page *page;
+		char *dst, *src;
 
+		page = read_cache_page_gfp(mapping, i,
+					   GFP_HIGHUSER | __GFP_RECLAIMABLE);
+		if (IS_ERR(page))
+			return PTR_ERR(page);
+
+		src = kmap_atomic(page);
+		dst = obj->phys_obj->handle->vaddr + (i * PAGE_SIZE);
 		memcpy(dst, src, PAGE_SIZE);
 		kunmap_atomic(src);
-	}
 
-	i915_gem_object_put_pages(obj);
+		mark_page_accessed(page);
+		page_cache_release(page);
+	}
 
 	return 0;
-out:
-	return ret;
 }
 
 static int
-i915_gem_phys_pwrite(struct drm_device *dev, struct drm_gem_object *obj,
+i915_gem_phys_pwrite(struct drm_device *dev,
+		     struct drm_i915_gem_object *obj,
 		     struct drm_i915_gem_pwrite *args,
 		     struct drm_file *file_priv)
 {
-	struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
-	void *vaddr = obj_priv->phys_obj->handle->vaddr + args->offset;
+	void *vaddr = obj->phys_obj->handle->vaddr + args->offset;
 	char __user *user_data = (char __user *) (uintptr_t) args->data_ptr;
 
-	DRM_DEBUG_DRIVER("vaddr %p, %lld\n", vaddr, args->size);
-
 	if (__copy_from_user_inatomic_nocache(vaddr, user_data, args->size)) {
 		unsigned long unwritten;
 
@@ -5036,7 +4024,7 @@ i915_gem_phys_pwrite(struct drm_device *
 			return -EFAULT;
 	}
 
-	drm_agp_chipset_flush(dev);
+	intel_gtt_chipset_flush();
 	return 0;
 }
 
@@ -5074,144 +4062,68 @@ i915_gpu_is_active(struct drm_device *de
 }
 
 static int
-i915_gem_shrink(struct shrinker *shrink, int nr_to_scan, gfp_t gfp_mask)
+i915_gem_inactive_shrink(struct shrinker *shrinker,
+			 int nr_to_scan,
+			 gfp_t gfp_mask)
 {
-	drm_i915_private_t *dev_priv, *next_dev;
-	struct drm_i915_gem_object *obj_priv, *next_obj;
-	int cnt = 0;
-	int would_deadlock = 1;
+	struct drm_i915_private *dev_priv =
+		container_of(shrinker,
+			     struct drm_i915_private,
+			     mm.inactive_shrinker);
+	struct drm_device *dev = dev_priv->dev;
+	struct drm_i915_gem_object *obj, *next;
+	int cnt;
+
+	if (!mutex_trylock(&dev->struct_mutex))
+		return 0;
 
 	/* "fast-path" to count number of available objects */
 	if (nr_to_scan == 0) {
-		spin_lock(&shrink_list_lock);
-		list_for_each_entry(dev_priv, &shrink_list, mm.shrink_list) {
-			struct drm_device *dev = dev_priv->dev;
-
-			if (mutex_trylock(&dev->struct_mutex)) {
-				list_for_each_entry(obj_priv,
-						    &dev_priv->mm.inactive_list,
-						    mm_list)
-					cnt++;
-				mutex_unlock(&dev->struct_mutex);
-			}
-		}
-		spin_unlock(&shrink_list_lock);
-
-		return (cnt / 100) * sysctl_vfs_cache_pressure;
+		cnt = 0;
+		list_for_each_entry(obj,
+				    &dev_priv->mm.inactive_list,
+				    mm_list)
+			cnt++;
+		mutex_unlock(&dev->struct_mutex);
+		return cnt / 100 * sysctl_vfs_cache_pressure;
 	}
 
-	spin_lock(&shrink_list_lock);
-
 rescan:
 	/* first scan for clean buffers */
-	list_for_each_entry_safe(dev_priv, next_dev,
-				 &shrink_list, mm.shrink_list) {
-		struct drm_device *dev = dev_priv->dev;
-
-		if (! mutex_trylock(&dev->struct_mutex))
-			continue;
-
-		spin_unlock(&shrink_list_lock);
-		i915_gem_retire_requests(dev);
+	i915_gem_retire_requests(dev);
 
-		list_for_each_entry_safe(obj_priv, next_obj,
-					 &dev_priv->mm.inactive_list,
-					 mm_list) {
-			if (i915_gem_object_is_purgeable(obj_priv)) {
-				i915_gem_object_unbind(&obj_priv->base);
-				if (--nr_to_scan <= 0)
-					break;
-			}
+	list_for_each_entry_safe(obj, next,
+				 &dev_priv->mm.inactive_list,
+				 mm_list) {
+		if (i915_gem_object_is_purgeable(obj)) {
+			if (i915_gem_object_unbind(obj) == 0 &&
+			    --nr_to_scan == 0)
+				break;
 		}
-
-		spin_lock(&shrink_list_lock);
-		mutex_unlock(&dev->struct_mutex);
-
-		would_deadlock = 0;
-
-		if (nr_to_scan <= 0)
-			break;
 	}
 
 	/* second pass, evict/count anything still on the inactive list */
-	list_for_each_entry_safe(dev_priv, next_dev,
-				 &shrink_list, mm.shrink_list) {
-		struct drm_device *dev = dev_priv->dev;
-
-		if (! mutex_trylock(&dev->struct_mutex))
-			continue;
-
-		spin_unlock(&shrink_list_lock);
-
-		list_for_each_entry_safe(obj_priv, next_obj,
-					 &dev_priv->mm.inactive_list,
-					 mm_list) {
-			if (nr_to_scan > 0) {
-				i915_gem_object_unbind(&obj_priv->base);
-				nr_to_scan--;
-			} else
-				cnt++;
-		}
-
-		spin_lock(&shrink_list_lock);
-		mutex_unlock(&dev->struct_mutex);
-
-		would_deadlock = 0;
+	cnt = 0;
+	list_for_each_entry_safe(obj, next,
+				 &dev_priv->mm.inactive_list,
+				 mm_list) {
+		if (nr_to_scan &&
+		    i915_gem_object_unbind(obj) == 0)
+			nr_to_scan--;
+		else
+			cnt++;
 	}
 
-	if (nr_to_scan) {
-		int active = 0;
-
+	if (nr_to_scan && i915_gpu_is_active(dev)) {
 		/*
 		 * We are desperate for pages, so as a last resort, wait
 		 * for the GPU to finish and discard whatever we can.
 		 * This has a dramatic impact to reduce the number of
 		 * OOM-killer events whilst running the GPU aggressively.
 		 */
-		list_for_each_entry(dev_priv, &shrink_list, mm.shrink_list) {
-			struct drm_device *dev = dev_priv->dev;
-
-			if (!mutex_trylock(&dev->struct_mutex))
-				continue;
-
-			spin_unlock(&shrink_list_lock);
-
-			if (i915_gpu_is_active(dev)) {
-				i915_gpu_idle(dev);
-				active++;
-			}
-
-			spin_lock(&shrink_list_lock);
-			mutex_unlock(&dev->struct_mutex);
-		}
-
-		if (active)
+		if (i915_gpu_idle(dev) == 0)
 			goto rescan;
 	}
-
-	spin_unlock(&shrink_list_lock);
-
-	if (would_deadlock)
-		return -1;
-	else if (cnt > 0)
-		return (cnt / 100) * sysctl_vfs_cache_pressure;
-	else
-		return 0;
-}
-
-static struct shrinker shrinker = {
-	.shrink = i915_gem_shrink,
-	.seeks = DEFAULT_SEEKS,
-};
-
-__init void
-i915_gem_shrinker_init(void)
-{
-    register_shrinker(&shrinker);
-}
-
-__exit void
-i915_gem_shrinker_exit(void)
-{
-    unregister_shrinker(&shrinker);
+	mutex_unlock(&dev->struct_mutex);
+	return cnt / 100 * sysctl_vfs_cache_pressure;
 }
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/i915/i915_gem_debug.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/i915/i915_gem_debug.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/i915/i915_gem_debug.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/i915/i915_gem_debug.c	2011-03-14 21:20:32.000000000 -0400
@@ -152,13 +152,12 @@ i915_gem_dump_page(struct page *page, ui
 }
 
 void
-i915_gem_dump_object(struct drm_gem_object *obj, int len,
+i915_gem_dump_object(struct drm_i915_gem_object *obj, int len,
 		     const char *where, uint32_t mark)
 {
-	struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
 	int page;
 
-	DRM_INFO("%s: object at offset %08x\n", where, obj_priv->gtt_offset);
+	DRM_INFO("%s: object at offset %08x\n", where, obj->gtt_offset);
 	for (page = 0; page < (len + PAGE_SIZE-1) / PAGE_SIZE; page++) {
 		int page_len, chunk, chunk_len;
 
@@ -170,9 +169,9 @@ i915_gem_dump_object(struct drm_gem_obje
 			chunk_len = page_len - chunk;
 			if (chunk_len > 128)
 				chunk_len = 128;
-			i915_gem_dump_page(obj_priv->pages[page],
+			i915_gem_dump_page(obj->pages[page],
 					   chunk, chunk + chunk_len,
-					   obj_priv->gtt_offset +
+					   obj->gtt_offset +
 					   page * PAGE_SIZE,
 					   mark);
 		}
@@ -182,21 +181,19 @@ i915_gem_dump_object(struct drm_gem_obje
 
 #if WATCH_COHERENCY
 void
-i915_gem_object_check_coherency(struct drm_gem_object *obj, int handle)
+i915_gem_object_check_coherency(struct drm_i915_gem_object *obj, int handle)
 {
-	struct drm_device *dev = obj->dev;
-	struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
+	struct drm_device *dev = obj->base.dev;
 	int page;
 	uint32_t *gtt_mapping;
 	uint32_t *backing_map = NULL;
 	int bad_count = 0;
 
 	DRM_INFO("%s: checking coherency of object %p@0x%08x (%d, %zdkb):\n",
-		 __func__, obj, obj_priv->gtt_offset, handle,
+		 __func__, obj, obj->gtt_offset, handle,
 		 obj->size / 1024);
 
-	gtt_mapping = ioremap(dev->agp->base + obj_priv->gtt_offset,
-			      obj->size);
+	gtt_mapping = ioremap(dev->agp->base + obj->gtt_offset, obj->base.size);
 	if (gtt_mapping == NULL) {
 		DRM_ERROR("failed to map GTT space\n");
 		return;
@@ -205,7 +202,7 @@ i915_gem_object_check_coherency(struct d
 	for (page = 0; page < obj->size / PAGE_SIZE; page++) {
 		int i;
 
-		backing_map = kmap_atomic(obj_priv->pages[page], KM_USER0);
+		backing_map = kmap_atomic(obj->pages[page], KM_USER0);
 
 		if (backing_map == NULL) {
 			DRM_ERROR("failed to map backing page\n");
@@ -220,7 +217,7 @@ i915_gem_object_check_coherency(struct d
 			if (cpuval != gttval) {
 				DRM_INFO("incoherent CPU vs GPU at 0x%08x: "
 					 "0x%08x vs 0x%08x\n",
-					 (int)(obj_priv->gtt_offset +
+					 (int)(obj->gtt_offset +
 					       page * PAGE_SIZE + i * 4),
 					 cpuval, gttval);
 				if (bad_count++ >= 8) {
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/i915/i915_gem_evict.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/i915/i915_gem_evict.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/i915/i915_gem_evict.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/i915/i915_gem_evict.c	2011-03-14 21:20:32.000000000 -0400
@@ -32,28 +32,36 @@
 #include "i915_drm.h"
 
 static bool
-mark_free(struct drm_i915_gem_object *obj_priv,
-	   struct list_head *unwind)
+mark_free(struct drm_i915_gem_object *obj, struct list_head *unwind)
 {
-	list_add(&obj_priv->evict_list, unwind);
-	drm_gem_object_reference(&obj_priv->base);
-	return drm_mm_scan_add_block(obj_priv->gtt_space);
+	list_add(&obj->exec_list, unwind);
+	drm_gem_object_reference(&obj->base);
+	return drm_mm_scan_add_block(obj->gtt_space);
 }
 
 int
-i915_gem_evict_something(struct drm_device *dev, int min_size, unsigned alignment)
+i915_gem_evict_something(struct drm_device *dev, int min_size,
+			 unsigned alignment, bool mappable)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	struct list_head eviction_list, unwind_list;
-	struct drm_i915_gem_object *obj_priv;
+	struct drm_i915_gem_object *obj;
 	int ret = 0;
 
 	i915_gem_retire_requests(dev);
 
 	/* Re-check for free space after retiring requests */
-	if (drm_mm_search_free(&dev_priv->mm.gtt_space,
-			       min_size, alignment, 0))
-		return 0;
+	if (mappable) {
+		if (drm_mm_search_free_in_range(&dev_priv->mm.gtt_space,
+						min_size, alignment, 0,
+						dev_priv->mm.gtt_mappable_end,
+						0))
+			return 0;
+	} else {
+		if (drm_mm_search_free(&dev_priv->mm.gtt_space,
+				       min_size, alignment, 0))
+			return 0;
+	}
 
 	/*
 	 * The goal is to evict objects and amalgamate space in LRU order.
@@ -79,45 +87,56 @@ i915_gem_evict_something(struct drm_devi
 	 */
 
 	INIT_LIST_HEAD(&unwind_list);
-	drm_mm_init_scan(&dev_priv->mm.gtt_space, min_size, alignment);
+	if (mappable)
+		drm_mm_init_scan_with_range(&dev_priv->mm.gtt_space, min_size,
+					    alignment, 0,
+					    dev_priv->mm.gtt_mappable_end);
+	else
+		drm_mm_init_scan(&dev_priv->mm.gtt_space, min_size, alignment);
 
 	/* First see if there is a large enough contiguous idle region... */
-	list_for_each_entry(obj_priv, &dev_priv->mm.inactive_list, mm_list) {
-		if (mark_free(obj_priv, &unwind_list))
+	list_for_each_entry(obj, &dev_priv->mm.inactive_list, mm_list) {
+		if (mark_free(obj, &unwind_list))
 			goto found;
 	}
 
 	/* Now merge in the soon-to-be-expired objects... */
-	list_for_each_entry(obj_priv, &dev_priv->mm.active_list, mm_list) {
+	list_for_each_entry(obj, &dev_priv->mm.active_list, mm_list) {
 		/* Does the object require an outstanding flush? */
-		if (obj_priv->base.write_domain || obj_priv->pin_count)
+		if (obj->base.write_domain || obj->pin_count)
 			continue;
 
-		if (mark_free(obj_priv, &unwind_list))
+		if (mark_free(obj, &unwind_list))
 			goto found;
 	}
 
 	/* Finally add anything with a pending flush (in order of retirement) */
-	list_for_each_entry(obj_priv, &dev_priv->mm.flushing_list, mm_list) {
-		if (obj_priv->pin_count)
+	list_for_each_entry(obj, &dev_priv->mm.flushing_list, mm_list) {
+		if (obj->pin_count)
 			continue;
 
-		if (mark_free(obj_priv, &unwind_list))
+		if (mark_free(obj, &unwind_list))
 			goto found;
 	}
-	list_for_each_entry(obj_priv, &dev_priv->mm.active_list, mm_list) {
-		if (! obj_priv->base.write_domain || obj_priv->pin_count)
+	list_for_each_entry(obj, &dev_priv->mm.active_list, mm_list) {
+		if (! obj->base.write_domain || obj->pin_count)
 			continue;
 
-		if (mark_free(obj_priv, &unwind_list))
+		if (mark_free(obj, &unwind_list))
 			goto found;
 	}
 
 	/* Nothing found, clean up and bail out! */
-	list_for_each_entry(obj_priv, &unwind_list, evict_list) {
-		ret = drm_mm_scan_remove_block(obj_priv->gtt_space);
+	while (!list_empty(&unwind_list)) {
+		obj = list_first_entry(&unwind_list,
+				       struct drm_i915_gem_object,
+				       exec_list);
+
+		ret = drm_mm_scan_remove_block(obj->gtt_space);
 		BUG_ON(ret);
-		drm_gem_object_unreference(&obj_priv->base);
+
+		list_del_init(&obj->exec_list);
+		drm_gem_object_unreference(&obj->base);
 	}
 
 	/* We expect the caller to unpin, evict all and try again, or give up.
@@ -131,33 +150,34 @@ found:
 	 * temporary list. */
 	INIT_LIST_HEAD(&eviction_list);
 	while (!list_empty(&unwind_list)) {
-		obj_priv = list_first_entry(&unwind_list,
-					    struct drm_i915_gem_object,
-					    evict_list);
-		if (drm_mm_scan_remove_block(obj_priv->gtt_space)) {
-			list_move(&obj_priv->evict_list, &eviction_list);
+		obj = list_first_entry(&unwind_list,
+				       struct drm_i915_gem_object,
+				       exec_list);
+		if (drm_mm_scan_remove_block(obj->gtt_space)) {
+			list_move(&obj->exec_list, &eviction_list);
 			continue;
 		}
-		list_del(&obj_priv->evict_list);
-		drm_gem_object_unreference(&obj_priv->base);
+		list_del_init(&obj->exec_list);
+		drm_gem_object_unreference(&obj->base);
 	}
 
 	/* Unbinding will emit any required flushes */
 	while (!list_empty(&eviction_list)) {
-		obj_priv = list_first_entry(&eviction_list,
-					    struct drm_i915_gem_object,
-					    evict_list);
+		obj = list_first_entry(&eviction_list,
+				       struct drm_i915_gem_object,
+				       exec_list);
 		if (ret == 0)
-			ret = i915_gem_object_unbind(&obj_priv->base);
-		list_del(&obj_priv->evict_list);
-		drm_gem_object_unreference(&obj_priv->base);
+			ret = i915_gem_object_unbind(obj);
+
+		list_del_init(&obj->exec_list);
+		drm_gem_object_unreference(&obj->base);
 	}
 
 	return ret;
 }
 
 int
-i915_gem_evict_everything(struct drm_device *dev)
+i915_gem_evict_everything(struct drm_device *dev, bool purgeable_only)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	int ret;
@@ -176,36 +196,22 @@ i915_gem_evict_everything(struct drm_dev
 
 	BUG_ON(!list_empty(&dev_priv->mm.flushing_list));
 
-	ret = i915_gem_evict_inactive(dev);
-	if (ret)
-		return ret;
-
-	lists_empty = (list_empty(&dev_priv->mm.inactive_list) &&
-		       list_empty(&dev_priv->mm.flushing_list) &&
-		       list_empty(&dev_priv->mm.active_list));
-	BUG_ON(!lists_empty);
-
-	return 0;
+	return i915_gem_evict_inactive(dev, purgeable_only);
 }
 
 /** Unbinds all inactive objects. */
 int
-i915_gem_evict_inactive(struct drm_device *dev)
+i915_gem_evict_inactive(struct drm_device *dev, bool purgeable_only)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
+	struct drm_i915_gem_object *obj, *next;
 
-	while (!list_empty(&dev_priv->mm.inactive_list)) {
-		struct drm_gem_object *obj;
-		int ret;
-
-		obj = &list_first_entry(&dev_priv->mm.inactive_list,
-					struct drm_i915_gem_object,
-					mm_list)->base;
-
-		ret = i915_gem_object_unbind(obj);
-		if (ret != 0) {
-			DRM_ERROR("Error unbinding object: %d\n", ret);
-			return ret;
+	list_for_each_entry_safe(obj, next,
+				 &dev_priv->mm.inactive_list, mm_list) {
+		if (!purgeable_only || obj->madv != I915_MADV_WILLNEED) {
+			int ret = i915_gem_object_unbind(obj);
+			if (ret)
+				return ret;
 		}
 	}
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/i915/i915_gem_execbuffer.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/i915/i915_gem_execbuffer.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/i915/i915_gem_execbuffer.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/i915/i915_gem_execbuffer.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,1377 @@
+/*
+ * Copyright © 2008,2010 Intel Corporation
+ *
+ * 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
+ * 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.
+ *
+ * Authors:
+ *    Eric Anholt <eric@anholt.net>
+ *    Chris Wilson <chris@chris-wilson.co.uk>
+ *
+ */
+
+#include "drmP.h"
+#include "drm.h"
+#include "i915_drm.h"
+#include "i915_drv.h"
+#include "i915_trace.h"
+#include "intel_drv.h"
+
+struct change_domains {
+	uint32_t invalidate_domains;
+	uint32_t flush_domains;
+	uint32_t flush_rings;
+};
+
+/*
+ * Set the next domain for the specified object. This
+ * may not actually perform the necessary flushing/invaliding though,
+ * as that may want to be batched with other set_domain operations
+ *
+ * This is (we hope) the only really tricky part of gem. The goal
+ * is fairly simple -- track which caches hold bits of the object
+ * and make sure they remain coherent. A few concrete examples may
+ * help to explain how it works. For shorthand, we use the notation
+ * (read_domains, write_domain), e.g. (CPU, CPU) to indicate the
+ * a pair of read and write domain masks.
+ *
+ * Case 1: the batch buffer
+ *
+ *	1. Allocated
+ *	2. Written by CPU
+ *	3. Mapped to GTT
+ *	4. Read by GPU
+ *	5. Unmapped from GTT
+ *	6. Freed
+ *
+ *	Let's take these a step at a time
+ *
+ *	1. Allocated
+ *		Pages allocated from the kernel may still have
+ *		cache contents, so we set them to (CPU, CPU) always.
+ *	2. Written by CPU (using pwrite)
+ *		The pwrite function calls set_domain (CPU, CPU) and
+ *		this function does nothing (as nothing changes)
+ *	3. Mapped by GTT
+ *		This function asserts that the object is not
+ *		currently in any GPU-based read or write domains
+ *	4. Read by GPU
+ *		i915_gem_execbuffer calls set_domain (COMMAND, 0).
+ *		As write_domain is zero, this function adds in the
+ *		current read domains (CPU+COMMAND, 0).
+ *		flush_domains is set to CPU.
+ *		invalidate_domains is set to COMMAND
+ *		clflush is run to get data out of the CPU caches
+ *		then i915_dev_set_domain calls i915_gem_flush to
+ *		emit an MI_FLUSH and drm_agp_chipset_flush
+ *	5. Unmapped from GTT
+ *		i915_gem_object_unbind calls set_domain (CPU, CPU)
+ *		flush_domains and invalidate_domains end up both zero
+ *		so no flushing/invalidating happens
+ *	6. Freed
+ *		yay, done
+ *
+ * Case 2: The shared render buffer
+ *
+ *	1. Allocated
+ *	2. Mapped to GTT
+ *	3. Read/written by GPU
+ *	4. set_domain to (CPU,CPU)
+ *	5. Read/written by CPU
+ *	6. Read/written by GPU
+ *
+ *	1. Allocated
+ *		Same as last example, (CPU, CPU)
+ *	2. Mapped to GTT
+ *		Nothing changes (assertions find that it is not in the GPU)
+ *	3. Read/written by GPU
+ *		execbuffer calls set_domain (RENDER, RENDER)
+ *		flush_domains gets CPU
+ *		invalidate_domains gets GPU
+ *		clflush (obj)
+ *		MI_FLUSH and drm_agp_chipset_flush
+ *	4. set_domain (CPU, CPU)
+ *		flush_domains gets GPU
+ *		invalidate_domains gets CPU
+ *		wait_rendering (obj) to make sure all drawing is complete.
+ *		This will include an MI_FLUSH to get the data from GPU
+ *		to memory
+ *		clflush (obj) to invalidate the CPU cache
+ *		Another MI_FLUSH in i915_gem_flush (eliminate this somehow?)
+ *	5. Read/written by CPU
+ *		cache lines are loaded and dirtied
+ *	6. Read written by GPU
+ *		Same as last GPU access
+ *
+ * Case 3: The constant buffer
+ *
+ *	1. Allocated
+ *	2. Written by CPU
+ *	3. Read by GPU
+ *	4. Updated (written) by CPU again
+ *	5. Read by GPU
+ *
+ *	1. Allocated
+ *		(CPU, CPU)
+ *	2. Written by CPU
+ *		(CPU, CPU)
+ *	3. Read by GPU
+ *		(CPU+RENDER, 0)
+ *		flush_domains = CPU
+ *		invalidate_domains = RENDER
+ *		clflush (obj)
+ *		MI_FLUSH
+ *		drm_agp_chipset_flush
+ *	4. Updated (written) by CPU again
+ *		(CPU, CPU)
+ *		flush_domains = 0 (no previous write domain)
+ *		invalidate_domains = 0 (no new read domains)
+ *	5. Read by GPU
+ *		(CPU+RENDER, 0)
+ *		flush_domains = CPU
+ *		invalidate_domains = RENDER
+ *		clflush (obj)
+ *		MI_FLUSH
+ *		drm_agp_chipset_flush
+ */
+static void
+i915_gem_object_set_to_gpu_domain(struct drm_i915_gem_object *obj,
+				  struct intel_ring_buffer *ring,
+				  struct change_domains *cd)
+{
+	uint32_t invalidate_domains = 0, flush_domains = 0;
+
+	/*
+	 * If the object isn't moving to a new write domain,
+	 * let the object stay in multiple read domains
+	 */
+	if (obj->base.pending_write_domain == 0)
+		obj->base.pending_read_domains |= obj->base.read_domains;
+
+	/*
+	 * Flush the current write domain if
+	 * the new read domains don't match. Invalidate
+	 * any read domains which differ from the old
+	 * write domain
+	 */
+	if (obj->base.write_domain &&
+	    (((obj->base.write_domain != obj->base.pending_read_domains ||
+	       obj->ring != ring)) ||
+	     (obj->fenced_gpu_access && !obj->pending_fenced_gpu_access))) {
+		flush_domains |= obj->base.write_domain;
+		invalidate_domains |=
+			obj->base.pending_read_domains & ~obj->base.write_domain;
+	}
+	/*
+	 * Invalidate any read caches which may have
+	 * stale data. That is, any new read domains.
+	 */
+	invalidate_domains |= obj->base.pending_read_domains & ~obj->base.read_domains;
+	if ((flush_domains | invalidate_domains) & I915_GEM_DOMAIN_CPU)
+		i915_gem_clflush_object(obj);
+
+	/* blow away mappings if mapped through GTT */
+	if ((flush_domains | invalidate_domains) & I915_GEM_DOMAIN_GTT)
+		i915_gem_release_mmap(obj);
+
+	/* The actual obj->write_domain will be updated with
+	 * pending_write_domain after we emit the accumulated flush for all
+	 * of our domain changes in execbuffers (which clears objects'
+	 * write_domains).  So if we have a current write domain that we
+	 * aren't changing, set pending_write_domain to that.
+	 */
+	if (flush_domains == 0 && obj->base.pending_write_domain == 0)
+		obj->base.pending_write_domain = obj->base.write_domain;
+
+	cd->invalidate_domains |= invalidate_domains;
+	cd->flush_domains |= flush_domains;
+	if (flush_domains & I915_GEM_GPU_DOMAINS)
+		cd->flush_rings |= obj->ring->id;
+	if (invalidate_domains & I915_GEM_GPU_DOMAINS)
+		cd->flush_rings |= ring->id;
+}
+
+struct eb_objects {
+	int and;
+	struct hlist_head buckets[0];
+};
+
+static struct eb_objects *
+eb_create(int size)
+{
+	struct eb_objects *eb;
+	int count = PAGE_SIZE / sizeof(struct hlist_head) / 2;
+	while (count > size)
+		count >>= 1;
+	eb = kzalloc(count*sizeof(struct hlist_head) +
+		     sizeof(struct eb_objects),
+		     GFP_KERNEL);
+	if (eb == NULL)
+		return eb;
+
+	eb->and = count - 1;
+	return eb;
+}
+
+static void
+eb_reset(struct eb_objects *eb)
+{
+	memset(eb->buckets, 0, (eb->and+1)*sizeof(struct hlist_head));
+}
+
+static void
+eb_add_object(struct eb_objects *eb, struct drm_i915_gem_object *obj)
+{
+	hlist_add_head(&obj->exec_node,
+		       &eb->buckets[obj->exec_handle & eb->and]);
+}
+
+static struct drm_i915_gem_object *
+eb_get_object(struct eb_objects *eb, unsigned long handle)
+{
+	struct hlist_head *head;
+	struct hlist_node *node;
+	struct drm_i915_gem_object *obj;
+
+	head = &eb->buckets[handle & eb->and];
+	hlist_for_each(node, head) {
+		obj = hlist_entry(node, struct drm_i915_gem_object, exec_node);
+		if (obj->exec_handle == handle)
+			return obj;
+	}
+
+	return NULL;
+}
+
+static void
+eb_destroy(struct eb_objects *eb)
+{
+	kfree(eb);
+}
+
+static int
+i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj,
+				   struct eb_objects *eb,
+				   struct drm_i915_gem_relocation_entry *reloc)
+{
+	struct drm_device *dev = obj->base.dev;
+	struct drm_gem_object *target_obj;
+	uint32_t target_offset;
+	int ret = -EINVAL;
+
+	/* we've already hold a reference to all valid objects */
+	target_obj = &eb_get_object(eb, reloc->target_handle)->base;
+	if (unlikely(target_obj == NULL))
+		return -ENOENT;
+
+	target_offset = to_intel_bo(target_obj)->gtt_offset;
+
+#if WATCH_RELOC
+	DRM_INFO("%s: obj %p offset %08x target %d "
+		 "read %08x write %08x gtt %08x "
+		 "presumed %08x delta %08x\n",
+		 __func__,
+		 obj,
+		 (int) reloc->offset,
+		 (int) reloc->target_handle,
+		 (int) reloc->read_domains,
+		 (int) reloc->write_domain,
+		 (int) target_offset,
+		 (int) reloc->presumed_offset,
+		 reloc->delta);
+#endif
+
+	/* The target buffer should have appeared before us in the
+	 * exec_object list, so it should have a GTT space bound by now.
+	 */
+	if (unlikely(target_offset == 0)) {
+		DRM_ERROR("No GTT space found for object %d\n",
+			  reloc->target_handle);
+		return ret;
+	}
+
+	/* Validate that the target is in a valid r/w GPU domain */
+	if (unlikely(reloc->write_domain & (reloc->write_domain - 1))) {
+		DRM_ERROR("reloc with multiple write domains: "
+			  "obj %p target %d offset %d "
+			  "read %08x write %08x",
+			  obj, reloc->target_handle,
+			  (int) reloc->offset,
+			  reloc->read_domains,
+			  reloc->write_domain);
+		return ret;
+	}
+	if (unlikely((reloc->write_domain | reloc->read_domains) & I915_GEM_DOMAIN_CPU)) {
+		DRM_ERROR("reloc with read/write CPU domains: "
+			  "obj %p target %d offset %d "
+			  "read %08x write %08x",
+			  obj, reloc->target_handle,
+			  (int) reloc->offset,
+			  reloc->read_domains,
+			  reloc->write_domain);
+		return ret;
+	}
+	if (unlikely(reloc->write_domain && target_obj->pending_write_domain &&
+		     reloc->write_domain != target_obj->pending_write_domain)) {
+		DRM_ERROR("Write domain conflict: "
+			  "obj %p target %d offset %d "
+			  "new %08x old %08x\n",
+			  obj, reloc->target_handle,
+			  (int) reloc->offset,
+			  reloc->write_domain,
+			  target_obj->pending_write_domain);
+		return ret;
+	}
+
+	target_obj->pending_read_domains |= reloc->read_domains;
+	target_obj->pending_write_domain |= reloc->write_domain;
+
+	/* If the relocation already has the right value in it, no
+	 * more work needs to be done.
+	 */
+	if (target_offset == reloc->presumed_offset)
+		return 0;
+
+	/* Check that the relocation address is valid... */
+	if (unlikely(reloc->offset > obj->base.size - 4)) {
+		DRM_ERROR("Relocation beyond object bounds: "
+			  "obj %p target %d offset %d size %d.\n",
+			  obj, reloc->target_handle,
+			  (int) reloc->offset,
+			  (int) obj->base.size);
+		return ret;
+	}
+	if (unlikely(reloc->offset & 3)) {
+		DRM_ERROR("Relocation not 4-byte aligned: "
+			  "obj %p target %d offset %d.\n",
+			  obj, reloc->target_handle,
+			  (int) reloc->offset);
+		return ret;
+	}
+
+	/* and points to somewhere within the target object. */
+	if (unlikely(reloc->delta >= target_obj->size)) {
+		DRM_ERROR("Relocation beyond target object bounds: "
+			  "obj %p target %d delta %d size %d.\n",
+			  obj, reloc->target_handle,
+			  (int) reloc->delta,
+			  (int) target_obj->size);
+		return ret;
+	}
+
+	reloc->delta += target_offset;
+	if (obj->base.write_domain == I915_GEM_DOMAIN_CPU) {
+		uint32_t page_offset = reloc->offset & ~PAGE_MASK;
+		char *vaddr;
+
+		vaddr = kmap_atomic(obj->pages[reloc->offset >> PAGE_SHIFT]);
+		*(uint32_t *)(vaddr + page_offset) = reloc->delta;
+		kunmap_atomic(vaddr);
+	} else {
+		struct drm_i915_private *dev_priv = dev->dev_private;
+		uint32_t __iomem *reloc_entry;
+		void __iomem *reloc_page;
+
+		ret = i915_gem_object_set_to_gtt_domain(obj, 1);
+		if (ret)
+			return ret;
+
+		/* Map the page containing the relocation we're going to perform.  */
+		reloc->offset += obj->gtt_offset;
+		reloc_page = io_mapping_map_atomic_wc(dev_priv->mm.gtt_mapping,
+						      reloc->offset & PAGE_MASK);
+		reloc_entry = (uint32_t __iomem *)
+			(reloc_page + (reloc->offset & ~PAGE_MASK));
+		iowrite32(reloc->delta, reloc_entry);
+		io_mapping_unmap_atomic(reloc_page);
+	}
+
+	/* and update the user's relocation entry */
+	reloc->presumed_offset = target_offset;
+
+	return 0;
+}
+
+static int
+i915_gem_execbuffer_relocate_object(struct drm_i915_gem_object *obj,
+				    struct eb_objects *eb)
+{
+	struct drm_i915_gem_relocation_entry __user *user_relocs;
+	struct drm_i915_gem_exec_object2 *entry = obj->exec_entry;
+	int i, ret;
+
+	user_relocs = (void __user *)(uintptr_t)entry->relocs_ptr;
+	for (i = 0; i < entry->relocation_count; i++) {
+		struct drm_i915_gem_relocation_entry reloc;
+
+		if (__copy_from_user_inatomic(&reloc,
+					      user_relocs+i,
+					      sizeof(reloc)))
+			return -EFAULT;
+
+		ret = i915_gem_execbuffer_relocate_entry(obj, eb, &reloc);
+		if (ret)
+			return ret;
+
+		if (__copy_to_user_inatomic(&user_relocs[i].presumed_offset,
+					    &reloc.presumed_offset,
+					    sizeof(reloc.presumed_offset)))
+			return -EFAULT;
+	}
+
+	return 0;
+}
+
+static int
+i915_gem_execbuffer_relocate_object_slow(struct drm_i915_gem_object *obj,
+					 struct eb_objects *eb,
+					 struct drm_i915_gem_relocation_entry *relocs)
+{
+	const struct drm_i915_gem_exec_object2 *entry = obj->exec_entry;
+	int i, ret;
+
+	for (i = 0; i < entry->relocation_count; i++) {
+		ret = i915_gem_execbuffer_relocate_entry(obj, eb, &relocs[i]);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static int
+i915_gem_execbuffer_relocate(struct drm_device *dev,
+			     struct eb_objects *eb,
+			     struct list_head *objects)
+{
+	struct drm_i915_gem_object *obj;
+	int ret;
+
+	list_for_each_entry(obj, objects, exec_list) {
+		ret = i915_gem_execbuffer_relocate_object(obj, eb);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static int
+i915_gem_execbuffer_reserve(struct intel_ring_buffer *ring,
+			    struct drm_file *file,
+			    struct list_head *objects)
+{
+	struct drm_i915_gem_object *obj;
+	int ret, retry;
+	bool has_fenced_gpu_access = INTEL_INFO(ring->dev)->gen < 4;
+	struct list_head ordered_objects;
+
+	INIT_LIST_HEAD(&ordered_objects);
+	while (!list_empty(objects)) {
+		struct drm_i915_gem_exec_object2 *entry;
+		bool need_fence, need_mappable;
+
+		obj = list_first_entry(objects,
+				       struct drm_i915_gem_object,
+				       exec_list);
+		entry = obj->exec_entry;
+
+		need_fence =
+			has_fenced_gpu_access &&
+			entry->flags & EXEC_OBJECT_NEEDS_FENCE &&
+			obj->tiling_mode != I915_TILING_NONE;
+		need_mappable =
+			entry->relocation_count ? true : need_fence;
+
+		if (need_mappable)
+			list_move(&obj->exec_list, &ordered_objects);
+		else
+			list_move_tail(&obj->exec_list, &ordered_objects);
+
+		obj->base.pending_read_domains = 0;
+		obj->base.pending_write_domain = 0;
+	}
+	list_splice(&ordered_objects, objects);
+
+	/* Attempt to pin all of the buffers into the GTT.
+	 * This is done in 3 phases:
+	 *
+	 * 1a. Unbind all objects that do not match the GTT constraints for
+	 *     the execbuffer (fenceable, mappable, alignment etc).
+	 * 1b. Increment pin count for already bound objects.
+	 * 2.  Bind new objects.
+	 * 3.  Decrement pin count.
+	 *
+	 * This avoid unnecessary unbinding of later objects in order to makr
+	 * room for the earlier objects *unless* we need to defragment.
+	 */
+	retry = 0;
+	do {
+		ret = 0;
+
+		/* Unbind any ill-fitting objects or pin. */
+		list_for_each_entry(obj, objects, exec_list) {
+			struct drm_i915_gem_exec_object2 *entry = obj->exec_entry;
+			bool need_fence, need_mappable;
+			if (!obj->gtt_space)
+				continue;
+
+			need_fence =
+				has_fenced_gpu_access &&
+				entry->flags & EXEC_OBJECT_NEEDS_FENCE &&
+				obj->tiling_mode != I915_TILING_NONE;
+			need_mappable =
+				entry->relocation_count ? true : need_fence;
+
+			if ((entry->alignment && obj->gtt_offset & (entry->alignment - 1)) ||
+			    (need_mappable && !obj->map_and_fenceable))
+				ret = i915_gem_object_unbind(obj);
+			else
+				ret = i915_gem_object_pin(obj,
+							  entry->alignment,
+							  need_mappable);
+			if (ret)
+				goto err;
+
+			entry++;
+		}
+
+		/* Bind fresh objects */
+		list_for_each_entry(obj, objects, exec_list) {
+			struct drm_i915_gem_exec_object2 *entry = obj->exec_entry;
+			bool need_fence;
+
+			need_fence =
+				has_fenced_gpu_access &&
+				entry->flags & EXEC_OBJECT_NEEDS_FENCE &&
+				obj->tiling_mode != I915_TILING_NONE;
+
+			if (!obj->gtt_space) {
+				bool need_mappable =
+					entry->relocation_count ? true : need_fence;
+
+				ret = i915_gem_object_pin(obj,
+							  entry->alignment,
+							  need_mappable);
+				if (ret)
+					break;
+			}
+
+			if (has_fenced_gpu_access) {
+				if (need_fence) {
+					ret = i915_gem_object_get_fence(obj, ring, 1);
+					if (ret)
+						break;
+				} else if (entry->flags & EXEC_OBJECT_NEEDS_FENCE &&
+					   obj->tiling_mode == I915_TILING_NONE) {
+					/* XXX pipelined! */
+					ret = i915_gem_object_put_fence(obj);
+					if (ret)
+						break;
+				}
+				obj->pending_fenced_gpu_access = need_fence;
+			}
+
+			entry->offset = obj->gtt_offset;
+		}
+
+		/* Decrement pin count for bound objects */
+		list_for_each_entry(obj, objects, exec_list) {
+			if (obj->gtt_space)
+				i915_gem_object_unpin(obj);
+		}
+
+		if (ret != -ENOSPC || retry > 1)
+			return ret;
+
+		/* First attempt, just clear anything that is purgeable.
+		 * Second attempt, clear the entire GTT.
+		 */
+		ret = i915_gem_evict_everything(ring->dev, retry == 0);
+		if (ret)
+			return ret;
+
+		retry++;
+	} while (1);
+
+err:
+	obj = list_entry(obj->exec_list.prev,
+			 struct drm_i915_gem_object,
+			 exec_list);
+	while (objects != &obj->exec_list) {
+		if (obj->gtt_space)
+			i915_gem_object_unpin(obj);
+
+		obj = list_entry(obj->exec_list.prev,
+				 struct drm_i915_gem_object,
+				 exec_list);
+	}
+
+	return ret;
+}
+
+static int
+i915_gem_execbuffer_relocate_slow(struct drm_device *dev,
+				  struct drm_file *file,
+				  struct intel_ring_buffer *ring,
+				  struct list_head *objects,
+				  struct eb_objects *eb,
+				  struct drm_i915_gem_exec_object2 *exec,
+				  int count)
+{
+	struct drm_i915_gem_relocation_entry *reloc;
+	struct drm_i915_gem_object *obj;
+	int *reloc_offset;
+	int i, total, ret;
+
+	/* We may process another execbuffer during the unlock... */
+	while (!list_empty(objects)) {
+		obj = list_first_entry(objects,
+				       struct drm_i915_gem_object,
+				       exec_list);
+		list_del_init(&obj->exec_list);
+		drm_gem_object_unreference(&obj->base);
+	}
+
+	mutex_unlock(&dev->struct_mutex);
+
+	total = 0;
+	for (i = 0; i < count; i++)
+		total += exec[i].relocation_count;
+
+	reloc_offset = drm_malloc_ab(count, sizeof(*reloc_offset));
+	reloc = drm_malloc_ab(total, sizeof(*reloc));
+	if (reloc == NULL || reloc_offset == NULL) {
+		drm_free_large(reloc);
+		drm_free_large(reloc_offset);
+		mutex_lock(&dev->struct_mutex);
+		return -ENOMEM;
+	}
+
+	total = 0;
+	for (i = 0; i < count; i++) {
+		struct drm_i915_gem_relocation_entry __user *user_relocs;
+
+		user_relocs = (void __user *)(uintptr_t)exec[i].relocs_ptr;
+
+		if (copy_from_user(reloc+total, user_relocs,
+				   exec[i].relocation_count * sizeof(*reloc))) {
+			ret = -EFAULT;
+			mutex_lock(&dev->struct_mutex);
+			goto err;
+		}
+
+		reloc_offset[i] = total;
+		total += exec[i].relocation_count;
+	}
+
+	ret = i915_mutex_lock_interruptible(dev);
+	if (ret) {
+		mutex_lock(&dev->struct_mutex);
+		goto err;
+	}
+
+	/* reacquire the objects */
+	eb_reset(eb);
+	for (i = 0; i < count; i++) {
+		struct drm_i915_gem_object *obj;
+
+		obj = to_intel_bo(drm_gem_object_lookup(dev, file,
+							exec[i].handle));
+		if (obj == NULL) {
+			DRM_ERROR("Invalid object handle %d at index %d\n",
+				   exec[i].handle, i);
+			ret = -ENOENT;
+			goto err;
+		}
+
+		list_add_tail(&obj->exec_list, objects);
+		obj->exec_handle = exec[i].handle;
+		obj->exec_entry = &exec[i];
+		eb_add_object(eb, obj);
+	}
+
+	ret = i915_gem_execbuffer_reserve(ring, file, objects);
+	if (ret)
+		goto err;
+
+	list_for_each_entry(obj, objects, exec_list) {
+		int offset = obj->exec_entry - exec;
+		ret = i915_gem_execbuffer_relocate_object_slow(obj, eb,
+							       reloc + reloc_offset[offset]);
+		if (ret)
+			goto err;
+	}
+
+	/* Leave the user relocations as are, this is the painfully slow path,
+	 * and we want to avoid the complication of dropping the lock whilst
+	 * having buffers reserved in the aperture and so causing spurious
+	 * ENOSPC for random operations.
+	 */
+
+err:
+	drm_free_large(reloc);
+	drm_free_large(reloc_offset);
+	return ret;
+}
+
+static int
+i915_gem_execbuffer_flush(struct drm_device *dev,
+			  uint32_t invalidate_domains,
+			  uint32_t flush_domains,
+			  uint32_t flush_rings)
+{
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	int i, ret;
+
+	if (flush_domains & I915_GEM_DOMAIN_CPU)
+		intel_gtt_chipset_flush();
+
+	if (flush_domains & I915_GEM_DOMAIN_GTT)
+		wmb();
+
+	if ((flush_domains | invalidate_domains) & I915_GEM_GPU_DOMAINS) {
+		for (i = 0; i < I915_NUM_RINGS; i++)
+			if (flush_rings & (1 << i)) {
+				ret = i915_gem_flush_ring(dev,
+							  &dev_priv->ring[i],
+							  invalidate_domains,
+							  flush_domains);
+				if (ret)
+					return ret;
+			}
+	}
+
+	return 0;
+}
+
+static int
+i915_gem_execbuffer_sync_rings(struct drm_i915_gem_object *obj,
+			       struct intel_ring_buffer *to)
+{
+	struct intel_ring_buffer *from = obj->ring;
+	u32 seqno;
+	int ret, idx;
+
+	if (from == NULL || to == from)
+		return 0;
+
+	/* XXX gpu semaphores are implicated in various hard hangs on SNB */
+	if (INTEL_INFO(obj->base.dev)->gen < 6 || !i915_semaphores)
+		return i915_gem_object_wait_rendering(obj, true);
+
+	idx = intel_ring_sync_index(from, to);
+
+	seqno = obj->last_rendering_seqno;
+	if (seqno <= from->sync_seqno[idx])
+		return 0;
+
+	if (seqno == from->outstanding_lazy_request) {
+		struct drm_i915_gem_request *request;
+
+		request = kzalloc(sizeof(*request), GFP_KERNEL);
+		if (request == NULL)
+			return -ENOMEM;
+
+		ret = i915_add_request(obj->base.dev, NULL, request, from);
+		if (ret) {
+			kfree(request);
+			return ret;
+		}
+
+		seqno = request->seqno;
+	}
+
+	from->sync_seqno[idx] = seqno;
+	return intel_ring_sync(to, from, seqno - 1);
+}
+
+static int
+i915_gem_execbuffer_move_to_gpu(struct intel_ring_buffer *ring,
+				struct list_head *objects)
+{
+	struct drm_i915_gem_object *obj;
+	struct change_domains cd;
+	int ret;
+
+	cd.invalidate_domains = 0;
+	cd.flush_domains = 0;
+	cd.flush_rings = 0;
+	list_for_each_entry(obj, objects, exec_list)
+		i915_gem_object_set_to_gpu_domain(obj, ring, &cd);
+
+	if (cd.invalidate_domains | cd.flush_domains) {
+#if WATCH_EXEC
+		DRM_INFO("%s: invalidate_domains %08x flush_domains %08x\n",
+			  __func__,
+			 cd.invalidate_domains,
+			 cd.flush_domains);
+#endif
+		ret = i915_gem_execbuffer_flush(ring->dev,
+						cd.invalidate_domains,
+						cd.flush_domains,
+						cd.flush_rings);
+		if (ret)
+			return ret;
+	}
+
+	list_for_each_entry(obj, objects, exec_list) {
+		ret = i915_gem_execbuffer_sync_rings(obj, ring);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static bool
+i915_gem_check_execbuffer(struct drm_i915_gem_execbuffer2 *exec)
+{
+	return ((exec->batch_start_offset | exec->batch_len) & 0x7) == 0;
+}
+
+static int
+validate_exec_list(struct drm_i915_gem_exec_object2 *exec,
+		   int count)
+{
+	int i;
+
+	for (i = 0; i < count; i++) {
+		char __user *ptr = (char __user *)(uintptr_t)exec[i].relocs_ptr;
+		int length; /* limited by fault_in_pages_readable() */
+
+		/* First check for malicious input causing overflow */
+		if (exec[i].relocation_count >
+		    INT_MAX / sizeof(struct drm_i915_gem_relocation_entry))
+			return -EINVAL;
+
+		length = exec[i].relocation_count *
+			sizeof(struct drm_i915_gem_relocation_entry);
+		if (!access_ok(VERIFY_READ, ptr, length))
+			return -EFAULT;
+
+		/* we may also need to update the presumed offsets */
+		if (!access_ok(VERIFY_WRITE, ptr, length))
+			return -EFAULT;
+
+		if (fault_in_pages_readable(ptr, length))
+			return -EFAULT;
+	}
+
+	return 0;
+}
+
+static int
+i915_gem_execbuffer_wait_for_flips(struct intel_ring_buffer *ring,
+				   struct list_head *objects)
+{
+	struct drm_i915_gem_object *obj;
+	int flips;
+
+	/* Check for any pending flips. As we only maintain a flip queue depth
+	 * of 1, we can simply insert a WAIT for the next display flip prior
+	 * to executing the batch and avoid stalling the CPU.
+	 */
+	flips = 0;
+	list_for_each_entry(obj, objects, exec_list) {
+		if (obj->base.write_domain)
+			flips |= atomic_read(&obj->pending_flip);
+	}
+	if (flips) {
+		int plane, flip_mask, ret;
+
+		for (plane = 0; flips >> plane; plane++) {
+			if (((flips >> plane) & 1) == 0)
+				continue;
+
+			if (plane)
+				flip_mask = MI_WAIT_FOR_PLANE_B_FLIP;
+			else
+				flip_mask = MI_WAIT_FOR_PLANE_A_FLIP;
+
+			ret = intel_ring_begin(ring, 2);
+			if (ret)
+				return ret;
+
+			intel_ring_emit(ring, MI_WAIT_FOR_EVENT | flip_mask);
+			intel_ring_emit(ring, MI_NOOP);
+			intel_ring_advance(ring);
+		}
+	}
+
+	return 0;
+}
+
+static void
+i915_gem_execbuffer_move_to_active(struct list_head *objects,
+				   struct intel_ring_buffer *ring,
+				   u32 seqno)
+{
+	struct drm_i915_gem_object *obj;
+
+	list_for_each_entry(obj, objects, exec_list) {
+		obj->base.read_domains = obj->base.pending_read_domains;
+		obj->base.write_domain = obj->base.pending_write_domain;
+		obj->fenced_gpu_access = obj->pending_fenced_gpu_access;
+
+		i915_gem_object_move_to_active(obj, ring, seqno);
+		if (obj->base.write_domain) {
+			obj->dirty = 1;
+			obj->pending_gpu_write = true;
+			list_move_tail(&obj->gpu_write_list,
+				       &ring->gpu_write_list);
+			intel_mark_busy(ring->dev, obj);
+		}
+
+		trace_i915_gem_object_change_domain(obj,
+						    obj->base.read_domains,
+						    obj->base.write_domain);
+	}
+}
+
+static void
+i915_gem_execbuffer_retire_commands(struct drm_device *dev,
+				    struct drm_file *file,
+				    struct intel_ring_buffer *ring)
+{
+	struct drm_i915_gem_request *request;
+	u32 invalidate;
+
+	/*
+	 * Ensure that the commands in the batch buffer are
+	 * finished before the interrupt fires.
+	 *
+	 * The sampler always gets flushed on i965 (sigh).
+	 */
+	invalidate = I915_GEM_DOMAIN_COMMAND;
+	if (INTEL_INFO(dev)->gen >= 4)
+		invalidate |= I915_GEM_DOMAIN_SAMPLER;
+	if (ring->flush(ring, invalidate, 0)) {
+		i915_gem_next_request_seqno(dev, ring);
+		return;
+	}
+
+	/* Add a breadcrumb for the completion of the batch buffer */
+	request = kzalloc(sizeof(*request), GFP_KERNEL);
+	if (request == NULL || i915_add_request(dev, file, request, ring)) {
+		i915_gem_next_request_seqno(dev, ring);
+		kfree(request);
+	}
+}
+
+static int
+i915_gem_do_execbuffer(struct drm_device *dev, void *data,
+		       struct drm_file *file,
+		       struct drm_i915_gem_execbuffer2 *args,
+		       struct drm_i915_gem_exec_object2 *exec)
+{
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	struct list_head objects;
+	struct eb_objects *eb;
+	struct drm_i915_gem_object *batch_obj;
+	struct drm_clip_rect *cliprects = NULL;
+	struct intel_ring_buffer *ring;
+	u32 exec_start, exec_len;
+	u32 seqno;
+	int ret, mode, i;
+
+	if (!i915_gem_check_execbuffer(args)) {
+		DRM_ERROR("execbuf with invalid offset/length\n");
+		return -EINVAL;
+	}
+
+	ret = validate_exec_list(exec, args->buffer_count);
+	if (ret)
+		return ret;
+
+#if WATCH_EXEC
+	DRM_INFO("buffers_ptr %d buffer_count %d len %08x\n",
+		  (int) args->buffers_ptr, args->buffer_count, args->batch_len);
+#endif
+	switch (args->flags & I915_EXEC_RING_MASK) {
+	case I915_EXEC_DEFAULT:
+	case I915_EXEC_RENDER:
+		ring = &dev_priv->ring[RCS];
+		break;
+	case I915_EXEC_BSD:
+		if (!HAS_BSD(dev)) {
+			DRM_ERROR("execbuf with invalid ring (BSD)\n");
+			return -EINVAL;
+		}
+		ring = &dev_priv->ring[VCS];
+		break;
+	case I915_EXEC_BLT:
+		if (!HAS_BLT(dev)) {
+			DRM_ERROR("execbuf with invalid ring (BLT)\n");
+			return -EINVAL;
+		}
+		ring = &dev_priv->ring[BCS];
+		break;
+	default:
+		DRM_ERROR("execbuf with unknown ring: %d\n",
+			  (int)(args->flags & I915_EXEC_RING_MASK));
+		return -EINVAL;
+	}
+
+	mode = args->flags & I915_EXEC_CONSTANTS_MASK;
+	switch (mode) {
+	case I915_EXEC_CONSTANTS_REL_GENERAL:
+	case I915_EXEC_CONSTANTS_ABSOLUTE:
+	case I915_EXEC_CONSTANTS_REL_SURFACE:
+		if (ring == &dev_priv->ring[RCS] &&
+		    mode != dev_priv->relative_constants_mode) {
+			if (INTEL_INFO(dev)->gen < 4)
+				return -EINVAL;
+
+			if (INTEL_INFO(dev)->gen > 5 &&
+			    mode == I915_EXEC_CONSTANTS_REL_SURFACE)
+				return -EINVAL;
+
+			ret = intel_ring_begin(ring, 4);
+			if (ret)
+				return ret;
+
+			intel_ring_emit(ring, MI_NOOP);
+			intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1));
+			intel_ring_emit(ring, INSTPM);
+			intel_ring_emit(ring,
+					I915_EXEC_CONSTANTS_MASK << 16 | mode);
+			intel_ring_advance(ring);
+
+			dev_priv->relative_constants_mode = mode;
+		}
+		break;
+	default:
+		DRM_ERROR("execbuf with unknown constants: %d\n", mode);
+		return -EINVAL;
+	}
+
+	if (args->buffer_count < 1) {
+		DRM_ERROR("execbuf with %d buffers\n", args->buffer_count);
+		return -EINVAL;
+	}
+
+	if (args->num_cliprects != 0) {
+		if (ring != &dev_priv->ring[RCS]) {
+			DRM_ERROR("clip rectangles are only valid with the render ring\n");
+			return -EINVAL;
+		}
+
+		cliprects = kmalloc(args->num_cliprects * sizeof(*cliprects),
+				    GFP_KERNEL);
+		if (cliprects == NULL) {
+			ret = -ENOMEM;
+			goto pre_mutex_err;
+		}
+
+		if (copy_from_user(cliprects,
+				     (struct drm_clip_rect __user *)(uintptr_t)
+				     args->cliprects_ptr,
+				     sizeof(*cliprects)*args->num_cliprects)) {
+			ret = -EFAULT;
+			goto pre_mutex_err;
+		}
+	}
+
+	ret = i915_mutex_lock_interruptible(dev);
+	if (ret)
+		goto pre_mutex_err;
+
+	if (dev_priv->mm.suspended) {
+		mutex_unlock(&dev->struct_mutex);
+		ret = -EBUSY;
+		goto pre_mutex_err;
+	}
+
+	eb = eb_create(args->buffer_count);
+	if (eb == NULL) {
+		mutex_unlock(&dev->struct_mutex);
+		ret = -ENOMEM;
+		goto pre_mutex_err;
+	}
+
+	/* Look up object handles */
+	INIT_LIST_HEAD(&objects);
+	for (i = 0; i < args->buffer_count; i++) {
+		struct drm_i915_gem_object *obj;
+
+		obj = to_intel_bo(drm_gem_object_lookup(dev, file,
+							exec[i].handle));
+		if (obj == NULL) {
+			DRM_ERROR("Invalid object handle %d at index %d\n",
+				   exec[i].handle, i);
+			/* prevent error path from reading uninitialized data */
+			ret = -ENOENT;
+			goto err;
+		}
+
+		if (!list_empty(&obj->exec_list)) {
+			DRM_ERROR("Object %p [handle %d, index %d] appears more than once in object list\n",
+				   obj, exec[i].handle, i);
+			ret = -EINVAL;
+			goto err;
+		}
+
+		list_add_tail(&obj->exec_list, &objects);
+		obj->exec_handle = exec[i].handle;
+		obj->exec_entry = &exec[i];
+		eb_add_object(eb, obj);
+	}
+
+	/* take note of the batch buffer before we might reorder the lists */
+	batch_obj = list_entry(objects.prev,
+			       struct drm_i915_gem_object,
+			       exec_list);
+
+	/* Move the objects en-masse into the GTT, evicting if necessary. */
+	ret = i915_gem_execbuffer_reserve(ring, file, &objects);
+	if (ret)
+		goto err;
+
+	/* The objects are in their final locations, apply the relocations. */
+	ret = i915_gem_execbuffer_relocate(dev, eb, &objects);
+	if (ret) {
+		if (ret == -EFAULT) {
+			ret = i915_gem_execbuffer_relocate_slow(dev, file, ring,
+								&objects, eb,
+								exec,
+								args->buffer_count);
+			BUG_ON(!mutex_is_locked(&dev->struct_mutex));
+		}
+		if (ret)
+			goto err;
+	}
+
+	/* Set the pending read domains for the batch buffer to COMMAND */
+	if (batch_obj->base.pending_write_domain) {
+		DRM_ERROR("Attempting to use self-modifying batch buffer\n");
+		ret = -EINVAL;
+		goto err;
+	}
+	batch_obj->base.pending_read_domains |= I915_GEM_DOMAIN_COMMAND;
+
+	ret = i915_gem_execbuffer_move_to_gpu(ring, &objects);
+	if (ret)
+		goto err;
+
+	ret = i915_gem_execbuffer_wait_for_flips(ring, &objects);
+	if (ret)
+		goto err;
+
+	seqno = i915_gem_next_request_seqno(dev, ring);
+	for (i = 0; i < ARRAY_SIZE(ring->sync_seqno); i++) {
+		if (seqno < ring->sync_seqno[i]) {
+			/* The GPU can not handle its semaphore value wrapping,
+			 * so every billion or so execbuffers, we need to stall
+			 * the GPU in order to reset the counters.
+			 */
+			ret = i915_gpu_idle(dev);
+			if (ret)
+				goto err;
+
+			BUG_ON(ring->sync_seqno[i]);
+		}
+	}
+
+	exec_start = batch_obj->gtt_offset + args->batch_start_offset;
+	exec_len = args->batch_len;
+	if (cliprects) {
+		for (i = 0; i < args->num_cliprects; i++) {
+			ret = i915_emit_box(dev, &cliprects[i],
+					    args->DR1, args->DR4);
+			if (ret)
+				goto err;
+
+			ret = ring->dispatch_execbuffer(ring,
+							exec_start, exec_len);
+			if (ret)
+				goto err;
+		}
+	} else {
+		ret = ring->dispatch_execbuffer(ring, exec_start, exec_len);
+		if (ret)
+			goto err;
+	}
+
+	i915_gem_execbuffer_move_to_active(&objects, ring, seqno);
+	i915_gem_execbuffer_retire_commands(dev, file, ring);
+
+err:
+	eb_destroy(eb);
+	while (!list_empty(&objects)) {
+		struct drm_i915_gem_object *obj;
+
+		obj = list_first_entry(&objects,
+				       struct drm_i915_gem_object,
+				       exec_list);
+		list_del_init(&obj->exec_list);
+		drm_gem_object_unreference(&obj->base);
+	}
+
+	mutex_unlock(&dev->struct_mutex);
+
+pre_mutex_err:
+	kfree(cliprects);
+	return ret;
+}
+
+/*
+ * Legacy execbuffer just creates an exec2 list from the original exec object
+ * list array and passes it to the real function.
+ */
+int
+i915_gem_execbuffer(struct drm_device *dev, void *data,
+		    struct drm_file *file)
+{
+	struct drm_i915_gem_execbuffer *args = data;
+	struct drm_i915_gem_execbuffer2 exec2;
+	struct drm_i915_gem_exec_object *exec_list = NULL;
+	struct drm_i915_gem_exec_object2 *exec2_list = NULL;
+	int ret, i;
+
+#if WATCH_EXEC
+	DRM_INFO("buffers_ptr %d buffer_count %d len %08x\n",
+		  (int) args->buffers_ptr, args->buffer_count, args->batch_len);
+#endif
+
+	if (args->buffer_count < 1) {
+		DRM_ERROR("execbuf with %d buffers\n", args->buffer_count);
+		return -EINVAL;
+	}
+
+	/* Copy in the exec list from userland */
+	exec_list = drm_malloc_ab(sizeof(*exec_list), args->buffer_count);
+	exec2_list = drm_malloc_ab(sizeof(*exec2_list), args->buffer_count);
+	if (exec_list == NULL || exec2_list == NULL) {
+		DRM_ERROR("Failed to allocate exec list for %d buffers\n",
+			  args->buffer_count);
+		drm_free_large(exec_list);
+		drm_free_large(exec2_list);
+		return -ENOMEM;
+	}
+	ret = copy_from_user(exec_list,
+			     (struct drm_i915_relocation_entry __user *)
+			     (uintptr_t) args->buffers_ptr,
+			     sizeof(*exec_list) * args->buffer_count);
+	if (ret != 0) {
+		DRM_ERROR("copy %d exec entries failed %d\n",
+			  args->buffer_count, ret);
+		drm_free_large(exec_list);
+		drm_free_large(exec2_list);
+		return -EFAULT;
+	}
+
+	for (i = 0; i < args->buffer_count; i++) {
+		exec2_list[i].handle = exec_list[i].handle;
+		exec2_list[i].relocation_count = exec_list[i].relocation_count;
+		exec2_list[i].relocs_ptr = exec_list[i].relocs_ptr;
+		exec2_list[i].alignment = exec_list[i].alignment;
+		exec2_list[i].offset = exec_list[i].offset;
+		if (INTEL_INFO(dev)->gen < 4)
+			exec2_list[i].flags = EXEC_OBJECT_NEEDS_FENCE;
+		else
+			exec2_list[i].flags = 0;
+	}
+
+	exec2.buffers_ptr = args->buffers_ptr;
+	exec2.buffer_count = args->buffer_count;
+	exec2.batch_start_offset = args->batch_start_offset;
+	exec2.batch_len = args->batch_len;
+	exec2.DR1 = args->DR1;
+	exec2.DR4 = args->DR4;
+	exec2.num_cliprects = args->num_cliprects;
+	exec2.cliprects_ptr = args->cliprects_ptr;
+	exec2.flags = I915_EXEC_RENDER;
+
+	ret = i915_gem_do_execbuffer(dev, data, file, &exec2, exec2_list);
+	if (!ret) {
+		/* Copy the new buffer offsets back to the user's exec list. */
+		for (i = 0; i < args->buffer_count; i++)
+			exec_list[i].offset = exec2_list[i].offset;
+		/* ... and back out to userspace */
+		ret = copy_to_user((struct drm_i915_relocation_entry __user *)
+				   (uintptr_t) args->buffers_ptr,
+				   exec_list,
+				   sizeof(*exec_list) * args->buffer_count);
+		if (ret) {
+			ret = -EFAULT;
+			DRM_ERROR("failed to copy %d exec entries "
+				  "back to user (%d)\n",
+				  args->buffer_count, ret);
+		}
+	}
+
+	drm_free_large(exec_list);
+	drm_free_large(exec2_list);
+	return ret;
+}
+
+int
+i915_gem_execbuffer2(struct drm_device *dev, void *data,
+		     struct drm_file *file)
+{
+	struct drm_i915_gem_execbuffer2 *args = data;
+	struct drm_i915_gem_exec_object2 *exec2_list = NULL;
+	int ret;
+
+#if WATCH_EXEC
+	DRM_INFO("buffers_ptr %d buffer_count %d len %08x\n",
+		  (int) args->buffers_ptr, args->buffer_count, args->batch_len);
+#endif
+
+	if (args->buffer_count < 1) {
+		DRM_ERROR("execbuf2 with %d buffers\n", args->buffer_count);
+		return -EINVAL;
+	}
+
+	exec2_list = drm_malloc_ab(sizeof(*exec2_list), args->buffer_count);
+	if (exec2_list == NULL) {
+		DRM_ERROR("Failed to allocate exec list for %d buffers\n",
+			  args->buffer_count);
+		return -ENOMEM;
+	}
+	ret = copy_from_user(exec2_list,
+			     (struct drm_i915_relocation_entry __user *)
+			     (uintptr_t) args->buffers_ptr,
+			     sizeof(*exec2_list) * args->buffer_count);
+	if (ret != 0) {
+		DRM_ERROR("copy %d exec entries failed %d\n",
+			  args->buffer_count, ret);
+		drm_free_large(exec2_list);
+		return -EFAULT;
+	}
+
+	ret = i915_gem_do_execbuffer(dev, data, file, args, exec2_list);
+	if (!ret) {
+		/* Copy the new buffer offsets back to the user's exec list. */
+		ret = copy_to_user((struct drm_i915_relocation_entry __user *)
+				   (uintptr_t) args->buffers_ptr,
+				   exec2_list,
+				   sizeof(*exec2_list) * args->buffer_count);
+		if (ret) {
+			ret = -EFAULT;
+			DRM_ERROR("failed to copy %d exec entries "
+				  "back to user (%d)\n",
+				  args->buffer_count, ret);
+		}
+	}
+
+	drm_free_large(exec2_list);
+	return ret;
+}
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/i915/i915_gem_gtt.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/i915/i915_gem_gtt.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/i915/i915_gem_gtt.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/i915/i915_gem_gtt.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,99 @@
+/*
+ * Copyright © 2010 Daniel Vetter
+ *
+ * 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
+ * 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 "drmP.h"
+#include "drm.h"
+#include "i915_drm.h"
+#include "i915_drv.h"
+#include "i915_trace.h"
+#include "intel_drv.h"
+
+void i915_gem_restore_gtt_mappings(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_i915_gem_object *obj;
+
+	/* First fill our portion of the GTT with scratch pages */
+	intel_gtt_clear_range(dev_priv->mm.gtt_start / PAGE_SIZE,
+			      (dev_priv->mm.gtt_end - dev_priv->mm.gtt_start) / PAGE_SIZE);
+
+	list_for_each_entry(obj, &dev_priv->mm.gtt_list, gtt_list) {
+		i915_gem_clflush_object(obj);
+
+		if (dev_priv->mm.gtt->needs_dmar) {
+			BUG_ON(!obj->sg_list);
+
+			intel_gtt_insert_sg_entries(obj->sg_list,
+						    obj->num_sg,
+						    obj->gtt_space->start
+							>> PAGE_SHIFT,
+						    obj->agp_type);
+		} else
+			intel_gtt_insert_pages(obj->gtt_space->start
+						   >> PAGE_SHIFT,
+					       obj->base.size >> PAGE_SHIFT,
+					       obj->pages,
+					       obj->agp_type);
+	}
+
+	intel_gtt_chipset_flush();
+}
+
+int i915_gem_gtt_bind_object(struct drm_i915_gem_object *obj)
+{
+	struct drm_device *dev = obj->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	int ret;
+
+	if (dev_priv->mm.gtt->needs_dmar) {
+		ret = intel_gtt_map_memory(obj->pages,
+					   obj->base.size >> PAGE_SHIFT,
+					   &obj->sg_list,
+					   &obj->num_sg);
+		if (ret != 0)
+			return ret;
+
+		intel_gtt_insert_sg_entries(obj->sg_list,
+					    obj->num_sg,
+					    obj->gtt_space->start >> PAGE_SHIFT,
+					    obj->agp_type);
+	} else
+		intel_gtt_insert_pages(obj->gtt_space->start >> PAGE_SHIFT,
+				       obj->base.size >> PAGE_SHIFT,
+				       obj->pages,
+				       obj->agp_type);
+
+	return 0;
+}
+
+void i915_gem_gtt_unbind_object(struct drm_i915_gem_object *obj)
+{
+	intel_gtt_clear_range(obj->gtt_space->start >> PAGE_SHIFT,
+			      obj->base.size >> PAGE_SHIFT);
+
+	if (obj->sg_list) {
+		intel_gtt_unmap_memory(obj->sg_list, obj->num_sg);
+		obj->sg_list = NULL;
+	}
+}
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/i915/i915_gem_tiling.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/i915/i915_gem_tiling.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/i915/i915_gem_tiling.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/i915/i915_gem_tiling.c	2011-03-14 21:20:32.000000000 -0400
@@ -181,7 +181,7 @@ i915_gem_detect_bit_6_swizzle(struct drm
 }
 
 /* Check pitch constriants for all chips & tiling formats */
-bool
+static bool
 i915_tiling_ok(struct drm_device *dev, int stride, int size, int tiling_mode)
 {
 	int tile_width;
@@ -232,32 +232,44 @@ i915_tiling_ok(struct drm_device *dev, i
 	return true;
 }
 
-bool
-i915_gem_object_fence_offset_ok(struct drm_gem_object *obj, int tiling_mode)
+/* Is the current GTT allocation valid for the change in tiling? */
+static bool
+i915_gem_object_fence_ok(struct drm_i915_gem_object *obj, int tiling_mode)
 {
-	struct drm_device *dev = obj->dev;
-	struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
-
-	if (obj_priv->gtt_space == NULL)
-		return true;
+	u32 size;
 
 	if (tiling_mode == I915_TILING_NONE)
 		return true;
 
-	if (INTEL_INFO(dev)->gen >= 4)
+	if (INTEL_INFO(obj->base.dev)->gen >= 4)
 		return true;
 
-	if (obj_priv->gtt_offset & (obj->size - 1))
-		return false;
-
-	if (IS_GEN3(dev)) {
-		if (obj_priv->gtt_offset & ~I915_FENCE_START_MASK)
+	if (INTEL_INFO(obj->base.dev)->gen == 3) {
+		if (obj->gtt_offset & ~I915_FENCE_START_MASK)
 			return false;
 	} else {
-		if (obj_priv->gtt_offset & ~I830_FENCE_START_MASK)
+		if (obj->gtt_offset & ~I830_FENCE_START_MASK)
 			return false;
 	}
 
+	/*
+	 * Previous chips need to be aligned to the size of the smallest
+	 * fence register that can contain the object.
+	 */
+	if (INTEL_INFO(obj->base.dev)->gen == 3)
+		size = 1024*1024;
+	else
+		size = 512*1024;
+
+	while (size < obj->base.size)
+		size <<= 1;
+
+	if (obj->gtt_space->size != size)
+		return false;
+
+	if (obj->gtt_offset & (size - 1))
+		return false;
+
 	return true;
 }
 
@@ -267,30 +279,29 @@ i915_gem_object_fence_offset_ok(struct d
  */
 int
 i915_gem_set_tiling(struct drm_device *dev, void *data,
-		   struct drm_file *file_priv)
+		   struct drm_file *file)
 {
 	struct drm_i915_gem_set_tiling *args = data;
 	drm_i915_private_t *dev_priv = dev->dev_private;
-	struct drm_gem_object *obj;
-	struct drm_i915_gem_object *obj_priv;
+	struct drm_i915_gem_object *obj;
 	int ret;
 
 	ret = i915_gem_check_is_wedged(dev);
 	if (ret)
 		return ret;
 
-	obj = drm_gem_object_lookup(dev, file_priv, args->handle);
+	obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle));
 	if (obj == NULL)
 		return -ENOENT;
-	obj_priv = to_intel_bo(obj);
 
-	if (!i915_tiling_ok(dev, args->stride, obj->size, args->tiling_mode)) {
-		drm_gem_object_unreference_unlocked(obj);
+	if (!i915_tiling_ok(dev,
+			    args->stride, obj->base.size, args->tiling_mode)) {
+		drm_gem_object_unreference_unlocked(&obj->base);
 		return -EINVAL;
 	}
 
-	if (obj_priv->pin_count) {
-		drm_gem_object_unreference_unlocked(obj);
+	if (obj->pin_count) {
+		drm_gem_object_unreference_unlocked(&obj->base);
 		return -EBUSY;
 	}
 
@@ -324,31 +335,38 @@ i915_gem_set_tiling(struct drm_device *d
 	}
 
 	mutex_lock(&dev->struct_mutex);
-	if (args->tiling_mode != obj_priv->tiling_mode ||
-	    args->stride != obj_priv->stride) {
+	if (args->tiling_mode != obj->tiling_mode ||
+	    args->stride != obj->stride) {
 		/* We need to rebind the object if its current allocation
 		 * no longer meets the alignment restrictions for its new
 		 * tiling mode. Otherwise we can just leave it alone, but
 		 * need to ensure that any fence register is cleared.
 		 */
-		if (!i915_gem_object_fence_offset_ok(obj, args->tiling_mode))
-			ret = i915_gem_object_unbind(obj);
-		else if (obj_priv->fence_reg != I915_FENCE_REG_NONE)
-			ret = i915_gem_object_put_fence_reg(obj, true);
-		else
-			i915_gem_release_mmap(obj);
+		i915_gem_release_mmap(obj);
 
-		if (ret != 0) {
-			args->tiling_mode = obj_priv->tiling_mode;
-			args->stride = obj_priv->stride;
-			goto err;
+		obj->map_and_fenceable =
+			obj->gtt_space == NULL ||
+			(obj->gtt_offset + obj->base.size <= dev_priv->mm.gtt_mappable_end &&
+			 i915_gem_object_fence_ok(obj, args->tiling_mode));
+
+		/* Rebind if we need a change of alignment */
+		if (!obj->map_and_fenceable) {
+			u32 unfenced_alignment =
+				i915_gem_get_unfenced_gtt_alignment(obj);
+			if (obj->gtt_offset & (unfenced_alignment - 1))
+				ret = i915_gem_object_unbind(obj);
 		}
 
-		obj_priv->tiling_mode = args->tiling_mode;
-		obj_priv->stride = args->stride;
+		if (ret == 0) {
+			obj->tiling_changed = true;
+			obj->tiling_mode = args->tiling_mode;
+			obj->stride = args->stride;
+		}
 	}
-err:
-	drm_gem_object_unreference(obj);
+	/* we have to maintain this existing ABI... */
+	args->stride = obj->stride;
+	args->tiling_mode = obj->tiling_mode;
+	drm_gem_object_unreference(&obj->base);
 	mutex_unlock(&dev->struct_mutex);
 
 	return ret;
@@ -359,22 +377,20 @@ err:
  */
 int
 i915_gem_get_tiling(struct drm_device *dev, void *data,
-		   struct drm_file *file_priv)
+		   struct drm_file *file)
 {
 	struct drm_i915_gem_get_tiling *args = data;
 	drm_i915_private_t *dev_priv = dev->dev_private;
-	struct drm_gem_object *obj;
-	struct drm_i915_gem_object *obj_priv;
+	struct drm_i915_gem_object *obj;
 
-	obj = drm_gem_object_lookup(dev, file_priv, args->handle);
+	obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle));
 	if (obj == NULL)
 		return -ENOENT;
-	obj_priv = to_intel_bo(obj);
 
 	mutex_lock(&dev->struct_mutex);
 
-	args->tiling_mode = obj_priv->tiling_mode;
-	switch (obj_priv->tiling_mode) {
+	args->tiling_mode = obj->tiling_mode;
+	switch (obj->tiling_mode) {
 	case I915_TILING_X:
 		args->swizzle_mode = dev_priv->mm.bit_6_swizzle_x;
 		break;
@@ -394,7 +410,7 @@ i915_gem_get_tiling(struct drm_device *d
 	if (args->swizzle_mode == I915_BIT_6_SWIZZLE_9_10_17)
 		args->swizzle_mode = I915_BIT_6_SWIZZLE_9_10;
 
-	drm_gem_object_unreference(obj);
+	drm_gem_object_unreference(&obj->base);
 	mutex_unlock(&dev->struct_mutex);
 
 	return 0;
@@ -424,46 +440,44 @@ i915_gem_swizzle_page(struct page *page)
 }
 
 void
-i915_gem_object_do_bit_17_swizzle(struct drm_gem_object *obj)
+i915_gem_object_do_bit_17_swizzle(struct drm_i915_gem_object *obj)
 {
-	struct drm_device *dev = obj->dev;
+	struct drm_device *dev = obj->base.dev;
 	drm_i915_private_t *dev_priv = dev->dev_private;
-	struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
-	int page_count = obj->size >> PAGE_SHIFT;
+	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_priv->bit_17 == NULL)
+	if (obj->bit_17 == NULL)
 		return;
 
 	for (i = 0; i < page_count; i++) {
-		char new_bit_17 = page_to_phys(obj_priv->pages[i]) >> 17;
+		char new_bit_17 = page_to_phys(obj->pages[i]) >> 17;
 		if ((new_bit_17 & 0x1) !=
-		    (test_bit(i, obj_priv->bit_17) != 0)) {
-			i915_gem_swizzle_page(obj_priv->pages[i]);
-			set_page_dirty(obj_priv->pages[i]);
+		    (test_bit(i, obj->bit_17) != 0)) {
+			i915_gem_swizzle_page(obj->pages[i]);
+			set_page_dirty(obj->pages[i]);
 		}
 	}
 }
 
 void
-i915_gem_object_save_bit_17_swizzle(struct drm_gem_object *obj)
+i915_gem_object_save_bit_17_swizzle(struct drm_i915_gem_object *obj)
 {
-	struct drm_device *dev = obj->dev;
+	struct drm_device *dev = obj->base.dev;
 	drm_i915_private_t *dev_priv = dev->dev_private;
-	struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
-	int page_count = obj->size >> PAGE_SHIFT;
+	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_priv->bit_17 == NULL) {
-		obj_priv->bit_17 = kmalloc(BITS_TO_LONGS(page_count) *
+	if (obj->bit_17 == NULL) {
+		obj->bit_17 = kmalloc(BITS_TO_LONGS(page_count) *
 					   sizeof(long), GFP_KERNEL);
-		if (obj_priv->bit_17 == NULL) {
+		if (obj->bit_17 == NULL) {
 			DRM_ERROR("Failed to allocate memory for bit 17 "
 				  "record\n");
 			return;
@@ -471,9 +485,9 @@ i915_gem_object_save_bit_17_swizzle(stru
 	}
 
 	for (i = 0; i < page_count; i++) {
-		if (page_to_phys(obj_priv->pages[i]) & (1 << 17))
-			__set_bit(i, obj_priv->bit_17);
+		if (page_to_phys(obj->pages[i]) & (1 << 17))
+			__set_bit(i, obj->bit_17);
 		else
-			__clear_bit(i, obj_priv->bit_17);
+			__clear_bit(i, obj->bit_17);
 	}
 }
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/i915/i915_irq.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/i915/i915_irq.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/i915/i915_irq.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/i915/i915_irq.c	2011-03-14 21:20:32.000000000 -0400
@@ -64,64 +64,24 @@
 #define DRM_I915_VBLANK_PIPE_ALL	(DRM_I915_VBLANK_PIPE_A | \
 					 DRM_I915_VBLANK_PIPE_B)
 
-void
-ironlake_enable_graphics_irq(drm_i915_private_t *dev_priv, u32 mask)
-{
-	if ((dev_priv->gt_irq_mask_reg & mask) != 0) {
-		dev_priv->gt_irq_mask_reg &= ~mask;
-		I915_WRITE(GTIMR, dev_priv->gt_irq_mask_reg);
-		(void) I915_READ(GTIMR);
-	}
-}
-
-void
-ironlake_disable_graphics_irq(drm_i915_private_t *dev_priv, u32 mask)
-{
-	if ((dev_priv->gt_irq_mask_reg & mask) != mask) {
-		dev_priv->gt_irq_mask_reg |= mask;
-		I915_WRITE(GTIMR, dev_priv->gt_irq_mask_reg);
-		(void) I915_READ(GTIMR);
-	}
-}
-
 /* For display hotplug interrupt */
 static void
 ironlake_enable_display_irq(drm_i915_private_t *dev_priv, u32 mask)
 {
-	if ((dev_priv->irq_mask_reg & mask) != 0) {
-		dev_priv->irq_mask_reg &= ~mask;
-		I915_WRITE(DEIMR, dev_priv->irq_mask_reg);
-		(void) I915_READ(DEIMR);
+	if ((dev_priv->irq_mask & mask) != 0) {
+		dev_priv->irq_mask &= ~mask;
+		I915_WRITE(DEIMR, dev_priv->irq_mask);
+		POSTING_READ(DEIMR);
 	}
 }
 
 static inline void
 ironlake_disable_display_irq(drm_i915_private_t *dev_priv, u32 mask)
 {
-	if ((dev_priv->irq_mask_reg & mask) != mask) {
-		dev_priv->irq_mask_reg |= mask;
-		I915_WRITE(DEIMR, dev_priv->irq_mask_reg);
-		(void) I915_READ(DEIMR);
-	}
-}
-
-void
-i915_enable_irq(drm_i915_private_t *dev_priv, u32 mask)
-{
-	if ((dev_priv->irq_mask_reg & mask) != 0) {
-		dev_priv->irq_mask_reg &= ~mask;
-		I915_WRITE(IMR, dev_priv->irq_mask_reg);
-		(void) I915_READ(IMR);
-	}
-}
-
-void
-i915_disable_irq(drm_i915_private_t *dev_priv, u32 mask)
-{
-	if ((dev_priv->irq_mask_reg & mask) != mask) {
-		dev_priv->irq_mask_reg |= mask;
-		I915_WRITE(IMR, dev_priv->irq_mask_reg);
-		(void) I915_READ(IMR);
+	if ((dev_priv->irq_mask & mask) != mask) {
+		dev_priv->irq_mask |= mask;
+		I915_WRITE(DEIMR, dev_priv->irq_mask);
+		POSTING_READ(DEIMR);
 	}
 }
 
@@ -144,7 +104,7 @@ i915_enable_pipestat(drm_i915_private_t
 		dev_priv->pipestat[pipe] |= mask;
 		/* Enable the interrupt, clear any pending status */
 		I915_WRITE(reg, dev_priv->pipestat[pipe] | (mask >> 16));
-		(void) I915_READ(reg);
+		POSTING_READ(reg);
 	}
 }
 
@@ -156,16 +116,19 @@ i915_disable_pipestat(drm_i915_private_t
 
 		dev_priv->pipestat[pipe] &= ~mask;
 		I915_WRITE(reg, dev_priv->pipestat[pipe]);
-		(void) I915_READ(reg);
+		POSTING_READ(reg);
 	}
 }
 
 /**
  * intel_enable_asle - enable ASLE interrupt for OpRegion
  */
-void intel_enable_asle (struct drm_device *dev)
+void intel_enable_asle(struct drm_device *dev)
 {
-	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	unsigned long irqflags;
+
+	spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
 
 	if (HAS_PCH_SPLIT(dev))
 		ironlake_enable_display_irq(dev_priv, DE_GSE);
@@ -176,6 +139,8 @@ void intel_enable_asle (struct drm_devic
 			i915_enable_pipestat(dev_priv, 0,
 					     PIPE_LEGACY_BLC_EVENT_ENABLE);
 	}
+
+	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
 }
 
 /**
@@ -243,6 +208,103 @@ u32 gm45_get_vblank_counter(struct drm_d
 	return I915_READ(reg);
 }
 
+int i915_get_crtc_scanoutpos(struct drm_device *dev, int pipe,
+			     int *vpos, int *hpos)
+{
+	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+	u32 vbl = 0, position = 0;
+	int vbl_start, vbl_end, htotal, vtotal;
+	bool in_vbl = true;
+	int ret = 0;
+
+	if (!i915_pipe_enabled(dev, pipe)) {
+		DRM_DEBUG_DRIVER("trying to get scanoutpos for disabled "
+					"pipe %d\n", pipe);
+		return 0;
+	}
+
+	/* Get vtotal. */
+	vtotal = 1 + ((I915_READ(VTOTAL(pipe)) >> 16) & 0x1fff);
+
+	if (INTEL_INFO(dev)->gen >= 4) {
+		/* No obvious pixelcount register. Only query vertical
+		 * scanout position from Display scan line register.
+		 */
+		position = I915_READ(PIPEDSL(pipe));
+
+		/* Decode into vertical scanout position. Don't have
+		 * horizontal scanout position.
+		 */
+		*vpos = position & 0x1fff;
+		*hpos = 0;
+	} else {
+		/* Have access to pixelcount since start of frame.
+		 * We can split this into vertical and horizontal
+		 * scanout position.
+		 */
+		position = (I915_READ(PIPEFRAMEPIXEL(pipe)) & PIPE_PIXEL_MASK) >> PIPE_PIXEL_SHIFT;
+
+		htotal = 1 + ((I915_READ(HTOTAL(pipe)) >> 16) & 0x1fff);
+		*vpos = position / htotal;
+		*hpos = position - (*vpos * htotal);
+	}
+
+	/* Query vblank area. */
+	vbl = I915_READ(VBLANK(pipe));
+
+	/* Test position against vblank region. */
+	vbl_start = vbl & 0x1fff;
+	vbl_end = (vbl >> 16) & 0x1fff;
+
+	if ((*vpos < vbl_start) || (*vpos > vbl_end))
+		in_vbl = false;
+
+	/* Inside "upper part" of vblank area? Apply corrective offset: */
+	if (in_vbl && (*vpos >= vbl_start))
+		*vpos = *vpos - vtotal;
+
+	/* Readouts valid? */
+	if (vbl > 0)
+		ret |= DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_ACCURATE;
+
+	/* In vblank? */
+	if (in_vbl)
+		ret |= DRM_SCANOUTPOS_INVBL;
+
+	return ret;
+}
+
+int i915_get_vblank_timestamp(struct drm_device *dev, int pipe,
+			      int *max_error,
+			      struct timeval *vblank_time,
+			      unsigned flags)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_crtc *crtc;
+
+	if (pipe < 0 || pipe >= dev_priv->num_pipe) {
+		DRM_ERROR("Invalid crtc %d\n", pipe);
+		return -EINVAL;
+	}
+
+	/* Get drm_crtc to timestamp: */
+	crtc = intel_get_crtc_for_pipe(dev, pipe);
+	if (crtc == NULL) {
+		DRM_ERROR("Invalid crtc %d\n", pipe);
+		return -EINVAL;
+	}
+
+	if (!crtc->enabled) {
+		DRM_DEBUG_KMS("crtc %d is disabled\n", pipe);
+		return -EBUSY;
+	}
+
+	/* Helper routine in DRM core does all the work: */
+	return drm_calc_vbltimestamp_from_scanoutpos(dev, pipe, max_error,
+						     vblank_time, flags,
+						     crtc);
+}
+
 /*
  * Handle hotplug events outside the interrupt handler proper.
  */
@@ -254,6 +316,8 @@ static void i915_hotplug_work_func(struc
 	struct drm_mode_config *mode_config = &dev->mode_config;
 	struct intel_encoder *encoder;
 
+	DRM_DEBUG_KMS("running encoder hotplug functions\n");
+
 	list_for_each_entry(encoder, &mode_config->encoder_list, base.head)
 		if (encoder->hot_plug)
 			encoder->hot_plug(encoder);
@@ -297,20 +361,109 @@ static void notify_ring(struct drm_devic
 			struct intel_ring_buffer *ring)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	u32 seqno = ring->get_seqno(dev, ring);
-	ring->irq_gem_seqno = seqno;
+	u32 seqno;
+
+	if (ring->obj == NULL)
+		return;
+
+	seqno = ring->get_seqno(ring);
 	trace_i915_gem_request_complete(dev, seqno);
+
+	ring->irq_seqno = seqno;
 	wake_up_all(&ring->irq_queue);
+
 	dev_priv->hangcheck_count = 0;
 	mod_timer(&dev_priv->hangcheck_timer,
 		  jiffies + msecs_to_jiffies(DRM_I915_HANGCHECK_PERIOD));
 }
 
+static void gen6_pm_irq_handler(struct drm_device *dev)
+{
+	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+	u8 new_delay = dev_priv->cur_delay;
+	u32 pm_iir;
+
+	pm_iir = I915_READ(GEN6_PMIIR);
+	if (!pm_iir)
+		return;
+
+	if (pm_iir & GEN6_PM_RP_UP_THRESHOLD) {
+		if (dev_priv->cur_delay != dev_priv->max_delay)
+			new_delay = dev_priv->cur_delay + 1;
+		if (new_delay > dev_priv->max_delay)
+			new_delay = dev_priv->max_delay;
+	} else if (pm_iir & (GEN6_PM_RP_DOWN_THRESHOLD | GEN6_PM_RP_DOWN_TIMEOUT)) {
+		if (dev_priv->cur_delay != dev_priv->min_delay)
+			new_delay = dev_priv->cur_delay - 1;
+		if (new_delay < dev_priv->min_delay) {
+			new_delay = dev_priv->min_delay;
+			I915_WRITE(GEN6_RP_INTERRUPT_LIMITS,
+				   I915_READ(GEN6_RP_INTERRUPT_LIMITS) |
+				   ((new_delay << 16) & 0x3f0000));
+		} else {
+			/* Make sure we continue to get down interrupts
+			 * until we hit the minimum frequency */
+			I915_WRITE(GEN6_RP_INTERRUPT_LIMITS,
+				   I915_READ(GEN6_RP_INTERRUPT_LIMITS) & ~0x3f0000);
+		}
+
+	}
+
+	gen6_set_rps(dev, new_delay);
+	dev_priv->cur_delay = new_delay;
+
+	I915_WRITE(GEN6_PMIIR, pm_iir);
+}
+
+static void pch_irq_handler(struct drm_device *dev)
+{
+	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+	u32 pch_iir;
+
+	pch_iir = I915_READ(SDEIIR);
+
+	if (pch_iir & SDE_AUDIO_POWER_MASK)
+		DRM_DEBUG_DRIVER("PCH audio power change on port %d\n",
+				 (pch_iir & SDE_AUDIO_POWER_MASK) >>
+				 SDE_AUDIO_POWER_SHIFT);
+
+	if (pch_iir & SDE_GMBUS)
+		DRM_DEBUG_DRIVER("PCH GMBUS interrupt\n");
+
+	if (pch_iir & SDE_AUDIO_HDCP_MASK)
+		DRM_DEBUG_DRIVER("PCH HDCP audio interrupt\n");
+
+	if (pch_iir & SDE_AUDIO_TRANS_MASK)
+		DRM_DEBUG_DRIVER("PCH transcoder audio interrupt\n");
+
+	if (pch_iir & SDE_POISON)
+		DRM_ERROR("PCH poison interrupt\n");
+
+	if (pch_iir & SDE_FDI_MASK) {
+		u32 fdia, fdib;
+
+		fdia = I915_READ(FDI_RXA_IIR);
+		fdib = I915_READ(FDI_RXB_IIR);
+		DRM_DEBUG_DRIVER("PCH FDI RX interrupt; FDI RXA IIR: 0x%08x, FDI RXB IIR: 0x%08x\n", fdia, fdib);
+	}
+
+	if (pch_iir & (SDE_TRANSB_CRC_DONE | SDE_TRANSA_CRC_DONE))
+		DRM_DEBUG_DRIVER("PCH transcoder CRC done interrupt\n");
+
+	if (pch_iir & (SDE_TRANSB_CRC_ERR | SDE_TRANSA_CRC_ERR))
+		DRM_DEBUG_DRIVER("PCH transcoder CRC error interrupt\n");
+
+	if (pch_iir & SDE_TRANSB_FIFO_UNDER)
+		DRM_DEBUG_DRIVER("PCH transcoder B underrun interrupt\n");
+	if (pch_iir & SDE_TRANSA_FIFO_UNDER)
+		DRM_DEBUG_DRIVER("PCH transcoder A underrun interrupt\n");
+}
+
 static irqreturn_t ironlake_irq_handler(struct drm_device *dev)
 {
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 	int ret = IRQ_NONE;
-	u32 de_iir, gt_iir, de_ier, pch_iir;
+	u32 de_iir, gt_iir, de_ier, pch_iir, pm_iir;
 	u32 hotplug_mask;
 	struct drm_i915_master_private *master_priv;
 	u32 bsd_usr_interrupt = GT_BSD_USER_INTERRUPT;
@@ -321,13 +474,15 @@ static irqreturn_t ironlake_irq_handler(
 	/* disable master interrupt before clearing iir  */
 	de_ier = I915_READ(DEIER);
 	I915_WRITE(DEIER, de_ier & ~DE_MASTER_IRQ_CONTROL);
-	(void)I915_READ(DEIER);
+	POSTING_READ(DEIER);
 
 	de_iir = I915_READ(DEIIR);
 	gt_iir = I915_READ(GTIIR);
 	pch_iir = I915_READ(SDEIIR);
+	pm_iir = I915_READ(GEN6_PMIIR);
 
-	if (de_iir == 0 && gt_iir == 0 && pch_iir == 0)
+	if (de_iir == 0 && gt_iir == 0 && pch_iir == 0 &&
+	    (!IS_GEN6(dev) || pm_iir == 0))
 		goto done;
 
 	if (HAS_PCH_CPT(dev))
@@ -344,12 +499,12 @@ static irqreturn_t ironlake_irq_handler(
 				READ_BREADCRUMB(dev_priv);
 	}
 
-	if (gt_iir & GT_PIPE_NOTIFY)
-		notify_ring(dev, &dev_priv->render_ring);
+	if (gt_iir & (GT_USER_INTERRUPT | GT_PIPE_NOTIFY))
+		notify_ring(dev, &dev_priv->ring[RCS]);
 	if (gt_iir & bsd_usr_interrupt)
-		notify_ring(dev, &dev_priv->bsd_ring);
-	if (HAS_BLT(dev) && gt_iir & GT_BLT_USER_INTERRUPT)
-		notify_ring(dev, &dev_priv->blt_ring);
+		notify_ring(dev, &dev_priv->ring[VCS]);
+	if (gt_iir & GT_BLT_USER_INTERRUPT)
+		notify_ring(dev, &dev_priv->ring[BCS]);
 
 	if (de_iir & DE_GSE)
 		intel_opregion_gse_intr(dev);
@@ -371,14 +526,20 @@ static irqreturn_t ironlake_irq_handler(
 		drm_handle_vblank(dev, 1);
 
 	/* check event from PCH */
-	if ((de_iir & DE_PCH_EVENT) && (pch_iir & hotplug_mask))
-		queue_work(dev_priv->wq, &dev_priv->hotplug_work);
+	if (de_iir & DE_PCH_EVENT) {
+		if (pch_iir & hotplug_mask)
+			queue_work(dev_priv->wq, &dev_priv->hotplug_work);
+		pch_irq_handler(dev);
+	}
 
 	if (de_iir & DE_PCU_EVENT) {
 		I915_WRITE16(MEMINTRSTS, I915_READ(MEMINTRSTS));
 		i915_handle_rps_change(dev);
 	}
 
+	if (IS_GEN6(dev))
+		gen6_pm_irq_handler(dev);
+
 	/* should clear PCH hotplug event before clear CPU irq */
 	I915_WRITE(SDEIIR, pch_iir);
 	I915_WRITE(GTIIR, gt_iir);
@@ -386,7 +547,7 @@ static irqreturn_t ironlake_irq_handler(
 
 done:
 	I915_WRITE(DEIER, de_ier);
-	(void)I915_READ(DEIER);
+	POSTING_READ(DEIER);
 
 	return ret;
 }
@@ -422,29 +583,23 @@ static void i915_error_work_func(struct
 
 #ifdef CONFIG_DEBUG_FS
 static struct drm_i915_error_object *
-i915_error_object_create(struct drm_device *dev,
-			 struct drm_gem_object *src)
+i915_error_object_create(struct drm_i915_private *dev_priv,
+			 struct drm_i915_gem_object *src)
 {
-	drm_i915_private_t *dev_priv = dev->dev_private;
 	struct drm_i915_error_object *dst;
-	struct drm_i915_gem_object *src_priv;
 	int page, page_count;
 	u32 reloc_offset;
 
-	if (src == NULL)
-		return NULL;
-
-	src_priv = to_intel_bo(src);
-	if (src_priv->pages == NULL)
+	if (src == NULL || src->pages == NULL)
 		return NULL;
 
-	page_count = src->size / PAGE_SIZE;
+	page_count = src->base.size / PAGE_SIZE;
 
 	dst = kmalloc(sizeof(*dst) + page_count * sizeof (u32 *), GFP_ATOMIC);
 	if (dst == NULL)
 		return NULL;
 
-	reloc_offset = src_priv->gtt_offset;
+	reloc_offset = src->gtt_offset;
 	for (page = 0; page < page_count; page++) {
 		unsigned long flags;
 		void __iomem *s;
@@ -466,7 +621,7 @@ i915_error_object_create(struct drm_devi
 		reloc_offset += PAGE_SIZE;
 	}
 	dst->page_count = page_count;
-	dst->gtt_offset = src_priv->gtt_offset;
+	dst->gtt_offset = src->gtt_offset;
 
 	return dst;
 
@@ -503,53 +658,98 @@ i915_error_state_free(struct drm_device
 	kfree(error);
 }
 
-static u32
-i915_get_bbaddr(struct drm_device *dev, u32 *ring)
+static u32 capture_bo_list(struct drm_i915_error_buffer *err,
+			   int count,
+			   struct list_head *head)
 {
-	u32 cmd;
+	struct drm_i915_gem_object *obj;
+	int i = 0;
 
-	if (IS_I830(dev) || IS_845G(dev))
-		cmd = MI_BATCH_BUFFER;
-	else if (INTEL_INFO(dev)->gen >= 4)
-		cmd = (MI_BATCH_BUFFER_START | (2 << 6) |
-		       MI_BATCH_NON_SECURE_I965);
-	else
-		cmd = (MI_BATCH_BUFFER_START | (2 << 6));
+	list_for_each_entry(obj, head, mm_list) {
+		err->size = obj->base.size;
+		err->name = obj->base.name;
+		err->seqno = obj->last_rendering_seqno;
+		err->gtt_offset = obj->gtt_offset;
+		err->read_domains = obj->base.read_domains;
+		err->write_domain = obj->base.write_domain;
+		err->fence_reg = obj->fence_reg;
+		err->pinned = 0;
+		if (obj->pin_count > 0)
+			err->pinned = 1;
+		if (obj->user_pin_count > 0)
+			err->pinned = -1;
+		err->tiling = obj->tiling_mode;
+		err->dirty = obj->dirty;
+		err->purgeable = obj->madv != I915_MADV_WILLNEED;
+		err->ring = obj->ring ? obj->ring->id : 0;
+		err->agp_type = obj->agp_type == AGP_USER_CACHED_MEMORY;
 
-	return ring[0] == cmd ? ring[1] : 0;
+		if (++i == count)
+			break;
+
+		err++;
+	}
+
+	return i;
 }
 
-static u32
-i915_ringbuffer_last_batch(struct drm_device *dev)
+static void i915_gem_record_fences(struct drm_device *dev,
+				   struct drm_i915_error_state *error)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	u32 head, bbaddr;
-	u32 *ring;
+	int i;
 
-	/* Locate the current position in the ringbuffer and walk back
-	 * to find the most recently dispatched batch buffer.
-	 */
-	bbaddr = 0;
-	head = I915_READ(PRB0_HEAD) & HEAD_ADDR;
-	ring = (u32 *)(dev_priv->render_ring.virtual_start + head);
+	/* Fences */
+	switch (INTEL_INFO(dev)->gen) {
+	case 6:
+		for (i = 0; i < 16; i++)
+			error->fence[i] = I915_READ64(FENCE_REG_SANDYBRIDGE_0 + (i * 8));
+		break;
+	case 5:
+	case 4:
+		for (i = 0; i < 16; i++)
+			error->fence[i] = I915_READ64(FENCE_REG_965_0 + (i * 8));
+		break;
+	case 3:
+		if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev))
+			for (i = 0; i < 8; i++)
+				error->fence[i+8] = I915_READ(FENCE_REG_945_8 + (i * 4));
+	case 2:
+		for (i = 0; i < 8; i++)
+			error->fence[i] = I915_READ(FENCE_REG_830_0 + (i * 4));
+		break;
 
-	while (--ring >= (u32 *)dev_priv->render_ring.virtual_start) {
-		bbaddr = i915_get_bbaddr(dev, ring);
-		if (bbaddr)
-			break;
 	}
+}
 
-	if (bbaddr == 0) {
-		ring = (u32 *)(dev_priv->render_ring.virtual_start
-				+ dev_priv->render_ring.size);
-		while (--ring >= (u32 *)dev_priv->render_ring.virtual_start) {
-			bbaddr = i915_get_bbaddr(dev, ring);
-			if (bbaddr)
-				break;
-		}
+static struct drm_i915_error_object *
+i915_error_first_batchbuffer(struct drm_i915_private *dev_priv,
+			     struct intel_ring_buffer *ring)
+{
+	struct drm_i915_gem_object *obj;
+	u32 seqno;
+
+	if (!ring->get_seqno)
+		return NULL;
+
+	seqno = ring->get_seqno(ring);
+	list_for_each_entry(obj, &dev_priv->mm.active_list, mm_list) {
+		if (obj->ring != ring)
+			continue;
+
+		if (i915_seqno_passed(seqno, obj->last_rendering_seqno))
+			continue;
+
+		if ((obj->base.read_domains & I915_GEM_DOMAIN_COMMAND) == 0)
+			continue;
+
+		/* We need to copy these to an anonymous buffer as the simplest
+		 * method to avoid being overwritten by userspace.
+		 */
+		return i915_error_object_create(dev_priv, obj);
 	}
 
-	return bbaddr;
+	return NULL;
 }
 
 /**
@@ -564,12 +764,10 @@ i915_ringbuffer_last_batch(struct drm_de
 static void i915_capture_error_state(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct drm_i915_gem_object *obj_priv;
+	struct drm_i915_gem_object *obj;
 	struct drm_i915_error_state *error;
-	struct drm_gem_object *batchbuffer[2];
 	unsigned long flags;
-	u32 bbaddr;
-	int count;
+	int i;
 
 	spin_lock_irqsave(&dev_priv->error_lock, flags);
 	error = dev_priv->first_error;
@@ -585,20 +783,33 @@ static void i915_capture_error_state(str
 
 	DRM_DEBUG_DRIVER("generating error event\n");
 
-	error->seqno =
-		dev_priv->render_ring.get_seqno(dev, &dev_priv->render_ring);
+	error->seqno = dev_priv->ring[RCS].get_seqno(&dev_priv->ring[RCS]);
 	error->eir = I915_READ(EIR);
 	error->pgtbl_er = I915_READ(PGTBL_ER);
 	error->pipeastat = I915_READ(PIPEASTAT);
 	error->pipebstat = I915_READ(PIPEBSTAT);
 	error->instpm = I915_READ(INSTPM);
-	if (INTEL_INFO(dev)->gen < 4) {
-		error->ipeir = I915_READ(IPEIR);
-		error->ipehr = I915_READ(IPEHR);
-		error->instdone = I915_READ(INSTDONE);
-		error->acthd = I915_READ(ACTHD);
-		error->bbaddr = 0;
-	} else {
+	error->error = 0;
+	if (INTEL_INFO(dev)->gen >= 6) {
+		error->error = I915_READ(ERROR_GEN6);
+
+		error->bcs_acthd = I915_READ(BCS_ACTHD);
+		error->bcs_ipehr = I915_READ(BCS_IPEHR);
+		error->bcs_ipeir = I915_READ(BCS_IPEIR);
+		error->bcs_instdone = I915_READ(BCS_INSTDONE);
+		error->bcs_seqno = 0;
+		if (dev_priv->ring[BCS].get_seqno)
+			error->bcs_seqno = dev_priv->ring[BCS].get_seqno(&dev_priv->ring[BCS]);
+
+		error->vcs_acthd = I915_READ(VCS_ACTHD);
+		error->vcs_ipehr = I915_READ(VCS_IPEHR);
+		error->vcs_ipeir = I915_READ(VCS_IPEIR);
+		error->vcs_instdone = I915_READ(VCS_INSTDONE);
+		error->vcs_seqno = 0;
+		if (dev_priv->ring[VCS].get_seqno)
+			error->vcs_seqno = dev_priv->ring[VCS].get_seqno(&dev_priv->ring[VCS]);
+	}
+	if (INTEL_INFO(dev)->gen >= 4) {
 		error->ipeir = I915_READ(IPEIR_I965);
 		error->ipehr = I915_READ(IPEHR_I965);
 		error->instdone = I915_READ(INSTDONE_I965);
@@ -606,118 +817,63 @@ static void i915_capture_error_state(str
 		error->instdone1 = I915_READ(INSTDONE1);
 		error->acthd = I915_READ(ACTHD_I965);
 		error->bbaddr = I915_READ64(BB_ADDR);
+	} else {
+		error->ipeir = I915_READ(IPEIR);
+		error->ipehr = I915_READ(IPEHR);
+		error->instdone = I915_READ(INSTDONE);
+		error->acthd = I915_READ(ACTHD);
+		error->bbaddr = 0;
 	}
+	i915_gem_record_fences(dev, error);
 
-	bbaddr = i915_ringbuffer_last_batch(dev);
-
-	/* Grab the current batchbuffer, most likely to have crashed. */
-	batchbuffer[0] = NULL;
-	batchbuffer[1] = NULL;
-	count = 0;
-	list_for_each_entry(obj_priv, &dev_priv->mm.active_list, mm_list) {
-		struct drm_gem_object *obj = &obj_priv->base;
-
-		if (batchbuffer[0] == NULL &&
-		    bbaddr >= obj_priv->gtt_offset &&
-		    bbaddr < obj_priv->gtt_offset + obj->size)
-			batchbuffer[0] = obj;
-
-		if (batchbuffer[1] == NULL &&
-		    error->acthd >= obj_priv->gtt_offset &&
-		    error->acthd < obj_priv->gtt_offset + obj->size)
-			batchbuffer[1] = obj;
-
-		count++;
-	}
-	/* Scan the other lists for completeness for those bizarre errors. */
-	if (batchbuffer[0] == NULL || batchbuffer[1] == NULL) {
-		list_for_each_entry(obj_priv, &dev_priv->mm.flushing_list, mm_list) {
-			struct drm_gem_object *obj = &obj_priv->base;
-
-			if (batchbuffer[0] == NULL &&
-			    bbaddr >= obj_priv->gtt_offset &&
-			    bbaddr < obj_priv->gtt_offset + obj->size)
-				batchbuffer[0] = obj;
-
-			if (batchbuffer[1] == NULL &&
-			    error->acthd >= obj_priv->gtt_offset &&
-			    error->acthd < obj_priv->gtt_offset + obj->size)
-				batchbuffer[1] = obj;
-
-			if (batchbuffer[0] && batchbuffer[1])
-				break;
-		}
-	}
-	if (batchbuffer[0] == NULL || batchbuffer[1] == NULL) {
-		list_for_each_entry(obj_priv, &dev_priv->mm.inactive_list, mm_list) {
-			struct drm_gem_object *obj = &obj_priv->base;
-
-			if (batchbuffer[0] == NULL &&
-			    bbaddr >= obj_priv->gtt_offset &&
-			    bbaddr < obj_priv->gtt_offset + obj->size)
-				batchbuffer[0] = obj;
-
-			if (batchbuffer[1] == NULL &&
-			    error->acthd >= obj_priv->gtt_offset &&
-			    error->acthd < obj_priv->gtt_offset + obj->size)
-				batchbuffer[1] = obj;
-
-			if (batchbuffer[0] && batchbuffer[1])
-				break;
-		}
-	}
-
-	/* We need to copy these to an anonymous buffer as the simplest
-	 * method to avoid being overwritten by userspace.
-	 */
-	error->batchbuffer[0] = i915_error_object_create(dev, batchbuffer[0]);
-	if (batchbuffer[1] != batchbuffer[0])
-		error->batchbuffer[1] = i915_error_object_create(dev, batchbuffer[1]);
-	else
-		error->batchbuffer[1] = NULL;
+	/* Record the active batchbuffers */
+	for (i = 0; i < I915_NUM_RINGS; i++)
+		error->batchbuffer[i] =
+			i915_error_first_batchbuffer(dev_priv,
+						     &dev_priv->ring[i]);
 
 	/* Record the ringbuffer */
-	error->ringbuffer = i915_error_object_create(dev,
-			dev_priv->render_ring.gem_object);
+	error->ringbuffer = i915_error_object_create(dev_priv,
+						     dev_priv->ring[RCS].obj);
 
-	/* Record buffers on the active list. */
+	/* Record buffers on the active and pinned lists. */
 	error->active_bo = NULL;
-	error->active_bo_count = 0;
+	error->pinned_bo = NULL;
 
-	if (count)
-		error->active_bo = kmalloc(sizeof(*error->active_bo)*count,
-					   GFP_ATOMIC);
+	i = 0;
+	list_for_each_entry(obj, &dev_priv->mm.active_list, mm_list)
+		i++;
+	error->active_bo_count = i;
+	list_for_each_entry(obj, &dev_priv->mm.pinned_list, mm_list)
+		i++;
+	error->pinned_bo_count = i - error->active_bo_count;
 
-	if (error->active_bo) {
-		int i = 0;
-		list_for_each_entry(obj_priv, &dev_priv->mm.active_list, mm_list) {
-			struct drm_gem_object *obj = &obj_priv->base;
+	error->active_bo = NULL;
+	error->pinned_bo = NULL;
+	if (i) {
+		error->active_bo = kmalloc(sizeof(*error->active_bo)*i,
+					   GFP_ATOMIC);
+		if (error->active_bo)
+			error->pinned_bo =
+				error->active_bo + error->active_bo_count;
+	}
 
-			error->active_bo[i].size = obj->size;
-			error->active_bo[i].name = obj->name;
-			error->active_bo[i].seqno = obj_priv->last_rendering_seqno;
-			error->active_bo[i].gtt_offset = obj_priv->gtt_offset;
-			error->active_bo[i].read_domains = obj->read_domains;
-			error->active_bo[i].write_domain = obj->write_domain;
-			error->active_bo[i].fence_reg = obj_priv->fence_reg;
-			error->active_bo[i].pinned = 0;
-			if (obj_priv->pin_count > 0)
-				error->active_bo[i].pinned = 1;
-			if (obj_priv->user_pin_count > 0)
-				error->active_bo[i].pinned = -1;
-			error->active_bo[i].tiling = obj_priv->tiling_mode;
-			error->active_bo[i].dirty = obj_priv->dirty;
-			error->active_bo[i].purgeable = obj_priv->madv != I915_MADV_WILLNEED;
+	if (error->active_bo)
+		error->active_bo_count =
+			capture_bo_list(error->active_bo,
+					error->active_bo_count,
+					&dev_priv->mm.active_list);
 
-			if (++i == count)
-				break;
-		}
-		error->active_bo_count = i;
-	}
+	if (error->pinned_bo)
+		error->pinned_bo_count =
+			capture_bo_list(error->pinned_bo,
+					error->pinned_bo_count,
+					&dev_priv->mm.pinned_list);
 
 	do_gettimeofday(&error->time);
 
 	error->overlay = intel_overlay_capture_error_state(dev);
+	error->display = intel_display_capture_error_state(dev);
 
 	spin_lock_irqsave(&dev_priv->error_lock, flags);
 	if (dev_priv->first_error == NULL) {
@@ -775,7 +931,7 @@ static void i915_report_and_clear_eir(st
 			printk(KERN_ERR "  ACTHD: 0x%08x\n",
 			       I915_READ(ACTHD_I965));
 			I915_WRITE(IPEIR_I965, ipeir);
-			(void)I915_READ(IPEIR_I965);
+			POSTING_READ(IPEIR_I965);
 		}
 		if (eir & GM45_ERROR_PAGE_TABLE) {
 			u32 pgtbl_err = I915_READ(PGTBL_ER);
@@ -783,7 +939,7 @@ static void i915_report_and_clear_eir(st
 			printk(KERN_ERR "  PGTBL_ER: 0x%08x\n",
 			       pgtbl_err);
 			I915_WRITE(PGTBL_ER, pgtbl_err);
-			(void)I915_READ(PGTBL_ER);
+			POSTING_READ(PGTBL_ER);
 		}
 	}
 
@@ -794,7 +950,7 @@ static void i915_report_and_clear_eir(st
 			printk(KERN_ERR "  PGTBL_ER: 0x%08x\n",
 			       pgtbl_err);
 			I915_WRITE(PGTBL_ER, pgtbl_err);
-			(void)I915_READ(PGTBL_ER);
+			POSTING_READ(PGTBL_ER);
 		}
 	}
 
@@ -825,7 +981,7 @@ static void i915_report_and_clear_eir(st
 			printk(KERN_ERR "  ACTHD: 0x%08x\n",
 			       I915_READ(ACTHD));
 			I915_WRITE(IPEIR, ipeir);
-			(void)I915_READ(IPEIR);
+			POSTING_READ(IPEIR);
 		} else {
 			u32 ipeir = I915_READ(IPEIR_I965);
 
@@ -842,12 +998,12 @@ static void i915_report_and_clear_eir(st
 			printk(KERN_ERR "  ACTHD: 0x%08x\n",
 			       I915_READ(ACTHD_I965));
 			I915_WRITE(IPEIR_I965, ipeir);
-			(void)I915_READ(IPEIR_I965);
+			POSTING_READ(IPEIR_I965);
 		}
 	}
 
 	I915_WRITE(EIR, eir);
-	(void)I915_READ(EIR);
+	POSTING_READ(EIR);
 	eir = I915_READ(EIR);
 	if (eir) {
 		/*
@@ -870,7 +1026,7 @@ static void i915_report_and_clear_eir(st
  * so userspace knows something bad happened (should trigger collection
  * of a ring dump etc.).
  */
-static void i915_handle_error(struct drm_device *dev, bool wedged)
+void i915_handle_error(struct drm_device *dev, bool wedged)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
@@ -884,11 +1040,11 @@ static void i915_handle_error(struct drm
 		/*
 		 * Wakeup waiting processes so they don't hang
 		 */
-		wake_up_all(&dev_priv->render_ring.irq_queue);
+		wake_up_all(&dev_priv->ring[RCS].irq_queue);
 		if (HAS_BSD(dev))
-			wake_up_all(&dev_priv->bsd_ring.irq_queue);
+			wake_up_all(&dev_priv->ring[VCS].irq_queue);
 		if (HAS_BLT(dev))
-			wake_up_all(&dev_priv->blt_ring.irq_queue);
+			wake_up_all(&dev_priv->ring[BCS].irq_queue);
 	}
 
 	queue_work(dev_priv->wq, &dev_priv->error_work);
@@ -899,7 +1055,7 @@ static void i915_pageflip_stall_check(st
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe];
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-	struct drm_i915_gem_object *obj_priv;
+	struct drm_i915_gem_object *obj;
 	struct intel_unpin_work *work;
 	unsigned long flags;
 	bool stall_detected;
@@ -918,13 +1074,13 @@ static void i915_pageflip_stall_check(st
 	}
 
 	/* Potential stall - if we see that the flip has happened, assume a missed interrupt */
-	obj_priv = to_intel_bo(work->pending_flip_obj);
+	obj = work->pending_flip_obj;
 	if (INTEL_INFO(dev)->gen >= 4) {
 		int dspsurf = intel_crtc->plane == 0 ? DSPASURF : DSPBSURF;
-		stall_detected = I915_READ(dspsurf) == obj_priv->gtt_offset;
+		stall_detected = I915_READ(dspsurf) == obj->gtt_offset;
 	} else {
 		int dspaddr = intel_crtc->plane == 0 ? DSPAADDR : DSPBADDR;
-		stall_detected = I915_READ(dspaddr) == (obj_priv->gtt_offset +
+		stall_detected = I915_READ(dspaddr) == (obj->gtt_offset +
 							crtc->y * crtc->fb->pitch +
 							crtc->x * crtc->fb->bits_per_pixel/8);
 	}
@@ -970,7 +1126,7 @@ irqreturn_t i915_driver_irq_handler(DRM_
 		 * It doesn't set the bit in iir again, but it still produces
 		 * interrupts (for non-MSI).
 		 */
-		spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
+		spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
 		pipea_stats = I915_READ(PIPEASTAT);
 		pipeb_stats = I915_READ(PIPEBSTAT);
 
@@ -993,7 +1149,7 @@ irqreturn_t i915_driver_irq_handler(DRM_
 			I915_WRITE(PIPEBSTAT, pipeb_stats);
 			irq_received = 1;
 		}
-		spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags);
+		spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
 
 		if (!irq_received)
 			break;
@@ -1026,9 +1182,9 @@ irqreturn_t i915_driver_irq_handler(DRM_
 		}
 
 		if (iir & I915_USER_INTERRUPT)
-			notify_ring(dev, &dev_priv->render_ring);
-		if (HAS_BSD(dev) && (iir & I915_BSD_USER_INTERRUPT))
-			notify_ring(dev, &dev_priv->bsd_ring);
+			notify_ring(dev, &dev_priv->ring[RCS]);
+		if (iir & I915_BSD_USER_INTERRUPT)
+			notify_ring(dev, &dev_priv->ring[VCS]);
 
 		if (iir & I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT) {
 			intel_prepare_page_flip(dev, 0);
@@ -1042,18 +1198,18 @@ irqreturn_t i915_driver_irq_handler(DRM_
 				intel_finish_page_flip_plane(dev, 1);
 		}
 
-		if (pipea_stats & vblank_status) {
+		if (pipea_stats & vblank_status &&
+		    drm_handle_vblank(dev, 0)) {
 			vblank++;
-			drm_handle_vblank(dev, 0);
 			if (!dev_priv->flip_pending_is_done) {
 				i915_pageflip_stall_check(dev, 0);
 				intel_finish_page_flip(dev, 0);
 			}
 		}
 
-		if (pipeb_stats & vblank_status) {
+		if (pipeb_stats & vblank_status &&
+		    drm_handle_vblank(dev, 1)) {
 			vblank++;
-			drm_handle_vblank(dev, 1);
 			if (!dev_priv->flip_pending_is_done) {
 				i915_pageflip_stall_check(dev, 1);
 				intel_finish_page_flip(dev, 1);
@@ -1101,12 +1257,13 @@ static int i915_emit_irq(struct drm_devi
 	if (master_priv->sarea_priv)
 		master_priv->sarea_priv->last_enqueue = dev_priv->counter;
 
-	BEGIN_LP_RING(4);
-	OUT_RING(MI_STORE_DWORD_INDEX);
-	OUT_RING(I915_BREADCRUMB_INDEX << MI_STORE_DWORD_INDEX_SHIFT);
-	OUT_RING(dev_priv->counter);
-	OUT_RING(MI_USER_INTERRUPT);
-	ADVANCE_LP_RING();
+	if (BEGIN_LP_RING(4) == 0) {
+		OUT_RING(MI_STORE_DWORD_INDEX);
+		OUT_RING(I915_BREADCRUMB_INDEX << MI_STORE_DWORD_INDEX_SHIFT);
+		OUT_RING(dev_priv->counter);
+		OUT_RING(MI_USER_INTERRUPT);
+		ADVANCE_LP_RING();
+	}
 
 	return dev_priv->counter;
 }
@@ -1114,12 +1271,11 @@ static int i915_emit_irq(struct drm_devi
 void i915_trace_irq_get(struct drm_device *dev, u32 seqno)
 {
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-	struct intel_ring_buffer *render_ring = &dev_priv->render_ring;
-
-	if (dev_priv->trace_irq_seqno == 0)
-		render_ring->user_irq_get(dev, render_ring);
+	struct intel_ring_buffer *ring = LP_RING(dev_priv);
 
-	dev_priv->trace_irq_seqno = seqno;
+	if (dev_priv->trace_irq_seqno == 0 &&
+	    ring->irq_get(ring))
+		dev_priv->trace_irq_seqno = seqno;
 }
 
 static int i915_wait_irq(struct drm_device * dev, int irq_nr)
@@ -1127,7 +1283,7 @@ static int i915_wait_irq(struct drm_devi
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 	struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
 	int ret = 0;
-	struct intel_ring_buffer *render_ring = &dev_priv->render_ring;
+	struct intel_ring_buffer *ring = LP_RING(dev_priv);
 
 	DRM_DEBUG_DRIVER("irq_nr=%d breadcrumb=%d\n", irq_nr,
 		  READ_BREADCRUMB(dev_priv));
@@ -1141,10 +1297,12 @@ static int i915_wait_irq(struct drm_devi
 	if (master_priv->sarea_priv)
 		master_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT;
 
-	render_ring->user_irq_get(dev, render_ring);
-	DRM_WAIT_ON(ret, dev_priv->render_ring.irq_queue, 3 * DRM_HZ,
-		    READ_BREADCRUMB(dev_priv) >= irq_nr);
-	render_ring->user_irq_put(dev, render_ring);
+	if (ring->irq_get(ring)) {
+		DRM_WAIT_ON(ret, ring->irq_queue, 3 * DRM_HZ,
+			    READ_BREADCRUMB(dev_priv) >= irq_nr);
+		ring->irq_put(ring);
+	} else if (wait_for(READ_BREADCRUMB(dev_priv) >= irq_nr, 3000))
+		ret = -EBUSY;
 
 	if (ret == -EBUSY) {
 		DRM_ERROR("EBUSY -- rec: %d emitted: %d\n",
@@ -1163,7 +1321,7 @@ int i915_irq_emit(struct drm_device *dev
 	drm_i915_irq_emit_t *emit = data;
 	int result;
 
-	if (!dev_priv || !dev_priv->render_ring.virtual_start) {
+	if (!dev_priv || !LP_RING(dev_priv)->virtual_start) {
 		DRM_ERROR("called with no initialization\n");
 		return -EINVAL;
 	}
@@ -1209,9 +1367,9 @@ int i915_enable_vblank(struct drm_device
 	if (!i915_pipe_enabled(dev, pipe))
 		return -EINVAL;
 
-	spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
+	spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
 	if (HAS_PCH_SPLIT(dev))
-		ironlake_enable_display_irq(dev_priv, (pipe == 0) ? 
+		ironlake_enable_display_irq(dev_priv, (pipe == 0) ?
 					    DE_PIPEA_VBLANK: DE_PIPEB_VBLANK);
 	else if (INTEL_INFO(dev)->gen >= 4)
 		i915_enable_pipestat(dev_priv, pipe,
@@ -1219,7 +1377,7 @@ int i915_enable_vblank(struct drm_device
 	else
 		i915_enable_pipestat(dev_priv, pipe,
 				     PIPE_VBLANK_INTERRUPT_ENABLE);
-	spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags);
+	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
 	return 0;
 }
 
@@ -1231,15 +1389,15 @@ void i915_disable_vblank(struct drm_devi
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 	unsigned long irqflags;
 
-	spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
+	spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
 	if (HAS_PCH_SPLIT(dev))
-		ironlake_disable_display_irq(dev_priv, (pipe == 0) ? 
+		ironlake_disable_display_irq(dev_priv, (pipe == 0) ?
 					     DE_PIPEA_VBLANK: DE_PIPEB_VBLANK);
 	else
 		i915_disable_pipestat(dev_priv, pipe,
 				      PIPE_VBLANK_INTERRUPT_ENABLE |
 				      PIPE_START_VBLANK_INTERRUPT_ENABLE);
-	spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags);
+	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
 }
 
 void i915_enable_interrupt (struct drm_device *dev)
@@ -1306,12 +1464,50 @@ int i915_vblank_swap(struct drm_device *
 	return -EINVAL;
 }
 
-static struct drm_i915_gem_request *
-i915_get_tail_request(struct drm_device *dev)
+static u32
+ring_last_seqno(struct intel_ring_buffer *ring)
 {
-	drm_i915_private_t *dev_priv = dev->dev_private;
-	return list_entry(dev_priv->render_ring.request_list.prev,
-			struct drm_i915_gem_request, list);
+	return list_entry(ring->request_list.prev,
+			  struct drm_i915_gem_request, list)->seqno;
+}
+
+static bool i915_hangcheck_ring_idle(struct intel_ring_buffer *ring, bool *err)
+{
+	if (list_empty(&ring->request_list) ||
+	    i915_seqno_passed(ring->get_seqno(ring), ring_last_seqno(ring))) {
+		/* Issue a wake-up to catch stuck h/w. */
+		if (ring->waiting_seqno && waitqueue_active(&ring->irq_queue)) {
+			DRM_ERROR("Hangcheck timer elapsed... %s idle [waiting on %d, at %d], missed IRQ?\n",
+				  ring->name,
+				  ring->waiting_seqno,
+				  ring->get_seqno(ring));
+			wake_up_all(&ring->irq_queue);
+			*err = true;
+		}
+		return true;
+	}
+	return false;
+}
+
+static bool kick_ring(struct intel_ring_buffer *ring)
+{
+	struct drm_device *dev = ring->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	u32 tmp = I915_READ_CTL(ring);
+	if (tmp & RING_WAIT) {
+		DRM_ERROR("Kicking stuck wait on %s\n",
+			  ring->name);
+		I915_WRITE_CTL(ring, tmp);
+		return true;
+	}
+	if (IS_GEN6(dev) &&
+	    (tmp & RING_WAIT_SEMAPHORE)) {
+		DRM_ERROR("Kicking stuck semaphore on %s\n",
+			  ring->name);
+		I915_WRITE_CTL(ring, tmp);
+		return true;
+	}
+	return false;
 }
 
 /**
@@ -1325,6 +1521,17 @@ void i915_hangcheck_elapsed(unsigned lon
 	struct drm_device *dev = (struct drm_device *)data;
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	uint32_t acthd, instdone, instdone1;
+	bool err = false;
+
+	/* If all work is done then ACTHD clearly hasn't advanced. */
+	if (i915_hangcheck_ring_idle(&dev_priv->ring[RCS], &err) &&
+	    i915_hangcheck_ring_idle(&dev_priv->ring[VCS], &err) &&
+	    i915_hangcheck_ring_idle(&dev_priv->ring[BCS], &err)) {
+		dev_priv->hangcheck_count = 0;
+		if (err)
+			goto repeat;
+		return;
+	}
 
 	if (INTEL_INFO(dev)->gen < 4) {
 		acthd = I915_READ(ACTHD);
@@ -1336,38 +1543,6 @@ void i915_hangcheck_elapsed(unsigned lon
 		instdone1 = I915_READ(INSTDONE1);
 	}
 
-	/* If all work is done then ACTHD clearly hasn't advanced. */
-	if (list_empty(&dev_priv->render_ring.request_list) ||
-		i915_seqno_passed(dev_priv->render_ring.get_seqno(dev, &dev_priv->render_ring),
-				  i915_get_tail_request(dev)->seqno)) {
-		bool missed_wakeup = false;
-
-		dev_priv->hangcheck_count = 0;
-
-		/* Issue a wake-up to catch stuck h/w. */
-		if (dev_priv->render_ring.waiting_gem_seqno &&
-		    waitqueue_active(&dev_priv->render_ring.irq_queue)) {
-			wake_up_all(&dev_priv->render_ring.irq_queue);
-			missed_wakeup = true;
-		}
-
-		if (dev_priv->bsd_ring.waiting_gem_seqno &&
-		    waitqueue_active(&dev_priv->bsd_ring.irq_queue)) {
-			wake_up_all(&dev_priv->bsd_ring.irq_queue);
-			missed_wakeup = true;
-		}
-
-		if (dev_priv->blt_ring.waiting_gem_seqno &&
-		    waitqueue_active(&dev_priv->blt_ring.irq_queue)) {
-			wake_up_all(&dev_priv->blt_ring.irq_queue);
-			missed_wakeup = true;
-		}
-
-		if (missed_wakeup)
-			DRM_ERROR("Hangcheck timer elapsed... GPU idle, missed IRQ.\n");
-		return;
-	}
-
 	if (dev_priv->last_acthd == acthd &&
 	    dev_priv->last_instdone == instdone &&
 	    dev_priv->last_instdone1 == instdone1) {
@@ -1380,12 +1555,17 @@ void i915_hangcheck_elapsed(unsigned lon
 				 * and break the hang. This should work on
 				 * all but the second generation chipsets.
 				 */
-				u32 tmp = I915_READ(PRB0_CTL);
-				if (tmp & RING_WAIT) {
-					I915_WRITE(PRB0_CTL, tmp);
-					POSTING_READ(PRB0_CTL);
-					goto out;
-				}
+
+				if (kick_ring(&dev_priv->ring[RCS]))
+					goto repeat;
+
+				if (HAS_BSD(dev) &&
+				    kick_ring(&dev_priv->ring[VCS]))
+					goto repeat;
+
+				if (HAS_BLT(dev) &&
+				    kick_ring(&dev_priv->ring[BCS]))
+					goto repeat;
 			}
 
 			i915_handle_error(dev, true);
@@ -1399,7 +1579,7 @@ void i915_hangcheck_elapsed(unsigned lon
 		dev_priv->last_instdone1 = instdone1;
 	}
 
-out:
+repeat:
 	/* Reset timer case chip hangs without another request being added */
 	mod_timer(&dev_priv->hangcheck_timer,
 		  jiffies + msecs_to_jiffies(DRM_I915_HANGCHECK_PERIOD));
@@ -1417,17 +1597,17 @@ static void ironlake_irq_preinstall(stru
 
 	I915_WRITE(DEIMR, 0xffffffff);
 	I915_WRITE(DEIER, 0x0);
-	(void) I915_READ(DEIER);
+	POSTING_READ(DEIER);
 
 	/* and GT */
 	I915_WRITE(GTIMR, 0xffffffff);
 	I915_WRITE(GTIER, 0x0);
-	(void) I915_READ(GTIER);
+	POSTING_READ(GTIER);
 
 	/* south display irq */
 	I915_WRITE(SDEIMR, 0xffffffff);
 	I915_WRITE(SDEIER, 0x0);
-	(void) I915_READ(SDEIER);
+	POSTING_READ(SDEIER);
 }
 
 static int ironlake_irq_postinstall(struct drm_device *dev)
@@ -1436,38 +1616,34 @@ static int ironlake_irq_postinstall(stru
 	/* enable kind of interrupts always enabled */
 	u32 display_mask = DE_MASTER_IRQ_CONTROL | DE_GSE | DE_PCH_EVENT |
 			   DE_PLANEA_FLIP_DONE | DE_PLANEB_FLIP_DONE;
-	u32 render_mask = GT_PIPE_NOTIFY | GT_BSD_USER_INTERRUPT;
+	u32 render_irqs;
 	u32 hotplug_mask;
 
-	dev_priv->irq_mask_reg = ~display_mask;
-	dev_priv->de_irq_enable_reg = display_mask | DE_PIPEA_VBLANK | DE_PIPEB_VBLANK;
+	dev_priv->irq_mask = ~display_mask;
 
 	/* should always can generate irq */
 	I915_WRITE(DEIIR, I915_READ(DEIIR));
-	I915_WRITE(DEIMR, dev_priv->irq_mask_reg);
-	I915_WRITE(DEIER, dev_priv->de_irq_enable_reg);
-	(void) I915_READ(DEIER);
-
-	if (IS_GEN6(dev)) {
-		render_mask =
-			GT_PIPE_NOTIFY |
-			GT_GEN6_BSD_USER_INTERRUPT |
-			GT_BLT_USER_INTERRUPT;
-	}
+	I915_WRITE(DEIMR, dev_priv->irq_mask);
+	I915_WRITE(DEIER, display_mask | DE_PIPEA_VBLANK | DE_PIPEB_VBLANK);
+	POSTING_READ(DEIER);
 
-	dev_priv->gt_irq_mask_reg = ~render_mask;
-	dev_priv->gt_irq_enable_reg = render_mask;
+	dev_priv->gt_irq_mask = ~0;
 
 	I915_WRITE(GTIIR, I915_READ(GTIIR));
-	I915_WRITE(GTIMR, dev_priv->gt_irq_mask_reg);
-	if (IS_GEN6(dev)) {
-		I915_WRITE(GEN6_RENDER_IMR, ~GEN6_RENDER_PIPE_CONTROL_NOTIFY_INTERRUPT);
-		I915_WRITE(GEN6_BSD_IMR, ~GEN6_BSD_IMR_USER_INTERRUPT);
-		I915_WRITE(GEN6_BLITTER_IMR, ~GEN6_BLITTER_USER_INTERRUPT);
-	}
+	I915_WRITE(GTIMR, dev_priv->gt_irq_mask);
 
-	I915_WRITE(GTIER, dev_priv->gt_irq_enable_reg);
-	(void) I915_READ(GTIER);
+	if (IS_GEN6(dev))
+		render_irqs =
+			GT_USER_INTERRUPT |
+			GT_GEN6_BSD_USER_INTERRUPT |
+			GT_BLT_USER_INTERRUPT;
+	else
+		render_irqs =
+			GT_USER_INTERRUPT |
+			GT_PIPE_NOTIFY |
+			GT_BSD_USER_INTERRUPT;
+	I915_WRITE(GTIER, render_irqs);
+	POSTING_READ(GTIER);
 
 	if (HAS_PCH_CPT(dev)) {
 		hotplug_mask = SDE_CRT_HOTPLUG_CPT | SDE_PORTB_HOTPLUG_CPT  |
@@ -1475,15 +1651,15 @@ static int ironlake_irq_postinstall(stru
 	} else {
 		hotplug_mask = SDE_CRT_HOTPLUG | SDE_PORTB_HOTPLUG |
 			       SDE_PORTC_HOTPLUG | SDE_PORTD_HOTPLUG;
+		hotplug_mask |= SDE_AUX_MASK;
 	}
 
-	dev_priv->pch_irq_mask_reg = ~hotplug_mask;
-	dev_priv->pch_irq_enable_reg = hotplug_mask;
+	dev_priv->pch_irq_mask = ~hotplug_mask;
 
 	I915_WRITE(SDEIIR, I915_READ(SDEIIR));
-	I915_WRITE(SDEIMR, dev_priv->pch_irq_mask_reg);
-	I915_WRITE(SDEIER, dev_priv->pch_irq_enable_reg);
-	(void) I915_READ(SDEIER);
+	I915_WRITE(SDEIMR, dev_priv->pch_irq_mask);
+	I915_WRITE(SDEIER, hotplug_mask);
+	POSTING_READ(SDEIER);
 
 	if (IS_IRONLAKE_M(dev)) {
 		/* Clear & enable PCU event interrupts */
@@ -1519,7 +1695,7 @@ void i915_driver_irq_preinstall(struct d
 	I915_WRITE(PIPEBSTAT, 0);
 	I915_WRITE(IMR, 0xffffffff);
 	I915_WRITE(IER, 0x0);
-	(void) I915_READ(IER);
+	POSTING_READ(IER);
 }
 
 /*
@@ -1532,11 +1708,11 @@ int i915_driver_irq_postinstall(struct d
 	u32 enable_mask = I915_INTERRUPT_ENABLE_FIX | I915_INTERRUPT_ENABLE_VAR;
 	u32 error_mask;
 
-	DRM_INIT_WAITQUEUE(&dev_priv->render_ring.irq_queue);
+	DRM_INIT_WAITQUEUE(&dev_priv->ring[RCS].irq_queue);
 	if (HAS_BSD(dev))
-		DRM_INIT_WAITQUEUE(&dev_priv->bsd_ring.irq_queue);
+		DRM_INIT_WAITQUEUE(&dev_priv->ring[VCS].irq_queue);
 	if (HAS_BLT(dev))
-		DRM_INIT_WAITQUEUE(&dev_priv->blt_ring.irq_queue);
+		DRM_INIT_WAITQUEUE(&dev_priv->ring[BCS].irq_queue);
 
 	dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B;
 
@@ -1544,7 +1720,7 @@ int i915_driver_irq_postinstall(struct d
 		return ironlake_irq_postinstall(dev);
 
 	/* Unmask the interrupts that we always want on. */
-	dev_priv->irq_mask_reg = ~I915_INTERRUPT_ENABLE_FIX;
+	dev_priv->irq_mask = ~I915_INTERRUPT_ENABLE_FIX;
 
 	dev_priv->pipestat[0] = 0;
 	dev_priv->pipestat[1] = 0;
@@ -1553,7 +1729,7 @@ int i915_driver_irq_postinstall(struct d
 		/* Enable in IER... */
 		enable_mask |= I915_DISPLAY_PORT_INTERRUPT;
 		/* and unmask in IMR */
-		dev_priv->irq_mask_reg &= ~I915_DISPLAY_PORT_INTERRUPT;
+		dev_priv->irq_mask &= ~I915_DISPLAY_PORT_INTERRUPT;
 	}
 
 	/*
@@ -1571,9 +1747,9 @@ int i915_driver_irq_postinstall(struct d
 	}
 	I915_WRITE(EMR, error_mask);
 
-	I915_WRITE(IMR, dev_priv->irq_mask_reg);
+	I915_WRITE(IMR, dev_priv->irq_mask);
 	I915_WRITE(IER, enable_mask);
-	(void) I915_READ(IER);
+	POSTING_READ(IER);
 
 	if (I915_HAS_HOTPLUG(dev)) {
 		u32 hotplug_en = I915_READ(PORT_HOTPLUG_EN);
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/i915/i915_reg.h linux-libre-2.6.38-gnu1/drivers/gpu/drm/i915/i915_reg.h
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/i915/i915_reg.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/i915/i915_reg.h	2011-03-14 21:20:32.000000000 -0400
@@ -78,6 +78,12 @@
 #define  GRDOM_RENDER	(1<<2)
 #define  GRDOM_MEDIA	(3<<2)
 
+#define GEN6_GDRST	0x941c
+#define  GEN6_GRDOM_FULL		(1 << 0)
+#define  GEN6_GRDOM_RENDER		(1 << 1)
+#define  GEN6_GRDOM_MEDIA		(1 << 2)
+#define  GEN6_GRDOM_BLT			(1 << 3)
+
 /* VGA stuff */
 
 #define VGA_ST01_MDA 0x3ba
@@ -139,6 +145,8 @@
 #define   MI_END_SCENE		(1 << 4) /* flush binner and incr scene count */
 #define   MI_INVALIDATE_ISP	(1 << 5) /* invalidate indirect state pointers */
 #define MI_BATCH_BUFFER_END	MI_INSTR(0x0a, 0)
+#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_CONTINUE	(0x0<<21)
@@ -153,17 +161,31 @@
 #define   MI_MM_SPACE_PHYSICAL		(0<<8)
 #define   MI_SAVE_EXT_STATE_EN		(1<<3)
 #define   MI_RESTORE_EXT_STATE_EN	(1<<2)
+#define   MI_FORCE_RESTORE		(1<<1)
 #define   MI_RESTORE_INHIBIT		(1<<0)
 #define MI_STORE_DWORD_IMM	MI_INSTR(0x20, 1)
 #define   MI_MEM_VIRTUAL	(1 << 22) /* 965+ only */
 #define MI_STORE_DWORD_INDEX	MI_INSTR(0x21, 1)
 #define   MI_STORE_DWORD_INDEX_SHIFT 2
-#define MI_LOAD_REGISTER_IMM	MI_INSTR(0x22, 1)
-#define MI_FLUSH_DW		MI_INSTR(0x26, 2) /* for GEN6 */
+/* Official intel docs are somewhat sloppy concerning MI_LOAD_REGISTER_IMM:
+ * - Always issue a MI_NOOP _before_ the MI_LOAD_REGISTER_IMM - otherwise hw
+ *   simply ignores the register load under certain conditions.
+ * - One can actually load arbitrary many arbitrary registers: Simply issue x
+ *   address/value pairs. Don't overdue it, though, x <= 2^4 must hold!
+ */
+#define MI_LOAD_REGISTER_IMM(x)	MI_INSTR(0x22, 2*x-1)
+#define MI_FLUSH_DW		MI_INSTR(0x26, 1) /* for GEN6 */
+#define   MI_INVALIDATE_TLB	(1<<18)
+#define   MI_INVALIDATE_BSD	(1<<7)
 #define MI_BATCH_BUFFER		MI_INSTR(0x30, 1)
 #define   MI_BATCH_NON_SECURE	(1)
 #define   MI_BATCH_NON_SECURE_I965 (1<<8)
 #define MI_BATCH_BUFFER_START	MI_INSTR(0x31, 0)
+#define MI_SEMAPHORE_MBOX	MI_INSTR(0x16, 1) /* gen6+ */
+#define  MI_SEMAPHORE_GLOBAL_GTT    (1<<22)
+#define  MI_SEMAPHORE_UPDATE	    (1<<21)
+#define  MI_SEMAPHORE_COMPARE	    (1<<20)
+#define  MI_SEMAPHORE_REGISTER	    (1<<18)
 /*
  * 3D instructions used by the kernel
  */
@@ -256,10 +278,6 @@
  * Instruction and interrupt control regs
  */
 #define PGTBL_ER	0x02024
-#define PRB0_TAIL	0x02030
-#define PRB0_HEAD	0x02034
-#define PRB0_START	0x02038
-#define PRB0_CTL	0x0203c
 #define RENDER_RING_BASE	0x02000
 #define BSD_RING_BASE		0x04000
 #define GEN6_BSD_RING_BASE	0x12000
@@ -268,9 +286,14 @@
 #define RING_HEAD(base)		((base)+0x34)
 #define RING_START(base)	((base)+0x38)
 #define RING_CTL(base)		((base)+0x3c)
+#define RING_SYNC_0(base)	((base)+0x40)
+#define RING_SYNC_1(base)	((base)+0x44)
+#define RING_MAX_IDLE(base)	((base)+0x54)
 #define RING_HWS_PGA(base)	((base)+0x80)
 #define RING_HWS_PGA_GEN6(base)	((base)+0x2080)
 #define RING_ACTHD(base)	((base)+0x74)
+#define RING_NOPID(base)	((base)+0x94)
+#define RING_IMR(base)		((base)+0xa8)
 #define   TAIL_ADDR		0x001FFFF8
 #define   HEAD_WRAP_COUNT	0xFFE00000
 #define   HEAD_WRAP_ONE		0x00200000
@@ -285,10 +308,17 @@
 #define   RING_INVALID		0x00000000
 #define   RING_WAIT_I8XX	(1<<0) /* gen2, PRBx_HEAD */
 #define   RING_WAIT		(1<<11) /* gen3+, PRBx_CTL */
+#define   RING_WAIT_SEMAPHORE	(1<<10) /* gen6+ */
+#if 0
+#define PRB0_TAIL	0x02030
+#define PRB0_HEAD	0x02034
+#define PRB0_START	0x02038
+#define PRB0_CTL	0x0203c
 #define PRB1_TAIL	0x02040 /* 915+ only */
 #define PRB1_HEAD	0x02044 /* 915+ only */
 #define PRB1_START	0x02048 /* 915+ only */
 #define PRB1_CTL	0x0204c /* 915+ only */
+#endif
 #define IPEIR_I965	0x02064
 #define IPEHR_I965	0x02068
 #define INSTDONE_I965	0x0206c
@@ -305,11 +335,42 @@
 #define INSTDONE	0x02090
 #define NOPID		0x02094
 #define HWSTAM		0x02098
+#define VCS_INSTDONE	0x1206C
+#define VCS_IPEIR	0x12064
+#define VCS_IPEHR	0x12068
+#define VCS_ACTHD	0x12074
+#define BCS_INSTDONE	0x2206C
+#define BCS_IPEIR	0x22064
+#define BCS_IPEHR	0x22068
+#define BCS_ACTHD	0x22074
+
+#define ERROR_GEN6	0x040a0
+
+/* GM45+ chicken bits -- debug workaround bits that may be required
+ * for various sorts of correct behavior.  The top 16 bits of each are
+ * the enables for writing to the corresponding low bit.
+ */
+#define _3D_CHICKEN	0x02084
+#define _3D_CHICKEN2	0x0208c
+/* Disables pipelining of read flushes past the SF-WIZ interface.
+ * Required on all Ironlake steppings according to the B-Spec, but the
+ * particular danger of not doing so is not specified.
+ */
+# define _3D_CHICKEN2_WM_READ_PIPELINED			(1 << 14)
+#define _3D_CHICKEN3	0x02090
 
 #define MI_MODE		0x0209c
 # define VS_TIMER_DISPATCH				(1 << 6)
 # define MI_FLUSH_ENABLE				(1 << 11)
 
+#define GFX_MODE	0x02520
+#define   GFX_RUN_LIST_ENABLE		(1<<15)
+#define   GFX_TLB_INVALIDATE_ALWAYS	(1<<13)
+#define   GFX_SURFACE_FAULT_ENABLE	(1<<12)
+#define   GFX_REPLAY_MODE		(1<<11)
+#define   GFX_PSMI_GRANULARITY		(1<<10)
+#define   GFX_PPGTT_ENABLE		(1<<9)
+
 #define SCPD0		0x0209c /* 915+ only */
 #define IER		0x020a0
 #define IIR		0x020a4
@@ -454,6 +515,10 @@
 #define   GEN6_BLITTER_SYNC_STATUS			(1 << 24)
 #define   GEN6_BLITTER_USER_INTERRUPT			(1 << 22)
 
+#define GEN6_BLITTER_ECOSKPD	0x221d0
+#define   GEN6_BLITTER_LOCK_SHIFT			16
+#define   GEN6_BLITTER_FBC_NOTIFY			(1<<3)
+
 #define GEN6_BSD_SLEEP_PSMI_CONTROL	0x12050
 #define   GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_MODIFY_MASK	(1 << 16)
 #define   GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_DISABLE		(1 << 0)
@@ -461,7 +526,7 @@
 #define   GEN6_BSD_SLEEP_PSMI_CONTROL_IDLE_INDICATOR			(1 << 3)
 
 #define GEN6_BSD_IMR			0x120a8
-#define   GEN6_BSD_IMR_USER_INTERRUPT	(1 << 12)
+#define   GEN6_BSD_USER_INTERRUPT	(1 << 12)
 
 #define GEN6_BSD_RNCID			0x12198
 
@@ -541,6 +606,18 @@
 
 #define ILK_DISPLAY_CHICKEN1	0x42000
 #define   ILK_FBCQ_DIS		(1<<22)
+#define   ILK_PABSTRETCH_DIS 	(1<<21)
+
+
+/*
+ * Framebuffer compression for Sandybridge
+ *
+ * The following two registers are of type GTTMMADR
+ */
+#define SNB_DPFC_CTL_SA		0x100100
+#define   SNB_CPU_FENCE_ENABLE	(1<<29)
+#define DPFC_CPU_FENCE_OFFSET	0x100104
+
 
 /*
  * GPIO regs
@@ -900,6 +977,8 @@
  */
 #define MCHBAR_MIRROR_BASE	0x10000
 
+#define MCHBAR_MIRROR_BASE_SNB	0x140000
+
 /** 915-945 and GM965 MCH register controlling DRAM channel access */
 #define DCC			0x10200
 #define DCC_ADDRESSING_MODE_SINGLE_CHANNEL		(0 << 0)
@@ -1061,9 +1140,50 @@
 #define RCBMINAVG		0x111a0
 #define RCUPEI			0x111b0
 #define RCDNEI			0x111b4
-#define MCHBAR_RENDER_STANDBY		0x111b8
-#define   RCX_SW_EXIT		(1<<23)
-#define   RSX_STATUS_MASK	0x00700000
+#define RSTDBYCTL		0x111b8
+#define   RS1EN			(1<<31)
+#define   RS2EN			(1<<30)
+#define   RS3EN			(1<<29)
+#define   D3RS3EN		(1<<28) /* Display D3 imlies RS3 */
+#define   SWPROMORSX		(1<<27) /* RSx promotion timers ignored */
+#define   RCWAKERW		(1<<26) /* Resetwarn from PCH causes wakeup */
+#define   DPRSLPVREN		(1<<25) /* Fast voltage ramp enable */
+#define   GFXTGHYST		(1<<24) /* Hysteresis to allow trunk gating */
+#define   RCX_SW_EXIT		(1<<23) /* Leave RSx and prevent re-entry */
+#define   RSX_STATUS_MASK	(7<<20)
+#define   RSX_STATUS_ON		(0<<20)
+#define   RSX_STATUS_RC1	(1<<20)
+#define   RSX_STATUS_RC1E	(2<<20)
+#define   RSX_STATUS_RS1	(3<<20)
+#define   RSX_STATUS_RS2	(4<<20) /* aka rc6 */
+#define   RSX_STATUS_RSVD	(5<<20) /* deep rc6 unsupported on ilk */
+#define   RSX_STATUS_RS3	(6<<20) /* rs3 unsupported on ilk */
+#define   RSX_STATUS_RSVD2	(7<<20)
+#define   UWRCRSXE		(1<<19) /* wake counter limit prevents rsx */
+#define   RSCRP			(1<<18) /* rs requests control on rs1/2 reqs */
+#define   JRSC			(1<<17) /* rsx coupled to cpu c-state */
+#define   RS2INC0		(1<<16) /* allow rs2 in cpu c0 */
+#define   RS1CONTSAV_MASK	(3<<14)
+#define   RS1CONTSAV_NO_RS1	(0<<14) /* rs1 doesn't save/restore context */
+#define   RS1CONTSAV_RSVD	(1<<14)
+#define   RS1CONTSAV_SAVE_RS1	(2<<14) /* rs1 saves context */
+#define   RS1CONTSAV_FULL_RS1	(3<<14) /* rs1 saves and restores context */
+#define   NORMSLEXLAT_MASK	(3<<12)
+#define   SLOW_RS123		(0<<12)
+#define   SLOW_RS23		(1<<12)
+#define   SLOW_RS3		(2<<12)
+#define   NORMAL_RS123		(3<<12)
+#define   RCMODE_TIMEOUT	(1<<11) /* 0 is eval interval method */
+#define   IMPROMOEN		(1<<10) /* promo is immediate or delayed until next idle interval (only for timeout method above) */
+#define   RCENTSYNC		(1<<9) /* rs coupled to cpu c-state (3/6/7) */
+#define   STATELOCK		(1<<7) /* locked to rs_cstate if 0 */
+#define   RS_CSTATE_MASK	(3<<4)
+#define   RS_CSTATE_C367_RS1	(0<<4)
+#define   RS_CSTATE_C36_RS1_C7_RS2 (1<<4)
+#define   RS_CSTATE_RSVD	(2<<4)
+#define   RS_CSTATE_C367_RS2	(3<<4)
+#define   REDSAVES		(1<<3) /* no context save if was idle during rs0 */
+#define   REDRESTORES		(1<<2) /* no restore if was idle during rs0 */
 #define VIDCTL			0x111c0
 #define VIDSTS			0x111c8
 #define VIDSTART		0x111cc /* 8 bits */
@@ -1119,6 +1239,10 @@
 #define DDRMPLL1		0X12c20
 #define PEG_BAND_GAP_DATA	0x14d68
 
+#define GEN6_GT_PERF_STATUS	0x145948
+#define GEN6_RP_STATE_LIMITS	0x145994
+#define GEN6_RP_STATE_CAP	0x145998
+
 /*
  * Logical Context regs
  */
@@ -1168,7 +1292,6 @@
 #define VTOTAL(pipe) _PIPE(pipe, VTOTAL_A, VTOTAL_B)
 #define VBLANK(pipe) _PIPE(pipe, VBLANK_A, VBLANK_B)
 #define VSYNC(pipe) _PIPE(pipe, VSYNC_A, VSYNC_B)
-#define PIPESRC(pipe) _PIPE(pipe, PIPEASRC, PIPEBSRC)
 #define BCLRPAT(pipe) _PIPE(pipe, BCLRPAT_A, BCLRPAT_B)
 
 /* VGA port control */
@@ -2182,8 +2305,10 @@
 #define   PIPE_6BPC				(2 << 5)
 #define   PIPE_12BPC				(3 << 5)
 
+#define PIPESRC(pipe) _PIPE(pipe, PIPEASRC, PIPEBSRC)
 #define PIPECONF(pipe) _PIPE(pipe, PIPEACONF, PIPEBCONF)
 #define PIPEDSL(pipe)  _PIPE(pipe, PIPEADSL, PIPEBDSL)
+#define PIPEFRAMEPIXEL(pipe)  _PIPE(pipe, PIPEAFRAMEPIXEL, PIPEBFRAMEPIXEL)
 
 #define DSPARB			0x70030
 #define   DSPARB_CSTART_MASK	(0x7f << 7)
@@ -2271,8 +2396,13 @@
 
 /* Memory latency timer register */
 #define MLTR_ILK		0x11222
+#define  MLTR_WM1_SHIFT		0
+#define  MLTR_WM2_SHIFT		8
 /* the unit of memory self-refresh latency time is 0.5us */
 #define  ILK_SRLT_MASK		0x3f
+#define ILK_LATENCY(shift)	(I915_READ(MLTR_ILK) >> (shift) & ILK_SRLT_MASK)
+#define ILK_READ_WM1_LATENCY()	ILK_LATENCY(MLTR_WM1_SHIFT)
+#define ILK_READ_WM2_LATENCY()	ILK_LATENCY(MLTR_WM2_SHIFT)
 
 /* define the fifo size on Ironlake */
 #define ILK_DISPLAY_FIFO	128
@@ -2291,6 +2421,40 @@
 
 #define ILK_FIFO_LINE_SIZE	64
 
+/* define the WM info on Sandybridge */
+#define SNB_DISPLAY_FIFO	128
+#define SNB_DISPLAY_MAXWM	0x7f	/* bit 16:22 */
+#define SNB_DISPLAY_DFTWM	8
+#define SNB_CURSOR_FIFO		32
+#define SNB_CURSOR_MAXWM	0x1f	/* bit 4:0 */
+#define SNB_CURSOR_DFTWM	8
+
+#define SNB_DISPLAY_SR_FIFO	512
+#define SNB_DISPLAY_MAX_SRWM	0x1ff	/* bit 16:8 */
+#define SNB_DISPLAY_DFT_SRWM	0x3f
+#define SNB_CURSOR_SR_FIFO	64
+#define SNB_CURSOR_MAX_SRWM	0x3f	/* bit 5:0 */
+#define SNB_CURSOR_DFT_SRWM	8
+
+#define SNB_FBC_MAX_SRWM	0xf	/* bit 23:20 */
+
+#define SNB_FIFO_LINE_SIZE	64
+
+
+/* the address where we get all kinds of latency value */
+#define SSKPD			0x5d10
+#define SSKPD_WM_MASK		0x3f
+#define SSKPD_WM0_SHIFT		0
+#define SSKPD_WM1_SHIFT		8
+#define SSKPD_WM2_SHIFT		16
+#define SSKPD_WM3_SHIFT		24
+
+#define SNB_LATENCY(shift)	(I915_READ(MCHBAR_MIRROR_BASE_SNB + SSKPD) >> (shift) & SSKPD_WM_MASK)
+#define SNB_READ_WM0_LATENCY()		SNB_LATENCY(SSKPD_WM0_SHIFT)
+#define SNB_READ_WM1_LATENCY()		SNB_LATENCY(SSKPD_WM1_SHIFT)
+#define SNB_READ_WM2_LATENCY()		SNB_LATENCY(SSKPD_WM2_SHIFT)
+#define SNB_READ_WM3_LATENCY()		SNB_LATENCY(SSKPD_WM3_SHIFT)
+
 /*
  * The two pipe frame counter registers are not synchronized, so
  * reading a stable value is somewhat tricky. The following code
@@ -2351,6 +2515,10 @@
 #define CURBBASE		0x700c4
 #define CURBPOS			0x700c8
 
+#define CURCNTR(pipe) _PIPE(pipe, CURACNTR, CURBCNTR)
+#define CURBASE(pipe) _PIPE(pipe, CURABASE, CURBBASE)
+#define CURPOS(pipe) _PIPE(pipe, CURAPOS, CURBPOS)
+
 /* Display A control */
 #define DSPACNTR                0x70180
 #define   DISPLAY_PLANE_ENABLE			(1<<31)
@@ -2464,6 +2632,8 @@
 #define DISPLAY_PORT_PLL_BIOS_2         0x46014
 
 #define PCH_DSPCLK_GATE_D	0x42020
+# define DPFCUNIT_CLOCK_GATE_DISABLE		(1 << 9)
+# define DPFCRUNIT_CLOCK_GATE_DISABLE		(1 << 8)
 # define DPFDUNIT_CLOCK_GATE_DISABLE		(1 << 7)
 # define DPARBUNIT_CLOCK_GATE_DISABLE		(1 << 5)
 
@@ -2589,6 +2759,8 @@
 #define GTIER   0x4401c
 
 #define ILK_DISPLAY_CHICKEN2	0x42004
+/* Required on all Ironlake and Sandybridge according to the B-Spec. */
+#define  ILK_ELPIN_409_SELECT	(1 << 25)
 #define  ILK_DPARB_GATE	(1<<22)
 #define  ILK_VSDPFD_FULL	(1<<21)
 #define ILK_DISPLAY_CHICKEN_FUSES	0x42014
@@ -2600,6 +2772,8 @@
 #define  ILK_DESKTOP			(1<<23)
 #define ILK_DSPCLK_GATE		0x42020
 #define  ILK_DPARB_CLK_GATE	(1<<5)
+#define  ILK_DPFD_CLK_GATE	(1<<7)
+
 /* According to spec this bit 7/8/9 of 0x42020 should be set to enable FBC */
 #define   ILK_CLK_FBC		(1<<7)
 #define   ILK_DPFC_DIS1		(1<<8)
@@ -2612,12 +2786,41 @@
 /* PCH */
 
 /* south display engine interrupt */
+#define SDE_AUDIO_POWER_D	(1 << 27)
+#define SDE_AUDIO_POWER_C	(1 << 26)
+#define SDE_AUDIO_POWER_B	(1 << 25)
+#define SDE_AUDIO_POWER_SHIFT	(25)
+#define SDE_AUDIO_POWER_MASK	(7 << SDE_AUDIO_POWER_SHIFT)
+#define SDE_GMBUS		(1 << 24)
+#define SDE_AUDIO_HDCP_TRANSB	(1 << 23)
+#define SDE_AUDIO_HDCP_TRANSA	(1 << 22)
+#define SDE_AUDIO_HDCP_MASK	(3 << 22)
+#define SDE_AUDIO_TRANSB	(1 << 21)
+#define SDE_AUDIO_TRANSA	(1 << 20)
+#define SDE_AUDIO_TRANS_MASK	(3 << 20)
+#define SDE_POISON		(1 << 19)
+/* 18 reserved */
+#define SDE_FDI_RXB		(1 << 17)
+#define SDE_FDI_RXA		(1 << 16)
+#define SDE_FDI_MASK		(3 << 16)
+#define SDE_AUXD		(1 << 15)
+#define SDE_AUXC		(1 << 14)
+#define SDE_AUXB		(1 << 13)
+#define SDE_AUX_MASK		(7 << 13)
+/* 12 reserved */
 #define SDE_CRT_HOTPLUG         (1 << 11)
 #define SDE_PORTD_HOTPLUG       (1 << 10)
 #define SDE_PORTC_HOTPLUG       (1 << 9)
 #define SDE_PORTB_HOTPLUG       (1 << 8)
 #define SDE_SDVOB_HOTPLUG       (1 << 6)
 #define SDE_HOTPLUG_MASK	(0xf << 8)
+#define SDE_TRANSB_CRC_DONE	(1 << 5)
+#define SDE_TRANSB_CRC_ERR	(1 << 4)
+#define SDE_TRANSB_FIFO_UNDER	(1 << 3)
+#define SDE_TRANSA_CRC_DONE	(1 << 2)
+#define SDE_TRANSA_CRC_ERR	(1 << 1)
+#define SDE_TRANSA_FIFO_UNDER	(1 << 0)
+#define SDE_TRANS_MASK		(0x3f)
 /* CPT */
 #define SDE_CRT_HOTPLUG_CPT	(1 << 19)
 #define SDE_PORTD_HOTPLUG_CPT	(1 << 23)
@@ -2679,6 +2882,7 @@
 #define PCH_DPLL(pipe) _PIPE(pipe, 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
@@ -3057,10 +3261,76 @@
 #define  EDP_LINK_TRAIN_600MV_3_5DB_SNB_A	(0x01<<22)
 #define  EDP_LINK_TRAIN_800MV_0DB_SNB_A		(0x0<<22)
 /* SNB B-stepping */
-#define  EDP_LINK_TRAIN_400MV_0DB_SNB_B		(0x0<<22)
-#define  EDP_LINK_TRAIN_400MV_6DB_SNB_B		(0x3a<<22)
-#define  EDP_LINK_TRAIN_600MV_3_5DB_SNB_B	(0x39<<22)
-#define  EDP_LINK_TRAIN_800MV_0DB_SNB_B		(0x38<<22)
+#define  EDP_LINK_TRAIN_400_600MV_0DB_SNB_B	(0x0<<22)
+#define  EDP_LINK_TRAIN_400MV_3_5DB_SNB_B	(0x1<<22)
+#define  EDP_LINK_TRAIN_400_600MV_6DB_SNB_B	(0x3a<<22)
+#define  EDP_LINK_TRAIN_600_800MV_3_5DB_SNB_B	(0x39<<22)
+#define  EDP_LINK_TRAIN_800_1200MV_0DB_SNB_B	(0x38<<22)
 #define  EDP_LINK_TRAIN_VOL_EMP_MASK_SNB	(0x3f<<22)
 
+#define  FORCEWAKE				0xA18C
+#define  FORCEWAKE_ACK				0x130090
+
+#define  GT_FIFO_FREE_ENTRIES			0x120008
+
+#define GEN6_RPNSWREQ				0xA008
+#define   GEN6_TURBO_DISABLE			(1<<31)
+#define   GEN6_FREQUENCY(x)			((x)<<25)
+#define   GEN6_OFFSET(x)			((x)<<19)
+#define   GEN6_AGGRESSIVE_TURBO			(0<<15)
+#define GEN6_RC_VIDEO_FREQ			0xA00C
+#define GEN6_RC_CONTROL				0xA090
+#define   GEN6_RC_CTL_RC6pp_ENABLE		(1<<16)
+#define   GEN6_RC_CTL_RC6p_ENABLE		(1<<17)
+#define   GEN6_RC_CTL_RC6_ENABLE		(1<<18)
+#define   GEN6_RC_CTL_RC1e_ENABLE		(1<<20)
+#define   GEN6_RC_CTL_RC7_ENABLE		(1<<22)
+#define   GEN6_RC_CTL_EI_MODE(x)		((x)<<27)
+#define   GEN6_RC_CTL_HW_ENABLE			(1<<31)
+#define GEN6_RP_DOWN_TIMEOUT			0xA010
+#define GEN6_RP_INTERRUPT_LIMITS		0xA014
+#define GEN6_RPSTAT1				0xA01C
+#define GEN6_RP_CONTROL				0xA024
+#define   GEN6_RP_MEDIA_TURBO			(1<<11)
+#define   GEN6_RP_USE_NORMAL_FREQ		(1<<9)
+#define   GEN6_RP_MEDIA_IS_GFX			(1<<8)
+#define   GEN6_RP_ENABLE			(1<<7)
+#define   GEN6_RP_UP_BUSY_MAX			(0x2<<3)
+#define   GEN6_RP_DOWN_BUSY_MIN			(0x2<<0)
+#define GEN6_RP_UP_THRESHOLD			0xA02C
+#define GEN6_RP_DOWN_THRESHOLD			0xA030
+#define GEN6_RP_UP_EI				0xA068
+#define GEN6_RP_DOWN_EI				0xA06C
+#define GEN6_RP_IDLE_HYSTERSIS			0xA070
+#define GEN6_RC_STATE				0xA094
+#define GEN6_RC1_WAKE_RATE_LIMIT		0xA098
+#define GEN6_RC6_WAKE_RATE_LIMIT		0xA09C
+#define GEN6_RC6pp_WAKE_RATE_LIMIT		0xA0A0
+#define GEN6_RC_EVALUATION_INTERVAL		0xA0A8
+#define GEN6_RC_IDLE_HYSTERSIS			0xA0AC
+#define GEN6_RC_SLEEP				0xA0B0
+#define GEN6_RC1e_THRESHOLD			0xA0B4
+#define GEN6_RC6_THRESHOLD			0xA0B8
+#define GEN6_RC6p_THRESHOLD			0xA0BC
+#define GEN6_RC6pp_THRESHOLD			0xA0C0
+#define GEN6_PMINTRMSK				0xA168
+
+#define GEN6_PMISR				0x44020
+#define GEN6_PMIMR				0x44024
+#define GEN6_PMIIR				0x44028
+#define GEN6_PMIER				0x4402C
+#define  GEN6_PM_MBOX_EVENT			(1<<25)
+#define  GEN6_PM_THERMAL_EVENT			(1<<24)
+#define  GEN6_PM_RP_DOWN_TIMEOUT		(1<<6)
+#define  GEN6_PM_RP_UP_THRESHOLD		(1<<5)
+#define  GEN6_PM_RP_DOWN_THRESHOLD		(1<<4)
+#define  GEN6_PM_RP_UP_EI_EXPIRED		(1<<2)
+#define  GEN6_PM_RP_DOWN_EI_EXPIRED		(1<<1)
+
+#define GEN6_PCODE_MAILBOX			0x138124
+#define   GEN6_PCODE_READY			(1<<31)
+#define   GEN6_READ_OC_PARAMS			0xc
+#define   GEN6_PCODE_WRITE_MIN_FREQ_TABLE	0x9
+#define GEN6_PCODE_DATA				0x138128
+
 #endif /* _I915_REG_H_ */
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/i915/i915_suspend.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/i915/i915_suspend.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/i915/i915_suspend.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/i915/i915_suspend.c	2011-03-14 21:20:32.000000000 -0400
@@ -235,6 +235,7 @@ static void i915_restore_vga(struct drm_
 static void i915_save_modeset_reg(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
+	int i;
 
 	if (drm_core_check_feature(dev, DRIVER_MODESET))
 		return;
@@ -367,6 +368,28 @@ static void i915_save_modeset_reg(struct
 	}
 	i915_save_palette(dev, PIPE_B);
 	dev_priv->savePIPEBSTAT = I915_READ(PIPEBSTAT);
+
+	/* Fences */
+	switch (INTEL_INFO(dev)->gen) {
+	case 6:
+		for (i = 0; i < 16; i++)
+			dev_priv->saveFENCE[i] = I915_READ64(FENCE_REG_SANDYBRIDGE_0 + (i * 8));
+		break;
+	case 5:
+	case 4:
+		for (i = 0; i < 16; i++)
+			dev_priv->saveFENCE[i] = I915_READ64(FENCE_REG_965_0 + (i * 8));
+		break;
+	case 3:
+		if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev))
+			for (i = 0; i < 8; i++)
+				dev_priv->saveFENCE[i+8] = I915_READ(FENCE_REG_945_8 + (i * 4));
+	case 2:
+		for (i = 0; i < 8; i++)
+			dev_priv->saveFENCE[i] = I915_READ(FENCE_REG_830_0 + (i * 4));
+		break;
+	}
+
 	return;
 }
 
@@ -375,10 +398,33 @@ static void i915_restore_modeset_reg(str
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	int dpll_a_reg, fpa0_reg, fpa1_reg;
 	int dpll_b_reg, fpb0_reg, fpb1_reg;
+	int i;
 
 	if (drm_core_check_feature(dev, DRIVER_MODESET))
 		return;
 
+	/* Fences */
+	switch (INTEL_INFO(dev)->gen) {
+	case 6:
+		for (i = 0; i < 16; i++)
+			I915_WRITE64(FENCE_REG_SANDYBRIDGE_0 + (i * 8), dev_priv->saveFENCE[i]);
+		break;
+	case 5:
+	case 4:
+		for (i = 0; i < 16; i++)
+			I915_WRITE64(FENCE_REG_965_0 + (i * 8), dev_priv->saveFENCE[i]);
+		break;
+	case 3:
+	case 2:
+		if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev))
+			for (i = 0; i < 8; i++)
+				I915_WRITE(FENCE_REG_945_8 + (i * 4), dev_priv->saveFENCE[i+8]);
+		for (i = 0; i < 8; i++)
+			I915_WRITE(FENCE_REG_830_0 + (i * 4), dev_priv->saveFENCE[i]);
+		break;
+	}
+
+
 	if (HAS_PCH_SPLIT(dev)) {
 		dpll_a_reg = PCH_DPLL_A;
 		dpll_b_reg = PCH_DPLL_B;
@@ -694,7 +740,7 @@ void i915_restore_display(struct drm_dev
 		I915_WRITE(PCH_PP_OFF_DELAYS, dev_priv->savePP_OFF_DELAYS);
 		I915_WRITE(PCH_PP_DIVISOR, dev_priv->savePP_DIVISOR);
 		I915_WRITE(PCH_PP_CONTROL, dev_priv->savePP_CONTROL);
-		I915_WRITE(MCHBAR_RENDER_STANDBY,
+		I915_WRITE(RSTDBYCTL,
 			   dev_priv->saveMCHBAR_RENDER_STANDBY);
 	} else {
 		I915_WRITE(PFIT_PGM_RATIOS, dev_priv->savePFIT_PGM_RATIOS);
@@ -765,14 +811,16 @@ int i915_save_state(struct drm_device *d
 		dev_priv->saveFDI_RXA_IMR = I915_READ(FDI_RXA_IMR);
 		dev_priv->saveFDI_RXB_IMR = I915_READ(FDI_RXB_IMR);
 		dev_priv->saveMCHBAR_RENDER_STANDBY =
-			I915_READ(MCHBAR_RENDER_STANDBY);
+			I915_READ(RSTDBYCTL);
 	} else {
 		dev_priv->saveIER = I915_READ(IER);
 		dev_priv->saveIMR = I915_READ(IMR);
 	}
 
-	if (HAS_PCH_SPLIT(dev))
+	if (IS_IRONLAKE_M(dev))
 		ironlake_disable_drps(dev);
+	if (IS_GEN6(dev))
+		gen6_disable_rps(dev);
 
 	/* Cache mode state */
 	dev_priv->saveCACHE_MODE_0 = I915_READ(CACHE_MODE_0);
@@ -788,28 +836,6 @@ int i915_save_state(struct drm_device *d
 	for (i = 0; i < 3; i++)
 		dev_priv->saveSWF2[i] = I915_READ(SWF30 + (i << 2));
 
-	/* Fences */
-	switch (INTEL_INFO(dev)->gen) {
-	case 6:
-		for (i = 0; i < 16; i++)
-			dev_priv->saveFENCE[i] = I915_READ64(FENCE_REG_SANDYBRIDGE_0 + (i * 8));
-		break;
-	case 5:
-	case 4:
-		for (i = 0; i < 16; i++)
-			dev_priv->saveFENCE[i] = I915_READ64(FENCE_REG_965_0 + (i * 8));
-		break;
-	case 3:
-		if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev))
-			for (i = 0; i < 8; i++)
-				dev_priv->saveFENCE[i+8] = I915_READ(FENCE_REG_945_8 + (i * 4));
-	case 2:
-		for (i = 0; i < 8; i++)
-			dev_priv->saveFENCE[i] = I915_READ(FENCE_REG_830_0 + (i * 4));
-		break;
-
-	}
-
 	return 0;
 }
 
@@ -823,27 +849,6 @@ int i915_restore_state(struct drm_device
 	/* Hardware status page */
 	I915_WRITE(HWS_PGA, dev_priv->saveHWS);
 
-	/* Fences */
-	switch (INTEL_INFO(dev)->gen) {
-	case 6:
-		for (i = 0; i < 16; i++)
-			I915_WRITE64(FENCE_REG_SANDYBRIDGE_0 + (i * 8), dev_priv->saveFENCE[i]);
-		break;
-	case 5:
-	case 4:
-		for (i = 0; i < 16; i++)
-			I915_WRITE64(FENCE_REG_965_0 + (i * 8), dev_priv->saveFENCE[i]);
-		break;
-	case 3:
-	case 2:
-		if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev))
-			for (i = 0; i < 8; i++)
-				I915_WRITE(FENCE_REG_945_8 + (i * 4), dev_priv->saveFENCE[i+8]);
-		for (i = 0; i < 8; i++)
-			I915_WRITE(FENCE_REG_830_0 + (i * 4), dev_priv->saveFENCE[i]);
-		break;
-	}
-
 	i915_restore_display(dev);
 
 	/* Interrupt state */
@@ -860,13 +865,16 @@ int i915_restore_state(struct drm_device
 	}
 
 	/* Clock gating state */
-	intel_init_clock_gating(dev);
+	intel_enable_clock_gating(dev);
 
-	if (HAS_PCH_SPLIT(dev)) {
+	if (IS_IRONLAKE_M(dev)) {
 		ironlake_enable_drps(dev);
 		intel_init_emon(dev);
 	}
 
+	if (IS_GEN6(dev))
+		gen6_enable_rps(dev_priv);
+
 	/* Cache mode state */
 	I915_WRITE (CACHE_MODE_0, dev_priv->saveCACHE_MODE_0 | 0xffff0000);
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/i915/i915_trace.h linux-libre-2.6.38-gnu1/drivers/gpu/drm/i915/i915_trace.h
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/i915/i915_trace.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/i915/i915_trace.h	2011-03-14 21:20:32.000000000 -0400
@@ -6,6 +6,7 @@
 #include <linux/tracepoint.h>
 
 #include <drm/drmP.h>
+#include "i915_drv.h"
 
 #undef TRACE_SYSTEM
 #define TRACE_SYSTEM i915
@@ -16,18 +17,18 @@
 
 TRACE_EVENT(i915_gem_object_create,
 
-	    TP_PROTO(struct drm_gem_object *obj),
+	    TP_PROTO(struct drm_i915_gem_object *obj),
 
 	    TP_ARGS(obj),
 
 	    TP_STRUCT__entry(
-			     __field(struct drm_gem_object *, obj)
+			     __field(struct drm_i915_gem_object *, obj)
 			     __field(u32, size)
 			     ),
 
 	    TP_fast_assign(
 			   __entry->obj = obj;
-			   __entry->size = obj->size;
+			   __entry->size = obj->base.size;
 			   ),
 
 	    TP_printk("obj=%p, size=%u", __entry->obj, __entry->size)
@@ -35,40 +36,43 @@ TRACE_EVENT(i915_gem_object_create,
 
 TRACE_EVENT(i915_gem_object_bind,
 
-	    TP_PROTO(struct drm_gem_object *obj, u32 gtt_offset),
+	    TP_PROTO(struct drm_i915_gem_object *obj, u32 gtt_offset, bool mappable),
 
-	    TP_ARGS(obj, gtt_offset),
+	    TP_ARGS(obj, gtt_offset, mappable),
 
 	    TP_STRUCT__entry(
-			     __field(struct drm_gem_object *, obj)
+			     __field(struct drm_i915_gem_object *, obj)
 			     __field(u32, gtt_offset)
+			     __field(bool, mappable)
 			     ),
 
 	    TP_fast_assign(
 			   __entry->obj = obj;
 			   __entry->gtt_offset = gtt_offset;
+			   __entry->mappable = mappable;
 			   ),
 
-	    TP_printk("obj=%p, gtt_offset=%08x",
-		      __entry->obj, __entry->gtt_offset)
+	    TP_printk("obj=%p, gtt_offset=%08x%s",
+		      __entry->obj, __entry->gtt_offset,
+		      __entry->mappable ? ", mappable" : "")
 );
 
 TRACE_EVENT(i915_gem_object_change_domain,
 
-	    TP_PROTO(struct drm_gem_object *obj, uint32_t old_read_domains, uint32_t old_write_domain),
+	    TP_PROTO(struct drm_i915_gem_object *obj, uint32_t old_read_domains, uint32_t old_write_domain),
 
 	    TP_ARGS(obj, old_read_domains, old_write_domain),
 
 	    TP_STRUCT__entry(
-			     __field(struct drm_gem_object *, obj)
+			     __field(struct drm_i915_gem_object *, obj)
 			     __field(u32, read_domains)
 			     __field(u32, write_domain)
 			     ),
 
 	    TP_fast_assign(
 			   __entry->obj = obj;
-			   __entry->read_domains = obj->read_domains | (old_read_domains << 16);
-			   __entry->write_domain = obj->write_domain | (old_write_domain << 16);
+			   __entry->read_domains = obj->base.read_domains | (old_read_domains << 16);
+			   __entry->write_domain = obj->base.write_domain | (old_write_domain << 16);
 			   ),
 
 	    TP_printk("obj=%p, read=%04x, write=%04x",
@@ -76,36 +80,14 @@ TRACE_EVENT(i915_gem_object_change_domai
 		      __entry->read_domains, __entry->write_domain)
 );
 
-TRACE_EVENT(i915_gem_object_get_fence,
-
-	    TP_PROTO(struct drm_gem_object *obj, int fence, int tiling_mode),
-
-	    TP_ARGS(obj, fence, tiling_mode),
-
-	    TP_STRUCT__entry(
-			     __field(struct drm_gem_object *, obj)
-			     __field(int, fence)
-			     __field(int, tiling_mode)
-			     ),
-
-	    TP_fast_assign(
-			   __entry->obj = obj;
-			   __entry->fence = fence;
-			   __entry->tiling_mode = tiling_mode;
-			   ),
-
-	    TP_printk("obj=%p, fence=%d, tiling=%d",
-		      __entry->obj, __entry->fence, __entry->tiling_mode)
-);
-
 DECLARE_EVENT_CLASS(i915_gem_object,
 
-	    TP_PROTO(struct drm_gem_object *obj),
+	    TP_PROTO(struct drm_i915_gem_object *obj),
 
 	    TP_ARGS(obj),
 
 	    TP_STRUCT__entry(
-			     __field(struct drm_gem_object *, obj)
+			     __field(struct drm_i915_gem_object *, obj)
 			     ),
 
 	    TP_fast_assign(
@@ -117,21 +99,21 @@ DECLARE_EVENT_CLASS(i915_gem_object,
 
 DEFINE_EVENT(i915_gem_object, i915_gem_object_clflush,
 
-	    TP_PROTO(struct drm_gem_object *obj),
+	    TP_PROTO(struct drm_i915_gem_object *obj),
 
 	    TP_ARGS(obj)
 );
 
 DEFINE_EVENT(i915_gem_object, i915_gem_object_unbind,
 
-	    TP_PROTO(struct drm_gem_object *obj),
+	    TP_PROTO(struct drm_i915_gem_object *obj),
 
 	    TP_ARGS(obj)
 );
 
 DEFINE_EVENT(i915_gem_object, i915_gem_object_destroy,
 
-	    TP_PROTO(struct drm_gem_object *obj),
+	    TP_PROTO(struct drm_i915_gem_object *obj),
 
 	    TP_ARGS(obj)
 );
@@ -263,13 +245,13 @@ DEFINE_EVENT(i915_ring, i915_ring_wait_e
 );
 
 TRACE_EVENT(i915_flip_request,
-	    TP_PROTO(int plane, struct drm_gem_object *obj),
+	    TP_PROTO(int plane, struct drm_i915_gem_object *obj),
 
 	    TP_ARGS(plane, obj),
 
 	    TP_STRUCT__entry(
 		    __field(int, plane)
-		    __field(struct drm_gem_object *, obj)
+		    __field(struct drm_i915_gem_object *, obj)
 		    ),
 
 	    TP_fast_assign(
@@ -281,13 +263,13 @@ TRACE_EVENT(i915_flip_request,
 );
 
 TRACE_EVENT(i915_flip_complete,
-	    TP_PROTO(int plane, struct drm_gem_object *obj),
+	    TP_PROTO(int plane, struct drm_i915_gem_object *obj),
 
 	    TP_ARGS(plane, obj),
 
 	    TP_STRUCT__entry(
 		    __field(int, plane)
-		    __field(struct drm_gem_object *, obj)
+		    __field(struct drm_i915_gem_object *, obj)
 		    ),
 
 	    TP_fast_assign(
@@ -298,6 +280,29 @@ TRACE_EVENT(i915_flip_complete,
 	    TP_printk("plane=%d, obj=%p", __entry->plane, __entry->obj)
 );
 
+TRACE_EVENT(i915_reg_rw,
+           TP_PROTO(int cmd, uint32_t reg, uint64_t val, int len),
+
+           TP_ARGS(cmd, reg, val, len),
+
+           TP_STRUCT__entry(
+                   __field(int, cmd)
+                   __field(uint32_t, reg)
+                   __field(uint64_t, val)
+                   __field(int, len)
+                   ),
+
+           TP_fast_assign(
+                   __entry->cmd = cmd;
+                   __entry->reg = reg;
+                   __entry->val = (uint64_t)val;
+                   __entry->len = len;
+                   ),
+
+           TP_printk("cmd=%c, reg=0x%x, val=0x%llx, len=%d",
+                     __entry->cmd, __entry->reg, __entry->val, __entry->len)
+);
+
 #endif /* _I915_TRACE_H_ */
 
 /* This part must be outside protection */
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/i915/intel_bios.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/i915/intel_bios.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/i915/intel_bios.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/i915/intel_bios.c	2011-03-14 21:20:32.000000000 -0400
@@ -264,17 +264,12 @@ parse_general_features(struct drm_i915_p
 		dev_priv->int_crt_support = general->int_crt_support;
 		dev_priv->lvds_use_ssc = general->enable_ssc;
 
-		if (dev_priv->lvds_use_ssc) {
-			if (IS_I85X(dev))
-				dev_priv->lvds_ssc_freq =
-					general->ssc_freq ? 66 : 48;
-			else if (IS_GEN5(dev) || IS_GEN6(dev))
-				dev_priv->lvds_ssc_freq =
-					general->ssc_freq ? 100 : 120;
-			else
-				dev_priv->lvds_ssc_freq =
-					general->ssc_freq ? 100 : 96;
-		}
+		if (IS_I85X(dev))
+			dev_priv->lvds_ssc_freq = general->ssc_freq ? 66 : 48;
+		else if (IS_GEN5(dev) || IS_GEN6(dev))
+			dev_priv->lvds_ssc_freq = general->ssc_freq ? 100 : 120;
+		else
+			dev_priv->lvds_ssc_freq = general->ssc_freq ? 100 : 96;
 	}
 }
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/i915/intel_crt.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/i915/intel_crt.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/i915/intel_crt.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/i915/intel_crt.c	2011-03-14 21:20:32.000000000 -0400
@@ -30,6 +30,7 @@
 #include "drm.h"
 #include "drm_crtc.h"
 #include "drm_crtc_helper.h"
+#include "drm_edid.h"
 #include "intel_drv.h"
 #include "i915_drm.h"
 #include "i915_drv.h"
@@ -287,8 +288,9 @@ static bool intel_crt_ddc_probe(struct d
 	return i2c_transfer(&dev_priv->gmbus[ddc_bus].adapter, msgs, 1) == 1;
 }
 
-static bool intel_crt_detect_ddc(struct intel_crt *crt)
+static bool intel_crt_detect_ddc(struct drm_connector *connector)
 {
+	struct intel_crt *crt = intel_attached_crt(connector);
 	struct drm_i915_private *dev_priv = crt->base.base.dev->dev_private;
 
 	/* CRT should always be at 0, but check anyway */
@@ -301,8 +303,26 @@ static bool intel_crt_detect_ddc(struct
 	}
 
 	if (intel_ddc_probe(&crt->base, dev_priv->crt_ddc_pin)) {
-		DRM_DEBUG_KMS("CRT detected via DDC:0x50 [EDID]\n");
-		return true;
+		struct edid *edid;
+		bool is_digital = false;
+
+		edid = drm_get_edid(connector,
+			&dev_priv->gmbus[dev_priv->crt_ddc_pin].adapter);
+		/*
+		 * This may be a DVI-I connector with a shared DDC
+		 * link between analog and digital outputs, so we
+		 * have to check the EDID input spec of the attached device.
+		 */
+		if (edid != NULL) {
+			is_digital = edid->input & DRM_EDID_INPUT_DIGITAL;
+			connector->display_info.raw_edid = NULL;
+			kfree(edid);
+		}
+
+		if (!is_digital) {
+			DRM_DEBUG_KMS("CRT detected via DDC:0x50 [EDID]\n");
+			return true;
+		}
 	}
 
 	return false;
@@ -458,7 +478,7 @@ intel_crt_detect(struct drm_connector *c
 		}
 	}
 
-	if (intel_crt_detect_ddc(crt))
+	if (intel_crt_detect_ddc(connector))
 		return connector_status_connected;
 
 	if (!force)
@@ -472,7 +492,7 @@ intel_crt_detect(struct drm_connector *c
 		crtc = intel_get_load_detect_pipe(&crt->base, connector,
 						  NULL, &dpms_mode);
 		if (crtc) {
-			if (intel_crt_detect_ddc(crt))
+			if (intel_crt_detect_ddc(connector))
 				status = connector_status_connected;
 			else
 				status = intel_crt_load_detect(crtc, crt);
@@ -515,6 +535,15 @@ static int intel_crt_set_property(struct
 	return 0;
 }
 
+static void intel_crt_reset(struct drm_connector *connector)
+{
+	struct drm_device *dev = connector->dev;
+	struct intel_crt *crt = intel_attached_crt(connector);
+
+	if (HAS_PCH_SPLIT(dev))
+		crt->force_hotplug_required = 1;
+}
+
 /*
  * Routines for controlling stuff on the analog port
  */
@@ -528,6 +557,7 @@ static const struct drm_encoder_helper_f
 };
 
 static const struct drm_connector_funcs intel_crt_connector_funcs = {
+	.reset = intel_crt_reset,
 	.dpms = drm_helper_connector_dpms,
 	.detect = intel_crt_detect,
 	.fill_modes = drm_helper_probe_single_connector_modes,
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/i915/intel_display.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/i915/intel_display.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/i915/intel_display.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/i915/intel_display.c	2011-03-14 21:20:32.000000000 -0400
@@ -642,26 +642,23 @@ static const intel_limit_t intel_limits_
         .find_pll = intel_find_pll_ironlake_dp,
 };
 
-static const intel_limit_t *intel_ironlake_limit(struct drm_crtc *crtc)
+static const intel_limit_t *intel_ironlake_limit(struct drm_crtc *crtc,
+						int refclk)
 {
 	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	const intel_limit_t *limit;
-	int refclk = 120;
 
 	if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) {
-		if (dev_priv->lvds_use_ssc && dev_priv->lvds_ssc_freq == 100)
-			refclk = 100;
-
 		if ((I915_READ(PCH_LVDS) & LVDS_CLKB_POWER_MASK) ==
 		    LVDS_CLKB_POWER_UP) {
 			/* LVDS dual channel */
-			if (refclk == 100)
+			if (refclk == 100000)
 				limit = &intel_limits_ironlake_dual_lvds_100m;
 			else
 				limit = &intel_limits_ironlake_dual_lvds;
 		} else {
-			if (refclk == 100)
+			if (refclk == 100000)
 				limit = &intel_limits_ironlake_single_lvds_100m;
 			else
 				limit = &intel_limits_ironlake_single_lvds;
@@ -702,13 +699,13 @@ static const intel_limit_t *intel_g4x_li
 	return limit;
 }
 
-static const intel_limit_t *intel_limit(struct drm_crtc *crtc)
+static const intel_limit_t *intel_limit(struct drm_crtc *crtc, int refclk)
 {
 	struct drm_device *dev = crtc->dev;
 	const intel_limit_t *limit;
 
 	if (HAS_PCH_SPLIT(dev))
-		limit = intel_ironlake_limit(crtc);
+		limit = intel_ironlake_limit(crtc, refclk);
 	else if (IS_G4X(dev)) {
 		limit = intel_g4x_limit(crtc);
 	} else if (IS_PINEVIEW(dev)) {
@@ -773,11 +770,10 @@ bool intel_pipe_has_type(struct drm_crtc
  * the given connectors.
  */
 
-static bool intel_PLL_is_valid(struct drm_crtc *crtc, intel_clock_t *clock)
+static bool intel_PLL_is_valid(struct drm_device *dev,
+			       const intel_limit_t *limit,
+			       const intel_clock_t *clock)
 {
-	const intel_limit_t *limit = intel_limit (crtc);
-	struct drm_device *dev = crtc->dev;
-
 	if (clock->p1  < limit->p1.min  || limit->p1.max  < clock->p1)
 		INTELPllInvalid ("p1 out of range\n");
 	if (clock->p   < limit->p.min   || limit->p.max   < clock->p)
@@ -849,8 +845,8 @@ intel_find_best_PLL(const intel_limit_t
 					int this_err;
 
 					intel_clock(dev, refclk, &clock);
-
-					if (!intel_PLL_is_valid(crtc, &clock))
+					if (!intel_PLL_is_valid(dev, limit,
+								&clock))
 						continue;
 
 					this_err = abs(clock.dot - target);
@@ -912,9 +908,11 @@ intel_g4x_find_best_PLL(const intel_limi
 					int this_err;
 
 					intel_clock(dev, refclk, &clock);
-					if (!intel_PLL_is_valid(crtc, &clock))
+					if (!intel_PLL_is_valid(dev, limit,
+								&clock))
 						continue;
-					this_err = abs(clock.dot - target) ;
+
+					this_err = abs(clock.dot - target);
 					if (this_err < err_most) {
 						*best_clock = clock;
 						err_most = this_err;
@@ -1066,13 +1064,13 @@ static void i8xx_enable_fbc(struct drm_c
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct drm_framebuffer *fb = crtc->fb;
 	struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
-	struct drm_i915_gem_object *obj_priv = to_intel_bo(intel_fb->obj);
+	struct drm_i915_gem_object *obj = intel_fb->obj;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	int plane, i;
 	u32 fbc_ctl, fbc_ctl2;
 
 	if (fb->pitch == dev_priv->cfb_pitch &&
-	    obj_priv->fence_reg == dev_priv->cfb_fence &&
+	    obj->fence_reg == dev_priv->cfb_fence &&
 	    intel_crtc->plane == dev_priv->cfb_plane &&
 	    I915_READ(FBC_CONTROL) & FBC_CTL_EN)
 		return;
@@ -1086,7 +1084,7 @@ static void i8xx_enable_fbc(struct drm_c
 
 	/* FBC_CTL wants 64B units */
 	dev_priv->cfb_pitch = (dev_priv->cfb_pitch / 64) - 1;
-	dev_priv->cfb_fence = obj_priv->fence_reg;
+	dev_priv->cfb_fence = obj->fence_reg;
 	dev_priv->cfb_plane = intel_crtc->plane;
 	plane = dev_priv->cfb_plane == 0 ? FBC_CTL_PLANEA : FBC_CTL_PLANEB;
 
@@ -1096,7 +1094,7 @@ static void i8xx_enable_fbc(struct drm_c
 
 	/* Set it up... */
 	fbc_ctl2 = FBC_CTL_FENCE_DBL | FBC_CTL_IDLE_IMM | plane;
-	if (obj_priv->tiling_mode != I915_TILING_NONE)
+	if (obj->tiling_mode != I915_TILING_NONE)
 		fbc_ctl2 |= FBC_CTL_CPU_FENCE;
 	I915_WRITE(FBC_CONTROL2, fbc_ctl2);
 	I915_WRITE(FBC_FENCE_OFF, crtc->y);
@@ -1107,7 +1105,7 @@ static void i8xx_enable_fbc(struct drm_c
 		fbc_ctl |= FBC_CTL_C3_IDLE; /* 945 needs special SR handling */
 	fbc_ctl |= (dev_priv->cfb_pitch & 0xff) << FBC_CTL_STRIDE_SHIFT;
 	fbc_ctl |= (interval & 0x2fff) << FBC_CTL_INTERVAL_SHIFT;
-	if (obj_priv->tiling_mode != I915_TILING_NONE)
+	if (obj->tiling_mode != I915_TILING_NONE)
 		fbc_ctl |= dev_priv->cfb_fence;
 	I915_WRITE(FBC_CONTROL, fbc_ctl);
 
@@ -1150,7 +1148,7 @@ static void g4x_enable_fbc(struct drm_cr
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct drm_framebuffer *fb = crtc->fb;
 	struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
-	struct drm_i915_gem_object *obj_priv = to_intel_bo(intel_fb->obj);
+	struct drm_i915_gem_object *obj = intel_fb->obj;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	int plane = intel_crtc->plane == 0 ? DPFC_CTL_PLANEA : DPFC_CTL_PLANEB;
 	unsigned long stall_watermark = 200;
@@ -1159,7 +1157,7 @@ static void g4x_enable_fbc(struct drm_cr
 	dpfc_ctl = I915_READ(DPFC_CONTROL);
 	if (dpfc_ctl & DPFC_CTL_EN) {
 		if (dev_priv->cfb_pitch == dev_priv->cfb_pitch / 64 - 1 &&
-		    dev_priv->cfb_fence == obj_priv->fence_reg &&
+		    dev_priv->cfb_fence == obj->fence_reg &&
 		    dev_priv->cfb_plane == intel_crtc->plane &&
 		    dev_priv->cfb_y == crtc->y)
 			return;
@@ -1170,12 +1168,12 @@ static void g4x_enable_fbc(struct drm_cr
 	}
 
 	dev_priv->cfb_pitch = (dev_priv->cfb_pitch / 64) - 1;
-	dev_priv->cfb_fence = obj_priv->fence_reg;
+	dev_priv->cfb_fence = obj->fence_reg;
 	dev_priv->cfb_plane = intel_crtc->plane;
 	dev_priv->cfb_y = crtc->y;
 
 	dpfc_ctl = plane | DPFC_SR_EN | DPFC_CTL_LIMIT_1X;
-	if (obj_priv->tiling_mode != I915_TILING_NONE) {
+	if (obj->tiling_mode != I915_TILING_NONE) {
 		dpfc_ctl |= DPFC_CTL_FENCE_EN | dev_priv->cfb_fence;
 		I915_WRITE(DPFC_CHICKEN, DPFC_HT_MODIFY);
 	} else {
@@ -1215,13 +1213,33 @@ static bool g4x_fbc_enabled(struct drm_d
 	return I915_READ(DPFC_CONTROL) & DPFC_CTL_EN;
 }
 
+static void sandybridge_blit_fbc_update(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	u32 blt_ecoskpd;
+
+	/* Make sure blitter notifies FBC of writes */
+	__gen6_gt_force_wake_get(dev_priv);
+	blt_ecoskpd = I915_READ(GEN6_BLITTER_ECOSKPD);
+	blt_ecoskpd |= GEN6_BLITTER_FBC_NOTIFY <<
+		GEN6_BLITTER_LOCK_SHIFT;
+	I915_WRITE(GEN6_BLITTER_ECOSKPD, blt_ecoskpd);
+	blt_ecoskpd |= GEN6_BLITTER_FBC_NOTIFY;
+	I915_WRITE(GEN6_BLITTER_ECOSKPD, blt_ecoskpd);
+	blt_ecoskpd &= ~(GEN6_BLITTER_FBC_NOTIFY <<
+			 GEN6_BLITTER_LOCK_SHIFT);
+	I915_WRITE(GEN6_BLITTER_ECOSKPD, blt_ecoskpd);
+	POSTING_READ(GEN6_BLITTER_ECOSKPD);
+	__gen6_gt_force_wake_put(dev_priv);
+}
+
 static void ironlake_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
 {
 	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct drm_framebuffer *fb = crtc->fb;
 	struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
-	struct drm_i915_gem_object *obj_priv = to_intel_bo(intel_fb->obj);
+	struct drm_i915_gem_object *obj = intel_fb->obj;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	int plane = intel_crtc->plane == 0 ? DPFC_CTL_PLANEA : DPFC_CTL_PLANEB;
 	unsigned long stall_watermark = 200;
@@ -1230,9 +1248,9 @@ static void ironlake_enable_fbc(struct d
 	dpfc_ctl = I915_READ(ILK_DPFC_CONTROL);
 	if (dpfc_ctl & DPFC_CTL_EN) {
 		if (dev_priv->cfb_pitch == dev_priv->cfb_pitch / 64 - 1 &&
-		    dev_priv->cfb_fence == obj_priv->fence_reg &&
+		    dev_priv->cfb_fence == obj->fence_reg &&
 		    dev_priv->cfb_plane == intel_crtc->plane &&
-		    dev_priv->cfb_offset == obj_priv->gtt_offset &&
+		    dev_priv->cfb_offset == obj->gtt_offset &&
 		    dev_priv->cfb_y == crtc->y)
 			return;
 
@@ -1242,14 +1260,14 @@ static void ironlake_enable_fbc(struct d
 	}
 
 	dev_priv->cfb_pitch = (dev_priv->cfb_pitch / 64) - 1;
-	dev_priv->cfb_fence = obj_priv->fence_reg;
+	dev_priv->cfb_fence = obj->fence_reg;
 	dev_priv->cfb_plane = intel_crtc->plane;
-	dev_priv->cfb_offset = obj_priv->gtt_offset;
+	dev_priv->cfb_offset = obj->gtt_offset;
 	dev_priv->cfb_y = crtc->y;
 
 	dpfc_ctl &= DPFC_RESERVED;
 	dpfc_ctl |= (plane | DPFC_CTL_LIMIT_1X);
-	if (obj_priv->tiling_mode != I915_TILING_NONE) {
+	if (obj->tiling_mode != I915_TILING_NONE) {
 		dpfc_ctl |= (DPFC_CTL_FENCE_EN | dev_priv->cfb_fence);
 		I915_WRITE(ILK_DPFC_CHICKEN, DPFC_HT_MODIFY);
 	} else {
@@ -1260,10 +1278,17 @@ static void ironlake_enable_fbc(struct d
 		   (stall_watermark << DPFC_RECOMP_STALL_WM_SHIFT) |
 		   (interval << DPFC_RECOMP_TIMER_COUNT_SHIFT));
 	I915_WRITE(ILK_DPFC_FENCE_YOFF, crtc->y);
-	I915_WRITE(ILK_FBC_RT_BASE, obj_priv->gtt_offset | ILK_FBC_RT_VALID);
+	I915_WRITE(ILK_FBC_RT_BASE, obj->gtt_offset | ILK_FBC_RT_VALID);
 	/* enable it... */
 	I915_WRITE(ILK_DPFC_CONTROL, dpfc_ctl | DPFC_CTL_EN);
 
+	if (IS_GEN6(dev)) {
+		I915_WRITE(SNB_DPFC_CTL_SA,
+			   SNB_CPU_FENCE_ENABLE | dev_priv->cfb_fence);
+		I915_WRITE(DPFC_CPU_FENCE_OFFSET, crtc->y);
+		sandybridge_blit_fbc_update(dev);
+	}
+
 	DRM_DEBUG_KMS("enabled fbc on plane %d\n", intel_crtc->plane);
 }
 
@@ -1345,7 +1370,7 @@ static void intel_update_fbc(struct drm_
 	struct intel_crtc *intel_crtc;
 	struct drm_framebuffer *fb;
 	struct intel_framebuffer *intel_fb;
-	struct drm_i915_gem_object *obj_priv;
+	struct drm_i915_gem_object *obj;
 
 	DRM_DEBUG_KMS("\n");
 
@@ -1384,9 +1409,9 @@ static void intel_update_fbc(struct drm_
 	intel_crtc = to_intel_crtc(crtc);
 	fb = crtc->fb;
 	intel_fb = to_intel_framebuffer(fb);
-	obj_priv = to_intel_bo(intel_fb->obj);
+	obj = intel_fb->obj;
 
-	if (intel_fb->obj->size > dev_priv->cfb_size) {
+	if (intel_fb->obj->base.size > dev_priv->cfb_size) {
 		DRM_DEBUG_KMS("framebuffer too large, disabling "
 			      "compression\n");
 		dev_priv->no_fbc_reason = FBC_STOLEN_TOO_SMALL;
@@ -1410,7 +1435,7 @@ static void intel_update_fbc(struct drm_
 		dev_priv->no_fbc_reason = FBC_BAD_PLANE;
 		goto out_disable;
 	}
-	if (obj_priv->tiling_mode != I915_TILING_X) {
+	if (obj->tiling_mode != I915_TILING_X) {
 		DRM_DEBUG_KMS("framebuffer not tiled, disabling compression\n");
 		dev_priv->no_fbc_reason = FBC_NOT_TILED;
 		goto out_disable;
@@ -1433,14 +1458,13 @@ out_disable:
 
 int
 intel_pin_and_fence_fb_obj(struct drm_device *dev,
-			   struct drm_gem_object *obj,
-			   bool pipelined)
+			   struct drm_i915_gem_object *obj,
+			   struct intel_ring_buffer *pipelined)
 {
-	struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
 	u32 alignment;
 	int ret;
 
-	switch (obj_priv->tiling_mode) {
+	switch (obj->tiling_mode) {
 	case I915_TILING_NONE:
 		if (IS_BROADWATER(dev) || IS_CRESTLINE(dev))
 			alignment = 128 * 1024;
@@ -1461,7 +1485,7 @@ intel_pin_and_fence_fb_obj(struct drm_de
 		BUG();
 	}
 
-	ret = i915_gem_object_pin(obj, alignment);
+	ret = i915_gem_object_pin(obj, alignment, true);
 	if (ret)
 		return ret;
 
@@ -1474,9 +1498,8 @@ intel_pin_and_fence_fb_obj(struct drm_de
 	 * framebuffer compression.  For simplicity, we always install
 	 * a fence as the cost is not that onerous.
 	 */
-	if (obj_priv->fence_reg == I915_FENCE_REG_NONE &&
-	    obj_priv->tiling_mode != I915_TILING_NONE) {
-		ret = i915_gem_object_get_fence_reg(obj, false);
+	if (obj->tiling_mode != I915_TILING_NONE) {
+		ret = i915_gem_object_get_fence(obj, pipelined, false);
 		if (ret)
 			goto err_unpin;
 	}
@@ -1497,8 +1520,7 @@ intel_pipe_set_base_atomic(struct drm_cr
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	struct intel_framebuffer *intel_fb;
-	struct drm_i915_gem_object *obj_priv;
-	struct drm_gem_object *obj;
+	struct drm_i915_gem_object *obj;
 	int plane = intel_crtc->plane;
 	unsigned long Start, Offset;
 	u32 dspcntr;
@@ -1515,7 +1537,6 @@ intel_pipe_set_base_atomic(struct drm_cr
 
 	intel_fb = to_intel_framebuffer(fb);
 	obj = intel_fb->obj;
-	obj_priv = to_intel_bo(obj);
 
 	reg = DSPCNTR(plane);
 	dspcntr = I915_READ(reg);
@@ -1540,7 +1561,7 @@ intel_pipe_set_base_atomic(struct drm_cr
 		return -EINVAL;
 	}
 	if (INTEL_INFO(dev)->gen >= 4) {
-		if (obj_priv->tiling_mode != I915_TILING_NONE)
+		if (obj->tiling_mode != I915_TILING_NONE)
 			dspcntr |= DISPPLANE_TILED;
 		else
 			dspcntr &= ~DISPPLANE_TILED;
@@ -1552,7 +1573,7 @@ intel_pipe_set_base_atomic(struct drm_cr
 
 	I915_WRITE(reg, dspcntr);
 
-	Start = obj_priv->gtt_offset;
+	Start = obj->gtt_offset;
 	Offset = y * fb->pitch + x * (fb->bits_per_pixel / 8);
 
 	DRM_DEBUG_KMS("Writing base %08lX %08lX %d %d %d\n",
@@ -1598,7 +1619,7 @@ intel_pipe_set_base(struct drm_crtc *crt
 	mutex_lock(&dev->struct_mutex);
 	ret = intel_pin_and_fence_fb_obj(dev,
 					 to_intel_framebuffer(crtc->fb)->obj,
-					 false);
+					 NULL);
 	if (ret != 0) {
 		mutex_unlock(&dev->struct_mutex);
 		return ret;
@@ -1606,23 +1627,22 @@ intel_pipe_set_base(struct drm_crtc *crt
 
 	if (old_fb) {
 		struct drm_i915_private *dev_priv = dev->dev_private;
-		struct drm_gem_object *obj = to_intel_framebuffer(old_fb)->obj;
-		struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
+		struct drm_i915_gem_object *obj = to_intel_framebuffer(old_fb)->obj;
 
 		wait_event(dev_priv->pending_flip_queue,
-			   atomic_read(&obj_priv->pending_flip) == 0);
+			   atomic_read(&dev_priv->mm.wedged) ||
+			   atomic_read(&obj->pending_flip) == 0);
 
 		/* Big Hammer, we also need to ensure that any pending
 		 * MI_WAIT_FOR_EVENT inside a user batch buffer on the
 		 * current scanout is retired before unpinning the old
 		 * framebuffer.
+		 *
+		 * This should only fail upon a hung GPU, in which case we
+		 * can safely continue.
 		 */
-		ret = i915_gem_object_flush_gpu(obj_priv, false);
-		if (ret) {
-			i915_gem_object_unpin(to_intel_framebuffer(crtc->fb)->obj);
-			mutex_unlock(&dev->struct_mutex);
-			return ret;
-		}
+		ret = i915_gem_object_flush_gpu(obj, false);
+		(void) ret;
 	}
 
 	ret = intel_pipe_set_base_atomic(crtc, crtc->fb, x, y,
@@ -1633,8 +1653,10 @@ intel_pipe_set_base(struct drm_crtc *crt
 		return ret;
 	}
 
-	if (old_fb)
+	if (old_fb) {
+		intel_wait_for_vblank(dev, intel_crtc->pipe);
 		i915_gem_object_unpin(to_intel_framebuffer(old_fb)->obj);
+	}
 
 	mutex_unlock(&dev->struct_mutex);
 
@@ -1996,31 +2018,56 @@ static void intel_flush_display_plane(st
 static void intel_clear_scanline_wait(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_ring_buffer *ring;
 	u32 tmp;
 
 	if (IS_GEN2(dev))
 		/* Can't break the hang on i8xx */
 		return;
 
-	tmp = I915_READ(PRB0_CTL);
-	if (tmp & RING_WAIT) {
-		I915_WRITE(PRB0_CTL, tmp);
-		POSTING_READ(PRB0_CTL);
-	}
+	ring = LP_RING(dev_priv);
+	tmp = I915_READ_CTL(ring);
+	if (tmp & RING_WAIT)
+		I915_WRITE_CTL(ring, tmp);
 }
 
 static void intel_crtc_wait_for_pending_flips(struct drm_crtc *crtc)
 {
-	struct drm_i915_gem_object *obj_priv;
+	struct drm_i915_gem_object *obj;
 	struct drm_i915_private *dev_priv;
 
 	if (crtc->fb == NULL)
 		return;
 
-	obj_priv = to_intel_bo(to_intel_framebuffer(crtc->fb)->obj);
+	obj = to_intel_framebuffer(crtc->fb)->obj;
 	dev_priv = crtc->dev->dev_private;
 	wait_event(dev_priv->pending_flip_queue,
-		   atomic_read(&obj_priv->pending_flip) == 0);
+		   atomic_read(&obj->pending_flip) == 0);
+}
+
+static bool intel_crtc_driving_pch(struct drm_crtc *crtc)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_mode_config *mode_config = &dev->mode_config;
+	struct intel_encoder *encoder;
+
+	/*
+	 * If there's a non-PCH eDP on this crtc, it must be DP_A, and that
+	 * must be driven by its own crtc; no sharing is possible.
+	 */
+	list_for_each_entry(encoder, &mode_config->encoder_list, base.head) {
+		if (encoder->base.crtc != crtc)
+			continue;
+
+		switch (encoder->type) {
+		case INTEL_OUTPUT_EDP:
+			if (!intel_encoder_is_pch_edp(&encoder->base))
+				return false;
+			continue;
+		}
+	}
+
+	return true;
 }
 
 static void ironlake_crtc_enable(struct drm_crtc *crtc)
@@ -2031,6 +2078,7 @@ static void ironlake_crtc_enable(struct
 	int pipe = intel_crtc->pipe;
 	int plane = intel_crtc->plane;
 	u32 reg, temp;
+	bool is_pch_port = false;
 
 	if (intel_crtc->active)
 		return;
@@ -2044,7 +2092,56 @@ static void ironlake_crtc_enable(struct
 			I915_WRITE(PCH_LVDS, temp | LVDS_PORT_EN);
 	}
 
-	ironlake_fdi_enable(crtc);
+	is_pch_port = intel_crtc_driving_pch(crtc);
+
+	if (is_pch_port)
+		ironlake_fdi_enable(crtc);
+	else {
+		/* disable CPU FDI tx and PCH FDI rx */
+		reg = FDI_TX_CTL(pipe);
+		temp = I915_READ(reg);
+		I915_WRITE(reg, temp & ~FDI_TX_ENABLE);
+		POSTING_READ(reg);
+
+		reg = FDI_RX_CTL(pipe);
+		temp = I915_READ(reg);
+		temp &= ~(0x7 << 16);
+		temp |= (I915_READ(PIPECONF(pipe)) & PIPE_BPC_MASK) << 11;
+		I915_WRITE(reg, temp & ~FDI_RX_ENABLE);
+
+		POSTING_READ(reg);
+		udelay(100);
+
+		/* Ironlake workaround, disable clock pointer after downing FDI */
+		if (HAS_PCH_IBX(dev))
+			I915_WRITE(FDI_RX_CHICKEN(pipe),
+				   I915_READ(FDI_RX_CHICKEN(pipe) &
+					     ~FDI_RX_PHASE_SYNC_POINTER_ENABLE));
+
+		/* still set train pattern 1 */
+		reg = FDI_TX_CTL(pipe);
+		temp = I915_READ(reg);
+		temp &= ~FDI_LINK_TRAIN_NONE;
+		temp |= FDI_LINK_TRAIN_PATTERN_1;
+		I915_WRITE(reg, temp);
+
+		reg = FDI_RX_CTL(pipe);
+		temp = I915_READ(reg);
+		if (HAS_PCH_CPT(dev)) {
+			temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT;
+			temp |= FDI_LINK_TRAIN_PATTERN_1_CPT;
+		} else {
+			temp &= ~FDI_LINK_TRAIN_NONE;
+			temp |= FDI_LINK_TRAIN_PATTERN_1;
+		}
+		/* BPC in FDI rx is consistent with that in PIPECONF */
+		temp &= ~(0x07 << 16);
+		temp |= (I915_READ(PIPECONF(pipe)) & PIPE_BPC_MASK) << 11;
+		I915_WRITE(reg, temp);
+
+		POSTING_READ(reg);
+		udelay(100);
+	}
 
 	/* Enable panel fitting for LVDS */
 	if (dev_priv->pch_pf_size &&
@@ -2078,6 +2175,10 @@ static void ironlake_crtc_enable(struct
 		intel_flush_display_plane(dev, plane);
 	}
 
+	/* Skip the PCH stuff if possible */
+	if (!is_pch_port)
+		goto done;
+
 	/* For PCH output, training FDI link */
 	if (IS_GEN6(dev))
 		gen6_fdi_link_train(crtc);
@@ -2162,7 +2263,7 @@ static void ironlake_crtc_enable(struct
 	I915_WRITE(reg, temp | TRANS_ENABLE);
 	if (wait_for(I915_READ(reg) & TRANS_STATE_ENABLE, 100))
 		DRM_ERROR("failed to enable transcoder %d\n", pipe);
-
+done:
 	intel_crtc_load_lut(crtc);
 	intel_update_fbc(dev);
 	intel_crtc_update_cursor(crtc, true);
@@ -2850,6 +2951,39 @@ static struct intel_watermark_params iro
 	ILK_FIFO_LINE_SIZE
 };
 
+static struct intel_watermark_params sandybridge_display_wm_info = {
+	SNB_DISPLAY_FIFO,
+	SNB_DISPLAY_MAXWM,
+	SNB_DISPLAY_DFTWM,
+	2,
+	SNB_FIFO_LINE_SIZE
+};
+
+static struct intel_watermark_params sandybridge_cursor_wm_info = {
+	SNB_CURSOR_FIFO,
+	SNB_CURSOR_MAXWM,
+	SNB_CURSOR_DFTWM,
+	2,
+	SNB_FIFO_LINE_SIZE
+};
+
+static struct intel_watermark_params sandybridge_display_srwm_info = {
+	SNB_DISPLAY_SR_FIFO,
+	SNB_DISPLAY_MAX_SRWM,
+	SNB_DISPLAY_DFT_SRWM,
+	2,
+	SNB_FIFO_LINE_SIZE
+};
+
+static struct intel_watermark_params sandybridge_cursor_srwm_info = {
+	SNB_CURSOR_SR_FIFO,
+	SNB_CURSOR_MAX_SRWM,
+	SNB_CURSOR_DFT_SRWM,
+	2,
+	SNB_FIFO_LINE_SIZE
+};
+
+
 /**
  * intel_calculate_wm - calculate watermark level
  * @clock_in_khz: pixel clock
@@ -3383,12 +3517,17 @@ static void i830_update_wm(struct drm_de
 
 static bool ironlake_compute_wm0(struct drm_device *dev,
 				 int pipe,
+				 const struct intel_watermark_params *display,
+				 int display_latency_ns,
+				 const struct intel_watermark_params *cursor,
+				 int cursor_latency_ns,
 				 int *plane_wm,
 				 int *cursor_wm)
 {
 	struct drm_crtc *crtc;
-	int htotal, hdisplay, clock, pixel_size = 0;
-	int line_time_us, line_count, entries;
+	int htotal, hdisplay, clock, pixel_size;
+	int line_time_us, line_count;
+	int entries, tlb_miss;
 
 	crtc = intel_get_crtc_for_pipe(dev, pipe);
 	if (crtc->fb == NULL || !crtc->enabled)
@@ -3400,37 +3539,141 @@ static bool ironlake_compute_wm0(struct
 	pixel_size = crtc->fb->bits_per_pixel / 8;
 
 	/* Use the small buffer method to calculate plane watermark */
-	entries = ((clock * pixel_size / 1000) * ILK_LP0_PLANE_LATENCY) / 1000;
-	entries = DIV_ROUND_UP(entries,
-			       ironlake_display_wm_info.cacheline_size);
-	*plane_wm = entries + ironlake_display_wm_info.guard_size;
-	if (*plane_wm > (int)ironlake_display_wm_info.max_wm)
-		*plane_wm = ironlake_display_wm_info.max_wm;
+	entries = ((clock * pixel_size / 1000) * display_latency_ns) / 1000;
+	tlb_miss = display->fifo_size*display->cacheline_size - hdisplay * 8;
+	if (tlb_miss > 0)
+		entries += tlb_miss;
+	entries = DIV_ROUND_UP(entries, display->cacheline_size);
+	*plane_wm = entries + display->guard_size;
+	if (*plane_wm > (int)display->max_wm)
+		*plane_wm = display->max_wm;
 
 	/* Use the large buffer method to calculate cursor watermark */
 	line_time_us = ((htotal * 1000) / clock);
-	line_count = (ILK_LP0_CURSOR_LATENCY / line_time_us + 1000) / 1000;
+	line_count = (cursor_latency_ns / line_time_us + 1000) / 1000;
 	entries = line_count * 64 * pixel_size;
-	entries = DIV_ROUND_UP(entries,
-			       ironlake_cursor_wm_info.cacheline_size);
-	*cursor_wm = entries + ironlake_cursor_wm_info.guard_size;
-	if (*cursor_wm > ironlake_cursor_wm_info.max_wm)
-		*cursor_wm = ironlake_cursor_wm_info.max_wm;
+	tlb_miss = cursor->fifo_size*cursor->cacheline_size - hdisplay * 8;
+	if (tlb_miss > 0)
+		entries += tlb_miss;
+	entries = DIV_ROUND_UP(entries, cursor->cacheline_size);
+	*cursor_wm = entries + cursor->guard_size;
+	if (*cursor_wm > (int)cursor->max_wm)
+		*cursor_wm = (int)cursor->max_wm;
+
+	return true;
+}
+
+/*
+ * Check the wm result.
+ *
+ * If any calculated watermark values is larger than the maximum value that
+ * can be programmed into the associated watermark register, that watermark
+ * must be disabled.
+ */
+static bool ironlake_check_srwm(struct drm_device *dev, int level,
+				int fbc_wm, int display_wm, int cursor_wm,
+				const struct intel_watermark_params *display,
+				const struct intel_watermark_params *cursor)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	DRM_DEBUG_KMS("watermark %d: display plane %d, fbc lines %d,"
+		      " cursor %d\n", level, display_wm, fbc_wm, cursor_wm);
+
+	if (fbc_wm > SNB_FBC_MAX_SRWM) {
+		DRM_DEBUG_KMS("fbc watermark(%d) is too large(%d), disabling wm%d+\n",
+			      fbc_wm, SNB_FBC_MAX_SRWM, level);
+
+		/* fbc has it's own way to disable FBC WM */
+		I915_WRITE(DISP_ARB_CTL,
+			   I915_READ(DISP_ARB_CTL) | DISP_FBC_WM_DIS);
+		return false;
+	}
+
+	if (display_wm > display->max_wm) {
+		DRM_DEBUG_KMS("display watermark(%d) is too large(%d), disabling wm%d+\n",
+			      display_wm, SNB_DISPLAY_MAX_SRWM, level);
+		return false;
+	}
+
+	if (cursor_wm > cursor->max_wm) {
+		DRM_DEBUG_KMS("cursor watermark(%d) is too large(%d), disabling wm%d+\n",
+			      cursor_wm, SNB_CURSOR_MAX_SRWM, level);
+		return false;
+	}
+
+	if (!(fbc_wm || display_wm || cursor_wm)) {
+		DRM_DEBUG_KMS("latency %d is 0, disabling wm%d+\n", level, level);
+		return false;
+	}
 
 	return true;
 }
 
+/*
+ * Compute watermark values of WM[1-3],
+ */
+static bool ironlake_compute_srwm(struct drm_device *dev, int level,
+				  int hdisplay, int htotal,
+				  int pixel_size, int clock, int latency_ns,
+				  const struct intel_watermark_params *display,
+				  const struct intel_watermark_params *cursor,
+				  int *fbc_wm, int *display_wm, int *cursor_wm)
+{
+
+	unsigned long line_time_us;
+	int line_count, line_size;
+	int small, large;
+	int entries;
+
+	if (!latency_ns) {
+		*fbc_wm = *display_wm = *cursor_wm = 0;
+		return false;
+	}
+
+	line_time_us = (htotal * 1000) / clock;
+	line_count = (latency_ns / line_time_us + 1000) / 1000;
+	line_size = hdisplay * pixel_size;
+
+	/* Use the minimum of the small and large buffer method for primary */
+	small = ((clock * pixel_size / 1000) * latency_ns) / 1000;
+	large = line_count * line_size;
+
+	entries = DIV_ROUND_UP(min(small, large), display->cacheline_size);
+	*display_wm = entries + display->guard_size;
+
+	/*
+	 * Spec says:
+	 * FBC WM = ((Final Primary WM * 64) / number of bytes per line) + 2
+	 */
+	*fbc_wm = DIV_ROUND_UP(*display_wm * 64, line_size) + 2;
+
+	/* calculate the self-refresh watermark for display cursor */
+	entries = line_count * pixel_size * 64;
+	entries = DIV_ROUND_UP(entries, cursor->cacheline_size);
+	*cursor_wm = entries + cursor->guard_size;
+
+	return ironlake_check_srwm(dev, level,
+				   *fbc_wm, *display_wm, *cursor_wm,
+				   display, cursor);
+}
+
 static void ironlake_update_wm(struct drm_device *dev,
 			       int planea_clock, int planeb_clock,
-			       int sr_hdisplay, int sr_htotal,
+			       int hdisplay, int htotal,
 			       int pixel_size)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	int plane_wm, cursor_wm, enabled;
-	int tmp;
+	int fbc_wm, plane_wm, cursor_wm, enabled;
+	int clock;
 
 	enabled = 0;
-	if (ironlake_compute_wm0(dev, 0, &plane_wm, &cursor_wm)) {
+	if (ironlake_compute_wm0(dev, 0,
+				 &ironlake_display_wm_info,
+				 ILK_LP0_PLANE_LATENCY,
+				 &ironlake_cursor_wm_info,
+				 ILK_LP0_CURSOR_LATENCY,
+				 &plane_wm, &cursor_wm)) {
 		I915_WRITE(WM0_PIPEA_ILK,
 			   (plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm);
 		DRM_DEBUG_KMS("FIFO watermarks For pipe A -"
@@ -3439,7 +3682,12 @@ static void ironlake_update_wm(struct dr
 		enabled++;
 	}
 
-	if (ironlake_compute_wm0(dev, 1, &plane_wm, &cursor_wm)) {
+	if (ironlake_compute_wm0(dev, 1,
+				 &ironlake_display_wm_info,
+				 ILK_LP0_PLANE_LATENCY,
+				 &ironlake_cursor_wm_info,
+				 ILK_LP0_CURSOR_LATENCY,
+				 &plane_wm, &cursor_wm)) {
 		I915_WRITE(WM0_PIPEB_ILK,
 			   (plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm);
 		DRM_DEBUG_KMS("FIFO watermarks For pipe B -"
@@ -3452,57 +3700,151 @@ static void ironlake_update_wm(struct dr
 	 * Calculate and update the self-refresh watermark only when one
 	 * display plane is used.
 	 */
-	tmp = 0;
-	if (enabled == 1 && /* XXX disabled due to buggy implmentation? */ 0) {
-		unsigned long line_time_us;
-		int small, large, plane_fbc;
-		int sr_clock, entries;
-		int line_count, line_size;
-		/* Read the self-refresh latency. The unit is 0.5us */
-		int ilk_sr_latency = I915_READ(MLTR_ILK) & ILK_SRLT_MASK;
+	I915_WRITE(WM3_LP_ILK, 0);
+	I915_WRITE(WM2_LP_ILK, 0);
+	I915_WRITE(WM1_LP_ILK, 0);
 
-		sr_clock = planea_clock ? planea_clock : planeb_clock;
-		line_time_us = (sr_htotal * 1000) / sr_clock;
+	if (enabled != 1)
+		return;
 
-		/* Use ns/us then divide to preserve precision */
-		line_count = ((ilk_sr_latency * 500) / line_time_us + 1000)
-			/ 1000;
-		line_size = sr_hdisplay * pixel_size;
+	clock = planea_clock ? planea_clock : planeb_clock;
 
-		/* Use the minimum of the small and large buffer method for primary */
-		small = ((sr_clock * pixel_size / 1000) * (ilk_sr_latency * 500)) / 1000;
-		large = line_count * line_size;
+	/* WM1 */
+	if (!ironlake_compute_srwm(dev, 1, hdisplay, htotal, pixel_size,
+				   clock, ILK_READ_WM1_LATENCY() * 500,
+				   &ironlake_display_srwm_info,
+				   &ironlake_cursor_srwm_info,
+				   &fbc_wm, &plane_wm, &cursor_wm))
+		return;
 
-		entries = DIV_ROUND_UP(min(small, large),
-				       ironlake_display_srwm_info.cacheline_size);
+	I915_WRITE(WM1_LP_ILK,
+		   WM1_LP_SR_EN |
+		   (ILK_READ_WM1_LATENCY() << WM1_LP_LATENCY_SHIFT) |
+		   (fbc_wm << WM1_LP_FBC_SHIFT) |
+		   (plane_wm << WM1_LP_SR_SHIFT) |
+		   cursor_wm);
 
-		plane_fbc = entries * 64;
-		plane_fbc = DIV_ROUND_UP(plane_fbc, line_size);
+	/* WM2 */
+	if (!ironlake_compute_srwm(dev, 2, hdisplay, htotal, pixel_size,
+				   clock, ILK_READ_WM2_LATENCY() * 500,
+				   &ironlake_display_srwm_info,
+				   &ironlake_cursor_srwm_info,
+				   &fbc_wm, &plane_wm, &cursor_wm))
+		return;
 
-		plane_wm = entries + ironlake_display_srwm_info.guard_size;
-		if (plane_wm > (int)ironlake_display_srwm_info.max_wm)
-			plane_wm = ironlake_display_srwm_info.max_wm;
+	I915_WRITE(WM2_LP_ILK,
+		   WM2_LP_EN |
+		   (ILK_READ_WM2_LATENCY() << WM1_LP_LATENCY_SHIFT) |
+		   (fbc_wm << WM1_LP_FBC_SHIFT) |
+		   (plane_wm << WM1_LP_SR_SHIFT) |
+		   cursor_wm);
 
-		/* calculate the self-refresh watermark for display cursor */
-		entries = line_count * pixel_size * 64;
-		entries = DIV_ROUND_UP(entries,
-				       ironlake_cursor_srwm_info.cacheline_size);
+	/*
+	 * WM3 is unsupported on ILK, probably because we don't have latency
+	 * data for that power state
+	 */
+}
 
-		cursor_wm = entries + ironlake_cursor_srwm_info.guard_size;
-		if (cursor_wm > (int)ironlake_cursor_srwm_info.max_wm)
-			cursor_wm = ironlake_cursor_srwm_info.max_wm;
+static void sandybridge_update_wm(struct drm_device *dev,
+			       int planea_clock, int planeb_clock,
+			       int hdisplay, int htotal,
+			       int pixel_size)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	int latency = SNB_READ_WM0_LATENCY() * 100;	/* In unit 0.1us */
+	int fbc_wm, plane_wm, cursor_wm, enabled;
+	int clock;
 
-		/* configure watermark and enable self-refresh */
-		tmp = (WM1_LP_SR_EN |
-		       (ilk_sr_latency << WM1_LP_LATENCY_SHIFT) |
-		       (plane_fbc << WM1_LP_FBC_SHIFT) |
-		       (plane_wm << WM1_LP_SR_SHIFT) |
-		       cursor_wm);
-		DRM_DEBUG_KMS("self-refresh watermark: display plane %d, fbc lines %d,"
-			      " cursor %d\n", plane_wm, plane_fbc, cursor_wm);
+	enabled = 0;
+	if (ironlake_compute_wm0(dev, 0,
+				 &sandybridge_display_wm_info, latency,
+				 &sandybridge_cursor_wm_info, latency,
+				 &plane_wm, &cursor_wm)) {
+		I915_WRITE(WM0_PIPEA_ILK,
+			   (plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm);
+		DRM_DEBUG_KMS("FIFO watermarks For pipe A -"
+			      " plane %d, " "cursor: %d\n",
+			      plane_wm, cursor_wm);
+		enabled++;
 	}
-	I915_WRITE(WM1_LP_ILK, tmp);
-	/* XXX setup WM2 and WM3 */
+
+	if (ironlake_compute_wm0(dev, 1,
+				 &sandybridge_display_wm_info, latency,
+				 &sandybridge_cursor_wm_info, latency,
+				 &plane_wm, &cursor_wm)) {
+		I915_WRITE(WM0_PIPEB_ILK,
+			   (plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm);
+		DRM_DEBUG_KMS("FIFO watermarks For pipe B -"
+			      " plane %d, cursor: %d\n",
+			      plane_wm, cursor_wm);
+		enabled++;
+	}
+
+	/*
+	 * Calculate and update the self-refresh watermark only when one
+	 * display plane is used.
+	 *
+	 * SNB support 3 levels of watermark.
+	 *
+	 * WM1/WM2/WM2 watermarks have to be enabled in the ascending order,
+	 * and disabled in the descending order
+	 *
+	 */
+	I915_WRITE(WM3_LP_ILK, 0);
+	I915_WRITE(WM2_LP_ILK, 0);
+	I915_WRITE(WM1_LP_ILK, 0);
+
+	if (enabled != 1)
+		return;
+
+	clock = planea_clock ? planea_clock : planeb_clock;
+
+	/* WM1 */
+	if (!ironlake_compute_srwm(dev, 1, hdisplay, htotal, pixel_size,
+				   clock, SNB_READ_WM1_LATENCY() * 500,
+				   &sandybridge_display_srwm_info,
+				   &sandybridge_cursor_srwm_info,
+				   &fbc_wm, &plane_wm, &cursor_wm))
+		return;
+
+	I915_WRITE(WM1_LP_ILK,
+		   WM1_LP_SR_EN |
+		   (SNB_READ_WM1_LATENCY() << WM1_LP_LATENCY_SHIFT) |
+		   (fbc_wm << WM1_LP_FBC_SHIFT) |
+		   (plane_wm << WM1_LP_SR_SHIFT) |
+		   cursor_wm);
+
+	/* WM2 */
+	if (!ironlake_compute_srwm(dev, 2,
+				   hdisplay, htotal, pixel_size,
+				   clock, SNB_READ_WM2_LATENCY() * 500,
+				   &sandybridge_display_srwm_info,
+				   &sandybridge_cursor_srwm_info,
+				   &fbc_wm, &plane_wm, &cursor_wm))
+		return;
+
+	I915_WRITE(WM2_LP_ILK,
+		   WM2_LP_EN |
+		   (SNB_READ_WM2_LATENCY() << WM1_LP_LATENCY_SHIFT) |
+		   (fbc_wm << WM1_LP_FBC_SHIFT) |
+		   (plane_wm << WM1_LP_SR_SHIFT) |
+		   cursor_wm);
+
+	/* WM3 */
+	if (!ironlake_compute_srwm(dev, 3,
+				   hdisplay, htotal, pixel_size,
+				   clock, SNB_READ_WM3_LATENCY() * 500,
+				   &sandybridge_display_srwm_info,
+				   &sandybridge_cursor_srwm_info,
+				   &fbc_wm, &plane_wm, &cursor_wm))
+		return;
+
+	I915_WRITE(WM3_LP_ILK,
+		   WM3_LP_EN |
+		   (SNB_READ_WM3_LATENCY() << WM1_LP_LATENCY_SHIFT) |
+		   (fbc_wm << WM1_LP_FBC_SHIFT) |
+		   (plane_wm << WM1_LP_SR_SHIFT) |
+		   cursor_wm);
 }
 
 /**
@@ -3580,6 +3922,11 @@ static void intel_update_watermarks(stru
 				    sr_hdisplay, sr_htotal, pixel_size);
 }
 
+static inline bool intel_panel_use_ssc(struct drm_i915_private *dev_priv)
+{
+	return dev_priv->lvds_use_ssc && i915_panel_use_ssc;
+}
+
 static int intel_crtc_mode_set(struct drm_crtc *crtc,
 			       struct drm_display_mode *mode,
 			       struct drm_display_mode *adjusted_mode,
@@ -3642,7 +3989,7 @@ static int intel_crtc_mode_set(struct dr
 		num_connectors++;
 	}
 
-	if (is_lvds && dev_priv->lvds_use_ssc && num_connectors < 2) {
+	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);
@@ -3660,7 +4007,7 @@ static int intel_crtc_mode_set(struct dr
 	 * refclk, or FALSE.  The returned values represent the clock equation:
 	 * reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2.
 	 */
-	limit = intel_limit(crtc);
+	limit = intel_limit(crtc, refclk);
 	ok = limit->find_pll(limit, crtc, adjusted_mode->clock, refclk, &clock);
 	if (!ok) {
 		DRM_ERROR("Couldn't find PLL settings for mode!\n");
@@ -3714,7 +4061,7 @@ static int intel_crtc_mode_set(struct dr
 		int lane = 0, link_bw, bpp;
 		/* CPU eDP doesn't require FDI link, so just set DP M/N
 		   according to current link config */
-		if (has_edp_encoder && !intel_encoder_is_pch_edp(&encoder->base)) {
+		if (has_edp_encoder && !intel_encoder_is_pch_edp(&has_edp_encoder->base)) {
 			target_clock = mode->clock;
 			intel_edp_link_config(has_edp_encoder,
 					      &lane, &link_bw);
@@ -3817,7 +4164,7 @@ static int intel_crtc_mode_set(struct dr
 		udelay(200);
 
 		if (has_edp_encoder) {
-			if (dev_priv->lvds_use_ssc) {
+			if (intel_panel_use_ssc(dev_priv)) {
 				temp |= DREF_SSC1_ENABLE;
 				I915_WRITE(PCH_DREF_CONTROL, temp);
 
@@ -3828,13 +4175,13 @@ static int intel_crtc_mode_set(struct dr
 
 			/* Enable CPU source on CPU attached eDP */
 			if (!intel_encoder_is_pch_edp(&has_edp_encoder->base)) {
-				if (dev_priv->lvds_use_ssc)
+				if (intel_panel_use_ssc(dev_priv))
 					temp |= DREF_CPU_SOURCE_OUTPUT_DOWNSPREAD;
 				else
 					temp |= DREF_CPU_SOURCE_OUTPUT_NONSPREAD;
 			} else {
 				/* Enable SSC on PCH eDP if needed */
-				if (dev_priv->lvds_use_ssc) {
+				if (intel_panel_use_ssc(dev_priv)) {
 					DRM_ERROR("enabling SSC on PCH\n");
 					temp |= DREF_SUPERSPREAD_SOURCE_ENABLE;
 				}
@@ -3857,6 +4204,22 @@ static int intel_crtc_mode_set(struct dr
 				reduced_clock.m2;
 	}
 
+	/* Enable autotuning of the PLL clock (if permissible) */
+	if (HAS_PCH_SPLIT(dev)) {
+		int factor = 21;
+
+		if (is_lvds) {
+			if ((intel_panel_use_ssc(dev_priv) &&
+			     dev_priv->lvds_ssc_freq == 100) ||
+			    (I915_READ(PCH_LVDS) & LVDS_CLKB_POWER_MASK) == LVDS_CLKB_POWER_UP)
+				factor = 25;
+		} else if (is_sdvo && is_tv)
+			factor = 20;
+
+		if (clock.m1 < factor * clock.n)
+			fp |= FP_CB_TUNE;
+	}
+
 	dpll = 0;
 	if (!HAS_PCH_SPLIT(dev))
 		dpll = DPLL_VGA_MODE_DIS;
@@ -3925,7 +4288,7 @@ static int intel_crtc_mode_set(struct dr
 		/* XXX: just matching BIOS for now */
 		/*	dpll |= PLL_REF_INPUT_TVCLKINBC; */
 		dpll |= 3;
-	else if (is_lvds && dev_priv->lvds_use_ssc && num_connectors < 2)
+	else if (is_lvds && intel_panel_use_ssc(dev_priv) && num_connectors < 2)
 		dpll |= PLLB_REF_INPUT_SPREADSPECTRUMIN;
 	else
 		dpll |= PLL_REF_INPUT_DREFCLK;
@@ -4071,7 +4434,6 @@ static int intel_crtc_mode_set(struct dr
 	}
 
 	if (!has_edp_encoder || intel_encoder_is_pch_edp(&has_edp_encoder->base)) {
-		I915_WRITE(fp_reg, fp);
 		I915_WRITE(dpll_reg, dpll);
 
 		/* Wait for the clocks to stabilize. */
@@ -4089,13 +4451,13 @@ static int intel_crtc_mode_set(struct dr
 			}
 			I915_WRITE(DPLL_MD(pipe), temp);
 		} else {
-			/* write it again -- the BIOS does, after all */
+			/* The pixel multiplier can only be updated once the
+			 * DPLL is enabled and the clocks are stable.
+			 *
+			 * So write it again.
+			 */
 			I915_WRITE(dpll_reg, dpll);
 		}
-
-		/* Wait for the clocks to stabilize. */
-		POSTING_READ(dpll_reg);
-		udelay(150);
 	}
 
 	intel_crtc->lowfreq_avail = false;
@@ -4331,15 +4693,14 @@ static void intel_crtc_update_cursor(str
 }
 
 static int intel_crtc_cursor_set(struct drm_crtc *crtc,
-				 struct drm_file *file_priv,
+				 struct drm_file *file,
 				 uint32_t handle,
 				 uint32_t width, uint32_t height)
 {
 	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-	struct drm_gem_object *bo;
-	struct drm_i915_gem_object *obj_priv;
+	struct drm_i915_gem_object *obj;
 	uint32_t addr;
 	int ret;
 
@@ -4349,7 +4710,7 @@ static int intel_crtc_cursor_set(struct
 	if (!handle) {
 		DRM_DEBUG_KMS("cursor off\n");
 		addr = 0;
-		bo = NULL;
+		obj = NULL;
 		mutex_lock(&dev->struct_mutex);
 		goto finish;
 	}
@@ -4360,13 +4721,11 @@ static int intel_crtc_cursor_set(struct
 		return -EINVAL;
 	}
 
-	bo = drm_gem_object_lookup(dev, file_priv, handle);
-	if (!bo)
+	obj = to_intel_bo(drm_gem_object_lookup(dev, file, handle));
+	if (!obj)
 		return -ENOENT;
 
-	obj_priv = to_intel_bo(bo);
-
-	if (bo->size < width * height * 4) {
+	if (obj->base.size < width * height * 4) {
 		DRM_ERROR("buffer is to small\n");
 		ret = -ENOMEM;
 		goto fail;
@@ -4375,29 +4734,41 @@ static int intel_crtc_cursor_set(struct
 	/* we only need to pin inside GTT if cursor is non-phy */
 	mutex_lock(&dev->struct_mutex);
 	if (!dev_priv->info->cursor_needs_physical) {
-		ret = i915_gem_object_pin(bo, PAGE_SIZE);
+		if (obj->tiling_mode) {
+			DRM_ERROR("cursor cannot be tiled\n");
+			ret = -EINVAL;
+			goto fail_locked;
+		}
+
+		ret = i915_gem_object_pin(obj, PAGE_SIZE, true);
 		if (ret) {
 			DRM_ERROR("failed to pin cursor bo\n");
 			goto fail_locked;
 		}
 
-		ret = i915_gem_object_set_to_gtt_domain(bo, 0);
+		ret = i915_gem_object_set_to_gtt_domain(obj, 0);
 		if (ret) {
 			DRM_ERROR("failed to move cursor bo into the GTT\n");
 			goto fail_unpin;
 		}
 
-		addr = obj_priv->gtt_offset;
+		ret = i915_gem_object_put_fence(obj);
+		if (ret) {
+			DRM_ERROR("failed to move cursor bo into the GTT\n");
+			goto fail_unpin;
+		}
+
+		addr = obj->gtt_offset;
 	} else {
 		int align = IS_I830(dev) ? 16 * 1024 : 256;
-		ret = i915_gem_attach_phys_object(dev, bo,
+		ret = i915_gem_attach_phys_object(dev, obj,
 						  (intel_crtc->pipe == 0) ? I915_GEM_PHYS_CURSOR_0 : I915_GEM_PHYS_CURSOR_1,
 						  align);
 		if (ret) {
 			DRM_ERROR("failed to attach phys object\n");
 			goto fail_locked;
 		}
-		addr = obj_priv->phys_obj->handle->busaddr;
+		addr = obj->phys_obj->handle->busaddr;
 	}
 
 	if (IS_GEN2(dev))
@@ -4406,17 +4777,17 @@ static int intel_crtc_cursor_set(struct
  finish:
 	if (intel_crtc->cursor_bo) {
 		if (dev_priv->info->cursor_needs_physical) {
-			if (intel_crtc->cursor_bo != bo)
+			if (intel_crtc->cursor_bo != obj)
 				i915_gem_detach_phys_object(dev, intel_crtc->cursor_bo);
 		} else
 			i915_gem_object_unpin(intel_crtc->cursor_bo);
-		drm_gem_object_unreference(intel_crtc->cursor_bo);
+		drm_gem_object_unreference(&intel_crtc->cursor_bo->base);
 	}
 
 	mutex_unlock(&dev->struct_mutex);
 
 	intel_crtc->cursor_addr = addr;
-	intel_crtc->cursor_bo = bo;
+	intel_crtc->cursor_bo = obj;
 	intel_crtc->cursor_width = width;
 	intel_crtc->cursor_height = height;
 
@@ -4424,11 +4795,11 @@ static int intel_crtc_cursor_set(struct
 
 	return 0;
 fail_unpin:
-	i915_gem_object_unpin(bo);
+	i915_gem_object_unpin(obj);
 fail_locked:
 	mutex_unlock(&dev->struct_mutex);
 fail:
-	drm_gem_object_unreference_unlocked(bo);
+	drm_gem_object_unreference_unlocked(&obj->base);
 	return ret;
 }
 
@@ -4739,8 +5110,14 @@ static void intel_gpu_idle_timer(unsigne
 	struct drm_device *dev = (struct drm_device *)arg;
 	drm_i915_private_t *dev_priv = dev->dev_private;
 
-	dev_priv->busy = false;
+	if (!list_empty(&dev_priv->mm.active_list)) {
+		/* Still processing requests, so just re-arm the timer. */
+		mod_timer(&dev_priv->idle_timer, jiffies +
+			  msecs_to_jiffies(GPU_IDLE_TIMEOUT));
+		return;
+	}
 
+	dev_priv->busy = false;
 	queue_work(dev_priv->wq, &dev_priv->idle_work);
 }
 
@@ -4751,9 +5128,17 @@ static void intel_crtc_idle_timer(unsign
 	struct intel_crtc *intel_crtc = (struct intel_crtc *)arg;
 	struct drm_crtc *crtc = &intel_crtc->base;
 	drm_i915_private_t *dev_priv = crtc->dev->dev_private;
+	struct intel_framebuffer *intel_fb;
 
-	intel_crtc->busy = false;
+	intel_fb = to_intel_framebuffer(crtc->fb);
+	if (intel_fb && intel_fb->obj->active) {
+		/* The framebuffer is still being accessed by the GPU. */
+		mod_timer(&intel_crtc->idle_timer, jiffies +
+			  msecs_to_jiffies(CRTC_IDLE_TIMEOUT));
+		return;
+	}
 
+	intel_crtc->busy = false;
 	queue_work(dev_priv->wq, &dev_priv->idle_work);
 }
 
@@ -4763,8 +5148,8 @@ static void intel_increase_pllclock(stru
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	int pipe = intel_crtc->pipe;
-	int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B;
-	int dpll = I915_READ(dpll_reg);
+	int dpll_reg = DPLL(pipe);
+	int dpll;
 
 	if (HAS_PCH_SPLIT(dev))
 		return;
@@ -4772,17 +5157,19 @@ static void intel_increase_pllclock(stru
 	if (!dev_priv->lvds_downclock_avail)
 		return;
 
+	dpll = I915_READ(dpll_reg);
 	if (!HAS_PIPE_CXSR(dev) && (dpll & DISPLAY_RATE_SELECT_FPA1)) {
 		DRM_DEBUG_DRIVER("upclocking LVDS\n");
 
 		/* Unlock panel regs */
-		I915_WRITE(PP_CONTROL, I915_READ(PP_CONTROL) |
-			   PANEL_UNLOCK_REGS);
+		I915_WRITE(PP_CONTROL,
+			   I915_READ(PP_CONTROL) | PANEL_UNLOCK_REGS);
 
 		dpll &= ~DISPLAY_RATE_SELECT_FPA1;
 		I915_WRITE(dpll_reg, dpll);
-		dpll = I915_READ(dpll_reg);
+		POSTING_READ(dpll_reg);
 		intel_wait_for_vblank(dev, pipe);
+
 		dpll = I915_READ(dpll_reg);
 		if (dpll & DISPLAY_RATE_SELECT_FPA1)
 			DRM_DEBUG_DRIVER("failed to upclock LVDS!\n");
@@ -4888,7 +5275,7 @@ static void intel_idle_update(struct wor
  * buffer), we'll also mark the display as busy, so we know to increase its
  * clock frequency.
  */
-void intel_mark_busy(struct drm_device *dev, struct drm_gem_object *obj)
+void intel_mark_busy(struct drm_device *dev, struct drm_i915_gem_object *obj)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	struct drm_crtc *crtc = NULL;
@@ -4969,8 +5356,9 @@ static void intel_unpin_work_fn(struct w
 
 	mutex_lock(&work->dev->struct_mutex);
 	i915_gem_object_unpin(work->old_fb_obj);
-	drm_gem_object_unreference(work->pending_flip_obj);
-	drm_gem_object_unreference(work->old_fb_obj);
+	drm_gem_object_unreference(&work->pending_flip_obj->base);
+	drm_gem_object_unreference(&work->old_fb_obj->base);
+
 	mutex_unlock(&work->dev->struct_mutex);
 	kfree(work);
 }
@@ -4981,15 +5369,17 @@ static void do_intel_finish_page_flip(st
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	struct intel_unpin_work *work;
-	struct drm_i915_gem_object *obj_priv;
+	struct drm_i915_gem_object *obj;
 	struct drm_pending_vblank_event *e;
-	struct timeval now;
+	struct timeval tnow, tvbl;
 	unsigned long flags;
 
 	/* Ignore early vblank irqs */
 	if (intel_crtc == NULL)
 		return;
 
+	do_gettimeofday(&tnow);
+
 	spin_lock_irqsave(&dev->event_lock, flags);
 	work = intel_crtc->unpin_work;
 	if (work == NULL || !work->pending) {
@@ -4998,26 +5388,49 @@ static void do_intel_finish_page_flip(st
 	}
 
 	intel_crtc->unpin_work = NULL;
-	drm_vblank_put(dev, intel_crtc->pipe);
 
 	if (work->event) {
 		e = work->event;
-		do_gettimeofday(&now);
-		e->event.sequence = drm_vblank_count(dev, intel_crtc->pipe);
-		e->event.tv_sec = now.tv_sec;
-		e->event.tv_usec = now.tv_usec;
+		e->event.sequence = drm_vblank_count_and_time(dev, intel_crtc->pipe, &tvbl);
+
+		/* Called before vblank count and timestamps have
+		 * been updated for the vblank interval of flip
+		 * completion? Need to increment vblank count and
+		 * add one videorefresh duration to returned timestamp
+		 * to account for this. We assume this happened if we
+		 * get called over 0.9 frame durations after the last
+		 * timestamped vblank.
+		 *
+		 * This calculation can not be used with vrefresh rates
+		 * below 5Hz (10Hz to be on the safe side) without
+		 * promoting to 64 integers.
+		 */
+		if (10 * (timeval_to_ns(&tnow) - timeval_to_ns(&tvbl)) >
+		    9 * crtc->framedur_ns) {
+			e->event.sequence++;
+			tvbl = ns_to_timeval(timeval_to_ns(&tvbl) +
+					     crtc->framedur_ns);
+		}
+
+		e->event.tv_sec = tvbl.tv_sec;
+		e->event.tv_usec = tvbl.tv_usec;
+
 		list_add_tail(&e->base.link,
 			      &e->base.file_priv->event_list);
 		wake_up_interruptible(&e->base.file_priv->event_wait);
 	}
 
+	drm_vblank_put(dev, intel_crtc->pipe);
+
 	spin_unlock_irqrestore(&dev->event_lock, flags);
 
-	obj_priv = to_intel_bo(work->old_fb_obj);
+	obj = work->old_fb_obj;
+
 	atomic_clear_mask(1 << intel_crtc->plane,
-			  &obj_priv->pending_flip.counter);
-	if (atomic_read(&obj_priv->pending_flip) == 0)
+			  &obj->pending_flip.counter);
+	if (atomic_read(&obj->pending_flip) == 0)
 		wake_up(&dev_priv->pending_flip_queue);
+
 	schedule_work(&work->work);
 
 	trace_i915_flip_complete(intel_crtc->plane, work->pending_flip_obj);
@@ -5063,8 +5476,7 @@ static int intel_crtc_page_flip(struct d
 	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_framebuffer *intel_fb;
-	struct drm_i915_gem_object *obj_priv;
-	struct drm_gem_object *obj;
+	struct drm_i915_gem_object *obj;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	struct intel_unpin_work *work;
 	unsigned long flags, offset;
@@ -5098,13 +5510,13 @@ static int intel_crtc_page_flip(struct d
 	obj = intel_fb->obj;
 
 	mutex_lock(&dev->struct_mutex);
-	ret = intel_pin_and_fence_fb_obj(dev, obj, true);
+	ret = intel_pin_and_fence_fb_obj(dev, obj, LP_RING(dev_priv));
 	if (ret)
 		goto cleanup_work;
 
 	/* Reference the objects for the scheduled work. */
-	drm_gem_object_reference(work->old_fb_obj);
-	drm_gem_object_reference(obj);
+	drm_gem_object_reference(&work->old_fb_obj->base);
+	drm_gem_object_reference(&obj->base);
 
 	crtc->fb = fb;
 
@@ -5112,22 +5524,16 @@ static int intel_crtc_page_flip(struct d
 	if (ret)
 		goto cleanup_objs;
 
-	/* Block clients from rendering to the new back buffer until
-	 * the flip occurs and the object is no longer visible.
-	 */
-	atomic_add(1 << intel_crtc->plane,
-		   &to_intel_bo(work->old_fb_obj)->pending_flip);
-
-	work->pending_flip_obj = obj;
-	obj_priv = to_intel_bo(obj);
-
 	if (IS_GEN3(dev) || IS_GEN2(dev)) {
 		u32 flip_mask;
 
 		/* Can't queue multiple flips, so wait for the previous
 		 * one to finish before executing the next.
 		 */
-		BEGIN_LP_RING(2);
+		ret = BEGIN_LP_RING(2);
+		if (ret)
+			goto cleanup_objs;
+
 		if (intel_crtc->plane)
 			flip_mask = MI_WAIT_FOR_PLANE_B_FLIP;
 		else
@@ -5137,18 +5543,28 @@ static int intel_crtc_page_flip(struct d
 		ADVANCE_LP_RING();
 	}
 
+	work->pending_flip_obj = obj;
+
 	work->enable_stall_check = true;
 
 	/* Offset into the new buffer for cases of shared fbs between CRTCs */
 	offset = crtc->y * fb->pitch + crtc->x * fb->bits_per_pixel/8;
 
-	BEGIN_LP_RING(4);
-	switch(INTEL_INFO(dev)->gen) {
+	ret = BEGIN_LP_RING(4);
+	if (ret)
+		goto cleanup_objs;
+
+	/* Block clients from rendering to the new back buffer until
+	 * the flip occurs and the object is no longer visible.
+	 */
+	atomic_add(1 << intel_crtc->plane, &work->old_fb_obj->pending_flip);
+
+	switch (INTEL_INFO(dev)->gen) {
 	case 2:
 		OUT_RING(MI_DISPLAY_FLIP |
 			 MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));
 		OUT_RING(fb->pitch);
-		OUT_RING(obj_priv->gtt_offset + offset);
+		OUT_RING(obj->gtt_offset + offset);
 		OUT_RING(MI_NOOP);
 		break;
 
@@ -5156,7 +5572,7 @@ static int intel_crtc_page_flip(struct d
 		OUT_RING(MI_DISPLAY_FLIP_I915 |
 			 MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));
 		OUT_RING(fb->pitch);
-		OUT_RING(obj_priv->gtt_offset + offset);
+		OUT_RING(obj->gtt_offset + offset);
 		OUT_RING(MI_NOOP);
 		break;
 
@@ -5169,7 +5585,7 @@ static int intel_crtc_page_flip(struct d
 		OUT_RING(MI_DISPLAY_FLIP |
 			 MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));
 		OUT_RING(fb->pitch);
-		OUT_RING(obj_priv->gtt_offset | obj_priv->tiling_mode);
+		OUT_RING(obj->gtt_offset | obj->tiling_mode);
 
 		/* XXX Enabling the panel-fitter across page-flip is so far
 		 * untested on non-native modes, so ignore it for now.
@@ -5183,8 +5599,8 @@ static int intel_crtc_page_flip(struct d
 	case 6:
 		OUT_RING(MI_DISPLAY_FLIP |
 			 MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));
-		OUT_RING(fb->pitch | obj_priv->tiling_mode);
-		OUT_RING(obj_priv->gtt_offset);
+		OUT_RING(fb->pitch | obj->tiling_mode);
+		OUT_RING(obj->gtt_offset);
 
 		pf = I915_READ(pipe == 0 ? PFA_CTL_1 : PFB_CTL_1) & PF_ENABLE;
 		pipesrc = I915_READ(pipe == 0 ? PIPEASRC : PIPEBSRC) & 0x0fff0fff;
@@ -5200,8 +5616,8 @@ static int intel_crtc_page_flip(struct d
 	return 0;
 
 cleanup_objs:
-	drm_gem_object_unreference(work->old_fb_obj);
-	drm_gem_object_unreference(obj);
+	drm_gem_object_unreference(&work->old_fb_obj->base);
+	drm_gem_object_unreference(&obj->base);
 cleanup_work:
 	mutex_unlock(&dev->struct_mutex);
 
@@ -5214,6 +5630,16 @@ cleanup_work:
 	return ret;
 }
 
+static void intel_crtc_reset(struct drm_crtc *crtc)
+{
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+
+	/* Reset flags back to the 'unknown' status so that they
+	 * will be correctly set on the initial modeset.
+	 */
+	intel_crtc->dpms_mode = -1;
+}
+
 static struct drm_crtc_helper_funcs intel_helper_funcs = {
 	.dpms = intel_crtc_dpms,
 	.mode_fixup = intel_crtc_mode_fixup,
@@ -5225,6 +5651,7 @@ static struct drm_crtc_helper_funcs inte
 };
 
 static const struct drm_crtc_funcs intel_crtc_funcs = {
+	.reset = intel_crtc_reset,
 	.cursor_set = intel_crtc_cursor_set,
 	.cursor_move = intel_crtc_cursor_move,
 	.gamma_set = intel_crtc_gamma_set,
@@ -5315,8 +5742,7 @@ static void intel_crtc_init(struct drm_d
 	dev_priv->plane_to_crtc_mapping[intel_crtc->plane] = &intel_crtc->base;
 	dev_priv->pipe_to_crtc_mapping[intel_crtc->pipe] = &intel_crtc->base;
 
-	intel_crtc->cursor_addr = 0;
-	intel_crtc->dpms_mode = -1;
+	intel_crtc_reset(&intel_crtc->base);
 	intel_crtc->active = true; /* force the pipe off on setup_init_config */
 
 	if (HAS_PCH_SPLIT(dev)) {
@@ -5338,7 +5764,7 @@ static void intel_crtc_init(struct drm_d
 }
 
 int intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data,
-				struct drm_file *file_priv)
+				struct drm_file *file)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	struct drm_i915_get_pipe_from_crtc_id *pipe_from_crtc_id = data;
@@ -5498,6 +5924,8 @@ static void intel_setup_outputs(struct d
 		encoder->base.possible_clones =
 			intel_encoder_clones(dev, encoder->clone_mask);
 	}
+
+	intel_panel_setup_backlight(dev);
 }
 
 static void intel_user_framebuffer_destroy(struct drm_framebuffer *fb)
@@ -5505,19 +5933,19 @@ static void intel_user_framebuffer_destr
 	struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
 
 	drm_framebuffer_cleanup(fb);
-	drm_gem_object_unreference_unlocked(intel_fb->obj);
+	drm_gem_object_unreference_unlocked(&intel_fb->obj->base);
 
 	kfree(intel_fb);
 }
 
 static int intel_user_framebuffer_create_handle(struct drm_framebuffer *fb,
-						struct drm_file *file_priv,
+						struct drm_file *file,
 						unsigned int *handle)
 {
 	struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
-	struct drm_gem_object *object = intel_fb->obj;
+	struct drm_i915_gem_object *obj = intel_fb->obj;
 
-	return drm_gem_handle_create(file_priv, object, handle);
+	return drm_gem_handle_create(file, &obj->base, handle);
 }
 
 static const struct drm_framebuffer_funcs intel_fb_funcs = {
@@ -5528,12 +5956,11 @@ static const struct drm_framebuffer_func
 int intel_framebuffer_init(struct drm_device *dev,
 			   struct intel_framebuffer *intel_fb,
 			   struct drm_mode_fb_cmd *mode_cmd,
-			   struct drm_gem_object *obj)
+			   struct drm_i915_gem_object *obj)
 {
-	struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
 	int ret;
 
-	if (obj_priv->tiling_mode == I915_TILING_Y)
+	if (obj->tiling_mode == I915_TILING_Y)
 		return -EINVAL;
 
 	if (mode_cmd->pitch & 63)
@@ -5565,11 +5992,11 @@ intel_user_framebuffer_create(struct drm
 			      struct drm_file *filp,
 			      struct drm_mode_fb_cmd *mode_cmd)
 {
-	struct drm_gem_object *obj;
+	struct drm_i915_gem_object *obj;
 	struct intel_framebuffer *intel_fb;
 	int ret;
 
-	obj = drm_gem_object_lookup(dev, filp, mode_cmd->handle);
+	obj = to_intel_bo(drm_gem_object_lookup(dev, filp, mode_cmd->handle));
 	if (!obj)
 		return ERR_PTR(-ENOENT);
 
@@ -5577,10 +6004,9 @@ intel_user_framebuffer_create(struct drm
 	if (!intel_fb)
 		return ERR_PTR(-ENOMEM);
 
-	ret = intel_framebuffer_init(dev, intel_fb,
-				     mode_cmd, obj);
+	ret = intel_framebuffer_init(dev, intel_fb, mode_cmd, obj);
 	if (ret) {
-		drm_gem_object_unreference_unlocked(obj);
+		drm_gem_object_unreference_unlocked(&obj->base);
 		kfree(intel_fb);
 		return ERR_PTR(ret);
 	}
@@ -5593,10 +6019,10 @@ static const struct drm_mode_config_func
 	.output_poll_changed = intel_fb_output_poll_changed,
 };
 
-static struct drm_gem_object *
+static struct drm_i915_gem_object *
 intel_alloc_context_page(struct drm_device *dev)
 {
-	struct drm_gem_object *ctx;
+	struct drm_i915_gem_object *ctx;
 	int ret;
 
 	ctx = i915_gem_alloc_object(dev, 4096);
@@ -5606,7 +6032,7 @@ intel_alloc_context_page(struct drm_devi
 	}
 
 	mutex_lock(&dev->struct_mutex);
-	ret = i915_gem_object_pin(ctx, 4096);
+	ret = i915_gem_object_pin(ctx, 4096, true);
 	if (ret) {
 		DRM_ERROR("failed to pin power context: %d\n", ret);
 		goto err_unref;
@@ -5624,7 +6050,7 @@ intel_alloc_context_page(struct drm_devi
 err_unpin:
 	i915_gem_object_unpin(ctx);
 err_unref:
-	drm_gem_object_unreference(ctx);
+	drm_gem_object_unreference(&ctx->base);
 	mutex_unlock(&dev->struct_mutex);
 	return NULL;
 }
@@ -5736,6 +6162,25 @@ void ironlake_disable_drps(struct drm_de
 
 }
 
+void gen6_set_rps(struct drm_device *dev, u8 val)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	u32 swreq;
+
+	swreq = (val & 0x3ff) << 25;
+	I915_WRITE(GEN6_RPNSWREQ, swreq);
+}
+
+void gen6_disable_rps(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	I915_WRITE(GEN6_RPNSWREQ, 1 << 31);
+	I915_WRITE(GEN6_PMINTRMSK, 0xffffffff);
+	I915_WRITE(GEN6_PMIER, 0);
+	I915_WRITE(GEN6_PMIIR, I915_READ(GEN6_PMIIR));
+}
+
 static unsigned long intel_pxfreq(u32 vidfreq)
 {
 	unsigned long freq;
@@ -5822,7 +6267,123 @@ void intel_init_emon(struct drm_device *
 	dev_priv->corr = (lcfuse & LCFUSE_HIV_MASK);
 }
 
-void intel_init_clock_gating(struct drm_device *dev)
+void gen6_enable_rps(struct drm_i915_private *dev_priv)
+{
+	u32 rp_state_cap = I915_READ(GEN6_RP_STATE_CAP);
+	u32 gt_perf_status = I915_READ(GEN6_GT_PERF_STATUS);
+	u32 pcu_mbox;
+	int cur_freq, min_freq, max_freq;
+	int i;
+
+	/* Here begins a magic sequence of register writes to enable
+	 * auto-downclocking.
+	 *
+	 * Perhaps there might be some value in exposing these to
+	 * userspace...
+	 */
+	I915_WRITE(GEN6_RC_STATE, 0);
+	__gen6_gt_force_wake_get(dev_priv);
+
+	/* disable the counters and set deterministic thresholds */
+	I915_WRITE(GEN6_RC_CONTROL, 0);
+
+	I915_WRITE(GEN6_RC1_WAKE_RATE_LIMIT, 1000 << 16);
+	I915_WRITE(GEN6_RC6_WAKE_RATE_LIMIT, 40 << 16 | 30);
+	I915_WRITE(GEN6_RC6pp_WAKE_RATE_LIMIT, 30);
+	I915_WRITE(GEN6_RC_EVALUATION_INTERVAL, 125000);
+	I915_WRITE(GEN6_RC_IDLE_HYSTERSIS, 25);
+
+	for (i = 0; i < I915_NUM_RINGS; i++)
+		I915_WRITE(RING_MAX_IDLE(dev_priv->ring[i].mmio_base), 10);
+
+	I915_WRITE(GEN6_RC_SLEEP, 0);
+	I915_WRITE(GEN6_RC1e_THRESHOLD, 1000);
+	I915_WRITE(GEN6_RC6_THRESHOLD, 50000);
+	I915_WRITE(GEN6_RC6p_THRESHOLD, 100000);
+	I915_WRITE(GEN6_RC6pp_THRESHOLD, 64000); /* unused */
+
+	I915_WRITE(GEN6_RC_CONTROL,
+		   GEN6_RC_CTL_RC6p_ENABLE |
+		   GEN6_RC_CTL_RC6_ENABLE |
+		   GEN6_RC_CTL_EI_MODE(1) |
+		   GEN6_RC_CTL_HW_ENABLE);
+
+	I915_WRITE(GEN6_RPNSWREQ,
+		   GEN6_FREQUENCY(10) |
+		   GEN6_OFFSET(0) |
+		   GEN6_AGGRESSIVE_TURBO);
+	I915_WRITE(GEN6_RC_VIDEO_FREQ,
+		   GEN6_FREQUENCY(12));
+
+	I915_WRITE(GEN6_RP_DOWN_TIMEOUT, 1000000);
+	I915_WRITE(GEN6_RP_INTERRUPT_LIMITS,
+		   18 << 24 |
+		   6 << 16);
+	I915_WRITE(GEN6_RP_UP_THRESHOLD, 90000);
+	I915_WRITE(GEN6_RP_DOWN_THRESHOLD, 100000);
+	I915_WRITE(GEN6_RP_UP_EI, 100000);
+	I915_WRITE(GEN6_RP_DOWN_EI, 300000);
+	I915_WRITE(GEN6_RP_IDLE_HYSTERSIS, 10);
+	I915_WRITE(GEN6_RP_CONTROL,
+		   GEN6_RP_MEDIA_TURBO |
+		   GEN6_RP_USE_NORMAL_FREQ |
+		   GEN6_RP_MEDIA_IS_GFX |
+		   GEN6_RP_ENABLE |
+		   GEN6_RP_UP_BUSY_MAX |
+		   GEN6_RP_DOWN_BUSY_MIN);
+
+	if (wait_for((I915_READ(GEN6_PCODE_MAILBOX) & GEN6_PCODE_READY) == 0,
+		     500))
+		DRM_ERROR("timeout waiting for pcode mailbox to become idle\n");
+
+	I915_WRITE(GEN6_PCODE_DATA, 0);
+	I915_WRITE(GEN6_PCODE_MAILBOX,
+		   GEN6_PCODE_READY |
+		   GEN6_PCODE_WRITE_MIN_FREQ_TABLE);
+	if (wait_for((I915_READ(GEN6_PCODE_MAILBOX) & GEN6_PCODE_READY) == 0,
+		     500))
+		DRM_ERROR("timeout waiting for pcode mailbox to finish\n");
+
+	min_freq = (rp_state_cap & 0xff0000) >> 16;
+	max_freq = rp_state_cap & 0xff;
+	cur_freq = (gt_perf_status & 0xff00) >> 8;
+
+	/* Check for overclock support */
+	if (wait_for((I915_READ(GEN6_PCODE_MAILBOX) & GEN6_PCODE_READY) == 0,
+		     500))
+		DRM_ERROR("timeout waiting for pcode mailbox to become idle\n");
+	I915_WRITE(GEN6_PCODE_MAILBOX, GEN6_READ_OC_PARAMS);
+	pcu_mbox = I915_READ(GEN6_PCODE_DATA);
+	if (wait_for((I915_READ(GEN6_PCODE_MAILBOX) & GEN6_PCODE_READY) == 0,
+		     500))
+		DRM_ERROR("timeout waiting for pcode mailbox to finish\n");
+	if (pcu_mbox & (1<<31)) { /* OC supported */
+		max_freq = pcu_mbox & 0xff;
+		DRM_DEBUG_DRIVER("overclocking supported, adjusting frequency max to %dMHz\n", pcu_mbox * 100);
+	}
+
+	/* In units of 100MHz */
+	dev_priv->max_delay = max_freq;
+	dev_priv->min_delay = min_freq;
+	dev_priv->cur_delay = cur_freq;
+
+	/* requires MSI enabled */
+	I915_WRITE(GEN6_PMIER,
+		   GEN6_PM_MBOX_EVENT |
+		   GEN6_PM_THERMAL_EVENT |
+		   GEN6_PM_RP_DOWN_TIMEOUT |
+		   GEN6_PM_RP_UP_THRESHOLD |
+		   GEN6_PM_RP_DOWN_THRESHOLD |
+		   GEN6_PM_RP_UP_EI_EXPIRED |
+		   GEN6_PM_RP_DOWN_EI_EXPIRED);
+	I915_WRITE(GEN6_PMIMR, 0);
+	/* enable all PM interrupts */
+	I915_WRITE(GEN6_PMINTRMSK, 0);
+
+	__gen6_gt_force_wake_put(dev_priv);
+}
+
+void intel_enable_clock_gating(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
@@ -5835,7 +6396,9 @@ void intel_init_clock_gating(struct drm_
 
 		if (IS_GEN5(dev)) {
 			/* Required for FBC */
-			dspclk_gate |= DPFDUNIT_CLOCK_GATE_DISABLE;
+			dspclk_gate |= DPFCUNIT_CLOCK_GATE_DISABLE |
+				DPFCRUNIT_CLOCK_GATE_DISABLE |
+				DPFDUNIT_CLOCK_GATE_DISABLE;
 			/* Required for CxSR */
 			dspclk_gate |= DPARBUNIT_CLOCK_GATE_DISABLE;
 
@@ -5872,9 +6435,9 @@ void intel_init_clock_gating(struct drm_
 			I915_WRITE(DISP_ARB_CTL,
 					(I915_READ(DISP_ARB_CTL) |
 						DISP_FBC_WM_DIS));
-		I915_WRITE(WM3_LP_ILK, 0);
-		I915_WRITE(WM2_LP_ILK, 0);
-		I915_WRITE(WM1_LP_ILK, 0);
+			I915_WRITE(WM3_LP_ILK, 0);
+			I915_WRITE(WM2_LP_ILK, 0);
+			I915_WRITE(WM1_LP_ILK, 0);
 		}
 		/*
 		 * Based on the document from hardware guys the following bits
@@ -5896,7 +6459,49 @@ void intel_init_clock_gating(struct drm_
 				   ILK_DPFC_DIS2 |
 				   ILK_CLK_FBC);
 		}
-		return;
+
+		I915_WRITE(ILK_DISPLAY_CHICKEN2,
+			   I915_READ(ILK_DISPLAY_CHICKEN2) |
+			   ILK_ELPIN_409_SELECT);
+
+		if (IS_GEN5(dev)) {
+			I915_WRITE(_3D_CHICKEN2,
+				   _3D_CHICKEN2_WM_READ_PIPELINED << 16 |
+				   _3D_CHICKEN2_WM_READ_PIPELINED);
+		}
+
+		if (IS_GEN6(dev)) {
+			I915_WRITE(WM3_LP_ILK, 0);
+			I915_WRITE(WM2_LP_ILK, 0);
+			I915_WRITE(WM1_LP_ILK, 0);
+
+			/*
+			 * According to the spec the following bits should be
+			 * set in order to enable memory self-refresh and fbc:
+			 * The bit21 and bit22 of 0x42000
+			 * The bit21 and bit22 of 0x42004
+			 * The bit5 and bit7 of 0x42020
+			 * The bit14 of 0x70180
+			 * The bit14 of 0x71180
+			 */
+			I915_WRITE(ILK_DISPLAY_CHICKEN1,
+				   I915_READ(ILK_DISPLAY_CHICKEN1) |
+				   ILK_FBCQ_DIS | ILK_PABSTRETCH_DIS);
+			I915_WRITE(ILK_DISPLAY_CHICKEN2,
+				   I915_READ(ILK_DISPLAY_CHICKEN2) |
+				   ILK_DPARB_GATE | ILK_VSDPFD_FULL);
+			I915_WRITE(ILK_DSPCLK_GATE,
+				   I915_READ(ILK_DSPCLK_GATE) |
+				   ILK_DPARB_CLK_GATE  |
+				   ILK_DPFD_CLK_GATE);
+
+			I915_WRITE(DSPACNTR,
+				   I915_READ(DSPACNTR) |
+				   DISPPLANE_TRICKLE_FEED_DISABLE);
+			I915_WRITE(DSPBCNTR,
+				   I915_READ(DSPBCNTR) |
+				   DISPPLANE_TRICKLE_FEED_DISABLE);
+		}
 	} else if (IS_G4X(dev)) {
 		uint32_t dspclk_gate;
 		I915_WRITE(RENCLK_GATE_D1, 0);
@@ -5934,57 +6539,106 @@ void intel_init_clock_gating(struct drm_
 	} else if (IS_I830(dev)) {
 		I915_WRITE(DSPCLK_GATE_D, OVRUNIT_CLOCK_GATE_DISABLE);
 	}
+}
+
+static void ironlake_teardown_rc6(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	if (dev_priv->renderctx) {
+		i915_gem_object_unpin(dev_priv->renderctx);
+		drm_gem_object_unreference(&dev_priv->renderctx->base);
+		dev_priv->renderctx = NULL;
+	}
+
+	if (dev_priv->pwrctx) {
+		i915_gem_object_unpin(dev_priv->pwrctx);
+		drm_gem_object_unreference(&dev_priv->pwrctx->base);
+		dev_priv->pwrctx = NULL;
+	}
+}
+
+static void ironlake_disable_rc6(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	if (I915_READ(PWRCTXA)) {
+		/* Wake the GPU, prevent RC6, then restore RSTDBYCTL */
+		I915_WRITE(RSTDBYCTL, I915_READ(RSTDBYCTL) | RCX_SW_EXIT);
+		wait_for(((I915_READ(RSTDBYCTL) & RSX_STATUS_MASK) == RSX_STATUS_ON),
+			 50);
+
+		I915_WRITE(PWRCTXA, 0);
+		POSTING_READ(PWRCTXA);
+
+		I915_WRITE(RSTDBYCTL, I915_READ(RSTDBYCTL) & ~RCX_SW_EXIT);
+		POSTING_READ(RSTDBYCTL);
+	}
+
+	ironlake_teardown_rc6(dev);
+}
+
+static int ironlake_setup_rc6(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	if (dev_priv->renderctx == NULL)
+		dev_priv->renderctx = intel_alloc_context_page(dev);
+	if (!dev_priv->renderctx)
+		return -ENOMEM;
+
+	if (dev_priv->pwrctx == NULL)
+		dev_priv->pwrctx = intel_alloc_context_page(dev);
+	if (!dev_priv->pwrctx) {
+		ironlake_teardown_rc6(dev);
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+void ironlake_enable_rc6(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	int ret;
+
+	/* rc6 disabled by default due to repeated reports of hanging during
+	 * boot and resume.
+	 */
+	if (!i915_enable_rc6)
+		return;
+
+	ret = ironlake_setup_rc6(dev);
+	if (ret)
+		return;
 
 	/*
 	 * GPU can automatically power down the render unit if given a page
 	 * to save state.
 	 */
-	if (IS_IRONLAKE_M(dev)) {
-		if (dev_priv->renderctx == NULL)
-			dev_priv->renderctx = intel_alloc_context_page(dev);
-		if (dev_priv->renderctx) {
-			struct drm_i915_gem_object *obj_priv;
-			obj_priv = to_intel_bo(dev_priv->renderctx);
-			if (obj_priv) {
-				BEGIN_LP_RING(4);
-				OUT_RING(MI_SET_CONTEXT);
-				OUT_RING(obj_priv->gtt_offset |
-						MI_MM_SPACE_GTT |
-						MI_SAVE_EXT_STATE_EN |
-						MI_RESTORE_EXT_STATE_EN |
-						MI_RESTORE_INHIBIT);
-				OUT_RING(MI_NOOP);
-				OUT_RING(MI_FLUSH);
-				ADVANCE_LP_RING();
-			}
-		} else
-			DRM_DEBUG_KMS("Failed to allocate render context."
-				       "Disable RC6\n");
+	ret = BEGIN_LP_RING(6);
+	if (ret) {
+		ironlake_teardown_rc6(dev);
+		return;
 	}
 
-	if (I915_HAS_RC6(dev) && drm_core_check_feature(dev, DRIVER_MODESET)) {
-		struct drm_i915_gem_object *obj_priv = NULL;
-
-		if (dev_priv->pwrctx) {
-			obj_priv = to_intel_bo(dev_priv->pwrctx);
-		} else {
-			struct drm_gem_object *pwrctx;
-
-			pwrctx = intel_alloc_context_page(dev);
-			if (pwrctx) {
-				dev_priv->pwrctx = pwrctx;
-				obj_priv = to_intel_bo(pwrctx);
-			}
-		}
+	OUT_RING(MI_SUSPEND_FLUSH | MI_SUSPEND_FLUSH_EN);
+	OUT_RING(MI_SET_CONTEXT);
+	OUT_RING(dev_priv->renderctx->gtt_offset |
+		 MI_MM_SPACE_GTT |
+		 MI_SAVE_EXT_STATE_EN |
+		 MI_RESTORE_EXT_STATE_EN |
+		 MI_RESTORE_INHIBIT);
+	OUT_RING(MI_SUSPEND_FLUSH);
+	OUT_RING(MI_NOOP);
+	OUT_RING(MI_FLUSH);
+	ADVANCE_LP_RING();
 
-		if (obj_priv) {
-			I915_WRITE(PWRCTXA, obj_priv->gtt_offset | PWRCTX_EN);
-			I915_WRITE(MCHBAR_RENDER_STANDBY,
-				   I915_READ(MCHBAR_RENDER_STANDBY) & ~RCX_SW_EXIT);
-		}
-	}
+	I915_WRITE(PWRCTXA, dev_priv->pwrctx->gtt_offset | PWRCTX_EN);
+	I915_WRITE(RSTDBYCTL, I915_READ(RSTDBYCTL) & ~RCX_SW_EXIT);
 }
 
+
 /* Set up chip specific display functions */
 static void intel_init_display(struct drm_device *dev)
 {
@@ -5997,7 +6651,7 @@ static void intel_init_display(struct dr
 		dev_priv->display.dpms = i9xx_crtc_dpms;
 
 	if (I915_HAS_FBC(dev)) {
-		if (IS_IRONLAKE_M(dev)) {
+		if (HAS_PCH_SPLIT(dev)) {
 			dev_priv->display.fbc_enabled = ironlake_fbc_enabled;
 			dev_priv->display.enable_fbc = ironlake_enable_fbc;
 			dev_priv->display.disable_fbc = ironlake_disable_fbc;
@@ -6046,6 +6700,14 @@ static void intel_init_display(struct dr
 					      "Disable CxSR\n");
 				dev_priv->display.update_wm = NULL;
 			}
+		} else if (IS_GEN6(dev)) {
+			if (SNB_READ_WM0_LATENCY()) {
+				dev_priv->display.update_wm = sandybridge_update_wm;
+			} else {
+				DRM_DEBUG_KMS("Failed to read display plane latency. "
+					      "Disable CxSR\n");
+				dev_priv->display.update_wm = NULL;
+			}
 		} else
 			dev_priv->display.update_wm = NULL;
 	} else if (IS_PINEVIEW(dev)) {
@@ -6191,12 +6853,7 @@ void intel_modeset_init(struct drm_devic
 		dev->mode_config.max_width = 8192;
 		dev->mode_config.max_height = 8192;
 	}
-
-	/* set memory base */
-	if (IS_GEN2(dev))
-		dev->mode_config.fb_base = pci_resource_start(dev->pdev, 0);
-	else
-		dev->mode_config.fb_base = pci_resource_start(dev->pdev, 2);
+	dev->mode_config.fb_base = dev->agp->base;
 
 	if (IS_MOBILE(dev) || !IS_GEN2(dev))
 		dev_priv->num_pipe = 2;
@@ -6211,7 +6868,7 @@ void intel_modeset_init(struct drm_devic
 
 	intel_setup_outputs(dev);
 
-	intel_init_clock_gating(dev);
+	intel_enable_clock_gating(dev);
 
 	/* Just disable it once at startup */
 	i915_disable_vga(dev);
@@ -6221,6 +6878,12 @@ void intel_modeset_init(struct drm_devic
 		intel_init_emon(dev);
 	}
 
+	if (IS_GEN6(dev))
+		gen6_enable_rps(dev_priv);
+
+	if (IS_IRONLAKE_M(dev))
+		ironlake_enable_rc6(dev);
+
 	INIT_WORK(&dev_priv->idle_work, intel_idle_update);
 	setup_timer(&dev_priv->idle_timer, intel_gpu_idle_timer,
 		    (unsigned long)dev);
@@ -6252,28 +6915,13 @@ void intel_modeset_cleanup(struct drm_de
 	if (dev_priv->display.disable_fbc)
 		dev_priv->display.disable_fbc(dev);
 
-	if (dev_priv->renderctx) {
-		struct drm_i915_gem_object *obj_priv;
-
-		obj_priv = to_intel_bo(dev_priv->renderctx);
-		I915_WRITE(CCID, obj_priv->gtt_offset &~ CCID_EN);
-		I915_READ(CCID);
-		i915_gem_object_unpin(dev_priv->renderctx);
-		drm_gem_object_unreference(dev_priv->renderctx);
-	}
-
-	if (dev_priv->pwrctx) {
-		struct drm_i915_gem_object *obj_priv;
-
-		obj_priv = to_intel_bo(dev_priv->pwrctx);
-		I915_WRITE(PWRCTXA, obj_priv->gtt_offset &~ PWRCTX_EN);
-		I915_READ(PWRCTXA);
-		i915_gem_object_unpin(dev_priv->pwrctx);
-		drm_gem_object_unreference(dev_priv->pwrctx);
-	}
-
 	if (IS_IRONLAKE_M(dev))
 		ironlake_disable_drps(dev);
+	if (IS_GEN6(dev))
+		gen6_disable_rps(dev);
+
+	if (IS_IRONLAKE_M(dev))
+		ironlake_disable_rc6(dev);
 
 	mutex_unlock(&dev->struct_mutex);
 
@@ -6325,3 +6973,113 @@ int intel_modeset_vga_set_state(struct d
 	pci_write_config_word(dev_priv->bridge_dev, INTEL_GMCH_CTRL, gmch_ctrl);
 	return 0;
 }
+
+#ifdef CONFIG_DEBUG_FS
+#include <linux/seq_file.h>
+
+struct intel_display_error_state {
+	struct intel_cursor_error_state {
+		u32 control;
+		u32 position;
+		u32 base;
+		u32 size;
+	} cursor[2];
+
+	struct intel_pipe_error_state {
+		u32 conf;
+		u32 source;
+
+		u32 htotal;
+		u32 hblank;
+		u32 hsync;
+		u32 vtotal;
+		u32 vblank;
+		u32 vsync;
+	} pipe[2];
+
+	struct intel_plane_error_state {
+		u32 control;
+		u32 stride;
+		u32 size;
+		u32 pos;
+		u32 addr;
+		u32 surface;
+		u32 tile_offset;
+	} plane[2];
+};
+
+struct intel_display_error_state *
+intel_display_capture_error_state(struct drm_device *dev)
+{
+        drm_i915_private_t *dev_priv = dev->dev_private;
+	struct intel_display_error_state *error;
+	int i;
+
+	error = kmalloc(sizeof(*error), GFP_ATOMIC);
+	if (error == NULL)
+		return NULL;
+
+	for (i = 0; i < 2; i++) {
+		error->cursor[i].control = I915_READ(CURCNTR(i));
+		error->cursor[i].position = I915_READ(CURPOS(i));
+		error->cursor[i].base = I915_READ(CURBASE(i));
+
+		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].addr = I915_READ(DSPADDR(i));
+		if (INTEL_INFO(dev)->gen >= 4) {
+			error->plane[i].surface = I915_READ(DSPSURF(i));
+			error->plane[i].tile_offset = I915_READ(DSPTILEOFF(i));
+		}
+
+		error->pipe[i].conf = I915_READ(PIPECONF(i));
+		error->pipe[i].source = I915_READ(PIPESRC(i));
+		error->pipe[i].htotal = I915_READ(HTOTAL(i));
+		error->pipe[i].hblank = I915_READ(HBLANK(i));
+		error->pipe[i].hsync = I915_READ(HSYNC(i));
+		error->pipe[i].vtotal = I915_READ(VTOTAL(i));
+		error->pipe[i].vblank = I915_READ(VBLANK(i));
+		error->pipe[i].vsync = I915_READ(VSYNC(i));
+	}
+
+	return error;
+}
+
+void
+intel_display_print_error_state(struct seq_file *m,
+				struct drm_device *dev,
+				struct intel_display_error_state *error)
+{
+	int i;
+
+	for (i = 0; i < 2; i++) {
+		seq_printf(m, "Pipe [%d]:\n", i);
+		seq_printf(m, "  CONF: %08x\n", error->pipe[i].conf);
+		seq_printf(m, "  SRC: %08x\n", error->pipe[i].source);
+		seq_printf(m, "  HTOTAL: %08x\n", error->pipe[i].htotal);
+		seq_printf(m, "  HBLANK: %08x\n", error->pipe[i].hblank);
+		seq_printf(m, "  HSYNC: %08x\n", error->pipe[i].hsync);
+		seq_printf(m, "  VTOTAL: %08x\n", error->pipe[i].vtotal);
+		seq_printf(m, "  VBLANK: %08x\n", error->pipe[i].vblank);
+		seq_printf(m, "  VSYNC: %08x\n", error->pipe[i].vsync);
+
+		seq_printf(m, "Plane [%d]:\n", i);
+		seq_printf(m, "  CNTR: %08x\n", error->plane[i].control);
+		seq_printf(m, "  STRIDE: %08x\n", error->plane[i].stride);
+		seq_printf(m, "  SIZE: %08x\n", error->plane[i].size);
+		seq_printf(m, "  POS: %08x\n", error->plane[i].pos);
+		seq_printf(m, "  ADDR: %08x\n", error->plane[i].addr);
+		if (INTEL_INFO(dev)->gen >= 4) {
+			seq_printf(m, "  SURF: %08x\n", error->plane[i].surface);
+			seq_printf(m, "  TILEOFF: %08x\n", error->plane[i].tile_offset);
+		}
+
+		seq_printf(m, "Cursor [%d]:\n", i);
+		seq_printf(m, "  CNTR: %08x\n", error->cursor[i].control);
+		seq_printf(m, "  POS: %08x\n", error->cursor[i].position);
+		seq_printf(m, "  BASE: %08x\n", error->cursor[i].base);
+	}
+}
+#endif
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/i915/intel_dp.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/i915/intel_dp.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/i915/intel_dp.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/i915/intel_dp.c	2011-03-14 21:20:32.000000000 -0400
@@ -1153,18 +1153,27 @@ intel_dp_signal_levels(uint8_t train_set
 static uint32_t
 intel_gen6_edp_signal_levels(uint8_t train_set)
 {
-	switch (train_set & (DP_TRAIN_VOLTAGE_SWING_MASK|DP_TRAIN_PRE_EMPHASIS_MASK)) {
+	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_SNB_B;
+	case DP_TRAIN_VOLTAGE_SWING_600 | DP_TRAIN_PRE_EMPHASIS_0:
+		return EDP_LINK_TRAIN_400_600MV_0DB_SNB_B;
+	case DP_TRAIN_VOLTAGE_SWING_400 | DP_TRAIN_PRE_EMPHASIS_3_5:
+		return EDP_LINK_TRAIN_400MV_3_5DB_SNB_B;
 	case DP_TRAIN_VOLTAGE_SWING_400 | DP_TRAIN_PRE_EMPHASIS_6:
-		return EDP_LINK_TRAIN_400MV_6DB_SNB_B;
+	case DP_TRAIN_VOLTAGE_SWING_600 | DP_TRAIN_PRE_EMPHASIS_6:
+		return EDP_LINK_TRAIN_400_600MV_6DB_SNB_B;
 	case DP_TRAIN_VOLTAGE_SWING_600 | DP_TRAIN_PRE_EMPHASIS_3_5:
-		return EDP_LINK_TRAIN_600MV_3_5DB_SNB_B;
+	case DP_TRAIN_VOLTAGE_SWING_800 | DP_TRAIN_PRE_EMPHASIS_3_5:
+		return EDP_LINK_TRAIN_600_800MV_3_5DB_SNB_B;
 	case DP_TRAIN_VOLTAGE_SWING_800 | DP_TRAIN_PRE_EMPHASIS_0:
-		return EDP_LINK_TRAIN_800MV_0DB_SNB_B;
+	case DP_TRAIN_VOLTAGE_SWING_1200 | DP_TRAIN_PRE_EMPHASIS_0:
+		return EDP_LINK_TRAIN_800_1200MV_0DB_SNB_B;
 	default:
-		DRM_DEBUG_KMS("Unsupported voltage swing/pre-emphasis level\n");
-		return EDP_LINK_TRAIN_400MV_0DB_SNB_B;
+		DRM_DEBUG_KMS("Unsupported voltage swing/pre-emphasis level:"
+			      "0x%x\n", signal_levels);
+		return EDP_LINK_TRAIN_400_600MV_0DB_SNB_B;
 	}
 }
 
@@ -1334,17 +1343,24 @@ intel_dp_complete_link_train(struct inte
 	struct drm_device *dev = intel_dp->base.base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	bool channel_eq = false;
-	int tries;
+	int tries, cr_tries;
 	u32 reg;
 	uint32_t DP = intel_dp->DP;
 
 	/* channel equalization */
 	tries = 0;
+	cr_tries = 0;
 	channel_eq = false;
 	for (;;) {
 		/* Use intel_dp->train_set[0] to set the voltage and pre emphasis values */
 		uint32_t    signal_levels;
 
+		if (cr_tries > 5) {
+			DRM_ERROR("failed to train DP, aborting\n");
+			intel_dp_link_down(intel_dp);
+			break;
+		}
+
 		if (IS_GEN6(dev) && is_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;
@@ -1367,14 +1383,26 @@ intel_dp_complete_link_train(struct inte
 		if (!intel_dp_get_link_status(intel_dp))
 			break;
 
+		/* Make sure clock is still ok */
+		if (!intel_clock_recovery_ok(intel_dp->link_status, intel_dp->lane_count)) {
+			intel_dp_start_link_train(intel_dp);
+			cr_tries++;
+			continue;
+		}
+
 		if (intel_channel_eq_ok(intel_dp)) {
 			channel_eq = true;
 			break;
 		}
 
-		/* Try 5 times */
-		if (tries > 5)
-			break;
+		/* Try 5 times, then try clock recovery if that fails */
+		if (tries > 5) {
+			intel_dp_link_down(intel_dp);
+			intel_dp_start_link_train(intel_dp);
+			tries = 0;
+			cr_tries++;
+			continue;
+		}
 
 		/* Compute new intel_dp->train_set as requested by target */
 		intel_get_adjust_train(intel_dp);
@@ -1442,8 +1470,7 @@ intel_dp_link_down(struct intel_dp *inte
 		/* Changes to enable or select take place the vblank
 		 * after being written.
 		 */
-		intel_wait_for_vblank(intel_dp->base.base.dev,
-				      intel_crtc->pipe);
+		intel_wait_for_vblank(dev, intel_crtc->pipe);
 	}
 
 	I915_WRITE(intel_dp->output_reg, DP & ~DP_PORT_EN);
@@ -1612,6 +1639,24 @@ static int intel_dp_get_modes(struct drm
 	return 0;
 }
 
+static bool
+intel_dp_detect_audio(struct drm_connector *connector)
+{
+	struct intel_dp *intel_dp = intel_attached_dp(connector);
+	struct edid *edid;
+	bool has_audio = false;
+
+	edid = drm_get_edid(connector, &intel_dp->adapter);
+	if (edid) {
+		has_audio = drm_detect_monitor_audio(edid);
+
+		connector->display_info.raw_edid = NULL;
+		kfree(edid);
+	}
+
+	return has_audio;
+}
+
 static int
 intel_dp_set_property(struct drm_connector *connector,
 		      struct drm_property *property,
@@ -1625,17 +1670,23 @@ intel_dp_set_property(struct drm_connect
 		return ret;
 
 	if (property == intel_dp->force_audio_property) {
-		if (val == intel_dp->force_audio)
+		int i = val;
+		bool has_audio;
+
+		if (i == intel_dp->force_audio)
 			return 0;
 
-		intel_dp->force_audio = val;
+		intel_dp->force_audio = i;
 
-		if (val > 0 && intel_dp->has_audio)
-			return 0;
-		if (val < 0 && !intel_dp->has_audio)
+		if (i == 0)
+			has_audio = intel_dp_detect_audio(connector);
+		else
+			has_audio = i > 0;
+
+		if (has_audio == intel_dp->has_audio)
 			return 0;
 
-		intel_dp->has_audio = val > 0;
+		intel_dp->has_audio = has_audio;
 		goto done;
 	}
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/i915/intel_drv.h linux-libre-2.6.38-gnu1/drivers/gpu/drm/i915/intel_drv.h
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/i915/intel_drv.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/i915/intel_drv.h	2011-03-14 21:20:32.000000000 -0400
@@ -127,7 +127,7 @@ intel_mode_get_pixel_multiplier(const st
 
 struct intel_framebuffer {
 	struct drm_framebuffer base;
-	struct drm_gem_object *obj;
+	struct drm_i915_gem_object *obj;
 };
 
 struct intel_fbdev {
@@ -166,7 +166,7 @@ struct intel_crtc {
 	struct intel_unpin_work *unpin_work;
 	int fdi_lanes;
 
-	struct drm_gem_object *cursor_bo;
+	struct drm_i915_gem_object *cursor_bo;
 	uint32_t cursor_addr;
 	int16_t cursor_x, cursor_y;
 	int16_t cursor_width, cursor_height;
@@ -220,8 +220,8 @@ intel_get_crtc_for_pipe(struct drm_devic
 struct intel_unpin_work {
 	struct work_struct work;
 	struct drm_device *dev;
-	struct drm_gem_object *old_fb_obj;
-	struct drm_gem_object *pending_flip_obj;
+	struct drm_i915_gem_object *old_fb_obj;
+	struct drm_i915_gem_object *pending_flip_obj;
 	struct drm_pending_vblank_event *event;
 	int pending;
 	bool enable_stall_check;
@@ -236,7 +236,8 @@ void intel_dip_infoframe_csum(struct dip
 extern bool intel_sdvo_init(struct drm_device *dev, int output_device);
 extern void intel_dvo_init(struct drm_device *dev);
 extern void intel_tv_init(struct drm_device *dev);
-extern void intel_mark_busy(struct drm_device *dev, struct drm_gem_object *obj);
+extern void intel_mark_busy(struct drm_device *dev,
+			    struct drm_i915_gem_object *obj);
 extern bool intel_lvds_init(struct drm_device *dev);
 extern void intel_dp_init(struct drm_device *dev, int dp_reg);
 void
@@ -256,6 +257,9 @@ extern void intel_pch_panel_fitting(stru
 extern u32 intel_panel_get_max_backlight(struct drm_device *dev);
 extern u32 intel_panel_get_backlight(struct drm_device *dev);
 extern void intel_panel_set_backlight(struct drm_device *dev, u32 level);
+extern void intel_panel_setup_backlight(struct drm_device *dev);
+extern void intel_panel_enable_backlight(struct drm_device *dev);
+extern void intel_panel_disable_backlight(struct drm_device *dev);
 
 extern void intel_crtc_load_lut(struct drm_crtc *crtc);
 extern void intel_encoder_prepare (struct drm_encoder *encoder);
@@ -293,19 +297,21 @@ extern void intel_crtc_fb_gamma_set(stru
 				    u16 blue, int regno);
 extern void intel_crtc_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green,
 				    u16 *blue, int regno);
-extern void intel_init_clock_gating(struct drm_device *dev);
+extern void intel_enable_clock_gating(struct drm_device *dev);
 extern void ironlake_enable_drps(struct drm_device *dev);
 extern void ironlake_disable_drps(struct drm_device *dev);
+extern void gen6_enable_rps(struct drm_i915_private *dev_priv);
+extern void gen6_disable_rps(struct drm_device *dev);
 extern void intel_init_emon(struct drm_device *dev);
 
 extern int intel_pin_and_fence_fb_obj(struct drm_device *dev,
-				      struct drm_gem_object *obj,
-				      bool pipelined);
+				      struct drm_i915_gem_object *obj,
+				      struct intel_ring_buffer *pipelined);
 
 extern int intel_framebuffer_init(struct drm_device *dev,
 				  struct intel_framebuffer *ifb,
 				  struct drm_mode_fb_cmd *mode_cmd,
-				  struct drm_gem_object *obj);
+				  struct drm_i915_gem_object *obj);
 extern int intel_fbdev_init(struct drm_device *dev);
 extern void intel_fbdev_fini(struct drm_device *dev);
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/i915/intel_fb.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/i915/intel_fb.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/i915/intel_fb.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/i915/intel_fb.c	2011-03-14 21:20:32.000000000 -0400
@@ -62,13 +62,13 @@ static int intelfb_create(struct intel_f
 			  struct drm_fb_helper_surface_size *sizes)
 {
 	struct drm_device *dev = ifbdev->helper.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct fb_info *info;
 	struct drm_framebuffer *fb;
 	struct drm_mode_fb_cmd mode_cmd;
-	struct drm_gem_object *fbo = NULL;
-	struct drm_i915_gem_object *obj_priv;
+	struct drm_i915_gem_object *obj;
 	struct device *device = &dev->pdev->dev;
-	int size, ret, mmio_bar = IS_GEN2(dev) ? 1 : 0;
+	int size, ret;
 
 	/* we don't do packed 24bpp */
 	if (sizes->surface_bpp == 24)
@@ -78,23 +78,22 @@ static int intelfb_create(struct intel_f
 	mode_cmd.height = sizes->surface_height;
 
 	mode_cmd.bpp = sizes->surface_bpp;
-	mode_cmd.pitch = ALIGN(mode_cmd.width * ((mode_cmd.bpp + 1) / 8), 64);
+	mode_cmd.pitch = ALIGN(mode_cmd.width * ((mode_cmd.bpp + 7) / 8), 64);
 	mode_cmd.depth = sizes->surface_depth;
 
 	size = mode_cmd.pitch * mode_cmd.height;
 	size = ALIGN(size, PAGE_SIZE);
-	fbo = i915_gem_alloc_object(dev, size);
-	if (!fbo) {
+	obj = i915_gem_alloc_object(dev, size);
+	if (!obj) {
 		DRM_ERROR("failed to allocate framebuffer\n");
 		ret = -ENOMEM;
 		goto out;
 	}
-	obj_priv = to_intel_bo(fbo);
 
 	mutex_lock(&dev->struct_mutex);
 
 	/* Flush everything out, we'll be doing GTT only from now on */
-	ret = intel_pin_and_fence_fb_obj(dev, fbo, false);
+	ret = intel_pin_and_fence_fb_obj(dev, obj, false);
 	if (ret) {
 		DRM_ERROR("failed to pin fb: %d\n", ret);
 		goto out_unref;
@@ -108,7 +107,7 @@ static int intelfb_create(struct intel_f
 
 	info->par = ifbdev;
 
-	ret = intel_framebuffer_init(dev, &ifbdev->ifb, &mode_cmd, fbo);
+	ret = intel_framebuffer_init(dev, &ifbdev->ifb, &mode_cmd, obj);
 	if (ret)
 		goto out_unpin;
 
@@ -122,6 +121,11 @@ static int intelfb_create(struct intel_f
 	info->flags = FBINFO_DEFAULT | FBINFO_CAN_FORCE_OUTPUT;
 	info->fbops = &intelfb_ops;
 
+	ret = fb_alloc_cmap(&info->cmap, 256, 0);
+	if (ret) {
+		ret = -ENOMEM;
+		goto out_unpin;
+	}
 	/* setup aperture base/size for vesafb takeover */
 	info->apertures = alloc_apertures(1);
 	if (!info->apertures) {
@@ -129,26 +133,17 @@ static int intelfb_create(struct intel_f
 		goto out_unpin;
 	}
 	info->apertures->ranges[0].base = dev->mode_config.fb_base;
-	if (!IS_GEN2(dev))
-		info->apertures->ranges[0].size = pci_resource_len(dev->pdev, 2);
-	else
-		info->apertures->ranges[0].size = pci_resource_len(dev->pdev, 0);
+	info->apertures->ranges[0].size =
+		dev_priv->mm.gtt->gtt_mappable_entries << PAGE_SHIFT;
 
-	info->fix.smem_start = dev->mode_config.fb_base + obj_priv->gtt_offset;
+	info->fix.smem_start = dev->mode_config.fb_base + obj->gtt_offset;
 	info->fix.smem_len = size;
 
-	info->screen_base = ioremap_wc(dev->agp->base + obj_priv->gtt_offset,
-				       size);
+	info->screen_base = ioremap_wc(dev->agp->base + obj->gtt_offset, size);
 	if (!info->screen_base) {
 		ret = -ENOSPC;
 		goto out_unpin;
 	}
-
-	ret = fb_alloc_cmap(&info->cmap, 256, 0);
-	if (ret) {
-		ret = -ENOMEM;
-		goto out_unpin;
-	}
 	info->screen_size = size;
 
 //	memset(info->screen_base, 0, size);
@@ -156,10 +151,6 @@ static int intelfb_create(struct intel_f
 	drm_fb_helper_fill_fix(info, fb->pitch, fb->depth);
 	drm_fb_helper_fill_var(info, &ifbdev->helper, sizes->fb_width, sizes->fb_height);
 
-	/* FIXME: we really shouldn't expose mmio space at all */
-	info->fix.mmio_start = pci_resource_start(dev->pdev, mmio_bar);
-	info->fix.mmio_len = pci_resource_len(dev->pdev, mmio_bar);
-
 	info->pixmap.size = 64*1024;
 	info->pixmap.buf_align = 8;
 	info->pixmap.access_align = 32;
@@ -168,7 +159,7 @@ static int intelfb_create(struct intel_f
 
 	DRM_DEBUG_KMS("allocated %dx%d fb: 0x%08x, bo %p\n",
 		      fb->width, fb->height,
-		      obj_priv->gtt_offset, fbo);
+		      obj->gtt_offset, obj);
 
 
 	mutex_unlock(&dev->struct_mutex);
@@ -176,9 +167,9 @@ static int intelfb_create(struct intel_f
 	return 0;
 
 out_unpin:
-	i915_gem_object_unpin(fbo);
+	i915_gem_object_unpin(obj);
 out_unref:
-	drm_gem_object_unreference(fbo);
+	drm_gem_object_unreference(&obj->base);
 	mutex_unlock(&dev->struct_mutex);
 out:
 	return ret;
@@ -225,7 +216,7 @@ static void intel_fbdev_destroy(struct d
 
 	drm_framebuffer_cleanup(&ifb->base);
 	if (ifb->obj) {
-		drm_gem_object_unreference_unlocked(ifb->obj);
+		drm_gem_object_unreference_unlocked(&ifb->obj->base);
 		ifb->obj = NULL;
 	}
 }
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/i915/intel_hdmi.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/i915/intel_hdmi.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/i915/intel_hdmi.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/i915/intel_hdmi.c	2011-03-14 21:20:32.000000000 -0400
@@ -251,6 +251,27 @@ static int intel_hdmi_get_modes(struct d
 				   &dev_priv->gmbus[intel_hdmi->ddc_bus].adapter);
 }
 
+static bool
+intel_hdmi_detect_audio(struct drm_connector *connector)
+{
+	struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector);
+	struct drm_i915_private *dev_priv = connector->dev->dev_private;
+	struct edid *edid;
+	bool has_audio = false;
+
+	edid = drm_get_edid(connector,
+			    &dev_priv->gmbus[intel_hdmi->ddc_bus].adapter);
+	if (edid) {
+		if (edid->input & DRM_EDID_INPUT_DIGITAL)
+			has_audio = drm_detect_monitor_audio(edid);
+
+		connector->display_info.raw_edid = NULL;
+		kfree(edid);
+	}
+
+	return has_audio;
+}
+
 static int
 intel_hdmi_set_property(struct drm_connector *connector,
 		      struct drm_property *property,
@@ -264,17 +285,23 @@ intel_hdmi_set_property(struct drm_conne
 		return ret;
 
 	if (property == intel_hdmi->force_audio_property) {
-		if (val == intel_hdmi->force_audio)
+		int i = val;
+		bool has_audio;
+
+		if (i == intel_hdmi->force_audio)
 			return 0;
 
-		intel_hdmi->force_audio = val;
+		intel_hdmi->force_audio = i;
 
-		if (val > 0 && intel_hdmi->has_audio)
-			return 0;
-		if (val < 0 && !intel_hdmi->has_audio)
+		if (i == 0)
+			has_audio = intel_hdmi_detect_audio(connector);
+		else
+			has_audio = i > 0;
+
+		if (has_audio == intel_hdmi->has_audio)
 			return 0;
 
-		intel_hdmi->has_audio = val > 0;
+		intel_hdmi->has_audio = has_audio;
 		goto done;
 	}
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/i915/intel_i2c.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/i915/intel_i2c.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/i915/intel_i2c.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/i915/intel_i2c.c	2011-03-14 21:20:32.000000000 -0400
@@ -85,8 +85,9 @@ static u32 get_reserved(struct intel_gpi
 
 	/* On most chips, these bits must be preserved in software. */
 	if (!IS_I830(dev) && !IS_845G(dev))
-		reserved = I915_READ(gpio->reg) & (GPIO_DATA_PULLUP_DISABLE |
-						   GPIO_CLOCK_PULLUP_DISABLE);
+		reserved = I915_READ_NOTRACE(gpio->reg) &
+					     (GPIO_DATA_PULLUP_DISABLE |
+					      GPIO_CLOCK_PULLUP_DISABLE);
 
 	return reserved;
 }
@@ -96,9 +97,9 @@ static int get_clock(void *data)
 	struct intel_gpio *gpio = data;
 	struct drm_i915_private *dev_priv = gpio->dev_priv;
 	u32 reserved = get_reserved(gpio);
-	I915_WRITE(gpio->reg, reserved | GPIO_CLOCK_DIR_MASK);
-	I915_WRITE(gpio->reg, reserved);
-	return (I915_READ(gpio->reg) & GPIO_CLOCK_VAL_IN) != 0;
+	I915_WRITE_NOTRACE(gpio->reg, reserved | GPIO_CLOCK_DIR_MASK);
+	I915_WRITE_NOTRACE(gpio->reg, reserved);
+	return (I915_READ_NOTRACE(gpio->reg) & GPIO_CLOCK_VAL_IN) != 0;
 }
 
 static int get_data(void *data)
@@ -106,9 +107,9 @@ static int get_data(void *data)
 	struct intel_gpio *gpio = data;
 	struct drm_i915_private *dev_priv = gpio->dev_priv;
 	u32 reserved = get_reserved(gpio);
-	I915_WRITE(gpio->reg, reserved | GPIO_DATA_DIR_MASK);
-	I915_WRITE(gpio->reg, reserved);
-	return (I915_READ(gpio->reg) & GPIO_DATA_VAL_IN) != 0;
+	I915_WRITE_NOTRACE(gpio->reg, reserved | GPIO_DATA_DIR_MASK);
+	I915_WRITE_NOTRACE(gpio->reg, reserved);
+	return (I915_READ_NOTRACE(gpio->reg) & GPIO_DATA_VAL_IN) != 0;
 }
 
 static void set_clock(void *data, int state_high)
@@ -124,7 +125,7 @@ static void set_clock(void *data, int st
 		clock_bits = GPIO_CLOCK_DIR_OUT | GPIO_CLOCK_DIR_MASK |
 			GPIO_CLOCK_VAL_MASK;
 
-	I915_WRITE(gpio->reg, reserved | clock_bits);
+	I915_WRITE_NOTRACE(gpio->reg, reserved | clock_bits);
 	POSTING_READ(gpio->reg);
 }
 
@@ -141,7 +142,7 @@ static void set_data(void *data, int sta
 		data_bits = GPIO_DATA_DIR_OUT | GPIO_DATA_DIR_MASK |
 			GPIO_DATA_VAL_MASK;
 
-	I915_WRITE(gpio->reg, reserved | data_bits);
+	I915_WRITE_NOTRACE(gpio->reg, reserved | data_bits);
 	POSTING_READ(gpio->reg);
 }
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/i915/intel_lvds.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/i915/intel_lvds.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/i915/intel_lvds.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/i915/intel_lvds.c	2011-03-14 21:20:32.000000000 -0400
@@ -106,7 +106,7 @@ static void intel_lvds_enable(struct int
 	I915_WRITE(ctl_reg, I915_READ(ctl_reg) | POWER_TARGET_ON);
 	POSTING_READ(lvds_reg);
 
-	intel_panel_set_backlight(dev, dev_priv->backlight_level);
+	intel_panel_enable_backlight(dev);
 }
 
 static void intel_lvds_disable(struct intel_lvds *intel_lvds)
@@ -123,8 +123,7 @@ static void intel_lvds_disable(struct in
 		lvds_reg = LVDS;
 	}
 
-	dev_priv->backlight_level = intel_panel_get_backlight(dev);
-	intel_panel_set_backlight(dev, 0);
+	intel_panel_disable_backlight(dev);
 
 	I915_WRITE(ctl_reg, I915_READ(ctl_reg) & ~POWER_TARGET_ON);
 
@@ -262,12 +261,6 @@ static bool intel_lvds_mode_fixup(struct
 		return true;
 	}
 
-	/* Make sure pre-965s set dither correctly */
-	if (INTEL_INFO(dev)->gen < 4) {
-		if (dev_priv->lvds_dither)
-			pfit_control |= PANEL_8TO6_DITHER_ENABLE;
-	}
-
 	/* Native modes don't need fitting */
 	if (adjusted_mode->hdisplay == mode->hdisplay &&
 	    adjusted_mode->vdisplay == mode->vdisplay)
@@ -304,14 +297,13 @@ static bool intel_lvds_mode_fixup(struct
 			u32 scaled_width = adjusted_mode->hdisplay * mode->vdisplay;
 			u32 scaled_height = mode->hdisplay * adjusted_mode->vdisplay;
 
-			pfit_control |= PFIT_ENABLE;
 			/* 965+ is easy, it does everything in hw */
 			if (scaled_width > scaled_height)
-				pfit_control |= PFIT_SCALING_PILLAR;
+				pfit_control |= PFIT_ENABLE | PFIT_SCALING_PILLAR;
 			else if (scaled_width < scaled_height)
-				pfit_control |= PFIT_SCALING_LETTER;
-			else
-				pfit_control |= PFIT_SCALING_AUTO;
+				pfit_control |= PFIT_ENABLE | PFIT_SCALING_LETTER;
+			else if (adjusted_mode->hdisplay != mode->hdisplay)
+				pfit_control |= PFIT_ENABLE | PFIT_SCALING_AUTO;
 		} else {
 			u32 scaled_width = adjusted_mode->hdisplay * mode->vdisplay;
 			u32 scaled_height = mode->hdisplay * adjusted_mode->vdisplay;
@@ -358,13 +350,17 @@ static bool intel_lvds_mode_fixup(struct
 		 * Full scaling, even if it changes the aspect ratio.
 		 * Fortunately this is all done for us in hw.
 		 */
-		pfit_control |= PFIT_ENABLE;
-		if (INTEL_INFO(dev)->gen >= 4)
-			pfit_control |= PFIT_SCALING_AUTO;
-		else
-			pfit_control |= (VERT_AUTO_SCALE | HORIZ_AUTO_SCALE |
-					 VERT_INTERP_BILINEAR |
-					 HORIZ_INTERP_BILINEAR);
+		if (mode->vdisplay != adjusted_mode->vdisplay ||
+		    mode->hdisplay != adjusted_mode->hdisplay) {
+			pfit_control |= PFIT_ENABLE;
+			if (INTEL_INFO(dev)->gen >= 4)
+				pfit_control |= PFIT_SCALING_AUTO;
+			else
+				pfit_control |= (VERT_AUTO_SCALE |
+						 VERT_INTERP_BILINEAR |
+						 HORIZ_AUTO_SCALE |
+						 HORIZ_INTERP_BILINEAR);
+		}
 		break;
 
 	default:
@@ -372,6 +368,16 @@ static bool intel_lvds_mode_fixup(struct
 	}
 
 out:
+	/* If not enabling scaling, be consistent and always use 0. */
+	if ((pfit_control & PFIT_ENABLE) == 0) {
+		pfit_control = 0;
+		pfit_pgm_ratios = 0;
+	}
+
+	/* Make sure pre-965 set dither correctly */
+	if (INTEL_INFO(dev)->gen < 4 && dev_priv->lvds_dither)
+		pfit_control |= PANEL_8TO6_DITHER_ENABLE;
+
 	if (pfit_control != intel_lvds->pfit_control ||
 	    pfit_pgm_ratios != intel_lvds->pfit_pgm_ratios) {
 		intel_lvds->pfit_control = pfit_control;
@@ -395,8 +401,6 @@ static void intel_lvds_prepare(struct dr
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_lvds *intel_lvds = to_intel_lvds(encoder);
 
-	dev_priv->backlight_level = intel_panel_get_backlight(dev);
-
 	/* We try to do the minimum that is necessary in order to unlock
 	 * the registers for mode setting.
 	 *
@@ -427,9 +431,6 @@ static void intel_lvds_commit(struct drm
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_lvds *intel_lvds = to_intel_lvds(encoder);
 
-	if (dev_priv->backlight_level == 0)
-		dev_priv->backlight_level = intel_panel_get_max_backlight(dev);
-
 	/* Undo any unlocking done in prepare to prevent accidental
 	 * adjustment of the registers.
 	 */
@@ -703,6 +704,14 @@ static const struct dmi_system_id intel_
 	},
 	{
 		.callback = intel_no_lvds_dmi_callback,
+		.ident = "AOpen i915GMm-HFS",
+		.matches = {
+			DMI_MATCH(DMI_BOARD_VENDOR, "AOpen"),
+			DMI_MATCH(DMI_BOARD_NAME, "i915GMm-HFS"),
+		},
+	},
+	{
+		.callback = intel_no_lvds_dmi_callback,
 		.ident = "Aopen i945GTt-VFA",
 		.matches = {
 			DMI_MATCH(DMI_PRODUCT_VERSION, "AO00001JW"),
@@ -914,6 +923,8 @@ bool intel_lvds_init(struct drm_device *
 
 	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);
 	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;
@@ -1019,10 +1030,18 @@ bool intel_lvds_init(struct drm_device *
 out:
 	if (HAS_PCH_SPLIT(dev)) {
 		u32 pwm;
-		/* make sure PWM is enabled */
+
+		pipe = (I915_READ(PCH_LVDS) & LVDS_PIPEB_SELECT) ? 1 : 0;
+
+		/* make sure PWM is enabled and locked to the LVDS pipe */
 		pwm = I915_READ(BLC_PWM_CPU_CTL2);
-		pwm |= (PWM_ENABLE | PWM_PIPE_B);
-		I915_WRITE(BLC_PWM_CPU_CTL2, pwm);
+		if (pipe == 0 && (pwm & PWM_PIPE_B))
+			I915_WRITE(BLC_PWM_CPU_CTL2, pwm & ~PWM_ENABLE);
+		if (pipe)
+			pwm |= PWM_PIPE_B;
+		else
+			pwm &= ~PWM_PIPE_B;
+		I915_WRITE(BLC_PWM_CPU_CTL2, pwm | PWM_ENABLE);
 
 		pwm = I915_READ(BLC_PWM_PCH_CTL1);
 		pwm |= PWM_PCH_ENABLE;
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/i915/intel_opregion.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/i915/intel_opregion.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/i915/intel_opregion.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/i915/intel_opregion.c	2011-03-14 21:20:32.000000000 -0400
@@ -26,6 +26,7 @@
  */
 
 #include <linux/acpi.h>
+#include <linux/acpi_io.h>
 #include <acpi/video.h>
 
 #include "drmP.h"
@@ -273,14 +274,8 @@ void intel_opregion_enable_asle(struct d
 	struct opregion_asle *asle = dev_priv->opregion.asle;
 
 	if (asle) {
-		if (IS_MOBILE(dev)) {
-			unsigned long irqflags;
-
-			spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
+		if (IS_MOBILE(dev))
 			intel_enable_asle(dev);
-			spin_unlock_irqrestore(&dev_priv->user_irq_lock,
-					       irqflags);
-		}
 
 		asle->tche = ASLE_ALS_EN | ASLE_BLC_EN | ASLE_PFIT_EN |
 			ASLE_PFMB_EN;
@@ -482,7 +477,7 @@ int intel_opregion_setup(struct drm_devi
 		return -ENOTSUPP;
 	}
 
-	base = ioremap(asls, OPREGION_SIZE);
+	base = acpi_os_ioremap(asls, OPREGION_SIZE);
 	if (!base)
 		return -ENOMEM;
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/i915/intel_overlay.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/i915/intel_overlay.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/i915/intel_overlay.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/i915/intel_overlay.c	2011-03-14 21:20:32.000000000 -0400
@@ -221,15 +221,16 @@ static int intel_overlay_do_wait_request
 	int ret;
 
 	BUG_ON(overlay->last_flip_req);
-	overlay->last_flip_req =
-		i915_add_request(dev, NULL, request, &dev_priv->render_ring);
-	if (overlay->last_flip_req == 0)
-		return -ENOMEM;
-
+	ret = i915_add_request(dev, NULL, request, LP_RING(dev_priv));
+	if (ret) {
+	    kfree(request);
+	    return ret;
+	}
+	overlay->last_flip_req = request->seqno;
 	overlay->flip_tail = tail;
 	ret = i915_do_wait_request(dev,
 				   overlay->last_flip_req, true,
-				   &dev_priv->render_ring);
+				   LP_RING(dev_priv));
 	if (ret)
 		return ret;
 
@@ -289,6 +290,7 @@ i830_deactivate_pipe_a(struct drm_device
 static int intel_overlay_on(struct intel_overlay *overlay)
 {
 	struct drm_device *dev = overlay->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct drm_i915_gem_request *request;
 	int pipe_a_quirk = 0;
 	int ret;
@@ -308,7 +310,12 @@ static int intel_overlay_on(struct intel
 		goto out;
 	}
 
-	BEGIN_LP_RING(4);
+	ret = BEGIN_LP_RING(4);
+	if (ret) {
+		kfree(request);
+		goto out;
+	}
+
 	OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_ON);
 	OUT_RING(overlay->flip_addr | OFC_UPDATE);
 	OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
@@ -332,6 +339,7 @@ static int intel_overlay_continue(struct
 	struct drm_i915_gem_request *request;
 	u32 flip_addr = overlay->flip_addr;
 	u32 tmp;
+	int ret;
 
 	BUG_ON(!overlay->active);
 
@@ -347,36 +355,44 @@ static int intel_overlay_continue(struct
 	if (tmp & (1 << 17))
 		DRM_DEBUG("overlay underrun, DOVSTA: %x\n", tmp);
 
-	BEGIN_LP_RING(2);
+	ret = BEGIN_LP_RING(2);
+	if (ret) {
+		kfree(request);
+		return ret;
+	}
 	OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE);
 	OUT_RING(flip_addr);
         ADVANCE_LP_RING();
 
-	overlay->last_flip_req =
-		i915_add_request(dev, NULL, request, &dev_priv->render_ring);
+	ret = i915_add_request(dev, NULL, request, LP_RING(dev_priv));
+	if (ret) {
+		kfree(request);
+		return ret;
+	}
+
+	overlay->last_flip_req = request->seqno;
 	return 0;
 }
 
 static void intel_overlay_release_old_vid_tail(struct intel_overlay *overlay)
 {
-	struct drm_gem_object *obj = &overlay->old_vid_bo->base;
+	struct drm_i915_gem_object *obj = overlay->old_vid_bo;
 
 	i915_gem_object_unpin(obj);
-	drm_gem_object_unreference(obj);
+	drm_gem_object_unreference(&obj->base);
 
 	overlay->old_vid_bo = NULL;
 }
 
 static void intel_overlay_off_tail(struct intel_overlay *overlay)
 {
-	struct drm_gem_object *obj;
+	struct drm_i915_gem_object *obj = overlay->vid_bo;
 
 	/* never have the overlay hw on without showing a frame */
 	BUG_ON(!overlay->vid_bo);
-	obj = &overlay->vid_bo->base;
 
 	i915_gem_object_unpin(obj);
-	drm_gem_object_unreference(obj);
+	drm_gem_object_unreference(&obj->base);
 	overlay->vid_bo = NULL;
 
 	overlay->crtc->overlay = NULL;
@@ -389,8 +405,10 @@ static int intel_overlay_off(struct inte
 			     bool interruptible)
 {
 	struct drm_device *dev = overlay->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
 	u32 flip_addr = overlay->flip_addr;
 	struct drm_i915_gem_request *request;
+	int ret;
 
 	BUG_ON(!overlay->active);
 
@@ -404,7 +422,11 @@ static int intel_overlay_off(struct inte
 	 * of the hw. Do it in both cases */
 	flip_addr |= OFC_UPDATE;
 
-	BEGIN_LP_RING(6);
+	ret = BEGIN_LP_RING(6);
+	if (ret) {
+		kfree(request);
+		return ret;
+	}
 	/* wait for overlay to go idle */
 	OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE);
 	OUT_RING(flip_addr);
@@ -432,7 +454,7 @@ static int intel_overlay_recover_from_in
 		return 0;
 
 	ret = i915_do_wait_request(dev, overlay->last_flip_req,
-				   interruptible, &dev_priv->render_ring);
+				   interruptible, LP_RING(dev_priv));
 	if (ret)
 		return ret;
 
@@ -467,7 +489,12 @@ static int intel_overlay_release_old_vid
 		if (request == NULL)
 			return -ENOMEM;
 
-		BEGIN_LP_RING(2);
+		ret = BEGIN_LP_RING(2);
+		if (ret) {
+			kfree(request);
+			return ret;
+		}
+
 		OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
 		OUT_RING(MI_NOOP);
 		ADVANCE_LP_RING();
@@ -736,13 +763,12 @@ static u32 overlay_cmd_reg(struct put_im
 }
 
 static int intel_overlay_do_put_image(struct intel_overlay *overlay,
-				      struct drm_gem_object *new_bo,
+				      struct drm_i915_gem_object *new_bo,
 				      struct put_image_params *params)
 {
 	int ret, tmp_width;
 	struct overlay_registers *regs;
 	bool scale_changed = false;
-	struct drm_i915_gem_object *bo_priv = to_intel_bo(new_bo);
 	struct drm_device *dev = overlay->dev;
 
 	BUG_ON(!mutex_is_locked(&dev->struct_mutex));
@@ -753,7 +779,7 @@ static int intel_overlay_do_put_image(st
 	if (ret != 0)
 		return ret;
 
-	ret = i915_gem_object_pin(new_bo, PAGE_SIZE);
+	ret = i915_gem_object_pin(new_bo, PAGE_SIZE, true);
 	if (ret != 0)
 		return ret;
 
@@ -761,6 +787,10 @@ static int intel_overlay_do_put_image(st
 	if (ret != 0)
 		goto out_unpin;
 
+	ret = i915_gem_object_put_fence(new_bo);
+	if (ret)
+		goto out_unpin;
+
 	if (!overlay->active) {
 		regs = intel_overlay_map_regs(overlay);
 		if (!regs) {
@@ -797,7 +827,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 = bo_priv->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) {
@@ -811,8 +841,8 @@ static int intel_overlay_do_put_image(st
 				      params->src_w/uv_hscale);
 		regs->SWIDTHSW |= max_t(u32, tmp_U, tmp_V) << 16;
 		regs->SHEIGHT |= (params->src_h/uv_vscale) << 16;
-		regs->OBUF_0U = bo_priv->gtt_offset + params->offset_U;
-		regs->OBUF_0V = bo_priv->gtt_offset + params->offset_V;
+		regs->OBUF_0U = new_bo->gtt_offset + params->offset_U;
+		regs->OBUF_0V = new_bo->gtt_offset + params->offset_V;
 		regs->OSTRIDE |= params->stride_UV << 16;
 	}
 
@@ -829,7 +859,7 @@ static int intel_overlay_do_put_image(st
 		goto out_unpin;
 
 	overlay->old_vid_bo = overlay->vid_bo;
-	overlay->vid_bo = to_intel_bo(new_bo);
+	overlay->vid_bo = new_bo;
 
 	return 0;
 
@@ -942,7 +972,7 @@ static int check_overlay_scaling(struct
 
 static int check_overlay_src(struct drm_device *dev,
 			     struct drm_intel_overlay_put_image *rec,
-			     struct drm_gem_object *new_bo)
+			     struct drm_i915_gem_object *new_bo)
 {
 	int uv_hscale = uv_hsubsampling(rec->flags);
 	int uv_vscale = uv_vsubsampling(rec->flags);
@@ -1027,7 +1057,7 @@ static int check_overlay_src(struct drm_
 			return -EINVAL;
 
 		tmp = rec->stride_Y*rec->src_height;
-		if (rec->offset_Y + tmp > new_bo->size)
+		if (rec->offset_Y + tmp > new_bo->base.size)
 			return -EINVAL;
 		break;
 
@@ -1038,12 +1068,12 @@ static int check_overlay_src(struct drm_
 			return -EINVAL;
 
 		tmp = rec->stride_Y * rec->src_height;
-		if (rec->offset_Y + tmp > new_bo->size)
+		if (rec->offset_Y + tmp > new_bo->base.size)
 			return -EINVAL;
 
 		tmp = rec->stride_UV * (rec->src_height / uv_vscale);
-		if (rec->offset_U + tmp > new_bo->size ||
-		    rec->offset_V + tmp > new_bo->size)
+		if (rec->offset_U + tmp > new_bo->base.size ||
+		    rec->offset_V + tmp > new_bo->base.size)
 			return -EINVAL;
 		break;
 	}
@@ -1086,7 +1116,7 @@ int intel_overlay_put_image(struct drm_d
 	struct intel_overlay *overlay;
 	struct drm_mode_object *drmmode_obj;
 	struct intel_crtc *crtc;
-	struct drm_gem_object *new_bo;
+	struct drm_i915_gem_object *new_bo;
 	struct put_image_params *params;
 	int ret;
 
@@ -1125,8 +1155,8 @@ int intel_overlay_put_image(struct drm_d
 	}
 	crtc = to_intel_crtc(obj_to_crtc(drmmode_obj));
 
-	new_bo = drm_gem_object_lookup(dev, file_priv,
-				       put_image_rec->bo_handle);
+	new_bo = to_intel_bo(drm_gem_object_lookup(dev, file_priv,
+						   put_image_rec->bo_handle));
 	if (!new_bo) {
 		ret = -ENOENT;
 		goto out_free;
@@ -1135,6 +1165,12 @@ int intel_overlay_put_image(struct drm_d
 	mutex_lock(&dev->mode_config.mutex);
 	mutex_lock(&dev->struct_mutex);
 
+	if (new_bo->tiling_mode) {
+		DRM_ERROR("buffer used for overlay image can not be tiled\n");
+		ret = -EINVAL;
+		goto out_unlock;
+	}
+
 	ret = intel_overlay_recover_from_interrupt(overlay, true);
 	if (ret != 0)
 		goto out_unlock;
@@ -1217,7 +1253,7 @@ int intel_overlay_put_image(struct drm_d
 out_unlock:
 	mutex_unlock(&dev->struct_mutex);
 	mutex_unlock(&dev->mode_config.mutex);
-	drm_gem_object_unreference_unlocked(new_bo);
+	drm_gem_object_unreference_unlocked(&new_bo->base);
 out_free:
 	kfree(params);
 
@@ -1370,7 +1406,7 @@ void intel_setup_overlay(struct drm_devi
 {
         drm_i915_private_t *dev_priv = dev->dev_private;
 	struct intel_overlay *overlay;
-	struct drm_gem_object *reg_bo;
+	struct drm_i915_gem_object *reg_bo;
 	struct overlay_registers *regs;
 	int ret;
 
@@ -1385,7 +1421,7 @@ void intel_setup_overlay(struct drm_devi
 	reg_bo = i915_gem_alloc_object(dev, PAGE_SIZE);
 	if (!reg_bo)
 		goto out_free;
-	overlay->reg_bo = to_intel_bo(reg_bo);
+	overlay->reg_bo = reg_bo;
 
 	if (OVERLAY_NEEDS_PHYSICAL(dev)) {
 		ret = i915_gem_attach_phys_object(dev, reg_bo,
@@ -1395,14 +1431,14 @@ void intel_setup_overlay(struct drm_devi
                         DRM_ERROR("failed to attach phys overlay regs\n");
                         goto out_free_bo;
                 }
-		overlay->flip_addr = overlay->reg_bo->phys_obj->handle->busaddr;
+		overlay->flip_addr = reg_bo->phys_obj->handle->busaddr;
 	} else {
-		ret = i915_gem_object_pin(reg_bo, PAGE_SIZE);
+		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;
                 }
-		overlay->flip_addr = overlay->reg_bo->gtt_offset;
+		overlay->flip_addr = reg_bo->gtt_offset;
 
 		ret = i915_gem_object_set_to_gtt_domain(reg_bo, true);
 		if (ret) {
@@ -1434,7 +1470,7 @@ void intel_setup_overlay(struct drm_devi
 out_unpin_bo:
 	i915_gem_object_unpin(reg_bo);
 out_free_bo:
-	drm_gem_object_unreference(reg_bo);
+	drm_gem_object_unreference(&reg_bo->base);
 out_free:
 	kfree(overlay);
 	return;
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/i915/intel_panel.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/i915/intel_panel.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/i915/intel_panel.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/i915/intel_panel.c	2011-03-14 21:20:32.000000000 -0400
@@ -125,15 +125,55 @@ static int is_backlight_combination_mode
 	return 0;
 }
 
+static u32 i915_read_blc_pwm_ctl(struct drm_i915_private *dev_priv)
+{
+	u32 val;
+
+	/* Restore the CTL value if it lost, e.g. GPU reset */
+
+	if (HAS_PCH_SPLIT(dev_priv->dev)) {
+		val = I915_READ(BLC_PWM_PCH_CTL2);
+		if (dev_priv->saveBLC_PWM_CTL2 == 0) {
+			dev_priv->saveBLC_PWM_CTL2 = val;
+		} else if (val == 0) {
+			I915_WRITE(BLC_PWM_PCH_CTL2,
+				   dev_priv->saveBLC_PWM_CTL);
+			val = dev_priv->saveBLC_PWM_CTL;
+		}
+	} else {
+		val = I915_READ(BLC_PWM_CTL);
+		if (dev_priv->saveBLC_PWM_CTL == 0) {
+			dev_priv->saveBLC_PWM_CTL = val;
+			dev_priv->saveBLC_PWM_CTL2 = I915_READ(BLC_PWM_CTL2);
+		} else if (val == 0) {
+			I915_WRITE(BLC_PWM_CTL,
+				   dev_priv->saveBLC_PWM_CTL);
+			I915_WRITE(BLC_PWM_CTL2,
+				   dev_priv->saveBLC_PWM_CTL2);
+			val = dev_priv->saveBLC_PWM_CTL;
+		}
+	}
+
+	return val;
+}
+
 u32 intel_panel_get_max_backlight(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	u32 max;
 
+	max = i915_read_blc_pwm_ctl(dev_priv);
+	if (max == 0) {
+		/* XXX add code here to query mode clock or hardware clock
+		 * and program max PWM appropriately.
+		 */
+		printk_once(KERN_WARNING "fixme: max PWM is zero.\n");
+		return 1;
+	}
+
 	if (HAS_PCH_SPLIT(dev)) {
-		max = I915_READ(BLC_PWM_PCH_CTL2) >> 16;
+		max >>= 16;
 	} else {
-		max = I915_READ(BLC_PWM_CTL);
 		if (IS_PINEVIEW(dev)) {
 			max >>= 17;
 		} else {
@@ -146,14 +186,6 @@ u32 intel_panel_get_max_backlight(struct
 			max *= 0xff;
 	}
 
-	if (max == 0) {
-		/* XXX add code here to query mode clock or hardware clock
-		 * and program max PWM appropriately.
-		 */
-		DRM_ERROR("fixme: max PWM is zero.\n");
-		max = 1;
-	}
-
 	DRM_DEBUG_DRIVER("max backlight PWM = %d\n", max);
 	return max;
 }
@@ -176,7 +208,6 @@ u32 intel_panel_get_backlight(struct drm
 			val &= ~1;
 			pci_read_config_byte(dev->pdev, PCI_LBPC, &lbpc);
 			val *= lbpc;
-			val >>= 1;
 		}
 	}
 
@@ -203,11 +234,11 @@ void intel_panel_set_backlight(struct dr
 
 	if (is_backlight_combination_mode(dev)){
 		u32 max = intel_panel_get_max_backlight(dev);
-		u8 lpbc;
+		u8 lbpc;
 
-		lpbc = level * 0xfe / max + 1;
-		level /= lpbc;
-		pci_write_config_byte(dev->pdev, PCI_LBPC, lpbc);
+		lbpc = level * 0xfe / max + 1;
+		level /= lbpc;
+		pci_write_config_byte(dev->pdev, PCI_LBPC, lbpc);
 	}
 
 	tmp = I915_READ(BLC_PWM_CTL);
@@ -218,3 +249,34 @@ void intel_panel_set_backlight(struct dr
 		tmp &= ~BACKLIGHT_DUTY_CYCLE_MASK;
 	I915_WRITE(BLC_PWM_CTL, tmp | level);
 }
+
+void intel_panel_disable_backlight(struct drm_device *dev)
+{
+	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;
+	}
+
+	intel_panel_set_backlight(dev, 0);
+}
+
+void intel_panel_enable_backlight(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	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;
+}
+
+void intel_panel_setup_backlight(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	dev_priv->backlight_level = intel_panel_get_backlight(dev);
+	dev_priv->backlight_enabled = dev_priv->backlight_level != 0;
+}
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/i915/intel_ringbuffer.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/i915/intel_ringbuffer.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/i915/intel_ringbuffer.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/i915/intel_ringbuffer.c	2011-03-14 21:20:32.000000000 -0400
@@ -34,6 +34,14 @@
 #include "i915_trace.h"
 #include "intel_drv.h"
 
+static inline int ring_space(struct intel_ring_buffer *ring)
+{
+	int space = (ring->head & HEAD_ADDR) - (ring->tail + 8);
+	if (space < 0)
+		space += ring->size;
+	return space;
+}
+
 static u32 i915_gem_get_seqno(struct drm_device *dev)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
@@ -48,14 +56,15 @@ static u32 i915_gem_get_seqno(struct drm
 	return seqno;
 }
 
-static void
-render_ring_flush(struct drm_device *dev,
-		  struct intel_ring_buffer *ring,
+static int
+render_ring_flush(struct intel_ring_buffer *ring,
 		  u32	invalidate_domains,
 		  u32	flush_domains)
 {
+	struct drm_device *dev = ring->dev;
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	u32 cmd;
+	int ret;
 
 #if WATCH_EXEC
 	DRM_INFO("%s: invalidate %08x flush %08x\n", __func__,
@@ -109,49 +118,54 @@ render_ring_flush(struct drm_device *dev
 		if (invalidate_domains & I915_GEM_DOMAIN_INSTRUCTION)
 			cmd |= MI_EXE_FLUSH;
 
+		if (invalidate_domains & I915_GEM_DOMAIN_COMMAND &&
+		    (IS_G4X(dev) || IS_GEN5(dev)))
+			cmd |= MI_INVALIDATE_ISP;
+
 #if WATCH_EXEC
 		DRM_INFO("%s: queue flush %08x to ring\n", __func__, cmd);
 #endif
-		intel_ring_begin(dev, ring, 2);
-		intel_ring_emit(dev, ring, cmd);
-		intel_ring_emit(dev, ring, MI_NOOP);
-		intel_ring_advance(dev, ring);
+		ret = intel_ring_begin(ring, 2);
+		if (ret)
+			return ret;
+
+		intel_ring_emit(ring, cmd);
+		intel_ring_emit(ring, MI_NOOP);
+		intel_ring_advance(ring);
 	}
+
+	return 0;
 }
 
-static void ring_write_tail(struct drm_device *dev,
-			    struct intel_ring_buffer *ring,
+static void ring_write_tail(struct intel_ring_buffer *ring,
 			    u32 value)
 {
-	drm_i915_private_t *dev_priv = dev->dev_private;
+	drm_i915_private_t *dev_priv = ring->dev->dev_private;
 	I915_WRITE_TAIL(ring, value);
 }
 
-u32 intel_ring_get_active_head(struct drm_device *dev,
-			       struct intel_ring_buffer *ring)
+u32 intel_ring_get_active_head(struct intel_ring_buffer *ring)
 {
-	drm_i915_private_t *dev_priv = dev->dev_private;
-	u32 acthd_reg = INTEL_INFO(dev)->gen >= 4 ?
+	drm_i915_private_t *dev_priv = ring->dev->dev_private;
+	u32 acthd_reg = INTEL_INFO(ring->dev)->gen >= 4 ?
 			RING_ACTHD(ring->mmio_base) : ACTHD;
 
 	return I915_READ(acthd_reg);
 }
 
-static int init_ring_common(struct drm_device *dev,
-			    struct intel_ring_buffer *ring)
+static int init_ring_common(struct intel_ring_buffer *ring)
 {
+	drm_i915_private_t *dev_priv = ring->dev->dev_private;
+	struct drm_i915_gem_object *obj = ring->obj;
 	u32 head;
-	drm_i915_private_t *dev_priv = dev->dev_private;
-	struct drm_i915_gem_object *obj_priv;
-	obj_priv = to_intel_bo(ring->gem_object);
 
 	/* Stop the ring if it's running. */
 	I915_WRITE_CTL(ring, 0);
 	I915_WRITE_HEAD(ring, 0);
-	ring->write_tail(dev, ring, 0);
+	ring->write_tail(ring, 0);
 
 	/* Initialize the ring. */
-	I915_WRITE_START(ring, obj_priv->gtt_offset);
+	I915_WRITE_START(ring, obj->gtt_offset);
 	head = I915_READ_HEAD(ring) & HEAD_ADDR;
 
 	/* G45 ring initialization fails to reset head to zero */
@@ -178,12 +192,13 @@ static int init_ring_common(struct drm_d
 	}
 
 	I915_WRITE_CTL(ring,
-			((ring->gem_object->size - PAGE_SIZE) & RING_NR_PAGES)
+			((ring->size - PAGE_SIZE) & RING_NR_PAGES)
 			| RING_REPORT_64K | RING_VALID);
 
-	head = I915_READ_HEAD(ring) & HEAD_ADDR;
 	/* If the head is still not zero, the ring is dead */
-	if (head != 0) {
+	if ((I915_READ_CTL(ring) & RING_VALID) == 0 ||
+	    I915_READ_START(ring) != obj->gtt_offset ||
+	    (I915_READ_HEAD(ring) & HEAD_ADDR) != 0) {
 		DRM_ERROR("%s initialization failed "
 				"ctl %08x head %08x tail %08x start %08x\n",
 				ring->name,
@@ -194,344 +209,569 @@ static int init_ring_common(struct drm_d
 		return -EIO;
 	}
 
-	if (!drm_core_check_feature(dev, DRIVER_MODESET))
-		i915_kernel_lost_context(dev);
+	if (!drm_core_check_feature(ring->dev, DRIVER_MODESET))
+		i915_kernel_lost_context(ring->dev);
 	else {
-		ring->head = I915_READ_HEAD(ring) & HEAD_ADDR;
+		ring->head = I915_READ_HEAD(ring);
 		ring->tail = I915_READ_TAIL(ring) & TAIL_ADDR;
-		ring->space = ring->head - (ring->tail + 8);
-		if (ring->space < 0)
-			ring->space += ring->size;
+		ring->space = ring_space(ring);
 	}
+
 	return 0;
 }
 
-static int init_render_ring(struct drm_device *dev,
-			    struct intel_ring_buffer *ring)
+/*
+ * 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)
 {
-	drm_i915_private_t *dev_priv = dev->dev_private;
-	int ret = init_ring_common(dev, ring);
-	int mode;
+	struct pipe_control *pc;
+	struct drm_i915_gem_object *obj;
+	int ret;
+
+	if (ring->private)
+		return 0;
+
+	pc = kmalloc(sizeof(*pc), GFP_KERNEL);
+	if (!pc)
+		return -ENOMEM;
+
+	obj = i915_gem_alloc_object(ring->dev, 4096);
+	if (obj == NULL) {
+		DRM_ERROR("Failed to allocate seqno page\n");
+		ret = -ENOMEM;
+		goto err;
+	}
+	obj->agp_type = AGP_USER_CACHED_MEMORY;
+
+	ret = i915_gem_object_pin(obj, 4096, true);
+	if (ret)
+		goto err_unref;
+
+	pc->gtt_offset = obj->gtt_offset;
+	pc->cpu_page =  kmap(obj->pages[0]);
+	if (pc->cpu_page == NULL)
+		goto err_unpin;
+
+	pc->obj = obj;
+	ring->private = pc;
+	return 0;
+
+err_unpin:
+	i915_gem_object_unpin(obj);
+err_unref:
+	drm_gem_object_unreference(&obj->base);
+err:
+	kfree(pc);
+	return ret;
+}
+
+static void
+cleanup_pipe_control(struct intel_ring_buffer *ring)
+{
+	struct pipe_control *pc = ring->private;
+	struct drm_i915_gem_object *obj;
+
+	if (!ring->private)
+		return;
+
+	obj = pc->obj;
+	kunmap(obj->pages[0]);
+	i915_gem_object_unpin(obj);
+	drm_gem_object_unreference(&obj->base);
+
+	kfree(pc);
+	ring->private = NULL;
+}
+
+static int init_render_ring(struct intel_ring_buffer *ring)
+{
+	struct drm_device *dev = ring->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	int ret = init_ring_common(ring);
 
 	if (INTEL_INFO(dev)->gen > 3) {
-		mode = VS_TIMER_DISPATCH << 16 | VS_TIMER_DISPATCH;
+		int mode = VS_TIMER_DISPATCH << 16 | VS_TIMER_DISPATCH;
 		if (IS_GEN6(dev))
 			mode |= MI_FLUSH_ENABLE << 16 | MI_FLUSH_ENABLE;
 		I915_WRITE(MI_MODE, mode);
 	}
+
+	if (INTEL_INFO(dev)->gen >= 6) {
+	} else if (IS_GEN5(dev)) {
+		ret = init_pipe_control(ring);
+		if (ret)
+			return ret;
+	}
+
 	return ret;
 }
 
-#define PIPE_CONTROL_FLUSH(addr)					\
+static void render_ring_cleanup(struct intel_ring_buffer *ring)
+{
+	if (!ring->private)
+		return;
+
+	cleanup_pipe_control(ring);
+}
+
+static void
+update_semaphore(struct intel_ring_buffer *ring, int i, u32 seqno)
+{
+	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, seqno);
+	intel_ring_emit(ring,
+			RING_SYNC_0(dev_priv->ring[id].mmio_base) + 4*i);
+}
+
+static int
+gen6_add_request(struct intel_ring_buffer *ring,
+		 u32 *result)
+{
+	u32 seqno;
+	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);
+
+	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, 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,
+		u32 seqno)
+{
+	int ret;
+
+	ret = intel_ring_begin(ring, 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);
+
+	return 0;
+}
+
+#define PIPE_CONTROL_FLUSH(ring__, addr__)					\
 do {									\
-	OUT_RING(GFX_OP_PIPE_CONTROL | PIPE_CONTROL_QW_WRITE |		\
+	intel_ring_emit(ring__, GFX_OP_PIPE_CONTROL | PIPE_CONTROL_QW_WRITE |		\
 		 PIPE_CONTROL_DEPTH_STALL | 2);				\
-	OUT_RING(addr | PIPE_CONTROL_GLOBAL_GTT);			\
-	OUT_RING(0);							\
-	OUT_RING(0);							\
+	intel_ring_emit(ring__, (addr__) | PIPE_CONTROL_GLOBAL_GTT);			\
+	intel_ring_emit(ring__, 0);							\
+	intel_ring_emit(ring__, 0);							\
 } while (0)
 
-/**
- * Creates a new sequence number, emitting a write of it to the status page
- * plus an interrupt, which will trigger i915_user_interrupt_handler.
- *
- * Must be called with struct_lock held.
- *
- * Returned sequence numbers are nonzero on success.
- */
-static u32
-render_ring_add_request(struct drm_device *dev,
-			struct intel_ring_buffer *ring,
-			u32 flush_domains)
+static int
+pc_render_add_request(struct intel_ring_buffer *ring,
+		      u32 *result)
 {
-	drm_i915_private_t *dev_priv = dev->dev_private;
-	u32 seqno;
+	struct drm_device *dev = ring->dev;
+	u32 seqno = i915_gem_get_seqno(dev);
+	struct pipe_control *pc = ring->private;
+	u32 scratch_addr = pc->gtt_offset + 128;
+	int ret;
 
-	seqno = i915_gem_get_seqno(dev);
+	/* For Ironlake, MI_USER_INTERRUPT was deprecated and apparently
+	 * incoherent with writes to memory, i.e. completely fubar,
+	 * so we need to use PIPE_NOTIFY instead.
+	 *
+	 * However, we also need to workaround the qword write
+	 * incoherence by flushing the 6 PIPE_NOTIFY buffers out to
+	 * memory before requesting an interrupt.
+	 */
+	ret = intel_ring_begin(ring, 32);
+	if (ret)
+		return ret;
 
-	if (IS_GEN6(dev)) {
-		BEGIN_LP_RING(6);
-		OUT_RING(GFX_OP_PIPE_CONTROL | 3);
-		OUT_RING(PIPE_CONTROL_QW_WRITE |
-			 PIPE_CONTROL_WC_FLUSH | PIPE_CONTROL_IS_FLUSH |
-			 PIPE_CONTROL_NOTIFY);
-		OUT_RING(dev_priv->seqno_gfx_addr | PIPE_CONTROL_GLOBAL_GTT);
-		OUT_RING(seqno);
-		OUT_RING(0);
-		OUT_RING(0);
-		ADVANCE_LP_RING();
-	} else if (HAS_PIPE_CONTROL(dev)) {
-		u32 scratch_addr = dev_priv->seqno_gfx_addr + 128;
+	intel_ring_emit(ring, GFX_OP_PIPE_CONTROL | PIPE_CONTROL_QW_WRITE |
+			PIPE_CONTROL_WC_FLUSH | PIPE_CONTROL_TC_FLUSH);
+	intel_ring_emit(ring, pc->gtt_offset | PIPE_CONTROL_GLOBAL_GTT);
+	intel_ring_emit(ring, seqno);
+	intel_ring_emit(ring, 0);
+	PIPE_CONTROL_FLUSH(ring, scratch_addr);
+	scratch_addr += 128; /* write to separate cachelines */
+	PIPE_CONTROL_FLUSH(ring, scratch_addr);
+	scratch_addr += 128;
+	PIPE_CONTROL_FLUSH(ring, scratch_addr);
+	scratch_addr += 128;
+	PIPE_CONTROL_FLUSH(ring, scratch_addr);
+	scratch_addr += 128;
+	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 |
+			PIPE_CONTROL_NOTIFY);
+	intel_ring_emit(ring, pc->gtt_offset | PIPE_CONTROL_GLOBAL_GTT);
+	intel_ring_emit(ring, seqno);
+	intel_ring_emit(ring, 0);
+	intel_ring_advance(ring);
 
-		/*
-		 * Workaround qword write incoherence by flushing the
-		 * PIPE_NOTIFY buffers out to memory before requesting
-		 * an interrupt.
-		 */
-		BEGIN_LP_RING(32);
-		OUT_RING(GFX_OP_PIPE_CONTROL | PIPE_CONTROL_QW_WRITE |
-			 PIPE_CONTROL_WC_FLUSH | PIPE_CONTROL_TC_FLUSH);
-		OUT_RING(dev_priv->seqno_gfx_addr | PIPE_CONTROL_GLOBAL_GTT);
-		OUT_RING(seqno);
-		OUT_RING(0);
-		PIPE_CONTROL_FLUSH(scratch_addr);
-		scratch_addr += 128; /* write to separate cachelines */
-		PIPE_CONTROL_FLUSH(scratch_addr);
-		scratch_addr += 128;
-		PIPE_CONTROL_FLUSH(scratch_addr);
-		scratch_addr += 128;
-		PIPE_CONTROL_FLUSH(scratch_addr);
-		scratch_addr += 128;
-		PIPE_CONTROL_FLUSH(scratch_addr);
-		scratch_addr += 128;
-		PIPE_CONTROL_FLUSH(scratch_addr);
-		OUT_RING(GFX_OP_PIPE_CONTROL | PIPE_CONTROL_QW_WRITE |
-			 PIPE_CONTROL_WC_FLUSH | PIPE_CONTROL_TC_FLUSH |
-			 PIPE_CONTROL_NOTIFY);
-		OUT_RING(dev_priv->seqno_gfx_addr | PIPE_CONTROL_GLOBAL_GTT);
-		OUT_RING(seqno);
-		OUT_RING(0);
-		ADVANCE_LP_RING();
-	} else {
-		BEGIN_LP_RING(4);
-		OUT_RING(MI_STORE_DWORD_INDEX);
-		OUT_RING(I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT);
-		OUT_RING(seqno);
+	*result = seqno;
+	return 0;
+}
 
-		OUT_RING(MI_USER_INTERRUPT);
-		ADVANCE_LP_RING();
-	}
-	return seqno;
+static int
+render_ring_add_request(struct intel_ring_buffer *ring,
+			u32 *result)
+{
+	struct drm_device *dev = ring->dev;
+	u32 seqno = i915_gem_get_seqno(dev);
+	int ret;
+
+	ret = intel_ring_begin(ring, 4);
+	if (ret)
+		return ret;
+
+	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, MI_USER_INTERRUPT);
+	intel_ring_advance(ring);
+
+	*result = seqno;
+	return 0;
 }
 
 static u32
-render_ring_get_seqno(struct drm_device *dev,
-		      struct intel_ring_buffer *ring)
+ring_get_seqno(struct intel_ring_buffer *ring)
 {
-	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-	if (HAS_PIPE_CONTROL(dev))
-		return ((volatile u32 *)(dev_priv->seqno_page))[0];
-	else
-		return intel_read_status_page(ring, I915_GEM_HWS_INDEX);
+	return intel_read_status_page(ring, I915_GEM_HWS_INDEX);
+}
+
+static u32
+pc_render_get_seqno(struct intel_ring_buffer *ring)
+{
+	struct pipe_control *pc = ring->private;
+	return pc->cpu_page[0];
 }
 
 static void
-render_ring_get_user_irq(struct drm_device *dev,
-			 struct intel_ring_buffer *ring)
+ironlake_enable_irq(drm_i915_private_t *dev_priv, u32 mask)
 {
-	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-	unsigned long irqflags;
+	dev_priv->gt_irq_mask &= ~mask;
+	I915_WRITE(GTIMR, dev_priv->gt_irq_mask);
+	POSTING_READ(GTIMR);
+}
 
-	spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
-	if (dev->irq_enabled && (++ring->user_irq_refcount == 1)) {
+static void
+ironlake_disable_irq(drm_i915_private_t *dev_priv, u32 mask)
+{
+	dev_priv->gt_irq_mask |= mask;
+	I915_WRITE(GTIMR, dev_priv->gt_irq_mask);
+	POSTING_READ(GTIMR);
+}
+
+static void
+i915_enable_irq(drm_i915_private_t *dev_priv, u32 mask)
+{
+	dev_priv->irq_mask &= ~mask;
+	I915_WRITE(IMR, dev_priv->irq_mask);
+	POSTING_READ(IMR);
+}
+
+static void
+i915_disable_irq(drm_i915_private_t *dev_priv, u32 mask)
+{
+	dev_priv->irq_mask |= mask;
+	I915_WRITE(IMR, dev_priv->irq_mask);
+	POSTING_READ(IMR);
+}
+
+static bool
+render_ring_get_irq(struct intel_ring_buffer *ring)
+{
+	struct drm_device *dev = ring->dev;
+	drm_i915_private_t *dev_priv = dev->dev_private;
+
+	if (!dev->irq_enabled)
+		return false;
+
+	spin_lock(&ring->irq_lock);
+	if (ring->irq_refcount++ == 0) {
 		if (HAS_PCH_SPLIT(dev))
-			ironlake_enable_graphics_irq(dev_priv, GT_PIPE_NOTIFY);
+			ironlake_enable_irq(dev_priv,
+					    GT_PIPE_NOTIFY | GT_USER_INTERRUPT);
 		else
 			i915_enable_irq(dev_priv, I915_USER_INTERRUPT);
 	}
-	spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags);
+	spin_unlock(&ring->irq_lock);
+
+	return true;
 }
 
 static void
-render_ring_put_user_irq(struct drm_device *dev,
-			 struct intel_ring_buffer *ring)
+render_ring_put_irq(struct intel_ring_buffer *ring)
 {
-	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-	unsigned long irqflags;
+	struct drm_device *dev = ring->dev;
+	drm_i915_private_t *dev_priv = dev->dev_private;
 
-	spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
-	BUG_ON(dev->irq_enabled && ring->user_irq_refcount <= 0);
-	if (dev->irq_enabled && (--ring->user_irq_refcount == 0)) {
+	spin_lock(&ring->irq_lock);
+	if (--ring->irq_refcount == 0) {
 		if (HAS_PCH_SPLIT(dev))
-			ironlake_disable_graphics_irq(dev_priv, GT_PIPE_NOTIFY);
+			ironlake_disable_irq(dev_priv,
+					     GT_USER_INTERRUPT |
+					     GT_PIPE_NOTIFY);
 		else
 			i915_disable_irq(dev_priv, I915_USER_INTERRUPT);
 	}
-	spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags);
+	spin_unlock(&ring->irq_lock);
 }
 
-void intel_ring_setup_status_page(struct drm_device *dev,
-				  struct intel_ring_buffer *ring)
+void intel_ring_setup_status_page(struct intel_ring_buffer *ring)
 {
-	drm_i915_private_t *dev_priv = dev->dev_private;
-	if (IS_GEN6(dev)) {
-		I915_WRITE(RING_HWS_PGA_GEN6(ring->mmio_base),
-			   ring->status_page.gfx_addr);
-		I915_READ(RING_HWS_PGA_GEN6(ring->mmio_base)); /* posting read */
-	} else {
-		I915_WRITE(RING_HWS_PGA(ring->mmio_base),
-			   ring->status_page.gfx_addr);
-		I915_READ(RING_HWS_PGA(ring->mmio_base)); /* posting read */
-	}
-
+	drm_i915_private_t *dev_priv = ring->dev->dev_private;
+	u32 mmio = IS_GEN6(ring->dev) ?
+		RING_HWS_PGA_GEN6(ring->mmio_base) :
+		RING_HWS_PGA(ring->mmio_base);
+	I915_WRITE(mmio, (u32)ring->status_page.gfx_addr);
+	POSTING_READ(mmio);
 }
 
-static void
-bsd_ring_flush(struct drm_device *dev,
-		struct intel_ring_buffer *ring,
-		u32     invalidate_domains,
-		u32     flush_domains)
+static int
+bsd_ring_flush(struct intel_ring_buffer *ring,
+	       u32     invalidate_domains,
+	       u32     flush_domains)
 {
-	intel_ring_begin(dev, ring, 2);
-	intel_ring_emit(dev, ring, MI_FLUSH);
-	intel_ring_emit(dev, ring, MI_NOOP);
-	intel_ring_advance(dev, ring);
-}
+	int ret;
 
-static int init_bsd_ring(struct drm_device *dev,
-			 struct intel_ring_buffer *ring)
-{
-	return init_ring_common(dev, ring);
+	if ((flush_domains & I915_GEM_DOMAIN_RENDER) == 0)
+		return 0;
+
+	ret = intel_ring_begin(ring, 2);
+	if (ret)
+		return ret;
+
+	intel_ring_emit(ring, MI_FLUSH);
+	intel_ring_emit(ring, MI_NOOP);
+	intel_ring_advance(ring);
+	return 0;
 }
 
-static u32
-ring_add_request(struct drm_device *dev,
-		 struct intel_ring_buffer *ring,
-		 u32 flush_domains)
+static int
+ring_add_request(struct intel_ring_buffer *ring,
+		 u32 *result)
 {
 	u32 seqno;
+	int ret;
 
-	seqno = i915_gem_get_seqno(dev);
+	ret = intel_ring_begin(ring, 4);
+	if (ret)
+		return ret;
 
-	intel_ring_begin(dev, ring, 4);
-	intel_ring_emit(dev, ring, MI_STORE_DWORD_INDEX);
-	intel_ring_emit(dev, ring,
-			I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT);
-	intel_ring_emit(dev, ring, seqno);
-	intel_ring_emit(dev, ring, MI_USER_INTERRUPT);
-	intel_ring_advance(dev, ring);
+	seqno = i915_gem_get_seqno(ring->dev);
+
+	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, MI_USER_INTERRUPT);
+	intel_ring_advance(ring);
 
 	DRM_DEBUG_DRIVER("%s %d\n", ring->name, seqno);
+	*result = seqno;
+	return 0;
+}
 
-	return seqno;
+static bool
+ring_get_irq(struct intel_ring_buffer *ring, u32 flag)
+{
+	struct drm_device *dev = ring->dev;
+	drm_i915_private_t *dev_priv = dev->dev_private;
+
+	if (!dev->irq_enabled)
+	       return false;
+
+	spin_lock(&ring->irq_lock);
+	if (ring->irq_refcount++ == 0)
+		ironlake_enable_irq(dev_priv, flag);
+	spin_unlock(&ring->irq_lock);
+
+	return true;
 }
 
 static void
-bsd_ring_get_user_irq(struct drm_device *dev,
-		      struct intel_ring_buffer *ring)
+ring_put_irq(struct intel_ring_buffer *ring, u32 flag)
 {
-	/* do nothing */
+	struct drm_device *dev = ring->dev;
+	drm_i915_private_t *dev_priv = dev->dev_private;
+
+	spin_lock(&ring->irq_lock);
+	if (--ring->irq_refcount == 0)
+		ironlake_disable_irq(dev_priv, flag);
+	spin_unlock(&ring->irq_lock);
 }
+
+static bool
+gen6_ring_get_irq(struct intel_ring_buffer *ring, u32 gflag, u32 rflag)
+{
+	struct drm_device *dev = ring->dev;
+	drm_i915_private_t *dev_priv = dev->dev_private;
+
+	if (!dev->irq_enabled)
+	       return false;
+
+	spin_lock(&ring->irq_lock);
+	if (ring->irq_refcount++ == 0) {
+		ring->irq_mask &= ~rflag;
+		I915_WRITE_IMR(ring, ring->irq_mask);
+		ironlake_enable_irq(dev_priv, gflag);
+	}
+	spin_unlock(&ring->irq_lock);
+
+	return true;
+}
+
 static void
-bsd_ring_put_user_irq(struct drm_device *dev,
-		      struct intel_ring_buffer *ring)
+gen6_ring_put_irq(struct intel_ring_buffer *ring, u32 gflag, u32 rflag)
 {
-	/* do nothing */
+	struct drm_device *dev = ring->dev;
+	drm_i915_private_t *dev_priv = dev->dev_private;
+
+	spin_lock(&ring->irq_lock);
+	if (--ring->irq_refcount == 0) {
+		ring->irq_mask |= rflag;
+		I915_WRITE_IMR(ring, ring->irq_mask);
+		ironlake_disable_irq(dev_priv, gflag);
+	}
+	spin_unlock(&ring->irq_lock);
 }
 
-static u32
-ring_status_page_get_seqno(struct drm_device *dev,
-			   struct intel_ring_buffer *ring)
+static bool
+bsd_ring_get_irq(struct intel_ring_buffer *ring)
 {
-	return intel_read_status_page(ring, I915_GEM_HWS_INDEX);
+	return ring_get_irq(ring, GT_BSD_USER_INTERRUPT);
+}
+static void
+bsd_ring_put_irq(struct intel_ring_buffer *ring)
+{
+	ring_put_irq(ring, GT_BSD_USER_INTERRUPT);
 }
 
 static int
-ring_dispatch_gem_execbuffer(struct drm_device *dev,
-			     struct intel_ring_buffer *ring,
-			     struct drm_i915_gem_execbuffer2 *exec,
-			     struct drm_clip_rect *cliprects,
-			     uint64_t exec_offset)
+ring_dispatch_execbuffer(struct intel_ring_buffer *ring, u32 offset, u32 length)
 {
-	uint32_t exec_start;
-	exec_start = (uint32_t) exec_offset + exec->batch_start_offset;
-	intel_ring_begin(dev, ring, 2);
-	intel_ring_emit(dev, ring, MI_BATCH_BUFFER_START |
-			(2 << 6) | MI_BATCH_NON_SECURE_I965);
-	intel_ring_emit(dev, ring, exec_start);
-	intel_ring_advance(dev, ring);
+	int ret;
+
+	ret = intel_ring_begin(ring, 2);
+	if (ret)
+		return ret;
+
+	intel_ring_emit(ring,
+			MI_BATCH_BUFFER_START | (2 << 6) |
+			MI_BATCH_NON_SECURE_I965);
+	intel_ring_emit(ring, offset);
+	intel_ring_advance(ring);
+
 	return 0;
 }
 
 static int
-render_ring_dispatch_gem_execbuffer(struct drm_device *dev,
-				    struct intel_ring_buffer *ring,
-				    struct drm_i915_gem_execbuffer2 *exec,
-				    struct drm_clip_rect *cliprects,
-				    uint64_t exec_offset)
+render_ring_dispatch_execbuffer(struct intel_ring_buffer *ring,
+				u32 offset, u32 len)
 {
+	struct drm_device *dev = ring->dev;
 	drm_i915_private_t *dev_priv = dev->dev_private;
-	int nbox = exec->num_cliprects;
-	int i = 0, count;
-	uint32_t exec_start, exec_len;
-	exec_start = (uint32_t) exec_offset + exec->batch_start_offset;
-	exec_len = (uint32_t) exec->batch_len;
+	int ret;
 
 	trace_i915_gem_request_submit(dev, dev_priv->next_seqno + 1);
 
-	count = nbox ? nbox : 1;
+	if (IS_I830(dev) || IS_845G(dev)) {
+		ret = intel_ring_begin(ring, 4);
+		if (ret)
+			return ret;
 
-	for (i = 0; i < count; i++) {
-		if (i < nbox) {
-			int ret = i915_emit_box(dev, cliprects, i,
-						exec->DR1, exec->DR4);
-			if (ret)
-				return ret;
-		}
+		intel_ring_emit(ring, MI_BATCH_BUFFER);
+		intel_ring_emit(ring, offset | MI_BATCH_NON_SECURE);
+		intel_ring_emit(ring, offset + len - 8);
+		intel_ring_emit(ring, 0);
+	} else {
+		ret = intel_ring_begin(ring, 2);
+		if (ret)
+			return ret;
 
-		if (IS_I830(dev) || IS_845G(dev)) {
-			intel_ring_begin(dev, ring, 4);
-			intel_ring_emit(dev, ring, MI_BATCH_BUFFER);
-			intel_ring_emit(dev, ring,
-					exec_start | MI_BATCH_NON_SECURE);
-			intel_ring_emit(dev, ring, exec_start + exec_len - 4);
-			intel_ring_emit(dev, ring, 0);
+		if (INTEL_INFO(dev)->gen >= 4) {
+			intel_ring_emit(ring,
+					MI_BATCH_BUFFER_START | (2 << 6) |
+					MI_BATCH_NON_SECURE_I965);
+			intel_ring_emit(ring, offset);
 		} else {
-			intel_ring_begin(dev, ring, 2);
-			if (INTEL_INFO(dev)->gen >= 4) {
-				intel_ring_emit(dev, ring,
-						MI_BATCH_BUFFER_START | (2 << 6)
-						| MI_BATCH_NON_SECURE_I965);
-				intel_ring_emit(dev, ring, exec_start);
-			} else {
-				intel_ring_emit(dev, ring, MI_BATCH_BUFFER_START
-						| (2 << 6));
-				intel_ring_emit(dev, ring, exec_start |
-						MI_BATCH_NON_SECURE);
-			}
+			intel_ring_emit(ring,
+					MI_BATCH_BUFFER_START | (2 << 6));
+			intel_ring_emit(ring, offset | MI_BATCH_NON_SECURE);
 		}
-		intel_ring_advance(dev, ring);
-	}
-
-	if (IS_G4X(dev) || IS_GEN5(dev)) {
-		intel_ring_begin(dev, ring, 2);
-		intel_ring_emit(dev, ring, MI_FLUSH |
-				MI_NO_WRITE_FLUSH |
-				MI_INVALIDATE_ISP );
-		intel_ring_emit(dev, ring, MI_NOOP);
-		intel_ring_advance(dev, ring);
 	}
-	/* XXX breadcrumb */
+	intel_ring_advance(ring);
 
 	return 0;
 }
 
-static void cleanup_status_page(struct drm_device *dev,
-				struct intel_ring_buffer *ring)
+static void cleanup_status_page(struct intel_ring_buffer *ring)
 {
-	drm_i915_private_t *dev_priv = dev->dev_private;
-	struct drm_gem_object *obj;
-	struct drm_i915_gem_object *obj_priv;
+	drm_i915_private_t *dev_priv = ring->dev->dev_private;
+	struct drm_i915_gem_object *obj;
 
 	obj = ring->status_page.obj;
 	if (obj == NULL)
 		return;
-	obj_priv = to_intel_bo(obj);
 
-	kunmap(obj_priv->pages[0]);
+	kunmap(obj->pages[0]);
 	i915_gem_object_unpin(obj);
-	drm_gem_object_unreference(obj);
+	drm_gem_object_unreference(&obj->base);
 	ring->status_page.obj = NULL;
 
 	memset(&dev_priv->hws_map, 0, sizeof(dev_priv->hws_map));
 }
 
-static int init_status_page(struct drm_device *dev,
-			    struct intel_ring_buffer *ring)
+static int init_status_page(struct intel_ring_buffer *ring)
 {
+	struct drm_device *dev = ring->dev;
 	drm_i915_private_t *dev_priv = dev->dev_private;
-	struct drm_gem_object *obj;
-	struct drm_i915_gem_object *obj_priv;
+	struct drm_i915_gem_object *obj;
 	int ret;
 
 	obj = i915_gem_alloc_object(dev, 4096);
@@ -540,16 +780,15 @@ static int init_status_page(struct drm_d
 		ret = -ENOMEM;
 		goto err;
 	}
-	obj_priv = to_intel_bo(obj);
-	obj_priv->agp_type = AGP_USER_CACHED_MEMORY;
+	obj->agp_type = AGP_USER_CACHED_MEMORY;
 
-	ret = i915_gem_object_pin(obj, 4096);
+	ret = i915_gem_object_pin(obj, 4096, true);
 	if (ret != 0) {
 		goto err_unref;
 	}
 
-	ring->status_page.gfx_addr = obj_priv->gtt_offset;
-	ring->status_page.page_addr = kmap(obj_priv->pages[0]);
+	ring->status_page.gfx_addr = obj->gtt_offset;
+	ring->status_page.page_addr = kmap(obj->pages[0]);
 	if (ring->status_page.page_addr == NULL) {
 		memset(&dev_priv->hws_map, 0, sizeof(dev_priv->hws_map));
 		goto err_unpin;
@@ -557,7 +796,7 @@ static int init_status_page(struct drm_d
 	ring->status_page.obj = obj;
 	memset(ring->status_page.page_addr, 0, PAGE_SIZE);
 
-	intel_ring_setup_status_page(dev, ring);
+	intel_ring_setup_status_page(ring);
 	DRM_DEBUG_DRIVER("%s hws offset: 0x%08x\n",
 			ring->name, ring->status_page.gfx_addr);
 
@@ -566,7 +805,7 @@ static int init_status_page(struct drm_d
 err_unpin:
 	i915_gem_object_unpin(obj);
 err_unref:
-	drm_gem_object_unreference(obj);
+	drm_gem_object_unreference(&obj->base);
 err:
 	return ret;
 }
@@ -574,9 +813,7 @@ err:
 int intel_init_ring_buffer(struct drm_device *dev,
 			   struct intel_ring_buffer *ring)
 {
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct drm_i915_gem_object *obj_priv;
-	struct drm_gem_object *obj;
+	struct drm_i915_gem_object *obj;
 	int ret;
 
 	ring->dev = dev;
@@ -584,8 +821,11 @@ int intel_init_ring_buffer(struct drm_de
 	INIT_LIST_HEAD(&ring->request_list);
 	INIT_LIST_HEAD(&ring->gpu_write_list);
 
+	spin_lock_init(&ring->irq_lock);
+	ring->irq_mask = ~0;
+
 	if (I915_NEED_GFX_HWS(dev)) {
-		ret = init_status_page(dev, ring);
+		ret = init_status_page(ring);
 		if (ret)
 			return ret;
 	}
@@ -597,15 +837,14 @@ int intel_init_ring_buffer(struct drm_de
 		goto err_hws;
 	}
 
-	ring->gem_object = obj;
+	ring->obj = obj;
 
-	ret = i915_gem_object_pin(obj, PAGE_SIZE);
+	ret = i915_gem_object_pin(obj, PAGE_SIZE, true);
 	if (ret)
 		goto err_unref;
 
-	obj_priv = to_intel_bo(obj);
 	ring->map.size = ring->size;
-	ring->map.offset = dev->agp->base + obj_priv->gtt_offset;
+	ring->map.offset = dev->agp->base + obj->gtt_offset;
 	ring->map.type = 0;
 	ring->map.flags = 0;
 	ring->map.mtrr = 0;
@@ -618,60 +857,64 @@ int intel_init_ring_buffer(struct drm_de
 	}
 
 	ring->virtual_start = ring->map.handle;
-	ret = ring->init(dev, ring);
+	ret = ring->init(ring);
 	if (ret)
 		goto err_unmap;
 
-	if (!drm_core_check_feature(dev, DRIVER_MODESET))
-		i915_kernel_lost_context(dev);
-	else {
-		ring->head = I915_READ_HEAD(ring) & HEAD_ADDR;
-		ring->tail = I915_READ_TAIL(ring) & TAIL_ADDR;
-		ring->space = ring->head - (ring->tail + 8);
-		if (ring->space < 0)
-			ring->space += ring->size;
-	}
-	return ret;
+	/* Workaround an erratum on the i830 which causes a hang if
+	 * the TAIL pointer points to within the last 2 cachelines
+	 * of the buffer.
+	 */
+	ring->effective_size = ring->size;
+	if (IS_I830(ring->dev))
+		ring->effective_size -= 128;
+
+	return 0;
 
 err_unmap:
 	drm_core_ioremapfree(&ring->map, dev);
 err_unpin:
 	i915_gem_object_unpin(obj);
 err_unref:
-	drm_gem_object_unreference(obj);
-	ring->gem_object = NULL;
+	drm_gem_object_unreference(&obj->base);
+	ring->obj = NULL;
 err_hws:
-	cleanup_status_page(dev, ring);
+	cleanup_status_page(ring);
 	return ret;
 }
 
-void intel_cleanup_ring_buffer(struct drm_device *dev,
-			       struct intel_ring_buffer *ring)
+void intel_cleanup_ring_buffer(struct intel_ring_buffer *ring)
 {
-	if (ring->gem_object == NULL)
+	struct drm_i915_private *dev_priv;
+	int ret;
+
+	if (ring->obj == NULL)
 		return;
 
-	drm_core_ioremapfree(&ring->map, dev);
+	/* Disable the ring buffer. The ring must be idle at this point */
+	dev_priv = ring->dev->dev_private;
+	ret = intel_wait_ring_buffer(ring, ring->size - 8);
+	I915_WRITE_CTL(ring, 0);
 
-	i915_gem_object_unpin(ring->gem_object);
-	drm_gem_object_unreference(ring->gem_object);
-	ring->gem_object = NULL;
+	drm_core_ioremapfree(&ring->map, ring->dev);
+
+	i915_gem_object_unpin(ring->obj);
+	drm_gem_object_unreference(&ring->obj->base);
+	ring->obj = NULL;
 
 	if (ring->cleanup)
 		ring->cleanup(ring);
 
-	cleanup_status_page(dev, ring);
+	cleanup_status_page(ring);
 }
 
-static int intel_wrap_ring_buffer(struct drm_device *dev,
-				  struct intel_ring_buffer *ring)
+static int intel_wrap_ring_buffer(struct intel_ring_buffer *ring)
 {
 	unsigned int *virt;
-	int rem;
-	rem = ring->size - ring->tail;
+	int rem = ring->size - ring->tail;
 
 	if (ring->space < rem) {
-		int ret = intel_wait_ring_buffer(dev, ring, rem);
+		int ret = intel_wait_ring_buffer(ring, rem);
 		if (ret)
 			return ret;
 	}
@@ -684,34 +927,36 @@ static int intel_wrap_ring_buffer(struct
 	}
 
 	ring->tail = 0;
-	ring->space = ring->head - 8;
+	ring->space = ring_space(ring);
 
 	return 0;
 }
 
-int intel_wait_ring_buffer(struct drm_device *dev,
-			   struct intel_ring_buffer *ring, int n)
+int intel_wait_ring_buffer(struct intel_ring_buffer *ring, int n)
 {
+	struct drm_device *dev = ring->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
 	unsigned long end;
-	drm_i915_private_t *dev_priv = dev->dev_private;
 	u32 head;
 
+	/* If the reported head position has wrapped or hasn't advanced,
+	 * fallback to the slow and accurate path.
+	 */
+	head = intel_read_status_page(ring, 4);
+	if (head > ring->head) {
+		ring->head = head;
+		ring->space = ring_space(ring);
+		if (ring->space >= n)
+			return 0;
+	}
+
 	trace_i915_ring_wait_begin (dev);
 	end = jiffies + 3 * HZ;
 	do {
-		/* If the reported head position has wrapped or hasn't advanced,
-		 * fallback to the slow and accurate path.
-		 */
-		head = intel_read_status_page(ring, 4);
-		if (head < ring->actual_head)
-			head = I915_READ_HEAD(ring);
-		ring->actual_head = head;
-		ring->head = head & HEAD_ADDR;
-		ring->space = ring->head - (ring->tail + 8);
-		if (ring->space < 0)
-			ring->space += ring->size;
+		ring->head = I915_READ_HEAD(ring);
+		ring->space = ring_space(ring);
 		if (ring->space >= n) {
-			trace_i915_ring_wait_end (dev);
+			trace_i915_ring_wait_end(dev);
 			return 0;
 		}
 
@@ -722,29 +967,39 @@ int intel_wait_ring_buffer(struct drm_de
 		}
 
 		msleep(1);
+		if (atomic_read(&dev_priv->mm.wedged))
+			return -EAGAIN;
 	} while (!time_after(jiffies, end));
 	trace_i915_ring_wait_end (dev);
 	return -EBUSY;
 }
 
-void intel_ring_begin(struct drm_device *dev,
-		      struct intel_ring_buffer *ring,
-		      int num_dwords)
+int intel_ring_begin(struct intel_ring_buffer *ring,
+		     int num_dwords)
 {
 	int n = 4*num_dwords;
-	if (unlikely(ring->tail + n > ring->size))
-		intel_wrap_ring_buffer(dev, ring);
-	if (unlikely(ring->space < n))
-		intel_wait_ring_buffer(dev, ring, n);
+	int ret;
+
+	if (unlikely(ring->tail + n > ring->effective_size)) {
+		ret = intel_wrap_ring_buffer(ring);
+		if (unlikely(ret))
+			return ret;
+	}
+
+	if (unlikely(ring->space < n)) {
+		ret = intel_wait_ring_buffer(ring, n);
+		if (unlikely(ret))
+			return ret;
+	}
 
 	ring->space -= n;
+	return 0;
 }
 
-void intel_ring_advance(struct drm_device *dev,
-			struct intel_ring_buffer *ring)
+void intel_ring_advance(struct intel_ring_buffer *ring)
 {
 	ring->tail &= ring->size - 1;
-	ring->write_tail(dev, ring, ring->tail);
+	ring->write_tail(ring, ring->tail);
 }
 
 static const struct intel_ring_buffer render_ring = {
@@ -756,10 +1011,11 @@ static const struct intel_ring_buffer re
 	.write_tail		= ring_write_tail,
 	.flush			= render_ring_flush,
 	.add_request		= render_ring_add_request,
-	.get_seqno		= render_ring_get_seqno,
-	.user_irq_get		= render_ring_get_user_irq,
-	.user_irq_put		= render_ring_put_user_irq,
-	.dispatch_gem_execbuffer = render_ring_dispatch_gem_execbuffer,
+	.get_seqno		= ring_get_seqno,
+	.irq_get		= render_ring_get_irq,
+	.irq_put		= render_ring_put_irq,
+	.dispatch_execbuffer	= render_ring_dispatch_execbuffer,
+       .cleanup			= render_ring_cleanup,
 };
 
 /* ring buffer for bit-stream decoder */
@@ -769,22 +1025,21 @@ static const struct intel_ring_buffer bs
 	.id			= RING_BSD,
 	.mmio_base		= BSD_RING_BASE,
 	.size			= 32 * PAGE_SIZE,
-	.init			= init_bsd_ring,
+	.init			= init_ring_common,
 	.write_tail		= ring_write_tail,
 	.flush			= bsd_ring_flush,
 	.add_request		= ring_add_request,
-	.get_seqno		= ring_status_page_get_seqno,
-	.user_irq_get		= bsd_ring_get_user_irq,
-	.user_irq_put		= bsd_ring_put_user_irq,
-	.dispatch_gem_execbuffer = ring_dispatch_gem_execbuffer,
+	.get_seqno		= ring_get_seqno,
+	.irq_get		= bsd_ring_get_irq,
+	.irq_put		= bsd_ring_put_irq,
+	.dispatch_execbuffer	= ring_dispatch_execbuffer,
 };
 
 
-static void gen6_bsd_ring_write_tail(struct drm_device *dev,
-				     struct intel_ring_buffer *ring,
+static void gen6_bsd_ring_write_tail(struct intel_ring_buffer *ring,
 				     u32 value)
 {
-       drm_i915_private_t *dev_priv = 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,
@@ -803,69 +1058,112 @@ static void gen6_bsd_ring_write_tail(str
 	       GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_ENABLE);
 }
 
-static void gen6_ring_flush(struct drm_device *dev,
-			    struct intel_ring_buffer *ring,
-			    u32 invalidate_domains,
-			    u32 flush_domains)
+static int gen6_ring_flush(struct intel_ring_buffer *ring,
+			   u32 invalidate, u32 flush)
 {
-       intel_ring_begin(dev, ring, 4);
-       intel_ring_emit(dev, ring, MI_FLUSH_DW);
-       intel_ring_emit(dev, ring, 0);
-       intel_ring_emit(dev, ring, 0);
-       intel_ring_emit(dev, ring, 0);
-       intel_ring_advance(dev, ring);
+	uint32_t cmd;
+	int ret;
+
+	if (((invalidate | flush) & I915_GEM_GPU_DOMAINS) == 0)
+		return 0;
+
+	ret = intel_ring_begin(ring, 4);
+	if (ret)
+		return ret;
+
+	cmd = MI_FLUSH_DW;
+	if (invalidate & I915_GEM_GPU_DOMAINS)
+		cmd |= MI_INVALIDATE_TLB | MI_INVALIDATE_BSD;
+	intel_ring_emit(ring, cmd);
+	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_ring_dispatch_gem_execbuffer(struct drm_device *dev,
-				  struct intel_ring_buffer *ring,
-				  struct drm_i915_gem_execbuffer2 *exec,
-				  struct drm_clip_rect *cliprects,
-				  uint64_t exec_offset)
+gen6_ring_dispatch_execbuffer(struct intel_ring_buffer *ring,
+			      u32 offset, u32 len)
 {
-       uint32_t exec_start;
+       int ret;
 
-       exec_start = (uint32_t) exec_offset + exec->batch_start_offset;
+       ret = intel_ring_begin(ring, 2);
+       if (ret)
+	       return ret;
 
-       intel_ring_begin(dev, ring, 2);
-       intel_ring_emit(dev, ring,
-		       MI_BATCH_BUFFER_START | MI_BATCH_NON_SECURE_I965);
+       intel_ring_emit(ring, MI_BATCH_BUFFER_START | MI_BATCH_NON_SECURE_I965);
        /* bit0-7 is the length on GEN6+ */
-       intel_ring_emit(dev, ring, exec_start);
-       intel_ring_advance(dev, ring);
+       intel_ring_emit(ring, offset);
+       intel_ring_advance(ring);
 
        return 0;
 }
 
+static bool
+gen6_render_ring_get_irq(struct intel_ring_buffer *ring)
+{
+	return gen6_ring_get_irq(ring,
+				 GT_USER_INTERRUPT,
+				 GEN6_RENDER_USER_INTERRUPT);
+}
+
+static void
+gen6_render_ring_put_irq(struct intel_ring_buffer *ring)
+{
+	return gen6_ring_put_irq(ring,
+				 GT_USER_INTERRUPT,
+				 GEN6_RENDER_USER_INTERRUPT);
+}
+
+static bool
+gen6_bsd_ring_get_irq(struct intel_ring_buffer *ring)
+{
+	return gen6_ring_get_irq(ring,
+				 GT_GEN6_BSD_USER_INTERRUPT,
+				 GEN6_BSD_USER_INTERRUPT);
+}
+
+static void
+gen6_bsd_ring_put_irq(struct intel_ring_buffer *ring)
+{
+	return gen6_ring_put_irq(ring,
+				 GT_GEN6_BSD_USER_INTERRUPT,
+				 GEN6_BSD_USER_INTERRUPT);
+}
+
 /* ring buffer for Video Codec for Gen6+ */
 static const struct intel_ring_buffer gen6_bsd_ring = {
-       .name			= "gen6 bsd ring",
-       .id			= RING_BSD,
-       .mmio_base		= GEN6_BSD_RING_BASE,
-       .size			= 32 * PAGE_SIZE,
-       .init			= init_bsd_ring,
-       .write_tail		= gen6_bsd_ring_write_tail,
-       .flush			= gen6_ring_flush,
-       .add_request		= ring_add_request,
-       .get_seqno		= ring_status_page_get_seqno,
-       .user_irq_get		= bsd_ring_get_user_irq,
-       .user_irq_put		= bsd_ring_put_user_irq,
-       .dispatch_gem_execbuffer	= gen6_ring_dispatch_gem_execbuffer,
+	.name			= "gen6 bsd ring",
+	.id			= RING_BSD,
+	.mmio_base		= GEN6_BSD_RING_BASE,
+	.size			= 32 * PAGE_SIZE,
+	.init			= init_ring_common,
+	.write_tail		= gen6_bsd_ring_write_tail,
+	.flush			= gen6_ring_flush,
+	.add_request		= gen6_add_request,
+	.get_seqno		= ring_get_seqno,
+	.irq_get		= gen6_bsd_ring_get_irq,
+	.irq_put		= gen6_bsd_ring_put_irq,
+	.dispatch_execbuffer	= gen6_ring_dispatch_execbuffer,
 };
 
 /* Blitter support (SandyBridge+) */
 
-static void
-blt_ring_get_user_irq(struct drm_device *dev,
-		      struct intel_ring_buffer *ring)
+static bool
+blt_ring_get_irq(struct intel_ring_buffer *ring)
 {
-	/* do nothing */
+	return gen6_ring_get_irq(ring,
+				 GT_BLT_USER_INTERRUPT,
+				 GEN6_BLITTER_USER_INTERRUPT);
 }
+
 static void
-blt_ring_put_user_irq(struct drm_device *dev,
-		      struct intel_ring_buffer *ring)
+blt_ring_put_irq(struct intel_ring_buffer *ring)
 {
-	/* do nothing */
+	gen6_ring_put_irq(ring,
+			  GT_BLT_USER_INTERRUPT,
+			  GEN6_BLITTER_USER_INTERRUPT);
 }
 
 
@@ -883,32 +1181,31 @@ to_blt_workaround(struct intel_ring_buff
 	return ring->private;
 }
 
-static int blt_ring_init(struct drm_device *dev,
-			 struct intel_ring_buffer *ring)
+static int blt_ring_init(struct intel_ring_buffer *ring)
 {
-	if (NEED_BLT_WORKAROUND(dev)) {
+	if (NEED_BLT_WORKAROUND(ring->dev)) {
 		struct drm_i915_gem_object *obj;
-		u32 __iomem *ptr;
+		u32 *ptr;
 		int ret;
 
-		obj = to_intel_bo(i915_gem_alloc_object(dev, 4096));
+		obj = i915_gem_alloc_object(ring->dev, 4096);
 		if (obj == NULL)
 			return -ENOMEM;
 
-		ret = i915_gem_object_pin(&obj->base, 4096);
+		ret = i915_gem_object_pin(obj, 4096, true);
 		if (ret) {
 			drm_gem_object_unreference(&obj->base);
 			return ret;
 		}
 
 		ptr = kmap(obj->pages[0]);
-		iowrite32(MI_BATCH_BUFFER_END, ptr);
-		iowrite32(MI_NOOP, ptr+1);
+		*ptr++ = MI_BATCH_BUFFER_END;
+		*ptr++ = MI_NOOP;
 		kunmap(obj->pages[0]);
 
-		ret = i915_gem_object_set_to_gtt_domain(&obj->base, false);
+		ret = i915_gem_object_set_to_gtt_domain(obj, false);
 		if (ret) {
-			i915_gem_object_unpin(&obj->base);
+			i915_gem_object_unpin(obj);
 			drm_gem_object_unreference(&obj->base);
 			return ret;
 		}
@@ -916,51 +1213,47 @@ static int blt_ring_init(struct drm_devi
 		ring->private = obj;
 	}
 
-	return init_ring_common(dev, ring);
+	return init_ring_common(ring);
 }
 
-static void blt_ring_begin(struct drm_device *dev,
-			   struct intel_ring_buffer *ring,
+static int blt_ring_begin(struct intel_ring_buffer *ring,
 			  int num_dwords)
 {
 	if (ring->private) {
-		intel_ring_begin(dev, ring, num_dwords+2);
-		intel_ring_emit(dev, ring, MI_BATCH_BUFFER_START);
-		intel_ring_emit(dev, ring, to_blt_workaround(ring)->gtt_offset);
+		int ret = intel_ring_begin(ring, num_dwords+2);
+		if (ret)
+			return ret;
+
+		intel_ring_emit(ring, MI_BATCH_BUFFER_START);
+		intel_ring_emit(ring, to_blt_workaround(ring)->gtt_offset);
+
+		return 0;
 	} else
-		intel_ring_begin(dev, ring, 4);
+		return intel_ring_begin(ring, 4);
 }
 
-static void blt_ring_flush(struct drm_device *dev,
-			   struct intel_ring_buffer *ring,
-			   u32 invalidate_domains,
-			   u32 flush_domains)
+static int blt_ring_flush(struct intel_ring_buffer *ring,
+			  u32 invalidate, u32 flush)
 {
-	blt_ring_begin(dev, ring, 4);
-	intel_ring_emit(dev, ring, MI_FLUSH_DW);
-	intel_ring_emit(dev, ring, 0);
-	intel_ring_emit(dev, ring, 0);
-	intel_ring_emit(dev, ring, 0);
-	intel_ring_advance(dev, ring);
-}
+	uint32_t cmd;
+	int ret;
 
-static u32
-blt_ring_add_request(struct drm_device *dev,
-		     struct intel_ring_buffer *ring,
-		     u32 flush_domains)
-{
-	u32 seqno = i915_gem_get_seqno(dev);
+	if (((invalidate | flush) & I915_GEM_DOMAIN_RENDER) == 0)
+		return 0;
 
-	blt_ring_begin(dev, ring, 4);
-	intel_ring_emit(dev, ring, MI_STORE_DWORD_INDEX);
-	intel_ring_emit(dev, ring,
-			I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT);
-	intel_ring_emit(dev, ring, seqno);
-	intel_ring_emit(dev, ring, MI_USER_INTERRUPT);
-	intel_ring_advance(dev, ring);
+	ret = blt_ring_begin(ring, 4);
+	if (ret)
+		return ret;
 
-	DRM_DEBUG_DRIVER("%s %d\n", ring->name, seqno);
-	return seqno;
+	cmd = MI_FLUSH_DW;
+	if (invalidate & I915_GEM_DOMAIN_RENDER)
+		cmd |= MI_INVALIDATE_TLB;
+	intel_ring_emit(ring, cmd);
+	intel_ring_emit(ring, 0);
+	intel_ring_emit(ring, 0);
+	intel_ring_emit(ring, MI_NOOP);
+	intel_ring_advance(ring);
+	return 0;
 }
 
 static void blt_ring_cleanup(struct intel_ring_buffer *ring)
@@ -981,47 +1274,98 @@ static const struct intel_ring_buffer ge
        .init			= blt_ring_init,
        .write_tail		= ring_write_tail,
        .flush			= blt_ring_flush,
-       .add_request		= blt_ring_add_request,
-       .get_seqno		= ring_status_page_get_seqno,
-       .user_irq_get		= blt_ring_get_user_irq,
-       .user_irq_put		= blt_ring_put_user_irq,
-       .dispatch_gem_execbuffer	= gen6_ring_dispatch_gem_execbuffer,
+       .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,
 };
 
 int intel_init_render_ring_buffer(struct drm_device *dev)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
+	struct intel_ring_buffer *ring = &dev_priv->ring[RCS];
 
-	dev_priv->render_ring = render_ring;
+	*ring = render_ring;
+	if (INTEL_INFO(dev)->gen >= 6) {
+		ring->add_request = gen6_add_request;
+		ring->irq_get = gen6_render_ring_get_irq;
+		ring->irq_put = gen6_render_ring_put_irq;
+	} else if (IS_GEN5(dev)) {
+		ring->add_request = pc_render_add_request;
+		ring->get_seqno = pc_render_get_seqno;
+	}
 
 	if (!I915_NEED_GFX_HWS(dev)) {
-		dev_priv->render_ring.status_page.page_addr
-			= dev_priv->status_page_dmah->vaddr;
-		memset(dev_priv->render_ring.status_page.page_addr,
-				0, PAGE_SIZE);
+		ring->status_page.page_addr = dev_priv->status_page_dmah->vaddr;
+		memset(ring->status_page.page_addr, 0, PAGE_SIZE);
 	}
 
-	return intel_init_ring_buffer(dev, &dev_priv->render_ring);
+	return intel_init_ring_buffer(dev, ring);
+}
+
+int intel_render_ring_init_dri(struct drm_device *dev, u64 start, u32 size)
+{
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	struct intel_ring_buffer *ring = &dev_priv->ring[RCS];
+
+	*ring = render_ring;
+	if (INTEL_INFO(dev)->gen >= 6) {
+		ring->add_request = gen6_add_request;
+		ring->irq_get = gen6_render_ring_get_irq;
+		ring->irq_put = gen6_render_ring_put_irq;
+	} else if (IS_GEN5(dev)) {
+		ring->add_request = pc_render_add_request;
+		ring->get_seqno = pc_render_get_seqno;
+	}
+
+	ring->dev = dev;
+	INIT_LIST_HEAD(&ring->active_list);
+	INIT_LIST_HEAD(&ring->request_list);
+	INIT_LIST_HEAD(&ring->gpu_write_list);
+
+	ring->size = size;
+	ring->effective_size = ring->size;
+	if (IS_I830(ring->dev))
+		ring->effective_size -= 128;
+
+	ring->map.offset = start;
+	ring->map.size = size;
+	ring->map.type = 0;
+	ring->map.flags = 0;
+	ring->map.mtrr = 0;
+
+	drm_core_ioremap_wc(&ring->map, dev);
+	if (ring->map.handle == NULL) {
+		DRM_ERROR("can not ioremap virtual address for"
+			  " ring buffer\n");
+		return -ENOMEM;
+	}
+
+	ring->virtual_start = (void __force __iomem *)ring->map.handle;
+	return 0;
 }
 
 int intel_init_bsd_ring_buffer(struct drm_device *dev)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
+	struct intel_ring_buffer *ring = &dev_priv->ring[VCS];
 
 	if (IS_GEN6(dev))
-		dev_priv->bsd_ring = gen6_bsd_ring;
+		*ring = gen6_bsd_ring;
 	else
-		dev_priv->bsd_ring = bsd_ring;
+		*ring = bsd_ring;
 
-	return intel_init_ring_buffer(dev, &dev_priv->bsd_ring);
+	return intel_init_ring_buffer(dev, ring);
 }
 
 int intel_init_blt_ring_buffer(struct drm_device *dev)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
+	struct intel_ring_buffer *ring = &dev_priv->ring[BCS];
 
-	dev_priv->blt_ring = gen6_blt_ring;
+	*ring = gen6_blt_ring;
 
-	return intel_init_ring_buffer(dev, &dev_priv->blt_ring);
+	return intel_init_ring_buffer(dev, ring);
 }
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/i915/intel_ringbuffer.h linux-libre-2.6.38-gnu1/drivers/gpu/drm/i915/intel_ringbuffer.h
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/i915/intel_ringbuffer.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/i915/intel_ringbuffer.h	2011-03-14 21:20:32.000000000 -0400
@@ -1,22 +1,41 @@
 #ifndef _INTEL_RINGBUFFER_H_
 #define _INTEL_RINGBUFFER_H_
 
+enum {
+    RCS = 0x0,
+    VCS,
+    BCS,
+    I915_NUM_RINGS,
+};
+
 struct  intel_hw_status_page {
-	void		*page_addr;
+	u32	__iomem	*page_addr;
 	unsigned int	gfx_addr;
-	struct		drm_gem_object *obj;
+	struct		drm_i915_gem_object *obj;
 };
 
-#define I915_READ_TAIL(ring) I915_READ(RING_TAIL(ring->mmio_base))
-#define I915_WRITE_TAIL(ring, val) I915_WRITE(RING_TAIL(ring->mmio_base), val)
-#define I915_READ_START(ring) I915_READ(RING_START(ring->mmio_base))
-#define I915_WRITE_START(ring, val) I915_WRITE(RING_START(ring->mmio_base), val)
-#define I915_READ_HEAD(ring) I915_READ(RING_HEAD(ring->mmio_base))
-#define I915_WRITE_HEAD(ring, val) I915_WRITE(RING_HEAD(ring->mmio_base), val)
-#define I915_READ_CTL(ring) I915_READ(RING_CTL(ring->mmio_base))
-#define I915_WRITE_CTL(ring, val) I915_WRITE(RING_CTL(ring->mmio_base), val)
+#define I915_RING_READ(reg) i915_gt_read(dev_priv, reg)
+#define I915_RING_WRITE(reg, val) i915_gt_write(dev_priv, reg, val)
+
+#define I915_READ_TAIL(ring) I915_RING_READ(RING_TAIL((ring)->mmio_base))
+#define I915_WRITE_TAIL(ring, val) I915_RING_WRITE(RING_TAIL((ring)->mmio_base), val)
+
+#define I915_READ_START(ring) I915_RING_READ(RING_START((ring)->mmio_base))
+#define I915_WRITE_START(ring, val) I915_RING_WRITE(RING_START((ring)->mmio_base), val)
+
+#define I915_READ_HEAD(ring)  I915_RING_READ(RING_HEAD((ring)->mmio_base))
+#define I915_WRITE_HEAD(ring, val) I915_RING_WRITE(RING_HEAD((ring)->mmio_base), val)
+
+#define I915_READ_CTL(ring) I915_RING_READ(RING_CTL((ring)->mmio_base))
+#define I915_WRITE_CTL(ring, val) I915_RING_WRITE(RING_CTL((ring)->mmio_base), val)
+
+#define I915_READ_IMR(ring) I915_RING_READ(RING_IMR((ring)->mmio_base))
+#define I915_WRITE_IMR(ring, val) I915_RING_WRITE(RING_IMR((ring)->mmio_base), val)
+
+#define I915_READ_NOPID(ring) I915_RING_READ(RING_NOPID((ring)->mmio_base))
+#define I915_READ_SYNC_0(ring) I915_RING_READ(RING_SYNC_0((ring)->mmio_base))
+#define I915_READ_SYNC_1(ring) I915_RING_READ(RING_SYNC_1((ring)->mmio_base))
 
-struct drm_i915_gem_execbuffer2;
 struct  intel_ring_buffer {
 	const char	*name;
 	enum intel_ring_id {
@@ -25,45 +44,38 @@ struct  intel_ring_buffer {
 		RING_BLT = 0x4,
 	} id;
 	u32		mmio_base;
-	unsigned long	size;
 	void		*virtual_start;
 	struct		drm_device *dev;
-	struct		drm_gem_object *gem_object;
+	struct		drm_i915_gem_object *obj;
 
-	u32		actual_head;
 	u32		head;
 	u32		tail;
 	int		space;
+	int		size;
+	int		effective_size;
 	struct intel_hw_status_page status_page;
 
-	u32		irq_gem_seqno;		/* last seq seem at irq time */
-	u32		waiting_gem_seqno;
-	int		user_irq_refcount;
-	void		(*user_irq_get)(struct drm_device *dev,
-			struct intel_ring_buffer *ring);
-	void		(*user_irq_put)(struct drm_device *dev,
-			struct intel_ring_buffer *ring);
+	spinlock_t	irq_lock;
+	u32		irq_refcount;
+	u32		irq_mask;
+	u32		irq_seqno;		/* last seq seem at irq time */
+	u32		waiting_seqno;
+	u32		sync_seqno[I915_NUM_RINGS-1];
+	bool __must_check (*irq_get)(struct intel_ring_buffer *ring);
+	void		(*irq_put)(struct intel_ring_buffer *ring);
 
-	int		(*init)(struct drm_device *dev,
-			struct intel_ring_buffer *ring);
+	int		(*init)(struct intel_ring_buffer *ring);
 
-	void		(*write_tail)(struct drm_device *dev,
-				      struct intel_ring_buffer *ring,
+	void		(*write_tail)(struct intel_ring_buffer *ring,
 				      u32 value);
-	void		(*flush)(struct drm_device *dev,
-			struct intel_ring_buffer *ring,
-			u32	invalidate_domains,
-			u32	flush_domains);
-	u32		(*add_request)(struct drm_device *dev,
-			struct intel_ring_buffer *ring,
-			u32 flush_domains);
-	u32		(*get_seqno)(struct drm_device *dev,
-				     struct intel_ring_buffer *ring);
-	int		(*dispatch_gem_execbuffer)(struct drm_device *dev,
-			struct intel_ring_buffer *ring,
-			struct drm_i915_gem_execbuffer2 *exec,
-			struct drm_clip_rect *cliprects,
-			uint64_t exec_offset);
+	int __must_check (*flush)(struct intel_ring_buffer *ring,
+				  u32	invalidate_domains,
+				  u32	flush_domains);
+	int		(*add_request)(struct intel_ring_buffer *ring,
+				       u32 *seqno);
+	u32		(*get_seqno)(struct intel_ring_buffer *ring);
+	int		(*dispatch_execbuffer)(struct intel_ring_buffer *ring,
+					       u32 offset, u32 length);
 	void		(*cleanup)(struct intel_ring_buffer *ring);
 
 	/**
@@ -96,7 +108,7 @@ struct  intel_ring_buffer {
 	/**
 	 * Do we have some not yet emitted requests outstanding?
 	 */
-	bool outstanding_lazy_request;
+	u32 outstanding_lazy_request;
 
 	wait_queue_head_t irq_queue;
 	drm_local_map_t map;
@@ -105,44 +117,57 @@ struct  intel_ring_buffer {
 };
 
 static inline u32
+intel_ring_sync_index(struct intel_ring_buffer *ring,
+		      struct intel_ring_buffer *other)
+{
+	int idx;
+
+	/*
+	 * cs -> 0 = vcs, 1 = bcs
+	 * vcs -> 0 = bcs, 1 = cs,
+	 * bcs -> 0 = cs, 1 = vcs.
+	 */
+
+	idx = (other - ring) - 1;
+	if (idx < 0)
+		idx += I915_NUM_RINGS;
+
+	return idx;
+}
+
+static inline u32
 intel_read_status_page(struct intel_ring_buffer *ring,
-		int reg)
+		       int reg)
 {
-	u32 *regs = ring->status_page.page_addr;
-	return regs[reg];
+	return ioread32(ring->status_page.page_addr + reg);
 }
 
-int intel_init_ring_buffer(struct drm_device *dev,
-			   struct intel_ring_buffer *ring);
-void intel_cleanup_ring_buffer(struct drm_device *dev,
-			       struct intel_ring_buffer *ring);
-int intel_wait_ring_buffer(struct drm_device *dev,
-			   struct intel_ring_buffer *ring, int n);
-void intel_ring_begin(struct drm_device *dev,
-		      struct intel_ring_buffer *ring, int n);
+void intel_cleanup_ring_buffer(struct intel_ring_buffer *ring);
+int __must_check intel_wait_ring_buffer(struct intel_ring_buffer *ring, int n);
+int __must_check intel_ring_begin(struct intel_ring_buffer *ring, int n);
 
-static inline void intel_ring_emit(struct drm_device *dev,
-				   struct intel_ring_buffer *ring,
-				   unsigned int data)
+static inline void intel_ring_emit(struct intel_ring_buffer *ring,
+				   u32 data)
 {
-	unsigned int *virt = ring->virtual_start + ring->tail;
-	*virt = data;
+	iowrite32(data, ring->virtual_start + ring->tail);
 	ring->tail += 4;
 }
 
-void intel_ring_advance(struct drm_device *dev,
-		struct intel_ring_buffer *ring);
+void intel_ring_advance(struct intel_ring_buffer *ring);
 
-u32 intel_ring_get_seqno(struct drm_device *dev,
-		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);
 int intel_init_blt_ring_buffer(struct drm_device *dev);
 
-u32 intel_ring_get_active_head(struct drm_device *dev,
-			       struct intel_ring_buffer *ring);
-void intel_ring_setup_status_page(struct drm_device *dev,
-				  struct intel_ring_buffer *ring);
+u32 intel_ring_get_active_head(struct intel_ring_buffer *ring);
+void intel_ring_setup_status_page(struct intel_ring_buffer *ring);
+
+/* DRI warts */
+int intel_render_ring_init_dri(struct drm_device *dev, u64 start, u32 size);
 
 #endif /* _INTEL_RINGBUFFER_H_ */
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/i915/intel_sdvo.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/i915/intel_sdvo.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/i915/intel_sdvo.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/i915/intel_sdvo.c	2011-03-14 21:20:32.000000000 -0400
@@ -46,6 +46,7 @@
                          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))
 
@@ -473,20 +474,6 @@ static bool intel_sdvo_write_cmd(struct
 		return false;
 	}
 
-	i = 3;
-	while (status == SDVO_CMD_STATUS_PENDING && i--) {
-		if (!intel_sdvo_read_byte(intel_sdvo,
-					  SDVO_I2C_CMD_STATUS,
-					  &status))
-			return false;
-	}
-	if (status != SDVO_CMD_STATUS_SUCCESS) {
-		DRM_DEBUG_KMS("command returns response %s [%d]\n",
-			      status <= SDVO_CMD_STATUS_SCALING_NOT_SUPP ? cmd_status_names[status] : "???",
-			      status);
-		return false;
-	}
-
 	return true;
 }
 
@@ -497,6 +484,8 @@ static bool intel_sdvo_read_response(str
 	u8 status;
 	int i;
 
+	DRM_DEBUG_KMS("%s: R: ", SDVO_NAME(intel_sdvo));
+
 	/*
 	 * The documentation states that all commands will be
 	 * processed within 15µs, and that we need only poll
@@ -505,14 +494,19 @@ static bool intel_sdvo_read_response(str
 	 *
 	 * Check 5 times in case the hardware failed to read the docs.
 	 */
-	do {
+	if (!intel_sdvo_read_byte(intel_sdvo,
+				  SDVO_I2C_CMD_STATUS,
+				  &status))
+		goto log_fail;
+
+	while (status == SDVO_CMD_STATUS_PENDING && retry--) {
+		udelay(15);
 		if (!intel_sdvo_read_byte(intel_sdvo,
 					  SDVO_I2C_CMD_STATUS,
 					  &status))
-			return false;
-	} while (status == SDVO_CMD_STATUS_PENDING && --retry);
+			goto log_fail;
+	}
 
-	DRM_DEBUG_KMS("%s: R: ", SDVO_NAME(intel_sdvo));
 	if (status <= SDVO_CMD_STATUS_SCALING_NOT_SUPP)
 		DRM_LOG_KMS("(%s)", cmd_status_names[status]);
 	else
@@ -533,7 +527,7 @@ static bool intel_sdvo_read_response(str
 	return true;
 
 log_fail:
-	DRM_LOG_KMS("\n");
+	DRM_LOG_KMS("... failed\n");
 	return false;
 }
 
@@ -550,6 +544,7 @@ static int intel_sdvo_get_pixel_multipli
 static bool intel_sdvo_set_control_bus_switch(struct intel_sdvo *intel_sdvo,
 					      u8 ddc_bus)
 {
+	/* This must be the immediately preceding write before the i2c xfer */
 	return intel_sdvo_write_cmd(intel_sdvo,
 				    SDVO_CMD_SET_CONTROL_BUS_SWITCH,
 				    &ddc_bus, 1);
@@ -557,7 +552,10 @@ static bool intel_sdvo_set_control_bus_s
 
 static bool intel_sdvo_set_value(struct intel_sdvo *intel_sdvo, u8 cmd, const void *data, int len)
 {
-	return intel_sdvo_write_cmd(intel_sdvo, cmd, data, len);
+	if (!intel_sdvo_write_cmd(intel_sdvo, cmd, data, len))
+		return false;
+
+	return intel_sdvo_read_response(intel_sdvo, NULL, 0);
 }
 
 static bool
@@ -859,18 +857,21 @@ static bool intel_sdvo_set_avi_infoframe
 
 	intel_dip_infoframe_csum(&avi_if);
 
-	if (!intel_sdvo_write_cmd(intel_sdvo, SDVO_CMD_SET_HBUF_INDEX,
+	if (!intel_sdvo_set_value(intel_sdvo,
+				  SDVO_CMD_SET_HBUF_INDEX,
 				  set_buf_index, 2))
 		return false;
 
 	for (i = 0; i < sizeof(avi_if); i += 8) {
-		if (!intel_sdvo_write_cmd(intel_sdvo, SDVO_CMD_SET_HBUF_DATA,
+		if (!intel_sdvo_set_value(intel_sdvo,
+					  SDVO_CMD_SET_HBUF_DATA,
 					  data, 8))
 			return false;
 		data++;
 	}
 
-	return intel_sdvo_write_cmd(intel_sdvo, SDVO_CMD_SET_HBUF_TXRATE,
+	return intel_sdvo_set_value(intel_sdvo,
+				    SDVO_CMD_SET_HBUF_TXRATE,
 				    &tx_rate, 1);
 }
 
@@ -1024,9 +1025,13 @@ static void intel_sdvo_mode_set(struct d
 	if (!intel_sdvo_set_target_input(intel_sdvo))
 		return;
 
-	if (intel_sdvo->has_hdmi_monitor &&
-	    !intel_sdvo_set_avi_infoframe(intel_sdvo))
-		return;
+	if (intel_sdvo->has_hdmi_monitor) {
+		intel_sdvo_set_encode(intel_sdvo, SDVO_ENCODE_HDMI);
+		intel_sdvo_set_colorimetry(intel_sdvo,
+					   SDVO_COLORIMETRY_RGB256);
+		intel_sdvo_set_avi_infoframe(intel_sdvo);
+	} else
+		intel_sdvo_set_encode(intel_sdvo, SDVO_ENCODE_DVI);
 
 	if (intel_sdvo->is_tv &&
 	    !intel_sdvo_set_tv_format(intel_sdvo))
@@ -1045,7 +1050,9 @@ static void intel_sdvo_mode_set(struct d
 
 	/* Set the SDVO control regs. */
 	if (INTEL_INFO(dev)->gen >= 4) {
-		sdvox = SDVO_BORDER_ENABLE;
+		sdvox = 0;
+		if (INTEL_INFO(dev)->gen < 5)
+			sdvox |= SDVO_BORDER_ENABLE;
 		if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
 			sdvox |= SDVO_VSYNC_ACTIVE_HIGH;
 		if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
@@ -1075,7 +1082,8 @@ static void intel_sdvo_mode_set(struct d
 		sdvox |= (pixel_multiplier - 1) << SDVO_PORT_MULTIPLY_SHIFT;
 	}
 
-	if (input_dtd.part2.sdvo_flags & SDVO_NEED_TO_STALL)
+	if (input_dtd.part2.sdvo_flags & SDVO_NEED_TO_STALL &&
+	    INTEL_INFO(dev)->gen < 5)
 		sdvox |= SDVO_STALL_SELECT;
 	intel_sdvo_write_sdvox(intel_sdvo, sdvox);
 }
@@ -1352,7 +1360,8 @@ intel_sdvo_hdmi_sink_detect(struct drm_c
 				intel_sdvo->has_hdmi_monitor = drm_detect_hdmi_monitor(edid);
 				intel_sdvo->has_hdmi_audio = drm_detect_monitor_audio(edid);
 			}
-		}
+		} else
+			status = connector_status_disconnected;
 		connector->display_info.raw_edid = NULL;
 		kfree(edid);
 	}
@@ -1395,12 +1404,30 @@ intel_sdvo_detect(struct drm_connector *
 
 	intel_sdvo->attached_output = response;
 
+	intel_sdvo->has_hdmi_monitor = false;
+	intel_sdvo->has_hdmi_audio = false;
+
 	if ((intel_sdvo_connector->output_flag & response) == 0)
 		ret = connector_status_disconnected;
-	else if (response & SDVO_TMDS_MASK)
+	else if (IS_TMDS(intel_sdvo_connector))
 		ret = intel_sdvo_hdmi_sink_detect(connector);
-	else
-		ret = connector_status_connected;
+	else {
+		struct edid *edid;
+
+		/* if we have an edid check it matches the connection */
+		edid = intel_sdvo_get_edid(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
+				ret = connector_status_connected;
+			connector->display_info.raw_edid = NULL;
+			kfree(edid);
+		} else
+			ret = connector_status_connected;
+	}
 
 	/* May update encoder flag for like clock for SDVO TV, etc.*/
 	if (ret == connector_status_connected) {
@@ -1436,10 +1463,15 @@ static void intel_sdvo_get_ddc_modes(str
 		edid = intel_sdvo_get_analog_edid(connector);
 
 	if (edid != NULL) {
-		if (edid->input & DRM_EDID_INPUT_DIGITAL) {
+		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) {
 			drm_mode_connector_update_edid_property(connector, edid);
 			drm_add_edid_modes(connector, edid);
 		}
+
 		connector->display_info.raw_edid = NULL;
 		kfree(edid);
 	}
@@ -1658,6 +1690,22 @@ static void intel_sdvo_destroy(struct dr
 	kfree(connector);
 }
 
+static bool intel_sdvo_detect_hdmi_audio(struct drm_connector *connector)
+{
+	struct intel_sdvo *intel_sdvo = intel_attached_sdvo(connector);
+	struct edid *edid;
+	bool has_audio = false;
+
+	if (!intel_sdvo->is_hdmi)
+		return false;
+
+	edid = intel_sdvo_get_edid(connector);
+	if (edid != NULL && edid->input & DRM_EDID_INPUT_DIGITAL)
+		has_audio = drm_detect_monitor_audio(edid);
+
+	return has_audio;
+}
+
 static int
 intel_sdvo_set_property(struct drm_connector *connector,
 			struct drm_property *property,
@@ -1674,17 +1722,23 @@ intel_sdvo_set_property(struct drm_conne
 		return ret;
 
 	if (property == intel_sdvo_connector->force_audio_property) {
-		if (val == intel_sdvo_connector->force_audio)
+		int i = val;
+		bool has_audio;
+
+		if (i == intel_sdvo_connector->force_audio)
 			return 0;
 
-		intel_sdvo_connector->force_audio = val;
+		intel_sdvo_connector->force_audio = i;
 
-		if (val > 0 && intel_sdvo->has_hdmi_audio)
-			return 0;
-		if (val < 0 && !intel_sdvo->has_hdmi_audio)
+		if (i == 0)
+			has_audio = intel_sdvo_detect_hdmi_audio(connector);
+		else
+			has_audio = i > 0;
+
+		if (has_audio == intel_sdvo->has_hdmi_audio)
 			return 0;
 
-		intel_sdvo->has_hdmi_audio = val > 0;
+		intel_sdvo->has_hdmi_audio = has_audio;
 		goto done;
 	}
 
@@ -1919,20 +1973,7 @@ intel_sdvo_select_i2c_bus(struct drm_i91
 static bool
 intel_sdvo_is_hdmi_connector(struct intel_sdvo *intel_sdvo, int device)
 {
-	int is_hdmi;
-
-	if (!intel_sdvo_check_supp_encode(intel_sdvo))
-		return false;
-
-	if (!intel_sdvo_set_target_output(intel_sdvo,
-					  device == 0 ? SDVO_OUTPUT_TMDS0 : SDVO_OUTPUT_TMDS1))
-		return false;
-
-	is_hdmi = 0;
-	if (!intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_ENCODE, &is_hdmi, 1))
-		return false;
-
-	return !!is_hdmi;
+	return intel_sdvo_check_supp_encode(intel_sdvo);
 }
 
 static u8
@@ -2034,12 +2075,7 @@ intel_sdvo_dvi_init(struct intel_sdvo *i
 	connector->connector_type = DRM_MODE_CONNECTOR_DVID;
 
 	if (intel_sdvo_is_hdmi_connector(intel_sdvo, device)) {
-		/* enable hdmi encoding mode if supported */
-		intel_sdvo_set_encode(intel_sdvo, SDVO_ENCODE_HDMI);
-		intel_sdvo_set_colorimetry(intel_sdvo,
-					   SDVO_COLORIMETRY_RGB256);
 		connector->connector_type = DRM_MODE_CONNECTOR_HDMIA;
-
 		intel_sdvo->is_hdmi = true;
 	}
 	intel_sdvo->base.clone_mask = ((1 << INTEL_SDVO_NON_TV_CLONE_BIT) |
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/i915/intel_tv.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/i915/intel_tv.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/i915/intel_tv.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/i915/intel_tv.c	2011-03-14 21:20:32.000000000 -0400
@@ -1234,7 +1234,8 @@ 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;
 	struct drm_device *dev = encoder->dev;
@@ -1245,10 +1246,13 @@ intel_tv_detect_type (struct intel_tv *i
 	int type;
 
 	/* Disable TV interrupts around load detect or we'll recurse */
-	spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
-	i915_disable_pipestat(dev_priv, 0, PIPE_HOTPLUG_INTERRUPT_ENABLE |
-			      PIPE_HOTPLUG_TV_INTERRUPT_ENABLE);
-	spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags);
+	if (connector->polled & DRM_CONNECTOR_POLL_HPD) {
+		spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
+		i915_disable_pipestat(dev_priv, 0,
+				      PIPE_HOTPLUG_INTERRUPT_ENABLE |
+				      PIPE_HOTPLUG_TV_INTERRUPT_ENABLE);
+		spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
+	}
 
 	save_tv_dac = tv_dac = I915_READ(TV_DAC);
 	save_tv_ctl = tv_ctl = I915_READ(TV_CTL);
@@ -1301,10 +1305,13 @@ intel_tv_detect_type (struct intel_tv *i
 	I915_WRITE(TV_CTL, save_tv_ctl);
 
 	/* Restore interrupt config */
-	spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
-	i915_enable_pipestat(dev_priv, 0, PIPE_HOTPLUG_INTERRUPT_ENABLE |
-			     PIPE_HOTPLUG_TV_INTERRUPT_ENABLE);
-	spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags);
+	if (connector->polled & DRM_CONNECTOR_POLL_HPD) {
+		spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
+		i915_enable_pipestat(dev_priv, 0,
+				     PIPE_HOTPLUG_INTERRUPT_ENABLE |
+				     PIPE_HOTPLUG_TV_INTERRUPT_ENABLE);
+		spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
+	}
 
 	return type;
 }
@@ -1354,7 +1361,7 @@ intel_tv_detect(struct drm_connector *co
 	drm_mode_set_crtcinfo(&mode, CRTC_INTERLACE_HALVE_V);
 
 	if (intel_tv->base.base.crtc && intel_tv->base.base.crtc->enabled) {
-		type = intel_tv_detect_type(intel_tv);
+		type = intel_tv_detect_type(intel_tv, connector);
 	} else if (force) {
 		struct drm_crtc *crtc;
 		int dpms_mode;
@@ -1362,7 +1369,7 @@ intel_tv_detect(struct drm_connector *co
 		crtc = intel_get_load_detect_pipe(&intel_tv->base, connector,
 						  &mode, &dpms_mode);
 		if (crtc) {
-			type = intel_tv_detect_type(intel_tv);
+			type = intel_tv_detect_type(intel_tv, connector);
 			intel_release_load_detect_pipe(&intel_tv->base, connector,
 						       dpms_mode);
 		} else
@@ -1656,6 +1663,18 @@ intel_tv_init(struct drm_device *dev)
 	intel_encoder = &intel_tv->base;
 	connector = &intel_connector->base;
 
+	/* The documentation, for the older chipsets at least, recommend
+	 * using a polling method rather than hotplug detection for TVs.
+	 * This is because in order to perform the hotplug detection, the PLLs
+	 * for the TV must be kept alive increasing power drain and starving
+	 * bandwidth from other encoders. Notably for instance, it causes
+	 * pipe underruns on Crestline when this encoder is supposedly idle.
+	 *
+	 * More recent chipsets favour HDMI rather than integrated S-Video.
+	 */
+	connector->polled =
+		DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT;
+
 	drm_connector_init(dev, connector, &intel_tv_connector_funcs,
 			   DRM_MODE_CONNECTOR_SVIDEO);
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/i915/Makefile linux-libre-2.6.38-gnu1/drivers/gpu/drm/i915/Makefile
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/i915/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/i915/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -9,6 +9,8 @@ i915-y := i915_drv.o i915_dma.o i915_irq
 	  i915_gem.o \
 	  i915_gem_debug.o \
 	  i915_gem_evict.o \
+	  i915_gem_execbuffer.o \
+	  i915_gem_gtt.o \
 	  i915_gem_tiling.o \
 	  i915_trace_points.o \
 	  intel_display.o \
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/Kconfig linux-libre-2.6.38-gnu1/drivers/gpu/drm/Kconfig
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -23,7 +23,7 @@ config DRM_KMS_HELPER
 	tristate
 	depends on DRM
 	select FB
-	select FRAMEBUFFER_CONSOLE if !EMBEDDED
+	select FRAMEBUFFER_CONSOLE if !EXPERT
 	help
 	  FB and CRTC helpers for KMS drivers.
 
@@ -100,14 +100,16 @@ config DRM_I830
 config DRM_I915
 	tristate "i915 driver"
 	depends on AGP_INTEL
+	# we need shmfs for the swappable backing store, and in particular
+	# the shmem_readpage() which depends upon tmpfs
 	select SHMEM
+	select TMPFS
 	select DRM_KMS_HELPER
 	select FB_CFB_FILLRECT
 	select FB_CFB_COPYAREA
 	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 VIDEO_OUTPUT_CONTROL if ACPI
 	select BACKLIGHT_CLASS_DEVICE if ACPI
 	select INPUT if ACPI
 	select ACPI_VIDEO if ACPI
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/Kconfig linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/Kconfig
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -8,9 +8,9 @@ config DRM_NOUVEAU
 	select FB_CFB_COPYAREA
 	select FB_CFB_IMAGEBLIT
 	select FB
-	select FRAMEBUFFER_CONSOLE if !EMBEDDED
+	select FRAMEBUFFER_CONSOLE if !EXPERT
 	select FB_BACKLIGHT if DRM_NOUVEAU_BACKLIGHT
-	select ACPI_VIDEO if ACPI
+	select ACPI_VIDEO if ACPI && X86 && BACKLIGHT_CLASS_DEVICE && VIDEO_OUTPUT_CONTROL && INPUT
 	help
 	  Choose this option for open-source nVidia support.
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/Makefile linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/Makefile
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -5,27 +5,32 @@
 ccflags-y := -Iinclude/drm
 nouveau-y := nouveau_drv.o nouveau_state.o nouveau_channel.o nouveau_mem.o \
              nouveau_object.o nouveau_irq.o nouveau_notifier.o \
-             nouveau_sgdma.o nouveau_dma.o \
+             nouveau_sgdma.o nouveau_dma.o nouveau_util.o \
              nouveau_bo.o nouveau_fence.o nouveau_gem.o nouveau_ttm.o \
              nouveau_hw.o nouveau_calc.o nouveau_bios.o nouveau_i2c.o \
              nouveau_display.o nouveau_connector.o nouveau_fbcon.o \
              nouveau_dp.o nouveau_ramht.o \
 	     nouveau_pm.o nouveau_volt.o nouveau_perf.o nouveau_temp.o \
+	     nouveau_mm.o nouveau_vm.o \
              nv04_timer.o \
              nv04_mc.o nv40_mc.o nv50_mc.o \
              nv04_fb.o nv10_fb.o nv30_fb.o nv40_fb.o nv50_fb.o nvc0_fb.o \
              nv04_fifo.o nv10_fifo.o nv40_fifo.o nv50_fifo.o nvc0_fifo.o \
              nv04_graph.o nv10_graph.o nv20_graph.o \
              nv40_graph.o nv50_graph.o nvc0_graph.o \
-             nv40_grctx.o nv50_grctx.o \
+             nv40_grctx.o nv50_grctx.o nvc0_grctx.o \
+             nv84_crypt.o \
              nv04_instmem.o nv50_instmem.o nvc0_instmem.o \
-             nv50_crtc.o nv50_dac.o nv50_sor.o \
-             nv50_cursor.o nv50_display.o nv50_fbcon.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 nv04_fbcon.o \
+             nv04_crtc.o nv04_display.o nv04_cursor.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 nv50_pm.o nva3_pm.o \
+	     nv50_vram.o nvc0_vram.o \
+	     nv50_vm.o nvc0_vm.o
 
 nouveau-$(CONFIG_DRM_NOUVEAU_DEBUG) += nouveau_debugfs.o
 nouveau-$(CONFIG_COMPAT) += nouveau_ioc32.o
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nouveau_acpi.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nouveau_acpi.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nouveau_acpi.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nouveau_acpi.c	2011-03-14 21:20:32.000000000 -0400
@@ -130,10 +130,15 @@ static int nouveau_dsm_init(void)
 
 static int nouveau_dsm_get_client_id(struct pci_dev *pdev)
 {
-	if (nouveau_dsm_priv.dhandle == DEVICE_ACPI_HANDLE(&pdev->dev))
+	/* easy option one - intel vendor ID means Integrated */
+	if (pdev->vendor == PCI_VENDOR_ID_INTEL)
 		return VGA_SWITCHEROO_IGD;
-	else
-		return VGA_SWITCHEROO_DIS;
+
+	/* is this device on Bus 0? - this may need improving */
+	if (pdev->bus->number == 0)
+		return VGA_SWITCHEROO_IGD;
+
+	return VGA_SWITCHEROO_DIS;
 }
 
 static struct vga_switcheroo_handler nouveau_dsm_handler = {
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nouveau_backlight.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nouveau_backlight.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nouveau_backlight.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nouveau_backlight.c	2011-03-14 21:20:32.000000000 -0400
@@ -59,7 +59,7 @@ static int nv40_set_intensity(struct bac
 	return 0;
 }
 
-static struct backlight_ops nv40_bl_ops = {
+static const struct backlight_ops nv40_bl_ops = {
 	.options = BL_CORE_SUSPENDRESUME,
 	.get_brightness = nv40_get_intensity,
 	.update_status = nv40_set_intensity,
@@ -82,7 +82,7 @@ static int nv50_set_intensity(struct bac
 	return 0;
 }
 
-static struct backlight_ops nv50_bl_ops = {
+static const struct backlight_ops nv50_bl_ops = {
 	.options = BL_CORE_SUSPENDRESUME,
 	.get_brightness = nv50_get_intensity,
 	.update_status = nv50_set_intensity,
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nouveau_bios.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nouveau_bios.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nouveau_bios.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nouveau_bios.c	2011-03-14 21:20:32.000000000 -0400
@@ -1927,7 +1927,7 @@ init_ltime(struct nvbios *bios, uint16_t
 	 * offset      (8  bit): opcode
 	 * offset + 1  (16 bit): time
 	 *
-	 * Sleep for "time" miliseconds.
+	 * Sleep for "time" milliseconds.
 	 */
 
 	unsigned time = ROM16(bios->data[offset + 1]);
@@ -1935,7 +1935,7 @@ init_ltime(struct nvbios *bios, uint16_t
 	if (!iexec->execute)
 		return 3;
 
-	BIOSLOG(bios, "0x%04X: Sleeping for 0x%04X miliseconds\n",
+	BIOSLOG(bios, "0x%04X: Sleeping for 0x%04X milliseconds\n",
 		offset, time);
 
 	msleep(time);
@@ -6053,52 +6053,17 @@ static struct dcb_entry *new_dcb_entry(s
 	return entry;
 }
 
-static void fabricate_vga_output(struct dcb_table *dcb, int i2c, int heads)
+static void fabricate_dcb_output(struct dcb_table *dcb, int type, int i2c,
+				 int heads, int or)
 {
 	struct dcb_entry *entry = new_dcb_entry(dcb);
 
-	entry->type = 0;
+	entry->type = type;
 	entry->i2c_index = i2c;
 	entry->heads = heads;
-	entry->location = DCB_LOC_ON_CHIP;
-	entry->or = 1;
-}
-
-static void fabricate_dvi_i_output(struct dcb_table *dcb, bool twoHeads)
-{
-	struct dcb_entry *entry = new_dcb_entry(dcb);
-
-	entry->type = 2;
-	entry->i2c_index = LEGACY_I2C_PANEL;
-	entry->heads = twoHeads ? 3 : 1;
-	entry->location = !DCB_LOC_ON_CHIP;	/* ie OFF CHIP */
-	entry->or = 1;	/* means |0x10 gets set on CRE_LCD__INDEX */
-	entry->duallink_possible = false; /* SiI164 and co. are single link */
-
-#if 0
-	/*
-	 * For dvi-a either crtc probably works, but my card appears to only
-	 * support dvi-d.  "nvidia" still attempts to program it for dvi-a,
-	 * doing the full fp output setup (program 0x6808.. fp dimension regs,
-	 * setting 0x680848 to 0x10000111 to enable, maybe setting 0x680880);
-	 * the monitor picks up the mode res ok and lights up, but no pixel
-	 * data appears, so the board manufacturer probably connected up the
-	 * sync lines, but missed the video traces / components
-	 *
-	 * with this introduction, dvi-a left as an exercise for the reader.
-	 */
-	fabricate_vga_output(dcb, LEGACY_I2C_PANEL, entry->heads);
-#endif
-}
-
-static void fabricate_tv_output(struct dcb_table *dcb, bool twoHeads)
-{
-	struct dcb_entry *entry = new_dcb_entry(dcb);
-
-	entry->type = 1;
-	entry->i2c_index = LEGACY_I2C_TV;
-	entry->heads = twoHeads ? 3 : 1;
-	entry->location = !DCB_LOC_ON_CHIP;	/* ie OFF CHIP */
+	if (type != OUTPUT_ANALOG)
+		entry->location = !DCB_LOC_ON_CHIP; /* ie OFF CHIP */
+	entry->or = or;
 }
 
 static bool
@@ -6263,7 +6228,7 @@ parse_dcb15_entry(struct drm_device *dev
 		entry->tvconf.has_component_output = false;
 		break;
 	case OUTPUT_LVDS:
-		if ((conn & 0x00003f00) != 0x10)
+		if ((conn & 0x00003f00) >> 8 != 0x10)
 			entry->lvdsconf.use_straps_for_mode = true;
 		entry->lvdsconf.use_power_scripts = true;
 		break;
@@ -6345,6 +6310,9 @@ void merge_like_dcb_entries(struct drm_d
 static bool
 apply_dcb_encoder_quirks(struct drm_device *dev, int idx, u32 *conn, u32 *conf)
 {
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct dcb_table *dcb = &dev_priv->vbios.dcb;
+
 	/* Dell Precision M6300
 	 *   DCB entry 2: 02025312 00000010
 	 *   DCB entry 3: 02026312 00000020
@@ -6362,11 +6330,51 @@ apply_dcb_encoder_quirks(struct drm_devi
 			return false;
 	}
 
+	/* GeForce3 Ti 200
+	 *
+	 * DCB reports an LVDS output that should be TMDS:
+	 *   DCB entry 1: f2005014 ffffffff
+	 */
+	if (nv_match_device(dev, 0x0201, 0x1462, 0x8851)) {
+		if (*conn == 0xf2005014 && *conf == 0xffffffff) {
+			fabricate_dcb_output(dcb, OUTPUT_TMDS, 1, 1, 1);
+			return false;
+		}
+	}
+
 	return true;
 }
 
+static void
+fabricate_dcb_encoder_table(struct drm_device *dev, struct nvbios *bios)
+{
+	struct dcb_table *dcb = &bios->dcb;
+	int all_heads = (nv_two_heads(dev) ? 3 : 1);
+
+#ifdef __powerpc__
+	/* Apple iMac G4 NV17 */
+	if (of_machine_is_compatible("PowerMac4,5")) {
+		fabricate_dcb_output(dcb, OUTPUT_TMDS, 0, all_heads, 1);
+		fabricate_dcb_output(dcb, OUTPUT_ANALOG, 1, all_heads, 2);
+		return;
+	}
+#endif
+
+	/* Make up some sane defaults */
+	fabricate_dcb_output(dcb, OUTPUT_ANALOG, LEGACY_I2C_CRT, 1, 1);
+
+	if (nv04_tv_identify(dev, bios->legacy.i2c_indices.tv) >= 0)
+		fabricate_dcb_output(dcb, OUTPUT_TV, LEGACY_I2C_TV,
+				     all_heads, 0);
+
+	else if (bios->tmds.output0_script_ptr ||
+		 bios->tmds.output1_script_ptr)
+		fabricate_dcb_output(dcb, OUTPUT_TMDS, LEGACY_I2C_PANEL,
+				     all_heads, 1);
+}
+
 static int
-parse_dcb_table(struct drm_device *dev, struct nvbios *bios, bool twoHeads)
+parse_dcb_table(struct drm_device *dev, struct nvbios *bios)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct dcb_table *dcb = &bios->dcb;
@@ -6386,12 +6394,7 @@ parse_dcb_table(struct drm_device *dev,
 
 	/* this situation likely means a really old card, pre DCB */
 	if (dcbptr == 0x0) {
-		NV_INFO(dev, "Assuming a CRT output exists\n");
-		fabricate_vga_output(dcb, LEGACY_I2C_CRT, 1);
-
-		if (nv04_tv_identify(dev, bios->legacy.i2c_indices.tv) >= 0)
-			fabricate_tv_output(dcb, twoHeads);
-
+		fabricate_dcb_encoder_table(dev, bios);
 		return 0;
 	}
 
@@ -6451,21 +6454,7 @@ parse_dcb_table(struct drm_device *dev,
 		 */
 		NV_TRACEWARN(dev, "No useful information in BIOS output table; "
 				  "adding all possible outputs\n");
-		fabricate_vga_output(dcb, LEGACY_I2C_CRT, 1);
-
-		/*
-		 * Attempt to detect TV before DVI because the test
-		 * for the former is more accurate and it rules the
-		 * latter out.
-		 */
-		if (nv04_tv_identify(dev,
-				     bios->legacy.i2c_indices.tv) >= 0)
-			fabricate_tv_output(dcb, twoHeads);
-
-		else if (bios->tmds.output0_script_ptr ||
-			 bios->tmds.output1_script_ptr)
-			fabricate_dvi_i_output(dcb, twoHeads);
-
+		fabricate_dcb_encoder_table(dev, bios);
 		return 0;
 	}
 
@@ -6859,7 +6848,7 @@ nouveau_bios_init(struct drm_device *dev
 	if (ret)
 		return ret;
 
-	ret = parse_dcb_table(dev, bios, nv_two_heads(dev));
+	ret = parse_dcb_table(dev, bios);
 	if (ret)
 		return ret;
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nouveau_bo.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nouveau_bo.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nouveau_bo.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nouveau_bo.c	2011-03-14 21:20:32.000000000 -0400
@@ -32,6 +32,8 @@
 #include "nouveau_drm.h"
 #include "nouveau_drv.h"
 #include "nouveau_dma.h"
+#include "nouveau_mm.h"
+#include "nouveau_vm.h"
 
 #include <linux/log2.h>
 #include <linux/slab.h>
@@ -46,82 +48,54 @@ nouveau_bo_del_ttm(struct ttm_buffer_obj
 	if (unlikely(nvbo->gem))
 		DRM_ERROR("bo %p still attached to GEM object\n", bo);
 
-	if (nvbo->tile)
-		nv10_mem_expire_tiling(dev, nvbo->tile, NULL);
-
+	nv10_mem_put_tile_region(dev, nvbo->tile, NULL);
+	if (nvbo->vma.node) {
+		nouveau_vm_unmap(&nvbo->vma);
+		nouveau_vm_put(&nvbo->vma);
+	}
 	kfree(nvbo);
 }
 
 static void
-nouveau_bo_fixup_align(struct drm_device *dev,
-		       uint32_t tile_mode, uint32_t tile_flags,
-		       int *align, int *size)
+nouveau_bo_fixup_align(struct nouveau_bo *nvbo, int *align, int *size,
+		       int *page_shift)
 {
-	struct drm_nouveau_private *dev_priv = dev->dev_private;
-
-	/*
-	 * Some of the tile_flags have a periodic structure of N*4096 bytes,
-	 * align to to that as well as the page size. Align the size to the
-	 * appropriate boundaries. This does imply that sizes are rounded up
-	 * 3-7 pages, so be aware of this and do not waste memory by allocating
-	 * many small buffers.
-	 */
-	if (dev_priv->card_type == NV_50) {
-		uint32_t block_size = dev_priv->vram_size >> 15;
-		int i;
-
-		switch (tile_flags) {
-		case 0x1800:
-		case 0x2800:
-		case 0x4800:
-		case 0x7a00:
-			if (is_power_of_2(block_size)) {
-				for (i = 1; i < 10; i++) {
-					*align = 12 * i * block_size;
-					if (!(*align % 65536))
-						break;
-				}
-			} else {
-				for (i = 1; i < 10; i++) {
-					*align = 8 * i * block_size;
-					if (!(*align % 65536))
-						break;
-				}
-			}
-			*size = roundup(*size, *align);
-			break;
-		default:
-			break;
-		}
+	struct drm_nouveau_private *dev_priv = nouveau_bdev(nvbo->bo.bdev);
 
-	} else {
-		if (tile_mode) {
+	if (dev_priv->card_type < NV_50) {
+		if (nvbo->tile_mode) {
 			if (dev_priv->chipset >= 0x40) {
 				*align = 65536;
-				*size = roundup(*size, 64 * tile_mode);
+				*size = roundup(*size, 64 * nvbo->tile_mode);
 
 			} else if (dev_priv->chipset >= 0x30) {
 				*align = 32768;
-				*size = roundup(*size, 64 * tile_mode);
+				*size = roundup(*size, 64 * nvbo->tile_mode);
 
 			} else if (dev_priv->chipset >= 0x20) {
 				*align = 16384;
-				*size = roundup(*size, 64 * tile_mode);
+				*size = roundup(*size, 64 * nvbo->tile_mode);
 
 			} else if (dev_priv->chipset >= 0x10) {
 				*align = 16384;
-				*size = roundup(*size, 32 * tile_mode);
+				*size = roundup(*size, 32 * nvbo->tile_mode);
 			}
 		}
+	} else {
+		if (likely(dev_priv->chan_vm)) {
+			if (*size > 256 * 1024)
+				*page_shift = dev_priv->chan_vm->lpg_shift;
+			else
+				*page_shift = dev_priv->chan_vm->spg_shift;
+		} else {
+			*page_shift = 12;
+		}
+
+		*size = roundup(*size, (1 << *page_shift));
+		*align = max((1 << *page_shift), *align);
 	}
 
-	/* ALIGN works only on powers of two. */
 	*size = roundup(*size, PAGE_SIZE);
-
-	if (dev_priv->card_type == NV_50) {
-		*size = roundup(*size, 65536);
-		*align = max(65536, *align);
-	}
 }
 
 int
@@ -132,7 +106,7 @@ nouveau_bo_new(struct drm_device *dev, s
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct nouveau_bo *nvbo;
-	int ret = 0;
+	int ret = 0, page_shift = 0;
 
 	nvbo = kzalloc(sizeof(struct nouveau_bo), GFP_KERNEL);
 	if (!nvbo)
@@ -145,10 +119,19 @@ nouveau_bo_new(struct drm_device *dev, s
 	nvbo->tile_flags = tile_flags;
 	nvbo->bo.bdev = &dev_priv->ttm.bdev;
 
-	nouveau_bo_fixup_align(dev, tile_mode, nouveau_bo_tile_layout(nvbo),
-			       &align, &size);
+	nouveau_bo_fixup_align(nvbo, &align, &size, &page_shift);
 	align >>= PAGE_SHIFT;
 
+	if (!nvbo->no_vm && dev_priv->chan_vm) {
+		ret = nouveau_vm_get(dev_priv->chan_vm, size, page_shift,
+				     NV_MEM_ACCESS_RW, &nvbo->vma);
+		if (ret) {
+			kfree(nvbo);
+			return ret;
+		}
+	}
+
+	nvbo->bo.mem.num_pages = size >> PAGE_SHIFT;
 	nouveau_bo_placement_set(nvbo, flags, 0);
 
 	nvbo->channel = chan;
@@ -161,6 +144,11 @@ nouveau_bo_new(struct drm_device *dev, s
 	}
 	nvbo->channel = NULL;
 
+	if (nvbo->vma.node) {
+		if (nvbo->bo.mem.mem_type == TTM_PL_VRAM)
+			nvbo->bo.offset = nvbo->vma.offset;
+	}
+
 	*pnvbo = nvbo;
 	return 0;
 }
@@ -182,17 +170,17 @@ static void
 set_placement_range(struct nouveau_bo *nvbo, uint32_t type)
 {
 	struct drm_nouveau_private *dev_priv = nouveau_bdev(nvbo->bo.bdev);
+	int vram_pages = dev_priv->vram_size >> PAGE_SHIFT;
 
 	if (dev_priv->card_type == NV_10 &&
-	    nvbo->tile_mode && (type & TTM_PL_FLAG_VRAM)) {
+	    nvbo->tile_mode && (type & TTM_PL_FLAG_VRAM) &&
+	    nvbo->bo.mem.num_pages < vram_pages / 2) {
 		/*
 		 * Make sure that the color and depth buffers are handled
 		 * by independent memory controller units. Up to a 9x
 		 * speed up when alpha-blending and depth-test are enabled
 		 * at the same time.
 		 */
-		int vram_pages = dev_priv->vram_size >> PAGE_SHIFT;
-
 		if (nvbo->tile_flags & NOUVEAU_GEM_TILE_ZETA) {
 			nvbo->placement.fpfn = vram_pages / 2;
 			nvbo->placement.lpfn = ~0;
@@ -244,7 +232,7 @@ nouveau_bo_pin(struct nouveau_bo *nvbo,
 
 	nouveau_bo_placement_set(nvbo, memtype, 0);
 
-	ret = ttm_bo_validate(bo, &nvbo->placement, false, false, false);
+	ret = nouveau_bo_validate(nvbo, false, false, false);
 	if (ret == 0) {
 		switch (bo->mem.mem_type) {
 		case TTM_PL_VRAM:
@@ -280,7 +268,7 @@ nouveau_bo_unpin(struct nouveau_bo *nvbo
 
 	nouveau_bo_placement_set(nvbo, bo->mem.placement, 0);
 
-	ret = ttm_bo_validate(bo, &nvbo->placement, false, false, false);
+	ret = nouveau_bo_validate(nvbo, false, false, false);
 	if (ret == 0) {
 		switch (bo->mem.mem_type) {
 		case TTM_PL_VRAM:
@@ -319,6 +307,25 @@ nouveau_bo_unmap(struct nouveau_bo *nvbo
 		ttm_bo_kunmap(&nvbo->kmap);
 }
 
+int
+nouveau_bo_validate(struct nouveau_bo *nvbo, bool interruptible,
+		    bool no_wait_reserve, bool no_wait_gpu)
+{
+	int ret;
+
+	ret = ttm_bo_validate(&nvbo->bo, &nvbo->placement, interruptible,
+			      no_wait_reserve, no_wait_gpu);
+	if (ret)
+		return ret;
+
+	if (nvbo->vma.node) {
+		if (nvbo->bo.mem.mem_type == TTM_PL_VRAM)
+			nvbo->bo.offset = nvbo->vma.offset;
+	}
+
+	return 0;
+}
+
 u16
 nouveau_bo_rd16(struct nouveau_bo *nvbo, unsigned index)
 {
@@ -410,37 +417,40 @@ nouveau_bo_init_mem_type(struct ttm_bo_d
 		man->default_caching = TTM_PL_FLAG_CACHED;
 		break;
 	case TTM_PL_VRAM:
-		man->func = &ttm_bo_manager_func;
+		if (dev_priv->card_type >= NV_50) {
+			man->func = &nouveau_vram_manager;
+			man->io_reserve_fastpath = false;
+			man->use_io_reserve_lru = true;
+		} else {
+			man->func = &ttm_bo_manager_func;
+		}
 		man->flags = TTM_MEMTYPE_FLAG_FIXED |
 			     TTM_MEMTYPE_FLAG_MAPPABLE;
 		man->available_caching = TTM_PL_FLAG_UNCACHED |
 					 TTM_PL_FLAG_WC;
 		man->default_caching = TTM_PL_FLAG_WC;
-		if (dev_priv->card_type == NV_50)
-			man->gpu_offset = 0x40000000;
-		else
-			man->gpu_offset = 0;
 		break;
 	case TTM_PL_TT:
 		man->func = &ttm_bo_manager_func;
 		switch (dev_priv->gart_info.type) {
 		case NOUVEAU_GART_AGP:
 			man->flags = TTM_MEMTYPE_FLAG_MAPPABLE;
-			man->available_caching = TTM_PL_FLAG_UNCACHED;
-			man->default_caching = TTM_PL_FLAG_UNCACHED;
+			man->available_caching = TTM_PL_FLAG_UNCACHED |
+				TTM_PL_FLAG_WC;
+			man->default_caching = TTM_PL_FLAG_WC;
 			break;
 		case NOUVEAU_GART_SGDMA:
 			man->flags = TTM_MEMTYPE_FLAG_MAPPABLE |
 				     TTM_MEMTYPE_FLAG_CMA;
 			man->available_caching = TTM_PL_MASK_CACHING;
 			man->default_caching = TTM_PL_FLAG_CACHED;
+			man->gpu_offset = dev_priv->gart_info.aper_base;
 			break;
 		default:
 			NV_ERROR(dev, "Unknown GART type: %d\n",
 				 dev_priv->gart_info.type);
 			return -EINVAL;
 		}
-		man->gpu_offset = dev_priv->vm_gart_base;
 		break;
 	default:
 		NV_ERROR(dev, "Unsupported memory type %u\n", (unsigned)type);
@@ -485,16 +495,9 @@ nouveau_bo_move_accel_cleanup(struct nou
 	if (ret)
 		return ret;
 
-	if (nvbo->channel) {
-		ret = nouveau_fence_sync(fence, nvbo->channel);
-		if (ret)
-			goto out;
-	}
-
 	ret = ttm_bo_move_accel_cleanup(&nvbo->bo, fence, NULL, evict,
 					no_wait_reserve, no_wait_gpu, new_mem);
-out:
-	nouveau_fence_unref((void *)&fence);
+	nouveau_fence_unref(&fence);
 	return ret;
 }
 
@@ -516,6 +519,58 @@ nouveau_bo_mem_ctxdma(struct ttm_buffer_
 }
 
 static int
+nvc0_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo,
+		  struct ttm_mem_reg *old_mem, struct ttm_mem_reg *new_mem)
+{
+	struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev);
+	struct nouveau_bo *nvbo = nouveau_bo(bo);
+	u64 src_offset = old_mem->start << PAGE_SHIFT;
+	u64 dst_offset = new_mem->start << PAGE_SHIFT;
+	u32 page_count = new_mem->num_pages;
+	int ret;
+
+	if (!nvbo->no_vm) {
+		if (old_mem->mem_type == TTM_PL_VRAM)
+			src_offset  = nvbo->vma.offset;
+		else
+			src_offset += dev_priv->gart_info.aper_base;
+
+		if (new_mem->mem_type == TTM_PL_VRAM)
+			dst_offset  = nvbo->vma.offset;
+		else
+			dst_offset += dev_priv->gart_info.aper_base;
+	}
+
+	page_count = new_mem->num_pages;
+	while (page_count) {
+		int line_count = (page_count > 2047) ? 2047 : page_count;
+
+		ret = RING_SPACE(chan, 12);
+		if (ret)
+			return ret;
+
+		BEGIN_NVC0(chan, 2, NvSubM2MF, 0x0238, 2);
+		OUT_RING  (chan, upper_32_bits(dst_offset));
+		OUT_RING  (chan, lower_32_bits(dst_offset));
+		BEGIN_NVC0(chan, 2, NvSubM2MF, 0x030c, 6);
+		OUT_RING  (chan, upper_32_bits(src_offset));
+		OUT_RING  (chan, lower_32_bits(src_offset));
+		OUT_RING  (chan, PAGE_SIZE); /* src_pitch */
+		OUT_RING  (chan, PAGE_SIZE); /* dst_pitch */
+		OUT_RING  (chan, PAGE_SIZE); /* line_length */
+		OUT_RING  (chan, line_count);
+		BEGIN_NVC0(chan, 2, NvSubM2MF, 0x0300, 1);
+		OUT_RING  (chan, 0x00100110);
+
+		page_count -= line_count;
+		src_offset += (PAGE_SIZE * line_count);
+		dst_offset += (PAGE_SIZE * line_count);
+	}
+
+	return 0;
+}
+
+static int
 nv50_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo,
 		  struct ttm_mem_reg *old_mem, struct ttm_mem_reg *new_mem)
 {
@@ -529,14 +584,14 @@ nv50_bo_move_m2mf(struct nouveau_channel
 	dst_offset = new_mem->start << PAGE_SHIFT;
 	if (!nvbo->no_vm) {
 		if (old_mem->mem_type == TTM_PL_VRAM)
-			src_offset += dev_priv->vm_vram_base;
+			src_offset  = nvbo->vma.offset;
 		else
-			src_offset += dev_priv->vm_gart_base;
+			src_offset += dev_priv->gart_info.aper_base;
 
 		if (new_mem->mem_type == TTM_PL_VRAM)
-			dst_offset += dev_priv->vm_vram_base;
+			dst_offset  = nvbo->vma.offset;
 		else
-			dst_offset += dev_priv->vm_gart_base;
+			dst_offset += dev_priv->gart_info.aper_base;
 	}
 
 	ret = RING_SPACE(chan, 3);
@@ -683,17 +738,27 @@ nouveau_bo_move_m2mf(struct ttm_buffer_o
 	int ret;
 
 	chan = nvbo->channel;
-	if (!chan || nvbo->no_vm)
+	if (!chan || nvbo->no_vm) {
 		chan = dev_priv->channel;
+		mutex_lock_nested(&chan->mutex, NOUVEAU_KCHANNEL_MUTEX);
+	}
 
 	if (dev_priv->card_type < NV_50)
 		ret = nv04_bo_move_m2mf(chan, bo, &bo->mem, new_mem);
 	else
+	if (dev_priv->card_type < NV_C0)
 		ret = nv50_bo_move_m2mf(chan, bo, &bo->mem, new_mem);
-	if (ret)
-		return ret;
+	else
+		ret = nvc0_bo_move_m2mf(chan, bo, &bo->mem, new_mem);
+	if (ret == 0) {
+		ret = nouveau_bo_move_accel_cleanup(chan, nvbo, evict,
+						    no_wait_reserve,
+						    no_wait_gpu, new_mem);
+	}
 
-	return nouveau_bo_move_accel_cleanup(chan, nvbo, evict, no_wait_reserve, no_wait_gpu, new_mem);
+	if (chan == dev_priv->channel)
+		mutex_unlock(&chan->mutex);
+	return ret;
 }
 
 static int
@@ -724,7 +789,7 @@ nouveau_bo_move_flipd(struct ttm_buffer_
 	if (ret)
 		goto out;
 
-	ret = ttm_bo_move_ttm(bo, evict, no_wait_reserve, no_wait_gpu, new_mem);
+	ret = ttm_bo_move_ttm(bo, true, no_wait_reserve, no_wait_gpu, new_mem);
 out:
 	ttm_bo_mem_put(bo, &tmp_mem);
 	return ret;
@@ -750,11 +815,11 @@ nouveau_bo_move_flips(struct ttm_buffer_
 	if (ret)
 		return ret;
 
-	ret = ttm_bo_move_ttm(bo, evict, no_wait_reserve, no_wait_gpu, &tmp_mem);
+	ret = ttm_bo_move_ttm(bo, true, no_wait_reserve, no_wait_gpu, &tmp_mem);
 	if (ret)
 		goto out;
 
-	ret = nouveau_bo_move_m2mf(bo, evict, intr, no_wait_reserve, no_wait_gpu, new_mem);
+	ret = nouveau_bo_move_m2mf(bo, true, intr, no_wait_reserve, no_wait_gpu, new_mem);
 	if (ret)
 		goto out;
 
@@ -771,7 +836,6 @@ nouveau_bo_vm_bind(struct ttm_buffer_obj
 	struct drm_device *dev = dev_priv->dev;
 	struct nouveau_bo *nvbo = nouveau_bo(bo);
 	uint64_t offset;
-	int ret;
 
 	if (nvbo->no_vm || new_mem->mem_type != TTM_PL_VRAM) {
 		/* Nothing to do. */
@@ -781,18 +845,12 @@ nouveau_bo_vm_bind(struct ttm_buffer_obj
 
 	offset = new_mem->start << PAGE_SHIFT;
 
-	if (dev_priv->card_type == NV_50) {
-		ret = nv50_mem_vm_bind_linear(dev,
-					      offset + dev_priv->vm_vram_base,
-					      new_mem->size,
-					      nouveau_bo_tile_layout(nvbo),
-					      offset);
-		if (ret)
-			return ret;
-
+	if (dev_priv->chan_vm) {
+		nouveau_vm_map(&nvbo->vma, new_mem->mm_node);
 	} else if (dev_priv->card_type >= NV_10) {
 		*new_tile = nv10_mem_set_tiling(dev, offset, new_mem->size,
-						nvbo->tile_mode);
+						nvbo->tile_mode,
+						nvbo->tile_flags);
 	}
 
 	return 0;
@@ -808,9 +866,7 @@ nouveau_bo_vm_cleanup(struct ttm_buffer_
 
 	if (dev_priv->card_type >= NV_10 &&
 	    dev_priv->card_type < NV_50) {
-		if (*old_tile)
-			nv10_mem_expire_tiling(dev, *old_tile, bo->sync_obj);
-
+		nv10_mem_put_tile_region(dev, *old_tile, bo->sync_obj);
 		*old_tile = new_tile;
 	}
 }
@@ -879,6 +935,7 @@ nouveau_ttm_io_mem_reserve(struct ttm_bo
 	struct ttm_mem_type_manager *man = &bdev->man[mem->mem_type];
 	struct drm_nouveau_private *dev_priv = nouveau_bdev(bdev);
 	struct drm_device *dev = dev_priv->dev;
+	int ret;
 
 	mem->bus.addr = NULL;
 	mem->bus.offset = 0;
@@ -901,9 +958,40 @@ nouveau_ttm_io_mem_reserve(struct ttm_bo
 #endif
 		break;
 	case TTM_PL_VRAM:
-		mem->bus.offset = mem->start << PAGE_SHIFT;
+	{
+		struct nouveau_vram *vram = mem->mm_node;
+		u8 page_shift;
+
+		if (!dev_priv->bar1_vm) {
+			mem->bus.offset = mem->start << PAGE_SHIFT;
+			mem->bus.base = pci_resource_start(dev->pdev, 1);
+			mem->bus.is_iomem = true;
+			break;
+		}
+
+		if (dev_priv->card_type == NV_C0)
+			page_shift = vram->page_shift;
+		else
+			page_shift = 12;
+
+		ret = nouveau_vm_get(dev_priv->bar1_vm, mem->bus.size,
+				     page_shift, NV_MEM_ACCESS_RW,
+				     &vram->bar_vma);
+		if (ret)
+			return ret;
+
+		nouveau_vm_map(&vram->bar_vma, vram);
+		if (ret) {
+			nouveau_vm_put(&vram->bar_vma);
+			return ret;
+		}
+
+		mem->bus.offset = vram->bar_vma.offset;
+		if (dev_priv->card_type == NV_50) /*XXX*/
+			mem->bus.offset -= 0x0020000000ULL;
 		mem->bus.base = pci_resource_start(dev->pdev, 1);
 		mem->bus.is_iomem = true;
+	}
 		break;
 	default:
 		return -EINVAL;
@@ -914,6 +1002,17 @@ nouveau_ttm_io_mem_reserve(struct ttm_bo
 static void
 nouveau_ttm_io_mem_free(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem)
 {
+	struct drm_nouveau_private *dev_priv = nouveau_bdev(bdev);
+	struct nouveau_vram *vram = mem->mm_node;
+
+	if (!dev_priv->bar1_vm || mem->mem_type != TTM_PL_VRAM)
+		return;
+
+	if (!vram->bar_vma.node)
+		return;
+
+	nouveau_vm_unmap(&vram->bar_vma);
+	nouveau_vm_put(&vram->bar_vma);
 }
 
 static int
@@ -939,7 +1038,23 @@ nouveau_ttm_fault_reserve_notify(struct
 	nvbo->placement.fpfn = 0;
 	nvbo->placement.lpfn = dev_priv->fb_mappable_pages;
 	nouveau_bo_placement_set(nvbo, TTM_PL_VRAM, 0);
-	return ttm_bo_validate(bo, &nvbo->placement, false, true, false);
+	return nouveau_bo_validate(nvbo, false, true, false);
+}
+
+void
+nouveau_bo_fence(struct nouveau_bo *nvbo, struct nouveau_fence *fence)
+{
+	struct nouveau_fence *old_fence;
+
+	if (likely(fence))
+		nouveau_fence_ref(fence);
+
+	spin_lock(&nvbo->bo.bdev->fence_lock);
+	old_fence = nvbo->bo.sync_obj;
+	nvbo->bo.sync_obj = fence;
+	spin_unlock(&nvbo->bo.bdev->fence_lock);
+
+	nouveau_fence_unref(&old_fence);
 }
 
 struct ttm_bo_driver nouveau_bo_driver = {
@@ -949,11 +1064,11 @@ struct ttm_bo_driver nouveau_bo_driver =
 	.evict_flags = nouveau_bo_evict_flags,
 	.move = nouveau_bo_move,
 	.verify_access = nouveau_bo_verify_access,
-	.sync_obj_signaled = nouveau_fence_signalled,
-	.sync_obj_wait = nouveau_fence_wait,
-	.sync_obj_flush = nouveau_fence_flush,
-	.sync_obj_unref = nouveau_fence_unref,
-	.sync_obj_ref = nouveau_fence_ref,
+	.sync_obj_signaled = __nouveau_fence_signalled,
+	.sync_obj_wait = __nouveau_fence_wait,
+	.sync_obj_flush = __nouveau_fence_flush,
+	.sync_obj_unref = __nouveau_fence_unref,
+	.sync_obj_ref = __nouveau_fence_ref,
 	.fault_reserve_notify = &nouveau_ttm_fault_reserve_notify,
 	.io_mem_reserve = &nouveau_ttm_io_mem_reserve,
 	.io_mem_free = &nouveau_ttm_io_mem_free,
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nouveau_channel.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nouveau_channel.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nouveau_channel.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nouveau_channel.c	2011-03-14 21:20:32.000000000 -0400
@@ -38,23 +38,28 @@ nouveau_channel_pushbuf_ctxdma_init(stru
 	int ret;
 
 	if (dev_priv->card_type >= NV_50) {
-		ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, 0,
-					     dev_priv->vm_end, NV_DMA_ACCESS_RO,
-					     NV_DMA_TARGET_AGP, &pushbuf);
+		if (dev_priv->card_type < NV_C0) {
+			ret = nouveau_gpuobj_dma_new(chan,
+						     NV_CLASS_DMA_IN_MEMORY, 0,
+						     (1ULL << 40),
+						     NV_MEM_ACCESS_RO,
+						     NV_MEM_TARGET_VM,
+						     &pushbuf);
+		}
 		chan->pushbuf_base = pb->bo.offset;
 	} else
 	if (pb->bo.mem.mem_type == TTM_PL_TT) {
-		ret = nouveau_gpuobj_gart_dma_new(chan, 0,
-						  dev_priv->gart_info.aper_size,
-						  NV_DMA_ACCESS_RO, &pushbuf,
-						  NULL);
+		ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, 0,
+					     dev_priv->gart_info.aper_size,
+					     NV_MEM_ACCESS_RO,
+					     NV_MEM_TARGET_GART, &pushbuf);
 		chan->pushbuf_base = pb->bo.mem.start << PAGE_SHIFT;
 	} else
 	if (dev_priv->card_type != NV_04) {
 		ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, 0,
 					     dev_priv->fb_available_size,
-					     NV_DMA_ACCESS_RO,
-					     NV_DMA_TARGET_VIDMEM, &pushbuf);
+					     NV_MEM_ACCESS_RO,
+					     NV_MEM_TARGET_VRAM, &pushbuf);
 		chan->pushbuf_base = pb->bo.mem.start << PAGE_SHIFT;
 	} else {
 		/* NV04 cmdbuf hack, from original ddx.. not sure of it's
@@ -62,17 +67,16 @@ nouveau_channel_pushbuf_ctxdma_init(stru
 		 * VRAM.
 		 */
 		ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY,
-					     pci_resource_start(dev->pdev,
-					     1),
+					     pci_resource_start(dev->pdev, 1),
 					     dev_priv->fb_available_size,
-					     NV_DMA_ACCESS_RO,
-					     NV_DMA_TARGET_PCI, &pushbuf);
+					     NV_MEM_ACCESS_RO,
+					     NV_MEM_TARGET_PCI, &pushbuf);
 		chan->pushbuf_base = pb->bo.mem.start << PAGE_SHIFT;
 	}
 
 	nouveau_gpuobj_ref(pushbuf, &chan->pushbuf);
 	nouveau_gpuobj_ref(NULL, &pushbuf);
-	return 0;
+	return ret;
 }
 
 static struct nouveau_bo *
@@ -100,6 +104,13 @@ nouveau_channel_user_pushbuf_alloc(struc
 		return NULL;
 	}
 
+	ret = nouveau_bo_map(pushbuf);
+	if (ret) {
+		nouveau_bo_unpin(pushbuf);
+		nouveau_bo_ref(NULL, &pushbuf);
+		return NULL;
+	}
+
 	return pushbuf;
 }
 
@@ -107,74 +118,59 @@ nouveau_channel_user_pushbuf_alloc(struc
 int
 nouveau_channel_alloc(struct drm_device *dev, struct nouveau_channel **chan_ret,
 		      struct drm_file *file_priv,
-		      uint32_t vram_handle, uint32_t tt_handle)
+		      uint32_t vram_handle, uint32_t gart_handle)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
 	struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo;
 	struct nouveau_channel *chan;
-	int channel, user;
+	unsigned long flags;
 	int ret;
 
-	/*
-	 * Alright, here is the full story
-	 * Nvidia cards have multiple hw fifo contexts (praise them for that,
-	 * no complicated crash-prone context switches)
-	 * We allocate a new context for each app and let it write to it
-	 * directly (woo, full userspace command submission !)
-	 * When there are no more contexts, you lost
-	 */
-	for (channel = 0; channel < pfifo->channels; channel++) {
-		if (dev_priv->fifos[channel] == NULL)
+	/* allocate and lock channel structure */
+	chan = kzalloc(sizeof(*chan), GFP_KERNEL);
+	if (!chan)
+		return -ENOMEM;
+	chan->dev = dev;
+	chan->file_priv = file_priv;
+	chan->vram_handle = vram_handle;
+	chan->gart_handle = gart_handle;
+
+	kref_init(&chan->ref);
+	atomic_set(&chan->users, 1);
+	mutex_init(&chan->mutex);
+	mutex_lock(&chan->mutex);
+
+	/* allocate hw channel id */
+	spin_lock_irqsave(&dev_priv->channels.lock, flags);
+	for (chan->id = 0; chan->id < pfifo->channels; chan->id++) {
+		if (!dev_priv->channels.ptr[chan->id]) {
+			nouveau_channel_ref(chan, &dev_priv->channels.ptr[chan->id]);
 			break;
+		}
 	}
+	spin_unlock_irqrestore(&dev_priv->channels.lock, flags);
 
-	/* no more fifos. you lost. */
-	if (channel == pfifo->channels)
-		return -EINVAL;
+	if (chan->id == pfifo->channels) {
+		mutex_unlock(&chan->mutex);
+		kfree(chan);
+		return -ENODEV;
+	}
 
-	dev_priv->fifos[channel] = kzalloc(sizeof(struct nouveau_channel),
-					   GFP_KERNEL);
-	if (!dev_priv->fifos[channel])
-		return -ENOMEM;
-	chan = dev_priv->fifos[channel];
+	NV_DEBUG(dev, "initialising channel %d\n", chan->id);
 	INIT_LIST_HEAD(&chan->nvsw.vbl_wait);
+	INIT_LIST_HEAD(&chan->nvsw.flip);
 	INIT_LIST_HEAD(&chan->fence.pending);
-	chan->dev = dev;
-	chan->id = channel;
-	chan->file_priv = file_priv;
-	chan->vram_handle = vram_handle;
-	chan->gart_handle = tt_handle;
-
-	NV_INFO(dev, "Allocating FIFO number %d\n", channel);
 
 	/* Allocate DMA push buffer */
 	chan->pushbuf_bo = nouveau_channel_user_pushbuf_alloc(dev);
 	if (!chan->pushbuf_bo) {
 		ret = -ENOMEM;
 		NV_ERROR(dev, "pushbuf %d\n", ret);
-		nouveau_channel_free(chan);
+		nouveau_channel_put(&chan);
 		return ret;
 	}
 
 	nouveau_dma_pre_init(chan);
-
-	/* Locate channel's user control regs */
-	if (dev_priv->card_type < NV_40)
-		user = NV03_USER(channel);
-	else
-	if (dev_priv->card_type < NV_50)
-		user = NV40_USER(channel);
-	else
-		user = NV50_USER(channel);
-
-	chan->user = ioremap(pci_resource_start(dev->pdev, 0) + user,
-								PAGE_SIZE);
-	if (!chan->user) {
-		NV_ERROR(dev, "ioremap of regs failed.\n");
-		nouveau_channel_free(chan);
-		return -ENOMEM;
-	}
 	chan->user_put = 0x40;
 	chan->user_get = 0x44;
 
@@ -182,15 +178,15 @@ nouveau_channel_alloc(struct drm_device
 	ret = nouveau_notifier_init_channel(chan);
 	if (ret) {
 		NV_ERROR(dev, "ntfy %d\n", ret);
-		nouveau_channel_free(chan);
+		nouveau_channel_put(&chan);
 		return ret;
 	}
 
 	/* Setup channel's default objects */
-	ret = nouveau_gpuobj_channel_init(chan, vram_handle, tt_handle);
+	ret = nouveau_gpuobj_channel_init(chan, vram_handle, gart_handle);
 	if (ret) {
 		NV_ERROR(dev, "gpuobj %d\n", ret);
-		nouveau_channel_free(chan);
+		nouveau_channel_put(&chan);
 		return ret;
 	}
 
@@ -198,24 +194,17 @@ nouveau_channel_alloc(struct drm_device
 	ret = nouveau_channel_pushbuf_ctxdma_init(chan);
 	if (ret) {
 		NV_ERROR(dev, "pbctxdma %d\n", ret);
-		nouveau_channel_free(chan);
+		nouveau_channel_put(&chan);
 		return ret;
 	}
 
 	/* disable the fifo caches */
 	pfifo->reassign(dev, false);
 
-	/* Create a graphics context for new channel */
-	ret = pgraph->create_context(chan);
-	if (ret) {
-		nouveau_channel_free(chan);
-		return ret;
-	}
-
 	/* Construct inital RAMFC for new channel */
 	ret = pfifo->create_context(chan);
 	if (ret) {
-		nouveau_channel_free(chan);
+		nouveau_channel_put(&chan);
 		return ret;
 	}
 
@@ -225,83 +214,111 @@ nouveau_channel_alloc(struct drm_device
 	if (!ret)
 		ret = nouveau_fence_channel_init(chan);
 	if (ret) {
-		nouveau_channel_free(chan);
+		nouveau_channel_put(&chan);
 		return ret;
 	}
 
 	nouveau_debugfs_channel_init(chan);
 
-	NV_INFO(dev, "%s: initialised FIFO %d\n", __func__, channel);
+	NV_DEBUG(dev, "channel %d initialised\n", chan->id);
 	*chan_ret = chan;
 	return 0;
 }
 
-/* stops a fifo */
+struct nouveau_channel *
+nouveau_channel_get_unlocked(struct nouveau_channel *ref)
+{
+	struct nouveau_channel *chan = NULL;
+
+	if (likely(ref && atomic_inc_not_zero(&ref->users)))
+		nouveau_channel_ref(ref, &chan);
+
+	return chan;
+}
+
+struct nouveau_channel *
+nouveau_channel_get(struct drm_device *dev, struct drm_file *file_priv, int id)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_channel *chan;
+	unsigned long flags;
+
+	if (unlikely(id < 0 || id >= NOUVEAU_MAX_CHANNEL_NR))
+		return ERR_PTR(-EINVAL);
+
+	spin_lock_irqsave(&dev_priv->channels.lock, flags);
+	chan = nouveau_channel_get_unlocked(dev_priv->channels.ptr[id]);
+	spin_unlock_irqrestore(&dev_priv->channels.lock, flags);
+
+	if (unlikely(!chan))
+		return ERR_PTR(-EINVAL);
+
+	if (unlikely(file_priv && chan->file_priv != file_priv)) {
+		nouveau_channel_put_unlocked(&chan);
+		return ERR_PTR(-EINVAL);
+	}
+
+	mutex_lock(&chan->mutex);
+	return chan;
+}
+
 void
-nouveau_channel_free(struct nouveau_channel *chan)
+nouveau_channel_put_unlocked(struct nouveau_channel **pchan)
 {
+	struct nouveau_channel *chan = *pchan;
 	struct drm_device *dev = chan->dev;
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
 	struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo;
+	struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
+	struct nouveau_crypt_engine *pcrypt = &dev_priv->engine.crypt;
 	unsigned long flags;
-	int ret;
 
-	NV_INFO(dev, "%s: freeing fifo %d\n", __func__, chan->id);
+	/* decrement the refcount, and we're done if there's still refs */
+	if (likely(!atomic_dec_and_test(&chan->users))) {
+		nouveau_channel_ref(NULL, pchan);
+		return;
+	}
 
+	/* noone wants the channel anymore */
+	NV_DEBUG(dev, "freeing channel %d\n", chan->id);
 	nouveau_debugfs_channel_fini(chan);
 
-	/* Give outstanding push buffers a chance to complete */
-	nouveau_fence_update(chan);
-	if (chan->fence.sequence != chan->fence.sequence_ack) {
-		struct nouveau_fence *fence = NULL;
-
-		ret = nouveau_fence_new(chan, &fence, true);
-		if (ret == 0) {
-			ret = nouveau_fence_wait(fence, NULL, false, false);
-			nouveau_fence_unref((void *)&fence);
-		}
-
-		if (ret)
-			NV_ERROR(dev, "Failed to idle channel %d.\n", chan->id);
-	}
+	/* give it chance to idle */
+	nouveau_channel_idle(chan);
 
-	/* Ensure all outstanding fences are signaled.  They should be if the
+	/* ensure all outstanding fences are signaled.  they should be if the
 	 * above attempts at idling were OK, but if we failed this'll tell TTM
 	 * we're done with the buffers.
 	 */
 	nouveau_fence_channel_fini(chan);
 
-	/* This will prevent pfifo from switching channels. */
+	/* boot it off the hardware */
 	pfifo->reassign(dev, false);
 
-	/* We want to give pgraph a chance to idle and get rid of all potential
-	 * errors. We need to do this before the lock, otherwise the irq handler
-	 * is unable to process them.
+	/* We want to give pgraph a chance to idle and get rid of all
+	 * potential errors. We need to do this without the context
+	 * switch lock held, otherwise the irq handler is unable to
+	 * process them.
 	 */
 	if (pgraph->channel(dev) == chan)
 		nouveau_wait_for_idle(dev);
 
-	spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
-
-	pgraph->fifo_access(dev, false);
-	if (pgraph->channel(dev) == chan)
-		pgraph->unload_context(dev);
-	pgraph->destroy_context(chan);
-	pgraph->fifo_access(dev, true);
-
-	if (pfifo->channel_id(dev) == chan->id) {
-		pfifo->disable(dev);
-		pfifo->unload_context(dev);
-		pfifo->enable(dev);
-	}
+	/* destroy the engine specific contexts */
 	pfifo->destroy_context(chan);
+	pgraph->destroy_context(chan);
+	if (pcrypt->destroy_context)
+		pcrypt->destroy_context(chan);
 
 	pfifo->reassign(dev, true);
 
-	spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
+	/* aside from its resources, the channel should now be dead,
+	 * remove it from the channel list
+	 */
+	spin_lock_irqsave(&dev_priv->channels.lock, flags);
+	nouveau_channel_ref(NULL, &dev_priv->channels.ptr[chan->id]);
+	spin_unlock_irqrestore(&dev_priv->channels.lock, flags);
 
-	/* Release the channel's resources */
+	/* destroy any resources the channel owned */
 	nouveau_gpuobj_ref(NULL, &chan->pushbuf);
 	if (chan->pushbuf_bo) {
 		nouveau_bo_unmap(chan->pushbuf_bo);
@@ -310,44 +327,80 @@ nouveau_channel_free(struct nouveau_chan
 	}
 	nouveau_gpuobj_channel_takedown(chan);
 	nouveau_notifier_takedown_channel(chan);
-	if (chan->user)
-		iounmap(chan->user);
 
-	dev_priv->fifos[chan->id] = NULL;
+	nouveau_channel_ref(NULL, pchan);
+}
+
+void
+nouveau_channel_put(struct nouveau_channel **pchan)
+{
+	mutex_unlock(&(*pchan)->mutex);
+	nouveau_channel_put_unlocked(pchan);
+}
+
+static void
+nouveau_channel_del(struct kref *ref)
+{
+	struct nouveau_channel *chan =
+		container_of(ref, struct nouveau_channel, ref);
+
 	kfree(chan);
 }
 
+void
+nouveau_channel_ref(struct nouveau_channel *chan,
+		    struct nouveau_channel **pchan)
+{
+	if (chan)
+		kref_get(&chan->ref);
+
+	if (*pchan)
+		kref_put(&(*pchan)->ref, nouveau_channel_del);
+
+	*pchan = chan;
+}
+
+void
+nouveau_channel_idle(struct nouveau_channel *chan)
+{
+	struct drm_device *dev = chan->dev;
+	struct nouveau_fence *fence = NULL;
+	int ret;
+
+	nouveau_fence_update(chan);
+
+	if (chan->fence.sequence != chan->fence.sequence_ack) {
+		ret = nouveau_fence_new(chan, &fence, true);
+		if (!ret) {
+			ret = nouveau_fence_wait(fence, false, false);
+			nouveau_fence_unref(&fence);
+		}
+
+		if (ret)
+			NV_ERROR(dev, "Failed to idle channel %d.\n", chan->id);
+	}
+}
+
 /* cleans up all the fifos from file_priv */
 void
 nouveau_channel_cleanup(struct drm_device *dev, struct drm_file *file_priv)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct nouveau_engine *engine = &dev_priv->engine;
+	struct nouveau_channel *chan;
 	int i;
 
 	NV_DEBUG(dev, "clearing FIFO enables from file_priv\n");
 	for (i = 0; i < engine->fifo.channels; i++) {
-		struct nouveau_channel *chan = dev_priv->fifos[i];
+		chan = nouveau_channel_get(dev, file_priv, i);
+		if (IS_ERR(chan))
+			continue;
 
-		if (chan && chan->file_priv == file_priv)
-			nouveau_channel_free(chan);
+		atomic_dec(&chan->users);
+		nouveau_channel_put(&chan);
 	}
 }
 
-int
-nouveau_channel_owner(struct drm_device *dev, struct drm_file *file_priv,
-		      int channel)
-{
-	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nouveau_engine *engine = &dev_priv->engine;
-
-	if (channel >= engine->fifo.channels)
-		return 0;
-	if (dev_priv->fifos[channel] == NULL)
-		return 0;
-
-	return (dev_priv->fifos[channel]->file_priv == file_priv);
-}
 
 /***********************************
  * ioctls wrapping the functions
@@ -383,36 +436,44 @@ nouveau_ioctl_fifo_alloc(struct drm_devi
 	else
 		init->pushbuf_domains = NOUVEAU_GEM_DOMAIN_GART;
 
-	init->subchan[0].handle = NvM2MF;
-	if (dev_priv->card_type < NV_50)
-		init->subchan[0].grclass = 0x0039;
-	else
-		init->subchan[0].grclass = 0x5039;
-	init->subchan[1].handle = NvSw;
-	init->subchan[1].grclass = NV_SW;
-	init->nr_subchan = 2;
+	if (dev_priv->card_type < NV_C0) {
+		init->subchan[0].handle = NvM2MF;
+		if (dev_priv->card_type < NV_50)
+			init->subchan[0].grclass = 0x0039;
+		else
+			init->subchan[0].grclass = 0x5039;
+		init->subchan[1].handle = NvSw;
+		init->subchan[1].grclass = NV_SW;
+		init->nr_subchan = 2;
+	} else {
+		init->subchan[0].handle  = 0x9039;
+		init->subchan[0].grclass = 0x9039;
+		init->nr_subchan = 1;
+	}
 
 	/* Named memory object area */
 	ret = drm_gem_handle_create(file_priv, chan->notifier_bo->gem,
 				    &init->notifier_handle);
-	if (ret) {
-		nouveau_channel_free(chan);
-		return ret;
-	}
 
-	return 0;
+	if (ret == 0)
+		atomic_inc(&chan->users); /* userspace reference */
+	nouveau_channel_put(&chan);
+	return ret;
 }
 
 static int
 nouveau_ioctl_fifo_free(struct drm_device *dev, void *data,
 			struct drm_file *file_priv)
 {
-	struct drm_nouveau_channel_free *cfree = data;
+	struct drm_nouveau_channel_free *req = data;
 	struct nouveau_channel *chan;
 
-	NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(cfree->channel, file_priv, chan);
+	chan = nouveau_channel_get(dev, file_priv, req->channel);
+	if (IS_ERR(chan))
+		return PTR_ERR(chan);
 
-	nouveau_channel_free(chan);
+	atomic_dec(&chan->users);
+	nouveau_channel_put(&chan);
 	return 0;
 }
 
@@ -421,18 +482,18 @@ nouveau_ioctl_fifo_free(struct drm_devic
  ***********************************/
 
 struct drm_ioctl_desc nouveau_ioctls[] = {
-	DRM_IOCTL_DEF_DRV(NOUVEAU_GETPARAM, nouveau_ioctl_getparam, DRM_AUTH),
-	DRM_IOCTL_DEF_DRV(NOUVEAU_SETPARAM, nouveau_ioctl_setparam, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-	DRM_IOCTL_DEF_DRV(NOUVEAU_CHANNEL_ALLOC, nouveau_ioctl_fifo_alloc, DRM_AUTH),
-	DRM_IOCTL_DEF_DRV(NOUVEAU_CHANNEL_FREE, nouveau_ioctl_fifo_free, DRM_AUTH),
-	DRM_IOCTL_DEF_DRV(NOUVEAU_GROBJ_ALLOC, nouveau_ioctl_grobj_alloc, DRM_AUTH),
-	DRM_IOCTL_DEF_DRV(NOUVEAU_NOTIFIEROBJ_ALLOC, nouveau_ioctl_notifier_alloc, DRM_AUTH),
-	DRM_IOCTL_DEF_DRV(NOUVEAU_GPUOBJ_FREE, nouveau_ioctl_gpuobj_free, DRM_AUTH),
-	DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_NEW, nouveau_gem_ioctl_new, DRM_AUTH),
-	DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_PUSHBUF, nouveau_gem_ioctl_pushbuf, DRM_AUTH),
-	DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_CPU_PREP, nouveau_gem_ioctl_cpu_prep, DRM_AUTH),
-	DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_CPU_FINI, nouveau_gem_ioctl_cpu_fini, DRM_AUTH),
-	DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_INFO, nouveau_gem_ioctl_info, DRM_AUTH),
+	DRM_IOCTL_DEF_DRV(NOUVEAU_GETPARAM, nouveau_ioctl_getparam, DRM_UNLOCKED|DRM_AUTH),
+	DRM_IOCTL_DEF_DRV(NOUVEAU_SETPARAM, nouveau_ioctl_setparam, DRM_UNLOCKED|DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+	DRM_IOCTL_DEF_DRV(NOUVEAU_CHANNEL_ALLOC, nouveau_ioctl_fifo_alloc, DRM_UNLOCKED|DRM_AUTH),
+	DRM_IOCTL_DEF_DRV(NOUVEAU_CHANNEL_FREE, nouveau_ioctl_fifo_free, DRM_UNLOCKED|DRM_AUTH),
+	DRM_IOCTL_DEF_DRV(NOUVEAU_GROBJ_ALLOC, nouveau_ioctl_grobj_alloc, DRM_UNLOCKED|DRM_AUTH),
+	DRM_IOCTL_DEF_DRV(NOUVEAU_NOTIFIEROBJ_ALLOC, nouveau_ioctl_notifier_alloc, DRM_UNLOCKED|DRM_AUTH),
+	DRM_IOCTL_DEF_DRV(NOUVEAU_GPUOBJ_FREE, nouveau_ioctl_gpuobj_free, DRM_UNLOCKED|DRM_AUTH),
+	DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_NEW, nouveau_gem_ioctl_new, DRM_UNLOCKED|DRM_AUTH),
+	DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_PUSHBUF, nouveau_gem_ioctl_pushbuf, DRM_UNLOCKED|DRM_AUTH),
+	DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_CPU_PREP, nouveau_gem_ioctl_cpu_prep, DRM_UNLOCKED|DRM_AUTH),
+	DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_CPU_FINI, nouveau_gem_ioctl_cpu_fini, DRM_UNLOCKED|DRM_AUTH),
+	DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_INFO, nouveau_gem_ioctl_info, DRM_UNLOCKED|DRM_AUTH),
 };
 
 int nouveau_max_ioctl = DRM_ARRAY_SIZE(nouveau_ioctls);
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nouveau_connector.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nouveau_connector.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nouveau_connector.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nouveau_connector.c	2011-03-14 21:20:32.000000000 -0400
@@ -37,6 +37,8 @@
 #include "nouveau_connector.h"
 #include "nouveau_hw.h"
 
+static void nouveau_connector_hotplug(void *, int);
+
 static struct nouveau_encoder *
 find_encoder_by_type(struct drm_connector *connector, int type)
 {
@@ -94,22 +96,30 @@ nouveau_connector_bpp(struct drm_connect
 }
 
 static void
-nouveau_connector_destroy(struct drm_connector *drm_connector)
+nouveau_connector_destroy(struct drm_connector *connector)
 {
-	struct nouveau_connector *nv_connector =
-		nouveau_connector(drm_connector);
+	struct nouveau_connector *nv_connector = nouveau_connector(connector);
+	struct drm_nouveau_private *dev_priv;
+	struct nouveau_gpio_engine *pgpio;
 	struct drm_device *dev;
 
 	if (!nv_connector)
 		return;
 
 	dev = nv_connector->base.dev;
+	dev_priv = dev->dev_private;
 	NV_DEBUG_KMS(dev, "\n");
 
+	pgpio = &dev_priv->engine.gpio;
+	if (pgpio->irq_unregister) {
+		pgpio->irq_unregister(dev, nv_connector->dcb->gpio_tag,
+				      nouveau_connector_hotplug, connector);
+	}
+
 	kfree(nv_connector->edid);
-	drm_sysfs_connector_remove(drm_connector);
-	drm_connector_cleanup(drm_connector);
-	kfree(drm_connector);
+	drm_sysfs_connector_remove(connector);
+	drm_connector_cleanup(connector);
+	kfree(connector);
 }
 
 static struct nouveau_i2c_chan *
@@ -497,6 +507,7 @@ nouveau_connector_native_mode(struct drm
 	int high_w = 0, high_h = 0, high_v = 0;
 
 	list_for_each_entry(mode, &nv_connector->base.probed_modes, head) {
+		mode->vrefresh = drm_mode_vrefresh(mode);
 		if (helper->mode_valid(connector, mode) != MODE_OK ||
 		    (mode->flags & DRM_MODE_FLAG_INTERLACE))
 			continue;
@@ -760,6 +771,7 @@ nouveau_connector_create(struct drm_devi
 {
 	const struct drm_connector_funcs *funcs = &nouveau_connector_funcs;
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio;
 	struct nouveau_connector *nv_connector = NULL;
 	struct dcb_connector_table_entry *dcb = NULL;
 	struct drm_connector *connector;
@@ -876,6 +888,11 @@ nouveau_connector_create(struct drm_devi
 		break;
 	}
 
+	if (pgpio->irq_register) {
+		pgpio->irq_register(dev, nv_connector->dcb->gpio_tag,
+				    nouveau_connector_hotplug, connector);
+	}
+
 	drm_sysfs_connector_add(connector);
 	dcb->drm = connector;
 	return dcb->drm;
@@ -886,3 +903,29 @@ fail:
 	return ERR_PTR(ret);
 
 }
+
+static void
+nouveau_connector_hotplug(void *data, int plugged)
+{
+	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;
+
+		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);
+		}
+	}
+
+	drm_helper_hpd_irq_event(dev);
+}
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nouveau_display.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nouveau_display.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nouveau_display.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nouveau_display.c	2011-03-14 21:20:32.000000000 -0400
@@ -29,6 +29,9 @@
 #include "nouveau_drv.h"
 #include "nouveau_fb.h"
 #include "nouveau_fbcon.h"
+#include "nouveau_hw.h"
+#include "nouveau_crtc.h"
+#include "nouveau_dma.h"
 
 static void
 nouveau_user_framebuffer_destroy(struct drm_framebuffer *drm_fb)
@@ -104,3 +107,207 @@ const struct drm_mode_config_funcs nouve
 	.output_poll_changed = nouveau_fbcon_output_poll_changed,
 };
 
+int
+nouveau_vblank_enable(struct drm_device *dev, int crtc)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+	if (dev_priv->card_type >= NV_50)
+		nv_mask(dev, NV50_PDISPLAY_INTR_EN_1, 0,
+			NV50_PDISPLAY_INTR_EN_1_VBLANK_CRTC_(crtc));
+	else
+		NVWriteCRTC(dev, crtc, NV_PCRTC_INTR_EN_0,
+			    NV_PCRTC_INTR_0_VBLANK);
+
+	return 0;
+}
+
+void
+nouveau_vblank_disable(struct drm_device *dev, int crtc)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+	if (dev_priv->card_type >= NV_50)
+		nv_mask(dev, NV50_PDISPLAY_INTR_EN_1,
+			NV50_PDISPLAY_INTR_EN_1_VBLANK_CRTC_(crtc), 0);
+	else
+		NVWriteCRTC(dev, crtc, NV_PCRTC_INTR_EN_0, 0);
+}
+
+static int
+nouveau_page_flip_reserve(struct nouveau_bo *old_bo,
+			  struct nouveau_bo *new_bo)
+{
+	int ret;
+
+	ret = nouveau_bo_pin(new_bo, TTM_PL_FLAG_VRAM);
+	if (ret)
+		return ret;
+
+	ret = ttm_bo_reserve(&new_bo->bo, false, false, false, 0);
+	if (ret)
+		goto fail;
+
+	ret = ttm_bo_reserve(&old_bo->bo, false, false, false, 0);
+	if (ret)
+		goto fail_unreserve;
+
+	return 0;
+
+fail_unreserve:
+	ttm_bo_unreserve(&new_bo->bo);
+fail:
+	nouveau_bo_unpin(new_bo);
+	return ret;
+}
+
+static void
+nouveau_page_flip_unreserve(struct nouveau_bo *old_bo,
+			    struct nouveau_bo *new_bo,
+			    struct nouveau_fence *fence)
+{
+	nouveau_bo_fence(new_bo, fence);
+	ttm_bo_unreserve(&new_bo->bo);
+
+	nouveau_bo_fence(old_bo, fence);
+	ttm_bo_unreserve(&old_bo->bo);
+
+	nouveau_bo_unpin(old_bo);
+}
+
+static int
+nouveau_page_flip_emit(struct nouveau_channel *chan,
+		       struct nouveau_bo *old_bo,
+		       struct nouveau_bo *new_bo,
+		       struct nouveau_page_flip_state *s,
+		       struct nouveau_fence **pfence)
+{
+	struct drm_device *dev = chan->dev;
+	unsigned long flags;
+	int ret;
+
+	/* Queue it to the pending list */
+	spin_lock_irqsave(&dev->event_lock, flags);
+	list_add_tail(&s->head, &chan->nvsw.flip);
+	spin_unlock_irqrestore(&dev->event_lock, flags);
+
+	/* Synchronize with the old framebuffer */
+	ret = nouveau_fence_sync(old_bo->bo.sync_obj, chan);
+	if (ret)
+		goto fail;
+
+	/* Emit the pageflip */
+	ret = RING_SPACE(chan, 2);
+	if (ret)
+		goto fail;
+
+	BEGIN_RING(chan, NvSubSw, NV_SW_PAGE_FLIP, 1);
+	OUT_RING(chan, 0);
+	FIRE_RING(chan);
+
+	ret = nouveau_fence_new(chan, pfence, true);
+	if (ret)
+		goto fail;
+
+	return 0;
+fail:
+	spin_lock_irqsave(&dev->event_lock, flags);
+	list_del(&s->head);
+	spin_unlock_irqrestore(&dev->event_lock, flags);
+	return ret;
+}
+
+int
+nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
+		       struct drm_pending_vblank_event *event)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_bo *old_bo = nouveau_framebuffer(crtc->fb)->nvbo;
+	struct nouveau_bo *new_bo = nouveau_framebuffer(fb)->nvbo;
+	struct nouveau_page_flip_state *s;
+	struct nouveau_channel *chan;
+	struct nouveau_fence *fence;
+	int ret;
+
+	if (dev_priv->engine.graph.accel_blocked)
+		return -ENODEV;
+
+	s = kzalloc(sizeof(*s), GFP_KERNEL);
+	if (!s)
+		return -ENOMEM;
+
+	/* Don't let the buffers go away while we flip */
+	ret = nouveau_page_flip_reserve(old_bo, new_bo);
+	if (ret)
+		goto fail_free;
+
+	/* Initialize a page flip struct */
+	*s = (struct nouveau_page_flip_state)
+		{ { }, s->event, nouveau_crtc(crtc)->index,
+		  fb->bits_per_pixel, fb->pitch, crtc->x, crtc->y,
+		  new_bo->bo.offset };
+
+	/* Choose the channel the flip will be handled in */
+	chan = nouveau_fence_channel(new_bo->bo.sync_obj);
+	if (!chan)
+		chan = nouveau_channel_get_unlocked(dev_priv->channel);
+	mutex_lock(&chan->mutex);
+
+	/* Emit a page flip */
+	ret = nouveau_page_flip_emit(chan, old_bo, new_bo, s, &fence);
+	nouveau_channel_put(&chan);
+	if (ret)
+		goto fail_unreserve;
+
+	/* Update the crtc struct and cleanup */
+	crtc->fb = fb;
+
+	nouveau_page_flip_unreserve(old_bo, new_bo, fence);
+	nouveau_fence_unref(&fence);
+	return 0;
+
+fail_unreserve:
+	nouveau_page_flip_unreserve(old_bo, new_bo, NULL);
+fail_free:
+	kfree(s);
+	return ret;
+}
+
+int
+nouveau_finish_page_flip(struct nouveau_channel *chan,
+			 struct nouveau_page_flip_state *ps)
+{
+	struct drm_device *dev = chan->dev;
+	struct nouveau_page_flip_state *s;
+	unsigned long flags;
+
+	spin_lock_irqsave(&dev->event_lock, flags);
+
+	if (list_empty(&chan->nvsw.flip)) {
+		NV_ERROR(dev, "Unexpected pageflip in channel %d.\n", chan->id);
+		spin_unlock_irqrestore(&dev->event_lock, flags);
+		return -EINVAL;
+	}
+
+	s = list_first_entry(&chan->nvsw.flip,
+			     struct nouveau_page_flip_state, head);
+	if (s->event) {
+		struct drm_pending_vblank_event *e = s->event;
+		struct timeval now;
+
+		do_gettimeofday(&now);
+		e->event.sequence = 0;
+		e->event.tv_sec = now.tv_sec;
+		e->event.tv_usec = now.tv_usec;
+		list_add_tail(&e->base.link, &e->base.file_priv->event_list);
+		wake_up_interruptible(&e->base.file_priv->event_wait);
+	}
+
+	list_del(&s->head);
+	*ps = *s;
+	kfree(s);
+
+	spin_unlock_irqrestore(&dev->event_lock, flags);
+	return 0;
+}
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nouveau_dma.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nouveau_dma.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nouveau_dma.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nouveau_dma.c	2011-03-14 21:20:32.000000000 -0400
@@ -36,7 +36,7 @@ nouveau_dma_pre_init(struct nouveau_chan
 	struct drm_nouveau_private *dev_priv = chan->dev->dev_private;
 	struct nouveau_bo *pushbuf = chan->pushbuf_bo;
 
-	if (dev_priv->card_type == NV_50) {
+	if (dev_priv->card_type >= NV_50) {
 		const int ib_size = pushbuf->bo.mem.size / 2;
 
 		chan->dma.ib_base = (pushbuf->bo.mem.size - ib_size) >> 2;
@@ -59,27 +59,32 @@ nouveau_dma_init(struct nouveau_channel
 {
 	struct drm_device *dev = chan->dev;
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nouveau_gpuobj *obj = NULL;
 	int ret, i;
 
-	/* Create NV_MEMORY_TO_MEMORY_FORMAT for buffer moves */
-	ret = nouveau_gpuobj_gr_new(chan, dev_priv->card_type < NV_50 ?
-				    0x0039 : 0x5039, &obj);
-	if (ret)
-		return ret;
+	if (dev_priv->card_type >= NV_C0) {
+		ret = nouveau_gpuobj_gr_new(chan, 0x9039, 0x9039);
+		if (ret)
+			return ret;
 
-	ret = nouveau_ramht_insert(chan, NvM2MF, obj);
-	nouveau_gpuobj_ref(NULL, &obj);
-	if (ret)
-		return ret;
+		ret = RING_SPACE(chan, 2);
+		if (ret)
+			return ret;
 
-	/* NV_MEMORY_TO_MEMORY_FORMAT requires a notifier object */
-	ret = nouveau_notifier_alloc(chan, NvNotify0, 32, &chan->m2mf_ntfy);
+		BEGIN_NVC0(chan, 2, NvSubM2MF, 0x0000, 1);
+		OUT_RING  (chan, 0x00009039);
+		FIRE_RING (chan);
+		return 0;
+	}
+
+	/* Create NV_MEMORY_TO_MEMORY_FORMAT for buffer moves */
+	ret = nouveau_gpuobj_gr_new(chan, NvM2MF, dev_priv->card_type < NV_50 ?
+				    0x0039 : 0x5039);
 	if (ret)
 		return ret;
 
-	/* Map push buffer */
-	ret = nouveau_bo_map(chan->pushbuf_bo);
+	/* NV_MEMORY_TO_MEMORY_FORMAT requires a notifier object */
+	ret = nouveau_notifier_alloc(chan, NvNotify0, 32, 0xfd0, 0x1000,
+				     &chan->m2mf_ntfy);
 	if (ret)
 		return ret;
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nouveau_dma.h linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nouveau_dma.h
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nouveau_dma.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nouveau_dma.h	2011-03-14 21:20:32.000000000 -0400
@@ -77,7 +77,8 @@ enum {
 	/* G80+ display objects */
 	NvEvoVRAM	= 0x01000000,
 	NvEvoFB16	= 0x01000001,
-	NvEvoFB32	= 0x01000002
+	NvEvoFB32	= 0x01000002,
+	NvEvoVRAM_LP	= 0x01000003
 };
 
 #define NV_MEMORY_TO_MEMORY_FORMAT                                    0x00000039
@@ -125,6 +126,12 @@ extern void
 OUT_RINGp(struct nouveau_channel *chan, const void *data, unsigned nr_dwords);
 
 static inline void
+BEGIN_NVC0(struct nouveau_channel *chan, int op, int subc, int mthd, int size)
+{
+	OUT_RING(chan, (op << 28) | (size << 16) | (subc << 13) | (mthd >> 2));
+}
+
+static inline void
 BEGIN_RING(struct nouveau_channel *chan, int subc, int mthd, int size)
 {
 	OUT_RING(chan, (subc << 13) | (size << 18) | mthd);
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nouveau_dp.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nouveau_dp.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nouveau_dp.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nouveau_dp.c	2011-03-14 21:20:32.000000000 -0400
@@ -279,7 +279,7 @@ nouveau_dp_link_train(struct drm_encoder
 	struct bit_displayport_encoder_table *dpe;
 	int dpe_headerlen;
 	uint8_t config[4], status[3];
-	bool cr_done, cr_max_vs, eq_done;
+	bool cr_done, cr_max_vs, eq_done, hpd_state;
 	int ret = 0, i, tries, voltage;
 
 	NV_DEBUG_KMS(dev, "link training!!\n");
@@ -297,7 +297,7 @@ nouveau_dp_link_train(struct drm_encoder
 	/* disable hotplug detect, this flips around on some panels during
 	 * link training.
 	 */
-	pgpio->irq_enable(dev, nv_connector->dcb->gpio_tag, false);
+	hpd_state = pgpio->irq_enable(dev, nv_connector->dcb->gpio_tag, false);
 
 	if (dpe->script0) {
 		NV_DEBUG_KMS(dev, "SOR-%d: running DP script 0\n", nv_encoder->or);
@@ -439,7 +439,7 @@ stop:
 	}
 
 	/* re-enable hotplug detect */
-	pgpio->irq_enable(dev, nv_connector->dcb->gpio_tag, true);
+	pgpio->irq_enable(dev, nv_connector->dcb->gpio_tag, hpd_state);
 
 	return eq_done;
 }
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nouveau_drv.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nouveau_drv.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nouveau_drv.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nouveau_drv.c	2011-03-14 21:20:32.000000000 -0400
@@ -115,6 +115,10 @@ MODULE_PARM_DESC(perflvl_wr, "Allow perf
 int nouveau_perflvl_wr;
 module_param_named(perflvl_wr, nouveau_perflvl_wr, int, 0400);
 
+MODULE_PARM_DESC(msi, "Enable MSI (default: off)\n");
+int nouveau_msi;
+module_param_named(msi, nouveau_msi, int, 0400);
+
 int nouveau_fbpercrtc;
 #if 0
 module_param_named(fbpercrtc, nouveau_fbpercrtc, int, 0400);
@@ -167,6 +171,9 @@ nouveau_pci_suspend(struct pci_dev *pdev
 	if (pm_state.event == PM_EVENT_PRETHAW)
 		return 0;
 
+	if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)
+		return 0;
+
 	NV_INFO(dev, "Disabling fbcon acceleration...\n");
 	nouveau_fbcon_save_disable_accel(dev);
 
@@ -193,23 +200,10 @@ nouveau_pci_suspend(struct pci_dev *pdev
 
 	NV_INFO(dev, "Idling channels...\n");
 	for (i = 0; i < pfifo->channels; i++) {
-		struct nouveau_fence *fence = NULL;
-
-		chan = dev_priv->fifos[i];
-		if (!chan || (dev_priv->card_type >= NV_50 &&
-			      chan == dev_priv->fifos[0]))
-			continue;
-
-		ret = nouveau_fence_new(chan, &fence, true);
-		if (ret == 0) {
-			ret = nouveau_fence_wait(fence, NULL, false, false);
-			nouveau_fence_unref((void *)&fence);
-		}
+		chan = dev_priv->channels.ptr[i];
 
-		if (ret) {
-			NV_ERROR(dev, "Failed to idle channel %d for suspend\n",
-				 chan->id);
-		}
+		if (chan && chan->pushbuf_bo)
+			nouveau_channel_idle(chan);
 	}
 
 	pgraph->fifo_access(dev, false);
@@ -219,17 +213,17 @@ nouveau_pci_suspend(struct pci_dev *pdev
 	pfifo->unload_context(dev);
 	pgraph->unload_context(dev);
 
-	NV_INFO(dev, "Suspending GPU objects...\n");
-	ret = nouveau_gpuobj_suspend(dev);
+	ret = pinstmem->suspend(dev);
 	if (ret) {
 		NV_ERROR(dev, "... failed: %d\n", ret);
 		goto out_abort;
 	}
 
-	ret = pinstmem->suspend(dev);
+	NV_INFO(dev, "Suspending GPU objects...\n");
+	ret = nouveau_gpuobj_suspend(dev);
 	if (ret) {
 		NV_ERROR(dev, "... failed: %d\n", ret);
-		nouveau_gpuobj_suspend_cleanup(dev);
+		pinstmem->resume(dev);
 		goto out_abort;
 	}
 
@@ -240,9 +234,9 @@ nouveau_pci_suspend(struct pci_dev *pdev
 		pci_set_power_state(pdev, PCI_D3hot);
 	}
 
-	acquire_console_sem();
+	console_lock();
 	nouveau_fbcon_set_suspend(dev, 1);
-	release_console_sem();
+	console_unlock();
 	nouveau_fbcon_restore_accel(dev);
 	return 0;
 
@@ -263,6 +257,9 @@ nouveau_pci_resume(struct pci_dev *pdev)
 	struct drm_crtc *crtc;
 	int ret, i;
 
+	if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)
+		return 0;
+
 	nouveau_fbcon_save_disable_accel(dev);
 
 	NV_INFO(dev, "We're back, enabling device...\n");
@@ -294,17 +291,18 @@ nouveau_pci_resume(struct pci_dev *pdev)
 		}
 	}
 
+	NV_INFO(dev, "Restoring GPU objects...\n");
+	nouveau_gpuobj_resume(dev);
+
 	NV_INFO(dev, "Reinitialising engines...\n");
 	engine->instmem.resume(dev);
 	engine->mc.init(dev);
 	engine->timer.init(dev);
 	engine->fb.init(dev);
 	engine->graph.init(dev);
+	engine->crypt.init(dev);
 	engine->fifo.init(dev);
 
-	NV_INFO(dev, "Restoring GPU objects...\n");
-	nouveau_gpuobj_resume(dev);
-
 	nouveau_irq_postinstall(dev);
 
 	/* Re-write SKIPS, they'll have been lost over the suspend */
@@ -313,7 +311,7 @@ nouveau_pci_resume(struct pci_dev *pdev)
 		int j;
 
 		for (i = 0; i < dev_priv->engine.fifo.channels; i++) {
-			chan = dev_priv->fifos[i];
+			chan = dev_priv->channels.ptr[i];
 			if (!chan || !chan->pushbuf_bo)
 				continue;
 
@@ -347,13 +345,11 @@ nouveau_pci_resume(struct pci_dev *pdev)
 
 	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
 		struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
+		u32 offset = nv_crtc->cursor.nvbo->bo.mem.start << PAGE_SHIFT;
 
-		nv_crtc->cursor.set_offset(nv_crtc,
-					nv_crtc->cursor.nvbo->bo.offset -
-					dev_priv->vm_vram_base);
-
+		nv_crtc->cursor.set_offset(nv_crtc, offset);
 		nv_crtc->cursor.set_pos(nv_crtc, nv_crtc->cursor_saved_x,
-			nv_crtc->cursor_saved_y);
+						 nv_crtc->cursor_saved_y);
 	}
 
 	/* Force CLUT to get re-loaded during modeset */
@@ -363,9 +359,9 @@ nouveau_pci_resume(struct pci_dev *pdev)
 		nv_crtc->lut.depth = 0;
 	}
 
-	acquire_console_sem();
+	console_lock();
 	nouveau_fbcon_set_suspend(dev, 0);
-	release_console_sem();
+	console_unlock();
 
 	nouveau_fbcon_zfill_all(dev);
 
@@ -393,6 +389,9 @@ static struct drm_driver driver = {
 	.irq_postinstall = nouveau_irq_postinstall,
 	.irq_uninstall = nouveau_irq_uninstall,
 	.irq_handler = nouveau_irq_handler,
+	.get_vblank_counter = drm_vblank_count,
+	.enable_vblank = nouveau_vblank_enable,
+	.disable_vblank = nouveau_vblank_disable,
 	.reclaim_buffers = drm_core_reclaim_buffers,
 	.ioctls = nouveau_ioctls,
 	.fops = {
@@ -403,6 +402,7 @@ static struct drm_driver driver = {
 		.mmap = nouveau_ttm_mmap,
 		.poll = drm_poll,
 		.fasync = drm_fasync,
+		.read = drm_read,
 #if defined(CONFIG_COMPAT)
 		.compat_ioctl = nouveau_compat_ioctl,
 #endif
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nouveau_drv.h linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nouveau_drv.h
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nouveau_drv.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nouveau_drv.h	2011-03-14 21:20:32.000000000 -0400
@@ -54,22 +54,37 @@ struct nouveau_fpriv {
 #include "nouveau_drm.h"
 #include "nouveau_reg.h"
 #include "nouveau_bios.h"
+#include "nouveau_util.h"
+
 struct nouveau_grctx;
+struct nouveau_vram;
+#include "nouveau_vm.h"
 
 #define MAX_NUM_DCB_ENTRIES 16
 
 #define NOUVEAU_MAX_CHANNEL_NR 128
 #define NOUVEAU_MAX_TILE_NR 15
 
-#define NV50_VM_MAX_VRAM (2*1024*1024*1024ULL)
-#define NV50_VM_BLOCK    (512*1024*1024ULL)
-#define NV50_VM_VRAM_NR  (NV50_VM_MAX_VRAM / NV50_VM_BLOCK)
+struct nouveau_vram {
+	struct drm_device *dev;
+
+	struct nouveau_vma bar_vma;
+	u8  page_shift;
+
+	struct list_head regions;
+	u32 memtype;
+	u64 offset;
+	u64 size;
+};
 
 struct nouveau_tile_reg {
-	struct nouveau_fence *fence;
-	uint32_t addr;
-	uint32_t size;
 	bool used;
+	uint32_t addr;
+	uint32_t limit;
+	uint32_t pitch;
+	uint32_t zcomp;
+	struct drm_mm_node *tag_mem;
+	struct nouveau_fence *fence;
 };
 
 struct nouveau_bo {
@@ -88,6 +103,7 @@ struct nouveau_bo {
 
 	struct nouveau_channel *channel;
 
+	struct nouveau_vma vma;
 	bool mappable;
 	bool no_vm;
 
@@ -96,7 +112,6 @@ struct nouveau_bo {
 	struct nouveau_tile_reg *tile;
 
 	struct drm_gem_object *gem;
-	struct drm_file *cpu_filp;
 	int pin_refcnt;
 };
 
@@ -133,20 +148,29 @@ enum nouveau_flags {
 
 #define NVOBJ_ENGINE_SW		0
 #define NVOBJ_ENGINE_GR		1
-#define NVOBJ_ENGINE_DISPLAY	2
+#define NVOBJ_ENGINE_PPP	2
+#define NVOBJ_ENGINE_COPY	3
+#define NVOBJ_ENGINE_VP		4
+#define NVOBJ_ENGINE_CRYPT      5
+#define NVOBJ_ENGINE_BSP	6
+#define NVOBJ_ENGINE_DISPLAY	0xcafe0001
 #define NVOBJ_ENGINE_INT	0xdeadbeef
 
+#define NVOBJ_FLAG_DONT_MAP             (1 << 0)
 #define NVOBJ_FLAG_ZERO_ALLOC		(1 << 1)
 #define NVOBJ_FLAG_ZERO_FREE		(1 << 2)
+#define NVOBJ_FLAG_VM			(1 << 3)
+#define NVOBJ_FLAG_VM_USER		(1 << 4)
+
+#define NVOBJ_CINST_GLOBAL	0xdeadbeef
+
 struct nouveau_gpuobj {
 	struct drm_device *dev;
 	struct kref refcount;
 	struct list_head list;
 
-	struct drm_mm_node *im_pramin;
-	struct nouveau_bo *im_backing;
-	uint32_t *im_backing_suspend;
-	int im_bound;
+	void *node;
+	u32 *suspend;
 
 	uint32_t flags;
 
@@ -162,10 +186,29 @@ struct nouveau_gpuobj {
 	void *priv;
 };
 
+struct nouveau_page_flip_state {
+	struct list_head head;
+	struct drm_pending_vblank_event *event;
+	int crtc, bpp, pitch, x, y;
+	uint64_t offset;
+};
+
+enum nouveau_channel_mutex_class {
+	NOUVEAU_UCHANNEL_MUTEX,
+	NOUVEAU_KCHANNEL_MUTEX
+};
+
 struct nouveau_channel {
 	struct drm_device *dev;
 	int id;
 
+	/* references to the channel data structure */
+	struct kref ref;
+	/* users of the hardware channel resources, the hardware
+	 * context will be kicked off when it reaches zero. */
+	atomic_t users;
+	struct mutex mutex;
+
 	/* owner of this fifo */
 	struct drm_file *file_priv;
 	/* mapping of the fifo itself */
@@ -198,16 +241,17 @@ struct nouveau_channel {
 	/* PFIFO context */
 	struct nouveau_gpuobj *ramfc;
 	struct nouveau_gpuobj *cache;
+	void *fifo_priv;
 
 	/* PGRAPH context */
 	/* XXX may be merge 2 pointers as private data ??? */
 	struct nouveau_gpuobj *ramin_grctx;
+	struct nouveau_gpuobj *crypt_ctx;
 	void *pgraph_ctx;
 
 	/* NV50 VM */
+	struct nouveau_vm     *vm;
 	struct nouveau_gpuobj *vm_pd;
-	struct nouveau_gpuobj *vm_gart_pt;
-	struct nouveau_gpuobj *vm_vram_pt[NV50_VM_VRAM_NR];
 
 	/* Objects */
 	struct nouveau_gpuobj *ramin; /* Private instmem */
@@ -238,9 +282,11 @@ struct nouveau_channel {
 
 	struct {
 		struct nouveau_gpuobj *vblsem;
+		uint32_t vblsem_head;
 		uint32_t vblsem_offset;
 		uint32_t vblsem_rval;
 		struct list_head vbl_wait;
+		struct list_head flip;
 	} nvsw;
 
 	struct {
@@ -258,11 +304,11 @@ struct nouveau_instmem_engine {
 	int	(*suspend)(struct drm_device *dev);
 	void	(*resume)(struct drm_device *dev);
 
-	int	(*populate)(struct drm_device *, struct nouveau_gpuobj *,
-			    uint32_t *size);
-	void	(*clear)(struct drm_device *, struct nouveau_gpuobj *);
-	int	(*bind)(struct drm_device *, struct nouveau_gpuobj *);
-	int	(*unbind)(struct drm_device *, struct nouveau_gpuobj *);
+	int	(*get)(struct nouveau_gpuobj *, u32 size, u32 align);
+	void	(*put)(struct nouveau_gpuobj *);
+	int	(*map)(struct nouveau_gpuobj *);
+	void	(*unmap)(struct nouveau_gpuobj *);
+
 	void	(*flush)(struct drm_device *);
 };
 
@@ -279,15 +325,21 @@ struct nouveau_timer_engine {
 
 struct nouveau_fb_engine {
 	int num_tiles;
+	struct drm_mm tag_heap;
+	void *priv;
 
 	int  (*init)(struct drm_device *dev);
 	void (*takedown)(struct drm_device *dev);
 
-	void (*set_region_tiling)(struct drm_device *dev, int i, uint32_t addr,
-				 uint32_t size, uint32_t pitch);
+	void (*init_tile_region)(struct drm_device *dev, int i,
+				 uint32_t addr, uint32_t size,
+				 uint32_t pitch, uint32_t flags);
+	void (*set_tile_region)(struct drm_device *dev, int i);
+	void (*free_tile_region)(struct drm_device *dev, int i);
 };
 
 struct nouveau_fifo_engine {
+	void *priv;
 	int  channels;
 
 	struct nouveau_gpuobj *playlist[2];
@@ -310,22 +362,11 @@ struct nouveau_fifo_engine {
 	void (*tlb_flush)(struct drm_device *dev);
 };
 
-struct nouveau_pgraph_object_method {
-	int id;
-	int (*exec)(struct nouveau_channel *chan, int grclass, int mthd,
-		      uint32_t data);
-};
-
-struct nouveau_pgraph_object_class {
-	int id;
-	bool software;
-	struct nouveau_pgraph_object_method *methods;
-};
-
 struct nouveau_pgraph_engine {
-	struct nouveau_pgraph_object_class *grclass;
 	bool accel_blocked;
+	bool registered;
 	int grctx_size;
+	void *priv;
 
 	/* NV2x/NV3x context table (0x400780) */
 	struct nouveau_gpuobj *ctx_table;
@@ -342,8 +383,7 @@ struct nouveau_pgraph_engine {
 	int  (*unload_context)(struct drm_device *);
 	void (*tlb_flush)(struct drm_device *dev);
 
-	void (*set_region_tiling)(struct drm_device *dev, int i, uint32_t addr,
-				  uint32_t size, uint32_t pitch);
+	void (*set_tile_region)(struct drm_device *dev, int i);
 };
 
 struct nouveau_display_engine {
@@ -355,13 +395,19 @@ struct nouveau_display_engine {
 };
 
 struct nouveau_gpio_engine {
+	void *priv;
+
 	int  (*init)(struct drm_device *);
 	void (*takedown)(struct drm_device *);
 
 	int  (*get)(struct drm_device *, enum dcb_gpio_tag);
 	int  (*set)(struct drm_device *, enum dcb_gpio_tag, int state);
 
-	void (*irq_enable)(struct drm_device *, enum dcb_gpio_tag, bool on);
+	int  (*irq_register)(struct drm_device *, enum dcb_gpio_tag,
+			     void (*)(void *, int), void *);
+	void (*irq_unregister)(struct drm_device *, enum dcb_gpio_tag,
+			       void (*)(void *, int), void *);
+	bool (*irq_enable)(struct drm_device *, enum dcb_gpio_tag, bool on);
 };
 
 struct nouveau_pm_voltage_level {
@@ -437,6 +483,7 @@ struct nouveau_pm_engine {
 	struct nouveau_pm_level *cur;
 
 	struct device *hwmon;
+	struct notifier_block acpi_nb;
 
 	int (*clock_get)(struct drm_device *, u32 id);
 	void *(*clock_pre)(struct drm_device *, struct nouveau_pm_level *,
@@ -449,6 +496,25 @@ struct nouveau_pm_engine {
 	int (*temp_get)(struct drm_device *);
 };
 
+struct nouveau_crypt_engine {
+	bool registered;
+
+	int  (*init)(struct drm_device *);
+	void (*takedown)(struct drm_device *);
+	int  (*create_context)(struct nouveau_channel *);
+	void (*destroy_context)(struct nouveau_channel *);
+	void (*tlb_flush)(struct drm_device *dev);
+};
+
+struct nouveau_vram_engine {
+	int  (*init)(struct drm_device *);
+	int  (*get)(struct drm_device *, u64, u32 align, u32 size_nc,
+		    u32 type, struct nouveau_vram **);
+	void (*put)(struct drm_device *, struct nouveau_vram **);
+
+	bool (*flags_valid)(struct drm_device *, u32 tile_flags);
+};
+
 struct nouveau_engine {
 	struct nouveau_instmem_engine instmem;
 	struct nouveau_mc_engine      mc;
@@ -459,6 +525,8 @@ struct nouveau_engine {
 	struct nouveau_display_engine display;
 	struct nouveau_gpio_engine    gpio;
 	struct nouveau_pm_engine      pm;
+	struct nouveau_crypt_engine   crypt;
+	struct nouveau_vram_engine    vram;
 };
 
 struct nouveau_pll_vals {
@@ -577,18 +645,15 @@ struct drm_nouveau_private {
 	bool ramin_available;
 	struct drm_mm ramin_heap;
 	struct list_head gpuobj_list;
+	struct list_head classes;
 
 	struct nouveau_bo *vga_ram;
 
+	/* interrupt handling */
+	void (*irq_handler[32])(struct drm_device *);
+	bool msi_enabled;
 	struct workqueue_struct *wq;
 	struct work_struct irq_work;
-	struct work_struct hpd_work;
-
-	struct {
-		spinlock_t lock;
-		uint32_t hpd0_bits;
-		uint32_t hpd1_bits;
-	} hpd_state;
 
 	struct list_head vbl_waiting;
 
@@ -605,8 +670,10 @@ struct drm_nouveau_private {
 		struct nouveau_bo *bo;
 	} fence;
 
-	int fifo_alloc_count;
-	struct nouveau_channel *fifos[NOUVEAU_MAX_CHANNEL_NR];
+	struct {
+		spinlock_t lock;
+		struct nouveau_channel *ptr[NOUVEAU_MAX_CHANNEL_NR];
+	} channels;
 
 	struct nouveau_engine engine;
 	struct nouveau_channel *channel;
@@ -632,12 +699,14 @@ struct drm_nouveau_private {
 		uint64_t aper_free;
 
 		struct nouveau_gpuobj *sg_ctxdma;
-		struct page *sg_dummy_page;
-		dma_addr_t sg_dummy_bus;
+		struct nouveau_vma vma;
 	} gart_info;
 
 	/* nv10-nv40 tiling regions */
-	struct nouveau_tile_reg tile[NOUVEAU_MAX_TILE_NR];
+	struct {
+		struct nouveau_tile_reg reg[NOUVEAU_MAX_TILE_NR];
+		spinlock_t lock;
+	} tile;
 
 	/* VRAM/fb configuration */
 	uint64_t vram_size;
@@ -650,14 +719,12 @@ struct drm_nouveau_private {
 	uint64_t fb_aper_free;
 	int fb_mtrr;
 
+	/* BAR control (NV50-) */
+	struct nouveau_vm *bar1_vm;
+	struct nouveau_vm *bar3_vm;
+
 	/* G8x/G9x virtual address space */
-	uint64_t vm_gart_base;
-	uint64_t vm_gart_size;
-	uint64_t vm_vram_base;
-	uint64_t vm_vram_size;
-	uint64_t vm_end;
-	struct nouveau_gpuobj *vm_vram_pt[NV50_VM_VRAM_NR];
-	int vm_vram_pt_nr;
+	struct nouveau_vm *chan_vm;
 
 	struct nvbios vbios;
 
@@ -674,6 +741,7 @@ struct drm_nouveau_private {
 	struct backlight_device *backlight;
 
 	struct nouveau_channel *evo;
+	u32 evo_alloc;
 	struct {
 		struct dcb_entry *dcb;
 		u16 script;
@@ -686,6 +754,8 @@ struct drm_nouveau_private {
 
 	struct nouveau_fbdev *nfbdev;
 	struct apertures_struct *apertures;
+
+	bool powered_down;
 };
 
 static inline struct drm_nouveau_private *
@@ -719,16 +789,6 @@ nouveau_bo_ref(struct nouveau_bo *ref, s
 	return 0;
 }
 
-#define NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(id, cl, ch) do {    \
-	struct drm_nouveau_private *nv = dev->dev_private;       \
-	if (!nouveau_channel_owner(dev, (cl), (id))) {           \
-		NV_ERROR(dev, "pid %d doesn't own channel %d\n", \
-			 DRM_CURRENTPID, (id));                  \
-		return -EPERM;                                   \
-	}                                                        \
-	(ch) = nv->fifos[(id)];                                  \
-} while (0)
-
 /* nouveau_drv.c */
 extern int nouveau_agpmode;
 extern int nouveau_duallink;
@@ -748,6 +808,7 @@ extern int nouveau_force_post;
 extern int nouveau_override_conntype;
 extern char *nouveau_perflvl;
 extern int nouveau_perflvl_wr;
+extern int nouveau_msi;
 
 extern int nouveau_pci_suspend(struct pci_dev *pdev, pm_message_t pm_state);
 extern int nouveau_pci_resume(struct pci_dev *pdev);
@@ -762,8 +823,10 @@ extern int  nouveau_ioctl_getparam(struc
 				   struct drm_file *);
 extern int  nouveau_ioctl_setparam(struct drm_device *, void *data,
 				   struct drm_file *);
-extern bool nouveau_wait_until(struct drm_device *, uint64_t timeout,
-			       uint32_t reg, uint32_t mask, uint32_t val);
+extern bool nouveau_wait_eq(struct drm_device *, uint64_t timeout,
+			    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_for_idle(struct drm_device *);
 extern int  nouveau_card_init(struct drm_device *);
 
@@ -775,24 +838,22 @@ extern void nouveau_mem_gart_fini(struct
 extern int  nouveau_mem_init_agp(struct drm_device *);
 extern int  nouveau_mem_reset_agp(struct drm_device *);
 extern void nouveau_mem_close(struct drm_device *);
-extern struct nouveau_tile_reg *nv10_mem_set_tiling(struct drm_device *dev,
-						    uint32_t addr,
-						    uint32_t size,
-						    uint32_t pitch);
-extern void nv10_mem_expire_tiling(struct drm_device *dev,
-				   struct nouveau_tile_reg *tile,
-				   struct nouveau_fence *fence);
-extern int  nv50_mem_vm_bind_linear(struct drm_device *, uint64_t virt,
-				    uint32_t size, uint32_t flags,
-				    uint64_t phys);
-extern void nv50_mem_vm_unbind(struct drm_device *, uint64_t virt,
-			       uint32_t size);
+extern int  nouveau_mem_detect(struct drm_device *);
+extern bool nouveau_mem_flags_valid(struct drm_device *, u32 tile_flags);
+extern struct nouveau_tile_reg *nv10_mem_set_tiling(
+	struct drm_device *dev, uint32_t addr, uint32_t size,
+	uint32_t pitch, uint32_t flags);
+extern void nv10_mem_put_tile_region(struct drm_device *dev,
+				     struct nouveau_tile_reg *tile,
+				     struct nouveau_fence *fence);
+extern const struct ttm_mem_type_manager_func nouveau_vram_manager;
 
 /* nouveau_notifier.c */
 extern int  nouveau_notifier_init_channel(struct nouveau_channel *);
 extern void nouveau_notifier_takedown_channel(struct nouveau_channel *);
 extern int  nouveau_notifier_alloc(struct nouveau_channel *, uint32_t handle,
-				   int cout, uint32_t *offset);
+				   int cout, uint32_t start, uint32_t end,
+				   uint32_t *offset);
 extern int  nouveau_notifier_offset(struct nouveau_gpuobj *, uint32_t *);
 extern int  nouveau_ioctl_notifier_alloc(struct drm_device *, void *data,
 					 struct drm_file *);
@@ -803,21 +864,44 @@ extern int  nouveau_ioctl_notifier_free(
 extern struct drm_ioctl_desc nouveau_ioctls[];
 extern int nouveau_max_ioctl;
 extern void nouveau_channel_cleanup(struct drm_device *, struct drm_file *);
-extern int  nouveau_channel_owner(struct drm_device *, struct drm_file *,
-				  int channel);
 extern int  nouveau_channel_alloc(struct drm_device *dev,
 				  struct nouveau_channel **chan,
 				  struct drm_file *file_priv,
 				  uint32_t fb_ctxdma, uint32_t tt_ctxdma);
-extern void nouveau_channel_free(struct nouveau_channel *);
+extern struct nouveau_channel *
+nouveau_channel_get_unlocked(struct nouveau_channel *);
+extern struct nouveau_channel *
+nouveau_channel_get(struct drm_device *, struct drm_file *, int id);
+extern void nouveau_channel_put_unlocked(struct nouveau_channel **);
+extern void nouveau_channel_put(struct nouveau_channel **);
+extern void nouveau_channel_ref(struct nouveau_channel *chan,
+				struct nouveau_channel **pchan);
+extern void nouveau_channel_idle(struct nouveau_channel *chan);
 
 /* nouveau_object.c */
+#define NVOBJ_CLASS(d,c,e) do {                                                \
+	int ret = nouveau_gpuobj_class_new((d), (c), NVOBJ_ENGINE_##e);        \
+	if (ret)                                                               \
+		return ret;                                                    \
+} while(0)
+
+#define NVOBJ_MTHD(d,c,m,e) do {                                               \
+	int ret = nouveau_gpuobj_mthd_new((d), (c), (m), (e));                 \
+	if (ret)                                                               \
+		return ret;                                                    \
+} while(0)
+
 extern int  nouveau_gpuobj_early_init(struct drm_device *);
 extern int  nouveau_gpuobj_init(struct drm_device *);
 extern void nouveau_gpuobj_takedown(struct drm_device *);
 extern int  nouveau_gpuobj_suspend(struct drm_device *dev);
-extern void nouveau_gpuobj_suspend_cleanup(struct drm_device *dev);
 extern void nouveau_gpuobj_resume(struct drm_device *dev);
+extern int  nouveau_gpuobj_class_new(struct drm_device *, u32 class, u32 eng);
+extern int  nouveau_gpuobj_mthd_new(struct drm_device *, u32 class, u32 mthd,
+				    int (*exec)(struct nouveau_channel *,
+					        u32 class, u32 mthd, u32 data));
+extern int  nouveau_gpuobj_mthd_call(struct nouveau_channel *, u32, u32, u32);
+extern int  nouveau_gpuobj_mthd_call2(struct drm_device *, int, u32, u32, u32);
 extern int nouveau_gpuobj_channel_init(struct nouveau_channel *,
 				       uint32_t vram_h, uint32_t tt_h);
 extern void nouveau_gpuobj_channel_takedown(struct nouveau_channel *);
@@ -832,21 +916,25 @@ extern int nouveau_gpuobj_new_fake(struc
 extern int nouveau_gpuobj_dma_new(struct nouveau_channel *, int class,
 				  uint64_t offset, uint64_t size, int access,
 				  int target, struct nouveau_gpuobj **);
-extern int nouveau_gpuobj_gart_dma_new(struct nouveau_channel *,
-				       uint64_t offset, uint64_t size,
-				       int access, struct nouveau_gpuobj **,
-				       uint32_t *o_ret);
-extern int nouveau_gpuobj_gr_new(struct nouveau_channel *, int class,
-				 struct nouveau_gpuobj **);
-extern int nouveau_gpuobj_sw_new(struct nouveau_channel *, int class,
-				 struct nouveau_gpuobj **);
+extern int nouveau_gpuobj_gr_new(struct nouveau_channel *, u32 handle, int class);
+extern int nv50_gpuobj_dma_new(struct nouveau_channel *, int class, u64 base,
+			       u64 size, int target, int access, u32 type,
+			       u32 comp, struct nouveau_gpuobj **pobj);
+extern void nv50_gpuobj_dma_init(struct nouveau_gpuobj *, u32 offset,
+				 int class, u64 base, u64 size, int target,
+				 int access, u32 type, u32 comp);
 extern int nouveau_ioctl_grobj_alloc(struct drm_device *, void *data,
 				     struct drm_file *);
 extern int nouveau_ioctl_gpuobj_free(struct drm_device *, void *data,
 				     struct drm_file *);
 
 /* nouveau_irq.c */
+extern int         nouveau_irq_init(struct drm_device *);
+extern void        nouveau_irq_fini(struct drm_device *);
 extern irqreturn_t nouveau_irq_handler(DRM_IRQ_ARGS);
+extern void        nouveau_irq_register(struct drm_device *, int status_bit,
+					void (*)(struct drm_device *));
+extern void        nouveau_irq_unregister(struct drm_device *, int status_bit);
 extern void        nouveau_irq_preinstall(struct drm_device *);
 extern int         nouveau_irq_postinstall(struct drm_device *);
 extern void        nouveau_irq_uninstall(struct drm_device *);
@@ -854,8 +942,8 @@ extern void        nouveau_irq_uninstall
 /* nouveau_sgdma.c */
 extern int nouveau_sgdma_init(struct drm_device *);
 extern void nouveau_sgdma_takedown(struct drm_device *);
-extern int nouveau_sgdma_get_page(struct drm_device *, uint32_t offset,
-				  uint32_t *page);
+extern uint32_t nouveau_sgdma_get_physical(struct drm_device *,
+					   uint32_t offset);
 extern struct ttm_backend *nouveau_sgdma_init_ttm(struct drm_device *);
 
 /* nouveau_debugfs.c */
@@ -966,18 +1054,25 @@ extern void nv04_fb_takedown(struct drm_
 /* nv10_fb.c */
 extern int  nv10_fb_init(struct drm_device *);
 extern void nv10_fb_takedown(struct drm_device *);
-extern void nv10_fb_set_region_tiling(struct drm_device *, int, uint32_t,
-				      uint32_t, uint32_t);
+extern void nv10_fb_init_tile_region(struct drm_device *dev, int i,
+				     uint32_t addr, uint32_t size,
+				     uint32_t pitch, uint32_t flags);
+extern void nv10_fb_set_tile_region(struct drm_device *dev, int i);
+extern void nv10_fb_free_tile_region(struct drm_device *dev, int i);
 
 /* nv30_fb.c */
 extern int  nv30_fb_init(struct drm_device *);
 extern void nv30_fb_takedown(struct drm_device *);
+extern void nv30_fb_init_tile_region(struct drm_device *dev, int i,
+				     uint32_t addr, uint32_t size,
+				     uint32_t pitch, uint32_t flags);
+extern void nv30_fb_free_tile_region(struct drm_device *dev, int i);
 
 /* nv40_fb.c */
 extern int  nv40_fb_init(struct drm_device *);
 extern void nv40_fb_takedown(struct drm_device *);
-extern void nv40_fb_set_region_tiling(struct drm_device *, int, uint32_t,
-				      uint32_t, uint32_t);
+extern void nv40_fb_set_tile_region(struct drm_device *dev, int i);
+
 /* nv50_fb.c */
 extern int  nv50_fb_init(struct drm_device *);
 extern void nv50_fb_takedown(struct drm_device *);
@@ -989,6 +1084,7 @@ extern void nvc0_fb_takedown(struct drm_
 
 /* nv04_fifo.c */
 extern int  nv04_fifo_init(struct drm_device *);
+extern void nv04_fifo_fini(struct drm_device *);
 extern void nv04_fifo_disable(struct drm_device *);
 extern void nv04_fifo_enable(struct drm_device *);
 extern bool nv04_fifo_reassign(struct drm_device *, bool);
@@ -998,19 +1094,18 @@ extern int  nv04_fifo_create_context(str
 extern void nv04_fifo_destroy_context(struct nouveau_channel *);
 extern int  nv04_fifo_load_context(struct nouveau_channel *);
 extern int  nv04_fifo_unload_context(struct drm_device *);
+extern void nv04_fifo_isr(struct drm_device *);
 
 /* nv10_fifo.c */
 extern int  nv10_fifo_init(struct drm_device *);
 extern int  nv10_fifo_channel_id(struct drm_device *);
 extern int  nv10_fifo_create_context(struct nouveau_channel *);
-extern void nv10_fifo_destroy_context(struct nouveau_channel *);
 extern int  nv10_fifo_load_context(struct nouveau_channel *);
 extern int  nv10_fifo_unload_context(struct drm_device *);
 
 /* nv40_fifo.c */
 extern int  nv40_fifo_init(struct drm_device *);
 extern int  nv40_fifo_create_context(struct nouveau_channel *);
-extern void nv40_fifo_destroy_context(struct nouveau_channel *);
 extern int  nv40_fifo_load_context(struct nouveau_channel *);
 extern int  nv40_fifo_unload_context(struct drm_device *);
 
@@ -1038,7 +1133,6 @@ extern int  nvc0_fifo_load_context(struc
 extern int  nvc0_fifo_unload_context(struct drm_device *);
 
 /* nv04_graph.c */
-extern struct nouveau_pgraph_object_class nv04_graph_grclass[];
 extern int  nv04_graph_init(struct drm_device *);
 extern void nv04_graph_takedown(struct drm_device *);
 extern void nv04_graph_fifo_access(struct drm_device *, bool);
@@ -1047,10 +1141,11 @@ extern int  nv04_graph_create_context(st
 extern void nv04_graph_destroy_context(struct nouveau_channel *);
 extern int  nv04_graph_load_context(struct nouveau_channel *);
 extern int  nv04_graph_unload_context(struct drm_device *);
-extern void nv04_graph_context_switch(struct drm_device *);
+extern int  nv04_graph_mthd_page_flip(struct nouveau_channel *chan,
+				      u32 class, u32 mthd, u32 data);
+extern struct nouveau_bitfield nv04_graph_nsource[];
 
 /* nv10_graph.c */
-extern struct nouveau_pgraph_object_class nv10_graph_grclass[];
 extern int  nv10_graph_init(struct drm_device *);
 extern void nv10_graph_takedown(struct drm_device *);
 extern struct nouveau_channel *nv10_graph_channel(struct drm_device *);
@@ -1058,13 +1153,11 @@ extern int  nv10_graph_create_context(st
 extern void nv10_graph_destroy_context(struct nouveau_channel *);
 extern int  nv10_graph_load_context(struct nouveau_channel *);
 extern int  nv10_graph_unload_context(struct drm_device *);
-extern void nv10_graph_context_switch(struct drm_device *);
-extern void nv10_graph_set_region_tiling(struct drm_device *, int, uint32_t,
-					 uint32_t, uint32_t);
+extern void nv10_graph_set_tile_region(struct drm_device *dev, int i);
+extern struct nouveau_bitfield nv10_graph_intr[];
+extern struct nouveau_bitfield nv10_graph_nstatus[];
 
 /* nv20_graph.c */
-extern struct nouveau_pgraph_object_class nv20_graph_grclass[];
-extern struct nouveau_pgraph_object_class nv30_graph_grclass[];
 extern int  nv20_graph_create_context(struct nouveau_channel *);
 extern void nv20_graph_destroy_context(struct nouveau_channel *);
 extern int  nv20_graph_load_context(struct nouveau_channel *);
@@ -1072,11 +1165,9 @@ extern int  nv20_graph_unload_context(st
 extern int  nv20_graph_init(struct drm_device *);
 extern void nv20_graph_takedown(struct drm_device *);
 extern int  nv30_graph_init(struct drm_device *);
-extern void nv20_graph_set_region_tiling(struct drm_device *, int, uint32_t,
-					 uint32_t, uint32_t);
+extern void nv20_graph_set_tile_region(struct drm_device *dev, int i);
 
 /* nv40_graph.c */
-extern struct nouveau_pgraph_object_class nv40_graph_grclass[];
 extern int  nv40_graph_init(struct drm_device *);
 extern void nv40_graph_takedown(struct drm_device *);
 extern struct nouveau_channel *nv40_graph_channel(struct drm_device *);
@@ -1085,11 +1176,9 @@ extern void nv40_graph_destroy_context(s
 extern int  nv40_graph_load_context(struct nouveau_channel *);
 extern int  nv40_graph_unload_context(struct drm_device *);
 extern void nv40_grctx_init(struct nouveau_grctx *);
-extern void nv40_graph_set_region_tiling(struct drm_device *, int, uint32_t,
-					 uint32_t, uint32_t);
+extern void nv40_graph_set_tile_region(struct drm_device *dev, int i);
 
 /* nv50_graph.c */
-extern struct nouveau_pgraph_object_class nv50_graph_grclass[];
 extern int  nv50_graph_init(struct drm_device *);
 extern void nv50_graph_takedown(struct drm_device *);
 extern void nv50_graph_fifo_access(struct drm_device *, bool);
@@ -1098,10 +1187,10 @@ extern int  nv50_graph_create_context(st
 extern void nv50_graph_destroy_context(struct nouveau_channel *);
 extern int  nv50_graph_load_context(struct nouveau_channel *);
 extern int  nv50_graph_unload_context(struct drm_device *);
-extern void nv50_graph_context_switch(struct drm_device *);
 extern int  nv50_grctx_init(struct nouveau_grctx *);
 extern void nv50_graph_tlb_flush(struct drm_device *dev);
 extern void nv86_graph_tlb_flush(struct drm_device *dev);
+extern struct nouveau_enum nv50_data_error_names[];
 
 /* nvc0_graph.c */
 extern int  nvc0_graph_init(struct drm_device *);
@@ -1113,16 +1202,22 @@ extern void nvc0_graph_destroy_context(s
 extern int  nvc0_graph_load_context(struct nouveau_channel *);
 extern int  nvc0_graph_unload_context(struct drm_device *);
 
+/* nv84_crypt.c */
+extern int  nv84_crypt_init(struct drm_device *dev);
+extern void nv84_crypt_fini(struct drm_device *dev);
+extern int  nv84_crypt_create_context(struct nouveau_channel *);
+extern void nv84_crypt_destroy_context(struct nouveau_channel *);
+extern void nv84_crypt_tlb_flush(struct drm_device *dev);
+
 /* nv04_instmem.c */
 extern int  nv04_instmem_init(struct drm_device *);
 extern void nv04_instmem_takedown(struct drm_device *);
 extern int  nv04_instmem_suspend(struct drm_device *);
 extern void nv04_instmem_resume(struct drm_device *);
-extern int  nv04_instmem_populate(struct drm_device *, struct nouveau_gpuobj *,
-				  uint32_t *size);
-extern void nv04_instmem_clear(struct drm_device *, struct nouveau_gpuobj *);
-extern int  nv04_instmem_bind(struct drm_device *, struct nouveau_gpuobj *);
-extern int  nv04_instmem_unbind(struct drm_device *, struct nouveau_gpuobj *);
+extern int  nv04_instmem_get(struct nouveau_gpuobj *, u32 size, u32 align);
+extern void nv04_instmem_put(struct nouveau_gpuobj *);
+extern int  nv04_instmem_map(struct nouveau_gpuobj *);
+extern void nv04_instmem_unmap(struct nouveau_gpuobj *);
 extern void nv04_instmem_flush(struct drm_device *);
 
 /* nv50_instmem.c */
@@ -1130,26 +1225,18 @@ extern int  nv50_instmem_init(struct drm
 extern void nv50_instmem_takedown(struct drm_device *);
 extern int  nv50_instmem_suspend(struct drm_device *);
 extern void nv50_instmem_resume(struct drm_device *);
-extern int  nv50_instmem_populate(struct drm_device *, struct nouveau_gpuobj *,
-				  uint32_t *size);
-extern void nv50_instmem_clear(struct drm_device *, struct nouveau_gpuobj *);
-extern int  nv50_instmem_bind(struct drm_device *, struct nouveau_gpuobj *);
-extern int  nv50_instmem_unbind(struct drm_device *, struct nouveau_gpuobj *);
+extern int  nv50_instmem_get(struct nouveau_gpuobj *, u32 size, u32 align);
+extern void nv50_instmem_put(struct nouveau_gpuobj *);
+extern int  nv50_instmem_map(struct nouveau_gpuobj *);
+extern void nv50_instmem_unmap(struct nouveau_gpuobj *);
 extern void nv50_instmem_flush(struct drm_device *);
 extern void nv84_instmem_flush(struct drm_device *);
-extern void nv50_vm_flush(struct drm_device *, int engine);
 
 /* nvc0_instmem.c */
 extern int  nvc0_instmem_init(struct drm_device *);
 extern void nvc0_instmem_takedown(struct drm_device *);
 extern int  nvc0_instmem_suspend(struct drm_device *);
 extern void nvc0_instmem_resume(struct drm_device *);
-extern int  nvc0_instmem_populate(struct drm_device *, struct nouveau_gpuobj *,
-				  uint32_t *size);
-extern void nvc0_instmem_clear(struct drm_device *, struct nouveau_gpuobj *);
-extern int  nvc0_instmem_bind(struct drm_device *, struct nouveau_gpuobj *);
-extern int  nvc0_instmem_unbind(struct drm_device *, struct nouveau_gpuobj *);
-extern void nvc0_instmem_flush(struct drm_device *);
 
 /* nv04_mc.c */
 extern int  nv04_mc_init(struct drm_device *);
@@ -1219,6 +1306,9 @@ extern u16 nouveau_bo_rd16(struct nouvea
 extern void nouveau_bo_wr16(struct nouveau_bo *nvbo, unsigned index, u16 val);
 extern u32 nouveau_bo_rd32(struct nouveau_bo *nvbo, unsigned index);
 extern void nouveau_bo_wr32(struct nouveau_bo *nvbo, unsigned index, u32 val);
+extern void nouveau_bo_fence(struct nouveau_bo *, struct nouveau_fence *);
+extern int nouveau_bo_validate(struct nouveau_bo *, bool interruptible,
+			       bool no_wait_reserve, bool no_wait_gpu);
 
 /* nouveau_fence.c */
 struct nouveau_fence;
@@ -1234,12 +1324,35 @@ extern void nouveau_fence_work(struct no
 			       void (*work)(void *priv, bool signalled),
 			       void *priv);
 struct nouveau_channel *nouveau_fence_channel(struct nouveau_fence *);
-extern bool nouveau_fence_signalled(void *obj, void *arg);
-extern int nouveau_fence_wait(void *obj, void *arg, bool lazy, bool intr);
+
+extern bool __nouveau_fence_signalled(void *obj, void *arg);
+extern int __nouveau_fence_wait(void *obj, void *arg, bool lazy, bool intr);
+extern int __nouveau_fence_flush(void *obj, void *arg);
+extern void __nouveau_fence_unref(void **obj);
+extern void *__nouveau_fence_ref(void *obj);
+
+static inline bool nouveau_fence_signalled(struct nouveau_fence *obj)
+{
+	return __nouveau_fence_signalled(obj, NULL);
+}
+static inline int
+nouveau_fence_wait(struct nouveau_fence *obj, bool lazy, bool intr)
+{
+	return __nouveau_fence_wait(obj, NULL, lazy, intr);
+}
 extern int nouveau_fence_sync(struct nouveau_fence *, struct nouveau_channel *);
-extern int nouveau_fence_flush(void *obj, void *arg);
-extern void nouveau_fence_unref(void **obj);
-extern void *nouveau_fence_ref(void *obj);
+static inline int nouveau_fence_flush(struct nouveau_fence *obj)
+{
+	return __nouveau_fence_flush(obj, NULL);
+}
+static inline void nouveau_fence_unref(struct nouveau_fence **obj)
+{
+	__nouveau_fence_unref((void **)obj);
+}
+static inline struct nouveau_fence *nouveau_fence_ref(struct nouveau_fence *obj)
+{
+	return __nouveau_fence_ref(obj);
+}
 
 /* nouveau_gem.c */
 extern int nouveau_gem_new(struct drm_device *, struct nouveau_channel *,
@@ -1259,15 +1372,28 @@ extern int nouveau_gem_ioctl_cpu_fini(st
 extern int nouveau_gem_ioctl_info(struct drm_device *, void *,
 				  struct drm_file *);
 
+/* nouveau_display.c */
+int nouveau_vblank_enable(struct drm_device *dev, int crtc);
+void nouveau_vblank_disable(struct drm_device *dev, int crtc);
+int nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
+			   struct drm_pending_vblank_event *event);
+int nouveau_finish_page_flip(struct nouveau_channel *,
+			     struct nouveau_page_flip_state *);
+
 /* nv10_gpio.c */
 int nv10_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag);
 int nv10_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state);
 
 /* nv50_gpio.c */
 int nv50_gpio_init(struct drm_device *dev);
+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);
-void nv50_gpio_irq_enable(struct drm_device *, enum dcb_gpio_tag, bool on);
+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,
+			      void (*)(void *, int), void *);
+bool nv50_gpio_irq_enable(struct drm_device *, enum dcb_gpio_tag, bool on);
 
 /* nv50_calc. */
 int nv50_calc_pll(struct drm_device *, struct pll_lims *, int clk,
@@ -1334,7 +1460,9 @@ static inline void nv_wr08(struct drm_de
 }
 
 #define nv_wait(dev, reg, mask, val) \
-	nouveau_wait_until(dev, 2000000000ULL, (reg), (mask), (val))
+	nouveau_wait_eq(dev, 2000000000ULL, (reg), (mask), (val))
+#define nv_wait_ne(dev, reg, mask, val) \
+	nouveau_wait_ne(dev, 2000000000ULL, (reg), (mask), (val))
 
 /* PRAMIN access */
 static inline u32 nv_ri32(struct drm_device *dev, unsigned offset)
@@ -1447,6 +1575,37 @@ nv_match_device(struct drm_device *dev,
 		dev->pdev->subsystem_device == sub_device;
 }
 
+/* returns 1 if device is one of the nv4x using the 0x4497 object class,
+ * helpful to determine a number of other hardware features
+ */
+static inline int
+nv44_graph_class(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+	if ((dev_priv->chipset & 0xf0) == 0x60)
+		return 1;
+
+	return !(0x0baf & (1 << (dev_priv->chipset & 0x0f)));
+}
+
+/* memory type/access flags, do not match hardware values */
+#define NV_MEM_ACCESS_RO  1
+#define NV_MEM_ACCESS_WO  2
+#define NV_MEM_ACCESS_RW (NV_MEM_ACCESS_RO | NV_MEM_ACCESS_WO)
+#define NV_MEM_ACCESS_SYS 4
+#define NV_MEM_ACCESS_VM  8
+
+#define NV_MEM_TARGET_VRAM        0
+#define NV_MEM_TARGET_PCI         1
+#define NV_MEM_TARGET_PCI_NOSNOOP 2
+#define NV_MEM_TARGET_VM          3
+#define NV_MEM_TARGET_GART        4
+
+#define NV_MEM_TYPE_VM 0x7f
+#define NV_MEM_COMP_VM 0x03
+
+/* NV_SW object class */
 #define NV_SW                                                        0x0000506e
 #define NV_SW_DMA_SEMAPHORE                                          0x00000060
 #define NV_SW_SEMAPHORE_OFFSET                                       0x00000064
@@ -1457,5 +1616,6 @@ nv_match_device(struct drm_device *dev,
 #define NV_SW_VBLSEM_OFFSET                                          0x00000400
 #define NV_SW_VBLSEM_RELEASE_VALUE                                   0x00000404
 #define NV_SW_VBLSEM_RELEASE                                         0x00000408
+#define NV_SW_PAGE_FLIP                                              0x00000500
 
 #endif /* __NOUVEAU_DRV_H__ */
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nouveau_fbcon.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nouveau_fbcon.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nouveau_fbcon.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nouveau_fbcon.c	2011-03-14 21:20:32.000000000 -0400
@@ -49,6 +49,102 @@
 #include "nouveau_fbcon.h"
 #include "nouveau_dma.h"
 
+static void
+nouveau_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
+{
+	struct nouveau_fbdev *nfbdev = info->par;
+	struct drm_device *dev = nfbdev->dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	int ret;
+
+	if (info->state != FBINFO_STATE_RUNNING)
+		return;
+
+	ret = -ENODEV;
+	if (!in_interrupt() && !(info->flags & FBINFO_HWACCEL_DISABLED) &&
+	    mutex_trylock(&dev_priv->channel->mutex)) {
+		if (dev_priv->card_type < NV_50)
+			ret = nv04_fbcon_fillrect(info, rect);
+		else
+		if (dev_priv->card_type < NV_C0)
+			ret = nv50_fbcon_fillrect(info, rect);
+		else
+			ret = nvc0_fbcon_fillrect(info, rect);
+		mutex_unlock(&dev_priv->channel->mutex);
+	}
+
+	if (ret == 0)
+		return;
+
+	if (ret != -ENODEV)
+		nouveau_fbcon_gpu_lockup(info);
+	cfb_fillrect(info, rect);
+}
+
+static void
+nouveau_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *image)
+{
+	struct nouveau_fbdev *nfbdev = info->par;
+	struct drm_device *dev = nfbdev->dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	int ret;
+
+	if (info->state != FBINFO_STATE_RUNNING)
+		return;
+
+	ret = -ENODEV;
+	if (!in_interrupt() && !(info->flags & FBINFO_HWACCEL_DISABLED) &&
+	    mutex_trylock(&dev_priv->channel->mutex)) {
+		if (dev_priv->card_type < NV_50)
+			ret = nv04_fbcon_copyarea(info, image);
+		else
+		if (dev_priv->card_type < NV_C0)
+			ret = nv50_fbcon_copyarea(info, image);
+		else
+			ret = nvc0_fbcon_copyarea(info, image);
+		mutex_unlock(&dev_priv->channel->mutex);
+	}
+
+	if (ret == 0)
+		return;
+
+	if (ret != -ENODEV)
+		nouveau_fbcon_gpu_lockup(info);
+	cfb_copyarea(info, image);
+}
+
+static void
+nouveau_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
+{
+	struct nouveau_fbdev *nfbdev = info->par;
+	struct drm_device *dev = nfbdev->dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	int ret;
+
+	if (info->state != FBINFO_STATE_RUNNING)
+		return;
+
+	ret = -ENODEV;
+	if (!in_interrupt() && !(info->flags & FBINFO_HWACCEL_DISABLED) &&
+	    mutex_trylock(&dev_priv->channel->mutex)) {
+		if (dev_priv->card_type < NV_50)
+			ret = nv04_fbcon_imageblit(info, image);
+		else
+		if (dev_priv->card_type < NV_C0)
+			ret = nv50_fbcon_imageblit(info, image);
+		else
+			ret = nvc0_fbcon_imageblit(info, image);
+		mutex_unlock(&dev_priv->channel->mutex);
+	}
+
+	if (ret == 0)
+		return;
+
+	if (ret != -ENODEV)
+		nouveau_fbcon_gpu_lockup(info);
+	cfb_imageblit(info, image);
+}
+
 static int
 nouveau_fbcon_sync(struct fb_info *info)
 {
@@ -58,22 +154,36 @@ nouveau_fbcon_sync(struct fb_info *info)
 	struct nouveau_channel *chan = dev_priv->channel;
 	int ret, i;
 
-	if (!chan || !chan->accel_done ||
+	if (!chan || !chan->accel_done || in_interrupt() ||
 	    info->state != FBINFO_STATE_RUNNING ||
 	    info->flags & FBINFO_HWACCEL_DISABLED)
 		return 0;
 
-	if (RING_SPACE(chan, 4)) {
+	if (!mutex_trylock(&chan->mutex))
+		return 0;
+
+	ret = RING_SPACE(chan, 4);
+	if (ret) {
+		mutex_unlock(&chan->mutex);
 		nouveau_fbcon_gpu_lockup(info);
 		return 0;
 	}
 
-	BEGIN_RING(chan, 0, 0x0104, 1);
-	OUT_RING(chan, 0);
-	BEGIN_RING(chan, 0, 0x0100, 1);
-	OUT_RING(chan, 0);
+	if (dev_priv->card_type >= NV_C0) {
+		BEGIN_NVC0(chan, 2, NvSub2D, 0x010c, 1);
+		OUT_RING  (chan, 0);
+		BEGIN_NVC0(chan, 2, NvSub2D, 0x0100, 1);
+		OUT_RING  (chan, 0);
+	} else {
+		BEGIN_RING(chan, 0, 0x0104, 1);
+		OUT_RING  (chan, 0);
+		BEGIN_RING(chan, 0, 0x0100, 1);
+		OUT_RING  (chan, 0);
+	}
+
 	nouveau_bo_wr32(chan->notifier_bo, chan->m2mf_ntfy + 3, 0xffffffff);
 	FIRE_RING(chan);
+	mutex_unlock(&chan->mutex);
 
 	ret = -EBUSY;
 	for (i = 0; i < 100000; i++) {
@@ -97,24 +207,9 @@ static struct fb_ops nouveau_fbcon_ops =
 	.owner = THIS_MODULE,
 	.fb_check_var = drm_fb_helper_check_var,
 	.fb_set_par = drm_fb_helper_set_par,
-	.fb_fillrect = cfb_fillrect,
-	.fb_copyarea = cfb_copyarea,
-	.fb_imageblit = cfb_imageblit,
-	.fb_sync = nouveau_fbcon_sync,
-	.fb_pan_display = drm_fb_helper_pan_display,
-	.fb_blank = drm_fb_helper_blank,
-	.fb_setcmap = drm_fb_helper_setcmap,
-	.fb_debug_enter = drm_fb_helper_debug_enter,
-	.fb_debug_leave = drm_fb_helper_debug_leave,
-};
-
-static struct fb_ops nv04_fbcon_ops = {
-	.owner = THIS_MODULE,
-	.fb_check_var = drm_fb_helper_check_var,
-	.fb_set_par = drm_fb_helper_set_par,
-	.fb_fillrect = nv04_fbcon_fillrect,
-	.fb_copyarea = nv04_fbcon_copyarea,
-	.fb_imageblit = nv04_fbcon_imageblit,
+	.fb_fillrect = nouveau_fbcon_fillrect,
+	.fb_copyarea = nouveau_fbcon_copyarea,
+	.fb_imageblit = nouveau_fbcon_imageblit,
 	.fb_sync = nouveau_fbcon_sync,
 	.fb_pan_display = drm_fb_helper_pan_display,
 	.fb_blank = drm_fb_helper_blank,
@@ -123,14 +218,13 @@ static struct fb_ops nv04_fbcon_ops = {
 	.fb_debug_leave = drm_fb_helper_debug_leave,
 };
 
-static struct fb_ops nv50_fbcon_ops = {
+static struct fb_ops nouveau_fbcon_sw_ops = {
 	.owner = THIS_MODULE,
 	.fb_check_var = drm_fb_helper_check_var,
 	.fb_set_par = drm_fb_helper_set_par,
-	.fb_fillrect = nv50_fbcon_fillrect,
-	.fb_copyarea = nv50_fbcon_copyarea,
-	.fb_imageblit = nv50_fbcon_imageblit,
-	.fb_sync = nouveau_fbcon_sync,
+	.fb_fillrect = cfb_fillrect,
+	.fb_copyarea = cfb_copyarea,
+	.fb_imageblit = cfb_imageblit,
 	.fb_pan_display = drm_fb_helper_pan_display,
 	.fb_blank = drm_fb_helper_blank,
 	.fb_setcmap = drm_fb_helper_setcmap,
@@ -257,9 +351,9 @@ nouveau_fbcon_create(struct nouveau_fbde
 			      FBINFO_HWACCEL_FILLRECT |
 			      FBINFO_HWACCEL_IMAGEBLIT;
 	info->flags |= FBINFO_CAN_FORCE_OUTPUT;
-	info->fbops = &nouveau_fbcon_ops;
-	info->fix.smem_start = dev->mode_config.fb_base + nvbo->bo.offset -
-			       dev_priv->vm_vram_base;
+	info->fbops = &nouveau_fbcon_sw_ops;
+	info->fix.smem_start = nvbo->bo.mem.bus.base +
+			       nvbo->bo.mem.bus.offset;
 	info->fix.smem_len = size;
 
 	info->screen_base = nvbo_kmap_obj_iovirtual(nouveau_fb->nvbo);
@@ -268,10 +362,6 @@ nouveau_fbcon_create(struct nouveau_fbde
 	drm_fb_helper_fill_fix(info, fb->pitch, fb->depth);
 	drm_fb_helper_fill_var(info, &nfbdev->helper, sizes->fb_width, sizes->fb_height);
 
-	/* FIXME: we really shouldn't expose mmio space at all */
-	info->fix.mmio_start = pci_resource_start(pdev, 1);
-	info->fix.mmio_len = pci_resource_len(pdev, 1);
-
 	/* Set aperture base/size for vesafb takeover */
 	info->apertures = dev_priv->apertures;
 	if (!info->apertures) {
@@ -285,19 +375,20 @@ nouveau_fbcon_create(struct nouveau_fbde
 	info->pixmap.flags = FB_PIXMAP_SYSTEM;
 	info->pixmap.scan_align = 1;
 
+	mutex_unlock(&dev->struct_mutex);
+
 	if (dev_priv->channel && !nouveau_nofbaccel) {
-		switch (dev_priv->card_type) {
-		case NV_C0:
-			break;
-		case NV_50:
-			nv50_fbcon_accel_init(info);
-			info->fbops = &nv50_fbcon_ops;
-			break;
-		default:
-			nv04_fbcon_accel_init(info);
-			info->fbops = &nv04_fbcon_ops;
-			break;
-		};
+		ret = -ENODEV;
+		if (dev_priv->card_type < NV_50)
+			ret = nv04_fbcon_accel_init(info);
+		else
+		if (dev_priv->card_type < NV_C0)
+			ret = nv50_fbcon_accel_init(info);
+		else
+			ret = nvc0_fbcon_accel_init(info);
+
+		if (ret == 0)
+			info->fbops = &nouveau_fbcon_ops;
 	}
 
 	nouveau_fbcon_zfill(dev, nfbdev);
@@ -308,7 +399,6 @@ nouveau_fbcon_create(struct nouveau_fbde
 						nouveau_fb->base.height,
 						nvbo->bo.offset, nvbo);
 
-	mutex_unlock(&dev->struct_mutex);
 	vga_switcheroo_client_fb_set(dev->pdev, info);
 	return 0;
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nouveau_fbcon.h linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nouveau_fbcon.h
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nouveau_fbcon.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nouveau_fbcon.h	2011-03-14 21:20:32.000000000 -0400
@@ -40,15 +40,21 @@ struct nouveau_fbdev {
 
 void nouveau_fbcon_restore(void);
 
-void nv04_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region);
-void nv04_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect);
-void nv04_fbcon_imageblit(struct fb_info *info, const struct fb_image *image);
+int nv04_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region);
+int nv04_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect);
+int nv04_fbcon_imageblit(struct fb_info *info, const struct fb_image *image);
 int nv04_fbcon_accel_init(struct fb_info *info);
-void nv50_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect);
-void nv50_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region);
-void nv50_fbcon_imageblit(struct fb_info *info, const struct fb_image *image);
+
+int nv50_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect);
+int nv50_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region);
+int nv50_fbcon_imageblit(struct fb_info *info, const struct fb_image *image);
 int nv50_fbcon_accel_init(struct fb_info *info);
 
+int nvc0_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect);
+int nvc0_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region);
+int nvc0_fbcon_imageblit(struct fb_info *info, const struct fb_image *image);
+int nvc0_fbcon_accel_init(struct fb_info *info);
+
 void nouveau_fbcon_gpu_lockup(struct fb_info *info);
 
 int nouveau_fbcon_init(struct drm_device *dev);
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nouveau_fence.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nouveau_fence.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nouveau_fence.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nouveau_fence.c	2011-03-14 21:20:32.000000000 -0400
@@ -32,7 +32,8 @@
 #include "nouveau_dma.h"
 
 #define USE_REFCNT(dev) (nouveau_private(dev)->chipset >= 0x10)
-#define USE_SEMA(dev) (nouveau_private(dev)->chipset >= 0x17)
+#define USE_SEMA(dev) (nouveau_private(dev)->chipset >= 0x17 && \
+		       nouveau_private(dev)->card_type < NV_C0)
 
 struct nouveau_fence {
 	struct nouveau_channel *channel;
@@ -64,6 +65,7 @@ nouveau_fence_del(struct kref *ref)
 	struct nouveau_fence *fence =
 		container_of(ref, struct nouveau_fence, refcount);
 
+	nouveau_channel_ref(NULL, &fence->channel);
 	kfree(fence);
 }
 
@@ -76,14 +78,17 @@ nouveau_fence_update(struct nouveau_chan
 
 	spin_lock(&chan->fence.lock);
 
-	if (USE_REFCNT(dev))
-		sequence = nvchan_rd32(chan, 0x48);
-	else
-		sequence = atomic_read(&chan->fence.last_sequence_irq);
+	/* Fetch the last sequence if the channel is still up and running */
+	if (likely(!list_empty(&chan->fence.pending))) {
+		if (USE_REFCNT(dev))
+			sequence = nvchan_rd32(chan, 0x48);
+		else
+			sequence = atomic_read(&chan->fence.last_sequence_irq);
 
-	if (chan->fence.sequence_ack == sequence)
-		goto out;
-	chan->fence.sequence_ack = sequence;
+		if (chan->fence.sequence_ack == sequence)
+			goto out;
+		chan->fence.sequence_ack = sequence;
+	}
 
 	list_for_each_entry_safe(fence, tmp, &chan->fence.pending, entry) {
 		sequence = fence->sequence;
@@ -113,13 +118,13 @@ nouveau_fence_new(struct nouveau_channel
 	if (!fence)
 		return -ENOMEM;
 	kref_init(&fence->refcount);
-	fence->channel = chan;
+	nouveau_channel_ref(chan, &fence->channel);
 
 	if (emit)
 		ret = nouveau_fence_emit(fence);
 
 	if (ret)
-		nouveau_fence_unref((void *)&fence);
+		nouveau_fence_unref(&fence);
 	*pfence = fence;
 	return ret;
 }
@@ -127,7 +132,7 @@ nouveau_fence_new(struct nouveau_channel
 struct nouveau_channel *
 nouveau_fence_channel(struct nouveau_fence *fence)
 {
-	return fence ? fence->channel : NULL;
+	return fence ? nouveau_channel_get_unlocked(fence->channel) : NULL;
 }
 
 int
@@ -135,6 +140,7 @@ nouveau_fence_emit(struct nouveau_fence
 {
 	struct nouveau_channel *chan = fence->channel;
 	struct drm_device *dev = chan->dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	int ret;
 
 	ret = RING_SPACE(chan, 2);
@@ -155,8 +161,15 @@ nouveau_fence_emit(struct nouveau_fence
 	list_add_tail(&fence->entry, &chan->fence.pending);
 	spin_unlock(&chan->fence.lock);
 
-	BEGIN_RING(chan, NvSubSw, USE_REFCNT(dev) ? 0x0050 : 0x0150, 1);
-	OUT_RING(chan, fence->sequence);
+	if (USE_REFCNT(dev)) {
+		if (dev_priv->card_type < NV_C0)
+			BEGIN_RING(chan, NvSubSw, 0x0050, 1);
+		else
+			BEGIN_NVC0(chan, 2, NvSubM2MF, 0x0050, 1);
+	} else {
+		BEGIN_RING(chan, NvSubSw, 0x0150, 1);
+	}
+	OUT_RING (chan, fence->sequence);
 	FIRE_RING(chan);
 
 	return 0;
@@ -182,7 +195,7 @@ nouveau_fence_work(struct nouveau_fence
 }
 
 void
-nouveau_fence_unref(void **sync_obj)
+__nouveau_fence_unref(void **sync_obj)
 {
 	struct nouveau_fence *fence = nouveau_fence(*sync_obj);
 
@@ -192,7 +205,7 @@ nouveau_fence_unref(void **sync_obj)
 }
 
 void *
-nouveau_fence_ref(void *sync_obj)
+__nouveau_fence_ref(void *sync_obj)
 {
 	struct nouveau_fence *fence = nouveau_fence(sync_obj);
 
@@ -201,7 +214,7 @@ nouveau_fence_ref(void *sync_obj)
 }
 
 bool
-nouveau_fence_signalled(void *sync_obj, void *sync_arg)
+__nouveau_fence_signalled(void *sync_obj, void *sync_arg)
 {
 	struct nouveau_fence *fence = nouveau_fence(sync_obj);
 	struct nouveau_channel *chan = fence->channel;
@@ -214,13 +227,14 @@ nouveau_fence_signalled(void *sync_obj,
 }
 
 int
-nouveau_fence_wait(void *sync_obj, void *sync_arg, bool lazy, bool intr)
+__nouveau_fence_wait(void *sync_obj, void *sync_arg, bool lazy, bool intr)
 {
 	unsigned long timeout = jiffies + (3 * DRM_HZ);
+	unsigned long sleep_time = jiffies + 1;
 	int ret = 0;
 
 	while (1) {
-		if (nouveau_fence_signalled(sync_obj, sync_arg))
+		if (__nouveau_fence_signalled(sync_obj, sync_arg))
 			break;
 
 		if (time_after_eq(jiffies, timeout)) {
@@ -230,7 +244,7 @@ nouveau_fence_wait(void *sync_obj, void
 
 		__set_current_state(intr ? TASK_INTERRUPTIBLE
 			: TASK_UNINTERRUPTIBLE);
-		if (lazy)
+		if (lazy && time_after_eq(jiffies, sleep_time))
 			schedule_timeout(1);
 
 		if (intr && signal_pending(current)) {
@@ -368,7 +382,7 @@ emit_semaphore(struct nouveau_channel *c
 
 	kref_get(&sema->ref);
 	nouveau_fence_work(fence, semaphore_work, sema);
-	nouveau_fence_unref((void *)&fence);
+	nouveau_fence_unref(&fence);
 
 	return 0;
 }
@@ -380,33 +394,49 @@ nouveau_fence_sync(struct nouveau_fence
 	struct nouveau_channel *chan = nouveau_fence_channel(fence);
 	struct drm_device *dev = wchan->dev;
 	struct nouveau_semaphore *sema;
-	int ret;
+	int ret = 0;
 
-	if (likely(!fence || chan == wchan ||
-		   nouveau_fence_signalled(fence, NULL)))
-		return 0;
+	if (likely(!chan || chan == wchan ||
+		   nouveau_fence_signalled(fence)))
+		goto out;
 
 	sema = alloc_semaphore(dev);
 	if (!sema) {
 		/* Early card or broken userspace, fall back to
 		 * software sync. */
-		return nouveau_fence_wait(fence, NULL, false, false);
+		ret = nouveau_fence_wait(fence, true, false);
+		goto out;
+	}
+
+	/* try to take chan's mutex, if we can't take it right away
+	 * we have to fallback to software sync to prevent locking
+	 * order issues
+	 */
+	if (!mutex_trylock(&chan->mutex)) {
+		ret = nouveau_fence_wait(fence, true, false);
+		goto out_unref;
 	}
 
 	/* Make wchan wait until it gets signalled */
 	ret = emit_semaphore(wchan, NV_SW_SEMAPHORE_ACQUIRE, sema);
 	if (ret)
-		goto out;
+		goto out_unlock;
 
 	/* Signal the semaphore from chan */
 	ret = emit_semaphore(chan, NV_SW_SEMAPHORE_RELEASE, sema);
-out:
+
+out_unlock:
+	mutex_unlock(&chan->mutex);
+out_unref:
 	kref_put(&sema->ref, free_semaphore);
+out:
+	if (chan)
+		nouveau_channel_put_unlocked(&chan);
 	return ret;
 }
 
 int
-nouveau_fence_flush(void *sync_obj, void *sync_arg)
+__nouveau_fence_flush(void *sync_obj, void *sync_arg)
 {
 	return 0;
 }
@@ -420,30 +450,27 @@ nouveau_fence_channel_init(struct nouvea
 	int ret;
 
 	/* Create an NV_SW object for various sync purposes */
-	ret = nouveau_gpuobj_sw_new(chan, NV_SW, &obj);
-	if (ret)
-		return ret;
-
-	ret = nouveau_ramht_insert(chan, NvSw, obj);
-	nouveau_gpuobj_ref(NULL, &obj);
+	ret = nouveau_gpuobj_gr_new(chan, NvSw, NV_SW);
 	if (ret)
 		return ret;
 
-	ret = RING_SPACE(chan, 2);
-	if (ret)
-		return ret;
-	BEGIN_RING(chan, NvSubSw, 0, 1);
-	OUT_RING(chan, NvSw);
+	/* we leave subchannel empty for nvc0 */
+	if (dev_priv->card_type < NV_C0) {
+		ret = RING_SPACE(chan, 2);
+		if (ret)
+			return ret;
+		BEGIN_RING(chan, NvSubSw, 0, 1);
+		OUT_RING(chan, NvSw);
+	}
 
 	/* Create a DMA object for the shared cross-channel sync area. */
 	if (USE_SEMA(dev)) {
-		struct drm_mm_node *mem = dev_priv->fence.bo->bo.mem.mm_node;
+		struct ttm_mem_reg *mem = &dev_priv->fence.bo->bo.mem;
 
 		ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY,
 					     mem->start << PAGE_SHIFT,
-					     mem->size << PAGE_SHIFT,
-					     NV_DMA_ACCESS_RW,
-					     NV_DMA_TARGET_VIDMEM, &obj);
+					     mem->size, NV_MEM_ACCESS_RW,
+					     NV_MEM_TARGET_VRAM, &obj);
 		if (ret)
 			return ret;
 
@@ -473,6 +500,8 @@ nouveau_fence_channel_fini(struct nouvea
 {
 	struct nouveau_fence *tmp, *fence;
 
+	spin_lock(&chan->fence.lock);
+
 	list_for_each_entry_safe(fence, tmp, &chan->fence.pending, entry) {
 		fence->signalled = true;
 		list_del(&fence->entry);
@@ -482,6 +511,8 @@ nouveau_fence_channel_fini(struct nouvea
 
 		kref_put(&fence->refcount, nouveau_fence_del);
 	}
+
+	spin_unlock(&chan->fence.lock);
 }
 
 int
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nouveau_gem.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nouveau_gem.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nouveau_gem.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nouveau_gem.c	2011-03-14 21:20:32.000000000 -0400
@@ -48,9 +48,6 @@ nouveau_gem_object_del(struct drm_gem_ob
 		return;
 	nvbo->gem = NULL;
 
-	if (unlikely(nvbo->cpu_filp))
-		ttm_bo_synccpu_write_release(bo);
-
 	if (unlikely(nvbo->pin_refcnt)) {
 		nvbo->pin_refcnt = 1;
 		nouveau_bo_unpin(nvbo);
@@ -106,32 +103,6 @@ nouveau_gem_info(struct drm_gem_object *
 	return 0;
 }
 
-static bool
-nouveau_gem_tile_flags_valid(struct drm_device *dev, uint32_t tile_flags)
-{
-	struct drm_nouveau_private *dev_priv = dev->dev_private;
-
-	if (dev_priv->card_type >= NV_50) {
-		switch (tile_flags & NOUVEAU_GEM_TILE_LAYOUT_MASK) {
-		case 0x0000:
-		case 0x1800:
-		case 0x2800:
-		case 0x4800:
-		case 0x7000:
-		case 0x7400:
-		case 0x7a00:
-		case 0xe000:
-			return true;
-		}
-	} else {
-		if (!(tile_flags & NOUVEAU_GEM_TILE_LAYOUT_MASK))
-			return true;
-	}
-
-	NV_ERROR(dev, "bad page flags: 0x%08x\n", tile_flags);
-	return false;
-}
-
 int
 nouveau_gem_ioctl_new(struct drm_device *dev, void *data,
 		      struct drm_file *file_priv)
@@ -146,11 +117,6 @@ nouveau_gem_ioctl_new(struct drm_device
 	if (unlikely(dev_priv->ttm.bdev.dev_mapping == NULL))
 		dev_priv->ttm.bdev.dev_mapping = dev_priv->dev->dev_mapping;
 
-	if (req->channel_hint) {
-		NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(req->channel_hint,
-						     file_priv, chan);
-	}
-
 	if (req->info.domain & NOUVEAU_GEM_DOMAIN_VRAM)
 		flags |= TTM_PL_FLAG_VRAM;
 	if (req->info.domain & NOUVEAU_GEM_DOMAIN_GART)
@@ -158,13 +124,23 @@ nouveau_gem_ioctl_new(struct drm_device
 	if (!flags || req->info.domain & NOUVEAU_GEM_DOMAIN_CPU)
 		flags |= TTM_PL_FLAG_SYSTEM;
 
-	if (!nouveau_gem_tile_flags_valid(dev, req->info.tile_flags))
+	if (!dev_priv->engine.vram.flags_valid(dev, req->info.tile_flags)) {
+		NV_ERROR(dev, "bad page flags: 0x%08x\n", req->info.tile_flags);
 		return -EINVAL;
+	}
+
+	if (req->channel_hint) {
+		chan = nouveau_channel_get(dev, file_priv, req->channel_hint);
+		if (IS_ERR(chan))
+			return PTR_ERR(chan);
+	}
 
 	ret = nouveau_gem_new(dev, chan, req->info.size, req->align, flags,
 			      req->info.tile_mode, req->info.tile_flags, false,
 			      (req->info.domain & NOUVEAU_GEM_DOMAIN_MAPPABLE),
 			      &nvbo);
+	if (chan)
+		nouveau_channel_put(&chan);
 	if (ret)
 		return ret;
 
@@ -231,15 +207,8 @@ validate_fini_list(struct list_head *lis
 
 	list_for_each_safe(entry, tmp, list) {
 		nvbo = list_entry(entry, struct nouveau_bo, entry);
-		if (likely(fence)) {
-			struct nouveau_fence *prev_fence;
 
-			spin_lock(&nvbo->bo.lock);
-			prev_fence = nvbo->bo.sync_obj;
-			nvbo->bo.sync_obj = nouveau_fence_ref(fence);
-			spin_unlock(&nvbo->bo.lock);
-			nouveau_fence_unref((void *)&prev_fence);
-		}
+		nouveau_bo_fence(nvbo, fence);
 
 		if (unlikely(nvbo->validate_mapped)) {
 			ttm_bo_kunmap(&nvbo->kmap);
@@ -299,14 +268,15 @@ retry:
 			return -EINVAL;
 		}
 
-		ret = ttm_bo_reserve(&nvbo->bo, false, false, true, sequence);
+		ret = ttm_bo_reserve(&nvbo->bo, true, false, true, sequence);
 		if (ret) {
 			validate_fini(op, NULL);
-			if (ret == -EAGAIN)
-				ret = ttm_bo_wait_unreserved(&nvbo->bo, false);
+			if (unlikely(ret == -EAGAIN))
+				ret = ttm_bo_wait_unreserved(&nvbo->bo, true);
 			drm_gem_object_unreference_unlocked(gem);
-			if (ret) {
-				NV_ERROR(dev, "fail reserve\n");
+			if (unlikely(ret)) {
+				if (ret != -ERESTARTSYS)
+					NV_ERROR(dev, "fail reserve\n");
 				return ret;
 			}
 			goto retry;
@@ -331,25 +301,6 @@ retry:
 			validate_fini(op, NULL);
 			return -EINVAL;
 		}
-
-		if (unlikely(atomic_read(&nvbo->bo.cpu_writers) > 0)) {
-			validate_fini(op, NULL);
-
-			if (nvbo->cpu_filp == file_priv) {
-				NV_ERROR(dev, "bo %p mapped by process trying "
-					      "to validate it!\n", nvbo);
-				return -EINVAL;
-			}
-
-			mutex_unlock(&drm_global_mutex);
-			ret = ttm_bo_wait_cpu(&nvbo->bo, false);
-			mutex_lock(&drm_global_mutex);
-			if (ret) {
-				NV_ERROR(dev, "fail wait_cpu\n");
-				return ret;
-			}
-			goto retry;
-		}
 	}
 
 	return 0;
@@ -383,11 +334,11 @@ validate_list(struct nouveau_channel *ch
 		}
 
 		nvbo->channel = (b->read_domains & (1 << 31)) ? NULL : chan;
-		ret = ttm_bo_validate(&nvbo->bo, &nvbo->placement,
-				      false, false, false);
+		ret = nouveau_bo_validate(nvbo, true, false, false);
 		nvbo->channel = NULL;
 		if (unlikely(ret)) {
-			NV_ERROR(dev, "fail ttm_validate\n");
+			if (ret != -ERESTARTSYS)
+				NV_ERROR(dev, "fail ttm_validate\n");
 			return ret;
 		}
 
@@ -439,13 +390,15 @@ nouveau_gem_pushbuf_validate(struct nouv
 
 	ret = validate_init(chan, file_priv, pbbo, nr_buffers, op);
 	if (unlikely(ret)) {
-		NV_ERROR(dev, "validate_init\n");
+		if (ret != -ERESTARTSYS)
+			NV_ERROR(dev, "validate_init\n");
 		return ret;
 	}
 
 	ret = validate_list(chan, &op->vram_list, pbbo, user_buffers);
 	if (unlikely(ret < 0)) {
-		NV_ERROR(dev, "validate vram_list\n");
+		if (ret != -ERESTARTSYS)
+			NV_ERROR(dev, "validate vram_list\n");
 		validate_fini(op, NULL);
 		return ret;
 	}
@@ -453,7 +406,8 @@ nouveau_gem_pushbuf_validate(struct nouv
 
 	ret = validate_list(chan, &op->gart_list, pbbo, user_buffers);
 	if (unlikely(ret < 0)) {
-		NV_ERROR(dev, "validate gart_list\n");
+		if (ret != -ERESTARTSYS)
+			NV_ERROR(dev, "validate gart_list\n");
 		validate_fini(op, NULL);
 		return ret;
 	}
@@ -461,7 +415,8 @@ nouveau_gem_pushbuf_validate(struct nouv
 
 	ret = validate_list(chan, &op->both_list, pbbo, user_buffers);
 	if (unlikely(ret < 0)) {
-		NV_ERROR(dev, "validate both_list\n");
+		if (ret != -ERESTARTSYS)
+			NV_ERROR(dev, "validate both_list\n");
 		validate_fini(op, NULL);
 		return ret;
 	}
@@ -557,9 +512,9 @@ nouveau_gem_pushbuf_reloc_apply(struct d
 				data |= r->vor;
 		}
 
-		spin_lock(&nvbo->bo.lock);
+		spin_lock(&nvbo->bo.bdev->fence_lock);
 		ret = ttm_bo_wait(&nvbo->bo, false, false, false);
-		spin_unlock(&nvbo->bo.lock);
+		spin_unlock(&nvbo->bo.bdev->fence_lock);
 		if (ret) {
 			NV_ERROR(dev, "reloc wait_idle failed: %d\n", ret);
 			break;
@@ -585,7 +540,9 @@ nouveau_gem_ioctl_pushbuf(struct drm_dev
 	struct nouveau_fence *fence = NULL;
 	int i, j, ret = 0, do_reloc = 0;
 
-	NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(req->channel, file_priv, chan);
+	chan = nouveau_channel_get(dev, file_priv, req->channel);
+	if (IS_ERR(chan))
+		return PTR_ERR(chan);
 
 	req->vram_available = dev_priv->fb_aper_free;
 	req->gart_available = dev_priv->gart_info.aper_free;
@@ -595,28 +552,34 @@ nouveau_gem_ioctl_pushbuf(struct drm_dev
 	if (unlikely(req->nr_push > NOUVEAU_GEM_MAX_PUSH)) {
 		NV_ERROR(dev, "pushbuf push count exceeds limit: %d max %d\n",
 			 req->nr_push, NOUVEAU_GEM_MAX_PUSH);
+		nouveau_channel_put(&chan);
 		return -EINVAL;
 	}
 
 	if (unlikely(req->nr_buffers > NOUVEAU_GEM_MAX_BUFFERS)) {
 		NV_ERROR(dev, "pushbuf bo count exceeds limit: %d max %d\n",
 			 req->nr_buffers, NOUVEAU_GEM_MAX_BUFFERS);
+		nouveau_channel_put(&chan);
 		return -EINVAL;
 	}
 
 	if (unlikely(req->nr_relocs > NOUVEAU_GEM_MAX_RELOCS)) {
 		NV_ERROR(dev, "pushbuf reloc count exceeds limit: %d max %d\n",
 			 req->nr_relocs, NOUVEAU_GEM_MAX_RELOCS);
+		nouveau_channel_put(&chan);
 		return -EINVAL;
 	}
 
 	push = u_memcpya(req->push, req->nr_push, sizeof(*push));
-	if (IS_ERR(push))
+	if (IS_ERR(push)) {
+		nouveau_channel_put(&chan);
 		return PTR_ERR(push);
+	}
 
 	bo = u_memcpya(req->buffers, req->nr_buffers, sizeof(*bo));
 	if (IS_ERR(bo)) {
 		kfree(push);
+		nouveau_channel_put(&chan);
 		return PTR_ERR(bo);
 	}
 
@@ -639,7 +602,8 @@ nouveau_gem_ioctl_pushbuf(struct drm_dev
 	ret = nouveau_gem_pushbuf_validate(chan, file_priv, bo, req->buffers,
 					   req->nr_buffers, &op, &do_reloc);
 	if (ret) {
-		NV_ERROR(dev, "validate: %d\n", ret);
+		if (ret != -ERESTARTSYS)
+			NV_ERROR(dev, "validate: %d\n", ret);
 		goto out;
 	}
 
@@ -732,7 +696,7 @@ nouveau_gem_ioctl_pushbuf(struct drm_dev
 
 out:
 	validate_fini(&op, fence);
-	nouveau_fence_unref((void**)&fence);
+	nouveau_fence_unref(&fence);
 	kfree(bo);
 	kfree(push);
 
@@ -750,6 +714,7 @@ out_next:
 		req->suffix1 = 0x00000000;
 	}
 
+	nouveau_channel_put(&chan);
 	return ret;
 }
 
@@ -781,26 +746,9 @@ nouveau_gem_ioctl_cpu_prep(struct drm_de
 		return -ENOENT;
 	nvbo = nouveau_gem_object(gem);
 
-	if (nvbo->cpu_filp) {
-		if (nvbo->cpu_filp == file_priv)
-			goto out;
-
-		ret = ttm_bo_wait_cpu(&nvbo->bo, no_wait);
-		if (ret)
-			goto out;
-	}
-
-	if (req->flags & NOUVEAU_GEM_CPU_PREP_NOBLOCK) {
-		spin_lock(&nvbo->bo.lock);
-		ret = ttm_bo_wait(&nvbo->bo, false, false, no_wait);
-		spin_unlock(&nvbo->bo.lock);
-	} else {
-		ret = ttm_bo_synccpu_write_grab(&nvbo->bo, no_wait);
-		if (ret == 0)
-			nvbo->cpu_filp = file_priv;
-	}
-
-out:
+	spin_lock(&nvbo->bo.bdev->fence_lock);
+	ret = ttm_bo_wait(&nvbo->bo, true, true, no_wait);
+	spin_unlock(&nvbo->bo.bdev->fence_lock);
 	drm_gem_object_unreference_unlocked(gem);
 	return ret;
 }
@@ -809,26 +757,7 @@ int
 nouveau_gem_ioctl_cpu_fini(struct drm_device *dev, void *data,
 			   struct drm_file *file_priv)
 {
-	struct drm_nouveau_gem_cpu_prep *req = data;
-	struct drm_gem_object *gem;
-	struct nouveau_bo *nvbo;
-	int ret = -EINVAL;
-
-	gem = drm_gem_object_lookup(dev, file_priv, req->handle);
-	if (!gem)
-		return -ENOENT;
-	nvbo = nouveau_gem_object(gem);
-
-	if (nvbo->cpu_filp != file_priv)
-		goto out;
-	nvbo->cpu_filp = NULL;
-
-	ttm_bo_synccpu_write_release(&nvbo->bo);
-	ret = 0;
-
-out:
-	drm_gem_object_unreference_unlocked(gem);
-	return ret;
+	return 0;
 }
 
 int
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nouveau_hw.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nouveau_hw.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nouveau_hw.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nouveau_hw.c	2011-03-14 21:20:32.000000000 -0400
@@ -953,7 +953,7 @@ nv_load_state_ext(struct drm_device *dev
 			NVWriteCRTC(dev, head, NV_PCRTC_850, regp->crtc_850);
 
 			reg900 = NVReadRAMDAC(dev, head, NV_PRAMDAC_900);
-			if (regp->crtc_cfg == NV_PCRTC_CONFIG_START_ADDRESS_HSYNC)
+			if (regp->crtc_cfg == NV10_PCRTC_CONFIG_START_ADDRESS_HSYNC)
 				NVWriteRAMDAC(dev, head, NV_PRAMDAC_900, reg900 | 0x10000);
 			else
 				NVWriteRAMDAC(dev, head, NV_PRAMDAC_900, reg900 & ~0x10000);
@@ -999,8 +999,8 @@ nv_load_state_ext(struct drm_device *dev
 		if (dev_priv->card_type == NV_10) {
 			/* Not waiting for vertical retrace before modifying
 			   CRE_53/CRE_54 causes lockups. */
-			nouveau_wait_until(dev, 650000000, NV_PRMCIO_INP0__COLOR, 0x8, 0x8);
-			nouveau_wait_until(dev, 650000000, NV_PRMCIO_INP0__COLOR, 0x8, 0x0);
+			nouveau_wait_eq(dev, 650000000, NV_PRMCIO_INP0__COLOR, 0x8, 0x8);
+			nouveau_wait_eq(dev, 650000000, NV_PRMCIO_INP0__COLOR, 0x8, 0x0);
 		}
 
 		wr_cio_state(dev, head, regp, NV_CIO_CRE_53);
@@ -1017,8 +1017,9 @@ nv_load_state_ext(struct drm_device *dev
 
 	NVWriteCRTC(dev, head, NV_PCRTC_START, regp->fb_start);
 
-	/* Setting 1 on this value gives you interrupts for every vblank period. */
-	NVWriteCRTC(dev, head, NV_PCRTC_INTR_EN_0, 0);
+	/* Enable vblank interrupts. */
+	NVWriteCRTC(dev, head, NV_PCRTC_INTR_EN_0,
+		    (dev->vblank_enabled[head] ? 1 : 0));
 	NVWriteCRTC(dev, head, NV_PCRTC_INTR_0, NV_PCRTC_INTR_0_VBLANK);
 }
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nouveau_irq.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nouveau_irq.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nouveau_irq.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nouveau_irq.c	2011-03-14 21:20:32.000000000 -0400
@@ -36,18 +36,7 @@
 #include "nouveau_drv.h"
 #include "nouveau_reg.h"
 #include "nouveau_ramht.h"
-#include <linux/ratelimit.h>
-
-/* needed for hotplug irq */
-#include "nouveau_connector.h"
-#include "nv50_display.h"
-
-static DEFINE_RATELIMIT_STATE(nouveau_ratelimit_state, 3 * HZ, 20);
-
-static int nouveau_ratelimit(void)
-{
-	return __ratelimit(&nouveau_ratelimit_state);
-}
+#include "nouveau_util.h"
 
 void
 nouveau_irq_preinstall(struct drm_device *dev)
@@ -57,19 +46,19 @@ nouveau_irq_preinstall(struct drm_device
 	/* Master disable */
 	nv_wr32(dev, NV03_PMC_INTR_EN_0, 0);
 
-	if (dev_priv->card_type >= NV_50) {
-		INIT_WORK(&dev_priv->irq_work, nv50_display_irq_handler_bh);
-		INIT_WORK(&dev_priv->hpd_work, nv50_display_irq_hotplug_bh);
-		spin_lock_init(&dev_priv->hpd_state.lock);
-		INIT_LIST_HEAD(&dev_priv->vbl_waiting);
-	}
+	INIT_LIST_HEAD(&dev_priv->vbl_waiting);
 }
 
 int
 nouveau_irq_postinstall(struct drm_device *dev)
 {
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+
 	/* Master enable */
 	nv_wr32(dev, NV03_PMC_INTR_EN_0, NV_PMC_INTR_EN_0_MASTER_ENABLE);
+	if (dev_priv->msi_enabled)
+		nv_wr08(dev, 0x00088068, 0xff);
+
 	return 0;
 }
 
@@ -80,1178 +69,83 @@ nouveau_irq_uninstall(struct drm_device
 	nv_wr32(dev, NV03_PMC_INTR_EN_0, 0);
 }
 
-static int
-nouveau_call_method(struct nouveau_channel *chan, int class, int mthd, int data)
-{
-	struct drm_nouveau_private *dev_priv = chan->dev->dev_private;
-	struct nouveau_pgraph_object_method *grm;
-	struct nouveau_pgraph_object_class *grc;
-
-	grc = dev_priv->engine.graph.grclass;
-	while (grc->id) {
-		if (grc->id == class)
-			break;
-		grc++;
-	}
-
-	if (grc->id != class || !grc->methods)
-		return -ENOENT;
-
-	grm = grc->methods;
-	while (grm->id) {
-		if (grm->id == mthd)
-			return grm->exec(chan, class, mthd, data);
-		grm++;
-	}
-
-	return -ENOENT;
-}
-
-static bool
-nouveau_fifo_swmthd(struct nouveau_channel *chan, uint32_t addr, uint32_t data)
-{
-	struct drm_device *dev = chan->dev;
-	const int subc = (addr >> 13) & 0x7;
-	const int mthd = addr & 0x1ffc;
-
-	if (mthd == 0x0000) {
-		struct nouveau_gpuobj *gpuobj;
-
-		gpuobj = nouveau_ramht_find(chan, data);
-		if (!gpuobj)
-			return false;
-
-		if (gpuobj->engine != NVOBJ_ENGINE_SW)
-			return false;
-
-		chan->sw_subchannel[subc] = gpuobj->class;
-		nv_wr32(dev, NV04_PFIFO_CACHE1_ENGINE, nv_rd32(dev,
-			NV04_PFIFO_CACHE1_ENGINE) & ~(0xf << subc * 4));
-		return true;
-	}
-
-	/* hw object */
-	if (nv_rd32(dev, NV04_PFIFO_CACHE1_ENGINE) & (1 << (subc*4)))
-		return false;
-
-	if (nouveau_call_method(chan, chan->sw_subchannel[subc], mthd, data))
-		return false;
-
-	return true;
-}
-
-static void
-nouveau_fifo_irq_handler(struct drm_device *dev)
-{
-	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nouveau_engine *engine = &dev_priv->engine;
-	uint32_t status, reassign;
-	int cnt = 0;
-
-	reassign = nv_rd32(dev, NV03_PFIFO_CACHES) & 1;
-	while ((status = nv_rd32(dev, NV03_PFIFO_INTR_0)) && (cnt++ < 100)) {
-		struct nouveau_channel *chan = NULL;
-		uint32_t chid, get;
-
-		nv_wr32(dev, NV03_PFIFO_CACHES, 0);
-
-		chid = engine->fifo.channel_id(dev);
-		if (chid >= 0 && chid < engine->fifo.channels)
-			chan = dev_priv->fifos[chid];
-		get  = nv_rd32(dev, NV03_PFIFO_CACHE1_GET);
-
-		if (status & NV_PFIFO_INTR_CACHE_ERROR) {
-			uint32_t mthd, data;
-			int ptr;
-
-			/* NV_PFIFO_CACHE1_GET actually goes to 0xffc before
-			 * wrapping on my G80 chips, but CACHE1 isn't big
-			 * enough for this much data.. Tests show that it
-			 * wraps around to the start at GET=0x800.. No clue
-			 * as to why..
-			 */
-			ptr = (get & 0x7ff) >> 2;
-
-			if (dev_priv->card_type < NV_40) {
-				mthd = nv_rd32(dev,
-					NV04_PFIFO_CACHE1_METHOD(ptr));
-				data = nv_rd32(dev,
-					NV04_PFIFO_CACHE1_DATA(ptr));
-			} else {
-				mthd = nv_rd32(dev,
-					NV40_PFIFO_CACHE1_METHOD(ptr));
-				data = nv_rd32(dev,
-					NV40_PFIFO_CACHE1_DATA(ptr));
-			}
-
-			if (!chan || !nouveau_fifo_swmthd(chan, mthd, data)) {
-				NV_INFO(dev, "PFIFO_CACHE_ERROR - Ch %d/%d "
-					     "Mthd 0x%04x Data 0x%08x\n",
-					chid, (mthd >> 13) & 7, mthd & 0x1ffc,
-					data);
-			}
-
-			nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_PUSH, 0);
-			nv_wr32(dev, NV03_PFIFO_INTR_0,
-						NV_PFIFO_INTR_CACHE_ERROR);
-
-			nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH0,
-				nv_rd32(dev, NV03_PFIFO_CACHE1_PUSH0) & ~1);
-			nv_wr32(dev, NV03_PFIFO_CACHE1_GET, get + 4);
-			nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH0,
-				nv_rd32(dev, NV03_PFIFO_CACHE1_PUSH0) | 1);
-			nv_wr32(dev, NV04_PFIFO_CACHE1_HASH, 0);
-
-			nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_PUSH,
-				nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_PUSH) | 1);
-			nv_wr32(dev, NV04_PFIFO_CACHE1_PULL0, 1);
-
-			status &= ~NV_PFIFO_INTR_CACHE_ERROR;
-		}
-
-		if (status & NV_PFIFO_INTR_DMA_PUSHER) {
-			u32 dma_get = nv_rd32(dev, 0x003244);
-			u32 dma_put = nv_rd32(dev, 0x003240);
-			u32 push = nv_rd32(dev, 0x003220);
-			u32 state = nv_rd32(dev, 0x003228);
-
-			if (dev_priv->card_type == NV_50) {
-				u32 ho_get = nv_rd32(dev, 0x003328);
-				u32 ho_put = nv_rd32(dev, 0x003320);
-				u32 ib_get = nv_rd32(dev, 0x003334);
-				u32 ib_put = nv_rd32(dev, 0x003330);
-
-				if (nouveau_ratelimit())
-					NV_INFO(dev, "PFIFO_DMA_PUSHER - Ch %d Get 0x%02x%08x "
-					     "Put 0x%02x%08x IbGet 0x%08x IbPut 0x%08x "
-					     "State 0x%08x Push 0x%08x\n",
-						chid, ho_get, dma_get, ho_put,
-						dma_put, ib_get, ib_put, state,
-						push);
-
-				/* METHOD_COUNT, in DMA_STATE on earlier chipsets */
-				nv_wr32(dev, 0x003364, 0x00000000);
-				if (dma_get != dma_put || ho_get != ho_put) {
-					nv_wr32(dev, 0x003244, dma_put);
-					nv_wr32(dev, 0x003328, ho_put);
-				} else
-				if (ib_get != ib_put) {
-					nv_wr32(dev, 0x003334, ib_put);
-				}
-			} else {
-				NV_INFO(dev, "PFIFO_DMA_PUSHER - Ch %d Get 0x%08x "
-					     "Put 0x%08x State 0x%08x Push 0x%08x\n",
-					chid, dma_get, dma_put, state, push);
-
-				if (dma_get != dma_put)
-					nv_wr32(dev, 0x003244, dma_put);
-			}
-
-			nv_wr32(dev, 0x003228, 0x00000000);
-			nv_wr32(dev, 0x003220, 0x00000001);
-			nv_wr32(dev, 0x002100, NV_PFIFO_INTR_DMA_PUSHER);
-			status &= ~NV_PFIFO_INTR_DMA_PUSHER;
-		}
-
-		if (status & NV_PFIFO_INTR_SEMAPHORE) {
-			uint32_t sem;
-
-			status &= ~NV_PFIFO_INTR_SEMAPHORE;
-			nv_wr32(dev, NV03_PFIFO_INTR_0,
-				NV_PFIFO_INTR_SEMAPHORE);
-
-			sem = nv_rd32(dev, NV10_PFIFO_CACHE1_SEMAPHORE);
-			nv_wr32(dev, NV10_PFIFO_CACHE1_SEMAPHORE, sem | 0x1);
-
-			nv_wr32(dev, NV03_PFIFO_CACHE1_GET, get + 4);
-			nv_wr32(dev, NV04_PFIFO_CACHE1_PULL0, 1);
-		}
-
-		if (dev_priv->card_type == NV_50) {
-			if (status & 0x00000010) {
-				nv50_fb_vm_trap(dev, 1, "PFIFO_BAR_FAULT");
-				status &= ~0x00000010;
-				nv_wr32(dev, 0x002100, 0x00000010);
-			}
-		}
-
-		if (status) {
-			if (nouveau_ratelimit())
-				NV_INFO(dev, "PFIFO_INTR 0x%08x - Ch %d\n",
-					status, chid);
-			nv_wr32(dev, NV03_PFIFO_INTR_0, status);
-			status = 0;
-		}
-
-		nv_wr32(dev, NV03_PFIFO_CACHES, reassign);
-	}
-
-	if (status) {
-		NV_INFO(dev, "PFIFO still angry after %d spins, halt\n", cnt);
-		nv_wr32(dev, 0x2140, 0);
-		nv_wr32(dev, 0x140, 0);
-	}
-
-	nv_wr32(dev, NV03_PMC_INTR_0, NV_PMC_INTR_0_PFIFO_PENDING);
-}
-
-struct nouveau_bitfield_names {
-	uint32_t mask;
-	const char *name;
-};
-
-static struct nouveau_bitfield_names nstatus_names[] =
-{
-	{ NV04_PGRAPH_NSTATUS_STATE_IN_USE,       "STATE_IN_USE" },
-	{ NV04_PGRAPH_NSTATUS_INVALID_STATE,      "INVALID_STATE" },
-	{ NV04_PGRAPH_NSTATUS_BAD_ARGUMENT,       "BAD_ARGUMENT" },
-	{ NV04_PGRAPH_NSTATUS_PROTECTION_FAULT,   "PROTECTION_FAULT" }
-};
-
-static struct nouveau_bitfield_names nstatus_names_nv10[] =
-{
-	{ NV10_PGRAPH_NSTATUS_STATE_IN_USE,       "STATE_IN_USE" },
-	{ NV10_PGRAPH_NSTATUS_INVALID_STATE,      "INVALID_STATE" },
-	{ NV10_PGRAPH_NSTATUS_BAD_ARGUMENT,       "BAD_ARGUMENT" },
-	{ NV10_PGRAPH_NSTATUS_PROTECTION_FAULT,   "PROTECTION_FAULT" }
-};
-
-static struct nouveau_bitfield_names nsource_names[] =
-{
-	{ NV03_PGRAPH_NSOURCE_NOTIFICATION,       "NOTIFICATION" },
-	{ NV03_PGRAPH_NSOURCE_DATA_ERROR,         "DATA_ERROR" },
-	{ NV03_PGRAPH_NSOURCE_PROTECTION_ERROR,   "PROTECTION_ERROR" },
-	{ NV03_PGRAPH_NSOURCE_RANGE_EXCEPTION,    "RANGE_EXCEPTION" },
-	{ NV03_PGRAPH_NSOURCE_LIMIT_COLOR,        "LIMIT_COLOR" },
-	{ NV03_PGRAPH_NSOURCE_LIMIT_ZETA,         "LIMIT_ZETA" },
-	{ NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD,       "ILLEGAL_MTHD" },
-	{ NV03_PGRAPH_NSOURCE_DMA_R_PROTECTION,   "DMA_R_PROTECTION" },
-	{ NV03_PGRAPH_NSOURCE_DMA_W_PROTECTION,   "DMA_W_PROTECTION" },
-	{ NV03_PGRAPH_NSOURCE_FORMAT_EXCEPTION,   "FORMAT_EXCEPTION" },
-	{ NV03_PGRAPH_NSOURCE_PATCH_EXCEPTION,    "PATCH_EXCEPTION" },
-	{ NV03_PGRAPH_NSOURCE_STATE_INVALID,      "STATE_INVALID" },
-	{ NV03_PGRAPH_NSOURCE_DOUBLE_NOTIFY,      "DOUBLE_NOTIFY" },
-	{ NV03_PGRAPH_NSOURCE_NOTIFY_IN_USE,      "NOTIFY_IN_USE" },
-	{ NV03_PGRAPH_NSOURCE_METHOD_CNT,         "METHOD_CNT" },
-	{ NV03_PGRAPH_NSOURCE_BFR_NOTIFICATION,   "BFR_NOTIFICATION" },
-	{ NV03_PGRAPH_NSOURCE_DMA_VTX_PROTECTION, "DMA_VTX_PROTECTION" },
-	{ NV03_PGRAPH_NSOURCE_DMA_WIDTH_A,        "DMA_WIDTH_A" },
-	{ NV03_PGRAPH_NSOURCE_DMA_WIDTH_B,        "DMA_WIDTH_B" },
-};
-
-static void
-nouveau_print_bitfield_names_(uint32_t value,
-				const struct nouveau_bitfield_names *namelist,
-				const int namelist_len)
-{
-	/*
-	 * Caller must have already printed the KERN_* log level for us.
-	 * Also the caller is responsible for adding the newline.
-	 */
-	int i;
-	for (i = 0; i < namelist_len; ++i) {
-		uint32_t mask = namelist[i].mask;
-		if (value & mask) {
-			printk(" %s", namelist[i].name);
-			value &= ~mask;
-		}
-	}
-	if (value)
-		printk(" (unknown bits 0x%08x)", value);
-}
-#define nouveau_print_bitfield_names(val, namelist) \
-	nouveau_print_bitfield_names_((val), (namelist), ARRAY_SIZE(namelist))
-
-struct nouveau_enum_names {
-	uint32_t value;
-	const char *name;
-};
-
-static void
-nouveau_print_enum_names_(uint32_t value,
-				const struct nouveau_enum_names *namelist,
-				const int namelist_len)
-{
-	/*
-	 * Caller must have already printed the KERN_* log level for us.
-	 * Also the caller is responsible for adding the newline.
-	 */
-	int i;
-	for (i = 0; i < namelist_len; ++i) {
-		if (value == namelist[i].value) {
-			printk("%s", namelist[i].name);
-			return;
-		}
-	}
-	printk("unknown value 0x%08x", value);
-}
-#define nouveau_print_enum_names(val, namelist) \
-	nouveau_print_enum_names_((val), (namelist), ARRAY_SIZE(namelist))
-
-static int
-nouveau_graph_chid_from_grctx(struct drm_device *dev)
+irqreturn_t
+nouveau_irq_handler(DRM_IRQ_ARGS)
 {
+	struct drm_device *dev = (struct drm_device *)arg;
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	uint32_t inst;
+	unsigned long flags;
+	u32 stat;
 	int i;
 
-	if (dev_priv->card_type < NV_40)
-		return dev_priv->engine.fifo.channels;
-	else
-	if (dev_priv->card_type < NV_50) {
-		inst = (nv_rd32(dev, 0x40032c) & 0xfffff) << 4;
-
-		for (i = 0; i < dev_priv->engine.fifo.channels; i++) {
-			struct nouveau_channel *chan = dev_priv->fifos[i];
-
-			if (!chan || !chan->ramin_grctx)
-				continue;
-
-			if (inst == chan->ramin_grctx->pinst)
-				break;
-		}
-	} else {
-		inst = (nv_rd32(dev, 0x40032c) & 0xfffff) << 12;
-
-		for (i = 0; i < dev_priv->engine.fifo.channels; i++) {
-			struct nouveau_channel *chan = dev_priv->fifos[i];
-
-			if (!chan || !chan->ramin)
-				continue;
-
-			if (inst == chan->ramin->vinst)
-				break;
-		}
-	}
-
-
-	return i;
-}
-
-static int
-nouveau_graph_trapped_channel(struct drm_device *dev, int *channel_ret)
-{
-	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nouveau_engine *engine = &dev_priv->engine;
-	int channel;
-
-	if (dev_priv->card_type < NV_10)
-		channel = (nv_rd32(dev, NV04_PGRAPH_TRAPPED_ADDR) >> 24) & 0xf;
-	else
-	if (dev_priv->card_type < NV_40)
-		channel = (nv_rd32(dev, NV04_PGRAPH_TRAPPED_ADDR) >> 20) & 0x1f;
-	else
-		channel = nouveau_graph_chid_from_grctx(dev);
-
-	if (channel >= engine->fifo.channels || !dev_priv->fifos[channel]) {
-		NV_ERROR(dev, "AIII, invalid/inactive channel id %d\n", channel);
-		return -EINVAL;
-	}
-
-	*channel_ret = channel;
-	return 0;
-}
-
-struct nouveau_pgraph_trap {
-	int channel;
-	int class;
-	int subc, mthd, size;
-	uint32_t data, data2;
-	uint32_t nsource, nstatus;
-};
-
-static void
-nouveau_graph_trap_info(struct drm_device *dev,
-			struct nouveau_pgraph_trap *trap)
-{
-	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	uint32_t address;
-
-	trap->nsource = trap->nstatus = 0;
-	if (dev_priv->card_type < NV_50) {
-		trap->nsource = nv_rd32(dev, NV03_PGRAPH_NSOURCE);
-		trap->nstatus = nv_rd32(dev, NV03_PGRAPH_NSTATUS);
-	}
-
-	if (nouveau_graph_trapped_channel(dev, &trap->channel))
-		trap->channel = -1;
-	address = nv_rd32(dev, NV04_PGRAPH_TRAPPED_ADDR);
-
-	trap->mthd = address & 0x1FFC;
-	trap->data = nv_rd32(dev, NV04_PGRAPH_TRAPPED_DATA);
-	if (dev_priv->card_type < NV_10) {
-		trap->subc  = (address >> 13) & 0x7;
-	} else {
-		trap->subc  = (address >> 16) & 0x7;
-		trap->data2 = nv_rd32(dev, NV10_PGRAPH_TRAPPED_DATA_HIGH);
-	}
-
-	if (dev_priv->card_type < NV_10)
-		trap->class = nv_rd32(dev, 0x400180 + trap->subc*4) & 0xFF;
-	else if (dev_priv->card_type < NV_40)
-		trap->class = nv_rd32(dev, 0x400160 + trap->subc*4) & 0xFFF;
-	else if (dev_priv->card_type < NV_50)
-		trap->class = nv_rd32(dev, 0x400160 + trap->subc*4) & 0xFFFF;
-	else
-		trap->class = nv_rd32(dev, 0x400814);
-}
-
-static void
-nouveau_graph_dump_trap_info(struct drm_device *dev, const char *id,
-			     struct nouveau_pgraph_trap *trap)
-{
-	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	uint32_t nsource = trap->nsource, nstatus = trap->nstatus;
-
-	if (dev_priv->card_type < NV_50) {
-		NV_INFO(dev, "%s - nSource:", id);
-		nouveau_print_bitfield_names(nsource, nsource_names);
-		printk(", nStatus:");
-		if (dev_priv->card_type < NV_10)
-			nouveau_print_bitfield_names(nstatus, nstatus_names);
-		else
-			nouveau_print_bitfield_names(nstatus, nstatus_names_nv10);
-		printk("\n");
-	}
-
-	NV_INFO(dev, "%s - Ch %d/%d Class 0x%04x Mthd 0x%04x "
-					"Data 0x%08x:0x%08x\n",
-					id, trap->channel, trap->subc,
-					trap->class, trap->mthd,
-					trap->data2, trap->data);
-}
-
-static int
-nouveau_pgraph_intr_swmthd(struct drm_device *dev,
-			   struct nouveau_pgraph_trap *trap)
-{
-	struct drm_nouveau_private *dev_priv = dev->dev_private;
-
-	if (trap->channel < 0 ||
-	    trap->channel >= dev_priv->engine.fifo.channels ||
-	    !dev_priv->fifos[trap->channel])
-		return -ENODEV;
-
-	return nouveau_call_method(dev_priv->fifos[trap->channel],
-				   trap->class, trap->mthd, trap->data);
-}
-
-static inline void
-nouveau_pgraph_intr_notify(struct drm_device *dev, uint32_t nsource)
-{
-	struct nouveau_pgraph_trap trap;
-	int unhandled = 0;
+	stat = nv_rd32(dev, NV03_PMC_INTR_0);
+	if (!stat)
+		return IRQ_NONE;
 
-	nouveau_graph_trap_info(dev, &trap);
+	spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
+	for (i = 0; i < 32 && stat; i++) {
+		if (!(stat & (1 << i)) || !dev_priv->irq_handler[i])
+			continue;
 
-	if (nsource & NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD) {
-		if (nouveau_pgraph_intr_swmthd(dev, &trap))
-			unhandled = 1;
-	} else {
-		unhandled = 1;
+		dev_priv->irq_handler[i](dev);
+		stat &= ~(1 << i);
 	}
 
-	if (unhandled)
-		nouveau_graph_dump_trap_info(dev, "PGRAPH_NOTIFY", &trap);
-}
-
-
-static inline void
-nouveau_pgraph_intr_error(struct drm_device *dev, uint32_t nsource)
-{
-	struct nouveau_pgraph_trap trap;
-	int unhandled = 0;
-
-	nouveau_graph_trap_info(dev, &trap);
-	trap.nsource = nsource;
-
-	if (nsource & NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD) {
-		if (nouveau_pgraph_intr_swmthd(dev, &trap))
-			unhandled = 1;
-	} else if (nsource & NV03_PGRAPH_NSOURCE_DMA_VTX_PROTECTION) {
-		uint32_t v = nv_rd32(dev, 0x402000);
-		nv_wr32(dev, 0x402000, v);
-
-		/* dump the error anyway for now: it's useful for
-		   Gallium development */
-		unhandled = 1;
-	} else {
-		unhandled = 1;
-	}
+	if (dev_priv->msi_enabled)
+		nv_wr08(dev, 0x00088068, 0xff);
+	spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
 
-	if (unhandled && nouveau_ratelimit())
-		nouveau_graph_dump_trap_info(dev, "PGRAPH_ERROR", &trap);
+	if (stat && nouveau_ratelimit())
+		NV_ERROR(dev, "PMC - unhandled INTR 0x%08x\n", stat);
+	return IRQ_HANDLED;
 }
 
-static inline void
-nouveau_pgraph_intr_context_switch(struct drm_device *dev)
+int
+nouveau_irq_init(struct drm_device *dev)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nouveau_engine *engine = &dev_priv->engine;
-	uint32_t chid;
-
-	chid = engine->fifo.channel_id(dev);
-	NV_DEBUG(dev, "PGRAPH context switch interrupt channel %x\n", chid);
-
-	switch (dev_priv->card_type) {
-	case NV_04:
-		nv04_graph_context_switch(dev);
-		break;
-	case NV_10:
-		nv10_graph_context_switch(dev);
-		break;
-	default:
-		NV_ERROR(dev, "Context switch not implemented\n");
-		break;
-	}
-}
-
-static void
-nouveau_pgraph_irq_handler(struct drm_device *dev)
-{
-	uint32_t status;
-
-	while ((status = nv_rd32(dev, NV03_PGRAPH_INTR))) {
-		uint32_t nsource = nv_rd32(dev, NV03_PGRAPH_NSOURCE);
-
-		if (status & NV_PGRAPH_INTR_NOTIFY) {
-			nouveau_pgraph_intr_notify(dev, nsource);
-
-			status &= ~NV_PGRAPH_INTR_NOTIFY;
-			nv_wr32(dev, NV03_PGRAPH_INTR, NV_PGRAPH_INTR_NOTIFY);
-		}
-
-		if (status & NV_PGRAPH_INTR_ERROR) {
-			nouveau_pgraph_intr_error(dev, nsource);
-
-			status &= ~NV_PGRAPH_INTR_ERROR;
-			nv_wr32(dev, NV03_PGRAPH_INTR, NV_PGRAPH_INTR_ERROR);
-		}
-
-		if (status & NV_PGRAPH_INTR_CONTEXT_SWITCH) {
-			status &= ~NV_PGRAPH_INTR_CONTEXT_SWITCH;
-			nv_wr32(dev, NV03_PGRAPH_INTR,
-				 NV_PGRAPH_INTR_CONTEXT_SWITCH);
-
-			nouveau_pgraph_intr_context_switch(dev);
-		}
+	int ret;
 
-		if (status) {
-			NV_INFO(dev, "Unhandled PGRAPH_INTR - 0x%08x\n", status);
-			nv_wr32(dev, NV03_PGRAPH_INTR, status);
+	if (nouveau_msi != 0 && dev_priv->card_type >= NV_50) {
+		ret = pci_enable_msi(dev->pdev);
+		if (ret == 0) {
+			NV_INFO(dev, "enabled MSI\n");
+			dev_priv->msi_enabled = true;
 		}
-
-		if ((nv_rd32(dev, NV04_PGRAPH_FIFO) & (1 << 0)) == 0)
-			nv_wr32(dev, NV04_PGRAPH_FIFO, 1);
 	}
 
-	nv_wr32(dev, NV03_PMC_INTR_0, NV_PMC_INTR_0_PGRAPH_PENDING);
-}
-
-static struct nouveau_enum_names nv50_mp_exec_error_names[] =
-{
-	{ 3, "STACK_UNDERFLOW" },
-	{ 4, "QUADON_ACTIVE" },
-	{ 8, "TIMEOUT" },
-	{ 0x10, "INVALID_OPCODE" },
-	{ 0x40, "BREAKPOINT" },
-};
-
-static void
-nv50_pgraph_mp_trap(struct drm_device *dev, int tpid, int display)
-{
-	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	uint32_t units = nv_rd32(dev, 0x1540);
-	uint32_t addr, mp10, status, pc, oplow, ophigh;
-	int i;
-	int mps = 0;
-	for (i = 0; i < 4; i++) {
-		if (!(units & 1 << (i+24)))
-			continue;
-		if (dev_priv->chipset < 0xa0)
-			addr = 0x408200 + (tpid << 12) + (i << 7);
-		else
-			addr = 0x408100 + (tpid << 11) + (i << 7);
-		mp10 = nv_rd32(dev, addr + 0x10);
-		status = nv_rd32(dev, addr + 0x14);
-		if (!status)
-			continue;
-		if (display) {
-			nv_rd32(dev, addr + 0x20);
-			pc = nv_rd32(dev, addr + 0x24);
-			oplow = nv_rd32(dev, addr + 0x70);
-			ophigh= nv_rd32(dev, addr + 0x74);
-			NV_INFO(dev, "PGRAPH_TRAP_MP_EXEC - "
-					"TP %d MP %d: ", tpid, i);
-			nouveau_print_enum_names(status,
-					nv50_mp_exec_error_names);
-			printk(" at %06x warp %d, opcode %08x %08x\n",
-					pc&0xffffff, pc >> 24,
-					oplow, ophigh);
-		}
-		nv_wr32(dev, addr + 0x10, mp10);
-		nv_wr32(dev, addr + 0x14, 0);
-		mps++;
-	}
-	if (!mps && display)
-		NV_INFO(dev, "PGRAPH_TRAP_MP_EXEC - TP %d: "
-				"No MPs claiming errors?\n", tpid);
+	return drm_irq_install(dev);
 }
 
-static void
-nv50_pgraph_tp_trap(struct drm_device *dev, int type, uint32_t ustatus_old,
-		uint32_t ustatus_new, int display, const char *name)
+void
+nouveau_irq_fini(struct drm_device *dev)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	int tps = 0;
-	uint32_t units = nv_rd32(dev, 0x1540);
-	int i, r;
-	uint32_t ustatus_addr, ustatus;
-	for (i = 0; i < 16; i++) {
-		if (!(units & (1 << i)))
-			continue;
-		if (dev_priv->chipset < 0xa0)
-			ustatus_addr = ustatus_old + (i << 12);
-		else
-			ustatus_addr = ustatus_new + (i << 11);
-		ustatus = nv_rd32(dev, ustatus_addr) & 0x7fffffff;
-		if (!ustatus)
-			continue;
-		tps++;
-		switch (type) {
-		case 6: /* texture error... unknown for now */
-			nv50_fb_vm_trap(dev, display, name);
-			if (display) {
-				NV_ERROR(dev, "magic set %d:\n", i);
-				for (r = ustatus_addr + 4; r <= ustatus_addr + 0x10; r += 4)
-					NV_ERROR(dev, "\t0x%08x: 0x%08x\n", r,
-						nv_rd32(dev, r));
-			}
-			break;
-		case 7: /* MP error */
-			if (ustatus & 0x00010000) {
-				nv50_pgraph_mp_trap(dev, i, display);
-				ustatus &= ~0x00010000;
-			}
-			break;
-		case 8: /* TPDMA error */
-			{
-			uint32_t e0c = nv_rd32(dev, ustatus_addr + 4);
-			uint32_t e10 = nv_rd32(dev, ustatus_addr + 8);
-			uint32_t e14 = nv_rd32(dev, ustatus_addr + 0xc);
-			uint32_t e18 = nv_rd32(dev, ustatus_addr + 0x10);
-			uint32_t e1c = nv_rd32(dev, ustatus_addr + 0x14);
-			uint32_t e20 = nv_rd32(dev, ustatus_addr + 0x18);
-			uint32_t e24 = nv_rd32(dev, ustatus_addr + 0x1c);
-			nv50_fb_vm_trap(dev, display, name);
-			/* 2d engine destination */
-			if (ustatus & 0x00000010) {
-				if (display) {
-					NV_INFO(dev, "PGRAPH_TRAP_TPDMA_2D - TP %d - Unknown fault at address %02x%08x\n",
-							i, e14, e10);
-					NV_INFO(dev, "PGRAPH_TRAP_TPDMA_2D - TP %d - e0c: %08x, e18: %08x, e1c: %08x, e20: %08x, e24: %08x\n",
-							i, e0c, e18, e1c, e20, e24);
-				}
-				ustatus &= ~0x00000010;
-			}
-			/* Render target */
-			if (ustatus & 0x00000040) {
-				if (display) {
-					NV_INFO(dev, "PGRAPH_TRAP_TPDMA_RT - TP %d - Unknown fault at address %02x%08x\n",
-							i, e14, e10);
-					NV_INFO(dev, "PGRAPH_TRAP_TPDMA_RT - TP %d - e0c: %08x, e18: %08x, e1c: %08x, e20: %08x, e24: %08x\n",
-							i, e0c, e18, e1c, e20, e24);
-				}
-				ustatus &= ~0x00000040;
-			}
-			/* CUDA memory: l[], g[] or stack. */
-			if (ustatus & 0x00000080) {
-				if (display) {
-					if (e18 & 0x80000000) {
-						/* g[] read fault? */
-						NV_INFO(dev, "PGRAPH_TRAP_TPDMA - TP %d - Global read fault at address %02x%08x\n",
-								i, e14, e10 | ((e18 >> 24) & 0x1f));
-						e18 &= ~0x1f000000;
-					} else if (e18 & 0xc) {
-						/* g[] write fault? */
-						NV_INFO(dev, "PGRAPH_TRAP_TPDMA - TP %d - Global write fault at address %02x%08x\n",
-								i, e14, e10 | ((e18 >> 7) & 0x1f));
-						e18 &= ~0x00000f80;
-					} else {
-						NV_INFO(dev, "PGRAPH_TRAP_TPDMA - TP %d - Unknown CUDA fault at address %02x%08x\n",
-								i, e14, e10);
-					}
-					NV_INFO(dev, "PGRAPH_TRAP_TPDMA - TP %d - e0c: %08x, e18: %08x, e1c: %08x, e20: %08x, e24: %08x\n",
-							i, e0c, e18, e1c, e20, e24);
-				}
-				ustatus &= ~0x00000080;
-			}
-			}
-			break;
-		}
-		if (ustatus) {
-			if (display)
-				NV_INFO(dev, "%s - TP%d: Unhandled ustatus 0x%08x\n", name, i, ustatus);
-		}
-		nv_wr32(dev, ustatus_addr, 0xc0000000);
-	}
 
-	if (!tps && display)
-		NV_INFO(dev, "%s - No TPs claiming errors?\n", name);
-}
-
-static void
-nv50_pgraph_trap_handler(struct drm_device *dev)
-{
-	struct nouveau_pgraph_trap trap;
-	uint32_t status = nv_rd32(dev, 0x400108);
-	uint32_t ustatus;
-	int display = nouveau_ratelimit();
-
-
-	if (!status && display) {
-		nouveau_graph_trap_info(dev, &trap);
-		nouveau_graph_dump_trap_info(dev, "PGRAPH_TRAP", &trap);
-		NV_INFO(dev, "PGRAPH_TRAP - no units reporting traps?\n");
-	}
-
-	/* DISPATCH: Relays commands to other units and handles NOTIFY,
-	 * COND, QUERY. If you get a trap from it, the command is still stuck
-	 * in DISPATCH and you need to do something about it. */
-	if (status & 0x001) {
-		ustatus = nv_rd32(dev, 0x400804) & 0x7fffffff;
-		if (!ustatus && display) {
-			NV_INFO(dev, "PGRAPH_TRAP_DISPATCH - no ustatus?\n");
-		}
-
-		/* Known to be triggered by screwed up NOTIFY and COND... */
-		if (ustatus & 0x00000001) {
-			nv50_fb_vm_trap(dev, display, "PGRAPH_TRAP_DISPATCH_FAULT");
-			nv_wr32(dev, 0x400500, 0);
-			if (nv_rd32(dev, 0x400808) & 0x80000000) {
-				if (display) {
-					if (nouveau_graph_trapped_channel(dev, &trap.channel))
-						trap.channel = -1;
-					trap.class = nv_rd32(dev, 0x400814);
-					trap.mthd = nv_rd32(dev, 0x400808) & 0x1ffc;
-					trap.subc = (nv_rd32(dev, 0x400808) >> 16) & 0x7;
-					trap.data = nv_rd32(dev, 0x40080c);
-					trap.data2 = nv_rd32(dev, 0x400810);
-					nouveau_graph_dump_trap_info(dev,
-							"PGRAPH_TRAP_DISPATCH_FAULT", &trap);
-					NV_INFO(dev, "PGRAPH_TRAP_DISPATCH_FAULT - 400808: %08x\n", nv_rd32(dev, 0x400808));
-					NV_INFO(dev, "PGRAPH_TRAP_DISPATCH_FAULT - 400848: %08x\n", nv_rd32(dev, 0x400848));
-				}
-				nv_wr32(dev, 0x400808, 0);
-			} else if (display) {
-				NV_INFO(dev, "PGRAPH_TRAP_DISPATCH_FAULT - No stuck command?\n");
-			}
-			nv_wr32(dev, 0x4008e8, nv_rd32(dev, 0x4008e8) & 3);
-			nv_wr32(dev, 0x400848, 0);
-			ustatus &= ~0x00000001;
-		}
-		if (ustatus & 0x00000002) {
-			nv50_fb_vm_trap(dev, display, "PGRAPH_TRAP_DISPATCH_QUERY");
-			nv_wr32(dev, 0x400500, 0);
-			if (nv_rd32(dev, 0x40084c) & 0x80000000) {
-				if (display) {
-					if (nouveau_graph_trapped_channel(dev, &trap.channel))
-						trap.channel = -1;
-					trap.class = nv_rd32(dev, 0x400814);
-					trap.mthd = nv_rd32(dev, 0x40084c) & 0x1ffc;
-					trap.subc = (nv_rd32(dev, 0x40084c) >> 16) & 0x7;
-					trap.data = nv_rd32(dev, 0x40085c);
-					trap.data2 = 0;
-					nouveau_graph_dump_trap_info(dev,
-							"PGRAPH_TRAP_DISPATCH_QUERY", &trap);
-					NV_INFO(dev, "PGRAPH_TRAP_DISPATCH_QUERY - 40084c: %08x\n", nv_rd32(dev, 0x40084c));
-				}
-				nv_wr32(dev, 0x40084c, 0);
-			} else if (display) {
-				NV_INFO(dev, "PGRAPH_TRAP_DISPATCH_QUERY - No stuck command?\n");
-			}
-			ustatus &= ~0x00000002;
-		}
-		if (ustatus && display)
-			NV_INFO(dev, "PGRAPH_TRAP_DISPATCH - Unhandled ustatus 0x%08x\n", ustatus);
-		nv_wr32(dev, 0x400804, 0xc0000000);
-		nv_wr32(dev, 0x400108, 0x001);
-		status &= ~0x001;
-	}
-
-	/* TRAPs other than dispatch use the "normal" trap regs. */
-	if (status && display) {
-		nouveau_graph_trap_info(dev, &trap);
-		nouveau_graph_dump_trap_info(dev,
-				"PGRAPH_TRAP", &trap);
-	}
-
-	/* M2MF: Memory to memory copy engine. */
-	if (status & 0x002) {
-		ustatus = nv_rd32(dev, 0x406800) & 0x7fffffff;
-		if (!ustatus && display) {
-			NV_INFO(dev, "PGRAPH_TRAP_M2MF - no ustatus?\n");
-		}
-		if (ustatus & 0x00000001) {
-			nv50_fb_vm_trap(dev, display, "PGRAPH_TRAP_M2MF_NOTIFY");
-			ustatus &= ~0x00000001;
-		}
-		if (ustatus & 0x00000002) {
-			nv50_fb_vm_trap(dev, display, "PGRAPH_TRAP_M2MF_IN");
-			ustatus &= ~0x00000002;
-		}
-		if (ustatus & 0x00000004) {
-			nv50_fb_vm_trap(dev, display, "PGRAPH_TRAP_M2MF_OUT");
-			ustatus &= ~0x00000004;
-		}
-		NV_INFO (dev, "PGRAPH_TRAP_M2MF - %08x %08x %08x %08x\n",
-				nv_rd32(dev, 0x406804),
-				nv_rd32(dev, 0x406808),
-				nv_rd32(dev, 0x40680c),
-				nv_rd32(dev, 0x406810));
-		if (ustatus && display)
-			NV_INFO(dev, "PGRAPH_TRAP_M2MF - Unhandled ustatus 0x%08x\n", ustatus);
-		/* No sane way found yet -- just reset the bugger. */
-		nv_wr32(dev, 0x400040, 2);
-		nv_wr32(dev, 0x400040, 0);
-		nv_wr32(dev, 0x406800, 0xc0000000);
-		nv_wr32(dev, 0x400108, 0x002);
-		status &= ~0x002;
-	}
-
-	/* VFETCH: Fetches data from vertex buffers. */
-	if (status & 0x004) {
-		ustatus = nv_rd32(dev, 0x400c04) & 0x7fffffff;
-		if (!ustatus && display) {
-			NV_INFO(dev, "PGRAPH_TRAP_VFETCH - no ustatus?\n");
-		}
-		if (ustatus & 0x00000001) {
-			nv50_fb_vm_trap(dev, display, "PGRAPH_TRAP_VFETCH_FAULT");
-			NV_INFO (dev, "PGRAPH_TRAP_VFETCH_FAULT - %08x %08x %08x %08x\n",
-					nv_rd32(dev, 0x400c00),
-					nv_rd32(dev, 0x400c08),
-					nv_rd32(dev, 0x400c0c),
-					nv_rd32(dev, 0x400c10));
-			ustatus &= ~0x00000001;
-		}
-		if (ustatus && display)
-			NV_INFO(dev, "PGRAPH_TRAP_VFETCH - Unhandled ustatus 0x%08x\n", ustatus);
-		nv_wr32(dev, 0x400c04, 0xc0000000);
-		nv_wr32(dev, 0x400108, 0x004);
-		status &= ~0x004;
-	}
-
-	/* STRMOUT: DirectX streamout / OpenGL transform feedback. */
-	if (status & 0x008) {
-		ustatus = nv_rd32(dev, 0x401800) & 0x7fffffff;
-		if (!ustatus && display) {
-			NV_INFO(dev, "PGRAPH_TRAP_STRMOUT - no ustatus?\n");
-		}
-		if (ustatus & 0x00000001) {
-			nv50_fb_vm_trap(dev, display, "PGRAPH_TRAP_STRMOUT_FAULT");
-			NV_INFO (dev, "PGRAPH_TRAP_STRMOUT_FAULT - %08x %08x %08x %08x\n",
-					nv_rd32(dev, 0x401804),
-					nv_rd32(dev, 0x401808),
-					nv_rd32(dev, 0x40180c),
-					nv_rd32(dev, 0x401810));
-			ustatus &= ~0x00000001;
-		}
-		if (ustatus && display)
-			NV_INFO(dev, "PGRAPH_TRAP_STRMOUT - Unhandled ustatus 0x%08x\n", ustatus);
-		/* No sane way found yet -- just reset the bugger. */
-		nv_wr32(dev, 0x400040, 0x80);
-		nv_wr32(dev, 0x400040, 0);
-		nv_wr32(dev, 0x401800, 0xc0000000);
-		nv_wr32(dev, 0x400108, 0x008);
-		status &= ~0x008;
-	}
-
-	/* CCACHE: Handles code and c[] caches and fills them. */
-	if (status & 0x010) {
-		ustatus = nv_rd32(dev, 0x405018) & 0x7fffffff;
-		if (!ustatus && display) {
-			NV_INFO(dev, "PGRAPH_TRAP_CCACHE - no ustatus?\n");
-		}
-		if (ustatus & 0x00000001) {
-			nv50_fb_vm_trap(dev, display, "PGRAPH_TRAP_CCACHE_FAULT");
-			NV_INFO (dev, "PGRAPH_TRAP_CCACHE_FAULT - %08x %08x %08x %08x %08x %08x %08x\n",
-					nv_rd32(dev, 0x405800),
-					nv_rd32(dev, 0x405804),
-					nv_rd32(dev, 0x405808),
-					nv_rd32(dev, 0x40580c),
-					nv_rd32(dev, 0x405810),
-					nv_rd32(dev, 0x405814),
-					nv_rd32(dev, 0x40581c));
-			ustatus &= ~0x00000001;
-		}
-		if (ustatus && display)
-			NV_INFO(dev, "PGRAPH_TRAP_CCACHE - Unhandled ustatus 0x%08x\n", ustatus);
-		nv_wr32(dev, 0x405018, 0xc0000000);
-		nv_wr32(dev, 0x400108, 0x010);
-		status &= ~0x010;
-	}
-
-	/* Unknown, not seen yet... 0x402000 is the only trap status reg
-	 * remaining, so try to handle it anyway. Perhaps related to that
-	 * unknown DMA slot on tesla? */
-	if (status & 0x20) {
-		nv50_fb_vm_trap(dev, display, "PGRAPH_TRAP_UNKC04");
-		ustatus = nv_rd32(dev, 0x402000) & 0x7fffffff;
-		if (display)
-			NV_INFO(dev, "PGRAPH_TRAP_UNKC04 - Unhandled ustatus 0x%08x\n", ustatus);
-		nv_wr32(dev, 0x402000, 0xc0000000);
-		/* no status modifiction on purpose */
-	}
-
-	/* TEXTURE: CUDA texturing units */
-	if (status & 0x040) {
-		nv50_pgraph_tp_trap (dev, 6, 0x408900, 0x408600, display,
-				"PGRAPH_TRAP_TEXTURE");
-		nv_wr32(dev, 0x400108, 0x040);
-		status &= ~0x040;
-	}
-
-	/* MP: CUDA execution engines. */
-	if (status & 0x080) {
-		nv50_pgraph_tp_trap (dev, 7, 0x408314, 0x40831c, display,
-				"PGRAPH_TRAP_MP");
-		nv_wr32(dev, 0x400108, 0x080);
-		status &= ~0x080;
-	}
-
-	/* TPDMA:  Handles TP-initiated uncached memory accesses:
-	 * l[], g[], stack, 2d surfaces, render targets. */
-	if (status & 0x100) {
-		nv50_pgraph_tp_trap (dev, 8, 0x408e08, 0x408708, display,
-				"PGRAPH_TRAP_TPDMA");
-		nv_wr32(dev, 0x400108, 0x100);
-		status &= ~0x100;
-	}
-
-	if (status) {
-		if (display)
-			NV_INFO(dev, "PGRAPH_TRAP - Unknown trap 0x%08x\n",
-				status);
-		nv_wr32(dev, 0x400108, status);
-	}
-}
-
-/* There must be a *lot* of these. Will take some time to gather them up. */
-static struct nouveau_enum_names nv50_data_error_names[] =
-{
-	{ 4,	"INVALID_VALUE" },
-	{ 5,	"INVALID_ENUM" },
-	{ 8,	"INVALID_OBJECT" },
-	{ 0xc,	"INVALID_BITFIELD" },
-	{ 0x28,	"MP_NO_REG_SPACE" },
-	{ 0x2b,	"MP_BLOCK_SIZE_MISMATCH" },
-};
-
-static void
-nv50_pgraph_irq_handler(struct drm_device *dev)
-{
-	struct nouveau_pgraph_trap trap;
-	int unhandled = 0;
-	uint32_t status;
-
-	while ((status = nv_rd32(dev, NV03_PGRAPH_INTR))) {
-		/* NOTIFY: You've set a NOTIFY an a command and it's done. */
-		if (status & 0x00000001) {
-			nouveau_graph_trap_info(dev, &trap);
-			if (nouveau_ratelimit())
-				nouveau_graph_dump_trap_info(dev,
-						"PGRAPH_NOTIFY", &trap);
-			status &= ~0x00000001;
-			nv_wr32(dev, NV03_PGRAPH_INTR, 0x00000001);
-		}
-
-		/* COMPUTE_QUERY: Purpose and exact cause unknown, happens
-		 * when you write 0x200 to 0x50c0 method 0x31c. */
-		if (status & 0x00000002) {
-			nouveau_graph_trap_info(dev, &trap);
-			if (nouveau_ratelimit())
-				nouveau_graph_dump_trap_info(dev,
-						"PGRAPH_COMPUTE_QUERY", &trap);
-			status &= ~0x00000002;
-			nv_wr32(dev, NV03_PGRAPH_INTR, 0x00000002);
-		}
-
-		/* Unknown, never seen: 0x4 */
-
-		/* ILLEGAL_MTHD: You used a wrong method for this class. */
-		if (status & 0x00000010) {
-			nouveau_graph_trap_info(dev, &trap);
-			if (nouveau_pgraph_intr_swmthd(dev, &trap))
-				unhandled = 1;
-			if (unhandled && nouveau_ratelimit())
-				nouveau_graph_dump_trap_info(dev,
-						"PGRAPH_ILLEGAL_MTHD", &trap);
-			status &= ~0x00000010;
-			nv_wr32(dev, NV03_PGRAPH_INTR, 0x00000010);
-		}
-
-		/* ILLEGAL_CLASS: You used a wrong class. */
-		if (status & 0x00000020) {
-			nouveau_graph_trap_info(dev, &trap);
-			if (nouveau_ratelimit())
-				nouveau_graph_dump_trap_info(dev,
-						"PGRAPH_ILLEGAL_CLASS", &trap);
-			status &= ~0x00000020;
-			nv_wr32(dev, NV03_PGRAPH_INTR, 0x00000020);
-		}
-
-		/* DOUBLE_NOTIFY: You tried to set a NOTIFY on another NOTIFY. */
-		if (status & 0x00000040) {
-			nouveau_graph_trap_info(dev, &trap);
-			if (nouveau_ratelimit())
-				nouveau_graph_dump_trap_info(dev,
-						"PGRAPH_DOUBLE_NOTIFY", &trap);
-			status &= ~0x00000040;
-			nv_wr32(dev, NV03_PGRAPH_INTR, 0x00000040);
-		}
-
-		/* CONTEXT_SWITCH: PGRAPH needs us to load a new context */
-		if (status & 0x00001000) {
-			nv_wr32(dev, 0x400500, 0x00000000);
-			nv_wr32(dev, NV03_PGRAPH_INTR,
-				NV_PGRAPH_INTR_CONTEXT_SWITCH);
-			nv_wr32(dev, NV40_PGRAPH_INTR_EN, nv_rd32(dev,
-				NV40_PGRAPH_INTR_EN) &
-				~NV_PGRAPH_INTR_CONTEXT_SWITCH);
-			nv_wr32(dev, 0x400500, 0x00010001);
-
-			nv50_graph_context_switch(dev);
-
-			status &= ~NV_PGRAPH_INTR_CONTEXT_SWITCH;
-		}
-
-		/* BUFFER_NOTIFY: Your m2mf transfer finished */
-		if (status & 0x00010000) {
-			nouveau_graph_trap_info(dev, &trap);
-			if (nouveau_ratelimit())
-				nouveau_graph_dump_trap_info(dev,
-						"PGRAPH_BUFFER_NOTIFY", &trap);
-			status &= ~0x00010000;
-			nv_wr32(dev, NV03_PGRAPH_INTR, 0x00010000);
-		}
-
-		/* DATA_ERROR: Invalid value for this method, or invalid
-		 * state in current PGRAPH context for this operation */
-		if (status & 0x00100000) {
-			nouveau_graph_trap_info(dev, &trap);
-			if (nouveau_ratelimit()) {
-				nouveau_graph_dump_trap_info(dev,
-						"PGRAPH_DATA_ERROR", &trap);
-				NV_INFO (dev, "PGRAPH_DATA_ERROR - ");
-				nouveau_print_enum_names(nv_rd32(dev, 0x400110),
-						nv50_data_error_names);
-				printk("\n");
-			}
-			status &= ~0x00100000;
-			nv_wr32(dev, NV03_PGRAPH_INTR, 0x00100000);
-		}
-
-		/* TRAP: Something bad happened in the middle of command
-		 * execution.  Has a billion types, subtypes, and even
-		 * subsubtypes. */
-		if (status & 0x00200000) {
-			nv50_pgraph_trap_handler(dev);
-			status &= ~0x00200000;
-			nv_wr32(dev, NV03_PGRAPH_INTR, 0x00200000);
-		}
-
-		/* Unknown, never seen: 0x00400000 */
-
-		/* SINGLE_STEP: Happens on every method if you turned on
-		 * single stepping in 40008c */
-		if (status & 0x01000000) {
-			nouveau_graph_trap_info(dev, &trap);
-			if (nouveau_ratelimit())
-				nouveau_graph_dump_trap_info(dev,
-						"PGRAPH_SINGLE_STEP", &trap);
-			status &= ~0x01000000;
-			nv_wr32(dev, NV03_PGRAPH_INTR, 0x01000000);
-		}
-
-		/* 0x02000000 happens when you pause a ctxprog...
-		 * but the only way this can happen that I know is by
-		 * poking the relevant MMIO register, and we don't
-		 * do that. */
-
-		if (status) {
-			NV_INFO(dev, "Unhandled PGRAPH_INTR - 0x%08x\n",
-				status);
-			nv_wr32(dev, NV03_PGRAPH_INTR, status);
-		}
-
-		{
-			const int isb = (1 << 16) | (1 << 0);
-
-			if ((nv_rd32(dev, 0x400500) & isb) != isb)
-				nv_wr32(dev, 0x400500,
-					nv_rd32(dev, 0x400500) | isb);
-		}
-	}
-
-	nv_wr32(dev, NV03_PMC_INTR_0, NV_PMC_INTR_0_PGRAPH_PENDING);
-	if (nv_rd32(dev, 0x400824) & (1 << 31))
-		nv_wr32(dev, 0x400824, nv_rd32(dev, 0x400824) & ~(1 << 31));
+	drm_irq_uninstall(dev);
+	if (dev_priv->msi_enabled)
+		pci_disable_msi(dev->pdev);
 }
 
-static void
-nouveau_crtc_irq_handler(struct drm_device *dev, int crtc)
+void
+nouveau_irq_register(struct drm_device *dev, int status_bit,
+		     void (*handler)(struct drm_device *))
 {
-	if (crtc & 1)
-		nv_wr32(dev, NV_CRTC0_INTSTAT, NV_CRTC_INTR_VBLANK);
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	unsigned long flags;
 
-	if (crtc & 2)
-		nv_wr32(dev, NV_CRTC1_INTSTAT, NV_CRTC_INTR_VBLANK);
+	spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
+	dev_priv->irq_handler[status_bit] = handler;
+	spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
 }
 
-irqreturn_t
-nouveau_irq_handler(DRM_IRQ_ARGS)
+void
+nouveau_irq_unregister(struct drm_device *dev, int status_bit)
 {
-	struct drm_device *dev = (struct drm_device *)arg;
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	uint32_t status;
 	unsigned long flags;
 
-	status = nv_rd32(dev, NV03_PMC_INTR_0);
-	if (!status)
-		return IRQ_NONE;
-
 	spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
-
-	if (status & NV_PMC_INTR_0_PFIFO_PENDING) {
-		nouveau_fifo_irq_handler(dev);
-		status &= ~NV_PMC_INTR_0_PFIFO_PENDING;
-	}
-
-	if (status & NV_PMC_INTR_0_PGRAPH_PENDING) {
-		if (dev_priv->card_type >= NV_50)
-			nv50_pgraph_irq_handler(dev);
-		else
-			nouveau_pgraph_irq_handler(dev);
-
-		status &= ~NV_PMC_INTR_0_PGRAPH_PENDING;
-	}
-
-	if (status & NV_PMC_INTR_0_CRTCn_PENDING) {
-		nouveau_crtc_irq_handler(dev, (status>>24)&3);
-		status &= ~NV_PMC_INTR_0_CRTCn_PENDING;
-	}
-
-	if (status & (NV_PMC_INTR_0_NV50_DISPLAY_PENDING |
-		      NV_PMC_INTR_0_NV50_I2C_PENDING)) {
-		nv50_display_irq_handler(dev);
-		status &= ~(NV_PMC_INTR_0_NV50_DISPLAY_PENDING |
-			    NV_PMC_INTR_0_NV50_I2C_PENDING);
-	}
-
-	if (status)
-		NV_ERROR(dev, "Unhandled PMC INTR status bits 0x%08x\n", status);
-
+	dev_priv->irq_handler[status_bit] = NULL;
 	spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
-
-	return IRQ_HANDLED;
 }
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nouveau_mem.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nouveau_mem.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nouveau_mem.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nouveau_mem.c	2011-03-14 21:20:32.000000000 -0400
@@ -36,183 +36,112 @@
 
 #include "nouveau_drv.h"
 #include "nouveau_pm.h"
+#include "nouveau_mm.h"
+#include "nouveau_vm.h"
 
 /*
  * NV10-NV40 tiling helpers
  */
 
 static void
-nv10_mem_set_region_tiling(struct drm_device *dev, int i, uint32_t addr,
-			   uint32_t size, uint32_t pitch)
+nv10_mem_update_tile_region(struct drm_device *dev,
+			    struct nouveau_tile_reg *tile, uint32_t addr,
+			    uint32_t size, uint32_t pitch, uint32_t flags)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo;
 	struct nouveau_fb_engine *pfb = &dev_priv->engine.fb;
 	struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
-	struct nouveau_tile_reg *tile = &dev_priv->tile[i];
+	int i = tile - dev_priv->tile.reg;
+	unsigned long save;
 
-	tile->addr = addr;
-	tile->size = size;
-	tile->used = !!pitch;
-	nouveau_fence_unref((void **)&tile->fence);
+	nouveau_fence_unref(&tile->fence);
+
+	if (tile->pitch)
+		pfb->free_tile_region(dev, i);
+
+	if (pitch)
+		pfb->init_tile_region(dev, i, addr, size, pitch, flags);
 
+	spin_lock_irqsave(&dev_priv->context_switch_lock, save);
 	pfifo->reassign(dev, false);
 	pfifo->cache_pull(dev, false);
 
 	nouveau_wait_for_idle(dev);
 
-	pgraph->set_region_tiling(dev, i, addr, size, pitch);
-	pfb->set_region_tiling(dev, i, addr, size, pitch);
+	pfb->set_tile_region(dev, i);
+	pgraph->set_tile_region(dev, i);
 
 	pfifo->cache_pull(dev, true);
 	pfifo->reassign(dev, true);
+	spin_unlock_irqrestore(&dev_priv->context_switch_lock, save);
 }
 
-struct nouveau_tile_reg *
-nv10_mem_set_tiling(struct drm_device *dev, uint32_t addr, uint32_t size,
-		    uint32_t pitch)
+static struct nouveau_tile_reg *
+nv10_mem_get_tile_region(struct drm_device *dev, int i)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nouveau_fb_engine *pfb = &dev_priv->engine.fb;
-	struct nouveau_tile_reg *found = NULL;
-	unsigned long i, flags;
-
-	spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
-
-	for (i = 0; i < pfb->num_tiles; i++) {
-		struct nouveau_tile_reg *tile = &dev_priv->tile[i];
-
-		if (tile->used)
-			/* Tile region in use. */
-			continue;
-
-		if (tile->fence &&
-		    !nouveau_fence_signalled(tile->fence, NULL))
-			/* Pending tile region. */
-			continue;
-
-		if (max(tile->addr, addr) <
-		    min(tile->addr + tile->size, addr + size))
-			/* Kill an intersecting tile region. */
-			nv10_mem_set_region_tiling(dev, i, 0, 0, 0);
+	struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i];
 
-		if (pitch && !found) {
-			/* Free tile region. */
-			nv10_mem_set_region_tiling(dev, i, addr, size, pitch);
-			found = tile;
-		}
-	}
+	spin_lock(&dev_priv->tile.lock);
 
-	spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
+	if (!tile->used &&
+	    (!tile->fence || nouveau_fence_signalled(tile->fence)))
+		tile->used = true;
+	else
+		tile = NULL;
 
-	return found;
+	spin_unlock(&dev_priv->tile.lock);
+	return tile;
 }
 
 void
-nv10_mem_expire_tiling(struct drm_device *dev, struct nouveau_tile_reg *tile,
-		       struct nouveau_fence *fence)
-{
-	if (fence) {
-		/* Mark it as pending. */
-		tile->fence = fence;
-		nouveau_fence_ref(fence);
-	}
-
-	tile->used = false;
-}
-
-/*
- * NV50 VM helpers
- */
-int
-nv50_mem_vm_bind_linear(struct drm_device *dev, uint64_t virt, uint32_t size,
-			uint32_t flags, uint64_t phys)
+nv10_mem_put_tile_region(struct drm_device *dev, struct nouveau_tile_reg *tile,
+			 struct nouveau_fence *fence)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nouveau_gpuobj *pgt;
-	unsigned block;
-	int i;
-
-	virt = ((virt - dev_priv->vm_vram_base) >> 16) << 1;
-	size = (size >> 16) << 1;
-
-	phys |= ((uint64_t)flags << 32);
-	phys |= 1;
-	if (dev_priv->vram_sys_base) {
-		phys += dev_priv->vram_sys_base;
-		phys |= 0x30;
-	}
-
-	while (size) {
-		unsigned offset_h = upper_32_bits(phys);
-		unsigned offset_l = lower_32_bits(phys);
-		unsigned pte, end;
 
-		for (i = 7; i >= 0; i--) {
-			block = 1 << (i + 1);
-			if (size >= block && !(virt & (block - 1)))
-				break;
+	if (tile) {
+		spin_lock(&dev_priv->tile.lock);
+		if (fence) {
+			/* Mark it as pending. */
+			tile->fence = fence;
+			nouveau_fence_ref(fence);
 		}
-		offset_l |= (i << 7);
-
-		phys += block << 15;
-		size -= block;
 
-		while (block) {
-			pgt = dev_priv->vm_vram_pt[virt >> 14];
-			pte = virt & 0x3ffe;
-
-			end = pte + block;
-			if (end > 16384)
-				end = 16384;
-			block -= (end - pte);
-			virt  += (end - pte);
-
-			while (pte < end) {
-				nv_wo32(pgt, (pte * 4) + 0, offset_l);
-				nv_wo32(pgt, (pte * 4) + 4, offset_h);
-				pte += 2;
-			}
-		}
+		tile->used = false;
+		spin_unlock(&dev_priv->tile.lock);
 	}
-
-	dev_priv->engine.instmem.flush(dev);
-	dev_priv->engine.fifo.tlb_flush(dev);
-	dev_priv->engine.graph.tlb_flush(dev);
-	nv50_vm_flush(dev, 6);
-	return 0;
 }
 
-void
-nv50_mem_vm_unbind(struct drm_device *dev, uint64_t virt, uint32_t size)
+struct nouveau_tile_reg *
+nv10_mem_set_tiling(struct drm_device *dev, uint32_t addr, uint32_t size,
+		    uint32_t pitch, uint32_t flags)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nouveau_gpuobj *pgt;
-	unsigned pages, pte, end;
-
-	virt -= dev_priv->vm_vram_base;
-	pages = (size >> 16) << 1;
+	struct nouveau_fb_engine *pfb = &dev_priv->engine.fb;
+	struct nouveau_tile_reg *tile, *found = NULL;
+	int i;
 
-	while (pages) {
-		pgt = dev_priv->vm_vram_pt[virt >> 29];
-		pte = (virt & 0x1ffe0000ULL) >> 15;
+	for (i = 0; i < pfb->num_tiles; i++) {
+		tile = nv10_mem_get_tile_region(dev, i);
 
-		end = pte + pages;
-		if (end > 16384)
-			end = 16384;
-		pages -= (end - pte);
-		virt  += (end - pte) << 15;
+		if (pitch && !found) {
+			found = tile;
+			continue;
 
-		while (pte < end) {
-			nv_wo32(pgt, (pte * 4), 0);
-			pte++;
+		} else if (tile && tile->pitch) {
+			/* Kill an unused tile region. */
+			nv10_mem_update_tile_region(dev, tile, 0, 0, 0, 0);
 		}
+
+		nv10_mem_put_tile_region(dev, tile, NULL);
 	}
 
-	dev_priv->engine.instmem.flush(dev);
-	dev_priv->engine.fifo.tlb_flush(dev);
-	dev_priv->engine.graph.tlb_flush(dev);
-	nv50_vm_flush(dev, 6);
+	if (found)
+		nv10_mem_update_tile_region(dev, found, addr, size,
+					    pitch, flags);
+	return found;
 }
 
 /*
@@ -312,62 +241,7 @@ nouveau_mem_detect_nforce(struct drm_dev
 	return 0;
 }
 
-static void
-nv50_vram_preinit(struct drm_device *dev)
-{
-	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	int i, parts, colbits, rowbitsa, rowbitsb, banks;
-	u64 rowsize, predicted;
-	u32 r0, r4, rt, ru;
-
-	r0 = nv_rd32(dev, 0x100200);
-	r4 = nv_rd32(dev, 0x100204);
-	rt = nv_rd32(dev, 0x100250);
-	ru = nv_rd32(dev, 0x001540);
-	NV_DEBUG(dev, "memcfg 0x%08x 0x%08x 0x%08x 0x%08x\n", r0, r4, rt, ru);
-
-	for (i = 0, parts = 0; i < 8; i++) {
-		if (ru & (0x00010000 << i))
-			parts++;
-	}
-
-	colbits  =  (r4 & 0x0000f000) >> 12;
-	rowbitsa = ((r4 & 0x000f0000) >> 16) + 8;
-	rowbitsb = ((r4 & 0x00f00000) >> 20) + 8;
-	banks    = ((r4 & 0x01000000) ? 8 : 4);
-
-	rowsize = parts * banks * (1 << colbits) * 8;
-	predicted = rowsize << rowbitsa;
-	if (r0 & 0x00000004)
-		predicted += rowsize << rowbitsb;
-
-	if (predicted != dev_priv->vram_size) {
-		NV_WARN(dev, "memory controller reports %dMiB VRAM\n",
-			(u32)(dev_priv->vram_size >> 20));
-		NV_WARN(dev, "we calculated %dMiB VRAM\n",
-			(u32)(predicted >> 20));
-	}
-
-	dev_priv->vram_rblock_size = rowsize >> 12;
-	if (rt & 1)
-		dev_priv->vram_rblock_size *= 3;
-
-	NV_DEBUG(dev, "rblock %lld bytes\n",
-		 (u64)dev_priv->vram_rblock_size << 12);
-}
-
-static void
-nvaa_vram_preinit(struct drm_device *dev)
-{
-	struct drm_nouveau_private *dev_priv = dev->dev_private;
-
-	/* To our knowledge, there's no large scale reordering of pages
-	 * that occurs on IGP chipsets.
-	 */
-	dev_priv->vram_rblock_size = 1;
-}
-
-static int
+int
 nouveau_mem_detect(struct drm_device *dev)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
@@ -381,33 +255,6 @@ nouveau_mem_detect(struct drm_device *de
 	if (dev_priv->card_type < NV_50) {
 		dev_priv->vram_size  = nv_rd32(dev, NV04_PFB_FIFO_DATA);
 		dev_priv->vram_size &= NV10_PFB_FIFO_DATA_RAM_AMOUNT_MB_MASK;
-	} else
-	if (dev_priv->card_type < NV_C0) {
-		dev_priv->vram_size = nv_rd32(dev, NV04_PFB_FIFO_DATA);
-		dev_priv->vram_size |= (dev_priv->vram_size & 0xff) << 32;
-		dev_priv->vram_size &= 0xffffffff00ll;
-
-		switch (dev_priv->chipset) {
-		case 0xaa:
-		case 0xac:
-		case 0xaf:
-			dev_priv->vram_sys_base = nv_rd32(dev, 0x100e10);
-			dev_priv->vram_sys_base <<= 12;
-			nvaa_vram_preinit(dev);
-			break;
-		default:
-			nv50_vram_preinit(dev);
-			break;
-		}
-	} else {
-		dev_priv->vram_size  = nv_rd32(dev, 0x10f20c) << 20;
-		dev_priv->vram_size *= nv_rd32(dev, 0x121c74);
-	}
-
-	NV_INFO(dev, "Detected %dMiB VRAM\n", (int)(dev_priv->vram_size >> 20));
-	if (dev_priv->vram_sys_base) {
-		NV_INFO(dev, "Stolen system memory at: 0x%010llx\n",
-			dev_priv->vram_sys_base);
 	}
 
 	if (dev_priv->vram_size)
@@ -415,6 +262,15 @@ nouveau_mem_detect(struct drm_device *de
 	return -ENOMEM;
 }
 
+bool
+nouveau_mem_flags_valid(struct drm_device *dev, u32 tile_flags)
+{
+	if (!(tile_flags & NOUVEAU_GEM_TILE_LAYOUT_MASK))
+		return true;
+
+	return false;
+}
+
 #if __OS_HAS_AGP
 static unsigned long
 get_agp_mode(struct drm_device *dev, unsigned long mode)
@@ -547,10 +403,6 @@ nouveau_mem_vram_init(struct drm_device
 	if (ret)
 		return ret;
 
-	ret = nouveau_mem_detect(dev);
-	if (ret)
-		return ret;
-
 	dev_priv->fb_phys = pci_resource_start(dev->pdev, 1);
 
 	ret = nouveau_ttm_global_init(dev_priv);
@@ -566,13 +418,6 @@ nouveau_mem_vram_init(struct drm_device
 		return ret;
 	}
 
-	dev_priv->fb_available_size = dev_priv->vram_size;
-	dev_priv->fb_mappable_pages = dev_priv->fb_available_size;
-	if (dev_priv->fb_mappable_pages > pci_resource_len(dev->pdev, 1))
-		dev_priv->fb_mappable_pages =
-			pci_resource_len(dev->pdev, 1);
-	dev_priv->fb_mappable_pages >>= PAGE_SHIFT;
-
 	/* reserve space at end of VRAM for PRAMIN */
 	if (dev_priv->chipset == 0x40 || dev_priv->chipset == 0x47 ||
 	    dev_priv->chipset == 0x49 || dev_priv->chipset == 0x4b)
@@ -583,6 +428,22 @@ nouveau_mem_vram_init(struct drm_device
 	else
 		dev_priv->ramin_rsvd_vram = (512 * 1024);
 
+	ret = dev_priv->engine.vram.init(dev);
+	if (ret)
+		return ret;
+
+	NV_INFO(dev, "Detected %dMiB VRAM\n", (int)(dev_priv->vram_size >> 20));
+	if (dev_priv->vram_sys_base) {
+		NV_INFO(dev, "Stolen system memory at: 0x%010llx\n",
+			dev_priv->vram_sys_base);
+	}
+
+	dev_priv->fb_available_size = dev_priv->vram_size;
+	dev_priv->fb_mappable_pages = dev_priv->fb_available_size;
+	if (dev_priv->fb_mappable_pages > pci_resource_len(dev->pdev, 1))
+		dev_priv->fb_mappable_pages = pci_resource_len(dev->pdev, 1);
+	dev_priv->fb_mappable_pages >>= PAGE_SHIFT;
+
 	dev_priv->fb_available_size -= dev_priv->ramin_rsvd_vram;
 	dev_priv->fb_aper_free = dev_priv->fb_available_size;
 
@@ -799,3 +660,114 @@ nouveau_mem_timing_fini(struct drm_devic
 
 	kfree(mem->timing);
 }
+
+static int
+nouveau_vram_manager_init(struct ttm_mem_type_manager *man, unsigned long p_size)
+{
+	struct drm_nouveau_private *dev_priv = nouveau_bdev(man->bdev);
+	struct nouveau_mm *mm;
+	u32 b_size;
+	int ret;
+
+	p_size = (p_size << PAGE_SHIFT) >> 12;
+	b_size = dev_priv->vram_rblock_size >> 12;
+
+	ret = nouveau_mm_init(&mm, 0, p_size, b_size);
+	if (ret)
+		return ret;
+
+	man->priv = mm;
+	return 0;
+}
+
+static int
+nouveau_vram_manager_fini(struct ttm_mem_type_manager *man)
+{
+	struct nouveau_mm *mm = man->priv;
+	int ret;
+
+	ret = nouveau_mm_fini(&mm);
+	if (ret)
+		return ret;
+
+	man->priv = NULL;
+	return 0;
+}
+
+static void
+nouveau_vram_manager_del(struct ttm_mem_type_manager *man,
+			 struct ttm_mem_reg *mem)
+{
+	struct drm_nouveau_private *dev_priv = nouveau_bdev(man->bdev);
+	struct nouveau_vram_engine *vram = &dev_priv->engine.vram;
+	struct drm_device *dev = dev_priv->dev;
+
+	vram->put(dev, (struct nouveau_vram **)&mem->mm_node);
+}
+
+static int
+nouveau_vram_manager_new(struct ttm_mem_type_manager *man,
+			 struct ttm_buffer_object *bo,
+			 struct ttm_placement *placement,
+			 struct ttm_mem_reg *mem)
+{
+	struct drm_nouveau_private *dev_priv = nouveau_bdev(man->bdev);
+	struct nouveau_vram_engine *vram = &dev_priv->engine.vram;
+	struct drm_device *dev = dev_priv->dev;
+	struct nouveau_bo *nvbo = nouveau_bo(bo);
+	struct nouveau_vram *node;
+	u32 size_nc = 0;
+	int ret;
+
+	if (nvbo->tile_flags & NOUVEAU_GEM_TILE_NONCONTIG)
+		size_nc = 1 << nvbo->vma.node->type;
+
+	ret = vram->get(dev, mem->num_pages << PAGE_SHIFT,
+			mem->page_alignment << PAGE_SHIFT, size_nc,
+			(nvbo->tile_flags >> 8) & 0xff, &node);
+	if (ret) {
+		mem->mm_node = NULL;
+		return (ret == -ENOSPC) ? 0 : ret;
+	}
+
+	node->page_shift = 12;
+	if (nvbo->vma.node)
+		node->page_shift = nvbo->vma.node->type;
+
+	mem->mm_node = node;
+	mem->start   = node->offset >> PAGE_SHIFT;
+	return 0;
+}
+
+void
+nouveau_vram_manager_debug(struct ttm_mem_type_manager *man, const char *prefix)
+{
+	struct nouveau_mm *mm = man->priv;
+	struct nouveau_mm_node *r;
+	u32 total = 0, free = 0;
+
+	mutex_lock(&mm->mutex);
+	list_for_each_entry(r, &mm->nodes, nl_entry) {
+		printk(KERN_DEBUG "%s %d: 0x%010llx 0x%010llx\n",
+		       prefix, r->type, ((u64)r->offset << 12),
+		       (((u64)r->offset + r->length) << 12));
+
+		total += r->length;
+		if (!r->type)
+			free += r->length;
+	}
+	mutex_unlock(&mm->mutex);
+
+	printk(KERN_DEBUG "%s  total: 0x%010llx free: 0x%010llx\n",
+	       prefix, (u64)total << 12, (u64)free << 12);
+	printk(KERN_DEBUG "%s  block: 0x%08x\n",
+	       prefix, mm->block_size << 12);
+}
+
+const struct ttm_mem_type_manager_func nouveau_vram_manager = {
+	nouveau_vram_manager_init,
+	nouveau_vram_manager_fini,
+	nouveau_vram_manager_new,
+	nouveau_vram_manager_del,
+	nouveau_vram_manager_debug
+};
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nouveau_mm.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nouveau_mm.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nouveau_mm.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nouveau_mm.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,171 @@
+/*
+ * Copyright 2010 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_mm.h"
+
+static inline void
+region_put(struct nouveau_mm *rmm, struct nouveau_mm_node *a)
+{
+	list_del(&a->nl_entry);
+	list_del(&a->fl_entry);
+	kfree(a);
+}
+
+static struct nouveau_mm_node *
+region_split(struct nouveau_mm *rmm, struct nouveau_mm_node *a, u32 size)
+{
+	struct nouveau_mm_node *b;
+
+	if (a->length == size)
+		return a;
+
+	b = kmalloc(sizeof(*b), GFP_KERNEL);
+	if (unlikely(b == NULL))
+		return NULL;
+
+	b->offset = a->offset;
+	b->length = size;
+	b->type   = a->type;
+	a->offset += size;
+	a->length -= size;
+	list_add_tail(&b->nl_entry, &a->nl_entry);
+	if (b->type == 0)
+		list_add_tail(&b->fl_entry, &a->fl_entry);
+	return b;
+}
+
+#define node(root, dir) ((root)->nl_entry.dir == &rmm->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)
+{
+	struct nouveau_mm_node *prev = node(this, prev);
+	struct nouveau_mm_node *next = node(this, next);
+
+	list_add(&this->fl_entry, &rmm->free);
+	this->type = 0;
+
+	if (prev && prev->type == 0) {
+		prev->length += this->length;
+		region_put(rmm, this);
+		this = prev;
+	}
+
+	if (next && next->type == 0) {
+		next->offset  = this->offset;
+		next->length += this->length;
+		region_put(rmm, this);
+	}
+}
+
+int
+nouveau_mm_get(struct nouveau_mm *rmm, int type, u32 size, u32 size_nc,
+	       u32 align, struct nouveau_mm_node **pnode)
+{
+	struct nouveau_mm_node *prev, *this, *next;
+	u32 min = size_nc ? size_nc : size;
+	u32 align_mask = align - 1;
+	u32 splitoff;
+	u32 s, e;
+
+	list_for_each_entry(this, &rmm->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);
+
+		next = node(this, next);
+		if (next && next->type != type)
+			e = rounddown(e, rmm->block_size);
+
+		s  = (s + align_mask) & ~align_mask;
+		e &= ~align_mask;
+		if (s > e || e - s < min)
+			continue;
+
+		splitoff = s - this->offset;
+		if (splitoff && !region_split(rmm, this, splitoff))
+			return -ENOMEM;
+
+		this = region_split(rmm, this, min(size, e - s));
+		if (!this)
+			return -ENOMEM;
+
+		this->type = type;
+		list_del(&this->fl_entry);
+		*pnode = this;
+		return 0;
+	}
+
+	return -ENOSPC;
+}
+
+int
+nouveau_mm_init(struct nouveau_mm **prmm, u32 offset, u32 length, u32 block)
+{
+	struct nouveau_mm *rmm;
+	struct nouveau_mm_node *heap;
+
+	heap = kzalloc(sizeof(*heap), GFP_KERNEL);
+	if (!heap)
+		return -ENOMEM;
+	heap->offset = roundup(offset, block);
+	heap->length = rounddown(offset + length, block) - heap->offset;
+
+	rmm = kzalloc(sizeof(*rmm), GFP_KERNEL);
+	if (!rmm) {
+		kfree(heap);
+		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);
+
+	*prmm = rmm;
+	return 0;
+}
+
+int
+nouveau_mm_fini(struct nouveau_mm **prmm)
+{
+	struct nouveau_mm *rmm = *prmm;
+	struct nouveau_mm_node *heap =
+		list_first_entry(&rmm->nodes, struct nouveau_mm_node, nl_entry);
+
+	if (!list_is_singular(&rmm->nodes))
+		return -EBUSY;
+
+	kfree(heap);
+	kfree(rmm);
+	*prmm = NULL;
+	return 0;
+}
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nouveau_mm.h linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nouveau_mm.h
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nouveau_mm.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nouveau_mm.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2010 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
+ */
+
+#ifndef __NOUVEAU_REGION_H__
+#define __NOUVEAU_REGION_H__
+
+struct nouveau_mm_node {
+	struct list_head nl_entry;
+	struct list_head fl_entry;
+	struct list_head rl_entry;
+
+	u8  type;
+	u32 offset;
+	u32 length;
+};
+
+struct nouveau_mm {
+	struct list_head nodes;
+	struct list_head free;
+
+	struct mutex mutex;
+
+	u32 block_size;
+};
+
+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 **);
+void nouveau_mm_put(struct nouveau_mm *, struct nouveau_mm_node *);
+
+int  nv50_vram_init(struct drm_device *);
+int  nv50_vram_new(struct drm_device *, u64 size, u32 align, u32 size_nc,
+		    u32 memtype, struct nouveau_vram **);
+void nv50_vram_del(struct drm_device *, struct nouveau_vram **);
+bool nv50_vram_flags_valid(struct drm_device *, u32 tile_flags);
+
+int  nvc0_vram_init(struct drm_device *);
+int  nvc0_vram_new(struct drm_device *, u64 size, u32 align, u32 ncmin,
+		    u32 memtype, struct nouveau_vram **);
+bool nvc0_vram_flags_valid(struct drm_device *, u32 tile_flags);
+
+#endif
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nouveau_notifier.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nouveau_notifier.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nouveau_notifier.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nouveau_notifier.c	2011-03-14 21:20:32.000000000 -0400
@@ -96,48 +96,33 @@ nouveau_notifier_gpuobj_dtor(struct drm_
 
 int
 nouveau_notifier_alloc(struct nouveau_channel *chan, uint32_t handle,
-		       int size, uint32_t *b_offset)
+		       int size, uint32_t start, uint32_t end,
+		       uint32_t *b_offset)
 {
 	struct drm_device *dev = chan->dev;
-	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct nouveau_gpuobj *nobj = NULL;
 	struct drm_mm_node *mem;
 	uint32_t offset;
 	int target, ret;
 
-	mem = drm_mm_search_free(&chan->notifier_heap, size, 0, 0);
+	mem = drm_mm_search_free_in_range(&chan->notifier_heap, size, 0,
+					  start, end, 0);
 	if (mem)
-		mem = drm_mm_get_block(mem, size, 0);
+		mem = drm_mm_get_block_range(mem, size, 0, start, end);
 	if (!mem) {
 		NV_ERROR(dev, "Channel %d notifier block full\n", chan->id);
 		return -ENOMEM;
 	}
 
-	offset = chan->notifier_bo->bo.mem.start << PAGE_SHIFT;
-	if (chan->notifier_bo->bo.mem.mem_type == TTM_PL_VRAM) {
-		target = NV_DMA_TARGET_VIDMEM;
-	} else
-	if (chan->notifier_bo->bo.mem.mem_type == TTM_PL_TT) {
-		if (dev_priv->gart_info.type == NOUVEAU_GART_SGDMA &&
-		    dev_priv->card_type < NV_50) {
-			ret = nouveau_sgdma_get_page(dev, offset, &offset);
-			if (ret)
-				return ret;
-			target = NV_DMA_TARGET_PCI;
-		} else {
-			target = NV_DMA_TARGET_AGP;
-			if (dev_priv->card_type >= NV_50)
-				offset += dev_priv->vm_gart_base;
-		}
-	} else {
-		NV_ERROR(dev, "Bad DMA target, mem_type %d!\n",
-			 chan->notifier_bo->bo.mem.mem_type);
-		return -EINVAL;
-	}
+	if (chan->notifier_bo->bo.mem.mem_type == TTM_PL_VRAM)
+		target = NV_MEM_TARGET_VRAM;
+	else
+		target = NV_MEM_TARGET_GART;
+	offset  = chan->notifier_bo->bo.mem.start << PAGE_SHIFT;
 	offset += mem->start;
 
 	ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, offset,
-				     mem->size, NV_DMA_ACCESS_RW, target,
+				     mem->size, NV_MEM_ACCESS_RW, target,
 				     &nobj);
 	if (ret) {
 		drm_mm_put_block(mem);
@@ -181,15 +166,21 @@ int
 nouveau_ioctl_notifier_alloc(struct drm_device *dev, void *data,
 			     struct drm_file *file_priv)
 {
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct drm_nouveau_notifierobj_alloc *na = data;
 	struct nouveau_channel *chan;
 	int ret;
 
-	NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(na->channel, file_priv, chan);
+	/* completely unnecessary for these chipsets... */
+	if (unlikely(dev_priv->card_type >= NV_C0))
+		return -EINVAL;
 
-	ret = nouveau_notifier_alloc(chan, na->handle, na->size, &na->offset);
-	if (ret)
-		return ret;
+	chan = nouveau_channel_get(dev, file_priv, na->channel);
+	if (IS_ERR(chan))
+		return PTR_ERR(chan);
 
-	return 0;
+	ret = nouveau_notifier_alloc(chan, na->handle, na->size, 0, 0x1000,
+				     &na->offset);
+	nouveau_channel_put(&chan);
+	return ret;
 }
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nouveau_object.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nouveau_object.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nouveau_object.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nouveau_object.c	2011-03-14 21:20:32.000000000 -0400
@@ -35,6 +35,102 @@
 #include "nouveau_drv.h"
 #include "nouveau_drm.h"
 #include "nouveau_ramht.h"
+#include "nouveau_vm.h"
+
+struct nouveau_gpuobj_method {
+	struct list_head head;
+	u32 mthd;
+	int (*exec)(struct nouveau_channel *, u32 class, u32 mthd, u32 data);
+};
+
+struct nouveau_gpuobj_class {
+	struct list_head head;
+	struct list_head methods;
+	u32 id;
+	u32 engine;
+};
+
+int
+nouveau_gpuobj_class_new(struct drm_device *dev, u32 class, u32 engine)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_gpuobj_class *oc;
+
+	oc = kzalloc(sizeof(*oc), GFP_KERNEL);
+	if (!oc)
+		return -ENOMEM;
+
+	INIT_LIST_HEAD(&oc->methods);
+	oc->id = class;
+	oc->engine = engine;
+	list_add(&oc->head, &dev_priv->classes);
+	return 0;
+}
+
+int
+nouveau_gpuobj_mthd_new(struct drm_device *dev, u32 class, u32 mthd,
+			int (*exec)(struct nouveau_channel *, u32, u32, u32))
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_gpuobj_method *om;
+	struct nouveau_gpuobj_class *oc;
+
+	list_for_each_entry(oc, &dev_priv->classes, head) {
+		if (oc->id == class)
+			goto found;
+	}
+
+	return -EINVAL;
+
+found:
+	om = kzalloc(sizeof(*om), GFP_KERNEL);
+	if (!om)
+		return -ENOMEM;
+
+	om->mthd = mthd;
+	om->exec = exec;
+	list_add(&om->head, &oc->methods);
+	return 0;
+}
+
+int
+nouveau_gpuobj_mthd_call(struct nouveau_channel *chan,
+			 u32 class, u32 mthd, u32 data)
+{
+	struct drm_nouveau_private *dev_priv = chan->dev->dev_private;
+	struct nouveau_gpuobj_method *om;
+	struct nouveau_gpuobj_class *oc;
+
+	list_for_each_entry(oc, &dev_priv->classes, head) {
+		if (oc->id != class)
+			continue;
+
+		list_for_each_entry(om, &oc->methods, head) {
+			if (om->mthd == mthd)
+				return om->exec(chan, class, mthd, data);
+		}
+	}
+
+	return -ENOENT;
+}
+
+int
+nouveau_gpuobj_mthd_call2(struct drm_device *dev, int chid,
+			  u32 class, u32 mthd, u32 data)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_channel *chan = NULL;
+	unsigned long flags;
+	int ret = -EINVAL;
+
+	spin_lock_irqsave(&dev_priv->channels.lock, flags);
+	if (chid > 0 && chid < dev_priv->engine.fifo.channels)
+		chan = dev_priv->channels.ptr[chid];
+	if (chan)
+		ret = nouveau_gpuobj_mthd_call(chan, class, mthd, data);
+	spin_unlock_irqrestore(&dev_priv->channels.lock, flags);
+	return ret;
+}
 
 /* NVidia uses context objects to drive drawing operations.
 
@@ -73,17 +169,14 @@ nouveau_gpuobj_new(struct drm_device *de
 		   struct nouveau_gpuobj **gpuobj_ret)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nouveau_engine *engine = &dev_priv->engine;
+	struct nouveau_instmem_engine *instmem = &dev_priv->engine.instmem;
 	struct nouveau_gpuobj *gpuobj;
 	struct drm_mm_node *ramin = NULL;
-	int ret;
+	int ret, i;
 
 	NV_DEBUG(dev, "ch%d size=%u align=%d flags=0x%08x\n",
 		 chan ? chan->id : -1, size, align, flags);
 
-	if (!dev_priv || !gpuobj_ret || *gpuobj_ret != NULL)
-		return -EINVAL;
-
 	gpuobj = kzalloc(sizeof(*gpuobj), GFP_KERNEL);
 	if (!gpuobj)
 		return -ENOMEM;
@@ -98,88 +191,41 @@ nouveau_gpuobj_new(struct drm_device *de
 	spin_unlock(&dev_priv->ramin_lock);
 
 	if (chan) {
-		NV_DEBUG(dev, "channel heap\n");
-
 		ramin = drm_mm_search_free(&chan->ramin_heap, size, align, 0);
 		if (ramin)
 			ramin = drm_mm_get_block(ramin, size, align);
-
 		if (!ramin) {
 			nouveau_gpuobj_ref(NULL, &gpuobj);
 			return -ENOMEM;
 		}
-	} else {
-		NV_DEBUG(dev, "global heap\n");
-
-		/* allocate backing pages, sets vinst */
-		ret = engine->instmem.populate(dev, gpuobj, &size);
-		if (ret) {
-			nouveau_gpuobj_ref(NULL, &gpuobj);
-			return ret;
-		}
 
-		/* try and get aperture space */
-		do {
-			if (drm_mm_pre_get(&dev_priv->ramin_heap))
-				return -ENOMEM;
-
-			spin_lock(&dev_priv->ramin_lock);
-			ramin = drm_mm_search_free(&dev_priv->ramin_heap, size,
-						   align, 0);
-			if (ramin == NULL) {
-				spin_unlock(&dev_priv->ramin_lock);
-				nouveau_gpuobj_ref(NULL, &gpuobj);
-				return -ENOMEM;
-			}
-
-			ramin = drm_mm_get_block_atomic(ramin, size, align);
-			spin_unlock(&dev_priv->ramin_lock);
-		} while (ramin == NULL);
-
-		/* on nv50 it's ok to fail, we have a fallback path */
-		if (!ramin && dev_priv->card_type < NV_50) {
-			nouveau_gpuobj_ref(NULL, &gpuobj);
-			return -ENOMEM;
-		}
-	}
+		gpuobj->pinst = chan->ramin->pinst;
+		if (gpuobj->pinst != ~0)
+			gpuobj->pinst += ramin->start;
 
-	/* if we got a chunk of the aperture, map pages into it */
-	gpuobj->im_pramin = ramin;
-	if (!chan && gpuobj->im_pramin && dev_priv->ramin_available) {
-		ret = engine->instmem.bind(dev, gpuobj);
+		gpuobj->cinst = ramin->start;
+		gpuobj->vinst = ramin->start + chan->ramin->vinst;
+		gpuobj->node  = ramin;
+	} else {
+		ret = instmem->get(gpuobj, size, align);
 		if (ret) {
 			nouveau_gpuobj_ref(NULL, &gpuobj);
 			return ret;
 		}
-	}
-
-	/* calculate the various different addresses for the object */
-	if (chan) {
-		gpuobj->pinst = chan->ramin->pinst;
-		if (gpuobj->pinst != ~0)
-			gpuobj->pinst += gpuobj->im_pramin->start;
 
-		if (dev_priv->card_type < NV_50) {
-			gpuobj->cinst = gpuobj->pinst;
-		} else {
-			gpuobj->cinst = gpuobj->im_pramin->start;
-			gpuobj->vinst = gpuobj->im_pramin->start +
-					chan->ramin->vinst;
-		}
-	} else {
-		if (gpuobj->im_pramin)
-			gpuobj->pinst = gpuobj->im_pramin->start;
-		else
+		ret = -ENOSYS;
+		if (!(flags & NVOBJ_FLAG_DONT_MAP))
+			ret = instmem->map(gpuobj);
+		if (ret)
 			gpuobj->pinst = ~0;
-		gpuobj->cinst = 0xdeadbeef;
+
+		gpuobj->cinst = NVOBJ_CINST_GLOBAL;
 	}
 
 	if (gpuobj->flags & NVOBJ_FLAG_ZERO_ALLOC) {
-		int i;
-
 		for (i = 0; i < gpuobj->size; i += 4)
 			nv_wo32(gpuobj, i, 0);
-		engine->instmem.flush(dev);
+		instmem->flush(dev);
 	}
 
 
@@ -195,6 +241,7 @@ nouveau_gpuobj_init(struct drm_device *d
 	NV_DEBUG(dev, "\n");
 
 	INIT_LIST_HEAD(&dev_priv->gpuobj_list);
+	INIT_LIST_HEAD(&dev_priv->classes);
 	spin_lock_init(&dev_priv->ramin_lock);
 	dev_priv->ramin_base = ~0;
 
@@ -205,9 +252,20 @@ void
 nouveau_gpuobj_takedown(struct drm_device *dev)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_gpuobj_method *om, *tm;
+	struct nouveau_gpuobj_class *oc, *tc;
 
 	NV_DEBUG(dev, "\n");
 
+	list_for_each_entry_safe(oc, tc, &dev_priv->classes, head) {
+		list_for_each_entry_safe(om, tm, &oc->methods, head) {
+			list_del(&om->head);
+			kfree(om);
+		}
+		list_del(&oc->head);
+		kfree(oc);
+	}
+
 	BUG_ON(!list_empty(&dev_priv->gpuobj_list));
 }
 
@@ -219,26 +277,34 @@ nouveau_gpuobj_del(struct kref *ref)
 		container_of(ref, struct nouveau_gpuobj, refcount);
 	struct drm_device *dev = gpuobj->dev;
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nouveau_engine *engine = &dev_priv->engine;
+	struct nouveau_instmem_engine *instmem = &dev_priv->engine.instmem;
 	int i;
 
 	NV_DEBUG(dev, "gpuobj %p\n", gpuobj);
 
-	if (gpuobj->im_pramin && (gpuobj->flags & NVOBJ_FLAG_ZERO_FREE)) {
+	if (gpuobj->node && (gpuobj->flags & NVOBJ_FLAG_ZERO_FREE)) {
 		for (i = 0; i < gpuobj->size; i += 4)
 			nv_wo32(gpuobj, i, 0);
-		engine->instmem.flush(dev);
+		instmem->flush(dev);
 	}
 
 	if (gpuobj->dtor)
 		gpuobj->dtor(dev, gpuobj);
 
-	if (gpuobj->im_backing)
-		engine->instmem.clear(dev, gpuobj);
+	if (gpuobj->cinst == NVOBJ_CINST_GLOBAL) {
+		if (gpuobj->node) {
+			instmem->unmap(gpuobj);
+			instmem->put(gpuobj);
+		}
+	} else {
+		if (gpuobj->node) {
+			spin_lock(&dev_priv->ramin_lock);
+			drm_mm_put_block(gpuobj->node);
+			spin_unlock(&dev_priv->ramin_lock);
+		}
+	}
 
 	spin_lock(&dev_priv->ramin_lock);
-	if (gpuobj->im_pramin)
-		drm_mm_put_block(gpuobj->im_pramin);
 	list_del(&gpuobj->list);
 	spin_unlock(&dev_priv->ramin_lock);
 
@@ -278,7 +344,7 @@ nouveau_gpuobj_new_fake(struct drm_devic
 	kref_init(&gpuobj->refcount);
 	gpuobj->size  = size;
 	gpuobj->pinst = pinst;
-	gpuobj->cinst = 0xdeadbeef;
+	gpuobj->cinst = NVOBJ_CINST_GLOBAL;
 	gpuobj->vinst = vinst;
 
 	if (gpuobj->flags & NVOBJ_FLAG_ZERO_ALLOC) {
@@ -335,113 +401,150 @@ nouveau_gpuobj_class_instmem_size(struct
    The method below creates a DMA object in instance RAM and returns a handle
    to it that can be used to set up context objects.
 */
-int
-nouveau_gpuobj_dma_new(struct nouveau_channel *chan, int class,
-		       uint64_t offset, uint64_t size, int access,
-		       int target, struct nouveau_gpuobj **gpuobj)
+
+void
+nv50_gpuobj_dma_init(struct nouveau_gpuobj *obj, u32 offset, int class,
+		     u64 base, u64 size, int target, int access,
+		     u32 type, u32 comp)
 {
-	struct drm_device *dev = chan->dev;
-	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nouveau_instmem_engine *instmem = &dev_priv->engine.instmem;
-	int ret;
+	struct drm_nouveau_private *dev_priv = obj->dev->dev_private;
+	struct nouveau_instmem_engine *pinstmem = &dev_priv->engine.instmem;
+	u32 flags0;
 
-	NV_DEBUG(dev, "ch%d class=0x%04x offset=0x%llx size=0x%llx\n",
-		 chan->id, class, offset, size);
-	NV_DEBUG(dev, "access=%d target=%d\n", access, target);
+	flags0  = (comp << 29) | (type << 22) | class;
+	flags0 |= 0x00100000;
 
-	switch (target) {
-	case NV_DMA_TARGET_AGP:
-		offset += dev_priv->gart_info.aper_base;
-		break;
+	switch (access) {
+	case NV_MEM_ACCESS_RO: flags0 |= 0x00040000; break;
+	case NV_MEM_ACCESS_RW:
+	case NV_MEM_ACCESS_WO: flags0 |= 0x00080000; break;
 	default:
 		break;
 	}
 
-	ret = nouveau_gpuobj_new(dev, chan,
-				 nouveau_gpuobj_class_instmem_size(dev, class),
-				 16, NVOBJ_FLAG_ZERO_ALLOC |
-				 NVOBJ_FLAG_ZERO_FREE, gpuobj);
-	if (ret) {
-		NV_ERROR(dev, "Error creating gpuobj: %d\n", ret);
-		return ret;
+	switch (target) {
+	case NV_MEM_TARGET_VRAM:
+		flags0 |= 0x00010000;
+		break;
+	case NV_MEM_TARGET_PCI:
+		flags0 |= 0x00020000;
+		break;
+	case NV_MEM_TARGET_PCI_NOSNOOP:
+		flags0 |= 0x00030000;
+		break;
+	case NV_MEM_TARGET_GART:
+		base += dev_priv->gart_info.aper_base;
+	default:
+		flags0 &= ~0x00100000;
+		break;
 	}
 
-	if (dev_priv->card_type < NV_50) {
-		uint32_t frame, adjust, pte_flags = 0;
-
-		if (access != NV_DMA_ACCESS_RO)
-			pte_flags |= (1<<1);
-		adjust = offset &  0x00000fff;
-		frame  = offset & ~0x00000fff;
+	/* convert to base + limit */
+	size = (base + size) - 1;
 
-		nv_wo32(*gpuobj,  0, ((1<<12) | (1<<13) | (adjust << 20) |
-				      (access << 14) | (target << 16) |
-				      class));
-		nv_wo32(*gpuobj,  4, size - 1);
-		nv_wo32(*gpuobj,  8, frame | pte_flags);
-		nv_wo32(*gpuobj, 12, frame | pte_flags);
-	} else {
-		uint64_t limit = offset + size - 1;
-		uint32_t flags0, flags5;
+	nv_wo32(obj, offset + 0x00, flags0);
+	nv_wo32(obj, offset + 0x04, lower_32_bits(size));
+	nv_wo32(obj, offset + 0x08, lower_32_bits(base));
+	nv_wo32(obj, offset + 0x0c, upper_32_bits(size) << 24 |
+				    upper_32_bits(base));
+	nv_wo32(obj, offset + 0x10, 0x00000000);
+	nv_wo32(obj, offset + 0x14, 0x00000000);
 
-		if (target == NV_DMA_TARGET_VIDMEM) {
-			flags0 = 0x00190000;
-			flags5 = 0x00010000;
-		} else {
-			flags0 = 0x7fc00000;
-			flags5 = 0x00080000;
-		}
+	pinstmem->flush(obj->dev);
+}
 
-		nv_wo32(*gpuobj,  0, flags0 | class);
-		nv_wo32(*gpuobj,  4, lower_32_bits(limit));
-		nv_wo32(*gpuobj,  8, lower_32_bits(offset));
-		nv_wo32(*gpuobj, 12, ((upper_32_bits(limit) & 0xff) << 24) |
-				      (upper_32_bits(offset) & 0xff));
-		nv_wo32(*gpuobj, 20, flags5);
-	}
+int
+nv50_gpuobj_dma_new(struct nouveau_channel *chan, int class, u64 base, u64 size,
+		    int target, int access, u32 type, u32 comp,
+		    struct nouveau_gpuobj **pobj)
+{
+	struct drm_device *dev = chan->dev;
+	int ret;
 
-	instmem->flush(dev);
+	ret = nouveau_gpuobj_new(dev, chan, 24, 16, NVOBJ_FLAG_ZERO_FREE, pobj);
+	if (ret)
+		return ret;
 
-	(*gpuobj)->engine = NVOBJ_ENGINE_SW;
-	(*gpuobj)->class  = class;
+	nv50_gpuobj_dma_init(*pobj, 0, class, base, size, target,
+			     access, type, comp);
 	return 0;
 }
 
 int
-nouveau_gpuobj_gart_dma_new(struct nouveau_channel *chan,
-			    uint64_t offset, uint64_t size, int access,
-			    struct nouveau_gpuobj **gpuobj,
-			    uint32_t *o_ret)
+nouveau_gpuobj_dma_new(struct nouveau_channel *chan, int class, u64 base,
+		       u64 size, int access, int target,
+		       struct nouveau_gpuobj **pobj)
 {
+	struct drm_nouveau_private *dev_priv = chan->dev->dev_private;
 	struct drm_device *dev = chan->dev;
-	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_gpuobj *obj;
+	u32 flags0, flags2;
 	int ret;
 
-	if (dev_priv->gart_info.type == NOUVEAU_GART_AGP ||
-	    (dev_priv->card_type >= NV_50 &&
-	     dev_priv->gart_info.type == NOUVEAU_GART_SGDMA)) {
-		ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY,
-					     offset + dev_priv->vm_gart_base,
-					     size, access, NV_DMA_TARGET_AGP,
-					     gpuobj);
-		if (o_ret)
-			*o_ret = 0;
-	} else
-	if (dev_priv->gart_info.type == NOUVEAU_GART_SGDMA) {
-		nouveau_gpuobj_ref(dev_priv->gart_info.sg_ctxdma, gpuobj);
-		if (offset & ~0xffffffffULL) {
-			NV_ERROR(dev, "obj offset exceeds 32-bits\n");
-			return -EINVAL;
+	if (dev_priv->card_type >= NV_50) {
+		u32 comp = (target == NV_MEM_TARGET_VM) ? NV_MEM_COMP_VM : 0;
+		u32 type = (target == NV_MEM_TARGET_VM) ? NV_MEM_TYPE_VM : 0;
+
+		return nv50_gpuobj_dma_new(chan, class, base, size,
+					   target, access, type, comp, pobj);
+	}
+
+	if (target == NV_MEM_TARGET_GART) {
+		if (dev_priv->gart_info.type == NOUVEAU_GART_AGP) {
+			target = NV_MEM_TARGET_PCI_NOSNOOP;
+			base  += dev_priv->gart_info.aper_base;
+		} else
+		if (base != 0) {
+			base = nouveau_sgdma_get_physical(dev, base);
+			target = NV_MEM_TARGET_PCI;
+		} else {
+			nouveau_gpuobj_ref(dev_priv->gart_info.sg_ctxdma, pobj);
+			return 0;
 		}
-		if (o_ret)
-			*o_ret = (uint32_t)offset;
-		ret = (*gpuobj != NULL) ? 0 : -EINVAL;
-	} else {
-		NV_ERROR(dev, "Invalid GART type %d\n", dev_priv->gart_info.type);
-		return -EINVAL;
 	}
 
-	return ret;
+	flags0  = class;
+	flags0 |= 0x00003000; /* PT present, PT linear */
+	flags2  = 0;
+
+	switch (target) {
+	case NV_MEM_TARGET_PCI:
+		flags0 |= 0x00020000;
+		break;
+	case NV_MEM_TARGET_PCI_NOSNOOP:
+		flags0 |= 0x00030000;
+		break;
+	default:
+		break;
+	}
+
+	switch (access) {
+	case NV_MEM_ACCESS_RO:
+		flags0 |= 0x00004000;
+		break;
+	case NV_MEM_ACCESS_WO:
+		flags0 |= 0x00008000;
+	default:
+		flags2 |= 0x00000002;
+		break;
+	}
+
+	flags0 |= (base & 0x00000fff) << 20;
+	flags2 |= (base & 0xfffff000);
+
+	ret = nouveau_gpuobj_new(dev, chan, 16, 16, NVOBJ_FLAG_ZERO_FREE, &obj);
+	if (ret)
+		return ret;
+
+	nv_wo32(obj, 0x00, flags0);
+	nv_wo32(obj, 0x04, size - 1);
+	nv_wo32(obj, 0x08, flags2);
+	nv_wo32(obj, 0x0c, flags2);
+
+	obj->engine = NVOBJ_ENGINE_SW;
+	obj->class  = class;
+	*pobj = obj;
+	return 0;
 }
 
 /* Context objects in the instance RAM have the following structure.
@@ -495,82 +598,130 @@ nouveau_gpuobj_gart_dma_new(struct nouve
    entry[5]:
    set to 0?
 */
+static int
+nouveau_gpuobj_sw_new(struct nouveau_channel *chan, int class,
+		      struct nouveau_gpuobj **gpuobj_ret)
+{
+	struct drm_nouveau_private *dev_priv = chan->dev->dev_private;
+	struct nouveau_gpuobj *gpuobj;
+
+	gpuobj = kzalloc(sizeof(*gpuobj), GFP_KERNEL);
+	if (!gpuobj)
+		return -ENOMEM;
+	gpuobj->dev = chan->dev;
+	gpuobj->engine = NVOBJ_ENGINE_SW;
+	gpuobj->class = class;
+	kref_init(&gpuobj->refcount);
+	gpuobj->cinst = 0x40;
+
+	spin_lock(&dev_priv->ramin_lock);
+	list_add_tail(&gpuobj->list, &dev_priv->gpuobj_list);
+	spin_unlock(&dev_priv->ramin_lock);
+	*gpuobj_ret = gpuobj;
+	return 0;
+}
+
 int
-nouveau_gpuobj_gr_new(struct nouveau_channel *chan, int class,
-		      struct nouveau_gpuobj **gpuobj)
+nouveau_gpuobj_gr_new(struct nouveau_channel *chan, u32 handle, int class)
 {
+	struct drm_nouveau_private *dev_priv = chan->dev->dev_private;
 	struct drm_device *dev = chan->dev;
-	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_gpuobj_class *oc;
+	struct nouveau_gpuobj *gpuobj;
 	int ret;
 
 	NV_DEBUG(dev, "ch%d class=0x%04x\n", chan->id, class);
 
+	list_for_each_entry(oc, &dev_priv->classes, head) {
+		if (oc->id == class)
+			goto found;
+	}
+
+	NV_ERROR(dev, "illegal object class: 0x%x\n", class);
+	return -EINVAL;
+
+found:
+	switch (oc->engine) {
+	case NVOBJ_ENGINE_SW:
+		if (dev_priv->card_type < NV_C0) {
+			ret = nouveau_gpuobj_sw_new(chan, class, &gpuobj);
+			if (ret)
+				return ret;
+			goto insert;
+		}
+		break;
+	case NVOBJ_ENGINE_GR:
+		if ((dev_priv->card_type >= NV_20 && !chan->ramin_grctx) ||
+		    (dev_priv->card_type  < NV_20 && !chan->pgraph_ctx)) {
+			struct nouveau_pgraph_engine *pgraph =
+				&dev_priv->engine.graph;
+
+			ret = pgraph->create_context(chan);
+			if (ret)
+				return ret;
+		}
+		break;
+	case NVOBJ_ENGINE_CRYPT:
+		if (!chan->crypt_ctx) {
+			struct nouveau_crypt_engine *pcrypt =
+				&dev_priv->engine.crypt;
+
+			ret = pcrypt->create_context(chan);
+			if (ret)
+				return ret;
+		}
+		break;
+	}
+
+	/* we're done if this is fermi */
+	if (dev_priv->card_type >= NV_C0)
+		return 0;
+
 	ret = nouveau_gpuobj_new(dev, chan,
 				 nouveau_gpuobj_class_instmem_size(dev, class),
 				 16,
 				 NVOBJ_FLAG_ZERO_ALLOC | NVOBJ_FLAG_ZERO_FREE,
-				 gpuobj);
+				 &gpuobj);
 	if (ret) {
-		NV_ERROR(dev, "Error creating gpuobj: %d\n", ret);
+		NV_ERROR(dev, "error creating gpuobj: %d\n", ret);
 		return ret;
 	}
 
 	if (dev_priv->card_type >= NV_50) {
-		nv_wo32(*gpuobj,  0, class);
-		nv_wo32(*gpuobj, 20, 0x00010000);
+		nv_wo32(gpuobj,  0, class);
+		nv_wo32(gpuobj, 20, 0x00010000);
 	} else {
 		switch (class) {
 		case NV_CLASS_NULL:
-			nv_wo32(*gpuobj, 0, 0x00001030);
-			nv_wo32(*gpuobj, 4, 0xFFFFFFFF);
+			nv_wo32(gpuobj, 0, 0x00001030);
+			nv_wo32(gpuobj, 4, 0xFFFFFFFF);
 			break;
 		default:
 			if (dev_priv->card_type >= NV_40) {
-				nv_wo32(*gpuobj, 0, class);
+				nv_wo32(gpuobj, 0, class);
 #ifdef __BIG_ENDIAN
-				nv_wo32(*gpuobj, 8, 0x01000000);
+				nv_wo32(gpuobj, 8, 0x01000000);
 #endif
 			} else {
 #ifdef __BIG_ENDIAN
-				nv_wo32(*gpuobj, 0, class | 0x00080000);
+				nv_wo32(gpuobj, 0, class | 0x00080000);
 #else
-				nv_wo32(*gpuobj, 0, class);
+				nv_wo32(gpuobj, 0, class);
 #endif
 			}
 		}
 	}
 	dev_priv->engine.instmem.flush(dev);
 
-	(*gpuobj)->engine = NVOBJ_ENGINE_GR;
-	(*gpuobj)->class  = class;
-	return 0;
-}
-
-int
-nouveau_gpuobj_sw_new(struct nouveau_channel *chan, int class,
-		      struct nouveau_gpuobj **gpuobj_ret)
-{
-	struct drm_nouveau_private *dev_priv;
-	struct nouveau_gpuobj *gpuobj;
-
-	if (!chan || !gpuobj_ret || *gpuobj_ret != NULL)
-		return -EINVAL;
-	dev_priv = chan->dev->dev_private;
-
-	gpuobj = kzalloc(sizeof(*gpuobj), GFP_KERNEL);
-	if (!gpuobj)
-		return -ENOMEM;
-	gpuobj->dev = chan->dev;
-	gpuobj->engine = NVOBJ_ENGINE_SW;
-	gpuobj->class = class;
-	kref_init(&gpuobj->refcount);
-	gpuobj->cinst = 0x40;
+	gpuobj->engine = oc->engine;
+	gpuobj->class  = oc->id;
 
-	spin_lock(&dev_priv->ramin_lock);
-	list_add_tail(&gpuobj->list, &dev_priv->gpuobj_list);
-	spin_unlock(&dev_priv->ramin_lock);
-	*gpuobj_ret = gpuobj;
-	return 0;
+insert:
+	ret = nouveau_ramht_insert(chan, handle, gpuobj);
+	if (ret)
+		NV_ERROR(dev, "error adding gpuobj to RAMHT: %d\n", ret);
+	nouveau_gpuobj_ref(NULL, &gpuobj);
+	return ret;
 }
 
 static int
@@ -585,7 +736,7 @@ nouveau_gpuobj_channel_init_pramin(struc
 	NV_DEBUG(dev, "ch%d\n", chan->id);
 
 	/* Base amount for object storage (4KiB enough?) */
-	size = 0x1000;
+	size = 0x2000;
 	base = 0;
 
 	/* PGRAPH context */
@@ -624,12 +775,30 @@ nouveau_gpuobj_channel_init(struct nouve
 {
 	struct drm_device *dev = chan->dev;
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nouveau_instmem_engine *instmem = &dev_priv->engine.instmem;
 	struct nouveau_gpuobj *vram = NULL, *tt = NULL;
-	int ret, i;
+	int ret;
 
 	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) {
+		struct nouveau_vm *vm = dev_priv->chan_vm;
+		struct nouveau_vm_pgd *vpgd;
+
+		ret = nouveau_gpuobj_new(dev, NULL, 4096, 0x1000, 0,
+					 &chan->ramin);
+		if (ret)
+			return ret;
+
+		nouveau_vm_ref(vm, &chan->vm, NULL);
+
+		vpgd = list_first_entry(&vm->pgd_list, struct nouveau_vm_pgd, head);
+		nv_wo32(chan->ramin, 0x0200, lower_32_bits(vpgd->obj->vinst));
+		nv_wo32(chan->ramin, 0x0204, upper_32_bits(vpgd->obj->vinst));
+		nv_wo32(chan->ramin, 0x0208, 0xffffffff);
+		nv_wo32(chan->ramin, 0x020c, 0x000000ff);
+		return 0;
+	}
+
 	/* Allocate a chunk of memory for per-channel object storage */
 	ret = nouveau_gpuobj_channel_init_pramin(chan);
 	if (ret) {
@@ -639,14 +808,12 @@ nouveau_gpuobj_channel_init(struct nouve
 
 	/* NV50 VM
 	 *  - Allocate per-channel page-directory
-	 *  - Map GART and VRAM into the channel's address space at the
-	 *    locations determined during init.
+	 *  - Link with shared channel VM
 	 */
-	if (dev_priv->card_type >= NV_50) {
+	if (dev_priv->chan_vm) {
 		u32 pgd_offs = (dev_priv->chipset == 0x50) ? 0x1400 : 0x0200;
 		u64 vm_vinst = chan->ramin->vinst + pgd_offs;
 		u32 vm_pinst = chan->ramin->pinst;
-		u32 pde;
 
 		if (vm_pinst != ~0)
 			vm_pinst += pgd_offs;
@@ -655,29 +822,8 @@ nouveau_gpuobj_channel_init(struct nouve
 					      0, &chan->vm_pd);
 		if (ret)
 			return ret;
-		for (i = 0; i < 0x4000; i += 8) {
-			nv_wo32(chan->vm_pd, i + 0, 0x00000000);
-			nv_wo32(chan->vm_pd, i + 4, 0xdeadcafe);
-		}
-
-		nouveau_gpuobj_ref(dev_priv->gart_info.sg_ctxdma,
-				   &chan->vm_gart_pt);
-		pde = (dev_priv->vm_gart_base / (512*1024*1024)) * 8;
-		nv_wo32(chan->vm_pd, pde + 0, chan->vm_gart_pt->vinst | 3);
-		nv_wo32(chan->vm_pd, pde + 4, 0x00000000);
 
-		pde = (dev_priv->vm_vram_base / (512*1024*1024)) * 8;
-		for (i = 0; i < dev_priv->vm_vram_pt_nr; i++) {
-			nouveau_gpuobj_ref(dev_priv->vm_vram_pt[i],
-					   &chan->vm_vram_pt[i]);
-
-			nv_wo32(chan->vm_pd, pde + 0,
-				chan->vm_vram_pt[i]->vinst | 0x61);
-			nv_wo32(chan->vm_pd, pde + 4, 0x00000000);
-			pde += 8;
-		}
-
-		instmem->flush(dev);
+		nouveau_vm_ref(dev_priv->chan_vm, &chan->vm, chan->vm_pd);
 	}
 
 	/* RAMHT */
@@ -700,9 +846,8 @@ nouveau_gpuobj_channel_init(struct nouve
 	/* VRAM ctxdma */
 	if (dev_priv->card_type >= NV_50) {
 		ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY,
-					     0, dev_priv->vm_end,
-					     NV_DMA_ACCESS_RW,
-					     NV_DMA_TARGET_AGP, &vram);
+					     0, (1ULL << 40), NV_MEM_ACCESS_RW,
+					     NV_MEM_TARGET_VM, &vram);
 		if (ret) {
 			NV_ERROR(dev, "Error creating VRAM ctxdma: %d\n", ret);
 			return ret;
@@ -710,8 +855,8 @@ nouveau_gpuobj_channel_init(struct nouve
 	} else {
 		ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY,
 					     0, dev_priv->fb_available_size,
-					     NV_DMA_ACCESS_RW,
-					     NV_DMA_TARGET_VIDMEM, &vram);
+					     NV_MEM_ACCESS_RW,
+					     NV_MEM_TARGET_VRAM, &vram);
 		if (ret) {
 			NV_ERROR(dev, "Error creating VRAM ctxdma: %d\n", ret);
 			return ret;
@@ -728,21 +873,13 @@ nouveau_gpuobj_channel_init(struct nouve
 	/* TT memory ctxdma */
 	if (dev_priv->card_type >= NV_50) {
 		ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY,
-					     0, dev_priv->vm_end,
-					     NV_DMA_ACCESS_RW,
-					     NV_DMA_TARGET_AGP, &tt);
-		if (ret) {
-			NV_ERROR(dev, "Error creating VRAM ctxdma: %d\n", ret);
-			return ret;
-		}
-	} else
-	if (dev_priv->gart_info.type != NOUVEAU_GART_NONE) {
-		ret = nouveau_gpuobj_gart_dma_new(chan, 0,
-						  dev_priv->gart_info.aper_size,
-						  NV_DMA_ACCESS_RW, &tt, NULL);
+					     0, (1ULL << 40), NV_MEM_ACCESS_RW,
+					     NV_MEM_TARGET_VM, &tt);
 	} else {
-		NV_ERROR(dev, "Invalid GART type %d\n", dev_priv->gart_info.type);
-		ret = -EINVAL;
+		ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY,
+					     0, dev_priv->gart_info.aper_size,
+					     NV_MEM_ACCESS_RW,
+					     NV_MEM_TARGET_GART, &tt);
 	}
 
 	if (ret) {
@@ -763,21 +900,14 @@ nouveau_gpuobj_channel_init(struct nouve
 void
 nouveau_gpuobj_channel_takedown(struct nouveau_channel *chan)
 {
-	struct drm_nouveau_private *dev_priv = chan->dev->dev_private;
 	struct drm_device *dev = chan->dev;
-	int i;
 
 	NV_DEBUG(dev, "ch%d\n", chan->id);
 
-	if (!chan->ramht)
-		return;
-
 	nouveau_ramht_ref(NULL, &chan->ramht, chan);
 
+	nouveau_vm_ref(NULL, &chan->vm, chan->vm_pd);
 	nouveau_gpuobj_ref(NULL, &chan->vm_pd);
-	nouveau_gpuobj_ref(NULL, &chan->vm_gart_pt);
-	for (i = 0; i < dev_priv->vm_vram_pt_nr; i++)
-		nouveau_gpuobj_ref(NULL, &chan->vm_vram_pt[i]);
 
 	if (chan->ramin_heap.free_stack.next)
 		drm_mm_takedown(&chan->ramin_heap);
@@ -791,147 +921,91 @@ nouveau_gpuobj_suspend(struct drm_device
 	struct nouveau_gpuobj *gpuobj;
 	int i;
 
-	if (dev_priv->card_type < NV_50) {
-		dev_priv->susres.ramin_copy = vmalloc(dev_priv->ramin_rsvd_vram);
-		if (!dev_priv->susres.ramin_copy)
-			return -ENOMEM;
-
-		for (i = 0; i < dev_priv->ramin_rsvd_vram; i += 4)
-			dev_priv->susres.ramin_copy[i/4] = nv_ri32(dev, i);
-		return 0;
-	}
-
 	list_for_each_entry(gpuobj, &dev_priv->gpuobj_list, list) {
-		if (!gpuobj->im_backing)
+		if (gpuobj->cinst != NVOBJ_CINST_GLOBAL)
 			continue;
 
-		gpuobj->im_backing_suspend = vmalloc(gpuobj->size);
-		if (!gpuobj->im_backing_suspend) {
+		gpuobj->suspend = vmalloc(gpuobj->size);
+		if (!gpuobj->suspend) {
 			nouveau_gpuobj_resume(dev);
 			return -ENOMEM;
 		}
 
 		for (i = 0; i < gpuobj->size; i += 4)
-			gpuobj->im_backing_suspend[i/4] = nv_ro32(gpuobj, i);
+			gpuobj->suspend[i/4] = nv_ro32(gpuobj, i);
 	}
 
 	return 0;
 }
 
 void
-nouveau_gpuobj_suspend_cleanup(struct drm_device *dev)
-{
-	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nouveau_gpuobj *gpuobj;
-
-	if (dev_priv->card_type < NV_50) {
-		vfree(dev_priv->susres.ramin_copy);
-		dev_priv->susres.ramin_copy = NULL;
-		return;
-	}
-
-	list_for_each_entry(gpuobj, &dev_priv->gpuobj_list, list) {
-		if (!gpuobj->im_backing_suspend)
-			continue;
-
-		vfree(gpuobj->im_backing_suspend);
-		gpuobj->im_backing_suspend = NULL;
-	}
-}
-
-void
 nouveau_gpuobj_resume(struct drm_device *dev)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct nouveau_gpuobj *gpuobj;
 	int i;
 
-	if (dev_priv->card_type < NV_50) {
-		for (i = 0; i < dev_priv->ramin_rsvd_vram; i += 4)
-			nv_wi32(dev, i, dev_priv->susres.ramin_copy[i/4]);
-		nouveau_gpuobj_suspend_cleanup(dev);
-		return;
-	}
-
 	list_for_each_entry(gpuobj, &dev_priv->gpuobj_list, list) {
-		if (!gpuobj->im_backing_suspend)
+		if (!gpuobj->suspend)
 			continue;
 
 		for (i = 0; i < gpuobj->size; i += 4)
-			nv_wo32(gpuobj, i, gpuobj->im_backing_suspend[i/4]);
-		dev_priv->engine.instmem.flush(dev);
+			nv_wo32(gpuobj, i, gpuobj->suspend[i/4]);
+
+		vfree(gpuobj->suspend);
+		gpuobj->suspend = NULL;
 	}
 
-	nouveau_gpuobj_suspend_cleanup(dev);
+	dev_priv->engine.instmem.flush(dev);
 }
 
 int nouveau_ioctl_grobj_alloc(struct drm_device *dev, void *data,
 			      struct drm_file *file_priv)
 {
-	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct drm_nouveau_grobj_alloc *init = data;
-	struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
-	struct nouveau_pgraph_object_class *grc;
-	struct nouveau_gpuobj *gr = NULL;
 	struct nouveau_channel *chan;
 	int ret;
 
-	NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(init->channel, file_priv, chan);
-
 	if (init->handle == ~0)
 		return -EINVAL;
 
-	grc = pgraph->grclass;
-	while (grc->id) {
-		if (grc->id == init->class)
-			break;
-		grc++;
-	}
+	chan = nouveau_channel_get(dev, file_priv, init->channel);
+	if (IS_ERR(chan))
+		return PTR_ERR(chan);
 
-	if (!grc->id) {
-		NV_ERROR(dev, "Illegal object class: 0x%x\n", init->class);
-		return -EPERM;
+	if (nouveau_ramht_find(chan, init->handle)) {
+		ret = -EEXIST;
+		goto out;
 	}
 
-	if (nouveau_ramht_find(chan, init->handle))
-		return -EEXIST;
-
-	if (!grc->software)
-		ret = nouveau_gpuobj_gr_new(chan, grc->id, &gr);
-	else
-		ret = nouveau_gpuobj_sw_new(chan, grc->id, &gr);
+	ret = nouveau_gpuobj_gr_new(chan, init->handle, init->class);
 	if (ret) {
 		NV_ERROR(dev, "Error creating object: %d (%d/0x%08x)\n",
 			 ret, init->channel, init->handle);
-		return ret;
 	}
 
-	ret = nouveau_ramht_insert(chan, init->handle, gr);
-	nouveau_gpuobj_ref(NULL, &gr);
-	if (ret) {
-		NV_ERROR(dev, "Error referencing object: %d (%d/0x%08x)\n",
-			 ret, init->channel, init->handle);
-		return ret;
-	}
-
-	return 0;
+out:
+	nouveau_channel_put(&chan);
+	return ret;
 }
 
 int nouveau_ioctl_gpuobj_free(struct drm_device *dev, void *data,
 			      struct drm_file *file_priv)
 {
 	struct drm_nouveau_gpuobj_free *objfree = data;
-	struct nouveau_gpuobj *gpuobj;
 	struct nouveau_channel *chan;
+	int ret;
 
-	NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(objfree->channel, file_priv, chan);
+	chan = nouveau_channel_get(dev, file_priv, objfree->channel);
+	if (IS_ERR(chan))
+		return PTR_ERR(chan);
 
-	gpuobj = nouveau_ramht_find(chan, objfree->handle);
-	if (!gpuobj)
-		return -ENOENT;
+	/* Synchronize with the user channel */
+	nouveau_channel_idle(chan);
 
-	nouveau_ramht_remove(chan, objfree->handle);
-	return 0;
+	ret = nouveau_ramht_remove(chan, objfree->handle);
+	nouveau_channel_put(&chan);
+	return ret;
 }
 
 u32
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nouveau_pm.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nouveau_pm.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nouveau_pm.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nouveau_pm.c	2011-03-14 21:20:32.000000000 -0400
@@ -27,6 +27,10 @@
 #include "nouveau_drv.h"
 #include "nouveau_pm.h"
 
+#ifdef CONFIG_ACPI
+#include <linux/acpi.h>
+#endif
+#include <linux/power_supply.h>
 #include <linux/hwmon.h>
 #include <linux/hwmon-sysfs.h>
 
@@ -418,8 +422,7 @@ nouveau_hwmon_init(struct drm_device *de
 		return ret;
 	}
 	dev_set_drvdata(hwmon_dev, dev);
-	ret = sysfs_create_group(&hwmon_dev->kobj,
-					&hwmon_attrgroup);
+	ret = sysfs_create_group(&dev->pdev->dev.kobj, &hwmon_attrgroup);
 	if (ret) {
 		NV_ERROR(dev,
 			"Unable to create hwmon sysfs file: %d\n", ret);
@@ -440,12 +443,31 @@ nouveau_hwmon_fini(struct drm_device *de
 	struct nouveau_pm_engine *pm = &dev_priv->engine.pm;
 
 	if (pm->hwmon) {
-		sysfs_remove_group(&pm->hwmon->kobj, &hwmon_attrgroup);
+		sysfs_remove_group(&dev->pdev->dev.kobj, &hwmon_attrgroup);
 		hwmon_device_unregister(pm->hwmon);
 	}
 #endif
 }
 
+#ifdef CONFIG_ACPI
+static int
+nouveau_pm_acpi_event(struct notifier_block *nb, unsigned long val, void *data)
+{
+	struct drm_nouveau_private *dev_priv =
+		container_of(nb, struct drm_nouveau_private, engine.pm.acpi_nb);
+	struct drm_device *dev = dev_priv->dev;
+	struct acpi_bus_event *entry = (struct acpi_bus_event *)data;
+
+	if (strcmp(entry->device_class, "ac_adapter") == 0) {
+		bool ac = power_supply_is_system_supplied();
+
+		NV_DEBUG(dev, "power supply changed: %s\n", ac ? "AC" : "DC");
+	}
+
+	return NOTIFY_OK;
+}
+#endif
+
 int
 nouveau_pm_init(struct drm_device *dev)
 {
@@ -485,6 +507,10 @@ nouveau_pm_init(struct drm_device *dev)
 
 	nouveau_sysfs_init(dev);
 	nouveau_hwmon_init(dev);
+#ifdef CONFIG_ACPI
+	pm->acpi_nb.notifier_call = nouveau_pm_acpi_event;
+	register_acpi_notifier(&pm->acpi_nb);
+#endif
 
 	return 0;
 }
@@ -503,6 +529,9 @@ nouveau_pm_fini(struct drm_device *dev)
 	nouveau_perf_fini(dev);
 	nouveau_volt_fini(dev);
 
+#ifdef CONFIG_ACPI
+	unregister_acpi_notifier(&pm->acpi_nb);
+#endif
 	nouveau_hwmon_fini(dev);
 	nouveau_sysfs_fini(dev);
 }
@@ -514,7 +543,7 @@ nouveau_pm_resume(struct drm_device *dev
 	struct nouveau_pm_engine *pm = &dev_priv->engine.pm;
 	struct nouveau_pm_level *perflvl;
 
-	if (pm->cur == &pm->boot)
+	if (!pm->cur || pm->cur == &pm->boot)
 		return;
 
 	perflvl = pm->cur;
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nouveau_ramht.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nouveau_ramht.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nouveau_ramht.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nouveau_ramht.c	2011-03-14 21:20:32.000000000 -0400
@@ -104,17 +104,17 @@ nouveau_ramht_insert(struct nouveau_chan
 	nouveau_gpuobj_ref(gpuobj, &entry->gpuobj);
 
 	if (dev_priv->card_type < NV_40) {
-		ctx = NV_RAMHT_CONTEXT_VALID | (gpuobj->cinst >> 4) |
+		ctx = NV_RAMHT_CONTEXT_VALID | (gpuobj->pinst >> 4) |
 		      (chan->id << NV_RAMHT_CONTEXT_CHANNEL_SHIFT) |
 		      (gpuobj->engine << NV_RAMHT_CONTEXT_ENGINE_SHIFT);
 	} else
 	if (dev_priv->card_type < NV_50) {
-		ctx = (gpuobj->cinst >> 4) |
+		ctx = (gpuobj->pinst >> 4) |
 		      (chan->id << NV40_RAMHT_CONTEXT_CHANNEL_SHIFT) |
 		      (gpuobj->engine << NV40_RAMHT_CONTEXT_ENGINE_SHIFT);
 	} else {
 		if (gpuobj->engine == NVOBJ_ENGINE_DISPLAY) {
-			ctx = (gpuobj->cinst << 10) | 2;
+			ctx = (gpuobj->cinst << 10) | chan->id;
 		} else {
 			ctx = (gpuobj->cinst >> 4) |
 			      ((gpuobj->engine <<
@@ -214,18 +214,19 @@ out:
 	spin_unlock_irqrestore(&chan->ramht->lock, flags);
 }
 
-void
+int
 nouveau_ramht_remove(struct nouveau_channel *chan, u32 handle)
 {
 	struct nouveau_ramht_entry *entry;
 
 	entry = nouveau_ramht_remove_entry(chan, handle);
 	if (!entry)
-		return;
+		return -ENOENT;
 
 	nouveau_ramht_remove_hash(chan, entry->handle);
 	nouveau_gpuobj_ref(NULL, &entry->gpuobj);
 	kfree(entry);
+	return 0;
 }
 
 struct nouveau_gpuobj *
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nouveau_ramht.h linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nouveau_ramht.h
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nouveau_ramht.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nouveau_ramht.h	2011-03-14 21:20:32.000000000 -0400
@@ -48,7 +48,7 @@ extern void nouveau_ramht_ref(struct nou
 
 extern int  nouveau_ramht_insert(struct nouveau_channel *, u32 handle,
 				 struct nouveau_gpuobj *);
-extern void nouveau_ramht_remove(struct nouveau_channel *, u32 handle);
+extern int  nouveau_ramht_remove(struct nouveau_channel *, u32 handle);
 extern struct nouveau_gpuobj *
 nouveau_ramht_find(struct nouveau_channel *chan, u32 handle);
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nouveau_reg.h linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nouveau_reg.h
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nouveau_reg.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nouveau_reg.h	2011-03-14 21:20:32.000000000 -0400
@@ -45,6 +45,11 @@
 #	define NV04_PFB_REF_CMD_REFRESH				(1 << 0)
 #define NV04_PFB_PRE						0x001002d4
 #	define NV04_PFB_PRE_CMD_PRECHARGE			(1 << 0)
+#define NV20_PFB_ZCOMP(i)                              (0x00100300 + 4*(i))
+#	define NV20_PFB_ZCOMP_MODE_32				(4 << 24)
+#	define NV20_PFB_ZCOMP_EN				(1 << 31)
+#	define NV25_PFB_ZCOMP_MODE_16				(1 << 20)
+#	define NV25_PFB_ZCOMP_MODE_32				(2 << 20)
 #define NV10_PFB_CLOSE_PAGE2					0x0010033c
 #define NV04_PFB_SCRAMBLE(i)                         (0x00100400 + 4 * (i))
 #define NV40_PFB_TILE(i)                              (0x00100600 + (i*16))
@@ -74,17 +79,6 @@
 #    define NV40_RAMHT_CONTEXT_ENGINE_SHIFT                20
 #    define NV40_RAMHT_CONTEXT_INSTANCE_SHIFT              0
 
-/* DMA object defines */
-#define NV_DMA_ACCESS_RW 0
-#define NV_DMA_ACCESS_RO 1
-#define NV_DMA_ACCESS_WO 2
-#define NV_DMA_TARGET_VIDMEM 0
-#define NV_DMA_TARGET_PCI    2
-#define NV_DMA_TARGET_AGP    3
-/* The following is not a real value used by the card, it's changed by
- * nouveau_object_dma_create */
-#define NV_DMA_TARGET_PCI_NONLINEAR 8
-
 /* Some object classes we care about in the drm */
 #define NV_CLASS_DMA_FROM_MEMORY                           0x00000002
 #define NV_CLASS_DMA_TO_MEMORY                             0x00000003
@@ -332,6 +326,7 @@
 #define NV04_PGRAPH_BSWIZZLE5                              0x004006A0
 #define NV03_PGRAPH_STATUS                                 0x004006B0
 #define NV04_PGRAPH_STATUS                                 0x00400700
+#    define NV40_PGRAPH_STATUS_SYNC_STALL                  0x00004000
 #define NV04_PGRAPH_TRAPPED_ADDR                           0x00400704
 #define NV04_PGRAPH_TRAPPED_DATA                           0x00400708
 #define NV04_PGRAPH_SURFACE                                0x0040070C
@@ -378,6 +373,7 @@
 #define NV20_PGRAPH_TLIMIT(i)                              (0x00400904 + (i*16))
 #define NV20_PGRAPH_TSIZE(i)                               (0x00400908 + (i*16))
 #define NV20_PGRAPH_TSTATUS(i)                             (0x0040090C + (i*16))
+#define NV20_PGRAPH_ZCOMP(i)                               (0x00400980 + 4*(i))
 #define NV10_PGRAPH_TILE(i)                                (0x00400B00 + (i*16))
 #define NV10_PGRAPH_TLIMIT(i)                              (0x00400B04 + (i*16))
 #define NV10_PGRAPH_TSIZE(i)                               (0x00400B08 + (i*16))
@@ -714,31 +710,32 @@
 #define NV50_PDISPLAY_INTR_1_CLK_UNK10                               0x00000010
 #define NV50_PDISPLAY_INTR_1_CLK_UNK20                               0x00000020
 #define NV50_PDISPLAY_INTR_1_CLK_UNK40                               0x00000040
-#define NV50_PDISPLAY_INTR_EN                                        0x0061002c
-#define NV50_PDISPLAY_INTR_EN_VBLANK_CRTC                            0x0000000c
-#define NV50_PDISPLAY_INTR_EN_VBLANK_CRTC_(n)                   (1 << ((n) + 2))
-#define NV50_PDISPLAY_INTR_EN_VBLANK_CRTC_0                          0x00000004
-#define NV50_PDISPLAY_INTR_EN_VBLANK_CRTC_1                          0x00000008
-#define NV50_PDISPLAY_INTR_EN_CLK_UNK10                              0x00000010
-#define NV50_PDISPLAY_INTR_EN_CLK_UNK20                              0x00000020
-#define NV50_PDISPLAY_INTR_EN_CLK_UNK40                              0x00000040
+#define NV50_PDISPLAY_INTR_EN_0                                      0x00610028
+#define NV50_PDISPLAY_INTR_EN_1                                      0x0061002c
+#define NV50_PDISPLAY_INTR_EN_1_VBLANK_CRTC                          0x0000000c
+#define NV50_PDISPLAY_INTR_EN_1_VBLANK_CRTC_(n)                 (1 << ((n) + 2))
+#define NV50_PDISPLAY_INTR_EN_1_VBLANK_CRTC_0                        0x00000004
+#define NV50_PDISPLAY_INTR_EN_1_VBLANK_CRTC_1                        0x00000008
+#define NV50_PDISPLAY_INTR_EN_1_CLK_UNK10                            0x00000010
+#define NV50_PDISPLAY_INTR_EN_1_CLK_UNK20                            0x00000020
+#define NV50_PDISPLAY_INTR_EN_1_CLK_UNK40                            0x00000040
 #define NV50_PDISPLAY_UNK30_CTRL                                     0x00610030
 #define NV50_PDISPLAY_UNK30_CTRL_UPDATE_VCLK0                        0x00000200
 #define NV50_PDISPLAY_UNK30_CTRL_UPDATE_VCLK1                        0x00000400
 #define NV50_PDISPLAY_UNK30_CTRL_PENDING                             0x80000000
-#define NV50_PDISPLAY_TRAPPED_ADDR                                   0x00610080
-#define NV50_PDISPLAY_TRAPPED_DATA                                   0x00610084
-#define NV50_PDISPLAY_CHANNEL_STAT(i)                  ((i) * 0x10 + 0x00610200)
-#define NV50_PDISPLAY_CHANNEL_STAT_DMA                               0x00000010
-#define NV50_PDISPLAY_CHANNEL_STAT_DMA_DISABLED                      0x00000000
-#define NV50_PDISPLAY_CHANNEL_STAT_DMA_ENABLED                       0x00000010
-#define NV50_PDISPLAY_CHANNEL_DMA_CB(i)                ((i) * 0x10 + 0x00610204)
-#define NV50_PDISPLAY_CHANNEL_DMA_CB_LOCATION                        0x00000002
-#define NV50_PDISPLAY_CHANNEL_DMA_CB_LOCATION_VRAM                   0x00000000
-#define NV50_PDISPLAY_CHANNEL_DMA_CB_LOCATION_SYSTEM                 0x00000002
-#define NV50_PDISPLAY_CHANNEL_DMA_CB_VALID                           0x00000001
-#define NV50_PDISPLAY_CHANNEL_UNK2(i)                  ((i) * 0x10 + 0x00610208)
-#define NV50_PDISPLAY_CHANNEL_UNK3(i)                  ((i) * 0x10 + 0x0061020c)
+#define NV50_PDISPLAY_TRAPPED_ADDR(i)                  ((i) * 0x08 + 0x00610080)
+#define NV50_PDISPLAY_TRAPPED_DATA(i)                  ((i) * 0x08 + 0x00610084)
+#define NV50_PDISPLAY_EVO_CTRL(i)                      ((i) * 0x10 + 0x00610200)
+#define NV50_PDISPLAY_EVO_CTRL_DMA                                   0x00000010
+#define NV50_PDISPLAY_EVO_CTRL_DMA_DISABLED                          0x00000000
+#define NV50_PDISPLAY_EVO_CTRL_DMA_ENABLED                           0x00000010
+#define NV50_PDISPLAY_EVO_DMA_CB(i)                    ((i) * 0x10 + 0x00610204)
+#define NV50_PDISPLAY_EVO_DMA_CB_LOCATION                            0x00000002
+#define NV50_PDISPLAY_EVO_DMA_CB_LOCATION_VRAM                       0x00000000
+#define NV50_PDISPLAY_EVO_DMA_CB_LOCATION_SYSTEM                     0x00000002
+#define NV50_PDISPLAY_EVO_DMA_CB_VALID                               0x00000001
+#define NV50_PDISPLAY_EVO_UNK2(i)                      ((i) * 0x10 + 0x00610208)
+#define NV50_PDISPLAY_EVO_HASH_TAG(i)                  ((i) * 0x10 + 0x0061020c)
 
 #define NV50_PDISPLAY_CURSOR                                         0x00610270
 #define NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i)           ((i) * 0x10 + 0x00610270)
@@ -746,15 +743,11 @@
 #define NV50_PDISPLAY_CURSOR_CURSOR_CTRL2_STATUS                     0x00030000
 #define NV50_PDISPLAY_CURSOR_CURSOR_CTRL2_STATUS_ACTIVE              0x00010000
 
-#define NV50_PDISPLAY_CTRL_STATE                                     0x00610300
-#define NV50_PDISPLAY_CTRL_STATE_PENDING                             0x80000000
-#define NV50_PDISPLAY_CTRL_STATE_METHOD                              0x00001ffc
-#define NV50_PDISPLAY_CTRL_STATE_ENABLE                              0x00000001
-#define NV50_PDISPLAY_CTRL_VAL                                       0x00610304
-#define NV50_PDISPLAY_UNK_380                                        0x00610380
-#define NV50_PDISPLAY_RAM_AMOUNT                                     0x00610384
-#define NV50_PDISPLAY_UNK_388                                        0x00610388
-#define NV50_PDISPLAY_UNK_38C                                        0x0061038c
+#define NV50_PDISPLAY_PIO_CTRL                                       0x00610300
+#define NV50_PDISPLAY_PIO_CTRL_PENDING                               0x80000000
+#define NV50_PDISPLAY_PIO_CTRL_MTHD                                  0x00001ffc
+#define NV50_PDISPLAY_PIO_CTRL_ENABLED                               0x00000001
+#define NV50_PDISPLAY_PIO_DATA                                       0x00610304
 
 #define NV50_PDISPLAY_CRTC_P(i, r)        ((i) * 0x540 + NV50_PDISPLAY_CRTC_##r)
 #define NV50_PDISPLAY_CRTC_C(i, r)    (4 + (i) * 0x540 + NV50_PDISPLAY_CRTC_##r)
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nouveau_sgdma.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nouveau_sgdma.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nouveau_sgdma.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nouveau_sgdma.c	2011-03-14 21:20:32.000000000 -0400
@@ -14,7 +14,7 @@ struct nouveau_sgdma_be {
 	dma_addr_t *pages;
 	unsigned nr_pages;
 
-	unsigned pte_start;
+	u64 offset;
 	bool bound;
 };
 
@@ -74,18 +74,6 @@ nouveau_sgdma_clear(struct ttm_backend *
 	}
 }
 
-static inline unsigned
-nouveau_sgdma_pte(struct drm_device *dev, uint64_t offset)
-{
-	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	unsigned pte = (offset >> NV_CTXDMA_PAGE_SHIFT);
-
-	if (dev_priv->card_type < NV_50)
-		return pte + 2;
-
-	return pte << 1;
-}
-
 static int
 nouveau_sgdma_bind(struct ttm_backend *be, struct ttm_mem_reg *mem)
 {
@@ -97,32 +85,17 @@ nouveau_sgdma_bind(struct ttm_backend *b
 
 	NV_DEBUG(dev, "pg=0x%lx\n", mem->start);
 
-	pte = nouveau_sgdma_pte(nvbe->dev, mem->start << PAGE_SHIFT);
-	nvbe->pte_start = pte;
+	nvbe->offset = mem->start << PAGE_SHIFT;
+	pte = (nvbe->offset >> NV_CTXDMA_PAGE_SHIFT) + 2;
 	for (i = 0; i < nvbe->nr_pages; i++) {
 		dma_addr_t dma_offset = nvbe->pages[i];
 		uint32_t offset_l = lower_32_bits(dma_offset);
-		uint32_t offset_h = upper_32_bits(dma_offset);
-
-		for (j = 0; j < PAGE_SIZE / NV_CTXDMA_PAGE_SIZE; j++) {
-			if (dev_priv->card_type < NV_50) {
-				nv_wo32(gpuobj, (pte * 4) + 0, offset_l | 3);
-				pte += 1;
-			} else {
-				nv_wo32(gpuobj, (pte * 4) + 0, offset_l | 0x21);
-				nv_wo32(gpuobj, (pte * 4) + 4, offset_h & 0xff);
-				pte += 2;
-			}
 
+		for (j = 0; j < PAGE_SIZE / NV_CTXDMA_PAGE_SIZE; j++, pte++) {
+			nv_wo32(gpuobj, (pte * 4) + 0, offset_l | 3);
 			dma_offset += NV_CTXDMA_PAGE_SIZE;
 		}
 	}
-	dev_priv->engine.instmem.flush(nvbe->dev);
-
-	if (dev_priv->card_type == NV_50) {
-		dev_priv->engine.fifo.tlb_flush(dev);
-		dev_priv->engine.graph.tlb_flush(dev);
-	}
 
 	nvbe->bound = true;
 	return 0;
@@ -142,28 +115,10 @@ nouveau_sgdma_unbind(struct ttm_backend
 	if (!nvbe->bound)
 		return 0;
 
-	pte = nvbe->pte_start;
+	pte = (nvbe->offset >> NV_CTXDMA_PAGE_SHIFT) + 2;
 	for (i = 0; i < nvbe->nr_pages; i++) {
-		dma_addr_t dma_offset = dev_priv->gart_info.sg_dummy_bus;
-
-		for (j = 0; j < PAGE_SIZE / NV_CTXDMA_PAGE_SIZE; j++) {
-			if (dev_priv->card_type < NV_50) {
-				nv_wo32(gpuobj, (pte * 4) + 0, dma_offset | 3);
-				pte += 1;
-			} else {
-				nv_wo32(gpuobj, (pte * 4) + 0, 0x00000000);
-				nv_wo32(gpuobj, (pte * 4) + 4, 0x00000000);
-				pte += 2;
-			}
-
-			dma_offset += NV_CTXDMA_PAGE_SIZE;
-		}
-	}
-	dev_priv->engine.instmem.flush(nvbe->dev);
-
-	if (dev_priv->card_type == NV_50) {
-		dev_priv->engine.fifo.tlb_flush(dev);
-		dev_priv->engine.graph.tlb_flush(dev);
+		for (j = 0; j < PAGE_SIZE / NV_CTXDMA_PAGE_SIZE; j++, pte++)
+			nv_wo32(gpuobj, (pte * 4) + 0, 0x00000000);
 	}
 
 	nvbe->bound = false;
@@ -186,6 +141,35 @@ nouveau_sgdma_destroy(struct ttm_backend
 	}
 }
 
+static int
+nv50_sgdma_bind(struct ttm_backend *be, struct ttm_mem_reg *mem)
+{
+	struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be;
+	struct drm_nouveau_private *dev_priv = nvbe->dev->dev_private;
+
+	nvbe->offset = mem->start << PAGE_SHIFT;
+
+	nouveau_vm_map_sg(&dev_priv->gart_info.vma, nvbe->offset,
+			  nvbe->nr_pages << PAGE_SHIFT, nvbe->pages);
+	nvbe->bound = true;
+	return 0;
+}
+
+static int
+nv50_sgdma_unbind(struct ttm_backend *be)
+{
+	struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be;
+	struct drm_nouveau_private *dev_priv = nvbe->dev->dev_private;
+
+	if (!nvbe->bound)
+		return 0;
+
+	nouveau_vm_unmap_at(&dev_priv->gart_info.vma, nvbe->offset,
+			    nvbe->nr_pages << PAGE_SHIFT);
+	nvbe->bound = false;
+	return 0;
+}
+
 static struct ttm_backend_func nouveau_sgdma_backend = {
 	.populate		= nouveau_sgdma_populate,
 	.clear			= nouveau_sgdma_clear,
@@ -194,23 +178,30 @@ static struct ttm_backend_func nouveau_s
 	.destroy		= nouveau_sgdma_destroy
 };
 
+static struct ttm_backend_func nv50_sgdma_backend = {
+	.populate		= nouveau_sgdma_populate,
+	.clear			= nouveau_sgdma_clear,
+	.bind			= nv50_sgdma_bind,
+	.unbind			= nv50_sgdma_unbind,
+	.destroy		= nouveau_sgdma_destroy
+};
+
 struct ttm_backend *
 nouveau_sgdma_init_ttm(struct drm_device *dev)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct nouveau_sgdma_be *nvbe;
 
-	if (!dev_priv->gart_info.sg_ctxdma)
-		return NULL;
-
 	nvbe = kzalloc(sizeof(*nvbe), GFP_KERNEL);
 	if (!nvbe)
 		return NULL;
 
 	nvbe->dev = dev;
 
-	nvbe->backend.func	= &nouveau_sgdma_backend;
-
+	if (dev_priv->card_type < NV_50)
+		nvbe->backend.func = &nouveau_sgdma_backend;
+	else
+		nvbe->backend.func = &nv50_sgdma_backend;
 	return &nvbe->backend;
 }
 
@@ -218,7 +209,6 @@ int
 nouveau_sgdma_init(struct drm_device *dev)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct pci_dev *pdev = dev->pdev;
 	struct nouveau_gpuobj *gpuobj = NULL;
 	uint32_t aper_size, obj_size;
 	int i, ret;
@@ -231,68 +221,40 @@ nouveau_sgdma_init(struct drm_device *de
 
 		obj_size  = (aper_size >> NV_CTXDMA_PAGE_SHIFT) * 4;
 		obj_size += 8; /* ctxdma header */
-	} else {
-		/* 1 entire VM page table */
-		aper_size = (512 * 1024 * 1024);
-		obj_size  = (aper_size >> NV_CTXDMA_PAGE_SHIFT) * 8;
-	}
 
-	ret = nouveau_gpuobj_new(dev, NULL, obj_size, 16,
-				      NVOBJ_FLAG_ZERO_ALLOC |
-				      NVOBJ_FLAG_ZERO_FREE, &gpuobj);
-	if (ret) {
-		NV_ERROR(dev, "Error creating sgdma object: %d\n", ret);
-		return ret;
-	}
-
-	dev_priv->gart_info.sg_dummy_page =
-		alloc_page(GFP_KERNEL|__GFP_DMA32|__GFP_ZERO);
-	if (!dev_priv->gart_info.sg_dummy_page) {
-		nouveau_gpuobj_ref(NULL, &gpuobj);
-		return -ENOMEM;
-	}
-
-	set_bit(PG_locked, &dev_priv->gart_info.sg_dummy_page->flags);
-	dev_priv->gart_info.sg_dummy_bus =
-		pci_map_page(pdev, dev_priv->gart_info.sg_dummy_page, 0,
-			     PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
-	if (pci_dma_mapping_error(pdev, dev_priv->gart_info.sg_dummy_bus)) {
-		nouveau_gpuobj_ref(NULL, &gpuobj);
-		return -EFAULT;
-	}
-
-	if (dev_priv->card_type < NV_50) {
-		/* special case, allocated from global instmem heap so
-		 * cinst is invalid, we use it on all channels though so
-		 * cinst needs to be valid, set it the same as pinst
-		 */
-		gpuobj->cinst = gpuobj->pinst;
+		ret = nouveau_gpuobj_new(dev, NULL, obj_size, 16,
+					      NVOBJ_FLAG_ZERO_ALLOC |
+					      NVOBJ_FLAG_ZERO_FREE, &gpuobj);
+		if (ret) {
+			NV_ERROR(dev, "Error creating sgdma object: %d\n", ret);
+			return ret;
+		}
 
-		/* Maybe use NV_DMA_TARGET_AGP for PCIE? NVIDIA do this, and
-		 * confirmed to work on c51.  Perhaps means NV_DMA_TARGET_PCIE
-		 * on those cards? */
 		nv_wo32(gpuobj, 0, NV_CLASS_DMA_IN_MEMORY |
 				   (1 << 12) /* PT present */ |
 				   (0 << 13) /* PT *not* linear */ |
-				   (NV_DMA_ACCESS_RW  << 14) |
-				   (NV_DMA_TARGET_PCI << 16));
+				   (0 << 14) /* RW */ |
+				   (2 << 16) /* PCI */);
 		nv_wo32(gpuobj, 4, aper_size - 1);
-		for (i = 2; i < 2 + (aper_size >> 12); i++) {
-			nv_wo32(gpuobj, i * 4,
-				dev_priv->gart_info.sg_dummy_bus | 3);
-		}
-	} else {
-		for (i = 0; i < obj_size; i += 8) {
-			nv_wo32(gpuobj, i + 0, 0x00000000);
-			nv_wo32(gpuobj, i + 4, 0x00000000);
-		}
+		for (i = 2; i < 2 + (aper_size >> 12); i++)
+			nv_wo32(gpuobj, i * 4, 0x00000000);
+
+		dev_priv->gart_info.sg_ctxdma = gpuobj;
+		dev_priv->gart_info.aper_base = 0;
+		dev_priv->gart_info.aper_size = aper_size;
+	} else
+	if (dev_priv->chan_vm) {
+		ret = nouveau_vm_get(dev_priv->chan_vm, 512 * 1024 * 1024,
+				     12, NV_MEM_ACCESS_RW,
+				     &dev_priv->gart_info.vma);
+		if (ret)
+			return ret;
+
+		dev_priv->gart_info.aper_base = dev_priv->gart_info.vma.offset;
+		dev_priv->gart_info.aper_size = 512 * 1024 * 1024;
 	}
-	dev_priv->engine.instmem.flush(dev);
 
 	dev_priv->gart_info.type      = NOUVEAU_GART_SGDMA;
-	dev_priv->gart_info.aper_base = 0;
-	dev_priv->gart_info.aper_size = aper_size;
-	dev_priv->gart_info.sg_ctxdma = gpuobj;
 	return 0;
 }
 
@@ -301,31 +263,19 @@ nouveau_sgdma_takedown(struct drm_device
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 
-	if (dev_priv->gart_info.sg_dummy_page) {
-		pci_unmap_page(dev->pdev, dev_priv->gart_info.sg_dummy_bus,
-			       NV_CTXDMA_PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
-		unlock_page(dev_priv->gart_info.sg_dummy_page);
-		__free_page(dev_priv->gart_info.sg_dummy_page);
-		dev_priv->gart_info.sg_dummy_page = NULL;
-		dev_priv->gart_info.sg_dummy_bus = 0;
-	}
-
 	nouveau_gpuobj_ref(NULL, &dev_priv->gart_info.sg_ctxdma);
+	nouveau_vm_put(&dev_priv->gart_info.vma);
 }
 
-int
-nouveau_sgdma_get_page(struct drm_device *dev, uint32_t offset, uint32_t *page)
+uint32_t
+nouveau_sgdma_get_physical(struct drm_device *dev, uint32_t offset)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct nouveau_gpuobj *gpuobj = dev_priv->gart_info.sg_ctxdma;
-	int pte;
+	int pte = (offset >> NV_CTXDMA_PAGE_SHIFT) + 2;
 
-	pte = (offset >> NV_CTXDMA_PAGE_SHIFT) << 2;
-	if (dev_priv->card_type < NV_50) {
-		*page = nv_ro32(gpuobj, (pte + 8)) & ~NV_CTXDMA_PAGE_MASK;
-		return 0;
-	}
+	BUG_ON(dev_priv->card_type >= NV_50);
 
-	NV_ERROR(dev, "Unimplemented on NV50\n");
-	return -EINVAL;
+	return (nv_ro32(gpuobj, 4 * pte) & ~NV_CTXDMA_PAGE_MASK) |
+		(offset & NV_CTXDMA_PAGE_MASK);
 }
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nouveau_state.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nouveau_state.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nouveau_state.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nouveau_state.c	2011-03-14 21:20:32.000000000 -0400
@@ -53,10 +53,10 @@ static int nouveau_init_engine_ptrs(stru
 		engine->instmem.takedown	= nv04_instmem_takedown;
 		engine->instmem.suspend		= nv04_instmem_suspend;
 		engine->instmem.resume		= nv04_instmem_resume;
-		engine->instmem.populate	= nv04_instmem_populate;
-		engine->instmem.clear		= nv04_instmem_clear;
-		engine->instmem.bind		= nv04_instmem_bind;
-		engine->instmem.unbind		= nv04_instmem_unbind;
+		engine->instmem.get		= nv04_instmem_get;
+		engine->instmem.put		= nv04_instmem_put;
+		engine->instmem.map		= nv04_instmem_map;
+		engine->instmem.unmap		= nv04_instmem_unmap;
 		engine->instmem.flush		= nv04_instmem_flush;
 		engine->mc.init			= nv04_mc_init;
 		engine->mc.takedown		= nv04_mc_takedown;
@@ -65,7 +65,6 @@ static int nouveau_init_engine_ptrs(stru
 		engine->timer.takedown		= nv04_timer_takedown;
 		engine->fb.init			= nv04_fb_init;
 		engine->fb.takedown		= nv04_fb_takedown;
-		engine->graph.grclass		= nv04_graph_grclass;
 		engine->graph.init		= nv04_graph_init;
 		engine->graph.takedown		= nv04_graph_takedown;
 		engine->graph.fifo_access	= nv04_graph_fifo_access;
@@ -76,7 +75,7 @@ static int nouveau_init_engine_ptrs(stru
 		engine->graph.unload_context	= nv04_graph_unload_context;
 		engine->fifo.channels		= 16;
 		engine->fifo.init		= nv04_fifo_init;
-		engine->fifo.takedown		= nouveau_stub_takedown;
+		engine->fifo.takedown		= nv04_fifo_fini;
 		engine->fifo.disable		= nv04_fifo_disable;
 		engine->fifo.enable		= nv04_fifo_enable;
 		engine->fifo.reassign		= nv04_fifo_reassign;
@@ -99,16 +98,20 @@ static int nouveau_init_engine_ptrs(stru
 		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->crypt.init		= nouveau_stub_init;
+		engine->crypt.takedown		= nouveau_stub_takedown;
+		engine->vram.init		= nouveau_mem_detect;
+		engine->vram.flags_valid	= nouveau_mem_flags_valid;
 		break;
 	case 0x10:
 		engine->instmem.init		= nv04_instmem_init;
 		engine->instmem.takedown	= nv04_instmem_takedown;
 		engine->instmem.suspend		= nv04_instmem_suspend;
 		engine->instmem.resume		= nv04_instmem_resume;
-		engine->instmem.populate	= nv04_instmem_populate;
-		engine->instmem.clear		= nv04_instmem_clear;
-		engine->instmem.bind		= nv04_instmem_bind;
-		engine->instmem.unbind		= nv04_instmem_unbind;
+		engine->instmem.get		= nv04_instmem_get;
+		engine->instmem.put		= nv04_instmem_put;
+		engine->instmem.map		= nv04_instmem_map;
+		engine->instmem.unmap		= nv04_instmem_unmap;
 		engine->instmem.flush		= nv04_instmem_flush;
 		engine->mc.init			= nv04_mc_init;
 		engine->mc.takedown		= nv04_mc_takedown;
@@ -117,8 +120,9 @@ static int nouveau_init_engine_ptrs(stru
 		engine->timer.takedown		= nv04_timer_takedown;
 		engine->fb.init			= nv10_fb_init;
 		engine->fb.takedown		= nv10_fb_takedown;
-		engine->fb.set_region_tiling	= nv10_fb_set_region_tiling;
-		engine->graph.grclass		= nv10_graph_grclass;
+		engine->fb.init_tile_region	= nv10_fb_init_tile_region;
+		engine->fb.set_tile_region	= nv10_fb_set_tile_region;
+		engine->fb.free_tile_region	= nv10_fb_free_tile_region;
 		engine->graph.init		= nv10_graph_init;
 		engine->graph.takedown		= nv10_graph_takedown;
 		engine->graph.channel		= nv10_graph_channel;
@@ -127,17 +131,17 @@ static int nouveau_init_engine_ptrs(stru
 		engine->graph.fifo_access	= nv04_graph_fifo_access;
 		engine->graph.load_context	= nv10_graph_load_context;
 		engine->graph.unload_context	= nv10_graph_unload_context;
-		engine->graph.set_region_tiling	= nv10_graph_set_region_tiling;
+		engine->graph.set_tile_region	= nv10_graph_set_tile_region;
 		engine->fifo.channels		= 32;
 		engine->fifo.init		= nv10_fifo_init;
-		engine->fifo.takedown		= nouveau_stub_takedown;
+		engine->fifo.takedown		= nv04_fifo_fini;
 		engine->fifo.disable		= nv04_fifo_disable;
 		engine->fifo.enable		= nv04_fifo_enable;
 		engine->fifo.reassign		= nv04_fifo_reassign;
 		engine->fifo.cache_pull		= nv04_fifo_cache_pull;
 		engine->fifo.channel_id		= nv10_fifo_channel_id;
 		engine->fifo.create_context	= nv10_fifo_create_context;
-		engine->fifo.destroy_context	= nv10_fifo_destroy_context;
+		engine->fifo.destroy_context	= nv04_fifo_destroy_context;
 		engine->fifo.load_context	= nv10_fifo_load_context;
 		engine->fifo.unload_context	= nv10_fifo_unload_context;
 		engine->display.early_init	= nv04_display_early_init;
@@ -153,16 +157,20 @@ static int nouveau_init_engine_ptrs(stru
 		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->crypt.init		= nouveau_stub_init;
+		engine->crypt.takedown		= nouveau_stub_takedown;
+		engine->vram.init		= nouveau_mem_detect;
+		engine->vram.flags_valid	= nouveau_mem_flags_valid;
 		break;
 	case 0x20:
 		engine->instmem.init		= nv04_instmem_init;
 		engine->instmem.takedown	= nv04_instmem_takedown;
 		engine->instmem.suspend		= nv04_instmem_suspend;
 		engine->instmem.resume		= nv04_instmem_resume;
-		engine->instmem.populate	= nv04_instmem_populate;
-		engine->instmem.clear		= nv04_instmem_clear;
-		engine->instmem.bind		= nv04_instmem_bind;
-		engine->instmem.unbind		= nv04_instmem_unbind;
+		engine->instmem.get		= nv04_instmem_get;
+		engine->instmem.put		= nv04_instmem_put;
+		engine->instmem.map		= nv04_instmem_map;
+		engine->instmem.unmap		= nv04_instmem_unmap;
 		engine->instmem.flush		= nv04_instmem_flush;
 		engine->mc.init			= nv04_mc_init;
 		engine->mc.takedown		= nv04_mc_takedown;
@@ -171,8 +179,9 @@ static int nouveau_init_engine_ptrs(stru
 		engine->timer.takedown		= nv04_timer_takedown;
 		engine->fb.init			= nv10_fb_init;
 		engine->fb.takedown		= nv10_fb_takedown;
-		engine->fb.set_region_tiling	= nv10_fb_set_region_tiling;
-		engine->graph.grclass		= nv20_graph_grclass;
+		engine->fb.init_tile_region	= nv10_fb_init_tile_region;
+		engine->fb.set_tile_region	= nv10_fb_set_tile_region;
+		engine->fb.free_tile_region	= nv10_fb_free_tile_region;
 		engine->graph.init		= nv20_graph_init;
 		engine->graph.takedown		= nv20_graph_takedown;
 		engine->graph.channel		= nv10_graph_channel;
@@ -181,17 +190,17 @@ static int nouveau_init_engine_ptrs(stru
 		engine->graph.fifo_access	= nv04_graph_fifo_access;
 		engine->graph.load_context	= nv20_graph_load_context;
 		engine->graph.unload_context	= nv20_graph_unload_context;
-		engine->graph.set_region_tiling	= nv20_graph_set_region_tiling;
+		engine->graph.set_tile_region	= nv20_graph_set_tile_region;
 		engine->fifo.channels		= 32;
 		engine->fifo.init		= nv10_fifo_init;
-		engine->fifo.takedown		= nouveau_stub_takedown;
+		engine->fifo.takedown		= nv04_fifo_fini;
 		engine->fifo.disable		= nv04_fifo_disable;
 		engine->fifo.enable		= nv04_fifo_enable;
 		engine->fifo.reassign		= nv04_fifo_reassign;
 		engine->fifo.cache_pull		= nv04_fifo_cache_pull;
 		engine->fifo.channel_id		= nv10_fifo_channel_id;
 		engine->fifo.create_context	= nv10_fifo_create_context;
-		engine->fifo.destroy_context	= nv10_fifo_destroy_context;
+		engine->fifo.destroy_context	= nv04_fifo_destroy_context;
 		engine->fifo.load_context	= nv10_fifo_load_context;
 		engine->fifo.unload_context	= nv10_fifo_unload_context;
 		engine->display.early_init	= nv04_display_early_init;
@@ -207,16 +216,20 @@ static int nouveau_init_engine_ptrs(stru
 		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->crypt.init		= nouveau_stub_init;
+		engine->crypt.takedown		= nouveau_stub_takedown;
+		engine->vram.init		= nouveau_mem_detect;
+		engine->vram.flags_valid	= nouveau_mem_flags_valid;
 		break;
 	case 0x30:
 		engine->instmem.init		= nv04_instmem_init;
 		engine->instmem.takedown	= nv04_instmem_takedown;
 		engine->instmem.suspend		= nv04_instmem_suspend;
 		engine->instmem.resume		= nv04_instmem_resume;
-		engine->instmem.populate	= nv04_instmem_populate;
-		engine->instmem.clear		= nv04_instmem_clear;
-		engine->instmem.bind		= nv04_instmem_bind;
-		engine->instmem.unbind		= nv04_instmem_unbind;
+		engine->instmem.get		= nv04_instmem_get;
+		engine->instmem.put		= nv04_instmem_put;
+		engine->instmem.map		= nv04_instmem_map;
+		engine->instmem.unmap		= nv04_instmem_unmap;
 		engine->instmem.flush		= nv04_instmem_flush;
 		engine->mc.init			= nv04_mc_init;
 		engine->mc.takedown		= nv04_mc_takedown;
@@ -225,8 +238,9 @@ static int nouveau_init_engine_ptrs(stru
 		engine->timer.takedown		= nv04_timer_takedown;
 		engine->fb.init			= nv30_fb_init;
 		engine->fb.takedown		= nv30_fb_takedown;
-		engine->fb.set_region_tiling	= nv10_fb_set_region_tiling;
-		engine->graph.grclass		= nv30_graph_grclass;
+		engine->fb.init_tile_region	= nv30_fb_init_tile_region;
+		engine->fb.set_tile_region	= nv10_fb_set_tile_region;
+		engine->fb.free_tile_region	= nv30_fb_free_tile_region;
 		engine->graph.init		= nv30_graph_init;
 		engine->graph.takedown		= nv20_graph_takedown;
 		engine->graph.fifo_access	= nv04_graph_fifo_access;
@@ -235,17 +249,17 @@ static int nouveau_init_engine_ptrs(stru
 		engine->graph.destroy_context	= nv20_graph_destroy_context;
 		engine->graph.load_context	= nv20_graph_load_context;
 		engine->graph.unload_context	= nv20_graph_unload_context;
-		engine->graph.set_region_tiling	= nv20_graph_set_region_tiling;
+		engine->graph.set_tile_region	= nv20_graph_set_tile_region;
 		engine->fifo.channels		= 32;
 		engine->fifo.init		= nv10_fifo_init;
-		engine->fifo.takedown		= nouveau_stub_takedown;
+		engine->fifo.takedown		= nv04_fifo_fini;
 		engine->fifo.disable		= nv04_fifo_disable;
 		engine->fifo.enable		= nv04_fifo_enable;
 		engine->fifo.reassign		= nv04_fifo_reassign;
 		engine->fifo.cache_pull		= nv04_fifo_cache_pull;
 		engine->fifo.channel_id		= nv10_fifo_channel_id;
 		engine->fifo.create_context	= nv10_fifo_create_context;
-		engine->fifo.destroy_context	= nv10_fifo_destroy_context;
+		engine->fifo.destroy_context	= nv04_fifo_destroy_context;
 		engine->fifo.load_context	= nv10_fifo_load_context;
 		engine->fifo.unload_context	= nv10_fifo_unload_context;
 		engine->display.early_init	= nv04_display_early_init;
@@ -263,6 +277,10 @@ static int nouveau_init_engine_ptrs(stru
 		engine->pm.clock_set		= nv04_pm_clock_set;
 		engine->pm.voltage_get		= nouveau_voltage_gpio_get;
 		engine->pm.voltage_set		= nouveau_voltage_gpio_set;
+		engine->crypt.init		= nouveau_stub_init;
+		engine->crypt.takedown		= nouveau_stub_takedown;
+		engine->vram.init		= nouveau_mem_detect;
+		engine->vram.flags_valid	= nouveau_mem_flags_valid;
 		break;
 	case 0x40:
 	case 0x60:
@@ -270,10 +288,10 @@ static int nouveau_init_engine_ptrs(stru
 		engine->instmem.takedown	= nv04_instmem_takedown;
 		engine->instmem.suspend		= nv04_instmem_suspend;
 		engine->instmem.resume		= nv04_instmem_resume;
-		engine->instmem.populate	= nv04_instmem_populate;
-		engine->instmem.clear		= nv04_instmem_clear;
-		engine->instmem.bind		= nv04_instmem_bind;
-		engine->instmem.unbind		= nv04_instmem_unbind;
+		engine->instmem.get		= nv04_instmem_get;
+		engine->instmem.put		= nv04_instmem_put;
+		engine->instmem.map		= nv04_instmem_map;
+		engine->instmem.unmap		= nv04_instmem_unmap;
 		engine->instmem.flush		= nv04_instmem_flush;
 		engine->mc.init			= nv40_mc_init;
 		engine->mc.takedown		= nv40_mc_takedown;
@@ -282,8 +300,9 @@ static int nouveau_init_engine_ptrs(stru
 		engine->timer.takedown		= nv04_timer_takedown;
 		engine->fb.init			= nv40_fb_init;
 		engine->fb.takedown		= nv40_fb_takedown;
-		engine->fb.set_region_tiling	= nv40_fb_set_region_tiling;
-		engine->graph.grclass		= nv40_graph_grclass;
+		engine->fb.init_tile_region	= nv30_fb_init_tile_region;
+		engine->fb.set_tile_region	= nv40_fb_set_tile_region;
+		engine->fb.free_tile_region	= nv30_fb_free_tile_region;
 		engine->graph.init		= nv40_graph_init;
 		engine->graph.takedown		= nv40_graph_takedown;
 		engine->graph.fifo_access	= nv04_graph_fifo_access;
@@ -292,17 +311,17 @@ static int nouveau_init_engine_ptrs(stru
 		engine->graph.destroy_context	= nv40_graph_destroy_context;
 		engine->graph.load_context	= nv40_graph_load_context;
 		engine->graph.unload_context	= nv40_graph_unload_context;
-		engine->graph.set_region_tiling	= nv40_graph_set_region_tiling;
+		engine->graph.set_tile_region	= nv40_graph_set_tile_region;
 		engine->fifo.channels		= 32;
 		engine->fifo.init		= nv40_fifo_init;
-		engine->fifo.takedown		= nouveau_stub_takedown;
+		engine->fifo.takedown		= nv04_fifo_fini;
 		engine->fifo.disable		= nv04_fifo_disable;
 		engine->fifo.enable		= nv04_fifo_enable;
 		engine->fifo.reassign		= nv04_fifo_reassign;
 		engine->fifo.cache_pull		= nv04_fifo_cache_pull;
 		engine->fifo.channel_id		= nv10_fifo_channel_id;
 		engine->fifo.create_context	= nv40_fifo_create_context;
-		engine->fifo.destroy_context	= nv40_fifo_destroy_context;
+		engine->fifo.destroy_context	= nv04_fifo_destroy_context;
 		engine->fifo.load_context	= nv40_fifo_load_context;
 		engine->fifo.unload_context	= nv40_fifo_unload_context;
 		engine->display.early_init	= nv04_display_early_init;
@@ -321,6 +340,10 @@ static int nouveau_init_engine_ptrs(stru
 		engine->pm.voltage_get		= nouveau_voltage_gpio_get;
 		engine->pm.voltage_set		= nouveau_voltage_gpio_set;
 		engine->pm.temp_get		= nv40_temp_get;
+		engine->crypt.init		= nouveau_stub_init;
+		engine->crypt.takedown		= nouveau_stub_takedown;
+		engine->vram.init		= nouveau_mem_detect;
+		engine->vram.flags_valid	= nouveau_mem_flags_valid;
 		break;
 	case 0x50:
 	case 0x80: /* gotta love NVIDIA's consistency.. */
@@ -330,10 +353,10 @@ static int nouveau_init_engine_ptrs(stru
 		engine->instmem.takedown	= nv50_instmem_takedown;
 		engine->instmem.suspend		= nv50_instmem_suspend;
 		engine->instmem.resume		= nv50_instmem_resume;
-		engine->instmem.populate	= nv50_instmem_populate;
-		engine->instmem.clear		= nv50_instmem_clear;
-		engine->instmem.bind		= nv50_instmem_bind;
-		engine->instmem.unbind		= nv50_instmem_unbind;
+		engine->instmem.get		= nv50_instmem_get;
+		engine->instmem.put		= nv50_instmem_put;
+		engine->instmem.map		= nv50_instmem_map;
+		engine->instmem.unmap		= nv50_instmem_unmap;
 		if (dev_priv->chipset == 0x50)
 			engine->instmem.flush	= nv50_instmem_flush;
 		else
@@ -345,7 +368,6 @@ static int nouveau_init_engine_ptrs(stru
 		engine->timer.takedown		= nv04_timer_takedown;
 		engine->fb.init			= nv50_fb_init;
 		engine->fb.takedown		= nv50_fb_takedown;
-		engine->graph.grclass		= nv50_graph_grclass;
 		engine->graph.init		= nv50_graph_init;
 		engine->graph.takedown		= nv50_graph_takedown;
 		engine->graph.fifo_access	= nv50_graph_fifo_access;
@@ -381,24 +403,32 @@ static int nouveau_init_engine_ptrs(stru
 		engine->display.init		= nv50_display_init;
 		engine->display.destroy		= nv50_display_destroy;
 		engine->gpio.init		= nv50_gpio_init;
-		engine->gpio.takedown		= nouveau_stub_takedown;
+		engine->gpio.takedown		= nv50_gpio_fini;
 		engine->gpio.get		= nv50_gpio_get;
 		engine->gpio.set		= nv50_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;
 		switch (dev_priv->chipset) {
-		case 0xa3:
-		case 0xa5:
-		case 0xa8:
-		case 0xaf:
-			engine->pm.clock_get	= nva3_pm_clock_get;
-			engine->pm.clock_pre	= nva3_pm_clock_pre;
-			engine->pm.clock_set	= nva3_pm_clock_set;
-			break;
-		default:
+		case 0x84:
+		case 0x86:
+		case 0x92:
+		case 0x94:
+		case 0x96:
+		case 0x98:
+		case 0xa0:
+		case 0xaa:
+		case 0xac:
+		case 0x50:
 			engine->pm.clock_get	= nv50_pm_clock_get;
 			engine->pm.clock_pre	= nv50_pm_clock_pre;
 			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;
+			break;
 		}
 		engine->pm.voltage_get		= nouveau_voltage_gpio_get;
 		engine->pm.voltage_set		= nouveau_voltage_gpio_set;
@@ -406,17 +436,39 @@ static int nouveau_init_engine_ptrs(stru
 			engine->pm.temp_get	= nv84_temp_get;
 		else
 			engine->pm.temp_get	= nv40_temp_get;
+		switch (dev_priv->chipset) {
+		case 0x84:
+		case 0x86:
+		case 0x92:
+		case 0x94:
+		case 0x96:
+		case 0xa0:
+			engine->crypt.init	= nv84_crypt_init;
+			engine->crypt.takedown	= nv84_crypt_fini;
+			engine->crypt.create_context = nv84_crypt_create_context;
+			engine->crypt.destroy_context = nv84_crypt_destroy_context;
+			engine->crypt.tlb_flush	= nv84_crypt_tlb_flush;
+			break;
+		default:
+			engine->crypt.init	= nouveau_stub_init;
+			engine->crypt.takedown	= nouveau_stub_takedown;
+			break;
+		}
+		engine->vram.init		= nv50_vram_init;
+		engine->vram.get		= nv50_vram_new;
+		engine->vram.put		= nv50_vram_del;
+		engine->vram.flags_valid	= nv50_vram_flags_valid;
 		break;
 	case 0xC0:
 		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.populate	= nvc0_instmem_populate;
-		engine->instmem.clear		= nvc0_instmem_clear;
-		engine->instmem.bind		= nvc0_instmem_bind;
-		engine->instmem.unbind		= nvc0_instmem_unbind;
-		engine->instmem.flush		= nvc0_instmem_flush;
+		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;
@@ -424,7 +476,6 @@ static int nouveau_init_engine_ptrs(stru
 		engine->timer.takedown		= nv04_timer_takedown;
 		engine->fb.init			= nvc0_fb_init;
 		engine->fb.takedown		= nvc0_fb_takedown;
-		engine->graph.grclass		= NULL;  //nvc0_graph_grclass;
 		engine->graph.init		= nvc0_graph_init;
 		engine->graph.takedown		= nvc0_graph_takedown;
 		engine->graph.fifo_access	= nvc0_graph_fifo_access;
@@ -453,7 +504,15 @@ static int nouveau_init_engine_ptrs(stru
 		engine->gpio.takedown		= nouveau_stub_takedown;
 		engine->gpio.get		= nv50_gpio_get;
 		engine->gpio.set		= nv50_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->crypt.init		= nouveau_stub_init;
+		engine->crypt.takedown		= nouveau_stub_takedown;
+		engine->vram.init		= nvc0_vram_init;
+		engine->vram.get		= nvc0_vram_new;
+		engine->vram.put		= nv50_vram_del;
+		engine->vram.flags_valid	= nvc0_vram_flags_valid;
 		break;
 	default:
 		NV_ERROR(dev, "NV%02x unsupported\n", dev_priv->chipset);
@@ -493,9 +552,13 @@ nouveau_card_init_channel(struct drm_dev
 	if (ret)
 		return ret;
 
+	/* no dma objects on fermi... */
+	if (dev_priv->card_type >= NV_C0)
+		goto out_done;
+
 	ret = nouveau_gpuobj_dma_new(dev_priv->channel, NV_CLASS_DMA_IN_MEMORY,
 				     0, dev_priv->vram_size,
-				     NV_DMA_ACCESS_RW, NV_DMA_TARGET_VIDMEM,
+				     NV_MEM_ACCESS_RW, NV_MEM_TARGET_VRAM,
 				     &gpuobj);
 	if (ret)
 		goto out_err;
@@ -505,9 +568,10 @@ nouveau_card_init_channel(struct drm_dev
 	if (ret)
 		goto out_err;
 
-	ret = nouveau_gpuobj_gart_dma_new(dev_priv->channel, 0,
-					  dev_priv->gart_info.aper_size,
-					  NV_DMA_ACCESS_RW, &gpuobj, NULL);
+	ret = nouveau_gpuobj_dma_new(dev_priv->channel, NV_CLASS_DMA_IN_MEMORY,
+				     0, dev_priv->gart_info.aper_size,
+				     NV_MEM_ACCESS_RW, NV_MEM_TARGET_GART,
+				     &gpuobj);
 	if (ret)
 		goto out_err;
 
@@ -516,11 +580,12 @@ nouveau_card_init_channel(struct drm_dev
 	if (ret)
 		goto out_err;
 
+out_done:
+	mutex_unlock(&dev_priv->channel->mutex);
 	return 0;
 
 out_err:
-	nouveau_channel_free(dev_priv->channel);
-	dev_priv->channel = NULL;
+	nouveau_channel_put(&dev_priv->channel);
 	return ret;
 }
 
@@ -531,15 +596,25 @@ static void nouveau_switcheroo_set_state
 	pm_message_t pmm = { .event = PM_EVENT_SUSPEND };
 	if (state == VGA_SWITCHEROO_ON) {
 		printk(KERN_ERR "VGA switcheroo: switched nouveau on\n");
+		dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
 		nouveau_pci_resume(pdev);
 		drm_kms_helper_poll_enable(dev);
+		dev->switch_power_state = DRM_SWITCH_POWER_ON;
 	} else {
 		printk(KERN_ERR "VGA switcheroo: switched nouveau off\n");
+		dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
 		drm_kms_helper_poll_disable(dev);
 		nouveau_pci_suspend(pdev, pmm);
+		dev->switch_power_state = DRM_SWITCH_POWER_OFF;
 	}
 }
 
+static void nouveau_switcheroo_reprobe(struct pci_dev *pdev)
+{
+	struct drm_device *dev = pci_get_drvdata(pdev);
+	nouveau_fbcon_output_poll_changed(dev);
+}
+
 static bool nouveau_switcheroo_can_switch(struct pci_dev *pdev)
 {
 	struct drm_device *dev = pci_get_drvdata(pdev);
@@ -560,6 +635,7 @@ nouveau_card_init(struct drm_device *dev
 
 	vga_client_register(dev->pdev, dev, NULL, nouveau_vga_set_decode);
 	vga_switcheroo_register_client(dev->pdev, nouveau_switcheroo_set_state,
+				       nouveau_switcheroo_reprobe,
 				       nouveau_switcheroo_can_switch);
 
 	/* Initialise internal driver API hooks */
@@ -567,6 +643,8 @@ nouveau_card_init(struct drm_device *dev
 	if (ret)
 		goto out;
 	engine = &dev_priv->engine;
+	spin_lock_init(&dev_priv->channels.lock);
+	spin_lock_init(&dev_priv->tile.lock);
 	spin_lock_init(&dev_priv->context_switch_lock);
 
 	/* Make the CRTCs and I2C buses accessible */
@@ -625,26 +703,28 @@ nouveau_card_init(struct drm_device *dev
 		if (ret)
 			goto out_fb;
 
+		/* PCRYPT */
+		ret = engine->crypt.init(dev);
+		if (ret)
+			goto out_graph;
+
 		/* PFIFO */
 		ret = engine->fifo.init(dev);
 		if (ret)
-			goto out_graph;
+			goto out_crypt;
 	}
 
 	ret = engine->display.create(dev);
 	if (ret)
 		goto out_fifo;
 
-	/* this call irq_preinstall, register irq handler and
-	 * call irq_postinstall
-	 */
-	ret = drm_irq_install(dev);
+	ret = drm_vblank_init(dev, nv_two_heads(dev) ? 2 : 1);
 	if (ret)
-		goto out_display;
+		goto out_vblank;
 
-	ret = drm_vblank_init(dev, 0);
+	ret = nouveau_irq_init(dev);
 	if (ret)
-		goto out_irq;
+		goto out_vblank;
 
 	/* what about PVIDEO/PCRTC/PRAMDAC etc? */
 
@@ -669,12 +749,16 @@ nouveau_card_init(struct drm_device *dev
 out_fence:
 	nouveau_fence_fini(dev);
 out_irq:
-	drm_irq_uninstall(dev);
-out_display:
+	nouveau_irq_fini(dev);
+out_vblank:
+	drm_vblank_cleanup(dev);
 	engine->display.destroy(dev);
 out_fifo:
 	if (!nouveau_noaccel)
 		engine->fifo.takedown(dev);
+out_crypt:
+	if (!nouveau_noaccel)
+		engine->crypt.takedown(dev);
 out_graph:
 	if (!nouveau_noaccel)
 		engine->graph.takedown(dev);
@@ -713,12 +797,12 @@ static void nouveau_card_takedown(struct
 
 	if (!engine->graph.accel_blocked) {
 		nouveau_fence_fini(dev);
-		nouveau_channel_free(dev_priv->channel);
-		dev_priv->channel = NULL;
+		nouveau_channel_put_unlocked(&dev_priv->channel);
 	}
 
 	if (!nouveau_noaccel) {
 		engine->fifo.takedown(dev);
+		engine->crypt.takedown(dev);
 		engine->graph.takedown(dev);
 	}
 	engine->fb.takedown(dev);
@@ -737,7 +821,8 @@ static void nouveau_card_takedown(struct
 	nouveau_gpuobj_takedown(dev);
 	nouveau_mem_vram_fini(dev);
 
-	drm_irq_uninstall(dev);
+	nouveau_irq_fini(dev);
+	drm_vblank_cleanup(dev);
 
 	nouveau_pm_fini(dev);
 	nouveau_bios_takedown(dev);
@@ -980,6 +1065,7 @@ err_out:
 
 void nouveau_lastclose(struct drm_device *dev)
 {
+	vga_switcheroo_process_delayed_switch();
 }
 
 int nouveau_unload(struct drm_device *dev)
@@ -1024,21 +1110,6 @@ int nouveau_ioctl_getparam(struct drm_de
 		else
 			getparam->value = NV_PCI;
 		break;
-	case NOUVEAU_GETPARAM_FB_PHYSICAL:
-		getparam->value = dev_priv->fb_phys;
-		break;
-	case NOUVEAU_GETPARAM_AGP_PHYSICAL:
-		getparam->value = dev_priv->gart_info.aper_base;
-		break;
-	case NOUVEAU_GETPARAM_PCI_PHYSICAL:
-		if (dev->sg) {
-			getparam->value = (unsigned long)dev->sg->virtual;
-		} else {
-			NV_ERROR(dev, "Requested PCIGART address, "
-					"while no PCIGART was created\n");
-			return -EINVAL;
-		}
-		break;
 	case NOUVEAU_GETPARAM_FB_SIZE:
 		getparam->value = dev_priv->fb_available_size;
 		break;
@@ -1046,7 +1117,7 @@ int nouveau_ioctl_getparam(struct drm_de
 		getparam->value = dev_priv->gart_info.aper_size;
 		break;
 	case NOUVEAU_GETPARAM_VM_VRAM_BASE:
-		getparam->value = dev_priv->vm_vram_base;
+		getparam->value = 0; /* deprecated */
 		break;
 	case NOUVEAU_GETPARAM_PTIMER_TIME:
 		getparam->value = dev_priv->engine.timer.read(dev);
@@ -1054,6 +1125,9 @@ int nouveau_ioctl_getparam(struct drm_de
 	case NOUVEAU_GETPARAM_HAS_BO_USAGE:
 		getparam->value = 1;
 		break;
+	case NOUVEAU_GETPARAM_HAS_PAGEFLIP:
+		getparam->value = (dev_priv->card_type < NV_50);
+		break;
 	case NOUVEAU_GETPARAM_GRAPH_UNITS:
 		/* NV40 and NV50 versions are quite different, but register
 		 * address is the same. User is supposed to know the card
@@ -1087,8 +1161,9 @@ nouveau_ioctl_setparam(struct drm_device
 }
 
 /* Wait until (value(reg) & mask) == val, up until timeout has hit */
-bool nouveau_wait_until(struct drm_device *dev, uint64_t timeout,
-			uint32_t reg, uint32_t mask, uint32_t val)
+bool
+nouveau_wait_eq(struct drm_device *dev, uint64_t timeout,
+		uint32_t reg, uint32_t mask, uint32_t val)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct nouveau_timer_engine *ptimer = &dev_priv->engine.timer;
@@ -1102,10 +1177,33 @@ bool nouveau_wait_until(struct drm_devic
 	return false;
 }
 
+/* Wait until (value(reg) & mask) != val, up until timeout has hit */
+bool
+nouveau_wait_ne(struct drm_device *dev, uint64_t timeout,
+		uint32_t reg, uint32_t mask, uint32_t val)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_timer_engine *ptimer = &dev_priv->engine.timer;
+	uint64_t start = ptimer->read(dev);
+
+	do {
+		if ((nv_rd32(dev, reg) & mask) != val)
+			return true;
+	} while (ptimer->read(dev) - start < timeout);
+
+	return false;
+}
+
 /* Waits for PGRAPH to go completely idle */
 bool nouveau_wait_for_idle(struct drm_device *dev)
 {
-	if (!nv_wait(dev, NV04_PGRAPH_STATUS, 0xffffffff, 0x00000000)) {
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	uint32_t mask = ~0;
+
+	if (dev_priv->card_type == NV_40)
+		mask &= ~NV40_PGRAPH_STATUS_SYNC_STALL;
+
+	if (!nv_wait(dev, NV04_PGRAPH_STATUS, mask, 0)) {
 		NV_ERROR(dev, "PGRAPH idle timed out with status 0x%08x\n",
 			 nv_rd32(dev, NV04_PGRAPH_STATUS));
 		return false;
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nouveau_temp.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nouveau_temp.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nouveau_temp.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nouveau_temp.c	2011-03-14 21:20:32.000000000 -0400
@@ -265,8 +265,8 @@ nouveau_temp_probe_i2c(struct drm_device
 	struct i2c_board_info info[] = {
 		{ I2C_BOARD_INFO("w83l785ts", 0x2d) },
 		{ I2C_BOARD_INFO("w83781d", 0x2d) },
-		{ I2C_BOARD_INFO("f75375", 0x2e) },
 		{ I2C_BOARD_INFO("adt7473", 0x2e) },
+		{ I2C_BOARD_INFO("f75375", 0x2e) },
 		{ I2C_BOARD_INFO("lm99", 0x4c) },
 		{ }
 	};
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nouveau_util.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nouveau_util.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nouveau_util.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nouveau_util.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2010 Nouveau Project
+ *
+ * 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, 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 THE COPYRIGHT OWNER(S) 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 <linux/ratelimit.h>
+
+#include "nouveau_util.h"
+
+static DEFINE_RATELIMIT_STATE(nouveau_ratelimit_state, 3 * HZ, 20);
+
+void
+nouveau_bitfield_print(const struct nouveau_bitfield *bf, u32 value)
+{
+	while (bf->name) {
+		if (value & bf->mask) {
+			printk(" %s", bf->name);
+			value &= ~bf->mask;
+		}
+
+		bf++;
+	}
+
+	if (value)
+		printk(" (unknown bits 0x%08x)", value);
+}
+
+void
+nouveau_enum_print(const struct nouveau_enum *en, u32 value)
+{
+	while (en->name) {
+		if (value == en->value) {
+			printk("%s", en->name);
+			return;
+		}
+
+		en++;
+	}
+
+	printk("(unknown enum 0x%08x)", value);
+}
+
+int
+nouveau_ratelimit(void)
+{
+	return __ratelimit(&nouveau_ratelimit_state);
+}
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nouveau_util.h linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nouveau_util.h
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nouveau_util.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nouveau_util.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2010 Nouveau Project
+ *
+ * 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, 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 THE COPYRIGHT OWNER(S) 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 __NOUVEAU_UTIL_H__
+#define __NOUVEAU_UTIL_H__
+
+struct nouveau_bitfield {
+	u32 mask;
+	const char *name;
+};
+
+struct nouveau_enum {
+	u32 value;
+	const char *name;
+};
+
+void nouveau_bitfield_print(const struct nouveau_bitfield *, u32 value);
+void nouveau_enum_print(const struct nouveau_enum *, u32 value);
+int nouveau_ratelimit(void);
+
+#endif
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nouveau_vm.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nouveau_vm.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nouveau_vm.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nouveau_vm.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,439 @@
+/*
+ * Copyright 2010 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_mm.h"
+#include "nouveau_vm.h"
+
+void
+nouveau_vm_map_at(struct nouveau_vma *vma, u64 delta, struct nouveau_vram *vram)
+{
+	struct nouveau_vm *vm = vma->vm;
+	struct nouveau_mm_node *r;
+	int big = vma->node->type != vm->spg_shift;
+	u32 offset = vma->node->offset + (delta >> 12);
+	u32 bits = vma->node->type - 12;
+	u32 pde  = (offset >> vm->pgt_bits) - vm->fpde;
+	u32 pte  = (offset & ((1 << vm->pgt_bits) - 1)) >> bits;
+	u32 max  = 1 << (vm->pgt_bits - bits);
+	u32 end, len;
+
+	list_for_each_entry(r, &vram->regions, rl_entry) {
+		u64 phys = (u64)r->offset << 12;
+		u32 num  = r->length >> bits;
+
+		while (num) {
+			struct nouveau_gpuobj *pgt = vm->pgt[pde].obj[big];
+
+			end = (pte + num);
+			if (unlikely(end >= max))
+				end = max;
+			len = end - pte;
+
+			vm->map(vma, pgt, vram, pte, len, phys);
+
+			num -= len;
+			pte += len;
+			if (unlikely(end >= max)) {
+				pde++;
+				pte = 0;
+			}
+		}
+	}
+
+	vm->flush(vm);
+}
+
+void
+nouveau_vm_map(struct nouveau_vma *vma, struct nouveau_vram *vram)
+{
+	nouveau_vm_map_at(vma, 0, vram);
+}
+
+void
+nouveau_vm_map_sg(struct nouveau_vma *vma, u64 delta, u64 length,
+		  dma_addr_t *list)
+{
+	struct nouveau_vm *vm = vma->vm;
+	int big = vma->node->type != vm->spg_shift;
+	u32 offset = vma->node->offset + (delta >> 12);
+	u32 bits = vma->node->type - 12;
+	u32 num  = length >> vma->node->type;
+	u32 pde  = (offset >> vm->pgt_bits) - vm->fpde;
+	u32 pte  = (offset & ((1 << vm->pgt_bits) - 1)) >> bits;
+	u32 max  = 1 << (vm->pgt_bits - bits);
+	u32 end, len;
+
+	while (num) {
+		struct nouveau_gpuobj *pgt = vm->pgt[pde].obj[big];
+
+		end = (pte + num);
+		if (unlikely(end >= max))
+			end = max;
+		len = end - pte;
+
+		vm->map_sg(vma, pgt, pte, list, len);
+
+		num  -= len;
+		pte  += len;
+		list += len;
+		if (unlikely(end >= max)) {
+			pde++;
+			pte = 0;
+		}
+	}
+
+	vm->flush(vm);
+}
+
+void
+nouveau_vm_unmap_at(struct nouveau_vma *vma, u64 delta, u64 length)
+{
+	struct nouveau_vm *vm = vma->vm;
+	int big = vma->node->type != vm->spg_shift;
+	u32 offset = vma->node->offset + (delta >> 12);
+	u32 bits = vma->node->type - 12;
+	u32 num  = length >> vma->node->type;
+	u32 pde  = (offset >> vm->pgt_bits) - vm->fpde;
+	u32 pte  = (offset & ((1 << vm->pgt_bits) - 1)) >> bits;
+	u32 max  = 1 << (vm->pgt_bits - bits);
+	u32 end, len;
+
+	while (num) {
+		struct nouveau_gpuobj *pgt = vm->pgt[pde].obj[big];
+
+		end = (pte + num);
+		if (unlikely(end >= max))
+			end = max;
+		len = end - pte;
+
+		vm->unmap(pgt, pte, len);
+
+		num -= len;
+		pte += len;
+		if (unlikely(end >= max)) {
+			pde++;
+			pte = 0;
+		}
+	}
+
+	vm->flush(vm);
+}
+
+void
+nouveau_vm_unmap(struct nouveau_vma *vma)
+{
+	nouveau_vm_unmap_at(vma, 0, (u64)vma->node->length << 12);
+}
+
+static void
+nouveau_vm_unmap_pgt(struct nouveau_vm *vm, int big, u32 fpde, u32 lpde)
+{
+	struct nouveau_vm_pgd *vpgd;
+	struct nouveau_vm_pgt *vpgt;
+	struct nouveau_gpuobj *pgt;
+	u32 pde;
+
+	for (pde = fpde; pde <= lpde; pde++) {
+		vpgt = &vm->pgt[pde - vm->fpde];
+		if (--vpgt->refcount[big])
+			continue;
+
+		pgt = vpgt->obj[big];
+		vpgt->obj[big] = NULL;
+
+		list_for_each_entry(vpgd, &vm->pgd_list, head) {
+			vm->map_pgt(vpgd->obj, pde, vpgt->obj);
+		}
+
+		mutex_unlock(&vm->mm->mutex);
+		nouveau_gpuobj_ref(NULL, &pgt);
+		mutex_lock(&vm->mm->mutex);
+	}
+}
+
+static int
+nouveau_vm_map_pgt(struct nouveau_vm *vm, u32 pde, u32 type)
+{
+	struct nouveau_vm_pgt *vpgt = &vm->pgt[pde - vm->fpde];
+	struct nouveau_vm_pgd *vpgd;
+	struct nouveau_gpuobj *pgt;
+	int big = (type != vm->spg_shift);
+	u32 pgt_size;
+	int ret;
+
+	pgt_size  = (1 << (vm->pgt_bits + 12)) >> type;
+	pgt_size *= 8;
+
+	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);
+	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);
+		nouveau_gpuobj_ref(NULL, &pgt);
+		mutex_lock(&vm->mm->mutex);
+		return 0;
+	}
+
+	vpgt->obj[big] = pgt;
+	list_for_each_entry(vpgd, &vm->pgd_list, head) {
+		vm->map_pgt(vpgd->obj, pde, vpgt->obj);
+	}
+
+	return 0;
+}
+
+int
+nouveau_vm_get(struct nouveau_vm *vm, u64 size, u32 page_shift,
+	       u32 access, struct nouveau_vma *vma)
+{
+	u32 align = (1 << page_shift) >> 12;
+	u32 msize = size >> 12;
+	u32 fpde, lpde, pde;
+	int ret;
+
+	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);
+		return ret;
+	}
+
+	fpde = (vma->node->offset >> vm->pgt_bits);
+	lpde = (vma->node->offset + vma->node->length - 1) >> vm->pgt_bits;
+	for (pde = fpde; pde <= lpde; pde++) {
+		struct nouveau_vm_pgt *vpgt = &vm->pgt[pde - vm->fpde];
+		int big = (vma->node->type != vm->spg_shift);
+
+		if (likely(vpgt->refcount[big])) {
+			vpgt->refcount[big]++;
+			continue;
+		}
+
+		ret = nouveau_vm_map_pgt(vm, pde, vma->node->type);
+		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);
+			vma->node = NULL;
+			return ret;
+		}
+	}
+	mutex_unlock(&vm->mm->mutex);
+
+	vma->vm     = vm;
+	vma->offset = (u64)vma->node->offset << 12;
+	vma->access = access;
+	return 0;
+}
+
+void
+nouveau_vm_put(struct nouveau_vma *vma)
+{
+	struct nouveau_vm *vm = vma->vm;
+	u32 fpde, lpde;
+
+	if (unlikely(vma->node == NULL))
+		return;
+	fpde = (vma->node->offset >> vm->pgt_bits);
+	lpde = (vma->node->offset + vma->node->length - 1) >> vm->pgt_bits;
+
+	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);
+	vma->node = NULL;
+	mutex_unlock(&vm->mm->mutex);
+}
+
+int
+nouveau_vm_new(struct drm_device *dev, u64 offset, u64 length, u64 mm_offset,
+	       struct nouveau_vm **pvm)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_vm *vm;
+	u64 mm_length = (offset + length) - mm_offset;
+	u32 block, pgt_bits;
+	int ret;
+
+	vm = kzalloc(sizeof(*vm), GFP_KERNEL);
+	if (!vm)
+		return -ENOMEM;
+
+	if (dev_priv->card_type == NV_50) {
+		vm->map_pgt = nv50_vm_map_pgt;
+		vm->map = nv50_vm_map;
+		vm->map_sg = nv50_vm_map_sg;
+		vm->unmap = nv50_vm_unmap;
+		vm->flush = nv50_vm_flush;
+		vm->spg_shift = 12;
+		vm->lpg_shift = 16;
+
+		pgt_bits = 29;
+		block = (1 << pgt_bits);
+		if (length < block)
+			block = length;
+
+	} else
+	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;
+		vm->unmap = nvc0_vm_unmap;
+		vm->flush = nvc0_vm_flush;
+		vm->spg_shift = 12;
+		vm->lpg_shift = 17;
+		pgt_bits = 27;
+
+		/* Should be 4096 everywhere, this is a hack that's
+		 * currently necessary to avoid an elusive bug that
+		 * causes corruption when mixing small/large pages
+		 */
+		if (length < (1ULL << 40))
+			block = 4096;
+		else {
+			block = (1 << pgt_bits);
+			if (length < block)
+				block = length;
+		}
+	} else {
+		kfree(vm);
+		return -ENOSYS;
+	}
+
+	vm->fpde   = offset >> pgt_bits;
+	vm->lpde   = (offset + length - 1) >> pgt_bits;
+	vm->pgt = kcalloc(vm->lpde - vm->fpde + 1, sizeof(*vm->pgt), GFP_KERNEL);
+	if (!vm->pgt) {
+		kfree(vm);
+		return -ENOMEM;
+	}
+
+	INIT_LIST_HEAD(&vm->pgd_list);
+	vm->dev = dev;
+	vm->refcount = 1;
+	vm->pgt_bits = pgt_bits - 12;
+
+	ret = nouveau_mm_init(&vm->mm, mm_offset >> 12, mm_length >> 12,
+			      block >> 12);
+	if (ret) {
+		kfree(vm);
+		return ret;
+	}
+
+	*pvm = vm;
+	return 0;
+}
+
+static int
+nouveau_vm_link(struct nouveau_vm *vm, struct nouveau_gpuobj *pgd)
+{
+	struct nouveau_vm_pgd *vpgd;
+	int i;
+
+	if (!pgd)
+		return 0;
+
+	vpgd = kzalloc(sizeof(*vpgd), GFP_KERNEL);
+	if (!vpgd)
+		return -ENOMEM;
+
+	nouveau_gpuobj_ref(pgd, &vpgd->obj);
+
+	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);
+	return 0;
+}
+
+static void
+nouveau_vm_unlink(struct nouveau_vm *vm, struct nouveau_gpuobj *pgd)
+{
+	struct nouveau_vm_pgd *vpgd, *tmp;
+
+	if (!pgd)
+		return;
+
+	mutex_lock(&vm->mm->mutex);
+	list_for_each_entry_safe(vpgd, tmp, &vm->pgd_list, head) {
+		if (vpgd->obj != pgd)
+			continue;
+
+		list_del(&vpgd->head);
+		nouveau_gpuobj_ref(NULL, &vpgd->obj);
+		kfree(vpgd);
+	}
+	mutex_unlock(&vm->mm->mutex);
+}
+
+static void
+nouveau_vm_del(struct nouveau_vm *vm)
+{
+	struct nouveau_vm_pgd *vpgd, *tmp;
+
+	list_for_each_entry_safe(vpgd, tmp, &vm->pgd_list, head) {
+		nouveau_vm_unlink(vm, vpgd->obj);
+	}
+	WARN_ON(nouveau_mm_fini(&vm->mm) != 0);
+
+	kfree(vm->pgt);
+	kfree(vm);
+}
+
+int
+nouveau_vm_ref(struct nouveau_vm *ref, struct nouveau_vm **ptr,
+	       struct nouveau_gpuobj *pgd)
+{
+	struct nouveau_vm *vm;
+	int ret;
+
+	vm = ref;
+	if (vm) {
+		ret = nouveau_vm_link(vm, pgd);
+		if (ret)
+			return ret;
+
+		vm->refcount++;
+	}
+
+	vm = *ptr;
+	*ptr = ref;
+
+	if (vm) {
+		nouveau_vm_unlink(vm, pgd);
+
+		if (--vm->refcount == 0)
+			nouveau_vm_del(vm);
+	}
+
+	return 0;
+}
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nouveau_vm.h linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nouveau_vm.h
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nouveau_vm.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nouveau_vm.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,113 @@
+/*
+ * Copyright 2010 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
+ */
+
+#ifndef __NOUVEAU_VM_H__
+#define __NOUVEAU_VM_H__
+
+#include "drmP.h"
+
+#include "nouveau_drv.h"
+#include "nouveau_mm.h"
+
+struct nouveau_vm_pgt {
+	struct nouveau_gpuobj *obj[2];
+	u32 refcount[2];
+};
+
+struct nouveau_vm_pgd {
+	struct list_head head;
+	struct nouveau_gpuobj *obj;
+};
+
+struct nouveau_vma {
+	struct nouveau_vm *vm;
+	struct nouveau_mm_node *node;
+	u64 offset;
+	u32 access;
+};
+
+struct nouveau_vm {
+	struct drm_device *dev;
+	struct nouveau_mm *mm;
+	int refcount;
+
+	struct list_head pgd_list;
+	atomic_t pgraph_refs;
+	atomic_t pcrypt_refs;
+
+	struct nouveau_vm_pgt *pgt;
+	u32 fpde;
+	u32 lpde;
+
+	u32 pgt_bits;
+	u8  spg_shift;
+	u8  lpg_shift;
+
+	void (*map_pgt)(struct nouveau_gpuobj *pgd, u32 pde,
+			struct nouveau_gpuobj *pgt[2]);
+	void (*map)(struct nouveau_vma *, struct nouveau_gpuobj *,
+		    struct nouveau_vram *, u32 pte, u32 cnt, u64 phys);
+	void (*map_sg)(struct nouveau_vma *, struct nouveau_gpuobj *,
+		       u32 pte, dma_addr_t *, u32 cnt);
+	void (*unmap)(struct nouveau_gpuobj *pgt, u32 pte, u32 cnt);
+	void (*flush)(struct nouveau_vm *);
+};
+
+/* nouveau_vm.c */
+int  nouveau_vm_new(struct drm_device *, u64 offset, u64 length, u64 mm_offset,
+		    struct nouveau_vm **);
+int  nouveau_vm_ref(struct nouveau_vm *, struct nouveau_vm **,
+		    struct nouveau_gpuobj *pgd);
+int  nouveau_vm_get(struct nouveau_vm *, u64 size, u32 page_shift,
+		    u32 access, struct nouveau_vma *);
+void nouveau_vm_put(struct nouveau_vma *);
+void nouveau_vm_map(struct nouveau_vma *, struct nouveau_vram *);
+void nouveau_vm_map_at(struct nouveau_vma *, u64 offset, struct nouveau_vram *);
+void nouveau_vm_unmap(struct nouveau_vma *);
+void nouveau_vm_unmap_at(struct nouveau_vma *, u64 offset, u64 length);
+void nouveau_vm_map_sg(struct nouveau_vma *, u64 offset, u64 length,
+		       dma_addr_t *);
+
+/* nv50_vm.c */
+void nv50_vm_map_pgt(struct nouveau_gpuobj *pgd, u32 pde,
+		     struct nouveau_gpuobj *pgt[2]);
+void nv50_vm_map(struct nouveau_vma *, struct nouveau_gpuobj *,
+		 struct nouveau_vram *, u32 pte, u32 cnt, u64 phys);
+void nv50_vm_map_sg(struct nouveau_vma *, struct nouveau_gpuobj *,
+		    u32 pte, dma_addr_t *, u32 cnt);
+void nv50_vm_unmap(struct nouveau_gpuobj *, u32 pte, u32 cnt);
+void nv50_vm_flush(struct nouveau_vm *);
+void nv50_vm_flush_engine(struct drm_device *, int engine);
+
+/* nvc0_vm.c */
+void nvc0_vm_map_pgt(struct nouveau_gpuobj *pgd, u32 pde,
+		     struct nouveau_gpuobj *pgt[2]);
+void nvc0_vm_map(struct nouveau_vma *, struct nouveau_gpuobj *,
+		 struct nouveau_vram *, u32 pte, u32 cnt, u64 phys);
+void nvc0_vm_map_sg(struct nouveau_vma *, struct nouveau_gpuobj *,
+		    u32 pte, dma_addr_t *, u32 cnt);
+void nvc0_vm_unmap(struct nouveau_gpuobj *, u32 pte, u32 cnt);
+void nvc0_vm_flush(struct nouveau_vm *);
+
+#endif
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nv04_crtc.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nv04_crtc.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nv04_crtc.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nv04_crtc.c	2011-03-14 21:20:32.000000000 -0400
@@ -551,7 +551,10 @@ nv_crtc_mode_set_regs(struct drm_crtc *c
 	if (dev_priv->card_type >= NV_30)
 		regp->gpio_ext = NVReadCRTC(dev, 0, NV_PCRTC_GPIO_EXT);
 
-	regp->crtc_cfg = NV_PCRTC_CONFIG_START_ADDRESS_HSYNC;
+	if (dev_priv->card_type >= NV_10)
+		regp->crtc_cfg = NV10_PCRTC_CONFIG_START_ADDRESS_HSYNC;
+	else
+		regp->crtc_cfg = NV04_PCRTC_CONFIG_START_ADDRESS_HSYNC;
 
 	/* Some misc regs */
 	if (dev_priv->card_type == NV_40) {
@@ -669,6 +672,7 @@ static void nv_crtc_prepare(struct drm_c
 	if (nv_two_heads(dev))
 		NVSetOwner(dev, nv_crtc->index);
 
+	drm_vblank_pre_modeset(dev, nv_crtc->index);
 	funcs->dpms(crtc, DRM_MODE_DPMS_OFF);
 
 	NVBlankScreen(dev, nv_crtc->index, true);
@@ -701,6 +705,7 @@ static void nv_crtc_commit(struct drm_cr
 #endif
 
 	funcs->dpms(crtc, DRM_MODE_DPMS_ON);
+	drm_vblank_post_modeset(dev, nv_crtc->index);
 }
 
 static void nv_crtc_destroy(struct drm_crtc *crtc)
@@ -986,6 +991,7 @@ static const struct drm_crtc_funcs nv04_
 	.cursor_move = nv04_crtc_cursor_move,
 	.gamma_set = nv_crtc_gamma_set,
 	.set_config = drm_crtc_helper_set_config,
+	.page_flip = nouveau_crtc_page_flip,
 	.destroy = nv_crtc_destroy,
 };
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nv04_dac.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nv04_dac.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nv04_dac.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nv04_dac.c	2011-03-14 21:20:32.000000000 -0400
@@ -74,14 +74,14 @@ static int sample_load_twice(struct drm_
 		 * use a 10ms timeout (guards against crtc being inactive, in
 		 * which case blank state would never change)
 		 */
-		if (!nouveau_wait_until(dev, 10000000, NV_PRMCIO_INP0__COLOR,
-					0x00000001, 0x00000000))
+		if (!nouveau_wait_eq(dev, 10000000, NV_PRMCIO_INP0__COLOR,
+				     0x00000001, 0x00000000))
 			return -EBUSY;
-		if (!nouveau_wait_until(dev, 10000000, NV_PRMCIO_INP0__COLOR,
-					0x00000001, 0x00000001))
+		if (!nouveau_wait_eq(dev, 10000000, NV_PRMCIO_INP0__COLOR,
+				     0x00000001, 0x00000001))
 			return -EBUSY;
-		if (!nouveau_wait_until(dev, 10000000, NV_PRMCIO_INP0__COLOR,
-					0x00000001, 0x00000000))
+		if (!nouveau_wait_eq(dev, 10000000, NV_PRMCIO_INP0__COLOR,
+				     0x00000001, 0x00000000))
 			return -EBUSY;
 
 		udelay(100);
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nv04_dfp.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nv04_dfp.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nv04_dfp.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nv04_dfp.c	2011-03-14 21:20:32.000000000 -0400
@@ -342,8 +342,8 @@ static void nv04_dfp_mode_set(struct drm
 	if (nv_encoder->dcb->type == OUTPUT_LVDS) {
 		bool duallink, dummy;
 
-		nouveau_bios_parse_lvds_table(dev, nv_connector->native_mode->
-					      clock, &duallink, &dummy);
+		nouveau_bios_parse_lvds_table(dev, output_mode->clock,
+					      &duallink, &dummy);
 		if (duallink)
 			regp->fp_control |= (8 << 28);
 	} else
@@ -518,8 +518,6 @@ static void nv04_lvds_dpms(struct drm_en
 		return;
 
 	if (nv_encoder->dcb->lvdsconf.use_power_scripts) {
-		struct nouveau_connector *nv_connector = nouveau_encoder_connector_get(nv_encoder);
-
 		/* when removing an output, crtc may not be set, but PANEL_OFF
 		 * must still be run
 		 */
@@ -527,12 +525,8 @@ static void nv04_lvds_dpms(struct drm_en
 			   nv04_dfp_get_bound_head(dev, nv_encoder->dcb);
 
 		if (mode == DRM_MODE_DPMS_ON) {
-			if (!nv_connector->native_mode) {
-				NV_ERROR(dev, "Not turning on LVDS without native mode\n");
-				return;
-			}
 			call_lvds_script(dev, nv_encoder->dcb, head,
-					 LVDS_PANEL_ON, nv_connector->native_mode->clock);
+					 LVDS_PANEL_ON, nv_encoder->mode.clock);
 		} else
 			/* pxclk of 0 is fine for PANEL_OFF, and for a
 			 * disconnected LVDS encoder there is no native_mode
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nv04_display.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nv04_display.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nv04_display.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nv04_display.c	2011-03-14 21:20:32.000000000 -0400
@@ -32,6 +32,9 @@
 #include "nouveau_encoder.h"
 #include "nouveau_connector.h"
 
+static void nv04_vblank_crtc0_isr(struct drm_device *);
+static void nv04_vblank_crtc1_isr(struct drm_device *);
+
 static void
 nv04_display_store_initial_head_owner(struct drm_device *dev)
 {
@@ -197,6 +200,8 @@ nv04_display_create(struct drm_device *d
 		func->save(encoder);
 	}
 
+	nouveau_irq_register(dev, 24, nv04_vblank_crtc0_isr);
+	nouveau_irq_register(dev, 25, nv04_vblank_crtc1_isr);
 	return 0;
 }
 
@@ -208,6 +213,9 @@ nv04_display_destroy(struct drm_device *
 
 	NV_DEBUG_KMS(dev, "\n");
 
+	nouveau_irq_unregister(dev, 24);
+	nouveau_irq_unregister(dev, 25);
+
 	/* Turn every CRTC off. */
 	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
 		struct drm_mode_set modeset = {
@@ -258,3 +266,16 @@ nv04_display_init(struct drm_device *dev
 	return 0;
 }
 
+static void
+nv04_vblank_crtc0_isr(struct drm_device *dev)
+{
+	nv_wr32(dev, NV_CRTC0_INTSTAT, NV_CRTC_INTR_VBLANK);
+	drm_handle_vblank(dev, 0);
+}
+
+static void
+nv04_vblank_crtc1_isr(struct drm_device *dev)
+{
+	nv_wr32(dev, NV_CRTC1_INTSTAT, NV_CRTC_INTR_VBLANK);
+	drm_handle_vblank(dev, 1);
+}
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nv04_fbcon.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nv04_fbcon.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nv04_fbcon.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nv04_fbcon.c	2011-03-14 21:20:32.000000000 -0400
@@ -28,52 +28,39 @@
 #include "nouveau_ramht.h"
 #include "nouveau_fbcon.h"
 
-void
+int
 nv04_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region)
 {
 	struct nouveau_fbdev *nfbdev = info->par;
 	struct drm_device *dev = nfbdev->dev;
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct nouveau_channel *chan = dev_priv->channel;
+	int ret;
 
-	if (info->state != FBINFO_STATE_RUNNING)
-		return;
-
-	if (!(info->flags & FBINFO_HWACCEL_DISABLED) && RING_SPACE(chan, 4)) {
-		nouveau_fbcon_gpu_lockup(info);
-	}
-
-	if (info->flags & FBINFO_HWACCEL_DISABLED) {
-		cfb_copyarea(info, region);
-		return;
-	}
+	ret = RING_SPACE(chan, 4);
+	if (ret)
+		return ret;
 
 	BEGIN_RING(chan, NvSubImageBlit, 0x0300, 3);
 	OUT_RING(chan, (region->sy << 16) | region->sx);
 	OUT_RING(chan, (region->dy << 16) | region->dx);
 	OUT_RING(chan, (region->height << 16) | region->width);
 	FIRE_RING(chan);
+	return 0;
 }
 
-void
+int
 nv04_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
 {
 	struct nouveau_fbdev *nfbdev = info->par;
 	struct drm_device *dev = nfbdev->dev;
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct nouveau_channel *chan = dev_priv->channel;
+	int ret;
 
-	if (info->state != FBINFO_STATE_RUNNING)
-		return;
-
-	if (!(info->flags & FBINFO_HWACCEL_DISABLED) && RING_SPACE(chan, 7)) {
-		nouveau_fbcon_gpu_lockup(info);
-	}
-
-	if (info->flags & FBINFO_HWACCEL_DISABLED) {
-		cfb_fillrect(info, rect);
-		return;
-	}
+	ret = RING_SPACE(chan, 7);
+	if (ret)
+		return ret;
 
 	BEGIN_RING(chan, NvSubGdiRect, 0x02fc, 1);
 	OUT_RING(chan, (rect->rop != ROP_COPY) ? 1 : 3);
@@ -87,9 +74,10 @@ nv04_fbcon_fillrect(struct fb_info *info
 	OUT_RING(chan, (rect->dx << 16) | rect->dy);
 	OUT_RING(chan, (rect->width << 16) | rect->height);
 	FIRE_RING(chan);
+	return 0;
 }
 
-void
+int
 nv04_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
 {
 	struct nouveau_fbdev *nfbdev = info->par;
@@ -101,23 +89,14 @@ nv04_fbcon_imageblit(struct fb_info *inf
 	uint32_t dsize;
 	uint32_t width;
 	uint32_t *data = (uint32_t *)image->data;
+	int ret;
 
-	if (info->state != FBINFO_STATE_RUNNING)
-		return;
-
-	if (image->depth != 1) {
-		cfb_imageblit(info, image);
-		return;
-	}
-
-	if (!(info->flags & FBINFO_HWACCEL_DISABLED) && RING_SPACE(chan, 8)) {
-		nouveau_fbcon_gpu_lockup(info);
-	}
+	if (image->depth != 1)
+		return -ENODEV;
 
-	if (info->flags & FBINFO_HWACCEL_DISABLED) {
-		cfb_imageblit(info, image);
-		return;
-	}
+	ret = RING_SPACE(chan, 8);
+	if (ret)
+		return ret;
 
 	width = ALIGN(image->width, 8);
 	dsize = ALIGN(width * image->height, 32) >> 5;
@@ -144,11 +123,9 @@ nv04_fbcon_imageblit(struct fb_info *inf
 	while (dsize) {
 		int iter_len = dsize > 128 ? 128 : dsize;
 
-		if (RING_SPACE(chan, iter_len + 1)) {
-			nouveau_fbcon_gpu_lockup(info);
-			cfb_imageblit(info, image);
-			return;
-		}
+		ret = RING_SPACE(chan, iter_len + 1);
+		if (ret)
+			return ret;
 
 		BEGIN_RING(chan, NvSubGdiRect, 0x0c00, iter_len);
 		OUT_RINGp(chan, data, iter_len);
@@ -157,22 +134,7 @@ nv04_fbcon_imageblit(struct fb_info *inf
 	}
 
 	FIRE_RING(chan);
-}
-
-static int
-nv04_fbcon_grobj_new(struct drm_device *dev, int class, uint32_t handle)
-{
-	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nouveau_gpuobj *obj = NULL;
-	int ret;
-
-	ret = nouveau_gpuobj_gr_new(dev_priv->channel, class, &obj);
-	if (ret)
-		return ret;
-
-	ret = nouveau_ramht_insert(dev_priv->channel, handle, obj);
-	nouveau_gpuobj_ref(NULL, &obj);
-	return ret;
+	return 0;
 }
 
 int
@@ -214,29 +176,31 @@ nv04_fbcon_accel_init(struct fb_info *in
 		return -EINVAL;
 	}
 
-	ret = nv04_fbcon_grobj_new(dev, dev_priv->card_type >= NV_10 ?
-				   0x0062 : 0x0042, NvCtxSurf2D);
+	ret = nouveau_gpuobj_gr_new(chan, NvCtxSurf2D,
+				    dev_priv->card_type >= NV_10 ?
+				    0x0062 : 0x0042);
 	if (ret)
 		return ret;
 
-	ret = nv04_fbcon_grobj_new(dev, 0x0019, NvClipRect);
+	ret = nouveau_gpuobj_gr_new(chan, NvClipRect, 0x0019);
 	if (ret)
 		return ret;
 
-	ret = nv04_fbcon_grobj_new(dev, 0x0043, NvRop);
+	ret = nouveau_gpuobj_gr_new(chan, NvRop, 0x0043);
 	if (ret)
 		return ret;
 
-	ret = nv04_fbcon_grobj_new(dev, 0x0044, NvImagePatt);
+	ret = nouveau_gpuobj_gr_new(chan, NvImagePatt, 0x0044);
 	if (ret)
 		return ret;
 
-	ret = nv04_fbcon_grobj_new(dev, 0x004a, NvGdiRect);
+	ret = nouveau_gpuobj_gr_new(chan, NvGdiRect, 0x004a);
 	if (ret)
 		return ret;
 
-	ret = nv04_fbcon_grobj_new(dev, dev_priv->chipset >= 0x11 ?
-				   0x009f : 0x005f, NvImageBlit);
+	ret = nouveau_gpuobj_gr_new(chan, NvImageBlit,
+				    dev_priv->chipset >= 0x11 ?
+				    0x009f : 0x005f);
 	if (ret)
 		return ret;
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nv04_fifo.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nv04_fifo.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nv04_fifo.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nv04_fifo.c	2011-03-14 21:20:32.000000000 -0400
@@ -28,6 +28,7 @@
 #include "drm.h"
 #include "nouveau_drv.h"
 #include "nouveau_ramht.h"
+#include "nouveau_util.h"
 
 #define NV04_RAMFC(c) (dev_priv->ramfc->pinst + ((c) * NV04_RAMFC__SIZE))
 #define NV04_RAMFC__SIZE 32
@@ -128,6 +129,11 @@ nv04_fifo_create_context(struct nouveau_
 	if (ret)
 		return ret;
 
+	chan->user = ioremap(pci_resource_start(dev->pdev, 0) +
+			     NV03_USER(chan->id), PAGE_SIZE);
+	if (!chan->user)
+		return -ENOMEM;
+
 	spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
 
 	/* Setup initial state */
@@ -151,10 +157,31 @@ void
 nv04_fifo_destroy_context(struct nouveau_channel *chan)
 {
 	struct drm_device *dev = chan->dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo;
+	unsigned long flags;
 
-	nv_wr32(dev, NV04_PFIFO_MODE,
-		nv_rd32(dev, NV04_PFIFO_MODE) & ~(1 << chan->id));
+	spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
+	pfifo->reassign(dev, false);
+
+	/* Unload the context if it's the currently active one */
+	if (pfifo->channel_id(dev) == chan->id) {
+		pfifo->disable(dev);
+		pfifo->unload_context(dev);
+		pfifo->enable(dev);
+	}
+
+	/* Keep it from being rescheduled */
+	nv_mask(dev, NV04_PFIFO_MODE, 1 << chan->id, 0);
 
+	pfifo->reassign(dev, true);
+	spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
+
+	/* Free the channel resources */
+	if (chan->user) {
+		iounmap(chan->user);
+		chan->user = NULL;
+	}
 	nouveau_gpuobj_ref(NULL, &chan->ramfc);
 }
 
@@ -208,7 +235,7 @@ nv04_fifo_unload_context(struct drm_devi
 	if (chid < 0 || chid >= dev_priv->engine.fifo.channels)
 		return 0;
 
-	chan = dev_priv->fifos[chid];
+	chan = dev_priv->channels.ptr[chid];
 	if (!chan) {
 		NV_ERROR(dev, "Inactive channel on PFIFO: %d\n", chid);
 		return -EINVAL;
@@ -267,6 +294,7 @@ nv04_fifo_init_ramxx(struct drm_device *
 static void
 nv04_fifo_init_intr(struct drm_device *dev)
 {
+	nouveau_irq_register(dev, 8, nv04_fifo_isr);
 	nv_wr32(dev, 0x002100, 0xffffffff);
 	nv_wr32(dev, 0x002140, 0xffffffff);
 }
@@ -289,7 +317,7 @@ nv04_fifo_init(struct drm_device *dev)
 	pfifo->reassign(dev, true);
 
 	for (i = 0; i < dev_priv->engine.fifo.channels; i++) {
-		if (dev_priv->fifos[i]) {
+		if (dev_priv->channels.ptr[i]) {
 			uint32_t mode = nv_rd32(dev, NV04_PFIFO_MODE);
 			nv_wr32(dev, NV04_PFIFO_MODE, mode | (1 << i));
 		}
@@ -298,3 +326,207 @@ nv04_fifo_init(struct drm_device *dev)
 	return 0;
 }
 
+void
+nv04_fifo_fini(struct drm_device *dev)
+{
+	nv_wr32(dev, 0x2140, 0x00000000);
+	nouveau_irq_unregister(dev, 8);
+}
+
+static bool
+nouveau_fifo_swmthd(struct drm_device *dev, u32 chid, u32 addr, u32 data)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_channel *chan = NULL;
+	struct nouveau_gpuobj *obj;
+	unsigned long flags;
+	const int subc = (addr >> 13) & 0x7;
+	const int mthd = addr & 0x1ffc;
+	bool handled = false;
+	u32 engine;
+
+	spin_lock_irqsave(&dev_priv->channels.lock, flags);
+	if (likely(chid >= 0 && chid < dev_priv->engine.fifo.channels))
+		chan = dev_priv->channels.ptr[chid];
+	if (unlikely(!chan))
+		goto out;
+
+	switch (mthd) {
+	case 0x0000: /* bind object to subchannel */
+		obj = nouveau_ramht_find(chan, data);
+		if (unlikely(!obj || obj->engine != NVOBJ_ENGINE_SW))
+			break;
+
+		chan->sw_subchannel[subc] = obj->class;
+		engine = 0x0000000f << (subc * 4);
+
+		nv_mask(dev, NV04_PFIFO_CACHE1_ENGINE, engine, 0x00000000);
+		handled = true;
+		break;
+	default:
+		engine = nv_rd32(dev, NV04_PFIFO_CACHE1_ENGINE);
+		if (unlikely(((engine >> (subc * 4)) & 0xf) != 0))
+			break;
+
+		if (!nouveau_gpuobj_mthd_call(chan, chan->sw_subchannel[subc],
+					      mthd, data))
+			handled = true;
+		break;
+	}
+
+out:
+	spin_unlock_irqrestore(&dev_priv->channels.lock, flags);
+	return handled;
+}
+
+void
+nv04_fifo_isr(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_engine *engine = &dev_priv->engine;
+	uint32_t status, reassign;
+	int cnt = 0;
+
+	reassign = nv_rd32(dev, NV03_PFIFO_CACHES) & 1;
+	while ((status = nv_rd32(dev, NV03_PFIFO_INTR_0)) && (cnt++ < 100)) {
+		uint32_t chid, get;
+
+		nv_wr32(dev, NV03_PFIFO_CACHES, 0);
+
+		chid = engine->fifo.channel_id(dev);
+		get  = nv_rd32(dev, NV03_PFIFO_CACHE1_GET);
+
+		if (status & NV_PFIFO_INTR_CACHE_ERROR) {
+			uint32_t mthd, data;
+			int ptr;
+
+			/* NV_PFIFO_CACHE1_GET actually goes to 0xffc before
+			 * wrapping on my G80 chips, but CACHE1 isn't big
+			 * enough for this much data.. Tests show that it
+			 * wraps around to the start at GET=0x800.. No clue
+			 * as to why..
+			 */
+			ptr = (get & 0x7ff) >> 2;
+
+			if (dev_priv->card_type < NV_40) {
+				mthd = nv_rd32(dev,
+					NV04_PFIFO_CACHE1_METHOD(ptr));
+				data = nv_rd32(dev,
+					NV04_PFIFO_CACHE1_DATA(ptr));
+			} else {
+				mthd = nv_rd32(dev,
+					NV40_PFIFO_CACHE1_METHOD(ptr));
+				data = nv_rd32(dev,
+					NV40_PFIFO_CACHE1_DATA(ptr));
+			}
+
+			if (!nouveau_fifo_swmthd(dev, chid, mthd, data)) {
+				NV_INFO(dev, "PFIFO_CACHE_ERROR - Ch %d/%d "
+					     "Mthd 0x%04x Data 0x%08x\n",
+					chid, (mthd >> 13) & 7, mthd & 0x1ffc,
+					data);
+			}
+
+			nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_PUSH, 0);
+			nv_wr32(dev, NV03_PFIFO_INTR_0,
+						NV_PFIFO_INTR_CACHE_ERROR);
+
+			nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH0,
+				nv_rd32(dev, NV03_PFIFO_CACHE1_PUSH0) & ~1);
+			nv_wr32(dev, NV03_PFIFO_CACHE1_GET, get + 4);
+			nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH0,
+				nv_rd32(dev, NV03_PFIFO_CACHE1_PUSH0) | 1);
+			nv_wr32(dev, NV04_PFIFO_CACHE1_HASH, 0);
+
+			nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_PUSH,
+				nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_PUSH) | 1);
+			nv_wr32(dev, NV04_PFIFO_CACHE1_PULL0, 1);
+
+			status &= ~NV_PFIFO_INTR_CACHE_ERROR;
+		}
+
+		if (status & NV_PFIFO_INTR_DMA_PUSHER) {
+			u32 dma_get = nv_rd32(dev, 0x003244);
+			u32 dma_put = nv_rd32(dev, 0x003240);
+			u32 push = nv_rd32(dev, 0x003220);
+			u32 state = nv_rd32(dev, 0x003228);
+
+			if (dev_priv->card_type == NV_50) {
+				u32 ho_get = nv_rd32(dev, 0x003328);
+				u32 ho_put = nv_rd32(dev, 0x003320);
+				u32 ib_get = nv_rd32(dev, 0x003334);
+				u32 ib_put = nv_rd32(dev, 0x003330);
+
+				if (nouveau_ratelimit())
+					NV_INFO(dev, "PFIFO_DMA_PUSHER - Ch %d Get 0x%02x%08x "
+					     "Put 0x%02x%08x IbGet 0x%08x IbPut 0x%08x "
+					     "State 0x%08x Push 0x%08x\n",
+						chid, ho_get, dma_get, ho_put,
+						dma_put, ib_get, ib_put, state,
+						push);
+
+				/* METHOD_COUNT, in DMA_STATE on earlier chipsets */
+				nv_wr32(dev, 0x003364, 0x00000000);
+				if (dma_get != dma_put || ho_get != ho_put) {
+					nv_wr32(dev, 0x003244, dma_put);
+					nv_wr32(dev, 0x003328, ho_put);
+				} else
+				if (ib_get != ib_put) {
+					nv_wr32(dev, 0x003334, ib_put);
+				}
+			} else {
+				NV_INFO(dev, "PFIFO_DMA_PUSHER - Ch %d Get 0x%08x "
+					     "Put 0x%08x State 0x%08x Push 0x%08x\n",
+					chid, dma_get, dma_put, state, push);
+
+				if (dma_get != dma_put)
+					nv_wr32(dev, 0x003244, dma_put);
+			}
+
+			nv_wr32(dev, 0x003228, 0x00000000);
+			nv_wr32(dev, 0x003220, 0x00000001);
+			nv_wr32(dev, 0x002100, NV_PFIFO_INTR_DMA_PUSHER);
+			status &= ~NV_PFIFO_INTR_DMA_PUSHER;
+		}
+
+		if (status & NV_PFIFO_INTR_SEMAPHORE) {
+			uint32_t sem;
+
+			status &= ~NV_PFIFO_INTR_SEMAPHORE;
+			nv_wr32(dev, NV03_PFIFO_INTR_0,
+				NV_PFIFO_INTR_SEMAPHORE);
+
+			sem = nv_rd32(dev, NV10_PFIFO_CACHE1_SEMAPHORE);
+			nv_wr32(dev, NV10_PFIFO_CACHE1_SEMAPHORE, sem | 0x1);
+
+			nv_wr32(dev, NV03_PFIFO_CACHE1_GET, get + 4);
+			nv_wr32(dev, NV04_PFIFO_CACHE1_PULL0, 1);
+		}
+
+		if (dev_priv->card_type == NV_50) {
+			if (status & 0x00000010) {
+				nv50_fb_vm_trap(dev, 1, "PFIFO_BAR_FAULT");
+				status &= ~0x00000010;
+				nv_wr32(dev, 0x002100, 0x00000010);
+			}
+		}
+
+		if (status) {
+			if (nouveau_ratelimit())
+				NV_INFO(dev, "PFIFO_INTR 0x%08x - Ch %d\n",
+					status, chid);
+			nv_wr32(dev, NV03_PFIFO_INTR_0, status);
+			status = 0;
+		}
+
+		nv_wr32(dev, NV03_PFIFO_CACHES, reassign);
+	}
+
+	if (status) {
+		NV_INFO(dev, "PFIFO still angry after %d spins, halt\n", cnt);
+		nv_wr32(dev, 0x2140, 0);
+		nv_wr32(dev, 0x140, 0);
+	}
+
+	nv_wr32(dev, NV03_PMC_INTR_0, NV_PMC_INTR_0_PFIFO_PENDING);
+}
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nv04_graph.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nv04_graph.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nv04_graph.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nv04_graph.c	2011-03-14 21:20:32.000000000 -0400
@@ -26,6 +26,11 @@
 #include "drm.h"
 #include "nouveau_drm.h"
 #include "nouveau_drv.h"
+#include "nouveau_hw.h"
+#include "nouveau_util.h"
+
+static int  nv04_graph_register(struct drm_device *dev);
+static void nv04_graph_isr(struct drm_device *dev);
 
 static uint32_t nv04_graph_ctx_regs[] = {
 	0x0040053c,
@@ -357,10 +362,10 @@ nv04_graph_channel(struct drm_device *de
 	if (chid >= dev_priv->engine.fifo.channels)
 		return NULL;
 
-	return dev_priv->fifos[chid];
+	return dev_priv->channels.ptr[chid];
 }
 
-void
+static void
 nv04_graph_context_switch(struct drm_device *dev)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
@@ -368,7 +373,6 @@ nv04_graph_context_switch(struct drm_dev
 	struct nouveau_channel *chan = NULL;
 	int chid;
 
-	pgraph->fifo_access(dev, false);
 	nouveau_wait_for_idle(dev);
 
 	/* If previous context is valid, we need to save it */
@@ -376,11 +380,9 @@ nv04_graph_context_switch(struct drm_dev
 
 	/* Load context for next channel */
 	chid = dev_priv->engine.fifo.channel_id(dev);
-	chan = dev_priv->fifos[chid];
+	chan = dev_priv->channels.ptr[chid];
 	if (chan)
 		nv04_graph_load_context(chan);
-
-	pgraph->fifo_access(dev, true);
 }
 
 static uint32_t *ctx_reg(struct graph_state *ctx, uint32_t reg)
@@ -412,10 +414,25 @@ int nv04_graph_create_context(struct nou
 
 void nv04_graph_destroy_context(struct nouveau_channel *chan)
 {
+	struct drm_device *dev = chan->dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
 	struct graph_state *pgraph_ctx = chan->pgraph_ctx;
+	unsigned long flags;
+
+	spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
+	pgraph->fifo_access(dev, false);
+
+	/* Unload the context if it's the currently active one */
+	if (pgraph->channel(dev) == chan)
+		pgraph->unload_context(dev);
 
+	/* Free the context resources */
 	kfree(pgraph_ctx);
 	chan->pgraph_ctx = NULL;
+
+	pgraph->fifo_access(dev, true);
+	spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
 }
 
 int nv04_graph_load_context(struct nouveau_channel *chan)
@@ -468,13 +485,19 @@ int nv04_graph_init(struct drm_device *d
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	uint32_t tmp;
+	int ret;
 
 	nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) &
 			~NV_PMC_ENABLE_PGRAPH);
 	nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) |
 			 NV_PMC_ENABLE_PGRAPH);
 
+	ret = nv04_graph_register(dev);
+	if (ret)
+		return ret;
+
 	/* Enable PGRAPH interrupts */
+	nouveau_irq_register(dev, 12, nv04_graph_isr);
 	nv_wr32(dev, NV03_PGRAPH_INTR, 0xFFFFFFFF);
 	nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0xFFFFFFFF);
 
@@ -510,6 +533,8 @@ int nv04_graph_init(struct drm_device *d
 
 void nv04_graph_takedown(struct drm_device *dev)
 {
+	nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0x00000000);
+	nouveau_irq_unregister(dev, 12);
 }
 
 void
@@ -524,13 +549,27 @@ nv04_graph_fifo_access(struct drm_device
 }
 
 static int
-nv04_graph_mthd_set_ref(struct nouveau_channel *chan, int grclass,
-			int mthd, uint32_t data)
+nv04_graph_mthd_set_ref(struct nouveau_channel *chan,
+			u32 class, u32 mthd, u32 data)
 {
 	atomic_set(&chan->fence.last_sequence_irq, data);
 	return 0;
 }
 
+int
+nv04_graph_mthd_page_flip(struct nouveau_channel *chan,
+			  u32 class, u32 mthd, u32 data)
+{
+	struct drm_device *dev = chan->dev;
+	struct nouveau_page_flip_state s;
+
+	if (!nouveau_finish_page_flip(chan, &s))
+		nv_set_crtc_base(dev, s.crtc,
+				 s.offset + s.y * s.pitch + s.x * s.bpp / 8);
+
+	return 0;
+}
+
 /*
  * Software methods, why they are needed, and how they all work:
  *
@@ -606,12 +645,12 @@ nv04_graph_mthd_set_ref(struct nouveau_c
  */
 
 static void
-nv04_graph_set_ctx1(struct nouveau_channel *chan, uint32_t mask, uint32_t value)
+nv04_graph_set_ctx1(struct nouveau_channel *chan, u32 mask, u32 value)
 {
 	struct drm_device *dev = chan->dev;
-	uint32_t instance = (nv_rd32(dev, NV04_PGRAPH_CTX_SWITCH4) & 0xffff) << 4;
+	u32 instance = (nv_rd32(dev, NV04_PGRAPH_CTX_SWITCH4) & 0xffff) << 4;
 	int subc = (nv_rd32(dev, NV04_PGRAPH_TRAPPED_ADDR) >> 13) & 0x7;
-	uint32_t tmp;
+	u32 tmp;
 
 	tmp  = nv_ri32(dev, instance);
 	tmp &= ~mask;
@@ -623,11 +662,11 @@ nv04_graph_set_ctx1(struct nouveau_chann
 }
 
 static void
-nv04_graph_set_ctx_val(struct nouveau_channel *chan, uint32_t mask, uint32_t value)
+nv04_graph_set_ctx_val(struct nouveau_channel *chan, u32 mask, u32 value)
 {
 	struct drm_device *dev = chan->dev;
-	uint32_t instance = (nv_rd32(dev, NV04_PGRAPH_CTX_SWITCH4) & 0xffff) << 4;
-	uint32_t tmp, ctx1;
+	u32 instance = (nv_rd32(dev, NV04_PGRAPH_CTX_SWITCH4) & 0xffff) << 4;
+	u32 tmp, ctx1;
 	int class, op, valid = 1;
 
 	ctx1 = nv_ri32(dev, instance);
@@ -672,13 +711,13 @@ nv04_graph_set_ctx_val(struct nouveau_ch
 }
 
 static int
-nv04_graph_mthd_set_operation(struct nouveau_channel *chan, int grclass,
-			      int mthd, uint32_t data)
+nv04_graph_mthd_set_operation(struct nouveau_channel *chan,
+			      u32 class, u32 mthd, u32 data)
 {
 	if (data > 5)
 		return 1;
 	/* Old versions of the objects only accept first three operations. */
-	if (data > 2 && grclass < 0x40)
+	if (data > 2 && class < 0x40)
 		return 1;
 	nv04_graph_set_ctx1(chan, 0x00038000, data << 15);
 	/* changing operation changes set of objects needed for validation */
@@ -687,8 +726,8 @@ nv04_graph_mthd_set_operation(struct nou
 }
 
 static int
-nv04_graph_mthd_surf3d_clip_h(struct nouveau_channel *chan, int grclass,
-			      int mthd, uint32_t data)
+nv04_graph_mthd_surf3d_clip_h(struct nouveau_channel *chan,
+			      u32 class, u32 mthd, u32 data)
 {
 	uint32_t min = data & 0xffff, max;
 	uint32_t w = data >> 16;
@@ -706,8 +745,8 @@ nv04_graph_mthd_surf3d_clip_h(struct nou
 }
 
 static int
-nv04_graph_mthd_surf3d_clip_v(struct nouveau_channel *chan, int grclass,
-			      int mthd, uint32_t data)
+nv04_graph_mthd_surf3d_clip_v(struct nouveau_channel *chan,
+			      u32 class, u32 mthd, u32 data)
 {
 	uint32_t min = data & 0xffff, max;
 	uint32_t w = data >> 16;
@@ -725,8 +764,8 @@ nv04_graph_mthd_surf3d_clip_v(struct nou
 }
 
 static int
-nv04_graph_mthd_bind_surf2d(struct nouveau_channel *chan, int grclass,
-			      int mthd, uint32_t data)
+nv04_graph_mthd_bind_surf2d(struct nouveau_channel *chan,
+			    u32 class, u32 mthd, u32 data)
 {
 	switch (nv_ri32(chan->dev, data << 4) & 0xff) {
 	case 0x30:
@@ -742,8 +781,8 @@ nv04_graph_mthd_bind_surf2d(struct nouve
 }
 
 static int
-nv04_graph_mthd_bind_surf2d_swzsurf(struct nouveau_channel *chan, int grclass,
-			      int mthd, uint32_t data)
+nv04_graph_mthd_bind_surf2d_swzsurf(struct nouveau_channel *chan,
+				    u32 class, u32 mthd, u32 data)
 {
 	switch (nv_ri32(chan->dev, data << 4) & 0xff) {
 	case 0x30:
@@ -763,8 +802,8 @@ nv04_graph_mthd_bind_surf2d_swzsurf(stru
 }
 
 static int
-nv04_graph_mthd_bind_nv01_patt(struct nouveau_channel *chan, int grclass,
-			      int mthd, uint32_t data)
+nv04_graph_mthd_bind_nv01_patt(struct nouveau_channel *chan,
+			       u32 class, u32 mthd, u32 data)
 {
 	switch (nv_ri32(chan->dev, data << 4) & 0xff) {
 	case 0x30:
@@ -778,8 +817,8 @@ nv04_graph_mthd_bind_nv01_patt(struct no
 }
 
 static int
-nv04_graph_mthd_bind_nv04_patt(struct nouveau_channel *chan, int grclass,
-			      int mthd, uint32_t data)
+nv04_graph_mthd_bind_nv04_patt(struct nouveau_channel *chan,
+			       u32 class, u32 mthd, u32 data)
 {
 	switch (nv_ri32(chan->dev, data << 4) & 0xff) {
 	case 0x30:
@@ -793,8 +832,8 @@ nv04_graph_mthd_bind_nv04_patt(struct no
 }
 
 static int
-nv04_graph_mthd_bind_rop(struct nouveau_channel *chan, int grclass,
-			      int mthd, uint32_t data)
+nv04_graph_mthd_bind_rop(struct nouveau_channel *chan,
+			 u32 class, u32 mthd, u32 data)
 {
 	switch (nv_ri32(chan->dev, data << 4) & 0xff) {
 	case 0x30:
@@ -808,8 +847,8 @@ nv04_graph_mthd_bind_rop(struct nouveau_
 }
 
 static int
-nv04_graph_mthd_bind_beta1(struct nouveau_channel *chan, int grclass,
-			      int mthd, uint32_t data)
+nv04_graph_mthd_bind_beta1(struct nouveau_channel *chan,
+			   u32 class, u32 mthd, u32 data)
 {
 	switch (nv_ri32(chan->dev, data << 4) & 0xff) {
 	case 0x30:
@@ -823,8 +862,8 @@ nv04_graph_mthd_bind_beta1(struct nouvea
 }
 
 static int
-nv04_graph_mthd_bind_beta4(struct nouveau_channel *chan, int grclass,
-			      int mthd, uint32_t data)
+nv04_graph_mthd_bind_beta4(struct nouveau_channel *chan,
+			   u32 class, u32 mthd, u32 data)
 {
 	switch (nv_ri32(chan->dev, data << 4) & 0xff) {
 	case 0x30:
@@ -838,8 +877,8 @@ nv04_graph_mthd_bind_beta4(struct nouvea
 }
 
 static int
-nv04_graph_mthd_bind_surf_dst(struct nouveau_channel *chan, int grclass,
-			      int mthd, uint32_t data)
+nv04_graph_mthd_bind_surf_dst(struct nouveau_channel *chan,
+			      u32 class, u32 mthd, u32 data)
 {
 	switch (nv_ri32(chan->dev, data << 4) & 0xff) {
 	case 0x30:
@@ -853,8 +892,8 @@ nv04_graph_mthd_bind_surf_dst(struct nou
 }
 
 static int
-nv04_graph_mthd_bind_surf_src(struct nouveau_channel *chan, int grclass,
-			      int mthd, uint32_t data)
+nv04_graph_mthd_bind_surf_src(struct nouveau_channel *chan,
+			      u32 class, u32 mthd, u32 data)
 {
 	switch (nv_ri32(chan->dev, data << 4) & 0xff) {
 	case 0x30:
@@ -868,8 +907,8 @@ nv04_graph_mthd_bind_surf_src(struct nou
 }
 
 static int
-nv04_graph_mthd_bind_surf_color(struct nouveau_channel *chan, int grclass,
-			      int mthd, uint32_t data)
+nv04_graph_mthd_bind_surf_color(struct nouveau_channel *chan,
+				u32 class, u32 mthd, u32 data)
 {
 	switch (nv_ri32(chan->dev, data << 4) & 0xff) {
 	case 0x30:
@@ -883,8 +922,8 @@ nv04_graph_mthd_bind_surf_color(struct n
 }
 
 static int
-nv04_graph_mthd_bind_surf_zeta(struct nouveau_channel *chan, int grclass,
-			      int mthd, uint32_t data)
+nv04_graph_mthd_bind_surf_zeta(struct nouveau_channel *chan,
+			       u32 class, u32 mthd, u32 data)
 {
 	switch (nv_ri32(chan->dev, data << 4) & 0xff) {
 	case 0x30:
@@ -898,8 +937,8 @@ nv04_graph_mthd_bind_surf_zeta(struct no
 }
 
 static int
-nv04_graph_mthd_bind_clip(struct nouveau_channel *chan, int grclass,
-			      int mthd, uint32_t data)
+nv04_graph_mthd_bind_clip(struct nouveau_channel *chan,
+			  u32 class, u32 mthd, u32 data)
 {
 	switch (nv_ri32(chan->dev, data << 4) & 0xff) {
 	case 0x30:
@@ -913,8 +952,8 @@ nv04_graph_mthd_bind_clip(struct nouveau
 }
 
 static int
-nv04_graph_mthd_bind_chroma(struct nouveau_channel *chan, int grclass,
-			      int mthd, uint32_t data)
+nv04_graph_mthd_bind_chroma(struct nouveau_channel *chan,
+			    u32 class, u32 mthd, u32 data)
 {
 	switch (nv_ri32(chan->dev, data << 4) & 0xff) {
 	case 0x30:
@@ -930,194 +969,346 @@ nv04_graph_mthd_bind_chroma(struct nouve
 	return 1;
 }
 
-static struct nouveau_pgraph_object_method nv04_graph_mthds_sw[] = {
-	{ 0x0150, nv04_graph_mthd_set_ref },
-	{}
-};
+static int
+nv04_graph_register(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
 
-static struct nouveau_pgraph_object_method nv04_graph_mthds_nv03_gdirect[] = {
-	{ 0x0184, nv04_graph_mthd_bind_nv01_patt },
-	{ 0x0188, nv04_graph_mthd_bind_rop },
-	{ 0x018c, nv04_graph_mthd_bind_beta1 },
-	{ 0x0190, nv04_graph_mthd_bind_surf_dst },
-	{ 0x02fc, nv04_graph_mthd_set_operation },
-	{},
-};
+	if (dev_priv->engine.graph.registered)
+		return 0;
 
-static struct nouveau_pgraph_object_method nv04_graph_mthds_nv04_gdirect[] = {
-	{ 0x0188, nv04_graph_mthd_bind_nv04_patt },
-	{ 0x018c, nv04_graph_mthd_bind_rop },
-	{ 0x0190, nv04_graph_mthd_bind_beta1 },
-	{ 0x0194, nv04_graph_mthd_bind_beta4 },
-	{ 0x0198, nv04_graph_mthd_bind_surf2d },
-	{ 0x02fc, nv04_graph_mthd_set_operation },
-	{},
-};
+	/* dvd subpicture */
+	NVOBJ_CLASS(dev, 0x0038, GR);
 
-static struct nouveau_pgraph_object_method nv04_graph_mthds_nv01_imageblit[] = {
-	{ 0x0184, nv04_graph_mthd_bind_chroma },
-	{ 0x0188, nv04_graph_mthd_bind_clip },
-	{ 0x018c, nv04_graph_mthd_bind_nv01_patt },
-	{ 0x0190, nv04_graph_mthd_bind_rop },
-	{ 0x0194, nv04_graph_mthd_bind_beta1 },
-	{ 0x0198, nv04_graph_mthd_bind_surf_dst },
-	{ 0x019c, nv04_graph_mthd_bind_surf_src },
-	{ 0x02fc, nv04_graph_mthd_set_operation },
-	{},
-};
+	/* m2mf */
+	NVOBJ_CLASS(dev, 0x0039, GR);
 
-static struct nouveau_pgraph_object_method nv04_graph_mthds_nv04_imageblit_ifc[] = {
-	{ 0x0184, nv04_graph_mthd_bind_chroma },
-	{ 0x0188, nv04_graph_mthd_bind_clip },
-	{ 0x018c, nv04_graph_mthd_bind_nv04_patt },
-	{ 0x0190, nv04_graph_mthd_bind_rop },
-	{ 0x0194, nv04_graph_mthd_bind_beta1 },
-	{ 0x0198, nv04_graph_mthd_bind_beta4 },
-	{ 0x019c, nv04_graph_mthd_bind_surf2d },
-	{ 0x02fc, nv04_graph_mthd_set_operation },
-	{},
-};
+	/* nv03 gdirect */
+	NVOBJ_CLASS(dev, 0x004b, GR);
+	NVOBJ_MTHD (dev, 0x004b, 0x0184, nv04_graph_mthd_bind_nv01_patt);
+	NVOBJ_MTHD (dev, 0x004b, 0x0188, nv04_graph_mthd_bind_rop);
+	NVOBJ_MTHD (dev, 0x004b, 0x018c, nv04_graph_mthd_bind_beta1);
+	NVOBJ_MTHD (dev, 0x004b, 0x0190, nv04_graph_mthd_bind_surf_dst);
+	NVOBJ_MTHD (dev, 0x004b, 0x02fc, nv04_graph_mthd_set_operation);
 
-static struct nouveau_pgraph_object_method nv04_graph_mthds_nv04_iifc[] = {
-	{ 0x0188, nv04_graph_mthd_bind_chroma },
-	{ 0x018c, nv04_graph_mthd_bind_clip },
-	{ 0x0190, nv04_graph_mthd_bind_nv04_patt },
-	{ 0x0194, nv04_graph_mthd_bind_rop },
-	{ 0x0198, nv04_graph_mthd_bind_beta1 },
-	{ 0x019c, nv04_graph_mthd_bind_beta4 },
-	{ 0x01a0, nv04_graph_mthd_bind_surf2d_swzsurf },
-	{ 0x03e4, nv04_graph_mthd_set_operation },
-	{},
-};
+	/* nv04 gdirect */
+	NVOBJ_CLASS(dev, 0x004a, GR);
+	NVOBJ_MTHD (dev, 0x004a, 0x0188, nv04_graph_mthd_bind_nv04_patt);
+	NVOBJ_MTHD (dev, 0x004a, 0x018c, nv04_graph_mthd_bind_rop);
+	NVOBJ_MTHD (dev, 0x004a, 0x0190, nv04_graph_mthd_bind_beta1);
+	NVOBJ_MTHD (dev, 0x004a, 0x0194, nv04_graph_mthd_bind_beta4);
+	NVOBJ_MTHD (dev, 0x004a, 0x0198, nv04_graph_mthd_bind_surf2d);
+	NVOBJ_MTHD (dev, 0x004a, 0x02fc, nv04_graph_mthd_set_operation);
 
-static struct nouveau_pgraph_object_method nv04_graph_mthds_nv01_ifc[] = {
-	{ 0x0184, nv04_graph_mthd_bind_chroma },
-	{ 0x0188, nv04_graph_mthd_bind_clip },
-	{ 0x018c, nv04_graph_mthd_bind_nv01_patt },
-	{ 0x0190, nv04_graph_mthd_bind_rop },
-	{ 0x0194, nv04_graph_mthd_bind_beta1 },
-	{ 0x0198, nv04_graph_mthd_bind_surf_dst },
-	{ 0x02fc, nv04_graph_mthd_set_operation },
-	{},
-};
+	/* nv01 imageblit */
+	NVOBJ_CLASS(dev, 0x001f, GR);
+	NVOBJ_MTHD (dev, 0x001f, 0x0184, nv04_graph_mthd_bind_chroma);
+	NVOBJ_MTHD (dev, 0x001f, 0x0188, nv04_graph_mthd_bind_clip);
+	NVOBJ_MTHD (dev, 0x001f, 0x018c, nv04_graph_mthd_bind_nv01_patt);
+	NVOBJ_MTHD (dev, 0x001f, 0x0190, nv04_graph_mthd_bind_rop);
+	NVOBJ_MTHD (dev, 0x001f, 0x0194, nv04_graph_mthd_bind_beta1);
+	NVOBJ_MTHD (dev, 0x001f, 0x0198, nv04_graph_mthd_bind_surf_dst);
+	NVOBJ_MTHD (dev, 0x001f, 0x019c, nv04_graph_mthd_bind_surf_src);
+	NVOBJ_MTHD (dev, 0x001f, 0x02fc, nv04_graph_mthd_set_operation);
 
-static struct nouveau_pgraph_object_method nv04_graph_mthds_nv03_sifc[] = {
-	{ 0x0184, nv04_graph_mthd_bind_chroma },
-	{ 0x0188, nv04_graph_mthd_bind_nv01_patt },
-	{ 0x018c, nv04_graph_mthd_bind_rop },
-	{ 0x0190, nv04_graph_mthd_bind_beta1 },
-	{ 0x0194, nv04_graph_mthd_bind_surf_dst },
-	{ 0x02fc, nv04_graph_mthd_set_operation },
-	{},
-};
+	/* nv04 imageblit */
+	NVOBJ_CLASS(dev, 0x005f, GR);
+	NVOBJ_MTHD (dev, 0x005f, 0x0184, nv04_graph_mthd_bind_chroma);
+	NVOBJ_MTHD (dev, 0x005f, 0x0188, nv04_graph_mthd_bind_clip);
+	NVOBJ_MTHD (dev, 0x005f, 0x018c, nv04_graph_mthd_bind_nv04_patt);
+	NVOBJ_MTHD (dev, 0x005f, 0x0190, nv04_graph_mthd_bind_rop);
+	NVOBJ_MTHD (dev, 0x005f, 0x0194, nv04_graph_mthd_bind_beta1);
+	NVOBJ_MTHD (dev, 0x005f, 0x0198, nv04_graph_mthd_bind_beta4);
+	NVOBJ_MTHD (dev, 0x005f, 0x019c, nv04_graph_mthd_bind_surf2d);
+	NVOBJ_MTHD (dev, 0x005f, 0x02fc, nv04_graph_mthd_set_operation);
 
-static struct nouveau_pgraph_object_method nv04_graph_mthds_nv04_sifc[] = {
-	{ 0x0184, nv04_graph_mthd_bind_chroma },
-	{ 0x0188, nv04_graph_mthd_bind_nv04_patt },
-	{ 0x018c, nv04_graph_mthd_bind_rop },
-	{ 0x0190, nv04_graph_mthd_bind_beta1 },
-	{ 0x0194, nv04_graph_mthd_bind_beta4 },
-	{ 0x0198, nv04_graph_mthd_bind_surf2d },
-	{ 0x02fc, nv04_graph_mthd_set_operation },
-	{},
-};
+	/* nv04 iifc */
+	NVOBJ_CLASS(dev, 0x0060, GR);
+	NVOBJ_MTHD (dev, 0x0060, 0x0188, nv04_graph_mthd_bind_chroma);
+	NVOBJ_MTHD (dev, 0x0060, 0x018c, nv04_graph_mthd_bind_clip);
+	NVOBJ_MTHD (dev, 0x0060, 0x0190, nv04_graph_mthd_bind_nv04_patt);
+	NVOBJ_MTHD (dev, 0x0060, 0x0194, nv04_graph_mthd_bind_rop);
+	NVOBJ_MTHD (dev, 0x0060, 0x0198, nv04_graph_mthd_bind_beta1);
+	NVOBJ_MTHD (dev, 0x0060, 0x019c, nv04_graph_mthd_bind_beta4);
+	NVOBJ_MTHD (dev, 0x0060, 0x01a0, nv04_graph_mthd_bind_surf2d_swzsurf);
+	NVOBJ_MTHD (dev, 0x0060, 0x03e4, nv04_graph_mthd_set_operation);
 
-static struct nouveau_pgraph_object_method nv04_graph_mthds_nv03_sifm[] = {
-	{ 0x0188, nv04_graph_mthd_bind_nv01_patt },
-	{ 0x018c, nv04_graph_mthd_bind_rop },
-	{ 0x0190, nv04_graph_mthd_bind_beta1 },
-	{ 0x0194, nv04_graph_mthd_bind_surf_dst },
-	{ 0x0304, nv04_graph_mthd_set_operation },
-	{},
-};
+	/* nv05 iifc */
+	NVOBJ_CLASS(dev, 0x0064, GR);
 
-static struct nouveau_pgraph_object_method nv04_graph_mthds_nv04_sifm[] = {
-	{ 0x0188, nv04_graph_mthd_bind_nv04_patt },
-	{ 0x018c, nv04_graph_mthd_bind_rop },
-	{ 0x0190, nv04_graph_mthd_bind_beta1 },
-	{ 0x0194, nv04_graph_mthd_bind_beta4 },
-	{ 0x0198, nv04_graph_mthd_bind_surf2d_swzsurf },
-	{ 0x0304, nv04_graph_mthd_set_operation },
-	{},
-};
+	/* nv01 ifc */
+	NVOBJ_CLASS(dev, 0x0021, GR);
+	NVOBJ_MTHD (dev, 0x0021, 0x0184, nv04_graph_mthd_bind_chroma);
+	NVOBJ_MTHD (dev, 0x0021, 0x0188, nv04_graph_mthd_bind_clip);
+	NVOBJ_MTHD (dev, 0x0021, 0x018c, nv04_graph_mthd_bind_nv01_patt);
+	NVOBJ_MTHD (dev, 0x0021, 0x0190, nv04_graph_mthd_bind_rop);
+	NVOBJ_MTHD (dev, 0x0021, 0x0194, nv04_graph_mthd_bind_beta1);
+	NVOBJ_MTHD (dev, 0x0021, 0x0198, nv04_graph_mthd_bind_surf_dst);
+	NVOBJ_MTHD (dev, 0x0021, 0x02fc, nv04_graph_mthd_set_operation);
 
-static struct nouveau_pgraph_object_method nv04_graph_mthds_nv01_shape[] = {
-	{ 0x0184, nv04_graph_mthd_bind_clip },
-	{ 0x0188, nv04_graph_mthd_bind_nv01_patt },
-	{ 0x018c, nv04_graph_mthd_bind_rop },
-	{ 0x0190, nv04_graph_mthd_bind_beta1 },
-	{ 0x0194, nv04_graph_mthd_bind_surf_dst },
-	{ 0x02fc, nv04_graph_mthd_set_operation },
-	{},
-};
+	/* nv04 ifc */
+	NVOBJ_CLASS(dev, 0x0061, GR);
+	NVOBJ_MTHD (dev, 0x0061, 0x0184, nv04_graph_mthd_bind_chroma);
+	NVOBJ_MTHD (dev, 0x0061, 0x0188, nv04_graph_mthd_bind_clip);
+	NVOBJ_MTHD (dev, 0x0061, 0x018c, nv04_graph_mthd_bind_nv04_patt);
+	NVOBJ_MTHD (dev, 0x0061, 0x0190, nv04_graph_mthd_bind_rop);
+	NVOBJ_MTHD (dev, 0x0061, 0x0194, nv04_graph_mthd_bind_beta1);
+	NVOBJ_MTHD (dev, 0x0061, 0x0198, nv04_graph_mthd_bind_beta4);
+	NVOBJ_MTHD (dev, 0x0061, 0x019c, nv04_graph_mthd_bind_surf2d);
+	NVOBJ_MTHD (dev, 0x0061, 0x02fc, nv04_graph_mthd_set_operation);
 
-static struct nouveau_pgraph_object_method nv04_graph_mthds_nv04_shape[] = {
-	{ 0x0184, nv04_graph_mthd_bind_clip },
-	{ 0x0188, nv04_graph_mthd_bind_nv04_patt },
-	{ 0x018c, nv04_graph_mthd_bind_rop },
-	{ 0x0190, nv04_graph_mthd_bind_beta1 },
-	{ 0x0194, nv04_graph_mthd_bind_beta4 },
-	{ 0x0198, nv04_graph_mthd_bind_surf2d },
-	{ 0x02fc, nv04_graph_mthd_set_operation },
-	{},
+	/* nv05 ifc */
+	NVOBJ_CLASS(dev, 0x0065, GR);
+
+	/* nv03 sifc */
+	NVOBJ_CLASS(dev, 0x0036, GR);
+	NVOBJ_MTHD (dev, 0x0036, 0x0184, nv04_graph_mthd_bind_chroma);
+	NVOBJ_MTHD (dev, 0x0036, 0x0188, nv04_graph_mthd_bind_nv01_patt);
+	NVOBJ_MTHD (dev, 0x0036, 0x018c, nv04_graph_mthd_bind_rop);
+	NVOBJ_MTHD (dev, 0x0036, 0x0190, nv04_graph_mthd_bind_beta1);
+	NVOBJ_MTHD (dev, 0x0036, 0x0194, nv04_graph_mthd_bind_surf_dst);
+	NVOBJ_MTHD (dev, 0x0036, 0x02fc, nv04_graph_mthd_set_operation);
+
+	/* nv04 sifc */
+	NVOBJ_CLASS(dev, 0x0076, GR);
+	NVOBJ_MTHD (dev, 0x0076, 0x0184, nv04_graph_mthd_bind_chroma);
+	NVOBJ_MTHD (dev, 0x0076, 0x0188, nv04_graph_mthd_bind_nv04_patt);
+	NVOBJ_MTHD (dev, 0x0076, 0x018c, nv04_graph_mthd_bind_rop);
+	NVOBJ_MTHD (dev, 0x0076, 0x0190, nv04_graph_mthd_bind_beta1);
+	NVOBJ_MTHD (dev, 0x0076, 0x0194, nv04_graph_mthd_bind_beta4);
+	NVOBJ_MTHD (dev, 0x0076, 0x0198, nv04_graph_mthd_bind_surf2d);
+	NVOBJ_MTHD (dev, 0x0076, 0x02fc, nv04_graph_mthd_set_operation);
+
+	/* nv05 sifc */
+	NVOBJ_CLASS(dev, 0x0066, GR);
+
+	/* nv03 sifm */
+	NVOBJ_CLASS(dev, 0x0037, GR);
+	NVOBJ_MTHD (dev, 0x0037, 0x0188, nv04_graph_mthd_bind_nv01_patt);
+	NVOBJ_MTHD (dev, 0x0037, 0x018c, nv04_graph_mthd_bind_rop);
+	NVOBJ_MTHD (dev, 0x0037, 0x0190, nv04_graph_mthd_bind_beta1);
+	NVOBJ_MTHD (dev, 0x0037, 0x0194, nv04_graph_mthd_bind_surf_dst);
+	NVOBJ_MTHD (dev, 0x0037, 0x0304, nv04_graph_mthd_set_operation);
+
+	/* nv04 sifm */
+	NVOBJ_CLASS(dev, 0x0077, GR);
+	NVOBJ_MTHD (dev, 0x0077, 0x0188, nv04_graph_mthd_bind_nv04_patt);
+	NVOBJ_MTHD (dev, 0x0077, 0x018c, nv04_graph_mthd_bind_rop);
+	NVOBJ_MTHD (dev, 0x0077, 0x0190, nv04_graph_mthd_bind_beta1);
+	NVOBJ_MTHD (dev, 0x0077, 0x0194, nv04_graph_mthd_bind_beta4);
+	NVOBJ_MTHD (dev, 0x0077, 0x0198, nv04_graph_mthd_bind_surf2d_swzsurf);
+	NVOBJ_MTHD (dev, 0x0077, 0x0304, nv04_graph_mthd_set_operation);
+
+	/* null */
+	NVOBJ_CLASS(dev, 0x0030, GR);
+
+	/* surf2d */
+	NVOBJ_CLASS(dev, 0x0042, GR);
+
+	/* rop */
+	NVOBJ_CLASS(dev, 0x0043, GR);
+
+	/* beta1 */
+	NVOBJ_CLASS(dev, 0x0012, GR);
+
+	/* beta4 */
+	NVOBJ_CLASS(dev, 0x0072, GR);
+
+	/* cliprect */
+	NVOBJ_CLASS(dev, 0x0019, GR);
+
+	/* nv01 pattern */
+	NVOBJ_CLASS(dev, 0x0018, GR);
+
+	/* nv04 pattern */
+	NVOBJ_CLASS(dev, 0x0044, GR);
+
+	/* swzsurf */
+	NVOBJ_CLASS(dev, 0x0052, GR);
+
+	/* surf3d */
+	NVOBJ_CLASS(dev, 0x0053, GR);
+	NVOBJ_MTHD (dev, 0x0053, 0x02f8, nv04_graph_mthd_surf3d_clip_h);
+	NVOBJ_MTHD (dev, 0x0053, 0x02fc, nv04_graph_mthd_surf3d_clip_v);
+
+	/* nv03 tex_tri */
+	NVOBJ_CLASS(dev, 0x0048, GR);
+	NVOBJ_MTHD (dev, 0x0048, 0x0188, nv04_graph_mthd_bind_clip);
+	NVOBJ_MTHD (dev, 0x0048, 0x018c, nv04_graph_mthd_bind_surf_color);
+	NVOBJ_MTHD (dev, 0x0048, 0x0190, nv04_graph_mthd_bind_surf_zeta);
+
+	/* tex_tri */
+	NVOBJ_CLASS(dev, 0x0054, GR);
+
+	/* multitex_tri */
+	NVOBJ_CLASS(dev, 0x0055, GR);
+
+	/* nv01 chroma */
+	NVOBJ_CLASS(dev, 0x0017, GR);
+
+	/* nv04 chroma */
+	NVOBJ_CLASS(dev, 0x0057, GR);
+
+	/* surf_dst */
+	NVOBJ_CLASS(dev, 0x0058, GR);
+
+	/* surf_src */
+	NVOBJ_CLASS(dev, 0x0059, GR);
+
+	/* surf_color */
+	NVOBJ_CLASS(dev, 0x005a, GR);
+
+	/* surf_zeta */
+	NVOBJ_CLASS(dev, 0x005b, GR);
+
+	/* nv01 line */
+	NVOBJ_CLASS(dev, 0x001c, GR);
+	NVOBJ_MTHD (dev, 0x001c, 0x0184, nv04_graph_mthd_bind_clip);
+	NVOBJ_MTHD (dev, 0x001c, 0x0188, nv04_graph_mthd_bind_nv01_patt);
+	NVOBJ_MTHD (dev, 0x001c, 0x018c, nv04_graph_mthd_bind_rop);
+	NVOBJ_MTHD (dev, 0x001c, 0x0190, nv04_graph_mthd_bind_beta1);
+	NVOBJ_MTHD (dev, 0x001c, 0x0194, nv04_graph_mthd_bind_surf_dst);
+	NVOBJ_MTHD (dev, 0x001c, 0x02fc, nv04_graph_mthd_set_operation);
+
+	/* nv04 line */
+	NVOBJ_CLASS(dev, 0x005c, GR);
+	NVOBJ_MTHD (dev, 0x005c, 0x0184, nv04_graph_mthd_bind_clip);
+	NVOBJ_MTHD (dev, 0x005c, 0x0188, nv04_graph_mthd_bind_nv04_patt);
+	NVOBJ_MTHD (dev, 0x005c, 0x018c, nv04_graph_mthd_bind_rop);
+	NVOBJ_MTHD (dev, 0x005c, 0x0190, nv04_graph_mthd_bind_beta1);
+	NVOBJ_MTHD (dev, 0x005c, 0x0194, nv04_graph_mthd_bind_beta4);
+	NVOBJ_MTHD (dev, 0x005c, 0x0198, nv04_graph_mthd_bind_surf2d);
+	NVOBJ_MTHD (dev, 0x005c, 0x02fc, nv04_graph_mthd_set_operation);
+
+	/* nv01 tri */
+	NVOBJ_CLASS(dev, 0x001d, GR);
+	NVOBJ_MTHD (dev, 0x001d, 0x0184, nv04_graph_mthd_bind_clip);
+	NVOBJ_MTHD (dev, 0x001d, 0x0188, nv04_graph_mthd_bind_nv01_patt);
+	NVOBJ_MTHD (dev, 0x001d, 0x018c, nv04_graph_mthd_bind_rop);
+	NVOBJ_MTHD (dev, 0x001d, 0x0190, nv04_graph_mthd_bind_beta1);
+	NVOBJ_MTHD (dev, 0x001d, 0x0194, nv04_graph_mthd_bind_surf_dst);
+	NVOBJ_MTHD (dev, 0x001d, 0x02fc, nv04_graph_mthd_set_operation);
+
+	/* nv04 tri */
+	NVOBJ_CLASS(dev, 0x005d, GR);
+	NVOBJ_MTHD (dev, 0x005d, 0x0184, nv04_graph_mthd_bind_clip);
+	NVOBJ_MTHD (dev, 0x005d, 0x0188, nv04_graph_mthd_bind_nv04_patt);
+	NVOBJ_MTHD (dev, 0x005d, 0x018c, nv04_graph_mthd_bind_rop);
+	NVOBJ_MTHD (dev, 0x005d, 0x0190, nv04_graph_mthd_bind_beta1);
+	NVOBJ_MTHD (dev, 0x005d, 0x0194, nv04_graph_mthd_bind_beta4);
+	NVOBJ_MTHD (dev, 0x005d, 0x0198, nv04_graph_mthd_bind_surf2d);
+	NVOBJ_MTHD (dev, 0x005d, 0x02fc, nv04_graph_mthd_set_operation);
+
+	/* nv01 rect */
+	NVOBJ_CLASS(dev, 0x001e, GR);
+	NVOBJ_MTHD (dev, 0x001e, 0x0184, nv04_graph_mthd_bind_clip);
+	NVOBJ_MTHD (dev, 0x001e, 0x0188, nv04_graph_mthd_bind_nv01_patt);
+	NVOBJ_MTHD (dev, 0x001e, 0x018c, nv04_graph_mthd_bind_rop);
+	NVOBJ_MTHD (dev, 0x001e, 0x0190, nv04_graph_mthd_bind_beta1);
+	NVOBJ_MTHD (dev, 0x001e, 0x0194, nv04_graph_mthd_bind_surf_dst);
+	NVOBJ_MTHD (dev, 0x001e, 0x02fc, nv04_graph_mthd_set_operation);
+
+	/* nv04 rect */
+	NVOBJ_CLASS(dev, 0x005e, GR);
+	NVOBJ_MTHD (dev, 0x005e, 0x0184, nv04_graph_mthd_bind_clip);
+	NVOBJ_MTHD (dev, 0x005e, 0x0188, nv04_graph_mthd_bind_nv04_patt);
+	NVOBJ_MTHD (dev, 0x005e, 0x018c, nv04_graph_mthd_bind_rop);
+	NVOBJ_MTHD (dev, 0x005e, 0x0190, nv04_graph_mthd_bind_beta1);
+	NVOBJ_MTHD (dev, 0x005e, 0x0194, nv04_graph_mthd_bind_beta4);
+	NVOBJ_MTHD (dev, 0x005e, 0x0198, nv04_graph_mthd_bind_surf2d);
+	NVOBJ_MTHD (dev, 0x005e, 0x02fc, nv04_graph_mthd_set_operation);
+
+	/* nvsw */
+	NVOBJ_CLASS(dev, 0x506e, SW);
+	NVOBJ_MTHD (dev, 0x506e, 0x0150, nv04_graph_mthd_set_ref);
+	NVOBJ_MTHD (dev, 0x506e, 0x0500, nv04_graph_mthd_page_flip);
+
+	dev_priv->engine.graph.registered = true;
+	return 0;
 };
 
-static struct nouveau_pgraph_object_method nv04_graph_mthds_nv03_tex_tri[] = {
-	{ 0x0188, nv04_graph_mthd_bind_clip },
-	{ 0x018c, nv04_graph_mthd_bind_surf_color },
-	{ 0x0190, nv04_graph_mthd_bind_surf_zeta },
-	{},
+static struct nouveau_bitfield nv04_graph_intr[] = {
+	{ NV_PGRAPH_INTR_NOTIFY, "NOTIFY" },
+	{}
 };
 
-static struct nouveau_pgraph_object_method nv04_graph_mthds_surf3d[] = {
-	{ 0x02f8, nv04_graph_mthd_surf3d_clip_h },
-	{ 0x02fc, nv04_graph_mthd_surf3d_clip_v },
-	{},
+static struct nouveau_bitfield nv04_graph_nstatus[] =
+{
+	{ NV04_PGRAPH_NSTATUS_STATE_IN_USE,       "STATE_IN_USE" },
+	{ NV04_PGRAPH_NSTATUS_INVALID_STATE,      "INVALID_STATE" },
+	{ NV04_PGRAPH_NSTATUS_BAD_ARGUMENT,       "BAD_ARGUMENT" },
+	{ NV04_PGRAPH_NSTATUS_PROTECTION_FAULT,   "PROTECTION_FAULT" },
+	{}
 };
 
-struct nouveau_pgraph_object_class nv04_graph_grclass[] = {
-	{ 0x0038, false, NULL }, /* dvd subpicture */
-	{ 0x0039, false, NULL }, /* m2mf */
-	{ 0x004b, false, nv04_graph_mthds_nv03_gdirect }, /* nv03 gdirect */
-	{ 0x004a, false, nv04_graph_mthds_nv04_gdirect }, /* nv04 gdirect */
-	{ 0x001f, false, nv04_graph_mthds_nv01_imageblit }, /* nv01 imageblit */
-	{ 0x005f, false, nv04_graph_mthds_nv04_imageblit_ifc }, /* nv04 imageblit */
-	{ 0x0060, false, nv04_graph_mthds_nv04_iifc }, /* nv04 iifc */
-	{ 0x0064, false, NULL }, /* nv05 iifc */
-	{ 0x0021, false, nv04_graph_mthds_nv01_ifc }, /* nv01 ifc */
-	{ 0x0061, false, nv04_graph_mthds_nv04_imageblit_ifc }, /* nv04 ifc */
-	{ 0x0065, false, NULL }, /* nv05 ifc */
-	{ 0x0036, false, nv04_graph_mthds_nv03_sifc }, /* nv03 sifc */
-	{ 0x0076, false, nv04_graph_mthds_nv04_sifc }, /* nv04 sifc */
-	{ 0x0066, false, NULL }, /* nv05 sifc */
-	{ 0x0037, false, nv04_graph_mthds_nv03_sifm }, /* nv03 sifm */
-	{ 0x0077, false, nv04_graph_mthds_nv04_sifm }, /* nv04 sifm */
-	{ 0x0030, false, NULL }, /* null */
-	{ 0x0042, false, NULL }, /* surf2d */
-	{ 0x0043, false, NULL }, /* rop */
-	{ 0x0012, false, NULL }, /* beta1 */
-	{ 0x0072, false, NULL }, /* beta4 */
-	{ 0x0019, false, NULL }, /* cliprect */
-	{ 0x0018, false, NULL }, /* nv01 pattern */
-	{ 0x0044, false, NULL }, /* nv04 pattern */
-	{ 0x0052, false, NULL }, /* swzsurf */
-	{ 0x0053, false, nv04_graph_mthds_surf3d }, /* surf3d */
-	{ 0x0048, false, nv04_graph_mthds_nv03_tex_tri }, /* nv03 tex_tri */
-	{ 0x0054, false, NULL }, /* tex_tri */
-	{ 0x0055, false, NULL }, /* multitex_tri */
-	{ 0x0017, false, NULL }, /* nv01 chroma */
-	{ 0x0057, false, NULL }, /* nv04 chroma */
-	{ 0x0058, false, NULL }, /* surf_dst */
-	{ 0x0059, false, NULL }, /* surf_src */
-	{ 0x005a, false, NULL }, /* surf_color */
-	{ 0x005b, false, NULL }, /* surf_zeta */
-	{ 0x001c, false, nv04_graph_mthds_nv01_shape }, /* nv01 line */
-	{ 0x005c, false, nv04_graph_mthds_nv04_shape }, /* nv04 line */
-	{ 0x001d, false, nv04_graph_mthds_nv01_shape }, /* nv01 tri */
-	{ 0x005d, false, nv04_graph_mthds_nv04_shape }, /* nv04 tri */
-	{ 0x001e, false, nv04_graph_mthds_nv01_shape }, /* nv01 rect */
-	{ 0x005e, false, nv04_graph_mthds_nv04_shape }, /* nv04 rect */
-	{ 0x506e, true, nv04_graph_mthds_sw },
+struct nouveau_bitfield nv04_graph_nsource[] =
+{
+	{ NV03_PGRAPH_NSOURCE_NOTIFICATION,       "NOTIFICATION" },
+	{ NV03_PGRAPH_NSOURCE_DATA_ERROR,         "DATA_ERROR" },
+	{ NV03_PGRAPH_NSOURCE_PROTECTION_ERROR,   "PROTECTION_ERROR" },
+	{ NV03_PGRAPH_NSOURCE_RANGE_EXCEPTION,    "RANGE_EXCEPTION" },
+	{ NV03_PGRAPH_NSOURCE_LIMIT_COLOR,        "LIMIT_COLOR" },
+	{ NV03_PGRAPH_NSOURCE_LIMIT_ZETA,         "LIMIT_ZETA" },
+	{ NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD,       "ILLEGAL_MTHD" },
+	{ NV03_PGRAPH_NSOURCE_DMA_R_PROTECTION,   "DMA_R_PROTECTION" },
+	{ NV03_PGRAPH_NSOURCE_DMA_W_PROTECTION,   "DMA_W_PROTECTION" },
+	{ NV03_PGRAPH_NSOURCE_FORMAT_EXCEPTION,   "FORMAT_EXCEPTION" },
+	{ NV03_PGRAPH_NSOURCE_PATCH_EXCEPTION,    "PATCH_EXCEPTION" },
+	{ NV03_PGRAPH_NSOURCE_STATE_INVALID,      "STATE_INVALID" },
+	{ NV03_PGRAPH_NSOURCE_DOUBLE_NOTIFY,      "DOUBLE_NOTIFY" },
+	{ NV03_PGRAPH_NSOURCE_NOTIFY_IN_USE,      "NOTIFY_IN_USE" },
+	{ NV03_PGRAPH_NSOURCE_METHOD_CNT,         "METHOD_CNT" },
+	{ NV03_PGRAPH_NSOURCE_BFR_NOTIFICATION,   "BFR_NOTIFICATION" },
+	{ NV03_PGRAPH_NSOURCE_DMA_VTX_PROTECTION, "DMA_VTX_PROTECTION" },
+	{ NV03_PGRAPH_NSOURCE_DMA_WIDTH_A,        "DMA_WIDTH_A" },
+	{ NV03_PGRAPH_NSOURCE_DMA_WIDTH_B,        "DMA_WIDTH_B" },
 	{}
 };
 
+static void
+nv04_graph_isr(struct drm_device *dev)
+{
+	u32 stat;
+
+	while ((stat = nv_rd32(dev, NV03_PGRAPH_INTR))) {
+		u32 nsource = nv_rd32(dev, NV03_PGRAPH_NSOURCE);
+		u32 nstatus = nv_rd32(dev, NV03_PGRAPH_NSTATUS);
+		u32 addr = nv_rd32(dev, NV04_PGRAPH_TRAPPED_ADDR);
+		u32 chid = (addr & 0x0f000000) >> 24;
+		u32 subc = (addr & 0x0000e000) >> 13;
+		u32 mthd = (addr & 0x00001ffc);
+		u32 data = nv_rd32(dev, NV04_PGRAPH_TRAPPED_DATA);
+		u32 class = nv_rd32(dev, 0x400180 + subc * 4) & 0xff;
+		u32 show = stat;
+
+		if (stat & NV_PGRAPH_INTR_NOTIFY) {
+			if (nsource & NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD) {
+				if (!nouveau_gpuobj_mthd_call2(dev, chid, class, mthd, data))
+					show &= ~NV_PGRAPH_INTR_NOTIFY;
+			}
+		}
+
+		if (stat & NV_PGRAPH_INTR_CONTEXT_SWITCH) {
+			nv_wr32(dev, NV03_PGRAPH_INTR, NV_PGRAPH_INTR_CONTEXT_SWITCH);
+			stat &= ~NV_PGRAPH_INTR_CONTEXT_SWITCH;
+			show &= ~NV_PGRAPH_INTR_CONTEXT_SWITCH;
+			nv04_graph_context_switch(dev);
+		}
+
+		nv_wr32(dev, NV03_PGRAPH_INTR, stat);
+		nv_wr32(dev, NV04_PGRAPH_FIFO, 0x00000001);
+
+		if (show && nouveau_ratelimit()) {
+			NV_INFO(dev, "PGRAPH -");
+			nouveau_bitfield_print(nv04_graph_intr, show);
+			printk(" nsource:");
+			nouveau_bitfield_print(nv04_graph_nsource, nsource);
+			printk(" nstatus:");
+			nouveau_bitfield_print(nv04_graph_nstatus, nstatus);
+			printk("\n");
+			NV_INFO(dev, "PGRAPH - ch %d/%d class 0x%04x "
+				     "mthd 0x%04x data 0x%08x\n",
+				chid, subc, class, mthd, data);
+		}
+	}
+}
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nv04_instmem.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nv04_instmem.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nv04_instmem.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nv04_instmem.c	2011-03-14 21:20:32.000000000 -0400
@@ -98,42 +98,66 @@ nv04_instmem_takedown(struct drm_device
 }
 
 int
-nv04_instmem_populate(struct drm_device *dev, struct nouveau_gpuobj *gpuobj,
-		      uint32_t *sz)
+nv04_instmem_suspend(struct drm_device *dev)
 {
 	return 0;
 }
 
 void
-nv04_instmem_clear(struct drm_device *dev, struct nouveau_gpuobj *gpuobj)
+nv04_instmem_resume(struct drm_device *dev)
 {
 }
 
 int
-nv04_instmem_bind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj)
+nv04_instmem_get(struct nouveau_gpuobj *gpuobj, u32 size, u32 align)
 {
-	return 0;
-}
+	struct drm_nouveau_private *dev_priv = gpuobj->dev->dev_private;
+	struct drm_mm_node *ramin = NULL;
 
-int
-nv04_instmem_unbind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj)
-{
+	do {
+		if (drm_mm_pre_get(&dev_priv->ramin_heap))
+			return -ENOMEM;
+
+		spin_lock(&dev_priv->ramin_lock);
+		ramin = drm_mm_search_free(&dev_priv->ramin_heap, size, align, 0);
+		if (ramin == NULL) {
+			spin_unlock(&dev_priv->ramin_lock);
+			return -ENOMEM;
+		}
+
+		ramin = drm_mm_get_block_atomic(ramin, size, align);
+		spin_unlock(&dev_priv->ramin_lock);
+	} while (ramin == NULL);
+
+	gpuobj->node  = ramin;
+	gpuobj->vinst = ramin->start;
 	return 0;
 }
 
 void
-nv04_instmem_flush(struct drm_device *dev)
+nv04_instmem_put(struct nouveau_gpuobj *gpuobj)
 {
+	struct drm_nouveau_private *dev_priv = gpuobj->dev->dev_private;
+
+	spin_lock(&dev_priv->ramin_lock);
+	drm_mm_put_block(gpuobj->node);
+	gpuobj->node = NULL;
+	spin_unlock(&dev_priv->ramin_lock);
 }
 
 int
-nv04_instmem_suspend(struct drm_device *dev)
+nv04_instmem_map(struct nouveau_gpuobj *gpuobj)
 {
+	gpuobj->pinst = gpuobj->vinst;
 	return 0;
 }
 
 void
-nv04_instmem_resume(struct drm_device *dev)
+nv04_instmem_unmap(struct nouveau_gpuobj *gpuobj)
 {
 }
 
+void
+nv04_instmem_flush(struct drm_device *dev)
+{
+}
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nv10_fb.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nv10_fb.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nv10_fb.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nv10_fb.c	2011-03-14 21:20:32.000000000 -0400
@@ -3,23 +3,109 @@
 #include "nouveau_drv.h"
 #include "nouveau_drm.h"
 
+static struct drm_mm_node *
+nv20_fb_alloc_tag(struct drm_device *dev, uint32_t size)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_fb_engine *pfb = &dev_priv->engine.fb;
+	struct drm_mm_node *mem;
+	int ret;
+
+	ret = drm_mm_pre_get(&pfb->tag_heap);
+	if (ret)
+		return NULL;
+
+	spin_lock(&dev_priv->tile.lock);
+	mem = drm_mm_search_free(&pfb->tag_heap, size, 0, 0);
+	if (mem)
+		mem = drm_mm_get_block_atomic(mem, size, 0);
+	spin_unlock(&dev_priv->tile.lock);
+
+	return mem;
+}
+
+static void
+nv20_fb_free_tag(struct drm_device *dev, struct drm_mm_node *mem)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+	spin_lock(&dev_priv->tile.lock);
+	drm_mm_put_block(mem);
+	spin_unlock(&dev_priv->tile.lock);
+}
+
 void
-nv10_fb_set_region_tiling(struct drm_device *dev, int i, uint32_t addr,
-			  uint32_t size, uint32_t pitch)
+nv10_fb_init_tile_region(struct drm_device *dev, int i, uint32_t addr,
+			 uint32_t size, uint32_t pitch, uint32_t flags)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	uint32_t limit = max(1u, addr + size) - 1;
+	struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i];
+	int bpp = (flags & NOUVEAU_GEM_TILE_32BPP ? 32 : 16);
 
-	if (pitch) {
-		if (dev_priv->card_type >= NV_20)
-			addr |= 1;
-		else
-			addr |= 1 << 31;
+	tile->addr = addr;
+	tile->limit = max(1u, addr + size) - 1;
+	tile->pitch = pitch;
+
+	if (dev_priv->card_type == NV_20) {
+		if (flags & NOUVEAU_GEM_TILE_ZETA) {
+			/*
+			 * Allocate some of the on-die tag memory,
+			 * used to store Z compression meta-data (most
+			 * likely just a bitmap determining if a given
+			 * tile is compressed or not).
+			 */
+			tile->tag_mem = nv20_fb_alloc_tag(dev, size / 256);
+
+			if (tile->tag_mem) {
+				/* Enable Z compression */
+				if (dev_priv->chipset >= 0x25)
+					tile->zcomp = tile->tag_mem->start |
+						(bpp == 16 ?
+						 NV25_PFB_ZCOMP_MODE_16 :
+						 NV25_PFB_ZCOMP_MODE_32);
+				else
+					tile->zcomp = tile->tag_mem->start |
+						NV20_PFB_ZCOMP_EN |
+						(bpp == 16 ? 0 :
+						 NV20_PFB_ZCOMP_MODE_32);
+			}
+
+			tile->addr |= 3;
+		} else {
+			tile->addr |= 1;
+		}
+
+	} else {
+		tile->addr |= 1 << 31;
 	}
+}
 
-	nv_wr32(dev, NV10_PFB_TLIMIT(i), limit);
-	nv_wr32(dev, NV10_PFB_TSIZE(i), pitch);
-	nv_wr32(dev, NV10_PFB_TILE(i), addr);
+void
+nv10_fb_free_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];
+
+	if (tile->tag_mem) {
+		nv20_fb_free_tag(dev, tile->tag_mem);
+		tile->tag_mem = NULL;
+	}
+
+	tile->addr = tile->limit = tile->pitch = tile->zcomp = 0;
+}
+
+void
+nv10_fb_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, NV10_PFB_TLIMIT(i), tile->limit);
+	nv_wr32(dev, NV10_PFB_TSIZE(i), tile->pitch);
+	nv_wr32(dev, NV10_PFB_TILE(i), tile->addr);
+
+	if (dev_priv->card_type == NV_20)
+		nv_wr32(dev, NV20_PFB_ZCOMP(i), tile->zcomp);
 }
 
 int
@@ -31,9 +117,14 @@ nv10_fb_init(struct drm_device *dev)
 
 	pfb->num_tiles = NV10_PFB_TILE__SIZE;
 
+	if (dev_priv->card_type == NV_20)
+		drm_mm_init(&pfb->tag_heap, 0,
+			    (dev_priv->chipset >= 0x25 ?
+			     64 * 1024 : 32 * 1024));
+
 	/* Turn all the tiling regions off. */
 	for (i = 0; i < pfb->num_tiles; i++)
-		pfb->set_region_tiling(dev, i, 0, 0, 0);
+		pfb->set_tile_region(dev, i);
 
 	return 0;
 }
@@ -41,4 +132,13 @@ nv10_fb_init(struct drm_device *dev)
 void
 nv10_fb_takedown(struct drm_device *dev)
 {
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_fb_engine *pfb = &dev_priv->engine.fb;
+	int i;
+
+	for (i = 0; i < pfb->num_tiles; i++)
+		pfb->free_tile_region(dev, i);
+
+	if (dev_priv->card_type == NV_20)
+		drm_mm_takedown(&pfb->tag_heap);
 }
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nv10_fifo.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nv10_fifo.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nv10_fifo.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nv10_fifo.c	2011-03-14 21:20:32.000000000 -0400
@@ -53,6 +53,11 @@ nv10_fifo_create_context(struct nouveau_
 	if (ret)
 		return ret;
 
+	chan->user = ioremap(pci_resource_start(dev->pdev, 0) +
+			     NV03_USER(chan->id), PAGE_SIZE);
+	if (!chan->user)
+		return -ENOMEM;
+
 	/* Fill entries that are seen filled in dumps of nvidia driver just
 	 * after channel's is put into DMA mode
 	 */
@@ -73,17 +78,6 @@ nv10_fifo_create_context(struct nouveau_
 	return 0;
 }
 
-void
-nv10_fifo_destroy_context(struct nouveau_channel *chan)
-{
-	struct drm_device *dev = chan->dev;
-
-	nv_wr32(dev, NV04_PFIFO_MODE,
-			nv_rd32(dev, NV04_PFIFO_MODE) & ~(1 << chan->id));
-
-	nouveau_gpuobj_ref(NULL, &chan->ramfc);
-}
-
 static void
 nv10_fifo_do_load_context(struct drm_device *dev, int chid)
 {
@@ -219,6 +213,7 @@ nv10_fifo_init_ramxx(struct drm_device *
 static void
 nv10_fifo_init_intr(struct drm_device *dev)
 {
+	nouveau_irq_register(dev, 8, nv04_fifo_isr);
 	nv_wr32(dev, 0x002100, 0xffffffff);
 	nv_wr32(dev, 0x002140, 0xffffffff);
 }
@@ -241,7 +236,7 @@ nv10_fifo_init(struct drm_device *dev)
 	pfifo->reassign(dev, true);
 
 	for (i = 0; i < dev_priv->engine.fifo.channels; i++) {
-		if (dev_priv->fifos[i]) {
+		if (dev_priv->channels.ptr[i]) {
 			uint32_t mode = nv_rd32(dev, NV04_PFIFO_MODE);
 			nv_wr32(dev, NV04_PFIFO_MODE, mode | (1 << i));
 		}
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nv10_graph.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nv10_graph.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nv10_graph.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nv10_graph.c	2011-03-14 21:20:32.000000000 -0400
@@ -26,6 +26,10 @@
 #include "drm.h"
 #include "nouveau_drm.h"
 #include "nouveau_drv.h"
+#include "nouveau_util.h"
+
+static int  nv10_graph_register(struct drm_device *);
+static void nv10_graph_isr(struct drm_device *);
 
 #define NV10_FIFO_NUMBER 32
 
@@ -786,15 +790,13 @@ nv10_graph_unload_context(struct drm_dev
 	return 0;
 }
 
-void
+static void
 nv10_graph_context_switch(struct drm_device *dev)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
 	struct nouveau_channel *chan = NULL;
 	int chid;
 
-	pgraph->fifo_access(dev, false);
 	nouveau_wait_for_idle(dev);
 
 	/* If previous context is valid, we need to save it */
@@ -802,11 +804,9 @@ nv10_graph_context_switch(struct drm_dev
 
 	/* Load context for next channel */
 	chid = (nv_rd32(dev, NV04_PGRAPH_TRAPPED_ADDR) >> 20) & 0x1f;
-	chan = dev_priv->fifos[chid];
+	chan = dev_priv->channels.ptr[chid];
 	if (chan && chan->pgraph_ctx)
 		nv10_graph_load_context(chan);
-
-	pgraph->fifo_access(dev, true);
 }
 
 #define NV_WRITE_CTX(reg, val) do { \
@@ -833,7 +833,7 @@ nv10_graph_channel(struct drm_device *de
 	if (chid >= dev_priv->engine.fifo.channels)
 		return NULL;
 
-	return dev_priv->fifos[chid];
+	return dev_priv->channels.ptr[chid];
 }
 
 int nv10_graph_create_context(struct nouveau_channel *chan)
@@ -875,37 +875,54 @@ int nv10_graph_create_context(struct nou
 
 void nv10_graph_destroy_context(struct nouveau_channel *chan)
 {
+	struct drm_device *dev = chan->dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
 	struct graph_state *pgraph_ctx = chan->pgraph_ctx;
+	unsigned long flags;
 
+	spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
+	pgraph->fifo_access(dev, false);
+
+	/* Unload the context if it's the currently active one */
+	if (pgraph->channel(dev) == chan)
+		pgraph->unload_context(dev);
+
+	/* Free the context resources */
 	kfree(pgraph_ctx);
 	chan->pgraph_ctx = NULL;
+
+	pgraph->fifo_access(dev, true);
+	spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
 }
 
 void
-nv10_graph_set_region_tiling(struct drm_device *dev, int i, uint32_t addr,
-			     uint32_t size, uint32_t pitch)
+nv10_graph_set_tile_region(struct drm_device *dev, int i)
 {
-	uint32_t limit = max(1u, addr + size) - 1;
-
-	if (pitch)
-		addr |= 1 << 31;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i];
 
-	nv_wr32(dev, NV10_PGRAPH_TLIMIT(i), limit);
-	nv_wr32(dev, NV10_PGRAPH_TSIZE(i), pitch);
-	nv_wr32(dev, NV10_PGRAPH_TILE(i), addr);
+	nv_wr32(dev, NV10_PGRAPH_TLIMIT(i), tile->limit);
+	nv_wr32(dev, NV10_PGRAPH_TSIZE(i), tile->pitch);
+	nv_wr32(dev, NV10_PGRAPH_TILE(i), tile->addr);
 }
 
 int nv10_graph_init(struct drm_device *dev)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	uint32_t tmp;
-	int i;
+	int ret, i;
 
 	nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) &
 			~NV_PMC_ENABLE_PGRAPH);
 	nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) |
 			 NV_PMC_ENABLE_PGRAPH);
 
+	ret = nv10_graph_register(dev);
+	if (ret)
+		return ret;
+
+	nouveau_irq_register(dev, 12, nv10_graph_isr);
 	nv_wr32(dev, NV03_PGRAPH_INTR   , 0xFFFFFFFF);
 	nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0xFFFFFFFF);
 
@@ -928,7 +945,7 @@ int nv10_graph_init(struct drm_device *d
 
 	/* Turn all the tiling regions off. */
 	for (i = 0; i < NV10_PFB_TILE__SIZE; i++)
-		nv10_graph_set_region_tiling(dev, i, 0, 0, 0);
+		nv10_graph_set_tile_region(dev, i);
 
 	nv_wr32(dev, NV10_PGRAPH_CTX_SWITCH(0), 0x00000000);
 	nv_wr32(dev, NV10_PGRAPH_CTX_SWITCH(1), 0x00000000);
@@ -948,17 +965,17 @@ int nv10_graph_init(struct drm_device *d
 
 void nv10_graph_takedown(struct drm_device *dev)
 {
+	nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0x00000000);
+	nouveau_irq_unregister(dev, 12);
 }
 
 static int
-nv17_graph_mthd_lma_window(struct nouveau_channel *chan, int grclass,
-			   int mthd, uint32_t data)
+nv17_graph_mthd_lma_window(struct nouveau_channel *chan,
+			   u32 class, u32 mthd, u32 data)
 {
 	struct drm_device *dev = chan->dev;
 	struct graph_state *ctx = chan->pgraph_ctx;
 	struct pipe_state *pipe = &ctx->pipe_state;
-	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
 	uint32_t pipe_0x0040[1], pipe_0x64c0[8], pipe_0x6a80[3], pipe_0x6ab0[3];
 	uint32_t xfmode0, xfmode1;
 	int i;
@@ -1025,18 +1042,14 @@ nv17_graph_mthd_lma_window(struct nouvea
 
 	nouveau_wait_for_idle(dev);
 
-	pgraph->fifo_access(dev, true);
-
 	return 0;
 }
 
 static int
-nv17_graph_mthd_lma_enable(struct nouveau_channel *chan, int grclass,
-			   int mthd, uint32_t data)
+nv17_graph_mthd_lma_enable(struct nouveau_channel *chan,
+			   u32 class, u32 mthd, u32 data)
 {
 	struct drm_device *dev = chan->dev;
-	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
 
 	nouveau_wait_for_idle(dev);
 
@@ -1045,40 +1058,118 @@ nv17_graph_mthd_lma_enable(struct nouvea
 	nv_wr32(dev, 0x004006b0,
 		nv_rd32(dev, 0x004006b0) | 0x8 << 24);
 
-	pgraph->fifo_access(dev, true);
+	return 0;
+}
+
+static int
+nv10_graph_register(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
 
+	if (dev_priv->engine.graph.registered)
+		return 0;
+
+	NVOBJ_CLASS(dev, 0x506e, SW); /* nvsw */
+	NVOBJ_CLASS(dev, 0x0030, GR); /* null */
+	NVOBJ_CLASS(dev, 0x0039, GR); /* m2mf */
+	NVOBJ_CLASS(dev, 0x004a, GR); /* gdirect */
+	NVOBJ_CLASS(dev, 0x005f, GR); /* imageblit */
+	NVOBJ_CLASS(dev, 0x009f, GR); /* imageblit (nv12) */
+	NVOBJ_CLASS(dev, 0x008a, GR); /* ifc */
+	NVOBJ_CLASS(dev, 0x0089, GR); /* sifm */
+	NVOBJ_CLASS(dev, 0x0062, GR); /* surf2d */
+	NVOBJ_CLASS(dev, 0x0043, GR); /* rop */
+	NVOBJ_CLASS(dev, 0x0012, GR); /* beta1 */
+	NVOBJ_CLASS(dev, 0x0072, GR); /* beta4 */
+	NVOBJ_CLASS(dev, 0x0019, GR); /* cliprect */
+	NVOBJ_CLASS(dev, 0x0044, GR); /* pattern */
+	NVOBJ_CLASS(dev, 0x0052, GR); /* swzsurf */
+	NVOBJ_CLASS(dev, 0x0093, GR); /* surf3d */
+	NVOBJ_CLASS(dev, 0x0094, GR); /* tex_tri */
+	NVOBJ_CLASS(dev, 0x0095, GR); /* multitex_tri */
+
+	/* celcius */
+	if (dev_priv->chipset <= 0x10) {
+		NVOBJ_CLASS(dev, 0x0056, GR);
+	} else
+	if (dev_priv->chipset < 0x17 || dev_priv->chipset == 0x1a) {
+		NVOBJ_CLASS(dev, 0x0096, GR);
+	} else {
+		NVOBJ_CLASS(dev, 0x0099, GR);
+		NVOBJ_MTHD (dev, 0x0099, 0x1638, nv17_graph_mthd_lma_window);
+		NVOBJ_MTHD (dev, 0x0099, 0x163c, nv17_graph_mthd_lma_window);
+		NVOBJ_MTHD (dev, 0x0099, 0x1640, nv17_graph_mthd_lma_window);
+		NVOBJ_MTHD (dev, 0x0099, 0x1644, nv17_graph_mthd_lma_window);
+		NVOBJ_MTHD (dev, 0x0099, 0x1658, nv17_graph_mthd_lma_enable);
+	}
+
+	/* nvsw */
+	NVOBJ_CLASS(dev, 0x506e, SW);
+	NVOBJ_MTHD (dev, 0x506e, 0x0500, nv04_graph_mthd_page_flip);
+
+	dev_priv->engine.graph.registered = true;
 	return 0;
 }
 
-static struct nouveau_pgraph_object_method nv17_graph_celsius_mthds[] = {
-	{ 0x1638, nv17_graph_mthd_lma_window },
-	{ 0x163c, nv17_graph_mthd_lma_window },
-	{ 0x1640, nv17_graph_mthd_lma_window },
-	{ 0x1644, nv17_graph_mthd_lma_window },
-	{ 0x1658, nv17_graph_mthd_lma_enable },
+struct nouveau_bitfield nv10_graph_intr[] = {
+	{ NV_PGRAPH_INTR_NOTIFY, "NOTIFY" },
+	{ NV_PGRAPH_INTR_ERROR,  "ERROR"  },
 	{}
 };
 
-struct nouveau_pgraph_object_class nv10_graph_grclass[] = {
-	{ 0x0030, false, NULL }, /* null */
-	{ 0x0039, false, NULL }, /* m2mf */
-	{ 0x004a, false, NULL }, /* gdirect */
-	{ 0x005f, false, NULL }, /* imageblit */
-	{ 0x009f, false, NULL }, /* imageblit (nv12) */
-	{ 0x008a, false, NULL }, /* ifc */
-	{ 0x0089, false, NULL }, /* sifm */
-	{ 0x0062, false, NULL }, /* surf2d */
-	{ 0x0043, false, NULL }, /* rop */
-	{ 0x0012, false, NULL }, /* beta1 */
-	{ 0x0072, false, NULL }, /* beta4 */
-	{ 0x0019, false, NULL }, /* cliprect */
-	{ 0x0044, false, NULL }, /* pattern */
-	{ 0x0052, false, NULL }, /* swzsurf */
-	{ 0x0093, false, NULL }, /* surf3d */
-	{ 0x0094, false, NULL }, /* tex_tri */
-	{ 0x0095, false, NULL }, /* multitex_tri */
-	{ 0x0056, false, NULL }, /* celcius (nv10) */
-	{ 0x0096, false, NULL }, /* celcius (nv11) */
-	{ 0x0099, false, nv17_graph_celsius_mthds }, /* celcius (nv17) */
+struct nouveau_bitfield nv10_graph_nstatus[] =
+{
+	{ NV10_PGRAPH_NSTATUS_STATE_IN_USE,       "STATE_IN_USE" },
+	{ NV10_PGRAPH_NSTATUS_INVALID_STATE,      "INVALID_STATE" },
+	{ NV10_PGRAPH_NSTATUS_BAD_ARGUMENT,       "BAD_ARGUMENT" },
+	{ NV10_PGRAPH_NSTATUS_PROTECTION_FAULT,   "PROTECTION_FAULT" },
 	{}
 };
+
+static void
+nv10_graph_isr(struct drm_device *dev)
+{
+	u32 stat;
+
+	while ((stat = nv_rd32(dev, NV03_PGRAPH_INTR))) {
+		u32 nsource = nv_rd32(dev, NV03_PGRAPH_NSOURCE);
+		u32 nstatus = nv_rd32(dev, NV03_PGRAPH_NSTATUS);
+		u32 addr = nv_rd32(dev, NV04_PGRAPH_TRAPPED_ADDR);
+		u32 chid = (addr & 0x01f00000) >> 20;
+		u32 subc = (addr & 0x00070000) >> 16;
+		u32 mthd = (addr & 0x00001ffc);
+		u32 data = nv_rd32(dev, NV04_PGRAPH_TRAPPED_DATA);
+		u32 class = nv_rd32(dev, 0x400160 + subc * 4) & 0xfff;
+		u32 show = stat;
+
+		if (stat & NV_PGRAPH_INTR_ERROR) {
+			if (nsource & NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD) {
+				if (!nouveau_gpuobj_mthd_call2(dev, chid, class, mthd, data))
+					show &= ~NV_PGRAPH_INTR_ERROR;
+			}
+		}
+
+		if (stat & NV_PGRAPH_INTR_CONTEXT_SWITCH) {
+			nv_wr32(dev, NV03_PGRAPH_INTR, NV_PGRAPH_INTR_CONTEXT_SWITCH);
+			stat &= ~NV_PGRAPH_INTR_CONTEXT_SWITCH;
+			show &= ~NV_PGRAPH_INTR_CONTEXT_SWITCH;
+			nv10_graph_context_switch(dev);
+		}
+
+		nv_wr32(dev, NV03_PGRAPH_INTR, stat);
+		nv_wr32(dev, NV04_PGRAPH_FIFO, 0x00000001);
+
+		if (show && nouveau_ratelimit()) {
+			NV_INFO(dev, "PGRAPH -");
+			nouveau_bitfield_print(nv10_graph_intr, show);
+			printk(" nsource:");
+			nouveau_bitfield_print(nv04_graph_nsource, nsource);
+			printk(" nstatus:");
+			nouveau_bitfield_print(nv10_graph_nstatus, nstatus);
+			printk("\n");
+			NV_INFO(dev, "PGRAPH - ch %d/%d class 0x%04x "
+				     "mthd 0x%04x data 0x%08x\n",
+				chid, subc, class, mthd, data);
+		}
+	}
+}
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nv20_graph.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nv20_graph.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nv20_graph.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nv20_graph.c	2011-03-14 21:20:32.000000000 -0400
@@ -32,6 +32,10 @@
 #define NV34_GRCTX_SIZE    (18140)
 #define NV35_36_GRCTX_SIZE (22396)
 
+static int nv20_graph_register(struct drm_device *);
+static int nv30_graph_register(struct drm_device *);
+static void nv20_graph_isr(struct drm_device *);
+
 static void
 nv20_graph_context_init(struct drm_device *dev, struct nouveau_gpuobj *ctx)
 {
@@ -425,9 +429,21 @@ nv20_graph_destroy_context(struct nouvea
 	struct drm_device *dev = chan->dev;
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
+	unsigned long flags;
 
-	nouveau_gpuobj_ref(NULL, &chan->ramin_grctx);
+	spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
+	pgraph->fifo_access(dev, false);
+
+	/* Unload the context if it's the currently active one */
+	if (pgraph->channel(dev) == chan)
+		pgraph->unload_context(dev);
+
+	pgraph->fifo_access(dev, true);
+	spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
+
+	/* Free the context resources */
 	nv_wo32(pgraph->ctx_table, chan->id * 4, 0);
+	nouveau_gpuobj_ref(NULL, &chan->ramin_grctx);
 }
 
 int
@@ -496,24 +512,27 @@ nv20_graph_rdi(struct drm_device *dev)
 }
 
 void
-nv20_graph_set_region_tiling(struct drm_device *dev, int i, uint32_t addr,
-			     uint32_t size, uint32_t pitch)
+nv20_graph_set_tile_region(struct drm_device *dev, int i)
 {
-	uint32_t limit = max(1u, addr + size) - 1;
-
-	if (pitch)
-		addr |= 1;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i];
 
-	nv_wr32(dev, NV20_PGRAPH_TLIMIT(i), limit);
-	nv_wr32(dev, NV20_PGRAPH_TSIZE(i), pitch);
-	nv_wr32(dev, NV20_PGRAPH_TILE(i), addr);
+	nv_wr32(dev, NV20_PGRAPH_TLIMIT(i), tile->limit);
+	nv_wr32(dev, NV20_PGRAPH_TSIZE(i), tile->pitch);
+	nv_wr32(dev, NV20_PGRAPH_TILE(i), tile->addr);
 
 	nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00EA0030 + 4 * i);
-	nv_wr32(dev, NV10_PGRAPH_RDI_DATA, limit);
+	nv_wr32(dev, NV10_PGRAPH_RDI_DATA, tile->limit);
 	nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00EA0050 + 4 * i);
-	nv_wr32(dev, NV10_PGRAPH_RDI_DATA, pitch);
+	nv_wr32(dev, NV10_PGRAPH_RDI_DATA, tile->pitch);
 	nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00EA0010 + 4 * i);
-	nv_wr32(dev, NV10_PGRAPH_RDI_DATA, addr);
+	nv_wr32(dev, NV10_PGRAPH_RDI_DATA, tile->addr);
+
+	if (dev_priv->card_type == NV_20) {
+		nv_wr32(dev, NV20_PGRAPH_ZCOMP(i), tile->zcomp);
+		nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00ea0090 + 4 * i);
+		nv_wr32(dev, NV10_PGRAPH_RDI_DATA, tile->zcomp);
+	}
 }
 
 int
@@ -560,6 +579,13 @@ nv20_graph_init(struct drm_device *dev)
 
 	nv20_graph_rdi(dev);
 
+	ret = nv20_graph_register(dev);
+	if (ret) {
+		nouveau_gpuobj_ref(NULL, &pgraph->ctx_table);
+		return ret;
+	}
+
+	nouveau_irq_register(dev, 12, nv20_graph_isr);
 	nv_wr32(dev, NV03_PGRAPH_INTR   , 0xFFFFFFFF);
 	nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0xFFFFFFFF);
 
@@ -571,16 +597,17 @@ nv20_graph_init(struct drm_device *dev)
 	nv_wr32(dev, 0x40009C           , 0x00000040);
 
 	if (dev_priv->chipset >= 0x25) {
-		nv_wr32(dev, 0x400890, 0x00080000);
+		nv_wr32(dev, 0x400890, 0x00a8cfff);
 		nv_wr32(dev, 0x400610, 0x304B1FB6);
-		nv_wr32(dev, 0x400B80, 0x18B82880);
+		nv_wr32(dev, 0x400B80, 0x1cbd3883);
 		nv_wr32(dev, 0x400B84, 0x44000000);
 		nv_wr32(dev, 0x400098, 0x40000080);
 		nv_wr32(dev, 0x400B88, 0x000000ff);
+
 	} else {
-		nv_wr32(dev, 0x400880, 0x00080000); /* 0x0008c7df */
+		nv_wr32(dev, 0x400880, 0x0008c7df);
 		nv_wr32(dev, 0x400094, 0x00000005);
-		nv_wr32(dev, 0x400B80, 0x45CAA208); /* 0x45eae20e */
+		nv_wr32(dev, 0x400B80, 0x45eae20e);
 		nv_wr32(dev, 0x400B84, 0x24000000);
 		nv_wr32(dev, 0x400098, 0x00000040);
 		nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00E00038);
@@ -591,14 +618,8 @@ nv20_graph_init(struct drm_device *dev)
 
 	/* Turn all the tiling regions off. */
 	for (i = 0; i < NV10_PFB_TILE__SIZE; i++)
-		nv20_graph_set_region_tiling(dev, i, 0, 0, 0);
+		nv20_graph_set_tile_region(dev, i);
 
-	for (i = 0; i < 8; i++) {
-		nv_wr32(dev, 0x400980 + i * 4, nv_rd32(dev, 0x100300 + i * 4));
-		nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00EA0090 + i * 4);
-		nv_wr32(dev, NV10_PGRAPH_RDI_DATA,
-					nv_rd32(dev, 0x100300 + i * 4));
-	}
 	nv_wr32(dev, 0x4009a0, nv_rd32(dev, 0x100324));
 	nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00EA000C);
 	nv_wr32(dev, NV10_PGRAPH_RDI_DATA, nv_rd32(dev, 0x100324));
@@ -642,6 +663,9 @@ nv20_graph_takedown(struct drm_device *d
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
 
+	nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0x00000000);
+	nouveau_irq_unregister(dev, 12);
+
 	nouveau_gpuobj_ref(NULL, &pgraph->ctx_table);
 }
 
@@ -684,9 +708,16 @@ nv30_graph_init(struct drm_device *dev)
 			return ret;
 	}
 
+	ret = nv30_graph_register(dev);
+	if (ret) {
+		nouveau_gpuobj_ref(NULL, &pgraph->ctx_table);
+		return ret;
+	}
+
 	nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_TABLE,
 		     pgraph->ctx_table->pinst >> 4);
 
+	nouveau_irq_register(dev, 12, nv20_graph_isr);
 	nv_wr32(dev, NV03_PGRAPH_INTR   , 0xFFFFFFFF);
 	nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0xFFFFFFFF);
 
@@ -724,7 +755,7 @@ nv30_graph_init(struct drm_device *dev)
 
 	/* Turn all the tiling regions off. */
 	for (i = 0; i < NV10_PFB_TILE__SIZE; i++)
-		nv20_graph_set_region_tiling(dev, i, 0, 0, 0);
+		nv20_graph_set_tile_region(dev, i);
 
 	nv_wr32(dev, NV10_PGRAPH_CTX_CONTROL, 0x10000100);
 	nv_wr32(dev, NV10_PGRAPH_STATE      , 0xFFFFFFFF);
@@ -744,46 +775,125 @@ nv30_graph_init(struct drm_device *dev)
 	return 0;
 }
 
-struct nouveau_pgraph_object_class nv20_graph_grclass[] = {
-	{ 0x0030, false, NULL }, /* null */
-	{ 0x0039, false, NULL }, /* m2mf */
-	{ 0x004a, false, NULL }, /* gdirect */
-	{ 0x009f, false, NULL }, /* imageblit (nv12) */
-	{ 0x008a, false, NULL }, /* ifc */
-	{ 0x0089, false, NULL }, /* sifm */
-	{ 0x0062, false, NULL }, /* surf2d */
-	{ 0x0043, false, NULL }, /* rop */
-	{ 0x0012, false, NULL }, /* beta1 */
-	{ 0x0072, false, NULL }, /* beta4 */
-	{ 0x0019, false, NULL }, /* cliprect */
-	{ 0x0044, false, NULL }, /* pattern */
-	{ 0x009e, false, NULL }, /* swzsurf */
-	{ 0x0096, false, NULL }, /* celcius */
-	{ 0x0097, false, NULL }, /* kelvin (nv20) */
-	{ 0x0597, false, NULL }, /* kelvin (nv25) */
-	{}
-};
+static int
+nv20_graph_register(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
 
-struct nouveau_pgraph_object_class nv30_graph_grclass[] = {
-	{ 0x0030, false, NULL }, /* null */
-	{ 0x0039, false, NULL }, /* m2mf */
-	{ 0x004a, false, NULL }, /* gdirect */
-	{ 0x009f, false, NULL }, /* imageblit (nv12) */
-	{ 0x008a, false, NULL }, /* ifc */
-	{ 0x038a, false, NULL }, /* ifc (nv30) */
-	{ 0x0089, false, NULL }, /* sifm */
-	{ 0x0389, false, NULL }, /* sifm (nv30) */
-	{ 0x0062, false, NULL }, /* surf2d */
-	{ 0x0362, false, NULL }, /* surf2d (nv30) */
-	{ 0x0043, false, NULL }, /* rop */
-	{ 0x0012, false, NULL }, /* beta1 */
-	{ 0x0072, false, NULL }, /* beta4 */
-	{ 0x0019, false, NULL }, /* cliprect */
-	{ 0x0044, false, NULL }, /* pattern */
-	{ 0x039e, false, NULL }, /* swzsurf */
-	{ 0x0397, false, NULL }, /* rankine (nv30) */
-	{ 0x0497, false, NULL }, /* rankine (nv35) */
-	{ 0x0697, false, NULL }, /* rankine (nv34) */
-	{}
-};
+	if (dev_priv->engine.graph.registered)
+		return 0;
 
+	NVOBJ_CLASS(dev, 0x506e, SW); /* nvsw */
+	NVOBJ_CLASS(dev, 0x0030, GR); /* null */
+	NVOBJ_CLASS(dev, 0x0039, GR); /* m2mf */
+	NVOBJ_CLASS(dev, 0x004a, GR); /* gdirect */
+	NVOBJ_CLASS(dev, 0x009f, GR); /* imageblit (nv12) */
+	NVOBJ_CLASS(dev, 0x008a, GR); /* ifc */
+	NVOBJ_CLASS(dev, 0x0089, GR); /* sifm */
+	NVOBJ_CLASS(dev, 0x0062, GR); /* surf2d */
+	NVOBJ_CLASS(dev, 0x0043, GR); /* rop */
+	NVOBJ_CLASS(dev, 0x0012, GR); /* beta1 */
+	NVOBJ_CLASS(dev, 0x0072, GR); /* beta4 */
+	NVOBJ_CLASS(dev, 0x0019, GR); /* cliprect */
+	NVOBJ_CLASS(dev, 0x0044, GR); /* pattern */
+	NVOBJ_CLASS(dev, 0x009e, GR); /* swzsurf */
+	NVOBJ_CLASS(dev, 0x0096, GR); /* celcius */
+
+	/* kelvin */
+	if (dev_priv->chipset < 0x25)
+		NVOBJ_CLASS(dev, 0x0097, GR);
+	else
+		NVOBJ_CLASS(dev, 0x0597, GR);
+
+	/* nvsw */
+	NVOBJ_CLASS(dev, 0x506e, SW);
+	NVOBJ_MTHD (dev, 0x506e, 0x0500, nv04_graph_mthd_page_flip);
+
+	dev_priv->engine.graph.registered = true;
+	return 0;
+}
+
+static int
+nv30_graph_register(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+	if (dev_priv->engine.graph.registered)
+		return 0;
+
+	NVOBJ_CLASS(dev, 0x506e, SW); /* nvsw */
+	NVOBJ_CLASS(dev, 0x0030, GR); /* null */
+	NVOBJ_CLASS(dev, 0x0039, GR); /* m2mf */
+	NVOBJ_CLASS(dev, 0x004a, GR); /* gdirect */
+	NVOBJ_CLASS(dev, 0x009f, GR); /* imageblit (nv12) */
+	NVOBJ_CLASS(dev, 0x008a, GR); /* ifc */
+	NVOBJ_CLASS(dev, 0x038a, GR); /* ifc (nv30) */
+	NVOBJ_CLASS(dev, 0x0089, GR); /* sifm */
+	NVOBJ_CLASS(dev, 0x0389, GR); /* sifm (nv30) */
+	NVOBJ_CLASS(dev, 0x0062, GR); /* surf2d */
+	NVOBJ_CLASS(dev, 0x0362, GR); /* surf2d (nv30) */
+	NVOBJ_CLASS(dev, 0x0043, GR); /* rop */
+	NVOBJ_CLASS(dev, 0x0012, GR); /* beta1 */
+	NVOBJ_CLASS(dev, 0x0072, GR); /* beta4 */
+	NVOBJ_CLASS(dev, 0x0019, GR); /* cliprect */
+	NVOBJ_CLASS(dev, 0x0044, GR); /* pattern */
+	NVOBJ_CLASS(dev, 0x039e, GR); /* swzsurf */
+
+	/* rankine */
+	if (0x00000003 & (1 << (dev_priv->chipset & 0x0f)))
+		NVOBJ_CLASS(dev, 0x0397, GR);
+	else
+	if (0x00000010 & (1 << (dev_priv->chipset & 0x0f)))
+		NVOBJ_CLASS(dev, 0x0697, GR);
+	else
+	if (0x000001e0 & (1 << (dev_priv->chipset & 0x0f)))
+		NVOBJ_CLASS(dev, 0x0497, GR);
+
+	/* nvsw */
+	NVOBJ_CLASS(dev, 0x506e, SW);
+	NVOBJ_MTHD (dev, 0x506e, 0x0500, nv04_graph_mthd_page_flip);
+
+	dev_priv->engine.graph.registered = true;
+	return 0;
+}
+
+static void
+nv20_graph_isr(struct drm_device *dev)
+{
+	u32 stat;
+
+	while ((stat = nv_rd32(dev, NV03_PGRAPH_INTR))) {
+		u32 nsource = nv_rd32(dev, NV03_PGRAPH_NSOURCE);
+		u32 nstatus = nv_rd32(dev, NV03_PGRAPH_NSTATUS);
+		u32 addr = nv_rd32(dev, NV04_PGRAPH_TRAPPED_ADDR);
+		u32 chid = (addr & 0x01f00000) >> 20;
+		u32 subc = (addr & 0x00070000) >> 16;
+		u32 mthd = (addr & 0x00001ffc);
+		u32 data = nv_rd32(dev, NV04_PGRAPH_TRAPPED_DATA);
+		u32 class = nv_rd32(dev, 0x400160 + subc * 4) & 0xfff;
+		u32 show = stat;
+
+		if (stat & NV_PGRAPH_INTR_ERROR) {
+			if (nsource & NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD) {
+				if (!nouveau_gpuobj_mthd_call2(dev, chid, class, mthd, data))
+					show &= ~NV_PGRAPH_INTR_ERROR;
+			}
+		}
+
+		nv_wr32(dev, NV03_PGRAPH_INTR, stat);
+		nv_wr32(dev, NV04_PGRAPH_FIFO, 0x00000001);
+
+		if (show && nouveau_ratelimit()) {
+			NV_INFO(dev, "PGRAPH -");
+			nouveau_bitfield_print(nv10_graph_intr, show);
+			printk(" nsource:");
+			nouveau_bitfield_print(nv04_graph_nsource, nsource);
+			printk(" nstatus:");
+			nouveau_bitfield_print(nv10_graph_nstatus, nstatus);
+			printk("\n");
+			NV_INFO(dev, "PGRAPH - ch %d/%d class 0x%04x "
+				     "mthd 0x%04x data 0x%08x\n",
+				chid, subc, class, mthd, data);
+		}
+	}
+}
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nv30_fb.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nv30_fb.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nv30_fb.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nv30_fb.c	2011-03-14 21:20:32.000000000 -0400
@@ -29,6 +29,27 @@
 #include "nouveau_drv.h"
 #include "nouveau_drm.h"
 
+void
+nv30_fb_init_tile_region(struct drm_device *dev, int i, uint32_t addr,
+			 uint32_t size, uint32_t pitch, uint32_t flags)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i];
+
+	tile->addr = addr | 1;
+	tile->limit = max(1u, addr + size) - 1;
+	tile->pitch = pitch;
+}
+
+void
+nv30_fb_free_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];
+
+	tile->addr = tile->limit = tile->pitch = 0;
+}
+
 static int
 calc_bias(struct drm_device *dev, int k, int i, int j)
 {
@@ -65,7 +86,7 @@ nv30_fb_init(struct drm_device *dev)
 
 	/* Turn all the tiling regions off. */
 	for (i = 0; i < pfb->num_tiles; i++)
-		pfb->set_region_tiling(dev, i, 0, 0, 0);
+		pfb->set_tile_region(dev, i);
 
 	/* Init the memory timing regs at 0x10037c/0x1003ac */
 	if (dev_priv->chipset == 0x30 ||
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nv40_fb.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nv40_fb.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nv40_fb.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nv40_fb.c	2011-03-14 21:20:32.000000000 -0400
@@ -4,26 +4,22 @@
 #include "nouveau_drm.h"
 
 void
-nv40_fb_set_region_tiling(struct drm_device *dev, int i, uint32_t addr,
-			  uint32_t size, uint32_t pitch)
+nv40_fb_set_tile_region(struct drm_device *dev, int i)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	uint32_t limit = max(1u, addr + size) - 1;
-
-	if (pitch)
-		addr |= 1;
+	struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i];
 
 	switch (dev_priv->chipset) {
 	case 0x40:
-		nv_wr32(dev, NV10_PFB_TLIMIT(i), limit);
-		nv_wr32(dev, NV10_PFB_TSIZE(i), pitch);
-		nv_wr32(dev, NV10_PFB_TILE(i), addr);
+		nv_wr32(dev, NV10_PFB_TLIMIT(i), tile->limit);
+		nv_wr32(dev, NV10_PFB_TSIZE(i), tile->pitch);
+		nv_wr32(dev, NV10_PFB_TILE(i), tile->addr);
 		break;
 
 	default:
-		nv_wr32(dev, NV40_PFB_TLIMIT(i), limit);
-		nv_wr32(dev, NV40_PFB_TSIZE(i), pitch);
-		nv_wr32(dev, NV40_PFB_TILE(i), addr);
+		nv_wr32(dev, NV40_PFB_TLIMIT(i), tile->limit);
+		nv_wr32(dev, NV40_PFB_TSIZE(i), tile->pitch);
+		nv_wr32(dev, NV40_PFB_TILE(i), tile->addr);
 		break;
 	}
 }
@@ -64,7 +60,7 @@ nv40_fb_init(struct drm_device *dev)
 
 	/* Turn all the tiling regions off. */
 	for (i = 0; i < pfb->num_tiles; i++)
-		pfb->set_region_tiling(dev, i, 0, 0, 0);
+		pfb->set_tile_region(dev, i);
 
 	return 0;
 }
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nv40_fifo.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nv40_fifo.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nv40_fifo.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nv40_fifo.c	2011-03-14 21:20:32.000000000 -0400
@@ -47,6 +47,11 @@ nv40_fifo_create_context(struct nouveau_
 	if (ret)
 		return ret;
 
+	chan->user = ioremap(pci_resource_start(dev->pdev, 0) +
+			     NV40_USER(chan->id), PAGE_SIZE);
+	if (!chan->user)
+		return -ENOMEM;
+
 	spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
 
 	nv_wi32(dev, fc +  0, chan->pushbuf_base);
@@ -59,7 +64,6 @@ nv40_fifo_create_context(struct nouveau_
 			      NV_PFIFO_CACHE1_BIG_ENDIAN |
 #endif
 			      0x30000000 /* no idea.. */);
-	nv_wi32(dev, fc + 56, chan->ramin_grctx->pinst >> 4);
 	nv_wi32(dev, fc + 60, 0x0001FFFF);
 
 	/* enable the fifo dma operation */
@@ -70,17 +74,6 @@ nv40_fifo_create_context(struct nouveau_
 	return 0;
 }
 
-void
-nv40_fifo_destroy_context(struct nouveau_channel *chan)
-{
-	struct drm_device *dev = chan->dev;
-
-	nv_wr32(dev, NV04_PFIFO_MODE,
-		nv_rd32(dev, NV04_PFIFO_MODE) & ~(1 << chan->id));
-
-	nouveau_gpuobj_ref(NULL, &chan->ramfc);
-}
-
 static void
 nv40_fifo_do_load_context(struct drm_device *dev, int chid)
 {
@@ -279,6 +272,7 @@ nv40_fifo_init_ramxx(struct drm_device *
 static void
 nv40_fifo_init_intr(struct drm_device *dev)
 {
+	nouveau_irq_register(dev, 8, nv04_fifo_isr);
 	nv_wr32(dev, 0x002100, 0xffffffff);
 	nv_wr32(dev, 0x002140, 0xffffffff);
 }
@@ -301,7 +295,7 @@ nv40_fifo_init(struct drm_device *dev)
 	pfifo->reassign(dev, true);
 
 	for (i = 0; i < dev_priv->engine.fifo.channels; i++) {
-		if (dev_priv->fifos[i]) {
+		if (dev_priv->channels.ptr[i]) {
 			uint32_t mode = nv_rd32(dev, NV04_PFIFO_MODE);
 			nv_wr32(dev, NV04_PFIFO_MODE, mode | (1 << i));
 		}
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nv40_graph.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nv40_graph.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nv40_graph.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nv40_graph.c	2011-03-14 21:20:32.000000000 -0400
@@ -29,6 +29,9 @@
 #include "nouveau_drv.h"
 #include "nouveau_grctx.h"
 
+static int nv40_graph_register(struct drm_device *);
+static void nv40_graph_isr(struct drm_device *);
+
 struct nouveau_channel *
 nv40_graph_channel(struct drm_device *dev)
 {
@@ -42,7 +45,7 @@ nv40_graph_channel(struct drm_device *de
 	inst = (inst & NV40_PGRAPH_CTXCTL_CUR_INSTANCE) << 4;
 
 	for (i = 0; i < dev_priv->engine.fifo.channels; i++) {
-		struct nouveau_channel *chan = dev_priv->fifos[i];
+		struct nouveau_channel *chan = dev_priv->channels.ptr[i];
 
 		if (chan && chan->ramin_grctx &&
 		    chan->ramin_grctx->pinst == inst)
@@ -59,6 +62,7 @@ nv40_graph_create_context(struct nouveau
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
 	struct nouveau_grctx ctx = {};
+	unsigned long flags;
 	int ret;
 
 	ret = nouveau_gpuobj_new(dev, chan, pgraph->grctx_size, 16,
@@ -73,12 +77,39 @@ nv40_graph_create_context(struct nouveau
 	nv40_grctx_init(&ctx);
 
 	nv_wo32(chan->ramin_grctx, 0, chan->ramin_grctx->pinst);
+
+	/* init grctx pointer in ramfc, and on PFIFO if channel is
+	 * already active there
+	 */
+	spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
+	nv_wo32(chan->ramfc, 0x38, chan->ramin_grctx->pinst >> 4);
+	nv_mask(dev, 0x002500, 0x00000001, 0x00000000);
+	if ((nv_rd32(dev, 0x003204) & 0x0000001f) == chan->id)
+		nv_wr32(dev, 0x0032e0, chan->ramin_grctx->pinst >> 4);
+	nv_mask(dev, 0x002500, 0x00000001, 0x00000001);
+	spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
 	return 0;
 }
 
 void
 nv40_graph_destroy_context(struct nouveau_channel *chan)
 {
+	struct drm_device *dev = chan->dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
+	unsigned long flags;
+
+	spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
+	pgraph->fifo_access(dev, false);
+
+	/* Unload the context if it's the currently active one */
+	if (pgraph->channel(dev) == chan)
+		pgraph->unload_context(dev);
+
+	pgraph->fifo_access(dev, true);
+	spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
+
+	/* Free the context resources */
 	nouveau_gpuobj_ref(NULL, &chan->ramin_grctx);
 }
 
@@ -174,43 +205,44 @@ nv40_graph_unload_context(struct drm_dev
 }
 
 void
-nv40_graph_set_region_tiling(struct drm_device *dev, int i, uint32_t addr,
-			     uint32_t size, uint32_t pitch)
+nv40_graph_set_tile_region(struct drm_device *dev, int i)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	uint32_t limit = max(1u, addr + size) - 1;
-
-	if (pitch)
-		addr |= 1;
+	struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i];
 
 	switch (dev_priv->chipset) {
+	case 0x40:
+	case 0x41: /* guess */
+	case 0x42:
+	case 0x43:
+	case 0x45: /* guess */
+	case 0x4e:
+		nv_wr32(dev, NV20_PGRAPH_TSIZE(i), tile->pitch);
+		nv_wr32(dev, NV20_PGRAPH_TLIMIT(i), tile->limit);
+		nv_wr32(dev, NV20_PGRAPH_TILE(i), tile->addr);
+		nv_wr32(dev, NV40_PGRAPH_TSIZE1(i), tile->pitch);
+		nv_wr32(dev, NV40_PGRAPH_TLIMIT1(i), tile->limit);
+		nv_wr32(dev, NV40_PGRAPH_TILE1(i), tile->addr);
+		break;
 	case 0x44:
 	case 0x4a:
-	case 0x4e:
-		nv_wr32(dev, NV20_PGRAPH_TSIZE(i), pitch);
-		nv_wr32(dev, NV20_PGRAPH_TLIMIT(i), limit);
-		nv_wr32(dev, NV20_PGRAPH_TILE(i), addr);
+		nv_wr32(dev, NV20_PGRAPH_TSIZE(i), tile->pitch);
+		nv_wr32(dev, NV20_PGRAPH_TLIMIT(i), tile->limit);
+		nv_wr32(dev, NV20_PGRAPH_TILE(i), tile->addr);
 		break;
-
 	case 0x46:
 	case 0x47:
 	case 0x49:
 	case 0x4b:
-		nv_wr32(dev, NV47_PGRAPH_TSIZE(i), pitch);
-		nv_wr32(dev, NV47_PGRAPH_TLIMIT(i), limit);
-		nv_wr32(dev, NV47_PGRAPH_TILE(i), addr);
-		nv_wr32(dev, NV40_PGRAPH_TSIZE1(i), pitch);
-		nv_wr32(dev, NV40_PGRAPH_TLIMIT1(i), limit);
-		nv_wr32(dev, NV40_PGRAPH_TILE1(i), addr);
-		break;
-
+	case 0x4c:
+	case 0x67:
 	default:
-		nv_wr32(dev, NV20_PGRAPH_TSIZE(i), pitch);
-		nv_wr32(dev, NV20_PGRAPH_TLIMIT(i), limit);
-		nv_wr32(dev, NV20_PGRAPH_TILE(i), addr);
-		nv_wr32(dev, NV40_PGRAPH_TSIZE1(i), pitch);
-		nv_wr32(dev, NV40_PGRAPH_TLIMIT1(i), limit);
-		nv_wr32(dev, NV40_PGRAPH_TILE1(i), addr);
+		nv_wr32(dev, NV47_PGRAPH_TSIZE(i), tile->pitch);
+		nv_wr32(dev, NV47_PGRAPH_TLIMIT(i), tile->limit);
+		nv_wr32(dev, NV47_PGRAPH_TILE(i), tile->addr);
+		nv_wr32(dev, NV40_PGRAPH_TSIZE1(i), tile->pitch);
+		nv_wr32(dev, NV40_PGRAPH_TLIMIT1(i), tile->limit);
+		nv_wr32(dev, NV40_PGRAPH_TILE1(i), tile->addr);
 		break;
 	}
 }
@@ -232,7 +264,7 @@ nv40_graph_init(struct drm_device *dev)
 	struct nouveau_fb_engine *pfb = &dev_priv->engine.fb;
 	struct nouveau_grctx ctx = {};
 	uint32_t vramsz, *cp;
-	int i, j;
+	int ret, i, j;
 
 	nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) &
 			~NV_PMC_ENABLE_PGRAPH);
@@ -256,9 +288,14 @@ nv40_graph_init(struct drm_device *dev)
 
 	kfree(cp);
 
+	ret = nv40_graph_register(dev);
+	if (ret)
+		return ret;
+
 	/* No context present currently */
 	nv_wr32(dev, NV40_PGRAPH_CTXCTL_CUR, 0x00000000);
 
+	nouveau_irq_register(dev, 12, nv40_graph_isr);
 	nv_wr32(dev, NV03_PGRAPH_INTR   , 0xFFFFFFFF);
 	nv_wr32(dev, NV40_PGRAPH_INTR_EN, 0xFFFFFFFF);
 
@@ -347,7 +384,7 @@ nv40_graph_init(struct drm_device *dev)
 
 	/* Turn all the tiling regions off. */
 	for (i = 0; i < pfb->num_tiles; i++)
-		nv40_graph_set_region_tiling(dev, i, 0, 0, 0);
+		nv40_graph_set_tile_region(dev, i);
 
 	/* begin RAM config */
 	vramsz = pci_resource_len(dev->pdev, 0) - 1;
@@ -364,17 +401,20 @@ nv40_graph_init(struct drm_device *dev)
 		break;
 	default:
 		switch (dev_priv->chipset) {
-		case 0x46:
-		case 0x47:
-		case 0x49:
-		case 0x4b:
-			nv_wr32(dev, 0x400DF0, nv_rd32(dev, NV04_PFB_CFG0));
-			nv_wr32(dev, 0x400DF4, nv_rd32(dev, NV04_PFB_CFG1));
-			break;
-		default:
+		case 0x41:
+		case 0x42:
+		case 0x43:
+		case 0x45:
+		case 0x4e:
+		case 0x44:
+		case 0x4a:
 			nv_wr32(dev, 0x4009F0, nv_rd32(dev, NV04_PFB_CFG0));
 			nv_wr32(dev, 0x4009F4, nv_rd32(dev, NV04_PFB_CFG1));
 			break;
+		default:
+			nv_wr32(dev, 0x400DF0, nv_rd32(dev, NV04_PFB_CFG0));
+			nv_wr32(dev, 0x400DF4, nv_rd32(dev, NV04_PFB_CFG1));
+			break;
 		}
 		nv_wr32(dev, 0x4069F0, nv_rd32(dev, NV04_PFB_CFG0));
 		nv_wr32(dev, 0x4069F4, nv_rd32(dev, NV04_PFB_CFG1));
@@ -390,26 +430,110 @@ nv40_graph_init(struct drm_device *dev)
 
 void nv40_graph_takedown(struct drm_device *dev)
 {
+	nouveau_irq_unregister(dev, 12);
 }
 
-struct nouveau_pgraph_object_class nv40_graph_grclass[] = {
-	{ 0x0030, false, NULL }, /* null */
-	{ 0x0039, false, NULL }, /* m2mf */
-	{ 0x004a, false, NULL }, /* gdirect */
-	{ 0x009f, false, NULL }, /* imageblit (nv12) */
-	{ 0x008a, false, NULL }, /* ifc */
-	{ 0x0089, false, NULL }, /* sifm */
-	{ 0x3089, false, NULL }, /* sifm (nv40) */
-	{ 0x0062, false, NULL }, /* surf2d */
-	{ 0x3062, false, NULL }, /* surf2d (nv40) */
-	{ 0x0043, false, NULL }, /* rop */
-	{ 0x0012, false, NULL }, /* beta1 */
-	{ 0x0072, false, NULL }, /* beta4 */
-	{ 0x0019, false, NULL }, /* cliprect */
-	{ 0x0044, false, NULL }, /* pattern */
-	{ 0x309e, false, NULL }, /* swzsurf */
-	{ 0x4097, false, NULL }, /* curie (nv40) */
-	{ 0x4497, false, NULL }, /* curie (nv44) */
-	{}
-};
+static int
+nv40_graph_register(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+	if (dev_priv->engine.graph.registered)
+		return 0;
+
+	NVOBJ_CLASS(dev, 0x506e, SW); /* nvsw */
+	NVOBJ_CLASS(dev, 0x0030, GR); /* null */
+	NVOBJ_CLASS(dev, 0x0039, GR); /* m2mf */
+	NVOBJ_CLASS(dev, 0x004a, GR); /* gdirect */
+	NVOBJ_CLASS(dev, 0x009f, GR); /* imageblit (nv12) */
+	NVOBJ_CLASS(dev, 0x008a, GR); /* ifc */
+	NVOBJ_CLASS(dev, 0x0089, GR); /* sifm */
+	NVOBJ_CLASS(dev, 0x3089, GR); /* sifm (nv40) */
+	NVOBJ_CLASS(dev, 0x0062, GR); /* surf2d */
+	NVOBJ_CLASS(dev, 0x3062, GR); /* surf2d (nv40) */
+	NVOBJ_CLASS(dev, 0x0043, GR); /* rop */
+	NVOBJ_CLASS(dev, 0x0012, GR); /* beta1 */
+	NVOBJ_CLASS(dev, 0x0072, GR); /* beta4 */
+	NVOBJ_CLASS(dev, 0x0019, GR); /* cliprect */
+	NVOBJ_CLASS(dev, 0x0044, GR); /* pattern */
+	NVOBJ_CLASS(dev, 0x309e, GR); /* swzsurf */
+
+	/* curie */
+	if (nv44_graph_class(dev))
+		NVOBJ_CLASS(dev, 0x4497, GR);
+	else
+		NVOBJ_CLASS(dev, 0x4097, GR);
+
+	/* nvsw */
+	NVOBJ_CLASS(dev, 0x506e, SW);
+	NVOBJ_MTHD (dev, 0x506e, 0x0500, nv04_graph_mthd_page_flip);
+
+	dev_priv->engine.graph.registered = true;
+	return 0;
+}
+
+static int
+nv40_graph_isr_chid(struct drm_device *dev, u32 inst)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_channel *chan;
+	unsigned long flags;
+	int i;
+
+	spin_lock_irqsave(&dev_priv->channels.lock, flags);
+	for (i = 0; i < dev_priv->engine.fifo.channels; i++) {
+		chan = dev_priv->channels.ptr[i];
+		if (!chan || !chan->ramin_grctx)
+			continue;
+
+		if (inst == chan->ramin_grctx->pinst)
+			break;
+	}
+	spin_unlock_irqrestore(&dev_priv->channels.lock, flags);
+	return i;
+}
 
+static void
+nv40_graph_isr(struct drm_device *dev)
+{
+	u32 stat;
+
+	while ((stat = nv_rd32(dev, NV03_PGRAPH_INTR))) {
+		u32 nsource = nv_rd32(dev, NV03_PGRAPH_NSOURCE);
+		u32 nstatus = nv_rd32(dev, NV03_PGRAPH_NSTATUS);
+		u32 inst = (nv_rd32(dev, 0x40032c) & 0x000fffff) << 4;
+		u32 chid = nv40_graph_isr_chid(dev, inst);
+		u32 addr = nv_rd32(dev, NV04_PGRAPH_TRAPPED_ADDR);
+		u32 subc = (addr & 0x00070000) >> 16;
+		u32 mthd = (addr & 0x00001ffc);
+		u32 data = nv_rd32(dev, NV04_PGRAPH_TRAPPED_DATA);
+		u32 class = nv_rd32(dev, 0x400160 + subc * 4) & 0xffff;
+		u32 show = stat;
+
+		if (stat & NV_PGRAPH_INTR_ERROR) {
+			if (nsource & NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD) {
+				if (!nouveau_gpuobj_mthd_call2(dev, chid, class, mthd, data))
+					show &= ~NV_PGRAPH_INTR_ERROR;
+			} else
+			if (nsource & NV03_PGRAPH_NSOURCE_DMA_VTX_PROTECTION) {
+				nv_mask(dev, 0x402000, 0, 0);
+			}
+		}
+
+		nv_wr32(dev, NV03_PGRAPH_INTR, stat);
+		nv_wr32(dev, NV04_PGRAPH_FIFO, 0x00000001);
+
+		if (show && nouveau_ratelimit()) {
+			NV_INFO(dev, "PGRAPH -");
+			nouveau_bitfield_print(nv10_graph_intr, show);
+			printk(" nsource:");
+			nouveau_bitfield_print(nv04_graph_nsource, nsource);
+			printk(" nstatus:");
+			nouveau_bitfield_print(nv10_graph_nstatus, nstatus);
+			printk("\n");
+			NV_INFO(dev, "PGRAPH - ch %d (0x%08x) subc %d "
+				     "class 0x%04x mthd 0x%04x data 0x%08x\n",
+				chid, inst, subc, class, mthd, data);
+		}
+	}
+}
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nv40_grctx.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nv40_grctx.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nv40_grctx.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nv40_grctx.c	2011-03-14 21:20:32.000000000 -0400
@@ -118,17 +118,6 @@
  */
 
 static int
-nv40_graph_4097(struct drm_device *dev)
-{
-	struct drm_nouveau_private *dev_priv = dev->dev_private;
-
-	if ((dev_priv->chipset & 0xf0) == 0x60)
-		return 0;
-
-	return !!(0x0baf & (1 << dev_priv->chipset));
-}
-
-static int
 nv40_graph_vs_count(struct drm_device *dev)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
@@ -219,7 +208,7 @@ nv40_graph_construct_general(struct nouv
 		gr_def(ctx, 0x4009dc, 0x80000000);
 	} else {
 		cp_ctx(ctx, 0x400840, 20);
-		if (!nv40_graph_4097(ctx->dev)) {
+		if (nv44_graph_class(ctx->dev)) {
 			for (i = 0; i < 8; i++)
 				gr_def(ctx, 0x400860 + (i * 4), 0x00000001);
 		}
@@ -228,7 +217,7 @@ nv40_graph_construct_general(struct nouv
 		gr_def(ctx, 0x400888, 0x00000040);
 		cp_ctx(ctx, 0x400894, 11);
 		gr_def(ctx, 0x400894, 0x00000040);
-		if (nv40_graph_4097(ctx->dev)) {
+		if (!nv44_graph_class(ctx->dev)) {
 			for (i = 0; i < 8; i++)
 				gr_def(ctx, 0x4008a0 + (i * 4), 0x80000000);
 		}
@@ -546,7 +535,7 @@ nv40_graph_construct_state3d_2(struct no
 static void
 nv40_graph_construct_state3d_3(struct nouveau_grctx *ctx)
 {
-	int len = nv40_graph_4097(ctx->dev) ? 0x0684 : 0x0084;
+	int len = nv44_graph_class(ctx->dev) ? 0x0084 : 0x0684;
 
 	cp_out (ctx, 0x300000);
 	cp_lsr (ctx, len - 4);
@@ -582,11 +571,11 @@ nv40_graph_construct_shader(struct nouve
 	} else {
 		b0_offset = 0x1d40/4; /* 2200 */
 		b1_offset = 0x3f40/4; /* 0b00 : 0a40 */
-		vs_len = nv40_graph_4097(dev) ? 0x4a40/4 : 0x4980/4;
+		vs_len = nv44_graph_class(dev) ? 0x4980/4 : 0x4a40/4;
 	}
 
 	cp_lsr(ctx, vs_len * vs_nr + 0x300/4);
-	cp_out(ctx, nv40_graph_4097(dev) ? 0x800041 : 0x800029);
+	cp_out(ctx, nv44_graph_class(dev) ? 0x800029 : 0x800041);
 
 	offset = ctx->ctxvals_pos;
 	ctx->ctxvals_pos += (0x0300/4 + (vs_nr * vs_len));
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nv40_mc.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nv40_mc.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nv40_mc.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nv40_mc.c	2011-03-14 21:20:32.000000000 -0400
@@ -6,27 +6,17 @@
 int
 nv40_mc_init(struct drm_device *dev)
 {
-	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	uint32_t tmp;
-
 	/* Power up everything, resetting each individual unit will
 	 * be done later if needed.
 	 */
 	nv_wr32(dev, NV03_PMC_ENABLE, 0xFFFFFFFF);
 
-	switch (dev_priv->chipset) {
-	case 0x44:
-	case 0x46: /* G72 */
-	case 0x4e:
-	case 0x4c: /* C51_G7X */
-		tmp = nv_rd32(dev, NV04_PFB_FIFO_DATA);
+	if (nv44_graph_class(dev)) {
+		u32 tmp = nv_rd32(dev, NV04_PFB_FIFO_DATA);
 		nv_wr32(dev, NV40_PMC_1700, tmp);
 		nv_wr32(dev, NV40_PMC_1704, 0);
 		nv_wr32(dev, NV40_PMC_1708, 0);
 		nv_wr32(dev, NV40_PMC_170C, tmp);
-		break;
-	default:
-		break;
 	}
 
 	return 0;
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nv50_crtc.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nv50_crtc.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nv50_crtc.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nv50_crtc.c	2011-03-14 21:20:32.000000000 -0400
@@ -115,15 +115,16 @@ nv50_crtc_blank(struct nouveau_crtc *nv_
 		OUT_RING(evo, 0);
 		BEGIN_RING(evo, 0, NV50_EVO_CRTC(index, FB_DMA), 1);
 		if (dev_priv->chipset != 0x50)
-			if (nv_crtc->fb.tile_flags == 0x7a00)
+			if (nv_crtc->fb.tile_flags == 0x7a00 ||
+			    nv_crtc->fb.tile_flags == 0xfe00)
 				OUT_RING(evo, NvEvoFB32);
 			else
 			if (nv_crtc->fb.tile_flags == 0x7000)
 				OUT_RING(evo, NvEvoFB16);
 			else
-				OUT_RING(evo, NvEvoVRAM);
+				OUT_RING(evo, NvEvoVRAM_LP);
 		else
-			OUT_RING(evo, NvEvoVRAM);
+			OUT_RING(evo, NvEvoVRAM_LP);
 	}
 
 	nv_crtc->fb.blanked = blanked;
@@ -345,7 +346,6 @@ nv50_crtc_cursor_set(struct drm_crtc *cr
 		     uint32_t buffer_handle, uint32_t width, uint32_t height)
 {
 	struct drm_device *dev = crtc->dev;
-	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
 	struct nouveau_bo *cursor = NULL;
 	struct drm_gem_object *gem;
@@ -374,8 +374,7 @@ nv50_crtc_cursor_set(struct drm_crtc *cr
 
 	nouveau_bo_unmap(cursor);
 
-	nv_crtc->cursor.set_offset(nv_crtc, nv_crtc->cursor.nvbo->bo.offset -
-					    dev_priv->vm_vram_base);
+	nv_crtc->cursor.set_offset(nv_crtc, nv_crtc->cursor.nvbo->bo.mem.start << PAGE_SHIFT);
 	nv_crtc->cursor.show(nv_crtc, true);
 
 out:
@@ -437,6 +436,7 @@ static const struct drm_crtc_funcs nv50_
 	.cursor_move = nv50_crtc_cursor_move,
 	.gamma_set = nv50_crtc_gamma_set,
 	.set_config = drm_crtc_helper_set_config,
+	.page_flip = nouveau_crtc_page_flip,
 	.destroy = nv50_crtc_destroy,
 };
 
@@ -453,6 +453,7 @@ nv50_crtc_prepare(struct drm_crtc *crtc)
 
 	NV_DEBUG_KMS(dev, "index %d\n", nv_crtc->index);
 
+	drm_vblank_pre_modeset(dev, nv_crtc->index);
 	nv50_crtc_blank(nv_crtc, true);
 }
 
@@ -468,6 +469,7 @@ nv50_crtc_commit(struct drm_crtc *crtc)
 	NV_DEBUG_KMS(dev, "index %d\n", nv_crtc->index);
 
 	nv50_crtc_blank(nv_crtc, false);
+	drm_vblank_post_modeset(dev, nv_crtc->index);
 
 	ret = RING_SPACE(evo, 2);
 	if (ret) {
@@ -545,7 +547,7 @@ nv50_crtc_do_mode_set_base(struct drm_cr
 		 return -EINVAL;
 	}
 
-	nv_crtc->fb.offset = fb->nvbo->bo.offset - dev_priv->vm_vram_base;
+	nv_crtc->fb.offset = fb->nvbo->bo.mem.start << PAGE_SHIFT;
 	nv_crtc->fb.tile_flags = nouveau_bo_tile_layout(fb->nvbo);
 	nv_crtc->fb.cpp = drm_fb->bits_per_pixel / 8;
 	if (!nv_crtc->fb.blanked && dev_priv->chipset != 0x50) {
@@ -554,13 +556,14 @@ nv50_crtc_do_mode_set_base(struct drm_cr
 			return ret;
 
 		BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, FB_DMA), 1);
-		if (nv_crtc->fb.tile_flags == 0x7a00)
+		if (nv_crtc->fb.tile_flags == 0x7a00 ||
+		    nv_crtc->fb.tile_flags == 0xfe00)
 			OUT_RING(evo, NvEvoFB32);
 		else
 		if (nv_crtc->fb.tile_flags == 0x7000)
 			OUT_RING(evo, NvEvoFB16);
 		else
-			OUT_RING(evo, NvEvoVRAM);
+			OUT_RING(evo, NvEvoVRAM_LP);
 	}
 
 	ret = RING_SPACE(evo, 12);
@@ -574,8 +577,10 @@ nv50_crtc_do_mode_set_base(struct drm_cr
 	if (!nv_crtc->fb.tile_flags) {
 		OUT_RING(evo, drm_fb->pitch | (1 << 20));
 	} else {
-		OUT_RING(evo, ((drm_fb->pitch / 4) << 4) |
-				  fb->nvbo->tile_mode);
+		u32 tile_mode = fb->nvbo->tile_mode;
+		if (dev_priv->card_type >= NV_C0)
+			tile_mode >>= 4;
+		OUT_RING(evo, ((drm_fb->pitch / 4) << 4) | tile_mode);
 	}
 	if (dev_priv->chipset == 0x50)
 		OUT_RING(evo, (nv_crtc->fb.tile_flags << 8) | format);
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nv50_display.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nv50_display.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nv50_display.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nv50_display.c	2011-03-14 21:20:32.000000000 -0400
@@ -33,6 +33,8 @@
 #include "nouveau_ramht.h"
 #include "drm_crtc_helper.h"
 
+static void nv50_display_isr(struct drm_device *);
+
 static inline int
 nv50_sor_nr(struct drm_device *dev)
 {
@@ -46,159 +48,6 @@ nv50_sor_nr(struct drm_device *dev)
 	return 4;
 }
 
-static void
-nv50_evo_channel_del(struct nouveau_channel **pchan)
-{
-	struct nouveau_channel *chan = *pchan;
-
-	if (!chan)
-		return;
-	*pchan = NULL;
-
-	nouveau_gpuobj_channel_takedown(chan);
-	nouveau_bo_unmap(chan->pushbuf_bo);
-	nouveau_bo_ref(NULL, &chan->pushbuf_bo);
-
-	if (chan->user)
-		iounmap(chan->user);
-
-	kfree(chan);
-}
-
-static int
-nv50_evo_dmaobj_new(struct nouveau_channel *evo, uint32_t class, uint32_t name,
-		    uint32_t tile_flags, uint32_t magic_flags,
-		    uint32_t offset, uint32_t limit)
-{
-	struct drm_nouveau_private *dev_priv = evo->dev->dev_private;
-	struct drm_device *dev = evo->dev;
-	struct nouveau_gpuobj *obj = NULL;
-	int ret;
-
-	ret = nouveau_gpuobj_new(dev, evo, 6*4, 32, 0, &obj);
-	if (ret)
-		return ret;
-	obj->engine = NVOBJ_ENGINE_DISPLAY;
-
-	nv_wo32(obj,  0, (tile_flags << 22) | (magic_flags << 16) | class);
-	nv_wo32(obj,  4, limit);
-	nv_wo32(obj,  8, offset);
-	nv_wo32(obj, 12, 0x00000000);
-	nv_wo32(obj, 16, 0x00000000);
-	if (dev_priv->card_type < NV_C0)
-		nv_wo32(obj, 20, 0x00010000);
-	else
-		nv_wo32(obj, 20, 0x00020000);
-	dev_priv->engine.instmem.flush(dev);
-
-	ret = nouveau_ramht_insert(evo, name, obj);
-	nouveau_gpuobj_ref(NULL, &obj);
-	if (ret) {
-		return ret;
-	}
-
-	return 0;
-}
-
-static int
-nv50_evo_channel_new(struct drm_device *dev, struct nouveau_channel **pchan)
-{
-	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nouveau_gpuobj *ramht = NULL;
-	struct nouveau_channel *chan;
-	int ret;
-
-	chan = kzalloc(sizeof(struct nouveau_channel), GFP_KERNEL);
-	if (!chan)
-		return -ENOMEM;
-	*pchan = chan;
-
-	chan->id = -1;
-	chan->dev = dev;
-	chan->user_get = 4;
-	chan->user_put = 0;
-
-	ret = nouveau_gpuobj_new(dev, NULL, 32768, 0x1000,
-				 NVOBJ_FLAG_ZERO_ALLOC, &chan->ramin);
-	if (ret) {
-		NV_ERROR(dev, "Error allocating EVO channel memory: %d\n", ret);
-		nv50_evo_channel_del(pchan);
-		return ret;
-	}
-
-	ret = drm_mm_init(&chan->ramin_heap, 0, 32768);
-	if (ret) {
-		NV_ERROR(dev, "Error initialising EVO PRAMIN heap: %d\n", ret);
-		nv50_evo_channel_del(pchan);
-		return ret;
-	}
-
-	ret = nouveau_gpuobj_new(dev, chan, 4096, 16, 0, &ramht);
-	if (ret) {
-		NV_ERROR(dev, "Unable to allocate EVO RAMHT: %d\n", ret);
-		nv50_evo_channel_del(pchan);
-		return ret;
-	}
-
-	ret = nouveau_ramht_new(dev, ramht, &chan->ramht);
-	nouveau_gpuobj_ref(NULL, &ramht);
-	if (ret) {
-		nv50_evo_channel_del(pchan);
-		return ret;
-	}
-
-	if (dev_priv->chipset != 0x50) {
-		ret = nv50_evo_dmaobj_new(chan, 0x3d, NvEvoFB16, 0x70, 0x19,
-					  0, 0xffffffff);
-		if (ret) {
-			nv50_evo_channel_del(pchan);
-			return ret;
-		}
-
-
-		ret = nv50_evo_dmaobj_new(chan, 0x3d, NvEvoFB32, 0x7a, 0x19,
-					  0, 0xffffffff);
-		if (ret) {
-			nv50_evo_channel_del(pchan);
-			return ret;
-		}
-	}
-
-	ret = nv50_evo_dmaobj_new(chan, 0x3d, NvEvoVRAM, 0, 0x19,
-				  0, dev_priv->vram_size);
-	if (ret) {
-		nv50_evo_channel_del(pchan);
-		return ret;
-	}
-
-	ret = nouveau_bo_new(dev, NULL, 4096, 0, TTM_PL_FLAG_VRAM, 0, 0,
-			     false, true, &chan->pushbuf_bo);
-	if (ret == 0)
-		ret = nouveau_bo_pin(chan->pushbuf_bo, TTM_PL_FLAG_VRAM);
-	if (ret) {
-		NV_ERROR(dev, "Error creating EVO DMA push buffer: %d\n", ret);
-		nv50_evo_channel_del(pchan);
-		return ret;
-	}
-
-	ret = nouveau_bo_map(chan->pushbuf_bo);
-	if (ret) {
-		NV_ERROR(dev, "Error mapping EVO DMA push buffer: %d\n", ret);
-		nv50_evo_channel_del(pchan);
-		return ret;
-	}
-
-	chan->user = ioremap(pci_resource_start(dev->pdev, 0) +
-					NV50_PDISPLAY_USER(0), PAGE_SIZE);
-	if (!chan->user) {
-		NV_ERROR(dev, "Error mapping EVO control regs.\n");
-		nv50_evo_channel_del(pchan);
-		return -ENOMEM;
-	}
-
-	return 0;
-}
-
 int
 nv50_display_early_init(struct drm_device *dev)
 {
@@ -214,17 +63,16 @@ int
 nv50_display_init(struct drm_device *dev)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nouveau_timer_engine *ptimer = &dev_priv->engine.timer;
 	struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio;
-	struct nouveau_channel *evo = dev_priv->evo;
 	struct drm_connector *connector;
-	uint32_t val, ram_amount;
-	uint64_t start;
+	struct nouveau_channel *evo;
 	int ret, i;
+	u32 val;
 
 	NV_DEBUG_KMS(dev, "\n");
 
 	nv_wr32(dev, 0x00610184, nv_rd32(dev, 0x00614004));
+
 	/*
 	 * I think the 0x006101XX range is some kind of main control area
 	 * that enables things.
@@ -240,16 +88,19 @@ nv50_display_init(struct drm_device *dev
 		val = nv_rd32(dev, 0x0061610c + (i * 0x800));
 		nv_wr32(dev, 0x0061019c + (i * 0x10), val);
 	}
+
 	/* DAC */
 	for (i = 0; i < 3; i++) {
 		val = nv_rd32(dev, 0x0061a000 + (i * 0x800));
 		nv_wr32(dev, 0x006101d0 + (i * 0x04), val);
 	}
+
 	/* SOR */
 	for (i = 0; i < nv50_sor_nr(dev); i++) {
 		val = nv_rd32(dev, 0x0061c000 + (i * 0x800));
 		nv_wr32(dev, 0x006101e0 + (i * 0x04), val);
 	}
+
 	/* EXT */
 	for (i = 0; i < 3; i++) {
 		val = nv_rd32(dev, 0x0061e000 + (i * 0x800));
@@ -262,17 +113,6 @@ nv50_display_init(struct drm_device *dev
 		nv_wr32(dev, NV50_PDISPLAY_DAC_CLK_CTRL1(i), 0x00000001);
 	}
 
-	/* This used to be in crtc unblank, but seems out of place there. */
-	nv_wr32(dev, NV50_PDISPLAY_UNK_380, 0);
-	/* RAM is clamped to 256 MiB. */
-	ram_amount = dev_priv->vram_size;
-	NV_DEBUG_KMS(dev, "ram_amount %d\n", ram_amount);
-	if (ram_amount > 256*1024*1024)
-		ram_amount = 256*1024*1024;
-	nv_wr32(dev, NV50_PDISPLAY_RAM_AMOUNT, ram_amount - 1);
-	nv_wr32(dev, NV50_PDISPLAY_UNK_388, 0x150000);
-	nv_wr32(dev, NV50_PDISPLAY_UNK_38C, 0);
-
 	/* The precise purpose is unknown, i suspect it has something to do
 	 * with text mode.
 	 */
@@ -287,37 +127,6 @@ nv50_display_init(struct drm_device *dev
 		}
 	}
 
-	/* taken from nv bug #12637, attempts to un-wedge the hw if it's
-	 * stuck in some unspecified state
-	 */
-	start = ptimer->read(dev);
-	nv_wr32(dev, NV50_PDISPLAY_CHANNEL_STAT(0), 0x2b00);
-	while ((val = nv_rd32(dev, NV50_PDISPLAY_CHANNEL_STAT(0))) & 0x1e0000) {
-		if ((val & 0x9f0000) == 0x20000)
-			nv_wr32(dev, NV50_PDISPLAY_CHANNEL_STAT(0),
-							val | 0x800000);
-
-		if ((val & 0x3f0000) == 0x30000)
-			nv_wr32(dev, NV50_PDISPLAY_CHANNEL_STAT(0),
-							val | 0x200000);
-
-		if (ptimer->read(dev) - start > 1000000000ULL) {
-			NV_ERROR(dev, "timeout: (0x610200 & 0x1e0000) != 0\n");
-			NV_ERROR(dev, "0x610200 = 0x%08x\n", val);
-			return -EBUSY;
-		}
-	}
-
-	nv_wr32(dev, NV50_PDISPLAY_CTRL_STATE, NV50_PDISPLAY_CTRL_STATE_ENABLE);
-	nv_wr32(dev, NV50_PDISPLAY_CHANNEL_STAT(0), 0x1000b03);
-	if (!nv_wait(dev, NV50_PDISPLAY_CHANNEL_STAT(0),
-		     0x40000000, 0x40000000)) {
-		NV_ERROR(dev, "timeout: (0x610200 & 0x40000000) == 0x40000000\n");
-		NV_ERROR(dev, "0x610200 = 0x%08x\n",
-			  nv_rd32(dev, NV50_PDISPLAY_CHANNEL_STAT(0)));
-		return -EBUSY;
-	}
-
 	for (i = 0; i < 2; i++) {
 		nv_wr32(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i), 0x2000);
 		if (!nv_wait(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i),
@@ -341,39 +150,31 @@ nv50_display_init(struct drm_device *dev
 		}
 	}
 
-	nv_wr32(dev, NV50_PDISPLAY_OBJECTS, (evo->ramin->vinst >> 8) | 9);
+	nv_wr32(dev, NV50_PDISPLAY_PIO_CTRL, 0x00000000);
+	nv_mask(dev, NV50_PDISPLAY_INTR_0, 0x00000000, 0x00000000);
+	nv_wr32(dev, NV50_PDISPLAY_INTR_EN_0, 0x00000000);
+	nv_mask(dev, NV50_PDISPLAY_INTR_1, 0x00000000, 0x00000000);
+	nv_wr32(dev, NV50_PDISPLAY_INTR_EN_1,
+		     NV50_PDISPLAY_INTR_EN_1_CLK_UNK10 |
+		     NV50_PDISPLAY_INTR_EN_1_CLK_UNK20 |
+		     NV50_PDISPLAY_INTR_EN_1_CLK_UNK40);
 
-	/* initialise fifo */
-	nv_wr32(dev, NV50_PDISPLAY_CHANNEL_DMA_CB(0),
-		((evo->pushbuf_bo->bo.mem.start << PAGE_SHIFT) >> 8) |
-		NV50_PDISPLAY_CHANNEL_DMA_CB_LOCATION_VRAM |
-		NV50_PDISPLAY_CHANNEL_DMA_CB_VALID);
-	nv_wr32(dev, NV50_PDISPLAY_CHANNEL_UNK2(0), 0x00010000);
-	nv_wr32(dev, NV50_PDISPLAY_CHANNEL_UNK3(0), 0x00000002);
-	if (!nv_wait(dev, 0x610200, 0x80000000, 0x00000000)) {
-		NV_ERROR(dev, "timeout: (0x610200 & 0x80000000) == 0\n");
-		NV_ERROR(dev, "0x610200 = 0x%08x\n", nv_rd32(dev, 0x610200));
-		return -EBUSY;
-	}
-	nv_wr32(dev, NV50_PDISPLAY_CHANNEL_STAT(0),
-		(nv_rd32(dev, NV50_PDISPLAY_CHANNEL_STAT(0)) & ~0x00000003) |
-		 NV50_PDISPLAY_CHANNEL_STAT_DMA_ENABLED);
-	nv_wr32(dev, NV50_PDISPLAY_USER_PUT(0), 0);
-	nv_wr32(dev, NV50_PDISPLAY_CHANNEL_STAT(0), 0x01000003 |
-		NV50_PDISPLAY_CHANNEL_STAT_DMA_ENABLED);
-	nv_wr32(dev, 0x610300, nv_rd32(dev, 0x610300) & ~1);
+	/* enable hotplug interrupts */
+	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+		struct nouveau_connector *conn = nouveau_connector(connector);
 
-	evo->dma.max = (4096/4) - 2;
-	evo->dma.put = 0;
-	evo->dma.cur = evo->dma.put;
-	evo->dma.free = evo->dma.max - evo->dma.cur;
+		if (conn->dcb->gpio_tag == 0xff)
+			continue;
 
-	ret = RING_SPACE(evo, NOUVEAU_DMA_SKIPS);
+		pgpio->irq_enable(dev, conn->dcb->gpio_tag, true);
+	}
+
+	ret = nv50_evo_init(dev);
 	if (ret)
 		return ret;
+	evo = dev_priv->evo;
 
-	for (i = 0; i < NOUVEAU_DMA_SKIPS; i++)
-		OUT_RING(evo, 0);
+	nv_wr32(dev, NV50_PDISPLAY_OBJECTS, (evo->ramin->vinst >> 8) | 9);
 
 	ret = RING_SPACE(evo, 11);
 	if (ret)
@@ -393,21 +194,6 @@ nv50_display_init(struct drm_device *dev
 	if (!nv_wait(dev, 0x640004, 0xffffffff, evo->dma.put << 2))
 		NV_ERROR(dev, "evo pushbuf stalled\n");
 
-	/* enable clock change interrupts. */
-	nv_wr32(dev, 0x610028, 0x00010001);
-	nv_wr32(dev, NV50_PDISPLAY_INTR_EN, (NV50_PDISPLAY_INTR_EN_CLK_UNK10 |
-					     NV50_PDISPLAY_INTR_EN_CLK_UNK20 |
-					     NV50_PDISPLAY_INTR_EN_CLK_UNK40));
-
-	/* enable hotplug interrupts */
-	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
-		struct nouveau_connector *conn = nouveau_connector(connector);
-
-		if (conn->dcb->gpio_tag == 0xff)
-			continue;
-
-		pgpio->irq_enable(dev, conn->dcb->gpio_tag, true);
-	}
 
 	return 0;
 }
@@ -452,13 +238,7 @@ static int nv50_display_disable(struct d
 		}
 	}
 
-	nv_wr32(dev, NV50_PDISPLAY_CHANNEL_STAT(0), 0);
-	nv_wr32(dev, NV50_PDISPLAY_CTRL_STATE, 0);
-	if (!nv_wait(dev, NV50_PDISPLAY_CHANNEL_STAT(0), 0x1e0000, 0)) {
-		NV_ERROR(dev, "timeout: (0x610200 & 0x1e0000) == 0\n");
-		NV_ERROR(dev, "0x610200 = 0x%08x\n",
-			  nv_rd32(dev, NV50_PDISPLAY_CHANNEL_STAT(0)));
-	}
+	nv50_evo_fini(dev);
 
 	for (i = 0; i < 3; i++) {
 		if (!nv_wait(dev, NV50_PDISPLAY_SOR_DPMS_STATE(i),
@@ -470,7 +250,7 @@ static int nv50_display_disable(struct d
 	}
 
 	/* disable interrupts. */
-	nv_wr32(dev, NV50_PDISPLAY_INTR_EN, 0x00000000);
+	nv_wr32(dev, NV50_PDISPLAY_INTR_EN_1, 0x00000000);
 
 	/* disable hotplug interrupts */
 	nv_wr32(dev, 0xe054, 0xffffffff);
@@ -508,13 +288,6 @@ int nv50_display_create(struct drm_devic
 
 	dev->mode_config.fb_base = dev_priv->fb_phys;
 
-	/* Create EVO channel */
-	ret = nv50_evo_channel_new(dev, &dev_priv->evo);
-	if (ret) {
-		NV_ERROR(dev, "Error creating EVO channel: %d\n", ret);
-		return ret;
-	}
-
 	/* Create CRTC objects */
 	for (i = 0; i < 2; i++)
 		nv50_crtc_create(dev, i);
@@ -557,6 +330,9 @@ int nv50_display_create(struct drm_devic
 		}
 	}
 
+	INIT_WORK(&dev_priv->irq_work, nv50_display_irq_handler_bh);
+	nouveau_irq_register(dev, 26, nv50_display_isr);
+
 	ret = nv50_display_init(dev);
 	if (ret) {
 		nv50_display_destroy(dev);
@@ -569,14 +345,12 @@ int nv50_display_create(struct drm_devic
 void
 nv50_display_destroy(struct drm_device *dev)
 {
-	struct drm_nouveau_private *dev_priv = dev->dev_private;
-
 	NV_DEBUG_KMS(dev, "\n");
 
 	drm_mode_config_cleanup(dev);
 
 	nv50_display_disable(dev);
-	nv50_evo_channel_del(&dev_priv->evo);
+	nouveau_irq_unregister(dev, 26);
 }
 
 static u16
@@ -660,32 +434,32 @@ static void
 nv50_display_vblank_crtc_handler(struct drm_device *dev, int crtc)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nouveau_channel *chan;
-	struct list_head *entry, *tmp;
+	struct nouveau_channel *chan, *tmp;
 
-	list_for_each_safe(entry, tmp, &dev_priv->vbl_waiting) {
-		chan = list_entry(entry, struct nouveau_channel, nvsw.vbl_wait);
+	list_for_each_entry_safe(chan, tmp, &dev_priv->vbl_waiting,
+				 nvsw.vbl_wait) {
+		if (chan->nvsw.vblsem_head != crtc)
+			continue;
 
 		nouveau_bo_wr32(chan->notifier_bo, chan->nvsw.vblsem_offset,
 						chan->nvsw.vblsem_rval);
 		list_del(&chan->nvsw.vbl_wait);
+		drm_vblank_put(dev, crtc);
 	}
+
+	drm_handle_vblank(dev, crtc);
 }
 
 static void
 nv50_display_vblank_handler(struct drm_device *dev, uint32_t intr)
 {
-	intr &= NV50_PDISPLAY_INTR_1_VBLANK_CRTC;
-
 	if (intr & NV50_PDISPLAY_INTR_1_VBLANK_CRTC_0)
 		nv50_display_vblank_crtc_handler(dev, 0);
 
 	if (intr & NV50_PDISPLAY_INTR_1_VBLANK_CRTC_1)
 		nv50_display_vblank_crtc_handler(dev, 1);
 
-	nv_wr32(dev, NV50_PDISPLAY_INTR_EN, nv_rd32(dev,
-		     NV50_PDISPLAY_INTR_EN) & ~intr);
-	nv_wr32(dev, NV50_PDISPLAY_INTR_1, intr);
+	nv_wr32(dev, NV50_PDISPLAY_INTR_1, NV50_PDISPLAY_INTR_1_VBLANK_CRTC);
 }
 
 static void
@@ -1011,108 +785,31 @@ nv50_display_irq_handler_bh(struct work_
 static void
 nv50_display_error_handler(struct drm_device *dev)
 {
-	uint32_t addr, data;
-
-	nv_wr32(dev, NV50_PDISPLAY_INTR_0, 0x00010000);
-	addr = nv_rd32(dev, NV50_PDISPLAY_TRAPPED_ADDR);
-	data = nv_rd32(dev, NV50_PDISPLAY_TRAPPED_DATA);
-
-	NV_ERROR(dev, "EvoCh %d Mthd 0x%04x Data 0x%08x (0x%04x 0x%02x)\n",
-		 0, addr & 0xffc, data, addr >> 16, (addr >> 12) & 0xf);
-
-	nv_wr32(dev, NV50_PDISPLAY_TRAPPED_ADDR, 0x90000000);
-}
-
-void
-nv50_display_irq_hotplug_bh(struct work_struct *work)
-{
-	struct drm_nouveau_private *dev_priv =
-		container_of(work, struct drm_nouveau_private, hpd_work);
-	struct drm_device *dev = dev_priv->dev;
-	struct drm_connector *connector;
-	const uint32_t gpio_reg[4] = { 0xe104, 0xe108, 0xe280, 0xe284 };
-	uint32_t unplug_mask, plug_mask, change_mask;
-	uint32_t hpd0, hpd1;
-
-	spin_lock_irq(&dev_priv->hpd_state.lock);
-	hpd0 = dev_priv->hpd_state.hpd0_bits;
-	dev_priv->hpd_state.hpd0_bits = 0;
-	hpd1 = dev_priv->hpd_state.hpd1_bits;
-	dev_priv->hpd_state.hpd1_bits = 0;
-	spin_unlock_irq(&dev_priv->hpd_state.lock);
-
-	hpd0 &= nv_rd32(dev, 0xe050);
-	if (dev_priv->chipset >= 0x90)
-		hpd1 &= nv_rd32(dev, 0xe070);
-
-	plug_mask   = (hpd0 & 0x0000ffff) | (hpd1 << 16);
-	unplug_mask = (hpd0 >> 16) | (hpd1 & 0xffff0000);
-	change_mask = plug_mask | unplug_mask;
-
-	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
-		struct drm_encoder_helper_funcs *helper;
-		struct nouveau_connector *nv_connector =
-			nouveau_connector(connector);
-		struct nouveau_encoder *nv_encoder;
-		struct dcb_gpio_entry *gpio;
-		uint32_t reg;
-		bool plugged;
-
-		if (!nv_connector->dcb)
-			continue;
-
-		gpio = nouveau_bios_gpio_entry(dev, nv_connector->dcb->gpio_tag);
-		if (!gpio || !(change_mask & (1 << gpio->line)))
-			continue;
-
-		reg = nv_rd32(dev, gpio_reg[gpio->line >> 3]);
-		plugged = !!(reg & (4 << ((gpio->line & 7) << 2)));
-		NV_INFO(dev, "%splugged %s\n", plugged ? "" : "un",
-			drm_get_connector_name(connector)) ;
+	u32 channels = (nv_rd32(dev, NV50_PDISPLAY_INTR_0) & 0x001f0000) >> 16;
+	u32 addr, data;
+	int chid;
 
-		if (!connector->encoder || !connector->encoder->crtc ||
-		    !connector->encoder->crtc->enabled)
+	for (chid = 0; chid < 5; chid++) {
+		if (!(channels & (1 << chid)))
 			continue;
-		nv_encoder = nouveau_encoder(connector->encoder);
-		helper = connector->encoder->helper_private;
 
-		if (nv_encoder->dcb->type != OUTPUT_DP)
-			continue;
+		nv_wr32(dev, NV50_PDISPLAY_INTR_0, 0x00010000 << chid);
+		addr = nv_rd32(dev, NV50_PDISPLAY_TRAPPED_ADDR(chid));
+		data = nv_rd32(dev, NV50_PDISPLAY_TRAPPED_DATA(chid));
+		NV_ERROR(dev, "EvoCh %d Mthd 0x%04x Data 0x%08x "
+			      "(0x%04x 0x%02x)\n", chid,
+			 addr & 0xffc, data, addr >> 16, (addr >> 12) & 0xf);
 
-		if (plugged)
-			helper->dpms(connector->encoder, DRM_MODE_DPMS_ON);
-		else
-			helper->dpms(connector->encoder, DRM_MODE_DPMS_OFF);
+		nv_wr32(dev, NV50_PDISPLAY_TRAPPED_ADDR(chid), 0x90000000);
 	}
-
-	drm_helper_hpd_irq_event(dev);
 }
 
-void
-nv50_display_irq_handler(struct drm_device *dev)
+static void
+nv50_display_isr(struct drm_device *dev)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	uint32_t delayed = 0;
 
-	if (nv_rd32(dev, NV50_PMC_INTR_0) & NV50_PMC_INTR_0_HOTPLUG) {
-		uint32_t hpd0_bits, hpd1_bits = 0;
-
-		hpd0_bits = nv_rd32(dev, 0xe054);
-		nv_wr32(dev, 0xe054, hpd0_bits);
-
-		if (dev_priv->chipset >= 0x90) {
-			hpd1_bits = nv_rd32(dev, 0xe074);
-			nv_wr32(dev, 0xe074, hpd1_bits);
-		}
-
-		spin_lock(&dev_priv->hpd_state.lock);
-		dev_priv->hpd_state.hpd0_bits |= hpd0_bits;
-		dev_priv->hpd_state.hpd1_bits |= hpd1_bits;
-		spin_unlock(&dev_priv->hpd_state.lock);
-
-		queue_work(dev_priv->wq, &dev_priv->hpd_work);
-	}
-
 	while (nv_rd32(dev, NV50_PMC_INTR_0) & NV50_PMC_INTR_0_DISPLAY) {
 		uint32_t intr0 = nv_rd32(dev, NV50_PDISPLAY_INTR_0);
 		uint32_t intr1 = nv_rd32(dev, NV50_PDISPLAY_INTR_1);
@@ -1123,9 +820,9 @@ nv50_display_irq_handler(struct drm_devi
 		if (!intr0 && !(intr1 & ~delayed))
 			break;
 
-		if (intr0 & 0x00010000) {
+		if (intr0 & 0x001f0000) {
 			nv50_display_error_handler(dev);
-			intr0 &= ~0x00010000;
+			intr0 &= ~0x001f0000;
 		}
 
 		if (intr1 & NV50_PDISPLAY_INTR_1_VBLANK_CRTC) {
@@ -1156,4 +853,3 @@ nv50_display_irq_handler(struct drm_devi
 		}
 	}
 }
-
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nv50_display.h linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nv50_display.h
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nv50_display.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nv50_display.h	2011-03-14 21:20:32.000000000 -0400
@@ -35,9 +35,7 @@
 #include "nouveau_crtc.h"
 #include "nv50_evo.h"
 
-void nv50_display_irq_handler(struct drm_device *dev);
 void nv50_display_irq_handler_bh(struct work_struct *work);
-void nv50_display_irq_hotplug_bh(struct work_struct *work);
 int nv50_display_early_init(struct drm_device *dev);
 void nv50_display_late_takedown(struct drm_device *dev);
 int nv50_display_create(struct drm_device *dev);
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nv50_evo.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nv50_evo.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nv50_evo.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nv50_evo.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,344 @@
+/*
+ * Copyright 2010 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_dma.h"
+#include "nouveau_ramht.h"
+
+static void
+nv50_evo_channel_del(struct nouveau_channel **pevo)
+{
+	struct drm_nouveau_private *dev_priv;
+	struct nouveau_channel *evo = *pevo;
+
+	if (!evo)
+		return;
+	*pevo = NULL;
+
+	dev_priv = evo->dev->dev_private;
+	dev_priv->evo_alloc &= ~(1 << evo->id);
+
+	nouveau_gpuobj_channel_takedown(evo);
+	nouveau_bo_unmap(evo->pushbuf_bo);
+	nouveau_bo_ref(NULL, &evo->pushbuf_bo);
+
+	if (evo->user)
+		iounmap(evo->user);
+
+	kfree(evo);
+}
+
+int
+nv50_evo_dmaobj_new(struct nouveau_channel *evo, u32 class, u32 name,
+		    u32 tile_flags, u32 magic_flags, u32 offset, u32 limit,
+		    u32 flags5)
+{
+	struct drm_nouveau_private *dev_priv = evo->dev->dev_private;
+	struct drm_device *dev = evo->dev;
+	struct nouveau_gpuobj *obj = NULL;
+	int ret;
+
+	ret = nouveau_gpuobj_new(dev, dev_priv->evo, 6*4, 32, 0, &obj);
+	if (ret)
+		return ret;
+	obj->engine = NVOBJ_ENGINE_DISPLAY;
+
+	nv_wo32(obj,  0, (tile_flags << 22) | (magic_flags << 16) | class);
+	nv_wo32(obj,  4, limit);
+	nv_wo32(obj,  8, offset);
+	nv_wo32(obj, 12, 0x00000000);
+	nv_wo32(obj, 16, 0x00000000);
+	nv_wo32(obj, 20, flags5);
+	dev_priv->engine.instmem.flush(dev);
+
+	ret = nouveau_ramht_insert(evo, name, obj);
+	nouveau_gpuobj_ref(NULL, &obj);
+	if (ret) {
+		return ret;
+	}
+
+	return 0;
+}
+
+static int
+nv50_evo_channel_new(struct drm_device *dev, struct nouveau_channel **pevo)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_channel *evo;
+	int ret;
+
+	evo = kzalloc(sizeof(struct nouveau_channel), GFP_KERNEL);
+	if (!evo)
+		return -ENOMEM;
+	*pevo = evo;
+
+	for (evo->id = 0; evo->id < 5; evo->id++) {
+		if (dev_priv->evo_alloc & (1 << evo->id))
+			continue;
+
+		dev_priv->evo_alloc |= (1 << evo->id);
+		break;
+	}
+
+	if (evo->id == 5) {
+		kfree(evo);
+		return -ENODEV;
+	}
+
+	evo->dev = dev;
+	evo->user_get = 4;
+	evo->user_put = 0;
+
+	ret = nouveau_bo_new(dev, NULL, 4096, 0, TTM_PL_FLAG_VRAM, 0, 0,
+			     false, true, &evo->pushbuf_bo);
+	if (ret == 0)
+		ret = nouveau_bo_pin(evo->pushbuf_bo, TTM_PL_FLAG_VRAM);
+	if (ret) {
+		NV_ERROR(dev, "Error creating EVO DMA push buffer: %d\n", ret);
+		nv50_evo_channel_del(pevo);
+		return ret;
+	}
+
+	ret = nouveau_bo_map(evo->pushbuf_bo);
+	if (ret) {
+		NV_ERROR(dev, "Error mapping EVO DMA push buffer: %d\n", ret);
+		nv50_evo_channel_del(pevo);
+		return ret;
+	}
+
+	evo->user = ioremap(pci_resource_start(dev->pdev, 0) +
+			    NV50_PDISPLAY_USER(evo->id), PAGE_SIZE);
+	if (!evo->user) {
+		NV_ERROR(dev, "Error mapping EVO control regs.\n");
+		nv50_evo_channel_del(pevo);
+		return -ENOMEM;
+	}
+
+	/* bind primary evo channel's ramht to the channel */
+	if (dev_priv->evo && evo != dev_priv->evo)
+		nouveau_ramht_ref(dev_priv->evo->ramht, &evo->ramht, NULL);
+
+	return 0;
+}
+
+static int
+nv50_evo_channel_init(struct nouveau_channel *evo)
+{
+	struct drm_device *dev = evo->dev;
+	int id = evo->id, ret, i;
+	u64 pushbuf = evo->pushbuf_bo->bo.mem.start << PAGE_SHIFT;
+	u32 tmp;
+
+	tmp = nv_rd32(dev, NV50_PDISPLAY_EVO_CTRL(id));
+	if ((tmp & 0x009f0000) == 0x00020000)
+		nv_wr32(dev, NV50_PDISPLAY_EVO_CTRL(id), tmp | 0x00800000);
+
+	tmp = nv_rd32(dev, NV50_PDISPLAY_EVO_CTRL(id));
+	if ((tmp & 0x003f0000) == 0x00030000)
+		nv_wr32(dev, NV50_PDISPLAY_EVO_CTRL(id), tmp | 0x00600000);
+
+	/* initialise fifo */
+	nv_wr32(dev, NV50_PDISPLAY_EVO_DMA_CB(id), pushbuf >> 8 |
+		     NV50_PDISPLAY_EVO_DMA_CB_LOCATION_VRAM |
+		     NV50_PDISPLAY_EVO_DMA_CB_VALID);
+	nv_wr32(dev, NV50_PDISPLAY_EVO_UNK2(id), 0x00010000);
+	nv_wr32(dev, NV50_PDISPLAY_EVO_HASH_TAG(id), id);
+	nv_mask(dev, NV50_PDISPLAY_EVO_CTRL(id), NV50_PDISPLAY_EVO_CTRL_DMA,
+		     NV50_PDISPLAY_EVO_CTRL_DMA_ENABLED);
+
+	nv_wr32(dev, NV50_PDISPLAY_USER_PUT(id), 0x00000000);
+	nv_wr32(dev, NV50_PDISPLAY_EVO_CTRL(id), 0x01000003 |
+		     NV50_PDISPLAY_EVO_CTRL_DMA_ENABLED);
+	if (!nv_wait(dev, NV50_PDISPLAY_EVO_CTRL(id), 0x80000000, 0x00000000)) {
+		NV_ERROR(dev, "EvoCh %d init timeout: 0x%08x\n", id,
+			 nv_rd32(dev, NV50_PDISPLAY_EVO_CTRL(id)));
+		return -EBUSY;
+	}
+
+	/* enable error reporting on the channel */
+	nv_mask(dev, 0x610028, 0x00000000, 0x00010001 << id);
+
+	evo->dma.max = (4096/4) - 2;
+	evo->dma.put = 0;
+	evo->dma.cur = evo->dma.put;
+	evo->dma.free = evo->dma.max - evo->dma.cur;
+
+	ret = RING_SPACE(evo, NOUVEAU_DMA_SKIPS);
+	if (ret)
+		return ret;
+
+	for (i = 0; i < NOUVEAU_DMA_SKIPS; i++)
+		OUT_RING(evo, 0);
+
+	return 0;
+}
+
+static void
+nv50_evo_channel_fini(struct nouveau_channel *evo)
+{
+	struct drm_device *dev = evo->dev;
+	int id = evo->id;
+
+	nv_mask(dev, 0x610028, 0x00010001 << id, 0x00000000);
+	nv_mask(dev, NV50_PDISPLAY_EVO_CTRL(id), 0x00001010, 0x00001000);
+	nv_wr32(dev, NV50_PDISPLAY_INTR_0, (1 << id));
+	nv_mask(dev, NV50_PDISPLAY_EVO_CTRL(id), 0x00000003, 0x00000000);
+	if (!nv_wait(dev, NV50_PDISPLAY_EVO_CTRL(id), 0x001e0000, 0x00000000)) {
+		NV_ERROR(dev, "EvoCh %d takedown timeout: 0x%08x\n", id,
+			 nv_rd32(dev, NV50_PDISPLAY_EVO_CTRL(id)));
+	}
+}
+
+static int
+nv50_evo_create(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_gpuobj *ramht = NULL;
+	struct nouveau_channel *evo;
+	int ret;
+
+	/* create primary evo channel, the one we use for modesetting
+	 * purporses
+	 */
+	ret = nv50_evo_channel_new(dev, &dev_priv->evo);
+	if (ret)
+		return ret;
+	evo = dev_priv->evo;
+
+	/* setup object management on it, any other evo channel will
+	 * use this also as there's no per-channel support on the
+	 * hardware
+	 */
+	ret = nouveau_gpuobj_new(dev, NULL, 32768, 65536,
+				 NVOBJ_FLAG_ZERO_ALLOC, &evo->ramin);
+	if (ret) {
+		NV_ERROR(dev, "Error allocating EVO channel memory: %d\n", ret);
+		nv50_evo_channel_del(&dev_priv->evo);
+		return ret;
+	}
+
+	ret = drm_mm_init(&evo->ramin_heap, 0, 32768);
+	if (ret) {
+		NV_ERROR(dev, "Error initialising EVO PRAMIN heap: %d\n", ret);
+		nv50_evo_channel_del(&dev_priv->evo);
+		return ret;
+	}
+
+	ret = nouveau_gpuobj_new(dev, evo, 4096, 16, 0, &ramht);
+	if (ret) {
+		NV_ERROR(dev, "Unable to allocate EVO RAMHT: %d\n", ret);
+		nv50_evo_channel_del(&dev_priv->evo);
+		return ret;
+	}
+
+	ret = nouveau_ramht_new(dev, ramht, &evo->ramht);
+	nouveau_gpuobj_ref(NULL, &ramht);
+	if (ret) {
+		nv50_evo_channel_del(&dev_priv->evo);
+		return ret;
+	}
+
+	/* create some default objects for the scanout memtypes we support */
+	if (dev_priv->card_type >= NV_C0) {
+		ret = nv50_evo_dmaobj_new(evo, 0x3d, NvEvoFB32, 0xfe, 0x19,
+					  0, 0xffffffff, 0x00000000);
+		if (ret) {
+			nv50_evo_channel_del(&dev_priv->evo);
+			return ret;
+		}
+
+		ret = nv50_evo_dmaobj_new(evo, 0x3d, NvEvoVRAM, 0, 0x19,
+					  0, dev_priv->vram_size, 0x00020000);
+		if (ret) {
+			nv50_evo_channel_del(&dev_priv->evo);
+			return ret;
+		}
+
+		ret = nv50_evo_dmaobj_new(evo, 0x3d, NvEvoVRAM_LP, 0, 0x19,
+					  0, dev_priv->vram_size, 0x00000000);
+		if (ret) {
+			nv50_evo_channel_del(&dev_priv->evo);
+			return ret;
+		}
+	} else {
+		ret = nv50_evo_dmaobj_new(evo, 0x3d, NvEvoFB16, 0x70, 0x19,
+					  0, 0xffffffff, 0x00010000);
+		if (ret) {
+			nv50_evo_channel_del(&dev_priv->evo);
+			return ret;
+		}
+
+
+		ret = nv50_evo_dmaobj_new(evo, 0x3d, NvEvoFB32, 0x7a, 0x19,
+					  0, 0xffffffff, 0x00010000);
+		if (ret) {
+			nv50_evo_channel_del(&dev_priv->evo);
+			return ret;
+		}
+
+		ret = nv50_evo_dmaobj_new(evo, 0x3d, NvEvoVRAM, 0, 0x19,
+					  0, dev_priv->vram_size, 0x00010000);
+		if (ret) {
+			nv50_evo_channel_del(&dev_priv->evo);
+			return ret;
+		}
+
+		ret = nv50_evo_dmaobj_new(evo, 0x3d, NvEvoVRAM_LP, 0, 0x19,
+					  0, dev_priv->vram_size, 0x00010000);
+		if (ret) {
+			nv50_evo_channel_del(&dev_priv->evo);
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+int
+nv50_evo_init(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	int ret;
+
+	if (!dev_priv->evo) {
+		ret = nv50_evo_create(dev);
+		if (ret)
+			return ret;
+	}
+
+	return nv50_evo_channel_init(dev_priv->evo);
+}
+
+void
+nv50_evo_fini(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+	if (dev_priv->evo) {
+		nv50_evo_channel_fini(dev_priv->evo);
+		nv50_evo_channel_del(&dev_priv->evo);
+	}
+}
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nv50_evo.h linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nv50_evo.h
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nv50_evo.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nv50_evo.h	2011-03-14 21:20:32.000000000 -0400
@@ -24,6 +24,15 @@
  *
  */
 
+#ifndef __NV50_EVO_H__
+#define __NV50_EVO_H__
+
+int  nv50_evo_init(struct drm_device *dev);
+void nv50_evo_fini(struct drm_device *dev);
+int  nv50_evo_dmaobj_new(struct nouveau_channel *, u32 class, u32 name,
+			 u32 tile_flags, u32 magic_flags,
+			 u32 offset, u32 limit);
+
 #define NV50_EVO_UPDATE                                              0x00000080
 #define NV50_EVO_UNK84                                               0x00000084
 #define NV50_EVO_UNK84_NOTIFY                                        0x40000000
@@ -111,3 +120,4 @@
 #define NV50_EVO_CRTC_SCALE_RES1                                     0x000008d8
 #define NV50_EVO_CRTC_SCALE_RES2                                     0x000008dc
 
+#endif
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nv50_fb.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nv50_fb.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nv50_fb.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nv50_fb.c	2011-03-14 21:20:32.000000000 -0400
@@ -3,30 +3,75 @@
 #include "nouveau_drv.h"
 #include "nouveau_drm.h"
 
+struct nv50_fb_priv {
+	struct page *r100c08_page;
+	dma_addr_t r100c08;
+};
+
+static int
+nv50_fb_create(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nv50_fb_priv *priv;
+
+	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	priv->r100c08_page = alloc_page(GFP_KERNEL | __GFP_ZERO);
+	if (!priv->r100c08_page) {
+		kfree(priv);
+		return -ENOMEM;
+	}
+
+	priv->r100c08 = pci_map_page(dev->pdev, priv->r100c08_page, 0,
+				     PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
+	if (pci_dma_mapping_error(dev->pdev, priv->r100c08)) {
+		__free_page(priv->r100c08_page);
+		kfree(priv);
+		return -EFAULT;
+	}
+
+	dev_priv->engine.fb.priv = priv;
+	return 0;
+}
+
 int
 nv50_fb_init(struct drm_device *dev)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nv50_fb_priv *priv;
+	int ret;
+
+	if (!dev_priv->engine.fb.priv) {
+		ret = nv50_fb_create(dev);
+		if (ret)
+			return ret;
+	}
+	priv = dev_priv->engine.fb.priv;
 
 	/* Not a clue what this is exactly.  Without pointing it at a
 	 * scratch page, VRAM->GART blits with M2MF (as in DDX DFS)
 	 * cause IOMMU "read from address 0" errors (rh#561267)
 	 */
-	nv_wr32(dev, 0x100c08, dev_priv->gart_info.sg_dummy_bus >> 8);
+	nv_wr32(dev, 0x100c08, priv->r100c08 >> 8);
 
 	/* This is needed to get meaningful information from 100c90
 	 * on traps. No idea what these values mean exactly. */
 	switch (dev_priv->chipset) {
 	case 0x50:
-		nv_wr32(dev, 0x100c90, 0x0707ff);
+		nv_wr32(dev, 0x100c90, 0x000707ff);
 		break;
 	case 0xa3:
 	case 0xa5:
 	case 0xa8:
-		nv_wr32(dev, 0x100c90, 0x0d0fff);
+		nv_wr32(dev, 0x100c90, 0x000d0fff);
+		break;
+	case 0xaf:
+		nv_wr32(dev, 0x100c90, 0x089d1fff);
 		break;
 	default:
-		nv_wr32(dev, 0x100c90, 0x1d07ff);
+		nv_wr32(dev, 0x100c90, 0x001d07ff);
 		break;
 	}
 
@@ -36,12 +81,25 @@ nv50_fb_init(struct drm_device *dev)
 void
 nv50_fb_takedown(struct drm_device *dev)
 {
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nv50_fb_priv *priv;
+
+	priv = dev_priv->engine.fb.priv;
+	if (!priv)
+		return;
+	dev_priv->engine.fb.priv = NULL;
+
+	pci_unmap_page(dev->pdev, priv->r100c08, PAGE_SIZE,
+		       PCI_DMA_BIDIRECTIONAL);
+	__free_page(priv->r100c08_page);
+	kfree(priv);
 }
 
 void
 nv50_fb_vm_trap(struct drm_device *dev, int display, const char *name)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	unsigned long flags;
 	u32 trap[6], idx, chinst;
 	int i, ch;
 
@@ -60,8 +118,10 @@ nv50_fb_vm_trap(struct drm_device *dev,
 		return;
 
 	chinst = (trap[2] << 16) | trap[1];
+
+	spin_lock_irqsave(&dev_priv->channels.lock, flags);
 	for (ch = 0; ch < dev_priv->engine.fifo.channels; ch++) {
-		struct nouveau_channel *chan = dev_priv->fifos[ch];
+		struct nouveau_channel *chan = dev_priv->channels.ptr[ch];
 
 		if (!chan || !chan->ramin)
 			continue;
@@ -69,6 +129,7 @@ nv50_fb_vm_trap(struct drm_device *dev,
 		if (chinst == chan->ramin->vinst >> 12)
 			break;
 	}
+	spin_unlock_irqrestore(&dev_priv->channels.lock, flags);
 
 	NV_INFO(dev, "%s - VM: Trapped %s at %02x%04x%04x status %08x "
 		     "channel %d (0x%08x)\n",
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nv50_fbcon.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nv50_fbcon.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nv50_fbcon.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nv50_fbcon.c	2011-03-14 21:20:32.000000000 -0400
@@ -1,29 +1,46 @@
+/*
+ * Copyright 2010 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_dma.h"
 #include "nouveau_ramht.h"
 #include "nouveau_fbcon.h"
+#include "nouveau_mm.h"
 
-void
+int
 nv50_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
 {
 	struct nouveau_fbdev *nfbdev = info->par;
 	struct drm_device *dev = nfbdev->dev;
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct nouveau_channel *chan = dev_priv->channel;
+	int ret;
 
-	if (info->state != FBINFO_STATE_RUNNING)
-		return;
-
-	if (!(info->flags & FBINFO_HWACCEL_DISABLED) &&
-	     RING_SPACE(chan, rect->rop == ROP_COPY ? 7 : 11)) {
-		nouveau_fbcon_gpu_lockup(info);
-	}
-
-	if (info->flags & FBINFO_HWACCEL_DISABLED) {
-		cfb_fillrect(info, rect);
-		return;
-	}
+	ret = RING_SPACE(chan, rect->rop == ROP_COPY ? 7 : 11);
+	if (ret)
+		return ret;
 
 	if (rect->rop != ROP_COPY) {
 		BEGIN_RING(chan, NvSub2D, 0x02ac, 1);
@@ -45,27 +62,21 @@ nv50_fbcon_fillrect(struct fb_info *info
 		OUT_RING(chan, 3);
 	}
 	FIRE_RING(chan);
+	return 0;
 }
 
-void
+int
 nv50_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region)
 {
 	struct nouveau_fbdev *nfbdev = info->par;
 	struct drm_device *dev = nfbdev->dev;
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct nouveau_channel *chan = dev_priv->channel;
+	int ret;
 
-	if (info->state != FBINFO_STATE_RUNNING)
-		return;
-
-	if (!(info->flags & FBINFO_HWACCEL_DISABLED) && RING_SPACE(chan, 12)) {
-		nouveau_fbcon_gpu_lockup(info);
-	}
-
-	if (info->flags & FBINFO_HWACCEL_DISABLED) {
-		cfb_copyarea(info, region);
-		return;
-	}
+	ret = RING_SPACE(chan, 12);
+	if (ret)
+		return ret;
 
 	BEGIN_RING(chan, NvSub2D, 0x0110, 1);
 	OUT_RING(chan, 0);
@@ -80,9 +91,10 @@ nv50_fbcon_copyarea(struct fb_info *info
 	OUT_RING(chan, 0);
 	OUT_RING(chan, region->sy);
 	FIRE_RING(chan);
+	return 0;
 }
 
-void
+int
 nv50_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
 {
 	struct nouveau_fbdev *nfbdev = info->par;
@@ -92,23 +104,14 @@ nv50_fbcon_imageblit(struct fb_info *inf
 	uint32_t width, dwords, *data = (uint32_t *)image->data;
 	uint32_t mask = ~(~0 >> (32 - info->var.bits_per_pixel));
 	uint32_t *palette = info->pseudo_palette;
+	int ret;
 
-	if (info->state != FBINFO_STATE_RUNNING)
-		return;
-
-	if (image->depth != 1) {
-		cfb_imageblit(info, image);
-		return;
-	}
-
-	if (!(info->flags & FBINFO_HWACCEL_DISABLED) && RING_SPACE(chan, 11)) {
-		nouveau_fbcon_gpu_lockup(info);
-	}
+	if (image->depth != 1)
+		return -ENODEV;
 
-	if (info->flags & FBINFO_HWACCEL_DISABLED) {
-		cfb_imageblit(info, image);
-		return;
-	}
+	ret = RING_SPACE(chan, 11);
+	if (ret)
+		return ret;
 
 	width = ALIGN(image->width, 32);
 	dwords = (width * image->height) >> 5;
@@ -134,11 +137,9 @@ nv50_fbcon_imageblit(struct fb_info *inf
 	while (dwords) {
 		int push = dwords > 2047 ? 2047 : dwords;
 
-		if (RING_SPACE(chan, push + 1)) {
-			nouveau_fbcon_gpu_lockup(info);
-			cfb_imageblit(info, image);
-			return;
-		}
+		ret = RING_SPACE(chan, push + 1);
+		if (ret)
+			return ret;
 
 		dwords -= push;
 
@@ -148,6 +149,7 @@ nv50_fbcon_imageblit(struct fb_info *inf
 	}
 
 	FIRE_RING(chan);
+	return 0;
 }
 
 int
@@ -157,12 +159,9 @@ nv50_fbcon_accel_init(struct fb_info *in
 	struct drm_device *dev = nfbdev->dev;
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct nouveau_channel *chan = dev_priv->channel;
-	struct nouveau_gpuobj *eng2d = NULL;
-	uint64_t fb;
+	struct nouveau_bo *nvbo = nfbdev->nouveau_fb.nvbo;
 	int ret, format;
 
-	fb = info->fix.smem_start - dev_priv->fb_phys + dev_priv->vm_vram_base;
-
 	switch (info->var.bits_per_pixel) {
 	case 8:
 		format = 0xf3;
@@ -190,12 +189,7 @@ nv50_fbcon_accel_init(struct fb_info *in
 		return -EINVAL;
 	}
 
-	ret = nouveau_gpuobj_gr_new(dev_priv->channel, 0x502d, &eng2d);
-	if (ret)
-		return ret;
-
-	ret = nouveau_ramht_insert(dev_priv->channel, Nv2D, eng2d);
-	nouveau_gpuobj_ref(NULL, &eng2d);
+	ret = nouveau_gpuobj_gr_new(dev_priv->channel, Nv2D, 0x502d);
 	if (ret)
 		return ret;
 
@@ -253,8 +247,8 @@ nv50_fbcon_accel_init(struct fb_info *in
 	OUT_RING(chan, info->fix.line_length);
 	OUT_RING(chan, info->var.xres_virtual);
 	OUT_RING(chan, info->var.yres_virtual);
-	OUT_RING(chan, upper_32_bits(fb));
-	OUT_RING(chan, lower_32_bits(fb));
+	OUT_RING(chan, upper_32_bits(nvbo->vma.offset));
+	OUT_RING(chan, lower_32_bits(nvbo->vma.offset));
 	BEGIN_RING(chan, NvSub2D, 0x0230, 2);
 	OUT_RING(chan, format);
 	OUT_RING(chan, 1);
@@ -262,8 +256,8 @@ nv50_fbcon_accel_init(struct fb_info *in
 	OUT_RING(chan, info->fix.line_length);
 	OUT_RING(chan, info->var.xres_virtual);
 	OUT_RING(chan, info->var.yres_virtual);
-	OUT_RING(chan, upper_32_bits(fb));
-	OUT_RING(chan, lower_32_bits(fb));
+	OUT_RING(chan, upper_32_bits(nvbo->vma.offset));
+	OUT_RING(chan, lower_32_bits(nvbo->vma.offset));
 
 	return 0;
 }
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nv50_fifo.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nv50_fifo.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nv50_fifo.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nv50_fifo.c	2011-03-14 21:20:32.000000000 -0400
@@ -28,6 +28,7 @@
 #include "drm.h"
 #include "nouveau_drv.h"
 #include "nouveau_ramht.h"
+#include "nouveau_vm.h"
 
 static void
 nv50_fifo_playlist_update(struct drm_device *dev)
@@ -44,7 +45,8 @@ nv50_fifo_playlist_update(struct drm_dev
 
 	/* We never schedule channel 0 or 127 */
 	for (i = 1, nr = 0; i < 127; i++) {
-		if (dev_priv->fifos[i] && dev_priv->fifos[i]->ramfc) {
+		if (dev_priv->channels.ptr[i] &&
+		    dev_priv->channels.ptr[i]->ramfc) {
 			nv_wo32(cur, (nr * 4), i);
 			nr++;
 		}
@@ -60,7 +62,7 @@ static void
 nv50_fifo_channel_enable(struct drm_device *dev, int channel)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nouveau_channel *chan = dev_priv->fifos[channel];
+	struct nouveau_channel *chan = dev_priv->channels.ptr[channel];
 	uint32_t inst;
 
 	NV_DEBUG(dev, "ch%d\n", channel);
@@ -105,6 +107,7 @@ nv50_fifo_init_intr(struct drm_device *d
 {
 	NV_DEBUG(dev, "\n");
 
+	nouveau_irq_register(dev, 8, nv04_fifo_isr);
 	nv_wr32(dev, NV03_PFIFO_INTR_0, 0xFFFFFFFF);
 	nv_wr32(dev, NV03_PFIFO_INTR_EN_0, 0xFFFFFFFF);
 }
@@ -118,7 +121,7 @@ nv50_fifo_init_context_table(struct drm_
 	NV_DEBUG(dev, "\n");
 
 	for (i = 0; i < NV50_PFIFO_CTX_TABLE__SIZE; i++) {
-		if (dev_priv->fifos[i])
+		if (dev_priv->channels.ptr[i])
 			nv50_fifo_channel_enable(dev, i);
 		else
 			nv50_fifo_channel_disable(dev, i);
@@ -206,6 +209,9 @@ nv50_fifo_takedown(struct drm_device *de
 	if (!pfifo->playlist[0])
 		return;
 
+	nv_wr32(dev, 0x2140, 0x00000000);
+	nouveau_irq_unregister(dev, 8);
+
 	nouveau_gpuobj_ref(NULL, &pfifo->playlist[0]);
 	nouveau_gpuobj_ref(NULL, &pfifo->playlist[1]);
 }
@@ -256,6 +262,11 @@ nv50_fifo_create_context(struct nouveau_
 	}
 	ramfc = chan->ramfc;
 
+	chan->user = ioremap(pci_resource_start(dev->pdev, 0) +
+			     NV50_USER(chan->id), PAGE_SIZE);
+	if (!chan->user)
+		return -ENOMEM;
+
 	spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
 
 	nv_wo32(ramfc, 0x48, chan->pushbuf->cinst >> 4);
@@ -291,10 +302,23 @@ void
 nv50_fifo_destroy_context(struct nouveau_channel *chan)
 {
 	struct drm_device *dev = chan->dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo;
 	struct nouveau_gpuobj *ramfc = NULL;
+	unsigned long flags;
 
 	NV_DEBUG(dev, "ch%d\n", chan->id);
 
+	spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
+	pfifo->reassign(dev, false);
+
+	/* Unload the context if it's the currently active one */
+	if (pfifo->channel_id(dev) == chan->id) {
+		pfifo->disable(dev);
+		pfifo->unload_context(dev);
+		pfifo->enable(dev);
+	}
+
 	/* This will ensure the channel is seen as disabled. */
 	nouveau_gpuobj_ref(chan->ramfc, &ramfc);
 	nouveau_gpuobj_ref(NULL, &chan->ramfc);
@@ -305,6 +329,14 @@ nv50_fifo_destroy_context(struct nouveau
 		nv50_fifo_channel_disable(dev, 127);
 	nv50_fifo_playlist_update(dev);
 
+	pfifo->reassign(dev, true);
+	spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
+
+	/* Free the channel resources */
+	if (chan->user) {
+		iounmap(chan->user);
+		chan->user = NULL;
+	}
 	nouveau_gpuobj_ref(NULL, &ramfc);
 	nouveau_gpuobj_ref(NULL, &chan->cache);
 }
@@ -392,7 +424,7 @@ nv50_fifo_unload_context(struct drm_devi
 	if (chid < 1 || chid >= dev_priv->engine.fifo.channels - 1)
 		return 0;
 
-	chan = dev_priv->fifos[chid];
+	chan = dev_priv->channels.ptr[chid];
 	if (!chan) {
 		NV_ERROR(dev, "Inactive channel on PFIFO: %d\n", chid);
 		return -EINVAL;
@@ -467,5 +499,5 @@ nv50_fifo_unload_context(struct drm_devi
 void
 nv50_fifo_tlb_flush(struct drm_device *dev)
 {
-	nv50_vm_flush(dev, 5);
+	nv50_vm_flush_engine(dev, 5);
 }
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nv50_gpio.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nv50_gpio.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nv50_gpio.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nv50_gpio.c	2011-03-14 21:20:32.000000000 -0400
@@ -26,6 +26,28 @@
 #include "nouveau_drv.h"
 #include "nouveau_hw.h"
 
+#include "nv50_display.h"
+
+static void nv50_gpio_isr(struct drm_device *dev);
+static void nv50_gpio_isr_bh(struct work_struct *work);
+
+struct nv50_gpio_priv {
+	struct list_head handlers;
+	spinlock_t lock;
+};
+
+struct nv50_gpio_handler {
+	struct drm_device *dev;
+	struct list_head head;
+	struct work_struct work;
+	bool inhibit;
+
+	struct dcb_gpio_entry *gpio;
+
+	void (*handler)(void *data, int state);
+	void *data;
+};
+
 static int
 nv50_gpio_location(struct dcb_gpio_entry *gpio, uint32_t *reg, uint32_t *shift)
 {
@@ -75,29 +97,123 @@ nv50_gpio_set(struct drm_device *dev, en
 	return 0;
 }
 
+int
+nv50_gpio_irq_register(struct drm_device *dev, enum dcb_gpio_tag tag,
+		       void (*handler)(void *, int), void *data)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio;
+	struct nv50_gpio_priv *priv = pgpio->priv;
+	struct nv50_gpio_handler *gpioh;
+	struct dcb_gpio_entry *gpio;
+	unsigned long flags;
+
+	gpio = nouveau_bios_gpio_entry(dev, tag);
+	if (!gpio)
+		return -ENOENT;
+
+	gpioh = kzalloc(sizeof(*gpioh), GFP_KERNEL);
+	if (!gpioh)
+		return -ENOMEM;
+
+	INIT_WORK(&gpioh->work, nv50_gpio_isr_bh);
+	gpioh->dev  = dev;
+	gpioh->gpio = gpio;
+	gpioh->handler = handler;
+	gpioh->data = data;
+
+	spin_lock_irqsave(&priv->lock, flags);
+	list_add(&gpioh->head, &priv->handlers);
+	spin_unlock_irqrestore(&priv->lock, flags);
+	return 0;
+}
+
 void
-nv50_gpio_irq_enable(struct drm_device *dev, enum dcb_gpio_tag tag, bool on)
+nv50_gpio_irq_unregister(struct drm_device *dev, enum dcb_gpio_tag tag,
+			 void (*handler)(void *, int), void *data)
 {
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio;
+	struct nv50_gpio_priv *priv = pgpio->priv;
+	struct nv50_gpio_handler *gpioh, *tmp;
 	struct dcb_gpio_entry *gpio;
-	u32 reg, mask;
+	unsigned long flags;
 
 	gpio = nouveau_bios_gpio_entry(dev, tag);
-	if (!gpio) {
-		NV_ERROR(dev, "gpio tag 0x%02x not found\n", tag);
+	if (!gpio)
 		return;
+
+	spin_lock_irqsave(&priv->lock, flags);
+	list_for_each_entry_safe(gpioh, tmp, &priv->handlers, head) {
+		if (gpioh->gpio != gpio ||
+		    gpioh->handler != handler ||
+		    gpioh->data != data)
+			continue;
+		list_del(&gpioh->head);
+		kfree(gpioh);
 	}
+	spin_unlock_irqrestore(&priv->lock, flags);
+}
+
+bool
+nv50_gpio_irq_enable(struct drm_device *dev, enum dcb_gpio_tag tag, bool on)
+{
+	struct dcb_gpio_entry *gpio;
+	u32 reg, mask;
+
+	gpio = nouveau_bios_gpio_entry(dev, tag);
+	if (!gpio)
+		return false;
 
 	reg  = gpio->line < 16 ? 0xe050 : 0xe070;
 	mask = 0x00010001 << (gpio->line & 0xf);
 
 	nv_wr32(dev, reg + 4, mask);
-	nv_mask(dev, reg + 0, mask, on ? mask : 0);
+	reg = nv_mask(dev, reg + 0, mask, on ? mask : 0);
+	return (reg & mask) == mask;
+}
+
+static int
+nv50_gpio_create(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio;
+	struct nv50_gpio_priv *priv;
+
+	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	INIT_LIST_HEAD(&priv->handlers);
+	spin_lock_init(&priv->lock);
+	pgpio->priv = priv;
+	return 0;
+}
+
+static void
+nv50_gpio_destroy(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio;
+
+	kfree(pgpio->priv);
+	pgpio->priv = NULL;
 }
 
 int
 nv50_gpio_init(struct drm_device *dev)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio;
+	struct nv50_gpio_priv *priv;
+	int ret;
+
+	if (!pgpio->priv) {
+		ret = nv50_gpio_create(dev);
+		if (ret)
+			return ret;
+	}
+	priv = pgpio->priv;
 
 	/* disable, and ack any pending gpio interrupts */
 	nv_wr32(dev, 0xe050, 0x00000000);
@@ -107,5 +223,77 @@ nv50_gpio_init(struct drm_device *dev)
 		nv_wr32(dev, 0xe074, 0xffffffff);
 	}
 
+	nouveau_irq_register(dev, 21, nv50_gpio_isr);
 	return 0;
 }
+
+void
+nv50_gpio_fini(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+	nv_wr32(dev, 0xe050, 0x00000000);
+	if (dev_priv->chipset >= 0x90)
+		nv_wr32(dev, 0xe070, 0x00000000);
+	nouveau_irq_unregister(dev, 21);
+
+	nv50_gpio_destroy(dev);
+}
+
+static void
+nv50_gpio_isr_bh(struct work_struct *work)
+{
+	struct nv50_gpio_handler *gpioh =
+		container_of(work, struct nv50_gpio_handler, work);
+	struct drm_nouveau_private *dev_priv = gpioh->dev->dev_private;
+	struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio;
+	struct nv50_gpio_priv *priv = pgpio->priv;
+	unsigned long flags;
+	int state;
+
+	state = pgpio->get(gpioh->dev, gpioh->gpio->tag);
+	if (state < 0)
+		return;
+
+	gpioh->handler(gpioh->data, state);
+
+	spin_lock_irqsave(&priv->lock, flags);
+	gpioh->inhibit = false;
+	spin_unlock_irqrestore(&priv->lock, flags);
+}
+
+static void
+nv50_gpio_isr(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio;
+	struct nv50_gpio_priv *priv = pgpio->priv;
+	struct nv50_gpio_handler *gpioh;
+	u32 intr0, intr1 = 0;
+	u32 hi, lo, ch;
+
+	intr0 = nv_rd32(dev, 0xe054) & nv_rd32(dev, 0xe050);
+	if (dev_priv->chipset >= 0x90)
+		intr1 = nv_rd32(dev, 0xe074) & nv_rd32(dev, 0xe070);
+
+	hi = (intr0 & 0x0000ffff) | (intr1 << 16);
+	lo = (intr0 >> 16) | (intr1 & 0xffff0000);
+	ch = hi | lo;
+
+	nv_wr32(dev, 0xe054, intr0);
+	if (dev_priv->chipset >= 0x90)
+		nv_wr32(dev, 0xe074, intr1);
+
+	spin_lock(&priv->lock);
+	list_for_each_entry(gpioh, &priv->handlers, head) {
+		if (!(ch & (1 << gpioh->gpio->line)))
+			continue;
+
+		if (gpioh->inhibit)
+			continue;
+		gpioh->inhibit = true;
+
+		queue_work(dev_priv->wq, &gpioh->work);
+	}
+	spin_unlock(&priv->lock);
+}
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nv50_graph.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nv50_graph.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nv50_graph.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nv50_graph.c	2011-03-14 21:20:32.000000000 -0400
@@ -29,6 +29,12 @@
 #include "nouveau_drv.h"
 #include "nouveau_ramht.h"
 #include "nouveau_grctx.h"
+#include "nouveau_dma.h"
+#include "nouveau_vm.h"
+#include "nv50_evo.h"
+
+static int  nv50_graph_register(struct drm_device *);
+static void nv50_graph_isr(struct drm_device *);
 
 static void
 nv50_graph_init_reset(struct drm_device *dev)
@@ -46,6 +52,7 @@ nv50_graph_init_intr(struct drm_device *
 {
 	NV_DEBUG(dev, "\n");
 
+	nouveau_irq_register(dev, 12, nv50_graph_isr);
 	nv_wr32(dev, NV03_PGRAPH_INTR, 0xffffffff);
 	nv_wr32(dev, 0x400138, 0xffffffff);
 	nv_wr32(dev, NV40_PGRAPH_INTR_EN, 0xffffffff);
@@ -145,12 +152,15 @@ nv50_graph_init(struct drm_device *dev)
 	nv50_graph_init_reset(dev);
 	nv50_graph_init_regs__nv(dev);
 	nv50_graph_init_regs(dev);
-	nv50_graph_init_intr(dev);
 
 	ret = nv50_graph_init_ctxctl(dev);
 	if (ret)
 		return ret;
 
+	ret = nv50_graph_register(dev);
+	if (ret)
+		return ret;
+	nv50_graph_init_intr(dev);
 	return 0;
 }
 
@@ -158,6 +168,8 @@ void
 nv50_graph_takedown(struct drm_device *dev)
 {
 	NV_DEBUG(dev, "\n");
+	nv_wr32(dev, 0x40013c, 0x00000000);
+	nouveau_irq_unregister(dev, 12);
 }
 
 void
@@ -190,7 +202,7 @@ nv50_graph_channel(struct drm_device *de
 	inst = (inst & NV50_PGRAPH_CTXCTL_CUR_INSTANCE) << 12;
 
 	for (i = 0; i < dev_priv->engine.fifo.channels; i++) {
-		struct nouveau_channel *chan = dev_priv->fifos[i];
+		struct nouveau_channel *chan = dev_priv->channels.ptr[i];
 
 		if (chan && chan->ramin && chan->ramin->vinst == inst)
 			return chan;
@@ -211,7 +223,7 @@ nv50_graph_create_context(struct nouveau
 
 	NV_DEBUG(dev, "ch%d\n", chan->id);
 
-	ret = nouveau_gpuobj_new(dev, chan, pgraph->grctx_size, 0x1000,
+	ret = nouveau_gpuobj_new(dev, chan, pgraph->grctx_size, 0,
 				 NVOBJ_FLAG_ZERO_ALLOC |
 				 NVOBJ_FLAG_ZERO_FREE, &chan->ramin_grctx);
 	if (ret)
@@ -234,6 +246,7 @@ nv50_graph_create_context(struct nouveau
 	nv_wo32(chan->ramin_grctx, 0x00000, chan->ramin->vinst >> 12);
 
 	dev_priv->engine.instmem.flush(dev);
+	atomic_inc(&chan->vm->pgraph_refs);
 	return 0;
 }
 
@@ -242,18 +255,34 @@ nv50_graph_destroy_context(struct nouvea
 {
 	struct drm_device *dev = chan->dev;
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
+	struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo;
 	int i, hdr = (dev_priv->chipset == 0x50) ? 0x200 : 0x20;
+	unsigned long flags;
 
 	NV_DEBUG(dev, "ch%d\n", chan->id);
 
 	if (!chan->ramin)
 		return;
 
+	spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
+	pfifo->reassign(dev, false);
+	pgraph->fifo_access(dev, false);
+
+	if (pgraph->channel(dev) == chan)
+		pgraph->unload_context(dev);
+
 	for (i = hdr; i < hdr + 24; i += 4)
 		nv_wo32(chan->ramin, i, 0);
 	dev_priv->engine.instmem.flush(dev);
 
+	pgraph->fifo_access(dev, true);
+	pfifo->reassign(dev, true);
+	spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
+
 	nouveau_gpuobj_ref(NULL, &chan->ramin_grctx);
+
+	atomic_dec(&chan->vm->pgraph_refs);
 }
 
 static int
@@ -306,7 +335,7 @@ nv50_graph_unload_context(struct drm_dev
 	return 0;
 }
 
-void
+static void
 nv50_graph_context_switch(struct drm_device *dev)
 {
 	uint32_t inst;
@@ -322,8 +351,8 @@ nv50_graph_context_switch(struct drm_dev
 }
 
 static int
-nv50_graph_nvsw_dma_vblsem(struct nouveau_channel *chan, int grclass,
-			   int mthd, uint32_t data)
+nv50_graph_nvsw_dma_vblsem(struct nouveau_channel *chan,
+			   u32 class, u32 mthd, u32 data)
 {
 	struct nouveau_gpuobj *gpuobj;
 
@@ -340,8 +369,8 @@ nv50_graph_nvsw_dma_vblsem(struct nouvea
 }
 
 static int
-nv50_graph_nvsw_vblsem_offset(struct nouveau_channel *chan, int grclass,
-			      int mthd, uint32_t data)
+nv50_graph_nvsw_vblsem_offset(struct nouveau_channel *chan,
+			      u32 class, u32 mthd, u32 data)
 {
 	if (nouveau_notifier_offset(chan->nvsw.vblsem, &data))
 		return -ERANGE;
@@ -351,16 +380,16 @@ nv50_graph_nvsw_vblsem_offset(struct nou
 }
 
 static int
-nv50_graph_nvsw_vblsem_release_val(struct nouveau_channel *chan, int grclass,
-				   int mthd, uint32_t data)
+nv50_graph_nvsw_vblsem_release_val(struct nouveau_channel *chan,
+				   u32 class, u32 mthd, u32 data)
 {
 	chan->nvsw.vblsem_rval = data;
 	return 0;
 }
 
 static int
-nv50_graph_nvsw_vblsem_release(struct nouveau_channel *chan, int grclass,
-			       int mthd, uint32_t data)
+nv50_graph_nvsw_vblsem_release(struct nouveau_channel *chan,
+			       u32 class, u32 mthd, u32 data)
 {
 	struct drm_device *dev = chan->dev;
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
@@ -368,45 +397,85 @@ nv50_graph_nvsw_vblsem_release(struct no
 	if (!chan->nvsw.vblsem || chan->nvsw.vblsem_offset == ~0 || data > 1)
 		return -EINVAL;
 
-	if (!(nv_rd32(dev, NV50_PDISPLAY_INTR_EN) &
-		      NV50_PDISPLAY_INTR_EN_VBLANK_CRTC_(data))) {
-		nv_wr32(dev, NV50_PDISPLAY_INTR_1,
-			NV50_PDISPLAY_INTR_1_VBLANK_CRTC_(data));
-		nv_wr32(dev, NV50_PDISPLAY_INTR_EN, nv_rd32(dev,
-			NV50_PDISPLAY_INTR_EN) |
-			NV50_PDISPLAY_INTR_EN_VBLANK_CRTC_(data));
-	}
+	drm_vblank_get(dev, data);
 
+	chan->nvsw.vblsem_head = data;
 	list_add(&chan->nvsw.vbl_wait, &dev_priv->vbl_waiting);
+
 	return 0;
 }
 
-static struct nouveau_pgraph_object_method nv50_graph_nvsw_methods[] = {
-	{ 0x018c, nv50_graph_nvsw_dma_vblsem },
-	{ 0x0400, nv50_graph_nvsw_vblsem_offset },
-	{ 0x0404, nv50_graph_nvsw_vblsem_release_val },
-	{ 0x0408, nv50_graph_nvsw_vblsem_release },
-	{}
-};
+static int
+nv50_graph_nvsw_mthd_page_flip(struct nouveau_channel *chan,
+			       u32 class, u32 mthd, u32 data)
+{
+	struct nouveau_page_flip_state s;
 
-struct nouveau_pgraph_object_class nv50_graph_grclass[] = {
-	{ 0x506e, true, nv50_graph_nvsw_methods }, /* nvsw */
-	{ 0x0030, false, NULL }, /* null */
-	{ 0x5039, false, NULL }, /* m2mf */
-	{ 0x502d, false, NULL }, /* 2d */
-	{ 0x50c0, false, NULL }, /* compute */
-	{ 0x85c0, false, NULL }, /* compute (nva3, nva5, nva8) */
-	{ 0x5097, false, NULL }, /* tesla (nv50) */
-	{ 0x8297, false, NULL }, /* tesla (nv8x/nv9x) */
-	{ 0x8397, false, NULL }, /* tesla (nva0, nvaa, nvac) */
-	{ 0x8597, false, NULL }, /* tesla (nva3, nva5, nva8) */
-	{}
-};
+	if (!nouveau_finish_page_flip(chan, &s)) {
+		/* XXX - Do something here */
+	}
+
+	return 0;
+}
+
+static int
+nv50_graph_register(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+	if (dev_priv->engine.graph.registered)
+		return 0;
+
+	NVOBJ_CLASS(dev, 0x506e, SW); /* nvsw */
+	NVOBJ_MTHD (dev, 0x506e, 0x018c, nv50_graph_nvsw_dma_vblsem);
+	NVOBJ_MTHD (dev, 0x506e, 0x0400, nv50_graph_nvsw_vblsem_offset);
+	NVOBJ_MTHD (dev, 0x506e, 0x0404, nv50_graph_nvsw_vblsem_release_val);
+	NVOBJ_MTHD (dev, 0x506e, 0x0408, nv50_graph_nvsw_vblsem_release);
+	NVOBJ_MTHD (dev, 0x506e, 0x0500, nv50_graph_nvsw_mthd_page_flip);
+
+	NVOBJ_CLASS(dev, 0x0030, GR); /* null */
+	NVOBJ_CLASS(dev, 0x5039, GR); /* m2mf */
+	NVOBJ_CLASS(dev, 0x502d, GR); /* 2d */
+
+	/* tesla */
+	if (dev_priv->chipset == 0x50)
+		NVOBJ_CLASS(dev, 0x5097, GR); /* tesla (nv50) */
+	else
+	if (dev_priv->chipset < 0xa0)
+		NVOBJ_CLASS(dev, 0x8297, GR); /* tesla (nv8x/nv9x) */
+	else {
+		switch (dev_priv->chipset) {
+		case 0xa0:
+		case 0xaa:
+		case 0xac:
+			NVOBJ_CLASS(dev, 0x8397, GR);
+			break;
+		case 0xa3:
+		case 0xa5:
+		case 0xa8:
+			NVOBJ_CLASS(dev, 0x8597, GR);
+			break;
+		case 0xaf:
+			NVOBJ_CLASS(dev, 0x8697, GR);
+			break;
+		}
+	}
+
+	/* compute */
+	NVOBJ_CLASS(dev, 0x50c0, GR);
+	if (dev_priv->chipset  > 0xa0 &&
+	    dev_priv->chipset != 0xaa &&
+	    dev_priv->chipset != 0xac)
+		NVOBJ_CLASS(dev, 0x85c0, GR);
+
+	dev_priv->engine.graph.registered = true;
+	return 0;
+}
 
 void
 nv50_graph_tlb_flush(struct drm_device *dev)
 {
-	nv50_vm_flush(dev, 0);
+	nv50_vm_flush_engine(dev, 0);
 }
 
 void
@@ -449,8 +518,535 @@ nv86_graph_tlb_flush(struct drm_device *
 			 nv_rd32(dev, 0x400384), nv_rd32(dev, 0x400388));
 	}
 
-	nv50_vm_flush(dev, 0);
+	nv50_vm_flush_engine(dev, 0);
 
 	nv_mask(dev, 0x400500, 0x00000001, 0x00000001);
 	spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
 }
+
+static struct nouveau_enum nv50_mp_exec_error_names[] =
+{
+	{ 3, "STACK_UNDERFLOW" },
+	{ 4, "QUADON_ACTIVE" },
+	{ 8, "TIMEOUT" },
+	{ 0x10, "INVALID_OPCODE" },
+	{ 0x40, "BREAKPOINT" },
+	{}
+};
+
+static struct nouveau_bitfield nv50_graph_trap_m2mf[] = {
+	{ 0x00000001, "NOTIFY" },
+	{ 0x00000002, "IN" },
+	{ 0x00000004, "OUT" },
+	{}
+};
+
+static struct nouveau_bitfield nv50_graph_trap_vfetch[] = {
+	{ 0x00000001, "FAULT" },
+	{}
+};
+
+static struct nouveau_bitfield nv50_graph_trap_strmout[] = {
+	{ 0x00000001, "FAULT" },
+	{}
+};
+
+static struct nouveau_bitfield nv50_graph_trap_ccache[] = {
+	{ 0x00000001, "FAULT" },
+	{}
+};
+
+/* There must be a *lot* of these. Will take some time to gather them up. */
+struct nouveau_enum nv50_data_error_names[] = {
+	{ 0x00000003, "INVALID_QUERY_OR_TEXTURE" },
+	{ 0x00000004, "INVALID_VALUE" },
+	{ 0x00000005, "INVALID_ENUM" },
+	{ 0x00000008, "INVALID_OBJECT" },
+	{ 0x00000009, "READ_ONLY_OBJECT" },
+	{ 0x0000000a, "SUPERVISOR_OBJECT" },
+	{ 0x0000000b, "INVALID_ADDRESS_ALIGNMENT" },
+	{ 0x0000000c, "INVALID_BITFIELD" },
+	{ 0x0000000d, "BEGIN_END_ACTIVE" },
+	{ 0x0000000e, "SEMANTIC_COLOR_BACK_OVER_LIMIT" },
+	{ 0x0000000f, "VIEWPORT_ID_NEEDS_GP" },
+	{ 0x00000010, "RT_DOUBLE_BIND" },
+	{ 0x00000011, "RT_TYPES_MISMATCH" },
+	{ 0x00000012, "RT_LINEAR_WITH_ZETA" },
+	{ 0x00000015, "FP_TOO_FEW_REGS" },
+	{ 0x00000016, "ZETA_FORMAT_CSAA_MISMATCH" },
+	{ 0x00000017, "RT_LINEAR_WITH_MSAA" },
+	{ 0x00000018, "FP_INTERPOLANT_START_OVER_LIMIT" },
+	{ 0x00000019, "SEMANTIC_LAYER_OVER_LIMIT" },
+	{ 0x0000001a, "RT_INVALID_ALIGNMENT" },
+	{ 0x0000001b, "SAMPLER_OVER_LIMIT" },
+	{ 0x0000001c, "TEXTURE_OVER_LIMIT" },
+	{ 0x0000001e, "GP_TOO_MANY_OUTPUTS" },
+	{ 0x0000001f, "RT_BPP128_WITH_MS8" },
+	{ 0x00000021, "Z_OUT_OF_BOUNDS" },
+	{ 0x00000023, "XY_OUT_OF_BOUNDS" },
+	{ 0x00000027, "CP_MORE_PARAMS_THAN_SHARED" },
+	{ 0x00000028, "CP_NO_REG_SPACE_STRIPED" },
+	{ 0x00000029, "CP_NO_REG_SPACE_PACKED" },
+	{ 0x0000002a, "CP_NOT_ENOUGH_WARPS" },
+	{ 0x0000002b, "CP_BLOCK_SIZE_MISMATCH" },
+	{ 0x0000002c, "CP_NOT_ENOUGH_LOCAL_WARPS" },
+	{ 0x0000002d, "CP_NOT_ENOUGH_STACK_WARPS" },
+	{ 0x0000002e, "CP_NO_BLOCKDIM_LATCH" },
+	{ 0x00000031, "ENG2D_FORMAT_MISMATCH" },
+	{ 0x0000003f, "PRIMITIVE_ID_NEEDS_GP" },
+	{ 0x00000044, "SEMANTIC_VIEWPORT_OVER_LIMIT" },
+	{ 0x00000045, "SEMANTIC_COLOR_FRONT_OVER_LIMIT" },
+	{ 0x00000046, "LAYER_ID_NEEDS_GP" },
+	{ 0x00000047, "SEMANTIC_CLIP_OVER_LIMIT" },
+	{ 0x00000048, "SEMANTIC_PTSZ_OVER_LIMIT" },
+	{}
+};
+
+static struct nouveau_bitfield nv50_graph_intr[] = {
+	{ 0x00000001, "NOTIFY" },
+	{ 0x00000002, "COMPUTE_QUERY" },
+	{ 0x00000010, "ILLEGAL_MTHD" },
+	{ 0x00000020, "ILLEGAL_CLASS" },
+	{ 0x00000040, "DOUBLE_NOTIFY" },
+	{ 0x00001000, "CONTEXT_SWITCH" },
+	{ 0x00010000, "BUFFER_NOTIFY" },
+	{ 0x00100000, "DATA_ERROR" },
+	{ 0x00200000, "TRAP" },
+	{ 0x01000000, "SINGLE_STEP" },
+	{}
+};
+
+static void
+nv50_pgraph_mp_trap(struct drm_device *dev, int tpid, int display)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	uint32_t units = nv_rd32(dev, 0x1540);
+	uint32_t addr, mp10, status, pc, oplow, ophigh;
+	int i;
+	int mps = 0;
+	for (i = 0; i < 4; i++) {
+		if (!(units & 1 << (i+24)))
+			continue;
+		if (dev_priv->chipset < 0xa0)
+			addr = 0x408200 + (tpid << 12) + (i << 7);
+		else
+			addr = 0x408100 + (tpid << 11) + (i << 7);
+		mp10 = nv_rd32(dev, addr + 0x10);
+		status = nv_rd32(dev, addr + 0x14);
+		if (!status)
+			continue;
+		if (display) {
+			nv_rd32(dev, addr + 0x20);
+			pc = nv_rd32(dev, addr + 0x24);
+			oplow = nv_rd32(dev, addr + 0x70);
+			ophigh= nv_rd32(dev, addr + 0x74);
+			NV_INFO(dev, "PGRAPH_TRAP_MP_EXEC - "
+					"TP %d MP %d: ", tpid, i);
+			nouveau_enum_print(nv50_mp_exec_error_names, status);
+			printk(" at %06x warp %d, opcode %08x %08x\n",
+					pc&0xffffff, pc >> 24,
+					oplow, ophigh);
+		}
+		nv_wr32(dev, addr + 0x10, mp10);
+		nv_wr32(dev, addr + 0x14, 0);
+		mps++;
+	}
+	if (!mps && display)
+		NV_INFO(dev, "PGRAPH_TRAP_MP_EXEC - TP %d: "
+				"No MPs claiming errors?\n", tpid);
+}
+
+static void
+nv50_pgraph_tp_trap(struct drm_device *dev, int type, uint32_t ustatus_old,
+		uint32_t ustatus_new, int display, const char *name)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	int tps = 0;
+	uint32_t units = nv_rd32(dev, 0x1540);
+	int i, r;
+	uint32_t ustatus_addr, ustatus;
+	for (i = 0; i < 16; i++) {
+		if (!(units & (1 << i)))
+			continue;
+		if (dev_priv->chipset < 0xa0)
+			ustatus_addr = ustatus_old + (i << 12);
+		else
+			ustatus_addr = ustatus_new + (i << 11);
+		ustatus = nv_rd32(dev, ustatus_addr) & 0x7fffffff;
+		if (!ustatus)
+			continue;
+		tps++;
+		switch (type) {
+		case 6: /* texture error... unknown for now */
+			nv50_fb_vm_trap(dev, display, name);
+			if (display) {
+				NV_ERROR(dev, "magic set %d:\n", i);
+				for (r = ustatus_addr + 4; r <= ustatus_addr + 0x10; r += 4)
+					NV_ERROR(dev, "\t0x%08x: 0x%08x\n", r,
+						nv_rd32(dev, r));
+			}
+			break;
+		case 7: /* MP error */
+			if (ustatus & 0x00010000) {
+				nv50_pgraph_mp_trap(dev, i, display);
+				ustatus &= ~0x00010000;
+			}
+			break;
+		case 8: /* TPDMA error */
+			{
+			uint32_t e0c = nv_rd32(dev, ustatus_addr + 4);
+			uint32_t e10 = nv_rd32(dev, ustatus_addr + 8);
+			uint32_t e14 = nv_rd32(dev, ustatus_addr + 0xc);
+			uint32_t e18 = nv_rd32(dev, ustatus_addr + 0x10);
+			uint32_t e1c = nv_rd32(dev, ustatus_addr + 0x14);
+			uint32_t e20 = nv_rd32(dev, ustatus_addr + 0x18);
+			uint32_t e24 = nv_rd32(dev, ustatus_addr + 0x1c);
+			nv50_fb_vm_trap(dev, display, name);
+			/* 2d engine destination */
+			if (ustatus & 0x00000010) {
+				if (display) {
+					NV_INFO(dev, "PGRAPH_TRAP_TPDMA_2D - TP %d - Unknown fault at address %02x%08x\n",
+							i, e14, e10);
+					NV_INFO(dev, "PGRAPH_TRAP_TPDMA_2D - TP %d - e0c: %08x, e18: %08x, e1c: %08x, e20: %08x, e24: %08x\n",
+							i, e0c, e18, e1c, e20, e24);
+				}
+				ustatus &= ~0x00000010;
+			}
+			/* Render target */
+			if (ustatus & 0x00000040) {
+				if (display) {
+					NV_INFO(dev, "PGRAPH_TRAP_TPDMA_RT - TP %d - Unknown fault at address %02x%08x\n",
+							i, e14, e10);
+					NV_INFO(dev, "PGRAPH_TRAP_TPDMA_RT - TP %d - e0c: %08x, e18: %08x, e1c: %08x, e20: %08x, e24: %08x\n",
+							i, e0c, e18, e1c, e20, e24);
+				}
+				ustatus &= ~0x00000040;
+			}
+			/* CUDA memory: l[], g[] or stack. */
+			if (ustatus & 0x00000080) {
+				if (display) {
+					if (e18 & 0x80000000) {
+						/* g[] read fault? */
+						NV_INFO(dev, "PGRAPH_TRAP_TPDMA - TP %d - Global read fault at address %02x%08x\n",
+								i, e14, e10 | ((e18 >> 24) & 0x1f));
+						e18 &= ~0x1f000000;
+					} else if (e18 & 0xc) {
+						/* g[] write fault? */
+						NV_INFO(dev, "PGRAPH_TRAP_TPDMA - TP %d - Global write fault at address %02x%08x\n",
+								i, e14, e10 | ((e18 >> 7) & 0x1f));
+						e18 &= ~0x00000f80;
+					} else {
+						NV_INFO(dev, "PGRAPH_TRAP_TPDMA - TP %d - Unknown CUDA fault at address %02x%08x\n",
+								i, e14, e10);
+					}
+					NV_INFO(dev, "PGRAPH_TRAP_TPDMA - TP %d - e0c: %08x, e18: %08x, e1c: %08x, e20: %08x, e24: %08x\n",
+							i, e0c, e18, e1c, e20, e24);
+				}
+				ustatus &= ~0x00000080;
+			}
+			}
+			break;
+		}
+		if (ustatus) {
+			if (display)
+				NV_INFO(dev, "%s - TP%d: Unhandled ustatus 0x%08x\n", name, i, ustatus);
+		}
+		nv_wr32(dev, ustatus_addr, 0xc0000000);
+	}
+
+	if (!tps && display)
+		NV_INFO(dev, "%s - No TPs claiming errors?\n", name);
+}
+
+static int
+nv50_pgraph_trap_handler(struct drm_device *dev, u32 display, u64 inst, u32 chid)
+{
+	u32 status = nv_rd32(dev, 0x400108);
+	u32 ustatus;
+
+	if (!status && display) {
+		NV_INFO(dev, "PGRAPH - TRAP: no units reporting traps?\n");
+		return 1;
+	}
+
+	/* DISPATCH: Relays commands to other units and handles NOTIFY,
+	 * COND, QUERY. If you get a trap from it, the command is still stuck
+	 * in DISPATCH and you need to do something about it. */
+	if (status & 0x001) {
+		ustatus = nv_rd32(dev, 0x400804) & 0x7fffffff;
+		if (!ustatus && display) {
+			NV_INFO(dev, "PGRAPH_TRAP_DISPATCH - no ustatus?\n");
+		}
+
+		nv_wr32(dev, 0x400500, 0x00000000);
+
+		/* Known to be triggered by screwed up NOTIFY and COND... */
+		if (ustatus & 0x00000001) {
+			u32 addr = nv_rd32(dev, 0x400808);
+			u32 subc = (addr & 0x00070000) >> 16;
+			u32 mthd = (addr & 0x00001ffc);
+			u32 datal = nv_rd32(dev, 0x40080c);
+			u32 datah = nv_rd32(dev, 0x400810);
+			u32 class = nv_rd32(dev, 0x400814);
+			u32 r848 = nv_rd32(dev, 0x400848);
+
+			NV_INFO(dev, "PGRAPH - TRAP DISPATCH_FAULT\n");
+			if (display && (addr & 0x80000000)) {
+				NV_INFO(dev, "PGRAPH - ch %d (0x%010llx) "
+					     "subc %d class 0x%04x mthd 0x%04x "
+					     "data 0x%08x%08x "
+					     "400808 0x%08x 400848 0x%08x\n",
+					chid, inst, subc, class, mthd, datah,
+					datal, addr, r848);
+			} else
+			if (display) {
+				NV_INFO(dev, "PGRAPH - no stuck command?\n");
+			}
+
+			nv_wr32(dev, 0x400808, 0);
+			nv_wr32(dev, 0x4008e8, nv_rd32(dev, 0x4008e8) & 3);
+			nv_wr32(dev, 0x400848, 0);
+			ustatus &= ~0x00000001;
+		}
+
+		if (ustatus & 0x00000002) {
+			u32 addr = nv_rd32(dev, 0x40084c);
+			u32 subc = (addr & 0x00070000) >> 16;
+			u32 mthd = (addr & 0x00001ffc);
+			u32 data = nv_rd32(dev, 0x40085c);
+			u32 class = nv_rd32(dev, 0x400814);
+
+			NV_INFO(dev, "PGRAPH - TRAP DISPATCH_QUERY\n");
+			if (display && (addr & 0x80000000)) {
+				NV_INFO(dev, "PGRAPH - ch %d (0x%010llx) "
+					     "subc %d class 0x%04x mthd 0x%04x "
+					     "data 0x%08x 40084c 0x%08x\n",
+					chid, inst, subc, class, mthd,
+					data, addr);
+			} else
+			if (display) {
+				NV_INFO(dev, "PGRAPH - no stuck command?\n");
+			}
+
+			nv_wr32(dev, 0x40084c, 0);
+			ustatus &= ~0x00000002;
+		}
+
+		if (ustatus && display) {
+			NV_INFO(dev, "PGRAPH - TRAP_DISPATCH (unknown "
+				      "0x%08x)\n", ustatus);
+		}
+
+		nv_wr32(dev, 0x400804, 0xc0000000);
+		nv_wr32(dev, 0x400108, 0x001);
+		status &= ~0x001;
+		if (!status)
+			return 0;
+	}
+
+	/* M2MF: Memory to memory copy engine. */
+	if (status & 0x002) {
+		u32 ustatus = nv_rd32(dev, 0x406800) & 0x7fffffff;
+		if (display) {
+			NV_INFO(dev, "PGRAPH - TRAP_M2MF");
+			nouveau_bitfield_print(nv50_graph_trap_m2mf, ustatus);
+			printk("\n");
+			NV_INFO(dev, "PGRAPH - TRAP_M2MF %08x %08x %08x %08x\n",
+				nv_rd32(dev, 0x406804), nv_rd32(dev, 0x406808),
+				nv_rd32(dev, 0x40680c), nv_rd32(dev, 0x406810));
+
+		}
+
+		/* No sane way found yet -- just reset the bugger. */
+		nv_wr32(dev, 0x400040, 2);
+		nv_wr32(dev, 0x400040, 0);
+		nv_wr32(dev, 0x406800, 0xc0000000);
+		nv_wr32(dev, 0x400108, 0x002);
+		status &= ~0x002;
+	}
+
+	/* VFETCH: Fetches data from vertex buffers. */
+	if (status & 0x004) {
+		u32 ustatus = nv_rd32(dev, 0x400c04) & 0x7fffffff;
+		if (display) {
+			NV_INFO(dev, "PGRAPH - TRAP_VFETCH");
+			nouveau_bitfield_print(nv50_graph_trap_vfetch, ustatus);
+			printk("\n");
+			NV_INFO(dev, "PGRAPH - TRAP_VFETCH %08x %08x %08x %08x\n",
+				nv_rd32(dev, 0x400c00), nv_rd32(dev, 0x400c08),
+				nv_rd32(dev, 0x400c0c), nv_rd32(dev, 0x400c10));
+		}
+
+		nv_wr32(dev, 0x400c04, 0xc0000000);
+		nv_wr32(dev, 0x400108, 0x004);
+		status &= ~0x004;
+	}
+
+	/* STRMOUT: DirectX streamout / OpenGL transform feedback. */
+	if (status & 0x008) {
+		ustatus = nv_rd32(dev, 0x401800) & 0x7fffffff;
+		if (display) {
+			NV_INFO(dev, "PGRAPH - TRAP_STRMOUT");
+			nouveau_bitfield_print(nv50_graph_trap_strmout, ustatus);
+			printk("\n");
+			NV_INFO(dev, "PGRAPH - TRAP_STRMOUT %08x %08x %08x %08x\n",
+				nv_rd32(dev, 0x401804), nv_rd32(dev, 0x401808),
+				nv_rd32(dev, 0x40180c), nv_rd32(dev, 0x401810));
+
+		}
+
+		/* No sane way found yet -- just reset the bugger. */
+		nv_wr32(dev, 0x400040, 0x80);
+		nv_wr32(dev, 0x400040, 0);
+		nv_wr32(dev, 0x401800, 0xc0000000);
+		nv_wr32(dev, 0x400108, 0x008);
+		status &= ~0x008;
+	}
+
+	/* CCACHE: Handles code and c[] caches and fills them. */
+	if (status & 0x010) {
+		ustatus = nv_rd32(dev, 0x405018) & 0x7fffffff;
+		if (display) {
+			NV_INFO(dev, "PGRAPH - TRAP_CCACHE");
+			nouveau_bitfield_print(nv50_graph_trap_ccache, ustatus);
+			printk("\n");
+			NV_INFO(dev, "PGRAPH - TRAP_CCACHE %08x %08x %08x %08x"
+				     " %08x %08x %08x\n",
+				nv_rd32(dev, 0x405800), nv_rd32(dev, 0x405804),
+				nv_rd32(dev, 0x405808), nv_rd32(dev, 0x40580c),
+				nv_rd32(dev, 0x405810), nv_rd32(dev, 0x405814),
+				nv_rd32(dev, 0x40581c));
+
+		}
+
+		nv_wr32(dev, 0x405018, 0xc0000000);
+		nv_wr32(dev, 0x400108, 0x010);
+		status &= ~0x010;
+	}
+
+	/* Unknown, not seen yet... 0x402000 is the only trap status reg
+	 * remaining, so try to handle it anyway. Perhaps related to that
+	 * unknown DMA slot on tesla? */
+	if (status & 0x20) {
+		ustatus = nv_rd32(dev, 0x402000) & 0x7fffffff;
+		if (display)
+			NV_INFO(dev, "PGRAPH - TRAP_UNKC04 0x%08x\n", ustatus);
+		nv_wr32(dev, 0x402000, 0xc0000000);
+		/* no status modifiction on purpose */
+	}
+
+	/* TEXTURE: CUDA texturing units */
+	if (status & 0x040) {
+		nv50_pgraph_tp_trap(dev, 6, 0x408900, 0x408600, display,
+				    "PGRAPH - TRAP_TEXTURE");
+		nv_wr32(dev, 0x400108, 0x040);
+		status &= ~0x040;
+	}
+
+	/* MP: CUDA execution engines. */
+	if (status & 0x080) {
+		nv50_pgraph_tp_trap(dev, 7, 0x408314, 0x40831c, display,
+				    "PGRAPH - TRAP_MP");
+		nv_wr32(dev, 0x400108, 0x080);
+		status &= ~0x080;
+	}
+
+	/* TPDMA:  Handles TP-initiated uncached memory accesses:
+	 * l[], g[], stack, 2d surfaces, render targets. */
+	if (status & 0x100) {
+		nv50_pgraph_tp_trap(dev, 8, 0x408e08, 0x408708, display,
+				    "PGRAPH - TRAP_TPDMA");
+		nv_wr32(dev, 0x400108, 0x100);
+		status &= ~0x100;
+	}
+
+	if (status) {
+		if (display)
+			NV_INFO(dev, "PGRAPH - TRAP: unknown 0x%08x\n", status);
+		nv_wr32(dev, 0x400108, status);
+	}
+
+	return 1;
+}
+
+static int
+nv50_graph_isr_chid(struct drm_device *dev, u64 inst)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_channel *chan;
+	unsigned long flags;
+	int i;
+
+	spin_lock_irqsave(&dev_priv->channels.lock, flags);
+	for (i = 0; i < dev_priv->engine.fifo.channels; i++) {
+		chan = dev_priv->channels.ptr[i];
+		if (!chan || !chan->ramin)
+			continue;
+
+		if (inst == chan->ramin->vinst)
+			break;
+	}
+	spin_unlock_irqrestore(&dev_priv->channels.lock, flags);
+	return i;
+}
+
+static void
+nv50_graph_isr(struct drm_device *dev)
+{
+	u32 stat;
+
+	while ((stat = nv_rd32(dev, 0x400100))) {
+		u64 inst = (u64)(nv_rd32(dev, 0x40032c) & 0x0fffffff) << 12;
+		u32 chid = nv50_graph_isr_chid(dev, inst);
+		u32 addr = nv_rd32(dev, NV04_PGRAPH_TRAPPED_ADDR);
+		u32 subc = (addr & 0x00070000) >> 16;
+		u32 mthd = (addr & 0x00001ffc);
+		u32 data = nv_rd32(dev, NV04_PGRAPH_TRAPPED_DATA);
+		u32 class = nv_rd32(dev, 0x400814);
+		u32 show = stat;
+
+		if (stat & 0x00000010) {
+			if (!nouveau_gpuobj_mthd_call2(dev, chid, class,
+						       mthd, data))
+				show &= ~0x00000010;
+		}
+
+		if (stat & 0x00001000) {
+			nv_wr32(dev, 0x400500, 0x00000000);
+			nv_wr32(dev, 0x400100, 0x00001000);
+			nv_mask(dev, 0x40013c, 0x00001000, 0x00000000);
+			nv50_graph_context_switch(dev);
+			stat &= ~0x00001000;
+			show &= ~0x00001000;
+		}
+
+		show = (show && nouveau_ratelimit()) ? show : 0;
+
+		if (show & 0x00100000) {
+			u32 ecode = nv_rd32(dev, 0x400110);
+			NV_INFO(dev, "PGRAPH - DATA_ERROR ");
+			nouveau_enum_print(nv50_data_error_names, ecode);
+			printk("\n");
+		}
+
+		if (stat & 0x00200000) {
+			if (!nv50_pgraph_trap_handler(dev, show, inst, chid))
+				show &= ~0x00200000;
+		}
+
+		nv_wr32(dev, 0x400100, stat);
+		nv_wr32(dev, 0x400500, 0x00010001);
+
+		if (show) {
+			NV_INFO(dev, "PGRAPH -");
+			nouveau_bitfield_print(nv50_graph_intr, show);
+			printk("\n");
+			NV_INFO(dev, "PGRAPH - ch %d (0x%010llx) subc %d "
+				     "class 0x%04x mthd 0x%04x data 0x%08x\n",
+				chid, inst, subc, class, mthd, data);
+		}
+	}
+
+	if (nv_rd32(dev, 0x400824) & (1 << 31))
+		nv_wr32(dev, 0x400824, nv_rd32(dev, 0x400824) & ~(1 << 31));
+}
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nv50_instmem.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nv50_instmem.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nv50_instmem.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nv50_instmem.c	2011-03-14 21:20:32.000000000 -0400
@@ -27,14 +27,20 @@
 
 #include "drmP.h"
 #include "drm.h"
+
 #include "nouveau_drv.h"
+#include "nouveau_vm.h"
+
+#define BAR1_VM_BASE 0x0020000000ULL
+#define BAR1_VM_SIZE pci_resource_len(dev->pdev, 1)
+#define BAR3_VM_BASE 0x0000000000ULL
+#define BAR3_VM_SIZE pci_resource_len(dev->pdev, 3)
 
 struct nv50_instmem_priv {
 	uint32_t save1700[5]; /* 0x1700->0x1710 */
 
-	struct nouveau_gpuobj *pramin_pt;
-	struct nouveau_gpuobj *pramin_bar;
-	struct nouveau_gpuobj *fb_bar;
+	struct nouveau_gpuobj *bar1_dmaobj;
+	struct nouveau_gpuobj *bar3_dmaobj;
 };
 
 static void
@@ -48,6 +54,7 @@ nv50_channel_del(struct nouveau_channel
 		return;
 
 	nouveau_gpuobj_ref(NULL, &chan->ramfc);
+	nouveau_vm_ref(NULL, &chan->vm, chan->vm_pd);
 	nouveau_gpuobj_ref(NULL, &chan->vm_pd);
 	if (chan->ramin_heap.free_stack.next)
 		drm_mm_takedown(&chan->ramin_heap);
@@ -56,14 +63,14 @@ nv50_channel_del(struct nouveau_channel
 }
 
 static int
-nv50_channel_new(struct drm_device *dev, u32 size,
+nv50_channel_new(struct drm_device *dev, u32 size, struct nouveau_vm *vm,
 		 struct nouveau_channel **pchan)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	u32 pgd = (dev_priv->chipset == 0x50) ? 0x1400 : 0x0200;
 	u32  fc = (dev_priv->chipset == 0x50) ? 0x0000 : 0x4200;
 	struct nouveau_channel *chan;
-	int ret;
+	int ret, i;
 
 	chan = kzalloc(sizeof(*chan), GFP_KERNEL);
 	if (!chan)
@@ -92,6 +99,17 @@ nv50_channel_new(struct drm_device *dev,
 		return ret;
 	}
 
+	for (i = 0; i < 0x4000; i += 8) {
+		nv_wo32(chan->vm_pd, i + 0, 0x00000000);
+		nv_wo32(chan->vm_pd, i + 4, 0xdeadcafe);
+	}
+
+	ret = nouveau_vm_ref(vm, &chan->vm, chan->vm_pd);
+	if (ret) {
+		nv50_channel_del(&chan);
+		return ret;
+	}
+
 	ret = nouveau_gpuobj_new_fake(dev, chan->ramin->pinst == ~0 ? ~0 :
 				      chan->ramin->pinst + fc,
 				      chan->ramin->vinst + fc, 0x100,
@@ -111,6 +129,7 @@ nv50_instmem_init(struct drm_device *dev
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct nv50_instmem_priv *priv;
 	struct nouveau_channel *chan;
+	struct nouveau_vm *vm;
 	int ret, i;
 	u32 tmp;
 
@@ -127,112 +146,87 @@ nv50_instmem_init(struct drm_device *dev
 	ret = drm_mm_init(&dev_priv->ramin_heap, 0, dev_priv->ramin_size);
 	if (ret) {
 		NV_ERROR(dev, "Failed to init RAMIN heap\n");
-		return -ENOMEM;
+		goto error;
 	}
 
-	/* we need a channel to plug into the hw to control the BARs */
-	ret = nv50_channel_new(dev, 128*1024, &dev_priv->fifos[0]);
+	/* BAR3 */
+	ret = nouveau_vm_new(dev, BAR3_VM_BASE, BAR3_VM_SIZE, BAR3_VM_BASE,
+			     &dev_priv->bar3_vm);
 	if (ret)
-		return ret;
-	chan = dev_priv->fifos[127] = dev_priv->fifos[0];
+		goto error;
 
-	/* allocate page table for PRAMIN BAR */
-	ret = nouveau_gpuobj_new(dev, chan, (dev_priv->ramin_size >> 12) * 8,
-				 0x1000, NVOBJ_FLAG_ZERO_ALLOC,
-				 &priv->pramin_pt);
+	ret = nouveau_gpuobj_new(dev, NULL, (BAR3_VM_SIZE >> 12) * 8,
+				 0x1000, NVOBJ_FLAG_DONT_MAP |
+				 NVOBJ_FLAG_ZERO_ALLOC,
+				 &dev_priv->bar3_vm->pgt[0].obj[0]);
 	if (ret)
-		return ret;
+		goto error;
+	dev_priv->bar3_vm->pgt[0].refcount[0] = 1;
 
-	nv_wo32(chan->vm_pd, 0x0000, priv->pramin_pt->vinst | 0x63);
-	nv_wo32(chan->vm_pd, 0x0004, 0);
+	nv50_instmem_map(dev_priv->bar3_vm->pgt[0].obj[0]);
 
-	/* DMA object for PRAMIN BAR */
-	ret = nouveau_gpuobj_new(dev, chan, 6*4, 16, 0, &priv->pramin_bar);
+	ret = nv50_channel_new(dev, 128 * 1024, dev_priv->bar3_vm, &chan);
 	if (ret)
-		return ret;
-	nv_wo32(priv->pramin_bar, 0x00, 0x7fc00000);
-	nv_wo32(priv->pramin_bar, 0x04, dev_priv->ramin_size - 1);
-	nv_wo32(priv->pramin_bar, 0x08, 0x00000000);
-	nv_wo32(priv->pramin_bar, 0x0c, 0x00000000);
-	nv_wo32(priv->pramin_bar, 0x10, 0x00000000);
-	nv_wo32(priv->pramin_bar, 0x14, 0x00000000);
+		goto error;
+	dev_priv->channels.ptr[0] = dev_priv->channels.ptr[127] = chan;
 
-	/* map channel into PRAMIN, gpuobj didn't do it for us */
-	ret = nv50_instmem_bind(dev, chan->ramin);
+	ret = nv50_gpuobj_dma_new(chan, 0x0000, BAR3_VM_BASE, BAR3_VM_SIZE,
+				  NV_MEM_TARGET_VM, NV_MEM_ACCESS_VM,
+				  NV_MEM_TYPE_VM, NV_MEM_COMP_VM,
+				  &priv->bar3_dmaobj);
 	if (ret)
-		return ret;
+		goto error;
 
-	/* poke regs... */
 	nv_wr32(dev, 0x001704, 0x00000000 | (chan->ramin->vinst >> 12));
 	nv_wr32(dev, 0x001704, 0x40000000 | (chan->ramin->vinst >> 12));
-	nv_wr32(dev, 0x00170c, 0x80000000 | (priv->pramin_bar->cinst >> 4));
-
-	tmp = nv_ri32(dev, 0);
-	nv_wi32(dev, 0, ~tmp);
-	if (nv_ri32(dev, 0) != ~tmp) {
-		NV_ERROR(dev, "PRAMIN readback failed\n");
-		return -EIO;
-	}
-	nv_wi32(dev, 0, tmp);
+	nv_wr32(dev, 0x00170c, 0x80000000 | (priv->bar3_dmaobj->cinst >> 4));
 
+	dev_priv->engine.instmem.flush(dev);
 	dev_priv->ramin_available = true;
 
-	/* Determine VM layout */
-	dev_priv->vm_gart_base = roundup(NV50_VM_BLOCK, NV50_VM_BLOCK);
-	dev_priv->vm_gart_size = NV50_VM_BLOCK;
-
-	dev_priv->vm_vram_base = dev_priv->vm_gart_base + dev_priv->vm_gart_size;
-	dev_priv->vm_vram_size = dev_priv->vram_size;
-	if (dev_priv->vm_vram_size > NV50_VM_MAX_VRAM)
-		dev_priv->vm_vram_size = NV50_VM_MAX_VRAM;
-	dev_priv->vm_vram_size = roundup(dev_priv->vm_vram_size, NV50_VM_BLOCK);
-	dev_priv->vm_vram_pt_nr = dev_priv->vm_vram_size / NV50_VM_BLOCK;
-
-	dev_priv->vm_end = dev_priv->vm_vram_base + dev_priv->vm_vram_size;
-
-	NV_DEBUG(dev, "NV50VM: GART 0x%016llx-0x%016llx\n",
-		 dev_priv->vm_gart_base,
-		 dev_priv->vm_gart_base + dev_priv->vm_gart_size - 1);
-	NV_DEBUG(dev, "NV50VM: VRAM 0x%016llx-0x%016llx\n",
-		 dev_priv->vm_vram_base,
-		 dev_priv->vm_vram_base + dev_priv->vm_vram_size - 1);
-
-	/* VRAM page table(s), mapped into VM at +1GiB  */
-	for (i = 0; i < dev_priv->vm_vram_pt_nr; i++) {
-		ret = nouveau_gpuobj_new(dev, NULL, NV50_VM_BLOCK / 0x10000 * 8,
-					 0, NVOBJ_FLAG_ZERO_ALLOC,
-					 &chan->vm_vram_pt[i]);
-		if (ret) {
-			NV_ERROR(dev, "Error creating VRAM PGT: %d\n", ret);
-			dev_priv->vm_vram_pt_nr = i;
-			return ret;
-		}
-		dev_priv->vm_vram_pt[i] = chan->vm_vram_pt[i];
-
-		nv_wo32(chan->vm_pd, 0x10 + (i*8),
-			chan->vm_vram_pt[i]->vinst | 0x61);
-		nv_wo32(chan->vm_pd, 0x14 + (i*8), 0);
+	tmp = nv_ro32(chan->ramin, 0);
+	nv_wo32(chan->ramin, 0, ~tmp);
+	if (nv_ro32(chan->ramin, 0) != ~tmp) {
+		NV_ERROR(dev, "PRAMIN readback failed\n");
+		ret = -EIO;
+		goto error;
 	}
+	nv_wo32(chan->ramin, 0, tmp);
 
-	/* DMA object for FB BAR */
-	ret = nouveau_gpuobj_new(dev, chan, 6*4, 16, 0, &priv->fb_bar);
+	/* BAR1 */
+	ret = nouveau_vm_new(dev, BAR1_VM_BASE, BAR1_VM_SIZE, BAR1_VM_BASE, &vm);
 	if (ret)
-		return ret;
-	nv_wo32(priv->fb_bar, 0x00, 0x7fc00000);
-	nv_wo32(priv->fb_bar, 0x04, 0x40000000 +
-				    pci_resource_len(dev->pdev, 1) - 1);
-	nv_wo32(priv->fb_bar, 0x08, 0x40000000);
-	nv_wo32(priv->fb_bar, 0x0c, 0x00000000);
-	nv_wo32(priv->fb_bar, 0x10, 0x00000000);
-	nv_wo32(priv->fb_bar, 0x14, 0x00000000);
+		goto error;
 
-	dev_priv->engine.instmem.flush(dev);
+	ret = nouveau_vm_ref(vm, &dev_priv->bar1_vm, chan->vm_pd);
+	if (ret)
+		goto error;
+	nouveau_vm_ref(NULL, &vm, NULL);
 
-	nv_wr32(dev, 0x001708, 0x80000000 | (priv->fb_bar->cinst >> 4));
+	ret = nv50_gpuobj_dma_new(chan, 0x0000, BAR1_VM_BASE, BAR1_VM_SIZE,
+				  NV_MEM_TARGET_VM, NV_MEM_ACCESS_VM,
+				  NV_MEM_TYPE_VM, NV_MEM_COMP_VM,
+				  &priv->bar1_dmaobj);
+	if (ret)
+		goto error;
+
+	nv_wr32(dev, 0x001708, 0x80000000 | (priv->bar1_dmaobj->cinst >> 4));
 	for (i = 0; i < 8; i++)
 		nv_wr32(dev, 0x1900 + (i*4), 0);
 
+	/* Create shared channel VM, space is reserved at the beginning
+	 * to catch "NULL pointer" references
+	 */
+	ret = nouveau_vm_new(dev, 0, (1ULL << 40), 0x0020000000ULL,
+			     &dev_priv->chan_vm);
+	if (ret)
+		return ret;
+
 	return 0;
+
+error:
+	nv50_instmem_takedown(dev);
+	return ret;
 }
 
 void
@@ -240,7 +234,7 @@ nv50_instmem_takedown(struct drm_device
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct nv50_instmem_priv *priv = dev_priv->engine.instmem.priv;
-	struct nouveau_channel *chan = dev_priv->fifos[0];
+	struct nouveau_channel *chan = dev_priv->channels.ptr[0];
 	int i;
 
 	NV_DEBUG(dev, "\n");
@@ -250,23 +244,23 @@ nv50_instmem_takedown(struct drm_device
 
 	dev_priv->ramin_available = false;
 
-	/* Restore state from before init */
+	nouveau_vm_ref(NULL, &dev_priv->chan_vm, NULL);
+
 	for (i = 0x1700; i <= 0x1710; i += 4)
 		nv_wr32(dev, i, priv->save1700[(i - 0x1700) / 4]);
 
-	nouveau_gpuobj_ref(NULL, &priv->fb_bar);
-	nouveau_gpuobj_ref(NULL, &priv->pramin_bar);
-	nouveau_gpuobj_ref(NULL, &priv->pramin_pt);
+	nouveau_gpuobj_ref(NULL, &priv->bar3_dmaobj);
+	nouveau_gpuobj_ref(NULL, &priv->bar1_dmaobj);
 
-	/* Destroy dummy channel */
-	if (chan) {
-		for (i = 0; i < dev_priv->vm_vram_pt_nr; i++)
-			nouveau_gpuobj_ref(NULL, &chan->vm_vram_pt[i]);
-		dev_priv->vm_vram_pt_nr = 0;
+	nouveau_vm_ref(NULL, &dev_priv->bar1_vm, chan->vm_pd);
+	dev_priv->channels.ptr[127] = 0;
+	nv50_channel_del(&dev_priv->channels.ptr[0]);
 
-		nv50_channel_del(&dev_priv->fifos[0]);
-		dev_priv->fifos[127] = NULL;
-	}
+	nouveau_gpuobj_ref(NULL, &dev_priv->bar3_vm->pgt[0].obj[0]);
+	nouveau_vm_ref(NULL, &dev_priv->bar3_vm, NULL);
+
+	if (dev_priv->ramin_heap.free_stack.next)
+		drm_mm_takedown(&dev_priv->ramin_heap);
 
 	dev_priv->engine.instmem.priv = NULL;
 	kfree(priv);
@@ -276,16 +270,8 @@ int
 nv50_instmem_suspend(struct drm_device *dev)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nouveau_channel *chan = dev_priv->fifos[0];
-	struct nouveau_gpuobj *ramin = chan->ramin;
-	int i;
-
-	ramin->im_backing_suspend = vmalloc(ramin->size);
-	if (!ramin->im_backing_suspend)
-		return -ENOMEM;
 
-	for (i = 0; i < ramin->size; i += 4)
-		ramin->im_backing_suspend[i/4] = nv_ri32(dev, i);
+	dev_priv->ramin_available = false;
 	return 0;
 }
 
@@ -294,169 +280,147 @@ nv50_instmem_resume(struct drm_device *d
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct nv50_instmem_priv *priv = dev_priv->engine.instmem.priv;
-	struct nouveau_channel *chan = dev_priv->fifos[0];
-	struct nouveau_gpuobj *ramin = chan->ramin;
+	struct nouveau_channel *chan = dev_priv->channels.ptr[0];
 	int i;
 
-	dev_priv->ramin_available = false;
-	dev_priv->ramin_base = ~0;
-	for (i = 0; i < ramin->size; i += 4)
-		nv_wo32(ramin, i, ramin->im_backing_suspend[i/4]);
-	dev_priv->ramin_available = true;
-	vfree(ramin->im_backing_suspend);
-	ramin->im_backing_suspend = NULL;
-
 	/* Poke the relevant regs, and pray it works :) */
 	nv_wr32(dev, NV50_PUNK_BAR_CFG_BASE, (chan->ramin->vinst >> 12));
 	nv_wr32(dev, NV50_PUNK_UNK1710, 0);
 	nv_wr32(dev, NV50_PUNK_BAR_CFG_BASE, (chan->ramin->vinst >> 12) |
 					 NV50_PUNK_BAR_CFG_BASE_VALID);
-	nv_wr32(dev, NV50_PUNK_BAR1_CTXDMA, (priv->fb_bar->cinst >> 4) |
+	nv_wr32(dev, NV50_PUNK_BAR1_CTXDMA, (priv->bar1_dmaobj->cinst >> 4) |
 					NV50_PUNK_BAR1_CTXDMA_VALID);
-	nv_wr32(dev, NV50_PUNK_BAR3_CTXDMA, (priv->pramin_bar->cinst >> 4) |
+	nv_wr32(dev, NV50_PUNK_BAR3_CTXDMA, (priv->bar3_dmaobj->cinst >> 4) |
 					NV50_PUNK_BAR3_CTXDMA_VALID);
 
 	for (i = 0; i < 8; i++)
 		nv_wr32(dev, 0x1900 + (i*4), 0);
+
+	dev_priv->ramin_available = true;
 }
 
+struct nv50_gpuobj_node {
+	struct nouveau_vram *vram;
+	struct nouveau_vma chan_vma;
+	u32 align;
+};
+
+
 int
-nv50_instmem_populate(struct drm_device *dev, struct nouveau_gpuobj *gpuobj,
-		      uint32_t *sz)
+nv50_instmem_get(struct nouveau_gpuobj *gpuobj, u32 size, u32 align)
 {
+	struct drm_device *dev = gpuobj->dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_vram_engine *vram = &dev_priv->engine.vram;
+	struct nv50_gpuobj_node *node = NULL;
 	int ret;
 
-	if (gpuobj->im_backing)
-		return -EINVAL;
+	node = kzalloc(sizeof(*node), GFP_KERNEL);
+	if (!node)
+		return -ENOMEM;
+	node->align = align;
 
-	*sz = ALIGN(*sz, 4096);
-	if (*sz == 0)
-		return -EINVAL;
+	size  = (size + 4095) & ~4095;
+	align = max(align, (u32)4096);
 
-	ret = nouveau_bo_new(dev, NULL, *sz, 0, TTM_PL_FLAG_VRAM, 0, 0x0000,
-			     true, false, &gpuobj->im_backing);
+	ret = vram->get(dev, size, align, 0, 0, &node->vram);
 	if (ret) {
-		NV_ERROR(dev, "error getting PRAMIN backing pages: %d\n", ret);
+		kfree(node);
 		return ret;
 	}
 
-	ret = nouveau_bo_pin(gpuobj->im_backing, TTM_PL_FLAG_VRAM);
-	if (ret) {
-		NV_ERROR(dev, "error pinning PRAMIN backing VRAM: %d\n", ret);
-		nouveau_bo_ref(NULL, &gpuobj->im_backing);
-		return ret;
+	gpuobj->vinst = node->vram->offset;
+
+	if (gpuobj->flags & NVOBJ_FLAG_VM) {
+		u32 flags = NV_MEM_ACCESS_RW;
+		if (!(gpuobj->flags & NVOBJ_FLAG_VM_USER))
+			flags |= NV_MEM_ACCESS_SYS;
+
+		ret = nouveau_vm_get(dev_priv->chan_vm, size, 12, flags,
+				     &node->chan_vma);
+		if (ret) {
+			vram->put(dev, &node->vram);
+			kfree(node);
+			return ret;
+		}
+
+		nouveau_vm_map(&node->chan_vma, node->vram);
+		gpuobj->vinst = node->chan_vma.offset;
 	}
 
-	gpuobj->vinst = gpuobj->im_backing->bo.mem.start << PAGE_SHIFT;
+	gpuobj->size = size;
+	gpuobj->node = node;
 	return 0;
 }
 
 void
-nv50_instmem_clear(struct drm_device *dev, struct nouveau_gpuobj *gpuobj)
+nv50_instmem_put(struct nouveau_gpuobj *gpuobj)
 {
+	struct drm_device *dev = gpuobj->dev;
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_vram_engine *vram = &dev_priv->engine.vram;
+	struct nv50_gpuobj_node *node;
 
-	if (gpuobj && gpuobj->im_backing) {
-		if (gpuobj->im_bound)
-			dev_priv->engine.instmem.unbind(dev, gpuobj);
-		nouveau_bo_unpin(gpuobj->im_backing);
-		nouveau_bo_ref(NULL, &gpuobj->im_backing);
-		gpuobj->im_backing = NULL;
+	node = gpuobj->node;
+	gpuobj->node = NULL;
+
+	if (node->chan_vma.node) {
+		nouveau_vm_unmap(&node->chan_vma);
+		nouveau_vm_put(&node->chan_vma);
 	}
+	vram->put(dev, &node->vram);
+	kfree(node);
 }
 
 int
-nv50_instmem_bind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj)
+nv50_instmem_map(struct nouveau_gpuobj *gpuobj)
 {
-	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nv50_instmem_priv *priv = dev_priv->engine.instmem.priv;
-	struct nouveau_gpuobj *pramin_pt = priv->pramin_pt;
-	uint32_t pte, pte_end;
-	uint64_t vram;
-
-	if (!gpuobj->im_backing || !gpuobj->im_pramin || gpuobj->im_bound)
-		return -EINVAL;
-
-	NV_DEBUG(dev, "st=0x%lx sz=0x%lx\n",
-		 gpuobj->im_pramin->start, gpuobj->im_pramin->size);
-
-	pte     = (gpuobj->im_pramin->start >> 12) << 1;
-	pte_end = ((gpuobj->im_pramin->size >> 12) << 1) + pte;
-	vram    = gpuobj->vinst;
-
-	NV_DEBUG(dev, "pramin=0x%lx, pte=%d, pte_end=%d\n",
-		 gpuobj->im_pramin->start, pte, pte_end);
-	NV_DEBUG(dev, "first vram page: 0x%010llx\n", gpuobj->vinst);
-
-	vram |= 1;
-	if (dev_priv->vram_sys_base) {
-		vram += dev_priv->vram_sys_base;
-		vram |= 0x30;
-	}
-
-	while (pte < pte_end) {
-		nv_wo32(pramin_pt, (pte * 4) + 0, lower_32_bits(vram));
-		nv_wo32(pramin_pt, (pte * 4) + 4, upper_32_bits(vram));
-		vram += 0x1000;
-		pte += 2;
-	}
-	dev_priv->engine.instmem.flush(dev);
+	struct drm_nouveau_private *dev_priv = gpuobj->dev->dev_private;
+	struct nv50_gpuobj_node *node = gpuobj->node;
+	int ret;
 
-	nv50_vm_flush(dev, 6);
+	ret = nouveau_vm_get(dev_priv->bar3_vm, gpuobj->size, 12,
+			     NV_MEM_ACCESS_RW, &node->vram->bar_vma);
+	if (ret)
+		return ret;
 
-	gpuobj->im_bound = 1;
+	nouveau_vm_map(&node->vram->bar_vma, node->vram);
+	gpuobj->pinst = node->vram->bar_vma.offset;
 	return 0;
 }
 
-int
-nv50_instmem_unbind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj)
+void
+nv50_instmem_unmap(struct nouveau_gpuobj *gpuobj)
 {
-	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nv50_instmem_priv *priv = dev_priv->engine.instmem.priv;
-	uint32_t pte, pte_end;
-
-	if (gpuobj->im_bound == 0)
-		return -EINVAL;
-
-	/* can happen during late takedown */
-	if (unlikely(!dev_priv->ramin_available))
-		return 0;
-
-	pte     = (gpuobj->im_pramin->start >> 12) << 1;
-	pte_end = ((gpuobj->im_pramin->size >> 12) << 1) + pte;
+	struct nv50_gpuobj_node *node = gpuobj->node;
 
-	while (pte < pte_end) {
-		nv_wo32(priv->pramin_pt, (pte * 4) + 0, 0x00000000);
-		nv_wo32(priv->pramin_pt, (pte * 4) + 4, 0x00000000);
-		pte += 2;
+	if (node->vram->bar_vma.node) {
+		nouveau_vm_unmap(&node->vram->bar_vma);
+		nouveau_vm_put(&node->vram->bar_vma);
 	}
-	dev_priv->engine.instmem.flush(dev);
-
-	gpuobj->im_bound = 0;
-	return 0;
 }
 
 void
 nv50_instmem_flush(struct drm_device *dev)
 {
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+	spin_lock(&dev_priv->ramin_lock);
 	nv_wr32(dev, 0x00330c, 0x00000001);
 	if (!nv_wait(dev, 0x00330c, 0x00000002, 0x00000000))
 		NV_ERROR(dev, "PRAMIN flush timeout\n");
+	spin_unlock(&dev_priv->ramin_lock);
 }
 
 void
 nv84_instmem_flush(struct drm_device *dev)
 {
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+	spin_lock(&dev_priv->ramin_lock);
 	nv_wr32(dev, 0x070000, 0x00000001);
 	if (!nv_wait(dev, 0x070000, 0x00000002, 0x00000000))
 		NV_ERROR(dev, "PRAMIN flush timeout\n");
-}
-
-void
-nv50_vm_flush(struct drm_device *dev, int engine)
-{
-	nv_wr32(dev, 0x100c80, (engine << 16) | 1);
-	if (!nv_wait(dev, 0x100c80, 0x00000001, 0x00000000))
-		NV_ERROR(dev, "vm flush timeout: engine %d\n", engine);
+	spin_unlock(&dev_priv->ramin_lock);
 }
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nv50_vm.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nv50_vm.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nv50_vm.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nv50_vm.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,179 @@
+/*
+ * Copyright 2010 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_vm.h"
+
+void
+nv50_vm_map_pgt(struct nouveau_gpuobj *pgd, u32 pde,
+		struct nouveau_gpuobj *pgt[2])
+{
+	struct drm_nouveau_private *dev_priv = pgd->dev->dev_private;
+	u64 phys = 0xdeadcafe00000000ULL;
+	u32 coverage = 0;
+
+	if (pgt[0]) {
+		phys = 0x00000003 | pgt[0]->vinst; /* present, 4KiB pages */
+		coverage = (pgt[0]->size >> 3) << 12;
+	} else
+	if (pgt[1]) {
+		phys = 0x00000001 | pgt[1]->vinst; /* present */
+		coverage = (pgt[1]->size >> 3) << 16;
+	}
+
+	if (phys & 1) {
+		if (coverage <= 32 * 1024 * 1024)
+			phys |= 0x60;
+		else if (coverage <= 64 * 1024 * 1024)
+			phys |= 0x40;
+		else if (coverage < 128 * 1024 * 1024)
+			phys |= 0x20;
+	}
+
+	nv_wo32(pgd, (pde * 8) + 0, lower_32_bits(phys));
+	nv_wo32(pgd, (pde * 8) + 4, upper_32_bits(phys));
+}
+
+static inline u64
+nv50_vm_addr(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt,
+	     u64 phys, u32 memtype, u32 target)
+{
+	struct drm_nouveau_private *dev_priv = pgt->dev->dev_private;
+
+	phys |= 1; /* present */
+	phys |= (u64)memtype << 40;
+
+	/* IGPs don't have real VRAM, re-target to stolen system memory */
+	if (target == 0 && dev_priv->vram_sys_base) {
+		phys  += dev_priv->vram_sys_base;
+		target = 3;
+	}
+
+	phys |= target << 4;
+
+	if (vma->access & NV_MEM_ACCESS_SYS)
+		phys |= (1 << 6);
+
+	if (!(vma->access & NV_MEM_ACCESS_WO))
+		phys |= (1 << 3);
+
+	return phys;
+}
+
+void
+nv50_vm_map(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt,
+	    struct nouveau_vram *mem, u32 pte, u32 cnt, u64 phys)
+{
+	u32 block;
+	int i;
+
+	phys  = nv50_vm_addr(vma, pgt, phys, mem->memtype, 0);
+	pte <<= 3;
+	cnt <<= 3;
+
+	while (cnt) {
+		u32 offset_h = upper_32_bits(phys);
+		u32 offset_l = lower_32_bits(phys);
+
+		for (i = 7; i >= 0; i--) {
+			block = 1 << (i + 3);
+			if (cnt >= block && !(pte & (block - 1)))
+				break;
+		}
+		offset_l |= (i << 7);
+
+		phys += block << (vma->node->type - 3);
+		cnt  -= block;
+
+		while (block) {
+			nv_wo32(pgt, pte + 0, offset_l);
+			nv_wo32(pgt, pte + 4, offset_h);
+			pte += 8;
+			block -= 8;
+		}
+	}
+}
+
+void
+nv50_vm_map_sg(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt,
+	       u32 pte, dma_addr_t *list, u32 cnt)
+{
+	pte <<= 3;
+	while (cnt--) {
+		u64 phys = nv50_vm_addr(vma, pgt, (u64)*list++, 0, 2);
+		nv_wo32(pgt, pte + 0, lower_32_bits(phys));
+		nv_wo32(pgt, pte + 4, upper_32_bits(phys));
+		pte += 8;
+	}
+}
+
+void
+nv50_vm_unmap(struct nouveau_gpuobj *pgt, u32 pte, u32 cnt)
+{
+	pte <<= 3;
+	while (cnt--) {
+		nv_wo32(pgt, pte + 0, 0x00000000);
+		nv_wo32(pgt, pte + 4, 0x00000000);
+		pte += 8;
+	}
+}
+
+void
+nv50_vm_flush(struct nouveau_vm *vm)
+{
+	struct drm_nouveau_private *dev_priv = vm->dev->dev_private;
+	struct nouveau_instmem_engine *pinstmem = &dev_priv->engine.instmem;
+	struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo;
+	struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
+	struct nouveau_crypt_engine *pcrypt = &dev_priv->engine.crypt;
+
+	pinstmem->flush(vm->dev);
+
+	/* BAR */
+	if (vm != dev_priv->chan_vm) {
+		nv50_vm_flush_engine(vm->dev, 6);
+		return;
+	}
+
+	pfifo->tlb_flush(vm->dev);
+
+	if (atomic_read(&vm->pgraph_refs))
+		pgraph->tlb_flush(vm->dev);
+	if (atomic_read(&vm->pcrypt_refs))
+		pcrypt->tlb_flush(vm->dev);
+}
+
+void
+nv50_vm_flush_engine(struct drm_device *dev, int engine)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+	spin_lock(&dev_priv->ramin_lock);
+	nv_wr32(dev, 0x100c80, (engine << 16) | 1);
+	if (!nv_wait(dev, 0x100c80, 0x00000001, 0x00000000))
+		NV_ERROR(dev, "vm flush timeout: engine %d\n", engine);
+	spin_unlock(&dev_priv->ramin_lock);
+}
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nv50_vram.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nv50_vram.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nv50_vram.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nv50_vram.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,190 @@
+/*
+ * Copyright 2010 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_mm.h"
+
+static int types[0x80] = {
+	1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	1, 1, 1, 1, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0,
+	1, 1, 1, 1, 1, 1, 1, 0, 2, 2, 2, 2, 2, 2, 2, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 0, 0,
+	0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 2, 2, 2, 2,
+	1, 0, 2, 0, 1, 0, 2, 0, 1, 1, 2, 2, 1, 1, 0, 0
+};
+
+bool
+nv50_vram_flags_valid(struct drm_device *dev, u32 tile_flags)
+{
+	int type = (tile_flags & NOUVEAU_GEM_TILE_LAYOUT_MASK) >> 8;
+
+	if (likely(type < ARRAY_SIZE(types) && types[type]))
+		return true;
+	return false;
+}
+
+void
+nv50_vram_del(struct drm_device *dev, struct nouveau_vram **pvram)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct ttm_bo_device *bdev = &dev_priv->ttm.bdev;
+	struct ttm_mem_type_manager *man = &bdev->man[TTM_PL_VRAM];
+	struct nouveau_mm *mm = man->priv;
+	struct nouveau_mm_node *this;
+	struct nouveau_vram *vram;
+
+	vram = *pvram;
+	*pvram = NULL;
+	if (unlikely(vram == NULL))
+		return;
+
+	mutex_lock(&mm->mutex);
+	while (!list_empty(&vram->regions)) {
+		this = list_first_entry(&vram->regions, struct nouveau_mm_node, rl_entry);
+
+		list_del(&this->rl_entry);
+		nouveau_mm_put(mm, this);
+	}
+	mutex_unlock(&mm->mutex);
+
+	kfree(vram);
+}
+
+int
+nv50_vram_new(struct drm_device *dev, u64 size, u32 align, u32 size_nc,
+	      u32 type, struct nouveau_vram **pvram)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct ttm_bo_device *bdev = &dev_priv->ttm.bdev;
+	struct ttm_mem_type_manager *man = &bdev->man[TTM_PL_VRAM];
+	struct nouveau_mm *mm = man->priv;
+	struct nouveau_mm_node *r;
+	struct nouveau_vram *vram;
+	int ret;
+
+	if (!types[type])
+		return -EINVAL;
+	size >>= 12;
+	align >>= 12;
+	size_nc >>= 12;
+
+	vram = kzalloc(sizeof(*vram), GFP_KERNEL);
+	if (!vram)
+		return -ENOMEM;
+
+	INIT_LIST_HEAD(&vram->regions);
+	vram->dev = dev_priv->dev;
+	vram->memtype = type;
+	vram->size = size;
+
+	mutex_lock(&mm->mutex);
+	do {
+		ret = nouveau_mm_get(mm, types[type], size, size_nc, align, &r);
+		if (ret) {
+			mutex_unlock(&mm->mutex);
+			nv50_vram_del(dev, &vram);
+			return ret;
+		}
+
+		list_add_tail(&r->rl_entry, &vram->regions);
+		size -= r->length;
+	} while (size);
+	mutex_unlock(&mm->mutex);
+
+	r = list_first_entry(&vram->regions, struct nouveau_mm_node, rl_entry);
+	vram->offset = (u64)r->offset << 12;
+	*pvram = vram;
+	return 0;
+}
+
+static u32
+nv50_vram_rblock(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	int i, parts, colbits, rowbitsa, rowbitsb, banks;
+	u64 rowsize, predicted;
+	u32 r0, r4, rt, ru, rblock_size;
+
+	r0 = nv_rd32(dev, 0x100200);
+	r4 = nv_rd32(dev, 0x100204);
+	rt = nv_rd32(dev, 0x100250);
+	ru = nv_rd32(dev, 0x001540);
+	NV_DEBUG(dev, "memcfg 0x%08x 0x%08x 0x%08x 0x%08x\n", r0, r4, rt, ru);
+
+	for (i = 0, parts = 0; i < 8; i++) {
+		if (ru & (0x00010000 << i))
+			parts++;
+	}
+
+	colbits  =  (r4 & 0x0000f000) >> 12;
+	rowbitsa = ((r4 & 0x000f0000) >> 16) + 8;
+	rowbitsb = ((r4 & 0x00f00000) >> 20) + 8;
+	banks    = ((r4 & 0x01000000) ? 8 : 4);
+
+	rowsize = parts * banks * (1 << colbits) * 8;
+	predicted = rowsize << rowbitsa;
+	if (r0 & 0x00000004)
+		predicted += rowsize << rowbitsb;
+
+	if (predicted != dev_priv->vram_size) {
+		NV_WARN(dev, "memory controller reports %dMiB VRAM\n",
+			(u32)(dev_priv->vram_size >> 20));
+		NV_WARN(dev, "we calculated %dMiB VRAM\n",
+			(u32)(predicted >> 20));
+	}
+
+	rblock_size = rowsize;
+	if (rt & 1)
+		rblock_size *= 3;
+
+	NV_DEBUG(dev, "rblock %d bytes\n", rblock_size);
+	return rblock_size;
+}
+
+int
+nv50_vram_init(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+	dev_priv->vram_size  = nv_rd32(dev, 0x10020c);
+	dev_priv->vram_size |= (dev_priv->vram_size & 0xff) << 32;
+	dev_priv->vram_size &= 0xffffffff00ULL;
+
+	switch (dev_priv->chipset) {
+	case 0xaa:
+	case 0xac:
+	case 0xaf:
+		dev_priv->vram_sys_base = (u64)nv_rd32(dev, 0x100e10) << 12;
+		dev_priv->vram_rblock_size = 4096;
+		break;
+	default:
+		dev_priv->vram_rblock_size = nv50_vram_rblock(dev);
+		break;
+	}
+
+	return 0;
+}
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nv84_crypt.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nv84_crypt.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nv84_crypt.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nv84_crypt.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,140 @@
+/*
+ * Copyright 2010 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_util.h"
+#include "nouveau_vm.h"
+
+static void nv84_crypt_isr(struct drm_device *);
+
+int
+nv84_crypt_create_context(struct nouveau_channel *chan)
+{
+	struct drm_device *dev = chan->dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_gpuobj *ramin = chan->ramin;
+	int ret;
+
+	NV_DEBUG(dev, "ch%d\n", chan->id);
+
+	ret = nouveau_gpuobj_new(dev, chan, 256, 0,
+				 NVOBJ_FLAG_ZERO_ALLOC | NVOBJ_FLAG_ZERO_FREE,
+				 &chan->crypt_ctx);
+	if (ret)
+		return ret;
+
+	nv_wo32(ramin, 0xa0, 0x00190000);
+	nv_wo32(ramin, 0xa4, chan->crypt_ctx->vinst + 0xff);
+	nv_wo32(ramin, 0xa8, chan->crypt_ctx->vinst);
+	nv_wo32(ramin, 0xac, 0);
+	nv_wo32(ramin, 0xb0, 0);
+	nv_wo32(ramin, 0xb4, 0);
+
+	dev_priv->engine.instmem.flush(dev);
+	atomic_inc(&chan->vm->pcrypt_refs);
+	return 0;
+}
+
+void
+nv84_crypt_destroy_context(struct nouveau_channel *chan)
+{
+	struct drm_device *dev = chan->dev;
+	u32 inst;
+
+	if (!chan->crypt_ctx)
+		return;
+
+	inst  = (chan->ramin->vinst >> 12);
+	inst |= 0x80000000;
+
+	/* mark context as invalid if still on the hardware, not
+	 * doing this causes issues the next time PCRYPT is used,
+	 * unsurprisingly :)
+	 */
+	nv_wr32(dev, 0x10200c, 0x00000000);
+	if (nv_rd32(dev, 0x102188) == inst)
+		nv_mask(dev, 0x102188, 0x80000000, 0x00000000);
+	if (nv_rd32(dev, 0x10218c) == inst)
+		nv_mask(dev, 0x10218c, 0x80000000, 0x00000000);
+	nv_wr32(dev, 0x10200c, 0x00000010);
+
+	nouveau_gpuobj_ref(NULL, &chan->crypt_ctx);
+	atomic_dec(&chan->vm->pcrypt_refs);
+}
+
+void
+nv84_crypt_tlb_flush(struct drm_device *dev)
+{
+	nv50_vm_flush_engine(dev, 0x0a);
+}
+
+int
+nv84_crypt_init(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_crypt_engine *pcrypt = &dev_priv->engine.crypt;
+
+	if (!pcrypt->registered) {
+		NVOBJ_CLASS(dev, 0x74c1, CRYPT);
+		pcrypt->registered = true;
+	}
+
+	nv_mask(dev, 0x000200, 0x00004000, 0x00000000);
+	nv_mask(dev, 0x000200, 0x00004000, 0x00004000);
+
+	nouveau_irq_register(dev, 14, nv84_crypt_isr);
+	nv_wr32(dev, 0x102130, 0xffffffff);
+	nv_wr32(dev, 0x102140, 0xffffffbf);
+
+	nv_wr32(dev, 0x10200c, 0x00000010);
+	return 0;
+}
+
+void
+nv84_crypt_fini(struct drm_device *dev)
+{
+	nv_wr32(dev, 0x102140, 0x00000000);
+	nouveau_irq_unregister(dev, 14);
+}
+
+static void
+nv84_crypt_isr(struct drm_device *dev)
+{
+	u32 stat = nv_rd32(dev, 0x102130);
+	u32 mthd = nv_rd32(dev, 0x102190);
+	u32 data = nv_rd32(dev, 0x102194);
+	u32 inst = nv_rd32(dev, 0x102188) & 0x7fffffff;
+	int show = nouveau_ratelimit();
+
+	if (show) {
+		NV_INFO(dev, "PCRYPT_INTR: 0x%08x 0x%08x 0x%08x 0x%08x\n",
+			     stat, mthd, data, inst);
+	}
+
+	nv_wr32(dev, 0x102130, stat);
+	nv_wr32(dev, 0x10200c, 0x10);
+
+	nv50_fb_vm_trap(dev, show, "PCRYPT");
+}
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nvc0_fbcon.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nvc0_fbcon.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nvc0_fbcon.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nvc0_fbcon.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,269 @@
+/*
+ * Copyright 2010 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_dma.h"
+#include "nouveau_ramht.h"
+#include "nouveau_fbcon.h"
+#include "nouveau_mm.h"
+
+int
+nvc0_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
+{
+	struct nouveau_fbdev *nfbdev = info->par;
+	struct drm_device *dev = nfbdev->dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_channel *chan = dev_priv->channel;
+	int ret;
+
+	ret = RING_SPACE(chan, rect->rop == ROP_COPY ? 7 : 11);
+	if (ret)
+		return ret;
+
+	if (rect->rop != ROP_COPY) {
+		BEGIN_NVC0(chan, 2, NvSub2D, 0x02ac, 1);
+		OUT_RING  (chan, 1);
+	}
+	BEGIN_NVC0(chan, 2, NvSub2D, 0x0588, 1);
+	if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
+	    info->fix.visual == FB_VISUAL_DIRECTCOLOR)
+		OUT_RING  (chan, ((uint32_t *)info->pseudo_palette)[rect->color]);
+	else
+		OUT_RING  (chan, rect->color);
+	BEGIN_NVC0(chan, 2, NvSub2D, 0x0600, 4);
+	OUT_RING  (chan, rect->dx);
+	OUT_RING  (chan, rect->dy);
+	OUT_RING  (chan, rect->dx + rect->width);
+	OUT_RING  (chan, rect->dy + rect->height);
+	if (rect->rop != ROP_COPY) {
+		BEGIN_NVC0(chan, 2, NvSub2D, 0x02ac, 1);
+		OUT_RING  (chan, 3);
+	}
+	FIRE_RING(chan);
+	return 0;
+}
+
+int
+nvc0_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region)
+{
+	struct nouveau_fbdev *nfbdev = info->par;
+	struct drm_device *dev = nfbdev->dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_channel *chan = dev_priv->channel;
+	int ret;
+
+	ret = RING_SPACE(chan, 12);
+	if (ret)
+		return ret;
+
+	BEGIN_NVC0(chan, 2, NvSub2D, 0x0110, 1);
+	OUT_RING  (chan, 0);
+	BEGIN_NVC0(chan, 2, NvSub2D, 0x08b0, 4);
+	OUT_RING  (chan, region->dx);
+	OUT_RING  (chan, region->dy);
+	OUT_RING  (chan, region->width);
+	OUT_RING  (chan, region->height);
+	BEGIN_NVC0(chan, 2, NvSub2D, 0x08d0, 4);
+	OUT_RING  (chan, 0);
+	OUT_RING  (chan, region->sx);
+	OUT_RING  (chan, 0);
+	OUT_RING  (chan, region->sy);
+	FIRE_RING(chan);
+	return 0;
+}
+
+int
+nvc0_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
+{
+	struct nouveau_fbdev *nfbdev = info->par;
+	struct drm_device *dev = nfbdev->dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_channel *chan = dev_priv->channel;
+	uint32_t width, dwords, *data = (uint32_t *)image->data;
+	uint32_t mask = ~(~0 >> (32 - info->var.bits_per_pixel));
+	uint32_t *palette = info->pseudo_palette;
+	int ret;
+
+	if (image->depth != 1)
+		return -ENODEV;
+
+	ret = RING_SPACE(chan, 11);
+	if (ret)
+		return ret;
+
+	width = ALIGN(image->width, 32);
+	dwords = (width * image->height) >> 5;
+
+	BEGIN_NVC0(chan, 2, NvSub2D, 0x0814, 2);
+	if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
+	    info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
+		OUT_RING  (chan, palette[image->bg_color] | mask);
+		OUT_RING  (chan, palette[image->fg_color] | mask);
+	} else {
+		OUT_RING  (chan, image->bg_color);
+		OUT_RING  (chan, image->fg_color);
+	}
+	BEGIN_NVC0(chan, 2, NvSub2D, 0x0838, 2);
+	OUT_RING  (chan, image->width);
+	OUT_RING  (chan, image->height);
+	BEGIN_NVC0(chan, 2, NvSub2D, 0x0850, 4);
+	OUT_RING  (chan, 0);
+	OUT_RING  (chan, image->dx);
+	OUT_RING  (chan, 0);
+	OUT_RING  (chan, image->dy);
+
+	while (dwords) {
+		int push = dwords > 2047 ? 2047 : dwords;
+
+		ret = RING_SPACE(chan, push + 1);
+		if (ret)
+			return ret;
+
+		dwords -= push;
+
+		BEGIN_NVC0(chan, 6, NvSub2D, 0x0860, push);
+		OUT_RINGp(chan, data, push);
+		data += push;
+	}
+
+	FIRE_RING(chan);
+	return 0;
+}
+
+int
+nvc0_fbcon_accel_init(struct fb_info *info)
+{
+	struct nouveau_fbdev *nfbdev = info->par;
+	struct drm_device *dev = nfbdev->dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_channel *chan = dev_priv->channel;
+	struct nouveau_bo *nvbo = nfbdev->nouveau_fb.nvbo;
+	int ret, format;
+
+	ret = nouveau_gpuobj_gr_new(chan, 0x902d, 0x902d);
+	if (ret)
+		return ret;
+
+	switch (info->var.bits_per_pixel) {
+	case 8:
+		format = 0xf3;
+		break;
+	case 15:
+		format = 0xf8;
+		break;
+	case 16:
+		format = 0xe8;
+		break;
+	case 32:
+		switch (info->var.transp.length) {
+		case 0: /* depth 24 */
+		case 8: /* depth 32, just use 24.. */
+			format = 0xe6;
+			break;
+		case 2: /* depth 30 */
+			format = 0xd1;
+			break;
+		default:
+			return -EINVAL;
+		}
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	ret = RING_SPACE(chan, 60);
+	if (ret) {
+		WARN_ON(1);
+		nouveau_fbcon_gpu_lockup(info);
+		return ret;
+	}
+
+	BEGIN_NVC0(chan, 2, NvSub2D, 0x0000, 1);
+	OUT_RING  (chan, 0x0000902d);
+	BEGIN_NVC0(chan, 2, NvSub2D, 0x0104, 2);
+	OUT_RING  (chan, upper_32_bits(chan->notifier_bo->bo.offset));
+	OUT_RING  (chan, lower_32_bits(chan->notifier_bo->bo.offset));
+	BEGIN_NVC0(chan, 2, NvSub2D, 0x0290, 1);
+	OUT_RING  (chan, 0);
+	BEGIN_NVC0(chan, 2, NvSub2D, 0x0888, 1);
+	OUT_RING  (chan, 1);
+	BEGIN_NVC0(chan, 2, NvSub2D, 0x02ac, 1);
+	OUT_RING  (chan, 3);
+	BEGIN_NVC0(chan, 2, NvSub2D, 0x02a0, 1);
+	OUT_RING  (chan, 0x55);
+	BEGIN_NVC0(chan, 2, NvSub2D, 0x08c0, 4);
+	OUT_RING  (chan, 0);
+	OUT_RING  (chan, 1);
+	OUT_RING  (chan, 0);
+	OUT_RING  (chan, 1);
+	BEGIN_NVC0(chan, 2, NvSub2D, 0x0580, 2);
+	OUT_RING  (chan, 4);
+	OUT_RING  (chan, format);
+	BEGIN_NVC0(chan, 2, NvSub2D, 0x02e8, 2);
+	OUT_RING  (chan, 2);
+	OUT_RING  (chan, 1);
+
+	BEGIN_NVC0(chan, 2, NvSub2D, 0x0804, 1);
+	OUT_RING  (chan, format);
+	BEGIN_NVC0(chan, 2, NvSub2D, 0x0800, 1);
+	OUT_RING  (chan, 1);
+	BEGIN_NVC0(chan, 2, NvSub2D, 0x0808, 3);
+	OUT_RING  (chan, 0);
+	OUT_RING  (chan, 0);
+	OUT_RING  (chan, 1);
+	BEGIN_NVC0(chan, 2, NvSub2D, 0x081c, 1);
+	OUT_RING  (chan, 1);
+	BEGIN_NVC0(chan, 2, NvSub2D, 0x0840, 4);
+	OUT_RING  (chan, 0);
+	OUT_RING  (chan, 1);
+	OUT_RING  (chan, 0);
+	OUT_RING  (chan, 1);
+	BEGIN_NVC0(chan, 2, NvSub2D, 0x0200, 10);
+	OUT_RING  (chan, format);
+	OUT_RING  (chan, 1);
+	OUT_RING  (chan, 0);
+	OUT_RING  (chan, 1);
+	OUT_RING  (chan, 0);
+	OUT_RING  (chan, info->fix.line_length);
+	OUT_RING  (chan, info->var.xres_virtual);
+	OUT_RING  (chan, info->var.yres_virtual);
+	OUT_RING  (chan, upper_32_bits(nvbo->vma.offset));
+	OUT_RING  (chan, lower_32_bits(nvbo->vma.offset));
+	BEGIN_NVC0(chan, 2, NvSub2D, 0x0230, 10);
+	OUT_RING  (chan, format);
+	OUT_RING  (chan, 1);
+	OUT_RING  (chan, 0);
+	OUT_RING  (chan, 1);
+	OUT_RING  (chan, 0);
+	OUT_RING  (chan, info->fix.line_length);
+	OUT_RING  (chan, info->var.xres_virtual);
+	OUT_RING  (chan, info->var.yres_virtual);
+	OUT_RING  (chan, upper_32_bits(nvbo->vma.offset));
+	OUT_RING  (chan, lower_32_bits(nvbo->vma.offset));
+	FIRE_RING (chan);
+
+	return 0;
+}
+
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nvc0_fifo.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nvc0_fifo.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nvc0_fifo.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nvc0_fifo.c	2011-03-14 21:20:32.000000000 -0400
@@ -25,6 +25,49 @@
 #include "drmP.h"
 
 #include "nouveau_drv.h"
+#include "nouveau_mm.h"
+
+static void nvc0_fifo_isr(struct drm_device *);
+
+struct nvc0_fifo_priv {
+	struct nouveau_gpuobj *playlist[2];
+	int cur_playlist;
+	struct nouveau_vma user_vma;
+	int spoon_nr;
+};
+
+struct nvc0_fifo_chan {
+	struct nouveau_bo *user;
+	struct nouveau_gpuobj *ramfc;
+};
+
+static void
+nvc0_fifo_playlist_update(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_instmem_engine *pinstmem = &dev_priv->engine.instmem;
+	struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo;
+	struct nvc0_fifo_priv *priv = pfifo->priv;
+	struct nouveau_gpuobj *cur;
+	int i, p;
+
+	cur = priv->playlist[priv->cur_playlist];
+	priv->cur_playlist = !priv->cur_playlist;
+
+	for (i = 0, p = 0; i < 128; i++) {
+		if (!(nv_rd32(dev, 0x3004 + (i * 8)) & 1))
+			continue;
+		nv_wo32(cur, p + 0, i);
+		nv_wo32(cur, p + 4, 0x00000004);
+		p += 8;
+	}
+	pinstmem->flush(dev);
+
+	nv_wr32(dev, 0x002270, cur->vinst >> 12);
+	nv_wr32(dev, 0x002274, 0x01f00000 | (p >> 3));
+	if (!nv_wait(dev, 0x00227c, 0x00100000, 0x00000000))
+		NV_ERROR(dev, "PFIFO - playlist update failed\n");
+}
 
 void
 nvc0_fifo_disable(struct drm_device *dev)
@@ -57,12 +100,135 @@ nvc0_fifo_channel_id(struct drm_device *
 int
 nvc0_fifo_create_context(struct nouveau_channel *chan)
 {
+	struct drm_device *dev = chan->dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_instmem_engine *pinstmem = &dev_priv->engine.instmem;
+	struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo;
+	struct nvc0_fifo_priv *priv = pfifo->priv;
+	struct nvc0_fifo_chan *fifoch;
+	u64 ib_virt, user_vinst;
+	int ret;
+
+	chan->fifo_priv = kzalloc(sizeof(*fifoch), GFP_KERNEL);
+	if (!chan->fifo_priv)
+		return -ENOMEM;
+	fifoch = chan->fifo_priv;
+
+	/* allocate vram for control regs, map into polling area */
+	ret = nouveau_bo_new(dev, NULL, 0x1000, 0, TTM_PL_FLAG_VRAM,
+			     0, 0, true, true, &fifoch->user);
+	if (ret)
+		goto error;
+
+	ret = nouveau_bo_pin(fifoch->user, TTM_PL_FLAG_VRAM);
+	if (ret) {
+		nouveau_bo_ref(NULL, &fifoch->user);
+		goto error;
+	}
+
+	user_vinst = fifoch->user->bo.mem.start << PAGE_SHIFT;
+
+	ret = nouveau_bo_map(fifoch->user);
+	if (ret) {
+		nouveau_bo_unpin(fifoch->user);
+		nouveau_bo_ref(NULL, &fifoch->user);
+		goto error;
+	}
+
+	nouveau_vm_map_at(&priv->user_vma, chan->id * 0x1000,
+			  fifoch->user->bo.mem.mm_node);
+
+	chan->user = ioremap_wc(pci_resource_start(dev->pdev, 1) +
+				priv->user_vma.offset + (chan->id * 0x1000),
+				PAGE_SIZE);
+	if (!chan->user) {
+		ret = -ENOMEM;
+		goto error;
+	}
+
+	ib_virt = chan->pushbuf_base + chan->dma.ib_base * 4;
+
+	/* zero channel regs */
+	nouveau_bo_wr32(fifoch->user, 0x0040/4, 0);
+	nouveau_bo_wr32(fifoch->user, 0x0044/4, 0);
+	nouveau_bo_wr32(fifoch->user, 0x0048/4, 0);
+	nouveau_bo_wr32(fifoch->user, 0x004c/4, 0);
+	nouveau_bo_wr32(fifoch->user, 0x0050/4, 0);
+	nouveau_bo_wr32(fifoch->user, 0x0058/4, 0);
+	nouveau_bo_wr32(fifoch->user, 0x005c/4, 0);
+	nouveau_bo_wr32(fifoch->user, 0x0060/4, 0);
+	nouveau_bo_wr32(fifoch->user, 0x0088/4, 0);
+	nouveau_bo_wr32(fifoch->user, 0x008c/4, 0);
+
+	/* ramfc */
+	ret = nouveau_gpuobj_new_fake(dev, chan->ramin->pinst,
+				      chan->ramin->vinst, 0x100,
+				      NVOBJ_FLAG_ZERO_ALLOC, &fifoch->ramfc);
+	if (ret)
+		goto error;
+
+	nv_wo32(fifoch->ramfc, 0x08, lower_32_bits(user_vinst));
+	nv_wo32(fifoch->ramfc, 0x0c, upper_32_bits(user_vinst));
+	nv_wo32(fifoch->ramfc, 0x10, 0x0000face);
+	nv_wo32(fifoch->ramfc, 0x30, 0xfffff902);
+	nv_wo32(fifoch->ramfc, 0x48, lower_32_bits(ib_virt));
+	nv_wo32(fifoch->ramfc, 0x4c, drm_order(chan->dma.ib_max + 1) << 16 |
+				   upper_32_bits(ib_virt));
+	nv_wo32(fifoch->ramfc, 0x54, 0x00000002);
+	nv_wo32(fifoch->ramfc, 0x84, 0x20400000);
+	nv_wo32(fifoch->ramfc, 0x94, 0x30000001);
+	nv_wo32(fifoch->ramfc, 0x9c, 0x00000100);
+	nv_wo32(fifoch->ramfc, 0xa4, 0x1f1f1f1f);
+	nv_wo32(fifoch->ramfc, 0xa8, 0x1f1f1f1f);
+	nv_wo32(fifoch->ramfc, 0xac, 0x0000001f);
+	nv_wo32(fifoch->ramfc, 0xb8, 0xf8000000);
+	nv_wo32(fifoch->ramfc, 0xf8, 0x10003080); /* 0x002310 */
+	nv_wo32(fifoch->ramfc, 0xfc, 0x10000010); /* 0x002350 */
+	pinstmem->flush(dev);
+
+	nv_wr32(dev, 0x003000 + (chan->id * 8), 0xc0000000 |
+						(chan->ramin->vinst >> 12));
+	nv_wr32(dev, 0x003004 + (chan->id * 8), 0x001f0001);
+	nvc0_fifo_playlist_update(dev);
 	return 0;
+
+error:
+	pfifo->destroy_context(chan);
+	return ret;
 }
 
 void
 nvc0_fifo_destroy_context(struct nouveau_channel *chan)
 {
+	struct drm_device *dev = chan->dev;
+	struct nvc0_fifo_chan *fifoch;
+
+	nv_mask(dev, 0x003004 + (chan->id * 8), 0x00000001, 0x00000000);
+	nv_wr32(dev, 0x002634, chan->id);
+	if (!nv_wait(dev, 0x0002634, 0xffffffff, chan->id))
+		NV_WARN(dev, "0x2634 != chid: 0x%08x\n", nv_rd32(dev, 0x2634));
+
+	nvc0_fifo_playlist_update(dev);
+
+	nv_wr32(dev, 0x003000 + (chan->id * 8), 0x00000000);
+
+	if (chan->user) {
+		iounmap(chan->user);
+		chan->user = NULL;
+	}
+
+	fifoch = chan->fifo_priv;
+	chan->fifo_priv = NULL;
+	if (!fifoch)
+		return;
+
+	nouveau_gpuobj_ref(NULL, &fifoch->ramfc);
+	if (fifoch->user) {
+		nouveau_bo_unmap(fifoch->user);
+		nouveau_bo_unpin(fifoch->user);
+		nouveau_bo_ref(NULL, &fifoch->user);
+	}
+	kfree(fifoch);
 }
 
 int
@@ -77,14 +243,213 @@ nvc0_fifo_unload_context(struct drm_devi
 	return 0;
 }
 
+static void
+nvc0_fifo_destroy(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo;
+	struct nvc0_fifo_priv *priv;
+
+	priv = pfifo->priv;
+	if (!priv)
+		return;
+
+	nouveau_vm_put(&priv->user_vma);
+	nouveau_gpuobj_ref(NULL, &priv->playlist[1]);
+	nouveau_gpuobj_ref(NULL, &priv->playlist[0]);
+	kfree(priv);
+}
+
 void
 nvc0_fifo_takedown(struct drm_device *dev)
 {
+	nv_wr32(dev, 0x002140, 0x00000000);
+	nvc0_fifo_destroy(dev);
+}
+
+static int
+nvc0_fifo_create(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo;
+	struct nvc0_fifo_priv *priv;
+	int ret;
+
+	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+	pfifo->priv = priv;
+
+	ret = nouveau_gpuobj_new(dev, NULL, 0x1000, 0x1000, 0,
+				 &priv->playlist[0]);
+	if (ret)
+		goto error;
+
+	ret = nouveau_gpuobj_new(dev, NULL, 0x1000, 0x1000, 0,
+				 &priv->playlist[1]);
+	if (ret)
+		goto error;
+
+	ret = nouveau_vm_get(dev_priv->bar1_vm, pfifo->channels * 0x1000,
+			     12, NV_MEM_ACCESS_RW, &priv->user_vma);
+	if (ret)
+		goto error;
+
+	nouveau_irq_register(dev, 8, nvc0_fifo_isr);
+	NVOBJ_CLASS(dev, 0x506e, SW); /* nvsw */
+	return 0;
+
+error:
+	nvc0_fifo_destroy(dev);
+	return ret;
 }
 
 int
 nvc0_fifo_init(struct drm_device *dev)
 {
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo;
+	struct nvc0_fifo_priv *priv;
+	int ret, i;
+
+	if (!pfifo->priv) {
+		ret = nvc0_fifo_create(dev);
+		if (ret)
+			return ret;
+	}
+	priv = pfifo->priv;
+
+	/* reset PFIFO, enable all available PSUBFIFO areas */
+	nv_mask(dev, 0x000200, 0x00000100, 0x00000000);
+	nv_mask(dev, 0x000200, 0x00000100, 0x00000100);
+	nv_wr32(dev, 0x000204, 0xffffffff);
+	nv_wr32(dev, 0x002204, 0xffffffff);
+
+	priv->spoon_nr = hweight32(nv_rd32(dev, 0x002204));
+	NV_DEBUG(dev, "PFIFO: %d subfifo(s)\n", priv->spoon_nr);
+
+	/* assign engines to subfifos */
+	if (priv->spoon_nr >= 3) {
+		nv_wr32(dev, 0x002208, ~(1 << 0)); /* PGRAPH */
+		nv_wr32(dev, 0x00220c, ~(1 << 1)); /* PVP */
+		nv_wr32(dev, 0x002210, ~(1 << 1)); /* PPP */
+		nv_wr32(dev, 0x002214, ~(1 << 1)); /* PBSP */
+		nv_wr32(dev, 0x002218, ~(1 << 2)); /* PCE0 */
+		nv_wr32(dev, 0x00221c, ~(1 << 1)); /* PCE1 */
+	}
+
+	/* PSUBFIFO[n] */
+	for (i = 0; i < 3; 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 */
+	}
+
+	nv_mask(dev, 0x002200, 0x00000001, 0x00000001);
+	nv_wr32(dev, 0x002254, 0x10000000 | priv->user_vma.offset >> 12);
+
+	nv_wr32(dev, 0x002a00, 0xffffffff); /* clears PFIFO.INTR bit 30 */
+	nv_wr32(dev, 0x002100, 0xffffffff);
+	nv_wr32(dev, 0x002140, 0xbfffffff);
 	return 0;
 }
 
+struct nouveau_enum nvc0_fifo_fault_unit[] = {
+	{ 0, "PGRAPH" },
+	{ 3, "PEEPHOLE" },
+	{ 4, "BAR1" },
+	{ 5, "BAR3" },
+	{ 7, "PFIFO" },
+	{}
+};
+
+struct nouveau_enum nvc0_fifo_fault_reason[] = {
+	{ 0, "PT_NOT_PRESENT" },
+	{ 1, "PT_TOO_SHORT" },
+	{ 2, "PAGE_NOT_PRESENT" },
+	{ 3, "VM_LIMIT_EXCEEDED" },
+	{}
+};
+
+struct nouveau_bitfield nvc0_fifo_subfifo_intr[] = {
+/*	{ 0x00008000, "" }	seen with null ib push */
+	{ 0x00200000, "ILLEGAL_MTHD" },
+	{ 0x00800000, "EMPTY_SUBC" },
+	{}
+};
+
+static void
+nvc0_fifo_isr_vm_fault(struct drm_device *dev, int unit)
+{
+	u32 inst = nv_rd32(dev, 0x2800 + (unit * 0x10));
+	u32 valo = nv_rd32(dev, 0x2804 + (unit * 0x10));
+	u32 vahi = nv_rd32(dev, 0x2808 + (unit * 0x10));
+	u32 stat = nv_rd32(dev, 0x280c + (unit * 0x10));
+
+	NV_INFO(dev, "PFIFO: %s fault at 0x%010llx [",
+		(stat & 0x00000080) ? "write" : "read", (u64)vahi << 32 | valo);
+	nouveau_enum_print(nvc0_fifo_fault_reason, stat & 0x0000000f);
+	printk("] from ");
+	nouveau_enum_print(nvc0_fifo_fault_unit, unit);
+	printk(" on channel 0x%010llx\n", (u64)inst << 12);
+}
+
+static void
+nvc0_fifo_isr_subfifo_intr(struct drm_device *dev, int unit)
+{
+	u32 stat = nv_rd32(dev, 0x040108 + (unit * 0x2000));
+	u32 addr = nv_rd32(dev, 0x0400c0 + (unit * 0x2000));
+	u32 data = nv_rd32(dev, 0x0400c4 + (unit * 0x2000));
+	u32 chid = nv_rd32(dev, 0x040120 + (unit * 0x2000)) & 0x7f;
+	u32 subc = (addr & 0x00070000);
+	u32 mthd = (addr & 0x00003ffc);
+
+	NV_INFO(dev, "PSUBFIFO %d:", unit);
+	nouveau_bitfield_print(nvc0_fifo_subfifo_intr, stat);
+	NV_INFO(dev, "PSUBFIFO %d: ch %d subc %d mthd 0x%04x data 0x%08x\n",
+		unit, chid, subc, mthd, data);
+
+	nv_wr32(dev, 0x0400c0 + (unit * 0x2000), 0x80600008);
+	nv_wr32(dev, 0x040108 + (unit * 0x2000), stat);
+}
+
+static void
+nvc0_fifo_isr(struct drm_device *dev)
+{
+	u32 stat = nv_rd32(dev, 0x002100);
+
+	if (stat & 0x10000000) {
+		u32 units = nv_rd32(dev, 0x00259c);
+		u32 u = units;
+
+		while (u) {
+			int i = ffs(u) - 1;
+			nvc0_fifo_isr_vm_fault(dev, i);
+			u &= ~(1 << i);
+		}
+
+		nv_wr32(dev, 0x00259c, units);
+		stat &= ~0x10000000;
+	}
+
+	if (stat & 0x20000000) {
+		u32 units = nv_rd32(dev, 0x0025a0);
+		u32 u = units;
+
+		while (u) {
+			int i = ffs(u) - 1;
+			nvc0_fifo_isr_subfifo_intr(dev, i);
+			u &= ~(1 << i);
+		}
+
+		nv_wr32(dev, 0x0025a0, units);
+		stat &= ~0x20000000;
+	}
+
+	if (stat) {
+		NV_INFO(dev, "PFIFO: unhandled status 0x%08x\n", stat);
+		nv_wr32(dev, 0x002100, stat);
+	}
+
+	nv_wr32(dev, 0x2140, 0);
+}
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nvc0_graph.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nvc0_graph.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nvc0_graph.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nvc0_graph.c	2013-05-03 01:53:36.000000000 -0400
@@ -22,9 +22,17 @@
  * Authors: Ben Skeggs
  */
 
+#include <linux/firmware.h>
+
 #include "drmP.h"
 
 #include "nouveau_drv.h"
+#include "nouveau_mm.h"
+#include "nvc0_graph.h"
+
+static void nvc0_graph_isr(struct drm_device *);
+static void nvc0_runk140_isr(struct drm_device *);
+static int  nvc0_graph_unload_context_to(struct drm_device *dev, u64 chan);
 
 void
 nvc0_graph_fifo_access(struct drm_device *dev, bool enabled)
@@ -37,39 +45,754 @@ nvc0_graph_channel(struct drm_device *de
 	return NULL;
 }
 
+static int
+nvc0_graph_construct_context(struct nouveau_channel *chan)
+{
+	struct drm_nouveau_private *dev_priv = chan->dev->dev_private;
+	struct nvc0_graph_priv *priv = dev_priv->engine.graph.priv;
+	struct nvc0_graph_chan *grch = chan->pgraph_ctx;
+	struct drm_device *dev = chan->dev;
+	int ret, i;
+	u32 *ctx;
+
+	ctx = kmalloc(priv->grctx_size, GFP_KERNEL);
+	if (!ctx)
+		return -ENOMEM;
+
+	nvc0_graph_load_context(chan);
+
+	nv_wo32(grch->grctx, 0x1c, 1);
+	nv_wo32(grch->grctx, 0x20, 0);
+	nv_wo32(grch->grctx, 0x28, 0);
+	nv_wo32(grch->grctx, 0x2c, 0);
+	dev_priv->engine.instmem.flush(dev);
+
+	ret = nvc0_grctx_generate(chan);
+	if (ret) {
+		kfree(ctx);
+		return ret;
+	}
+
+	ret = nvc0_graph_unload_context_to(dev, chan->ramin->vinst);
+	if (ret) {
+		kfree(ctx);
+		return ret;
+	}
+
+	for (i = 0; i < priv->grctx_size; i += 4)
+		ctx[i / 4] = nv_ro32(grch->grctx, i);
+
+	priv->grctx_vals = ctx;
+	return 0;
+}
+
+static int
+nvc0_graph_create_context_mmio_list(struct nouveau_channel *chan)
+{
+	struct drm_nouveau_private *dev_priv = chan->dev->dev_private;
+	struct nvc0_graph_priv *priv = dev_priv->engine.graph.priv;
+	struct nvc0_graph_chan *grch = chan->pgraph_ctx;
+	struct drm_device *dev = chan->dev;
+	int i = 0, gpc, tp, ret;
+	u32 magic;
+
+	ret = nouveau_gpuobj_new(dev, NULL, 0x2000, 256, NVOBJ_FLAG_VM,
+				 &grch->unk408004);
+	if (ret)
+		return ret;
+
+	ret = nouveau_gpuobj_new(dev, NULL, 0x8000, 256, NVOBJ_FLAG_VM,
+				 &grch->unk40800c);
+	if (ret)
+		return ret;
+
+	ret = nouveau_gpuobj_new(dev, NULL, 384 * 1024, 4096,
+				 NVOBJ_FLAG_VM | NVOBJ_FLAG_VM_USER,
+				 &grch->unk418810);
+	if (ret)
+		return ret;
+
+	ret = nouveau_gpuobj_new(dev, NULL, 0x1000, 0, NVOBJ_FLAG_VM,
+				 &grch->mmio);
+	if (ret)
+		return ret;
+
+
+	nv_wo32(grch->mmio, i++ * 4, 0x00408004);
+	nv_wo32(grch->mmio, i++ * 4, grch->unk408004->vinst >> 8);
+	nv_wo32(grch->mmio, i++ * 4, 0x00408008);
+	nv_wo32(grch->mmio, i++ * 4, 0x80000018);
+
+	nv_wo32(grch->mmio, i++ * 4, 0x0040800c);
+	nv_wo32(grch->mmio, i++ * 4, grch->unk40800c->vinst >> 8);
+	nv_wo32(grch->mmio, i++ * 4, 0x00408010);
+	nv_wo32(grch->mmio, i++ * 4, 0x80000000);
+
+	nv_wo32(grch->mmio, i++ * 4, 0x00418810);
+	nv_wo32(grch->mmio, i++ * 4, 0x80000000 | grch->unk418810->vinst >> 12);
+	nv_wo32(grch->mmio, i++ * 4, 0x00419848);
+	nv_wo32(grch->mmio, i++ * 4, 0x10000000 | grch->unk418810->vinst >> 12);
+
+	nv_wo32(grch->mmio, i++ * 4, 0x00419004);
+	nv_wo32(grch->mmio, i++ * 4, grch->unk40800c->vinst >> 8);
+	nv_wo32(grch->mmio, i++ * 4, 0x00419008);
+	nv_wo32(grch->mmio, i++ * 4, 0x00000000);
+
+	nv_wo32(grch->mmio, i++ * 4, 0x00418808);
+	nv_wo32(grch->mmio, i++ * 4, grch->unk408004->vinst >> 8);
+	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 += 0x02fc) {
+			u32 reg = 0x504520 + (gpc * 0x8000) + (tp * 0x0800);
+			nv_wo32(grch->mmio, i++ * 4, reg);
+			nv_wo32(grch->mmio, i++ * 4, magic);
+		}
+	}
+
+	grch->mmio_nr = i / 2;
+	return 0;
+}
+
 int
 nvc0_graph_create_context(struct nouveau_channel *chan)
 {
+	struct drm_nouveau_private *dev_priv = chan->dev->dev_private;
+	struct nouveau_instmem_engine *pinstmem = &dev_priv->engine.instmem;
+	struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
+	struct nvc0_graph_priv *priv = pgraph->priv;
+	struct nvc0_graph_chan *grch;
+	struct drm_device *dev = chan->dev;
+	struct nouveau_gpuobj *grctx;
+	int ret, i;
+
+	chan->pgraph_ctx = kzalloc(sizeof(*grch), GFP_KERNEL);
+	if (!chan->pgraph_ctx)
+		return -ENOMEM;
+	grch = chan->pgraph_ctx;
+
+	ret = nouveau_gpuobj_new(dev, NULL, priv->grctx_size, 256,
+				 NVOBJ_FLAG_VM | NVOBJ_FLAG_ZERO_ALLOC,
+				 &grch->grctx);
+	if (ret)
+		goto error;
+	chan->ramin_grctx = grch->grctx;
+	grctx = grch->grctx;
+
+	ret = nvc0_graph_create_context_mmio_list(chan);
+	if (ret)
+		goto error;
+
+	nv_wo32(chan->ramin, 0x0210, lower_32_bits(grctx->vinst) | 4);
+	nv_wo32(chan->ramin, 0x0214, upper_32_bits(grctx->vinst));
+	pinstmem->flush(dev);
+
+	if (!priv->grctx_vals) {
+		ret = nvc0_graph_construct_context(chan);
+		if (ret)
+			goto error;
+	}
+
+	for (i = 0; i < priv->grctx_size; i += 4)
+		nv_wo32(grctx, i, priv->grctx_vals[i / 4]);
+
+        nv_wo32(grctx, 0xf4, 0);
+        nv_wo32(grctx, 0xf8, 0);
+        nv_wo32(grctx, 0x10, grch->mmio_nr);
+        nv_wo32(grctx, 0x14, lower_32_bits(grch->mmio->vinst));
+        nv_wo32(grctx, 0x18, upper_32_bits(grch->mmio->vinst));
+        nv_wo32(grctx, 0x1c, 1);
+        nv_wo32(grctx, 0x20, 0);
+        nv_wo32(grctx, 0x28, 0);
+        nv_wo32(grctx, 0x2c, 0);
+	pinstmem->flush(dev);
 	return 0;
+
+error:
+	pgraph->destroy_context(chan);
+	return ret;
 }
 
 void
 nvc0_graph_destroy_context(struct nouveau_channel *chan)
 {
+	struct nvc0_graph_chan *grch;
+
+	grch = chan->pgraph_ctx;
+	chan->pgraph_ctx = NULL;
+	if (!grch)
+		return;
+
+	nouveau_gpuobj_ref(NULL, &grch->mmio);
+	nouveau_gpuobj_ref(NULL, &grch->unk418810);
+	nouveau_gpuobj_ref(NULL, &grch->unk40800c);
+	nouveau_gpuobj_ref(NULL, &grch->unk408004);
+	nouveau_gpuobj_ref(NULL, &grch->grctx);
+	chan->ramin_grctx = NULL;
 }
 
 int
 nvc0_graph_load_context(struct nouveau_channel *chan)
 {
+	struct drm_device *dev = chan->dev;
+
+	nv_wr32(dev, 0x409840, 0x00000030);
+	nv_wr32(dev, 0x409500, 0x80000000 | chan->ramin->vinst >> 12);
+	nv_wr32(dev, 0x409504, 0x00000003);
+	if (!nv_wait(dev, 0x409800, 0x00000010, 0x00000010))
+		NV_ERROR(dev, "PGRAPH: load_ctx timeout\n");
+
+	return 0;
+}
+
+static int
+nvc0_graph_unload_context_to(struct drm_device *dev, u64 chan)
+{
+	nv_wr32(dev, 0x409840, 0x00000003);
+	nv_wr32(dev, 0x409500, 0x80000000 | chan >> 12);
+	nv_wr32(dev, 0x409504, 0x00000009);
+	if (!nv_wait(dev, 0x409800, 0x00000001, 0x00000000)) {
+		NV_ERROR(dev, "PGRAPH: unload_ctx timeout\n");
+		return -EBUSY;
+	}
+
 	return 0;
 }
 
 int
 nvc0_graph_unload_context(struct drm_device *dev)
 {
-	return 0;
+	u64 inst = (u64)(nv_rd32(dev, 0x409b00) & 0x0fffffff) << 12;
+	return nvc0_graph_unload_context_to(dev, inst);
+}
+
+static void
+nvc0_graph_destroy(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
+	struct nvc0_graph_priv *priv;
+
+	priv = pgraph->priv;
+	if (!priv)
+		return;
+
+	nouveau_irq_unregister(dev, 12);
+	nouveau_irq_unregister(dev, 25);
+
+	nouveau_gpuobj_ref(NULL, &priv->unk4188b8);
+	nouveau_gpuobj_ref(NULL, &priv->unk4188b4);
+
+	if (priv->grctx_vals)
+		kfree(priv->grctx_vals);
+	kfree(priv);
 }
 
 void
 nvc0_graph_takedown(struct drm_device *dev)
 {
+	nvc0_graph_destroy(dev);
+}
+
+static int
+nvc0_graph_create(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
+	struct nvc0_graph_priv *priv;
+	int ret, gpc, i;
+
+	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+	pgraph->priv = priv;
+
+	ret = nouveau_gpuobj_new(dev, NULL, 0x1000, 256, 0, &priv->unk4188b4);
+	if (ret)
+		goto error;
+
+	ret = nouveau_gpuobj_new(dev, NULL, 0x1000, 256, 0, &priv->unk4188b8);
+	if (ret)
+		goto error;
+
+	for (i = 0; i < 0x1000; i += 4) {
+		nv_wo32(priv->unk4188b4, i, 0x00000010);
+		nv_wo32(priv->unk4188b8, i, 0x00000010);
+	}
+
+	priv->gpc_nr  =  nv_rd32(dev, 0x409604) & 0x0000001f;
+	priv->rop_nr = (nv_rd32(dev, 0x409604) & 0x001f0000) >> 16;
+	for (gpc = 0; gpc < priv->gpc_nr; gpc++) {
+		priv->tp_nr[gpc] = nv_rd32(dev, GPC_UNIT(gpc, 0x2608));
+		priv->tp_total += priv->tp_nr[gpc];
+	}
+
+	/*XXX: these need figuring out... */
+	switch (dev_priv->chipset) {
+	case 0xc0:
+		if (priv->tp_total == 11) { /* 465, 3/4/4/0, 4 */
+			priv->magic_not_rop_nr = 0x07;
+			/* filled values up to tp_total, the rest 0 */
+			priv->magicgpc980[0]   = 0x22111000;
+			priv->magicgpc980[1]   = 0x00000233;
+			priv->magicgpc980[2]   = 0x00000000;
+			priv->magicgpc980[3]   = 0x00000000;
+			priv->magicgpc918      = 0x000ba2e9;
+		} else
+		if (priv->tp_total == 14) { /* 470, 3/3/4/4, 5 */
+			priv->magic_not_rop_nr = 0x05;
+			priv->magicgpc980[0]   = 0x11110000;
+			priv->magicgpc980[1]   = 0x00233222;
+			priv->magicgpc980[2]   = 0x00000000;
+			priv->magicgpc980[3]   = 0x00000000;
+			priv->magicgpc918      = 0x00092493;
+		} else
+		if (priv->tp_total == 15) { /* 480, 3/4/4/4, 6 */
+			priv->magic_not_rop_nr = 0x06;
+			priv->magicgpc980[0]   = 0x11110000;
+			priv->magicgpc980[1]   = 0x03332222;
+			priv->magicgpc980[2]   = 0x00000000;
+			priv->magicgpc980[3]   = 0x00000000;
+			priv->magicgpc918      = 0x00088889;
+		}
+		break;
+	case 0xc3: /* 450, 4/0/0/0, 2 */
+		priv->magic_not_rop_nr = 0x03;
+		priv->magicgpc980[0]   = 0x00003210;
+		priv->magicgpc980[1]   = 0x00000000;
+		priv->magicgpc980[2]   = 0x00000000;
+		priv->magicgpc980[3]   = 0x00000000;
+		priv->magicgpc918      = 0x00200000;
+		break;
+	case 0xc4: /* 460, 3/4/0/0, 4 */
+		priv->magic_not_rop_nr = 0x01;
+		priv->magicgpc980[0]   = 0x02321100;
+		priv->magicgpc980[1]   = 0x00000000;
+		priv->magicgpc980[2]   = 0x00000000;
+		priv->magicgpc980[3]   = 0x00000000;
+		priv->magicgpc918      = 0x00124925;
+		break;
+	}
+
+	if (!priv->magic_not_rop_nr) {
+		NV_ERROR(dev, "PGRAPH: unknown config: %d/%d/%d/%d, %d\n",
+			 priv->tp_nr[0], priv->tp_nr[1], priv->tp_nr[2],
+			 priv->tp_nr[3], priv->rop_nr);
+		/* use 0xc3's values... */
+		priv->magic_not_rop_nr = 0x03;
+		priv->magicgpc980[0]   = 0x00003210;
+		priv->magicgpc980[1]   = 0x00000000;
+		priv->magicgpc980[2]   = 0x00000000;
+		priv->magicgpc980[3]   = 0x00000000;
+		priv->magicgpc918      = 0x00200000;
+	}
+
+	nouveau_irq_register(dev, 12, nvc0_graph_isr);
+	nouveau_irq_register(dev, 25, nvc0_runk140_isr);
+	NVOBJ_CLASS(dev, 0x902d, GR); /* 2D */
+	NVOBJ_CLASS(dev, 0x9039, GR); /* M2MF */
+	NVOBJ_CLASS(dev, 0x9097, GR); /* 3D */
+	NVOBJ_CLASS(dev, 0x90c0, GR); /* COMPUTE */
+	return 0;
+
+error:
+	nvc0_graph_destroy(dev);
+	return ret;
+}
+
+static void
+nvc0_graph_init_obj418880(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
+	struct nvc0_graph_priv *priv = pgraph->priv;
+	int i;
+
+	nv_wr32(dev, GPC_BCAST(0x0880), 0x00000000);
+	nv_wr32(dev, GPC_BCAST(0x08a4), 0x00000000);
+	for (i = 0; i < 4; i++)
+		nv_wr32(dev, GPC_BCAST(0x0888) + (i * 4), 0x00000000);
+	nv_wr32(dev, GPC_BCAST(0x08b4), priv->unk4188b4->vinst >> 8);
+	nv_wr32(dev, GPC_BCAST(0x08b8), priv->unk4188b8->vinst >> 8);
+}
+
+static void
+nvc0_graph_init_regs(struct drm_device *dev)
+{
+	nv_wr32(dev, 0x400080, 0x003083c2);
+	nv_wr32(dev, 0x400088, 0x00006fe7);
+	nv_wr32(dev, 0x40008c, 0x00000000);
+	nv_wr32(dev, 0x400090, 0x00000030);
+	nv_wr32(dev, 0x40013c, 0x013901f7);
+	nv_wr32(dev, 0x400140, 0x00000100);
+	nv_wr32(dev, 0x400144, 0x00000000);
+	nv_wr32(dev, 0x400148, 0x00000110);
+	nv_wr32(dev, 0x400138, 0x00000000);
+	nv_wr32(dev, 0x400130, 0x00000000);
+	nv_wr32(dev, 0x400134, 0x00000000);
+	nv_wr32(dev, 0x400124, 0x00000002);
+}
+
+static void
+nvc0_graph_init_gpc_0(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nvc0_graph_priv *priv = dev_priv->engine.graph.priv;
+	int gpc;
+	
+	//      TP      ROP UNKVAL(magic_not_rop_nr)
+	// 450: 4/0/0/0 2        3
+	// 460: 3/4/0/0 4        1
+	// 465: 3/4/4/0 4        7
+	// 470: 3/3/4/4 5        5
+	// 480: 3/4/4/4 6        6
+
+	// magicgpc918
+	// 450: 00200000 00000000001000000000000000000000
+	// 460: 00124925 00000000000100100100100100100101
+	// 465: 000ba2e9 00000000000010111010001011101001
+	// 470: 00092493 00000000000010010010010010010011
+	// 480: 00088889 00000000000010001000100010001001
+
+	/* filled values up to tp_total, remainder 0 */
+	// 450: 00003210 00000000 00000000 00000000
+	// 460: 02321100 00000000 00000000 00000000
+	// 465: 22111000 00000233 00000000 00000000
+	// 470: 11110000 00233222 00000000 00000000
+	// 480: 11110000 03332222 00000000 00000000
+	
+	nv_wr32(dev, GPC_BCAST(0x0980), priv->magicgpc980[0]);
+	nv_wr32(dev, GPC_BCAST(0x0984), priv->magicgpc980[1]);
+	nv_wr32(dev, GPC_BCAST(0x0988), priv->magicgpc980[2]);
+	nv_wr32(dev, GPC_BCAST(0x098c), priv->magicgpc980[3]);
+
+	for (gpc = 0; gpc < priv->gpc_nr; gpc++) {
+		nv_wr32(dev, GPC_UNIT(gpc, 0x0914), priv->magic_not_rop_nr << 8 |
+						  priv->tp_nr[gpc]);
+		nv_wr32(dev, GPC_UNIT(gpc, 0x0910), 0x00040000 | priv->tp_total);
+		nv_wr32(dev, GPC_UNIT(gpc, 0x0918), priv->magicgpc918);
+	}
+
+	nv_wr32(dev, GPC_BCAST(0x1bd4), priv->magicgpc918);
+	nv_wr32(dev, GPC_BCAST(0x08ac), priv->rop_nr);
+}
+
+static void
+nvc0_graph_init_units(struct drm_device *dev)
+{
+	nv_wr32(dev, 0x409c24, 0x000f0000);
+	nv_wr32(dev, 0x404000, 0xc0000000); /* DISPATCH */
+	nv_wr32(dev, 0x404600, 0xc0000000); /* M2MF */
+	nv_wr32(dev, 0x408030, 0xc0000000);
+	nv_wr32(dev, 0x40601c, 0xc0000000);
+	nv_wr32(dev, 0x404490, 0xc0000000); /* MACRO */
+	nv_wr32(dev, 0x406018, 0xc0000000);
+	nv_wr32(dev, 0x405840, 0xc0000000);
+	nv_wr32(dev, 0x405844, 0x00ffffff);
+	nv_mask(dev, 0x419cc0, 0x00000008, 0x00000008);
+	nv_mask(dev, 0x419eb4, 0x00001000, 0x00001000);
+}
+
+static void
+nvc0_graph_init_gpc_1(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nvc0_graph_priv *priv = dev_priv->engine.graph.priv;
+	int gpc, tp;
+
+	for (gpc = 0; gpc < priv->gpc_nr; gpc++) {
+		nv_wr32(dev, GPC_UNIT(gpc, 0x0420), 0xc0000000);
+		nv_wr32(dev, GPC_UNIT(gpc, 0x0900), 0xc0000000);
+		nv_wr32(dev, GPC_UNIT(gpc, 0x1028), 0xc0000000);
+		nv_wr32(dev, GPC_UNIT(gpc, 0x0824), 0xc0000000);
+		for (tp = 0; tp < priv->tp_nr[gpc]; tp++) {
+			nv_wr32(dev, TP_UNIT(gpc, tp, 0x508), 0xffffffff);
+			nv_wr32(dev, TP_UNIT(gpc, tp, 0x50c), 0xffffffff);
+			nv_wr32(dev, TP_UNIT(gpc, tp, 0x224), 0xc0000000);
+			nv_wr32(dev, TP_UNIT(gpc, tp, 0x48c), 0xc0000000);
+			nv_wr32(dev, TP_UNIT(gpc, tp, 0x084), 0xc0000000);
+			nv_wr32(dev, TP_UNIT(gpc, tp, 0x644), 0x001ffffe);
+			nv_wr32(dev, TP_UNIT(gpc, tp, 0x64c), 0x0000000f);
+		}
+		nv_wr32(dev, GPC_UNIT(gpc, 0x2c90), 0xffffffff);
+		nv_wr32(dev, GPC_UNIT(gpc, 0x2c94), 0xffffffff);
+	}
+}
+
+static void
+nvc0_graph_init_rop(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nvc0_graph_priv *priv = dev_priv->engine.graph.priv;
+	int rop;
+
+	for (rop = 0; rop < priv->rop_nr; rop++) {
+		nv_wr32(dev, ROP_UNIT(rop, 0x144), 0xc0000000);
+		nv_wr32(dev, ROP_UNIT(rop, 0x070), 0xc0000000);
+		nv_wr32(dev, ROP_UNIT(rop, 0x204), 0xffffffff);
+		nv_wr32(dev, ROP_UNIT(rop, 0x208), 0xffffffff);
+	}
+}
+
+static int
+nvc0_fuc_load_fw(struct drm_device *dev, u32 fuc_base,
+		 const char *code_fw, const char *data_fw)
+{
+	const struct firmware *fw;
+	char name[32];
+	int ret, i;
+
+	snprintf(name, sizeof(name), "/*(DEBLOBBED)*/", data_fw);
+	ret = reject_firmware(&fw, name, &dev->pdev->dev);
+	if (ret) {
+		NV_ERROR(dev, "failed to load %s\n", data_fw);
+		return ret;
+	}
+
+	nv_wr32(dev, fuc_base + 0x01c0, 0x01000000);
+	for (i = 0; i < fw->size / 4; i++)
+		nv_wr32(dev, fuc_base + 0x01c4, ((u32 *)fw->data)[i]);
+	release_firmware(fw);
+
+	snprintf(name, sizeof(name), "/*(DEBLOBBED)*/", code_fw);
+	ret = reject_firmware(&fw, name, &dev->pdev->dev);
+	if (ret) {
+		NV_ERROR(dev, "failed to load %s\n", code_fw);
+		return ret;
+	}
+
+	nv_wr32(dev, fuc_base + 0x0180, 0x01000000);
+	for (i = 0; i < fw->size / 4; i++) {
+		if ((i & 0x3f) == 0)
+			nv_wr32(dev, fuc_base + 0x0188, i >> 6);
+		nv_wr32(dev, fuc_base + 0x0184, ((u32 *)fw->data)[i]);
+	}
+	release_firmware(fw);
+
+	return 0;
+}
+
+static int
+nvc0_graph_init_ctxctl(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nvc0_graph_priv *priv = dev_priv->engine.graph.priv;
+	u32 r000260;
+	int ret;
+
+	/* load fuc microcode */
+	r000260 = nv_mask(dev, 0x000260, 0x00000001, 0x00000000);
+	ret = nvc0_fuc_load_fw(dev, 0x409000, "/*(DEBLOBBED)*/", "/*(DEBLOBBED)*/");
+	if (ret == 0)
+		ret = nvc0_fuc_load_fw(dev, 0x41a000, "/*(DEBLOBBED)*/", "/*(DEBLOBBED)*/");
+	nv_wr32(dev, 0x000260, r000260);
+
+	if (ret)
+		return ret;
+
+	/* start both of them running */
+	nv_wr32(dev, 0x409840, 0xffffffff);
+	nv_wr32(dev, 0x41a10c, 0x00000000);
+	nv_wr32(dev, 0x40910c, 0x00000000);
+	nv_wr32(dev, 0x41a100, 0x00000002);
+	nv_wr32(dev, 0x409100, 0x00000002);
+	if (!nv_wait(dev, 0x409800, 0x00000001, 0x00000001))
+		NV_INFO(dev, "0x409800 wait failed\n");
+
+	nv_wr32(dev, 0x409840, 0xffffffff);
+	nv_wr32(dev, 0x409500, 0x7fffffff);
+	nv_wr32(dev, 0x409504, 0x00000021);
+
+	nv_wr32(dev, 0x409840, 0xffffffff);
+	nv_wr32(dev, 0x409500, 0x00000000);
+	nv_wr32(dev, 0x409504, 0x00000010);
+	if (!nv_wait_ne(dev, 0x409800, 0xffffffff, 0x00000000)) {
+		NV_ERROR(dev, "fuc09 req 0x10 timeout\n");
+		return -EBUSY;
+	}
+	priv->grctx_size = nv_rd32(dev, 0x409800);
+
+	nv_wr32(dev, 0x409840, 0xffffffff);
+	nv_wr32(dev, 0x409500, 0x00000000);
+	nv_wr32(dev, 0x409504, 0x00000016);
+	if (!nv_wait_ne(dev, 0x409800, 0xffffffff, 0x00000000)) {
+		NV_ERROR(dev, "fuc09 req 0x16 timeout\n");
+		return -EBUSY;
+	}
+
+	nv_wr32(dev, 0x409840, 0xffffffff);
+	nv_wr32(dev, 0x409500, 0x00000000);
+	nv_wr32(dev, 0x409504, 0x00000025);
+	if (!nv_wait_ne(dev, 0x409800, 0xffffffff, 0x00000000)) {
+		NV_ERROR(dev, "fuc09 req 0x25 timeout\n");
+		return -EBUSY;
+	}
+
+	return 0;
 }
 
 int
 nvc0_graph_init(struct drm_device *dev)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
+	struct nvc0_graph_priv *priv;
+	int ret;
+
 	dev_priv->engine.graph.accel_blocked = true;
+
+	switch (dev_priv->chipset) {
+	case 0xc0:
+	case 0xc3:
+	case 0xc4:
+		break;
+	default:
+		NV_ERROR(dev, "PGRAPH: unsupported chipset, please report!\n");
+		if (nouveau_noaccel != 0)
+			return 0;
+		break;
+	}
+
+	nv_mask(dev, 0x000200, 0x18001000, 0x00000000);
+	nv_mask(dev, 0x000200, 0x18001000, 0x18001000);
+
+	if (!pgraph->priv) {
+		ret = nvc0_graph_create(dev);
+		if (ret)
+			return ret;
+	}
+	priv = pgraph->priv;
+
+	nvc0_graph_init_obj418880(dev);
+	nvc0_graph_init_regs(dev);
+	//nvc0_graph_init_unitplemented_magics(dev);
+	nvc0_graph_init_gpc_0(dev);
+	//nvc0_graph_init_unitplemented_c242(dev);
+
+	nv_wr32(dev, 0x400500, 0x00010001);
+	nv_wr32(dev, 0x400100, 0xffffffff);
+	nv_wr32(dev, 0x40013c, 0xffffffff);
+
+	nvc0_graph_init_units(dev);
+	nvc0_graph_init_gpc_1(dev);
+	nvc0_graph_init_rop(dev);
+
+	nv_wr32(dev, 0x400108, 0xffffffff);
+	nv_wr32(dev, 0x400138, 0xffffffff);
+	nv_wr32(dev, 0x400118, 0xffffffff);
+	nv_wr32(dev, 0x400130, 0xffffffff);
+	nv_wr32(dev, 0x40011c, 0xffffffff);
+	nv_wr32(dev, 0x400134, 0xffffffff);
+	nv_wr32(dev, 0x400054, 0x34ce3464);
+
+	ret = nvc0_graph_init_ctxctl(dev);
+	if (ret == 0)
+		dev_priv->engine.graph.accel_blocked = false;
 	return 0;
 }
 
+static int
+nvc0_graph_isr_chid(struct drm_device *dev, u64 inst)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_channel *chan;
+	unsigned long flags;
+	int i;
+
+	spin_lock_irqsave(&dev_priv->channels.lock, flags);
+	for (i = 0; i < dev_priv->engine.fifo.channels; i++) {
+		chan = dev_priv->channels.ptr[i];
+		if (!chan || !chan->ramin)
+			continue;
+
+		if (inst == chan->ramin->vinst)
+			break;
+	}
+	spin_unlock_irqrestore(&dev_priv->channels.lock, flags);
+	return i;
+}
+
+static void
+nvc0_graph_isr(struct drm_device *dev)
+{
+	u64 inst = (u64)(nv_rd32(dev, 0x409b00) & 0x0fffffff) << 12;
+	u32 chid = nvc0_graph_isr_chid(dev, inst);
+	u32 stat = nv_rd32(dev, 0x400100);
+	u32 addr = nv_rd32(dev, 0x400704);
+	u32 mthd = (addr & 0x00003ffc);
+	u32 subc = (addr & 0x00070000) >> 16;
+	u32 data = nv_rd32(dev, 0x400708);
+	u32 code = nv_rd32(dev, 0x400110);
+	u32 class = nv_rd32(dev, 0x404200 + (subc * 4));
+
+	if (stat & 0x00000010) {
+		NV_INFO(dev, "PGRAPH: ILLEGAL_MTHD ch %d [0x%010llx] subc %d "
+			     "class 0x%04x mthd 0x%04x data 0x%08x\n",
+			chid, inst, subc, class, mthd, data);
+		nv_wr32(dev, 0x400100, 0x00000010);
+		stat &= ~0x00000010;
+	}
+
+	if (stat & 0x00000020) {
+		NV_INFO(dev, "PGRAPH: ILLEGAL_CLASS ch %d [0x%010llx] subc %d "
+			     "class 0x%04x mthd 0x%04x data 0x%08x\n",
+			chid, inst, subc, class, mthd, data);
+		nv_wr32(dev, 0x400100, 0x00000020);
+		stat &= ~0x00000020;
+	}
+
+	if (stat & 0x00100000) {
+		NV_INFO(dev, "PGRAPH: DATA_ERROR [");
+		nouveau_enum_print(nv50_data_error_names, code);
+		printk("] ch %d [0x%010llx] subc %d class 0x%04x "
+		       "mthd 0x%04x data 0x%08x\n",
+		       chid, inst, subc, class, mthd, data);
+		nv_wr32(dev, 0x400100, 0x00100000);
+		stat &= ~0x00100000;
+	}
+
+	if (stat & 0x00200000) {
+		u32 trap = nv_rd32(dev, 0x400108);
+		NV_INFO(dev, "PGRAPH: TRAP ch %d status 0x%08x\n", chid, trap);
+		nv_wr32(dev, 0x400108, trap);
+		nv_wr32(dev, 0x400100, 0x00200000);
+		stat &= ~0x00200000;
+	}
+
+	if (stat & 0x00080000) {
+		u32 ustat = nv_rd32(dev, 0x409c18);
+
+		NV_INFO(dev, "PGRAPH: CTXCTRL ustat 0x%08x\n", ustat);
+
+		nv_wr32(dev, 0x409c20, ustat);
+		nv_wr32(dev, 0x400100, 0x00080000);
+		stat &= ~0x00080000;
+	}
+
+	if (stat) {
+		NV_INFO(dev, "PGRAPH: unknown stat 0x%08x\n", stat);
+		nv_wr32(dev, 0x400100, stat);
+	}
+
+	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_INFO(dev, "PRUNK140: %d 0x%08x 0x%08x\n", unit, st0, st1);
+		units &= ~(1 << unit);
+	}
+}
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nvc0_graph.h linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nvc0_graph.h
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nvc0_graph.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nvc0_graph.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2010 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
+ */
+
+#ifndef __NVC0_GRAPH_H__
+#define __NVC0_GRAPH_H__
+
+#define GPC_MAX 4
+#define TP_MAX 32
+
+#define ROP_BCAST(r)   (0x408800 + (r))
+#define ROP_UNIT(u,r)  (0x410000 + (u) * 0x400 + (r))
+#define GPC_BCAST(r)   (0x418000 + (r))
+#define GPC_UNIT(t,r)  (0x500000 + (t) * 0x8000 + (r))
+#define TP_UNIT(t,m,r) (0x504000 + (t) * 0x8000 + (m) * 0x800 + (r))
+
+struct nvc0_graph_priv {
+	u8 gpc_nr;
+	u8 rop_nr;
+	u8 tp_nr[GPC_MAX];
+	u8 tp_total;
+
+	u32  grctx_size;
+	u32 *grctx_vals;
+	struct nouveau_gpuobj *unk4188b4;
+	struct nouveau_gpuobj *unk4188b8;
+
+	u8  magic_not_rop_nr;
+	u32 magicgpc980[4];
+	u32 magicgpc918;
+};
+
+struct nvc0_graph_chan {
+	struct nouveau_gpuobj *grctx;
+	struct nouveau_gpuobj *unk408004; // 0x418810 too
+	struct nouveau_gpuobj *unk40800c; // 0x419004 too
+	struct nouveau_gpuobj *unk418810; // 0x419848 too
+	struct nouveau_gpuobj *mmio;
+	int mmio_nr;
+};
+
+int nvc0_grctx_generate(struct nouveau_channel *);
+
+#endif
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nvc0_grctx.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nvc0_grctx.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nvc0_grctx.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nvc0_grctx.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,2874 @@
+/*
+ * Copyright 2010 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_mm.h"
+#include "nvc0_graph.h"
+
+static void
+nv_icmd(struct drm_device *dev, u32 icmd, u32 data)
+{
+	nv_wr32(dev, 0x400204, data);
+	nv_wr32(dev, 0x400200, icmd);
+	while (nv_rd32(dev, 0x400700) & 2) {}
+}
+
+static void
+nv_mthd(struct drm_device *dev, u32 class, u32 mthd, u32 data)
+{
+	nv_wr32(dev, 0x40448c, data);
+	nv_wr32(dev, 0x404488, 0x80000000 | (mthd << 14) | class);
+}
+
+static void
+nvc0_grctx_generate_9097(struct drm_device *dev)
+{
+	nv_mthd(dev, 0x9097, 0x0800, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0840, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0880, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x08c0, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0900, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0940, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0980, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x09c0, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0804, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0844, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0884, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x08c4, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0904, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0944, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0984, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x09c4, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0808, 0x00000400);
+	nv_mthd(dev, 0x9097, 0x0848, 0x00000400);
+	nv_mthd(dev, 0x9097, 0x0888, 0x00000400);
+	nv_mthd(dev, 0x9097, 0x08c8, 0x00000400);
+	nv_mthd(dev, 0x9097, 0x0908, 0x00000400);
+	nv_mthd(dev, 0x9097, 0x0948, 0x00000400);
+	nv_mthd(dev, 0x9097, 0x0988, 0x00000400);
+	nv_mthd(dev, 0x9097, 0x09c8, 0x00000400);
+	nv_mthd(dev, 0x9097, 0x080c, 0x00000300);
+	nv_mthd(dev, 0x9097, 0x084c, 0x00000300);
+	nv_mthd(dev, 0x9097, 0x088c, 0x00000300);
+	nv_mthd(dev, 0x9097, 0x08cc, 0x00000300);
+	nv_mthd(dev, 0x9097, 0x090c, 0x00000300);
+	nv_mthd(dev, 0x9097, 0x094c, 0x00000300);
+	nv_mthd(dev, 0x9097, 0x098c, 0x00000300);
+	nv_mthd(dev, 0x9097, 0x09cc, 0x00000300);
+	nv_mthd(dev, 0x9097, 0x0810, 0x000000cf);
+	nv_mthd(dev, 0x9097, 0x0850, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0890, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x08d0, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0910, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0950, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0990, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x09d0, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0814, 0x00000040);
+	nv_mthd(dev, 0x9097, 0x0854, 0x00000040);
+	nv_mthd(dev, 0x9097, 0x0894, 0x00000040);
+	nv_mthd(dev, 0x9097, 0x08d4, 0x00000040);
+	nv_mthd(dev, 0x9097, 0x0914, 0x00000040);
+	nv_mthd(dev, 0x9097, 0x0954, 0x00000040);
+	nv_mthd(dev, 0x9097, 0x0994, 0x00000040);
+	nv_mthd(dev, 0x9097, 0x09d4, 0x00000040);
+	nv_mthd(dev, 0x9097, 0x0818, 0x00000001);
+	nv_mthd(dev, 0x9097, 0x0858, 0x00000001);
+	nv_mthd(dev, 0x9097, 0x0898, 0x00000001);
+	nv_mthd(dev, 0x9097, 0x08d8, 0x00000001);
+	nv_mthd(dev, 0x9097, 0x0918, 0x00000001);
+	nv_mthd(dev, 0x9097, 0x0958, 0x00000001);
+	nv_mthd(dev, 0x9097, 0x0998, 0x00000001);
+	nv_mthd(dev, 0x9097, 0x09d8, 0x00000001);
+	nv_mthd(dev, 0x9097, 0x081c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x085c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x089c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x08dc, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x091c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x095c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x099c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x09dc, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0820, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0860, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x08a0, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x08e0, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0920, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0960, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x09a0, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x09e0, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x2700, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x2720, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x2740, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x2760, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x2780, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x27a0, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x27c0, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x27e0, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x2704, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x2724, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x2744, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x2764, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x2784, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x27a4, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x27c4, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x27e4, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x2708, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x2728, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x2748, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x2768, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x2788, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x27a8, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x27c8, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x27e8, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x270c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x272c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x274c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x276c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x278c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x27ac, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x27cc, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x27ec, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x2710, 0x00014000);
+	nv_mthd(dev, 0x9097, 0x2730, 0x00014000);
+	nv_mthd(dev, 0x9097, 0x2750, 0x00014000);
+	nv_mthd(dev, 0x9097, 0x2770, 0x00014000);
+	nv_mthd(dev, 0x9097, 0x2790, 0x00014000);
+	nv_mthd(dev, 0x9097, 0x27b0, 0x00014000);
+	nv_mthd(dev, 0x9097, 0x27d0, 0x00014000);
+	nv_mthd(dev, 0x9097, 0x27f0, 0x00014000);
+	nv_mthd(dev, 0x9097, 0x2714, 0x00000040);
+	nv_mthd(dev, 0x9097, 0x2734, 0x00000040);
+	nv_mthd(dev, 0x9097, 0x2754, 0x00000040);
+	nv_mthd(dev, 0x9097, 0x2774, 0x00000040);
+	nv_mthd(dev, 0x9097, 0x2794, 0x00000040);
+	nv_mthd(dev, 0x9097, 0x27b4, 0x00000040);
+	nv_mthd(dev, 0x9097, 0x27d4, 0x00000040);
+	nv_mthd(dev, 0x9097, 0x27f4, 0x00000040);
+	nv_mthd(dev, 0x9097, 0x1c00, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1c10, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1c20, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1c30, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1c40, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1c50, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1c60, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1c70, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1c80, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1c90, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1ca0, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1cb0, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1cc0, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1cd0, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1ce0, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1cf0, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1c04, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1c14, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1c24, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1c34, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1c44, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1c54, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1c64, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1c74, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1c84, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1c94, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1ca4, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1cb4, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1cc4, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1cd4, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1ce4, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1cf4, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1c08, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1c18, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1c28, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1c38, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1c48, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1c58, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1c68, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1c78, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1c88, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1c98, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1ca8, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1cb8, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1cc8, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1cd8, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1ce8, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1cf8, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1c0c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1c1c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1c2c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1c3c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1c4c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1c5c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1c6c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1c7c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1c8c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1c9c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1cac, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1cbc, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1ccc, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1cdc, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1cec, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1cfc, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1d00, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1d10, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1d20, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1d30, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1d40, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1d50, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1d60, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1d70, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1d80, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1d90, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1da0, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1db0, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1dc0, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1dd0, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1de0, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1df0, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1d04, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1d14, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1d24, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1d34, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1d44, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1d54, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1d64, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1d74, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1d84, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1d94, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1da4, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1db4, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1dc4, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1dd4, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1de4, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1df4, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1d08, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1d18, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1d28, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1d38, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1d48, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1d58, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1d68, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1d78, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1d88, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1d98, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1da8, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1db8, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1dc8, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1dd8, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1de8, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1df8, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1d0c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1d1c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1d2c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1d3c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1d4c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1d5c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1d6c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1d7c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1d8c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1d9c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1dac, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1dbc, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1dcc, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1ddc, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1dec, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1dfc, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1f00, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1f08, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1f10, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1f18, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1f20, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1f28, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1f30, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1f38, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1f40, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1f48, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1f50, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1f58, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1f60, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1f68, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1f70, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1f78, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1f04, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1f0c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1f14, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1f1c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1f24, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1f2c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1f34, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1f3c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1f44, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1f4c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1f54, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1f5c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1f64, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1f6c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1f74, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1f7c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1f80, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1f88, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1f90, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1f98, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1fa0, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1fa8, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1fb0, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1fb8, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1fc0, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1fc8, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1fd0, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1fd8, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1fe0, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1fe8, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1ff0, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1ff8, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1f84, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1f8c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1f94, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1f9c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1fa4, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1fac, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1fb4, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1fbc, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1fc4, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1fcc, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1fd4, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1fdc, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1fe4, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1fec, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1ff4, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1ffc, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x2200, 0x00000022);
+	nv_mthd(dev, 0x9097, 0x2210, 0x00000022);
+	nv_mthd(dev, 0x9097, 0x2220, 0x00000022);
+	nv_mthd(dev, 0x9097, 0x2230, 0x00000022);
+	nv_mthd(dev, 0x9097, 0x2240, 0x00000022);
+	nv_mthd(dev, 0x9097, 0x2000, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x2040, 0x00000011);
+	nv_mthd(dev, 0x9097, 0x2080, 0x00000020);
+	nv_mthd(dev, 0x9097, 0x20c0, 0x00000030);
+	nv_mthd(dev, 0x9097, 0x2100, 0x00000040);
+	nv_mthd(dev, 0x9097, 0x2140, 0x00000051);
+	nv_mthd(dev, 0x9097, 0x200c, 0x00000001);
+	nv_mthd(dev, 0x9097, 0x204c, 0x00000001);
+	nv_mthd(dev, 0x9097, 0x208c, 0x00000001);
+	nv_mthd(dev, 0x9097, 0x20cc, 0x00000001);
+	nv_mthd(dev, 0x9097, 0x210c, 0x00000001);
+	nv_mthd(dev, 0x9097, 0x214c, 0x00000001);
+	nv_mthd(dev, 0x9097, 0x2010, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x2050, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x2090, 0x00000001);
+	nv_mthd(dev, 0x9097, 0x20d0, 0x00000002);
+	nv_mthd(dev, 0x9097, 0x2110, 0x00000003);
+	nv_mthd(dev, 0x9097, 0x2150, 0x00000004);
+	nv_mthd(dev, 0x9097, 0x0380, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x03a0, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x03c0, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x03e0, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0384, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x03a4, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x03c4, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x03e4, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0388, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x03a8, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x03c8, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x03e8, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x038c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x03ac, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x03cc, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x03ec, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0700, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0710, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0720, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0730, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0704, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0714, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0724, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0734, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0708, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0718, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0728, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0738, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x2800, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x2804, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x2808, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x280c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x2810, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x2814, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x2818, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x281c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x2820, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x2824, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x2828, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x282c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x2830, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x2834, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x2838, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x283c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x2840, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x2844, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x2848, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x284c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x2850, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x2854, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x2858, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x285c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x2860, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x2864, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x2868, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x286c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x2870, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x2874, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x2878, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x287c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x2880, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x2884, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x2888, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x288c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x2890, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x2894, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x2898, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x289c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x28a0, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x28a4, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x28a8, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x28ac, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x28b0, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x28b4, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x28b8, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x28bc, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x28c0, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x28c4, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x28c8, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x28cc, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x28d0, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x28d4, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x28d8, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x28dc, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x28e0, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x28e4, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x28e8, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x28ec, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x28f0, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x28f4, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x28f8, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x28fc, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x2900, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x2904, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x2908, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x290c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x2910, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x2914, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x2918, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x291c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x2920, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x2924, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x2928, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x292c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x2930, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x2934, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x2938, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x293c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x2940, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x2944, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x2948, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x294c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x2950, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x2954, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x2958, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x295c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x2960, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x2964, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x2968, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x296c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x2970, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x2974, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x2978, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x297c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x2980, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x2984, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x2988, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x298c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x2990, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x2994, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x2998, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x299c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x29a0, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x29a4, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x29a8, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x29ac, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x29b0, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x29b4, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x29b8, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x29bc, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x29c0, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x29c4, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x29c8, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x29cc, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x29d0, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x29d4, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x29d8, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x29dc, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x29e0, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x29e4, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x29e8, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x29ec, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x29f0, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x29f4, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x29f8, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x29fc, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0a00, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0a20, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0a40, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0a60, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0a80, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0aa0, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0ac0, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0ae0, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0b00, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0b20, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0b40, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0b60, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0b80, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0ba0, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0bc0, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0be0, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0a04, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0a24, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0a44, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0a64, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0a84, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0aa4, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0ac4, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0ae4, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0b04, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0b24, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0b44, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0b64, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0b84, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0ba4, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0bc4, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0be4, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0a08, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0a28, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0a48, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0a68, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0a88, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0aa8, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0ac8, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0ae8, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0b08, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0b28, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0b48, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0b68, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0b88, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0ba8, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0bc8, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0be8, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0a0c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0a2c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0a4c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0a6c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0a8c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0aac, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0acc, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0aec, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0b0c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0b2c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0b4c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0b6c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0b8c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0bac, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0bcc, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0bec, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0a10, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0a30, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0a50, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0a70, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0a90, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0ab0, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0ad0, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0af0, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0b10, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0b30, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0b50, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0b70, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0b90, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0bb0, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0bd0, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0bf0, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0a14, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0a34, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0a54, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0a74, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0a94, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0ab4, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0ad4, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0af4, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0b14, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0b34, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0b54, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0b74, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0b94, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0bb4, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0bd4, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0bf4, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0c00, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0c10, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0c20, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0c30, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0c40, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0c50, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0c60, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0c70, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0c80, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0c90, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0ca0, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0cb0, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0cc0, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0cd0, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0ce0, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0cf0, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0c04, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0c14, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0c24, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0c34, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0c44, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0c54, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0c64, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0c74, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0c84, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0c94, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0ca4, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0cb4, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0cc4, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0cd4, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0ce4, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0cf4, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0c08, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0c18, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0c28, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0c38, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0c48, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0c58, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0c68, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0c78, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0c88, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0c98, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0ca8, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0cb8, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0cc8, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0cd8, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0ce8, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0cf8, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0c0c, 0x3f800000);
+	nv_mthd(dev, 0x9097, 0x0c1c, 0x3f800000);
+	nv_mthd(dev, 0x9097, 0x0c2c, 0x3f800000);
+	nv_mthd(dev, 0x9097, 0x0c3c, 0x3f800000);
+	nv_mthd(dev, 0x9097, 0x0c4c, 0x3f800000);
+	nv_mthd(dev, 0x9097, 0x0c5c, 0x3f800000);
+	nv_mthd(dev, 0x9097, 0x0c6c, 0x3f800000);
+	nv_mthd(dev, 0x9097, 0x0c7c, 0x3f800000);
+	nv_mthd(dev, 0x9097, 0x0c8c, 0x3f800000);
+	nv_mthd(dev, 0x9097, 0x0c9c, 0x3f800000);
+	nv_mthd(dev, 0x9097, 0x0cac, 0x3f800000);
+	nv_mthd(dev, 0x9097, 0x0cbc, 0x3f800000);
+	nv_mthd(dev, 0x9097, 0x0ccc, 0x3f800000);
+	nv_mthd(dev, 0x9097, 0x0cdc, 0x3f800000);
+	nv_mthd(dev, 0x9097, 0x0cec, 0x3f800000);
+	nv_mthd(dev, 0x9097, 0x0cfc, 0x3f800000);
+	nv_mthd(dev, 0x9097, 0x0d00, 0xffff0000);
+	nv_mthd(dev, 0x9097, 0x0d08, 0xffff0000);
+	nv_mthd(dev, 0x9097, 0x0d10, 0xffff0000);
+	nv_mthd(dev, 0x9097, 0x0d18, 0xffff0000);
+	nv_mthd(dev, 0x9097, 0x0d20, 0xffff0000);
+	nv_mthd(dev, 0x9097, 0x0d28, 0xffff0000);
+	nv_mthd(dev, 0x9097, 0x0d30, 0xffff0000);
+	nv_mthd(dev, 0x9097, 0x0d38, 0xffff0000);
+	nv_mthd(dev, 0x9097, 0x0d04, 0xffff0000);
+	nv_mthd(dev, 0x9097, 0x0d0c, 0xffff0000);
+	nv_mthd(dev, 0x9097, 0x0d14, 0xffff0000);
+	nv_mthd(dev, 0x9097, 0x0d1c, 0xffff0000);
+	nv_mthd(dev, 0x9097, 0x0d24, 0xffff0000);
+	nv_mthd(dev, 0x9097, 0x0d2c, 0xffff0000);
+	nv_mthd(dev, 0x9097, 0x0d34, 0xffff0000);
+	nv_mthd(dev, 0x9097, 0x0d3c, 0xffff0000);
+	nv_mthd(dev, 0x9097, 0x0e00, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0e10, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0e20, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0e30, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0e40, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0e50, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0e60, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0e70, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0e80, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0e90, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0ea0, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0eb0, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0ec0, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0ed0, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0ee0, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0ef0, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0e04, 0xffff0000);
+	nv_mthd(dev, 0x9097, 0x0e14, 0xffff0000);
+	nv_mthd(dev, 0x9097, 0x0e24, 0xffff0000);
+	nv_mthd(dev, 0x9097, 0x0e34, 0xffff0000);
+	nv_mthd(dev, 0x9097, 0x0e44, 0xffff0000);
+	nv_mthd(dev, 0x9097, 0x0e54, 0xffff0000);
+	nv_mthd(dev, 0x9097, 0x0e64, 0xffff0000);
+	nv_mthd(dev, 0x9097, 0x0e74, 0xffff0000);
+	nv_mthd(dev, 0x9097, 0x0e84, 0xffff0000);
+	nv_mthd(dev, 0x9097, 0x0e94, 0xffff0000);
+	nv_mthd(dev, 0x9097, 0x0ea4, 0xffff0000);
+	nv_mthd(dev, 0x9097, 0x0eb4, 0xffff0000);
+	nv_mthd(dev, 0x9097, 0x0ec4, 0xffff0000);
+	nv_mthd(dev, 0x9097, 0x0ed4, 0xffff0000);
+	nv_mthd(dev, 0x9097, 0x0ee4, 0xffff0000);
+	nv_mthd(dev, 0x9097, 0x0ef4, 0xffff0000);
+	nv_mthd(dev, 0x9097, 0x0e08, 0xffff0000);
+	nv_mthd(dev, 0x9097, 0x0e18, 0xffff0000);
+	nv_mthd(dev, 0x9097, 0x0e28, 0xffff0000);
+	nv_mthd(dev, 0x9097, 0x0e38, 0xffff0000);
+	nv_mthd(dev, 0x9097, 0x0e48, 0xffff0000);
+	nv_mthd(dev, 0x9097, 0x0e58, 0xffff0000);
+	nv_mthd(dev, 0x9097, 0x0e68, 0xffff0000);
+	nv_mthd(dev, 0x9097, 0x0e78, 0xffff0000);
+	nv_mthd(dev, 0x9097, 0x0e88, 0xffff0000);
+	nv_mthd(dev, 0x9097, 0x0e98, 0xffff0000);
+	nv_mthd(dev, 0x9097, 0x0ea8, 0xffff0000);
+	nv_mthd(dev, 0x9097, 0x0eb8, 0xffff0000);
+	nv_mthd(dev, 0x9097, 0x0ec8, 0xffff0000);
+	nv_mthd(dev, 0x9097, 0x0ed8, 0xffff0000);
+	nv_mthd(dev, 0x9097, 0x0ee8, 0xffff0000);
+	nv_mthd(dev, 0x9097, 0x0ef8, 0xffff0000);
+	nv_mthd(dev, 0x9097, 0x0d40, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0d48, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0d50, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0d58, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0d44, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0d4c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0d54, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0d5c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1e00, 0x00000001);
+	nv_mthd(dev, 0x9097, 0x1e20, 0x00000001);
+	nv_mthd(dev, 0x9097, 0x1e40, 0x00000001);
+	nv_mthd(dev, 0x9097, 0x1e60, 0x00000001);
+	nv_mthd(dev, 0x9097, 0x1e80, 0x00000001);
+	nv_mthd(dev, 0x9097, 0x1ea0, 0x00000001);
+	nv_mthd(dev, 0x9097, 0x1ec0, 0x00000001);
+	nv_mthd(dev, 0x9097, 0x1ee0, 0x00000001);
+	nv_mthd(dev, 0x9097, 0x1e04, 0x00000001);
+	nv_mthd(dev, 0x9097, 0x1e24, 0x00000001);
+	nv_mthd(dev, 0x9097, 0x1e44, 0x00000001);
+	nv_mthd(dev, 0x9097, 0x1e64, 0x00000001);
+	nv_mthd(dev, 0x9097, 0x1e84, 0x00000001);
+	nv_mthd(dev, 0x9097, 0x1ea4, 0x00000001);
+	nv_mthd(dev, 0x9097, 0x1ec4, 0x00000001);
+	nv_mthd(dev, 0x9097, 0x1ee4, 0x00000001);
+	nv_mthd(dev, 0x9097, 0x1e08, 0x00000002);
+	nv_mthd(dev, 0x9097, 0x1e28, 0x00000002);
+	nv_mthd(dev, 0x9097, 0x1e48, 0x00000002);
+	nv_mthd(dev, 0x9097, 0x1e68, 0x00000002);
+	nv_mthd(dev, 0x9097, 0x1e88, 0x00000002);
+	nv_mthd(dev, 0x9097, 0x1ea8, 0x00000002);
+	nv_mthd(dev, 0x9097, 0x1ec8, 0x00000002);
+	nv_mthd(dev, 0x9097, 0x1ee8, 0x00000002);
+	nv_mthd(dev, 0x9097, 0x1e0c, 0x00000001);
+	nv_mthd(dev, 0x9097, 0x1e2c, 0x00000001);
+	nv_mthd(dev, 0x9097, 0x1e4c, 0x00000001);
+	nv_mthd(dev, 0x9097, 0x1e6c, 0x00000001);
+	nv_mthd(dev, 0x9097, 0x1e8c, 0x00000001);
+	nv_mthd(dev, 0x9097, 0x1eac, 0x00000001);
+	nv_mthd(dev, 0x9097, 0x1ecc, 0x00000001);
+	nv_mthd(dev, 0x9097, 0x1eec, 0x00000001);
+	nv_mthd(dev, 0x9097, 0x1e10, 0x00000001);
+	nv_mthd(dev, 0x9097, 0x1e30, 0x00000001);
+	nv_mthd(dev, 0x9097, 0x1e50, 0x00000001);
+	nv_mthd(dev, 0x9097, 0x1e70, 0x00000001);
+	nv_mthd(dev, 0x9097, 0x1e90, 0x00000001);
+	nv_mthd(dev, 0x9097, 0x1eb0, 0x00000001);
+	nv_mthd(dev, 0x9097, 0x1ed0, 0x00000001);
+	nv_mthd(dev, 0x9097, 0x1ef0, 0x00000001);
+	nv_mthd(dev, 0x9097, 0x1e14, 0x00000002);
+	nv_mthd(dev, 0x9097, 0x1e34, 0x00000002);
+	nv_mthd(dev, 0x9097, 0x1e54, 0x00000002);
+	nv_mthd(dev, 0x9097, 0x1e74, 0x00000002);
+	nv_mthd(dev, 0x9097, 0x1e94, 0x00000002);
+	nv_mthd(dev, 0x9097, 0x1eb4, 0x00000002);
+	nv_mthd(dev, 0x9097, 0x1ed4, 0x00000002);
+	nv_mthd(dev, 0x9097, 0x1ef4, 0x00000002);
+	nv_mthd(dev, 0x9097, 0x1e18, 0x00000001);
+	nv_mthd(dev, 0x9097, 0x1e38, 0x00000001);
+	nv_mthd(dev, 0x9097, 0x1e58, 0x00000001);
+	nv_mthd(dev, 0x9097, 0x1e78, 0x00000001);
+	nv_mthd(dev, 0x9097, 0x1e98, 0x00000001);
+	nv_mthd(dev, 0x9097, 0x1eb8, 0x00000001);
+	nv_mthd(dev, 0x9097, 0x1ed8, 0x00000001);
+	nv_mthd(dev, 0x9097, 0x1ef8, 0x00000001);
+	nv_mthd(dev, 0x9097, 0x3400, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x3404, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x3408, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x340c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x3410, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x3414, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x3418, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x341c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x3420, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x3424, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x3428, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x342c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x3430, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x3434, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x3438, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x343c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x3440, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x3444, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x3448, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x344c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x3450, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x3454, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x3458, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x345c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x3460, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x3464, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x3468, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x346c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x3470, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x3474, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x3478, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x347c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x3480, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x3484, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x3488, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x348c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x3490, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x3494, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x3498, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x349c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x34a0, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x34a4, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x34a8, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x34ac, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x34b0, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x34b4, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x34b8, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x34bc, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x34c0, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x34c4, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x34c8, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x34cc, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x34d0, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x34d4, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x34d8, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x34dc, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x34e0, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x34e4, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x34e8, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x34ec, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x34f0, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x34f4, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x34f8, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x34fc, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x3500, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x3504, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x3508, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x350c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x3510, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x3514, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x3518, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x351c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x3520, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x3524, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x3528, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x352c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x3530, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x3534, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x3538, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x353c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x3540, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x3544, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x3548, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x354c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x3550, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x3554, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x3558, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x355c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x3560, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x3564, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x3568, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x356c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x3570, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x3574, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x3578, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x357c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x3580, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x3584, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x3588, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x358c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x3590, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x3594, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x3598, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x359c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x35a0, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x35a4, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x35a8, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x35ac, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x35b0, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x35b4, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x35b8, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x35bc, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x35c0, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x35c4, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x35c8, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x35cc, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x35d0, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x35d4, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x35d8, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x35dc, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x35e0, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x35e4, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x35e8, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x35ec, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x35f0, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x35f4, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x35f8, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x35fc, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x030c, 0x00000001);
+	nv_mthd(dev, 0x9097, 0x1944, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1514, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0d68, 0x0000ffff);
+	nv_mthd(dev, 0x9097, 0x121c, 0x0fac6881);
+	nv_mthd(dev, 0x9097, 0x0fac, 0x00000001);
+	nv_mthd(dev, 0x9097, 0x1538, 0x00000001);
+	nv_mthd(dev, 0x9097, 0x0fe0, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0fe4, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0fe8, 0x00000014);
+	nv_mthd(dev, 0x9097, 0x0fec, 0x00000040);
+	nv_mthd(dev, 0x9097, 0x0ff0, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x179c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1228, 0x00000400);
+	nv_mthd(dev, 0x9097, 0x122c, 0x00000300);
+	nv_mthd(dev, 0x9097, 0x1230, 0x00010001);
+	nv_mthd(dev, 0x9097, 0x07f8, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x15b4, 0x00000001);
+	nv_mthd(dev, 0x9097, 0x15cc, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1534, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0fb0, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x15d0, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x153c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x16b4, 0x00000003);
+	nv_mthd(dev, 0x9097, 0x0fbc, 0x0000ffff);
+	nv_mthd(dev, 0x9097, 0x0fc0, 0x0000ffff);
+	nv_mthd(dev, 0x9097, 0x0fc4, 0x0000ffff);
+	nv_mthd(dev, 0x9097, 0x0fc8, 0x0000ffff);
+	nv_mthd(dev, 0x9097, 0x0df8, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0dfc, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1948, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1970, 0x00000001);
+	nv_mthd(dev, 0x9097, 0x161c, 0x000009f0);
+	nv_mthd(dev, 0x9097, 0x0dcc, 0x00000010);
+	nv_mthd(dev, 0x9097, 0x163c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x15e4, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1160, 0x25e00040);
+	nv_mthd(dev, 0x9097, 0x1164, 0x25e00040);
+	nv_mthd(dev, 0x9097, 0x1168, 0x25e00040);
+	nv_mthd(dev, 0x9097, 0x116c, 0x25e00040);
+	nv_mthd(dev, 0x9097, 0x1170, 0x25e00040);
+	nv_mthd(dev, 0x9097, 0x1174, 0x25e00040);
+	nv_mthd(dev, 0x9097, 0x1178, 0x25e00040);
+	nv_mthd(dev, 0x9097, 0x117c, 0x25e00040);
+	nv_mthd(dev, 0x9097, 0x1180, 0x25e00040);
+	nv_mthd(dev, 0x9097, 0x1184, 0x25e00040);
+	nv_mthd(dev, 0x9097, 0x1188, 0x25e00040);
+	nv_mthd(dev, 0x9097, 0x118c, 0x25e00040);
+	nv_mthd(dev, 0x9097, 0x1190, 0x25e00040);
+	nv_mthd(dev, 0x9097, 0x1194, 0x25e00040);
+	nv_mthd(dev, 0x9097, 0x1198, 0x25e00040);
+	nv_mthd(dev, 0x9097, 0x119c, 0x25e00040);
+	nv_mthd(dev, 0x9097, 0x11a0, 0x25e00040);
+	nv_mthd(dev, 0x9097, 0x11a4, 0x25e00040);
+	nv_mthd(dev, 0x9097, 0x11a8, 0x25e00040);
+	nv_mthd(dev, 0x9097, 0x11ac, 0x25e00040);
+	nv_mthd(dev, 0x9097, 0x11b0, 0x25e00040);
+	nv_mthd(dev, 0x9097, 0x11b4, 0x25e00040);
+	nv_mthd(dev, 0x9097, 0x11b8, 0x25e00040);
+	nv_mthd(dev, 0x9097, 0x11bc, 0x25e00040);
+	nv_mthd(dev, 0x9097, 0x11c0, 0x25e00040);
+	nv_mthd(dev, 0x9097, 0x11c4, 0x25e00040);
+	nv_mthd(dev, 0x9097, 0x11c8, 0x25e00040);
+	nv_mthd(dev, 0x9097, 0x11cc, 0x25e00040);
+	nv_mthd(dev, 0x9097, 0x11d0, 0x25e00040);
+	nv_mthd(dev, 0x9097, 0x11d4, 0x25e00040);
+	nv_mthd(dev, 0x9097, 0x11d8, 0x25e00040);
+	nv_mthd(dev, 0x9097, 0x11dc, 0x25e00040);
+	nv_mthd(dev, 0x9097, 0x1880, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1884, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1888, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x188c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1890, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1894, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1898, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x189c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x18a0, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x18a4, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x18a8, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x18ac, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x18b0, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x18b4, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x18b8, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x18bc, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x18c0, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x18c4, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x18c8, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x18cc, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x18d0, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x18d4, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x18d8, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x18dc, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x18e0, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x18e4, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x18e8, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x18ec, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x18f0, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x18f4, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x18f8, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x18fc, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0f84, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0f88, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x17c8, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x17cc, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x17d0, 0x000000ff);
+	nv_mthd(dev, 0x9097, 0x17d4, 0xffffffff);
+	nv_mthd(dev, 0x9097, 0x17d8, 0x00000002);
+	nv_mthd(dev, 0x9097, 0x17dc, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x15f4, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x15f8, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1434, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1438, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0d74, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0dec, 0x00000001);
+	nv_mthd(dev, 0x9097, 0x13a4, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1318, 0x00000001);
+	nv_mthd(dev, 0x9097, 0x1644, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0748, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0de8, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1648, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x12a4, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1120, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1124, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1128, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x112c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1118, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x164c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1658, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1910, 0x00000290);
+	nv_mthd(dev, 0x9097, 0x1518, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x165c, 0x00000001);
+	nv_mthd(dev, 0x9097, 0x1520, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1604, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1570, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x13b0, 0x3f800000);
+	nv_mthd(dev, 0x9097, 0x13b4, 0x3f800000);
+	nv_mthd(dev, 0x9097, 0x020c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1670, 0x30201000);
+	nv_mthd(dev, 0x9097, 0x1674, 0x70605040);
+	nv_mthd(dev, 0x9097, 0x1678, 0xb8a89888);
+	nv_mthd(dev, 0x9097, 0x167c, 0xf8e8d8c8);
+	nv_mthd(dev, 0x9097, 0x166c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1680, 0x00ffff00);
+	nv_mthd(dev, 0x9097, 0x12d0, 0x00000003);
+	nv_mthd(dev, 0x9097, 0x12d4, 0x00000002);
+	nv_mthd(dev, 0x9097, 0x1684, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1688, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0dac, 0x00001b02);
+	nv_mthd(dev, 0x9097, 0x0db0, 0x00001b02);
+	nv_mthd(dev, 0x9097, 0x0db4, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x168c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x15bc, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x156c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x187c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1110, 0x00000001);
+	nv_mthd(dev, 0x9097, 0x0dc0, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0dc4, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0dc8, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1234, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1690, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x12ac, 0x00000001);
+	nv_mthd(dev, 0x9097, 0x02c4, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0790, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0794, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0798, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x079c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x07a0, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x077c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1000, 0x00000010);
+	nv_mthd(dev, 0x9097, 0x10fc, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1290, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0218, 0x00000010);
+	nv_mthd(dev, 0x9097, 0x12d8, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x12dc, 0x00000010);
+	nv_mthd(dev, 0x9097, 0x0d94, 0x00000001);
+	nv_mthd(dev, 0x9097, 0x155c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1560, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1564, 0x00001fff);
+	nv_mthd(dev, 0x9097, 0x1574, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1578, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x157c, 0x003fffff);
+	nv_mthd(dev, 0x9097, 0x1354, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1664, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1610, 0x00000012);
+	nv_mthd(dev, 0x9097, 0x1608, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x160c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x162c, 0x00000003);
+	nv_mthd(dev, 0x9097, 0x0210, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0320, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0324, 0x3f800000);
+	nv_mthd(dev, 0x9097, 0x0328, 0x3f800000);
+	nv_mthd(dev, 0x9097, 0x032c, 0x3f800000);
+	nv_mthd(dev, 0x9097, 0x0330, 0x3f800000);
+	nv_mthd(dev, 0x9097, 0x0334, 0x3f800000);
+	nv_mthd(dev, 0x9097, 0x0338, 0x3f800000);
+	nv_mthd(dev, 0x9097, 0x0750, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0760, 0x39291909);
+	nv_mthd(dev, 0x9097, 0x0764, 0x79695949);
+	nv_mthd(dev, 0x9097, 0x0768, 0xb9a99989);
+	nv_mthd(dev, 0x9097, 0x076c, 0xf9e9d9c9);
+	nv_mthd(dev, 0x9097, 0x0770, 0x30201000);
+	nv_mthd(dev, 0x9097, 0x0774, 0x70605040);
+	nv_mthd(dev, 0x9097, 0x0778, 0x00009080);
+	nv_mthd(dev, 0x9097, 0x0780, 0x39291909);
+	nv_mthd(dev, 0x9097, 0x0784, 0x79695949);
+	nv_mthd(dev, 0x9097, 0x0788, 0xb9a99989);
+	nv_mthd(dev, 0x9097, 0x078c, 0xf9e9d9c9);
+	nv_mthd(dev, 0x9097, 0x07d0, 0x30201000);
+	nv_mthd(dev, 0x9097, 0x07d4, 0x70605040);
+	nv_mthd(dev, 0x9097, 0x07d8, 0x00009080);
+	nv_mthd(dev, 0x9097, 0x037c, 0x00000001);
+	nv_mthd(dev, 0x9097, 0x0740, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0744, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x2600, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1918, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x191c, 0x00000900);
+	nv_mthd(dev, 0x9097, 0x1920, 0x00000405);
+	nv_mthd(dev, 0x9097, 0x1308, 0x00000001);
+	nv_mthd(dev, 0x9097, 0x1924, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x13ac, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x192c, 0x00000001);
+	nv_mthd(dev, 0x9097, 0x193c, 0x00002c1c);
+	nv_mthd(dev, 0x9097, 0x0d7c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0f8c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x02c0, 0x00000001);
+	nv_mthd(dev, 0x9097, 0x1510, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1940, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0ff4, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0ff8, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x194c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1950, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1968, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1590, 0x0000003f);
+	nv_mthd(dev, 0x9097, 0x07e8, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x07ec, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x07f0, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x07f4, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x196c, 0x00000011);
+	nv_mthd(dev, 0x9097, 0x197c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0fcc, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0fd0, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x02d8, 0x00000040);
+	nv_mthd(dev, 0x9097, 0x1980, 0x00000080);
+	nv_mthd(dev, 0x9097, 0x1504, 0x00000080);
+	nv_mthd(dev, 0x9097, 0x1984, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0300, 0x00000001);
+	nv_mthd(dev, 0x9097, 0x13a8, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x12ec, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1310, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1314, 0x00000001);
+	nv_mthd(dev, 0x9097, 0x1380, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1384, 0x00000001);
+	nv_mthd(dev, 0x9097, 0x1388, 0x00000001);
+	nv_mthd(dev, 0x9097, 0x138c, 0x00000001);
+	nv_mthd(dev, 0x9097, 0x1390, 0x00000001);
+	nv_mthd(dev, 0x9097, 0x1394, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x139c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1398, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1594, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1598, 0x00000001);
+	nv_mthd(dev, 0x9097, 0x159c, 0x00000001);
+	nv_mthd(dev, 0x9097, 0x15a0, 0x00000001);
+	nv_mthd(dev, 0x9097, 0x15a4, 0x00000001);
+	nv_mthd(dev, 0x9097, 0x0f54, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0f58, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0f5c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x19bc, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0f9c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0fa0, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x12cc, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x12e8, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x130c, 0x00000001);
+	nv_mthd(dev, 0x9097, 0x1360, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1364, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1368, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x136c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1370, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1374, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1378, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x137c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x133c, 0x00000001);
+	nv_mthd(dev, 0x9097, 0x1340, 0x00000001);
+	nv_mthd(dev, 0x9097, 0x1344, 0x00000002);
+	nv_mthd(dev, 0x9097, 0x1348, 0x00000001);
+	nv_mthd(dev, 0x9097, 0x134c, 0x00000001);
+	nv_mthd(dev, 0x9097, 0x1350, 0x00000002);
+	nv_mthd(dev, 0x9097, 0x1358, 0x00000001);
+	nv_mthd(dev, 0x9097, 0x12e4, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x131c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1320, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1324, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1328, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x19c0, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1140, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x19c4, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x19c8, 0x00001500);
+	nv_mthd(dev, 0x9097, 0x135c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0f90, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x19e0, 0x00000001);
+	nv_mthd(dev, 0x9097, 0x19e4, 0x00000001);
+	nv_mthd(dev, 0x9097, 0x19e8, 0x00000001);
+	nv_mthd(dev, 0x9097, 0x19ec, 0x00000001);
+	nv_mthd(dev, 0x9097, 0x19f0, 0x00000001);
+	nv_mthd(dev, 0x9097, 0x19f4, 0x00000001);
+	nv_mthd(dev, 0x9097, 0x19f8, 0x00000001);
+	nv_mthd(dev, 0x9097, 0x19fc, 0x00000001);
+	nv_mthd(dev, 0x9097, 0x19cc, 0x00000001);
+	nv_mthd(dev, 0x9097, 0x15b8, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1a00, 0x00001111);
+	nv_mthd(dev, 0x9097, 0x1a04, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1a08, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1a0c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1a10, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1a14, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1a18, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1a1c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0d6c, 0xffff0000);
+	nv_mthd(dev, 0x9097, 0x0d70, 0xffff0000);
+	nv_mthd(dev, 0x9097, 0x10f8, 0x00001010);
+	nv_mthd(dev, 0x9097, 0x0d80, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0d84, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0d88, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0d8c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0d90, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0da0, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1508, 0x80000000);
+	nv_mthd(dev, 0x9097, 0x150c, 0x40000000);
+	nv_mthd(dev, 0x9097, 0x1668, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0318, 0x00000008);
+	nv_mthd(dev, 0x9097, 0x031c, 0x00000008);
+	nv_mthd(dev, 0x9097, 0x0d9c, 0x00000001);
+	nv_mthd(dev, 0x9097, 0x07dc, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x074c, 0x00000055);
+	nv_mthd(dev, 0x9097, 0x1420, 0x00000003);
+	nv_mthd(dev, 0x9097, 0x17bc, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x17c0, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x17c4, 0x00000001);
+	nv_mthd(dev, 0x9097, 0x1008, 0x00000008);
+	nv_mthd(dev, 0x9097, 0x100c, 0x00000040);
+	nv_mthd(dev, 0x9097, 0x1010, 0x0000012c);
+	nv_mthd(dev, 0x9097, 0x0d60, 0x00000040);
+	nv_mthd(dev, 0x9097, 0x075c, 0x00000003);
+	nv_mthd(dev, 0x9097, 0x1018, 0x00000020);
+	nv_mthd(dev, 0x9097, 0x101c, 0x00000001);
+	nv_mthd(dev, 0x9097, 0x1020, 0x00000020);
+	nv_mthd(dev, 0x9097, 0x1024, 0x00000001);
+	nv_mthd(dev, 0x9097, 0x1444, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x1448, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x144c, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0360, 0x20164010);
+	nv_mthd(dev, 0x9097, 0x0364, 0x00000020);
+	nv_mthd(dev, 0x9097, 0x0368, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0de4, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0204, 0x00000006);
+	nv_mthd(dev, 0x9097, 0x0208, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x02cc, 0x003fffff);
+	nv_mthd(dev, 0x9097, 0x02d0, 0x00000c48);
+	nv_mthd(dev, 0x9097, 0x1220, 0x00000005);
+	nv_mthd(dev, 0x9097, 0x0fdc, 0x00000000);
+	nv_mthd(dev, 0x9097, 0x0f98, 0x00300008);
+	nv_mthd(dev, 0x9097, 0x1284, 0x04000080);
+	nv_mthd(dev, 0x9097, 0x1450, 0x00300008);
+	nv_mthd(dev, 0x9097, 0x1454, 0x04000080);
+	nv_mthd(dev, 0x9097, 0x0214, 0x00000000);
+	/* in trace, right after 0x90c0, not here */
+	nv_mthd(dev, 0x9097, 0x3410, 0x80002006);
+}
+
+static void
+nvc0_grctx_generate_902d(struct drm_device *dev)
+{
+	nv_mthd(dev, 0x902d, 0x0200, 0x000000cf);
+	nv_mthd(dev, 0x902d, 0x0204, 0x00000001);
+	nv_mthd(dev, 0x902d, 0x0208, 0x00000020);
+	nv_mthd(dev, 0x902d, 0x020c, 0x00000001);
+	nv_mthd(dev, 0x902d, 0x0210, 0x00000000);
+	nv_mthd(dev, 0x902d, 0x0214, 0x00000080);
+	nv_mthd(dev, 0x902d, 0x0218, 0x00000100);
+	nv_mthd(dev, 0x902d, 0x021c, 0x00000100);
+	nv_mthd(dev, 0x902d, 0x0220, 0x00000000);
+	nv_mthd(dev, 0x902d, 0x0224, 0x00000000);
+	nv_mthd(dev, 0x902d, 0x0230, 0x000000cf);
+	nv_mthd(dev, 0x902d, 0x0234, 0x00000001);
+	nv_mthd(dev, 0x902d, 0x0238, 0x00000020);
+	nv_mthd(dev, 0x902d, 0x023c, 0x00000001);
+	nv_mthd(dev, 0x902d, 0x0244, 0x00000080);
+	nv_mthd(dev, 0x902d, 0x0248, 0x00000100);
+	nv_mthd(dev, 0x902d, 0x024c, 0x00000100);
+}
+
+static void
+nvc0_grctx_generate_9039(struct drm_device *dev)
+{
+	nv_mthd(dev, 0x9039, 0x030c, 0x00000000);
+	nv_mthd(dev, 0x9039, 0x0310, 0x00000000);
+	nv_mthd(dev, 0x9039, 0x0314, 0x00000000);
+	nv_mthd(dev, 0x9039, 0x0320, 0x00000000);
+	nv_mthd(dev, 0x9039, 0x0238, 0x00000000);
+	nv_mthd(dev, 0x9039, 0x023c, 0x00000000);
+	nv_mthd(dev, 0x9039, 0x0318, 0x00000000);
+	nv_mthd(dev, 0x9039, 0x031c, 0x00000000);
+}
+
+static void
+nvc0_grctx_generate_90c0(struct drm_device *dev)
+{
+	nv_mthd(dev, 0x90c0, 0x270c, 0x00000000);
+	nv_mthd(dev, 0x90c0, 0x272c, 0x00000000);
+	nv_mthd(dev, 0x90c0, 0x274c, 0x00000000);
+	nv_mthd(dev, 0x90c0, 0x276c, 0x00000000);
+	nv_mthd(dev, 0x90c0, 0x278c, 0x00000000);
+	nv_mthd(dev, 0x90c0, 0x27ac, 0x00000000);
+	nv_mthd(dev, 0x90c0, 0x27cc, 0x00000000);
+	nv_mthd(dev, 0x90c0, 0x27ec, 0x00000000);
+	nv_mthd(dev, 0x90c0, 0x030c, 0x00000001);
+	nv_mthd(dev, 0x90c0, 0x1944, 0x00000000);
+	nv_mthd(dev, 0x90c0, 0x0758, 0x00000100);
+	nv_mthd(dev, 0x90c0, 0x02c4, 0x00000000);
+	nv_mthd(dev, 0x90c0, 0x0790, 0x00000000);
+	nv_mthd(dev, 0x90c0, 0x0794, 0x00000000);
+	nv_mthd(dev, 0x90c0, 0x0798, 0x00000000);
+	nv_mthd(dev, 0x90c0, 0x079c, 0x00000000);
+	nv_mthd(dev, 0x90c0, 0x07a0, 0x00000000);
+	nv_mthd(dev, 0x90c0, 0x077c, 0x00000000);
+	nv_mthd(dev, 0x90c0, 0x0204, 0x00000000);
+	nv_mthd(dev, 0x90c0, 0x0208, 0x00000000);
+	nv_mthd(dev, 0x90c0, 0x020c, 0x00000000);
+	nv_mthd(dev, 0x90c0, 0x0214, 0x00000000);
+	nv_mthd(dev, 0x90c0, 0x024c, 0x00000000);
+	nv_mthd(dev, 0x90c0, 0x0d94, 0x00000001);
+	nv_mthd(dev, 0x90c0, 0x1608, 0x00000000);
+	nv_mthd(dev, 0x90c0, 0x160c, 0x00000000);
+	nv_mthd(dev, 0x90c0, 0x1664, 0x00000000);
+}
+
+static void
+nvc0_grctx_generate_dispatch(struct drm_device *dev)
+{
+	int i;
+
+	nv_wr32(dev, 0x404004, 0x00000000);
+	nv_wr32(dev, 0x404008, 0x00000000);
+	nv_wr32(dev, 0x40400c, 0x00000000);
+	nv_wr32(dev, 0x404010, 0x00000000);
+	nv_wr32(dev, 0x404014, 0x00000000);
+	nv_wr32(dev, 0x404018, 0x00000000);
+	nv_wr32(dev, 0x40401c, 0x00000000);
+	nv_wr32(dev, 0x404020, 0x00000000);
+	nv_wr32(dev, 0x404024, 0x00000000);
+	nv_wr32(dev, 0x404028, 0x00000000);
+	nv_wr32(dev, 0x40402c, 0x00000000);
+	nv_wr32(dev, 0x404044, 0x00000000);
+	nv_wr32(dev, 0x404094, 0x00000000);
+	nv_wr32(dev, 0x404098, 0x00000000);
+	nv_wr32(dev, 0x40409c, 0x00000000);
+	nv_wr32(dev, 0x4040a0, 0x00000000);
+	nv_wr32(dev, 0x4040a4, 0x00000000);
+	nv_wr32(dev, 0x4040a8, 0x00000000);
+	nv_wr32(dev, 0x4040ac, 0x00000000);
+	nv_wr32(dev, 0x4040b0, 0x00000000);
+	nv_wr32(dev, 0x4040b4, 0x00000000);
+	nv_wr32(dev, 0x4040b8, 0x00000000);
+	nv_wr32(dev, 0x4040bc, 0x00000000);
+	nv_wr32(dev, 0x4040c0, 0x00000000);
+	nv_wr32(dev, 0x4040c4, 0x00000000);
+	nv_wr32(dev, 0x4040c8, 0xf0000087);
+	nv_wr32(dev, 0x4040d4, 0x00000000);
+	nv_wr32(dev, 0x4040d8, 0x00000000);
+	nv_wr32(dev, 0x4040dc, 0x00000000);
+	nv_wr32(dev, 0x4040e0, 0x00000000);
+	nv_wr32(dev, 0x4040e4, 0x00000000);
+	nv_wr32(dev, 0x4040e8, 0x00001000);
+	nv_wr32(dev, 0x4040f8, 0x00000000);
+	nv_wr32(dev, 0x404130, 0x00000000);
+	nv_wr32(dev, 0x404134, 0x00000000);
+	nv_wr32(dev, 0x404138, 0x20000040);
+	nv_wr32(dev, 0x404150, 0x0000002e);
+	nv_wr32(dev, 0x404154, 0x00000400);
+	nv_wr32(dev, 0x404158, 0x00000200);
+	nv_wr32(dev, 0x404164, 0x00000055);
+	nv_wr32(dev, 0x404168, 0x00000000);
+	nv_wr32(dev, 0x404174, 0x00000000);
+	nv_wr32(dev, 0x404178, 0x00000000);
+	nv_wr32(dev, 0x40417c, 0x00000000);
+	for (i = 0; i < 8; i++)
+		nv_wr32(dev, 0x404200 + (i * 4), 0x00000000); /* subc */
+}
+
+static void
+nvc0_grctx_generate_macro(struct drm_device *dev)
+{
+	nv_wr32(dev, 0x404404, 0x00000000);
+	nv_wr32(dev, 0x404408, 0x00000000);
+	nv_wr32(dev, 0x40440c, 0x00000000);
+	nv_wr32(dev, 0x404410, 0x00000000);
+	nv_wr32(dev, 0x404414, 0x00000000);
+	nv_wr32(dev, 0x404418, 0x00000000);
+	nv_wr32(dev, 0x40441c, 0x00000000);
+	nv_wr32(dev, 0x404420, 0x00000000);
+	nv_wr32(dev, 0x404424, 0x00000000);
+	nv_wr32(dev, 0x404428, 0x00000000);
+	nv_wr32(dev, 0x40442c, 0x00000000);
+	nv_wr32(dev, 0x404430, 0x00000000);
+	nv_wr32(dev, 0x404434, 0x00000000);
+	nv_wr32(dev, 0x404438, 0x00000000);
+	nv_wr32(dev, 0x404460, 0x00000000);
+	nv_wr32(dev, 0x404464, 0x00000000);
+	nv_wr32(dev, 0x404468, 0x00ffffff);
+	nv_wr32(dev, 0x40446c, 0x00000000);
+	nv_wr32(dev, 0x404480, 0x00000001);
+	nv_wr32(dev, 0x404498, 0x00000001);
+}
+
+static void
+nvc0_grctx_generate_m2mf(struct drm_device *dev)
+{
+	nv_wr32(dev, 0x404604, 0x00000015);
+	nv_wr32(dev, 0x404608, 0x00000000);
+	nv_wr32(dev, 0x40460c, 0x00002e00);
+	nv_wr32(dev, 0x404610, 0x00000100);
+	nv_wr32(dev, 0x404618, 0x00000000);
+	nv_wr32(dev, 0x40461c, 0x00000000);
+	nv_wr32(dev, 0x404620, 0x00000000);
+	nv_wr32(dev, 0x404624, 0x00000000);
+	nv_wr32(dev, 0x404628, 0x00000000);
+	nv_wr32(dev, 0x40462c, 0x00000000);
+	nv_wr32(dev, 0x404630, 0x00000000);
+	nv_wr32(dev, 0x404634, 0x00000000);
+	nv_wr32(dev, 0x404638, 0x00000004);
+	nv_wr32(dev, 0x40463c, 0x00000000);
+	nv_wr32(dev, 0x404640, 0x00000000);
+	nv_wr32(dev, 0x404644, 0x00000000);
+	nv_wr32(dev, 0x404648, 0x00000000);
+	nv_wr32(dev, 0x40464c, 0x00000000);
+	nv_wr32(dev, 0x404650, 0x00000000);
+	nv_wr32(dev, 0x404654, 0x00000000);
+	nv_wr32(dev, 0x404658, 0x00000000);
+	nv_wr32(dev, 0x40465c, 0x007f0100);
+	nv_wr32(dev, 0x404660, 0x00000000);
+	nv_wr32(dev, 0x404664, 0x00000000);
+	nv_wr32(dev, 0x404668, 0x00000000);
+	nv_wr32(dev, 0x40466c, 0x00000000);
+	nv_wr32(dev, 0x404670, 0x00000000);
+	nv_wr32(dev, 0x404674, 0x00000000);
+	nv_wr32(dev, 0x404678, 0x00000000);
+	nv_wr32(dev, 0x40467c, 0x00000002);
+	nv_wr32(dev, 0x404680, 0x00000000);
+	nv_wr32(dev, 0x404684, 0x00000000);
+	nv_wr32(dev, 0x404688, 0x00000000);
+	nv_wr32(dev, 0x40468c, 0x00000000);
+	nv_wr32(dev, 0x404690, 0x00000000);
+	nv_wr32(dev, 0x404694, 0x00000000);
+	nv_wr32(dev, 0x404698, 0x00000000);
+	nv_wr32(dev, 0x40469c, 0x00000000);
+	nv_wr32(dev, 0x4046a0, 0x007f0080);
+	nv_wr32(dev, 0x4046a4, 0x00000000);
+	nv_wr32(dev, 0x4046a8, 0x00000000);
+	nv_wr32(dev, 0x4046ac, 0x00000000);
+	nv_wr32(dev, 0x4046b0, 0x00000000);
+	nv_wr32(dev, 0x4046b4, 0x00000000);
+	nv_wr32(dev, 0x4046b8, 0x00000000);
+	nv_wr32(dev, 0x4046bc, 0x00000000);
+	nv_wr32(dev, 0x4046c0, 0x00000000);
+	nv_wr32(dev, 0x4046c4, 0x00000000);
+	nv_wr32(dev, 0x4046c8, 0x00000000);
+	nv_wr32(dev, 0x4046cc, 0x00000000);
+	nv_wr32(dev, 0x4046d0, 0x00000000);
+	nv_wr32(dev, 0x4046d4, 0x00000000);
+	nv_wr32(dev, 0x4046d8, 0x00000000);
+	nv_wr32(dev, 0x4046dc, 0x00000000);
+	nv_wr32(dev, 0x4046e0, 0x00000000);
+	nv_wr32(dev, 0x4046e4, 0x00000000);
+	nv_wr32(dev, 0x4046e8, 0x00000000);
+	nv_wr32(dev, 0x4046f0, 0x00000000);
+	nv_wr32(dev, 0x4046f4, 0x00000000);
+}
+
+static void
+nvc0_grctx_generate_unk47xx(struct drm_device *dev)
+{
+	nv_wr32(dev, 0x404700, 0x00000000);
+	nv_wr32(dev, 0x404704, 0x00000000);
+	nv_wr32(dev, 0x404708, 0x00000000);
+	nv_wr32(dev, 0x40470c, 0x00000000);
+	nv_wr32(dev, 0x404710, 0x00000000);
+	nv_wr32(dev, 0x404714, 0x00000000);
+	nv_wr32(dev, 0x404718, 0x00000000);
+	nv_wr32(dev, 0x40471c, 0x00000000);
+	nv_wr32(dev, 0x404720, 0x00000000);
+	nv_wr32(dev, 0x404724, 0x00000000);
+	nv_wr32(dev, 0x404728, 0x00000000);
+	nv_wr32(dev, 0x40472c, 0x00000000);
+	nv_wr32(dev, 0x404730, 0x00000000);
+	nv_wr32(dev, 0x404734, 0x00000100);
+	nv_wr32(dev, 0x404738, 0x00000000);
+	nv_wr32(dev, 0x40473c, 0x00000000);
+	nv_wr32(dev, 0x404740, 0x00000000);
+	nv_wr32(dev, 0x404744, 0x00000000);
+	nv_wr32(dev, 0x404748, 0x00000000);
+	nv_wr32(dev, 0x40474c, 0x00000000);
+	nv_wr32(dev, 0x404750, 0x00000000);
+	nv_wr32(dev, 0x404754, 0x00000000);
+}
+
+static void
+nvc0_grctx_generate_shaders(struct drm_device *dev)
+{
+	nv_wr32(dev, 0x405800, 0x078000bf);
+	nv_wr32(dev, 0x405830, 0x02180000);
+	nv_wr32(dev, 0x405834, 0x00000000);
+	nv_wr32(dev, 0x405838, 0x00000000);
+	nv_wr32(dev, 0x405854, 0x00000000);
+	nv_wr32(dev, 0x405870, 0x00000001);
+	nv_wr32(dev, 0x405874, 0x00000001);
+	nv_wr32(dev, 0x405878, 0x00000001);
+	nv_wr32(dev, 0x40587c, 0x00000001);
+	nv_wr32(dev, 0x405a00, 0x00000000);
+	nv_wr32(dev, 0x405a04, 0x00000000);
+	nv_wr32(dev, 0x405a18, 0x00000000);
+}
+
+static void
+nvc0_grctx_generate_unk60xx(struct drm_device *dev)
+{
+	nv_wr32(dev, 0x406020, 0x000103c1);
+	nv_wr32(dev, 0x406028, 0x00000001);
+	nv_wr32(dev, 0x40602c, 0x00000001);
+	nv_wr32(dev, 0x406030, 0x00000001);
+	nv_wr32(dev, 0x406034, 0x00000001);
+}
+
+static void
+nvc0_grctx_generate_unk64xx(struct drm_device *dev)
+{
+	nv_wr32(dev, 0x4064a8, 0x00000000);
+	nv_wr32(dev, 0x4064ac, 0x00003fff);
+	nv_wr32(dev, 0x4064b4, 0x00000000);
+	nv_wr32(dev, 0x4064b8, 0x00000000);
+}
+
+static void
+nvc0_grctx_generate_tpbus(struct drm_device *dev)
+{
+	nv_wr32(dev, 0x407804, 0x00000023);
+	nv_wr32(dev, 0x40780c, 0x0a418820);
+	nv_wr32(dev, 0x407810, 0x062080e6);
+	nv_wr32(dev, 0x407814, 0x020398a4);
+	nv_wr32(dev, 0x407818, 0x0e629062);
+	nv_wr32(dev, 0x40781c, 0x0a418820);
+	nv_wr32(dev, 0x407820, 0x000000e6);
+	nv_wr32(dev, 0x4078bc, 0x00000103);
+}
+
+static void
+nvc0_grctx_generate_ccache(struct drm_device *dev)
+{
+	nv_wr32(dev, 0x408000, 0x00000000);
+	nv_wr32(dev, 0x408004, 0x00000000);
+	nv_wr32(dev, 0x408008, 0x00000018);
+	nv_wr32(dev, 0x40800c, 0x00000000);
+	nv_wr32(dev, 0x408010, 0x00000000);
+	nv_wr32(dev, 0x408014, 0x00000069);
+	nv_wr32(dev, 0x408018, 0xe100e100);
+	nv_wr32(dev, 0x408064, 0x00000000);
+}
+
+static void
+nvc0_grctx_generate_rop(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+	// ROPC_BROADCAST
+	nv_wr32(dev, 0x408800, 0x02802a3c);
+	nv_wr32(dev, 0x408804, 0x00000040);
+	nv_wr32(dev, 0x408808, 0x0003e00d);
+	switch (dev_priv->chipset) {
+	case 0xc0:
+		nv_wr32(dev, 0x408900, 0x0080b801);
+		break;
+	case 0xc3:
+	case 0xc4:
+		nv_wr32(dev, 0x408900, 0x3080b801);
+		break;
+	}
+	nv_wr32(dev, 0x408904, 0x02000001);
+	nv_wr32(dev, 0x408908, 0x00c80929);
+	nv_wr32(dev, 0x40890c, 0x00000000);
+	nv_wr32(dev, 0x408980, 0x0000011d);
+}
+
+static void
+nvc0_grctx_generate_gpc(struct drm_device *dev)
+{
+	int i;
+
+	// GPC_BROADCAST
+	nv_wr32(dev, 0x418380, 0x00000016);
+	nv_wr32(dev, 0x418400, 0x38004e00);
+	nv_wr32(dev, 0x418404, 0x71e0ffff);
+	nv_wr32(dev, 0x418408, 0x00000000);
+	nv_wr32(dev, 0x41840c, 0x00001008);
+	nv_wr32(dev, 0x418410, 0x0fff0fff);
+	nv_wr32(dev, 0x418414, 0x00200fff);
+	nv_wr32(dev, 0x418450, 0x00000000);
+	nv_wr32(dev, 0x418454, 0x00000000);
+	nv_wr32(dev, 0x418458, 0x00000000);
+	nv_wr32(dev, 0x41845c, 0x00000000);
+	nv_wr32(dev, 0x418460, 0x00000000);
+	nv_wr32(dev, 0x418464, 0x00000000);
+	nv_wr32(dev, 0x418468, 0x00000001);
+	nv_wr32(dev, 0x41846c, 0x00000000);
+	nv_wr32(dev, 0x418470, 0x00000000);
+	nv_wr32(dev, 0x418600, 0x0000001f);
+	nv_wr32(dev, 0x418684, 0x0000000f);
+	nv_wr32(dev, 0x418700, 0x00000002);
+	nv_wr32(dev, 0x418704, 0x00000080);
+	nv_wr32(dev, 0x418708, 0x00000000);
+	nv_wr32(dev, 0x41870c, 0x07c80000);
+	nv_wr32(dev, 0x418710, 0x00000000);
+	nv_wr32(dev, 0x418800, 0x0006860a);
+	nv_wr32(dev, 0x418808, 0x00000000);
+	nv_wr32(dev, 0x41880c, 0x00000000);
+	nv_wr32(dev, 0x418810, 0x00000000);
+	nv_wr32(dev, 0x418828, 0x00008442);
+	nv_wr32(dev, 0x418830, 0x00000001);
+	nv_wr32(dev, 0x4188d8, 0x00000008);
+	nv_wr32(dev, 0x4188e0, 0x01000000);
+	nv_wr32(dev, 0x4188e8, 0x00000000);
+	nv_wr32(dev, 0x4188ec, 0x00000000);
+	nv_wr32(dev, 0x4188f0, 0x00000000);
+	nv_wr32(dev, 0x4188f4, 0x00000000);
+	nv_wr32(dev, 0x4188f8, 0x00000000);
+	nv_wr32(dev, 0x4188fc, 0x00100000);
+	nv_wr32(dev, 0x41891c, 0x00ff00ff);
+	nv_wr32(dev, 0x418924, 0x00000000);
+	nv_wr32(dev, 0x418928, 0x00ffff00);
+	nv_wr32(dev, 0x41892c, 0x0000ff00);
+	for (i = 0; i < 8; i++) {
+		nv_wr32(dev, 0x418a00 + (i * 0x20), 0x00000000);
+		nv_wr32(dev, 0x418a04 + (i * 0x20), 0x00000000);
+		nv_wr32(dev, 0x418a08 + (i * 0x20), 0x00000000);
+		nv_wr32(dev, 0x418a0c + (i * 0x20), 0x00010000);
+		nv_wr32(dev, 0x418a10 + (i * 0x20), 0x00000000);
+		nv_wr32(dev, 0x418a14 + (i * 0x20), 0x00000000);
+		nv_wr32(dev, 0x418a18 + (i * 0x20), 0x00000000);
+	}
+	nv_wr32(dev, 0x418b00, 0x00000000);
+	nv_wr32(dev, 0x418b08, 0x0a418820);
+	nv_wr32(dev, 0x418b0c, 0x062080e6);
+	nv_wr32(dev, 0x418b10, 0x020398a4);
+	nv_wr32(dev, 0x418b14, 0x0e629062);
+	nv_wr32(dev, 0x418b18, 0x0a418820);
+	nv_wr32(dev, 0x418b1c, 0x000000e6);
+	nv_wr32(dev, 0x418bb8, 0x00000103);
+	nv_wr32(dev, 0x418c08, 0x00000001);
+	nv_wr32(dev, 0x418c10, 0x00000000);
+	nv_wr32(dev, 0x418c14, 0x00000000);
+	nv_wr32(dev, 0x418c18, 0x00000000);
+	nv_wr32(dev, 0x418c1c, 0x00000000);
+	nv_wr32(dev, 0x418c20, 0x00000000);
+	nv_wr32(dev, 0x418c24, 0x00000000);
+	nv_wr32(dev, 0x418c28, 0x00000000);
+	nv_wr32(dev, 0x418c2c, 0x00000000);
+	nv_wr32(dev, 0x418c80, 0x20200004);
+	nv_wr32(dev, 0x418c8c, 0x00000001);
+	nv_wr32(dev, 0x419000, 0x00000780);
+	nv_wr32(dev, 0x419004, 0x00000000);
+	nv_wr32(dev, 0x419008, 0x00000000);
+	nv_wr32(dev, 0x419014, 0x00000004);
+}
+
+static void
+nvc0_grctx_generate_tp(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+	// GPC_BROADCAST.TP_BROADCAST
+	nv_wr32(dev, 0x419848, 0x00000000);
+	nv_wr32(dev, 0x419864, 0x0000012a);
+	nv_wr32(dev, 0x419888, 0x00000000);
+	nv_wr32(dev, 0x419a00, 0x000001f0);
+	nv_wr32(dev, 0x419a04, 0x00000001);
+	nv_wr32(dev, 0x419a08, 0x00000023);
+	nv_wr32(dev, 0x419a0c, 0x00020000);
+	nv_wr32(dev, 0x419a10, 0x00000000);
+	nv_wr32(dev, 0x419a14, 0x00000200);
+	nv_wr32(dev, 0x419a1c, 0x00000000);
+	nv_wr32(dev, 0x419a20, 0x00000800);
+	if (dev_priv->chipset != 0xc0)
+		nv_wr32(dev, 0x00419ac4, 0x0007f440); // 0xc3
+	nv_wr32(dev, 0x419b00, 0x0a418820);
+	nv_wr32(dev, 0x419b04, 0x062080e6);
+	nv_wr32(dev, 0x419b08, 0x020398a4);
+	nv_wr32(dev, 0x419b0c, 0x0e629062);
+	nv_wr32(dev, 0x419b10, 0x0a418820);
+	nv_wr32(dev, 0x419b14, 0x000000e6);
+	nv_wr32(dev, 0x419bd0, 0x00900103);
+	nv_wr32(dev, 0x419be0, 0x00000001);
+	nv_wr32(dev, 0x419be4, 0x00000000);
+	nv_wr32(dev, 0x419c00, 0x00000002);
+	nv_wr32(dev, 0x419c04, 0x00000006);
+	nv_wr32(dev, 0x419c08, 0x00000002);
+	nv_wr32(dev, 0x419c20, 0x00000000);
+	nv_wr32(dev, 0x419cbc, 0x28137606);
+	nv_wr32(dev, 0x419ce8, 0x00000000);
+	nv_wr32(dev, 0x419cf4, 0x00000183);
+	nv_wr32(dev, 0x419d20, 0x02180000);
+	nv_wr32(dev, 0x419d24, 0x00001fff);
+	nv_wr32(dev, 0x419e04, 0x00000000);
+	nv_wr32(dev, 0x419e08, 0x00000000);
+	nv_wr32(dev, 0x419e0c, 0x00000000);
+	nv_wr32(dev, 0x419e10, 0x00000002);
+	nv_wr32(dev, 0x419e44, 0x001beff2);
+	nv_wr32(dev, 0x419e48, 0x00000000);
+	nv_wr32(dev, 0x419e4c, 0x0000000f);
+	nv_wr32(dev, 0x419e50, 0x00000000);
+	nv_wr32(dev, 0x419e54, 0x00000000);
+	nv_wr32(dev, 0x419e58, 0x00000000);
+	nv_wr32(dev, 0x419e5c, 0x00000000);
+	nv_wr32(dev, 0x419e60, 0x00000000);
+	nv_wr32(dev, 0x419e64, 0x00000000);
+	nv_wr32(dev, 0x419e68, 0x00000000);
+	nv_wr32(dev, 0x419e6c, 0x00000000);
+	nv_wr32(dev, 0x419e70, 0x00000000);
+	nv_wr32(dev, 0x419e74, 0x00000000);
+	nv_wr32(dev, 0x419e78, 0x00000000);
+	nv_wr32(dev, 0x419e7c, 0x00000000);
+	nv_wr32(dev, 0x419e80, 0x00000000);
+	nv_wr32(dev, 0x419e84, 0x00000000);
+	nv_wr32(dev, 0x419e88, 0x00000000);
+	nv_wr32(dev, 0x419e8c, 0x00000000);
+	nv_wr32(dev, 0x419e90, 0x00000000);
+	nv_wr32(dev, 0x419e98, 0x00000000);
+	if (dev_priv->chipset != 0xc0)
+		nv_wr32(dev, 0x419ee0, 0x00011110);
+	nv_wr32(dev, 0x419f50, 0x00000000);
+	nv_wr32(dev, 0x419f54, 0x00000000);
+	if (dev_priv->chipset != 0xc0)
+		nv_wr32(dev, 0x419f58, 0x00000000);
+}
+
+int
+nvc0_grctx_generate(struct nouveau_channel *chan)
+{
+	struct drm_nouveau_private *dev_priv = chan->dev->dev_private;
+	struct nvc0_graph_priv *priv = dev_priv->engine.graph.priv;
+	struct nvc0_graph_chan *grch = chan->pgraph_ctx;
+	struct drm_device *dev = chan->dev;
+	int i, gpc, tp, id;
+	u32 r000260, tmp;
+
+	r000260 = nv_rd32(dev, 0x000260);
+	nv_wr32(dev, 0x000260, r000260 & ~1);
+	nv_wr32(dev, 0x400208, 0x00000000);
+
+	nvc0_grctx_generate_dispatch(dev);
+	nvc0_grctx_generate_macro(dev);
+	nvc0_grctx_generate_m2mf(dev);
+	nvc0_grctx_generate_unk47xx(dev);
+	nvc0_grctx_generate_shaders(dev);
+	nvc0_grctx_generate_unk60xx(dev);
+	nvc0_grctx_generate_unk64xx(dev);
+	nvc0_grctx_generate_tpbus(dev);
+	nvc0_grctx_generate_ccache(dev);
+	nvc0_grctx_generate_rop(dev);
+	nvc0_grctx_generate_gpc(dev);
+	nvc0_grctx_generate_tp(dev);
+
+	nv_wr32(dev, 0x404154, 0x00000000);
+
+	/* fuc "mmio list" writes */
+	for (i = 0; i < grch->mmio_nr * 8; i += 8) {
+		u32 reg = nv_ro32(grch->mmio, i + 0);
+		nv_wr32(dev, reg, nv_ro32(grch->mmio, i + 4));
+	}
+
+	for (tp = 0, id = 0; tp < 4; tp++) {
+		for (gpc = 0; gpc < priv->gpc_nr; gpc++) {
+			if (tp < priv->tp_nr[gpc]) {
+				nv_wr32(dev, TP_UNIT(gpc, tp, 0x698), id);
+				nv_wr32(dev, TP_UNIT(gpc, tp, 0x4e8), id);
+				nv_wr32(dev, GPC_UNIT(gpc, 0x0c10 + tp * 4), id);
+				nv_wr32(dev, TP_UNIT(gpc, tp, 0x088), id);
+				id++;
+			}
+
+			nv_wr32(dev, GPC_UNIT(gpc, 0x0c08), priv->tp_nr[gpc]);
+			nv_wr32(dev, GPC_UNIT(gpc, 0x0c8c), priv->tp_nr[gpc]);
+		}
+	}
+
+	tmp = 0;
+	for (i = 0; i < priv->gpc_nr; i++)
+		tmp |= priv->tp_nr[i] << (i * 4);
+	nv_wr32(dev, 0x406028, tmp);
+	nv_wr32(dev, 0x405870, tmp);
+
+	nv_wr32(dev, 0x40602c, 0x00000000);
+	nv_wr32(dev, 0x405874, 0x00000000);
+	nv_wr32(dev, 0x406030, 0x00000000);
+	nv_wr32(dev, 0x405878, 0x00000000);
+	nv_wr32(dev, 0x406034, 0x00000000);
+	nv_wr32(dev, 0x40587c, 0x00000000);
+
+	if (1) {
+		const u8 chipset_tp_max[] = { 16, 0, 0, 4, 8 };
+		u8 max = chipset_tp_max[dev_priv->chipset & 0x0f];
+		u8 tpnr[GPC_MAX];
+		u8 data[32];
+
+		memcpy(tpnr, priv->tp_nr, sizeof(priv->tp_nr));
+		memset(data, 0x1f, sizeof(data));
+
+		gpc = -1;
+		for (tp = 0; tp < priv->tp_total; tp++) {
+			do {
+				gpc = (gpc + 1) % priv->gpc_nr;
+			} while (!tpnr[gpc]);
+			tpnr[gpc]--;
+			data[tp] = gpc;
+		}
+
+		for (i = 0; i < max / 4; i++)
+			nv_wr32(dev, 0x4060a8 + (i * 4), ((u32 *)data)[i]);
+	}
+
+	if (1) {
+		u32 data[6] = {}, data2[2] = {};
+		u8 tpnr[GPC_MAX];
+		u8 shift, ntpcv;
+
+		/* calculate first set of magics */
+		memcpy(tpnr, priv->tp_nr, sizeof(priv->tp_nr));
+
+		for (tp = 0; tp < priv->tp_total; tp++) {
+			do {
+				gpc = (gpc + 1) % priv->gpc_nr;
+			} while (!tpnr[gpc]);
+			tpnr[gpc]--;
+
+			data[tp / 6] |= gpc << ((tp % 6) * 5);
+		}
+
+		for (; tp < 32; tp++)
+			data[tp / 6] |= 7 << ((tp % 6) * 5);
+
+		/* and the second... */
+		shift = 0;
+		ntpcv = priv->tp_total;
+		while (!(ntpcv & (1 << 4))) {
+			ntpcv <<= 1;
+			shift++;
+		}
+
+		data2[0]  = (ntpcv << 16);
+		data2[0] |= (shift << 21);
+		data2[0] |= (((1 << (0 + 5)) % ntpcv) << 24);
+		for (i = 1; i < 7; i++)
+			data2[1] |= ((1 << (i + 5)) % ntpcv) << ((i - 1) * 5);
+
+		// GPC_BROADCAST
+		nv_wr32(dev, 0x418bb8, (priv->tp_total << 8) |
+					priv->magic_not_rop_nr);
+		for (i = 0; i < 6; i++)
+			nv_wr32(dev, 0x418b08 + (i * 4), data[i]);
+
+		// GPC_BROADCAST.TP_BROADCAST
+		nv_wr32(dev, 0x419bd0, (priv->tp_total << 8) |
+				       priv->magic_not_rop_nr |
+				       data2[0]);
+		nv_wr32(dev, 0x419be4, data2[1]);
+		for (i = 0; i < 6; i++)
+			nv_wr32(dev, 0x419b00 + (i * 4), data[i]);
+
+		// UNK78xx
+		nv_wr32(dev, 0x4078bc, (priv->tp_total << 8) |
+					priv->magic_not_rop_nr);
+		for (i = 0; i < 6; i++)
+			nv_wr32(dev, 0x40780c + (i * 4), data[i]);
+	}
+
+	if (1) {
+		u32 tp_mask = 0, tp_set = 0;
+		u8  tpnr[GPC_MAX];
+
+		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]--;
+
+			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, 0x400208, 0x80000000);
+
+	nv_icmd(dev, 0x00001000, 0x00000004);
+	nv_icmd(dev, 0x000000a9, 0x0000ffff);
+	nv_icmd(dev, 0x00000038, 0x0fac6881);
+	nv_icmd(dev, 0x0000003d, 0x00000001);
+	nv_icmd(dev, 0x000000e8, 0x00000400);
+	nv_icmd(dev, 0x000000e9, 0x00000400);
+	nv_icmd(dev, 0x000000ea, 0x00000400);
+	nv_icmd(dev, 0x000000eb, 0x00000400);
+	nv_icmd(dev, 0x000000ec, 0x00000400);
+	nv_icmd(dev, 0x000000ed, 0x00000400);
+	nv_icmd(dev, 0x000000ee, 0x00000400);
+	nv_icmd(dev, 0x000000ef, 0x00000400);
+	nv_icmd(dev, 0x00000078, 0x00000300);
+	nv_icmd(dev, 0x00000079, 0x00000300);
+	nv_icmd(dev, 0x0000007a, 0x00000300);
+	nv_icmd(dev, 0x0000007b, 0x00000300);
+	nv_icmd(dev, 0x0000007c, 0x00000300);
+	nv_icmd(dev, 0x0000007d, 0x00000300);
+	nv_icmd(dev, 0x0000007e, 0x00000300);
+	nv_icmd(dev, 0x0000007f, 0x00000300);
+	nv_icmd(dev, 0x00000050, 0x00000011);
+	nv_icmd(dev, 0x00000058, 0x00000008);
+	nv_icmd(dev, 0x00000059, 0x00000008);
+	nv_icmd(dev, 0x0000005a, 0x00000008);
+	nv_icmd(dev, 0x0000005b, 0x00000008);
+	nv_icmd(dev, 0x0000005c, 0x00000008);
+	nv_icmd(dev, 0x0000005d, 0x00000008);
+	nv_icmd(dev, 0x0000005e, 0x00000008);
+	nv_icmd(dev, 0x0000005f, 0x00000008);
+	nv_icmd(dev, 0x00000208, 0x00000001);
+	nv_icmd(dev, 0x00000209, 0x00000001);
+	nv_icmd(dev, 0x0000020a, 0x00000001);
+	nv_icmd(dev, 0x0000020b, 0x00000001);
+	nv_icmd(dev, 0x0000020c, 0x00000001);
+	nv_icmd(dev, 0x0000020d, 0x00000001);
+	nv_icmd(dev, 0x0000020e, 0x00000001);
+	nv_icmd(dev, 0x0000020f, 0x00000001);
+	nv_icmd(dev, 0x00000081, 0x00000001);
+	nv_icmd(dev, 0x00000085, 0x00000004);
+	nv_icmd(dev, 0x00000088, 0x00000400);
+	nv_icmd(dev, 0x00000090, 0x00000300);
+	nv_icmd(dev, 0x00000098, 0x00001001);
+	nv_icmd(dev, 0x000000e3, 0x00000001);
+	nv_icmd(dev, 0x000000da, 0x00000001);
+	nv_icmd(dev, 0x000000f8, 0x00000003);
+	nv_icmd(dev, 0x000000fa, 0x00000001);
+	nv_icmd(dev, 0x0000009f, 0x0000ffff);
+	nv_icmd(dev, 0x000000a0, 0x0000ffff);
+	nv_icmd(dev, 0x000000a1, 0x0000ffff);
+	nv_icmd(dev, 0x000000a2, 0x0000ffff);
+	nv_icmd(dev, 0x000000b1, 0x00000001);
+	nv_icmd(dev, 0x000000b2, 0x00000000);
+	nv_icmd(dev, 0x000000b3, 0x00000000);
+	nv_icmd(dev, 0x000000b4, 0x00000000);
+	nv_icmd(dev, 0x000000b5, 0x00000000);
+	nv_icmd(dev, 0x000000b6, 0x00000000);
+	nv_icmd(dev, 0x000000b7, 0x00000000);
+	nv_icmd(dev, 0x000000b8, 0x00000000);
+	nv_icmd(dev, 0x000000b9, 0x00000000);
+	nv_icmd(dev, 0x000000ba, 0x00000000);
+	nv_icmd(dev, 0x000000bb, 0x00000000);
+	nv_icmd(dev, 0x000000bc, 0x00000000);
+	nv_icmd(dev, 0x000000bd, 0x00000000);
+	nv_icmd(dev, 0x000000be, 0x00000000);
+	nv_icmd(dev, 0x000000bf, 0x00000000);
+	nv_icmd(dev, 0x000000c0, 0x00000000);
+	nv_icmd(dev, 0x000000c1, 0x00000000);
+	nv_icmd(dev, 0x000000c2, 0x00000000);
+	nv_icmd(dev, 0x000000c3, 0x00000000);
+	nv_icmd(dev, 0x000000c4, 0x00000000);
+	nv_icmd(dev, 0x000000c5, 0x00000000);
+	nv_icmd(dev, 0x000000c6, 0x00000000);
+	nv_icmd(dev, 0x000000c7, 0x00000000);
+	nv_icmd(dev, 0x000000c8, 0x00000000);
+	nv_icmd(dev, 0x000000c9, 0x00000000);
+	nv_icmd(dev, 0x000000ca, 0x00000000);
+	nv_icmd(dev, 0x000000cb, 0x00000000);
+	nv_icmd(dev, 0x000000cc, 0x00000000);
+	nv_icmd(dev, 0x000000cd, 0x00000000);
+	nv_icmd(dev, 0x000000ce, 0x00000000);
+	nv_icmd(dev, 0x000000cf, 0x00000000);
+	nv_icmd(dev, 0x000000d0, 0x00000000);
+	nv_icmd(dev, 0x000000d1, 0x00000000);
+	nv_icmd(dev, 0x000000d2, 0x00000000);
+	nv_icmd(dev, 0x000000d3, 0x00000000);
+	nv_icmd(dev, 0x000000d4, 0x00000000);
+	nv_icmd(dev, 0x000000d5, 0x00000000);
+	nv_icmd(dev, 0x000000d6, 0x00000000);
+	nv_icmd(dev, 0x000000d7, 0x00000000);
+	nv_icmd(dev, 0x000000d8, 0x00000000);
+	nv_icmd(dev, 0x000000d9, 0x00000000);
+	nv_icmd(dev, 0x00000210, 0x00000040);
+	nv_icmd(dev, 0x00000211, 0x00000040);
+	nv_icmd(dev, 0x00000212, 0x00000040);
+	nv_icmd(dev, 0x00000213, 0x00000040);
+	nv_icmd(dev, 0x00000214, 0x00000040);
+	nv_icmd(dev, 0x00000215, 0x00000040);
+	nv_icmd(dev, 0x00000216, 0x00000040);
+	nv_icmd(dev, 0x00000217, 0x00000040);
+	nv_icmd(dev, 0x00000218, 0x0000c080);
+	nv_icmd(dev, 0x00000219, 0x0000c080);
+	nv_icmd(dev, 0x0000021a, 0x0000c080);
+	nv_icmd(dev, 0x0000021b, 0x0000c080);
+	nv_icmd(dev, 0x0000021c, 0x0000c080);
+	nv_icmd(dev, 0x0000021d, 0x0000c080);
+	nv_icmd(dev, 0x0000021e, 0x0000c080);
+	nv_icmd(dev, 0x0000021f, 0x0000c080);
+	nv_icmd(dev, 0x000000ad, 0x0000013e);
+	nv_icmd(dev, 0x000000e1, 0x00000010);
+	nv_icmd(dev, 0x00000290, 0x00000000);
+	nv_icmd(dev, 0x00000291, 0x00000000);
+	nv_icmd(dev, 0x00000292, 0x00000000);
+	nv_icmd(dev, 0x00000293, 0x00000000);
+	nv_icmd(dev, 0x00000294, 0x00000000);
+	nv_icmd(dev, 0x00000295, 0x00000000);
+	nv_icmd(dev, 0x00000296, 0x00000000);
+	nv_icmd(dev, 0x00000297, 0x00000000);
+	nv_icmd(dev, 0x00000298, 0x00000000);
+	nv_icmd(dev, 0x00000299, 0x00000000);
+	nv_icmd(dev, 0x0000029a, 0x00000000);
+	nv_icmd(dev, 0x0000029b, 0x00000000);
+	nv_icmd(dev, 0x0000029c, 0x00000000);
+	nv_icmd(dev, 0x0000029d, 0x00000000);
+	nv_icmd(dev, 0x0000029e, 0x00000000);
+	nv_icmd(dev, 0x0000029f, 0x00000000);
+	nv_icmd(dev, 0x000003b0, 0x00000000);
+	nv_icmd(dev, 0x000003b1, 0x00000000);
+	nv_icmd(dev, 0x000003b2, 0x00000000);
+	nv_icmd(dev, 0x000003b3, 0x00000000);
+	nv_icmd(dev, 0x000003b4, 0x00000000);
+	nv_icmd(dev, 0x000003b5, 0x00000000);
+	nv_icmd(dev, 0x000003b6, 0x00000000);
+	nv_icmd(dev, 0x000003b7, 0x00000000);
+	nv_icmd(dev, 0x000003b8, 0x00000000);
+	nv_icmd(dev, 0x000003b9, 0x00000000);
+	nv_icmd(dev, 0x000003ba, 0x00000000);
+	nv_icmd(dev, 0x000003bb, 0x00000000);
+	nv_icmd(dev, 0x000003bc, 0x00000000);
+	nv_icmd(dev, 0x000003bd, 0x00000000);
+	nv_icmd(dev, 0x000003be, 0x00000000);
+	nv_icmd(dev, 0x000003bf, 0x00000000);
+	nv_icmd(dev, 0x000002a0, 0x00000000);
+	nv_icmd(dev, 0x000002a1, 0x00000000);
+	nv_icmd(dev, 0x000002a2, 0x00000000);
+	nv_icmd(dev, 0x000002a3, 0x00000000);
+	nv_icmd(dev, 0x000002a4, 0x00000000);
+	nv_icmd(dev, 0x000002a5, 0x00000000);
+	nv_icmd(dev, 0x000002a6, 0x00000000);
+	nv_icmd(dev, 0x000002a7, 0x00000000);
+	nv_icmd(dev, 0x000002a8, 0x00000000);
+	nv_icmd(dev, 0x000002a9, 0x00000000);
+	nv_icmd(dev, 0x000002aa, 0x00000000);
+	nv_icmd(dev, 0x000002ab, 0x00000000);
+	nv_icmd(dev, 0x000002ac, 0x00000000);
+	nv_icmd(dev, 0x000002ad, 0x00000000);
+	nv_icmd(dev, 0x000002ae, 0x00000000);
+	nv_icmd(dev, 0x000002af, 0x00000000);
+	nv_icmd(dev, 0x00000420, 0x00000000);
+	nv_icmd(dev, 0x00000421, 0x00000000);
+	nv_icmd(dev, 0x00000422, 0x00000000);
+	nv_icmd(dev, 0x00000423, 0x00000000);
+	nv_icmd(dev, 0x00000424, 0x00000000);
+	nv_icmd(dev, 0x00000425, 0x00000000);
+	nv_icmd(dev, 0x00000426, 0x00000000);
+	nv_icmd(dev, 0x00000427, 0x00000000);
+	nv_icmd(dev, 0x00000428, 0x00000000);
+	nv_icmd(dev, 0x00000429, 0x00000000);
+	nv_icmd(dev, 0x0000042a, 0x00000000);
+	nv_icmd(dev, 0x0000042b, 0x00000000);
+	nv_icmd(dev, 0x0000042c, 0x00000000);
+	nv_icmd(dev, 0x0000042d, 0x00000000);
+	nv_icmd(dev, 0x0000042e, 0x00000000);
+	nv_icmd(dev, 0x0000042f, 0x00000000);
+	nv_icmd(dev, 0x000002b0, 0x00000000);
+	nv_icmd(dev, 0x000002b1, 0x00000000);
+	nv_icmd(dev, 0x000002b2, 0x00000000);
+	nv_icmd(dev, 0x000002b3, 0x00000000);
+	nv_icmd(dev, 0x000002b4, 0x00000000);
+	nv_icmd(dev, 0x000002b5, 0x00000000);
+	nv_icmd(dev, 0x000002b6, 0x00000000);
+	nv_icmd(dev, 0x000002b7, 0x00000000);
+	nv_icmd(dev, 0x000002b8, 0x00000000);
+	nv_icmd(dev, 0x000002b9, 0x00000000);
+	nv_icmd(dev, 0x000002ba, 0x00000000);
+	nv_icmd(dev, 0x000002bb, 0x00000000);
+	nv_icmd(dev, 0x000002bc, 0x00000000);
+	nv_icmd(dev, 0x000002bd, 0x00000000);
+	nv_icmd(dev, 0x000002be, 0x00000000);
+	nv_icmd(dev, 0x000002bf, 0x00000000);
+	nv_icmd(dev, 0x00000430, 0x00000000);
+	nv_icmd(dev, 0x00000431, 0x00000000);
+	nv_icmd(dev, 0x00000432, 0x00000000);
+	nv_icmd(dev, 0x00000433, 0x00000000);
+	nv_icmd(dev, 0x00000434, 0x00000000);
+	nv_icmd(dev, 0x00000435, 0x00000000);
+	nv_icmd(dev, 0x00000436, 0x00000000);
+	nv_icmd(dev, 0x00000437, 0x00000000);
+	nv_icmd(dev, 0x00000438, 0x00000000);
+	nv_icmd(dev, 0x00000439, 0x00000000);
+	nv_icmd(dev, 0x0000043a, 0x00000000);
+	nv_icmd(dev, 0x0000043b, 0x00000000);
+	nv_icmd(dev, 0x0000043c, 0x00000000);
+	nv_icmd(dev, 0x0000043d, 0x00000000);
+	nv_icmd(dev, 0x0000043e, 0x00000000);
+	nv_icmd(dev, 0x0000043f, 0x00000000);
+	nv_icmd(dev, 0x000002c0, 0x00000000);
+	nv_icmd(dev, 0x000002c1, 0x00000000);
+	nv_icmd(dev, 0x000002c2, 0x00000000);
+	nv_icmd(dev, 0x000002c3, 0x00000000);
+	nv_icmd(dev, 0x000002c4, 0x00000000);
+	nv_icmd(dev, 0x000002c5, 0x00000000);
+	nv_icmd(dev, 0x000002c6, 0x00000000);
+	nv_icmd(dev, 0x000002c7, 0x00000000);
+	nv_icmd(dev, 0x000002c8, 0x00000000);
+	nv_icmd(dev, 0x000002c9, 0x00000000);
+	nv_icmd(dev, 0x000002ca, 0x00000000);
+	nv_icmd(dev, 0x000002cb, 0x00000000);
+	nv_icmd(dev, 0x000002cc, 0x00000000);
+	nv_icmd(dev, 0x000002cd, 0x00000000);
+	nv_icmd(dev, 0x000002ce, 0x00000000);
+	nv_icmd(dev, 0x000002cf, 0x00000000);
+	nv_icmd(dev, 0x000004d0, 0x00000000);
+	nv_icmd(dev, 0x000004d1, 0x00000000);
+	nv_icmd(dev, 0x000004d2, 0x00000000);
+	nv_icmd(dev, 0x000004d3, 0x00000000);
+	nv_icmd(dev, 0x000004d4, 0x00000000);
+	nv_icmd(dev, 0x000004d5, 0x00000000);
+	nv_icmd(dev, 0x000004d6, 0x00000000);
+	nv_icmd(dev, 0x000004d7, 0x00000000);
+	nv_icmd(dev, 0x000004d8, 0x00000000);
+	nv_icmd(dev, 0x000004d9, 0x00000000);
+	nv_icmd(dev, 0x000004da, 0x00000000);
+	nv_icmd(dev, 0x000004db, 0x00000000);
+	nv_icmd(dev, 0x000004dc, 0x00000000);
+	nv_icmd(dev, 0x000004dd, 0x00000000);
+	nv_icmd(dev, 0x000004de, 0x00000000);
+	nv_icmd(dev, 0x000004df, 0x00000000);
+	nv_icmd(dev, 0x00000720, 0x00000000);
+	nv_icmd(dev, 0x00000721, 0x00000000);
+	nv_icmd(dev, 0x00000722, 0x00000000);
+	nv_icmd(dev, 0x00000723, 0x00000000);
+	nv_icmd(dev, 0x00000724, 0x00000000);
+	nv_icmd(dev, 0x00000725, 0x00000000);
+	nv_icmd(dev, 0x00000726, 0x00000000);
+	nv_icmd(dev, 0x00000727, 0x00000000);
+	nv_icmd(dev, 0x00000728, 0x00000000);
+	nv_icmd(dev, 0x00000729, 0x00000000);
+	nv_icmd(dev, 0x0000072a, 0x00000000);
+	nv_icmd(dev, 0x0000072b, 0x00000000);
+	nv_icmd(dev, 0x0000072c, 0x00000000);
+	nv_icmd(dev, 0x0000072d, 0x00000000);
+	nv_icmd(dev, 0x0000072e, 0x00000000);
+	nv_icmd(dev, 0x0000072f, 0x00000000);
+	nv_icmd(dev, 0x000008c0, 0x00000000);
+	nv_icmd(dev, 0x000008c1, 0x00000000);
+	nv_icmd(dev, 0x000008c2, 0x00000000);
+	nv_icmd(dev, 0x000008c3, 0x00000000);
+	nv_icmd(dev, 0x000008c4, 0x00000000);
+	nv_icmd(dev, 0x000008c5, 0x00000000);
+	nv_icmd(dev, 0x000008c6, 0x00000000);
+	nv_icmd(dev, 0x000008c7, 0x00000000);
+	nv_icmd(dev, 0x000008c8, 0x00000000);
+	nv_icmd(dev, 0x000008c9, 0x00000000);
+	nv_icmd(dev, 0x000008ca, 0x00000000);
+	nv_icmd(dev, 0x000008cb, 0x00000000);
+	nv_icmd(dev, 0x000008cc, 0x00000000);
+	nv_icmd(dev, 0x000008cd, 0x00000000);
+	nv_icmd(dev, 0x000008ce, 0x00000000);
+	nv_icmd(dev, 0x000008cf, 0x00000000);
+	nv_icmd(dev, 0x00000890, 0x00000000);
+	nv_icmd(dev, 0x00000891, 0x00000000);
+	nv_icmd(dev, 0x00000892, 0x00000000);
+	nv_icmd(dev, 0x00000893, 0x00000000);
+	nv_icmd(dev, 0x00000894, 0x00000000);
+	nv_icmd(dev, 0x00000895, 0x00000000);
+	nv_icmd(dev, 0x00000896, 0x00000000);
+	nv_icmd(dev, 0x00000897, 0x00000000);
+	nv_icmd(dev, 0x00000898, 0x00000000);
+	nv_icmd(dev, 0x00000899, 0x00000000);
+	nv_icmd(dev, 0x0000089a, 0x00000000);
+	nv_icmd(dev, 0x0000089b, 0x00000000);
+	nv_icmd(dev, 0x0000089c, 0x00000000);
+	nv_icmd(dev, 0x0000089d, 0x00000000);
+	nv_icmd(dev, 0x0000089e, 0x00000000);
+	nv_icmd(dev, 0x0000089f, 0x00000000);
+	nv_icmd(dev, 0x000008e0, 0x00000000);
+	nv_icmd(dev, 0x000008e1, 0x00000000);
+	nv_icmd(dev, 0x000008e2, 0x00000000);
+	nv_icmd(dev, 0x000008e3, 0x00000000);
+	nv_icmd(dev, 0x000008e4, 0x00000000);
+	nv_icmd(dev, 0x000008e5, 0x00000000);
+	nv_icmd(dev, 0x000008e6, 0x00000000);
+	nv_icmd(dev, 0x000008e7, 0x00000000);
+	nv_icmd(dev, 0x000008e8, 0x00000000);
+	nv_icmd(dev, 0x000008e9, 0x00000000);
+	nv_icmd(dev, 0x000008ea, 0x00000000);
+	nv_icmd(dev, 0x000008eb, 0x00000000);
+	nv_icmd(dev, 0x000008ec, 0x00000000);
+	nv_icmd(dev, 0x000008ed, 0x00000000);
+	nv_icmd(dev, 0x000008ee, 0x00000000);
+	nv_icmd(dev, 0x000008ef, 0x00000000);
+	nv_icmd(dev, 0x000008a0, 0x00000000);
+	nv_icmd(dev, 0x000008a1, 0x00000000);
+	nv_icmd(dev, 0x000008a2, 0x00000000);
+	nv_icmd(dev, 0x000008a3, 0x00000000);
+	nv_icmd(dev, 0x000008a4, 0x00000000);
+	nv_icmd(dev, 0x000008a5, 0x00000000);
+	nv_icmd(dev, 0x000008a6, 0x00000000);
+	nv_icmd(dev, 0x000008a7, 0x00000000);
+	nv_icmd(dev, 0x000008a8, 0x00000000);
+	nv_icmd(dev, 0x000008a9, 0x00000000);
+	nv_icmd(dev, 0x000008aa, 0x00000000);
+	nv_icmd(dev, 0x000008ab, 0x00000000);
+	nv_icmd(dev, 0x000008ac, 0x00000000);
+	nv_icmd(dev, 0x000008ad, 0x00000000);
+	nv_icmd(dev, 0x000008ae, 0x00000000);
+	nv_icmd(dev, 0x000008af, 0x00000000);
+	nv_icmd(dev, 0x000008f0, 0x00000000);
+	nv_icmd(dev, 0x000008f1, 0x00000000);
+	nv_icmd(dev, 0x000008f2, 0x00000000);
+	nv_icmd(dev, 0x000008f3, 0x00000000);
+	nv_icmd(dev, 0x000008f4, 0x00000000);
+	nv_icmd(dev, 0x000008f5, 0x00000000);
+	nv_icmd(dev, 0x000008f6, 0x00000000);
+	nv_icmd(dev, 0x000008f7, 0x00000000);
+	nv_icmd(dev, 0x000008f8, 0x00000000);
+	nv_icmd(dev, 0x000008f9, 0x00000000);
+	nv_icmd(dev, 0x000008fa, 0x00000000);
+	nv_icmd(dev, 0x000008fb, 0x00000000);
+	nv_icmd(dev, 0x000008fc, 0x00000000);
+	nv_icmd(dev, 0x000008fd, 0x00000000);
+	nv_icmd(dev, 0x000008fe, 0x00000000);
+	nv_icmd(dev, 0x000008ff, 0x00000000);
+	nv_icmd(dev, 0x0000094c, 0x000000ff);
+	nv_icmd(dev, 0x0000094d, 0xffffffff);
+	nv_icmd(dev, 0x0000094e, 0x00000002);
+	nv_icmd(dev, 0x000002ec, 0x00000001);
+	nv_icmd(dev, 0x00000303, 0x00000001);
+	nv_icmd(dev, 0x000002e6, 0x00000001);
+	nv_icmd(dev, 0x00000466, 0x00000052);
+	nv_icmd(dev, 0x00000301, 0x3f800000);
+	nv_icmd(dev, 0x00000304, 0x30201000);
+	nv_icmd(dev, 0x00000305, 0x70605040);
+	nv_icmd(dev, 0x00000306, 0xb8a89888);
+	nv_icmd(dev, 0x00000307, 0xf8e8d8c8);
+	nv_icmd(dev, 0x0000030a, 0x00ffff00);
+	nv_icmd(dev, 0x0000030b, 0x0000001a);
+	nv_icmd(dev, 0x0000030c, 0x00000001);
+	nv_icmd(dev, 0x00000318, 0x00000001);
+	nv_icmd(dev, 0x00000340, 0x00000000);
+	nv_icmd(dev, 0x00000375, 0x00000001);
+	nv_icmd(dev, 0x00000351, 0x00000100);
+	nv_icmd(dev, 0x0000037d, 0x00000006);
+	nv_icmd(dev, 0x000003a0, 0x00000002);
+	nv_icmd(dev, 0x000003aa, 0x00000001);
+	nv_icmd(dev, 0x000003a9, 0x00000001);
+	nv_icmd(dev, 0x00000380, 0x00000001);
+	nv_icmd(dev, 0x00000360, 0x00000040);
+	nv_icmd(dev, 0x00000366, 0x00000000);
+	nv_icmd(dev, 0x00000367, 0x00000000);
+	nv_icmd(dev, 0x00000368, 0x00001fff);
+	nv_icmd(dev, 0x00000370, 0x00000000);
+	nv_icmd(dev, 0x00000371, 0x00000000);
+	nv_icmd(dev, 0x00000372, 0x003fffff);
+	nv_icmd(dev, 0x0000037a, 0x00000012);
+	nv_icmd(dev, 0x000005e0, 0x00000022);
+	nv_icmd(dev, 0x000005e1, 0x00000022);
+	nv_icmd(dev, 0x000005e2, 0x00000022);
+	nv_icmd(dev, 0x000005e3, 0x00000022);
+	nv_icmd(dev, 0x000005e4, 0x00000022);
+	nv_icmd(dev, 0x00000619, 0x00000003);
+	nv_icmd(dev, 0x00000811, 0x00000003);
+	nv_icmd(dev, 0x00000812, 0x00000004);
+	nv_icmd(dev, 0x00000813, 0x00000006);
+	nv_icmd(dev, 0x00000814, 0x00000008);
+	nv_icmd(dev, 0x00000815, 0x0000000b);
+	nv_icmd(dev, 0x00000800, 0x00000001);
+	nv_icmd(dev, 0x00000801, 0x00000001);
+	nv_icmd(dev, 0x00000802, 0x00000001);
+	nv_icmd(dev, 0x00000803, 0x00000001);
+	nv_icmd(dev, 0x00000804, 0x00000001);
+	nv_icmd(dev, 0x00000805, 0x00000001);
+	nv_icmd(dev, 0x00000632, 0x00000001);
+	nv_icmd(dev, 0x00000633, 0x00000002);
+	nv_icmd(dev, 0x00000634, 0x00000003);
+	nv_icmd(dev, 0x00000635, 0x00000004);
+	nv_icmd(dev, 0x00000654, 0x3f800000);
+	nv_icmd(dev, 0x00000657, 0x3f800000);
+	nv_icmd(dev, 0x00000655, 0x3f800000);
+	nv_icmd(dev, 0x00000656, 0x3f800000);
+	nv_icmd(dev, 0x000006cd, 0x3f800000);
+	nv_icmd(dev, 0x000007f5, 0x3f800000);
+	nv_icmd(dev, 0x000007dc, 0x39291909);
+	nv_icmd(dev, 0x000007dd, 0x79695949);
+	nv_icmd(dev, 0x000007de, 0xb9a99989);
+	nv_icmd(dev, 0x000007df, 0xf9e9d9c9);
+	nv_icmd(dev, 0x000007e8, 0x00003210);
+	nv_icmd(dev, 0x000007e9, 0x00007654);
+	nv_icmd(dev, 0x000007ea, 0x00000098);
+	nv_icmd(dev, 0x000007ec, 0x39291909);
+	nv_icmd(dev, 0x000007ed, 0x79695949);
+	nv_icmd(dev, 0x000007ee, 0xb9a99989);
+	nv_icmd(dev, 0x000007ef, 0xf9e9d9c9);
+	nv_icmd(dev, 0x000007f0, 0x00003210);
+	nv_icmd(dev, 0x000007f1, 0x00007654);
+	nv_icmd(dev, 0x000007f2, 0x00000098);
+	nv_icmd(dev, 0x000005a5, 0x00000001);
+	nv_icmd(dev, 0x00000980, 0x00000000);
+	nv_icmd(dev, 0x00000981, 0x00000000);
+	nv_icmd(dev, 0x00000982, 0x00000000);
+	nv_icmd(dev, 0x00000983, 0x00000000);
+	nv_icmd(dev, 0x00000984, 0x00000000);
+	nv_icmd(dev, 0x00000985, 0x00000000);
+	nv_icmd(dev, 0x00000986, 0x00000000);
+	nv_icmd(dev, 0x00000987, 0x00000000);
+	nv_icmd(dev, 0x00000988, 0x00000000);
+	nv_icmd(dev, 0x00000989, 0x00000000);
+	nv_icmd(dev, 0x0000098a, 0x00000000);
+	nv_icmd(dev, 0x0000098b, 0x00000000);
+	nv_icmd(dev, 0x0000098c, 0x00000000);
+	nv_icmd(dev, 0x0000098d, 0x00000000);
+	nv_icmd(dev, 0x0000098e, 0x00000000);
+	nv_icmd(dev, 0x0000098f, 0x00000000);
+	nv_icmd(dev, 0x00000990, 0x00000000);
+	nv_icmd(dev, 0x00000991, 0x00000000);
+	nv_icmd(dev, 0x00000992, 0x00000000);
+	nv_icmd(dev, 0x00000993, 0x00000000);
+	nv_icmd(dev, 0x00000994, 0x00000000);
+	nv_icmd(dev, 0x00000995, 0x00000000);
+	nv_icmd(dev, 0x00000996, 0x00000000);
+	nv_icmd(dev, 0x00000997, 0x00000000);
+	nv_icmd(dev, 0x00000998, 0x00000000);
+	nv_icmd(dev, 0x00000999, 0x00000000);
+	nv_icmd(dev, 0x0000099a, 0x00000000);
+	nv_icmd(dev, 0x0000099b, 0x00000000);
+	nv_icmd(dev, 0x0000099c, 0x00000000);
+	nv_icmd(dev, 0x0000099d, 0x00000000);
+	nv_icmd(dev, 0x0000099e, 0x00000000);
+	nv_icmd(dev, 0x0000099f, 0x00000000);
+	nv_icmd(dev, 0x000009a0, 0x00000000);
+	nv_icmd(dev, 0x000009a1, 0x00000000);
+	nv_icmd(dev, 0x000009a2, 0x00000000);
+	nv_icmd(dev, 0x000009a3, 0x00000000);
+	nv_icmd(dev, 0x000009a4, 0x00000000);
+	nv_icmd(dev, 0x000009a5, 0x00000000);
+	nv_icmd(dev, 0x000009a6, 0x00000000);
+	nv_icmd(dev, 0x000009a7, 0x00000000);
+	nv_icmd(dev, 0x000009a8, 0x00000000);
+	nv_icmd(dev, 0x000009a9, 0x00000000);
+	nv_icmd(dev, 0x000009aa, 0x00000000);
+	nv_icmd(dev, 0x000009ab, 0x00000000);
+	nv_icmd(dev, 0x000009ac, 0x00000000);
+	nv_icmd(dev, 0x000009ad, 0x00000000);
+	nv_icmd(dev, 0x000009ae, 0x00000000);
+	nv_icmd(dev, 0x000009af, 0x00000000);
+	nv_icmd(dev, 0x000009b0, 0x00000000);
+	nv_icmd(dev, 0x000009b1, 0x00000000);
+	nv_icmd(dev, 0x000009b2, 0x00000000);
+	nv_icmd(dev, 0x000009b3, 0x00000000);
+	nv_icmd(dev, 0x000009b4, 0x00000000);
+	nv_icmd(dev, 0x000009b5, 0x00000000);
+	nv_icmd(dev, 0x000009b6, 0x00000000);
+	nv_icmd(dev, 0x000009b7, 0x00000000);
+	nv_icmd(dev, 0x000009b8, 0x00000000);
+	nv_icmd(dev, 0x000009b9, 0x00000000);
+	nv_icmd(dev, 0x000009ba, 0x00000000);
+	nv_icmd(dev, 0x000009bb, 0x00000000);
+	nv_icmd(dev, 0x000009bc, 0x00000000);
+	nv_icmd(dev, 0x000009bd, 0x00000000);
+	nv_icmd(dev, 0x000009be, 0x00000000);
+	nv_icmd(dev, 0x000009bf, 0x00000000);
+	nv_icmd(dev, 0x000009c0, 0x00000000);
+	nv_icmd(dev, 0x000009c1, 0x00000000);
+	nv_icmd(dev, 0x000009c2, 0x00000000);
+	nv_icmd(dev, 0x000009c3, 0x00000000);
+	nv_icmd(dev, 0x000009c4, 0x00000000);
+	nv_icmd(dev, 0x000009c5, 0x00000000);
+	nv_icmd(dev, 0x000009c6, 0x00000000);
+	nv_icmd(dev, 0x000009c7, 0x00000000);
+	nv_icmd(dev, 0x000009c8, 0x00000000);
+	nv_icmd(dev, 0x000009c9, 0x00000000);
+	nv_icmd(dev, 0x000009ca, 0x00000000);
+	nv_icmd(dev, 0x000009cb, 0x00000000);
+	nv_icmd(dev, 0x000009cc, 0x00000000);
+	nv_icmd(dev, 0x000009cd, 0x00000000);
+	nv_icmd(dev, 0x000009ce, 0x00000000);
+	nv_icmd(dev, 0x000009cf, 0x00000000);
+	nv_icmd(dev, 0x000009d0, 0x00000000);
+	nv_icmd(dev, 0x000009d1, 0x00000000);
+	nv_icmd(dev, 0x000009d2, 0x00000000);
+	nv_icmd(dev, 0x000009d3, 0x00000000);
+	nv_icmd(dev, 0x000009d4, 0x00000000);
+	nv_icmd(dev, 0x000009d5, 0x00000000);
+	nv_icmd(dev, 0x000009d6, 0x00000000);
+	nv_icmd(dev, 0x000009d7, 0x00000000);
+	nv_icmd(dev, 0x000009d8, 0x00000000);
+	nv_icmd(dev, 0x000009d9, 0x00000000);
+	nv_icmd(dev, 0x000009da, 0x00000000);
+	nv_icmd(dev, 0x000009db, 0x00000000);
+	nv_icmd(dev, 0x000009dc, 0x00000000);
+	nv_icmd(dev, 0x000009dd, 0x00000000);
+	nv_icmd(dev, 0x000009de, 0x00000000);
+	nv_icmd(dev, 0x000009df, 0x00000000);
+	nv_icmd(dev, 0x000009e0, 0x00000000);
+	nv_icmd(dev, 0x000009e1, 0x00000000);
+	nv_icmd(dev, 0x000009e2, 0x00000000);
+	nv_icmd(dev, 0x000009e3, 0x00000000);
+	nv_icmd(dev, 0x000009e4, 0x00000000);
+	nv_icmd(dev, 0x000009e5, 0x00000000);
+	nv_icmd(dev, 0x000009e6, 0x00000000);
+	nv_icmd(dev, 0x000009e7, 0x00000000);
+	nv_icmd(dev, 0x000009e8, 0x00000000);
+	nv_icmd(dev, 0x000009e9, 0x00000000);
+	nv_icmd(dev, 0x000009ea, 0x00000000);
+	nv_icmd(dev, 0x000009eb, 0x00000000);
+	nv_icmd(dev, 0x000009ec, 0x00000000);
+	nv_icmd(dev, 0x000009ed, 0x00000000);
+	nv_icmd(dev, 0x000009ee, 0x00000000);
+	nv_icmd(dev, 0x000009ef, 0x00000000);
+	nv_icmd(dev, 0x000009f0, 0x00000000);
+	nv_icmd(dev, 0x000009f1, 0x00000000);
+	nv_icmd(dev, 0x000009f2, 0x00000000);
+	nv_icmd(dev, 0x000009f3, 0x00000000);
+	nv_icmd(dev, 0x000009f4, 0x00000000);
+	nv_icmd(dev, 0x000009f5, 0x00000000);
+	nv_icmd(dev, 0x000009f6, 0x00000000);
+	nv_icmd(dev, 0x000009f7, 0x00000000);
+	nv_icmd(dev, 0x000009f8, 0x00000000);
+	nv_icmd(dev, 0x000009f9, 0x00000000);
+	nv_icmd(dev, 0x000009fa, 0x00000000);
+	nv_icmd(dev, 0x000009fb, 0x00000000);
+	nv_icmd(dev, 0x000009fc, 0x00000000);
+	nv_icmd(dev, 0x000009fd, 0x00000000);
+	nv_icmd(dev, 0x000009fe, 0x00000000);
+	nv_icmd(dev, 0x000009ff, 0x00000000);
+	nv_icmd(dev, 0x00000468, 0x00000004);
+	nv_icmd(dev, 0x0000046c, 0x00000001);
+	nv_icmd(dev, 0x00000470, 0x00000000);
+	nv_icmd(dev, 0x00000471, 0x00000000);
+	nv_icmd(dev, 0x00000472, 0x00000000);
+	nv_icmd(dev, 0x00000473, 0x00000000);
+	nv_icmd(dev, 0x00000474, 0x00000000);
+	nv_icmd(dev, 0x00000475, 0x00000000);
+	nv_icmd(dev, 0x00000476, 0x00000000);
+	nv_icmd(dev, 0x00000477, 0x00000000);
+	nv_icmd(dev, 0x00000478, 0x00000000);
+	nv_icmd(dev, 0x00000479, 0x00000000);
+	nv_icmd(dev, 0x0000047a, 0x00000000);
+	nv_icmd(dev, 0x0000047b, 0x00000000);
+	nv_icmd(dev, 0x0000047c, 0x00000000);
+	nv_icmd(dev, 0x0000047d, 0x00000000);
+	nv_icmd(dev, 0x0000047e, 0x00000000);
+	nv_icmd(dev, 0x0000047f, 0x00000000);
+	nv_icmd(dev, 0x00000480, 0x00000000);
+	nv_icmd(dev, 0x00000481, 0x00000000);
+	nv_icmd(dev, 0x00000482, 0x00000000);
+	nv_icmd(dev, 0x00000483, 0x00000000);
+	nv_icmd(dev, 0x00000484, 0x00000000);
+	nv_icmd(dev, 0x00000485, 0x00000000);
+	nv_icmd(dev, 0x00000486, 0x00000000);
+	nv_icmd(dev, 0x00000487, 0x00000000);
+	nv_icmd(dev, 0x00000488, 0x00000000);
+	nv_icmd(dev, 0x00000489, 0x00000000);
+	nv_icmd(dev, 0x0000048a, 0x00000000);
+	nv_icmd(dev, 0x0000048b, 0x00000000);
+	nv_icmd(dev, 0x0000048c, 0x00000000);
+	nv_icmd(dev, 0x0000048d, 0x00000000);
+	nv_icmd(dev, 0x0000048e, 0x00000000);
+	nv_icmd(dev, 0x0000048f, 0x00000000);
+	nv_icmd(dev, 0x00000490, 0x00000000);
+	nv_icmd(dev, 0x00000491, 0x00000000);
+	nv_icmd(dev, 0x00000492, 0x00000000);
+	nv_icmd(dev, 0x00000493, 0x00000000);
+	nv_icmd(dev, 0x00000494, 0x00000000);
+	nv_icmd(dev, 0x00000495, 0x00000000);
+	nv_icmd(dev, 0x00000496, 0x00000000);
+	nv_icmd(dev, 0x00000497, 0x00000000);
+	nv_icmd(dev, 0x00000498, 0x00000000);
+	nv_icmd(dev, 0x00000499, 0x00000000);
+	nv_icmd(dev, 0x0000049a, 0x00000000);
+	nv_icmd(dev, 0x0000049b, 0x00000000);
+	nv_icmd(dev, 0x0000049c, 0x00000000);
+	nv_icmd(dev, 0x0000049d, 0x00000000);
+	nv_icmd(dev, 0x0000049e, 0x00000000);
+	nv_icmd(dev, 0x0000049f, 0x00000000);
+	nv_icmd(dev, 0x000004a0, 0x00000000);
+	nv_icmd(dev, 0x000004a1, 0x00000000);
+	nv_icmd(dev, 0x000004a2, 0x00000000);
+	nv_icmd(dev, 0x000004a3, 0x00000000);
+	nv_icmd(dev, 0x000004a4, 0x00000000);
+	nv_icmd(dev, 0x000004a5, 0x00000000);
+	nv_icmd(dev, 0x000004a6, 0x00000000);
+	nv_icmd(dev, 0x000004a7, 0x00000000);
+	nv_icmd(dev, 0x000004a8, 0x00000000);
+	nv_icmd(dev, 0x000004a9, 0x00000000);
+	nv_icmd(dev, 0x000004aa, 0x00000000);
+	nv_icmd(dev, 0x000004ab, 0x00000000);
+	nv_icmd(dev, 0x000004ac, 0x00000000);
+	nv_icmd(dev, 0x000004ad, 0x00000000);
+	nv_icmd(dev, 0x000004ae, 0x00000000);
+	nv_icmd(dev, 0x000004af, 0x00000000);
+	nv_icmd(dev, 0x000004b0, 0x00000000);
+	nv_icmd(dev, 0x000004b1, 0x00000000);
+	nv_icmd(dev, 0x000004b2, 0x00000000);
+	nv_icmd(dev, 0x000004b3, 0x00000000);
+	nv_icmd(dev, 0x000004b4, 0x00000000);
+	nv_icmd(dev, 0x000004b5, 0x00000000);
+	nv_icmd(dev, 0x000004b6, 0x00000000);
+	nv_icmd(dev, 0x000004b7, 0x00000000);
+	nv_icmd(dev, 0x000004b8, 0x00000000);
+	nv_icmd(dev, 0x000004b9, 0x00000000);
+	nv_icmd(dev, 0x000004ba, 0x00000000);
+	nv_icmd(dev, 0x000004bb, 0x00000000);
+	nv_icmd(dev, 0x000004bc, 0x00000000);
+	nv_icmd(dev, 0x000004bd, 0x00000000);
+	nv_icmd(dev, 0x000004be, 0x00000000);
+	nv_icmd(dev, 0x000004bf, 0x00000000);
+	nv_icmd(dev, 0x000004c0, 0x00000000);
+	nv_icmd(dev, 0x000004c1, 0x00000000);
+	nv_icmd(dev, 0x000004c2, 0x00000000);
+	nv_icmd(dev, 0x000004c3, 0x00000000);
+	nv_icmd(dev, 0x000004c4, 0x00000000);
+	nv_icmd(dev, 0x000004c5, 0x00000000);
+	nv_icmd(dev, 0x000004c6, 0x00000000);
+	nv_icmd(dev, 0x000004c7, 0x00000000);
+	nv_icmd(dev, 0x000004c8, 0x00000000);
+	nv_icmd(dev, 0x000004c9, 0x00000000);
+	nv_icmd(dev, 0x000004ca, 0x00000000);
+	nv_icmd(dev, 0x000004cb, 0x00000000);
+	nv_icmd(dev, 0x000004cc, 0x00000000);
+	nv_icmd(dev, 0x000004cd, 0x00000000);
+	nv_icmd(dev, 0x000004ce, 0x00000000);
+	nv_icmd(dev, 0x000004cf, 0x00000000);
+	nv_icmd(dev, 0x00000510, 0x3f800000);
+	nv_icmd(dev, 0x00000511, 0x3f800000);
+	nv_icmd(dev, 0x00000512, 0x3f800000);
+	nv_icmd(dev, 0x00000513, 0x3f800000);
+	nv_icmd(dev, 0x00000514, 0x3f800000);
+	nv_icmd(dev, 0x00000515, 0x3f800000);
+	nv_icmd(dev, 0x00000516, 0x3f800000);
+	nv_icmd(dev, 0x00000517, 0x3f800000);
+	nv_icmd(dev, 0x00000518, 0x3f800000);
+	nv_icmd(dev, 0x00000519, 0x3f800000);
+	nv_icmd(dev, 0x0000051a, 0x3f800000);
+	nv_icmd(dev, 0x0000051b, 0x3f800000);
+	nv_icmd(dev, 0x0000051c, 0x3f800000);
+	nv_icmd(dev, 0x0000051d, 0x3f800000);
+	nv_icmd(dev, 0x0000051e, 0x3f800000);
+	nv_icmd(dev, 0x0000051f, 0x3f800000);
+	nv_icmd(dev, 0x00000520, 0x000002b6);
+	nv_icmd(dev, 0x00000529, 0x00000001);
+	nv_icmd(dev, 0x00000530, 0xffff0000);
+	nv_icmd(dev, 0x00000531, 0xffff0000);
+	nv_icmd(dev, 0x00000532, 0xffff0000);
+	nv_icmd(dev, 0x00000533, 0xffff0000);
+	nv_icmd(dev, 0x00000534, 0xffff0000);
+	nv_icmd(dev, 0x00000535, 0xffff0000);
+	nv_icmd(dev, 0x00000536, 0xffff0000);
+	nv_icmd(dev, 0x00000537, 0xffff0000);
+	nv_icmd(dev, 0x00000538, 0xffff0000);
+	nv_icmd(dev, 0x00000539, 0xffff0000);
+	nv_icmd(dev, 0x0000053a, 0xffff0000);
+	nv_icmd(dev, 0x0000053b, 0xffff0000);
+	nv_icmd(dev, 0x0000053c, 0xffff0000);
+	nv_icmd(dev, 0x0000053d, 0xffff0000);
+	nv_icmd(dev, 0x0000053e, 0xffff0000);
+	nv_icmd(dev, 0x0000053f, 0xffff0000);
+	nv_icmd(dev, 0x00000585, 0x0000003f);
+	nv_icmd(dev, 0x00000576, 0x00000003);
+	nv_icmd(dev, 0x00000586, 0x00000040);
+	nv_icmd(dev, 0x00000582, 0x00000080);
+	nv_icmd(dev, 0x00000583, 0x00000080);
+	nv_icmd(dev, 0x000005c2, 0x00000001);
+	nv_icmd(dev, 0x00000638, 0x00000001);
+	nv_icmd(dev, 0x00000639, 0x00000001);
+	nv_icmd(dev, 0x0000063a, 0x00000002);
+	nv_icmd(dev, 0x0000063b, 0x00000001);
+	nv_icmd(dev, 0x0000063c, 0x00000001);
+	nv_icmd(dev, 0x0000063d, 0x00000002);
+	nv_icmd(dev, 0x0000063e, 0x00000001);
+	nv_icmd(dev, 0x000008b8, 0x00000001);
+	nv_icmd(dev, 0x000008b9, 0x00000001);
+	nv_icmd(dev, 0x000008ba, 0x00000001);
+	nv_icmd(dev, 0x000008bb, 0x00000001);
+	nv_icmd(dev, 0x000008bc, 0x00000001);
+	nv_icmd(dev, 0x000008bd, 0x00000001);
+	nv_icmd(dev, 0x000008be, 0x00000001);
+	nv_icmd(dev, 0x000008bf, 0x00000001);
+	nv_icmd(dev, 0x00000900, 0x00000001);
+	nv_icmd(dev, 0x00000901, 0x00000001);
+	nv_icmd(dev, 0x00000902, 0x00000001);
+	nv_icmd(dev, 0x00000903, 0x00000001);
+	nv_icmd(dev, 0x00000904, 0x00000001);
+	nv_icmd(dev, 0x00000905, 0x00000001);
+	nv_icmd(dev, 0x00000906, 0x00000001);
+	nv_icmd(dev, 0x00000907, 0x00000001);
+	nv_icmd(dev, 0x00000908, 0x00000002);
+	nv_icmd(dev, 0x00000909, 0x00000002);
+	nv_icmd(dev, 0x0000090a, 0x00000002);
+	nv_icmd(dev, 0x0000090b, 0x00000002);
+	nv_icmd(dev, 0x0000090c, 0x00000002);
+	nv_icmd(dev, 0x0000090d, 0x00000002);
+	nv_icmd(dev, 0x0000090e, 0x00000002);
+	nv_icmd(dev, 0x0000090f, 0x00000002);
+	nv_icmd(dev, 0x00000910, 0x00000001);
+	nv_icmd(dev, 0x00000911, 0x00000001);
+	nv_icmd(dev, 0x00000912, 0x00000001);
+	nv_icmd(dev, 0x00000913, 0x00000001);
+	nv_icmd(dev, 0x00000914, 0x00000001);
+	nv_icmd(dev, 0x00000915, 0x00000001);
+	nv_icmd(dev, 0x00000916, 0x00000001);
+	nv_icmd(dev, 0x00000917, 0x00000001);
+	nv_icmd(dev, 0x00000918, 0x00000001);
+	nv_icmd(dev, 0x00000919, 0x00000001);
+	nv_icmd(dev, 0x0000091a, 0x00000001);
+	nv_icmd(dev, 0x0000091b, 0x00000001);
+	nv_icmd(dev, 0x0000091c, 0x00000001);
+	nv_icmd(dev, 0x0000091d, 0x00000001);
+	nv_icmd(dev, 0x0000091e, 0x00000001);
+	nv_icmd(dev, 0x0000091f, 0x00000001);
+	nv_icmd(dev, 0x00000920, 0x00000002);
+	nv_icmd(dev, 0x00000921, 0x00000002);
+	nv_icmd(dev, 0x00000922, 0x00000002);
+	nv_icmd(dev, 0x00000923, 0x00000002);
+	nv_icmd(dev, 0x00000924, 0x00000002);
+	nv_icmd(dev, 0x00000925, 0x00000002);
+	nv_icmd(dev, 0x00000926, 0x00000002);
+	nv_icmd(dev, 0x00000927, 0x00000002);
+	nv_icmd(dev, 0x00000928, 0x00000001);
+	nv_icmd(dev, 0x00000929, 0x00000001);
+	nv_icmd(dev, 0x0000092a, 0x00000001);
+	nv_icmd(dev, 0x0000092b, 0x00000001);
+	nv_icmd(dev, 0x0000092c, 0x00000001);
+	nv_icmd(dev, 0x0000092d, 0x00000001);
+	nv_icmd(dev, 0x0000092e, 0x00000001);
+	nv_icmd(dev, 0x0000092f, 0x00000001);
+	nv_icmd(dev, 0x00000648, 0x00000001);
+	nv_icmd(dev, 0x00000649, 0x00000001);
+	nv_icmd(dev, 0x0000064a, 0x00000001);
+	nv_icmd(dev, 0x0000064b, 0x00000001);
+	nv_icmd(dev, 0x0000064c, 0x00000001);
+	nv_icmd(dev, 0x0000064d, 0x00000001);
+	nv_icmd(dev, 0x0000064e, 0x00000001);
+	nv_icmd(dev, 0x0000064f, 0x00000001);
+	nv_icmd(dev, 0x00000650, 0x00000001);
+	nv_icmd(dev, 0x00000658, 0x0000000f);
+	nv_icmd(dev, 0x000007ff, 0x0000000a);
+	nv_icmd(dev, 0x0000066a, 0x40000000);
+	nv_icmd(dev, 0x0000066b, 0x10000000);
+	nv_icmd(dev, 0x0000066c, 0xffff0000);
+	nv_icmd(dev, 0x0000066d, 0xffff0000);
+	nv_icmd(dev, 0x000007af, 0x00000008);
+	nv_icmd(dev, 0x000007b0, 0x00000008);
+	nv_icmd(dev, 0x000007f6, 0x00000001);
+	nv_icmd(dev, 0x000006b2, 0x00000055);
+	nv_icmd(dev, 0x000007ad, 0x00000003);
+	nv_icmd(dev, 0x00000937, 0x00000001);
+	nv_icmd(dev, 0x00000971, 0x00000008);
+	nv_icmd(dev, 0x00000972, 0x00000040);
+	nv_icmd(dev, 0x00000973, 0x0000012c);
+	nv_icmd(dev, 0x0000097c, 0x00000040);
+	nv_icmd(dev, 0x00000979, 0x00000003);
+	nv_icmd(dev, 0x00000975, 0x00000020);
+	nv_icmd(dev, 0x00000976, 0x00000001);
+	nv_icmd(dev, 0x00000977, 0x00000020);
+	nv_icmd(dev, 0x00000978, 0x00000001);
+	nv_icmd(dev, 0x00000957, 0x00000003);
+	nv_icmd(dev, 0x0000095e, 0x20164010);
+	nv_icmd(dev, 0x0000095f, 0x00000020);
+	nv_icmd(dev, 0x00000683, 0x00000006);
+	nv_icmd(dev, 0x00000685, 0x003fffff);
+	nv_icmd(dev, 0x00000687, 0x00000c48);
+	nv_icmd(dev, 0x000006a0, 0x00000005);
+	nv_icmd(dev, 0x00000840, 0x00300008);
+	nv_icmd(dev, 0x00000841, 0x04000080);
+	nv_icmd(dev, 0x00000842, 0x00300008);
+	nv_icmd(dev, 0x00000843, 0x04000080);
+	nv_icmd(dev, 0x00000818, 0x00000000);
+	nv_icmd(dev, 0x00000819, 0x00000000);
+	nv_icmd(dev, 0x0000081a, 0x00000000);
+	nv_icmd(dev, 0x0000081b, 0x00000000);
+	nv_icmd(dev, 0x0000081c, 0x00000000);
+	nv_icmd(dev, 0x0000081d, 0x00000000);
+	nv_icmd(dev, 0x0000081e, 0x00000000);
+	nv_icmd(dev, 0x0000081f, 0x00000000);
+	nv_icmd(dev, 0x00000848, 0x00000000);
+	nv_icmd(dev, 0x00000849, 0x00000000);
+	nv_icmd(dev, 0x0000084a, 0x00000000);
+	nv_icmd(dev, 0x0000084b, 0x00000000);
+	nv_icmd(dev, 0x0000084c, 0x00000000);
+	nv_icmd(dev, 0x0000084d, 0x00000000);
+	nv_icmd(dev, 0x0000084e, 0x00000000);
+	nv_icmd(dev, 0x0000084f, 0x00000000);
+	nv_icmd(dev, 0x00000850, 0x00000000);
+	nv_icmd(dev, 0x00000851, 0x00000000);
+	nv_icmd(dev, 0x00000852, 0x00000000);
+	nv_icmd(dev, 0x00000853, 0x00000000);
+	nv_icmd(dev, 0x00000854, 0x00000000);
+	nv_icmd(dev, 0x00000855, 0x00000000);
+	nv_icmd(dev, 0x00000856, 0x00000000);
+	nv_icmd(dev, 0x00000857, 0x00000000);
+	nv_icmd(dev, 0x00000738, 0x00000000);
+	nv_icmd(dev, 0x000006aa, 0x00000001);
+	nv_icmd(dev, 0x000006ab, 0x00000002);
+	nv_icmd(dev, 0x000006ac, 0x00000080);
+	nv_icmd(dev, 0x000006ad, 0x00000100);
+	nv_icmd(dev, 0x000006ae, 0x00000100);
+	nv_icmd(dev, 0x000006b1, 0x00000011);
+	nv_icmd(dev, 0x000006bb, 0x000000cf);
+	nv_icmd(dev, 0x000006ce, 0x2a712488);
+	nv_icmd(dev, 0x00000739, 0x4085c000);
+	nv_icmd(dev, 0x0000073a, 0x00000080);
+	nv_icmd(dev, 0x00000786, 0x80000100);
+	nv_icmd(dev, 0x0000073c, 0x00010100);
+	nv_icmd(dev, 0x0000073d, 0x02800000);
+	nv_icmd(dev, 0x00000787, 0x000000cf);
+	nv_icmd(dev, 0x0000078c, 0x00000008);
+	nv_icmd(dev, 0x00000792, 0x00000001);
+	nv_icmd(dev, 0x00000794, 0x00000001);
+	nv_icmd(dev, 0x00000795, 0x00000001);
+	nv_icmd(dev, 0x00000796, 0x00000001);
+	nv_icmd(dev, 0x00000797, 0x000000cf);
+	nv_icmd(dev, 0x00000836, 0x00000001);
+	nv_icmd(dev, 0x0000079a, 0x00000002);
+	nv_icmd(dev, 0x00000833, 0x04444480);
+	nv_icmd(dev, 0x000007a1, 0x00000001);
+	nv_icmd(dev, 0x000007a3, 0x00000001);
+	nv_icmd(dev, 0x000007a4, 0x00000001);
+	nv_icmd(dev, 0x000007a5, 0x00000001);
+	nv_icmd(dev, 0x00000831, 0x00000004);
+	nv_icmd(dev, 0x0000080c, 0x00000002);
+	nv_icmd(dev, 0x0000080d, 0x00000100);
+	nv_icmd(dev, 0x0000080e, 0x00000100);
+	nv_icmd(dev, 0x0000080f, 0x00000001);
+	nv_icmd(dev, 0x00000823, 0x00000002);
+	nv_icmd(dev, 0x00000824, 0x00000100);
+	nv_icmd(dev, 0x00000825, 0x00000100);
+	nv_icmd(dev, 0x00000826, 0x00000001);
+	nv_icmd(dev, 0x0000095d, 0x00000001);
+	nv_icmd(dev, 0x0000082b, 0x00000004);
+	nv_icmd(dev, 0x00000942, 0x00010001);
+	nv_icmd(dev, 0x00000943, 0x00000001);
+	nv_icmd(dev, 0x00000944, 0x00000022);
+	nv_icmd(dev, 0x000007c5, 0x00010001);
+	nv_icmd(dev, 0x00000834, 0x00000001);
+	nv_icmd(dev, 0x000007c7, 0x00000001);
+	nv_icmd(dev, 0x0000c1b0, 0x0000000f);
+	nv_icmd(dev, 0x0000c1b1, 0x0000000f);
+	nv_icmd(dev, 0x0000c1b2, 0x0000000f);
+	nv_icmd(dev, 0x0000c1b3, 0x0000000f);
+	nv_icmd(dev, 0x0000c1b4, 0x0000000f);
+	nv_icmd(dev, 0x0000c1b5, 0x0000000f);
+	nv_icmd(dev, 0x0000c1b6, 0x0000000f);
+	nv_icmd(dev, 0x0000c1b7, 0x0000000f);
+	nv_icmd(dev, 0x0000c1b8, 0x0fac6881);
+	nv_icmd(dev, 0x0000c1b9, 0x00fac688);
+	nv_icmd(dev, 0x0001e100, 0x00000001);
+	nv_icmd(dev, 0x00001000, 0x00000002);
+	nv_icmd(dev, 0x000006aa, 0x00000001);
+	nv_icmd(dev, 0x000006ad, 0x00000100);
+	nv_icmd(dev, 0x000006ae, 0x00000100);
+	nv_icmd(dev, 0x000006b1, 0x00000011);
+	nv_icmd(dev, 0x0000078c, 0x00000008);
+	nv_icmd(dev, 0x00000792, 0x00000001);
+	nv_icmd(dev, 0x00000794, 0x00000001);
+	nv_icmd(dev, 0x00000795, 0x00000001);
+	nv_icmd(dev, 0x00000796, 0x00000001);
+	nv_icmd(dev, 0x00000797, 0x000000cf);
+	nv_icmd(dev, 0x0000079a, 0x00000002);
+	nv_icmd(dev, 0x00000833, 0x04444480);
+	nv_icmd(dev, 0x000007a1, 0x00000001);
+	nv_icmd(dev, 0x000007a3, 0x00000001);
+	nv_icmd(dev, 0x000007a4, 0x00000001);
+	nv_icmd(dev, 0x000007a5, 0x00000001);
+	nv_icmd(dev, 0x00000831, 0x00000004);
+	nv_icmd(dev, 0x0001e100, 0x00000001);
+	nv_icmd(dev, 0x00001000, 0x00000014);
+	nv_icmd(dev, 0x00000351, 0x00000100);
+	nv_icmd(dev, 0x00000957, 0x00000003);
+	nv_icmd(dev, 0x0000095d, 0x00000001);
+	nv_icmd(dev, 0x0000082b, 0x00000004);
+	nv_icmd(dev, 0x00000942, 0x00010001);
+	nv_icmd(dev, 0x00000943, 0x00000001);
+	nv_icmd(dev, 0x000007c5, 0x00010001);
+	nv_icmd(dev, 0x00000834, 0x00000001);
+	nv_icmd(dev, 0x000007c7, 0x00000001);
+	nv_icmd(dev, 0x0001e100, 0x00000001);
+	nv_icmd(dev, 0x00001000, 0x00000001);
+	nv_icmd(dev, 0x0000080c, 0x00000002);
+	nv_icmd(dev, 0x0000080d, 0x00000100);
+	nv_icmd(dev, 0x0000080e, 0x00000100);
+	nv_icmd(dev, 0x0000080f, 0x00000001);
+	nv_icmd(dev, 0x00000823, 0x00000002);
+	nv_icmd(dev, 0x00000824, 0x00000100);
+	nv_icmd(dev, 0x00000825, 0x00000100);
+	nv_icmd(dev, 0x00000826, 0x00000001);
+	nv_icmd(dev, 0x0001e100, 0x00000001);
+	nv_wr32(dev, 0x400208, 0x00000000);
+	nv_wr32(dev, 0x404154, 0x00000400);
+
+	nvc0_grctx_generate_9097(dev);
+	nvc0_grctx_generate_902d(dev);
+	nvc0_grctx_generate_9039(dev);
+	nvc0_grctx_generate_90c0(dev);
+
+	nv_wr32(dev, 0x000260, r000260);
+	return 0;
+}
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nvc0_instmem.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nvc0_instmem.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nvc0_instmem.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nvc0_instmem.c	2011-03-14 21:20:32.000000000 -0400
@@ -25,206 +25,207 @@
 #include "drmP.h"
 
 #include "nouveau_drv.h"
+#include "nouveau_vm.h"
+
+struct nvc0_instmem_priv {
+	struct nouveau_gpuobj  *bar1_pgd;
+	struct nouveau_channel *bar1;
+	struct nouveau_gpuobj  *bar3_pgd;
+	struct nouveau_channel *bar3;
+	struct nouveau_gpuobj  *chan_pgd;
+};
 
 int
-nvc0_instmem_populate(struct drm_device *dev, struct nouveau_gpuobj *gpuobj,
-		      uint32_t *size)
+nvc0_instmem_suspend(struct drm_device *dev)
 {
-	int ret;
-
-	*size = ALIGN(*size, 4096);
-	if (*size == 0)
-		return -EINVAL;
-
-	ret = nouveau_bo_new(dev, NULL, *size, 0, TTM_PL_FLAG_VRAM, 0, 0x0000,
-			     true, false, &gpuobj->im_backing);
-	if (ret) {
-		NV_ERROR(dev, "error getting PRAMIN backing pages: %d\n", ret);
-		return ret;
-	}
-
-	ret = nouveau_bo_pin(gpuobj->im_backing, TTM_PL_FLAG_VRAM);
-	if (ret) {
-		NV_ERROR(dev, "error pinning PRAMIN backing VRAM: %d\n", ret);
-		nouveau_bo_ref(NULL, &gpuobj->im_backing);
-		return ret;
-	}
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
 
-	gpuobj->vinst = gpuobj->im_backing->bo.mem.start << PAGE_SHIFT;
+	dev_priv->ramin_available = false;
 	return 0;
 }
 
 void
-nvc0_instmem_clear(struct drm_device *dev, struct nouveau_gpuobj *gpuobj)
+nvc0_instmem_resume(struct drm_device *dev)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nvc0_instmem_priv *priv = dev_priv->engine.instmem.priv;
 
-	if (gpuobj && gpuobj->im_backing) {
-		if (gpuobj->im_bound)
-			dev_priv->engine.instmem.unbind(dev, gpuobj);
-		nouveau_bo_unpin(gpuobj->im_backing);
-		nouveau_bo_ref(NULL, &gpuobj->im_backing);
-		gpuobj->im_backing = NULL;
-	}
+	nv_mask(dev, 0x100c80, 0x00000001, 0x00000000);
+	nv_wr32(dev, 0x001704, 0x80000000 | priv->bar1->ramin->vinst >> 12);
+	nv_wr32(dev, 0x001714, 0xc0000000 | priv->bar3->ramin->vinst >> 12);
+	dev_priv->ramin_available = true;
 }
 
-int
-nvc0_instmem_bind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj)
+static void
+nvc0_channel_del(struct nouveau_channel **pchan)
 {
-	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	uint32_t pte, pte_end;
-	uint64_t vram;
+	struct nouveau_channel *chan;
 
-	if (!gpuobj->im_backing || !gpuobj->im_pramin || gpuobj->im_bound)
-		return -EINVAL;
+	chan = *pchan;
+	*pchan = NULL;
+	if (!chan)
+		return;
 
-	NV_DEBUG(dev, "st=0x%lx sz=0x%lx\n",
-		 gpuobj->im_pramin->start, gpuobj->im_pramin->size);
+	nouveau_vm_ref(NULL, &chan->vm, NULL);
+	if (chan->ramin_heap.free_stack.next)
+		drm_mm_takedown(&chan->ramin_heap);
+	nouveau_gpuobj_ref(NULL, &chan->ramin);
+	kfree(chan);
+}
 
-	pte     = gpuobj->im_pramin->start >> 12;
-	pte_end = (gpuobj->im_pramin->size >> 12) + pte;
-	vram    = gpuobj->vinst;
+static int
+nvc0_channel_new(struct drm_device *dev, u32 size, struct nouveau_vm *vm,
+		 struct nouveau_channel **pchan,
+		 struct nouveau_gpuobj *pgd, u64 vm_size)
+{
+	struct nouveau_channel *chan;
+	int ret;
 
-	NV_DEBUG(dev, "pramin=0x%lx, pte=%d, pte_end=%d\n",
-		 gpuobj->im_pramin->start, pte, pte_end);
-	NV_DEBUG(dev, "first vram page: 0x%010llx\n", gpuobj->vinst);
+	chan = kzalloc(sizeof(*chan), GFP_KERNEL);
+	if (!chan)
+		return -ENOMEM;
+	chan->dev = dev;
 
-	while (pte < pte_end) {
-		nv_wr32(dev, 0x702000 + (pte * 8), (vram >> 8) | 1);
-		nv_wr32(dev, 0x702004 + (pte * 8), 0);
-		vram += 4096;
-		pte++;
+	ret = nouveau_gpuobj_new(dev, NULL, size, 0x1000, 0, &chan->ramin);
+	if (ret) {
+		nvc0_channel_del(&chan);
+		return ret;
 	}
-	dev_priv->engine.instmem.flush(dev);
 
-	if (1) {
-		u32 chan = nv_rd32(dev, 0x1700) << 16;
-		nv_wr32(dev, 0x100cb8, (chan + 0x1000) >> 8);
-		nv_wr32(dev, 0x100cbc, 0x80000005);
+	ret = drm_mm_init(&chan->ramin_heap, 0x1000, size - 0x1000);
+	if (ret) {
+		nvc0_channel_del(&chan);
+		return ret;
 	}
 
-	gpuobj->im_bound = 1;
-	return 0;
-}
-
-int
-nvc0_instmem_unbind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj)
-{
-	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	uint32_t pte, pte_end;
-
-	if (gpuobj->im_bound == 0)
-		return -EINVAL;
-
-	pte     = gpuobj->im_pramin->start >> 12;
-	pte_end = (gpuobj->im_pramin->size >> 12) + pte;
-	while (pte < pte_end) {
-		nv_wr32(dev, 0x702000 + (pte * 8), 0);
-		nv_wr32(dev, 0x702004 + (pte * 8), 0);
-		pte++;
+	ret = nouveau_vm_ref(vm, &chan->vm, NULL);
+	if (ret) {
+		nvc0_channel_del(&chan);
+		return ret;
 	}
-	dev_priv->engine.instmem.flush(dev);
 
-	gpuobj->im_bound = 0;
-	return 0;
-}
+	nv_wo32(chan->ramin, 0x0200, lower_32_bits(pgd->vinst));
+	nv_wo32(chan->ramin, 0x0204, upper_32_bits(pgd->vinst));
+	nv_wo32(chan->ramin, 0x0208, lower_32_bits(vm_size - 1));
+	nv_wo32(chan->ramin, 0x020c, upper_32_bits(vm_size - 1));
 
-void
-nvc0_instmem_flush(struct drm_device *dev)
-{
-	nv_wr32(dev, 0x070000, 1);
-	if (!nv_wait(dev, 0x070000, 0x00000002, 0x00000000))
-		NV_ERROR(dev, "PRAMIN flush timeout\n");
+	*pchan = chan;
+	return 0;
 }
 
 int
-nvc0_instmem_suspend(struct drm_device *dev)
+nvc0_instmem_init(struct drm_device *dev)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	u32 *buf;
-	int i;
+	struct nouveau_instmem_engine *pinstmem = &dev_priv->engine.instmem;
+	struct pci_dev *pdev = dev->pdev;
+	struct nvc0_instmem_priv *priv;
+	struct nouveau_vm *vm = NULL;
+	int ret;
 
-	dev_priv->susres.ramin_copy = vmalloc(65536);
-	if (!dev_priv->susres.ramin_copy)
+	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+	if (!priv)
 		return -ENOMEM;
-	buf = dev_priv->susres.ramin_copy;
-
-	for (i = 0; i < 65536; i += 4)
-		buf[i/4] = nv_rd32(dev, NV04_PRAMIN + i);
-	return 0;
-}
+	pinstmem->priv = priv;
 
-void
-nvc0_instmem_resume(struct drm_device *dev)
-{
-	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	u32 *buf = dev_priv->susres.ramin_copy;
-	u64 chan;
-	int i;
+	/* BAR3 VM */
+	ret = nouveau_vm_new(dev, 0, pci_resource_len(pdev, 3), 0,
+			     &dev_priv->bar3_vm);
+	if (ret)
+		goto error;
 
-	chan = dev_priv->vram_size - dev_priv->ramin_rsvd_vram;
-	nv_wr32(dev, 0x001700, chan >> 16);
+	ret = nouveau_gpuobj_new(dev, NULL,
+				 (pci_resource_len(pdev, 3) >> 12) * 8, 0,
+				 NVOBJ_FLAG_DONT_MAP |
+				 NVOBJ_FLAG_ZERO_ALLOC,
+				 &dev_priv->bar3_vm->pgt[0].obj[0]);
+	if (ret)
+		goto error;
+	dev_priv->bar3_vm->pgt[0].refcount[0] = 1;
 
-	for (i = 0; i < 65536; i += 4)
-		nv_wr32(dev, NV04_PRAMIN + i, buf[i/4]);
-	vfree(dev_priv->susres.ramin_copy);
-	dev_priv->susres.ramin_copy = NULL;
+	nv50_instmem_map(dev_priv->bar3_vm->pgt[0].obj[0]);
 
-	nv_wr32(dev, 0x001714, 0xc0000000 | (chan >> 12));
-}
+	ret = nouveau_gpuobj_new(dev, NULL, 0x8000, 4096,
+				 NVOBJ_FLAG_ZERO_ALLOC, &priv->bar3_pgd);
+	if (ret)
+		goto error;
 
-int
-nvc0_instmem_init(struct drm_device *dev)
-{
-	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	u64 chan, pgt3, imem, lim3 = dev_priv->ramin_size - 1;
-	int ret, i;
+	ret = nouveau_vm_ref(dev_priv->bar3_vm, &vm, priv->bar3_pgd);
+	if (ret)
+		goto error;
+	nouveau_vm_ref(NULL, &vm, NULL);
 
-	dev_priv->ramin_rsvd_vram = 1 * 1024 * 1024;
-	chan = dev_priv->vram_size - dev_priv->ramin_rsvd_vram;
-	imem = 4096 + 4096 + 32768;
+	ret = nvc0_channel_new(dev, 8192, dev_priv->bar3_vm, &priv->bar3,
+			       priv->bar3_pgd, pci_resource_len(dev->pdev, 3));
+	if (ret)
+		goto error;
 
-	nv_wr32(dev, 0x001700, chan >> 16);
+	/* BAR1 VM */
+	ret = nouveau_vm_new(dev, 0, pci_resource_len(pdev, 1), 0, &vm);
+	if (ret)
+		goto error;
 
-	/* channel setup */
-	nv_wr32(dev, 0x700200, lower_32_bits(chan + 0x1000));
-	nv_wr32(dev, 0x700204, upper_32_bits(chan + 0x1000));
-	nv_wr32(dev, 0x700208, lower_32_bits(lim3));
-	nv_wr32(dev, 0x70020c, upper_32_bits(lim3));
+	ret = nouveau_gpuobj_new(dev, NULL, 0x8000, 4096,
+				 NVOBJ_FLAG_ZERO_ALLOC, &priv->bar1_pgd);
+	if (ret)
+		goto error;
 
-	/* point pgd -> pgt */
-	nv_wr32(dev, 0x701000, 0);
-	nv_wr32(dev, 0x701004, ((chan + 0x2000) >> 8) | 1);
+	ret = nouveau_vm_ref(vm, &dev_priv->bar1_vm, priv->bar1_pgd);
+	if (ret)
+		goto error;
+	nouveau_vm_ref(NULL, &vm, NULL);
 
-	/* point pgt -> physical vram for channel */
-	pgt3 = 0x2000;
-	for (i = 0; i < dev_priv->ramin_rsvd_vram; i += 4096, pgt3 += 8) {
-		nv_wr32(dev, 0x700000 + pgt3, ((chan + i) >> 8) | 1);
-		nv_wr32(dev, 0x700004 + pgt3, 0);
-	}
+	ret = nvc0_channel_new(dev, 8192, dev_priv->bar1_vm, &priv->bar1,
+			       priv->bar1_pgd, pci_resource_len(dev->pdev, 1));
+	if (ret)
+		goto error;
 
-	/* clear rest of pgt */
-	for (; i < dev_priv->ramin_size; i += 4096, pgt3 += 8) {
-		nv_wr32(dev, 0x700000 + pgt3, 0);
-		nv_wr32(dev, 0x700004 + pgt3, 0);
-	}
+	/* channel vm */
+	ret = nouveau_vm_new(dev, 0, (1ULL << 40), 0x0008000000ULL, &vm);
+	if (ret)
+		goto error;
 
-	/* point bar3 at the channel */
-	nv_wr32(dev, 0x001714, 0xc0000000 | (chan >> 12));
+	ret = nouveau_gpuobj_new(dev, NULL, 0x8000, 4096, 0, &priv->chan_pgd);
+	if (ret)
+		goto error;
 
-	/* Global PRAMIN heap */
-	ret = drm_mm_init(&dev_priv->ramin_heap, imem,
-			  dev_priv->ramin_size - imem);
-	if (ret) {
-		NV_ERROR(dev, "Failed to init RAMIN heap\n");
-		return -ENOMEM;
-	}
+	nouveau_vm_ref(vm, &dev_priv->chan_vm, priv->chan_pgd);
+	nouveau_vm_ref(NULL, &vm, NULL);
 
+	nvc0_instmem_resume(dev);
 	return 0;
+error:
+	nvc0_instmem_takedown(dev);
+	return ret;
 }
 
 void
 nvc0_instmem_takedown(struct drm_device *dev)
 {
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nvc0_instmem_priv *priv = dev_priv->engine.instmem.priv;
+	struct nouveau_vm *vm = NULL;
+
+	nvc0_instmem_suspend(dev);
+
+	nv_wr32(dev, 0x1704, 0x00000000);
+	nv_wr32(dev, 0x1714, 0x00000000);
+
+	nouveau_vm_ref(NULL, &dev_priv->chan_vm, priv->chan_pgd);
+	nouveau_gpuobj_ref(NULL, &priv->chan_pgd);
+
+	nvc0_channel_del(&priv->bar1);
+	nouveau_vm_ref(NULL, &dev_priv->bar1_vm, priv->bar1_pgd);
+	nouveau_gpuobj_ref(NULL, &priv->bar1_pgd);
+
+	nvc0_channel_del(&priv->bar3);
+	nouveau_vm_ref(dev_priv->bar3_vm, &vm, NULL);
+	nouveau_vm_ref(NULL, &vm, priv->bar3_pgd);
+	nouveau_gpuobj_ref(NULL, &priv->bar3_pgd);
+	nouveau_gpuobj_ref(NULL, &dev_priv->bar3_vm->pgt[0].obj[0]);
+	nouveau_vm_ref(NULL, &dev_priv->bar3_vm, NULL);
+
+	dev_priv->engine.instmem.priv = NULL;
+	kfree(priv);
 }
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nvc0_vm.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nvc0_vm.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nvc0_vm.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nvc0_vm.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,123 @@
+/*
+ * Copyright 2010 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_vm.h"
+
+void
+nvc0_vm_map_pgt(struct nouveau_gpuobj *pgd, u32 index,
+		struct nouveau_gpuobj *pgt[2])
+{
+	u32 pde[2] = { 0, 0 };
+
+	if (pgt[0])
+		pde[1] = 0x00000001 | (pgt[0]->vinst >> 8);
+	if (pgt[1])
+		pde[0] = 0x00000001 | (pgt[1]->vinst >> 8);
+
+	nv_wo32(pgd, (index * 8) + 0, pde[0]);
+	nv_wo32(pgd, (index * 8) + 4, pde[1]);
+}
+
+static inline u64
+nvc0_vm_addr(struct nouveau_vma *vma, u64 phys, u32 memtype, u32 target)
+{
+	phys >>= 8;
+
+	phys |= 0x00000001; /* present */
+	if (vma->access & NV_MEM_ACCESS_SYS)
+		phys |= 0x00000002;
+
+	phys |= ((u64)target  << 32);
+	phys |= ((u64)memtype << 36);
+
+	return phys;
+}
+
+void
+nvc0_vm_map(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt,
+	    struct nouveau_vram *mem, u32 pte, u32 cnt, u64 phys)
+{
+	u32 next = 1 << (vma->node->type - 8);
+
+	phys  = nvc0_vm_addr(vma, phys, mem->memtype, 0);
+	pte <<= 3;
+	while (cnt--) {
+		nv_wo32(pgt, pte + 0, lower_32_bits(phys));
+		nv_wo32(pgt, pte + 4, upper_32_bits(phys));
+		phys += next;
+		pte  += 8;
+	}
+}
+
+void
+nvc0_vm_map_sg(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt,
+	       u32 pte, dma_addr_t *list, u32 cnt)
+{
+	pte <<= 3;
+	while (cnt--) {
+		u64 phys = nvc0_vm_addr(vma, *list++, 0, 5);
+		nv_wo32(pgt, pte + 0, lower_32_bits(phys));
+		nv_wo32(pgt, pte + 4, upper_32_bits(phys));
+		pte += 8;
+	}
+}
+
+void
+nvc0_vm_unmap(struct nouveau_gpuobj *pgt, u32 pte, u32 cnt)
+{
+	pte <<= 3;
+	while (cnt--) {
+		nv_wo32(pgt, pte + 0, 0x00000000);
+		nv_wo32(pgt, pte + 4, 0x00000000);
+		pte += 8;
+	}
+}
+
+void
+nvc0_vm_flush(struct nouveau_vm *vm)
+{
+	struct drm_nouveau_private *dev_priv = vm->dev->dev_private;
+	struct nouveau_instmem_engine *pinstmem = &dev_priv->engine.instmem;
+	struct drm_device *dev = vm->dev;
+	struct nouveau_vm_pgd *vpgd;
+	u32 r100c80, engine;
+
+	pinstmem->flush(vm->dev);
+
+	if (vm == dev_priv->chan_vm)
+		engine = 1;
+	else
+		engine = 5;
+
+	list_for_each_entry(vpgd, &vm->pgd_list, head) {
+		r100c80 = nv_rd32(dev, 0x100c80);
+		nv_wr32(dev, 0x100cb8, vpgd->obj->vinst >> 8);
+		nv_wr32(dev, 0x100cbc, 0x80000000 | engine);
+		if (!nv_wait(dev, 0x100c80, 0xffffffff, r100c80))
+			NV_ERROR(dev, "vm flush timeout eng %d\n", engine);
+	}
+}
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nvc0_vram.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nvc0_vram.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nvc0_vram.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nvc0_vram.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2010 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_mm.h"
+
+bool
+nvc0_vram_flags_valid(struct drm_device *dev, u32 tile_flags)
+{
+	switch (tile_flags & NOUVEAU_GEM_TILE_LAYOUT_MASK) {
+	case 0x0000:
+	case 0xfe00:
+	case 0xdb00:
+	case 0x1100:
+		return true;
+	default:
+		break;
+	}
+
+	return false;
+}
+
+int
+nvc0_vram_new(struct drm_device *dev, u64 size, u32 align, u32 ncmin,
+	      u32 type, struct nouveau_vram **pvram)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct ttm_bo_device *bdev = &dev_priv->ttm.bdev;
+	struct ttm_mem_type_manager *man = &bdev->man[TTM_PL_VRAM];
+	struct nouveau_mm *mm = man->priv;
+	struct nouveau_mm_node *r;
+	struct nouveau_vram *vram;
+	int ret;
+
+	size  >>= 12;
+	align >>= 12;
+	ncmin >>= 12;
+
+	vram = kzalloc(sizeof(*vram), GFP_KERNEL);
+	if (!vram)
+		return -ENOMEM;
+
+	INIT_LIST_HEAD(&vram->regions);
+	vram->dev = dev_priv->dev;
+	vram->memtype = type;
+	vram->size = size;
+
+	mutex_lock(&mm->mutex);
+	do {
+		ret = nouveau_mm_get(mm, 1, size, ncmin, align, &r);
+		if (ret) {
+			mutex_unlock(&mm->mutex);
+			nv50_vram_del(dev, &vram);
+			return ret;
+		}
+
+		list_add_tail(&r->rl_entry, &vram->regions);
+		size -= r->length;
+	} while (size);
+	mutex_unlock(&mm->mutex);
+
+	r = list_first_entry(&vram->regions, struct nouveau_mm_node, rl_entry);
+	vram->offset = (u64)r->offset << 12;
+	*pvram = vram;
+	return 0;
+}
+
+int
+nvc0_vram_init(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+	dev_priv->vram_size  = nv_rd32(dev, 0x10f20c) << 20;
+	dev_priv->vram_size *= nv_rd32(dev, 0x121c74);
+	dev_priv->vram_rblock_size = 4096;
+	return 0;
+}
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nvreg.h linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nvreg.h
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/nouveau/nvreg.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/nouveau/nvreg.h	2011-03-14 21:20:32.000000000 -0400
@@ -153,7 +153,8 @@
 #define NV_PCRTC_START					0x00600800
 #define NV_PCRTC_CONFIG					0x00600804
 #	define NV_PCRTC_CONFIG_START_ADDRESS_NON_VGA		(1 << 0)
-#	define NV_PCRTC_CONFIG_START_ADDRESS_HSYNC		(2 << 0)
+#	define NV04_PCRTC_CONFIG_START_ADDRESS_HSYNC		(4 << 0)
+#	define NV10_PCRTC_CONFIG_START_ADDRESS_HSYNC		(2 << 0)
 #define NV_PCRTC_CURSOR_CONFIG				0x00600810
 #	define NV_PCRTC_CURSOR_CONFIG_ENABLE_ENABLE		(1 << 0)
 #	define NV_PCRTC_CURSOR_CONFIG_DOUBLE_SCAN_ENABLE	(1 << 4)
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/atombios_crtc.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/atombios_crtc.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/atombios_crtc.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/atombios_crtc.c	2011-03-14 21:20:32.000000000 -0400
@@ -48,29 +48,29 @@ static void atombios_overscan_setup(stru
 
 	switch (radeon_crtc->rmx_type) {
 	case RMX_CENTER:
-		args.usOverscanTop = (adjusted_mode->crtc_vdisplay - mode->crtc_vdisplay) / 2;
-		args.usOverscanBottom = (adjusted_mode->crtc_vdisplay - mode->crtc_vdisplay) / 2;
-		args.usOverscanLeft = (adjusted_mode->crtc_hdisplay - mode->crtc_hdisplay) / 2;
-		args.usOverscanRight = (adjusted_mode->crtc_hdisplay - mode->crtc_hdisplay) / 2;
+		args.usOverscanTop = cpu_to_le16((adjusted_mode->crtc_vdisplay - mode->crtc_vdisplay) / 2);
+		args.usOverscanBottom = cpu_to_le16((adjusted_mode->crtc_vdisplay - mode->crtc_vdisplay) / 2);
+		args.usOverscanLeft = cpu_to_le16((adjusted_mode->crtc_hdisplay - mode->crtc_hdisplay) / 2);
+		args.usOverscanRight = cpu_to_le16((adjusted_mode->crtc_hdisplay - mode->crtc_hdisplay) / 2);
 		break;
 	case RMX_ASPECT:
 		a1 = mode->crtc_vdisplay * adjusted_mode->crtc_hdisplay;
 		a2 = adjusted_mode->crtc_vdisplay * mode->crtc_hdisplay;
 
 		if (a1 > a2) {
-			args.usOverscanLeft = (adjusted_mode->crtc_hdisplay - (a2 / mode->crtc_vdisplay)) / 2;
-			args.usOverscanRight = (adjusted_mode->crtc_hdisplay - (a2 / mode->crtc_vdisplay)) / 2;
+			args.usOverscanLeft = cpu_to_le16((adjusted_mode->crtc_hdisplay - (a2 / mode->crtc_vdisplay)) / 2);
+			args.usOverscanRight = cpu_to_le16((adjusted_mode->crtc_hdisplay - (a2 / mode->crtc_vdisplay)) / 2);
 		} else if (a2 > a1) {
-			args.usOverscanLeft = (adjusted_mode->crtc_vdisplay - (a1 / mode->crtc_hdisplay)) / 2;
-			args.usOverscanRight = (adjusted_mode->crtc_vdisplay - (a1 / mode->crtc_hdisplay)) / 2;
+			args.usOverscanLeft = cpu_to_le16((adjusted_mode->crtc_vdisplay - (a1 / mode->crtc_hdisplay)) / 2);
+			args.usOverscanRight = cpu_to_le16((adjusted_mode->crtc_vdisplay - (a1 / mode->crtc_hdisplay)) / 2);
 		}
 		break;
 	case RMX_FULL:
 	default:
-		args.usOverscanRight = radeon_crtc->h_border;
-		args.usOverscanLeft = radeon_crtc->h_border;
-		args.usOverscanBottom = radeon_crtc->v_border;
-		args.usOverscanTop = radeon_crtc->v_border;
+		args.usOverscanRight = cpu_to_le16(radeon_crtc->h_border);
+		args.usOverscanLeft = cpu_to_le16(radeon_crtc->h_border);
+		args.usOverscanBottom = cpu_to_le16(radeon_crtc->v_border);
+		args.usOverscanTop = cpu_to_le16(radeon_crtc->v_border);
 		break;
 	}
 	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
@@ -403,6 +403,7 @@ union atom_enable_ss {
 	ENABLE_LVDS_SS_PARAMETERS_V2 lvds_ss_2;
 	ENABLE_SPREAD_SPECTRUM_ON_PPLL_PS_ALLOCATION v1;
 	ENABLE_SPREAD_SPECTRUM_ON_PPLL_V2 v2;
+	ENABLE_SPREAD_SPECTRUM_ON_PPLL_V3 v3;
 };
 
 static void atombios_crtc_program_ss(struct drm_crtc *crtc,
@@ -417,24 +418,47 @@ static void atombios_crtc_program_ss(str
 
 	memset(&args, 0, sizeof(args));
 
-	if (ASIC_IS_DCE4(rdev)) {
+	if (ASIC_IS_DCE5(rdev)) {
+		args.v3.usSpreadSpectrumAmountFrac = cpu_to_le16(0);
+		args.v3.ucSpreadSpectrumType = ss->type;
+		switch (pll_id) {
+		case ATOM_PPLL1:
+			args.v3.ucSpreadSpectrumType |= ATOM_PPLL_SS_TYPE_V3_P1PLL;
+			args.v3.usSpreadSpectrumAmount = cpu_to_le16(ss->amount);
+			args.v3.usSpreadSpectrumStep = cpu_to_le16(ss->step);
+			break;
+		case ATOM_PPLL2:
+			args.v3.ucSpreadSpectrumType |= ATOM_PPLL_SS_TYPE_V3_P2PLL;
+			args.v3.usSpreadSpectrumAmount = cpu_to_le16(ss->amount);
+			args.v3.usSpreadSpectrumStep = cpu_to_le16(ss->step);
+			break;
+		case ATOM_DCPLL:
+			args.v3.ucSpreadSpectrumType |= ATOM_PPLL_SS_TYPE_V3_DCPLL;
+			args.v3.usSpreadSpectrumAmount = cpu_to_le16(0);
+			args.v3.usSpreadSpectrumStep = cpu_to_le16(0);
+			break;
+		case ATOM_PPLL_INVALID:
+			return;
+		}
+		args.v2.ucEnable = enable;
+	} else if (ASIC_IS_DCE4(rdev)) {
 		args.v2.usSpreadSpectrumPercentage = cpu_to_le16(ss->percentage);
 		args.v2.ucSpreadSpectrumType = ss->type;
 		switch (pll_id) {
 		case ATOM_PPLL1:
 			args.v2.ucSpreadSpectrumType |= ATOM_PPLL_SS_TYPE_V2_P1PLL;
-			args.v2.usSpreadSpectrumAmount = ss->amount;
-			args.v2.usSpreadSpectrumStep = ss->step;
+			args.v2.usSpreadSpectrumAmount = cpu_to_le16(ss->amount);
+			args.v2.usSpreadSpectrumStep = cpu_to_le16(ss->step);
 			break;
 		case ATOM_PPLL2:
 			args.v2.ucSpreadSpectrumType |= ATOM_PPLL_SS_TYPE_V2_P2PLL;
-			args.v2.usSpreadSpectrumAmount = ss->amount;
-			args.v2.usSpreadSpectrumStep = ss->step;
+			args.v2.usSpreadSpectrumAmount = cpu_to_le16(ss->amount);
+			args.v2.usSpreadSpectrumStep = cpu_to_le16(ss->step);
 			break;
 		case ATOM_DCPLL:
 			args.v2.ucSpreadSpectrumType |= ATOM_PPLL_SS_TYPE_V2_DCPLL;
-			args.v2.usSpreadSpectrumAmount = 0;
-			args.v2.usSpreadSpectrumStep = 0;
+			args.v2.usSpreadSpectrumAmount = cpu_to_le16(0);
+			args.v2.usSpreadSpectrumStep = cpu_to_le16(0);
 			break;
 		case ATOM_PPLL_INVALID:
 			return;
@@ -514,7 +538,6 @@ static u32 atombios_adjust_pll(struct dr
 			pll->flags |= RADEON_PLL_PREFER_HIGH_FB_DIV;
 		else
 			pll->flags |= RADEON_PLL_PREFER_LOW_REF_DIV;
-
 	}
 
 	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
@@ -531,23 +554,28 @@ static u32 atombios_adjust_pll(struct dr
 					dp_clock = dig_connector->dp_clock;
 				}
 			}
-#if 0 /* doesn't work properly on some laptops */
+
 			/* use recommended ref_div for ss */
 			if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
 				if (ss_enabled) {
 					if (ss->refdiv) {
+						pll->flags |= RADEON_PLL_PREFER_MINM_OVER_MAXP;
 						pll->flags |= RADEON_PLL_USE_REF_DIV;
 						pll->reference_div = ss->refdiv;
+						if (ASIC_IS_AVIVO(rdev))
+							pll->flags |= RADEON_PLL_USE_FRAC_FB_DIV;
 					}
 				}
 			}
-#endif
+
 			if (ASIC_IS_AVIVO(rdev)) {
 				/* DVO wants 2x pixel clock if the DVO chip is in 12 bit mode */
 				if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1)
 					adjusted_clock = mode->clock * 2;
 				if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
 					pll->flags |= RADEON_PLL_PREFER_CLOSEST_LOWER;
+				if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
+					pll->flags |= RADEON_PLL_IS_LCD;
 			} else {
 				if (encoder->encoder_type != DRM_MODE_ENCODER_DAC)
 					pll->flags |= RADEON_PLL_NO_ODD_POST_DIV;
@@ -582,14 +610,9 @@ static u32 atombios_adjust_pll(struct dr
 				args.v1.usPixelClock = cpu_to_le16(mode->clock / 10);
 				args.v1.ucTransmitterID = radeon_encoder->encoder_id;
 				args.v1.ucEncodeMode = encoder_mode;
-				if (encoder_mode == ATOM_ENCODER_MODE_DP) {
-					if (ss_enabled)
-						args.v1.ucConfig |=
-							ADJUST_DISPLAY_CONFIG_SS_ENABLE;
-				} else if (encoder_mode == ATOM_ENCODER_MODE_LVDS) {
+				if (ss_enabled)
 					args.v1.ucConfig |=
 						ADJUST_DISPLAY_CONFIG_SS_ENABLE;
-				}
 
 				atom_execute_table(rdev->mode_info.atom_context,
 						   index, (uint32_t *)&args);
@@ -600,12 +623,12 @@ static u32 atombios_adjust_pll(struct dr
 				args.v3.sInput.ucTransmitterID = radeon_encoder->encoder_id;
 				args.v3.sInput.ucEncodeMode = encoder_mode;
 				args.v3.sInput.ucDispPllConfig = 0;
+				if (ss_enabled)
+					args.v3.sInput.ucDispPllConfig |=
+						DISPPLL_CONFIG_SS_ENABLE;
 				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 (ss_enabled)
-							args.v3.sInput.ucDispPllConfig |=
-								DISPPLL_CONFIG_SS_ENABLE;
 						args.v3.sInput.ucDispPllConfig |=
 							DISPPLL_CONFIG_COHERENT_MODE;
 						/* 16200 or 27000 */
@@ -625,18 +648,11 @@ static u32 atombios_adjust_pll(struct dr
 					}
 				} else if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
 					if (encoder_mode == ATOM_ENCODER_MODE_DP) {
-						if (ss_enabled)
-							args.v3.sInput.ucDispPllConfig |=
-								DISPPLL_CONFIG_SS_ENABLE;
 						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 (ss_enabled)
-							args.v3.sInput.ucDispPllConfig |=
-								DISPPLL_CONFIG_SS_ENABLE;
-					} else {
+					} else if (encoder_mode != ATOM_ENCODER_MODE_LVDS) {
 						if (mode->clock > 165000)
 							args.v3.sInput.ucDispPllConfig |=
 								DISPPLL_CONFIG_DUAL_LINK;
@@ -646,10 +662,12 @@ static u32 atombios_adjust_pll(struct dr
 						   index, (uint32_t *)&args);
 				adjusted_clock = le32_to_cpu(args.v3.sOutput.ulDispPllFreq) * 10;
 				if (args.v3.sOutput.ucRefDiv) {
+					pll->flags |= RADEON_PLL_USE_FRAC_FB_DIV;
 					pll->flags |= RADEON_PLL_USE_REF_DIV;
 					pll->reference_div = args.v3.sOutput.ucRefDiv;
 				}
 				if (args.v3.sOutput.ucPostDiv) {
+					pll->flags |= RADEON_PLL_USE_FRAC_FB_DIV;
 					pll->flags |= RADEON_PLL_USE_POST_DIV;
 					pll->post_div = args.v3.sOutput.ucPostDiv;
 				}
@@ -673,9 +691,14 @@ union set_pixel_clock {
 	PIXEL_CLOCK_PARAMETERS_V2 v2;
 	PIXEL_CLOCK_PARAMETERS_V3 v3;
 	PIXEL_CLOCK_PARAMETERS_V5 v5;
+	PIXEL_CLOCK_PARAMETERS_V6 v6;
 };
 
-static void atombios_crtc_set_dcpll(struct drm_crtc *crtc)
+/* on DCE5, make sure the voltage is high enough to support the
+ * required disp clk.
+ */
+static void atombios_crtc_set_dcpll(struct drm_crtc *crtc,
+				    u32 dispclk)
 {
 	struct drm_device *dev = crtc->dev;
 	struct radeon_device *rdev = dev->dev_private;
@@ -698,9 +721,16 @@ static void atombios_crtc_set_dcpll(stru
 			 * SetPixelClock provides the dividers
 			 */
 			args.v5.ucCRTC = ATOM_CRTC_INVALID;
-			args.v5.usPixelClock = rdev->clock.default_dispclk;
+			args.v5.usPixelClock = cpu_to_le16(dispclk);
 			args.v5.ucPpll = ATOM_DCPLL;
 			break;
+		case 6:
+			/* if the default dcpll clock is specified,
+			 * SetPixelClock provides the dividers
+			 */
+			args.v6.ulDispEngClkFreq = cpu_to_le32(dispclk);
+			args.v6.ucPpll = ATOM_DCPLL;
+			break;
 		default:
 			DRM_ERROR("Unknown table version %d %d\n", frev, crev);
 			return;
@@ -784,6 +814,18 @@ static void atombios_crtc_program_pll(st
 			args.v5.ucEncoderMode = encoder_mode;
 			args.v5.ucPpll = pll_id;
 			break;
+		case 6:
+			args.v6.ulCrtcPclkFreq.ucCRTC = crtc_id;
+			args.v6.ulCrtcPclkFreq.ulPixelClock = cpu_to_le32(clock / 10);
+			args.v6.ucRefDiv = ref_div;
+			args.v6.usFbDiv = cpu_to_le16(fb_div);
+			args.v6.ulFbDivDecFrac = cpu_to_le32(frac_fb_div * 100000);
+			args.v6.ucPostDiv = post_div;
+			args.v6.ucMiscInfo = 0; /* HDMI depth, etc. */
+			args.v6.ucTransmitterID = encoder_id;
+			args.v6.ucEncoderMode = encoder_mode;
+			args.v6.ucPpll = pll_id;
+			break;
 		default:
 			DRM_ERROR("Unknown table version %d %d\n", frev, crev);
 			return;
@@ -915,8 +957,12 @@ static void atombios_crtc_set_pll(struct
 	/* adjust pixel clock as needed */
 	adjusted_clock = atombios_adjust_pll(crtc, mode, pll, ss_enabled, &ss);
 
-	radeon_compute_pll(pll, adjusted_clock, &pll_clock, &fb_div, &frac_fb_div,
-			   &ref_div, &post_div);
+	if (ASIC_IS_AVIVO(rdev))
+		radeon_compute_pll_avivo(pll, adjusted_clock, &pll_clock, &fb_div, &frac_fb_div,
+					 &ref_div, &post_div);
+	else
+		radeon_compute_pll_legacy(pll, adjusted_clock, &pll_clock, &fb_div, &frac_fb_div,
+					  &ref_div, &post_div);
 
 	atombios_crtc_program_ss(crtc, ATOM_DISABLE, radeon_crtc->pll_id, &ss);
 
@@ -945,9 +991,9 @@ static void atombios_crtc_set_pll(struct
 	}
 }
 
-static int evergreen_crtc_do_set_base(struct drm_crtc *crtc,
-				      struct drm_framebuffer *fb,
-				      int x, int y, int atomic)
+static int dce4_crtc_do_set_base(struct drm_crtc *crtc,
+				 struct drm_framebuffer *fb,
+				 int x, int y, int atomic)
 {
 	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
 	struct drm_device *dev = crtc->dev;
@@ -958,6 +1004,7 @@ static int evergreen_crtc_do_set_base(st
 	struct radeon_bo *rbo;
 	uint64_t fb_location;
 	uint32_t fb_format, fb_pitch_pixels, tiling_flags;
+	u32 fb_swap = EVERGREEN_GRPH_ENDIAN_SWAP(EVERGREEN_GRPH_ENDIAN_NONE);
 	int r;
 
 	/* no fb bound */
@@ -1009,11 +1056,17 @@ static int evergreen_crtc_do_set_base(st
 	case 16:
 		fb_format = (EVERGREEN_GRPH_DEPTH(EVERGREEN_GRPH_DEPTH_16BPP) |
 			     EVERGREEN_GRPH_FORMAT(EVERGREEN_GRPH_FORMAT_ARGB565));
+#ifdef __BIG_ENDIAN
+		fb_swap = EVERGREEN_GRPH_ENDIAN_SWAP(EVERGREEN_GRPH_ENDIAN_8IN16);
+#endif
 		break;
 	case 24:
 	case 32:
 		fb_format = (EVERGREEN_GRPH_DEPTH(EVERGREEN_GRPH_DEPTH_32BPP) |
 			     EVERGREEN_GRPH_FORMAT(EVERGREEN_GRPH_FORMAT_ARGB8888));
+#ifdef __BIG_ENDIAN
+		fb_swap = EVERGREEN_GRPH_ENDIAN_SWAP(EVERGREEN_GRPH_ENDIAN_8IN32);
+#endif
 		break;
 	default:
 		DRM_ERROR("Unsupported screen depth %d\n",
@@ -1058,6 +1111,7 @@ static int evergreen_crtc_do_set_base(st
 	WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset,
 	       (u32) fb_location & EVERGREEN_GRPH_SURFACE_ADDRESS_MASK);
 	WREG32(EVERGREEN_GRPH_CONTROL + radeon_crtc->crtc_offset, fb_format);
+	WREG32(EVERGREEN_GRPH_SWAP_CONTROL + radeon_crtc->crtc_offset, fb_swap);
 
 	WREG32(EVERGREEN_GRPH_SURFACE_OFFSET_X + radeon_crtc->crtc_offset, 0);
 	WREG32(EVERGREEN_GRPH_SURFACE_OFFSET_Y + radeon_crtc->crtc_offset, 0);
@@ -1079,12 +1133,6 @@ static int evergreen_crtc_do_set_base(st
 	WREG32(EVERGREEN_VIEWPORT_SIZE + radeon_crtc->crtc_offset,
 	       (crtc->mode.hdisplay << 16) | crtc->mode.vdisplay);
 
-	if (crtc->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);
-
 	if (!atomic && fb && fb != crtc->fb) {
 		radeon_fb = to_radeon_framebuffer(fb);
 		rbo = radeon_fb->obj->driver_private;
@@ -1114,6 +1162,7 @@ static int avivo_crtc_do_set_base(struct
 	struct drm_framebuffer *target_fb;
 	uint64_t fb_location;
 	uint32_t fb_format, fb_pitch_pixels, tiling_flags;
+	u32 fb_swap = R600_D1GRPH_SWAP_ENDIAN_NONE;
 	int r;
 
 	/* no fb bound */
@@ -1167,12 +1216,18 @@ static int avivo_crtc_do_set_base(struct
 		fb_format =
 		    AVIVO_D1GRPH_CONTROL_DEPTH_16BPP |
 		    AVIVO_D1GRPH_CONTROL_16BPP_RGB565;
+#ifdef __BIG_ENDIAN
+		fb_swap = R600_D1GRPH_SWAP_ENDIAN_16BIT;
+#endif
 		break;
 	case 24:
 	case 32:
 		fb_format =
 		    AVIVO_D1GRPH_CONTROL_DEPTH_32BPP |
 		    AVIVO_D1GRPH_CONTROL_32BPP_ARGB8888;
+#ifdef __BIG_ENDIAN
+		fb_swap = R600_D1GRPH_SWAP_ENDIAN_32BIT;
+#endif
 		break;
 	default:
 		DRM_ERROR("Unsupported screen depth %d\n",
@@ -1212,6 +1267,8 @@ static int avivo_crtc_do_set_base(struct
 	WREG32(AVIVO_D1GRPH_SECONDARY_SURFACE_ADDRESS +
 	       radeon_crtc->crtc_offset, (u32) fb_location);
 	WREG32(AVIVO_D1GRPH_CONTROL + radeon_crtc->crtc_offset, fb_format);
+	if (rdev->family >= CHIP_R600)
+		WREG32(R600_D1GRPH_SWAP_CONTROL + radeon_crtc->crtc_offset, fb_swap);
 
 	WREG32(AVIVO_D1GRPH_SURFACE_OFFSET_X + radeon_crtc->crtc_offset, 0);
 	WREG32(AVIVO_D1GRPH_SURFACE_OFFSET_Y + radeon_crtc->crtc_offset, 0);
@@ -1233,12 +1290,6 @@ static int avivo_crtc_do_set_base(struct
 	WREG32(AVIVO_D1MODE_VIEWPORT_SIZE + radeon_crtc->crtc_offset,
 	       (crtc->mode.hdisplay << 16) | crtc->mode.vdisplay);
 
-	if (crtc->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);
-
 	if (!atomic && fb && fb != crtc->fb) {
 		radeon_fb = to_radeon_framebuffer(fb);
 		rbo = radeon_fb->obj->driver_private;
@@ -1262,7 +1313,7 @@ int atombios_crtc_set_base(struct drm_cr
 	struct radeon_device *rdev = dev->dev_private;
 
 	if (ASIC_IS_DCE4(rdev))
-		return evergreen_crtc_do_set_base(crtc, old_fb, x, y, 0);
+		return dce4_crtc_do_set_base(crtc, old_fb, x, y, 0);
 	else if (ASIC_IS_AVIVO(rdev))
 		return avivo_crtc_do_set_base(crtc, old_fb, x, y, 0);
 	else
@@ -1277,7 +1328,7 @@ int atombios_crtc_set_base_atomic(struct
        struct radeon_device *rdev = dev->dev_private;
 
 	if (ASIC_IS_DCE4(rdev))
-		return evergreen_crtc_do_set_base(crtc, fb, x, y, 1);
+		return dce4_crtc_do_set_base(crtc, fb, x, y, 1);
 	else if (ASIC_IS_AVIVO(rdev))
 		return avivo_crtc_do_set_base(crtc, fb, x, y, 1);
 	else
@@ -1377,7 +1428,8 @@ int atombios_crtc_mode_set(struct drm_cr
 								   rdev->clock.default_dispclk);
 		if (ss_enabled)
 			atombios_crtc_program_ss(crtc, ATOM_DISABLE, ATOM_DCPLL, &ss);
-		atombios_crtc_set_dcpll(crtc);
+		/* XXX: DCE5, make sure voltage, dispclk is high enough */
+		atombios_crtc_set_dcpll(crtc, rdev->clock.default_dispclk);
 		if (ss_enabled)
 			atombios_crtc_program_ss(crtc, ATOM_ENABLE, ATOM_DCPLL, &ss);
 	}
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/atombios_dp.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/atombios_dp.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/atombios_dp.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/atombios_dp.c	2011-03-14 21:20:32.000000000 -0400
@@ -187,9 +187,9 @@ static int dp_link_clock_for_mode_clock(
 int dp_mode_valid(u8 dpcd[DP_DPCD_SIZE], int mode_clock)
 {
 	int lanes = dp_lanes_for_mode_clock(dpcd, mode_clock);
-	int bw = dp_lanes_for_mode_clock(dpcd, mode_clock);
+	int dp_clock = dp_link_clock_for_mode_clock(dpcd, mode_clock);
 
-	if ((lanes == 0) || (bw == 0))
+	if ((lanes == 0) || (dp_clock == 0))
 		return MODE_CLOCK_HIGH;
 
 	return MODE_OK;
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/atombios.h linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/atombios.h
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/atombios.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/atombios.h	2011-03-14 21:20:32.000000000 -0400
@@ -73,8 +73,18 @@
 #define ATOM_PPLL1            0
 #define ATOM_PPLL2            1
 #define ATOM_DCPLL            2
+#define ATOM_PPLL0            2
+#define ATOM_EXT_PLL1         8
+#define ATOM_EXT_PLL2         9
+#define ATOM_EXT_CLOCK        10
 #define ATOM_PPLL_INVALID     0xFF
 
+#define ENCODER_REFCLK_SRC_P1PLL       0       
+#define ENCODER_REFCLK_SRC_P2PLL       1
+#define ENCODER_REFCLK_SRC_DCPLL       2
+#define ENCODER_REFCLK_SRC_EXTCLK      3
+#define ENCODER_REFCLK_SRC_INVALID     0xFF
+
 #define ATOM_SCALER1          0
 #define ATOM_SCALER2          1
 
@@ -192,6 +202,9 @@ typedef struct _ATOM_COMMON_TABLE_HEADER
                                   /*Image can't be updated, while Driver needs to carry the new table! */
 }ATOM_COMMON_TABLE_HEADER;
 
+/****************************************************************************/	
+// Structure stores the ROM header.
+/****************************************************************************/	
 typedef struct _ATOM_ROM_HEADER
 {
   ATOM_COMMON_TABLE_HEADER		sHeader;
@@ -221,6 +234,9 @@ typedef struct _ATOM_ROM_HEADER
 	#define	USHORT	void*
 #endif
 
+/****************************************************************************/	
+// Structures used in Command.mtb 
+/****************************************************************************/	
 typedef struct _ATOM_MASTER_LIST_OF_COMMAND_TABLES{
   USHORT ASIC_Init;                              //Function Table, used by various SW components,latest version 1.1
   USHORT GetDisplaySurfaceSize;                  //Atomic Table,  Used by Bios when enabling HW ICON
@@ -312,6 +328,7 @@ typedef struct _ATOM_MASTER_LIST_OF_COMM
 #define SetUniphyInstance                        ASIC_StaticPwrMgtStatusChange
 #define HPDInterruptService                      ReadHWAssistedI2CStatus
 #define EnableVGA_Access                         GetSCLKOverMCLKRatio
+#define GetDispObjectInfo                        EnableYUV 
 
 typedef struct _ATOM_MASTER_COMMAND_TABLE
 {
@@ -357,6 +374,24 @@ typedef struct _ATOM_COMMON_ROM_COMMAND_
 /****************************************************************************/	
 #define COMPUTE_MEMORY_PLL_PARAM        1
 #define COMPUTE_ENGINE_PLL_PARAM        2
+#define ADJUST_MC_SETTING_PARAM         3
+
+/****************************************************************************/	
+// Structures used by AdjustMemoryControllerTable
+/****************************************************************************/	
+typedef struct _ATOM_ADJUST_MEMORY_CLOCK_FREQ
+{
+#if ATOM_BIG_ENDIAN
+  ULONG ulPointerReturnFlag:1;      // BYTE_3[7]=1 - Return the pointer to the right Data Block; BYTE_3[7]=0 - Program the right Data Block 
+  ULONG ulMemoryModuleNumber:7;     // BYTE_3[6:0]
+  ULONG ulClockFreq:24;
+#else
+  ULONG ulClockFreq:24;
+  ULONG ulMemoryModuleNumber:7;     // BYTE_3[6:0]
+  ULONG ulPointerReturnFlag:1;      // BYTE_3[7]=1 - Return the pointer to the right Data Block; BYTE_3[7]=0 - Program the right Data Block 
+#endif
+}ATOM_ADJUST_MEMORY_CLOCK_FREQ;
+#define POINTER_RETURN_FLAG             0x80
 
 typedef struct _COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS
 {
@@ -440,6 +475,26 @@ typedef struct _COMPUTE_MEMORY_ENGINE_PL
 #endif
 }COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_V4;
 
+typedef struct _COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_V5
+{
+  union
+  {
+    ATOM_COMPUTE_CLOCK_FREQ  ulClock;         //Input Parameter
+    ATOM_S_MPLL_FB_DIVIDER   ulFbDiv;         //Output Parameter
+  };
+  UCHAR   ucRefDiv;                           //Output Parameter      
+  UCHAR   ucPostDiv;                          //Output Parameter      
+  union
+  {
+    UCHAR   ucCntlFlag;                       //Output Flags
+    UCHAR   ucInputFlag;                      //Input Flags. ucInputFlag[0] - Strobe(1)/Performance(0) mode
+  };
+  UCHAR   ucReserved;                       
+}COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_V5;
+
+// ucInputFlag
+#define ATOM_PLL_INPUT_FLAG_PLL_STROBE_MODE_EN  1   // 1-StrobeMode, 0-PerformanceMode
+
 typedef struct _DYNAMICE_MEMORY_SETTINGS_PARAMETER
 {
   ATOM_COMPUTE_CLOCK_FREQ ulClock;
@@ -583,6 +638,7 @@ typedef struct _DIG_ENCODER_CONTROL_PARA
 #define ATOM_ENCODER_CONFIG_DPLINKRATE_MASK				0x01
 #define ATOM_ENCODER_CONFIG_DPLINKRATE_1_62GHZ		0x00
 #define ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ		0x01
+#define ATOM_ENCODER_CONFIG_DPLINKRATE_5_40GHZ		0x02
 #define ATOM_ENCODER_CONFIG_LINK_SEL_MASK				  0x04
 #define ATOM_ENCODER_CONFIG_LINKA								  0x00
 #define ATOM_ENCODER_CONFIG_LINKB								  0x04
@@ -608,6 +664,9 @@ typedef struct _DIG_ENCODER_CONTROL_PARA
 #define ATOM_ENCODER_MODE_TV											13
 #define ATOM_ENCODER_MODE_CV											14
 #define ATOM_ENCODER_MODE_CRT											15
+#define ATOM_ENCODER_MODE_DVO											16
+#define ATOM_ENCODER_MODE_DP_SST                  ATOM_ENCODER_MODE_DP    // For DP1.2
+#define ATOM_ENCODER_MODE_DP_MST                  5                       // For DP1.2
 
 typedef struct _ATOM_DIG_ENCODER_CONFIG_V2
 {
@@ -661,6 +720,7 @@ typedef struct _DIG_ENCODER_CONTROL_PARA
 #define ATOM_ENCODER_CMD_DP_LINK_TRAINING_START       0x08
 #define ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN1    0x09
 #define ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN2    0x0a
+#define ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN3    0x13
 #define ATOM_ENCODER_CMD_DP_LINK_TRAINING_COMPLETE    0x0b
 #define ATOM_ENCODER_CMD_DP_VIDEO_OFF                 0x0c
 #define ATOM_ENCODER_CMD_DP_VIDEO_ON                  0x0d
@@ -671,24 +731,34 @@ typedef struct _DIG_ENCODER_CONTROL_PARA
 #define ATOM_ENCODER_STATUS_LINK_TRAINING_COMPLETE    0x10
 #define ATOM_ENCODER_STATUS_LINK_TRAINING_INCOMPLETE  0x00
 
+//ucTableFormatRevision=1
+//ucTableContentRevision=3
 // Following function ENABLE sub-function will be used by driver when TMDS/HDMI/LVDS is used, disable function will be used by driver
 typedef struct _ATOM_DIG_ENCODER_CONFIG_V3
 {
 #if ATOM_BIG_ENDIAN
     UCHAR ucReserved1:1;
-    UCHAR ucDigSel:3;             // =0: DIGA/B/C/D/E/F
+    UCHAR ucDigSel:3;             // =0/1/2/3/4/5: DIG0/1/2/3/4/5 (In register spec also refered as DIGA/B/C/D/E/F)
     UCHAR ucReserved:3;
     UCHAR ucDPLinkRate:1;         // =0: 1.62Ghz, =1: 2.7Ghz
 #else
     UCHAR ucDPLinkRate:1;         // =0: 1.62Ghz, =1: 2.7Ghz
     UCHAR ucReserved:3;
-    UCHAR ucDigSel:3;             // =0: DIGA/B/C/D/E/F
+    UCHAR ucDigSel:3;             // =0/1/2/3/4/5: DIG0/1/2/3/4/5 (In register spec also refered as DIGA/B/C/D/E/F)
     UCHAR ucReserved1:1;
 #endif
 }ATOM_DIG_ENCODER_CONFIG_V3;
 
+#define ATOM_ENCODER_CONFIG_V3_DPLINKRATE_MASK				0x03
+#define ATOM_ENCODER_CONFIG_V3_DPLINKRATE_1_62GHZ		  0x00
+#define ATOM_ENCODER_CONFIG_V3_DPLINKRATE_2_70GHZ		  0x01
 #define ATOM_ENCODER_CONFIG_V3_ENCODER_SEL					  0x70
-
+#define ATOM_ENCODER_CONFIG_V3_DIG0_ENCODER					  0x00
+#define ATOM_ENCODER_CONFIG_V3_DIG1_ENCODER					  0x10
+#define ATOM_ENCODER_CONFIG_V3_DIG2_ENCODER					  0x20
+#define ATOM_ENCODER_CONFIG_V3_DIG3_ENCODER					  0x30
+#define ATOM_ENCODER_CONFIG_V3_DIG4_ENCODER					  0x40
+#define ATOM_ENCODER_CONFIG_V3_DIG5_ENCODER					  0x50
 
 typedef struct _DIG_ENCODER_CONTROL_PARAMETERS_V3
 {
@@ -707,6 +777,56 @@ typedef struct _DIG_ENCODER_CONTROL_PARA
   UCHAR ucReserved;
 }DIG_ENCODER_CONTROL_PARAMETERS_V3;
 
+//ucTableFormatRevision=1
+//ucTableContentRevision=4
+// start from NI           
+// Following function ENABLE sub-function will be used by driver when TMDS/HDMI/LVDS is used, disable function will be used by driver
+typedef struct _ATOM_DIG_ENCODER_CONFIG_V4
+{
+#if ATOM_BIG_ENDIAN
+    UCHAR ucReserved1:1;
+    UCHAR ucDigSel:3;             // =0/1/2/3/4/5: DIG0/1/2/3/4/5 (In register spec also refered as DIGA/B/C/D/E/F)
+    UCHAR ucReserved:2;
+    UCHAR ucDPLinkRate:2;         // =0: 1.62Ghz, =1: 2.7Ghz, 2=5.4Ghz    <= Changed comparing to previous version
+#else
+    UCHAR ucDPLinkRate:2;         // =0: 1.62Ghz, =1: 2.7Ghz, 2=5.4Ghz    <= Changed comparing to previous version
+    UCHAR ucReserved:2;
+    UCHAR ucDigSel:3;             // =0/1/2/3/4/5: DIG0/1/2/3/4/5 (In register spec also refered as DIGA/B/C/D/E/F)
+    UCHAR ucReserved1:1;
+#endif
+}ATOM_DIG_ENCODER_CONFIG_V4;
+
+#define ATOM_ENCODER_CONFIG_V4_DPLINKRATE_MASK				0x03
+#define ATOM_ENCODER_CONFIG_V4_DPLINKRATE_1_62GHZ		  0x00
+#define ATOM_ENCODER_CONFIG_V4_DPLINKRATE_2_70GHZ		  0x01
+#define ATOM_ENCODER_CONFIG_V4_DPLINKRATE_5_40GHZ		  0x02
+#define ATOM_ENCODER_CONFIG_V4_ENCODER_SEL					  0x70
+#define ATOM_ENCODER_CONFIG_V4_DIG0_ENCODER					  0x00
+#define ATOM_ENCODER_CONFIG_V4_DIG1_ENCODER					  0x10
+#define ATOM_ENCODER_CONFIG_V4_DIG2_ENCODER					  0x20
+#define ATOM_ENCODER_CONFIG_V4_DIG3_ENCODER					  0x30
+#define ATOM_ENCODER_CONFIG_V4_DIG4_ENCODER					  0x40
+#define ATOM_ENCODER_CONFIG_V4_DIG5_ENCODER					  0x50
+
+typedef struct _DIG_ENCODER_CONTROL_PARAMETERS_V4
+{
+  USHORT usPixelClock;      // in 10KHz; for bios convenient
+  union{
+  ATOM_DIG_ENCODER_CONFIG_V4 acConfig;
+  UCHAR ucConfig;
+  };
+  UCHAR ucAction;                              
+  UCHAR ucEncoderMode;
+                            // =0: DP   encoder      
+                            // =1: LVDS encoder          
+                            // =2: DVI  encoder  
+                            // =3: HDMI encoder
+                            // =4: SDVO encoder
+                            // =5: DP audio
+  UCHAR ucLaneNum;          // how many lanes to enable
+  UCHAR ucBitPerColor;      // only valid for DP mode when ucAction = ATOM_ENCODER_CMD_SETUP
+  UCHAR ucHPD_ID;           // HPD ID (1-6). =0 means to skip HDP programming. New comparing to previous version
+}DIG_ENCODER_CONTROL_PARAMETERS_V4;
 
 // define ucBitPerColor: 
 #define PANEL_BPC_UNDEFINE                               0x00
@@ -893,6 +1013,7 @@ typedef struct _ATOM_DIG_TRANSMITTER_CON
 #endif
 }ATOM_DIG_TRANSMITTER_CONFIG_V3;
 
+
 typedef struct _DIG_TRANSMITTER_CONTROL_PARAMETERS_V3
 {
 	union
@@ -936,6 +1057,149 @@ typedef struct _DIG_TRANSMITTER_CONTROL_
 #define ATOM_TRANSMITTER_CONFIG_V3_TRANSMITTER2           	0x40	//CD
 #define ATOM_TRANSMITTER_CONFIG_V3_TRANSMITTER3           	0x80	//EF
 
+
+/****************************************************************************/	
+// Structures used by UNIPHYTransmitterControlTable V1.4
+// ASIC Families: NI
+// ucTableFormatRevision=1
+// ucTableContentRevision=4
+/****************************************************************************/	
+typedef struct _ATOM_DP_VS_MODE_V4
+{
+  UCHAR ucLaneSel;
+ 	union
+ 	{  
+ 	  UCHAR ucLaneSet;
+ 	  struct {
+#if ATOM_BIG_ENDIAN
+ 		  UCHAR ucPOST_CURSOR2:2;         //Bit[7:6] Post Cursor2 Level      <= New in V4
+ 		  UCHAR ucPRE_EMPHASIS:3;         //Bit[5:3] Pre-emphasis Level
+ 		  UCHAR ucVOLTAGE_SWING:3;        //Bit[2:0] Voltage Swing Level
+#else
+ 		  UCHAR ucVOLTAGE_SWING:3;        //Bit[2:0] Voltage Swing Level
+ 		  UCHAR ucPRE_EMPHASIS:3;         //Bit[5:3] Pre-emphasis Level
+ 		  UCHAR ucPOST_CURSOR2:2;         //Bit[7:6] Post Cursor2 Level      <= New in V4
+#endif
+ 		};
+ 	}; 
+}ATOM_DP_VS_MODE_V4;
+ 
+typedef struct _ATOM_DIG_TRANSMITTER_CONFIG_V4
+{
+#if ATOM_BIG_ENDIAN
+  UCHAR ucTransmitterSel:2;         //bit7:6: =0 Dig Transmitter 1 ( Uniphy AB )
+                                    //        =1 Dig Transmitter 2 ( Uniphy CD )
+                                    //        =2 Dig Transmitter 3 ( Uniphy EF )
+  UCHAR ucRefClkSource:2;           //bit5:4: PPLL1 =0, PPLL2=1, DCPLL=2, EXT_CLK=3   <= New
+  UCHAR ucEncoderSel:1;             //bit3=0: Data/Clk path source from DIGA/C/E. =1: Data/clk path source from DIGB/D/F
+  UCHAR ucLinkSel:1;                //bit2=0: Uniphy LINKA or C or E when fDualLinkConnector=0. when fDualLinkConnector=1, it means master link of dual link is A or C or E
+                                    //    =1: Uniphy LINKB or D or F when fDualLinkConnector=0. when fDualLinkConnector=1, it means master link of dual link is B or D or F
+  UCHAR fCoherentMode:1;            //bit1=1: Coherent Mode ( for DVI/HDMI mode )
+  UCHAR fDualLinkConnector:1;       //bit0=1: Dual Link DVI connector
+#else
+  UCHAR fDualLinkConnector:1;       //bit0=1: Dual Link DVI connector
+  UCHAR fCoherentMode:1;            //bit1=1: Coherent Mode ( for DVI/HDMI mode )
+  UCHAR ucLinkSel:1;                //bit2=0: Uniphy LINKA or C or E when fDualLinkConnector=0. when fDualLinkConnector=1, it means master link of dual link is A or C or E
+                                    //    =1: Uniphy LINKB or D or F when fDualLinkConnector=0. when fDualLinkConnector=1, it means master link of dual link is B or D or F
+  UCHAR ucEncoderSel:1;             //bit3=0: Data/Clk path source from DIGA/C/E. =1: Data/clk path source from DIGB/D/F
+  UCHAR ucRefClkSource:2;           //bit5:4: PPLL1 =0, PPLL2=1, DCPLL=2, EXT_CLK=3   <= New
+  UCHAR ucTransmitterSel:2;         //bit7:6: =0 Dig Transmitter 1 ( Uniphy AB )
+                                    //        =1 Dig Transmitter 2 ( Uniphy CD )
+                                    //        =2 Dig Transmitter 3 ( Uniphy EF )
+#endif
+}ATOM_DIG_TRANSMITTER_CONFIG_V4;
+
+typedef struct _DIG_TRANSMITTER_CONTROL_PARAMETERS_V4
+{
+  union
+  {
+    USHORT usPixelClock;		// in 10KHz; for bios convenient
+    USHORT usInitInfo;			// when init uniphy,lower 8bit is used for connector type defined in objectid.h
+    ATOM_DP_VS_MODE_V4 asMode; // DP Voltage swing mode     Redefined comparing to previous version
+  };
+  union
+  {
+  ATOM_DIG_TRANSMITTER_CONFIG_V4 acConfig;
+  UCHAR ucConfig;
+  };
+  UCHAR ucAction;				    // define as ATOM_TRANSMITER_ACTION_XXX	                        
+  UCHAR ucLaneNum;
+  UCHAR ucReserved[3];
+}DIG_TRANSMITTER_CONTROL_PARAMETERS_V4;
+
+//ucConfig 
+//Bit0
+#define ATOM_TRANSMITTER_CONFIG_V4_DUAL_LINK_CONNECTOR			0x01
+//Bit1
+#define ATOM_TRANSMITTER_CONFIG_V4_COHERENT				          0x02
+//Bit2
+#define ATOM_TRANSMITTER_CONFIG_V4_LINK_SEL_MASK		        0x04
+#define ATOM_TRANSMITTER_CONFIG_V4_LINKA  			            0x00			
+#define ATOM_TRANSMITTER_CONFIG_V4_LINKB				            0x04
+// Bit3
+#define ATOM_TRANSMITTER_CONFIG_V4_ENCODER_SEL_MASK	        0x08
+#define ATOM_TRANSMITTER_CONFIG_V4_DIG1_ENCODER		          0x00				 
+#define ATOM_TRANSMITTER_CONFIG_V4_DIG2_ENCODER		          0x08				
+// Bit5:4
+#define ATOM_TRANSMITTER_CONFIG_V4_REFCLK_SEL_MASK 	        0x30
+#define ATOM_TRANSMITTER_CONFIG_V4_P1PLL         		        0x00
+#define ATOM_TRANSMITTER_CONFIG_V4_P2PLL		                0x10
+#define ATOM_TRANSMITTER_CONFIG_V4_DCPLL		                0x20   // New in _V4
+#define ATOM_TRANSMITTER_CONFIG_V4_REFCLK_SRC_EXT           0x30   // Changed comparing to V3
+// Bit7:6
+#define ATOM_TRANSMITTER_CONFIG_V4_TRANSMITTER_SEL_MASK     0xC0
+#define ATOM_TRANSMITTER_CONFIG_V4_TRANSMITTER1           	0x00	//AB
+#define ATOM_TRANSMITTER_CONFIG_V4_TRANSMITTER2           	0x40	//CD
+#define ATOM_TRANSMITTER_CONFIG_V4_TRANSMITTER3           	0x80	//EF
+
+
+/****************************************************************************/	
+// Structures used by ExternalEncoderControlTable V1.3
+// ASIC Families: Evergreen, Llano, NI
+// ucTableFormatRevision=1
+// ucTableContentRevision=3
+/****************************************************************************/	
+
+typedef struct _EXTERNAL_ENCODER_CONTROL_PARAMETERS_V3
+{
+  union{
+  USHORT usPixelClock;      // pixel clock in 10Khz, valid when ucAction=SETUP/ENABLE_OUTPUT 
+  USHORT usConnectorId;     // connector id, valid when ucAction = INIT
+  };
+  UCHAR  ucConfig;          // indicate which encoder, and DP link rate when ucAction = SETUP/ENABLE_OUTPUT  
+  UCHAR  ucAction;          // 
+  UCHAR  ucEncoderMode;     // encoder mode, only used when ucAction = SETUP/ENABLE_OUTPUT
+  UCHAR  ucLaneNum;         // lane number, only used when ucAction = SETUP/ENABLE_OUTPUT  
+  UCHAR  ucBitPerColor;     // output bit per color, only valid when ucAction = SETUP/ENABLE_OUTPUT and ucEncodeMode= DP
+  UCHAR  ucReserved;        
+}EXTERNAL_ENCODER_CONTROL_PARAMETERS_V3;
+
+// ucAction
+#define EXTERNAL_ENCODER_ACTION_V3_DISABLE_OUTPUT         0x00
+#define EXTERNAL_ENCODER_ACTION_V3_ENABLE_OUTPUT          0x01
+#define EXTERNAL_ENCODER_ACTION_V3_ENCODER_INIT           0x07
+#define EXTERNAL_ENCODER_ACTION_V3_ENCODER_SETUP          0x0f
+#define EXTERNAL_ENCODER_ACTION_V3_ENCODER_BLANKING_OFF   0x10
+#define EXTERNAL_ENCODER_ACTION_V3_ENCODER_BLANKING       0x11
+#define EXTERNAL_ENCODER_ACTION_V3_DACLOAD_DETECTION      0x12
+
+// ucConfig
+#define EXTERNAL_ENCODER_CONFIG_V3_DPLINKRATE_MASK				0x03
+#define EXTERNAL_ENCODER_CONFIG_V3_DPLINKRATE_1_62GHZ		  0x00
+#define EXTERNAL_ENCODER_CONFIG_V3_DPLINKRATE_2_70GHZ		  0x01
+#define EXTERNAL_ENCODER_CONFIG_V3_DPLINKRATE_5_40GHZ		  0x02
+#define EXTERNAL_ENCODER_CONFIG_V3_ENCODER_SEL_MASK		    0x70
+#define EXTERNAL_ENCODER_CONFIG_V3_ENCODER1		            0x00
+#define EXTERNAL_ENCODER_CONFIG_V3_ENCODER2		            0x10
+#define EXTERNAL_ENCODER_CONFIG_V3_ENCODER3		            0x20
+
+typedef struct _EXTERNAL_ENCODER_CONTROL_PS_ALLOCATION_V3
+{
+  EXTERNAL_ENCODER_CONTROL_PARAMETERS_V3 sExtEncoder;
+  ULONG ulReserved[2];
+}EXTERNAL_ENCODER_CONTROL_PS_ALLOCATION_V3;
+
+
 /****************************************************************************/	
 // Structures used by DAC1OuputControlTable
 //                    DAC2OuputControlTable
@@ -1142,6 +1406,7 @@ typedef struct _PIXEL_CLOCK_PARAMETERS_V
 #define PIXEL_CLOCK_V4_MISC_SS_ENABLE               0x10
 #define PIXEL_CLOCK_V4_MISC_COHERENT_MODE           0x20
 
+
 typedef struct _PIXEL_CLOCK_PARAMETERS_V3
 {
   USHORT usPixelClock;                // in 10kHz unit; for bios convenient = (RefClk*FB_Div)/(Ref_Div*Post_Div)
@@ -1202,6 +1467,55 @@ typedef struct _PIXEL_CLOCK_PARAMETERS_V
 #define PIXEL_CLOCK_V5_MISC_HDMI_32BPP              0x08
 #define PIXEL_CLOCK_V5_MISC_REF_DIV_SRC             0x10
 
+typedef struct _CRTC_PIXEL_CLOCK_FREQ
+{
+#if ATOM_BIG_ENDIAN
+  ULONG  ucCRTC:8;            // ATOM_CRTC1~6, indicate the CRTC controller to 
+                              // drive the pixel clock. not used for DCPLL case.
+  ULONG  ulPixelClock:24;     // target the pixel clock to drive the CRTC timing. 
+                              // 0 means disable PPLL/DCPLL. Expanded to 24 bits comparing to previous version.
+#else
+  ULONG  ulPixelClock:24;     // target the pixel clock to drive the CRTC timing. 
+                              // 0 means disable PPLL/DCPLL. Expanded to 24 bits comparing to previous version.
+  ULONG  ucCRTC:8;            // ATOM_CRTC1~6, indicate the CRTC controller to 
+                              // drive the pixel clock. not used for DCPLL case.
+#endif
+}CRTC_PIXEL_CLOCK_FREQ;
+
+typedef struct _PIXEL_CLOCK_PARAMETERS_V6
+{
+  union{
+    CRTC_PIXEL_CLOCK_FREQ ulCrtcPclkFreq;    // pixel clock and CRTC id frequency 
+    ULONG ulDispEngClkFreq;                  // dispclk frequency
+  };
+  USHORT usFbDiv;            // feedback divider integer part. 
+  UCHAR  ucPostDiv;          // post divider. 
+  UCHAR  ucRefDiv;           // Reference divider
+  UCHAR  ucPpll;             // ATOM_PPLL1/ATOM_PPLL2/ATOM_DCPLL
+  UCHAR  ucTransmitterID;    // ASIC encoder id defined in objectId.h, 
+                             // indicate which graphic encoder will be used. 
+  UCHAR  ucEncoderMode;      // Encoder mode: 
+  UCHAR  ucMiscInfo;         // bit[0]= Force program PPLL 
+                             // bit[1]= when VGA timing is used. 
+                             // bit[3:2]= HDMI panel bit depth: =0: 24bpp =1:30bpp, =2:32bpp
+                             // bit[4]= RefClock source for PPLL. 
+                             // =0: XTLAIN( default mode )
+	                           // =1: other external clock source, which is pre-defined                                            
+                             //     by VBIOS depend on the feature required.
+                             // bit[7:5]: reserved.
+  ULONG  ulFbDivDecFrac;     // 20 bit feedback divider decimal fraction part, range from 1~999999 ( 0.000001 to 0.999999 )
+
+}PIXEL_CLOCK_PARAMETERS_V6;
+
+#define PIXEL_CLOCK_V6_MISC_FORCE_PROG_PPLL					0x01
+#define PIXEL_CLOCK_V6_MISC_VGA_MODE								0x02
+#define PIXEL_CLOCK_V6_MISC_HDMI_BPP_MASK           0x0c
+#define PIXEL_CLOCK_V6_MISC_HDMI_24BPP              0x00
+#define PIXEL_CLOCK_V6_MISC_HDMI_36BPP              0x04
+#define PIXEL_CLOCK_V6_MISC_HDMI_30BPP              0x08
+#define PIXEL_CLOCK_V6_MISC_HDMI_48BPP              0x0c
+#define PIXEL_CLOCK_V6_MISC_REF_DIV_SRC             0x10
+
 typedef struct _GET_DISP_PLL_STATUS_INPUT_PARAMETERS_V2
 {
   PIXEL_CLOCK_PARAMETERS_V3 sDispClkInput;
@@ -1241,10 +1555,11 @@ typedef struct _ADJUST_DISPLAY_PLL_PARAM
 typedef struct _ADJUST_DISPLAY_PLL_INPUT_PARAMETERS_V3
 {
 	USHORT usPixelClock;                    // target pixel clock
-	UCHAR ucTransmitterID;                  // transmitter id defined in objectid.h
+	UCHAR ucTransmitterID;                  // GPU transmitter id defined in objectid.h
 	UCHAR ucEncodeMode;                     // encoder mode: CRT, LVDS, DP, TMDS or HDMI
   UCHAR ucDispPllConfig;                 // display pll configure parameter defined as following DISPPLL_CONFIG_XXXX
-	UCHAR ucReserved[3];
+  UCHAR ucExtTransmitterID;               // external encoder id.
+	UCHAR ucReserved[2];
 }ADJUST_DISPLAY_PLL_INPUT_PARAMETERS_V3;
 
 // usDispPllConfig v1.2 for RoadRunner
@@ -1314,7 +1629,7 @@ typedef struct _GET_ENGINE_CLOCK_PARAMET
 typedef struct _READ_EDID_FROM_HW_I2C_DATA_PARAMETERS
 {
   USHORT    usPrescale;         //Ratio between Engine clock and I2C clock
-  USHORT    usVRAMAddress;      //Adress in Frame Buffer where to pace raw EDID
+  USHORT    usVRAMAddress;      //Address in Frame Buffer where to pace raw EDID
   USHORT    usStatus;           //When use output: lower byte EDID checksum, high byte hardware status
                                 //WHen use input:  lower byte as 'byte to read':currently limited to 128byte or 1byte
   UCHAR     ucSlaveAddr;        //Read from which slave
@@ -1358,6 +1673,7 @@ typedef struct _SET_UP_HW_I2C_DATA_PARAM
 /**************************************************************************/
 #define SPEED_FAN_CONTROL_PS_ALLOCATION   WRITE_ONE_BYTE_HW_I2C_DATA_PARAMETERS
 
+
 /****************************************************************************/	
 // Structures used by PowerConnectorDetectionTable
 /****************************************************************************/	
@@ -1438,6 +1754,31 @@ typedef struct _ENABLE_SPREAD_SPECTRUM_O
 #define ATOM_PPLL_SS_AMOUNT_V2_NFRAC_MASK     0x0F00
 #define ATOM_PPLL_SS_AMOUNT_V2_NFRAC_SHIFT    8
 
+// Used by DCE5.0
+ typedef struct _ENABLE_SPREAD_SPECTRUM_ON_PPLL_V3
+{
+  USHORT  usSpreadSpectrumAmountFrac;   // SS_AMOUNT_DSFRAC New in DCE5.0
+  UCHAR   ucSpreadSpectrumType;	        // Bit[0]: 0-Down Spread,1-Center Spread. 
+                                        // Bit[1]: 1-Ext. 0-Int. 
+                                        // Bit[3:2]: =0 P1PLL =1 P2PLL =2 DCPLL
+                                        // Bits[7:4] reserved
+  UCHAR   ucEnable;	                    // ATOM_ENABLE or ATOM_DISABLE
+  USHORT  usSpreadSpectrumAmount;      	// Includes SS_AMOUNT_FBDIV[7:0] and SS_AMOUNT_NFRAC_SLIP[11:8]    
+  USHORT  usSpreadSpectrumStep;	        // SS_STEP_SIZE_DSFRAC
+}ENABLE_SPREAD_SPECTRUM_ON_PPLL_V3;
+    
+#define ATOM_PPLL_SS_TYPE_V3_DOWN_SPREAD      0x00
+#define ATOM_PPLL_SS_TYPE_V3_CENTRE_SPREAD    0x01
+#define ATOM_PPLL_SS_TYPE_V3_EXT_SPREAD       0x02
+#define ATOM_PPLL_SS_TYPE_V3_PPLL_SEL_MASK    0x0c
+#define ATOM_PPLL_SS_TYPE_V3_P1PLL            0x00
+#define ATOM_PPLL_SS_TYPE_V3_P2PLL            0x04
+#define ATOM_PPLL_SS_TYPE_V3_DCPLL            0x08
+#define ATOM_PPLL_SS_AMOUNT_V3_FBDIV_MASK     0x00FF
+#define ATOM_PPLL_SS_AMOUNT_V3_FBDIV_SHIFT    0
+#define ATOM_PPLL_SS_AMOUNT_V3_NFRAC_MASK     0x0F00
+#define ATOM_PPLL_SS_AMOUNT_V3_NFRAC_SHIFT    8
+
 #define ENABLE_SPREAD_SPECTRUM_ON_PPLL_PS_ALLOCATION  ENABLE_SPREAD_SPECTRUM_ON_PPLL
 
 /**************************************************************************/
@@ -1706,7 +2047,7 @@ typedef struct _ATOM_MASTER_LIST_OF_DATA
   USHORT        StandardVESA_Timing;      // Only used by Bios
   USHORT        FirmwareInfo;             // Shared by various SW components,latest version 1.4
   USHORT        DAC_Info;                 // Will be obsolete from R600
-  USHORT        LVDS_Info;                // Shared by various SW components,latest version 1.1 
+  USHORT        LCD_Info;                 // Shared by various SW components,latest version 1.3, was called LVDS_Info 
   USHORT        TMDS_Info;                // Will be obsolete from R600
   USHORT        AnalogTV_Info;            // Shared by various SW components,latest version 1.1 
   USHORT        SupportedDevicesInfo;     // Will be obsolete from R600
@@ -1736,12 +2077,16 @@ typedef struct _ATOM_MASTER_LIST_OF_DATA
 	USHORT				PowerSourceInfo;					// Shared by various SW components, latest versoin 1.1
 }ATOM_MASTER_LIST_OF_DATA_TABLES;
 
+// For backward compatible 
+#define LVDS_Info                LCD_Info
+
 typedef struct _ATOM_MASTER_DATA_TABLE
 { 
   ATOM_COMMON_TABLE_HEADER sHeader;  
   ATOM_MASTER_LIST_OF_DATA_TABLES   ListOfDataTables;
 }ATOM_MASTER_DATA_TABLE;
 
+
 /****************************************************************************/	
 // Structure used in MultimediaCapabilityInfoTable
 /****************************************************************************/	
@@ -1776,6 +2121,7 @@ typedef struct _ATOM_MULTIMEDIA_CONFIG_I
   UCHAR                    ucVideoInput4Info;// Video Input 4 Type (1:0) F/B setting (2) physical connector ID (5:3) reserved (7:6)
 }ATOM_MULTIMEDIA_CONFIG_INFO;
 
+
 /****************************************************************************/	
 // Structures used in FirmwareInfoTable
 /****************************************************************************/	
@@ -2031,8 +2377,47 @@ typedef struct _ATOM_FIRMWARE_INFO_V2_1
   UCHAR                           ucReserved4[3];
 }ATOM_FIRMWARE_INFO_V2_1;
 
+//the structure below to be used from NI
+//ucTableFormatRevision=2
+//ucTableContentRevision=2
+typedef struct _ATOM_FIRMWARE_INFO_V2_2
+{
+  ATOM_COMMON_TABLE_HEADER        sHeader; 
+  ULONG                           ulFirmwareRevision;
+  ULONG                           ulDefaultEngineClock;       //In 10Khz unit
+  ULONG                           ulDefaultMemoryClock;       //In 10Khz unit
+  ULONG                           ulReserved[2];
+  ULONG                           ulReserved1;                //Was ulMaxEngineClockPLL_Output; //In 10Khz unit*
+  ULONG                           ulReserved2;                //Was ulMaxMemoryClockPLL_Output; //In 10Khz unit*
+  ULONG                           ulMaxPixelClockPLL_Output;  //In 10Khz unit
+  ULONG                           ulBinaryAlteredInfo;        //Was ulASICMaxEngineClock  ?
+  ULONG                           ulDefaultDispEngineClkFreq; //In 10Khz unit. This is the frequency before DCDTO, corresponding to usBootUpVDDCVoltage.          
+  UCHAR                           ucReserved3;                //Was ucASICMaxTemperature;
+  UCHAR                           ucMinAllowedBL_Level;
+  USHORT                          usBootUpVDDCVoltage;        //In MV unit
+  USHORT                          usLcdMinPixelClockPLL_Output; // In MHz unit
+  USHORT                          usLcdMaxPixelClockPLL_Output; // In MHz unit
+  ULONG                           ulReserved4;                //Was ulAsicMaximumVoltage
+  ULONG                           ulMinPixelClockPLL_Output;  //In 10Khz unit
+  ULONG                           ulReserved5;                //Was usMinEngineClockPLL_Input and usMaxEngineClockPLL_Input
+  ULONG                           ulReserved6;                //Was usMinEngineClockPLL_Output and usMinMemoryClockPLL_Input
+  ULONG                           ulReserved7;                //Was usMaxMemoryClockPLL_Input and usMinMemoryClockPLL_Output
+  USHORT                          usReserved11;               //Was usMaxPixelClock;  //In 10Khz unit, Max.  Pclk used only for DAC
+  USHORT                          usMinPixelClockPLL_Input;   //In 10Khz unit
+  USHORT                          usMaxPixelClockPLL_Input;   //In 10Khz unit
+  USHORT                          usBootUpVDDCIVoltage;       //In unit of mv; Was usMinPixelClockPLL_Output;
+  ATOM_FIRMWARE_CAPABILITY_ACCESS usFirmwareCapability;
+  USHORT                          usCoreReferenceClock;       //In 10Khz unit	
+  USHORT                          usMemoryReferenceClock;     //In 10Khz unit	
+  USHORT                          usUniphyDPModeExtClkFreq;   //In 10Khz unit, if it is 0, In DP Mode Uniphy Input clock from internal PPLL, otherwise Input clock from external Spread clock
+  UCHAR                           ucMemoryModule_ID;          //Indicate what is the board design
+  UCHAR                           ucReserved9[3];
+  USHORT                          usBootUpMVDDCVoltage;       //In unit of mv; Was usMinPixelClockPLL_Output;
+  USHORT                          usReserved12;
+  ULONG                           ulReserved10[3];            // New added comparing to previous version
+}ATOM_FIRMWARE_INFO_V2_2;
 
-#define ATOM_FIRMWARE_INFO_LAST  ATOM_FIRMWARE_INFO_V2_1
+#define ATOM_FIRMWARE_INFO_LAST  ATOM_FIRMWARE_INFO_V2_2
 
 /****************************************************************************/	
 // Structures used in IntegratedSystemInfoTable
@@ -2212,7 +2597,7 @@ ulDockingPinCFGInfo: [15:0]-Bus/Device/F
 ucDockingPinBit:     which bit in this register to read the pin status;
 ucDockingPinPolarity:Polarity of the pin when docked;
 
-ulCPUCapInfo:        [7:0]=1:Griffin;[7:0]=2:Greyhound;[7:0]=3:K8, other bits reserved for now and must be 0x0
+ulCPUCapInfo:        [7:0]=1:Griffin;[7:0]=2:Greyhound;[7:0]=3:K8, [7:0]=4:Pharaoh, other bits reserved for now and must be 0x0
 
 usNumberOfCyclesInPeriod:Indicate how many cycles when PWM duty is 100%.
 
@@ -2250,6 +2635,14 @@ usMinUpStreamHTLinkWidth:    Asymmetric
 usMinDownStreamHTLinkWidth:  same as above.
 */
 
+// ATOM_INTEGRATED_SYSTEM_INFO::ulCPUCapInfo  - CPU type definition 
+#define    INTEGRATED_SYSTEM_INFO__UNKNOWN_CPU             0
+#define    INTEGRATED_SYSTEM_INFO__AMD_CPU__GRIFFIN        1
+#define    INTEGRATED_SYSTEM_INFO__AMD_CPU__GREYHOUND      2
+#define    INTEGRATED_SYSTEM_INFO__AMD_CPU__K8             3
+#define    INTEGRATED_SYSTEM_INFO__AMD_CPU__PHARAOH        4
+
+#define    INTEGRATED_SYSTEM_INFO__AMD_CPU__MAX_CODE       INTEGRATED_SYSTEM_INFO__AMD_CPU__PHARAOH    // this deff reflects max defined CPU code
 
 #define SYSTEM_CONFIG_POWEREXPRESS_ENABLE                 0x00000001
 #define SYSTEM_CONFIG_RUN_AT_OVERDRIVE_ENGINE             0x00000002
@@ -2778,8 +3171,88 @@ typedef struct _ATOM_LVDS_INFO_V12
 #define PANEL_RANDOM_DITHER   0x80
 #define PANEL_RANDOM_DITHER_MASK   0x80
 
+#define ATOM_LVDS_INFO_LAST  ATOM_LVDS_INFO_V12   // no need to change this 
 
-#define ATOM_LVDS_INFO_LAST  ATOM_LVDS_INFO_V12
+/****************************************************************************/	
+// Structures used by LCD_InfoTable V1.3    Note: previous version was called ATOM_LVDS_INFO_V12
+// ASIC Families:  NI
+// ucTableFormatRevision=1
+// ucTableContentRevision=3
+/****************************************************************************/	
+typedef struct _ATOM_LCD_INFO_V13
+{
+  ATOM_COMMON_TABLE_HEADER sHeader;  
+  ATOM_DTD_FORMAT     sLCDTiming;
+  USHORT              usExtInfoTableOffset;
+  USHORT              usSupportedRefreshRate;     //Refer to panel info table in ATOMBIOS extension Spec.
+  ULONG               ulReserved0;
+  UCHAR               ucLCD_Misc;                // Reorganized in V13
+                                                 // Bit0: {=0:single, =1:dual},
+                                                 // Bit1: {=0:LDI format for RGB888, =1 FPDI format for RGB888}  // was {=0:666RGB, =1:888RGB},
+                                                 // Bit3:2: {Grey level}
+                                                 // Bit6:4 Color Bit Depth definition (see below definition in EDID V1.4 @BYTE 14h) 
+                                                 // Bit7   Reserved.  was for ATOM_PANEL_MISC_API_ENABLED, still need it?  
+  UCHAR               ucPanelDefaultRefreshRate;
+  UCHAR               ucPanelIdentification;
+  UCHAR               ucSS_Id;
+  USHORT              usLCDVenderID;
+  USHORT              usLCDProductID;
+  UCHAR               ucLCDPanel_SpecialHandlingCap;  // Reorganized in V13 
+                                                 // Bit0: Once DAL sees this CAP is set, it will read EDID from LCD on its own
+                                                 // Bit1: See LCDPANEL_CAP_DRR_SUPPORTED
+                                                 // Bit2: a quick reference whether an embadded panel (LCD1 ) is LVDS (0) or eDP (1)
+                                                 // Bit7-3: Reserved 
+  UCHAR               ucPanelInfoSize;					 //  start from ATOM_DTD_FORMAT to end of panel info, include ExtInfoTable
+  USHORT              usBacklightPWM;            //  Backlight PWM in Hz. New in _V13
+
+  UCHAR               ucPowerSequenceDIGONtoDE_in4Ms;
+  UCHAR               ucPowerSequenceDEtoVARY_BL_in4Ms;
+  UCHAR               ucPowerSequenceDEtoDIGON_in4Ms;
+  UCHAR               ucPowerSequenceVARY_BLtoDE_in4Ms;
+
+  UCHAR               ucOffDelay_in4Ms;
+  UCHAR               ucPowerSequenceVARY_BLtoBLON_in4Ms;
+  UCHAR               ucPowerSequenceBLONtoVARY_BL_in4Ms;
+  UCHAR               ucReserved1;
+
+  ULONG               ulReserved[4];
+}ATOM_LCD_INFO_V13;  
+
+#define ATOM_LCD_INFO_LAST  ATOM_LCD_INFO_V13    
+
+//Definitions for ucLCD_Misc
+#define ATOM_PANEL_MISC_V13_DUAL                   0x00000001
+#define ATOM_PANEL_MISC_V13_FPDI                   0x00000002
+#define ATOM_PANEL_MISC_V13_GREY_LEVEL             0x0000000C
+#define ATOM_PANEL_MISC_V13_GREY_LEVEL_SHIFT       2
+#define ATOM_PANEL_MISC_V13_COLOR_BIT_DEPTH_MASK   0x70
+#define ATOM_PANEL_MISC_V13_6BIT_PER_COLOR         0x10
+#define ATOM_PANEL_MISC_V13_8BIT_PER_COLOR         0x20
+
+//Color Bit Depth definition in EDID V1.4 @BYTE 14h
+//Bit 6  5  4
+                              //      0  0  0  -  Color bit depth is undefined
+                              //      0  0  1  -  6 Bits per Primary Color
+                              //      0  1  0  -  8 Bits per Primary Color
+                              //      0  1  1  - 10 Bits per Primary Color
+                              //      1  0  0  - 12 Bits per Primary Color
+                              //      1  0  1  - 14 Bits per Primary Color
+                              //      1  1  0  - 16 Bits per Primary Color
+                              //      1  1  1  - Reserved
+ 
+//Definitions for ucLCDPanel_SpecialHandlingCap:
+
+//Once DAL sees this CAP is set, it will read EDID from LCD on its own instead of using sLCDTiming in ATOM_LVDS_INFO_V12. 
+//Other entries in ATOM_LVDS_INFO_V12 are still valid/useful to DAL 
+#define	LCDPANEL_CAP_V13_READ_EDID              0x1        // = LCDPANEL_CAP_READ_EDID no change comparing to previous version
+
+//If a design supports DRR (dynamic refresh rate) on internal panels (LVDS or EDP), this cap is set in ucLCDPanel_SpecialHandlingCap together
+//with multiple supported refresh rates@usSupportedRefreshRate. This cap should not be set when only slow refresh rate is supported (static
+//refresh rate switch by SW. This is only valid from ATOM_LVDS_INFO_V12
+#define	LCDPANEL_CAP_V13_DRR_SUPPORTED          0x2        // = LCDPANEL_CAP_DRR_SUPPORTED no change comparing to previous version
+
+//Use this cap bit for a quick reference whether an embadded panel (LCD1 ) is LVDS or eDP.
+#define	LCDPANEL_CAP_V13_eDP                    0x4        // = LCDPANEL_CAP_eDP no change comparing to previous version
 
 typedef struct  _ATOM_PATCH_RECORD_MODE
 {
@@ -2944,9 +3417,9 @@ typedef struct _ATOM_DPCD_INFO
 #define MAX_DTD_MODE_IN_VRAM            6
 #define ATOM_DTD_MODE_SUPPORT_TBL_SIZE  (MAX_DTD_MODE_IN_VRAM*28)    //28= (SIZEOF ATOM_DTD_FORMAT) 
 #define ATOM_STD_MODE_SUPPORT_TBL_SIZE  32*8                         //32 is a predefined number,8= (SIZEOF ATOM_STD_FORMAT)
-#define DFP_ENCODER_TYPE_OFFSET					0x80
-#define DP_ENCODER_LANE_NUM_OFFSET			0x84
-#define DP_ENCODER_LINK_RATE_OFFSET			0x88
+//20 bytes for Encoder Type and DPCD in STD EDID area
+#define DFP_ENCODER_TYPE_OFFSET         (ATOM_EDID_RAW_DATASIZE + ATOM_DTD_MODE_SUPPORT_TBL_SIZE + ATOM_STD_MODE_SUPPORT_TBL_SIZE - 20)    
+#define ATOM_DP_DPCD_OFFSET             (DFP_ENCODER_TYPE_OFFSET + 4 )        
 
 #define ATOM_HWICON1_SURFACE_ADDR       0
 #define ATOM_HWICON2_SURFACE_ADDR       (ATOM_HWICON1_SURFACE_ADDR + ATOM_HWICON_SURFACE_SIZE)
@@ -2997,14 +3470,16 @@ typedef struct _ATOM_DPCD_INFO
 #define ATOM_DFP5_DTD_MODE_TBL_ADDR     (ATOM_DFP5_EDID_ADDR + ATOM_EDID_RAW_DATASIZE)
 #define ATOM_DFP5_STD_MODE_TBL_ADDR     (ATOM_DFP5_DTD_MODE_TBL_ADDR + ATOM_DTD_MODE_SUPPORT_TBL_SIZE)
 
-#define ATOM_DP_TRAINING_TBL_ADDR				(ATOM_DFP5_STD_MODE_TBL_ADDR+ATOM_STD_MODE_SUPPORT_TBL_SIZE)       
+#define ATOM_DP_TRAINING_TBL_ADDR       (ATOM_DFP5_STD_MODE_TBL_ADDR + ATOM_STD_MODE_SUPPORT_TBL_SIZE)
 
-#define ATOM_STACK_STORAGE_START        (ATOM_DP_TRAINING_TBL_ADDR+256)       
-#define ATOM_STACK_STORAGE_END          ATOM_STACK_STORAGE_START+512        
+#define ATOM_STACK_STORAGE_START        (ATOM_DP_TRAINING_TBL_ADDR + 1024)       
+#define ATOM_STACK_STORAGE_END          ATOM_STACK_STORAGE_START + 512        
 
 //The size below is in Kb!
 #define ATOM_VRAM_RESERVE_SIZE         ((((ATOM_STACK_STORAGE_END - ATOM_HWICON1_SURFACE_ADDR)>>10)+4)&0xFFFC)
    
+#define ATOM_VRAM_RESERVE_V2_SIZE      32
+
 #define	ATOM_VRAM_OPERATION_FLAGS_MASK         0xC0000000L
 #define ATOM_VRAM_OPERATION_FLAGS_SHIFT        30
 #define	ATOM_VRAM_BLOCK_NEEDS_NO_RESERVATION   0x1
@@ -3206,6 +3681,15 @@ typedef struct  _ATOM_DISPLAY_OBJECT_PAT
   USHORT    usGraphicObjIds[1];                             //1st Encoder Obj source from GPU to last Graphic Obj destinate to connector.
 }ATOM_DISPLAY_OBJECT_PATH;
 
+typedef struct  _ATOM_DISPLAY_EXTERNAL_OBJECT_PATH
+{
+  USHORT    usDeviceTag;                                   //supported device 
+  USHORT    usSize;                                        //the size of ATOM_DISPLAY_OBJECT_PATH
+  USHORT    usConnObjectId;                                //Connector Object ID 
+  USHORT    usGPUObjectId;                                 //GPU ID 
+  USHORT    usGraphicObjIds[2];                            //usGraphicObjIds[0]= GPU internal encoder, usGraphicObjIds[1]= external encoder 
+}ATOM_DISPLAY_EXTERNAL_OBJECT_PATH;
+
 typedef struct _ATOM_DISPLAY_OBJECT_PATH_TABLE
 {
   UCHAR                           ucNumOfDispPath;
@@ -3261,6 +3745,47 @@ typedef struct _ATOM_SRC_DST_TABLE_FOR_O
 #define EXT_AUXDDC_LUTINDEX_7                   7
 #define MAX_NUMBER_OF_EXT_AUXDDC_LUT_ENTRIES   (EXT_AUXDDC_LUTINDEX_7+1)
 
+//ucChannelMapping are defined as following
+//for DP connector, eDP, DP to VGA/LVDS 
+//Bit[1:0]: Define which pin connect to DP connector DP_Lane0, =0: source from GPU pin TX0, =1: from GPU pin TX1, =2: from GPU pin TX2, =3 from GPU pin TX3
+//Bit[3:2]: Define which pin connect to DP connector DP_Lane1, =0: source from GPU pin TX0, =1: from GPU pin TX1, =2: from GPU pin TX2, =3 from GPU pin TX3
+//Bit[5:4]: Define which pin connect to DP connector DP_Lane2, =0: source from GPU pin TX0, =1: from GPU pin TX1, =2: from GPU pin TX2, =3 from GPU pin TX3
+//Bit[7:6]: Define which pin connect to DP connector DP_Lane3, =0: source from GPU pin TX0, =1: from GPU pin TX1, =2: from GPU pin TX2, =3 from GPU pin TX3
+typedef struct _ATOM_DP_CONN_CHANNEL_MAPPING
+{
+#if ATOM_BIG_ENDIAN
+  UCHAR ucDP_Lane3_Source:2;
+  UCHAR ucDP_Lane2_Source:2;
+  UCHAR ucDP_Lane1_Source:2;
+  UCHAR ucDP_Lane0_Source:2;
+#else
+  UCHAR ucDP_Lane0_Source:2;
+  UCHAR ucDP_Lane1_Source:2;
+  UCHAR ucDP_Lane2_Source:2;
+  UCHAR ucDP_Lane3_Source:2;
+#endif
+}ATOM_DP_CONN_CHANNEL_MAPPING;
+
+//for DVI/HDMI, in dual link case, both links have to have same mapping. 
+//Bit[1:0]: Define which pin connect to DVI connector data Lane2, =0: source from GPU pin TX0, =1: from GPU pin TX1, =2: from GPU pin TX2, =3 from GPU pin TX3
+//Bit[3:2]: Define which pin connect to DVI connector data Lane1, =0: source from GPU pin TX0, =1: from GPU pin TX1, =2: from GPU pin TX2, =3 from GPU pin TX3
+//Bit[5:4]: Define which pin connect to DVI connector data Lane0, =0: source from GPU pin TX0, =1: from GPU pin TX1, =2: from GPU pin TX2, =3 from GPU pin TX3
+//Bit[7:6]: Define which pin connect to DVI connector clock lane, =0: source from GPU pin TX0, =1: from GPU pin TX1, =2: from GPU pin TX2, =3 from GPU pin TX3
+typedef struct _ATOM_DVI_CONN_CHANNEL_MAPPING
+{
+#if ATOM_BIG_ENDIAN
+  UCHAR ucDVI_CLK_Source:2;
+  UCHAR ucDVI_DATA0_Source:2;
+  UCHAR ucDVI_DATA1_Source:2;
+  UCHAR ucDVI_DATA2_Source:2;
+#else
+  UCHAR ucDVI_DATA2_Source:2;
+  UCHAR ucDVI_DATA1_Source:2;
+  UCHAR ucDVI_DATA0_Source:2;
+  UCHAR ucDVI_CLK_Source:2;
+#endif
+}ATOM_DVI_CONN_CHANNEL_MAPPING;
+
 typedef struct _EXT_DISPLAY_PATH
 {
   USHORT  usDeviceTag;                    //A bit vector to show what devices are supported 
@@ -3269,7 +3794,13 @@ typedef struct _EXT_DISPLAY_PATH
   UCHAR   ucExtAUXDDCLutIndex;            //An index into external AUX/DDC channel LUT
   UCHAR   ucExtHPDPINLutIndex;            //An index into external HPD pin LUT
   USHORT  usExtEncoderObjId;              //external encoder object id
-  USHORT  usReserved[3]; 
+  union{
+    UCHAR   ucChannelMapping;                  // if ucChannelMapping=0, using default one to one mapping
+    ATOM_DP_CONN_CHANNEL_MAPPING asDPMapping;
+    ATOM_DVI_CONN_CHANNEL_MAPPING asDVIMapping;
+  };
+  UCHAR   ucReserved;
+  USHORT  usReserved[2]; 
 }EXT_DISPLAY_PATH;
    
 #define NUMBER_OF_UCHAR_FOR_GUID          16
@@ -3281,7 +3812,8 @@ typedef  struct _ATOM_EXTERNAL_DISPLAY_C
   UCHAR                    ucGuid [NUMBER_OF_UCHAR_FOR_GUID];     // a GUID is a 16 byte long string
   EXT_DISPLAY_PATH         sPath[MAX_NUMBER_OF_EXT_DISPLAY_PATH]; // total of fixed 7 entries.
   UCHAR                    ucChecksum;                            // a  simple Checksum of the sum of whole structure equal to 0x0. 
-  UCHAR                    Reserved [7];                          // for potential expansion
+  UCHAR                    uc3DStereoPinId;                       // use for eDP panel
+  UCHAR                    Reserved [6];                          // for potential expansion
 }ATOM_EXTERNAL_DISPLAY_CONNECTION_INFO;
 
 //Related definitions, all records are differnt but they have a commond header
@@ -3311,10 +3843,11 @@ typedef struct _ATOM_COMMON_RECORD_HEADE
 #define ATOM_CONNECTOR_AUXDDC_LUT_RECORD_TYPE          17 //This is for the case when connectors are not known to object table
 #define ATOM_OBJECT_LINK_RECORD_TYPE                   18 //Once this record is present under one object, it indicats the oobject is linked to another obj described by the record
 #define ATOM_CONNECTOR_REMOTE_CAP_RECORD_TYPE          19
+#define ATOM_ENCODER_CAP_RECORD_TYPE                   20
 
 
 //Must be updated when new record type is added,equal to that record definition!
-#define ATOM_MAX_OBJECT_RECORD_NUMBER             ATOM_CONNECTOR_REMOTE_CAP_RECORD_TYPE
+#define ATOM_MAX_OBJECT_RECORD_NUMBER             ATOM_ENCODER_CAP_RECORD_TYPE
 
 typedef struct  _ATOM_I2C_RECORD
 {
@@ -3441,6 +3974,26 @@ typedef struct  _ATOM_ENCODER_DVO_CF_REC
   UCHAR                       ucPadding[2];
 }ATOM_ENCODER_DVO_CF_RECORD;
 
+// Bit maps for ATOM_ENCODER_CAP_RECORD.ucEncoderCap
+#define ATOM_ENCODER_CAP_RECORD_HBR2     0x01         // DP1.2 HBR2 is supported by this path
+
+typedef struct  _ATOM_ENCODER_CAP_RECORD
+{
+  ATOM_COMMON_RECORD_HEADER   sheader;
+  union {
+    USHORT                    usEncoderCap;         
+    struct {
+#if ATOM_BIG_ENDIAN
+      USHORT                  usReserved:15;        // Bit1-15 may be defined for other capability in future
+      USHORT                  usHBR2Cap:1;          // Bit0 is for DP1.2 HBR2 capability. 
+#else
+      USHORT                  usHBR2Cap:1;          // Bit0 is for DP1.2 HBR2 capability. 
+      USHORT                  usReserved:15;        // Bit1-15 may be defined for other capability in future
+#endif
+    };
+  }; 
+}ATOM_ENCODER_CAP_RECORD;                             
+
 // value for ATOM_CONNECTOR_CF_RECORD.ucConnectedDvoBundle
 #define ATOM_CONNECTOR_CF_RECORD_CONNECTED_UPPER12BITBUNDLEA   1
 #define ATOM_CONNECTOR_CF_RECORD_CONNECTED_LOWER12BITBUNDLEB   2
@@ -3580,6 +4133,11 @@ typedef struct _ATOM_VOLTAGE_CONTROL
 #define	VOLTAGE_CONTROL_ID_DAC								0x02									//I2C control, used for R5xx/R6xx MVDDC,MVDDQ or VDDCI
 #define	VOLTAGE_CONTROL_ID_VT116xM						0x03									//I2C control, used for R6xx Core Voltage
 #define VOLTAGE_CONTROL_ID_DS4402							0x04									
+#define VOLTAGE_CONTROL_ID_UP6266 						0x05									
+#define VOLTAGE_CONTROL_ID_SCORPIO						0x06
+#define	VOLTAGE_CONTROL_ID_VT1556M						0x07									
+#define	VOLTAGE_CONTROL_ID_CHL822x						0x08									
+#define	VOLTAGE_CONTROL_ID_VT1586M						0x09
 
 typedef struct  _ATOM_VOLTAGE_OBJECT
 {
@@ -3670,66 +4228,157 @@ typedef struct _ATOM_POWER_SOURCE_INFO
 #define POWER_SENSOR_GPIO								0x01
 #define POWER_SENSOR_I2C								0x02
 
+typedef struct _ATOM_CLK_VOLT_CAPABILITY
+{
+  ULONG      ulVoltageIndex;                      // The Voltage Index indicated by FUSE, same voltage index shared with SCLK DPM fuse table        
+  ULONG      ulMaximumSupportedCLK;               // Maximum clock supported with specified voltage index, unit in 10kHz
+}ATOM_CLK_VOLT_CAPABILITY;
+
+typedef struct _ATOM_AVAILABLE_SCLK_LIST
+{
+  ULONG      ulSupportedSCLK;               // Maximum clock supported with specified voltage index,  unit in 10kHz
+  USHORT     usVoltageIndex;                // The Voltage Index indicated by FUSE for specified SCLK  
+  USHORT     usVoltageID;                   // The Voltage ID indicated by FUSE for specified SCLK 
+}ATOM_AVAILABLE_SCLK_LIST;
+
+// ATOM_INTEGRATED_SYSTEM_INFO_V6 ulSystemConfig cap definition
+#define ATOM_IGP_INFO_V6_SYSTEM_CONFIG__PCIE_POWER_GATING_ENABLE             1       // refer to ulSystemConfig bit[0]
+
+// this IntegrateSystemInfoTable is used for Liano/Ontario APU
 typedef struct _ATOM_INTEGRATED_SYSTEM_INFO_V6
 {
   ATOM_COMMON_TABLE_HEADER   sHeader;
   ULONG  ulBootUpEngineClock;
   ULONG  ulDentistVCOFreq;          
   ULONG  ulBootUpUMAClock;          
-  ULONG  ulReserved1[8];            
+  ATOM_CLK_VOLT_CAPABILITY   sDISPCLK_Voltage[4];            
   ULONG  ulBootUpReqDisplayVector;
   ULONG  ulOtherDisplayMisc;
   ULONG  ulGPUCapInfo;
-  ULONG  ulReserved2[3];            
+  ULONG  ulSB_MMIO_Base_Addr;
+  USHORT usRequestedPWMFreqInHz;
+  UCHAR  ucHtcTmpLmt;   
+  UCHAR  ucHtcHystLmt;
+  ULONG  ulMinEngineClock;           
   ULONG  ulSystemConfig;            
   ULONG  ulCPUCapInfo;              
-  USHORT usMaxNBVoltage;  
-  USHORT usMinNBVoltage;  
-  USHORT usBootUpNBVoltage;         
-  USHORT usExtDispConnInfoOffset;  
-  UCHAR  ucHtcTmpLmt;   
-  UCHAR  ucTjOffset;    
+  USHORT usNBP0Voltage;               
+  USHORT usNBP1Voltage;
+  USHORT usBootUpNBVoltage;                       
+  USHORT usExtDispConnInfoOffset;
+  USHORT usPanelRefreshRateRange;     
   UCHAR  ucMemoryType;  
   UCHAR  ucUMAChannelNumber;
   ULONG  ulCSR_M3_ARB_CNTL_DEFAULT[10];  
   ULONG  ulCSR_M3_ARB_CNTL_UVD[10]; 
   ULONG  ulCSR_M3_ARB_CNTL_FS3D[10];
-  ULONG  ulReserved3[42]; 
+  ATOM_AVAILABLE_SCLK_LIST   sAvail_SCLK[5];
+  ULONG  ulGMCRestoreResetTime;
+  ULONG  ulMinimumNClk;
+  ULONG  ulIdleNClk;
+  ULONG  ulDDR_DLL_PowerUpTime;
+  ULONG  ulDDR_PLL_PowerUpTime;
+  USHORT usPCIEClkSSPercentage;
+  USHORT usPCIEClkSSType;
+  USHORT usLvdsSSPercentage;
+  USHORT usLvdsSSpreadRateIn10Hz;
+  USHORT usHDMISSPercentage;
+  USHORT usHDMISSpreadRateIn10Hz;
+  USHORT usDVISSPercentage;
+  USHORT usDVISSpreadRateIn10Hz;
+  ULONG  ulReserved3[21]; 
   ATOM_EXTERNAL_DISPLAY_CONNECTION_INFO sExtDispConnInfo;   
 }ATOM_INTEGRATED_SYSTEM_INFO_V6;   
 
+// ulGPUCapInfo
+#define INTEGRATED_SYSTEM_INFO_V6_GPUCAPINFO__TMDSHDMI_COHERENT_SINGLEPLL_MODE       0x01
+#define INTEGRATED_SYSTEM_INFO_V6_GPUCAPINFO__DISABLE_AUX_HW_MODE_DETECTION          0x08
+
+// ulOtherDisplayMisc
+#define INTEGRATED_SYSTEM_INFO__GET_EDID_CALLBACK_FUNC_SUPPORT                       0x01
+
+
 /**********************************************************************************************************************
-// ATOM_INTEGRATED_SYSTEM_INFO_V6 Description
-//ulBootUpEngineClock:              VBIOS bootup Engine clock frequency, in 10kHz unit. 
-//ulDentistVCOFreq:                 Dentist VCO clock in 10kHz unit. 
-//ulBootUpUMAClock:                 System memory boot up clock frequency in 10Khz unit. 
-//ulReserved1[8]                    Reserved by now, must be 0x0. 
-//ulBootUpReqDisplayVector	        VBIOS boot up display IDs
-//                                  ATOM_DEVICE_CRT1_SUPPORT                  0x0001
-//                                  ATOM_DEVICE_CRT2_SUPPORT                  0x0010
-//                                  ATOM_DEVICE_DFP1_SUPPORT                  0x0008 
-//                                  ATOM_DEVICE_DFP6_SUPPORT                  0x0040 
-//                                  ATOM_DEVICE_DFP2_SUPPORT                  0x0080       
-//                                  ATOM_DEVICE_DFP3_SUPPORT                  0x0200       
-//                                  ATOM_DEVICE_DFP4_SUPPORT                  0x0400        
-//                                  ATOM_DEVICE_DFP5_SUPPORT                  0x0800
-//                                  ATOM_DEVICE_LCD1_SUPPORT                  0x0002
-//ulOtherDisplayMisc      	        Other display related flags, not defined yet. 
-//ulGPUCapInfo                      TBD
-//ulReserved2[3]                    must be 0x0 for the reserved.
-//ulSystemConfig                    TBD
-//ulCPUCapInfo                      TBD
-//usMaxNBVoltage                    High NB voltage in unit of mv, calculated using current VDDNB (D24F2xDC) and VDDNB offset fuse. 
-//usMinNBVoltage                    Low NB voltage in unit of mv, calculated using current VDDNB (D24F2xDC) and VDDNB offset fuse.
-//usBootUpNBVoltage                 Boot up NB voltage in unit of mv.
-//ucHtcTmpLmt                       Bit [22:16] of D24F3x64 Thermal Control (HTC) Register.
-//ucTjOffset                        Bit [28:22] of D24F3xE4 Thermtrip Status Register,may not be needed.
-//ucMemoryType                      [3:0]=1:DDR1;=2:DDR2;=3:DDR3.[7:4] is reserved.
-//ucUMAChannelNumber      	        System memory channel numbers. 
-//usExtDispConnectionInfoOffset     ATOM_EXTERNAL_DISPLAY_CONNECTION_INFO offset relative to beginning of this table. 
-//ulCSR_M3_ARB_CNTL_DEFAULT[10]     Arrays with values for CSR M3 arbiter for default
-//ulCSR_M3_ARB_CNTL_UVD[10]         Arrays with values for CSR M3 arbiter for UVD playback.
-//ulCSR_M3_ARB_CNTL_FS3D[10]        Arrays with values for CSR M3 arbiter for Full Screen 3D applications.
+  ATOM_INTEGRATED_SYSTEM_INFO_V6 Description
+ulBootUpEngineClock:              VBIOS bootup Engine clock frequency, in 10kHz unit. if it is equal 0, then VBIOS use pre-defined bootup engine clock
+ulDentistVCOFreq:                 Dentist VCO clock in 10kHz unit. 
+ulBootUpUMAClock:                 System memory boot up clock frequency in 10Khz unit. 
+sDISPCLK_Voltage:                 Report Display clock voltage requirement.
+ 
+ulBootUpReqDisplayVector:         VBIOS boot up display IDs, following are supported devices in Liano/Ontaio projects:
+                                  ATOM_DEVICE_CRT1_SUPPORT                  0x0001
+                                  ATOM_DEVICE_CRT2_SUPPORT                  0x0010
+                                  ATOM_DEVICE_DFP1_SUPPORT                  0x0008 
+                                  ATOM_DEVICE_DFP6_SUPPORT                  0x0040 
+                                  ATOM_DEVICE_DFP2_SUPPORT                  0x0080       
+                                  ATOM_DEVICE_DFP3_SUPPORT                  0x0200       
+                                  ATOM_DEVICE_DFP4_SUPPORT                  0x0400        
+                                  ATOM_DEVICE_DFP5_SUPPORT                  0x0800
+                                  ATOM_DEVICE_LCD1_SUPPORT                  0x0002
+ulOtherDisplayMisc:      	        Other display related flags, not defined yet. 
+ulGPUCapInfo:                     bit[0]=0: TMDS/HDMI Coherent Mode use cascade PLL mode.
+                                        =1: TMDS/HDMI Coherent Mode use signel PLL mode.
+                                  bit[3]=0: Enable HW AUX mode detection logic
+                                        =1: Disable HW AUX mode dettion logic
+ulSB_MMIO_Base_Addr:              Physical Base address to SB MMIO space. Driver needs to initialize it for SMU usage.
+
+usRequestedPWMFreqInHz:           When it's set to 0x0 by SBIOS: the LCD BackLight is not controlled by GPU(SW). 
+                                  Any attempt to change BL using VBIOS function or enable VariBri from PP table is not effective since ATOM_BIOS_INFO_BL_CONTROLLED_BY_GPU==0;
+                                  
+                                  When it's set to a non-zero frequency, the BackLight is controlled by GPU (SW) in one of two ways below:
+                                  1. SW uses the GPU BL PWM output to control the BL, in chis case, this non-zero frequency determines what freq GPU should use;
+                                  VBIOS will set up proper PWM frequency and ATOM_BIOS_INFO_BL_CONTROLLED_BY_GPU==1,as the result,
+                                  Changing BL using VBIOS function is functional in both driver and non-driver present environment; 
+                                  and enabling VariBri under the driver environment from PP table is optional.
+
+                                  2. SW uses other means to control BL (like DPCD),this non-zero frequency serves as a flag only indicating
+                                  that BL control from GPU is expected.
+                                  VBIOS will NOT set up PWM frequency but make ATOM_BIOS_INFO_BL_CONTROLLED_BY_GPU==1
+                                  Changing BL using VBIOS function could be functional in both driver and non-driver present environment,but
+                                  it's per platform 
+                                  and enabling VariBri under the driver environment from PP table is optional.
+
+ucHtcTmpLmt:                      Refer to D18F3x64 bit[22:16], HtcTmpLmt. 
+                                  Threshold on value to enter HTC_active state.
+ucHtcHystLmt:                     Refer to D18F3x64 bit[27:24], HtcHystLmt. 
+                                  To calculate threshold off value to exit HTC_active state, which is Threshold on vlaue minus ucHtcHystLmt.
+ulMinEngineClock:                 Minimum SCLK allowed in 10kHz unit. This is calculated based on WRCK Fuse settings.
+ulSystemConfig:                   Bit[0]=0: PCIE Power Gating Disabled 
+                                        =1: PCIE Power Gating Enabled
+                                  Bit[1]=0: DDR-DLL shut-down feature disabled.
+                                         1: DDR-DLL shut-down feature enabled.
+                                  Bit[2]=0: DDR-PLL Power down feature disabled.
+                                         1: DDR-PLL Power down feature enabled.                                 
+ulCPUCapInfo:                     TBD
+usNBP0Voltage:                    VID for voltage on NB P0 State
+usNBP1Voltage:                    VID for voltage on NB P1 State  
+usBootUpNBVoltage:                Voltage Index of GNB voltage configured by SBIOS, which is suffcient to support VBIOS DISPCLK requirement.
+usExtDispConnInfoOffset:          Offset to sExtDispConnInfo inside the structure
+usPanelRefreshRateRange:          Bit vector for LCD supported refresh rate range. If DRR is requestd by the platform, at least two bits need to be set
+                                  to indicate a range.
+                                  SUPPORTED_LCD_REFRESHRATE_30Hz          0x0004
+                                  SUPPORTED_LCD_REFRESHRATE_40Hz          0x0008
+                                  SUPPORTED_LCD_REFRESHRATE_50Hz          0x0010
+                                  SUPPORTED_LCD_REFRESHRATE_60Hz          0x0020
+ucMemoryType:                     [3:0]=1:DDR1;=2:DDR2;=3:DDR3.[7:4] is reserved.
+ucUMAChannelNumber:      	        System memory channel numbers. 
+ulCSR_M3_ARB_CNTL_DEFAULT[10]:    Arrays with values for CSR M3 arbiter for default
+ulCSR_M3_ARB_CNTL_UVD[10]:        Arrays with values for CSR M3 arbiter for UVD playback.
+ulCSR_M3_ARB_CNTL_FS3D[10]:       Arrays with values for CSR M3 arbiter for Full Screen 3D applications.
+sAvail_SCLK[5]:                   Arrays to provide availabe list of SLCK and corresponding voltage, order from low to high  
+ulGMCRestoreResetTime:            GMC power restore and GMC reset time to calculate data reconnection latency. Unit in ns. 
+ulMinimumNClk:                    Minimum NCLK speed among all NB-Pstates to calcualte data reconnection latency. Unit in 10kHz. 
+ulIdleNClk:                       NCLK speed while memory runs in self-refresh state. Unit in 10kHz.
+ulDDR_DLL_PowerUpTime:            DDR PHY DLL power up time. Unit in ns.
+ulDDR_PLL_PowerUpTime:            DDR PHY PLL power up time. Unit in ns.
+usPCIEClkSSPercentage:            PCIE Clock Spred Spectrum Percentage in unit 0.01%; 100 mean 1%.
+usPCIEClkSSType:                  PCIE Clock Spred Spectrum Type. 0 for Down spread(default); 1 for Center spread.
+usLvdsSSPercentage:               LVDS panel ( not include eDP ) Spread Spectrum Percentage in unit of 0.01%, =0, use VBIOS default setting. 
+usLvdsSSpreadRateIn10Hz:          LVDS panel ( not include eDP ) Spread Spectrum frequency in unit of 10Hz, =0, use VBIOS default setting. 
+usHDMISSPercentage:               HDMI Spread Spectrum Percentage in unit 0.01%; 100 mean 1%,  =0, use VBIOS default setting. 
+usHDMISSpreadRateIn10Hz:          HDMI Spread Spectrum frequency in unit of 10Hz,  =0, use VBIOS default setting. 
+usDVISSPercentage:                DVI Spread Spectrum Percentage in unit 0.01%; 100 mean 1%,  =0, use VBIOS default setting. 
+usDVISSpreadRateIn10Hz:           DVI Spread Spectrum frequency in unit of 10Hz,  =0, use VBIOS default setting. 
 **********************************************************************************************************************/
 
 /**************************************************************************/
@@ -3790,6 +4439,7 @@ typedef struct _ATOM_ASIC_SS_ASSIGNMENT
 #define ASIC_INTERNAL_SS_ON_LVDS    6
 #define ASIC_INTERNAL_SS_ON_DP      7
 #define ASIC_INTERNAL_SS_ON_DCPLL   8
+#define ASIC_EXTERNAL_SS_ON_DP_CLOCK 9
 
 typedef struct _ATOM_ASIC_SS_ASSIGNMENT_V2
 {
@@ -3903,6 +4553,7 @@ typedef struct _ATOM_ASIC_INTERNAL_SS_IN
 #define ATOM_S0_SYSTEM_POWER_STATE_VALUE_AC     1
 #define ATOM_S0_SYSTEM_POWER_STATE_VALUE_DC     2
 #define ATOM_S0_SYSTEM_POWER_STATE_VALUE_LITEAC 3
+#define ATOM_S0_SYSTEM_POWER_STATE_VALUE_LIT2AC 4
 
 //Byte aligned defintion for BIOS usage
 #define ATOM_S0_CRT1_MONOb0             0x01
@@ -4529,7 +5180,8 @@ typedef struct _ATOM_INIT_REG_BLOCK{
 #define INDEX_ACCESS_RANGE_BEGIN	    (VALUE_DWORD + 1)
 #define INDEX_ACCESS_RANGE_END		    (INDEX_ACCESS_RANGE_BEGIN + 1)
 #define VALUE_INDEX_ACCESS_SINGLE	    (INDEX_ACCESS_RANGE_END + 1)
-
+//#define ACCESS_MCIODEBUGIND            0x40       //defined in BIOS code
+#define ACCESS_PLACEHOLDER             0x80
 
 typedef struct _ATOM_MC_INIT_PARAM_TABLE
 { 
@@ -4554,6 +5206,10 @@ typedef struct _ATOM_MC_INIT_PARAM_TABLE
 #define _32Mx32             0x33
 #define _64Mx8              0x41
 #define _64Mx16             0x42
+#define _64Mx32             0x43
+#define _128Mx8             0x51
+#define _128Mx16            0x52
+#define _256Mx8             0x61
 
 #define SAMSUNG             0x1
 #define INFINEON            0x2
@@ -4569,10 +5225,11 @@ typedef struct _ATOM_MC_INIT_PARAM_TABLE
 #define QIMONDA             INFINEON
 #define PROMOS              MOSEL
 #define KRETON              INFINEON
+#define ELIXIR              NANYA
 
 /////////////Support for GDDR5 MC uCode to reside in upper 64K of ROM/////////////
 
-#define UCODE_ROM_START_ADDRESS		0x1c000
+#define UCODE_ROM_START_ADDRESS		0x1b800
 #define	UCODE_SIGNATURE			0x4375434d // 'MCuC' - MC uCode
 
 //uCode block header for reference
@@ -4903,7 +5560,34 @@ typedef struct _ATOM_VRAM_MODULE_V6
   ATOM_MEMORY_TIMING_FORMAT_V2  asMemTiming[5];//Memory Timing block sort from lower clock to higher clock
 }ATOM_VRAM_MODULE_V6;
 
-
+typedef struct _ATOM_VRAM_MODULE_V7
+{
+// Design Specific Values
+  ULONG	  ulChannelMapCfg;	                // mmMC_SHARED_CHREMAP
+  USHORT  usModuleSize;                     // Size of ATOM_VRAM_MODULE_V7
+  USHORT  usPrivateReserved;                // MC_ARB_RAMCFG (includes NOOFBANK,NOOFRANKS,NOOFROWS,NOOFCOLS)
+  USHORT  usReserved;
+  UCHAR   ucExtMemoryID;                    // Current memory module ID
+  UCHAR   ucMemoryType;                     // MEM_TYPE_DDR2/DDR3/GDDR3/GDDR5
+  UCHAR   ucChannelNum;                     // Number of mem. channels supported in this module
+  UCHAR   ucChannelWidth;                   // CHANNEL_16BIT/CHANNEL_32BIT/CHANNEL_64BIT
+  UCHAR   ucDensity;                        // _8Mx32, _16Mx32, _16Mx16, _32Mx16
+  UCHAR	  ucReserve;                        // Former container for Mx_FLAGS like DBI_AC_MODE_ENABLE_ASIC for GDDR4. Not used now.
+  UCHAR	  ucMisc;                           // RANK_OF_THISMEMORY etc.
+  UCHAR	  ucVREFI;                          // Not used.
+  UCHAR   ucNPL_RT;                         // Round trip delay (MC_SEQ_CAS_TIMING [28:24]:TCL=CL+NPL_RT-2). Always 2.
+  UCHAR	  ucPreamble;                       // [7:4] Write Preamble, [3:0] Read Preamble
+  UCHAR   ucMemorySize;                     // Total memory size in unit of 16MB for CONFIG_MEMSIZE - bit[23:0] zeros
+  UCHAR   ucReserved[3];
+// Memory Module specific values
+  USHORT  usEMRS2Value;                     // EMRS2/MR2 Value. 
+  USHORT  usEMRS3Value;                     // EMRS3/MR3 Value.
+  UCHAR   ucMemoryVenderID;                 // [7:4] Revision, [3:0] Vendor code
+  UCHAR	  ucRefreshRateFactor;              // [1:0]=RefreshFactor (00=8ms, 01=16ms, 10=32ms,11=64ms)
+  UCHAR	  ucFIFODepth;                      // FIFO depth can be detected during vendor detection, here is hardcoded per memory
+  UCHAR   ucCDR_Bandwidth;                  // [0:3]=Read CDR bandwidth, [4:7] - Write CDR Bandwidth
+  char    strMemPNString[20];               // part number end with '0'. 
+}ATOM_VRAM_MODULE_V7;
 
 typedef struct _ATOM_VRAM_INFO_V2
 {
@@ -4942,6 +5626,20 @@ typedef struct _ATOM_VRAM_INFO_V4
 																																						 //	ATOM_INIT_REG_BLOCK				 aMemAdjust;
 }ATOM_VRAM_INFO_V4;
 
+typedef struct _ATOM_VRAM_INFO_HEADER_V2_1
+{
+  ATOM_COMMON_TABLE_HEADER   sHeader;
+	USHORT										 usMemAdjustTblOffset;													 // offset of ATOM_INIT_REG_BLOCK structure for memory vendor specific MC adjust setting
+	USHORT										 usMemClkPatchTblOffset;												 //	offset of ATOM_INIT_REG_BLOCK structure for memory clock specific MC setting
+	USHORT										 usReserved[4];
+  UCHAR                      ucNumOfVRAMModule;                              // indicate number of VRAM module
+  UCHAR                      ucMemoryClkPatchTblVer;                         // version of memory AC timing register list
+  UCHAR                      ucVramModuleVer;                                // indicate ATOM_VRAM_MODUE version
+  UCHAR                      ucReserved; 
+  ATOM_VRAM_MODULE_V7		     aVramInfo[ATOM_MAX_NUMBER_OF_VRAM_MODULE];      // just for allocation, real number of blocks is in ucNumOfVRAMModule;
+}ATOM_VRAM_INFO_HEADER_V2_1;
+
+
 typedef struct _ATOM_VRAM_GPIO_DETECTION_INFO
 {
   ATOM_COMMON_TABLE_HEADER   sHeader;
@@ -5182,6 +5880,16 @@ typedef struct _ASIC_TRANSMITTER_INFO
 	UCHAR  ucReserved;
 }ASIC_TRANSMITTER_INFO;
 
+#define ASIC_TRANSMITTER_INFO_CONFIG__DVO_SDR_MODE          0x01
+#define ASIC_TRANSMITTER_INFO_CONFIG__COHERENT_MODE         0x02
+#define ASIC_TRANSMITTER_INFO_CONFIG__ENCODEROBJ_ID_MASK    0xc4
+#define ASIC_TRANSMITTER_INFO_CONFIG__ENCODER_A             0x00
+#define ASIC_TRANSMITTER_INFO_CONFIG__ENCODER_B             0x04
+#define ASIC_TRANSMITTER_INFO_CONFIG__ENCODER_C             0x40
+#define ASIC_TRANSMITTER_INFO_CONFIG__ENCODER_D             0x44
+#define ASIC_TRANSMITTER_INFO_CONFIG__ENCODER_E             0x80
+#define ASIC_TRANSMITTER_INFO_CONFIG__ENCODER_F             0x84
+
 typedef struct _ASIC_ENCODER_INFO
 {
 	UCHAR ucEncoderID;
@@ -5284,6 +5992,28 @@ typedef struct _DP_ENCODER_SERVICE_PARAM
 /* /obselete */
 #define DP_ENCODER_SERVICE_PS_ALLOCATION				WRITE_ONE_BYTE_HW_I2C_DATA_PARAMETERS
 
+
+typedef struct _DP_ENCODER_SERVICE_PARAMETERS_V2
+{
+	USHORT usExtEncoderObjId;   // External Encoder Object Id, output parameter only, use when ucAction = DP_SERVICE_V2_ACTION_DET_EXT_CONNECTION
+  UCHAR  ucAuxId;
+  UCHAR  ucAction;
+  UCHAR  ucSinkType;          // Iput and Output parameters. 
+  UCHAR  ucHPDId;             // Input parameter, used when ucAction = DP_SERVICE_V2_ACTION_DET_EXT_CONNECTION
+	UCHAR  ucReserved[2];
+}DP_ENCODER_SERVICE_PARAMETERS_V2;
+
+typedef struct _DP_ENCODER_SERVICE_PS_ALLOCATION_V2
+{
+  DP_ENCODER_SERVICE_PARAMETERS_V2 asDPServiceParam;
+  PROCESS_AUX_CHANNEL_TRANSACTION_PARAMETERS_V2 asAuxParam;
+}DP_ENCODER_SERVICE_PS_ALLOCATION_V2;
+
+// ucAction
+#define DP_SERVICE_V2_ACTION_GET_SINK_TYPE							0x01
+#define DP_SERVICE_V2_ACTION_DET_LCD_CONNECTION			    0x02
+
+
 // DP_TRAINING_TABLE
 #define DPCD_SET_LINKRATE_LANENUM_PATTERN1_TBL_ADDR				ATOM_DP_TRAINING_TBL_ADDR		
 #define DPCD_SET_SS_CNTL_TBL_ADDR													(ATOM_DP_TRAINING_TBL_ADDR + 8 )
@@ -5339,6 +6069,7 @@ typedef struct _SET_HWBLOCK_INSTANCE_PAR
 #define SELECT_DCIO_IMPCAL            4
 #define SELECT_DCIO_DIG               6
 #define SELECT_CRTC_PIXEL_RATE        7
+#define SELECT_VGA_BLK                8
 
 /****************************************************************************/	
 //Portion VI: Definitinos for vbios MC scratch registers that driver used
@@ -5744,7 +6475,17 @@ typedef struct _ATOM_PPLIB_THERMALCONTRO
 #define ATOM_PP_THERMALCONTROLLER_ADT7473   9
 #define ATOM_PP_THERMALCONTROLLER_EXTERNAL_GPIO     11
 #define ATOM_PP_THERMALCONTROLLER_EVERGREEN 12
+#define ATOM_PP_THERMALCONTROLLER_EMC2103   13  /* 0x0D */ // Only fan control will be implemented, do NOT show this in PPGen.
+#define ATOM_PP_THERMALCONTROLLER_SUMO      14  /* 0x0E */ // Sumo type, used internally
+#define ATOM_PP_THERMALCONTROLLER_NISLANDS  15
+
+// Thermal controller 'combo type' to use an external controller for Fan control and an internal controller for thermal.
+// We probably should reserve the bit 0x80 for this use.
+// To keep the number of these types low we should also use the same code for all ASICs (i.e. do not distinguish RV6xx and RV7xx Internal here).
+// The driver can pick the correct internal controller based on the ASIC.
+
 #define ATOM_PP_THERMALCONTROLLER_ADT7473_WITH_INTERNAL   0x89    // ADT7473 Fan Control + Internal Thermal Controller
+#define ATOM_PP_THERMALCONTROLLER_EMC2103_WITH_INTERNAL   0x8D    // EMC2103 Fan Control + Internal Thermal Controller
 
 typedef struct _ATOM_PPLIB_STATE
 {
@@ -5841,6 +6582,29 @@ typedef struct _ATOM_PPLIB_POWERPLAYTABL
     USHORT                     usExtendendedHeaderOffset;
 } ATOM_PPLIB_POWERPLAYTABLE3, *LPATOM_PPLIB_POWERPLAYTABLE3;
 
+typedef struct _ATOM_PPLIB_POWERPLAYTABLE4
+{
+    ATOM_PPLIB_POWERPLAYTABLE3 basicTable3;
+    ULONG                      ulGoldenPPID;                    // PPGen use only     
+    ULONG                      ulGoldenRevision;                // PPGen use only
+    USHORT                     usVddcDependencyOnSCLKOffset;
+    USHORT                     usVddciDependencyOnMCLKOffset;
+    USHORT                     usVddcDependencyOnMCLKOffset;
+    USHORT                     usMaxClockVoltageOnDCOffset;
+    USHORT                     usReserved[2];  
+} ATOM_PPLIB_POWERPLAYTABLE4, *LPATOM_PPLIB_POWERPLAYTABLE4;
+
+typedef struct _ATOM_PPLIB_POWERPLAYTABLE5
+{
+    ATOM_PPLIB_POWERPLAYTABLE4 basicTable4;
+    ULONG                      ulTDPLimit;
+    ULONG                      ulNearTDPLimit;
+    ULONG                      ulSQRampingThreshold;
+    USHORT                     usCACLeakageTableOffset;         // Points to ATOM_PPLIB_CAC_Leakage_Table
+    ULONG                      ulCACLeakage;                    // TBD, this parameter is still under discussion.  Change to ulReserved if not needed.
+    ULONG                      ulReserved;
+} ATOM_PPLIB_POWERPLAYTABLE5, *LPATOM_PPLIB_POWERPLAYTABLE5;
+
 //// ATOM_PPLIB_NONCLOCK_INFO::usClassification
 #define ATOM_PPLIB_CLASSIFICATION_UI_MASK          0x0007
 #define ATOM_PPLIB_CLASSIFICATION_UI_SHIFT         0
@@ -5864,6 +6628,10 @@ typedef struct _ATOM_PPLIB_POWERPLAYTABL
 #define ATOM_PPLIB_CLASSIFICATION_HDSTATE                0x4000
 #define ATOM_PPLIB_CLASSIFICATION_SDSTATE                0x8000
 
+//// ATOM_PPLIB_NONCLOCK_INFO::usClassification2
+#define ATOM_PPLIB_CLASSIFICATION2_LIMITEDPOWERSOURCE_2     0x0001
+#define ATOM_PPLIB_CLASSIFICATION2_ULV                      0x0002
+
 //// ATOM_PPLIB_NONCLOCK_INFO::ulCapsAndSettings
 #define ATOM_PPLIB_SINGLE_DISPLAY_ONLY           0x00000001
 #define ATOM_PPLIB_SUPPORTS_VIDEO_PLAYBACK         0x00000002
@@ -5896,9 +6664,21 @@ typedef struct _ATOM_PPLIB_POWERPLAYTABL
 #define ATOM_PPLIB_M3ARB_MASK                       0x00060000
 #define ATOM_PPLIB_M3ARB_SHIFT                      17
 
+#define ATOM_PPLIB_ENABLE_DRR                       0x00080000
+
+// remaining 16 bits are reserved
+typedef struct _ATOM_PPLIB_THERMAL_STATE
+{
+    UCHAR   ucMinTemperature;
+    UCHAR   ucMaxTemperature;
+    UCHAR   ucThermalAction;
+}ATOM_PPLIB_THERMAL_STATE, *LPATOM_PPLIB_THERMAL_STATE;
+
 // Contained in an array starting at the offset
 // in ATOM_PPLIB_POWERPLAYTABLE::usNonClockInfoArrayOffset.
 // referenced from ATOM_PPLIB_STATE_INFO::ucNonClockStateIndex
+#define ATOM_PPLIB_NONCLOCKINFO_VER1      12
+#define ATOM_PPLIB_NONCLOCKINFO_VER2      24
 typedef struct _ATOM_PPLIB_NONCLOCK_INFO
 {
       USHORT usClassification;
@@ -5906,15 +6686,15 @@ typedef struct _ATOM_PPLIB_NONCLOCK_INFO
       UCHAR  ucMaxTemperature;
       ULONG  ulCapsAndSettings;
       UCHAR  ucRequiredPower;
-      UCHAR  ucUnused1[3];
+      USHORT usClassification2;
+      ULONG  ulVCLK;
+      ULONG  ulDCLK;
+      UCHAR  ucUnused[5];
 } ATOM_PPLIB_NONCLOCK_INFO;
 
 // Contained in an array starting at the offset
 // in ATOM_PPLIB_POWERPLAYTABLE::usClockInfoArrayOffset.
 // referenced from ATOM_PPLIB_STATE::ucClockStateIndices
-#define ATOM_PPLIB_NONCLOCKINFO_VER1      12
-#define ATOM_PPLIB_NONCLOCKINFO_VER2      24
-
 typedef struct _ATOM_PPLIB_R600_CLOCK_INFO
 {
       USHORT usEngineClockLow;
@@ -5985,6 +6765,93 @@ typedef struct _ATOM_PPLIB_RS780_CLOCK_I
 #define ATOM_PPLIB_RS780_HTLINKFREQ_LOW        1 
 #define ATOM_PPLIB_RS780_HTLINKFREQ_HIGH       2 
 
+typedef struct _ATOM_PPLIB_SUMO_CLOCK_INFO{
+      USHORT usEngineClockLow;  //clockfrequency & 0xFFFF. The unit is in 10khz
+      UCHAR  ucEngineClockHigh; //clockfrequency >> 16. 
+      UCHAR  vddcIndex;         //2-bit vddc index;
+      UCHAR  leakage;          //please use 8-bit absolute value, not the 6-bit % value 
+      //please initalize to 0
+      UCHAR  rsv;
+      //please initalize to 0
+      USHORT rsv1;
+      //please initialize to 0s
+      ULONG rsv2[2];
+}ATOM_PPLIB_SUMO_CLOCK_INFO;
+
+
+
+typedef struct _ATOM_PPLIB_STATE_V2
+{
+      //number of valid dpm levels in this state; Driver uses it to calculate the whole 
+      //size of the state: sizeof(ATOM_PPLIB_STATE_V2) + (ucNumDPMLevels - 1) * sizeof(UCHAR)
+      UCHAR ucNumDPMLevels;
+      
+      //a index to the array of nonClockInfos
+      UCHAR nonClockInfoIndex;
+      /**
+      * Driver will read the first ucNumDPMLevels in this array
+      */
+      UCHAR clockInfoIndex[1];
+} ATOM_PPLIB_STATE_V2;
+
+typedef struct StateArray{
+    //how many states we have 
+    UCHAR ucNumEntries;
+    
+    ATOM_PPLIB_STATE_V2 states[1];
+}StateArray;
+
+
+typedef struct ClockInfoArray{
+    //how many clock levels we have
+    UCHAR ucNumEntries;
+    
+    //sizeof(ATOM_PPLIB_SUMO_CLOCK_INFO)
+    UCHAR ucEntrySize;
+    
+    //this is for Sumo
+    ATOM_PPLIB_SUMO_CLOCK_INFO clockInfo[1];
+}ClockInfoArray;
+
+typedef struct NonClockInfoArray{
+
+    //how many non-clock levels we have. normally should be same as number of states
+    UCHAR ucNumEntries;
+    //sizeof(ATOM_PPLIB_NONCLOCK_INFO)
+    UCHAR ucEntrySize;
+    
+    ATOM_PPLIB_NONCLOCK_INFO nonClockInfo[1];
+}NonClockInfoArray;
+
+typedef struct _ATOM_PPLIB_Clock_Voltage_Dependency_Record
+{
+    USHORT usClockLow;
+    UCHAR  ucClockHigh;
+    USHORT usVoltage;
+}ATOM_PPLIB_Clock_Voltage_Dependency_Record;
+
+typedef struct _ATOM_PPLIB_Clock_Voltage_Dependency_Table
+{
+    UCHAR ucNumEntries;                                                // Number of entries.
+    ATOM_PPLIB_Clock_Voltage_Dependency_Record entries[1];             // Dynamically allocate entries.
+}ATOM_PPLIB_Clock_Voltage_Dependency_Table;
+
+typedef struct _ATOM_PPLIB_Clock_Voltage_Limit_Record
+{
+    USHORT usSclkLow;
+    UCHAR  ucSclkHigh;
+    USHORT usMclkLow;
+    UCHAR  ucMclkHigh;
+    USHORT usVddc;
+    USHORT usVddci;
+}ATOM_PPLIB_Clock_Voltage_Limit_Record;
+
+typedef struct _ATOM_PPLIB_Clock_Voltage_Limit_Table
+{
+    UCHAR ucNumEntries;                                                // Number of entries.
+    ATOM_PPLIB_Clock_Voltage_Limit_Record entries[1];                  // Dynamically allocate entries.
+}ATOM_PPLIB_Clock_Voltage_Limit_Table;
+
 /**************************************************************************/
 
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/atom.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/atom.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/atom.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/atom.c	2011-03-14 21:20:32.000000000 -0400
@@ -734,16 +734,16 @@ static void atom_op_jump(atom_exec_conte
 static void atom_op_mask(atom_exec_context *ctx, int *ptr, int arg)
 {
 	uint8_t attr = U8((*ptr)++);
-	uint32_t dst, src1, src2, saved;
+	uint32_t dst, mask, src, saved;
 	int dptr = *ptr;
 	SDEBUG("   dst: ");
 	dst = atom_get_dst(ctx, arg, attr, ptr, &saved, 1);
-	SDEBUG("   src1: ");
-	src1 = atom_get_src_direct(ctx, ((attr >> 3) & 7), ptr);
-	SDEBUG("   src2: ");
-	src2 = atom_get_src(ctx, attr, ptr);
-	dst &= src1;
-	dst |= src2;
+	mask = atom_get_src_direct(ctx, ((attr >> 3) & 7), ptr);
+	SDEBUG("   mask: 0x%08x", mask);
+	SDEBUG("   src: ");
+	src = atom_get_src(ctx, attr, ptr);
+	dst &= mask;
+	dst |= src;
 	SDEBUG("   dst: ");
 	atom_put_dst(ctx, arg, attr, &dptr, dst, saved);
 }
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/evergreen_blit_kms.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/evergreen_blit_kms.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/evergreen_blit_kms.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/evergreen_blit_kms.c	2011-03-14 21:20:32.000000000 -0400
@@ -55,7 +55,7 @@ set_render_target(struct radeon_device *
 	if (h < 8)
 		h = 8;
 
-	cb_color_info = ((format << 2) | (1 << 24));
+	cb_color_info = ((format << 2) | (1 << 24) | (1 << 8));
 	pitch = (w / 8) - 1;
 	slice = ((w * h) / 64) - 1;
 
@@ -133,6 +133,9 @@ set_vtx_resource(struct radeon_device *r
 
 	/* high addr, stride */
 	sq_vtx_constant_word2 = ((upper_32_bits(gpu_addr) & 0xff) | (16 << 8));
+#ifdef __BIG_ENDIAN
+	sq_vtx_constant_word2 |= (2 << 30);
+#endif
 	/* xyzw swizzles */
 	sq_vtx_constant_word3 = (0 << 3) | (1 << 6) | (2 << 9) | (3 << 12);
 
@@ -147,7 +150,9 @@ set_vtx_resource(struct radeon_device *r
 	radeon_ring_write(rdev, 0);
 	radeon_ring_write(rdev, SQ_TEX_VTX_VALID_BUFFER << 30);
 
-	if (rdev->family == CHIP_CEDAR)
+	if ((rdev->family == CHIP_CEDAR) ||
+	    (rdev->family == CHIP_PALM) ||
+	    (rdev->family == CHIP_CAICOS))
 		cp_set_surface_sync(rdev,
 				    PACKET3_TC_ACTION_ENA, 48, gpu_addr);
 	else
@@ -171,7 +176,7 @@ set_tex_resource(struct radeon_device *r
 	sq_tex_resource_word0 = (1 << 0); /* 2D */
 	sq_tex_resource_word0 |= ((((pitch >> 3) - 1) << 6) |
 				  ((w - 1) << 18));
-	sq_tex_resource_word1 = ((h - 1) << 0);
+	sq_tex_resource_word1 = ((h - 1) << 0) | (1 << 28);
 	/* xyzw swizzles */
 	sq_tex_resource_word4 = (0 << 16) | (1 << 19) | (2 << 22) | (3 << 25);
 
@@ -219,7 +224,11 @@ draw_auto(struct radeon_device *rdev)
 	radeon_ring_write(rdev, DI_PT_RECTLIST);
 
 	radeon_ring_write(rdev, PACKET3(PACKET3_INDEX_TYPE, 0));
-	radeon_ring_write(rdev, DI_INDEX_SIZE_16_BIT);
+	radeon_ring_write(rdev,
+#ifdef __BIG_ENDIAN
+			  (2 << 2) |
+#endif
+			  DI_INDEX_SIZE_16_BIT);
 
 	radeon_ring_write(rdev, PACKET3(PACKET3_NUM_INSTANCES, 0));
 	radeon_ring_write(rdev, 1);
@@ -230,7 +239,7 @@ draw_auto(struct radeon_device *rdev)
 
 }
 
-/* emits 30 */
+/* emits 36 */
 static void
 set_default_state(struct radeon_device *rdev)
 {
@@ -243,6 +252,8 @@ set_default_state(struct radeon_device *
 	int num_hs_threads, num_ls_threads;
 	int num_ps_stack_entries, num_vs_stack_entries, num_gs_stack_entries, num_es_stack_entries;
 	int num_hs_stack_entries, num_ls_stack_entries;
+	u64 gpu_addr;
+	int dwords;
 
 	switch (rdev->family) {
 	case CHIP_CEDAR:
@@ -331,9 +342,95 @@ set_default_state(struct radeon_device *
 		num_hs_stack_entries = 85;
 		num_ls_stack_entries = 85;
 		break;
+	case CHIP_PALM:
+		num_ps_gprs = 93;
+		num_vs_gprs = 46;
+		num_temp_gprs = 4;
+		num_gs_gprs = 31;
+		num_es_gprs = 31;
+		num_hs_gprs = 23;
+		num_ls_gprs = 23;
+		num_ps_threads = 96;
+		num_vs_threads = 16;
+		num_gs_threads = 16;
+		num_es_threads = 16;
+		num_hs_threads = 16;
+		num_ls_threads = 16;
+		num_ps_stack_entries = 42;
+		num_vs_stack_entries = 42;
+		num_gs_stack_entries = 42;
+		num_es_stack_entries = 42;
+		num_hs_stack_entries = 42;
+		num_ls_stack_entries = 42;
+		break;
+	case CHIP_BARTS:
+		num_ps_gprs = 93;
+		num_vs_gprs = 46;
+		num_temp_gprs = 4;
+		num_gs_gprs = 31;
+		num_es_gprs = 31;
+		num_hs_gprs = 23;
+		num_ls_gprs = 23;
+		num_ps_threads = 128;
+		num_vs_threads = 20;
+		num_gs_threads = 20;
+		num_es_threads = 20;
+		num_hs_threads = 20;
+		num_ls_threads = 20;
+		num_ps_stack_entries = 85;
+		num_vs_stack_entries = 85;
+		num_gs_stack_entries = 85;
+		num_es_stack_entries = 85;
+		num_hs_stack_entries = 85;
+		num_ls_stack_entries = 85;
+		break;
+	case CHIP_TURKS:
+		num_ps_gprs = 93;
+		num_vs_gprs = 46;
+		num_temp_gprs = 4;
+		num_gs_gprs = 31;
+		num_es_gprs = 31;
+		num_hs_gprs = 23;
+		num_ls_gprs = 23;
+		num_ps_threads = 128;
+		num_vs_threads = 20;
+		num_gs_threads = 20;
+		num_es_threads = 20;
+		num_hs_threads = 20;
+		num_ls_threads = 20;
+		num_ps_stack_entries = 42;
+		num_vs_stack_entries = 42;
+		num_gs_stack_entries = 42;
+		num_es_stack_entries = 42;
+		num_hs_stack_entries = 42;
+		num_ls_stack_entries = 42;
+		break;
+	case CHIP_CAICOS:
+		num_ps_gprs = 93;
+		num_vs_gprs = 46;
+		num_temp_gprs = 4;
+		num_gs_gprs = 31;
+		num_es_gprs = 31;
+		num_hs_gprs = 23;
+		num_ls_gprs = 23;
+		num_ps_threads = 128;
+		num_vs_threads = 10;
+		num_gs_threads = 10;
+		num_es_threads = 10;
+		num_hs_threads = 10;
+		num_ls_threads = 10;
+		num_ps_stack_entries = 42;
+		num_vs_stack_entries = 42;
+		num_gs_stack_entries = 42;
+		num_es_stack_entries = 42;
+		num_hs_stack_entries = 42;
+		num_ls_stack_entries = 42;
+		break;
 	}
 
-	if (rdev->family == CHIP_CEDAR)
+	if ((rdev->family == CHIP_CEDAR) ||
+	    (rdev->family == CHIP_PALM) ||
+	    (rdev->family == CHIP_CAICOS))
 		sq_config = 0;
 	else
 		sq_config = VC_ENABLE;
@@ -409,6 +506,18 @@ set_default_state(struct radeon_device *
 	radeon_ring_write(rdev, 0x00000000);
 	radeon_ring_write(rdev, 0x00000000);
 
+	/* set to DX10/11 mode */
+	radeon_ring_write(rdev, PACKET3(PACKET3_MODE_CONTROL, 0));
+	radeon_ring_write(rdev, 1);
+
+	/* emit an IB pointing at default state */
+	dwords = ALIGN(rdev->r600_blit.state_len, 0x10);
+	gpu_addr = rdev->r600_blit.shader_gpu_addr + rdev->r600_blit.state_offset;
+	radeon_ring_write(rdev, PACKET3(PACKET3_INDIRECT_BUFFER, 2));
+	radeon_ring_write(rdev, gpu_addr & 0xFFFFFFFC);
+	radeon_ring_write(rdev, upper_32_bits(gpu_addr) & 0xFF);
+	radeon_ring_write(rdev, dwords);
+
 }
 
 static inline uint32_t i2f(uint32_t input)
@@ -439,8 +548,10 @@ static inline uint32_t i2f(uint32_t inpu
 int evergreen_blit_init(struct radeon_device *rdev)
 {
 	u32 obj_size;
-	int r;
+	int i, r, dwords;
 	void *ptr;
+	u32 packet2s[16];
+	int num_packet2s = 0;
 
 	/* pin copy shader into vram if already initialized */
 	if (rdev->r600_blit.shader_obj)
@@ -448,8 +559,17 @@ int evergreen_blit_init(struct radeon_de
 
 	mutex_init(&rdev->r600_blit.mutex);
 	rdev->r600_blit.state_offset = 0;
-	rdev->r600_blit.state_len = 0;
-	obj_size = 0;
+
+	rdev->r600_blit.state_len = evergreen_default_size;
+
+	dwords = rdev->r600_blit.state_len;
+	while (dwords & 0xf) {
+		packet2s[num_packet2s++] = cpu_to_le32(PACKET2(0));
+		dwords++;
+	}
+
+	obj_size = dwords * 4;
+	obj_size = ALIGN(obj_size, 256);
 
 	rdev->r600_blit.vs_offset = obj_size;
 	obj_size += evergreen_vs_size * 4;
@@ -479,8 +599,16 @@ int evergreen_blit_init(struct radeon_de
 		return r;
 	}
 
-	memcpy(ptr + rdev->r600_blit.vs_offset, evergreen_vs, evergreen_vs_size * 4);
-	memcpy(ptr + rdev->r600_blit.ps_offset, evergreen_ps, evergreen_ps_size * 4);
+	memcpy_toio(ptr + rdev->r600_blit.state_offset,
+		    evergreen_default_state, rdev->r600_blit.state_len * 4);
+
+	if (num_packet2s)
+		memcpy_toio(ptr + rdev->r600_blit.state_offset + (rdev->r600_blit.state_len * 4),
+			    packet2s, num_packet2s * 4);
+	for (i = 0; i < evergreen_vs_size; i++)
+		*(u32 *)((unsigned long)ptr + rdev->r600_blit.vs_offset + i * 4) = cpu_to_le32(evergreen_vs[i]);
+	for (i = 0; i < evergreen_ps_size; i++)
+		*(u32 *)((unsigned long)ptr + rdev->r600_blit.ps_offset + i * 4) = cpu_to_le32(evergreen_ps[i]);
 	radeon_bo_kunmap(rdev->r600_blit.shader_obj);
 	radeon_bo_unreserve(rdev->r600_blit.shader_obj);
 
@@ -495,7 +623,7 @@ done:
 		dev_err(rdev->dev, "(%d) pin blit object failed\n", r);
 		return r;
 	}
-	rdev->mc.active_vram_size = rdev->mc.real_vram_size;
+	radeon_ttm_set_active_vram_size(rdev, rdev->mc.real_vram_size);
 	return 0;
 }
 
@@ -503,7 +631,7 @@ void evergreen_blit_fini(struct radeon_d
 {
 	int r;
 
-	rdev->mc.active_vram_size = rdev->mc.visible_vram_size;
+	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
@@ -564,7 +692,7 @@ int evergreen_blit_prepare_copy(struct r
 	/* calculate number of loops correctly */
 	ring_size = num_loops * dwords_per_loop;
 	/* set default  + shaders */
-	ring_size += 46; /* shaders + def state */
+	ring_size += 52; /* shaders + def state */
 	ring_size += 10; /* fence emit for VB IB */
 	ring_size += 5; /* done copy */
 	ring_size += 10; /* fence emit for done copy */
@@ -572,7 +700,7 @@ int evergreen_blit_prepare_copy(struct r
 	if (r)
 		return r;
 
-	set_default_state(rdev); /* 30 */
+	set_default_state(rdev); /* 36 */
 	set_shaders(rdev); /* 16 */
 	return 0;
 }
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/evergreen_blit_shaders.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/evergreen_blit_shaders.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/evergreen_blit_shaders.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/evergreen_blit_shaders.c	2011-03-14 21:20:32.000000000 -0400
@@ -311,11 +311,19 @@ const u32 evergreen_vs[] =
 	0x00000000,
 	0x3c000000,
 	0x67961001,
+#ifdef __BIG_ENDIAN
+	0x000a0000,
+#else
 	0x00080000,
+#endif
 	0x00000000,
 	0x1c000000,
 	0x67961000,
+#ifdef __BIG_ENDIAN
+	0x00020008,
+#else
 	0x00000008,
+#endif
 	0x00000000,
 };
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/evergreen.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/evergreen.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/evergreen.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/evergreen.c	2011-03-14 21:20:32.000000000 -0400
@@ -39,20 +39,87 @@
 
 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_pre_page_flip(struct radeon_device *rdev, int crtc)
+{
+	struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc];
+	u32 tmp;
+
+	/* make sure flip is at vb rather than hb */
+	tmp = RREG32(EVERGREEN_GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset);
+	tmp &= ~EVERGREEN_GRPH_SURFACE_UPDATE_H_RETRACE_EN;
+	WREG32(EVERGREEN_GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset, tmp);
+
+	/* set pageflip to happen anywhere in vblank interval */
+	WREG32(EVERGREEN_MASTER_UPDATE_MODE + radeon_crtc->crtc_offset, 0);
+
+	/* enable the pflip int */
+	radeon_irq_kms_pflip_irq_get(rdev, crtc);
+}
+
+void evergreen_post_page_flip(struct radeon_device *rdev, int crtc)
+{
+	/* disable the pflip int */
+	radeon_irq_kms_pflip_irq_put(rdev, crtc);
+}
+
+u32 evergreen_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base)
+{
+	struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
+	u32 tmp = RREG32(EVERGREEN_GRPH_UPDATE + radeon_crtc->crtc_offset);
+
+	/* Lock the graphics update lock */
+	tmp |= EVERGREEN_GRPH_UPDATE_LOCK;
+	WREG32(EVERGREEN_GRPH_UPDATE + radeon_crtc->crtc_offset, tmp);
+
+	/* update the scanout addresses */
+	WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + radeon_crtc->crtc_offset,
+	       upper_32_bits(crtc_base));
+	WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset,
+	       (u32)crtc_base);
+
+	WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + radeon_crtc->crtc_offset,
+	       upper_32_bits(crtc_base));
+	WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset,
+	       (u32)crtc_base);
+
+	/* Wait for update_pending to go high. */
+	while (!(RREG32(EVERGREEN_GRPH_UPDATE + radeon_crtc->crtc_offset) & EVERGREEN_GRPH_SURFACE_UPDATE_PENDING));
+	DRM_DEBUG("Update pending now high. Unlocking vupdate_lock.\n");
+
+	/* Unlock the lock, so double-buffering can take place inside vblank */
+	tmp &= ~EVERGREEN_GRPH_UPDATE_LOCK;
+	WREG32(EVERGREEN_GRPH_UPDATE + radeon_crtc->crtc_offset, tmp);
+
+	/* Return current update_pending status: */
+	return RREG32(EVERGREEN_GRPH_UPDATE + radeon_crtc->crtc_offset) & EVERGREEN_GRPH_SURFACE_UPDATE_PENDING;
+}
 
 /* get temperature in millidegrees */
-u32 evergreen_get_temp(struct radeon_device *rdev)
+int evergreen_get_temp(struct radeon_device *rdev)
 {
 	u32 temp = (RREG32(CG_MULT_THERMAL_STATUS) & ASIC_T_MASK) >>
 		ASIC_T_SHIFT;
 	u32 actual_temp = 0;
 
-	if ((temp >> 10) & 1)
-		actual_temp = 0;
-	else if ((temp >> 9) & 1)
+	if (temp & 0x400)
+		actual_temp = -256;
+	else if (temp & 0x200)
 		actual_temp = 255;
-	else
-		actual_temp = (temp >> 1) & 0xff;
+	else if (temp & 0x100) {
+		actual_temp = temp & 0x1ff;
+		actual_temp |= ~0x1ff;
+	} else
+		actual_temp = temp & 0xff;
+
+	return (actual_temp * 1000) / 2;
+}
+
+int sumo_get_temp(struct radeon_device *rdev)
+{
+	u32 temp = RREG32(CG_THERMAL_STATUS) & 0xff;
+	int actual_temp = temp - 49;
 
 	return actual_temp * 1000;
 }
@@ -337,16 +404,28 @@ static u32 evergreen_line_buffer_adjust(
 	case 0:
 	case 4:
 	default:
-		return 3840 * 2;
+		if (ASIC_IS_DCE5(rdev))
+			return 4096 * 2;
+		else
+			return 3840 * 2;
 	case 1:
 	case 5:
-		return 5760 * 2;
+		if (ASIC_IS_DCE5(rdev))
+			return 6144 * 2;
+		else
+			return 5760 * 2;
 	case 2:
 	case 6:
-		return 7680 * 2;
+		if (ASIC_IS_DCE5(rdev))
+			return 8192 * 2;
+		else
+			return 7680 * 2;
 	case 3:
 	case 7:
-		return 1920 * 2;
+		if (ASIC_IS_DCE5(rdev))
+			return 2048 * 2;
+		else
+			return 1920 * 2;
 	}
 }
 
@@ -890,31 +969,39 @@ static void evergreen_mc_stop(struct rad
 	save->vga_hdp_control = RREG32(VGA_HDP_CONTROL);
 	save->crtc_control[0] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET);
 	save->crtc_control[1] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET);
-	save->crtc_control[2] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET);
-	save->crtc_control[3] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET);
-	save->crtc_control[4] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET);
-	save->crtc_control[5] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET);
+	if (!(rdev->flags & RADEON_IS_IGP)) {
+		save->crtc_control[2] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET);
+		save->crtc_control[3] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET);
+		save->crtc_control[4] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET);
+		save->crtc_control[5] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET);
+	}
 
 	/* Stop all video */
 	WREG32(VGA_RENDER_CONTROL, 0);
 	WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC0_REGISTER_OFFSET, 1);
 	WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC1_REGISTER_OFFSET, 1);
-	WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC2_REGISTER_OFFSET, 1);
-	WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC3_REGISTER_OFFSET, 1);
-	WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC4_REGISTER_OFFSET, 1);
-	WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC5_REGISTER_OFFSET, 1);
+	if (!(rdev->flags & RADEON_IS_IGP)) {
+		WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC2_REGISTER_OFFSET, 1);
+		WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC3_REGISTER_OFFSET, 1);
+		WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC4_REGISTER_OFFSET, 1);
+		WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC5_REGISTER_OFFSET, 1);
+	}
 	WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, 0);
 	WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, 0);
-	WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, 0);
-	WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, 0);
-	WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, 0);
-	WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, 0);
+	if (!(rdev->flags & RADEON_IS_IGP)) {
+		WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, 0);
+		WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, 0);
+		WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, 0);
+		WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, 0);
+	}
 	WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC0_REGISTER_OFFSET, 0);
 	WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC1_REGISTER_OFFSET, 0);
-	WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC2_REGISTER_OFFSET, 0);
-	WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC3_REGISTER_OFFSET, 0);
-	WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC4_REGISTER_OFFSET, 0);
-	WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC5_REGISTER_OFFSET, 0);
+	if (!(rdev->flags & RADEON_IS_IGP)) {
+		WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC2_REGISTER_OFFSET, 0);
+		WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC3_REGISTER_OFFSET, 0);
+		WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC4_REGISTER_OFFSET, 0);
+		WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC5_REGISTER_OFFSET, 0);
+	}
 
 	WREG32(D1VGA_CONTROL, 0);
 	WREG32(D2VGA_CONTROL, 0);
@@ -944,41 +1031,43 @@ static void evergreen_mc_resume(struct r
 	WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC1_REGISTER_OFFSET,
 	       (u32)rdev->mc.vram_start);
 
-	WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC2_REGISTER_OFFSET,
-	       upper_32_bits(rdev->mc.vram_start));
-	WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC2_REGISTER_OFFSET,
-	       upper_32_bits(rdev->mc.vram_start));
-	WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + EVERGREEN_CRTC2_REGISTER_OFFSET,
-	       (u32)rdev->mc.vram_start);
-	WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC2_REGISTER_OFFSET,
-	       (u32)rdev->mc.vram_start);
+	if (!(rdev->flags & RADEON_IS_IGP)) {
+		WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC2_REGISTER_OFFSET,
+		       upper_32_bits(rdev->mc.vram_start));
+		WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC2_REGISTER_OFFSET,
+		       upper_32_bits(rdev->mc.vram_start));
+		WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + EVERGREEN_CRTC2_REGISTER_OFFSET,
+		       (u32)rdev->mc.vram_start);
+		WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC2_REGISTER_OFFSET,
+		       (u32)rdev->mc.vram_start);
 
-	WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC3_REGISTER_OFFSET,
-	       upper_32_bits(rdev->mc.vram_start));
-	WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC3_REGISTER_OFFSET,
-	       upper_32_bits(rdev->mc.vram_start));
-	WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + EVERGREEN_CRTC3_REGISTER_OFFSET,
-	       (u32)rdev->mc.vram_start);
-	WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC3_REGISTER_OFFSET,
-	       (u32)rdev->mc.vram_start);
+		WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC3_REGISTER_OFFSET,
+		       upper_32_bits(rdev->mc.vram_start));
+		WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC3_REGISTER_OFFSET,
+		       upper_32_bits(rdev->mc.vram_start));
+		WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + EVERGREEN_CRTC3_REGISTER_OFFSET,
+		       (u32)rdev->mc.vram_start);
+		WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC3_REGISTER_OFFSET,
+		       (u32)rdev->mc.vram_start);
 
-	WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC4_REGISTER_OFFSET,
-	       upper_32_bits(rdev->mc.vram_start));
-	WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC4_REGISTER_OFFSET,
-	       upper_32_bits(rdev->mc.vram_start));
-	WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + EVERGREEN_CRTC4_REGISTER_OFFSET,
-	       (u32)rdev->mc.vram_start);
-	WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC4_REGISTER_OFFSET,
-	       (u32)rdev->mc.vram_start);
+		WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC4_REGISTER_OFFSET,
+		       upper_32_bits(rdev->mc.vram_start));
+		WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC4_REGISTER_OFFSET,
+		       upper_32_bits(rdev->mc.vram_start));
+		WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + EVERGREEN_CRTC4_REGISTER_OFFSET,
+		       (u32)rdev->mc.vram_start);
+		WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC4_REGISTER_OFFSET,
+		       (u32)rdev->mc.vram_start);
 
-	WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC5_REGISTER_OFFSET,
-	       upper_32_bits(rdev->mc.vram_start));
-	WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC5_REGISTER_OFFSET,
-	       upper_32_bits(rdev->mc.vram_start));
-	WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + EVERGREEN_CRTC5_REGISTER_OFFSET,
-	       (u32)rdev->mc.vram_start);
-	WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC5_REGISTER_OFFSET,
-	       (u32)rdev->mc.vram_start);
+		WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC5_REGISTER_OFFSET,
+		       upper_32_bits(rdev->mc.vram_start));
+		WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC5_REGISTER_OFFSET,
+		       upper_32_bits(rdev->mc.vram_start));
+		WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + EVERGREEN_CRTC5_REGISTER_OFFSET,
+		       (u32)rdev->mc.vram_start);
+		WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC5_REGISTER_OFFSET,
+		       (u32)rdev->mc.vram_start);
+	}
 
 	WREG32(EVERGREEN_VGA_MEMORY_BASE_ADDRESS_HIGH, upper_32_bits(rdev->mc.vram_start));
 	WREG32(EVERGREEN_VGA_MEMORY_BASE_ADDRESS, (u32)rdev->mc.vram_start);
@@ -994,22 +1083,28 @@ static void evergreen_mc_resume(struct r
 	WREG32(EVERGREEN_D6VGA_CONTROL, save->vga_control[5]);
 	WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC0_REGISTER_OFFSET, 1);
 	WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC1_REGISTER_OFFSET, 1);
-	WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC2_REGISTER_OFFSET, 1);
-	WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC3_REGISTER_OFFSET, 1);
-	WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC4_REGISTER_OFFSET, 1);
-	WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC5_REGISTER_OFFSET, 1);
+	if (!(rdev->flags & RADEON_IS_IGP)) {
+		WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC2_REGISTER_OFFSET, 1);
+		WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC3_REGISTER_OFFSET, 1);
+		WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC4_REGISTER_OFFSET, 1);
+		WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC5_REGISTER_OFFSET, 1);
+	}
 	WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, save->crtc_control[0]);
 	WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, save->crtc_control[1]);
-	WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, save->crtc_control[2]);
-	WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, save->crtc_control[3]);
-	WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, save->crtc_control[4]);
-	WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, save->crtc_control[5]);
+	if (!(rdev->flags & RADEON_IS_IGP)) {
+		WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, save->crtc_control[2]);
+		WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, save->crtc_control[3]);
+		WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, save->crtc_control[4]);
+		WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, save->crtc_control[5]);
+	}
 	WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC0_REGISTER_OFFSET, 0);
 	WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC1_REGISTER_OFFSET, 0);
-	WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC2_REGISTER_OFFSET, 0);
-	WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC3_REGISTER_OFFSET, 0);
-	WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC4_REGISTER_OFFSET, 0);
-	WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC5_REGISTER_OFFSET, 0);
+	if (!(rdev->flags & RADEON_IS_IGP)) {
+		WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC2_REGISTER_OFFSET, 0);
+		WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC3_REGISTER_OFFSET, 0);
+		WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC4_REGISTER_OFFSET, 0);
+		WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC5_REGISTER_OFFSET, 0);
+	}
 	WREG32(VGA_RENDER_CONTROL, save->vga_render_control);
 }
 
@@ -1057,11 +1152,17 @@ static void evergreen_mc_program(struct
 			rdev->mc.vram_end >> 12);
 	}
 	WREG32(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR, 0);
+	if (rdev->flags & RADEON_IS_IGP) {
+		tmp = RREG32(MC_FUS_VM_FB_OFFSET) & 0x000FFFFF;
+		tmp |= ((rdev->mc.vram_end >> 20) & 0xF) << 24;
+		tmp |= ((rdev->mc.vram_start >> 20) & 0xF) << 20;
+		WREG32(MC_FUS_VM_FB_OFFSET, tmp);
+	}
 	tmp = ((rdev->mc.vram_end >> 24) & 0xFFFF) << 16;
 	tmp |= ((rdev->mc.vram_start >> 24) & 0xFFFF);
 	WREG32(MC_VM_FB_LOCATION, tmp);
 	WREG32(HDP_NONSURFACE_BASE, (rdev->mc.vram_start >> 8));
-	WREG32(HDP_NONSURFACE_INFO, (2 << 7));
+	WREG32(HDP_NONSURFACE_INFO, (2 << 7) | (1 << 30));
 	WREG32(HDP_NONSURFACE_SIZE, 0x3FFFFFFF);
 	if (rdev->flags & RADEON_IS_AGP) {
 		WREG32(MC_VM_AGP_TOP, rdev->mc.gtt_end >> 16);
@@ -1084,6 +1185,22 @@ static void evergreen_mc_program(struct
 /*
  * CP.
  */
+void evergreen_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib)
+{
+	/* set to DX10/11 mode */
+	radeon_ring_write(rdev, PACKET3(PACKET3_MODE_CONTROL, 0));
+	radeon_ring_write(rdev, 1);
+	/* FIXME: implement */
+	radeon_ring_write(rdev, PACKET3(PACKET3_INDIRECT_BUFFER, 2));
+	radeon_ring_write(rdev,
+#ifdef __BIG_ENDIAN
+			  (2 << 0) |
+#endif
+			  (ib->gpu_addr & 0xFFFFFFFC));
+	radeon_ring_write(rdev, upper_32_bits(ib->gpu_addr) & 0xFF);
+	radeon_ring_write(rdev, ib->length_dw);
+}
+
 
 static int evergreen_cp_load_microcode(struct radeon_device *rdev)
 {
@@ -1094,7 +1211,11 @@ static int evergreen_cp_load_microcode(s
 		return -EINVAL;
 
 	r700_cp_stop(rdev);
-	WREG32(CP_RB_CNTL, RB_NO_UPDATE | (15 << 8) | (3 << 0));
+	WREG32(CP_RB_CNTL,
+#ifdef __BIG_ENDIAN
+	       BUF_SWAP_32BIT |
+#endif
+	       RB_NO_UPDATE | RB_BLKSZ(15) | RB_BUFSZ(3));
 
 	fw_data = (const __be32 *)rdev->pfp_fw->data;
 	WREG32(CP_PFP_UCODE_ADDR, 0);
@@ -1135,7 +1256,7 @@ static int evergreen_cp_start(struct rad
 	cp_me = 0xff;
 	WREG32(CP_ME_CNTL, cp_me);
 
-	r = radeon_ring_lock(rdev, evergreen_default_size + 15);
+	r = radeon_ring_lock(rdev, evergreen_default_size + 19);
 	if (r) {
 		DRM_ERROR("radeon: cp failed to lock ring (%d).\n", r);
 		return r;
@@ -1168,6 +1289,11 @@ static int evergreen_cp_start(struct rad
 	radeon_ring_write(rdev, 0xffffffff);
 	radeon_ring_write(rdev, 0xffffffff);
 
+	radeon_ring_write(rdev, 0xc0026900);
+	radeon_ring_write(rdev, 0x00000316);
+	radeon_ring_write(rdev, 0x0000000e); /* VGT_VERTEX_REUSE_BLOCK_CNTL */
+	radeon_ring_write(rdev, 0x00000010); /*  */
+
 	radeon_ring_unlock_commit(rdev);
 
 	return 0;
@@ -1208,7 +1334,11 @@ int evergreen_cp_resume(struct radeon_de
 	WREG32(CP_RB_WPTR, 0);
 
 	/* set the wb address wether it's enabled or not */
-	WREG32(CP_RB_RPTR_ADDR, (rdev->wb.gpu_addr + RADEON_WB_CP_RPTR_OFFSET) & 0xFFFFFFFC);
+	WREG32(CP_RB_RPTR_ADDR,
+#ifdef __BIG_ENDIAN
+	       RB_RPTR_SWAP(2) |
+#endif
+	       ((rdev->wb.gpu_addr + RADEON_WB_CP_RPTR_OFFSET) & 0xFFFFFFFC));
 	WREG32(CP_RB_RPTR_ADDR_HI, upper_32_bits(rdev->wb.gpu_addr + RADEON_WB_CP_RPTR_OFFSET) & 0xFF);
 	WREG32(SCRATCH_ADDR, ((rdev->wb.gpu_addr + RADEON_WB_SCRATCH_OFFSET) >> 8) & 0xFFFFFFFF);
 
@@ -1285,11 +1415,15 @@ static u32 evergreen_get_tile_pipe_to_ba
 	switch (rdev->family) {
 	case CHIP_CEDAR:
 	case CHIP_REDWOOD:
+	case CHIP_PALM:
+	case CHIP_TURKS:
+	case CHIP_CAICOS:
 		force_no_swizzle = false;
 		break;
 	case CHIP_CYPRESS:
 	case CHIP_HEMLOCK:
 	case CHIP_JUNIPER:
+	case CHIP_BARTS:
 	default:
 		force_no_swizzle = true;
 		break;
@@ -1384,6 +1518,46 @@ static u32 evergreen_get_tile_pipe_to_ba
 	return backend_map;
 }
 
+static void evergreen_program_channel_remap(struct radeon_device *rdev)
+{
+	u32 tcp_chan_steer_lo, tcp_chan_steer_hi, mc_shared_chremap, tmp;
+
+	tmp = RREG32(MC_SHARED_CHMAP);
+	switch ((tmp & NOOFCHAN_MASK) >> NOOFCHAN_SHIFT) {
+	case 0:
+	case 1:
+	case 2:
+	case 3:
+	default:
+		/* default mapping */
+		mc_shared_chremap = 0x00fac688;
+		break;
+	}
+
+	switch (rdev->family) {
+	case CHIP_HEMLOCK:
+	case CHIP_CYPRESS:
+	case CHIP_BARTS:
+		tcp_chan_steer_lo = 0x54763210;
+		tcp_chan_steer_hi = 0x0000ba98;
+		break;
+	case CHIP_JUNIPER:
+	case CHIP_REDWOOD:
+	case CHIP_CEDAR:
+	case CHIP_PALM:
+	case CHIP_TURKS:
+	case CHIP_CAICOS:
+	default:
+		tcp_chan_steer_lo = 0x76543210;
+		tcp_chan_steer_hi = 0x0000ba98;
+		break;
+	}
+
+	WREG32(TCP_CHAN_STEER_LO, tcp_chan_steer_lo);
+	WREG32(TCP_CHAN_STEER_HI, tcp_chan_steer_hi);
+	WREG32(MC_SHARED_CHREMAP, mc_shared_chremap);
+}
+
 static void evergreen_gpu_init(struct radeon_device *rdev)
 {
 	u32 cc_rb_backend_disable = 0;
@@ -1495,6 +1669,90 @@ static void evergreen_gpu_init(struct ra
 		rdev->config.evergreen.sc_hiz_tile_fifo_size = 0x30;
 		rdev->config.evergreen.sc_earlyz_tile_fifo_size = 0x130;
 		break;
+	case CHIP_PALM:
+		rdev->config.evergreen.num_ses = 1;
+		rdev->config.evergreen.max_pipes = 2;
+		rdev->config.evergreen.max_tile_pipes = 2;
+		rdev->config.evergreen.max_simds = 2;
+		rdev->config.evergreen.max_backends = 1 * rdev->config.evergreen.num_ses;
+		rdev->config.evergreen.max_gprs = 256;
+		rdev->config.evergreen.max_threads = 192;
+		rdev->config.evergreen.max_gs_threads = 16;
+		rdev->config.evergreen.max_stack_entries = 256;
+		rdev->config.evergreen.sx_num_of_sets = 4;
+		rdev->config.evergreen.sx_max_export_size = 128;
+		rdev->config.evergreen.sx_max_export_pos_size = 32;
+		rdev->config.evergreen.sx_max_export_smx_size = 96;
+		rdev->config.evergreen.max_hw_contexts = 4;
+		rdev->config.evergreen.sq_num_cf_insts = 1;
+
+		rdev->config.evergreen.sc_prim_fifo_size = 0x40;
+		rdev->config.evergreen.sc_hiz_tile_fifo_size = 0x30;
+		rdev->config.evergreen.sc_earlyz_tile_fifo_size = 0x130;
+		break;
+	case CHIP_BARTS:
+		rdev->config.evergreen.num_ses = 2;
+		rdev->config.evergreen.max_pipes = 4;
+		rdev->config.evergreen.max_tile_pipes = 8;
+		rdev->config.evergreen.max_simds = 7;
+		rdev->config.evergreen.max_backends = 4 * rdev->config.evergreen.num_ses;
+		rdev->config.evergreen.max_gprs = 256;
+		rdev->config.evergreen.max_threads = 248;
+		rdev->config.evergreen.max_gs_threads = 32;
+		rdev->config.evergreen.max_stack_entries = 512;
+		rdev->config.evergreen.sx_num_of_sets = 4;
+		rdev->config.evergreen.sx_max_export_size = 256;
+		rdev->config.evergreen.sx_max_export_pos_size = 64;
+		rdev->config.evergreen.sx_max_export_smx_size = 192;
+		rdev->config.evergreen.max_hw_contexts = 8;
+		rdev->config.evergreen.sq_num_cf_insts = 2;
+
+		rdev->config.evergreen.sc_prim_fifo_size = 0x100;
+		rdev->config.evergreen.sc_hiz_tile_fifo_size = 0x30;
+		rdev->config.evergreen.sc_earlyz_tile_fifo_size = 0x130;
+		break;
+	case CHIP_TURKS:
+		rdev->config.evergreen.num_ses = 1;
+		rdev->config.evergreen.max_pipes = 4;
+		rdev->config.evergreen.max_tile_pipes = 4;
+		rdev->config.evergreen.max_simds = 6;
+		rdev->config.evergreen.max_backends = 2 * rdev->config.evergreen.num_ses;
+		rdev->config.evergreen.max_gprs = 256;
+		rdev->config.evergreen.max_threads = 248;
+		rdev->config.evergreen.max_gs_threads = 32;
+		rdev->config.evergreen.max_stack_entries = 256;
+		rdev->config.evergreen.sx_num_of_sets = 4;
+		rdev->config.evergreen.sx_max_export_size = 256;
+		rdev->config.evergreen.sx_max_export_pos_size = 64;
+		rdev->config.evergreen.sx_max_export_smx_size = 192;
+		rdev->config.evergreen.max_hw_contexts = 8;
+		rdev->config.evergreen.sq_num_cf_insts = 2;
+
+		rdev->config.evergreen.sc_prim_fifo_size = 0x100;
+		rdev->config.evergreen.sc_hiz_tile_fifo_size = 0x30;
+		rdev->config.evergreen.sc_earlyz_tile_fifo_size = 0x130;
+		break;
+	case CHIP_CAICOS:
+		rdev->config.evergreen.num_ses = 1;
+		rdev->config.evergreen.max_pipes = 4;
+		rdev->config.evergreen.max_tile_pipes = 2;
+		rdev->config.evergreen.max_simds = 2;
+		rdev->config.evergreen.max_backends = 1 * rdev->config.evergreen.num_ses;
+		rdev->config.evergreen.max_gprs = 256;
+		rdev->config.evergreen.max_threads = 192;
+		rdev->config.evergreen.max_gs_threads = 16;
+		rdev->config.evergreen.max_stack_entries = 256;
+		rdev->config.evergreen.sx_num_of_sets = 4;
+		rdev->config.evergreen.sx_max_export_size = 128;
+		rdev->config.evergreen.sx_max_export_pos_size = 32;
+		rdev->config.evergreen.sx_max_export_smx_size = 96;
+		rdev->config.evergreen.max_hw_contexts = 4;
+		rdev->config.evergreen.sq_num_cf_insts = 1;
+
+		rdev->config.evergreen.sc_prim_fifo_size = 0x40;
+		rdev->config.evergreen.sc_hiz_tile_fifo_size = 0x30;
+		rdev->config.evergreen.sc_earlyz_tile_fifo_size = 0x130;
+		break;
 	}
 
 	/* Initialize HDP */
@@ -1636,6 +1894,7 @@ static void evergreen_gpu_init(struct ra
 		switch (rdev->family) {
 		case CHIP_CYPRESS:
 		case CHIP_HEMLOCK:
+		case CHIP_BARTS:
 			gb_backend_map = 0x66442200;
 			break;
 		case CHIP_JUNIPER:
@@ -1687,6 +1946,8 @@ static void evergreen_gpu_init(struct ra
 	WREG32(DMIF_ADDR_CONFIG, gb_addr_config);
 	WREG32(HDP_ADDR_CONFIG, gb_addr_config);
 
+	evergreen_program_channel_remap(rdev);
+
 	num_shader_engines = ((RREG32(GB_ADDR_CONFIG) & NUM_SHADER_ENGINES(3)) >> 12) + 1;
 	grbm_gfx_index = INSTANCE_BROADCAST_WRITES;
 
@@ -1769,9 +2030,16 @@ static void evergreen_gpu_init(struct ra
 		      GS_PRIO(2) |
 		      ES_PRIO(3));
 
-	if (rdev->family == CHIP_CEDAR)
+	switch (rdev->family) {
+	case CHIP_CEDAR:
+	case CHIP_PALM:
+	case CHIP_CAICOS:
 		/* no vertex cache */
 		sq_config &= ~VC_ENABLE;
+		break;
+	default:
+		break;
+	}
 
 	sq_lds_resource_mgmt = RREG32(SQ_LDS_RESOURCE_MGMT);
 
@@ -1783,10 +2051,15 @@ static void evergreen_gpu_init(struct ra
 	sq_gpr_resource_mgmt_3 = NUM_HS_GPRS((rdev->config.evergreen.max_gprs - (4 * 2)) * 3 / 32);
 	sq_gpr_resource_mgmt_3 |= NUM_LS_GPRS((rdev->config.evergreen.max_gprs - (4 * 2)) * 3 / 32);
 
-	if (rdev->family == CHIP_CEDAR)
+	switch (rdev->family) {
+	case CHIP_CEDAR:
+	case CHIP_PALM:
 		ps_thread_count = 96;
-	else
+		break;
+	default:
 		ps_thread_count = 128;
+		break;
+	}
 
 	sq_thread_resource_mgmt = NUM_PS_THREADS(ps_thread_count);
 	sq_thread_resource_mgmt |= NUM_VS_THREADS((((rdev->config.evergreen.max_threads - ps_thread_count) / 6) / 8) * 8);
@@ -1817,14 +2090,21 @@ static void evergreen_gpu_init(struct ra
 	WREG32(PA_SC_FORCE_EOV_MAX_CNTS, (FORCE_EOV_MAX_CLK_CNT(4095) |
 					  FORCE_EOV_MAX_REZ_CNT(255)));
 
-	if (rdev->family == CHIP_CEDAR)
+	switch (rdev->family) {
+	case CHIP_CEDAR:
+	case CHIP_PALM:
+	case CHIP_CAICOS:
 		vgt_cache_invalidation = CACHE_INVALIDATION(TC_ONLY);
-	else
+		break;
+	default:
 		vgt_cache_invalidation = CACHE_INVALIDATION(VC_AND_TC);
+		break;
+	}
 	vgt_cache_invalidation |= AUTO_INVLD_EN(ES_AND_GS_AUTO);
 	WREG32(VGT_CACHE_INVALIDATION, vgt_cache_invalidation);
 
 	WREG32(VGT_GS_VERTEX_REUSE, 16);
+	WREG32(PA_SU_LINE_STIPPLE_VALUE, 0);
 	WREG32(PA_SC_LINE_STIPPLE_STATE, 0);
 
 	WREG32(VGT_VERTEX_REUSE_BLOCK_CNTL, 14);
@@ -1904,12 +2184,17 @@ int evergreen_mc_init(struct radeon_devi
 	rdev->mc.aper_base = pci_resource_start(rdev->pdev, 0);
 	rdev->mc.aper_size = pci_resource_len(rdev->pdev, 0);
 	/* Setup GPU memory space */
-	/* size in MB on evergreen */
-	rdev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE) * 1024 * 1024;
-	rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE) * 1024 * 1024;
+	if (rdev->flags & RADEON_IS_IGP) {
+		/* size in bytes on fusion */
+		rdev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE);
+		rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE);
+	} else {
+		/* size in MB on evergreen */
+		rdev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE) * 1024 * 1024;
+		rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE) * 1024 * 1024;
+	}
 	rdev->mc.visible_vram_size = rdev->mc.aper_size;
-	rdev->mc.active_vram_size = rdev->mc.visible_vram_size;
-	r600_vram_gtt_location(rdev, &rdev->mc);
+	r700_vram_gtt_location(rdev, &rdev->mc);
 	radeon_update_bandwidth_info(rdev);
 
 	return 0;
@@ -1917,8 +2202,30 @@ int evergreen_mc_init(struct radeon_devi
 
 bool evergreen_gpu_is_lockup(struct radeon_device *rdev)
 {
-	/* FIXME: implement for evergreen */
-	return false;
+	u32 srbm_status;
+	u32 grbm_status;
+	u32 grbm_status_se0, grbm_status_se1;
+	struct r100_gpu_lockup *lockup = &rdev->config.evergreen.lockup;
+	int r;
+
+	srbm_status = RREG32(SRBM_STATUS);
+	grbm_status = RREG32(GRBM_STATUS);
+	grbm_status_se0 = RREG32(GRBM_STATUS_SE0);
+	grbm_status_se1 = RREG32(GRBM_STATUS_SE1);
+	if (!(grbm_status & GUI_ACTIVE)) {
+		r100_gpu_lockup_update(lockup, &rdev->cp);
+		return false;
+	}
+	/* force CP activities */
+	r = radeon_ring_lock(rdev, 2);
+	if (!r) {
+		/* PACKET2 NOP */
+		radeon_ring_write(rdev, 0x80000000);
+		radeon_ring_write(rdev, 0x80000000);
+		radeon_ring_unlock_commit(rdev);
+	}
+	rdev->cp.rptr = RREG32(CP_RB_RPTR);
+	return r100_gpu_cp_is_lockup(rdev, lockup, &rdev->cp);
 }
 
 static int evergreen_gpu_soft_reset(struct radeon_device *rdev)
@@ -1926,6 +2233,9 @@ static int evergreen_gpu_soft_reset(stru
 	struct evergreen_mc_save save;
 	u32 grbm_reset = 0;
 
+	if (!(RREG32(GRBM_STATUS) & GUI_ACTIVE))
+		return 0;
+
 	dev_info(rdev->dev, "GPU softreset \n");
 	dev_info(rdev->dev, "  GRBM_STATUS=0x%08X\n",
 		RREG32(GRBM_STATUS));
@@ -2011,17 +2321,21 @@ void evergreen_disable_interrupt_state(s
 	WREG32(GRBM_INT_CNTL, 0);
 	WREG32(INT_MASK + EVERGREEN_CRTC0_REGISTER_OFFSET, 0);
 	WREG32(INT_MASK + EVERGREEN_CRTC1_REGISTER_OFFSET, 0);
-	WREG32(INT_MASK + EVERGREEN_CRTC2_REGISTER_OFFSET, 0);
-	WREG32(INT_MASK + EVERGREEN_CRTC3_REGISTER_OFFSET, 0);
-	WREG32(INT_MASK + EVERGREEN_CRTC4_REGISTER_OFFSET, 0);
-	WREG32(INT_MASK + EVERGREEN_CRTC5_REGISTER_OFFSET, 0);
+	if (!(rdev->flags & RADEON_IS_IGP)) {
+		WREG32(INT_MASK + EVERGREEN_CRTC2_REGISTER_OFFSET, 0);
+		WREG32(INT_MASK + EVERGREEN_CRTC3_REGISTER_OFFSET, 0);
+		WREG32(INT_MASK + EVERGREEN_CRTC4_REGISTER_OFFSET, 0);
+		WREG32(INT_MASK + EVERGREEN_CRTC5_REGISTER_OFFSET, 0);
+	}
 
 	WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, 0);
 	WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, 0);
-	WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, 0);
-	WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, 0);
-	WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, 0);
-	WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, 0);
+	if (!(rdev->flags & RADEON_IS_IGP)) {
+		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, 0);
+		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, 0);
+		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, 0);
+		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, 0);
+	}
 
 	WREG32(DACA_AUTODETECT_INT_CONTROL, 0);
 	WREG32(DACB_AUTODETECT_INT_CONTROL, 0);
@@ -2047,6 +2361,7 @@ int evergreen_irq_set(struct radeon_devi
 	u32 crtc1 = 0, crtc2 = 0, crtc3 = 0, crtc4 = 0, crtc5 = 0, crtc6 = 0;
 	u32 hpd1, hpd2, hpd3, hpd4, hpd5, hpd6;
 	u32 grbm_int_cntl = 0;
+	u32 grph1 = 0, grph2 = 0, grph3 = 0, grph4 = 0, grph5 = 0, grph6 = 0;
 
 	if (!rdev->irq.installed) {
 		WARN(1, "Can't enable IRQ/MSI because no handler is installed\n");
@@ -2072,27 +2387,33 @@ int evergreen_irq_set(struct radeon_devi
 		cp_int_cntl |= RB_INT_ENABLE;
 		cp_int_cntl |= TIME_STAMP_INT_ENABLE;
 	}
-	if (rdev->irq.crtc_vblank_int[0]) {
+	if (rdev->irq.crtc_vblank_int[0] ||
+	    rdev->irq.pflip[0]) {
 		DRM_DEBUG("evergreen_irq_set: vblank 0\n");
 		crtc1 |= VBLANK_INT_MASK;
 	}
-	if (rdev->irq.crtc_vblank_int[1]) {
+	if (rdev->irq.crtc_vblank_int[1] ||
+	    rdev->irq.pflip[1]) {
 		DRM_DEBUG("evergreen_irq_set: vblank 1\n");
 		crtc2 |= VBLANK_INT_MASK;
 	}
-	if (rdev->irq.crtc_vblank_int[2]) {
+	if (rdev->irq.crtc_vblank_int[2] ||
+	    rdev->irq.pflip[2]) {
 		DRM_DEBUG("evergreen_irq_set: vblank 2\n");
 		crtc3 |= VBLANK_INT_MASK;
 	}
-	if (rdev->irq.crtc_vblank_int[3]) {
+	if (rdev->irq.crtc_vblank_int[3] ||
+	    rdev->irq.pflip[3]) {
 		DRM_DEBUG("evergreen_irq_set: vblank 3\n");
 		crtc4 |= VBLANK_INT_MASK;
 	}
-	if (rdev->irq.crtc_vblank_int[4]) {
+	if (rdev->irq.crtc_vblank_int[4] ||
+	    rdev->irq.pflip[4]) {
 		DRM_DEBUG("evergreen_irq_set: vblank 4\n");
 		crtc5 |= VBLANK_INT_MASK;
 	}
-	if (rdev->irq.crtc_vblank_int[5]) {
+	if (rdev->irq.crtc_vblank_int[5] ||
+	    rdev->irq.pflip[5]) {
 		DRM_DEBUG("evergreen_irq_set: vblank 5\n");
 		crtc6 |= VBLANK_INT_MASK;
 	}
@@ -2130,10 +2451,19 @@ int evergreen_irq_set(struct radeon_devi
 
 	WREG32(INT_MASK + EVERGREEN_CRTC0_REGISTER_OFFSET, crtc1);
 	WREG32(INT_MASK + EVERGREEN_CRTC1_REGISTER_OFFSET, crtc2);
-	WREG32(INT_MASK + EVERGREEN_CRTC2_REGISTER_OFFSET, crtc3);
-	WREG32(INT_MASK + EVERGREEN_CRTC3_REGISTER_OFFSET, crtc4);
-	WREG32(INT_MASK + EVERGREEN_CRTC4_REGISTER_OFFSET, crtc5);
-	WREG32(INT_MASK + EVERGREEN_CRTC5_REGISTER_OFFSET, crtc6);
+	if (!(rdev->flags & RADEON_IS_IGP)) {
+		WREG32(INT_MASK + EVERGREEN_CRTC2_REGISTER_OFFSET, crtc3);
+		WREG32(INT_MASK + EVERGREEN_CRTC3_REGISTER_OFFSET, crtc4);
+		WREG32(INT_MASK + EVERGREEN_CRTC4_REGISTER_OFFSET, crtc5);
+		WREG32(INT_MASK + EVERGREEN_CRTC5_REGISTER_OFFSET, crtc6);
+	}
+
+	WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, grph1);
+	WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, grph2);
+	WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, grph3);
+	WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, grph4);
+	WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, grph5);
+	WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, grph6);
 
 	WREG32(DC_HPD1_INT_CONTROL, hpd1);
 	WREG32(DC_HPD2_INT_CONTROL, hpd2);
@@ -2145,79 +2475,92 @@ int evergreen_irq_set(struct radeon_devi
 	return 0;
 }
 
-static inline void evergreen_irq_ack(struct radeon_device *rdev,
-				     u32 *disp_int,
-				     u32 *disp_int_cont,
-				     u32 *disp_int_cont2,
-				     u32 *disp_int_cont3,
-				     u32 *disp_int_cont4,
-				     u32 *disp_int_cont5)
+static inline void evergreen_irq_ack(struct radeon_device *rdev)
 {
 	u32 tmp;
 
-	*disp_int = RREG32(DISP_INTERRUPT_STATUS);
-	*disp_int_cont = RREG32(DISP_INTERRUPT_STATUS_CONTINUE);
-	*disp_int_cont2 = RREG32(DISP_INTERRUPT_STATUS_CONTINUE2);
-	*disp_int_cont3 = RREG32(DISP_INTERRUPT_STATUS_CONTINUE3);
-	*disp_int_cont4 = RREG32(DISP_INTERRUPT_STATUS_CONTINUE4);
-	*disp_int_cont5 = RREG32(DISP_INTERRUPT_STATUS_CONTINUE5);
+	rdev->irq.stat_regs.evergreen.disp_int = RREG32(DISP_INTERRUPT_STATUS);
+	rdev->irq.stat_regs.evergreen.disp_int_cont = RREG32(DISP_INTERRUPT_STATUS_CONTINUE);
+	rdev->irq.stat_regs.evergreen.disp_int_cont2 = RREG32(DISP_INTERRUPT_STATUS_CONTINUE2);
+	rdev->irq.stat_regs.evergreen.disp_int_cont3 = RREG32(DISP_INTERRUPT_STATUS_CONTINUE3);
+	rdev->irq.stat_regs.evergreen.disp_int_cont4 = RREG32(DISP_INTERRUPT_STATUS_CONTINUE4);
+	rdev->irq.stat_regs.evergreen.disp_int_cont5 = RREG32(DISP_INTERRUPT_STATUS_CONTINUE5);
+	rdev->irq.stat_regs.evergreen.d1grph_int = RREG32(GRPH_INT_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET);
+	rdev->irq.stat_regs.evergreen.d2grph_int = RREG32(GRPH_INT_STATUS + EVERGREEN_CRTC1_REGISTER_OFFSET);
+	rdev->irq.stat_regs.evergreen.d3grph_int = RREG32(GRPH_INT_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET);
+	rdev->irq.stat_regs.evergreen.d4grph_int = RREG32(GRPH_INT_STATUS + EVERGREEN_CRTC3_REGISTER_OFFSET);
+	rdev->irq.stat_regs.evergreen.d5grph_int = RREG32(GRPH_INT_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET);
+	rdev->irq.stat_regs.evergreen.d6grph_int = RREG32(GRPH_INT_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET);
 
-	if (*disp_int & LB_D1_VBLANK_INTERRUPT)
+	if (rdev->irq.stat_regs.evergreen.d1grph_int & GRPH_PFLIP_INT_OCCURRED)
+		WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR);
+	if (rdev->irq.stat_regs.evergreen.d2grph_int & GRPH_PFLIP_INT_OCCURRED)
+		WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC1_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR);
+	if (rdev->irq.stat_regs.evergreen.d3grph_int & GRPH_PFLIP_INT_OCCURRED)
+		WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR);
+	if (rdev->irq.stat_regs.evergreen.d4grph_int & GRPH_PFLIP_INT_OCCURRED)
+		WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC3_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR);
+	if (rdev->irq.stat_regs.evergreen.d5grph_int & GRPH_PFLIP_INT_OCCURRED)
+		WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR);
+	if (rdev->irq.stat_regs.evergreen.d6grph_int & GRPH_PFLIP_INT_OCCURRED)
+		WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR);
+
+	if (rdev->irq.stat_regs.evergreen.disp_int & LB_D1_VBLANK_INTERRUPT)
 		WREG32(VBLANK_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET, VBLANK_ACK);
-	if (*disp_int & LB_D1_VLINE_INTERRUPT)
+	if (rdev->irq.stat_regs.evergreen.disp_int & LB_D1_VLINE_INTERRUPT)
 		WREG32(VLINE_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET, VLINE_ACK);
 
-	if (*disp_int_cont & LB_D2_VBLANK_INTERRUPT)
+	if (rdev->irq.stat_regs.evergreen.disp_int_cont & LB_D2_VBLANK_INTERRUPT)
 		WREG32(VBLANK_STATUS + EVERGREEN_CRTC1_REGISTER_OFFSET, VBLANK_ACK);
-	if (*disp_int_cont & LB_D2_VLINE_INTERRUPT)
+	if (rdev->irq.stat_regs.evergreen.disp_int_cont & LB_D2_VLINE_INTERRUPT)
 		WREG32(VLINE_STATUS + EVERGREEN_CRTC1_REGISTER_OFFSET, VLINE_ACK);
 
-	if (*disp_int_cont2 & LB_D3_VBLANK_INTERRUPT)
+	if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & LB_D3_VBLANK_INTERRUPT)
 		WREG32(VBLANK_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET, VBLANK_ACK);
-	if (*disp_int_cont2 & LB_D3_VLINE_INTERRUPT)
+	if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & LB_D3_VLINE_INTERRUPT)
 		WREG32(VLINE_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET, VLINE_ACK);
 
-	if (*disp_int_cont3 & LB_D4_VBLANK_INTERRUPT)
+	if (rdev->irq.stat_regs.evergreen.disp_int_cont3 & LB_D4_VBLANK_INTERRUPT)
 		WREG32(VBLANK_STATUS + EVERGREEN_CRTC3_REGISTER_OFFSET, VBLANK_ACK);
-	if (*disp_int_cont3 & LB_D4_VLINE_INTERRUPT)
+	if (rdev->irq.stat_regs.evergreen.disp_int_cont3 & LB_D4_VLINE_INTERRUPT)
 		WREG32(VLINE_STATUS + EVERGREEN_CRTC3_REGISTER_OFFSET, VLINE_ACK);
 
-	if (*disp_int_cont4 & LB_D5_VBLANK_INTERRUPT)
+	if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & LB_D5_VBLANK_INTERRUPT)
 		WREG32(VBLANK_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET, VBLANK_ACK);
-	if (*disp_int_cont4 & LB_D5_VLINE_INTERRUPT)
+	if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & LB_D5_VLINE_INTERRUPT)
 		WREG32(VLINE_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET, VLINE_ACK);
 
-	if (*disp_int_cont5 & LB_D6_VBLANK_INTERRUPT)
+	if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & LB_D6_VBLANK_INTERRUPT)
 		WREG32(VBLANK_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET, VBLANK_ACK);
-	if (*disp_int_cont5 & LB_D6_VLINE_INTERRUPT)
+	if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & LB_D6_VLINE_INTERRUPT)
 		WREG32(VLINE_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET, VLINE_ACK);
 
-	if (*disp_int & DC_HPD1_INTERRUPT) {
+	if (rdev->irq.stat_regs.evergreen.disp_int & DC_HPD1_INTERRUPT) {
 		tmp = RREG32(DC_HPD1_INT_CONTROL);
 		tmp |= DC_HPDx_INT_ACK;
 		WREG32(DC_HPD1_INT_CONTROL, tmp);
 	}
-	if (*disp_int_cont & DC_HPD2_INTERRUPT) {
+	if (rdev->irq.stat_regs.evergreen.disp_int_cont & DC_HPD2_INTERRUPT) {
 		tmp = RREG32(DC_HPD2_INT_CONTROL);
 		tmp |= DC_HPDx_INT_ACK;
 		WREG32(DC_HPD2_INT_CONTROL, tmp);
 	}
-	if (*disp_int_cont2 & DC_HPD3_INTERRUPT) {
+	if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & DC_HPD3_INTERRUPT) {
 		tmp = RREG32(DC_HPD3_INT_CONTROL);
 		tmp |= DC_HPDx_INT_ACK;
 		WREG32(DC_HPD3_INT_CONTROL, tmp);
 	}
-	if (*disp_int_cont3 & DC_HPD4_INTERRUPT) {
+	if (rdev->irq.stat_regs.evergreen.disp_int_cont3 & DC_HPD4_INTERRUPT) {
 		tmp = RREG32(DC_HPD4_INT_CONTROL);
 		tmp |= DC_HPDx_INT_ACK;
 		WREG32(DC_HPD4_INT_CONTROL, tmp);
 	}
-	if (*disp_int_cont4 & DC_HPD5_INTERRUPT) {
+	if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & DC_HPD5_INTERRUPT) {
 		tmp = RREG32(DC_HPD5_INT_CONTROL);
 		tmp |= DC_HPDx_INT_ACK;
 		WREG32(DC_HPD5_INT_CONTROL, tmp);
 	}
-	if (*disp_int_cont5 & DC_HPD6_INTERRUPT) {
+	if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & DC_HPD6_INTERRUPT) {
 		tmp = RREG32(DC_HPD5_INT_CONTROL);
 		tmp |= DC_HPDx_INT_ACK;
 		WREG32(DC_HPD6_INT_CONTROL, tmp);
@@ -2226,14 +2569,10 @@ static inline void evergreen_irq_ack(str
 
 void evergreen_irq_disable(struct radeon_device *rdev)
 {
-	u32 disp_int, disp_int_cont, disp_int_cont2;
-	u32 disp_int_cont3, disp_int_cont4, disp_int_cont5;
-
 	r600_disable_interrupts(rdev);
 	/* Wait and acknowledge irq */
 	mdelay(1);
-	evergreen_irq_ack(rdev, &disp_int, &disp_int_cont, &disp_int_cont2,
-			  &disp_int_cont3, &disp_int_cont4, &disp_int_cont5);
+	evergreen_irq_ack(rdev);
 	evergreen_disable_interrupt_state(rdev);
 }
 
@@ -2273,8 +2612,6 @@ int evergreen_irq_process(struct radeon_
 	u32 rptr = rdev->ih.rptr;
 	u32 src_id, src_data;
 	u32 ring_index;
-	u32 disp_int, disp_int_cont, disp_int_cont2;
-	u32 disp_int_cont3, disp_int_cont4, disp_int_cont5;
 	unsigned long flags;
 	bool queue_hotplug = false;
 
@@ -2295,31 +2632,34 @@ int evergreen_irq_process(struct radeon_
 
 restart_ih:
 	/* display interrupts */
-	evergreen_irq_ack(rdev, &disp_int, &disp_int_cont, &disp_int_cont2,
-			  &disp_int_cont3, &disp_int_cont4, &disp_int_cont5);
+	evergreen_irq_ack(rdev);
 
 	rdev->ih.wptr = wptr;
 	while (rptr != wptr) {
 		/* wptr/rptr are in bytes! */
 		ring_index = rptr / 4;
-		src_id =  rdev->ih.ring[ring_index] & 0xff;
-		src_data = rdev->ih.ring[ring_index + 1] & 0xfffffff;
+		src_id =  le32_to_cpu(rdev->ih.ring[ring_index]) & 0xff;
+		src_data = le32_to_cpu(rdev->ih.ring[ring_index + 1]) & 0xfffffff;
 
 		switch (src_id) {
 		case 1: /* D1 vblank/vline */
 			switch (src_data) {
 			case 0: /* D1 vblank */
-				if (disp_int & LB_D1_VBLANK_INTERRUPT) {
-					drm_handle_vblank(rdev->ddev, 0);
-					rdev->pm.vblank_sync = true;
-					wake_up(&rdev->irq.vblank_queue);
-					disp_int &= ~LB_D1_VBLANK_INTERRUPT;
+				if (rdev->irq.stat_regs.evergreen.disp_int & LB_D1_VBLANK_INTERRUPT) {
+					if (rdev->irq.crtc_vblank_int[0]) {
+						drm_handle_vblank(rdev->ddev, 0);
+						rdev->pm.vblank_sync = true;
+						wake_up(&rdev->irq.vblank_queue);
+					}
+					if (rdev->irq.pflip[0])
+						radeon_crtc_handle_flip(rdev, 0);
+					rdev->irq.stat_regs.evergreen.disp_int &= ~LB_D1_VBLANK_INTERRUPT;
 					DRM_DEBUG("IH: D1 vblank\n");
 				}
 				break;
 			case 1: /* D1 vline */
-				if (disp_int & LB_D1_VLINE_INTERRUPT) {
-					disp_int &= ~LB_D1_VLINE_INTERRUPT;
+				if (rdev->irq.stat_regs.evergreen.disp_int & LB_D1_VLINE_INTERRUPT) {
+					rdev->irq.stat_regs.evergreen.disp_int &= ~LB_D1_VLINE_INTERRUPT;
 					DRM_DEBUG("IH: D1 vline\n");
 				}
 				break;
@@ -2331,17 +2671,21 @@ restart_ih:
 		case 2: /* D2 vblank/vline */
 			switch (src_data) {
 			case 0: /* D2 vblank */
-				if (disp_int_cont & LB_D2_VBLANK_INTERRUPT) {
-					drm_handle_vblank(rdev->ddev, 1);
-					rdev->pm.vblank_sync = true;
-					wake_up(&rdev->irq.vblank_queue);
-					disp_int_cont &= ~LB_D2_VBLANK_INTERRUPT;
+				if (rdev->irq.stat_regs.evergreen.disp_int_cont & LB_D2_VBLANK_INTERRUPT) {
+					if (rdev->irq.crtc_vblank_int[1]) {
+						drm_handle_vblank(rdev->ddev, 1);
+						rdev->pm.vblank_sync = true;
+						wake_up(&rdev->irq.vblank_queue);
+					}
+					if (rdev->irq.pflip[1])
+						radeon_crtc_handle_flip(rdev, 1);
+					rdev->irq.stat_regs.evergreen.disp_int_cont &= ~LB_D2_VBLANK_INTERRUPT;
 					DRM_DEBUG("IH: D2 vblank\n");
 				}
 				break;
 			case 1: /* D2 vline */
-				if (disp_int_cont & LB_D2_VLINE_INTERRUPT) {
-					disp_int_cont &= ~LB_D2_VLINE_INTERRUPT;
+				if (rdev->irq.stat_regs.evergreen.disp_int_cont & LB_D2_VLINE_INTERRUPT) {
+					rdev->irq.stat_regs.evergreen.disp_int_cont &= ~LB_D2_VLINE_INTERRUPT;
 					DRM_DEBUG("IH: D2 vline\n");
 				}
 				break;
@@ -2353,17 +2697,21 @@ restart_ih:
 		case 3: /* D3 vblank/vline */
 			switch (src_data) {
 			case 0: /* D3 vblank */
-				if (disp_int_cont2 & LB_D3_VBLANK_INTERRUPT) {
-					drm_handle_vblank(rdev->ddev, 2);
-					rdev->pm.vblank_sync = true;
-					wake_up(&rdev->irq.vblank_queue);
-					disp_int_cont2 &= ~LB_D3_VBLANK_INTERRUPT;
+				if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & LB_D3_VBLANK_INTERRUPT) {
+					if (rdev->irq.crtc_vblank_int[2]) {
+						drm_handle_vblank(rdev->ddev, 2);
+						rdev->pm.vblank_sync = true;
+						wake_up(&rdev->irq.vblank_queue);
+					}
+					if (rdev->irq.pflip[2])
+						radeon_crtc_handle_flip(rdev, 2);
+					rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~LB_D3_VBLANK_INTERRUPT;
 					DRM_DEBUG("IH: D3 vblank\n");
 				}
 				break;
 			case 1: /* D3 vline */
-				if (disp_int_cont2 & LB_D3_VLINE_INTERRUPT) {
-					disp_int_cont2 &= ~LB_D3_VLINE_INTERRUPT;
+				if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & LB_D3_VLINE_INTERRUPT) {
+					rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~LB_D3_VLINE_INTERRUPT;
 					DRM_DEBUG("IH: D3 vline\n");
 				}
 				break;
@@ -2375,17 +2723,21 @@ restart_ih:
 		case 4: /* D4 vblank/vline */
 			switch (src_data) {
 			case 0: /* D4 vblank */
-				if (disp_int_cont3 & LB_D4_VBLANK_INTERRUPT) {
-					drm_handle_vblank(rdev->ddev, 3);
-					rdev->pm.vblank_sync = true;
-					wake_up(&rdev->irq.vblank_queue);
-					disp_int_cont3 &= ~LB_D4_VBLANK_INTERRUPT;
+				if (rdev->irq.stat_regs.evergreen.disp_int_cont3 & LB_D4_VBLANK_INTERRUPT) {
+					if (rdev->irq.crtc_vblank_int[3]) {
+						drm_handle_vblank(rdev->ddev, 3);
+						rdev->pm.vblank_sync = true;
+						wake_up(&rdev->irq.vblank_queue);
+					}
+					if (rdev->irq.pflip[3])
+						radeon_crtc_handle_flip(rdev, 3);
+					rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~LB_D4_VBLANK_INTERRUPT;
 					DRM_DEBUG("IH: D4 vblank\n");
 				}
 				break;
 			case 1: /* D4 vline */
-				if (disp_int_cont3 & LB_D4_VLINE_INTERRUPT) {
-					disp_int_cont3 &= ~LB_D4_VLINE_INTERRUPT;
+				if (rdev->irq.stat_regs.evergreen.disp_int_cont3 & LB_D4_VLINE_INTERRUPT) {
+					rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~LB_D4_VLINE_INTERRUPT;
 					DRM_DEBUG("IH: D4 vline\n");
 				}
 				break;
@@ -2397,17 +2749,21 @@ restart_ih:
 		case 5: /* D5 vblank/vline */
 			switch (src_data) {
 			case 0: /* D5 vblank */
-				if (disp_int_cont4 & LB_D5_VBLANK_INTERRUPT) {
-					drm_handle_vblank(rdev->ddev, 4);
-					rdev->pm.vblank_sync = true;
-					wake_up(&rdev->irq.vblank_queue);
-					disp_int_cont4 &= ~LB_D5_VBLANK_INTERRUPT;
+				if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & LB_D5_VBLANK_INTERRUPT) {
+					if (rdev->irq.crtc_vblank_int[4]) {
+						drm_handle_vblank(rdev->ddev, 4);
+						rdev->pm.vblank_sync = true;
+						wake_up(&rdev->irq.vblank_queue);
+					}
+					if (rdev->irq.pflip[4])
+						radeon_crtc_handle_flip(rdev, 4);
+					rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~LB_D5_VBLANK_INTERRUPT;
 					DRM_DEBUG("IH: D5 vblank\n");
 				}
 				break;
 			case 1: /* D5 vline */
-				if (disp_int_cont4 & LB_D5_VLINE_INTERRUPT) {
-					disp_int_cont4 &= ~LB_D5_VLINE_INTERRUPT;
+				if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & LB_D5_VLINE_INTERRUPT) {
+					rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~LB_D5_VLINE_INTERRUPT;
 					DRM_DEBUG("IH: D5 vline\n");
 				}
 				break;
@@ -2419,17 +2775,21 @@ restart_ih:
 		case 6: /* D6 vblank/vline */
 			switch (src_data) {
 			case 0: /* D6 vblank */
-				if (disp_int_cont5 & LB_D6_VBLANK_INTERRUPT) {
-					drm_handle_vblank(rdev->ddev, 5);
-					rdev->pm.vblank_sync = true;
-					wake_up(&rdev->irq.vblank_queue);
-					disp_int_cont5 &= ~LB_D6_VBLANK_INTERRUPT;
+				if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & LB_D6_VBLANK_INTERRUPT) {
+					if (rdev->irq.crtc_vblank_int[5]) {
+						drm_handle_vblank(rdev->ddev, 5);
+						rdev->pm.vblank_sync = true;
+						wake_up(&rdev->irq.vblank_queue);
+					}
+					if (rdev->irq.pflip[5])
+						radeon_crtc_handle_flip(rdev, 5);
+					rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~LB_D6_VBLANK_INTERRUPT;
 					DRM_DEBUG("IH: D6 vblank\n");
 				}
 				break;
 			case 1: /* D6 vline */
-				if (disp_int_cont5 & LB_D6_VLINE_INTERRUPT) {
-					disp_int_cont5 &= ~LB_D6_VLINE_INTERRUPT;
+				if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & LB_D6_VLINE_INTERRUPT) {
+					rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~LB_D6_VLINE_INTERRUPT;
 					DRM_DEBUG("IH: D6 vline\n");
 				}
 				break;
@@ -2441,43 +2801,43 @@ restart_ih:
 		case 42: /* HPD hotplug */
 			switch (src_data) {
 			case 0:
-				if (disp_int & DC_HPD1_INTERRUPT) {
-					disp_int &= ~DC_HPD1_INTERRUPT;
+				if (rdev->irq.stat_regs.evergreen.disp_int & DC_HPD1_INTERRUPT) {
+					rdev->irq.stat_regs.evergreen.disp_int &= ~DC_HPD1_INTERRUPT;
 					queue_hotplug = true;
 					DRM_DEBUG("IH: HPD1\n");
 				}
 				break;
 			case 1:
-				if (disp_int_cont & DC_HPD2_INTERRUPT) {
-					disp_int_cont &= ~DC_HPD2_INTERRUPT;
+				if (rdev->irq.stat_regs.evergreen.disp_int_cont & DC_HPD2_INTERRUPT) {
+					rdev->irq.stat_regs.evergreen.disp_int_cont &= ~DC_HPD2_INTERRUPT;
 					queue_hotplug = true;
 					DRM_DEBUG("IH: HPD2\n");
 				}
 				break;
 			case 2:
-				if (disp_int_cont2 & DC_HPD3_INTERRUPT) {
-					disp_int_cont2 &= ~DC_HPD3_INTERRUPT;
+				if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & DC_HPD3_INTERRUPT) {
+					rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~DC_HPD3_INTERRUPT;
 					queue_hotplug = true;
 					DRM_DEBUG("IH: HPD3\n");
 				}
 				break;
 			case 3:
-				if (disp_int_cont3 & DC_HPD4_INTERRUPT) {
-					disp_int_cont3 &= ~DC_HPD4_INTERRUPT;
+				if (rdev->irq.stat_regs.evergreen.disp_int_cont3 & DC_HPD4_INTERRUPT) {
+					rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~DC_HPD4_INTERRUPT;
 					queue_hotplug = true;
 					DRM_DEBUG("IH: HPD4\n");
 				}
 				break;
 			case 4:
-				if (disp_int_cont4 & DC_HPD5_INTERRUPT) {
-					disp_int_cont4 &= ~DC_HPD5_INTERRUPT;
+				if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & DC_HPD5_INTERRUPT) {
+					rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~DC_HPD5_INTERRUPT;
 					queue_hotplug = true;
 					DRM_DEBUG("IH: HPD5\n");
 				}
 				break;
 			case 5:
-				if (disp_int_cont5 & DC_HPD6_INTERRUPT) {
-					disp_int_cont5 &= ~DC_HPD6_INTERRUPT;
+				if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & DC_HPD6_INTERRUPT) {
+					rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~DC_HPD6_INTERRUPT;
 					queue_hotplug = true;
 					DRM_DEBUG("IH: HPD6\n");
 				}
@@ -2516,7 +2876,7 @@ restart_ih:
 	if (wptr != rdev->ih.wptr)
 		goto restart_ih;
 	if (queue_hotplug)
-		queue_work(rdev->wq, &rdev->hotplug_work);
+		schedule_work(&rdev->hotplug_work);
 	rdev->ih.rptr = rptr;
 	WREG32(IH_RB_RPTR, rdev->ih.rptr);
 	spin_unlock_irqrestore(&rdev->ih.lock, flags);
@@ -2527,12 +2887,31 @@ static int evergreen_startup(struct rade
 {
 	int r;
 
-	if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw) {
-		r = r600_init_microcode(rdev);
+	/* enable pcie gen2 link */
+	if (!ASIC_IS_DCE5(rdev))
+		evergreen_pcie_gen2_enable(rdev);
+
+	if (ASIC_IS_DCE5(rdev)) {
+		if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw || !rdev->mc_fw) {
+			r = ni_init_microcode(rdev);
+			if (r) {
+				DRM_ERROR("Failed to load firmware!\n");
+				return r;
+			}
+		}
+		r = btc_mc_load_microcode(rdev);
 		if (r) {
-			DRM_ERROR("Failed to load firmware!\n");
+			DRM_ERROR("Failed to load MC firmware!\n");
 			return r;
 		}
+	} else {
+		if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw) {
+			r = r600_init_microcode(rdev);
+			if (r) {
+				DRM_ERROR("Failed to load firmware!\n");
+				return r;
+			}
+		}
 	}
 
 	evergreen_mc_program(rdev);
@@ -2551,6 +2930,11 @@ static int evergreen_startup(struct rade
 		rdev->asic->copy = NULL;
 		dev_warn(rdev->dev, "failed blitter (%d) falling back to memcpy\n", r);
 	}
+	/* XXX: ontario has problems blitting to gart at the moment */
+	if (rdev->family == CHIP_PALM) {
+		rdev->asic->copy = NULL;
+		radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size);
+	}
 
 	/* allocate wb buffer */
 	r = radeon_wb_init(rdev);
@@ -2653,27 +3037,6 @@ int evergreen_copy_blit(struct radeon_de
 	return 0;
 }
 
-static bool evergreen_card_posted(struct radeon_device *rdev)
-{
-	u32 reg;
-
-	/* first check CRTCs */
-	reg = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET) |
-		RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET) |
-		RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET) |
-		RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET) |
-		RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET) |
-		RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET);
-	if (reg & EVERGREEN_CRTC_MASTER_EN)
-		return true;
-
-	/* then check MEM_SIZE, in case the crtcs are off */
-	if (RREG32(CONFIG_MEMSIZE))
-		return true;
-
-	return false;
-}
-
 /* Plan is to move initialization in that function and use
  * helper function so that radeon_device_init pretty much
  * do nothing more than calling asic specific function. This
@@ -2710,7 +3073,7 @@ int evergreen_init(struct radeon_device
 	if (radeon_asic_reset(rdev))
 		dev_warn(rdev->dev, "GPU reset failed !\n");
 	/* Post card if necessary */
-	if (!evergreen_card_posted(rdev)) {
+	if (!radeon_card_posted(rdev)) {
 		if (!rdev->bios) {
 			dev_err(rdev->dev, "Card not posted and no BIOS - ignoring\n");
 			return -EINVAL;
@@ -2800,3 +3163,55 @@ void evergreen_fini(struct radeon_device
 	rdev->bios = NULL;
 	radeon_dummy_page_fini(rdev);
 }
+
+static void evergreen_pcie_gen2_enable(struct radeon_device *rdev)
+{
+	u32 link_width_cntl, speed_cntl;
+
+	if (radeon_pcie_gen2 == 0)
+		return;
+
+	if (rdev->flags & RADEON_IS_IGP)
+		return;
+
+	if (!(rdev->flags & RADEON_IS_PCIE))
+		return;
+
+	/* x2 cards have a special sequence */
+	if (ASIC_IS_X2(rdev))
+		return;
+
+	speed_cntl = RREG32_PCIE_P(PCIE_LC_SPEED_CNTL);
+	if ((speed_cntl & LC_OTHER_SIDE_EVER_SENT_GEN2) ||
+	    (speed_cntl & LC_OTHER_SIDE_SUPPORTS_GEN2)) {
+
+		link_width_cntl = RREG32_PCIE_P(PCIE_LC_LINK_WIDTH_CNTL);
+		link_width_cntl &= ~LC_UPCONFIGURE_DIS;
+		WREG32_PCIE_P(PCIE_LC_LINK_WIDTH_CNTL, link_width_cntl);
+
+		speed_cntl = RREG32_PCIE_P(PCIE_LC_SPEED_CNTL);
+		speed_cntl &= ~LC_TARGET_LINK_SPEED_OVERRIDE_EN;
+		WREG32_PCIE_P(PCIE_LC_SPEED_CNTL, speed_cntl);
+
+		speed_cntl = RREG32_PCIE_P(PCIE_LC_SPEED_CNTL);
+		speed_cntl |= LC_CLR_FAILED_SPD_CHANGE_CNT;
+		WREG32_PCIE_P(PCIE_LC_SPEED_CNTL, speed_cntl);
+
+		speed_cntl = RREG32_PCIE_P(PCIE_LC_SPEED_CNTL);
+		speed_cntl &= ~LC_CLR_FAILED_SPD_CHANGE_CNT;
+		WREG32_PCIE_P(PCIE_LC_SPEED_CNTL, speed_cntl);
+
+		speed_cntl = RREG32_PCIE_P(PCIE_LC_SPEED_CNTL);
+		speed_cntl |= LC_GEN2_EN_STRAP;
+		WREG32_PCIE_P(PCIE_LC_SPEED_CNTL, speed_cntl);
+
+	} else {
+		link_width_cntl = RREG32_PCIE_P(PCIE_LC_LINK_WIDTH_CNTL);
+		/* XXX: only disable it if gen1 bridge vendor == 0x111d or 0x1106 */
+		if (1)
+			link_width_cntl |= LC_UPCONFIGURE_DIS;
+		else
+			link_width_cntl &= ~LC_UPCONFIGURE_DIS;
+		WREG32_PCIE_P(PCIE_LC_LINK_WIDTH_CNTL, link_width_cntl);
+	}
+}
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/evergreend.h linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/evergreend.h
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/evergreend.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/evergreend.h	2011-03-14 21:20:32.000000000 -0400
@@ -98,6 +98,7 @@
 #define		BUF_SWAP_32BIT					(2 << 16)
 #define	CP_RB_RPTR					0x8700
 #define	CP_RB_RPTR_ADDR					0xC10C
+#define		RB_RPTR_SWAP(x)					((x) << 0)
 #define	CP_RB_RPTR_ADDR_HI				0xC110
 #define	CP_RB_RPTR_WR					0xC108
 #define	CP_RB_WPTR					0xC114
@@ -164,11 +165,13 @@
 #define		SE_SC_BUSY					(1 << 29)
 #define		SE_DB_BUSY					(1 << 30)
 #define		SE_CB_BUSY					(1 << 31)
-
+/* evergreen */
 #define	CG_MULT_THERMAL_STATUS				0x740
 #define		ASIC_T(x)			        ((x) << 16)
 #define		ASIC_T_MASK			        0x7FF0000
 #define		ASIC_T_SHIFT			        16
+/* APU */
+#define	CG_THERMAL_STATUS			        0x678
 
 #define	HDP_HOST_PATH_CNTL				0x2C00
 #define	HDP_NONSURFACE_BASE				0x2C04
@@ -181,6 +184,7 @@
 #define MC_SHARED_CHMAP						0x2004
 #define		NOOFCHAN_SHIFT					12
 #define		NOOFCHAN_MASK					0x00003000
+#define MC_SHARED_CHREMAP					0x2008
 
 #define	MC_ARB_RAMCFG					0x2760
 #define		NOOFBANK_SHIFT					0
@@ -200,6 +204,7 @@
 #define	MC_VM_AGP_BOT					0x202C
 #define	MC_VM_AGP_BASE					0x2030
 #define	MC_VM_FB_LOCATION				0x2024
+#define	MC_FUS_VM_FB_OFFSET				0x2898
 #define	MC_VM_MB_L1_TLB0_CNTL				0x2234
 #define	MC_VM_MB_L1_TLB1_CNTL				0x2238
 #define	MC_VM_MB_L1_TLB2_CNTL				0x223C
@@ -236,6 +241,7 @@
 #define		FORCE_EOV_MAX_CLK_CNT(x)			((x) << 0)
 #define		FORCE_EOV_MAX_REZ_CNT(x)			((x) << 16)
 #define PA_SC_LINE_STIPPLE				0x28A0C
+#define	PA_SU_LINE_STIPPLE_VALUE			0x8A60
 #define	PA_SC_LINE_STIPPLE_STATE			0x8B10
 
 #define	SCRATCH_REG0					0x8500
@@ -349,6 +355,9 @@
 #define		SYNC_WALKER					(1 << 25)
 #define		SYNC_ALIGNER					(1 << 26)
 
+#define	TCP_CHAN_STEER_LO				0x960c
+#define	TCP_CHAN_STEER_HI				0x9610
+
 #define	VGT_CACHE_INVALIDATION				0x88C4
 #define		CACHE_INVALIDATION(x)				((x) << 0)
 #define			VC_ONLY						0
@@ -574,6 +583,44 @@
 #       define DC_HPDx_RX_INT_TIMER(x)                    ((x) << 16)
 #       define DC_HPDx_EN                                 (1 << 28)
 
+/* PCIE link stuff */
+#define PCIE_LC_TRAINING_CNTL                             0xa1 /* PCIE_P */
+#define PCIE_LC_LINK_WIDTH_CNTL                           0xa2 /* PCIE_P */
+#       define LC_LINK_WIDTH_SHIFT                        0
+#       define LC_LINK_WIDTH_MASK                         0x7
+#       define LC_LINK_WIDTH_X0                           0
+#       define LC_LINK_WIDTH_X1                           1
+#       define LC_LINK_WIDTH_X2                           2
+#       define LC_LINK_WIDTH_X4                           3
+#       define LC_LINK_WIDTH_X8                           4
+#       define LC_LINK_WIDTH_X16                          6
+#       define LC_LINK_WIDTH_RD_SHIFT                     4
+#       define LC_LINK_WIDTH_RD_MASK                      0x70
+#       define LC_RECONFIG_ARC_MISSING_ESCAPE             (1 << 7)
+#       define LC_RECONFIG_NOW                            (1 << 8)
+#       define LC_RENEGOTIATION_SUPPORT                   (1 << 9)
+#       define LC_RENEGOTIATE_EN                          (1 << 10)
+#       define LC_SHORT_RECONFIG_EN                       (1 << 11)
+#       define LC_UPCONFIGURE_SUPPORT                     (1 << 12)
+#       define LC_UPCONFIGURE_DIS                         (1 << 13)
+#define PCIE_LC_SPEED_CNTL                                0xa4 /* PCIE_P */
+#       define LC_GEN2_EN_STRAP                           (1 << 0)
+#       define LC_TARGET_LINK_SPEED_OVERRIDE_EN           (1 << 1)
+#       define LC_FORCE_EN_HW_SPEED_CHANGE                (1 << 5)
+#       define LC_FORCE_DIS_HW_SPEED_CHANGE               (1 << 6)
+#       define LC_SPEED_CHANGE_ATTEMPTS_ALLOWED_MASK      (0x3 << 8)
+#       define LC_SPEED_CHANGE_ATTEMPTS_ALLOWED_SHIFT     3
+#       define LC_CURRENT_DATA_RATE                       (1 << 11)
+#       define LC_VOLTAGE_TIMER_SEL_MASK                  (0xf << 14)
+#       define LC_CLR_FAILED_SPD_CHANGE_CNT               (1 << 21)
+#       define LC_OTHER_SIDE_EVER_SENT_GEN2               (1 << 23)
+#       define LC_OTHER_SIDE_SUPPORTS_GEN2                (1 << 24)
+#define MM_CFGREGS_CNTL                                   0x544c
+#       define MM_WR_TO_CFG_EN                            (1 << 3)
+#define LINK_CNTL2                                        0x88 /* F0 */
+#       define TARGET_LINK_SPEED_MASK                     (0xf << 0)
+#       define SELECTABLE_DEEMPHASIS                      (1 << 6)
+
 /*
  * PM4
  */
@@ -603,10 +650,11 @@
 #define	PACKET3_NOP					0x10
 #define	PACKET3_SET_BASE				0x11
 #define	PACKET3_CLEAR_STATE				0x12
-#define	PACKET3_INDIRECT_BUFFER_SIZE			0x13
+#define	PACKET3_INDEX_BUFFER_SIZE			0x13
 #define	PACKET3_DISPATCH_DIRECT				0x15
 #define	PACKET3_DISPATCH_INDIRECT			0x16
 #define	PACKET3_INDIRECT_BUFFER_END			0x17
+#define	PACKET3_MODE_CONTROL				0x18
 #define	PACKET3_SET_PREDICATION				0x20
 #define	PACKET3_REG_RMW					0x21
 #define	PACKET3_COND_EXEC				0x22
@@ -644,14 +692,14 @@
 #              define PACKET3_CB8_DEST_BASE_ENA    (1 << 15)
 #              define PACKET3_CB9_DEST_BASE_ENA    (1 << 16)
 #              define PACKET3_CB10_DEST_BASE_ENA   (1 << 17)
-#              define PACKET3_CB11_DEST_BASE_ENA   (1 << 17)
+#              define PACKET3_CB11_DEST_BASE_ENA   (1 << 18)
 #              define PACKET3_FULL_CACHE_ENA       (1 << 20)
 #              define PACKET3_TC_ACTION_ENA        (1 << 23)
 #              define PACKET3_VC_ACTION_ENA        (1 << 24)
 #              define PACKET3_CB_ACTION_ENA        (1 << 25)
 #              define PACKET3_DB_ACTION_ENA        (1 << 26)
 #              define PACKET3_SH_ACTION_ENA        (1 << 27)
-#              define PACKET3_SMX_ACTION_ENA       (1 << 28)
+#              define PACKET3_SX_ACTION_ENA        (1 << 28)
 #define	PACKET3_ME_INITIALIZE				0x44
 #define		PACKET3_ME_INITIALIZE_DEVICE_ID(x) ((x) << 16)
 #define	PACKET3_COND_WRITE				0x45
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/evergreen_reg.h linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/evergreen_reg.h
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/evergreen_reg.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/evergreen_reg.h	2011-03-14 21:20:32.000000000 -0400
@@ -105,6 +105,11 @@
 #define EVERGREEN_GRPH_Y_START                          0x6830
 #define EVERGREEN_GRPH_X_END                            0x6834
 #define EVERGREEN_GRPH_Y_END                            0x6838
+#define EVERGREEN_GRPH_UPDATE                           0x6844
+#       define EVERGREEN_GRPH_SURFACE_UPDATE_PENDING    (1 << 2)
+#       define EVERGREEN_GRPH_UPDATE_LOCK               (1 << 16)
+#define EVERGREEN_GRPH_FLIP_CONTROL                     0x6848
+#       define EVERGREEN_GRPH_SURFACE_UPDATE_H_RETRACE_EN (1 << 0)
 
 /* CUR blocks at 0x6998, 0x7598, 0x10198, 0x10d98, 0x11998, 0x12598 */
 #define EVERGREEN_CUR_CONTROL                           0x6998
@@ -178,6 +183,7 @@
 #       define EVERGREEN_CRTC_DISP_READ_REQUEST_DISABLE (1 << 24)
 #define EVERGREEN_CRTC_STATUS                           0x6e8c
 #define EVERGREEN_CRTC_STATUS_POSITION                  0x6e90
+#define EVERGREEN_MASTER_UPDATE_MODE                    0x6ef8
 #define EVERGREEN_CRTC_UPDATE_LOCK                      0x6ed4
 
 #define EVERGREEN_DC_GPIO_HPD_MASK                      0x64b0
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/Makefile linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/Makefile
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -65,10 +65,13 @@ radeon-y += radeon_device.o radeon_asic.
 	rs400.o rs600.o rs690.o rv515.o r520.o r600.o rv770.o radeon_test.o \
 	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
+	evergreen.o evergreen_cs.o evergreen_blit_shaders.o evergreen_blit_kms.o \
+	radeon_trace_points.o ni.o
 
 radeon-$(CONFIG_COMPAT) += radeon_ioc32.o
 radeon-$(CONFIG_VGA_SWITCHEROO) += radeon_atpx_handler.o
 radeon-$(CONFIG_ACPI) += radeon_acpi.o
 
 obj-$(CONFIG_DRM_RADEON)+= radeon.o
+
+CFLAGS_radeon_trace_points.o := -I$(src)
\ No newline at end of file
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/mkregtable.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/mkregtable.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/mkregtable.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/mkregtable.c	2011-03-14 21:20:32.000000000 -0400
@@ -673,8 +673,10 @@ static int parser_auth(struct table *t,
 	last_reg = strtol(last_reg_s, NULL, 16);
 
 	do {
-		if (fgets(buf, 1024, file) == NULL)
+		if (fgets(buf, 1024, file) == NULL) {
+			fclose(file);
 			return -1;
+		}
 		len = strlen(buf);
 		if (ftell(file) == end)
 			done = 1;
@@ -685,6 +687,7 @@ static int parser_auth(struct table *t,
 				fprintf(stderr,
 					"Error matching regular expression %d in %s\n",
 					r, filename);
+				fclose(file);
 				return -1;
 			} else {
 				buf[match[0].rm_eo] = 0;
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/ni.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/ni.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/ni.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/ni.c	2013-05-03 01:54:09.000000000 -0400
@@ -0,0 +1,307 @@
+/*
+ * Copyright 2010 Advanced Micro Devices, 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: Alex Deucher
+ */
+#include <linux/firmware.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include "drmP.h"
+#include "radeon.h"
+#include "radeon_asic.h"
+#include "radeon_drm.h"
+#include "nid.h"
+#include "atom.h"
+#include "ni_reg.h"
+
+#define EVERGREEN_PFP_UCODE_SIZE 1120
+#define EVERGREEN_PM4_UCODE_SIZE 1376
+#define EVERGREEN_RLC_UCODE_SIZE 768
+#define BTC_MC_UCODE_SIZE 6024
+
+/* Firmware Names */
+/*(DEBLOBBED)*/
+
+#define BTC_IO_MC_REGS_SIZE 29
+
+static const u32 barts_io_mc_regs[BTC_IO_MC_REGS_SIZE][2] = {
+	{0x00000077, 0xff010100},
+	{0x00000078, 0x00000000},
+	{0x00000079, 0x00001434},
+	{0x0000007a, 0xcc08ec08},
+	{0x0000007b, 0x00040000},
+	{0x0000007c, 0x000080c0},
+	{0x0000007d, 0x09000000},
+	{0x0000007e, 0x00210404},
+	{0x00000081, 0x08a8e800},
+	{0x00000082, 0x00030444},
+	{0x00000083, 0x00000000},
+	{0x00000085, 0x00000001},
+	{0x00000086, 0x00000002},
+	{0x00000087, 0x48490000},
+	{0x00000088, 0x20244647},
+	{0x00000089, 0x00000005},
+	{0x0000008b, 0x66030000},
+	{0x0000008c, 0x00006603},
+	{0x0000008d, 0x00000100},
+	{0x0000008f, 0x00001c0a},
+	{0x00000090, 0xff000001},
+	{0x00000094, 0x00101101},
+	{0x00000095, 0x00000fff},
+	{0x00000096, 0x00116fff},
+	{0x00000097, 0x60010000},
+	{0x00000098, 0x10010000},
+	{0x00000099, 0x00006000},
+	{0x0000009a, 0x00001000},
+	{0x0000009f, 0x00946a00}
+};
+
+static const u32 turks_io_mc_regs[BTC_IO_MC_REGS_SIZE][2] = {
+	{0x00000077, 0xff010100},
+	{0x00000078, 0x00000000},
+	{0x00000079, 0x00001434},
+	{0x0000007a, 0xcc08ec08},
+	{0x0000007b, 0x00040000},
+	{0x0000007c, 0x000080c0},
+	{0x0000007d, 0x09000000},
+	{0x0000007e, 0x00210404},
+	{0x00000081, 0x08a8e800},
+	{0x00000082, 0x00030444},
+	{0x00000083, 0x00000000},
+	{0x00000085, 0x00000001},
+	{0x00000086, 0x00000002},
+	{0x00000087, 0x48490000},
+	{0x00000088, 0x20244647},
+	{0x00000089, 0x00000005},
+	{0x0000008b, 0x66030000},
+	{0x0000008c, 0x00006603},
+	{0x0000008d, 0x00000100},
+	{0x0000008f, 0x00001c0a},
+	{0x00000090, 0xff000001},
+	{0x00000094, 0x00101101},
+	{0x00000095, 0x00000fff},
+	{0x00000096, 0x00116fff},
+	{0x00000097, 0x60010000},
+	{0x00000098, 0x10010000},
+	{0x00000099, 0x00006000},
+	{0x0000009a, 0x00001000},
+	{0x0000009f, 0x00936a00}
+};
+
+static const u32 caicos_io_mc_regs[BTC_IO_MC_REGS_SIZE][2] = {
+	{0x00000077, 0xff010100},
+	{0x00000078, 0x00000000},
+	{0x00000079, 0x00001434},
+	{0x0000007a, 0xcc08ec08},
+	{0x0000007b, 0x00040000},
+	{0x0000007c, 0x000080c0},
+	{0x0000007d, 0x09000000},
+	{0x0000007e, 0x00210404},
+	{0x00000081, 0x08a8e800},
+	{0x00000082, 0x00030444},
+	{0x00000083, 0x00000000},
+	{0x00000085, 0x00000001},
+	{0x00000086, 0x00000002},
+	{0x00000087, 0x48490000},
+	{0x00000088, 0x20244647},
+	{0x00000089, 0x00000005},
+	{0x0000008b, 0x66030000},
+	{0x0000008c, 0x00006603},
+	{0x0000008d, 0x00000100},
+	{0x0000008f, 0x00001c0a},
+	{0x00000090, 0xff000001},
+	{0x00000094, 0x00101101},
+	{0x00000095, 0x00000fff},
+	{0x00000096, 0x00116fff},
+	{0x00000097, 0x60010000},
+	{0x00000098, 0x10010000},
+	{0x00000099, 0x00006000},
+	{0x0000009a, 0x00001000},
+	{0x0000009f, 0x00916a00}
+};
+
+int btc_mc_load_microcode(struct radeon_device *rdev)
+{
+	const __be32 *fw_data;
+	u32 mem_type, running, blackout = 0;
+	u32 *io_mc_regs;
+	int i;
+
+	if (!rdev->mc_fw)
+		return -EINVAL;
+
+	switch (rdev->family) {
+	case CHIP_BARTS:
+		io_mc_regs = (u32 *)&barts_io_mc_regs;
+		break;
+	case CHIP_TURKS:
+		io_mc_regs = (u32 *)&turks_io_mc_regs;
+		break;
+	case CHIP_CAICOS:
+	default:
+		io_mc_regs = (u32 *)&caicos_io_mc_regs;
+		break;
+	}
+
+	mem_type = (RREG32(MC_SEQ_MISC0) & MC_SEQ_MISC0_GDDR5_MASK) >> MC_SEQ_MISC0_GDDR5_SHIFT;
+	running = RREG32(MC_SEQ_SUP_CNTL) & RUN_MASK;
+
+	if ((mem_type == MC_SEQ_MISC0_GDDR5_VALUE) && (running == 0)) {
+		if (running) {
+			blackout = RREG32(MC_SHARED_BLACKOUT_CNTL);
+			WREG32(MC_SHARED_BLACKOUT_CNTL, 1);
+		}
+
+		/* reset the engine and set to writable */
+		WREG32(MC_SEQ_SUP_CNTL, 0x00000008);
+		WREG32(MC_SEQ_SUP_CNTL, 0x00000010);
+
+		/* load mc io regs */
+		for (i = 0; i < BTC_IO_MC_REGS_SIZE; i++) {
+			WREG32(MC_SEQ_IO_DEBUG_INDEX, io_mc_regs[(i << 1)]);
+			WREG32(MC_SEQ_IO_DEBUG_DATA, io_mc_regs[(i << 1) + 1]);
+		}
+		/* load the MC ucode */
+		fw_data = (const __be32 *)rdev->mc_fw->data;
+		for (i = 0; i < BTC_MC_UCODE_SIZE; i++)
+			WREG32(MC_SEQ_SUP_PGM, be32_to_cpup(fw_data++));
+
+		/* put the engine back into the active state */
+		WREG32(MC_SEQ_SUP_CNTL, 0x00000008);
+		WREG32(MC_SEQ_SUP_CNTL, 0x00000004);
+		WREG32(MC_SEQ_SUP_CNTL, 0x00000001);
+
+		/* wait for training to complete */
+		while (!(RREG32(MC_IO_PAD_CNTL_D0) & MEM_FALL_OUT_CMD))
+			udelay(10);
+
+		if (running)
+			WREG32(MC_SHARED_BLACKOUT_CNTL, blackout);
+	}
+
+	return 0;
+}
+
+int ni_init_microcode(struct radeon_device *rdev)
+{
+	struct platform_device *pdev;
+	const char *chip_name;
+	const char *rlc_chip_name;
+	size_t pfp_req_size, me_req_size, rlc_req_size, mc_req_size;
+	char fw_name[30];
+	int err;
+
+	DRM_DEBUG("\n");
+
+	pdev = platform_device_register_simple("radeon_cp", 0, NULL, 0);
+	err = IS_ERR(pdev);
+	if (err) {
+		printk(KERN_ERR "radeon_cp: Failed to register firmware\n");
+		return -EINVAL;
+	}
+
+	switch (rdev->family) {
+	case CHIP_BARTS:
+		chip_name = "BARTS";
+		rlc_chip_name = "BTC";
+		break;
+	case CHIP_TURKS:
+		chip_name = "TURKS";
+		rlc_chip_name = "BTC";
+		break;
+	case CHIP_CAICOS:
+		chip_name = "CAICOS";
+		rlc_chip_name = "BTC";
+		break;
+	default: BUG();
+	}
+
+	pfp_req_size = EVERGREEN_PFP_UCODE_SIZE * 4;
+	me_req_size = EVERGREEN_PM4_UCODE_SIZE * 4;
+	rlc_req_size = EVERGREEN_RLC_UCODE_SIZE * 4;
+	mc_req_size = BTC_MC_UCODE_SIZE * 4;
+
+	DRM_INFO("Loading %s Microcode\n", chip_name);
+
+	snprintf(fw_name, sizeof(fw_name), "/*(DEBLOBBED)*/", chip_name);
+	err = reject_firmware(&rdev->pfp_fw, fw_name, &pdev->dev);
+	if (err)
+		goto out;
+	if (rdev->pfp_fw->size != pfp_req_size) {
+		printk(KERN_ERR
+		       "ni_cp: Bogus length %zu in firmware \"%s\"\n",
+		       rdev->pfp_fw->size, fw_name);
+		err = -EINVAL;
+		goto out;
+	}
+
+	snprintf(fw_name, sizeof(fw_name), "/*(DEBLOBBED)*/", chip_name);
+	err = reject_firmware(&rdev->me_fw, fw_name, &pdev->dev);
+	if (err)
+		goto out;
+	if (rdev->me_fw->size != me_req_size) {
+		printk(KERN_ERR
+		       "ni_cp: Bogus length %zu in firmware \"%s\"\n",
+		       rdev->me_fw->size, fw_name);
+		err = -EINVAL;
+	}
+
+	snprintf(fw_name, sizeof(fw_name), "/*(DEBLOBBED)*/", rlc_chip_name);
+	err = reject_firmware(&rdev->rlc_fw, fw_name, &pdev->dev);
+	if (err)
+		goto out;
+	if (rdev->rlc_fw->size != rlc_req_size) {
+		printk(KERN_ERR
+		       "ni_rlc: Bogus length %zu in firmware \"%s\"\n",
+		       rdev->rlc_fw->size, fw_name);
+		err = -EINVAL;
+	}
+
+	snprintf(fw_name, sizeof(fw_name), "/*(DEBLOBBED)*/", chip_name);
+	err = reject_firmware(&rdev->mc_fw, fw_name, &pdev->dev);
+	if (err)
+		goto out;
+	if (rdev->mc_fw->size != mc_req_size) {
+		printk(KERN_ERR
+		       "ni_mc: Bogus length %zu in firmware \"%s\"\n",
+		       rdev->mc_fw->size, fw_name);
+		err = -EINVAL;
+	}
+out:
+	platform_device_unregister(pdev);
+
+	if (err) {
+		if (err != -EINVAL)
+			printk(KERN_ERR
+			       "ni_cp: Failed to load firmware \"%s\"\n",
+			       fw_name);
+		release_firmware(rdev->pfp_fw);
+		rdev->pfp_fw = NULL;
+		release_firmware(rdev->me_fw);
+		rdev->me_fw = NULL;
+		release_firmware(rdev->rlc_fw);
+		rdev->rlc_fw = NULL;
+		release_firmware(rdev->mc_fw);
+		rdev->mc_fw = NULL;
+	}
+	return err;
+}
+
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/nid.h linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/nid.h
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/nid.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/nid.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2010 Advanced Micro Devices, 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: Alex Deucher
+ */
+#ifndef NI_H
+#define NI_H
+
+#define MC_SHARED_BLACKOUT_CNTL           		0x20ac
+#define MC_SEQ_SUP_CNTL           			0x28c8
+#define		RUN_MASK      				(1 << 0)
+#define MC_SEQ_SUP_PGM           			0x28cc
+#define MC_IO_PAD_CNTL_D0           			0x29d0
+#define		MEM_FALL_OUT_CMD      			(1 << 8)
+#define MC_SEQ_MISC0           				0x2a00
+#define		MC_SEQ_MISC0_GDDR5_SHIFT      		28
+#define		MC_SEQ_MISC0_GDDR5_MASK      		0xf0000000
+#define		MC_SEQ_MISC0_GDDR5_VALUE      		5
+#define MC_SEQ_IO_DEBUG_INDEX           		0x2a44
+#define MC_SEQ_IO_DEBUG_DATA           			0x2a48
+
+#endif
+
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/ni_reg.h linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/ni_reg.h
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/ni_reg.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/ni_reg.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2010 Advanced Micro Devices, 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: Alex Deucher
+ */
+#ifndef __NI_REG_H__
+#define __NI_REG_H__
+
+/* northern islands - DCE5 */
+
+#define NI_INPUT_GAMMA_CONTROL                         0x6840
+#       define NI_GRPH_INPUT_GAMMA_MODE(x)             (((x) & 0x3) << 0)
+#       define NI_INPUT_GAMMA_USE_LUT                  0
+#       define NI_INPUT_GAMMA_BYPASS                   1
+#       define NI_INPUT_GAMMA_SRGB_24                  2
+#       define NI_INPUT_GAMMA_XVYCC_222                3
+#       define NI_OVL_INPUT_GAMMA_MODE(x)              (((x) & 0x3) << 4)
+
+#define NI_PRESCALE_GRPH_CONTROL                       0x68b4
+#       define NI_GRPH_PRESCALE_BYPASS                 (1 << 4)
+
+#define NI_PRESCALE_OVL_CONTROL                        0x68c4
+#       define NI_OVL_PRESCALE_BYPASS                  (1 << 4)
+
+#define NI_INPUT_CSC_CONTROL                           0x68d4
+#       define NI_INPUT_CSC_GRPH_MODE(x)               (((x) & 0x3) << 0)
+#       define NI_INPUT_CSC_BYPASS                     0
+#       define NI_INPUT_CSC_PROG_COEFF                 1
+#       define NI_INPUT_CSC_PROG_SHARED_MATRIXA        2
+#       define NI_INPUT_CSC_OVL_MODE(x)                (((x) & 0x3) << 4)
+
+#define NI_OUTPUT_CSC_CONTROL                          0x68f0
+#       define NI_OUTPUT_CSC_GRPH_MODE(x)              (((x) & 0x7) << 0)
+#       define NI_OUTPUT_CSC_BYPASS                    0
+#       define NI_OUTPUT_CSC_TV_RGB                    1
+#       define NI_OUTPUT_CSC_YCBCR_601                 2
+#       define NI_OUTPUT_CSC_YCBCR_709                 3
+#       define NI_OUTPUT_CSC_PROG_COEFF                4
+#       define NI_OUTPUT_CSC_PROG_SHARED_MATRIXB       5
+#       define NI_OUTPUT_CSC_OVL_MODE(x)               (((x) & 0x7) << 4)
+
+#define NI_DEGAMMA_CONTROL                             0x6960
+#       define NI_GRPH_DEGAMMA_MODE(x)                 (((x) & 0x3) << 0)
+#       define NI_DEGAMMA_BYPASS                       0
+#       define NI_DEGAMMA_SRGB_24                      1
+#       define NI_DEGAMMA_XVYCC_222                    2
+#       define NI_OVL_DEGAMMA_MODE(x)                  (((x) & 0x3) << 4)
+#       define NI_ICON_DEGAMMA_MODE(x)                 (((x) & 0x3) << 8)
+#       define NI_CURSOR_DEGAMMA_MODE(x)               (((x) & 0x3) << 12)
+
+#define NI_GAMUT_REMAP_CONTROL                         0x6964
+#       define NI_GRPH_GAMUT_REMAP_MODE(x)             (((x) & 0x3) << 0)
+#       define NI_GAMUT_REMAP_BYPASS                   0
+#       define NI_GAMUT_REMAP_PROG_COEFF               1
+#       define NI_GAMUT_REMAP_PROG_SHARED_MATRIXA      2
+#       define NI_GAMUT_REMAP_PROG_SHARED_MATRIXB      3
+#       define NI_OVL_GAMUT_REMAP_MODE(x)              (((x) & 0x3) << 4)
+
+#define NI_REGAMMA_CONTROL                             0x6a80
+#       define NI_GRPH_REGAMMA_MODE(x)                 (((x) & 0x7) << 0)
+#       define NI_REGAMMA_BYPASS                       0
+#       define NI_REGAMMA_SRGB_24                      1
+#       define NI_REGAMMA_XVYCC_222                    2
+#       define NI_REGAMMA_PROG_A                       3
+#       define NI_REGAMMA_PROG_B                       4
+#       define NI_OVL_REGAMMA_MODE(x)                  (((x) & 0x7) << 4)
+
+#endif
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/ObjectID.h linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/ObjectID.h
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/ObjectID.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/ObjectID.h	2011-03-14 21:20:32.000000000 -0400
@@ -37,6 +37,8 @@
 #define GRAPH_OBJECT_TYPE_CONNECTOR               0x3
 #define GRAPH_OBJECT_TYPE_ROUTER                  0x4
 /* deleted */
+#define GRAPH_OBJECT_TYPE_DISPLAY_PATH            0x6  
+#define GRAPH_OBJECT_TYPE_GENERIC                 0x7
 
 /****************************************************/
 /* Encoder Object ID Definition                     */
@@ -64,6 +66,9 @@
 #define ENCODER_OBJECT_ID_VT1623                  0x10
 #define ENCODER_OBJECT_ID_HDMI_SI1930             0x11
 #define ENCODER_OBJECT_ID_HDMI_INTERNAL           0x12
+#define ENCODER_OBJECT_ID_ALMOND                  0x22
+#define ENCODER_OBJECT_ID_TRAVIS                  0x23
+#define ENCODER_OBJECT_ID_NUTMEG                  0x22
 /* Kaleidoscope (KLDSCP) Class Display Hardware (internal) */
 #define ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1   0x13
 #define ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1    0x14
@@ -108,6 +113,7 @@
 #define CONNECTOR_OBJECT_ID_DISPLAYPORT           0x13
 #define CONNECTOR_OBJECT_ID_eDP                   0x14
 #define CONNECTOR_OBJECT_ID_MXM                   0x15
+#define CONNECTOR_OBJECT_ID_LVDS_eDP              0x16
 
 /* deleted */
 
@@ -124,6 +130,7 @@
 #define GENERIC_OBJECT_ID_GLSYNC                  0x01
 #define GENERIC_OBJECT_ID_PX2_NON_DRIVABLE        0x02
 #define GENERIC_OBJECT_ID_MXM_OPM                 0x03
+#define GENERIC_OBJECT_ID_STEREO_PIN              0x04        //This object could show up from Misc Object table, it follows ATOM_OBJECT format, and contains one ATOM_OBJECT_GPIO_CNTL_RECORD for the stereo pin
 
 /****************************************************/
 /* Graphics Object ENUM ID Definition               */
@@ -360,6 +367,26 @@
                                                   GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
                                                   ENCODER_OBJECT_ID_GENERAL_EXTERNAL_DVO << OBJECT_ID_SHIFT)
 
+#define ENCODER_ALMOND_ENUM_ID1                  ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+                                                  GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                                  ENCODER_OBJECT_ID_ALMOND << OBJECT_ID_SHIFT)
+
+#define ENCODER_ALMOND_ENUM_ID2                  ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+                                                  GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
+                                                  ENCODER_OBJECT_ID_ALMOND << OBJECT_ID_SHIFT)
+
+#define ENCODER_TRAVIS_ENUM_ID1                  ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+                                                  GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                                  ENCODER_OBJECT_ID_TRAVIS << OBJECT_ID_SHIFT)
+
+#define ENCODER_TRAVIS_ENUM_ID2                  ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+                                                  GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
+                                                  ENCODER_OBJECT_ID_TRAVIS << OBJECT_ID_SHIFT)
+
+#define ENCODER_NUTMEG_ENUM_ID1                  ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+                                                  GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                                  ENCODER_OBJECT_ID_NUTMEG << OBJECT_ID_SHIFT)
+
 /****************************************************/
 /* Connector Object ID definition - Shared with BIOS */
 /****************************************************/
@@ -421,6 +448,14 @@
                                                  GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
                                                  CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D << OBJECT_ID_SHIFT)
 
+#define CONNECTOR_SINGLE_LINK_DVI_D_ENUM_ID3   ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID3 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_SINGLE_LINK_DVI_D_ENUM_ID4   ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID4 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D << OBJECT_ID_SHIFT)
+
 #define CONNECTOR_DUAL_LINK_DVI_D_ENUM_ID1     ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
                                                  GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
                                                  CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D << OBJECT_ID_SHIFT)
@@ -512,6 +547,7 @@
 #define CONNECTOR_7PIN_DIN_ENUM_ID1            ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
                                                  GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
                                                  CONNECTOR_OBJECT_ID_7PIN_DIN << OBJECT_ID_SHIFT)
+
 #define CONNECTOR_7PIN_DIN_ENUM_ID2            ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
                                                  GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
                                                  CONNECTOR_OBJECT_ID_7PIN_DIN << OBJECT_ID_SHIFT)
@@ -593,6 +629,14 @@
                                                  GRAPH_OBJECT_ENUM_ID7 << ENUM_ID_SHIFT |\
                                                  CONNECTOR_OBJECT_ID_MXM << OBJECT_ID_SHIFT)          //Mapping to MXM_DAC
 
+#define CONNECTOR_LVDS_eDP_ENUM_ID1            ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_LVDS_eDP << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_LVDS_eDP_ENUM_ID2            ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_LVDS_eDP << OBJECT_ID_SHIFT)
+
 /****************************************************/
 /* Router Object ID definition - Shared with BIOS   */
 /****************************************************/
@@ -621,6 +665,10 @@
                                                  GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
                                                  GENERIC_OBJECT_ID_MXM_OPM << OBJECT_ID_SHIFT)
 
+#define GENERICOBJECT_STEREO_PIN_ENUM_ID1        (GRAPH_OBJECT_TYPE_GENERIC << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                                 GENERIC_OBJECT_ID_STEREO_PIN << OBJECT_ID_SHIFT)
+
 /****************************************************/
 /* Object Cap definition - Shared with BIOS         */
 /****************************************************/
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/r100.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/r100.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/r100.c	2013-05-03 03:54:47.000000000 -0400
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/r100.c	2013-05-03 01:53:55.000000000 -0400
@@ -62,6 +62,39 @@
  * r100,rv100,rs100,rv200,rs200,r200,rv250,rs300,rv280
  */
 
+void r100_pre_page_flip(struct radeon_device *rdev, int crtc)
+{
+	/* enable the pflip int */
+	radeon_irq_kms_pflip_irq_get(rdev, crtc);
+}
+
+void r100_post_page_flip(struct radeon_device *rdev, int crtc)
+{
+	/* disable the pflip int */
+	radeon_irq_kms_pflip_irq_put(rdev, crtc);
+}
+
+u32 r100_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base)
+{
+	struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
+	u32 tmp = ((u32)crtc_base) | RADEON_CRTC_OFFSET__OFFSET_LOCK;
+
+	/* 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));
+	DRM_DEBUG("Update pending now high. Unlocking vupdate_lock.\n");
+
+	/* Unlock the lock, so double-buffering can take place inside vblank */
+	tmp &= ~RADEON_CRTC_OFFSET__OFFSET_LOCK;
+	WREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset, tmp);
+
+	/* Return current update_pending status: */
+	return RREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset) & RADEON_CRTC_OFFSET__GUI_TRIG_OFFSET;
+}
+
 void r100_pm_get_dynpm_state(struct radeon_device *rdev)
 {
 	int i;
@@ -520,10 +553,12 @@ int r100_irq_set(struct radeon_device *r
 	if (rdev->irq.gui_idle) {
 		tmp |= RADEON_GUI_IDLE_MASK;
 	}
-	if (rdev->irq.crtc_vblank_int[0]) {
+	if (rdev->irq.crtc_vblank_int[0] ||
+	    rdev->irq.pflip[0]) {
 		tmp |= RADEON_CRTC_VBLANK_MASK;
 	}
-	if (rdev->irq.crtc_vblank_int[1]) {
+	if (rdev->irq.crtc_vblank_int[1] ||
+	    rdev->irq.pflip[1]) {
 		tmp |= RADEON_CRTC2_VBLANK_MASK;
 	}
 	if (rdev->irq.hpd[0]) {
@@ -594,14 +629,22 @@ int r100_irq_process(struct radeon_devic
 		}
 		/* Vertical blank interrupts */
 		if (status & RADEON_CRTC_VBLANK_STAT) {
-			drm_handle_vblank(rdev->ddev, 0);
-			rdev->pm.vblank_sync = true;
-			wake_up(&rdev->irq.vblank_queue);
+			if (rdev->irq.crtc_vblank_int[0]) {
+				drm_handle_vblank(rdev->ddev, 0);
+				rdev->pm.vblank_sync = true;
+				wake_up(&rdev->irq.vblank_queue);
+			}
+			if (rdev->irq.pflip[0])
+				radeon_crtc_handle_flip(rdev, 0);
 		}
 		if (status & RADEON_CRTC2_VBLANK_STAT) {
-			drm_handle_vblank(rdev->ddev, 1);
-			rdev->pm.vblank_sync = true;
-			wake_up(&rdev->irq.vblank_queue);
+			if (rdev->irq.crtc_vblank_int[1]) {
+				drm_handle_vblank(rdev->ddev, 1);
+				rdev->pm.vblank_sync = true;
+				wake_up(&rdev->irq.vblank_queue);
+			}
+			if (rdev->irq.pflip[1])
+				radeon_crtc_handle_flip(rdev, 1);
 		}
 		if (status & RADEON_FP_DETECT_STAT) {
 			queue_hotplug = true;
@@ -616,7 +659,7 @@ int r100_irq_process(struct radeon_devic
 	/* reset gui idle ack.  the status bit is broken */
 	rdev->irq.gui_idle_acked = false;
 	if (queue_hotplug)
-		queue_work(rdev->wq, &rdev->hotplug_work);
+		schedule_work(&rdev->hotplug_work);
 	if (rdev->msi_enabled) {
 		switch (rdev->family) {
 		case CHIP_RS400:
@@ -965,8 +1008,8 @@ int r100_cp_init(struct radeon_device *r
 	WREG32(RADEON_CP_CSQ_MODE,
 	       REG_SET(RADEON_INDIRECT2_START, indirect2_start) |
 	       REG_SET(RADEON_INDIRECT1_START, indirect1_start));
-	WREG32(0x718, 0);
-	WREG32(0x744, 0x00004D4D);
+	WREG32(RADEON_CP_RB_WPTR_DELAY, 0);
+	WREG32(RADEON_CP_CSQ_MODE, 0x00004D4D);
 	WREG32(RADEON_CP_CSQ_CNTL, RADEON_CSQ_PRIBM_INDBM);
 	radeon_ring_start(rdev);
 	r = radeon_ring_test(rdev);
@@ -975,7 +1018,7 @@ int r100_cp_init(struct radeon_device *r
 		return r;
 	}
 	rdev->cp.ready = true;
-	rdev->mc.active_vram_size = rdev->mc.real_vram_size;
+	radeon_ttm_set_active_vram_size(rdev, rdev->mc.real_vram_size);
 	return 0;
 }
 
@@ -993,7 +1036,7 @@ void r100_cp_fini(struct radeon_device *
 void r100_cp_disable(struct radeon_device *rdev)
 {
 	/* Disable ring */
-	rdev->mc.active_vram_size = rdev->mc.visible_vram_size;
+	radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size);
 	rdev->cp.ready = false;
 	WREG32(RADEON_CP_CSQ_MODE, 0);
 	WREG32(RADEON_CP_CSQ_CNTL, 0);
@@ -1361,6 +1404,7 @@ static int r100_packet0_check(struct rad
 		}
 		track->zb.robj = reloc->robj;
 		track->zb.offset = idx_value;
+		track->zb_dirty = true;
 		ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset);
 		break;
 	case RADEON_RB3D_COLOROFFSET:
@@ -1373,6 +1417,7 @@ static int r100_packet0_check(struct rad
 		}
 		track->cb[0].robj = reloc->robj;
 		track->cb[0].offset = idx_value;
+		track->cb_dirty = true;
 		ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset);
 		break;
 	case RADEON_PP_TXOFFSET_0:
@@ -1388,6 +1433,7 @@ static int r100_packet0_check(struct rad
 		}
 		ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset);
 		track->textures[i].robj = reloc->robj;
+		track->tex_dirty = true;
 		break;
 	case RADEON_PP_CUBIC_OFFSET_T0_0:
 	case RADEON_PP_CUBIC_OFFSET_T0_1:
@@ -1405,6 +1451,7 @@ static int r100_packet0_check(struct rad
 		track->textures[0].cube_info[i].offset = idx_value;
 		ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset);
 		track->textures[0].cube_info[i].robj = reloc->robj;
+		track->tex_dirty = true;
 		break;
 	case RADEON_PP_CUBIC_OFFSET_T1_0:
 	case RADEON_PP_CUBIC_OFFSET_T1_1:
@@ -1422,6 +1469,7 @@ static int r100_packet0_check(struct rad
 		track->textures[1].cube_info[i].offset = idx_value;
 		ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset);
 		track->textures[1].cube_info[i].robj = reloc->robj;
+		track->tex_dirty = true;
 		break;
 	case RADEON_PP_CUBIC_OFFSET_T2_0:
 	case RADEON_PP_CUBIC_OFFSET_T2_1:
@@ -1439,9 +1487,12 @@ static int r100_packet0_check(struct rad
 		track->textures[2].cube_info[i].offset = idx_value;
 		ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset);
 		track->textures[2].cube_info[i].robj = reloc->robj;
+		track->tex_dirty = true;
 		break;
 	case RADEON_RE_WIDTH_HEIGHT:
 		track->maxy = ((idx_value >> 16) & 0x7FF);
+		track->cb_dirty = true;
+		track->zb_dirty = true;
 		break;
 	case RADEON_RB3D_COLORPITCH:
 		r = r100_cs_packet_next_reloc(p, &reloc);
@@ -1462,9 +1513,11 @@ static int r100_packet0_check(struct rad
 		ib[idx] = tmp;
 
 		track->cb[0].pitch = idx_value & RADEON_COLORPITCH_MASK;
+		track->cb_dirty = true;
 		break;
 	case RADEON_RB3D_DEPTHPITCH:
 		track->zb.pitch = idx_value & RADEON_DEPTHPITCH_MASK;
+		track->zb_dirty = true;
 		break;
 	case RADEON_RB3D_CNTL:
 		switch ((idx_value >> RADEON_RB3D_COLOR_FORMAT_SHIFT) & 0x1f) {
@@ -1489,6 +1542,8 @@ static int r100_packet0_check(struct rad
 			return -EINVAL;
 		}
 		track->z_enabled = !!(idx_value & RADEON_Z_ENABLE);
+		track->cb_dirty = true;
+		track->zb_dirty = true;
 		break;
 	case RADEON_RB3D_ZSTENCILCNTL:
 		switch (idx_value & 0xf) {
@@ -1506,6 +1561,7 @@ static int r100_packet0_check(struct rad
 		default:
 			break;
 		}
+		track->zb_dirty = true;
 		break;
 	case RADEON_RB3D_ZPASS_ADDR:
 		r = r100_cs_packet_next_reloc(p, &reloc);
@@ -1522,6 +1578,7 @@ static int r100_packet0_check(struct rad
 			uint32_t temp = idx_value >> 4;
 			for (i = 0; i < track->num_texture; i++)
 				track->textures[i].enabled = !!(temp & (1 << i));
+			track->tex_dirty = true;
 		}
 		break;
 	case RADEON_SE_VF_CNTL:
@@ -1536,12 +1593,14 @@ static int r100_packet0_check(struct rad
 		i = (reg - RADEON_PP_TEX_SIZE_0) / 8;
 		track->textures[i].width = (idx_value & RADEON_TEX_USIZE_MASK) + 1;
 		track->textures[i].height = ((idx_value & RADEON_TEX_VSIZE_MASK) >> RADEON_TEX_VSIZE_SHIFT) + 1;
+		track->tex_dirty = true;
 		break;
 	case RADEON_PP_TEX_PITCH_0:
 	case RADEON_PP_TEX_PITCH_1:
 	case RADEON_PP_TEX_PITCH_2:
 		i = (reg - RADEON_PP_TEX_PITCH_0) / 8;
 		track->textures[i].pitch = idx_value + 32;
+		track->tex_dirty = true;
 		break;
 	case RADEON_PP_TXFILTER_0:
 	case RADEON_PP_TXFILTER_1:
@@ -1555,6 +1614,7 @@ static int r100_packet0_check(struct rad
 		tmp = (idx_value >> 27) & 0x7;
 		if (tmp == 2 || tmp == 6)
 			track->textures[i].roundup_h = false;
+		track->tex_dirty = true;
 		break;
 	case RADEON_PP_TXFORMAT_0:
 	case RADEON_PP_TXFORMAT_1:
@@ -1607,6 +1667,7 @@ static int r100_packet0_check(struct rad
 		}
 		track->textures[i].cube_info[4].width = 1 << ((idx_value >> 16) & 0xf);
 		track->textures[i].cube_info[4].height = 1 << ((idx_value >> 20) & 0xf);
+		track->tex_dirty = true;
 		break;
 	case RADEON_PP_CUBIC_FACES_0:
 	case RADEON_PP_CUBIC_FACES_1:
@@ -1617,6 +1678,7 @@ static int r100_packet0_check(struct rad
 			track->textures[i].cube_info[face].width = 1 << ((tmp >> (face * 8)) & 0xf);
 			track->textures[i].cube_info[face].height = 1 << ((tmp >> ((face * 8) + 4)) & 0xf);
 		}
+		track->tex_dirty = true;
 		break;
 	default:
 		printk(KERN_ERR "Forbidden register 0x%04X in cs at %d\n",
@@ -2020,12 +2082,13 @@ int r100_asic_reset(struct radeon_device
 {
 	struct r100_mc_save save;
 	u32 status, tmp;
+	int ret = 0;
 
-	r100_mc_stop(rdev, &save);
 	status = RREG32(R_000E40_RBBM_STATUS);
 	if (!G_000E40_GUI_ACTIVE(status)) {
 		return 0;
 	}
+	r100_mc_stop(rdev, &save);
 	status = RREG32(R_000E40_RBBM_STATUS);
 	dev_info(rdev->dev, "(%s:%d) RBBM_STATUS=0x%08X\n", __func__, __LINE__, status);
 	/* stop CP */
@@ -2065,11 +2128,11 @@ int r100_asic_reset(struct radeon_device
 		G_000E40_TAM_BUSY(status) || G_000E40_PB_BUSY(status)) {
 		dev_err(rdev->dev, "failed to reset GPU\n");
 		rdev->gpu_lockup = true;
-		return -1;
-	}
+		ret = -1;
+	} else
+		dev_info(rdev->dev, "GPU reset succeed\n");
 	r100_mc_resume(rdev, &save);
-	dev_info(rdev->dev, "GPU reset succeed\n");
-	return 0;
+	return ret;
 }
 
 void r100_set_common_regs(struct radeon_device *rdev)
@@ -2243,7 +2306,6 @@ void r100_vram_init_sizes(struct radeon_
 	/* FIXME we don't use the second aperture yet when we could use it */
 	if (rdev->mc.visible_vram_size > rdev->mc.aper_size)
 		rdev->mc.visible_vram_size = rdev->mc.aper_size;
-	rdev->mc.active_vram_size = rdev->mc.visible_vram_size;
 	config_aper_size = RREG32(RADEON_CONFIG_APER_SIZE);
 	if (rdev->flags & RADEON_IS_IGP) {
 		uint32_t tom;
@@ -2280,10 +2342,10 @@ void r100_vga_set_state(struct radeon_de
 
 	temp = RREG32(RADEON_CONFIG_CNTL);
 	if (state == false) {
-		temp &= ~(1<<8);
-		temp |= (1<<9);
+		temp &= ~RADEON_CFG_VGA_RAM_EN;
+		temp |= RADEON_CFG_VGA_IO_DIS;
 	} else {
-		temp &= ~(1<<9);
+		temp &= ~RADEON_CFG_VGA_IO_DIS;
 	}
 	WREG32(RADEON_CONFIG_CNTL, temp);
 }
@@ -3251,9 +3313,9 @@ int r100_cs_track_check(struct radeon_de
 	unsigned long size;
 	unsigned prim_walk;
 	unsigned nverts;
-	unsigned num_cb = track->num_cb;
+	unsigned num_cb = track->cb_dirty ? track->num_cb : 0;
 
-	if (!track->zb_cb_clear && !track->color_channel_mask &&
+	if (num_cb && !track->zb_cb_clear && !track->color_channel_mask &&
 	    !track->blend_read_enable)
 		num_cb = 0;
 
@@ -3274,7 +3336,9 @@ int r100_cs_track_check(struct radeon_de
 			return -EINVAL;
 		}
 	}
-	if (track->z_enabled) {
+	track->cb_dirty = false;
+
+	if (track->zb_dirty && track->z_enabled) {
 		if (track->zb.robj == NULL) {
 			DRM_ERROR("[drm] No buffer for z buffer !\n");
 			return -EINVAL;
@@ -3291,6 +3355,28 @@ int r100_cs_track_check(struct radeon_de
 			return -EINVAL;
 		}
 	}
+	track->zb_dirty = false;
+
+	if (track->aa_dirty && track->aaresolve) {
+		if (track->aa.robj == NULL) {
+			DRM_ERROR("[drm] No buffer for AA resolve buffer %d !\n", i);
+			return -EINVAL;
+		}
+		/* I believe the format comes from colorbuffer0. */
+		size = track->aa.pitch * track->cb[0].cpp * track->maxy;
+		size += track->aa.offset;
+		if (size > radeon_bo_size(track->aa.robj)) {
+			DRM_ERROR("[drm] Buffer too small for AA resolve buffer %d "
+				  "(need %lu have %lu) !\n", i, size,
+				  radeon_bo_size(track->aa.robj));
+			DRM_ERROR("[drm] AA resolve buffer %d (%u %u %u %u)\n",
+				  i, track->aa.pitch, track->cb[0].cpp,
+				  track->aa.offset, track->maxy);
+			return -EINVAL;
+		}
+	}
+	track->aa_dirty = false;
+
 	prim_walk = (track->vap_vf_cntl >> 4) & 0x3;
 	if (track->vap_vf_cntl & (1 << 14)) {
 		nverts = track->vap_alt_nverts;
@@ -3350,13 +3436,23 @@ int r100_cs_track_check(struct radeon_de
 			  prim_walk);
 		return -EINVAL;
 	}
-	return r100_cs_track_texture_check(rdev, track);
+
+	if (track->tex_dirty) {
+		track->tex_dirty = false;
+		return r100_cs_track_texture_check(rdev, track);
+	}
+	return 0;
 }
 
 void r100_cs_track_clear(struct radeon_device *rdev, struct r100_cs_track *track)
 {
 	unsigned i, face;
 
+	track->cb_dirty = true;
+	track->zb_dirty = true;
+	track->tex_dirty = true;
+	track->aa_dirty = true;
+
 	if (rdev->family < CHIP_R300) {
 		track->num_cb = 1;
 		if (rdev->family <= CHIP_RS200)
@@ -3370,6 +3466,8 @@ void r100_cs_track_clear(struct radeon_d
 		track->num_texture = 16;
 		track->maxy = 4096;
 		track->separate_cube = 0;
+		track->aaresolve = false;
+		track->aa.robj = NULL;
 	}
 
 	for (i = 0; i < track->num_cb; i++) {
@@ -3455,7 +3553,7 @@ int r100_ring_test(struct radeon_device
 	if (i < rdev->usec_timeout) {
 		DRM_INFO("ring test succeeded in %d usecs\n", i);
 	} else {
-		DRM_ERROR("radeon: ring test failed (sracth(0x%04X)=0x%08X)\n",
+		DRM_ERROR("radeon: ring test failed (scratch(0x%04X)=0x%08X)\n",
 			  scratch, tmp);
 		r = -EINVAL;
 	}
@@ -3679,8 +3777,6 @@ static int r100_startup(struct radeon_de
 	r100_mc_program(rdev);
 	/* Resume clock */
 	r100_clock_startup(rdev);
-	/* Initialize GPU configuration (# pipes, ...) */
-//	r100_gpu_init(rdev);
 	/* Initialize GART (initialize after TTM so we can allocate
 	 * memory through TTM but finalize after TTM) */
 	r100_enable_bm(rdev);
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/r100d.h linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/r100d.h
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/r100d.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/r100d.h	2011-03-14 21:20:32.000000000 -0400
@@ -551,7 +551,7 @@
 #define   S_000360_CUR2_LOCK(x)                        (((x) & 0x1) << 31)
 #define   G_000360_CUR2_LOCK(x)                        (((x) >> 31) & 0x1)
 #define   C_000360_CUR2_LOCK                           0x7FFFFFFF
-#define R_0003C2_GENMO_WT                            0x0003C0
+#define R_0003C2_GENMO_WT                            0x0003C2
 #define   S_0003C2_GENMO_MONO_ADDRESS_B(x)             (((x) & 0x1) << 0)
 #define   G_0003C2_GENMO_MONO_ADDRESS_B(x)             (((x) >> 0) & 0x1)
 #define   C_0003C2_GENMO_MONO_ADDRESS_B                0xFE
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/r100_track.h linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/r100_track.h
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/r100_track.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/r100_track.h	2011-03-14 21:20:32.000000000 -0400
@@ -52,14 +52,7 @@ struct r100_cs_track_texture {
 	unsigned                compress_format;
 };
 
-struct r100_cs_track_limits {
-	unsigned num_cb;
-	unsigned num_texture;
-	unsigned max_levels;
-};
-
 struct r100_cs_track {
-	struct radeon_device *rdev;
 	unsigned			num_cb;
 	unsigned                        num_texture;
 	unsigned			maxy;
@@ -73,11 +66,17 @@ struct r100_cs_track {
 	struct r100_cs_track_array	arrays[11];
 	struct r100_cs_track_cb 	cb[R300_MAX_CB];
 	struct r100_cs_track_cb 	zb;
+	struct r100_cs_track_cb 	aa;
 	struct r100_cs_track_texture	textures[R300_TRACK_MAX_TEXTURE];
 	bool				z_enabled;
 	bool                            separate_cube;
 	bool				zb_cb_clear;
 	bool				blend_read_enable;
+	bool				cb_dirty;
+	bool				zb_dirty;
+	bool				tex_dirty;
+	bool				aa_dirty;
+	bool				aaresolve;
 };
 
 int r100_cs_track_check(struct radeon_device *rdev, struct r100_cs_track *track);
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/r200.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/r200.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/r200.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/r200.c	2011-03-14 21:20:32.000000000 -0400
@@ -184,6 +184,7 @@ int r200_packet0_check(struct radeon_cs_
 		}
 		track->zb.robj = reloc->robj;
 		track->zb.offset = idx_value;
+		track->zb_dirty = true;
 		ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset);
 		break;
 	case RADEON_RB3D_COLOROFFSET:
@@ -196,6 +197,7 @@ int r200_packet0_check(struct radeon_cs_
 		}
 		track->cb[0].robj = reloc->robj;
 		track->cb[0].offset = idx_value;
+		track->cb_dirty = true;
 		ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset);
 		break;
 	case R200_PP_TXOFFSET_0:
@@ -214,6 +216,7 @@ int r200_packet0_check(struct radeon_cs_
 		}
 		ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset);
 		track->textures[i].robj = reloc->robj;
+		track->tex_dirty = true;
 		break;
 	case R200_PP_CUBIC_OFFSET_F1_0:
 	case R200_PP_CUBIC_OFFSET_F2_0:
@@ -257,9 +260,12 @@ int r200_packet0_check(struct radeon_cs_
 		track->textures[i].cube_info[face - 1].offset = idx_value;
 		ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset);
 		track->textures[i].cube_info[face - 1].robj = reloc->robj;
+		track->tex_dirty = true;
 		break;
 	case RADEON_RE_WIDTH_HEIGHT:
 		track->maxy = ((idx_value >> 16) & 0x7FF);
+		track->cb_dirty = true;
+		track->zb_dirty = true;
 		break;
 	case RADEON_RB3D_COLORPITCH:
 		r = r100_cs_packet_next_reloc(p, &reloc);
@@ -280,9 +286,11 @@ int r200_packet0_check(struct radeon_cs_
 		ib[idx] = tmp;
 
 		track->cb[0].pitch = idx_value & RADEON_COLORPITCH_MASK;
+		track->cb_dirty = true;
 		break;
 	case RADEON_RB3D_DEPTHPITCH:
 		track->zb.pitch = idx_value & RADEON_DEPTHPITCH_MASK;
+		track->zb_dirty = true;
 		break;
 	case RADEON_RB3D_CNTL:
 		switch ((idx_value >> RADEON_RB3D_COLOR_FORMAT_SHIFT) & 0x1f) {
@@ -312,6 +320,8 @@ int r200_packet0_check(struct radeon_cs_
 		}
 
 		track->z_enabled = !!(idx_value & RADEON_Z_ENABLE);
+		track->cb_dirty = true;
+		track->zb_dirty = true;
 		break;
 	case RADEON_RB3D_ZSTENCILCNTL:
 		switch (idx_value & 0xf) {
@@ -329,6 +339,7 @@ int r200_packet0_check(struct radeon_cs_
 		default:
 			break;
 		}
+		track->zb_dirty = true;
 		break;
 	case RADEON_RB3D_ZPASS_ADDR:
 		r = r100_cs_packet_next_reloc(p, &reloc);
@@ -345,6 +356,7 @@ int r200_packet0_check(struct radeon_cs_
 			uint32_t temp = idx_value >> 4;
 			for (i = 0; i < track->num_texture; i++)
 				track->textures[i].enabled = !!(temp & (1 << i));
+			track->tex_dirty = true;
 		}
 		break;
 	case RADEON_SE_VF_CNTL:
@@ -369,6 +381,7 @@ int r200_packet0_check(struct radeon_cs_
 		i = (reg - R200_PP_TXSIZE_0) / 32;
 		track->textures[i].width = (idx_value & RADEON_TEX_USIZE_MASK) + 1;
 		track->textures[i].height = ((idx_value & RADEON_TEX_VSIZE_MASK) >> RADEON_TEX_VSIZE_SHIFT) + 1;
+		track->tex_dirty = true;
 		break;
 	case R200_PP_TXPITCH_0:
 	case R200_PP_TXPITCH_1:
@@ -378,6 +391,7 @@ int r200_packet0_check(struct radeon_cs_
 	case R200_PP_TXPITCH_5:
 		i = (reg - R200_PP_TXPITCH_0) / 32;
 		track->textures[i].pitch = idx_value + 32;
+		track->tex_dirty = true;
 		break;
 	case R200_PP_TXFILTER_0:
 	case R200_PP_TXFILTER_1:
@@ -394,6 +408,7 @@ int r200_packet0_check(struct radeon_cs_
 		tmp = (idx_value >> 27) & 0x7;
 		if (tmp == 2 || tmp == 6)
 			track->textures[i].roundup_h = false;
+		track->tex_dirty = true;
 		break;
 	case R200_PP_TXMULTI_CTL_0:
 	case R200_PP_TXMULTI_CTL_1:
@@ -432,6 +447,7 @@ int r200_packet0_check(struct radeon_cs_
 			track->textures[i].tex_coord_type = 1;
 			break;
 		}
+		track->tex_dirty = true;
 		break;
 	case R200_PP_TXFORMAT_0:
 	case R200_PP_TXFORMAT_1:
@@ -488,6 +504,7 @@ int r200_packet0_check(struct radeon_cs_
 		}
 		track->textures[i].cube_info[4].width = 1 << ((idx_value >> 16) & 0xf);
 		track->textures[i].cube_info[4].height = 1 << ((idx_value >> 20) & 0xf);
+		track->tex_dirty = true;
 		break;
 	case R200_PP_CUBIC_FACES_0:
 	case R200_PP_CUBIC_FACES_1:
@@ -501,6 +518,7 @@ int r200_packet0_check(struct radeon_cs_
 			track->textures[i].cube_info[face].width = 1 << ((tmp >> (face * 8)) & 0xf);
 			track->textures[i].cube_info[face].height = 1 << ((tmp >> ((face * 8) + 4)) & 0xf);
 		}
+		track->tex_dirty = true;
 		break;
 	default:
 		printk(KERN_ERR "Forbidden register 0x%04X in cs at %d\n",
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/r300.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/r300.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/r300.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/r300.c	2011-03-14 21:20:32.000000000 -0400
@@ -69,6 +69,9 @@ void rv370_pcie_gart_tlb_flush(struct ra
 	mb();
 }
 
+#define R300_PTE_WRITEABLE (1 << 2)
+#define R300_PTE_READABLE  (1 << 3)
+
 int rv370_pcie_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr)
 {
 	void __iomem *ptr = (void *)rdev->gart.table.vram.ptr;
@@ -78,7 +81,7 @@ int rv370_pcie_gart_set_page(struct rade
 	}
 	addr = (lower_32_bits(addr) >> 8) |
 	       ((upper_32_bits(addr) & 0xff) << 24) |
-	       0xc;
+	       R300_PTE_WRITEABLE | R300_PTE_READABLE;
 	/* on x86 we want this to be CPU endian, on powerpc
 	 * on powerpc without HW swappers, it'll get swapped on way
 	 * into VRAM - so no need for cpu_to_le32 on VRAM tables */
@@ -135,7 +138,7 @@ int rv370_pcie_gart_enable(struct radeon
 	WREG32_PCIE(RADEON_PCIE_TX_DISCARD_RD_ADDR_LO, rdev->mc.vram_start);
 	WREG32_PCIE(RADEON_PCIE_TX_DISCARD_RD_ADDR_HI, 0);
 	/* Clear error */
-	WREG32_PCIE(0x18, 0);
+	WREG32_PCIE(RADEON_PCIE_TX_GART_ERROR, 0);
 	tmp = RREG32_PCIE(RADEON_PCIE_TX_GART_CNTL);
 	tmp |= RADEON_PCIE_TX_GART_EN;
 	tmp |= RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_DISCARD;
@@ -405,12 +408,13 @@ int r300_asic_reset(struct radeon_device
 {
 	struct r100_mc_save save;
 	u32 status, tmp;
+	int ret = 0;
 
-	r100_mc_stop(rdev, &save);
 	status = RREG32(R_000E40_RBBM_STATUS);
 	if (!G_000E40_GUI_ACTIVE(status)) {
 		return 0;
 	}
+	r100_mc_stop(rdev, &save);
 	status = RREG32(R_000E40_RBBM_STATUS);
 	dev_info(rdev->dev, "(%s:%d) RBBM_STATUS=0x%08X\n", __func__, __LINE__, status);
 	/* stop CP */
@@ -451,11 +455,11 @@ int r300_asic_reset(struct radeon_device
 	if (G_000E40_GA_BUSY(status) || G_000E40_VAP_BUSY(status)) {
 		dev_err(rdev->dev, "failed to reset GPU\n");
 		rdev->gpu_lockup = true;
-		return -1;
-	}
+		ret = -1;
+	} else
+		dev_info(rdev->dev, "GPU reset succeed\n");
 	r100_mc_resume(rdev, &save);
-	dev_info(rdev->dev, "GPU reset succeed\n");
-	return 0;
+	return ret;
 }
 
 /*
@@ -558,10 +562,7 @@ int rv370_get_pcie_lanes(struct radeon_d
 
 	/* FIXME wait for idle */
 
-	if (rdev->family < CHIP_R600)
-		link_width_cntl = RREG32_PCIE(RADEON_PCIE_LC_LINK_WIDTH_CNTL);
-	else
-		link_width_cntl = RREG32_PCIE_P(RADEON_PCIE_LC_LINK_WIDTH_CNTL);
+	link_width_cntl = RREG32_PCIE(RADEON_PCIE_LC_LINK_WIDTH_CNTL);
 
 	switch ((link_width_cntl & RADEON_PCIE_LC_LINK_WIDTH_RD_MASK) >> RADEON_PCIE_LC_LINK_WIDTH_RD_SHIFT) {
 	case RADEON_PCIE_LC_LINK_WIDTH_X0:
@@ -666,6 +667,7 @@ static int r300_packet0_check(struct rad
 		}
 		track->cb[i].robj = reloc->robj;
 		track->cb[i].offset = idx_value;
+		track->cb_dirty = true;
 		ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset);
 		break;
 	case R300_ZB_DEPTHOFFSET:
@@ -678,6 +680,7 @@ static int r300_packet0_check(struct rad
 		}
 		track->zb.robj = reloc->robj;
 		track->zb.offset = idx_value;
+		track->zb_dirty = true;
 		ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset);
 		break;
 	case R300_TX_OFFSET_0:
@@ -716,6 +719,7 @@ static int r300_packet0_check(struct rad
 		tmp |= tile_flags;
 		ib[idx] = tmp;
 		track->textures[i].robj = reloc->robj;
+		track->tex_dirty = true;
 		break;
 	/* Tracked registers */
 	case 0x2084:
@@ -742,10 +746,18 @@ static int r300_packet0_check(struct rad
 		if (p->rdev->family < CHIP_RV515) {
 			track->maxy -= 1440;
 		}
+		track->cb_dirty = true;
+		track->zb_dirty = true;
 		break;
 	case 0x4E00:
 		/* RB3D_CCTL */
+		if ((idx_value & (1 << 10)) && /* CMASK_ENABLE */
+		    p->rdev->cmask_filp != p->filp) {
+			DRM_ERROR("Invalid RB3D_CCTL: Cannot enable CMASK.\n");
+			return -EINVAL;
+		}
 		track->num_cb = ((idx_value >> 5) & 0x3) + 1;
+		track->cb_dirty = true;
 		break;
 	case 0x4E38:
 	case 0x4E3C:
@@ -787,6 +799,13 @@ static int r300_packet0_check(struct rad
 		case 15:
 			track->cb[i].cpp = 2;
 			break;
+		case 5:
+			if (p->rdev->family < CHIP_RV515) {
+				DRM_ERROR("Invalid color buffer format (%d)!\n",
+					  ((idx_value >> 21) & 0xF));
+				return -EINVAL;
+			}
+			/* Pass through. */
 		case 6:
 			track->cb[i].cpp = 4;
 			break;
@@ -801,6 +820,7 @@ static int r300_packet0_check(struct rad
 				  ((idx_value >> 21) & 0xF));
 			return -EINVAL;
 		}
+		track->cb_dirty = true;
 		break;
 	case 0x4F00:
 		/* ZB_CNTL */
@@ -809,6 +829,7 @@ static int r300_packet0_check(struct rad
 		} else {
 			track->z_enabled = false;
 		}
+		track->zb_dirty = true;
 		break;
 	case 0x4F10:
 		/* ZB_FORMAT */
@@ -825,6 +846,7 @@ static int r300_packet0_check(struct rad
 				  (idx_value & 0xF));
 			return -EINVAL;
 		}
+		track->zb_dirty = true;
 		break;
 	case 0x4F24:
 		/* ZB_DEPTHPITCH */
@@ -848,14 +870,17 @@ static int r300_packet0_check(struct rad
 		ib[idx] = tmp;
 
 		track->zb.pitch = idx_value & 0x3FFC;
+		track->zb_dirty = true;
 		break;
 	case 0x4104:
+		/* TX_ENABLE */
 		for (i = 0; i < 16; i++) {
 			bool enabled;
 
 			enabled = !!(idx_value & (1 << i));
 			track->textures[i].enabled = enabled;
 		}
+		track->tex_dirty = true;
 		break;
 	case 0x44C0:
 	case 0x44C4:
@@ -885,6 +910,7 @@ static int r300_packet0_check(struct rad
 			track->textures[i].compress_format = R100_TRACK_COMP_NONE;
 			break;
 		case R300_TX_FORMAT_X16:
+		case R300_TX_FORMAT_FL_I16:
 		case R300_TX_FORMAT_Y8X8:
 		case R300_TX_FORMAT_Z5Y6X5:
 		case R300_TX_FORMAT_Z6Y5X5:
@@ -897,6 +923,7 @@ static int r300_packet0_check(struct rad
 			track->textures[i].compress_format = R100_TRACK_COMP_NONE;
 			break;
 		case R300_TX_FORMAT_Y16X16:
+		case R300_TX_FORMAT_FL_I16A16:
 		case R300_TX_FORMAT_Z11Y11X10:
 		case R300_TX_FORMAT_Z10Y11X11:
 		case R300_TX_FORMAT_W8Z8Y8X8:
@@ -938,8 +965,8 @@ static int r300_packet0_check(struct rad
 			DRM_ERROR("Invalid texture format %u\n",
 				  (idx_value & 0x1F));
 			return -EINVAL;
-			break;
 		}
+		track->tex_dirty = true;
 		break;
 	case 0x4400:
 	case 0x4404:
@@ -967,6 +994,7 @@ static int r300_packet0_check(struct rad
 		if (tmp == 2 || tmp == 4 || tmp == 6) {
 			track->textures[i].roundup_h = false;
 		}
+		track->tex_dirty = true;
 		break;
 	case 0x4500:
 	case 0x4504:
@@ -1004,6 +1032,7 @@ static int r300_packet0_check(struct rad
 			DRM_ERROR("Forbidden bit TXFORMAT_MSB\n");
 			return -EINVAL;
 		}
+		track->tex_dirty = true;
 		break;
 	case 0x4480:
 	case 0x4484:
@@ -1033,6 +1062,7 @@ static int r300_packet0_check(struct rad
 		track->textures[i].use_pitch = !!tmp;
 		tmp = (idx_value >> 22) & 0xF;
 		track->textures[i].txdepth = tmp;
+		track->tex_dirty = true;
 		break;
 	case R300_ZB_ZPASS_ADDR:
 		r = r100_cs_packet_next_reloc(p, &reloc);
@@ -1047,6 +1077,7 @@ static int r300_packet0_check(struct rad
 	case 0x4e0c:
 		/* RB3D_COLOR_CHANNEL_MASK */
 		track->color_channel_mask = idx_value;
+		track->cb_dirty = true;
 		break;
 	case 0x43a4:
 		/* SC_HYPERZ_EN */
@@ -1060,6 +1091,8 @@ static int r300_packet0_check(struct rad
 	case 0x4f1c:
 		/* ZB_BW_CNTL */
 		track->zb_cb_clear = !!(idx_value & (1 << 5));
+		track->cb_dirty = true;
+		track->zb_dirty = true;
 		if (p->rdev->hyperz_filp != p->filp) {
 			if (idx_value & (R300_HIZ_ENABLE |
 					 R300_RD_COMP_ENABLE |
@@ -1071,8 +1104,28 @@ static int r300_packet0_check(struct rad
 	case 0x4e04:
 		/* RB3D_BLENDCNTL */
 		track->blend_read_enable = !!(idx_value & (1 << 2));
+		track->cb_dirty = true;
 		break;
-	case 0x4f28: /* ZB_DEPTHCLEARVALUE */
+	case R300_RB3D_AARESOLVE_OFFSET:
+		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;
+		}
+		track->aa.robj = reloc->robj;
+		track->aa.offset = idx_value;
+		track->aa_dirty = true;
+		ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset);
+		break;
+	case R300_RB3D_AARESOLVE_PITCH:
+		track->aa.pitch = idx_value & 0x3FFE;
+		track->aa_dirty = true;
+		break;
+	case R300_RB3D_AARESOLVE_CTL:
+		track->aaresolve = idx_value & 0x1;
+		track->aa_dirty = true;
 		break;
 	case 0x4f30: /* ZB_MASK_OFFSET */
 	case 0x4f34: /* ZB_ZMASK_PITCH */
@@ -1199,6 +1252,10 @@ static int r300_packet3_check(struct rad
 		if (p->rdev->hyperz_filp != p->filp)
 			return -EINVAL;
 		break;
+	case PACKET3_3D_CLEAR_CMASK:
+		if (p->rdev->cmask_filp != p->filp)
+			return -EINVAL;
+		break;
 	case PACKET3_NOP:
 		break;
 	default:
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/r300d.h linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/r300d.h
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/r300d.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/r300d.h	2011-03-14 21:20:32.000000000 -0400
@@ -54,6 +54,7 @@
 #define		PACKET3_3D_DRAW_IMMD_2		0x35
 #define		PACKET3_3D_DRAW_INDX_2		0x36
 #define		PACKET3_3D_CLEAR_HIZ		0x37
+#define		PACKET3_3D_CLEAR_CMASK		0x38
 #define		PACKET3_BITBLT_MULTI		0x9B
 
 #define PACKET0(reg, n)	(CP_PACKET0 |					\
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/r300_reg.h linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/r300_reg.h
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/r300_reg.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/r300_reg.h	2011-03-14 21:20:32.000000000 -0400
@@ -1371,6 +1371,8 @@
 #define R300_RB3D_COLORPITCH2               0x4E40 /* GUESS */
 #define R300_RB3D_COLORPITCH3               0x4E44 /* GUESS */
 
+#define R300_RB3D_AARESOLVE_OFFSET          0x4E80
+#define R300_RB3D_AARESOLVE_PITCH           0x4E84
 #define R300_RB3D_AARESOLVE_CTL             0x4E88
 /* gap */
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/r420.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/r420.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/r420.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/r420.c	2011-03-14 21:20:32.000000000 -0400
@@ -96,7 +96,7 @@ void r420_pipes_init(struct radeon_devic
 		       "programming pipes. Bad things might happen.\n");
 	}
 	/* get max number of pipes */
-	gb_pipe_select = RREG32(0x402C);
+	gb_pipe_select = RREG32(R400_GB_PIPE_SELECT);
 	num_pipes = ((gb_pipe_select >> 12) & 3) + 1;
 
 	/* SE chips have 1 pipe */
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/r500_reg.h linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/r500_reg.h
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/r500_reg.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/r500_reg.h	2011-03-14 21:20:32.000000000 -0400
@@ -355,6 +355,8 @@
 #define AVIVO_D1CRTC_FRAME_COUNT                                0x60a4
 #define AVIVO_D1CRTC_STEREO_CONTROL                             0x60c4
 
+#define AVIVO_D1MODE_MASTER_UPDATE_MODE                         0x60e4
+
 /* master controls */
 #define AVIVO_DC_CRTC_MASTER_EN                                 0x60f8
 #define AVIVO_DC_CRTC_TV_CONTROL                                0x60fc
@@ -409,8 +411,10 @@
 #define AVIVO_D1GRPH_X_END                                      0x6134
 #define AVIVO_D1GRPH_Y_END                                      0x6138
 #define AVIVO_D1GRPH_UPDATE                                     0x6144
+#       define AVIVO_D1GRPH_SURFACE_UPDATE_PENDING              (1 << 2)
 #       define AVIVO_D1GRPH_UPDATE_LOCK                         (1 << 16)
 #define AVIVO_D1GRPH_FLIP_CONTROL                               0x6148
+#       define AVIVO_D1GRPH_SURFACE_UPDATE_H_RETRACE_EN         (1 << 0)
 
 #define AVIVO_D1CUR_CONTROL                     0x6400
 #       define AVIVO_D1CURSOR_EN                (1 << 0)
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/r520.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/r520.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/r520.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/r520.c	2011-03-14 21:20:32.000000000 -0400
@@ -79,8 +79,8 @@ static void r520_gpu_init(struct radeon_
 		WREG32(0x4128, 0xFF);
 	}
 	r420_pipes_init(rdev);
-	gb_pipe_select = RREG32(0x402C);
-	tmp = RREG32(0x170C);
+	gb_pipe_select = RREG32(R400_GB_PIPE_SELECT);
+	tmp = RREG32(R300_DST_PIPE_CONFIG);
 	pipe_select_current = (tmp >> 2) & 3;
 	tmp = (1 << pipe_select_current) |
 	      (((gb_pipe_select >> 8) & 0xF) << 4);
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/r600_blit.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/r600_blit.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/r600_blit.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/r600_blit.c	2011-03-14 21:20:32.000000000 -0400
@@ -137,9 +137,9 @@ set_shaders(struct drm_device *dev)
 	ps = (u32 *) ((char *)dev->agp_buffer_map->handle + dev_priv->blit_vb->offset + 256);
 
 	for (i = 0; i < r6xx_vs_size; i++)
-		vs[i] = r6xx_vs[i];
+		vs[i] = cpu_to_le32(r6xx_vs[i]);
 	for (i = 0; i < r6xx_ps_size; i++)
-		ps[i] = r6xx_ps[i];
+		ps[i] = cpu_to_le32(r6xx_ps[i]);
 
 	dev_priv->blit_vb->used = 512;
 
@@ -192,6 +192,9 @@ set_vtx_resource(drm_radeon_private_t *d
 	DRM_DEBUG("\n");
 
 	sq_vtx_constant_word2 = (((gpu_addr >> 32) & 0xff) | (16 << 8));
+#ifdef __BIG_ENDIAN
+	sq_vtx_constant_word2 |= (2 << 30);
+#endif
 
 	BEGIN_RING(9);
 	OUT_RING(CP_PACKET3(R600_IT_SET_RESOURCE, 7));
@@ -291,7 +294,11 @@ draw_auto(drm_radeon_private_t *dev_priv
 	OUT_RING(DI_PT_RECTLIST);
 
 	OUT_RING(CP_PACKET3(R600_IT_INDEX_TYPE, 0));
+#ifdef __BIG_ENDIAN
+	OUT_RING((2 << 2) | DI_INDEX_SIZE_16_BIT);
+#else
 	OUT_RING(DI_INDEX_SIZE_16_BIT);
+#endif
 
 	OUT_RING(CP_PACKET3(R600_IT_NUM_INSTANCES, 0));
 	OUT_RING(1);
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/r600_blit_kms.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/r600_blit_kms.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/r600_blit_kms.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/r600_blit_kms.c	2011-03-14 21:20:32.000000000 -0400
@@ -54,7 +54,7 @@ set_render_target(struct radeon_device *
 	if (h < 8)
 		h = 8;
 
-	cb_color_info = ((format << 2) | (1 << 27));
+	cb_color_info = ((format << 2) | (1 << 27) | (1 << 8));
 	pitch = (w / 8) - 1;
 	slice = ((w * h) / 64) - 1;
 
@@ -165,6 +165,9 @@ set_vtx_resource(struct radeon_device *r
 	u32 sq_vtx_constant_word2;
 
 	sq_vtx_constant_word2 = ((upper_32_bits(gpu_addr) & 0xff) | (16 << 8));
+#ifdef __BIG_ENDIAN
+	sq_vtx_constant_word2 |= (2 << 30);
+#endif
 
 	radeon_ring_write(rdev, PACKET3(PACKET3_SET_RESOURCE, 7));
 	radeon_ring_write(rdev, 0x460);
@@ -199,7 +202,7 @@ set_tex_resource(struct radeon_device *r
 	if (h < 1)
 		h = 1;
 
-	sq_tex_resource_word0 = (1 << 0);
+	sq_tex_resource_word0 = (1 << 0) | (1 << 3);
 	sq_tex_resource_word0 |= ((((pitch >> 3) - 1) << 8) |
 				  ((w - 1) << 19));
 
@@ -253,7 +256,11 @@ draw_auto(struct radeon_device *rdev)
 	radeon_ring_write(rdev, DI_PT_RECTLIST);
 
 	radeon_ring_write(rdev, PACKET3(PACKET3_INDEX_TYPE, 0));
-	radeon_ring_write(rdev, DI_INDEX_SIZE_16_BIT);
+	radeon_ring_write(rdev,
+#ifdef __BIG_ENDIAN
+			  (2 << 2) |
+#endif
+			  DI_INDEX_SIZE_16_BIT);
 
 	radeon_ring_write(rdev, PACKET3(PACKET3_NUM_INSTANCES, 0));
 	radeon_ring_write(rdev, 1);
@@ -424,7 +431,11 @@ set_default_state(struct radeon_device *
 	dwords = ALIGN(rdev->r600_blit.state_len, 0x10);
 	gpu_addr = rdev->r600_blit.shader_gpu_addr + rdev->r600_blit.state_offset;
 	radeon_ring_write(rdev, PACKET3(PACKET3_INDIRECT_BUFFER, 2));
-	radeon_ring_write(rdev, gpu_addr & 0xFFFFFFFC);
+	radeon_ring_write(rdev,
+#ifdef __BIG_ENDIAN
+			  (2 << 0) |
+#endif
+			  (gpu_addr & 0xFFFFFFFC));
 	radeon_ring_write(rdev, upper_32_bits(gpu_addr) & 0xFF);
 	radeon_ring_write(rdev, dwords);
 
@@ -467,7 +478,7 @@ static inline uint32_t i2f(uint32_t inpu
 int r600_blit_init(struct radeon_device *rdev)
 {
 	u32 obj_size;
-	int r, dwords;
+	int i, r, dwords;
 	void *ptr;
 	u32 packet2s[16];
 	int num_packet2s = 0;
@@ -486,7 +497,7 @@ int r600_blit_init(struct radeon_device
 
 	dwords = rdev->r600_blit.state_len;
 	while (dwords & 0xf) {
-		packet2s[num_packet2s++] = PACKET2(0);
+		packet2s[num_packet2s++] = cpu_to_le32(PACKET2(0));
 		dwords++;
 	}
 
@@ -529,8 +540,10 @@ int r600_blit_init(struct radeon_device
 	if (num_packet2s)
 		memcpy_toio(ptr + rdev->r600_blit.state_offset + (rdev->r600_blit.state_len * 4),
 			    packet2s, num_packet2s * 4);
-	memcpy(ptr + rdev->r600_blit.vs_offset, r6xx_vs, r6xx_vs_size * 4);
-	memcpy(ptr + rdev->r600_blit.ps_offset, r6xx_ps, r6xx_ps_size * 4);
+	for (i = 0; i < r6xx_vs_size; i++)
+		*(u32 *)((unsigned long)ptr + rdev->r600_blit.vs_offset + i * 4) = cpu_to_le32(r6xx_vs[i]);
+	for (i = 0; i < r6xx_ps_size; i++)
+		*(u32 *)((unsigned long)ptr + rdev->r600_blit.ps_offset + i * 4) = cpu_to_le32(r6xx_ps[i]);
 	radeon_bo_kunmap(rdev->r600_blit.shader_obj);
 	radeon_bo_unreserve(rdev->r600_blit.shader_obj);
 
@@ -545,7 +558,7 @@ done:
 		dev_err(rdev->dev, "(%d) pin blit object failed\n", r);
 		return r;
 	}
-	rdev->mc.active_vram_size = rdev->mc.real_vram_size;
+	radeon_ttm_set_active_vram_size(rdev, rdev->mc.real_vram_size);
 	return 0;
 }
 
@@ -553,7 +566,7 @@ void r600_blit_fini(struct radeon_device
 {
 	int r;
 
-	rdev->mc.active_vram_size = rdev->mc.visible_vram_size;
+	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
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/r600_blit_shaders.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/r600_blit_shaders.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/r600_blit_shaders.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/r600_blit_shaders.c	2011-03-14 21:20:32.000000000 -0400
@@ -684,7 +684,11 @@ const u32 r6xx_vs[] =
 	0x00000000,
 	0x3c000000,
 	0x68cd1000,
+#ifdef __BIG_ENDIAN
+	0x000a0000,
+#else
 	0x00080000,
+#endif
 	0x00000000,
 };
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/r600.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/r600.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/r600.c	2013-05-03 03:54:50.000000000 -0400
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/r600.c	2013-05-03 01:54:02.000000000 -0400
@@ -58,14 +58,19 @@ int r600_mc_wait_for_idle(struct radeon_
 void r600_gpu_init(struct radeon_device *rdev);
 void r600_fini(struct radeon_device *rdev);
 void r600_irq_disable(struct radeon_device *rdev);
+static void r600_pcie_gen2_enable(struct radeon_device *rdev);
 
 /* get temperature in millidegrees */
-u32 rv6xx_get_temp(struct radeon_device *rdev)
+int rv6xx_get_temp(struct radeon_device *rdev)
 {
 	u32 temp = (RREG32(CG_THERMAL_STATUS) & ASIC_T_MASK) >>
 		ASIC_T_SHIFT;
+	int actual_temp = temp & 0xff;
 
-	return temp * 1000;
+	if (temp & 0x100)
+		actual_temp -= 256;
+
+	return actual_temp * 1000;
 }
 
 void r600_pm_get_dynpm_state(struct radeon_device *rdev)
@@ -1131,7 +1136,7 @@ static void r600_mc_program(struct radeo
  * Note: GTT start, end, size should be initialized before calling this
  * function on AGP platform.
  */
-void r600_vram_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc)
+static void r600_vram_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc)
 {
 	u64 size_bf, size_af;
 
@@ -1214,7 +1219,6 @@ int r600_mc_init(struct radeon_device *r
 	rdev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE);
 	rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE);
 	rdev->mc.visible_vram_size = rdev->mc.aper_size;
-	rdev->mc.active_vram_size = rdev->mc.visible_vram_size;
 	r600_vram_gtt_location(rdev, &rdev->mc);
 
 	if (rdev->flags & RADEON_IS_IGP) {
@@ -1250,6 +1254,9 @@ int r600_gpu_soft_reset(struct radeon_de
 			S_008014_CB2_BUSY(1) | S_008014_CB3_BUSY(1);
 	u32 tmp;
 
+	if (!(RREG32(GRBM_STATUS) & GUI_ACTIVE))
+		return 0;
+
 	dev_info(rdev->dev, "GPU softreset \n");
 	dev_info(rdev->dev, "  R_008010_GRBM_STATUS=0x%08X\n",
 		RREG32(R_008010_GRBM_STATUS));
@@ -1893,7 +1900,7 @@ void r600_pciep_wreg(struct radeon_devic
  */
 void r600_cp_stop(struct radeon_device *rdev)
 {
-	rdev->mc.active_vram_size = rdev->mc.visible_vram_size;
+	radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size);
 	WREG32(R_0086D8_CP_ME_CNTL, S_0086D8_CP_ME_HALT(1));
 	WREG32(SCRATCH_UMSK, 0);
 }
@@ -1976,6 +1983,10 @@ int r600_init_microcode(struct radeon_de
 		chip_name = "CYPRESS";
 		rlc_chip_name = "CYPRESS";
 		break;
+	case CHIP_PALM:
+		chip_name = "PALM";
+		rlc_chip_name = "SUMO";
+		break;
 	default: BUG();
 	}
 
@@ -2057,7 +2068,11 @@ static int r600_cp_load_microcode(struct
 
 	r600_cp_stop(rdev);
 
-	WREG32(CP_RB_CNTL, RB_NO_UPDATE | RB_BLKSZ(15) | RB_BUFSZ(3));
+	WREG32(CP_RB_CNTL,
+#ifdef __BIG_ENDIAN
+	       BUF_SWAP_32BIT |
+#endif
+	       RB_NO_UPDATE | RB_BLKSZ(15) | RB_BUFSZ(3));
 
 	/* Reset cp */
 	WREG32(GRBM_SOFT_RESET, SOFT_RESET_CP);
@@ -2144,7 +2159,11 @@ int r600_cp_resume(struct radeon_device
 	WREG32(CP_RB_WPTR, 0);
 
 	/* set the wb address whether it's enabled or not */
-	WREG32(CP_RB_RPTR_ADDR, (rdev->wb.gpu_addr + RADEON_WB_CP_RPTR_OFFSET) & 0xFFFFFFFC);
+	WREG32(CP_RB_RPTR_ADDR,
+#ifdef __BIG_ENDIAN
+	       RB_RPTR_SWAP(2) |
+#endif
+	       ((rdev->wb.gpu_addr + RADEON_WB_CP_RPTR_OFFSET) & 0xFFFFFFFC));
 	WREG32(CP_RB_RPTR_ADDR_HI, upper_32_bits(rdev->wb.gpu_addr + RADEON_WB_CP_RPTR_OFFSET) & 0xFF);
 	WREG32(SCRATCH_ADDR, ((rdev->wb.gpu_addr + RADEON_WB_SCRATCH_OFFSET) >> 8) & 0xFFFFFFFF);
 
@@ -2317,28 +2336,13 @@ void r600_clear_surface_reg(struct radeo
 	/* FIXME: implement */
 }
 
-
-bool r600_card_posted(struct radeon_device *rdev)
-{
-	uint32_t reg;
-
-	/* first check CRTCs */
-	reg = RREG32(D1CRTC_CONTROL) |
-		RREG32(D2CRTC_CONTROL);
-	if (reg & CRTC_EN)
-		return true;
-
-	/* then check MEM_SIZE, in case the crtcs are off */
-	if (RREG32(CONFIG_MEMSIZE))
-		return true;
-
-	return false;
-}
-
 int r600_startup(struct radeon_device *rdev)
 {
 	int r;
 
+	/* enable pcie gen2 link */
+	r600_pcie_gen2_enable(rdev);
+
 	if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw) {
 		r = r600_init_microcode(rdev);
 		if (r) {
@@ -2492,7 +2496,7 @@ int r600_init(struct radeon_device *rdev
 	if (r)
 		return r;
 	/* Post card if necessary */
-	if (!r600_card_posted(rdev)) {
+	if (!radeon_card_posted(rdev)) {
 		if (!rdev->bios) {
 			dev_err(rdev->dev, "Card not posted and no BIOS - ignoring\n");
 			return -EINVAL;
@@ -2595,7 +2599,11 @@ void r600_ring_ib_execute(struct radeon_
 {
 	/* FIXME: implement */
 	radeon_ring_write(rdev, PACKET3(PACKET3_INDIRECT_BUFFER, 2));
-	radeon_ring_write(rdev, ib->gpu_addr & 0xFFFFFFFC);
+	radeon_ring_write(rdev,
+#ifdef __BIG_ENDIAN
+			  (2 << 0) |
+#endif
+			  (ib->gpu_addr & 0xFFFFFFFC));
 	radeon_ring_write(rdev, upper_32_bits(ib->gpu_addr) & 0xFF);
 	radeon_ring_write(rdev, ib->length_dw);
 }
@@ -2841,6 +2849,8 @@ static void r600_disable_interrupt_state
 	WREG32(CP_INT_CNTL, CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE);
 	WREG32(GRBM_INT_CNTL, 0);
 	WREG32(DxMODE_INT_MASK, 0);
+	WREG32(D1GRPH_INTERRUPT_CONTROL, 0);
+	WREG32(D2GRPH_INTERRUPT_CONTROL, 0);
 	if (ASIC_IS_DCE3(rdev)) {
 		WREG32(DCE3_DACA_AUTODETECT_INT_CONTROL, 0);
 		WREG32(DCE3_DACB_AUTODETECT_INT_CONTROL, 0);
@@ -2965,6 +2975,7 @@ int r600_irq_set(struct radeon_device *r
 	u32 hpd1, hpd2, hpd3, hpd4 = 0, hpd5 = 0, hpd6 = 0;
 	u32 grbm_int_cntl = 0;
 	u32 hdmi1, hdmi2;
+	u32 d1grph = 0, d2grph = 0;
 
 	if (!rdev->irq.installed) {
 		WARN(1, "Can't enable IRQ/MSI because no handler is installed\n");
@@ -3001,11 +3012,13 @@ int r600_irq_set(struct radeon_device *r
 		cp_int_cntl |= RB_INT_ENABLE;
 		cp_int_cntl |= TIME_STAMP_INT_ENABLE;
 	}
-	if (rdev->irq.crtc_vblank_int[0]) {
+	if (rdev->irq.crtc_vblank_int[0] ||
+	    rdev->irq.pflip[0]) {
 		DRM_DEBUG("r600_irq_set: vblank 0\n");
 		mode_int |= D1MODE_VBLANK_INT_MASK;
 	}
-	if (rdev->irq.crtc_vblank_int[1]) {
+	if (rdev->irq.crtc_vblank_int[1] ||
+	    rdev->irq.pflip[1]) {
 		DRM_DEBUG("r600_irq_set: vblank 1\n");
 		mode_int |= D2MODE_VBLANK_INT_MASK;
 	}
@@ -3048,6 +3061,8 @@ int r600_irq_set(struct radeon_device *r
 
 	WREG32(CP_INT_CNTL, cp_int_cntl);
 	WREG32(DxMODE_INT_MASK, mode_int);
+	WREG32(D1GRPH_INTERRUPT_CONTROL, d1grph);
+	WREG32(D2GRPH_INTERRUPT_CONTROL, d2grph);
 	WREG32(GRBM_INT_CNTL, grbm_int_cntl);
 	WREG32(R600_HDMI_BLOCK1 + R600_HDMI_CNTL, hdmi1);
 	if (ASIC_IS_DCE3(rdev)) {
@@ -3070,32 +3085,35 @@ int r600_irq_set(struct radeon_device *r
 	return 0;
 }
 
-static inline void r600_irq_ack(struct radeon_device *rdev,
-				u32 *disp_int,
-				u32 *disp_int_cont,
-				u32 *disp_int_cont2)
+static inline void r600_irq_ack(struct radeon_device *rdev)
 {
 	u32 tmp;
 
 	if (ASIC_IS_DCE3(rdev)) {
-		*disp_int = RREG32(DCE3_DISP_INTERRUPT_STATUS);
-		*disp_int_cont = RREG32(DCE3_DISP_INTERRUPT_STATUS_CONTINUE);
-		*disp_int_cont2 = RREG32(DCE3_DISP_INTERRUPT_STATUS_CONTINUE2);
+		rdev->irq.stat_regs.r600.disp_int = RREG32(DCE3_DISP_INTERRUPT_STATUS);
+		rdev->irq.stat_regs.r600.disp_int_cont = RREG32(DCE3_DISP_INTERRUPT_STATUS_CONTINUE);
+		rdev->irq.stat_regs.r600.disp_int_cont2 = RREG32(DCE3_DISP_INTERRUPT_STATUS_CONTINUE2);
 	} else {
-		*disp_int = RREG32(DISP_INTERRUPT_STATUS);
-		*disp_int_cont = RREG32(DISP_INTERRUPT_STATUS_CONTINUE);
-		*disp_int_cont2 = 0;
+		rdev->irq.stat_regs.r600.disp_int = RREG32(DISP_INTERRUPT_STATUS);
+		rdev->irq.stat_regs.r600.disp_int_cont = RREG32(DISP_INTERRUPT_STATUS_CONTINUE);
+		rdev->irq.stat_regs.r600.disp_int_cont2 = 0;
 	}
+	rdev->irq.stat_regs.r600.d1grph_int = RREG32(D1GRPH_INTERRUPT_STATUS);
+	rdev->irq.stat_regs.r600.d2grph_int = RREG32(D2GRPH_INTERRUPT_STATUS);
 
-	if (*disp_int & LB_D1_VBLANK_INTERRUPT)
+	if (rdev->irq.stat_regs.r600.d1grph_int & DxGRPH_PFLIP_INT_OCCURRED)
+		WREG32(D1GRPH_INTERRUPT_STATUS, DxGRPH_PFLIP_INT_CLEAR);
+	if (rdev->irq.stat_regs.r600.d2grph_int & DxGRPH_PFLIP_INT_OCCURRED)
+		WREG32(D2GRPH_INTERRUPT_STATUS, DxGRPH_PFLIP_INT_CLEAR);
+	if (rdev->irq.stat_regs.r600.disp_int & LB_D1_VBLANK_INTERRUPT)
 		WREG32(D1MODE_VBLANK_STATUS, DxMODE_VBLANK_ACK);
-	if (*disp_int & LB_D1_VLINE_INTERRUPT)
+	if (rdev->irq.stat_regs.r600.disp_int & LB_D1_VLINE_INTERRUPT)
 		WREG32(D1MODE_VLINE_STATUS, DxMODE_VLINE_ACK);
-	if (*disp_int & LB_D2_VBLANK_INTERRUPT)
+	if (rdev->irq.stat_regs.r600.disp_int & LB_D2_VBLANK_INTERRUPT)
 		WREG32(D2MODE_VBLANK_STATUS, DxMODE_VBLANK_ACK);
-	if (*disp_int & LB_D2_VLINE_INTERRUPT)
+	if (rdev->irq.stat_regs.r600.disp_int & LB_D2_VLINE_INTERRUPT)
 		WREG32(D2MODE_VLINE_STATUS, DxMODE_VLINE_ACK);
-	if (*disp_int & DC_HPD1_INTERRUPT) {
+	if (rdev->irq.stat_regs.r600.disp_int & DC_HPD1_INTERRUPT) {
 		if (ASIC_IS_DCE3(rdev)) {
 			tmp = RREG32(DC_HPD1_INT_CONTROL);
 			tmp |= DC_HPDx_INT_ACK;
@@ -3106,7 +3124,7 @@ static inline void r600_irq_ack(struct r
 			WREG32(DC_HOT_PLUG_DETECT1_INT_CONTROL, tmp);
 		}
 	}
-	if (*disp_int & DC_HPD2_INTERRUPT) {
+	if (rdev->irq.stat_regs.r600.disp_int & DC_HPD2_INTERRUPT) {
 		if (ASIC_IS_DCE3(rdev)) {
 			tmp = RREG32(DC_HPD2_INT_CONTROL);
 			tmp |= DC_HPDx_INT_ACK;
@@ -3117,7 +3135,7 @@ static inline void r600_irq_ack(struct r
 			WREG32(DC_HOT_PLUG_DETECT2_INT_CONTROL, tmp);
 		}
 	}
-	if (*disp_int_cont & DC_HPD3_INTERRUPT) {
+	if (rdev->irq.stat_regs.r600.disp_int_cont & DC_HPD3_INTERRUPT) {
 		if (ASIC_IS_DCE3(rdev)) {
 			tmp = RREG32(DC_HPD3_INT_CONTROL);
 			tmp |= DC_HPDx_INT_ACK;
@@ -3128,18 +3146,18 @@ static inline void r600_irq_ack(struct r
 			WREG32(DC_HOT_PLUG_DETECT3_INT_CONTROL, tmp);
 		}
 	}
-	if (*disp_int_cont & DC_HPD4_INTERRUPT) {
+	if (rdev->irq.stat_regs.r600.disp_int_cont & DC_HPD4_INTERRUPT) {
 		tmp = RREG32(DC_HPD4_INT_CONTROL);
 		tmp |= DC_HPDx_INT_ACK;
 		WREG32(DC_HPD4_INT_CONTROL, tmp);
 	}
 	if (ASIC_IS_DCE32(rdev)) {
-		if (*disp_int_cont2 & DC_HPD5_INTERRUPT) {
+		if (rdev->irq.stat_regs.r600.disp_int_cont2 & DC_HPD5_INTERRUPT) {
 			tmp = RREG32(DC_HPD5_INT_CONTROL);
 			tmp |= DC_HPDx_INT_ACK;
 			WREG32(DC_HPD5_INT_CONTROL, tmp);
 		}
-		if (*disp_int_cont2 & DC_HPD6_INTERRUPT) {
+		if (rdev->irq.stat_regs.r600.disp_int_cont2 & DC_HPD6_INTERRUPT) {
 			tmp = RREG32(DC_HPD5_INT_CONTROL);
 			tmp |= DC_HPDx_INT_ACK;
 			WREG32(DC_HPD6_INT_CONTROL, tmp);
@@ -3161,12 +3179,10 @@ static inline void r600_irq_ack(struct r
 
 void r600_irq_disable(struct radeon_device *rdev)
 {
-	u32 disp_int, disp_int_cont, disp_int_cont2;
-
 	r600_disable_interrupts(rdev);
 	/* Wait and acknowledge irq */
 	mdelay(1);
-	r600_irq_ack(rdev, &disp_int, &disp_int_cont, &disp_int_cont2);
+	r600_irq_ack(rdev);
 	r600_disable_interrupt_state(rdev);
 }
 
@@ -3229,7 +3245,7 @@ int r600_irq_process(struct radeon_devic
 	u32 wptr = r600_get_ih_wptr(rdev);
 	u32 rptr = rdev->ih.rptr;
 	u32 src_id, src_data;
-	u32 ring_index, disp_int, disp_int_cont, disp_int_cont2;
+	u32 ring_index;
 	unsigned long flags;
 	bool queue_hotplug = false;
 
@@ -3250,30 +3266,34 @@ int r600_irq_process(struct radeon_devic
 
 restart_ih:
 	/* display interrupts */
-	r600_irq_ack(rdev, &disp_int, &disp_int_cont, &disp_int_cont2);
+	r600_irq_ack(rdev);
 
 	rdev->ih.wptr = wptr;
 	while (rptr != wptr) {
 		/* wptr/rptr are in bytes! */
 		ring_index = rptr / 4;
-		src_id =  rdev->ih.ring[ring_index] & 0xff;
-		src_data = rdev->ih.ring[ring_index + 1] & 0xfffffff;
+		src_id = le32_to_cpu(rdev->ih.ring[ring_index]) & 0xff;
+		src_data = le32_to_cpu(rdev->ih.ring[ring_index + 1]) & 0xfffffff;
 
 		switch (src_id) {
 		case 1: /* D1 vblank/vline */
 			switch (src_data) {
 			case 0: /* D1 vblank */
-				if (disp_int & LB_D1_VBLANK_INTERRUPT) {
-					drm_handle_vblank(rdev->ddev, 0);
-					rdev->pm.vblank_sync = true;
-					wake_up(&rdev->irq.vblank_queue);
-					disp_int &= ~LB_D1_VBLANK_INTERRUPT;
+				if (rdev->irq.stat_regs.r600.disp_int & LB_D1_VBLANK_INTERRUPT) {
+					if (rdev->irq.crtc_vblank_int[0]) {
+						drm_handle_vblank(rdev->ddev, 0);
+						rdev->pm.vblank_sync = true;
+						wake_up(&rdev->irq.vblank_queue);
+					}
+					if (rdev->irq.pflip[0])
+						radeon_crtc_handle_flip(rdev, 0);
+					rdev->irq.stat_regs.r600.disp_int &= ~LB_D1_VBLANK_INTERRUPT;
 					DRM_DEBUG("IH: D1 vblank\n");
 				}
 				break;
 			case 1: /* D1 vline */
-				if (disp_int & LB_D1_VLINE_INTERRUPT) {
-					disp_int &= ~LB_D1_VLINE_INTERRUPT;
+				if (rdev->irq.stat_regs.r600.disp_int & LB_D1_VLINE_INTERRUPT) {
+					rdev->irq.stat_regs.r600.disp_int &= ~LB_D1_VLINE_INTERRUPT;
 					DRM_DEBUG("IH: D1 vline\n");
 				}
 				break;
@@ -3285,17 +3305,21 @@ restart_ih:
 		case 5: /* D2 vblank/vline */
 			switch (src_data) {
 			case 0: /* D2 vblank */
-				if (disp_int & LB_D2_VBLANK_INTERRUPT) {
-					drm_handle_vblank(rdev->ddev, 1);
-					rdev->pm.vblank_sync = true;
-					wake_up(&rdev->irq.vblank_queue);
-					disp_int &= ~LB_D2_VBLANK_INTERRUPT;
+				if (rdev->irq.stat_regs.r600.disp_int & LB_D2_VBLANK_INTERRUPT) {
+					if (rdev->irq.crtc_vblank_int[1]) {
+						drm_handle_vblank(rdev->ddev, 1);
+						rdev->pm.vblank_sync = true;
+						wake_up(&rdev->irq.vblank_queue);
+					}
+					if (rdev->irq.pflip[1])
+						radeon_crtc_handle_flip(rdev, 1);
+					rdev->irq.stat_regs.r600.disp_int &= ~LB_D2_VBLANK_INTERRUPT;
 					DRM_DEBUG("IH: D2 vblank\n");
 				}
 				break;
 			case 1: /* D1 vline */
-				if (disp_int & LB_D2_VLINE_INTERRUPT) {
-					disp_int &= ~LB_D2_VLINE_INTERRUPT;
+				if (rdev->irq.stat_regs.r600.disp_int & LB_D2_VLINE_INTERRUPT) {
+					rdev->irq.stat_regs.r600.disp_int &= ~LB_D2_VLINE_INTERRUPT;
 					DRM_DEBUG("IH: D2 vline\n");
 				}
 				break;
@@ -3307,43 +3331,43 @@ restart_ih:
 		case 19: /* HPD/DAC hotplug */
 			switch (src_data) {
 			case 0:
-				if (disp_int & DC_HPD1_INTERRUPT) {
-					disp_int &= ~DC_HPD1_INTERRUPT;
+				if (rdev->irq.stat_regs.r600.disp_int & DC_HPD1_INTERRUPT) {
+					rdev->irq.stat_regs.r600.disp_int &= ~DC_HPD1_INTERRUPT;
 					queue_hotplug = true;
 					DRM_DEBUG("IH: HPD1\n");
 				}
 				break;
 			case 1:
-				if (disp_int & DC_HPD2_INTERRUPT) {
-					disp_int &= ~DC_HPD2_INTERRUPT;
+				if (rdev->irq.stat_regs.r600.disp_int & DC_HPD2_INTERRUPT) {
+					rdev->irq.stat_regs.r600.disp_int &= ~DC_HPD2_INTERRUPT;
 					queue_hotplug = true;
 					DRM_DEBUG("IH: HPD2\n");
 				}
 				break;
 			case 4:
-				if (disp_int_cont & DC_HPD3_INTERRUPT) {
-					disp_int_cont &= ~DC_HPD3_INTERRUPT;
+				if (rdev->irq.stat_regs.r600.disp_int_cont & DC_HPD3_INTERRUPT) {
+					rdev->irq.stat_regs.r600.disp_int_cont &= ~DC_HPD3_INTERRUPT;
 					queue_hotplug = true;
 					DRM_DEBUG("IH: HPD3\n");
 				}
 				break;
 			case 5:
-				if (disp_int_cont & DC_HPD4_INTERRUPT) {
-					disp_int_cont &= ~DC_HPD4_INTERRUPT;
+				if (rdev->irq.stat_regs.r600.disp_int_cont & DC_HPD4_INTERRUPT) {
+					rdev->irq.stat_regs.r600.disp_int_cont &= ~DC_HPD4_INTERRUPT;
 					queue_hotplug = true;
 					DRM_DEBUG("IH: HPD4\n");
 				}
 				break;
 			case 10:
-				if (disp_int_cont2 & DC_HPD5_INTERRUPT) {
-					disp_int_cont2 &= ~DC_HPD5_INTERRUPT;
+				if (rdev->irq.stat_regs.r600.disp_int_cont2 & DC_HPD5_INTERRUPT) {
+					rdev->irq.stat_regs.r600.disp_int_cont2 &= ~DC_HPD5_INTERRUPT;
 					queue_hotplug = true;
 					DRM_DEBUG("IH: HPD5\n");
 				}
 				break;
 			case 12:
-				if (disp_int_cont2 & DC_HPD6_INTERRUPT) {
-					disp_int_cont2 &= ~DC_HPD6_INTERRUPT;
+				if (rdev->irq.stat_regs.r600.disp_int_cont2 & DC_HPD6_INTERRUPT) {
+					rdev->irq.stat_regs.r600.disp_int_cont2 &= ~DC_HPD6_INTERRUPT;
 					queue_hotplug = true;
 					DRM_DEBUG("IH: HPD6\n");
 				}
@@ -3386,7 +3410,7 @@ restart_ih:
 	if (wptr != rdev->ih.wptr)
 		goto restart_ih;
 	if (queue_hotplug)
-		queue_work(rdev->wq, &rdev->hotplug_work);
+		schedule_work(&rdev->hotplug_work);
 	rdev->ih.rptr = rptr;
 	WREG32(IH_RB_RPTR, rdev->ih.rptr);
 	spin_unlock_irqrestore(&rdev->ih.lock, flags);
@@ -3475,3 +3499,222 @@ void r600_ioctl_wait_idle(struct radeon_
 	} else
 		WREG32(R_005480_HDP_MEM_COHERENCY_FLUSH_CNTL, 0x1);
 }
+
+void r600_set_pcie_lanes(struct radeon_device *rdev, int lanes)
+{
+	u32 link_width_cntl, mask, target_reg;
+
+	if (rdev->flags & RADEON_IS_IGP)
+		return;
+
+	if (!(rdev->flags & RADEON_IS_PCIE))
+		return;
+
+	/* x2 cards have a special sequence */
+	if (ASIC_IS_X2(rdev))
+		return;
+
+	/* FIXME wait for idle */
+
+	switch (lanes) {
+	case 0:
+		mask = RADEON_PCIE_LC_LINK_WIDTH_X0;
+		break;
+	case 1:
+		mask = RADEON_PCIE_LC_LINK_WIDTH_X1;
+		break;
+	case 2:
+		mask = RADEON_PCIE_LC_LINK_WIDTH_X2;
+		break;
+	case 4:
+		mask = RADEON_PCIE_LC_LINK_WIDTH_X4;
+		break;
+	case 8:
+		mask = RADEON_PCIE_LC_LINK_WIDTH_X8;
+		break;
+	case 12:
+		mask = RADEON_PCIE_LC_LINK_WIDTH_X12;
+		break;
+	case 16:
+	default:
+		mask = RADEON_PCIE_LC_LINK_WIDTH_X16;
+		break;
+	}
+
+	link_width_cntl = RREG32_PCIE_P(RADEON_PCIE_LC_LINK_WIDTH_CNTL);
+
+	if ((link_width_cntl & RADEON_PCIE_LC_LINK_WIDTH_RD_MASK) ==
+	    (mask << RADEON_PCIE_LC_LINK_WIDTH_RD_SHIFT))
+		return;
+
+	if (link_width_cntl & R600_PCIE_LC_UPCONFIGURE_DIS)
+		return;
+
+	link_width_cntl &= ~(RADEON_PCIE_LC_LINK_WIDTH_MASK |
+			     RADEON_PCIE_LC_RECONFIG_NOW |
+			     R600_PCIE_LC_RENEGOTIATE_EN |
+			     R600_PCIE_LC_RECONFIG_ARC_MISSING_ESCAPE);
+	link_width_cntl |= mask;
+
+	WREG32_PCIE_P(RADEON_PCIE_LC_LINK_WIDTH_CNTL, link_width_cntl);
+
+        /* some northbridges can renegotiate the link rather than requiring                                  
+         * a complete re-config.                                                                             
+         * e.g., AMD 780/790 northbridges (pci ids: 0x5956, 0x5957, 0x5958, etc.)                            
+         */
+        if (link_width_cntl & R600_PCIE_LC_RENEGOTIATION_SUPPORT)
+		link_width_cntl |= R600_PCIE_LC_RENEGOTIATE_EN | R600_PCIE_LC_UPCONFIGURE_SUPPORT;
+        else
+		link_width_cntl |= R600_PCIE_LC_RECONFIG_ARC_MISSING_ESCAPE;
+
+	WREG32_PCIE_P(RADEON_PCIE_LC_LINK_WIDTH_CNTL, (link_width_cntl |
+						       RADEON_PCIE_LC_RECONFIG_NOW));
+
+        if (rdev->family >= CHIP_RV770)
+		target_reg = R700_TARGET_AND_CURRENT_PROFILE_INDEX;
+        else
+		target_reg = R600_TARGET_AND_CURRENT_PROFILE_INDEX;
+
+        /* wait for lane set to complete */
+        link_width_cntl = RREG32(target_reg);
+        while (link_width_cntl == 0xffffffff)
+		link_width_cntl = RREG32(target_reg);
+
+}
+
+int r600_get_pcie_lanes(struct radeon_device *rdev)
+{
+	u32 link_width_cntl;
+
+	if (rdev->flags & RADEON_IS_IGP)
+		return 0;
+
+	if (!(rdev->flags & RADEON_IS_PCIE))
+		return 0;
+
+	/* x2 cards have a special sequence */
+	if (ASIC_IS_X2(rdev))
+		return 0;
+
+	/* FIXME wait for idle */
+
+	link_width_cntl = RREG32_PCIE_P(RADEON_PCIE_LC_LINK_WIDTH_CNTL);
+
+	switch ((link_width_cntl & RADEON_PCIE_LC_LINK_WIDTH_RD_MASK) >> RADEON_PCIE_LC_LINK_WIDTH_RD_SHIFT) {
+	case RADEON_PCIE_LC_LINK_WIDTH_X0:
+		return 0;
+	case RADEON_PCIE_LC_LINK_WIDTH_X1:
+		return 1;
+	case RADEON_PCIE_LC_LINK_WIDTH_X2:
+		return 2;
+	case RADEON_PCIE_LC_LINK_WIDTH_X4:
+		return 4;
+	case RADEON_PCIE_LC_LINK_WIDTH_X8:
+		return 8;
+	case RADEON_PCIE_LC_LINK_WIDTH_X16:
+	default:
+		return 16;
+	}
+}
+
+static void r600_pcie_gen2_enable(struct radeon_device *rdev)
+{
+	u32 link_width_cntl, lanes, speed_cntl, training_cntl, tmp;
+	u16 link_cntl2;
+
+	if (radeon_pcie_gen2 == 0)
+		return;
+
+	if (rdev->flags & RADEON_IS_IGP)
+		return;
+
+	if (!(rdev->flags & RADEON_IS_PCIE))
+		return;
+
+	/* x2 cards have a special sequence */
+	if (ASIC_IS_X2(rdev))
+		return;
+
+	/* only RV6xx+ chips are supported */
+	if (rdev->family <= CHIP_R600)
+		return;
+
+	/* 55 nm r6xx asics */
+	if ((rdev->family == CHIP_RV670) ||
+	    (rdev->family == CHIP_RV620) ||
+	    (rdev->family == CHIP_RV635)) {
+		/* advertise upconfig capability */
+		link_width_cntl = RREG32_PCIE_P(PCIE_LC_LINK_WIDTH_CNTL);
+		link_width_cntl &= ~LC_UPCONFIGURE_DIS;
+		WREG32_PCIE_P(PCIE_LC_LINK_WIDTH_CNTL, link_width_cntl);
+		link_width_cntl = RREG32_PCIE_P(PCIE_LC_LINK_WIDTH_CNTL);
+		if (link_width_cntl & LC_RENEGOTIATION_SUPPORT) {
+			lanes = (link_width_cntl & LC_LINK_WIDTH_RD_MASK) >> LC_LINK_WIDTH_RD_SHIFT;
+			link_width_cntl &= ~(LC_LINK_WIDTH_MASK |
+					     LC_RECONFIG_ARC_MISSING_ESCAPE);
+			link_width_cntl |= lanes | LC_RECONFIG_NOW | LC_RENEGOTIATE_EN;
+			WREG32_PCIE_P(PCIE_LC_LINK_WIDTH_CNTL, link_width_cntl);
+		} else {
+			link_width_cntl |= LC_UPCONFIGURE_DIS;
+			WREG32_PCIE_P(PCIE_LC_LINK_WIDTH_CNTL, link_width_cntl);
+		}
+	}
+
+	speed_cntl = RREG32_PCIE_P(PCIE_LC_SPEED_CNTL);
+	if ((speed_cntl & LC_OTHER_SIDE_EVER_SENT_GEN2) &&
+	    (speed_cntl & LC_OTHER_SIDE_SUPPORTS_GEN2)) {
+
+		/* 55 nm r6xx asics */
+		if ((rdev->family == CHIP_RV670) ||
+		    (rdev->family == CHIP_RV620) ||
+		    (rdev->family == CHIP_RV635)) {
+			WREG32(MM_CFGREGS_CNTL, 0x8);
+			link_cntl2 = RREG32(0x4088);
+			WREG32(MM_CFGREGS_CNTL, 0);
+			/* not supported yet */
+			if (link_cntl2 & SELECTABLE_DEEMPHASIS)
+				return;
+		}
+
+		speed_cntl &= ~LC_SPEED_CHANGE_ATTEMPTS_ALLOWED_MASK;
+		speed_cntl |= (0x3 << LC_SPEED_CHANGE_ATTEMPTS_ALLOWED_SHIFT);
+		speed_cntl &= ~LC_VOLTAGE_TIMER_SEL_MASK;
+		speed_cntl &= ~LC_FORCE_DIS_HW_SPEED_CHANGE;
+		speed_cntl |= LC_FORCE_EN_HW_SPEED_CHANGE;
+		WREG32_PCIE_P(PCIE_LC_SPEED_CNTL, speed_cntl);
+
+		tmp = RREG32(0x541c);
+		WREG32(0x541c, tmp | 0x8);
+		WREG32(MM_CFGREGS_CNTL, MM_WR_TO_CFG_EN);
+		link_cntl2 = RREG16(0x4088);
+		link_cntl2 &= ~TARGET_LINK_SPEED_MASK;
+		link_cntl2 |= 0x2;
+		WREG16(0x4088, link_cntl2);
+		WREG32(MM_CFGREGS_CNTL, 0);
+
+		if ((rdev->family == CHIP_RV670) ||
+		    (rdev->family == CHIP_RV620) ||
+		    (rdev->family == CHIP_RV635)) {
+			training_cntl = RREG32_PCIE_P(PCIE_LC_TRAINING_CNTL);
+			training_cntl &= ~LC_POINT_7_PLUS_EN;
+			WREG32_PCIE_P(PCIE_LC_TRAINING_CNTL, training_cntl);
+		} else {
+			speed_cntl = RREG32_PCIE_P(PCIE_LC_SPEED_CNTL);
+			speed_cntl &= ~LC_TARGET_LINK_SPEED_OVERRIDE_EN;
+			WREG32_PCIE_P(PCIE_LC_SPEED_CNTL, speed_cntl);
+		}
+
+		speed_cntl = RREG32_PCIE_P(PCIE_LC_SPEED_CNTL);
+		speed_cntl |= LC_GEN2_EN_STRAP;
+		WREG32_PCIE_P(PCIE_LC_SPEED_CNTL, speed_cntl);
+
+	} else {
+		link_width_cntl = RREG32_PCIE_P(PCIE_LC_LINK_WIDTH_CNTL);
+		/* XXX: only disable it if gen1 bridge vendor == 0x111d or 0x1106 */
+		if (1)
+			link_width_cntl |= LC_UPCONFIGURE_DIS;
+		else
+			link_width_cntl &= ~LC_UPCONFIGURE_DIS;
+		WREG32_PCIE_P(PCIE_LC_LINK_WIDTH_CNTL, link_width_cntl);
+	}
+}
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/r600_cp.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/r600_cp.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/r600_cp.c	2013-05-03 03:54:53.000000000 -0400
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/r600_cp.c	2013-05-03 01:54:07.000000000 -0400
@@ -377,6 +377,9 @@ static void r600_cp_load_microcode(drm_r
 	r600_do_cp_stop(dev_priv);
 
 	RADEON_WRITE(R600_CP_RB_CNTL,
+#ifdef __BIG_ENDIAN
+		     R600_BUF_SWAP_32BIT |
+#endif
 		     R600_RB_NO_UPDATE |
 		     R600_RB_BLKSZ(15) |
 		     R600_RB_BUFSZ(3));
@@ -467,9 +470,12 @@ static void r700_cp_load_microcode(drm_r
 	r600_do_cp_stop(dev_priv);
 
 	RADEON_WRITE(R600_CP_RB_CNTL,
+#ifdef __BIG_ENDIAN
+		     R600_BUF_SWAP_32BIT |
+#endif
 		     R600_RB_NO_UPDATE |
-		     (15 << 8) |
-		     (3 << 0));
+		     R600_RB_BLKSZ(15) |
+		     R600_RB_BUFSZ(3));
 
 	RADEON_WRITE(R600_GRBM_SOFT_RESET, R600_SOFT_RESET_CP);
 	RADEON_READ(R600_GRBM_SOFT_RESET);
@@ -531,8 +537,12 @@ static void r600_test_writeback(drm_rade
 
 	if (!dev_priv->writeback_works) {
 		/* Disable writeback to avoid unnecessary bus master transfer */
-		RADEON_WRITE(R600_CP_RB_CNTL, RADEON_READ(R600_CP_RB_CNTL) |
-			     RADEON_RB_NO_UPDATE);
+		RADEON_WRITE(R600_CP_RB_CNTL,
+#ifdef __BIG_ENDIAN
+			     R600_BUF_SWAP_32BIT |
+#endif
+			     RADEON_READ(R600_CP_RB_CNTL) |
+			     R600_RB_NO_UPDATE);
 		RADEON_WRITE(R600_SCRATCH_UMSK, 0);
 	}
 }
@@ -556,7 +566,11 @@ int r600_do_engine_reset(struct drm_devi
 
 	RADEON_WRITE(R600_CP_RB_WPTR_DELAY, 0);
 	cp_rb_cntl = RADEON_READ(R600_CP_RB_CNTL);
-	RADEON_WRITE(R600_CP_RB_CNTL, R600_RB_RPTR_WR_ENA);
+	RADEON_WRITE(R600_CP_RB_CNTL,
+#ifdef __BIG_ENDIAN
+		     R600_BUF_SWAP_32BIT |
+#endif
+		     R600_RB_RPTR_WR_ENA);
 
 	RADEON_WRITE(R600_CP_RB_RPTR_WR, cp_ptr);
 	RADEON_WRITE(R600_CP_RB_WPTR, cp_ptr);
@@ -1819,7 +1833,10 @@ static void r600_cp_init_ring_buffer(str
 			+ dev_priv->gart_vm_start;
 	}
 	RADEON_WRITE(R600_CP_RB_RPTR_ADDR,
-		     rptr_addr & 0xffffffff);
+#ifdef __BIG_ENDIAN
+		     (2 << 0) |
+#endif
+		     (rptr_addr & 0xfffffffc));
 	RADEON_WRITE(R600_CP_RB_RPTR_ADDR_HI,
 		     upper_32_bits(rptr_addr));
 
@@ -1870,7 +1887,7 @@ static void r600_cp_init_ring_buffer(str
 	{
 		u64 scratch_addr;
 
-		scratch_addr = RADEON_READ(R600_CP_RB_RPTR_ADDR);
+		scratch_addr = RADEON_READ(R600_CP_RB_RPTR_ADDR) & 0xFFFFFFFC;
 		scratch_addr |= ((u64)RADEON_READ(R600_CP_RB_RPTR_ADDR_HI)) << 32;
 		scratch_addr += R600_SCRATCH_REG_OFFSET;
 		scratch_addr >>= 8;
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/r600_cs.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/r600_cs.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/r600_cs.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/r600_cs.c	2011-03-14 21:20:32.000000000 -0400
@@ -295,17 +295,18 @@ static inline int r600_cs_track_validate
 	}
 
 	if (!IS_ALIGNED(pitch, pitch_align)) {
-		dev_warn(p->dev, "%s:%d cb pitch (%d) invalid\n",
-			 __func__, __LINE__, pitch);
+		dev_warn(p->dev, "%s:%d cb pitch (%d, 0x%x, %d) invalid\n",
+			 __func__, __LINE__, pitch, pitch_align, array_mode);
 		return -EINVAL;
 	}
 	if (!IS_ALIGNED(height, height_align)) {
-		dev_warn(p->dev, "%s:%d cb height (%d) invalid\n",
-			 __func__, __LINE__, height);
+		dev_warn(p->dev, "%s:%d cb height (%d, 0x%x, %d) invalid\n",
+			 __func__, __LINE__, height, height_align, array_mode);
 		return -EINVAL;
 	}
 	if (!IS_ALIGNED(base_offset, base_align)) {
-		dev_warn(p->dev, "%s offset[%d] 0x%llx not aligned\n", __func__, i, base_offset);
+		dev_warn(p->dev, "%s offset[%d] 0x%llx 0x%llx, %d not aligned\n", __func__, i,
+			 base_offset, base_align, array_mode);
 		return -EINVAL;
 	}
 
@@ -320,7 +321,10 @@ static inline int r600_cs_track_validate
 			 * broken userspace.
 			 */
 		} else {
-			dev_warn(p->dev, "%s offset[%d] %d %d %lu too big\n", __func__, i, track->cb_color_bo_offset[i], tmp, radeon_bo_size(track->cb_color_bo[i]));
+			dev_warn(p->dev, "%s offset[%d] %d %d %d %lu too big\n", __func__, i,
+				 array_mode,
+				 track->cb_color_bo_offset[i], tmp,
+				 radeon_bo_size(track->cb_color_bo[i]));
 			return -EINVAL;
 		}
 	}
@@ -455,17 +459,18 @@ static int r600_cs_track_check(struct ra
 			}
 
 			if (!IS_ALIGNED(pitch, pitch_align)) {
-				dev_warn(p->dev, "%s:%d db pitch (%d) invalid\n",
-					 __func__, __LINE__, pitch);
+				dev_warn(p->dev, "%s:%d db pitch (%d, 0x%x, %d) invalid\n",
+					 __func__, __LINE__, pitch, pitch_align, array_mode);
 				return -EINVAL;
 			}
 			if (!IS_ALIGNED(height, height_align)) {
-				dev_warn(p->dev, "%s:%d db height (%d) invalid\n",
-					 __func__, __LINE__, height);
+				dev_warn(p->dev, "%s:%d db height (%d, 0x%x, %d) invalid\n",
+					 __func__, __LINE__, height, height_align, array_mode);
 				return -EINVAL;
 			}
 			if (!IS_ALIGNED(base_offset, base_align)) {
-				dev_warn(p->dev, "%s offset[%d] 0x%llx not aligned\n", __func__, i, base_offset);
+				dev_warn(p->dev, "%s offset[%d] 0x%llx, 0x%llx, %d not aligned\n", __func__, i,
+					 base_offset, base_align, array_mode);
 				return -EINVAL;
 			}
 
@@ -473,9 +478,10 @@ static int r600_cs_track_check(struct ra
 			nviews = G_028004_SLICE_MAX(track->db_depth_view) + 1;
 			tmp = ntiles * bpe * 64 * nviews;
 			if ((tmp + track->db_offset) > radeon_bo_size(track->db_bo)) {
-				dev_warn(p->dev, "z/stencil buffer too small (0x%08X %d %d %d -> %u have %lu)\n",
-						track->db_depth_size, ntiles, nviews, bpe, tmp + track->db_offset,
-						radeon_bo_size(track->db_bo));
+				dev_warn(p->dev, "z/stencil buffer (%d) too small (0x%08X %d %d %d -> %u have %lu)\n",
+					 array_mode,
+					 track->db_depth_size, ntiles, nviews, bpe, tmp + track->db_offset,
+					 radeon_bo_size(track->db_bo));
 				return -EINVAL;
 			}
 		}
@@ -1227,18 +1233,18 @@ static inline int r600_check_texture_res
 	/* XXX check height as well... */
 
 	if (!IS_ALIGNED(pitch, pitch_align)) {
-		dev_warn(p->dev, "%s:%d tex pitch (%d) invalid\n",
-			 __func__, __LINE__, pitch);
+		dev_warn(p->dev, "%s:%d tex pitch (%d, 0x%x, %d) invalid\n",
+			 __func__, __LINE__, pitch, pitch_align, G_038000_TILE_MODE(word0));
 		return -EINVAL;
 	}
 	if (!IS_ALIGNED(base_offset, base_align)) {
-		dev_warn(p->dev, "%s:%d tex base offset (0x%llx) invalid\n",
-			 __func__, __LINE__, base_offset);
+		dev_warn(p->dev, "%s:%d tex base offset (0x%llx, 0x%llx, %d) invalid\n",
+			 __func__, __LINE__, base_offset, base_align, G_038000_TILE_MODE(word0));
 		return -EINVAL;
 	}
 	if (!IS_ALIGNED(mip_offset, base_align)) {
-		dev_warn(p->dev, "%s:%d tex mip offset (0x%llx) invalid\n",
-			 __func__, __LINE__, mip_offset);
+		dev_warn(p->dev, "%s:%d tex mip offset (0x%llx, 0x%llx, %d) invalid\n",
+			 __func__, __LINE__, mip_offset, base_align, G_038000_TILE_MODE(word0));
 		return -EINVAL;
 	}
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/r600d.h linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/r600d.h
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/r600d.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/r600d.h	2011-03-14 21:20:32.000000000 -0400
@@ -154,13 +154,14 @@
 #define		ROQ_IB2_START(x)				((x) << 8)
 #define	CP_RB_BASE					0xC100
 #define	CP_RB_CNTL					0xC104
-#define		RB_BUFSZ(x)					((x)<<0)
-#define		RB_BLKSZ(x)					((x)<<8)
-#define		RB_NO_UPDATE					(1<<27)
-#define		RB_RPTR_WR_ENA					(1<<31)
+#define		RB_BUFSZ(x)					((x) << 0)
+#define		RB_BLKSZ(x)					((x) << 8)
+#define		RB_NO_UPDATE					(1 << 27)
+#define		RB_RPTR_WR_ENA					(1 << 31)
 #define		BUF_SWAP_32BIT					(2 << 16)
 #define	CP_RB_RPTR					0x8700
 #define	CP_RB_RPTR_ADDR					0xC10C
+#define		RB_RPTR_SWAP(x)					((x) << 0)
 #define	CP_RB_RPTR_ADDR_HI				0xC110
 #define	CP_RB_RPTR_WR					0xC108
 #define	CP_RB_WPTR					0xC114
@@ -728,6 +729,54 @@
 /* DCE 3.2 */
 #       define DC_HPDx_EN                                 (1 << 28)
 
+#define D1GRPH_INTERRUPT_STATUS                           0x6158
+#define D2GRPH_INTERRUPT_STATUS                           0x6958
+#       define DxGRPH_PFLIP_INT_OCCURRED                  (1 << 0)
+#       define DxGRPH_PFLIP_INT_CLEAR                     (1 << 8)
+#define D1GRPH_INTERRUPT_CONTROL                          0x615c
+#define D2GRPH_INTERRUPT_CONTROL                          0x695c
+#       define DxGRPH_PFLIP_INT_MASK                      (1 << 0)
+#       define DxGRPH_PFLIP_INT_TYPE                      (1 << 8)
+
+/* PCIE link stuff */
+#define PCIE_LC_TRAINING_CNTL                             0xa1 /* PCIE_P */
+#       define LC_POINT_7_PLUS_EN                         (1 << 6)
+#define PCIE_LC_LINK_WIDTH_CNTL                           0xa2 /* PCIE_P */
+#       define LC_LINK_WIDTH_SHIFT                        0
+#       define LC_LINK_WIDTH_MASK                         0x7
+#       define LC_LINK_WIDTH_X0                           0
+#       define LC_LINK_WIDTH_X1                           1
+#       define LC_LINK_WIDTH_X2                           2
+#       define LC_LINK_WIDTH_X4                           3
+#       define LC_LINK_WIDTH_X8                           4
+#       define LC_LINK_WIDTH_X16                          6
+#       define LC_LINK_WIDTH_RD_SHIFT                     4
+#       define LC_LINK_WIDTH_RD_MASK                      0x70
+#       define LC_RECONFIG_ARC_MISSING_ESCAPE             (1 << 7)
+#       define LC_RECONFIG_NOW                            (1 << 8)
+#       define LC_RENEGOTIATION_SUPPORT                   (1 << 9)
+#       define LC_RENEGOTIATE_EN                          (1 << 10)
+#       define LC_SHORT_RECONFIG_EN                       (1 << 11)
+#       define LC_UPCONFIGURE_SUPPORT                     (1 << 12)
+#       define LC_UPCONFIGURE_DIS                         (1 << 13)
+#define PCIE_LC_SPEED_CNTL                                0xa4 /* PCIE_P */
+#       define LC_GEN2_EN_STRAP                           (1 << 0)
+#       define LC_TARGET_LINK_SPEED_OVERRIDE_EN           (1 << 1)
+#       define LC_FORCE_EN_HW_SPEED_CHANGE                (1 << 5)
+#       define LC_FORCE_DIS_HW_SPEED_CHANGE               (1 << 6)
+#       define LC_SPEED_CHANGE_ATTEMPTS_ALLOWED_MASK      (0x3 << 8)
+#       define LC_SPEED_CHANGE_ATTEMPTS_ALLOWED_SHIFT     3
+#       define LC_CURRENT_DATA_RATE                       (1 << 11)
+#       define LC_VOLTAGE_TIMER_SEL_MASK                  (0xf << 14)
+#       define LC_CLR_FAILED_SPD_CHANGE_CNT               (1 << 21)
+#       define LC_OTHER_SIDE_EVER_SENT_GEN2               (1 << 23)
+#       define LC_OTHER_SIDE_SUPPORTS_GEN2                (1 << 24)
+#define MM_CFGREGS_CNTL                                   0x544c
+#       define MM_WR_TO_CFG_EN                            (1 << 3)
+#define LINK_CNTL2                                        0x88 /* F0 */
+#       define TARGET_LINK_SPEED_MASK                     (0xf << 0)
+#       define SELECTABLE_DEEMPHASIS                      (1 << 6)
+
 /*
  * PM4
  */
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/r600_reg.h linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/r600_reg.h
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/r600_reg.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/r600_reg.h	2011-03-14 21:20:32.000000000 -0400
@@ -81,7 +81,11 @@
 #define R600_MEDIUM_VID_LOWER_GPIO_CNTL                            0x720
 #define R600_LOW_VID_LOWER_GPIO_CNTL                               0x724
 
-
+#define R600_D1GRPH_SWAP_CONTROL                               0x610C
+#       define R600_D1GRPH_SWAP_ENDIAN_NONE                    (0 << 0)
+#       define R600_D1GRPH_SWAP_ENDIAN_16BIT                   (1 << 0)
+#       define R600_D1GRPH_SWAP_ENDIAN_32BIT                   (2 << 0)
+#       define R600_D1GRPH_SWAP_ENDIAN_64BIT                   (3 << 0)
 
 #define R600_HDP_NONSURFACE_BASE                                0x2c04
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/radeon_asic.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/radeon_asic.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/radeon_asic.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/radeon_asic.c	2011-03-14 21:20:32.000000000 -0400
@@ -94,7 +94,7 @@ static void radeon_register_accessor_ini
 		rdev->mc_rreg = &rs600_mc_rreg;
 		rdev->mc_wreg = &rs600_mc_wreg;
 	}
-	if ((rdev->family >= CHIP_R600) && (rdev->family <= CHIP_RV740)) {
+	if ((rdev->family >= CHIP_R600) && (rdev->family <= CHIP_HEMLOCK)) {
 		rdev->pciep_rreg = &r600_pciep_rreg;
 		rdev->pciep_wreg = &r600_pciep_wreg;
 	}
@@ -171,6 +171,9 @@ static struct radeon_asic r100_asic = {
 	.pm_finish = &r100_pm_finish,
 	.pm_init_profile = &r100_pm_init_profile,
 	.pm_get_dynpm_state = &r100_pm_get_dynpm_state,
+	.pre_page_flip = &r100_pre_page_flip,
+	.page_flip = &r100_page_flip,
+	.post_page_flip = &r100_post_page_flip,
 };
 
 static struct radeon_asic r200_asic = {
@@ -215,6 +218,9 @@ static struct radeon_asic r200_asic = {
 	.pm_finish = &r100_pm_finish,
 	.pm_init_profile = &r100_pm_init_profile,
 	.pm_get_dynpm_state = &r100_pm_get_dynpm_state,
+	.pre_page_flip = &r100_pre_page_flip,
+	.page_flip = &r100_page_flip,
+	.post_page_flip = &r100_post_page_flip,
 };
 
 static struct radeon_asic r300_asic = {
@@ -260,6 +266,9 @@ static struct radeon_asic r300_asic = {
 	.pm_finish = &r100_pm_finish,
 	.pm_init_profile = &r100_pm_init_profile,
 	.pm_get_dynpm_state = &r100_pm_get_dynpm_state,
+	.pre_page_flip = &r100_pre_page_flip,
+	.page_flip = &r100_page_flip,
+	.post_page_flip = &r100_post_page_flip,
 };
 
 static struct radeon_asic r300_asic_pcie = {
@@ -304,6 +313,9 @@ static struct radeon_asic r300_asic_pcie
 	.pm_finish = &r100_pm_finish,
 	.pm_init_profile = &r100_pm_init_profile,
 	.pm_get_dynpm_state = &r100_pm_get_dynpm_state,
+	.pre_page_flip = &r100_pre_page_flip,
+	.page_flip = &r100_page_flip,
+	.post_page_flip = &r100_post_page_flip,
 };
 
 static struct radeon_asic r420_asic = {
@@ -349,6 +361,9 @@ static struct radeon_asic r420_asic = {
 	.pm_finish = &r100_pm_finish,
 	.pm_init_profile = &r420_pm_init_profile,
 	.pm_get_dynpm_state = &r100_pm_get_dynpm_state,
+	.pre_page_flip = &r100_pre_page_flip,
+	.page_flip = &r100_page_flip,
+	.post_page_flip = &r100_post_page_flip,
 };
 
 static struct radeon_asic rs400_asic = {
@@ -394,6 +409,9 @@ static struct radeon_asic rs400_asic = {
 	.pm_finish = &r100_pm_finish,
 	.pm_init_profile = &r100_pm_init_profile,
 	.pm_get_dynpm_state = &r100_pm_get_dynpm_state,
+	.pre_page_flip = &r100_pre_page_flip,
+	.page_flip = &r100_page_flip,
+	.post_page_flip = &r100_post_page_flip,
 };
 
 static struct radeon_asic rs600_asic = {
@@ -439,6 +457,9 @@ static struct radeon_asic rs600_asic = {
 	.pm_finish = &rs600_pm_finish,
 	.pm_init_profile = &r420_pm_init_profile,
 	.pm_get_dynpm_state = &r100_pm_get_dynpm_state,
+	.pre_page_flip = &rs600_pre_page_flip,
+	.page_flip = &rs600_page_flip,
+	.post_page_flip = &rs600_post_page_flip,
 };
 
 static struct radeon_asic rs690_asic = {
@@ -484,6 +505,9 @@ static struct radeon_asic rs690_asic = {
 	.pm_finish = &rs600_pm_finish,
 	.pm_init_profile = &r420_pm_init_profile,
 	.pm_get_dynpm_state = &r100_pm_get_dynpm_state,
+	.pre_page_flip = &rs600_pre_page_flip,
+	.page_flip = &rs600_page_flip,
+	.post_page_flip = &rs600_post_page_flip,
 };
 
 static struct radeon_asic rv515_asic = {
@@ -529,6 +553,9 @@ static struct radeon_asic rv515_asic = {
 	.pm_finish = &rs600_pm_finish,
 	.pm_init_profile = &r420_pm_init_profile,
 	.pm_get_dynpm_state = &r100_pm_get_dynpm_state,
+	.pre_page_flip = &rs600_pre_page_flip,
+	.page_flip = &rs600_page_flip,
+	.post_page_flip = &rs600_post_page_flip,
 };
 
 static struct radeon_asic r520_asic = {
@@ -574,6 +601,9 @@ static struct radeon_asic r520_asic = {
 	.pm_finish = &rs600_pm_finish,
 	.pm_init_profile = &r420_pm_init_profile,
 	.pm_get_dynpm_state = &r100_pm_get_dynpm_state,
+	.pre_page_flip = &rs600_pre_page_flip,
+	.page_flip = &rs600_page_flip,
+	.post_page_flip = &rs600_post_page_flip,
 };
 
 static struct radeon_asic r600_asic = {
@@ -601,8 +631,8 @@ static struct radeon_asic r600_asic = {
 	.set_engine_clock = &radeon_atom_set_engine_clock,
 	.get_memory_clock = &radeon_atom_get_memory_clock,
 	.set_memory_clock = &radeon_atom_set_memory_clock,
-	.get_pcie_lanes = &rv370_get_pcie_lanes,
-	.set_pcie_lanes = NULL,
+	.get_pcie_lanes = &r600_get_pcie_lanes,
+	.set_pcie_lanes = &r600_set_pcie_lanes,
 	.set_clock_gating = NULL,
 	.set_surface_reg = r600_set_surface_reg,
 	.clear_surface_reg = r600_clear_surface_reg,
@@ -618,6 +648,9 @@ static struct radeon_asic r600_asic = {
 	.pm_finish = &rs600_pm_finish,
 	.pm_init_profile = &r600_pm_init_profile,
 	.pm_get_dynpm_state = &r600_pm_get_dynpm_state,
+	.pre_page_flip = &rs600_pre_page_flip,
+	.page_flip = &rs600_page_flip,
+	.post_page_flip = &rs600_post_page_flip,
 };
 
 static struct radeon_asic rs780_asic = {
@@ -662,6 +695,9 @@ static struct radeon_asic rs780_asic = {
 	.pm_finish = &rs600_pm_finish,
 	.pm_init_profile = &rs780_pm_init_profile,
 	.pm_get_dynpm_state = &r600_pm_get_dynpm_state,
+	.pre_page_flip = &rs600_pre_page_flip,
+	.page_flip = &rs600_page_flip,
+	.post_page_flip = &rs600_post_page_flip,
 };
 
 static struct radeon_asic rv770_asic = {
@@ -689,8 +725,8 @@ static struct radeon_asic rv770_asic = {
 	.set_engine_clock = &radeon_atom_set_engine_clock,
 	.get_memory_clock = &radeon_atom_get_memory_clock,
 	.set_memory_clock = &radeon_atom_set_memory_clock,
-	.get_pcie_lanes = &rv370_get_pcie_lanes,
-	.set_pcie_lanes = NULL,
+	.get_pcie_lanes = &r600_get_pcie_lanes,
+	.set_pcie_lanes = &r600_set_pcie_lanes,
 	.set_clock_gating = &radeon_atom_set_clock_gating,
 	.set_surface_reg = r600_set_surface_reg,
 	.clear_surface_reg = r600_clear_surface_reg,
@@ -706,6 +742,9 @@ static struct radeon_asic rv770_asic = {
 	.pm_finish = &rs600_pm_finish,
 	.pm_init_profile = &r600_pm_init_profile,
 	.pm_get_dynpm_state = &r600_pm_get_dynpm_state,
+	.pre_page_flip = &rs600_pre_page_flip,
+	.page_flip = &rv770_page_flip,
+	.post_page_flip = &rs600_post_page_flip,
 };
 
 static struct radeon_asic evergreen_asic = {
@@ -720,7 +759,99 @@ static struct radeon_asic evergreen_asic
 	.gart_tlb_flush = &evergreen_pcie_gart_tlb_flush,
 	.gart_set_page = &rs600_gart_set_page,
 	.ring_test = &r600_ring_test,
-	.ring_ib_execute = &r600_ring_ib_execute,
+	.ring_ib_execute = &evergreen_ring_ib_execute,
+	.irq_set = &evergreen_irq_set,
+	.irq_process = &evergreen_irq_process,
+	.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_dma = &evergreen_copy_blit,
+	.copy = &evergreen_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,
+	.set_memory_clock = &radeon_atom_set_memory_clock,
+	.get_pcie_lanes = &r600_get_pcie_lanes,
+	.set_pcie_lanes = &r600_set_pcie_lanes,
+	.set_clock_gating = NULL,
+	.set_surface_reg = r600_set_surface_reg,
+	.clear_surface_reg = r600_clear_surface_reg,
+	.bandwidth_update = &evergreen_bandwidth_update,
+	.hpd_init = &evergreen_hpd_init,
+	.hpd_fini = &evergreen_hpd_fini,
+	.hpd_sense = &evergreen_hpd_sense,
+	.hpd_set_polarity = &evergreen_hpd_set_polarity,
+	.gui_idle = &r600_gui_idle,
+	.pm_misc = &evergreen_pm_misc,
+	.pm_prepare = &evergreen_pm_prepare,
+	.pm_finish = &evergreen_pm_finish,
+	.pm_init_profile = &r600_pm_init_profile,
+	.pm_get_dynpm_state = &r600_pm_get_dynpm_state,
+	.pre_page_flip = &evergreen_pre_page_flip,
+	.page_flip = &evergreen_page_flip,
+	.post_page_flip = &evergreen_post_page_flip,
+};
+
+static struct radeon_asic sumo_asic = {
+	.init = &evergreen_init,
+	.fini = &evergreen_fini,
+	.suspend = &evergreen_suspend,
+	.resume = &evergreen_resume,
+	.cp_commit = &r600_cp_commit,
+	.gpu_is_lockup = &evergreen_gpu_is_lockup,
+	.asic_reset = &evergreen_asic_reset,
+	.vga_set_state = &r600_vga_set_state,
+	.gart_tlb_flush = &evergreen_pcie_gart_tlb_flush,
+	.gart_set_page = &rs600_gart_set_page,
+	.ring_test = &r600_ring_test,
+	.ring_ib_execute = &evergreen_ring_ib_execute,
+	.irq_set = &evergreen_irq_set,
+	.irq_process = &evergreen_irq_process,
+	.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_dma = &evergreen_copy_blit,
+	.copy = &evergreen_copy_blit,
+	.get_engine_clock = &radeon_atom_get_engine_clock,
+	.set_engine_clock = &radeon_atom_set_engine_clock,
+	.get_memory_clock = NULL,
+	.set_memory_clock = NULL,
+	.get_pcie_lanes = NULL,
+	.set_pcie_lanes = NULL,
+	.set_clock_gating = NULL,
+	.set_surface_reg = r600_set_surface_reg,
+	.clear_surface_reg = r600_clear_surface_reg,
+	.bandwidth_update = &evergreen_bandwidth_update,
+	.hpd_init = &evergreen_hpd_init,
+	.hpd_fini = &evergreen_hpd_fini,
+	.hpd_sense = &evergreen_hpd_sense,
+	.hpd_set_polarity = &evergreen_hpd_set_polarity,
+	.gui_idle = &r600_gui_idle,
+	.pm_misc = &evergreen_pm_misc,
+	.pm_prepare = &evergreen_pm_prepare,
+	.pm_finish = &evergreen_pm_finish,
+	.pm_init_profile = &rs780_pm_init_profile,
+	.pm_get_dynpm_state = &r600_pm_get_dynpm_state,
+	.pre_page_flip = &evergreen_pre_page_flip,
+	.page_flip = &evergreen_page_flip,
+	.post_page_flip = &evergreen_post_page_flip,
+};
+
+static struct radeon_asic btc_asic = {
+	.init = &evergreen_init,
+	.fini = &evergreen_fini,
+	.suspend = &evergreen_suspend,
+	.resume = &evergreen_resume,
+	.cp_commit = &r600_cp_commit,
+	.gpu_is_lockup = &evergreen_gpu_is_lockup,
+	.asic_reset = &evergreen_asic_reset,
+	.vga_set_state = &r600_vga_set_state,
+	.gart_tlb_flush = &evergreen_pcie_gart_tlb_flush,
+	.gart_set_page = &rs600_gart_set_page,
+	.ring_test = &r600_ring_test,
+	.ring_ib_execute = &evergreen_ring_ib_execute,
 	.irq_set = &evergreen_irq_set,
 	.irq_process = &evergreen_irq_process,
 	.get_vblank_counter = &evergreen_get_vblank_counter,
@@ -749,6 +880,9 @@ static struct radeon_asic evergreen_asic
 	.pm_finish = &evergreen_pm_finish,
 	.pm_init_profile = &r600_pm_init_profile,
 	.pm_get_dynpm_state = &r600_pm_get_dynpm_state,
+	.pre_page_flip = &evergreen_pre_page_flip,
+	.page_flip = &evergreen_page_flip,
+	.post_page_flip = &evergreen_post_page_flip,
 };
 
 int radeon_asic_init(struct radeon_device *rdev)
@@ -835,6 +969,14 @@ int radeon_asic_init(struct radeon_devic
 	case CHIP_HEMLOCK:
 		rdev->asic = &evergreen_asic;
 		break;
+	case CHIP_PALM:
+		rdev->asic = &sumo_asic;
+		break;
+	case CHIP_BARTS:
+	case CHIP_TURKS:
+	case CHIP_CAICOS:
+		rdev->asic = &btc_asic;
+		break;
 	default:
 		/* FIXME: not supported yet */
 		return -EINVAL;
@@ -849,7 +991,9 @@ int radeon_asic_init(struct radeon_devic
 	if (rdev->flags & RADEON_SINGLE_CRTC)
 		rdev->num_crtc = 1;
 	else {
-		if (ASIC_IS_DCE4(rdev))
+		if (ASIC_IS_DCE41(rdev))
+			rdev->num_crtc = 2;
+		else if (ASIC_IS_DCE4(rdev))
 			rdev->num_crtc = 6;
 		else
 			rdev->num_crtc = 2;
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/radeon_asic.h linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/radeon_asic.h
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/radeon_asic.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/radeon_asic.h	2011-03-14 21:20:32.000000000 -0400
@@ -102,6 +102,11 @@ int r100_pci_gart_enable(struct radeon_d
 void r100_pci_gart_disable(struct radeon_device *rdev);
 int r100_debugfs_mc_info_init(struct radeon_device *rdev);
 int r100_gui_wait_for_idle(struct radeon_device *rdev);
+void r100_gpu_lockup_update(struct r100_gpu_lockup *lockup,
+			    struct radeon_cp *cp);
+bool r100_gpu_cp_is_lockup(struct radeon_device *rdev,
+			   struct r100_gpu_lockup *lockup,
+			   struct radeon_cp *cp);
 void r100_ib_fini(struct radeon_device *rdev);
 int r100_ib_init(struct radeon_device *rdev);
 void r100_irq_disable(struct radeon_device *rdev);
@@ -130,15 +135,19 @@ extern void r100_pm_prepare(struct radeo
 extern void r100_pm_finish(struct radeon_device *rdev);
 extern void r100_pm_init_profile(struct radeon_device *rdev);
 extern void r100_pm_get_dynpm_state(struct radeon_device *rdev);
+extern void r100_pre_page_flip(struct radeon_device *rdev, int crtc);
+extern u32 r100_page_flip(struct radeon_device *rdev, int crtc, u64 crtc_base);
+extern void r100_post_page_flip(struct radeon_device *rdev, int crtc);
 
 /*
  * r200,rv250,rs300,rv280
  */
 extern int r200_copy_dma(struct radeon_device *rdev,
-			uint64_t src_offset,
-			uint64_t dst_offset,
-			unsigned num_pages,
+			 uint64_t src_offset,
+			 uint64_t dst_offset,
+			 unsigned num_pages,
 			 struct radeon_fence *fence);
+void r200_set_safe_registers(struct radeon_device *rdev);
 
 /*
  * r300,r350,rv350,rv380
@@ -159,6 +168,15 @@ extern uint32_t rv370_pcie_rreg(struct r
 extern void rv370_pcie_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v);
 extern void rv370_set_pcie_lanes(struct radeon_device *rdev, int lanes);
 extern int rv370_get_pcie_lanes(struct radeon_device *rdev);
+extern void r300_set_reg_safe(struct radeon_device *rdev);
+extern void r300_mc_program(struct radeon_device *rdev);
+extern void r300_mc_init(struct radeon_device *rdev);
+extern void r300_clock_startup(struct radeon_device *rdev);
+extern int r300_mc_wait_for_idle(struct radeon_device *rdev);
+extern int rv370_pcie_gart_init(struct radeon_device *rdev);
+extern void rv370_pcie_gart_fini(struct radeon_device *rdev);
+extern int rv370_pcie_gart_enable(struct radeon_device *rdev);
+extern void rv370_pcie_gart_disable(struct radeon_device *rdev);
 
 /*
  * r420,r423,rv410
@@ -168,6 +186,10 @@ extern void r420_fini(struct radeon_devi
 extern int r420_suspend(struct radeon_device *rdev);
 extern int r420_resume(struct radeon_device *rdev);
 extern void r420_pm_init_profile(struct radeon_device *rdev);
+extern u32 r420_mc_rreg(struct radeon_device *rdev, u32 reg);
+extern void r420_mc_wreg(struct radeon_device *rdev, u32 reg, u32 v);
+extern int r420_debugfs_pipes_info_init(struct radeon_device *rdev);
+extern void r420_pipes_init(struct radeon_device *rdev);
 
 /*
  * rs400,rs480
@@ -180,6 +202,12 @@ void rs400_gart_tlb_flush(struct radeon_
 int rs400_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr);
 uint32_t rs400_mc_rreg(struct radeon_device *rdev, uint32_t reg);
 void rs400_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v);
+int rs400_gart_init(struct radeon_device *rdev);
+int rs400_gart_enable(struct radeon_device *rdev);
+void rs400_gart_adjust_size(struct radeon_device *rdev);
+void rs400_gart_disable(struct radeon_device *rdev);
+void rs400_gart_fini(struct radeon_device *rdev);
+
 
 /*
  * rs600.
@@ -191,6 +219,7 @@ extern int rs600_suspend(struct radeon_d
 extern int rs600_resume(struct radeon_device *rdev);
 int rs600_irq_set(struct radeon_device *rdev);
 int rs600_irq_process(struct radeon_device *rdev);
+void rs600_irq_disable(struct radeon_device *rdev);
 u32 rs600_get_vblank_counter(struct radeon_device *rdev, int crtc);
 void rs600_gart_tlb_flush(struct radeon_device *rdev);
 int rs600_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr);
@@ -205,6 +234,11 @@ void rs600_hpd_set_polarity(struct radeo
 extern void rs600_pm_misc(struct radeon_device *rdev);
 extern void rs600_pm_prepare(struct radeon_device *rdev);
 extern void rs600_pm_finish(struct radeon_device *rdev);
+extern void rs600_pre_page_flip(struct radeon_device *rdev, int crtc);
+extern u32 rs600_page_flip(struct radeon_device *rdev, int crtc, u64 crtc_base);
+extern void rs600_post_page_flip(struct radeon_device *rdev, int crtc);
+void rs600_set_safe_registers(struct radeon_device *rdev);
+
 
 /*
  * rs690,rs740
@@ -216,10 +250,21 @@ int rs690_suspend(struct radeon_device *
 uint32_t rs690_mc_rreg(struct radeon_device *rdev, uint32_t reg);
 void rs690_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v);
 void rs690_bandwidth_update(struct radeon_device *rdev);
+void rs690_line_buffer_adjust(struct radeon_device *rdev,
+					struct drm_display_mode *mode1,
+					struct drm_display_mode *mode2);
 
 /*
  * rv515
  */
+struct rv515_mc_save {
+	u32 d1vga_control;
+	u32 d2vga_control;
+	u32 vga_render_control;
+	u32 vga_hdp_control;
+	u32 d1crtc_control;
+	u32 d2crtc_control;
+};
 int rv515_init(struct radeon_device *rdev);
 void rv515_fini(struct radeon_device *rdev);
 uint32_t rv515_mc_rreg(struct radeon_device *rdev, uint32_t reg);
@@ -230,6 +275,14 @@ void rv515_pcie_wreg(struct radeon_devic
 void rv515_bandwidth_update(struct radeon_device *rdev);
 int rv515_resume(struct radeon_device *rdev);
 int rv515_suspend(struct radeon_device *rdev);
+void rv515_bandwidth_avivo_update(struct radeon_device *rdev);
+void rv515_vga_render_disable(struct radeon_device *rdev);
+void rv515_set_safe_registers(struct radeon_device *rdev);
+void rv515_mc_stop(struct radeon_device *rdev, struct rv515_mc_save *save);
+void rv515_mc_resume(struct radeon_device *rdev, struct rv515_mc_save *save);
+void rv515_clock_startup(struct radeon_device *rdev);
+void rv515_debugfs(struct radeon_device *rdev);
+
 
 /*
  * r520,rv530,rv560,rv570,r580
@@ -278,6 +331,8 @@ extern void r600_pm_misc(struct radeon_d
 extern void r600_pm_init_profile(struct radeon_device *rdev);
 extern void rs780_pm_init_profile(struct radeon_device *rdev);
 extern void r600_pm_get_dynpm_state(struct radeon_device *rdev);
+extern void r600_set_pcie_lanes(struct radeon_device *rdev, int lanes);
+extern int r600_get_pcie_lanes(struct radeon_device *rdev);
 
 /*
  * rv770,rv730,rv710,rv740
@@ -287,6 +342,7 @@ void rv770_fini(struct radeon_device *rd
 int rv770_suspend(struct radeon_device *rdev);
 int rv770_resume(struct radeon_device *rdev);
 extern void rv770_pm_misc(struct radeon_device *rdev);
+extern u32 rv770_page_flip(struct radeon_device *rdev, int crtc, u64 crtc_base);
 
 /*
  * evergreen
@@ -299,6 +355,7 @@ int evergreen_resume(struct radeon_devic
 bool evergreen_gpu_is_lockup(struct radeon_device *rdev);
 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_pages, struct radeon_fence *fence);
@@ -314,5 +371,8 @@ 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 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);
 
 #endif
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/radeon_atombios.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/radeon_atombios.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/radeon_atombios.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/radeon_atombios.c	2011-03-14 21:20:32.000000000 -0400
@@ -37,7 +37,7 @@ radeon_get_encoder_enum(struct drm_devic
 extern void radeon_link_encoder_connector(struct drm_device *dev);
 extern void
 radeon_add_atom_encoder(struct drm_device *dev, uint32_t encoder_enum,
-			uint32_t supported_device);
+			uint32_t supported_device, u16 caps);
 
 /* from radeon_connector.c */
 extern void
@@ -88,7 +88,7 @@ static inline struct radeon_i2c_bus_rec
 			/* some evergreen boards have bad data for this entry */
 			if (ASIC_IS_DCE4(rdev)) {
 				if ((i == 7) &&
-				    (gpio->usClkMaskRegisterIndex == 0x1936) &&
+				    (le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x1936) &&
 				    (gpio->sucI2cId.ucAccess == 0)) {
 					gpio->sucI2cId.ucAccess = 0x97;
 					gpio->ucDataMaskShift = 8;
@@ -101,7 +101,7 @@ static inline struct radeon_i2c_bus_rec
 			/* some DCE3 boards have bad data for this entry */
 			if (ASIC_IS_DCE3(rdev)) {
 				if ((i == 4) &&
-				    (gpio->usClkMaskRegisterIndex == 0x1fda) &&
+				    (le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x1fda) &&
 				    (gpio->sucI2cId.ucAccess == 0x94))
 					gpio->sucI2cId.ucAccess = 0x14;
 			}
@@ -172,7 +172,7 @@ void radeon_atombios_i2c_init(struct rad
 			/* some evergreen boards have bad data for this entry */
 			if (ASIC_IS_DCE4(rdev)) {
 				if ((i == 7) &&
-				    (gpio->usClkMaskRegisterIndex == 0x1936) &&
+				    (le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x1936) &&
 				    (gpio->sucI2cId.ucAccess == 0)) {
 					gpio->sucI2cId.ucAccess = 0x97;
 					gpio->ucDataMaskShift = 8;
@@ -185,7 +185,7 @@ void radeon_atombios_i2c_init(struct rad
 			/* some DCE3 boards have bad data for this entry */
 			if (ASIC_IS_DCE3(rdev)) {
 				if ((i == 4) &&
-				    (gpio->usClkMaskRegisterIndex == 0x1fda) &&
+				    (le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x1fda) &&
 				    (gpio->sucI2cId.ucAccess == 0x94))
 					gpio->sucI2cId.ucAccess = 0x14;
 			}
@@ -252,7 +252,7 @@ static inline struct radeon_gpio_rec rad
 			pin = &gpio_info->asGPIO_Pin[i];
 			if (id == pin->ucGPIO_ID) {
 				gpio.id = pin->ucGPIO_ID;
-				gpio.reg = pin->usGpioPin_AIndex * 4;
+				gpio.reg = le16_to_cpu(pin->usGpioPin_AIndex) * 4;
 				gpio.mask = (1 << pin->ucGpioPinBitShift);
 				gpio.valid = true;
 				break;
@@ -313,7 +313,6 @@ static bool radeon_atom_apply_quirks(str
 				     uint16_t *line_mux,
 				     struct radeon_hpd *hpd)
 {
-	struct radeon_device *rdev = dev->dev_private;
 
 	/* Asus M2A-VM HDMI board lists the DVI port as HDMI */
 	if ((dev->pdev->device == 0x791e) &&
@@ -388,6 +387,13 @@ static bool radeon_atom_apply_quirks(str
 			*line_mux = 0x90;
 	}
 
+	/* mac rv630, rv730, others */
+	if ((supported_device == ATOM_DEVICE_TV1_SUPPORT) &&
+	    (*connector_type == DRM_MODE_CONNECTOR_DVII)) {
+		*connector_type = DRM_MODE_CONNECTOR_9PinDIN;
+		*line_mux = CONNECTOR_7PIN_DIN_ENUM_ID1;
+	}
+
 	/* ASUS HD 3600 XT board lists the DVI port as HDMI */
 	if ((dev->pdev->device == 0x9598) &&
 	    (dev->pdev->subsystem_vendor == 0x1043) &&
@@ -425,21 +431,23 @@ static bool radeon_atom_apply_quirks(str
 		}
 	}
 
-	/* Acer laptop reports DVI-D as DVI-I and hpd pins reversed */
+	/* Acer laptop (Acer TravelMate 5730G) has an HDMI port
+	 * on the laptop and a DVI port on the docking station and
+	 * both share the same encoder, hpd pin, and ddc line.
+	 * So while the bios table is technically correct,
+	 * we drop the DVI port here since xrandr has no concept of
+	 * encoders and will try and drive both connectors
+	 * with different crtcs which isn't possible on the hardware
+	 * side and leaves no crtcs for LVDS or VGA.
+	 */
 	if ((dev->pdev->device == 0x95c4) &&
 	    (dev->pdev->subsystem_vendor == 0x1025) &&
 	    (dev->pdev->subsystem_device == 0x013c)) {
-		struct radeon_gpio_rec gpio;
-
 		if ((*connector_type == DRM_MODE_CONNECTOR_DVII) &&
 		    (supported_device == ATOM_DEVICE_DFP1_SUPPORT)) {
-			gpio = radeon_lookup_gpio(rdev, 6);
-			*hpd = radeon_atom_get_hpd_info_from_gpio(rdev, &gpio);
+			/* actually it's a DVI-D port not DVI-I */
 			*connector_type = DRM_MODE_CONNECTOR_DVID;
-		} else if ((*connector_type == DRM_MODE_CONNECTOR_HDMIA) &&
-			   (supported_device == ATOM_DEVICE_DFP1_SUPPORT)) {
-			gpio = radeon_lookup_gpio(rdev, 7);
-			*hpd = radeon_atom_get_hpd_info_from_gpio(rdev, &gpio);
+			return false;
 		}
 	}
 
@@ -525,6 +533,7 @@ bool radeon_get_atom_connector_info_from
 	u16 size, data_offset;
 	u8 frev, crev;
 	ATOM_CONNECTOR_OBJECT_TABLE *con_obj;
+	ATOM_ENCODER_OBJECT_TABLE *enc_obj;
 	ATOM_OBJECT_TABLE *router_obj;
 	ATOM_DISPLAY_OBJECT_PATH_TABLE *path_obj;
 	ATOM_OBJECT_HEADER *obj_header;
@@ -549,6 +558,9 @@ bool radeon_get_atom_connector_info_from
 	con_obj = (ATOM_CONNECTOR_OBJECT_TABLE *)
 	    (ctx->bios + data_offset +
 	     le16_to_cpu(obj_header->usConnectorObjectTableOffset));
+	enc_obj = (ATOM_ENCODER_OBJECT_TABLE *)
+	    (ctx->bios + data_offset +
+	     le16_to_cpu(obj_header->usEncoderObjectTableOffset));
 	router_obj = (ATOM_OBJECT_TABLE *)
 		(ctx->bios + data_offset +
 		 le16_to_cpu(obj_header->usRouterObjectTableOffset));
@@ -654,14 +666,35 @@ bool radeon_get_atom_connector_info_from
 				     OBJECT_TYPE_MASK) >> OBJECT_TYPE_SHIFT;
 
 				if (grph_obj_type == GRAPH_OBJECT_TYPE_ENCODER) {
-					u16 encoder_obj = le16_to_cpu(path->usGraphicObjIds[j]);
-
-					radeon_add_atom_encoder(dev,
-								encoder_obj,
-								le16_to_cpu
-								(path->
-								 usDeviceTag));
+					for (k = 0; k < enc_obj->ucNumberOfObjects; k++) {
+						u16 encoder_obj = le16_to_cpu(enc_obj->asObjects[k].usObjectID);
+						if (le16_to_cpu(path->usGraphicObjIds[j]) == encoder_obj) {
+							ATOM_COMMON_RECORD_HEADER *record = (ATOM_COMMON_RECORD_HEADER *)
+								(ctx->bios + data_offset +
+								 le16_to_cpu(enc_obj->asObjects[k].usRecordOffset));
+							ATOM_ENCODER_CAP_RECORD *cap_record;
+							u16 caps = 0;
 
+							while (record->ucRecordType > 0 &&
+							       record->ucRecordType <= ATOM_MAX_OBJECT_RECORD_NUMBER) {
+								switch (record->ucRecordType) {
+								case ATOM_ENCODER_CAP_RECORD_TYPE:
+									cap_record =(ATOM_ENCODER_CAP_RECORD *)
+										record;
+									caps = le16_to_cpu(cap_record->usEncoderCap);
+									break;
+								}
+								record = (ATOM_COMMON_RECORD_HEADER *)
+									((char *)record + record->ucRecordSize);
+							}
+							radeon_add_atom_encoder(dev,
+										encoder_obj,
+										le16_to_cpu
+										(path->
+										 usDeviceTag),
+										caps);
+						}
+					}
 				} else if (grph_obj_type == GRAPH_OBJECT_TYPE_ROUTER) {
 					for (k = 0; k < router_obj->ucNumberOfObjects; k++) {
 						u16 router_obj_id = le16_to_cpu(router_obj->asObjects[k].usObjectID);
@@ -995,7 +1028,8 @@ bool radeon_get_atom_connector_info_from
 						radeon_get_encoder_enum(dev,
 								      (1 << i),
 								      dac),
-						(1 << i));
+						(1 << i),
+						0);
 		else
 			radeon_add_legacy_encoder(dev,
 						  radeon_get_encoder_enum(dev,
@@ -1074,6 +1108,7 @@ union firmware_info {
 	ATOM_FIRMWARE_INFO_V1_3 info_13;
 	ATOM_FIRMWARE_INFO_V1_4 info_14;
 	ATOM_FIRMWARE_INFO_V2_1 info_21;
+	ATOM_FIRMWARE_INFO_V2_2 info_22;
 };
 
 bool radeon_atom_get_clock_info(struct drm_device *dev)
@@ -1128,16 +1163,6 @@ bool radeon_atom_get_clock_info(struct d
 				p1pll->pll_out_min = 64800;
 			else
 				p1pll->pll_out_min = 20000;
-		} else if (p1pll->pll_out_min > 64800) {
-			/* Limiting the pll output range is a good thing generally as
-			 * it limits the number of possible pll combinations for a given
-			 * frequency presumably to the ones that work best on each card.
-			 * However, certain duallink DVI monitors seem to like
-			 * pll combinations that would be limited by this at least on
-			 * pre-DCE 3.0 r6xx hardware.  This might need to be adjusted per
-			 * family.
-			 */
-			p1pll->pll_out_min = 64800;
 		}
 
 		p1pll->pll_in_min =
@@ -1148,8 +1173,12 @@ bool radeon_atom_get_clock_info(struct d
 		*p2pll = *p1pll;
 
 		/* system clock */
-		spll->reference_freq =
-		    le16_to_cpu(firmware_info->info.usReferenceClock);
+		if (ASIC_IS_DCE4(rdev))
+			spll->reference_freq =
+				le16_to_cpu(firmware_info->info_21.usCoreReferenceClock);
+		else
+			spll->reference_freq =
+				le16_to_cpu(firmware_info->info.usReferenceClock);
 		spll->reference_div = 0;
 
 		spll->pll_out_min =
@@ -1171,8 +1200,12 @@ bool radeon_atom_get_clock_info(struct d
 		    le16_to_cpu(firmware_info->info.usMaxEngineClockPLL_Input);
 
 		/* memory clock */
-		mpll->reference_freq =
-		    le16_to_cpu(firmware_info->info.usReferenceClock);
+		if (ASIC_IS_DCE4(rdev))
+			mpll->reference_freq =
+				le16_to_cpu(firmware_info->info_21.usMemoryReferenceClock);
+		else
+			mpll->reference_freq =
+				le16_to_cpu(firmware_info->info.usReferenceClock);
 		mpll->reference_div = 0;
 
 		mpll->pll_out_min =
@@ -1201,8 +1234,12 @@ bool radeon_atom_get_clock_info(struct d
 		if (ASIC_IS_DCE4(rdev)) {
 			rdev->clock.default_dispclk =
 				le32_to_cpu(firmware_info->info_21.ulDefaultDispEngineClkFreq);
-			if (rdev->clock.default_dispclk == 0)
-				rdev->clock.default_dispclk = 60000; /* 600 Mhz */
+			if (rdev->clock.default_dispclk == 0) {
+				if (ASIC_IS_DCE5(rdev))
+					rdev->clock.default_dispclk = 54000; /* 540 Mhz */
+				else
+					rdev->clock.default_dispclk = 60000; /* 600 Mhz */
+			}
 			rdev->clock.dp_extclk =
 				le16_to_cpu(firmware_info->info_21.usUniphyDPModeExtClkFreq);
 		}
@@ -1237,11 +1274,11 @@ bool radeon_atombios_sideport_present(st
 				      data_offset);
 		switch (crev) {
 		case 1:
-			if (igp_info->info.ulBootUpMemoryClock)
+			if (le32_to_cpu(igp_info->info.ulBootUpMemoryClock))
 				return true;
 			break;
 		case 2:
-			if (igp_info->info_2.ulBootUpSidePortClock)
+			if (le32_to_cpu(igp_info->info_2.ulBootUpSidePortClock))
 				return true;
 			break;
 		default:
@@ -1337,6 +1374,43 @@ bool radeon_atombios_get_ppll_ss_info(st
 	return false;
 }
 
+static void radeon_atombios_get_igp_ss_overrides(struct radeon_device *rdev,
+						 struct radeon_atom_ss *ss,
+						 int id)
+{
+	struct radeon_mode_info *mode_info = &rdev->mode_info;
+	int index = GetIndexIntoMasterTable(DATA, IntegratedSystemInfo);
+	u16 data_offset, size;
+	struct _ATOM_INTEGRATED_SYSTEM_INFO_V6 *igp_info;
+	u8 frev, crev;
+	u16 percentage = 0, rate = 0;
+
+	/* get any igp specific overrides */
+	if (atom_parse_data_header(mode_info->atom_context, index, &size,
+				   &frev, &crev, &data_offset)) {
+		igp_info = (struct _ATOM_INTEGRATED_SYSTEM_INFO_V6 *)
+			(mode_info->atom_context->bios + data_offset);
+		switch (id) {
+		case ASIC_INTERNAL_SS_ON_TMDS:
+			percentage = le16_to_cpu(igp_info->usDVISSPercentage);
+			rate = le16_to_cpu(igp_info->usDVISSpreadRateIn10Hz);
+			break;
+		case ASIC_INTERNAL_SS_ON_HDMI:
+			percentage = le16_to_cpu(igp_info->usHDMISSPercentage);
+			rate = le16_to_cpu(igp_info->usHDMISSpreadRateIn10Hz);
+			break;
+		case ASIC_INTERNAL_SS_ON_LVDS:
+			percentage = le16_to_cpu(igp_info->usLvdsSSPercentage);
+			rate = le16_to_cpu(igp_info->usLvdsSSpreadRateIn10Hz);
+			break;
+		}
+		if (percentage)
+			ss->percentage = percentage;
+		if (rate)
+			ss->rate = rate;
+	}
+}
+
 union asic_ss_info {
 	struct _ATOM_ASIC_INTERNAL_SS_INFO info;
 	struct _ATOM_ASIC_INTERNAL_SS_INFO_V2 info_2;
@@ -1368,7 +1442,7 @@ bool radeon_atombios_get_asic_ss_info(st
 
 			for (i = 0; i < num_indices; i++) {
 				if ((ss_info->info.asSpreadSpectrum[i].ucClockIndication == id) &&
-				    (clock <= ss_info->info.asSpreadSpectrum[i].ulTargetClockRange)) {
+				    (clock <= le32_to_cpu(ss_info->info.asSpreadSpectrum[i].ulTargetClockRange))) {
 					ss->percentage =
 						le16_to_cpu(ss_info->info.asSpreadSpectrum[i].usSpreadSpectrumPercentage);
 					ss->type = ss_info->info.asSpreadSpectrum[i].ucSpreadSpectrumMode;
@@ -1382,7 +1456,7 @@ bool radeon_atombios_get_asic_ss_info(st
 				sizeof(ATOM_ASIC_SS_ASSIGNMENT_V2);
 			for (i = 0; i < num_indices; i++) {
 				if ((ss_info->info_2.asSpreadSpectrum[i].ucClockIndication == id) &&
-				    (clock <= ss_info->info_2.asSpreadSpectrum[i].ulTargetClockRange)) {
+				    (clock <= le32_to_cpu(ss_info->info_2.asSpreadSpectrum[i].ulTargetClockRange))) {
 					ss->percentage =
 						le16_to_cpu(ss_info->info_2.asSpreadSpectrum[i].usSpreadSpectrumPercentage);
 					ss->type = ss_info->info_2.asSpreadSpectrum[i].ucSpreadSpectrumMode;
@@ -1396,11 +1470,13 @@ bool radeon_atombios_get_asic_ss_info(st
 				sizeof(ATOM_ASIC_SS_ASSIGNMENT_V3);
 			for (i = 0; i < num_indices; i++) {
 				if ((ss_info->info_3.asSpreadSpectrum[i].ucClockIndication == id) &&
-				    (clock <= ss_info->info_3.asSpreadSpectrum[i].ulTargetClockRange)) {
+				    (clock <= le32_to_cpu(ss_info->info_3.asSpreadSpectrum[i].ulTargetClockRange))) {
 					ss->percentage =
 						le16_to_cpu(ss_info->info_3.asSpreadSpectrum[i].usSpreadSpectrumPercentage);
 					ss->type = ss_info->info_3.asSpreadSpectrum[i].ucSpreadSpectrumMode;
 					ss->rate = le16_to_cpu(ss_info->info_3.asSpreadSpectrum[i].usSpreadRateIn10Hz);
+					if (rdev->flags & RADEON_IS_IGP)
+						radeon_atombios_get_igp_ss_overrides(rdev, ss, id);
 					return true;
 				}
 			}
@@ -1477,6 +1553,9 @@ struct radeon_encoder_atom_dig *radeon_a
 		if (misc & ATOM_DOUBLE_CLOCK_MODE)
 			lvds->native_mode.flags |= DRM_MODE_FLAG_DBLSCAN;
 
+		lvds->native_mode.width_mm = le16_to_cpu(lvds_info->info.sLCDTiming.usImageHSize);
+		lvds->native_mode.height_mm = le16_to_cpu(lvds_info->info.sLCDTiming.usImageVSize);
+
 		/* set crtc values */
 		drm_mode_set_crtcinfo(&lvds->native_mode, CRTC_INTERLACE_HALVE_V);
 
@@ -1489,6 +1568,59 @@ struct radeon_encoder_atom_dig *radeon_a
 		else
 			lvds->linkb = false;
 
+		/* parse the lcd record table */
+		if (le16_to_cpu(lvds_info->info.usModePatchTableOffset)) {
+			ATOM_FAKE_EDID_PATCH_RECORD *fake_edid_record;
+			ATOM_PANEL_RESOLUTION_PATCH_RECORD *panel_res_record;
+			bool bad_record = false;
+			u8 *record = (u8 *)(mode_info->atom_context->bios +
+					    data_offset +
+					    le16_to_cpu(lvds_info->info.usModePatchTableOffset));
+			while (*record != ATOM_RECORD_END_TYPE) {
+				switch (*record) {
+				case LCD_MODE_PATCH_RECORD_MODE_TYPE:
+					record += sizeof(ATOM_PATCH_RECORD_MODE);
+					break;
+				case LCD_RTS_RECORD_TYPE:
+					record += sizeof(ATOM_LCD_RTS_RECORD);
+					break;
+				case LCD_CAP_RECORD_TYPE:
+					record += sizeof(ATOM_LCD_MODE_CONTROL_CAP);
+					break;
+				case LCD_FAKE_EDID_PATCH_RECORD_TYPE:
+					fake_edid_record = (ATOM_FAKE_EDID_PATCH_RECORD *)record;
+					if (fake_edid_record->ucFakeEDIDLength) {
+						struct edid *edid;
+						int edid_size =
+							max((int)EDID_LENGTH, (int)fake_edid_record->ucFakeEDIDLength);
+						edid = kmalloc(edid_size, GFP_KERNEL);
+						if (edid) {
+							memcpy((u8 *)edid, (u8 *)&fake_edid_record->ucFakeEDIDString[0],
+							       fake_edid_record->ucFakeEDIDLength);
+
+							if (drm_edid_is_valid(edid))
+								rdev->mode_info.bios_hardcoded_edid = edid;
+							else
+								kfree(edid);
+						}
+					}
+					record += sizeof(ATOM_FAKE_EDID_PATCH_RECORD);
+					break;
+				case LCD_PANEL_RESOLUTION_RECORD_TYPE:
+					panel_res_record = (ATOM_PANEL_RESOLUTION_PATCH_RECORD *)record;
+					lvds->native_mode.width_mm = panel_res_record->usHSize;
+					lvds->native_mode.height_mm = panel_res_record->usVSize;
+					record += sizeof(ATOM_PANEL_RESOLUTION_PATCH_RECORD);
+					break;
+				default:
+					DRM_ERROR("Bad LCD record %d\n", *record);
+					bad_record = true;
+					break;
+				}
+				if (bad_record)
+					break;
+			}
+		}
 	}
 	return lvds;
 }
@@ -1740,510 +1872,642 @@ static const char *pp_lib_thermal_contro
 	"RV6xx",
 	"RV770",
 	"adt7473",
+	"NONE",
 	"External GPIO",
 	"Evergreen",
-	"adt7473 with internal",
-
+	"emc2103",
+	"Sumo",
+	"Northern Islands",
 };
 
 union power_info {
 	struct _ATOM_POWERPLAY_INFO info;
 	struct _ATOM_POWERPLAY_INFO_V2 info_2;
 	struct _ATOM_POWERPLAY_INFO_V3 info_3;
-	struct _ATOM_PPLIB_POWERPLAYTABLE info_4;
+	struct _ATOM_PPLIB_POWERPLAYTABLE pplib;
+	struct _ATOM_PPLIB_POWERPLAYTABLE2 pplib2;
+	struct _ATOM_PPLIB_POWERPLAYTABLE3 pplib3;
 };
 
-void radeon_atombios_get_power_modes(struct radeon_device *rdev)
+union pplib_clock_info {
+	struct _ATOM_PPLIB_R600_CLOCK_INFO r600;
+	struct _ATOM_PPLIB_RS780_CLOCK_INFO rs780;
+	struct _ATOM_PPLIB_EVERGREEN_CLOCK_INFO evergreen;
+	struct _ATOM_PPLIB_SUMO_CLOCK_INFO sumo;
+};
+
+union pplib_power_state {
+	struct _ATOM_PPLIB_STATE v1;
+	struct _ATOM_PPLIB_STATE_V2 v2;
+};
+
+static void radeon_atombios_parse_misc_flags_1_3(struct radeon_device *rdev,
+						 int state_index,
+						 u32 misc, u32 misc2)
+{
+	rdev->pm.power_state[state_index].misc = misc;
+	rdev->pm.power_state[state_index].misc2 = misc2;
+	/* order matters! */
+	if (misc & ATOM_PM_MISCINFO_POWER_SAVING_MODE)
+		rdev->pm.power_state[state_index].type =
+			POWER_STATE_TYPE_POWERSAVE;
+	if (misc & ATOM_PM_MISCINFO_DEFAULT_DC_STATE_ENTRY_TRUE)
+		rdev->pm.power_state[state_index].type =
+			POWER_STATE_TYPE_BATTERY;
+	if (misc & ATOM_PM_MISCINFO_DEFAULT_LOW_DC_STATE_ENTRY_TRUE)
+		rdev->pm.power_state[state_index].type =
+			POWER_STATE_TYPE_BATTERY;
+	if (misc & ATOM_PM_MISCINFO_LOAD_BALANCE_EN)
+		rdev->pm.power_state[state_index].type =
+			POWER_STATE_TYPE_BALANCED;
+	if (misc & ATOM_PM_MISCINFO_3D_ACCELERATION_EN) {
+		rdev->pm.power_state[state_index].type =
+			POWER_STATE_TYPE_PERFORMANCE;
+		rdev->pm.power_state[state_index].flags &=
+			~RADEON_PM_STATE_SINGLE_DISPLAY_ONLY;
+	}
+	if (misc2 & ATOM_PM_MISCINFO2_SYSTEM_AC_LITE_MODE)
+		rdev->pm.power_state[state_index].type =
+			POWER_STATE_TYPE_BALANCED;
+	if (misc & ATOM_PM_MISCINFO_DRIVER_DEFAULT_MODE) {
+		rdev->pm.power_state[state_index].type =
+			POWER_STATE_TYPE_DEFAULT;
+		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[0];
+	} else if (state_index == 0) {
+		rdev->pm.power_state[state_index].clock_info[0].flags |=
+			RADEON_PM_MODE_NO_DISPLAY;
+	}
+}
+
+static int radeon_atombios_parse_power_table_1_3(struct radeon_device *rdev)
 {
 	struct radeon_mode_info *mode_info = &rdev->mode_info;
+	u32 misc, misc2 = 0;
+	int num_modes = 0, i;
+	int state_index = 0;
+	struct radeon_i2c_bus_rec i2c_bus;
+	union power_info *power_info;
 	int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo);
-	u16 data_offset;
+        u16 data_offset;
 	u8 frev, crev;
-	u32 misc, misc2 = 0, sclk, mclk;
-	union power_info *power_info;
-	struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info;
-	struct _ATOM_PPLIB_STATE *power_state;
-	int num_modes = 0, i, j;
-	int state_index = 0, mode_index = 0;
-	struct radeon_i2c_bus_rec i2c_bus;
 
-	rdev->pm.default_power_state_index = -1;
+	if (!atom_parse_data_header(mode_info->atom_context, index, NULL,
+				   &frev, &crev, &data_offset))
+		return state_index;
+	power_info = (union power_info *)(mode_info->atom_context->bios + data_offset);
 
-	if (atom_parse_data_header(mode_info->atom_context, index, NULL,
-				   &frev, &crev, &data_offset)) {
-		power_info = (union power_info *)(mode_info->atom_context->bios + data_offset);
-		if (frev < 4) {
-			/* add the i2c bus for thermal/fan chip */
-			if (power_info->info.ucOverdriveThermalController > 0) {
-				DRM_INFO("Possible %s thermal controller at 0x%02x\n",
-					 thermal_controller_names[power_info->info.ucOverdriveThermalController],
-					 power_info->info.ucOverdriveControllerAddress >> 1);
-				i2c_bus = radeon_lookup_i2c_gpio(rdev, power_info->info.ucOverdriveI2cLine);
-				rdev->pm.i2c_bus = radeon_i2c_lookup(rdev, &i2c_bus);
-				if (rdev->pm.i2c_bus) {
-					struct i2c_board_info info = { };
-					const char *name = thermal_controller_names[power_info->info.
-										    ucOverdriveThermalController];
-					info.addr = power_info->info.ucOverdriveControllerAddress >> 1;
-					strlcpy(info.type, name, sizeof(info.type));
-					i2c_new_device(&rdev->pm.i2c_bus->adapter, &info);
-				}
+	/* add the i2c bus for thermal/fan chip */
+	if (power_info->info.ucOverdriveThermalController > 0) {
+		DRM_INFO("Possible %s thermal controller at 0x%02x\n",
+			 thermal_controller_names[power_info->info.ucOverdriveThermalController],
+			 power_info->info.ucOverdriveControllerAddress >> 1);
+		i2c_bus = radeon_lookup_i2c_gpio(rdev, power_info->info.ucOverdriveI2cLine);
+		rdev->pm.i2c_bus = radeon_i2c_lookup(rdev, &i2c_bus);
+		if (rdev->pm.i2c_bus) {
+			struct i2c_board_info info = { };
+			const char *name = thermal_controller_names[power_info->info.
+								    ucOverdriveThermalController];
+			info.addr = power_info->info.ucOverdriveControllerAddress >> 1;
+			strlcpy(info.type, name, sizeof(info.type));
+			i2c_new_device(&rdev->pm.i2c_bus->adapter, &info);
+		}
+	}
+	num_modes = power_info->info.ucNumOfPowerModeEntries;
+	if (num_modes > ATOM_MAX_NUMBEROF_POWER_BLOCK)
+		num_modes = ATOM_MAX_NUMBEROF_POWER_BLOCK;
+	rdev->pm.power_state = kzalloc(sizeof(struct radeon_power_state) * num_modes, GFP_KERNEL);
+	if (!rdev->pm.power_state)
+		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[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 =
+				le16_to_cpu(power_info->info.asPowerPlayInfo[i].usEngineClock);
+			/* skip invalid modes */
+			if ((rdev->pm.power_state[state_index].clock_info[0].mclk == 0) ||
+			    (rdev->pm.power_state[state_index].clock_info[0].sclk == 0))
+				continue;
+			rdev->pm.power_state[state_index].pcie_lanes =
+				power_info->info.asPowerPlayInfo[i].ucNumPciELanes;
+			misc = le32_to_cpu(power_info->info.asPowerPlayInfo[i].ulMiscInfo);
+			if ((misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_SUPPORT) ||
+			    (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH)) {
+				rdev->pm.power_state[state_index].clock_info[0].voltage.type =
+					VOLTAGE_GPIO;
+				rdev->pm.power_state[state_index].clock_info[0].voltage.gpio =
+					radeon_lookup_gpio(rdev,
+							   power_info->info.asPowerPlayInfo[i].ucVoltageDropIndex);
+				if (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH)
+					rdev->pm.power_state[state_index].clock_info[0].voltage.active_high =
+						true;
+				else
+					rdev->pm.power_state[state_index].clock_info[0].voltage.active_high =
+						false;
+			} else if (misc & ATOM_PM_MISCINFO_PROGRAM_VOLTAGE) {
+				rdev->pm.power_state[state_index].clock_info[0].voltage.type =
+					VOLTAGE_VDDC;
+				rdev->pm.power_state[state_index].clock_info[0].voltage.vddc_id =
+					power_info->info.asPowerPlayInfo[i].ucVoltageDropIndex;
 			}
-			num_modes = power_info->info.ucNumOfPowerModeEntries;
-			if (num_modes > ATOM_MAX_NUMBEROF_POWER_BLOCK)
-				num_modes = ATOM_MAX_NUMBEROF_POWER_BLOCK;
-			/* 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[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 =
-						le16_to_cpu(power_info->info.asPowerPlayInfo[i].usEngineClock);
-					/* skip invalid modes */
-					if ((rdev->pm.power_state[state_index].clock_info[0].mclk == 0) ||
-					    (rdev->pm.power_state[state_index].clock_info[0].sclk == 0))
-						continue;
-					rdev->pm.power_state[state_index].pcie_lanes =
-						power_info->info.asPowerPlayInfo[i].ucNumPciELanes;
-					misc = le32_to_cpu(power_info->info.asPowerPlayInfo[i].ulMiscInfo);
-					if ((misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_SUPPORT) ||
-					    (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH)) {
-						rdev->pm.power_state[state_index].clock_info[0].voltage.type =
-							VOLTAGE_GPIO;
-						rdev->pm.power_state[state_index].clock_info[0].voltage.gpio =
-							radeon_lookup_gpio(rdev,
-							power_info->info.asPowerPlayInfo[i].ucVoltageDropIndex);
-						if (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH)
-							rdev->pm.power_state[state_index].clock_info[0].voltage.active_high =
-								true;
-						else
-							rdev->pm.power_state[state_index].clock_info[0].voltage.active_high =
-								false;
-					} else if (misc & ATOM_PM_MISCINFO_PROGRAM_VOLTAGE) {
-						rdev->pm.power_state[state_index].clock_info[0].voltage.type =
-							VOLTAGE_VDDC;
-						rdev->pm.power_state[state_index].clock_info[0].voltage.vddc_id =
-							power_info->info.asPowerPlayInfo[i].ucVoltageDropIndex;
-					}
-					rdev->pm.power_state[state_index].flags = RADEON_PM_STATE_SINGLE_DISPLAY_ONLY;
-					rdev->pm.power_state[state_index].misc = misc;
-					/* order matters! */
-					if (misc & ATOM_PM_MISCINFO_POWER_SAVING_MODE)
-						rdev->pm.power_state[state_index].type =
-							POWER_STATE_TYPE_POWERSAVE;
-					if (misc & ATOM_PM_MISCINFO_DEFAULT_DC_STATE_ENTRY_TRUE)
-						rdev->pm.power_state[state_index].type =
-							POWER_STATE_TYPE_BATTERY;
-					if (misc & ATOM_PM_MISCINFO_DEFAULT_LOW_DC_STATE_ENTRY_TRUE)
-						rdev->pm.power_state[state_index].type =
-							POWER_STATE_TYPE_BATTERY;
-					if (misc & ATOM_PM_MISCINFO_LOAD_BALANCE_EN)
-						rdev->pm.power_state[state_index].type =
-							POWER_STATE_TYPE_BALANCED;
-					if (misc & ATOM_PM_MISCINFO_3D_ACCELERATION_EN) {
-						rdev->pm.power_state[state_index].type =
-							POWER_STATE_TYPE_PERFORMANCE;
-						rdev->pm.power_state[state_index].flags &=
-							~RADEON_PM_STATE_SINGLE_DISPLAY_ONLY;
-					}
-					if (misc & ATOM_PM_MISCINFO_DRIVER_DEFAULT_MODE) {
-						rdev->pm.power_state[state_index].type =
-							POWER_STATE_TYPE_DEFAULT;
-						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[0];
-						rdev->pm.power_state[state_index].flags &=
-							~RADEON_PM_STATE_SINGLE_DISPLAY_ONLY;
-					} else if (state_index == 0) {
-						rdev->pm.power_state[state_index].clock_info[0].flags |=
-							RADEON_PM_MODE_NO_DISPLAY;
-					}
-					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 =
-						le32_to_cpu(power_info->info_2.asPowerPlayInfo[i].ulEngineClock);
-					/* skip invalid modes */
-					if ((rdev->pm.power_state[state_index].clock_info[0].mclk == 0) ||
-					    (rdev->pm.power_state[state_index].clock_info[0].sclk == 0))
-						continue;
-					rdev->pm.power_state[state_index].pcie_lanes =
-						power_info->info_2.asPowerPlayInfo[i].ucNumPciELanes;
-					misc = le32_to_cpu(power_info->info_2.asPowerPlayInfo[i].ulMiscInfo);
-					misc2 = le32_to_cpu(power_info->info_2.asPowerPlayInfo[i].ulMiscInfo2);
-					if ((misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_SUPPORT) ||
-					    (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH)) {
-						rdev->pm.power_state[state_index].clock_info[0].voltage.type =
-							VOLTAGE_GPIO;
-						rdev->pm.power_state[state_index].clock_info[0].voltage.gpio =
-							radeon_lookup_gpio(rdev,
-							power_info->info_2.asPowerPlayInfo[i].ucVoltageDropIndex);
-						if (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH)
-							rdev->pm.power_state[state_index].clock_info[0].voltage.active_high =
-								true;
-						else
-							rdev->pm.power_state[state_index].clock_info[0].voltage.active_high =
-								false;
-					} else if (misc & ATOM_PM_MISCINFO_PROGRAM_VOLTAGE) {
-						rdev->pm.power_state[state_index].clock_info[0].voltage.type =
-							VOLTAGE_VDDC;
-						rdev->pm.power_state[state_index].clock_info[0].voltage.vddc_id =
-							power_info->info_2.asPowerPlayInfo[i].ucVoltageDropIndex;
-					}
-					rdev->pm.power_state[state_index].flags = RADEON_PM_STATE_SINGLE_DISPLAY_ONLY;
-					rdev->pm.power_state[state_index].misc = misc;
-					rdev->pm.power_state[state_index].misc2 = misc2;
-					/* order matters! */
-					if (misc & ATOM_PM_MISCINFO_POWER_SAVING_MODE)
-						rdev->pm.power_state[state_index].type =
-							POWER_STATE_TYPE_POWERSAVE;
-					if (misc & ATOM_PM_MISCINFO_DEFAULT_DC_STATE_ENTRY_TRUE)
-						rdev->pm.power_state[state_index].type =
-							POWER_STATE_TYPE_BATTERY;
-					if (misc & ATOM_PM_MISCINFO_DEFAULT_LOW_DC_STATE_ENTRY_TRUE)
-						rdev->pm.power_state[state_index].type =
-							POWER_STATE_TYPE_BATTERY;
-					if (misc & ATOM_PM_MISCINFO_LOAD_BALANCE_EN)
-						rdev->pm.power_state[state_index].type =
-							POWER_STATE_TYPE_BALANCED;
-					if (misc & ATOM_PM_MISCINFO_3D_ACCELERATION_EN) {
-						rdev->pm.power_state[state_index].type =
-							POWER_STATE_TYPE_PERFORMANCE;
-						rdev->pm.power_state[state_index].flags &=
-							~RADEON_PM_STATE_SINGLE_DISPLAY_ONLY;
-					}
-					if (misc2 & ATOM_PM_MISCINFO2_SYSTEM_AC_LITE_MODE)
-						rdev->pm.power_state[state_index].type =
-							POWER_STATE_TYPE_BALANCED;
-					if (misc2 & ATOM_PM_MISCINFO2_MULTI_DISPLAY_SUPPORT)
-						rdev->pm.power_state[state_index].flags &=
-							~RADEON_PM_STATE_SINGLE_DISPLAY_ONLY;
-					if (misc & ATOM_PM_MISCINFO_DRIVER_DEFAULT_MODE) {
-						rdev->pm.power_state[state_index].type =
-							POWER_STATE_TYPE_DEFAULT;
-						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[0];
-						rdev->pm.power_state[state_index].flags &=
-							~RADEON_PM_STATE_SINGLE_DISPLAY_ONLY;
-					} else if (state_index == 0) {
-						rdev->pm.power_state[state_index].clock_info[0].flags |=
-							RADEON_PM_MODE_NO_DISPLAY;
-					}
-					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 =
-						le32_to_cpu(power_info->info_3.asPowerPlayInfo[i].ulEngineClock);
-					/* skip invalid modes */
-					if ((rdev->pm.power_state[state_index].clock_info[0].mclk == 0) ||
-					    (rdev->pm.power_state[state_index].clock_info[0].sclk == 0))
-						continue;
-					rdev->pm.power_state[state_index].pcie_lanes =
-						power_info->info_3.asPowerPlayInfo[i].ucNumPciELanes;
-					misc = le32_to_cpu(power_info->info_3.asPowerPlayInfo[i].ulMiscInfo);
-					misc2 = le32_to_cpu(power_info->info_3.asPowerPlayInfo[i].ulMiscInfo2);
-					if ((misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_SUPPORT) ||
-					    (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH)) {
-						rdev->pm.power_state[state_index].clock_info[0].voltage.type =
-							VOLTAGE_GPIO;
-						rdev->pm.power_state[state_index].clock_info[0].voltage.gpio =
-							radeon_lookup_gpio(rdev,
-							power_info->info_3.asPowerPlayInfo[i].ucVoltageDropIndex);
-						if (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH)
-							rdev->pm.power_state[state_index].clock_info[0].voltage.active_high =
-								true;
-						else
-							rdev->pm.power_state[state_index].clock_info[0].voltage.active_high =
-								false;
-					} else if (misc & ATOM_PM_MISCINFO_PROGRAM_VOLTAGE) {
-						rdev->pm.power_state[state_index].clock_info[0].voltage.type =
-							VOLTAGE_VDDC;
-						rdev->pm.power_state[state_index].clock_info[0].voltage.vddc_id =
-							power_info->info_3.asPowerPlayInfo[i].ucVoltageDropIndex;
-						if (misc2 & ATOM_PM_MISCINFO2_VDDCI_DYNAMIC_VOLTAGE_EN) {
-							rdev->pm.power_state[state_index].clock_info[0].voltage.vddci_enabled =
-								true;
-							rdev->pm.power_state[state_index].clock_info[0].voltage.vddci_id =
-							power_info->info_3.asPowerPlayInfo[i].ucVDDCI_VoltageDropIndex;
-						}
-					}
-					rdev->pm.power_state[state_index].flags = RADEON_PM_STATE_SINGLE_DISPLAY_ONLY;
-					rdev->pm.power_state[state_index].misc = misc;
-					rdev->pm.power_state[state_index].misc2 = misc2;
-					/* order matters! */
-					if (misc & ATOM_PM_MISCINFO_POWER_SAVING_MODE)
-						rdev->pm.power_state[state_index].type =
-							POWER_STATE_TYPE_POWERSAVE;
-					if (misc & ATOM_PM_MISCINFO_DEFAULT_DC_STATE_ENTRY_TRUE)
-						rdev->pm.power_state[state_index].type =
-							POWER_STATE_TYPE_BATTERY;
-					if (misc & ATOM_PM_MISCINFO_DEFAULT_LOW_DC_STATE_ENTRY_TRUE)
-						rdev->pm.power_state[state_index].type =
-							POWER_STATE_TYPE_BATTERY;
-					if (misc & ATOM_PM_MISCINFO_LOAD_BALANCE_EN)
-						rdev->pm.power_state[state_index].type =
-							POWER_STATE_TYPE_BALANCED;
-					if (misc & ATOM_PM_MISCINFO_3D_ACCELERATION_EN) {
-						rdev->pm.power_state[state_index].type =
-							POWER_STATE_TYPE_PERFORMANCE;
-						rdev->pm.power_state[state_index].flags &=
-							~RADEON_PM_STATE_SINGLE_DISPLAY_ONLY;
-					}
-					if (misc2 & ATOM_PM_MISCINFO2_SYSTEM_AC_LITE_MODE)
-						rdev->pm.power_state[state_index].type =
-							POWER_STATE_TYPE_BALANCED;
-					if (misc & ATOM_PM_MISCINFO_DRIVER_DEFAULT_MODE) {
-						rdev->pm.power_state[state_index].type =
-							POWER_STATE_TYPE_DEFAULT;
-						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[0];
-					} else if (state_index == 0) {
-						rdev->pm.power_state[state_index].clock_info[0].flags |=
-							RADEON_PM_MODE_NO_DISPLAY;
-					}
-					state_index++;
-					break;
-				}
+			rdev->pm.power_state[state_index].flags = RADEON_PM_STATE_SINGLE_DISPLAY_ONLY;
+			radeon_atombios_parse_misc_flags_1_3(rdev, state_index, misc, 0);
+			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 =
+				le32_to_cpu(power_info->info_2.asPowerPlayInfo[i].ulEngineClock);
+			/* skip invalid modes */
+			if ((rdev->pm.power_state[state_index].clock_info[0].mclk == 0) ||
+			    (rdev->pm.power_state[state_index].clock_info[0].sclk == 0))
+				continue;
+			rdev->pm.power_state[state_index].pcie_lanes =
+				power_info->info_2.asPowerPlayInfo[i].ucNumPciELanes;
+			misc = le32_to_cpu(power_info->info_2.asPowerPlayInfo[i].ulMiscInfo);
+			misc2 = le32_to_cpu(power_info->info_2.asPowerPlayInfo[i].ulMiscInfo2);
+			if ((misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_SUPPORT) ||
+			    (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH)) {
+				rdev->pm.power_state[state_index].clock_info[0].voltage.type =
+					VOLTAGE_GPIO;
+				rdev->pm.power_state[state_index].clock_info[0].voltage.gpio =
+					radeon_lookup_gpio(rdev,
+							   power_info->info_2.asPowerPlayInfo[i].ucVoltageDropIndex);
+				if (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH)
+					rdev->pm.power_state[state_index].clock_info[0].voltage.active_high =
+						true;
+				else
+					rdev->pm.power_state[state_index].clock_info[0].voltage.active_high =
+						false;
+			} else if (misc & ATOM_PM_MISCINFO_PROGRAM_VOLTAGE) {
+				rdev->pm.power_state[state_index].clock_info[0].voltage.type =
+					VOLTAGE_VDDC;
+				rdev->pm.power_state[state_index].clock_info[0].voltage.vddc_id =
+					power_info->info_2.asPowerPlayInfo[i].ucVoltageDropIndex;
 			}
-			/* last mode is usually default */
-			if (rdev->pm.default_power_state_index == -1) {
-				rdev->pm.power_state[state_index - 1].type =
-					POWER_STATE_TYPE_DEFAULT;
-				rdev->pm.default_power_state_index = state_index - 1;
-				rdev->pm.power_state[state_index - 1].default_clock_mode =
-					&rdev->pm.power_state[state_index - 1].clock_info[0];
-				rdev->pm.power_state[state_index].flags &=
-					~RADEON_PM_STATE_SINGLE_DISPLAY_ONLY;
-				rdev->pm.power_state[state_index].misc = 0;
-				rdev->pm.power_state[state_index].misc2 = 0;
+			rdev->pm.power_state[state_index].flags = RADEON_PM_STATE_SINGLE_DISPLAY_ONLY;
+			radeon_atombios_parse_misc_flags_1_3(rdev, state_index, misc, misc2);
+			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 =
+				le32_to_cpu(power_info->info_3.asPowerPlayInfo[i].ulEngineClock);
+			/* skip invalid modes */
+			if ((rdev->pm.power_state[state_index].clock_info[0].mclk == 0) ||
+			    (rdev->pm.power_state[state_index].clock_info[0].sclk == 0))
+				continue;
+			rdev->pm.power_state[state_index].pcie_lanes =
+				power_info->info_3.asPowerPlayInfo[i].ucNumPciELanes;
+			misc = le32_to_cpu(power_info->info_3.asPowerPlayInfo[i].ulMiscInfo);
+			misc2 = le32_to_cpu(power_info->info_3.asPowerPlayInfo[i].ulMiscInfo2);
+			if ((misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_SUPPORT) ||
+			    (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH)) {
+				rdev->pm.power_state[state_index].clock_info[0].voltage.type =
+					VOLTAGE_GPIO;
+				rdev->pm.power_state[state_index].clock_info[0].voltage.gpio =
+					radeon_lookup_gpio(rdev,
+							   power_info->info_3.asPowerPlayInfo[i].ucVoltageDropIndex);
+				if (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH)
+					rdev->pm.power_state[state_index].clock_info[0].voltage.active_high =
+						true;
+				else
+					rdev->pm.power_state[state_index].clock_info[0].voltage.active_high =
+						false;
+			} else if (misc & ATOM_PM_MISCINFO_PROGRAM_VOLTAGE) {
+				rdev->pm.power_state[state_index].clock_info[0].voltage.type =
+					VOLTAGE_VDDC;
+				rdev->pm.power_state[state_index].clock_info[0].voltage.vddc_id =
+					power_info->info_3.asPowerPlayInfo[i].ucVoltageDropIndex;
+				if (misc2 & ATOM_PM_MISCINFO2_VDDCI_DYNAMIC_VOLTAGE_EN) {
+					rdev->pm.power_state[state_index].clock_info[0].voltage.vddci_enabled =
+						true;
+					rdev->pm.power_state[state_index].clock_info[0].voltage.vddci_id =
+						power_info->info_3.asPowerPlayInfo[i].ucVDDCI_VoltageDropIndex;
+				}
 			}
-		} else {
-			int fw_index = GetIndexIntoMasterTable(DATA, FirmwareInfo);
-			uint8_t fw_frev, fw_crev;
-			uint16_t fw_data_offset, vddc = 0;
-			union firmware_info *firmware_info;
-			ATOM_PPLIB_THERMALCONTROLLER *controller = &power_info->info_4.sThermalController;
+			rdev->pm.power_state[state_index].flags = RADEON_PM_STATE_SINGLE_DISPLAY_ONLY;
+			radeon_atombios_parse_misc_flags_1_3(rdev, state_index, misc, misc2);
+			state_index++;
+			break;
+		}
+	}
+	/* last mode is usually default */
+	if (rdev->pm.default_power_state_index == -1) {
+		rdev->pm.power_state[state_index - 1].type =
+			POWER_STATE_TYPE_DEFAULT;
+		rdev->pm.default_power_state_index = state_index - 1;
+		rdev->pm.power_state[state_index - 1].default_clock_mode =
+			&rdev->pm.power_state[state_index - 1].clock_info[0];
+		rdev->pm.power_state[state_index].flags &=
+			~RADEON_PM_STATE_SINGLE_DISPLAY_ONLY;
+		rdev->pm.power_state[state_index].misc = 0;
+		rdev->pm.power_state[state_index].misc2 = 0;
+	}
+	return state_index;
+}
 
-			if (atom_parse_data_header(mode_info->atom_context, fw_index, NULL,
-						   &fw_frev, &fw_crev, &fw_data_offset)) {
-				firmware_info =
-					(union firmware_info *)(mode_info->atom_context->bios +
-								fw_data_offset);
-				vddc = firmware_info->info_14.usBootUpVDDCVoltage;
+static void radeon_atombios_add_pplib_thermal_controller(struct radeon_device *rdev,
+							 ATOM_PPLIB_THERMALCONTROLLER *controller)
+{
+	struct radeon_i2c_bus_rec i2c_bus;
+
+	/* add the i2c bus for thermal/fan chip */
+	if (controller->ucType > 0) {
+		if (controller->ucType == ATOM_PP_THERMALCONTROLLER_RV6xx) {
+			DRM_INFO("Internal thermal controller %s fan control\n",
+				 (controller->ucFanParameters &
+				  ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
+			rdev->pm.int_thermal_type = THERMAL_TYPE_RV6XX;
+		} else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_RV770) {
+			DRM_INFO("Internal thermal controller %s fan control\n",
+				 (controller->ucFanParameters &
+				  ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
+			rdev->pm.int_thermal_type = THERMAL_TYPE_RV770;
+		} else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_EVERGREEN) {
+			DRM_INFO("Internal thermal controller %s fan control\n",
+				 (controller->ucFanParameters &
+				  ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
+			rdev->pm.int_thermal_type = THERMAL_TYPE_EVERGREEN;
+		} else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_SUMO) {
+			DRM_INFO("Internal thermal controller %s fan control\n",
+				 (controller->ucFanParameters &
+				  ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
+			rdev->pm.int_thermal_type = THERMAL_TYPE_SUMO;
+		} else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_NISLANDS) {
+			DRM_INFO("Internal thermal controller %s fan control\n",
+				 (controller->ucFanParameters &
+				  ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
+			rdev->pm.int_thermal_type = THERMAL_TYPE_NI;
+		} else if ((controller->ucType ==
+			    ATOM_PP_THERMALCONTROLLER_EXTERNAL_GPIO) ||
+			   (controller->ucType ==
+			    ATOM_PP_THERMALCONTROLLER_ADT7473_WITH_INTERNAL) ||
+			   (controller->ucType ==
+			    ATOM_PP_THERMALCONTROLLER_EMC2103_WITH_INTERNAL)) {
+			DRM_INFO("Special thermal controller config\n");
+		} else {
+			DRM_INFO("Possible %s thermal controller at 0x%02x %s fan control\n",
+				 pp_lib_thermal_controller_names[controller->ucType],
+				 controller->ucI2cAddress >> 1,
+				 (controller->ucFanParameters &
+				  ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
+			i2c_bus = radeon_lookup_i2c_gpio(rdev, controller->ucI2cLine);
+			rdev->pm.i2c_bus = radeon_i2c_lookup(rdev, &i2c_bus);
+			if (rdev->pm.i2c_bus) {
+				struct i2c_board_info info = { };
+				const char *name = pp_lib_thermal_controller_names[controller->ucType];
+				info.addr = controller->ucI2cAddress >> 1;
+				strlcpy(info.type, name, sizeof(info.type));
+				i2c_new_device(&rdev->pm.i2c_bus->adapter, &info);
 			}
+		}
+	}
+}
 
-			/* add the i2c bus for thermal/fan chip */
-			if (controller->ucType > 0) {
-				if (controller->ucType == ATOM_PP_THERMALCONTROLLER_RV6xx) {
-					DRM_INFO("Internal thermal controller %s fan control\n",
-						 (controller->ucFanParameters &
-						  ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
-					rdev->pm.int_thermal_type = THERMAL_TYPE_RV6XX;
-				} else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_RV770) {
-					DRM_INFO("Internal thermal controller %s fan control\n",
-						 (controller->ucFanParameters &
-						  ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
-					rdev->pm.int_thermal_type = THERMAL_TYPE_RV770;
-				} else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_EVERGREEN) {
-					DRM_INFO("Internal thermal controller %s fan control\n",
-						 (controller->ucFanParameters &
-						  ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
-					rdev->pm.int_thermal_type = THERMAL_TYPE_EVERGREEN;
-				} else if ((controller->ucType ==
-					    ATOM_PP_THERMALCONTROLLER_EXTERNAL_GPIO) ||
-					   (controller->ucType ==
-					    ATOM_PP_THERMALCONTROLLER_ADT7473_WITH_INTERNAL)) {
-					DRM_INFO("Special thermal controller config\n");
-				} else {
-					DRM_INFO("Possible %s thermal controller at 0x%02x %s fan control\n",
-						 pp_lib_thermal_controller_names[controller->ucType],
-						 controller->ucI2cAddress >> 1,
-						 (controller->ucFanParameters &
-						  ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
-					i2c_bus = radeon_lookup_i2c_gpio(rdev, controller->ucI2cLine);
-					rdev->pm.i2c_bus = radeon_i2c_lookup(rdev, &i2c_bus);
-					if (rdev->pm.i2c_bus) {
-						struct i2c_board_info info = { };
-						const char *name = pp_lib_thermal_controller_names[controller->ucType];
-						info.addr = controller->ucI2cAddress >> 1;
-						strlcpy(info.type, name, sizeof(info.type));
-						i2c_new_device(&rdev->pm.i2c_bus->adapter, &info);
-					}
+static u16 radeon_atombios_get_default_vddc(struct radeon_device *rdev)
+{
+	struct radeon_mode_info *mode_info = &rdev->mode_info;
+	int index = GetIndexIntoMasterTable(DATA, FirmwareInfo);
+	u8 frev, crev;
+	u16 data_offset;
+	union firmware_info *firmware_info;
+	u16 vddc = 0;
 
-				}
-			}
-			/* first mode is usually default, followed by low to high */
-			for (i = 0; i < power_info->info_4.ucNumStates; i++) {
-				mode_index = 0;
-				power_state = (struct _ATOM_PPLIB_STATE *)
-					(mode_info->atom_context->bios +
-					 data_offset +
-					 le16_to_cpu(power_info->info_4.usStateArrayOffset) +
-					 i * power_info->info_4.ucStateEntrySize);
-				non_clock_info = (struct _ATOM_PPLIB_NONCLOCK_INFO *)
-					(mode_info->atom_context->bios +
-					 data_offset +
-					 le16_to_cpu(power_info->info_4.usNonClockInfoArrayOffset) +
-					 (power_state->ucNonClockStateIndex *
-					  power_info->info_4.ucNonClockSize));
-				for (j = 0; j < (power_info->info_4.ucStateEntrySize - 1); j++) {
-					if (rdev->flags & RADEON_IS_IGP) {
-						struct _ATOM_PPLIB_RS780_CLOCK_INFO *clock_info =
-							(struct _ATOM_PPLIB_RS780_CLOCK_INFO *)
-							(mode_info->atom_context->bios +
-							 data_offset +
-							 le16_to_cpu(power_info->info_4.usClockInfoArrayOffset) +
-							 (power_state->ucClockStateIndices[j] *
-							  power_info->info_4.ucClockInfoSize));
-						sclk = le16_to_cpu(clock_info->usLowEngineClockLow);
-						sclk |= clock_info->ucLowEngineClockHigh << 16;
-						rdev->pm.power_state[state_index].clock_info[mode_index].sclk = sclk;
-						/* skip invalid modes */
-						if (rdev->pm.power_state[state_index].clock_info[mode_index].sclk == 0)
-							continue;
-						/* voltage works differently on IGPs */
-						mode_index++;
-					} else if (ASIC_IS_DCE4(rdev)) {
-						struct _ATOM_PPLIB_EVERGREEN_CLOCK_INFO *clock_info =
-							(struct _ATOM_PPLIB_EVERGREEN_CLOCK_INFO *)
-							(mode_info->atom_context->bios +
-							 data_offset +
-							 le16_to_cpu(power_info->info_4.usClockInfoArrayOffset) +
-							 (power_state->ucClockStateIndices[j] *
-							  power_info->info_4.ucClockInfoSize));
-						sclk = le16_to_cpu(clock_info->usEngineClockLow);
-						sclk |= clock_info->ucEngineClockHigh << 16;
-						mclk = le16_to_cpu(clock_info->usMemoryClockLow);
-						mclk |= clock_info->ucMemoryClockHigh << 16;
-						rdev->pm.power_state[state_index].clock_info[mode_index].mclk = mclk;
-						rdev->pm.power_state[state_index].clock_info[mode_index].sclk = sclk;
-						/* skip invalid modes */
-						if ((rdev->pm.power_state[state_index].clock_info[mode_index].mclk == 0) ||
-						    (rdev->pm.power_state[state_index].clock_info[mode_index].sclk == 0))
-							continue;
-						rdev->pm.power_state[state_index].clock_info[mode_index].voltage.type =
-							VOLTAGE_SW;
-						rdev->pm.power_state[state_index].clock_info[mode_index].voltage.voltage =
-							clock_info->usVDDC;
-						/* XXX usVDDCI */
-						mode_index++;
-					} else {
-						struct _ATOM_PPLIB_R600_CLOCK_INFO *clock_info =
-							(struct _ATOM_PPLIB_R600_CLOCK_INFO *)
-							(mode_info->atom_context->bios +
-							 data_offset +
-							 le16_to_cpu(power_info->info_4.usClockInfoArrayOffset) +
-							 (power_state->ucClockStateIndices[j] *
-							  power_info->info_4.ucClockInfoSize));
-						sclk = le16_to_cpu(clock_info->usEngineClockLow);
-						sclk |= clock_info->ucEngineClockHigh << 16;
-						mclk = le16_to_cpu(clock_info->usMemoryClockLow);
-						mclk |= clock_info->ucMemoryClockHigh << 16;
-						rdev->pm.power_state[state_index].clock_info[mode_index].mclk = mclk;
-						rdev->pm.power_state[state_index].clock_info[mode_index].sclk = sclk;
-						/* skip invalid modes */
-						if ((rdev->pm.power_state[state_index].clock_info[mode_index].mclk == 0) ||
-						    (rdev->pm.power_state[state_index].clock_info[mode_index].sclk == 0))
-							continue;
-						rdev->pm.power_state[state_index].clock_info[mode_index].voltage.type =
-							VOLTAGE_SW;
-						rdev->pm.power_state[state_index].clock_info[mode_index].voltage.voltage =
-							clock_info->usVDDC;
-						mode_index++;
-					}
-				}
-				rdev->pm.power_state[state_index].num_clock_modes = mode_index;
-				if (mode_index) {
-					misc = le32_to_cpu(non_clock_info->ulCapsAndSettings);
-					misc2 = le16_to_cpu(non_clock_info->usClassification);
-					rdev->pm.power_state[state_index].misc = misc;
-					rdev->pm.power_state[state_index].misc2 = misc2;
-					rdev->pm.power_state[state_index].pcie_lanes =
-						((misc & ATOM_PPLIB_PCIE_LINK_WIDTH_MASK) >>
-						ATOM_PPLIB_PCIE_LINK_WIDTH_SHIFT) + 1;
-					switch (misc2 & ATOM_PPLIB_CLASSIFICATION_UI_MASK) {
-					case ATOM_PPLIB_CLASSIFICATION_UI_BATTERY:
-						rdev->pm.power_state[state_index].type =
-							POWER_STATE_TYPE_BATTERY;
-						break;
-					case ATOM_PPLIB_CLASSIFICATION_UI_BALANCED:
-						rdev->pm.power_state[state_index].type =
-							POWER_STATE_TYPE_BALANCED;
-						break;
-					case ATOM_PPLIB_CLASSIFICATION_UI_PERFORMANCE:
-						rdev->pm.power_state[state_index].type =
-							POWER_STATE_TYPE_PERFORMANCE;
-						break;
-					case ATOM_PPLIB_CLASSIFICATION_UI_NONE:
-						if (misc2 & ATOM_PPLIB_CLASSIFICATION_3DPERFORMANCE)
-							rdev->pm.power_state[state_index].type =
-								POWER_STATE_TYPE_PERFORMANCE;
-						break;
-					}
-					rdev->pm.power_state[state_index].flags = 0;
-					if (misc & ATOM_PPLIB_SINGLE_DISPLAY_ONLY)
-						rdev->pm.power_state[state_index].flags |=
-							RADEON_PM_STATE_SINGLE_DISPLAY_ONLY;
-					if (misc2 & ATOM_PPLIB_CLASSIFICATION_BOOT) {
-						rdev->pm.power_state[state_index].type =
-							POWER_STATE_TYPE_DEFAULT;
-						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];
-						/* patch the table values with the default slck/mclk from firmware info */
-						for (j = 0; j < mode_index; j++) {
-							rdev->pm.power_state[state_index].clock_info[j].mclk =
-								rdev->clock.default_mclk;
-							rdev->pm.power_state[state_index].clock_info[j].sclk =
-								rdev->clock.default_sclk;
-							if (vddc)
-								rdev->pm.power_state[state_index].clock_info[j].voltage.voltage =
-									vddc;
-						}
-					}
-					state_index++;
-				}
-			}
-			/* if multiple clock modes, mark the lowest as no display */
-			for (i = 0; i < state_index; i++) {
-				if (rdev->pm.power_state[i].num_clock_modes > 1)
-					rdev->pm.power_state[i].clock_info[0].flags |=
-						RADEON_PM_MODE_NO_DISPLAY;
-			}
-			/* first mode is usually default */
-			if (rdev->pm.default_power_state_index == -1) {
-				rdev->pm.power_state[0].type =
-					POWER_STATE_TYPE_DEFAULT;
-				rdev->pm.default_power_state_index = 0;
-				rdev->pm.power_state[0].default_clock_mode =
-					&rdev->pm.power_state[0].clock_info[0];
+	if (atom_parse_data_header(mode_info->atom_context, index, NULL,
+				   &frev, &crev, &data_offset)) {
+		firmware_info =
+			(union firmware_info *)(mode_info->atom_context->bios +
+						data_offset);
+		vddc = le16_to_cpu(firmware_info->info_14.usBootUpVDDCVoltage);
+	}
+
+	return vddc;
+}
+
+static void radeon_atombios_parse_pplib_non_clock_info(struct radeon_device *rdev,
+						       int state_index, int mode_index,
+						       struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info)
+{
+	int j;
+	u32 misc = le32_to_cpu(non_clock_info->ulCapsAndSettings);
+	u32 misc2 = le16_to_cpu(non_clock_info->usClassification);
+	u16 vddc = radeon_atombios_get_default_vddc(rdev);
+
+	rdev->pm.power_state[state_index].misc = misc;
+	rdev->pm.power_state[state_index].misc2 = misc2;
+	rdev->pm.power_state[state_index].pcie_lanes =
+		((misc & ATOM_PPLIB_PCIE_LINK_WIDTH_MASK) >>
+		 ATOM_PPLIB_PCIE_LINK_WIDTH_SHIFT) + 1;
+	switch (misc2 & ATOM_PPLIB_CLASSIFICATION_UI_MASK) {
+	case ATOM_PPLIB_CLASSIFICATION_UI_BATTERY:
+		rdev->pm.power_state[state_index].type =
+			POWER_STATE_TYPE_BATTERY;
+		break;
+	case ATOM_PPLIB_CLASSIFICATION_UI_BALANCED:
+		rdev->pm.power_state[state_index].type =
+			POWER_STATE_TYPE_BALANCED;
+		break;
+	case ATOM_PPLIB_CLASSIFICATION_UI_PERFORMANCE:
+		rdev->pm.power_state[state_index].type =
+			POWER_STATE_TYPE_PERFORMANCE;
+		break;
+	case ATOM_PPLIB_CLASSIFICATION_UI_NONE:
+		if (misc2 & ATOM_PPLIB_CLASSIFICATION_3DPERFORMANCE)
+			rdev->pm.power_state[state_index].type =
+				POWER_STATE_TYPE_PERFORMANCE;
+		break;
+	}
+	rdev->pm.power_state[state_index].flags = 0;
+	if (misc & ATOM_PPLIB_SINGLE_DISPLAY_ONLY)
+		rdev->pm.power_state[state_index].flags |=
+			RADEON_PM_STATE_SINGLE_DISPLAY_ONLY;
+	if (misc2 & ATOM_PPLIB_CLASSIFICATION_BOOT) {
+		rdev->pm.power_state[state_index].type =
+			POWER_STATE_TYPE_DEFAULT;
+		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)) {
+			/* 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;
+			rdev->pm.default_vddc = rdev->pm.power_state[state_index].clock_info[0].voltage.voltage;
+		} else {
+			/* patch the table values with the default slck/mclk from firmware info */
+			for (j = 0; j < mode_index; j++) {
+				rdev->pm.power_state[state_index].clock_info[j].mclk =
+					rdev->clock.default_mclk;
+				rdev->pm.power_state[state_index].clock_info[j].sclk =
+					rdev->clock.default_sclk;
+				if (vddc)
+					rdev->pm.power_state[state_index].clock_info[j].voltage.voltage =
+						vddc;
 			}
 		}
+	}
+}
+
+static bool radeon_atombios_parse_pplib_clock_info(struct radeon_device *rdev,
+						   int state_index, int mode_index,
+						   union pplib_clock_info *clock_info)
+{
+	u32 sclk, mclk;
+
+	if (rdev->flags & RADEON_IS_IGP) {
+		if (rdev->family >= CHIP_PALM) {
+			sclk = le16_to_cpu(clock_info->sumo.usEngineClockLow);
+			sclk |= clock_info->sumo.ucEngineClockHigh << 16;
+			rdev->pm.power_state[state_index].clock_info[mode_index].sclk = sclk;
+		} else {
+			sclk = le16_to_cpu(clock_info->rs780.usLowEngineClockLow);
+			sclk |= clock_info->rs780.ucLowEngineClockHigh << 16;
+			rdev->pm.power_state[state_index].clock_info[mode_index].sclk = sclk;
+		}
+	} else if (ASIC_IS_DCE4(rdev)) {
+		sclk = le16_to_cpu(clock_info->evergreen.usEngineClockLow);
+		sclk |= clock_info->evergreen.ucEngineClockHigh << 16;
+		mclk = le16_to_cpu(clock_info->evergreen.usMemoryClockLow);
+		mclk |= clock_info->evergreen.ucMemoryClockHigh << 16;
+		rdev->pm.power_state[state_index].clock_info[mode_index].mclk = mclk;
+		rdev->pm.power_state[state_index].clock_info[mode_index].sclk = sclk;
+		rdev->pm.power_state[state_index].clock_info[mode_index].voltage.type =
+			VOLTAGE_SW;
+		rdev->pm.power_state[state_index].clock_info[mode_index].voltage.voltage =
+			le16_to_cpu(clock_info->evergreen.usVDDC);
 	} else {
-		/* add the default mode */
-		rdev->pm.power_state[state_index].type =
+		sclk = le16_to_cpu(clock_info->r600.usEngineClockLow);
+		sclk |= clock_info->r600.ucEngineClockHigh << 16;
+		mclk = le16_to_cpu(clock_info->r600.usMemoryClockLow);
+		mclk |= clock_info->r600.ucMemoryClockHigh << 16;
+		rdev->pm.power_state[state_index].clock_info[mode_index].mclk = mclk;
+		rdev->pm.power_state[state_index].clock_info[mode_index].sclk = sclk;
+		rdev->pm.power_state[state_index].clock_info[mode_index].voltage.type =
+			VOLTAGE_SW;
+		rdev->pm.power_state[state_index].clock_info[mode_index].voltage.voltage =
+			le16_to_cpu(clock_info->r600.usVDDC);
+	}
+
+	if (rdev->flags & RADEON_IS_IGP) {
+		/* skip invalid modes */
+		if (rdev->pm.power_state[state_index].clock_info[mode_index].sclk == 0)
+			return false;
+	} else {
+		/* skip invalid modes */
+		if ((rdev->pm.power_state[state_index].clock_info[mode_index].mclk == 0) ||
+		    (rdev->pm.power_state[state_index].clock_info[mode_index].sclk == 0))
+			return false;
+	}
+	return true;
+}
+
+static int radeon_atombios_parse_power_table_4_5(struct radeon_device *rdev)
+{
+	struct radeon_mode_info *mode_info = &rdev->mode_info;
+	struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info;
+	union pplib_power_state *power_state;
+	int i, j;
+	int state_index = 0, mode_index = 0;
+	union pplib_clock_info *clock_info;
+	bool valid;
+	union power_info *power_info;
+	int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo);
+        u16 data_offset;
+	u8 frev, crev;
+
+	if (!atom_parse_data_header(mode_info->atom_context, index, NULL,
+				   &frev, &crev, &data_offset))
+		return state_index;
+	power_info = (union power_info *)(mode_info->atom_context->bios + data_offset);
+
+	radeon_atombios_add_pplib_thermal_controller(rdev, &power_info->pplib.sThermalController);
+	rdev->pm.power_state = kzalloc(sizeof(struct radeon_power_state) *
+				       power_info->pplib.ucNumStates, GFP_KERNEL);
+	if (!rdev->pm.power_state)
+		return state_index;
+	/* first mode is usually default, followed by low to high */
+	for (i = 0; i < power_info->pplib.ucNumStates; i++) {
+		mode_index = 0;
+		power_state = (union pplib_power_state *)
+			(mode_info->atom_context->bios + data_offset +
+			 le16_to_cpu(power_info->pplib.usStateArrayOffset) +
+			 i * power_info->pplib.ucStateEntrySize);
+		non_clock_info = (struct _ATOM_PPLIB_NONCLOCK_INFO *)
+			(mode_info->atom_context->bios + data_offset +
+			 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[state_index].num_clock_modes = mode_index;
+		if (mode_index) {
+			radeon_atombios_parse_pplib_non_clock_info(rdev, state_index, mode_index,
+								   non_clock_info);
+			state_index++;
+		}
+	}
+	/* if multiple clock modes, mark the lowest as no display */
+	for (i = 0; i < state_index; i++) {
+		if (rdev->pm.power_state[i].num_clock_modes > 1)
+			rdev->pm.power_state[i].clock_info[0].flags |=
+				RADEON_PM_MODE_NO_DISPLAY;
+	}
+	/* first mode is usually default */
+	if (rdev->pm.default_power_state_index == -1) {
+		rdev->pm.power_state[0].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.default_power_state_index = 0;
+		rdev->pm.power_state[0].default_clock_mode =
+			&rdev->pm.power_state[0].clock_info[0];
+	}
+	return state_index;
+}
+
+static int radeon_atombios_parse_power_table_6(struct radeon_device *rdev)
+{
+	struct radeon_mode_info *mode_info = &rdev->mode_info;
+	struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info;
+	union pplib_power_state *power_state;
+	int i, j, non_clock_array_index, clock_array_index;
+	int state_index = 0, mode_index = 0;
+	union pplib_clock_info *clock_info;
+	struct StateArray *state_array;
+	struct ClockInfoArray *clock_info_array;
+	struct NonClockInfoArray *non_clock_info_array;
+	bool valid;
+	union power_info *power_info;
+	int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo);
+        u16 data_offset;
+	u8 frev, crev;
+
+	if (!atom_parse_data_header(mode_info->atom_context, index, NULL,
+				   &frev, &crev, &data_offset))
+		return state_index;
+	power_info = (union power_info *)(mode_info->atom_context->bios + data_offset);
+
+	radeon_atombios_add_pplib_thermal_controller(rdev, &power_info->pplib.sThermalController);
+	state_array = (struct StateArray *)
+		(mode_info->atom_context->bios + data_offset +
+		 le16_to_cpu(power_info->pplib.usStateArrayOffset));
+	clock_info_array = (struct ClockInfoArray *)
+		(mode_info->atom_context->bios + data_offset +
+		 le16_to_cpu(power_info->pplib.usClockInfoArrayOffset));
+	non_clock_info_array = (struct NonClockInfoArray *)
+		(mode_info->atom_context->bios + data_offset +
+		 le16_to_cpu(power_info->pplib.usNonClockInfoArrayOffset));
+	rdev->pm.power_state = kzalloc(sizeof(struct radeon_power_state) *
+				       state_array->ucNumEntries, GFP_KERNEL);
+	if (!rdev->pm.power_state)
+		return state_index;
+	for (i = 0; i < state_array->ucNumEntries; i++) {
+		mode_index = 0;
+		power_state = (union pplib_power_state *)&state_array->states[i];
+		/* XXX this might be an inagua bug... */
+		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[state_index].num_clock_modes = mode_index;
+		if (mode_index) {
+			radeon_atombios_parse_pplib_non_clock_info(rdev, state_index, mode_index,
+								   non_clock_info);
+			state_index++;
+		}
+	}
+	/* if multiple clock modes, mark the lowest as no display */
+	for (i = 0; i < state_index; i++) {
+		if (rdev->pm.power_state[i].num_clock_modes > 1)
+			rdev->pm.power_state[i].clock_info[0].flags |=
+				RADEON_PM_MODE_NO_DISPLAY;
+	}
+	/* first mode is usually default */
+	if (rdev->pm.default_power_state_index == -1) {
+		rdev->pm.power_state[0].type =
+			POWER_STATE_TYPE_DEFAULT;
+		rdev->pm.default_power_state_index = 0;
+		rdev->pm.power_state[0].default_clock_mode =
+			&rdev->pm.power_state[0].clock_info[0];
+	}
+	return state_index;
+}
+
+void radeon_atombios_get_power_modes(struct radeon_device *rdev)
+{
+	struct radeon_mode_info *mode_info = &rdev->mode_info;
+	int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo);
+	u16 data_offset;
+	u8 frev, crev;
+	int state_index = 0;
+
+	rdev->pm.default_power_state_index = -1;
+
+	if (atom_parse_data_header(mode_info->atom_context, index, NULL,
+				   &frev, &crev, &data_offset)) {
+		switch (frev) {
+		case 1:
+		case 2:
+		case 3:
+			state_index = radeon_atombios_parse_power_table_1_3(rdev);
+			break;
+		case 4:
+		case 5:
+			state_index = radeon_atombios_parse_power_table_4_5(rdev);
+			break;
+		case 6:
+			state_index = radeon_atombios_parse_power_table_6(rdev);
+			break;
+		default:
+			break;
+		}
+	} 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.num_power_states = state_index;
@@ -2269,7 +2533,7 @@ uint32_t radeon_atom_get_engine_clock(st
 	int index = GetIndexIntoMasterTable(COMMAND, GetEngineClock);
 
 	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
-	return args.ulReturnEngineClock;
+	return le32_to_cpu(args.ulReturnEngineClock);
 }
 
 uint32_t radeon_atom_get_memory_clock(struct radeon_device *rdev)
@@ -2278,7 +2542,7 @@ uint32_t radeon_atom_get_memory_clock(st
 	int index = GetIndexIntoMasterTable(COMMAND, GetMemoryClock);
 
 	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
-	return args.ulReturnMemoryClock;
+	return le32_to_cpu(args.ulReturnMemoryClock);
 }
 
 void radeon_atom_set_engine_clock(struct radeon_device *rdev,
@@ -2287,7 +2551,7 @@ void radeon_atom_set_engine_clock(struct
 	SET_ENGINE_CLOCK_PS_ALLOCATION args;
 	int index = GetIndexIntoMasterTable(COMMAND, SetEngineClock);
 
-	args.ulTargetEngineClock = eng_clock;	/* 10 khz */
+	args.ulTargetEngineClock = cpu_to_le32(eng_clock);	/* 10 khz */
 
 	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
 }
@@ -2301,7 +2565,7 @@ void radeon_atom_set_memory_clock(struct
 	if (rdev->flags & RADEON_IS_IGP)
 		return;
 
-	args.ulTargetMemoryClock = mem_clock;	/* 10 khz */
+	args.ulTargetMemoryClock = cpu_to_le32(mem_clock);	/* 10 khz */
 
 	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
 }
@@ -2359,7 +2623,7 @@ void radeon_atom_initialize_bios_scratch
 	bios_2_scratch &= ~ATOM_S2_VRI_BRIGHT_ENABLE;
 
 	/* tell the bios not to handle mode switching */
-	bios_6_scratch |= (ATOM_S6_ACC_BLOCK_DISPLAY_SWITCH | ATOM_S6_ACC_MODE);
+	bios_6_scratch |= ATOM_S6_ACC_BLOCK_DISPLAY_SWITCH;
 
 	if (rdev->family >= CHIP_R600) {
 		WREG32(R600_BIOS_2_SCRATCH, bios_2_scratch);
@@ -2410,10 +2674,13 @@ void radeon_atom_output_lock(struct drm_
 	else
 		bios_6_scratch = RREG32(RADEON_BIOS_6_SCRATCH);
 
-	if (lock)
+	if (lock) {
 		bios_6_scratch |= ATOM_S6_CRITICAL_STATE;
-	else
+		bios_6_scratch &= ~ATOM_S6_ACC_MODE;
+	} else {
 		bios_6_scratch &= ~ATOM_S6_CRITICAL_STATE;
+		bios_6_scratch |= ATOM_S6_ACC_MODE;
+	}
 
 	if (rdev->family >= CHIP_R600)
 		WREG32(R600_BIOS_6_SCRATCH, bios_6_scratch);
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/radeon_bios.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/radeon_bios.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/radeon_bios.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/radeon_bios.c	2011-03-14 21:20:32.000000000 -0400
@@ -131,6 +131,45 @@ static bool radeon_atrm_get_bios(struct
 	return true;
 }
 
+static bool ni_read_disabled_bios(struct radeon_device *rdev)
+{
+	u32 bus_cntl;
+	u32 d1vga_control;
+	u32 d2vga_control;
+	u32 vga_render_control;
+	u32 rom_cntl;
+	bool r;
+
+	bus_cntl = RREG32(R600_BUS_CNTL);
+	d1vga_control = RREG32(AVIVO_D1VGA_CONTROL);
+	d2vga_control = RREG32(AVIVO_D2VGA_CONTROL);
+	vga_render_control = RREG32(AVIVO_VGA_RENDER_CONTROL);
+	rom_cntl = RREG32(R600_ROM_CNTL);
+
+	/* enable the rom */
+	WREG32(R600_BUS_CNTL, (bus_cntl & ~R600_BIOS_ROM_DIS));
+	/* Disable VGA mode */
+	WREG32(AVIVO_D1VGA_CONTROL,
+	       (d1vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE |
+		AVIVO_DVGA_CONTROL_TIMING_SELECT)));
+	WREG32(AVIVO_D2VGA_CONTROL,
+	       (d2vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE |
+		AVIVO_DVGA_CONTROL_TIMING_SELECT)));
+	WREG32(AVIVO_VGA_RENDER_CONTROL,
+	       (vga_render_control & ~AVIVO_VGA_VSTATUS_CNTL_MASK));
+	WREG32(R600_ROM_CNTL, rom_cntl | R600_SCK_OVERWRITE);
+
+	r = radeon_read_bios(rdev);
+
+	/* restore regs */
+	WREG32(R600_BUS_CNTL, bus_cntl);
+	WREG32(AVIVO_D1VGA_CONTROL, d1vga_control);
+	WREG32(AVIVO_D2VGA_CONTROL, d2vga_control);
+	WREG32(AVIVO_VGA_RENDER_CONTROL, vga_render_control);
+	WREG32(R600_ROM_CNTL, rom_cntl);
+	return r;
+}
+
 static bool r700_read_disabled_bios(struct radeon_device *rdev)
 {
 	uint32_t viph_control;
@@ -416,6 +455,8 @@ static bool radeon_read_disabled_bios(st
 {
 	if (rdev->flags & RADEON_IS_IGP)
 		return igp_read_bios_from_vram(rdev);
+	else if (rdev->family >= CHIP_BARTS)
+		return ni_read_disabled_bios(rdev);
 	else if (rdev->family >= CHIP_RV770)
 		return r700_read_disabled_bios(rdev);
 	else if (rdev->family >= CHIP_R600)
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/radeon_combios.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/radeon_combios.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/radeon_combios.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/radeon_combios.c	2011-03-14 21:20:32.000000000 -0400
@@ -471,8 +471,9 @@ bool radeon_combios_check_hardcoded_edid
 	return true;
 }
 
+/* this is used for atom LCDs as well */
 struct edid *
-radeon_combios_get_hardcoded_edid(struct radeon_device *rdev)
+radeon_bios_get_hardcoded_edid(struct radeon_device *rdev)
 {
 	if (rdev->mode_info.bios_hardcoded_edid)
 		return rdev->mode_info.bios_hardcoded_edid;
@@ -1503,6 +1504,11 @@ bool radeon_get_legacy_connector_info_fr
 			   (rdev->pdev->subsystem_device == 0x4a48)) {
 			/* Mac X800 */
 			rdev->mode_info.connector_table = CT_MAC_X800;
+		} else if ((rdev->pdev->device == 0x4150) &&
+			   (rdev->pdev->subsystem_vendor == 0x1002) &&
+			   (rdev->pdev->subsystem_device == 0x4150)) {
+			/* Mac G5 9600 */
+			rdev->mode_info.connector_table = CT_MAC_G5_9600;
 		} else
 #endif /* CONFIG_PPC_PMAC */
 #ifdef CONFIG_PPC64
@@ -2021,6 +2027,48 @@ bool radeon_get_legacy_connector_info_fr
 					    CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I,
 					    &hpd);
 		break;
+	case CT_MAC_G5_9600:
+		DRM_INFO("Connector Table: %d (mac g5 9600)\n",
+			 rdev->mode_info.connector_table);
+		/* DVI - tv dac, dvo */
+		ddc_i2c = combios_setup_i2c_bus(rdev, DDC_DVI, 0, 0);
+		hpd.hpd = RADEON_HPD_1; /* ??? */
+		radeon_add_legacy_encoder(dev,
+					  radeon_get_encoder_enum(dev,
+								  ATOM_DEVICE_DFP2_SUPPORT,
+								  0),
+					  ATOM_DEVICE_DFP2_SUPPORT);
+		radeon_add_legacy_encoder(dev,
+					  radeon_get_encoder_enum(dev,
+								  ATOM_DEVICE_CRT2_SUPPORT,
+								  2),
+					  ATOM_DEVICE_CRT2_SUPPORT);
+		radeon_add_legacy_connector(dev, 0,
+					    ATOM_DEVICE_DFP2_SUPPORT |
+					    ATOM_DEVICE_CRT2_SUPPORT,
+					    DRM_MODE_CONNECTOR_DVII, &ddc_i2c,
+					    CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I,
+					    &hpd);
+		/* ADC - primary dac, internal tmds */
+		ddc_i2c = combios_setup_i2c_bus(rdev, DDC_VGA, 0, 0);
+		hpd.hpd = RADEON_HPD_2; /* ??? */
+		radeon_add_legacy_encoder(dev,
+					  radeon_get_encoder_enum(dev,
+								  ATOM_DEVICE_DFP1_SUPPORT,
+								  0),
+					  ATOM_DEVICE_DFP1_SUPPORT);
+		radeon_add_legacy_encoder(dev,
+					  radeon_get_encoder_enum(dev,
+								  ATOM_DEVICE_CRT1_SUPPORT,
+								  1),
+					  ATOM_DEVICE_CRT1_SUPPORT);
+		radeon_add_legacy_connector(dev, 1,
+					    ATOM_DEVICE_DFP1_SUPPORT |
+					    ATOM_DEVICE_CRT1_SUPPORT,
+					    DRM_MODE_CONNECTOR_DVII, &ddc_i2c,
+					    CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I,
+					    &hpd);
+		break;
 	default:
 		DRM_INFO("Connector table: %d (invalid)\n",
 			 rdev->mode_info.connector_table);
@@ -2441,6 +2489,17 @@ void radeon_combios_get_power_modes(stru
 
 	rdev->pm.default_power_state_index = -1;
 
+	/* 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->flags & RADEON_IS_MOBILITY) {
 		offset = combios_get_table_offset(dev, COMBIOS_POWERPLAY_INFO_TABLE);
 		if (offset) {
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/radeon_connectors.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/radeon_connectors.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/radeon_connectors.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/radeon_connectors.c	2011-03-14 21:20:32.000000000 -0400
@@ -472,6 +472,9 @@ static int radeon_lvds_get_modes(struct
 	if (mode) {
 		ret = 1;
 		drm_mode_probed_add(connector, mode);
+		/* add the width/height from vbios tables if available */
+		connector->display_info.width_mm = mode->width_mm;
+		connector->display_info.height_mm = mode->height_mm;
 		/* add scaled modes */
 		radeon_add_common_modes(encoder, connector);
 	}
@@ -1216,7 +1219,7 @@ radeon_add_atom_connector(struct drm_dev
 		if (ASIC_IS_AVIVO(rdev)) {
 			drm_connector_attach_property(&radeon_connector->base,
 						      rdev->mode_info.underscan_property,
-						      UNDERSCAN_AUTO);
+						      UNDERSCAN_OFF);
 			drm_connector_attach_property(&radeon_connector->base,
 						      rdev->mode_info.underscan_hborder_property,
 						      0);
@@ -1256,7 +1259,7 @@ radeon_add_atom_connector(struct drm_dev
 		if (ASIC_IS_AVIVO(rdev)) {
 			drm_connector_attach_property(&radeon_connector->base,
 						      rdev->mode_info.underscan_property,
-						      UNDERSCAN_AUTO);
+						      UNDERSCAN_OFF);
 			drm_connector_attach_property(&radeon_connector->base,
 						      rdev->mode_info.underscan_hborder_property,
 						      0);
@@ -1299,7 +1302,7 @@ radeon_add_atom_connector(struct drm_dev
 		if (ASIC_IS_AVIVO(rdev)) {
 			drm_connector_attach_property(&radeon_connector->base,
 						      rdev->mode_info.underscan_property,
-						      UNDERSCAN_AUTO);
+						      UNDERSCAN_OFF);
 			drm_connector_attach_property(&radeon_connector->base,
 						      rdev->mode_info.underscan_hborder_property,
 						      0);
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/radeon_cs.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/radeon_cs.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/radeon_cs.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/radeon_cs.c	2011-03-14 21:20:32.000000000 -0400
@@ -77,13 +77,13 @@ int radeon_cs_parser_relocs(struct radeo
 			p->relocs_ptr[i] = &p->relocs[i];
 			p->relocs[i].robj = p->relocs[i].gobj->driver_private;
 			p->relocs[i].lobj.bo = p->relocs[i].robj;
-			p->relocs[i].lobj.rdomain = r->read_domains;
 			p->relocs[i].lobj.wdomain = r->write_domain;
+			p->relocs[i].lobj.rdomain = r->read_domains;
+			p->relocs[i].lobj.tv.bo = &p->relocs[i].robj->tbo;
 			p->relocs[i].handle = r->handle;
 			p->relocs[i].flags = r->flags;
-			INIT_LIST_HEAD(&p->relocs[i].lobj.list);
 			radeon_bo_list_add_object(&p->relocs[i].lobj,
-						&p->validated);
+						  &p->validated);
 		}
 	}
 	return radeon_bo_list_validate(&p->validated);
@@ -189,10 +189,13 @@ static void radeon_cs_parser_fini(struct
 {
 	unsigned i;
 
-	if (!error && parser->ib) {
-		radeon_bo_list_fence(&parser->validated, parser->ib->fence);
-	}
-	radeon_bo_list_unreserve(&parser->validated);
+
+	if (!error && parser->ib)
+		ttm_eu_fence_buffer_objects(&parser->validated,
+					    parser->ib->fence);
+	else
+		ttm_eu_backoff_reservation(&parser->validated);
+
 	if (parser->relocs != NULL) {
 		for (i = 0; i < parser->nrelocs; i++) {
 			if (parser->relocs[i].gobj)
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/radeon_device.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/radeon_device.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/radeon_device.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/radeon_device.c	2011-03-14 21:20:32.000000000 -0400
@@ -81,6 +81,10 @@ static const char radeon_family_name[][1
 	"JUNIPER",
 	"CYPRESS",
 	"HEMLOCK",
+	"PALM",
+	"BARTS",
+	"TURKS",
+	"CAICOS",
 	"LAST",
 };
 
@@ -224,6 +228,11 @@ int radeon_wb_init(struct radeon_device
 				rdev->wb.use_event = true;
 		}
 	}
+	/* always use writeback/events on NI */
+	if (ASIC_IS_DCE5(rdev)) {
+		rdev->wb.enabled = true;
+		rdev->wb.use_event = true;
+	}
 
 	dev_info(rdev->dev, "WB %sabled\n", rdev->wb.enabled ? "en" : "dis");
 
@@ -335,7 +344,12 @@ bool radeon_card_posted(struct radeon_de
 	uint32_t reg;
 
 	/* first check CRTCs */
-	if (ASIC_IS_DCE4(rdev)) {
+	if (ASIC_IS_DCE41(rdev)) {
+		reg = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET) |
+			RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET);
+		if (reg & EVERGREEN_CRTC_MASTER_EN)
+			return true;
+	} else if (ASIC_IS_DCE4(rdev)) {
 		reg = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET) |
 			RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET) |
 			RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET) |
@@ -636,20 +650,20 @@ void radeon_check_arguments(struct radeo
 static void radeon_switcheroo_set_state(struct pci_dev *pdev, enum vga_switcheroo_state state)
 {
 	struct drm_device *dev = pci_get_drvdata(pdev);
-	struct radeon_device *rdev = dev->dev_private;
 	pm_message_t pmm = { .event = PM_EVENT_SUSPEND };
 	if (state == VGA_SWITCHEROO_ON) {
 		printk(KERN_INFO "radeon: switched on\n");
 		/* don't suspend or resume card normally */
-		rdev->powered_down = false;
+		dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
 		radeon_resume_kms(dev);
+		dev->switch_power_state = DRM_SWITCH_POWER_ON;
 		drm_kms_helper_poll_enable(dev);
 	} else {
 		printk(KERN_INFO "radeon: switched off\n");
 		drm_kms_helper_poll_disable(dev);
+		dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
 		radeon_suspend_kms(dev, pmm);
-		/* don't suspend or resume card normally */
-		rdev->powered_down = true;
+		dev->switch_power_state = DRM_SWITCH_POWER_OFF;
 	}
 }
 
@@ -704,11 +718,6 @@ int radeon_device_init(struct radeon_dev
 	init_waitqueue_head(&rdev->irq.vblank_queue);
 	init_waitqueue_head(&rdev->irq.idle_queue);
 
-	/* setup workqueue */
-	rdev->wq = create_workqueue("radeon");
-	if (rdev->wq == NULL)
-		return -ENOMEM;
-
 	/* Set asic functions */
 	r = radeon_asic_init(rdev);
 	if (r)
@@ -773,6 +782,7 @@ int radeon_device_init(struct radeon_dev
 	vga_client_register(rdev->pdev, rdev, NULL, radeon_vga_set_decode);
 	vga_switcheroo_register_client(rdev->pdev,
 				       radeon_switcheroo_set_state,
+				       NULL,
 				       radeon_switcheroo_can_switch);
 
 	r = radeon_init(rdev);
@@ -806,7 +816,6 @@ void radeon_device_fini(struct radeon_de
 	/* evict vram memory */
 	radeon_bo_evict_vram(rdev);
 	radeon_fini(rdev);
-	destroy_workqueue(rdev->wq);
 	vga_switcheroo_unregister_client(rdev->pdev);
 	vga_client_register(rdev->pdev, NULL, NULL, NULL);
 	if (rdev->rio_mem)
@@ -835,7 +844,7 @@ int radeon_suspend_kms(struct drm_device
 	}
 	rdev = dev->dev_private;
 
-	if (rdev->powered_down)
+	if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)
 		return 0;
 
 	/* turn off display hw */
@@ -882,9 +891,9 @@ int radeon_suspend_kms(struct drm_device
 		pci_disable_device(dev->pdev);
 		pci_set_power_state(dev->pdev, PCI_D3hot);
 	}
-	acquire_console_sem();
+	console_lock();
 	radeon_fbdev_set_suspend(rdev, 1);
-	release_console_sem();
+	console_unlock();
 	return 0;
 }
 
@@ -893,14 +902,14 @@ int radeon_resume_kms(struct drm_device
 	struct drm_connector *connector;
 	struct radeon_device *rdev = dev->dev_private;
 
-	if (rdev->powered_down)
+	if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)
 		return 0;
 
-	acquire_console_sem();
+	console_lock();
 	pci_set_power_state(dev->pdev, PCI_D0);
 	pci_restore_state(dev->pdev);
 	if (pci_enable_device(dev->pdev)) {
-		release_console_sem();
+		console_unlock();
 		return -1;
 	}
 	pci_set_master(dev->pdev);
@@ -911,7 +920,7 @@ int radeon_resume_kms(struct drm_device
 	radeon_restore_bios_scratch_regs(rdev);
 
 	radeon_fbdev_set_suspend(rdev, 0);
-	release_console_sem();
+	console_unlock();
 
 	/* reset hpd state */
 	radeon_hpd_init(rdev);
@@ -927,8 +936,11 @@ int radeon_resume_kms(struct drm_device
 int radeon_gpu_reset(struct radeon_device *rdev)
 {
 	int r;
+	int resched;
 
 	radeon_save_bios_scratch_regs(rdev);
+	/* block TTM */
+	resched = ttm_bo_lock_delayed_workqueue(&rdev->mman.bdev);
 	radeon_suspend(rdev);
 
 	r = radeon_asic_reset(rdev);
@@ -937,6 +949,7 @@ int radeon_gpu_reset(struct radeon_devic
 		radeon_resume(rdev);
 		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 ? */
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/radeon_display.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/radeon_display.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/radeon_display.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/radeon_display.c	2011-03-14 21:20:32.000000000 -0400
@@ -68,7 +68,7 @@ static void avivo_crtc_load_lut(struct d
 	WREG32(AVIVO_D1GRPH_LUT_SEL + radeon_crtc->crtc_offset, radeon_crtc->crtc_id);
 }
 
-static void evergreen_crtc_load_lut(struct drm_crtc *crtc)
+static void dce4_crtc_load_lut(struct drm_crtc *crtc)
 {
 	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
 	struct drm_device *dev = crtc->dev;
@@ -98,6 +98,66 @@ static void evergreen_crtc_load_lut(stru
 	}
 }
 
+static void dce5_crtc_load_lut(struct drm_crtc *crtc)
+{
+	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
+	struct drm_device *dev = crtc->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	int i;
+
+	DRM_DEBUG_KMS("%d\n", radeon_crtc->crtc_id);
+
+	WREG32(NI_INPUT_CSC_CONTROL + radeon_crtc->crtc_offset,
+	       (NI_INPUT_CSC_GRPH_MODE(NI_INPUT_CSC_BYPASS) |
+		NI_INPUT_CSC_OVL_MODE(NI_INPUT_CSC_BYPASS)));
+	WREG32(NI_PRESCALE_GRPH_CONTROL + radeon_crtc->crtc_offset,
+	       NI_GRPH_PRESCALE_BYPASS);
+	WREG32(NI_PRESCALE_OVL_CONTROL + radeon_crtc->crtc_offset,
+	       NI_OVL_PRESCALE_BYPASS);
+	WREG32(NI_INPUT_GAMMA_CONTROL + radeon_crtc->crtc_offset,
+	       (NI_GRPH_INPUT_GAMMA_MODE(NI_INPUT_GAMMA_USE_LUT) |
+		NI_OVL_INPUT_GAMMA_MODE(NI_INPUT_GAMMA_USE_LUT)));
+
+	WREG32(EVERGREEN_DC_LUT_CONTROL + radeon_crtc->crtc_offset, 0);
+
+	WREG32(EVERGREEN_DC_LUT_BLACK_OFFSET_BLUE + radeon_crtc->crtc_offset, 0);
+	WREG32(EVERGREEN_DC_LUT_BLACK_OFFSET_GREEN + radeon_crtc->crtc_offset, 0);
+	WREG32(EVERGREEN_DC_LUT_BLACK_OFFSET_RED + radeon_crtc->crtc_offset, 0);
+
+	WREG32(EVERGREEN_DC_LUT_WHITE_OFFSET_BLUE + radeon_crtc->crtc_offset, 0xffff);
+	WREG32(EVERGREEN_DC_LUT_WHITE_OFFSET_GREEN + radeon_crtc->crtc_offset, 0xffff);
+	WREG32(EVERGREEN_DC_LUT_WHITE_OFFSET_RED + radeon_crtc->crtc_offset, 0xffff);
+
+	WREG32(EVERGREEN_DC_LUT_RW_MODE + radeon_crtc->crtc_offset, 0);
+	WREG32(EVERGREEN_DC_LUT_WRITE_EN_MASK + radeon_crtc->crtc_offset, 0x00000007);
+
+	WREG32(EVERGREEN_DC_LUT_RW_INDEX + radeon_crtc->crtc_offset, 0);
+	for (i = 0; i < 256; i++) {
+		WREG32(EVERGREEN_DC_LUT_30_COLOR + radeon_crtc->crtc_offset,
+		       (radeon_crtc->lut_r[i] << 20) |
+		       (radeon_crtc->lut_g[i] << 10) |
+		       (radeon_crtc->lut_b[i] << 0));
+	}
+
+	WREG32(NI_DEGAMMA_CONTROL + radeon_crtc->crtc_offset,
+	       (NI_GRPH_DEGAMMA_MODE(NI_DEGAMMA_BYPASS) |
+		NI_OVL_DEGAMMA_MODE(NI_DEGAMMA_BYPASS) |
+		NI_ICON_DEGAMMA_MODE(NI_DEGAMMA_BYPASS) |
+		NI_CURSOR_DEGAMMA_MODE(NI_DEGAMMA_BYPASS)));
+	WREG32(NI_GAMUT_REMAP_CONTROL + radeon_crtc->crtc_offset,
+	       (NI_GRPH_GAMUT_REMAP_MODE(NI_GAMUT_REMAP_BYPASS) |
+		NI_OVL_GAMUT_REMAP_MODE(NI_GAMUT_REMAP_BYPASS)));
+	WREG32(NI_REGAMMA_CONTROL + radeon_crtc->crtc_offset,
+	       (NI_GRPH_REGAMMA_MODE(NI_REGAMMA_BYPASS) |
+		NI_OVL_REGAMMA_MODE(NI_REGAMMA_BYPASS)));
+	WREG32(NI_OUTPUT_CSC_CONTROL + radeon_crtc->crtc_offset,
+	       (NI_OUTPUT_CSC_GRPH_MODE(NI_OUTPUT_CSC_BYPASS) |
+		NI_OUTPUT_CSC_OVL_MODE(NI_OUTPUT_CSC_BYPASS)));
+	/* XXX match this to the depth of the crtc fmt block, move to modeset? */
+	WREG32(0x6940 + radeon_crtc->crtc_offset, 0);
+
+}
+
 static void legacy_crtc_load_lut(struct drm_crtc *crtc)
 {
 	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
@@ -130,8 +190,10 @@ void radeon_crtc_load_lut(struct drm_crt
 	if (!crtc->enabled)
 		return;
 
-	if (ASIC_IS_DCE4(rdev))
-		evergreen_crtc_load_lut(crtc);
+	if (ASIC_IS_DCE5(rdev))
+		dce5_crtc_load_lut(crtc);
+	else if (ASIC_IS_DCE4(rdev))
+		dce4_crtc_load_lut(crtc);
 	else if (ASIC_IS_AVIVO(rdev))
 		avivo_crtc_load_lut(crtc);
 	else
@@ -183,12 +245,272 @@ static void radeon_crtc_destroy(struct d
 	kfree(radeon_crtc);
 }
 
+/*
+ * Handle unpin events outside the interrupt handler proper.
+ */
+static void radeon_unpin_work_func(struct work_struct *__work)
+{
+	struct radeon_unpin_work *work =
+		container_of(__work, struct radeon_unpin_work, work);
+	int r;
+
+	/* unpin of the old buffer */
+	r = radeon_bo_reserve(work->old_rbo, false);
+	if (likely(r == 0)) {
+		r = radeon_bo_unpin(work->old_rbo);
+		if (unlikely(r != 0)) {
+			DRM_ERROR("failed to unpin buffer after flip\n");
+		}
+		radeon_bo_unreserve(work->old_rbo);
+	} else
+		DRM_ERROR("failed to reserve buffer after flip\n");
+	kfree(work);
+}
+
+void radeon_crtc_handle_flip(struct radeon_device *rdev, int crtc_id)
+{
+	struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
+	struct radeon_unpin_work *work;
+	struct drm_pending_vblank_event *e;
+	struct timeval now;
+	unsigned long flags;
+	u32 update_pending;
+	int vpos, hpos;
+
+	spin_lock_irqsave(&rdev->ddev->event_lock, flags);
+	work = radeon_crtc->unpin_work;
+	if (work == NULL ||
+	    !radeon_fence_signaled(work->fence)) {
+		spin_unlock_irqrestore(&rdev->ddev->event_lock, flags);
+		return;
+	}
+	/* New pageflip, or just completion of a previous one? */
+	if (!radeon_crtc->deferred_flip_completion) {
+		/* do the flip (mmio) */
+		update_pending = radeon_page_flip(rdev, crtc_id, work->new_crtc_base);
+	} else {
+		/* This is just a completion of a flip queued in crtc
+		 * at last invocation. Make sure we go directly to
+		 * completion routine.
+		 */
+		update_pending = 0;
+		radeon_crtc->deferred_flip_completion = 0;
+	}
+
+	/* Has the pageflip already completed in crtc, or is it certain
+	 * to complete in this vblank?
+	 */
+	if (update_pending &&
+	    (DRM_SCANOUTPOS_VALID & radeon_get_crtc_scanoutpos(rdev->ddev, crtc_id,
+							       &vpos, &hpos)) &&
+	    (vpos >=0) &&
+	    (vpos < (99 * rdev->mode_info.crtcs[crtc_id]->base.hwmode.crtc_vdisplay)/100)) {
+		/* crtc didn't flip in this target vblank interval,
+		 * but flip is pending in crtc. It will complete it
+		 * in next vblank interval, so complete the flip at
+		 * next vblank irq.
+		 */
+		radeon_crtc->deferred_flip_completion = 1;
+		spin_unlock_irqrestore(&rdev->ddev->event_lock, flags);
+		return;
+	}
+
+	/* Pageflip (will be) certainly completed in this vblank. Clean up. */
+	radeon_crtc->unpin_work = NULL;
+
+	/* wakeup userspace */
+	if (work->event) {
+		e = work->event;
+		e->event.sequence = drm_vblank_count_and_time(rdev->ddev, crtc_id, &now);
+		e->event.tv_sec = now.tv_sec;
+		e->event.tv_usec = now.tv_usec;
+		list_add_tail(&e->base.link, &e->base.file_priv->event_list);
+		wake_up_interruptible(&e->base.file_priv->event_wait);
+	}
+	spin_unlock_irqrestore(&rdev->ddev->event_lock, flags);
+
+	drm_vblank_put(rdev->ddev, radeon_crtc->crtc_id);
+	radeon_fence_unref(&work->fence);
+	radeon_post_page_flip(work->rdev, work->crtc_id);
+	schedule_work(&work->work);
+}
+
+static int radeon_crtc_page_flip(struct drm_crtc *crtc,
+				 struct drm_framebuffer *fb,
+				 struct drm_pending_vblank_event *event)
+{
+	struct drm_device *dev = crtc->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
+	struct radeon_framebuffer *old_radeon_fb;
+	struct radeon_framebuffer *new_radeon_fb;
+	struct drm_gem_object *obj;
+	struct radeon_bo *rbo;
+	struct radeon_fence *fence;
+	struct radeon_unpin_work *work;
+	unsigned long flags;
+	u32 tiling_flags, pitch_pixels;
+	u64 base;
+	int r;
+
+	work = kzalloc(sizeof *work, GFP_KERNEL);
+	if (work == NULL)
+		return -ENOMEM;
+
+	r = radeon_fence_create(rdev, &fence);
+	if (unlikely(r != 0)) {
+		kfree(work);
+		DRM_ERROR("flip queue: failed to create fence.\n");
+		return -ENOMEM;
+	}
+	work->event = event;
+	work->rdev = rdev;
+	work->crtc_id = radeon_crtc->crtc_id;
+	work->fence = radeon_fence_ref(fence);
+	old_radeon_fb = to_radeon_framebuffer(crtc->fb);
+	new_radeon_fb = to_radeon_framebuffer(fb);
+	/* schedule unpin of the old buffer */
+	obj = old_radeon_fb->obj;
+	rbo = obj->driver_private;
+	work->old_rbo = rbo;
+	INIT_WORK(&work->work, radeon_unpin_work_func);
+
+	/* We borrow the event spin lock for protecting unpin_work */
+	spin_lock_irqsave(&dev->event_lock, flags);
+	if (radeon_crtc->unpin_work) {
+		spin_unlock_irqrestore(&dev->event_lock, flags);
+		kfree(work);
+		radeon_fence_unref(&fence);
+
+		DRM_DEBUG_DRIVER("flip queue: crtc already busy\n");
+		return -EBUSY;
+	}
+	radeon_crtc->unpin_work = work;
+	radeon_crtc->deferred_flip_completion = 0;
+	spin_unlock_irqrestore(&dev->event_lock, flags);
+
+	/* pin the new buffer */
+	obj = new_radeon_fb->obj;
+	rbo = obj->driver_private;
+
+	DRM_DEBUG_DRIVER("flip-ioctl() cur_fbo = %p, cur_bbo = %p\n",
+			 work->old_rbo, rbo);
+
+	r = radeon_bo_reserve(rbo, false);
+	if (unlikely(r != 0)) {
+		DRM_ERROR("failed to reserve new rbo buffer before flip\n");
+		goto pflip_cleanup;
+	}
+	r = radeon_bo_pin(rbo, RADEON_GEM_DOMAIN_VRAM, &base);
+	if (unlikely(r != 0)) {
+		radeon_bo_unreserve(rbo);
+		r = -EINVAL;
+		DRM_ERROR("failed to pin new rbo buffer before flip\n");
+		goto pflip_cleanup;
+	}
+	radeon_bo_get_tiling_flags(rbo, &tiling_flags, NULL);
+	radeon_bo_unreserve(rbo);
+
+	if (!ASIC_IS_AVIVO(rdev)) {
+		/* crtc offset is from display base addr not FB location */
+		base -= radeon_crtc->legacy_display_base_addr;
+		pitch_pixels = fb->pitch / (fb->bits_per_pixel / 8);
+
+		if (tiling_flags & RADEON_TILING_MACRO) {
+			if (ASIC_IS_R300(rdev)) {
+				base &= ~0x7ff;
+			} else {
+				int byteshift = fb->bits_per_pixel >> 4;
+				int tile_addr = (((crtc->y >> 3) * pitch_pixels +  crtc->x) >> (8 - byteshift)) << 11;
+				base += tile_addr + ((crtc->x << byteshift) % 256) + ((crtc->y % 8) << 8);
+			}
+		} else {
+			int offset = crtc->y * pitch_pixels + crtc->x;
+			switch (fb->bits_per_pixel) {
+			case 8:
+			default:
+				offset *= 1;
+				break;
+			case 15:
+			case 16:
+				offset *= 2;
+				break;
+			case 24:
+				offset *= 3;
+				break;
+			case 32:
+				offset *= 4;
+				break;
+			}
+			base += offset;
+		}
+		base &= ~7;
+	}
+
+	spin_lock_irqsave(&dev->event_lock, flags);
+	work->new_crtc_base = base;
+	spin_unlock_irqrestore(&dev->event_lock, flags);
+
+	/* update crtc fb */
+	crtc->fb = fb;
+
+	r = drm_vblank_get(dev, radeon_crtc->crtc_id);
+	if (r) {
+		DRM_ERROR("failed to get vblank before flip\n");
+		goto pflip_cleanup1;
+	}
+
+	/* 32 ought to cover us */
+	r = radeon_ring_lock(rdev, 32);
+	if (r) {
+		DRM_ERROR("failed to lock the ring before flip\n");
+		goto pflip_cleanup2;
+	}
+
+	/* emit the fence */
+	radeon_fence_emit(rdev, fence);
+	/* set the proper interrupt */
+	radeon_pre_page_flip(rdev, radeon_crtc->crtc_id);
+	/* fire the ring */
+	radeon_ring_unlock_commit(rdev);
+
+	return 0;
+
+pflip_cleanup2:
+	drm_vblank_put(dev, radeon_crtc->crtc_id);
+
+pflip_cleanup1:
+	r = radeon_bo_reserve(rbo, false);
+	if (unlikely(r != 0)) {
+		DRM_ERROR("failed to reserve new rbo in error path\n");
+		goto pflip_cleanup;
+	}
+	r = radeon_bo_unpin(rbo);
+	if (unlikely(r != 0)) {
+		radeon_bo_unreserve(rbo);
+		r = -EINVAL;
+		DRM_ERROR("failed to unpin new rbo in error path\n");
+		goto pflip_cleanup;
+	}
+	radeon_bo_unreserve(rbo);
+
+pflip_cleanup:
+	spin_lock_irqsave(&dev->event_lock, flags);
+	radeon_crtc->unpin_work = NULL;
+	spin_unlock_irqrestore(&dev->event_lock, flags);
+	radeon_fence_unref(&fence);
+	kfree(work);
+
+	return r;
+}
+
 static const struct drm_crtc_funcs radeon_crtc_funcs = {
 	.cursor_set = radeon_crtc_cursor_set,
 	.cursor_move = radeon_crtc_cursor_move,
 	.gamma_set = radeon_crtc_gamma_set,
 	.set_config = drm_crtc_helper_set_config,
 	.destroy = radeon_crtc_destroy,
+	.page_flip = radeon_crtc_page_flip,
 };
 
 static void radeon_crtc_init(struct drm_device *dev, int index)
@@ -225,7 +547,7 @@ static void radeon_crtc_init(struct drm_
 		radeon_legacy_init_crtc(dev, radeon_crtc);
 }
 
-static const char *encoder_names[34] = {
+static const char *encoder_names[36] = {
 	"NONE",
 	"INTERNAL_LVDS",
 	"INTERNAL_TMDS1",
@@ -260,6 +582,8 @@ static const char *encoder_names[34] = {
 	"INTERNAL_KLDSCP_LVTMA",
 	"INTERNAL_UNIPHY1",
 	"INTERNAL_UNIPHY2",
+	"NUTMEG",
+	"TRAVIS",
 };
 
 static const char *connector_names[15] = {
@@ -417,9 +741,17 @@ int radeon_ddc_get_modes(struct radeon_c
 	if (!radeon_connector->edid) {
 		radeon_connector->edid = drm_get_edid(&radeon_connector->base, &radeon_connector->ddc_bus->adapter);
 	}
-	/* some servers provide a hardcoded edid in rom for KVMs */
-	if (!radeon_connector->edid)
-		radeon_connector->edid = radeon_combios_get_hardcoded_edid(rdev);
+
+	if (!radeon_connector->edid) {
+		if (rdev->is_atom_bios) {
+			/* some laptops provide a hardcoded edid in rom for LCDs */
+			if (((radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_LVDS) ||
+			     (radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_eDP)))
+				radeon_connector->edid = radeon_bios_get_hardcoded_edid(rdev);
+		} else
+			/* some servers provide a hardcoded edid in rom for KVMs */
+			radeon_connector->edid = radeon_bios_get_hardcoded_edid(rdev);
+	}
 	if (radeon_connector->edid) {
 		drm_mode_connector_update_edid_property(&radeon_connector->base, radeon_connector->edid);
 		ret = drm_add_edid_modes(&radeon_connector->base, radeon_connector->edid);
@@ -448,6 +780,125 @@ static int radeon_ddc_dump(struct drm_co
 	return ret;
 }
 
+/* avivo */
+static void avivo_get_fb_div(struct radeon_pll *pll,
+			     u32 target_clock,
+			     u32 post_div,
+			     u32 ref_div,
+			     u32 *fb_div,
+			     u32 *frac_fb_div)
+{
+	u32 tmp = post_div * ref_div;
+
+	tmp *= target_clock;
+	*fb_div = tmp / pll->reference_freq;
+	*frac_fb_div = tmp % pll->reference_freq;
+
+        if (*fb_div > pll->max_feedback_div)
+		*fb_div = pll->max_feedback_div;
+        else if (*fb_div < pll->min_feedback_div)
+                *fb_div = pll->min_feedback_div;
+}
+
+static u32 avivo_get_post_div(struct radeon_pll *pll,
+			      u32 target_clock)
+{
+	u32 vco, post_div, tmp;
+
+	if (pll->flags & RADEON_PLL_USE_POST_DIV)
+		return pll->post_div;
+
+	if (pll->flags & RADEON_PLL_PREFER_MINM_OVER_MAXP) {
+		if (pll->flags & RADEON_PLL_IS_LCD)
+			vco = pll->lcd_pll_out_min;
+		else
+			vco = pll->pll_out_min;
+	} else {
+		if (pll->flags & RADEON_PLL_IS_LCD)
+			vco = pll->lcd_pll_out_max;
+		else
+			vco = pll->pll_out_max;
+	}
+
+	post_div = vco / target_clock;
+	tmp = vco % target_clock;
+
+	if (pll->flags & RADEON_PLL_PREFER_MINM_OVER_MAXP) {
+		if (tmp)
+			post_div++;
+	} else {
+		if (!tmp)
+			post_div--;
+	}
+
+	if (post_div > pll->max_post_div)
+		post_div = pll->max_post_div;
+	else if (post_div < pll->min_post_div)
+		post_div = pll->min_post_div;
+
+	return post_div;
+}
+
+#define MAX_TOLERANCE 10
+
+void radeon_compute_pll_avivo(struct radeon_pll *pll,
+			      u32 freq,
+			      u32 *dot_clock_p,
+			      u32 *fb_div_p,
+			      u32 *frac_fb_div_p,
+			      u32 *ref_div_p,
+			      u32 *post_div_p)
+{
+	u32 target_clock = freq / 10;
+	u32 post_div = avivo_get_post_div(pll, target_clock);
+	u32 ref_div = pll->min_ref_div;
+	u32 fb_div = 0, frac_fb_div = 0, tmp;
+
+	if (pll->flags & RADEON_PLL_USE_REF_DIV)
+		ref_div = pll->reference_div;
+
+	if (pll->flags & RADEON_PLL_USE_FRAC_FB_DIV) {
+		avivo_get_fb_div(pll, target_clock, post_div, ref_div, &fb_div, &frac_fb_div);
+		frac_fb_div = (100 * frac_fb_div) / pll->reference_freq;
+		if (frac_fb_div >= 5) {
+			frac_fb_div -= 5;
+			frac_fb_div = frac_fb_div / 10;
+			frac_fb_div++;
+		}
+		if (frac_fb_div >= 10) {
+			fb_div++;
+			frac_fb_div = 0;
+		}
+	} else {
+		while (ref_div <= pll->max_ref_div) {
+			avivo_get_fb_div(pll, target_clock, post_div, ref_div,
+					 &fb_div, &frac_fb_div);
+			if (frac_fb_div >= (pll->reference_freq / 2))
+				fb_div++;
+			frac_fb_div = 0;
+			tmp = (pll->reference_freq * fb_div) / (post_div * ref_div);
+			tmp = (tmp * 10000) / target_clock;
+
+			if (tmp > (10000 + MAX_TOLERANCE))
+				ref_div++;
+			else if (tmp >= (10000 - MAX_TOLERANCE))
+				break;
+			else
+				ref_div++;
+		}
+	}
+
+	*dot_clock_p = ((pll->reference_freq * fb_div * 10) + (pll->reference_freq * frac_fb_div)) /
+		(ref_div * post_div * 10);
+	*fb_div_p = fb_div;
+	*frac_fb_div_p = frac_fb_div;
+	*ref_div_p = ref_div;
+	*post_div_p = post_div;
+	DRM_DEBUG_KMS("%d, pll dividers - fb: %d.%d ref: %d, post %d\n",
+		      *dot_clock_p, fb_div, frac_fb_div, ref_div, post_div);
+}
+
+/* pre-avivo */
 static inline uint32_t radeon_div(uint64_t n, uint32_t d)
 {
 	uint64_t mod;
@@ -458,13 +909,13 @@ static inline uint32_t radeon_div(uint64
 	return n;
 }
 
-void radeon_compute_pll(struct radeon_pll *pll,
-			uint64_t freq,
-			uint32_t *dot_clock_p,
-			uint32_t *fb_div_p,
-			uint32_t *frac_fb_div_p,
-			uint32_t *ref_div_p,
-			uint32_t *post_div_p)
+void radeon_compute_pll_legacy(struct radeon_pll *pll,
+			       uint64_t freq,
+			       uint32_t *dot_clock_p,
+			       uint32_t *fb_div_p,
+			       uint32_t *frac_fb_div_p,
+			       uint32_t *ref_div_p,
+			       uint32_t *post_div_p)
 {
 	uint32_t min_ref_div = pll->min_ref_div;
 	uint32_t max_ref_div = pll->max_ref_div;
@@ -494,6 +945,9 @@ void radeon_compute_pll(struct radeon_pl
 		pll_out_max = pll->pll_out_max;
 	}
 
+	if (pll_out_min > 64800)
+		pll_out_min = 64800;
+
 	if (pll->flags & RADEON_PLL_USE_REF_DIV)
 		min_ref_div = max_ref_div = pll->reference_div;
 	else {
@@ -633,6 +1087,10 @@ void radeon_compute_pll(struct radeon_pl
 	*frac_fb_div_p = best_frac_feedback_div;
 	*ref_div_p = best_ref_div;
 	*post_div_p = best_post_div;
+	DRM_DEBUG_KMS("%d %d, pll dividers - fb: %d.%d ref: %d, post %d\n",
+		      freq, best_freq / 1000, best_feedback_div, best_frac_feedback_div,
+		      best_ref_div, best_post_div);
+
 }
 
 static void radeon_user_framebuffer_destroy(struct drm_framebuffer *fb)
@@ -849,7 +1307,10 @@ int radeon_modeset_init(struct radeon_de
 
 	rdev->ddev->mode_config.funcs = (void *)&radeon_mode_funcs;
 
-	if (ASIC_IS_AVIVO(rdev)) {
+	if (ASIC_IS_DCE5(rdev)) {
+		rdev->ddev->mode_config.max_width = 16384;
+		rdev->ddev->mode_config.max_height = 16384;
+	} else if (ASIC_IS_AVIVO(rdev)) {
 		rdev->ddev->mode_config.max_width = 8192;
 		rdev->ddev->mode_config.max_height = 8192;
 	} else {
@@ -1019,7 +1480,7 @@ bool radeon_crtc_scaling_mode_fixup(stru
 /*
  * Retrieve current video scanout position of crtc on a given gpu.
  *
- * \param rdev Device to query.
+ * \param dev Device to query.
  * \param crtc Crtc to query.
  * \param *vpos Location where vertical scanout position should be stored.
  * \param *hpos Location where horizontal scanout position should go.
@@ -1031,72 +1492,74 @@ bool radeon_crtc_scaling_mode_fixup(stru
  *
  * \return Flags, or'ed together as follows:
  *
- * RADEON_SCANOUTPOS_VALID = Query successfull.
- * RADEON_SCANOUTPOS_INVBL = Inside vblank.
- * RADEON_SCANOUTPOS_ACCURATE = Returned position is accurate. A lack of
+ * DRM_SCANOUTPOS_VALID = Query successfull.
+ * DRM_SCANOUTPOS_INVBL = Inside vblank.
+ * DRM_SCANOUTPOS_ACCURATE = Returned position is accurate. A lack of
  * this flag means that returned position may be offset by a constant but
  * unknown small number of scanlines wrt. real scanout position.
  *
  */
-int radeon_get_crtc_scanoutpos(struct radeon_device *rdev, int crtc, int *vpos, int *hpos)
+int radeon_get_crtc_scanoutpos(struct drm_device *dev, int crtc, int *vpos, int *hpos)
 {
 	u32 stat_crtc = 0, vbl = 0, position = 0;
 	int vbl_start, vbl_end, vtotal, ret = 0;
 	bool in_vbl = true;
 
+	struct radeon_device *rdev = dev->dev_private;
+
 	if (ASIC_IS_DCE4(rdev)) {
 		if (crtc == 0) {
 			vbl = RREG32(EVERGREEN_CRTC_V_BLANK_START_END +
 				     EVERGREEN_CRTC0_REGISTER_OFFSET);
 			position = RREG32(EVERGREEN_CRTC_STATUS_POSITION +
 					  EVERGREEN_CRTC0_REGISTER_OFFSET);
-			ret |= RADEON_SCANOUTPOS_VALID;
+			ret |= DRM_SCANOUTPOS_VALID;
 		}
 		if (crtc == 1) {
 			vbl = RREG32(EVERGREEN_CRTC_V_BLANK_START_END +
 				     EVERGREEN_CRTC1_REGISTER_OFFSET);
 			position = RREG32(EVERGREEN_CRTC_STATUS_POSITION +
 					  EVERGREEN_CRTC1_REGISTER_OFFSET);
-			ret |= RADEON_SCANOUTPOS_VALID;
+			ret |= DRM_SCANOUTPOS_VALID;
 		}
 		if (crtc == 2) {
 			vbl = RREG32(EVERGREEN_CRTC_V_BLANK_START_END +
 				     EVERGREEN_CRTC2_REGISTER_OFFSET);
 			position = RREG32(EVERGREEN_CRTC_STATUS_POSITION +
 					  EVERGREEN_CRTC2_REGISTER_OFFSET);
-			ret |= RADEON_SCANOUTPOS_VALID;
+			ret |= DRM_SCANOUTPOS_VALID;
 		}
 		if (crtc == 3) {
 			vbl = RREG32(EVERGREEN_CRTC_V_BLANK_START_END +
 				     EVERGREEN_CRTC3_REGISTER_OFFSET);
 			position = RREG32(EVERGREEN_CRTC_STATUS_POSITION +
 					  EVERGREEN_CRTC3_REGISTER_OFFSET);
-			ret |= RADEON_SCANOUTPOS_VALID;
+			ret |= DRM_SCANOUTPOS_VALID;
 		}
 		if (crtc == 4) {
 			vbl = RREG32(EVERGREEN_CRTC_V_BLANK_START_END +
 				     EVERGREEN_CRTC4_REGISTER_OFFSET);
 			position = RREG32(EVERGREEN_CRTC_STATUS_POSITION +
 					  EVERGREEN_CRTC4_REGISTER_OFFSET);
-			ret |= RADEON_SCANOUTPOS_VALID;
+			ret |= DRM_SCANOUTPOS_VALID;
 		}
 		if (crtc == 5) {
 			vbl = RREG32(EVERGREEN_CRTC_V_BLANK_START_END +
 				     EVERGREEN_CRTC5_REGISTER_OFFSET);
 			position = RREG32(EVERGREEN_CRTC_STATUS_POSITION +
 					  EVERGREEN_CRTC5_REGISTER_OFFSET);
-			ret |= RADEON_SCANOUTPOS_VALID;
+			ret |= DRM_SCANOUTPOS_VALID;
 		}
 	} else if (ASIC_IS_AVIVO(rdev)) {
 		if (crtc == 0) {
 			vbl = RREG32(AVIVO_D1CRTC_V_BLANK_START_END);
 			position = RREG32(AVIVO_D1CRTC_STATUS_POSITION);
-			ret |= RADEON_SCANOUTPOS_VALID;
+			ret |= DRM_SCANOUTPOS_VALID;
 		}
 		if (crtc == 1) {
 			vbl = RREG32(AVIVO_D2CRTC_V_BLANK_START_END);
 			position = RREG32(AVIVO_D2CRTC_STATUS_POSITION);
-			ret |= RADEON_SCANOUTPOS_VALID;
+			ret |= DRM_SCANOUTPOS_VALID;
 		}
 	} else {
 		/* Pre-AVIVO: Different encoding of scanout pos and vblank interval. */
@@ -1112,7 +1575,7 @@ int radeon_get_crtc_scanoutpos(struct ra
 			if (!(stat_crtc & 1))
 				in_vbl = false;
 
-			ret |= RADEON_SCANOUTPOS_VALID;
+			ret |= DRM_SCANOUTPOS_VALID;
 		}
 		if (crtc == 1) {
 			vbl = (RREG32(RADEON_CRTC2_V_TOTAL_DISP) &
@@ -1122,7 +1585,7 @@ int radeon_get_crtc_scanoutpos(struct ra
 			if (!(stat_crtc & 1))
 				in_vbl = false;
 
-			ret |= RADEON_SCANOUTPOS_VALID;
+			ret |= DRM_SCANOUTPOS_VALID;
 		}
 	}
 
@@ -1133,13 +1596,13 @@ int radeon_get_crtc_scanoutpos(struct ra
 	/* Valid vblank area boundaries from gpu retrieved? */
 	if (vbl > 0) {
 		/* Yes: Decode. */
-		ret |= RADEON_SCANOUTPOS_ACCURATE;
+		ret |= DRM_SCANOUTPOS_ACCURATE;
 		vbl_start = vbl & 0x1fff;
 		vbl_end = (vbl >> 16) & 0x1fff;
 	}
 	else {
 		/* No: Fake something reasonable which gives at least ok results. */
-		vbl_start = rdev->mode_info.crtcs[crtc]->base.mode.crtc_vdisplay;
+		vbl_start = rdev->mode_info.crtcs[crtc]->base.hwmode.crtc_vdisplay;
 		vbl_end = 0;
 	}
 
@@ -1155,7 +1618,7 @@ int radeon_get_crtc_scanoutpos(struct ra
 
 	/* Inside "upper part" of vblank area? Apply corrective offset if so: */
 	if (in_vbl && (*vpos >= vbl_start)) {
-		vtotal = rdev->mode_info.crtcs[crtc]->base.mode.crtc_vtotal;
+		vtotal = rdev->mode_info.crtcs[crtc]->base.hwmode.crtc_vtotal;
 		*vpos = *vpos - vtotal;
 	}
 
@@ -1164,7 +1627,7 @@ int radeon_get_crtc_scanoutpos(struct ra
 
 	/* In vblank? */
 	if (in_vbl)
-		ret |= RADEON_SCANOUTPOS_INVBL;
+		ret |= DRM_SCANOUTPOS_INVBL;
 
 	return ret;
 }
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/radeon_drv.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/radeon_drv.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/radeon_drv.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/radeon_drv.c	2011-03-14 21:20:32.000000000 -0400
@@ -48,9 +48,10 @@
  * - 2.5.0 - add get accel 2 to work around ddx breakage for evergreen
  * - 2.6.0 - add tiling config query (r6xx+), add initial HiZ support (r300->r500)
  *   2.7.0 - fixups for r600 2D tiling support. (no external ABI change), add eg dyn gpr regs
+ *   2.8.0 - pageflip support, r500 US_FORMAT regs. r500 ARGB2101010 colorbuf, r300->r500 CMASK, clock crystal query
  */
 #define KMS_DRIVER_MAJOR	2
-#define KMS_DRIVER_MINOR	7
+#define KMS_DRIVER_MINOR	8
 #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);
@@ -66,6 +67,10 @@ int radeon_resume_kms(struct drm_device
 u32 radeon_get_vblank_counter_kms(struct drm_device *dev, int crtc);
 int radeon_enable_vblank_kms(struct drm_device *dev, int crtc);
 void radeon_disable_vblank_kms(struct drm_device *dev, int crtc);
+int radeon_get_vblank_timestamp_kms(struct drm_device *dev, int crtc,
+				    int *max_error,
+				    struct timeval *vblank_time,
+				    unsigned flags);
 void radeon_driver_irq_preinstall_kms(struct drm_device *dev);
 int radeon_driver_irq_postinstall_kms(struct drm_device *dev);
 void radeon_driver_irq_uninstall_kms(struct drm_device *dev);
@@ -74,6 +79,8 @@ int radeon_dma_ioctl_kms(struct drm_devi
 			 struct drm_file *file_priv);
 int radeon_gem_object_init(struct drm_gem_object *obj);
 void radeon_gem_object_free(struct drm_gem_object *obj);
+extern int radeon_get_crtc_scanoutpos(struct drm_device *dev, int crtc,
+				      int *vpos, int *hpos);
 extern struct drm_ioctl_desc radeon_ioctls_kms[];
 extern int radeon_max_kms_ioctl;
 int radeon_mmap(struct file *filp, struct vm_area_struct *vma);
@@ -97,6 +104,7 @@ int radeon_tv = 1;
 int radeon_audio = 1;
 int radeon_disp_priority = 0;
 int radeon_hw_i2c = 0;
+int radeon_pcie_gen2 = 0;
 
 MODULE_PARM_DESC(no_wb, "Disable AGP writeback for scratch registers");
 module_param_named(no_wb, radeon_no_wb, int, 0444);
@@ -140,6 +148,9 @@ module_param_named(disp_priority, radeon
 MODULE_PARM_DESC(hw_i2c, "hw i2c engine enable (0 = disable)");
 module_param_named(hw_i2c, radeon_hw_i2c, int, 0444);
 
+MODULE_PARM_DESC(pcie_gen2, "PCIE Gen2 mode (1 = enable)");
+module_param_named(pcie_gen2, radeon_pcie_gen2, int, 0444);
+
 static int radeon_suspend(struct drm_device *dev, pm_message_t state)
 {
 	drm_radeon_private_t *dev_priv = dev->dev_private;
@@ -296,6 +307,8 @@ static struct drm_driver kms_driver = {
 	.get_vblank_counter = radeon_get_vblank_counter_kms,
 	.enable_vblank = radeon_enable_vblank_kms,
 	.disable_vblank = radeon_disable_vblank_kms,
+	.get_vblank_timestamp = radeon_get_vblank_timestamp_kms,
+	.get_scanout_position = radeon_get_crtc_scanoutpos,
 #if defined(CONFIG_DEBUG_FS)
 	.debugfs_init = radeon_debugfs_init,
 	.debugfs_cleanup = radeon_debugfs_cleanup,
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/radeon_drv.h linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/radeon_drv.h
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/radeon_drv.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/radeon_drv.h	2011-03-14 21:20:32.000000000 -0400
@@ -1524,6 +1524,7 @@ extern u32 radeon_get_scratch(drm_radeon
 #define R600_CP_RB_CNTL                                        0xc104
 #       define R600_RB_BUFSZ(x)                                ((x) << 0)
 #       define R600_RB_BLKSZ(x)                                ((x) << 8)
+#	define R600_BUF_SWAP_32BIT		               (2 << 16)
 #       define R600_RB_NO_UPDATE                               (1 << 27)
 #       define R600_RB_RPTR_WR_ENA                             (1 << 31)
 #define R600_CP_RB_RPTR_WR                                     0xc108
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/radeon_encoders.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/radeon_encoders.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/radeon_encoders.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/radeon_encoders.c	2011-03-14 21:20:32.000000000 -0400
@@ -641,7 +641,7 @@ atombios_get_encoder_mode(struct drm_enc
 	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_hdmi_monitor(radeon_connector->edid)) {
+		if (drm_detect_monitor_audio(radeon_connector->edid) && radeon_audio) {
 			/* fix me */
 			if (ASIC_IS_DCE4(rdev))
 				return ATOM_ENCODER_MODE_DVI;
@@ -655,7 +655,7 @@ atombios_get_encoder_mode(struct drm_enc
 	case DRM_MODE_CONNECTOR_DVID:
 	case DRM_MODE_CONNECTOR_HDMIA:
 	default:
-		if (drm_detect_hdmi_monitor(radeon_connector->edid)) {
+		if (drm_detect_monitor_audio(radeon_connector->edid) && radeon_audio) {
 			/* fix me */
 			if (ASIC_IS_DCE4(rdev))
 				return ATOM_ENCODER_MODE_DVI;
@@ -673,7 +673,7 @@ atombios_get_encoder_mode(struct drm_enc
 		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_hdmi_monitor(radeon_connector->edid)) {
+		else if (drm_detect_monitor_audio(radeon_connector->edid) && radeon_audio) {
 			/* fix me */
 			if (ASIC_IS_DCE4(rdev))
 				return ATOM_ENCODER_MODE_DVI;
@@ -712,8 +712,8 @@ atombios_get_encoder_mode(struct drm_enc
  * - 2 DIG encoder blocks.
  * DIG1/2 can drive UNIPHY0/1/2 link A or link B
  *
- * DCE 4.0
- * - 3 DIG transmitter blocks UNPHY0/1/2 (links A and 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
@@ -724,6 +724,12 @@ atombios_get_encoder_mode(struct drm_enc
  * 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:
@@ -737,6 +743,7 @@ 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
@@ -752,6 +759,7 @@ atombios_dig_encoder_setup(struct drm_en
 	uint8_t frev, crev;
 	int dp_clock = 0;
 	int dp_lane_count = 0;
+	int hpd_id = RADEON_HPD_NONE;
 
 	if (connector) {
 		struct radeon_connector *radeon_connector = to_radeon_connector(connector);
@@ -760,6 +768,7 @@ atombios_dig_encoder_setup(struct drm_en
 
 		dp_clock = dig_connector->dp_clock;
 		dp_lane_count = dig_connector->dp_lane_count;
+		hpd_id = radeon_connector->hpd.hpd;
 	}
 
 	/* no dig encoder assigned */
@@ -784,19 +793,36 @@ atombios_dig_encoder_setup(struct drm_en
 	args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
 	args.v1.ucEncoderMode = atombios_get_encoder_mode(encoder);
 
-	if (args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP) {
-		if (dp_clock == 270000)
-			args.v1.ucConfig |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ;
+	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)
+	else if (radeon_encoder->pixel_clock > 165000)
 		args.v1.ucLaneNum = 8;
 	else
 		args.v1.ucLaneNum = 4;
 
-	if (ASIC_IS_DCE4(rdev)) {
+	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;
+		args.v4.ucBitPerColor = PANEL_8BIT_PER_COLOR;
+		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;
 		args.v3.ucBitPerColor = PANEL_8BIT_PER_COLOR;
 	} 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;
@@ -823,6 +849,7 @@ 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
@@ -883,7 +910,7 @@ atombios_dig_transmitter_setup(struct dr
 
 	args.v1.ucAction = action;
 	if (action == ATOM_TRANSMITTER_ACTION_INIT) {
-		args.v1.usInitInfo = connector_object_id;
+		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;
@@ -917,10 +944,18 @@ atombios_dig_transmitter_setup(struct dr
 			struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
 			pll_id = radeon_crtc->pll_id;
 		}
-		if (is_dp && rdev->clock.dp_extclk)
-			args.v3.acConfig.ucRefClkSource = 2; /* external src */
-		else
-			args.v3.acConfig.ucRefClkSource = pll_id;
+
+		if (ASIC_IS_DCE5(rdev)) {
+			if (is_dp && rdev->clock.dp_extclk)
+				args.v4.acConfig.ucRefClkSource = 3; /* external src */
+			else
+				args.v4.acConfig.ucRefClkSource = pll_id;
+		} else {
+			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:
@@ -1028,7 +1063,7 @@ atombios_set_edp_panel_power(struct drm_
 	if (!ASIC_IS_DCE4(rdev))
 		return;
 
-	if ((action != ATOM_TRANSMITTER_ACTION_POWER_ON) ||
+	if ((action != ATOM_TRANSMITTER_ACTION_POWER_ON) &&
 	    (action != ATOM_TRANSMITTER_ACTION_POWER_OFF))
 		return;
 
@@ -1044,6 +1079,7 @@ atombios_set_edp_panel_power(struct drm_
 
 union external_encoder_control {
 	EXTERNAL_ENCODER_CONTROL_PS_ALLOCATION v1;
+	EXTERNAL_ENCODER_CONTROL_PS_ALLOCATION_V3 v3;
 };
 
 static void
@@ -1054,6 +1090,7 @@ atombios_external_encoder_setup(struct d
 	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 = radeon_get_connector_for_encoder(encoder);
 	int index = GetIndexIntoMasterTable(COMMAND, ExternalEncoderControl);
@@ -1061,6 +1098,7 @@ atombios_external_encoder_setup(struct d
 	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;
 
 	if (connector) {
 		struct radeon_connector *radeon_connector = to_radeon_connector(connector);
@@ -1099,6 +1137,37 @@ atombios_external_encoder_setup(struct d
 			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;
+			}
+			args.v3.sExtEncoder.ucBitPerColor = PANEL_8BIT_PER_COLOR;
+			break;
 		default:
 			DRM_ERROR("Unknown table version: %d, %d\n", frev, crev);
 			return;
@@ -1158,6 +1227,8 @@ radeon_atom_encoder_dpms(struct drm_enco
 	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));
 
@@ -1180,7 +1251,9 @@ radeon_atom_encoder_dpms(struct drm_enco
 		index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl);
 		break;
 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
-		if (ASIC_IS_DCE3(rdev))
+		if (ASIC_IS_DCE5(rdev))
+			is_dce5_dvo = true;
+		else if (ASIC_IS_DCE3(rdev))
 			is_dig = true;
 		else
 			index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl);
@@ -1196,12 +1269,16 @@ radeon_atom_encoder_dpms(struct drm_enco
 		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);
+		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:
@@ -1260,6 +1337,28 @@ radeon_atom_encoder_dpms(struct drm_enco
 				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:
@@ -1289,12 +1388,18 @@ radeon_atom_encoder_dpms(struct drm_enco
 		switch (mode) {
 		case DRM_MODE_DPMS_ON:
 		default:
-			action = ATOM_ENABLE;
+			if (ASIC_IS_DCE41(rdev))
+				action = EXTERNAL_ENCODER_ACTION_V3_ENABLE_OUTPUT;
+			else
+				action = ATOM_ENABLE;
 			break;
 		case DRM_MODE_DPMS_STANDBY:
 		case DRM_MODE_DPMS_SUSPEND:
 		case DRM_MODE_DPMS_OFF:
-			action = ATOM_DISABLE;
+			if (ASIC_IS_DCE41(rdev))
+				action = EXTERNAL_ENCODER_ACTION_V3_DISABLE_OUTPUT;
+			else
+				action = ATOM_DISABLE;
 			break;
 		}
 		atombios_external_encoder_setup(encoder, ext_encoder, action);
@@ -1465,11 +1570,21 @@ atombios_apply_encoder_quirks(struct drm
 	}
 
 	/* set scaler clears this on some chips */
-	/* XXX check DCE4 */
-	if (!(radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))) {
-		if (ASIC_IS_AVIVO(rdev) && (mode->flags & DRM_MODE_FLAG_INTERLACE))
-			WREG32(AVIVO_D1MODE_DATA_FORMAT + radeon_crtc->crtc_offset,
-			       AVIVO_D1MODE_INTERLEAVE_EN);
+	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);
+		}
 	}
 }
 
@@ -1483,27 +1598,35 @@ static int radeon_atom_pick_dig_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;
-		switch (radeon_encoder->encoder_id) {
-		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
+		if (ASIC_IS_DCE41(rdev)) {
 			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;
+		} 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;
+			}
 		}
 	}
 
@@ -1610,7 +1733,13 @@ radeon_atom_encoder_mode_set(struct drm_
 	}
 
 	if (ext_encoder) {
-		atombios_external_encoder_setup(encoder, ext_encoder, ATOM_ENABLE);
+		if (ASIC_IS_DCE41(rdev)) {
+			atombios_external_encoder_setup(encoder, ext_encoder,
+							EXTERNAL_ENCODER_ACTION_V3_ENCODER_INIT);
+			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);
@@ -1927,7 +2056,10 @@ radeon_atombios_set_dig_info(struct rade
 }
 
 void
-radeon_add_atom_encoder(struct drm_device *dev, uint32_t encoder_enum, uint32_t supported_device)
+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;
@@ -1970,6 +2102,7 @@ radeon_add_atom_encoder(struct drm_devic
 	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:
@@ -2029,6 +2162,8 @@ radeon_add_atom_encoder(struct drm_devic
 	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))
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/radeon_family.h linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/radeon_family.h
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/radeon_family.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/radeon_family.h	2011-03-14 21:20:32.000000000 -0400
@@ -80,6 +80,10 @@ enum radeon_family {
 	CHIP_JUNIPER,
 	CHIP_CYPRESS,
 	CHIP_HEMLOCK,
+	CHIP_PALM,
+	CHIP_BARTS,
+	CHIP_TURKS,
+	CHIP_CAICOS,
 	CHIP_LAST,
 };
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/radeon_fb.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/radeon_fb.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/radeon_fb.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/radeon_fb.c	2011-03-14 21:20:32.000000000 -0400
@@ -113,11 +113,14 @@ static int radeonfb_create_pinned_object
 	u32 tiling_flags = 0;
 	int ret;
 	int aligned_size, size;
+	int height = mode_cmd->height;
 
 	/* need to align pitch with crtc limits */
 	mode_cmd->pitch = radeon_align_pitch(rdev, mode_cmd->width, mode_cmd->bpp, fb_tiled) * ((mode_cmd->bpp + 1) / 8);
 
-	size = mode_cmd->pitch * mode_cmd->height;
+	if (rdev->family >= CHIP_R600)
+		height = ALIGN(mode_cmd->height, 8);
+	size = mode_cmd->pitch * height;
 	aligned_size = ALIGN(size, PAGE_SIZE);
 	ret = radeon_gem_object_create(rdev, aligned_size, 0,
 				       RADEON_GEM_DOMAIN_VRAM,
@@ -247,8 +250,6 @@ static int radeonfb_create(struct radeon
 	info->apertures->ranges[0].base = rdev->ddev->mode_config.fb_base;
 	info->apertures->ranges[0].size = rdev->mc.aper_size;
 
-	info->fix.mmio_start = 0;
-	info->fix.mmio_len = 0;
 	info->pixmap.size = 64*1024;
 	info->pixmap.buf_align = 8;
 	info->pixmap.access_align = 32;
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/radeon_fence.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/radeon_fence.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/radeon_fence.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/radeon_fence.c	2011-03-14 21:20:32.000000000 -0400
@@ -38,6 +38,7 @@
 #include "drm.h"
 #include "radeon_reg.h"
 #include "radeon.h"
+#include "radeon_trace.h"
 
 int radeon_fence_emit(struct radeon_device *rdev, struct radeon_fence *fence)
 {
@@ -57,6 +58,7 @@ int radeon_fence_emit(struct radeon_devi
 	} else
 		radeon_fence_ring_emit(rdev, fence);
 
+	trace_radeon_fence_emit(rdev->ddev, fence->seq);
 	fence->emited = true;
 	list_del(&fence->list);
 	list_add_tail(&fence->list, &rdev->fence_drv.emited);
@@ -213,6 +215,7 @@ int radeon_fence_wait(struct radeon_fenc
 retry:
 	/* save current sequence used to check for GPU lockup */
 	seq = rdev->fence_drv.last_seq;
+	trace_radeon_fence_wait_begin(rdev->ddev, seq);
 	if (intr) {
 		radeon_irq_kms_sw_irq_get(rdev);
 		r = wait_event_interruptible_timeout(rdev->fence_drv.queue,
@@ -227,6 +230,7 @@ retry:
 			 radeon_fence_signaled(fence), timeout);
 		radeon_irq_kms_sw_irq_put(rdev);
 	}
+	trace_radeon_fence_wait_end(rdev->ddev, seq);
 	if (unlikely(!radeon_fence_signaled(fence))) {
 		/* we were interrupted for some reason and fence isn't
 		 * isn't signaled yet, resume wait
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/radeon_gem.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/radeon_gem.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/radeon_gem.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/radeon_gem.c	2011-03-14 21:20:32.000000000 -0400
@@ -156,9 +156,12 @@ int radeon_gem_info_ioctl(struct drm_dev
 {
 	struct radeon_device *rdev = dev->dev_private;
 	struct drm_radeon_gem_info *args = data;
+	struct ttm_mem_type_manager *man;
+
+	man = &rdev->mman.bdev.man[TTM_PL_VRAM];
 
 	args->vram_size = rdev->mc.real_vram_size;
-	args->vram_visible = rdev->mc.real_vram_size;
+	args->vram_visible = (u64)man->size << PAGE_SHIFT;
 	if (rdev->stollen_vga_memory)
 		args->vram_visible -= radeon_bo_size(rdev->stollen_vga_memory);
 	args->vram_visible -= radeon_fbdev_total_size(rdev);
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/radeon.h linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/radeon.h
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/radeon.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/radeon.h	2011-03-14 21:20:32.000000000 -0400
@@ -69,6 +69,7 @@
 #include <ttm/ttm_bo_driver.h>
 #include <ttm/ttm_placement.h>
 #include <ttm/ttm_module.h>
+#include <ttm/ttm_execbuf_util.h>
 
 #include "radeon_family.h"
 #include "radeon_mode.h"
@@ -91,6 +92,7 @@ extern int radeon_tv;
 extern int radeon_audio;
 extern int radeon_disp_priority;
 extern int radeon_hw_i2c;
+extern int radeon_pcie_gen2;
 
 /*
  * Copy from radeon_drv.h so we don't have to include both and have conflicting
@@ -177,9 +179,10 @@ void radeon_combios_get_power_modes(stru
 void radeon_atombios_get_power_modes(struct radeon_device *rdev);
 void radeon_atom_set_voltage(struct radeon_device *rdev, u16 level);
 void rs690_pm_info(struct radeon_device *rdev);
-extern u32 rv6xx_get_temp(struct radeon_device *rdev);
-extern u32 rv770_get_temp(struct radeon_device *rdev);
-extern u32 evergreen_get_temp(struct radeon_device *rdev);
+extern int rv6xx_get_temp(struct radeon_device *rdev);
+extern int rv770_get_temp(struct radeon_device *rdev);
+extern int evergreen_get_temp(struct radeon_device *rdev);
+extern int sumo_get_temp(struct radeon_device *rdev);
 
 /*
  * Fences.
@@ -259,13 +262,12 @@ struct radeon_bo {
 };
 
 struct radeon_bo_list {
-	struct list_head	list;
+	struct ttm_validate_buffer tv;
 	struct radeon_bo	*bo;
 	uint64_t		gpu_offset;
 	unsigned		rdomain;
 	unsigned		wdomain;
 	u32			tiling_flags;
-	bool			reserved;
 };
 
 /*
@@ -343,7 +345,6 @@ struct radeon_mc {
 	 * about vram size near mc fb location */
 	u64			mc_vram_size;
 	u64			visible_vram_size;
-	u64			active_vram_size;
 	u64			gtt_size;
 	u64			gtt_start;
 	u64			gtt_end;
@@ -377,11 +378,56 @@ void radeon_scratch_free(struct radeon_d
 /*
  * IRQS.
  */
+
+struct radeon_unpin_work {
+	struct work_struct work;
+	struct radeon_device *rdev;
+	int crtc_id;
+	struct radeon_fence *fence;
+	struct drm_pending_vblank_event *event;
+	struct radeon_bo *old_rbo;
+	u64 new_crtc_base;
+};
+
+struct r500_irq_stat_regs {
+	u32 disp_int;
+};
+
+struct r600_irq_stat_regs {
+	u32 disp_int;
+	u32 disp_int_cont;
+	u32 disp_int_cont2;
+	u32 d1grph_int;
+	u32 d2grph_int;
+};
+
+struct evergreen_irq_stat_regs {
+	u32 disp_int;
+	u32 disp_int_cont;
+	u32 disp_int_cont2;
+	u32 disp_int_cont3;
+	u32 disp_int_cont4;
+	u32 disp_int_cont5;
+	u32 d1grph_int;
+	u32 d2grph_int;
+	u32 d3grph_int;
+	u32 d4grph_int;
+	u32 d5grph_int;
+	u32 d6grph_int;
+};
+
+union radeon_irq_stat_regs {
+	struct r500_irq_stat_regs r500;
+	struct r600_irq_stat_regs r600;
+	struct evergreen_irq_stat_regs evergreen;
+};
+
 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];
 	wait_queue_head_t	vblank_queue;
 	/* FIXME: use defines for max hpd/dacs */
 	bool            hpd[6];
@@ -392,12 +438,17 @@ struct radeon_irq {
 	bool		hdmi[2];
 	spinlock_t sw_lock;
 	int sw_refcount;
+	union radeon_irq_stat_regs stat_regs;
+	spinlock_t pflip_lock[6];
+	int pflip_refcount[6];
 };
 
 int radeon_irq_kms_init(struct radeon_device *rdev);
 void radeon_irq_kms_fini(struct radeon_device *rdev);
 void radeon_irq_kms_sw_irq_get(struct radeon_device *rdev);
 void radeon_irq_kms_sw_irq_put(struct radeon_device *rdev);
+void radeon_irq_kms_pflip_irq_get(struct radeon_device *rdev, int crtc);
+void radeon_irq_kms_pflip_irq_put(struct radeon_device *rdev, int crtc);
 
 /*
  * CP & ring.
@@ -687,6 +738,8 @@ enum radeon_int_thermal_type {
 	THERMAL_TYPE_RV6XX,
 	THERMAL_TYPE_RV770,
 	THERMAL_TYPE_EVERGREEN,
+	THERMAL_TYPE_SUMO,
+	THERMAL_TYPE_NI,
 };
 
 struct radeon_voltage {
@@ -758,8 +811,7 @@ struct radeon_pm {
 	fixed20_12		sclk;
 	fixed20_12		mclk;
 	fixed20_12		needed_bandwidth;
-	/* XXX: use a define for num power modes */
-	struct radeon_power_state power_state[8];
+	struct radeon_power_state *power_state;
 	/* number of valid power states */
 	int                     num_power_states;
 	int                     current_power_state_index;
@@ -770,6 +822,9 @@ struct radeon_pm {
 	u32                     current_sclk;
 	u32                     current_mclk;
 	u32                     current_vddc;
+	u32                     default_sclk;
+	u32                     default_mclk;
+	u32                     default_vddc;
 	struct radeon_i2c_chan *i2c_bus;
 	/* selected pm method */
 	enum radeon_pm_method     pm_method;
@@ -881,6 +936,10 @@ struct radeon_asic {
 	void (*pm_finish)(struct radeon_device *rdev);
 	void (*pm_init_profile)(struct radeon_device *rdev);
 	void (*pm_get_dynpm_state)(struct radeon_device *rdev);
+	/* pageflipping */
+	void (*pre_page_flip)(struct radeon_device *rdev, int crtc);
+	u32 (*page_flip)(struct radeon_device *rdev, int crtc, u64 crtc_base);
+	void (*post_page_flip)(struct radeon_device *rdev, int crtc);
 };
 
 /*
@@ -975,6 +1034,7 @@ struct evergreen_asic {
 	unsigned tiling_npipes;
 	unsigned tiling_group_size;
 	unsigned tile_config;
+	struct r100_gpu_lockup	lockup;
 };
 
 union radeon_asic_config {
@@ -1091,11 +1151,11 @@ struct radeon_device {
 	const struct firmware *me_fw;	/* all family ME firmware */
 	const struct firmware *pfp_fw;	/* r6/700 PFP firmware */
 	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;
 	int msi_enabled; /* msi enabled */
 	struct r600_ih ih; /* r6/700 interrupt ring */
-	struct workqueue_struct *wq;
 	struct work_struct hotplug_work;
 	int num_crtc; /* number of crtcs */
 	struct mutex dc_hw_i2c_mutex; /* display controller hw i2c mutex */
@@ -1110,10 +1170,10 @@ struct radeon_device {
 	uint8_t			audio_status_bits;
 	uint8_t			audio_category_code;
 
-	bool powered_down;
 	struct notifier_block acpi_nb;
-	/* only one userspace can use Hyperz features at a time */
+	/* only one userspace can use Hyperz features or CMASK at a time */
 	struct drm_file *hyperz_filp;
+	struct drm_file *cmask_filp;
 	/* i2c buses */
 	struct radeon_i2c_chan *i2c_bus[RADEON_MAX_I2C_BUS];
 };
@@ -1188,6 +1248,8 @@ static inline void r100_io_wreg(struct r
  */
 #define RREG8(reg) readb(((void __iomem *)rdev->rmmio) + (reg))
 #define WREG8(reg, v) writeb(v, ((void __iomem *)rdev->rmmio) + (reg))
+#define RREG16(reg) readw(((void __iomem *)rdev->rmmio) + (reg))
+#define WREG16(reg, v) writew(v, ((void __iomem *)rdev->rmmio) + (reg))
 #define RREG32(reg) r100_mm_rreg(rdev, (reg))
 #define DREG32(reg) printk(KERN_INFO "REGISTER: " #reg " : 0x%08X\n", r100_mm_rreg(rdev, (reg)))
 #define WREG32(reg, v) r100_mm_wreg(rdev, (reg), (v))
@@ -1261,6 +1323,14 @@ void r100_pll_errata_after_index(struct
 		(rdev->family == CHIP_RV410) ||			\
 		(rdev->family == CHIP_RS400) ||			\
 		(rdev->family == CHIP_RS480))
+#define ASIC_IS_X2(rdev) ((rdev->ddev->pdev->device == 0x9441) || \
+		(rdev->ddev->pdev->device == 0x9443) || \
+		(rdev->ddev->pdev->device == 0x944B) || \
+		(rdev->ddev->pdev->device == 0x9506) || \
+		(rdev->ddev->pdev->device == 0x9509) || \
+		(rdev->ddev->pdev->device == 0x950F) || \
+		(rdev->ddev->pdev->device == 0x689C) || \
+		(rdev->ddev->pdev->device == 0x689D))
 #define ASIC_IS_AVIVO(rdev) ((rdev->family >= CHIP_RS600))
 #define ASIC_IS_DCE2(rdev) ((rdev->family == CHIP_RS600)  ||	\
 			    (rdev->family == CHIP_RS690)  ||	\
@@ -1269,6 +1339,9 @@ void r100_pll_errata_after_index(struct
 #define ASIC_IS_DCE3(rdev) ((rdev->family >= CHIP_RV620))
 #define ASIC_IS_DCE32(rdev) ((rdev->family >= CHIP_RV730))
 #define ASIC_IS_DCE4(rdev) ((rdev->family >= CHIP_CEDAR))
+#define ASIC_IS_DCE41(rdev) ((rdev->family >= CHIP_PALM) && \
+			     (rdev->flags & RADEON_IS_IGP))
+#define ASIC_IS_DCE5(rdev) ((rdev->family >= CHIP_BARTS))
 
 /*
  * BIOS helpers.
@@ -1344,6 +1417,9 @@ static inline void radeon_ring_write(str
 #define radeon_pm_finish(rdev) (rdev)->asic->pm_finish((rdev))
 #define radeon_pm_init_profile(rdev) (rdev)->asic->pm_init_profile((rdev))
 #define radeon_pm_get_dynpm_state(rdev) (rdev)->asic->pm_get_dynpm_state((rdev))
+#define radeon_pre_page_flip(rdev, crtc) rdev->asic->pre_page_flip((rdev), (crtc))
+#define radeon_page_flip(rdev, crtc, base) rdev->asic->page_flip((rdev), (crtc), (base))
+#define radeon_post_page_flip(rdev, crtc) rdev->asic->post_page_flip((rdev), (crtc))
 
 /* Common functions */
 /* AGP */
@@ -1371,68 +1447,9 @@ extern void radeon_vram_location(struct
 extern void radeon_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc);
 extern int radeon_resume_kms(struct drm_device *dev);
 extern int radeon_suspend_kms(struct drm_device *dev, pm_message_t state);
-
-/* r100,rv100,rs100,rv200,rs200,r200,rv250,rs300,rv280 */
-extern void r100_gpu_lockup_update(struct r100_gpu_lockup *lockup, struct radeon_cp *cp);
-extern bool r100_gpu_cp_is_lockup(struct radeon_device *rdev, struct r100_gpu_lockup *lockup, struct radeon_cp *cp);
-
-/* rv200,rv250,rv280 */
-extern void r200_set_safe_registers(struct radeon_device *rdev);
-
-/* r300,r350,rv350,rv370,rv380 */
-extern void r300_set_reg_safe(struct radeon_device *rdev);
-extern void r300_mc_program(struct radeon_device *rdev);
-extern void r300_mc_init(struct radeon_device *rdev);
-extern void r300_clock_startup(struct radeon_device *rdev);
-extern int r300_mc_wait_for_idle(struct radeon_device *rdev);
-extern int rv370_pcie_gart_init(struct radeon_device *rdev);
-extern void rv370_pcie_gart_fini(struct radeon_device *rdev);
-extern int rv370_pcie_gart_enable(struct radeon_device *rdev);
-extern void rv370_pcie_gart_disable(struct radeon_device *rdev);
-
-/* r420,r423,rv410 */
-extern u32 r420_mc_rreg(struct radeon_device *rdev, u32 reg);
-extern void r420_mc_wreg(struct radeon_device *rdev, u32 reg, u32 v);
-extern int r420_debugfs_pipes_info_init(struct radeon_device *rdev);
-extern void r420_pipes_init(struct radeon_device *rdev);
-
-/* rv515 */
-struct rv515_mc_save {
-	u32 d1vga_control;
-	u32 d2vga_control;
-	u32 vga_render_control;
-	u32 vga_hdp_control;
-	u32 d1crtc_control;
-	u32 d2crtc_control;
-};
-extern void rv515_bandwidth_avivo_update(struct radeon_device *rdev);
-extern void rv515_vga_render_disable(struct radeon_device *rdev);
-extern void rv515_set_safe_registers(struct radeon_device *rdev);
-extern void rv515_mc_stop(struct radeon_device *rdev, struct rv515_mc_save *save);
-extern void rv515_mc_resume(struct radeon_device *rdev, struct rv515_mc_save *save);
-extern void rv515_clock_startup(struct radeon_device *rdev);
-extern void rv515_debugfs(struct radeon_device *rdev);
-extern int rv515_suspend(struct radeon_device *rdev);
-
-/* rs400 */
-extern int rs400_gart_init(struct radeon_device *rdev);
-extern int rs400_gart_enable(struct radeon_device *rdev);
-extern void rs400_gart_adjust_size(struct radeon_device *rdev);
-extern void rs400_gart_disable(struct radeon_device *rdev);
-extern void rs400_gart_fini(struct radeon_device *rdev);
-
-/* rs600 */
-extern void rs600_set_safe_registers(struct radeon_device *rdev);
-extern int rs600_irq_set(struct radeon_device *rdev);
-extern void rs600_irq_disable(struct radeon_device *rdev);
-
-/* rs690, rs740 */
-extern void rs690_line_buffer_adjust(struct radeon_device *rdev,
-					struct drm_display_mode *mode1,
-					struct drm_display_mode *mode2);
+extern void radeon_ttm_set_active_vram_size(struct radeon_device *rdev, u64 size);
 
 /* r600, rv610, rv630, rv620, rv635, rv670, rs780, rs880 */
-extern void r600_vram_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc);
 extern bool r600_card_posted(struct radeon_device *rdev);
 extern void r600_cp_stop(struct radeon_device *rdev);
 extern int r600_cp_start(struct radeon_device *rdev);
@@ -1478,6 +1495,7 @@ extern void r600_hdmi_setmode(struct drm
 extern int r600_hdmi_buffer_status_changed(struct drm_encoder *encoder);
 extern void r600_hdmi_update_audio_settings(struct drm_encoder *encoder);
 
+extern void r700_vram_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc);
 extern void r700_cp_stop(struct radeon_device *rdev);
 extern void r700_cp_fini(struct radeon_device *rdev);
 extern void evergreen_disable_interrupt_state(struct radeon_device *rdev);
@@ -1485,6 +1503,9 @@ extern int evergreen_irq_set(struct rade
 extern int evergreen_blit_init(struct radeon_device *rdev);
 extern void evergreen_blit_fini(struct radeon_device *rdev);
 
+extern int ni_init_microcode(struct radeon_device *rdev);
+extern int btc_mc_load_microcode(struct radeon_device *rdev);
+
 /* radeon_acpi.c */ 
 #if defined(CONFIG_ACPI) 
 extern int radeon_acpi_init(struct radeon_device *rdev); 
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/radeon_irq_kms.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/radeon_irq_kms.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/radeon_irq_kms.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/radeon_irq_kms.c	2011-03-14 21:20:32.000000000 -0400
@@ -64,15 +64,15 @@ void radeon_driver_irq_preinstall_kms(st
 	struct radeon_device *rdev = dev->dev_private;
 	unsigned i;
 
-	INIT_WORK(&rdev->hotplug_work, radeon_hotplug_work_func);
-
 	/* 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 < 6; i++) {
 		rdev->irq.hpd[i] = false;
+		rdev->irq.pflip[i] = false;
+	}
 	radeon_irq_set(rdev);
 	/* Clear bits */
 	radeon_irq_process(rdev);
@@ -101,16 +101,23 @@ void radeon_driver_irq_uninstall_kms(str
 	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 < 6; i++) {
 		rdev->irq.hpd[i] = false;
+		rdev->irq.pflip[i] = false;
+	}
 	radeon_irq_set(rdev);
 }
 
 int radeon_irq_kms_init(struct radeon_device *rdev)
 {
+	int i;
 	int r = 0;
 
+	INIT_WORK(&rdev->hotplug_work, radeon_hotplug_work_func);
+
 	spin_lock_init(&rdev->irq.sw_lock);
+	for (i = 0; i < rdev->num_crtc; i++)
+		spin_lock_init(&rdev->irq.pflip_lock[i]);
 	r = drm_vblank_init(rdev->ddev, rdev->num_crtc);
 	if (r) {
 		return r;
@@ -121,7 +128,7 @@ int radeon_irq_kms_init(struct radeon_de
 	 * chips.  Disable MSI on them for now.
 	 */
 	if ((rdev->family >= CHIP_RV380) &&
-	    (!(rdev->flags & RADEON_IS_IGP)) &&
+	    ((!(rdev->flags & RADEON_IS_IGP)) || (rdev->family >= CHIP_PALM)) &&
 	    (!(rdev->flags & RADEON_IS_AGP))) {
 		int ret = pci_enable_msi(rdev->pdev);
 		if (!ret) {
@@ -148,6 +155,7 @@ void radeon_irq_kms_fini(struct radeon_d
 		if (rdev->msi_enabled)
 			pci_disable_msi(rdev->pdev);
 	}
+	flush_work_sync(&rdev->hotplug_work);
 }
 
 void radeon_irq_kms_sw_irq_get(struct radeon_device *rdev)
@@ -175,3 +183,34 @@ void radeon_irq_kms_sw_irq_put(struct ra
 	spin_unlock_irqrestore(&rdev->irq.sw_lock, irqflags);
 }
 
+void radeon_irq_kms_pflip_irq_get(struct radeon_device *rdev, int crtc)
+{
+	unsigned long irqflags;
+
+	if (crtc < 0 || crtc >= rdev->num_crtc)
+		return;
+
+	spin_lock_irqsave(&rdev->irq.pflip_lock[crtc], irqflags);
+	if (rdev->ddev->irq_enabled && (++rdev->irq.pflip_refcount[crtc] == 1)) {
+		rdev->irq.pflip[crtc] = true;
+		radeon_irq_set(rdev);
+	}
+	spin_unlock_irqrestore(&rdev->irq.pflip_lock[crtc], irqflags);
+}
+
+void radeon_irq_kms_pflip_irq_put(struct radeon_device *rdev, int crtc)
+{
+	unsigned long irqflags;
+
+	if (crtc < 0 || crtc >= rdev->num_crtc)
+		return;
+
+	spin_lock_irqsave(&rdev->irq.pflip_lock[crtc], irqflags);
+	BUG_ON(rdev->ddev->irq_enabled && rdev->irq.pflip_refcount[crtc] <= 0);
+	if (rdev->ddev->irq_enabled && (--rdev->irq.pflip_refcount[crtc] == 0)) {
+		rdev->irq.pflip[crtc] = false;
+		radeon_irq_set(rdev);
+	}
+	spin_unlock_irqrestore(&rdev->irq.pflip_lock[crtc], irqflags);
+}
+
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/radeon_kms.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/radeon_kms.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/radeon_kms.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/radeon_kms.c	2011-03-14 21:20:32.000000000 -0400
@@ -96,9 +96,27 @@ out:
 	return r;
 }
 
+static void radeon_set_filp_rights(struct drm_device *dev,
+				   struct drm_file **owner,
+				   struct drm_file *applier,
+				   uint32_t *value)
+{
+	mutex_lock(&dev->struct_mutex);
+	if (*value == 1) {
+		/* wants rights */
+		if (!*owner)
+			*owner = applier;
+	} else if (*value == 0) {
+		/* revokes rights */
+		if (*owner == applier)
+			*owner = NULL;
+	}
+	*value = *owner == applier ? 1 : 0;
+	mutex_unlock(&dev->struct_mutex);
+}
 
 /*
- * Userspace get informations ioctl
+ * Userspace get information ioctl
  */
 int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
 {
@@ -173,18 +191,19 @@ int radeon_info_ioctl(struct drm_device
 			DRM_DEBUG_KMS("WANT_HYPERZ: invalid value %d\n", value);
 			return -EINVAL;
 		}
-		mutex_lock(&dev->struct_mutex);
-		if (value == 1) {
-			/* wants hyper-z */
-			if (!rdev->hyperz_filp)
-				rdev->hyperz_filp = filp;
-		} else if (value == 0) {
-			/* revokes hyper-z */
-			if (rdev->hyperz_filp == filp)
-				rdev->hyperz_filp = NULL;
+		radeon_set_filp_rights(dev, &rdev->hyperz_filp, filp, &value);
+		break;
+	case RADEON_INFO_WANT_CMASK:
+		/* The same logic as Hyper-Z. */
+		if (value >= 2) {
+			DRM_DEBUG_KMS("WANT_CMASK: invalid value %d\n", value);
+			return -EINVAL;
 		}
-		value = rdev->hyperz_filp == filp ?  1 : 0;
-		mutex_unlock(&dev->struct_mutex);
+		radeon_set_filp_rights(dev, &rdev->cmask_filp, filp, &value);
+		break;
+	case RADEON_INFO_CLOCK_CRYSTAL_FREQ:
+		/* return clock value in KHz */
+		value = rdev->clock.spll.reference_freq * 10;
 		break;
 	default:
 		DRM_DEBUG_KMS("Invalid request %d\n", info->request);
@@ -203,10 +222,6 @@ int radeon_info_ioctl(struct drm_device
  */
 int radeon_driver_firstopen_kms(struct drm_device *dev)
 {
-	struct radeon_device *rdev = dev->dev_private;
-
-	if (rdev->powered_down)
-		return -EINVAL;
 	return 0;
 }
 
@@ -232,6 +247,8 @@ void radeon_driver_preclose_kms(struct d
 	struct radeon_device *rdev = dev->dev_private;
 	if (rdev->hyperz_filp == file_priv)
 		rdev->hyperz_filp = NULL;
+	if (rdev->cmask_filp == file_priv)
+		rdev->cmask_filp = NULL;
 }
 
 /*
@@ -277,6 +294,27 @@ void radeon_disable_vblank_kms(struct dr
 	radeon_irq_set(rdev);
 }
 
+int radeon_get_vblank_timestamp_kms(struct drm_device *dev, int crtc,
+				    int *max_error,
+				    struct timeval *vblank_time,
+				    unsigned flags)
+{
+	struct drm_crtc *drmcrtc;
+	struct radeon_device *rdev = dev->dev_private;
+
+	if (crtc < 0 || crtc >= dev->num_crtcs) {
+		DRM_ERROR("Invalid crtc %d\n", crtc);
+		return -EINVAL;
+	}
+
+	/* Get associated drm_crtc: */
+	drmcrtc = &rdev->mode_info.crtcs[crtc]->base;
+
+	/* Helper routine in DRM core does all the work: */
+	return drm_calc_vbltimestamp_from_scanoutpos(dev, crtc, max_error,
+						     vblank_time, flags,
+						     drmcrtc);
+}
 
 /*
  * IOCTL.
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/radeon_legacy_crtc.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/radeon_legacy_crtc.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/radeon_legacy_crtc.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/radeon_legacy_crtc.c	2011-03-14 21:20:32.000000000 -0400
@@ -443,7 +443,7 @@ int radeon_crtc_do_set_base(struct drm_c
 		       (target_fb->bits_per_pixel * 8));
 	crtc_pitch |= crtc_pitch << 16;
 
-
+	crtc_offset_cntl |= RADEON_CRTC_GUI_TRIG_OFFSET_LEFT_EN;
 	if (tiling_flags & RADEON_TILING_MACRO) {
 		if (ASIC_IS_R300(rdev))
 			crtc_offset_cntl |= (R300_CRTC_X_Y_MODE_EN |
@@ -502,6 +502,7 @@ int radeon_crtc_do_set_base(struct drm_c
 	gen_cntl_val = RREG32(gen_cntl_reg);
 	gen_cntl_val &= ~(0xf << 8);
 	gen_cntl_val |= (format << 8);
+	gen_cntl_val &= ~RADEON_CRTC_VSTAT_MODE_MASK;
 	WREG32(gen_cntl_reg, gen_cntl_val);
 
 	crtc_offset = (u32)base;
@@ -778,9 +779,9 @@ static void radeon_set_pll(struct drm_cr
 	DRM_DEBUG_KMS("\n");
 
 	if (!use_bios_divs) {
-		radeon_compute_pll(pll, mode->clock,
-				   &freq, &feedback_div, &frac_fb_div,
-				   &reference_div, &post_divider);
+		radeon_compute_pll_legacy(pll, mode->clock,
+					  &freq, &feedback_div, &frac_fb_div,
+					  &reference_div, &post_divider);
 
 		for (post_div = &post_divs[0]; post_div->divider; ++post_div) {
 			if (post_div->divider == post_divider)
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/radeon_mode.h linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/radeon_mode.h
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/radeon_mode.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/radeon_mode.h	2011-03-14 21:20:32.000000000 -0400
@@ -149,6 +149,7 @@ struct radeon_tmds_pll {
 #define RADEON_PLL_PREFER_CLOSEST_LOWER (1 << 11)
 #define RADEON_PLL_USE_POST_DIV         (1 << 12)
 #define RADEON_PLL_IS_LCD               (1 << 13)
+#define RADEON_PLL_PREFER_MINM_OVER_MAXP (1 << 14)
 
 struct radeon_pll {
 	/* reference frequency */
@@ -208,6 +209,7 @@ enum radeon_connector_table {
 	CT_EMAC,
 	CT_RN50_POWER,
 	CT_MAC_X800,
+	CT_MAC_G5_9600,
 };
 
 enum radeon_dvo_chip {
@@ -277,6 +279,9 @@ struct radeon_crtc {
 	fixed20_12 hsc;
 	struct drm_display_mode native_mode;
 	int pll_id;
+	/* page flipping */
+	struct radeon_unpin_work *unpin_work;
+	int deferred_flip_completion;
 };
 
 struct radeon_encoder_primary_dac {
@@ -376,6 +381,7 @@ struct radeon_encoder {
 	int hdmi_audio_workaround;
 	int hdmi_buffer_status;
 	bool is_ext_encoder;
+	u16 caps;
 };
 
 struct radeon_connector_atom_dig {
@@ -442,10 +448,6 @@ struct radeon_framebuffer {
 	struct drm_gem_object *obj;
 };
 
-/* radeon_get_crtc_scanoutpos() return flags */
-#define RADEON_SCANOUTPOS_VALID        (1 << 0)
-#define RADEON_SCANOUTPOS_INVBL        (1 << 1)
-#define RADEON_SCANOUTPOS_ACCURATE     (1 << 2)
 
 extern enum radeon_tv_std
 radeon_combios_get_tv_info(struct radeon_device *rdev);
@@ -510,13 +512,21 @@ extern bool radeon_atombios_get_asic_ss_
 					     struct radeon_atom_ss *ss,
 					     int id, u32 clock);
 
-extern void radeon_compute_pll(struct radeon_pll *pll,
-			       uint64_t freq,
-			       uint32_t *dot_clock_p,
-			       uint32_t *fb_div_p,
-			       uint32_t *frac_fb_div_p,
-			       uint32_t *ref_div_p,
-			       uint32_t *post_div_p);
+extern void radeon_compute_pll_legacy(struct radeon_pll *pll,
+				      uint64_t freq,
+				      uint32_t *dot_clock_p,
+				      uint32_t *fb_div_p,
+				      uint32_t *frac_fb_div_p,
+				      uint32_t *ref_div_p,
+				      uint32_t *post_div_p);
+
+extern void radeon_compute_pll_avivo(struct radeon_pll *pll,
+				     u32 freq,
+				     u32 *dot_clock_p,
+				     u32 *fb_div_p,
+				     u32 *frac_fb_div_p,
+				     u32 *ref_div_p,
+				     u32 *post_div_p);
 
 extern void radeon_setup_encoder_clones(struct drm_device *dev);
 
@@ -562,11 +572,12 @@ extern int radeon_crtc_cursor_set(struct
 extern int radeon_crtc_cursor_move(struct drm_crtc *crtc,
 				   int x, int y);
 
-extern int radeon_get_crtc_scanoutpos(struct radeon_device *rdev, int crtc, int *vpos, int *hpos);
+extern int radeon_get_crtc_scanoutpos(struct drm_device *dev, int crtc,
+				      int *vpos, int *hpos);
 
 extern bool radeon_combios_check_hardcoded_edid(struct radeon_device *rdev);
 extern struct edid *
-radeon_combios_get_hardcoded_edid(struct radeon_device *rdev);
+radeon_bios_get_hardcoded_edid(struct radeon_device *rdev);
 extern bool radeon_atom_get_clock_info(struct drm_device *dev);
 extern bool radeon_combios_get_clock_info(struct drm_device *dev);
 extern struct radeon_encoder_atom_dig *
@@ -662,4 +673,7 @@ int radeon_fbdev_total_size(struct radeo
 bool radeon_fbdev_robj_is_fb(struct radeon_device *rdev, struct radeon_bo *robj);
 
 void radeon_fb_output_poll_changed(struct radeon_device *rdev);
+
+void radeon_crtc_handle_flip(struct radeon_device *rdev, int crtc_id);
+
 #endif
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/radeon_object.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/radeon_object.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/radeon_object.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/radeon_object.c	2011-03-14 21:20:32.000000000 -0400
@@ -34,6 +34,7 @@
 #include <drm/drmP.h>
 #include "radeon_drm.h"
 #include "radeon.h"
+#include "radeon_trace.h"
 
 
 int radeon_ttm_init(struct radeon_device *rdev);
@@ -146,6 +147,7 @@ retry:
 		list_add_tail(&bo->list, &rdev->gem.objects);
 		mutex_unlock(&bo->rdev->gem.mutex);
 	}
+	trace_radeon_bo_create(bo);
 	return 0;
 }
 
@@ -302,34 +304,9 @@ void radeon_bo_list_add_object(struct ra
 				struct list_head *head)
 {
 	if (lobj->wdomain) {
-		list_add(&lobj->list, head);
+		list_add(&lobj->tv.head, head);
 	} else {
-		list_add_tail(&lobj->list, head);
-	}
-}
-
-int radeon_bo_list_reserve(struct list_head *head)
-{
-	struct radeon_bo_list *lobj;
-	int r;
-
-	list_for_each_entry(lobj, head, list){
-		r = radeon_bo_reserve(lobj->bo, false);
-		if (unlikely(r != 0))
-			return r;
-		lobj->reserved = true;
-	}
-	return 0;
-}
-
-void radeon_bo_list_unreserve(struct list_head *head)
-{
-	struct radeon_bo_list *lobj;
-
-	list_for_each_entry(lobj, head, list) {
-		/* only unreserve object we successfully reserved */
-		if (lobj->reserved && radeon_bo_is_reserved(lobj->bo))
-			radeon_bo_unreserve(lobj->bo);
+		list_add_tail(&lobj->tv.head, head);
 	}
 }
 
@@ -340,14 +317,11 @@ int radeon_bo_list_validate(struct list_
 	u32 domain;
 	int r;
 
-	list_for_each_entry(lobj, head, list) {
-		lobj->reserved = false;
-	}
-	r = radeon_bo_list_reserve(head);
+	r = ttm_eu_reserve_buffers(head);
 	if (unlikely(r != 0)) {
 		return r;
 	}
-	list_for_each_entry(lobj, head, list) {
+	list_for_each_entry(lobj, head, tv.head) {
 		bo = lobj->bo;
 		if (!bo->pin_count) {
 			domain = lobj->wdomain ? lobj->wdomain : lobj->rdomain;
@@ -370,25 +344,6 @@ int radeon_bo_list_validate(struct list_
 	return 0;
 }
 
-void radeon_bo_list_fence(struct list_head *head, void *fence)
-{
-	struct radeon_bo_list *lobj;
-	struct radeon_bo *bo;
-	struct radeon_fence *old_fence = NULL;
-
-	list_for_each_entry(lobj, head, list) {
-		bo = lobj->bo;
-		spin_lock(&bo->tbo.lock);
-		old_fence = (struct radeon_fence *)bo->tbo.sync_obj;
-		bo->tbo.sync_obj = radeon_fence_ref(fence);
-		bo->tbo.sync_obj_arg = NULL;
-		spin_unlock(&bo->tbo.lock);
-		if (old_fence) {
-			radeon_fence_unref(&old_fence);
-		}
-	}
-}
-
 int radeon_bo_fbdev_mmap(struct radeon_bo *bo,
 			     struct vm_area_struct *vma)
 {
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/radeon_object.h linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/radeon_object.h
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/radeon_object.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/radeon_object.h	2011-03-14 21:20:32.000000000 -0400
@@ -126,12 +126,12 @@ static inline int radeon_bo_wait(struct
 	r = ttm_bo_reserve(&bo->tbo, true, no_wait, false, 0);
 	if (unlikely(r != 0))
 		return r;
-	spin_lock(&bo->tbo.lock);
+	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.lock);
+	spin_unlock(&bo->tbo.bdev->fence_lock);
 	ttm_bo_unreserve(&bo->tbo);
 	return r;
 }
@@ -152,10 +152,7 @@ extern int radeon_bo_init(struct radeon_
 extern void radeon_bo_fini(struct radeon_device *rdev);
 extern void radeon_bo_list_add_object(struct radeon_bo_list *lobj,
 				struct list_head *head);
-extern int radeon_bo_list_reserve(struct list_head *head);
-extern void radeon_bo_list_unreserve(struct list_head *head);
 extern int radeon_bo_list_validate(struct list_head *head);
-extern void radeon_bo_list_fence(struct list_head *head, void *fence);
 extern int radeon_bo_fbdev_mmap(struct radeon_bo *bo,
 				struct vm_area_struct *vma);
 extern int radeon_bo_set_tiling_flags(struct radeon_bo *bo,
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/radeon_pm.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/radeon_pm.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/radeon_pm.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/radeon_pm.c	2011-03-14 21:20:32.000000000 -0400
@@ -167,13 +167,13 @@ static void radeon_set_power_state(struc
 	if (radeon_gui_idle(rdev)) {
 		sclk = rdev->pm.power_state[rdev->pm.requested_power_state_index].
 			clock_info[rdev->pm.requested_clock_mode_index].sclk;
-		if (sclk > rdev->clock.default_sclk)
-			sclk = rdev->clock.default_sclk;
+		if (sclk > rdev->pm.default_sclk)
+			sclk = rdev->pm.default_sclk;
 
 		mclk = rdev->pm.power_state[rdev->pm.requested_power_state_index].
 			clock_info[rdev->pm.requested_clock_mode_index].mclk;
-		if (mclk > rdev->clock.default_mclk)
-			mclk = rdev->clock.default_mclk;
+		if (mclk > rdev->pm.default_mclk)
+			mclk = rdev->pm.default_mclk;
 
 		/* upvolt before raising clocks, downvolt after lowering clocks */
 		if (sclk < rdev->pm.current_sclk)
@@ -405,20 +405,13 @@ static ssize_t radeon_set_pm_method(stru
 		rdev->pm.dynpm_planned_action = DYNPM_ACTION_DEFAULT;
 		mutex_unlock(&rdev->pm.mutex);
 	} else if (strncmp("profile", buf, strlen("profile")) == 0) {
-		bool flush_wq = false;
-
 		mutex_lock(&rdev->pm.mutex);
-		if (rdev->pm.pm_method == PM_METHOD_DYNPM) {
-			cancel_delayed_work(&rdev->pm.dynpm_idle_work);
-			flush_wq = true;
-		}
 		/* disable dynpm */
 		rdev->pm.dynpm_state = DYNPM_STATE_DISABLED;
 		rdev->pm.dynpm_planned_action = DYNPM_ACTION_NONE;
 		rdev->pm.pm_method = PM_METHOD_PROFILE;
 		mutex_unlock(&rdev->pm.mutex);
-		if (flush_wq)
-			flush_workqueue(rdev->wq);
+		cancel_delayed_work_sync(&rdev->pm.dynpm_idle_work);
 	} else {
 		DRM_ERROR("invalid power method!\n");
 		goto fail;
@@ -437,7 +430,7 @@ static ssize_t radeon_hwmon_show_temp(st
 {
 	struct drm_device *ddev = pci_get_drvdata(to_pci_dev(dev));
 	struct radeon_device *rdev = ddev->dev_private;
-	u32 temp;
+	int temp;
 
 	switch (rdev->pm.int_thermal_type) {
 	case THERMAL_TYPE_RV6XX:
@@ -447,8 +440,12 @@ static ssize_t radeon_hwmon_show_temp(st
 		temp = rv770_get_temp(rdev);
 		break;
 	case THERMAL_TYPE_EVERGREEN:
+	case THERMAL_TYPE_NI:
 		temp = evergreen_get_temp(rdev);
 		break;
+	case THERMAL_TYPE_SUMO:
+		temp = sumo_get_temp(rdev);
+		break;
 	default:
 		temp = 0;
 		break;
@@ -487,6 +484,7 @@ static int radeon_hwmon_init(struct rade
 	case THERMAL_TYPE_RV6XX:
 	case THERMAL_TYPE_RV770:
 	case THERMAL_TYPE_EVERGREEN:
+	case THERMAL_TYPE_SUMO:
 		rdev->pm.int_hwmon_dev = hwmon_device_register(rdev->dev);
 		if (IS_ERR(rdev->pm.int_hwmon_dev)) {
 			err = PTR_ERR(rdev->pm.int_hwmon_dev);
@@ -520,34 +518,39 @@ static void radeon_hwmon_fini(struct rad
 
 void radeon_pm_suspend(struct radeon_device *rdev)
 {
-	bool flush_wq = false;
-
 	mutex_lock(&rdev->pm.mutex);
 	if (rdev->pm.pm_method == PM_METHOD_DYNPM) {
-		cancel_delayed_work(&rdev->pm.dynpm_idle_work);
 		if (rdev->pm.dynpm_state == DYNPM_STATE_ACTIVE)
 			rdev->pm.dynpm_state = DYNPM_STATE_SUSPENDED;
-		flush_wq = true;
 	}
 	mutex_unlock(&rdev->pm.mutex);
-	if (flush_wq)
-		flush_workqueue(rdev->wq);
+
+	cancel_delayed_work_sync(&rdev->pm.dynpm_idle_work);
 }
 
 void radeon_pm_resume(struct radeon_device *rdev)
 {
+	/* set up the default clocks if the MC ucode is loaded */
+	if (ASIC_IS_DCE5(rdev) && rdev->mc_fw) {
+		if (rdev->pm.default_vddc)
+			radeon_atom_set_voltage(rdev, rdev->pm.default_vddc);
+		if (rdev->pm.default_sclk)
+			radeon_set_engine_clock(rdev, rdev->pm.default_sclk);
+		if (rdev->pm.default_mclk)
+			radeon_set_memory_clock(rdev, rdev->pm.default_mclk);
+	}
 	/* asic init will reset the default power state */
 	mutex_lock(&rdev->pm.mutex);
 	rdev->pm.current_power_state_index = rdev->pm.default_power_state_index;
 	rdev->pm.current_clock_mode_index = 0;
-	rdev->pm.current_sclk = rdev->clock.default_sclk;
-	rdev->pm.current_mclk = rdev->clock.default_mclk;
+	rdev->pm.current_sclk = rdev->pm.default_sclk;
+	rdev->pm.current_mclk = rdev->pm.default_mclk;
 	rdev->pm.current_vddc = rdev->pm.power_state[rdev->pm.default_power_state_index].clock_info[0].voltage.voltage;
 	if (rdev->pm.pm_method == PM_METHOD_DYNPM
 	    && rdev->pm.dynpm_state == DYNPM_STATE_SUSPENDED) {
 		rdev->pm.dynpm_state = DYNPM_STATE_ACTIVE;
-		queue_delayed_work(rdev->wq, &rdev->pm.dynpm_idle_work,
-					msecs_to_jiffies(RADEON_IDLE_LOOP_MS));
+		schedule_delayed_work(&rdev->pm.dynpm_idle_work,
+				      msecs_to_jiffies(RADEON_IDLE_LOOP_MS));
 	}
 	mutex_unlock(&rdev->pm.mutex);
 	radeon_pm_compute_clocks(rdev);
@@ -564,6 +567,8 @@ int radeon_pm_init(struct radeon_device
 	rdev->pm.dynpm_planned_action = DYNPM_ACTION_NONE;
 	rdev->pm.dynpm_can_upclock = true;
 	rdev->pm.dynpm_can_downclock = true;
+	rdev->pm.default_sclk = rdev->clock.default_sclk;
+	rdev->pm.default_mclk = rdev->clock.default_mclk;
 	rdev->pm.current_sclk = rdev->clock.default_sclk;
 	rdev->pm.current_mclk = rdev->clock.default_mclk;
 	rdev->pm.int_thermal_type = THERMAL_TYPE_NONE;
@@ -575,12 +580,24 @@ int radeon_pm_init(struct radeon_device
 			radeon_combios_get_power_modes(rdev);
 		radeon_pm_print_states(rdev);
 		radeon_pm_init_profile(rdev);
+		/* set up the default clocks if the MC ucode is loaded */
+		if (ASIC_IS_DCE5(rdev) && rdev->mc_fw) {
+			if (rdev->pm.default_vddc)
+				radeon_atom_set_voltage(rdev, rdev->pm.default_vddc);
+			if (rdev->pm.default_sclk)
+				radeon_set_engine_clock(rdev, rdev->pm.default_sclk);
+			if (rdev->pm.default_mclk)
+				radeon_set_memory_clock(rdev, rdev->pm.default_mclk);
+		}
 	}
 
 	/* set up the internal thermal sensor if applicable */
 	ret = radeon_hwmon_init(rdev);
 	if (ret)
 		return ret;
+
+	INIT_DELAYED_WORK(&rdev->pm.dynpm_idle_work, radeon_dynpm_idle_work_handler);
+
 	if (rdev->pm.num_power_states > 1) {
 		/* where's the best place to put these? */
 		ret = device_create_file(rdev->dev, &dev_attr_power_profile);
@@ -594,8 +611,6 @@ int radeon_pm_init(struct radeon_device
 		rdev->acpi_nb.notifier_call = radeon_acpi_event;
 		register_acpi_notifier(&rdev->acpi_nb);
 #endif
-		INIT_DELAYED_WORK(&rdev->pm.dynpm_idle_work, radeon_dynpm_idle_work_handler);
-
 		if (radeon_debugfs_pm_init(rdev)) {
 			DRM_ERROR("Failed to register debugfs file for PM!\n");
 		}
@@ -609,25 +624,20 @@ int radeon_pm_init(struct radeon_device
 void radeon_pm_fini(struct radeon_device *rdev)
 {
 	if (rdev->pm.num_power_states > 1) {
-		bool flush_wq = false;
-
 		mutex_lock(&rdev->pm.mutex);
 		if (rdev->pm.pm_method == PM_METHOD_PROFILE) {
 			rdev->pm.profile = PM_PROFILE_DEFAULT;
 			radeon_pm_update_profile(rdev);
 			radeon_pm_set_clocks(rdev);
 		} else if (rdev->pm.pm_method == PM_METHOD_DYNPM) {
-			/* cancel work */
-			cancel_delayed_work(&rdev->pm.dynpm_idle_work);
-			flush_wq = true;
 			/* reset default clocks */
 			rdev->pm.dynpm_state = DYNPM_STATE_DISABLED;
 			rdev->pm.dynpm_planned_action = DYNPM_ACTION_DEFAULT;
 			radeon_pm_set_clocks(rdev);
 		}
 		mutex_unlock(&rdev->pm.mutex);
-		if (flush_wq)
-			flush_workqueue(rdev->wq);
+
+		cancel_delayed_work_sync(&rdev->pm.dynpm_idle_work);
 
 		device_remove_file(rdev->dev, &dev_attr_power_profile);
 		device_remove_file(rdev->dev, &dev_attr_power_method);
@@ -636,6 +646,9 @@ void radeon_pm_fini(struct radeon_device
 #endif
 	}
 
+	if (rdev->pm.power_state)
+		kfree(rdev->pm.power_state);
+
 	radeon_hwmon_fini(rdev);
 }
 
@@ -686,12 +699,12 @@ void radeon_pm_compute_clocks(struct rad
 					radeon_pm_get_dynpm_state(rdev);
 					radeon_pm_set_clocks(rdev);
 
-					queue_delayed_work(rdev->wq, &rdev->pm.dynpm_idle_work,
-							   msecs_to_jiffies(RADEON_IDLE_LOOP_MS));
+					schedule_delayed_work(&rdev->pm.dynpm_idle_work,
+							      msecs_to_jiffies(RADEON_IDLE_LOOP_MS));
 				} else if (rdev->pm.dynpm_state == DYNPM_STATE_PAUSED) {
 					rdev->pm.dynpm_state = DYNPM_STATE_ACTIVE;
-					queue_delayed_work(rdev->wq, &rdev->pm.dynpm_idle_work,
-							   msecs_to_jiffies(RADEON_IDLE_LOOP_MS));
+					schedule_delayed_work(&rdev->pm.dynpm_idle_work,
+							      msecs_to_jiffies(RADEON_IDLE_LOOP_MS));
 					DRM_DEBUG_DRIVER("radeon: dynamic power management activated\n");
 				}
 			} else { /* count == 0 */
@@ -720,9 +733,9 @@ static bool radeon_pm_in_vbl(struct rade
 	 */
 	for (crtc = 0; (crtc < rdev->num_crtc) && in_vbl; crtc++) {
 		if (rdev->pm.active_crtcs & (1 << crtc)) {
-			vbl_status = radeon_get_crtc_scanoutpos(rdev, crtc, &vpos, &hpos);
-			if ((vbl_status & RADEON_SCANOUTPOS_VALID) &&
-			    !(vbl_status & RADEON_SCANOUTPOS_INVBL))
+			vbl_status = radeon_get_crtc_scanoutpos(rdev->ddev, crtc, &vpos, &hpos);
+			if ((vbl_status & DRM_SCANOUTPOS_VALID) &&
+			    !(vbl_status & DRM_SCANOUTPOS_INVBL))
 				in_vbl = false;
 		}
 	}
@@ -796,8 +809,8 @@ static void radeon_dynpm_idle_work_handl
 			radeon_pm_set_clocks(rdev);
 		}
 
-		queue_delayed_work(rdev->wq, &rdev->pm.dynpm_idle_work,
-					msecs_to_jiffies(RADEON_IDLE_LOOP_MS));
+		schedule_delayed_work(&rdev->pm.dynpm_idle_work,
+				      msecs_to_jiffies(RADEON_IDLE_LOOP_MS));
 	}
 	mutex_unlock(&rdev->pm.mutex);
 	ttm_bo_unlock_delayed_workqueue(&rdev->mman.bdev, resched);
@@ -814,9 +827,9 @@ static int radeon_debugfs_pm_info(struct
 	struct drm_device *dev = node->minor->dev;
 	struct radeon_device *rdev = dev->dev_private;
 
-	seq_printf(m, "default engine clock: %u0 kHz\n", rdev->clock.default_sclk);
+	seq_printf(m, "default engine clock: %u0 kHz\n", rdev->pm.default_sclk);
 	seq_printf(m, "current engine clock: %u0 kHz\n", radeon_get_engine_clock(rdev));
-	seq_printf(m, "default memory clock: %u0 kHz\n", rdev->clock.default_mclk);
+	seq_printf(m, "default memory clock: %u0 kHz\n", rdev->pm.default_mclk);
 	if (rdev->asic->get_memory_clock)
 		seq_printf(m, "current memory clock: %u0 kHz\n", radeon_get_memory_clock(rdev));
 	if (rdev->pm.current_vddc)
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/radeon_reg.h linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/radeon_reg.h
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/radeon_reg.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/radeon_reg.h	2011-03-14 21:20:32.000000000 -0400
@@ -55,6 +55,7 @@
 #include "r500_reg.h"
 #include "r600_reg.h"
 #include "evergreen_reg.h"
+#include "ni_reg.h"
 
 #define RADEON_MC_AGP_LOCATION		0x014c
 #define		RADEON_MC_AGP_START_MASK	0x0000FFFF
@@ -320,6 +321,15 @@
 #       define RADEON_PCIE_LC_RECONFIG_NOW         (1 << 8)
 #       define RADEON_PCIE_LC_RECONFIG_LATER       (1 << 9)
 #       define RADEON_PCIE_LC_SHORT_RECONFIG_EN    (1 << 10)
+#       define R600_PCIE_LC_RECONFIG_ARC_MISSING_ESCAPE   (1 << 7)
+#       define R600_PCIE_LC_RENEGOTIATION_SUPPORT  (1 << 9)
+#       define R600_PCIE_LC_RENEGOTIATE_EN         (1 << 10)
+#       define R600_PCIE_LC_SHORT_RECONFIG_EN      (1 << 11)
+#       define R600_PCIE_LC_UPCONFIGURE_SUPPORT    (1 << 12)
+#       define R600_PCIE_LC_UPCONFIGURE_DIS        (1 << 13)
+
+#define R600_TARGET_AND_CURRENT_PROFILE_INDEX      0x70c
+#define R700_TARGET_AND_CURRENT_PROFILE_INDEX      0x66c
 
 #define RADEON_CACHE_CNTL                   0x1724
 #define RADEON_CACHE_LINE                   0x0f0c /* PCI */
@@ -365,6 +375,8 @@
 #define RADEON_CONFIG_APER_SIZE             0x0108
 #define RADEON_CONFIG_BONDS                 0x00e8
 #define RADEON_CONFIG_CNTL                  0x00e0
+#       define RADEON_CFG_VGA_RAM_EN        (1 << 8)
+#       define RADEON_CFG_VGA_IO_DIS        (1 << 9)
 #       define RADEON_CFG_ATI_REV_A11       (0   << 16)
 #       define RADEON_CFG_ATI_REV_A12       (1   << 16)
 #       define RADEON_CFG_ATI_REV_A13       (2   << 16)
@@ -422,6 +434,7 @@
 #       define RADEON_CRTC_CSYNC_EN         (1 <<  4)
 #       define RADEON_CRTC_ICON_EN          (1 << 15)
 #       define RADEON_CRTC_CUR_EN           (1 << 16)
+#       define RADEON_CRTC_VSTAT_MODE_MASK  (3 << 17)
 #       define RADEON_CRTC_CUR_MODE_MASK    (7 << 20)
 #       define RADEON_CRTC_CUR_MODE_SHIFT   20
 #       define RADEON_CRTC_CUR_MODE_MONO    0
@@ -509,6 +522,8 @@
 #       define RADEON_CRTC_TILE_EN                      (1 << 15)
 #       define RADEON_CRTC_OFFSET_FLIP_CNTL             (1 << 16)
 #       define RADEON_CRTC_STEREO_OFFSET_EN             (1 << 17)
+#       define RADEON_CRTC_GUI_TRIG_OFFSET_LEFT_EN      (1 << 28)
+#       define RADEON_CRTC_GUI_TRIG_OFFSET_RIGHT_EN     (1 << 29)
 
 #define R300_CRTC_TILE_X0_Y0	            0x0350
 #define R300_CRTC2_TILE_X0_Y0	            0x0358
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/radeon_trace.h linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/radeon_trace.h
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/radeon_trace.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/radeon_trace.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,82 @@
+#if !defined(_RADEON_TRACE_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _RADEON_TRACE_H_
+
+#include <linux/stringify.h>
+#include <linux/types.h>
+#include <linux/tracepoint.h>
+
+#include <drm/drmP.h>
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM radeon
+#define TRACE_SYSTEM_STRING __stringify(TRACE_SYSTEM)
+#define TRACE_INCLUDE_FILE radeon_trace
+
+TRACE_EVENT(radeon_bo_create,
+	    TP_PROTO(struct radeon_bo *bo),
+	    TP_ARGS(bo),
+	    TP_STRUCT__entry(
+			     __field(struct radeon_bo *, bo)
+			     __field(u32, pages)
+			     ),
+
+	    TP_fast_assign(
+			   __entry->bo = bo;
+			   __entry->pages = bo->tbo.num_pages;
+			   ),
+	    TP_printk("bo=%p, pages=%u", __entry->bo, __entry->pages)
+);
+
+DECLARE_EVENT_CLASS(radeon_fence_request,
+
+	    TP_PROTO(struct drm_device *dev, u32 seqno),
+
+	    TP_ARGS(dev, seqno),
+
+	    TP_STRUCT__entry(
+			     __field(u32, dev)
+			     __field(u32, seqno)
+			     ),
+
+	    TP_fast_assign(
+			   __entry->dev = dev->primary->index;
+			   __entry->seqno = seqno;
+			   ),
+
+	    TP_printk("dev=%u, seqno=%u", __entry->dev, __entry->seqno)
+);
+
+DEFINE_EVENT(radeon_fence_request, radeon_fence_emit,
+
+	    TP_PROTO(struct drm_device *dev, u32 seqno),
+
+	    TP_ARGS(dev, seqno)
+);
+
+DEFINE_EVENT(radeon_fence_request, radeon_fence_retire,
+
+	    TP_PROTO(struct drm_device *dev, u32 seqno),
+
+	    TP_ARGS(dev, seqno)
+);
+
+DEFINE_EVENT(radeon_fence_request, radeon_fence_wait_begin,
+
+	    TP_PROTO(struct drm_device *dev, u32 seqno),
+
+	    TP_ARGS(dev, seqno)
+);
+
+DEFINE_EVENT(radeon_fence_request, radeon_fence_wait_end,
+
+	    TP_PROTO(struct drm_device *dev, u32 seqno),
+
+	    TP_ARGS(dev, seqno)
+);
+
+#endif
+
+/* This part must be outside protection */
+#undef TRACE_INCLUDE_PATH
+#define TRACE_INCLUDE_PATH .
+#include <trace/define_trace.h>
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/radeon_trace_points.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/radeon_trace_points.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/radeon_trace_points.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/radeon_trace_points.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,9 @@
+/* Copyright Red Hat Inc 2010.
+ * Author : Dave Airlie <airlied@redhat.com>
+ */
+#include <drm/drmP.h>
+#include "radeon_drm.h"
+#include "radeon.h"
+
+#define CREATE_TRACE_POINTS
+#include "radeon_trace.h"
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/radeon_ttm.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/radeon_ttm.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/radeon_ttm.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/radeon_ttm.c	2011-03-14 21:20:32.000000000 -0400
@@ -589,6 +589,20 @@ void radeon_ttm_fini(struct radeon_devic
 	DRM_INFO("radeon: ttm finalized\n");
 }
 
+/* this should only be called at bootup or when userspace
+ * isn't running */
+void radeon_ttm_set_active_vram_size(struct radeon_device *rdev, u64 size)
+{
+	struct ttm_mem_type_manager *man;
+
+	if (!rdev->mman.initialized)
+		return;
+
+	man = &rdev->mman.bdev.man[TTM_PL_VRAM];
+	/* this just adjusts TTM size idea, which sets lpfn to the correct value */
+	man->size = size >> PAGE_SHIFT;
+}
+
 static struct vm_operations_struct radeon_ttm_vm_ops;
 static const struct vm_operations_struct *ttm_vm_ops = NULL;
 
@@ -787,9 +801,9 @@ static int radeon_ttm_debugfs_init(struc
 		radeon_mem_types_list[i].show = &radeon_mm_dump_table;
 		radeon_mem_types_list[i].driver_features = 0;
 		if (i == 0)
-			radeon_mem_types_list[i].data = &rdev->mman.bdev.man[TTM_PL_VRAM].priv;
+			radeon_mem_types_list[i].data = rdev->mman.bdev.man[TTM_PL_VRAM].priv;
 		else
-			radeon_mem_types_list[i].data = &rdev->mman.bdev.man[TTM_PL_TT].priv;
+			radeon_mem_types_list[i].data = rdev->mman.bdev.man[TTM_PL_TT].priv;
 
 	}
 	/* Add ttm page pool to debugfs */
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/reg_srcs/evergreen linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/reg_srcs/evergreen
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/reg_srcs/evergreen	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/reg_srcs/evergreen	2011-03-14 21:20:32.000000000 -0400
@@ -439,7 +439,7 @@ evergreen 0x9400
 0x000286EC SPI_COMPUTE_NUM_THREAD_X
 0x000286F0 SPI_COMPUTE_NUM_THREAD_Y
 0x000286F4 SPI_COMPUTE_NUM_THREAD_Z
-0x000286F8 GDS_ADDR_SIZE
+0x00028724 GDS_ADDR_SIZE
 0x00028780 CB_BLEND0_CONTROL
 0x00028784 CB_BLEND1_CONTROL
 0x00028788 CB_BLEND2_CONTROL
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/reg_srcs/r300 linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/reg_srcs/r300
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/reg_srcs/r300	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/reg_srcs/r300	2011-03-14 21:20:32.000000000 -0400
@@ -683,9 +683,7 @@ r300 0x4f60
 0x4DF4 US_ALU_CONST_G_31
 0x4DF8 US_ALU_CONST_B_31
 0x4DFC US_ALU_CONST_A_31
-0x4E04 RB3D_BLENDCNTL_R3
 0x4E08 RB3D_ABLENDCNTL_R3
-0x4E0C RB3D_COLOR_CHANNEL_MASK
 0x4E10 RB3D_CONSTANT_COLOR
 0x4E14 RB3D_COLOR_CLEAR_VALUE
 0x4E18 RB3D_ROPCNTL_R3
@@ -706,13 +704,11 @@ r300 0x4f60
 0x4E74 RB3D_CMASK_WRINDEX
 0x4E78 RB3D_CMASK_DWORD
 0x4E7C RB3D_CMASK_RDINDEX
-0x4E80 RB3D_AARESOLVE_OFFSET
-0x4E84 RB3D_AARESOLVE_PITCH
-0x4E88 RB3D_AARESOLVE_CTL
 0x4EA0 RB3D_DISCARD_SRC_PIXEL_LTE_THRESHOLD
 0x4EA4 RB3D_DISCARD_SRC_PIXEL_GTE_THRESHOLD
 0x4F04 ZB_ZSTENCILCNTL
 0x4F08 ZB_STENCILREFMASK
 0x4F14 ZB_ZTOP
 0x4F18 ZB_ZCACHE_CTLSTAT
+0x4F28 ZB_DEPTHCLEARVALUE
 0x4F58 ZB_ZPASS_DATA
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/reg_srcs/r420 linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/reg_srcs/r420
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/reg_srcs/r420	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/reg_srcs/r420	2011-03-14 21:20:32.000000000 -0400
@@ -130,7 +130,6 @@ r420 0x4f60
 0x401C GB_SELECT
 0x4020 GB_AA_CONFIG
 0x4024 GB_FIFO_SIZE
-0x4028 GB_Z_PEQ_CONFIG
 0x4100 TX_INVALTAGS
 0x4200 GA_POINT_S0
 0x4204 GA_POINT_T0
@@ -750,9 +749,7 @@ r420 0x4f60
 0x4DF4 US_ALU_CONST_G_31
 0x4DF8 US_ALU_CONST_B_31
 0x4DFC US_ALU_CONST_A_31
-0x4E04 RB3D_BLENDCNTL_R3
 0x4E08 RB3D_ABLENDCNTL_R3
-0x4E0C RB3D_COLOR_CHANNEL_MASK
 0x4E10 RB3D_CONSTANT_COLOR
 0x4E14 RB3D_COLOR_CLEAR_VALUE
 0x4E18 RB3D_ROPCNTL_R3
@@ -773,13 +770,11 @@ r420 0x4f60
 0x4E74 RB3D_CMASK_WRINDEX
 0x4E78 RB3D_CMASK_DWORD
 0x4E7C RB3D_CMASK_RDINDEX
-0x4E80 RB3D_AARESOLVE_OFFSET
-0x4E84 RB3D_AARESOLVE_PITCH
-0x4E88 RB3D_AARESOLVE_CTL
 0x4EA0 RB3D_DISCARD_SRC_PIXEL_LTE_THRESHOLD
 0x4EA4 RB3D_DISCARD_SRC_PIXEL_GTE_THRESHOLD
 0x4F04 ZB_ZSTENCILCNTL
 0x4F08 ZB_STENCILREFMASK
 0x4F14 ZB_ZTOP
 0x4F18 ZB_ZCACHE_CTLSTAT
+0x4F28 ZB_DEPTHCLEARVALUE
 0x4F58 ZB_ZPASS_DATA
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/reg_srcs/rs600 linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/reg_srcs/rs600
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/reg_srcs/rs600	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/reg_srcs/rs600	2011-03-14 21:20:32.000000000 -0400
@@ -749,9 +749,7 @@ rs600 0x6d40
 0x4DF4 US_ALU_CONST_G_31
 0x4DF8 US_ALU_CONST_B_31
 0x4DFC US_ALU_CONST_A_31
-0x4E04 RB3D_BLENDCNTL_R3
 0x4E08 RB3D_ABLENDCNTL_R3
-0x4E0C RB3D_COLOR_CHANNEL_MASK
 0x4E10 RB3D_CONSTANT_COLOR
 0x4E14 RB3D_COLOR_CLEAR_VALUE
 0x4E18 RB3D_ROPCNTL_R3
@@ -772,13 +770,11 @@ rs600 0x6d40
 0x4E74 RB3D_CMASK_WRINDEX
 0x4E78 RB3D_CMASK_DWORD
 0x4E7C RB3D_CMASK_RDINDEX
-0x4E80 RB3D_AARESOLVE_OFFSET
-0x4E84 RB3D_AARESOLVE_PITCH
-0x4E88 RB3D_AARESOLVE_CTL
 0x4EA0 RB3D_DISCARD_SRC_PIXEL_LTE_THRESHOLD
 0x4EA4 RB3D_DISCARD_SRC_PIXEL_GTE_THRESHOLD
 0x4F04 ZB_ZSTENCILCNTL
 0x4F08 ZB_STENCILREFMASK
 0x4F14 ZB_ZTOP
 0x4F18 ZB_ZCACHE_CTLSTAT
+0x4F28 ZB_DEPTHCLEARVALUE
 0x4F58 ZB_ZPASS_DATA
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/reg_srcs/rv515 linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/reg_srcs/rv515
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/reg_srcs/rv515	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/reg_srcs/rv515	2011-03-14 21:20:32.000000000 -0400
@@ -164,7 +164,6 @@ rv515 0x6d40
 0x401C GB_SELECT
 0x4020 GB_AA_CONFIG
 0x4024 GB_FIFO_SIZE
-0x4028 GB_Z_PEQ_CONFIG
 0x4100 TX_INVALTAGS
 0x4114 SU_TEX_WRAP_PS3
 0x4118 PS3_ENABLE
@@ -304,6 +303,22 @@ rv515 0x6d40
 0x4630 US_CODE_ADDR
 0x4634 US_CODE_RANGE
 0x4638 US_CODE_OFFSET
+0x4640 US_FORMAT0_0
+0x4644 US_FORMAT0_1
+0x4648 US_FORMAT0_2
+0x464C US_FORMAT0_3
+0x4650 US_FORMAT0_4
+0x4654 US_FORMAT0_5
+0x4658 US_FORMAT0_6
+0x465C US_FORMAT0_7
+0x4660 US_FORMAT0_8
+0x4664 US_FORMAT0_9
+0x4668 US_FORMAT0_10
+0x466C US_FORMAT0_11
+0x4670 US_FORMAT0_12
+0x4674 US_FORMAT0_13
+0x4678 US_FORMAT0_14
+0x467C US_FORMAT0_15
 0x46A4 US_OUT_FMT_0
 0x46A8 US_OUT_FMT_1
 0x46AC US_OUT_FMT_2
@@ -445,9 +460,7 @@ rv515 0x6d40
 0x4DF4 US_ALU_CONST_G_31
 0x4DF8 US_ALU_CONST_B_31
 0x4DFC US_ALU_CONST_A_31
-0x4E04 RB3D_BLENDCNTL_R3
 0x4E08 RB3D_ABLENDCNTL_R3
-0x4E0C RB3D_COLOR_CHANNEL_MASK
 0x4E10 RB3D_CONSTANT_COLOR
 0x4E14 RB3D_COLOR_CLEAR_VALUE
 0x4E18 RB3D_ROPCNTL_R3
@@ -468,9 +481,6 @@ rv515 0x6d40
 0x4E74 RB3D_CMASK_WRINDEX
 0x4E78 RB3D_CMASK_DWORD
 0x4E7C RB3D_CMASK_RDINDEX
-0x4E80 RB3D_AARESOLVE_OFFSET
-0x4E84 RB3D_AARESOLVE_PITCH
-0x4E88 RB3D_AARESOLVE_CTL
 0x4EA0 RB3D_DISCARD_SRC_PIXEL_LTE_THRESHOLD
 0x4EA4 RB3D_DISCARD_SRC_PIXEL_GTE_THRESHOLD
 0x4EF8 RB3D_CONSTANT_COLOR_AR
@@ -480,4 +490,5 @@ rv515 0x6d40
 0x4F14 ZB_ZTOP
 0x4F18 ZB_ZCACHE_CTLSTAT
 0x4F58 ZB_ZPASS_DATA
+0x4F28 ZB_DEPTHCLEARVALUE
 0x4FD4 ZB_STENCILREFMASK_BF
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/rs400.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/rs400.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/rs400.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/rs400.c	2011-03-14 21:20:32.000000000 -0400
@@ -203,6 +203,9 @@ void rs400_gart_fini(struct radeon_devic
 	radeon_gart_table_ram_free(rdev);
 }
 
+#define RS400_PTE_WRITEABLE (1 << 2)
+#define RS400_PTE_READABLE  (1 << 3)
+
 int rs400_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr)
 {
 	uint32_t entry;
@@ -213,7 +216,7 @@ int rs400_gart_set_page(struct radeon_de
 
 	entry = (lower_32_bits(addr) & PAGE_MASK) |
 		((upper_32_bits(addr) & 0xff) << 4) |
-		0xc;
+		RS400_PTE_WRITEABLE | RS400_PTE_READABLE;
 	entry = cpu_to_le32(entry);
 	rdev->gart.table.ram.ptr[i] = entry;
 	return 0;
@@ -226,8 +229,8 @@ int rs400_mc_wait_for_idle(struct radeon
 
 	for (i = 0; i < rdev->usec_timeout; i++) {
 		/* read MC_STATUS */
-		tmp = RREG32(0x0150);
-		if (tmp & (1 << 2)) {
+		tmp = RREG32(RADEON_MC_STATUS);
+		if (tmp & RADEON_MC_IDLE) {
 			return 0;
 		}
 		DRM_UDELAY(1);
@@ -241,7 +244,7 @@ void rs400_gpu_init(struct radeon_device
 	r420_pipes_init(rdev);
 	if (rs400_mc_wait_for_idle(rdev)) {
 		printk(KERN_WARNING "rs400: Failed to wait MC idle while "
-		       "programming pipes. Bad things might happen. %08x\n", RREG32(0x150));
+		       "programming pipes. Bad things might happen. %08x\n", RREG32(RADEON_MC_STATUS));
 	}
 }
 
@@ -300,9 +303,9 @@ static int rs400_debugfs_gart_info(struc
 		seq_printf(m, "MCCFG_AGP_BASE_2 0x%08x\n", tmp);
 		tmp = RREG32_MC(RS690_MCCFG_AGP_LOCATION);
 		seq_printf(m, "MCCFG_AGP_LOCATION 0x%08x\n", tmp);
-		tmp = RREG32_MC(0x100);
+		tmp = RREG32_MC(RS690_MCCFG_FB_LOCATION);
 		seq_printf(m, "MCCFG_FB_LOCATION 0x%08x\n", tmp);
-		tmp = RREG32(0x134);
+		tmp = RREG32(RS690_HDP_FB_LOCATION);
 		seq_printf(m, "HDP_FB_LOCATION 0x%08x\n", tmp);
 	} else {
 		tmp = RREG32(RADEON_AGP_BASE);
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/rs600.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/rs600.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/rs600.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/rs600.c	2011-03-14 21:20:32.000000000 -0400
@@ -46,6 +46,56 @@
 void rs600_gpu_init(struct radeon_device *rdev);
 int rs600_mc_wait_for_idle(struct radeon_device *rdev);
 
+void rs600_pre_page_flip(struct radeon_device *rdev, int crtc)
+{
+	struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc];
+	u32 tmp;
+
+	/* make sure flip is at vb rather than hb */
+	tmp = RREG32(AVIVO_D1GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset);
+	tmp &= ~AVIVO_D1GRPH_SURFACE_UPDATE_H_RETRACE_EN;
+	WREG32(AVIVO_D1GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset, tmp);
+
+	/* set pageflip to happen anywhere in vblank interval */
+	WREG32(AVIVO_D1MODE_MASTER_UPDATE_MODE + radeon_crtc->crtc_offset, 0);
+
+	/* enable the pflip int */
+	radeon_irq_kms_pflip_irq_get(rdev, crtc);
+}
+
+void rs600_post_page_flip(struct radeon_device *rdev, int crtc)
+{
+	/* disable the pflip int */
+	radeon_irq_kms_pflip_irq_put(rdev, crtc);
+}
+
+u32 rs600_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base)
+{
+	struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
+	u32 tmp = RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset);
+
+	/* Lock the graphics update lock */
+	tmp |= AVIVO_D1GRPH_UPDATE_LOCK;
+	WREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset, tmp);
+
+	/* update the scanout addresses */
+	WREG32(AVIVO_D1GRPH_SECONDARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset,
+	       (u32)crtc_base);
+	WREG32(AVIVO_D1GRPH_PRIMARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset,
+	       (u32)crtc_base);
+
+	/* Wait for update_pending to go high. */
+	while (!(RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset) & AVIVO_D1GRPH_SURFACE_UPDATE_PENDING));
+	DRM_DEBUG("Update pending now high. Unlocking vupdate_lock.\n");
+
+	/* Unlock the lock, so double-buffering can take place inside vblank */
+	tmp &= ~AVIVO_D1GRPH_UPDATE_LOCK;
+	WREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset, tmp);
+
+	/* Return current update_pending status: */
+	return RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset) & AVIVO_D1GRPH_SURFACE_UPDATE_PENDING;
+}
+
 void rs600_pm_misc(struct radeon_device *rdev)
 {
 	int requested_index = rdev->pm.requested_power_state_index;
@@ -289,16 +339,16 @@ void rs600_bm_disable(struct radeon_devi
 
 int rs600_asic_reset(struct radeon_device *rdev)
 {
-	u32 status, tmp;
-
 	struct rv515_mc_save save;
+	u32 status, tmp;
+	int ret = 0;
 
-	/* Stops all mc clients */
-	rv515_mc_stop(rdev, &save);
 	status = RREG32(R_000E40_RBBM_STATUS);
 	if (!G_000E40_GUI_ACTIVE(status)) {
 		return 0;
 	}
+	/* Stops all mc clients */
+	rv515_mc_stop(rdev, &save);
 	status = RREG32(R_000E40_RBBM_STATUS);
 	dev_info(rdev->dev, "(%s:%d) RBBM_STATUS=0x%08X\n", __func__, __LINE__, status);
 	/* stop CP */
@@ -342,11 +392,11 @@ int rs600_asic_reset(struct radeon_devic
 	if (G_000E40_GA_BUSY(status) || G_000E40_VAP_BUSY(status)) {
 		dev_err(rdev->dev, "failed to reset GPU\n");
 		rdev->gpu_lockup = true;
-		return -1;
-	}
+		ret = -1;
+	} else
+		dev_info(rdev->dev, "GPU reset succeed\n");
 	rv515_mc_resume(rdev, &save);
-	dev_info(rdev->dev, "GPU reset succeed\n");
-	return 0;
+	return ret;
 }
 
 /*
@@ -515,10 +565,12 @@ int rs600_irq_set(struct radeon_device *
 	if (rdev->irq.gui_idle) {
 		tmp |= S_000040_GUI_IDLE(1);
 	}
-	if (rdev->irq.crtc_vblank_int[0]) {
+	if (rdev->irq.crtc_vblank_int[0] ||
+	    rdev->irq.pflip[0]) {
 		mode_int |= S_006540_D1MODE_VBLANK_INT_MASK(1);
 	}
-	if (rdev->irq.crtc_vblank_int[1]) {
+	if (rdev->irq.crtc_vblank_int[1] ||
+	    rdev->irq.pflip[1]) {
 		mode_int |= S_006540_D2MODE_VBLANK_INT_MASK(1);
 	}
 	if (rdev->irq.hpd[0]) {
@@ -534,7 +586,7 @@ int rs600_irq_set(struct radeon_device *
 	return 0;
 }
 
-static inline uint32_t rs600_irq_ack(struct radeon_device *rdev, u32 *r500_disp_int)
+static inline u32 rs600_irq_ack(struct radeon_device *rdev)
 {
 	uint32_t irqs = RREG32(R_000044_GEN_INT_STATUS);
 	uint32_t irq_mask = S_000044_SW_INT(1);
@@ -547,27 +599,27 @@ static inline uint32_t rs600_irq_ack(str
 	}
 
 	if (G_000044_DISPLAY_INT_STAT(irqs)) {
-		*r500_disp_int = RREG32(R_007EDC_DISP_INTERRUPT_STATUS);
-		if (G_007EDC_LB_D1_VBLANK_INTERRUPT(*r500_disp_int)) {
+		rdev->irq.stat_regs.r500.disp_int = RREG32(R_007EDC_DISP_INTERRUPT_STATUS);
+		if (G_007EDC_LB_D1_VBLANK_INTERRUPT(rdev->irq.stat_regs.r500.disp_int)) {
 			WREG32(R_006534_D1MODE_VBLANK_STATUS,
 				S_006534_D1MODE_VBLANK_ACK(1));
 		}
-		if (G_007EDC_LB_D2_VBLANK_INTERRUPT(*r500_disp_int)) {
+		if (G_007EDC_LB_D2_VBLANK_INTERRUPT(rdev->irq.stat_regs.r500.disp_int)) {
 			WREG32(R_006D34_D2MODE_VBLANK_STATUS,
 				S_006D34_D2MODE_VBLANK_ACK(1));
 		}
-		if (G_007EDC_DC_HOT_PLUG_DETECT1_INTERRUPT(*r500_disp_int)) {
+		if (G_007EDC_DC_HOT_PLUG_DETECT1_INTERRUPT(rdev->irq.stat_regs.r500.disp_int)) {
 			tmp = RREG32(R_007D08_DC_HOT_PLUG_DETECT1_INT_CONTROL);
 			tmp |= S_007D08_DC_HOT_PLUG_DETECT1_INT_ACK(1);
 			WREG32(R_007D08_DC_HOT_PLUG_DETECT1_INT_CONTROL, tmp);
 		}
-		if (G_007EDC_DC_HOT_PLUG_DETECT2_INTERRUPT(*r500_disp_int)) {
+		if (G_007EDC_DC_HOT_PLUG_DETECT2_INTERRUPT(rdev->irq.stat_regs.r500.disp_int)) {
 			tmp = RREG32(R_007D18_DC_HOT_PLUG_DETECT2_INT_CONTROL);
 			tmp |= S_007D18_DC_HOT_PLUG_DETECT2_INT_ACK(1);
 			WREG32(R_007D18_DC_HOT_PLUG_DETECT2_INT_CONTROL, tmp);
 		}
 	} else {
-		*r500_disp_int = 0;
+		rdev->irq.stat_regs.r500.disp_int = 0;
 	}
 
 	if (irqs) {
@@ -578,32 +630,30 @@ static inline uint32_t rs600_irq_ack(str
 
 void rs600_irq_disable(struct radeon_device *rdev)
 {
-	u32 tmp;
-
 	WREG32(R_000040_GEN_INT_CNTL, 0);
 	WREG32(R_006540_DxMODE_INT_MASK, 0);
 	/* Wait and acknowledge irq */
 	mdelay(1);
-	rs600_irq_ack(rdev, &tmp);
+	rs600_irq_ack(rdev);
 }
 
 int rs600_irq_process(struct radeon_device *rdev)
 {
-	uint32_t status, msi_rearm;
-	uint32_t r500_disp_int;
+	u32 status, msi_rearm;
 	bool queue_hotplug = false;
 
 	/* reset gui idle ack.  the status bit is broken */
 	rdev->irq.gui_idle_acked = false;
 
-	status = rs600_irq_ack(rdev, &r500_disp_int);
-	if (!status && !r500_disp_int) {
+	status = rs600_irq_ack(rdev);
+	if (!status && !rdev->irq.stat_regs.r500.disp_int) {
 		return IRQ_NONE;
 	}
-	while (status || r500_disp_int) {
+	while (status || rdev->irq.stat_regs.r500.disp_int) {
 		/* SW interrupt */
-		if (G_000044_SW_INT(status))
+		if (G_000044_SW_INT(status)) {
 			radeon_fence_process(rdev);
+		}
 		/* GUI idle */
 		if (G_000040_GUI_IDLE(status)) {
 			rdev->irq.gui_idle_acked = true;
@@ -611,30 +661,38 @@ int rs600_irq_process(struct radeon_devi
 			wake_up(&rdev->irq.idle_queue);
 		}
 		/* Vertical blank interrupts */
-		if (G_007EDC_LB_D1_VBLANK_INTERRUPT(r500_disp_int)) {
-			drm_handle_vblank(rdev->ddev, 0);
-			rdev->pm.vblank_sync = true;
-			wake_up(&rdev->irq.vblank_queue);
+		if (G_007EDC_LB_D1_VBLANK_INTERRUPT(rdev->irq.stat_regs.r500.disp_int)) {
+			if (rdev->irq.crtc_vblank_int[0]) {
+				drm_handle_vblank(rdev->ddev, 0);
+				rdev->pm.vblank_sync = true;
+				wake_up(&rdev->irq.vblank_queue);
+			}
+			if (rdev->irq.pflip[0])
+				radeon_crtc_handle_flip(rdev, 0);
 		}
-		if (G_007EDC_LB_D2_VBLANK_INTERRUPT(r500_disp_int)) {
-			drm_handle_vblank(rdev->ddev, 1);
-			rdev->pm.vblank_sync = true;
-			wake_up(&rdev->irq.vblank_queue);
+		if (G_007EDC_LB_D2_VBLANK_INTERRUPT(rdev->irq.stat_regs.r500.disp_int)) {
+			if (rdev->irq.crtc_vblank_int[1]) {
+				drm_handle_vblank(rdev->ddev, 1);
+				rdev->pm.vblank_sync = true;
+				wake_up(&rdev->irq.vblank_queue);
+			}
+			if (rdev->irq.pflip[1])
+				radeon_crtc_handle_flip(rdev, 1);
 		}
-		if (G_007EDC_DC_HOT_PLUG_DETECT1_INTERRUPT(r500_disp_int)) {
+		if (G_007EDC_DC_HOT_PLUG_DETECT1_INTERRUPT(rdev->irq.stat_regs.r500.disp_int)) {
 			queue_hotplug = true;
 			DRM_DEBUG("HPD1\n");
 		}
-		if (G_007EDC_DC_HOT_PLUG_DETECT2_INTERRUPT(r500_disp_int)) {
+		if (G_007EDC_DC_HOT_PLUG_DETECT2_INTERRUPT(rdev->irq.stat_regs.r500.disp_int)) {
 			queue_hotplug = true;
 			DRM_DEBUG("HPD2\n");
 		}
-		status = rs600_irq_ack(rdev, &r500_disp_int);
+		status = rs600_irq_ack(rdev);
 	}
 	/* reset gui idle ack.  the status bit is broken */
 	rdev->irq.gui_idle_acked = false;
 	if (queue_hotplug)
-		queue_work(rdev->wq, &rdev->hotplug_work);
+		schedule_work(&rdev->hotplug_work);
 	if (rdev->msi_enabled) {
 		switch (rdev->family) {
 		case CHIP_RS600:
@@ -693,7 +751,6 @@ void rs600_mc_init(struct radeon_device
 	rdev->mc.real_vram_size = RREG32(RADEON_CONFIG_MEMSIZE);
 	rdev->mc.mc_vram_size = rdev->mc.real_vram_size;
 	rdev->mc.visible_vram_size = rdev->mc.aper_size;
-	rdev->mc.active_vram_size = rdev->mc.visible_vram_size;
 	rdev->mc.igp_sideport_enabled = radeon_atombios_sideport_present(rdev);
 	base = RREG32_MC(R_000004_MC_FB_LOCATION);
 	base = G_000004_MC_FB_START(base) << 16;
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/rs690.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/rs690.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/rs690.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/rs690.c	2011-03-14 21:20:32.000000000 -0400
@@ -77,9 +77,9 @@ void rs690_pm_info(struct radeon_device
 		switch (crev) {
 		case 1:
 			tmp.full = dfixed_const(100);
-			rdev->pm.igp_sideport_mclk.full = dfixed_const(info->info.ulBootUpMemoryClock);
+			rdev->pm.igp_sideport_mclk.full = dfixed_const(le32_to_cpu(info->info.ulBootUpMemoryClock));
 			rdev->pm.igp_sideport_mclk.full = dfixed_div(rdev->pm.igp_sideport_mclk, tmp);
-			if (info->info.usK8MemoryClock)
+			if (le16_to_cpu(info->info.usK8MemoryClock))
 				rdev->pm.igp_system_mclk.full = dfixed_const(le16_to_cpu(info->info.usK8MemoryClock));
 			else if (rdev->clock.default_mclk) {
 				rdev->pm.igp_system_mclk.full = dfixed_const(rdev->clock.default_mclk);
@@ -91,16 +91,16 @@ void rs690_pm_info(struct radeon_device
 			break;
 		case 2:
 			tmp.full = dfixed_const(100);
-			rdev->pm.igp_sideport_mclk.full = dfixed_const(info->info_v2.ulBootUpSidePortClock);
+			rdev->pm.igp_sideport_mclk.full = dfixed_const(le32_to_cpu(info->info_v2.ulBootUpSidePortClock));
 			rdev->pm.igp_sideport_mclk.full = dfixed_div(rdev->pm.igp_sideport_mclk, tmp);
-			if (info->info_v2.ulBootUpUMAClock)
-				rdev->pm.igp_system_mclk.full = dfixed_const(info->info_v2.ulBootUpUMAClock);
+			if (le32_to_cpu(info->info_v2.ulBootUpUMAClock))
+				rdev->pm.igp_system_mclk.full = dfixed_const(le32_to_cpu(info->info_v2.ulBootUpUMAClock));
 			else if (rdev->clock.default_mclk)
 				rdev->pm.igp_system_mclk.full = dfixed_const(rdev->clock.default_mclk);
 			else
 				rdev->pm.igp_system_mclk.full = dfixed_const(66700);
 			rdev->pm.igp_system_mclk.full = dfixed_div(rdev->pm.igp_system_mclk, tmp);
-			rdev->pm.igp_ht_link_clk.full = dfixed_const(info->info_v2.ulHTLinkFreq);
+			rdev->pm.igp_ht_link_clk.full = dfixed_const(le32_to_cpu(info->info_v2.ulHTLinkFreq));
 			rdev->pm.igp_ht_link_clk.full = dfixed_div(rdev->pm.igp_ht_link_clk, tmp);
 			rdev->pm.igp_ht_link_width.full = dfixed_const(le16_to_cpu(info->info_v2.usMinHTLinkWidth));
 			break;
@@ -157,7 +157,6 @@ void rs690_mc_init(struct radeon_device
 	rdev->mc.aper_base = pci_resource_start(rdev->pdev, 0);
 	rdev->mc.aper_size = pci_resource_len(rdev->pdev, 0);
 	rdev->mc.visible_vram_size = rdev->mc.aper_size;
-	rdev->mc.active_vram_size = rdev->mc.visible_vram_size;
 	base = RREG32_MC(R_000100_MCCFG_FB_LOCATION);
 	base = G_000100_MC_FB_START(base) << 16;
 	rdev->mc.igp_sideport_enabled = radeon_atombios_sideport_present(rdev);
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/rv515.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/rv515.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/rv515.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/rv515.c	2011-03-14 21:20:32.000000000 -0400
@@ -69,13 +69,13 @@ void rv515_ring_start(struct radeon_devi
 			  ISYNC_CPSCRATCH_IDLEGUI);
 	radeon_ring_write(rdev, PACKET0(WAIT_UNTIL, 0));
 	radeon_ring_write(rdev, WAIT_2D_IDLECLEAN | WAIT_3D_IDLECLEAN);
-	radeon_ring_write(rdev, PACKET0(0x170C, 0));
-	radeon_ring_write(rdev, 1 << 31);
+	radeon_ring_write(rdev, PACKET0(R300_DST_PIPE_CONFIG, 0));
+	radeon_ring_write(rdev, R300_PIPE_AUTO_CONFIG);
 	radeon_ring_write(rdev, PACKET0(GB_SELECT, 0));
 	radeon_ring_write(rdev, 0);
 	radeon_ring_write(rdev, PACKET0(GB_ENABLE, 0));
 	radeon_ring_write(rdev, 0);
-	radeon_ring_write(rdev, PACKET0(0x42C8, 0));
+	radeon_ring_write(rdev, PACKET0(R500_SU_REG_DEST, 0));
 	radeon_ring_write(rdev, (1 << rdev->num_gb_pipes) - 1);
 	radeon_ring_write(rdev, PACKET0(VAP_INDEX_OFFSET, 0));
 	radeon_ring_write(rdev, 0);
@@ -153,8 +153,8 @@ void rv515_gpu_init(struct radeon_device
 	}
 	rv515_vga_render_disable(rdev);
 	r420_pipes_init(rdev);
-	gb_pipe_select = RREG32(0x402C);
-	tmp = RREG32(0x170C);
+	gb_pipe_select = RREG32(R400_GB_PIPE_SELECT);
+	tmp = RREG32(R300_DST_PIPE_CONFIG);
 	pipe_select_current = (tmp >> 2) & 3;
 	tmp = (1 << pipe_select_current) |
 	      (((gb_pipe_select >> 8) & 0xF) << 4);
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/rv770.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/rv770.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/rv770.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/rv770.c	2011-03-14 21:20:32.000000000 -0400
@@ -41,20 +41,60 @@
 
 static void rv770_gpu_init(struct radeon_device *rdev);
 void rv770_fini(struct radeon_device *rdev);
+static void rv770_pcie_gen2_enable(struct radeon_device *rdev);
+
+u32 rv770_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base)
+{
+	struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
+	u32 tmp = RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset);
+
+	/* Lock the graphics update lock */
+	tmp |= AVIVO_D1GRPH_UPDATE_LOCK;
+	WREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset, tmp);
+
+	/* update the scanout addresses */
+	if (radeon_crtc->crtc_id) {
+		WREG32(D2GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, upper_32_bits(crtc_base));
+		WREG32(D2GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, upper_32_bits(crtc_base));
+	} else {
+		WREG32(D1GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, upper_32_bits(crtc_base));
+		WREG32(D1GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, upper_32_bits(crtc_base));
+	}
+	WREG32(D1GRPH_SECONDARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset,
+	       (u32)crtc_base);
+	WREG32(D1GRPH_PRIMARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset,
+	       (u32)crtc_base);
+
+	/* Wait for update_pending to go high. */
+	while (!(RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset) & AVIVO_D1GRPH_SURFACE_UPDATE_PENDING));
+	DRM_DEBUG("Update pending now high. Unlocking vupdate_lock.\n");
+
+	/* Unlock the lock, so double-buffering can take place inside vblank */
+	tmp &= ~AVIVO_D1GRPH_UPDATE_LOCK;
+	WREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset, tmp);
+
+	/* Return current update_pending status: */
+	return RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset) & AVIVO_D1GRPH_SURFACE_UPDATE_PENDING;
+}
 
 /* get temperature in millidegrees */
-u32 rv770_get_temp(struct radeon_device *rdev)
+int rv770_get_temp(struct radeon_device *rdev)
 {
 	u32 temp = (RREG32(CG_MULT_THERMAL_STATUS) & ASIC_T_MASK) >>
 		ASIC_T_SHIFT;
-	u32 actual_temp = 0;
+	int actual_temp;
 
-	if ((temp >> 9) & 1)
-		actual_temp = 0;
-	else
-		actual_temp = (temp >> 1) & 0xff;
+	if (temp & 0x400)
+		actual_temp = -256;
+	else if (temp & 0x200)
+		actual_temp = 255;
+	else if (temp & 0x100) {
+		actual_temp = temp & 0x1ff;
+		actual_temp |= ~0x1ff;
+	} else
+		actual_temp = temp & 0xff;
 
-	return actual_temp * 1000;
+	return (actual_temp * 1000) / 2;
 }
 
 void rv770_pm_misc(struct radeon_device *rdev)
@@ -267,7 +307,7 @@ static void rv770_mc_program(struct rade
  */
 void r700_cp_stop(struct radeon_device *rdev)
 {
-	rdev->mc.active_vram_size = rdev->mc.visible_vram_size;
+	radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size);
 	WREG32(CP_ME_CNTL, (CP_ME_HALT | CP_PFP_HALT));
 	WREG32(SCRATCH_UMSK, 0);
 }
@@ -281,7 +321,11 @@ static int rv770_cp_load_microcode(struc
 		return -EINVAL;
 
 	r700_cp_stop(rdev);
-	WREG32(CP_RB_CNTL, RB_NO_UPDATE | (15 << 8) | (3 << 0));
+	WREG32(CP_RB_CNTL,
+#ifdef __BIG_ENDIAN
+	       BUF_SWAP_32BIT |
+#endif
+	       RB_NO_UPDATE | RB_BLKSZ(15) | RB_BUFSZ(3));
 
 	/* Reset cp */
 	WREG32(GRBM_SOFT_RESET, SOFT_RESET_CP);
@@ -489,6 +533,49 @@ static u32 r700_get_tile_pipe_to_backend
 	return backend_map;
 }
 
+static void rv770_program_channel_remap(struct radeon_device *rdev)
+{
+	u32 tcp_chan_steer, mc_shared_chremap, tmp;
+	bool force_no_swizzle;
+
+	switch (rdev->family) {
+	case CHIP_RV770:
+	case CHIP_RV730:
+		force_no_swizzle = false;
+		break;
+	case CHIP_RV710:
+	case CHIP_RV740:
+	default:
+		force_no_swizzle = true;
+		break;
+	}
+
+	tmp = RREG32(MC_SHARED_CHMAP);
+	switch ((tmp & NOOFCHAN_MASK) >> NOOFCHAN_SHIFT) {
+	case 0:
+	case 1:
+	default:
+		/* default mapping */
+		mc_shared_chremap = 0x00fac688;
+		break;
+	case 2:
+	case 3:
+		if (force_no_swizzle)
+			mc_shared_chremap = 0x00fac688;
+		else
+			mc_shared_chremap = 0x00bbc298;
+		break;
+	}
+
+	if (rdev->family == CHIP_RV740)
+		tcp_chan_steer = 0x00ef2a60;
+	else
+		tcp_chan_steer = 0x00fac688;
+
+	WREG32(TCP_CHAN_STEER, tcp_chan_steer);
+	WREG32(MC_SHARED_CHREMAP, mc_shared_chremap);
+}
+
 static void rv770_gpu_init(struct radeon_device *rdev)
 {
 	int i, j, num_qd_pipes;
@@ -688,6 +775,8 @@ static void rv770_gpu_init(struct radeon
 	WREG32(DCP_TILING_CONFIG, (gb_tiling_config & 0xffff));
 	WREG32(HDP_TILING_CONFIG, (gb_tiling_config & 0xffff));
 
+	rv770_program_channel_remap(rdev);
+
 	WREG32(CC_RB_BACKEND_DISABLE,      cc_rb_backend_disable);
 	WREG32(CC_GC_SHADER_PIPE_CONFIG,   cc_gc_shader_pipe_config);
 	WREG32(GC_USER_SHADER_PIPE_CONFIG, cc_gc_shader_pipe_config);
@@ -956,6 +1045,45 @@ static void rv770_vram_scratch_fini(stru
 	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;
+
+	if (mc->mc_vram_size > 0xE0000000) {
+		/* leave room for at least 512M GTT */
+		dev_warn(rdev->dev, "limiting VRAM\n");
+		mc->real_vram_size = 0xE0000000;
+		mc->mc_vram_size = 0xE0000000;
+	}
+	if (rdev->flags & RADEON_IS_AGP) {
+		size_bf = mc->gtt_start;
+		size_af = 0xFFFFFFFF - mc->gtt_end + 1;
+		if (size_bf > size_af) {
+			if (mc->mc_vram_size > size_bf) {
+				dev_warn(rdev->dev, "limiting VRAM\n");
+				mc->real_vram_size = size_bf;
+				mc->mc_vram_size = size_bf;
+			}
+			mc->vram_start = mc->gtt_start - mc->mc_vram_size;
+		} else {
+			if (mc->mc_vram_size > size_af) {
+				dev_warn(rdev->dev, "limiting VRAM\n");
+				mc->real_vram_size = size_af;
+				mc->mc_vram_size = size_af;
+			}
+			mc->vram_start = mc->gtt_end;
+		}
+		mc->vram_end = mc->vram_start + mc->mc_vram_size - 1;
+		dev_info(rdev->dev, "VRAM: %lluM 0x%08llX - 0x%08llX (%lluM used)\n",
+				mc->mc_vram_size >> 20, mc->vram_start,
+				mc->vram_end, mc->real_vram_size >> 20);
+	} else {
+		radeon_vram_location(rdev, &rdev->mc, 0);
+		rdev->mc.gtt_base_align = 0;
+		radeon_gtt_location(rdev, mc);
+	}
+}
+
 int rv770_mc_init(struct radeon_device *rdev)
 {
 	u32 tmp;
@@ -995,8 +1123,7 @@ int rv770_mc_init(struct radeon_device *
 	rdev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE);
 	rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE);
 	rdev->mc.visible_vram_size = rdev->mc.aper_size;
-	rdev->mc.active_vram_size = rdev->mc.visible_vram_size;
-	r600_vram_gtt_location(rdev, &rdev->mc);
+	r700_vram_gtt_location(rdev, &rdev->mc);
 	radeon_update_bandwidth_info(rdev);
 
 	return 0;
@@ -1006,6 +1133,9 @@ static int rv770_startup(struct radeon_d
 {
 	int r;
 
+	/* enable pcie gen2 link */
+	rv770_pcie_gen2_enable(rdev);
+
 	if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw) {
 		r = r600_init_microcode(rdev);
 		if (r) {
@@ -1146,7 +1276,7 @@ int rv770_init(struct radeon_device *rde
 	if (r)
 		return r;
 	/* Post card if necessary */
-	if (!r600_card_posted(rdev)) {
+	if (!radeon_card_posted(rdev)) {
 		if (!rdev->bios) {
 			dev_err(rdev->dev, "Card not posted and no BIOS - ignoring\n");
 			return -EINVAL;
@@ -1244,3 +1374,78 @@ void rv770_fini(struct radeon_device *rd
 	rdev->bios = NULL;
 	radeon_dummy_page_fini(rdev);
 }
+
+static void rv770_pcie_gen2_enable(struct radeon_device *rdev)
+{
+	u32 link_width_cntl, lanes, speed_cntl, tmp;
+	u16 link_cntl2;
+
+	if (radeon_pcie_gen2 == 0)
+		return;
+
+	if (rdev->flags & RADEON_IS_IGP)
+		return;
+
+	if (!(rdev->flags & RADEON_IS_PCIE))
+		return;
+
+	/* x2 cards have a special sequence */
+	if (ASIC_IS_X2(rdev))
+		return;
+
+	/* advertise upconfig capability */
+	link_width_cntl = RREG32_PCIE_P(PCIE_LC_LINK_WIDTH_CNTL);
+	link_width_cntl &= ~LC_UPCONFIGURE_DIS;
+	WREG32_PCIE_P(PCIE_LC_LINK_WIDTH_CNTL, link_width_cntl);
+	link_width_cntl = RREG32_PCIE_P(PCIE_LC_LINK_WIDTH_CNTL);
+	if (link_width_cntl & LC_RENEGOTIATION_SUPPORT) {
+		lanes = (link_width_cntl & LC_LINK_WIDTH_RD_MASK) >> LC_LINK_WIDTH_RD_SHIFT;
+		link_width_cntl &= ~(LC_LINK_WIDTH_MASK |
+				     LC_RECONFIG_ARC_MISSING_ESCAPE);
+		link_width_cntl |= lanes | LC_RECONFIG_NOW |
+			LC_RENEGOTIATE_EN | LC_UPCONFIGURE_SUPPORT;
+		WREG32_PCIE_P(PCIE_LC_LINK_WIDTH_CNTL, link_width_cntl);
+	} else {
+		link_width_cntl |= LC_UPCONFIGURE_DIS;
+		WREG32_PCIE_P(PCIE_LC_LINK_WIDTH_CNTL, link_width_cntl);
+	}
+
+	speed_cntl = RREG32_PCIE_P(PCIE_LC_SPEED_CNTL);
+	if ((speed_cntl & LC_OTHER_SIDE_EVER_SENT_GEN2) &&
+	    (speed_cntl & LC_OTHER_SIDE_SUPPORTS_GEN2)) {
+
+		tmp = RREG32(0x541c);
+		WREG32(0x541c, tmp | 0x8);
+		WREG32(MM_CFGREGS_CNTL, MM_WR_TO_CFG_EN);
+		link_cntl2 = RREG16(0x4088);
+		link_cntl2 &= ~TARGET_LINK_SPEED_MASK;
+		link_cntl2 |= 0x2;
+		WREG16(0x4088, link_cntl2);
+		WREG32(MM_CFGREGS_CNTL, 0);
+
+		speed_cntl = RREG32_PCIE_P(PCIE_LC_SPEED_CNTL);
+		speed_cntl &= ~LC_TARGET_LINK_SPEED_OVERRIDE_EN;
+		WREG32_PCIE_P(PCIE_LC_SPEED_CNTL, speed_cntl);
+
+		speed_cntl = RREG32_PCIE_P(PCIE_LC_SPEED_CNTL);
+		speed_cntl |= LC_CLR_FAILED_SPD_CHANGE_CNT;
+		WREG32_PCIE_P(PCIE_LC_SPEED_CNTL, speed_cntl);
+
+		speed_cntl = RREG32_PCIE_P(PCIE_LC_SPEED_CNTL);
+		speed_cntl &= ~LC_CLR_FAILED_SPD_CHANGE_CNT;
+		WREG32_PCIE_P(PCIE_LC_SPEED_CNTL, speed_cntl);
+
+		speed_cntl = RREG32_PCIE_P(PCIE_LC_SPEED_CNTL);
+		speed_cntl |= LC_GEN2_EN_STRAP;
+		WREG32_PCIE_P(PCIE_LC_SPEED_CNTL, speed_cntl);
+
+	} else {
+		link_width_cntl = RREG32_PCIE_P(PCIE_LC_LINK_WIDTH_CNTL);
+		/* XXX: only disable it if gen1 bridge vendor == 0x111d or 0x1106 */
+		if (1)
+			link_width_cntl |= LC_UPCONFIGURE_DIS;
+		else
+			link_width_cntl &= ~LC_UPCONFIGURE_DIS;
+		WREG32_PCIE_P(PCIE_LC_LINK_WIDTH_CNTL, link_width_cntl);
+	}
+}
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/rv770d.h linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/rv770d.h
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/radeon/rv770d.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/radeon/rv770d.h	2011-03-14 21:20:32.000000000 -0400
@@ -76,10 +76,10 @@
 #define		ROQ_IB1_START(x)				((x) << 0)
 #define		ROQ_IB2_START(x)				((x) << 8)
 #define	CP_RB_CNTL					0xC104
-#define		RB_BUFSZ(x)					((x)<<0)
-#define		RB_BLKSZ(x)					((x)<<8)
-#define		RB_NO_UPDATE					(1<<27)
-#define		RB_RPTR_WR_ENA					(1<<31)
+#define		RB_BUFSZ(x)					((x) << 0)
+#define		RB_BLKSZ(x)					((x) << 8)
+#define		RB_NO_UPDATE					(1 << 27)
+#define		RB_RPTR_WR_ENA					(1 << 31)
 #define		BUF_SWAP_32BIT					(2 << 16)
 #define	CP_RB_RPTR					0x8700
 #define	CP_RB_RPTR_ADDR					0xC10C
@@ -138,6 +138,7 @@
 #define MC_SHARED_CHMAP						0x2004
 #define		NOOFCHAN_SHIFT					12
 #define		NOOFCHAN_MASK					0x00003000
+#define MC_SHARED_CHREMAP					0x2008
 
 #define	MC_ARB_RAMCFG					0x2760
 #define		NOOFBANK_SHIFT					0
@@ -303,6 +304,7 @@
 #define		BILINEAR_PRECISION_8_BIT			(1 << 31)
 
 #define	TCP_CNTL					0x9610
+#define	TCP_CHAN_STEER					0x9614
 
 #define	VGT_CACHE_INVALIDATION				0x88C4
 #define		CACHE_INVALIDATION(x)				((x)<<0)
@@ -351,4 +353,49 @@
 
 #define	SRBM_STATUS				        0x0E50
 
+#define D1GRPH_PRIMARY_SURFACE_ADDRESS                    0x6110
+#define D1GRPH_PRIMARY_SURFACE_ADDRESS_HIGH               0x6914
+#define D2GRPH_PRIMARY_SURFACE_ADDRESS_HIGH               0x6114
+#define D1GRPH_SECONDARY_SURFACE_ADDRESS                  0x6118
+#define D1GRPH_SECONDARY_SURFACE_ADDRESS_HIGH             0x691c
+#define D2GRPH_SECONDARY_SURFACE_ADDRESS_HIGH             0x611c
+
+/* PCIE link stuff */
+#define PCIE_LC_TRAINING_CNTL                             0xa1 /* PCIE_P */
+#define PCIE_LC_LINK_WIDTH_CNTL                           0xa2 /* PCIE_P */
+#       define LC_LINK_WIDTH_SHIFT                        0
+#       define LC_LINK_WIDTH_MASK                         0x7
+#       define LC_LINK_WIDTH_X0                           0
+#       define LC_LINK_WIDTH_X1                           1
+#       define LC_LINK_WIDTH_X2                           2
+#       define LC_LINK_WIDTH_X4                           3
+#       define LC_LINK_WIDTH_X8                           4
+#       define LC_LINK_WIDTH_X16                          6
+#       define LC_LINK_WIDTH_RD_SHIFT                     4
+#       define LC_LINK_WIDTH_RD_MASK                      0x70
+#       define LC_RECONFIG_ARC_MISSING_ESCAPE             (1 << 7)
+#       define LC_RECONFIG_NOW                            (1 << 8)
+#       define LC_RENEGOTIATION_SUPPORT                   (1 << 9)
+#       define LC_RENEGOTIATE_EN                          (1 << 10)
+#       define LC_SHORT_RECONFIG_EN                       (1 << 11)
+#       define LC_UPCONFIGURE_SUPPORT                     (1 << 12)
+#       define LC_UPCONFIGURE_DIS                         (1 << 13)
+#define PCIE_LC_SPEED_CNTL                                0xa4 /* PCIE_P */
+#       define LC_GEN2_EN_STRAP                           (1 << 0)
+#       define LC_TARGET_LINK_SPEED_OVERRIDE_EN           (1 << 1)
+#       define LC_FORCE_EN_HW_SPEED_CHANGE                (1 << 5)
+#       define LC_FORCE_DIS_HW_SPEED_CHANGE               (1 << 6)
+#       define LC_SPEED_CHANGE_ATTEMPTS_ALLOWED_MASK      (0x3 << 8)
+#       define LC_SPEED_CHANGE_ATTEMPTS_ALLOWED_SHIFT     3
+#       define LC_CURRENT_DATA_RATE                       (1 << 11)
+#       define LC_VOLTAGE_TIMER_SEL_MASK                  (0xf << 14)
+#       define LC_CLR_FAILED_SPD_CHANGE_CNT               (1 << 21)
+#       define LC_OTHER_SIDE_EVER_SENT_GEN2               (1 << 23)
+#       define LC_OTHER_SIDE_SUPPORTS_GEN2                (1 << 24)
+#define MM_CFGREGS_CNTL                                   0x544c
+#       define MM_WR_TO_CFG_EN                            (1 << 3)
+#define LINK_CNTL2                                        0x88 /* F0 */
+#       define TARGET_LINK_SPEED_MASK                     (0xf << 0)
+#       define SELECTABLE_DEEMPHASIS                      (1 << 6)
+
 #endif
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/ttm/ttm_bo.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/ttm/ttm_bo.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/ttm/ttm_bo.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/ttm/ttm_bo.c	2011-03-14 21:20:32.000000000 -0400
@@ -169,7 +169,7 @@ int ttm_bo_wait_unreserved(struct ttm_bu
 }
 EXPORT_SYMBOL(ttm_bo_wait_unreserved);
 
-static void ttm_bo_add_to_lru(struct ttm_buffer_object *bo)
+void ttm_bo_add_to_lru(struct ttm_buffer_object *bo)
 {
 	struct ttm_bo_device *bdev = bo->bdev;
 	struct ttm_mem_type_manager *man;
@@ -191,11 +191,7 @@ static void ttm_bo_add_to_lru(struct ttm
 	}
 }
 
-/**
- * Call with the lru_lock held.
- */
-
-static int ttm_bo_del_from_lru(struct ttm_buffer_object *bo)
+int ttm_bo_del_from_lru(struct ttm_buffer_object *bo)
 {
 	int put_count = 0;
 
@@ -227,9 +223,18 @@ int ttm_bo_reserve_locked(struct ttm_buf
 		/**
 		 * Deadlock avoidance for multi-bo reserving.
 		 */
-		if (use_sequence && bo->seq_valid &&
-			(sequence - bo->val_seq < (1 << 31))) {
-			return -EAGAIN;
+		if (use_sequence && bo->seq_valid) {
+			/**
+			 * We've already reserved this one.
+			 */
+			if (unlikely(sequence == bo->val_seq))
+				return -EDEADLK;
+			/**
+			 * Already reserved by a thread that will not back
+			 * off for us. We need to back off.
+			 */
+			if (unlikely(sequence - bo->val_seq < (1 << 31)))
+				return -EAGAIN;
 		}
 
 		if (no_wait)
@@ -267,6 +272,13 @@ static void ttm_bo_ref_bug(struct kref *
 	BUG();
 }
 
+void ttm_bo_list_ref_sub(struct ttm_buffer_object *bo, int count,
+			 bool never_free)
+{
+	kref_sub(&bo->list_kref, count,
+		 (never_free) ? ttm_bo_ref_bug : ttm_bo_release_list);
+}
+
 int ttm_bo_reserve(struct ttm_buffer_object *bo,
 		   bool interruptible,
 		   bool no_wait, bool use_sequence, uint32_t sequence)
@@ -282,20 +294,24 @@ int ttm_bo_reserve(struct ttm_buffer_obj
 		put_count = ttm_bo_del_from_lru(bo);
 	spin_unlock(&glob->lru_lock);
 
-	while (put_count--)
-		kref_put(&bo->list_kref, ttm_bo_ref_bug);
+	ttm_bo_list_ref_sub(bo, put_count, true);
 
 	return ret;
 }
 
+void ttm_bo_unreserve_locked(struct ttm_buffer_object *bo)
+{
+	ttm_bo_add_to_lru(bo);
+	atomic_set(&bo->reserved, 0);
+	wake_up_all(&bo->event_queue);
+}
+
 void ttm_bo_unreserve(struct ttm_buffer_object *bo)
 {
 	struct ttm_bo_global *glob = bo->glob;
 
 	spin_lock(&glob->lru_lock);
-	ttm_bo_add_to_lru(bo);
-	atomic_set(&bo->reserved, 0);
-	wake_up_all(&bo->event_queue);
+	ttm_bo_unreserve_locked(bo);
 	spin_unlock(&glob->lru_lock);
 }
 EXPORT_SYMBOL(ttm_bo_unreserve);
@@ -362,8 +378,13 @@ static int ttm_bo_handle_move_mem(struct
 	int ret = 0;
 
 	if (old_is_pci || new_is_pci ||
-	    ((mem->placement & bo->mem.placement & TTM_PL_MASK_CACHING) == 0))
-		ttm_bo_unmap_virtual(bo);
+	    ((mem->placement & bo->mem.placement & TTM_PL_MASK_CACHING) == 0)) {
+		ret = ttm_mem_io_lock(old_man, true);
+		if (unlikely(ret != 0))
+			goto out_err;
+		ttm_bo_unmap_virtual_locked(bo);
+		ttm_mem_io_unlock(old_man);
+	}
 
 	/*
 	 * Create and bind a ttm if required.
@@ -416,11 +437,9 @@ moved:
 	}
 
 	if (bo->mem.mm_node) {
-		spin_lock(&bo->lock);
 		bo->offset = (bo->mem.start << PAGE_SHIFT) +
 		    bdev->man[bo->mem.mem_type].gpu_offset;
 		bo->cur_placement = bo->mem.placement;
-		spin_unlock(&bo->lock);
 	} else
 		bo->offset = 0;
 
@@ -452,7 +471,6 @@ static void ttm_bo_cleanup_memtype_use(s
 		ttm_tt_destroy(bo->ttm);
 		bo->ttm = NULL;
 	}
-
 	ttm_bo_mem_put(bo, &bo->mem);
 
 	atomic_set(&bo->reserved, 0);
@@ -474,14 +492,14 @@ static void ttm_bo_cleanup_refs_or_queue
 	int put_count;
 	int ret;
 
-	spin_lock(&bo->lock);
+	spin_lock(&bdev->fence_lock);
 	(void) ttm_bo_wait(bo, false, false, true);
 	if (!bo->sync_obj) {
 
 		spin_lock(&glob->lru_lock);
 
 		/**
-		 * Lock inversion between bo::reserve and bo::lock here,
+		 * Lock inversion between bo:reserve and bdev::fence_lock here,
 		 * but that's OK, since we're only trylocking.
 		 */
 
@@ -490,14 +508,13 @@ static void ttm_bo_cleanup_refs_or_queue
 		if (unlikely(ret == -EBUSY))
 			goto queue;
 
-		spin_unlock(&bo->lock);
+		spin_unlock(&bdev->fence_lock);
 		put_count = ttm_bo_del_from_lru(bo);
 
 		spin_unlock(&glob->lru_lock);
 		ttm_bo_cleanup_memtype_use(bo);
 
-		while (put_count--)
-			kref_put(&bo->list_kref, ttm_bo_ref_bug);
+		ttm_bo_list_ref_sub(bo, put_count, true);
 
 		return;
 	} else {
@@ -512,7 +529,7 @@ queue:
 	kref_get(&bo->list_kref);
 	list_add_tail(&bo->ddestroy, &bdev->ddestroy);
 	spin_unlock(&glob->lru_lock);
-	spin_unlock(&bo->lock);
+	spin_unlock(&bdev->fence_lock);
 
 	if (sync_obj) {
 		driver->sync_obj_flush(sync_obj, sync_obj_arg);
@@ -537,14 +554,15 @@ static int ttm_bo_cleanup_refs(struct tt
 			       bool no_wait_reserve,
 			       bool no_wait_gpu)
 {
+	struct ttm_bo_device *bdev = bo->bdev;
 	struct ttm_bo_global *glob = bo->glob;
 	int put_count;
 	int ret = 0;
 
 retry:
-	spin_lock(&bo->lock);
+	spin_lock(&bdev->fence_lock);
 	ret = ttm_bo_wait(bo, false, interruptible, no_wait_gpu);
-	spin_unlock(&bo->lock);
+	spin_unlock(&bdev->fence_lock);
 
 	if (unlikely(ret != 0))
 		return ret;
@@ -580,8 +598,7 @@ retry:
 	spin_unlock(&glob->lru_lock);
 	ttm_bo_cleanup_memtype_use(bo);
 
-	while (put_count--)
-		kref_put(&bo->list_kref, ttm_bo_ref_bug);
+	ttm_bo_list_ref_sub(bo, put_count, true);
 
 	return 0;
 }
@@ -652,6 +669,7 @@ static void ttm_bo_release(struct kref *
 	struct ttm_buffer_object *bo =
 	    container_of(kref, struct ttm_buffer_object, kref);
 	struct ttm_bo_device *bdev = bo->bdev;
+	struct ttm_mem_type_manager *man = &bdev->man[bo->mem.mem_type];
 
 	if (likely(bo->vm_node != NULL)) {
 		rb_erase(&bo->vm_rb, &bdev->addr_space_rb);
@@ -659,6 +677,9 @@ static void ttm_bo_release(struct kref *
 		bo->vm_node = NULL;
 	}
 	write_unlock(&bdev->vm_lock);
+	ttm_mem_io_lock(man, false);
+	ttm_mem_io_free_vm(bo);
+	ttm_mem_io_unlock(man);
 	ttm_bo_cleanup_refs_or_queue(bo);
 	kref_put(&bo->list_kref, ttm_bo_release_list);
 	write_lock(&bdev->vm_lock);
@@ -698,9 +719,9 @@ static int ttm_bo_evict(struct ttm_buffe
 	struct ttm_placement placement;
 	int ret = 0;
 
-	spin_lock(&bo->lock);
+	spin_lock(&bdev->fence_lock);
 	ret = ttm_bo_wait(bo, false, interruptible, no_wait_gpu);
-	spin_unlock(&bo->lock);
+	spin_unlock(&bdev->fence_lock);
 
 	if (unlikely(ret != 0)) {
 		if (ret != -ERESTARTSYS) {
@@ -715,7 +736,8 @@ static int ttm_bo_evict(struct ttm_buffe
 
 	evict_mem = bo->mem;
 	evict_mem.mm_node = NULL;
-	evict_mem.bus.io_reserved = false;
+	evict_mem.bus.io_reserved_vm = false;
+	evict_mem.bus.io_reserved_count = 0;
 
 	placement.fpfn = 0;
 	placement.lpfn = 0;
@@ -802,8 +824,7 @@ retry:
 
 	BUG_ON(ret != 0);
 
-	while (put_count--)
-		kref_put(&bo->list_kref, ttm_bo_ref_bug);
+	ttm_bo_list_ref_sub(bo, put_count, true);
 
 	ret = ttm_bo_evict(bo, interruptible, no_wait_reserve, no_wait_gpu);
 	ttm_bo_unreserve(bo);
@@ -1036,6 +1057,7 @@ int ttm_bo_move_buffer(struct ttm_buffer
 {
 	int ret = 0;
 	struct ttm_mem_reg mem;
+	struct ttm_bo_device *bdev = bo->bdev;
 
 	BUG_ON(!atomic_read(&bo->reserved));
 
@@ -1044,15 +1066,16 @@ int ttm_bo_move_buffer(struct ttm_buffer
 	 * Have the driver move function wait for idle when necessary,
 	 * instead of doing it here.
 	 */
-	spin_lock(&bo->lock);
+	spin_lock(&bdev->fence_lock);
 	ret = ttm_bo_wait(bo, false, interruptible, no_wait_gpu);
-	spin_unlock(&bo->lock);
+	spin_unlock(&bdev->fence_lock);
 	if (ret)
 		return ret;
 	mem.num_pages = bo->num_pages;
 	mem.size = mem.num_pages << PAGE_SHIFT;
 	mem.page_alignment = bo->mem.page_alignment;
-	mem.bus.io_reserved = false;
+	mem.bus.io_reserved_vm = false;
+	mem.bus.io_reserved_count = 0;
 	/*
 	 * Determine where to move the buffer.
 	 */
@@ -1163,7 +1186,6 @@ int ttm_bo_init(struct ttm_bo_device *bd
 	}
 	bo->destroy = destroy;
 
-	spin_lock_init(&bo->lock);
 	kref_init(&bo->kref);
 	kref_init(&bo->list_kref);
 	atomic_set(&bo->cpu_writers, 0);
@@ -1172,6 +1194,7 @@ int ttm_bo_init(struct ttm_bo_device *bd
 	INIT_LIST_HEAD(&bo->lru);
 	INIT_LIST_HEAD(&bo->ddestroy);
 	INIT_LIST_HEAD(&bo->swap);
+	INIT_LIST_HEAD(&bo->io_reserve_lru);
 	bo->bdev = bdev;
 	bo->glob = bdev->glob;
 	bo->type = type;
@@ -1181,7 +1204,8 @@ int ttm_bo_init(struct ttm_bo_device *bd
 	bo->mem.num_pages = bo->num_pages;
 	bo->mem.mm_node = NULL;
 	bo->mem.page_alignment = page_alignment;
-	bo->mem.bus.io_reserved = false;
+	bo->mem.bus.io_reserved_vm = false;
+	bo->mem.bus.io_reserved_count = 0;
 	bo->buffer_start = buffer_start & PAGE_MASK;
 	bo->priv_flags = 0;
 	bo->mem.placement = (TTM_PL_FLAG_SYSTEM | TTM_PL_FLAG_CACHED);
@@ -1355,6 +1379,10 @@ int ttm_bo_init_mm(struct ttm_bo_device
 	BUG_ON(type >= TTM_NUM_MEM_TYPES);
 	man = &bdev->man[type];
 	BUG_ON(man->has_type);
+	man->io_reserve_fastpath = true;
+	man->use_io_reserve_lru = false;
+	mutex_init(&man->io_reserve_mutex);
+	INIT_LIST_HEAD(&man->io_reserve_lru);
 
 	ret = bdev->driver->init_mem_type(bdev, type, man);
 	if (ret)
@@ -1472,8 +1500,7 @@ int ttm_bo_device_release(struct ttm_bo_
 	list_del(&bdev->device_list);
 	mutex_unlock(&glob->device_list_mutex);
 
-	if (!cancel_delayed_work(&bdev->wq))
-		flush_scheduled_work();
+	cancel_delayed_work_sync(&bdev->wq);
 
 	while (ttm_bo_delayed_delete(bdev, true))
 		;
@@ -1527,7 +1554,8 @@ int ttm_bo_device_init(struct ttm_bo_dev
 	bdev->dev_mapping = NULL;
 	bdev->glob = glob;
 	bdev->need_dma32 = need_dma32;
-
+	bdev->val_seq = 0;
+	spin_lock_init(&bdev->fence_lock);
 	mutex_lock(&glob->device_list_mutex);
 	list_add_tail(&bdev->device_list, &glob->device_list);
 	mutex_unlock(&glob->device_list_mutex);
@@ -1561,7 +1589,7 @@ bool ttm_mem_reg_is_pci(struct ttm_bo_de
 	return true;
 }
 
-void ttm_bo_unmap_virtual(struct ttm_buffer_object *bo)
+void ttm_bo_unmap_virtual_locked(struct ttm_buffer_object *bo)
 {
 	struct ttm_bo_device *bdev = bo->bdev;
 	loff_t offset = (loff_t) bo->addr_space_offset;
@@ -1570,8 +1598,20 @@ void ttm_bo_unmap_virtual(struct ttm_buf
 	if (!bdev->dev_mapping)
 		return;
 	unmap_mapping_range(bdev->dev_mapping, offset, holelen, 1);
-	ttm_mem_io_free(bdev, &bo->mem);
+	ttm_mem_io_free_vm(bo);
 }
+
+void ttm_bo_unmap_virtual(struct ttm_buffer_object *bo)
+{
+	struct ttm_bo_device *bdev = bo->bdev;
+	struct ttm_mem_type_manager *man = &bdev->man[bo->mem.mem_type];
+
+	ttm_mem_io_lock(man, false);
+	ttm_bo_unmap_virtual_locked(bo);
+	ttm_mem_io_unlock(man);
+}
+
+
 EXPORT_SYMBOL(ttm_bo_unmap_virtual);
 
 static void ttm_bo_vm_insert_rb(struct ttm_buffer_object *bo)
@@ -1651,6 +1691,7 @@ int ttm_bo_wait(struct ttm_buffer_object
 		bool lazy, bool interruptible, bool no_wait)
 {
 	struct ttm_bo_driver *driver = bo->bdev->driver;
+	struct ttm_bo_device *bdev = bo->bdev;
 	void *sync_obj;
 	void *sync_obj_arg;
 	int ret = 0;
@@ -1664,9 +1705,9 @@ int ttm_bo_wait(struct ttm_buffer_object
 			void *tmp_obj = bo->sync_obj;
 			bo->sync_obj = NULL;
 			clear_bit(TTM_BO_PRIV_FLAG_MOVING, &bo->priv_flags);
-			spin_unlock(&bo->lock);
+			spin_unlock(&bdev->fence_lock);
 			driver->sync_obj_unref(&tmp_obj);
-			spin_lock(&bo->lock);
+			spin_lock(&bdev->fence_lock);
 			continue;
 		}
 
@@ -1675,29 +1716,29 @@ int ttm_bo_wait(struct ttm_buffer_object
 
 		sync_obj = driver->sync_obj_ref(bo->sync_obj);
 		sync_obj_arg = bo->sync_obj_arg;
-		spin_unlock(&bo->lock);
+		spin_unlock(&bdev->fence_lock);
 		ret = driver->sync_obj_wait(sync_obj, sync_obj_arg,
 					    lazy, interruptible);
 		if (unlikely(ret != 0)) {
 			driver->sync_obj_unref(&sync_obj);
-			spin_lock(&bo->lock);
+			spin_lock(&bdev->fence_lock);
 			return ret;
 		}
-		spin_lock(&bo->lock);
+		spin_lock(&bdev->fence_lock);
 		if (likely(bo->sync_obj == sync_obj &&
 			   bo->sync_obj_arg == sync_obj_arg)) {
 			void *tmp_obj = bo->sync_obj;
 			bo->sync_obj = NULL;
 			clear_bit(TTM_BO_PRIV_FLAG_MOVING,
 				  &bo->priv_flags);
-			spin_unlock(&bo->lock);
+			spin_unlock(&bdev->fence_lock);
 			driver->sync_obj_unref(&sync_obj);
 			driver->sync_obj_unref(&tmp_obj);
-			spin_lock(&bo->lock);
+			spin_lock(&bdev->fence_lock);
 		} else {
-			spin_unlock(&bo->lock);
+			spin_unlock(&bdev->fence_lock);
 			driver->sync_obj_unref(&sync_obj);
-			spin_lock(&bo->lock);
+			spin_lock(&bdev->fence_lock);
 		}
 	}
 	return 0;
@@ -1706,6 +1747,7 @@ EXPORT_SYMBOL(ttm_bo_wait);
 
 int ttm_bo_synccpu_write_grab(struct ttm_buffer_object *bo, bool no_wait)
 {
+	struct ttm_bo_device *bdev = bo->bdev;
 	int ret = 0;
 
 	/*
@@ -1715,9 +1757,9 @@ int ttm_bo_synccpu_write_grab(struct ttm
 	ret = ttm_bo_reserve(bo, true, no_wait, false, 0);
 	if (unlikely(ret != 0))
 		return ret;
-	spin_lock(&bo->lock);
+	spin_lock(&bdev->fence_lock);
 	ret = ttm_bo_wait(bo, false, true, no_wait);
-	spin_unlock(&bo->lock);
+	spin_unlock(&bdev->fence_lock);
 	if (likely(ret == 0))
 		atomic_inc(&bo->cpu_writers);
 	ttm_bo_unreserve(bo);
@@ -1783,16 +1825,15 @@ static int ttm_bo_swapout(struct ttm_mem
 	put_count = ttm_bo_del_from_lru(bo);
 	spin_unlock(&glob->lru_lock);
 
-	while (put_count--)
-		kref_put(&bo->list_kref, ttm_bo_ref_bug);
+	ttm_bo_list_ref_sub(bo, put_count, true);
 
 	/**
 	 * Wait for GPU, then move to system cached.
 	 */
 
-	spin_lock(&bo->lock);
+	spin_lock(&bo->bdev->fence_lock);
 	ret = ttm_bo_wait(bo, false, false, false);
-	spin_unlock(&bo->lock);
+	spin_unlock(&bo->bdev->fence_lock);
 
 	if (unlikely(ret != 0))
 		goto out;
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/ttm/ttm_bo_util.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/ttm/ttm_bo_util.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/ttm/ttm_bo_util.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/ttm/ttm_bo_util.c	2011-03-14 21:20:32.000000000 -0400
@@ -75,37 +75,123 @@ int ttm_bo_move_ttm(struct ttm_buffer_ob
 }
 EXPORT_SYMBOL(ttm_bo_move_ttm);
 
-int ttm_mem_io_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem)
+int ttm_mem_io_lock(struct ttm_mem_type_manager *man, bool interruptible)
 {
-	int ret;
+	if (likely(man->io_reserve_fastpath))
+		return 0;
 
-	if (!mem->bus.io_reserved) {
-		mem->bus.io_reserved = true;
+	if (interruptible)
+		return mutex_lock_interruptible(&man->io_reserve_mutex);
+
+	mutex_lock(&man->io_reserve_mutex);
+	return 0;
+}
+
+void ttm_mem_io_unlock(struct ttm_mem_type_manager *man)
+{
+	if (likely(man->io_reserve_fastpath))
+		return;
+
+	mutex_unlock(&man->io_reserve_mutex);
+}
+
+static int ttm_mem_io_evict(struct ttm_mem_type_manager *man)
+{
+	struct ttm_buffer_object *bo;
+
+	if (!man->use_io_reserve_lru || list_empty(&man->io_reserve_lru))
+		return -EAGAIN;
+
+	bo = list_first_entry(&man->io_reserve_lru,
+			      struct ttm_buffer_object,
+			      io_reserve_lru);
+	list_del_init(&bo->io_reserve_lru);
+	ttm_bo_unmap_virtual_locked(bo);
+
+	return 0;
+}
+
+static int ttm_mem_io_reserve(struct ttm_bo_device *bdev,
+			      struct ttm_mem_reg *mem)
+{
+	struct ttm_mem_type_manager *man = &bdev->man[mem->mem_type];
+	int ret = 0;
+
+	if (!bdev->driver->io_mem_reserve)
+		return 0;
+	if (likely(man->io_reserve_fastpath))
+		return bdev->driver->io_mem_reserve(bdev, mem);
+
+	if (bdev->driver->io_mem_reserve &&
+	    mem->bus.io_reserved_count++ == 0) {
+retry:
 		ret = bdev->driver->io_mem_reserve(bdev, mem);
+		if (ret == -EAGAIN) {
+			ret = ttm_mem_io_evict(man);
+			if (ret == 0)
+				goto retry;
+		}
+	}
+	return ret;
+}
+
+static void ttm_mem_io_free(struct ttm_bo_device *bdev,
+			    struct ttm_mem_reg *mem)
+{
+	struct ttm_mem_type_manager *man = &bdev->man[mem->mem_type];
+
+	if (likely(man->io_reserve_fastpath))
+		return;
+
+	if (bdev->driver->io_mem_reserve &&
+	    --mem->bus.io_reserved_count == 0 &&
+	    bdev->driver->io_mem_free)
+		bdev->driver->io_mem_free(bdev, mem);
+
+}
+
+int ttm_mem_io_reserve_vm(struct ttm_buffer_object *bo)
+{
+	struct ttm_mem_reg *mem = &bo->mem;
+	int ret;
+
+	if (!mem->bus.io_reserved_vm) {
+		struct ttm_mem_type_manager *man =
+			&bo->bdev->man[mem->mem_type];
+
+		ret = ttm_mem_io_reserve(bo->bdev, mem);
 		if (unlikely(ret != 0))
 			return ret;
+		mem->bus.io_reserved_vm = true;
+		if (man->use_io_reserve_lru)
+			list_add_tail(&bo->io_reserve_lru,
+				      &man->io_reserve_lru);
 	}
 	return 0;
 }
 
-void ttm_mem_io_free(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem)
+void ttm_mem_io_free_vm(struct ttm_buffer_object *bo)
 {
-	if (bdev->driver->io_mem_reserve) {
-		if (mem->bus.io_reserved) {
-			mem->bus.io_reserved = false;
-			bdev->driver->io_mem_free(bdev, mem);
-		}
+	struct ttm_mem_reg *mem = &bo->mem;
+
+	if (mem->bus.io_reserved_vm) {
+		mem->bus.io_reserved_vm = false;
+		list_del_init(&bo->io_reserve_lru);
+		ttm_mem_io_free(bo->bdev, mem);
 	}
 }
 
 int ttm_mem_reg_ioremap(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem,
 			void **virtual)
 {
+	struct ttm_mem_type_manager *man = &bdev->man[mem->mem_type];
 	int ret;
 	void *addr;
 
 	*virtual = NULL;
+	(void) ttm_mem_io_lock(man, false);
 	ret = ttm_mem_io_reserve(bdev, mem);
+	ttm_mem_io_unlock(man);
 	if (ret || !mem->bus.is_iomem)
 		return ret;
 
@@ -117,7 +203,9 @@ int ttm_mem_reg_ioremap(struct ttm_bo_de
 		else
 			addr = ioremap_nocache(mem->bus.base + mem->bus.offset, mem->bus.size);
 		if (!addr) {
+			(void) ttm_mem_io_lock(man, false);
 			ttm_mem_io_free(bdev, mem);
+			ttm_mem_io_unlock(man);
 			return -ENOMEM;
 		}
 	}
@@ -134,7 +222,9 @@ void ttm_mem_reg_iounmap(struct ttm_bo_d
 
 	if (virtual && mem->bus.addr == NULL)
 		iounmap(virtual);
+	(void) ttm_mem_io_lock(man, false);
 	ttm_mem_io_free(bdev, mem);
+	ttm_mem_io_unlock(man);
 }
 
 static int ttm_copy_io_page(void *dst, void *src, unsigned long page)
@@ -231,7 +321,7 @@ int ttm_bo_move_memcpy(struct ttm_buffer
 	struct ttm_mem_type_manager *man = &bdev->man[new_mem->mem_type];
 	struct ttm_tt *ttm = bo->ttm;
 	struct ttm_mem_reg *old_mem = &bo->mem;
-	struct ttm_mem_reg old_copy = *old_mem;
+	struct ttm_mem_reg old_copy;
 	void *old_iomap;
 	void *new_iomap;
 	int ret;
@@ -280,8 +370,7 @@ int ttm_bo_move_memcpy(struct ttm_buffer
 	}
 	mb();
 out2:
-	ttm_bo_free_old_node(bo);
-
+	old_copy = *old_mem;
 	*old_mem = *new_mem;
 	new_mem->mm_node = NULL;
 
@@ -292,9 +381,10 @@ out2:
 	}
 
 out1:
-	ttm_mem_reg_iounmap(bdev, new_mem, new_iomap);
+	ttm_mem_reg_iounmap(bdev, old_mem, new_iomap);
 out:
 	ttm_mem_reg_iounmap(bdev, &old_copy, old_iomap);
+	ttm_bo_mem_put(bo, &old_copy);
 	return ret;
 }
 EXPORT_SYMBOL(ttm_bo_move_memcpy);
@@ -337,11 +427,11 @@ static int ttm_buffer_object_transfer(st
 	 * TODO: Explicit member copy would probably be better here.
 	 */
 
-	spin_lock_init(&fbo->lock);
 	init_waitqueue_head(&fbo->event_queue);
 	INIT_LIST_HEAD(&fbo->ddestroy);
 	INIT_LIST_HEAD(&fbo->lru);
 	INIT_LIST_HEAD(&fbo->swap);
+	INIT_LIST_HEAD(&fbo->io_reserve_lru);
 	fbo->vm_node = NULL;
 	atomic_set(&fbo->cpu_writers, 0);
 
@@ -453,6 +543,8 @@ int ttm_bo_kmap(struct ttm_buffer_object
 		unsigned long start_page, unsigned long num_pages,
 		struct ttm_bo_kmap_obj *map)
 {
+	struct ttm_mem_type_manager *man =
+		&bo->bdev->man[bo->mem.mem_type];
 	unsigned long offset, size;
 	int ret;
 
@@ -467,7 +559,9 @@ int ttm_bo_kmap(struct ttm_buffer_object
 	if (num_pages > 1 && !DRM_SUSER(DRM_CURPROC))
 		return -EPERM;
 #endif
+	(void) ttm_mem_io_lock(man, false);
 	ret = ttm_mem_io_reserve(bo->bdev, &bo->mem);
+	ttm_mem_io_unlock(man);
 	if (ret)
 		return ret;
 	if (!bo->mem.bus.is_iomem) {
@@ -482,12 +576,15 @@ EXPORT_SYMBOL(ttm_bo_kmap);
 
 void ttm_bo_kunmap(struct ttm_bo_kmap_obj *map)
 {
+	struct ttm_buffer_object *bo = map->bo;
+	struct ttm_mem_type_manager *man =
+		&bo->bdev->man[bo->mem.mem_type];
+
 	if (!map->virtual)
 		return;
 	switch (map->bo_kmap_type) {
 	case ttm_bo_map_iomap:
 		iounmap(map->virtual);
-		ttm_mem_io_free(map->bo->bdev, &map->bo->mem);
 		break;
 	case ttm_bo_map_vmap:
 		vunmap(map->virtual);
@@ -500,6 +597,9 @@ void ttm_bo_kunmap(struct ttm_bo_kmap_ob
 	default:
 		BUG();
 	}
+	(void) ttm_mem_io_lock(man, false);
+	ttm_mem_io_free(map->bo->bdev, &map->bo->mem);
+	ttm_mem_io_unlock(man);
 	map->virtual = NULL;
 	map->page = NULL;
 }
@@ -520,7 +620,7 @@ int ttm_bo_move_accel_cleanup(struct ttm
 	struct ttm_buffer_object *ghost_obj;
 	void *tmp_obj = NULL;
 
-	spin_lock(&bo->lock);
+	spin_lock(&bdev->fence_lock);
 	if (bo->sync_obj) {
 		tmp_obj = bo->sync_obj;
 		bo->sync_obj = NULL;
@@ -529,7 +629,7 @@ int ttm_bo_move_accel_cleanup(struct ttm
 	bo->sync_obj_arg = sync_obj_arg;
 	if (evict) {
 		ret = ttm_bo_wait(bo, false, false, false);
-		spin_unlock(&bo->lock);
+		spin_unlock(&bdev->fence_lock);
 		if (tmp_obj)
 			driver->sync_obj_unref(&tmp_obj);
 		if (ret)
@@ -552,7 +652,7 @@ int ttm_bo_move_accel_cleanup(struct ttm
 		 */
 
 		set_bit(TTM_BO_PRIV_FLAG_MOVING, &bo->priv_flags);
-		spin_unlock(&bo->lock);
+		spin_unlock(&bdev->fence_lock);
 		if (tmp_obj)
 			driver->sync_obj_unref(&tmp_obj);
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/ttm/ttm_bo_vm.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/ttm/ttm_bo_vm.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/ttm/ttm_bo_vm.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/ttm/ttm_bo_vm.c	2011-03-14 21:20:32.000000000 -0400
@@ -83,6 +83,8 @@ static int ttm_bo_vm_fault(struct vm_are
 	int i;
 	unsigned long address = (unsigned long)vmf->virtual_address;
 	int retval = VM_FAULT_NOPAGE;
+	struct ttm_mem_type_manager *man =
+		&bdev->man[bo->mem.mem_type];
 
 	/*
 	 * Work around locking order reversal in fault / nopfn
@@ -118,24 +120,28 @@ static int ttm_bo_vm_fault(struct vm_are
 	 * move.
 	 */
 
-	spin_lock(&bo->lock);
+	spin_lock(&bdev->fence_lock);
 	if (test_bit(TTM_BO_PRIV_FLAG_MOVING, &bo->priv_flags)) {
 		ret = ttm_bo_wait(bo, false, true, false);
-		spin_unlock(&bo->lock);
+		spin_unlock(&bdev->fence_lock);
 		if (unlikely(ret != 0)) {
 			retval = (ret != -ERESTARTSYS) ?
 			    VM_FAULT_SIGBUS : VM_FAULT_NOPAGE;
 			goto out_unlock;
 		}
 	} else
-		spin_unlock(&bo->lock);
-
+		spin_unlock(&bdev->fence_lock);
 
-	ret = ttm_mem_io_reserve(bdev, &bo->mem);
-	if (ret) {
-		retval = VM_FAULT_SIGBUS;
+	ret = ttm_mem_io_lock(man, true);
+	if (unlikely(ret != 0)) {
+		retval = VM_FAULT_NOPAGE;
 		goto out_unlock;
 	}
+	ret = ttm_mem_io_reserve_vm(bo);
+	if (unlikely(ret != 0)) {
+		retval = VM_FAULT_SIGBUS;
+		goto out_io_unlock;
+	}
 
 	page_offset = ((address - vma->vm_start) >> PAGE_SHIFT) +
 	    bo->vm_node->start - vma->vm_pgoff;
@@ -144,7 +150,7 @@ static int ttm_bo_vm_fault(struct vm_are
 
 	if (unlikely(page_offset >= bo->num_pages)) {
 		retval = VM_FAULT_SIGBUS;
-		goto out_unlock;
+		goto out_io_unlock;
 	}
 
 	/*
@@ -182,7 +188,7 @@ static int ttm_bo_vm_fault(struct vm_are
 			page = ttm_tt_get_page(ttm, page_offset);
 			if (unlikely(!page && i == 0)) {
 				retval = VM_FAULT_OOM;
-				goto out_unlock;
+				goto out_io_unlock;
 			} else if (unlikely(!page)) {
 				break;
 			}
@@ -200,14 +206,15 @@ static int ttm_bo_vm_fault(struct vm_are
 		else if (unlikely(ret != 0)) {
 			retval =
 			    (ret == -ENOMEM) ? VM_FAULT_OOM : VM_FAULT_SIGBUS;
-			goto out_unlock;
+			goto out_io_unlock;
 		}
 
 		address += PAGE_SIZE;
 		if (unlikely(++page_offset >= page_last))
 			break;
 	}
-
+out_io_unlock:
+	ttm_mem_io_unlock(man);
 out_unlock:
 	ttm_bo_unreserve(bo);
 	return retval;
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/ttm/ttm_execbuf_util.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/ttm/ttm_execbuf_util.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/ttm/ttm_execbuf_util.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/ttm/ttm_execbuf_util.c	2011-03-14 21:20:32.000000000 -0400
@@ -32,7 +32,7 @@
 #include <linux/sched.h>
 #include <linux/module.h>
 
-void ttm_eu_backoff_reservation(struct list_head *list)
+static void ttm_eu_backoff_reservation_locked(struct list_head *list)
 {
 	struct ttm_validate_buffer *entry;
 
@@ -41,10 +41,77 @@ void ttm_eu_backoff_reservation(struct l
 		if (!entry->reserved)
 			continue;
 
+		if (entry->removed) {
+			ttm_bo_add_to_lru(bo);
+			entry->removed = false;
+
+		}
 		entry->reserved = false;
-		ttm_bo_unreserve(bo);
+		atomic_set(&bo->reserved, 0);
+		wake_up_all(&bo->event_queue);
 	}
 }
+
+static void ttm_eu_del_from_lru_locked(struct list_head *list)
+{
+	struct ttm_validate_buffer *entry;
+
+	list_for_each_entry(entry, list, head) {
+		struct ttm_buffer_object *bo = entry->bo;
+		if (!entry->reserved)
+			continue;
+
+		if (!entry->removed) {
+			entry->put_count = ttm_bo_del_from_lru(bo);
+			entry->removed = true;
+		}
+	}
+}
+
+static void ttm_eu_list_ref_sub(struct list_head *list)
+{
+	struct ttm_validate_buffer *entry;
+
+	list_for_each_entry(entry, list, head) {
+		struct ttm_buffer_object *bo = entry->bo;
+
+		if (entry->put_count) {
+			ttm_bo_list_ref_sub(bo, entry->put_count, true);
+			entry->put_count = 0;
+		}
+	}
+}
+
+static int ttm_eu_wait_unreserved_locked(struct list_head *list,
+					 struct ttm_buffer_object *bo)
+{
+	struct ttm_bo_global *glob = bo->glob;
+	int ret;
+
+	ttm_eu_del_from_lru_locked(list);
+	spin_unlock(&glob->lru_lock);
+	ret = ttm_bo_wait_unreserved(bo, true);
+	spin_lock(&glob->lru_lock);
+	if (unlikely(ret != 0))
+		ttm_eu_backoff_reservation_locked(list);
+	return ret;
+}
+
+
+void ttm_eu_backoff_reservation(struct list_head *list)
+{
+	struct ttm_validate_buffer *entry;
+	struct ttm_bo_global *glob;
+
+	if (list_empty(list))
+		return;
+
+	entry = list_first_entry(list, struct ttm_validate_buffer, head);
+	glob = entry->bo->glob;
+	spin_lock(&glob->lru_lock);
+	ttm_eu_backoff_reservation_locked(list);
+	spin_unlock(&glob->lru_lock);
+}
 EXPORT_SYMBOL(ttm_eu_backoff_reservation);
 
 /*
@@ -59,37 +126,76 @@ EXPORT_SYMBOL(ttm_eu_backoff_reservation
  * buffers in different orders.
  */
 
-int ttm_eu_reserve_buffers(struct list_head *list, uint32_t val_seq)
+int ttm_eu_reserve_buffers(struct list_head *list)
 {
+	struct ttm_bo_global *glob;
 	struct ttm_validate_buffer *entry;
 	int ret;
+	uint32_t val_seq;
+
+	if (list_empty(list))
+		return 0;
+
+	list_for_each_entry(entry, list, head) {
+		entry->reserved = false;
+		entry->put_count = 0;
+		entry->removed = false;
+	}
+
+	entry = list_first_entry(list, struct ttm_validate_buffer, head);
+	glob = entry->bo->glob;
 
 retry:
+	spin_lock(&glob->lru_lock);
+	val_seq = entry->bo->bdev->val_seq++;
+
 	list_for_each_entry(entry, list, head) {
 		struct ttm_buffer_object *bo = entry->bo;
 
-		entry->reserved = false;
-		ret = ttm_bo_reserve(bo, true, false, true, val_seq);
-		if (ret != 0) {
-			ttm_eu_backoff_reservation(list);
-			if (ret == -EAGAIN) {
-				ret = ttm_bo_wait_unreserved(bo, true);
-				if (unlikely(ret != 0))
-					return ret;
-				goto retry;
-			} else
+retry_this_bo:
+		ret = ttm_bo_reserve_locked(bo, true, true, true, val_seq);
+		switch (ret) {
+		case 0:
+			break;
+		case -EBUSY:
+			ret = ttm_eu_wait_unreserved_locked(list, bo);
+			if (unlikely(ret != 0)) {
+				spin_unlock(&glob->lru_lock);
+				ttm_eu_list_ref_sub(list);
 				return ret;
+			}
+			goto retry_this_bo;
+		case -EAGAIN:
+			ttm_eu_backoff_reservation_locked(list);
+			spin_unlock(&glob->lru_lock);
+			ttm_eu_list_ref_sub(list);
+			ret = ttm_bo_wait_unreserved(bo, true);
+			if (unlikely(ret != 0))
+				return ret;
+			goto retry;
+		default:
+			ttm_eu_backoff_reservation_locked(list);
+			spin_unlock(&glob->lru_lock);
+			ttm_eu_list_ref_sub(list);
+			return ret;
 		}
 
 		entry->reserved = true;
 		if (unlikely(atomic_read(&bo->cpu_writers) > 0)) {
-			ttm_eu_backoff_reservation(list);
+			ttm_eu_backoff_reservation_locked(list);
+			spin_unlock(&glob->lru_lock);
+			ttm_eu_list_ref_sub(list);
 			ret = ttm_bo_wait_cpu(bo, false);
 			if (ret)
 				return ret;
 			goto retry;
 		}
 	}
+
+	ttm_eu_del_from_lru_locked(list);
+	spin_unlock(&glob->lru_lock);
+	ttm_eu_list_ref_sub(list);
+
 	return 0;
 }
 EXPORT_SYMBOL(ttm_eu_reserve_buffers);
@@ -97,21 +203,36 @@ EXPORT_SYMBOL(ttm_eu_reserve_buffers);
 void ttm_eu_fence_buffer_objects(struct list_head *list, void *sync_obj)
 {
 	struct ttm_validate_buffer *entry;
+	struct ttm_buffer_object *bo;
+	struct ttm_bo_global *glob;
+	struct ttm_bo_device *bdev;
+	struct ttm_bo_driver *driver;
 
-	list_for_each_entry(entry, list, head) {
-		struct ttm_buffer_object *bo = entry->bo;
-		struct ttm_bo_driver *driver = bo->bdev->driver;
-		void *old_sync_obj;
+	if (list_empty(list))
+		return;
 
-		spin_lock(&bo->lock);
-		old_sync_obj = bo->sync_obj;
+	bo = list_first_entry(list, struct ttm_validate_buffer, head)->bo;
+	bdev = bo->bdev;
+	driver = bdev->driver;
+	glob = bo->glob;
+
+	spin_lock(&bdev->fence_lock);
+	spin_lock(&glob->lru_lock);
+
+	list_for_each_entry(entry, list, head) {
+		bo = entry->bo;
+		entry->old_sync_obj = bo->sync_obj;
 		bo->sync_obj = driver->sync_obj_ref(sync_obj);
 		bo->sync_obj_arg = entry->new_sync_obj_arg;
-		spin_unlock(&bo->lock);
-		ttm_bo_unreserve(bo);
+		ttm_bo_unreserve_locked(bo);
 		entry->reserved = false;
-		if (old_sync_obj)
-			driver->sync_obj_unref(&old_sync_obj);
+	}
+	spin_unlock(&glob->lru_lock);
+	spin_unlock(&bdev->fence_lock);
+
+	list_for_each_entry(entry, list, head) {
+		if (entry->old_sync_obj)
+			driver->sync_obj_unref(&entry->old_sync_obj);
 	}
 }
 EXPORT_SYMBOL(ttm_eu_fence_buffer_objects);
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h linux-libre-2.6.38-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h	2011-03-14 21:20:32.000000000 -0400
@@ -264,7 +264,6 @@ struct vmw_private {
 	 */
 
 	struct vmw_sw_context ctx;
-	uint32_t val_seq;
 	struct mutex cmdbuf_mutex;
 
 	/**
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c	2011-03-14 21:20:32.000000000 -0400
@@ -653,8 +653,7 @@ int vmw_execbuf_ioctl(struct drm_device
 	ret = vmw_cmd_check_all(dev_priv, sw_context, cmd, arg->command_size);
 	if (unlikely(ret != 0))
 		goto out_err;
-	ret = ttm_eu_reserve_buffers(&sw_context->validate_nodes,
-				     dev_priv->val_seq++);
+	ret = ttm_eu_reserve_buffers(&sw_context->validate_nodes);
 	if (unlikely(ret != 0))
 		goto out_err;
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c linux-libre-2.6.38-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c	2011-03-14 21:20:32.000000000 -0400
@@ -480,9 +480,6 @@ int vmw_fb_init(struct vmw_private *vmw_
 	info->fix.smem_start = 0;
 	info->fix.smem_len = fb_size;
 
-	info->fix.mmio_start = 0;
-	info->fix.mmio_len = 0;
-
 	info->pseudo_palette = par->pseudo_palette;
 	info->screen_base = par->vmalloc;
 	info->screen_size = fb_size;
@@ -659,7 +656,7 @@ int vmw_fb_off(struct vmw_private *vmw_p
 	par->dirty.active = false;
 	spin_unlock_irqrestore(&par->dirty.lock, flags);
 
-	flush_scheduled_work();
+	flush_delayed_work_sync(&info->deferred_work);
 
 	par->bo_ptr = NULL;
 	ttm_bo_kunmap(&par->map);
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/stub/Kconfig linux-libre-2.6.38-gnu1/drivers/gpu/stub/Kconfig
--- linux-libre-2.6.37-gnu1/drivers/gpu/stub/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/stub/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -1,12 +1,13 @@
 config STUB_POULSBO
 	tristate "Intel GMA500 Stub Driver"
 	depends on PCI
+	depends on NET # for THERMAL
 	# Poulsbo stub depends on ACPI_VIDEO when ACPI is enabled
 	# but for select to work, need to select ACPI_VIDEO's dependencies, ick
-	select VIDEO_OUTPUT_CONTROL if ACPI
 	select BACKLIGHT_CLASS_DEVICE if ACPI
 	select INPUT if ACPI
 	select ACPI_VIDEO if ACPI
+	select THERMAL if ACPI
 	help
 	  Choose this option if you have a system that has Intel GMA500
 	  (Poulsbo) integrated graphics. If M is selected, the module will
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/vga/Kconfig linux-libre-2.6.38-gnu1/drivers/gpu/vga/Kconfig
--- linux-libre-2.6.37-gnu1/drivers/gpu/vga/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/vga/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -1,5 +1,5 @@
 config VGA_ARB
-	bool "VGA Arbitration" if EMBEDDED
+	bool "VGA Arbitration" if EXPERT
 	default y
 	depends on PCI
 	help
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/vga/vgaarb.c linux-libre-2.6.38-gnu1/drivers/gpu/vga/vgaarb.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/vga/vgaarb.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/vga/vgaarb.c	2011-03-14 21:20:32.000000000 -0400
@@ -636,7 +636,7 @@ int vga_client_register(struct pci_dev *
 			void (*irq_set_state)(void *cookie, bool state),
 			unsigned int (*set_vga_decode)(void *cookie, bool decode))
 {
-	int ret = -1;
+	int ret = -ENODEV;
 	struct vga_device *vgadev;
 	unsigned long flags;
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/gpu/vga/vga_switcheroo.c linux-libre-2.6.38-gnu1/drivers/gpu/vga/vga_switcheroo.c
--- linux-libre-2.6.37-gnu1/drivers/gpu/vga/vga_switcheroo.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/gpu/vga/vga_switcheroo.c	2011-03-14 21:20:32.000000000 -0400
@@ -33,6 +33,7 @@ struct vga_switcheroo_client {
 	struct fb_info *fb_info;
 	int pwr_state;
 	void (*set_gpu_state)(struct pci_dev *pdev, enum vga_switcheroo_state);
+	void (*reprobe)(struct pci_dev *pdev);
 	bool (*can_switch)(struct pci_dev *pdev);
 	int id;
 	bool active;
@@ -103,6 +104,7 @@ static void vga_switcheroo_enable(void)
 
 int vga_switcheroo_register_client(struct pci_dev *pdev,
 				   void (*set_gpu_state)(struct pci_dev *pdev, enum vga_switcheroo_state),
+				   void (*reprobe)(struct pci_dev *pdev),
 				   bool (*can_switch)(struct pci_dev *pdev))
 {
 	int index;
@@ -117,6 +119,7 @@ int vga_switcheroo_register_client(struc
 	vgasr_priv.clients[index].pwr_state = VGA_SWITCHEROO_ON;
 	vgasr_priv.clients[index].pdev = pdev;
 	vgasr_priv.clients[index].set_gpu_state = set_gpu_state;
+	vgasr_priv.clients[index].reprobe = reprobe;
 	vgasr_priv.clients[index].can_switch = can_switch;
 	vgasr_priv.clients[index].id = -1;
 	if (pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW)
@@ -174,7 +177,8 @@ static int vga_switcheroo_show(struct se
 	int i;
 	mutex_lock(&vgasr_mutex);
 	for (i = 0; i < VGA_SWITCHEROO_MAX_CLIENTS; i++) {
-		seq_printf(m, "%d:%c:%s:%s\n", i,
+		seq_printf(m, "%d:%s:%c:%s:%s\n", i,
+			   vgasr_priv.clients[i].id == VGA_SWITCHEROO_DIS ? "DIS" : "IGD",
 			   vgasr_priv.clients[i].active ? '+' : ' ',
 			   vgasr_priv.clients[i].pwr_state ? "Pwr" : "Off",
 			   pci_name(vgasr_priv.clients[i].pdev));
@@ -190,9 +194,8 @@ static int vga_switcheroo_debugfs_open(s
 
 static int vga_switchon(struct vga_switcheroo_client *client)
 {
-	int ret;
-
-	ret = vgasr_priv.handler->power_state(client->id, VGA_SWITCHEROO_ON);
+	if (vgasr_priv.handler->power_state)
+		vgasr_priv.handler->power_state(client->id, VGA_SWITCHEROO_ON);
 	/* call the driver callback to turn on device */
 	client->set_gpu_state(client->pdev, VGA_SWITCHEROO_ON);
 	client->pwr_state = VGA_SWITCHEROO_ON;
@@ -203,12 +206,14 @@ static int vga_switchoff(struct vga_swit
 {
 	/* call the driver callback to turn off device */
 	client->set_gpu_state(client->pdev, VGA_SWITCHEROO_OFF);
-	vgasr_priv.handler->power_state(client->id, VGA_SWITCHEROO_OFF);
+	if (vgasr_priv.handler->power_state)
+		vgasr_priv.handler->power_state(client->id, VGA_SWITCHEROO_OFF);
 	client->pwr_state = VGA_SWITCHEROO_OFF;
 	return 0;
 }
 
-static int vga_switchto(struct vga_switcheroo_client *new_client)
+/* stage one happens before delay */
+static int vga_switchto_stage1(struct vga_switcheroo_client *new_client)
 {
 	int ret;
 	int i;
@@ -235,10 +240,28 @@ static int vga_switchto(struct vga_switc
 		vga_switchon(new_client);
 
 	/* swap shadow resource to denote boot VGA device has changed so X starts on new device */
-	active->active = false;
-
 	active->pdev->resource[PCI_ROM_RESOURCE].flags &= ~IORESOURCE_ROM_SHADOW;
 	new_client->pdev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_SHADOW;
+	return 0;
+}
+
+/* post delay */
+static int vga_switchto_stage2(struct vga_switcheroo_client *new_client)
+{
+	int ret;
+	int i;
+	struct vga_switcheroo_client *active = NULL;
+
+	for (i = 0; i < VGA_SWITCHEROO_MAX_CLIENTS; i++) {
+		if (vgasr_priv.clients[i].active == true) {
+			active = &vgasr_priv.clients[i];
+			break;
+		}
+	}
+	if (!active)
+		return 0;
+
+	active->active = false;
 
 	if (new_client->fb_info) {
 		struct fb_event event;
@@ -250,6 +273,9 @@ static int vga_switchto(struct vga_switc
 	if (ret)
 		return ret;
 
+	if (new_client->reprobe)
+		new_client->reprobe(new_client->pdev);
+
 	if (active->pwr_state == VGA_SWITCHEROO_ON)
 		vga_switchoff(active);
 
@@ -265,6 +291,7 @@ vga_switcheroo_debugfs_write(struct file
 	const char *pdev_name;
 	int i, ret;
 	bool delay = false, can_switch;
+	bool just_mux = false;
 	int client_id = -1;
 	struct vga_switcheroo_client *client = NULL;
 
@@ -319,6 +346,15 @@ vga_switcheroo_debugfs_write(struct file
 	if (strncmp(usercmd, "DIS", 3) == 0)
 		client_id = VGA_SWITCHEROO_DIS;
 
+	if (strncmp(usercmd, "MIGD", 4) == 0) {
+		just_mux = true;
+		client_id = VGA_SWITCHEROO_IGD;
+	}
+	if (strncmp(usercmd, "MDIS", 4) == 0) {
+		just_mux = true;
+		client_id = VGA_SWITCHEROO_DIS;
+	}
+
 	if (client_id == -1)
 		goto out;
 
@@ -330,6 +366,12 @@ vga_switcheroo_debugfs_write(struct file
 	}
 
 	vgasr_priv.delayed_switch_active = false;
+
+	if (just_mux) {
+		ret = vgasr_priv.handler->switchto(client_id);
+		goto out;
+	}
+
 	/* okay we want a switch - test if devices are willing to switch */
 	can_switch = true;
 	for (i = 0; i < VGA_SWITCHEROO_MAX_CLIENTS; i++) {
@@ -345,18 +387,22 @@ vga_switcheroo_debugfs_write(struct file
 
 	if (can_switch == true) {
 		pdev_name = pci_name(client->pdev);
-		ret = vga_switchto(client);
+		ret = vga_switchto_stage1(client);
 		if (ret)
-			printk(KERN_ERR "vga_switcheroo: switching failed %d\n", ret);
+			printk(KERN_ERR "vga_switcheroo: switching failed stage 1 %d\n", ret);
+
+		ret = vga_switchto_stage2(client);
+		if (ret)
+			printk(KERN_ERR "vga_switcheroo: switching failed stage 2 %d\n", ret);
+
 	} else {
 		printk(KERN_INFO "vga_switcheroo: setting delayed switch to client %d\n", client->id);
 		vgasr_priv.delayed_switch_active = true;
 		vgasr_priv.delayed_client_id = client_id;
 
-		/* we should at least power up the card to
-		   make the switch faster */
-		if (client->pwr_state == VGA_SWITCHEROO_OFF)
-			vga_switchon(client);
+		ret = vga_switchto_stage1(client);
+		if (ret)
+			printk(KERN_ERR "vga_switcheroo: delayed switching stage 1 failed %d\n", ret);
 	}
 
 out:
@@ -438,9 +484,9 @@ int vga_switcheroo_process_delayed_switc
 		goto err;
 
 	pdev_name = pci_name(client->pdev);
-	ret = vga_switchto(client);
+	ret = vga_switchto_stage2(client);
 	if (ret)
-		printk(KERN_ERR "vga_switcheroo: delayed switching failed %d\n", ret);
+		printk(KERN_ERR "vga_switcheroo: delayed switching failed stage 2 %d\n", ret);
 
 	vgasr_priv.delayed_switch_active = false;
 	err = 0;
diff -druNp linux-libre-2.6.37-gnu1/drivers/hid/hid-3m-pct.c linux-libre-2.6.38-gnu1/drivers/hid/hid-3m-pct.c
--- linux-libre-2.6.37-gnu1/drivers/hid/hid-3m-pct.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hid/hid-3m-pct.c	2011-03-14 21:20:32.000000000 -0400
@@ -19,6 +19,7 @@
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/usb.h>
+#include <linux/input/mt.h>
 
 MODULE_AUTHOR("Stephane Chatty <chatty@enac.fr>");
 MODULE_DESCRIPTION("3M PCT multitouch panels");
@@ -27,8 +28,6 @@ MODULE_LICENSE("GPL");
 #include "hid-ids.h"
 
 #define MAX_SLOTS		60
-#define MAX_TRKID		USHRT_MAX
-#define MAX_EVENTS		360
 
 /* estimated signal-to-noise ratios */
 #define SN_MOVE			2048
@@ -36,14 +35,11 @@ MODULE_LICENSE("GPL");
 
 struct mmm_finger {
 	__s32 x, y, w, h;
-	__u16 id;
-	bool prev_touch;
 	bool touch, valid;
 };
 
 struct mmm_data {
 	struct mmm_finger f[MAX_SLOTS];
-	__u16 id;
 	__u8 curid;
 	__u8 nexp, nreal;
 	bool touch, valid;
@@ -117,14 +113,7 @@ static int mmm_input_mapping(struct hid_
 					0, 1, 0, 0);
 			return 1;
 		case HID_DG_CONTACTID:
-			field->logical_maximum = MAX_TRKID;
-			hid_map_usage(hi, usage, bit, max,
-					EV_ABS, ABS_MT_TRACKING_ID);
-			input_set_abs_params(hi->input, ABS_MT_TRACKING_ID,
-					     0, MAX_TRKID, 0, 0);
-			if (!hi->input->mt)
-				input_mt_create_slots(hi->input, MAX_SLOTS);
-			input_set_events_per_packet(hi->input, MAX_EVENTS);
+			input_mt_init_slots(hi->input, MAX_SLOTS);
 			return 1;
 		}
 		/* let hid-input decide for the others */
@@ -154,7 +143,6 @@ static int mmm_input_mapped(struct hid_d
  */
 static void mmm_filter_event(struct mmm_data *md, struct input_dev *input)
 {
-	struct mmm_finger *oldest = 0;
 	int i;
 	for (i = 0; i < MAX_SLOTS; ++i) {
 		struct mmm_finger *f = &md->f[i];
@@ -163,6 +151,7 @@ static void mmm_filter_event(struct mmm_
 			continue;
 		}
 		input_mt_slot(input, i);
+		input_mt_report_slot_state(input, MT_TOOL_FINGER, f->touch);
 		if (f->touch) {
 			/* this finger is on the screen */
 			int wide = (f->w > f->h);
@@ -170,33 +159,16 @@ static void mmm_filter_event(struct mmm_
 			int major = max(f->w, f->h) >> 1;
 			int minor = min(f->w, f->h) >> 1;
 
-			if (!f->prev_touch)
-				f->id = md->id++;
-			input_event(input, EV_ABS, ABS_MT_TRACKING_ID, f->id);
 			input_event(input, EV_ABS, ABS_MT_POSITION_X, f->x);
 			input_event(input, EV_ABS, ABS_MT_POSITION_Y, f->y);
 			input_event(input, EV_ABS, ABS_MT_ORIENTATION, wide);
 			input_event(input, EV_ABS, ABS_MT_TOUCH_MAJOR, major);
 			input_event(input, EV_ABS, ABS_MT_TOUCH_MINOR, minor);
-			/* touchscreen emulation: pick the oldest contact */
-			if (!oldest || ((f->id - oldest->id) & (SHRT_MAX + 1)))
-				oldest = f;
-		} else {
-			/* this finger took off the screen */
-			input_event(input, EV_ABS, ABS_MT_TRACKING_ID, -1);
 		}
-		f->prev_touch = f->touch;
 		f->valid = 0;
 	}
 
-	/* touchscreen emulation */
-	if (oldest) {
-		input_event(input, EV_KEY, BTN_TOUCH, 1);
-		input_event(input, EV_ABS, ABS_X, oldest->x);
-		input_event(input, EV_ABS, ABS_Y, oldest->y);
-	} else {
-		input_event(input, EV_KEY, BTN_TOUCH, 0);
-	}
+	input_mt_report_pointer_emulation(input, true);
 	input_sync(input);
 }
 
@@ -274,7 +246,7 @@ static int mmm_probe(struct hid_device *
 
 	md = kzalloc(sizeof(struct mmm_data), GFP_KERNEL);
 	if (!md) {
-		dev_err(&hdev->dev, "cannot allocate 3M data\n");
+		hid_err(hdev, "cannot allocate 3M data\n");
 		return -ENOMEM;
 	}
 	hid_set_drvdata(hdev, md);
diff -druNp linux-libre-2.6.37-gnu1/drivers/hid/hid-a4tech.c linux-libre-2.6.38-gnu1/drivers/hid/hid-a4tech.c
--- linux-libre-2.6.37-gnu1/drivers/hid/hid-a4tech.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hid/hid-a4tech.c	2011-03-14 21:20:32.000000000 -0400
@@ -93,7 +93,7 @@ static int a4_probe(struct hid_device *h
 
 	a4 = kzalloc(sizeof(*a4), GFP_KERNEL);
 	if (a4 == NULL) {
-		dev_err(&hdev->dev, "can't alloc device descriptor\n");
+		hid_err(hdev, "can't alloc device descriptor\n");
 		ret = -ENOMEM;
 		goto err_free;
 	}
@@ -104,13 +104,13 @@ static int a4_probe(struct hid_device *h
 
 	ret = hid_parse(hdev);
 	if (ret) {
-		dev_err(&hdev->dev, "parse failed\n");
+		hid_err(hdev, "parse failed\n");
 		goto err_free;
 	}
 
 	ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
 	if (ret) {
-		dev_err(&hdev->dev, "hw start failed\n");
+		hid_err(hdev, "hw start failed\n");
 		goto err_free;
 	}
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/hid/hid-apple.c linux-libre-2.6.38-gnu1/drivers/hid/hid-apple.c
--- linux-libre-2.6.37-gnu1/drivers/hid/hid-apple.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hid/hid-apple.c	2011-03-14 21:20:32.000000000 -0400
@@ -16,6 +16,8 @@
  * any later version.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/device.h>
 #include <linux/hid.h>
 #include <linux/module.h>
@@ -59,6 +61,27 @@ struct apple_key_translation {
 	u8 flags;
 };
 
+static const struct apple_key_translation macbookair_fn_keys[] = {
+	{ KEY_BACKSPACE, KEY_DELETE },
+	{ KEY_ENTER,	KEY_INSERT },
+	{ KEY_F1,	KEY_BRIGHTNESSDOWN, APPLE_FLAG_FKEY },
+	{ KEY_F2,	KEY_BRIGHTNESSUP,   APPLE_FLAG_FKEY },
+	{ KEY_F3,	KEY_SCALE,          APPLE_FLAG_FKEY },
+	{ KEY_F4,	KEY_DASHBOARD,      APPLE_FLAG_FKEY },
+	{ KEY_F6,	KEY_PREVIOUSSONG,   APPLE_FLAG_FKEY },
+	{ KEY_F7,	KEY_PLAYPAUSE,      APPLE_FLAG_FKEY },
+	{ KEY_F8,	KEY_NEXTSONG,       APPLE_FLAG_FKEY },
+	{ KEY_F9,	KEY_MUTE,           APPLE_FLAG_FKEY },
+	{ KEY_F10,	KEY_VOLUMEDOWN,     APPLE_FLAG_FKEY },
+	{ KEY_F11,	KEY_VOLUMEUP,       APPLE_FLAG_FKEY },
+	{ KEY_F12,	KEY_EJECTCD,        APPLE_FLAG_FKEY },
+	{ KEY_UP,	KEY_PAGEUP },
+	{ KEY_DOWN,	KEY_PAGEDOWN },
+	{ KEY_LEFT,	KEY_HOME },
+	{ KEY_RIGHT,	KEY_END },
+	{ }
+};
+
 static const struct apple_key_translation apple_fn_keys[] = {
 	{ KEY_BACKSPACE, KEY_DELETE },
 	{ KEY_ENTER,	KEY_INSERT },
@@ -146,7 +169,7 @@ static int hidinput_apple_event(struct h
 		struct hid_usage *usage, __s32 value)
 {
 	struct apple_sc *asc = hid_get_drvdata(hid);
-	const struct apple_key_translation *trans;
+	const struct apple_key_translation *trans, *table;
 
 	if (usage->code == KEY_FN) {
 		asc->fn_on = !!value;
@@ -157,10 +180,16 @@ static int hidinput_apple_event(struct h
 	if (fnmode) {
 		int do_translate;
 
-		trans = apple_find_translation((hid->product < 0x21d ||
-					hid->product >= 0x300) ?
-					powerbook_fn_keys : apple_fn_keys,
-					usage->code);
+		if (hid->product >= USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI &&
+				hid->product <= USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS)
+			table = macbookair_fn_keys;
+		else if (hid->product < 0x21d || hid->product >= 0x300)
+			table = powerbook_fn_keys;
+		else
+			table = apple_fn_keys;
+
+		trans = apple_find_translation (table, usage->code);
+
 		if (trans) {
 			if (test_bit(usage->code, asc->pressed_fn))
 				do_translate = 1;
@@ -253,8 +282,8 @@ static __u8 *apple_report_fixup(struct h
 
 	if ((asc->quirks & APPLE_RDESC_JIS) && *rsize >= 60 &&
 			rdesc[53] == 0x65 && rdesc[59] == 0x65) {
-		dev_info(&hdev->dev, "fixing up MacBook JIS keyboard report "
-				"descriptor\n");
+		hid_info(hdev,
+			 "fixing up MacBook JIS keyboard report descriptor\n");
 		rdesc[53] = rdesc[59] = 0xe7;
 	}
 	return rdesc;
@@ -324,7 +353,7 @@ static int apple_probe(struct hid_device
 
 	asc = kzalloc(sizeof(*asc), GFP_KERNEL);
 	if (asc == NULL) {
-		dev_err(&hdev->dev, "can't alloc apple descriptor\n");
+		hid_err(hdev, "can't alloc apple descriptor\n");
 		return -ENOMEM;
 	}
 
@@ -334,7 +363,7 @@ static int apple_probe(struct hid_device
 
 	ret = hid_parse(hdev);
 	if (ret) {
-		dev_err(&hdev->dev, "parse failed\n");
+		hid_err(hdev, "parse failed\n");
 		goto err_free;
 	}
 
@@ -345,7 +374,7 @@ static int apple_probe(struct hid_device
 
 	ret = hid_hw_start(hdev, connect_mask);
 	if (ret) {
-		dev_err(&hdev->dev, "hw start failed\n");
+		hid_err(hdev, "hw start failed\n");
 		goto err_free;
 	}
 
@@ -440,6 +469,18 @@ 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_WELLSPRING3_JIS),
 		.driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI),
+		.driver_data = APPLE_HAS_FN },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4_ISO),
+		.driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4_JIS),
+		.driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI),
+		.driver_data = APPLE_HAS_FN },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO),
+		.driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_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),
@@ -473,7 +514,7 @@ static int __init apple_init(void)
 
 	ret = hid_register_driver(&apple_driver);
 	if (ret)
-		printk(KERN_ERR "can't register apple driver\n");
+		pr_err("can't register apple driver\n");
 
 	return ret;
 }
diff -druNp linux-libre-2.6.37-gnu1/drivers/hid/hid-axff.c linux-libre-2.6.38-gnu1/drivers/hid/hid-axff.c
--- linux-libre-2.6.37-gnu1/drivers/hid/hid-axff.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hid/hid-axff.c	2011-03-14 21:20:32.000000000 -0400
@@ -73,14 +73,14 @@ static int axff_init(struct hid_device *
 	int error;
 
 	if (list_empty(report_list)) {
-		dev_err(&hid->dev, "no output reports found\n");
+		hid_err(hid, "no output reports found\n");
 		return -ENODEV;
 	}
 
 	report = list_first_entry(report_list, struct hid_report, list);
 
 	if (report->maxfield < 4) {
-		dev_err(&hid->dev, "no fields in the report: %d\n", report->maxfield);
+		hid_err(hid, "no fields in the report: %d\n", report->maxfield);
 		return -ENODEV;
 	}
 
@@ -101,7 +101,7 @@ static int axff_init(struct hid_device *
 	axff->report->field[3]->value[0] = 0x00;
 	usbhid_submit_report(hid, axff->report, USB_DIR_OUT);
 
-	dev_info(&hid->dev, "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;
 
@@ -114,17 +114,17 @@ static int ax_probe(struct hid_device *h
 {
 	int error;
 
-	dev_dbg(&hdev->dev, "ACRUX HID hardware probe...");
+	dev_dbg(&hdev->dev, "ACRUX HID hardware probe...\n");
 
 	error = hid_parse(hdev);
 	if (error) {
-		dev_err(&hdev->dev, "parse failed\n");
+		hid_err(hdev, "parse failed\n");
 		return error;
 	}
 
 	error = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF);
 	if (error) {
-		dev_err(&hdev->dev, "hw start failed\n");
+		hid_err(hdev, "hw start failed\n");
 		return error;
 	}
 
@@ -134,7 +134,7 @@ static int ax_probe(struct hid_device *h
 		 * Do not fail device initialization completely as device
 		 * may still be partially operable, just warn.
 		 */
-		dev_warn(&hdev->dev,
+		hid_warn(hdev,
 			 "Failed to enable force feedback support, error: %d\n",
 			 error);
 	}
diff -druNp linux-libre-2.6.37-gnu1/drivers/hid/hid-belkin.c linux-libre-2.6.38-gnu1/drivers/hid/hid-belkin.c
--- linux-libre-2.6.37-gnu1/drivers/hid/hid-belkin.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hid/hid-belkin.c	2011-03-14 21:20:32.000000000 -0400
@@ -56,14 +56,14 @@ static int belkin_probe(struct hid_devic
 
 	ret = hid_parse(hdev);
 	if (ret) {
-		dev_err(&hdev->dev, "parse failed\n");
+		hid_err(hdev, "parse failed\n");
 		goto err_free;
 	}
 
 	ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT |
 		((quirks & BELKIN_HIDDEV) ? HID_CONNECT_HIDDEV_FORCE : 0));
 	if (ret) {
-		dev_err(&hdev->dev, "hw start failed\n");
+		hid_err(hdev, "hw start failed\n");
 		goto err_free;
 	}
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/hid/hid-cando.c linux-libre-2.6.38-gnu1/drivers/hid/hid-cando.c
--- linux-libre-2.6.37-gnu1/drivers/hid/hid-cando.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hid/hid-cando.c	2011-03-14 21:20:32.000000000 -0400
@@ -207,7 +207,7 @@ static int cando_probe(struct hid_device
 
 	td = kmalloc(sizeof(struct cando_data), GFP_KERNEL);
 	if (!td) {
-		dev_err(&hdev->dev, "cannot allocate Cando Touch data\n");
+		hid_err(hdev, "cannot allocate Cando Touch data\n");
 		return -ENOMEM;
 	}
 	hid_set_drvdata(hdev, td);
@@ -236,6 +236,8 @@ static const struct hid_device_id cando_
 	{ HID_USB_DEVICE(USB_VENDOR_ID_CANDO,
 			USB_DEVICE_ID_CANDO_MULTI_TOUCH) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_CANDO,
+			USB_DEVICE_ID_CANDO_MULTI_TOUCH_10_1) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_CANDO,
 			USB_DEVICE_ID_CANDO_MULTI_TOUCH_11_6) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_CANDO,
 		USB_DEVICE_ID_CANDO_MULTI_TOUCH_15_6) },
diff -druNp linux-libre-2.6.37-gnu1/drivers/hid/hid-cherry.c linux-libre-2.6.38-gnu1/drivers/hid/hid-cherry.c
--- linux-libre-2.6.37-gnu1/drivers/hid/hid-cherry.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hid/hid-cherry.c	2011-03-14 21:20:32.000000000 -0400
@@ -30,8 +30,7 @@ static __u8 *ch_report_fixup(struct hid_
 		unsigned int *rsize)
 {
 	if (*rsize >= 17 && rdesc[11] == 0x3c && rdesc[12] == 0x02) {
-		dev_info(&hdev->dev, "fixing up Cherry Cymotion report "
-				"descriptor\n");
+		hid_info(hdev, "fixing up Cherry Cymotion report descriptor\n");
 		rdesc[11] = rdesc[16] = 0xff;
 		rdesc[12] = rdesc[17] = 0x03;
 	}
diff -druNp linux-libre-2.6.37-gnu1/drivers/hid/hid-core.c linux-libre-2.6.38-gnu1/drivers/hid/hid-core.c
--- linux-libre-2.6.37-gnu1/drivers/hid/hid-core.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hid/hid-core.c	2011-03-14 21:20:32.000000000 -0400
@@ -14,6 +14,8 @@
  * any later version.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/init.h>
@@ -59,7 +61,8 @@ struct hid_report *hid_register_report(s
 	if (report_enum->report_id_hash[id])
 		return report_enum->report_id_hash[id];
 
-	if (!(report = kzalloc(sizeof(struct hid_report), GFP_KERNEL)))
+	report = kzalloc(sizeof(struct hid_report), GFP_KERNEL);
+	if (!report)
 		return NULL;
 
 	if (id != 0)
@@ -90,8 +93,11 @@ static struct hid_field *hid_register_fi
 		return NULL;
 	}
 
-	if (!(field = kzalloc(sizeof(struct hid_field) + usages * sizeof(struct hid_usage)
-		+ values * sizeof(unsigned), GFP_KERNEL))) return NULL;
+	field = kzalloc((sizeof(struct hid_field) +
+			 usages * sizeof(struct hid_usage) +
+			 values * sizeof(unsigned)), GFP_KERNEL);
+	if (!field)
+		return NULL;
 
 	field->index = report->maxfield++;
 	report->field[field->index] = field;
@@ -172,10 +178,14 @@ static int close_collection(struct hid_p
 
 static unsigned hid_lookup_collection(struct hid_parser *parser, unsigned type)
 {
+	struct hid_collection *collection = parser->device->collection;
 	int n;
-	for (n = parser->collection_stack_ptr - 1; n >= 0; n--)
-		if (parser->device->collection[parser->collection_stack[n]].type == type)
-			return parser->device->collection[parser->collection_stack[n]].usage;
+
+	for (n = parser->collection_stack_ptr - 1; n >= 0; n--) {
+		unsigned index = parser->collection_stack[n];
+		if (collection[index].type == type)
+			return collection[index].usage;
+	}
 	return 0; /* we know nothing about this usage type */
 }
 
@@ -209,7 +219,8 @@ static int hid_add_field(struct hid_pars
 	unsigned offset;
 	int i;
 
-	if (!(report = hid_register_report(parser->device, report_type, parser->global.report_id))) {
+	report = hid_register_report(parser->device, report_type, parser->global.report_id);
+	if (!report) {
 		dbg_hid("hid_register_report failed\n");
 		return -1;
 	}
@@ -227,7 +238,8 @@ static int hid_add_field(struct hid_pars
 
 	usages = max_t(int, parser->local.usage_index, parser->global.report_count);
 
-	if ((field = hid_register_field(report, usages, parser->global.report_count)) == NULL)
+	field = hid_register_field(report, usages, parser->global.report_count);
+	if (!field)
 		return 0;
 
 	field->physical = hid_lookup_collection(parser, HID_COLLECTION_PHYSICAL);
@@ -652,13 +664,12 @@ int hid_parse_report(struct hid_device *
 		return -ENOMEM;
 	device->rsize = size;
 
-	parser = vmalloc(sizeof(struct hid_parser));
+	parser = vzalloc(sizeof(struct hid_parser));
 	if (!parser) {
 		ret = -ENOMEM;
 		goto err;
 	}
 
-	memset(parser, 0, sizeof(struct hid_parser));
 	parser->device = device;
 
 	end = start + size;
@@ -672,7 +683,8 @@ int hid_parse_report(struct hid_device *
 
 		if (dispatch_type[item.type](parser, &item)) {
 			dbg_hid("item %u %u %u %u parsing failed\n",
-				item.format, (unsigned)item.size, (unsigned)item.type, (unsigned)item.tag);
+				item.format, (unsigned)item.size,
+				(unsigned)item.type, (unsigned)item.tag);
 			goto err;
 		}
 
@@ -737,13 +749,14 @@ static u32 s32ton(__s32 value, unsigned
  * Search linux-kernel and linux-usb-devel archives for "hid-core extract".
  */
 
-static __inline__ __u32 extract(__u8 *report, unsigned offset, unsigned n)
+static __u32 extract(const struct hid_device *hid, __u8 *report,
+		     unsigned offset, unsigned n)
 {
 	u64 x;
 
 	if (n > 32)
-		printk(KERN_WARNING "HID: extract() called with n (%d) > 32! (%s)\n",
-				n, current->comm);
+		hid_warn(hid, "extract() called with n (%d) > 32! (%s)\n",
+			 n, current->comm);
 
 	report += offset >> 3;  /* adjust byte index */
 	offset &= 7;            /* now only need bit offset into one byte */
@@ -760,18 +773,19 @@ static __inline__ __u32 extract(__u8 *re
  * endianness of register values by considering a register
  * a "cached" copy of the little endiad bit stream.
  */
-static __inline__ void implement(__u8 *report, unsigned offset, unsigned n, __u32 value)
+static void implement(const struct hid_device *hid, __u8 *report,
+		      unsigned offset, unsigned n, __u32 value)
 {
 	u64 x;
 	u64 m = (1ULL << n) - 1;
 
 	if (n > 32)
-		printk(KERN_WARNING "HID: implement() called with n (%d) > 32! (%s)\n",
-				n, current->comm);
+		hid_warn(hid, "%s() called with n (%d) > 32! (%s)\n",
+			 __func__, n, current->comm);
 
 	if (value > m)
-		printk(KERN_WARNING "HID: implement() called with too large value %d! (%s)\n",
-				value, current->comm);
+		hid_warn(hid, "%s() called with too large value %d! (%s)\n",
+			 __func__, value, current->comm);
 	WARN_ON(value > m);
 	value &= m;
 
@@ -788,7 +802,7 @@ static __inline__ void implement(__u8 *r
  * Search an array for a value.
  */
 
-static __inline__ int search(__s32 *array, __s32 value, unsigned n)
+static int search(__s32 *array, __s32 value, unsigned n)
 {
 	while (n--) {
 		if (*array++ == value)
@@ -887,18 +901,22 @@ static void hid_input_field(struct hid_d
 	__s32 max = field->logical_maximum;
 	__s32 *value;
 
-	if (!(value = kmalloc(sizeof(__s32) * count, GFP_ATOMIC)))
+	value = kmalloc(sizeof(__s32) * count, GFP_ATOMIC);
+	if (!value)
 		return;
 
 	for (n = 0; n < count; n++) {
 
-			value[n] = min < 0 ? snto32(extract(data, offset + n * size, size), size) :
-						    extract(data, offset + n * size, size);
+		value[n] = min < 0 ?
+			snto32(extract(hid, data, offset + n * size, size),
+			       size) :
+			extract(hid, data, offset + n * size, size);
 
-			if (!(field->flags & HID_MAIN_ITEM_VARIABLE) /* Ignore report if ErrorRollOver */
-			    && value[n] >= min && value[n] <= max
-			    && field->usage[value[n] - min].hid == HID_UP_KEYBOARD + 1)
-				goto exit;
+		/* Ignore report if ErrorRollOver */
+		if (!(field->flags & HID_MAIN_ITEM_VARIABLE) &&
+		    value[n] >= min && value[n] <= max &&
+		    field->usage[value[n] - min].hid == HID_UP_KEYBOARD + 1)
+			goto exit;
 	}
 
 	for (n = 0; n < count; n++) {
@@ -928,7 +946,8 @@ exit:
  * Output the field into the report.
  */
 
-static void hid_output_field(struct hid_field *field, __u8 *data)
+static void hid_output_field(const struct hid_device *hid,
+			     struct hid_field *field, __u8 *data)
 {
 	unsigned count = field->report_count;
 	unsigned offset = field->report_offset;
@@ -937,9 +956,11 @@ static void hid_output_field(struct hid_
 
 	for (n = 0; n < count; n++) {
 		if (field->logical_minimum < 0)	/* signed values */
-			implement(data, offset + n * size, size, s32ton(field->value[n], size));
+			implement(hid, data, offset + n * size, size,
+				  s32ton(field->value[n], size));
 		else				/* unsigned values */
-			implement(data, offset + n * size, size, field->value[n]);
+			implement(hid, data, offset + n * size, size,
+				  field->value[n]);
 	}
 }
 
@@ -956,7 +977,7 @@ void hid_output_report(struct hid_report
 
 	memset(data, 0, ((report->size - 1) >> 3) + 1);
 	for (n = 0; n < report->maxfield; n++)
-		hid_output_field(report->field[n], data);
+		hid_output_field(report->device, report->field[n], data);
 }
 EXPORT_SYMBOL_GPL(hid_output_report);
 
@@ -1169,8 +1190,7 @@ int hid_connect(struct hid_device *hdev,
 		hdev->claimed |= HID_CLAIMED_HIDRAW;
 
 	if (!hdev->claimed) {
-		dev_err(&hdev->dev, "claimed by neither input, hiddev nor "
-				"hidraw\n");
+		hid_err(hdev, "claimed by neither input, hiddev nor hidraw\n");
 		return -ENODEV;
 	}
 
@@ -1210,9 +1230,9 @@ int hid_connect(struct hid_device *hdev,
 		bus = "<UNKNOWN>";
 	}
 
-	dev_info(&hdev->dev, "%s: %s HID v%x.%02x %s [%s] on %s\n",
-			buf, bus, hdev->version >> 8, hdev->version & 0xff,
-			type, hdev->name, hdev->phys);
+	hid_info(hdev, "%s: %s HID v%x.%02x %s [%s] on %s\n",
+		 buf, bus, hdev->version >> 8, hdev->version & 0xff,
+		 type, hdev->name, hdev->phys);
 
 	return 0;
 }
@@ -1230,7 +1250,7 @@ void hid_disconnect(struct hid_device *h
 EXPORT_SYMBOL_GPL(hid_disconnect);
 
 /* a list of devices for which there is a specialized driver on HID bus */
-static const struct hid_device_id hid_blacklist[] = {
+static const struct hid_device_id hid_have_special_driver[] = {
 	{ HID_USB_DEVICE(USB_VENDOR_ID_3M, USB_DEVICE_ID_3M1968) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_3M, USB_DEVICE_ID_3M2256) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU) },
@@ -1276,6 +1296,12 @@ static const struct hid_device_id hid_bl
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ISO) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_JIS) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4_ISO) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4_JIS) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_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) },
@@ -1286,29 +1312,39 @@ static const struct hid_device_id hid_bl
 	{ HID_USB_DEVICE(USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE_2) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_PIXCIR_MULTI_TOUCH) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH_10_1) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH_11_6) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH_15_6) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION_SOLAR) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_TACTICAL_PAD) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_CREATIVELABS, USB_DEVICE_ID_PRODIKEYS_PCMIDI) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_1) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_2) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_3) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_TRUETOUCH) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0006) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH1) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH2) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH3) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH4) },
 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_BM084) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_EMS, USB_DEVICE_ID_EMS_TRIO_LINKER_PLUS_II) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_EZKEY, USB_DEVICE_ID_BTC_8193) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PCS_ADAPTOR) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, USB_DEVICE_ID_GENERAL_TOUCH_WIN7_TWOFINGERS) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0003) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0012) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE) },
 	{ 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_KENSINGTON, USB_DEVICE_ID_KS_SLIMBLADE) },
 	{ 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) },
@@ -1369,6 +1405,7 @@ static const struct hid_device_id hid_bl
 	{ 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) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONEPLUS) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_PYRA_WIRED) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_WIRELESS_KBD_MOUSE) },
@@ -1390,6 +1427,7 @@ static const struct hid_device_id hid_bl
 	{ HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED, USB_DEVICE_ID_TOPSEED_CYBERLINK) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED2, USB_DEVICE_ID_TOPSEED2_RF_COMBO) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_TWINHAN, USB_DEVICE_ID_TWINHAN_IR_REMOTE) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_TOUCHSCREEN_MOSART) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_PF1209) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U) },
@@ -1496,9 +1534,9 @@ static int hid_bus_match(struct device *
 	if (!hid_match_device(hdev, hdrv))
 		return 0;
 
-	/* generic wants all non-blacklisted */
+	/* generic wants all that don't have specialized driver */
 	if (!strncmp(hdrv->name, "generic-", 8))
-		return !hid_match_id(hdev, hid_blacklist);
+		return !hid_match_id(hdev, hid_have_special_driver);
 
 	return 1;
 }
@@ -1604,10 +1642,10 @@ static const struct hid_device_id hid_ig
 	{ HID_USB_DEVICE(USB_VENDOR_ID_DEALEXTREAME, USB_DEVICE_ID_DEALEXTREAME_RADIO_SI4701) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EARTHMATE) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EM_LT20) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_DREAM_CHEEKY, 0x0004) },
 	{ 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) },
@@ -1757,6 +1795,12 @@ static const struct hid_device_id hid_mo
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ISO) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_JIS) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4_ISO) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4_JIS) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_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) },
 	{ }
@@ -1948,12 +1992,12 @@ static int __init hid_init(void)
 	int ret;
 
 	if (hid_debug)
-		printk(KERN_WARNING "HID: hid_debug is now used solely for parser and driver debugging.\n"
-				"HID: debugfs is now used for inspecting the device (report descriptor, reports)\n");
+		pr_warn("hid_debug is now used solely for parser and driver debugging.\n"
+			"debugfs is now used for inspecting the device (report descriptor, reports)\n");
 
 	ret = bus_register(&hid_bus_type);
 	if (ret) {
-		printk(KERN_ERR "HID: can't register hid bus\n");
+		pr_err("can't register hid bus\n");
 		goto err;
 	}
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/hid/hid-cypress.c linux-libre-2.6.38-gnu1/drivers/hid/hid-cypress.c
--- linux-libre-2.6.37-gnu1/drivers/hid/hid-cypress.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hid/hid-cypress.c	2011-03-14 21:20:32.000000000 -0400
@@ -107,13 +107,13 @@ static int cp_probe(struct hid_device *h
 
 	ret = hid_parse(hdev);
 	if (ret) {
-		dev_err(&hdev->dev, "parse failed\n");
+		hid_err(hdev, "parse failed\n");
 		goto err_free;
 	}
 
 	ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
 	if (ret) {
-		dev_err(&hdev->dev, "hw start failed\n");
+		hid_err(hdev, "hw start failed\n");
 		goto err_free;
 	}
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/hid/hid-debug.c linux-libre-2.6.38-gnu1/drivers/hid/hid-debug.c
--- linux-libre-2.6.37-gnu1/drivers/hid/hid-debug.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hid/hid-debug.c	2011-03-14 21:20:32.000000000 -0400
@@ -26,6 +26,8 @@
  * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/debugfs.h>
 #include <linux/seq_file.h>
 #include <linux/sched.h>
@@ -393,7 +395,7 @@ char *hid_resolv_usage(unsigned usage, s
 
 	buf = resolv_usage_page(usage >> 16, f);
 	if (IS_ERR(buf)) {
-		printk(KERN_ERR "error allocating HID debug buffer\n");
+		pr_err("error allocating HID debug buffer\n");
 		return NULL;
 	}
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/hid/hid-drff.c linux-libre-2.6.38-gnu1/drivers/hid/hid-drff.c
--- linux-libre-2.6.37-gnu1/drivers/hid/hid-drff.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hid/hid-drff.c	2011-03-14 21:20:32.000000000 -0400
@@ -96,18 +96,18 @@ static int drff_init(struct hid_device *
 	int error;
 
 	if (list_empty(report_list)) {
-		dev_err(&hid->dev, "no output reports found\n");
+		hid_err(hid, "no output reports found\n");
 		return -ENODEV;
 	}
 
 	report = list_first_entry(report_list, struct hid_report, list);
 	if (report->maxfield < 1) {
-		dev_err(&hid->dev, "no fields in the report\n");
+		hid_err(hid, "no fields in the report\n");
 		return -ENODEV;
 	}
 
 	if (report->field[0]->report_count < 7) {
-		dev_err(&hid->dev, "not enough values in the field\n");
+		hid_err(hid, "not enough values in the field\n");
 		return -ENODEV;
 	}
 
@@ -133,8 +133,8 @@ static int drff_init(struct hid_device *
 	drff->report->field[0]->value[6] = 0x00;
 	usbhid_submit_report(hid, drff->report, USB_DIR_OUT);
 
-	dev_info(&hid->dev, "Force Feedback for DragonRise Inc. game "
-	       "controllers by Richard Walmsley <richwalm@gmail.com>\n");
+	hid_info(hid, "Force Feedback for DragonRise Inc. "
+		 "game controllers by Richard Walmsley <richwalm@gmail.com>\n");
 
 	return 0;
 }
@@ -153,13 +153,13 @@ static int dr_probe(struct hid_device *h
 
 	ret = hid_parse(hdev);
 	if (ret) {
-		dev_err(&hdev->dev, "parse failed\n");
+		hid_err(hdev, "parse failed\n");
 		goto err;
 	}
 
 	ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF);
 	if (ret) {
-		dev_err(&hdev->dev, "hw start failed\n");
+		hid_err(hdev, "hw start failed\n");
 		goto err;
 	}
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/hid/hid-egalax.c linux-libre-2.6.38-gnu1/drivers/hid/hid-egalax.c
--- linux-libre-2.6.37-gnu1/drivers/hid/hid-egalax.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hid/hid-egalax.c	2011-03-14 21:20:32.000000000 -0400
@@ -2,6 +2,8 @@
  *  HID driver for eGalax dual-touch panels
  *
  *  Copyright (c) 2010 Stephane Chatty <chatty@enac.fr>
+ *  Copyright (c) 2010 Henrik Rydberg <rydberg@euromail.se>
+ *  Copyright (c) 2010 Canonical, Ltd.
  *
  */
 
@@ -16,6 +18,7 @@
 #include <linux/hid.h>
 #include <linux/module.h>
 #include <linux/usb.h>
+#include <linux/input/mt.h>
 #include <linux/slab.h>
 #include "usbhid/usbhid.h"
 
@@ -25,38 +28,53 @@ MODULE_LICENSE("GPL");
 
 #include "hid-ids.h"
 
+#define MAX_SLOTS		2
+
+/* estimated signal-to-noise ratios */
+#define SN_MOVE			4096
+#define SN_PRESSURE		32
+
 struct egalax_data {
-	__u16 x, y, z;
-	__u8 id;
-	bool first;		/* is this the first finger in the frame? */
-	bool valid;		/* valid finger data, or just placeholder? */
-	bool activity;		/* at least one active finger previously? */
-	__u16 lastx, lasty, lastz;	/* latest valid (x, y, z) in the frame */
+	int valid;
+	int slot;
+	int touch;
+	int x, y, z;
 };
 
+static void set_abs(struct input_dev *input, unsigned int code,
+		    struct hid_field *field, int snratio)
+{
+	int fmin = field->logical_minimum;
+	int fmax = field->logical_maximum;
+	int fuzz = snratio ? (fmax - fmin) / snratio : 0;
+	input_set_abs_params(input, code, fmin, fmax, fuzz, 0);
+}
+
 static int egalax_input_mapping(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;
+
 	switch (usage->hid & HID_USAGE_PAGE) {
 
 	case HID_UP_GENDESK:
 		switch (usage->hid) {
 		case HID_GD_X:
+			field->logical_maximum = 32760;
 			hid_map_usage(hi, usage, bit, max,
 					EV_ABS, ABS_MT_POSITION_X);
+			set_abs(input, ABS_MT_POSITION_X, field, SN_MOVE);
 			/* touchscreen emulation */
-			input_set_abs_params(hi->input, ABS_X,
-						field->logical_minimum,
-						field->logical_maximum, 0, 0);
+			set_abs(input, ABS_X, field, SN_MOVE);
 			return 1;
 		case HID_GD_Y:
+			field->logical_maximum = 32760;
 			hid_map_usage(hi, usage, bit, max,
 					EV_ABS, ABS_MT_POSITION_Y);
+			set_abs(input, ABS_MT_POSITION_Y, field, SN_MOVE);
 			/* touchscreen emulation */
-			input_set_abs_params(hi->input, ABS_Y,
-						field->logical_minimum,
-						field->logical_maximum, 0, 0);
+			set_abs(input, ABS_Y, field, SN_MOVE);
 			return 1;
 		}
 		return 0;
@@ -66,6 +84,7 @@ static int egalax_input_mapping(struct h
 		case HID_DG_TIPSWITCH:
 			/* touchscreen emulation */
 			hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH);
+			input_set_capability(input, EV_KEY, BTN_TOUCH);
 			return 1;
 		case HID_DG_INRANGE:
 		case HID_DG_CONFIDENCE:
@@ -73,16 +92,15 @@ static int egalax_input_mapping(struct h
 		case HID_DG_CONTACTMAX:
 			return -1;
 		case HID_DG_CONTACTID:
-			hid_map_usage(hi, usage, bit, max,
-					EV_ABS, ABS_MT_TRACKING_ID);
+			input_mt_init_slots(input, MAX_SLOTS);
 			return 1;
 		case HID_DG_TIPPRESSURE:
+			field->logical_minimum = 0;
 			hid_map_usage(hi, usage, bit, max,
 					EV_ABS, ABS_MT_PRESSURE);
+			set_abs(input, ABS_MT_PRESSURE, field, SN_PRESSURE);
 			/* touchscreen emulation */
-			input_set_abs_params(hi->input, ABS_PRESSURE,
-						field->logical_minimum,
-						field->logical_maximum, 0, 0);
+			set_abs(input, ABS_PRESSURE, field, SN_PRESSURE);
 			return 1;
 		}
 		return 0;
@@ -96,10 +114,10 @@ static int egalax_input_mapped(struct hi
 		struct hid_field *field, struct hid_usage *usage,
 		unsigned long **bit, int *max)
 {
+	/* tell hid-input to skip setup of these event types */
 	if (usage->type == EV_KEY || usage->type == EV_ABS)
-		clear_bit(usage->code, *bit);
-
-	return 0;
+		set_bit(usage->type, hi->input->evbit);
+	return -1;
 }
 
 /*
@@ -108,58 +126,16 @@ static int egalax_input_mapped(struct hi
  */
 static void egalax_filter_event(struct egalax_data *td, struct input_dev *input)
 {
-	td->first = !td->first; /* touchscreen emulation */
-
-	if (td->valid) {
-		/* emit multitouch events */
-		input_event(input, EV_ABS, ABS_MT_TRACKING_ID, td->id);
-		input_event(input, EV_ABS, ABS_MT_POSITION_X, td->x >> 3);
-		input_event(input, EV_ABS, ABS_MT_POSITION_Y, td->y >> 3);
+	input_mt_slot(input, td->slot);
+	input_mt_report_slot_state(input, MT_TOOL_FINGER, td->touch);
+	if (td->touch) {
+		input_event(input, EV_ABS, ABS_MT_POSITION_X, td->x);
+		input_event(input, EV_ABS, ABS_MT_POSITION_Y, td->y);
 		input_event(input, EV_ABS, ABS_MT_PRESSURE, td->z);
-
-		input_mt_sync(input);
-
-		/*
-		 * touchscreen emulation: store (x, y) as
-		 * the last valid values in this frame
-		 */
-		td->lastx = td->x;
-		td->lasty = td->y;
-		td->lastz = td->z;
-	}
-
-	/*
-	 * touchscreen emulation: if this is the second finger and at least
-	 * one in this frame is valid, the latest valid in the frame is
-	 * the oldest on the panel, the one we want for single touch
-	 */
-	if (!td->first && td->activity) {
-		input_event(input, EV_ABS, ABS_X, td->lastx >> 3);
-		input_event(input, EV_ABS, ABS_Y, td->lasty >> 3);
- 		input_event(input, EV_ABS, ABS_PRESSURE, td->lastz);
-	}
-
-	if (!td->valid) {
-		/*
-		 * touchscreen emulation: if the first finger is invalid
-		 * and there previously was finger activity, this is a release
-		 */ 
-		if (td->first && td->activity) {
-			input_event(input, EV_KEY, BTN_TOUCH, 0);
-			td->activity = false;
-		}
-		return;
-	}
-
-
-	/* touchscreen emulation: if no previous activity, emit touch event */
-	if (!td->activity) {
-		input_event(input, EV_KEY, BTN_TOUCH, 1);
-		td->activity = true;
 	}
+	input_mt_report_pointer_emulation(input, true);
 }
 
-
 static int egalax_event(struct hid_device *hid, struct hid_field *field,
 				struct hid_usage *usage, __s32 value)
 {
@@ -169,25 +145,26 @@ static int egalax_event(struct hid_devic
 	 * uses a standard parallel multitouch protocol (product ID ==
 	 * 48xx).  The second is capacitive and uses an unusual "serial"
 	 * protocol with a different message for each multitouch finger
-	 * (product ID == 72xx).  We do not yet generate a correct event
-	 * sequence for the capacitive/serial protocol.
+	 * (product ID == 72xx).
 	 */
 	if (hid->claimed & HID_CLAIMED_INPUT) {
 		struct input_dev *input = field->hidinput->input;
 
 		switch (usage->hid) {
 		case HID_DG_INRANGE:
+			td->valid = value;
+			break;
 		case HID_DG_CONFIDENCE:
 			/* avoid interference from generic hidinput handling */
 			break;
 		case HID_DG_TIPSWITCH:
-			td->valid = value;
+			td->touch = value;
 			break;
 		case HID_DG_TIPPRESSURE:
 			td->z = value;
 			break;
 		case HID_DG_CONTACTID:
-			td->id = value;
+			td->slot = clamp_val(value, 0, MAX_SLOTS - 1);
 			break;
 		case HID_GD_X:
 			td->x = value;
@@ -195,11 +172,11 @@ static int egalax_event(struct hid_devic
 		case HID_GD_Y:
 			td->y = value;
 			/* this is the last field in a finger */
-			egalax_filter_event(td, input);
+			if (td->valid)
+				egalax_filter_event(td, input);
 			break;
 		case HID_DG_CONTACTCOUNT:
 			/* touch emulation: this is the last field in a frame */
-			td->first = false;
 			break;
 
 		default:
@@ -223,7 +200,7 @@ static int egalax_probe(struct hid_devic
 
 	td = kzalloc(sizeof(struct egalax_data), GFP_KERNEL);
 	if (!td) {
-		dev_err(&hdev->dev, "cannot allocate eGalax data\n");
+		hid_err(hdev, "cannot allocate eGalax data\n");
 		return -ENOMEM;
 	}
 	hid_set_drvdata(hdev, td);
@@ -261,6 +238,12 @@ static const struct hid_device_id egalax
 			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
 			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH1) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
+			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH2) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
+			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH3) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
+			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH4) },
 	{ }
 };
 MODULE_DEVICE_TABLE(hid, egalax_devices);
diff -druNp linux-libre-2.6.37-gnu1/drivers/hid/hid-elecom.c linux-libre-2.6.38-gnu1/drivers/hid/hid-elecom.c
--- linux-libre-2.6.37-gnu1/drivers/hid/hid-elecom.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hid/hid-elecom.c	2011-03-14 21:20:32.000000000 -0400
@@ -24,8 +24,7 @@ static __u8 *elecom_report_fixup(struct
 		unsigned int *rsize)
 {
 	if (*rsize >= 48 && rdesc[46] == 0x05 && rdesc[47] == 0x0c) {
-		dev_info(&hdev->dev, "Fixing up Elecom BM084 "
-				"report descriptor.\n");
+		hid_info(hdev, "Fixing up Elecom BM084 report descriptor\n");
 		rdesc[47] = 0x00;
 	}
     return rdesc;
diff -druNp linux-libre-2.6.37-gnu1/drivers/hid/hid-emsff.c linux-libre-2.6.38-gnu1/drivers/hid/hid-emsff.c
--- linux-libre-2.6.37-gnu1/drivers/hid/hid-emsff.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hid/hid-emsff.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,161 @@
+/*
+ *  Force feedback support for EMS Trio Linker Plus II
+ *
+ *  Copyright (c) 2010 Ignaz Forster <ignaz.forster@gmx.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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include <linux/hid.h>
+#include <linux/input.h>
+#include <linux/usb.h>
+
+#include "hid-ids.h"
+#include "usbhid/usbhid.h"
+
+struct emsff_device {
+	struct hid_report *report;
+};
+
+static int emsff_play(struct input_dev *dev, void *data,
+			 struct ff_effect *effect)
+{
+	struct hid_device *hid = input_get_drvdata(dev);
+	struct emsff_device *emsff = data;
+	int weak, strong;
+
+	weak = effect->u.rumble.weak_magnitude;
+	strong = effect->u.rumble.strong_magnitude;
+
+	dbg_hid("called with 0x%04x 0x%04x\n", strong, weak);
+
+	weak = weak * 0xff / 0xffff;
+	strong = strong * 0xff / 0xffff;
+
+	emsff->report->field[0]->value[1] = weak;
+	emsff->report->field[0]->value[2] = strong;
+
+	dbg_hid("running with 0x%02x 0x%02x\n", strong, weak);
+	usbhid_submit_report(hid, emsff->report, USB_DIR_OUT);
+
+	return 0;
+}
+
+static int emsff_init(struct hid_device *hid)
+{
+	struct emsff_device *emsff;
+	struct hid_report *report;
+	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 error;
+
+	if (list_empty(report_list)) {
+		hid_err(hid, "no output reports found\n");
+		return -ENODEV;
+	}
+
+	report = list_first_entry(report_list, 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 < 7) {
+		hid_err(hid, "not enough values in the field\n");
+		return -ENODEV;
+	}
+
+	emsff = kzalloc(sizeof(struct emsff_device), GFP_KERNEL);
+	if (!emsff)
+		return -ENOMEM;
+
+	set_bit(FF_RUMBLE, dev->ffbit);
+
+	error = input_ff_create_memless(dev, emsff, emsff_play);
+	if (error) {
+		kfree(emsff);
+		return error;
+	}
+
+	emsff->report = report;
+	emsff->report->field[0]->value[0] = 0x01;
+	emsff->report->field[0]->value[1] = 0x00;
+	emsff->report->field[0]->value[2] = 0x00;
+	emsff->report->field[0]->value[3] = 0x00;
+	emsff->report->field[0]->value[4] = 0x00;
+	emsff->report->field[0]->value[5] = 0x00;
+	emsff->report->field[0]->value[6] = 0x00;
+	usbhid_submit_report(hid, emsff->report, USB_DIR_OUT);
+
+	hid_info(hid, "force feedback for EMS based devices by Ignaz Forster <ignaz.forster@gmx.de>\n");
+
+	return 0;
+}
+
+static int ems_probe(struct hid_device *hdev, const struct hid_device_id *id)
+{
+	int ret;
+
+	ret = hid_parse(hdev);
+	if (ret) {
+		hid_err(hdev, "parse failed\n");
+		goto err;
+	}
+
+	ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF);
+	if (ret) {
+		hid_err(hdev, "hw start failed\n");
+		goto err;
+	}
+
+	emsff_init(hdev);
+
+	return 0;
+err:
+	return ret;
+}
+
+static const struct hid_device_id ems_devices[] = {
+	{ HID_USB_DEVICE(USB_VENDOR_ID_EMS, 0x118) },
+	{ }
+};
+MODULE_DEVICE_TABLE(hid, ems_devices);
+
+static struct hid_driver ems_driver = {
+	.name = "hkems",
+	.id_table = ems_devices,
+	.probe = ems_probe,
+};
+
+static int ems_init(void)
+{
+	return hid_register_driver(&ems_driver);
+}
+
+static void ems_exit(void)
+{
+	hid_unregister_driver(&ems_driver);
+}
+
+module_init(ems_init);
+module_exit(ems_exit);
+MODULE_LICENSE("GPL");
+
diff -druNp linux-libre-2.6.37-gnu1/drivers/hid/hid-gaff.c linux-libre-2.6.38-gnu1/drivers/hid/hid-gaff.c
--- linux-libre-2.6.37-gnu1/drivers/hid/hid-gaff.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hid/hid-gaff.c	2011-03-14 21:20:32.000000000 -0400
@@ -87,7 +87,7 @@ static int gaff_init(struct hid_device *
 	int error;
 
 	if (list_empty(report_list)) {
-		dev_err(&hid->dev, "no output reports found\n");
+		hid_err(hid, "no output reports found\n");
 		return -ENODEV;
 	}
 
@@ -95,12 +95,12 @@ static int gaff_init(struct hid_device *
 
 	report = list_entry(report_ptr, struct hid_report, list);
 	if (report->maxfield < 1) {
-		dev_err(&hid->dev, "no fields in the report\n");
+		hid_err(hid, "no fields in the report\n");
 		return -ENODEV;
 	}
 
 	if (report->field[0]->report_count < 6) {
-		dev_err(&hid->dev, "not enough values in the field\n");
+		hid_err(hid, "not enough values in the field\n");
 		return -ENODEV;
 	}
 
@@ -128,8 +128,7 @@ static int gaff_init(struct hid_device *
 
 	usbhid_submit_report(hid, gaff->report, USB_DIR_OUT);
 
-	dev_info(&hid->dev, "Force Feedback for GreenAsia 0x12"
-	       " devices by Lukasz Lubojanski <lukasz@lubojanski.info>\n");
+	hid_info(hid, "Force Feedback for GreenAsia 0x12 devices by Lukasz Lubojanski <lukasz@lubojanski.info>\n");
 
 	return 0;
 }
@@ -148,13 +147,13 @@ static int ga_probe(struct hid_device *h
 
 	ret = hid_parse(hdev);
 	if (ret) {
-		dev_err(&hdev->dev, "parse failed\n");
+		hid_err(hdev, "parse failed\n");
 		goto err;
 	}
 
 	ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF);
 	if (ret) {
-		dev_err(&hdev->dev, "hw start failed\n");
+		hid_err(hdev, "hw start failed\n");
 		goto err;
 	}
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/hid/hid-ids.h linux-libre-2.6.38-gnu1/drivers/hid/hid-ids.h
--- linux-libre-2.6.37-gnu1/drivers/hid/hid-ids.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hid/hid-ids.h	2011-03-14 21:20:32.000000000 -0400
@@ -97,6 +97,12 @@
 #define USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI	0x0236
 #define USB_DEVICE_ID_APPLE_WELLSPRING3_ISO	0x0237
 #define USB_DEVICE_ID_APPLE_WELLSPRING3_JIS	0x0238
+#define USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI	0x023f
+#define USB_DEVICE_ID_APPLE_WELLSPRING4_ISO	0x0240
+#define USB_DEVICE_ID_APPLE_WELLSPRING4_JIS	0x0241
+#define USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI	0x0242
+#define USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO	0x0243
+#define USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS	0x0244
 #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
@@ -134,7 +140,9 @@
 #define USB_DEVICE_ID_BTC_EMPREX_REMOTE_2	0x5577
 
 #define USB_VENDOR_ID_CANDO		0x2087
+#define USB_DEVICE_ID_CANDO_PIXCIR_MULTI_TOUCH 0x0703
 #define USB_DEVICE_ID_CANDO_MULTI_TOUCH	0x0a01
+#define USB_DEVICE_ID_CANDO_MULTI_TOUCH_10_1 0x0a02
 #define USB_DEVICE_ID_CANDO_MULTI_TOUCH_11_6 0x0b03
 #define USB_DEVICE_ID_CANDO_MULTI_TOUCH_15_6 0x0f01
 
@@ -156,6 +164,7 @@
 #define USB_VENDOR_ID_CHICONY		0x04f2
 #define USB_DEVICE_ID_CHICONY_TACTICAL_PAD	0x0418
 #define USB_DEVICE_ID_CHICONY_MULTI_TOUCH	0xb19d
+#define USB_DEVICE_ID_CHICONY_WIRELESS	0x0618
 
 #define USB_VENDOR_ID_CIDC		0x1677
 
@@ -179,6 +188,7 @@
 #define USB_DEVICE_ID_CYPRESS_BARCODE_1	0xde61
 #define USB_DEVICE_ID_CYPRESS_BARCODE_2	0xde64
 #define USB_DEVICE_ID_CYPRESS_BARCODE_3	0xbca1
+#define USB_DEVICE_ID_CYPRESS_TRUETOUCH	0xc001
 
 #define USB_VENDOR_ID_DEALEXTREAME	0x10c5
 #define USB_DEVICE_ID_DEALEXTREAME_RADIO_SI4701	0x819a
@@ -196,13 +206,21 @@
 #define USB_DEVICE_ID_EGALAX_TOUCHCONTROLLER	0x0001
 #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH	0x480d
 #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH1	0x720c
+#define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH2	0x72a1
+#define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH3	0x480e
+#define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH4	0x726b
 
 #define USB_VENDOR_ID_ELECOM		0x056e
 #define USB_DEVICE_ID_ELECOM_BM084	0x0061
 
+#define USB_VENDOR_ID_DREAM_CHEEKY	0x1d34
+
 #define USB_VENDOR_ID_ELO		0x04E7
 #define USB_DEVICE_ID_ELO_TS2700	0x0020
 
+#define USB_VENDOR_ID_EMS		0x2006
+#define USB_DEVICE_ID_EMS_TRIO_LINKER_PLUS_II 0x0118
+
 #define USB_VENDOR_ID_ESSENTIAL_REALITY	0x0d7f
 #define USB_DEVICE_ID_ESSENTIAL_REALITY_P5 0x0100
 
@@ -221,6 +239,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_VENDOR_ID_GLAB		0x06c2
 #define USB_DEVICE_ID_4_PHIDGETSERVO_30	0x0038
@@ -303,6 +322,9 @@
 #define USB_DEVICE_ID_HANWANG_TABLET_FIRST	0x5000
 #define USB_DEVICE_ID_HANWANG_TABLET_LAST	0x8fff
 
+#define USB_VENDOR_ID_HANVON		0x20b3
+#define USB_DEVICE_ID_HANVON_MULTITOUCH	0x0a18
+
 #define USB_VENDOR_ID_HAPP		0x078b
 #define USB_DEVICE_ID_UGCI_DRIVING	0x0010
 #define USB_DEVICE_ID_UGCI_FLYING	0x0020
@@ -475,6 +497,7 @@
 
 #define USB_VENDOR_ID_ROCCAT		0x1e7d
 #define USB_DEVICE_ID_ROCCAT_KONE	0x2ced
+#define USB_DEVICE_ID_ROCCAT_KONEPLUS	0x2d51
 #define USB_DEVICE_ID_ROCCAT_PYRA_WIRED	0x2c24
 #define USB_DEVICE_ID_ROCCAT_PYRA_WIRELESS	0x2cf6
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/hid/hid-input.c linux-libre-2.6.38-gnu1/drivers/hid/hid-input.c
--- linux-libre-2.6.37-gnu1/drivers/hid/hid-input.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hid/hid-input.c	2011-03-14 21:20:32.000000000 -0400
@@ -290,6 +290,14 @@ static void hidinput_configure_usage(str
 		goto ignore;
 	}
 
+	if (field->report_type == HID_FEATURE_REPORT) {
+		if (device->driver->feature_mapping) {
+			device->driver->feature_mapping(device, hidinput, field,
+				usage);
+		}
+		goto ignore;
+	}
+
 	if (device->driver->input_mapping) {
 		int ret = device->driver->input_mapping(device, hidinput, field,
 				usage, &bit, &max);
@@ -319,21 +327,21 @@ static void hidinput_configure_usage(str
 
 		switch (field->application) {
 		case HID_GD_MOUSE:
-		case HID_GD_POINTER:  code += 0x110; break;
+		case HID_GD_POINTER:  code += BTN_MOUSE; break;
 		case HID_GD_JOYSTICK:
 				if (code <= 0xf)
 					code += BTN_JOYSTICK;
 				else
 					code += BTN_TRIGGER_HAPPY;
 				break;
-		case HID_GD_GAMEPAD:  code += 0x130; break;
+		case HID_GD_GAMEPAD:  code += BTN_GAMEPAD; break;
 		default:
 			switch (field->physical) {
 			case HID_GD_MOUSE:
-			case HID_GD_POINTER:  code += 0x110; break;
-			case HID_GD_JOYSTICK: code += 0x120; break;
-			case HID_GD_GAMEPAD:  code += 0x130; break;
-			default:              code += 0x100;
+			case HID_GD_POINTER:  code += BTN_MOUSE; break;
+			case HID_GD_JOYSTICK: code += BTN_JOYSTICK; break;
+			case HID_GD_GAMEPAD:  code += BTN_GAMEPAD; break;
+			default:              code += BTN_MISC;
 			}
 		}
 
@@ -817,14 +825,14 @@ static int hidinput_open(struct input_de
 {
 	struct hid_device *hid = input_get_drvdata(dev);
 
-	return hid->ll_driver->open(hid);
+	return hid_hw_open(hid);
 }
 
 static void hidinput_close(struct input_dev *dev)
 {
 	struct hid_device *hid = input_get_drvdata(dev);
 
-	hid->ll_driver->close(hid);
+	hid_hw_close(hid);
 }
 
 /*
@@ -839,7 +847,6 @@ int hidinput_connect(struct hid_device *
 	struct hid_input *hidinput = NULL;
 	struct input_dev *input_dev;
 	int i, j, k;
-	int max_report_type = HID_OUTPUT_REPORT;
 
 	INIT_LIST_HEAD(&hid->inputs);
 
@@ -856,10 +863,11 @@ int hidinput_connect(struct hid_device *
 			return -1;
 	}
 
-	if (hid->quirks & HID_QUIRK_SKIP_OUTPUT_REPORTS)
-		max_report_type = HID_INPUT_REPORT;
+	for (k = HID_INPUT_REPORT; k <= HID_FEATURE_REPORT; k++) {
+		if (k == HID_OUTPUT_REPORT &&
+			hid->quirks & HID_QUIRK_SKIP_OUTPUT_REPORTS)
+			continue;
 
-	for (k = HID_INPUT_REPORT; k <= max_report_type; k++)
 		list_for_each_entry(report, &hid->report_enum[k].report_list, list) {
 
 			if (!report->maxfield)
@@ -871,7 +879,7 @@ int hidinput_connect(struct hid_device *
 				if (!hidinput || !input_dev) {
 					kfree(hidinput);
 					input_free_device(input_dev);
-					err_hid("Out of memory during hid input probe");
+					hid_err(hid, "Out of memory during hid input probe\n");
 					goto out_unwind;
 				}
 
@@ -912,6 +920,7 @@ int hidinput_connect(struct hid_device *
 				hidinput = NULL;
 			}
 		}
+	}
 
 	if (hidinput && input_register_device(hidinput->input))
 		goto out_cleanup;
diff -druNp linux-libre-2.6.37-gnu1/drivers/hid/hid-kye.c linux-libre-2.6.38-gnu1/drivers/hid/hid-kye.c
--- linux-libre-2.6.37-gnu1/drivers/hid/hid-kye.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hid/hid-kye.c	2011-03-14 21:20:32.000000000 -0400
@@ -32,8 +32,8 @@ static __u8 *kye_report_fixup(struct hid
 		rdesc[65] == 0x29 && rdesc[66] == 0x0f &&
 		rdesc[71] == 0x75 && rdesc[72] == 0x08 &&
 		rdesc[73] == 0x95 && rdesc[74] == 0x01) {
-		dev_info(&hdev->dev, "fixing up Kye/Genius Ergo Mouse report "
-				"descriptor\n");
+		hid_info(hdev,
+			 "fixing up Kye/Genius Ergo Mouse report descriptor\n");
 		rdesc[62] = 0x09;
 		rdesc[64] = 0x04;
 		rdesc[66] = 0x07;
diff -druNp linux-libre-2.6.37-gnu1/drivers/hid/hid-lg2ff.c linux-libre-2.6.38-gnu1/drivers/hid/hid-lg2ff.c
--- linux-libre-2.6.37-gnu1/drivers/hid/hid-lg2ff.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hid/hid-lg2ff.c	2011-03-14 21:20:32.000000000 -0400
@@ -72,18 +72,18 @@ int lg2ff_init(struct hid_device *hid)
 	int error;
 
 	if (list_empty(report_list)) {
-		dev_err(&hid->dev, "no output report found\n");
+		hid_err(hid, "no output report found\n");
 		return -ENODEV;
 	}
 
 	report = list_entry(report_list->next, struct hid_report, list);
 
 	if (report->maxfield < 1) {
-		dev_err(&hid->dev, "output report is empty\n");
+		hid_err(hid, "output report is empty\n");
 		return -ENODEV;
 	}
 	if (report->field[0]->report_count < 7) {
-		dev_err(&hid->dev, "not enough values in the field\n");
+		hid_err(hid, "not enough values in the field\n");
 		return -ENODEV;
 	}
 
@@ -110,8 +110,7 @@ int lg2ff_init(struct hid_device *hid)
 
 	usbhid_submit_report(hid, report, USB_DIR_OUT);
 
-	dev_info(&hid->dev, "Force feedback for Logitech RumblePad/Rumblepad 2 by "
-	       "Anssi Hannula <anssi.hannula@gmail.com>\n");
+	hid_info(hid, "Force feedback for Logitech RumblePad/Rumblepad 2 by Anssi Hannula <anssi.hannula@gmail.com>\n");
 
 	return 0;
 }
diff -druNp linux-libre-2.6.37-gnu1/drivers/hid/hid-lg3ff.c linux-libre-2.6.38-gnu1/drivers/hid/hid-lg3ff.c
--- linux-libre-2.6.37-gnu1/drivers/hid/hid-lg3ff.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hid/hid-lg3ff.c	2011-03-14 21:20:32.000000000 -0400
@@ -141,20 +141,20 @@ int lg3ff_init(struct hid_device *hid)
 
 	/* Find the report to use */
 	if (list_empty(report_list)) {
-		err_hid("No output report found");
+		hid_err(hid, "No output report found\n");
 		return -1;
 	}
 
 	/* Check that the report looks ok */
 	report = list_entry(report_list->next, struct hid_report, list);
 	if (!report) {
-		err_hid("NULL output report");
+		hid_err(hid, "NULL output report\n");
 		return -1;
 	}
 
 	field = report->field[0];
 	if (!field) {
-		err_hid("NULL field");
+		hid_err(hid, "NULL field\n");
 		return -1;
 	}
 
@@ -169,8 +169,7 @@ int lg3ff_init(struct hid_device *hid)
 	if (test_bit(FF_AUTOCENTER, dev->ffbit))
 		dev->ff->set_autocenter = hid_lg3ff_set_autocenter;
 
-	dev_info(&hid->dev, "Force feedback for Logitech Flight System G940 by "
-			"Gary Stein <LordCnidarian@gmail.com>\n");
+	hid_info(hid, "Force feedback for Logitech Flight System G940 by Gary Stein <LordCnidarian@gmail.com>\n");
 	return 0;
 }
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/hid/hid-lg4ff.c linux-libre-2.6.38-gnu1/drivers/hid/hid-lg4ff.c
--- linux-libre-2.6.37-gnu1/drivers/hid/hid-lg4ff.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hid/hid-lg4ff.c	2011-03-14 21:20:32.000000000 -0400
@@ -101,20 +101,20 @@ int lg4ff_init(struct hid_device *hid)
 
 	/* Find the report to use */
 	if (list_empty(report_list)) {
-		err_hid("No output report found");
+		hid_err(hid, "No output report found\n");
 		return -1;
 	}
 
 	/* Check that the report looks ok */
 	report = list_entry(report_list->next, struct hid_report, list);
 	if (!report) {
-		err_hid("NULL output report");
+		hid_err(hid, "NULL output report\n");
 		return -1;
 	}
 
 	field = report->field[0];
 	if (!field) {
-		err_hid("NULL field");
+		hid_err(hid, "NULL field\n");
 		return -1;
 	}
 
@@ -129,8 +129,7 @@ int lg4ff_init(struct hid_device *hid)
 	if (test_bit(FF_AUTOCENTER, dev->ffbit))
 		dev->ff->set_autocenter = hid_lg4ff_set_autocenter;
 
-	dev_info(&hid->dev, "Force feedback for Logitech Speed Force Wireless by "
-			"Simon Wood <simon@mungewell.org>\n");
+	hid_info(hid, "Force feedback for Logitech Speed Force Wireless by Simon Wood <simon@mungewell.org>\n");
 	return 0;
 }
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/hid/hid-lg.c linux-libre-2.6.38-gnu1/drivers/hid/hid-lg.c
--- linux-libre-2.6.37-gnu1/drivers/hid/hid-lg.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hid/hid-lg.c	2011-03-14 21:20:32.000000000 -0400
@@ -53,23 +53,22 @@ static __u8 *lg_report_fixup(struct hid_
 
 	if ((quirks & LG_RDESC) && *rsize >= 90 && rdesc[83] == 0x26 &&
 			rdesc[84] == 0x8c && rdesc[85] == 0x02) {
-		dev_info(&hdev->dev, "fixing up Logitech keyboard report "
-				"descriptor\n");
+		hid_info(hdev,
+			 "fixing up Logitech keyboard report descriptor\n");
 		rdesc[84] = rdesc[89] = 0x4d;
 		rdesc[85] = rdesc[90] = 0x10;
 	}
 	if ((quirks & LG_RDESC_REL_ABS) && *rsize >= 50 &&
 			rdesc[32] == 0x81 && rdesc[33] == 0x06 &&
 			rdesc[49] == 0x81 && rdesc[50] == 0x06) {
-		dev_info(&hdev->dev, "fixing up rel/abs in Logitech "
-				"report descriptor\n");
+		hid_info(hdev,
+			 "fixing up rel/abs in Logitech report descriptor\n");
 		rdesc[33] = rdesc[50] = 0x02;
 	}
 	if ((quirks & LG_FF4) && *rsize >= 101 &&
 			rdesc[41] == 0x95 && rdesc[42] == 0x0B &&
 			rdesc[47] == 0x05 && rdesc[48] == 0x09) {
-		dev_info(&hdev->dev, "fixing up Logitech Speed Force Wireless "
-			"button descriptor\n");
+		hid_info(hdev, "fixing up Logitech Speed Force Wireless button descriptor\n");
 		rdesc[41] = 0x05;
 		rdesc[42] = 0x09;
 		rdesc[47] = 0x95;
@@ -288,7 +287,7 @@ static int lg_probe(struct hid_device *h
 
 	ret = hid_parse(hdev);
 	if (ret) {
-		dev_err(&hdev->dev, "parse failed\n");
+		hid_err(hdev, "parse failed\n");
 		goto err_free;
 	}
 
@@ -297,7 +296,7 @@ static int lg_probe(struct hid_device *h
 
 	ret = hid_hw_start(hdev, connect_mask);
 	if (ret) {
-		dev_err(&hdev->dev, "hw start failed\n");
+		hid_err(hdev, "hw start failed\n");
 		goto err_free;
 	}
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/hid/hid-lgff.c linux-libre-2.6.38-gnu1/drivers/hid/hid-lgff.c
--- linux-libre-2.6.37-gnu1/drivers/hid/hid-lgff.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hid/hid-lgff.c	2011-03-14 21:20:32.000000000 -0400
@@ -27,6 +27,8 @@
  * e-mail - mail your message to <johann.deneux@it.uu.se>
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/input.h>
 #include <linux/usb.h>
 #include <linux/hid.h>
@@ -146,7 +148,7 @@ int lgff_init(struct hid_device* hid)
 
 	/* Find the report to use */
 	if (list_empty(report_list)) {
-		err_hid("No output report found");
+		hid_err(hid, "No output report found\n");
 		return -1;
 	}
 
@@ -154,7 +156,7 @@ int lgff_init(struct hid_device* hid)
 	report = list_entry(report_list->next, struct hid_report, list);
 	field = report->field[0];
 	if (!field) {
-		err_hid("NULL field");
+		hid_err(hid, "NULL field\n");
 		return -1;
 	}
 
@@ -176,7 +178,7 @@ int lgff_init(struct hid_device* hid)
 	if ( test_bit(FF_AUTOCENTER, dev->ffbit) )
 		dev->ff->set_autocenter = hid_lgff_set_autocenter;
 
-	printk(KERN_INFO "Force feedback for Logitech force feedback devices by Johann Deneux <johann.deneux@it.uu.se>\n");
+	pr_info("Force feedback for Logitech force feedback devices by Johann Deneux <johann.deneux@it.uu.se>\n");
 
 	return 0;
 }
diff -druNp linux-libre-2.6.37-gnu1/drivers/hid/hid-magicmouse.c linux-libre-2.6.38-gnu1/drivers/hid/hid-magicmouse.c
--- linux-libre-2.6.37-gnu1/drivers/hid/hid-magicmouse.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hid/hid-magicmouse.c	2011-03-14 21:20:32.000000000 -0400
@@ -12,6 +12,8 @@
  * any later version.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/device.h>
 #include <linux/hid.h>
 #include <linux/module.h>
@@ -433,6 +435,11 @@ static int magicmouse_input_mapping(stru
 	if (!msc->input)
 		msc->input = hi->input;
 
+	/* Magic Trackpad does not give relative data after switching to MT */
+	if (hi->input->id.product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD &&
+	    field->flags & HID_MAIN_ITEM_RELATIVE)
+		return -1;
+
 	return 0;
 }
 
@@ -446,7 +453,7 @@ static int magicmouse_probe(struct hid_d
 
 	msc = kzalloc(sizeof(*msc), GFP_KERNEL);
 	if (msc == NULL) {
-		dev_err(&hdev->dev, "can't alloc magicmouse descriptor\n");
+		hid_err(hdev, "can't alloc magicmouse descriptor\n");
 		return -ENOMEM;
 	}
 
@@ -459,13 +466,13 @@ static int magicmouse_probe(struct hid_d
 
 	ret = hid_parse(hdev);
 	if (ret) {
-		dev_err(&hdev->dev, "magicmouse hid parse failed\n");
+		hid_err(hdev, "magicmouse hid parse failed\n");
 		goto err_free;
 	}
 
 	ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
 	if (ret) {
-		dev_err(&hdev->dev, "magicmouse hw start failed\n");
+		hid_err(hdev, "magicmouse hw start failed\n");
 		goto err_free;
 	}
 
@@ -486,7 +493,7 @@ static int magicmouse_probe(struct hid_d
 	}
 
 	if (!report) {
-		dev_err(&hdev->dev, "unable to register touch report\n");
+		hid_err(hdev, "unable to register touch report\n");
 		ret = -ENOMEM;
 		goto err_stop_hw;
 	}
@@ -495,8 +502,7 @@ static int magicmouse_probe(struct hid_d
 	ret = hdev->hid_output_raw_report(hdev, feature, sizeof(feature),
 			HID_FEATURE_REPORT);
 	if (ret != sizeof(feature)) {
-		dev_err(&hdev->dev, "unable to request touch data (%d)\n",
-				ret);
+		hid_err(hdev, "unable to request touch data (%d)\n", ret);
 		goto err_stop_hw;
 	}
 
@@ -540,7 +546,7 @@ static int __init magicmouse_init(void)
 
 	ret = hid_register_driver(&magicmouse_driver);
 	if (ret)
-		printk(KERN_ERR "can't register magicmouse driver\n");
+		pr_err("can't register magicmouse driver\n");
 
 	return ret;
 }
diff -druNp linux-libre-2.6.37-gnu1/drivers/hid/hid-microsoft.c linux-libre-2.6.38-gnu1/drivers/hid/hid-microsoft.c
--- linux-libre-2.6.37-gnu1/drivers/hid/hid-microsoft.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hid/hid-microsoft.c	2011-03-14 21:20:32.000000000 -0400
@@ -40,8 +40,7 @@ static __u8 *ms_report_fixup(struct hid_
 
 	if ((quirks & MS_RDESC) && *rsize == 571 && rdesc[557] == 0x19 &&
 			rdesc[559] == 0x29) {
-		dev_info(&hdev->dev, "fixing up Microsoft Wireless Receiver "
-				"Model 1028 report descriptor\n");
+		hid_info(hdev, "fixing up Microsoft Wireless Receiver Model 1028 report descriptor\n");
 		rdesc[557] = 0x35;
 		rdesc[559] = 0x45;
 	}
@@ -155,14 +154,14 @@ static int ms_probe(struct hid_device *h
 
 	ret = hid_parse(hdev);
 	if (ret) {
-		dev_err(&hdev->dev, "parse failed\n");
+		hid_err(hdev, "parse failed\n");
 		goto err_free;
 	}
 
 	ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT | ((quirks & MS_HIDINPUT) ?
 				HID_CONNECT_HIDINPUT_FORCE : 0));
 	if (ret) {
-		dev_err(&hdev->dev, "hw start failed\n");
+		hid_err(hdev, "hw start failed\n");
 		goto err_free;
 	}
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/hid/hid-monterey.c linux-libre-2.6.38-gnu1/drivers/hid/hid-monterey.c
--- linux-libre-2.6.37-gnu1/drivers/hid/hid-monterey.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hid/hid-monterey.c	2011-03-14 21:20:32.000000000 -0400
@@ -26,8 +26,7 @@ static __u8 *mr_report_fixup(struct hid_
 		unsigned int *rsize)
 {
 	if (*rsize >= 30 && rdesc[29] == 0x05 && rdesc[30] == 0x09) {
-		dev_info(&hdev->dev, "fixing up button/consumer in HID report "
-				"descriptor\n");
+		hid_info(hdev, "fixing up button/consumer in HID report descriptor\n");
 		rdesc[30] = 0x0c;
 	}
 	return rdesc;
diff -druNp linux-libre-2.6.37-gnu1/drivers/hid/hid-mosart.c linux-libre-2.6.38-gnu1/drivers/hid/hid-mosart.c
--- linux-libre-2.6.37-gnu1/drivers/hid/hid-mosart.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hid/hid-mosart.c	2011-03-14 21:20:32.000000000 -0400
@@ -90,6 +90,10 @@ static int mosart_input_mapping(struct h
 	case 0xff000000:
 		/* ignore HID features */
 		return -1;
+
+	case HID_UP_BUTTON:
+		/* ignore buttons */
+		return -1;
 	}
 
 	return 0;
@@ -199,7 +203,7 @@ static int mosart_probe(struct hid_devic
 
 	td = kmalloc(sizeof(struct mosart_data), GFP_KERNEL);
 	if (!td) {
-		dev_err(&hdev->dev, "cannot allocate MosArt data\n");
+		hid_err(hdev, "cannot allocate MosArt data\n");
 		return -ENOMEM;
 	}
 	td->valid = false;
@@ -230,6 +234,19 @@ static int mosart_probe(struct hid_devic
 	return ret;
 }
 
+#ifdef CONFIG_PM
+static int mosart_reset_resume(struct hid_device *hdev)
+{
+	struct hid_report_enum *re = hdev->report_enum
+						+ HID_FEATURE_REPORT;
+	struct hid_report *r = re->report_id_hash[7];
+
+	r->field[0]->value[0] = 0x02;
+	usbhid_submit_report(hdev, r, USB_DIR_OUT);
+	return 0;
+}
+#endif
+
 static void mosart_remove(struct hid_device *hdev)
 {
 	hid_hw_stop(hdev);
@@ -240,6 +257,7 @@ static void mosart_remove(struct hid_dev
 static const struct hid_device_id mosart_devices[] = {
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_T91MT) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUSTEK_MULTITOUCH_YFO) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_TOUCHSCREEN_MOSART) },
 	{ }
 };
 MODULE_DEVICE_TABLE(hid, mosart_devices);
@@ -258,6 +276,9 @@ static struct hid_driver mosart_driver =
 	.input_mapped = mosart_input_mapped,
 	.usage_table = mosart_grabbed_usages,
 	.event = mosart_event,
+#ifdef CONFIG_PM
+	.reset_resume = mosart_reset_resume,
+#endif
 };
 
 static int __init mosart_init(void)
diff -druNp linux-libre-2.6.37-gnu1/drivers/hid/hid-multitouch.c linux-libre-2.6.38-gnu1/drivers/hid/hid-multitouch.c
--- linux-libre-2.6.37-gnu1/drivers/hid/hid-multitouch.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hid/hid-multitouch.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,516 @@
+/*
+ *  HID driver for multitouch panels
+ *
+ *  Copyright (c) 2010-2011 Stephane Chatty <chatty@enac.fr>
+ *  Copyright (c) 2010-2011 Benjamin Tissoires <benjamin.tissoires@gmail.com>
+ *  Copyright (c) 2010-2011 Ecole Nationale de l'Aviation Civile, France
+ *
+ */
+
+/*
+ * 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/device.h>
+#include <linux/hid.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/usb.h>
+#include <linux/input/mt.h>
+#include "usbhid/usbhid.h"
+
+
+MODULE_AUTHOR("Stephane Chatty <chatty@enac.fr>");
+MODULE_DESCRIPTION("HID multitouch panels");
+MODULE_LICENSE("GPL");
+
+#include "hid-ids.h"
+
+/* quirks to control the device */
+#define MT_QUIRK_NOT_SEEN_MEANS_UP	(1 << 0)
+#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)
+
+struct mt_slot {
+	__s32 x, y, p, w, h;
+	__s32 contactid;	/* the device ContactID assigned to this slot */
+	bool touch_state;	/* is the touch valid? */
+	bool seen_in_this_frame;/* has this slot been updated */
+};
+
+struct mt_device {
+	struct mt_slot curdata;	/* placeholder of incoming data */
+	struct mt_class *mtclass;	/* our mt device class */
+	unsigned last_field_index;	/* last field index of the report */
+	unsigned last_slot_field;	/* the last field of a slot */
+	__s8 inputmode;		/* InputMode HID feature, -1 if non-existent */
+	__u8 num_received;	/* how many contacts we received */
+	__u8 num_expected;	/* expected last contact index */
+	bool curvalid;		/* is the current contact valid? */
+	struct mt_slot slots[0];	/* first slot */
+};
+
+struct mt_class {
+	__s32 name;	/* MT_CLS */
+	__s32 quirks;
+	__s32 sn_move;	/* Signal/noise ratio for move events */
+	__s32 sn_pressure;	/* Signal/noise ratio for pressure events */
+	__u8 maxcontacts;
+};
+
+/* classes of device behavior */
+#define MT_CLS_DEFAULT	1
+#define MT_CLS_DUAL1	2
+#define MT_CLS_DUAL2	3
+#define MT_CLS_CYPRESS	4
+
+/*
+ * these device-dependent functions determine what slot corresponds
+ * to a valid contact that was just read.
+ */
+
+static int cypress_compute_slot(struct mt_device *td)
+{
+	if (td->curdata.contactid != 0 || td->num_received == 0)
+		return td->curdata.contactid;
+	else
+		return -1;
+}
+
+static int find_slot_from_contactid(struct mt_device *td)
+{
+	int i;
+	for (i = 0; i < td->mtclass->maxcontacts; ++i) {
+		if (td->slots[i].contactid == td->curdata.contactid &&
+			td->slots[i].touch_state)
+			return i;
+	}
+	for (i = 0; i < td->mtclass->maxcontacts; ++i) {
+		if (!td->slots[i].seen_in_this_frame &&
+			!td->slots[i].touch_state)
+			return i;
+	}
+	/* should not occurs. If this happens that means
+	 * that the device sent more touches that it says
+	 * in the report descriptor. It is ignored then. */
+	return -1;
+}
+
+struct mt_class mt_classes[] = {
+	{ .name = MT_CLS_DEFAULT,
+		.quirks = MT_QUIRK_VALID_IS_INRANGE,
+		.maxcontacts = 10 },
+	{ .name = MT_CLS_DUAL1,
+		.quirks = MT_QUIRK_VALID_IS_INRANGE |
+			MT_QUIRK_SLOT_IS_CONTACTID,
+		.maxcontacts = 2 },
+	{ .name = MT_CLS_DUAL2,
+		.quirks = MT_QUIRK_VALID_IS_INRANGE |
+			MT_QUIRK_SLOT_IS_CONTACTNUMBER,
+		.maxcontacts = 2 },
+	{ .name = MT_CLS_CYPRESS,
+		.quirks = MT_QUIRK_NOT_SEEN_MEANS_UP |
+			MT_QUIRK_CYPRESS,
+		.maxcontacts = 10 },
+
+	{ }
+};
+
+static void mt_feature_mapping(struct hid_device *hdev, struct hid_input *hi,
+		struct hid_field *field, struct hid_usage *usage)
+{
+	if (usage->hid == HID_DG_INPUTMODE) {
+		struct mt_device *td = hid_get_drvdata(hdev);
+		td->inputmode = field->report->id;
+	}
+}
+
+static void set_abs(struct input_dev *input, unsigned int code,
+		struct hid_field *field, int snratio)
+{
+	int fmin = field->logical_minimum;
+	int fmax = field->logical_maximum;
+	int fuzz = snratio ? (fmax - fmin) / snratio : 0;
+	input_set_abs_params(input, code, fmin, fmax, fuzz, 0);
+}
+
+static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
+		struct hid_field *field, struct hid_usage *usage,
+		unsigned long **bit, int *max)
+{
+	struct mt_device *td = hid_get_drvdata(hdev);
+	struct mt_class *cls = td->mtclass;
+	switch (usage->hid & HID_USAGE_PAGE) {
+
+	case HID_UP_GENDESK:
+		switch (usage->hid) {
+		case HID_GD_X:
+			hid_map_usage(hi, usage, bit, max,
+					EV_ABS, ABS_MT_POSITION_X);
+			set_abs(hi->input, ABS_MT_POSITION_X, field,
+				cls->sn_move);
+			/* touchscreen emulation */
+			set_abs(hi->input, ABS_X, field, cls->sn_move);
+			td->last_slot_field = usage->hid;
+			return 1;
+		case HID_GD_Y:
+			hid_map_usage(hi, usage, bit, max,
+					EV_ABS, ABS_MT_POSITION_Y);
+			set_abs(hi->input, ABS_MT_POSITION_Y, field,
+				cls->sn_move);
+			/* touchscreen emulation */
+			set_abs(hi->input, ABS_Y, field, cls->sn_move);
+			td->last_slot_field = usage->hid;
+			return 1;
+		}
+		return 0;
+
+	case HID_UP_DIGITIZER:
+		switch (usage->hid) {
+		case HID_DG_INRANGE:
+			td->last_slot_field = usage->hid;
+			return 1;
+		case HID_DG_CONFIDENCE:
+			td->last_slot_field = usage->hid;
+			return 1;
+		case HID_DG_TIPSWITCH:
+			hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH);
+			input_set_capability(hi->input, EV_KEY, BTN_TOUCH);
+			td->last_slot_field = usage->hid;
+			return 1;
+		case HID_DG_CONTACTID:
+			input_mt_init_slots(hi->input,
+					td->mtclass->maxcontacts);
+			td->last_slot_field = usage->hid;
+			return 1;
+		case HID_DG_WIDTH:
+			hid_map_usage(hi, usage, bit, max,
+					EV_ABS, ABS_MT_TOUCH_MAJOR);
+			td->last_slot_field = usage->hid;
+			return 1;
+		case HID_DG_HEIGHT:
+			hid_map_usage(hi, usage, bit, max,
+					EV_ABS, ABS_MT_TOUCH_MINOR);
+			field->logical_maximum = 1;
+			field->logical_minimum = 0;
+			set_abs(hi->input, ABS_MT_ORIENTATION, field, 0);
+			td->last_slot_field = usage->hid;
+			return 1;
+		case HID_DG_TIPPRESSURE:
+			hid_map_usage(hi, usage, bit, max,
+					EV_ABS, ABS_MT_PRESSURE);
+			set_abs(hi->input, ABS_MT_PRESSURE, field,
+				cls->sn_pressure);
+			/* touchscreen emulation */
+			set_abs(hi->input, ABS_PRESSURE, field,
+				cls->sn_pressure);
+			td->last_slot_field = usage->hid;
+			return 1;
+		case HID_DG_CONTACTCOUNT:
+			td->last_field_index = field->report->maxfield - 1;
+			return 1;
+		case HID_DG_CONTACTMAX:
+			/* we don't set td->last_slot_field as contactcount and
+			 * contact max are global to the report */
+			return -1;
+		}
+		/* let hid-input decide for the others */
+		return 0;
+
+	case 0xff000000:
+		/* we do not want to map these: no input-oriented meaning */
+		return -1;
+	}
+
+	return 0;
+}
+
+static int mt_input_mapped(struct hid_device *hdev, struct hid_input *hi,
+		struct hid_field *field, struct hid_usage *usage,
+		unsigned long **bit, int *max)
+{
+	if (usage->type == EV_KEY || usage->type == EV_ABS)
+		set_bit(usage->type, hi->input->evbit);
+
+	return -1;
+}
+
+static int mt_compute_slot(struct mt_device *td)
+{
+	__s32 quirks = td->mtclass->quirks;
+
+	if (quirks & MT_QUIRK_SLOT_IS_CONTACTID)
+		return td->curdata.contactid;
+
+	if (quirks & MT_QUIRK_CYPRESS)
+		return cypress_compute_slot(td);
+
+	if (quirks & MT_QUIRK_SLOT_IS_CONTACTNUMBER)
+		return td->num_received;
+
+	return find_slot_from_contactid(td);
+}
+
+/*
+ * this function is called when a whole contact has been processed,
+ * so that it can assign it to a slot and store the data there
+ */
+static void mt_complete_slot(struct mt_device *td)
+{
+	td->curdata.seen_in_this_frame = true;
+	if (td->curvalid) {
+		int slotnum = mt_compute_slot(td);
+
+		if (slotnum >= 0 && slotnum < td->mtclass->maxcontacts)
+			td->slots[slotnum] = td->curdata;
+	}
+	td->num_received++;
+}
+
+
+/*
+ * this function is called when a whole packet has been received and processed,
+ * so that it can decide what to send to the input layer.
+ */
+static void mt_emit_event(struct mt_device *td, struct input_dev *input)
+{
+	int i;
+
+	for (i = 0; i < td->mtclass->maxcontacts; ++i) {
+		struct mt_slot *s = &(td->slots[i]);
+		if ((td->mtclass->quirks & MT_QUIRK_NOT_SEEN_MEANS_UP) &&
+			!s->seen_in_this_frame) {
+			s->touch_state = false;
+		}
+
+		input_mt_slot(input, i);
+		input_mt_report_slot_state(input, MT_TOOL_FINGER,
+			s->touch_state);
+		if (s->touch_state) {
+			input_event(input, EV_ABS, ABS_MT_POSITION_X, s->x);
+			input_event(input, EV_ABS, ABS_MT_POSITION_Y, s->y);
+			input_event(input, EV_ABS, ABS_MT_PRESSURE, s->p);
+			input_event(input, EV_ABS, ABS_MT_TOUCH_MAJOR, s->w);
+			input_event(input, EV_ABS, ABS_MT_TOUCH_MINOR, s->h);
+		}
+		s->seen_in_this_frame = false;
+
+	}
+
+	input_mt_report_pointer_emulation(input, true);
+	input_sync(input);
+	td->num_received = 0;
+}
+
+
+
+static int mt_event(struct hid_device *hid, struct hid_field *field,
+				struct hid_usage *usage, __s32 value)
+{
+	struct mt_device *td = hid_get_drvdata(hid);
+	__s32 quirks = td->mtclass->quirks;
+
+	if (hid->claimed & HID_CLAIMED_INPUT) {
+		switch (usage->hid) {
+		case HID_DG_INRANGE:
+			if (quirks & MT_QUIRK_VALID_IS_INRANGE)
+				td->curvalid = value;
+			break;
+		case HID_DG_TIPSWITCH:
+			if (quirks & MT_QUIRK_NOT_SEEN_MEANS_UP)
+				td->curvalid = value;
+			td->curdata.touch_state = value;
+			break;
+		case HID_DG_CONFIDENCE:
+			if (quirks & MT_QUIRK_VALID_IS_CONFIDENCE)
+				td->curvalid = value;
+			break;
+		case HID_DG_CONTACTID:
+			td->curdata.contactid = value;
+			break;
+		case HID_DG_TIPPRESSURE:
+			td->curdata.p = value;
+			break;
+		case HID_GD_X:
+			td->curdata.x = value;
+			break;
+		case HID_GD_Y:
+			td->curdata.y = value;
+			break;
+		case HID_DG_WIDTH:
+			td->curdata.w = value;
+			break;
+		case HID_DG_HEIGHT:
+			td->curdata.h = value;
+			break;
+		case HID_DG_CONTACTCOUNT:
+			/*
+			 * Includes multi-packet support where subsequent
+			 * packets are sent with zero contactcount.
+			 */
+			if (value)
+				td->num_expected = value;
+			break;
+
+		default:
+			/* fallback to the generic hidinput handling */
+			return 0;
+		}
+
+		if (usage->hid == td->last_slot_field)
+			mt_complete_slot(td);
+
+		if (field->index == td->last_field_index
+			&& td->num_received >= td->num_expected)
+			mt_emit_event(td, field->hidinput->input);
+
+	}
+
+	/* we have handled the hidinput part, now remains hiddev */
+	if (hid->claimed & HID_CLAIMED_HIDDEV && hid->hiddev_hid_event)
+		hid->hiddev_hid_event(hid, field, usage, value);
+
+	return 1;
+}
+
+static void mt_set_input_mode(struct hid_device *hdev)
+{
+	struct mt_device *td = hid_get_drvdata(hdev);
+	struct hid_report *r;
+	struct hid_report_enum *re;
+
+	if (td->inputmode < 0)
+		return;
+
+	re = &(hdev->report_enum[HID_FEATURE_REPORT]);
+	r = re->report_id_hash[td->inputmode];
+	if (r) {
+		r->field[0]->value[0] = 0x02;
+		usbhid_submit_report(hdev, r, USB_DIR_OUT);
+	}
+}
+
+static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
+{
+	int ret, i;
+	struct mt_device *td;
+	struct mt_class *mtclass = mt_classes; /* MT_CLS_DEFAULT */
+
+	for (i = 0; mt_classes[i].name ; i++) {
+		if (id->driver_data == mt_classes[i].name) {
+			mtclass = &(mt_classes[i]);
+			break;
+		}
+	}
+
+	/* This allows the driver to correctly support devices
+	 * that emit events over several HID messages.
+	 */
+	hdev->quirks |= HID_QUIRK_NO_INPUT_SYNC;
+
+	td = kzalloc(sizeof(struct mt_device) +
+				mtclass->maxcontacts * sizeof(struct mt_slot),
+				GFP_KERNEL);
+	if (!td) {
+		dev_err(&hdev->dev, "cannot allocate multitouch data\n");
+		return -ENOMEM;
+	}
+	td->mtclass = mtclass;
+	td->inputmode = -1;
+	hid_set_drvdata(hdev, td);
+
+	ret = hid_parse(hdev);
+	if (ret != 0)
+		goto fail;
+
+	ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
+	if (ret)
+		goto fail;
+
+	mt_set_input_mode(hdev);
+
+	return 0;
+
+fail:
+	kfree(td);
+	return ret;
+}
+
+#ifdef CONFIG_PM
+static int mt_reset_resume(struct hid_device *hdev)
+{
+	mt_set_input_mode(hdev);
+	return 0;
+}
+#endif
+
+static void mt_remove(struct hid_device *hdev)
+{
+	struct mt_device *td = hid_get_drvdata(hdev);
+	hid_hw_stop(hdev);
+	kfree(td);
+	hid_set_drvdata(hdev, NULL);
+}
+
+static const struct hid_device_id mt_devices[] = {
+
+	/* Cypress panel */
+	{ .driver_data = MT_CLS_CYPRESS,
+		HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS,
+			USB_DEVICE_ID_CYPRESS_TRUETOUCH) },
+
+	/* GeneralTouch panel */
+	{ .driver_data = MT_CLS_DUAL2,
+		HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH,
+			USB_DEVICE_ID_GENERAL_TOUCH_WIN7_TWOFINGERS) },
+
+	/* PixCir-based panels */
+	{ .driver_data = MT_CLS_DUAL1,
+		HID_USB_DEVICE(USB_VENDOR_ID_HANVON,
+			USB_DEVICE_ID_HANVON_MULTITOUCH) },
+	{ .driver_data = MT_CLS_DUAL1,
+		HID_USB_DEVICE(USB_VENDOR_ID_CANDO,
+			USB_DEVICE_ID_CANDO_PIXCIR_MULTI_TOUCH) },
+
+	{ }
+};
+MODULE_DEVICE_TABLE(hid, mt_devices);
+
+static const struct hid_usage_id mt_grabbed_usages[] = {
+	{ HID_ANY_ID, HID_ANY_ID, HID_ANY_ID },
+	{ HID_ANY_ID - 1, HID_ANY_ID - 1, HID_ANY_ID - 1}
+};
+
+static struct hid_driver mt_driver = {
+	.name = "hid-multitouch",
+	.id_table = mt_devices,
+	.probe = mt_probe,
+	.remove = mt_remove,
+	.input_mapping = mt_input_mapping,
+	.input_mapped = mt_input_mapped,
+	.feature_mapping = mt_feature_mapping,
+	.usage_table = mt_grabbed_usages,
+	.event = mt_event,
+#ifdef CONFIG_PM
+	.reset_resume = mt_reset_resume,
+#endif
+};
+
+static int __init mt_init(void)
+{
+	return hid_register_driver(&mt_driver);
+}
+
+static void __exit mt_exit(void)
+{
+	hid_unregister_driver(&mt_driver);
+}
+
+module_init(mt_init);
+module_exit(mt_exit);
diff -druNp linux-libre-2.6.37-gnu1/drivers/hid/hid-ntrig.c linux-libre-2.6.38-gnu1/drivers/hid/hid-ntrig.c
--- linux-libre-2.6.37-gnu1/drivers/hid/hid-ntrig.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hid/hid-ntrig.c	2011-03-14 21:20:32.000000000 -0400
@@ -130,8 +130,7 @@ static void ntrig_report_version(struct
 	if (ret == 8) {
 		ret = ntrig_version_string(&data[2], buf);
 
-		dev_info(&hdev->dev,
-			 "Firmware version: %s (%02x%02x %02x%02x)\n",
+		hid_info(hdev, "Firmware version: %s (%02x%02x %02x%02x)\n",
 			 buf, data[2], data[3], data[4], data[5]);
 	}
 
@@ -831,7 +830,7 @@ static int ntrig_probe(struct hid_device
 
 	nd = kmalloc(sizeof(struct ntrig_data), GFP_KERNEL);
 	if (!nd) {
-		dev_err(&hdev->dev, "cannot allocate N-Trig data\n");
+		hid_err(hdev, "cannot allocate N-Trig data\n");
 		return -ENOMEM;
 	}
 
@@ -850,13 +849,13 @@ static int ntrig_probe(struct hid_device
 
 	ret = hid_parse(hdev);
 	if (ret) {
-		dev_err(&hdev->dev, "parse failed\n");
+		hid_err(hdev, "parse failed\n");
 		goto err_free;
 	}
 
 	ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF);
 	if (ret) {
-		dev_err(&hdev->dev, "hw start failed\n");
+		hid_err(hdev, "hw start failed\n");
 		goto err_free;
 	}
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/hid/hid-ortek.c linux-libre-2.6.38-gnu1/drivers/hid/hid-ortek.c
--- linux-libre-2.6.37-gnu1/drivers/hid/hid-ortek.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hid/hid-ortek.c	2011-03-14 21:20:32.000000000 -0400
@@ -23,8 +23,7 @@ static __u8 *ortek_report_fixup(struct h
 		unsigned int *rsize)
 {
 	if (*rsize >= 56 && rdesc[54] == 0x25 && rdesc[55] == 0x01) {
-		dev_info(&hdev->dev, "Fixing up Ortek WKB-2000 "
-				"report descriptor.\n");
+		hid_info(hdev, "Fixing up Ortek WKB-2000 report descriptor\n");
 		rdesc[55] = 0x92;
 	}
 	return rdesc;
diff -druNp linux-libre-2.6.37-gnu1/drivers/hid/hid-petalynx.c linux-libre-2.6.38-gnu1/drivers/hid/hid-petalynx.c
--- linux-libre-2.6.37-gnu1/drivers/hid/hid-petalynx.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hid/hid-petalynx.c	2011-03-14 21:20:32.000000000 -0400
@@ -29,8 +29,7 @@ static __u8 *pl_report_fixup(struct hid_
 	if (*rsize >= 60 && rdesc[39] == 0x2a && rdesc[40] == 0xf5 &&
 			rdesc[41] == 0x00 && rdesc[59] == 0x26 &&
 			rdesc[60] == 0xf9 && rdesc[61] == 0x00) {
-		dev_info(&hdev->dev, "fixing up Petalynx Maxter Remote report "
-				"descriptor\n");
+		hid_info(hdev, "fixing up Petalynx Maxter Remote report descriptor\n");
 		rdesc[60] = 0xfa;
 		rdesc[40] = 0xfa;
 	}
@@ -77,13 +76,13 @@ static int pl_probe(struct hid_device *h
 
 	ret = hid_parse(hdev);
 	if (ret) {
-		dev_err(&hdev->dev, "parse failed\n");
+		hid_err(hdev, "parse failed\n");
 		goto err_free;
 	}
 
 	ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
 	if (ret) {
-		dev_err(&hdev->dev, "hw start failed\n");
+		hid_err(hdev, "hw start failed\n");
 		goto err_free;
 	}
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/hid/hid-picolcd.c linux-libre-2.6.38-gnu1/drivers/hid/hid-picolcd.c
--- linux-libre-2.6.37-gnu1/drivers/hid/hid-picolcd.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hid/hid-picolcd.c	2011-03-14 21:20:32.000000000 -0400
@@ -253,7 +253,7 @@ static struct hid_report *picolcd_report
 		if (report->id == id)
 			return report;
 	}
-	dev_warn(&hdev->dev, "No report with id 0x%x found\n", id);
+	hid_warn(hdev, "No report with id 0x%x found\n", id);
 	return NULL;
 }
 
@@ -1329,7 +1329,7 @@ static int picolcd_check_version(struct
 
 	verinfo = picolcd_send_and_wait(hdev, REPORT_VERSION, NULL, 0);
 	if (!verinfo) {
-		dev_err(&hdev->dev, "no version response from PicoLCD");
+		hid_err(hdev, "no version response from PicoLCD\n");
 		return -ENODEV;
 	}
 
@@ -1337,14 +1337,14 @@ static int picolcd_check_version(struct
 		data->version[0] = verinfo->raw_data[1];
 		data->version[1] = verinfo->raw_data[0];
 		if (data->status & PICOLCD_BOOTLOADER) {
-			dev_info(&hdev->dev, "PicoLCD, bootloader version %d.%d\n",
-					verinfo->raw_data[1], verinfo->raw_data[0]);
+			hid_info(hdev, "PicoLCD, bootloader version %d.%d\n",
+				 verinfo->raw_data[1], verinfo->raw_data[0]);
 		} else {
-			dev_info(&hdev->dev, "PicoLCD, firmware version %d.%d\n",
-					verinfo->raw_data[1], verinfo->raw_data[0]);
+			hid_info(hdev, "PicoLCD, firmware version %d.%d\n",
+				 verinfo->raw_data[1], verinfo->raw_data[0]);
 		}
 	} else {
-		dev_err(&hdev->dev, "confused, got unexpected version response from PicoLCD\n");
+		hid_err(hdev, "confused, got unexpected version response from PicoLCD\n");
 		ret = -EINVAL;
 	}
 	kfree(verinfo);
@@ -1544,7 +1544,7 @@ static ssize_t picolcd_debug_eeprom_read
 
 	/* prepare buffer with info about what we want to read (addr & len) */
 	raw_data[0] = *off & 0xff;
-	raw_data[1] = (*off >> 8) && 0xff;
+	raw_data[1] = (*off >> 8) & 0xff;
 	raw_data[2] = s < 20 ? s : 20;
 	if (*off + raw_data[2] > 0xff)
 		raw_data[2] = 0x100 - *off;
@@ -1583,7 +1583,7 @@ static ssize_t picolcd_debug_eeprom_writ
 
 	memset(raw_data, 0, sizeof(raw_data));
 	raw_data[0] = *off & 0xff;
-	raw_data[1] = (*off >> 8) && 0xff;
+	raw_data[1] = (*off >> 8) & 0xff;
 	raw_data[2] = s < 20 ? s : 20;
 	if (*off + raw_data[2] > 0xff)
 		raw_data[2] = 0x100 - *off;
@@ -1867,6 +1867,7 @@ static void picolcd_debug_out_report(str
 			report->id, raw_size);
 	hid_debug_event(hdev, buff);
 	if (raw_size + 5 > sizeof(raw_data)) {
+		kfree(buff);
 		hid_debug_event(hdev, " TOO BIG\n");
 		return;
 	} else {
@@ -2328,8 +2329,7 @@ static void picolcd_init_devfs(struct pi
 			(flash_w ? S_IWUSR : 0) | (flash_r ? S_IRUSR : 0),
 			hdev->debug_dir, data, &picolcd_debug_flash_fops);
 	} else if (flash_r || flash_w)
-		dev_warn(&hdev->dev, "Unexpected FLASH access reports, "
-				"please submit rdesc for review\n");
+		hid_warn(hdev, "Unexpected FLASH access reports, please submit rdesc for review\n");
 }
 
 static void picolcd_exit_devfs(struct picolcd_data *data)
@@ -2457,13 +2457,13 @@ static int picolcd_init_keys(struct pico
 		return -ENODEV;
 	if (report->maxfield != 1 || report->field[0]->report_count != 2 ||
 			report->field[0]->report_size != 8) {
-		dev_err(&hdev->dev, "unsupported KEY_STATE report");
+		hid_err(hdev, "unsupported KEY_STATE report\n");
 		return -EINVAL;
 	}
 
 	idev = input_allocate_device();
 	if (idev == NULL) {
-		dev_err(&hdev->dev, "failed to allocate input device");
+		hid_err(hdev, "failed to allocate input device\n");
 		return -ENOMEM;
 	}
 	input_set_drvdata(idev, hdev);
@@ -2485,7 +2485,7 @@ static int picolcd_init_keys(struct pico
 		input_set_capability(idev, EV_KEY, data->keycode[i]);
 	error = input_register_device(idev);
 	if (error) {
-		dev_err(&hdev->dev, "error registering the input device");
+		hid_err(hdev, "error registering the input device\n");
 		input_free_device(idev);
 		return error;
 	}
@@ -2522,9 +2522,8 @@ static int picolcd_probe_lcd(struct hid_
 		return error;
 
 	if (data->version[0] != 0 && data->version[1] != 3)
-		dev_info(&hdev->dev, "Device with untested firmware revision, "
-				"please submit /sys/kernel/debug/hid/%s/rdesc for this device.\n",
-				dev_name(&hdev->dev));
+		hid_info(hdev, "Device with untested firmware revision, please submit /sys/kernel/debug/hid/%s/rdesc for this device.\n",
+			 dev_name(&hdev->dev));
 
 	/* Setup keypad input device */
 	error = picolcd_init_keys(data, picolcd_in_report(REPORT_KEY_STATE, hdev));
@@ -2581,9 +2580,8 @@ static int picolcd_probe_bootloader(stru
 		return error;
 
 	if (data->version[0] != 1 && data->version[1] != 0)
-		dev_info(&hdev->dev, "Device with untested bootloader revision, "
-				"please submit /sys/kernel/debug/hid/%s/rdesc for this device.\n",
-				dev_name(&hdev->dev));
+		hid_info(hdev, "Device with untested bootloader revision, please submit /sys/kernel/debug/hid/%s/rdesc for this device.\n",
+			 dev_name(&hdev->dev));
 
 	picolcd_init_devfs(data, NULL, NULL,
 			picolcd_out_report(REPORT_BL_READ_MEMORY, hdev),
@@ -2605,7 +2603,7 @@ static int picolcd_probe(struct hid_devi
 	 */
 	data = kzalloc(sizeof(struct picolcd_data), GFP_KERNEL);
 	if (data == NULL) {
-		dev_err(&hdev->dev, "can't allocate space for Minibox PicoLCD device data\n");
+		hid_err(hdev, "can't allocate space for Minibox PicoLCD device data\n");
 		error = -ENOMEM;
 		goto err_no_cleanup;
 	}
@@ -2621,7 +2619,7 @@ static int picolcd_probe(struct hid_devi
 	/* Parse the device reports and start it up */
 	error = hid_parse(hdev);
 	if (error) {
-		dev_err(&hdev->dev, "device report parse failed\n");
+		hid_err(hdev, "device report parse failed\n");
 		goto err_cleanup_data;
 	}
 
@@ -2631,25 +2629,25 @@ static int picolcd_probe(struct hid_devi
 	error = hid_hw_start(hdev, 0);
 	hdev->claimed = 0;
 	if (error) {
-		dev_err(&hdev->dev, "hardware start failed\n");
+		hid_err(hdev, "hardware start failed\n");
 		goto err_cleanup_data;
 	}
 
-	error = hdev->ll_driver->open(hdev);
+	error = hid_hw_open(hdev);
 	if (error) {
-		dev_err(&hdev->dev, "failed to open input interrupt pipe for key and IR events\n");
+		hid_err(hdev, "failed to open input interrupt pipe for key and IR events\n");
 		goto err_cleanup_hid_hw;
 	}
 
 	error = device_create_file(&hdev->dev, &dev_attr_operation_mode_delay);
 	if (error) {
-		dev_err(&hdev->dev, "failed to create sysfs attributes\n");
+		hid_err(hdev, "failed to create sysfs attributes\n");
 		goto err_cleanup_hid_ll;
 	}
 
 	error = device_create_file(&hdev->dev, &dev_attr_operation_mode);
 	if (error) {
-		dev_err(&hdev->dev, "failed to create sysfs attributes\n");
+		hid_err(hdev, "failed to create sysfs attributes\n");
 		goto err_cleanup_sysfs1;
 	}
 
@@ -2668,7 +2666,7 @@ err_cleanup_sysfs2:
 err_cleanup_sysfs1:
 	device_remove_file(&hdev->dev, &dev_attr_operation_mode_delay);
 err_cleanup_hid_ll:
-	hdev->ll_driver->close(hdev);
+	hid_hw_close(hdev);
 err_cleanup_hid_hw:
 	hid_hw_stop(hdev);
 err_cleanup_data:
@@ -2699,7 +2697,7 @@ static void picolcd_remove(struct hid_de
 	picolcd_exit_devfs(data);
 	device_remove_file(&hdev->dev, &dev_attr_operation_mode);
 	device_remove_file(&hdev->dev, &dev_attr_operation_mode_delay);
-	hdev->ll_driver->close(hdev);
+	hid_hw_close(hdev);
 	hid_hw_stop(hdev);
 	hid_set_drvdata(hdev, NULL);
 
@@ -2753,7 +2751,7 @@ static void __exit picolcd_exit(void)
 {
 	hid_unregister_driver(&picolcd_driver);
 #ifdef CONFIG_HID_PICOLCD_FB
-	flush_scheduled_work();
+	flush_work_sync(&picolcd_fb_cleanup);
 	WARN_ON(fb_pending);
 #endif
 }
diff -druNp linux-libre-2.6.37-gnu1/drivers/hid/hid-pl.c linux-libre-2.6.38-gnu1/drivers/hid/hid-pl.c
--- linux-libre-2.6.37-gnu1/drivers/hid/hid-pl.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hid/hid-pl.c	2011-03-14 21:20:32.000000000 -0400
@@ -103,7 +103,7 @@ static int plff_init(struct hid_device *
 	*/
 
 	if (list_empty(report_list)) {
-		dev_err(&hid->dev, "no output reports found\n");
+		hid_err(hid, "no output reports found\n");
 		return -ENODEV;
 	}
 
@@ -112,14 +112,13 @@ static int plff_init(struct hid_device *
 		report_ptr = report_ptr->next;
 
 		if (report_ptr == report_list) {
-			dev_err(&hid->dev, "required output report is "
-					"missing\n");
+			hid_err(hid, "required output report is missing\n");
 			return -ENODEV;
 		}
 
 		report = list_entry(report_ptr, struct hid_report, list);
 		if (report->maxfield < 1) {
-			dev_err(&hid->dev, "no fields in the report\n");
+			hid_err(hid, "no fields in the report\n");
 			return -ENODEV;
 		}
 
@@ -137,7 +136,7 @@ static int plff_init(struct hid_device *
 			weak = &report->field[3]->value[0];
 			debug("detected 4-field device");
 		} else {
-			dev_err(&hid->dev, "not enough fields or values\n");
+			hid_err(hid, "not enough fields or values\n");
 			return -ENODEV;
 		}
 
@@ -164,8 +163,7 @@ static int plff_init(struct hid_device *
 		usbhid_submit_report(hid, plff->report, USB_DIR_OUT);
 	}
 
-	dev_info(&hid->dev, "Force feedback for PantherLord/GreenAsia "
-	       "devices by Anssi Hannula <anssi.hannula@gmail.com>\n");
+	hid_info(hid, "Force feedback for PantherLord/GreenAsia devices by Anssi Hannula <anssi.hannula@gmail.com>\n");
 
 	return 0;
 }
@@ -185,13 +183,13 @@ static int pl_probe(struct hid_device *h
 
 	ret = hid_parse(hdev);
 	if (ret) {
-		dev_err(&hdev->dev, "parse failed\n");
+		hid_err(hdev, "parse failed\n");
 		goto err;
 	}
 
 	ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF);
 	if (ret) {
-		dev_err(&hdev->dev, "hw start failed\n");
+		hid_err(hdev, "hw start failed\n");
 		goto err;
 	}
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/hid/hid-prodikeys.c linux-libre-2.6.38-gnu1/drivers/hid/hid-prodikeys.c
--- linux-libre-2.6.37-gnu1/drivers/hid/hid-prodikeys.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hid/hid-prodikeys.c	2011-03-14 21:20:32.000000000 -0400
@@ -16,6 +16,8 @@
  * any later version.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/device.h>
 #include <linux/module.h>
 #include <linux/usb.h>
@@ -130,7 +132,7 @@ static ssize_t store_channel(struct devi
 	return -EINVAL;
 }
 
-static DEVICE_ATTR(channel, S_IRUGO | S_IWUGO, show_channel,
+static DEVICE_ATTR(channel, S_IRUGO | S_IWUSR | S_IWGRP , show_channel,
 		store_channel);
 
 static struct device_attribute *sysfs_device_attr_channel = {
@@ -169,7 +171,7 @@ static ssize_t store_sustain(struct devi
 	return -EINVAL;
 }
 
-static DEVICE_ATTR(sustain, S_IRUGO | S_IWUGO, show_sustain,
+static DEVICE_ATTR(sustain, S_IRUGO | S_IWUSR | S_IWGRP, show_sustain,
 		store_sustain);
 
 static struct device_attribute *sysfs_device_attr_sustain = {
@@ -207,7 +209,7 @@ static ssize_t store_octave(struct devic
 	return -EINVAL;
 }
 
-static DEVICE_ATTR(octave, S_IRUGO | S_IWUGO, show_octave,
+static DEVICE_ATTR(octave, S_IRUGO | S_IWUSR | S_IWGRP, show_octave,
 		store_octave);
 
 static struct device_attribute *sysfs_device_attr_octave = {
@@ -285,11 +287,11 @@ static int pcmidi_get_output_report(stru
 			continue;
 
 		if (report->maxfield < 1) {
-			dev_err(&hdev->dev, "output report is empty\n");
+			hid_err(hdev, "output report is empty\n");
 			break;
 		}
 		if (report->field[0]->report_count != 2) {
-			dev_err(&hdev->dev, "field count too low\n");
+			hid_err(hdev, "field count too low\n");
 			break;
 		}
 		pm->pcmidi_report6 = report;
@@ -746,8 +748,8 @@ static __u8 *pk_report_fixup(struct hid_
 	if (*rsize == 178 &&
 	      rdesc[111] == 0x06 && rdesc[112] == 0x00 &&
 	      rdesc[113] == 0xff) {
-		dev_info(&hdev->dev, "fixing up pc-midi keyboard report "
-			"descriptor\n");
+		hid_info(hdev,
+			 "fixing up pc-midi keyboard report descriptor\n");
 
 		rdesc[144] = 0x18; /* report 4: was 0x10 report count */
 	}
@@ -805,7 +807,7 @@ static int pk_probe(struct hid_device *h
 
 	pk = kzalloc(sizeof(*pk), GFP_KERNEL);
 	if (pk == NULL) {
-		dev_err(&hdev->dev, "prodikeys: can't alloc descriptor\n");
+		hid_err(hdev, "can't alloc descriptor\n");
 		return -ENOMEM;
 	}
 
@@ -813,8 +815,7 @@ static int pk_probe(struct hid_device *h
 
 	pm = kzalloc(sizeof(*pm), GFP_KERNEL);
 	if (pm == NULL) {
-		dev_err(&hdev->dev,
-			"prodikeys: can't alloc descriptor\n");
+		hid_err(hdev, "can't alloc descriptor\n");
 		ret = -ENOMEM;
 		goto err_free;
 	}
@@ -827,7 +828,7 @@ static int pk_probe(struct hid_device *h
 
 	ret = hid_parse(hdev);
 	if (ret) {
-		dev_err(&hdev->dev, "prodikeys: hid parse failed\n");
+		hid_err(hdev, "hid parse failed\n");
 		goto err_free;
 	}
 
@@ -837,7 +838,7 @@ static int pk_probe(struct hid_device *h
 
 	ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
 	if (ret) {
-		dev_err(&hdev->dev, "prodikeys: hw start failed\n");
+		hid_err(hdev, "hw start failed\n");
 		goto err_free;
 	}
 
@@ -896,7 +897,7 @@ static int pk_init(void)
 
 	ret = hid_register_driver(&pk_driver);
 	if (ret)
-		printk(KERN_ERR "can't register prodikeys driver\n");
+		pr_err("can't register prodikeys driver\n");
 
 	return ret;
 }
diff -druNp linux-libre-2.6.37-gnu1/drivers/hid/hid-quanta.c linux-libre-2.6.38-gnu1/drivers/hid/hid-quanta.c
--- linux-libre-2.6.37-gnu1/drivers/hid/hid-quanta.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hid/hid-quanta.c	2011-03-14 21:20:32.000000000 -0400
@@ -195,7 +195,7 @@ static int quanta_probe(struct hid_devic
 
 	td = kmalloc(sizeof(struct quanta_data), GFP_KERNEL);
 	if (!td) {
-		dev_err(&hdev->dev, "cannot allocate Quanta Touch data\n");
+		hid_err(hdev, "cannot allocate Quanta Touch data\n");
 		return -ENOMEM;
 	}
 	td->valid = false;
diff -druNp linux-libre-2.6.37-gnu1/drivers/hid/hidraw.c linux-libre-2.6.38-gnu1/drivers/hid/hidraw.c
--- linux-libre-2.6.37-gnu1/drivers/hid/hidraw.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hid/hidraw.c	2011-03-14 21:20:32.000000000 -0400
@@ -19,6 +19,8 @@
  * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/fs.h>
 #include <linux/module.h>
 #include <linux/errno.h>
@@ -122,15 +124,15 @@ static ssize_t hidraw_write(struct file
 	}
 
 	if (count > HID_MAX_BUFFER_SIZE) {
-		printk(KERN_WARNING "hidraw: pid %d passed too large report\n",
-				task_pid_nr(current));
+		hid_warn(dev, "pid %d passed too large report\n",
+			 task_pid_nr(current));
 		ret = -EINVAL;
 		goto out;
 	}
 
 	if (count < 2) {
-		printk(KERN_WARNING "hidraw: pid %d passed too short report\n",
-				task_pid_nr(current));
+		hid_warn(dev, "pid %d passed too short report\n",
+			 task_pid_nr(current));
 		ret = -EINVAL;
 		goto out;
 	}
@@ -192,15 +194,13 @@ static int hidraw_open(struct inode *ino
 
 	dev = hidraw_table[minor];
 	if (!dev->open++) {
-		if (dev->hid->ll_driver->power) {
-			err = dev->hid->ll_driver->power(dev->hid, PM_HINT_FULLON);
-			if (err < 0)
-				goto out_unlock;
-		}
-		err = dev->hid->ll_driver->open(dev->hid);
+		err = hid_hw_power(dev->hid, PM_HINT_FULLON);
+		if (err < 0)
+			goto out_unlock;
+
+		err = hid_hw_open(dev->hid);
 		if (err < 0) {
-			if (dev->hid->ll_driver->power)
-				dev->hid->ll_driver->power(dev->hid, PM_HINT_NORMAL);
+			hid_hw_power(dev->hid, PM_HINT_NORMAL);
 			dev->open--;
 		}
 	}
@@ -229,9 +229,8 @@ static int hidraw_release(struct inode *
 	dev = hidraw_table[minor];
 	if (!--dev->open) {
 		if (list->hidraw->exist) {
-			if (dev->hid->ll_driver->power)
-				dev->hid->ll_driver->power(dev->hid, PM_HINT_NORMAL);
-			dev->hid->ll_driver->close(dev->hid);
+			hid_hw_power(dev->hid, PM_HINT_NORMAL);
+			hid_hw_close(dev->hid);
 		} else {
 			kfree(list->hidraw);
 		}
@@ -345,6 +344,9 @@ static const struct file_operations hidr
 	.open =         hidraw_open,
 	.release =      hidraw_release,
 	.unlocked_ioctl = hidraw_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl   = hidraw_ioctl,
+#endif
 	.llseek =	noop_llseek,
 };
 
@@ -433,7 +435,7 @@ void hidraw_disconnect(struct hid_device
 	device_destroy(hidraw_class, MKDEV(hidraw_major, hidraw->minor));
 
 	if (hidraw->open) {
-		hid->ll_driver->close(hid);
+		hid_hw_close(hid);
 		wake_up_interruptible(&hidraw->wait);
 	} else {
 		kfree(hidraw);
@@ -452,7 +454,7 @@ int __init hidraw_init(void)
 	hidraw_major = MAJOR(dev_id);
 
 	if (result < 0) {
-		printk(KERN_WARNING "hidraw: can't get major number\n");
+		pr_warn("can't get major number\n");
 		result = 0;
 		goto out;
 	}
diff -druNp linux-libre-2.6.37-gnu1/drivers/hid/hid-roccat.c linux-libre-2.6.38-gnu1/drivers/hid/hid-roccat.c
--- linux-libre-2.6.37-gnu1/drivers/hid/hid-roccat.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hid/hid-roccat.c	2011-03-14 21:20:32.000000000 -0400
@@ -21,6 +21,8 @@
  * It is inspired by hidraw, but uses only one circular buffer for all readers.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/cdev.h>
 #include <linux/poll.h>
 #include <linux/sched.h>
@@ -65,7 +67,6 @@ struct roccat_reader {
 };
 
 static int roccat_major;
-static struct class *roccat_class;
 static struct cdev roccat_cdev;
 
 static struct roccat_device *devices[ROCCAT_MAX_DEVICES];
@@ -165,27 +166,22 @@ static int roccat_open(struct inode *ino
 	mutex_lock(&device->readers_lock);
 
 	if (!device) {
-		printk(KERN_EMERG "roccat device with minor %d doesn't exist\n",
-				minor);
+		pr_emerg("roccat device with minor %d doesn't exist\n", minor);
 		error = -ENODEV;
 		goto exit_err;
 	}
 
 	if (!device->open++) {
 		/* power on device on adding first reader */
-		if (device->hid->ll_driver->power) {
-			error = device->hid->ll_driver->power(device->hid,
-					PM_HINT_FULLON);
-			if (error < 0) {
-				--device->open;
-				goto exit_err;
-			}
+		error = hid_hw_power(device->hid, PM_HINT_FULLON);
+		if (error < 0) {
+			--device->open;
+			goto exit_err;
 		}
-		error = device->hid->ll_driver->open(device->hid);
+
+		error = hid_hw_open(device->hid);
 		if (error < 0) {
-			if (device->hid->ll_driver->power)
-				device->hid->ll_driver->power(device->hid,
-						PM_HINT_NORMAL);
+			hid_hw_power(device->hid, PM_HINT_NORMAL);
 			--device->open;
 			goto exit_err;
 		}
@@ -218,8 +214,7 @@ static int roccat_release(struct inode *
 	device = devices[minor];
 	if (!device) {
 		mutex_unlock(&devices_lock);
-		printk(KERN_EMERG "roccat device with minor %d doesn't exist\n",
-				minor);
+		pr_emerg("roccat device with minor %d doesn't exist\n", minor);
 		return -ENODEV;
 	}
 
@@ -231,10 +226,8 @@ static int roccat_release(struct inode *
 	if (!--device->open) {
 		/* removing last reader */
 		if (device->exist) {
-			if (device->hid->ll_driver->power)
-				device->hid->ll_driver->power(device->hid,
-						PM_HINT_NORMAL);
-			device->hid->ll_driver->close(device->hid);
+			hid_hw_power(device->hid, PM_HINT_NORMAL);
+			hid_hw_close(device->hid);
 		} else {
 			kfree(device);
 		}
@@ -295,12 +288,14 @@ EXPORT_SYMBOL_GPL(roccat_report_event);
 
 /*
  * roccat_connect() - create a char device for special event output
+ * @class: the class thats used to create the device. Meant to hold device
+ * specific sysfs attributes.
  * @hid: the hid device the char device should be connected to.
  *
  * Return value is minor device number in Range [0, ROCCAT_MAX_DEVICES] on
  * success, a negative error code on failure.
  */
-int roccat_connect(struct hid_device *hid)
+int roccat_connect(struct class *klass, struct hid_device *hid)
 {
 	unsigned int minor;
 	struct roccat_device *device;
@@ -326,7 +321,7 @@ int roccat_connect(struct hid_device *hi
 		return -EINVAL;
 	}
 
-	device->dev = device_create(roccat_class, &hid->dev,
+	device->dev = device_create(klass, &hid->dev,
 			MKDEV(roccat_major, minor), NULL,
 			"%s%s%d", "roccat", hid->driver->name, minor);
 
@@ -367,10 +362,10 @@ void roccat_disconnect(int minor)
 
 	device->exist = 0; /* TODO exist maybe not needed */
 
-	device_destroy(roccat_class, MKDEV(roccat_major, minor));
+	device_destroy(device->dev->class, MKDEV(roccat_major, minor));
 
 	if (device->open) {
-		device->hid->ll_driver->close(device->hid);
+		hid_hw_close(device->hid);
 		wake_up_interruptible(&device->wait);
 	} else {
 		kfree(device);
@@ -398,14 +393,7 @@ static int __init roccat_init(void)
 	roccat_major = MAJOR(dev_id);
 
 	if (retval < 0) {
-		printk(KERN_WARNING "roccat: can't get major number\n");
-		return retval;
-	}
-
-	roccat_class = class_create(THIS_MODULE, "roccat");
-	if (IS_ERR(roccat_class)) {
-		retval = PTR_ERR(roccat_class);
-		unregister_chrdev_region(dev_id, ROCCAT_MAX_DEVICES);
+		pr_warn("can't get major number\n");
 		return retval;
 	}
 
@@ -420,7 +408,6 @@ static void __exit roccat_exit(void)
 	dev_t dev_id = MKDEV(roccat_major, 0);
 
 	cdev_del(&roccat_cdev);
-	class_destroy(roccat_class);
 	unregister_chrdev_region(dev_id, ROCCAT_MAX_DEVICES);
 }
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/hid/hid-roccat.h linux-libre-2.6.38-gnu1/drivers/hid/hid-roccat.h
--- linux-libre-2.6.37-gnu1/drivers/hid/hid-roccat.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hid/hid-roccat.h	2011-03-14 21:20:32.000000000 -0400
@@ -16,11 +16,12 @@
 #include <linux/types.h>
 
 #if defined(CONFIG_HID_ROCCAT) || defined(CONFIG_HID_ROCCAT_MODULE)
-int roccat_connect(struct hid_device *hid);
+int roccat_connect(struct class *klass, struct hid_device *hid);
 void roccat_disconnect(int minor);
 int roccat_report_event(int minor, u8 const *data, int len);
 #else
-static inline int roccat_connect(struct hid_device *hid) { return -1; }
+static inline int roccat_connect(struct class *klass,
+		struct hid_device *hid) { return -1; }
 static inline void roccat_disconnect(int minor) {}
 static inline int roccat_report_event(int minor, u8 const *data, int len)
 {
diff -druNp linux-libre-2.6.37-gnu1/drivers/hid/hid-roccat-kone.c linux-libre-2.6.38-gnu1/drivers/hid/hid-roccat-kone.c
--- linux-libre-2.6.37-gnu1/drivers/hid/hid-roccat-kone.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hid/hid-roccat-kone.c	2011-03-14 21:20:32.000000000 -0400
@@ -35,6 +35,11 @@
 #include "hid-roccat.h"
 #include "hid-roccat-kone.h"
 
+static uint profile_numbers[5] = {0, 1, 2, 3, 4};
+
+/* kone_class is used for creating sysfs attributes via roccat char device */
+static struct class *kone_class;
+
 static void kone_set_settings_checksum(struct kone_settings *settings)
 {
 	uint16_t checksum = 0;
@@ -90,8 +95,7 @@ static int kone_check_write(struct usb_d
 		kfree(data);
 		return 0;
 	} else { /* unknown answer */
-		dev_err(&usb_dev->dev, "got retval %d when checking write\n",
-				*data);
+		hid_err(usb_dev, "got retval %d when checking write\n", *data);
 		kfree(data);
 		return -EIO;
 	}
@@ -262,7 +266,8 @@ static int kone_get_firmware_version(str
 static ssize_t kone_sysfs_read_settings(struct file *fp, struct kobject *kobj,
 		struct bin_attribute *attr, char *buf,
 		loff_t off, size_t count) {
-	struct device *dev = container_of(kobj, struct device, kobj);
+	struct device *dev =
+			container_of(kobj, struct device, kobj)->parent->parent;
 	struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev));
 
 	if (off >= sizeof(struct kone_settings))
@@ -286,7 +291,8 @@ static ssize_t kone_sysfs_read_settings(
 static ssize_t kone_sysfs_write_settings(struct file *fp, struct kobject *kobj,
 		struct bin_attribute *attr, char *buf,
 		loff_t off, size_t count) {
-	struct device *dev = container_of(kobj, struct device, kobj);
+	struct device *dev =
+			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;
@@ -319,10 +325,11 @@ static ssize_t kone_sysfs_write_settings
 	return sizeof(struct kone_settings);
 }
 
-static ssize_t kone_sysfs_read_profilex(struct kobject *kobj,
-		struct bin_attribute *attr, char *buf,
-		loff_t off, size_t count, int number) {
-	struct device *dev = container_of(kobj, struct device, kobj);
+static ssize_t kone_sysfs_read_profilex(struct file *fp,
+		struct kobject *kobj, struct bin_attribute *attr,
+		char *buf, loff_t off, size_t count) {
+	struct device *dev =
+			container_of(kobj, struct device, kobj)->parent->parent;
 	struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev));
 
 	if (off >= sizeof(struct kone_profile))
@@ -332,47 +339,18 @@ static ssize_t kone_sysfs_read_profilex(
 		count = sizeof(struct kone_profile) - off;
 
 	mutex_lock(&kone->kone_lock);
-	memcpy(buf, ((char const *)&kone->profiles[number - 1]) + off, count);
+	memcpy(buf, ((char const *)&kone->profiles[*(uint *)(attr->private)]) + off, count);
 	mutex_unlock(&kone->kone_lock);
 
 	return count;
 }
 
-static ssize_t kone_sysfs_read_profile1(struct file *fp, struct kobject *kobj,
-		struct bin_attribute *attr, char *buf,
-		loff_t off, size_t count) {
-	return kone_sysfs_read_profilex(kobj, attr, buf, off, count, 1);
-}
-
-static ssize_t kone_sysfs_read_profile2(struct file *fp, struct kobject *kobj,
-		struct bin_attribute *attr, char *buf,
-		loff_t off, size_t count) {
-	return kone_sysfs_read_profilex(kobj, attr, buf, off, count, 2);
-}
-
-static ssize_t kone_sysfs_read_profile3(struct file *fp, struct kobject *kobj,
-		struct bin_attribute *attr, char *buf,
-		loff_t off, size_t count) {
-	return kone_sysfs_read_profilex(kobj, attr, buf, off, count, 3);
-}
-
-static ssize_t kone_sysfs_read_profile4(struct file *fp, struct kobject *kobj,
-		struct bin_attribute *attr, char *buf,
-		loff_t off, size_t count) {
-	return kone_sysfs_read_profilex(kobj, attr, buf, off, count, 4);
-}
-
-static ssize_t kone_sysfs_read_profile5(struct file *fp, struct kobject *kobj,
-		struct bin_attribute *attr, char *buf,
-		loff_t off, size_t count) {
-	return kone_sysfs_read_profilex(kobj, attr, buf, off, count, 5);
-}
-
 /* Writes data only if different to stored data */
-static ssize_t kone_sysfs_write_profilex(struct kobject *kobj,
-		struct bin_attribute *attr, char *buf,
-		loff_t off, size_t count, int number) {
-	struct device *dev = container_of(kobj, struct device, kobj);
+static ssize_t kone_sysfs_write_profilex(struct file *fp,
+		struct kobject *kobj, struct bin_attribute *attr,
+		char *buf, loff_t off, size_t count) {
+	struct device *dev =
+			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));
 	struct kone_profile *profile;
@@ -382,13 +360,14 @@ static ssize_t kone_sysfs_write_profilex
 	if (off != 0 || count != sizeof(struct kone_profile))
 		return -EINVAL;
 
-	profile = &kone->profiles[number - 1];
+	profile = &kone->profiles[*(uint *)(attr->private)];
 
 	mutex_lock(&kone->kone_lock);
 	difference = memcmp(buf, profile, sizeof(struct kone_profile));
 	if (difference) {
 		retval = kone_set_profile(usb_dev,
-				(struct kone_profile const *)buf, number);
+				(struct kone_profile const *)buf,
+				*(uint *)(attr->private) + 1);
 		if (!retval)
 			memcpy(profile, buf, sizeof(struct kone_profile));
 	}
@@ -400,47 +379,19 @@ static ssize_t kone_sysfs_write_profilex
 	return sizeof(struct kone_profile);
 }
 
-static ssize_t kone_sysfs_write_profile1(struct file *fp, struct kobject *kobj,
-		struct bin_attribute *attr, char *buf,
-		loff_t off, size_t count) {
-	return kone_sysfs_write_profilex(kobj, attr, buf, off, count, 1);
-}
-
-static ssize_t kone_sysfs_write_profile2(struct file *fp, struct kobject *kobj,
-		struct bin_attribute *attr, char *buf,
-		loff_t off, size_t count) {
-	return kone_sysfs_write_profilex(kobj, attr, buf, off, count, 2);
-}
-
-static ssize_t kone_sysfs_write_profile3(struct file *fp, struct kobject *kobj,
-		struct bin_attribute *attr, char *buf,
-		loff_t off, size_t count) {
-	return kone_sysfs_write_profilex(kobj, attr, buf, off, count, 3);
-}
-
-static ssize_t kone_sysfs_write_profile4(struct file *fp, struct kobject *kobj,
-		struct bin_attribute *attr, char *buf,
-		loff_t off, size_t count) {
-	return kone_sysfs_write_profilex(kobj, attr, buf, off, count, 4);
-}
-
-static ssize_t kone_sysfs_write_profile5(struct file *fp, struct kobject *kobj,
-		struct bin_attribute *attr, char *buf,
-		loff_t off, size_t count) {
-	return kone_sysfs_write_profilex(kobj, attr, buf, off, count, 5);
-}
-
 static ssize_t kone_sysfs_show_actual_profile(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
-	struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev));
+	struct kone_device *kone =
+			hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
 	return snprintf(buf, PAGE_SIZE, "%d\n", kone->actual_profile);
 }
 
 static ssize_t kone_sysfs_show_actual_dpi(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
-	struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev));
+	struct kone_device *kone =
+			hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
 	return snprintf(buf, PAGE_SIZE, "%d\n", kone->actual_dpi);
 }
 
@@ -448,11 +399,15 @@ static ssize_t kone_sysfs_show_actual_dp
 static ssize_t kone_sysfs_show_weight(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
-	struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev));
-	struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
+	struct kone_device *kone;
+	struct usb_device *usb_dev;
 	int weight = 0;
 	int retval;
 
+	dev = dev->parent->parent;
+	kone = hid_get_drvdata(dev_get_drvdata(dev));
+	usb_dev = interface_to_usbdev(to_usb_interface(dev));
+
 	mutex_lock(&kone->kone_lock);
 	retval = kone_get_weight(usb_dev, &weight);
 	mutex_unlock(&kone->kone_lock);
@@ -465,14 +420,16 @@ static ssize_t kone_sysfs_show_weight(st
 static ssize_t kone_sysfs_show_firmware_version(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
-	struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev));
+	struct kone_device *kone =
+			hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
 	return snprintf(buf, PAGE_SIZE, "%d\n", kone->firmware_version);
 }
 
 static ssize_t kone_sysfs_show_tcu(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
-	struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev));
+	struct kone_device *kone =
+			hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
 	return snprintf(buf, PAGE_SIZE, "%d\n", kone->settings.tcu);
 }
 
@@ -504,11 +461,15 @@ static int kone_tcu_command(struct usb_d
 static ssize_t kone_sysfs_set_tcu(struct device *dev,
 		struct device_attribute *attr, char const *buf, size_t size)
 {
-	struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev));
-	struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
+	struct kone_device *kone;
+	struct usb_device *usb_dev;
 	int retval;
 	unsigned long state;
 
+	dev = dev->parent->parent;
+	kone = hid_get_drvdata(dev_get_drvdata(dev));
+	usb_dev = interface_to_usbdev(to_usb_interface(dev));
+
 	retval = strict_strtoul(buf, 10, &state);
 	if (retval)
 		return retval;
@@ -556,7 +517,7 @@ static ssize_t kone_sysfs_set_tcu(struct
 
 		retval = kone_set_settings(usb_dev, &kone->settings);
 		if (retval) {
-			dev_err(&usb_dev->dev, "couldn't set tcu state\n");
+			hid_err(usb_dev, "couldn't set tcu state\n");
 			/*
 			 * try to reread valid settings into buffer overwriting
 			 * first error code
@@ -570,7 +531,7 @@ static ssize_t kone_sysfs_set_tcu(struct
 
 	retval = size;
 exit_no_settings:
-	dev_err(&usb_dev->dev, "couldn't read settings\n");
+	hid_err(usb_dev, "couldn't read settings\n");
 exit_unlock:
 	mutex_unlock(&kone->kone_lock);
 	return retval;
@@ -579,18 +540,23 @@ exit_unlock:
 static ssize_t kone_sysfs_show_startup_profile(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
-	struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev));
+	struct kone_device *kone =
+			hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
 	return snprintf(buf, PAGE_SIZE, "%d\n", kone->settings.startup_profile);
 }
 
 static ssize_t kone_sysfs_set_startup_profile(struct device *dev,
 		struct device_attribute *attr, char const *buf, size_t size)
 {
-	struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev));
-	struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
+	struct kone_device *kone;
+	struct usb_device *usb_dev;
 	int retval;
 	unsigned long new_startup_profile;
 
+	dev = dev->parent->parent;
+	kone = hid_get_drvdata(dev_get_drvdata(dev));
+	usb_dev = interface_to_usbdev(to_usb_interface(dev));
+
 	retval = strict_strtoul(buf, 10, &new_startup_profile);
 	if (retval)
 		return retval;
@@ -617,160 +583,92 @@ static ssize_t kone_sysfs_set_startup_pr
 	return size;
 }
 
-/*
- * Read actual dpi settings.
- * Returns raw value for further processing. Refer to enum kone_polling_rates to
- * get real value.
- */
-static DEVICE_ATTR(actual_dpi, 0440, kone_sysfs_show_actual_dpi, NULL);
-
-static DEVICE_ATTR(actual_profile, 0440, kone_sysfs_show_actual_profile, NULL);
-
-/*
- * The mouse can be equipped with one of four supplied weights from 5 to 20
- * grams which are recognized and its value can be read out.
- * This returns the raw value reported by the mouse for easy evaluation by
- * software. Refer to enum kone_weights to get corresponding real weight.
- */
-static DEVICE_ATTR(weight, 0440, kone_sysfs_show_weight, NULL);
-
-/*
- * Prints firmware version stored in mouse as integer.
- * The raw value reported by the mouse is returned for easy evaluation, to get
- * the real version number the decimal point has to be shifted 2 positions to
- * the left. E.g. a value of 138 means 1.38.
- */
-static DEVICE_ATTR(firmware_version, 0440,
-		kone_sysfs_show_firmware_version, NULL);
-
-/*
- * Prints state of Tracking Control Unit as number where 0 = off and 1 = on
- * Writing 0 deactivates tcu and writing 1 calibrates and activates the tcu
- */
-static DEVICE_ATTR(tcu, 0660, kone_sysfs_show_tcu, kone_sysfs_set_tcu);
-
-/* Prints and takes the number of the profile the mouse starts with */
-static DEVICE_ATTR(startup_profile, 0660,
-		kone_sysfs_show_startup_profile,
-		kone_sysfs_set_startup_profile);
-
-static struct attribute *kone_attributes[] = {
-		&dev_attr_actual_dpi.attr,
-		&dev_attr_actual_profile.attr,
-		&dev_attr_weight.attr,
-		&dev_attr_firmware_version.attr,
-		&dev_attr_tcu.attr,
-		&dev_attr_startup_profile.attr,
-		NULL
-};
-
-static struct attribute_group kone_attribute_group = {
-		.attrs = kone_attributes
-};
-
-static struct bin_attribute kone_settings_attr = {
-	.attr = { .name = "settings", .mode = 0660 },
-	.size = sizeof(struct kone_settings),
-	.read = kone_sysfs_read_settings,
-	.write = kone_sysfs_write_settings
-};
+static struct device_attribute kone_attributes[] = {
+	/*
+	 * Read actual dpi settings.
+	 * Returns raw value for further processing. Refer to enum
+	 * kone_polling_rates to get real value.
+	 */
+	__ATTR(actual_dpi, 0440, kone_sysfs_show_actual_dpi, NULL),
+	__ATTR(actual_profile, 0440, kone_sysfs_show_actual_profile, NULL),
 
-static struct bin_attribute kone_profile1_attr = {
-	.attr = { .name = "profile1", .mode = 0660 },
-	.size = sizeof(struct kone_profile),
-	.read = kone_sysfs_read_profile1,
-	.write = kone_sysfs_write_profile1
-};
+	/*
+	 * The mouse can be equipped with one of four supplied weights from 5
+	 * to 20 grams which are recognized and its value can be read out.
+	 * This returns the raw value reported by the mouse for easy evaluation
+	 * by software. Refer to enum kone_weights to get corresponding real
+	 * weight.
+	 */
+	__ATTR(weight, 0440, kone_sysfs_show_weight, NULL),
 
-static struct bin_attribute kone_profile2_attr = {
-	.attr = { .name = "profile2", .mode = 0660 },
-	.size = sizeof(struct kone_profile),
-	.read = kone_sysfs_read_profile2,
-	.write = kone_sysfs_write_profile2
-};
+	/*
+	 * Prints firmware version stored in mouse as integer.
+	 * The raw value reported by the mouse is returned for easy evaluation,
+	 * to get the real version number the decimal point has to be shifted 2
+	 * positions to the left. E.g. a value of 138 means 1.38.
+	 */
+	__ATTR(firmware_version, 0440,
+			kone_sysfs_show_firmware_version, NULL),
 
-static struct bin_attribute kone_profile3_attr = {
-	.attr = { .name = "profile3", .mode = 0660 },
-	.size = sizeof(struct kone_profile),
-	.read = kone_sysfs_read_profile3,
-	.write = kone_sysfs_write_profile3
-};
+	/*
+	 * Prints state of Tracking Control Unit as number where 0 = off and
+	 * 1 = on. Writing 0 deactivates tcu and writing 1 calibrates and
+	 * activates the tcu
+	 */
+	__ATTR(tcu, 0660, kone_sysfs_show_tcu, kone_sysfs_set_tcu),
 
-static struct bin_attribute kone_profile4_attr = {
-	.attr = { .name = "profile4", .mode = 0660 },
-	.size = sizeof(struct kone_profile),
-	.read = kone_sysfs_read_profile4,
-	.write = kone_sysfs_write_profile4
+	/* Prints and takes the number of the profile the mouse starts with */
+	__ATTR(startup_profile, 0660,
+			kone_sysfs_show_startup_profile,
+			kone_sysfs_set_startup_profile),
+	__ATTR_NULL
 };
 
-static struct bin_attribute kone_profile5_attr = {
-	.attr = { .name = "profile5", .mode = 0660 },
-	.size = sizeof(struct kone_profile),
-	.read = kone_sysfs_read_profile5,
-	.write = kone_sysfs_write_profile5
+static struct bin_attribute kone_bin_attributes[] = {
+	{
+		.attr = { .name = "settings", .mode = 0660 },
+		.size = sizeof(struct kone_settings),
+		.read = kone_sysfs_read_settings,
+		.write = kone_sysfs_write_settings
+	},
+	{
+		.attr = { .name = "profile1", .mode = 0660 },
+		.size = sizeof(struct kone_profile),
+		.read = kone_sysfs_read_profilex,
+		.write = kone_sysfs_write_profilex,
+		.private = &profile_numbers[0]
+	},
+	{
+		.attr = { .name = "profile2", .mode = 0660 },
+		.size = sizeof(struct kone_profile),
+		.read = kone_sysfs_read_profilex,
+		.write = kone_sysfs_write_profilex,
+		.private = &profile_numbers[1]
+	},
+	{
+		.attr = { .name = "profile3", .mode = 0660 },
+		.size = sizeof(struct kone_profile),
+		.read = kone_sysfs_read_profilex,
+		.write = kone_sysfs_write_profilex,
+		.private = &profile_numbers[2]
+	},
+	{
+		.attr = { .name = "profile4", .mode = 0660 },
+		.size = sizeof(struct kone_profile),
+		.read = kone_sysfs_read_profilex,
+		.write = kone_sysfs_write_profilex,
+		.private = &profile_numbers[3]
+	},
+	{
+		.attr = { .name = "profile5", .mode = 0660 },
+		.size = sizeof(struct kone_profile),
+		.read = kone_sysfs_read_profilex,
+		.write = kone_sysfs_write_profilex,
+		.private = &profile_numbers[4]
+	},
+	__ATTR_NULL
 };
 
-static int kone_create_sysfs_attributes(struct usb_interface *intf)
-{
-	int retval;
-
-	retval = sysfs_create_group(&intf->dev.kobj, &kone_attribute_group);
-	if (retval)
-		goto exit_1;
-
-	retval = sysfs_create_bin_file(&intf->dev.kobj, &kone_settings_attr);
-	if (retval)
-		goto exit_2;
-
-	retval = sysfs_create_bin_file(&intf->dev.kobj, &kone_profile1_attr);
-	if (retval)
-		goto exit_3;
-
-	retval = sysfs_create_bin_file(&intf->dev.kobj, &kone_profile2_attr);
-	if (retval)
-		goto exit_4;
-
-	retval = sysfs_create_bin_file(&intf->dev.kobj, &kone_profile3_attr);
-	if (retval)
-		goto exit_5;
-
-	retval = sysfs_create_bin_file(&intf->dev.kobj, &kone_profile4_attr);
-	if (retval)
-		goto exit_6;
-
-	retval = sysfs_create_bin_file(&intf->dev.kobj, &kone_profile5_attr);
-	if (retval)
-		goto exit_7;
-
-	return 0;
-
-exit_7:
-	sysfs_remove_bin_file(&intf->dev.kobj, &kone_profile4_attr);
-exit_6:
-	sysfs_remove_bin_file(&intf->dev.kobj, &kone_profile3_attr);
-exit_5:
-	sysfs_remove_bin_file(&intf->dev.kobj, &kone_profile2_attr);
-exit_4:
-	sysfs_remove_bin_file(&intf->dev.kobj, &kone_profile1_attr);
-exit_3:
-	sysfs_remove_bin_file(&intf->dev.kobj, &kone_settings_attr);
-exit_2:
-	sysfs_remove_group(&intf->dev.kobj, &kone_attribute_group);
-exit_1:
-	return retval;
-}
-
-static void kone_remove_sysfs_attributes(struct usb_interface *intf)
-{
-	sysfs_remove_bin_file(&intf->dev.kobj, &kone_profile5_attr);
-	sysfs_remove_bin_file(&intf->dev.kobj, &kone_profile4_attr);
-	sysfs_remove_bin_file(&intf->dev.kobj, &kone_profile3_attr);
-	sysfs_remove_bin_file(&intf->dev.kobj, &kone_profile2_attr);
-	sysfs_remove_bin_file(&intf->dev.kobj, &kone_profile1_attr);
-	sysfs_remove_bin_file(&intf->dev.kobj, &kone_settings_attr);
-	sysfs_remove_group(&intf->dev.kobj, &kone_attribute_group);
-}
-
 static int kone_init_kone_device_struct(struct usb_device *usb_dev,
 		struct kone_device *kone)
 {
@@ -818,32 +716,25 @@ static int kone_init_specials(struct hid
 
 		kone = kzalloc(sizeof(*kone), GFP_KERNEL);
 		if (!kone) {
-			dev_err(&hdev->dev, "can't alloc device descriptor\n");
+			hid_err(hdev, "can't alloc device descriptor\n");
 			return -ENOMEM;
 		}
 		hid_set_drvdata(hdev, kone);
 
 		retval = kone_init_kone_device_struct(usb_dev, kone);
 		if (retval) {
-			dev_err(&hdev->dev,
-					"couldn't init struct kone_device\n");
+			hid_err(hdev, "couldn't init struct kone_device\n");
 			goto exit_free;
 		}
 
-		retval = roccat_connect(hdev);
+		retval = roccat_connect(kone_class, hdev);
 		if (retval < 0) {
-			dev_err(&hdev->dev, "couldn't init char dev\n");
+			hid_err(hdev, "couldn't init char dev\n");
 			/* be tolerant about not getting chrdev */
 		} else {
 			kone->roccat_claimed = 1;
 			kone->chrdev_minor = retval;
 		}
-
-		retval = kone_create_sysfs_attributes(intf);
-		if (retval) {
-			dev_err(&hdev->dev, "cannot create sysfs files\n");
-			goto exit_free;
-		}
 	} else {
 		hid_set_drvdata(hdev, NULL);
 	}
@@ -854,7 +745,6 @@ exit_free:
 	return retval;
 }
 
-
 static void kone_remove_specials(struct hid_device *hdev)
 {
 	struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
@@ -862,7 +752,6 @@ static void kone_remove_specials(struct
 
 	if (intf->cur_altsetting->desc.bInterfaceProtocol
 			== USB_INTERFACE_PROTOCOL_MOUSE) {
-		kone_remove_sysfs_attributes(intf);
 		kone = hid_get_drvdata(hdev);
 		if (kone->roccat_claimed)
 			roccat_disconnect(kone->chrdev_minor);
@@ -876,19 +765,19 @@ static int kone_probe(struct hid_device
 
 	retval = hid_parse(hdev);
 	if (retval) {
-		dev_err(&hdev->dev, "parse failed\n");
+		hid_err(hdev, "parse failed\n");
 		goto exit;
 	}
 
 	retval = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
 	if (retval) {
-		dev_err(&hdev->dev, "hw start failed\n");
+		hid_err(hdev, "hw start failed\n");
 		goto exit;
 	}
 
 	retval = kone_init_specials(hdev);
 	if (retval) {
-		dev_err(&hdev->dev, "couldn't install mouse\n");
+		hid_err(hdev, "couldn't install mouse\n");
 		goto exit_stop;
 	}
 
@@ -1006,11 +895,24 @@ static struct hid_driver kone_driver = {
 
 static int __init kone_init(void)
 {
-	return hid_register_driver(&kone_driver);
+	int retval;
+
+	/* class name has to be same as driver name */
+	kone_class = class_create(THIS_MODULE, "kone");
+	if (IS_ERR(kone_class))
+		return PTR_ERR(kone_class);
+	kone_class->dev_attrs = kone_attributes;
+	kone_class->dev_bin_attrs = kone_bin_attributes;
+
+	retval = hid_register_driver(&kone_driver);
+	if (retval)
+		class_destroy(kone_class);
+	return retval;
 }
 
 static void __exit kone_exit(void)
 {
+	class_destroy(kone_class);
 	hid_unregister_driver(&kone_driver);
 }
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/hid/hid-roccat-kone.h linux-libre-2.6.38-gnu1/drivers/hid/hid-roccat-kone.h
--- linux-libre-2.6.37-gnu1/drivers/hid/hid-roccat-kone.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hid/hid-roccat-kone.h	2011-03-14 21:20:32.000000000 -0400
@@ -14,14 +14,11 @@
 
 #include <linux/types.h>
 
-#pragma pack(push)
-#pragma pack(1)
-
 struct kone_keystroke {
 	uint8_t key;
 	uint8_t action;
 	uint16_t period; /* in milliseconds */
-};
+} __attribute__ ((__packed__));
 
 enum kone_keystroke_buttons {
 	kone_keystroke_button_1 = 0xf0, /* left mouse button */
@@ -44,7 +41,7 @@ struct kone_button_info {
 	uint8_t macro_name[16]; /* can be max 15 chars long */
 	uint8_t count;
 	struct kone_keystroke keystrokes[20];
-};
+} __attribute__ ((__packed__));
 
 enum kone_button_info_types {
 	/* valid button types until firmware 1.32 */
@@ -95,7 +92,7 @@ struct kone_light_info {
 	uint8_t red;   /* range 0x00-0xff */
 	uint8_t green; /* range 0x00-0xff */
 	uint8_t blue;  /* range 0x00-0xff */
-};
+} __attribute__ ((__packed__));
 
 struct kone_profile {
 	uint16_t size; /* always 975 */
@@ -130,7 +127,7 @@ struct kone_profile {
 	struct kone_button_info button_infos[8];
 
 	uint16_t checksum; /* \brief holds checksum of struct */
-};
+} __attribute__ ((__packed__));
 
 enum kone_polling_rates {
 	kone_polling_rate_125 = 1,
@@ -147,7 +144,7 @@ struct kone_settings {
 	uint8_t  calibration_data[4];
 	uint8_t  unknown3[2];
 	uint16_t checksum;
-};
+} __attribute__ ((__packed__));
 
 /*
  * 12 byte mouse event read by interrupt_read
@@ -163,7 +160,7 @@ struct kone_mouse_event {
 	uint8_t event;
 	uint8_t value; /* press = 0, release = 1 */
 	uint8_t macro_key; /* 0 to 8 */
-};
+} __attribute__ ((__packed__));
 
 enum kone_mouse_events {
 	/* osd events are thought to be display on screen */
@@ -191,9 +188,7 @@ struct kone_roccat_report {
 	uint8_t event;
 	uint8_t value; /* holds dpi or profile value */
 	uint8_t key; /* macro key on overlong macro execution */
-};
-
-#pragma pack(pop)
+} __attribute__ ((__packed__));
 
 struct kone_device {
 	/*
diff -druNp linux-libre-2.6.37-gnu1/drivers/hid/hid-roccat-koneplus.c linux-libre-2.6.38-gnu1/drivers/hid/hid-roccat-koneplus.c
--- linux-libre-2.6.37-gnu1/drivers/hid/hid-roccat-koneplus.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hid/hid-roccat-koneplus.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,837 @@
+/*
+ * Roccat Kone[+] driver for Linux
+ *
+ * Copyright (c) 2010 Stefan Achatz <erazor_de@users.sourceforge.net>
+ */
+
+/*
+ * 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.
+ */
+
+/*
+ * Roccat Kone[+] is an updated/improved version of the Kone with more memory
+ * and functionality and without the non-standard behaviours the Kone had.
+ */
+
+#include <linux/device.h>
+#include <linux/input.h>
+#include <linux/hid.h>
+#include <linux/usb.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include "hid-ids.h"
+#include "hid-roccat.h"
+#include "hid-roccat-koneplus.h"
+
+static uint profile_numbers[5] = {0, 1, 2, 3, 4};
+
+static struct class *koneplus_class;
+
+static void koneplus_profile_activated(struct koneplus_device *koneplus,
+		uint new_profile)
+{
+	koneplus->actual_profile = new_profile;
+}
+
+static int koneplus_send_control(struct usb_device *usb_dev, uint value,
+		enum koneplus_control_requests request)
+{
+	int len;
+	struct koneplus_control *control;
+
+	if ((request == KONEPLUS_CONTROL_REQUEST_PROFILE_SETTINGS ||
+			request == KONEPLUS_CONTROL_REQUEST_PROFILE_BUTTONS) &&
+			value > 4)
+		return -EINVAL;
+
+	control = kmalloc(sizeof(struct koneplus_control), GFP_KERNEL);
+	if (!control)
+		return -ENOMEM;
+
+	control->command = KONEPLUS_COMMAND_CONTROL;
+	control->value = value;
+	control->request = request;
+
+	len = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0),
+			USB_REQ_SET_CONFIGURATION,
+			USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT,
+			KONEPLUS_USB_COMMAND_CONTROL, 0, control,
+			sizeof(struct koneplus_control),
+			USB_CTRL_SET_TIMEOUT);
+
+	kfree(control);
+
+	if (len != sizeof(struct koneplus_control))
+		return len;
+
+	return 0;
+}
+
+static int koneplus_receive(struct usb_device *usb_dev, uint usb_command,
+		void *buf, uint size) {
+	int len;
+
+	len = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0),
+			USB_REQ_CLEAR_FEATURE,
+			USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
+			usb_command, 0, buf, size, USB_CTRL_SET_TIMEOUT);
+
+	return (len != size) ? -EIO : 0;
+}
+
+static int koneplus_receive_control_status(struct usb_device *usb_dev)
+{
+	int retval;
+	struct koneplus_control *control;
+
+	control = kmalloc(sizeof(struct koneplus_control), GFP_KERNEL);
+	if (!control)
+		return -ENOMEM;
+
+	do {
+		retval = koneplus_receive(usb_dev, KONEPLUS_USB_COMMAND_CONTROL,
+				control, sizeof(struct koneplus_control));
+
+		/* check if we get a completely wrong answer */
+		if (retval)
+			goto out;
+
+		if (control->value == KONEPLUS_CONTROL_REQUEST_STATUS_OK) {
+			retval = 0;
+			goto out;
+		}
+
+		/* indicates that hardware needs some more time to complete action */
+		if (control->value == KONEPLUS_CONTROL_REQUEST_STATUS_WAIT) {
+			msleep(500); /* windows driver uses 1000 */
+			continue;
+		}
+
+		/* seems to be critical - replug necessary */
+		if (control->value == KONEPLUS_CONTROL_REQUEST_STATUS_OVERLOAD) {
+			retval = -EINVAL;
+			goto out;
+		}
+
+		dev_err(&usb_dev->dev, "koneplus_receive_control_status: "
+				"unknown response value 0x%x\n", control->value);
+		retval = -EINVAL;
+		goto out;
+
+	} while (1);
+out:
+	kfree(control);
+	return retval;
+}
+
+static int koneplus_send(struct usb_device *usb_dev, uint command,
+		void *buf, uint size) {
+	int len;
+
+	len = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0),
+			USB_REQ_SET_CONFIGURATION,
+			USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT,
+			command, 0, buf, size, USB_CTRL_SET_TIMEOUT);
+
+	if (len != size)
+		return -EIO;
+
+	if (koneplus_receive_control_status(usb_dev))
+		return -EIO;
+
+	return 0;
+}
+
+static int koneplus_select_profile(struct usb_device *usb_dev, uint number,
+		enum koneplus_control_requests request)
+{
+	int retval;
+
+	retval = koneplus_send_control(usb_dev, number, request);
+	if (retval)
+		return retval;
+
+	/* allow time to settle things - windows driver uses 500 */
+	msleep(100);
+
+	retval = koneplus_receive_control_status(usb_dev);
+	if (retval)
+		return retval;
+
+	return 0;
+}
+
+static int koneplus_get_info(struct usb_device *usb_dev,
+		struct koneplus_info *buf)
+{
+	return koneplus_receive(usb_dev, KONEPLUS_USB_COMMAND_INFO,
+			buf, sizeof(struct koneplus_info));
+}
+
+static int koneplus_get_profile_settings(struct usb_device *usb_dev,
+		struct koneplus_profile_settings *buf, uint number)
+{
+	int retval;
+
+	retval = koneplus_select_profile(usb_dev, number,
+			KONEPLUS_CONTROL_REQUEST_PROFILE_SETTINGS);
+	if (retval)
+		return retval;
+
+	return koneplus_receive(usb_dev, KONEPLUS_USB_COMMAND_PROFILE_SETTINGS,
+			buf, sizeof(struct koneplus_profile_settings));
+}
+
+static int koneplus_set_profile_settings(struct usb_device *usb_dev,
+		struct koneplus_profile_settings const *settings)
+{
+	return koneplus_send(usb_dev, KONEPLUS_USB_COMMAND_PROFILE_SETTINGS,
+			(void *)settings, sizeof(struct koneplus_profile_settings));
+}
+
+static int koneplus_get_profile_buttons(struct usb_device *usb_dev,
+		struct koneplus_profile_buttons *buf, int number)
+{
+	int retval;
+
+	retval = koneplus_select_profile(usb_dev, number,
+			KONEPLUS_CONTROL_REQUEST_PROFILE_BUTTONS);
+	if (retval)
+		return retval;
+
+	return koneplus_receive(usb_dev, KONEPLUS_USB_COMMAND_PROFILE_BUTTONS,
+			buf, sizeof(struct koneplus_profile_buttons));
+}
+
+static int koneplus_set_profile_buttons(struct usb_device *usb_dev,
+		struct koneplus_profile_buttons const *buttons)
+{
+	return koneplus_send(usb_dev, KONEPLUS_USB_COMMAND_PROFILE_BUTTONS,
+			(void *)buttons, sizeof(struct koneplus_profile_buttons));
+}
+
+/* retval is 0-4 on success, < 0 on error */
+static int koneplus_get_startup_profile(struct usb_device *usb_dev)
+{
+	struct koneplus_startup_profile *buf;
+	int retval;
+
+	buf = kmalloc(sizeof(struct koneplus_startup_profile), GFP_KERNEL);
+
+	retval = koneplus_receive(usb_dev, KONEPLUS_USB_COMMAND_STARTUP_PROFILE,
+			buf, sizeof(struct koneplus_startup_profile));
+
+	if (retval)
+		goto out;
+
+	retval = buf->startup_profile;
+out:
+	kfree(buf);
+	return retval;
+}
+
+static int koneplus_set_startup_profile(struct usb_device *usb_dev,
+		int startup_profile)
+{
+	struct koneplus_startup_profile buf;
+
+	buf.command = KONEPLUS_COMMAND_STARTUP_PROFILE;
+	buf.size = sizeof(struct koneplus_startup_profile);
+	buf.startup_profile = startup_profile;
+
+	return koneplus_send(usb_dev, KONEPLUS_USB_COMMAND_STARTUP_PROFILE,
+			(char *)&buf, sizeof(struct koneplus_profile_buttons));
+}
+
+static ssize_t koneplus_sysfs_read(struct file *fp, struct kobject *kobj,
+		char *buf, loff_t off, size_t count,
+		size_t real_size, uint command)
+{
+	struct device *dev =
+			container_of(kobj, struct device, kobj)->parent->parent;
+	struct koneplus_device *koneplus = hid_get_drvdata(dev_get_drvdata(dev));
+	struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
+	int retval;
+
+	if (off != 0 || count != real_size)
+		return -EINVAL;
+
+	mutex_lock(&koneplus->koneplus_lock);
+	retval = koneplus_receive(usb_dev, command, buf, real_size);
+	mutex_unlock(&koneplus->koneplus_lock);
+
+	if (retval)
+		return retval;
+
+	return real_size;
+}
+
+static ssize_t koneplus_sysfs_write(struct file *fp, struct kobject *kobj,
+		void const *buf, loff_t off, size_t count,
+		size_t real_size, uint command)
+{
+	struct device *dev =
+			container_of(kobj, struct device, kobj)->parent->parent;
+	struct koneplus_device *koneplus = hid_get_drvdata(dev_get_drvdata(dev));
+	struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
+	int retval;
+
+	if (off != 0 || count != real_size)
+		return -EINVAL;
+
+	mutex_lock(&koneplus->koneplus_lock);
+	retval = koneplus_send(usb_dev, command, (void *)buf, real_size);
+	mutex_unlock(&koneplus->koneplus_lock);
+
+	if (retval)
+		return retval;
+
+	return real_size;
+}
+
+static ssize_t koneplus_sysfs_write_macro(struct file *fp,
+		struct kobject *kobj, struct bin_attribute *attr, char *buf,
+		loff_t off, size_t count)
+{
+	return koneplus_sysfs_write(fp, kobj, buf, off, count,
+			sizeof(struct koneplus_macro), KONEPLUS_USB_COMMAND_MACRO);
+}
+
+static ssize_t koneplus_sysfs_read_sensor(struct file *fp,
+		struct kobject *kobj, struct bin_attribute *attr, char *buf,
+		loff_t off, size_t count)
+{
+	return koneplus_sysfs_read(fp, kobj, buf, off, count,
+			sizeof(struct koneplus_sensor), KONEPLUS_USB_COMMAND_SENSOR);
+}
+
+static ssize_t koneplus_sysfs_write_sensor(struct file *fp,
+		struct kobject *kobj, struct bin_attribute *attr, char *buf,
+		loff_t off, size_t count)
+{
+	return koneplus_sysfs_write(fp, kobj, buf, off, count,
+			sizeof(struct koneplus_sensor), KONEPLUS_USB_COMMAND_SENSOR);
+}
+
+static ssize_t koneplus_sysfs_write_tcu(struct file *fp,
+		struct kobject *kobj, struct bin_attribute *attr, char *buf,
+		loff_t off, size_t count)
+{
+	return koneplus_sysfs_write(fp, kobj, buf, off, count,
+			sizeof(struct koneplus_tcu), KONEPLUS_USB_COMMAND_TCU);
+}
+
+static ssize_t koneplus_sysfs_read_tcu_image(struct file *fp,
+		struct kobject *kobj, struct bin_attribute *attr, char *buf,
+		loff_t off, size_t count)
+{
+	return koneplus_sysfs_read(fp, kobj, buf, off, count,
+			sizeof(struct koneplus_tcu_image), KONEPLUS_USB_COMMAND_TCU);
+}
+
+static ssize_t koneplus_sysfs_read_profilex_settings(struct file *fp,
+		struct kobject *kobj, struct bin_attribute *attr, char *buf,
+		loff_t off, size_t count)
+{
+	struct device *dev =
+			container_of(kobj, struct device, kobj)->parent->parent;
+	struct koneplus_device *koneplus = hid_get_drvdata(dev_get_drvdata(dev));
+
+	if (off >= sizeof(struct koneplus_profile_settings))
+		return 0;
+
+	if (off + count > sizeof(struct koneplus_profile_settings))
+		count = sizeof(struct koneplus_profile_settings) - off;
+
+	mutex_lock(&koneplus->koneplus_lock);
+	memcpy(buf, ((void const *)&koneplus->profile_settings[*(uint *)(attr->private)]) + off,
+			count);
+	mutex_unlock(&koneplus->koneplus_lock);
+
+	return count;
+}
+
+static ssize_t koneplus_sysfs_write_profile_settings(struct file *fp,
+		struct kobject *kobj, struct bin_attribute *attr, char *buf,
+		loff_t off, size_t count)
+{
+	struct device *dev =
+			container_of(kobj, struct device, kobj)->parent->parent;
+	struct koneplus_device *koneplus = hid_get_drvdata(dev_get_drvdata(dev));
+	struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
+	int retval = 0;
+	int difference;
+	int profile_number;
+	struct koneplus_profile_settings *profile_settings;
+
+	if (off != 0 || count != sizeof(struct koneplus_profile_settings))
+		return -EINVAL;
+
+	profile_number = ((struct koneplus_profile_settings const *)buf)->number;
+	profile_settings = &koneplus->profile_settings[profile_number];
+
+	mutex_lock(&koneplus->koneplus_lock);
+	difference = memcmp(buf, profile_settings,
+			sizeof(struct koneplus_profile_settings));
+	if (difference) {
+		retval = koneplus_set_profile_settings(usb_dev,
+				(struct koneplus_profile_settings const *)buf);
+		if (!retval)
+			memcpy(profile_settings, buf,
+					sizeof(struct koneplus_profile_settings));
+	}
+	mutex_unlock(&koneplus->koneplus_lock);
+
+	if (retval)
+		return retval;
+
+	return sizeof(struct koneplus_profile_settings);
+}
+
+static ssize_t koneplus_sysfs_read_profilex_buttons(struct file *fp,
+		struct kobject *kobj, struct bin_attribute *attr, char *buf,
+		loff_t off, size_t count)
+{
+	struct device *dev =
+			container_of(kobj, struct device, kobj)->parent->parent;
+	struct koneplus_device *koneplus = hid_get_drvdata(dev_get_drvdata(dev));
+
+	if (off >= sizeof(struct koneplus_profile_buttons))
+		return 0;
+
+	if (off + count > sizeof(struct koneplus_profile_buttons))
+		count = sizeof(struct koneplus_profile_buttons) - off;
+
+	mutex_lock(&koneplus->koneplus_lock);
+	memcpy(buf, ((void const *)&koneplus->profile_buttons[*(uint *)(attr->private)]) + off,
+			count);
+	mutex_unlock(&koneplus->koneplus_lock);
+
+	return count;
+}
+
+static ssize_t koneplus_sysfs_write_profile_buttons(struct file *fp,
+		struct kobject *kobj, struct bin_attribute *attr, char *buf,
+		loff_t off, size_t count)
+{
+	struct device *dev =
+			container_of(kobj, struct device, kobj)->parent->parent;
+	struct koneplus_device *koneplus = hid_get_drvdata(dev_get_drvdata(dev));
+	struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
+	int retval = 0;
+	int difference;
+	uint profile_number;
+	struct koneplus_profile_buttons *profile_buttons;
+
+	if (off != 0 || count != sizeof(struct koneplus_profile_buttons))
+		return -EINVAL;
+
+	profile_number = ((struct koneplus_profile_buttons const *)buf)->number;
+	profile_buttons = &koneplus->profile_buttons[profile_number];
+
+	mutex_lock(&koneplus->koneplus_lock);
+	difference = memcmp(buf, profile_buttons,
+			sizeof(struct koneplus_profile_buttons));
+	if (difference) {
+		retval = koneplus_set_profile_buttons(usb_dev,
+				(struct koneplus_profile_buttons const *)buf);
+		if (!retval)
+			memcpy(profile_buttons, buf,
+					sizeof(struct koneplus_profile_buttons));
+	}
+	mutex_unlock(&koneplus->koneplus_lock);
+
+	if (retval)
+		return retval;
+
+	return sizeof(struct koneplus_profile_buttons);
+}
+
+static ssize_t koneplus_sysfs_show_startup_profile(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct koneplus_device *koneplus =
+			hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
+	return snprintf(buf, PAGE_SIZE, "%d\n", koneplus->startup_profile);
+}
+
+static ssize_t koneplus_sysfs_set_startup_profile(struct device *dev,
+		struct device_attribute *attr, char const *buf, size_t size)
+{
+	struct koneplus_device *koneplus;
+	struct usb_device *usb_dev;
+	unsigned long profile;
+	int retval;
+
+	dev = dev->parent->parent;
+	koneplus = hid_get_drvdata(dev_get_drvdata(dev));
+	usb_dev = interface_to_usbdev(to_usb_interface(dev));
+
+	retval = strict_strtoul(buf, 10, &profile);
+	if (retval)
+		return retval;
+
+	mutex_lock(&koneplus->koneplus_lock);
+	retval = koneplus_set_startup_profile(usb_dev, profile);
+	mutex_unlock(&koneplus->koneplus_lock);
+	if (retval)
+		return retval;
+
+	return size;
+}
+
+static ssize_t koneplus_sysfs_show_actual_profile(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct koneplus_device *koneplus =
+			hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
+	return snprintf(buf, PAGE_SIZE, "%d\n", koneplus->actual_profile);
+}
+
+static ssize_t koneplus_sysfs_show_firmware_version(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct koneplus_device *koneplus =
+			hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
+	return snprintf(buf, PAGE_SIZE, "%d\n", koneplus->info.firmware_version);
+}
+
+static struct device_attribute koneplus_attributes[] = {
+	__ATTR(startup_profile, 0660,
+			koneplus_sysfs_show_startup_profile,
+			koneplus_sysfs_set_startup_profile),
+	__ATTR(actual_profile, 0440,
+			koneplus_sysfs_show_actual_profile, NULL),
+	__ATTR(firmware_version, 0440,
+			koneplus_sysfs_show_firmware_version, NULL),
+	__ATTR_NULL
+};
+
+static struct bin_attribute koneplus_bin_attributes[] = {
+	{
+		.attr = { .name = "sensor", .mode = 0220 },
+		.size = sizeof(struct koneplus_sensor),
+		.read = koneplus_sysfs_read_sensor,
+		.write = koneplus_sysfs_write_sensor
+	},
+	{
+		.attr = { .name = "tcu", .mode = 0220 },
+		.size = sizeof(struct koneplus_tcu),
+		.write = koneplus_sysfs_write_tcu
+	},
+	{
+		.attr = { .name = "tcu_image", .mode = 0440 },
+		.size = sizeof(struct koneplus_tcu_image),
+		.read = koneplus_sysfs_read_tcu_image
+	},
+	{
+		.attr = { .name = "profile_settings", .mode = 0220 },
+		.size = sizeof(struct koneplus_profile_settings),
+		.write = koneplus_sysfs_write_profile_settings
+	},
+	{
+		.attr = { .name = "profile1_settings", .mode = 0440 },
+		.size = sizeof(struct koneplus_profile_settings),
+		.read = koneplus_sysfs_read_profilex_settings,
+		.private = &profile_numbers[0]
+	},
+	{
+		.attr = { .name = "profile2_settings", .mode = 0440 },
+		.size = sizeof(struct koneplus_profile_settings),
+		.read = koneplus_sysfs_read_profilex_settings,
+		.private = &profile_numbers[1]
+	},
+	{
+		.attr = { .name = "profile3_settings", .mode = 0440 },
+		.size = sizeof(struct koneplus_profile_settings),
+		.read = koneplus_sysfs_read_profilex_settings,
+		.private = &profile_numbers[2]
+	},
+	{
+		.attr = { .name = "profile4_settings", .mode = 0440 },
+		.size = sizeof(struct koneplus_profile_settings),
+		.read = koneplus_sysfs_read_profilex_settings,
+		.private = &profile_numbers[3]
+	},
+	{
+		.attr = { .name = "profile5_settings", .mode = 0440 },
+		.size = sizeof(struct koneplus_profile_settings),
+		.read = koneplus_sysfs_read_profilex_settings,
+		.private = &profile_numbers[4]
+	},
+	{
+		.attr = { .name = "profile_buttons", .mode = 0220 },
+		.size = sizeof(struct koneplus_profile_buttons),
+		.write = koneplus_sysfs_write_profile_buttons
+	},
+	{
+		.attr = { .name = "profile1_buttons", .mode = 0440 },
+		.size = sizeof(struct koneplus_profile_buttons),
+		.read = koneplus_sysfs_read_profilex_buttons,
+		.private = &profile_numbers[0]
+	},
+	{
+		.attr = { .name = "profile2_buttons", .mode = 0440 },
+		.size = sizeof(struct koneplus_profile_buttons),
+		.read = koneplus_sysfs_read_profilex_buttons,
+		.private = &profile_numbers[1]
+	},
+	{
+		.attr = { .name = "profile3_buttons", .mode = 0440 },
+		.size = sizeof(struct koneplus_profile_buttons),
+		.read = koneplus_sysfs_read_profilex_buttons,
+		.private = &profile_numbers[2]
+	},
+	{
+		.attr = { .name = "profile4_buttons", .mode = 0440 },
+		.size = sizeof(struct koneplus_profile_buttons),
+		.read = koneplus_sysfs_read_profilex_buttons,
+		.private = &profile_numbers[3]
+	},
+	{
+		.attr = { .name = "profile5_buttons", .mode = 0440 },
+		.size = sizeof(struct koneplus_profile_buttons),
+		.read = koneplus_sysfs_read_profilex_buttons,
+		.private = &profile_numbers[4]
+	},
+	{
+		.attr = { .name = "macro", .mode = 0220 },
+		.size = sizeof(struct koneplus_macro),
+		.write = koneplus_sysfs_write_macro
+	},
+	__ATTR_NULL
+};
+
+static int koneplus_init_koneplus_device_struct(struct usb_device *usb_dev,
+		struct koneplus_device *koneplus)
+{
+	int retval, i;
+	static uint wait = 70; /* device will freeze with just 60 */
+
+	mutex_init(&koneplus->koneplus_lock);
+
+	koneplus->startup_profile = koneplus_get_startup_profile(usb_dev);
+
+	msleep(wait);
+	retval = koneplus_get_info(usb_dev, &koneplus->info);
+	if (retval)
+		return retval;
+
+	for (i = 0; i < 5; ++i) {
+		msleep(wait);
+		retval = koneplus_get_profile_settings(usb_dev,
+				&koneplus->profile_settings[i], i);
+		if (retval)
+			return retval;
+
+		msleep(wait);
+		retval = koneplus_get_profile_buttons(usb_dev,
+				&koneplus->profile_buttons[i], i);
+		if (retval)
+			return retval;
+	}
+
+	koneplus_profile_activated(koneplus, koneplus->startup_profile);
+
+	return 0;
+}
+
+static int koneplus_init_specials(struct hid_device *hdev)
+{
+	struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
+	struct usb_device *usb_dev = interface_to_usbdev(intf);
+	struct koneplus_device *koneplus;
+	int retval;
+
+	if (intf->cur_altsetting->desc.bInterfaceProtocol
+			== USB_INTERFACE_PROTOCOL_MOUSE) {
+
+		koneplus = kzalloc(sizeof(*koneplus), GFP_KERNEL);
+		if (!koneplus) {
+			dev_err(&hdev->dev, "can't alloc device descriptor\n");
+			return -ENOMEM;
+		}
+		hid_set_drvdata(hdev, koneplus);
+
+		retval = koneplus_init_koneplus_device_struct(usb_dev, koneplus);
+		if (retval) {
+			dev_err(&hdev->dev,
+					"couldn't init struct koneplus_device\n");
+			goto exit_free;
+		}
+
+		retval = roccat_connect(koneplus_class, hdev);
+		if (retval < 0) {
+			dev_err(&hdev->dev, "couldn't init char dev\n");
+		} else {
+			koneplus->chrdev_minor = retval;
+			koneplus->roccat_claimed = 1;
+		}
+	} else {
+		hid_set_drvdata(hdev, NULL);
+	}
+
+	return 0;
+exit_free:
+	kfree(koneplus);
+	return retval;
+}
+
+static void koneplus_remove_specials(struct hid_device *hdev)
+{
+	struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
+	struct koneplus_device *koneplus;
+
+	if (intf->cur_altsetting->desc.bInterfaceProtocol
+			== USB_INTERFACE_PROTOCOL_MOUSE) {
+		koneplus = hid_get_drvdata(hdev);
+		if (koneplus->roccat_claimed)
+			roccat_disconnect(koneplus->chrdev_minor);
+		kfree(koneplus);
+	}
+}
+
+static int koneplus_probe(struct hid_device *hdev,
+		const struct hid_device_id *id)
+{
+	int retval;
+
+	retval = hid_parse(hdev);
+	if (retval) {
+		dev_err(&hdev->dev, "parse failed\n");
+		goto exit;
+	}
+
+	retval = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
+	if (retval) {
+		dev_err(&hdev->dev, "hw start failed\n");
+		goto exit;
+	}
+
+	retval = koneplus_init_specials(hdev);
+	if (retval) {
+		dev_err(&hdev->dev, "couldn't install mouse\n");
+		goto exit_stop;
+	}
+
+	return 0;
+
+exit_stop:
+	hid_hw_stop(hdev);
+exit:
+	return retval;
+}
+
+static void koneplus_remove(struct hid_device *hdev)
+{
+	koneplus_remove_specials(hdev);
+	hid_hw_stop(hdev);
+}
+
+static void koneplus_keep_values_up_to_date(struct koneplus_device *koneplus,
+		u8 const *data)
+{
+	struct koneplus_mouse_report_button const *button_report;
+
+	switch (data[0]) {
+	case KONEPLUS_MOUSE_REPORT_NUMBER_BUTTON:
+		button_report = (struct koneplus_mouse_report_button const *)data;
+		switch (button_report->type) {
+		case KONEPLUS_MOUSE_REPORT_BUTTON_TYPE_PROFILE:
+			koneplus_profile_activated(koneplus, button_report->data1 - 1);
+			break;
+		}
+		break;
+	}
+}
+
+static void koneplus_report_to_chrdev(struct koneplus_device const *koneplus,
+		u8 const *data)
+{
+	struct koneplus_roccat_report roccat_report;
+	struct koneplus_mouse_report_button const *button_report;
+
+	if (data[0] != KONEPLUS_MOUSE_REPORT_NUMBER_BUTTON)
+		return;
+
+	button_report = (struct koneplus_mouse_report_button const *)data;
+
+	if ((button_report->type == KONEPLUS_MOUSE_REPORT_BUTTON_TYPE_QUICKLAUNCH ||
+			button_report->type == KONEPLUS_MOUSE_REPORT_BUTTON_TYPE_TIMER) &&
+			button_report->data2 != KONEPLUS_MOUSE_REPORT_BUTTON_ACTION_PRESS)
+		return;
+
+	roccat_report.type = button_report->type;
+	roccat_report.data1 = button_report->data1;
+	roccat_report.data2 = button_report->data2;
+	roccat_report.profile = koneplus->actual_profile + 1;
+	roccat_report_event(koneplus->chrdev_minor,
+			(uint8_t const *)&roccat_report,
+			sizeof(struct koneplus_roccat_report));
+}
+
+static int koneplus_raw_event(struct hid_device *hdev,
+		struct hid_report *report, u8 *data, int size)
+{
+	struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
+	struct koneplus_device *koneplus = hid_get_drvdata(hdev);
+
+	if (intf->cur_altsetting->desc.bInterfaceProtocol
+			!= USB_INTERFACE_PROTOCOL_MOUSE)
+		return 0;
+
+	koneplus_keep_values_up_to_date(koneplus, data);
+
+	if (koneplus->roccat_claimed)
+		koneplus_report_to_chrdev(koneplus, data);
+
+	return 0;
+}
+
+static const struct hid_device_id koneplus_devices[] = {
+	{ HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONEPLUS) },
+	{ }
+};
+
+MODULE_DEVICE_TABLE(hid, koneplus_devices);
+
+static struct hid_driver koneplus_driver = {
+		.name = "koneplus",
+		.id_table = koneplus_devices,
+		.probe = koneplus_probe,
+		.remove = koneplus_remove,
+		.raw_event = koneplus_raw_event
+};
+
+static int __init koneplus_init(void)
+{
+	int retval;
+
+	/* class name has to be same as driver name */
+	koneplus_class = class_create(THIS_MODULE, "koneplus");
+	if (IS_ERR(koneplus_class))
+		return PTR_ERR(koneplus_class);
+	koneplus_class->dev_attrs = koneplus_attributes;
+	koneplus_class->dev_bin_attrs = koneplus_bin_attributes;
+
+	retval = hid_register_driver(&koneplus_driver);
+	if (retval)
+		class_destroy(koneplus_class);
+	return retval;
+}
+
+static void __exit koneplus_exit(void)
+{
+	class_destroy(koneplus_class);
+	hid_unregister_driver(&koneplus_driver);
+}
+
+module_init(koneplus_init);
+module_exit(koneplus_exit);
+
+MODULE_AUTHOR("Stefan Achatz");
+MODULE_DESCRIPTION("USB Roccat Kone[+] driver");
+MODULE_LICENSE("GPL v2");
diff -druNp linux-libre-2.6.37-gnu1/drivers/hid/hid-roccat-koneplus.h linux-libre-2.6.38-gnu1/drivers/hid/hid-roccat-koneplus.h
--- linux-libre-2.6.37-gnu1/drivers/hid/hid-roccat-koneplus.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hid/hid-roccat-koneplus.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,224 @@
+#ifndef __HID_ROCCAT_KONEPLUS_H
+#define __HID_ROCCAT_KONEPLUS_H
+
+/*
+ * Copyright (c) 2010 Stefan Achatz <erazor_de@users.sourceforge.net>
+ */
+
+/*
+ * 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/types.h>
+
+/*
+ * case 1: writes request 80 and reads value 1
+ *
+ */
+struct koneplus_control {
+	uint8_t command; /* KONEPLUS_COMMAND_CONTROL */
+	/*
+	 * value is profile number in range 0-4 for requesting settings and buttons
+	 * 1 if status ok for requesting status
+	 */
+	uint8_t value;
+	uint8_t request;
+} __attribute__ ((__packed__));
+
+enum koneplus_control_requests {
+	KONEPLUS_CONTROL_REQUEST_STATUS = 0x00,
+	KONEPLUS_CONTROL_REQUEST_PROFILE_SETTINGS = 0x80,
+	KONEPLUS_CONTROL_REQUEST_PROFILE_BUTTONS = 0x90,
+};
+
+enum koneplus_control_values {
+	KONEPLUS_CONTROL_REQUEST_STATUS_OVERLOAD = 0,
+	KONEPLUS_CONTROL_REQUEST_STATUS_OK = 1,
+	KONEPLUS_CONTROL_REQUEST_STATUS_WAIT = 3,
+};
+
+struct koneplus_startup_profile {
+	uint8_t command; /* KONEPLUS_COMMAND_STARTUP_PROFILE */
+	uint8_t size; /* always 3 */
+	uint8_t startup_profile; /* Range 0-4! */
+} __attribute__ ((__packed__));
+
+struct koneplus_profile_settings {
+	uint8_t command; /* KONEPLUS_COMMAND_PROFILE_SETTINGS */
+	uint8_t size; /* always 43 */
+	uint8_t number; /* range 0-4 */
+	uint8_t advanced_sensitivity;
+	uint8_t sensitivity_x;
+	uint8_t sensitivity_y;
+	uint8_t cpi_levels_enabled;
+	uint8_t cpi_levels_x[5];
+	uint8_t cpi_startup_level; /* range 0-4 */
+	uint8_t cpi_levels_y[5]; /* range 1-60 means 100-6000 cpi */
+	uint8_t unknown1;
+	uint8_t polling_rate;
+	uint8_t lights_enabled;
+	uint8_t light_effect_mode;
+	uint8_t color_flow_effect;
+	uint8_t light_effect_type;
+	uint8_t light_effect_speed;
+	uint8_t lights[16];
+	uint16_t checksum;
+} __attribute__ ((__packed__));
+
+struct koneplus_profile_buttons {
+	uint8_t command; /* KONEPLUS_COMMAND_PROFILE_BUTTONS */
+	uint8_t size; /* always 77 */
+	uint8_t number; /* range 0-4 */
+	uint8_t data[72];
+	uint16_t checksum;
+} __attribute__ ((__packed__));
+
+struct koneplus_macro {
+	uint8_t command; /* KONEPLUS_COMMAND_MACRO */
+	uint16_t size; /* always 0x822 little endian */
+	uint8_t profile; /* range 0-4 */
+	uint8_t button; /* range 0-23 */
+	uint8_t data[2075];
+	uint16_t checksum;
+} __attribute__ ((__packed__));
+
+struct koneplus_info {
+	uint8_t command; /* KONEPLUS_COMMAND_INFO */
+	uint8_t size; /* always 6 */
+	uint8_t firmware_version;
+	uint8_t unknown[3];
+} __attribute__ ((__packed__));
+
+struct koneplus_e {
+	uint8_t command; /* KONEPLUS_COMMAND_E */
+	uint8_t size; /* always 3 */
+	uint8_t unknown; /* TODO 1; 0 before firmware update */
+} __attribute__ ((__packed__));
+
+struct koneplus_sensor {
+	uint8_t command;  /* KONEPLUS_COMMAND_SENSOR */
+	uint8_t size; /* always 6 */
+	uint8_t data[4];
+} __attribute__ ((__packed__));
+
+struct koneplus_firmware_write {
+	uint8_t command; /* KONEPLUS_COMMAND_FIRMWARE_WRITE */
+	uint8_t unknown[1025];
+} __attribute__ ((__packed__));
+
+struct koneplus_firmware_write_control {
+	uint8_t command; /* KONEPLUS_COMMAND_FIRMWARE_WRITE_CONTROL */
+	/*
+	 * value is 1 on success
+	 * 3 means "not finished yet"
+	 */
+	uint8_t value;
+	uint8_t unknown; /* always 0x75 */
+} __attribute__ ((__packed__));
+
+struct koneplus_tcu {
+	uint16_t usb_command; /* KONEPLUS_USB_COMMAND_TCU */
+	uint8_t data[2];
+} __attribute__ ((__packed__));
+
+struct koneplus_tcu_image {
+	uint16_t usb_command; /* KONEPLUS_USB_COMMAND_TCU */
+	uint8_t data[1024];
+	uint16_t checksum;
+} __attribute__ ((__packed__));
+
+enum koneplus_commands {
+	KONEPLUS_COMMAND_CONTROL = 0x4,
+	KONEPLUS_COMMAND_STARTUP_PROFILE = 0x5,
+	KONEPLUS_COMMAND_PROFILE_SETTINGS = 0x6,
+	KONEPLUS_COMMAND_PROFILE_BUTTONS = 0x7,
+	KONEPLUS_COMMAND_MACRO = 0x8,
+	KONEPLUS_COMMAND_INFO = 0x9,
+	KONEPLUS_COMMAND_E = 0xe,
+	KONEPLUS_COMMAND_SENSOR = 0xf,
+	KONEPLUS_COMMAND_FIRMWARE_WRITE = 0x1b,
+	KONEPLUS_COMMAND_FIRMWARE_WRITE_CONTROL = 0x1c,
+};
+
+enum koneplus_usb_commands {
+	KONEPLUS_USB_COMMAND_CONTROL = 0x304,
+	KONEPLUS_USB_COMMAND_STARTUP_PROFILE = 0x305,
+	KONEPLUS_USB_COMMAND_PROFILE_SETTINGS = 0x306,
+	KONEPLUS_USB_COMMAND_PROFILE_BUTTONS = 0x307,
+	KONEPLUS_USB_COMMAND_MACRO = 0x308,
+	KONEPLUS_USB_COMMAND_INFO = 0x309,
+	KONEPLUS_USB_COMMAND_TCU = 0x30c,
+	KONEPLUS_USB_COMMAND_E = 0x30e,
+	KONEPLUS_USB_COMMAND_SENSOR = 0x30f,
+	KONEPLUS_USB_COMMAND_FIRMWARE_WRITE = 0x31b,
+	KONEPLUS_USB_COMMAND_FIRMWARE_WRITE_CONTROL = 0x31c,
+};
+
+enum koneplus_mouse_report_numbers {
+	KONEPLUS_MOUSE_REPORT_NUMBER_HID = 1,
+	KONEPLUS_MOUSE_REPORT_NUMBER_AUDIO = 2,
+	KONEPLUS_MOUSE_REPORT_NUMBER_BUTTON = 3,
+};
+
+struct koneplus_mouse_report_button {
+	uint8_t report_number; /* always KONEPLUS_MOUSE_REPORT_NUMBER_BUTTON */
+	uint8_t zero1;
+	uint8_t type;
+	uint8_t data1;
+	uint8_t data2;
+	uint8_t zero2;
+	uint8_t unknown[2];
+} __attribute__ ((__packed__));
+
+enum koneplus_mouse_report_button_types {
+	/* data1 = new profile range 1-5 */
+	KONEPLUS_MOUSE_REPORT_BUTTON_TYPE_PROFILE = 0x20,
+
+	/* data1 = button number range 1-24; data2 = action */
+	KONEPLUS_MOUSE_REPORT_BUTTON_TYPE_QUICKLAUNCH = 0x60,
+
+	/* data1 = button number range 1-24; data2 = action */
+	KONEPLUS_MOUSE_REPORT_BUTTON_TYPE_TIMER = 0x80,
+
+	/* data1 = setting number range 1-5 */
+	KONEPLUS_MOUSE_REPORT_BUTTON_TYPE_CPI = 0xb0,
+
+	/* data1 and data2 = range 0x1-0xb */
+	KONEPLUS_MOUSE_REPORT_BUTTON_TYPE_SENSITIVITY = 0xc0,
+
+	/* data1 = 22 = next track...
+	 * data2 = action
+	 */
+	KONEPLUS_MOUSE_REPORT_BUTTON_TYPE_MULTIMEDIA = 0xf0,
+};
+
+enum koneplus_mouse_report_button_action {
+	KONEPLUS_MOUSE_REPORT_BUTTON_ACTION_PRESS = 0,
+	KONEPLUS_MOUSE_REPORT_BUTTON_ACTION_RELEASE = 1,
+};
+
+struct koneplus_roccat_report {
+	uint8_t type;
+	uint8_t data1;
+	uint8_t data2;
+	uint8_t profile;
+} __attribute__ ((__packed__));
+
+struct koneplus_device {
+	int actual_profile;
+
+	int roccat_claimed;
+	int chrdev_minor;
+
+	struct mutex koneplus_lock;
+
+	int startup_profile;
+	struct koneplus_info info;
+	struct koneplus_profile_settings profile_settings[5];
+	struct koneplus_profile_buttons profile_buttons[5];
+};
+
+#endif
diff -druNp linux-libre-2.6.37-gnu1/drivers/hid/hid-roccat-pyra.c linux-libre-2.6.38-gnu1/drivers/hid/hid-roccat-pyra.c
--- linux-libre-2.6.37-gnu1/drivers/hid/hid-roccat-pyra.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hid/hid-roccat-pyra.c	2011-03-14 21:20:32.000000000 -0400
@@ -27,6 +27,11 @@
 #include "hid-roccat.h"
 #include "hid-roccat-pyra.h"
 
+static uint profile_numbers[5] = {0, 1, 2, 3, 4};
+
+/* pyra_class is used for creating sysfs attributes via roccat char device */
+static struct class *pyra_class;
+
 static void profile_activated(struct pyra_device *pyra,
 		unsigned int new_profile)
 {
@@ -87,9 +92,8 @@ static int pyra_receive_control_status(s
 			control.value == 1)
 			return 0;
 	else {
-		dev_err(&usb_dev->dev, "receive control status: "
-				"unknown response 0x%x 0x%x\n",
-				control.request, control.value);
+		hid_err(usb_dev, "receive control status: unknown response 0x%x 0x%x\n",
+			control.request, control.value);
 		return -EINVAL;
 	}
 }
@@ -221,9 +225,10 @@ static int pyra_set_settings(struct usb_
 
 static ssize_t pyra_sysfs_read_profilex_settings(struct file *fp,
 		struct kobject *kobj, struct bin_attribute *attr, char *buf,
-		loff_t off, size_t count, int number)
+		loff_t off, size_t count)
 {
-	struct device *dev = container_of(kobj, struct device, kobj);
+	struct device *dev =
+			container_of(kobj, struct device, kobj)->parent->parent;
 	struct pyra_device *pyra = hid_get_drvdata(dev_get_drvdata(dev));
 
 	if (off >= sizeof(struct pyra_profile_settings))
@@ -233,58 +238,19 @@ static ssize_t pyra_sysfs_read_profilex_
 		count = sizeof(struct pyra_profile_settings) - off;
 
 	mutex_lock(&pyra->pyra_lock);
-	memcpy(buf, ((char const *)&pyra->profile_settings[number]) + off,
+	memcpy(buf, ((char const *)&pyra->profile_settings[*(uint *)(attr->private)]) + off,
 			count);
 	mutex_unlock(&pyra->pyra_lock);
 
 	return count;
 }
 
-static ssize_t pyra_sysfs_read_profile1_settings(struct file *fp,
-		struct kobject *kobj, struct bin_attribute *attr, char *buf,
-		loff_t off, size_t count)
-{
-	return pyra_sysfs_read_profilex_settings(fp, kobj,
-			attr, buf, off, count, 0);
-}
-
-static ssize_t pyra_sysfs_read_profile2_settings(struct file *fp,
-		struct kobject *kobj, struct bin_attribute *attr, char *buf,
-		loff_t off, size_t count)
-{
-	return pyra_sysfs_read_profilex_settings(fp, kobj,
-			attr, buf, off, count, 1);
-}
-
-static ssize_t pyra_sysfs_read_profile3_settings(struct file *fp,
-		struct kobject *kobj, struct bin_attribute *attr, char *buf,
-		loff_t off, size_t count)
-{
-	return pyra_sysfs_read_profilex_settings(fp, kobj,
-			attr, buf, off, count, 2);
-}
-
-static ssize_t pyra_sysfs_read_profile4_settings(struct file *fp,
-		struct kobject *kobj, struct bin_attribute *attr, char *buf,
-		loff_t off, size_t count)
-{
-	return pyra_sysfs_read_profilex_settings(fp, kobj,
-			attr, buf, off, count, 3);
-}
-
-static ssize_t pyra_sysfs_read_profile5_settings(struct file *fp,
-		struct kobject *kobj, struct bin_attribute *attr, char *buf,
-		loff_t off, size_t count)
-{
-	return pyra_sysfs_read_profilex_settings(fp, kobj,
-			attr, buf, off, count, 4);
-}
-
 static ssize_t pyra_sysfs_read_profilex_buttons(struct file *fp,
 		struct kobject *kobj, struct bin_attribute *attr, char *buf,
-		loff_t off, size_t count, int number)
+		loff_t off, size_t count)
 {
-	struct device *dev = container_of(kobj, struct device, kobj);
+	struct device *dev =
+			container_of(kobj, struct device, kobj)->parent->parent;
 	struct pyra_device *pyra = hid_get_drvdata(dev_get_drvdata(dev));
 
 	if (off >= sizeof(struct pyra_profile_buttons))
@@ -294,58 +260,19 @@ static ssize_t pyra_sysfs_read_profilex_
 		count = sizeof(struct pyra_profile_buttons) - off;
 
 	mutex_lock(&pyra->pyra_lock);
-	memcpy(buf, ((char const *)&pyra->profile_buttons[number]) + off,
+	memcpy(buf, ((char const *)&pyra->profile_buttons[*(uint *)(attr->private)]) + off,
 			count);
 	mutex_unlock(&pyra->pyra_lock);
 
 	return count;
 }
 
-static ssize_t pyra_sysfs_read_profile1_buttons(struct file *fp,
-		struct kobject *kobj, struct bin_attribute *attr, char *buf,
-		loff_t off, size_t count)
-{
-	return pyra_sysfs_read_profilex_buttons(fp, kobj,
-			attr, buf, off, count, 0);
-}
-
-static ssize_t pyra_sysfs_read_profile2_buttons(struct file *fp,
-		struct kobject *kobj, struct bin_attribute *attr, char *buf,
-		loff_t off, size_t count)
-{
-	return pyra_sysfs_read_profilex_buttons(fp, kobj,
-			attr, buf, off, count, 1);
-}
-
-static ssize_t pyra_sysfs_read_profile3_buttons(struct file *fp,
-		struct kobject *kobj, struct bin_attribute *attr, char *buf,
-		loff_t off, size_t count)
-{
-	return pyra_sysfs_read_profilex_buttons(fp, kobj,
-			attr, buf, off, count, 2);
-}
-
-static ssize_t pyra_sysfs_read_profile4_buttons(struct file *fp,
-		struct kobject *kobj, struct bin_attribute *attr, char *buf,
-		loff_t off, size_t count)
-{
-	return pyra_sysfs_read_profilex_buttons(fp, kobj,
-			attr, buf, off, count, 3);
-}
-
-static ssize_t pyra_sysfs_read_profile5_buttons(struct file *fp,
-		struct kobject *kobj, struct bin_attribute *attr, char *buf,
-		loff_t off, size_t count)
-{
-	return pyra_sysfs_read_profilex_buttons(fp, kobj,
-			attr, buf, off, count, 4);
-}
-
 static ssize_t pyra_sysfs_write_profile_settings(struct file *fp,
 		struct kobject *kobj, struct bin_attribute *attr, char *buf,
 		loff_t off, size_t count)
 {
-	struct device *dev = container_of(kobj, struct device, kobj);
+	struct device *dev =
+			container_of(kobj, struct device, kobj)->parent->parent;
 	struct pyra_device *pyra = hid_get_drvdata(dev_get_drvdata(dev));
 	struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
 	int retval = 0;
@@ -381,7 +308,8 @@ static ssize_t pyra_sysfs_write_profile_
 		struct kobject *kobj, struct bin_attribute *attr, char *buf,
 		loff_t off, size_t count)
 {
-	struct device *dev = container_of(kobj, struct device, kobj);
+	struct device *dev =
+			container_of(kobj, struct device, kobj)->parent->parent;
 	struct pyra_device *pyra = hid_get_drvdata(dev_get_drvdata(dev));
 	struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
 	int retval = 0;
@@ -417,7 +345,8 @@ static ssize_t pyra_sysfs_read_settings(
 		struct kobject *kobj, struct bin_attribute *attr, char *buf,
 		loff_t off, size_t count)
 {
-	struct device *dev = container_of(kobj, struct device, kobj);
+	struct device *dev =
+			container_of(kobj, struct device, kobj)->parent->parent;
 	struct pyra_device *pyra = hid_get_drvdata(dev_get_drvdata(dev));
 
 	if (off >= sizeof(struct pyra_settings))
@@ -437,7 +366,8 @@ static ssize_t pyra_sysfs_write_settings
 		struct kobject *kobj, struct bin_attribute *attr, char *buf,
 		loff_t off, size_t count)
 {
-	struct device *dev = container_of(kobj, struct device, kobj);
+	struct device *dev =
+			container_of(kobj, struct device, kobj)->parent->parent;
 	struct pyra_device *pyra = hid_get_drvdata(dev_get_drvdata(dev));
 	struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
 	int retval = 0;
@@ -469,255 +399,125 @@ static ssize_t pyra_sysfs_write_settings
 static ssize_t pyra_sysfs_show_actual_cpi(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
-	struct pyra_device *pyra = hid_get_drvdata(dev_get_drvdata(dev));
+	struct pyra_device *pyra =
+			hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
 	return snprintf(buf, PAGE_SIZE, "%d\n", pyra->actual_cpi);
 }
 
 static ssize_t pyra_sysfs_show_actual_profile(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
-	struct pyra_device *pyra = hid_get_drvdata(dev_get_drvdata(dev));
+	struct pyra_device *pyra =
+			hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
 	return snprintf(buf, PAGE_SIZE, "%d\n", pyra->actual_profile);
 }
 
 static ssize_t pyra_sysfs_show_firmware_version(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
-	struct pyra_device *pyra = hid_get_drvdata(dev_get_drvdata(dev));
+	struct pyra_device *pyra =
+			hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
 	return snprintf(buf, PAGE_SIZE, "%d\n", pyra->firmware_version);
 }
 
 static ssize_t pyra_sysfs_show_startup_profile(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
-	struct pyra_device *pyra = hid_get_drvdata(dev_get_drvdata(dev));
+	struct pyra_device *pyra =
+			hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
 	return snprintf(buf, PAGE_SIZE, "%d\n", pyra->settings.startup_profile);
 }
 
-static DEVICE_ATTR(actual_cpi, 0440, pyra_sysfs_show_actual_cpi, NULL);
-
-static DEVICE_ATTR(actual_profile, 0440, pyra_sysfs_show_actual_profile, NULL);
-
-static DEVICE_ATTR(firmware_version, 0440,
-		pyra_sysfs_show_firmware_version, NULL);
-
-static DEVICE_ATTR(startup_profile, 0440,
-		pyra_sysfs_show_startup_profile, NULL);
-
-static struct attribute *pyra_attributes[] = {
-		&dev_attr_actual_cpi.attr,
-		&dev_attr_actual_profile.attr,
-		&dev_attr_firmware_version.attr,
-		&dev_attr_startup_profile.attr,
-		NULL
-};
-
-static struct attribute_group pyra_attribute_group = {
-		.attrs = pyra_attributes
+static struct device_attribute pyra_attributes[] = {
+	__ATTR(actual_cpi, 0440, pyra_sysfs_show_actual_cpi, NULL),
+	__ATTR(actual_profile, 0440, pyra_sysfs_show_actual_profile, NULL),
+	__ATTR(firmware_version, 0440,
+			pyra_sysfs_show_firmware_version, NULL),
+	__ATTR(startup_profile, 0440,
+			pyra_sysfs_show_startup_profile, NULL),
+	__ATTR_NULL
 };
 
-static struct bin_attribute pyra_profile_settings_attr = {
+static struct bin_attribute pyra_bin_attributes[] = {
+	{
 		.attr = { .name = "profile_settings", .mode = 0220 },
 		.size = sizeof(struct pyra_profile_settings),
 		.write = pyra_sysfs_write_profile_settings
-};
-
-static struct bin_attribute pyra_profile1_settings_attr = {
+	},
+	{
 		.attr = { .name = "profile1_settings", .mode = 0440 },
 		.size = sizeof(struct pyra_profile_settings),
-		.read = pyra_sysfs_read_profile1_settings
-};
-
-static struct bin_attribute pyra_profile2_settings_attr = {
+		.read = pyra_sysfs_read_profilex_settings,
+		.private = &profile_numbers[0]
+	},
+	{
 		.attr = { .name = "profile2_settings", .mode = 0440 },
 		.size = sizeof(struct pyra_profile_settings),
-		.read = pyra_sysfs_read_profile2_settings
-};
-
-static struct bin_attribute pyra_profile3_settings_attr = {
+		.read = pyra_sysfs_read_profilex_settings,
+		.private = &profile_numbers[1]
+	},
+	{
 		.attr = { .name = "profile3_settings", .mode = 0440 },
 		.size = sizeof(struct pyra_profile_settings),
-		.read = pyra_sysfs_read_profile3_settings
-};
-
-static struct bin_attribute pyra_profile4_settings_attr = {
+		.read = pyra_sysfs_read_profilex_settings,
+		.private = &profile_numbers[2]
+	},
+	{
 		.attr = { .name = "profile4_settings", .mode = 0440 },
 		.size = sizeof(struct pyra_profile_settings),
-		.read = pyra_sysfs_read_profile4_settings
-};
-
-static struct bin_attribute pyra_profile5_settings_attr = {
+		.read = pyra_sysfs_read_profilex_settings,
+		.private = &profile_numbers[3]
+	},
+	{
 		.attr = { .name = "profile5_settings", .mode = 0440 },
 		.size = sizeof(struct pyra_profile_settings),
-		.read = pyra_sysfs_read_profile5_settings
-};
-
-static struct bin_attribute pyra_profile_buttons_attr = {
+		.read = pyra_sysfs_read_profilex_settings,
+		.private = &profile_numbers[4]
+	},
+	{
 		.attr = { .name = "profile_buttons", .mode = 0220 },
 		.size = sizeof(struct pyra_profile_buttons),
 		.write = pyra_sysfs_write_profile_buttons
-};
-
-static struct bin_attribute pyra_profile1_buttons_attr = {
+	},
+	{
 		.attr = { .name = "profile1_buttons", .mode = 0440 },
 		.size = sizeof(struct pyra_profile_buttons),
-		.read = pyra_sysfs_read_profile1_buttons
-};
-
-static struct bin_attribute pyra_profile2_buttons_attr = {
+		.read = pyra_sysfs_read_profilex_buttons,
+		.private = &profile_numbers[0]
+	},
+	{
 		.attr = { .name = "profile2_buttons", .mode = 0440 },
 		.size = sizeof(struct pyra_profile_buttons),
-		.read = pyra_sysfs_read_profile2_buttons
-};
-
-static struct bin_attribute pyra_profile3_buttons_attr = {
+		.read = pyra_sysfs_read_profilex_buttons,
+		.private = &profile_numbers[1]
+	},
+	{
 		.attr = { .name = "profile3_buttons", .mode = 0440 },
 		.size = sizeof(struct pyra_profile_buttons),
-		.read = pyra_sysfs_read_profile3_buttons
-};
-
-static struct bin_attribute pyra_profile4_buttons_attr = {
+		.read = pyra_sysfs_read_profilex_buttons,
+		.private = &profile_numbers[2]
+	},
+	{
 		.attr = { .name = "profile4_buttons", .mode = 0440 },
 		.size = sizeof(struct pyra_profile_buttons),
-		.read = pyra_sysfs_read_profile4_buttons
-};
-
-static struct bin_attribute pyra_profile5_buttons_attr = {
+		.read = pyra_sysfs_read_profilex_buttons,
+		.private = &profile_numbers[3]
+	},
+	{
 		.attr = { .name = "profile5_buttons", .mode = 0440 },
 		.size = sizeof(struct pyra_profile_buttons),
-		.read = pyra_sysfs_read_profile5_buttons
-};
-
-static struct bin_attribute pyra_settings_attr = {
+		.read = pyra_sysfs_read_profilex_buttons,
+		.private = &profile_numbers[4]
+	},
+	{
 		.attr = { .name = "settings", .mode = 0660 },
 		.size = sizeof(struct pyra_settings),
 		.read = pyra_sysfs_read_settings,
 		.write = pyra_sysfs_write_settings
+	},
+	__ATTR_NULL
 };
 
-static int pyra_create_sysfs_attributes(struct usb_interface *intf)
-{
-	int retval;
-
-	retval = sysfs_create_group(&intf->dev.kobj, &pyra_attribute_group);
-	if (retval)
-		goto exit_1;
-
-	retval = sysfs_create_bin_file(&intf->dev.kobj,
-			&pyra_profile_settings_attr);
-	if (retval)
-		goto exit_2;
-
-	retval = sysfs_create_bin_file(&intf->dev.kobj,
-			&pyra_profile1_settings_attr);
-	if (retval)
-		goto exit_3;
-
-	retval = sysfs_create_bin_file(&intf->dev.kobj,
-			&pyra_profile2_settings_attr);
-	if (retval)
-		goto exit_4;
-
-	retval = sysfs_create_bin_file(&intf->dev.kobj,
-			&pyra_profile3_settings_attr);
-	if (retval)
-		goto exit_5;
-
-	retval = sysfs_create_bin_file(&intf->dev.kobj,
-			&pyra_profile4_settings_attr);
-	if (retval)
-		goto exit_6;
-
-	retval = sysfs_create_bin_file(&intf->dev.kobj,
-			&pyra_profile5_settings_attr);
-	if (retval)
-		goto exit_7;
-
-	retval = sysfs_create_bin_file(&intf->dev.kobj,
-			&pyra_profile_buttons_attr);
-	if (retval)
-		goto exit_8;
-
-	retval = sysfs_create_bin_file(&intf->dev.kobj,
-			&pyra_profile1_buttons_attr);
-	if (retval)
-		goto exit_9;
-
-	retval = sysfs_create_bin_file(&intf->dev.kobj,
-			&pyra_profile2_buttons_attr);
-	if (retval)
-		goto exit_10;
-
-	retval = sysfs_create_bin_file(&intf->dev.kobj,
-			&pyra_profile3_buttons_attr);
-	if (retval)
-		goto exit_11;
-
-	retval = sysfs_create_bin_file(&intf->dev.kobj,
-			&pyra_profile4_buttons_attr);
-	if (retval)
-		goto exit_12;
-
-	retval = sysfs_create_bin_file(&intf->dev.kobj,
-			&pyra_profile5_buttons_attr);
-	if (retval)
-		goto exit_13;
-
-	retval = sysfs_create_bin_file(&intf->dev.kobj,
-			&pyra_settings_attr);
-	if (retval)
-		goto exit_14;
-
-	return 0;
-
-exit_14:
-	sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile5_buttons_attr);
-exit_13:
-	sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile4_buttons_attr);
-exit_12:
-	sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile3_buttons_attr);
-exit_11:
-	sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile2_buttons_attr);
-exit_10:
-	sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile1_buttons_attr);
-exit_9:
-	sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile_buttons_attr);
-exit_8:
-	sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile5_settings_attr);
-exit_7:
-	sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile4_settings_attr);
-exit_6:
-	sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile3_settings_attr);
-exit_5:
-	sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile2_settings_attr);
-exit_4:
-	sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile1_settings_attr);
-exit_3:
-	sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile_settings_attr);
-exit_2:
-	sysfs_remove_group(&intf->dev.kobj, &pyra_attribute_group);
-exit_1:
-	return retval;
-}
-
-static void pyra_remove_sysfs_attributes(struct usb_interface *intf)
-{
-	sysfs_remove_bin_file(&intf->dev.kobj, &pyra_settings_attr);
-	sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile5_buttons_attr);
-	sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile4_buttons_attr);
-	sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile3_buttons_attr);
-	sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile2_buttons_attr);
-	sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile1_buttons_attr);
-	sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile_buttons_attr);
-	sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile5_settings_attr);
-	sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile4_settings_attr);
-	sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile3_settings_attr);
-	sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile2_settings_attr);
-	sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile1_settings_attr);
-	sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile_settings_attr);
-	sysfs_remove_group(&intf->dev.kobj, &pyra_attribute_group);
-}
-
 static int pyra_init_pyra_device_struct(struct usb_device *usb_dev,
 		struct pyra_device *pyra)
 {
@@ -770,31 +570,24 @@ static int pyra_init_specials(struct hid
 
 		pyra = kzalloc(sizeof(*pyra), GFP_KERNEL);
 		if (!pyra) {
-			dev_err(&hdev->dev, "can't alloc device descriptor\n");
+			hid_err(hdev, "can't alloc device descriptor\n");
 			return -ENOMEM;
 		}
 		hid_set_drvdata(hdev, pyra);
 
 		retval = pyra_init_pyra_device_struct(usb_dev, pyra);
 		if (retval) {
-			dev_err(&hdev->dev,
-					"couldn't init struct pyra_device\n");
+			hid_err(hdev, "couldn't init struct pyra_device\n");
 			goto exit_free;
 		}
 
-		retval = roccat_connect(hdev);
+		retval = roccat_connect(pyra_class, hdev);
 		if (retval < 0) {
-			dev_err(&hdev->dev, "couldn't init char dev\n");
+			hid_err(hdev, "couldn't init char dev\n");
 		} else {
 			pyra->chrdev_minor = retval;
 			pyra->roccat_claimed = 1;
 		}
-
-		retval = pyra_create_sysfs_attributes(intf);
-		if (retval) {
-			dev_err(&hdev->dev, "cannot create sysfs files\n");
-			goto exit_free;
-		}
 	} else {
 		hid_set_drvdata(hdev, NULL);
 	}
@@ -812,7 +605,6 @@ static void pyra_remove_specials(struct
 
 	if (intf->cur_altsetting->desc.bInterfaceProtocol
 			== USB_INTERFACE_PROTOCOL_MOUSE) {
-		pyra_remove_sysfs_attributes(intf);
 		pyra = hid_get_drvdata(hdev);
 		if (pyra->roccat_claimed)
 			roccat_disconnect(pyra->chrdev_minor);
@@ -826,19 +618,19 @@ static int pyra_probe(struct hid_device
 
 	retval = hid_parse(hdev);
 	if (retval) {
-		dev_err(&hdev->dev, "parse failed\n");
+		hid_err(hdev, "parse failed\n");
 		goto exit;
 	}
 
 	retval = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
 	if (retval) {
-		dev_err(&hdev->dev, "hw start failed\n");
+		hid_err(hdev, "hw start failed\n");
 		goto exit;
 	}
 
 	retval = pyra_init_specials(hdev);
 	if (retval) {
-		dev_err(&hdev->dev, "couldn't install mouse\n");
+		hid_err(hdev, "couldn't install mouse\n");
 		goto exit_stop;
 	}
 	return 0;
@@ -952,11 +744,24 @@ static struct hid_driver pyra_driver = {
 
 static int __init pyra_init(void)
 {
-	return hid_register_driver(&pyra_driver);
+	int retval;
+
+	/* class name has to be same as driver name */
+	pyra_class = class_create(THIS_MODULE, "pyra");
+	if (IS_ERR(pyra_class))
+		return PTR_ERR(pyra_class);
+	pyra_class->dev_attrs = pyra_attributes;
+	pyra_class->dev_bin_attrs = pyra_bin_attributes;
+
+	retval = hid_register_driver(&pyra_driver);
+	if (retval)
+		class_destroy(pyra_class);
+	return retval;
 }
 
 static void __exit pyra_exit(void)
 {
+	class_destroy(pyra_class);
 	hid_unregister_driver(&pyra_driver);
 }
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/hid/hid-roccat-pyra.h linux-libre-2.6.38-gnu1/drivers/hid/hid-roccat-pyra.h
--- linux-libre-2.6.37-gnu1/drivers/hid/hid-roccat-pyra.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hid/hid-roccat-pyra.h	2011-03-14 21:20:32.000000000 -0400
@@ -14,14 +14,11 @@
 
 #include <linux/types.h>
 
-#pragma pack(push)
-#pragma pack(1)
-
 struct pyra_b {
 	uint8_t command; /* PYRA_COMMAND_B */
 	uint8_t size; /* always 3 */
 	uint8_t unknown; /* 1 */
-};
+} __attribute__ ((__packed__));
 
 struct pyra_control {
 	uint8_t command; /* PYRA_COMMAND_CONTROL */
@@ -31,7 +28,7 @@ struct pyra_control {
 	 */
 	uint8_t value; /* Range 0-4 */
 	uint8_t request;
-};
+} __attribute__ ((__packed__));
 
 enum pyra_control_requests {
 	PYRA_CONTROL_REQUEST_STATUS = 0x00,
@@ -43,7 +40,7 @@ struct pyra_settings {
 	uint8_t command; /* PYRA_COMMAND_SETTINGS */
 	uint8_t size; /* always 3 */
 	uint8_t startup_profile; /* Range 0-4! */
-};
+} __attribute__ ((__packed__));
 
 struct pyra_profile_settings {
 	uint8_t command; /* PYRA_COMMAND_PROFILE_SETTINGS */
@@ -58,7 +55,7 @@ struct pyra_profile_settings {
 	uint8_t light_effect;
 	uint8_t handedness;
 	uint16_t checksum; /* byte sum */
-};
+} __attribute__ ((__packed__));
 
 struct pyra_profile_buttons {
 	uint8_t command; /* PYRA_COMMAND_PROFILE_BUTTONS */
@@ -66,7 +63,7 @@ struct pyra_profile_buttons {
 	uint8_t number; /* Range 0-4 */
 	uint8_t buttons[14];
 	uint16_t checksum; /* byte sum */
-};
+} __attribute__ ((__packed__));
 
 struct pyra_info {
 	uint8_t command; /* PYRA_COMMAND_INFO */
@@ -75,7 +72,7 @@ struct pyra_info {
 	uint8_t unknown1; /* always 0 */
 	uint8_t unknown2; /* always 1 */
 	uint8_t unknown3; /* always 0 */
-};
+} __attribute__ ((__packed__));
 
 enum pyra_commands {
 	PYRA_COMMAND_CONTROL = 0x4,
@@ -107,13 +104,13 @@ struct pyra_mouse_event_button {
 	uint8_t type;
 	uint8_t data1;
 	uint8_t data2;
-};
+} __attribute__ ((__packed__));
 
 struct pyra_mouse_event_audio {
 	uint8_t report_number; /* always 2 */
 	uint8_t type;
 	uint8_t unused; /* always 0 */
-};
+} __attribute__ ((__packed__));
 
 /* hid audio controls */
 enum pyra_mouse_event_audio_types {
@@ -167,9 +164,7 @@ struct pyra_roccat_report {
 	uint8_t type;
 	uint8_t value;
 	uint8_t key;
-};
-
-#pragma pack(pop)
+} __attribute__ ((__packed__));
 
 struct pyra_device {
 	int actual_profile;
diff -druNp linux-libre-2.6.37-gnu1/drivers/hid/hid-samsung.c linux-libre-2.6.38-gnu1/drivers/hid/hid-samsung.c
--- linux-libre-2.6.37-gnu1/drivers/hid/hid-samsung.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hid/hid-samsung.c	2011-03-14 21:20:32.000000000 -0400
@@ -57,8 +57,8 @@
 static inline void samsung_irda_dev_trace(struct hid_device *hdev,
 		unsigned int rsize)
 {
-	dev_info(&hdev->dev, "fixing up Samsung IrDA %d byte report "
-			"descriptor\n", rsize);
+	hid_info(hdev, "fixing up Samsung IrDA %d byte report descriptor\n",
+		 rsize);
 }
 
 static __u8 *samsung_irda_report_fixup(struct hid_device *hdev, __u8 *rdesc,
@@ -160,7 +160,7 @@ static int samsung_probe(struct hid_devi
 
 	ret = hid_parse(hdev);
 	if (ret) {
-		dev_err(&hdev->dev, "parse failed\n");
+		hid_err(hdev, "parse failed\n");
 		goto err_free;
 	}
 
@@ -174,7 +174,7 @@ static int samsung_probe(struct hid_devi
 
 	ret = hid_hw_start(hdev, cmask);
 	if (ret) {
-		dev_err(&hdev->dev, "hw start failed\n");
+		hid_err(hdev, "hw start failed\n");
 		goto err_free;
 	}
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/hid/hid-sjoy.c linux-libre-2.6.38-gnu1/drivers/hid/hid-sjoy.c
--- linux-libre-2.6.37-gnu1/drivers/hid/hid-sjoy.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hid/hid-sjoy.c	2011-03-14 21:20:32.000000000 -0400
@@ -74,26 +74,25 @@ static int sjoyff_init(struct hid_device
 	int error;
 
 	if (list_empty(report_list)) {
-		dev_err(&hid->dev, "no output reports found\n");
+		hid_err(hid, "no output reports found\n");
 		return -ENODEV;
 	}
 
 	report_ptr = report_ptr->next;
 
 	if (report_ptr == report_list) {
-		dev_err(&hid->dev, "required output report is "
-				"missing\n");
+		hid_err(hid, "required output report is missing\n");
 		return -ENODEV;
 	}
 
 	report = list_entry(report_ptr, struct hid_report, list);
 	if (report->maxfield < 1) {
-		dev_err(&hid->dev, "no fields in the report\n");
+		hid_err(hid, "no fields in the report\n");
 		return -ENODEV;
 	}
 
 	if (report->field[0]->report_count < 3) {
-		dev_err(&hid->dev, "not enough values in the field\n");
+		hid_err(hid, "not enough values in the field\n");
 		return -ENODEV;
 	}
 
@@ -117,8 +116,7 @@ static int sjoyff_init(struct hid_device
 	sjoyff->report->field[0]->value[2] = 0x00;
 	usbhid_submit_report(hid, sjoyff->report, USB_DIR_OUT);
 
-	dev_info(&hid->dev,
-		"Force feedback for SmartJoy PLUS PS2/USB adapter\n");
+	hid_info(hid, "Force feedback for SmartJoy PLUS PS2/USB adapter\n");
 
 	return 0;
 }
@@ -135,13 +133,13 @@ static int sjoy_probe(struct hid_device
 
 	ret = hid_parse(hdev);
 	if (ret) {
-		dev_err(&hdev->dev, "parse failed\n");
+		hid_err(hdev, "parse failed\n");
 		goto err;
 	}
 
 	ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF);
 	if (ret) {
-		dev_err(&hdev->dev, "hw start failed\n");
+		hid_err(hdev, "hw start failed\n");
 		goto err;
 	}
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/hid/hid-sony.c linux-libre-2.6.38-gnu1/drivers/hid/hid-sony.c
--- linux-libre-2.6.37-gnu1/drivers/hid/hid-sony.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hid/hid-sony.c	2011-03-14 21:20:32.000000000 -0400
@@ -40,8 +40,7 @@ static __u8 *sony_report_fixup(struct hi
 
 	if ((sc->quirks & VAIO_RDESC_CONSTANT) &&
 			*rsize >= 56 && rdesc[54] == 0x81 && rdesc[55] == 0x07) {
-		dev_info(&hdev->dev, "Fixing up Sony Vaio VGX report "
-				"descriptor\n");
+		hid_info(hdev, "Fixing up Sony Vaio VGX report descriptor\n");
 		rdesc[55] = 0x06;
 	}
 	return rdesc;
@@ -89,7 +88,7 @@ static int sixaxis_set_operational_usb(s
 				 (3 << 8) | 0xf2, ifnum, buf, 17,
 				 USB_CTRL_GET_TIMEOUT);
 	if (ret < 0)
-		dev_err(&hdev->dev, "can't set operational mode\n");
+		hid_err(hdev, "can't set operational mode\n");
 
 	kfree(buf);
 
@@ -110,7 +109,7 @@ static int sony_probe(struct hid_device
 
 	sc = kzalloc(sizeof(*sc), GFP_KERNEL);
 	if (sc == NULL) {
-		dev_err(&hdev->dev, "can't alloc sony descriptor\n");
+		hid_err(hdev, "can't alloc sony descriptor\n");
 		return -ENOMEM;
 	}
 
@@ -119,14 +118,14 @@ static int sony_probe(struct hid_device
 
 	ret = hid_parse(hdev);
 	if (ret) {
-		dev_err(&hdev->dev, "parse failed\n");
+		hid_err(hdev, "parse failed\n");
 		goto err_free;
 	}
 
 	ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT |
 			HID_CONNECT_HIDDEV_FORCE);
 	if (ret) {
-		dev_err(&hdev->dev, "hw start failed\n");
+		hid_err(hdev, "hw start failed\n");
 		goto err_free;
 	}
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/hid/hid-stantum.c linux-libre-2.6.38-gnu1/drivers/hid/hid-stantum.c
--- linux-libre-2.6.37-gnu1/drivers/hid/hid-stantum.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hid/hid-stantum.c	2011-03-14 21:20:32.000000000 -0400
@@ -222,7 +222,7 @@ static int stantum_probe(struct hid_devi
 
 	sd = kmalloc(sizeof(struct stantum_data), GFP_KERNEL);
 	if (!sd) {
-		dev_err(&hdev->dev, "cannot allocate Stantum data\n");
+		hid_err(hdev, "cannot allocate Stantum data\n");
 		return -ENOMEM;
 	}
 	sd->valid = false;
diff -druNp linux-libre-2.6.37-gnu1/drivers/hid/hid-sunplus.c linux-libre-2.6.38-gnu1/drivers/hid/hid-sunplus.c
--- linux-libre-2.6.37-gnu1/drivers/hid/hid-sunplus.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hid/hid-sunplus.c	2011-03-14 21:20:32.000000000 -0400
@@ -27,8 +27,7 @@ static __u8 *sp_report_fixup(struct hid_
 {
 	if (*rsize >= 107 && rdesc[104] == 0x26 && rdesc[105] == 0x80 &&
 			rdesc[106] == 0x03) {
-		dev_info(&hdev->dev, "fixing up Sunplus Wireless Desktop "
-				"report descriptor\n");
+		hid_info(hdev, "fixing up Sunplus Wireless Desktop report descriptor\n");
 		rdesc[105] = rdesc[110] = 0x03;
 		rdesc[106] = rdesc[111] = 0x21;
 	}
diff -druNp linux-libre-2.6.37-gnu1/drivers/hid/hid-tmff.c linux-libre-2.6.38-gnu1/drivers/hid/hid-tmff.c
--- linux-libre-2.6.37-gnu1/drivers/hid/hid-tmff.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hid/hid-tmff.c	2011-03-14 21:20:32.000000000 -0400
@@ -151,28 +151,23 @@ static int tmff_init(struct hid_device *
 			switch (field->usage[0].hid) {
 			case THRUSTMASTER_USAGE_FF:
 				if (field->report_count < 2) {
-					dev_warn(&hid->dev, "ignoring FF field "
-						"with report_count < 2\n");
+					hid_warn(hid, "ignoring FF field with report_count < 2\n");
 					continue;
 				}
 
 				if (field->logical_maximum ==
 						field->logical_minimum) {
-					dev_warn(&hid->dev, "ignoring FF field "
-							"with logical_maximum "
-							"== logical_minimum\n");
+					hid_warn(hid, "ignoring FF field with logical_maximum == logical_minimum\n");
 					continue;
 				}
 
 				if (tmff->report && tmff->report != report) {
-					dev_warn(&hid->dev, "ignoring FF field "
-							"in other report\n");
+					hid_warn(hid, "ignoring FF field in other report\n");
 					continue;
 				}
 
 				if (tmff->ff_field && tmff->ff_field != field) {
-					dev_warn(&hid->dev, "ignoring "
-							"duplicate FF field\n");
+					hid_warn(hid, "ignoring duplicate FF field\n");
 					continue;
 				}
 
@@ -185,16 +180,15 @@ static int tmff_init(struct hid_device *
 				break;
 
 			default:
-				dev_warn(&hid->dev, "ignoring unknown output "
-						"usage %08x\n",
-						field->usage[0].hid);
+				hid_warn(hid, "ignoring unknown output usage %08x\n",
+					 field->usage[0].hid);
 				continue;
 			}
 		}
 	}
 
 	if (!tmff->report) {
-		dev_err(&hid->dev, "can't find FF field in output reports\n");
+		hid_err(hid, "can't find FF field in output reports\n");
 		error = -ENODEV;
 		goto fail;
 	}
@@ -203,8 +197,7 @@ static int tmff_init(struct hid_device *
 	if (error)
 		goto fail;
 
-	dev_info(&hid->dev, "force feedback for ThrustMaster devices by Zinx "
-			"Verituse <zinx@epicsol.org>");
+	hid_info(hid, "force feedback for ThrustMaster devices by Zinx Verituse <zinx@epicsol.org>\n");
 	return 0;
 
 fail:
@@ -224,13 +217,13 @@ static int tm_probe(struct hid_device *h
 
 	ret = hid_parse(hdev);
 	if (ret) {
-		dev_err(&hdev->dev, "parse failed\n");
+		hid_err(hdev, "parse failed\n");
 		goto err;
 	}
 
 	ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF);
 	if (ret) {
-		dev_err(&hdev->dev, "hw start failed\n");
+		hid_err(hdev, "hw start failed\n");
 		goto err;
 	}
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/hid/hid-topseed.c linux-libre-2.6.38-gnu1/drivers/hid/hid-topseed.c
--- linux-libre-2.6.37-gnu1/drivers/hid/hid-topseed.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hid/hid-topseed.c	2011-03-14 21:20:32.000000000 -0400
@@ -66,6 +66,7 @@ static const struct hid_device_id ts_dev
 	{ HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE_2) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED2, USB_DEVICE_ID_TOPSEED2_RF_COMBO) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS) },
 	{ }
 };
 MODULE_DEVICE_TABLE(hid, ts_devices);
diff -druNp linux-libre-2.6.37-gnu1/drivers/hid/hid-wacom.c linux-libre-2.6.38-gnu1/drivers/hid/hid-wacom.c
--- linux-libre-2.6.37-gnu1/drivers/hid/hid-wacom.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hid/hid-wacom.c	2011-03-14 21:20:32.000000000 -0400
@@ -18,6 +18,8 @@
  * any later version.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/device.h>
 #include <linux/hid.h>
 #include <linux/module.h>
@@ -141,8 +143,8 @@ static void wacom_poke(struct hid_device
 	 * Note that if the raw queries fail, it's not a hard failure and it
 	 * is safe to continue
 	 */
-	dev_warn(&hdev->dev, "failed to poke device, command %d, err %d\n",
-				rep_data[0], ret);
+	hid_warn(hdev, "failed to poke device, command %d, err %d\n",
+		 rep_data[0], ret);
 	return;
 }
 
@@ -172,7 +174,7 @@ static ssize_t wacom_store_speed(struct
 		return -EINVAL;
 }
 
-static DEVICE_ATTR(speed, S_IRUGO | S_IWUGO,
+static DEVICE_ATTR(speed, S_IRUGO | S_IWUSR | S_IWGRP,
 		wacom_show_speed, wacom_store_speed);
 
 static int wacom_raw_event(struct hid_device *hdev, struct hid_report *report,
@@ -312,7 +314,7 @@ static int wacom_probe(struct hid_device
 
 	wdata = kzalloc(sizeof(*wdata), GFP_KERNEL);
 	if (wdata == NULL) {
-		dev_err(&hdev->dev, "can't alloc wacom descriptor\n");
+		hid_err(hdev, "can't alloc wacom descriptor\n");
 		return -ENOMEM;
 	}
 
@@ -321,20 +323,20 @@ static int wacom_probe(struct hid_device
 	/* Parse the HID report now */
 	ret = hid_parse(hdev);
 	if (ret) {
-		dev_err(&hdev->dev, "parse failed\n");
+		hid_err(hdev, "parse failed\n");
 		goto err_free;
 	}
 
 	ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
 	if (ret) {
-		dev_err(&hdev->dev, "hw start failed\n");
+		hid_err(hdev, "hw start failed\n");
 		goto err_free;
 	}
 
 	ret = device_create_file(&hdev->dev, &dev_attr_speed);
 	if (ret)
-		dev_warn(&hdev->dev,
-			"can't create sysfs speed attribute err: %d\n", ret);
+		hid_warn(hdev,
+			 "can't create sysfs speed attribute err: %d\n", ret);
 
 	/* Set Wacom mode 2 with high reporting speed */
 	wacom_poke(hdev, 1);
@@ -349,8 +351,8 @@ static int wacom_probe(struct hid_device
 
 	ret = power_supply_register(&hdev->dev, &wdata->battery);
 	if (ret) {
-		dev_warn(&hdev->dev,
-			"can't create sysfs battery attribute, err: %d\n", ret);
+		hid_warn(hdev, "can't create sysfs battery attribute, err: %d\n",
+			 ret);
 		/*
 		 * battery attribute is not critical for the tablet, but if it
 		 * failed then there is no need to create ac attribute
@@ -367,8 +369,8 @@ static int wacom_probe(struct hid_device
 
 	ret = power_supply_register(&hdev->dev, &wdata->ac);
 	if (ret) {
-		dev_warn(&hdev->dev,
-			"can't create ac battery attribute, err: %d\n", ret);
+		hid_warn(hdev,
+			 "can't create ac battery attribute, err: %d\n", ret);
 		/*
 		 * ac attribute is not critical for the tablet, but if it
 		 * failed then we don't want to battery attribute to exist
@@ -454,7 +456,7 @@ static int __init wacom_init(void)
 
 	ret = hid_register_driver(&wacom_driver);
 	if (ret)
-		printk(KERN_ERR "can't register wacom driver\n");
+		pr_err("can't register wacom driver\n");
 	return ret;
 }
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/hid/hid-zpff.c linux-libre-2.6.38-gnu1/drivers/hid/hid-zpff.c
--- linux-libre-2.6.37-gnu1/drivers/hid/hid-zpff.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hid/hid-zpff.c	2011-03-14 21:20:32.000000000 -0400
@@ -75,14 +75,14 @@ static int zpff_init(struct hid_device *
 	int error;
 
 	if (list_empty(report_list)) {
-		dev_err(&hid->dev, "no output report found\n");
+		hid_err(hid, "no output report found\n");
 		return -ENODEV;
 	}
 
 	report = list_entry(report_list->next, struct hid_report, list);
 
 	if (report->maxfield < 4) {
-		dev_err(&hid->dev, "not enough fields in report\n");
+		hid_err(hid, "not enough fields in report\n");
 		return -ENODEV;
 	}
 
@@ -105,8 +105,7 @@ static int zpff_init(struct hid_device *
 	zpff->report->field[3]->value[0] = 0x00;
 	usbhid_submit_report(hid, zpff->report, USB_DIR_OUT);
 
-	dev_info(&hid->dev, "force feedback for Zeroplus based devices by "
-	       "Anssi Hannula <anssi.hannula@gmail.com>\n");
+	hid_info(hid, "force feedback for Zeroplus based devices by Anssi Hannula <anssi.hannula@gmail.com>\n");
 
 	return 0;
 }
@@ -123,13 +122,13 @@ static int zp_probe(struct hid_device *h
 
 	ret = hid_parse(hdev);
 	if (ret) {
-		dev_err(&hdev->dev, "parse failed\n");
+		hid_err(hdev, "parse failed\n");
 		goto err;
 	}
 
 	ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF);
 	if (ret) {
-		dev_err(&hdev->dev, "hw start failed\n");
+		hid_err(hdev, "hw start failed\n");
 		goto err;
 	}
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/hid/hid-zydacron.c linux-libre-2.6.38-gnu1/drivers/hid/hid-zydacron.c
--- linux-libre-2.6.37-gnu1/drivers/hid/hid-zydacron.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hid/hid-zydacron.c	2011-03-14 21:20:32.000000000 -0400
@@ -34,9 +34,8 @@ static __u8 *zc_report_fixup(struct hid_
 		rdesc[0x96] == 0xbc && rdesc[0x97] == 0xff &&
 		rdesc[0xca] == 0xbc && rdesc[0xcb] == 0xff &&
 		rdesc[0xe1] == 0xbc && rdesc[0xe2] == 0xff) {
-			dev_info(&hdev->dev,
-				"fixing up zydacron remote control report "
-				"descriptor\n");
+			hid_info(hdev,
+				"fixing up zydacron remote control report descriptor\n");
 			rdesc[0x96] = rdesc[0xca] = rdesc[0xe1] = 0x0c;
 			rdesc[0x97] = rdesc[0xcb] = rdesc[0xe2] = 0x00;
 		}
@@ -172,7 +171,7 @@ static int zc_probe(struct hid_device *h
 
 	zc = kzalloc(sizeof(*zc), GFP_KERNEL);
 	if (zc == NULL) {
-		dev_err(&hdev->dev, "zydacron: can't alloc descriptor\n");
+		hid_err(hdev, "can't alloc descriptor\n");
 		return -ENOMEM;
 	}
 
@@ -180,13 +179,13 @@ static int zc_probe(struct hid_device *h
 
 	ret = hid_parse(hdev);
 	if (ret) {
-		dev_err(&hdev->dev, "zydacron: parse failed\n");
+		hid_err(hdev, "parse failed\n");
 		goto err_free;
 	}
 
 	ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
 	if (ret) {
-		dev_err(&hdev->dev, "zydacron: hw start failed\n");
+		hid_err(hdev, "hw start failed\n");
 		goto err_free;
 	}
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/hid/Kconfig linux-libre-2.6.38-gnu1/drivers/hid/Kconfig
--- linux-libre-2.6.37-gnu1/drivers/hid/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hid/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -62,9 +62,9 @@ config HID_3M_PCT
 	Support for 3M PCT touch screens.
 
 config HID_A4TECH
-	tristate "A4 tech mice" if EMBEDDED
+	tristate "A4 tech mice" if EXPERT
 	depends on USB_HID
-	default !EMBEDDED
+	default !EXPERT
 	---help---
 	Support for A4 tech X5 and WOP-35 / Trust 450L mice.
 
@@ -77,9 +77,9 @@ config HID_ACRUX_FF
 	game controllers.
 
 config HID_APPLE
-	tristate "Apple {i,Power,Mac}Books" if EMBEDDED
+	tristate "Apple {i,Power,Mac}Books" if EXPERT
 	depends on (USB_HID || BT_HIDP)
-	default !EMBEDDED
+	default !EXPERT
 	---help---
 	Support for some Apple devices which less or more break
 	HID specification.
@@ -88,9 +88,9 @@ config HID_APPLE
 	MacBooks, MacBook Pros and Apple Aluminum.
 
 config HID_BELKIN
-	tristate "Belkin Flip KVM and Wireless keyboard" if EMBEDDED
+	tristate "Belkin Flip KVM and Wireless keyboard" if EXPERT
 	depends on USB_HID
-	default !EMBEDDED
+	default !EXPERT
 	---help---
 	Support for Belkin Flip KVM and Wireless keyboard.
 
@@ -101,16 +101,16 @@ config HID_CANDO
 	Support for Cando dual touch panel.
 
 config HID_CHERRY
-	tristate "Cherry Cymotion keyboard" if EMBEDDED
+	tristate "Cherry Cymotion keyboard" if EXPERT
 	depends on USB_HID
-	default !EMBEDDED
+	default !EXPERT
 	---help---
 	Support for Cherry Cymotion keyboard.
 
 config HID_CHICONY
-	tristate "Chicony Tactical pad" if EMBEDDED
+	tristate "Chicony Tactical pad" if EXPERT
 	depends on USB_HID
-	default !EMBEDDED
+	default !EXPERT
 	---help---
 	Support for Chicony Tactical pad.
 
@@ -130,9 +130,9 @@ config HID_PRODIKEYS
 	  and some additional multimedia keys.
 
 config HID_CYPRESS
-	tristate "Cypress mouse and barcode readers" if EMBEDDED
+	tristate "Cypress mouse and barcode readers" if EXPERT
 	depends on USB_HID
-	default !EMBEDDED
+	default !EXPERT
 	---help---
 	Support for cypress mouse and barcode readers.
 
@@ -150,11 +150,22 @@ config DRAGONRISE_FF
 	Say Y here if you want to enable force feedback support for DragonRise Inc.
 	game controllers.
 
+config HID_EMS_FF
+	tristate "EMS Production Inc. force feedback support"
+	depends on USB_HID
+	select INPUT_FF_MEMLESS
+	---help---
+	Say Y here if you want to enable force feedback support for devices by
+	EMS Production Ltd.
+	Currently the following devices are known to be supported:
+	 - Trio Linker Plus II
+
 config HID_EGALAX
 	tristate "eGalax multi-touch panel"
 	depends on USB_HID
 	---help---
-	Support for the eGalax dual-touch panel.
+	Support for the eGalax dual-touch panels, including the
+	Joojoo and Wetab tablets.
 
 config HID_ELECOM
 	tristate "ELECOM BM084 bluetooth mouse"
@@ -163,16 +174,16 @@ config HID_ELECOM
 	Support for the ELECOM BM084 (bluetooth mouse).
 
 config HID_EZKEY
-	tristate "Ezkey BTC 8193 keyboard" if EMBEDDED
+	tristate "Ezkey BTC 8193 keyboard" if EXPERT
 	depends on USB_HID
-	default !EMBEDDED
+	default !EXPERT
 	---help---
 	Support for Ezkey BTC 8193 keyboard.
 
 config HID_KYE
-	tristate "Kye/Genius Ergo Mouse" if EMBEDDED
+	tristate "Kye/Genius Ergo Mouse" if EXPERT
 	depends on USB_HID
-	default !EMBEDDED
+	default !EXPERT
 	---help---
 	Support for Kye/Genius Ergo Mouse.
 
@@ -201,16 +212,16 @@ config HID_TWINHAN
 	Support for Twinhan IR remote control.
 
 config HID_KENSINGTON
-	tristate "Kensington Slimblade Trackball" if EMBEDDED
+	tristate "Kensington Slimblade Trackball" if EXPERT
 	depends on USB_HID
-	default !EMBEDDED
+	default !EXPERT
 	---help---
 	Support for Kensington Slimblade Trackball.
 
 config HID_LOGITECH
-	tristate "Logitech devices" if EMBEDDED
+	tristate "Logitech devices" if EXPERT
 	depends on USB_HID
-	default !EMBEDDED
+	default !EXPERT
 	---help---
 	Support for Logitech devices that are not fully compliant with HID standard.
 
@@ -265,9 +276,9 @@ config HID_MAGICMOUSE
 	Apple Wireless "Magic" Mouse.
 
 config HID_MICROSOFT
-	tristate "Microsoft non-fully HID-compliant devices" if EMBEDDED
+	tristate "Microsoft non-fully HID-compliant devices" if EXPERT
 	depends on USB_HID
-	default !EMBEDDED
+	default !EXPERT
 	---help---
 	Support for Microsoft devices that are not fully compliant with HID standard.
 
@@ -278,12 +289,29 @@ config HID_MOSART
 	Support for MosArt dual-touch panels.
 
 config HID_MONTEREY
-	tristate "Monterey Genius KB29E keyboard" if EMBEDDED
+	tristate "Monterey Genius KB29E keyboard" if EXPERT
 	depends on USB_HID
-	default !EMBEDDED
+	default !EXPERT
 	---help---
 	Support for Monterey Genius KB29E.
 
+config HID_MULTITOUCH
+	tristate "HID Multitouch panels"
+	depends on USB_HID
+	---help---
+	  Generic support for HID multitouch panels.
+
+	  Say Y here if you have one of the following devices:
+	  - Cypress TrueTouch panels
+	  - Hanvon dual touch panels
+	  - Pixcir dual touch panels
+	  - 'Sensing Win7-TwoFinger' panel by GeneralTouch
+
+	  If unsure, say N.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called hid-multitouch.
+
 config HID_NTRIG
 	tristate "N-Trig touch screen"
 	depends on USB_HID
@@ -337,8 +365,8 @@ config HID_PICOLCD
 	  - IR
 
 config HID_PICOLCD_FB
-	bool "Framebuffer support" if EMBEDDED
-	default !EMBEDDED
+	bool "Framebuffer support" if EXPERT
+	default !EXPERT
 	depends on HID_PICOLCD
 	depends on HID_PICOLCD=FB || FB=y
 	select FB_DEFERRED_IO
@@ -351,8 +379,8 @@ config HID_PICOLCD_FB
 	  frambuffer device.
 
 config HID_PICOLCD_BACKLIGHT
-	bool "Backlight control" if EMBEDDED
-	default !EMBEDDED
+	bool "Backlight control" if EXPERT
+	default !EXPERT
 	depends on HID_PICOLCD
 	depends on HID_PICOLCD=BACKLIGHT_CLASS_DEVICE || BACKLIGHT_CLASS_DEVICE=y
 	---help---
@@ -360,16 +388,16 @@ config HID_PICOLCD_BACKLIGHT
 	  class.
 
 config HID_PICOLCD_LCD
-	bool "Contrast control" if EMBEDDED
-	default !EMBEDDED
+	bool "Contrast control" if EXPERT
+	default !EXPERT
 	depends on HID_PICOLCD
 	depends on HID_PICOLCD=LCD_CLASS_DEVICE || LCD_CLASS_DEVICE=y
 	---help---
 	  Provide access to PicoLCD's LCD contrast via lcd class.
 
 config HID_PICOLCD_LEDS
-	bool "GPO via leds class" if EMBEDDED
-	default !EMBEDDED
+	bool "GPO via leds class" if EXPERT
+	default !EXPERT
 	depends on HID_PICOLCD
 	depends on HID_PICOLCD=LEDS_CLASS || LEDS_CLASS=y
 	---help---
@@ -396,6 +424,13 @@ config HID_ROCCAT_KONE
 	---help---
 	Support for Roccat Kone mouse.
 
+config HID_ROCCAT_KONEPLUS
+	tristate "Roccat Kone[+] mouse support"
+	depends on USB_HID
+	select HID_ROCCAT
+	---help---
+	Support for Roccat Kone[+] mouse.
+
 config HID_ROCCAT_PYRA
 	tristate "Roccat Pyra mouse support"
 	depends on USB_HID
diff -druNp linux-libre-2.6.37-gnu1/drivers/hid/Makefile linux-libre-2.6.38-gnu1/drivers/hid/Makefile
--- linux-libre-2.6.37-gnu1/drivers/hid/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hid/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -1,7 +1,7 @@
 #
 # Makefile for the HID driver
 #
-hid-objs			:= hid-core.o hid-input.o
+hid-y			:= hid-core.o hid-input.o
 
 ifdef CONFIG_DEBUG_FS
 	hid-objs		+= hid-debug.o
@@ -11,18 +11,18 @@ obj-$(CONFIG_HID)		+= hid.o
 
 hid-$(CONFIG_HIDRAW)		+= hidraw.o
 
-hid-logitech-objs		:= hid-lg.o
+hid-logitech-y		:= hid-lg.o
 ifdef CONFIG_LOGITECH_FF
-	hid-logitech-objs	+= hid-lgff.o
+	hid-logitech-y	+= hid-lgff.o
 endif
 ifdef CONFIG_LOGIRUMBLEPAD2_FF
-	hid-logitech-objs	+= hid-lg2ff.o
+	hid-logitech-y	+= hid-lg2ff.o
 endif
 ifdef CONFIG_LOGIG940_FF
-	hid-logitech-objs	+= hid-lg3ff.o
+	hid-logitech-y	+= hid-lg3ff.o
 endif
 ifdef CONFIG_LOGIWII_FF
-	hid-logitech-objs	+= hid-lg4ff.o
+	hid-logitech-y	+= hid-lg4ff.o
 endif
 
 obj-$(CONFIG_HID_3M_PCT)	+= hid-3m-pct.o
@@ -35,6 +35,7 @@ obj-$(CONFIG_HID_CHERRY)	+= hid-cherry.o
 obj-$(CONFIG_HID_CHICONY)	+= hid-chicony.o
 obj-$(CONFIG_HID_CYPRESS)	+= hid-cypress.o
 obj-$(CONFIG_HID_DRAGONRISE)	+= hid-drff.o
+obj-$(CONFIG_HID_EMS_FF)	+= hid-emsff.o
 obj-$(CONFIG_HID_EGALAX)	+= hid-egalax.o
 obj-$(CONFIG_HID_ELECOM)	+= hid-elecom.o
 obj-$(CONFIG_HID_EZKEY)		+= hid-ezkey.o
@@ -46,6 +47,7 @@ obj-$(CONFIG_HID_MAGICMOUSE)    += hid-m
 obj-$(CONFIG_HID_MICROSOFT)	+= hid-microsoft.o
 obj-$(CONFIG_HID_MONTEREY)	+= hid-monterey.o
 obj-$(CONFIG_HID_MOSART)	+= hid-mosart.o
+obj-$(CONFIG_HID_MULTITOUCH)	+= hid-multitouch.o
 obj-$(CONFIG_HID_NTRIG)		+= hid-ntrig.o
 obj-$(CONFIG_HID_ORTEK)		+= hid-ortek.o
 obj-$(CONFIG_HID_PRODIKEYS)	+= hid-prodikeys.o
@@ -55,6 +57,7 @@ obj-$(CONFIG_HID_PETALYNX)	+= hid-petaly
 obj-$(CONFIG_HID_PICOLCD)	+= hid-picolcd.o
 obj-$(CONFIG_HID_ROCCAT)	+= hid-roccat.o
 obj-$(CONFIG_HID_ROCCAT_KONE)	+= hid-roccat-kone.o
+obj-$(CONFIG_HID_ROCCAT_KONEPLUS)	+= hid-roccat-koneplus.o
 obj-$(CONFIG_HID_ROCCAT_PYRA)	+= hid-roccat-pyra.o
 obj-$(CONFIG_HID_SAMSUNG)	+= hid-samsung.o
 obj-$(CONFIG_HID_SMARTJOYPLUS)	+= hid-sjoy.o
diff -druNp linux-libre-2.6.37-gnu1/drivers/hid/usbhid/hid-core.c linux-libre-2.6.38-gnu1/drivers/hid/usbhid/hid-core.c
--- linux-libre-2.6.37-gnu1/drivers/hid/usbhid/hid-core.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hid/usbhid/hid-core.c	2011-03-14 21:20:32.000000000 -0400
@@ -67,7 +67,6 @@ MODULE_PARM_DESC(quirks, "Add/modify USB
  * Input submission and I/O error handler.
  */
 static DEFINE_MUTEX(hid_open_mut);
-static struct workqueue_struct *resumption_waker;
 
 static void hid_io_error(struct hid_device *hid);
 static int hid_submit_out(struct hid_device *hid);
@@ -136,10 +135,10 @@ static void hid_reset(struct work_struct
 			hid_io_error(hid);
 		break;
 	default:
-		err_hid("can't reset device, %s-%s/input%d, status %d",
-				hid_to_usb_dev(hid)->bus->bus_name,
-				hid_to_usb_dev(hid)->devpath,
-				usbhid->ifnum, rc);
+		hid_err(hid, "can't reset device, %s-%s/input%d, status %d\n",
+			hid_to_usb_dev(hid)->bus->bus_name,
+			hid_to_usb_dev(hid)->devpath,
+			usbhid->ifnum, rc);
 		/* FALLTHROUGH */
 	case -EHOSTUNREACH:
 	case -ENODEV:
@@ -278,18 +277,18 @@ static void hid_irq_in(struct urb *urb)
 		hid_io_error(hid);
 		return;
 	default:		/* error */
-		dev_warn(&urb->dev->dev, "input irq status %d  "
-				"received\n", urb->status);
+		hid_warn(urb->dev, "input irq status %d received\n",
+			 urb->status);
 	}
 
 	status = usb_submit_urb(urb, GFP_ATOMIC);
 	if (status) {
 		clear_bit(HID_IN_RUNNING, &usbhid->iofl);
 		if (status != -EPERM) {
-			err_hid("can't resubmit intr, %s-%s/input%d, status %d",
-					hid_to_usb_dev(hid)->bus->bus_name,
-					hid_to_usb_dev(hid)->devpath,
-					usbhid->ifnum, status);
+			hid_err(hid, "can't resubmit intr, %s-%s/input%d, status %d\n",
+				hid_to_usb_dev(hid)->bus->bus_name,
+				hid_to_usb_dev(hid)->devpath,
+				usbhid->ifnum, status);
 			hid_io_error(hid);
 		}
 	}
@@ -300,10 +299,19 @@ static int hid_submit_out(struct hid_dev
 	struct hid_report *report;
 	char *raw_report;
 	struct usbhid_device *usbhid = hid->driver_data;
+	int r;
 
 	report = usbhid->out[usbhid->outtail].report;
 	raw_report = usbhid->out[usbhid->outtail].raw_report;
 
+	r = usb_autopm_get_interface_async(usbhid->intf);
+	if (r < 0)
+		return -1;
+
+	/*
+	 * if the device hasn't been woken, we leave the output
+	 * to resume()
+	 */
 	if (!test_bit(HID_REPORTED_IDLE, &usbhid->iofl)) {
 		usbhid->urbout->transfer_buffer_length = ((report->size - 1) >> 3) + 1 + (report->id > 0);
 		usbhid->urbout->dev = hid_to_usb_dev(hid);
@@ -313,17 +321,11 @@ static int hid_submit_out(struct hid_dev
 		dbg_hid("submitting out urb\n");
 
 		if (usb_submit_urb(usbhid->urbout, GFP_ATOMIC)) {
-			err_hid("usb_submit_urb(out) failed");
+			hid_err(hid, "usb_submit_urb(out) failed\n");
+			usb_autopm_put_interface_async(usbhid->intf);
 			return -1;
 		}
 		usbhid->last_out = jiffies;
-	} else {
-		/*
-		 * queue work to wake up the device.
-		 * as the work queue is freezeable, this is safe
-		 * with respect to STD and STR
-		 */
-		queue_work(resumption_waker, &usbhid->restart_work);
 	}
 
 	return 0;
@@ -334,13 +336,16 @@ static int hid_submit_ctrl(struct hid_de
 	struct hid_report *report;
 	unsigned char dir;
 	char *raw_report;
-	int len;
+	int len, r;
 	struct usbhid_device *usbhid = hid->driver_data;
 
 	report = usbhid->ctrl[usbhid->ctrltail].report;
 	raw_report = usbhid->ctrl[usbhid->ctrltail].raw_report;
 	dir = usbhid->ctrl[usbhid->ctrltail].dir;
 
+	r = usb_autopm_get_interface_async(usbhid->intf);
+	if (r < 0)
+		return -1;
 	if (!test_bit(HID_REPORTED_IDLE, &usbhid->iofl)) {
 		len = ((report->size - 1) >> 3) + 1 + (report->id > 0);
 		if (dir == USB_DIR_OUT) {
@@ -375,17 +380,11 @@ static int hid_submit_ctrl(struct hid_de
 			usbhid->cr->wValue, usbhid->cr->wIndex, usbhid->cr->wLength);
 
 		if (usb_submit_urb(usbhid->urbctrl, GFP_ATOMIC)) {
-			err_hid("usb_submit_urb(ctrl) failed");
+			usb_autopm_put_interface_async(usbhid->intf);
+			hid_err(hid, "usb_submit_urb(ctrl) failed\n");
 			return -1;
 		}
 		usbhid->last_ctrl = jiffies;
-	} else {
-		/*
-		 * queue work to wake up the device.
-		 * as the work queue is freezeable, this is safe
-		 * with respect to STD and STR
-		 */
-		queue_work(resumption_waker, &usbhid->restart_work);
 	}
 
 	return 0;
@@ -413,8 +412,8 @@ static void hid_irq_out(struct urb *urb)
 	case -ENOENT:
 		break;
 	default:		/* error */
-		dev_warn(&urb->dev->dev, "output irq status %d "
-				"received\n", urb->status);
+		hid_warn(urb->dev, "output irq status %d received\n",
+			 urb->status);
 	}
 
 	spin_lock_irqsave(&usbhid->lock, flags);
@@ -435,6 +434,7 @@ static void hid_irq_out(struct urb *urb)
 
 	clear_bit(HID_OUT_RUNNING, &usbhid->iofl);
 	spin_unlock_irqrestore(&usbhid->lock, flags);
+	usb_autopm_put_interface_async(usbhid->intf);
 	wake_up(&usbhid->wait);
 }
 
@@ -466,8 +466,7 @@ static void hid_ctrl(struct urb *urb)
 	case -EPIPE:		/* report not available */
 		break;
 	default:		/* error */
-		dev_warn(&urb->dev->dev, "ctrl urb status %d "
-				"received\n", status);
+		hid_warn(urb->dev, "ctrl urb status %d received\n", status);
 	}
 
 	if (unplug)
@@ -481,11 +480,13 @@ static void hid_ctrl(struct urb *urb)
 			wake_up(&usbhid->wait);
 		}
 		spin_unlock(&usbhid->lock);
+		usb_autopm_put_interface_async(usbhid->intf);
 		return;
 	}
 
 	clear_bit(HID_CTRL_RUNNING, &usbhid->iofl);
 	spin_unlock(&usbhid->lock);
+	usb_autopm_put_interface_async(usbhid->intf);
 	wake_up(&usbhid->wait);
 }
 
@@ -501,13 +502,13 @@ static void __usbhid_submit_report(struc
 
 	if (usbhid->urbout && dir == USB_DIR_OUT && report->type == HID_OUTPUT_REPORT) {
 		if ((head = (usbhid->outhead + 1) & (HID_OUTPUT_FIFO_SIZE - 1)) == usbhid->outtail) {
-			dev_warn(&hid->dev, "output queue full\n");
+			hid_warn(hid, "output queue full\n");
 			return;
 		}
 
 		usbhid->out[usbhid->outhead].raw_report = kmalloc(len, GFP_ATOMIC);
 		if (!usbhid->out[usbhid->outhead].raw_report) {
-			dev_warn(&hid->dev, "output queueing failed\n");
+			hid_warn(hid, "output queueing failed\n");
 			return;
 		}
 		hid_output_report(report, usbhid->out[usbhid->outhead].raw_report);
@@ -532,14 +533,14 @@ static void __usbhid_submit_report(struc
 	}
 
 	if ((head = (usbhid->ctrlhead + 1) & (HID_CONTROL_FIFO_SIZE - 1)) == usbhid->ctrltail) {
-		dev_warn(&hid->dev, "control queue full\n");
+		hid_warn(hid, "control queue full\n");
 		return;
 	}
 
 	if (dir == USB_DIR_OUT) {
 		usbhid->ctrl[usbhid->ctrlhead].raw_report = kmalloc(len, GFP_ATOMIC);
 		if (!usbhid->ctrl[usbhid->ctrlhead].raw_report) {
-			dev_warn(&hid->dev, "control queueing failed\n");
+			hid_warn(hid, "control queueing failed\n");
 			return;
 		}
 		hid_output_report(report, usbhid->ctrl[usbhid->ctrlhead].raw_report);
@@ -590,7 +591,7 @@ static int usb_hidinput_input_event(stru
 		return -1;
 
 	if ((offset = hidinput_find_field(hid, type, code, &field)) == -1) {
-		dev_warn(&dev->dev, "event field not found\n");
+		hid_warn(dev, "event field not found\n");
 		return -1;
 	}
 
@@ -656,7 +657,7 @@ int usbhid_open(struct hid_device *hid)
 	mutex_lock(&hid_open_mut);
 	if (!hid->open++) {
 		res = usb_autopm_get_interface(usbhid->intf);
-		/* the device must be awake to reliable request remote wakeup */
+		/* the device must be awake to reliably request remote wakeup */
 		if (res < 0) {
 			hid->open--;
 			mutex_unlock(&hid_open_mut);
@@ -722,7 +723,7 @@ void usbhid_init_reports(struct hid_devi
 	}
 
 	if (err)
-		dev_warn(&hid->dev, "timeout initializing reports\n");
+		hid_warn(hid, "timeout initializing reports\n");
 }
 
 /*
@@ -857,18 +858,6 @@ static void usbhid_restart_queues(struct
 	usbhid_restart_ctrl_queue(usbhid);
 }
 
-static void __usbhid_restart_queues(struct work_struct *work)
-{
-	struct usbhid_device *usbhid =
-		container_of(work, struct usbhid_device, restart_work);
-	int r;
-
-	r = usb_autopm_get_interface(usbhid->intf);
-	if (r < 0)
-		return;
-	usb_autopm_put_interface(usbhid->intf);
-}
-
 static void hid_free_buffers(struct usb_device *dev, struct hid_device *hid)
 {
 	struct usbhid_device *usbhid = hid->driver_data;
@@ -1140,8 +1129,7 @@ static int usbhid_probe(struct usb_inter
 		if (usb_endpoint_is_int_in(&interface->endpoint[n].desc))
 			has_in++;
 	if (!has_in) {
-		dev_err(&intf->dev, "couldn't find an input interrupt "
-				"endpoint\n");
+		hid_err(intf, "couldn't find an input interrupt endpoint\n");
 		return -ENODEV;
 	}
 
@@ -1206,14 +1194,13 @@ static int usbhid_probe(struct usb_inter
 
 	init_waitqueue_head(&usbhid->wait);
 	INIT_WORK(&usbhid->reset_work, hid_reset);
-	INIT_WORK(&usbhid->restart_work, __usbhid_restart_queues);
 	setup_timer(&usbhid->io_retry, hid_retry_timeout, (unsigned long) hid);
 	spin_lock_init(&usbhid->lock);
 
 	ret = hid_add_device(hid);
 	if (ret) {
 		if (ret != -ENODEV)
-			dev_err(&intf->dev, "can't add hid device: %d\n", ret);
+			hid_err(intf, "can't add hid device: %d\n", ret);
 		goto err_free;
 	}
 
@@ -1241,7 +1228,6 @@ static void usbhid_disconnect(struct usb
 static void hid_cancel_delayed_stuff(struct usbhid_device *usbhid)
 {
 	del_timer_sync(&usbhid->io_retry);
-	cancel_work_sync(&usbhid->restart_work);
 	cancel_work_sync(&usbhid->reset_work);
 }
 
@@ -1262,7 +1248,6 @@ static int hid_pre_reset(struct usb_inte
 	spin_lock_irq(&usbhid->lock);
 	set_bit(HID_RESET_PENDING, &usbhid->iofl);
 	spin_unlock_irq(&usbhid->lock);
-	cancel_work_sync(&usbhid->restart_work);
 	hid_cease_io(usbhid);
 
 	return 0;
@@ -1461,9 +1446,6 @@ static int __init hid_init(void)
 {
 	int retval = -ENOMEM;
 
-	resumption_waker = create_freezeable_workqueue("usbhid_resumer");
-	if (!resumption_waker)
-		goto no_queue;
 	retval = hid_register_driver(&hid_usb_driver);
 	if (retval)
 		goto hid_register_fail;
@@ -1481,8 +1463,6 @@ usb_register_fail:
 usbhid_quirks_init_fail:
 	hid_unregister_driver(&hid_usb_driver);
 hid_register_fail:
-	destroy_workqueue(resumption_waker);
-no_queue:
 	return retval;
 }
 
@@ -1491,7 +1471,6 @@ static void __exit hid_exit(void)
 	usb_deregister(&hid_driver);
 	usbhid_quirks_exit();
 	hid_unregister_driver(&hid_usb_driver);
-	destroy_workqueue(resumption_waker);
 }
 
 module_init(hid_init);
diff -druNp linux-libre-2.6.37-gnu1/drivers/hid/usbhid/hiddev.c linux-libre-2.6.38-gnu1/drivers/hid/usbhid/hiddev.c
--- linux-libre-2.6.37-gnu1/drivers/hid/usbhid/hiddev.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hid/usbhid/hiddev.c	2011-03-14 21:20:32.000000000 -0400
@@ -585,163 +585,168 @@ static long hiddev_ioctl(struct file *fi
 {
 	struct hiddev_list *list = file->private_data;
 	struct hiddev *hiddev = list->hiddev;
-	struct hid_device *hid = hiddev->hid;
-	struct usb_device *dev;
+	struct hid_device *hid;
 	struct hiddev_collection_info cinfo;
 	struct hiddev_report_info rinfo;
 	struct hiddev_field_info finfo;
 	struct hiddev_devinfo dinfo;
 	struct hid_report *report;
 	struct hid_field *field;
-	struct usbhid_device *usbhid = hid->driver_data;
 	void __user *user_arg = (void __user *)arg;
-	int i, r;
-	
+	int i, r = -EINVAL;
+
 	/* Called without BKL by compat methods so no BKL taken */
 
-	/* FIXME: Who or what stop this racing with a disconnect ?? */
-	if (!hiddev->exist || !hid)
-		return -EIO;
+	mutex_lock(&hiddev->existancelock);
+	if (!hiddev->exist) {
+		r = -ENODEV;
+		goto ret_unlock;
+	}
 
-	dev = hid_to_usb_dev(hid);
+	hid = hiddev->hid;
 
 	switch (cmd) {
 
 	case HIDIOCGVERSION:
-		return put_user(HID_VERSION, (int __user *)arg);
+		r = put_user(HID_VERSION, (int __user *)arg) ?
+			-EFAULT : 0;
+		break;
 
 	case HIDIOCAPPLICATION:
 		if (arg < 0 || arg >= hid->maxapplication)
-			return -EINVAL;
+			break;
 
 		for (i = 0; i < hid->maxcollection; i++)
 			if (hid->collection[i].type ==
 			    HID_COLLECTION_APPLICATION && arg-- == 0)
 				break;
 
-		if (i == hid->maxcollection)
-			return -EINVAL;
-
-		return hid->collection[i].usage;
+		if (i < hid->maxcollection)
+			r = hid->collection[i].usage;
+		break;
 
 	case HIDIOCGDEVINFO:
-		dinfo.bustype = BUS_USB;
-		dinfo.busnum = dev->bus->busnum;
-		dinfo.devnum = dev->devnum;
-		dinfo.ifnum = usbhid->ifnum;
-		dinfo.vendor = le16_to_cpu(dev->descriptor.idVendor);
-		dinfo.product = le16_to_cpu(dev->descriptor.idProduct);
-		dinfo.version = le16_to_cpu(dev->descriptor.bcdDevice);
-		dinfo.num_applications = hid->maxapplication;
-		if (copy_to_user(user_arg, &dinfo, sizeof(dinfo)))
-			return -EFAULT;
+		{
+			struct usb_device *dev = hid_to_usb_dev(hid);
+			struct usbhid_device *usbhid = hid->driver_data;
 
-		return 0;
+			dinfo.bustype = BUS_USB;
+			dinfo.busnum = dev->bus->busnum;
+			dinfo.devnum = dev->devnum;
+			dinfo.ifnum = usbhid->ifnum;
+			dinfo.vendor = le16_to_cpu(dev->descriptor.idVendor);
+			dinfo.product = le16_to_cpu(dev->descriptor.idProduct);
+			dinfo.version = le16_to_cpu(dev->descriptor.bcdDevice);
+			dinfo.num_applications = hid->maxapplication;
 
-	case HIDIOCGFLAG:
-		if (put_user(list->flags, (int __user *)arg))
-			return -EFAULT;
+			r = copy_to_user(user_arg, &dinfo, sizeof(dinfo)) ?
+				-EFAULT : 0;
+			break;
+		}
 
-		return 0;
+	case HIDIOCGFLAG:
+		r = put_user(list->flags, (int __user *)arg) ?
+			-EFAULT : 0;
+		break;
 
 	case HIDIOCSFLAG:
 		{
 			int newflags;
-			if (get_user(newflags, (int __user *)arg))
-				return -EFAULT;
+
+			if (get_user(newflags, (int __user *)arg)) {
+				r = -EFAULT;
+				break;
+			}
 
 			if ((newflags & ~HIDDEV_FLAGS) != 0 ||
 			    ((newflags & HIDDEV_FLAG_REPORT) != 0 &&
 			     (newflags & HIDDEV_FLAG_UREF) == 0))
-				return -EINVAL;
+				break;
 
 			list->flags = newflags;
 
-			return 0;
+			r = 0;
+			break;
 		}
 
 	case HIDIOCGSTRING:
-		mutex_lock(&hiddev->existancelock);
-		if (hiddev->exist)
-			r = hiddev_ioctl_string(hiddev, cmd, user_arg);
-		else
-			r = -ENODEV;
-		mutex_unlock(&hiddev->existancelock);
-		return r;
+		r = hiddev_ioctl_string(hiddev, cmd, user_arg);
+		break;
 
 	case HIDIOCINITREPORT:
-		mutex_lock(&hiddev->existancelock);
-		if (!hiddev->exist) {
-			mutex_unlock(&hiddev->existancelock);
-			return -ENODEV;
-		}
 		usbhid_init_reports(hid);
-		mutex_unlock(&hiddev->existancelock);
-
-		return 0;
+		r = 0;
+		break;
 
 	case HIDIOCGREPORT:
-		if (copy_from_user(&rinfo, user_arg, sizeof(rinfo)))
-			return -EFAULT;
+		if (copy_from_user(&rinfo, user_arg, sizeof(rinfo))) {
+			r = -EFAULT;
+			break;
+		}
 
 		if (rinfo.report_type == HID_REPORT_TYPE_OUTPUT)
-			return -EINVAL;
+			break;
 
-		if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL)
-			return -EINVAL;
+		report = hiddev_lookup_report(hid, &rinfo);
+		if (report == NULL)
+			break;
 
-		mutex_lock(&hiddev->existancelock);
-		if (hiddev->exist) {
-			usbhid_submit_report(hid, report, USB_DIR_IN);
-			usbhid_wait_io(hid);
-		}
-		mutex_unlock(&hiddev->existancelock);
+		usbhid_submit_report(hid, report, USB_DIR_IN);
+		usbhid_wait_io(hid);
 
-		return 0;
+		r = 0;
+		break;
 
 	case HIDIOCSREPORT:
-		if (copy_from_user(&rinfo, user_arg, sizeof(rinfo)))
-			return -EFAULT;
+		if (copy_from_user(&rinfo, user_arg, sizeof(rinfo))) {
+			r = -EFAULT;
+			break;
+		}
 
 		if (rinfo.report_type == HID_REPORT_TYPE_INPUT)
-			return -EINVAL;
+			break;
 
-		if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL)
-			return -EINVAL;
+		report = hiddev_lookup_report(hid, &rinfo);
+		if (report == NULL)
+			break;
 
-		mutex_lock(&hiddev->existancelock);
-		if (hiddev->exist) {
-			usbhid_submit_report(hid, report, USB_DIR_OUT);
-			usbhid_wait_io(hid);
-		}
-		mutex_unlock(&hiddev->existancelock);
+		usbhid_submit_report(hid, report, USB_DIR_OUT);
+		usbhid_wait_io(hid);
 
-		return 0;
+		r = 0;
+		break;
 
 	case HIDIOCGREPORTINFO:
-		if (copy_from_user(&rinfo, user_arg, sizeof(rinfo)))
-			return -EFAULT;
+		if (copy_from_user(&rinfo, user_arg, sizeof(rinfo))) {
+			r = -EFAULT;
+			break;
+		}
 
-		if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL)
-			return -EINVAL;
+		report = hiddev_lookup_report(hid, &rinfo);
+		if (report == NULL)
+			break;
 
 		rinfo.num_fields = report->maxfield;
 
-		if (copy_to_user(user_arg, &rinfo, sizeof(rinfo)))
-			return -EFAULT;
-
-		return 0;
+		r = copy_to_user(user_arg, &rinfo, sizeof(rinfo)) ?
+			-EFAULT : 0;
+		break;
 
 	case HIDIOCGFIELDINFO:
-		if (copy_from_user(&finfo, user_arg, sizeof(finfo)))
-			return -EFAULT;
+		if (copy_from_user(&finfo, user_arg, sizeof(finfo))) {
+			r = -EFAULT;
+			break;
+		}
+
 		rinfo.report_type = finfo.report_type;
 		rinfo.report_id = finfo.report_id;
-		if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL)
-			return -EINVAL;
+
+		report = hiddev_lookup_report(hid, &rinfo);
+		if (report == NULL)
+			break;
 
 		if (finfo.field_index >= report->maxfield)
-			return -EINVAL;
+			break;
 
 		field = report->field[finfo.field_index];
 		memset(&finfo, 0, sizeof(finfo));
@@ -760,10 +765,9 @@ static long hiddev_ioctl(struct file *fi
 		finfo.unit_exponent = field->unit_exponent;
 		finfo.unit = field->unit;
 
-		if (copy_to_user(user_arg, &finfo, sizeof(finfo)))
-			return -EFAULT;
-
-		return 0;
+		r = copy_to_user(user_arg, &finfo, sizeof(finfo)) ?
+			-EFAULT : 0;
+		break;
 
 	case HIDIOCGUCODE:
 		/* fall through */
@@ -772,57 +776,66 @@ static long hiddev_ioctl(struct file *fi
 	case HIDIOCGUSAGES:
 	case HIDIOCSUSAGES:
 	case HIDIOCGCOLLECTIONINDEX:
-		mutex_lock(&hiddev->existancelock);
-		if (hiddev->exist)
-			r = hiddev_ioctl_usage(hiddev, cmd, user_arg);
-		else
-			r = -ENODEV;
-		mutex_unlock(&hiddev->existancelock);
-		return r;
+		r = hiddev_ioctl_usage(hiddev, cmd, user_arg);
+		break;
 
 	case HIDIOCGCOLLECTIONINFO:
-		if (copy_from_user(&cinfo, user_arg, sizeof(cinfo)))
-			return -EFAULT;
+		if (copy_from_user(&cinfo, user_arg, sizeof(cinfo))) {
+			r = -EFAULT;
+			break;
+		}
 
 		if (cinfo.index >= hid->maxcollection)
-			return -EINVAL;
+			break;
 
 		cinfo.type = hid->collection[cinfo.index].type;
 		cinfo.usage = hid->collection[cinfo.index].usage;
 		cinfo.level = hid->collection[cinfo.index].level;
 
-		if (copy_to_user(user_arg, &cinfo, sizeof(cinfo)))
-			return -EFAULT;
-		return 0;
+		r = copy_to_user(user_arg, &cinfo, sizeof(cinfo)) ?
+			-EFAULT : 0;
+		break;
 
 	default:
-
 		if (_IOC_TYPE(cmd) != 'H' || _IOC_DIR(cmd) != _IOC_READ)
-			return -EINVAL;
+			break;
 
 		if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGNAME(0))) {
 			int len;
-			if (!hid->name)
-				return 0;
+
+			if (!hid->name) {
+				r = 0;
+				break;
+			}
+
 			len = strlen(hid->name) + 1;
 			if (len > _IOC_SIZE(cmd))
 				 len = _IOC_SIZE(cmd);
-			return copy_to_user(user_arg, hid->name, len) ?
+			r = copy_to_user(user_arg, hid->name, len) ?
 				-EFAULT : len;
+			break;
 		}
 
 		if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGPHYS(0))) {
 			int len;
-			if (!hid->phys)
-				return 0;
+
+			if (!hid->phys) {
+				r = 0;
+				break;
+			}
+
 			len = strlen(hid->phys) + 1;
 			if (len > _IOC_SIZE(cmd))
 				len = _IOC_SIZE(cmd);
-			return copy_to_user(user_arg, hid->phys, len) ?
+			r = copy_to_user(user_arg, hid->phys, len) ?
 				-EFAULT : len;
+			break;
 		}
 	}
-	return -EINVAL;
+
+ret_unlock:
+	mutex_unlock(&hiddev->existancelock);
+	return r;
 }
 
 #ifdef CONFIG_COMPAT
@@ -892,7 +905,7 @@ int hiddev_connect(struct hid_device *hi
 	hiddev->exist = 1;
 	retval = usb_register_dev(usbhid->intf, &hiddev_class);
 	if (retval) {
-		err_hid("Not able to get a minor for this device.");
+		hid_err(hid, "Not able to get a minor for this device\n");
 		hid->hiddev = NULL;
 		kfree(hiddev);
 		return -1;
diff -druNp linux-libre-2.6.37-gnu1/drivers/hid/usbhid/hid-pidff.c linux-libre-2.6.38-gnu1/drivers/hid/usbhid/hid-pidff.c
--- linux-libre-2.6.37-gnu1/drivers/hid/usbhid/hid-pidff.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hid/usbhid/hid-pidff.c	2011-03-14 21:20:32.000000000 -0400
@@ -22,7 +22,7 @@
 
 /* #define DEBUG */
 
-#define debug(format, arg...) pr_debug("hid-pidff: " format "\n" , ## arg)
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
 #include <linux/input.h>
 #include <linux/slab.h>
@@ -220,7 +220,7 @@ static int pidff_rescale_signed(int i, s
 static void pidff_set(struct pidff_usage *usage, u16 value)
 {
 	usage->value[0] = pidff_rescale(value, 0xffff, usage->field);
-	debug("calculated from %d to %d", value, usage->value[0]);
+	pr_debug("calculated from %d to %d\n", value, usage->value[0]);
 }
 
 static void pidff_set_signed(struct pidff_usage *usage, s16 value)
@@ -235,7 +235,7 @@ static void pidff_set_signed(struct pidf
 			usage->value[0] =
 			    pidff_rescale(value, 0x7fff, usage->field);
 	}
-	debug("calculated from %d to %d", value, usage->value[0]);
+	pr_debug("calculated from %d to %d\n", value, usage->value[0]);
 }
 
 /*
@@ -259,8 +259,9 @@ static void pidff_set_envelope_report(st
 	pidff->set_envelope[PID_ATTACK_TIME].value[0] = envelope->attack_length;
 	pidff->set_envelope[PID_FADE_TIME].value[0] = envelope->fade_length;
 
-	debug("attack %u => %d", envelope->attack_level,
-	      pidff->set_envelope[PID_ATTACK_LEVEL].value[0]);
+	hid_dbg(pidff->hid, "attack %u => %d\n",
+		envelope->attack_level,
+		pidff->set_envelope[PID_ATTACK_LEVEL].value[0]);
 
 	usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_ENVELOPE],
 			  USB_DIR_OUT);
@@ -466,33 +467,33 @@ static int pidff_request_effect_upload(s
 	pidff->create_new_effect_type->value[0] = efnum;
 	usbhid_submit_report(pidff->hid, pidff->reports[PID_CREATE_NEW_EFFECT],
 			  USB_DIR_OUT);
-	debug("create_new_effect sent, type: %d", efnum);
+	hid_dbg(pidff->hid, "create_new_effect sent, type: %d\n", efnum);
 
 	pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0] = 0;
 	pidff->block_load_status->value[0] = 0;
 	usbhid_wait_io(pidff->hid);
 
 	for (j = 0; j < 60; j++) {
-		debug("pid_block_load requested");
+		hid_dbg(pidff->hid, "pid_block_load requested\n");
 		usbhid_submit_report(pidff->hid, pidff->reports[PID_BLOCK_LOAD],
 				  USB_DIR_IN);
 		usbhid_wait_io(pidff->hid);
 		if (pidff->block_load_status->value[0] ==
 		    pidff->status_id[PID_BLOCK_LOAD_SUCCESS]) {
-			debug("device reported free memory: %d bytes",
-			      pidff->block_load[PID_RAM_POOL_AVAILABLE].value ?
-				pidff->block_load[PID_RAM_POOL_AVAILABLE].value[0] : -1);
+			hid_dbg(pidff->hid, "device reported free memory: %d bytes\n",
+				 pidff->block_load[PID_RAM_POOL_AVAILABLE].value ?
+				 pidff->block_load[PID_RAM_POOL_AVAILABLE].value[0] : -1);
 			return 0;
 		}
 		if (pidff->block_load_status->value[0] ==
 		    pidff->status_id[PID_BLOCK_LOAD_FULL]) {
-			debug("not enough memory free: %d bytes",
-			      pidff->block_load[PID_RAM_POOL_AVAILABLE].value ?
+			hid_dbg(pidff->hid, "not enough memory free: %d bytes\n",
+				pidff->block_load[PID_RAM_POOL_AVAILABLE].value ?
 				pidff->block_load[PID_RAM_POOL_AVAILABLE].value[0] : -1);
 			return -ENOSPC;
 		}
 	}
-	printk(KERN_ERR "hid-pidff: pid_block_load failed 60 times\n");
+	hid_err(pidff->hid, "pid_block_load failed 60 times\n");
 	return -EIO;
 }
 
@@ -546,7 +547,8 @@ static int pidff_erase_effect(struct inp
 	struct pidff_device *pidff = dev->ff->private;
 	int pid_id = pidff->pid_id[effect_id];
 
-	debug("starting to erase %d/%d", effect_id, pidff->pid_id[effect_id]);
+	hid_dbg(pidff->hid, "starting to erase %d/%d\n",
+		effect_id, pidff->pid_id[effect_id]);
 	/* Wait for the queue to clear. We do not want a full fifo to
 	   prevent the effect removal. */
 	usbhid_wait_io(pidff->hid);
@@ -604,8 +606,7 @@ static int pidff_upload_effect(struct in
 				type_id = PID_SAW_DOWN;
 				break;
 			default:
-				printk(KERN_ERR
-				       "hid-pidff: invalid waveform\n");
+				hid_err(pidff->hid, "invalid waveform\n");
 				return -EINVAL;
 			}
 
@@ -696,7 +697,7 @@ static int pidff_upload_effect(struct in
 		break;
 
 	default:
-		printk(KERN_ERR "hid-pidff: invalid type\n");
+		hid_err(pidff->hid, "invalid type\n");
 		return -EINVAL;
 	}
 
@@ -704,7 +705,7 @@ static int pidff_upload_effect(struct in
 		pidff->pid_id[effect->id] =
 		    pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0];
 
-	debug("uploaded");
+	hid_dbg(pidff->hid, "uploaded\n");
 
 	return 0;
 }
@@ -770,14 +771,14 @@ static int pidff_find_fields(struct pidf
 		for (i = 0; i < report->maxfield; i++) {
 			if (report->field[i]->maxusage !=
 			    report->field[i]->report_count) {
-				debug("maxusage and report_count do not match, "
-				      "skipping");
+				pr_debug("maxusage and report_count do not match, skipping\n");
 				continue;
 			}
 			for (j = 0; j < report->field[i]->maxusage; j++) {
 				if (report->field[i]->usage[j].hid ==
 				    (HID_UP_PID | table[k])) {
-					debug("found %d at %d->%d", k, i, j);
+					pr_debug("found %d at %d->%d\n",
+						 k, i, j);
 					usage[k].field = report->field[i];
 					usage[k].value =
 						&report->field[i]->value[j];
@@ -789,7 +790,7 @@ static int pidff_find_fields(struct pidf
 				break;
 		}
 		if (!found && strict) {
-			debug("failed to locate %d", k);
+			pr_debug("failed to locate %d\n", k);
 			return -1;
 		}
 	}
@@ -826,8 +827,8 @@ static void pidff_find_reports(struct hi
 			continue;
 		ret = pidff_check_usage(report->field[0]->logical);
 		if (ret != -1) {
-			debug("found usage 0x%02x from field->logical",
-			      pidff_reports[ret]);
+			hid_dbg(hid, "found usage 0x%02x from field->logical\n",
+				pidff_reports[ret]);
 			pidff->reports[ret] = report;
 			continue;
 		}
@@ -845,8 +846,9 @@ static void pidff_find_reports(struct hi
 			continue;
 		ret = pidff_check_usage(hid->collection[i - 1].usage);
 		if (ret != -1 && !pidff->reports[ret]) {
-			debug("found usage 0x%02x from collection array",
-			      pidff_reports[ret]);
+			hid_dbg(hid,
+				"found usage 0x%02x from collection array\n",
+				pidff_reports[ret]);
 			pidff->reports[ret] = report;
 		}
 	}
@@ -861,7 +863,7 @@ static int pidff_reports_ok(struct pidff
 
 	for (i = 0; i <= PID_REQUIRED_REPORTS; i++) {
 		if (!pidff->reports[i]) {
-			debug("%d missing", i);
+			hid_dbg(pidff->hid, "%d missing\n", i);
 			return 0;
 		}
 	}
@@ -884,8 +886,7 @@ static struct hid_field *pidff_find_spec
 			    report->field[i]->logical_minimum == 1)
 				return report->field[i];
 			else {
-				printk(KERN_ERR "hid-pidff: logical_minimum "
-					"is not 1 as it should be\n");
+				pr_err("logical_minimum is not 1 as it should be\n");
 				return NULL;
 			}
 		}
@@ -924,7 +925,7 @@ static int pidff_find_special_keys(int *
  */
 static int pidff_find_special_fields(struct pidff_device *pidff)
 {
-	debug("finding special fields");
+	hid_dbg(pidff->hid, "finding special fields\n");
 
 	pidff->create_new_effect_type =
 		pidff_find_special_field(pidff->reports[PID_CREATE_NEW_EFFECT],
@@ -945,32 +946,30 @@ static int pidff_find_special_fields(str
 		pidff_find_special_field(pidff->reports[PID_EFFECT_OPERATION],
 					 0x78, 1);
 
-	debug("search done");
+	hid_dbg(pidff->hid, "search done\n");
 
 	if (!pidff->create_new_effect_type || !pidff->set_effect_type) {
-		printk(KERN_ERR "hid-pidff: effect lists not found\n");
+		hid_err(pidff->hid, "effect lists not found\n");
 		return -1;
 	}
 
 	if (!pidff->effect_direction) {
-		printk(KERN_ERR "hid-pidff: direction field not found\n");
+		hid_err(pidff->hid, "direction field not found\n");
 		return -1;
 	}
 
 	if (!pidff->device_control) {
-		printk(KERN_ERR "hid-pidff: device control field not found\n");
+		hid_err(pidff->hid, "device control field not found\n");
 		return -1;
 	}
 
 	if (!pidff->block_load_status) {
-		printk(KERN_ERR
-		       "hid-pidff: block load status field not found\n");
+		hid_err(pidff->hid, "block load status field not found\n");
 		return -1;
 	}
 
 	if (!pidff->effect_operation_status) {
-		printk(KERN_ERR
-		       "hid-pidff: effect operation field not found\n");
+		hid_err(pidff->hid, "effect operation field not found\n");
 		return -1;
 	}
 
@@ -982,23 +981,22 @@ static int pidff_find_special_fields(str
 
 	if (!PIDFF_FIND_SPECIAL_KEYS(type_id, create_new_effect_type,
 				     effect_types)) {
-		printk(KERN_ERR "hid-pidff: no effect types found\n");
+		hid_err(pidff->hid, "no effect types found\n");
 		return -1;
 	}
 
 	if (PIDFF_FIND_SPECIAL_KEYS(status_id, block_load_status,
 				    block_load_status) !=
 			sizeof(pidff_block_load_status)) {
-		printk(KERN_ERR
-		       "hidpidff: block load status identifiers not found\n");
+		hid_err(pidff->hid,
+			"block load status identifiers not found\n");
 		return -1;
 	}
 
 	if (PIDFF_FIND_SPECIAL_KEYS(operation_id, effect_operation_status,
 				    effect_operation_status) !=
 			sizeof(pidff_effect_operation_status)) {
-		printk(KERN_ERR
-		       "hidpidff: effect operation identifiers not found\n");
+		hid_err(pidff->hid, "effect operation identifiers not found\n");
 		return -1;
 	}
 
@@ -1017,8 +1015,8 @@ static int pidff_find_effects(struct pid
 		int pidff_type = pidff->type_id[i];
 		if (pidff->set_effect_type->usage[pidff_type].hid !=
 		    pidff->create_new_effect_type->usage[pidff_type].hid) {
-			printk(KERN_ERR "hid-pidff: "
-			       "effect type number %d is invalid\n", i);
+			hid_err(pidff->hid,
+				"effect type number %d is invalid\n", i);
 			return -1;
 		}
 	}
@@ -1073,27 +1071,23 @@ static int pidff_init_fields(struct pidf
 	int envelope_ok = 0;
 
 	if (PIDFF_FIND_FIELDS(set_effect, PID_SET_EFFECT, 1)) {
-		printk(KERN_ERR
-		       "hid-pidff: unknown set_effect report layout\n");
+		hid_err(pidff->hid, "unknown set_effect report layout\n");
 		return -ENODEV;
 	}
 
 	PIDFF_FIND_FIELDS(block_load, PID_BLOCK_LOAD, 0);
 	if (!pidff->block_load[PID_EFFECT_BLOCK_INDEX].value) {
-		printk(KERN_ERR
-		       "hid-pidff: unknown pid_block_load report layout\n");
+		hid_err(pidff->hid, "unknown pid_block_load report layout\n");
 		return -ENODEV;
 	}
 
 	if (PIDFF_FIND_FIELDS(effect_operation, PID_EFFECT_OPERATION, 1)) {
-		printk(KERN_ERR
-		       "hid-pidff: unknown effect_operation report layout\n");
+		hid_err(pidff->hid, "unknown effect_operation report layout\n");
 		return -ENODEV;
 	}
 
 	if (PIDFF_FIND_FIELDS(block_free, PID_BLOCK_FREE, 1)) {
-		printk(KERN_ERR
-		       "hid-pidff: unknown pid_block_free report layout\n");
+		hid_err(pidff->hid, "unknown pid_block_free report layout\n");
 		return -ENODEV;
 	}
 
@@ -1105,27 +1099,26 @@ static int pidff_init_fields(struct pidf
 
 	if (!envelope_ok) {
 		if (test_and_clear_bit(FF_CONSTANT, dev->ffbit))
-			printk(KERN_WARNING "hid-pidff: "
-			       "has constant effect but no envelope\n");
+			hid_warn(pidff->hid,
+				 "has constant effect but no envelope\n");
 		if (test_and_clear_bit(FF_RAMP, dev->ffbit))
-			printk(KERN_WARNING "hid-pidff: "
-				"has ramp effect but no envelope\n");
+			hid_warn(pidff->hid,
+				 "has ramp effect but no envelope\n");
 
 		if (test_and_clear_bit(FF_PERIODIC, dev->ffbit))
-			printk(KERN_WARNING "hid-pidff: "
-				"has periodic effect but no envelope\n");
+			hid_warn(pidff->hid,
+				 "has periodic effect but no envelope\n");
 	}
 
 	if (test_bit(FF_CONSTANT, dev->ffbit) &&
 	    PIDFF_FIND_FIELDS(set_constant, PID_SET_CONSTANT, 1)) {
-		printk(KERN_WARNING
-		       "hid-pidff: unknown constant effect layout\n");
+		hid_warn(pidff->hid, "unknown constant effect layout\n");
 		clear_bit(FF_CONSTANT, dev->ffbit);
 	}
 
 	if (test_bit(FF_RAMP, dev->ffbit) &&
 	    PIDFF_FIND_FIELDS(set_ramp, PID_SET_RAMP, 1)) {
-		printk(KERN_WARNING "hid-pidff: unknown ramp effect layout\n");
+		hid_warn(pidff->hid, "unknown ramp effect layout\n");
 		clear_bit(FF_RAMP, dev->ffbit);
 	}
 
@@ -1134,8 +1127,7 @@ static int pidff_init_fields(struct pidf
 	     test_bit(FF_FRICTION, dev->ffbit) ||
 	     test_bit(FF_INERTIA, dev->ffbit)) &&
 	    PIDFF_FIND_FIELDS(set_condition, PID_SET_CONDITION, 1)) {
-		printk(KERN_WARNING
-		       "hid-pidff: unknown condition effect layout\n");
+		hid_warn(pidff->hid, "unknown condition effect layout\n");
 		clear_bit(FF_SPRING, dev->ffbit);
 		clear_bit(FF_DAMPER, dev->ffbit);
 		clear_bit(FF_FRICTION, dev->ffbit);
@@ -1144,8 +1136,7 @@ static int pidff_init_fields(struct pidf
 
 	if (test_bit(FF_PERIODIC, dev->ffbit) &&
 	    PIDFF_FIND_FIELDS(set_periodic, PID_SET_PERIODIC, 1)) {
-		printk(KERN_WARNING
-		       "hid-pidff: unknown periodic effect layout\n");
+		hid_warn(pidff->hid, "unknown periodic effect layout\n");
 		clear_bit(FF_PERIODIC, dev->ffbit);
 	}
 
@@ -1184,12 +1175,12 @@ static void pidff_reset(struct pidff_dev
 	if (pidff->pool[PID_SIMULTANEOUS_MAX].value) {
 		while (pidff->pool[PID_SIMULTANEOUS_MAX].value[0] < 2) {
 			if (i++ > 20) {
-				printk(KERN_WARNING "hid-pidff: device reports "
-				       "%d simultaneous effects\n",
-				       pidff->pool[PID_SIMULTANEOUS_MAX].value[0]);
+				hid_warn(pidff->hid,
+					 "device reports %d simultaneous effects\n",
+					 pidff->pool[PID_SIMULTANEOUS_MAX].value[0]);
 				break;
 			}
-			debug("pid_pool requested again");
+			hid_dbg(pidff->hid, "pid_pool requested again\n");
 			usbhid_submit_report(hid, pidff->reports[PID_POOL],
 					  USB_DIR_IN);
 			usbhid_wait_io(hid);
@@ -1215,7 +1206,7 @@ static int pidff_check_autocenter(struct
 
 	error = pidff_request_effect_upload(pidff, 1);
 	if (error) {
-		printk(KERN_ERR "hid-pidff: upload request failed\n");
+		hid_err(pidff->hid, "upload request failed\n");
 		return error;
 	}
 
@@ -1224,8 +1215,8 @@ static int pidff_check_autocenter(struct
 		pidff_autocenter(pidff, 0xffff);
 		set_bit(FF_AUTOCENTER, dev->ffbit);
 	} else {
-		printk(KERN_NOTICE "hid-pidff: "
-		       "device has unknown autocenter control method\n");
+		hid_notice(pidff->hid,
+			   "device has unknown autocenter control method\n");
 	}
 
 	pidff_erase_pid(pidff,
@@ -1248,10 +1239,10 @@ int hid_pidff_init(struct hid_device *hi
 	int max_effects;
 	int error;
 
-	debug("starting pid init");
+	hid_dbg(hid, "starting pid init\n");
 
 	if (list_empty(&hid->report_enum[HID_OUTPUT_REPORT].report_list)) {
-		debug("not a PID device, no output report");
+		hid_dbg(hid, "not a PID device, no output report\n");
 		return -ENODEV;
 	}
 
@@ -1265,7 +1256,7 @@ int hid_pidff_init(struct hid_device *hi
 	pidff_find_reports(hid, HID_FEATURE_REPORT, pidff);
 
 	if (!pidff_reports_ok(pidff)) {
-		debug("reports not ok, aborting");
+		hid_dbg(hid, "reports not ok, aborting\n");
 		error = -ENODEV;
 		goto fail;
 	}
@@ -1278,8 +1269,8 @@ int hid_pidff_init(struct hid_device *hi
 
 	if (test_bit(FF_GAIN, dev->ffbit)) {
 		pidff_set(&pidff->device_gain[PID_DEVICE_GAIN_FIELD], 0xffff);
-		usbhid_submit_report(pidff->hid, pidff->reports[PID_DEVICE_GAIN],
-				  USB_DIR_OUT);
+		usbhid_submit_report(hid, pidff->reports[PID_DEVICE_GAIN],
+				     USB_DIR_OUT);
 	}
 
 	error = pidff_check_autocenter(pidff, dev);
@@ -1290,23 +1281,23 @@ int hid_pidff_init(struct hid_device *hi
 	    pidff->block_load[PID_EFFECT_BLOCK_INDEX].field->logical_maximum -
 	    pidff->block_load[PID_EFFECT_BLOCK_INDEX].field->logical_minimum +
 	    1;
-	debug("max effects is %d", max_effects);
+	hid_dbg(hid, "max effects is %d\n", max_effects);
 
 	if (max_effects > PID_EFFECTS_MAX)
 		max_effects = PID_EFFECTS_MAX;
 
 	if (pidff->pool[PID_SIMULTANEOUS_MAX].value)
-		debug("max simultaneous effects is %d",
-		      pidff->pool[PID_SIMULTANEOUS_MAX].value[0]);
+		hid_dbg(hid, "max simultaneous effects is %d\n",
+			pidff->pool[PID_SIMULTANEOUS_MAX].value[0]);
 
 	if (pidff->pool[PID_RAM_POOL_SIZE].value)
-		debug("device memory size is %d bytes",
-		      pidff->pool[PID_RAM_POOL_SIZE].value[0]);
+		hid_dbg(hid, "device memory size is %d bytes\n",
+			pidff->pool[PID_RAM_POOL_SIZE].value[0]);
 
 	if (pidff->pool[PID_DEVICE_MANAGED_POOL].value &&
 	    pidff->pool[PID_DEVICE_MANAGED_POOL].value[0] == 0) {
-		printk(KERN_NOTICE "hid-pidff: "
-		       "device does not support device managed pool\n");
+		hid_notice(hid,
+			   "device does not support device managed pool\n");
 		goto fail;
 	}
 
@@ -1322,8 +1313,7 @@ int hid_pidff_init(struct hid_device *hi
 	ff->set_autocenter = pidff_set_autocenter;
 	ff->playback = pidff_playback;
 
-	printk(KERN_INFO "Force feedback for USB HID PID devices by "
-	       "Anssi Hannula <anssi.hannula@gmail.com>\n");
+	hid_info(dev, "Force feedback for USB HID PID devices by Anssi Hannula <anssi.hannula@gmail.com>\n");
 
 	return 0;
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/hid/usbhid/hid-quirks.c linux-libre-2.6.38-gnu1/drivers/hid/usbhid/hid-quirks.c
--- linux-libre-2.6.37-gnu1/drivers/hid/usbhid/hid-quirks.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hid/usbhid/hid-quirks.c	2011-03-14 21:20:32.000000000 -0400
@@ -35,7 +35,6 @@ static const struct hid_blacklist {
 	{ USB_VENDOR_ID_CHIC, USB_DEVICE_ID_CHIC_GAMEPAD, HID_QUIRK_BADPAD },
 	{ USB_VENDOR_ID_DWAV, USB_DEVICE_ID_EGALAX_TOUCHCONTROLLER, HID_QUIRK_MULTI_INPUT | HID_QUIRK_NOGET },
 	{ USB_VENDOR_ID_MOJO, USB_DEVICE_ID_RETRO_ADAPTER, HID_QUIRK_MULTI_INPUT },
-	{ USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_TOUCHSCREEN_MOSART, HID_QUIRK_MULTI_INPUT },
 	{ USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_DRIVING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT },
 	{ USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FLYING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT },
 	{ USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FIGHTING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT },
@@ -85,7 +84,7 @@ static const struct hid_blacklist {
 	{ USB_VENDOR_ID_PI_ENGINEERING, USB_DEVICE_ID_PI_ENGINEERING_VEC_USB_FOOTPEDAL, HID_QUIRK_HIDINPUT_FORCE },
 
 	{ USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_MULTI_TOUCH, HID_QUIRK_MULTI_INPUT },
-
+	{ USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS, HID_QUIRK_MULTI_INPUT },
 	{ 0, 0 }
 };
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/hid/usbhid/Kconfig linux-libre-2.6.38-gnu1/drivers/hid/usbhid/Kconfig
--- linux-libre-2.6.37-gnu1/drivers/hid/usbhid/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hid/usbhid/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -45,7 +45,7 @@ config USB_HIDDEV
 	  If unsure, say Y.
 
 menu "USB HID Boot Protocol drivers"
-	depends on USB!=n && USB_HID!=y && EMBEDDED
+	depends on USB!=n && USB_HID!=y && EXPERT
 
 config USB_KBD
 	tristate "USB HIDBP Keyboard (simple Boot) support"
diff -druNp linux-libre-2.6.37-gnu1/drivers/hid/usbhid/Makefile linux-libre-2.6.38-gnu1/drivers/hid/usbhid/Makefile
--- linux-libre-2.6.37-gnu1/drivers/hid/usbhid/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hid/usbhid/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -3,15 +3,15 @@
 #
 
 # Multipart objects.
-usbhid-objs	:= hid-core.o hid-quirks.o
+usbhid-y	:= hid-core.o hid-quirks.o
 
 # Optional parts of multipart objects.
 
 ifeq ($(CONFIG_USB_HIDDEV),y)
-	usbhid-objs	+= hiddev.o
+	usbhid-y	+= hiddev.o
 endif
 ifeq ($(CONFIG_HID_PID),y)
-	usbhid-objs	+= hid-pidff.o
+	usbhid-y	+= hid-pidff.o
 endif
 
 obj-$(CONFIG_USB_HID)		+= usbhid.o
diff -druNp linux-libre-2.6.37-gnu1/drivers/hid/usbhid/usbhid.h linux-libre-2.6.38-gnu1/drivers/hid/usbhid/usbhid.h
--- linux-libre-2.6.37-gnu1/drivers/hid/usbhid/usbhid.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hid/usbhid/usbhid.h	2011-03-14 21:20:32.000000000 -0400
@@ -95,7 +95,6 @@ struct usbhid_device {
 	unsigned long stop_retry;                                       /* Time to give up, in jiffies */
 	unsigned int retry_delay;                                       /* Delay length in ms */
 	struct work_struct reset_work;                                  /* Task context for resets */
-	struct work_struct restart_work;				/* waking up for output to be done in a task */
 	wait_queue_head_t wait;						/* For sleeping */
 	int ledcount;							/* counting the number of active leds */
 };
diff -druNp linux-libre-2.6.37-gnu1/drivers/hid/usbhid/usbkbd.c linux-libre-2.6.38-gnu1/drivers/hid/usbhid/usbkbd.c
--- linux-libre-2.6.37-gnu1/drivers/hid/usbhid/usbkbd.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hid/usbhid/usbkbd.c	2011-03-14 21:20:32.000000000 -0400
@@ -24,6 +24,8 @@
  * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/module.h>
@@ -104,16 +106,18 @@ static void usb_kbd_irq(struct urb *urb)
 			if (usb_kbd_keycode[kbd->old[i]])
 				input_report_key(kbd->dev, usb_kbd_keycode[kbd->old[i]], 0);
 			else
-				dev_info(&urb->dev->dev,
-						"Unknown key (scancode %#x) released.\n", kbd->old[i]);
+				hid_info(urb->dev,
+					 "Unknown key (scancode %#x) released.\n",
+					 kbd->old[i]);
 		}
 
 		if (kbd->new[i] > 3 && memscan(kbd->old + 2, kbd->new[i], 6) == kbd->old + 8) {
 			if (usb_kbd_keycode[kbd->new[i]])
 				input_report_key(kbd->dev, usb_kbd_keycode[kbd->new[i]], 1);
 			else
-				dev_info(&urb->dev->dev,
-						"Unknown key (scancode %#x) released.\n", kbd->new[i]);
+				hid_info(urb->dev,
+					 "Unknown key (scancode %#x) released.\n",
+					 kbd->new[i]);
 		}
 	}
 
@@ -124,9 +128,9 @@ static void usb_kbd_irq(struct urb *urb)
 resubmit:
 	i = usb_submit_urb (urb, GFP_ATOMIC);
 	if (i)
-		err_hid ("can't resubmit intr, %s-%s/input0, status %d",
-				kbd->usbdev->bus->bus_name,
-				kbd->usbdev->devpath, i);
+		hid_err(urb->dev, "can't resubmit intr, %s-%s/input0, status %d",
+			kbd->usbdev->bus->bus_name,
+			kbd->usbdev->devpath, i);
 }
 
 static int usb_kbd_event(struct input_dev *dev, unsigned int type,
@@ -150,7 +154,7 @@ static int usb_kbd_event(struct input_de
 	*(kbd->leds) = kbd->newleds;
 	kbd->led->dev = kbd->usbdev;
 	if (usb_submit_urb(kbd->led, GFP_ATOMIC))
-		err_hid("usb_submit_urb(leds) failed");
+		pr_err("usb_submit_urb(leds) failed\n");
 
 	return 0;
 }
@@ -160,7 +164,7 @@ static void usb_kbd_led(struct urb *urb)
 	struct usb_kbd *kbd = urb->context;
 
 	if (urb->status)
-		dev_warn(&urb->dev->dev, "led urb status %d received\n",
+		hid_warn(urb->dev, "led urb status %d received\n",
 			 urb->status);
 
 	if (*(kbd->leds) == kbd->newleds)
@@ -169,7 +173,7 @@ static void usb_kbd_led(struct urb *urb)
 	*(kbd->leds) = kbd->newleds;
 	kbd->led->dev = kbd->usbdev;
 	if (usb_submit_urb(kbd->led, GFP_ATOMIC))
-		err_hid("usb_submit_urb(leds) failed");
+		hid_err(urb->dev, "usb_submit_urb(leds) failed\n");
 }
 
 static int usb_kbd_open(struct input_dev *dev)
diff -druNp linux-libre-2.6.37-gnu1/drivers/hwmon/abituguru3.c linux-libre-2.6.38-gnu1/drivers/hwmon/abituguru3.c
--- linux-libre-2.6.37-gnu1/drivers/hwmon/abituguru3.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hwmon/abituguru3.c	2011-03-14 21:20:32.000000000 -0400
@@ -23,6 +23,9 @@
     chip found on newer Abit uGuru motherboards. Note: because of lack of specs
     only reading the sensors and their settings is supported.
 */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
@@ -608,6 +611,9 @@ static int verbose = 1;
 module_param(verbose, bool, 0644);
 MODULE_PARM_DESC(verbose, "Enable/disable verbose error reporting");
 
+static const char *never_happen = "This should never happen.";
+static const char *report_this =
+	"Please report this to the abituguru3 maintainer (see MAINTAINERS)";
 
 /* wait while the uguru is busy (usually after a write) */
 static int abituguru3_wait_while_busy(struct abituguru3_data *data)
@@ -940,15 +946,13 @@ static int __devinit abituguru3_probe(st
 		if (abituguru3_motherboards[i].id == id)
 			break;
 	if (!abituguru3_motherboards[i].id) {
-		printk(KERN_ERR ABIT_UGURU3_NAME ": error unknown motherboard "
-			"ID: %04X. Please report this to the abituguru3 "
-			"maintainer (see MAINTAINERS)\n", (unsigned int)id);
+		pr_err("error unknown motherboard ID: %04X. %s\n",
+		       (unsigned int)id, report_this);
 		goto abituguru3_probe_error;
 	}
 	data->sensors = abituguru3_motherboards[i].sensors;
 
-	printk(KERN_INFO ABIT_UGURU3_NAME ": found Abit uGuru3, motherboard "
-		"ID: %04X\n", (unsigned int)id);
+	pr_info("found Abit uGuru3, motherboard ID: %04X\n", (unsigned int)id);
 
 	/* Fill the sysfs attr array */
 	sysfs_attr_i = 0;
@@ -957,11 +961,8 @@ static int __devinit abituguru3_probe(st
 	for (i = 0; data->sensors[i].name; i++) {
 		/* Fail safe check, this should never happen! */
 		if (i >= ABIT_UGURU3_MAX_NO_SENSORS) {
-			printk(KERN_ERR ABIT_UGURU3_NAME
-				": Fatal error motherboard has more sensors "
-				"then ABIT_UGURU3_MAX_NO_SENSORS. This should "
-				"never happen please report to the abituguru3 "
-				"maintainer (see MAINTAINERS)\n");
+			pr_err("Fatal error motherboard has more sensors then ABIT_UGURU3_MAX_NO_SENSORS. %s %s\n",
+			       never_happen, report_this);
 			res = -ENAMETOOLONG;
 			goto abituguru3_probe_error;
 		}
@@ -983,10 +984,8 @@ static int __devinit abituguru3_probe(st
 	}
 	/* Fail safe check, this should never happen! */
 	if (sysfs_names_free < 0) {
-		printk(KERN_ERR ABIT_UGURU3_NAME
-			": Fatal error ran out of space for sysfs attr names. "
-			"This should never happen please report to the "
-			"abituguru3 maintainer (see MAINTAINERS)\n");
+		pr_err("Fatal error ran out of space for sysfs attr names. %s %s\n",
+		       never_happen, report_this);
 		res = -ENAMETOOLONG;
 		goto abituguru3_probe_error;
 	}
@@ -1189,8 +1188,7 @@ static int __init abituguru3_detect(void
 		"0x%02X\n", (unsigned int)data_val, (unsigned int)cmd_val);
 
 	if (force) {
-		printk(KERN_INFO ABIT_UGURU3_NAME ": Assuming Abit uGuru3 is "
-				"present because of \"force\" parameter\n");
+		pr_info("Assuming Abit uGuru3 is present because of \"force\" parameter\n");
 		return 0;
 	}
 
@@ -1219,10 +1217,8 @@ static int __init abituguru3_init(void)
 			return err;
 
 #ifdef CONFIG_DMI
-		printk(KERN_WARNING ABIT_UGURU3_NAME ": this motherboard was "
-			"not detected using DMI. Please send the output of "
-			"\"dmidecode\" to the abituguru3 maintainer "
-			"(see MAINTAINERS)\n");
+		pr_warn("this motherboard was not detected using DMI. "
+			"Please send the output of \"dmidecode\" to the abituguru3 maintainer (see MAINTAINERS)\n");
 #endif
 	}
 
@@ -1233,8 +1229,7 @@ static int __init abituguru3_init(void)
 	abituguru3_pdev = platform_device_alloc(ABIT_UGURU3_NAME,
 						ABIT_UGURU3_BASE);
 	if (!abituguru3_pdev) {
-		printk(KERN_ERR ABIT_UGURU3_NAME
-			": Device allocation failed\n");
+		pr_err("Device allocation failed\n");
 		err = -ENOMEM;
 		goto exit_driver_unregister;
 	}
@@ -1245,15 +1240,13 @@ static int __init abituguru3_init(void)
 
 	err = platform_device_add_resources(abituguru3_pdev, &res, 1);
 	if (err) {
-		printk(KERN_ERR ABIT_UGURU3_NAME
-			": Device resource addition failed (%d)\n", err);
+		pr_err("Device resource addition failed (%d)\n", err);
 		goto exit_device_put;
 	}
 
 	err = platform_device_add(abituguru3_pdev);
 	if (err) {
-		printk(KERN_ERR ABIT_UGURU3_NAME
-			": Device addition failed (%d)\n", err);
+		pr_err("Device addition failed (%d)\n", err);
 		goto exit_device_put;
 	}
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/hwmon/abituguru.c linux-libre-2.6.38-gnu1/drivers/hwmon/abituguru.c
--- linux-libre-2.6.37-gnu1/drivers/hwmon/abituguru.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hwmon/abituguru.c	2011-03-14 21:20:32.000000000 -0400
@@ -20,6 +20,9 @@
     the custom Abit uGuru chip found on Abit uGuru motherboards. Note: because
     of lack of specs the CPU/RAM voltage & frequency control is not supported!
 */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/sched.h>
 #include <linux/init.h>
@@ -220,6 +223,10 @@ struct abituguru_data {
 	u8 pwm_settings[ABIT_UGURU_MAX_PWMS][5];
 };
 
+static const char *never_happen = "This should never happen.";
+static const char *report_this =
+	"Please report this to the abituguru maintainer (see MAINTAINERS)";
+
 /* wait till the uguru is in the specified state */
 static int abituguru_wait(struct abituguru_data *data, u8 state)
 {
@@ -438,8 +445,7 @@ abituguru_detect_bank1_sensor_type(struc
 
 	/* Test val is sane / usable for sensor type detection. */
 	if ((val < 10u) || (val > 250u)) {
-		printk(KERN_WARNING ABIT_UGURU_NAME
-			": bank1-sensor: %d reading (%d) too close to limits, "
+		pr_warn("bank1-sensor: %d reading (%d) too close to limits, "
 			"unable to determine sensor type, skipping sensor\n",
 			(int)sensor_addr, (int)val);
 		/* assume no sensor is there for sensors for which we can't
@@ -535,10 +541,8 @@ abituguru_detect_bank1_sensor_type_exit:
 				3) == 3)
 			break;
 	if (i == 3) {
-		printk(KERN_ERR ABIT_UGURU_NAME
-			": Fatal error could not restore original settings. "
-			"This should never happen please report this to the "
-			"abituguru maintainer (see MAINTAINERS)\n");
+		pr_err("Fatal error could not restore original settings. %s %s\n",
+		       never_happen, report_this);
 		return -ENODEV;
 	}
 	return ret;
@@ -1268,14 +1272,12 @@ static int __devinit abituguru_probe(str
 	}
 	/* Fail safe check, this should never happen! */
 	if (sysfs_names_free < 0) {
-		printk(KERN_ERR ABIT_UGURU_NAME ": Fatal error ran out of "
-		       "space for sysfs attr names. This should never "
-		       "happen please report to the abituguru maintainer "
-		       "(see MAINTAINERS)\n");
+		pr_err("Fatal error ran out of space for sysfs attr names. %s %s",
+		       never_happen, report_this);
 		res = -ENAMETOOLONG;
 		goto abituguru_probe_error;
 	}
-	printk(KERN_INFO ABIT_UGURU_NAME ": found Abit uGuru\n");
+	pr_info("found Abit uGuru\n");
 
 	/* Register sysfs hooks */
 	for (i = 0; i < sysfs_attr_i; i++)
@@ -1432,8 +1434,7 @@ static int __init abituguru_detect(void)
 		"0x%02X\n", (unsigned int)data_val, (unsigned int)cmd_val);
 
 	if (force) {
-		printk(KERN_INFO ABIT_UGURU_NAME ": Assuming Abit uGuru is "
-				"present because of \"force\" parameter\n");
+		pr_info("Assuming Abit uGuru is present because of \"force\" parameter\n");
 		return ABIT_UGURU_BASE;
 	}
 
@@ -1467,8 +1468,7 @@ static int __init abituguru_init(void)
 
 	abituguru_pdev = platform_device_alloc(ABIT_UGURU_NAME, address);
 	if (!abituguru_pdev) {
-		printk(KERN_ERR ABIT_UGURU_NAME
-			": Device allocation failed\n");
+		pr_err("Device allocation failed\n");
 		err = -ENOMEM;
 		goto exit_driver_unregister;
 	}
@@ -1479,15 +1479,13 @@ static int __init abituguru_init(void)
 
 	err = platform_device_add_resources(abituguru_pdev, &res, 1);
 	if (err) {
-		printk(KERN_ERR ABIT_UGURU_NAME
-			": Device resource addition failed (%d)\n", err);
+		pr_err("Device resource addition failed (%d)\n", err);
 		goto exit_device_put;
 	}
 
 	err = platform_device_add(abituguru_pdev);
 	if (err) {
-		printk(KERN_ERR ABIT_UGURU_NAME
-			": Device addition failed (%d)\n", err);
+		pr_err("Device addition failed (%d)\n", err);
 		goto exit_device_put;
 	}
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/hwmon/ad7414.c linux-libre-2.6.38-gnu1/drivers/hwmon/ad7414.c
--- linux-libre-2.6.37-gnu1/drivers/hwmon/ad7414.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hwmon/ad7414.c	2011-03-14 21:20:32.000000000 -0400
@@ -242,6 +242,7 @@ static const struct i2c_device_id ad7414
 	{ "ad7414", 0 },
 	{}
 };
+MODULE_DEVICE_TABLE(i2c, ad7414_id);
 
 static struct i2c_driver ad7414_driver = {
 	.driver = {
diff -druNp linux-libre-2.6.37-gnu1/drivers/hwmon/adm9240.c linux-libre-2.6.38-gnu1/drivers/hwmon/adm9240.c
--- linux-libre-2.6.37-gnu1/drivers/hwmon/adm9240.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hwmon/adm9240.c	2011-03-14 21:20:32.000000000 -0400
@@ -20,7 +20,7 @@
  * Alarms	16-bit map of active alarms
  * Analog Out	0..1250 mV output
  *
- * Chassis Intrusion: clear CI latch with 'echo 1 > chassis_clear'
+ * Chassis Intrusion: clear CI latch with 'echo 0 > intrusion0_alarm'
  *
  * Test hardware: Intel SE440BX-2 desktop motherboard --Grant
  *
@@ -476,13 +476,16 @@ static ssize_t set_aout(struct device *d
 static DEVICE_ATTR(aout_output, S_IRUGO | S_IWUSR, show_aout, set_aout);
 
 /* chassis_clear */
-static ssize_t chassis_clear(struct device *dev,
+static ssize_t chassis_clear_legacy(struct device *dev,
 		struct device_attribute *attr,
 		const char *buf, size_t count)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	unsigned long val = simple_strtol(buf, NULL, 10);
 
+	dev_warn(dev, "Attribute chassis_clear is deprecated, "
+		 "use intrusion0_alarm instead\n");
+
 	if (val == 1) {
 		i2c_smbus_write_byte_data(client,
 				ADM9240_REG_CHASSIS_CLEAR, 0x80);
@@ -490,7 +493,29 @@ static ssize_t chassis_clear(struct devi
 	}
 	return count;
 }
-static DEVICE_ATTR(chassis_clear, S_IWUSR, NULL, chassis_clear);
+static DEVICE_ATTR(chassis_clear, S_IWUSR, NULL, chassis_clear_legacy);
+
+static ssize_t chassis_clear(struct device *dev,
+		struct device_attribute *attr,
+		const char *buf, size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct adm9240_data *data = i2c_get_clientdata(client);
+	unsigned long val;
+
+	if (strict_strtoul(buf, 10, &val) || val != 0)
+		return -EINVAL;
+
+	mutex_lock(&data->update_lock);
+	i2c_smbus_write_byte_data(client, ADM9240_REG_CHASSIS_CLEAR, 0x80);
+	data->valid = 0;		/* Force cache refresh */
+	mutex_unlock(&data->update_lock);
+	dev_dbg(&client->dev, "chassis intrusion latch cleared\n");
+
+	return count;
+}
+static SENSOR_DEVICE_ATTR(intrusion0_alarm, S_IRUGO | S_IWUSR, show_alarm,
+		chassis_clear, 12);
 
 static struct attribute *adm9240_attributes[] = {
 	&sensor_dev_attr_in0_input.dev_attr.attr,
@@ -532,6 +557,7 @@ static struct attribute *adm9240_attribu
 	&dev_attr_alarms.attr,
 	&dev_attr_aout_output.attr,
 	&dev_attr_chassis_clear.attr,
+	&sensor_dev_attr_intrusion0_alarm.dev_attr.attr,
 	&dev_attr_cpu0_vid.attr,
 	NULL
 };
diff -druNp linux-libre-2.6.37-gnu1/drivers/hwmon/ads7828.c linux-libre-2.6.38-gnu1/drivers/hwmon/ads7828.c
--- linux-libre-2.6.37-gnu1/drivers/hwmon/ads7828.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hwmon/ads7828.c	2011-03-14 21:20:32.000000000 -0400
@@ -4,7 +4,7 @@
 
 	This driver is based on the lm75 and other lm_sensors/hwmon drivers
 
-	Written by Steve Hardy <steve@linuxrealtime.co.uk>
+	Written by Steve Hardy <shardy@redhat.com>
 
 	Datasheet available at: http://focus.ti.com/lit/ds/symlink/ads7828.pdf
 
@@ -271,7 +271,7 @@ static void __exit sensors_ads7828_exit(
 	i2c_del_driver(&ads7828_driver);
 }
 
-MODULE_AUTHOR("Steve Hardy <steve@linuxrealtime.co.uk>");
+MODULE_AUTHOR("Steve Hardy <shardy@redhat.com>");
 MODULE_DESCRIPTION("ADS7828 driver");
 MODULE_LICENSE("GPL");
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/hwmon/adt7411.c linux-libre-2.6.38-gnu1/drivers/hwmon/adt7411.c
--- linux-libre-2.6.37-gnu1/drivers/hwmon/adt7411.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hwmon/adt7411.c	2011-03-14 21:20:32.000000000 -0400
@@ -334,6 +334,7 @@ static const struct i2c_device_id adt741
 	{ "adt7411", 0 },
 	{ }
 };
+MODULE_DEVICE_TABLE(i2c, adt7411_id);
 
 static struct i2c_driver adt7411_driver = {
 	.driver		= {
diff -druNp linux-libre-2.6.37-gnu1/drivers/hwmon/adt7470.c linux-libre-2.6.38-gnu1/drivers/hwmon/adt7470.c
--- linux-libre-2.6.37-gnu1/drivers/hwmon/adt7470.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hwmon/adt7470.c	2011-03-14 21:20:32.000000000 -0400
@@ -19,6 +19,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/jiffies.h>
 #include <linux/i2c.h>
@@ -274,7 +276,7 @@ static int adt7470_read_temperatures(str
 	i2c_smbus_write_byte_data(client, ADT7470_REG_PWM_CFG(2), pwm_cfg[1]);
 
 	if (res) {
-		printk(KERN_ERR "ha ha, interrupted");
+		pr_err("ha ha, interrupted\n");
 		return -EAGAIN;
 	}
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/hwmon/applesmc.c linux-libre-2.6.38-gnu1/drivers/hwmon/applesmc.c
--- linux-libre-2.6.37-gnu1/drivers/hwmon/applesmc.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hwmon/applesmc.c	2011-03-14 21:20:32.000000000 -0400
@@ -4,6 +4,7 @@
  * computers.
  *
  * Copyright (C) 2007 Nicolas Boichat <nicolas@boichat.ch>
+ * Copyright (C) 2010 Henrik Rydberg <rydberg@euromail.se>
  *
  * Based on hdaps.c driver:
  * Copyright (C) 2005 Robert Love <rml@novell.com>
@@ -26,10 +27,13 @@
  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/delay.h>
 #include <linux/platform_device.h>
 #include <linux/input-polldev.h>
 #include <linux/kernel.h>
+#include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/timer.h>
 #include <linux/dmi.h>
@@ -49,6 +53,7 @@
 
 #define APPLESMC_MAX_DATA_LENGTH 32
 
+/* wait up to 32 ms for a status change. */
 #define APPLESMC_MIN_WAIT	0x0040
 #define APPLESMC_MAX_WAIT	0x8000
 
@@ -73,104 +78,15 @@
 
 #define FANS_COUNT		"FNum" /* r-o ui8 */
 #define FANS_MANUAL		"FS! " /* r-w ui16 */
-#define FAN_ACTUAL_SPEED	"F0Ac" /* r-o fpe2 (2 bytes) */
-#define FAN_MIN_SPEED		"F0Mn" /* r-o fpe2 (2 bytes) */
-#define FAN_MAX_SPEED		"F0Mx" /* r-o fpe2 (2 bytes) */
-#define FAN_SAFE_SPEED		"F0Sf" /* r-o fpe2 (2 bytes) */
-#define FAN_TARGET_SPEED	"F0Tg" /* r-w fpe2 (2 bytes) */
-#define FAN_POSITION		"F0ID" /* r-o char[16] */
-
-/*
- * Temperature sensors keys (sp78 - 2 bytes).
- */
-static const char *temperature_sensors_sets[][41] = {
-/* Set 0: Macbook Pro */
-	{ "TA0P", "TB0T", "TC0D", "TC0P", "TG0H", "TG0P", "TG0T", "Th0H",
-	  "Th1H", "Tm0P", "Ts0P", "Ts1P", NULL },
-/* Set 1: Macbook2 set */
-	{ "TB0T", "TC0D", "TC0P", "TM0P", "TN0P", "TN1P", "TTF0", "Th0H",
-	  "Th0S", "Th1H", NULL },
-/* Set 2: Macbook set */
-	{ "TB0T", "TC0D", "TC0P", "TM0P", "TN0P", "TN1P", "Th0H", "Th0S",
-	  "Th1H", "Ts0P", NULL },
-/* Set 3: Macmini set */
-	{ "TC0D", "TC0P", NULL },
-/* Set 4: Mac Pro (2 x Quad-Core) */
-	{ "TA0P", "TCAG", "TCAH", "TCBG", "TCBH", "TC0C", "TC0D", "TC0P",
-	  "TC1C", "TC1D", "TC2C", "TC2D", "TC3C", "TC3D", "THTG", "TH0P",
-	  "TH1P", "TH2P", "TH3P", "TMAP", "TMAS", "TMBS", "TM0P", "TM0S",
-	  "TM1P", "TM1S", "TM2P", "TM2S", "TM3S", "TM8P", "TM8S", "TM9P",
-	  "TM9S", "TN0H", "TS0C", NULL },
-/* Set 5: iMac */
-	{ "TC0D", "TA0P", "TG0P", "TG0D", "TG0H", "TH0P", "Tm0P", "TO0P",
-	  "Tp0C", NULL },
-/* Set 6: Macbook3 set */
-	{ "TB0T", "TC0D", "TC0P", "TM0P", "TN0P", "TTF0", "TW0P", "Th0H",
-	  "Th0S", "Th1H", NULL },
-/* Set 7: Macbook Air */
-	{ "TB0T", "TB1S", "TB1T", "TB2S", "TB2T", "TC0D", "TC0P", "TCFP",
-	  "TTF0", "TW0P", "Th0H", "Tp0P", "TpFP", "Ts0P", "Ts0S", NULL },
-/* Set 8: Macbook Pro 4,1 (Penryn) */
-	{ "TB0T", "TC0D", "TC0P", "TG0D", "TG0H", "TTF0", "TW0P", "Th0H",
-	  "Th1H", "Th2H", "Tm0P", "Ts0P", NULL },
-/* Set 9: Macbook Pro 3,1 (Santa Rosa) */
-	{ "TALP", "TB0T", "TC0D", "TC0P", "TG0D", "TG0H", "TTF0", "TW0P",
-	  "Th0H", "Th1H", "Th2H", "Tm0P", "Ts0P", NULL },
-/* Set 10: iMac 5,1 */
-	{ "TA0P", "TC0D", "TC0P", "TG0D", "TH0P", "TO0P", "Tm0P", NULL },
-/* Set 11: Macbook 5,1 */
-	{ "TB0T", "TB1T", "TB2T", "TB3T", "TC0D", "TC0P", "TN0D", "TN0P",
-	  "TTF0", "Th0H", "Th1H", "ThFH", "Ts0P", "Ts0S", NULL },
-/* Set 12: Macbook Pro 5,1 */
-	{ "TB0T", "TB1T", "TB2T", "TB3T", "TC0D", "TC0F", "TC0P", "TG0D",
-	  "TG0F", "TG0H", "TG0P", "TG0T", "TG1H", "TN0D", "TN0P", "TTF0",
-	  "Th2H", "Tm0P", "Ts0P", "Ts0S", NULL },
-/* Set 13: iMac 8,1 */
-	{ "TA0P", "TC0D", "TC0H", "TC0P", "TG0D", "TG0H", "TG0P", "TH0P",
-	  "TL0P", "TO0P", "TW0P", "Tm0P", "Tp0P", NULL },
-/* Set 14: iMac 6,1 */
-	{ "TA0P", "TC0D", "TC0H", "TC0P", "TG0D", "TG0H", "TG0P", "TH0P",
-	  "TO0P", "Tp0P", NULL },
-/* Set 15: MacBook Air 2,1 */
-	{ "TB0T", "TB1S", "TB1T", "TB2S", "TB2T", "TC0D", "TN0D", "TTF0",
-	  "TV0P", "TVFP", "TW0P", "Th0P", "Tp0P", "Tp1P", "TpFP", "Ts0P",
-	  "Ts0S", NULL },
-/* Set 16: Mac Pro 3,1 (2 x Quad-Core) */
-	{ "TA0P", "TCAG", "TCAH", "TCBG", "TCBH", "TC0C", "TC0D", "TC0P",
-	  "TC1C", "TC1D", "TC2C", "TC2D", "TC3C", "TC3D", "TH0P", "TH1P",
-	  "TH2P", "TH3P", "TMAP", "TMAS", "TMBS", "TM0P", "TM0S", "TM1P",
-	  "TM1S", "TM2P", "TM2S", "TM3S", "TM8P", "TM8S", "TM9P", "TM9S",
-	  "TN0C", "TN0D", "TN0H", "TS0C", "Tp0C", "Tp1C", "Tv0S", "Tv1S",
-	  NULL },
-/* Set 17: iMac 9,1 */
-	{ "TA0P", "TC0D", "TC0H", "TC0P", "TG0D", "TG0H", "TH0P", "TL0P",
-	  "TN0D", "TN0H", "TN0P", "TO0P", "Tm0P", "Tp0P", NULL },
-/* Set 18: MacBook Pro 2,2 */
-	{ "TB0T", "TC0D", "TC0P", "TG0H", "TG0P", "TG0T", "TM0P", "TTF0",
-	  "Th0H", "Th1H", "Tm0P", "Ts0P", NULL },
-/* Set 19: Macbook Pro 5,3 */
-	{ "TB0T", "TB1T", "TB2T", "TB3T", "TC0D", "TC0F", "TC0P", "TG0D",
-	  "TG0F", "TG0H", "TG0P", "TG0T", "TN0D", "TN0P", "TTF0", "Th2H",
-	  "Tm0P", "Ts0P", "Ts0S", NULL },
-/* Set 20: MacBook Pro 5,4 */
-	{ "TB0T", "TB1T", "TB2T", "TB3T", "TC0D", "TC0F", "TC0P", "TN0D",
-	  "TN0P", "TTF0", "Th2H", "Ts0P", "Ts0S", NULL },
-/* Set 21: MacBook Pro 6,2 */
-	{ "TB0T", "TB1T", "TB2T", "TC0C", "TC0D", "TC0P", "TC1C", "TG0D",
-	  "TG0P", "TG0T", "TMCD", "TP0P", "TPCD", "Th1H", "Th2H", "Tm0P",
-	  "Ts0P", "Ts0S", NULL },
-/* Set 22: MacBook Pro 7,1 */
-	{ "TB0T", "TB1T", "TB2T", "TC0D", "TC0P", "TN0D", "TN0P", "TN0S",
-	  "TN1D", "TN1F", "TN1G", "TN1S", "Th1H", "Ts0P", "Ts0S", NULL },
-};
+#define FAN_ID_FMT		"F%dID" /* r-o char[16] */
 
 /* List of keys used to read/write fan speeds */
-static const char* fan_speed_keys[] = {
-	FAN_ACTUAL_SPEED,
-	FAN_MIN_SPEED,
-	FAN_MAX_SPEED,
-	FAN_SAFE_SPEED,
-	FAN_TARGET_SPEED
+static const char *const fan_speed_fmt[] = {
+	"F%dAc",		/* actual speed */
+	"F%dMn",		/* minimum speed (rw) */
+	"F%dMx",		/* maximum speed */
+	"F%dSf",		/* safe speed - not all models */
+	"F%dTg",		/* target speed (manual: rw) */
 };
 
 #define INIT_TIMEOUT_MSECS	5000	/* wait up to 5s for device init ... */
@@ -184,14 +100,48 @@ static const char* fan_speed_keys[] = {
 #define SENSOR_Y 1
 #define SENSOR_Z 2
 
-/* Structure to be passed to DMI_MATCH function */
-struct dmi_match_data {
-/* Indicates whether this computer has an accelerometer. */
-	int accelerometer;
-/* Indicates whether this computer has light sensors and keyboard backlight. */
-	int light;
-/* Indicates which temperature sensors set to use. */
-	int temperature_set;
+#define to_index(attr) (to_sensor_dev_attr(attr)->index & 0xffff)
+#define to_option(attr) (to_sensor_dev_attr(attr)->index >> 16)
+
+/* Dynamic device node attributes */
+struct applesmc_dev_attr {
+	struct sensor_device_attribute sda;	/* hwmon attributes */
+	char name[32];				/* room for node file name */
+};
+
+/* Dynamic device node group */
+struct applesmc_node_group {
+	char *format;				/* format string */
+	void *show;				/* show function */
+	void *store;				/* store function */
+	int option;				/* function argument */
+	struct applesmc_dev_attr *nodes;	/* dynamic node array */
+};
+
+/* AppleSMC entry - cached register information */
+struct applesmc_entry {
+	char key[5];		/* four-letter key code */
+	u8 valid;		/* set when entry is successfully read once */
+	u8 len;			/* bounded by APPLESMC_MAX_DATA_LENGTH */
+	char type[5];		/* four-letter type code */
+	u8 flags;		/* 0x10: func; 0x40: write; 0x80: read */
+};
+
+/* Register lookup and registers common to all SMCs */
+static struct applesmc_registers {
+	struct mutex mutex;		/* register read/write mutex */
+	unsigned int key_count;		/* number of SMC registers */
+	unsigned int fan_count;		/* number of fans */
+	unsigned int temp_count;	/* number of temperature registers */
+	unsigned int temp_begin;	/* temperature lower index bound */
+	unsigned int temp_end;		/* temperature upper index bound */
+	int num_light_sensors;		/* number of light sensors */
+	bool has_accelerometer;		/* has motion sensor */
+	bool has_key_backlight;		/* has keyboard backlight */
+	bool init_complete;		/* true when fully initialized */
+	struct applesmc_entry *cache;	/* cached key entries */
+} smcreg = {
+	.mutex = __MUTEX_INITIALIZER(smcreg.mutex),
 };
 
 static const int debug;
@@ -203,20 +153,6 @@ static u8 backlight_state[2];
 static struct device *hwmon_dev;
 static struct input_polled_dev *applesmc_idev;
 
-/* Indicates whether this computer has an accelerometer. */
-static unsigned int applesmc_accelerometer;
-
-/* Indicates whether this computer has light sensors and keyboard backlight. */
-static unsigned int applesmc_light;
-
-/* The number of fans handled by the driver */
-static unsigned int fans_handled;
-
-/* Indicates which temperature sensors set to use. */
-static unsigned int applesmc_temperature_set;
-
-static DEFINE_MUTEX(applesmc_lock);
-
 /*
  * Last index written to key_at_index sysfs file, and value to use for all other
  * key_at_index_* sysfs files.
@@ -238,18 +174,10 @@ static int __wait_status(u8 val)
 
 	for (us = APPLESMC_MIN_WAIT; us < APPLESMC_MAX_WAIT; us <<= 1) {
 		udelay(us);
-		if ((inb(APPLESMC_CMD_PORT) & APPLESMC_STATUS_MASK) == val) {
-			if (debug)
-				printk(KERN_DEBUG
-					"Waited %d us for status %x\n",
-					2 * us - APPLESMC_MIN_WAIT, val);
+		if ((inb(APPLESMC_CMD_PORT) & APPLESMC_STATUS_MASK) == val)
 			return 0;
-		}
 	}
 
-	printk(KERN_WARNING "applesmc: wait status failed: %x != %x\n",
-						val, inb(APPLESMC_CMD_PORT));
-
 	return -EIO;
 }
 
@@ -267,159 +195,242 @@ static int send_command(u8 cmd)
 		if ((inb(APPLESMC_CMD_PORT) & APPLESMC_STATUS_MASK) == 0x0c)
 			return 0;
 	}
-	printk(KERN_WARNING "applesmc: command failed: %x -> %x\n",
-		cmd, inb(APPLESMC_CMD_PORT));
 	return -EIO;
 }
 
-/*
- * applesmc_read_key - reads len bytes from a given key, and put them in buffer.
- * Returns zero on success or a negative error on failure. Callers must
- * hold applesmc_lock.
- */
-static int applesmc_read_key(const char* key, u8* buffer, u8 len)
+static int send_argument(const char *key)
 {
 	int i;
 
-	if (len > APPLESMC_MAX_DATA_LENGTH) {
-		printk(KERN_ERR	"applesmc_read_key: cannot read more than "
-					"%d bytes\n", APPLESMC_MAX_DATA_LENGTH);
-		return -EINVAL;
-	}
-
-	if (send_command(APPLESMC_READ_CMD))
-		return -EIO;
-
 	for (i = 0; i < 4; i++) {
 		outb(key[i], APPLESMC_DATA_PORT);
 		if (__wait_status(0x04))
 			return -EIO;
 	}
-	if (debug)
-		printk(KERN_DEBUG "<%s", key);
+	return 0;
+}
+
+static int read_smc(u8 cmd, const char *key, u8 *buffer, u8 len)
+{
+	int i;
+
+	if (send_command(cmd) || send_argument(key)) {
+		pr_warn("%s: read arg fail\n", key);
+		return -EIO;
+	}
 
 	outb(len, APPLESMC_DATA_PORT);
-	if (debug)
-		printk(KERN_DEBUG ">%x", len);
 
 	for (i = 0; i < len; i++) {
-		if (__wait_status(0x05))
+		if (__wait_status(0x05)) {
+			pr_warn("%s: read data fail\n", key);
 			return -EIO;
+		}
 		buffer[i] = inb(APPLESMC_DATA_PORT);
-		if (debug)
-			printk(KERN_DEBUG "<%x", buffer[i]);
 	}
-	if (debug)
-		printk(KERN_DEBUG "\n");
 
 	return 0;
 }
 
-/*
- * applesmc_write_key - writes len bytes from buffer to a given key.
- * Returns zero on success or a negative error on failure. Callers must
- * hold applesmc_lock.
- */
-static int applesmc_write_key(const char* key, u8* buffer, u8 len)
+static int write_smc(u8 cmd, const char *key, const u8 *buffer, u8 len)
 {
 	int i;
 
-	if (len > APPLESMC_MAX_DATA_LENGTH) {
-		printk(KERN_ERR	"applesmc_write_key: cannot write more than "
-					"%d bytes\n", APPLESMC_MAX_DATA_LENGTH);
-		return -EINVAL;
-	}
-
-	if (send_command(APPLESMC_WRITE_CMD))
+	if (send_command(cmd) || send_argument(key)) {
+		pr_warn("%s: write arg fail\n", key);
 		return -EIO;
-
-	for (i = 0; i < 4; i++) {
-		outb(key[i], APPLESMC_DATA_PORT);
-		if (__wait_status(0x04))
-			return -EIO;
 	}
 
 	outb(len, APPLESMC_DATA_PORT);
 
 	for (i = 0; i < len; i++) {
-		if (__wait_status(0x04))
+		if (__wait_status(0x04)) {
+			pr_warn("%s: write data fail\n", key);
 			return -EIO;
+		}
 		outb(buffer[i], APPLESMC_DATA_PORT);
 	}
 
 	return 0;
 }
 
+static int read_register_count(unsigned int *count)
+{
+	__be32 be;
+	int ret;
+
+	ret = read_smc(APPLESMC_READ_CMD, KEY_COUNT_KEY, (u8 *)&be, 4);
+	if (ret)
+		return ret;
+
+	*count = be32_to_cpu(be);
+	return 0;
+}
+
 /*
- * applesmc_get_key_at_index - get key at index, and put the result in key
- * (char[6]). Returns zero on success or a negative error on failure. Callers
- * must hold applesmc_lock.
+ * Serialized I/O
+ *
+ * Returns zero on success or a negative error on failure.
+ * All functions below are concurrency safe - callers should NOT hold lock.
  */
-static int applesmc_get_key_at_index(int index, char* key)
+
+static int applesmc_read_entry(const struct applesmc_entry *entry,
+			       u8 *buf, u8 len)
 {
-	int i;
-	u8 readkey[4];
-	readkey[0] = index >> 24;
-	readkey[1] = index >> 16;
-	readkey[2] = index >> 8;
-	readkey[3] = index;
+	int ret;
 
-	if (send_command(APPLESMC_GET_KEY_BY_INDEX_CMD))
-		return -EIO;
+	if (entry->len != len)
+		return -EINVAL;
+	mutex_lock(&smcreg.mutex);
+	ret = read_smc(APPLESMC_READ_CMD, entry->key, buf, len);
+	mutex_unlock(&smcreg.mutex);
 
-	for (i = 0; i < 4; i++) {
-		outb(readkey[i], APPLESMC_DATA_PORT);
-		if (__wait_status(0x04))
-			return -EIO;
+	return ret;
+}
+
+static int applesmc_write_entry(const struct applesmc_entry *entry,
+				const u8 *buf, u8 len)
+{
+	int ret;
+
+	if (entry->len != len)
+		return -EINVAL;
+	mutex_lock(&smcreg.mutex);
+	ret = write_smc(APPLESMC_WRITE_CMD, entry->key, buf, len);
+	mutex_unlock(&smcreg.mutex);
+	return ret;
+}
+
+static const struct applesmc_entry *applesmc_get_entry_by_index(int index)
+{
+	struct applesmc_entry *cache = &smcreg.cache[index];
+	u8 key[4], info[6];
+	__be32 be;
+	int ret = 0;
+
+	if (cache->valid)
+		return cache;
+
+	mutex_lock(&smcreg.mutex);
+
+	if (cache->valid)
+		goto out;
+	be = cpu_to_be32(index);
+	ret = read_smc(APPLESMC_GET_KEY_BY_INDEX_CMD, (u8 *)&be, key, 4);
+	if (ret)
+		goto out;
+	ret = read_smc(APPLESMC_GET_KEY_TYPE_CMD, key, info, 6);
+	if (ret)
+		goto out;
+
+	memcpy(cache->key, key, 4);
+	cache->len = info[0];
+	memcpy(cache->type, &info[1], 4);
+	cache->flags = info[5];
+	cache->valid = 1;
+
+out:
+	mutex_unlock(&smcreg.mutex);
+	if (ret)
+		return ERR_PTR(ret);
+	return cache;
+}
+
+static int applesmc_get_lower_bound(unsigned int *lo, const char *key)
+{
+	int begin = 0, end = smcreg.key_count;
+	const struct applesmc_entry *entry;
+
+	while (begin != end) {
+		int middle = begin + (end - begin) / 2;
+		entry = applesmc_get_entry_by_index(middle);
+		if (IS_ERR(entry))
+			return PTR_ERR(entry);
+		if (strcmp(entry->key, key) < 0)
+			begin = middle + 1;
+		else
+			end = middle;
 	}
 
-	outb(4, APPLESMC_DATA_PORT);
+	*lo = begin;
+	return 0;
+}
 
-	for (i = 0; i < 4; i++) {
-		if (__wait_status(0x05))
-			return -EIO;
-		key[i] = inb(APPLESMC_DATA_PORT);
+static int applesmc_get_upper_bound(unsigned int *hi, const char *key)
+{
+	int begin = 0, end = smcreg.key_count;
+	const struct applesmc_entry *entry;
+
+	while (begin != end) {
+		int middle = begin + (end - begin) / 2;
+		entry = applesmc_get_entry_by_index(middle);
+		if (IS_ERR(entry))
+			return PTR_ERR(entry);
+		if (strcmp(key, entry->key) < 0)
+			end = middle;
+		else
+			begin = middle + 1;
 	}
-	key[4] = 0;
 
+	*hi = begin;
 	return 0;
 }
 
-/*
- * applesmc_get_key_type - get key type, and put the result in type (char[6]).
- * Returns zero on success or a negative error on failure. Callers must
- * hold applesmc_lock.
- */
-static int applesmc_get_key_type(char* key, char* type)
+static const struct applesmc_entry *applesmc_get_entry_by_key(const char *key)
 {
-	int i;
+	int begin, end;
+	int ret;
 
-	if (send_command(APPLESMC_GET_KEY_TYPE_CMD))
-		return -EIO;
+	ret = applesmc_get_lower_bound(&begin, key);
+	if (ret)
+		return ERR_PTR(ret);
+	ret = applesmc_get_upper_bound(&end, key);
+	if (ret)
+		return ERR_PTR(ret);
+	if (end - begin != 1)
+		return ERR_PTR(-EINVAL);
 
-	for (i = 0; i < 4; i++) {
-		outb(key[i], APPLESMC_DATA_PORT);
-		if (__wait_status(0x04))
-			return -EIO;
-	}
+	return applesmc_get_entry_by_index(begin);
+}
 
-	outb(6, APPLESMC_DATA_PORT);
+static int applesmc_read_key(const char *key, u8 *buffer, u8 len)
+{
+	const struct applesmc_entry *entry;
 
-	for (i = 0; i < 6; i++) {
-		if (__wait_status(0x05))
-			return -EIO;
-		type[i] = inb(APPLESMC_DATA_PORT);
-	}
-	type[5] = 0;
+	entry = applesmc_get_entry_by_key(key);
+	if (IS_ERR(entry))
+		return PTR_ERR(entry);
+
+	return applesmc_read_entry(entry, buffer, len);
+}
 
+static int applesmc_write_key(const char *key, const u8 *buffer, u8 len)
+{
+	const struct applesmc_entry *entry;
+
+	entry = applesmc_get_entry_by_key(key);
+	if (IS_ERR(entry))
+		return PTR_ERR(entry);
+
+	return applesmc_write_entry(entry, buffer, len);
+}
+
+static int applesmc_has_key(const char *key, bool *value)
+{
+	const struct applesmc_entry *entry;
+
+	entry = applesmc_get_entry_by_key(key);
+	if (IS_ERR(entry) && PTR_ERR(entry) != -EINVAL)
+		return PTR_ERR(entry);
+
+	*value = !IS_ERR(entry);
 	return 0;
 }
 
 /*
- * applesmc_read_motion_sensor - Read motion sensor (X, Y or Z). Callers must
- * hold applesmc_lock.
+ * applesmc_read_motion_sensor - Read motion sensor (X, Y or Z).
  */
-static int applesmc_read_motion_sensor(int index, s16* value)
+static int applesmc_read_motion_sensor(int index, s16 *value)
 {
 	u8 buffer[2];
 	int ret;
@@ -444,69 +455,120 @@ static int applesmc_read_motion_sensor(i
 }
 
 /*
- * applesmc_device_init - initialize the accelerometer.  Returns zero on success
- * and negative error code on failure.  Can sleep.
+ * applesmc_device_init - initialize the accelerometer.  Can sleep.
  */
-static int applesmc_device_init(void)
+static void applesmc_device_init(void)
 {
-	int total, ret = -ENXIO;
+	int total;
 	u8 buffer[2];
 
-	if (!applesmc_accelerometer)
-		return 0;
-
-	mutex_lock(&applesmc_lock);
+	if (!smcreg.has_accelerometer)
+		return;
 
 	for (total = INIT_TIMEOUT_MSECS; total > 0; total -= INIT_WAIT_MSECS) {
-		if (debug)
-			printk(KERN_DEBUG "applesmc try %d\n", total);
 		if (!applesmc_read_key(MOTION_SENSOR_KEY, buffer, 2) &&
-				(buffer[0] != 0x00 || buffer[1] != 0x00)) {
-			if (total == INIT_TIMEOUT_MSECS) {
-				printk(KERN_DEBUG "applesmc: device has"
-						" already been initialized"
-						" (0x%02x, 0x%02x).\n",
-						buffer[0], buffer[1]);
-			} else {
-				printk(KERN_DEBUG "applesmc: device"
-						" successfully initialized"
-						" (0x%02x, 0x%02x).\n",
-						buffer[0], buffer[1]);
-			}
-			ret = 0;
-			goto out;
-		}
+				(buffer[0] != 0x00 || buffer[1] != 0x00))
+			return;
 		buffer[0] = 0xe0;
 		buffer[1] = 0x00;
 		applesmc_write_key(MOTION_SENSOR_KEY, buffer, 2);
 		msleep(INIT_WAIT_MSECS);
 	}
 
-	printk(KERN_WARNING "applesmc: failed to init the device\n");
-
-out:
-	mutex_unlock(&applesmc_lock);
-	return ret;
+	pr_warn("failed to init the device\n");
 }
 
 /*
- * applesmc_get_fan_count - get the number of fans. Callers must NOT hold
- * applesmc_lock.
+ * applesmc_init_smcreg_try - Try to initialize register cache. Idempotent.
  */
-static int applesmc_get_fan_count(void)
+static int applesmc_init_smcreg_try(void)
 {
+	struct applesmc_registers *s = &smcreg;
+	bool left_light_sensor, right_light_sensor;
+	u8 tmp[1];
 	int ret;
-	u8 buffer[1];
 
-	mutex_lock(&applesmc_lock);
+	if (s->init_complete)
+		return 0;
 
-	ret = applesmc_read_key(FANS_COUNT, buffer, 1);
+	ret = read_register_count(&s->key_count);
+	if (ret)
+		return ret;
 
-	mutex_unlock(&applesmc_lock);
+	if (!s->cache)
+		s->cache = kcalloc(s->key_count, sizeof(*s->cache), GFP_KERNEL);
+	if (!s->cache)
+		return -ENOMEM;
+
+	ret = applesmc_read_key(FANS_COUNT, tmp, 1);
 	if (ret)
 		return ret;
-	else
-		return buffer[0];
+	s->fan_count = tmp[0];
+
+	ret = applesmc_get_lower_bound(&s->temp_begin, "T");
+	if (ret)
+		return ret;
+	ret = applesmc_get_lower_bound(&s->temp_end, "U");
+	if (ret)
+		return ret;
+	s->temp_count = s->temp_end - s->temp_begin;
+
+	ret = applesmc_has_key(LIGHT_SENSOR_LEFT_KEY, &left_light_sensor);
+	if (ret)
+		return ret;
+	ret = applesmc_has_key(LIGHT_SENSOR_RIGHT_KEY, &right_light_sensor);
+	if (ret)
+		return ret;
+	ret = applesmc_has_key(MOTION_SENSOR_KEY, &s->has_accelerometer);
+	if (ret)
+		return ret;
+	ret = applesmc_has_key(BACKLIGHT_KEY, &s->has_key_backlight);
+	if (ret)
+		return ret;
+
+	s->num_light_sensors = left_light_sensor + right_light_sensor;
+	s->init_complete = true;
+
+	pr_info("key=%d fan=%d temp=%d acc=%d lux=%d kbd=%d\n",
+	       s->key_count, s->fan_count, s->temp_count,
+	       s->has_accelerometer,
+	       s->num_light_sensors,
+	       s->has_key_backlight);
+
+	return 0;
+}
+
+/*
+ * applesmc_init_smcreg - Initialize register cache.
+ *
+ * Retries until initialization is successful, or the operation times out.
+ *
+ */
+static int applesmc_init_smcreg(void)
+{
+	int ms, ret;
+
+	for (ms = 0; ms < INIT_TIMEOUT_MSECS; ms += INIT_WAIT_MSECS) {
+		ret = applesmc_init_smcreg_try();
+		if (!ret) {
+			if (ms)
+				pr_info("init_smcreg() took %d ms\n", ms);
+			return 0;
+		}
+		msleep(INIT_WAIT_MSECS);
+	}
+
+	kfree(smcreg.cache);
+	smcreg.cache = NULL;
+
+	return ret;
+}
+
+static void applesmc_destroy_smcreg(void)
+{
+	kfree(smcreg.cache);
+	smcreg.cache = NULL;
+	smcreg.init_complete = false;
 }
 
 /* Device model stuff */
@@ -514,30 +576,27 @@ static int applesmc_probe(struct platfor
 {
 	int ret;
 
-	ret = applesmc_device_init();
+	ret = applesmc_init_smcreg();
 	if (ret)
 		return ret;
 
-	printk(KERN_INFO "applesmc: device successfully initialized.\n");
+	applesmc_device_init();
+
 	return 0;
 }
 
 /* Synchronize device with memorized backlight state */
 static int applesmc_pm_resume(struct device *dev)
 {
-	mutex_lock(&applesmc_lock);
-	if (applesmc_light)
+	if (smcreg.has_key_backlight)
 		applesmc_write_key(BACKLIGHT_KEY, backlight_state, 2);
-	mutex_unlock(&applesmc_lock);
 	return 0;
 }
 
 /* Reinitialize device on resume from hibernation */
 static int applesmc_pm_restore(struct device *dev)
 {
-	int ret = applesmc_device_init();
-	if (ret)
-		return ret;
+	applesmc_device_init();
 	return applesmc_pm_resume(dev);
 }
 
@@ -571,20 +630,15 @@ static void applesmc_idev_poll(struct in
 	struct input_dev *idev = dev->input;
 	s16 x, y;
 
-	mutex_lock(&applesmc_lock);
-
 	if (applesmc_read_motion_sensor(SENSOR_X, &x))
-		goto out;
+		return;
 	if (applesmc_read_motion_sensor(SENSOR_Y, &y))
-		goto out;
+		return;
 
 	x = -x;
 	input_report_abs(idev, ABS_X, x - rest_x);
 	input_report_abs(idev, ABS_Y, y - rest_y);
 	input_sync(idev);
-
-out:
-	mutex_unlock(&applesmc_lock);
 }
 
 /* Sysfs Files */
@@ -601,8 +655,6 @@ static ssize_t applesmc_position_show(st
 	int ret;
 	s16 x, y, z;
 
-	mutex_lock(&applesmc_lock);
-
 	ret = applesmc_read_motion_sensor(SENSOR_X, &x);
 	if (ret)
 		goto out;
@@ -614,7 +666,6 @@ static ssize_t applesmc_position_show(st
 		goto out;
 
 out:
-	mutex_unlock(&applesmc_lock);
 	if (ret)
 		return ret;
 	else
@@ -624,20 +675,20 @@ out:
 static ssize_t applesmc_light_show(struct device *dev,
 				struct device_attribute *attr, char *sysfsbuf)
 {
+	const struct applesmc_entry *entry;
 	static int data_length;
 	int ret;
 	u8 left = 0, right = 0;
-	u8 buffer[10], query[6];
-
-	mutex_lock(&applesmc_lock);
+	u8 buffer[10];
 
 	if (!data_length) {
-		ret = applesmc_get_key_type(LIGHT_SENSOR_LEFT_KEY, query);
-		if (ret)
-			goto out;
-		data_length = clamp_val(query[0], 0, 10);
-		printk(KERN_INFO "applesmc: light sensor data length set to "
-			"%d\n", data_length);
+		entry = applesmc_get_entry_by_key(LIGHT_SENSOR_LEFT_KEY);
+		if (IS_ERR(entry))
+			return PTR_ERR(entry);
+		if (entry->len > 10)
+			return -ENXIO;
+		data_length = entry->len;
+		pr_info("light sensor data length set to %d\n", data_length);
 	}
 
 	ret = applesmc_read_key(LIGHT_SENSOR_LEFT_KEY, buffer, data_length);
@@ -653,7 +704,6 @@ static ssize_t applesmc_light_show(struc
 	right = buffer[2];
 
 out:
-	mutex_unlock(&applesmc_lock);
 	if (ret)
 		return ret;
 	else
@@ -664,36 +714,44 @@ out:
 static ssize_t applesmc_show_sensor_label(struct device *dev,
 			struct device_attribute *devattr, char *sysfsbuf)
 {
-	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-	const char *key =
-		temperature_sensors_sets[applesmc_temperature_set][attr->index];
+	int index = smcreg.temp_begin + to_index(devattr);
+	const struct applesmc_entry *entry;
 
-	return snprintf(sysfsbuf, PAGE_SIZE, "%s\n", key);
+	entry = applesmc_get_entry_by_index(index);
+	if (IS_ERR(entry))
+		return PTR_ERR(entry);
+
+	return snprintf(sysfsbuf, PAGE_SIZE, "%s\n", entry->key);
 }
 
 /* Displays degree Celsius * 1000 */
 static ssize_t applesmc_show_temperature(struct device *dev,
 			struct device_attribute *devattr, char *sysfsbuf)
 {
+	int index = smcreg.temp_begin + to_index(devattr);
+	const struct applesmc_entry *entry;
 	int ret;
 	u8 buffer[2];
 	unsigned int temp;
-	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-	const char* key =
-		temperature_sensors_sets[applesmc_temperature_set][attr->index];
-
-	mutex_lock(&applesmc_lock);
 
-	ret = applesmc_read_key(key, buffer, 2);
-	temp = buffer[0]*1000;
-	temp += (buffer[1] >> 6) * 250;
-
-	mutex_unlock(&applesmc_lock);
+	entry = applesmc_get_entry_by_index(index);
+	if (IS_ERR(entry))
+		return PTR_ERR(entry);
+	if (entry->len > 2)
+		return -EINVAL;
 
+	ret = applesmc_read_entry(entry, buffer, entry->len);
 	if (ret)
 		return ret;
-	else
-		return snprintf(sysfsbuf, PAGE_SIZE, "%u\n", temp);
+
+	if (entry->len == 2) {
+		temp = buffer[0] * 1000;
+		temp += (buffer[1] >> 6) * 250;
+	} else {
+		temp = buffer[0] * 4000;
+	}
+
+	return snprintf(sysfsbuf, PAGE_SIZE, "%u\n", temp);
 }
 
 static ssize_t applesmc_show_fan_speed(struct device *dev,
@@ -703,21 +761,12 @@ static ssize_t applesmc_show_fan_speed(s
 	unsigned int speed = 0;
 	char newkey[5];
 	u8 buffer[2];
-	struct sensor_device_attribute_2 *sensor_attr =
-						to_sensor_dev_attr_2(attr);
-
-	newkey[0] = fan_speed_keys[sensor_attr->nr][0];
-	newkey[1] = '0' + sensor_attr->index;
-	newkey[2] = fan_speed_keys[sensor_attr->nr][2];
-	newkey[3] = fan_speed_keys[sensor_attr->nr][3];
-	newkey[4] = 0;
 
-	mutex_lock(&applesmc_lock);
+	sprintf(newkey, fan_speed_fmt[to_option(attr)], to_index(attr));
 
 	ret = applesmc_read_key(newkey, buffer, 2);
 	speed = ((buffer[0] << 8 | buffer[1]) >> 2);
 
-	mutex_unlock(&applesmc_lock);
 	if (ret)
 		return ret;
 	else
@@ -729,30 +778,19 @@ static ssize_t applesmc_store_fan_speed(
 					const char *sysfsbuf, size_t count)
 {
 	int ret;
-	u32 speed;
+	unsigned long speed;
 	char newkey[5];
 	u8 buffer[2];
-	struct sensor_device_attribute_2 *sensor_attr =
-						to_sensor_dev_attr_2(attr);
-
-	speed = simple_strtoul(sysfsbuf, NULL, 10);
-
-	if (speed > 0x4000) /* Bigger than a 14-bit value */
-		return -EINVAL;
 
-	newkey[0] = fan_speed_keys[sensor_attr->nr][0];
-	newkey[1] = '0' + sensor_attr->index;
-	newkey[2] = fan_speed_keys[sensor_attr->nr][2];
-	newkey[3] = fan_speed_keys[sensor_attr->nr][3];
-	newkey[4] = 0;
+	if (strict_strtoul(sysfsbuf, 10, &speed) < 0 || speed >= 0x4000)
+		return -EINVAL;		/* Bigger than a 14-bit value */
 
-	mutex_lock(&applesmc_lock);
+	sprintf(newkey, fan_speed_fmt[to_option(attr)], to_index(attr));
 
 	buffer[0] = (speed >> 6) & 0xff;
 	buffer[1] = (speed << 2) & 0xff;
 	ret = applesmc_write_key(newkey, buffer, 2);
 
-	mutex_unlock(&applesmc_lock);
 	if (ret)
 		return ret;
 	else
@@ -760,19 +798,15 @@ static ssize_t applesmc_store_fan_speed(
 }
 
 static ssize_t applesmc_show_fan_manual(struct device *dev,
-			struct device_attribute *devattr, char *sysfsbuf)
+			struct device_attribute *attr, char *sysfsbuf)
 {
 	int ret;
 	u16 manual = 0;
 	u8 buffer[2];
-	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-
-	mutex_lock(&applesmc_lock);
 
 	ret = applesmc_read_key(FANS_MANUAL, buffer, 2);
-	manual = ((buffer[0] << 8 | buffer[1]) >> attr->index) & 0x01;
+	manual = ((buffer[0] << 8 | buffer[1]) >> to_index(attr)) & 0x01;
 
-	mutex_unlock(&applesmc_lock);
 	if (ret)
 		return ret;
 	else
@@ -780,18 +814,16 @@ static ssize_t applesmc_show_fan_manual(
 }
 
 static ssize_t applesmc_store_fan_manual(struct device *dev,
-					 struct device_attribute *devattr,
+					 struct device_attribute *attr,
 					 const char *sysfsbuf, size_t count)
 {
 	int ret;
 	u8 buffer[2];
-	u32 input;
+	unsigned long input;
 	u16 val;
-	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-
-	input = simple_strtoul(sysfsbuf, NULL, 10);
 
-	mutex_lock(&applesmc_lock);
+	if (strict_strtoul(sysfsbuf, 10, &input) < 0)
+		return -EINVAL;
 
 	ret = applesmc_read_key(FANS_MANUAL, buffer, 2);
 	val = (buffer[0] << 8 | buffer[1]);
@@ -799,9 +831,9 @@ static ssize_t applesmc_store_fan_manual
 		goto out;
 
 	if (input)
-		val = val | (0x01 << attr->index);
+		val = val | (0x01 << to_index(attr));
 	else
-		val = val & ~(0x01 << attr->index);
+		val = val & ~(0x01 << to_index(attr));
 
 	buffer[0] = (val >> 8) & 0xFF;
 	buffer[1] = val & 0xFF;
@@ -809,7 +841,6 @@ static ssize_t applesmc_store_fan_manual
 	ret = applesmc_write_key(FANS_MANUAL, buffer, 2);
 
 out:
-	mutex_unlock(&applesmc_lock);
 	if (ret)
 		return ret;
 	else
@@ -822,21 +853,12 @@ static ssize_t applesmc_show_fan_positio
 	int ret;
 	char newkey[5];
 	u8 buffer[17];
-	struct sensor_device_attribute_2 *sensor_attr =
-						to_sensor_dev_attr_2(attr);
-
-	newkey[0] = FAN_POSITION[0];
-	newkey[1] = '0' + sensor_attr->index;
-	newkey[2] = FAN_POSITION[2];
-	newkey[3] = FAN_POSITION[3];
-	newkey[4] = 0;
 
-	mutex_lock(&applesmc_lock);
+	sprintf(newkey, FAN_ID_FMT, to_index(attr));
 
 	ret = applesmc_read_key(newkey, buffer, 16);
 	buffer[16] = 0;
 
-	mutex_unlock(&applesmc_lock);
 	if (ret)
 		return ret;
 	else
@@ -852,18 +874,14 @@ static ssize_t applesmc_calibrate_show(s
 static ssize_t applesmc_calibrate_store(struct device *dev,
 	struct device_attribute *attr, const char *sysfsbuf, size_t count)
 {
-	mutex_lock(&applesmc_lock);
 	applesmc_calibrate();
-	mutex_unlock(&applesmc_lock);
 
 	return count;
 }
 
 static void applesmc_backlight_set(struct work_struct *work)
 {
-	mutex_lock(&applesmc_lock);
 	applesmc_write_key(BACKLIGHT_KEY, backlight_state, 2);
-	mutex_unlock(&applesmc_lock);
 }
 static DECLARE_WORK(backlight_work, &applesmc_backlight_set);
 
@@ -886,13 +904,10 @@ static ssize_t applesmc_key_count_show(s
 	u8 buffer[4];
 	u32 count;
 
-	mutex_lock(&applesmc_lock);
-
 	ret = applesmc_read_key(KEY_COUNT_KEY, buffer, 4);
 	count = ((u32)buffer[0]<<24) + ((u32)buffer[1]<<16) +
 						((u32)buffer[2]<<8) + buffer[3];
 
-	mutex_unlock(&applesmc_lock);
 	if (ret)
 		return ret;
 	else
@@ -902,113 +917,53 @@ static ssize_t applesmc_key_count_show(s
 static ssize_t applesmc_key_at_index_read_show(struct device *dev,
 				struct device_attribute *attr, char *sysfsbuf)
 {
-	char key[5];
-	char info[6];
+	const struct applesmc_entry *entry;
 	int ret;
 
-	mutex_lock(&applesmc_lock);
-
-	ret = applesmc_get_key_at_index(key_at_index, key);
-
-	if (ret || !key[0]) {
-		mutex_unlock(&applesmc_lock);
-
-		return -EINVAL;
-	}
-
-	ret = applesmc_get_key_type(key, info);
-
-	if (ret) {
-		mutex_unlock(&applesmc_lock);
-
+	entry = applesmc_get_entry_by_index(key_at_index);
+	if (IS_ERR(entry))
+		return PTR_ERR(entry);
+	ret = applesmc_read_entry(entry, sysfsbuf, entry->len);
+	if (ret)
 		return ret;
-	}
-
-	/*
-	 * info[0] maximum value (APPLESMC_MAX_DATA_LENGTH) is much lower than
-	 * PAGE_SIZE, so we don't need any checks before writing to sysfsbuf.
-	 */
-	ret = applesmc_read_key(key, sysfsbuf, info[0]);
-
-	mutex_unlock(&applesmc_lock);
 
-	if (!ret) {
-		return info[0];
-	} else {
-		return ret;
-	}
+	return entry->len;
 }
 
 static ssize_t applesmc_key_at_index_data_length_show(struct device *dev,
 				struct device_attribute *attr, char *sysfsbuf)
 {
-	char key[5];
-	char info[6];
-	int ret;
-
-	mutex_lock(&applesmc_lock);
-
-	ret = applesmc_get_key_at_index(key_at_index, key);
-
-	if (ret || !key[0]) {
-		mutex_unlock(&applesmc_lock);
-
-		return -EINVAL;
-	}
-
-	ret = applesmc_get_key_type(key, info);
+	const struct applesmc_entry *entry;
 
-	mutex_unlock(&applesmc_lock);
+	entry = applesmc_get_entry_by_index(key_at_index);
+	if (IS_ERR(entry))
+		return PTR_ERR(entry);
 
-	if (!ret)
-		return snprintf(sysfsbuf, PAGE_SIZE, "%d\n", info[0]);
-	else
-		return ret;
+	return snprintf(sysfsbuf, PAGE_SIZE, "%d\n", entry->len);
 }
 
 static ssize_t applesmc_key_at_index_type_show(struct device *dev,
 				struct device_attribute *attr, char *sysfsbuf)
 {
-	char key[5];
-	char info[6];
-	int ret;
-
-	mutex_lock(&applesmc_lock);
-
-	ret = applesmc_get_key_at_index(key_at_index, key);
-
-	if (ret || !key[0]) {
-		mutex_unlock(&applesmc_lock);
-
-		return -EINVAL;
-	}
-
-	ret = applesmc_get_key_type(key, info);
+	const struct applesmc_entry *entry;
 
-	mutex_unlock(&applesmc_lock);
+	entry = applesmc_get_entry_by_index(key_at_index);
+	if (IS_ERR(entry))
+		return PTR_ERR(entry);
 
-	if (!ret)
-		return snprintf(sysfsbuf, PAGE_SIZE, "%s\n", info+1);
-	else
-		return ret;
+	return snprintf(sysfsbuf, PAGE_SIZE, "%s\n", entry->type);
 }
 
 static ssize_t applesmc_key_at_index_name_show(struct device *dev,
 				struct device_attribute *attr, char *sysfsbuf)
 {
-	char key[5];
-	int ret;
-
-	mutex_lock(&applesmc_lock);
-
-	ret = applesmc_get_key_at_index(key_at_index, key);
+	const struct applesmc_entry *entry;
 
-	mutex_unlock(&applesmc_lock);
+	entry = applesmc_get_entry_by_index(key_at_index);
+	if (IS_ERR(entry))
+		return PTR_ERR(entry);
 
-	if (!ret && key[0])
-		return snprintf(sysfsbuf, PAGE_SIZE, "%s\n", key);
-	else
-		return -EINVAL;
+	return snprintf(sysfsbuf, PAGE_SIZE, "%s\n", entry->key);
 }
 
 static ssize_t applesmc_key_at_index_show(struct device *dev,
@@ -1020,12 +975,13 @@ static ssize_t applesmc_key_at_index_sho
 static ssize_t applesmc_key_at_index_store(struct device *dev,
 	struct device_attribute *attr, const char *sysfsbuf, size_t count)
 {
-	mutex_lock(&applesmc_lock);
-
-	key_at_index = simple_strtoul(sysfsbuf, NULL, 10);
+	unsigned long newkey;
 
-	mutex_unlock(&applesmc_lock);
+	if (strict_strtoul(sysfsbuf, 10, &newkey) < 0
+	    || newkey >= smcreg.key_count)
+		return -EINVAL;
 
+	key_at_index = newkey;
 	return count;
 }
 
@@ -1035,387 +991,102 @@ static struct led_classdev applesmc_back
 	.brightness_set		= applesmc_brightness_set,
 };
 
-static DEVICE_ATTR(name, 0444, applesmc_name_show, NULL);
-
-static DEVICE_ATTR(position, 0444, applesmc_position_show, NULL);
-static DEVICE_ATTR(calibrate, 0644,
-			applesmc_calibrate_show, applesmc_calibrate_store);
-
-static struct attribute *accelerometer_attributes[] = {
-	&dev_attr_position.attr,
-	&dev_attr_calibrate.attr,
-	NULL
-};
-
-static const struct attribute_group accelerometer_attributes_group =
-	{ .attrs = accelerometer_attributes };
-
-static DEVICE_ATTR(light, 0444, applesmc_light_show, NULL);
-
-static DEVICE_ATTR(key_count, 0444, applesmc_key_count_show, NULL);
-static DEVICE_ATTR(key_at_index, 0644,
-		applesmc_key_at_index_show, applesmc_key_at_index_store);
-static DEVICE_ATTR(key_at_index_name, 0444,
-					applesmc_key_at_index_name_show, NULL);
-static DEVICE_ATTR(key_at_index_type, 0444,
-					applesmc_key_at_index_type_show, NULL);
-static DEVICE_ATTR(key_at_index_data_length, 0444,
-				applesmc_key_at_index_data_length_show, NULL);
-static DEVICE_ATTR(key_at_index_data, 0444,
-				applesmc_key_at_index_read_show, NULL);
-
-static struct attribute *key_enumeration_attributes[] = {
-	&dev_attr_key_count.attr,
-	&dev_attr_key_at_index.attr,
-	&dev_attr_key_at_index_name.attr,
-	&dev_attr_key_at_index_type.attr,
-	&dev_attr_key_at_index_data_length.attr,
-	&dev_attr_key_at_index_data.attr,
-	NULL
+static struct applesmc_node_group info_group[] = {
+	{ "name", applesmc_name_show },
+	{ "key_count", applesmc_key_count_show },
+	{ "key_at_index", applesmc_key_at_index_show, applesmc_key_at_index_store },
+	{ "key_at_index_name", applesmc_key_at_index_name_show },
+	{ "key_at_index_type", applesmc_key_at_index_type_show },
+	{ "key_at_index_data_length", applesmc_key_at_index_data_length_show },
+	{ "key_at_index_data", applesmc_key_at_index_read_show },
+	{ }
 };
 
-static const struct attribute_group key_enumeration_group =
-	{ .attrs = key_enumeration_attributes };
-
-/*
- * Macro defining SENSOR_DEVICE_ATTR for a fan sysfs entries.
- *  - show actual speed
- *  - show/store minimum speed
- *  - show maximum speed
- *  - show safe speed
- *  - show/store target speed
- *  - show/store manual mode
- */
-#define sysfs_fan_speeds_offset(offset) \
-static SENSOR_DEVICE_ATTR_2(fan##offset##_input, S_IRUGO, \
-			applesmc_show_fan_speed, NULL, 0, offset-1); \
-\
-static SENSOR_DEVICE_ATTR_2(fan##offset##_min, S_IRUGO | S_IWUSR, \
-	applesmc_show_fan_speed, applesmc_store_fan_speed, 1, offset-1); \
-\
-static SENSOR_DEVICE_ATTR_2(fan##offset##_max, S_IRUGO, \
-			applesmc_show_fan_speed, NULL, 2, offset-1); \
-\
-static SENSOR_DEVICE_ATTR_2(fan##offset##_safe, S_IRUGO, \
-			applesmc_show_fan_speed, NULL, 3, offset-1); \
-\
-static SENSOR_DEVICE_ATTR_2(fan##offset##_output, S_IRUGO | S_IWUSR, \
-	applesmc_show_fan_speed, applesmc_store_fan_speed, 4, offset-1); \
-\
-static SENSOR_DEVICE_ATTR(fan##offset##_manual, S_IRUGO | S_IWUSR, \
-	applesmc_show_fan_manual, applesmc_store_fan_manual, offset-1); \
-\
-static SENSOR_DEVICE_ATTR(fan##offset##_label, S_IRUGO, \
-	applesmc_show_fan_position, NULL, offset-1); \
-\
-static struct attribute *fan##offset##_attributes[] = { \
-	&sensor_dev_attr_fan##offset##_input.dev_attr.attr, \
-	&sensor_dev_attr_fan##offset##_min.dev_attr.attr, \
-	&sensor_dev_attr_fan##offset##_max.dev_attr.attr, \
-	&sensor_dev_attr_fan##offset##_safe.dev_attr.attr, \
-	&sensor_dev_attr_fan##offset##_output.dev_attr.attr, \
-	&sensor_dev_attr_fan##offset##_manual.dev_attr.attr, \
-	&sensor_dev_attr_fan##offset##_label.dev_attr.attr, \
-	NULL \
+static struct applesmc_node_group accelerometer_group[] = {
+	{ "position", applesmc_position_show },
+	{ "calibrate", applesmc_calibrate_show, applesmc_calibrate_store },
+	{ }
 };
 
-/*
- * Create the needed functions for each fan using the macro defined above
- * (4 fans are supported)
- */
-sysfs_fan_speeds_offset(1);
-sysfs_fan_speeds_offset(2);
-sysfs_fan_speeds_offset(3);
-sysfs_fan_speeds_offset(4);
-
-static const struct attribute_group fan_attribute_groups[] = {
-	{ .attrs = fan1_attributes },
-	{ .attrs = fan2_attributes },
-	{ .attrs = fan3_attributes },
-	{ .attrs = fan4_attributes },
+static struct applesmc_node_group light_sensor_group[] = {
+	{ "light", applesmc_light_show },
+	{ }
 };
 
-/*
- * Temperature sensors sysfs entries.
- */
-static SENSOR_DEVICE_ATTR(temp1_label, S_IRUGO,
-					applesmc_show_sensor_label, NULL, 0);
-static SENSOR_DEVICE_ATTR(temp2_label, S_IRUGO,
-					applesmc_show_sensor_label, NULL, 1);
-static SENSOR_DEVICE_ATTR(temp3_label, S_IRUGO,
-					applesmc_show_sensor_label, NULL, 2);
-static SENSOR_DEVICE_ATTR(temp4_label, S_IRUGO,
-					applesmc_show_sensor_label, NULL, 3);
-static SENSOR_DEVICE_ATTR(temp5_label, S_IRUGO,
-					applesmc_show_sensor_label, NULL, 4);
-static SENSOR_DEVICE_ATTR(temp6_label, S_IRUGO,
-					applesmc_show_sensor_label, NULL, 5);
-static SENSOR_DEVICE_ATTR(temp7_label, S_IRUGO,
-					applesmc_show_sensor_label, NULL, 6);
-static SENSOR_DEVICE_ATTR(temp8_label, S_IRUGO,
-					applesmc_show_sensor_label, NULL, 7);
-static SENSOR_DEVICE_ATTR(temp9_label, S_IRUGO,
-					applesmc_show_sensor_label, NULL, 8);
-static SENSOR_DEVICE_ATTR(temp10_label, S_IRUGO,
-					applesmc_show_sensor_label, NULL, 9);
-static SENSOR_DEVICE_ATTR(temp11_label, S_IRUGO,
-					applesmc_show_sensor_label, NULL, 10);
-static SENSOR_DEVICE_ATTR(temp12_label, S_IRUGO,
-					applesmc_show_sensor_label, NULL, 11);
-static SENSOR_DEVICE_ATTR(temp13_label, S_IRUGO,
-					applesmc_show_sensor_label, NULL, 12);
-static SENSOR_DEVICE_ATTR(temp14_label, S_IRUGO,
-					applesmc_show_sensor_label, NULL, 13);
-static SENSOR_DEVICE_ATTR(temp15_label, S_IRUGO,
-					applesmc_show_sensor_label, NULL, 14);
-static SENSOR_DEVICE_ATTR(temp16_label, S_IRUGO,
-					applesmc_show_sensor_label, NULL, 15);
-static SENSOR_DEVICE_ATTR(temp17_label, S_IRUGO,
-					applesmc_show_sensor_label, NULL, 16);
-static SENSOR_DEVICE_ATTR(temp18_label, S_IRUGO,
-					applesmc_show_sensor_label, NULL, 17);
-static SENSOR_DEVICE_ATTR(temp19_label, S_IRUGO,
-					applesmc_show_sensor_label, NULL, 18);
-static SENSOR_DEVICE_ATTR(temp20_label, S_IRUGO,
-					applesmc_show_sensor_label, NULL, 19);
-static SENSOR_DEVICE_ATTR(temp21_label, S_IRUGO,
-					applesmc_show_sensor_label, NULL, 20);
-static SENSOR_DEVICE_ATTR(temp22_label, S_IRUGO,
-					applesmc_show_sensor_label, NULL, 21);
-static SENSOR_DEVICE_ATTR(temp23_label, S_IRUGO,
-					applesmc_show_sensor_label, NULL, 22);
-static SENSOR_DEVICE_ATTR(temp24_label, S_IRUGO,
-					applesmc_show_sensor_label, NULL, 23);
-static SENSOR_DEVICE_ATTR(temp25_label, S_IRUGO,
-					applesmc_show_sensor_label, NULL, 24);
-static SENSOR_DEVICE_ATTR(temp26_label, S_IRUGO,
-					applesmc_show_sensor_label, NULL, 25);
-static SENSOR_DEVICE_ATTR(temp27_label, S_IRUGO,
-					applesmc_show_sensor_label, NULL, 26);
-static SENSOR_DEVICE_ATTR(temp28_label, S_IRUGO,
-					applesmc_show_sensor_label, NULL, 27);
-static SENSOR_DEVICE_ATTR(temp29_label, S_IRUGO,
-					applesmc_show_sensor_label, NULL, 28);
-static SENSOR_DEVICE_ATTR(temp30_label, S_IRUGO,
-					applesmc_show_sensor_label, NULL, 29);
-static SENSOR_DEVICE_ATTR(temp31_label, S_IRUGO,
-					applesmc_show_sensor_label, NULL, 30);
-static SENSOR_DEVICE_ATTR(temp32_label, S_IRUGO,
-					applesmc_show_sensor_label, NULL, 31);
-static SENSOR_DEVICE_ATTR(temp33_label, S_IRUGO,
-					applesmc_show_sensor_label, NULL, 32);
-static SENSOR_DEVICE_ATTR(temp34_label, S_IRUGO,
-					applesmc_show_sensor_label, NULL, 33);
-static SENSOR_DEVICE_ATTR(temp35_label, S_IRUGO,
-					applesmc_show_sensor_label, NULL, 34);
-static SENSOR_DEVICE_ATTR(temp36_label, S_IRUGO,
-					applesmc_show_sensor_label, NULL, 35);
-static SENSOR_DEVICE_ATTR(temp37_label, S_IRUGO,
-					applesmc_show_sensor_label, NULL, 36);
-static SENSOR_DEVICE_ATTR(temp38_label, S_IRUGO,
-					applesmc_show_sensor_label, NULL, 37);
-static SENSOR_DEVICE_ATTR(temp39_label, S_IRUGO,
-					applesmc_show_sensor_label, NULL, 38);
-static SENSOR_DEVICE_ATTR(temp40_label, S_IRUGO,
-					applesmc_show_sensor_label, NULL, 39);
-static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO,
-					applesmc_show_temperature, NULL, 0);
-static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO,
-					applesmc_show_temperature, NULL, 1);
-static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO,
-					applesmc_show_temperature, NULL, 2);
-static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO,
-					applesmc_show_temperature, NULL, 3);
-static SENSOR_DEVICE_ATTR(temp5_input, S_IRUGO,
-					applesmc_show_temperature, NULL, 4);
-static SENSOR_DEVICE_ATTR(temp6_input, S_IRUGO,
-					applesmc_show_temperature, NULL, 5);
-static SENSOR_DEVICE_ATTR(temp7_input, S_IRUGO,
-					applesmc_show_temperature, NULL, 6);
-static SENSOR_DEVICE_ATTR(temp8_input, S_IRUGO,
-					applesmc_show_temperature, NULL, 7);
-static SENSOR_DEVICE_ATTR(temp9_input, S_IRUGO,
-					applesmc_show_temperature, NULL, 8);
-static SENSOR_DEVICE_ATTR(temp10_input, S_IRUGO,
-					applesmc_show_temperature, NULL, 9);
-static SENSOR_DEVICE_ATTR(temp11_input, S_IRUGO,
-					applesmc_show_temperature, NULL, 10);
-static SENSOR_DEVICE_ATTR(temp12_input, S_IRUGO,
-					applesmc_show_temperature, NULL, 11);
-static SENSOR_DEVICE_ATTR(temp13_input, S_IRUGO,
-					applesmc_show_temperature, NULL, 12);
-static SENSOR_DEVICE_ATTR(temp14_input, S_IRUGO,
-					applesmc_show_temperature, NULL, 13);
-static SENSOR_DEVICE_ATTR(temp15_input, S_IRUGO,
-					applesmc_show_temperature, NULL, 14);
-static SENSOR_DEVICE_ATTR(temp16_input, S_IRUGO,
-					applesmc_show_temperature, NULL, 15);
-static SENSOR_DEVICE_ATTR(temp17_input, S_IRUGO,
-					applesmc_show_temperature, NULL, 16);
-static SENSOR_DEVICE_ATTR(temp18_input, S_IRUGO,
-					applesmc_show_temperature, NULL, 17);
-static SENSOR_DEVICE_ATTR(temp19_input, S_IRUGO,
-					applesmc_show_temperature, NULL, 18);
-static SENSOR_DEVICE_ATTR(temp20_input, S_IRUGO,
-					applesmc_show_temperature, NULL, 19);
-static SENSOR_DEVICE_ATTR(temp21_input, S_IRUGO,
-					applesmc_show_temperature, NULL, 20);
-static SENSOR_DEVICE_ATTR(temp22_input, S_IRUGO,
-					applesmc_show_temperature, NULL, 21);
-static SENSOR_DEVICE_ATTR(temp23_input, S_IRUGO,
-					applesmc_show_temperature, NULL, 22);
-static SENSOR_DEVICE_ATTR(temp24_input, S_IRUGO,
-					applesmc_show_temperature, NULL, 23);
-static SENSOR_DEVICE_ATTR(temp25_input, S_IRUGO,
-					applesmc_show_temperature, NULL, 24);
-static SENSOR_DEVICE_ATTR(temp26_input, S_IRUGO,
-					applesmc_show_temperature, NULL, 25);
-static SENSOR_DEVICE_ATTR(temp27_input, S_IRUGO,
-					applesmc_show_temperature, NULL, 26);
-static SENSOR_DEVICE_ATTR(temp28_input, S_IRUGO,
-					applesmc_show_temperature, NULL, 27);
-static SENSOR_DEVICE_ATTR(temp29_input, S_IRUGO,
-					applesmc_show_temperature, NULL, 28);
-static SENSOR_DEVICE_ATTR(temp30_input, S_IRUGO,
-					applesmc_show_temperature, NULL, 29);
-static SENSOR_DEVICE_ATTR(temp31_input, S_IRUGO,
-					applesmc_show_temperature, NULL, 30);
-static SENSOR_DEVICE_ATTR(temp32_input, S_IRUGO,
-					applesmc_show_temperature, NULL, 31);
-static SENSOR_DEVICE_ATTR(temp33_input, S_IRUGO,
-					applesmc_show_temperature, NULL, 32);
-static SENSOR_DEVICE_ATTR(temp34_input, S_IRUGO,
-					applesmc_show_temperature, NULL, 33);
-static SENSOR_DEVICE_ATTR(temp35_input, S_IRUGO,
-					applesmc_show_temperature, NULL, 34);
-static SENSOR_DEVICE_ATTR(temp36_input, S_IRUGO,
-					applesmc_show_temperature, NULL, 35);
-static SENSOR_DEVICE_ATTR(temp37_input, S_IRUGO,
-					applesmc_show_temperature, NULL, 36);
-static SENSOR_DEVICE_ATTR(temp38_input, S_IRUGO,
-					applesmc_show_temperature, NULL, 37);
-static SENSOR_DEVICE_ATTR(temp39_input, S_IRUGO,
-					applesmc_show_temperature, NULL, 38);
-static SENSOR_DEVICE_ATTR(temp40_input, S_IRUGO,
-					applesmc_show_temperature, NULL, 39);
-
-static struct attribute *label_attributes[] = {
-	&sensor_dev_attr_temp1_label.dev_attr.attr,
-	&sensor_dev_attr_temp2_label.dev_attr.attr,
-	&sensor_dev_attr_temp3_label.dev_attr.attr,
-	&sensor_dev_attr_temp4_label.dev_attr.attr,
-	&sensor_dev_attr_temp5_label.dev_attr.attr,
-	&sensor_dev_attr_temp6_label.dev_attr.attr,
-	&sensor_dev_attr_temp7_label.dev_attr.attr,
-	&sensor_dev_attr_temp8_label.dev_attr.attr,
-	&sensor_dev_attr_temp9_label.dev_attr.attr,
-	&sensor_dev_attr_temp10_label.dev_attr.attr,
-	&sensor_dev_attr_temp11_label.dev_attr.attr,
-	&sensor_dev_attr_temp12_label.dev_attr.attr,
-	&sensor_dev_attr_temp13_label.dev_attr.attr,
-	&sensor_dev_attr_temp14_label.dev_attr.attr,
-	&sensor_dev_attr_temp15_label.dev_attr.attr,
-	&sensor_dev_attr_temp16_label.dev_attr.attr,
-	&sensor_dev_attr_temp17_label.dev_attr.attr,
-	&sensor_dev_attr_temp18_label.dev_attr.attr,
-	&sensor_dev_attr_temp19_label.dev_attr.attr,
-	&sensor_dev_attr_temp20_label.dev_attr.attr,
-	&sensor_dev_attr_temp21_label.dev_attr.attr,
-	&sensor_dev_attr_temp22_label.dev_attr.attr,
-	&sensor_dev_attr_temp23_label.dev_attr.attr,
-	&sensor_dev_attr_temp24_label.dev_attr.attr,
-	&sensor_dev_attr_temp25_label.dev_attr.attr,
-	&sensor_dev_attr_temp26_label.dev_attr.attr,
-	&sensor_dev_attr_temp27_label.dev_attr.attr,
-	&sensor_dev_attr_temp28_label.dev_attr.attr,
-	&sensor_dev_attr_temp29_label.dev_attr.attr,
-	&sensor_dev_attr_temp30_label.dev_attr.attr,
-	&sensor_dev_attr_temp31_label.dev_attr.attr,
-	&sensor_dev_attr_temp32_label.dev_attr.attr,
-	&sensor_dev_attr_temp33_label.dev_attr.attr,
-	&sensor_dev_attr_temp34_label.dev_attr.attr,
-	&sensor_dev_attr_temp35_label.dev_attr.attr,
-	&sensor_dev_attr_temp36_label.dev_attr.attr,
-	&sensor_dev_attr_temp37_label.dev_attr.attr,
-	&sensor_dev_attr_temp38_label.dev_attr.attr,
-	&sensor_dev_attr_temp39_label.dev_attr.attr,
-	&sensor_dev_attr_temp40_label.dev_attr.attr,
-	NULL
+static struct applesmc_node_group fan_group[] = {
+	{ "fan%d_label", applesmc_show_fan_position },
+	{ "fan%d_input", applesmc_show_fan_speed, NULL, 0 },
+	{ "fan%d_min", applesmc_show_fan_speed, applesmc_store_fan_speed, 1 },
+	{ "fan%d_max", applesmc_show_fan_speed, NULL, 2 },
+	{ "fan%d_safe", applesmc_show_fan_speed, NULL, 3 },
+	{ "fan%d_output", applesmc_show_fan_speed, applesmc_store_fan_speed, 4 },
+	{ "fan%d_manual", applesmc_show_fan_manual, applesmc_store_fan_manual },
+	{ }
 };
 
-static struct attribute *temperature_attributes[] = {
-	&sensor_dev_attr_temp1_input.dev_attr.attr,
-	&sensor_dev_attr_temp2_input.dev_attr.attr,
-	&sensor_dev_attr_temp3_input.dev_attr.attr,
-	&sensor_dev_attr_temp4_input.dev_attr.attr,
-	&sensor_dev_attr_temp5_input.dev_attr.attr,
-	&sensor_dev_attr_temp6_input.dev_attr.attr,
-	&sensor_dev_attr_temp7_input.dev_attr.attr,
-	&sensor_dev_attr_temp8_input.dev_attr.attr,
-	&sensor_dev_attr_temp9_input.dev_attr.attr,
-	&sensor_dev_attr_temp10_input.dev_attr.attr,
-	&sensor_dev_attr_temp11_input.dev_attr.attr,
-	&sensor_dev_attr_temp12_input.dev_attr.attr,
-	&sensor_dev_attr_temp13_input.dev_attr.attr,
-	&sensor_dev_attr_temp14_input.dev_attr.attr,
-	&sensor_dev_attr_temp15_input.dev_attr.attr,
-	&sensor_dev_attr_temp16_input.dev_attr.attr,
-	&sensor_dev_attr_temp17_input.dev_attr.attr,
-	&sensor_dev_attr_temp18_input.dev_attr.attr,
-	&sensor_dev_attr_temp19_input.dev_attr.attr,
-	&sensor_dev_attr_temp20_input.dev_attr.attr,
-	&sensor_dev_attr_temp21_input.dev_attr.attr,
-	&sensor_dev_attr_temp22_input.dev_attr.attr,
-	&sensor_dev_attr_temp23_input.dev_attr.attr,
-	&sensor_dev_attr_temp24_input.dev_attr.attr,
-	&sensor_dev_attr_temp25_input.dev_attr.attr,
-	&sensor_dev_attr_temp26_input.dev_attr.attr,
-	&sensor_dev_attr_temp27_input.dev_attr.attr,
-	&sensor_dev_attr_temp28_input.dev_attr.attr,
-	&sensor_dev_attr_temp29_input.dev_attr.attr,
-	&sensor_dev_attr_temp30_input.dev_attr.attr,
-	&sensor_dev_attr_temp31_input.dev_attr.attr,
-	&sensor_dev_attr_temp32_input.dev_attr.attr,
-	&sensor_dev_attr_temp33_input.dev_attr.attr,
-	&sensor_dev_attr_temp34_input.dev_attr.attr,
-	&sensor_dev_attr_temp35_input.dev_attr.attr,
-	&sensor_dev_attr_temp36_input.dev_attr.attr,
-	&sensor_dev_attr_temp37_input.dev_attr.attr,
-	&sensor_dev_attr_temp38_input.dev_attr.attr,
-	&sensor_dev_attr_temp39_input.dev_attr.attr,
-	&sensor_dev_attr_temp40_input.dev_attr.attr,
-	NULL
+static struct applesmc_node_group temp_group[] = {
+	{ "temp%d_label", applesmc_show_sensor_label },
+	{ "temp%d_input", applesmc_show_temperature },
+	{ }
 };
 
-static const struct attribute_group temperature_attributes_group =
-	{ .attrs = temperature_attributes };
+/* Module stuff */
 
-static const struct attribute_group label_attributes_group = {
-	.attrs = label_attributes
-};
+/*
+ * applesmc_destroy_nodes - remove files and free associated memory
+ */
+static void applesmc_destroy_nodes(struct applesmc_node_group *groups)
+{
+	struct applesmc_node_group *grp;
+	struct applesmc_dev_attr *node;
 
-/* Module stuff */
+	for (grp = groups; grp->nodes; grp++) {
+		for (node = grp->nodes; node->sda.dev_attr.attr.name; node++)
+			sysfs_remove_file(&pdev->dev.kobj,
+					  &node->sda.dev_attr.attr);
+		kfree(grp->nodes);
+		grp->nodes = NULL;
+	}
+}
 
 /*
- * applesmc_dmi_match - found a match.  return one, short-circuiting the hunt.
+ * applesmc_create_nodes - create a two-dimensional group of sysfs files
  */
-static int applesmc_dmi_match(const struct dmi_system_id *id)
+static int applesmc_create_nodes(struct applesmc_node_group *groups, int num)
 {
-	int i = 0;
-	struct dmi_match_data* dmi_data = id->driver_data;
-	printk(KERN_INFO "applesmc: %s detected:\n", id->ident);
-	applesmc_accelerometer = dmi_data->accelerometer;
-	printk(KERN_INFO "applesmc:  - Model %s accelerometer\n",
-				applesmc_accelerometer ? "with" : "without");
-	applesmc_light = dmi_data->light;
-	printk(KERN_INFO "applesmc:  - Model %s light sensors and backlight\n",
-					applesmc_light ? "with" : "without");
+	struct applesmc_node_group *grp;
+	struct applesmc_dev_attr *node;
+	struct attribute *attr;
+	int ret, i;
 
-	applesmc_temperature_set =  dmi_data->temperature_set;
-	while (temperature_sensors_sets[applesmc_temperature_set][i] != NULL)
-		i++;
-	printk(KERN_INFO "applesmc:  - Model with %d temperature sensors\n", i);
-	return 1;
+	for (grp = groups; grp->format; grp++) {
+		grp->nodes = kcalloc(num + 1, sizeof(*node), GFP_KERNEL);
+		if (!grp->nodes) {
+			ret = -ENOMEM;
+			goto out;
+		}
+		for (i = 0; i < num; i++) {
+			node = &grp->nodes[i];
+			sprintf(node->name, grp->format, i + 1);
+			node->sda.index = (grp->option << 16) | (i & 0xffff);
+			node->sda.dev_attr.show = grp->show;
+			node->sda.dev_attr.store = grp->store;
+			attr = &node->sda.dev_attr.attr;
+			sysfs_attr_init(attr);
+			attr->name = node->name;
+			attr->mode = S_IRUGO | (grp->store ? S_IWUSR : 0);
+			ret = sysfs_create_file(&pdev->dev.kobj, attr);
+			if (ret) {
+				attr->name = NULL;
+				goto out;
+			}
+		}
+	}
+
+	return 0;
+out:
+	applesmc_destroy_nodes(groups);
+	return ret;
 }
 
 /* Create accelerometer ressources */
@@ -1424,8 +1095,10 @@ static int applesmc_create_accelerometer
 	struct input_dev *idev;
 	int ret;
 
-	ret = sysfs_create_group(&pdev->dev.kobj,
-					&accelerometer_attributes_group);
+	if (!smcreg.has_accelerometer)
+		return 0;
+
+	ret = applesmc_create_nodes(accelerometer_group, 1);
 	if (ret)
 		goto out;
 
@@ -1462,184 +1135,96 @@ out_idev:
 	input_free_polled_device(applesmc_idev);
 
 out_sysfs:
-	sysfs_remove_group(&pdev->dev.kobj, &accelerometer_attributes_group);
+	applesmc_destroy_nodes(accelerometer_group);
 
 out:
-	printk(KERN_WARNING "applesmc: driver init failed (ret=%d)!\n", ret);
+	pr_warn("driver init failed (ret=%d)!\n", ret);
 	return ret;
 }
 
 /* Release all ressources used by the accelerometer */
 static void applesmc_release_accelerometer(void)
 {
+	if (!smcreg.has_accelerometer)
+		return;
 	input_unregister_polled_device(applesmc_idev);
 	input_free_polled_device(applesmc_idev);
-	sysfs_remove_group(&pdev->dev.kobj, &accelerometer_attributes_group);
+	applesmc_destroy_nodes(accelerometer_group);
 }
 
-static __initdata struct dmi_match_data applesmc_dmi_data[] = {
-/* MacBook Pro: accelerometer, backlight and temperature set 0 */
-	{ .accelerometer = 1, .light = 1, .temperature_set = 0 },
-/* MacBook2: accelerometer and temperature set 1 */
-	{ .accelerometer = 1, .light = 0, .temperature_set = 1 },
-/* MacBook: accelerometer and temperature set 2 */
-	{ .accelerometer = 1, .light = 0, .temperature_set = 2 },
-/* MacMini: temperature set 3 */
-	{ .accelerometer = 0, .light = 0, .temperature_set = 3 },
-/* MacPro: temperature set 4 */
-	{ .accelerometer = 0, .light = 0, .temperature_set = 4 },
-/* iMac: temperature set 5 */
-	{ .accelerometer = 0, .light = 0, .temperature_set = 5 },
-/* MacBook3, MacBook4: accelerometer and temperature set 6 */
-	{ .accelerometer = 1, .light = 0, .temperature_set = 6 },
-/* MacBook Air: accelerometer, backlight and temperature set 7 */
-	{ .accelerometer = 1, .light = 1, .temperature_set = 7 },
-/* MacBook Pro 4: accelerometer, backlight and temperature set 8 */
-	{ .accelerometer = 1, .light = 1, .temperature_set = 8 },
-/* MacBook Pro 3: accelerometer, backlight and temperature set 9 */
-	{ .accelerometer = 1, .light = 1, .temperature_set = 9 },
-/* iMac 5: light sensor only, temperature set 10 */
-	{ .accelerometer = 0, .light = 0, .temperature_set = 10 },
-/* MacBook 5: accelerometer, backlight and temperature set 11 */
-	{ .accelerometer = 1, .light = 1, .temperature_set = 11 },
-/* MacBook Pro 5: accelerometer, backlight and temperature set 12 */
-	{ .accelerometer = 1, .light = 1, .temperature_set = 12 },
-/* iMac 8: light sensor only, temperature set 13 */
-	{ .accelerometer = 0, .light = 0, .temperature_set = 13 },
-/* iMac 6: light sensor only, temperature set 14 */
-	{ .accelerometer = 0, .light = 0, .temperature_set = 14 },
-/* MacBook Air 2,1: accelerometer, backlight and temperature set 15 */
-	{ .accelerometer = 1, .light = 1, .temperature_set = 15 },
-/* MacPro3,1: temperature set 16 */
-	{ .accelerometer = 0, .light = 0, .temperature_set = 16 },
-/* iMac 9,1: light sensor only, temperature set 17 */
-	{ .accelerometer = 0, .light = 0, .temperature_set = 17 },
-/* MacBook Pro 2,2: accelerometer, backlight and temperature set 18 */
-	{ .accelerometer = 1, .light = 1, .temperature_set = 18 },
-/* MacBook Pro 5,3: accelerometer, backlight and temperature set 19 */
-	{ .accelerometer = 1, .light = 1, .temperature_set = 19 },
-/* MacBook Pro 5,4: accelerometer, backlight and temperature set 20 */
-	{ .accelerometer = 1, .light = 1, .temperature_set = 20 },
-/* MacBook Pro 6,2: accelerometer, backlight and temperature set 21 */
-	{ .accelerometer = 1, .light = 1, .temperature_set = 21 },
-/* MacBook Pro 7,1: accelerometer, backlight and temperature set 22 */
-	{ .accelerometer = 1, .light = 1, .temperature_set = 22 },
-};
+static int applesmc_create_light_sensor(void)
+{
+	if (!smcreg.num_light_sensors)
+		return 0;
+	return applesmc_create_nodes(light_sensor_group, 1);
+}
+
+static void applesmc_release_light_sensor(void)
+{
+	if (!smcreg.num_light_sensors)
+		return;
+	applesmc_destroy_nodes(light_sensor_group);
+}
+
+static int applesmc_create_key_backlight(void)
+{
+	if (!smcreg.has_key_backlight)
+		return 0;
+	applesmc_led_wq = create_singlethread_workqueue("applesmc-led");
+	if (!applesmc_led_wq)
+		return -ENOMEM;
+	return led_classdev_register(&pdev->dev, &applesmc_backlight);
+}
+
+static void applesmc_release_key_backlight(void)
+{
+	if (!smcreg.has_key_backlight)
+		return;
+	led_classdev_unregister(&applesmc_backlight);
+	destroy_workqueue(applesmc_led_wq);
+}
+
+static int applesmc_dmi_match(const struct dmi_system_id *id)
+{
+	return 1;
+}
 
 /* Note that DMI_MATCH(...,"MacBook") will match "MacBookPro1,1".
  * So we need to put "Apple MacBook Pro" before "Apple MacBook". */
 static __initdata struct dmi_system_id applesmc_whitelist[] = {
-	{ applesmc_dmi_match, "Apple MacBook Air 2", {
-	  DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
-	  DMI_MATCH(DMI_PRODUCT_NAME, "MacBookAir2") },
-		&applesmc_dmi_data[15]},
 	{ applesmc_dmi_match, "Apple MacBook Air", {
 	  DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
 	  DMI_MATCH(DMI_PRODUCT_NAME, "MacBookAir") },
-		&applesmc_dmi_data[7]},
-	{ applesmc_dmi_match, "Apple MacBook Pro 7", {
-	  DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
-	  DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro7") },
-		&applesmc_dmi_data[22]},
-	{ applesmc_dmi_match, "Apple MacBook Pro 5,4", {
-	  DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
-	  DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro5,4") },
-		&applesmc_dmi_data[20]},
-	{ applesmc_dmi_match, "Apple MacBook Pro 5,3", {
-	  DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
-	  DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro5,3") },
-		&applesmc_dmi_data[19]},
-	{ applesmc_dmi_match, "Apple MacBook Pro 6", {
-	  DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
-	  DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro6") },
-		&applesmc_dmi_data[21]},
-	{ applesmc_dmi_match, "Apple MacBook Pro 5", {
-	  DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
-	  DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro5") },
-		&applesmc_dmi_data[12]},
-	{ applesmc_dmi_match, "Apple MacBook Pro 4", {
-	  DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
-	  DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro4") },
-		&applesmc_dmi_data[8]},
-	{ applesmc_dmi_match, "Apple MacBook Pro 3", {
-	  DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
-	  DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro3") },
-		&applesmc_dmi_data[9]},
-	{ applesmc_dmi_match, "Apple MacBook Pro 2,2", {
-	  DMI_MATCH(DMI_BOARD_VENDOR, "Apple Computer, Inc."),
-	  DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro2,2") },
-		&applesmc_dmi_data[18]},
+	},
 	{ applesmc_dmi_match, "Apple MacBook Pro", {
-	  DMI_MATCH(DMI_BOARD_VENDOR,"Apple"),
-	  DMI_MATCH(DMI_PRODUCT_NAME,"MacBookPro") },
-		&applesmc_dmi_data[0]},
-	{ applesmc_dmi_match, "Apple MacBook (v2)", {
-	  DMI_MATCH(DMI_BOARD_VENDOR,"Apple"),
-	  DMI_MATCH(DMI_PRODUCT_NAME,"MacBook2") },
-		&applesmc_dmi_data[1]},
-	{ applesmc_dmi_match, "Apple MacBook (v3)", {
-	  DMI_MATCH(DMI_BOARD_VENDOR,"Apple"),
-	  DMI_MATCH(DMI_PRODUCT_NAME,"MacBook3") },
-		&applesmc_dmi_data[6]},
-	{ applesmc_dmi_match, "Apple MacBook 4", {
-	  DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
-	  DMI_MATCH(DMI_PRODUCT_NAME, "MacBook4") },
-		&applesmc_dmi_data[6]},
-	{ applesmc_dmi_match, "Apple MacBook 5", {
 	  DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
-	  DMI_MATCH(DMI_PRODUCT_NAME, "MacBook5") },
-		&applesmc_dmi_data[11]},
+	  DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro") },
+	},
 	{ applesmc_dmi_match, "Apple MacBook", {
-	  DMI_MATCH(DMI_BOARD_VENDOR,"Apple"),
-	  DMI_MATCH(DMI_PRODUCT_NAME,"MacBook") },
-		&applesmc_dmi_data[2]},
+	  DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
+	  DMI_MATCH(DMI_PRODUCT_NAME, "MacBook") },
+	},
 	{ applesmc_dmi_match, "Apple Macmini", {
-	  DMI_MATCH(DMI_BOARD_VENDOR,"Apple"),
-	  DMI_MATCH(DMI_PRODUCT_NAME,"Macmini") },
-		&applesmc_dmi_data[3]},
-	{ applesmc_dmi_match, "Apple MacPro2", {
-	  DMI_MATCH(DMI_BOARD_VENDOR,"Apple"),
-	  DMI_MATCH(DMI_PRODUCT_NAME,"MacPro2") },
-		&applesmc_dmi_data[4]},
-	{ applesmc_dmi_match, "Apple MacPro3", {
 	  DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
-	  DMI_MATCH(DMI_PRODUCT_NAME, "MacPro3") },
-		&applesmc_dmi_data[16]},
+	  DMI_MATCH(DMI_PRODUCT_NAME, "Macmini") },
+	},
 	{ applesmc_dmi_match, "Apple MacPro", {
 	  DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
 	  DMI_MATCH(DMI_PRODUCT_NAME, "MacPro") },
-		&applesmc_dmi_data[4]},
-	{ applesmc_dmi_match, "Apple iMac 9,1", {
-	  DMI_MATCH(DMI_BOARD_VENDOR, "Apple Inc."),
-	  DMI_MATCH(DMI_PRODUCT_NAME, "iMac9,1") },
-		&applesmc_dmi_data[17]},
-	{ applesmc_dmi_match, "Apple iMac 8", {
-	  DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
-	  DMI_MATCH(DMI_PRODUCT_NAME, "iMac8") },
-		&applesmc_dmi_data[13]},
-	{ applesmc_dmi_match, "Apple iMac 6", {
-	  DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
-	  DMI_MATCH(DMI_PRODUCT_NAME, "iMac6") },
-		&applesmc_dmi_data[14]},
-	{ applesmc_dmi_match, "Apple iMac 5", {
-	  DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
-	  DMI_MATCH(DMI_PRODUCT_NAME, "iMac5") },
-		&applesmc_dmi_data[10]},
+	},
 	{ applesmc_dmi_match, "Apple iMac", {
-	  DMI_MATCH(DMI_BOARD_VENDOR,"Apple"),
-	  DMI_MATCH(DMI_PRODUCT_NAME,"iMac") },
-		&applesmc_dmi_data[5]},
+	  DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
+	  DMI_MATCH(DMI_PRODUCT_NAME, "iMac") },
+	},
 	{ .ident = NULL }
 };
 
 static int __init applesmc_init(void)
 {
 	int ret;
-	int count;
-	int i;
 
 	if (!dmi_check_system(applesmc_whitelist)) {
-		printk(KERN_WARNING "applesmc: supported laptop not found!\n");
+		pr_warn("supported laptop not found!\n");
 		ret = -ENODEV;
 		goto out;
 	}
@@ -1661,83 +1246,34 @@ static int __init applesmc_init(void)
 		goto out_driver;
 	}
 
-	ret = sysfs_create_file(&pdev->dev.kobj, &dev_attr_name.attr);
+	/* create register cache */
+	ret = applesmc_init_smcreg();
 	if (ret)
 		goto out_device;
 
-	/* Create key enumeration sysfs files */
-	ret = sysfs_create_group(&pdev->dev.kobj, &key_enumeration_group);
+	ret = applesmc_create_nodes(info_group, 1);
 	if (ret)
-		goto out_name;
-
-	/* create fan files */
-	count = applesmc_get_fan_count();
-	if (count < 0)
-		printk(KERN_ERR "applesmc: Cannot get the number of fans.\n");
-	else
-		printk(KERN_INFO "applesmc: %d fans found.\n", count);
-
-	if (count > 4) {
-		count = 4;
-		printk(KERN_WARNING "applesmc: More than 4 fans found,"
-		       " but at most 4 fans are supported"
-		       " by the driver.\n");
-	}
-
-	while (fans_handled < count) {
-		ret = sysfs_create_group(&pdev->dev.kobj,
-					 &fan_attribute_groups[fans_handled]);
-		if (ret)
-			goto out_fans;
-		fans_handled++;
-	}
+		goto out_smcreg;
 
-	for (i = 0;
-	     temperature_sensors_sets[applesmc_temperature_set][i] != NULL;
-	     i++) {
-		if (temperature_attributes[i] == NULL ||
-		    label_attributes[i] == NULL) {
-			printk(KERN_ERR "applesmc: More temperature sensors "
-				"in temperature_sensors_sets (at least %i)"
-				"than available sysfs files in "
-				"temperature_attributes (%i), please report "
-				"this bug.\n", i, i-1);
-			goto out_temperature;
-		}
-		ret = sysfs_create_file(&pdev->dev.kobj,
-						temperature_attributes[i]);
-		if (ret)
-			goto out_temperature;
-		ret = sysfs_create_file(&pdev->dev.kobj,
-						label_attributes[i]);
-		if (ret)
-			goto out_temperature;
-	}
+	ret = applesmc_create_nodes(fan_group, smcreg.fan_count);
+	if (ret)
+		goto out_info;
 
-	if (applesmc_accelerometer) {
-		ret = applesmc_create_accelerometer();
-		if (ret)
-			goto out_temperature;
-	}
+	ret = applesmc_create_nodes(temp_group, smcreg.temp_count);
+	if (ret)
+		goto out_fans;
 
-	if (applesmc_light) {
-		/* Add light sensor file */
-		ret = sysfs_create_file(&pdev->dev.kobj, &dev_attr_light.attr);
-		if (ret)
-			goto out_accelerometer;
+	ret = applesmc_create_accelerometer();
+	if (ret)
+		goto out_temperature;
 
-		/* Create the workqueue */
-		applesmc_led_wq = create_singlethread_workqueue("applesmc-led");
-		if (!applesmc_led_wq) {
-			ret = -ENOMEM;
-			goto out_light_sysfs;
-		}
+	ret = applesmc_create_light_sensor();
+	if (ret)
+		goto out_accelerometer;
 
-		/* register as a led device */
-		ret = led_classdev_register(&pdev->dev, &applesmc_backlight);
-		if (ret < 0)
-			goto out_light_wq;
-	}
+	ret = applesmc_create_key_backlight();
+	if (ret)
+		goto out_light_sysfs;
 
 	hwmon_dev = hwmon_device_register(&pdev->dev);
 	if (IS_ERR(hwmon_dev)) {
@@ -1745,32 +1281,22 @@ static int __init applesmc_init(void)
 		goto out_light_ledclass;
 	}
 
-	printk(KERN_INFO "applesmc: driver successfully loaded.\n");
-
 	return 0;
 
 out_light_ledclass:
-	if (applesmc_light)
-		led_classdev_unregister(&applesmc_backlight);
-out_light_wq:
-	if (applesmc_light)
-		destroy_workqueue(applesmc_led_wq);
+	applesmc_release_key_backlight();
 out_light_sysfs:
-	if (applesmc_light)
-		sysfs_remove_file(&pdev->dev.kobj, &dev_attr_light.attr);
+	applesmc_release_light_sensor();
 out_accelerometer:
-	if (applesmc_accelerometer)
-		applesmc_release_accelerometer();
+	applesmc_release_accelerometer();
 out_temperature:
-	sysfs_remove_group(&pdev->dev.kobj, &label_attributes_group);
-	sysfs_remove_group(&pdev->dev.kobj, &temperature_attributes_group);
+	applesmc_destroy_nodes(temp_group);
 out_fans:
-	while (fans_handled)
-		sysfs_remove_group(&pdev->dev.kobj,
-				   &fan_attribute_groups[--fans_handled]);
-	sysfs_remove_group(&pdev->dev.kobj, &key_enumeration_group);
-out_name:
-	sysfs_remove_file(&pdev->dev.kobj, &dev_attr_name.attr);
+	applesmc_destroy_nodes(fan_group);
+out_info:
+	applesmc_destroy_nodes(info_group);
+out_smcreg:
+	applesmc_destroy_smcreg();
 out_device:
 	platform_device_unregister(pdev);
 out_driver:
@@ -1778,32 +1304,23 @@ out_driver:
 out_region:
 	release_region(APPLESMC_DATA_PORT, APPLESMC_NR_PORTS);
 out:
-	printk(KERN_WARNING "applesmc: driver init failed (ret=%d)!\n", ret);
+	pr_warn("driver init failed (ret=%d)!\n", ret);
 	return ret;
 }
 
 static void __exit applesmc_exit(void)
 {
 	hwmon_device_unregister(hwmon_dev);
-	if (applesmc_light) {
-		led_classdev_unregister(&applesmc_backlight);
-		destroy_workqueue(applesmc_led_wq);
-		sysfs_remove_file(&pdev->dev.kobj, &dev_attr_light.attr);
-	}
-	if (applesmc_accelerometer)
-		applesmc_release_accelerometer();
-	sysfs_remove_group(&pdev->dev.kobj, &label_attributes_group);
-	sysfs_remove_group(&pdev->dev.kobj, &temperature_attributes_group);
-	while (fans_handled)
-		sysfs_remove_group(&pdev->dev.kobj,
-				   &fan_attribute_groups[--fans_handled]);
-	sysfs_remove_group(&pdev->dev.kobj, &key_enumeration_group);
-	sysfs_remove_file(&pdev->dev.kobj, &dev_attr_name.attr);
+	applesmc_release_key_backlight();
+	applesmc_release_light_sensor();
+	applesmc_release_accelerometer();
+	applesmc_destroy_nodes(temp_group);
+	applesmc_destroy_nodes(fan_group);
+	applesmc_destroy_nodes(info_group);
+	applesmc_destroy_smcreg();
 	platform_device_unregister(pdev);
 	platform_driver_unregister(&applesmc_driver);
 	release_region(APPLESMC_DATA_PORT, APPLESMC_NR_PORTS);
-
-	printk(KERN_INFO "applesmc: driver unloaded.\n");
 }
 
 module_init(applesmc_init);
diff -druNp linux-libre-2.6.37-gnu1/drivers/hwmon/asb100.c linux-libre-2.6.38-gnu1/drivers/hwmon/asb100.c
--- linux-libre-2.6.37-gnu1/drivers/hwmon/asb100.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hwmon/asb100.c	2011-03-14 21:20:32.000000000 -0400
@@ -36,6 +36,8 @@
     asb100	7	3	1	4	0x31	0x0694	yes	no
 */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/i2c.h>
@@ -701,8 +703,7 @@ static int asb100_detect(struct i2c_clie
 	int val1, val2;
 
 	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
-		pr_debug("asb100.o: detect failed, "
-				"smbus byte data not supported!\n");
+		pr_debug("detect failed, smbus byte data not supported!\n");
 		return -ENODEV;
 	}
 
@@ -715,7 +716,7 @@ static int asb100_detect(struct i2c_clie
 			(((!(val1 & 0x80)) && (val2 != 0x94)) ||
 			/* Check for ASB100 ID (high byte ) */
 			((val1 & 0x80) && (val2 != 0x06)))) {
-		pr_debug("asb100: detect failed, bad chip id 0x%02x!\n", val2);
+		pr_debug("detect failed, bad chip id 0x%02x!\n", val2);
 		return -ENODEV;
 	}
 
@@ -744,7 +745,7 @@ static int asb100_probe(struct i2c_clien
 
 	data = kzalloc(sizeof(struct asb100_data), GFP_KERNEL);
 	if (!data) {
-		pr_debug("asb100.o: probe failed, kzalloc failed!\n");
+		pr_debug("probe failed, kzalloc failed!\n");
 		err = -ENOMEM;
 		goto ERROR0;
 	}
diff -druNp linux-libre-2.6.37-gnu1/drivers/hwmon/asus_atk0110.c linux-libre-2.6.38-gnu1/drivers/hwmon/asus_atk0110.c
--- linux-libre-2.6.37-gnu1/drivers/hwmon/asus_atk0110.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hwmon/asus_atk0110.c	2011-03-14 21:20:32.000000000 -0400
@@ -5,12 +5,15 @@
  * See COPYING in the top level directory of the kernel tree.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/debugfs.h>
 #include <linux/kernel.h>
 #include <linux/hwmon.h>
 #include <linux/list.h>
 #include <linux/module.h>
 #include <linux/slab.h>
+#include <linux/dmi.h>
 
 #include <acpi/acpi.h>
 #include <acpi/acpixf.h>
@@ -20,6 +23,21 @@
 
 #define ATK_HID "ATK0110"
 
+static bool new_if;
+module_param(new_if, bool, 0);
+MODULE_PARM_DESC(new_if, "Override detection heuristic and force the use of the new ATK0110 interface");
+
+static const struct dmi_system_id __initconst atk_force_new_if[] = {
+	{
+		/* Old interface has broken MCH temp monitoring */
+		.ident = "Asus Sabertooth X58",
+		.matches = {
+			DMI_MATCH(DMI_BOARD_NAME, "SABERTOOTH X58")
+		}
+	},
+	{ }
+};
+
 /* Minimum time between readings, enforced in order to avoid
  * hogging the CPU.
  */
@@ -1300,7 +1318,9 @@ static int atk_probe_if(struct atk_data
 	 * analysis of multiple DSDTs indicates that when both interfaces
 	 * are present the new one (GGRP/GITM) is not functional.
 	 */
-	if (data->rtmp_handle && data->rvlt_handle && data->rfan_handle)
+	if (new_if)
+		dev_info(dev, "Overriding interface detection\n");
+	if (data->rtmp_handle && data->rvlt_handle && data->rfan_handle && !new_if)
 		data->old_interface = true;
 	else if (data->enumerate_handle && data->read_handle &&
 			data->write_handle)
@@ -1414,14 +1434,16 @@ static int __init atk0110_init(void)
 
 	/* Make sure it's safe to access the device through ACPI */
 	if (!acpi_resources_are_enforced()) {
-		pr_err("atk: Resources not safely usable due to "
-		       "acpi_enforce_resources kernel parameter\n");
+		pr_err("Resources not safely usable due to acpi_enforce_resources kernel parameter\n");
 		return -EBUSY;
 	}
 
+	if (dmi_check_system(atk_force_new_if))
+		new_if = true;
+
 	ret = acpi_bus_register_driver(&atk_driver);
 	if (ret)
-		pr_info("atk: acpi_bus_register_driver failed: %d\n", ret);
+		pr_info("acpi_bus_register_driver failed: %d\n", ret);
 
 	return ret;
 }
diff -druNp linux-libre-2.6.37-gnu1/drivers/hwmon/coretemp.c linux-libre-2.6.38-gnu1/drivers/hwmon/coretemp.c
--- linux-libre-2.6.37-gnu1/drivers/hwmon/coretemp.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hwmon/coretemp.c	2011-03-14 21:20:32.000000000 -0400
@@ -20,6 +20,8 @@
  * 02110-1301 USA.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
@@ -445,8 +447,8 @@ static int __cpuinit coretemp_device_add
 	 * without thermal sensors will be filtered out.
 	 */
 	if (!cpu_has(c, X86_FEATURE_DTS)) {
-		printk(KERN_INFO DRVNAME ": CPU (model=0x%x)"
-		       " has no thermal sensor.\n", c->x86_model);
+		pr_info("CPU (model=0x%x) has no thermal sensor\n",
+			c->x86_model);
 		return 0;
 	}
 
@@ -466,7 +468,7 @@ static int __cpuinit coretemp_device_add
 	pdev = platform_device_alloc(DRVNAME, cpu);
 	if (!pdev) {
 		err = -ENOMEM;
-		printk(KERN_ERR DRVNAME ": Device allocation failed\n");
+		pr_err("Device allocation failed\n");
 		goto exit;
 	}
 
@@ -478,8 +480,7 @@ static int __cpuinit coretemp_device_add
 
 	err = platform_device_add(pdev);
 	if (err) {
-		printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n",
-		       err);
+		pr_err("Device addition failed (%d)\n", err);
 		goto exit_device_free;
 	}
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/hwmon/dme1737.c linux-libre-2.6.38-gnu1/drivers/hwmon/dme1737.c
--- linux-libre-2.6.37-gnu1/drivers/hwmon/dme1737.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hwmon/dme1737.c	2011-03-14 21:20:32.000000000 -0400
@@ -25,6 +25,8 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
@@ -75,12 +77,14 @@ enum chips { dme1737, sch5027, sch311x,
  * in4   +12V
  * in5   VTR   (+3.3V stby)
  * in6   Vbat
+ * in7   Vtrip (sch5127 only)
  *
  * --------------------------------------------------------------------- */
 
-/* Voltages (in) numbered 0-6 (ix) */
-#define	DME1737_REG_IN(ix)		((ix) < 5 ? 0x20 + (ix) \
-						  : 0x94 + (ix))
+/* Voltages (in) numbered 0-7 (ix) */
+#define	DME1737_REG_IN(ix)		((ix) < 5 ? 0x20 + (ix) : \
+					 (ix) < 7 ? 0x94 + (ix) : \
+						    0x1f)
 #define	DME1737_REG_IN_MIN(ix)		((ix) < 5 ? 0x44 + (ix) * 2 \
 						  : 0x91 + (ix) * 2)
 #define	DME1737_REG_IN_MAX(ix)		((ix) < 5 ? 0x45 + (ix) * 2 \
@@ -99,10 +103,11 @@ enum chips { dme1737, sch5027, sch311x,
  *    IN_TEMP_LSB(1) = [temp3, temp1]
  *    IN_TEMP_LSB(2) = [in4, temp2]
  *    IN_TEMP_LSB(3) = [in3, in0]
- *    IN_TEMP_LSB(4) = [in2, in1] */
+ *    IN_TEMP_LSB(4) = [in2, in1]
+ *    IN_TEMP_LSB(5) = [res, in7] */
 #define DME1737_REG_IN_TEMP_LSB(ix)	(0x84 + (ix))
-static const u8 DME1737_REG_IN_LSB[] = {3, 4, 4, 3, 2, 0, 0};
-static const u8 DME1737_REG_IN_LSB_SHL[] = {4, 4, 0, 0, 0, 0, 4};
+static const u8 DME1737_REG_IN_LSB[] = {3, 4, 4, 3, 2, 0, 0, 5};
+static const u8 DME1737_REG_IN_LSB_SHL[] = {4, 4, 0, 0, 0, 0, 4, 4};
 static const u8 DME1737_REG_TEMP_LSB[] = {1, 2, 1};
 static const u8 DME1737_REG_TEMP_LSB_SHL[] = {4, 4, 0};
 
@@ -143,7 +148,7 @@ static const u8 DME1737_REG_TEMP_LSB_SHL
 #define DME1737_REG_ALARM1		0x41
 #define DME1737_REG_ALARM2		0x42
 #define DME1737_REG_ALARM3		0x83
-static const u8 DME1737_BIT_ALARM_IN[] = {0, 1, 2, 3, 8, 16, 17};
+static const u8 DME1737_BIT_ALARM_IN[] = {0, 1, 2, 3, 8, 16, 17, 18};
 static const u8 DME1737_BIT_ALARM_TEMP[] = {4, 5, 6};
 static const u8 DME1737_BIT_ALARM_FAN[] = {10, 11, 12, 13, 22, 23};
 
@@ -188,6 +193,7 @@ static const u8 DME1737_BIT_ALARM_FAN[]
 #define HAS_PWM_MIN		(1 << 4)		/* bit 4 */
 #define HAS_FAN(ix)		(1 << ((ix) + 5))	/* bits 5-10 */
 #define HAS_PWM(ix)		(1 << ((ix) + 11))	/* bits 11-16 */
+#define HAS_IN7			(1 << 17)		/* bit 17 */
 
 /* ---------------------------------------------------------------------
  * Data structures and manipulation thereof
@@ -211,9 +217,9 @@ struct dme1737_data {
 	u32 has_features;
 
 	/* Register values */
-	u16 in[7];
-	u8  in_min[7];
-	u8  in_max[7];
+	u16 in[8];
+	u8  in_min[8];
+	u8  in_max[8];
 	s16 temp[3];
 	s8  temp_min[3];
 	s8  temp_max[3];
@@ -245,7 +251,7 @@ static const int IN_NOMINAL_SCH311x[] =
 static const int IN_NOMINAL_SCH5027[] = {5000, 2250, 3300, 1125, 1125, 3300,
 					 3300};
 static const int IN_NOMINAL_SCH5127[] = {2500, 2250, 3300, 1125, 1125, 3300,
-					 3300};
+					 3300, 1500};
 #define IN_NOMINAL(type)	((type) == sch311x ? IN_NOMINAL_SCH311x : \
 				 (type) == sch5027 ? IN_NOMINAL_SCH5027 : \
 				 (type) == sch5127 ? IN_NOMINAL_SCH5127 : \
@@ -578,7 +584,7 @@ static struct dme1737_data *dme1737_upda
 {
 	struct dme1737_data *data = dev_get_drvdata(dev);
 	int ix;
-	u8 lsb[5];
+	u8 lsb[6];
 
 	mutex_lock(&data->update_lock);
 
@@ -601,6 +607,9 @@ static struct dme1737_data *dme1737_upda
 			/* Voltage inputs are stored as 16 bit values even
 			 * though they have only 12 bits resolution. This is
 			 * to make it consistent with the temp inputs. */
+			if (ix == 7 && !(data->has_features & HAS_IN7)) {
+				continue;
+			}
 			data->in[ix] = dme1737_read(data,
 					DME1737_REG_IN(ix)) << 8;
 			data->in_min[ix] = dme1737_read(data,
@@ -633,10 +642,16 @@ static struct dme1737_data *dme1737_upda
 		 * which the registers are read (MSB first, then LSB) is
 		 * important! */
 		for (ix = 0; ix < ARRAY_SIZE(lsb); ix++) {
+			if (ix == 5 && !(data->has_features & HAS_IN7)) {
+				continue;
+			}
 			lsb[ix] = dme1737_read(data,
 					DME1737_REG_IN_TEMP_LSB(ix));
 		}
 		for (ix = 0; ix < ARRAY_SIZE(data->in); ix++) {
+			if (ix == 7 && !(data->has_features & HAS_IN7)) {
+				continue;
+			}
 			data->in[ix] |= (lsb[DME1737_REG_IN_LSB[ix]] <<
 					DME1737_REG_IN_LSB_SHL[ix]) & 0xf0;
 		}
@@ -760,7 +775,7 @@ static struct dme1737_data *dme1737_upda
 
 /* ---------------------------------------------------------------------
  * Voltage sysfs attributes
- * ix = [0-5]
+ * ix = [0-7]
  * --------------------------------------------------------------------- */
 
 #define SYS_IN_INPUT	0
@@ -1437,7 +1452,7 @@ static ssize_t show_name(struct device *
  * Sysfs device attribute defines and structs
  * --------------------------------------------------------------------- */
 
-/* Voltages 0-6 */
+/* Voltages 0-7 */
 
 #define SENSOR_DEVICE_ATTR_IN(ix) \
 static SENSOR_DEVICE_ATTR_2(in##ix##_input, S_IRUGO, \
@@ -1456,6 +1471,7 @@ SENSOR_DEVICE_ATTR_IN(3);
 SENSOR_DEVICE_ATTR_IN(4);
 SENSOR_DEVICE_ATTR_IN(5);
 SENSOR_DEVICE_ATTR_IN(6);
+SENSOR_DEVICE_ATTR_IN(7);
 
 /* Temperatures 1-3 */
 
@@ -1574,7 +1590,7 @@ static DEVICE_ATTR(name, S_IRUGO, show_n
  * created unconditionally. The attributes that need modification of their
  * permissions are created read-only and write permissions are added or removed
  * on the fly when required */
-static struct attribute *dme1737_attr[] ={
+static struct attribute *dme1737_attr[] = {
 	/* Voltages */
 	&sensor_dev_attr_in0_input.dev_attr.attr,
 	&sensor_dev_attr_in0_min.dev_attr.attr,
@@ -1679,7 +1695,7 @@ static const struct attribute_group dme1
 };
 
 
-/* The following struct holds temp zone hysteresis  related attributes, which
+/* The following struct holds temp zone hysteresis related attributes, which
  * are not available in all chips. The following chips support them:
  * DME1737, SCH311x */
 static struct attribute *dme1737_zone_hyst_attr[] = {
@@ -1693,6 +1709,21 @@ static const struct attribute_group dme1
 	.attrs = dme1737_zone_hyst_attr,
 };
 
+/* The following struct holds voltage in7 related attributes, which
+ * are not available in all chips. The following chips support them:
+ * SCH5127 */
+static struct attribute *dme1737_in7_attr[] = {
+	&sensor_dev_attr_in7_input.dev_attr.attr,
+	&sensor_dev_attr_in7_min.dev_attr.attr,
+	&sensor_dev_attr_in7_max.dev_attr.attr,
+	&sensor_dev_attr_in7_alarm.dev_attr.attr,
+	NULL
+};
+
+static const struct attribute_group dme1737_in7_group = {
+	.attrs = dme1737_in7_attr,
+};
+
 /* The following structs hold the PWM attributes, some of which are optional.
  * Their creation depends on the chip configuration which is determined during
  * module load. */
@@ -1984,6 +2015,9 @@ static void dme1737_remove_files(struct
 	if (data->has_features & HAS_ZONE_HYST) {
 		sysfs_remove_group(&dev->kobj, &dme1737_zone_hyst_group);
 	}
+	if (data->has_features & HAS_IN7) {
+		sysfs_remove_group(&dev->kobj, &dme1737_in7_group);
+	}
 	sysfs_remove_group(&dev->kobj, &dme1737_group);
 
 	if (!data->client) {
@@ -1997,43 +2031,58 @@ static int dme1737_create_files(struct d
 	int err, ix;
 
 	/* Create a name attribute for ISA devices */
-	if (!data->client &&
-	    (err = sysfs_create_file(&dev->kobj, &dev_attr_name.attr))) {
-		goto exit;
+	if (!data->client) {
+		err = sysfs_create_file(&dev->kobj, &dev_attr_name.attr);
+		if (err) {
+			goto exit;
+		}
 	}
 
 	/* Create standard sysfs attributes */
-	if ((err = sysfs_create_group(&dev->kobj, &dme1737_group))) {
+	err = sysfs_create_group(&dev->kobj, &dme1737_group);
+	if (err) {
 		goto exit_remove;
 	}
 
 	/* Create chip-dependent sysfs attributes */
-	if ((data->has_features & HAS_TEMP_OFFSET) &&
-	    (err = sysfs_create_group(&dev->kobj,
-				      &dme1737_temp_offset_group))) {
-		goto exit_remove;
+	if (data->has_features & HAS_TEMP_OFFSET) {
+		err = sysfs_create_group(&dev->kobj,
+					 &dme1737_temp_offset_group);
+		if (err) {
+			goto exit_remove;
+		}
 	}
-	if ((data->has_features & HAS_VID) &&
-	    (err = sysfs_create_group(&dev->kobj,
-				      &dme1737_vid_group))) {
-		goto exit_remove;
+	if (data->has_features & HAS_VID) {
+		err = sysfs_create_group(&dev->kobj, &dme1737_vid_group);
+		if (err) {
+			goto exit_remove;
+		}
 	}
-	if ((data->has_features & HAS_ZONE3) &&
-	    (err = sysfs_create_group(&dev->kobj,
-				      &dme1737_zone3_group))) {
-		goto exit_remove;
+	if (data->has_features & HAS_ZONE3) {
+		err = sysfs_create_group(&dev->kobj, &dme1737_zone3_group);
+		if (err) {
+			goto exit_remove;
+		}
 	}
-	if ((data->has_features & HAS_ZONE_HYST) &&
-	    (err = sysfs_create_group(&dev->kobj,
-				      &dme1737_zone_hyst_group))) {
-		goto exit_remove;
+	if (data->has_features & HAS_ZONE_HYST) {
+		err = sysfs_create_group(&dev->kobj, &dme1737_zone_hyst_group);
+		if (err) {
+			goto exit_remove;
+		}
+	}
+	if (data->has_features & HAS_IN7) {
+		err = sysfs_create_group(&dev->kobj, &dme1737_in7_group);
+		if (err) {
+			goto exit_remove;
+		}
 	}
 
 	/* Create fan sysfs attributes */
 	for (ix = 0; ix < ARRAY_SIZE(dme1737_fan_group); ix++) {
 		if (data->has_features & HAS_FAN(ix)) {
-			if ((err = sysfs_create_group(&dev->kobj,
-						&dme1737_fan_group[ix]))) {
+			err = sysfs_create_group(&dev->kobj,
+						 &dme1737_fan_group[ix]);
+			if (err) {
 				goto exit_remove;
 			}
 		}
@@ -2042,14 +2091,17 @@ static int dme1737_create_files(struct d
 	/* Create PWM sysfs attributes */
 	for (ix = 0; ix < ARRAY_SIZE(dme1737_pwm_group); ix++) {
 		if (data->has_features & HAS_PWM(ix)) {
-			if ((err = sysfs_create_group(&dev->kobj,
-						&dme1737_pwm_group[ix]))) {
+			err = sysfs_create_group(&dev->kobj,
+						 &dme1737_pwm_group[ix]);
+			if (err) {
 				goto exit_remove;
 			}
-			if ((data->has_features & HAS_PWM_MIN) && ix < 3 &&
-			    (err = sysfs_create_file(&dev->kobj,
-					dme1737_auto_pwm_min_attr[ix]))) {
-				goto exit_remove;
+			if ((data->has_features & HAS_PWM_MIN) && (ix < 3)) {
+				err = sysfs_create_file(&dev->kobj,
+						dme1737_auto_pwm_min_attr[ix]);
+				if (err) {
+					goto exit_remove;
+				}
 			}
 		}
 	}
@@ -2186,7 +2238,7 @@ static int dme1737_init_device(struct de
 		data->has_features |= HAS_ZONE3;
 		break;
 	case sch5127:
-		data->has_features |= HAS_FAN(2) | HAS_PWM(2);
+		data->has_features |= HAS_FAN(2) | HAS_PWM(2) | HAS_IN7;
 		break;
 	default:
 		break;
@@ -2279,8 +2331,9 @@ static int dme1737_i2c_get_features(int
 	dme1737_sio_outb(sio_cip, 0x07, 0x0a);
 
 	/* Get the base address of the runtime registers */
-	if (!(addr = (dme1737_sio_inb(sio_cip, 0x60) << 8) |
-		      dme1737_sio_inb(sio_cip, 0x61))) {
+	addr = (dme1737_sio_inb(sio_cip, 0x60) << 8) |
+		dme1737_sio_inb(sio_cip, 0x61);
+	if (!addr) {
 		err = -ENODEV;
 		goto exit;
 	}
@@ -2361,13 +2414,15 @@ static int dme1737_i2c_probe(struct i2c_
 	mutex_init(&data->update_lock);
 
 	/* Initialize the DME1737 chip */
-	if ((err = dme1737_init_device(dev))) {
+	err = dme1737_init_device(dev);
+	if (err) {
 		dev_err(dev, "Failed to initialize device.\n");
 		goto exit_kfree;
 	}
 
 	/* Create sysfs files */
-	if ((err = dme1737_create_files(dev))) {
+	err = dme1737_create_files(dev);
+	if (err) {
 		dev_err(dev, "Failed to create sysfs files.\n");
 		goto exit_kfree;
 	}
@@ -2444,9 +2499,10 @@ static int __init dme1737_isa_detect(int
 	dme1737_sio_outb(sio_cip, 0x07, 0x0a);
 
 	/* Get the base address of the runtime registers */
-	if (!(base_addr = (dme1737_sio_inb(sio_cip, 0x60) << 8) |
-			   dme1737_sio_inb(sio_cip, 0x61))) {
-		printk(KERN_ERR "dme1737: Base address not set.\n");
+	base_addr = (dme1737_sio_inb(sio_cip, 0x60) << 8) |
+		     dme1737_sio_inb(sio_cip, 0x61);
+	if (!base_addr) {
+		pr_err("Base address not set\n");
 		err = -ENODEV;
 		goto exit;
 	}
@@ -2474,21 +2530,22 @@ static int __init dme1737_isa_device_add
 	if (err)
 		goto exit;
 
-	if (!(pdev = platform_device_alloc("dme1737", addr))) {
-		printk(KERN_ERR "dme1737: Failed to allocate device.\n");
+	pdev = platform_device_alloc("dme1737", addr);
+	if (!pdev) {
+		pr_err("Failed to allocate device\n");
 		err = -ENOMEM;
 		goto exit;
 	}
 
-	if ((err = platform_device_add_resources(pdev, &res, 1))) {
-		printk(KERN_ERR "dme1737: Failed to add device resource "
-		       "(err = %d).\n", err);
+	err = platform_device_add_resources(pdev, &res, 1);
+	if (err) {
+		pr_err("Failed to add device resource (err = %d)\n", err);
 		goto exit_device_put;
 	}
 
-	if ((err = platform_device_add(pdev))) {
-		printk(KERN_ERR "dme1737: Failed to add device (err = %d).\n",
-		       err);
+	err = platform_device_add(pdev);
+	if (err) {
+		pr_err("Failed to add device (err = %d)\n", err);
 		goto exit_device_put;
 	}
 
@@ -2514,11 +2571,12 @@ static int __devinit dme1737_isa_probe(s
 		dev_err(dev, "Failed to request region 0x%04x-0x%04x.\n",
 			(unsigned short)res->start,
 			(unsigned short)res->start + DME1737_EXTENT - 1);
-                err = -EBUSY;
-                goto exit;
-        }
+		err = -EBUSY;
+		goto exit;
+	}
 
-	if (!(data = kzalloc(sizeof(struct dme1737_data), GFP_KERNEL))) {
+	data = kzalloc(sizeof(struct dme1737_data), GFP_KERNEL);
+	if (!data) {
 		err = -ENOMEM;
 		goto exit_release_region;
 	}
@@ -2565,13 +2623,15 @@ static int __devinit dme1737_isa_probe(s
 		 data->type == sch5127 ? "SCH5127" : "SCH311x", data->addr);
 
 	/* Initialize the chip */
-	if ((err = dme1737_init_device(dev))) {
+	err = dme1737_init_device(dev);
+	if (err) {
 		dev_err(dev, "Failed to initialize device.\n");
 		goto exit_kfree;
 	}
 
 	/* Create sysfs files */
-	if ((err = dme1737_create_files(dev))) {
+	err = dme1737_create_files(dev);
+	if (err) {
 		dev_err(dev, "Failed to create sysfs files.\n");
 		goto exit_kfree;
 	}
@@ -2628,7 +2688,8 @@ static int __init dme1737_init(void)
 	int err;
 	unsigned short addr;
 
-	if ((err = i2c_add_driver(&dme1737_i2c_driver))) {
+	err = i2c_add_driver(&dme1737_i2c_driver);
+	if (err) {
 		goto exit;
 	}
 
@@ -2641,12 +2702,14 @@ static int __init dme1737_init(void)
 		return 0;
 	}
 
-	if ((err = platform_driver_register(&dme1737_isa_driver))) {
+	err = platform_driver_register(&dme1737_isa_driver);
+	if (err) {
 		goto exit_del_i2c_driver;
 	}
 
 	/* Sets global pdev as a side effect */
-	if ((err = dme1737_isa_device_add(addr))) {
+	err = dme1737_isa_device_add(addr);
+	if (err) {
 		goto exit_del_isa_driver;
 	}
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/hwmon/ds620.c linux-libre-2.6.38-gnu1/drivers/hwmon/ds620.c
--- linux-libre-2.6.37-gnu1/drivers/hwmon/ds620.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hwmon/ds620.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,337 @@
+/*
+ *  ds620.c - Support for temperature sensor and thermostat DS620
+ *
+ *  Copyright (C) 2010, 2011 Roland Stigge <stigge@antcom.de>
+ *
+ *  based on ds1621.c by Christian W. Zuckschwerdt  <zany@triq.net>
+ *
+ *  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/jiffies.h>
+#include <linux/i2c.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/err.h>
+#include <linux/mutex.h>
+#include <linux/sysfs.h>
+#include <linux/i2c/ds620.h>
+
+/*
+ * Many DS620 constants specified below
+ *  15   14   13   12   11   10   09    08
+ * |Done|NVB |THF |TLF |R1  |R0  |AUTOC|1SHOT|
+ *
+ *  07   06   05   04   03   02   01    00
+ * |PO2 |PO1 |A2  |A1  |A0  |    |     |     |
+ */
+#define DS620_REG_CONFIG_DONE		0x8000
+#define DS620_REG_CONFIG_NVB		0x4000
+#define DS620_REG_CONFIG_THF		0x2000
+#define DS620_REG_CONFIG_TLF		0x1000
+#define DS620_REG_CONFIG_R1		0x0800
+#define DS620_REG_CONFIG_R0		0x0400
+#define DS620_REG_CONFIG_AUTOC		0x0200
+#define DS620_REG_CONFIG_1SHOT		0x0100
+#define DS620_REG_CONFIG_PO2		0x0080
+#define DS620_REG_CONFIG_PO1		0x0040
+#define DS620_REG_CONFIG_A2		0x0020
+#define DS620_REG_CONFIG_A1		0x0010
+#define DS620_REG_CONFIG_A0		0x0008
+
+/* The DS620 registers */
+static const u8 DS620_REG_TEMP[3] = {
+	0xAA,			/* input, word, RO */
+	0xA2,			/* min, word, RW */
+	0xA0,			/* max, word, RW */
+};
+
+#define DS620_REG_CONF		0xAC	/* word, RW */
+#define DS620_COM_START		0x51	/* no data */
+#define DS620_COM_STOP		0x22	/* no data */
+
+/* Each client has this additional data */
+struct ds620_data {
+	struct device *hwmon_dev;
+	struct mutex update_lock;
+	char valid;		/* !=0 if following fields are valid */
+	unsigned long last_updated;	/* In jiffies */
+
+	u16 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));
+
+	/* switch to continuous conversion mode */
+	new_conf &= ~DS620_REG_CONFIG_1SHOT;
+	/* already high at power-on, but don't trust the BIOS! */
+	new_conf |= DS620_REG_CONFIG_PO2;
+	/* thermostat mode according to platform data */
+	if (ds620_info && ds620_info->pomode == 1)
+		new_conf &= ~DS620_REG_CONFIG_PO1; /* PO_LOW */
+	else if (ds620_info && ds620_info->pomode == 2)
+		new_conf |= DS620_REG_CONFIG_PO1; /* PO_HIGH */
+	else
+		new_conf &= ~DS620_REG_CONFIG_PO2; /* always low */
+	/* with highest precision */
+	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));
+
+	/* start conversion */
+	i2c_smbus_write_byte(client, DS620_COM_START);
+}
+
+static struct ds620_data *ds620_update_client(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct ds620_data *data = i2c_get_clientdata(client);
+	struct ds620_data *ret = data;
+
+	mutex_lock(&data->update_lock);
+
+	if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
+	    || !data->valid) {
+		int i;
+		int res;
+
+		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]);
+			if (res < 0) {
+				ret = ERR_PTR(res);
+				goto abort;
+			}
+
+			data->temp[i] = res;
+		}
+
+		data->last_updated = jiffies;
+		data->valid = 1;
+	}
+abort:
+	mutex_unlock(&data->update_lock);
+
+	return ret;
+}
+
+static ssize_t show_temp(struct device *dev, struct device_attribute *da,
+			 char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+	struct ds620_data *data = ds620_update_client(dev);
+
+	if (IS_ERR(data))
+		return PTR_ERR(data);
+
+	return sprintf(buf, "%d\n", ((data->temp[attr->index] / 8) * 625) / 10);
+}
+
+static ssize_t set_temp(struct device *dev, struct device_attribute *da,
+			const char *buf, size_t count)
+{
+	int res;
+	long val;
+
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+	struct i2c_client *client = to_i2c_client(dev);
+	struct ds620_data *data = i2c_get_clientdata(client);
+
+	res = strict_strtol(buf, 10, &val);
+
+	if (res)
+		return res;
+
+	val = (val * 10 / 625) * 8;
+
+	mutex_lock(&data->update_lock);
+	data->temp[attr->index] = val;
+	ds620_write_temp(client, DS620_REG_TEMP[attr->index],
+			 data->temp[attr->index]);
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+static ssize_t show_alarm(struct device *dev, struct device_attribute *da,
+			  char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+	struct ds620_data *data = ds620_update_client(dev);
+	struct i2c_client *client = to_i2c_client(dev);
+	u16 conf, new_conf;
+	int res;
+
+	if (IS_ERR(data))
+		return PTR_ERR(data);
+
+	/* reset alarms if necessary */
+	res = i2c_smbus_read_word_data(client, DS620_REG_CONF);
+	if (res < 0)
+		return res;
+
+	conf = swab16(res);
+	new_conf = conf;
+	new_conf &= ~attr->index;
+	if (conf != new_conf) {
+		res = i2c_smbus_write_word_data(client, DS620_REG_CONF,
+						swab16(new_conf));
+		if (res < 0)
+			return res;
+	}
+
+	return sprintf(buf, "%d\n", !!(conf & attr->index));
+}
+
+static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0);
+static SENSOR_DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO, show_temp, set_temp, 1);
+static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp, set_temp, 2);
+static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO, show_alarm, NULL,
+			  DS620_REG_CONFIG_TLF);
+static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL,
+			  DS620_REG_CONFIG_THF);
+
+static struct attribute *ds620_attributes[] = {
+	&sensor_dev_attr_temp1_input.dev_attr.attr,
+	&sensor_dev_attr_temp1_min.dev_attr.attr,
+	&sensor_dev_attr_temp1_max.dev_attr.attr,
+	&sensor_dev_attr_temp1_min_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp1_max_alarm.dev_attr.attr,
+	NULL
+};
+
+static const struct attribute_group ds620_group = {
+	.attrs = ds620_attributes,
+};
+
+static int ds620_probe(struct i2c_client *client,
+		       const struct i2c_device_id *id)
+{
+	struct ds620_data *data;
+	int err;
+
+	data = kzalloc(sizeof(struct ds620_data), GFP_KERNEL);
+	if (!data) {
+		err = -ENOMEM;
+		goto exit;
+	}
+
+	i2c_set_clientdata(client, data);
+	mutex_init(&data->update_lock);
+
+	/* Initialize the DS620 chip */
+	ds620_init_client(client);
+
+	/* Register sysfs hooks */
+	err = sysfs_create_group(&client->dev.kobj, &ds620_group);
+	if (err)
+		goto exit_free;
+
+	data->hwmon_dev = hwmon_device_register(&client->dev);
+	if (IS_ERR(data->hwmon_dev)) {
+		err = PTR_ERR(data->hwmon_dev);
+		goto exit_remove_files;
+	}
+
+	dev_info(&client->dev, "temperature sensor found\n");
+
+	return 0;
+
+exit_remove_files:
+	sysfs_remove_group(&client->dev.kobj, &ds620_group);
+exit_free:
+	kfree(data);
+exit:
+	return err;
+}
+
+static int ds620_remove(struct i2c_client *client)
+{
+	struct ds620_data *data = i2c_get_clientdata(client);
+
+	hwmon_device_unregister(data->hwmon_dev);
+	sysfs_remove_group(&client->dev.kobj, &ds620_group);
+
+	kfree(data);
+
+	return 0;
+}
+
+static const struct i2c_device_id ds620_id[] = {
+	{"ds620", 0},
+	{}
+};
+
+MODULE_DEVICE_TABLE(i2c, ds620_id);
+
+/* This is the driver that will be inserted */
+static struct i2c_driver ds620_driver = {
+	.class = I2C_CLASS_HWMON,
+	.driver = {
+		   .name = "ds620",
+	},
+	.probe = ds620_probe,
+	.remove = ds620_remove,
+	.id_table = ds620_id,
+};
+
+static int __init ds620_init(void)
+{
+	return i2c_add_driver(&ds620_driver);
+}
+
+static void __exit ds620_exit(void)
+{
+	i2c_del_driver(&ds620_driver);
+}
+
+MODULE_AUTHOR("Roland Stigge <stigge@antcom.de>");
+MODULE_DESCRIPTION("DS620 driver");
+MODULE_LICENSE("GPL");
+
+module_init(ds620_init);
+module_exit(ds620_exit);
diff -druNp linux-libre-2.6.37-gnu1/drivers/hwmon/emc1403.c linux-libre-2.6.38-gnu1/drivers/hwmon/emc1403.c
--- linux-libre-2.6.37-gnu1/drivers/hwmon/emc1403.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hwmon/emc1403.c	2011-03-14 21:20:32.000000000 -0400
@@ -269,23 +269,30 @@ static int emc1403_detect(struct i2c_cli
 			struct i2c_board_info *info)
 {
 	int id;
-	/* Check if thermal chip is SMSC and EMC1403 */
+	/* Check if thermal chip is SMSC and EMC1403 or EMC1423 */
 
 	id = i2c_smbus_read_byte_data(client, THERMAL_SMSC_ID_REG);
 	if (id != 0x5d)
 		return -ENODEV;
 
+	id = i2c_smbus_read_byte_data(client, THERMAL_PID_REG);
+	switch (id) {
+	case 0x21:
+		strlcpy(info->type, "emc1403", I2C_NAME_SIZE);
+		break;
+	case 0x23:
+		strlcpy(info->type, "emc1423", I2C_NAME_SIZE);
+		break;
 	/* Note: 0x25 is the 1404 which is very similar and this
 	   driver could be extended */
-	id = i2c_smbus_read_byte_data(client, THERMAL_PID_REG);
-	if (id != 0x21)
+	default:
 		return -ENODEV;
+	}
 
 	id = i2c_smbus_read_byte_data(client, THERMAL_REVISION_REG);
 	if (id != 0x01)
 		return -ENODEV;
 
-	strlcpy(info->type, "emc1403", I2C_NAME_SIZE);
 	return 0;
 }
 
@@ -337,11 +344,12 @@ static int emc1403_remove(struct i2c_cli
 }
 
 static const unsigned short emc1403_address_list[] = {
-	0x18, 0x2a, 0x4c, 0x4d, I2C_CLIENT_END
+	0x18, 0x29, 0x4c, 0x4d, I2C_CLIENT_END
 };
 
 static const struct i2c_device_id emc1403_idtable[] = {
 	{ "emc1403", 0 },
+	{ "emc1423", 0 },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, emc1403_idtable);
diff -druNp linux-libre-2.6.37-gnu1/drivers/hwmon/f71805f.c linux-libre-2.6.38-gnu1/drivers/hwmon/f71805f.c
--- linux-libre-2.6.37-gnu1/drivers/hwmon/f71805f.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hwmon/f71805f.c	2011-03-14 21:20:32.000000000 -0400
@@ -28,6 +28,8 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
@@ -1309,7 +1311,7 @@ static int __devinit f71805f_probe(struc
 
 	if (!(data = kzalloc(sizeof(struct f71805f_data), GFP_KERNEL))) {
 		err = -ENOMEM;
-		printk(KERN_ERR DRVNAME ": Out of memory\n");
+		pr_err("Out of memory\n");
 		goto exit;
 	}
 
@@ -1451,7 +1453,7 @@ static int __init f71805f_device_add(uns
 	pdev = platform_device_alloc(DRVNAME, address);
 	if (!pdev) {
 		err = -ENOMEM;
-		printk(KERN_ERR DRVNAME ": Device allocation failed\n");
+		pr_err("Device allocation failed\n");
 		goto exit;
 	}
 
@@ -1462,22 +1464,20 @@ static int __init f71805f_device_add(uns
 
 	err = platform_device_add_resources(pdev, &res, 1);
 	if (err) {
-		printk(KERN_ERR DRVNAME ": Device resource addition failed "
-		       "(%d)\n", err);
+		pr_err("Device resource addition failed (%d)\n", err);
 		goto exit_device_put;
 	}
 
 	err = platform_device_add_data(pdev, sio_data,
 				       sizeof(struct f71805f_sio_data));
 	if (err) {
-		printk(KERN_ERR DRVNAME ": Platform data allocation failed\n");
+		pr_err("Platform data allocation failed\n");
 		goto exit_device_put;
 	}
 
 	err = platform_device_add(pdev);
 	if (err) {
-		printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n",
-		       err);
+		pr_err("Device addition failed (%d)\n", err);
 		goto exit_device_put;
 	}
 
@@ -1516,30 +1516,27 @@ static int __init f71805f_find(int sioad
 		sio_data->fnsel1 = superio_inb(sioaddr, SIO_REG_FNSEL1);
 		break;
 	default:
-		printk(KERN_INFO DRVNAME ": Unsupported Fintek device, "
-		       "skipping\n");
+		pr_info("Unsupported Fintek device, skipping\n");
 		goto exit;
 	}
 
 	superio_select(sioaddr, F71805F_LD_HWM);
 	if (!(superio_inb(sioaddr, SIO_REG_ENABLE) & 0x01)) {
-		printk(KERN_WARNING DRVNAME ": Device not activated, "
-		       "skipping\n");
+		pr_warn("Device not activated, skipping\n");
 		goto exit;
 	}
 
 	*address = superio_inw(sioaddr, SIO_REG_ADDR);
 	if (*address == 0) {
-		printk(KERN_WARNING DRVNAME ": Base address not set, "
-		       "skipping\n");
+		pr_warn("Base address not set, skipping\n");
 		goto exit;
 	}
 	*address &= ~(REGION_LENGTH - 1);	/* Ignore 3 LSB */
 
 	err = 0;
-	printk(KERN_INFO DRVNAME ": Found %s chip at %#x, revision %u\n",
-	       names[sio_data->kind], *address,
-	       superio_inb(sioaddr, SIO_REG_DEVREV));
+	pr_info("Found %s chip at %#x, revision %u\n",
+		names[sio_data->kind], *address,
+		superio_inb(sioaddr, SIO_REG_DEVREV));
 
 exit:
 	superio_exit(sioaddr);
diff -druNp linux-libre-2.6.37-gnu1/drivers/hwmon/f71882fg.c linux-libre-2.6.38-gnu1/drivers/hwmon/f71882fg.c
--- linux-libre-2.6.37-gnu1/drivers/hwmon/f71882fg.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hwmon/f71882fg.c	2011-03-14 21:20:32.000000000 -0400
@@ -18,6 +18,8 @@
  *   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/slab.h>
@@ -35,7 +37,7 @@
 #define SIO_F71858FG_LD_HWM	0x02	/* Hardware monitor logical device */
 #define SIO_F71882FG_LD_HWM	0x04	/* Hardware monitor logical device */
 #define SIO_UNLOCK_KEY		0x87	/* Key to enable Super-I/O */
-#define SIO_LOCK_KEY		0xAA	/* Key to diasble Super-I/O */
+#define SIO_LOCK_KEY		0xAA	/* Key to disable Super-I/O */
 
 #define SIO_REG_LDSEL		0x07	/* Logical device select */
 #define SIO_REG_DEVID		0x20	/* Device ID (2 bytes) */
@@ -865,8 +867,7 @@ static inline int superio_enter(int base
 {
 	/* Don't step on other drivers' I/O space by accident */
 	if (!request_muxed_region(base, 2, DRVNAME)) {
-		printk(KERN_ERR DRVNAME ": I/O address 0x%04x already in use\n",
-				base);
+		pr_err("I/O address 0x%04x already in use\n", base);
 		return -EBUSY;
 	}
 
@@ -2110,7 +2111,6 @@ static int f71882fg_remove(struct platfo
 	int nr_fans = (data->type == f71882fg) ? 4 : 3;
 	u8 start_reg = f71882fg_read8(data, F71882FG_REG_START);
 
-	platform_set_drvdata(pdev, NULL);
 	if (data->hwmon_dev)
 		hwmon_device_unregister(data->hwmon_dev);
 
@@ -2177,6 +2177,7 @@ static int f71882fg_remove(struct platfo
 		}
 	}
 
+	platform_set_drvdata(pdev, NULL);
 	kfree(data);
 
 	return 0;
@@ -2192,7 +2193,7 @@ static int __init f71882fg_find(int sioa
 
 	devid = superio_inw(sioaddr, SIO_REG_MANID);
 	if (devid != SIO_FINTEK_ID) {
-		pr_debug(DRVNAME ": Not a Fintek device\n");
+		pr_debug("Not a Fintek device\n");
 		err = -ENODEV;
 		goto exit;
 	}
@@ -2215,8 +2216,8 @@ static int __init f71882fg_find(int sioa
 		sio_data->type = f8000;
 		break;
 	default:
-		printk(KERN_INFO DRVNAME ": Unsupported Fintek device: %04x\n",
-		       (unsigned int)devid);
+		pr_info("Unsupported Fintek device: %04x\n",
+			(unsigned int)devid);
 		err = -ENODEV;
 		goto exit;
 	}
@@ -2227,21 +2228,21 @@ static int __init f71882fg_find(int sioa
 		superio_select(sioaddr, SIO_F71882FG_LD_HWM);
 
 	if (!(superio_inb(sioaddr, SIO_REG_ENABLE) & 0x01)) {
-		printk(KERN_WARNING DRVNAME ": Device not activated\n");
+		pr_warn("Device not activated\n");
 		err = -ENODEV;
 		goto exit;
 	}
 
 	*address = superio_inw(sioaddr, SIO_REG_ADDR);
 	if (*address == 0) {
-		printk(KERN_WARNING DRVNAME ": Base address not set\n");
+		pr_warn("Base address not set\n");
 		err = -ENODEV;
 		goto exit;
 	}
 	*address &= ~(REGION_LENGTH - 1);	/* Ignore 3 LSB */
 
 	err = 0;
-	printk(KERN_INFO DRVNAME ": Found %s chip at %#x, revision %d\n",
+	pr_info("Found %s chip at %#x, revision %d\n",
 		f71882fg_names[sio_data->type],	(unsigned int)*address,
 		(int)superio_inb(sioaddr, SIO_REG_DEVREV));
 exit:
@@ -2270,20 +2271,20 @@ static int __init f71882fg_device_add(un
 
 	err = platform_device_add_resources(f71882fg_pdev, &res, 1);
 	if (err) {
-		printk(KERN_ERR DRVNAME ": Device resource addition failed\n");
+		pr_err("Device resource addition failed\n");
 		goto exit_device_put;
 	}
 
 	err = platform_device_add_data(f71882fg_pdev, sio_data,
 				       sizeof(struct f71882fg_sio_data));
 	if (err) {
-		printk(KERN_ERR DRVNAME ": Platform data allocation failed\n");
+		pr_err("Platform data allocation failed\n");
 		goto exit_device_put;
 	}
 
 	err = platform_device_add(f71882fg_pdev);
 	if (err) {
-		printk(KERN_ERR DRVNAME ": Device addition failed\n");
+		pr_err("Device addition failed\n");
 		goto exit_device_put;
 	}
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/hwmon/fschmd.c linux-libre-2.6.38-gnu1/drivers/hwmon/fschmd.c
--- linux-libre-2.6.37-gnu1/drivers/hwmon/fschmd.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hwmon/fschmd.c	2011-03-14 21:20:32.000000000 -0400
@@ -49,7 +49,6 @@
 #include <linux/kref.h>
 
 /* Addresses to scan */
-static DEFINE_MUTEX(watchdog_mutex);
 static const unsigned short normal_i2c[] = { 0x73, I2C_CLIENT_END };
 
 /* Insmod parameters */
@@ -850,7 +849,7 @@ static ssize_t watchdog_write(struct fil
 
 static long watchdog_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 {
-	static struct watchdog_info ident = {
+	struct watchdog_info ident = {
 		.options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT |
 				WDIOF_CARDRESET,
 		.identity = "FSC watchdog"
@@ -858,7 +857,6 @@ static long watchdog_ioctl(struct file *
 	int i, ret = 0;
 	struct fschmd_data *data = filp->private_data;
 
-	mutex_lock(&watchdog_mutex);
 	switch (cmd) {
 	case WDIOC_GETSUPPORT:
 		ident.firmware_version = data->revision;
@@ -915,7 +913,6 @@ static long watchdog_ioctl(struct file *
 	default:
 		ret = -ENOTTY;
 	}
-	mutex_unlock(&watchdog_mutex);
 	return ret;
 }
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/hwmon/hp_accel.c linux-libre-2.6.38-gnu1/drivers/hwmon/hp_accel.c
--- linux-libre-2.6.37-gnu1/drivers/hwmon/hp_accel.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hwmon/hp_accel.c	2011-03-14 21:20:32.000000000 -0400
@@ -20,6 +20,8 @@
  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/dmi.h>
@@ -147,7 +149,7 @@ int lis3lv02d_acpi_write(struct lis3lv02
 static int lis3lv02d_dmi_matched(const struct dmi_system_id *dmi)
 {
 	lis3_dev.ac = *((union axis_conversion *)dmi->driver_data);
-	printk(KERN_INFO DRIVER_NAME ": hardware type %s found.\n", dmi->ident);
+	pr_info("hardware type %s found\n", dmi->ident);
 
 	return 1;
 }
@@ -303,11 +305,10 @@ static int lis3lv02d_add(struct acpi_dev
 
 	/* If possible use a "standard" axes order */
 	if (lis3_dev.ac.x && lis3_dev.ac.y && lis3_dev.ac.z) {
-		printk(KERN_INFO DRIVER_NAME ": Using custom axes %d,%d,%d\n",
-		       lis3_dev.ac.x, lis3_dev.ac.y, lis3_dev.ac.z);
+		pr_info("Using custom axes %d,%d,%d\n",
+			lis3_dev.ac.x, lis3_dev.ac.y, lis3_dev.ac.z);
 	} else if (dmi_check_system(lis3lv02d_dmi_ids) == 0) {
-		printk(KERN_INFO DRIVER_NAME ": laptop model unknown, "
-				 "using default axes configuration\n");
+		pr_info("laptop model unknown, using default axes configuration\n");
 		lis3_dev.ac = lis3lv02d_axis_normal;
 	}
 
@@ -385,7 +386,7 @@ static int __init lis3lv02d_init_module(
 	if (ret < 0)
 		return ret;
 
-	printk(KERN_INFO DRIVER_NAME " driver loaded.\n");
+	pr_info("driver loaded\n");
 
 	return 0;
 }
diff -druNp linux-libre-2.6.37-gnu1/drivers/hwmon/hwmon.c linux-libre-2.6.38-gnu1/drivers/hwmon/hwmon.c
--- linux-libre-2.6.37-gnu1/drivers/hwmon/hwmon.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hwmon/hwmon.c	2011-03-14 21:20:32.000000000 -0400
@@ -10,6 +10,8 @@
     the Free Software Foundation; version 2 of the License.
 */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/device.h>
 #include <linux/err.h>
@@ -119,7 +121,7 @@ static int __init hwmon_init(void)
 
 	hwmon_class = class_create(THIS_MODULE, "hwmon");
 	if (IS_ERR(hwmon_class)) {
-		printk(KERN_ERR "hwmon.c: couldn't create sysfs class\n");
+		pr_err("couldn't create sysfs class\n");
 		return PTR_ERR(hwmon_class);
 	}
 	return 0;
diff -druNp linux-libre-2.6.37-gnu1/drivers/hwmon/hwmon-vid.c linux-libre-2.6.38-gnu1/drivers/hwmon/hwmon-vid.c
--- linux-libre-2.6.37-gnu1/drivers/hwmon/hwmon-vid.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hwmon/hwmon-vid.c	2011-03-14 21:20:32.000000000 -0400
@@ -22,6 +22,8 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/hwmon-vid.h>
@@ -146,8 +148,8 @@ int vid_from_reg(int val, u8 vrm)
 		return(val > 0x77 ? 0 : (1500000 - (val * 12500) + 500) / 1000);
 	default:		/* report 0 for unknown */
 		if (vrm)
-			printk(KERN_WARNING "hwmon-vid: Requested unsupported "
-			       "VRM version (%u)\n", (unsigned int)vrm);
+			pr_warn("Requested unsupported VRM version (%u)\n",
+				(unsigned int)vrm);
 		return 0;
 	}
 }
@@ -246,8 +248,7 @@ u8 vid_which_vrm(void)
 	}
 	vrm_ret = find_vrm(eff_family, eff_model, eff_stepping, c->x86_vendor);
 	if (vrm_ret == 0)
-		printk(KERN_INFO "hwmon-vid: Unknown VRM version of your "
-		       "x86 CPU\n");
+		pr_info("Unknown VRM version of your x86 CPU\n");
 	return vrm_ret;
 }
 
@@ -255,7 +256,7 @@ u8 vid_which_vrm(void)
 #else
 u8 vid_which_vrm(void)
 {
-	printk(KERN_INFO "hwmon-vid: Unknown VRM version of your CPU\n");
+	pr_info("Unknown VRM version of your CPU\n");
 	return 0;
 }
 #endif
diff -druNp linux-libre-2.6.37-gnu1/drivers/hwmon/ibmaem.c linux-libre-2.6.38-gnu1/drivers/hwmon/ibmaem.c
--- linux-libre-2.6.37-gnu1/drivers/hwmon/ibmaem.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hwmon/ibmaem.c	2011-03-14 21:20:32.000000000 -0400
@@ -20,6 +20,8 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/ipmi.h>
 #include <linux/module.h>
 #include <linux/hwmon.h>
@@ -1090,7 +1092,7 @@ static int __init aem_init(void)
 
 	res = driver_register(&aem_driver.driver);
 	if (res) {
-		printk(KERN_ERR "Can't register aem driver\n");
+		pr_err("Can't register aem driver\n");
 		return res;
 	}
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/hwmon/it87.c linux-libre-2.6.38-gnu1/drivers/hwmon/it87.c
--- linux-libre-2.6.37-gnu1/drivers/hwmon/it87.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hwmon/it87.c	2011-03-14 21:20:32.000000000 -0400
@@ -38,6 +38,8 @@
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
@@ -1570,26 +1572,25 @@ static int __init it87_find(unsigned sho
 	case 0xffff:	/* No device at all */
 		goto exit;
 	default:
-		pr_debug(DRVNAME ": Unsupported chip (DEVID=0x%x)\n",
-			 chip_type);
+		pr_debug("Unsupported chip (DEVID=0x%x)\n", chip_type);
 		goto exit;
 	}
 
 	superio_select(PME);
 	if (!(superio_inb(IT87_ACT_REG) & 0x01)) {
-		pr_info("it87: Device not activated, skipping\n");
+		pr_info("Device not activated, skipping\n");
 		goto exit;
 	}
 
 	*address = superio_inw(IT87_BASE_REG) & ~(IT87_EXTENT - 1);
 	if (*address == 0) {
-		pr_info("it87: Base address not set, skipping\n");
+		pr_info("Base address not set, skipping\n");
 		goto exit;
 	}
 
 	err = 0;
 	sio_data->revision = superio_inb(DEVREV) & 0x0f;
-	pr_info("it87: Found IT%04xF chip at 0x%x, revision %d\n",
+	pr_info("Found IT%04xF chip at 0x%x, revision %d\n",
 		chip_type, *address, sio_data->revision);
 
 	/* in8 (Vbat) is always internal */
@@ -1615,7 +1616,7 @@ static int __init it87_find(unsigned sho
 		} else {
 			/* We need at least 4 VID pins */
 			if (reg & 0x0f) {
-				pr_info("it87: VID is disabled (pins used for GPIO)\n");
+				pr_info("VID is disabled (pins used for GPIO)\n");
 				sio_data->skip_vid = 1;
 			}
 		}
@@ -1651,7 +1652,7 @@ static int __init it87_find(unsigned sho
 		if (sio_data->type == it8720 && !(reg & (1 << 1))) {
 			reg |= (1 << 1);
 			superio_outb(IT87_SIO_PINX2_REG, reg);
-			pr_notice("it87: Routing internal VCCH to in7\n");
+			pr_notice("Routing internal VCCH to in7\n");
 		}
 		if (reg & (1 << 0))
 			sio_data->internal |= (1 << 0);
@@ -1661,7 +1662,7 @@ static int __init it87_find(unsigned sho
 		sio_data->beep_pin = superio_inb(IT87_SIO_BEEP_PIN_REG) & 0x3f;
 	}
 	if (sio_data->beep_pin)
-		pr_info("it87: Beeping is supported\n");
+		pr_info("Beeping is supported\n");
 
 	/* Disable specific features based on DMI strings */
 	board_vendor = dmi_get_system_info(DMI_BOARD_VENDOR);
@@ -1675,8 +1676,7 @@ static int __init it87_find(unsigned sho
 			   the PWM2 duty cycle, so we disable it.
 			   I use the board name string as the trigger in case
 			   the same board is ever used in other systems. */
-			pr_info("it87: Disabling pwm2 due to "
-				"hardware constraints\n");
+			pr_info("Disabling pwm2 due to hardware constraints\n");
 			sio_data->skip_pwm = (1 << 1);
 		}
 	}
@@ -2189,28 +2189,26 @@ static int __init it87_device_add(unsign
 	pdev = platform_device_alloc(DRVNAME, address);
 	if (!pdev) {
 		err = -ENOMEM;
-		printk(KERN_ERR DRVNAME ": Device allocation failed\n");
+		pr_err("Device allocation failed\n");
 		goto exit;
 	}
 
 	err = platform_device_add_resources(pdev, &res, 1);
 	if (err) {
-		printk(KERN_ERR DRVNAME ": Device resource addition failed "
-		       "(%d)\n", err);
+		pr_err("Device resource addition failed (%d)\n", err);
 		goto exit_device_put;
 	}
 
 	err = platform_device_add_data(pdev, sio_data,
 				       sizeof(struct it87_sio_data));
 	if (err) {
-		printk(KERN_ERR DRVNAME ": Platform data allocation failed\n");
+		pr_err("Platform data allocation failed\n");
 		goto exit_device_put;
 	}
 
 	err = platform_device_add(pdev);
 	if (err) {
-		printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n",
-		       err);
+		pr_err("Device addition failed (%d)\n", err);
 		goto exit_device_put;
 	}
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/hwmon/jc42.c linux-libre-2.6.38-gnu1/drivers/hwmon/jc42.c
--- linux-libre-2.6.37-gnu1/drivers/hwmon/jc42.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hwmon/jc42.c	2011-03-14 21:20:32.000000000 -0400
@@ -53,6 +53,8 @@ static const unsigned short normal_i2c[]
 
 /* Configuration register defines */
 #define JC42_CFG_CRIT_ONLY	(1 << 2)
+#define JC42_CFG_TCRIT_LOCK	(1 << 6)
+#define JC42_CFG_EVENT_LOCK	(1 << 7)
 #define JC42_CFG_SHUTDOWN	(1 << 8)
 #define JC42_CFG_HYST_SHIFT	9
 #define JC42_CFG_HYST_MASK	0x03
@@ -332,7 +334,7 @@ static ssize_t set_temp_crit_hyst(struct
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct jc42_data *data = i2c_get_clientdata(client);
-	long val;
+	unsigned long val;
 	int diff, hyst;
 	int err;
 	int ret = count;
@@ -380,14 +382,14 @@ static ssize_t show_alarm(struct device
 
 static DEVICE_ATTR(temp1_input, S_IRUGO,
 		   show_temp_input, NULL);
-static DEVICE_ATTR(temp1_crit, S_IWUSR | S_IRUGO,
+static DEVICE_ATTR(temp1_crit, S_IRUGO,
 		   show_temp_crit, set_temp_crit);
-static DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO,
+static DEVICE_ATTR(temp1_min, S_IRUGO,
 		   show_temp_min, set_temp_min);
-static DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO,
+static DEVICE_ATTR(temp1_max, S_IRUGO,
 		   show_temp_max, set_temp_max);
 
-static DEVICE_ATTR(temp1_crit_hyst, S_IWUSR | S_IRUGO,
+static DEVICE_ATTR(temp1_crit_hyst, S_IRUGO,
 		   show_temp_crit_hyst, set_temp_crit_hyst);
 static DEVICE_ATTR(temp1_max_hyst, S_IRUGO,
 		   show_temp_max_hyst, NULL);
@@ -412,8 +414,31 @@ static struct attribute *jc42_attributes
 	NULL
 };
 
+static mode_t jc42_attribute_mode(struct kobject *kobj,
+				  struct attribute *attr, int index)
+{
+	struct device *dev = container_of(kobj, struct device, kobj);
+	struct i2c_client *client = to_i2c_client(dev);
+	struct jc42_data *data = i2c_get_clientdata(client);
+	unsigned int config = data->config;
+	bool readonly;
+
+	if (attr == &dev_attr_temp1_crit.attr)
+		readonly = config & JC42_CFG_TCRIT_LOCK;
+	else if (attr == &dev_attr_temp1_min.attr ||
+		 attr == &dev_attr_temp1_max.attr)
+		readonly = config & JC42_CFG_EVENT_LOCK;
+	else if (attr == &dev_attr_temp1_crit_hyst.attr)
+		readonly = config & (JC42_CFG_EVENT_LOCK | JC42_CFG_TCRIT_LOCK);
+	else
+		readonly = true;
+
+	return S_IRUGO | (readonly ? 0 : S_IWUSR);
+}
+
 static const struct attribute_group jc42_group = {
 	.attrs = jc42_attributes,
+	.is_visible = jc42_attribute_mode,
 };
 
 /* Return 0 if detection is successful, -ENODEV otherwise */
diff -druNp linux-libre-2.6.37-gnu1/drivers/hwmon/k10temp.c linux-libre-2.6.38-gnu1/drivers/hwmon/k10temp.c
--- linux-libre-2.6.37-gnu1/drivers/hwmon/k10temp.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hwmon/k10temp.c	2011-03-14 21:20:32.000000000 -0400
@@ -1,5 +1,5 @@
 /*
- * k10temp.c - AMD Family 10h/11h processor hardware monitoring
+ * k10temp.c - AMD Family 10h/11h/12h/14h processor hardware monitoring
  *
  * Copyright (c) 2009 Clemens Ladisch <clemens@ladisch.de>
  *
@@ -25,7 +25,7 @@
 #include <linux/pci.h>
 #include <asm/processor.h>
 
-MODULE_DESCRIPTION("AMD Family 10h/11h CPU core temperature monitor");
+MODULE_DESCRIPTION("AMD Family 10h/11h/12h/14h CPU core temperature monitor");
 MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
 MODULE_LICENSE("GPL");
 
@@ -208,6 +208,7 @@ static void __devexit k10temp_remove(str
 static const struct pci_device_id k10temp_id_table[] = {
 	{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_10H_NB_MISC) },
 	{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_11H_NB_MISC) },
+	{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_CNB17H_F3) },
 	{}
 };
 MODULE_DEVICE_TABLE(pci, k10temp_id_table);
diff -druNp linux-libre-2.6.37-gnu1/drivers/hwmon/Kconfig linux-libre-2.6.38-gnu1/drivers/hwmon/Kconfig
--- linux-libre-2.6.37-gnu1/drivers/hwmon/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hwmon/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -238,13 +238,13 @@ config SENSORS_K8TEMP
 	  will be called k8temp.
 
 config SENSORS_K10TEMP
-	tristate "AMD Phenom/Sempron/Turion/Opteron temperature sensor"
+	tristate "AMD Family 10h/11h/12h/14h temperature sensor"
 	depends on X86 && PCI
 	help
 	  If you say yes here you get support for the temperature
 	  sensor(s) inside your CPU. Supported are later revisions of
-	  the AMD Family 10h and all revisions of the AMD Family 11h
-	  microarchitectures.
+	  the AMD Family 10h and all revisions of the AMD Family 11h,
+	  12h (Llano), and 14h (Brazos) microarchitectures.
 
 	  This driver can also be built as a module.  If so, the module
 	  will be called k10temp.
@@ -274,6 +274,16 @@ config SENSORS_ATXP1
 	  This driver can also be built as a module.  If so, the module
 	  will be called atxp1.
 
+config SENSORS_DS620
+	tristate "Dallas Semiconductor DS620"
+	depends on I2C
+	help
+	  If you say yes here you get support for Dallas Semiconductor
+	  DS620 sensor chip.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called ds620.
+
 config SENSORS_DS1621
 	tristate "Dallas Semiconductor DS1621 and DS1625"
 	depends on I2C
@@ -445,13 +455,14 @@ config SENSORS_JZ4740
 	  called jz4740-hwmon.
 
 config SENSORS_JC42
-	tristate "JEDEC JC42.4 compliant temperature sensors"
+	tristate "JEDEC JC42.4 compliant memory module temperature sensors"
 	depends on I2C
 	help
-	  If you say yes here you get support for Jedec JC42.4 compliant
-	  temperature sensors. Support will include, but not be limited to,
-	  ADT7408, CAT34TS02,, CAT6095, MAX6604, MCP9805, MCP98242, MCP98243,
-	  MCP9843, SE97, SE98, STTS424, TSE2002B3, and TS3000B3.
+	  If you say yes here, you get support for JEDEC JC42.4 compliant
+	  temperature sensors, which are used on many DDR3 memory modules for
+	  mobile devices and servers.  Support will include, but not be limited
+	  to, ADT7408, CAT34TS02, CAT6095, MAX6604, MCP9805, MCP98242, MCP98243,
+	  MCP9843, SE97, SE98, STTS424(E), TSE2002B3, and TS3000B3.
 
 	  This driver can also be built as a module.  If so, the module
 	  will be called jc42.
@@ -564,7 +575,7 @@ config SENSORS_LM85
 	help
 	  If you say yes here you get support for National Semiconductor LM85
 	  sensor chips and clones: ADM1027, ADT7463, ADT7468, EMC6D100,
-	  EMC6D101 and EMC6D102.
+	  EMC6D101, EMC6D102, and EMC6D103.
 
 	  This driver can also be built as a module.  If so, the module
 	  will be called lm85.
@@ -608,8 +619,8 @@ config SENSORS_LM93
 	depends on I2C
 	select HWMON_VID
 	help
-	  If you say yes here you get support for National Semiconductor LM93
-	  sensor chips.
+	  If you say yes here you get support for National Semiconductor LM93,
+	  LM94, and compatible sensor chips.
 
 	  This driver can also be built as a module.  If so, the module
 	  will be called lm93.
@@ -734,6 +745,16 @@ config SENSORS_SHT15
 	  This driver can also be built as a module.  If so, the module
 	  will be called sht15.
 
+config SENSORS_SHT21
+	tristate "Sensiron humidity and temperature sensors. SHT21 and compat."
+	depends on I2C
+	help
+	  If you say yes here you get support for the Sensiron SHT21, SHT25
+	  humidity and temperature sensors.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called sht21.
+
 config SENSORS_S3C
 	tristate "Samsung built-in ADC"
 	depends on S3C_ADC
@@ -789,10 +810,10 @@ config SENSORS_DME1737
 	  will be called dme1737.
 
 config SENSORS_EMC1403
-	tristate "SMSC EMC1403 thermal sensor"
+	tristate "SMSC EMC1403/23 thermal sensor"
 	depends on I2C
 	help
-	  If you say yes here you get support for the SMSC EMC1403
+	  If you say yes here you get support for the SMSC EMC1403/23
 	  temperature monitoring chip.
 
 	  Threshold values can be configured using sysfs.
diff -druNp linux-libre-2.6.37-gnu1/drivers/hwmon/lis3lv02d.c linux-libre-2.6.38-gnu1/drivers/hwmon/lis3lv02d.c
--- linux-libre-2.6.37-gnu1/drivers/hwmon/lis3lv02d.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hwmon/lis3lv02d.c	2011-03-14 21:20:32.000000000 -0400
@@ -20,6 +20,8 @@
  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/dmi.h>
@@ -860,8 +862,7 @@ static void lis3lv02d_8b_configure(struc
 					(p->irq_flags2 & IRQF_TRIGGER_MASK),
 					DRIVER_NAME, &lis3_dev);
 		if (err < 0)
-			printk(KERN_ERR DRIVER_NAME
-				"No second IRQ. Limited functionality\n");
+			pr_err("No second IRQ. Limited functionality\n");
 	}
 }
 
@@ -879,7 +880,7 @@ int lis3lv02d_init_device(struct lis3lv0
 
 	switch (dev->whoami) {
 	case WAI_12B:
-		printk(KERN_INFO DRIVER_NAME ": 12 bits sensor found\n");
+		pr_info("12 bits sensor found\n");
 		dev->read_data = lis3lv02d_read_12;
 		dev->mdps_max_val = 2048;
 		dev->pwron_delay = LIS3_PWRON_DELAY_WAI_12B;
@@ -890,7 +891,7 @@ int lis3lv02d_init_device(struct lis3lv0
 		dev->regs_size = ARRAY_SIZE(lis3_wai12_regs);
 		break;
 	case WAI_8B:
-		printk(KERN_INFO DRIVER_NAME ": 8 bits sensor found\n");
+		pr_info("8 bits sensor found\n");
 		dev->read_data = lis3lv02d_read_8;
 		dev->mdps_max_val = 128;
 		dev->pwron_delay = LIS3_PWRON_DELAY_WAI_8B;
@@ -901,7 +902,7 @@ int lis3lv02d_init_device(struct lis3lv0
 		dev->regs_size = ARRAY_SIZE(lis3_wai8_regs);
 		break;
 	case WAI_3DC:
-		printk(KERN_INFO DRIVER_NAME ": 8 bits 3DC sensor found\n");
+		pr_info("8 bits 3DC sensor found\n");
 		dev->read_data = lis3lv02d_read_8;
 		dev->mdps_max_val = 128;
 		dev->pwron_delay = LIS3_PWRON_DELAY_WAI_8B;
@@ -910,8 +911,7 @@ int lis3lv02d_init_device(struct lis3lv0
 		dev->scale = LIS3_SENSITIVITY_8B;
 		break;
 	default:
-		printk(KERN_ERR DRIVER_NAME
-			": unknown sensor type 0x%X\n", dev->whoami);
+		pr_err("unknown sensor type 0x%X\n", dev->whoami);
 		return -EINVAL;
 	}
 
@@ -935,7 +935,7 @@ int lis3lv02d_init_device(struct lis3lv0
 	}
 
 	if (lis3lv02d_joystick_enable())
-		printk(KERN_ERR DRIVER_NAME ": joystick initialization failed\n");
+		pr_err("joystick initialization failed\n");
 
 	/* passing in platform specific data is purely optional and only
 	 * used by the SPI transport layer at the moment */
@@ -957,8 +957,7 @@ int lis3lv02d_init_device(struct lis3lv0
 
 	/* bail if we did not get an IRQ from the bus layer */
 	if (!dev->irq) {
-		printk(KERN_ERR DRIVER_NAME
-			": No IRQ. Disabling /dev/freefall\n");
+		pr_debug("No IRQ. Disabling /dev/freefall\n");
 		goto out;
 	}
 
@@ -985,12 +984,12 @@ int lis3lv02d_init_device(struct lis3lv0
 				DRIVER_NAME, &lis3_dev);
 
 	if (err < 0) {
-		printk(KERN_ERR DRIVER_NAME "Cannot get IRQ\n");
+		pr_err("Cannot get IRQ\n");
 		goto out;
 	}
 
 	if (misc_register(&lis3lv02d_misc_device))
-		printk(KERN_ERR DRIVER_NAME ": misc_register failed\n");
+		pr_err("misc_register failed\n");
 out:
 	return 0;
 }
diff -druNp linux-libre-2.6.37-gnu1/drivers/hwmon/lm63.c linux-libre-2.6.38-gnu1/drivers/hwmon/lm63.c
--- linux-libre-2.6.37-gnu1/drivers/hwmon/lm63.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hwmon/lm63.c	2011-03-14 21:20:32.000000000 -0400
@@ -98,6 +98,9 @@ static const unsigned short normal_i2c[]
  * value, it uses signed 8-bit values with LSB = 1 degree Celsius.
  * For remote temperature, low and high limits, it uses signed 11-bit values
  * with LSB = 0.125 degree Celsius, left-justified in 16-bit registers.
+ * For LM64 the actual remote diode temperature is 16 degree Celsius higher
+ * than the register reading. Remote temperature setpoints have to be
+ * adapted accordingly.
  */
 
 #define FAN_FROM_REG(reg)	((reg) == 0xFFFC || (reg) == 0 ? 0 : \
@@ -165,6 +168,8 @@ struct lm63_data {
 	struct mutex update_lock;
 	char valid; /* zero until following fields are valid */
 	unsigned long last_updated; /* in jiffies */
+	int kind;
+	int temp2_offset;
 
 	/* registers values */
 	u8 config, config_fan;
@@ -247,16 +252,34 @@ static ssize_t show_pwm1_enable(struct d
 	return sprintf(buf, "%d\n", data->config_fan & 0x20 ? 1 : 2);
 }
 
-static ssize_t show_temp8(struct device *dev, struct device_attribute *devattr,
-			  char *buf)
+/*
+ * There are 8bit registers for both local(temp1) and remote(temp2) sensor.
+ * For remote sensor registers temp2_offset has to be considered,
+ * for local sensor it must not.
+ * So we need separate 8bit accessors for local and remote sensor.
+ */
+static ssize_t show_local_temp8(struct device *dev,
+				struct device_attribute *devattr,
+				char *buf)
 {
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
 	struct lm63_data *data = lm63_update_device(dev);
 	return sprintf(buf, "%d\n", TEMP8_FROM_REG(data->temp8[attr->index]));
 }
 
-static ssize_t set_temp8(struct device *dev, struct device_attribute *dummy,
-			 const char *buf, size_t count)
+static ssize_t show_remote_temp8(struct device *dev,
+				 struct device_attribute *devattr,
+				 char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	struct lm63_data *data = lm63_update_device(dev);
+	return sprintf(buf, "%d\n", TEMP8_FROM_REG(data->temp8[attr->index])
+		       + data->temp2_offset);
+}
+
+static ssize_t set_local_temp8(struct device *dev,
+			       struct device_attribute *dummy,
+			       const char *buf, size_t count)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct lm63_data *data = i2c_get_clientdata(client);
@@ -274,7 +297,8 @@ static ssize_t show_temp11(struct device
 {
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
 	struct lm63_data *data = lm63_update_device(dev);
-	return sprintf(buf, "%d\n", TEMP11_FROM_REG(data->temp11[attr->index]));
+	return sprintf(buf, "%d\n", TEMP11_FROM_REG(data->temp11[attr->index])
+		       + data->temp2_offset);
 }
 
 static ssize_t set_temp11(struct device *dev, struct device_attribute *devattr,
@@ -294,7 +318,7 @@ static ssize_t set_temp11(struct device
 	int nr = attr->index;
 
 	mutex_lock(&data->update_lock);
-	data->temp11[nr] = TEMP11_TO_REG(val);
+	data->temp11[nr] = TEMP11_TO_REG(val - data->temp2_offset);
 	i2c_smbus_write_byte_data(client, reg[(nr - 1) * 2],
 				  data->temp11[nr] >> 8);
 	i2c_smbus_write_byte_data(client, reg[(nr - 1) * 2 + 1],
@@ -310,6 +334,7 @@ static ssize_t show_temp2_crit_hyst(stru
 {
 	struct lm63_data *data = lm63_update_device(dev);
 	return sprintf(buf, "%d\n", TEMP8_FROM_REG(data->temp8[2])
+		       + data->temp2_offset
 		       - TEMP8_FROM_REG(data->temp2_crit_hyst));
 }
 
@@ -324,7 +349,7 @@ static ssize_t set_temp2_crit_hyst(struc
 	long hyst;
 
 	mutex_lock(&data->update_lock);
-	hyst = TEMP8_FROM_REG(data->temp8[2]) - val;
+	hyst = TEMP8_FROM_REG(data->temp8[2]) + data->temp2_offset - val;
 	i2c_smbus_write_byte_data(client, LM63_REG_REMOTE_TCRIT_HYST,
 				  HYST_TO_REG(hyst));
 	mutex_unlock(&data->update_lock);
@@ -355,16 +380,21 @@ static SENSOR_DEVICE_ATTR(fan1_min, S_IW
 static DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm1, set_pwm1);
 static DEVICE_ATTR(pwm1_enable, S_IRUGO, show_pwm1_enable, NULL);
 
-static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp8, NULL, 0);
-static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp8,
-	set_temp8, 1);
+static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_local_temp8, NULL, 0);
+static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_local_temp8,
+	set_local_temp8, 1);
 
 static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp11, NULL, 0);
 static SENSOR_DEVICE_ATTR(temp2_min, S_IWUSR | S_IRUGO, show_temp11,
 	set_temp11, 1);
 static SENSOR_DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_temp11,
 	set_temp11, 2);
-static SENSOR_DEVICE_ATTR(temp2_crit, S_IRUGO, show_temp8, NULL, 2);
+/*
+ * On LM63, temp2_crit can be set only once, which should be job
+ * of the bootloader.
+ */
+static SENSOR_DEVICE_ATTR(temp2_crit, S_IRUGO, show_remote_temp8,
+	NULL, 2);
 static DEVICE_ATTR(temp2_crit_hyst, S_IWUSR | S_IRUGO, show_temp2_crit_hyst,
 	set_temp2_crit_hyst);
 
@@ -479,7 +509,12 @@ static int lm63_probe(struct i2c_client
 	data->valid = 0;
 	mutex_init(&data->update_lock);
 
-	/* Initialize the LM63 chip */
+	/* Set the device type */
+	data->kind = id->driver_data;
+	if (data->kind == lm64)
+		data->temp2_offset = 16000;
+
+	/* Initialize chip */
 	lm63_init_client(new_client);
 
 	/* Register sysfs hooks */
diff -druNp linux-libre-2.6.37-gnu1/drivers/hwmon/lm70.c linux-libre-2.6.38-gnu1/drivers/hwmon/lm70.c
--- linux-libre-2.6.37-gnu1/drivers/hwmon/lm70.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hwmon/lm70.c	2011-03-14 21:20:32.000000000 -0400
@@ -24,6 +24,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/kernel.h>
@@ -67,8 +69,7 @@ static ssize_t lm70_sense_temp(struct de
 	 */
 	status = spi_write_then_read(spi, NULL, 0, &rxbuf[0], 2);
 	if (status < 0) {
-		printk(KERN_WARNING
-		"spi_write_then_read failed with status %d\n", status);
+		pr_warn("spi_write_then_read failed with status %d\n", status);
 		goto out;
 	}
 	raw = (rxbuf[0] << 8) + rxbuf[1];
diff -druNp linux-libre-2.6.37-gnu1/drivers/hwmon/lm78.c linux-libre-2.6.38-gnu1/drivers/hwmon/lm78.c
--- linux-libre-2.6.37-gnu1/drivers/hwmon/lm78.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hwmon/lm78.c	2011-03-14 21:20:32.000000000 -0400
@@ -19,6 +19,8 @@
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
@@ -858,7 +860,7 @@ static int __init lm78_isa_found(unsigne
 	 * individually for the probing phase. */
 	for (port = address; port < address + LM78_EXTENT; port++) {
 		if (!request_region(port, 1, "lm78")) {
-			pr_debug("lm78: Failed to request port 0x%x\n", port);
+			pr_debug("Failed to request port 0x%x\n", port);
 			goto release;
 		}
 	}
@@ -920,7 +922,7 @@ static int __init lm78_isa_found(unsigne
 		found = 1;
 
 	if (found)
-		pr_info("lm78: Found an %s chip at %#x\n",
+		pr_info("Found an %s chip at %#x\n",
 			val & 0x80 ? "LM79" : "LM78", (int)address);
 
  release:
@@ -942,21 +944,19 @@ static int __init lm78_isa_device_add(un
 	pdev = platform_device_alloc("lm78", address);
 	if (!pdev) {
 		err = -ENOMEM;
-		printk(KERN_ERR "lm78: Device allocation failed\n");
+		pr_err("Device allocation failed\n");
 		goto exit;
 	}
 
 	err = platform_device_add_resources(pdev, &res, 1);
 	if (err) {
-		printk(KERN_ERR "lm78: Device resource addition failed "
-		       "(%d)\n", err);
+		pr_err("Device resource addition failed (%d)\n", err);
 		goto exit_device_put;
 	}
 
 	err = platform_device_add(pdev);
 	if (err) {
-		printk(KERN_ERR "lm78: Device addition failed (%d)\n",
-		       err);
+		pr_err("Device addition failed (%d)\n", err);
 		goto exit_device_put;
 	}
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/hwmon/lm85.c linux-libre-2.6.38-gnu1/drivers/hwmon/lm85.c
--- linux-libre-2.6.37-gnu1/drivers/hwmon/lm85.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hwmon/lm85.c	2011-03-14 21:20:32.000000000 -0400
@@ -41,7 +41,7 @@ static const unsigned short normal_i2c[]
 enum chips {
 	any_chip, lm85b, lm85c,
 	adm1027, adt7463, adt7468,
-	emc6d100, emc6d102
+	emc6d100, emc6d102, emc6d103
 };
 
 /* The LM85 registers */
@@ -90,6 +90,9 @@ enum chips {
 #define	LM85_VERSTEP_EMC6D100_A0        0x60
 #define	LM85_VERSTEP_EMC6D100_A1        0x61
 #define	LM85_VERSTEP_EMC6D102		0x65
+#define	LM85_VERSTEP_EMC6D103_A0	0x68
+#define	LM85_VERSTEP_EMC6D103_A1	0x69
+#define	LM85_VERSTEP_EMC6D103S		0x6A	/* Also known as EMC6D103:A2 */
 
 #define	LM85_REG_CONFIG			0x40
 
@@ -348,6 +351,7 @@ static const struct i2c_device_id lm85_i
 	{ "emc6d100", emc6d100 },
 	{ "emc6d101", emc6d100 },
 	{ "emc6d102", emc6d102 },
+	{ "emc6d103", emc6d103 },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, lm85_id);
@@ -1250,6 +1254,20 @@ static int lm85_detect(struct i2c_client
 		case LM85_VERSTEP_EMC6D102:
 			type_name = "emc6d102";
 			break;
+		case LM85_VERSTEP_EMC6D103_A0:
+		case LM85_VERSTEP_EMC6D103_A1:
+			type_name = "emc6d103";
+			break;
+		/*
+		 * Registers apparently missing in EMC6D103S/EMC6D103:A2
+		 * compared to EMC6D103:A0, EMC6D103:A1, and EMC6D102
+		 * (according to the data sheets), but used unconditionally
+		 * in the driver: 62[5:7], 6D[0:7], and 6E[0:7].
+		 * So skip EMC6D103S for now.
+		case LM85_VERSTEP_EMC6D103S:
+			type_name = "emc6d103s";
+			break;
+		 */
 		}
 	} else {
 		dev_dbg(&adapter->dev,
@@ -1283,6 +1301,7 @@ static int lm85_probe(struct i2c_client
 	case adt7468:
 	case emc6d100:
 	case emc6d102:
+	case emc6d103:
 		data->freq_map = adm1027_freq_map;
 		break;
 	default:
@@ -1468,7 +1487,7 @@ static struct lm85_data *lm85_update_dev
 			/* More alarm bits */
 			data->alarms |= lm85_read_value(client,
 						EMC6D100_REG_ALARM3) << 16;
-		} else if (data->type == emc6d102) {
+		} else if (data->type == emc6d102 || data->type == emc6d103) {
 			/* Have to read LSB bits after the MSB ones because
 			   the reading of the MSB bits has frozen the
 			   LSBs (backward from the ADM1027).
diff -druNp linux-libre-2.6.37-gnu1/drivers/hwmon/lm93.c linux-libre-2.6.38-gnu1/drivers/hwmon/lm93.c
--- linux-libre-2.6.37-gnu1/drivers/hwmon/lm93.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hwmon/lm93.c	2011-03-14 21:20:32.000000000 -0400
@@ -135,6 +135,11 @@
 #define LM93_MFR_ID		0x73
 #define LM93_MFR_ID_PROTOTYPE	0x72
 
+/* LM94 REGISTER VALUES */
+#define LM94_MFR_ID_2		0x7a
+#define LM94_MFR_ID		0x79
+#define LM94_MFR_ID_PROTOTYPE	0x78
+
 /* SMBus capabilities */
 #define LM93_SMBUS_FUNC_FULL (I2C_FUNC_SMBUS_BYTE_DATA | \
 		I2C_FUNC_SMBUS_WORD_DATA | I2C_FUNC_SMBUS_BLOCK_DATA)
@@ -2504,6 +2509,7 @@ static int lm93_detect(struct i2c_client
 {
 	struct i2c_adapter *adapter = client->adapter;
 	int mfr, ver;
+	const char *name;
 
 	if (!i2c_check_functionality(adapter, LM93_SMBUS_FUNC_MIN))
 		return -ENODEV;
@@ -2517,13 +2523,23 @@ static int lm93_detect(struct i2c_client
 	}
 
 	ver = lm93_read_byte(client, LM93_REG_VER);
-	if (ver != LM93_MFR_ID && ver != LM93_MFR_ID_PROTOTYPE) {
+	switch (ver) {
+	case LM93_MFR_ID:
+	case LM93_MFR_ID_PROTOTYPE:
+		name = "lm93";
+		break;
+	case LM94_MFR_ID_2:
+	case LM94_MFR_ID:
+	case LM94_MFR_ID_PROTOTYPE:
+		name = "lm94";
+		break;
+	default:
 		dev_dbg(&adapter->dev,
 			"detect failed, bad version id 0x%02x!\n", ver);
 		return -ENODEV;
 	}
 
-	strlcpy(info->type, "lm93", I2C_NAME_SIZE);
+	strlcpy(info->type, name, I2C_NAME_SIZE);
 	dev_dbg(&adapter->dev,"loading %s at %d,0x%02x\n",
 		client->name, i2c_adapter_id(client->adapter),
 		client->addr);
@@ -2602,6 +2618,7 @@ static int lm93_remove(struct i2c_client
 
 static const struct i2c_device_id lm93_id[] = {
 	{ "lm93", 0 },
+	{ "lm94", 0 },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, lm93_id);
diff -druNp linux-libre-2.6.37-gnu1/drivers/hwmon/lm95241.c linux-libre-2.6.38-gnu1/drivers/hwmon/lm95241.c
--- linux-libre-2.6.37-gnu1/drivers/hwmon/lm95241.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hwmon/lm95241.c	2011-03-14 21:20:32.000000000 -0400
@@ -1,13 +1,9 @@
 /*
- * lm95241.c - Part of lm_sensors, Linux kernel modules for hardware
- *             monitoring
- * Copyright (C) 2008 Davide Rizzo <elpa-rizzo@gmail.com>
+ * Copyright (C) 2008, 2010 Davide Rizzo <elpa.rizzo@gmail.com>
  *
- * Based on the max1619 driver. The LM95241 is a sensor chip made by National
- *   Semiconductors.
- * It reports up to three temperatures (its own plus up to
- * two external ones). Complete datasheet can be
- * obtained from National's website at:
+ * The LM95241 is a sensor chip made by National Semiconductors.
+ * It reports up to three temperatures (its own plus up to two external ones).
+ * Complete datasheet can be obtained from National's website at:
  *   http://www.national.com/ds.cgi/LM/LM95241.pdf
  *
  * This program is free software; you can redistribute it and/or modify
@@ -36,8 +32,10 @@
 #include <linux/mutex.h>
 #include <linux/sysfs.h>
 
+#define DEVNAME "lm95241"
+
 static const unsigned short normal_i2c[] = {
-	0x19, 0x2a, 0x2b, I2C_CLIENT_END};
+	0x19, 0x2a, 0x2b, I2C_CLIENT_END };
 
 /* LM95241 registers */
 #define LM95241_REG_R_MAN_ID		0xFE
@@ -46,7 +44,7 @@ static const unsigned short normal_i2c[]
 #define LM95241_REG_RW_CONFIG		0x03
 #define LM95241_REG_RW_REM_FILTER	0x06
 #define LM95241_REG_RW_TRUTHERM		0x07
-#define LM95241_REG_W_ONE_SHOT  	0x0F
+#define LM95241_REG_W_ONE_SHOT		0x0F
 #define LM95241_REG_R_LOCAL_TEMPH	0x10
 #define LM95241_REG_R_REMOTE1_TEMPH	0x11
 #define LM95241_REG_R_REMOTE2_TEMPH	0x12
@@ -79,235 +77,246 @@ static const unsigned short normal_i2c[]
 #define MANUFACTURER_ID 0x01
 #define DEFAULT_REVISION 0xA4
 
-/* Conversions and various macros */
-#define TEMP_FROM_REG(val_h, val_l) (((val_h) & 0x80 ? (val_h) - 0x100 : \
-    (val_h)) * 1000 + (val_l) * 1000 / 256)
-
-/* Functions declaration */
-static void lm95241_init_client(struct i2c_client *client);
-static struct lm95241_data *lm95241_update_device(struct device *dev);
+static const u8 lm95241_reg_address[] = {
+	LM95241_REG_R_LOCAL_TEMPH,
+	LM95241_REG_R_LOCAL_TEMPL,
+	LM95241_REG_R_REMOTE1_TEMPH,
+	LM95241_REG_R_REMOTE1_TEMPL,
+	LM95241_REG_R_REMOTE2_TEMPH,
+	LM95241_REG_R_REMOTE2_TEMPL
+};
 
 /* Client data (each client gets its own) */
 struct lm95241_data {
 	struct device *hwmon_dev;
 	struct mutex update_lock;
-	unsigned long last_updated, interval; /* in jiffies */
-	char valid; /* zero until following fields are valid */
+	unsigned long last_updated, interval;	/* in jiffies */
+	char valid;		/* zero until following fields are valid */
 	/* registers values */
-	u8 local_h, local_l; /* local */
-	u8 remote1_h, remote1_l; /* remote1 */
-	u8 remote2_h, remote2_l; /* remote2 */
+	u8 temp[ARRAY_SIZE(lm95241_reg_address)];
 	u8 config, model, trutherm;
 };
 
+/* Conversions */
+static int TempFromReg(u8 val_h, u8 val_l)
+{
+	if (val_h & 0x80)
+		return val_h - 0x100;
+	return val_h * 1000 + val_l * 1000 / 256;
+}
+
+static struct lm95241_data *lm95241_update_device(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct lm95241_data *data = i2c_get_clientdata(client);
+
+	mutex_lock(&data->update_lock);
+
+	if (time_after(jiffies, data->last_updated + data->interval) ||
+	    !data->valid) {
+		int i;
+
+		dev_dbg(&client->dev, "Updating lm95241 data.\n");
+		for (i = 0; i < ARRAY_SIZE(lm95241_reg_address); i++)
+			data->temp[i]
+			  = i2c_smbus_read_byte_data(client,
+						     lm95241_reg_address[i]);
+		data->last_updated = jiffies;
+		data->valid = 1;
+	}
+
+	mutex_unlock(&data->update_lock);
+
+	return data;
+}
+
 /* Sysfs stuff */
-#define show_temp(value) \
-static ssize_t show_##value(struct device *dev, \
-    struct device_attribute *attr, char *buf) \
-{ \
-	struct lm95241_data *data = lm95241_update_device(dev); \
-	snprintf(buf, PAGE_SIZE - 1, "%d\n", \
-		TEMP_FROM_REG(data->value##_h, data->value##_l)); \
-	return strlen(buf); \
+static ssize_t show_input(struct device *dev, struct device_attribute *attr,
+			  char *buf)
+{
+	struct lm95241_data *data = lm95241_update_device(dev);
+
+	return snprintf(buf, PAGE_SIZE - 1, "%d\n",
+		TempFromReg(data->temp[to_sensor_dev_attr(attr)->index],
+			    data->temp[to_sensor_dev_attr(attr)->index + 1]));
 }
-show_temp(local);
-show_temp(remote1);
-show_temp(remote2);
 
-static ssize_t show_interval(struct device *dev, struct device_attribute *attr,
+static ssize_t show_type(struct device *dev, struct device_attribute *attr,
 			 char *buf)
 {
-	struct lm95241_data *data = lm95241_update_device(dev);
+	struct i2c_client *client = to_i2c_client(dev);
+	struct lm95241_data *data = i2c_get_clientdata(client);
 
-	snprintf(buf, PAGE_SIZE - 1, "%lu\n", 1000 * data->interval / HZ);
-	return strlen(buf);
+	return snprintf(buf, PAGE_SIZE - 1,
+		data->model & to_sensor_dev_attr(attr)->index ? "1\n" : "2\n");
 }
 
-static ssize_t set_interval(struct device *dev, struct device_attribute *attr,
+static ssize_t set_type(struct device *dev, struct device_attribute *attr,
 			const char *buf, size_t count)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct lm95241_data *data = i2c_get_clientdata(client);
 	unsigned long val;
+	int shift;
+	u8 mask = to_sensor_dev_attr(attr)->index;
 
 	if (strict_strtoul(buf, 10, &val) < 0)
 		return -EINVAL;
+	if (val != 1 && val != 2)
+		return -EINVAL;
 
-	data->interval = val * HZ / 1000;
+	shift = mask == R1MS_MASK ? TT1_SHIFT : TT2_SHIFT;
+
+	mutex_lock(&data->update_lock);
+
+	data->trutherm &= ~(TT_MASK << shift);
+	if (val == 1) {
+		data->model |= mask;
+		data->trutherm |= (TT_ON << shift);
+	} else {
+		data->model &= ~mask;
+		data->trutherm |= (TT_OFF << shift);
+	}
+	data->valid = 0;
+
+	i2c_smbus_write_byte_data(client, LM95241_REG_RW_REMOTE_MODEL,
+				  data->model);
+	i2c_smbus_write_byte_data(client, LM95241_REG_RW_TRUTHERM,
+				  data->trutherm);
+
+	mutex_unlock(&data->update_lock);
 
 	return count;
 }
 
-#define show_type(flag) \
-static ssize_t show_type##flag(struct device *dev, \
-				   struct device_attribute *attr, char *buf) \
-{ \
-	struct i2c_client *client = to_i2c_client(dev); \
-	struct lm95241_data *data = i2c_get_clientdata(client); \
-\
-	snprintf(buf, PAGE_SIZE - 1, \
-		data->model & R##flag##MS_MASK ? "1\n" : "2\n"); \
-	return strlen(buf); \
+static ssize_t show_min(struct device *dev, struct device_attribute *attr,
+			char *buf)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct lm95241_data *data = i2c_get_clientdata(client);
+
+	return snprintf(buf, PAGE_SIZE - 1,
+			data->config & to_sensor_dev_attr(attr)->index ?
+			"-127000\n" : "0\n");
 }
-show_type(1);
-show_type(2);
 
-#define show_min(flag) \
-static ssize_t show_min##flag(struct device *dev, \
-    struct device_attribute *attr, char *buf) \
-{ \
-	struct i2c_client *client = to_i2c_client(dev); \
-	struct lm95241_data *data = i2c_get_clientdata(client); \
-\
-	snprintf(buf, PAGE_SIZE - 1, \
-		data->config & R##flag##DF_MASK ?	\
-		"-127000\n" : "0\n"); \
-	return strlen(buf); \
+static ssize_t set_min(struct device *dev, struct device_attribute *attr,
+		       const char *buf, size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct lm95241_data *data = i2c_get_clientdata(client);
+	long val;
+
+	if (strict_strtol(buf, 10, &val) < 0)
+		return -EINVAL;
+	if (val < -128000)
+		return -EINVAL;
+
+	mutex_lock(&data->update_lock);
+
+	if (val < 0)
+		data->config |= to_sensor_dev_attr(attr)->index;
+	else
+		data->config &= ~to_sensor_dev_attr(attr)->index;
+	data->valid = 0;
+
+	i2c_smbus_write_byte_data(client, LM95241_REG_RW_CONFIG, data->config);
+
+	mutex_unlock(&data->update_lock);
+
+	return count;
 }
-show_min(1);
-show_min(2);
 
-#define show_max(flag) \
-static ssize_t show_max##flag(struct device *dev, \
-    struct device_attribute *attr, char *buf) \
-{ \
-	struct i2c_client *client = to_i2c_client(dev); \
-	struct lm95241_data *data = i2c_get_clientdata(client); \
-\
-	snprintf(buf, PAGE_SIZE - 1, \
-		data->config & R##flag##DF_MASK ? \
-		"127000\n" : "255000\n"); \
-	return strlen(buf); \
+static ssize_t show_max(struct device *dev, struct device_attribute *attr,
+			char *buf)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct lm95241_data *data = i2c_get_clientdata(client);
+
+	return snprintf(buf, PAGE_SIZE - 1,
+			data->config & to_sensor_dev_attr(attr)->index ?
+			"127000\n" : "255000\n");
 }
-show_max(1);
-show_max(2);
 
-#define set_type(flag) \
-static ssize_t set_type##flag(struct device *dev, \
-				  struct device_attribute *attr, \
-				  const char *buf, size_t count) \
-{ \
-	struct i2c_client *client = to_i2c_client(dev); \
-	struct lm95241_data *data = i2c_get_clientdata(client); \
-\
-	long val; \
-\
-	if (strict_strtol(buf, 10, &val) < 0) \
-		return -EINVAL; \
-\
-	if ((val == 1) || (val == 2)) { \
-\
-		mutex_lock(&data->update_lock); \
-\
-		data->trutherm &= ~(TT_MASK << TT##flag##_SHIFT); \
-		if (val == 1) { \
-			data->model |= R##flag##MS_MASK; \
-			data->trutherm |= (TT_ON << TT##flag##_SHIFT); \
-		} \
-		else { \
-			data->model &= ~R##flag##MS_MASK; \
-			data->trutherm |= (TT_OFF << TT##flag##_SHIFT); \
-		} \
-\
-		data->valid = 0; \
-\
-		i2c_smbus_write_byte_data(client, LM95241_REG_RW_REMOTE_MODEL, \
-					  data->model); \
-		i2c_smbus_write_byte_data(client, LM95241_REG_RW_TRUTHERM, \
-					  data->trutherm); \
-\
-		mutex_unlock(&data->update_lock); \
-\
-	} \
-	return count; \
+static ssize_t set_max(struct device *dev, struct device_attribute *attr,
+		       const char *buf, size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct lm95241_data *data = i2c_get_clientdata(client);
+	long val;
+
+	if (strict_strtol(buf, 10, &val) < 0)
+		return -EINVAL;
+	if (val >= 256000)
+		return -EINVAL;
+
+	mutex_lock(&data->update_lock);
+
+	if (val <= 127000)
+		data->config |= to_sensor_dev_attr(attr)->index;
+	else
+		data->config &= ~to_sensor_dev_attr(attr)->index;
+	data->valid = 0;
+
+	i2c_smbus_write_byte_data(client, LM95241_REG_RW_CONFIG, data->config);
+
+	mutex_unlock(&data->update_lock);
+
+	return count;
 }
-set_type(1);
-set_type(2);
 
-#define set_min(flag) \
-static ssize_t set_min##flag(struct device *dev, \
-	struct device_attribute *devattr, const char *buf, size_t count) \
-{ \
-	struct i2c_client *client = to_i2c_client(dev); \
-	struct lm95241_data *data = i2c_get_clientdata(client); \
-\
-	long val; \
-\
-	if (strict_strtol(buf, 10, &val) < 0) \
-		return -EINVAL;\
-\
-	mutex_lock(&data->update_lock); \
-\
-	if (val < 0) \
-		data->config |= R##flag##DF_MASK; \
-	else \
-		data->config &= ~R##flag##DF_MASK; \
-\
-	data->valid = 0; \
-\
-	i2c_smbus_write_byte_data(client, LM95241_REG_RW_CONFIG, \
-		data->config); \
-\
-	mutex_unlock(&data->update_lock); \
-\
-	return count; \
+static ssize_t show_interval(struct device *dev, struct device_attribute *attr,
+			     char *buf)
+{
+	struct lm95241_data *data = lm95241_update_device(dev);
+
+	return snprintf(buf, PAGE_SIZE - 1, "%lu\n", 1000 * data->interval
+			/ HZ);
 }
-set_min(1);
-set_min(2);
 
-#define set_max(flag) \
-static ssize_t set_max##flag(struct device *dev, \
-	struct device_attribute *devattr, const char *buf, size_t count) \
-{ \
-	struct i2c_client *client = to_i2c_client(dev); \
-	struct lm95241_data *data = i2c_get_clientdata(client); \
-\
-	long val; \
-\
-	if (strict_strtol(buf, 10, &val) < 0) \
-		return -EINVAL; \
-\
-	mutex_lock(&data->update_lock); \
-\
-	if (val <= 127000) \
-		data->config |= R##flag##DF_MASK; \
-	else \
-		data->config &= ~R##flag##DF_MASK; \
-\
-	data->valid = 0; \
-\
-	i2c_smbus_write_byte_data(client, LM95241_REG_RW_CONFIG, \
-		data->config); \
-\
-	mutex_unlock(&data->update_lock); \
-\
-	return count; \
+static ssize_t set_interval(struct device *dev, struct device_attribute *attr,
+			    const char *buf, size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct lm95241_data *data = i2c_get_clientdata(client);
+	unsigned long val;
+
+	if (strict_strtoul(buf, 10, &val) < 0)
+		return -EINVAL;
+
+	data->interval = val * HZ / 1000;
+
+	return count;
 }
-set_max(1);
-set_max(2);
 
-static DEVICE_ATTR(temp1_input, S_IRUGO, show_local, NULL);
-static DEVICE_ATTR(temp2_input, S_IRUGO, show_remote1, NULL);
-static DEVICE_ATTR(temp3_input, S_IRUGO, show_remote2, NULL);
-static DEVICE_ATTR(temp2_type, S_IWUSR | S_IRUGO, show_type1, set_type1);
-static DEVICE_ATTR(temp3_type, S_IWUSR | S_IRUGO, show_type2, set_type2);
-static DEVICE_ATTR(temp2_min, S_IWUSR | S_IRUGO, show_min1, set_min1);
-static DEVICE_ATTR(temp3_min, S_IWUSR | S_IRUGO, show_min2, set_min2);
-static DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_max1, set_max1);
-static DEVICE_ATTR(temp3_max, S_IWUSR | S_IRUGO, show_max2, set_max2);
+static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_input, NULL, 0);
+static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_input, NULL, 2);
+static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_input, NULL, 4);
+static SENSOR_DEVICE_ATTR(temp2_type, S_IWUSR | S_IRUGO, show_type, set_type,
+			  R1MS_MASK);
+static SENSOR_DEVICE_ATTR(temp3_type, S_IWUSR | S_IRUGO, show_type, set_type,
+			  R2MS_MASK);
+static SENSOR_DEVICE_ATTR(temp2_min, S_IWUSR | S_IRUGO, show_min, set_min,
+			  R1DF_MASK);
+static SENSOR_DEVICE_ATTR(temp3_min, S_IWUSR | S_IRUGO, show_min, set_min,
+			  R2DF_MASK);
+static SENSOR_DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_max, set_max,
+			  R1DF_MASK);
+static SENSOR_DEVICE_ATTR(temp3_max, S_IWUSR | S_IRUGO, show_max, set_max,
+			  R2DF_MASK);
 static DEVICE_ATTR(update_interval, S_IWUSR | S_IRUGO, show_interval,
 		   set_interval);
 
 static struct attribute *lm95241_attributes[] = {
-	&dev_attr_temp1_input.attr,
-	&dev_attr_temp2_input.attr,
-	&dev_attr_temp3_input.attr,
-	&dev_attr_temp2_type.attr,
-	&dev_attr_temp3_type.attr,
-	&dev_attr_temp2_min.attr,
-	&dev_attr_temp3_min.attr,
-	&dev_attr_temp2_max.attr,
-	&dev_attr_temp3_max.attr,
+	&sensor_dev_attr_temp1_input.dev_attr.attr,
+	&sensor_dev_attr_temp2_input.dev_attr.attr,
+	&sensor_dev_attr_temp3_input.dev_attr.attr,
+	&sensor_dev_attr_temp2_type.dev_attr.attr,
+	&sensor_dev_attr_temp3_type.dev_attr.attr,
+	&sensor_dev_attr_temp2_min.dev_attr.attr,
+	&sensor_dev_attr_temp3_min.dev_attr.attr,
+	&sensor_dev_attr_temp2_max.dev_attr.attr,
+	&sensor_dev_attr_temp3_max.dev_attr.attr,
 	&dev_attr_update_interval.attr,
 	NULL
 };
@@ -329,9 +338,9 @@ static int lm95241_detect(struct i2c_cli
 
 	if ((i2c_smbus_read_byte_data(new_client, LM95241_REG_R_MAN_ID)
 	     == MANUFACTURER_ID)
-	 && (i2c_smbus_read_byte_data(new_client, LM95241_REG_R_CHIP_ID)
-	     >= DEFAULT_REVISION)) {
-		name = "lm95241";
+	    && (i2c_smbus_read_byte_data(new_client, LM95241_REG_R_CHIP_ID)
+		>= DEFAULT_REVISION)) {
+		name = DEVNAME;
 	} else {
 		dev_dbg(&adapter->dev, "LM95241 detection failed at 0x%02x\n",
 			address);
@@ -343,6 +352,25 @@ static int lm95241_detect(struct i2c_cli
 	return 0;
 }
 
+static void lm95241_init_client(struct i2c_client *client)
+{
+	struct lm95241_data *data = i2c_get_clientdata(client);
+
+	data->interval = HZ;	/* 1 sec default */
+	data->valid = 0;
+	data->config = CFG_CR0076;
+	data->model = 0;
+	data->trutherm = (TT_OFF << TT1_SHIFT) | (TT_OFF << TT2_SHIFT);
+
+	i2c_smbus_write_byte_data(client, LM95241_REG_RW_CONFIG, data->config);
+	i2c_smbus_write_byte_data(client, LM95241_REG_RW_REM_FILTER,
+				  R1FE_MASK | R2FE_MASK);
+	i2c_smbus_write_byte_data(client, LM95241_REG_RW_TRUTHERM,
+				  data->trutherm);
+	i2c_smbus_write_byte_data(client, LM95241_REG_RW_REMOTE_MODEL,
+				  data->model);
+}
+
 static int lm95241_probe(struct i2c_client *new_client,
 			 const struct i2c_device_id *id)
 {
@@ -382,26 +410,6 @@ exit:
 	return err;
 }
 
-static void lm95241_init_client(struct i2c_client *client)
-{
-	struct lm95241_data *data = i2c_get_clientdata(client);
-
-	data->interval = HZ;    /* 1 sec default */
-	data->valid = 0;
-	data->config = CFG_CR0076;
-	data->model = 0;
-	data->trutherm = (TT_OFF << TT1_SHIFT) | (TT_OFF << TT2_SHIFT);
-
-	i2c_smbus_write_byte_data(client, LM95241_REG_RW_CONFIG,
-				  data->config);
-	i2c_smbus_write_byte_data(client, LM95241_REG_RW_REM_FILTER,
-				  R1FE_MASK | R2FE_MASK);
-	i2c_smbus_write_byte_data(client, LM95241_REG_RW_TRUTHERM,
-				  data->trutherm);
-	i2c_smbus_write_byte_data(client, LM95241_REG_RW_REMOTE_MODEL,
-				  data->model);
-}
-
 static int lm95241_remove(struct i2c_client *client)
 {
 	struct lm95241_data *data = i2c_get_clientdata(client);
@@ -413,46 +421,9 @@ static int lm95241_remove(struct i2c_cli
 	return 0;
 }
 
-static struct lm95241_data *lm95241_update_device(struct device *dev)
-{
-	struct i2c_client *client = to_i2c_client(dev);
-	struct lm95241_data *data = i2c_get_clientdata(client);
-
-	mutex_lock(&data->update_lock);
-
-	if (time_after(jiffies, data->last_updated + data->interval) ||
-	    !data->valid) {
-		dev_dbg(&client->dev, "Updating lm95241 data.\n");
-		data->local_h =
-			i2c_smbus_read_byte_data(client,
-						 LM95241_REG_R_LOCAL_TEMPH);
-		data->local_l =
-			i2c_smbus_read_byte_data(client,
-						 LM95241_REG_R_LOCAL_TEMPL);
-		data->remote1_h =
-			i2c_smbus_read_byte_data(client,
-						 LM95241_REG_R_REMOTE1_TEMPH);
-		data->remote1_l =
-			i2c_smbus_read_byte_data(client,
-						 LM95241_REG_R_REMOTE1_TEMPL);
-		data->remote2_h =
-			i2c_smbus_read_byte_data(client,
-						 LM95241_REG_R_REMOTE2_TEMPH);
-		data->remote2_l =
-			i2c_smbus_read_byte_data(client,
-						 LM95241_REG_R_REMOTE2_TEMPL);
-		data->last_updated = jiffies;
-		data->valid = 1;
-	}
-
-	mutex_unlock(&data->update_lock);
-
-	return data;
-}
-
 /* Driver data (common to all clients) */
 static const struct i2c_device_id lm95241_id[] = {
-	{ "lm95241", 0 },
+	{ DEVNAME, 0 },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, lm95241_id);
@@ -460,7 +431,7 @@ MODULE_DEVICE_TABLE(i2c, lm95241_id);
 static struct i2c_driver lm95241_driver = {
 	.class		= I2C_CLASS_HWMON,
 	.driver = {
-		.name   = "lm95241",
+		.name	= DEVNAME,
 	},
 	.probe		= lm95241_probe,
 	.remove		= lm95241_remove,
@@ -479,7 +450,7 @@ static void __exit sensors_lm95241_exit(
 	i2c_del_driver(&lm95241_driver);
 }
 
-MODULE_AUTHOR("Davide Rizzo <elpa-rizzo@gmail.com>");
+MODULE_AUTHOR("Davide Rizzo <elpa.rizzo@gmail.com>");
 MODULE_DESCRIPTION("LM95241 sensor driver");
 MODULE_LICENSE("GPL");
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/hwmon/Makefile linux-libre-2.6.38-gnu1/drivers/hwmon/Makefile
--- linux-libre-2.6.37-gnu1/drivers/hwmon/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hwmon/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -41,6 +41,7 @@ obj-$(CONFIG_SENSORS_ATXP1)	+= atxp1.o
 obj-$(CONFIG_SENSORS_CORETEMP)	+= coretemp.o
 obj-$(CONFIG_SENSORS_PKGTEMP)	+= pkgtemp.o
 obj-$(CONFIG_SENSORS_DME1737)	+= dme1737.o
+obj-$(CONFIG_SENSORS_DS620)	+= ds620.o
 obj-$(CONFIG_SENSORS_DS1621)	+= ds1621.o
 obj-$(CONFIG_SENSORS_EMC1403)	+= emc1403.o
 obj-$(CONFIG_SENSORS_EMC2103)	+= emc2103.o
@@ -90,6 +91,7 @@ obj-$(CONFIG_SENSORS_PC87427)	+= pc87427
 obj-$(CONFIG_SENSORS_PCF8591)	+= pcf8591.o
 obj-$(CONFIG_SENSORS_S3C)	+= s3c-hwmon.o
 obj-$(CONFIG_SENSORS_SHT15)	+= sht15.o
+obj-$(CONFIG_SENSORS_SHT21)	+= sht21.o
 obj-$(CONFIG_SENSORS_SIS5595)	+= sis5595.o
 obj-$(CONFIG_SENSORS_SMM665)	+= smm665.o
 obj-$(CONFIG_SENSORS_SMSC47B397)+= smsc47b397.o
diff -druNp linux-libre-2.6.37-gnu1/drivers/hwmon/pc87360.c linux-libre-2.6.38-gnu1/drivers/hwmon/pc87360.c
--- linux-libre-2.6.37-gnu1/drivers/hwmon/pc87360.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hwmon/pc87360.c	2011-03-14 21:20:32.000000000 -0400
@@ -33,6 +33,8 @@
  *  the standard Super-I/O addresses is used (0x2E/0x2F or 0x4E/0x4F).
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
@@ -1031,16 +1033,15 @@ static int __init pc87360_find(int sioad
 
 		val = superio_inb(sioaddr, ACT);
 		if (!(val & 0x01)) {
-			printk(KERN_INFO "pc87360: Device 0x%02x not "
-			       "activated\n", logdev[i]);
+			pr_info("Device 0x%02x not activated\n", logdev[i]);
 			continue;
 		}
 
 		val = (superio_inb(sioaddr, BASE) << 8)
 		    | superio_inb(sioaddr, BASE + 1);
 		if (!val) {
-			printk(KERN_INFO "pc87360: Base address not set for "
-			       "device 0x%02x\n", logdev[i]);
+			pr_info("Base address not set for device 0x%02x\n",
+				logdev[i]);
 			continue;
 		}
 
@@ -1050,17 +1051,15 @@ static int __init pc87360_find(int sioad
 			confreg[0] = superio_inb(sioaddr, 0xF0);
 			confreg[1] = superio_inb(sioaddr, 0xF1);
 
-#ifdef DEBUG
-			printk(KERN_DEBUG "pc87360: Fan 1: mon=%d "
-			       "ctrl=%d inv=%d\n", (confreg[0]>>2)&1,
-			       (confreg[0]>>3)&1, (confreg[0]>>4)&1);
-			printk(KERN_DEBUG "pc87360: Fan 2: mon=%d "
-			       "ctrl=%d inv=%d\n", (confreg[0]>>5)&1,
-			       (confreg[0]>>6)&1, (confreg[0]>>7)&1);
-			printk(KERN_DEBUG "pc87360: Fan 3: mon=%d "
-			       "ctrl=%d inv=%d\n", confreg[1]&1,
-			       (confreg[1]>>1)&1, (confreg[1]>>2)&1);
-#endif
+			pr_debug("Fan %d: mon=%d ctrl=%d inv=%d\n", 1,
+				 (confreg[0] >> 2) & 1, (confreg[0] >> 3) & 1,
+				 (confreg[0] >> 4) & 1);
+			pr_debug("Fan %d: mon=%d ctrl=%d inv=%d\n", 2,
+				 (confreg[0] >> 5) & 1, (confreg[0] >> 6) & 1,
+				 (confreg[0] >> 7) & 1);
+			pr_debug("Fan %d: mon=%d ctrl=%d inv=%d\n", 3,
+				 confreg[1] & 1, (confreg[1] >> 1) & 1,
+				 (confreg[1] >> 2) & 1);
 		} else if (i==1) { /* Voltages */
 			/* Are we using thermistors? */
 			if (*devid == 0xE9) { /* PC87366 */
@@ -1071,14 +1070,12 @@ static int __init pc87360_find(int sioad
 				confreg[3] = superio_inb(sioaddr, 0x25);
 
 				if (confreg[2] & 0x40) {
-					printk(KERN_INFO "pc87360: Using "
-					       "thermistors for temperature "
-					       "monitoring\n");
+					pr_info("Using thermistors for "
+						"temperature monitoring\n");
 				}
 				if (confreg[3] & 0xE0) {
-					printk(KERN_INFO "pc87360: VID "
-					       "inputs routed (mode %u)\n",
-					       confreg[3] >> 5);
+					pr_info("VID inputs routed (mode %u)\n",
+						confreg[3] >> 5);
 				}
 			}
 		}
@@ -1616,7 +1613,7 @@ static int __init pc87360_device_add(uns
 	pdev = platform_device_alloc("pc87360", address);
 	if (!pdev) {
 		err = -ENOMEM;
-		printk(KERN_ERR "pc87360: Device allocation failed\n");
+		pr_err("Device allocation failed\n");
 		goto exit;
 	}
 
@@ -1639,15 +1636,13 @@ static int __init pc87360_device_add(uns
 
 	err = platform_device_add_resources(pdev, res, res_count);
 	if (err) {
-		printk(KERN_ERR "pc87360: Device resources addition failed "
-		       "(%d)\n", err);
+		pr_err("Device resources addition failed (%d)\n", err);
 		goto exit_device_put;
 	}
 
 	err = platform_device_add(pdev);
 	if (err) {
-		printk(KERN_ERR "pc87360: Device addition failed (%d)\n",
-		       err);
+		pr_err("Device addition failed (%d)\n", err);
 		goto exit_device_put;
 	}
 
@@ -1666,8 +1661,7 @@ static int __init pc87360_init(void)
 
 	if (pc87360_find(0x2e, &devid, extra_isa)
 	 && pc87360_find(0x4e, &devid, extra_isa)) {
-		printk(KERN_WARNING "pc87360: PC8736x not detected, "
-		       "module not inserted.\n");
+		pr_warn("PC8736x not detected, module not inserted\n");
 		return -ENODEV;
 	}
 
@@ -1680,8 +1674,7 @@ static int __init pc87360_init(void)
 	}
 
 	if (address == 0x0000) {
-		printk(KERN_WARNING "pc87360: No active logical device, "
-		       "module not inserted.\n");
+		pr_warn("No active logical device, module not inserted\n");
 		return -ENODEV;
 	}
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/hwmon/pc87427.c linux-libre-2.6.38-gnu1/drivers/hwmon/pc87427.c
--- linux-libre-2.6.37-gnu1/drivers/hwmon/pc87427.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hwmon/pc87427.c	2011-03-14 21:20:32.000000000 -0400
@@ -22,6 +22,8 @@
  *  mode, and voltages aren't supported at all.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
@@ -1077,7 +1079,7 @@ static int __devinit pc87427_probe(struc
 	data = kzalloc(sizeof(struct pc87427_data), GFP_KERNEL);
 	if (!data) {
 		err = -ENOMEM;
-		printk(KERN_ERR DRVNAME ": Out of memory\n");
+		pr_err("Out of memory\n");
 		goto exit;
 	}
 
@@ -1196,28 +1198,26 @@ static int __init pc87427_device_add(con
 	pdev = platform_device_alloc(DRVNAME, res[0].start);
 	if (!pdev) {
 		err = -ENOMEM;
-		printk(KERN_ERR DRVNAME ": Device allocation failed\n");
+		pr_err("Device allocation failed\n");
 		goto exit;
 	}
 
 	err = platform_device_add_resources(pdev, res, res_count);
 	if (err) {
-		printk(KERN_ERR DRVNAME ": Device resource addition failed "
-		       "(%d)\n", err);
+		pr_err("Device resource addition failed (%d)\n", err);
 		goto exit_device_put;
 	}
 
 	err = platform_device_add_data(pdev, sio_data,
 				       sizeof(struct pc87427_sio_data));
 	if (err) {
-		printk(KERN_ERR DRVNAME ": Platform data allocation failed\n");
+		pr_err("Platform data allocation failed\n");
 		goto exit_device_put;
 	}
 
 	err = platform_device_add(pdev);
 	if (err) {
-		printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n",
-		       err);
+		pr_err("Device addition failed (%d)\n", err);
 		goto exit_device_put;
 	}
 
@@ -1249,23 +1249,23 @@ static int __init pc87427_find(int sioad
 
 		val = superio_inb(sioaddr, SIOREG_ACT);
 		if (!(val & 0x01)) {
-			printk(KERN_INFO DRVNAME ": Logical device 0x%02x "
-			       "not activated\n", logdev[i]);
+			pr_info("Logical device 0x%02x not activated\n",
+				logdev[i]);
 			continue;
 		}
 
 		val = superio_inb(sioaddr, SIOREG_MAP);
 		if (val & 0x01) {
-			printk(KERN_WARNING DRVNAME ": Logical device 0x%02x "
-			       "is memory-mapped, can't use\n", logdev[i]);
+			pr_warn("Logical device 0x%02x is memory-mapped, "
+				"can't use\n", logdev[i]);
 			continue;
 		}
 
 		val = (superio_inb(sioaddr, SIOREG_IOBASE) << 8)
 		    | superio_inb(sioaddr, SIOREG_IOBASE + 1);
 		if (!val) {
-			printk(KERN_INFO DRVNAME ": I/O base address not set "
-			       "for logical device 0x%02x\n", logdev[i]);
+			pr_info("I/O base address not set for logical device "
+				"0x%02x\n", logdev[i]);
 			continue;
 		}
 		sio_data->address[i] = val;
diff -druNp linux-libre-2.6.37-gnu1/drivers/hwmon/pcf8591.c linux-libre-2.6.38-gnu1/drivers/hwmon/pcf8591.c
--- linux-libre-2.6.37-gnu1/drivers/hwmon/pcf8591.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hwmon/pcf8591.c	2011-03-14 21:20:32.000000000 -0400
@@ -18,6 +18,8 @@
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
@@ -290,8 +292,7 @@ static struct i2c_driver pcf8591_driver
 static int __init pcf8591_init(void)
 {
 	if (input_mode < 0 || input_mode > 3) {
-		printk(KERN_WARNING "pcf8591: invalid input_mode (%d)\n",
-		       input_mode);
+		pr_warn("invalid input_mode (%d)\n", input_mode);
 		input_mode = 0;
 	}
 	return i2c_add_driver(&pcf8591_driver);
diff -druNp linux-libre-2.6.37-gnu1/drivers/hwmon/pkgtemp.c linux-libre-2.6.38-gnu1/drivers/hwmon/pkgtemp.c
--- linux-libre-2.6.37-gnu1/drivers/hwmon/pkgtemp.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hwmon/pkgtemp.c	2011-03-14 21:20:32.000000000 -0400
@@ -20,6 +20,8 @@
  * 02110-1301 USA.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
@@ -303,7 +305,7 @@ static int __cpuinit pkgtemp_device_add(
 	pdev = platform_device_alloc(DRVNAME, cpu);
 	if (!pdev) {
 		err = -ENOMEM;
-		printk(KERN_ERR DRVNAME ": Device allocation failed\n");
+		pr_err("Device allocation failed\n");
 		goto exit;
 	}
 
@@ -315,8 +317,7 @@ static int __cpuinit pkgtemp_device_add(
 
 	err = platform_device_add(pdev);
 	if (err) {
-		printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n",
-		       err);
+		pr_err("Device addition failed (%d)\n", err);
 		goto exit_device_free;
 	}
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/hwmon/sht21.c linux-libre-2.6.38-gnu1/drivers/hwmon/sht21.c
--- linux-libre-2.6.37-gnu1/drivers/hwmon/sht21.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hwmon/sht21.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,307 @@
+/* Sensirion SHT21 humidity and temperature sensor driver
+ *
+ * Copyright (C) 2010 Urs Fleisch <urs.fleisch@sensirion.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., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Data sheet available (5/2010) at
+ * http://www.sensirion.com/en/pdf/product_information/Datasheet-humidity-sensor-SHT21.pdf
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/err.h>
+#include <linux/mutex.h>
+#include <linux/device.h>
+
+/* I2C command bytes */
+#define SHT21_TRIG_T_MEASUREMENT_HM  0xe3
+#define SHT21_TRIG_RH_MEASUREMENT_HM 0xe5
+
+/**
+ * struct sht21 - SHT21 device specific data
+ * @hwmon_dev: device registered with hwmon
+ * @lock: mutex to protect measurement values
+ * @valid: only 0 before first measurement is taken
+ * @last_update: time of last update (jiffies)
+ * @temperature: cached temperature measurement value
+ * @humidity: cached humidity measurement value
+ */
+struct sht21 {
+	struct device *hwmon_dev;
+	struct mutex lock;
+	char valid;
+	unsigned long last_update;
+	int temperature;
+	int humidity;
+};
+
+/**
+ * sht21_temp_ticks_to_millicelsius() - convert raw temperature ticks to
+ * milli celsius
+ * @ticks: temperature ticks value received from sensor
+ */
+static inline int sht21_temp_ticks_to_millicelsius(int ticks)
+{
+	ticks &= ~0x0003; /* clear status bits */
+	/*
+	 * Formula T = -46.85 + 175.72 * ST / 2^16 from data sheet 6.2,
+	 * optimized for integer fixed point (3 digits) arithmetic
+	 */
+	return ((21965 * ticks) >> 13) - 46850;
+}
+
+/**
+ * sht21_rh_ticks_to_per_cent_mille() - convert raw humidity ticks to
+ * one-thousandths of a percent relative humidity
+ * @ticks: humidity ticks value received from sensor
+ */
+static inline int sht21_rh_ticks_to_per_cent_mille(int ticks)
+{
+	ticks &= ~0x0003; /* clear status bits */
+	/*
+	 * Formula RH = -6 + 125 * SRH / 2^16 from data sheet 6.1,
+	 * optimized for integer fixed point (3 digits) arithmetic
+	 */
+	return ((15625 * ticks) >> 13) - 6000;
+}
+
+/**
+ * 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
+ *
+ * Returns 0 on success, else negative errno.
+ */
+static int sht21_update_measurements(struct i2c_client *client)
+{
+	int ret = 0;
+	struct sht21 *sht21 = i2c_get_clientdata(client);
+
+	mutex_lock(&sht21->lock);
+	/*
+	 * Data sheet 2.4:
+	 * SHT2x should not be active for more than 10% of the time - e.g.
+	 * 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);
+		if (ret < 0)
+			goto out;
+		sht21->temperature = sht21_temp_ticks_to_millicelsius(ret);
+		ret = sht21_read_word_data(client,
+					SHT21_TRIG_RH_MEASUREMENT_HM);
+		if (ret < 0)
+			goto out;
+		sht21->humidity = sht21_rh_ticks_to_per_cent_mille(ret);
+		sht21->last_update = jiffies;
+		sht21->valid = 1;
+	}
+out:
+	mutex_unlock(&sht21->lock);
+
+	return ret >= 0 ? 0 : ret;
+}
+
+/**
+ * sht21_show_temperature() - show temperature measurement value in sysfs
+ * @dev: device
+ * @attr: device attribute
+ * @buf: sysfs buffer (PAGE_SIZE) where measurement values are written to
+ *
+ * Will be called on read access to temp1_input sysfs attribute.
+ * Returns number of bytes written into buffer, negative errno on error.
+ */
+static ssize_t sht21_show_temperature(struct device *dev,
+	struct device_attribute *attr,
+	char *buf)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct sht21 *sht21 = i2c_get_clientdata(client);
+	int ret = sht21_update_measurements(client);
+	if (ret < 0)
+		return ret;
+	return sprintf(buf, "%d\n", sht21->temperature);
+}
+
+/**
+ * sht21_show_humidity() - show humidity measurement value in sysfs
+ * @dev: device
+ * @attr: device attribute
+ * @buf: sysfs buffer (PAGE_SIZE) where measurement values are written to
+ *
+ * Will be called on read access to humidity1_input sysfs attribute.
+ * Returns number of bytes written into buffer, negative errno on error.
+ */
+static ssize_t sht21_show_humidity(struct device *dev,
+	struct device_attribute *attr,
+	char *buf)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct sht21 *sht21 = i2c_get_clientdata(client);
+	int ret = sht21_update_measurements(client);
+	if (ret < 0)
+		return ret;
+	return sprintf(buf, "%d\n", sht21->humidity);
+}
+
+/* sysfs attributes */
+static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, sht21_show_temperature,
+	NULL, 0);
+static SENSOR_DEVICE_ATTR(humidity1_input, S_IRUGO, sht21_show_humidity,
+	NULL, 0);
+
+static struct attribute *sht21_attributes[] = {
+	&sensor_dev_attr_temp1_input.dev_attr.attr,
+	&sensor_dev_attr_humidity1_input.dev_attr.attr,
+	NULL
+};
+
+static const struct attribute_group sht21_attr_group = {
+	.attrs = sht21_attributes,
+};
+
+/**
+ * sht21_probe() - probe device
+ * @client: I2C client device
+ * @id: device ID
+ *
+ * Called by the I2C core when an entry in the ID table matches a
+ * device's name.
+ * Returns 0 on success.
+ */
+static int __devinit sht21_probe(struct i2c_client *client,
+	const struct i2c_device_id *id)
+{
+	struct sht21 *sht21;
+	int err;
+
+	if (!i2c_check_functionality(client->adapter,
+				     I2C_FUNC_SMBUS_WORD_DATA)) {
+		dev_err(&client->dev,
+			"adapter does not support SMBus word transactions\n");
+		return -ENODEV;
+	}
+
+	sht21 = kzalloc(sizeof(*sht21), GFP_KERNEL);
+	if (!sht21) {
+		dev_dbg(&client->dev, "kzalloc failed\n");
+		return -ENOMEM;
+	}
+	i2c_set_clientdata(client, sht21);
+
+	mutex_init(&sht21->lock);
+
+	err = sysfs_create_group(&client->dev.kobj, &sht21_attr_group);
+	if (err) {
+		dev_dbg(&client->dev, "could not create sysfs files\n");
+		goto fail_free;
+	}
+	sht21->hwmon_dev = hwmon_device_register(&client->dev);
+	if (IS_ERR(sht21->hwmon_dev)) {
+		dev_dbg(&client->dev, "unable to register hwmon device\n");
+		err = PTR_ERR(sht21->hwmon_dev);
+		goto fail_remove_sysfs;
+	}
+
+	dev_info(&client->dev, "initialized\n");
+
+	return 0;
+
+fail_remove_sysfs:
+	sysfs_remove_group(&client->dev.kobj, &sht21_attr_group);
+fail_free:
+	kfree(sht21);
+
+	return err;
+}
+
+/**
+ * sht21_remove() - remove device
+ * @client: I2C client device
+ */
+static int __devexit sht21_remove(struct i2c_client *client)
+{
+	struct sht21 *sht21 = i2c_get_clientdata(client);
+
+	hwmon_device_unregister(sht21->hwmon_dev);
+	sysfs_remove_group(&client->dev.kobj, &sht21_attr_group);
+	kfree(sht21);
+
+	return 0;
+}
+
+/* Device ID table */
+static const struct i2c_device_id sht21_id[] = {
+	{ "sht21", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, sht21_id);
+
+static struct i2c_driver sht21_driver = {
+	.driver.name = "sht21",
+	.probe       = sht21_probe,
+	.remove      = __devexit_p(sht21_remove),
+	.id_table    = sht21_id,
+};
+
+/**
+ * sht21_init() - initialize driver
+ *
+ * Called when kernel is booted or module is inserted.
+ * Returns 0 on success.
+ */
+static int __init sht21_init(void)
+{
+	return i2c_add_driver(&sht21_driver);
+}
+module_init(sht21_init);
+
+/**
+ * sht21_init() - clean up driver
+ *
+ * Called when module is removed.
+ */
+static void __exit sht21_exit(void)
+{
+	i2c_del_driver(&sht21_driver);
+}
+module_exit(sht21_exit);
+
+MODULE_AUTHOR("Urs Fleisch <urs.fleisch@sensirion.com>");
+MODULE_DESCRIPTION("Sensirion SHT21 humidity and temperature sensor driver");
+MODULE_LICENSE("GPL");
diff -druNp linux-libre-2.6.37-gnu1/drivers/hwmon/sis5595.c linux-libre-2.6.38-gnu1/drivers/hwmon/sis5595.c
--- linux-libre-2.6.37-gnu1/drivers/hwmon/sis5595.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hwmon/sis5595.c	2011-03-14 21:20:32.000000000 -0400
@@ -50,6 +50,8 @@
 	 735		0008		0735
 */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/ioport.h>
@@ -735,21 +737,19 @@ static int __devinit sis5595_device_add(
 	pdev = platform_device_alloc("sis5595", address);
 	if (!pdev) {
 		err = -ENOMEM;
-		printk(KERN_ERR "sis5595: Device allocation failed\n");
+		pr_err("Device allocation failed\n");
 		goto exit;
 	}
 
 	err = platform_device_add_resources(pdev, &res, 1);
 	if (err) {
-		printk(KERN_ERR "sis5595: Device resource addition failed "
-		       "(%d)\n", err);
+		pr_err("Device resource addition failed (%d)\n", err);
 		goto exit_device_put;
 	}
 
 	err = platform_device_add(pdev);
 	if (err) {
-		printk(KERN_ERR "sis5595: Device addition failed (%d)\n",
-		       err);
+		pr_err("Device addition failed (%d)\n", err);
 		goto exit_device_put;
 	}
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/hwmon/smsc47b397.c linux-libre-2.6.38-gnu1/drivers/hwmon/smsc47b397.c
--- linux-libre-2.6.37-gnu1/drivers/hwmon/smsc47b397.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hwmon/smsc47b397.c	2011-03-14 21:20:32.000000000 -0400
@@ -26,6 +26,8 @@
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/ioport.h>
@@ -311,21 +313,19 @@ static int __init smsc47b397_device_add(
 	pdev = platform_device_alloc(DRVNAME, address);
 	if (!pdev) {
 		err = -ENOMEM;
-		printk(KERN_ERR DRVNAME ": Device allocation failed\n");
+		pr_err("Device allocation failed\n");
 		goto exit;
 	}
 
 	err = platform_device_add_resources(pdev, &res, 1);
 	if (err) {
-		printk(KERN_ERR DRVNAME ": Device resource addition failed "
-		       "(%d)\n", err);
+		pr_err("Device resource addition failed (%d)\n", err);
 		goto exit_device_put;
 	}
 
 	err = platform_device_add(pdev);
 	if (err) {
-		printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n",
-		       err);
+		pr_err("Device addition failed (%d)\n", err);
 		goto exit_device_put;
 	}
 
@@ -367,8 +367,7 @@ static int __init smsc47b397_find(unsign
 	*addr = (superio_inb(SUPERIO_REG_BASE_MSB) << 8)
 		 |  superio_inb(SUPERIO_REG_BASE_LSB);
 
-	printk(KERN_INFO DRVNAME ": found SMSC %s "
-		"(base address 0x%04x, revision %u)\n",
+	pr_info("found SMSC %s (base address 0x%04x, revision %u)\n",
 		name, *addr, rev);
 
 	superio_exit();
diff -druNp linux-libre-2.6.37-gnu1/drivers/hwmon/smsc47m1.c linux-libre-2.6.38-gnu1/drivers/hwmon/smsc47m1.c
--- linux-libre-2.6.37-gnu1/drivers/hwmon/smsc47m1.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hwmon/smsc47m1.c	2011-03-14 21:20:32.000000000 -0400
@@ -26,6 +26,8 @@
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/ioport.h>
@@ -435,30 +437,29 @@ static int __init smsc47m1_find(unsigned
 	 */
 	switch (val) {
 	case 0x51:
-		pr_info(DRVNAME ": Found SMSC LPC47B27x\n");
+		pr_info("Found SMSC LPC47B27x\n");
 		sio_data->type = smsc47m1;
 		break;
 	case 0x59:
-		pr_info(DRVNAME ": Found SMSC LPC47M10x/LPC47M112/LPC47M13x\n");
+		pr_info("Found SMSC LPC47M10x/LPC47M112/LPC47M13x\n");
 		sio_data->type = smsc47m1;
 		break;
 	case 0x5F:
-		pr_info(DRVNAME ": Found SMSC LPC47M14x\n");
+		pr_info("Found SMSC LPC47M14x\n");
 		sio_data->type = smsc47m1;
 		break;
 	case 0x60:
-		pr_info(DRVNAME ": Found SMSC LPC47M15x/LPC47M192/LPC47M997\n");
+		pr_info("Found SMSC LPC47M15x/LPC47M192/LPC47M997\n");
 		sio_data->type = smsc47m1;
 		break;
 	case 0x6B:
 		if (superio_inb(SUPERIO_REG_DEVREV) & 0x80) {
-			pr_debug(DRVNAME ": "
-				 "Found SMSC LPC47M233, unsupported\n");
+			pr_debug("Found SMSC LPC47M233, unsupported\n");
 			superio_exit();
 			return -ENODEV;
 		}
 
-		pr_info(DRVNAME ": Found SMSC LPC47M292\n");
+		pr_info("Found SMSC LPC47M292\n");
 		sio_data->type = smsc47m2;
 		break;
 	default:
@@ -470,7 +471,7 @@ static int __init smsc47m1_find(unsigned
 	*addr = (superio_inb(SUPERIO_REG_BASE) << 8)
 	      |  superio_inb(SUPERIO_REG_BASE + 1);
 	if (*addr == 0) {
-		pr_info(DRVNAME ": Device address not set, will not use\n");
+		pr_info("Device address not set, will not use\n");
 		superio_exit();
 		return -ENODEV;
 	}
@@ -479,7 +480,7 @@ static int __init smsc47m1_find(unsigned
 	 * Compaq Presario S4000NX) */
 	sio_data->activate = superio_inb(SUPERIO_REG_ACT);
 	if ((sio_data->activate & 0x01) == 0) {
-		pr_info(DRVNAME ": Enabling device\n");
+		pr_info("Enabling device\n");
 		superio_outb(SUPERIO_REG_ACT, sio_data->activate | 0x01);
 	}
 
@@ -494,7 +495,7 @@ static void smsc47m1_restore(const struc
 		superio_enter();
 		superio_select();
 
-		pr_info(DRVNAME ": Disabling device\n");
+		pr_info("Disabling device\n");
 		superio_outb(SUPERIO_REG_ACT, sio_data->activate);
 
 		superio_exit();
@@ -823,28 +824,26 @@ static int __init smsc47m1_device_add(un
 	pdev = platform_device_alloc(DRVNAME, address);
 	if (!pdev) {
 		err = -ENOMEM;
-		printk(KERN_ERR DRVNAME ": Device allocation failed\n");
+		pr_err("Device allocation failed\n");
 		goto exit;
 	}
 
 	err = platform_device_add_resources(pdev, &res, 1);
 	if (err) {
-		printk(KERN_ERR DRVNAME ": Device resource addition failed "
-		       "(%d)\n", err);
+		pr_err("Device resource addition failed (%d)\n", err);
 		goto exit_device_put;
 	}
 
 	err = platform_device_add_data(pdev, sio_data,
 				       sizeof(struct smsc47m1_sio_data));
 	if (err) {
-		printk(KERN_ERR DRVNAME ": Platform data allocation failed\n");
+		pr_err("Platform data allocation failed\n");
 		goto exit_device_put;
 	}
 
 	err = platform_device_add(pdev);
 	if (err) {
-		printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n",
-		       err);
+		pr_err("Device addition failed (%d)\n", err);
 		goto exit_device_put;
 	}
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/hwmon/via686a.c linux-libre-2.6.38-gnu1/drivers/hwmon/via686a.c
--- linux-libre-2.6.37-gnu1/drivers/hwmon/via686a.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hwmon/via686a.c	2011-03-14 21:20:32.000000000 -0400
@@ -30,6 +30,8 @@
     Warning - only supports a single device.
 */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/pci.h>
@@ -687,6 +689,13 @@ static int __devexit via686a_remove(stru
 	return 0;
 }
 
+static void via686a_update_fan_div(struct via686a_data *data)
+{
+	int reg = via686a_read_value(data, VIA686A_REG_FANDIV);
+	data->fan_div[0] = (reg >> 4) & 0x03;
+	data->fan_div[1] = reg >> 6;
+}
+
 static void __devinit via686a_init_device(struct via686a_data *data)
 {
 	u8 reg;
@@ -700,6 +709,9 @@ static void __devinit via686a_init_devic
 	via686a_write_value(data, VIA686A_REG_TEMP_MODE,
 			    (reg & ~VIA686A_TEMP_MODE_MASK)
 			    | VIA686A_TEMP_MODE_CONTINUOUS);
+
+	/* Pre-read fan clock divisor values */
+	via686a_update_fan_div(data);
 }
 
 static struct via686a_data *via686a_update_device(struct device *dev)
@@ -751,9 +763,7 @@ static struct via686a_data *via686a_upda
 		    (via686a_read_value(data, VIA686A_REG_TEMP_LOW23) &
 		     0xc0) >> 6;
 
-		i = via686a_read_value(data, VIA686A_REG_FANDIV);
-		data->fan_div[0] = (i >> 4) & 0x03;
-		data->fan_div[1] = i >> 6;
+		via686a_update_fan_div(data);
 		data->alarms =
 		    via686a_read_value(data,
 				       VIA686A_REG_ALARM1) |
@@ -791,21 +801,19 @@ static int __devinit via686a_device_add(
 	pdev = platform_device_alloc("via686a", address);
 	if (!pdev) {
 		err = -ENOMEM;
-		printk(KERN_ERR "via686a: Device allocation failed\n");
+		pr_err("Device allocation failed\n");
 		goto exit;
 	}
 
 	err = platform_device_add_resources(pdev, &res, 1);
 	if (err) {
-		printk(KERN_ERR "via686a: Device resource addition failed "
-		       "(%d)\n", err);
+		pr_err("Device resource addition failed (%d)\n", err);
 		goto exit_device_put;
 	}
 
 	err = platform_device_add(pdev);
 	if (err) {
-		printk(KERN_ERR "via686a: Device addition failed (%d)\n",
-		       err);
+		pr_err("Device addition failed (%d)\n", err);
 		goto exit_device_put;
 	}
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/hwmon/via-cputemp.c linux-libre-2.6.38-gnu1/drivers/hwmon/via-cputemp.c
--- linux-libre-2.6.37-gnu1/drivers/hwmon/via-cputemp.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hwmon/via-cputemp.c	2011-03-14 21:20:32.000000000 -0400
@@ -21,6 +21,8 @@
  * 02110-1301 USA.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
@@ -202,7 +204,7 @@ static int __cpuinit via_cputemp_device_
 	pdev = platform_device_alloc(DRVNAME, cpu);
 	if (!pdev) {
 		err = -ENOMEM;
-		printk(KERN_ERR DRVNAME ": Device allocation failed\n");
+		pr_err("Device allocation failed\n");
 		goto exit;
 	}
 
@@ -214,8 +216,7 @@ static int __cpuinit via_cputemp_device_
 
 	err = platform_device_add(pdev);
 	if (err) {
-		printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n",
-		       err);
+		pr_err("Device addition failed (%d)\n", err);
 		goto exit_device_free;
 	}
 
@@ -237,13 +238,16 @@ exit:
 
 static void __cpuinit via_cputemp_device_remove(unsigned int cpu)
 {
-	struct pdev_entry *p, *n;
+	struct pdev_entry *p;
+
 	mutex_lock(&pdev_list_mutex);
-	list_for_each_entry_safe(p, n, &pdev_list, list) {
+	list_for_each_entry(p, &pdev_list, list) {
 		if (p->cpu == cpu) {
 			platform_device_unregister(p->pdev);
 			list_del(&p->list);
+			mutex_unlock(&pdev_list_mutex);
 			kfree(p);
+			return;
 		}
 	}
 	mutex_unlock(&pdev_list_mutex);
@@ -273,7 +277,6 @@ static struct notifier_block via_cputemp
 static int __init via_cputemp_init(void)
 {
 	int i, err;
-	struct pdev_entry *p, *n;
 
 	if (cpu_data(0).x86_vendor != X86_VENDOR_CENTAUR) {
 		printk(KERN_DEBUG DRVNAME ": Not a VIA CPU\n");
@@ -295,33 +298,27 @@ static int __init via_cputemp_init(void)
 			continue;
 
 		if (c->x86_model > 0x0f) {
-			printk(KERN_WARNING DRVNAME ": Unknown CPU "
-				"model 0x%x\n", c->x86_model);
+			pr_warn("Unknown CPU model 0x%x\n", c->x86_model);
 			continue;
 		}
 
-		err = via_cputemp_device_add(i);
-		if (err)
-			goto exit_devices_unreg;
+		via_cputemp_device_add(i);
 	}
+
+#ifndef CONFIG_HOTPLUG_CPU
 	if (list_empty(&pdev_list)) {
 		err = -ENODEV;
 		goto exit_driver_unreg;
 	}
+#endif
 
 	register_hotcpu_notifier(&via_cputemp_cpu_notifier);
 	return 0;
 
-exit_devices_unreg:
-	mutex_lock(&pdev_list_mutex);
-	list_for_each_entry_safe(p, n, &pdev_list, list) {
-		platform_device_unregister(p->pdev);
-		list_del(&p->list);
-		kfree(p);
-	}
-	mutex_unlock(&pdev_list_mutex);
+#ifndef CONFIG_HOTPLUG_CPU
 exit_driver_unreg:
 	platform_driver_unregister(&via_cputemp_driver);
+#endif
 exit:
 	return err;
 }
diff -druNp linux-libre-2.6.37-gnu1/drivers/hwmon/vt1211.c linux-libre-2.6.38-gnu1/drivers/hwmon/vt1211.c
--- linux-libre-2.6.37-gnu1/drivers/hwmon/vt1211.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hwmon/vt1211.c	2011-03-14 21:20:32.000000000 -0400
@@ -21,6 +21,8 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
@@ -1254,8 +1256,7 @@ static int __init vt1211_device_add(unsi
 	pdev = platform_device_alloc(DRVNAME, address);
 	if (!pdev) {
 		err = -ENOMEM;
-		printk(KERN_ERR DRVNAME ": Device allocation failed (%d)\n",
-		       err);
+		pr_err("Device allocation failed (%d)\n", err);
 		goto EXIT;
 	}
 
@@ -1266,15 +1267,13 @@ static int __init vt1211_device_add(unsi
 
 	err = platform_device_add_resources(pdev, &res, 1);
 	if (err) {
-		printk(KERN_ERR DRVNAME ": Device resource addition failed "
-		       "(%d)\n", err);
+		pr_err("Device resource addition failed (%d)\n", err);
 		goto EXIT_DEV_PUT;
 	}
 
 	err = platform_device_add(pdev);
 	if (err) {
-		printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n",
-		       err);
+		pr_err("Device addition failed (%d)\n", err);
 		goto EXIT_DEV_PUT;
 	}
 
@@ -1301,23 +1300,20 @@ static int __init vt1211_find(int sio_ci
 	superio_select(sio_cip, SIO_VT1211_LDN_HWMON);
 
 	if ((superio_inb(sio_cip, SIO_VT1211_ACTIVE) & 1) == 0) {
-		printk(KERN_WARNING DRVNAME ": HW monitor is disabled, "
-		       "skipping\n");
+		pr_warn("HW monitor is disabled, skipping\n");
 		goto EXIT;
 	}
 
 	*address = ((superio_inb(sio_cip, SIO_VT1211_BADDR) << 8) |
 		    (superio_inb(sio_cip, SIO_VT1211_BADDR + 1))) & 0xff00;
 	if (*address == 0) {
-		printk(KERN_WARNING DRVNAME ": Base address is not set, "
-		       "skipping\n");
+		pr_warn("Base address is not set, skipping\n");
 		goto EXIT;
 	}
 
 	err = 0;
-	printk(KERN_INFO DRVNAME ": Found VT1211 chip at 0x%04x, "
-	       "revision %u\n", *address,
-	       superio_inb(sio_cip, SIO_VT1211_DEVREV));
+	pr_info("Found VT1211 chip at 0x%04x, revision %u\n",
+		*address, superio_inb(sio_cip, SIO_VT1211_DEVREV));
 
 EXIT:
 	superio_exit(sio_cip);
@@ -1336,15 +1332,15 @@ static int __init vt1211_init(void)
 
 	if ((uch_config < -1) || (uch_config > 31)) {
 		err = -EINVAL;
-		printk(KERN_WARNING DRVNAME ": Invalid UCH configuration %d. "
-		       "Choose a value between 0 and 31.\n", uch_config);
+		pr_warn("Invalid UCH configuration %d. "
+			"Choose a value between 0 and 31.\n", uch_config);
 	  goto EXIT;
 	}
 
 	if ((int_mode < -1) || (int_mode > 0)) {
 		err = -EINVAL;
-		printk(KERN_WARNING DRVNAME ": Invalid interrupt mode %d. "
-		       "Only mode 0 is supported.\n", int_mode);
+		pr_warn("Invalid interrupt mode %d. "
+			"Only mode 0 is supported.\n", int_mode);
 	  goto EXIT;
 	}
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/hwmon/vt8231.c linux-libre-2.6.38-gnu1/drivers/hwmon/vt8231.c
--- linux-libre-2.6.37-gnu1/drivers/hwmon/vt8231.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hwmon/vt8231.c	2011-03-14 21:20:32.000000000 -0400
@@ -24,6 +24,8 @@
 /* Supports VIA VT8231 South Bridge embedded sensors
 */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
@@ -902,21 +904,19 @@ static int __devinit vt8231_device_add(u
 	pdev = platform_device_alloc("vt8231", address);
 	if (!pdev) {
 		err = -ENOMEM;
-		printk(KERN_ERR "vt8231: Device allocation failed\n");
+		pr_err("Device allocation failed\n");
 		goto exit;
 	}
 
 	err = platform_device_add_resources(pdev, &res, 1);
 	if (err) {
-		printk(KERN_ERR "vt8231: Device resource addition failed "
-		       "(%d)\n", err);
+		pr_err("Device resource addition failed (%d)\n", err);
 		goto exit_device_put;
 	}
 
 	err = platform_device_add(pdev);
 	if (err) {
-		printk(KERN_ERR "vt8231: Device addition failed (%d)\n",
-		       err);
+		pr_err("Device addition failed (%d)\n", err);
 		goto exit_device_put;
 	}
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/hwmon/w83627ehf.c linux-libre-2.6.38-gnu1/drivers/hwmon/w83627ehf.c
--- linux-libre-2.6.37-gnu1/drivers/hwmon/w83627ehf.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hwmon/w83627ehf.c	2011-03-14 21:20:32.000000000 -0400
@@ -42,6 +42,8 @@
     w83667hg-b   9      5       3       3      0xb350 0xc1    0x5ca3
 */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
@@ -1668,8 +1670,7 @@ static int __init w83627ehf_find(int sio
 		break;
 	default:
 		if (val != 0xffff)
-			pr_debug(DRVNAME ": unsupported chip ID: 0x%04x\n",
-				 val);
+			pr_debug("unsupported chip ID: 0x%04x\n", val);
 		superio_exit(sioaddr);
 		return -ENODEV;
 	}
@@ -1680,8 +1681,7 @@ static int __init w83627ehf_find(int sio
 	    | superio_inb(sioaddr, SIO_REG_ADDR + 1);
 	*addr = val & IOREGION_ALIGNMENT;
 	if (*addr == 0) {
-		printk(KERN_ERR DRVNAME ": Refusing to enable a Super-I/O "
-		       "device with a base I/O port 0.\n");
+		pr_err("Refusing to enable a Super-I/O device with a base I/O port 0\n");
 		superio_exit(sioaddr);
 		return -ENODEV;
 	}
@@ -1689,13 +1689,12 @@ static int __init w83627ehf_find(int sio
 	/* Activate logical device if needed */
 	val = superio_inb(sioaddr, SIO_REG_ENABLE);
 	if (!(val & 0x01)) {
-		printk(KERN_WARNING DRVNAME ": Forcibly enabling Super-I/O. "
-		       "Sensor is probably unusable.\n");
+		pr_warn("Forcibly enabling Super-I/O. Sensor is probably unusable.\n");
 		superio_outb(sioaddr, SIO_REG_ENABLE, val | 0x01);
 	}
 
 	superio_exit(sioaddr);
-	pr_info(DRVNAME ": Found %s chip at %#x\n", sio_name, *addr);
+	pr_info("Found %s chip at %#x\n", sio_name, *addr);
 	sio_data->sioreg = sioaddr;
 
 	return 0;
@@ -1729,14 +1728,14 @@ static int __init sensors_w83627ehf_init
 
 	if (!(pdev = platform_device_alloc(DRVNAME, address))) {
 		err = -ENOMEM;
-		printk(KERN_ERR DRVNAME ": Device allocation failed\n");
+		pr_err("Device allocation failed\n");
 		goto exit_unregister;
 	}
 
 	err = platform_device_add_data(pdev, &sio_data,
 				       sizeof(struct w83627ehf_sio_data));
 	if (err) {
-		printk(KERN_ERR DRVNAME ": Platform data allocation failed\n");
+		pr_err("Platform data allocation failed\n");
 		goto exit_device_put;
 	}
 
@@ -1752,16 +1751,14 @@ static int __init sensors_w83627ehf_init
 
 	err = platform_device_add_resources(pdev, &res, 1);
 	if (err) {
-		printk(KERN_ERR DRVNAME ": Device resource addition failed "
-		       "(%d)\n", err);
+		pr_err("Device resource addition failed (%d)\n", err);
 		goto exit_device_put;
 	}
 
 	/* platform_device_add calls probe() */
 	err = platform_device_add(pdev);
 	if (err) {
-		printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n",
-		       err);
+		pr_err("Device addition failed (%d)\n", err);
 		goto exit_device_put;
 	}
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/hwmon/w83627hf.c linux-libre-2.6.38-gnu1/drivers/hwmon/w83627hf.c
--- linux-libre-2.6.37-gnu1/drivers/hwmon/w83627hf.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hwmon/w83627hf.c	2011-03-14 21:20:32.000000000 -0400
@@ -39,6 +39,8 @@
     supported yet.
 */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
@@ -1166,14 +1168,13 @@ static int __init w83627hf_find(int sioa
 	       superio_inb(sio_data, WINB_BASE_REG + 1);
 	*addr = val & WINB_ALIGNMENT;
 	if (*addr == 0) {
-		printk(KERN_WARNING DRVNAME ": Base address not set, "
-		       "skipping\n");
+		pr_warn("Base address not set, skipping\n");
 		goto exit;
 	}
 
 	val = superio_inb(sio_data, WINB_ACT_REG);
 	if (!(val & 0x01)) {
-		printk(KERN_WARNING DRVNAME ": Enabling HWM logical device\n");
+		pr_warn("Enabling HWM logical device\n");
 		superio_outb(sio_data, WINB_ACT_REG, val | 0x01);
 	}
 
@@ -1789,28 +1790,26 @@ static int __init w83627hf_device_add(un
 	pdev = platform_device_alloc(DRVNAME, address);
 	if (!pdev) {
 		err = -ENOMEM;
-		printk(KERN_ERR DRVNAME ": Device allocation failed\n");
+		pr_err("Device allocation failed\n");
 		goto exit;
 	}
 
 	err = platform_device_add_resources(pdev, &res, 1);
 	if (err) {
-		printk(KERN_ERR DRVNAME ": Device resource addition failed "
-		       "(%d)\n", err);
+		pr_err("Device resource addition failed (%d)\n", err);
 		goto exit_device_put;
 	}
 
 	err = platform_device_add_data(pdev, sio_data,
 				       sizeof(struct w83627hf_sio_data));
 	if (err) {
-		printk(KERN_ERR DRVNAME ": Platform data allocation failed\n");
+		pr_err("Platform data allocation failed\n");
 		goto exit_device_put;
 	}
 
 	err = platform_device_add(pdev);
 	if (err) {
-		printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n",
-		       err);
+		pr_err("Device addition failed (%d)\n", err);
 		goto exit_device_put;
 	}
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/hwmon/w83781d.c linux-libre-2.6.38-gnu1/drivers/hwmon/w83781d.c
--- linux-libre-2.6.37-gnu1/drivers/hwmon/w83781d.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hwmon/w83781d.c	2011-03-14 21:20:32.000000000 -0400
@@ -33,6 +33,8 @@
 
 */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
@@ -1798,8 +1800,7 @@ w83781d_isa_found(unsigned short address
 	 * individually for the probing phase. */
 	for (port = address; port < address + W83781D_EXTENT; port++) {
 		if (!request_region(port, 1, "w83781d")) {
-			pr_debug("w83781d: Failed to request port 0x%x\n",
-				 port);
+			pr_debug("Failed to request port 0x%x\n", port);
 			goto release;
 		}
 	}
@@ -1811,7 +1812,7 @@ w83781d_isa_found(unsigned short address
 	if (inb_p(address + 2) != val
 	 || inb_p(address + 3) != val
 	 || inb_p(address + 7) != val) {
-		pr_debug("w83781d: Detection failed at step 1\n");
+		pr_debug("Detection failed at step %d\n", 1);
 		goto release;
 	}
 #undef REALLY_SLOW_IO
@@ -1820,14 +1821,14 @@ w83781d_isa_found(unsigned short address
 	   MSB (busy flag) should be clear initially, set after the write. */
 	save = inb_p(address + W83781D_ADDR_REG_OFFSET);
 	if (save & 0x80) {
-		pr_debug("w83781d: Detection failed at step 2\n");
+		pr_debug("Detection failed at step %d\n", 2);
 		goto release;
 	}
 	val = ~save & 0x7f;
 	outb_p(val, address + W83781D_ADDR_REG_OFFSET);
 	if (inb_p(address + W83781D_ADDR_REG_OFFSET) != (val | 0x80)) {
 		outb_p(save, address + W83781D_ADDR_REG_OFFSET);
-		pr_debug("w83781d: Detection failed at step 3\n");
+		pr_debug("Detection failed at step %d\n", 3);
 		goto release;
 	}
 
@@ -1835,7 +1836,7 @@ w83781d_isa_found(unsigned short address
 	outb_p(W83781D_REG_CONFIG, address + W83781D_ADDR_REG_OFFSET);
 	val = inb_p(address + W83781D_DATA_REG_OFFSET);
 	if (val & 0x80) {
-		pr_debug("w83781d: Detection failed at step 4\n");
+		pr_debug("Detection failed at step %d\n", 4);
 		goto release;
 	}
 	outb_p(W83781D_REG_BANK, address + W83781D_ADDR_REG_OFFSET);
@@ -1844,19 +1845,19 @@ w83781d_isa_found(unsigned short address
 	val = inb_p(address + W83781D_DATA_REG_OFFSET);
 	if ((!(save & 0x80) && (val != 0xa3))
 	 || ((save & 0x80) && (val != 0x5c))) {
-		pr_debug("w83781d: Detection failed at step 5\n");
+		pr_debug("Detection failed at step %d\n", 5);
 		goto release;
 	}
 	outb_p(W83781D_REG_I2C_ADDR, address + W83781D_ADDR_REG_OFFSET);
 	val = inb_p(address + W83781D_DATA_REG_OFFSET);
 	if (val < 0x03 || val > 0x77) {	/* Not a valid I2C address */
-		pr_debug("w83781d: Detection failed at step 6\n");
+		pr_debug("Detection failed at step %d\n", 6);
 		goto release;
 	}
 
 	/* The busy flag should be clear again */
 	if (inb_p(address + W83781D_ADDR_REG_OFFSET) & 0x80) {
-		pr_debug("w83781d: Detection failed at step 7\n");
+		pr_debug("Detection failed at step %d\n", 7);
 		goto release;
 	}
 
@@ -1871,7 +1872,7 @@ w83781d_isa_found(unsigned short address
 		found = 1;
 
 	if (found)
-		pr_info("w83781d: Found a %s chip at %#x\n",
+		pr_info("Found a %s chip at %#x\n",
 			val == 0x30 ? "W83782D" : "W83781D", (int)address);
 
  release:
@@ -1894,21 +1895,19 @@ w83781d_isa_device_add(unsigned short ad
 	pdev = platform_device_alloc("w83781d", address);
 	if (!pdev) {
 		err = -ENOMEM;
-		printk(KERN_ERR "w83781d: Device allocation failed\n");
+		pr_err("Device allocation failed\n");
 		goto exit;
 	}
 
 	err = platform_device_add_resources(pdev, &res, 1);
 	if (err) {
-		printk(KERN_ERR "w83781d: Device resource addition failed "
-		       "(%d)\n", err);
+		pr_err("Device resource addition failed (%d)\n", err);
 		goto exit_device_put;
 	}
 
 	err = platform_device_add(pdev);
 	if (err) {
-		printk(KERN_ERR "w83781d: Device addition failed (%d)\n",
-		       err);
+		pr_err("Device addition failed (%d)\n", err);
 		goto exit_device_put;
 	}
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/hwmon/w83792d.c linux-libre-2.6.38-gnu1/drivers/hwmon/w83792d.c
--- linux-libre-2.6.37-gnu1/drivers/hwmon/w83792d.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hwmon/w83792d.c	2011-03-14 21:20:32.000000000 -0400
@@ -691,7 +691,7 @@ store_pwm_mode(struct device *dev, struc
 }
 
 static ssize_t
-show_regs_chassis(struct device *dev, struct device_attribute *attr,
+show_chassis(struct device *dev, struct device_attribute *attr,
 			char *buf)
 {
 	struct w83792d_data *data = w83792d_update_device(dev);
@@ -699,6 +699,16 @@ show_regs_chassis(struct device *dev, st
 }
 
 static ssize_t
+show_regs_chassis(struct device *dev, struct device_attribute *attr,
+			char *buf)
+{
+	dev_warn(dev,
+		 "Attribute %s is deprecated, use intrusion0_alarm instead\n",
+		 "chassis");
+	return show_chassis(dev, attr, buf);
+}
+
+static ssize_t
 show_chassis_clear(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct w83792d_data *data = w83792d_update_device(dev);
@@ -706,7 +716,7 @@ show_chassis_clear(struct device *dev, s
 }
 
 static ssize_t
-store_chassis_clear(struct device *dev, struct device_attribute *attr,
+store_chassis_clear_legacy(struct device *dev, struct device_attribute *attr,
 			const char *buf, size_t count)
 {
 	struct i2c_client *client = to_i2c_client(dev);
@@ -714,6 +724,10 @@ store_chassis_clear(struct device *dev,
 	u32 val;
 	u8 temp1 = 0, temp2 = 0;
 
+	dev_warn(dev,
+		 "Attribute %s is deprecated, use intrusion0_alarm instead\n",
+		 "chassis_clear");
+
 	val = simple_strtoul(buf, NULL, 10);
 	mutex_lock(&data->update_lock);
 	data->chassis_clear = SENSORS_LIMIT(val, 0 ,1);
@@ -726,6 +740,27 @@ store_chassis_clear(struct device *dev,
 	return count;
 }
 
+static ssize_t
+store_chassis_clear(struct device *dev, struct device_attribute *attr,
+			const char *buf, size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct w83792d_data *data = i2c_get_clientdata(client);
+	unsigned long val;
+	u8 reg;
+
+	if (strict_strtoul(buf, 10, &val) || val != 0)
+		return -EINVAL;
+
+	mutex_lock(&data->update_lock);
+	reg = w83792d_read_value(client, W83792D_REG_CHASSIS_CLR);
+	w83792d_write_value(client, W83792D_REG_CHASSIS_CLR, reg | 0x80);
+	data->valid = 0;		/* Force cache refresh */
+	mutex_unlock(&data->update_lock);
+
+	return count;
+}
+
 /* For Smart Fan I / Thermal Cruise */
 static ssize_t
 show_thermal_cruise(struct device *dev, struct device_attribute *attr,
@@ -1012,7 +1047,9 @@ static SENSOR_DEVICE_ATTR(fan5_alarm, S_
 static SENSOR_DEVICE_ATTR(fan6_alarm, S_IRUGO, show_alarm, NULL, 23);
 static DEVICE_ATTR(chassis, S_IRUGO, show_regs_chassis, NULL);
 static DEVICE_ATTR(chassis_clear, S_IRUGO | S_IWUSR,
-			show_chassis_clear, store_chassis_clear);
+			show_chassis_clear, store_chassis_clear_legacy);
+static DEVICE_ATTR(intrusion0_alarm, S_IRUGO | S_IWUSR,
+			show_chassis, store_chassis_clear);
 static SENSOR_DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 0);
 static SENSOR_DEVICE_ATTR(pwm2, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 1);
 static SENSOR_DEVICE_ATTR(pwm3, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 2);
@@ -1214,6 +1251,7 @@ static struct attribute *w83792d_attribu
 	&dev_attr_alarms.attr,
 	&dev_attr_chassis.attr,
 	&dev_attr_chassis_clear.attr,
+	&dev_attr_intrusion0_alarm.attr,
 	&sensor_dev_attr_tolerance1.dev_attr.attr,
 	&sensor_dev_attr_thermal_cruise1.dev_attr.attr,
 	&sensor_dev_attr_tolerance2.dev_attr.attr,
diff -druNp linux-libre-2.6.37-gnu1/drivers/hwmon/w83793.c linux-libre-2.6.38-gnu1/drivers/hwmon/w83793.c
--- linux-libre-2.6.37-gnu1/drivers/hwmon/w83793.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hwmon/w83793.c	2011-03-14 21:20:32.000000000 -0400
@@ -51,7 +51,6 @@
 #define WATCHDOG_TIMEOUT 2	/* 2 minute default timeout */
 
 /* Addresses to scan */
-static DEFINE_MUTEX(watchdog_mutex);
 static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, 0x2f,
 						I2C_CLIENT_END };
 
@@ -421,14 +420,17 @@ store_beep_enable(struct device *dev, st
 
 /* Write any value to clear chassis alarm */
 static ssize_t
-store_chassis_clear(struct device *dev,
-		    struct device_attribute *attr, const char *buf,
-		    size_t count)
+store_chassis_clear_legacy(struct device *dev,
+			   struct device_attribute *attr, const char *buf,
+			   size_t count)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct w83793_data *data = i2c_get_clientdata(client);
 	u8 val;
 
+	dev_warn(dev, "Attribute chassis is deprecated, "
+		 "use intrusion0_alarm instead\n");
+
 	mutex_lock(&data->update_lock);
 	val = w83793_read_value(client, W83793_REG_CLR_CHASSIS);
 	val |= 0x80;
@@ -437,6 +439,28 @@ store_chassis_clear(struct device *dev,
 	return count;
 }
 
+/* Write 0 to clear chassis alarm */
+static ssize_t
+store_chassis_clear(struct device *dev,
+		    struct device_attribute *attr, const char *buf,
+		    size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct w83793_data *data = i2c_get_clientdata(client);
+	unsigned long val;
+	u8 reg;
+
+	if (strict_strtoul(buf, 10, &val) || val != 0)
+		return -EINVAL;
+
+	mutex_lock(&data->update_lock);
+	reg = w83793_read_value(client, W83793_REG_CLR_CHASSIS);
+	w83793_write_value(client, W83793_REG_CLR_CHASSIS, reg | 0x80);
+	data->valid = 0;		/* Force cache refresh */
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
 #define FAN_INPUT			0
 #define FAN_MIN				1
 static ssize_t
@@ -1102,6 +1126,8 @@ static DEVICE_ATTR(vrm, S_IWUSR | S_IRUG
 
 static struct sensor_device_attribute_2 sda_single_files[] = {
 	SENSOR_ATTR_2(chassis, S_IWUSR | S_IRUGO, show_alarm_beep,
+		      store_chassis_clear_legacy, ALARM_STATUS, 30),
+	SENSOR_ATTR_2(intrusion0_alarm, S_IWUSR | S_IRUGO, show_alarm_beep,
 		      store_chassis_clear, ALARM_STATUS, 30),
 	SENSOR_ATTR_2(beep_enable, S_IWUSR | S_IRUGO, show_beep_enable,
 		      store_beep_enable, NOT_USED, NOT_USED),
@@ -1323,7 +1349,7 @@ static ssize_t watchdog_write(struct fil
 static long watchdog_ioctl(struct file *filp, unsigned int cmd,
 			   unsigned long arg)
 {
-	static struct watchdog_info ident = {
+	struct watchdog_info ident = {
 		.options = WDIOF_KEEPALIVEPING |
 			   WDIOF_SETTIMEOUT |
 			   WDIOF_CARDRESET,
@@ -1333,7 +1359,6 @@ static long watchdog_ioctl(struct file *
 	int val, ret = 0;
 	struct w83793_data *data = filp->private_data;
 
-	mutex_lock(&watchdog_mutex);
 	switch (cmd) {
 	case WDIOC_GETSUPPORT:
 		if (!nowayout)
@@ -1387,7 +1412,6 @@ static long watchdog_ioctl(struct file *
 	default:
 		ret = -ENOTTY;
 	}
-	mutex_unlock(&watchdog_mutex);
 	return ret;
 }
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/hwmon/w83795.c linux-libre-2.6.38-gnu1/drivers/hwmon/w83795.c
--- linux-libre-2.6.37-gnu1/drivers/hwmon/w83795.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/hwmon/w83795.c	2011-03-14 21:20:32.000000000 -0400
@@ -458,6 +458,7 @@ static void w83795_update_limits(struct
 {
 	struct w83795_data *data = i2c_get_clientdata(client);
 	int i, limit;
+	u8 lsb;
 
 	/* Read the voltage limits */
 	for (i = 0; i < ARRAY_SIZE(data->in); i++) {
@@ -479,9 +480,8 @@ static void w83795_update_limits(struct
 	}
 
 	/* Read the fan limits */
+	lsb = 0; /* Silent false gcc warning */
 	for (i = 0; i < ARRAY_SIZE(data->fan); i++) {
-		u8 lsb;
-
 		/* Each register contains LSB for 2 fans, but we want to
 		 * read it only once to save time */
 		if ((i & 1) == 0 && (data->has_fan & (3 << i)))
diff -druNp linux-libre-2.6.37-gnu1/drivers/i2c/algos/i2c-algo-bit.c linux-libre-2.6.38-gnu1/drivers/i2c/algos/i2c-algo-bit.c
--- linux-libre-2.6.37-gnu1/drivers/i2c/algos/i2c-algo-bit.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/i2c/algos/i2c-algo-bit.c	2011-03-14 21:20:32.000000000 -0400
@@ -600,12 +600,14 @@ static const struct i2c_algorithm i2c_bi
 /*
  * registering functions to load algorithms at runtime
  */
-static int i2c_bit_prepare_bus(struct i2c_adapter *adap)
+static int __i2c_bit_add_bus(struct i2c_adapter *adap,
+			     int (*add_adapter)(struct i2c_adapter *))
 {
 	struct i2c_algo_bit_data *bit_adap = adap->algo_data;
+	int ret;
 
 	if (bit_test) {
-		int ret = test_bus(bit_adap, adap->name);
+		ret = test_bus(bit_adap, adap->name);
 		if (ret < 0)
 			return -ENODEV;
 	}
@@ -614,30 +616,27 @@ static int i2c_bit_prepare_bus(struct i2
 	adap->algo = &i2c_bit_algo;
 	adap->retries = 3;
 
+	ret = add_adapter(adap);
+	if (ret < 0)
+		return ret;
+
+	/* Complain if SCL can't be read */
+	if (bit_adap->getscl == NULL) {
+		dev_warn(&adap->dev, "Not I2C compliant: can't read SCL\n");
+		dev_warn(&adap->dev, "Bus may be unreliable\n");
+	}
 	return 0;
 }
 
 int i2c_bit_add_bus(struct i2c_adapter *adap)
 {
-	int err;
-
-	err = i2c_bit_prepare_bus(adap);
-	if (err)
-		return err;
-
-	return i2c_add_adapter(adap);
+	return __i2c_bit_add_bus(adap, i2c_add_adapter);
 }
 EXPORT_SYMBOL(i2c_bit_add_bus);
 
 int i2c_bit_add_numbered_bus(struct i2c_adapter *adap)
 {
-	int err;
-
-	err = i2c_bit_prepare_bus(adap);
-	if (err)
-		return err;
-
-	return i2c_add_numbered_adapter(adap);
+	return __i2c_bit_add_bus(adap, i2c_add_numbered_adapter);
 }
 EXPORT_SYMBOL(i2c_bit_add_numbered_bus);
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/i2c/busses/i2c-bfin-twi.c linux-libre-2.6.38-gnu1/drivers/i2c/busses/i2c-bfin-twi.c
--- linux-libre-2.6.37-gnu1/drivers/i2c/busses/i2c-bfin-twi.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/i2c/busses/i2c-bfin-twi.c	2011-03-14 21:20:32.000000000 -0400
@@ -20,6 +20,7 @@
 #include <linux/completion.h>
 #include <linux/interrupt.h>
 #include <linux/platform_device.h>
+#include <linux/delay.h>
 
 #include <asm/blackfin.h>
 #include <asm/portmux.h>
@@ -159,6 +160,27 @@ static void bfin_twi_handle_interrupt(st
 		if (mast_stat & BUFWRERR)
 			dev_dbg(&iface->adap.dev, "Buffer Write Error\n");
 
+		/* Faulty slave devices, may drive SDA low after a transfer
+		 * finishes. To release the bus this code generates up to 9
+		 * extra clocks until SDA is released.
+		 */
+
+		if (read_MASTER_STAT(iface) & SDASEN) {
+			int cnt = 9;
+			do {
+				write_MASTER_CTL(iface, SCLOVR);
+				udelay(6);
+				write_MASTER_CTL(iface, 0);
+				udelay(6);
+			} while ((read_MASTER_STAT(iface) & SDASEN) && cnt--);
+
+			write_MASTER_CTL(iface, SDAOVR | SCLOVR);
+			udelay(6);
+			write_MASTER_CTL(iface, SDAOVR);
+			udelay(6);
+			write_MASTER_CTL(iface, 0);
+		}
+
 		/* If it is a quick transfer, only address without data,
 		 * not an err, return 1.
 		 */
@@ -760,7 +782,7 @@ static void __exit i2c_bfin_twi_exit(voi
 	platform_driver_unregister(&i2c_bfin_twi_driver);
 }
 
-module_init(i2c_bfin_twi_init);
+subsys_initcall(i2c_bfin_twi_init);
 module_exit(i2c_bfin_twi_exit);
 
 MODULE_AUTHOR("Bryan Wu, Sonic Zhang");
diff -druNp linux-libre-2.6.37-gnu1/drivers/i2c/busses/i2c-eg20t.c linux-libre-2.6.38-gnu1/drivers/i2c/busses/i2c-eg20t.c
--- linux-libre-2.6.37-gnu1/drivers/i2c/busses/i2c-eg20t.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/i2c/busses/i2c-eg20t.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,901 @@
+/*
+ * Copyright (C) 2010 OKI SEMICONDUCTOR 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; 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/kernel.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/i2c.h>
+#include <linux/fs.h>
+#include <linux/io.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/jiffies.h>
+#include <linux/pci.h>
+#include <linux/mutex.h>
+#include <linux/ktime.h>
+#include <linux/slab.h>
+
+#define PCH_EVENT_SET	0	/* I2C Interrupt Event Set Status */
+#define PCH_EVENT_NONE	1	/* I2C Interrupt Event Clear Status */
+#define PCH_MAX_CLK		100000	/* Maximum Clock speed in MHz */
+#define PCH_BUFFER_MODE_ENABLE	0x0002	/* flag for Buffer mode enable */
+#define PCH_EEPROM_SW_RST_MODE_ENABLE	0x0008	/* EEPROM SW RST enable flag */
+
+#define PCH_I2CSADR	0x00	/* I2C slave address register */
+#define PCH_I2CCTL	0x04	/* I2C control register */
+#define PCH_I2CSR	0x08	/* I2C status register */
+#define PCH_I2CDR	0x0C	/* I2C data register */
+#define PCH_I2CMON	0x10	/* I2C bus monitor register */
+#define PCH_I2CBC	0x14	/* I2C bus transfer rate setup counter */
+#define PCH_I2CMOD	0x18	/* I2C mode register */
+#define PCH_I2CBUFSLV	0x1C	/* I2C buffer mode slave address register */
+#define PCH_I2CBUFSUB	0x20	/* I2C buffer mode subaddress register */
+#define PCH_I2CBUFFOR	0x24	/* I2C buffer mode format register */
+#define PCH_I2CBUFCTL	0x28	/* I2C buffer mode control register */
+#define PCH_I2CBUFMSK	0x2C	/* I2C buffer mode interrupt mask register */
+#define PCH_I2CBUFSTA	0x30	/* I2C buffer mode status register */
+#define PCH_I2CBUFLEV	0x34	/* I2C buffer mode level register */
+#define PCH_I2CESRFOR	0x38	/* EEPROM software reset mode format register */
+#define PCH_I2CESRCTL	0x3C	/* EEPROM software reset mode ctrl register */
+#define PCH_I2CESRMSK	0x40	/* EEPROM software reset mode */
+#define PCH_I2CESRSTA	0x44	/* EEPROM software reset mode status register */
+#define PCH_I2CTMR	0x48	/* I2C timer register */
+#define PCH_I2CSRST	0xFC	/* I2C reset register */
+#define PCH_I2CNF	0xF8	/* I2C noise filter register */
+
+#define BUS_IDLE_TIMEOUT	20
+#define PCH_I2CCTL_I2CMEN	0x0080
+#define TEN_BIT_ADDR_DEFAULT	0xF000
+#define TEN_BIT_ADDR_MASK	0xF0
+#define PCH_START		0x0020
+#define PCH_ESR_START		0x0001
+#define PCH_BUFF_START		0x1
+#define PCH_REPSTART		0x0004
+#define PCH_ACK			0x0008
+#define PCH_GETACK		0x0001
+#define CLR_REG			0x0
+#define I2C_RD			0x1
+#define I2CMCF_BIT		0x0080
+#define I2CMIF_BIT		0x0002
+#define I2CMAL_BIT		0x0010
+#define I2CBMFI_BIT		0x0001
+#define I2CBMAL_BIT		0x0002
+#define I2CBMNA_BIT		0x0004
+#define I2CBMTO_BIT		0x0008
+#define I2CBMIS_BIT		0x0010
+#define I2CESRFI_BIT		0X0001
+#define I2CESRTO_BIT		0x0002
+#define I2CESRFIIE_BIT		0x1
+#define I2CESRTOIE_BIT		0x2
+#define I2CBMDZ_BIT		0x0040
+#define I2CBMAG_BIT		0x0020
+#define I2CMBB_BIT		0x0020
+#define BUFFER_MODE_MASK	(I2CBMFI_BIT | I2CBMAL_BIT | I2CBMNA_BIT | \
+				I2CBMTO_BIT | I2CBMIS_BIT)
+#define I2C_ADDR_MSK		0xFF
+#define I2C_MSB_2B_MSK		0x300
+#define FAST_MODE_CLK		400
+#define FAST_MODE_EN		0x0001
+#define SUB_ADDR_LEN_MAX	4
+#define BUF_LEN_MAX		32
+#define PCH_BUFFER_MODE		0x1
+#define EEPROM_SW_RST_MODE	0x0002
+#define NORMAL_INTR_ENBL	0x0300
+#define EEPROM_RST_INTR_ENBL	(I2CESRFIIE_BIT | I2CESRTOIE_BIT)
+#define EEPROM_RST_INTR_DISBL	0x0
+#define BUFFER_MODE_INTR_ENBL	0x001F
+#define BUFFER_MODE_INTR_DISBL	0x0
+#define NORMAL_MODE		0x0
+#define BUFFER_MODE		0x1
+#define EEPROM_SR_MODE		0x2
+#define I2C_TX_MODE		0x0010
+#define PCH_BUF_TX		0xFFF7
+#define PCH_BUF_RD		0x0008
+#define I2C_ERROR_MASK	(I2CESRTO_EVENT | I2CBMIS_EVENT | I2CBMTO_EVENT | \
+			I2CBMNA_EVENT | I2CBMAL_EVENT | I2CMAL_EVENT)
+#define I2CMAL_EVENT		0x0001
+#define I2CMCF_EVENT		0x0002
+#define I2CBMFI_EVENT		0x0004
+#define I2CBMAL_EVENT		0x0008
+#define I2CBMNA_EVENT		0x0010
+#define I2CBMTO_EVENT		0x0020
+#define I2CBMIS_EVENT		0x0040
+#define I2CESRFI_EVENT		0x0080
+#define I2CESRTO_EVENT		0x0100
+#define PCI_DEVICE_ID_PCH_I2C	0x8817
+
+#define pch_dbg(adap, fmt, arg...)  \
+	dev_dbg(adap->pch_adapter.dev.parent, "%s :" fmt, __func__, ##arg)
+
+#define pch_err(adap, fmt, arg...)  \
+	dev_err(adap->pch_adapter.dev.parent, "%s :" fmt, __func__, ##arg)
+
+#define pch_pci_err(pdev, fmt, arg...)  \
+	dev_err(&pdev->dev, "%s :" fmt, __func__, ##arg)
+
+#define pch_pci_dbg(pdev, fmt, arg...)  \
+	dev_dbg(&pdev->dev, "%s :" fmt, __func__, ##arg)
+
+/**
+ * struct i2c_algo_pch_data - for I2C driver functionalities
+ * @pch_adapter:		stores the reference to i2c_adapter structure
+ * @p_adapter_info:		stores the reference to adapter_info structure
+ * @pch_base_address:		specifies the remapped base address
+ * @pch_buff_mode_en:		specifies if buffer mode is enabled
+ * @pch_event_flag:		specifies occurrence of interrupt events
+ * @pch_i2c_xfer_in_progress:	specifies whether the transfer is completed
+ */
+struct i2c_algo_pch_data {
+	struct i2c_adapter pch_adapter;
+	struct adapter_info *p_adapter_info;
+	void __iomem *pch_base_address;
+	int pch_buff_mode_en;
+	u32 pch_event_flag;
+	bool pch_i2c_xfer_in_progress;
+};
+
+/**
+ * struct adapter_info - This structure holds the adapter information for the
+			 PCH i2c controller
+ * @pch_data:		stores a list of i2c_algo_pch_data
+ * @pch_i2c_suspended:	specifies whether the system is suspended or not
+ *			perhaps with more lines and words.
+ *
+ * pch_data has as many elements as maximum I2C channels
+ */
+struct adapter_info {
+	struct i2c_algo_pch_data pch_data;
+	bool pch_i2c_suspended;
+};
+
+
+static int pch_i2c_speed = 100; /* I2C bus speed in Kbps */
+static int pch_clk = 50000;	/* specifies I2C clock speed in KHz */
+static wait_queue_head_t pch_event;
+static DEFINE_MUTEX(pch_mutex);
+
+static struct pci_device_id __devinitdata pch_pcidev_id[] = {
+	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PCH_I2C)},
+	{0,}
+};
+
+static irqreturn_t pch_i2c_handler(int irq, void *pData);
+
+static inline void pch_setbit(void __iomem *addr, u32 offset, u32 bitmask)
+{
+	u32 val;
+	val = ioread32(addr + offset);
+	val |= bitmask;
+	iowrite32(val, addr + offset);
+}
+
+static inline void pch_clrbit(void __iomem *addr, u32 offset, u32 bitmask)
+{
+	u32 val;
+	val = ioread32(addr + offset);
+	val &= (~bitmask);
+	iowrite32(val, addr + offset);
+}
+
+/**
+ * pch_i2c_init() - hardware initialization of I2C module
+ * @adap:	Pointer to struct i2c_algo_pch_data.
+ */
+static void pch_i2c_init(struct i2c_algo_pch_data *adap)
+{
+	void __iomem *p = adap->pch_base_address;
+	u32 pch_i2cbc;
+	u32 pch_i2ctmr;
+	u32 reg_value;
+
+	/* reset I2C controller */
+	iowrite32(0x01, p + PCH_I2CSRST);
+	msleep(20);
+	iowrite32(0x0, p + PCH_I2CSRST);
+
+	/* Initialize I2C registers */
+	iowrite32(0x21, p + PCH_I2CNF);
+
+	pch_setbit(adap->pch_base_address, PCH_I2CCTL,
+			  PCH_I2CCTL_I2CMEN);
+
+	if (pch_i2c_speed != 400)
+		pch_i2c_speed = 100;
+
+	reg_value = PCH_I2CCTL_I2CMEN;
+	if (pch_i2c_speed == FAST_MODE_CLK) {
+		reg_value |= FAST_MODE_EN;
+		pch_dbg(adap, "Fast mode enabled\n");
+	}
+
+	if (pch_clk > PCH_MAX_CLK)
+		pch_clk = 62500;
+
+	pch_i2cbc = (pch_clk + (pch_i2c_speed * 4)) / pch_i2c_speed * 8;
+	/* Set transfer speed in I2CBC */
+	iowrite32(pch_i2cbc, p + PCH_I2CBC);
+
+	pch_i2ctmr = (pch_clk) / 8;
+	iowrite32(pch_i2ctmr, p + PCH_I2CTMR);
+
+	reg_value |= NORMAL_INTR_ENBL;	/* Enable interrupts in normal mode */
+	iowrite32(reg_value, p + PCH_I2CCTL);
+
+	pch_dbg(adap,
+		"I2CCTL=%x pch_i2cbc=%x pch_i2ctmr=%x Enable interrupts\n",
+		ioread32(p + PCH_I2CCTL), pch_i2cbc, pch_i2ctmr);
+
+	init_waitqueue_head(&pch_event);
+}
+
+static inline bool ktime_lt(const ktime_t cmp1, const ktime_t cmp2)
+{
+	return cmp1.tv64 < cmp2.tv64;
+}
+
+/**
+ * pch_i2c_wait_for_bus_idle() - check the status of bus.
+ * @adap:	Pointer to struct i2c_algo_pch_data.
+ * @timeout:	waiting time counter (us).
+ */
+static s32 pch_i2c_wait_for_bus_idle(struct i2c_algo_pch_data *adap,
+				 s32 timeout)
+{
+	void __iomem *p = adap->pch_base_address;
+
+	/* MAX timeout value is timeout*1000*1000nsec */
+	ktime_t ns_val = ktime_add_ns(ktime_get(), timeout*1000*1000);
+	do {
+		if ((ioread32(p + PCH_I2CSR) & I2CMBB_BIT) == 0)
+			break;
+		msleep(20);
+	} while (ktime_lt(ktime_get(), ns_val));
+
+	pch_dbg(adap, "I2CSR = %x\n", ioread32(p + PCH_I2CSR));
+
+	if (timeout == 0) {
+		pch_err(adap, "%s: Timeout Error.return%d\n", __func__, -ETIME);
+		return -ETIME;
+	}
+
+	return 0;
+}
+
+/**
+ * pch_i2c_start() - Generate I2C start condition in normal mode.
+ * @adap:	Pointer to struct i2c_algo_pch_data.
+ *
+ * Generate I2C start condition in normal mode by setting I2CCTL.I2CMSTA to 1.
+ */
+static void pch_i2c_start(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_START);
+}
+
+/**
+ * pch_i2c_wait_for_xfer_complete() - initiates a wait for the tx complete event
+ * @adap:	Pointer to struct i2c_algo_pch_data.
+ */
+static s32 pch_i2c_wait_for_xfer_complete(struct i2c_algo_pch_data *adap)
+{
+	s32 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);
+		return -ETIMEDOUT;
+	}
+
+	if (adap->pch_event_flag & I2C_ERROR_MASK) {
+		pch_err(adap, "error bits set: %x\n", adap->pch_event_flag);
+		return -EIO;
+	}
+
+	adap->pch_event_flag = 0;
+
+	return 0;
+}
+
+/**
+ * pch_i2c_getack() - to confirm ACK/NACK
+ * @adap:	Pointer to struct i2c_algo_pch_data.
+ */
+static s32 pch_i2c_getack(struct i2c_algo_pch_data *adap)
+{
+	u32 reg_val;
+	void __iomem *p = adap->pch_base_address;
+	reg_val = ioread32(p + PCH_I2CSR) & PCH_GETACK;
+
+	if (reg_val != 0) {
+		pch_err(adap, "return%d\n", -EPROTO);
+		return -EPROTO;
+	}
+
+	return 0;
+}
+
+/**
+ * pch_i2c_stop() - generate stop condition in normal mode.
+ * @adap:	Pointer to struct i2c_algo_pch_data.
+ */
+static void pch_i2c_stop(struct i2c_algo_pch_data *adap)
+{
+	void __iomem *p = adap->pch_base_address;
+	pch_dbg(adap, "I2CCTL = %x\n", ioread32(p + PCH_I2CCTL));
+	/* clear the start bit */
+	pch_clrbit(adap->pch_base_address, PCH_I2CCTL, PCH_START);
+}
+
+/**
+ * pch_i2c_repstart() - generate repeated start condition in normal mode
+ * @adap:	Pointer to struct i2c_algo_pch_data.
+ */
+static void pch_i2c_repstart(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_REPSTART);
+}
+
+/**
+ * pch_i2c_writebytes() - write data to I2C bus in normal mode
+ * @i2c_adap:	Pointer to the struct i2c_adapter.
+ * @last:	specifies whether last message or not.
+ *		In the case of compound mode it will be 1 for last message,
+ *		otherwise 0.
+ * @first:	specifies whether first message or not.
+ *		1 for first message otherwise 0.
+ */
+static s32 pch_i2c_writebytes(struct i2c_adapter *i2c_adap,
+			      struct i2c_msg *msgs, u32 last, u32 first)
+{
+	struct i2c_algo_pch_data *adap = i2c_adap->algo_data;
+	u8 *buf;
+	u32 length;
+	u32 addr;
+	u32 addr_2_msb;
+	u32 addr_8_lsb;
+	s32 wrcount;
+	void __iomem *p = adap->pch_base_address;
+
+	length = msgs->len;
+	buf = msgs->buf;
+	addr = msgs->addr;
+
+	/* enable master tx */
+	pch_setbit(adap->pch_base_address, PCH_I2CCTL, I2C_TX_MODE);
+
+	pch_dbg(adap, "I2CCTL = %x msgs->len = %d\n", ioread32(p + PCH_I2CCTL),
+		length);
+
+	if (first) {
+		if (pch_i2c_wait_for_bus_idle(adap, BUS_IDLE_TIMEOUT) == -ETIME)
+			return -ETIME;
+	}
+
+	if (msgs->flags & I2C_M_TEN) {
+		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);
+		if (pch_i2c_wait_for_xfer_complete(adap) == 0 &&
+		    pch_i2c_getack(adap) == 0) {
+			addr_8_lsb = (addr & I2C_ADDR_MSK);
+			iowrite32(addr_8_lsb, p + PCH_I2CDR);
+		} else {
+			pch_i2c_stop(adap);
+			return -ETIME;
+		}
+	} else {
+		/* set 7 bit slave address and R/W bit as 0 */
+		iowrite32(addr << 1, p + PCH_I2CDR);
+		if (first)
+			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]);
+
+			if (pch_i2c_wait_for_xfer_complete(adap) != 0)
+				return -ETIME;
+
+			if (pch_i2c_getack(adap))
+				return -EIO;
+		}
+
+		/* check if this is the last message */
+		if (last)
+			pch_i2c_stop(adap);
+		else
+			pch_i2c_repstart(adap);
+	} else {
+		pch_i2c_stop(adap);
+		return -EIO;
+	}
+
+	pch_dbg(adap, "return=%d\n", wrcount);
+
+	return wrcount;
+}
+
+/**
+ * pch_i2c_sendack() - send ACK
+ * @adap:	Pointer to struct i2c_algo_pch_data.
+ */
+static void pch_i2c_sendack(struct i2c_algo_pch_data *adap)
+{
+	void __iomem *p = adap->pch_base_address;
+	pch_dbg(adap, "I2CCTL = %x\n", ioread32(p + PCH_I2CCTL));
+	pch_clrbit(adap->pch_base_address, PCH_I2CCTL, PCH_ACK);
+}
+
+/**
+ * pch_i2c_sendnack() - send NACK
+ * @adap:	Pointer to struct i2c_algo_pch_data.
+ */
+static void pch_i2c_sendnack(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_ACK);
+}
+
+/**
+ * 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.
+ * @last:	specifies whether last message or not.
+ * @first:	specifies whether first message or not.
+ */
+s32 pch_i2c_readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs,
+		  u32 last, u32 first)
+{
+	struct i2c_algo_pch_data *adap = i2c_adap->algo_data;
+
+	u8 *buf;
+	u32 count;
+	u32 length;
+	u32 addr;
+	u32 addr_2_msb;
+	void __iomem *p = adap->pch_base_address;
+
+	length = msgs->len;
+	buf = msgs->buf;
+	addr = msgs->addr;
+
+	/* enable master reception */
+	pch_clrbit(adap->pch_base_address, PCH_I2CCTL, I2C_TX_MODE);
+
+	if (first) {
+		if (pch_i2c_wait_for_bus_idle(adap, BUS_IDLE_TIMEOUT) == -ETIME)
+			return -ETIME;
+	}
+
+	if (msgs->flags & I2C_M_TEN) {
+		addr_2_msb = (((addr & I2C_MSB_2B_MSK) >> 7) | (I2C_RD));
+		iowrite32(addr_2_msb | TEN_BIT_ADDR_MASK, p + PCH_I2CDR);
+
+	} else {
+		/* 7 address bits + R/W bit */
+		addr = (((addr) << 1) | (I2C_RD));
+		iowrite32(addr, p + PCH_I2CDR);
+	}
+
+	/* check if it is the first message */
+	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);
+
+		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);
+
+			/* Dummy read */
+			for (loop = 1, read_index = 0; loop < length; loop++) {
+				buf[read_index] = ioread32(p + PCH_I2CDR);
+
+				if (loop != 1)
+					read_index++;
+
+				if (pch_i2c_wait_for_xfer_complete(adap) != 0) {
+					pch_i2c_stop(adap);
+					return -ETIME;
+				}
+			}	/* end for */
+
+			pch_i2c_sendnack(adap);
+
+			buf[read_index] = ioread32(p + PCH_I2CDR);
+
+			if (length != 1)
+				read_index++;
+
+			if (pch_i2c_wait_for_xfer_complete(adap) == 0) {
+				if (last)
+					pch_i2c_stop(adap);
+				else
+					pch_i2c_repstart(adap);
+
+				buf[read_index++] = ioread32(p + PCH_I2CDR);
+				count = read_index;
+			} else {
+				count = -ETIME;
+			}
+
+		}
+	} else {
+		count = -ETIME;
+		pch_i2c_stop(adap);
+	}
+
+	return count;
+}
+
+/**
+ * pch_i2c_cb_ch0() - Interrupt handler Call back function
+ * @adap:	Pointer to struct i2c_algo_pch_data.
+ */
+static void pch_i2c_cb_ch0(struct i2c_algo_pch_data *adap)
+{
+	u32 sts;
+	void __iomem *p = adap->pch_base_address;
+
+	sts = ioread32(p + PCH_I2CSR);
+	sts &= (I2CMAL_BIT | I2CMCF_BIT | I2CMIF_BIT);
+	if (sts & I2CMAL_BIT)
+		adap->pch_event_flag |= I2CMAL_EVENT;
+
+	if (sts & I2CMCF_BIT)
+		adap->pch_event_flag |= I2CMCF_EVENT;
+
+	/* clear the applicable bits */
+	pch_clrbit(adap->pch_base_address, PCH_I2CSR, sts);
+
+	pch_dbg(adap, "PCH_I2CSR = %x\n", ioread32(p + PCH_I2CSR));
+
+	wake_up(&pch_event);
+}
+
+/**
+ * pch_i2c_handler() - interrupt handler for the PCH I2C controller
+ * @irq:	irq number.
+ * @pData:	cookie passed back to the handler function.
+ */
+static irqreturn_t pch_i2c_handler(int irq, void *pData)
+{
+	s32 reg_val;
+
+	struct i2c_algo_pch_data *adap_data = (struct i2c_algo_pch_data *)pData;
+	void __iomem *p = adap_data->pch_base_address;
+	u32 mode = ioread32(p + PCH_I2CMOD) & (BUFFER_MODE | EEPROM_SR_MODE);
+
+	if (mode != NORMAL_MODE) {
+		pch_err(adap_data, "I2C mode is not supported\n");
+		return IRQ_NONE;
+	}
+
+	reg_val = ioread32(p + PCH_I2CSR);
+	if (reg_val & (I2CMAL_BIT | I2CMCF_BIT | I2CMIF_BIT))
+		pch_i2c_cb_ch0(adap_data);
+	else
+		return IRQ_NONE;
+
+	return IRQ_HANDLED;
+}
+
+/**
+ * pch_i2c_xfer() - Reading adnd writing data through I2C bus
+ * @i2c_adap:	Pointer to the struct i2c_adapter.
+ * @msgs:	Pointer to i2c_msg structure.
+ * @num:	number of messages.
+ */
+static s32 pch_i2c_xfer(struct i2c_adapter *i2c_adap,
+		    struct i2c_msg *msgs, s32 num)
+{
+	struct i2c_msg *pmsg;
+	u32 i = 0;
+	u32 status;
+	u32 msglen;
+	u32 subaddrlen;
+	s32 ret;
+
+	struct i2c_algo_pch_data *adap = i2c_adap->algo_data;
+
+	ret = mutex_lock_interruptible(&pch_mutex);
+	if (ret)
+		return -ERESTARTSYS;
+
+	if (adap->p_adapter_info->pch_i2c_suspended) {
+		mutex_unlock(&pch_mutex);
+		return -EBUSY;
+	}
+
+	pch_dbg(adap, "adap->p_adapter_info->pch_i2c_suspended is %d\n",
+		adap->p_adapter_info->pch_i2c_suspended);
+	/* transfer not completed */
+	adap->pch_i2c_xfer_in_progress = true;
+
+	pmsg = &msgs[0];
+	pmsg->flags |= adap->pch_buff_mode_en;
+	status = pmsg->flags;
+	pch_dbg(adap,
+		"After invoking I2C_MODE_SEL :flag= 0x%x\n", status);
+	/* calculate sub address length and message length */
+	/* these are applicable only for buffer mode */
+	subaddrlen = pmsg->buf[0];
+	/* calculate actual message length excluding
+	 * the sub address fields */
+	msglen = (pmsg->len) - (subaddrlen + 1);
+	if (status & (I2C_M_RD)) {
+		pch_dbg(adap, "invoking pch_i2c_readbytes\n");
+		ret = pch_i2c_readbytes(i2c_adap, pmsg, (i + 1 == num),
+				   (i == 0));
+	} else {
+		pch_dbg(adap, "invoking pch_i2c_writebytes\n");
+		ret = pch_i2c_writebytes(i2c_adap, pmsg, (i + 1 == num),
+				    (i == 0));
+	}
+
+	adap->pch_i2c_xfer_in_progress = false;	/* transfer completed */
+
+	mutex_unlock(&pch_mutex);
+
+	return ret;
+}
+
+/**
+ * pch_i2c_func() - return the functionality of the I2C driver
+ * @adap:	Pointer to struct i2c_algo_pch_data.
+ */
+static u32 pch_i2c_func(struct i2c_adapter *adap)
+{
+	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR;
+}
+
+static struct i2c_algorithm pch_algorithm = {
+	.master_xfer = pch_i2c_xfer,
+	.functionality = pch_i2c_func
+};
+
+/**
+ * pch_i2c_disbl_int() - Disable PCH I2C interrupts
+ * @adap:	Pointer to struct i2c_algo_pch_data.
+ */
+static void pch_i2c_disbl_int(struct i2c_algo_pch_data *adap)
+{
+	void __iomem *p = adap->pch_base_address;
+
+	pch_clrbit(adap->pch_base_address, PCH_I2CCTL, NORMAL_INTR_ENBL);
+
+	iowrite32(EEPROM_RST_INTR_DISBL, p + PCH_I2CESRMSK);
+
+	iowrite32(BUFFER_MODE_INTR_DISBL, p + PCH_I2CBUFMSK);
+}
+
+static int __devinit pch_i2c_probe(struct pci_dev *pdev,
+			       const struct pci_device_id *id)
+{
+	void __iomem *base_addr;
+	s32 ret;
+	struct adapter_info *adap_info;
+
+	pch_pci_dbg(pdev, "Entered.\n");
+
+	adap_info = kzalloc((sizeof(struct adapter_info)), GFP_KERNEL);
+	if (adap_info == NULL) {
+		pch_pci_err(pdev, "Memory allocation FAILED\n");
+		return -ENOMEM;
+	}
+
+	ret = pci_enable_device(pdev);
+	if (ret) {
+		pch_pci_err(pdev, "pci_enable_device FAILED\n");
+		goto err_pci_enable;
+	}
+
+	ret = pci_request_regions(pdev, KBUILD_MODNAME);
+	if (ret) {
+		pch_pci_err(pdev, "pci_request_regions FAILED\n");
+		goto err_pci_req;
+	}
+
+	base_addr = pci_iomap(pdev, 1, 0);
+
+	if (base_addr == NULL) {
+		pch_pci_err(pdev, "pci_iomap FAILED\n");
+		ret = -ENOMEM;
+		goto err_pci_iomap;
+	}
+
+	adap_info->pch_i2c_suspended = false;
+
+	adap_info->pch_data.p_adapter_info = adap_info;
+
+	adap_info->pch_data.pch_adapter.owner = THIS_MODULE;
+	adap_info->pch_data.pch_adapter.class = I2C_CLASS_HWMON;
+	strcpy(adap_info->pch_data.pch_adapter.name, KBUILD_MODNAME);
+	adap_info->pch_data.pch_adapter.algo = &pch_algorithm;
+	adap_info->pch_data.pch_adapter.algo_data =
+						&adap_info->pch_data;
+
+	/* (i * 0x80) + base_addr; */
+	adap_info->pch_data.pch_base_address = base_addr;
+
+	adap_info->pch_data.pch_adapter.dev.parent = &pdev->dev;
+
+	ret = i2c_add_adapter(&(adap_info->pch_data.pch_adapter));
+
+	if (ret) {
+		pch_pci_err(pdev, "i2c_add_adapter FAILED\n");
+		goto err_i2c_add_adapter;
+	}
+
+	pch_i2c_init(&adap_info->pch_data);
+	ret = request_irq(pdev->irq, pch_i2c_handler, IRQF_SHARED,
+		  KBUILD_MODNAME, &adap_info->pch_data);
+	if (ret) {
+		pch_pci_err(pdev, "request_irq FAILED\n");
+		goto err_request_irq;
+	}
+
+	pci_set_drvdata(pdev, adap_info);
+	pch_pci_dbg(pdev, "returns %d.\n", ret);
+	return 0;
+
+err_request_irq:
+	i2c_del_adapter(&(adap_info->pch_data.pch_adapter));
+err_i2c_add_adapter:
+	pci_iounmap(pdev, base_addr);
+err_pci_iomap:
+	pci_release_regions(pdev);
+err_pci_req:
+	pci_disable_device(pdev);
+err_pci_enable:
+	kfree(adap_info);
+	return ret;
+}
+
+static void __devexit pch_i2c_remove(struct pci_dev *pdev)
+{
+	struct adapter_info *adap_info = pci_get_drvdata(pdev);
+
+	pch_i2c_disbl_int(&adap_info->pch_data);
+	free_irq(pdev->irq, &adap_info->pch_data);
+	i2c_del_adapter(&(adap_info->pch_data.pch_adapter));
+
+	if (adap_info->pch_data.pch_base_address) {
+		pci_iounmap(pdev, adap_info->pch_data.pch_base_address);
+		adap_info->pch_data.pch_base_address = 0;
+	}
+
+	pci_set_drvdata(pdev, NULL);
+
+	pci_release_regions(pdev);
+
+	pci_disable_device(pdev);
+	kfree(adap_info);
+}
+
+#ifdef CONFIG_PM
+static int pch_i2c_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+	int ret;
+	struct adapter_info *adap_info = pci_get_drvdata(pdev);
+	void __iomem *p = adap_info->pch_data.pch_base_address;
+
+	adap_info->pch_i2c_suspended = true;
+
+	while ((adap_info->pch_data.pch_i2c_xfer_in_progress)) {
+		/* Wait until all channel transfers are completed */
+		msleep(20);
+	}
+	/* Disable the i2c interrupts */
+	pch_i2c_disbl_int(&adap_info->pch_data);
+
+	pch_pci_dbg(pdev, "I2CSR = %x I2CBUFSTA = %x I2CESRSTA = %x "
+		"invoked function pch_i2c_disbl_int successfully\n",
+		ioread32(p + PCH_I2CSR), ioread32(p + PCH_I2CBUFSTA),
+		ioread32(p + PCH_I2CESRSTA));
+
+	ret = pci_save_state(pdev);
+
+	if (ret) {
+		pch_pci_err(pdev, "pci_save_state\n");
+		return ret;
+	}
+
+	pci_enable_wake(pdev, PCI_D3hot, 0);
+	pci_disable_device(pdev);
+	pci_set_power_state(pdev, pci_choose_state(pdev, state));
+
+	return 0;
+}
+
+static int pch_i2c_resume(struct pci_dev *pdev)
+{
+	struct adapter_info *adap_info = pci_get_drvdata(pdev);
+
+	pci_set_power_state(pdev, PCI_D0);
+	pci_restore_state(pdev);
+
+	if (pci_enable_device(pdev) < 0) {
+		pch_pci_err(pdev, "pch_i2c_resume:pci_enable_device FAILED\n");
+		return -EIO;
+	}
+
+	pci_enable_wake(pdev, PCI_D3hot, 0);
+
+	pch_i2c_init(&adap_info->pch_data);
+
+	adap_info->pch_i2c_suspended = false;
+
+	return 0;
+}
+#else
+#define pch_i2c_suspend NULL
+#define pch_i2c_resume NULL
+#endif
+
+static struct pci_driver pch_pcidriver = {
+	.name = KBUILD_MODNAME,
+	.id_table = pch_pcidev_id,
+	.probe = pch_i2c_probe,
+	.remove = __devexit_p(pch_i2c_remove),
+	.suspend = pch_i2c_suspend,
+	.resume = pch_i2c_resume
+};
+
+static int __init pch_pci_init(void)
+{
+	return pci_register_driver(&pch_pcidriver);
+}
+module_init(pch_pci_init);
+
+static void __exit pch_pci_exit(void)
+{
+	pci_unregister_driver(&pch_pcidriver);
+}
+module_exit(pch_pci_exit);
+
+MODULE_DESCRIPTION("PCH I2C PCI Driver");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Tomoya MORINAGA. <tomoya-linux@dsn.okisemi.com>");
+module_param(pch_i2c_speed, int, (S_IRUSR | S_IWUSR));
+module_param(pch_clk, int, (S_IRUSR | S_IWUSR));
diff -druNp linux-libre-2.6.37-gnu1/drivers/i2c/busses/i2c-i801.c linux-libre-2.6.38-gnu1/drivers/i2c/busses/i2c-i801.c
--- linux-libre-2.6.37-gnu1/drivers/i2c/busses/i2c-i801.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/i2c/busses/i2c-i801.c	2011-03-14 21:20:32.000000000 -0400
@@ -72,6 +72,7 @@
 #include <linux/acpi.h>
 #include <linux/io.h>
 #include <linux/dmi.h>
+#include <linux/slab.h>
 
 /* I801 SMBus address offsets */
 #define SMBHSTSTS(p)	(0 + (p)->smba)
diff -druNp linux-libre-2.6.37-gnu1/drivers/i2c/busses/i2c-iop3xx.c linux-libre-2.6.38-gnu1/drivers/i2c/busses/i2c-iop3xx.c
--- linux-libre-2.6.37-gnu1/drivers/i2c/busses/i2c-iop3xx.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/i2c/busses/i2c-iop3xx.c	2011-03-14 21:20:32.000000000 -0400
@@ -409,7 +409,7 @@ iop3xx_i2c_remove(struct platform_device
 		IOP3XX_ICR_RXFULL_IE | IOP3XX_ICR_TXEMPTY_IE);
 	__raw_writel(cr, adapter_data->ioaddr + CR_OFFSET);
 
-	iounmap((void __iomem*)adapter_data->ioaddr);
+	iounmap(adapter_data->ioaddr);
 	release_mem_region(res->start, IOP3XX_I2C_IO_SIZE);
 	kfree(adapter_data);
 	kfree(padapter);
@@ -453,7 +453,7 @@ iop3xx_i2c_probe(struct platform_device
 	/* set the adapter enumeration # */
 	adapter_data->id = i2c_id++;
 
-	adapter_data->ioaddr = (u32)ioremap(res->start, IOP3XX_I2C_IO_SIZE);
+	adapter_data->ioaddr = ioremap(res->start, IOP3XX_I2C_IO_SIZE);
 	if (!adapter_data->ioaddr) {
 		ret = -ENOMEM;
 		goto release_region;
@@ -498,7 +498,7 @@ iop3xx_i2c_probe(struct platform_device
 	return 0;
 
 unmap:
-	iounmap((void __iomem*)adapter_data->ioaddr);
+	iounmap(adapter_data->ioaddr);
 
 release_region:
 	release_mem_region(res->start, IOP3XX_I2C_IO_SIZE);
diff -druNp linux-libre-2.6.37-gnu1/drivers/i2c/busses/i2c-iop3xx.h linux-libre-2.6.38-gnu1/drivers/i2c/busses/i2c-iop3xx.h
--- linux-libre-2.6.37-gnu1/drivers/i2c/busses/i2c-iop3xx.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/i2c/busses/i2c-iop3xx.h	2011-03-14 21:20:32.000000000 -0400
@@ -97,7 +97,7 @@
 #define	IOP3XX_I2C_IO_SIZE	0x18
 
 struct i2c_algo_iop3xx_data {
-	u32 ioaddr;
+	void __iomem *ioaddr;
 	wait_queue_head_t waitq;
 	spinlock_t lock;
 	u32 SR_enabled, SR_received;
diff -druNp linux-libre-2.6.37-gnu1/drivers/i2c/busses/i2c-mv64xxx.c linux-libre-2.6.38-gnu1/drivers/i2c/busses/i2c-mv64xxx.c
--- linux-libre-2.6.37-gnu1/drivers/i2c/busses/i2c-mv64xxx.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/i2c/busses/i2c-mv64xxx.c	2011-03-14 21:20:32.000000000 -0400
@@ -59,6 +59,7 @@ enum {
 	MV64XXX_I2C_STATE_INVALID,
 	MV64XXX_I2C_STATE_IDLE,
 	MV64XXX_I2C_STATE_WAITING_FOR_START_COND,
+	MV64XXX_I2C_STATE_WAITING_FOR_RESTART,
 	MV64XXX_I2C_STATE_WAITING_FOR_ADDR_1_ACK,
 	MV64XXX_I2C_STATE_WAITING_FOR_ADDR_2_ACK,
 	MV64XXX_I2C_STATE_WAITING_FOR_SLAVE_ACK,
@@ -70,6 +71,7 @@ enum {
 	MV64XXX_I2C_ACTION_INVALID,
 	MV64XXX_I2C_ACTION_CONTINUE,
 	MV64XXX_I2C_ACTION_SEND_START,
+	MV64XXX_I2C_ACTION_SEND_RESTART,
 	MV64XXX_I2C_ACTION_SEND_ADDR_1,
 	MV64XXX_I2C_ACTION_SEND_ADDR_2,
 	MV64XXX_I2C_ACTION_SEND_DATA,
@@ -91,6 +93,7 @@ struct mv64xxx_i2c_data {
 	u32			addr2;
 	u32			bytes_left;
 	u32			byte_posn;
+	u32			send_stop;
 	u32			block;
 	int			rc;
 	u32			freq_m;
@@ -159,8 +162,15 @@ mv64xxx_i2c_fsm(struct mv64xxx_i2c_data
 		if ((drv_data->bytes_left == 0)
 				|| (drv_data->aborting
 					&& (drv_data->byte_posn != 0))) {
-			drv_data->action = MV64XXX_I2C_ACTION_SEND_STOP;
-			drv_data->state = MV64XXX_I2C_STATE_IDLE;
+			if (drv_data->send_stop) {
+				drv_data->action = MV64XXX_I2C_ACTION_SEND_STOP;
+				drv_data->state = MV64XXX_I2C_STATE_IDLE;
+			} else {
+				drv_data->action =
+					MV64XXX_I2C_ACTION_SEND_RESTART;
+				drv_data->state =
+					MV64XXX_I2C_STATE_WAITING_FOR_RESTART;
+			}
 		} else {
 			drv_data->action = MV64XXX_I2C_ACTION_SEND_DATA;
 			drv_data->state =
@@ -228,6 +238,15 @@ static void
 mv64xxx_i2c_do_action(struct mv64xxx_i2c_data *drv_data)
 {
 	switch(drv_data->action) {
+	case MV64XXX_I2C_ACTION_SEND_RESTART:
+		drv_data->cntl_bits |= MV64XXX_I2C_REG_CONTROL_START;
+		drv_data->cntl_bits &= ~MV64XXX_I2C_REG_CONTROL_INTEN;
+		writel(drv_data->cntl_bits,
+			drv_data->reg_base + MV64XXX_I2C_REG_CONTROL);
+		drv_data->block = 0;
+		wake_up_interruptible(&drv_data->waitq);
+		break;
+
 	case MV64XXX_I2C_ACTION_CONTINUE:
 		writel(drv_data->cntl_bits,
 			drv_data->reg_base + MV64XXX_I2C_REG_CONTROL);
@@ -386,7 +405,8 @@ mv64xxx_i2c_wait_for_completion(struct m
 }
 
 static int
-mv64xxx_i2c_execute_msg(struct mv64xxx_i2c_data *drv_data, struct i2c_msg *msg)
+mv64xxx_i2c_execute_msg(struct mv64xxx_i2c_data *drv_data, struct i2c_msg *msg,
+				int is_first, int is_last)
 {
 	unsigned long	flags;
 
@@ -406,10 +426,18 @@ mv64xxx_i2c_execute_msg(struct mv64xxx_i
 			drv_data->bytes_left--;
 		}
 	} else {
-		drv_data->action = MV64XXX_I2C_ACTION_SEND_START;
-		drv_data->state = MV64XXX_I2C_STATE_WAITING_FOR_START_COND;
+		if (is_first) {
+			drv_data->action = MV64XXX_I2C_ACTION_SEND_START;
+			drv_data->state =
+				MV64XXX_I2C_STATE_WAITING_FOR_START_COND;
+		} else {
+			drv_data->action = MV64XXX_I2C_ACTION_SEND_ADDR_1;
+			drv_data->state =
+				MV64XXX_I2C_STATE_WAITING_FOR_ADDR_1_ACK;
+		}
 	}
 
+	drv_data->send_stop = is_last;
 	drv_data->block = 1;
 	mv64xxx_i2c_do_action(drv_data);
 	spin_unlock_irqrestore(&drv_data->lock, flags);
@@ -437,9 +465,12 @@ mv64xxx_i2c_xfer(struct i2c_adapter *ada
 	struct mv64xxx_i2c_data *drv_data = i2c_get_adapdata(adap);
 	int	i, rc;
 
-	for (i=0; i<num; i++)
-		if ((rc = mv64xxx_i2c_execute_msg(drv_data, &msgs[i])) < 0)
+	for (i = 0; i < num; i++) {
+		rc = mv64xxx_i2c_execute_msg(drv_data, &msgs[i],
+						i == 0, i + 1 == num);
+		if (rc < 0)
 			return rc;
+	}
 
 	return num;
 }
diff -druNp linux-libre-2.6.37-gnu1/drivers/i2c/busses/i2c-nforce2.c linux-libre-2.6.38-gnu1/drivers/i2c/busses/i2c-nforce2.c
--- linux-libre-2.6.37-gnu1/drivers/i2c/busses/i2c-nforce2.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/i2c/busses/i2c-nforce2.c	2011-03-14 21:20:32.000000000 -0400
@@ -432,7 +432,7 @@ static int __devinit nforce2_probe(struc
 
 static void __devexit nforce2_remove(struct pci_dev *dev)
 {
-	struct nforce2_smbus *smbuses = (void*) pci_get_drvdata(dev);
+	struct nforce2_smbus *smbuses = pci_get_drvdata(dev);
 
 	nforce2_set_reference(NULL);
 	if (smbuses[0].base) {
diff -druNp linux-libre-2.6.37-gnu1/drivers/i2c/busses/i2c-nomadik.c linux-libre-2.6.38-gnu1/drivers/i2c/busses/i2c-nomadik.c
--- linux-libre-2.6.37-gnu1/drivers/i2c/busses/i2c-nomadik.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/i2c/busses/i2c-nomadik.c	2011-03-14 21:20:32.000000000 -0400
@@ -434,7 +434,7 @@ static int read_i2c(struct nmk_i2c_dev *
 	}
 
 	if (timeout == 0) {
-		/* controler has timedout, re-init the h/w */
+		/* controller has timedout, re-init the h/w */
 		dev_err(&dev->pdev->dev, "controller timed out, re-init h/w\n");
 		(void) init_hw(dev);
 		status = -ETIMEDOUT;
@@ -498,7 +498,7 @@ static int write_i2c(struct nmk_i2c_dev
 	}
 
 	if (timeout == 0) {
-		/* controler has timedout, re-init the h/w */
+		/* controller has timedout, re-init the h/w */
 		dev_err(&dev->pdev->dev, "controller timed out, re-init h/w\n");
 		(void) init_hw(dev);
 		status = -ETIMEDOUT;
@@ -872,6 +872,8 @@ static int __devinit nmk_i2c_probe(struc
 	adap->owner	= THIS_MODULE;
 	adap->class	= I2C_CLASS_HWMON | I2C_CLASS_SPD;
 	adap->algo	= &nmk_i2c_algo;
+	snprintf(adap->name, sizeof(adap->name),
+		 "Nomadik I2C%d at %lx", pdev->id, (unsigned long)res->start);
 
 	/* fetch the controller id */
 	adap->nr	= pdev->id;
@@ -891,8 +893,8 @@ static int __devinit nmk_i2c_probe(struc
 		goto err_init_hw;
 	}
 
-	dev_dbg(&pdev->dev, "initialize I2C%d bus on virtual "
-		"base %p\n", pdev->id, 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-2.6.37-gnu1/drivers/i2c/busses/i2c-ocores.c linux-libre-2.6.38-gnu1/drivers/i2c/busses/i2c-ocores.c
--- linux-libre-2.6.37-gnu1/drivers/i2c/busses/i2c-ocores.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/i2c/busses/i2c-ocores.c	2011-03-14 21:20:32.000000000 -0400
@@ -9,6 +9,41 @@
  * kind, whether express or implied.
  */
 
+/*
+ * Device tree configuration:
+ *
+ * Required properties:
+ * - compatible      : "opencores,i2c-ocores"
+ * - reg             : bus address start and address range size of device
+ * - interrupts      : interrupt number
+ * - regstep         : size of device registers in bytes
+ * - clock-frequency : frequency of bus clock in Hz
+ * 
+ * Example:
+ *
+ *  i2c0: ocores@a0000000 {
+ *              compatible = "opencores,i2c-ocores";
+ *              reg = <0xa0000000 0x8>;
+ *              interrupts = <10>;
+ *
+ *              regstep = <1>;
+ *              clock-frequency = <20000000>;
+ *
+ * -- Devices connected on this I2C bus get
+ * -- defined here; address- and size-cells
+ * -- apply to these child devices
+ *
+ *              #address-cells = <1>;
+ *              #size-cells = <0>;
+ *
+ *              dummy@60 {
+ *                     compatible = "dummy";
+ *                     reg = <60>;
+ *              };
+ *  };
+ *
+ */
+
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
@@ -210,6 +245,32 @@ static struct i2c_adapter ocores_adapter
 	.algo		= &ocores_algorithm,
 };
 
+#ifdef CONFIG_OF
+static int ocores_i2c_of_probe(struct platform_device* pdev,
+				struct ocores_i2c* i2c)
+{
+	const __be32* val;
+
+	val = of_get_property(pdev->dev.of_node, "regstep", NULL);
+	if (!val) {
+		dev_err(&pdev->dev, "Missing required parameter 'regstep'");
+		return -ENODEV;
+	}
+	i2c->regstep = be32_to_cpup(val);
+
+	val = of_get_property(pdev->dev.of_node, "clock-frequency", NULL);
+	if (!val) {
+		dev_err(&pdev->dev,
+			"Missing required parameter 'clock-frequency'");
+		return -ENODEV;
+	}
+	i2c->clock_khz = be32_to_cpup(val) / 1000;
+
+	return 0;
+}
+#else
+#define ocores_i2c_of_probe(pdev,i2c) -ENODEV
+#endif
 
 static int __devinit ocores_i2c_probe(struct platform_device *pdev)
 {
@@ -227,37 +288,41 @@ static int __devinit ocores_i2c_probe(st
 	if (!res2)
 		return -ENODEV;
 
-	pdata = (struct ocores_i2c_platform_data*) pdev->dev.platform_data;
-	if (!pdata)
-		return -ENODEV;
-
-	i2c = kzalloc(sizeof(*i2c), GFP_KERNEL);
+	i2c = devm_kzalloc(&pdev->dev, sizeof(*i2c), GFP_KERNEL);
 	if (!i2c)
 		return -ENOMEM;
 
-	if (!request_mem_region(res->start, resource_size(res),
-				pdev->name)) {
+	if (!devm_request_mem_region(&pdev->dev, res->start,
+				     resource_size(res), pdev->name)) {
 		dev_err(&pdev->dev, "Memory region busy\n");
-		ret = -EBUSY;
-		goto request_mem_failed;
+		return -EBUSY;
 	}
 
-	i2c->base = ioremap(res->start, resource_size(res));
+	i2c->base = devm_ioremap_nocache(&pdev->dev, res->start,
+					 resource_size(res));
 	if (!i2c->base) {
 		dev_err(&pdev->dev, "Unable to map registers\n");
-		ret = -EIO;
-		goto map_failed;
+		return -EIO;
+	}
+
+	pdata = pdev->dev.platform_data;
+	if (pdata) {
+		i2c->regstep = pdata->regstep;
+		i2c->clock_khz = pdata->clock_khz;
+	} else {
+		ret = ocores_i2c_of_probe(pdev, i2c);
+		if (ret)
+			return ret;
 	}
 
-	i2c->regstep = pdata->regstep;
-	i2c->clock_khz = pdata->clock_khz;
 	ocores_init(i2c);
 
 	init_waitqueue_head(&i2c->wait);
-	ret = request_irq(res2->start, ocores_isr, 0, pdev->name, i2c);
+	ret = devm_request_irq(&pdev->dev, res2->start, ocores_isr, 0,
+			       pdev->name, i2c);
 	if (ret) {
 		dev_err(&pdev->dev, "Cannot claim IRQ\n");
-		goto request_irq_failed;
+		return ret;
 	}
 
 	/* hook up driver to tree */
@@ -265,36 +330,29 @@ static int __devinit ocores_i2c_probe(st
 	i2c->adap = ocores_adapter;
 	i2c_set_adapdata(&i2c->adap, i2c);
 	i2c->adap.dev.parent = &pdev->dev;
+#ifdef CONFIG_OF
+	i2c->adap.dev.of_node = pdev->dev.of_node;
+#endif
 
 	/* add i2c adapter to i2c tree */
 	ret = i2c_add_adapter(&i2c->adap);
 	if (ret) {
 		dev_err(&pdev->dev, "Failed to add adapter\n");
-		goto add_adapter_failed;
+		return ret;
 	}
 
 	/* add in known devices to the bus */
-	for (i = 0; i < pdata->num_devices; i++)
-		i2c_new_device(&i2c->adap, pdata->devices + i);
+	if (pdata) {
+		for (i = 0; i < pdata->num_devices; i++)
+			i2c_new_device(&i2c->adap, pdata->devices + i);
+	}
 
 	return 0;
-
-add_adapter_failed:
-	free_irq(res2->start, i2c);
-request_irq_failed:
-	iounmap(i2c->base);
-map_failed:
-	release_mem_region(res->start, resource_size(res));
-request_mem_failed:
-	kfree(i2c);
-
-	return ret;
 }
 
 static int __devexit ocores_i2c_remove(struct platform_device* pdev)
 {
 	struct ocores_i2c *i2c = platform_get_drvdata(pdev);
-	struct resource *res;
 
 	/* disable i2c logic */
 	oc_setreg(i2c, OCI2C_CONTROL, oc_getreg(i2c, OCI2C_CONTROL)
@@ -304,18 +362,6 @@ static int __devexit ocores_i2c_remove(s
 	i2c_del_adapter(&i2c->adap);
 	platform_set_drvdata(pdev, NULL);
 
-	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-	if (res)
-		free_irq(res->start, i2c);
-
-	iounmap(i2c->base);
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (res)
-		release_mem_region(res->start, resource_size(res));
-
-	kfree(i2c);
-
 	return 0;
 }
 
@@ -344,6 +390,16 @@ static int ocores_i2c_resume(struct plat
 #define ocores_i2c_resume	NULL
 #endif
 
+#ifdef CONFIG_OF
+static struct of_device_id ocores_i2c_match[] = {
+        {
+                .compatible = "opencores,i2c-ocores",
+        },
+        {},
+};
+MODULE_DEVICE_TABLE(of, ocores_i2c_match);
+#endif
+
 /* work with hotplug and coldplug */
 MODULE_ALIAS("platform:ocores-i2c");
 
@@ -355,6 +411,9 @@ static struct platform_driver ocores_i2c
 	.driver  = {
 		.owner = THIS_MODULE,
 		.name = "ocores-i2c",
+#ifdef CONFIG_OF
+                .of_match_table = ocores_i2c_match,
+#endif
 	},
 };
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/i2c/busses/i2c-omap.c linux-libre-2.6.38-gnu1/drivers/i2c/busses/i2c-omap.c
--- linux-libre-2.6.37-gnu1/drivers/i2c/busses/i2c-omap.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/i2c/busses/i2c-omap.c	2011-03-14 21:20:32.000000000 -0400
@@ -39,6 +39,7 @@
 #include <linux/io.h>
 #include <linux/slab.h>
 #include <linux/i2c-omap.h>
+#include <linux/pm_runtime.h>
 
 /* I2C controller revisions */
 #define OMAP_I2C_REV_2			0x20
@@ -175,8 +176,6 @@ struct omap_i2c_dev {
 	void __iomem		*base;		/* virtual */
 	int			irq;
 	int			reg_shift;      /* bit shift for I2C register addresses */
-	struct clk		*iclk;		/* Interface clock */
-	struct clk		*fclk;		/* Functional clock */
 	struct completion	cmd_complete;
 	struct resource		*ioarea;
 	u32			latency;	/* maximum mpu wkup latency */
@@ -265,45 +264,18 @@ static inline u16 omap_i2c_read_reg(stru
 				(i2c_dev->regs[reg] << i2c_dev->reg_shift));
 }
 
-static int __init omap_i2c_get_clocks(struct omap_i2c_dev *dev)
+static void omap_i2c_unidle(struct omap_i2c_dev *dev)
 {
-	int ret;
-
-	dev->iclk = clk_get(dev->dev, "ick");
-	if (IS_ERR(dev->iclk)) {
-		ret = PTR_ERR(dev->iclk);
-		dev->iclk = NULL;
-		return ret;
-	}
-
-	dev->fclk = clk_get(dev->dev, "fck");
-	if (IS_ERR(dev->fclk)) {
-		ret = PTR_ERR(dev->fclk);
-		if (dev->iclk != NULL) {
-			clk_put(dev->iclk);
-			dev->iclk = NULL;
-		}
-		dev->fclk = NULL;
-		return ret;
-	}
+	struct platform_device *pdev;
+	struct omap_i2c_bus_platform_data *pdata;
 
-	return 0;
-}
+	WARN_ON(!dev->idle);
 
-static void omap_i2c_put_clocks(struct omap_i2c_dev *dev)
-{
-	clk_put(dev->fclk);
-	dev->fclk = NULL;
-	clk_put(dev->iclk);
-	dev->iclk = NULL;
-}
+	pdev = to_platform_device(dev->dev);
+	pdata = pdev->dev.platform_data;
 
-static void omap_i2c_unidle(struct omap_i2c_dev *dev)
-{
-	WARN_ON(!dev->idle);
+	pm_runtime_get_sync(&pdev->dev);
 
-	clk_enable(dev->iclk);
-	clk_enable(dev->fclk);
 	if (cpu_is_omap34xx()) {
 		omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0);
 		omap_i2c_write_reg(dev, OMAP_I2C_PSC_REG, dev->pscstate);
@@ -326,10 +298,15 @@ 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;
+
 	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);
@@ -345,8 +322,8 @@ static void omap_i2c_idle(struct omap_i2
 		omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG);
 	}
 	dev->idle = 1;
-	clk_disable(dev->fclk);
-	clk_disable(dev->iclk);
+
+	pm_runtime_put_sync(&pdev->dev);
 }
 
 static int omap_i2c_init(struct omap_i2c_dev *dev)
@@ -356,6 +333,7 @@ static int omap_i2c_init(struct omap_i2c
 	unsigned long fclk_rate = 12000000;
 	unsigned long timeout;
 	unsigned long internal_clk = 0;
+	struct clk *fclk;
 
 	if (dev->rev >= OMAP_I2C_REV_2) {
 		/* Disable I2C controller before soft reset */
@@ -400,9 +378,7 @@ static int omap_i2c_init(struct omap_i2c
 			 * REVISIT: Some wkup sources might not be needed.
 			 */
 			dev->westate = OMAP_I2C_WE_ALL;
-			if (dev->rev < OMAP_I2C_REV_ON_4430)
-				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);
@@ -414,7 +390,9 @@ static int omap_i2c_init(struct omap_i2c
 		 * always returns 12MHz for the functional clock, we can
 		 * do this bit unconditionally.
 		 */
-		fclk_rate = clk_get_rate(dev->fclk);
+		fclk = clk_get(dev->dev, "fck");
+		fclk_rate = clk_get_rate(fclk);
+		clk_put(fclk);
 
 		/* TRM for 5912 says the I2C clock must be prescaled to be
 		 * between 7 - 12 MHz. The XOR input clock is typically
@@ -443,7 +421,9 @@ static int omap_i2c_init(struct omap_i2c
 			internal_clk = 9600;
 		else
 			internal_clk = 4000;
-		fclk_rate = clk_get_rate(dev->fclk) / 1000;
+		fclk = clk_get(dev->dev, "fck");
+		fclk_rate = clk_get_rate(fclk) / 1000;
+		clk_put(fclk);
 
 		/* Compute prescaler divisor */
 		psc = fclk_rate / internal_clk;
@@ -616,12 +596,8 @@ static int omap_i2c_xfer_msg(struct i2c_
 	 * REVISIT: We should abort the transfer on signals, but the bus goes
 	 * into arbitration and we're currently unable to recover from it.
 	 */
-	if (dev->set_mpu_wkup_lat != NULL)
-		dev->set_mpu_wkup_lat(dev->dev, dev->latency);
 	r = wait_for_completion_timeout(&dev->cmd_complete,
 					OMAP_I2C_TIMEOUT);
-	if (dev->set_mpu_wkup_lat != NULL)
-		dev->set_mpu_wkup_lat(dev->dev, -1);
 	dev->buf_len = 0;
 	if (r < 0)
 		return r;
@@ -672,12 +648,18 @@ omap_i2c_xfer(struct i2c_adapter *adap,
 	if (r < 0)
 		goto out;
 
+	if (dev->set_mpu_wkup_lat != NULL)
+		dev->set_mpu_wkup_lat(dev->dev, dev->latency);
+
 	for (i = 0; i < num; i++) {
 		r = omap_i2c_xfer_msg(adap, &msgs[i], (i == (num - 1)));
 		if (r != 0)
 			break;
 	}
 
+	if (dev->set_mpu_wkup_lat != NULL)
+		dev->set_mpu_wkup_lat(dev->dev, -1);
+
 	if (r == 0)
 		r = num;
 
@@ -863,11 +845,15 @@ complete:
 			dev_err(dev->dev, "Arbitration lost\n");
 			err |= OMAP_I2C_STAT_AL;
 		}
+		/*
+		 * ProDB0017052: Clear ARDY bit twice
+		 */
 		if (stat & (OMAP_I2C_STAT_ARDY | OMAP_I2C_STAT_NACK |
 					OMAP_I2C_STAT_AL)) {
 			omap_i2c_ack_stat(dev, stat &
 				(OMAP_I2C_STAT_RRDY | OMAP_I2C_STAT_RDR |
-				OMAP_I2C_STAT_XRDY | OMAP_I2C_STAT_XDR));
+				OMAP_I2C_STAT_XRDY | OMAP_I2C_STAT_XDR |
+				OMAP_I2C_STAT_ARDY));
 			omap_i2c_complete_cmd(dev, err);
 			return IRQ_HANDLED;
 		}
@@ -1048,14 +1034,12 @@ omap_i2c_probe(struct platform_device *p
 	else
 		dev->reg_shift = 2;
 
-	if ((r = omap_i2c_get_clocks(dev)) != 0)
-		goto err_iounmap;
-
 	if (cpu_is_omap44xx())
 		dev->regs = (u8 *) omap4_reg_map;
 	else
 		dev->regs = (u8 *) reg_map;
 
+	pm_runtime_enable(&pdev->dev);
 	omap_i2c_unidle(dev);
 
 	dev->rev = omap_i2c_read_reg(dev, OMAP_I2C_REV_REG) & 0xff;
@@ -1127,8 +1111,6 @@ err_free_irq:
 err_unuse_clocks:
 	omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0);
 	omap_i2c_idle(dev);
-	omap_i2c_put_clocks(dev);
-err_iounmap:
 	iounmap(dev->base);
 err_free_mem:
 	platform_set_drvdata(pdev, NULL);
@@ -1150,7 +1132,6 @@ omap_i2c_remove(struct platform_device *
 	free_irq(dev->irq, dev);
 	i2c_del_adapter(&dev->adapter);
 	omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0);
-	omap_i2c_put_clocks(dev);
 	iounmap(dev->base);
 	kfree(dev);
 	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -1158,12 +1139,41 @@ omap_i2c_remove(struct platform_device *
 	return 0;
 }
 
+#ifdef CONFIG_SUSPEND
+static int omap_i2c_suspend(struct device *dev)
+{
+	if (!pm_runtime_suspended(dev))
+		if (dev->bus && dev->bus->pm && dev->bus->pm->runtime_suspend)
+			dev->bus->pm->runtime_suspend(dev);
+
+	return 0;
+}
+
+static int omap_i2c_resume(struct device *dev)
+{
+	if (!pm_runtime_suspended(dev))
+		if (dev->bus && dev->bus->pm && dev->bus->pm->runtime_resume)
+			dev->bus->pm->runtime_resume(dev);
+
+	return 0;
+}
+
+static struct dev_pm_ops omap_i2c_pm_ops = {
+	.suspend = omap_i2c_suspend,
+	.resume = omap_i2c_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	= "i2c_omap",
+		.name	= "omap_i2c",
 		.owner	= THIS_MODULE,
+		.pm	= OMAP_I2C_PM_OPS,
 	},
 };
 
@@ -1184,4 +1194,4 @@ module_exit(omap_i2c_exit_driver);
 MODULE_AUTHOR("MontaVista Software, Inc. (and others)");
 MODULE_DESCRIPTION("TI OMAP I2C bus adapter");
 MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:i2c_omap");
+MODULE_ALIAS("platform:omap_i2c");
diff -druNp linux-libre-2.6.37-gnu1/drivers/i2c/busses/i2c-stu300.c linux-libre-2.6.38-gnu1/drivers/i2c/busses/i2c-stu300.c
--- linux-libre-2.6.37-gnu1/drivers/i2c/busses/i2c-stu300.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/i2c/busses/i2c-stu300.c	2011-03-14 21:20:32.000000000 -0400
@@ -942,7 +942,7 @@ stu300_probe(struct platform_device *pde
 	adap->owner = THIS_MODULE;
 	/* DDC class but actually often used for more generic I2C */
 	adap->class = I2C_CLASS_DDC;
-	strncpy(adap->name, "ST Microelectronics DDC I2C adapter",
+	strlcpy(adap->name, "ST Microelectronics DDC I2C adapter",
 		sizeof(adap->name));
 	adap->nr = bus_nr;
 	adap->algo = &stu300_algo;
diff -druNp linux-libre-2.6.37-gnu1/drivers/i2c/busses/Kconfig linux-libre-2.6.38-gnu1/drivers/i2c/busses/Kconfig
--- linux-libre-2.6.37-gnu1/drivers/i2c/busses/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/i2c/busses/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -638,6 +638,14 @@ config I2C_XILINX
 	  This driver can also be built as a module.  If so, the module
 	  will be called xilinx_i2c.
 
+config I2C_EG20T
+        tristate "PCH I2C of Intel EG20T"
+        depends on PCI
+        help
+          This driver is for PCH(Platform controller Hub) I2C of EG20T which
+          is an IOH(Input/Output Hub) for x86 embedded processor.
+          This driver can access PCH I2C bus device.
+
 comment "External I2C/SMBus adapter drivers"
 
 config I2C_PARPORT
diff -druNp linux-libre-2.6.37-gnu1/drivers/i2c/busses/Makefile linux-libre-2.6.38-gnu1/drivers/i2c/busses/Makefile
--- linux-libre-2.6.37-gnu1/drivers/i2c/busses/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/i2c/busses/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -61,6 +61,7 @@ obj-$(CONFIG_I2C_STU300)	+= i2c-stu300.o
 obj-$(CONFIG_I2C_VERSATILE)	+= i2c-versatile.o
 obj-$(CONFIG_I2C_OCTEON)	+= i2c-octeon.o
 obj-$(CONFIG_I2C_XILINX)	+= i2c-xiic.o
+obj-$(CONFIG_I2C_EG20T)         += i2c-eg20t.o
 
 # External I2C/SMBus adapter drivers
 obj-$(CONFIG_I2C_PARPORT)	+= i2c-parport.o
diff -druNp linux-libre-2.6.37-gnu1/drivers/i2c/busses/scx200_acb.c linux-libre-2.6.38-gnu1/drivers/i2c/busses/scx200_acb.c
--- linux-libre-2.6.37-gnu1/drivers/i2c/busses/scx200_acb.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/i2c/busses/scx200_acb.c	2011-03-14 21:20:32.000000000 -0400
@@ -29,6 +29,7 @@
 #include <linux/init.h>
 #include <linux/i2c.h>
 #include <linux/pci.h>
+#include <linux/platform_device.h>
 #include <linux/delay.h>
 #include <linux/mutex.h>
 #include <linux/slab.h>
@@ -40,6 +41,7 @@
 
 MODULE_AUTHOR("Christer Weinigel <wingel@nano-system.com>");
 MODULE_DESCRIPTION("NatSemi SCx200 ACCESS.bus Driver");
+MODULE_ALIAS("platform:cs5535-smb");
 MODULE_LICENSE("GPL");
 
 #define MAX_DEVICES 4
@@ -84,10 +86,6 @@ struct scx200_acb_iface {
 	u8 *ptr;
 	char needs_reset;
 	unsigned len;
-
-	/* PCI device info */
-	struct pci_dev *pdev;
-	int bar;
 };
 
 /* Register Definitions */
@@ -391,7 +389,7 @@ static const struct i2c_algorithm scx200
 static struct scx200_acb_iface *scx200_acb_list;
 static DEFINE_MUTEX(scx200_acb_list_mutex);
 
-static __init int scx200_acb_probe(struct scx200_acb_iface *iface)
+static __devinit int scx200_acb_probe(struct scx200_acb_iface *iface)
 {
 	u8 val;
 
@@ -427,7 +425,7 @@ static __init int scx200_acb_probe(struc
 	return 0;
 }
 
-static __init struct scx200_acb_iface *scx200_create_iface(const char *text,
+static __devinit struct scx200_acb_iface *scx200_create_iface(const char *text,
 		struct device *dev, int index)
 {
 	struct scx200_acb_iface *iface;
@@ -452,7 +450,7 @@ static __init struct scx200_acb_iface *s
 	return iface;
 }
 
-static int __init scx200_acb_create(struct scx200_acb_iface *iface)
+static int __devinit scx200_acb_create(struct scx200_acb_iface *iface)
 {
 	struct i2c_adapter *adapter;
 	int rc;
@@ -472,183 +470,145 @@ static int __init scx200_acb_create(stru
 		return -ENODEV;
 	}
 
-	mutex_lock(&scx200_acb_list_mutex);
-	iface->next = scx200_acb_list;
-	scx200_acb_list = iface;
-	mutex_unlock(&scx200_acb_list_mutex);
+	if (!adapter->dev.parent) {
+		/* If there's no dev, we're tracking (ISA) ifaces manually */
+		mutex_lock(&scx200_acb_list_mutex);
+		iface->next = scx200_acb_list;
+		scx200_acb_list = iface;
+		mutex_unlock(&scx200_acb_list_mutex);
+	}
 
 	return 0;
 }
 
-static __init int scx200_create_pci(const char *text, struct pci_dev *pdev,
-		int bar)
+static struct scx200_acb_iface * __devinit scx200_create_dev(const char *text,
+		unsigned long base, int index, struct device *dev)
 {
 	struct scx200_acb_iface *iface;
 	int rc;
 
-	iface = scx200_create_iface(text, &pdev->dev, 0);
+	iface = scx200_create_iface(text, dev, index);
 
 	if (iface == NULL)
-		return -ENOMEM;
-
-	iface->pdev = pdev;
-	iface->bar = bar;
-
-	rc = pci_enable_device_io(iface->pdev);
-	if (rc)
-		goto errout_free;
+		return NULL;
 
-	rc = pci_request_region(iface->pdev, iface->bar, iface->adapter.name);
-	if (rc) {
-		printk(KERN_ERR NAME ": can't allocate PCI BAR %d\n",
-				iface->bar);
+	if (!request_region(base, 8, iface->adapter.name)) {
+		printk(KERN_ERR NAME ": can't allocate io 0x%lx-0x%lx\n",
+		       base, base + 8 - 1);
 		goto errout_free;
 	}
 
-	iface->base = pci_resource_start(iface->pdev, iface->bar);
+	iface->base = base;
 	rc = scx200_acb_create(iface);
 
 	if (rc == 0)
-		return 0;
+		return iface;
 
-	pci_release_region(iface->pdev, iface->bar);
-	pci_dev_put(iface->pdev);
+	release_region(base, 8);
  errout_free:
 	kfree(iface);
-	return rc;
+	return NULL;
 }
 
-static int __init scx200_create_isa(const char *text, unsigned long base,
-		int index)
+static int __devinit scx200_probe(struct platform_device *pdev)
 {
 	struct scx200_acb_iface *iface;
-	int rc;
-
-	iface = scx200_create_iface(text, NULL, index);
-
-	if (iface == NULL)
-		return -ENOMEM;
+	struct resource *res;
 
-	if (!request_region(base, 8, iface->adapter.name)) {
-		printk(KERN_ERR NAME ": can't allocate io 0x%lx-0x%lx\n",
-		       base, base + 8 - 1);
-		rc = -EBUSY;
-		goto errout_free;
+	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+	if (!res) {
+		dev_err(&pdev->dev, "can't fetch device resource info\n");
+		return -ENODEV;
 	}
 
-	iface->base = base;
-	rc = scx200_acb_create(iface);
+	iface = scx200_create_dev("CS5535", res->start, 0, &pdev->dev);
+	if (!iface)
+		return -EIO;
 
-	if (rc == 0)
-		return 0;
+	dev_info(&pdev->dev, "SCx200 device '%s' registered\n",
+			iface->adapter.name);
+	platform_set_drvdata(pdev, iface);
 
-	release_region(base, 8);
- errout_free:
+	return 0;
+}
+
+static void __devexit scx200_cleanup_iface(struct scx200_acb_iface *iface)
+{
+	i2c_del_adapter(&iface->adapter);
+	release_region(iface->base, 8);
 	kfree(iface);
-	return rc;
 }
 
-/* Driver data is an index into the scx200_data array that indicates
- * the name and the BAR where the I/O address resource is located.  ISA
- * devices are flagged with a bar value of -1 */
+static int __devexit scx200_remove(struct platform_device *pdev)
+{
+	struct scx200_acb_iface *iface;
 
-static const struct pci_device_id scx200_pci[] __initconst = {
-	{ PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_SCx200_BRIDGE),
-	  .driver_data = 0 },
-	{ PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_SC1100_BRIDGE),
-	  .driver_data = 0 },
-	{ PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_CS5535_ISA),
-	  .driver_data = 1 },
-	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA),
-	  .driver_data = 2 },
-	{ 0, }
+	iface = platform_get_drvdata(pdev);
+	platform_set_drvdata(pdev, NULL);
+	scx200_cleanup_iface(iface);
+
+	return 0;
+}
+
+static struct platform_driver scx200_pci_drv = {
+	.driver = {
+		.name = "cs5535-smb",
+		.owner = THIS_MODULE,
+	},
+	.probe = scx200_probe,
+	.remove = __devexit_p(scx200_remove),
 };
 
-static struct {
-	const char *name;
-	int bar;
-} scx200_data[] = {
-	{ "SCx200", -1 },
-	{ "CS5535",  0 },
-	{ "CS5536",  0 }
+static const struct pci_device_id scx200_isa[] __initconst = {
+	{ PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_SCx200_BRIDGE) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_SC1100_BRIDGE) },
+	{ 0, }
 };
 
-static __init int scx200_scan_pci(void)
+static __init void scx200_scan_isa(void)
 {
-	int data, dev;
-	int rc = -ENODEV;
-	struct pci_dev *pdev;
+	int i;
 
-	for(dev = 0; dev < ARRAY_SIZE(scx200_pci); dev++) {
-		pdev = pci_get_device(scx200_pci[dev].vendor,
-				scx200_pci[dev].device, NULL);
+	if (!pci_dev_present(scx200_isa))
+		return;
 
-		if (pdev == NULL)
+	for (i = 0; i < MAX_DEVICES; ++i) {
+		if (base[i] == 0)
 			continue;
 
-		data = scx200_pci[dev].driver_data;
-
-		/* if .bar is greater or equal to zero, this is a
-		 * PCI device - otherwise, we assume
-		   that the ports are ISA based
-		*/
-
-		if (scx200_data[data].bar >= 0)
-			rc = scx200_create_pci(scx200_data[data].name, pdev,
-					scx200_data[data].bar);
-		else {
-			int i;
-
-			pci_dev_put(pdev);
-			for (i = 0; i < MAX_DEVICES; ++i) {
-				if (base[i] == 0)
-					continue;
-
-				rc = scx200_create_isa(scx200_data[data].name,
-						base[i],
-						i);
-			}
-		}
-
-		break;
+		/* XXX: should we care about failures? */
+		scx200_create_dev("SCx200", base[i], i, NULL);
 	}
-
-	return rc;
 }
 
 static int __init scx200_acb_init(void)
 {
-	int rc;
-
 	pr_debug(NAME ": NatSemi SCx200 ACCESS.bus Driver\n");
 
-	rc = scx200_scan_pci();
+	/* First scan for ISA-based devices */
+	scx200_scan_isa();	/* XXX: should we care about errors? */
 
 	/* If at least one bus was created, init must succeed */
 	if (scx200_acb_list)
 		return 0;
-	return rc;
+
+	/* No ISA devices; register the platform driver for PCI-based devices */
+	return platform_driver_register(&scx200_pci_drv);
 }
 
 static void __exit scx200_acb_cleanup(void)
 {
 	struct scx200_acb_iface *iface;
 
+	platform_driver_unregister(&scx200_pci_drv);
+
 	mutex_lock(&scx200_acb_list_mutex);
 	while ((iface = scx200_acb_list) != NULL) {
 		scx200_acb_list = iface->next;
 		mutex_unlock(&scx200_acb_list_mutex);
 
-		i2c_del_adapter(&iface->adapter);
-
-		if (iface->pdev) {
-			pci_release_region(iface->pdev, iface->bar);
-			pci_dev_put(iface->pdev);
-		}
-		else
-			release_region(iface->base, 8);
+		scx200_cleanup_iface(iface);
 
-		kfree(iface);
 		mutex_lock(&scx200_acb_list_mutex);
 	}
 	mutex_unlock(&scx200_acb_list_mutex);
diff -druNp linux-libre-2.6.37-gnu1/drivers/i2c/i2c-core.c linux-libre-2.6.38-gnu1/drivers/i2c/i2c-core.c
--- linux-libre-2.6.37-gnu1/drivers/i2c/i2c-core.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/i2c/i2c-core.c	2011-03-14 21:20:32.000000000 -0400
@@ -196,88 +196,60 @@ static int i2c_device_pm_suspend(struct
 {
 	const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
 
-	if (pm) {
-		if (pm_runtime_suspended(dev))
-			return 0;
-		else
-			return pm->suspend ? pm->suspend(dev) : 0;
-	}
-
-	return i2c_legacy_suspend(dev, PMSG_SUSPEND);
+	if (pm)
+		return pm_generic_suspend(dev);
+	else
+		return i2c_legacy_suspend(dev, PMSG_SUSPEND);
 }
 
 static int i2c_device_pm_resume(struct device *dev)
 {
 	const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
-	int ret;
 
 	if (pm)
-		ret = pm->resume ? pm->resume(dev) : 0;
+		return pm_generic_resume(dev);
 	else
-		ret = i2c_legacy_resume(dev);
-
-	return ret;
+		return i2c_legacy_resume(dev);
 }
 
 static int i2c_device_pm_freeze(struct device *dev)
 {
 	const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
 
-	if (pm) {
-		if (pm_runtime_suspended(dev))
-			return 0;
-		else
-			return pm->freeze ? pm->freeze(dev) : 0;
-	}
-
-	return i2c_legacy_suspend(dev, PMSG_FREEZE);
+	if (pm)
+		return pm_generic_freeze(dev);
+	else
+		return i2c_legacy_suspend(dev, PMSG_FREEZE);
 }
 
 static int i2c_device_pm_thaw(struct device *dev)
 {
 	const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
 
-	if (pm) {
-		if (pm_runtime_suspended(dev))
-			return 0;
-		else
-			return pm->thaw ? pm->thaw(dev) : 0;
-	}
-
-	return i2c_legacy_resume(dev);
+	if (pm)
+		return pm_generic_thaw(dev);
+	else
+		return i2c_legacy_resume(dev);
 }
 
 static int i2c_device_pm_poweroff(struct device *dev)
 {
 	const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
 
-	if (pm) {
-		if (pm_runtime_suspended(dev))
-			return 0;
-		else
-			return pm->poweroff ? pm->poweroff(dev) : 0;
-	}
-
-	return i2c_legacy_suspend(dev, PMSG_HIBERNATE);
+	if (pm)
+		return pm_generic_poweroff(dev);
+	else
+		return i2c_legacy_suspend(dev, PMSG_HIBERNATE);
 }
 
 static int i2c_device_pm_restore(struct device *dev)
 {
 	const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
-	int ret;
 
 	if (pm)
-		ret = pm->restore ? pm->restore(dev) : 0;
+		return pm_generic_restore(dev);
 	else
-		ret = i2c_legacy_resume(dev);
-
-	if (!ret) {
-		pm_runtime_disable(dev);
-		pm_runtime_set_active(dev);
-		pm_runtime_enable(dev);
-	}
-
-	return ret;
+		return i2c_legacy_resume(dev);
 }
 #else /* !CONFIG_PM_SLEEP */
 #define i2c_device_pm_suspend	NULL
@@ -1021,6 +993,14 @@ static int i2c_do_del_adapter(struct i2c
 static int __unregister_client(struct device *dev, void *dummy)
 {
 	struct i2c_client *client = i2c_verify_client(dev);
+	if (client && strcmp(client->name, "dummy"))
+		i2c_unregister_device(client);
+	return 0;
+}
+
+static int __unregister_dummy(struct device *dev, void *dummy)
+{
+	struct i2c_client *client = i2c_verify_client(dev);
 	if (client)
 		i2c_unregister_device(client);
 	return 0;
@@ -1075,8 +1055,12 @@ int i2c_del_adapter(struct i2c_adapter *
 	mutex_unlock(&adap->userspace_clients_lock);
 
 	/* Detach any active clients. This can't fail, thus we do not
-	   checking the returned value. */
+	 * check the returned value. This is a two-pass process, because
+	 * we can't remove the dummy devices during the first pass: they
+	 * could have been instantiated by real devices wishing to clean
+	 * them up properly, so we give them a chance to do that first. */
 	res = device_for_each_child(&adap->dev, NULL, __unregister_client);
+	res = device_for_each_child(&adap->dev, NULL, __unregister_dummy);
 
 #ifdef CONFIG_I2C_COMPAT
 	class_compat_remove_link(i2c_adapter_compat_class, &adap->dev,
@@ -1140,6 +1124,14 @@ int i2c_register_driver(struct module *o
 	if (res)
 		return res;
 
+	/* Drivers should switch to dev_pm_ops instead. */
+	if (driver->suspend)
+		pr_warn("i2c-core: driver [%s] using legacy suspend method\n",
+			driver->driver.name);
+	if (driver->resume)
+		pr_warn("i2c-core: driver [%s] using legacy resume method\n",
+			driver->driver.name);
+
 	pr_debug("i2c-core: driver [%s] registered\n", driver->driver.name);
 
 	INIT_LIST_HEAD(&driver->clients);
@@ -1362,7 +1354,7 @@ EXPORT_SYMBOL(i2c_transfer);
  *
  * Returns negative errno, or else the number of bytes written.
  */
-int i2c_master_send(struct i2c_client *client, const char *buf, int count)
+int i2c_master_send(const struct i2c_client *client, const char *buf, int count)
 {
 	int ret;
 	struct i2c_adapter *adap = client->adapter;
@@ -1389,7 +1381,7 @@ EXPORT_SYMBOL(i2c_master_send);
  *
  * Returns negative errno, or else the number of bytes read.
  */
-int i2c_master_recv(struct i2c_client *client, char *buf, int count)
+int i2c_master_recv(const struct i2c_client *client, char *buf, int count)
 {
 	struct i2c_adapter *adap = client->adapter;
 	struct i2c_msg msg;
@@ -1679,7 +1671,7 @@ static int i2c_smbus_check_pec(u8 cpec,
  * This executes the SMBus "receive byte" protocol, returning negative errno
  * else the byte received from the device.
  */
-s32 i2c_smbus_read_byte(struct i2c_client *client)
+s32 i2c_smbus_read_byte(const struct i2c_client *client)
 {
 	union i2c_smbus_data data;
 	int status;
@@ -1699,7 +1691,7 @@ EXPORT_SYMBOL(i2c_smbus_read_byte);
  * This executes the SMBus "send byte" protocol, returning negative errno
  * else zero on success.
  */
-s32 i2c_smbus_write_byte(struct i2c_client *client, u8 value)
+s32 i2c_smbus_write_byte(const struct i2c_client *client, u8 value)
 {
 	return i2c_smbus_xfer(client->adapter, client->addr, client->flags,
 	                      I2C_SMBUS_WRITE, value, I2C_SMBUS_BYTE, NULL);
@@ -1714,7 +1706,7 @@ EXPORT_SYMBOL(i2c_smbus_write_byte);
  * This executes the SMBus "read byte" protocol, returning negative errno
  * else a data byte received from the device.
  */
-s32 i2c_smbus_read_byte_data(struct i2c_client *client, u8 command)
+s32 i2c_smbus_read_byte_data(const struct i2c_client *client, u8 command)
 {
 	union i2c_smbus_data data;
 	int status;
@@ -1735,7 +1727,8 @@ EXPORT_SYMBOL(i2c_smbus_read_byte_data);
  * This executes the SMBus "write byte" protocol, returning negative errno
  * else zero on success.
  */
-s32 i2c_smbus_write_byte_data(struct i2c_client *client, u8 command, u8 value)
+s32 i2c_smbus_write_byte_data(const struct i2c_client *client, u8 command,
+			      u8 value)
 {
 	union i2c_smbus_data data;
 	data.byte = value;
@@ -1753,7 +1746,7 @@ EXPORT_SYMBOL(i2c_smbus_write_byte_data)
  * This executes the SMBus "read word" protocol, returning negative errno
  * else a 16-bit unsigned "word" received from the device.
  */
-s32 i2c_smbus_read_word_data(struct i2c_client *client, u8 command)
+s32 i2c_smbus_read_word_data(const struct i2c_client *client, u8 command)
 {
 	union i2c_smbus_data data;
 	int status;
@@ -1774,7 +1767,8 @@ EXPORT_SYMBOL(i2c_smbus_read_word_data);
  * This executes the SMBus "write word" protocol, returning negative errno
  * else zero on success.
  */
-s32 i2c_smbus_write_word_data(struct i2c_client *client, u8 command, u16 value)
+s32 i2c_smbus_write_word_data(const struct i2c_client *client, u8 command,
+			      u16 value)
 {
 	union i2c_smbus_data data;
 	data.word = value;
@@ -1793,7 +1787,8 @@ EXPORT_SYMBOL(i2c_smbus_write_word_data)
  * This executes the SMBus "process call" protocol, returning negative errno
  * else a 16-bit unsigned "word" received from the device.
  */
-s32 i2c_smbus_process_call(struct i2c_client *client, u8 command, u16 value)
+s32 i2c_smbus_process_call(const struct i2c_client *client, u8 command,
+			   u16 value)
 {
 	union i2c_smbus_data data;
 	int status;
@@ -1821,7 +1816,7 @@ EXPORT_SYMBOL(i2c_smbus_process_call);
  * support this; its emulation through I2C messaging relies on a specific
  * mechanism (I2C_M_RECV_LEN) which may not be implemented.
  */
-s32 i2c_smbus_read_block_data(struct i2c_client *client, u8 command,
+s32 i2c_smbus_read_block_data(const struct i2c_client *client, u8 command,
 			      u8 *values)
 {
 	union i2c_smbus_data data;
@@ -1848,7 +1843,7 @@ EXPORT_SYMBOL(i2c_smbus_read_block_data)
  * This executes the SMBus "block write" protocol, returning negative errno
  * else zero on success.
  */
-s32 i2c_smbus_write_block_data(struct i2c_client *client, u8 command,
+s32 i2c_smbus_write_block_data(const struct i2c_client *client, u8 command,
 			       u8 length, const u8 *values)
 {
 	union i2c_smbus_data data;
@@ -1864,7 +1859,7 @@ s32 i2c_smbus_write_block_data(struct i2
 EXPORT_SYMBOL(i2c_smbus_write_block_data);
 
 /* Returns the number of read bytes */
-s32 i2c_smbus_read_i2c_block_data(struct i2c_client *client, u8 command,
+s32 i2c_smbus_read_i2c_block_data(const struct i2c_client *client, u8 command,
 				  u8 length, u8 *values)
 {
 	union i2c_smbus_data data;
@@ -1884,7 +1879,7 @@ s32 i2c_smbus_read_i2c_block_data(struct
 }
 EXPORT_SYMBOL(i2c_smbus_read_i2c_block_data);
 
-s32 i2c_smbus_write_i2c_block_data(struct i2c_client *client, u8 command,
+s32 i2c_smbus_write_i2c_block_data(const struct i2c_client *client, u8 command,
 				   u8 length, const u8 *values)
 {
 	union i2c_smbus_data data;
diff -druNp linux-libre-2.6.37-gnu1/drivers/i2c/muxes/gpio-i2cmux.c linux-libre-2.6.38-gnu1/drivers/i2c/muxes/gpio-i2cmux.c
--- linux-libre-2.6.37-gnu1/drivers/i2c/muxes/gpio-i2cmux.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/i2c/muxes/gpio-i2cmux.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,184 @@
+/*
+ * I2C multiplexer using GPIO API
+ *
+ * Peter Korsgaard <peter.korsgaard@barco.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/i2c.h>
+#include <linux/i2c-mux.h>
+#include <linux/gpio-i2cmux.h>
+#include <linux/platform_device.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/gpio.h>
+
+struct gpiomux {
+	struct i2c_adapter *parent;
+	struct i2c_adapter **adap; /* child busses */
+	struct gpio_i2cmux_platform_data data;
+};
+
+static void gpiomux_set(const struct gpiomux *mux, unsigned val)
+{
+	int i;
+
+	for (i = 0; i < mux->data.n_gpios; i++)
+		gpio_set_value(mux->data.gpios[i], val & (1 << i));
+}
+
+static int gpiomux_select(struct i2c_adapter *adap, void *data, u32 chan)
+{
+	struct gpiomux *mux = data;
+
+	gpiomux_set(mux, mux->data.values[chan]);
+
+	return 0;
+}
+
+static int gpiomux_deselect(struct i2c_adapter *adap, void *data, u32 chan)
+{
+	struct gpiomux *mux = data;
+
+	gpiomux_set(mux, mux->data.idle);
+
+	return 0;
+}
+
+static int __devinit gpiomux_probe(struct platform_device *pdev)
+{
+	struct gpiomux *mux;
+	struct gpio_i2cmux_platform_data *pdata;
+	struct i2c_adapter *parent;
+	int (*deselect) (struct i2c_adapter *, void *, u32);
+	unsigned initial_state;
+	int i, ret;
+
+	pdata = pdev->dev.platform_data;
+	if (!pdata) {
+		dev_err(&pdev->dev, "Missing platform data\n");
+		return -ENODEV;
+	}
+
+	parent = i2c_get_adapter(pdata->parent);
+	if (!parent) {
+		dev_err(&pdev->dev, "Parent adapter (%d) not found\n",
+			pdata->parent);
+		return -ENODEV;
+	}
+
+	mux = kzalloc(sizeof(*mux), GFP_KERNEL);
+	if (!mux) {
+		ret = -ENOMEM;
+		goto alloc_failed;
+	}
+
+	mux->parent = parent;
+	mux->data = *pdata;
+	mux->adap = kzalloc(sizeof(struct i2c_adapter *) * pdata->n_values,
+			    GFP_KERNEL);
+	if (!mux->adap) {
+		ret = -ENOMEM;
+		goto alloc_failed2;
+	}
+
+	if (pdata->idle != GPIO_I2CMUX_NO_IDLE) {
+		initial_state = pdata->idle;
+		deselect = gpiomux_deselect;
+	} else {
+		initial_state = pdata->values[0];
+		deselect = NULL;
+	}
+
+	for (i = 0; i < pdata->n_gpios; i++) {
+		ret = gpio_request(pdata->gpios[i], "gpio-i2cmux");
+		if (ret)
+			goto err_request_gpio;
+		gpio_direction_output(pdata->gpios[i],
+				      initial_state & (1 << i));
+	}
+
+	for (i = 0; i < pdata->n_values; i++) {
+		u32 nr = pdata->base_nr ? (pdata->base_nr + i) : 0;
+
+		mux->adap[i] = i2c_add_mux_adapter(parent, mux, nr, i,
+						   gpiomux_select, deselect);
+		if (!mux->adap[i]) {
+			ret = -ENODEV;
+			dev_err(&pdev->dev, "Failed to add adapter %d\n", i);
+			goto add_adapter_failed;
+		}
+	}
+
+	dev_info(&pdev->dev, "%d port mux on %s adapter\n",
+		 pdata->n_values, parent->name);
+
+	platform_set_drvdata(pdev, mux);
+
+	return 0;
+
+add_adapter_failed:
+	for (; i > 0; i--)
+		i2c_del_mux_adapter(mux->adap[i - 1]);
+	i = pdata->n_gpios;
+err_request_gpio:
+	for (; i > 0; i--)
+		gpio_free(pdata->gpios[i - 1]);
+	kfree(mux->adap);
+alloc_failed2:
+	kfree(mux);
+alloc_failed:
+	i2c_put_adapter(parent);
+
+	return ret;
+}
+
+static int __devexit gpiomux_remove(struct platform_device *pdev)
+{
+	struct gpiomux *mux = platform_get_drvdata(pdev);
+	int i;
+
+	for (i = 0; i < mux->data.n_values; i++)
+		i2c_del_mux_adapter(mux->adap[i]);
+
+	for (i = 0; i < mux->data.n_gpios; i++)
+		gpio_free(mux->data.gpios[i]);
+
+	platform_set_drvdata(pdev, NULL);
+	i2c_put_adapter(mux->parent);
+	kfree(mux->adap);
+	kfree(mux);
+
+	return 0;
+}
+
+static struct platform_driver gpiomux_driver = {
+	.probe	= gpiomux_probe,
+	.remove	= __devexit_p(gpiomux_remove),
+	.driver	= {
+		.owner	= THIS_MODULE,
+		.name	= "gpio-i2cmux",
+	},
+};
+
+static int __init gpiomux_init(void)
+{
+	return platform_driver_register(&gpiomux_driver);
+}
+
+static void __exit gpiomux_exit(void)
+{
+	platform_driver_unregister(&gpiomux_driver);
+}
+
+module_init(gpiomux_init);
+module_exit(gpiomux_exit);
+
+MODULE_DESCRIPTION("GPIO-based I2C multiplexer driver");
+MODULE_AUTHOR("Peter Korsgaard <peter.korsgaard@barco.com>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:gpio-i2cmux");
diff -druNp linux-libre-2.6.37-gnu1/drivers/i2c/muxes/Kconfig linux-libre-2.6.38-gnu1/drivers/i2c/muxes/Kconfig
--- linux-libre-2.6.37-gnu1/drivers/i2c/muxes/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/i2c/muxes/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -5,6 +5,18 @@
 menu "Multiplexer I2C Chip support"
 	depends on I2C_MUX
 
+config I2C_MUX_GPIO
+	tristate "GPIO-based I2C multiplexer"
+	depends on GENERIC_GPIO
+	help
+	  If you say yes to this option, support will be included for a
+	  GPIO based I2C multiplexer. This driver provides access to
+	  I2C busses connected through a MUX, which is controlled
+	  through GPIO pins.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called gpio-i2cmux.
+
 config I2C_MUX_PCA9541
 	tristate "NXP PCA9541 I2C Master Selector"
 	depends on EXPERIMENTAL
diff -druNp linux-libre-2.6.37-gnu1/drivers/i2c/muxes/Makefile linux-libre-2.6.38-gnu1/drivers/i2c/muxes/Makefile
--- linux-libre-2.6.37-gnu1/drivers/i2c/muxes/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/i2c/muxes/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -1,6 +1,7 @@
 #
 # Makefile for multiplexer I2C chip drivers.
 
+obj-$(CONFIG_I2C_MUX_GPIO)	+= gpio-i2cmux.o
 obj-$(CONFIG_I2C_MUX_PCA9541)	+= pca9541.o
 obj-$(CONFIG_I2C_MUX_PCA954x)	+= pca954x.o
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/ide/Kconfig linux-libre-2.6.38-gnu1/drivers/ide/Kconfig
--- linux-libre-2.6.37-gnu1/drivers/ide/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/ide/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -134,7 +134,7 @@ config BLK_DEV_IDECD
 	  module will be called ide-cd.
 
 config BLK_DEV_IDECD_VERBOSE_ERRORS
-	bool "Verbose error logging for IDE/ATAPI CDROM driver" if EMBEDDED
+	bool "Verbose error logging for IDE/ATAPI CDROM driver" if EXPERT
 	depends on BLK_DEV_IDECD
 	default y
 	help
diff -druNp linux-libre-2.6.37-gnu1/drivers/idle/intel_idle.c linux-libre-2.6.38-gnu1/drivers/idle/intel_idle.c
--- linux-libre-2.6.37-gnu1/drivers/idle/intel_idle.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/idle/intel_idle.c	2011-03-14 21:20:32.000000000 -0400
@@ -59,7 +59,10 @@
 #include <linux/hrtimer.h>	/* ktime_get_real() */
 #include <trace/events/power.h>
 #include <linux/sched.h>
+#include <linux/notifier.h>
+#include <linux/cpu.h>
 #include <asm/mwait.h>
+#include <asm/msr.h>
 
 #define INTEL_IDLE_VERSION "0.4"
 #define PREFIX "intel_idle: "
@@ -73,6 +76,7 @@ static int max_cstate = MWAIT_MAX_NUM_CS
 
 static unsigned int mwait_substates;
 
+#define LAPIC_TIMER_ALWAYS_RELIABLE 0xFFFFFFFF
 /* Reliable LAPIC Timer States, bit 1 for C1 etc.  */
 static unsigned int lapic_timer_reliable_states = (1 << 1);	 /* Default to only C1 */
 
@@ -82,6 +86,20 @@ static int intel_idle(struct cpuidle_dev
 static struct cpuidle_state *cpuidle_state_table;
 
 /*
+ * Hardware C-state auto-demotion may not always be optimal.
+ * Indicate which enable bits to clear here.
+ */
+static unsigned long long auto_demotion_disable_flags;
+
+/*
+ * Set this flag for states where the HW flushes the TLB for us
+ * and so we don't need cross-calls to keep it consistent.
+ * If this flag is set, SW flushes the TLB, so even if the
+ * HW doesn't do the flushing, this flag is safe to use.
+ */
+#define CPUIDLE_FLAG_TLB_FLUSHED	0x10000
+
+/*
  * States are indexed by the cstate number,
  * which is also the index into the MWAIT hint array.
  * Thus C0 is a dummy.
@@ -122,7 +140,7 @@ static struct cpuidle_state snb_cstates[
 		.driver_data = (void *) 0x00,
 		.flags = CPUIDLE_FLAG_TIME_VALID,
 		.exit_latency = 1,
-		.target_residency = 4,
+		.target_residency = 1,
 		.enter = &intel_idle },
 	{ /* MWAIT C2 */
 		.name = "SNB-C3",
@@ -130,7 +148,7 @@ static struct cpuidle_state snb_cstates[
 		.driver_data = (void *) 0x10,
 		.flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
 		.exit_latency = 80,
-		.target_residency = 160,
+		.target_residency = 211,
 		.enter = &intel_idle },
 	{ /* MWAIT C3 */
 		.name = "SNB-C6",
@@ -138,7 +156,7 @@ static struct cpuidle_state snb_cstates[
 		.driver_data = (void *) 0x20,
 		.flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
 		.exit_latency = 104,
-		.target_residency = 208,
+		.target_residency = 345,
 		.enter = &intel_idle },
 	{ /* MWAIT C4 */
 		.name = "SNB-C7",
@@ -146,7 +164,7 @@ static struct cpuidle_state snb_cstates[
 		.driver_data = (void *) 0x30,
 		.flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
 		.exit_latency = 109,
-		.target_residency = 300,
+		.target_residency = 345,
 		.enter = &intel_idle },
 };
 
@@ -220,9 +238,6 @@ static int intel_idle(struct cpuidle_dev
 	kt_before = ktime_get_real();
 
 	stop_critical_timings();
-#ifndef MODULE
-	trace_power_start(POWER_CSTATE, (eax >> 4) + 1, cpu);
-#endif
 	if (!need_resched()) {
 
 		__monitor((void *)&current_thread_info()->flags, 0, 0);
@@ -244,6 +259,44 @@ static int intel_idle(struct cpuidle_dev
 	return usec_delta;
 }
 
+static void __setup_broadcast_timer(void *arg)
+{
+	unsigned long reason = (unsigned long)arg;
+	int cpu = smp_processor_id();
+
+	reason = reason ?
+		CLOCK_EVT_NOTIFY_BROADCAST_ON : CLOCK_EVT_NOTIFY_BROADCAST_OFF;
+
+	clockevents_notify(reason, &cpu);
+}
+
+static int setup_broadcast_cpuhp_notify(struct notifier_block *n,
+		unsigned long action, void *hcpu)
+{
+	int hotcpu = (unsigned long)hcpu;
+
+	switch (action & 0xf) {
+	case CPU_ONLINE:
+		smp_call_function_single(hotcpu, __setup_broadcast_timer,
+			(void *)true, 1);
+		break;
+	}
+	return NOTIFY_OK;
+}
+
+static struct notifier_block setup_broadcast_notifier = {
+	.notifier_call = setup_broadcast_cpuhp_notify,
+};
+
+static void auto_demotion_disable(void *dummy)
+{
+	unsigned long long msr_bits;
+
+	rdmsrl(MSR_NHM_SNB_PKG_CST_CFG_CTL, msr_bits);
+	msr_bits &= ~auto_demotion_disable_flags;
+	wrmsrl(MSR_NHM_SNB_PKG_CST_CFG_CTL, msr_bits);
+}
+
 /*
  * intel_idle_probe()
  */
@@ -287,11 +340,17 @@ static int intel_idle_probe(void)
 	case 0x25:	/* Westmere */
 	case 0x2C:	/* Westmere */
 		cpuidle_state_table = nehalem_cstates;
+		auto_demotion_disable_flags =
+			(NHM_C1_AUTO_DEMOTE | NHM_C3_AUTO_DEMOTE);
 		break;
 
 	case 0x1C:	/* 28 - Atom Processor */
+		cpuidle_state_table = atom_cstates;
+		break;
+
 	case 0x26:	/* 38 - Lincroft Atom Processor */
 		cpuidle_state_table = atom_cstates;
+		auto_demotion_disable_flags = ATM_LNC_C6_AUTO_DEMOTE;
 		break;
 
 	case 0x2A:	/* SNB */
@@ -306,7 +365,11 @@ static int intel_idle_probe(void)
 	}
 
 	if (boot_cpu_has(X86_FEATURE_ARAT))	/* Always Reliable APIC Timer */
-		lapic_timer_reliable_states = 0xFFFFFFFF;
+		lapic_timer_reliable_states = LAPIC_TIMER_ALWAYS_RELIABLE;
+	else {
+		smp_call_function(__setup_broadcast_timer, (void *)true, 1);
+		register_cpu_notifier(&setup_broadcast_notifier);
+	}
 
 	pr_debug(PREFIX "v" INTEL_IDLE_VERSION
 		" model 0x%X\n", boot_cpu_data.x86_model);
@@ -395,6 +458,8 @@ static int intel_idle_cpuidle_devices_in
 			return -EIO;
 		}
 	}
+	if (auto_demotion_disable_flags)
+		smp_call_function(auto_demotion_disable, NULL, 1);
 
 	return 0;
 }
@@ -404,6 +469,10 @@ static int __init intel_idle_init(void)
 {
 	int retval;
 
+	/* Do not load intel_idle at all for now if idle= is passed */
+	if (boot_option_idle_override != IDLE_NO_OVERRIDE)
+		return -ENODEV;
+
 	retval = intel_idle_probe();
 	if (retval)
 		return retval;
@@ -429,6 +498,11 @@ static void __exit intel_idle_exit(void)
 	intel_idle_cpuidle_devices_uninit();
 	cpuidle_unregister_driver(&intel_idle_driver);
 
+	if (lapic_timer_reliable_states != LAPIC_TIMER_ALWAYS_RELIABLE) {
+		smp_call_function(__setup_broadcast_timer, (void *)false, 1);
+		unregister_cpu_notifier(&setup_broadcast_notifier);
+	}
+
 	return;
 }
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/infiniband/core/addr.c linux-libre-2.6.38-gnu1/drivers/infiniband/core/addr.c
--- linux-libre-2.6.37-gnu1/drivers/infiniband/core/addr.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/infiniband/core/addr.c	2011-03-14 21:20:32.000000000 -0400
@@ -130,8 +130,8 @@ int rdma_translate_ip(struct sockaddr *a
 
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 	case AF_INET6:
-		read_lock(&dev_base_lock);
-		for_each_netdev(&init_net, dev) {
+		rcu_read_lock();
+		for_each_netdev_rcu(&init_net, dev) {
 			if (ipv6_chk_addr(&init_net,
 					  &((struct sockaddr_in6 *) addr)->sin6_addr,
 					  dev, 1)) {
@@ -139,7 +139,7 @@ int rdma_translate_ip(struct sockaddr *a
 				break;
 			}
 		}
-		read_unlock(&dev_base_lock);
+		rcu_read_unlock();
 		break;
 #endif
 	}
@@ -200,7 +200,7 @@ static int addr4_resolve(struct sockaddr
 	src_in->sin_family = AF_INET;
 	src_in->sin_addr.s_addr = rt->rt_src;
 
-	if (rt->idev->dev->flags & IFF_LOOPBACK) {
+	if (rt->dst.dev->flags & IFF_LOOPBACK) {
 		ret = rdma_translate_ip((struct sockaddr *) dst_in, addr);
 		if (!ret)
 			memcpy(addr->dst_dev_addr, addr->src_dev_addr, MAX_ADDR_LEN);
@@ -208,12 +208,12 @@ static int addr4_resolve(struct sockaddr
 	}
 
 	/* If the device does ARP internally, return 'done' */
-	if (rt->idev->dev->flags & IFF_NOARP) {
-		rdma_copy_addr(addr, rt->idev->dev, NULL);
+	if (rt->dst.dev->flags & IFF_NOARP) {
+		rdma_copy_addr(addr, rt->dst.dev, NULL);
 		goto put;
 	}
 
-	neigh = neigh_lookup(&arp_tbl, &rt->rt_gateway, rt->idev->dev);
+	neigh = neigh_lookup(&arp_tbl, &rt->rt_gateway, rt->dst.dev);
 	if (!neigh || !(neigh->nud_state & NUD_VALID)) {
 		neigh_event_send(rt->dst.neighbour, NULL);
 		ret = -ENODATA;
diff -druNp linux-libre-2.6.37-gnu1/drivers/infiniband/core/cache.c linux-libre-2.6.38-gnu1/drivers/infiniband/core/cache.c
--- linux-libre-2.6.37-gnu1/drivers/infiniband/core/cache.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/infiniband/core/cache.c	2011-03-14 21:20:32.000000000 -0400
@@ -308,7 +308,7 @@ static void ib_cache_event(struct ib_eve
 			INIT_WORK(&work->work, ib_cache_task);
 			work->device   = event->device;
 			work->port_num = event->element.port_num;
-			schedule_work(&work->work);
+			queue_work(ib_wq, &work->work);
 		}
 	}
 }
@@ -368,7 +368,7 @@ static void ib_cache_cleanup_one(struct
 	int p;
 
 	ib_unregister_event_handler(&device->cache.event_handler);
-	flush_scheduled_work();
+	flush_workqueue(ib_wq);
 
 	for (p = 0; p <= end_port(device) - start_port(device); ++p) {
 		kfree(device->cache.pkey_cache[p]);
diff -druNp linux-libre-2.6.37-gnu1/drivers/infiniband/core/device.c linux-libre-2.6.38-gnu1/drivers/infiniband/core/device.c
--- linux-libre-2.6.37-gnu1/drivers/infiniband/core/device.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/infiniband/core/device.c	2011-03-14 21:20:32.000000000 -0400
@@ -38,7 +38,6 @@
 #include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/mutex.h>
-#include <linux/workqueue.h>
 
 #include "core_priv.h"
 
@@ -52,6 +51,9 @@ struct ib_client_data {
 	void *            data;
 };
 
+struct workqueue_struct *ib_wq;
+EXPORT_SYMBOL_GPL(ib_wq);
+
 static LIST_HEAD(device_list);
 static LIST_HEAD(client_list);
 
@@ -718,6 +720,10 @@ static int __init ib_core_init(void)
 {
 	int ret;
 
+	ib_wq = alloc_workqueue("infiniband", 0, 0);
+	if (!ib_wq)
+		return -ENOMEM;
+
 	ret = ib_sysfs_setup();
 	if (ret)
 		printk(KERN_WARNING "Couldn't create InfiniBand device class\n");
@@ -726,6 +732,7 @@ static int __init ib_core_init(void)
 	if (ret) {
 		printk(KERN_WARNING "Couldn't set up InfiniBand P_Key/GID cache\n");
 		ib_sysfs_cleanup();
+		destroy_workqueue(ib_wq);
 	}
 
 	return ret;
@@ -736,7 +743,7 @@ static void __exit ib_core_cleanup(void)
 	ib_cache_cleanup();
 	ib_sysfs_cleanup();
 	/* Make sure that any pending umem accounting work is done. */
-	flush_scheduled_work();
+	destroy_workqueue(ib_wq);
 }
 
 module_init(ib_core_init);
diff -druNp linux-libre-2.6.37-gnu1/drivers/infiniband/core/sa_query.c linux-libre-2.6.38-gnu1/drivers/infiniband/core/sa_query.c
--- linux-libre-2.6.37-gnu1/drivers/infiniband/core/sa_query.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/infiniband/core/sa_query.c	2011-03-14 21:20:32.000000000 -0400
@@ -425,7 +425,7 @@ static void ib_sa_event(struct ib_event_
 		port->sm_ah = NULL;
 		spin_unlock_irqrestore(&port->ah_lock, flags);
 
-		schedule_work(&sa_dev->port[event->element.port_num -
+		queue_work(ib_wq, &sa_dev->port[event->element.port_num -
 					    sa_dev->start_port].update_task);
 	}
 }
@@ -1079,7 +1079,7 @@ static void ib_sa_remove_one(struct ib_d
 
 	ib_unregister_event_handler(&sa_dev->event_handler);
 
-	flush_scheduled_work();
+	flush_workqueue(ib_wq);
 
 	for (i = 0; i <= sa_dev->end_port - sa_dev->start_port; ++i) {
 		if (rdma_port_get_link_layer(device, i + 1) == IB_LINK_LAYER_INFINIBAND) {
diff -druNp linux-libre-2.6.37-gnu1/drivers/infiniband/core/ucma.c linux-libre-2.6.38-gnu1/drivers/infiniband/core/ucma.c
--- linux-libre-2.6.37-gnu1/drivers/infiniband/core/ucma.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/infiniband/core/ucma.c	2011-03-14 21:20:32.000000000 -0400
@@ -636,6 +636,16 @@ static void ucma_copy_iboe_route(struct
 	}
 }
 
+static void ucma_copy_iw_route(struct rdma_ucm_query_route_resp *resp,
+			       struct rdma_route *route)
+{
+	struct rdma_dev_addr *dev_addr;
+
+	dev_addr = &route->addr.dev_addr;
+	rdma_addr_get_dgid(dev_addr, (union ib_gid *) &resp->ib_route[0].dgid);
+	rdma_addr_get_sgid(dev_addr, (union ib_gid *) &resp->ib_route[0].sgid);
+}
+
 static ssize_t ucma_query_route(struct ucma_file *file,
 				const char __user *inbuf,
 				int in_len, int out_len)
@@ -670,8 +680,10 @@ static ssize_t ucma_query_route(struct u
 
 	resp.node_guid = (__force __u64) ctx->cm_id->device->node_guid;
 	resp.port_num = ctx->cm_id->port_num;
-	if (rdma_node_get_transport(ctx->cm_id->device->node_type) == RDMA_TRANSPORT_IB) {
-		switch (rdma_port_get_link_layer(ctx->cm_id->device, ctx->cm_id->port_num)) {
+	switch (rdma_node_get_transport(ctx->cm_id->device->node_type)) {
+	case RDMA_TRANSPORT_IB:
+		switch (rdma_port_get_link_layer(ctx->cm_id->device,
+			ctx->cm_id->port_num)) {
 		case IB_LINK_LAYER_INFINIBAND:
 			ucma_copy_ib_route(&resp, &ctx->cm_id->route);
 			break;
@@ -681,6 +693,12 @@ static ssize_t ucma_query_route(struct u
 		default:
 			break;
 		}
+		break;
+	case RDMA_TRANSPORT_IWARP:
+		ucma_copy_iw_route(&resp, &ctx->cm_id->route);
+		break;
+	default:
+		break;
 	}
 
 out:
diff -druNp linux-libre-2.6.37-gnu1/drivers/infiniband/core/umem.c linux-libre-2.6.38-gnu1/drivers/infiniband/core/umem.c
--- linux-libre-2.6.37-gnu1/drivers/infiniband/core/umem.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/infiniband/core/umem.c	2011-03-14 21:20:32.000000000 -0400
@@ -262,7 +262,7 @@ void ib_umem_release(struct ib_umem *ume
 			umem->mm   = mm;
 			umem->diff = diff;
 
-			schedule_work(&umem->work);
+			queue_work(ib_wq, &umem->work);
 			return;
 		}
 	} else
diff -druNp linux-libre-2.6.37-gnu1/drivers/infiniband/hw/amso1100/c2_rnic.c linux-libre-2.6.38-gnu1/drivers/infiniband/hw/amso1100/c2_rnic.c
--- linux-libre-2.6.37-gnu1/drivers/infiniband/hw/amso1100/c2_rnic.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/infiniband/hw/amso1100/c2_rnic.c	2011-03-14 21:20:32.000000000 -0400
@@ -459,13 +459,12 @@ int __devinit c2_rnic_init(struct c2_dev
 	     IB_DEVICE_MEM_WINDOW);
 
 	/* Allocate the qptr_array */
-	c2dev->qptr_array = vmalloc(C2_MAX_CQS * sizeof(void *));
+	c2dev->qptr_array = vzalloc(C2_MAX_CQS * sizeof(void *));
 	if (!c2dev->qptr_array) {
 		return -ENOMEM;
 	}
 
-	/* Inialize the qptr_array */
-	memset(c2dev->qptr_array, 0, C2_MAX_CQS * sizeof(void *));
+	/* Initialize the qptr_array */
 	c2dev->qptr_array[0] = (void *) &c2dev->req_vq;
 	c2dev->qptr_array[1] = (void *) &c2dev->rep_vq;
 	c2dev->qptr_array[2] = (void *) &c2dev->aeq;
diff -druNp linux-libre-2.6.37-gnu1/drivers/infiniband/hw/amso1100/c2_vq.c linux-libre-2.6.38-gnu1/drivers/infiniband/hw/amso1100/c2_vq.c
--- linux-libre-2.6.37-gnu1/drivers/infiniband/hw/amso1100/c2_vq.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/infiniband/hw/amso1100/c2_vq.c	2011-03-14 21:20:32.000000000 -0400
@@ -107,7 +107,7 @@ struct c2_vq_req *vq_req_alloc(struct c2
 	r = kmalloc(sizeof(struct c2_vq_req), GFP_KERNEL);
 	if (r) {
 		init_waitqueue_head(&r->wait_object);
-		r->reply_msg = (u64) NULL;
+		r->reply_msg = 0;
 		r->event = 0;
 		r->cm_id = NULL;
 		r->qp = NULL;
@@ -123,7 +123,7 @@ struct c2_vq_req *vq_req_alloc(struct c2
  */
 void vq_req_free(struct c2_dev *c2dev, struct c2_vq_req *r)
 {
-	r->reply_msg = (u64) NULL;
+	r->reply_msg = 0;
 	if (atomic_dec_and_test(&r->refcnt)) {
 		kfree(r);
 	}
@@ -151,7 +151,7 @@ void vq_req_get(struct c2_dev *c2dev, st
 void vq_req_put(struct c2_dev *c2dev, struct c2_vq_req *r)
 {
 	if (atomic_dec_and_test(&r->refcnt)) {
-		if (r->reply_msg != (u64) NULL)
+		if (r->reply_msg != 0)
 			vq_repbuf_free(c2dev,
 				       (void *) (unsigned long) r->reply_msg);
 		kfree(r);
diff -druNp linux-libre-2.6.37-gnu1/drivers/infiniband/hw/cxgb3/cxio_hal.c linux-libre-2.6.38-gnu1/drivers/infiniband/hw/cxgb3/cxio_hal.c
--- linux-libre-2.6.37-gnu1/drivers/infiniband/hw/cxgb3/cxio_hal.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/infiniband/hw/cxgb3/cxio_hal.c	2011-03-14 21:20:32.000000000 -0400
@@ -189,6 +189,7 @@ int cxio_create_cq(struct cxio_rdev *rde
 	return (rdev_p->t3cdev_p->ctl(rdev_p->t3cdev_p, RDMA_CQ_SETUP, &setup));
 }
 
+#ifdef notyet
 int cxio_resize_cq(struct cxio_rdev *rdev_p, struct t3_cq *cq)
 {
 	struct rdma_cq_setup setup;
@@ -200,6 +201,7 @@ int cxio_resize_cq(struct cxio_rdev *rde
 	setup.ovfl_mode = 1;
 	return (rdev_p->t3cdev_p->ctl(rdev_p->t3cdev_p, RDMA_CQ_SETUP, &setup));
 }
+#endif
 
 static u32 get_qpid(struct cxio_rdev *rdev_p, struct cxio_ucontext *uctx)
 {
diff -druNp linux-libre-2.6.37-gnu1/drivers/infiniband/hw/cxgb3/cxio_wr.h linux-libre-2.6.38-gnu1/drivers/infiniband/hw/cxgb3/cxio_wr.h
--- linux-libre-2.6.37-gnu1/drivers/infiniband/hw/cxgb3/cxio_wr.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/infiniband/hw/cxgb3/cxio_wr.h	2011-03-14 21:20:32.000000000 -0400
@@ -689,7 +689,7 @@ struct t3_swrq {
  * A T3 WQ implements both the SQ and RQ.
  */
 struct t3_wq {
-	union t3_wr *queue;		/* DMA accessable memory */
+	union t3_wr *queue;		/* DMA accessible memory */
 	dma_addr_t dma_addr;		/* DMA address for HW */
 	DEFINE_DMA_UNMAP_ADDR(mapping); /* unmap kruft */
 	u32 error;			/* 1 once we go to ERROR */
diff -druNp linux-libre-2.6.37-gnu1/drivers/infiniband/hw/cxgb3/iwch_provider.h linux-libre-2.6.38-gnu1/drivers/infiniband/hw/cxgb3/iwch_provider.h
--- linux-libre-2.6.37-gnu1/drivers/infiniband/hw/cxgb3/iwch_provider.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/infiniband/hw/cxgb3/iwch_provider.h	2011-03-14 21:20:32.000000000 -0400
@@ -335,8 +335,6 @@ int iwch_post_terminate(struct iwch_qp *
 int iwch_post_zb_read(struct iwch_qp *qhp);
 int iwch_register_device(struct iwch_dev *dev);
 void iwch_unregister_device(struct iwch_dev *dev);
-int iwch_quiesce_qps(struct iwch_cq *chp);
-int iwch_resume_qps(struct iwch_cq *chp);
 void stop_read_rep_timer(struct iwch_qp *qhp);
 int iwch_register_mem(struct iwch_dev *rhp, struct iwch_pd *php,
 		      struct iwch_mr *mhp, int shift);
diff -druNp linux-libre-2.6.37-gnu1/drivers/infiniband/hw/cxgb3/iwch_qp.c linux-libre-2.6.38-gnu1/drivers/infiniband/hw/cxgb3/iwch_qp.c
--- linux-libre-2.6.37-gnu1/drivers/infiniband/hw/cxgb3/iwch_qp.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/infiniband/hw/cxgb3/iwch_qp.c	2011-03-14 21:20:32.000000000 -0400
@@ -1149,59 +1149,3 @@ out:
 	PDBG("%s exit state %d\n", __func__, qhp->attr.state);
 	return ret;
 }
-
-static int quiesce_qp(struct iwch_qp *qhp)
-{
-	spin_lock_irq(&qhp->lock);
-	iwch_quiesce_tid(qhp->ep);
-	qhp->flags |= QP_QUIESCED;
-	spin_unlock_irq(&qhp->lock);
-	return 0;
-}
-
-static int resume_qp(struct iwch_qp *qhp)
-{
-	spin_lock_irq(&qhp->lock);
-	iwch_resume_tid(qhp->ep);
-	qhp->flags &= ~QP_QUIESCED;
-	spin_unlock_irq(&qhp->lock);
-	return 0;
-}
-
-int iwch_quiesce_qps(struct iwch_cq *chp)
-{
-	int i;
-	struct iwch_qp *qhp;
-
-	for (i=0; i < T3_MAX_NUM_QP; i++) {
-		qhp = get_qhp(chp->rhp, i);
-		if (!qhp)
-			continue;
-		if ((qhp->attr.rcq == chp->cq.cqid) && !qp_quiesced(qhp)) {
-			quiesce_qp(qhp);
-			continue;
-		}
-		if ((qhp->attr.scq == chp->cq.cqid) && !qp_quiesced(qhp))
-			quiesce_qp(qhp);
-	}
-	return 0;
-}
-
-int iwch_resume_qps(struct iwch_cq *chp)
-{
-	int i;
-	struct iwch_qp *qhp;
-
-	for (i=0; i < T3_MAX_NUM_QP; i++) {
-		qhp = get_qhp(chp->rhp, i);
-		if (!qhp)
-			continue;
-		if ((qhp->attr.rcq == chp->cq.cqid) && qp_quiesced(qhp)) {
-			resume_qp(qhp);
-			continue;
-		}
-		if ((qhp->attr.scq == chp->cq.cqid) && qp_quiesced(qhp))
-			resume_qp(qhp);
-	}
-	return 0;
-}
diff -druNp linux-libre-2.6.37-gnu1/drivers/infiniband/hw/cxgb4/cm.c linux-libre-2.6.38-gnu1/drivers/infiniband/hw/cxgb4/cm.c
--- linux-libre-2.6.37-gnu1/drivers/infiniband/hw/cxgb4/cm.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/infiniband/hw/cxgb4/cm.c	2011-03-14 21:20:32.000000000 -0400
@@ -380,7 +380,7 @@ static void send_flowc(struct c4iw_ep *e
 					  16)) | FW_WR_FLOWID(ep->hwtid));
 
 	flowc->mnemval[0].mnemonic = FW_FLOWC_MNEM_PFNVFN;
-	flowc->mnemval[0].val = cpu_to_be32(0);
+	flowc->mnemval[0].val = cpu_to_be32(PCI_FUNC(ep->com.dev->rdev.lldi.pdev->devfn) << 8);
 	flowc->mnemval[1].mnemonic = FW_FLOWC_MNEM_CH;
 	flowc->mnemval[1].val = cpu_to_be32(ep->tx_chan);
 	flowc->mnemval[2].mnemonic = FW_FLOWC_MNEM_PORT;
diff -druNp linux-libre-2.6.37-gnu1/drivers/infiniband/hw/cxgb4/iw_cxgb4.h linux-libre-2.6.38-gnu1/drivers/infiniband/hw/cxgb4/iw_cxgb4.h
--- linux-libre-2.6.37-gnu1/drivers/infiniband/hw/cxgb4/iw_cxgb4.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/infiniband/hw/cxgb4/iw_cxgb4.h	2011-03-14 21:20:32.000000000 -0400
@@ -46,7 +46,6 @@
 #include <linux/timer.h>
 #include <linux/io.h>
 #include <linux/kfifo.h>
-#include <linux/mutex.h>
 
 #include <asm/byteorder.h>
 
@@ -760,7 +759,6 @@ int c4iw_flush_rq(struct t4_wq *wq, stru
 int c4iw_flush_sq(struct t4_wq *wq, struct t4_cq *cq, int count);
 int c4iw_ev_handler(struct c4iw_dev *rnicp, u32 qid);
 u16 c4iw_rqes_posted(struct c4iw_qp *qhp);
-int c4iw_post_zb_read(struct c4iw_qp *qhp);
 int c4iw_post_terminate(struct c4iw_qp *qhp, struct t4_cqe *err_cqe);
 u32 c4iw_get_cqid(struct c4iw_rdev *rdev, struct c4iw_dev_ucontext *uctx);
 void c4iw_put_cqid(struct c4iw_rdev *rdev, u32 qid,
diff -druNp linux-libre-2.6.37-gnu1/drivers/infiniband/hw/cxgb4/qp.c linux-libre-2.6.38-gnu1/drivers/infiniband/hw/cxgb4/qp.c
--- linux-libre-2.6.37-gnu1/drivers/infiniband/hw/cxgb4/qp.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/infiniband/hw/cxgb4/qp.c	2011-03-14 21:20:32.000000000 -0400
@@ -220,7 +220,7 @@ static int create_qp(struct c4iw_rdev *r
 		V_FW_RI_RES_WR_DCAEN(0) |
 		V_FW_RI_RES_WR_DCACPU(0) |
 		V_FW_RI_RES_WR_FBMIN(2) |
-		V_FW_RI_RES_WR_FBMAX(3) |
+		V_FW_RI_RES_WR_FBMAX(2) |
 		V_FW_RI_RES_WR_CIDXFTHRESHO(0) |
 		V_FW_RI_RES_WR_CIDXFTHRESH(0) |
 		V_FW_RI_RES_WR_EQSIZE(eqsize));
@@ -243,7 +243,7 @@ static int create_qp(struct c4iw_rdev *r
 		V_FW_RI_RES_WR_DCAEN(0) |
 		V_FW_RI_RES_WR_DCACPU(0) |
 		V_FW_RI_RES_WR_FBMIN(2) |
-		V_FW_RI_RES_WR_FBMAX(3) |
+		V_FW_RI_RES_WR_FBMAX(2) |
 		V_FW_RI_RES_WR_CIDXFTHRESHO(0) |
 		V_FW_RI_RES_WR_CIDXFTHRESH(0) |
 		V_FW_RI_RES_WR_EQSIZE(eqsize));
@@ -892,36 +892,6 @@ static inline void build_term_codes(stru
 	}
 }
 
-int c4iw_post_zb_read(struct c4iw_qp *qhp)
-{
-	union t4_wr *wqe;
-	struct sk_buff *skb;
-	u8 len16;
-
-	PDBG("%s enter\n", __func__);
-	skb = alloc_skb(40, GFP_KERNEL);
-	if (!skb) {
-		printk(KERN_ERR "%s cannot send zb_read!!\n", __func__);
-		return -ENOMEM;
-	}
-	set_wr_txq(skb, CPL_PRIORITY_DATA, qhp->ep->txq_idx);
-
-	wqe = (union t4_wr *)skb_put(skb, sizeof wqe->read);
-	memset(wqe, 0, sizeof wqe->read);
-	wqe->read.r2 = cpu_to_be64(0);
-	wqe->read.stag_sink = cpu_to_be32(1);
-	wqe->read.to_sink_hi = cpu_to_be32(0);
-	wqe->read.to_sink_lo = cpu_to_be32(1);
-	wqe->read.stag_src = cpu_to_be32(1);
-	wqe->read.plen = cpu_to_be32(0);
-	wqe->read.to_src_hi = cpu_to_be32(0);
-	wqe->read.to_src_lo = cpu_to_be32(1);
-	len16 = DIV_ROUND_UP(sizeof wqe->read, 16);
-	init_wr_hdr(wqe, 0, FW_RI_RDMA_READ_WR, FW_RI_COMPLETION_FLAG, len16);
-
-	return c4iw_ofld_send(&qhp->rhp->rdev, skb);
-}
-
 static void post_terminate(struct c4iw_qp *qhp, struct t4_cqe *err_cqe,
 			   gfp_t gfp)
 {
@@ -1029,7 +999,6 @@ static int rdma_fini(struct c4iw_dev *rh
 	wqe->cookie = (unsigned long) &ep->com.wr_wait;
 
 	wqe->u.fini.type = FW_RI_TYPE_FINI;
-	c4iw_init_wr_wait(&ep->com.wr_wait);
 	ret = c4iw_ofld_send(&rhp->rdev, skb);
 	if (ret)
 		goto out;
@@ -1125,7 +1094,6 @@ static int rdma_init(struct c4iw_dev *rh
 	if (qhp->attr.mpa_attr.initiator)
 		build_rtr_msg(qhp->attr.mpa_attr.p2p_type, &wqe->u.init);
 
-	c4iw_init_wr_wait(&qhp->ep->com.wr_wait);
 	ret = c4iw_ofld_send(&rhp->rdev, skb);
 	if (ret)
 		goto out;
diff -druNp linux-libre-2.6.37-gnu1/drivers/infiniband/hw/ehca/ipz_pt_fn.c linux-libre-2.6.38-gnu1/drivers/infiniband/hw/ehca/ipz_pt_fn.c
--- linux-libre-2.6.37-gnu1/drivers/infiniband/hw/ehca/ipz_pt_fn.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/infiniband/hw/ehca/ipz_pt_fn.c	2011-03-14 21:20:32.000000000 -0400
@@ -222,15 +222,14 @@ int ipz_queue_ctor(struct ehca_pd *pd, s
 	queue->small_page = NULL;
 
 	/* allocate queue page pointers */
-	queue->queue_pages = kmalloc(nr_of_pages * sizeof(void *), GFP_KERNEL);
+	queue->queue_pages = kzalloc(nr_of_pages * sizeof(void *), GFP_KERNEL);
 	if (!queue->queue_pages) {
-		queue->queue_pages = vmalloc(nr_of_pages * sizeof(void *));
+		queue->queue_pages = vzalloc(nr_of_pages * sizeof(void *));
 		if (!queue->queue_pages) {
 			ehca_gen_err("Couldn't allocate queue page list");
 			return 0;
 		}
 	}
-	memset(queue->queue_pages, 0, nr_of_pages * sizeof(void *));
 
 	/* allocate actual queue pages */
 	if (is_small) {
diff -druNp linux-libre-2.6.37-gnu1/drivers/infiniband/hw/ipath/ipath_driver.c linux-libre-2.6.38-gnu1/drivers/infiniband/hw/ipath/ipath_driver.c
--- linux-libre-2.6.37-gnu1/drivers/infiniband/hw/ipath/ipath_driver.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/infiniband/hw/ipath/ipath_driver.c	2011-03-14 21:20:32.000000000 -0400
@@ -199,12 +199,11 @@ static struct ipath_devdata *ipath_alloc
 		goto bail;
 	}
 
-	dd = vmalloc(sizeof(*dd));
+	dd = vzalloc(sizeof(*dd));
 	if (!dd) {
 		dd = ERR_PTR(-ENOMEM);
 		goto bail;
 	}
-	memset(dd, 0, sizeof(*dd));
 	dd->ipath_unit = -1;
 
 	spin_lock_irqsave(&ipath_devs_lock, flags);
@@ -530,9 +529,8 @@ static int __devinit ipath_init_one(stru
 	for (j = 0; j < 6; j++) {
 		if (!pdev->resource[j].start)
 			continue;
-		ipath_cdbg(VERBOSE, "BAR %d start %llx, end %llx, len %llx\n",
-			   j, (unsigned long long)pdev->resource[j].start,
-			   (unsigned long long)pdev->resource[j].end,
+		ipath_cdbg(VERBOSE, "BAR %d %pR, len %llx\n",
+			   j, &pdev->resource[j],
 			   (unsigned long long)pci_resource_len(pdev, j));
 	}
 
@@ -757,7 +755,7 @@ static void __devexit ipath_remove_one(s
 	 */
 	ipath_shutdown_device(dd);
 
-	flush_scheduled_work();
+	flush_workqueue(ib_wq);
 
 	if (dd->verbs_dev)
 		ipath_unregister_ib_device(dd->verbs_dev);
diff -druNp linux-libre-2.6.37-gnu1/drivers/infiniband/hw/ipath/ipath_file_ops.c linux-libre-2.6.38-gnu1/drivers/infiniband/hw/ipath/ipath_file_ops.c
--- linux-libre-2.6.37-gnu1/drivers/infiniband/hw/ipath/ipath_file_ops.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/infiniband/hw/ipath/ipath_file_ops.c	2011-03-14 21:20:32.000000000 -0400
@@ -1530,7 +1530,7 @@ static int init_subports(struct ipath_de
 	}
 
 	num_subports = uinfo->spu_subport_cnt;
-	pd->subport_uregbase = vmalloc(PAGE_SIZE * num_subports);
+	pd->subport_uregbase = vzalloc(PAGE_SIZE * num_subports);
 	if (!pd->subport_uregbase) {
 		ret = -ENOMEM;
 		goto bail;
@@ -1538,13 +1538,13 @@ static int init_subports(struct ipath_de
 	/* Note: pd->port_rcvhdrq_size isn't initialized yet. */
 	size = ALIGN(dd->ipath_rcvhdrcnt * dd->ipath_rcvhdrentsize *
 		     sizeof(u32), PAGE_SIZE) * num_subports;
-	pd->subport_rcvhdr_base = vmalloc(size);
+	pd->subport_rcvhdr_base = vzalloc(size);
 	if (!pd->subport_rcvhdr_base) {
 		ret = -ENOMEM;
 		goto bail_ureg;
 	}
 
-	pd->subport_rcvegrbuf = vmalloc(pd->port_rcvegrbuf_chunks *
+	pd->subport_rcvegrbuf = vzalloc(pd->port_rcvegrbuf_chunks *
 					pd->port_rcvegrbuf_size *
 					num_subports);
 	if (!pd->subport_rcvegrbuf) {
@@ -1556,11 +1556,6 @@ static int init_subports(struct ipath_de
 	pd->port_subport_id = uinfo->spu_subport_id;
 	pd->active_slaves = 1;
 	set_bit(IPATH_PORT_MASTER_UNINIT, &pd->port_flag);
-	memset(pd->subport_uregbase, 0, PAGE_SIZE * num_subports);
-	memset(pd->subport_rcvhdr_base, 0, size);
-	memset(pd->subport_rcvegrbuf, 0, pd->port_rcvegrbuf_chunks *
-				         pd->port_rcvegrbuf_size *
-				         num_subports);
 	goto bail;
 
 bail_rhdr:
diff -druNp linux-libre-2.6.37-gnu1/drivers/infiniband/hw/ipath/ipath_fs.c linux-libre-2.6.38-gnu1/drivers/infiniband/hw/ipath/ipath_fs.c
--- linux-libre-2.6.37-gnu1/drivers/infiniband/hw/ipath/ipath_fs.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/infiniband/hw/ipath/ipath_fs.c	2011-03-14 21:20:32.000000000 -0400
@@ -277,18 +277,14 @@ static int remove_file(struct dentry *pa
 		goto bail;
 	}
 
-	spin_lock(&dcache_lock);
 	spin_lock(&tmp->d_lock);
 	if (!(d_unhashed(tmp) && tmp->d_inode)) {
-		dget_locked(tmp);
+		dget_dlock(tmp);
 		__d_drop(tmp);
 		spin_unlock(&tmp->d_lock);
-		spin_unlock(&dcache_lock);
 		simple_unlink(parent->d_inode, tmp);
-	} else {
+	} else
 		spin_unlock(&tmp->d_lock);
-		spin_unlock(&dcache_lock);
-	}
 
 	ret = 0;
 bail:
diff -druNp linux-libre-2.6.37-gnu1/drivers/infiniband/hw/ipath/ipath_init_chip.c linux-libre-2.6.38-gnu1/drivers/infiniband/hw/ipath/ipath_init_chip.c
--- linux-libre-2.6.37-gnu1/drivers/infiniband/hw/ipath/ipath_init_chip.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/infiniband/hw/ipath/ipath_init_chip.c	2011-03-14 21:20:32.000000000 -0400
@@ -442,7 +442,7 @@ static void init_shadow_tids(struct ipat
 	struct page **pages;
 	dma_addr_t *addrs;
 
-	pages = vmalloc(dd->ipath_cfgports * dd->ipath_rcvtidcnt *
+	pages = vzalloc(dd->ipath_cfgports * dd->ipath_rcvtidcnt *
 			sizeof(struct page *));
 	if (!pages) {
 		ipath_dev_err(dd, "failed to allocate shadow page * "
@@ -461,9 +461,6 @@ static void init_shadow_tids(struct ipat
 		return;
 	}
 
-	memset(pages, 0, dd->ipath_cfgports * dd->ipath_rcvtidcnt *
-	       sizeof(struct page *));
-
 	dd->ipath_pageshadow = pages;
 	dd->ipath_physshadow = addrs;
 }
diff -druNp linux-libre-2.6.37-gnu1/drivers/infiniband/hw/ipath/ipath_user_pages.c linux-libre-2.6.38-gnu1/drivers/infiniband/hw/ipath/ipath_user_pages.c
--- linux-libre-2.6.37-gnu1/drivers/infiniband/hw/ipath/ipath_user_pages.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/infiniband/hw/ipath/ipath_user_pages.c	2011-03-14 21:20:32.000000000 -0400
@@ -220,7 +220,7 @@ void ipath_release_user_pages_on_close(s
 	work->mm = mm;
 	work->num_pages = num_pages;
 
-	schedule_work(&work->work);
+	queue_work(ib_wq, &work->work);
 	return;
 
 bail_mm:
diff -druNp linux-libre-2.6.37-gnu1/drivers/infiniband/hw/mlx4/cq.c linux-libre-2.6.38-gnu1/drivers/infiniband/hw/mlx4/cq.c
--- linux-libre-2.6.37-gnu1/drivers/infiniband/hw/mlx4/cq.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/infiniband/hw/mlx4/cq.c	2011-03-14 21:20:32.000000000 -0400
@@ -397,10 +397,14 @@ int mlx4_ib_resize_cq(struct ib_cq *ibcq
 		cq->resize_buf = NULL;
 		cq->resize_umem = NULL;
 	} else {
+		struct mlx4_ib_cq_buf tmp_buf;
+		int tmp_cqe = 0;
+
 		spin_lock_irq(&cq->lock);
 		if (cq->resize_buf) {
 			mlx4_ib_cq_resize_copy_cqes(cq);
-			mlx4_ib_free_cq_buf(dev, &cq->buf, cq->ibcq.cqe);
+			tmp_buf = cq->buf;
+			tmp_cqe = cq->ibcq.cqe;
 			cq->buf      = cq->resize_buf->buf;
 			cq->ibcq.cqe = cq->resize_buf->cqe;
 
@@ -408,6 +412,9 @@ int mlx4_ib_resize_cq(struct ib_cq *ibcq
 			cq->resize_buf = NULL;
 		}
 		spin_unlock_irq(&cq->lock);
+
+		if (tmp_cqe)
+			mlx4_ib_free_cq_buf(dev, &tmp_buf, tmp_cqe);
 	}
 
 	goto out;
diff -druNp linux-libre-2.6.37-gnu1/drivers/infiniband/hw/mlx4/mad.c linux-libre-2.6.38-gnu1/drivers/infiniband/hw/mlx4/mad.c
--- linux-libre-2.6.37-gnu1/drivers/infiniband/hw/mlx4/mad.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/infiniband/hw/mlx4/mad.c	2011-03-14 21:20:32.000000000 -0400
@@ -211,6 +211,8 @@ static void forward_trap(struct mlx4_ib_
 	if (agent) {
 		send_buf = ib_create_send_mad(agent, qpn, 0, 0, IB_MGMT_MAD_HDR,
 					      IB_MGMT_MAD_DATA, GFP_ATOMIC);
+		if (IS_ERR(send_buf))
+			return;
 		/*
 		 * We rely here on the fact that MLX QPs don't use the
 		 * address handle after the send is posted (this is
diff -druNp linux-libre-2.6.37-gnu1/drivers/infiniband/hw/mlx4/main.c linux-libre-2.6.38-gnu1/drivers/infiniband/hw/mlx4/main.c
--- linux-libre-2.6.37-gnu1/drivers/infiniband/hw/mlx4/main.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/infiniband/hw/mlx4/main.c	2011-03-14 21:20:32.000000000 -0400
@@ -623,8 +623,9 @@ static int mlx4_ib_mcg_attach(struct ib_
 	struct mlx4_ib_dev *mdev = to_mdev(ibqp->device);
 	struct mlx4_ib_qp *mqp = to_mqp(ibqp);
 
-	err = mlx4_multicast_attach(mdev->dev, &mqp->mqp, gid->raw, !!(mqp->flags &
-				    MLX4_IB_QP_BLOCK_MULTICAST_LOOPBACK));
+	err = mlx4_multicast_attach(mdev->dev, &mqp->mqp, gid->raw,
+				    !!(mqp->flags & MLX4_IB_QP_BLOCK_MULTICAST_LOOPBACK),
+				    MLX4_PROTOCOL_IB);
 	if (err)
 		return err;
 
@@ -635,7 +636,7 @@ static int mlx4_ib_mcg_attach(struct ib_
 	return 0;
 
 err_add:
-	mlx4_multicast_detach(mdev->dev, &mqp->mqp, gid->raw);
+	mlx4_multicast_detach(mdev->dev, &mqp->mqp, gid->raw, MLX4_PROTOCOL_IB);
 	return err;
 }
 
@@ -665,7 +666,7 @@ static int mlx4_ib_mcg_detach(struct ib_
 	struct mlx4_ib_gid_entry *ge;
 
 	err = mlx4_multicast_detach(mdev->dev,
-				    &mqp->mqp, gid->raw);
+				    &mqp->mqp, gid->raw, MLX4_PROTOCOL_IB);
 	if (err)
 		return err;
 
@@ -848,8 +849,8 @@ static int update_ipv6_gids(struct mlx4_
 		goto out;
 	}
 
-	read_lock(&dev_base_lock);
-	for_each_netdev(&init_net, tmp) {
+	rcu_read_lock();
+	for_each_netdev_rcu(&init_net, tmp) {
 		if (ndev && (tmp == ndev || rdma_vlan_dev_real_dev(tmp) == ndev)) {
 			gid.global.subnet_prefix = cpu_to_be64(0xfe80000000000000LL);
 			vid = rdma_vlan_dev_vlan_id(tmp);
@@ -884,7 +885,7 @@ static int update_ipv6_gids(struct mlx4_
 			}
 		}
 	}
-	read_unlock(&dev_base_lock);
+	rcu_read_unlock();
 
 	for (i = 0; i < 128; ++i)
 		if (!hits[i]) {
@@ -1005,7 +1006,8 @@ static void *mlx4_ib_add(struct mlx4_dev
 	if (mlx4_uar_alloc(dev, &ibdev->priv_uar))
 		goto err_pd;
 
-	ibdev->uar_map = ioremap(ibdev->priv_uar.pfn << PAGE_SHIFT, PAGE_SIZE);
+	ibdev->uar_map = ioremap((phys_addr_t) ibdev->priv_uar.pfn << PAGE_SHIFT,
+				 PAGE_SIZE);
 	if (!ibdev->uar_map)
 		goto err_uar;
 	MLX4_INIT_DOORBELL_LOCK(&ibdev->uar_lock);
diff -druNp linux-libre-2.6.37-gnu1/drivers/infiniband/hw/mthca/Kconfig linux-libre-2.6.38-gnu1/drivers/infiniband/hw/mthca/Kconfig
--- linux-libre-2.6.37-gnu1/drivers/infiniband/hw/mthca/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/infiniband/hw/mthca/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -7,7 +7,7 @@ config INFINIBAND_MTHCA
 	  ("Tavor") and the MT25208 PCI Express HCA ("Arbel").
 
 config INFINIBAND_MTHCA_DEBUG
-	bool "Verbose debugging output" if EMBEDDED
+	bool "Verbose debugging output" if EXPERT
 	depends on INFINIBAND_MTHCA
 	default y
 	---help---
diff -druNp linux-libre-2.6.37-gnu1/drivers/infiniband/hw/mthca/mthca_catas.c linux-libre-2.6.38-gnu1/drivers/infiniband/hw/mthca/mthca_catas.c
--- linux-libre-2.6.37-gnu1/drivers/infiniband/hw/mthca/mthca_catas.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/infiniband/hw/mthca/mthca_catas.c	2011-03-14 21:20:32.000000000 -0400
@@ -146,7 +146,7 @@ static void poll_catas(unsigned long dev
 
 void mthca_start_catas_poll(struct mthca_dev *dev)
 {
-	unsigned long addr;
+	phys_addr_t addr;
 
 	init_timer(&dev->catas_err.timer);
 	dev->catas_err.map  = NULL;
@@ -158,7 +158,8 @@ void mthca_start_catas_poll(struct mthca
 	dev->catas_err.map = ioremap(addr, dev->catas_err.size * 4);
 	if (!dev->catas_err.map) {
 		mthca_warn(dev, "couldn't map catastrophic error region "
-			   "at 0x%lx/0x%x\n", addr, dev->catas_err.size * 4);
+			   "at 0x%llx/0x%x\n", (unsigned long long) addr,
+			   dev->catas_err.size * 4);
 		return;
 	}
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/infiniband/hw/mthca/mthca_cmd.c linux-libre-2.6.38-gnu1/drivers/infiniband/hw/mthca/mthca_cmd.c
--- linux-libre-2.6.37-gnu1/drivers/infiniband/hw/mthca/mthca_cmd.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/infiniband/hw/mthca/mthca_cmd.c	2011-03-14 21:20:32.000000000 -0400
@@ -713,7 +713,7 @@ int mthca_RUN_FW(struct mthca_dev *dev,
 
 static void mthca_setup_cmd_doorbells(struct mthca_dev *dev, u64 base)
 {
-	unsigned long addr;
+	phys_addr_t addr;
 	u16 max_off = 0;
 	int i;
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/infiniband/hw/mthca/mthca_eq.c linux-libre-2.6.38-gnu1/drivers/infiniband/hw/mthca/mthca_eq.c
--- linux-libre-2.6.37-gnu1/drivers/infiniband/hw/mthca/mthca_eq.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/infiniband/hw/mthca/mthca_eq.c	2011-03-14 21:20:32.000000000 -0400
@@ -653,7 +653,7 @@ static int mthca_map_reg(struct mthca_de
 			 unsigned long offset, unsigned long size,
 			 void __iomem **map)
 {
-	unsigned long base = pci_resource_start(dev->pdev, 0);
+	phys_addr_t base = pci_resource_start(dev->pdev, 0);
 
 	*map = ioremap(base + offset, size);
 	if (!*map)
diff -druNp linux-libre-2.6.37-gnu1/drivers/infiniband/hw/mthca/mthca_mad.c linux-libre-2.6.38-gnu1/drivers/infiniband/hw/mthca/mthca_mad.c
--- linux-libre-2.6.37-gnu1/drivers/infiniband/hw/mthca/mthca_mad.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/infiniband/hw/mthca/mthca_mad.c	2011-03-14 21:20:32.000000000 -0400
@@ -171,6 +171,8 @@ static void forward_trap(struct mthca_de
 	if (agent) {
 		send_buf = ib_create_send_mad(agent, qpn, 0, 0, IB_MGMT_MAD_HDR,
 					      IB_MGMT_MAD_DATA, GFP_ATOMIC);
+		if (IS_ERR(send_buf))
+			return;
 		/*
 		 * We rely here on the fact that MLX QPs don't use the
 		 * address handle after the send is posted (this is
diff -druNp linux-libre-2.6.37-gnu1/drivers/infiniband/hw/mthca/mthca_main.c linux-libre-2.6.38-gnu1/drivers/infiniband/hw/mthca/mthca_main.c
--- linux-libre-2.6.37-gnu1/drivers/infiniband/hw/mthca/mthca_main.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/infiniband/hw/mthca/mthca_main.c	2011-03-14 21:20:32.000000000 -0400
@@ -790,7 +790,7 @@ static int mthca_setup_hca(struct mthca_
 		goto err_uar_table_free;
 	}
 
-	dev->kar = ioremap(dev->driver_uar.pfn << PAGE_SHIFT, PAGE_SIZE);
+	dev->kar = ioremap((phys_addr_t) dev->driver_uar.pfn << PAGE_SHIFT, PAGE_SIZE);
 	if (!dev->kar) {
 		mthca_err(dev, "Couldn't map kernel access region, "
 			  "aborting.\n");
diff -druNp linux-libre-2.6.37-gnu1/drivers/infiniband/hw/mthca/mthca_mr.c linux-libre-2.6.38-gnu1/drivers/infiniband/hw/mthca/mthca_mr.c
--- linux-libre-2.6.37-gnu1/drivers/infiniband/hw/mthca/mthca_mr.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/infiniband/hw/mthca/mthca_mr.c	2011-03-14 21:20:32.000000000 -0400
@@ -853,7 +853,7 @@ void mthca_arbel_fmr_unmap(struct mthca_
 
 int mthca_init_mr_table(struct mthca_dev *dev)
 {
-	unsigned long addr;
+	phys_addr_t addr;
 	int mpts, mtts, err, i;
 
 	err = mthca_alloc_init(&dev->mr_table.mpt_alloc,
diff -druNp linux-libre-2.6.37-gnu1/drivers/infiniband/hw/nes/nes.c linux-libre-2.6.38-gnu1/drivers/infiniband/hw/nes/nes.c
--- linux-libre-2.6.37-gnu1/drivers/infiniband/hw/nes/nes.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/infiniband/hw/nes/nes.c	2011-03-14 21:20:32.000000000 -0400
@@ -144,6 +144,7 @@ static int nes_inetaddr_event(struct not
 	struct nes_device *nesdev;
 	struct net_device *netdev;
 	struct nes_vnic *nesvnic;
+	unsigned int is_bonded;
 
 	nes_debug(NES_DBG_NETDEV, "nes_inetaddr_event: ip address %pI4, netmask %pI4.\n",
 		  &ifa->ifa_address, &ifa->ifa_mask);
@@ -152,7 +153,8 @@ static int nes_inetaddr_event(struct not
 				nesdev, nesdev->netdev[0]->name);
 		netdev = nesdev->netdev[0];
 		nesvnic = netdev_priv(netdev);
-		if (netdev == event_netdev) {
+		is_bonded = (netdev->master == event_netdev);
+		if ((netdev == event_netdev) || is_bonded) {
 			if (nesvnic->rdma_enabled == 0) {
 				nes_debug(NES_DBG_NETDEV, "Returning without processing event for %s since"
 						" RDMA is not enabled.\n",
@@ -169,7 +171,10 @@ static int nes_inetaddr_event(struct not
 					nes_manage_arp_cache(netdev, netdev->dev_addr,
 							ntohl(nesvnic->local_ipaddr), NES_ARP_DELETE);
 					nesvnic->local_ipaddr = 0;
-					return NOTIFY_OK;
+					if (is_bonded)
+						continue;
+					else
+						return NOTIFY_OK;
 					break;
 				case NETDEV_UP:
 					nes_debug(NES_DBG_NETDEV, "event:UP\n");
@@ -178,15 +183,24 @@ static int nes_inetaddr_event(struct not
 						nes_debug(NES_DBG_NETDEV, "Interface already has local_ipaddr\n");
 						return NOTIFY_OK;
 					}
+					/* fall through */
+				case NETDEV_CHANGEADDR:
 					/* Add the address to the IP table */
-					nesvnic->local_ipaddr = ifa->ifa_address;
+					if (netdev->master)
+						nesvnic->local_ipaddr =
+							((struct in_device *)netdev->master->ip_ptr)->ifa_list->ifa_address;
+					else
+						nesvnic->local_ipaddr = ifa->ifa_address;
 
 					nes_write_indexed(nesdev,
 							NES_IDX_DST_IP_ADDR+(0x10*PCI_FUNC(nesdev->pcidev->devfn)),
-							ntohl(ifa->ifa_address));
+							ntohl(nesvnic->local_ipaddr));
 					nes_manage_arp_cache(netdev, netdev->dev_addr,
 							ntohl(nesvnic->local_ipaddr), NES_ARP_ADD);
-					return NOTIFY_OK;
+					if (is_bonded)
+						continue;
+					else
+						return NOTIFY_OK;
 					break;
 				default:
 					break;
@@ -660,6 +674,8 @@ static int __devinit nes_probe(struct pc
 	}
 	nes_notifiers_registered++;
 
+	INIT_DELAYED_WORK(&nesdev->work, nes_recheck_link_status);
+
 	/* Initialize network devices */
 	if ((netdev = nes_netdev_init(nesdev, mmio_regs)) == NULL)
 		goto bail7;
@@ -742,6 +758,7 @@ static void __devexit nes_remove(struct
 	struct nes_device *nesdev = pci_get_drvdata(pcidev);
 	struct net_device *netdev;
 	int netdev_index = 0;
+	unsigned long flags;
 
 		if (nesdev->netdev_count) {
 			netdev = nesdev->netdev[netdev_index];
@@ -768,6 +785,14 @@ static void __devexit nes_remove(struct
 	free_irq(pcidev->irq, nesdev);
 	tasklet_kill(&nesdev->dpc_tasklet);
 
+	spin_lock_irqsave(&nesdev->nesadapter->phy_lock, flags);
+	if (nesdev->link_recheck) {
+		spin_unlock_irqrestore(&nesdev->nesadapter->phy_lock, flags);
+		cancel_delayed_work_sync(&nesdev->work);
+	} else {
+		spin_unlock_irqrestore(&nesdev->nesadapter->phy_lock, flags);
+	}
+
 	/* Deallocate the Adapter Structure */
 	nes_destroy_adapter(nesdev->nesadapter);
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/infiniband/hw/nes/nes_cm.c linux-libre-2.6.38-gnu1/drivers/infiniband/hw/nes/nes_cm.c
--- linux-libre-2.6.37-gnu1/drivers/infiniband/hw/nes/nes_cm.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/infiniband/hw/nes/nes_cm.c	2011-03-14 21:20:32.000000000 -0400
@@ -1107,6 +1107,7 @@ static int nes_addr_resolve_neigh(struct
 	struct flowi fl;
 	struct neighbour *neigh;
 	int rc = arpindex;
+	struct net_device *netdev;
 	struct nes_adapter *nesadapter = nesvnic->nesdev->nesadapter;
 
 	memset(&fl, 0, sizeof fl);
@@ -1117,7 +1118,12 @@ static int nes_addr_resolve_neigh(struct
 		return rc;
 	}
 
-	neigh = neigh_lookup(&arp_tbl, &rt->rt_gateway, nesvnic->netdev);
+	if (nesvnic->netdev->master)
+		netdev = nesvnic->netdev->master;
+	else
+		netdev = nesvnic->netdev;
+
+	neigh = neigh_lookup(&arp_tbl, &rt->rt_gateway, netdev);
 	if (neigh) {
 		if (neigh->nud_state & NUD_VALID) {
 			nes_debug(NES_DBG_CM, "Neighbor MAC address for 0x%08X"
diff -druNp linux-libre-2.6.37-gnu1/drivers/infiniband/hw/nes/nes.h linux-libre-2.6.38-gnu1/drivers/infiniband/hw/nes/nes.h
--- linux-libre-2.6.37-gnu1/drivers/infiniband/hw/nes/nes.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/infiniband/hw/nes/nes.h	2011-03-14 21:20:32.000000000 -0400
@@ -268,6 +268,9 @@ struct nes_device {
 	u8                     napi_isr_ran;
 	u8                     disable_rx_flow_control;
 	u8                     disable_tx_flow_control;
+
+	struct delayed_work    work;
+	u8                     link_recheck;
 };
 
 
@@ -507,6 +510,7 @@ void nes_nic_ce_handler(struct nes_devic
 void nes_iwarp_ce_handler(struct nes_device *, struct nes_hw_cq *);
 int nes_destroy_cqp(struct nes_device *);
 int nes_nic_cm_xmit(struct sk_buff *, struct net_device *);
+void nes_recheck_link_status(struct work_struct *work);
 
 /* nes_nic.c */
 struct net_device *nes_netdev_init(struct nes_device *, void __iomem *);
diff -druNp linux-libre-2.6.37-gnu1/drivers/infiniband/hw/nes/nes_hw.c linux-libre-2.6.38-gnu1/drivers/infiniband/hw/nes/nes_hw.c
--- linux-libre-2.6.37-gnu1/drivers/infiniband/hw/nes/nes_hw.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/infiniband/hw/nes/nes_hw.c	2011-03-14 21:20:32.000000000 -0400
@@ -2608,6 +2608,15 @@ static void nes_process_mac_intr(struct
 						netif_start_queue(nesvnic->netdev);
 					nesvnic->linkup = 1;
 					netif_carrier_on(nesvnic->netdev);
+
+					spin_lock(&nesvnic->port_ibevent_lock);
+					if (nesvnic->of_device_registered) {
+						if (nesdev->iw_status == 0) {
+							nesdev->iw_status = 1;
+							nes_port_ibevent(nesvnic);
+						}
+					}
+					spin_unlock(&nesvnic->port_ibevent_lock);
 				}
 			}
 		} else {
@@ -2633,9 +2642,25 @@ static void nes_process_mac_intr(struct
 						netif_stop_queue(nesvnic->netdev);
 					nesvnic->linkup = 0;
 					netif_carrier_off(nesvnic->netdev);
+
+					spin_lock(&nesvnic->port_ibevent_lock);
+					if (nesvnic->of_device_registered) {
+						if (nesdev->iw_status == 1) {
+							nesdev->iw_status = 0;
+							nes_port_ibevent(nesvnic);
+						}
+					}
+					spin_unlock(&nesvnic->port_ibevent_lock);
 				}
 			}
 		}
+		if (nesadapter->phy_type[mac_index] == NES_PHY_TYPE_SFP_D) {
+			if (nesdev->link_recheck)
+				cancel_delayed_work(&nesdev->work);
+			nesdev->link_recheck = 1;
+			schedule_delayed_work(&nesdev->work,
+					      NES_LINK_RECHECK_DELAY);
+		}
 	}
 
 	spin_unlock_irqrestore(&nesadapter->phy_lock, flags);
@@ -2643,6 +2668,84 @@ static void nes_process_mac_intr(struct
 	nesadapter->mac_sw_state[mac_number] = NES_MAC_SW_IDLE;
 }
 
+void nes_recheck_link_status(struct work_struct *work)
+{
+	unsigned long flags;
+	struct nes_device *nesdev = container_of(work, struct nes_device, work.work);
+	struct nes_adapter *nesadapter = nesdev->nesadapter;
+	struct nes_vnic *nesvnic;
+	u32 mac_index = nesdev->mac_index;
+	u16 phy_data;
+	u16 temp_phy_data;
+
+	spin_lock_irqsave(&nesadapter->phy_lock, flags);
+
+	/* check link status */
+	nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 1, 0x9003);
+	temp_phy_data = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL);
+
+	nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 3, 0x0021);
+	nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL);
+	nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 3, 0x0021);
+	phy_data = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL);
+
+	phy_data = (!temp_phy_data && (phy_data == 0x8000)) ? 0x4 : 0x0;
+
+	nes_debug(NES_DBG_PHY, "%s: Phy data = 0x%04X, link was %s.\n",
+		__func__, phy_data,
+		nesadapter->mac_link_down[mac_index] ? "DOWN" : "UP");
+
+	if (phy_data & 0x0004) {
+		nesadapter->mac_link_down[mac_index] = 0;
+		list_for_each_entry(nesvnic, &nesadapter->nesvnic_list[mac_index], list) {
+			if (nesvnic->linkup == 0) {
+				printk(PFX "The Link is now up for port %s, netdev %p.\n",
+						nesvnic->netdev->name, nesvnic->netdev);
+				if (netif_queue_stopped(nesvnic->netdev))
+					netif_start_queue(nesvnic->netdev);
+				nesvnic->linkup = 1;
+				netif_carrier_on(nesvnic->netdev);
+
+				spin_lock(&nesvnic->port_ibevent_lock);
+				if (nesvnic->of_device_registered) {
+					if (nesdev->iw_status == 0) {
+						nesdev->iw_status = 1;
+						nes_port_ibevent(nesvnic);
+					}
+				}
+				spin_unlock(&nesvnic->port_ibevent_lock);
+			}
+		}
+
+	} else {
+		nesadapter->mac_link_down[mac_index] = 1;
+		list_for_each_entry(nesvnic, &nesadapter->nesvnic_list[mac_index], list) {
+			if (nesvnic->linkup == 1) {
+				printk(PFX "The Link is now down for port %s, netdev %p.\n",
+						nesvnic->netdev->name, nesvnic->netdev);
+				if (!(netif_queue_stopped(nesvnic->netdev)))
+					netif_stop_queue(nesvnic->netdev);
+				nesvnic->linkup = 0;
+				netif_carrier_off(nesvnic->netdev);
+
+				spin_lock(&nesvnic->port_ibevent_lock);
+				if (nesvnic->of_device_registered) {
+					if (nesdev->iw_status == 1) {
+						nesdev->iw_status = 0;
+						nes_port_ibevent(nesvnic);
+					}
+				}
+				spin_unlock(&nesvnic->port_ibevent_lock);
+			}
+		}
+	}
+	if (nesdev->link_recheck++ < NES_LINK_RECHECK_MAX)
+		schedule_delayed_work(&nesdev->work, NES_LINK_RECHECK_DELAY);
+	else
+		nesdev->link_recheck = 0;
+
+	spin_unlock_irqrestore(&nesadapter->phy_lock, flags);
+}
 
 
 static void nes_nic_napi_ce_handler(struct nes_device *nesdev, struct nes_hw_nic_cq *cq)
diff -druNp linux-libre-2.6.37-gnu1/drivers/infiniband/hw/nes/nes_hw.h linux-libre-2.6.38-gnu1/drivers/infiniband/hw/nes/nes_hw.h
--- linux-libre-2.6.37-gnu1/drivers/infiniband/hw/nes/nes_hw.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/infiniband/hw/nes/nes_hw.h	2011-03-14 21:20:32.000000000 -0400
@@ -1193,6 +1193,8 @@ struct nes_listener {
 
 struct nes_ib_device;
 
+#define NES_EVENT_DELAY msecs_to_jiffies(100)
+
 struct nes_vnic {
 	struct nes_ib_device *nesibdev;
 	u64 sq_full;
@@ -1247,6 +1249,10 @@ struct nes_vnic {
 	u32 lro_max_aggr;
 	struct net_lro_mgr lro_mgr;
 	struct net_lro_desc lro_desc[NES_MAX_LRO_DESCRIPTORS];
+	struct timer_list event_timer;
+	enum ib_event_type delayed_event;
+	enum ib_event_type last_dispatched_event;
+	spinlock_t port_ibevent_lock;
 };
 
 struct nes_ib_device {
@@ -1348,6 +1354,10 @@ struct nes_terminate_hdr {
 #define BAD_FRAME_OFFSET	64
 #define CQE_MAJOR_DRV		0x8000
 
+/* Used for link status recheck after interrupt processing */
+#define NES_LINK_RECHECK_DELAY	msecs_to_jiffies(50)
+#define NES_LINK_RECHECK_MAX	60
+
 #define nes_vlan_rx vlan_hwaccel_receive_skb
 #define nes_netif_rx netif_receive_skb
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/infiniband/hw/nes/nes_nic.c linux-libre-2.6.38-gnu1/drivers/infiniband/hw/nes/nes_nic.c
--- linux-libre-2.6.37-gnu1/drivers/infiniband/hw/nes/nes_nic.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/infiniband/hw/nes/nes_nic.c	2011-03-14 21:20:32.000000000 -0400
@@ -144,6 +144,7 @@ static int nes_netdev_open(struct net_de
 	u32 nic_active_bit;
 	u32 nic_active;
 	struct list_head *list_pos, *list_temp;
+	unsigned long flags;
 
 	assert(nesdev != NULL);
 
@@ -233,18 +234,36 @@ static int nes_netdev_open(struct net_de
 		first_nesvnic = nesvnic;
 	}
 
-	if (nesvnic->of_device_registered) {
-		nesdev->iw_status = 1;
-		nesdev->nesadapter->send_term_ok = 1;
-		nes_port_ibevent(nesvnic);
-	}
-
 	if (first_nesvnic->linkup) {
 		/* Enable network packets */
 		nesvnic->linkup = 1;
 		netif_start_queue(netdev);
 		netif_carrier_on(netdev);
 	}
+
+	spin_lock_irqsave(&nesdev->nesadapter->phy_lock, flags);
+	if (nesdev->nesadapter->phy_type[nesdev->mac_index] == NES_PHY_TYPE_SFP_D) {
+		if (nesdev->link_recheck)
+			cancel_delayed_work(&nesdev->work);
+		nesdev->link_recheck = 1;
+		schedule_delayed_work(&nesdev->work, NES_LINK_RECHECK_DELAY);
+	}
+	spin_unlock_irqrestore(&nesdev->nesadapter->phy_lock, flags);
+
+	spin_lock_irqsave(&nesvnic->port_ibevent_lock, flags);
+	if (nesvnic->of_device_registered) {
+		nesdev->nesadapter->send_term_ok = 1;
+		if (nesvnic->linkup == 1) {
+			if (nesdev->iw_status == 0) {
+				nesdev->iw_status = 1;
+				nes_port_ibevent(nesvnic);
+			}
+		} else {
+			nesdev->iw_status = 0;
+		}
+	}
+	spin_unlock_irqrestore(&nesvnic->port_ibevent_lock, flags);
+
 	napi_enable(&nesvnic->napi);
 	nesvnic->netdev_open = 1;
 
@@ -263,6 +282,7 @@ static int nes_netdev_stop(struct net_de
 	u32 nic_active;
 	struct nes_vnic *first_nesvnic = NULL;
 	struct list_head *list_pos, *list_temp;
+	unsigned long flags;
 
 	nes_debug(NES_DBG_SHUTDOWN, "nesvnic=%p, nesdev=%p, netdev=%p %s\n",
 			nesvnic, nesdev, netdev, netdev->name);
@@ -315,12 +335,17 @@ static int nes_netdev_stop(struct net_de
 	nic_active &= nic_active_mask;
 	nes_write_indexed(nesdev, NES_IDX_NIC_BROADCAST_ON, nic_active);
 
-
+	spin_lock_irqsave(&nesvnic->port_ibevent_lock, flags);
 	if (nesvnic->of_device_registered) {
 		nesdev->nesadapter->send_term_ok = 0;
 		nesdev->iw_status = 0;
-		nes_port_ibevent(nesvnic);
+		if (nesvnic->linkup == 1)
+			nes_port_ibevent(nesvnic);
 	}
+	del_timer_sync(&nesvnic->event_timer);
+	nesvnic->event_timer.function = NULL;
+	spin_unlock_irqrestore(&nesvnic->port_ibevent_lock, flags);
+
 	nes_destroy_nic_qp(nesvnic);
 
 	nesvnic->netdev_open = 0;
@@ -908,8 +933,8 @@ static void nes_netdev_set_multicast_lis
 					nesvnic->nic_index &&
 					mc_index < max_pft_entries_avaiable) {
 						nes_debug(NES_DBG_NIC_RX,
-					"mc_index=%d skipping nic_index=%d,\
-					used for=%d \n", mc_index,
+					"mc_index=%d skipping nic_index=%d, "
+					"used for=%d \n", mc_index,
 					nesvnic->nic_index,
 					nesadapter->pft_mcast_map[mc_index]);
 				mc_index++;
@@ -1750,7 +1775,10 @@ struct net_device *nes_netdev_init(struc
 		nesvnic->rdma_enabled = 0;
 	}
 	nesvnic->nic_cq.cq_number = nesvnic->nic.qp_id;
+	init_timer(&nesvnic->event_timer);
+	nesvnic->event_timer.function = NULL;
 	spin_lock_init(&nesvnic->tx_lock);
+	spin_lock_init(&nesvnic->port_ibevent_lock);
 	nesdev->netdev[nesdev->netdev_count] = netdev;
 
 	nes_debug(NES_DBG_INIT, "Adding nesvnic (%p) to the adapters nesvnic_list for MAC%d.\n",
@@ -1763,8 +1791,11 @@ struct net_device *nes_netdev_init(struc
 	      (((PCI_FUNC(nesdev->pcidev->devfn) == 1) && (nesdev->mac_index == 2)) ||
 	       ((PCI_FUNC(nesdev->pcidev->devfn) == 2) && (nesdev->mac_index == 1)))))) {
 		u32 u32temp;
-		u32 link_mask;
-		u32 link_val;
+		u32 link_mask = 0;
+		u32 link_val = 0;
+		u16 temp_phy_data;
+		u16 phy_data = 0;
+		unsigned long flags;
 
 		u32temp = nes_read_indexed(nesdev, NES_IDX_PHY_PCS_CONTROL_STATUS0 +
 				(0x200 * (nesdev->mac_index & 1)));
@@ -1786,6 +1817,23 @@ struct net_device *nes_netdev_init(struc
 				link_val = 0x02020000;
 			}
 			break;
+		case NES_PHY_TYPE_SFP_D:
+			spin_lock_irqsave(&nesdev->nesadapter->phy_lock, flags);
+			nes_read_10G_phy_reg(nesdev,
+					     nesdev->nesadapter->phy_index[nesdev->mac_index],
+					     1, 0x9003);
+			temp_phy_data = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL);
+			nes_read_10G_phy_reg(nesdev,
+					     nesdev->nesadapter->phy_index[nesdev->mac_index],
+					     3, 0x0021);
+			nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL);
+			nes_read_10G_phy_reg(nesdev,
+					     nesdev->nesadapter->phy_index[nesdev->mac_index],
+					     3, 0x0021);
+			phy_data = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL);
+			spin_unlock_irqrestore(&nesdev->nesadapter->phy_lock, flags);
+			phy_data = (!temp_phy_data && (phy_data == 0x8000)) ? 0x4 : 0x0;
+			break;
 		default:
 			link_mask = 0x0f1f0000;
 			link_val = 0x0f0f0000;
@@ -1795,8 +1843,14 @@ struct net_device *nes_netdev_init(struc
 		u32temp = nes_read_indexed(nesdev,
 					   NES_IDX_PHY_PCS_CONTROL_STATUS0 +
 					   (0x200 * (nesdev->mac_index & 1)));
-		if ((u32temp & link_mask) == link_val)
-			nesvnic->linkup = 1;
+
+		if (phy_type == NES_PHY_TYPE_SFP_D) {
+			if (phy_data & 0x0004)
+				nesvnic->linkup = 1;
+		} else {
+			if ((u32temp & link_mask) == link_val)
+				nesvnic->linkup = 1;
+		}
 
 		/* clear the MAC interrupt status, assumes direct logical to physical mapping */
 		u32temp = nes_read_indexed(nesdev, NES_IDX_MAC_INT_STATUS + (0x200 * nesdev->mac_index));
diff -druNp linux-libre-2.6.37-gnu1/drivers/infiniband/hw/nes/nes_verbs.c linux-libre-2.6.38-gnu1/drivers/infiniband/hw/nes/nes_verbs.c
--- linux-libre-2.6.37-gnu1/drivers/infiniband/hw/nes/nes_verbs.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/infiniband/hw/nes/nes_verbs.c	2011-03-14 21:20:32.000000000 -0400
@@ -3936,6 +3936,30 @@ struct nes_ib_device *nes_init_ofa_devic
 	return nesibdev;
 }
 
+
+/**
+ * nes_handle_delayed_event
+ */
+static void nes_handle_delayed_event(unsigned long data)
+{
+	struct nes_vnic *nesvnic = (void *) data;
+
+	if (nesvnic->delayed_event != nesvnic->last_dispatched_event) {
+		struct ib_event event;
+
+		event.device = &nesvnic->nesibdev->ibdev;
+		if (!event.device)
+			goto stop_timer;
+		event.event = nesvnic->delayed_event;
+		event.element.port_num = nesvnic->logical_port + 1;
+		ib_dispatch_event(&event);
+	}
+
+stop_timer:
+	nesvnic->event_timer.function = NULL;
+}
+
+
 void  nes_port_ibevent(struct nes_vnic *nesvnic)
 {
 	struct nes_ib_device *nesibdev = nesvnic->nesibdev;
@@ -3944,7 +3968,18 @@ void  nes_port_ibevent(struct nes_vnic *
 	event.device = &nesibdev->ibdev;
 	event.element.port_num = nesvnic->logical_port + 1;
 	event.event = nesdev->iw_status ? IB_EVENT_PORT_ACTIVE : IB_EVENT_PORT_ERR;
-	ib_dispatch_event(&event);
+
+	if (!nesvnic->event_timer.function) {
+		ib_dispatch_event(&event);
+		nesvnic->last_dispatched_event = event.event;
+		nesvnic->event_timer.function = nes_handle_delayed_event;
+		nesvnic->event_timer.data = (unsigned long) nesvnic;
+		nesvnic->event_timer.expires = jiffies + NES_EVENT_DELAY;
+		add_timer(&nesvnic->event_timer);
+	} else {
+		mod_timer(&nesvnic->event_timer, jiffies + NES_EVENT_DELAY);
+	}
+	nesvnic->delayed_event = event.event;
 }
 
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/infiniband/hw/qib/qib_cq.c linux-libre-2.6.38-gnu1/drivers/infiniband/hw/qib/qib_cq.c
--- linux-libre-2.6.37-gnu1/drivers/infiniband/hw/qib/qib_cq.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/infiniband/hw/qib/qib_cq.c	2011-03-14 21:20:32.000000000 -0400
@@ -100,7 +100,8 @@ void qib_cq_enter(struct qib_cq *cq, str
 	wc->head = next;
 
 	if (cq->notify == IB_CQ_NEXT_COMP ||
-	    (cq->notify == IB_CQ_SOLICITED && solicited)) {
+	    (cq->notify == IB_CQ_SOLICITED &&
+	     (solicited || entry->status != IB_WC_SUCCESS))) {
 		cq->notify = IB_CQ_NONE;
 		cq->triggered++;
 		/*
diff -druNp linux-libre-2.6.37-gnu1/drivers/infiniband/hw/qib/qib_driver.c linux-libre-2.6.38-gnu1/drivers/infiniband/hw/qib/qib_driver.c
--- linux-libre-2.6.37-gnu1/drivers/infiniband/hw/qib/qib_driver.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/infiniband/hw/qib/qib_driver.c	2011-03-14 21:20:32.000000000 -0400
@@ -71,6 +71,11 @@ MODULE_DESCRIPTION("QLogic IB driver");
  */
 #define QIB_PIO_MAXIBHDR 128
 
+/*
+ * QIB_MAX_PKT_RCV is the max # if packets processed per receive interrupt.
+ */
+#define QIB_MAX_PKT_RECV 64
+
 struct qlogic_ib_stats qib_stats;
 
 const char *qib_get_unit_name(int unit)
@@ -284,14 +289,147 @@ static inline void *qib_get_egrbuf(const
  * Returns 1 if error was a CRC, else 0.
  * Needed for some chip's synthesized error counters.
  */
-static u32 qib_rcv_hdrerr(struct qib_pportdata *ppd, u32 ctxt,
-			  u32 eflags, u32 l, u32 etail, __le32 *rhf_addr,
-			  struct qib_message_header *hdr)
+static u32 qib_rcv_hdrerr(struct qib_ctxtdata *rcd, struct qib_pportdata *ppd,
+			  u32 ctxt, u32 eflags, u32 l, u32 etail,
+			  __le32 *rhf_addr, struct qib_message_header *rhdr)
 {
 	u32 ret = 0;
 
 	if (eflags & (QLOGIC_IB_RHF_H_ICRCERR | QLOGIC_IB_RHF_H_VCRCERR))
 		ret = 1;
+	else if (eflags == QLOGIC_IB_RHF_H_TIDERR) {
+		/* For TIDERR and RC QPs premptively schedule a NAK */
+		struct qib_ib_header *hdr = (struct qib_ib_header *) rhdr;
+		struct qib_other_headers *ohdr = NULL;
+		struct qib_ibport *ibp = &ppd->ibport_data;
+		struct qib_qp *qp = NULL;
+		u32 tlen = qib_hdrget_length_in_bytes(rhf_addr);
+		u16 lid  = be16_to_cpu(hdr->lrh[1]);
+		int lnh = be16_to_cpu(hdr->lrh[0]) & 3;
+		u32 qp_num;
+		u32 opcode;
+		u32 psn;
+		int diff;
+		unsigned long flags;
+
+		/* Sanity check packet */
+		if (tlen < 24)
+			goto drop;
+
+		if (lid < QIB_MULTICAST_LID_BASE) {
+			lid &= ~((1 << ppd->lmc) - 1);
+			if (unlikely(lid != ppd->lid))
+				goto drop;
+		}
+
+		/* Check for GRH */
+		if (lnh == QIB_LRH_BTH)
+			ohdr = &hdr->u.oth;
+		else if (lnh == QIB_LRH_GRH) {
+			u32 vtf;
+
+			ohdr = &hdr->u.l.oth;
+			if (hdr->u.l.grh.next_hdr != IB_GRH_NEXT_HDR)
+				goto drop;
+			vtf = be32_to_cpu(hdr->u.l.grh.version_tclass_flow);
+			if ((vtf >> IB_GRH_VERSION_SHIFT) != IB_GRH_VERSION)
+				goto drop;
+		} else
+			goto drop;
+
+		/* Get opcode and PSN from packet */
+		opcode = be32_to_cpu(ohdr->bth[0]);
+		opcode >>= 24;
+		psn = be32_to_cpu(ohdr->bth[2]);
+
+		/* Get the destination QP number. */
+		qp_num = be32_to_cpu(ohdr->bth[1]) & QIB_QPN_MASK;
+		if (qp_num != QIB_MULTICAST_QPN) {
+			int ruc_res;
+			qp = qib_lookup_qpn(ibp, qp_num);
+			if (!qp)
+				goto drop;
+
+			/*
+			 * Handle only RC QPs - for other QP types drop error
+			 * packet.
+			 */
+			spin_lock(&qp->r_lock);
+
+			/* Check for valid receive state. */
+			if (!(ib_qib_state_ops[qp->state] &
+			      QIB_PROCESS_RECV_OK)) {
+				ibp->n_pkt_drops++;
+				goto unlock;
+			}
+
+			switch (qp->ibqp.qp_type) {
+			case IB_QPT_RC:
+				spin_lock_irqsave(&qp->s_lock, flags);
+				ruc_res =
+					qib_ruc_check_hdr(
+						ibp, hdr,
+						lnh == QIB_LRH_GRH,
+						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 <
+				    IB_OPCODE_RC_RDMA_READ_RESPONSE_FIRST) {
+					diff = qib_cmp24(psn, qp->r_psn);
+					if (!qp->r_nak_state && diff >= 0) {
+						ibp->n_rc_seqnak++;
+						qp->r_nak_state =
+							IB_NAK_PSN_ERROR;
+						/* Use the expected PSN. */
+						qp->r_ack_psn = qp->r_psn;
+						/*
+						 * Wait to send the sequence
+						 * NAK until all packets
+						 * in the receive queue have
+						 * been processed.
+						 * Otherwise, we end up
+						 * propagating congestion.
+						 */
+						if (list_empty(&qp->rspwait)) {
+							qp->r_flags |=
+								QIB_R_RSP_NAK;
+							atomic_inc(
+								&qp->refcount);
+							list_add_tail(
+							 &qp->rspwait,
+							 &rcd->qp_wait_list);
+						}
+					} /* Out of sequence NAK */
+				} /* QP Request NAKs */
+				break;
+			case IB_QPT_SMI:
+			case IB_QPT_GSI:
+			case IB_QPT_UD:
+			case IB_QPT_UC:
+			default:
+				/* For now don't handle any other QP types */
+				break;
+			}
+
+unlock:
+			spin_unlock(&qp->r_lock);
+			/*
+			 * Notify qib_destroy_qp() if it is waiting
+			 * for us to finish.
+			 */
+			if (atomic_dec_and_test(&qp->refcount))
+				wake_up(&qp->wait);
+		} /* Unicast QP */
+	} /* Valid packet with TIDErr */
+
+drop:
 	return ret;
 }
 
@@ -335,7 +473,7 @@ u32 qib_kreceive(struct qib_ctxtdata *rc
 		smp_rmb();  /* prevent speculative reads of dma'ed hdrq */
 	}
 
-	for (last = 0, i = 1; !last && i <= 64; i += !last) {
+	for (last = 0, i = 1; !last; i += !last) {
 		hdr = dd->f_get_msgheader(dd, rhf_addr);
 		eflags = qib_hdrget_err_flags(rhf_addr);
 		etype = qib_hdrget_rcv_type(rhf_addr);
@@ -371,7 +509,7 @@ u32 qib_kreceive(struct qib_ctxtdata *rc
 		 * packets; only qibhdrerr should be set.
 		 */
 		if (unlikely(eflags))
-			crcs += qib_rcv_hdrerr(ppd, rcd->ctxt, eflags, l,
+			crcs += qib_rcv_hdrerr(rcd, ppd, rcd->ctxt, eflags, l,
 					       etail, rhf_addr, hdr);
 		else if (etype == RCVHQ_RCV_TYPE_NON_KD) {
 			qib_ib_rcv(rcd, hdr, ebuf, tlen);
@@ -384,6 +522,9 @@ move_along:
 		l += rsize;
 		if (l >= maxcnt)
 			l = 0;
+		if (i == QIB_MAX_PKT_RECV)
+			last = 1;
+
 		rhf_addr = (__le32 *) rcd->rcvhdrq + l + dd->rhf_offset;
 		if (dd->flags & QIB_NODMA_RTAIL) {
 			u32 seq = qib_hdrget_seq(rhf_addr);
@@ -402,7 +543,7 @@ move_along:
 		 */
 		lval = l;
 		if (!last && !(i & 0xf)) {
-			dd->f_update_usrhead(rcd, lval, updegr, etail);
+			dd->f_update_usrhead(rcd, lval, updegr, etail, i);
 			updegr = 0;
 		}
 	}
@@ -444,7 +585,7 @@ bail:
 	 * if no packets were processed.
 	 */
 	lval = (u64)rcd->head | dd->rhdrhead_intr_off;
-	dd->f_update_usrhead(rcd, lval, updegr, etail);
+	dd->f_update_usrhead(rcd, lval, updegr, etail, i);
 	return crcs;
 }
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/infiniband/hw/qib/qib_file_ops.c linux-libre-2.6.38-gnu1/drivers/infiniband/hw/qib/qib_file_ops.c
--- linux-libre-2.6.37-gnu1/drivers/infiniband/hw/qib/qib_file_ops.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/infiniband/hw/qib/qib_file_ops.c	2011-03-14 21:20:32.000000000 -0400
@@ -1379,17 +1379,17 @@ static int get_a_ctxt(struct file *fp, c
 		/* find device (with ACTIVE ports) with fewest ctxts in use */
 		for (ndev = 0; ndev < devmax; ndev++) {
 			struct qib_devdata *dd = qib_lookup(ndev);
-			unsigned cused = 0, cfree = 0;
+			unsigned cused = 0, cfree = 0, pusable = 0;
 			if (!dd)
 				continue;
 			if (port && port <= dd->num_pports &&
 			    usable(dd->pport + port - 1))
-				dusable = 1;
+				pusable = 1;
 			else
 				for (i = 0; i < dd->num_pports; i++)
 					if (usable(dd->pport + i))
-						dusable++;
-			if (!dusable)
+						pusable++;
+			if (!pusable)
 				continue;
 			for (ctxt = dd->first_user_ctxt; ctxt < dd->cfgctxts;
 			     ctxt++)
@@ -1397,7 +1397,7 @@ static int get_a_ctxt(struct file *fp, c
 					cused++;
 				else
 					cfree++;
-			if (cfree && cused < inuse) {
+			if (pusable && cfree && cused < inuse) {
 				udd = dd;
 				inuse = cused;
 			}
diff -druNp linux-libre-2.6.37-gnu1/drivers/infiniband/hw/qib/qib_fs.c linux-libre-2.6.38-gnu1/drivers/infiniband/hw/qib/qib_fs.c
--- linux-libre-2.6.37-gnu1/drivers/infiniband/hw/qib/qib_fs.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/infiniband/hw/qib/qib_fs.c	2011-03-14 21:20:32.000000000 -0400
@@ -453,17 +453,14 @@ static int remove_file(struct dentry *pa
 		goto bail;
 	}
 
-	spin_lock(&dcache_lock);
 	spin_lock(&tmp->d_lock);
 	if (!(d_unhashed(tmp) && tmp->d_inode)) {
-		dget_locked(tmp);
+		dget_dlock(tmp);
 		__d_drop(tmp);
 		spin_unlock(&tmp->d_lock);
-		spin_unlock(&dcache_lock);
 		simple_unlink(parent->d_inode, tmp);
 	} else {
 		spin_unlock(&tmp->d_lock);
-		spin_unlock(&dcache_lock);
 	}
 
 	ret = 0;
diff -druNp linux-libre-2.6.37-gnu1/drivers/infiniband/hw/qib/qib.h linux-libre-2.6.38-gnu1/drivers/infiniband/hw/qib/qib.h
--- linux-libre-2.6.37-gnu1/drivers/infiniband/hw/qib/qib.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/infiniband/hw/qib/qib.h	2011-03-14 21:20:32.000000000 -0400
@@ -766,7 +766,7 @@ struct qib_devdata {
 	void (*f_sdma_hw_start_up)(struct qib_pportdata *);
 	void (*f_sdma_init_early)(struct qib_pportdata *);
 	void (*f_set_cntr_sample)(struct qib_pportdata *, u32, u32);
-	void (*f_update_usrhead)(struct qib_ctxtdata *, u64, u32, u32);
+	void (*f_update_usrhead)(struct qib_ctxtdata *, u64, u32, u32, u32);
 	u32 (*f_hdrqempty)(struct qib_ctxtdata *);
 	u64 (*f_portcntr)(struct qib_pportdata *, u32);
 	u32 (*f_read_cntrs)(struct qib_devdata *, loff_t, char **,
diff -druNp linux-libre-2.6.37-gnu1/drivers/infiniband/hw/qib/qib_iba6120.c linux-libre-2.6.38-gnu1/drivers/infiniband/hw/qib/qib_iba6120.c
--- linux-libre-2.6.37-gnu1/drivers/infiniband/hw/qib/qib_iba6120.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/infiniband/hw/qib/qib_iba6120.c	2011-03-14 21:20:32.000000000 -0400
@@ -2074,7 +2074,7 @@ static void qib_6120_config_ctxts(struct
 }
 
 static void qib_update_6120_usrhead(struct qib_ctxtdata *rcd, u64 hd,
-				    u32 updegr, u32 egrhd)
+				    u32 updegr, u32 egrhd, u32 npkts)
 {
 	qib_write_ureg(rcd->dd, ur_rcvhdrhead, hd, rcd->ctxt);
 	if (updegr)
diff -druNp linux-libre-2.6.37-gnu1/drivers/infiniband/hw/qib/qib_iba7220.c linux-libre-2.6.38-gnu1/drivers/infiniband/hw/qib/qib_iba7220.c
--- linux-libre-2.6.37-gnu1/drivers/infiniband/hw/qib/qib_iba7220.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/infiniband/hw/qib/qib_iba7220.c	2011-03-14 21:20:32.000000000 -0400
@@ -1692,8 +1692,7 @@ static void qib_7220_quiet_serdes(struct
 	ppd->lflags &= ~QIBL_IB_AUTONEG_INPROG;
 	spin_unlock_irqrestore(&ppd->lflags_lock, flags);
 	wake_up(&ppd->cpspec->autoneg_wait);
-	cancel_delayed_work(&ppd->cpspec->autoneg_work);
-	flush_scheduled_work();
+	cancel_delayed_work_sync(&ppd->cpspec->autoneg_work);
 
 	shutdown_7220_relock_poll(ppd->dd);
 	val = qib_read_kreg64(ppd->dd, kr_xgxs_cfg);
@@ -2297,7 +2296,7 @@ static void qib_7220_config_ctxts(struct
 	nchipctxts = qib_read_kreg32(dd, kr_portcnt);
 	dd->cspec->numctxts = nchipctxts;
 	if (qib_n_krcv_queues > 1) {
-		dd->qpn_mask = 0x3f;
+		dd->qpn_mask = 0x3e;
 		dd->first_user_ctxt = qib_n_krcv_queues * dd->num_pports;
 		if (dd->first_user_ctxt > nchipctxts)
 			dd->first_user_ctxt = nchipctxts;
@@ -2703,7 +2702,7 @@ static int qib_7220_set_loopback(struct
 }
 
 static void qib_update_7220_usrhead(struct qib_ctxtdata *rcd, u64 hd,
-				    u32 updegr, u32 egrhd)
+				    u32 updegr, u32 egrhd, u32 npkts)
 {
 	qib_write_ureg(rcd->dd, ur_rcvhdrhead, hd, rcd->ctxt);
 	if (updegr)
@@ -3515,8 +3514,8 @@ static void try_7220_autoneg(struct qib_
 
 	toggle_7220_rclkrls(ppd->dd);
 	/* 2 msec is minimum length of a poll cycle */
-	schedule_delayed_work(&ppd->cpspec->autoneg_work,
-			      msecs_to_jiffies(2));
+	queue_delayed_work(ib_wq, &ppd->cpspec->autoneg_work,
+			   msecs_to_jiffies(2));
 }
 
 /*
diff -druNp linux-libre-2.6.37-gnu1/drivers/infiniband/hw/qib/qib_iba7322.c linux-libre-2.6.38-gnu1/drivers/infiniband/hw/qib/qib_iba7322.c
--- linux-libre-2.6.37-gnu1/drivers/infiniband/hw/qib/qib_iba7322.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/infiniband/hw/qib/qib_iba7322.c	2011-03-14 21:20:32.000000000 -0400
@@ -71,6 +71,9 @@ static void qib_7322_mini_pcs_reset(stru
 
 static u32 ahb_mod(struct qib_devdata *, int, int, int, u32, u32);
 static void ibsd_wr_allchans(struct qib_pportdata *, int, unsigned, unsigned);
+static void serdes_7322_los_enable(struct qib_pportdata *, int);
+static int serdes_7322_init_old(struct qib_pportdata *);
+static int serdes_7322_init_new(struct qib_pportdata *);
 
 #define BMASK(msb, lsb) (((1 << ((msb) + 1 - (lsb))) - 1) << (lsb))
 
@@ -111,6 +114,21 @@ static ushort qib_singleport;
 module_param_named(singleport, qib_singleport, ushort, S_IRUGO);
 MODULE_PARM_DESC(singleport, "Use only IB port 1; more per-port buffer space");
 
+/*
+ * Receive header queue sizes
+ */
+static unsigned qib_rcvhdrcnt;
+module_param_named(rcvhdrcnt, qib_rcvhdrcnt, uint, S_IRUGO);
+MODULE_PARM_DESC(rcvhdrcnt, "receive header count");
+
+static unsigned qib_rcvhdrsize;
+module_param_named(rcvhdrsize, qib_rcvhdrsize, uint, S_IRUGO);
+MODULE_PARM_DESC(rcvhdrsize, "receive header size in 32-bit words");
+
+static unsigned qib_rcvhdrentsize;
+module_param_named(rcvhdrentsize, qib_rcvhdrentsize, uint, S_IRUGO);
+MODULE_PARM_DESC(rcvhdrentsize, "receive header entry size in 32-bit words");
+
 #define MAX_ATTEN_LEN 64 /* plenty for any real system */
 /* for read back, default index is ~5m copper cable */
 static char txselect_list[MAX_ATTEN_LEN] = "10";
@@ -314,7 +332,7 @@ MODULE_PARM_DESC(txselect, \
 #define krp_serdesctrl KREG_IBPORT_IDX(IBSerdesCtrl)
 
 /*
- * Per-context kernel registers.  Acess only with qib_read_kreg_ctxt()
+ * Per-context kernel registers.  Access only with qib_read_kreg_ctxt()
  * or qib_write_kreg_ctxt()
  */
 #define krc_rcvhdraddr KREG_IDX(RcvHdrAddr0)
@@ -544,6 +562,7 @@ static void write_tx_serdes_param(struct
 
 #define TXDDS_TABLE_SZ 16 /* number of entries per speed in onchip table */
 #define TXDDS_EXTRA_SZ 13 /* number of extra tx settings entries */
+#define TXDDS_MFG_SZ 2    /* number of mfg tx settings entries */
 #define SERDES_CHANS 4 /* yes, it's obvious, but one less magic number */
 
 #define H1_FORCE_VAL 8
@@ -1677,6 +1696,8 @@ static void handle_serdes_issues(struct
 	    (ibcst & SYM_MASK(IBCStatusA_0, LinkSpeedQDR))) {
 		force_h1(ppd);
 		ppd->cpspec->qdr_reforce = 1;
+		if (!ppd->dd->cspec->r1)
+			serdes_7322_los_enable(ppd, 0);
 	} else if (ppd->cpspec->qdr_reforce &&
 		(ibcst & SYM_MASK(IBCStatusA_0, LinkSpeedQDR)) &&
 		 (ibclt == IB_7322_LT_STATE_CFGENH ||
@@ -1692,18 +1713,37 @@ static void handle_serdes_issues(struct
 	      ibclt <= IB_7322_LT_STATE_SLEEPQUIET)))
 		adj_tx_serdes(ppd);
 
-	if (!ppd->cpspec->qdr_dfe_on && ibclt != IB_7322_LT_STATE_LINKUP &&
-	    ibclt <= IB_7322_LT_STATE_SLEEPQUIET) {
-		ppd->cpspec->qdr_dfe_on = 1;
-		ppd->cpspec->qdr_dfe_time = 0;
-		/* On link down, reenable QDR adaptation */
-		qib_write_kreg_port(ppd, krp_static_adapt_dis(2),
-			ppd->dd->cspec->r1 ?
-				    QDR_STATIC_ADAPT_DOWN_R1 :
-				    QDR_STATIC_ADAPT_DOWN);
+	if (ibclt != IB_7322_LT_STATE_LINKUP) {
+		u8 ltstate = qib_7322_phys_portstate(ibcst);
+		u8 pibclt = (u8)SYM_FIELD(ppd->lastibcstat, IBCStatusA_0,
+					  LinkTrainingState);
+		if (!ppd->dd->cspec->r1 &&
+		    pibclt == IB_7322_LT_STATE_LINKUP &&
+		    ltstate != IB_PHYSPORTSTATE_LINK_ERR_RECOVER &&
+		    ltstate != IB_PHYSPORTSTATE_RECOVERY_RETRAIN &&
+		    ltstate != IB_PHYSPORTSTATE_RECOVERY_WAITRMT &&
+		    ltstate != IB_PHYSPORTSTATE_RECOVERY_IDLE)
+			/* If the link went down (but no into recovery,
+			 * turn LOS back on */
+			serdes_7322_los_enable(ppd, 1);
+		if (!ppd->cpspec->qdr_dfe_on &&
+		    ibclt <= IB_7322_LT_STATE_SLEEPQUIET) {
+			ppd->cpspec->qdr_dfe_on = 1;
+			ppd->cpspec->qdr_dfe_time = 0;
+			/* On link down, reenable QDR adaptation */
+			qib_write_kreg_port(ppd, krp_static_adapt_dis(2),
+					    ppd->dd->cspec->r1 ?
+					    QDR_STATIC_ADAPT_DOWN_R1 :
+					    QDR_STATIC_ADAPT_DOWN);
+			printk(KERN_INFO QIB_DRV_NAME
+				" IB%u:%u re-enabled QDR adaptation "
+				"ibclt %x\n", ppd->dd->unit, ppd->port, ibclt);
+		}
 	}
 }
 
+static int qib_7322_set_ib_cfg(struct qib_pportdata *, int, u32);
+
 /*
  * This is per-pport error handling.
  * will likely get it's own MSIx interrupt (one for each port,
@@ -2323,6 +2363,11 @@ static int qib_7322_bringup_serdes(struc
 	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,
@@ -2348,10 +2393,9 @@ static void qib_7322_mini_quiet_serdes(s
 	ppd->lflags &= ~QIBL_IB_AUTONEG_INPROG;
 	spin_unlock_irqrestore(&ppd->lflags_lock, flags);
 	wake_up(&ppd->cpspec->autoneg_wait);
-	cancel_delayed_work(&ppd->cpspec->autoneg_work);
+	cancel_delayed_work_sync(&ppd->cpspec->autoneg_work);
 	if (ppd->dd->cspec->r1)
-		cancel_delayed_work(&ppd->cpspec->ipg_work);
-	flush_scheduled_work();
+		cancel_delayed_work_sync(&ppd->cpspec->ipg_work);
 
 	ppd->cpspec->chase_end = 0;
 	if (ppd->cpspec->chase_timer.data) /* if initted */
@@ -2648,7 +2692,7 @@ static noinline void unknown_7322_gpio_i
 			if (!(pins & mask)) {
 				++handled;
 				qd->t_insert = get_jiffies_64();
-				schedule_work(&qd->work);
+				queue_work(ib_wq, &qd->work);
 			}
 		}
 	}
@@ -2785,7 +2829,6 @@ static irqreturn_t qib_7322intr(int irq,
 				ctxtrbits &= ~rmask;
 				if (dd->rcd[i]) {
 					qib_kreceive(dd->rcd[i], NULL, &npkts);
-					adjust_rcv_timeout(dd->rcd[i], npkts);
 				}
 			}
 			rmask <<= 1;
@@ -2835,7 +2878,6 @@ static irqreturn_t qib_7322pintr(int irq
 		       (1ULL << QIB_I_RCVURG_LSB)) << rcd->ctxt);
 
 	qib_kreceive(rcd, NULL, &npkts);
-	adjust_rcv_timeout(rcd, npkts);
 
 	return IRQ_HANDLED;
 }
@@ -3157,6 +3199,10 @@ static unsigned qib_7322_boardname(struc
 	case BOARD_QME7342:
 		n = "InfiniPath_QME7342";
 		break;
+	case 8:
+		n = "InfiniPath_QME7362";
+		dd->flags |= QIB_HAS_QSFP;
+		break;
 	case 15:
 		n = "InfiniPath_QLE7342_TEST";
 		dd->flags |= QIB_HAS_QSFP;
@@ -3475,11 +3521,6 @@ static void qib_7322_config_ctxts(struct
 	nchipctxts = qib_read_kreg32(dd, kr_contextcnt);
 	dd->cspec->numctxts = nchipctxts;
 	if (qib_n_krcv_queues > 1 && dd->num_pports) {
-		/*
-		 * Set the mask for which bits from the QPN are used
-		 * to select a context number.
-		 */
-		dd->qpn_mask = 0x3f;
 		dd->first_user_ctxt = NUM_IB_PORTS +
 			(qib_n_krcv_queues - 1) * dd->num_pports;
 		if (dd->first_user_ctxt > nchipctxts)
@@ -3530,8 +3571,11 @@ static void qib_7322_config_ctxts(struct
 
 	/* kr_rcvegrcnt changes based on the number of contexts enabled */
 	dd->cspec->rcvegrcnt = qib_read_kreg32(dd, kr_rcvegrcnt);
-	dd->rcvhdrcnt = max(dd->cspec->rcvegrcnt,
-				dd->num_pports > 1 ? 1024U : 2048U);
+	if (qib_rcvhdrcnt)
+		dd->rcvhdrcnt = max(dd->cspec->rcvegrcnt, qib_rcvhdrcnt);
+	else
+		dd->rcvhdrcnt = max(dd->cspec->rcvegrcnt,
+				    dd->num_pports > 1 ? 1024U : 2048U);
 }
 
 static int qib_7322_get_ib_cfg(struct qib_pportdata *ppd, int which)
@@ -4002,8 +4046,14 @@ static int qib_7322_set_ib_table(struct
 }
 
 static void qib_update_7322_usrhead(struct qib_ctxtdata *rcd, u64 hd,
-				    u32 updegr, u32 egrhd)
+				    u32 updegr, u32 egrhd, u32 npkts)
 {
+	/*
+	 * Need to write timeout register before updating rcvhdrhead to ensure
+	 * that the timer is enabled on reception of a packet.
+	 */
+	if (hd >> IBA7322_HDRHEAD_PKTINT_SHIFT)
+		adjust_rcv_timeout(rcd, npkts);
 	qib_write_ureg(rcd->dd, ur_rcvhdrhead, hd, rcd->ctxt);
 	qib_write_ureg(rcd->dd, ur_rcvhdrhead, hd, rcd->ctxt);
 	if (updegr)
@@ -4926,8 +4976,8 @@ static void try_7322_autoneg(struct qib_
 	set_7322_ibspeed_fast(ppd, QIB_IB_DDR);
 	qib_7322_mini_pcs_reset(ppd);
 	/* 2 msec is minimum length of a poll cycle */
-	schedule_delayed_work(&ppd->cpspec->autoneg_work,
-			      msecs_to_jiffies(2));
+	queue_delayed_work(ib_wq, &ppd->cpspec->autoneg_work,
+			   msecs_to_jiffies(2));
 }
 
 /*
@@ -5057,7 +5107,8 @@ static void try_7322_ipg(struct qib_ppor
 		ib_free_send_mad(send_buf);
 retry:
 	delay = 2 << ppd->cpspec->ipg_tries;
-	schedule_delayed_work(&ppd->cpspec->ipg_work, msecs_to_jiffies(delay));
+	queue_delayed_work(ib_wq, &ppd->cpspec->ipg_work,
+			   msecs_to_jiffies(delay));
 }
 
 /*
@@ -5522,7 +5573,7 @@ static void qsfp_7322_event(struct work_
 		u64 now = get_jiffies_64();
 		if (time_after64(now, pwrup))
 			break;
-		msleep(1);
+		msleep(20);
 	}
 	ret = qib_refresh_qsfp_cache(ppd, &qd->cache);
 	/*
@@ -5579,6 +5630,7 @@ static void set_no_qsfp_atten(struct qib
 	u32 pidx, unit, port, deflt, h1;
 	unsigned long val;
 	int any = 0, seth1;
+	int txdds_size;
 
 	str = txselect_list;
 
@@ -5587,6 +5639,10 @@ static void set_no_qsfp_atten(struct qib
 	for (pidx = 0; pidx < dd->num_pports; ++pidx)
 		dd->pport[pidx].cpspec->no_eep = deflt;
 
+	txdds_size = TXDDS_TABLE_SZ + TXDDS_EXTRA_SZ;
+	if (IS_QME(dd) || IS_QMH(dd))
+		txdds_size += TXDDS_MFG_SZ;
+
 	while (*nxt && nxt[1]) {
 		str = ++nxt;
 		unit = simple_strtoul(str, &nxt, 0);
@@ -5609,7 +5665,7 @@ static void set_no_qsfp_atten(struct qib
 				;
 			continue;
 		}
-		if (val >= TXDDS_TABLE_SZ + TXDDS_EXTRA_SZ)
+		if (val >= txdds_size)
 			continue;
 		seth1 = 0;
 		h1 = 0; /* gcc thinks it might be used uninitted */
@@ -5633,6 +5689,11 @@ static void set_no_qsfp_atten(struct qib
 				ppd->cpspec->h1_val = h1;
 			/* 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. */
+			if (IS_QMH(dd) || IS_QME(dd))
+				qib_set_ib_7322_lstate(ppd, 0,
+					    QLOGIC_IB_IBCC_LINKINITCMD_SLEEP);
 			any++;
 		}
 		if (*nxt == '\n')
@@ -5661,10 +5722,11 @@ static int setup_txselect(const char *st
 		return -ENOSPC;
 	}
 	val = simple_strtoul(str, &n, 0);
-	if (n == str || val >= (TXDDS_TABLE_SZ + TXDDS_EXTRA_SZ)) {
+	if (n == str || val >= (TXDDS_TABLE_SZ + TXDDS_EXTRA_SZ +
+				TXDDS_MFG_SZ)) {
 		printk(KERN_INFO QIB_DRV_NAME
 		       "txselect_values must start with a number < %d\n",
-			TXDDS_TABLE_SZ + TXDDS_EXTRA_SZ);
+			TXDDS_TABLE_SZ + TXDDS_EXTRA_SZ + TXDDS_MFG_SZ);
 		return -EINVAL;
 	}
 	strcpy(txselect_list, str);
@@ -5810,7 +5872,8 @@ static void write_7322_initregs(struct q
 		unsigned n, regno;
 		unsigned long flags;
 
-		if (!dd->qpn_mask || !dd->pport[pidx].link_speed_supported)
+		if (dd->n_krcv_queues < 2 ||
+			!dd->pport[pidx].link_speed_supported)
 			continue;
 
 		ppd = &dd->pport[pidx];
@@ -6097,8 +6160,10 @@ static int qib_init_7322_variables(struc
 		ppd++;
 	}
 
-	dd->rcvhdrentsize = QIB_RCVHDR_ENTSIZE;
-	dd->rcvhdrsize = QIB_DFLT_RCVHDRSIZE;
+	dd->rcvhdrentsize = qib_rcvhdrentsize ?
+		qib_rcvhdrentsize : QIB_RCVHDR_ENTSIZE;
+	dd->rcvhdrsize = qib_rcvhdrsize ?
+		qib_rcvhdrsize : QIB_DFLT_RCVHDRSIZE;
 	dd->rhf_offset = dd->rcvhdrentsize - sizeof(u64) / sizeof(u32);
 
 	/* we always allocate at least 2048 bytes for eager buffers */
@@ -6495,7 +6560,7 @@ static void qib_7322_txchk_change(struct
 		/* make sure we see an updated copy next time around */
 		sendctrl_7322_mod(dd->pport, QIB_SENDCTRL_AVAIL_BLIP);
 		sleeps++;
-		msleep(1);
+		msleep(20);
 	}
 
 	switch (which) {
@@ -6993,6 +7058,12 @@ static const struct txdds_ent txdds_extr
 	{  0, 1,  0, 12 },	/* QMH7342 backplane settings */
 };
 
+static const struct txdds_ent txdds_extra_mfg[TXDDS_MFG_SZ] = {
+	/* amp, pre, main, post */
+	{ 0, 0, 0, 0 },         /* QME7342 mfg settings */
+	{ 0, 0, 0, 6 },         /* QME7342 P2 mfg settings */
+};
+
 static const struct txdds_ent *get_atten_table(const struct txdds_ent *txdds,
 					       unsigned atten)
 {
@@ -7066,6 +7137,16 @@ static void find_best_ent(struct qib_ppo
 		*sdr_dds = &txdds_extra_sdr[idx];
 		*ddr_dds = &txdds_extra_ddr[idx];
 		*qdr_dds = &txdds_extra_qdr[idx];
+	} else if ((IS_QME(ppd->dd) || IS_QMH(ppd->dd)) &&
+		   ppd->cpspec->no_eep < (TXDDS_TABLE_SZ + TXDDS_EXTRA_SZ +
+					  TXDDS_MFG_SZ)) {
+		idx = ppd->cpspec->no_eep - (TXDDS_TABLE_SZ + TXDDS_EXTRA_SZ);
+		printk(KERN_INFO QIB_DRV_NAME
+			" IB%u:%u use idx %u into txdds_mfg\n",
+			ppd->dd->unit, ppd->port, idx);
+		*sdr_dds = &txdds_extra_mfg[idx];
+		*ddr_dds = &txdds_extra_mfg[idx];
+		*qdr_dds = &txdds_extra_mfg[idx];
 	} else {
 		/* this shouldn't happen, it's range checked */
 		*sdr_dds = txdds_sdr + qib_long_atten;
@@ -7210,9 +7291,30 @@ static void ibsd_wr_allchans(struct qib_
 	}
 }
 
+static void serdes_7322_los_enable(struct qib_pportdata *ppd, int enable)
+{
+	u64 data = qib_read_kreg_port(ppd, krp_serdesctrl);
+	printk(KERN_INFO QIB_DRV_NAME " IB%u:%u Turning LOS %s\n",
+		ppd->dd->unit, ppd->port, (enable ? "on" : "off"));
+	if (enable)
+		data |= SYM_MASK(IBSerdesCtrl_0, RXLOSEN);
+	else
+		data &= ~SYM_MASK(IBSerdesCtrl_0, RXLOSEN);
+	qib_write_kreg_port(ppd, krp_serdesctrl, data);
+}
+
 static int serdes_7322_init(struct qib_pportdata *ppd)
 {
-	u64 data;
+	int ret = 0;
+	if (ppd->dd->cspec->r1)
+		ret = serdes_7322_init_old(ppd);
+	else
+		ret = serdes_7322_init_new(ppd);
+	return ret;
+}
+
+static int serdes_7322_init_old(struct qib_pportdata *ppd)
+{
 	u32 le_val;
 
 	/*
@@ -7270,11 +7372,7 @@ static int serdes_7322_init(struct qib_p
 	ibsd_wr_allchans(ppd, 20, (2 << 10), BMASK(12, 10)); /* DDR */
 	ibsd_wr_allchans(ppd, 20, (4 << 13), BMASK(15, 13)); /* SDR */
 
-	data = qib_read_kreg_port(ppd, krp_serdesctrl);
-	/* Turn off IB latency mode */
-	data &= ~SYM_MASK(IBSerdesCtrl_0, IB_LAT_MODE);
-	qib_write_kreg_port(ppd, krp_serdesctrl, data |
-		SYM_MASK(IBSerdesCtrl_0, RXLOSEN));
+	serdes_7322_los_enable(ppd, 1);
 
 	/* rxbistena; set 0 to avoid effects of it switch later */
 	ibsd_wr_allchans(ppd, 9, 0 << 15, 1 << 15);
@@ -7313,6 +7411,205 @@ static int serdes_7322_init(struct qib_p
 
 	return 0;
 }
+
+static int serdes_7322_init_new(struct qib_pportdata *ppd)
+{
+	u64 tstart;
+	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);
+
+	/* ensure no tx overrides from earlier driver loads */
+	qib_write_kreg_port(ppd, krp_tx_deemph_override,
+		SYM_MASK(IBSD_TX_DEEMPHASIS_OVERRIDE_0,
+		reset_tx_deemphasis_override));
+
+	/* START OF LSI SUGGESTED SERDES BRINGUP */
+	/* Reset - Calibration Setup */
+	/*       Stop DFE adaptaion */
+	ibsd_wr_allchans(ppd, 1, 0, BMASK(9, 1));
+	/*       Disable LE1 */
+	ibsd_wr_allchans(ppd, 13, 0, BMASK(5, 5));
+	/*       Disable autoadapt for LE1 */
+	ibsd_wr_allchans(ppd, 1, 0, BMASK(15, 15));
+	/*       Disable LE2 */
+	ibsd_wr_allchans(ppd, 13, 0, BMASK(6, 6));
+	/*       Disable VGA */
+	ibsd_wr_allchans(ppd, 5, 0, BMASK(0, 0));
+	/*       Disable AFE Offset Cancel */
+	ibsd_wr_allchans(ppd, 12, 0, BMASK(12, 12));
+	/*       Disable Timing Loop */
+	ibsd_wr_allchans(ppd, 2, 0, BMASK(3, 3));
+	/*       Disable Frequency Loop */
+	ibsd_wr_allchans(ppd, 2, 0, BMASK(4, 4));
+	/*       Disable Baseline Wander Correction */
+	ibsd_wr_allchans(ppd, 13, 0, BMASK(13, 13));
+	/*       Disable RX Calibration */
+	ibsd_wr_allchans(ppd, 4, 0, BMASK(10, 10));
+	/*       Disable RX Offset Calibration */
+	ibsd_wr_allchans(ppd, 12, 0, BMASK(4, 4));
+	/*       Select BB CDR */
+	ibsd_wr_allchans(ppd, 2, (1 << 15), BMASK(15, 15));
+	/*       CDR Step Size */
+	ibsd_wr_allchans(ppd, 5, 0, BMASK(9, 8));
+	/*       Enable phase Calibration */
+	ibsd_wr_allchans(ppd, 12, (1 << 5), BMASK(5, 5));
+	/*       DFE Bandwidth [2:14-12] */
+	ibsd_wr_allchans(ppd, 2, (4 << 12), BMASK(14, 12));
+	/*       DFE Config (4 taps only) */
+	ibsd_wr_allchans(ppd, 16, 0, BMASK(1, 0));
+	/*       Gain Loop Bandwidth */
+	if (!ppd->dd->cspec->r1) {
+		ibsd_wr_allchans(ppd, 12, 1 << 12, BMASK(12, 12));
+		ibsd_wr_allchans(ppd, 12, 2 << 8, BMASK(11, 8));
+	} else {
+		ibsd_wr_allchans(ppd, 19, (3 << 11), BMASK(13, 11));
+	}
+	/*       Baseline Wander Correction Gain [13:4-0] (leave as default) */
+	/*       Baseline Wander Correction Gain [3:7-5] (leave as default) */
+	/*       Data Rate Select [5:7-6] (leave as default) */
+	/*       RX Parralel Word Width [3:10-8] (leave as default) */
+
+	/* RX REST */
+	/*       Single- or Multi-channel reset */
+	/*       RX Analog reset */
+	/*       RX Digital reset */
+	ibsd_wr_allchans(ppd, 0, 0, BMASK(15, 13));
+	msleep(20);
+	/*       RX Analog reset */
+	ibsd_wr_allchans(ppd, 0, (1 << 14), BMASK(14, 14));
+	msleep(20);
+	/*       RX Digital reset */
+	ibsd_wr_allchans(ppd, 0, (1 << 13), BMASK(13, 13));
+	msleep(20);
+
+	/* setup LoS params; these are subsystem, so chan == 5 */
+	/* LoS filter threshold_count on, ch 0-3, set to 8 */
+	ahb_mod(ppd->dd, IBSD(ppd->hw_pidx), 5, 5, 8 << 11, BMASK(14, 11));
+	ahb_mod(ppd->dd, IBSD(ppd->hw_pidx), 5, 7, 8 << 4, BMASK(7, 4));
+	ahb_mod(ppd->dd, IBSD(ppd->hw_pidx), 5, 8, 8 << 11, BMASK(14, 11));
+	ahb_mod(ppd->dd, IBSD(ppd->hw_pidx), 5, 10, 8 << 4, BMASK(7, 4));
+
+	/* LoS filter threshold_count off, ch 0-3, set to 4 */
+	ahb_mod(ppd->dd, IBSD(ppd->hw_pidx), 5, 6, 4 << 0, BMASK(3, 0));
+	ahb_mod(ppd->dd, IBSD(ppd->hw_pidx), 5, 7, 4 << 8, BMASK(11, 8));
+	ahb_mod(ppd->dd, IBSD(ppd->hw_pidx), 5, 9, 4 << 0, BMASK(3, 0));
+	ahb_mod(ppd->dd, IBSD(ppd->hw_pidx), 5, 10, 4 << 8, BMASK(11, 8));
+
+	/* LoS filter select enabled */
+	ahb_mod(ppd->dd, IBSD(ppd->hw_pidx), 5, 9, 1 << 15, 1 << 15);
+
+	/* LoS target data:  SDR=4, DDR=2, QDR=1 */
+	ibsd_wr_allchans(ppd, 14, (1 << 3), BMASK(5, 3)); /* QDR */
+	ibsd_wr_allchans(ppd, 20, (2 << 10), BMASK(12, 10)); /* DDR */
+	ibsd_wr_allchans(ppd, 20, (4 << 13), BMASK(15, 13)); /* SDR */
+
+	/* Turn on LOS on initial SERDES init */
+	serdes_7322_los_enable(ppd, 1);
+	/* FLoop LOS gate: PPM filter  enabled */
+	ibsd_wr_allchans(ppd, 38, 0 << 10, 1 << 10);
+
+	/* RX LATCH CALIBRATION */
+	/*       Enable Eyefinder Phase Calibration latch */
+	ibsd_wr_allchans(ppd, 15, 1, BMASK(0, 0));
+	/*       Enable RX Offset Calibration latch */
+	ibsd_wr_allchans(ppd, 12, (1 << 4), BMASK(4, 4));
+	msleep(20);
+	/*       Start Calibration */
+	ibsd_wr_allchans(ppd, 4, (1 << 10), BMASK(10, 10));
+	tstart = get_jiffies_64();
+	while (chan_done &&
+	       !time_after64(tstart, tstart + msecs_to_jiffies(500))) {
+		msleep(20);
+		for (chan = 0; chan < SERDES_CHANS; ++chan) {
+			rxcaldone = ahb_mod(ppd->dd, IBSD(ppd->hw_pidx),
+					    (chan + (chan >> 1)),
+					    25, 0, 0);
+			if ((~rxcaldone & (u32)BMASK(9, 9)) == 0 &&
+			    (~chan_done & (1 << chan)) == 0)
+				chan_done &= ~(1 << chan);
+		}
+	}
+	if (chan_done) {
+		printk(KERN_INFO QIB_DRV_NAME
+			 " Serdes %d calibration not done after .5 sec: 0x%x\n",
+			 IBSD(ppd->hw_pidx), chan_done);
+	} else {
+		for (chan = 0; chan < SERDES_CHANS; ++chan) {
+			rxcaldone = ahb_mod(ppd->dd, IBSD(ppd->hw_pidx),
+					    (chan + (chan >> 1)),
+					    25, 0, 0);
+			if ((~rxcaldone & (u32)BMASK(10, 10)) == 0)
+				printk(KERN_INFO QIB_DRV_NAME
+					 " Serdes %d chan %d calibration "
+					 "failed\n", IBSD(ppd->hw_pidx), chan);
+		}
+	}
+
+	/*       Turn off Calibration */
+	ibsd_wr_allchans(ppd, 4, 0, BMASK(10, 10));
+	msleep(20);
+
+	/* BRING RX UP */
+	/*       Set LE2 value (May be overridden in qsfp_7322_event) */
+	le_val = IS_QME(ppd->dd) ? LE2_QME : LE2_DEFAULT;
+	ibsd_wr_allchans(ppd, 13, (le_val << 7), BMASK(9, 7));
+	/*       Set LE2 Loop bandwidth */
+	ibsd_wr_allchans(ppd, 3, (7 << 5), BMASK(7, 5));
+	/*       Enable LE2 */
+	ibsd_wr_allchans(ppd, 13, (1 << 6), BMASK(6, 6));
+	msleep(20);
+	/*       Enable H0 only */
+	ibsd_wr_allchans(ppd, 1, 1, BMASK(9, 1));
+	/* gain hi stop 32 (22) (6:1) lo stop 7 (10:7) target 22 (13) (15:11) */
+	le_val = (ppd->dd->cspec->r1 || IS_QME(ppd->dd)) ? 0xb6c0 : 0x6bac;
+	ibsd_wr_allchans(ppd, 21, le_val, 0xfffe);
+	/*       Enable VGA */
+	ibsd_wr_allchans(ppd, 5, 0, BMASK(0, 0));
+	msleep(20);
+	/*       Set Frequency Loop Bandwidth */
+	ibsd_wr_allchans(ppd, 2, (7 << 5), BMASK(8, 5));
+	/*       Enable Frequency Loop */
+	ibsd_wr_allchans(ppd, 2, (1 << 4), BMASK(4, 4));
+	/*       Set Timing Loop Bandwidth */
+	ibsd_wr_allchans(ppd, 2, 0, BMASK(11, 9));
+	/*       Enable Timing Loop */
+	ibsd_wr_allchans(ppd, 2, (1 << 3), BMASK(3, 3));
+	msleep(50);
+	/*       Enable DFE
+	 *       Set receive adaptation mode.  SDR and DDR adaptation are
+	 *       always on, and QDR is initially enabled; later disabled.
+	 */
+	qib_write_kreg_port(ppd, krp_static_adapt_dis(0), 0ULL);
+	qib_write_kreg_port(ppd, krp_static_adapt_dis(1), 0ULL);
+	qib_write_kreg_port(ppd, krp_static_adapt_dis(2),
+			    ppd->dd->cspec->r1 ?
+			    QDR_STATIC_ADAPT_DOWN_R1 : QDR_STATIC_ADAPT_DOWN);
+	ppd->cpspec->qdr_dfe_on = 1;
+	/*       Disable LE1  */
+	ibsd_wr_allchans(ppd, 13, (0 << 5), (1 << 5));
+	/*       Disable auto adapt for LE1 */
+	ibsd_wr_allchans(ppd, 1, (0 << 15), BMASK(15, 15));
+	msleep(20);
+	/*       Enable AFE Offset Cancel */
+	ibsd_wr_allchans(ppd, 12, (1 << 12), BMASK(12, 12));
+	/*       Enable Baseline Wander Correction */
+	ibsd_wr_allchans(ppd, 12, (1 << 13), BMASK(13, 13));
+	/* Termination: rxtermctrl_r2d addr 11 bits [12:11] = 1 */
+	ibsd_wr_allchans(ppd, 11, (1 << 11), BMASK(12, 11));
+	/* VGA output common mode */
+	ibsd_wr_allchans(ppd, 12, (3 << 2), BMASK(3, 2));
+
+	return 0;
+}
 
 /* start adjust QMH serdes parameters */
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/infiniband/hw/qib/qib_init.c linux-libre-2.6.38-gnu1/drivers/infiniband/hw/qib/qib_init.c
--- linux-libre-2.6.37-gnu1/drivers/infiniband/hw/qib/qib_init.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/infiniband/hw/qib/qib_init.c	2011-03-14 21:20:32.000000000 -0400
@@ -80,7 +80,6 @@ unsigned qib_wc_pat = 1; /* default (1)
 module_param_named(wc_pat, qib_wc_pat, uint, S_IRUGO);
 MODULE_PARM_DESC(wc_pat, "enable write-combining via PAT mechanism");
 
-struct workqueue_struct *qib_wq;
 struct workqueue_struct *qib_cq_wq;
 
 static void verify_interrupt(unsigned long);
@@ -92,9 +91,11 @@ unsigned long *qib_cpulist;
 /* set number of contexts we'll actually use */
 void qib_set_ctxtcnt(struct qib_devdata *dd)
 {
-	if (!qib_cfgctxts)
+	if (!qib_cfgctxts) {
 		dd->cfgctxts = dd->first_user_ctxt + num_online_cpus();
-	else if (qib_cfgctxts < dd->num_pports)
+		if (dd->cfgctxts > dd->ctxtcnt)
+			dd->cfgctxts = dd->ctxtcnt;
+	} else if (qib_cfgctxts < dd->num_pports)
 		dd->cfgctxts = dd->ctxtcnt;
 	else if (qib_cfgctxts <= dd->ctxtcnt)
 		dd->cfgctxts = qib_cfgctxts;
@@ -268,23 +269,20 @@ static void init_shadow_tids(struct qib_
 	struct page **pages;
 	dma_addr_t *addrs;
 
-	pages = vmalloc(dd->cfgctxts * dd->rcvtidcnt * sizeof(struct page *));
+	pages = vzalloc(dd->cfgctxts * dd->rcvtidcnt * sizeof(struct page *));
 	if (!pages) {
 		qib_dev_err(dd, "failed to allocate shadow page * "
 			    "array, no expected sends!\n");
 		goto bail;
 	}
 
-	addrs = vmalloc(dd->cfgctxts * dd->rcvtidcnt * sizeof(dma_addr_t));
+	addrs = vzalloc(dd->cfgctxts * dd->rcvtidcnt * sizeof(dma_addr_t));
 	if (!addrs) {
 		qib_dev_err(dd, "failed to allocate shadow dma handle "
 			    "array, no expected sends!\n");
 		goto bail_free;
 	}
 
-	memset(pages, 0, dd->cfgctxts * dd->rcvtidcnt * sizeof(struct page *));
-	memset(addrs, 0, dd->cfgctxts * dd->rcvtidcnt * sizeof(dma_addr_t));
-
 	dd->pageshadow = pages;
 	dd->physshadow = addrs;
 	return;
@@ -1045,24 +1043,10 @@ static int __init qlogic_ib_init(void)
 	if (ret)
 		goto bail;
 
-	/*
-	 * We create our own workqueue mainly because we want to be
-	 * able to flush it when devices are being removed.  We can't
-	 * use schedule_work()/flush_scheduled_work() because both
-	 * unregister_netdev() and linkwatch_event take the rtnl lock,
-	 * so flush_scheduled_work() can deadlock during device
-	 * removal.
-	 */
-	qib_wq = create_workqueue("qib");
-	if (!qib_wq) {
-		ret = -ENOMEM;
-		goto bail_dev;
-	}
-
 	qib_cq_wq = create_singlethread_workqueue("qib_cq");
 	if (!qib_cq_wq) {
 		ret = -ENOMEM;
-		goto bail_wq;
+		goto bail_dev;
 	}
 
 	/*
@@ -1092,8 +1076,6 @@ bail_unit:
 	idr_destroy(&qib_unit_table);
 bail_cq_wq:
 	destroy_workqueue(qib_cq_wq);
-bail_wq:
-	destroy_workqueue(qib_wq);
 bail_dev:
 	qib_dev_cleanup();
 bail:
@@ -1117,7 +1099,6 @@ static void __exit qlogic_ib_cleanup(voi
 
 	pci_unregister_driver(&qib_driver);
 
-	destroy_workqueue(qib_wq);
 	destroy_workqueue(qib_cq_wq);
 
 	qib_cpulist_count = 0;
@@ -1290,7 +1271,7 @@ static int __devinit qib_init_one(struct
 
 	if (qib_mini_init || initfail || ret) {
 		qib_stop_timers(dd);
-		flush_scheduled_work();
+		flush_workqueue(ib_wq);
 		for (pidx = 0; pidx < dd->num_pports; ++pidx)
 			dd->f_quiet_serdes(dd->pport + pidx);
 		if (qib_mini_init)
@@ -1339,8 +1320,8 @@ static void __devexit qib_remove_one(str
 
 	qib_stop_timers(dd);
 
-	/* wait until all of our (qsfp) schedule_work() calls complete */
-	flush_scheduled_work();
+	/* wait until all of our (qsfp) queue_work() calls complete */
+	flush_workqueue(ib_wq);
 
 	ret = qibfs_remove(dd);
 	if (ret)
diff -druNp linux-libre-2.6.37-gnu1/drivers/infiniband/hw/qib/qib_intr.c linux-libre-2.6.38-gnu1/drivers/infiniband/hw/qib/qib_intr.c
--- linux-libre-2.6.37-gnu1/drivers/infiniband/hw/qib/qib_intr.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/infiniband/hw/qib/qib_intr.c	2011-03-14 21:20:32.000000000 -0400
@@ -131,7 +131,8 @@ void qib_handle_e_ibstatuschanged(struct
 			/* start a 75msec timer to clear symbol errors */
 			mod_timer(&ppd->symerr_clear_timer,
 				  msecs_to_jiffies(75));
-		} else if (ltstate == IB_PHYSPORTSTATE_LINKUP) {
+		} else if (ltstate == IB_PHYSPORTSTATE_LINKUP &&
+			   !(ppd->lflags & QIBL_LINKACTIVE)) {
 			/* active, but not active defered */
 			qib_hol_up(ppd); /* useful only for 6120 now */
 			*ppd->statusp |=
diff -druNp linux-libre-2.6.37-gnu1/drivers/infiniband/hw/qib/qib_keys.c linux-libre-2.6.38-gnu1/drivers/infiniband/hw/qib/qib_keys.c
--- linux-libre-2.6.37-gnu1/drivers/infiniband/hw/qib/qib_keys.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/infiniband/hw/qib/qib_keys.c	2011-03-14 21:20:32.000000000 -0400
@@ -136,7 +136,6 @@ int qib_lkey_ok(struct qib_lkey_table *r
 	struct qib_mregion *mr;
 	unsigned n, m;
 	size_t off;
-	int ret = 0;
 	unsigned long flags;
 
 	/*
@@ -152,6 +151,8 @@ int qib_lkey_ok(struct qib_lkey_table *r
 		if (!dev->dma_mr)
 			goto bail;
 		atomic_inc(&dev->dma_mr->refcount);
+		spin_unlock_irqrestore(&rkt->lock, flags);
+
 		isge->mr = dev->dma_mr;
 		isge->vaddr = (void *) sge->addr;
 		isge->length = sge->length;
@@ -170,19 +171,34 @@ int qib_lkey_ok(struct qib_lkey_table *r
 		     off + sge->length > mr->length ||
 		     (mr->access_flags & acc) != acc))
 		goto bail;
+	atomic_inc(&mr->refcount);
+	spin_unlock_irqrestore(&rkt->lock, flags);
 
 	off += mr->offset;
-	m = 0;
-	n = 0;
-	while (off >= mr->map[m]->segs[n].length) {
-		off -= mr->map[m]->segs[n].length;
-		n++;
-		if (n >= QIB_SEGSZ) {
-			m++;
-			n = 0;
+	if (mr->page_shift) {
+		/*
+		page sizes are uniform power of 2 so no loop is necessary
+		entries_spanned_by_off is the number of times the loop below
+		would have executed.
+		*/
+		size_t entries_spanned_by_off;
+
+		entries_spanned_by_off = off >> mr->page_shift;
+		off -= (entries_spanned_by_off << mr->page_shift);
+		m = entries_spanned_by_off/QIB_SEGSZ;
+		n = entries_spanned_by_off%QIB_SEGSZ;
+	} else {
+		m = 0;
+		n = 0;
+		while (off >= mr->map[m]->segs[n].length) {
+			off -= mr->map[m]->segs[n].length;
+			n++;
+			if (n >= QIB_SEGSZ) {
+				m++;
+				n = 0;
+			}
 		}
 	}
-	atomic_inc(&mr->refcount);
 	isge->mr = mr;
 	isge->vaddr = mr->map[m]->segs[n].vaddr + off;
 	isge->length = mr->map[m]->segs[n].length - off;
@@ -190,10 +206,10 @@ int qib_lkey_ok(struct qib_lkey_table *r
 	isge->m = m;
 	isge->n = n;
 ok:
-	ret = 1;
+	return 1;
 bail:
 	spin_unlock_irqrestore(&rkt->lock, flags);
-	return ret;
+	return 0;
 }
 
 /**
@@ -214,7 +230,6 @@ int qib_rkey_ok(struct qib_qp *qp, struc
 	struct qib_mregion *mr;
 	unsigned n, m;
 	size_t off;
-	int ret = 0;
 	unsigned long flags;
 
 	/*
@@ -231,6 +246,8 @@ int qib_rkey_ok(struct qib_qp *qp, struc
 		if (!dev->dma_mr)
 			goto bail;
 		atomic_inc(&dev->dma_mr->refcount);
+		spin_unlock_irqrestore(&rkt->lock, flags);
+
 		sge->mr = dev->dma_mr;
 		sge->vaddr = (void *) vaddr;
 		sge->length = len;
@@ -248,19 +265,34 @@ int qib_rkey_ok(struct qib_qp *qp, struc
 	if (unlikely(vaddr < mr->iova || off + len > mr->length ||
 		     (mr->access_flags & acc) == 0))
 		goto bail;
+	atomic_inc(&mr->refcount);
+	spin_unlock_irqrestore(&rkt->lock, flags);
 
 	off += mr->offset;
-	m = 0;
-	n = 0;
-	while (off >= mr->map[m]->segs[n].length) {
-		off -= mr->map[m]->segs[n].length;
-		n++;
-		if (n >= QIB_SEGSZ) {
-			m++;
-			n = 0;
+	if (mr->page_shift) {
+		/*
+		page sizes are uniform power of 2 so no loop is necessary
+		entries_spanned_by_off is the number of times the loop below
+		would have executed.
+		*/
+		size_t entries_spanned_by_off;
+
+		entries_spanned_by_off = off >> mr->page_shift;
+		off -= (entries_spanned_by_off << mr->page_shift);
+		m = entries_spanned_by_off/QIB_SEGSZ;
+		n = entries_spanned_by_off%QIB_SEGSZ;
+	} else {
+		m = 0;
+		n = 0;
+		while (off >= mr->map[m]->segs[n].length) {
+			off -= mr->map[m]->segs[n].length;
+			n++;
+			if (n >= QIB_SEGSZ) {
+				m++;
+				n = 0;
+			}
 		}
 	}
-	atomic_inc(&mr->refcount);
 	sge->mr = mr;
 	sge->vaddr = mr->map[m]->segs[n].vaddr + off;
 	sge->length = mr->map[m]->segs[n].length - off;
@@ -268,10 +300,10 @@ int qib_rkey_ok(struct qib_qp *qp, struc
 	sge->m = m;
 	sge->n = n;
 ok:
-	ret = 1;
+	return 1;
 bail:
 	spin_unlock_irqrestore(&rkt->lock, flags);
-	return ret;
+	return 0;
 }
 
 /*
diff -druNp linux-libre-2.6.37-gnu1/drivers/infiniband/hw/qib/qib_mad.c linux-libre-2.6.38-gnu1/drivers/infiniband/hw/qib/qib_mad.c
--- linux-libre-2.6.37-gnu1/drivers/infiniband/hw/qib/qib_mad.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/infiniband/hw/qib/qib_mad.c	2011-03-14 21:20:32.000000000 -0400
@@ -668,8 +668,8 @@ static int subn_set_portinfo(struct ib_s
 	lid = be16_to_cpu(pip->lid);
 	/* Must be a valid unicast LID address. */
 	if (lid == 0 || lid >= QIB_MULTICAST_LID_BASE)
-		goto err;
-	if (ppd->lid != lid || ppd->lmc != (pip->mkeyprot_resv_lmc & 7)) {
+		smp->status |= IB_SMP_INVALID_FIELD;
+	else if (ppd->lid != lid || ppd->lmc != (pip->mkeyprot_resv_lmc & 7)) {
 		if (ppd->lid != lid)
 			qib_set_uevent_bits(ppd, _QIB_EVENT_LID_CHANGE_BIT);
 		if (ppd->lmc != (pip->mkeyprot_resv_lmc & 7))
@@ -683,8 +683,8 @@ static int subn_set_portinfo(struct ib_s
 	msl = pip->neighbormtu_mastersmsl & 0xF;
 	/* Must be a valid unicast LID address. */
 	if (smlid == 0 || smlid >= QIB_MULTICAST_LID_BASE)
-		goto err;
-	if (smlid != ibp->sm_lid || msl != ibp->sm_sl) {
+		smp->status |= IB_SMP_INVALID_FIELD;
+	else if (smlid != ibp->sm_lid || msl != ibp->sm_sl) {
 		spin_lock_irqsave(&ibp->lock, flags);
 		if (ibp->sm_ah) {
 			if (smlid != ibp->sm_lid)
@@ -707,8 +707,9 @@ static int subn_set_portinfo(struct ib_s
 		if (lwe == 0xFF)
 			lwe = ppd->link_width_supported;
 		else if (lwe >= 16 || (lwe & ~ppd->link_width_supported))
-			goto err;
-		set_link_width_enabled(ppd, lwe);
+			smp->status |= IB_SMP_INVALID_FIELD;
+		else if (lwe != ppd->link_width_enabled)
+			set_link_width_enabled(ppd, lwe);
 	}
 
 	lse = pip->linkspeedactive_enabled & 0xF;
@@ -721,8 +722,9 @@ static int subn_set_portinfo(struct ib_s
 		if (lse == 15)
 			lse = ppd->link_speed_supported;
 		else if (lse >= 8 || (lse & ~ppd->link_speed_supported))
-			goto err;
-		set_link_speed_enabled(ppd, lse);
+			smp->status |= IB_SMP_INVALID_FIELD;
+		else if (lse != ppd->link_speed_enabled)
+			set_link_speed_enabled(ppd, lse);
 	}
 
 	/* Set link down default state. */
@@ -738,7 +740,7 @@ static int subn_set_portinfo(struct ib_s
 					IB_LINKINITCMD_POLL);
 		break;
 	default:
-		goto err;
+		smp->status |= IB_SMP_INVALID_FIELD;
 	}
 
 	ibp->mkeyprot = pip->mkeyprot_resv_lmc >> 6;
@@ -748,15 +750,17 @@ static int subn_set_portinfo(struct ib_s
 
 	mtu = ib_mtu_enum_to_int((pip->neighbormtu_mastersmsl >> 4) & 0xF);
 	if (mtu == -1)
-		goto err;
-	qib_set_mtu(ppd, mtu);
+		smp->status |= IB_SMP_INVALID_FIELD;
+	else
+		qib_set_mtu(ppd, mtu);
 
 	/* Set operational VLs */
 	vls = (pip->operationalvl_pei_peo_fpi_fpo >> 4) & 0xF;
 	if (vls) {
 		if (vls > ppd->vls_supported)
-			goto err;
-		(void) dd->f_set_ib_cfg(ppd, QIB_IB_CFG_OP_VLS, vls);
+			smp->status |= IB_SMP_INVALID_FIELD;
+		else
+			(void) dd->f_set_ib_cfg(ppd, QIB_IB_CFG_OP_VLS, vls);
 	}
 
 	if (pip->mkey_violations == 0)
@@ -770,10 +774,10 @@ static int subn_set_portinfo(struct ib_s
 
 	ore = pip->localphyerrors_overrunerrors;
 	if (set_phyerrthreshold(ppd, (ore >> 4) & 0xF))
-		goto err;
+		smp->status |= IB_SMP_INVALID_FIELD;
 
 	if (set_overrunthreshold(ppd, (ore & 0xF)))
-		goto err;
+		smp->status |= IB_SMP_INVALID_FIELD;
 
 	ibp->subnet_timeout = pip->clientrereg_resv_subnetto & 0x1F;
 
@@ -792,7 +796,7 @@ static int subn_set_portinfo(struct ib_s
 	state = pip->linkspeed_portstate & 0xF;
 	lstate = (pip->portphysstate_linkdown >> 4) & 0xF;
 	if (lstate && !(state == IB_PORT_DOWN || state == IB_PORT_NOP))
-		goto err;
+		smp->status |= IB_SMP_INVALID_FIELD;
 
 	/*
 	 * Only state changes of DOWN, ARM, and ACTIVE are valid
@@ -812,8 +816,10 @@ static int subn_set_portinfo(struct ib_s
 			lstate = QIB_IB_LINKDOWN;
 		else if (lstate == 3)
 			lstate = QIB_IB_LINKDOWN_DISABLE;
-		else
-			goto err;
+		else {
+			smp->status |= IB_SMP_INVALID_FIELD;
+			break;
+		}
 		spin_lock_irqsave(&ppd->lflags_lock, flags);
 		ppd->lflags &= ~QIBL_LINKV;
 		spin_unlock_irqrestore(&ppd->lflags_lock, flags);
@@ -835,8 +841,7 @@ static int subn_set_portinfo(struct ib_s
 		qib_set_linkstate(ppd, QIB_IB_LINKACTIVE);
 		break;
 	default:
-		/* XXX We have already partially updated our state! */
-		goto err;
+		smp->status |= IB_SMP_INVALID_FIELD;
 	}
 
 	ret = subn_get_portinfo(smp, ibdev, port);
diff -druNp linux-libre-2.6.37-gnu1/drivers/infiniband/hw/qib/qib_mr.c linux-libre-2.6.38-gnu1/drivers/infiniband/hw/qib/qib_mr.c
--- linux-libre-2.6.37-gnu1/drivers/infiniband/hw/qib/qib_mr.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/infiniband/hw/qib/qib_mr.c	2011-03-14 21:20:32.000000000 -0400
@@ -39,7 +39,6 @@
 /* Fast memory region */
 struct qib_fmr {
 	struct ib_fmr ibfmr;
-	u8 page_shift;
 	struct qib_mregion mr;        /* must be last */
 };
 
@@ -107,6 +106,7 @@ static struct qib_mr *alloc_mr(int count
 			goto bail;
 	}
 	mr->mr.mapsz = m;
+	mr->mr.page_shift = 0;
 	mr->mr.max_segs = count;
 
 	/*
@@ -231,6 +231,8 @@ struct ib_mr *qib_reg_user_mr(struct ib_
 	mr->mr.access_flags = mr_access_flags;
 	mr->umem = umem;
 
+	if (is_power_of_2(umem->page_size))
+		mr->mr.page_shift = ilog2(umem->page_size);
 	m = 0;
 	n = 0;
 	list_for_each_entry(chunk, &umem->chunk_list, list) {
@@ -390,7 +392,7 @@ struct ib_fmr *qib_alloc_fmr(struct ib_p
 	fmr->mr.offset = 0;
 	fmr->mr.access_flags = mr_access_flags;
 	fmr->mr.max_segs = fmr_attr->max_pages;
-	fmr->page_shift = fmr_attr->page_shift;
+	fmr->mr.page_shift = fmr_attr->page_shift;
 
 	atomic_set(&fmr->mr.refcount, 0);
 	ret = &fmr->ibfmr;
@@ -437,7 +439,7 @@ int qib_map_phys_fmr(struct ib_fmr *ibfm
 	spin_lock_irqsave(&rkt->lock, flags);
 	fmr->mr.user_base = iova;
 	fmr->mr.iova = iova;
-	ps = 1 << fmr->page_shift;
+	ps = 1 << fmr->mr.page_shift;
 	fmr->mr.length = list_len * ps;
 	m = 0;
 	n = 0;
diff -druNp linux-libre-2.6.37-gnu1/drivers/infiniband/hw/qib/qib_qp.c linux-libre-2.6.38-gnu1/drivers/infiniband/hw/qib/qib_qp.c
--- linux-libre-2.6.37-gnu1/drivers/infiniband/hw/qib/qib_qp.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/infiniband/hw/qib/qib_qp.c	2011-03-14 21:20:32.000000000 -0400
@@ -48,13 +48,12 @@ static inline unsigned mk_qpn(struct qib
 
 static inline unsigned find_next_offset(struct qib_qpn_table *qpt,
 					struct qpn_map *map, unsigned off,
-					unsigned r)
+					unsigned n)
 {
 	if (qpt->mask) {
 		off++;
-		if ((off & qpt->mask) >> 1 != r)
-			off = ((off & qpt->mask) ?
-				(off | qpt->mask) + 1 : off) | (r << 1);
+		if (((off & qpt->mask) >> 1) >= n)
+			off = (off | qpt->mask) + 2;
 	} else
 		off = find_next_zero_bit(map->page, BITS_PER_PAGE, off);
 	return off;
@@ -123,7 +122,6 @@ static int alloc_qpn(struct qib_devdata
 	u32 i, offset, max_scan, qpn;
 	struct qpn_map *map;
 	u32 ret;
-	int r;
 
 	if (type == IB_QPT_SMI || type == IB_QPT_GSI) {
 		unsigned n;
@@ -139,15 +137,11 @@ static int alloc_qpn(struct qib_devdata
 		goto bail;
 	}
 
-	r = smp_processor_id();
-	if (r >= dd->n_krcv_queues)
-		r %= dd->n_krcv_queues;
-	qpn = qpt->last + 1;
+	qpn = qpt->last + 2;
 	if (qpn >= QPN_MAX)
 		qpn = 2;
-	if (qpt->mask && ((qpn & qpt->mask) >> 1) != r)
-		qpn = ((qpn & qpt->mask) ? (qpn | qpt->mask) + 1 : qpn) |
-			(r << 1);
+	if (qpt->mask && ((qpn & qpt->mask) >> 1) >= dd->n_krcv_queues)
+		qpn = (qpn | qpt->mask) + 2;
 	offset = qpn & BITS_PER_PAGE_MASK;
 	map = &qpt->map[qpn / BITS_PER_PAGE];
 	max_scan = qpt->nmaps - !offset;
@@ -163,7 +157,8 @@ static int alloc_qpn(struct qib_devdata
 				ret = qpn;
 				goto bail;
 			}
-			offset = find_next_offset(qpt, map, offset, r);
+			offset = find_next_offset(qpt, map, offset,
+				dd->n_krcv_queues);
 			qpn = mk_qpn(qpt, map, offset);
 			/*
 			 * This test differs from alloc_pidmap().
@@ -183,13 +178,13 @@ static int alloc_qpn(struct qib_devdata
 			if (qpt->nmaps == QPNMAP_ENTRIES)
 				break;
 			map = &qpt->map[qpt->nmaps++];
-			offset = qpt->mask ? (r << 1) : 0;
+			offset = 0;
 		} else if (map < &qpt->map[qpt->nmaps]) {
 			++map;
-			offset = qpt->mask ? (r << 1) : 0;
+			offset = 0;
 		} else {
 			map = &qpt->map[0];
-			offset = qpt->mask ? (r << 1) : 2;
+			offset = 2;
 		}
 		qpn = mk_qpn(qpt, map, offset);
 	}
@@ -468,6 +463,10 @@ int qib_error_qp(struct qib_qp *qp, enum
 		qp->s_flags &= ~(QIB_S_TIMER | QIB_S_WAIT_RNR);
 		del_timer(&qp->s_timer);
 	}
+
+	if (qp->s_flags & QIB_S_ANY_WAIT_SEND)
+		qp->s_flags &= ~QIB_S_ANY_WAIT_SEND;
+
 	spin_lock(&dev->pending_lock);
 	if (!list_empty(&qp->iowait) && !(qp->s_flags & QIB_S_BUSY)) {
 		qp->s_flags &= ~QIB_S_ANY_WAIT_IO;
@@ -1061,7 +1060,6 @@ struct ib_qp *qib_create_qp(struct ib_pd
 		}
 		qp->ibqp.qp_num = err;
 		qp->port_num = init_attr->port_num;
-		qp->processor_id = smp_processor_id();
 		qib_reset_qp(qp, init_attr->qp_type);
 		break;
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/infiniband/hw/qib/qib_qsfp.c linux-libre-2.6.38-gnu1/drivers/infiniband/hw/qib/qib_qsfp.c
--- linux-libre-2.6.37-gnu1/drivers/infiniband/hw/qib/qib_qsfp.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/infiniband/hw/qib/qib_qsfp.c	2011-03-14 21:20:32.000000000 -0400
@@ -485,7 +485,7 @@ void qib_qsfp_init(struct qib_qsfp_data
 		goto bail;
 	/* We see a module, but it may be unwise to look yet. Just schedule */
 	qd->t_insert = get_jiffies_64();
-	schedule_work(&qd->work);
+	queue_work(ib_wq, &qd->work);
 bail:
 	return;
 }
@@ -493,10 +493,9 @@ bail:
 void qib_qsfp_deinit(struct qib_qsfp_data *qd)
 {
 	/*
-	 * There is nothing to do here for now.  our
-	 * work is scheduled with schedule_work(), and
-	 * flush_scheduled_work() from remove_one will
-	 * block until all work ssetup with schedule_work()
+	 * There is nothing to do here for now.  our work is scheduled
+	 * with queue_work(), and flush_workqueue() from remove_one
+	 * will block until all work setup with queue_work()
 	 * completes.
 	 */
 }
diff -druNp linux-libre-2.6.37-gnu1/drivers/infiniband/hw/qib/qib_rc.c linux-libre-2.6.38-gnu1/drivers/infiniband/hw/qib/qib_rc.c
--- linux-libre-2.6.37-gnu1/drivers/infiniband/hw/qib/qib_rc.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/infiniband/hw/qib/qib_rc.c	2011-03-14 21:20:32.000000000 -0400
@@ -1005,7 +1005,8 @@ void qib_rc_send_complete(struct qib_qp
 	 * there are still requests that haven't been acked.
 	 */
 	if ((psn & IB_BTH_REQ_ACK) && qp->s_acked != qp->s_tail &&
-	    !(qp->s_flags & (QIB_S_TIMER | QIB_S_WAIT_RNR | QIB_S_WAIT_PSN)))
+	    !(qp->s_flags & (QIB_S_TIMER | QIB_S_WAIT_RNR | QIB_S_WAIT_PSN)) &&
+	    (ib_qib_state_ops[qp->state] & QIB_PROCESS_RECV_OK))
 		start_timer(qp);
 
 	while (qp->s_last != qp->s_acked) {
@@ -1407,6 +1408,7 @@ static void qib_rc_rcv_resp(struct qib_i
 			    struct qib_ctxtdata *rcd)
 {
 	struct qib_swqe *wqe;
+	struct qib_pportdata *ppd = ppd_from_ibp(ibp);
 	enum ib_wc_status status;
 	unsigned long flags;
 	int diff;
@@ -1414,7 +1416,32 @@ static void qib_rc_rcv_resp(struct qib_i
 	u32 aeth;
 	u64 val;
 
+	if (opcode != OP(RDMA_READ_RESPONSE_MIDDLE)) {
+		/*
+		 * If ACK'd PSN on SDMA busy list try to make progress to
+		 * reclaim SDMA credits.
+		 */
+		if ((qib_cmp24(psn, qp->s_sending_psn) >= 0) &&
+		    (qib_cmp24(qp->s_sending_psn, qp->s_sending_hpsn) <= 0)) {
+
+			/*
+			 * If send tasklet not running attempt to progress
+			 * SDMA queue.
+			 */
+			if (!(qp->s_flags & QIB_S_BUSY)) {
+				/* Acquire SDMA Lock */
+				spin_lock_irqsave(&ppd->sdma_lock, flags);
+				/* Invoke sdma make progress */
+				qib_sdma_make_progress(ppd);
+				/* Release SDMA Lock */
+				spin_unlock_irqrestore(&ppd->sdma_lock, flags);
+			}
+		}
+	}
+
 	spin_lock_irqsave(&qp->s_lock, flags);
+	if (!(ib_qib_state_ops[qp->state] & QIB_PROCESS_RECV_OK))
+		goto ack_done;
 
 	/* Ignore invalid responses. */
 	if (qib_cmp24(psn, qp->s_next_psn) >= 0)
diff -druNp linux-libre-2.6.37-gnu1/drivers/infiniband/hw/qib/qib_ud.c linux-libre-2.6.38-gnu1/drivers/infiniband/hw/qib/qib_ud.c
--- linux-libre-2.6.37-gnu1/drivers/infiniband/hw/qib/qib_ud.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/infiniband/hw/qib/qib_ud.c	2011-03-14 21:20:32.000000000 -0400
@@ -445,13 +445,14 @@ void qib_ud_rcv(struct qib_ibport *ibp,
 	qkey = be32_to_cpu(ohdr->u.ud.deth[0]);
 	src_qp = be32_to_cpu(ohdr->u.ud.deth[1]) & QIB_QPN_MASK;
 
-	/* Get the number of bytes the message was padded by. */
+	/*
+	 * Get the number of bytes the message was padded by
+	 * and drop incomplete packets.
+	 */
 	pad = (be32_to_cpu(ohdr->bth[0]) >> 20) & 3;
-	if (unlikely(tlen < (hdrsize + pad + 4))) {
-		/* Drop incomplete packets. */
-		ibp->n_pkt_drops++;
-		goto bail;
-	}
+	if (unlikely(tlen < (hdrsize + pad + 4)))
+		goto drop;
+
 	tlen -= hdrsize + pad + 4;
 
 	/*
@@ -460,10 +461,8 @@ void qib_ud_rcv(struct qib_ibport *ibp,
 	 */
 	if (qp->ibqp.qp_num) {
 		if (unlikely(hdr->lrh[1] == IB_LID_PERMISSIVE ||
-			     hdr->lrh[3] == IB_LID_PERMISSIVE)) {
-			ibp->n_pkt_drops++;
-			goto bail;
-		}
+			     hdr->lrh[3] == IB_LID_PERMISSIVE))
+			goto drop;
 		if (qp->ibqp.qp_num > 1) {
 			u16 pkey1, pkey2;
 
@@ -476,7 +475,7 @@ void qib_ud_rcv(struct qib_ibport *ibp,
 						0xF,
 					      src_qp, qp->ibqp.qp_num,
 					      hdr->lrh[3], hdr->lrh[1]);
-				goto bail;
+				return;
 			}
 		}
 		if (unlikely(qkey != qp->qkey)) {
@@ -484,30 +483,24 @@ void qib_ud_rcv(struct qib_ibport *ibp,
 				      (be16_to_cpu(hdr->lrh[0]) >> 4) & 0xF,
 				      src_qp, qp->ibqp.qp_num,
 				      hdr->lrh[3], hdr->lrh[1]);
-			goto bail;
+			return;
 		}
 		/* Drop invalid MAD packets (see 13.5.3.1). */
 		if (unlikely(qp->ibqp.qp_num == 1 &&
 			     (tlen != 256 ||
-			      (be16_to_cpu(hdr->lrh[0]) >> 12) == 15))) {
-			ibp->n_pkt_drops++;
-			goto bail;
-		}
+			      (be16_to_cpu(hdr->lrh[0]) >> 12) == 15)))
+			goto drop;
 	} else {
 		struct ib_smp *smp;
 
 		/* Drop invalid MAD packets (see 13.5.3.1). */
-		if (tlen != 256 || (be16_to_cpu(hdr->lrh[0]) >> 12) != 15) {
-			ibp->n_pkt_drops++;
-			goto bail;
-		}
+		if (tlen != 256 || (be16_to_cpu(hdr->lrh[0]) >> 12) != 15)
+			goto drop;
 		smp = (struct ib_smp *) data;
 		if ((hdr->lrh[1] == IB_LID_PERMISSIVE ||
 		     hdr->lrh[3] == IB_LID_PERMISSIVE) &&
-		    smp->mgmt_class != IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE) {
-			ibp->n_pkt_drops++;
-			goto bail;
-		}
+		    smp->mgmt_class != IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE)
+			goto drop;
 	}
 
 	/*
@@ -519,14 +512,12 @@ void qib_ud_rcv(struct qib_ibport *ibp,
 	    opcode == IB_OPCODE_UD_SEND_ONLY_WITH_IMMEDIATE) {
 		wc.ex.imm_data = ohdr->u.ud.imm_data;
 		wc.wc_flags = IB_WC_WITH_IMM;
-		hdrsize += sizeof(u32);
+		tlen -= sizeof(u32);
 	} else if (opcode == IB_OPCODE_UD_SEND_ONLY) {
 		wc.ex.imm_data = 0;
 		wc.wc_flags = 0;
-	} else {
-		ibp->n_pkt_drops++;
-		goto bail;
-	}
+	} else
+		goto drop;
 
 	/*
 	 * A GRH is expected to preceed the data even if not
@@ -556,8 +547,7 @@ void qib_ud_rcv(struct qib_ibport *ibp,
 	/* Silently drop packets which are too big. */
 	if (unlikely(wc.byte_len > qp->r_len)) {
 		qp->r_flags |= QIB_R_REUSE_SGE;
-		ibp->n_pkt_drops++;
-		return;
+		goto drop;
 	}
 	if (has_grh) {
 		qib_copy_sge(&qp->r_sge, &hdr->u.l.grh,
@@ -594,5 +584,8 @@ void qib_ud_rcv(struct qib_ibport *ibp,
 	qib_cq_enter(to_icq(qp->ibqp.recv_cq), &wc,
 		     (ohdr->bth[0] &
 			cpu_to_be32(IB_BTH_SOLICITED)) != 0);
-bail:;
+	return;
+
+drop:
+	ibp->n_pkt_drops++;
 }
diff -druNp linux-libre-2.6.37-gnu1/drivers/infiniband/hw/qib/qib_user_sdma.c linux-libre-2.6.38-gnu1/drivers/infiniband/hw/qib/qib_user_sdma.c
--- linux-libre-2.6.37-gnu1/drivers/infiniband/hw/qib/qib_user_sdma.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/infiniband/hw/qib/qib_user_sdma.c	2011-03-14 21:20:32.000000000 -0400
@@ -382,6 +382,7 @@ static void qib_user_sdma_free_pkt_list(
 
 		kmem_cache_free(pq->pkt_slab, pkt);
 	}
+	INIT_LIST_HEAD(list);
 }
 
 /*
diff -druNp linux-libre-2.6.37-gnu1/drivers/infiniband/hw/qib/qib_verbs.h linux-libre-2.6.38-gnu1/drivers/infiniband/hw/qib/qib_verbs.h
--- linux-libre-2.6.37-gnu1/drivers/infiniband/hw/qib/qib_verbs.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/infiniband/hw/qib/qib_verbs.h	2011-03-14 21:20:32.000000000 -0400
@@ -301,6 +301,7 @@ struct qib_mregion {
 	int access_flags;
 	u32 max_segs;           /* number of qib_segs in all the arrays */
 	u32 mapsz;              /* size of the map array */
+	u8  page_shift;         /* 0 - non unform/non powerof2 sizes */
 	atomic_t refcount;
 	struct qib_segarray *map[0];    /* the segments */
 };
@@ -435,7 +436,6 @@ struct qib_qp {
 	spinlock_t r_lock;      /* used for APM */
 	spinlock_t s_lock;
 	atomic_t s_dma_busy;
-	unsigned processor_id;	/* Processor ID QP is bound to */
 	u32 s_flags;
 	u32 s_cur_size;         /* size of send packet in bytes */
 	u32 s_len;              /* total length of s_sge */
@@ -805,7 +805,6 @@ static inline int qib_send_ok(struct qib
 		 !(qp->s_flags & QIB_S_ANY_WAIT_SEND));
 }
 
-extern struct workqueue_struct *qib_wq;
 extern struct workqueue_struct *qib_cq_wq;
 
 /*
@@ -813,13 +812,8 @@ extern struct workqueue_struct *qib_cq_w
  */
 static inline void qib_schedule_send(struct qib_qp *qp)
 {
-	if (qib_send_ok(qp)) {
-		if (qp->processor_id == smp_processor_id())
-			queue_work(qib_wq, &qp->s_work);
-		else
-			queue_work_on(qp->processor_id,
-				      qib_wq, &qp->s_work);
-	}
+	if (qib_send_ok(qp))
+		queue_work(ib_wq, &qp->s_work);
 }
 
 static inline int qib_pkey_ok(u16 pkey1, u16 pkey2)
diff -druNp linux-libre-2.6.37-gnu1/drivers/infiniband/ulp/ipoib/ipoib_cm.c linux-libre-2.6.38-gnu1/drivers/infiniband/ulp/ipoib/ipoib_cm.c
--- linux-libre-2.6.37-gnu1/drivers/infiniband/ulp/ipoib/ipoib_cm.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/infiniband/ulp/ipoib/ipoib_cm.c	2011-03-14 21:20:32.000000000 -0400
@@ -352,15 +352,13 @@ static int ipoib_cm_nonsrq_init_rx(struc
 	int ret;
 	int i;
 
-	rx->rx_ring = vmalloc(ipoib_recvq_size * sizeof *rx->rx_ring);
+	rx->rx_ring = vzalloc(ipoib_recvq_size * sizeof *rx->rx_ring);
 	if (!rx->rx_ring) {
 		printk(KERN_WARNING "%s: failed to allocate CM non-SRQ ring (%d entries)\n",
 		       priv->ca->name, ipoib_recvq_size);
 		return -ENOMEM;
 	}
 
-	memset(rx->rx_ring, 0, ipoib_recvq_size * sizeof *rx->rx_ring);
-
 	t = kmalloc(sizeof *t, GFP_KERNEL);
 	if (!t) {
 		ret = -ENOMEM;
@@ -1097,13 +1095,12 @@ static int ipoib_cm_tx_init(struct ipoib
 	struct ipoib_dev_priv *priv = netdev_priv(p->dev);
 	int ret;
 
-	p->tx_ring = vmalloc(ipoib_sendq_size * sizeof *p->tx_ring);
+	p->tx_ring = vzalloc(ipoib_sendq_size * sizeof *p->tx_ring);
 	if (!p->tx_ring) {
 		ipoib_warn(priv, "failed to allocate tx ring\n");
 		ret = -ENOMEM;
 		goto err_tx;
 	}
-	memset(p->tx_ring, 0, ipoib_sendq_size * sizeof *p->tx_ring);
 
 	p->qp = ipoib_cm_create_tx_qp(p->dev, p);
 	if (IS_ERR(p->qp)) {
@@ -1480,6 +1477,7 @@ static ssize_t set_mode(struct device *d
 
 		if (test_bit(IPOIB_FLAG_CSUM, &priv->flags)) {
 			dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG;
+			priv->dev->features |= NETIF_F_GRO;
 			if (priv->hca_caps & IB_DEVICE_UD_TSO)
 				dev->features |= NETIF_F_TSO;
 		}
@@ -1520,7 +1518,7 @@ static void ipoib_cm_create_srq(struct n
 		return;
 	}
 
-	priv->cm.srq_ring = vmalloc(ipoib_recvq_size * sizeof *priv->cm.srq_ring);
+	priv->cm.srq_ring = vzalloc(ipoib_recvq_size * sizeof *priv->cm.srq_ring);
 	if (!priv->cm.srq_ring) {
 		printk(KERN_WARNING "%s: failed to allocate CM SRQ ring (%d entries)\n",
 		       priv->ca->name, ipoib_recvq_size);
@@ -1529,7 +1527,6 @@ static void ipoib_cm_create_srq(struct n
 		return;
 	}
 
-	memset(priv->cm.srq_ring, 0, ipoib_recvq_size * sizeof *priv->cm.srq_ring);
 }
 
 int ipoib_cm_dev_init(struct net_device *dev)
diff -druNp linux-libre-2.6.37-gnu1/drivers/infiniband/ulp/ipoib/ipoib_ethtool.c linux-libre-2.6.38-gnu1/drivers/infiniband/ulp/ipoib/ipoib_ethtool.c
--- linux-libre-2.6.37-gnu1/drivers/infiniband/ulp/ipoib/ipoib_ethtool.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/infiniband/ulp/ipoib/ipoib_ethtool.c	2011-03-14 21:20:32.000000000 -0400
@@ -106,63 +106,12 @@ static int ipoib_set_coalesce(struct net
 	return 0;
 }
 
-static const char ipoib_stats_keys[][ETH_GSTRING_LEN] = {
-	"LRO aggregated", "LRO flushed",
-	"LRO avg aggr", "LRO no desc"
-};
-
-static void ipoib_get_strings(struct net_device *netdev, u32 stringset, u8 *data)
-{
-	switch (stringset) {
-	case ETH_SS_STATS:
-		memcpy(data, *ipoib_stats_keys,	sizeof(ipoib_stats_keys));
-		break;
-	}
-}
-
-static int ipoib_get_sset_count(struct net_device *dev, int sset)
-{
-	switch (sset) {
-	case ETH_SS_STATS:
-		return ARRAY_SIZE(ipoib_stats_keys);
-	default:
-		return -EOPNOTSUPP;
-	}
-}
-
-static void ipoib_get_ethtool_stats(struct net_device *dev,
-				struct ethtool_stats *stats, uint64_t *data)
-{
-	struct ipoib_dev_priv *priv = netdev_priv(dev);
-	int index = 0;
-
-	/* Get LRO statistics */
-	data[index++] = priv->lro.lro_mgr.stats.aggregated;
-	data[index++] = priv->lro.lro_mgr.stats.flushed;
-	if (priv->lro.lro_mgr.stats.flushed)
-		data[index++] = priv->lro.lro_mgr.stats.aggregated /
-				priv->lro.lro_mgr.stats.flushed;
-	else
-		data[index++] = 0;
-	data[index++] = priv->lro.lro_mgr.stats.no_desc;
-}
-
-static int ipoib_set_flags(struct net_device *dev, u32 flags)
-{
-	return ethtool_op_set_flags(dev, flags, ETH_FLAG_LRO);
-}
-
 static const struct ethtool_ops ipoib_ethtool_ops = {
 	.get_drvinfo		= ipoib_get_drvinfo,
 	.get_rx_csum		= ipoib_get_rx_csum,
 	.set_tso		= ipoib_set_tso,
 	.get_coalesce		= ipoib_get_coalesce,
 	.set_coalesce		= ipoib_set_coalesce,
-	.get_flags		= ethtool_op_get_flags,
-	.set_flags		= ipoib_set_flags,
-	.get_strings		= ipoib_get_strings,
-	.get_sset_count		= ipoib_get_sset_count,
-	.get_ethtool_stats	= ipoib_get_ethtool_stats,
 };
 
 void ipoib_set_ethtool_ops(struct net_device *dev)
diff -druNp linux-libre-2.6.37-gnu1/drivers/infiniband/ulp/ipoib/ipoib.h linux-libre-2.6.38-gnu1/drivers/infiniband/ulp/ipoib/ipoib.h
--- linux-libre-2.6.37-gnu1/drivers/infiniband/ulp/ipoib/ipoib.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/infiniband/ulp/ipoib/ipoib.h	2011-03-14 21:20:32.000000000 -0400
@@ -50,7 +50,7 @@
 #include <rdma/ib_verbs.h>
 #include <rdma/ib_pack.h>
 #include <rdma/ib_sa.h>
-#include <linux/inet_lro.h>
+#include <linux/sched.h>
 
 /* constants */
 
@@ -100,9 +100,6 @@ enum {
 	IPOIB_MCAST_FLAG_BUSY	  = 2,	/* joining or already joined */
 	IPOIB_MCAST_FLAG_ATTACHED = 3,
 
-	IPOIB_MAX_LRO_DESCRIPTORS = 8,
-	IPOIB_LRO_MAX_AGGR 	  = 64,
-
 	MAX_SEND_CQE		  = 16,
 	IPOIB_CM_COPYBREAK	  = 256,
 };
@@ -262,11 +259,6 @@ struct ipoib_ethtool_st {
 	u16     max_coalesced_frames;
 };
 
-struct ipoib_lro {
-	struct net_lro_mgr lro_mgr;
-	struct net_lro_desc lro_desc[IPOIB_MAX_LRO_DESCRIPTORS];
-};
-
 /*
  * Device private locking: network stack tx_lock protects members used
  * in TX fast path, lock protects everything else.  lock nests inside
@@ -352,8 +344,6 @@ struct ipoib_dev_priv {
 	int	hca_caps;
 	struct ipoib_ethtool_st ethtool;
 	struct timer_list poll_timer;
-
-	struct ipoib_lro lro;
 };
 
 struct ipoib_ah {
diff -druNp linux-libre-2.6.37-gnu1/drivers/infiniband/ulp/ipoib/ipoib_ib.c linux-libre-2.6.38-gnu1/drivers/infiniband/ulp/ipoib/ipoib_ib.c
--- linux-libre-2.6.37-gnu1/drivers/infiniband/ulp/ipoib/ipoib_ib.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/infiniband/ulp/ipoib/ipoib_ib.c	2011-03-14 21:20:32.000000000 -0400
@@ -295,10 +295,7 @@ static void ipoib_ib_handle_rx_wc(struct
 	if (test_bit(IPOIB_FLAG_CSUM, &priv->flags) && likely(wc->csum_ok))
 		skb->ip_summed = CHECKSUM_UNNECESSARY;
 
-	if (dev->features & NETIF_F_LRO)
-		lro_receive_skb(&priv->lro.lro_mgr, skb, NULL);
-	else
-		netif_receive_skb(skb);
+	napi_gro_receive(&priv->napi, skb);
 
 repost:
 	if (unlikely(ipoib_ib_post_receive(dev, wr_id)))
@@ -450,9 +447,6 @@ poll_more:
 	}
 
 	if (done < budget) {
-		if (dev->features & NETIF_F_LRO)
-			lro_flush_all(&priv->lro.lro_mgr);
-
 		napi_complete(napi);
 		if (unlikely(ib_req_notify_cq(priv->recv_cq,
 					      IB_CQ_NEXT_COMP |
diff -druNp linux-libre-2.6.37-gnu1/drivers/infiniband/ulp/ipoib/ipoib_main.c linux-libre-2.6.38-gnu1/drivers/infiniband/ulp/ipoib/ipoib_main.c
--- linux-libre-2.6.37-gnu1/drivers/infiniband/ulp/ipoib/ipoib_main.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/infiniband/ulp/ipoib/ipoib_main.c	2011-03-14 21:20:32.000000000 -0400
@@ -60,15 +60,6 @@ MODULE_PARM_DESC(send_queue_size, "Numbe
 module_param_named(recv_queue_size, ipoib_recvq_size, int, 0444);
 MODULE_PARM_DESC(recv_queue_size, "Number of descriptors in receive queue");
 
-static int lro;
-module_param(lro, bool, 0444);
-MODULE_PARM_DESC(lro,  "Enable LRO (Large Receive Offload)");
-
-static int lro_max_aggr = IPOIB_LRO_MAX_AGGR;
-module_param(lro_max_aggr, int, 0644);
-MODULE_PARM_DESC(lro_max_aggr, "LRO: Max packets to be aggregated "
-		"(default = 64)");
-
 #ifdef CONFIG_INFINIBAND_IPOIB_DEBUG
 int ipoib_debug_level;
 
@@ -925,13 +916,12 @@ int ipoib_dev_init(struct net_device *de
 		goto out;
 	}
 
-	priv->tx_ring = vmalloc(ipoib_sendq_size * sizeof *priv->tx_ring);
+	priv->tx_ring = vzalloc(ipoib_sendq_size * sizeof *priv->tx_ring);
 	if (!priv->tx_ring) {
 		printk(KERN_WARNING "%s: failed to allocate TX ring (%d entries)\n",
 		       ca->name, ipoib_sendq_size);
 		goto out_rx_ring_cleanup;
 	}
-	memset(priv->tx_ring, 0, ipoib_sendq_size * sizeof *priv->tx_ring);
 
 	/* priv->tx_head, tx_tail & tx_outstanding are already 0 */
 
@@ -976,54 +966,6 @@ static const struct header_ops ipoib_hea
 	.create	= ipoib_hard_header,
 };
 
-static int get_skb_hdr(struct sk_buff *skb, void **iphdr,
-		       void **tcph, u64 *hdr_flags, void *priv)
-{
-	unsigned int ip_len;
-	struct iphdr *iph;
-
-	if (unlikely(skb->protocol != htons(ETH_P_IP)))
-		return -1;
-
-	/*
-	 * In the future we may add an else clause that verifies the
-	 * checksum and allows devices which do not calculate checksum
-	 * to use LRO.
-	 */
-	if (unlikely(skb->ip_summed != CHECKSUM_UNNECESSARY))
-		return -1;
-
-	/* Check for non-TCP packet */
-	skb_reset_network_header(skb);
-	iph = ip_hdr(skb);
-	if (iph->protocol != IPPROTO_TCP)
-		return -1;
-
-	ip_len = ip_hdrlen(skb);
-	skb_set_transport_header(skb, ip_len);
-	*tcph = tcp_hdr(skb);
-
-	/* check if IP header and TCP header are complete */
-	if (ntohs(iph->tot_len) < ip_len + tcp_hdrlen(skb))
-		return -1;
-
-	*hdr_flags = LRO_IPV4 | LRO_TCP;
-	*iphdr = iph;
-
-	return 0;
-}
-
-static void ipoib_lro_setup(struct ipoib_dev_priv *priv)
-{
-	priv->lro.lro_mgr.max_aggr	 = lro_max_aggr;
-	priv->lro.lro_mgr.max_desc	 = IPOIB_MAX_LRO_DESCRIPTORS;
-	priv->lro.lro_mgr.lro_arr	 = priv->lro.lro_desc;
-	priv->lro.lro_mgr.get_skb_header = get_skb_hdr;
-	priv->lro.lro_mgr.features	 = LRO_F_NAPI;
-	priv->lro.lro_mgr.dev		 = priv->dev;
-	priv->lro.lro_mgr.ip_summed_aggr = CHECKSUM_UNNECESSARY;
-}
-
 static const struct net_device_ops ipoib_netdev_ops = {
 	.ndo_open		 = ipoib_open,
 	.ndo_stop		 = ipoib_stop,
@@ -1067,8 +1009,6 @@ static void ipoib_setup(struct net_devic
 
 	priv->dev = dev;
 
-	ipoib_lro_setup(priv);
-
 	spin_lock_init(&priv->lock);
 
 	mutex_init(&priv->vlan_mutex);
@@ -1218,8 +1158,7 @@ int ipoib_set_dev_features(struct ipoib_
 		priv->dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM;
 	}
 
-	if (lro)
-		priv->dev->features |= NETIF_F_LRO;
+	priv->dev->features |= NETIF_F_GRO;
 
 	if (priv->dev->features & NETIF_F_SG && priv->hca_caps & IB_DEVICE_UD_TSO)
 		priv->dev->features |= NETIF_F_TSO;
diff -druNp linux-libre-2.6.37-gnu1/drivers/infiniband/ulp/ipoib/Kconfig linux-libre-2.6.38-gnu1/drivers/infiniband/ulp/ipoib/Kconfig
--- linux-libre-2.6.37-gnu1/drivers/infiniband/ulp/ipoib/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/infiniband/ulp/ipoib/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -1,7 +1,6 @@
 config INFINIBAND_IPOIB
 	tristate "IP-over-InfiniBand"
 	depends on NETDEVICES && INET && (IPV6 || IPV6=n)
-	select INET_LRO
 	---help---
 	  Support for the IP-over-InfiniBand protocol (IPoIB). This
 	  transports IP packets over InfiniBand so you can use your IB
@@ -25,7 +24,7 @@ config INFINIBAND_IPOIB_CM
 	  unless you limit mtu for these destinations to 2044.
 
 config INFINIBAND_IPOIB_DEBUG
-	bool "IP-over-InfiniBand debugging" if EMBEDDED
+	bool "IP-over-InfiniBand debugging" if EXPERT
 	depends on INFINIBAND_IPOIB
 	default y
 	---help---
diff -druNp linux-libre-2.6.37-gnu1/drivers/infiniband/ulp/srp/ib_srp.c linux-libre-2.6.38-gnu1/drivers/infiniband/ulp/srp/ib_srp.c
--- linux-libre-2.6.37-gnu1/drivers/infiniband/ulp/srp/ib_srp.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/infiniband/ulp/srp/ib_srp.c	2011-03-14 21:20:32.000000000 -0400
@@ -441,18 +441,28 @@ static void srp_disconnect_target(struct
 	wait_for_completion(&target->done);
 }
 
+static bool srp_change_state(struct srp_target_port *target,
+			    enum srp_target_state old,
+			    enum srp_target_state new)
+{
+	bool changed = false;
+
+	spin_lock_irq(&target->lock);
+	if (target->state == old) {
+		target->state = new;
+		changed = true;
+	}
+	spin_unlock_irq(&target->lock);
+	return changed;
+}
+
 static void srp_remove_work(struct work_struct *work)
 {
 	struct srp_target_port *target =
 		container_of(work, struct srp_target_port, work);
 
-	spin_lock_irq(target->scsi_host->host_lock);
-	if (target->state != SRP_TARGET_DEAD) {
-		spin_unlock_irq(target->scsi_host->host_lock);
+	if (!srp_change_state(target, SRP_TARGET_DEAD, SRP_TARGET_REMOVED))
 		return;
-	}
-	target->state = SRP_TARGET_REMOVED;
-	spin_unlock_irq(target->scsi_host->host_lock);
 
 	spin_lock(&target->srp_host->target_lock);
 	list_del(&target->list);
@@ -539,33 +549,34 @@ static void srp_unmap_data(struct scsi_c
 			scsi_sg_count(scmnd), scmnd->sc_data_direction);
 }
 
-static void srp_remove_req(struct srp_target_port *target, struct srp_request *req)
+static void srp_remove_req(struct srp_target_port *target,
+			   struct srp_request *req, s32 req_lim_delta)
 {
+	unsigned long flags;
+
 	srp_unmap_data(req->scmnd, target, req);
-	list_move_tail(&req->list, &target->free_reqs);
+	spin_lock_irqsave(&target->lock, flags);
+	target->req_lim += req_lim_delta;
+	req->scmnd = NULL;
+	list_add_tail(&req->list, &target->free_reqs);
+	spin_unlock_irqrestore(&target->lock, flags);
 }
 
 static void srp_reset_req(struct srp_target_port *target, struct srp_request *req)
 {
 	req->scmnd->result = DID_RESET << 16;
 	req->scmnd->scsi_done(req->scmnd);
-	srp_remove_req(target, req);
+	srp_remove_req(target, req, 0);
 }
 
 static int srp_reconnect_target(struct srp_target_port *target)
 {
 	struct ib_qp_attr qp_attr;
-	struct srp_request *req, *tmp;
 	struct ib_wc wc;
-	int ret;
+	int i, ret;
 
-	spin_lock_irq(target->scsi_host->host_lock);
-	if (target->state != SRP_TARGET_LIVE) {
-		spin_unlock_irq(target->scsi_host->host_lock);
+	if (!srp_change_state(target, SRP_TARGET_LIVE, SRP_TARGET_CONNECTING))
 		return -EAGAIN;
-	}
-	target->state = SRP_TARGET_CONNECTING;
-	spin_unlock_irq(target->scsi_host->host_lock);
 
 	srp_disconnect_target(target);
 	/*
@@ -590,27 +601,23 @@ static int srp_reconnect_target(struct s
 	while (ib_poll_cq(target->send_cq, 1, &wc) > 0)
 		; /* nothing */
 
-	spin_lock_irq(target->scsi_host->host_lock);
-	list_for_each_entry_safe(req, tmp, &target->req_queue, list)
-		srp_reset_req(target, req);
-	spin_unlock_irq(target->scsi_host->host_lock);
+	for (i = 0; i < SRP_CMD_SQ_SIZE; ++i) {
+		struct srp_request *req = &target->req_ring[i];
+		if (req->scmnd)
+			srp_reset_req(target, req);
+	}
 
-	target->rx_head	 = 0;
-	target->tx_head	 = 0;
-	target->tx_tail  = 0;
+	INIT_LIST_HEAD(&target->free_tx);
+	for (i = 0; i < SRP_SQ_SIZE; ++i)
+		list_add(&target->tx_ring[i]->list, &target->free_tx);
 
 	target->qp_in_error = 0;
 	ret = srp_connect_target(target);
 	if (ret)
 		goto err;
 
-	spin_lock_irq(target->scsi_host->host_lock);
-	if (target->state == SRP_TARGET_CONNECTING) {
-		ret = 0;
-		target->state = SRP_TARGET_LIVE;
-	} else
+	if (!srp_change_state(target, SRP_TARGET_CONNECTING, SRP_TARGET_LIVE))
 		ret = -EAGAIN;
-	spin_unlock_irq(target->scsi_host->host_lock);
 
 	return ret;
 
@@ -620,17 +627,20 @@ err:
 
 	/*
 	 * We couldn't reconnect, so kill our target port off.
-	 * However, we have to defer the real removal because we might
-	 * be in the context of the SCSI error handler now, which
-	 * would deadlock if we call scsi_remove_host().
+	 * However, we have to defer the real removal because we
+	 * are in the context of the SCSI error handler now, which
+	 * will deadlock if we call scsi_remove_host().
+	 *
+	 * Schedule our work inside the lock to avoid a race with
+	 * the flush_scheduled_work() in srp_remove_one().
 	 */
-	spin_lock_irq(target->scsi_host->host_lock);
+	spin_lock_irq(&target->lock);
 	if (target->state == SRP_TARGET_CONNECTING) {
 		target->state = SRP_TARGET_DEAD;
 		INIT_WORK(&target->work, srp_remove_work);
-		schedule_work(&target->work);
+		queue_work(ib_wq, &target->work);
 	}
-	spin_unlock_irq(target->scsi_host->host_lock);
+	spin_unlock_irq(&target->lock);
 
 	return ret;
 }
@@ -758,7 +768,7 @@ static int srp_map_data(struct scsi_cmnd
 		struct srp_direct_buf *buf = (void *) cmd->add_data;
 
 		buf->va  = cpu_to_be64(ib_sg_dma_address(ibdev, scat));
-		buf->key = cpu_to_be32(dev->mr->rkey);
+		buf->key = cpu_to_be32(target->rkey);
 		buf->len = cpu_to_be32(ib_sg_dma_len(ibdev, scat));
 	} else if (srp_map_fmr(target, scat, count, req,
 			       (void *) cmd->add_data)) {
@@ -783,7 +793,7 @@ static int srp_map_data(struct scsi_cmnd
 			buf->desc_list[i].va  =
 				cpu_to_be64(ib_sg_dma_address(ibdev, sg));
 			buf->desc_list[i].key =
-				cpu_to_be32(dev->mr->rkey);
+				cpu_to_be32(target->rkey);
 			buf->desc_list[i].len = cpu_to_be32(dma_len);
 			datalen += dma_len;
 		}
@@ -796,7 +806,7 @@ static int srp_map_data(struct scsi_cmnd
 		buf->table_desc.va  =
 			cpu_to_be64(req->cmd->dma + sizeof *cmd + sizeof *buf);
 		buf->table_desc.key =
-			cpu_to_be32(target->srp_host->srp_dev->mr->rkey);
+			cpu_to_be32(target->rkey);
 		buf->table_desc.len =
 			cpu_to_be32(count * sizeof (struct srp_direct_buf));
 
@@ -812,9 +822,23 @@ static int srp_map_data(struct scsi_cmnd
 }
 
 /*
- * Must be called with target->scsi_host->host_lock held to protect
- * req_lim and tx_head.  Lock cannot be dropped between call here and
- * call to __srp_post_send().
+ * Return an IU and possible credit to the free pool
+ */
+static void srp_put_tx_iu(struct srp_target_port *target, struct srp_iu *iu,
+			  enum srp_iu_type iu_type)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&target->lock, flags);
+	list_add(&iu->list, &target->free_tx);
+	if (iu_type != SRP_IU_RSP)
+		++target->req_lim;
+	spin_unlock_irqrestore(&target->lock, flags);
+}
+
+/*
+ * Must be called with target->lock held to protect req_lim and free_tx.
+ * If IU is not sent, it must be returned using srp_put_tx_iu().
  *
  * Note:
  * An upper limit for the number of allocated information units for each
@@ -833,83 +857,59 @@ static struct srp_iu *__srp_get_tx_iu(st
 
 	srp_send_completion(target->send_cq, target);
 
-	if (target->tx_head - target->tx_tail >= SRP_SQ_SIZE)
+	if (list_empty(&target->free_tx))
 		return NULL;
 
 	/* Initiator responses to target requests do not consume credits */
-	if (target->req_lim <= rsv && iu_type != SRP_IU_RSP) {
-		++target->zero_req_lim;
-		return NULL;
+	if (iu_type != SRP_IU_RSP) {
+		if (target->req_lim <= rsv) {
+			++target->zero_req_lim;
+			return NULL;
+		}
+
+		--target->req_lim;
 	}
 
-	iu = target->tx_ring[target->tx_head & SRP_SQ_MASK];
-	iu->type = iu_type;
+	iu = list_first_entry(&target->free_tx, struct srp_iu, list);
+	list_del(&iu->list);
 	return iu;
 }
 
-/*
- * Must be called with target->scsi_host->host_lock held to protect
- * req_lim and tx_head.
- */
-static int __srp_post_send(struct srp_target_port *target,
-			   struct srp_iu *iu, int len)
+static int srp_post_send(struct srp_target_port *target,
+			 struct srp_iu *iu, int len)
 {
 	struct ib_sge list;
 	struct ib_send_wr wr, *bad_wr;
-	int ret = 0;
 
 	list.addr   = iu->dma;
 	list.length = len;
-	list.lkey   = target->srp_host->srp_dev->mr->lkey;
+	list.lkey   = target->lkey;
 
 	wr.next       = NULL;
-	wr.wr_id      = target->tx_head & SRP_SQ_MASK;
+	wr.wr_id      = (uintptr_t) iu;
 	wr.sg_list    = &list;
 	wr.num_sge    = 1;
 	wr.opcode     = IB_WR_SEND;
 	wr.send_flags = IB_SEND_SIGNALED;
 
-	ret = ib_post_send(target->qp, &wr, &bad_wr);
-
-	if (!ret) {
-		++target->tx_head;
-		if (iu->type != SRP_IU_RSP)
-			--target->req_lim;
-	}
-
-	return ret;
+	return ib_post_send(target->qp, &wr, &bad_wr);
 }
 
-static int srp_post_recv(struct srp_target_port *target)
+static int srp_post_recv(struct srp_target_port *target, struct srp_iu *iu)
 {
-	unsigned long flags;
-	struct srp_iu *iu;
-	struct ib_sge list;
 	struct ib_recv_wr wr, *bad_wr;
-	unsigned int next;
-	int ret;
-
-	spin_lock_irqsave(target->scsi_host->host_lock, flags);
-
-	next	 = target->rx_head & SRP_RQ_MASK;
-	wr.wr_id = next;
-	iu	 = target->rx_ring[next];
+	struct ib_sge list;
 
 	list.addr   = iu->dma;
 	list.length = iu->size;
-	list.lkey   = target->srp_host->srp_dev->mr->lkey;
+	list.lkey   = target->lkey;
 
 	wr.next     = NULL;
+	wr.wr_id    = (uintptr_t) iu;
 	wr.sg_list  = &list;
 	wr.num_sge  = 1;
 
-	ret = ib_post_recv(target->qp, &wr, &bad_wr);
-	if (!ret)
-		++target->rx_head;
-
-	spin_unlock_irqrestore(target->scsi_host->host_lock, flags);
-
-	return ret;
+	return ib_post_recv(target->qp, &wr, &bad_wr);
 }
 
 static void srp_process_rsp(struct srp_target_port *target, struct srp_rsp *rsp)
@@ -917,23 +917,18 @@ static void srp_process_rsp(struct srp_t
 	struct srp_request *req;
 	struct scsi_cmnd *scmnd;
 	unsigned long flags;
-	s32 delta;
-
-	delta = (s32) be32_to_cpu(rsp->req_lim_delta);
-
-	spin_lock_irqsave(target->scsi_host->host_lock, flags);
-
-	target->req_lim += delta;
-
-	req = &target->req_ring[rsp->tag & ~SRP_TAG_TSK_MGMT];
 
 	if (unlikely(rsp->tag & SRP_TAG_TSK_MGMT)) {
-		if (be32_to_cpu(rsp->resp_data_len) < 4)
-			req->tsk_status = -1;
-		else
-			req->tsk_status = rsp->data[3];
-		complete(&req->done);
+		spin_lock_irqsave(&target->lock, flags);
+		target->req_lim += be32_to_cpu(rsp->req_lim_delta);
+		spin_unlock_irqrestore(&target->lock, flags);
+
+		target->tsk_mgmt_status = -1;
+		if (be32_to_cpu(rsp->resp_data_len) >= 4)
+			target->tsk_mgmt_status = rsp->data[3];
+		complete(&target->tsk_mgmt_done);
 	} else {
+		req = &target->req_ring[rsp->tag];
 		scmnd = req->scmnd;
 		if (!scmnd)
 			shost_printk(KERN_ERR, target->scsi_host,
@@ -953,49 +948,42 @@ static void srp_process_rsp(struct srp_t
 		else if (rsp->flags & (SRP_RSP_FLAG_DIOVER | SRP_RSP_FLAG_DIUNDER))
 			scsi_set_resid(scmnd, be32_to_cpu(rsp->data_in_res_cnt));
 
-		if (!req->tsk_mgmt) {
-			scmnd->host_scribble = (void *) -1L;
-			scmnd->scsi_done(scmnd);
-
-			srp_remove_req(target, req);
-		} else
-			req->cmd_done = 1;
+		srp_remove_req(target, req, be32_to_cpu(rsp->req_lim_delta));
+		scmnd->host_scribble = NULL;
+		scmnd->scsi_done(scmnd);
 	}
-
-	spin_unlock_irqrestore(target->scsi_host->host_lock, flags);
 }
 
 static int srp_response_common(struct srp_target_port *target, s32 req_delta,
 			       void *rsp, int len)
 {
-	struct ib_device *dev;
+	struct ib_device *dev = target->srp_host->srp_dev->dev;
 	unsigned long flags;
 	struct srp_iu *iu;
-	int err = 1;
-
-	dev = target->srp_host->srp_dev->dev;
+	int err;
 
-	spin_lock_irqsave(target->scsi_host->host_lock, flags);
+	spin_lock_irqsave(&target->lock, flags);
 	target->req_lim += req_delta;
-
 	iu = __srp_get_tx_iu(target, SRP_IU_RSP);
+	spin_unlock_irqrestore(&target->lock, flags);
+
 	if (!iu) {
 		shost_printk(KERN_ERR, target->scsi_host, PFX
 			     "no IU available to send response\n");
-		goto out;
+		return 1;
 	}
 
 	ib_dma_sync_single_for_cpu(dev, iu->dma, len, DMA_TO_DEVICE);
 	memcpy(iu->buf, rsp, len);
 	ib_dma_sync_single_for_device(dev, iu->dma, len, DMA_TO_DEVICE);
 
-	err = __srp_post_send(target, iu, len);
-	if (err)
+	err = srp_post_send(target, iu, len);
+	if (err) {
 		shost_printk(KERN_ERR, target->scsi_host, PFX
 			     "unable to post response: %d\n", err);
+		srp_put_tx_iu(target, iu, SRP_IU_RSP);
+	}
 
-out:
-	spin_unlock_irqrestore(target->scsi_host->host_lock, flags);
 	return err;
 }
 
@@ -1032,14 +1020,11 @@ static void srp_process_aer_req(struct s
 
 static void srp_handle_recv(struct srp_target_port *target, struct ib_wc *wc)
 {
-	struct ib_device *dev;
-	struct srp_iu *iu;
+	struct ib_device *dev = target->srp_host->srp_dev->dev;
+	struct srp_iu *iu = (struct srp_iu *) wc->wr_id;
 	int res;
 	u8 opcode;
 
-	iu = target->rx_ring[wc->wr_id];
-
-	dev = target->srp_host->srp_dev->dev;
 	ib_dma_sync_single_for_cpu(dev, iu->dma, target->max_ti_iu_len,
 				   DMA_FROM_DEVICE);
 
@@ -1080,7 +1065,7 @@ static void srp_handle_recv(struct srp_t
 	ib_dma_sync_single_for_device(dev, iu->dma, target->max_ti_iu_len,
 				      DMA_FROM_DEVICE);
 
-	res = srp_post_recv(target);
+	res = srp_post_recv(target, iu);
 	if (res != 0)
 		shost_printk(KERN_ERR, target->scsi_host,
 			     PFX "Recv failed with error code %d\n", res);
@@ -1109,6 +1094,7 @@ static void srp_send_completion(struct i
 {
 	struct srp_target_port *target = target_ptr;
 	struct ib_wc wc;
+	struct srp_iu *iu;
 
 	while (ib_poll_cq(cq, 1, &wc) > 0) {
 		if (wc.status) {
@@ -1119,18 +1105,19 @@ static void srp_send_completion(struct i
 			break;
 		}
 
-		++target->tx_tail;
+		iu = (struct srp_iu *) wc.wr_id;
+		list_add(&iu->list, &target->free_tx);
 	}
 }
 
-static int srp_queuecommand_lck(struct scsi_cmnd *scmnd,
-			    void (*done)(struct scsi_cmnd *))
+static int srp_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *scmnd)
 {
-	struct srp_target_port *target = host_to_target(scmnd->device->host);
+	struct srp_target_port *target = host_to_target(shost);
 	struct srp_request *req;
 	struct srp_iu *iu;
 	struct srp_cmd *cmd;
 	struct ib_device *dev;
+	unsigned long flags;
 	int len;
 
 	if (target->state == SRP_TARGET_CONNECTING)
@@ -1139,23 +1126,25 @@ static int srp_queuecommand_lck(struct s
 	if (target->state == SRP_TARGET_DEAD ||
 	    target->state == SRP_TARGET_REMOVED) {
 		scmnd->result = DID_BAD_TARGET << 16;
-		done(scmnd);
+		scmnd->scsi_done(scmnd);
 		return 0;
 	}
 
+	spin_lock_irqsave(&target->lock, flags);
 	iu = __srp_get_tx_iu(target, SRP_IU_CMD);
 	if (!iu)
-		goto err;
+		goto err_unlock;
+
+	req = list_first_entry(&target->free_reqs, struct srp_request, list);
+	list_del(&req->list);
+	spin_unlock_irqrestore(&target->lock, flags);
 
 	dev = target->srp_host->srp_dev->dev;
 	ib_dma_sync_single_for_cpu(dev, iu->dma, srp_max_iu_len,
 				   DMA_TO_DEVICE);
 
-	req = list_first_entry(&target->free_reqs, struct srp_request, list);
-
-	scmnd->scsi_done     = done;
 	scmnd->result        = 0;
-	scmnd->host_scribble = (void *) (long) req->index;
+	scmnd->host_scribble = (void *) req;
 
 	cmd = iu->buf;
 	memset(cmd, 0, sizeof *cmd);
@@ -1167,37 +1156,40 @@ static int srp_queuecommand_lck(struct s
 
 	req->scmnd    = scmnd;
 	req->cmd      = iu;
-	req->cmd_done = 0;
-	req->tsk_mgmt = NULL;
 
 	len = srp_map_data(scmnd, target, req);
 	if (len < 0) {
 		shost_printk(KERN_ERR, target->scsi_host,
 			     PFX "Failed to map data\n");
-		goto err;
+		goto err_iu;
 	}
 
 	ib_dma_sync_single_for_device(dev, iu->dma, srp_max_iu_len,
 				      DMA_TO_DEVICE);
 
-	if (__srp_post_send(target, iu, len)) {
+	if (srp_post_send(target, iu, len)) {
 		shost_printk(KERN_ERR, target->scsi_host, PFX "Send failed\n");
 		goto err_unmap;
 	}
 
-	list_move_tail(&req->list, &target->req_queue);
-
 	return 0;
 
 err_unmap:
 	srp_unmap_data(scmnd, target, req);
 
+err_iu:
+	srp_put_tx_iu(target, iu, SRP_IU_CMD);
+
+	spin_lock_irqsave(&target->lock, flags);
+	list_add(&req->list, &target->free_reqs);
+
+err_unlock:
+	spin_unlock_irqrestore(&target->lock, flags);
+
 err:
 	return SCSI_MLQUEUE_HOST_BUSY;
 }
 
-static DEF_SCSI_QCMD(srp_queuecommand)
-
 static int srp_alloc_iu_bufs(struct srp_target_port *target)
 {
 	int i;
@@ -1216,6 +1208,8 @@ static int srp_alloc_iu_bufs(struct srp_
 						  GFP_KERNEL, DMA_TO_DEVICE);
 		if (!target->tx_ring[i])
 			goto err;
+
+		list_add(&target->tx_ring[i]->list, &target->free_tx);
 	}
 
 	return 0;
@@ -1377,7 +1371,8 @@ static int srp_cm_handler(struct ib_cm_i
 			break;
 
 		for (i = 0; i < SRP_RQ_SIZE; i++) {
-			target->status = srp_post_recv(target);
+			struct srp_iu *iu = target->rx_ring[i];
+			target->status = srp_post_recv(target, iu);
 			if (target->status)
 				break;
 		}
@@ -1442,25 +1437,24 @@ static int srp_cm_handler(struct ib_cm_i
 }
 
 static int srp_send_tsk_mgmt(struct srp_target_port *target,
-			     struct srp_request *req, u8 func)
+			     u64 req_tag, unsigned int lun, u8 func)
 {
 	struct ib_device *dev = target->srp_host->srp_dev->dev;
 	struct srp_iu *iu;
 	struct srp_tsk_mgmt *tsk_mgmt;
 
-	spin_lock_irq(target->scsi_host->host_lock);
-
 	if (target->state == SRP_TARGET_DEAD ||
-	    target->state == SRP_TARGET_REMOVED) {
-		req->scmnd->result = DID_BAD_TARGET << 16;
-		goto out;
-	}
+	    target->state == SRP_TARGET_REMOVED)
+		return -1;
 
-	init_completion(&req->done);
+	init_completion(&target->tsk_mgmt_done);
 
+	spin_lock_irq(&target->lock);
 	iu = __srp_get_tx_iu(target, SRP_IU_TSK_MGMT);
+	spin_unlock_irq(&target->lock);
+
 	if (!iu)
-		goto out;
+		return -1;
 
 	ib_dma_sync_single_for_cpu(dev, iu->dma, sizeof *tsk_mgmt,
 				   DMA_TO_DEVICE);
@@ -1468,70 +1462,46 @@ static int srp_send_tsk_mgmt(struct srp_
 	memset(tsk_mgmt, 0, sizeof *tsk_mgmt);
 
 	tsk_mgmt->opcode 	= SRP_TSK_MGMT;
-	tsk_mgmt->lun 		= cpu_to_be64((u64) req->scmnd->device->lun << 48);
-	tsk_mgmt->tag 		= req->index | SRP_TAG_TSK_MGMT;
+	tsk_mgmt->lun		= cpu_to_be64((u64) lun << 48);
+	tsk_mgmt->tag		= req_tag | SRP_TAG_TSK_MGMT;
 	tsk_mgmt->tsk_mgmt_func = func;
-	tsk_mgmt->task_tag 	= req->index;
+	tsk_mgmt->task_tag	= req_tag;
 
 	ib_dma_sync_single_for_device(dev, iu->dma, sizeof *tsk_mgmt,
 				      DMA_TO_DEVICE);
-	if (__srp_post_send(target, iu, sizeof *tsk_mgmt))
-		goto out;
-
-	req->tsk_mgmt = iu;
-
-	spin_unlock_irq(target->scsi_host->host_lock);
-
-	if (!wait_for_completion_timeout(&req->done,
-					 msecs_to_jiffies(SRP_ABORT_TIMEOUT_MS)))
+	if (srp_post_send(target, iu, sizeof *tsk_mgmt)) {
+		srp_put_tx_iu(target, iu, SRP_IU_TSK_MGMT);
 		return -1;
+	}
 
-	return 0;
-
-out:
-	spin_unlock_irq(target->scsi_host->host_lock);
-	return -1;
-}
-
-static int srp_find_req(struct srp_target_port *target,
-			struct scsi_cmnd *scmnd,
-			struct srp_request **req)
-{
-	if (scmnd->host_scribble == (void *) -1L)
+	if (!wait_for_completion_timeout(&target->tsk_mgmt_done,
+					 msecs_to_jiffies(SRP_ABORT_TIMEOUT_MS)))
 		return -1;
 
-	*req = &target->req_ring[(long) scmnd->host_scribble];
-
 	return 0;
 }
 
 static int srp_abort(struct scsi_cmnd *scmnd)
 {
 	struct srp_target_port *target = host_to_target(scmnd->device->host);
-	struct srp_request *req;
+	struct srp_request *req = (struct srp_request *) scmnd->host_scribble;
 	int ret = SUCCESS;
 
 	shost_printk(KERN_ERR, target->scsi_host, "SRP abort called\n");
 
-	if (target->qp_in_error)
-		return FAILED;
-	if (srp_find_req(target, scmnd, &req))
+	if (!req || target->qp_in_error)
 		return FAILED;
-	if (srp_send_tsk_mgmt(target, req, SRP_TSK_ABORT_TASK))
+	if (srp_send_tsk_mgmt(target, req->index, scmnd->device->lun,
+			      SRP_TSK_ABORT_TASK))
 		return FAILED;
 
-	spin_lock_irq(target->scsi_host->host_lock);
-
-	if (req->cmd_done) {
-		srp_remove_req(target, req);
-		scmnd->scsi_done(scmnd);
-	} else if (!req->tsk_status) {
-		srp_remove_req(target, req);
-		scmnd->result = DID_ABORT << 16;
-	} else
-		ret = FAILED;
-
-	spin_unlock_irq(target->scsi_host->host_lock);
+	if (req->scmnd) {
+		if (!target->tsk_mgmt_status) {
+			srp_remove_req(target, req, 0);
+			scmnd->result = DID_ABORT << 16;
+		} else
+			ret = FAILED;
+	}
 
 	return ret;
 }
@@ -1539,26 +1509,23 @@ static int srp_abort(struct scsi_cmnd *s
 static int srp_reset_device(struct scsi_cmnd *scmnd)
 {
 	struct srp_target_port *target = host_to_target(scmnd->device->host);
-	struct srp_request *req, *tmp;
+	int i;
 
 	shost_printk(KERN_ERR, target->scsi_host, "SRP reset_device called\n");
 
 	if (target->qp_in_error)
 		return FAILED;
-	if (srp_find_req(target, scmnd, &req))
-		return FAILED;
-	if (srp_send_tsk_mgmt(target, req, SRP_TSK_LUN_RESET))
+	if (srp_send_tsk_mgmt(target, SRP_TAG_NO_REQ, scmnd->device->lun,
+			      SRP_TSK_LUN_RESET))
 		return FAILED;
-	if (req->tsk_status)
+	if (target->tsk_mgmt_status)
 		return FAILED;
 
-	spin_lock_irq(target->scsi_host->host_lock);
-
-	list_for_each_entry_safe(req, tmp, &target->req_queue, list)
-		if (req->scmnd->device == scmnd->device)
+	for (i = 0; i < SRP_CMD_SQ_SIZE; ++i) {
+		struct srp_request *req = &target->req_ring[i];
+		if (req->scmnd && req->scmnd->device == scmnd->device)
 			srp_reset_req(target, req);
-
-	spin_unlock_irq(target->scsi_host->host_lock);
+	}
 
 	return SUCCESS;
 }
@@ -1987,9 +1954,12 @@ static ssize_t srp_create_target(struct
 	target->io_class   = SRP_REV16A_IB_IO_CLASS;
 	target->scsi_host  = target_host;
 	target->srp_host   = host;
+	target->lkey	   = host->srp_dev->mr->lkey;
+	target->rkey	   = host->srp_dev->mr->rkey;
 
+	spin_lock_init(&target->lock);
+	INIT_LIST_HEAD(&target->free_tx);
 	INIT_LIST_HEAD(&target->free_reqs);
-	INIT_LIST_HEAD(&target->req_queue);
 	for (i = 0; i < SRP_CMD_SQ_SIZE; ++i) {
 		target->req_ring[i].index = i;
 		list_add_tail(&target->req_ring[i].list, &target->free_reqs);
@@ -2217,9 +2187,9 @@ static void srp_remove_one(struct ib_dev
 		 */
 		spin_lock(&host->target_lock);
 		list_for_each_entry(target, &host->target_list, list) {
-			spin_lock_irq(target->scsi_host->host_lock);
+			spin_lock_irq(&target->lock);
 			target->state = SRP_TARGET_REMOVED;
-			spin_unlock_irq(target->scsi_host->host_lock);
+			spin_unlock_irq(&target->lock);
 		}
 		spin_unlock(&host->target_lock);
 
@@ -2228,7 +2198,7 @@ static void srp_remove_one(struct ib_dev
 		 * started before we marked our target ports as
 		 * removed, and any target port removal tasks.
 		 */
-		flush_scheduled_work();
+		flush_workqueue(ib_wq);
 
 		list_for_each_entry_safe(target, tmp_target,
 					 &host->target_list, list) {
@@ -2258,8 +2228,7 @@ static int __init srp_init_module(void)
 {
 	int ret;
 
-	BUILD_BUG_ON_NOT_POWER_OF_2(SRP_SQ_SIZE);
-	BUILD_BUG_ON_NOT_POWER_OF_2(SRP_RQ_SIZE);
+	BUILD_BUG_ON(FIELD_SIZEOF(struct ib_wc, wr_id) < sizeof(void *));
 
 	if (srp_sg_tablesize > 255) {
 		printk(KERN_WARNING PFX "Clamping srp_sg_tablesize to 255\n");
diff -druNp linux-libre-2.6.37-gnu1/drivers/infiniband/ulp/srp/ib_srp.h linux-libre-2.6.38-gnu1/drivers/infiniband/ulp/srp/ib_srp.h
--- linux-libre-2.6.37-gnu1/drivers/infiniband/ulp/srp/ib_srp.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/infiniband/ulp/srp/ib_srp.h	2011-03-14 21:20:32.000000000 -0400
@@ -59,16 +59,15 @@ enum {
 
 	SRP_RQ_SHIFT    	= 6,
 	SRP_RQ_SIZE		= 1 << SRP_RQ_SHIFT,
-	SRP_RQ_MASK		= SRP_RQ_SIZE - 1,
 
 	SRP_SQ_SIZE		= SRP_RQ_SIZE,
-	SRP_SQ_MASK		= SRP_SQ_SIZE - 1,
 	SRP_RSP_SQ_SIZE		= 1,
 	SRP_REQ_SQ_SIZE		= SRP_SQ_SIZE - SRP_RSP_SQ_SIZE,
 	SRP_TSK_MGMT_SQ_SIZE	= 1,
 	SRP_CMD_SQ_SIZE		= SRP_REQ_SQ_SIZE - SRP_TSK_MGMT_SQ_SIZE,
 
-	SRP_TAG_TSK_MGMT	= 1 << (SRP_RQ_SHIFT + 1),
+	SRP_TAG_NO_REQ		= ~0U,
+	SRP_TAG_TSK_MGMT	= 1U << 31,
 
 	SRP_FMR_SIZE		= 256,
 	SRP_FMR_POOL_SIZE	= 1024,
@@ -113,15 +112,29 @@ struct srp_request {
 	struct list_head	list;
 	struct scsi_cmnd       *scmnd;
 	struct srp_iu	       *cmd;
-	struct srp_iu	       *tsk_mgmt;
 	struct ib_pool_fmr     *fmr;
-	struct completion	done;
 	short			index;
-	u8			cmd_done;
-	u8			tsk_status;
 };
 
 struct srp_target_port {
+	/* These are RW in the hot path, and commonly used together */
+	struct list_head	free_tx;
+	struct list_head	free_reqs;
+	spinlock_t		lock;
+	s32			req_lim;
+
+	/* These are read-only in the hot path */
+	struct ib_cq	       *send_cq ____cacheline_aligned_in_smp;
+	struct ib_cq	       *recv_cq;
+	struct ib_qp	       *qp;
+	u32			lkey;
+	u32			rkey;
+	enum srp_target_state	state;
+
+	/* Everything above this point is used in the hot path of
+	 * command processing. Try to keep them packed into cachelines.
+	 */
+
 	__be64			id_ext;
 	__be64			ioc_guid;
 	__be64			service_id;
@@ -138,24 +151,13 @@ struct srp_target_port {
 	int			path_query_id;
 
 	struct ib_cm_id	       *cm_id;
-	struct ib_cq	       *recv_cq;
-	struct ib_cq	       *send_cq;
-	struct ib_qp	       *qp;
 
 	int			max_ti_iu_len;
-	s32			req_lim;
 
 	int			zero_req_lim;
 
-	unsigned		rx_head;
-	struct srp_iu	       *rx_ring[SRP_RQ_SIZE];
-
-	unsigned		tx_head;
-	unsigned		tx_tail;
 	struct srp_iu	       *tx_ring[SRP_SQ_SIZE];
-
-	struct list_head	free_reqs;
-	struct list_head	req_queue;
+	struct srp_iu	       *rx_ring[SRP_RQ_SIZE];
 	struct srp_request	req_ring[SRP_CMD_SQ_SIZE];
 
 	struct work_struct	work;
@@ -163,16 +165,18 @@ struct srp_target_port {
 	struct list_head	list;
 	struct completion	done;
 	int			status;
-	enum srp_target_state	state;
 	int			qp_in_error;
+
+	struct completion	tsk_mgmt_done;
+	u8			tsk_mgmt_status;
 };
 
 struct srp_iu {
+	struct list_head	list;
 	u64			dma;
 	void		       *buf;
 	size_t			size;
 	enum dma_data_direction	direction;
-	enum srp_iu_type	type;
 };
 
 #endif /* IB_SRP_H */
diff -druNp linux-libre-2.6.37-gnu1/drivers/input/apm-power.c linux-libre-2.6.38-gnu1/drivers/input/apm-power.c
--- linux-libre-2.6.37-gnu1/drivers/input/apm-power.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/input/apm-power.c	2011-03-14 21:20:32.000000000 -0400
@@ -9,6 +9,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/input.h>
 #include <linux/slab.h>
@@ -23,8 +25,7 @@ static void system_power_event(unsigned
 	switch (keycode) {
 	case KEY_SUSPEND:
 		apm_queue_event(APM_USER_SUSPEND);
-
-		printk(KERN_INFO "apm-power: Requesting system suspend...\n");
+		pr_info("Requesting system suspend...\n");
 		break;
 	default:
 		break;
@@ -65,18 +66,15 @@ static int apmpower_connect(struct input
 
 	error = input_register_handle(handle);
 	if (error) {
-		printk(KERN_ERR
-			"apm-power: Failed to register input power handler, "
-			"error %d\n", error);
+		pr_err("Failed to register input power handler, error %d\n",
+		       error);
 		kfree(handle);
 		return error;
 	}
 
 	error = input_open_device(handle);
 	if (error) {
-		printk(KERN_ERR
-			"apm-power: Failed to open input power device, "
-			"error %d\n", error);
+		pr_err("Failed to open input power device, error %d\n", error);
 		input_unregister_handle(handle);
 		kfree(handle);
 		return error;
diff -druNp linux-libre-2.6.37-gnu1/drivers/input/evbug.c linux-libre-2.6.38-gnu1/drivers/input/evbug.c
--- linux-libre-2.6.37-gnu1/drivers/input/evbug.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/input/evbug.c	2011-03-14 21:20:32.000000000 -0400
@@ -26,6 +26,8 @@
  * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/input.h>
@@ -38,8 +40,8 @@ MODULE_LICENSE("GPL");
 
 static void evbug_event(struct input_handle *handle, unsigned int type, unsigned int code, int value)
 {
-	printk(KERN_DEBUG "evbug.c: Event. Dev: %s, Type: %d, Code: %d, Value: %d\n",
-		dev_name(&handle->dev->dev), type, code, value);
+	printk(KERN_DEBUG pr_fmt("Event. Dev: %s, Type: %d, Code: %d, Value: %d\n"),
+	       dev_name(&handle->dev->dev), type, code, value);
 }
 
 static int evbug_connect(struct input_handler *handler, struct input_dev *dev,
@@ -64,10 +66,10 @@ static int evbug_connect(struct input_ha
 	if (error)
 		goto err_unregister_handle;
 
-	printk(KERN_DEBUG "evbug.c: Connected device: %s (%s at %s)\n",
-		dev_name(&dev->dev),
-		dev->name ?: "unknown",
-		dev->phys ?: "unknown");
+	printk(KERN_DEBUG pr_fmt("Connected device: %s (%s at %s)\n"),
+	       dev_name(&dev->dev),
+	       dev->name ?: "unknown",
+	       dev->phys ?: "unknown");
 
 	return 0;
 
@@ -80,8 +82,8 @@ static int evbug_connect(struct input_ha
 
 static void evbug_disconnect(struct input_handle *handle)
 {
-	printk(KERN_DEBUG "evbug.c: Disconnected device: %s\n",
-		dev_name(&handle->dev->dev));
+	printk(KERN_DEBUG pr_fmt("Disconnected device: %s\n"),
+	       dev_name(&handle->dev->dev));
 
 	input_close_device(handle);
 	input_unregister_handle(handle);
diff -druNp linux-libre-2.6.37-gnu1/drivers/input/evdev.c linux-libre-2.6.38-gnu1/drivers/input/evdev.c
--- linux-libre-2.6.37-gnu1/drivers/input/evdev.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/input/evdev.c	2011-03-14 21:20:32.000000000 -0400
@@ -8,6 +8,8 @@
  * the Free Software Foundation.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #define EVDEV_MINOR_BASE	64
 #define EVDEV_MINORS		32
 #define EVDEV_MIN_BUFFER_SIZE	64U
@@ -522,12 +524,11 @@ static int handle_eviocgbit(struct input
 	if (type == EV_KEY && size == OLD_KEY_MAX) {
 		len = OLD_KEY_MAX;
 		if (printk_timed_ratelimit(&keymax_warn_time, 10 * 1000))
-			printk(KERN_WARNING
-				"evdev.c(EVIOCGBIT): Suspicious buffer size %u, "
-				"limiting output to %zu bytes. See "
-				"http://userweb.kernel.org/~dtor/eviocgbit-bug.html\n",
-				OLD_KEY_MAX,
-				BITS_TO_LONGS(OLD_KEY_MAX) * sizeof(long));
+			pr_warning("(EVIOCGBIT): Suspicious buffer size %u, "
+				   "limiting output to %zu bytes. See "
+				   "http://userweb.kernel.org/~dtor/eviocgbit-bug.html\n",
+				   OLD_KEY_MAX,
+				   BITS_TO_LONGS(OLD_KEY_MAX) * sizeof(long));
 	}
 
 	return bits_to_user(bits, len, size, p, compat_mode);
@@ -686,6 +687,10 @@ static long evdev_do_ioctl(struct file *
 #define EVIOC_MASK_SIZE(nr)	((nr) & ~(_IOC_SIZEMASK << _IOC_SIZESHIFT))
 	switch (EVIOC_MASK_SIZE(cmd)) {
 
+	case EVIOCGPROP(0):
+		return bits_to_user(dev->propbit, INPUT_PROP_MAX,
+				    size, p, compat_mode);
+
 	case EVIOCGKEY(0):
 		return bits_to_user(dev->key, KEY_MAX, size, p, compat_mode);
 
@@ -897,7 +902,7 @@ static int evdev_connect(struct input_ha
 			break;
 
 	if (minor == EVDEV_MINORS) {
-		printk(KERN_ERR "evdev: no more free evdev devices\n");
+		pr_err("no more free evdev devices\n");
 		return -ENFILE;
 	}
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/input/ff-core.c linux-libre-2.6.38-gnu1/drivers/input/ff-core.c
--- linux-libre-2.6.37-gnu1/drivers/input/ff-core.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/input/ff-core.c	2011-03-14 21:20:32.000000000 -0400
@@ -23,7 +23,7 @@
 
 /* #define DEBUG */
 
-#define debug(format, arg...) pr_debug("ff-core: " format "\n", ## arg)
+#define pr_fmt(fmt) KBUILD_BASENAME ": " fmt
 
 #include <linux/input.h>
 #include <linux/module.h>
@@ -116,7 +116,7 @@ int input_ff_upload(struct input_dev *de
 
 	if (effect->type < FF_EFFECT_MIN || effect->type > FF_EFFECT_MAX ||
 	    !test_bit(effect->type, dev->ffbit)) {
-		debug("invalid or not supported effect type in upload");
+		pr_debug("invalid or not supported effect type in upload\n");
 		return -EINVAL;
 	}
 
@@ -124,7 +124,7 @@ int input_ff_upload(struct input_dev *de
 	    (effect->u.periodic.waveform < FF_WAVEFORM_MIN ||
 	     effect->u.periodic.waveform > FF_WAVEFORM_MAX ||
 	     !test_bit(effect->u.periodic.waveform, dev->ffbit))) {
-		debug("invalid or not supported wave form in upload");
+		pr_debug("invalid or not supported wave form in upload\n");
 		return -EINVAL;
 	}
 
@@ -246,7 +246,7 @@ static int flush_effects(struct input_de
 	struct ff_device *ff = dev->ff;
 	int i;
 
-	debug("flushing now");
+	pr_debug("flushing now\n");
 
 	mutex_lock(&ff->mutex);
 
@@ -315,8 +315,7 @@ int input_ff_create(struct input_dev *de
 	int i;
 
 	if (!max_effects) {
-		printk(KERN_ERR
-		       "ff-core: cannot allocate device without any effects\n");
+		pr_err("cannot allocate device without any effects\n");
 		return -EINVAL;
 	}
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/input/ff-memless.c linux-libre-2.6.38-gnu1/drivers/input/ff-memless.c
--- linux-libre-2.6.37-gnu1/drivers/input/ff-memless.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/input/ff-memless.c	2011-03-14 21:20:32.000000000 -0400
@@ -23,7 +23,7 @@
 
 /* #define DEBUG */
 
-#define debug(format, arg...) pr_debug("ff-memless: " format "\n", ## arg)
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
 #include <linux/slab.h>
 #include <linux/input.h>
@@ -129,7 +129,7 @@ static void ml_schedule_timer(struct ml_
 	int events = 0;
 	int i;
 
-	debug("calculating next timer");
+	pr_debug("calculating next timer\n");
 
 	for (i = 0; i < FF_MEMLESS_EFFECTS; i++) {
 
@@ -149,10 +149,10 @@ static void ml_schedule_timer(struct ml_
 	}
 
 	if (!events) {
-		debug("no actions");
+		pr_debug("no actions\n");
 		del_timer(&ml->timer);
 	} else {
-		debug("timer set");
+		pr_debug("timer set\n");
 		mod_timer(&ml->timer, earliest);
 	}
 }
@@ -173,8 +173,8 @@ static int apply_envelope(struct ml_effe
 	if (envelope->attack_length &&
 	    time_before(now,
 			state->play_at + msecs_to_jiffies(envelope->attack_length))) {
-		debug("value = 0x%x, attack_level = 0x%x", value,
-		      envelope->attack_level);
+		pr_debug("value = 0x%x, attack_level = 0x%x\n",
+			 value, envelope->attack_level);
 		time_from_level = jiffies_to_msecs(now - state->play_at);
 		time_of_envelope = envelope->attack_length;
 		envelope_level = min_t(__s16, envelope->attack_level, 0x7fff);
@@ -191,13 +191,13 @@ static int apply_envelope(struct ml_effe
 
 	difference = abs(value) - envelope_level;
 
-	debug("difference = %d", difference);
-	debug("time_from_level = 0x%x", time_from_level);
-	debug("time_of_envelope = 0x%x", time_of_envelope);
+	pr_debug("difference = %d\n", difference);
+	pr_debug("time_from_level = 0x%x\n", time_from_level);
+	pr_debug("time_of_envelope = 0x%x\n", time_of_envelope);
 
 	difference = difference * time_from_level / time_of_envelope;
 
-	debug("difference = %d", difference);
+	pr_debug("difference = %d\n", difference);
 
 	return value < 0 ?
 		-(difference + envelope_level) : (difference + envelope_level);
@@ -215,8 +215,7 @@ static int get_compatible_type(struct ff
 	if (effect_type == FF_PERIODIC && test_bit(FF_RUMBLE, ff->ffbit))
 		return FF_RUMBLE;
 
-	printk(KERN_ERR
-	       "ff-memless: invalid type in get_compatible_type()\n");
+	pr_err("invalid type in get_compatible_type()\n");
 
 	return 0;
 }
@@ -312,7 +311,7 @@ static void ml_combine_effects(struct ff
 		break;
 
 	default:
-		printk(KERN_ERR "ff-memless: invalid type in ml_combine_effects()\n");
+		pr_err("invalid type in ml_combine_effects()\n");
 		break;
 	}
 
@@ -406,7 +405,7 @@ static void ml_effect_timer(unsigned lon
 	struct ml_device *ml = dev->ff->private;
 	unsigned long flags;
 
-	debug("timer: updating effects");
+	pr_debug("timer: updating effects\n");
 
 	spin_lock_irqsave(&dev->event_lock, flags);
 	ml_play_effects(ml);
@@ -438,7 +437,7 @@ static int ml_ff_playback(struct input_d
 	struct ml_effect_state *state = &ml->states[effect_id];
 
 	if (value > 0) {
-		debug("initiated play");
+		pr_debug("initiated play\n");
 
 		__set_bit(FF_EFFECT_STARTED, &state->flags);
 		state->count = value;
@@ -449,7 +448,7 @@ static int ml_ff_playback(struct input_d
 		state->adj_at = state->play_at;
 
 	} else {
-		debug("initiated stop");
+		pr_debug("initiated stop\n");
 
 		if (test_bit(FF_EFFECT_PLAYING, &state->flags))
 			__set_bit(FF_EFFECT_ABORTING, &state->flags);
diff -druNp linux-libre-2.6.37-gnu1/drivers/input/gameport/gameport.c linux-libre-2.6.38-gnu1/drivers/input/gameport/gameport.c
--- linux-libre-2.6.37-gnu1/drivers/input/gameport/gameport.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/input/gameport/gameport.c	2011-03-14 21:20:32.000000000 -0400
@@ -18,13 +18,11 @@
 #include <linux/ioport.h>
 #include <linux/init.h>
 #include <linux/gameport.h>
-#include <linux/wait.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
-#include <linux/kthread.h>
+#include <linux/workqueue.h>
 #include <linux/sched.h>	/* HZ */
 #include <linux/mutex.h>
-#include <linux/freezer.h>
 
 /*#include <asm/io.h>*/
 
@@ -123,7 +121,7 @@ static int gameport_measure_speed(struct
 	}
 
 	gameport_close(gameport);
-	return (cpu_data(raw_smp_processor_id()).loops_per_jiffy *
+	return (this_cpu_read(cpu_info.loops_per_jiffy) *
 		(unsigned long)HZ / (1000 / 50)) / (tx < 1 ? 1 : tx);
 
 #else
@@ -234,58 +232,22 @@ struct gameport_event {
 
 static DEFINE_SPINLOCK(gameport_event_lock);	/* protects gameport_event_list */
 static LIST_HEAD(gameport_event_list);
-static DECLARE_WAIT_QUEUE_HEAD(gameport_wait);
-static struct task_struct *gameport_task;
 
-static int gameport_queue_event(void *object, struct module *owner,
-				enum gameport_event_type event_type)
+static struct gameport_event *gameport_get_event(void)
 {
+	struct gameport_event *event = NULL;
 	unsigned long flags;
-	struct gameport_event *event;
-	int retval = 0;
 
 	spin_lock_irqsave(&gameport_event_lock, flags);
 
-	/*
-	 * Scan event list for the other events for the same gameport port,
-	 * starting with the most recent one. If event is the same we
-	 * do not need add new one. If event is of different type we
-	 * need to add this event and should not look further because
-	 * we need to preseve sequence of distinct events.
-	 */
-	list_for_each_entry_reverse(event, &gameport_event_list, node) {
-		if (event->object == object) {
-			if (event->type == event_type)
-				goto out;
-			break;
-		}
-	}
-
-	event = kmalloc(sizeof(struct gameport_event), GFP_ATOMIC);
-	if (!event) {
-		pr_err("Not enough memory to queue event %d\n", event_type);
-		retval = -ENOMEM;
-		goto out;
-	}
-
-	if (!try_module_get(owner)) {
-		pr_warning("Can't get module reference, dropping event %d\n",
-			   event_type);
-		kfree(event);
-		retval = -EINVAL;
-		goto out;
+	if (!list_empty(&gameport_event_list)) {
+		event = list_first_entry(&gameport_event_list,
+					 struct gameport_event, node);
+		list_del_init(&event->node);
 	}
 
-	event->type = event_type;
-	event->object = object;
-	event->owner = owner;
-
-	list_add_tail(&event->node, &gameport_event_list);
-	wake_up(&gameport_wait);
-
-out:
 	spin_unlock_irqrestore(&gameport_event_lock, flags);
-	return retval;
+	return event;
 }
 
 static void gameport_free_event(struct gameport_event *event)
@@ -319,24 +281,8 @@ static void gameport_remove_duplicate_ev
 	spin_unlock_irqrestore(&gameport_event_lock, flags);
 }
 
-static struct gameport_event *gameport_get_event(void)
-{
-	struct gameport_event *event = NULL;
-	unsigned long flags;
-
-	spin_lock_irqsave(&gameport_event_lock, flags);
-
-	if (!list_empty(&gameport_event_list)) {
-		event = list_first_entry(&gameport_event_list,
-					 struct gameport_event, node);
-		list_del_init(&event->node);
-	}
 
-	spin_unlock_irqrestore(&gameport_event_lock, flags);
-	return event;
-}
-
-static void gameport_handle_event(void)
+static void gameport_handle_events(struct work_struct *work)
 {
 	struct gameport_event *event;
 
@@ -368,6 +314,59 @@ static void gameport_handle_event(void)
 	mutex_unlock(&gameport_mutex);
 }
 
+static DECLARE_WORK(gameport_event_work, gameport_handle_events);
+
+static int gameport_queue_event(void *object, struct module *owner,
+				enum gameport_event_type event_type)
+{
+	unsigned long flags;
+	struct gameport_event *event;
+	int retval = 0;
+
+	spin_lock_irqsave(&gameport_event_lock, flags);
+
+	/*
+	 * Scan event list for the other events for the same gameport port,
+	 * starting with the most recent one. If event is the same we
+	 * do not need add new one. If event is of different type we
+	 * need to add this event and should not look further because
+	 * we need to preserve sequence of distinct events.
+	 */
+	list_for_each_entry_reverse(event, &gameport_event_list, node) {
+		if (event->object == object) {
+			if (event->type == event_type)
+				goto out;
+			break;
+		}
+	}
+
+	event = kmalloc(sizeof(struct gameport_event), GFP_ATOMIC);
+	if (!event) {
+		pr_err("Not enough memory to queue event %d\n", event_type);
+		retval = -ENOMEM;
+		goto out;
+	}
+
+	if (!try_module_get(owner)) {
+		pr_warning("Can't get module reference, dropping event %d\n",
+			   event_type);
+		kfree(event);
+		retval = -EINVAL;
+		goto out;
+	}
+
+	event->type = event_type;
+	event->object = object;
+	event->owner = owner;
+
+	list_add_tail(&event->node, &gameport_event_list);
+	queue_work(system_long_wq, &gameport_event_work);
+
+out:
+	spin_unlock_irqrestore(&gameport_event_lock, flags);
+	return retval;
+}
+
 /*
  * Remove all events that have been submitted for a given object,
  * be it a gameport port or a driver.
@@ -419,19 +418,6 @@ static struct gameport *gameport_get_pen
 	return child;
 }
 
-static int gameport_thread(void *nothing)
-{
-	set_freezable();
-	do {
-		gameport_handle_event();
-		wait_event_freezable(gameport_wait,
-			kthread_should_stop() || !list_empty(&gameport_event_list));
-	} while (!kthread_should_stop());
-
-	return 0;
-}
-
-
 /*
  * Gameport port operations
  */
@@ -814,13 +800,6 @@ static int __init gameport_init(void)
 		return error;
 	}
 
-	gameport_task = kthread_run(gameport_thread, NULL, "kgameportd");
-	if (IS_ERR(gameport_task)) {
-		bus_unregister(&gameport_bus);
-		error = PTR_ERR(gameport_task);
-		pr_err("Failed to start kgameportd, error: %d\n", error);
-		return error;
-	}
 
 	return 0;
 }
@@ -828,7 +807,12 @@ static int __init gameport_init(void)
 static void __exit gameport_exit(void)
 {
 	bus_unregister(&gameport_bus);
-	kthread_stop(gameport_task);
+
+	/*
+	 * There should not be any outstanding events but work may
+	 * still be scheduled so simply cancel it.
+	 */
+	cancel_work_sync(&gameport_event_work);
 }
 
 subsys_initcall(gameport_init);
diff -druNp linux-libre-2.6.37-gnu1/drivers/input/input.c linux-libre-2.6.38-gnu1/drivers/input/input.c
--- linux-libre-2.6.37-gnu1/drivers/input/input.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/input/input.c	2011-03-14 21:20:32.000000000 -0400
@@ -10,9 +10,11 @@
  * the Free Software Foundation.
  */
 
+#define pr_fmt(fmt) KBUILD_BASENAME ": " fmt
+
 #include <linux/init.h>
 #include <linux/types.h>
-#include <linux/input.h>
+#include <linux/input/mt.h>
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/random.h>
@@ -73,7 +75,6 @@ static int input_defuzz_abs_event(int va
  * dev->event_lock held and interrupts disabled.
  */
 static void input_pass_event(struct input_dev *dev,
-			     struct input_handler *src_handler,
 			     unsigned int type, unsigned int code, int value)
 {
 	struct input_handler *handler;
@@ -92,15 +93,6 @@ static void input_pass_event(struct inpu
 				continue;
 
 			handler = handle->handler;
-
-			/*
-			 * If this is the handler that injected this
-			 * particular event we want to skip it to avoid
-			 * filters firing again and again.
-			 */
-			if (handler == src_handler)
-				continue;
-
 			if (!handler->filter) {
 				if (filtered)
 					break;
@@ -130,7 +122,7 @@ static void input_repeat_key(unsigned lo
 	if (test_bit(dev->repeat_key, dev->key) &&
 	    is_event_supported(dev->repeat_key, dev->keybit, KEY_MAX)) {
 
-		input_pass_event(dev, NULL, EV_KEY, dev->repeat_key, 2);
+		input_pass_event(dev, EV_KEY, dev->repeat_key, 2);
 
 		if (dev->sync) {
 			/*
@@ -139,7 +131,7 @@ static void input_repeat_key(unsigned lo
 			 * Otherwise assume that the driver will send
 			 * SYN_REPORT once it's done.
 			 */
-			input_pass_event(dev, NULL, EV_SYN, SYN_REPORT, 1);
+			input_pass_event(dev, EV_SYN, SYN_REPORT, 1);
 		}
 
 		if (dev->rep[REP_PERIOD])
@@ -172,7 +164,6 @@ static void input_stop_autorepeat(struct
 #define INPUT_PASS_TO_ALL	(INPUT_PASS_TO_HANDLERS | INPUT_PASS_TO_DEVICE)
 
 static int input_handle_abs_event(struct input_dev *dev,
-				  struct input_handler *src_handler,
 				  unsigned int code, int *pval)
 {
 	bool is_mt_event;
@@ -216,15 +207,13 @@ static int input_handle_abs_event(struct
 	/* Flush pending "slot" event */
 	if (is_mt_event && dev->slot != input_abs_get_val(dev, ABS_MT_SLOT)) {
 		input_abs_set_val(dev, ABS_MT_SLOT, dev->slot);
-		input_pass_event(dev, src_handler,
-				 EV_ABS, ABS_MT_SLOT, dev->slot);
+		input_pass_event(dev, EV_ABS, ABS_MT_SLOT, dev->slot);
 	}
 
 	return INPUT_PASS_TO_HANDLERS;
 }
 
 static void input_handle_event(struct input_dev *dev,
-			       struct input_handler *src_handler,
 			       unsigned int type, unsigned int code, int value)
 {
 	int disposition = INPUT_IGNORE_EVENT;
@@ -277,8 +266,7 @@ static void input_handle_event(struct in
 
 	case EV_ABS:
 		if (is_event_supported(code, dev->absbit, ABS_MAX))
-			disposition = input_handle_abs_event(dev, src_handler,
-							     code, &value);
+			disposition = input_handle_abs_event(dev, code, &value);
 
 		break;
 
@@ -336,7 +324,7 @@ static void input_handle_event(struct in
 		dev->event(dev, type, code, value);
 
 	if (disposition & INPUT_PASS_TO_HANDLERS)
-		input_pass_event(dev, src_handler, type, code, value);
+		input_pass_event(dev, type, code, value);
 }
 
 /**
@@ -365,7 +353,7 @@ void input_event(struct input_dev *dev,
 
 		spin_lock_irqsave(&dev->event_lock, flags);
 		add_input_randomness(type, code, value);
-		input_handle_event(dev, NULL, type, code, value);
+		input_handle_event(dev, type, code, value);
 		spin_unlock_irqrestore(&dev->event_lock, flags);
 	}
 }
@@ -395,8 +383,7 @@ void input_inject_event(struct input_han
 		rcu_read_lock();
 		grab = rcu_dereference(dev->grab);
 		if (!grab || grab == handle)
-			input_handle_event(dev, handle->handler,
-					   type, code, value);
+			input_handle_event(dev, type, code, value);
 		rcu_read_unlock();
 
 		spin_unlock_irqrestore(&dev->event_lock, flags);
@@ -609,10 +596,10 @@ static void input_dev_release_keys(struc
 		for (code = 0; code <= KEY_MAX; code++) {
 			if (is_event_supported(code, dev->keybit, KEY_MAX) &&
 			    __test_and_clear_bit(code, dev->key)) {
-				input_pass_event(dev, NULL, EV_KEY, code, 0);
+				input_pass_event(dev, EV_KEY, code, 0);
 			}
 		}
-		input_pass_event(dev, NULL, EV_SYN, SYN_REPORT, 1);
+		input_pass_event(dev, EV_SYN, SYN_REPORT, 1);
 	}
 }
 
@@ -887,9 +874,9 @@ int input_set_keycode(struct input_dev *
 	    !is_event_supported(old_keycode, dev->keybit, KEY_MAX) &&
 	    __test_and_clear_bit(old_keycode, dev->key)) {
 
-		input_pass_event(dev, NULL, EV_KEY, old_keycode, 0);
+		input_pass_event(dev, EV_KEY, old_keycode, 0);
 		if (dev->sync)
-			input_pass_event(dev, NULL, EV_SYN, SYN_REPORT, 1);
+			input_pass_event(dev, EV_SYN, SYN_REPORT, 1);
 	}
 
  out:
@@ -958,10 +945,8 @@ static int input_attach_handler(struct i
 
 	error = handler->connect(handler, dev, id);
 	if (error && error != -ENODEV)
-		printk(KERN_ERR
-			"input: failed to attach handler %s to device %s, "
-			"error: %d\n",
-			handler->name, kobject_name(&dev->dev.kobj), error);
+		pr_err("failed to attach handler %s to device %s, error: %d\n",
+		       handler->name, kobject_name(&dev->dev.kobj), error);
 
 	return error;
 }
@@ -1109,6 +1094,8 @@ static int input_devices_seq_show(struct
 		seq_printf(seq, "%s ", handle->name);
 	seq_putc(seq, '\n');
 
+	input_seq_print_bitmap(seq, "PROP", dev->propbit, INPUT_PROP_MAX);
+
 	input_seq_print_bitmap(seq, "EV", dev->evbit, EV_MAX);
 	if (test_bit(EV_KEY, dev->evbit))
 		input_seq_print_bitmap(seq, "KEY", dev->keybit, KEY_MAX);
@@ -1332,11 +1319,26 @@ static ssize_t input_dev_show_modalias(s
 }
 static DEVICE_ATTR(modalias, S_IRUGO, input_dev_show_modalias, NULL);
 
+static int input_print_bitmap(char *buf, int buf_size, unsigned long *bitmap,
+			      int max, int add_cr);
+
+static ssize_t input_dev_show_properties(struct device *dev,
+					 struct device_attribute *attr,
+					 char *buf)
+{
+	struct input_dev *input_dev = to_input_dev(dev);
+	int len = input_print_bitmap(buf, PAGE_SIZE, input_dev->propbit,
+				     INPUT_PROP_MAX, true);
+	return min_t(int, len, PAGE_SIZE);
+}
+static DEVICE_ATTR(properties, S_IRUGO, input_dev_show_properties, NULL);
+
 static struct attribute *input_dev_attrs[] = {
 	&dev_attr_name.attr,
 	&dev_attr_phys.attr,
 	&dev_attr_uniq.attr,
 	&dev_attr_modalias.attr,
+	&dev_attr_properties.attr,
 	NULL
 };
 
@@ -1470,7 +1472,7 @@ static int input_add_uevent_bm_var(struc
 {
 	int len;
 
-	if (add_uevent_var(env, "%s=", name))
+	if (add_uevent_var(env, "%s", name))
 		return -ENOMEM;
 
 	len = input_print_bitmap(&env->buf[env->buflen - 1],
@@ -1536,6 +1538,8 @@ static int input_dev_uevent(struct devic
 	if (dev->uniq)
 		INPUT_ADD_HOTPLUG_VAR("UNIQ=\"%s\"", dev->uniq);
 
+	INPUT_ADD_HOTPLUG_BM_VAR("PROP=", dev->propbit, INPUT_PROP_MAX);
+
 	INPUT_ADD_HOTPLUG_BM_VAR("EV=", dev->evbit, EV_MAX);
 	if (test_bit(EV_KEY, dev->evbit))
 		INPUT_ADD_HOTPLUG_BM_VAR("KEY=", dev->keybit, KEY_MAX);
@@ -1725,52 +1729,6 @@ void input_free_device(struct input_dev
 EXPORT_SYMBOL(input_free_device);
 
 /**
- * input_mt_create_slots() - create MT input slots
- * @dev: input device supporting MT events and finger tracking
- * @num_slots: number of slots used by the device
- *
- * This function allocates all necessary memory for MT slot handling in the
- * input device, and adds ABS_MT_SLOT to the device capabilities. All slots
- * are initially marked as unused by setting ABS_MT_TRACKING_ID to -1.
- */
-int input_mt_create_slots(struct input_dev *dev, unsigned int num_slots)
-{
-	int i;
-
-	if (!num_slots)
-		return 0;
-
-	dev->mt = kcalloc(num_slots, sizeof(struct input_mt_slot), GFP_KERNEL);
-	if (!dev->mt)
-		return -ENOMEM;
-
-	dev->mtsize = num_slots;
-	input_set_abs_params(dev, ABS_MT_SLOT, 0, num_slots - 1, 0, 0);
-
-	/* Mark slots as 'unused' */
-	for (i = 0; i < num_slots; i++)
-		dev->mt[i].abs[ABS_MT_TRACKING_ID - ABS_MT_FIRST] = -1;
-
-	return 0;
-}
-EXPORT_SYMBOL(input_mt_create_slots);
-
-/**
- * input_mt_destroy_slots() - frees the MT slots of the input device
- * @dev: input device with allocated MT slots
- *
- * This function is only needed in error path as the input core will
- * automatically free the MT slots when the device is destroyed.
- */
-void input_mt_destroy_slots(struct input_dev *dev)
-{
-	kfree(dev->mt);
-	dev->mt = NULL;
-	dev->mtsize = 0;
-}
-EXPORT_SYMBOL(input_mt_destroy_slots);
-
-/**
  * input_set_capability - mark device as capable of a certain event
  * @dev: device that is capable of emitting or accepting event
  * @type: type of the event (EV_KEY, EV_REL, etc...)
@@ -1819,9 +1777,8 @@ void input_set_capability(struct input_d
 		break;
 
 	default:
-		printk(KERN_ERR
-			"input_set_capability: unknown type %u (code %u)\n",
-			type, code);
+		pr_err("input_set_capability: unknown type %u (code %u)\n",
+		       type, code);
 		dump_stack();
 		return;
 	}
@@ -1903,8 +1860,9 @@ int input_register_device(struct input_d
 		return error;
 
 	path = kobject_get_path(&dev->dev.kobj, GFP_KERNEL);
-	printk(KERN_INFO "input: %s as %s\n",
-		dev->name ? dev->name : "Unspecified device", path ? path : "N/A");
+	pr_info("%s as %s\n",
+		dev->name ? dev->name : "Unspecified device",
+		path ? path : "N/A");
 	kfree(path);
 
 	error = mutex_lock_interruptible(&input_mutex);
@@ -2186,7 +2144,7 @@ static int __init input_init(void)
 
 	err = class_register(&input_class);
 	if (err) {
-		printk(KERN_ERR "input: unable to register input_dev class\n");
+		pr_err("unable to register input_dev class\n");
 		return err;
 	}
 
@@ -2196,7 +2154,7 @@ static int __init input_init(void)
 
 	err = register_chrdev(INPUT_MAJOR, "input", &input_fops);
 	if (err) {
-		printk(KERN_ERR "input: unable to register char major %d", INPUT_MAJOR);
+		pr_err("unable to register char major %d", INPUT_MAJOR);
 		goto fail2;
 	}
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/input/input-mt.c linux-libre-2.6.38-gnu1/drivers/input/input-mt.c
--- linux-libre-2.6.37-gnu1/drivers/input/input-mt.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/input/input-mt.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,170 @@
+/*
+ * Input Multitouch Library
+ *
+ * Copyright (c) 2008-2010 Henrik Rydberg
+ *
+ * This program is free software; you can 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/input/mt.h>
+#include <linux/slab.h>
+
+#define TRKID_SGN	((TRKID_MAX + 1) >> 1)
+
+/**
+ * input_mt_init_slots() - initialize MT input slots
+ * @dev: input device supporting MT events and finger tracking
+ * @num_slots: number of slots used by the device
+ *
+ * This function allocates all necessary memory for MT slot handling
+ * in the input device, prepares the ABS_MT_SLOT and
+ * ABS_MT_TRACKING_ID events for use and sets up appropriate buffers.
+ * May be called repeatedly. Returns -EINVAL if attempting to
+ * reinitialize with a different number of slots.
+ */
+int input_mt_init_slots(struct input_dev *dev, unsigned int num_slots)
+{
+	int i;
+
+	if (!num_slots)
+		return 0;
+	if (dev->mt)
+		return dev->mtsize != num_slots ? -EINVAL : 0;
+
+	dev->mt = kcalloc(num_slots, sizeof(struct input_mt_slot), GFP_KERNEL);
+	if (!dev->mt)
+		return -ENOMEM;
+
+	dev->mtsize = num_slots;
+	input_set_abs_params(dev, ABS_MT_SLOT, 0, num_slots - 1, 0, 0);
+	input_set_abs_params(dev, ABS_MT_TRACKING_ID, 0, TRKID_MAX, 0, 0);
+	input_set_events_per_packet(dev, 6 * num_slots);
+
+	/* Mark slots as 'unused' */
+	for (i = 0; i < num_slots; i++)
+		input_mt_set_value(&dev->mt[i], ABS_MT_TRACKING_ID, -1);
+
+	return 0;
+}
+EXPORT_SYMBOL(input_mt_init_slots);
+
+/**
+ * input_mt_destroy_slots() - frees the MT slots of the input device
+ * @dev: input device with allocated MT slots
+ *
+ * This function is only needed in error path as the input core will
+ * automatically free the MT slots when the device is destroyed.
+ */
+void input_mt_destroy_slots(struct input_dev *dev)
+{
+	kfree(dev->mt);
+	dev->mt = NULL;
+	dev->mtsize = 0;
+	dev->slot = 0;
+	dev->trkid = 0;
+}
+EXPORT_SYMBOL(input_mt_destroy_slots);
+
+/**
+ * input_mt_report_slot_state() - report contact state
+ * @dev: input device with allocated MT slots
+ * @tool_type: the tool type to use in this slot
+ * @active: true if contact is active, false otherwise
+ *
+ * Reports a contact via ABS_MT_TRACKING_ID, and optionally
+ * ABS_MT_TOOL_TYPE. If active is true and the slot is currently
+ * inactive, or if the tool type is changed, a new tracking id is
+ * assigned to the slot. The tool type is only reported if the
+ * corresponding absbit field is set.
+ */
+void input_mt_report_slot_state(struct input_dev *dev,
+				unsigned int tool_type, bool active)
+{
+	struct input_mt_slot *mt;
+	int id;
+
+	if (!dev->mt || !active) {
+		input_event(dev, EV_ABS, ABS_MT_TRACKING_ID, -1);
+		return;
+	}
+
+	mt = &dev->mt[dev->slot];
+	id = input_mt_get_value(mt, ABS_MT_TRACKING_ID);
+	if (id < 0 || input_mt_get_value(mt, ABS_MT_TOOL_TYPE) != tool_type)
+		id = input_mt_new_trkid(dev);
+
+	input_event(dev, EV_ABS, ABS_MT_TRACKING_ID, id);
+	input_event(dev, EV_ABS, ABS_MT_TOOL_TYPE, tool_type);
+}
+EXPORT_SYMBOL(input_mt_report_slot_state);
+
+/**
+ * input_mt_report_finger_count() - report contact count
+ * @dev: input device with allocated MT slots
+ * @count: the number of contacts
+ *
+ * Reports the contact count via BTN_TOOL_FINGER, BTN_TOOL_DOUBLETAP,
+ * BTN_TOOL_TRIPLETAP and BTN_TOOL_QUADTAP.
+ *
+ * The input core ensures only the KEY events already setup for
+ * this device will produce output.
+ */
+void input_mt_report_finger_count(struct input_dev *dev, int count)
+{
+	input_event(dev, EV_KEY, BTN_TOOL_FINGER, count == 1);
+	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);
+}
+EXPORT_SYMBOL(input_mt_report_finger_count);
+
+/**
+ * input_mt_report_pointer_emulation() - common pointer emulation
+ * @dev: input device with allocated MT slots
+ * @use_count: report number of active contacts as finger count
+ *
+ * Performs legacy pointer emulation via BTN_TOUCH, ABS_X, ABS_Y and
+ * ABS_PRESSURE. Touchpad finger count is emulated if use_count is true.
+ *
+ * The input core ensures only the KEY and ABS axes already setup for
+ * this device will produce output.
+ */
+void input_mt_report_pointer_emulation(struct input_dev *dev, bool use_count)
+{
+	struct input_mt_slot *oldest = 0;
+	int oldid = dev->trkid;
+	int count = 0;
+	int i;
+
+	for (i = 0; i < dev->mtsize; ++i) {
+		struct input_mt_slot *ps = &dev->mt[i];
+		int id = input_mt_get_value(ps, ABS_MT_TRACKING_ID);
+
+		if (id < 0)
+			continue;
+		if ((id - oldid) & TRKID_SGN) {
+			oldest = ps;
+			oldid = id;
+		}
+		count++;
+	}
+
+	input_event(dev, EV_KEY, BTN_TOUCH, count > 0);
+	if (use_count)
+		input_mt_report_finger_count(dev, count);
+
+	if (oldest) {
+		int x = input_mt_get_value(oldest, ABS_MT_POSITION_X);
+		int y = input_mt_get_value(oldest, ABS_MT_POSITION_Y);
+		int p = input_mt_get_value(oldest, ABS_MT_PRESSURE);
+
+		input_event(dev, EV_ABS, ABS_X, x);
+		input_event(dev, EV_ABS, ABS_Y, y);
+		input_event(dev, EV_ABS, ABS_PRESSURE, p);
+	} else {
+		input_event(dev, EV_ABS, ABS_PRESSURE, 0);
+	}
+}
+EXPORT_SYMBOL(input_mt_report_pointer_emulation);
diff -druNp linux-libre-2.6.37-gnu1/drivers/input/input-polldev.c linux-libre-2.6.38-gnu1/drivers/input/input-polldev.c
--- linux-libre-2.6.37-gnu1/drivers/input/input-polldev.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/input/input-polldev.c	2011-03-14 21:20:32.000000000 -0400
@@ -8,6 +8,8 @@
  * the Free Software Foundation.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/jiffies.h>
 #include <linux/slab.h>
 #include <linux/mutex.h>
@@ -33,8 +35,7 @@ static int input_polldev_start_workqueue
 	if (!polldev_users) {
 		polldev_wq = create_singlethread_workqueue("ipolldevd");
 		if (!polldev_wq) {
-			printk(KERN_ERR "input-polldev: failed to create "
-				"ipolldevd workqueue\n");
+			pr_err("failed to create ipolldevd workqueue\n");
 			retval = -ENOMEM;
 			goto out;
 		}
diff -druNp linux-libre-2.6.37-gnu1/drivers/input/joydev.c linux-libre-2.6.38-gnu1/drivers/input/joydev.c
--- linux-libre-2.6.37-gnu1/drivers/input/joydev.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/input/joydev.c	2011-03-14 21:20:32.000000000 -0400
@@ -10,6 +10,8 @@
  * (at your option) any later version.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <asm/io.h>
 #include <asm/system.h>
 #include <linux/delay.h>
@@ -806,7 +808,7 @@ static int joydev_connect(struct input_h
 			break;
 
 	if (minor == JOYDEV_MINORS) {
-		printk(KERN_ERR "joydev: no more free joydev devices\n");
+		pr_err("no more free joydev devices\n");
 		return -ENFILE;
 	}
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/input/joystick/as5011.c linux-libre-2.6.38-gnu1/drivers/input/joystick/as5011.c
--- linux-libre-2.6.37-gnu1/drivers/input/joystick/as5011.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/input/joystick/as5011.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,367 @@
+/*
+ * Copyright (c) 2010, 2011 Fabien Marteau <fabien.marteau@armadeus.com>
+ * Sponsored by ARMadeus 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
+ *
+ * Driver for Austria Microsystems joysticks AS5011
+ *
+ * TODO:
+ *	- Power on the chip when open() and power down when close()
+ *	- Manage power mode
+ */
+
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/input.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+#include <linux/input/as5011.h>
+#include <linux/slab.h>
+
+#define DRIVER_DESC "Driver for Austria Microsystems AS5011 joystick"
+#define MODULE_DEVICE_ALIAS "as5011"
+
+MODULE_AUTHOR("Fabien Marteau <fabien.marteau@armadeus.com>");
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
+
+/* registers */
+#define AS5011_CTRL1		0x76
+#define AS5011_CTRL2		0x75
+#define AS5011_XP		0x43
+#define AS5011_XN		0x44
+#define AS5011_YP		0x53
+#define AS5011_YN		0x54
+#define AS5011_X_REG		0x41
+#define AS5011_Y_REG		0x42
+#define AS5011_X_RES_INT	0x51
+#define AS5011_Y_RES_INT	0x52
+
+/* CTRL1 bits */
+#define AS5011_CTRL1_LP_PULSED		0x80
+#define AS5011_CTRL1_LP_ACTIVE		0x40
+#define AS5011_CTRL1_LP_CONTINUE	0x20
+#define AS5011_CTRL1_INT_WUP_EN		0x10
+#define AS5011_CTRL1_INT_ACT_EN		0x08
+#define AS5011_CTRL1_EXT_CLK_EN		0x04
+#define AS5011_CTRL1_SOFT_RST		0x02
+#define AS5011_CTRL1_DATA_VALID		0x01
+
+/* CTRL2 bits */
+#define AS5011_CTRL2_EXT_SAMPLE_EN	0x08
+#define AS5011_CTRL2_RC_BIAS_ON		0x04
+#define AS5011_CTRL2_INV_SPINNING	0x02
+
+#define AS5011_MAX_AXIS	80
+#define AS5011_MIN_AXIS	(-80)
+#define AS5011_FUZZ	8
+#define AS5011_FLAT	40
+
+struct as5011_device {
+	struct input_dev *input_dev;
+	struct i2c_client *i2c_client;
+	unsigned int button_gpio;
+	unsigned int button_irq;
+	unsigned int axis_irq;
+};
+
+static int as5011_i2c_write(struct i2c_client *client,
+			    uint8_t aregaddr,
+			    uint8_t avalue)
+{
+	uint8_t data[2] = { aregaddr, avalue };
+	struct i2c_msg msg = {
+		client->addr, I2C_M_IGNORE_NAK, 2, (uint8_t *)data
+	};
+	int error;
+
+	error = i2c_transfer(client->adapter, &msg, 1);
+	return error < 0 ? error : 0;
+}
+
+static int as5011_i2c_read(struct i2c_client *client,
+			   uint8_t aregaddr, signed char *value)
+{
+	uint8_t data[2] = { aregaddr };
+	struct i2c_msg msg_set[2] = {
+		{ client->addr, I2C_M_REV_DIR_ADDR, 1, (uint8_t *)data },
+		{ client->addr, I2C_M_RD | I2C_M_NOSTART, 1, (uint8_t *)data }
+	};
+	int error;
+
+	error = i2c_transfer(client->adapter, msg_set, 2);
+	if (error < 0)
+		return error;
+
+	*value = data[0] & 0x80 ? -1 * (1 + ~data[0]) : data[0];
+	return 0;
+}
+
+static irqreturn_t as5011_button_interrupt(int irq, void *dev_id)
+{
+	struct as5011_device *as5011 = dev_id;
+	int val = gpio_get_value_cansleep(as5011->button_gpio);
+
+	input_report_key(as5011->input_dev, BTN_JOYSTICK, !val);
+	input_sync(as5011->input_dev);
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t as5011_axis_interrupt(int irq, void *dev_id)
+{
+	struct as5011_device *as5011 = dev_id;
+	int error;
+	signed char x, y;
+
+	error = as5011_i2c_read(as5011->i2c_client, AS5011_X_RES_INT, &x);
+	if (error < 0)
+		goto out;
+
+	error = as5011_i2c_read(as5011->i2c_client, AS5011_Y_RES_INT, &y);
+	if (error < 0)
+		goto out;
+
+	input_report_abs(as5011->input_dev, ABS_X, x);
+	input_report_abs(as5011->input_dev, ABS_Y, y);
+	input_sync(as5011->input_dev);
+
+out:
+	return IRQ_HANDLED;
+}
+
+static int __devinit as5011_configure_chip(struct as5011_device *as5011,
+				const struct as5011_platform_data *plat_dat)
+{
+	struct i2c_client *client = as5011->i2c_client;
+	int error;
+	signed char value;
+
+	/* chip soft reset */
+	error = as5011_i2c_write(client, AS5011_CTRL1,
+				 AS5011_CTRL1_SOFT_RST);
+	if (error < 0) {
+		dev_err(&client->dev, "Soft reset failed\n");
+		return error;
+	}
+
+	mdelay(10);
+
+	error = as5011_i2c_write(client, AS5011_CTRL1,
+				 AS5011_CTRL1_LP_PULSED |
+				 AS5011_CTRL1_LP_ACTIVE |
+				 AS5011_CTRL1_INT_ACT_EN);
+	if (error < 0) {
+		dev_err(&client->dev, "Power config failed\n");
+		return error;
+	}
+
+	error = as5011_i2c_write(client, AS5011_CTRL2,
+				 AS5011_CTRL2_INV_SPINNING);
+	if (error < 0) {
+		dev_err(&client->dev, "Can't invert spinning\n");
+		return error;
+	}
+
+	/* write threshold */
+	error = as5011_i2c_write(client, AS5011_XP, plat_dat->xp);
+	if (error < 0) {
+		dev_err(&client->dev, "Can't write threshold\n");
+		return error;
+	}
+
+	error = as5011_i2c_write(client, AS5011_XN, plat_dat->xn);
+	if (error < 0) {
+		dev_err(&client->dev, "Can't write threshold\n");
+		return error;
+	}
+
+	error = as5011_i2c_write(client, AS5011_YP, plat_dat->yp);
+	if (error < 0) {
+		dev_err(&client->dev, "Can't write threshold\n");
+		return error;
+	}
+
+	error = as5011_i2c_write(client, AS5011_YN, plat_dat->yn);
+	if (error < 0) {
+		dev_err(&client->dev, "Can't write threshold\n");
+		return error;
+	}
+
+	/* to free irq gpio in chip */
+	error = as5011_i2c_read(client, AS5011_X_RES_INT, &value);
+	if (error < 0) {
+		dev_err(&client->dev, "Can't read i2c X resolution value\n");
+		return error;
+	}
+
+	return 0;
+}
+
+static int __devinit as5011_probe(struct i2c_client *client,
+				const struct i2c_device_id *id)
+{
+	const struct as5011_platform_data *plat_data;
+	struct as5011_device *as5011;
+	struct input_dev *input_dev;
+	int irq;
+	int error;
+
+	plat_data = client->dev.platform_data;
+	if (!plat_data)
+		return -EINVAL;
+
+	if (!plat_data->axis_irq) {
+		dev_err(&client->dev, "No axis IRQ?\n");
+		return -EINVAL;
+	}
+
+	if (!i2c_check_functionality(client->adapter,
+				     I2C_FUNC_PROTOCOL_MANGLING)) {
+		dev_err(&client->dev,
+			"need i2c bus that supports protocol mangling\n");
+		return -ENODEV;
+	}
+
+	as5011 = kmalloc(sizeof(struct as5011_device), GFP_KERNEL);
+	input_dev = input_allocate_device();
+	if (!as5011 || !input_dev) {
+		dev_err(&client->dev,
+			"Can't allocate memory for device structure\n");
+		error = -ENOMEM;
+		goto err_free_mem;
+	}
+
+	as5011->i2c_client = client;
+	as5011->input_dev = input_dev;
+	as5011->button_gpio = plat_data->button_gpio;
+	as5011->axis_irq = plat_data->axis_irq;
+
+	input_dev->name = "Austria Microsystem as5011 joystick";
+	input_dev->id.bustype = BUS_I2C;
+	input_dev->dev.parent = &client->dev;
+
+	__set_bit(EV_KEY, input_dev->evbit);
+	__set_bit(EV_ABS, input_dev->evbit);
+	__set_bit(BTN_JOYSTICK, input_dev->keybit);
+
+	input_set_abs_params(input_dev, ABS_X,
+		AS5011_MIN_AXIS, AS5011_MAX_AXIS, AS5011_FUZZ, AS5011_FLAT);
+	input_set_abs_params(as5011->input_dev, ABS_Y,
+		AS5011_MIN_AXIS, AS5011_MAX_AXIS, AS5011_FUZZ, AS5011_FLAT);
+
+	error = gpio_request(as5011->button_gpio, "AS5011 button");
+	if (error < 0) {
+		dev_err(&client->dev, "Failed to request button gpio\n");
+		goto err_free_mem;
+	}
+
+	irq = gpio_to_irq(as5011->button_gpio);
+	if (irq < 0) {
+		dev_err(&client->dev,
+			"Failed to get irq number for button gpio\n");
+		goto err_free_button_gpio;
+	}
+
+	as5011->button_irq = irq;
+
+	error = request_threaded_irq(as5011->button_irq,
+				     NULL, as5011_button_interrupt,
+				     IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+				     "as5011_button", as5011);
+	if (error < 0) {
+		dev_err(&client->dev,
+			"Can't allocate button irq %d\n", as5011->button_irq);
+		goto err_free_button_gpio;
+	}
+
+	error = as5011_configure_chip(as5011, plat_data);
+	if (error)
+		goto err_free_button_irq;
+
+	error = request_threaded_irq(as5011->axis_irq, NULL,
+				     as5011_axis_interrupt,
+				     plat_data->axis_irqflags,
+				     "as5011_joystick", as5011);
+	if (error) {
+		dev_err(&client->dev,
+			"Can't allocate axis irq %d\n", plat_data->axis_irq);
+		goto err_free_button_irq;
+	}
+
+	error = input_register_device(as5011->input_dev);
+	if (error) {
+		dev_err(&client->dev, "Failed to register input device\n");
+		goto err_free_axis_irq;
+	}
+
+	i2c_set_clientdata(client, as5011);
+
+	return 0;
+
+err_free_axis_irq:
+	free_irq(as5011->axis_irq, as5011);
+err_free_button_irq:
+	free_irq(as5011->button_irq, as5011);
+err_free_button_gpio:
+	gpio_free(as5011->button_gpio);
+err_free_mem:
+	input_free_device(input_dev);
+	kfree(as5011);
+
+	return error;
+}
+
+static int __devexit as5011_remove(struct i2c_client *client)
+{
+	struct as5011_device *as5011 = i2c_get_clientdata(client);
+
+	free_irq(as5011->axis_irq, as5011);
+	free_irq(as5011->button_irq, as5011);
+	gpio_free(as5011->button_gpio);
+
+	input_unregister_device(as5011->input_dev);
+	kfree(as5011);
+
+	return 0;
+}
+
+static const struct i2c_device_id as5011_id[] = {
+	{ MODULE_DEVICE_ALIAS, 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, as5011_id);
+
+static struct i2c_driver as5011_driver = {
+	.driver = {
+		.name = "as5011",
+	},
+	.probe		= as5011_probe,
+	.remove		= __devexit_p(as5011_remove),
+	.id_table	= as5011_id,
+};
+
+static int __init as5011_init(void)
+{
+	return i2c_add_driver(&as5011_driver);
+}
+module_init(as5011_init);
+
+static void __exit as5011_exit(void)
+{
+	i2c_del_driver(&as5011_driver);
+}
+module_exit(as5011_exit);
diff -druNp linux-libre-2.6.37-gnu1/drivers/input/joystick/iforce/Makefile linux-libre-2.6.38-gnu1/drivers/input/joystick/iforce/Makefile
--- linux-libre-2.6.37-gnu1/drivers/input/joystick/iforce/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/input/joystick/iforce/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -4,17 +4,8 @@
 # By Johann Deneux <johann.deneux@gmail.com>
 #
 
-# Goal definition
-iforce-objs	:= iforce-ff.o iforce-main.o iforce-packets.o
-
 obj-$(CONFIG_JOYSTICK_IFORCE)	+= iforce.o
 
-ifeq ($(CONFIG_JOYSTICK_IFORCE_232),y)
-	iforce-objs += iforce-serio.o
-endif
-
-ifeq ($(CONFIG_JOYSTICK_IFORCE_USB),y)
-	iforce-objs += iforce-usb.o
-endif
-
-EXTRA_CFLAGS = -Werror-implicit-function-declaration
+iforce-y := iforce-ff.o iforce-main.o iforce-packets.o
+iforce-$(CONFIG_JOYSTICK_IFORCE_232)	+= iforce-serio.o
+iforce-$(CONFIG_JOYSTICK_IFORCE_USB)	+= iforce-usb.o
diff -druNp linux-libre-2.6.37-gnu1/drivers/input/joystick/Kconfig linux-libre-2.6.38-gnu1/drivers/input/joystick/Kconfig
--- linux-libre-2.6.37-gnu1/drivers/input/joystick/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/input/joystick/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -255,6 +255,16 @@ config JOYSTICK_AMIGA
 	  To compile this driver as a module, choose M here: the
 	  module will be called amijoy.
 
+config JOYSTICK_AS5011
+	tristate "Austria Microsystem AS5011 joystick"
+	depends on I2C
+	help
+	  Say Y here if you have an AS5011 digital joystick connected to your
+	  system.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called as5011.
+
 config JOYSTICK_JOYDUMP
 	tristate "Gameport data dumper"
 	select GAMEPORT
diff -druNp linux-libre-2.6.37-gnu1/drivers/input/joystick/Makefile linux-libre-2.6.38-gnu1/drivers/input/joystick/Makefile
--- linux-libre-2.6.37-gnu1/drivers/input/joystick/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/input/joystick/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -7,6 +7,7 @@
 obj-$(CONFIG_JOYSTICK_A3D)		+= a3d.o
 obj-$(CONFIG_JOYSTICK_ADI)		+= adi.o
 obj-$(CONFIG_JOYSTICK_AMIGA)		+= amijoy.o
+obj-$(CONFIG_JOYSTICK_AS5011)		+= as5011.o
 obj-$(CONFIG_JOYSTICK_ANALOG)		+= analog.o
 obj-$(CONFIG_JOYSTICK_COBRA)		+= cobra.o
 obj-$(CONFIG_JOYSTICK_DB9)		+= db9.o
diff -druNp linux-libre-2.6.37-gnu1/drivers/input/joystick/xpad.c linux-libre-2.6.38-gnu1/drivers/input/joystick/xpad.c
--- linux-libre-2.6.37-gnu1/drivers/input/joystick/xpad.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/input/joystick/xpad.c	2011-03-14 21:20:32.000000000 -0400
@@ -543,21 +543,25 @@ exit:
 static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad)
 {
 	struct usb_endpoint_descriptor *ep_irq_out;
-	int error = -ENOMEM;
+	int error;
 
 	if (xpad->xtype != XTYPE_XBOX360 && xpad->xtype != XTYPE_XBOX)
 		return 0;
 
 	xpad->odata = usb_alloc_coherent(xpad->udev, XPAD_PKT_LEN,
 					 GFP_KERNEL, &xpad->odata_dma);
-	if (!xpad->odata)
+	if (!xpad->odata) {
+		error = -ENOMEM;
 		goto fail1;
+	}
 
 	mutex_init(&xpad->odata_mutex);
 
 	xpad->irq_out = usb_alloc_urb(0, GFP_KERNEL);
-	if (!xpad->irq_out)
+	if (!xpad->irq_out) {
+		error = -ENOMEM;
 		goto fail2;
+	}
 
 	ep_irq_out = &intf->cur_altsetting->endpoint[1].desc;
 	usb_fill_int_urb(xpad->irq_out, xpad->udev,
@@ -728,7 +732,7 @@ static void xpad_led_disconnect(struct u
 
 	if (xpad_led) {
 		led_classdev_unregister(&xpad_led->led_cdev);
-		kfree(xpad_led->name);
+		kfree(xpad_led);
 	}
 }
 #else
@@ -756,8 +760,9 @@ static void xpad_close(struct input_dev
 {
 	struct usb_xpad *xpad = input_get_drvdata(dev);
 
-	if(xpad->xtype != XTYPE_XBOX360W)
+	if (xpad->xtype != XTYPE_XBOX360W)
 		usb_kill_urb(xpad->irq_in);
+
 	xpad_stop_output(xpad);
 }
 
@@ -789,8 +794,7 @@ static int xpad_probe(struct usb_interfa
 	struct usb_xpad *xpad;
 	struct input_dev *input_dev;
 	struct usb_endpoint_descriptor *ep_irq_in;
-	int i;
-	int error = -ENOMEM;
+	int i, error;
 
 	for (i = 0; xpad_device[i].idVendor; i++) {
 		if ((le16_to_cpu(udev->descriptor.idVendor) == xpad_device[i].idVendor) &&
@@ -800,17 +804,23 @@ static int xpad_probe(struct usb_interfa
 
 	xpad = kzalloc(sizeof(struct usb_xpad), GFP_KERNEL);
 	input_dev = input_allocate_device();
-	if (!xpad || !input_dev)
+	if (!xpad || !input_dev) {
+		error = -ENOMEM;
 		goto fail1;
+	}
 
 	xpad->idata = usb_alloc_coherent(udev, XPAD_PKT_LEN,
 					 GFP_KERNEL, &xpad->idata_dma);
-	if (!xpad->idata)
+	if (!xpad->idata) {
+		error = -ENOMEM;
 		goto fail1;
+	}
 
 	xpad->irq_in = usb_alloc_urb(0, GFP_KERNEL);
-	if (!xpad->irq_in)
+	if (!xpad->irq_in) {
+		error = -ENOMEM;
 		goto fail2;
+	}
 
 	xpad->udev = udev;
 	xpad->mapping = xpad_device[i].mapping;
@@ -887,15 +897,15 @@ static int xpad_probe(struct usb_interfa
 
 	error = xpad_init_output(intf, xpad);
 	if (error)
-		goto fail2;
+		goto fail3;
 
 	error = xpad_init_ff(xpad);
 	if (error)
-		goto fail3;
+		goto fail4;
 
 	error = xpad_led_probe(xpad);
 	if (error)
-		goto fail3;
+		goto fail5;
 
 	ep_irq_in = &intf->cur_altsetting->endpoint[0].desc;
 	usb_fill_int_urb(xpad->irq_in, udev,
@@ -907,34 +917,26 @@ static int xpad_probe(struct usb_interfa
 
 	error = input_register_device(xpad->dev);
 	if (error)
-		goto fail4;
+		goto fail6;
 
 	usb_set_intfdata(intf, xpad);
 
-	/*
-	 * Submit the int URB immediatly rather than waiting for open
-	 * because we get status messages from the device whether
-	 * or not any controllers are attached.  In fact, it's
-	 * exactly the message that a controller has arrived that
-	 * we're waiting for.
-	 */
 	if (xpad->xtype == XTYPE_XBOX360W) {
-		xpad->irq_in->dev = xpad->udev;
-		error = usb_submit_urb(xpad->irq_in, GFP_KERNEL);
-		if (error)
-			goto fail4;
-
 		/*
 		 * Setup the message to set the LEDs on the
 		 * controller when it shows up
 		 */
 		xpad->bulk_out = usb_alloc_urb(0, GFP_KERNEL);
-		if(!xpad->bulk_out)
-			goto fail5;
+		if (!xpad->bulk_out) {
+			error = -ENOMEM;
+			goto fail7;
+		}
 
 		xpad->bdata = kzalloc(XPAD_PKT_LEN, GFP_KERNEL);
-		if(!xpad->bdata)
-			goto fail6;
+		if (!xpad->bdata) {
+			error = -ENOMEM;
+			goto fail8;
+		}
 
 		xpad->bdata[2] = 0x08;
 		switch (intf->cur_altsetting->desc.bInterfaceNumber) {
@@ -955,14 +957,31 @@ static int xpad_probe(struct usb_interfa
 		usb_fill_bulk_urb(xpad->bulk_out, udev,
 				usb_sndbulkpipe(udev, ep_irq_in->bEndpointAddress),
 				xpad->bdata, XPAD_PKT_LEN, xpad_bulk_out, xpad);
+
+		/*
+		 * Submit the int URB immediately rather than waiting for open
+		 * because we get status messages from the device whether
+		 * or not any controllers are attached.  In fact, it's
+		 * exactly the message that a controller has arrived that
+		 * we're waiting for.
+		 */
+		xpad->irq_in->dev = xpad->udev;
+		error = usb_submit_urb(xpad->irq_in, GFP_KERNEL);
+		if (error)
+			goto fail9;
 	}
 
 	return 0;
 
- fail6:	usb_free_urb(xpad->bulk_out);
- fail5:	usb_kill_urb(xpad->irq_in);
- fail4:	usb_free_urb(xpad->irq_in);
- fail3:	xpad_deinit_output(xpad);
+ fail9:	kfree(xpad->bdata);
+ fail8:	usb_free_urb(xpad->bulk_out);
+ fail7:	input_unregister_device(input_dev);
+	input_dev = NULL;
+ fail6:	xpad_led_disconnect(xpad);
+ fail5:	if (input_dev)
+		input_ff_destroy(input_dev);
+ fail4:	xpad_deinit_output(xpad);
+ fail3:	usb_free_urb(xpad->irq_in);
  fail2:	usb_free_coherent(udev, XPAD_PKT_LEN, xpad->idata, xpad->idata_dma);
  fail1:	input_free_device(input_dev);
 	kfree(xpad);
@@ -974,21 +993,24 @@ static void xpad_disconnect(struct usb_i
 {
 	struct usb_xpad *xpad = usb_get_intfdata (intf);
 
-	usb_set_intfdata(intf, NULL);
-	if (xpad) {
-		xpad_led_disconnect(xpad);
-		input_unregister_device(xpad->dev);
-		xpad_deinit_output(xpad);
-		if (xpad->xtype == XTYPE_XBOX360W) {
-			usb_kill_urb(xpad->bulk_out);
-			usb_free_urb(xpad->bulk_out);
-			usb_kill_urb(xpad->irq_in);
-		}
-		usb_free_urb(xpad->irq_in);
-		usb_free_coherent(xpad->udev, XPAD_PKT_LEN,
-				xpad->idata, xpad->idata_dma);
-		kfree(xpad);
+	xpad_led_disconnect(xpad);
+	input_unregister_device(xpad->dev);
+	xpad_deinit_output(xpad);
+
+	if (xpad->xtype == XTYPE_XBOX360W) {
+		usb_kill_urb(xpad->bulk_out);
+		usb_free_urb(xpad->bulk_out);
+		usb_kill_urb(xpad->irq_in);
 	}
+
+	usb_free_urb(xpad->irq_in);
+	usb_free_coherent(xpad->udev, XPAD_PKT_LEN,
+			xpad->idata, xpad->idata_dma);
+
+	kfree(xpad->bdata);
+	kfree(xpad);
+
+	usb_set_intfdata(intf, NULL);
 }
 
 static struct usb_driver xpad_driver = {
@@ -1000,10 +1022,7 @@ static struct usb_driver xpad_driver = {
 
 static int __init usb_xpad_init(void)
 {
-	int result = usb_register(&xpad_driver);
-	if (result == 0)
-		printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_DESC "\n");
-	return result;
+	return usb_register(&xpad_driver);
 }
 
 static void __exit usb_xpad_exit(void)
diff -druNp linux-libre-2.6.37-gnu1/drivers/input/Kconfig linux-libre-2.6.38-gnu1/drivers/input/Kconfig
--- linux-libre-2.6.37-gnu1/drivers/input/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/input/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -6,7 +6,7 @@ menu "Input device support"
 	depends on !S390
 
 config INPUT
-	tristate "Generic input layer (needed for keyboard, mouse, ...)" if EMBEDDED
+	tristate "Generic input layer (needed for keyboard, mouse, ...)" if EXPERT
 	default y
 	help
 	  Say Y here if you have any input device (mouse, keyboard, tablet,
@@ -67,7 +67,7 @@ config INPUT_SPARSEKMAP
 comment "Userland interfaces"
 
 config INPUT_MOUSEDEV
-	tristate "Mouse interface" if EMBEDDED
+	tristate "Mouse interface" if EXPERT
 	default y
 	help
 	  Say Y here if you want your mouse to be accessible as char devices
@@ -150,7 +150,7 @@ config INPUT_EVBUG
 	  module will be called evbug.
 
 config INPUT_APMPOWER
-	tristate "Input Power Event -> APM Bridge" if EMBEDDED
+	tristate "Input Power Event -> APM Bridge" if EXPERT
 	depends on INPUT && APM_EMULATION
 	help
 	  Say Y here if you want suspend key events to trigger a user
diff -druNp linux-libre-2.6.37-gnu1/drivers/input/keyboard/aaed2000_kbd.c linux-libre-2.6.38-gnu1/drivers/input/keyboard/aaed2000_kbd.c
--- linux-libre-2.6.37-gnu1/drivers/input/keyboard/aaed2000_kbd.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/input/keyboard/aaed2000_kbd.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,186 +0,0 @@
-/*
- *  Keyboard driver for the AAED-2000 dev board
- *
- *  Copyright (c) 2006 Nicolas Bellido Y Ortega
- *
- *  Based on corgikbd.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/delay.h>
-#include <linux/platform_device.h>
-#include <linux/init.h>
-#include <linux/input-polldev.h>
-#include <linux/interrupt.h>
-#include <linux/jiffies.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-
-#include <mach/hardware.h>
-#include <mach/aaed2000.h>
-
-#define KB_ROWS			12
-#define KB_COLS			8
-#define KB_ROWMASK(r)		(1 << (r))
-#define SCANCODE(r,c)		(((c) * KB_ROWS) + (r))
-#define NR_SCANCODES		(KB_COLS * KB_ROWS)
-
-#define SCAN_INTERVAL		(50) /* ms */
-#define KB_ACTIVATE_DELAY	(20) /* us */
-
-static unsigned char aaedkbd_keycode[NR_SCANCODES] = {
-	KEY_9, KEY_0, KEY_MINUS, KEY_EQUAL, KEY_BACKSPACE, 0, KEY_SPACE, KEY_KP6, 0, KEY_KPDOT, 0, 0,
-	KEY_K, KEY_M, KEY_O, KEY_DOT, KEY_SLASH, 0, KEY_F, 0, 0, 0, KEY_LEFTSHIFT, 0,
-	KEY_I, KEY_P, KEY_LEFTBRACE, KEY_RIGHTBRACE, KEY_BACKSLASH, 0, 0, 0, 0, 0, KEY_RIGHTSHIFT, 0,
-	KEY_8, KEY_L, KEY_SEMICOLON, KEY_APOSTROPHE, KEY_ENTER, 0, 0, 0, 0, 0, 0, 0,
-	KEY_J, KEY_H, KEY_B, KEY_KP8, KEY_KP4, 0, KEY_C, KEY_D, KEY_S, KEY_A, 0, KEY_CAPSLOCK,
-	KEY_Y, KEY_U, KEY_N, KEY_T, 0, 0, KEY_R, KEY_E, KEY_W, KEY_Q, 0, KEY_TAB,
-	KEY_7, KEY_6, KEY_G, 0, KEY_5, 0, KEY_4, KEY_3, KEY_2, KEY_1, 0, KEY_GRAVE,
-	0, 0, KEY_COMMA, 0, KEY_KP2, 0, KEY_V, KEY_LEFTALT, KEY_X, KEY_Z, 0, KEY_LEFTCTRL
-};
-
-struct aaedkbd {
-	unsigned char keycode[ARRAY_SIZE(aaedkbd_keycode)];
-	struct input_polled_dev *poll_dev;
-	int kbdscan_state[KB_COLS];
-	int kbdscan_count[KB_COLS];
-};
-
-#define KBDSCAN_STABLE_COUNT 2
-
-static void aaedkbd_report_col(struct aaedkbd *aaedkbd,
-				unsigned int col, unsigned int rowd)
-{
-	unsigned int scancode, pressed;
-	unsigned int row;
-
-	for (row = 0; row < KB_ROWS; row++) {
-		scancode = SCANCODE(row, col);
-		pressed = rowd & KB_ROWMASK(row);
-
-		input_report_key(aaedkbd->poll_dev->input,
-				 aaedkbd->keycode[scancode], pressed);
-	}
-}
-
-/* Scan the hardware keyboard and push any changes up through the input layer */
-static void aaedkbd_poll(struct input_polled_dev *dev)
-{
-	struct aaedkbd *aaedkbd = dev->private;
-	unsigned int col, rowd;
-
-	col = 0;
-	do {
-		AAEC_GPIO_KSCAN = col + 8;
-		udelay(KB_ACTIVATE_DELAY);
-		rowd = AAED_EXT_GPIO & AAED_EGPIO_KBD_SCAN;
-
-		if (rowd != aaedkbd->kbdscan_state[col]) {
-			aaedkbd->kbdscan_count[col] = 0;
-			aaedkbd->kbdscan_state[col] = rowd;
-		} else if (++aaedkbd->kbdscan_count[col] >= KBDSCAN_STABLE_COUNT) {
-			aaedkbd_report_col(aaedkbd, col, rowd);
-			col++;
-		}
-	} while (col < KB_COLS);
-
-	AAEC_GPIO_KSCAN = 0x07;
-	input_sync(dev->input);
-}
-
-static int __devinit aaedkbd_probe(struct platform_device *pdev)
-{
-	struct aaedkbd *aaedkbd;
-	struct input_polled_dev *poll_dev;
-	struct input_dev *input_dev;
-	int i;
-	int error;
-
-	aaedkbd = kzalloc(sizeof(struct aaedkbd), GFP_KERNEL);
-	poll_dev = input_allocate_polled_device();
-	if (!aaedkbd || !poll_dev) {
-		error = -ENOMEM;
-		goto fail;
-	}
-
-	platform_set_drvdata(pdev, aaedkbd);
-
-	aaedkbd->poll_dev = poll_dev;
-	memcpy(aaedkbd->keycode, aaedkbd_keycode, sizeof(aaedkbd->keycode));
-
-	poll_dev->private = aaedkbd;
-	poll_dev->poll = aaedkbd_poll;
-	poll_dev->poll_interval = SCAN_INTERVAL;
-
-	input_dev = poll_dev->input;
-	input_dev->name = "AAED-2000 Keyboard";
-	input_dev->phys = "aaedkbd/input0";
-	input_dev->id.bustype = BUS_HOST;
-	input_dev->id.vendor = 0x0001;
-	input_dev->id.product = 0x0001;
-	input_dev->id.version = 0x0100;
-	input_dev->dev.parent = &pdev->dev;
-
-	input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP);
-	input_dev->keycode = aaedkbd->keycode;
-	input_dev->keycodesize = sizeof(unsigned char);
-	input_dev->keycodemax = ARRAY_SIZE(aaedkbd_keycode);
-
-	for (i = 0; i < ARRAY_SIZE(aaedkbd_keycode); i++)
-		set_bit(aaedkbd->keycode[i], input_dev->keybit);
-	clear_bit(0, input_dev->keybit);
-
-	error = input_register_polled_device(aaedkbd->poll_dev);
-	if (error)
-		goto fail;
-
-	return 0;
-
- fail:	kfree(aaedkbd);
-	input_free_polled_device(poll_dev);
-	return error;
-}
-
-static int __devexit aaedkbd_remove(struct platform_device *pdev)
-{
-	struct aaedkbd *aaedkbd = platform_get_drvdata(pdev);
-
-	input_unregister_polled_device(aaedkbd->poll_dev);
-	input_free_polled_device(aaedkbd->poll_dev);
-	kfree(aaedkbd);
-
-	return 0;
-}
-
-/* work with hotplug and coldplug */
-MODULE_ALIAS("platform:aaed2000-keyboard");
-
-static struct platform_driver aaedkbd_driver = {
-	.probe		= aaedkbd_probe,
-	.remove		= __devexit_p(aaedkbd_remove),
-	.driver		= {
-		.name	= "aaed2000-keyboard",
-		.owner	= THIS_MODULE,
-	},
-};
-
-static int __init aaedkbd_init(void)
-{
-	return platform_driver_register(&aaedkbd_driver);
-}
-
-static void __exit aaedkbd_exit(void)
-{
-	platform_driver_unregister(&aaedkbd_driver);
-}
-
-module_init(aaedkbd_init);
-module_exit(aaedkbd_exit);
-
-MODULE_AUTHOR("Nicolas Bellido Y Ortega");
-MODULE_DESCRIPTION("AAED-2000 Keyboard Driver");
-MODULE_LICENSE("GPL v2");
diff -druNp linux-libre-2.6.37-gnu1/drivers/input/keyboard/gpio_keys.c linux-libre-2.6.38-gnu1/drivers/input/keyboard/gpio_keys.c
--- linux-libre-2.6.37-gnu1/drivers/input/keyboard/gpio_keys.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/input/keyboard/gpio_keys.c	2011-03-14 21:20:32.000000000 -0400
@@ -322,7 +322,7 @@ static void gpio_keys_report_event(struc
 	struct gpio_keys_button *button = bdata->button;
 	struct input_dev *input = bdata->input;
 	unsigned int type = button->type ?: EV_KEY;
-	int state = (gpio_get_value(button->gpio) ? 1 : 0) ^ button->active_low;
+	int state = (gpio_get_value_cansleep(button->gpio) ? 1 : 0) ^ button->active_low;
 
 	input_event(input, type, button->code, !!state);
 	input_sync(input);
@@ -410,8 +410,8 @@ static int __devinit gpio_keys_setup_key
 	if (!button->can_disable)
 		irqflags |= IRQF_SHARED;
 
-	error = request_irq(irq, gpio_keys_isr, irqflags, desc, bdata);
-	if (error) {
+	error = request_any_context_irq(irq, gpio_keys_isr, irqflags, desc, bdata);
+	if (error < 0) {
 		dev_err(dev, "Unable to claim irq %d; error %d\n",
 			irq, error);
 		goto fail3;
diff -druNp linux-libre-2.6.37-gnu1/drivers/input/keyboard/Kconfig linux-libre-2.6.38-gnu1/drivers/input/keyboard/Kconfig
--- linux-libre-2.6.37-gnu1/drivers/input/keyboard/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/input/keyboard/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -2,7 +2,7 @@
 # Input core configuration
 #
 menuconfig INPUT_KEYBOARD
-	bool "Keyboards" if EMBEDDED || !X86
+	bool "Keyboards" if EXPERT || !X86
 	default y
 	help
 	  Say Y here, and a list of supported keyboards will be displayed.
@@ -12,18 +12,6 @@ menuconfig INPUT_KEYBOARD
 
 if INPUT_KEYBOARD
 
-config KEYBOARD_AAED2000
-	tristate "AAED-2000 keyboard"
-	depends on MACH_AAED2000
-	select INPUT_POLLDEV
-	default y
-	help
-	  Say Y here to enable the keyboard on the Agilent AAED-2000
-	  development board.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called aaed2000_kbd.
-
 config KEYBOARD_ADP5520
 	tristate "Keypad Support for ADP5520 PMIC"
 	depends on PMIC_ADP5520
@@ -69,7 +57,7 @@ config KEYBOARD_ATARI
 	  module will be called atakbd.
 
 config KEYBOARD_ATKBD
-	tristate "AT keyboard" if EMBEDDED || !X86
+	tristate "AT keyboard" if EXPERT || !X86
 	default y
 	select SERIO
 	select SERIO_LIBPS2
@@ -196,20 +184,22 @@ config KEYBOARD_GPIO_POLLED
 	  module will be called gpio_keys_polled.
 
 config KEYBOARD_TCA6416
-	tristate "TCA6416 Keypad Support"
+	tristate "TCA6416/TCA6408A Keypad Support"
 	depends on I2C
 	help
 	  This driver implements basic keypad functionality
-	  for keys connected through TCA6416 IO expander
+	  for keys connected through TCA6416/TCA6408A IO expanders.
 
 	  Say Y here if your device has keys connected to
-	  TCA6416 IO expander. Your board-specific setup logic
+	  TCA6416/TCA6408A IO expander. Your board-specific setup logic
 	  must also provide pin-mask details(of which TCA6416 pins
 	  are used for keypad).
 
-	  If enabled the complete TCA6416 device will be managed through
+	  If enabled the entire TCA6416 device will be managed through
 	  this driver.
 
+	  To compile this driver as a module, choose M here: the
+	  module will be called tca6416_keypad.
 
 config KEYBOARD_MATRIX
 	tristate "GPIO driven matrix keypad support"
@@ -353,6 +343,16 @@ config KEYBOARD_NOMADIK
 	  To compile this driver as a module, choose M here: the
 	  module will be called nmk-ske-keypad.
 
+config KEYBOARD_TEGRA
+	tristate "NVIDIA Tegra internal matrix keyboard controller support"
+	depends on ARCH_TEGRA
+	help
+	  Say Y here if you want to use a matrix keyboard connected directly
+	  to the internal keyboard controller on Tegra SoCs.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called tegra-kbc.
+
 config KEYBOARD_OPENCORES
 	tristate "OpenCores Keyboard Controller"
 	help
@@ -459,6 +459,25 @@ config KEYBOARD_OMAP4
 	  To compile this driver as a module, choose M here: the
 	  module will be called omap4-keypad.
 
+config KEYBOARD_SPEAR
+	tristate "ST SPEAR keyboard support"
+	depends on PLAT_SPEAR
+	help
+	  Say Y here if you want to use the SPEAR keyboard.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called spear-keboard.
+
+config KEYBOARD_TC3589X
+	tristate "TC3589X Keypad support"
+	depends on MFD_TC3589X
+	help
+	  Say Y here if you want to use the keypad controller on
+	  TC35892/3 I/O expander.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called tc3589x-keypad.
+
 config KEYBOARD_TNETV107X
 	tristate "TI TNETV107X keypad support"
 	depends on ARCH_DAVINCI_TNETV107X
diff -druNp linux-libre-2.6.37-gnu1/drivers/input/keyboard/Makefile linux-libre-2.6.38-gnu1/drivers/input/keyboard/Makefile
--- linux-libre-2.6.37-gnu1/drivers/input/keyboard/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/input/keyboard/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -4,7 +4,6 @@
 
 # Each configuration option enables a list of files.
 
-obj-$(CONFIG_KEYBOARD_AAED2000)		+= aaed2000_kbd.o
 obj-$(CONFIG_KEYBOARD_ADP5520)		+= adp5520-keys.o
 obj-$(CONFIG_KEYBOARD_ADP5588)		+= adp5588-keys.o
 obj-$(CONFIG_KEYBOARD_AMIGA)		+= amikbd.o
@@ -38,9 +37,12 @@ obj-$(CONFIG_KEYBOARD_PXA930_ROTARY)	+=
 obj-$(CONFIG_KEYBOARD_QT2160)		+= qt2160.o
 obj-$(CONFIG_KEYBOARD_SAMSUNG)		+= samsung-keypad.o
 obj-$(CONFIG_KEYBOARD_SH_KEYSC)		+= sh_keysc.o
+obj-$(CONFIG_KEYBOARD_SPEAR)		+= spear-keyboard.o
 obj-$(CONFIG_KEYBOARD_STMPE)		+= stmpe-keypad.o
 obj-$(CONFIG_KEYBOARD_STOWAWAY)		+= stowaway.o
 obj-$(CONFIG_KEYBOARD_SUNKBD)		+= sunkbd.o
+obj-$(CONFIG_KEYBOARD_TC3589X)		+= tc3589x-keypad.o
+obj-$(CONFIG_KEYBOARD_TEGRA)		+= tegra-kbc.o
 obj-$(CONFIG_KEYBOARD_TNETV107X)	+= tnetv107x-keypad.o
 obj-$(CONFIG_KEYBOARD_TWL4030)		+= twl4030_keypad.o
 obj-$(CONFIG_KEYBOARD_XTKBD)		+= xtkbd.o
diff -druNp linux-libre-2.6.37-gnu1/drivers/input/keyboard/omap-keypad.c linux-libre-2.6.38-gnu1/drivers/input/keyboard/omap-keypad.c
--- linux-libre-2.6.37-gnu1/drivers/input/keyboard/omap-keypad.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/input/keyboard/omap-keypad.c	2011-03-14 21:20:32.000000000 -0400
@@ -65,7 +65,6 @@ struct omap_kp {
 
 static DECLARE_TASKLET_DISABLED(kp_tasklet, omap_kp_tasklet, 0);
 
-static int *keymap;
 static unsigned int *row_gpios;
 static unsigned int *col_gpios;
 
@@ -162,20 +161,11 @@ static void omap_kp_scan_keypad(struct o
 	}
 }
 
-static inline int omap_kp_find_key(int col, int row)
-{
-	int i, key;
-
-	key = KEY(col, row, 0);
-	for (i = 0; keymap[i] != 0; i++)
-		if ((keymap[i] & 0xff000000) == key)
-			return keymap[i] & 0x00ffffff;
-	return -1;
-}
-
 static void omap_kp_tasklet(unsigned long data)
 {
 	struct omap_kp *omap_kp_data = (struct omap_kp *) data;
+	unsigned short *keycodes = omap_kp_data->input->keycode;
+	unsigned int row_shift = get_count_order(omap_kp_data->cols);
 	unsigned char new_state[8], changed, key_down = 0;
 	int col, row;
 	int spurious = 0;
@@ -199,7 +189,7 @@ static void omap_kp_tasklet(unsigned lon
 			       row, (new_state[col] & (1 << row)) ?
 			       "pressed" : "released");
 #else
-			key = omap_kp_find_key(col, row);
+			key = keycodes[MATRIX_SCAN_CODE(row, col, row_shift)];
 			if (key < 0) {
 				printk(KERN_WARNING
 				      "omap-keypad: Spurious key event %d-%d\n",
@@ -298,13 +288,18 @@ static int __devinit omap_kp_probe(struc
 	struct input_dev *input_dev;
 	struct omap_kp_platform_data *pdata =  pdev->dev.platform_data;
 	int i, col_idx, row_idx, irq_idx, ret;
+	unsigned int row_shift, keycodemax;
 
-	if (!pdata->rows || !pdata->cols || !pdata->keymap) {
-		printk(KERN_ERR "No rows, cols or keymap from pdata\n");
+	if (!pdata->rows || !pdata->cols || !pdata->keymap_data) {
+		printk(KERN_ERR "No rows, cols or keymap_data from pdata\n");
 		return -EINVAL;
 	}
 
-	omap_kp = kzalloc(sizeof(struct omap_kp), GFP_KERNEL);
+	row_shift = get_count_order(pdata->cols);
+	keycodemax = pdata->rows << row_shift;
+
+	omap_kp = kzalloc(sizeof(struct omap_kp) +
+			keycodemax * sizeof(unsigned short), GFP_KERNEL);
 	input_dev = input_allocate_device();
 	if (!omap_kp || !input_dev) {
 		kfree(omap_kp);
@@ -320,7 +315,9 @@ static int __devinit omap_kp_probe(struc
 	if (!cpu_is_omap24xx())
 		omap_writew(1, OMAP1_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT);
 
-	keymap = pdata->keymap;
+	input_dev->keycode      = &omap_kp[1];
+	input_dev->keycodesize  = sizeof(unsigned short);
+	input_dev->keycodemax   = keycodemax;
 
 	if (pdata->rep)
 		__set_bit(EV_REP, input_dev->evbit);
@@ -374,8 +371,8 @@ static int __devinit omap_kp_probe(struc
 
 	/* setup input device */
 	__set_bit(EV_KEY, input_dev->evbit);
-	for (i = 0; keymap[i] != 0; i++)
-		__set_bit(keymap[i] & KEY_MAX, input_dev->keybit);
+	matrix_keypad_build_keymap(pdata->keymap_data, row_shift,
+			input_dev->keycode, input_dev->keybit);
 	input_dev->name = "omap-keypad";
 	input_dev->phys = "omap-keypad/input0";
 	input_dev->dev.parent = &pdev->dev;
@@ -416,7 +413,7 @@ static int __devinit omap_kp_probe(struc
 	return 0;
 err5:
 	for (i = irq_idx - 1; i >=0; i--)
-		free_irq(row_gpios[i], 0);
+		free_irq(row_gpios[i], NULL);
 err4:
 	input_unregister_device(omap_kp->input);
 	input_dev = NULL;
@@ -447,11 +444,11 @@ static int __devexit omap_kp_remove(stru
 			gpio_free(col_gpios[i]);
 		for (i = 0; i < omap_kp->rows; i++) {
 			gpio_free(row_gpios[i]);
-			free_irq(gpio_to_irq(row_gpios[i]), 0);
+			free_irq(gpio_to_irq(row_gpios[i]), NULL);
 		}
 	} else {
 		omap_writew(1, OMAP1_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT);
-		free_irq(omap_kp->irq, 0);
+		free_irq(omap_kp->irq, NULL);
 	}
 
 	del_timer_sync(&omap_kp->timer);
diff -druNp linux-libre-2.6.37-gnu1/drivers/input/keyboard/spear-keyboard.c linux-libre-2.6.38-gnu1/drivers/input/keyboard/spear-keyboard.c
--- linux-libre-2.6.37-gnu1/drivers/input/keyboard/spear-keyboard.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/input/keyboard/spear-keyboard.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,344 @@
+/*
+ * SPEAr Keyboard Driver
+ * Based on omap-keypad driver
+ *
+ * Copyright (C) 2010 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.
+ */
+
+#include <linux/clk.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/input.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pm_wakeup.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <plat/keyboard.h>
+
+/* Keyboard Registers */
+#define MODE_REG	0x00	/* 16 bit reg */
+#define STATUS_REG	0x0C	/* 2 bit reg */
+#define DATA_REG	0x10	/* 8 bit reg */
+#define INTR_MASK	0x54
+
+/* Register Values */
+/*
+ * pclk freq mask = (APB FEQ -1)= 82 MHZ.Programme bit 15-9 in mode
+ * control register as 1010010(82MHZ)
+ */
+#define PCLK_FREQ_MSK	0xA400	/* 82 MHz */
+#define START_SCAN	0x0100
+#define SCAN_RATE_10	0x0000
+#define SCAN_RATE_20	0x0004
+#define SCAN_RATE_40	0x0008
+#define SCAN_RATE_80	0x000C
+#define MODE_KEYBOARD	0x0002
+#define DATA_AVAIL	0x2
+
+#define KEY_MASK	0xFF000000
+#define KEY_VALUE	0x00FFFFFF
+#define ROW_MASK	0xF0
+#define COLUMN_MASK	0x0F
+#define ROW_SHIFT	4
+
+struct spear_kbd {
+	struct input_dev *input;
+	struct resource *res;
+	void __iomem *io_base;
+	struct clk *clk;
+	unsigned int irq;
+	unsigned short last_key;
+	unsigned short keycodes[256];
+};
+
+static irqreturn_t spear_kbd_interrupt(int irq, void *dev_id)
+{
+	struct spear_kbd *kbd = dev_id;
+	struct input_dev *input = kbd->input;
+	unsigned int key;
+	u8 sts, val;
+
+	sts = readb(kbd->io_base + STATUS_REG);
+	if (sts & DATA_AVAIL)
+		return IRQ_NONE;
+
+	if (kbd->last_key != KEY_RESERVED) {
+		input_report_key(input, kbd->last_key, 0);
+		kbd->last_key = KEY_RESERVED;
+	}
+
+	/* following reads active (row, col) pair */
+	val = readb(kbd->io_base + DATA_REG);
+	key = kbd->keycodes[val];
+
+	input_event(input, EV_MSC, MSC_SCAN, val);
+	input_report_key(input, key, 1);
+	input_sync(input);
+
+	kbd->last_key = key;
+
+	/* clear interrupt */
+	writeb(0, kbd->io_base + STATUS_REG);
+
+	return IRQ_HANDLED;
+}
+
+static int spear_kbd_open(struct input_dev *dev)
+{
+	struct spear_kbd *kbd = input_get_drvdata(dev);
+	int error;
+	u16 val;
+
+	kbd->last_key = KEY_RESERVED;
+
+	error = clk_enable(kbd->clk);
+	if (error)
+		return error;
+
+	/* program keyboard */
+	val = SCAN_RATE_80 | MODE_KEYBOARD | PCLK_FREQ_MSK;
+	writew(val, kbd->io_base + MODE_REG);
+	writeb(1, kbd->io_base + STATUS_REG);
+
+	/* start key scan */
+	val = readw(kbd->io_base + MODE_REG);
+	val |= START_SCAN;
+	writew(val, kbd->io_base + MODE_REG);
+
+	return 0;
+}
+
+static void spear_kbd_close(struct input_dev *dev)
+{
+	struct spear_kbd *kbd = input_get_drvdata(dev);
+	u16 val;
+
+	/* stop key scan */
+	val = readw(kbd->io_base + MODE_REG);
+	val &= ~START_SCAN;
+	writew(val, kbd->io_base + MODE_REG);
+
+	clk_disable(kbd->clk);
+
+	kbd->last_key = KEY_RESERVED;
+}
+
+static int __devinit spear_kbd_probe(struct platform_device *pdev)
+{
+	const struct kbd_platform_data *pdata = pdev->dev.platform_data;
+	const struct matrix_keymap_data *keymap;
+	struct spear_kbd *kbd;
+	struct input_dev *input_dev;
+	struct resource *res;
+	int irq;
+	int error;
+
+	if (!pdata) {
+		dev_err(&pdev->dev, "Invalid platform data\n");
+		return -EINVAL;
+	}
+
+	keymap = pdata->keymap;
+	if (!keymap) {
+		dev_err(&pdev->dev, "no keymap defined\n");
+		return -EINVAL;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&pdev->dev, "no keyboard resource defined\n");
+		return -EBUSY;
+	}
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		dev_err(&pdev->dev, "not able to get irq for the device\n");
+		return irq;
+	}
+
+	kbd = kzalloc(sizeof(*kbd), GFP_KERNEL);
+	input_dev = input_allocate_device();
+	if (!kbd || !input_dev) {
+		dev_err(&pdev->dev, "out of memory\n");
+		error = -ENOMEM;
+		goto err_free_mem;
+	}
+
+	kbd->input = input_dev;
+	kbd->irq = irq;
+	kbd->res = request_mem_region(res->start, resource_size(res),
+				      pdev->name);
+	if (!kbd->res) {
+		dev_err(&pdev->dev, "keyboard region already claimed\n");
+		error = -EBUSY;
+		goto err_free_mem;
+	}
+
+	kbd->io_base = ioremap(res->start, resource_size(res));
+	if (!kbd->io_base) {
+		dev_err(&pdev->dev, "ioremap failed for kbd_region\n");
+		error = -ENOMEM;
+		goto err_release_mem_region;
+	}
+
+	kbd->clk = clk_get(&pdev->dev, NULL);
+	if (IS_ERR(kbd->clk)) {
+		error = PTR_ERR(kbd->clk);
+		goto err_iounmap;
+	}
+
+	input_dev->name = "Spear Keyboard";
+	input_dev->phys = "keyboard/input0";
+	input_dev->dev.parent = &pdev->dev;
+	input_dev->id.bustype = BUS_HOST;
+	input_dev->id.vendor = 0x0001;
+	input_dev->id.product = 0x0001;
+	input_dev->id.version = 0x0100;
+	input_dev->open = spear_kbd_open;
+	input_dev->close = spear_kbd_close;
+
+	__set_bit(EV_KEY, input_dev->evbit);
+	if (pdata->rep)
+		__set_bit(EV_REP, input_dev->evbit);
+	input_set_capability(input_dev, EV_MSC, MSC_SCAN);
+
+	input_dev->keycode = kbd->keycodes;
+	input_dev->keycodesize = sizeof(kbd->keycodes[0]);
+	input_dev->keycodemax = ARRAY_SIZE(kbd->keycodes);
+
+	matrix_keypad_build_keymap(keymap, ROW_SHIFT,
+			input_dev->keycode, input_dev->keybit);
+
+	input_set_drvdata(input_dev, kbd);
+
+	error = request_irq(irq, spear_kbd_interrupt, 0, "keyboard", kbd);
+	if (error) {
+		dev_err(&pdev->dev, "request_irq fail\n");
+		goto err_put_clk;
+	}
+
+	error = input_register_device(input_dev);
+	if (error) {
+		dev_err(&pdev->dev, "Unable to register keyboard device\n");
+		goto err_free_irq;
+	}
+
+	device_init_wakeup(&pdev->dev, 1);
+	platform_set_drvdata(pdev, kbd);
+
+	return 0;
+
+err_free_irq:
+	free_irq(kbd->irq, kbd);
+err_put_clk:
+	clk_put(kbd->clk);
+err_iounmap:
+	iounmap(kbd->io_base);
+err_release_mem_region:
+	release_mem_region(res->start, resource_size(res));
+err_free_mem:
+	input_free_device(input_dev);
+	kfree(kbd);
+
+	return error;
+}
+
+static int __devexit spear_kbd_remove(struct platform_device *pdev)
+{
+	struct spear_kbd *kbd = platform_get_drvdata(pdev);
+
+	free_irq(kbd->irq, kbd);
+	input_unregister_device(kbd->input);
+	clk_put(kbd->clk);
+	iounmap(kbd->io_base);
+	release_mem_region(kbd->res->start, resource_size(kbd->res));
+	kfree(kbd);
+
+	device_init_wakeup(&pdev->dev, 1);
+	platform_set_drvdata(pdev, NULL);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int spear_kbd_suspend(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct spear_kbd *kbd = platform_get_drvdata(pdev);
+	struct input_dev *input_dev = kbd->input;
+
+	mutex_lock(&input_dev->mutex);
+
+	if (input_dev->users)
+		clk_enable(kbd->clk);
+
+	if (device_may_wakeup(&pdev->dev))
+		enable_irq_wake(kbd->irq);
+
+	mutex_unlock(&input_dev->mutex);
+
+	return 0;
+}
+
+static int spear_kbd_resume(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct spear_kbd *kbd = platform_get_drvdata(pdev);
+	struct input_dev *input_dev = kbd->input;
+
+	mutex_lock(&input_dev->mutex);
+
+	if (device_may_wakeup(&pdev->dev))
+		disable_irq_wake(kbd->irq);
+
+	if (input_dev->users)
+		clk_enable(kbd->clk);
+
+	mutex_unlock(&input_dev->mutex);
+
+	return 0;
+}
+
+static const struct dev_pm_ops spear_kbd_pm_ops = {
+	.suspend	= spear_kbd_suspend,
+	.resume		= spear_kbd_resume,
+};
+#endif
+
+static struct platform_driver spear_kbd_driver = {
+	.probe		= spear_kbd_probe,
+	.remove		= __devexit_p(spear_kbd_remove),
+	.driver		= {
+		.name	= "keyboard",
+		.owner	= THIS_MODULE,
+#ifdef CONFIG_PM
+		.pm	= &spear_kbd_pm_ops,
+#endif
+	},
+};
+
+static int __init spear_kbd_init(void)
+{
+	return platform_driver_register(&spear_kbd_driver);
+}
+module_init(spear_kbd_init);
+
+static void __exit spear_kbd_exit(void)
+{
+	platform_driver_unregister(&spear_kbd_driver);
+}
+module_exit(spear_kbd_exit);
+
+MODULE_AUTHOR("Rajeev Kumar");
+MODULE_DESCRIPTION("SPEAr Keyboard Driver");
+MODULE_LICENSE("GPL");
diff -druNp linux-libre-2.6.37-gnu1/drivers/input/keyboard/tc3589x-keypad.c linux-libre-2.6.38-gnu1/drivers/input/keyboard/tc3589x-keypad.c
--- linux-libre-2.6.37-gnu1/drivers/input/keyboard/tc3589x-keypad.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/input/keyboard/tc3589x-keypad.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,472 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * Author: Jayeeta Banerjee <jayeeta.banerjee@stericsson.com>
+ * Author: Sundar Iyer <sundar.iyer@stericsson.com>
+ *
+ * License Terms: GNU General Public License, version 2
+ *
+ * TC35893 MFD Keypad Controller driver
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/input.h>
+#include <linux/platform_device.h>
+#include <linux/input/matrix_keypad.h>
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/mfd/tc3589x.h>
+
+/* Maximum supported keypad matrix row/columns size */
+#define TC3589x_MAX_KPROW               8
+#define TC3589x_MAX_KPCOL               12
+
+/* keypad related Constants */
+#define TC3589x_MAX_DEBOUNCE_SETTLE     0xFF
+#define DEDICATED_KEY_VAL		0xFF
+
+/* Pull up/down masks */
+#define TC3589x_NO_PULL_MASK		0x0
+#define TC3589x_PULL_DOWN_MASK		0x1
+#define TC3589x_PULL_UP_MASK		0x2
+#define TC3589x_PULLUP_ALL_MASK		0xAA
+#define TC3589x_IO_PULL_VAL(index, mask)	((mask)<<((index)%4)*2))
+
+/* Bit masks for IOCFG register */
+#define IOCFG_BALLCFG		0x01
+#define IOCFG_IG		0x08
+
+#define KP_EVCODE_COL_MASK	0x0F
+#define KP_EVCODE_ROW_MASK	0x70
+#define KP_RELEASE_EVT_MASK	0x80
+
+#define KP_ROW_SHIFT		4
+
+#define KP_NO_VALID_KEY_MASK	0x7F
+
+/* bit masks for RESTCTRL register */
+#define TC3589x_KBDRST		0x2
+#define TC3589x_IRQRST		0x10
+#define TC3589x_RESET_ALL	0x1B
+
+/* KBDMFS register bit mask */
+#define TC3589x_KBDMFS_EN	0x1
+
+/* CLKEN register bitmask */
+#define KPD_CLK_EN		0x1
+
+/* RSTINTCLR register bit mask */
+#define IRQ_CLEAR		0x1
+
+/* bit masks for keyboard interrupts*/
+#define TC3589x_EVT_LOSS_INT	0x8
+#define TC3589x_EVT_INT		0x4
+#define TC3589x_KBD_LOSS_INT	0x2
+#define TC3589x_KBD_INT		0x1
+
+/* bit masks for keyboard interrupt clear*/
+#define TC3589x_EVT_INT_CLR	0x2
+#define TC3589x_KBD_INT_CLR	0x1
+
+#define TC3589x_KBD_KEYMAP_SIZE     64
+
+/**
+ * struct tc_keypad - data structure used by keypad driver
+ * @input:      pointer to input device object
+ * @board:      keypad platform device
+ * @krow:	number of rows
+ * @kcol:	number of coloumns
+ * @keymap:     matrix scan code table for keycodes
+ */
+struct tc_keypad {
+	struct tc3589x *tc3589x;
+	struct input_dev *input;
+	const struct tc3589x_keypad_platform_data *board;
+	unsigned int krow;
+	unsigned int kcol;
+	unsigned short keymap[TC3589x_KBD_KEYMAP_SIZE];
+	bool keypad_stopped;
+};
+
+static int __devinit tc3589x_keypad_init_key_hardware(struct tc_keypad *keypad)
+{
+	int ret;
+	struct tc3589x *tc3589x = keypad->tc3589x;
+	u8 settle_time = keypad->board->settle_time;
+	u8 dbounce_period = keypad->board->debounce_period;
+	u8 rows = keypad->board->krow & 0xf;	/* mask out the nibble */
+	u8 column = keypad->board->kcol & 0xf;	/* mask out the nibble */
+
+	/* validate platform configurations */
+	if (keypad->board->kcol > TC3589x_MAX_KPCOL ||
+	    keypad->board->krow > TC3589x_MAX_KPROW ||
+	    keypad->board->debounce_period > TC3589x_MAX_DEBOUNCE_SETTLE ||
+	    keypad->board->settle_time > TC3589x_MAX_DEBOUNCE_SETTLE)
+		return -EINVAL;
+
+	/* configure KBDSIZE 4 LSbits for cols and 4 MSbits for rows */
+	ret = tc3589x_reg_write(tc3589x, TC3589x_KBDSIZE,
+			(rows << KP_ROW_SHIFT) | column);
+	if (ret < 0)
+		return ret;
+
+	/* configure dedicated key config, no dedicated key selected */
+	ret = tc3589x_reg_write(tc3589x, TC3589x_KBCFG_LSB, DEDICATED_KEY_VAL);
+	if (ret < 0)
+		return ret;
+
+	ret = tc3589x_reg_write(tc3589x, TC3589x_KBCFG_MSB, DEDICATED_KEY_VAL);
+	if (ret < 0)
+		return ret;
+
+	/* Configure settle time */
+	ret = tc3589x_reg_write(tc3589x, TC3589x_KBDSETTLE_REG, settle_time);
+	if (ret < 0)
+		return ret;
+
+	/* Configure debounce time */
+	ret = tc3589x_reg_write(tc3589x, TC3589x_KBDBOUNCE, dbounce_period);
+	if (ret < 0)
+		return ret;
+
+	/* Start of initialise keypad GPIOs */
+	ret = tc3589x_set_bits(tc3589x, TC3589x_IOCFG, 0x0, IOCFG_IG);
+	if (ret < 0)
+		return ret;
+
+	/* Configure pull-up resistors for all row GPIOs */
+	ret = tc3589x_reg_write(tc3589x, TC3589x_IOPULLCFG0_LSB,
+					TC3589x_PULLUP_ALL_MASK);
+	if (ret < 0)
+		return ret;
+
+	ret = tc3589x_reg_write(tc3589x, TC3589x_IOPULLCFG0_MSB,
+					TC3589x_PULLUP_ALL_MASK);
+	if (ret < 0)
+		return ret;
+
+	/* Configure pull-up resistors for all column GPIOs */
+	ret = tc3589x_reg_write(tc3589x, TC3589x_IOPULLCFG1_LSB,
+			TC3589x_PULLUP_ALL_MASK);
+	if (ret < 0)
+		return ret;
+
+	ret = tc3589x_reg_write(tc3589x, TC3589x_IOPULLCFG1_MSB,
+			TC3589x_PULLUP_ALL_MASK);
+	if (ret < 0)
+		return ret;
+
+	ret = tc3589x_reg_write(tc3589x, TC3589x_IOPULLCFG2_LSB,
+			TC3589x_PULLUP_ALL_MASK);
+
+	return ret;
+}
+
+#define TC35893_DATA_REGS		4
+#define TC35893_KEYCODE_FIFO_EMPTY	0x7f
+#define TC35893_KEYCODE_FIFO_CLEAR	0xff
+#define TC35893_KEYPAD_ROW_SHIFT	0x3
+
+static irqreturn_t tc3589x_keypad_irq(int irq, void *dev)
+{
+	struct tc_keypad *keypad = dev;
+	struct tc3589x *tc3589x = keypad->tc3589x;
+	u8 i, row_index, col_index, kbd_code, up;
+	u8 code;
+
+	for (i = 0; i < TC35893_DATA_REGS * 2; i++) {
+		kbd_code = tc3589x_reg_read(tc3589x, TC3589x_EVTCODE_FIFO);
+
+		/* loop till fifo is empty and no more keys are pressed */
+		if (kbd_code == TC35893_KEYCODE_FIFO_EMPTY ||
+				kbd_code == TC35893_KEYCODE_FIFO_CLEAR)
+			continue;
+
+		/* valid key is found */
+		col_index = kbd_code & KP_EVCODE_COL_MASK;
+		row_index = (kbd_code & KP_EVCODE_ROW_MASK) >> KP_ROW_SHIFT;
+		code = MATRIX_SCAN_CODE(row_index, col_index,
+						TC35893_KEYPAD_ROW_SHIFT);
+		up = kbd_code & KP_RELEASE_EVT_MASK;
+
+		input_event(keypad->input, EV_MSC, MSC_SCAN, code);
+		input_report_key(keypad->input, keypad->keymap[code], !up);
+		input_sync(keypad->input);
+	}
+
+	/* clear IRQ */
+	tc3589x_set_bits(tc3589x, TC3589x_KBDIC,
+			0x0, TC3589x_EVT_INT_CLR | TC3589x_KBD_INT_CLR);
+	/* enable IRQ */
+	tc3589x_set_bits(tc3589x, TC3589x_KBDMSK,
+			0x0, TC3589x_EVT_LOSS_INT | TC3589x_EVT_INT);
+
+	return IRQ_HANDLED;
+}
+
+static int tc3589x_keypad_enable(struct tc_keypad *keypad)
+{
+	struct tc3589x *tc3589x = keypad->tc3589x;
+	int ret;
+
+	/* pull the keypad module out of reset */
+	ret = tc3589x_set_bits(tc3589x, TC3589x_RSTCTRL, TC3589x_KBDRST, 0x0);
+	if (ret < 0)
+		return ret;
+
+	/* configure KBDMFS */
+	ret = tc3589x_set_bits(tc3589x, TC3589x_KBDMFS, 0x0, TC3589x_KBDMFS_EN);
+	if (ret < 0)
+		return ret;
+
+	/* enable the keypad clock */
+	ret = tc3589x_set_bits(tc3589x, TC3589x_CLKEN, 0x0, KPD_CLK_EN);
+	if (ret < 0)
+		return ret;
+
+	/* clear pending IRQs */
+	ret =  tc3589x_set_bits(tc3589x, TC3589x_RSTINTCLR, 0x0, 0x1);
+	if (ret < 0)
+		return ret;
+
+	/* enable the IRQs */
+	ret = tc3589x_set_bits(tc3589x, TC3589x_KBDMSK, 0x0,
+					TC3589x_EVT_LOSS_INT | TC3589x_EVT_INT);
+	if (ret < 0)
+		return ret;
+
+	keypad->keypad_stopped = false;
+
+	return ret;
+}
+
+static int tc3589x_keypad_disable(struct tc_keypad *keypad)
+{
+	struct tc3589x *tc3589x = keypad->tc3589x;
+	int ret;
+
+	/* clear IRQ */
+	ret = tc3589x_set_bits(tc3589x, TC3589x_KBDIC,
+			0x0, TC3589x_EVT_INT_CLR | TC3589x_KBD_INT_CLR);
+	if (ret < 0)
+		return ret;
+
+	/* disable all interrupts */
+	ret = tc3589x_set_bits(tc3589x, TC3589x_KBDMSK,
+			~(TC3589x_EVT_LOSS_INT | TC3589x_EVT_INT), 0x0);
+	if (ret < 0)
+		return ret;
+
+	/* disable the keypad module */
+	ret = tc3589x_set_bits(tc3589x, TC3589x_CLKEN, 0x1, 0x0);
+	if (ret < 0)
+		return ret;
+
+	/* put the keypad module into reset */
+	ret = tc3589x_set_bits(tc3589x, TC3589x_RSTCTRL, TC3589x_KBDRST, 0x1);
+
+	keypad->keypad_stopped = true;
+
+	return ret;
+}
+
+static int tc3589x_keypad_open(struct input_dev *input)
+{
+	int error;
+	struct tc_keypad *keypad = input_get_drvdata(input);
+
+	/* enable the keypad module */
+	error = tc3589x_keypad_enable(keypad);
+	if (error < 0) {
+		dev_err(&input->dev, "failed to enable keypad module\n");
+		return error;
+	}
+
+	error = tc3589x_keypad_init_key_hardware(keypad);
+	if (error < 0) {
+		dev_err(&input->dev, "failed to configure keypad module\n");
+		return error;
+	}
+
+	return 0;
+}
+
+static void tc3589x_keypad_close(struct input_dev *input)
+{
+	struct tc_keypad *keypad = input_get_drvdata(input);
+
+	/* disable the keypad module */
+	tc3589x_keypad_disable(keypad);
+}
+
+static int __devinit tc3589x_keypad_probe(struct platform_device *pdev)
+{
+	struct tc3589x *tc3589x = dev_get_drvdata(pdev->dev.parent);
+	struct tc_keypad *keypad;
+	struct input_dev *input;
+	const struct tc3589x_keypad_platform_data *plat;
+	int error, irq;
+
+	plat = tc3589x->pdata->keypad;
+	if (!plat) {
+		dev_err(&pdev->dev, "invalid keypad platform data\n");
+		return -EINVAL;
+	}
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0)
+		return irq;
+
+	keypad = kzalloc(sizeof(struct tc_keypad), GFP_KERNEL);
+	input = input_allocate_device();
+	if (!keypad || !input) {
+		dev_err(&pdev->dev, "failed to allocate keypad memory\n");
+		error = -ENOMEM;
+		goto err_free_mem;
+	}
+
+	keypad->board = plat;
+	keypad->input = input;
+	keypad->tc3589x = tc3589x;
+
+	input->id.bustype = BUS_I2C;
+	input->name = pdev->name;
+	input->dev.parent = &pdev->dev;
+
+	input->keycode = keypad->keymap;
+	input->keycodesize = sizeof(keypad->keymap[0]);
+	input->keycodemax = ARRAY_SIZE(keypad->keymap);
+
+	input->open = tc3589x_keypad_open;
+	input->close = tc3589x_keypad_close;
+
+	input_set_drvdata(input, keypad);
+
+	input_set_capability(input, EV_MSC, MSC_SCAN);
+
+	__set_bit(EV_KEY, input->evbit);
+	if (!plat->no_autorepeat)
+		__set_bit(EV_REP, input->evbit);
+
+	matrix_keypad_build_keymap(plat->keymap_data, 0x3,
+			input->keycode, input->keybit);
+
+	error = request_threaded_irq(irq, NULL,
+			tc3589x_keypad_irq, plat->irqtype,
+			"tc3589x-keypad", keypad);
+	if (error < 0) {
+		dev_err(&pdev->dev,
+				"Could not allocate irq %d,error %d\n",
+				irq, error);
+		goto err_free_mem;
+	}
+
+	error = input_register_device(input);
+	if (error) {
+		dev_err(&pdev->dev, "Could not register input device\n");
+		goto err_free_irq;
+	}
+
+	/* let platform decide if keypad is a wakeup source or not */
+	device_init_wakeup(&pdev->dev, plat->enable_wakeup);
+	device_set_wakeup_capable(&pdev->dev, plat->enable_wakeup);
+
+	platform_set_drvdata(pdev, keypad);
+
+	return 0;
+
+err_free_irq:
+	free_irq(irq, keypad);
+err_free_mem:
+	input_free_device(input);
+	kfree(keypad);
+	return error;
+}
+
+static int __devexit tc3589x_keypad_remove(struct platform_device *pdev)
+{
+	struct tc_keypad *keypad = platform_get_drvdata(pdev);
+	int irq = platform_get_irq(pdev, 0);
+
+	if (!keypad->keypad_stopped)
+		tc3589x_keypad_disable(keypad);
+
+	free_irq(irq, keypad);
+
+	input_unregister_device(keypad->input);
+
+	kfree(keypad);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int tc3589x_keypad_suspend(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct tc_keypad *keypad = platform_get_drvdata(pdev);
+	int irq = platform_get_irq(pdev, 0);
+
+	/* keypad is already off; we do nothing */
+	if (keypad->keypad_stopped)
+		return 0;
+
+	/* if device is not a wakeup source, disable it for powersave */
+	if (!device_may_wakeup(&pdev->dev))
+		tc3589x_keypad_disable(keypad);
+	else
+		enable_irq_wake(irq);
+
+	return 0;
+}
+
+static int tc3589x_keypad_resume(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct tc_keypad *keypad = platform_get_drvdata(pdev);
+	int irq = platform_get_irq(pdev, 0);
+
+	if (!keypad->keypad_stopped)
+		return 0;
+
+	/* enable the device to resume normal operations */
+	if (!device_may_wakeup(&pdev->dev))
+		tc3589x_keypad_enable(keypad);
+	else
+		disable_irq_wake(irq);
+
+	return 0;
+}
+
+static const SIMPLE_DEV_PM_OPS(tc3589x_keypad_dev_pm_ops,
+			       tc3589x_keypad_suspend, tc3589x_keypad_resume);
+#endif
+
+static struct platform_driver tc3589x_keypad_driver = {
+	.driver.name  = "tc3589x-keypad",
+	.driver.owner = THIS_MODULE,
+#ifdef CONFIG_PM
+	.driver.pm = &tc3589x_keypad_dev_pm_ops,
+#endif
+	.probe = tc3589x_keypad_probe,
+	.remove = __devexit_p(tc3589x_keypad_remove),
+};
+
+static int __init tc3589x_keypad_init(void)
+{
+	return platform_driver_register(&tc3589x_keypad_driver);
+}
+module_init(tc3589x_keypad_init);
+
+static void __exit tc3589x_keypad_exit(void)
+{
+	return platform_driver_unregister(&tc3589x_keypad_driver);
+}
+module_exit(tc3589x_keypad_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Jayeeta Banerjee/Sundar Iyer");
+MODULE_DESCRIPTION("TC35893 Keypad Driver");
+MODULE_ALIAS("platform:tc3589x-keypad");
diff -druNp linux-libre-2.6.37-gnu1/drivers/input/keyboard/tca6416-keypad.c linux-libre-2.6.38-gnu1/drivers/input/keyboard/tca6416-keypad.c
--- linux-libre-2.6.37-gnu1/drivers/input/keyboard/tca6416-keypad.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/input/keyboard/tca6416-keypad.c	2011-03-14 21:20:32.000000000 -0400
@@ -29,6 +29,7 @@
 
 static const struct i2c_device_id tca6416_id[] = {
 	{ "tca6416-keys", 16, },
+	{ "tca6408-keys", 8, },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, tca6416_id);
@@ -46,8 +47,9 @@ struct tca6416_keypad_chip {
 	struct i2c_client *client;
 	struct input_dev *input;
 	struct delayed_work dwork;
-	u16 pinmask;
+	int io_size;
 	int irqnum;
+	u16 pinmask;
 	bool use_polling;
 	struct tca6416_button buttons[0];
 };
@@ -56,7 +58,9 @@ static int tca6416_write_reg(struct tca6
 {
 	int error;
 
-	error = i2c_smbus_write_word_data(chip->client, reg << 1, val);
+	error = chip->io_size > 8 ?
+		i2c_smbus_write_word_data(chip->client, reg << 1, val) :
+		i2c_smbus_write_byte_data(chip->client, reg, val);
 	if (error < 0) {
 		dev_err(&chip->client->dev,
 			"%s failed, reg: %d, val: %d, error: %d\n",
@@ -71,7 +75,9 @@ static int tca6416_read_reg(struct tca64
 {
 	int retval;
 
-	retval = i2c_smbus_read_word_data(chip->client, reg << 1);
+	retval = chip->io_size > 8 ?
+		 i2c_smbus_read_word_data(chip->client, reg << 1) :
+		 i2c_smbus_read_byte_data(chip->client, reg);
 	if (retval < 0) {
 		dev_err(&chip->client->dev, "%s failed, reg: %d, error: %d\n",
 			__func__, reg, retval);
@@ -224,6 +230,7 @@ static int __devinit tca6416_keypad_prob
 
 	chip->client = client;
 	chip->input = input;
+	chip->io_size = id->driver_data;
 	chip->pinmask = pdata->pinmask;
 	chip->use_polling = pdata->use_polling;
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/input/keyboard/tegra-kbc.c linux-libre-2.6.38-gnu1/drivers/input/keyboard/tegra-kbc.c
--- linux-libre-2.6.37-gnu1/drivers/input/keyboard/tegra-kbc.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/input/keyboard/tegra-kbc.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,783 @@
+/*
+ * Keyboard class input driver for the NVIDIA Tegra SoC internal matrix
+ * keyboard controller
+ *
+ * Copyright (c) 2009-2011, NVIDIA 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.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/input.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/clk.h>
+#include <linux/slab.h>
+#include <mach/clk.h>
+#include <mach/kbc.h>
+
+#define KBC_MAX_DEBOUNCE_CNT	0x3ffu
+
+/* KBC row scan time and delay for beginning the row scan. */
+#define KBC_ROW_SCAN_TIME	16
+#define KBC_ROW_SCAN_DLY	5
+
+/* KBC uses a 32KHz clock so a cycle = 1/32Khz */
+#define KBC_CYCLE_USEC	32
+
+/* KBC Registers */
+
+/* KBC Control Register */
+#define KBC_CONTROL_0	0x0
+#define KBC_FIFO_TH_CNT_SHIFT(cnt)	(cnt << 14)
+#define KBC_DEBOUNCE_CNT_SHIFT(cnt)	(cnt << 4)
+#define KBC_CONTROL_FIFO_CNT_INT_EN	(1 << 3)
+#define KBC_CONTROL_KBC_EN		(1 << 0)
+
+/* KBC Interrupt Register */
+#define KBC_INT_0	0x4
+#define KBC_INT_FIFO_CNT_INT_STATUS	(1 << 2)
+
+#define KBC_ROW_CFG0_0	0x8
+#define KBC_COL_CFG0_0	0x18
+#define KBC_INIT_DLY_0	0x28
+#define KBC_RPT_DLY_0	0x2c
+#define KBC_KP_ENT0_0	0x30
+#define KBC_KP_ENT1_0	0x34
+#define KBC_ROW0_MASK_0	0x38
+
+#define KBC_ROW_SHIFT	3
+
+struct tegra_kbc {
+	void __iomem *mmio;
+	struct input_dev *idev;
+	unsigned int irq;
+	unsigned int wake_enable_rows;
+	unsigned int wake_enable_cols;
+	spinlock_t lock;
+	unsigned int repoll_dly;
+	unsigned long cp_dly_jiffies;
+	bool use_fn_map;
+	const struct tegra_kbc_platform_data *pdata;
+	unsigned short keycode[KBC_MAX_KEY * 2];
+	unsigned short current_keys[KBC_MAX_KPENT];
+	unsigned int num_pressed_keys;
+	struct timer_list timer;
+	struct clk *clk;
+};
+
+static const u32 tegra_kbc_default_keymap[] = {
+	KEY(0, 2, KEY_W),
+	KEY(0, 3, KEY_S),
+	KEY(0, 4, KEY_A),
+	KEY(0, 5, KEY_Z),
+	KEY(0, 7, KEY_FN),
+
+	KEY(1, 7, KEY_LEFTMETA),
+
+	KEY(2, 6, KEY_RIGHTALT),
+	KEY(2, 7, KEY_LEFTALT),
+
+	KEY(3, 0, KEY_5),
+	KEY(3, 1, KEY_4),
+	KEY(3, 2, KEY_R),
+	KEY(3, 3, KEY_E),
+	KEY(3, 4, KEY_F),
+	KEY(3, 5, KEY_D),
+	KEY(3, 6, KEY_X),
+
+	KEY(4, 0, KEY_7),
+	KEY(4, 1, KEY_6),
+	KEY(4, 2, KEY_T),
+	KEY(4, 3, KEY_H),
+	KEY(4, 4, KEY_G),
+	KEY(4, 5, KEY_V),
+	KEY(4, 6, KEY_C),
+	KEY(4, 7, KEY_SPACE),
+
+	KEY(5, 0, KEY_9),
+	KEY(5, 1, KEY_8),
+	KEY(5, 2, KEY_U),
+	KEY(5, 3, KEY_Y),
+	KEY(5, 4, KEY_J),
+	KEY(5, 5, KEY_N),
+	KEY(5, 6, KEY_B),
+	KEY(5, 7, KEY_BACKSLASH),
+
+	KEY(6, 0, KEY_MINUS),
+	KEY(6, 1, KEY_0),
+	KEY(6, 2, KEY_O),
+	KEY(6, 3, KEY_I),
+	KEY(6, 4, KEY_L),
+	KEY(6, 5, KEY_K),
+	KEY(6, 6, KEY_COMMA),
+	KEY(6, 7, KEY_M),
+
+	KEY(7, 1, KEY_EQUAL),
+	KEY(7, 2, KEY_RIGHTBRACE),
+	KEY(7, 3, KEY_ENTER),
+	KEY(7, 7, KEY_MENU),
+
+	KEY(8, 4, KEY_RIGHTSHIFT),
+	KEY(8, 5, KEY_LEFTSHIFT),
+
+	KEY(9, 5, KEY_RIGHTCTRL),
+	KEY(9, 7, KEY_LEFTCTRL),
+
+	KEY(11, 0, KEY_LEFTBRACE),
+	KEY(11, 1, KEY_P),
+	KEY(11, 2, KEY_APOSTROPHE),
+	KEY(11, 3, KEY_SEMICOLON),
+	KEY(11, 4, KEY_SLASH),
+	KEY(11, 5, KEY_DOT),
+
+	KEY(12, 0, KEY_F10),
+	KEY(12, 1, KEY_F9),
+	KEY(12, 2, KEY_BACKSPACE),
+	KEY(12, 3, KEY_3),
+	KEY(12, 4, KEY_2),
+	KEY(12, 5, KEY_UP),
+	KEY(12, 6, KEY_PRINT),
+	KEY(12, 7, KEY_PAUSE),
+
+	KEY(13, 0, KEY_INSERT),
+	KEY(13, 1, KEY_DELETE),
+	KEY(13, 3, KEY_PAGEUP),
+	KEY(13, 4, KEY_PAGEDOWN),
+	KEY(13, 5, KEY_RIGHT),
+	KEY(13, 6, KEY_DOWN),
+	KEY(13, 7, KEY_LEFT),
+
+	KEY(14, 0, KEY_F11),
+	KEY(14, 1, KEY_F12),
+	KEY(14, 2, KEY_F8),
+	KEY(14, 3, KEY_Q),
+	KEY(14, 4, KEY_F4),
+	KEY(14, 5, KEY_F3),
+	KEY(14, 6, KEY_1),
+	KEY(14, 7, KEY_F7),
+
+	KEY(15, 0, KEY_ESC),
+	KEY(15, 1, KEY_GRAVE),
+	KEY(15, 2, KEY_F5),
+	KEY(15, 3, KEY_TAB),
+	KEY(15, 4, KEY_F1),
+	KEY(15, 5, KEY_F2),
+	KEY(15, 6, KEY_CAPSLOCK),
+	KEY(15, 7, KEY_F6),
+
+	/* Software Handled Function Keys */
+	KEY(20, 0, KEY_KP7),
+
+	KEY(21, 0, KEY_KP9),
+	KEY(21, 1, KEY_KP8),
+	KEY(21, 2, KEY_KP4),
+	KEY(21, 4, KEY_KP1),
+
+	KEY(22, 1, KEY_KPSLASH),
+	KEY(22, 2, KEY_KP6),
+	KEY(22, 3, KEY_KP5),
+	KEY(22, 4, KEY_KP3),
+	KEY(22, 5, KEY_KP2),
+	KEY(22, 7, KEY_KP0),
+
+	KEY(27, 1, KEY_KPASTERISK),
+	KEY(27, 3, KEY_KPMINUS),
+	KEY(27, 4, KEY_KPPLUS),
+	KEY(27, 5, KEY_KPDOT),
+
+	KEY(28, 5, KEY_VOLUMEUP),
+
+	KEY(29, 3, KEY_HOME),
+	KEY(29, 4, KEY_END),
+	KEY(29, 5, KEY_BRIGHTNESSDOWN),
+	KEY(29, 6, KEY_VOLUMEDOWN),
+	KEY(29, 7, KEY_BRIGHTNESSUP),
+
+	KEY(30, 0, KEY_NUMLOCK),
+	KEY(30, 1, KEY_SCROLLLOCK),
+	KEY(30, 2, KEY_MUTE),
+
+	KEY(31, 4, KEY_HELP),
+};
+
+static const struct matrix_keymap_data tegra_kbc_default_keymap_data = {
+	.keymap		= tegra_kbc_default_keymap,
+	.keymap_size	= ARRAY_SIZE(tegra_kbc_default_keymap),
+};
+
+static void tegra_kbc_report_released_keys(struct input_dev *input,
+					   unsigned short old_keycodes[],
+					   unsigned int old_num_keys,
+					   unsigned short new_keycodes[],
+					   unsigned int new_num_keys)
+{
+	unsigned int i, j;
+
+	for (i = 0; i < old_num_keys; i++) {
+		for (j = 0; j < new_num_keys; j++)
+			if (old_keycodes[i] == new_keycodes[j])
+				break;
+
+		if (j == new_num_keys)
+			input_report_key(input, old_keycodes[i], 0);
+	}
+}
+
+static void tegra_kbc_report_pressed_keys(struct input_dev *input,
+					  unsigned char scancodes[],
+					  unsigned short keycodes[],
+					  unsigned int num_pressed_keys)
+{
+	unsigned int i;
+
+	for (i = 0; i < num_pressed_keys; i++) {
+		input_event(input, EV_MSC, MSC_SCAN, scancodes[i]);
+		input_report_key(input, keycodes[i], 1);
+	}
+}
+
+static void tegra_kbc_report_keys(struct tegra_kbc *kbc)
+{
+	unsigned char scancodes[KBC_MAX_KPENT];
+	unsigned short keycodes[KBC_MAX_KPENT];
+	u32 val = 0;
+	unsigned int i;
+	unsigned int num_down = 0;
+	unsigned long flags;
+	bool fn_keypress = 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);
+
+		if (val & 0x80) {
+			unsigned int col = val & 0x07;
+			unsigned int row = (val >> 3) & 0x0f;
+			unsigned char scancode =
+				MATRIX_SCAN_CODE(row, col, KBC_ROW_SHIFT);
+
+			scancodes[num_down] = scancode;
+			keycodes[num_down] = kbc->keycode[scancode];
+			/* If driver uses Fn map, do not report the Fn key. */
+			if ((keycodes[num_down] == KEY_FN) && kbc->use_fn_map)
+				fn_keypress = true;
+			else
+				num_down++;
+		}
+
+		val >>= 8;
+	}
+
+	/*
+	 * If the platform uses Fn keymaps, translate keys on a Fn keypress.
+	 * Function keycodes are KBC_MAX_KEY apart from the plain keycodes.
+	 */
+	if (fn_keypress) {
+		for (i = 0; i < num_down; i++) {
+			scancodes[i] += KBC_MAX_KEY;
+			keycodes[i] = kbc->keycode[scancodes[i]];
+		}
+	}
+
+	spin_unlock_irqrestore(&kbc->lock, flags);
+
+	tegra_kbc_report_released_keys(kbc->idev,
+				       kbc->current_keys, kbc->num_pressed_keys,
+				       keycodes, num_down);
+	tegra_kbc_report_pressed_keys(kbc->idev, scancodes, keycodes, num_down);
+	input_sync(kbc->idev);
+
+	memcpy(kbc->current_keys, keycodes, sizeof(kbc->current_keys));
+	kbc->num_pressed_keys = num_down;
+}
+
+static void tegra_kbc_keypress_timer(unsigned long data)
+{
+	struct tegra_kbc *kbc = (struct tegra_kbc *)data;
+	unsigned long flags;
+	u32 val;
+	unsigned int i;
+
+	val = (readl(kbc->mmio + KBC_INT_0) >> 4) & 0xf;
+	if (val) {
+		unsigned long dly;
+
+		tegra_kbc_report_keys(kbc);
+
+		/*
+		 * If more than one keys are pressed we need not wait
+		 * for the repoll delay.
+		 */
+		dly = (val == 1) ? kbc->repoll_dly : 1;
+		mod_timer(&kbc->timer, jiffies + msecs_to_jiffies(dly));
+	} else {
+		/* Release any pressed keys and exit the polling loop */
+		for (i = 0; i < kbc->num_pressed_keys; i++)
+			input_report_key(kbc->idev, kbc->current_keys[i], 0);
+		input_sync(kbc->idev);
+
+		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);
+	}
+}
+
+static irqreturn_t tegra_kbc_isr(int irq, void *args)
+{
+	struct tegra_kbc *kbc = args;
+	u32 val, ctl;
+
+	/*
+	 * 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);
+
+	/*
+	 * Quickly bail out & reenable interrupts if the fifo threshold
+	 * count interrupt wasn't the interrupt source
+	 */
+	val = readl(kbc->mmio + KBC_INT_0);
+	writel(val, kbc->mmio + KBC_INT_0);
+
+	if (val & KBC_INT_FIFO_CNT_INT_STATUS) {
+		/*
+		 * Schedule timer to run when hardware is in continuous
+		 * polling mode.
+		 */
+		mod_timer(&kbc->timer, jiffies + kbc->cp_dly_jiffies);
+	} else {
+		ctl |= KBC_CONTROL_FIFO_CNT_INT_EN;
+		writel(ctl, kbc->mmio + KBC_CONTROL_0);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static void tegra_kbc_setup_wakekeys(struct tegra_kbc *kbc, bool filter)
+{
+	const struct tegra_kbc_platform_data *pdata = kbc->pdata;
+	int i;
+	unsigned int rst_val;
+
+	BUG_ON(pdata->wake_cnt > KBC_MAX_KEY);
+	rst_val = (filter && pdata->wake_cnt) ? ~0 : 0;
+
+	for (i = 0; i < KBC_MAX_ROW; i++)
+		writel(rst_val, kbc->mmio + KBC_ROW0_MASK_0 + i * 4);
+
+	if (filter) {
+		for (i = 0; i < pdata->wake_cnt; i++) {
+			u32 val, addr;
+			addr = pdata->wake_cfg[i].row * 4 + KBC_ROW0_MASK_0;
+			val = readl(kbc->mmio + addr);
+			val &= ~(1 << pdata->wake_cfg[i].col);
+			writel(val, kbc->mmio + addr);
+		}
+	}
+}
+
+static void tegra_kbc_config_pins(struct tegra_kbc *kbc)
+{
+	const struct tegra_kbc_platform_data *pdata = kbc->pdata;
+	int i;
+
+	for (i = 0; i < KBC_MAX_GPIO; i++) {
+		u32 r_shft = 5 * (i % 6);
+		u32 c_shft = 4 * (i % 8);
+		u32 r_mask = 0x1f << r_shft;
+		u32 c_mask = 0x0f << c_shft;
+		u32 r_offs = (i / 6) * 4 + KBC_ROW_CFG0_0;
+		u32 c_offs = (i / 8) * 4 + KBC_COL_CFG0_0;
+		u32 row_cfg = readl(kbc->mmio + r_offs);
+		u32 col_cfg = readl(kbc->mmio + c_offs);
+
+		row_cfg &= ~r_mask;
+		col_cfg &= ~c_mask;
+
+		if (pdata->pin_cfg[i].is_row)
+			row_cfg |= ((pdata->pin_cfg[i].num << 1) | 1) << r_shft;
+		else
+			col_cfg |= ((pdata->pin_cfg[i].num << 1) | 1) << c_shft;
+
+		writel(row_cfg, kbc->mmio + r_offs);
+		writel(col_cfg, kbc->mmio + c_offs);
+	}
+}
+
+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;
+
+	clk_enable(kbc->clk);
+
+	/* Reset the KBC controller to clear all previous status.*/
+	tegra_periph_reset_assert(kbc->clk);
+	udelay(100);
+	tegra_periph_reset_deassert(kbc->clk);
+	udelay(100);
+
+	tegra_kbc_config_pins(kbc);
+	tegra_kbc_setup_wakekeys(kbc, false);
+
+	writel(pdata->repeat_cnt, kbc->mmio + KBC_RPT_DLY_0);
+
+	/* Keyboard debounce count is maximum of 12 bits. */
+	debounce_cnt = min(pdata->debounce_cnt, KBC_MAX_DEBOUNCE_CNT);
+	val = KBC_DEBOUNCE_CNT_SHIFT(debounce_cnt);
+	val |= KBC_FIFO_TH_CNT_SHIFT(1); /* set fifo interrupt threshold to 1 */
+	val |= KBC_CONTROL_FIFO_CNT_INT_EN;  /* interrupt on FIFO threshold */
+	val |= KBC_CONTROL_KBC_EN;     /* enable */
+	writel(val, kbc->mmio + KBC_CONTROL_0);
+
+	/*
+	 * Compute the delay(ns) from interrupt mode to continuous polling
+	 * mode so the timer routine is scheduled appropriately.
+	 */
+	val = readl(kbc->mmio + KBC_INIT_DLY_0);
+	kbc->cp_dly_jiffies = usecs_to_jiffies((val & 0xfffff) * 32);
+
+	kbc->num_pressed_keys = 0;
+
+	/*
+	 * 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;
+		if (!val)
+			break;
+
+		val = readl(kbc->mmio + KBC_KP_ENT0_0);
+		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);
+
+	return 0;
+}
+
+static void tegra_kbc_stop(struct tegra_kbc *kbc)
+{
+	unsigned long flags;
+	u32 val;
+
+	spin_lock_irqsave(&kbc->lock, flags);
+	val = readl(kbc->mmio + KBC_CONTROL_0);
+	val &= ~1;
+	writel(val, kbc->mmio + KBC_CONTROL_0);
+	spin_unlock_irqrestore(&kbc->lock, flags);
+
+	disable_irq(kbc->irq);
+	del_timer_sync(&kbc->timer);
+
+	clk_disable(kbc->clk);
+}
+
+static int tegra_kbc_open(struct input_dev *dev)
+{
+	struct tegra_kbc *kbc = input_get_drvdata(dev);
+
+	return tegra_kbc_start(kbc);
+}
+
+static void tegra_kbc_close(struct input_dev *dev)
+{
+	struct tegra_kbc *kbc = input_get_drvdata(dev);
+
+	return tegra_kbc_stop(kbc);
+}
+
+static bool __devinit
+tegra_kbc_check_pin_cfg(const struct tegra_kbc_platform_data *pdata,
+			struct device *dev, unsigned int *num_rows)
+{
+	int i;
+
+	*num_rows = 0;
+
+	for (i = 0; i < KBC_MAX_GPIO; i++) {
+		const struct tegra_kbc_pin_cfg *pin_cfg = &pdata->pin_cfg[i];
+
+		if (pin_cfg->is_row) {
+			if (pin_cfg->num >= KBC_MAX_ROW) {
+				dev_err(dev,
+					"pin_cfg[%d]: invalid row number %d\n",
+					i, pin_cfg->num);
+				return false;
+			}
+			(*num_rows)++;
+		} else {
+			if (pin_cfg->num >= KBC_MAX_COL) {
+				dev_err(dev,
+					"pin_cfg[%d]: invalid column number %d\n",
+					i, pin_cfg->num);
+				return false;
+			}
+		}
+	}
+
+	return true;
+}
+
+static int __devinit tegra_kbc_probe(struct platform_device *pdev)
+{
+	const struct tegra_kbc_platform_data *pdata = pdev->dev.platform_data;
+	const struct matrix_keymap_data *keymap_data;
+	struct tegra_kbc *kbc;
+	struct input_dev *input_dev;
+	struct resource *res;
+	int irq;
+	int err;
+	int i;
+	int num_rows = 0;
+	unsigned int debounce_cnt;
+	unsigned int scan_time_rows;
+
+	if (!pdata)
+		return -EINVAL;
+
+	if (!tegra_kbc_check_pin_cfg(pdata, &pdev->dev, &num_rows))
+		return -EINVAL;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&pdev->dev, "failed to get I/O memory\n");
+		return -ENXIO;
+	}
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		dev_err(&pdev->dev, "failed to get keyboard IRQ\n");
+		return -ENXIO;
+	}
+
+	kbc = kzalloc(sizeof(*kbc), GFP_KERNEL);
+	input_dev = input_allocate_device();
+	if (!kbc || !input_dev) {
+		err = -ENOMEM;
+		goto err_free_mem;
+	}
+
+	kbc->pdata = pdata;
+	kbc->idev = input_dev;
+	kbc->irq = irq;
+	spin_lock_init(&kbc->lock);
+	setup_timer(&kbc->timer, tegra_kbc_keypress_timer, (unsigned long)kbc);
+
+	res = request_mem_region(res->start, resource_size(res), pdev->name);
+	if (!res) {
+		dev_err(&pdev->dev, "failed to request I/O memory\n");
+		err = -EBUSY;
+		goto err_free_mem;
+	}
+
+	kbc->mmio = ioremap(res->start, resource_size(res));
+	if (!kbc->mmio) {
+		dev_err(&pdev->dev, "failed to remap I/O memory\n");
+		err = -ENXIO;
+		goto err_free_mem_region;
+	}
+
+	kbc->clk = clk_get(&pdev->dev, NULL);
+	if (IS_ERR(kbc->clk)) {
+		dev_err(&pdev->dev, "failed to get keyboard clock\n");
+		err = PTR_ERR(kbc->clk);
+		goto err_iounmap;
+	}
+
+	kbc->wake_enable_rows = 0;
+	kbc->wake_enable_cols = 0;
+	for (i = 0; i < pdata->wake_cnt; i++) {
+		kbc->wake_enable_rows |= (1 << pdata->wake_cfg[i].row);
+		kbc->wake_enable_cols |= (1 << pdata->wake_cfg[i].col);
+	}
+
+	/*
+	 * The time delay between two consecutive reads of the FIFO is
+	 * the sum of the repeat time and the time taken for scanning
+	 * the rows. There is an additional delay before the row scanning
+	 * starts. The repoll delay is computed in milliseconds.
+	 */
+	debounce_cnt = min(pdata->debounce_cnt, KBC_MAX_DEBOUNCE_CNT);
+	scan_time_rows = (KBC_ROW_SCAN_TIME + debounce_cnt) * num_rows;
+	kbc->repoll_dly = KBC_ROW_SCAN_DLY + scan_time_rows + pdata->repeat_cnt;
+	kbc->repoll_dly = ((kbc->repoll_dly * KBC_CYCLE_USEC) + 999) / 1000;
+
+	input_dev->name = pdev->name;
+	input_dev->id.bustype = BUS_HOST;
+	input_dev->dev.parent = &pdev->dev;
+	input_dev->open = tegra_kbc_open;
+	input_dev->close = tegra_kbc_close;
+
+	input_set_drvdata(input_dev, kbc);
+
+	input_dev->evbit[0] = BIT_MASK(EV_KEY);
+	input_set_capability(input_dev, EV_MSC, MSC_SCAN);
+
+	input_dev->keycode = kbc->keycode;
+	input_dev->keycodesize = sizeof(kbc->keycode[0]);
+	input_dev->keycodemax = KBC_MAX_KEY;
+	if (pdata->use_fn_map)
+		input_dev->keycodemax *= 2;
+
+	kbc->use_fn_map = pdata->use_fn_map;
+	keymap_data = pdata->keymap_data ?: &tegra_kbc_default_keymap_data;
+	matrix_keypad_build_keymap(keymap_data, KBC_ROW_SHIFT,
+				   input_dev->keycode, input_dev->keybit);
+
+	err = request_irq(kbc->irq, tegra_kbc_isr, IRQF_TRIGGER_HIGH,
+			  pdev->name, kbc);
+	if (err) {
+		dev_err(&pdev->dev, "failed to request keyboard IRQ\n");
+		goto err_put_clk;
+	}
+
+	disable_irq(kbc->irq);
+
+	err = input_register_device(kbc->idev);
+	if (err) {
+		dev_err(&pdev->dev, "failed to register input device\n");
+		goto err_free_irq;
+	}
+
+	platform_set_drvdata(pdev, kbc);
+	device_init_wakeup(&pdev->dev, pdata->wakeup);
+
+	return 0;
+
+err_free_irq:
+	free_irq(kbc->irq, pdev);
+err_put_clk:
+	clk_put(kbc->clk);
+err_iounmap:
+	iounmap(kbc->mmio);
+err_free_mem_region:
+	release_mem_region(res->start, resource_size(res));
+err_free_mem:
+	input_free_device(kbc->idev);
+	kfree(kbc);
+
+	return err;
+}
+
+static int __devexit tegra_kbc_remove(struct platform_device *pdev)
+{
+	struct tegra_kbc *kbc = platform_get_drvdata(pdev);
+	struct resource *res;
+
+	free_irq(kbc->irq, pdev);
+	clk_put(kbc->clk);
+
+	input_unregister_device(kbc->idev);
+	iounmap(kbc->mmio);
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	release_mem_region(res->start, resource_size(res));
+
+	kfree(kbc);
+
+	platform_set_drvdata(pdev, NULL);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int tegra_kbc_suspend(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct tegra_kbc *kbc = platform_get_drvdata(pdev);
+
+	if (device_may_wakeup(&pdev->dev)) {
+		tegra_kbc_setup_wakekeys(kbc, true);
+		enable_irq_wake(kbc->irq);
+		/* Forcefully clear the interrupt status */
+		writel(0x7, kbc->mmio + KBC_INT_0);
+		msleep(30);
+	} else {
+		mutex_lock(&kbc->idev->mutex);
+		if (kbc->idev->users)
+			tegra_kbc_stop(kbc);
+		mutex_unlock(&kbc->idev->mutex);
+	}
+
+	return 0;
+}
+
+static int tegra_kbc_resume(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct tegra_kbc *kbc = platform_get_drvdata(pdev);
+	int err = 0;
+
+	if (device_may_wakeup(&pdev->dev)) {
+		disable_irq_wake(kbc->irq);
+		tegra_kbc_setup_wakekeys(kbc, false);
+	} else {
+		mutex_lock(&kbc->idev->mutex);
+		if (kbc->idev->users)
+			err = tegra_kbc_start(kbc);
+		mutex_unlock(&kbc->idev->mutex);
+	}
+
+	return err;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(tegra_kbc_pm_ops, tegra_kbc_suspend, tegra_kbc_resume);
+
+static struct platform_driver tegra_kbc_driver = {
+	.probe		= tegra_kbc_probe,
+	.remove		= __devexit_p(tegra_kbc_remove),
+	.driver	= {
+		.name	= "tegra-kbc",
+		.owner  = THIS_MODULE,
+		.pm	= &tegra_kbc_pm_ops,
+	},
+};
+
+static void __exit tegra_kbc_exit(void)
+{
+	platform_driver_unregister(&tegra_kbc_driver);
+}
+module_exit(tegra_kbc_exit);
+
+static int __init tegra_kbc_init(void)
+{
+	return platform_driver_register(&tegra_kbc_driver);
+}
+module_init(tegra_kbc_init);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Rakesh Iyer <riyer@nvidia.com>");
+MODULE_DESCRIPTION("Tegra matrix keyboard controller driver");
+MODULE_ALIAS("platform:tegra-kbc");
diff -druNp linux-libre-2.6.37-gnu1/drivers/input/keyboard/tnetv107x-keypad.c linux-libre-2.6.38-gnu1/drivers/input/keyboard/tnetv107x-keypad.c
--- linux-libre-2.6.37-gnu1/drivers/input/keyboard/tnetv107x-keypad.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/input/keyboard/tnetv107x-keypad.c	2011-03-14 21:20:32.000000000 -0400
@@ -14,6 +14,7 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/err.h>
 #include <linux/errno.h>
 #include <linux/input.h>
 #include <linux/platform_device.h>
@@ -219,9 +220,9 @@ static int __devinit keypad_probe(struct
 	}
 
 	kp->clk = clk_get(dev, NULL);
-	if (!kp->clk) {
+	if (IS_ERR(kp->clk)) {
 		dev_err(dev, "cannot claim device clock\n");
-		error = -EINVAL;
+		error = PTR_ERR(kp->clk);
 		goto error_clk;
 	}
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/input/Makefile linux-libre-2.6.38-gnu1/drivers/input/Makefile
--- linux-libre-2.6.37-gnu1/drivers/input/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/input/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@
 # Each configuration option enables a list of files.
 
 obj-$(CONFIG_INPUT)		+= input-core.o
-input-core-objs := input.o input-compat.o ff-core.o
+input-core-y := input.o input-compat.o input-mt.o ff-core.o
 
 obj-$(CONFIG_INPUT_FF_MEMLESS)	+= ff-memless.o
 obj-$(CONFIG_INPUT_POLLDEV)	+= input-polldev.o
diff -druNp linux-libre-2.6.37-gnu1/drivers/input/misc/cma3000_d0x.c linux-libre-2.6.38-gnu1/drivers/input/misc/cma3000_d0x.c
--- linux-libre-2.6.37-gnu1/drivers/input/misc/cma3000_d0x.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/input/misc/cma3000_d0x.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,398 @@
+/*
+ * VTI CMA3000_D0x Accelerometer driver
+ *
+ * Copyright (C) 2010 Texas Instruments
+ * Author: Hemanth V <hemanthv@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 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/>.
+ */
+
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/input.h>
+#include <linux/input/cma3000.h>
+
+#include "cma3000_d0x.h"
+
+#define CMA3000_WHOAMI      0x00
+#define CMA3000_REVID       0x01
+#define CMA3000_CTRL        0x02
+#define CMA3000_STATUS      0x03
+#define CMA3000_RSTR        0x04
+#define CMA3000_INTSTATUS   0x05
+#define CMA3000_DOUTX       0x06
+#define CMA3000_DOUTY       0x07
+#define CMA3000_DOUTZ       0x08
+#define CMA3000_MDTHR       0x09
+#define CMA3000_MDFFTMR     0x0A
+#define CMA3000_FFTHR       0x0B
+
+#define CMA3000_RANGE2G    (1 << 7)
+#define CMA3000_RANGE8G    (0 << 7)
+#define CMA3000_BUSI2C     (0 << 4)
+#define CMA3000_MODEMASK   (7 << 1)
+#define CMA3000_GRANGEMASK (1 << 7)
+
+#define CMA3000_STATUS_PERR    1
+#define CMA3000_INTSTATUS_FFDET (1 << 2)
+
+/* Settling time delay in ms */
+#define CMA3000_SETDELAY    30
+
+/* Delay for clearing interrupt in us */
+#define CMA3000_INTDELAY    44
+
+
+/*
+ * Bit weights in mg for bit 0, other bits need
+ * multipy factor 2^n. Eight bit is the sign bit.
+ */
+#define BIT_TO_2G  18
+#define BIT_TO_8G  71
+
+struct cma3000_accl_data {
+	const struct cma3000_bus_ops *bus_ops;
+	const struct cma3000_platform_data *pdata;
+
+	struct device *dev;
+	struct input_dev *input_dev;
+
+	int bit_to_mg;
+	int irq;
+
+	int g_range;
+	u8 mode;
+
+	struct mutex mutex;
+	bool opened;
+	bool suspended;
+};
+
+#define CMA3000_READ(data, reg, msg) \
+	(data->bus_ops->read(data->dev, reg, msg))
+#define CMA3000_SET(data, reg, val, msg) \
+	((data)->bus_ops->write(data->dev, reg, val, msg))
+
+/*
+ * Conversion for each of the eight modes to g, depending
+ * on G range i.e 2G or 8G. Some modes always operate in
+ * 8G.
+ */
+
+static int mode_to_mg[8][2] = {
+	{ 0, 0 },
+	{ BIT_TO_8G, BIT_TO_2G },
+	{ BIT_TO_8G, BIT_TO_2G },
+	{ BIT_TO_8G, BIT_TO_8G },
+	{ BIT_TO_8G, BIT_TO_8G },
+	{ BIT_TO_8G, BIT_TO_2G },
+	{ BIT_TO_8G, BIT_TO_2G },
+	{ 0, 0},
+};
+
+static void decode_mg(struct cma3000_accl_data *data, int *datax,
+				int *datay, int *dataz)
+{
+	/* Data in 2's complement, convert to mg */
+	*datax = ((s8)*datax) * data->bit_to_mg;
+	*datay = ((s8)*datay) * data->bit_to_mg;
+	*dataz = ((s8)*dataz) * data->bit_to_mg;
+}
+
+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;
+
+	intr_status = CMA3000_READ(data, CMA3000_INTSTATUS, "interrupt status");
+	if (intr_status < 0)
+		return IRQ_NONE;
+
+	/* Check if free fall is detected, report immediately */
+	if (intr_status & CMA3000_INTSTATUS_FFDET) {
+		input_report_abs(data->input_dev, ABS_MISC, 1);
+		input_sync(data->input_dev);
+	} else {
+		input_report_abs(data->input_dev, ABS_MISC, 0);
+	}
+
+	datax = CMA3000_READ(data, CMA3000_DOUTX, "X");
+	datay = CMA3000_READ(data, CMA3000_DOUTY, "Y");
+	dataz = CMA3000_READ(data, CMA3000_DOUTZ, "Z");
+
+	ctrl = CMA3000_READ(data, CMA3000_CTRL, "ctrl");
+	mode = (ctrl & CMA3000_MODEMASK) >> 1;
+	range = (ctrl & CMA3000_GRANGEMASK) >> 7;
+
+	data->bit_to_mg = mode_to_mg[mode][range];
+
+	/* Interrupt not for this device */
+	if (data->bit_to_mg == 0)
+		return IRQ_NONE;
+
+	/* Decode register values to milli g */
+	decode_mg(data, &datax, &datay, &dataz);
+
+	input_report_abs(data->input_dev, ABS_X, datax);
+	input_report_abs(data->input_dev, ABS_Y, datay);
+	input_report_abs(data->input_dev, ABS_Z, dataz);
+	input_sync(data->input_dev);
+
+	return IRQ_HANDLED;
+}
+
+static int cma3000_reset(struct cma3000_accl_data *data)
+{
+	int val;
+
+	/* Reset sequence */
+	CMA3000_SET(data, CMA3000_RSTR, 0x02, "Reset");
+	CMA3000_SET(data, CMA3000_RSTR, 0x0A, "Reset");
+	CMA3000_SET(data, CMA3000_RSTR, 0x04, "Reset");
+
+	/* Settling time delay */
+	mdelay(10);
+
+	val = CMA3000_READ(data, CMA3000_STATUS, "Status");
+	if (val < 0) {
+		dev_err(data->dev, "Reset failed\n");
+		return val;
+	}
+
+	if (val & CMA3000_STATUS_PERR) {
+		dev_err(data->dev, "Parity Error\n");
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static int cma3000_poweron(struct cma3000_accl_data *data)
+{
+	const struct cma3000_platform_data *pdata = data->pdata;
+	u8 ctrl = 0;
+	int ret;
+
+	if (data->g_range == CMARANGE_2G) {
+		ctrl = (data->mode << 1) | CMA3000_RANGE2G;
+	} else if (data->g_range == CMARANGE_8G) {
+		ctrl = (data->mode << 1) | CMA3000_RANGE8G;
+	} else {
+		dev_info(data->dev,
+			 "Invalid G range specified, assuming 8G\n");
+		ctrl = (data->mode << 1) | CMA3000_RANGE8G;
+	}
+
+	ctrl |= data->bus_ops->ctrl_mod;
+
+	CMA3000_SET(data, CMA3000_MDTHR, pdata->mdthr,
+		    "Motion Detect Threshold");
+	CMA3000_SET(data, CMA3000_MDFFTMR, pdata->mdfftmr,
+		    "Time register");
+	CMA3000_SET(data, CMA3000_FFTHR, pdata->ffthr,
+		    "Free fall threshold");
+	ret = CMA3000_SET(data, CMA3000_CTRL, ctrl, "Mode setting");
+	if (ret < 0)
+		return -EIO;
+
+	msleep(CMA3000_SETDELAY);
+
+	return 0;
+}
+
+static int cma3000_poweroff(struct cma3000_accl_data *data)
+{
+	int ret;
+
+	ret = CMA3000_SET(data, CMA3000_CTRL, CMAMODE_POFF, "Mode setting");
+	msleep(CMA3000_SETDELAY);
+
+	return ret;
+}
+
+static int cma3000_open(struct input_dev *input_dev)
+{
+	struct cma3000_accl_data *data = input_get_drvdata(input_dev);
+
+	mutex_lock(&data->mutex);
+
+	if (!data->suspended)
+		cma3000_poweron(data);
+
+	data->opened = true;
+
+	mutex_unlock(&data->mutex);
+
+	return 0;
+}
+
+static void cma3000_close(struct input_dev *input_dev)
+{
+	struct cma3000_accl_data *data = input_get_drvdata(input_dev);
+
+	mutex_lock(&data->mutex);
+
+	if (!data->suspended)
+		cma3000_poweroff(data);
+
+	data->opened = false;
+
+	mutex_unlock(&data->mutex);
+}
+
+void cma3000_suspend(struct cma3000_accl_data *data)
+{
+	mutex_lock(&data->mutex);
+
+	if (!data->suspended && data->opened)
+		cma3000_poweroff(data);
+
+	data->suspended = true;
+
+	mutex_unlock(&data->mutex);
+}
+EXPORT_SYMBOL(cma3000_suspend);
+
+
+void cma3000_resume(struct cma3000_accl_data *data)
+{
+	mutex_lock(&data->mutex);
+
+	if (data->suspended && data->opened)
+		cma3000_poweron(data);
+
+	data->suspended = false;
+
+	mutex_unlock(&data->mutex);
+}
+EXPORT_SYMBOL(cma3000_resume);
+
+struct cma3000_accl_data *cma3000_init(struct device *dev, int irq,
+				       const struct cma3000_bus_ops *bops)
+{
+	const struct cma3000_platform_data *pdata = dev->platform_data;
+	struct cma3000_accl_data *data;
+	struct input_dev *input_dev;
+	int rev;
+	int error;
+
+	if (!pdata) {
+		dev_err(dev, "platform data not found\n");
+		error = -EINVAL;
+		goto err_out;
+	}
+
+
+	/* if no IRQ return error */
+	if (irq == 0) {
+		error = -EINVAL;
+		goto err_out;
+	}
+
+	data = kzalloc(sizeof(struct cma3000_accl_data), GFP_KERNEL);
+	input_dev = input_allocate_device();
+	if (!data || !input_dev) {
+		error = -ENOMEM;
+		goto err_free_mem;
+	}
+
+	data->dev = dev;
+	data->input_dev = input_dev;
+	data->bus_ops = bops;
+	data->pdata = pdata;
+	data->irq = irq;
+	mutex_init(&data->mutex);
+
+	data->mode = pdata->mode;
+	if (data->mode < CMAMODE_DEFAULT || data->mode > CMAMODE_POFF) {
+		data->mode = CMAMODE_MOTDET;
+		dev_warn(dev,
+			 "Invalid mode specified, assuming Motion Detect\n");
+	}
+
+	data->g_range = pdata->g_range;
+	if (data->g_range != CMARANGE_2G && data->g_range != CMARANGE_8G) {
+		dev_info(dev,
+			 "Invalid G range specified, assuming 8G\n");
+		data->g_range = CMARANGE_8G;
+	}
+
+	input_dev->name = "cma3000-accelerometer";
+	input_dev->id.bustype = bops->bustype;
+	input_dev->open = cma3000_open;
+	input_dev->close = cma3000_close;
+
+	 __set_bit(EV_ABS, input_dev->evbit);
+
+	input_set_abs_params(input_dev, ABS_X,
+			-data->g_range, data->g_range, pdata->fuzz_x, 0);
+	input_set_abs_params(input_dev, ABS_Y,
+			-data->g_range, data->g_range, pdata->fuzz_y, 0);
+	input_set_abs_params(input_dev, ABS_Z,
+			-data->g_range, data->g_range, pdata->fuzz_z, 0);
+	input_set_abs_params(input_dev, ABS_MISC, 0, 1, 0, 0);
+
+	input_set_drvdata(input_dev, data);
+
+	error = cma3000_reset(data);
+	if (error)
+		goto err_free_mem;
+
+	rev = CMA3000_READ(data, CMA3000_REVID, "Revid");
+	if (rev < 0) {
+		error = rev;
+		goto err_free_mem;
+	}
+
+	pr_info("CMA3000 Accelerometer: Revision %x\n", rev);
+
+	error = request_threaded_irq(irq, NULL, cma3000_thread_irq,
+				     pdata->irqflags | IRQF_ONESHOT,
+				     "cma3000_d0x", data);
+	if (error) {
+		dev_err(dev, "request_threaded_irq failed\n");
+		goto err_free_mem;
+	}
+
+	error = input_register_device(data->input_dev);
+	if (error) {
+		dev_err(dev, "Unable to register input device\n");
+		goto err_free_irq;
+	}
+
+	return data;
+
+err_free_irq:
+	free_irq(irq, data);
+err_free_mem:
+	input_free_device(input_dev);
+	kfree(data);
+err_out:
+	return ERR_PTR(error);
+}
+EXPORT_SYMBOL(cma3000_init);
+
+void cma3000_exit(struct cma3000_accl_data *data)
+{
+	free_irq(data->irq, data);
+	input_unregister_device(data->input_dev);
+	kfree(data);
+}
+EXPORT_SYMBOL(cma3000_exit);
+
+MODULE_DESCRIPTION("CMA3000-D0x Accelerometer Driver");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Hemanth V <hemanthv@ti.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/input/misc/cma3000_d0x.h linux-libre-2.6.38-gnu1/drivers/input/misc/cma3000_d0x.h
--- linux-libre-2.6.37-gnu1/drivers/input/misc/cma3000_d0x.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/input/misc/cma3000_d0x.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,42 @@
+/*
+ * VTI CMA3000_D0x Accelerometer driver
+ *
+ * Copyright (C) 2010 Texas Instruments
+ * Author: Hemanth V <hemanthv@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 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 _INPUT_CMA3000_H
+#define _INPUT_CMA3000_H
+
+#include <linux/types.h>
+#include <linux/input.h>
+
+struct device;
+struct cma3000_accl_data;
+
+struct cma3000_bus_ops {
+	u16 bustype;
+	u8 ctrl_mod;
+	int (*read)(struct device *, u8, char *);
+	int (*write)(struct device *, u8, u8, char *);
+};
+
+struct cma3000_accl_data *cma3000_init(struct device *dev, int irq,
+					const struct cma3000_bus_ops *bops);
+void cma3000_exit(struct cma3000_accl_data *);
+void cma3000_suspend(struct cma3000_accl_data *);
+void cma3000_resume(struct cma3000_accl_data *);
+
+#endif
diff -druNp linux-libre-2.6.37-gnu1/drivers/input/misc/cma3000_d0x_i2c.c linux-libre-2.6.38-gnu1/drivers/input/misc/cma3000_d0x_i2c.c
--- linux-libre-2.6.37-gnu1/drivers/input/misc/cma3000_d0x_i2c.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/input/misc/cma3000_d0x_i2c.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,143 @@
+/*
+ * Implements I2C interface for VTI CMA300_D0x Accelerometer driver
+ *
+ * Copyright (C) 2010 Texas Instruments
+ * Author: Hemanth V <hemanthv@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 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/>.
+ */
+
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/input/cma3000.h>
+#include "cma3000_d0x.h"
+
+static int cma3000_i2c_set(struct device *dev,
+			   u8 reg, u8 val, char *msg)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	int ret;
+
+	ret = i2c_smbus_write_byte_data(client, reg, val);
+	if (ret < 0)
+		dev_err(&client->dev,
+			"%s failed (%s, %d)\n", __func__, msg, ret);
+	return ret;
+}
+
+static int cma3000_i2c_read(struct device *dev, u8 reg, char *msg)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	int ret;
+
+	ret = i2c_smbus_read_byte_data(client, reg);
+	if (ret < 0)
+		dev_err(&client->dev,
+			"%s failed (%s, %d)\n", __func__, msg, ret);
+	return ret;
+}
+
+static const struct cma3000_bus_ops cma3000_i2c_bops = {
+	.bustype	= BUS_I2C,
+#define CMA3000_BUSI2C     (0 << 4)
+	.ctrl_mod	= CMA3000_BUSI2C,
+	.read		= cma3000_i2c_read,
+	.write		= cma3000_i2c_set,
+};
+
+static int __devinit cma3000_i2c_probe(struct i2c_client *client,
+					const struct i2c_device_id *id)
+{
+	struct cma3000_accl_data *data;
+
+	data = cma3000_init(&client->dev, client->irq, &cma3000_i2c_bops);
+	if (IS_ERR(data))
+		return PTR_ERR(data);
+
+	i2c_set_clientdata(client, data);
+
+	return 0;
+}
+
+static int __devexit cma3000_i2c_remove(struct i2c_client *client)
+{
+	struct cma3000_accl_data *data = i2c_get_clientdata(client);
+
+	cma3000_exit(data);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int cma3000_i2c_suspend(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct cma3000_accl_data *data = i2c_get_clientdata(client);
+
+	cma3000_suspend(data);
+
+	return 0;
+}
+
+static int cma3000_i2c_resume(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct cma3000_accl_data *data = i2c_get_clientdata(client);
+
+	cma3000_resume(data);
+
+	return 0;
+}
+
+static const struct dev_pm_ops cma3000_i2c_pm_ops = {
+	.suspend	= cma3000_i2c_suspend,
+	.resume		= cma3000_i2c_resume,
+};
+#endif
+
+static const struct i2c_device_id cma3000_i2c_id[] = {
+	{ "cma3000_d01", 0 },
+	{ },
+};
+
+MODULE_DEVICE_TABLE(i2c, cma3000_i2c_id);
+
+static struct i2c_driver cma3000_i2c_driver = {
+	.probe		= cma3000_i2c_probe,
+	.remove		= __devexit_p(cma3000_i2c_remove),
+	.id_table	= cma3000_i2c_id,
+	.driver = {
+		.name	= "cma3000_i2c_accl",
+		.owner	= THIS_MODULE,
+#ifdef CONFIG_PM
+		.pm	= &cma3000_i2c_pm_ops,
+#endif
+	},
+};
+
+static int __init cma3000_i2c_init(void)
+{
+	return i2c_add_driver(&cma3000_i2c_driver);
+}
+
+static void __exit cma3000_i2c_exit(void)
+{
+	i2c_del_driver(&cma3000_i2c_driver);
+}
+
+module_init(cma3000_i2c_init);
+module_exit(cma3000_i2c_exit);
+
+MODULE_DESCRIPTION("CMA3000-D0x Accelerometer I2C Driver");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Hemanth V <hemanthv@ti.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/input/misc/ixp4xx-beeper.c linux-libre-2.6.38-gnu1/drivers/input/misc/ixp4xx-beeper.c
--- linux-libre-2.6.37-gnu1/drivers/input/misc/ixp4xx-beeper.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/input/misc/ixp4xx-beeper.c	2011-03-14 21:20:32.000000000 -0400
@@ -69,11 +69,7 @@ static int ixp4xx_spkr_event(struct inpu
 	}
 
 	if (value > 20 && value < 32767)
-#ifndef FREQ
-		count = (ixp4xx_get_board_tick_rate() / (value * 4)) - 1;
-#else
-		count = (FREQ / (value * 4)) - 1;
-#endif
+		count = (IXP4XX_TIMER_FREQ / (value * 4)) - 1;
 
 	ixp4xx_spkr_control(pin, count);
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/input/misc/Kconfig linux-libre-2.6.38-gnu1/drivers/input/misc/Kconfig
--- linux-libre-2.6.37-gnu1/drivers/input/misc/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/input/misc/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -294,24 +294,6 @@ config INPUT_SGI_BTNS
 	  To compile this driver as a module, choose M here: the
 	  module will be called sgi_btns.
 
-config INPUT_WINBOND_CIR
-	tristate "Winbond IR remote control"
-	depends on X86 && PNP
-	select NEW_LEDS
-	select LEDS_CLASS
-	select LEDS_TRIGGERS
-	select BITREVERSE
-	help
-	  Say Y here if you want to use the IR remote functionality found
-	  in some Winbond SuperI/O chips. Currently only the WPCD376I
-	  chip is supported (included in some Intel Media series motherboards).
-
-	  IR Receive and wake-on-IR from suspend and power-off is currently
-	  supported.
-
-	  To compile this driver as a module, choose M here: the module will be
-	  called winbond_cir.
-
 config HP_SDC_RTC
 	tristate "HP SDC Real Time Clock"
 	depends on (GSC || HP300) && SERIO
@@ -448,4 +430,28 @@ config INPUT_ADXL34X_SPI
 	  To compile this driver as a module, choose M here: the
 	  module will be called adxl34x-spi.
 
+config INPUT_CMA3000
+	tristate "VTI CMA3000 Tri-axis accelerometer"
+	help
+	  Say Y here if you want to use VTI CMA3000_D0x Accelerometer
+	  driver
+
+	  This driver currently only supports I2C interface to the
+	  controller. Also select the I2C method.
+
+	  If unsure, say N
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called cma3000_d0x.
+
+config INPUT_CMA3000_I2C
+	tristate "Support I2C bus connection"
+	depends on INPUT_CMA3000 && I2C
+	help
+	  Say Y here if you want to use VTI CMA3000_D0x Accelerometer
+	  through I2C interface.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called cma3000_d0x_i2c.
+
 endif
diff -druNp linux-libre-2.6.37-gnu1/drivers/input/misc/Makefile linux-libre-2.6.38-gnu1/drivers/input/misc/Makefile
--- linux-libre-2.6.37-gnu1/drivers/input/misc/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/input/misc/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -18,6 +18,8 @@ obj-$(CONFIG_INPUT_ATI_REMOTE2)		+= ati_
 obj-$(CONFIG_INPUT_ATLAS_BTNS)		+= atlas_btns.o
 obj-$(CONFIG_INPUT_BFIN_ROTARY)		+= bfin_rotary.o
 obj-$(CONFIG_INPUT_CM109)		+= cm109.o
+obj-$(CONFIG_INPUT_CMA3000)		+= cma3000_d0x.o
+obj-$(CONFIG_INPUT_CMA3000_I2C)		+= cma3000_d0x_i2c.o
 obj-$(CONFIG_INPUT_COBALT_BTNS)		+= cobalt_btns.o
 obj-$(CONFIG_INPUT_DM355EVM)		+= dm355evm_keys.o
 obj-$(CONFIG_HP_SDC_RTC)		+= hp_sdc_rtc.o
@@ -38,7 +40,6 @@ obj-$(CONFIG_INPUT_SPARCSPKR)		+= sparcs
 obj-$(CONFIG_INPUT_TWL4030_PWRBUTTON)	+= twl4030-pwrbutton.o
 obj-$(CONFIG_INPUT_TWL4030_VIBRA)	+= twl4030-vibra.o
 obj-$(CONFIG_INPUT_UINPUT)		+= uinput.o
-obj-$(CONFIG_INPUT_WINBOND_CIR)		+= winbond-cir.o
 obj-$(CONFIG_INPUT_WISTRON_BTNS)	+= wistron_btns.o
 obj-$(CONFIG_INPUT_WM831X_ON)		+= wm831x-on.o
 obj-$(CONFIG_INPUT_YEALINK)		+= yealink.o
diff -druNp linux-libre-2.6.37-gnu1/drivers/input/misc/pcf8574_keypad.c linux-libre-2.6.38-gnu1/drivers/input/misc/pcf8574_keypad.c
--- linux-libre-2.6.37-gnu1/drivers/input/misc/pcf8574_keypad.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/input/misc/pcf8574_keypad.c	2011-03-14 21:20:32.000000000 -0400
@@ -169,19 +169,29 @@ static int __devexit pcf8574_kp_remove(s
 }
 
 #ifdef CONFIG_PM
-static int pcf8574_kp_resume(struct i2c_client *client)
+static int pcf8574_kp_resume(struct device *dev)
 {
+	struct i2c_client *client = to_i2c_client(dev);
+
 	enable_irq(client->irq);
 
 	return 0;
 }
 
-static int pcf8574_kp_suspend(struct i2c_client *client, pm_message_t mesg)
+static int pcf8574_kp_suspend(struct device *dev)
 {
+	struct i2c_client *client = to_i2c_client(dev);
+
 	disable_irq(client->irq);
 
 	return 0;
 }
+
+static const struct dev_pm_ops pcf8574_kp_pm_ops = {
+	.suspend	= pcf8574_kp_suspend,
+	.resume		= pcf8574_kp_resume,
+};
+
 #else
 # define pcf8574_kp_resume  NULL
 # define pcf8574_kp_suspend NULL
@@ -197,11 +207,12 @@ static struct i2c_driver pcf8574_kp_driv
 	.driver = {
 		.name  = DRV_NAME,
 		.owner = THIS_MODULE,
+#ifdef CONFIG_PM
+		.pm = &pcf8574_kp_pm_ops,
+#endif
 	},
 	.probe    = pcf8574_kp_probe,
 	.remove   = __devexit_p(pcf8574_kp_remove),
-	.suspend  = pcf8574_kp_suspend,
-	.resume   = pcf8574_kp_resume,
 	.id_table = pcf8574_kp_id,
 };
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/input/misc/rotary_encoder.c linux-libre-2.6.38-gnu1/drivers/input/misc/rotary_encoder.c
--- linux-libre-2.6.37-gnu1/drivers/input/misc/rotary_encoder.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/input/misc/rotary_encoder.c	2011-03-14 21:20:32.000000000 -0400
@@ -176,7 +176,7 @@ static int __devinit rotary_encoder_prob
 
 	/* request the IRQs */
 	err = request_irq(encoder->irq_a, &rotary_encoder_irq,
-			  IORESOURCE_IRQ_HIGHEDGE | IORESOURCE_IRQ_LOWEDGE,
+			  IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
 			  DRV_NAME, encoder);
 	if (err) {
 		dev_err(&pdev->dev, "unable to request IRQ %d\n",
@@ -185,7 +185,7 @@ static int __devinit rotary_encoder_prob
 	}
 
 	err = request_irq(encoder->irq_b, &rotary_encoder_irq,
-			  IORESOURCE_IRQ_HIGHEDGE | IORESOURCE_IRQ_LOWEDGE,
+			  IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
 			  DRV_NAME, encoder);
 	if (err) {
 		dev_err(&pdev->dev, "unable to request IRQ %d\n",
diff -druNp linux-libre-2.6.37-gnu1/drivers/input/misc/uinput.c linux-libre-2.6.38-gnu1/drivers/input/misc/uinput.c
--- linux-libre-2.6.37-gnu1/drivers/input/misc/uinput.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/input/misc/uinput.c	2011-03-14 21:20:32.000000000 -0400
@@ -37,6 +37,7 @@
 #include <linux/fs.h>
 #include <linux/miscdevice.h>
 #include <linux/uinput.h>
+#include <linux/input/mt.h>
 #include "../input-compat.h"
 
 static int uinput_dev_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
@@ -406,8 +407,7 @@ static int uinput_setup_device(struct ui
 			goto exit;
 		if (test_bit(ABS_MT_SLOT, dev->absbit)) {
 			int nslot = input_abs_get_max(dev, ABS_MT_SLOT) + 1;
-			input_mt_create_slots(dev, nslot);
-			input_set_events_per_packet(dev, 6 * nslot);
+			input_mt_init_slots(dev, nslot);
 		} else if (test_bit(ABS_MT_POSITION_X, dev->absbit)) {
 			input_set_events_per_packet(dev, 60);
 		}
@@ -680,6 +680,10 @@ static long uinput_ioctl_handler(struct
 			retval = uinput_set_bit(arg, swbit, SW_MAX);
 			break;
 
+		case UI_SET_PROPBIT:
+			retval = uinput_set_bit(arg, propbit, INPUT_PROP_MAX);
+			break;
+
 		case UI_SET_PHYS:
 			if (udev->state == UIST_CREATED) {
 				retval = -EINVAL;
diff -druNp linux-libre-2.6.37-gnu1/drivers/input/misc/winbond-cir.c linux-libre-2.6.38-gnu1/drivers/input/misc/winbond-cir.c
--- linux-libre-2.6.37-gnu1/drivers/input/misc/winbond-cir.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/input/misc/winbond-cir.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1608 +0,0 @@
-/*
- *  winbond-cir.c - Driver for the Consumer IR functionality of Winbond
- *                  SuperI/O chips.
- *
- *  Currently supports the Winbond WPCD376i chip (PNP id WEC1022), but
- *  could probably support others (Winbond WEC102X, NatSemi, etc)
- *  with minor modifications.
- *
- *  Original Author: David H�rdeman <david@hardeman.nu>
- *     Copyright (C) 2009 David H�rdeman <david@hardeman.nu>
- *
- *  Dedicated to Matilda, my newborn daughter, without whose loving attention
- *  this driver would have been finished in half the time and with a fraction
- *  of the bugs.
- *
- *  Written using:
- *    o Winbond WPCD376I datasheet helpfully provided by Jesse Barnes at Intel
- *    o NatSemi PC87338/PC97338 datasheet (for the serial port stuff)
- *    o DSDT dumps
- *
- *  Supported features:
- *    o RC6
- *    o Wake-On-CIR functionality
- *
- *  To do:
- *    o Test NEC and RC5
- *
- *  Left as an exercise for the reader:
- *    o Learning (I have neither the hardware, nor the need)
- *    o IR Transmit (ibid)
- *
- *  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/pnp.h>
-#include <linux/interrupt.h>
-#include <linux/timer.h>
-#include <linux/input.h>
-#include <linux/leds.h>
-#include <linux/list.h>
-#include <linux/spinlock.h>
-#include <linux/pci_ids.h>
-#include <linux/io.h>
-#include <linux/bitrev.h>
-#include <linux/bitops.h>
-#include <linux/slab.h>
-
-#define DRVNAME "winbond-cir"
-
-/* CEIR Wake-Up Registers, relative to data->wbase                      */
-#define WBCIR_REG_WCEIR_CTL	0x03 /* CEIR Receiver Control		*/
-#define WBCIR_REG_WCEIR_STS	0x04 /* CEIR Receiver Status		*/
-#define WBCIR_REG_WCEIR_EV_EN	0x05 /* CEIR Receiver Event Enable	*/
-#define WBCIR_REG_WCEIR_CNTL	0x06 /* CEIR Receiver Counter Low	*/
-#define WBCIR_REG_WCEIR_CNTH	0x07 /* CEIR Receiver Counter High	*/
-#define WBCIR_REG_WCEIR_INDEX	0x08 /* CEIR Receiver Index		*/
-#define WBCIR_REG_WCEIR_DATA	0x09 /* CEIR Receiver Data		*/
-#define WBCIR_REG_WCEIR_CSL	0x0A /* CEIR Re. Compare Strlen		*/
-#define WBCIR_REG_WCEIR_CFG1	0x0B /* CEIR Re. Configuration 1	*/
-#define WBCIR_REG_WCEIR_CFG2	0x0C /* CEIR Re. Configuration 2	*/
-
-/* CEIR Enhanced Functionality Registers, relative to data->ebase       */
-#define WBCIR_REG_ECEIR_CTS	0x00 /* Enhanced IR Control Status	*/
-#define WBCIR_REG_ECEIR_CCTL	0x01 /* Infrared Counter Control	*/
-#define WBCIR_REG_ECEIR_CNT_LO	0x02 /* Infrared Counter LSB		*/
-#define WBCIR_REG_ECEIR_CNT_HI	0x03 /* Infrared Counter MSB		*/
-#define WBCIR_REG_ECEIR_IREM	0x04 /* Infrared Emitter Status		*/
-
-/* SP3 Banked Registers, relative to data->sbase                        */
-#define WBCIR_REG_SP3_BSR	0x03 /* Bank Select, all banks		*/
-				      /* Bank 0				*/
-#define WBCIR_REG_SP3_RXDATA	0x00 /* FIFO RX data (r)		*/
-#define WBCIR_REG_SP3_TXDATA	0x00 /* FIFO TX data (w)		*/
-#define WBCIR_REG_SP3_IER	0x01 /* Interrupt Enable		*/
-#define WBCIR_REG_SP3_EIR	0x02 /* Event Identification (r)	*/
-#define WBCIR_REG_SP3_FCR	0x02 /* FIFO Control (w)		*/
-#define WBCIR_REG_SP3_MCR	0x04 /* Mode Control			*/
-#define WBCIR_REG_SP3_LSR	0x05 /* Link Status			*/
-#define WBCIR_REG_SP3_MSR	0x06 /* Modem Status			*/
-#define WBCIR_REG_SP3_ASCR	0x07 /* Aux Status and Control		*/
-				      /* Bank 2				*/
-#define WBCIR_REG_SP3_BGDL	0x00 /* Baud Divisor LSB		*/
-#define WBCIR_REG_SP3_BGDH	0x01 /* Baud Divisor MSB		*/
-#define WBCIR_REG_SP3_EXCR1	0x02 /* Extended Control 1		*/
-#define WBCIR_REG_SP3_EXCR2	0x04 /* Extended Control 2		*/
-#define WBCIR_REG_SP3_TXFLV	0x06 /* TX FIFO Level			*/
-#define WBCIR_REG_SP3_RXFLV	0x07 /* RX FIFO Level			*/
-				      /* Bank 3				*/
-#define WBCIR_REG_SP3_MRID	0x00 /* Module Identification		*/
-#define WBCIR_REG_SP3_SH_LCR	0x01 /* LCR Shadow			*/
-#define WBCIR_REG_SP3_SH_FCR	0x02 /* FCR Shadow			*/
-				      /* Bank 4				*/
-#define WBCIR_REG_SP3_IRCR1	0x02 /* Infrared Control 1		*/
-				      /* Bank 5				*/
-#define WBCIR_REG_SP3_IRCR2	0x04 /* Infrared Control 2		*/
-				      /* Bank 6				*/
-#define WBCIR_REG_SP3_IRCR3	0x00 /* Infrared Control 3		*/
-#define WBCIR_REG_SP3_SIR_PW	0x02 /* SIR Pulse Width		*/
-				      /* Bank 7				*/
-#define WBCIR_REG_SP3_IRRXDC	0x00 /* IR RX Demod Control		*/
-#define WBCIR_REG_SP3_IRTXMC	0x01 /* IR TX Mod Control		*/
-#define WBCIR_REG_SP3_RCCFG	0x02 /* CEIR Config			*/
-#define WBCIR_REG_SP3_IRCFG1	0x04 /* Infrared Config 1		*/
-#define WBCIR_REG_SP3_IRCFG4	0x07 /* Infrared Config 4		*/
-
-/*
- * Magic values follow
- */
-
-/* No interrupts for WBCIR_REG_SP3_IER and WBCIR_REG_SP3_EIR */
-#define WBCIR_IRQ_NONE		0x00
-/* RX data bit for WBCIR_REG_SP3_IER and WBCIR_REG_SP3_EIR */
-#define WBCIR_IRQ_RX		0x01
-/* Over/Under-flow bit for WBCIR_REG_SP3_IER and WBCIR_REG_SP3_EIR */
-#define WBCIR_IRQ_ERR		0x04
-/* Led enable/disable bit for WBCIR_REG_ECEIR_CTS */
-#define WBCIR_LED_ENABLE	0x80
-/* RX data available bit for WBCIR_REG_SP3_LSR */
-#define WBCIR_RX_AVAIL		0x01
-/* RX disable bit for WBCIR_REG_SP3_ASCR */
-#define WBCIR_RX_DISABLE	0x20
-/* Extended mode enable bit for WBCIR_REG_SP3_EXCR1 */
-#define WBCIR_EXT_ENABLE	0x01
-/* Select compare register in WBCIR_REG_WCEIR_INDEX (bits 5 & 6) */
-#define WBCIR_REGSEL_COMPARE	0x10
-/* Select mask register in WBCIR_REG_WCEIR_INDEX (bits 5 & 6) */
-#define WBCIR_REGSEL_MASK	0x20
-/* Starting address of selected register in WBCIR_REG_WCEIR_INDEX */
-#define WBCIR_REG_ADDR0		0x00
-
-/* Valid banks for the SP3 UART */
-enum wbcir_bank {
-	WBCIR_BANK_0          = 0x00,
-	WBCIR_BANK_1          = 0x80,
-	WBCIR_BANK_2          = 0xE0,
-	WBCIR_BANK_3          = 0xE4,
-	WBCIR_BANK_4          = 0xE8,
-	WBCIR_BANK_5          = 0xEC,
-	WBCIR_BANK_6          = 0xF0,
-	WBCIR_BANK_7          = 0xF4,
-};
-
-/* Supported IR Protocols */
-enum wbcir_protocol {
-	IR_PROTOCOL_RC5          = 0x0,
-	IR_PROTOCOL_NEC          = 0x1,
-	IR_PROTOCOL_RC6          = 0x2,
-};
-
-/* Misc */
-#define WBCIR_NAME	"Winbond CIR"
-#define WBCIR_ID_FAMILY          0xF1 /* Family ID for the WPCD376I	*/
-#define	WBCIR_ID_CHIP            0x04 /* Chip ID for the WPCD376I	*/
-#define IR_KEYPRESS_TIMEOUT       250 /* FIXME: should be per-protocol? */
-#define INVALID_SCANCODE   0x7FFFFFFF /* Invalid with all protos	*/
-#define WAKEUP_IOMEM_LEN         0x10 /* Wake-Up I/O Reg Len		*/
-#define EHFUNC_IOMEM_LEN         0x10 /* Enhanced Func I/O Reg Len	*/
-#define SP_IOMEM_LEN             0x08 /* Serial Port 3 (IR) Reg Len	*/
-#define WBCIR_MAX_IDLE_BYTES       10
-
-static DEFINE_SPINLOCK(wbcir_lock);
-static DEFINE_RWLOCK(keytable_lock);
-
-struct wbcir_key {
-	u32 scancode;
-	unsigned int keycode;
-};
-
-struct wbcir_keyentry {
-	struct wbcir_key key;
-	struct list_head list;
-};
-
-static struct wbcir_key rc6_def_keymap[] = {
-	{ 0x800F0400, KEY_NUMERIC_0		},
-	{ 0x800F0401, KEY_NUMERIC_1		},
-	{ 0x800F0402, KEY_NUMERIC_2		},
-	{ 0x800F0403, KEY_NUMERIC_3		},
-	{ 0x800F0404, KEY_NUMERIC_4		},
-	{ 0x800F0405, KEY_NUMERIC_5		},
-	{ 0x800F0406, KEY_NUMERIC_6		},
-	{ 0x800F0407, KEY_NUMERIC_7		},
-	{ 0x800F0408, KEY_NUMERIC_8		},
-	{ 0x800F0409, KEY_NUMERIC_9		},
-	{ 0x800F041D, KEY_NUMERIC_STAR		},
-	{ 0x800F041C, KEY_NUMERIC_POUND		},
-	{ 0x800F0410, KEY_VOLUMEUP		},
-	{ 0x800F0411, KEY_VOLUMEDOWN		},
-	{ 0x800F0412, KEY_CHANNELUP		},
-	{ 0x800F0413, KEY_CHANNELDOWN		},
-	{ 0x800F040E, KEY_MUTE			},
-	{ 0x800F040D, KEY_VENDOR		}, /* Vista Logo Key */
-	{ 0x800F041E, KEY_UP			},
-	{ 0x800F041F, KEY_DOWN			},
-	{ 0x800F0420, KEY_LEFT			},
-	{ 0x800F0421, KEY_RIGHT			},
-	{ 0x800F0422, KEY_OK			},
-	{ 0x800F0423, KEY_ESC			},
-	{ 0x800F040F, KEY_INFO			},
-	{ 0x800F040A, KEY_CLEAR			},
-	{ 0x800F040B, KEY_ENTER			},
-	{ 0x800F045B, KEY_RED			},
-	{ 0x800F045C, KEY_GREEN			},
-	{ 0x800F045D, KEY_YELLOW		},
-	{ 0x800F045E, KEY_BLUE			},
-	{ 0x800F045A, KEY_TEXT			},
-	{ 0x800F0427, KEY_SWITCHVIDEOMODE	},
-	{ 0x800F040C, KEY_POWER			},
-	{ 0x800F0450, KEY_RADIO			},
-	{ 0x800F0448, KEY_PVR			},
-	{ 0x800F0447, KEY_AUDIO			},
-	{ 0x800F0426, KEY_EPG			},
-	{ 0x800F0449, KEY_CAMERA		},
-	{ 0x800F0425, KEY_TV			},
-	{ 0x800F044A, KEY_VIDEO			},
-	{ 0x800F0424, KEY_DVD			},
-	{ 0x800F0416, KEY_PLAY			},
-	{ 0x800F0418, KEY_PAUSE			},
-	{ 0x800F0419, KEY_STOP			},
-	{ 0x800F0414, KEY_FASTFORWARD		},
-	{ 0x800F041A, KEY_NEXT			},
-	{ 0x800F041B, KEY_PREVIOUS		},
-	{ 0x800F0415, KEY_REWIND		},
-	{ 0x800F0417, KEY_RECORD		},
-};
-
-/* Registers and other state is protected by wbcir_lock */
-struct wbcir_data {
-	unsigned long wbase;        /* Wake-Up Baseaddr		*/
-	unsigned long ebase;        /* Enhanced Func. Baseaddr	*/
-	unsigned long sbase;        /* Serial Port Baseaddr	*/
-	unsigned int  irq;          /* Serial Port IRQ		*/
-
-	struct input_dev *input_dev;
-	struct timer_list timer_keyup;
-	struct led_trigger *rxtrigger;
-	struct led_trigger *txtrigger;
-	struct led_classdev led;
-
-	u32 last_scancode;
-	unsigned int last_keycode;
-	u8 last_toggle;
-	u8 keypressed;
-	unsigned long keyup_jiffies;
-	unsigned int idle_count;
-
-	/* RX irdata and parsing state */
-	unsigned long irdata[30];
-	unsigned int irdata_count;
-	unsigned int irdata_idle;
-	unsigned int irdata_off;
-	unsigned int irdata_error;
-
-	/* Protected by keytable_lock */
-	struct list_head keytable;
-};
-
-static enum wbcir_protocol protocol = IR_PROTOCOL_RC6;
-module_param(protocol, uint, 0444);
-MODULE_PARM_DESC(protocol, "IR protocol to use "
-		 "(0 = RC5, 1 = NEC, 2 = RC6A, default)");
-
-static int invert; /* default = 0 */
-module_param(invert, bool, 0444);
-MODULE_PARM_DESC(invert, "Invert the signal from the IR receiver");
-
-static unsigned int wake_sc = 0x800F040C;
-module_param(wake_sc, uint, 0644);
-MODULE_PARM_DESC(wake_sc, "Scancode of the power-on IR command");
-
-static unsigned int wake_rc6mode = 6;
-module_param(wake_rc6mode, uint, 0644);
-MODULE_PARM_DESC(wake_rc6mode, "RC6 mode for the power-on command "
-		 "(0 = 0, 6 = 6A, default)");
-
-
-
-/*****************************************************************************
- *
- * UTILITY FUNCTIONS
- *
- *****************************************************************************/
-
-/* Caller needs to hold wbcir_lock */
-static void
-wbcir_set_bits(unsigned long addr, u8 bits, u8 mask)
-{
-	u8 val;
-
-	val = inb(addr);
-	val = ((val & ~mask) | (bits & mask));
-	outb(val, addr);
-}
-
-/* Selects the register bank for the serial port */
-static inline void
-wbcir_select_bank(struct wbcir_data *data, enum wbcir_bank bank)
-{
-	outb(bank, data->sbase + WBCIR_REG_SP3_BSR);
-}
-
-static enum led_brightness
-wbcir_led_brightness_get(struct led_classdev *led_cdev)
-{
-	struct wbcir_data *data = container_of(led_cdev,
-					       struct wbcir_data,
-					       led);
-
-	if (inb(data->ebase + WBCIR_REG_ECEIR_CTS) & WBCIR_LED_ENABLE)
-		return LED_FULL;
-	else
-		return LED_OFF;
-}
-
-static void
-wbcir_led_brightness_set(struct led_classdev *led_cdev,
-			    enum led_brightness brightness)
-{
-	struct wbcir_data *data = container_of(led_cdev,
-					       struct wbcir_data,
-					       led);
-
-	wbcir_set_bits(data->ebase + WBCIR_REG_ECEIR_CTS,
-		       brightness == LED_OFF ? 0x00 : WBCIR_LED_ENABLE,
-		       WBCIR_LED_ENABLE);
-}
-
-/* Manchester encodes bits to RC6 message cells (see wbcir_parse_rc6) */
-static u8
-wbcir_to_rc6cells(u8 val)
-{
-	u8 coded = 0x00;
-	int i;
-
-	val &= 0x0F;
-	for (i = 0; i < 4; i++) {
-		if (val & 0x01)
-			coded |= 0x02 << (i * 2);
-		else
-			coded |= 0x01 << (i * 2);
-		val >>= 1;
-	}
-
-	return coded;
-}
-
-
-
-/*****************************************************************************
- *
- * INPUT FUNCTIONS
- *
- *****************************************************************************/
-
-static unsigned int
-wbcir_do_getkeycode(struct wbcir_data *data, u32 scancode)
-{
-	struct wbcir_keyentry *keyentry;
-	unsigned int keycode = KEY_RESERVED;
-	unsigned long flags;
-
-	read_lock_irqsave(&keytable_lock, flags);
-
-	list_for_each_entry(keyentry, &data->keytable, list) {
-		if (keyentry->key.scancode == scancode) {
-			keycode = keyentry->key.keycode;
-			break;
-		}
-	}
-
-	read_unlock_irqrestore(&keytable_lock, flags);
-	return keycode;
-}
-
-static int
-wbcir_getkeycode(struct input_dev *dev,
-		 unsigned int scancode, unsigned int *keycode)
-{
-	struct wbcir_data *data = input_get_drvdata(dev);
-
-	*keycode = wbcir_do_getkeycode(data, scancode);
-	return 0;
-}
-
-static int
-wbcir_setkeycode(struct input_dev *dev,
-		 unsigned int scancode, unsigned int keycode)
-{
-	struct wbcir_data *data = input_get_drvdata(dev);
-	struct wbcir_keyentry *keyentry;
-	struct wbcir_keyentry *new_keyentry;
-	unsigned long flags;
-	unsigned int old_keycode = KEY_RESERVED;
-
-	new_keyentry = kmalloc(sizeof(*new_keyentry), GFP_KERNEL);
-	if (!new_keyentry)
-		return -ENOMEM;
-
-	write_lock_irqsave(&keytable_lock, flags);
-
-	list_for_each_entry(keyentry, &data->keytable, list) {
-		if (keyentry->key.scancode != scancode)
-			continue;
-
-		old_keycode = keyentry->key.keycode;
-		keyentry->key.keycode = keycode;
-
-		if (keyentry->key.keycode == KEY_RESERVED) {
-			list_del(&keyentry->list);
-			kfree(keyentry);
-		}
-
-		break;
-	}
-
-	set_bit(keycode, dev->keybit);
-
-	if (old_keycode == KEY_RESERVED) {
-		new_keyentry->key.scancode = scancode;
-		new_keyentry->key.keycode = keycode;
-		list_add(&new_keyentry->list, &data->keytable);
-	} else {
-		kfree(new_keyentry);
-		clear_bit(old_keycode, dev->keybit);
-		list_for_each_entry(keyentry, &data->keytable, list) {
-			if (keyentry->key.keycode == old_keycode) {
-				set_bit(old_keycode, dev->keybit);
-				break;
-			}
-		}
-	}
-
-	write_unlock_irqrestore(&keytable_lock, flags);
-	return 0;
-}
-
-/*
- * Timer function to report keyup event some time after keydown is
- * reported by the ISR.
- */
-static void
-wbcir_keyup(unsigned long cookie)
-{
-	struct wbcir_data *data = (struct wbcir_data *)cookie;
-	unsigned long flags;
-
-	/*
-	 * data->keyup_jiffies is used to prevent a race condition if a
-	 * hardware interrupt occurs at this point and the keyup timer
-	 * event is moved further into the future as a result.
-	 *
-	 * The timer will then be reactivated and this function called
-	 * again in the future. We need to exit gracefully in that case
-	 * to allow the input subsystem to do its auto-repeat magic or
-	 * a keyup event might follow immediately after the keydown.
-	 */
-
-	spin_lock_irqsave(&wbcir_lock, flags);
-
-	if (time_is_after_eq_jiffies(data->keyup_jiffies) && data->keypressed) {
-		data->keypressed = 0;
-		led_trigger_event(data->rxtrigger, LED_OFF);
-		input_report_key(data->input_dev, data->last_keycode, 0);
-		input_sync(data->input_dev);
-	}
-
-	spin_unlock_irqrestore(&wbcir_lock, flags);
-}
-
-static void
-wbcir_keydown(struct wbcir_data *data, u32 scancode, u8 toggle)
-{
-	unsigned int keycode;
-
-	/* Repeat? */
-	if (data->last_scancode == scancode &&
-	    data->last_toggle == toggle &&
-	    data->keypressed)
-		goto set_timer;
-	data->last_scancode = scancode;
-
-	/* Do we need to release an old keypress? */
-	if (data->keypressed) {
-		input_report_key(data->input_dev, data->last_keycode, 0);
-		input_sync(data->input_dev);
-		data->keypressed = 0;
-	}
-
-	/* Report scancode */
-	input_event(data->input_dev, EV_MSC, MSC_SCAN, (int)scancode);
-
-	/* Do we know this scancode? */
-	keycode = wbcir_do_getkeycode(data, scancode);
-	if (keycode == KEY_RESERVED)
-		goto set_timer;
-
-	/* Register a keypress */
-	input_report_key(data->input_dev, keycode, 1);
-	data->keypressed = 1;
-	data->last_keycode = keycode;
-	data->last_toggle = toggle;
-
-set_timer:
-	input_sync(data->input_dev);
-	led_trigger_event(data->rxtrigger,
-			  data->keypressed ? LED_FULL : LED_OFF);
-	data->keyup_jiffies = jiffies + msecs_to_jiffies(IR_KEYPRESS_TIMEOUT);
-	mod_timer(&data->timer_keyup, data->keyup_jiffies);
-}
-
-
-
-/*****************************************************************************
- *
- * IR PARSING FUNCTIONS
- *
- *****************************************************************************/
-
-/* Resets all irdata */
-static void
-wbcir_reset_irdata(struct wbcir_data *data)
-{
-	memset(data->irdata, 0, sizeof(data->irdata));
-	data->irdata_count = 0;
-	data->irdata_off = 0;
-	data->irdata_error = 0;
-	data->idle_count = 0;
-}
-
-/* Adds one bit of irdata */
-static void
-add_irdata_bit(struct wbcir_data *data, int set)
-{
-	if (data->irdata_count >= sizeof(data->irdata) * 8) {
-		data->irdata_error = 1;
-		return;
-	}
-
-	if (set)
-		__set_bit(data->irdata_count, data->irdata);
-	data->irdata_count++;
-}
-
-/* Gets count bits of irdata */
-static u16
-get_bits(struct wbcir_data *data, int count)
-{
-	u16 val = 0x0;
-
-	if (data->irdata_count - data->irdata_off < count) {
-		data->irdata_error = 1;
-		return 0x0;
-	}
-
-	while (count > 0) {
-		val <<= 1;
-		if (test_bit(data->irdata_off, data->irdata))
-			val |= 0x1;
-		count--;
-		data->irdata_off++;
-	}
-
-	return val;
-}
-
-/* Reads 16 cells and converts them to a byte */
-static u8
-wbcir_rc6cells_to_byte(struct wbcir_data *data)
-{
-	u16 raw = get_bits(data, 16);
-	u8 val = 0x00;
-	int bit;
-
-	for (bit = 0; bit < 8; bit++) {
-		switch (raw & 0x03) {
-		case 0x01:
-			break;
-		case 0x02:
-			val |= (0x01 << bit);
-			break;
-		default:
-			data->irdata_error = 1;
-			break;
-		}
-		raw >>= 2;
-	}
-
-	return val;
-}
-
-/* Decodes a number of bits from raw RC5 data */
-static u8
-wbcir_get_rc5bits(struct wbcir_data *data, unsigned int count)
-{
-	u16 raw = get_bits(data, count * 2);
-	u8 val = 0x00;
-	int bit;
-
-	for (bit = 0; bit < count; bit++) {
-		switch (raw & 0x03) {
-		case 0x01:
-			val |= (0x01 << bit);
-			break;
-		case 0x02:
-			break;
-		default:
-			data->irdata_error = 1;
-			break;
-		}
-		raw >>= 2;
-	}
-
-	return val;
-}
-
-static void
-wbcir_parse_rc6(struct device *dev, struct wbcir_data *data)
-{
-	/*
-	 * Normal bits are manchester coded as follows:
-	 * cell0 + cell1 = logic "0"
-	 * cell1 + cell0 = logic "1"
-	 *
-	 * The IR pulse has the following components:
-	 *
-	 * Leader		- 6 * cell1 - discarded
-	 * Gap    		- 2 * cell0 - discarded
-	 * Start bit		- Normal Coding - always "1"
-	 * Mode Bit 2 - 0	- Normal Coding
-	 * Toggle bit		- Normal Coding with double bit time,
-	 *			  e.g. cell0 + cell0 + cell1 + cell1
-	 *			  means logic "0".
-	 *
-	 * The rest depends on the mode, the following modes are known:
-	 *
-	 * MODE 0:
-	 *  Address Bit 7 - 0	- Normal Coding
-	 *  Command Bit 7 - 0	- Normal Coding
-	 *
-	 * MODE 6:
-	 *  The above Toggle Bit is used as a submode bit, 0 = A, 1 = B.
-	 *  Submode B is for pointing devices, only remotes using submode A
-	 *  are supported.
-	 *
-	 *  Customer range bit	- 0 => Customer = 7 bits, 0...127
-	 *                        1 => Customer = 15 bits, 32768...65535
-	 *  Customer Bits	- Normal Coding
-	 *
-	 *  Customer codes are allocated by Philips. The rest of the bits
-	 *  are customer dependent. The following is commonly used (and the
-	 *  only supported config):
-	 *
-	 *  Toggle Bit		- Normal Coding
-	 *  Address Bit 6 - 0	- Normal Coding
-	 *  Command Bit 7 - 0	- Normal Coding
-	 *
-	 * All modes are followed by at least 6 * cell0.
-	 *
-	 * MODE 0 msglen:
-	 *  1 * 2 (start bit) + 3 * 2 (mode) + 2 * 2 (toggle) +
-	 *  8 * 2 (address) + 8 * 2 (command) =
-	 *  44 cells
-	 *
-	 * MODE 6A msglen:
-	 *  1 * 2 (start bit) + 3 * 2 (mode) + 2 * 2 (submode) +
-	 *  1 * 2 (customer range bit) + 7/15 * 2 (customer bits) +
-	 *  1 * 2 (toggle bit) + 7 * 2 (address) + 8 * 2 (command) =
-	 *  60 - 76 cells
-	 */
-	u8 mode;
-	u8 toggle;
-	u16 customer = 0x0;
-	u8 address;
-	u8 command;
-	u32 scancode;
-
-	/* Leader mark */
-	while (get_bits(data, 1) && !data->irdata_error)
-		/* Do nothing */;
-
-	/* Leader space */
-	if (get_bits(data, 1)) {
-		dev_dbg(dev, "RC6 - Invalid leader space\n");
-		return;
-	}
-
-	/* Start bit */
-	if (get_bits(data, 2) != 0x02) {
-		dev_dbg(dev, "RC6 - Invalid start bit\n");
-		return;
-	}
-
-	/* Mode */
-	mode = get_bits(data, 6);
-	switch (mode) {
-	case 0x15: /* 010101 = b000 */
-		mode = 0;
-		break;
-	case 0x29: /* 101001 = b110 */
-		mode = 6;
-		break;
-	default:
-		dev_dbg(dev, "RC6 - Invalid mode\n");
-		return;
-	}
-
-	/* Toggle bit / Submode bit */
-	toggle = get_bits(data, 4);
-	switch (toggle) {
-	case 0x03:
-		toggle = 0;
-		break;
-	case 0x0C:
-		toggle = 1;
-		break;
-	default:
-		dev_dbg(dev, "RC6 - Toggle bit error\n");
-		break;
-	}
-
-	/* Customer */
-	if (mode == 6) {
-		if (toggle != 0) {
-			dev_dbg(dev, "RC6B - Not Supported\n");
-			return;
-		}
-
-		customer = wbcir_rc6cells_to_byte(data);
-
-		if (customer & 0x80) {
-			/* 15 bit customer value */
-			customer <<= 8;
-			customer |= wbcir_rc6cells_to_byte(data);
-		}
-	}
-
-	/* Address */
-	address = wbcir_rc6cells_to_byte(data);
-	if (mode == 6) {
-		toggle = address >> 7;
-		address &= 0x7F;
-	}
-
-	/* Command */
-	command = wbcir_rc6cells_to_byte(data);
-
-	/* Create scancode */
-	scancode =  command;
-	scancode |= address << 8;
-	scancode |= customer << 16;
-
-	/* Last sanity check */
-	if (data->irdata_error) {
-		dev_dbg(dev, "RC6 - Cell error(s)\n");
-		return;
-	}
-
-	dev_dbg(dev, "IR-RC6 ad 0x%02X cm 0x%02X cu 0x%04X "
-		"toggle %u mode %u scan 0x%08X\n",
-		address,
-		command,
-		customer,
-		(unsigned int)toggle,
-		(unsigned int)mode,
-		scancode);
-
-	wbcir_keydown(data, scancode, toggle);
-}
-
-static void
-wbcir_parse_rc5(struct device *dev, struct wbcir_data *data)
-{
-	/*
-	 * Bits are manchester coded as follows:
-	 * cell1 + cell0 = logic "0"
-	 * cell0 + cell1 = logic "1"
-	 * (i.e. the reverse of RC6)
-	 *
-	 * Start bit 1		- "1" - discarded
-	 * Start bit 2		- Must be inverted to get command bit 6
-	 * Toggle bit
-	 * Address Bit 4 - 0
-	 * Command Bit 5 - 0
-	 */
-	u8 toggle;
-	u8 address;
-	u8 command;
-	u32 scancode;
-
-	/* Start bit 1 */
-	if (!get_bits(data, 1)) {
-		dev_dbg(dev, "RC5 - Invalid start bit\n");
-		return;
-	}
-
-	/* Start bit 2 */
-	if (!wbcir_get_rc5bits(data, 1))
-		command = 0x40;
-	else
-		command = 0x00;
-
-	toggle   = wbcir_get_rc5bits(data, 1);
-	address  = wbcir_get_rc5bits(data, 5);
-	command |= wbcir_get_rc5bits(data, 6);
-	scancode = address << 7 | command;
-
-	/* Last sanity check */
-	if (data->irdata_error) {
-		dev_dbg(dev, "RC5 - Invalid message\n");
-		return;
-	}
-
-	dev_dbg(dev, "IR-RC5 ad %u cm %u t %u s %u\n",
-		(unsigned int)address,
-		(unsigned int)command,
-		(unsigned int)toggle,
-		(unsigned int)scancode);
-
-	wbcir_keydown(data, scancode, toggle);
-}
-
-static void
-wbcir_parse_nec(struct device *dev, struct wbcir_data *data)
-{
-	/*
-	 * Each bit represents 560 us.
-	 *
-	 * Leader		- 9 ms burst
-	 * Gap			- 4.5 ms silence
-	 * Address1 bit 0 - 7	- Address 1
-	 * Address2 bit 0 - 7	- Address 2
-	 * Command1 bit 0 - 7	- Command 1
-	 * Command2 bit 0 - 7	- Command 2
-	 *
-	 * Note the bit order!
-	 *
-	 * With the old NEC protocol, Address2 was the inverse of Address1
-	 * and Command2 was the inverse of Command1 and were used as
-	 * an error check.
-	 *
-	 * With NEC extended, Address1 is the LSB of the Address and
-	 * Address2 is the MSB, Command parsing remains unchanged.
-	 *
-	 * A repeat message is coded as:
-	 * Leader		- 9 ms burst
-	 * Gap			- 2.25 ms silence
-	 * Repeat		- 560 us active
-	 */
-	u8 address1;
-	u8 address2;
-	u8 command1;
-	u8 command2;
-	u16 address;
-	u32 scancode;
-
-	/* Leader mark */
-	while (get_bits(data, 1) && !data->irdata_error)
-		/* Do nothing */;
-
-	/* Leader space */
-	if (get_bits(data, 4)) {
-		dev_dbg(dev, "NEC - Invalid leader space\n");
-		return;
-	}
-
-	/* Repeat? */
-	if (get_bits(data, 1)) {
-		if (!data->keypressed) {
-			dev_dbg(dev, "NEC - Stray repeat message\n");
-			return;
-		}
-
-		dev_dbg(dev, "IR-NEC repeat s %u\n",
-			(unsigned int)data->last_scancode);
-
-		wbcir_keydown(data, data->last_scancode, data->last_toggle);
-		return;
-	}
-
-	/* Remaining leader space */
-	if (get_bits(data, 3)) {
-		dev_dbg(dev, "NEC - Invalid leader space\n");
-		return;
-	}
-
-	address1  = bitrev8(get_bits(data, 8));
-	address2  = bitrev8(get_bits(data, 8));
-	command1  = bitrev8(get_bits(data, 8));
-	command2  = bitrev8(get_bits(data, 8));
-
-	/* Sanity check */
-	if (data->irdata_error) {
-		dev_dbg(dev, "NEC - Invalid message\n");
-		return;
-	}
-
-	/* Check command validity */
-	if (command1 != ~command2) {
-		dev_dbg(dev, "NEC - Command bytes mismatch\n");
-		return;
-	}
-
-	/* Check for extended NEC protocol */
-	address = address1;
-	if (address1 != ~address2)
-		address |= address2 << 8;
-
-	scancode = address << 8 | command1;
-
-	dev_dbg(dev, "IR-NEC ad %u cm %u s %u\n",
-		(unsigned int)address,
-		(unsigned int)command1,
-		(unsigned int)scancode);
-
-	wbcir_keydown(data, scancode, !data->last_toggle);
-}
-
-
-
-/*****************************************************************************
- *
- * INTERRUPT FUNCTIONS
- *
- *****************************************************************************/
-
-static irqreturn_t
-wbcir_irq_handler(int irqno, void *cookie)
-{
-	struct pnp_dev *device = cookie;
-	struct wbcir_data *data = pnp_get_drvdata(device);
-	struct device *dev = &device->dev;
-	u8 status;
-	unsigned long flags;
-	u8 irdata[8];
-	int i;
-	unsigned int hw;
-
-	spin_lock_irqsave(&wbcir_lock, flags);
-
-	wbcir_select_bank(data, WBCIR_BANK_0);
-
-	status = inb(data->sbase + WBCIR_REG_SP3_EIR);
-
-	if (!(status & (WBCIR_IRQ_RX | WBCIR_IRQ_ERR))) {
-		spin_unlock_irqrestore(&wbcir_lock, flags);
-		return IRQ_NONE;
-	}
-
-	if (status & WBCIR_IRQ_ERR)
-		data->irdata_error = 1;
-
-	if (!(status & WBCIR_IRQ_RX))
-		goto out;
-
-	/* Since RXHDLEV is set, at least 8 bytes are in the FIFO */
-	insb(data->sbase + WBCIR_REG_SP3_RXDATA, &irdata[0], 8);
-
-	for (i = 0; i < sizeof(irdata); i++) {
-		hw = hweight8(irdata[i]);
-		if (hw > 4)
-			add_irdata_bit(data, 0);
-		else
-			add_irdata_bit(data, 1);
-
-		if (hw == 8)
-			data->idle_count++;
-		else
-			data->idle_count = 0;
-	}
-
-	if (data->idle_count > WBCIR_MAX_IDLE_BYTES) {
-		/* Set RXINACTIVE... */
-		outb(WBCIR_RX_DISABLE, data->sbase + WBCIR_REG_SP3_ASCR);
-
-		/* ...and drain the FIFO */
-		while (inb(data->sbase + WBCIR_REG_SP3_LSR) & WBCIR_RX_AVAIL)
-			inb(data->sbase + WBCIR_REG_SP3_RXDATA);
-
-		dev_dbg(dev, "IRDATA:\n");
-		for (i = 0; i < data->irdata_count; i += BITS_PER_LONG)
-			dev_dbg(dev, "0x%08lX\n", data->irdata[i/BITS_PER_LONG]);
-
-		switch (protocol) {
-		case IR_PROTOCOL_RC5:
-			wbcir_parse_rc5(dev, data);
-			break;
-		case IR_PROTOCOL_RC6:
-			wbcir_parse_rc6(dev, data);
-			break;
-		case IR_PROTOCOL_NEC:
-			wbcir_parse_nec(dev, data);
-			break;
-		}
-
-		wbcir_reset_irdata(data);
-	}
-
-out:
-	spin_unlock_irqrestore(&wbcir_lock, flags);
-	return IRQ_HANDLED;
-}
-
-
-
-/*****************************************************************************
- *
- * SETUP/INIT/SUSPEND/RESUME FUNCTIONS
- *
- *****************************************************************************/
-
-static void
-wbcir_shutdown(struct pnp_dev *device)
-{
-	struct device *dev = &device->dev;
-	struct wbcir_data *data = pnp_get_drvdata(device);
-	int do_wake = 1;
-	u8 match[11];
-	u8 mask[11];
-	u8 rc6_csl = 0;
-	int i;
-
-	memset(match, 0, sizeof(match));
-	memset(mask, 0, sizeof(mask));
-
-	if (wake_sc == INVALID_SCANCODE || !device_may_wakeup(dev)) {
-		do_wake = 0;
-		goto finish;
-	}
-
-	switch (protocol) {
-	case IR_PROTOCOL_RC5:
-		if (wake_sc > 0xFFF) {
-			do_wake = 0;
-			dev_err(dev, "RC5 - Invalid wake scancode\n");
-			break;
-		}
-
-		/* Mask = 13 bits, ex toggle */
-		mask[0] = 0xFF;
-		mask[1] = 0x17;
-
-		match[0]  = (wake_sc & 0x003F);      /* 6 command bits */
-		match[0] |= (wake_sc & 0x0180) >> 1; /* 2 address bits */
-		match[1]  = (wake_sc & 0x0E00) >> 9; /* 3 address bits */
-		if (!(wake_sc & 0x0040))             /* 2nd start bit  */
-			match[1] |= 0x10;
-
-		break;
-
-	case IR_PROTOCOL_NEC:
-		if (wake_sc > 0xFFFFFF) {
-			do_wake = 0;
-			dev_err(dev, "NEC - Invalid wake scancode\n");
-			break;
-		}
-
-		mask[0] = mask[1] = mask[2] = mask[3] = 0xFF;
-
-		match[1] = bitrev8((wake_sc & 0xFF));
-		match[0] = ~match[1];
-
-		match[3] = bitrev8((wake_sc & 0xFF00) >> 8);
-		if (wake_sc > 0xFFFF)
-			match[2] = bitrev8((wake_sc & 0xFF0000) >> 16);
-		else
-			match[2] = ~match[3];
-
-		break;
-
-	case IR_PROTOCOL_RC6:
-
-		if (wake_rc6mode == 0) {
-			if (wake_sc > 0xFFFF) {
-				do_wake = 0;
-				dev_err(dev, "RC6 - Invalid wake scancode\n");
-				break;
-			}
-
-			/* Command */
-			match[0] = wbcir_to_rc6cells(wake_sc >>  0);
-			mask[0]  = 0xFF;
-			match[1] = wbcir_to_rc6cells(wake_sc >>  4);
-			mask[1]  = 0xFF;
-
-			/* Address */
-			match[2] = wbcir_to_rc6cells(wake_sc >>  8);
-			mask[2]  = 0xFF;
-			match[3] = wbcir_to_rc6cells(wake_sc >> 12);
-			mask[3]  = 0xFF;
-
-			/* Header */
-			match[4] = 0x50; /* mode1 = mode0 = 0, ignore toggle */
-			mask[4]  = 0xF0;
-			match[5] = 0x09; /* start bit = 1, mode2 = 0 */
-			mask[5]  = 0x0F;
-
-			rc6_csl = 44;
-
-		} else if (wake_rc6mode == 6) {
-			i = 0;
-
-			/* Command */
-			match[i]  = wbcir_to_rc6cells(wake_sc >>  0);
-			mask[i++] = 0xFF;
-			match[i]  = wbcir_to_rc6cells(wake_sc >>  4);
-			mask[i++] = 0xFF;
-
-			/* Address + Toggle */
-			match[i]  = wbcir_to_rc6cells(wake_sc >>  8);
-			mask[i++] = 0xFF;
-			match[i]  = wbcir_to_rc6cells(wake_sc >> 12);
-			mask[i++] = 0x3F;
-
-			/* Customer bits 7 - 0 */
-			match[i]  = wbcir_to_rc6cells(wake_sc >> 16);
-			mask[i++] = 0xFF;
-			match[i]  = wbcir_to_rc6cells(wake_sc >> 20);
-			mask[i++] = 0xFF;
-
-			if (wake_sc & 0x80000000) {
-				/* Customer range bit and bits 15 - 8 */
-				match[i]  = wbcir_to_rc6cells(wake_sc >> 24);
-				mask[i++] = 0xFF;
-				match[i]  = wbcir_to_rc6cells(wake_sc >> 28);
-				mask[i++] = 0xFF;
-				rc6_csl = 76;
-			} else if (wake_sc <= 0x007FFFFF) {
-				rc6_csl = 60;
-			} else {
-				do_wake = 0;
-				dev_err(dev, "RC6 - Invalid wake scancode\n");
-				break;
-			}
-
-			/* Header */
-			match[i]  = 0x93; /* mode1 = mode0 = 1, submode = 0 */
-			mask[i++] = 0xFF;
-			match[i]  = 0x0A; /* start bit = 1, mode2 = 1 */
-			mask[i++] = 0x0F;
-
-		} else {
-			do_wake = 0;
-			dev_err(dev, "RC6 - Invalid wake mode\n");
-		}
-
-		break;
-
-	default:
-		do_wake = 0;
-		break;
-	}
-
-finish:
-	if (do_wake) {
-		/* Set compare and compare mask */
-		wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_INDEX,
-			       WBCIR_REGSEL_COMPARE | WBCIR_REG_ADDR0,
-			       0x3F);
-		outsb(data->wbase + WBCIR_REG_WCEIR_DATA, match, 11);
-		wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_INDEX,
-			       WBCIR_REGSEL_MASK | WBCIR_REG_ADDR0,
-			       0x3F);
-		outsb(data->wbase + WBCIR_REG_WCEIR_DATA, mask, 11);
-
-		/* RC6 Compare String Len */
-		outb(rc6_csl, data->wbase + WBCIR_REG_WCEIR_CSL);
-
-		/* Clear status bits NEC_REP, BUFF, MSG_END, MATCH */
-		wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_STS, 0x17, 0x17);
-
-		/* Clear BUFF_EN, Clear END_EN, Set MATCH_EN */
-		wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_EV_EN, 0x01, 0x07);
-
-		/* Set CEIR_EN */
-		wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_CTL, 0x01, 0x01);
-
-	} else {
-		/* Clear BUFF_EN, Clear END_EN, Clear MATCH_EN */
-		wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_EV_EN, 0x00, 0x07);
-
-		/* Clear CEIR_EN */
-		wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_CTL, 0x00, 0x01);
-	}
-
-	/* Disable interrupts */
-	wbcir_select_bank(data, WBCIR_BANK_0);
-	outb(WBCIR_IRQ_NONE, data->sbase + WBCIR_REG_SP3_IER);
-
-	/*
-	 * ACPI will set the HW disable bit for SP3 which means that the
-	 * output signals are left in an undefined state which may cause
-	 * spurious interrupts which we need to ignore until the hardware
-	 * is reinitialized.
-	 */
-	disable_irq(data->irq);
-}
-
-static int
-wbcir_suspend(struct pnp_dev *device, pm_message_t state)
-{
-	wbcir_shutdown(device);
-	return 0;
-}
-
-static void
-wbcir_init_hw(struct wbcir_data *data)
-{
-	u8 tmp;
-
-	/* Disable interrupts */
-	wbcir_select_bank(data, WBCIR_BANK_0);
-	outb(WBCIR_IRQ_NONE, data->sbase + WBCIR_REG_SP3_IER);
-
-	/* Set PROT_SEL, RX_INV, Clear CEIR_EN (needed for the led) */
-	tmp = protocol << 4;
-	if (invert)
-		tmp |= 0x08;
-	outb(tmp, data->wbase + WBCIR_REG_WCEIR_CTL);
-
-	/* Clear status bits NEC_REP, BUFF, MSG_END, MATCH */
-	wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_STS, 0x17, 0x17);
-
-	/* Clear BUFF_EN, Clear END_EN, Clear MATCH_EN */
-	wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_EV_EN, 0x00, 0x07);
-
-	/* Set RC5 cell time to correspond to 36 kHz */
-	wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_CFG1, 0x4A, 0x7F);
-
-	/* Set IRTX_INV */
-	if (invert)
-		outb(0x04, data->ebase + WBCIR_REG_ECEIR_CCTL);
-	else
-		outb(0x00, data->ebase + WBCIR_REG_ECEIR_CCTL);
-
-	/*
-	 * Clear IR LED, set SP3 clock to 24Mhz
-	 * set SP3_IRRX_SW to binary 01, helpfully not documented
-	 */
-	outb(0x10, data->ebase + WBCIR_REG_ECEIR_CTS);
-
-	/* Enable extended mode */
-	wbcir_select_bank(data, WBCIR_BANK_2);
-	outb(WBCIR_EXT_ENABLE, data->sbase + WBCIR_REG_SP3_EXCR1);
-
-	/*
-	 * Configure baud generator, IR data will be sampled at
-	 * a bitrate of: (24Mhz * prescaler) / (divisor * 16).
-	 *
-	 * The ECIR registers include a flag to change the
-	 * 24Mhz clock freq to 48Mhz.
-	 *
-	 * It's not documented in the specs, but fifo levels
-	 * other than 16 seems to be unsupported.
-	 */
-
-	/* prescaler 1.0, tx/rx fifo lvl 16 */
-	outb(0x30, data->sbase + WBCIR_REG_SP3_EXCR2);
-
-	/* Set baud divisor to generate one byte per bit/cell */
-	switch (protocol) {
-	case IR_PROTOCOL_RC5:
-		outb(0xA7, data->sbase + WBCIR_REG_SP3_BGDL);
-		break;
-	case IR_PROTOCOL_RC6:
-		outb(0x53, data->sbase + WBCIR_REG_SP3_BGDL);
-		break;
-	case IR_PROTOCOL_NEC:
-		outb(0x69, data->sbase + WBCIR_REG_SP3_BGDL);
-		break;
-	}
-	outb(0x00, data->sbase + WBCIR_REG_SP3_BGDH);
-
-	/* Set CEIR mode */
-	wbcir_select_bank(data, WBCIR_BANK_0);
-	outb(0xC0, data->sbase + WBCIR_REG_SP3_MCR);
-	inb(data->sbase + WBCIR_REG_SP3_LSR); /* Clear LSR */
-	inb(data->sbase + WBCIR_REG_SP3_MSR); /* Clear MSR */
-
-	/* Disable RX demod, run-length encoding/decoding, set freq span */
-	wbcir_select_bank(data, WBCIR_BANK_7);
-	outb(0x10, data->sbase + WBCIR_REG_SP3_RCCFG);
-
-	/* Disable timer */
-	wbcir_select_bank(data, WBCIR_BANK_4);
-	outb(0x00, data->sbase + WBCIR_REG_SP3_IRCR1);
-
-	/* Enable MSR interrupt, Clear AUX_IRX */
-	wbcir_select_bank(data, WBCIR_BANK_5);
-	outb(0x00, data->sbase + WBCIR_REG_SP3_IRCR2);
-
-	/* Disable CRC */
-	wbcir_select_bank(data, WBCIR_BANK_6);
-	outb(0x20, data->sbase + WBCIR_REG_SP3_IRCR3);
-
-	/* Set RX/TX (de)modulation freq, not really used */
-	wbcir_select_bank(data, WBCIR_BANK_7);
-	outb(0xF2, data->sbase + WBCIR_REG_SP3_IRRXDC);
-	outb(0x69, data->sbase + WBCIR_REG_SP3_IRTXMC);
-
-	/* Set invert and pin direction */
-	if (invert)
-		outb(0x10, data->sbase + WBCIR_REG_SP3_IRCFG4);
-	else
-		outb(0x00, data->sbase + WBCIR_REG_SP3_IRCFG4);
-
-	/* Set FIFO thresholds (RX = 8, TX = 3), reset RX/TX */
-	wbcir_select_bank(data, WBCIR_BANK_0);
-	outb(0x97, data->sbase + WBCIR_REG_SP3_FCR);
-
-	/* Clear AUX status bits */
-	outb(0xE0, data->sbase + WBCIR_REG_SP3_ASCR);
-
-	/* Enable interrupts */
-	wbcir_reset_irdata(data);
-	outb(WBCIR_IRQ_RX | WBCIR_IRQ_ERR, data->sbase + WBCIR_REG_SP3_IER);
-}
-
-static int
-wbcir_resume(struct pnp_dev *device)
-{
-	struct wbcir_data *data = pnp_get_drvdata(device);
-
-	wbcir_init_hw(data);
-	enable_irq(data->irq);
-
-	return 0;
-}
-
-static int __devinit
-wbcir_probe(struct pnp_dev *device, const struct pnp_device_id *dev_id)
-{
-	struct device *dev = &device->dev;
-	struct wbcir_data *data;
-	int err;
-
-	if (!(pnp_port_len(device, 0) == EHFUNC_IOMEM_LEN &&
-	      pnp_port_len(device, 1) == WAKEUP_IOMEM_LEN &&
-	      pnp_port_len(device, 2) == SP_IOMEM_LEN)) {
-		dev_err(dev, "Invalid resources\n");
-		return -ENODEV;
-	}
-
-	data = kzalloc(sizeof(*data), GFP_KERNEL);
-	if (!data) {
-		err = -ENOMEM;
-		goto exit;
-	}
-
-	pnp_set_drvdata(device, data);
-
-	data->ebase = pnp_port_start(device, 0);
-	data->wbase = pnp_port_start(device, 1);
-	data->sbase = pnp_port_start(device, 2);
-	data->irq = pnp_irq(device, 0);
-
-	if (data->wbase == 0 || data->ebase == 0 ||
-	    data->sbase == 0 || data->irq == 0) {
-		err = -ENODEV;
-		dev_err(dev, "Invalid resources\n");
-		goto exit_free_data;
-	}
-
-	dev_dbg(&device->dev, "Found device "
-		"(w: 0x%lX, e: 0x%lX, s: 0x%lX, i: %u)\n",
-		data->wbase, data->ebase, data->sbase, data->irq);
-
-	if (!request_region(data->wbase, WAKEUP_IOMEM_LEN, DRVNAME)) {
-		dev_err(dev, "Region 0x%lx-0x%lx already in use!\n",
-			data->wbase, data->wbase + WAKEUP_IOMEM_LEN - 1);
-		err = -EBUSY;
-		goto exit_free_data;
-	}
-
-	if (!request_region(data->ebase, EHFUNC_IOMEM_LEN, DRVNAME)) {
-		dev_err(dev, "Region 0x%lx-0x%lx already in use!\n",
-			data->ebase, data->ebase + EHFUNC_IOMEM_LEN - 1);
-		err = -EBUSY;
-		goto exit_release_wbase;
-	}
-
-	if (!request_region(data->sbase, SP_IOMEM_LEN, DRVNAME)) {
-		dev_err(dev, "Region 0x%lx-0x%lx already in use!\n",
-			data->sbase, data->sbase + SP_IOMEM_LEN - 1);
-		err = -EBUSY;
-		goto exit_release_ebase;
-	}
-
-	err = request_irq(data->irq, wbcir_irq_handler,
-			  IRQF_DISABLED, DRVNAME, device);
-	if (err) {
-		dev_err(dev, "Failed to claim IRQ %u\n", data->irq);
-		err = -EBUSY;
-		goto exit_release_sbase;
-	}
-
-	led_trigger_register_simple("cir-tx", &data->txtrigger);
-	if (!data->txtrigger) {
-		err = -ENOMEM;
-		goto exit_free_irq;
-	}
-
-	led_trigger_register_simple("cir-rx", &data->rxtrigger);
-	if (!data->rxtrigger) {
-		err = -ENOMEM;
-		goto exit_unregister_txtrigger;
-	}
-
-	data->led.name = "cir::activity";
-	data->led.default_trigger = "cir-rx";
-	data->led.brightness_set = wbcir_led_brightness_set;
-	data->led.brightness_get = wbcir_led_brightness_get;
-	err = led_classdev_register(&device->dev, &data->led);
-	if (err)
-		goto exit_unregister_rxtrigger;
-
-	data->input_dev = input_allocate_device();
-	if (!data->input_dev) {
-		err = -ENOMEM;
-		goto exit_unregister_led;
-	}
-
-	data->input_dev->evbit[0] = BIT(EV_KEY);
-	data->input_dev->name = WBCIR_NAME;
-	data->input_dev->phys = "wbcir/cir0";
-	data->input_dev->id.bustype = BUS_HOST;
-	data->input_dev->id.vendor  = PCI_VENDOR_ID_WINBOND;
-	data->input_dev->id.product = WBCIR_ID_FAMILY;
-	data->input_dev->id.version = WBCIR_ID_CHIP;
-	data->input_dev->getkeycode = wbcir_getkeycode;
-	data->input_dev->setkeycode = wbcir_setkeycode;
-	input_set_capability(data->input_dev, EV_MSC, MSC_SCAN);
-	input_set_drvdata(data->input_dev, data);
-
-	err = input_register_device(data->input_dev);
-	if (err)
-		goto exit_free_input;
-
-	data->last_scancode = INVALID_SCANCODE;
-	INIT_LIST_HEAD(&data->keytable);
-	setup_timer(&data->timer_keyup, wbcir_keyup, (unsigned long)data);
-
-	/* Load default keymaps */
-	if (protocol == IR_PROTOCOL_RC6) {
-		int i;
-		for (i = 0; i < ARRAY_SIZE(rc6_def_keymap); i++) {
-			err = wbcir_setkeycode(data->input_dev,
-					       (int)rc6_def_keymap[i].scancode,
-					       (int)rc6_def_keymap[i].keycode);
-			if (err)
-				goto exit_unregister_keys;
-		}
-	}
-
-	device_init_wakeup(&device->dev, 1);
-
-	wbcir_init_hw(data);
-
-	return 0;
-
-exit_unregister_keys:
-	if (!list_empty(&data->keytable)) {
-		struct wbcir_keyentry *key;
-		struct wbcir_keyentry *keytmp;
-
-		list_for_each_entry_safe(key, keytmp, &data->keytable, list) {
-			list_del(&key->list);
-			kfree(key);
-		}
-	}
-	input_unregister_device(data->input_dev);
-	/* Can't call input_free_device on an unregistered device */
-	data->input_dev = NULL;
-exit_free_input:
-	input_free_device(data->input_dev);
-exit_unregister_led:
-	led_classdev_unregister(&data->led);
-exit_unregister_rxtrigger:
-	led_trigger_unregister_simple(data->rxtrigger);
-exit_unregister_txtrigger:
-	led_trigger_unregister_simple(data->txtrigger);
-exit_free_irq:
-	free_irq(data->irq, device);
-exit_release_sbase:
-	release_region(data->sbase, SP_IOMEM_LEN);
-exit_release_ebase:
-	release_region(data->ebase, EHFUNC_IOMEM_LEN);
-exit_release_wbase:
-	release_region(data->wbase, WAKEUP_IOMEM_LEN);
-exit_free_data:
-	kfree(data);
-	pnp_set_drvdata(device, NULL);
-exit:
-	return err;
-}
-
-static void __devexit
-wbcir_remove(struct pnp_dev *device)
-{
-	struct wbcir_data *data = pnp_get_drvdata(device);
-	struct wbcir_keyentry *key;
-	struct wbcir_keyentry *keytmp;
-
-	/* Disable interrupts */
-	wbcir_select_bank(data, WBCIR_BANK_0);
-	outb(WBCIR_IRQ_NONE, data->sbase + WBCIR_REG_SP3_IER);
-
-	del_timer_sync(&data->timer_keyup);
-
-	free_irq(data->irq, device);
-
-	/* Clear status bits NEC_REP, BUFF, MSG_END, MATCH */
-	wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_STS, 0x17, 0x17);
-
-	/* Clear CEIR_EN */
-	wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_CTL, 0x00, 0x01);
-
-	/* Clear BUFF_EN, END_EN, MATCH_EN */
-	wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_EV_EN, 0x00, 0x07);
-
-	/* This will generate a keyup event if necessary */
-	input_unregister_device(data->input_dev);
-
-	led_trigger_unregister_simple(data->rxtrigger);
-	led_trigger_unregister_simple(data->txtrigger);
-	led_classdev_unregister(&data->led);
-
-	/* This is ok since &data->led isn't actually used */
-	wbcir_led_brightness_set(&data->led, LED_OFF);
-
-	release_region(data->wbase, WAKEUP_IOMEM_LEN);
-	release_region(data->ebase, EHFUNC_IOMEM_LEN);
-	release_region(data->sbase, SP_IOMEM_LEN);
-
-	list_for_each_entry_safe(key, keytmp, &data->keytable, list) {
-		list_del(&key->list);
-		kfree(key);
-	}
-
-	kfree(data);
-
-	pnp_set_drvdata(device, NULL);
-}
-
-static const struct pnp_device_id wbcir_ids[] = {
-	{ "WEC1022", 0 },
-	{ "", 0 }
-};
-MODULE_DEVICE_TABLE(pnp, wbcir_ids);
-
-static struct pnp_driver wbcir_driver = {
-	.name     = WBCIR_NAME,
-	.id_table = wbcir_ids,
-	.probe    = wbcir_probe,
-	.remove   = __devexit_p(wbcir_remove),
-	.suspend  = wbcir_suspend,
-	.resume   = wbcir_resume,
-	.shutdown = wbcir_shutdown
-};
-
-static int __init
-wbcir_init(void)
-{
-	int ret;
-
-	switch (protocol) {
-	case IR_PROTOCOL_RC5:
-	case IR_PROTOCOL_NEC:
-	case IR_PROTOCOL_RC6:
-		break;
-	default:
-		printk(KERN_ERR DRVNAME ": Invalid protocol argument\n");
-		return -EINVAL;
-	}
-
-	ret = pnp_register_driver(&wbcir_driver);
-	if (ret)
-		printk(KERN_ERR DRVNAME ": Unable to register driver\n");
-
-	return ret;
-}
-
-static void __exit
-wbcir_exit(void)
-{
-	pnp_unregister_driver(&wbcir_driver);
-}
-
-MODULE_AUTHOR("David H�rdeman <david@hardeman.nu>");
-MODULE_DESCRIPTION("Winbond SuperI/O Consumer IR Driver");
-MODULE_LICENSE("GPL");
-
-module_init(wbcir_init);
-module_exit(wbcir_exit);
-
-
diff -druNp linux-libre-2.6.37-gnu1/drivers/input/mouse/bcm5974.c linux-libre-2.6.38-gnu1/drivers/input/mouse/bcm5974.c
--- linux-libre-2.6.37-gnu1/drivers/input/mouse/bcm5974.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/input/mouse/bcm5974.c	2011-03-14 21:20:32.000000000 -0400
@@ -55,6 +55,14 @@
 #define USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI	0x0236
 #define USB_DEVICE_ID_APPLE_WELLSPRING3_ISO	0x0237
 #define USB_DEVICE_ID_APPLE_WELLSPRING3_JIS	0x0238
+/* MacbookAir3,2 (unibody), aka wellspring5 */
+#define USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI	0x023f
+#define USB_DEVICE_ID_APPLE_WELLSPRING4_ISO	0x0240
+#define USB_DEVICE_ID_APPLE_WELLSPRING4_JIS	0x0241
+/* MacbookAir3,1 (unibody), aka wellspring4 */
+#define USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI	0x0242
+#define USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO	0x0243
+#define USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS	0x0244
 
 #define BCM5974_DEVICE(prod) {					\
 	.match_flags = (USB_DEVICE_ID_MATCH_DEVICE |		\
@@ -80,6 +88,14 @@ static const struct usb_device_id bcm597
 	BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI),
 	BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING3_ISO),
 	BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING3_JIS),
+	/* MacbookAir3,2 */
+	BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI),
+	BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING4_ISO),
+	BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING4_JIS),
+	/* MacbookAir3,1 */
+	BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI),
+	BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO),
+	BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS),
 	/* Terminating entry */
 	{}
 };
@@ -234,6 +250,30 @@ static const struct bcm5974_config bcm59
 		{ DIM_X, DIM_X / SN_COORD, -4460, 5166 },
 		{ DIM_Y, DIM_Y / SN_COORD, -75, 6700 }
 	},
+	{
+		USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI,
+		USB_DEVICE_ID_APPLE_WELLSPRING4_ISO,
+		USB_DEVICE_ID_APPLE_WELLSPRING4_JIS,
+		HAS_INTEGRATED_BUTTON,
+		0x84, sizeof(struct bt_data),
+		0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS,
+		{ DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 300 },
+		{ DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 },
+		{ DIM_X, DIM_X / SN_COORD, -4620, 5140 },
+		{ DIM_Y, DIM_Y / SN_COORD, -150, 6600 }
+	},
+	{
+		USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI,
+		USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO,
+		USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS,
+		HAS_INTEGRATED_BUTTON,
+		0x84, sizeof(struct bt_data),
+		0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS,
+		{ DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 300 },
+		{ DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 },
+		{ DIM_X, DIM_X / SN_COORD, -4616, 5112 },
+		{ DIM_Y, DIM_Y / SN_COORD, -142, 5234 }
+	},
 	{}
 };
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/input/mouse/hgpk.c linux-libre-2.6.38-gnu1/drivers/input/mouse/hgpk.c
--- linux-libre-2.6.37-gnu1/drivers/input/mouse/hgpk.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/input/mouse/hgpk.c	2011-03-14 21:20:32.000000000 -0400
@@ -40,6 +40,8 @@
 #include "psmouse.h"
 #include "hgpk.h"
 
+#define ILLEGAL_XY 999999
+
 static bool tpdebug;
 module_param(tpdebug, bool, 0644);
 MODULE_PARM_DESC(tpdebug, "enable debugging, dumping packets to KERN_DEBUG.");
@@ -47,48 +49,150 @@ MODULE_PARM_DESC(tpdebug, "enable debugg
 static int recalib_delta = 100;
 module_param(recalib_delta, int, 0644);
 MODULE_PARM_DESC(recalib_delta,
-	"packets containing a delta this large will cause a recalibration.");
+	"packets containing a delta this large will be discarded, and a "
+	"recalibration may be scheduled.");
 
-static int jumpy_delay = 1000;
+static int jumpy_delay = 20;
 module_param(jumpy_delay, int, 0644);
 MODULE_PARM_DESC(jumpy_delay,
 	"delay (ms) before recal after jumpiness detected");
 
-static int spew_delay = 1000;
+static int spew_delay = 1;
 module_param(spew_delay, int, 0644);
 MODULE_PARM_DESC(spew_delay,
 	"delay (ms) before recal after packet spew detected");
 
-static int recal_guard_time = 2000;
+static int recal_guard_time;
 module_param(recal_guard_time, int, 0644);
 MODULE_PARM_DESC(recal_guard_time,
 	"interval (ms) during which recal will be restarted if packet received");
 
-static int post_interrupt_delay = 1000;
+static int post_interrupt_delay = 40;
 module_param(post_interrupt_delay, int, 0644);
 MODULE_PARM_DESC(post_interrupt_delay,
 	"delay (ms) before recal after recal interrupt detected");
 
+static bool autorecal = true;
+module_param(autorecal, bool, 0644);
+MODULE_PARM_DESC(autorecal, "enable recalibration in the driver");
+
+static char hgpk_mode_name[16];
+module_param_string(hgpk_mode, hgpk_mode_name, sizeof(hgpk_mode_name), 0644);
+MODULE_PARM_DESC(hgpk_mode,
+	"default hgpk mode: mouse, glidesensor or pentablet");
+
+static int hgpk_default_mode = HGPK_MODE_MOUSE;
+
+static const char * const hgpk_mode_names[] = {
+	[HGPK_MODE_MOUSE] = "Mouse",
+	[HGPK_MODE_GLIDESENSOR] = "GlideSensor",
+	[HGPK_MODE_PENTABLET] = "PenTablet",
+};
+
+static int hgpk_mode_from_name(const char *buf, int len)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(hgpk_mode_names); i++) {
+		const char *name = hgpk_mode_names[i];
+		if (strlen(name) == len && !strncasecmp(name, buf, len))
+			return i;
+	}
+
+	return HGPK_MODE_INVALID;
+}
+
 /*
- * When the touchpad gets ultra-sensitive, one can keep their finger 1/2"
- * above the pad and still have it send packets.  This causes a jump cursor
- * when one places their finger on the pad.  We can probably detect the
- * jump as we see a large deltas (>= 100px).  In mouse mode, I've been
- * unable to even come close to 100px deltas during normal usage, so I think
- * this threshold is safe.  If a large delta occurs, trigger a recalibration.
+ * see if new value is within 20% of half of old value
  */
-static void hgpk_jumpy_hack(struct psmouse *psmouse, int x, int y)
+static int approx_half(int curr, int prev)
+{
+	int belowhalf, abovehalf;
+
+	if (curr < 5 || prev < 5)
+		return 0;
+
+	belowhalf = (prev * 8) / 20;
+	abovehalf = (prev * 12) / 20;
+
+	return belowhalf < curr && curr <= abovehalf;
+}
+
+/*
+ * Throw out oddly large delta packets, and any that immediately follow whose
+ * values are each approximately half of the previous.  It seems that the ALPS
+ * firmware emits errant packets, and they get averaged out slowly.
+ */
+static int hgpk_discard_decay_hack(struct psmouse *psmouse, int x, int y)
 {
 	struct hgpk_data *priv = psmouse->private;
+	int avx, avy;
+	bool do_recal = false;
 
-	if (abs(x) > recalib_delta || abs(y) > recalib_delta) {
-		hgpk_err(psmouse, ">%dpx jump detected (%d,%d)\n",
-				recalib_delta, x, y);
-		/* My car gets forty rods to the hogshead and that's the
-		 * way I likes it! */
+	avx = abs(x);
+	avy = abs(y);
+
+	/* 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);
+		priv->xbigj = avx;
+	} else if (approx_half(avx, priv->xbigj)) {
+		hgpk_err(psmouse, "detected secondary %dpx jump in x\n", x);
+		priv->xbigj = avx;
+		priv->xsaw_secondary++;
+	} else {
+		if (priv->xbigj && priv->xsaw_secondary > 1)
+			do_recal = true;
+		priv->xbigj = 0;
+		priv->xsaw_secondary = 0;
+	}
+
+	if (avy > recalib_delta ||
+		(avy > recalib_delta / 2 && ((avy / 4) > priv->ylast))) {
+		hgpk_err(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);
+		priv->ybigj = avy;
+		priv->ysaw_secondary++;
+	} else {
+		if (priv->ybigj && priv->ysaw_secondary > 1)
+			do_recal = true;
+		priv->ybigj = 0;
+		priv->ysaw_secondary = 0;
+	}
+
+	priv->xlast = avx;
+	priv->ylast = avy;
+
+	if (do_recal && jumpy_delay) {
+		hgpk_err(psmouse, "scheduling recalibration\n");
 		psmouse_queue_work(psmouse, &priv->recalib_wq,
 				msecs_to_jiffies(jumpy_delay));
 	}
+
+	return priv->xbigj || priv->ybigj;
+}
+
+static void hgpk_reset_spew_detection(struct hgpk_data *priv)
+{
+	priv->spew_count = 0;
+	priv->dupe_count = 0;
+	priv->x_tally = 0;
+	priv->y_tally = 0;
+	priv->spew_flag = NO_SPEW;
+}
+
+static void hgpk_reset_hack_state(struct psmouse *psmouse)
+{
+	struct hgpk_data *priv = psmouse->private;
+
+	priv->abs_x = priv->abs_y = -1;
+	priv->xlast = priv->ylast = ILLEGAL_XY;
+	priv->xbigj = priv->ybigj = 0;
+	priv->xsaw_secondary = priv->ysaw_secondary = 0;
+	hgpk_reset_spew_detection(priv);
 }
 
 /*
@@ -116,20 +220,57 @@ static void hgpk_spewing_hack(struct psm
 	if (l || r)
 		return;
 
+	/* don't track spew if the workaround feature has been turned off */
+	if (!spew_delay)
+		return;
+
+	if (abs(x) > 3 || abs(y) > 3) {
+		/* no spew, or spew ended */
+		hgpk_reset_spew_detection(priv);
+		return;
+	}
+
+	/* Keep a tally of the overall delta to the cursor position caused by
+	 * the spew */
 	priv->x_tally += x;
 	priv->y_tally += y;
 
-	if (++priv->count > 100) {
+	switch (priv->spew_flag) {
+	case NO_SPEW:
+		/* we're not spewing, but this packet might be the start */
+		priv->spew_flag = MAYBE_SPEWING;
+
+		/* fall-through */
+
+	case MAYBE_SPEWING:
+		priv->spew_count++;
+
+		if (priv->spew_count < SPEW_WATCH_COUNT)
+			break;
+
+		/* excessive spew detected, request recalibration */
+		priv->spew_flag = SPEW_DETECTED;
+
+		/* fall-through */
+
+	case SPEW_DETECTED:
+		/* only recalibrate when the overall delta to the cursor
+		 * is really small. if the spew is causing significant cursor
+		 * 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_dbg(psmouse, "packet spew detected (%d,%d)\n",
+			hgpk_err(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));
 		}
-		/* reset every 100 packets */
-		priv->count = 0;
-		priv->x_tally = 0;
-		priv->y_tally = 0;
+
+		break;
+	case RECALIBRATING:
+		/* we already detected a spew and requested a recalibration,
+		 * just wait for the queue to kick into action. */
+		break;
 	}
 }
 
@@ -143,25 +284,168 @@ static void hgpk_spewing_hack(struct psm
  * swr/swl are the left/right buttons.
  * x-neg/y-neg are the x and y delta negative bits
  * x-over/y-over are the x and y overflow bits
+ *
+ * ---
+ *
+ * HGPK Advanced Mode - single-mode format
+ *
+ * byte 0(PT):  1    1    0    0    1    1     1     1
+ * byte 0(GS):  1    1    1    1    1    1     1     1
+ * byte 1:      0   x6   x5   x4   x3   x2    x1    x0
+ * byte 2(PT):  0    0   x9   x8   x7    ? pt-dsw    0
+ * byte 2(GS):  0  x10   x9   x8   x7    ? gs-dsw pt-dsw
+ * byte 3:      0   y9   y8   y7    1    0   swr   swl
+ * byte 4:      0   y6   y5   y4   y3   y2    y1    y0
+ * byte 5:      0   z6   z5   z4   z3   z2    z1    z0
+ *
+ * ?'s are not defined in the protocol spec, may vary between models.
+ *
+ * swr/swl are the left/right buttons.
+ *
+ * pt-dsw/gs-dsw indicate that the pt/gs sensor is detecting a
+ * pen/finger
  */
-static int hgpk_validate_byte(unsigned char *packet)
+static bool hgpk_is_byte_valid(struct psmouse *psmouse, unsigned char *packet)
 {
-	return (packet[0] & 0x0C) != 0x08;
+	struct hgpk_data *priv = psmouse->private;
+	int pktcnt = psmouse->pktcnt;
+	bool valid;
+
+	switch (priv->mode) {
+	case HGPK_MODE_MOUSE:
+		valid = (packet[0] & 0x0C) == 0x08;
+		break;
+
+	case HGPK_MODE_GLIDESENSOR:
+		valid = pktcnt == 1 ?
+			packet[0] == HGPK_GS : !(packet[pktcnt - 1] & 0x80);
+		break;
+
+	case HGPK_MODE_PENTABLET:
+		valid = pktcnt == 1 ?
+			packet[0] == HGPK_PT : !(packet[pktcnt - 1] & 0x80);
+		break;
+
+	default:
+		valid = false;
+		break;
+	}
+
+	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]);
+
+	return valid;
 }
 
-static void hgpk_process_packet(struct psmouse *psmouse)
+static void hgpk_process_advanced_packet(struct psmouse *psmouse)
+{
+	struct hgpk_data *priv = psmouse->private;
+	struct input_dev *idev = psmouse->dev;
+	unsigned char *packet = psmouse->packet;
+	int down = !!(packet[2] & 2);
+	int left = !!(packet[3] & 1);
+	int right = !!(packet[3] & 2);
+	int x = packet[1] | ((packet[2] & 0x78) << 4);
+	int y = packet[4] | ((packet[3] & 0x70) << 3);
+
+	if (priv->mode == HGPK_MODE_GLIDESENSOR) {
+		int pt_down = !!(packet[2] & 1);
+		int finger_down = !!(packet[2] & 2);
+		int z = packet[5];
+
+		input_report_abs(idev, ABS_PRESSURE, z);
+		if (tpdebug)
+			hgpk_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);
+	}
+
+	if (tpdebug)
+		hgpk_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);
+	input_report_key(idev, BTN_RIGHT, right);
+
+	/*
+	 * If this packet says that the finger was removed, reset our position
+	 * tracking so that we don't erroneously detect a jump on next press.
+	 */
+	if (!down) {
+		hgpk_reset_hack_state(psmouse);
+		goto done;
+	}
+
+	/*
+	 * Weed out duplicate packets (we get quite a few, and they mess up
+	 * our jump detection)
+	 */
+	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");
+			priv->spew_flag = RECALIBRATING;
+			psmouse_queue_work(psmouse, &priv->recalib_wq,
+					   msecs_to_jiffies(spew_delay));
+		}
+		goto done;
+	}
+
+	/* not a duplicate, continue with position reporting */
+	priv->dupe_count = 0;
+
+	/* Don't apply hacks in PT mode, it seems reliable */
+	if (priv->mode != HGPK_MODE_PENTABLET && priv->abs_x != -1) {
+		int x_diff = priv->abs_x - x;
+		int y_diff = priv->abs_y - y;
+		if (hgpk_discard_decay_hack(psmouse, x_diff, y_diff)) {
+			if (tpdebug)
+				hgpk_dbg(psmouse, "discarding\n");
+			goto done;
+		}
+		hgpk_spewing_hack(psmouse, left, right, x_diff, y_diff);
+	}
+
+	input_report_abs(idev, ABS_X, x);
+	input_report_abs(idev, ABS_Y, y);
+	priv->abs_x = x;
+	priv->abs_y = y;
+
+done:
+	input_sync(idev);
+}
+
+static void hgpk_process_simple_packet(struct psmouse *psmouse)
 {
 	struct input_dev *dev = psmouse->dev;
 	unsigned char *packet = psmouse->packet;
-	int x, y, left, right;
+	int left = packet[0] & 1;
+	int right = (packet[0] >> 1) & 1;
+	int x = packet[1] - ((packet[0] << 4) & 0x100);
+	int y = ((packet[0] << 3) & 0x100) - packet[2];
 
-	left = packet[0] & 1;
-	right = (packet[0] >> 1) & 1;
+	if (packet[0] & 0xc0)
+		hgpk_dbg(psmouse,
+			 "overflow -- 0x%02x 0x%02x 0x%02x\n",
+			 packet[0], packet[1], packet[2]);
 
-	x = packet[1] - ((packet[0] << 4) & 0x100);
-	y = ((packet[0] << 3) & 0x100) - packet[2];
+	if (hgpk_discard_decay_hack(psmouse, x, y)) {
+		if (tpdebug)
+			hgpk_dbg(psmouse, "discarding\n");
+		return;
+	}
 
-	hgpk_jumpy_hack(psmouse, x, y);
 	hgpk_spewing_hack(psmouse, left, right, x, y);
 
 	if (tpdebug)
@@ -180,15 +464,14 @@ static psmouse_ret_t hgpk_process_byte(s
 {
 	struct hgpk_data *priv = psmouse->private;
 
-	if (hgpk_validate_byte(psmouse->packet)) {
-		hgpk_dbg(psmouse, "%s: (%d) %02x %02x %02x\n",
-				__func__, psmouse->pktcnt, psmouse->packet[0],
-				psmouse->packet[1], psmouse->packet[2]);
+	if (!hgpk_is_byte_valid(psmouse, psmouse->packet))
 		return PSMOUSE_BAD_DATA;
-	}
 
 	if (psmouse->pktcnt >= psmouse->pktsize) {
-		hgpk_process_packet(psmouse);
+		if (priv->mode == HGPK_MODE_MOUSE)
+			hgpk_process_simple_packet(psmouse);
+		else
+			hgpk_process_advanced_packet(psmouse);
 		return PSMOUSE_FULL_PACKET;
 	}
 
@@ -210,33 +493,176 @@ static psmouse_ret_t hgpk_process_byte(s
 	return PSMOUSE_GOOD_DATA;
 }
 
+static int hgpk_select_mode(struct psmouse *psmouse)
+{
+	struct ps2dev *ps2dev = &psmouse->ps2dev;
+	struct hgpk_data *priv = psmouse->private;
+	int i;
+	int cmd;
+
+	/*
+	 * 4 disables to enable advanced mode
+	 * then 3 0xf2 bytes as the preamble for GS/PT selection
+	 */
+	const int advanced_init[] = {
+		PSMOUSE_CMD_DISABLE, PSMOUSE_CMD_DISABLE,
+		PSMOUSE_CMD_DISABLE, PSMOUSE_CMD_DISABLE,
+		0xf2, 0xf2, 0xf2,
+	};
+
+	switch (priv->mode) {
+	case HGPK_MODE_MOUSE:
+		psmouse->pktsize = 3;
+		break;
+
+	case HGPK_MODE_GLIDESENSOR:
+	case HGPK_MODE_PENTABLET:
+		psmouse->pktsize = 6;
+
+		/* Switch to 'Advanced mode.', four disables in a row. */
+		for (i = 0; i < ARRAY_SIZE(advanced_init); i++)
+			if (ps2_command(ps2dev, NULL, advanced_init[i]))
+				return -EIO;
+
+		/* select between GlideSensor (mouse) or PenTablet */
+		cmd = priv->mode == HGPK_MODE_GLIDESENSOR ?
+			PSMOUSE_CMD_SETSCALE11 : PSMOUSE_CMD_SETSCALE21;
+
+		if (ps2_command(ps2dev, NULL, cmd))
+			return -EIO;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static void hgpk_setup_input_device(struct input_dev *input,
+				    struct input_dev *old_input,
+				    enum hgpk_mode mode)
+{
+	if (old_input) {
+		input->name = old_input->name;
+		input->phys = old_input->phys;
+		input->id = old_input->id;
+		input->dev.parent = old_input->dev.parent;
+	}
+
+	memset(input->evbit, 0, sizeof(input->evbit));
+	memset(input->relbit, 0, sizeof(input->relbit));
+	memset(input->keybit, 0, sizeof(input->keybit));
+
+	/* All modes report left and right buttons */
+	__set_bit(EV_KEY, input->evbit);
+	__set_bit(BTN_LEFT, input->keybit);
+	__set_bit(BTN_RIGHT, input->keybit);
+
+	switch (mode) {
+	case HGPK_MODE_MOUSE:
+		__set_bit(EV_REL, input->evbit);
+		__set_bit(REL_X, input->relbit);
+		__set_bit(REL_Y, input->relbit);
+		break;
+
+	case HGPK_MODE_GLIDESENSOR:
+		__set_bit(BTN_TOUCH, input->keybit);
+		__set_bit(BTN_TOOL_FINGER, input->keybit);
+
+		__set_bit(EV_ABS, input->evbit);
+
+		/* GlideSensor has pressure sensor, PenTablet does not */
+		input_set_abs_params(input, ABS_PRESSURE, 0, 15, 0, 0);
+
+		/* From device specs */
+		input_set_abs_params(input, ABS_X, 0, 399, 0, 0);
+		input_set_abs_params(input, ABS_Y, 0, 290, 0, 0);
+
+		/* Calculated by hand based on usable size (52mm x 38mm) */
+		input_abs_set_res(input, ABS_X, 8);
+		input_abs_set_res(input, ABS_Y, 8);
+		break;
+
+	case HGPK_MODE_PENTABLET:
+		__set_bit(BTN_TOUCH, input->keybit);
+		__set_bit(BTN_TOOL_FINGER, input->keybit);
+
+		__set_bit(EV_ABS, input->evbit);
+
+		/* From device specs */
+		input_set_abs_params(input, ABS_X, 0, 999, 0, 0);
+		input_set_abs_params(input, ABS_Y, 5, 239, 0, 0);
+
+		/* Calculated by hand based on usable size (156mm x 38mm) */
+		input_abs_set_res(input, ABS_X, 6);
+		input_abs_set_res(input, ABS_Y, 8);
+		break;
+
+	default:
+		BUG();
+	}
+}
+
+static int hgpk_reset_device(struct psmouse *psmouse, bool recalibrate)
+{
+	int err;
+
+	psmouse_reset(psmouse);
+
+	if (recalibrate) {
+		struct ps2dev *ps2dev = &psmouse->ps2dev;
+
+		/* send the recalibrate request */
+		if (ps2_command(ps2dev, NULL, 0xf5) ||
+		    ps2_command(ps2dev, NULL, 0xf5) ||
+		    ps2_command(ps2dev, NULL, 0xe6) ||
+		    ps2_command(ps2dev, NULL, 0xf5)) {
+			return -1;
+		}
+
+		/* according to ALPS, 150mS is required for recalibration */
+		msleep(150);
+	}
+
+	err = hgpk_select_mode(psmouse);
+	if (err) {
+		hgpk_err(psmouse, "failed to select mode\n");
+		return err;
+	}
+
+	hgpk_reset_hack_state(psmouse);
+
+	return 0;
+}
+
 static int hgpk_force_recalibrate(struct psmouse *psmouse)
 {
 	struct ps2dev *ps2dev = &psmouse->ps2dev;
 	struct hgpk_data *priv = psmouse->private;
+	int err;
 
 	/* C-series touchpads added the recalibrate command */
 	if (psmouse->model < HGPK_MODEL_C)
 		return 0;
 
+	if (!autorecal) {
+		hgpk_dbg(psmouse, "recalibrations disabled, ignoring\n");
+		return 0;
+	}
+
+	hgpk_dbg(psmouse, "recalibrating touchpad..\n");
+
 	/* we don't want to race with the irq handler, nor with resyncs */
 	psmouse_set_state(psmouse, PSMOUSE_INITIALIZING);
 
 	/* start by resetting the device */
-	psmouse_reset(psmouse);
-
-	/* send the recalibrate request */
-	if (ps2_command(ps2dev, NULL, 0xf5) ||
-	    ps2_command(ps2dev, NULL, 0xf5) ||
-	    ps2_command(ps2dev, NULL, 0xe6) ||
-	    ps2_command(ps2dev, NULL, 0xf5)) {
-		return -1;
-	}
-
-	/* according to ALPS, 150mS is required for recalibration */
-	msleep(150);
+	err = hgpk_reset_device(psmouse, true);
+	if (err)
+		return err;
 
-	/* XXX: If a finger is down during this delay, recalibration will
+	/*
+	 * XXX: If a finger is down during this delay, recalibration will
 	 * detect capacitance incorrectly.  This is a hardware bug, and
 	 * we don't have a good way to deal with it.  The 2s window stuff
 	 * (below) is our best option for now.
@@ -247,25 +673,35 @@ static int hgpk_force_recalibrate(struct
 
 	psmouse_set_state(psmouse, PSMOUSE_ACTIVATED);
 
-	/* After we recalibrate, we shouldn't get any packets for 2s.  If
-	 * we do, it's likely that someone's finger was on the touchpad.
-	 * If someone's finger *was* on the touchpad, it's probably
-	 * miscalibrated.  So, we should schedule another recalibration
+	if (tpdebug)
+		hgpk_dbg(psmouse, "touchpad reactivated\n");
+
+	/*
+	 * If we get packets right away after recalibrating, it's likely
+	 * that a finger was on the touchpad.  If so, it's probably
+	 * miscalibrated, so we optionally schedule another.
 	 */
-	priv->recalib_window = jiffies +  msecs_to_jiffies(recal_guard_time);
+	if (recal_guard_time)
+		priv->recalib_window = jiffies +
+			msecs_to_jiffies(recal_guard_time);
 
 	return 0;
 }
 
 /*
- * This kills power to the touchpad; according to ALPS, current consumption
- * goes down to 50uA after running this.  To turn power back on, we drive
- * MS-DAT low.
+ * This puts the touchpad in a power saving mode; according to ALPS, current
+ * consumption goes down to 50uA after running this.  To turn power back on,
+ * we drive MS-DAT low.  Measuring with a 1mA resolution ammeter says that
+ * the current on the SUS_3.3V rail drops from 3mA or 4mA to 0 when we do this.
+ *
+ * We have no formal spec that details this operation -- the low-power
+ * sequence came from a long-lost email trail.
  */
-static int hgpk_toggle_power(struct psmouse *psmouse, int enable)
+static int hgpk_toggle_powersave(struct psmouse *psmouse, int enable)
 {
 	struct ps2dev *ps2dev = &psmouse->ps2dev;
 	int timeo;
+	int err;
 
 	/* Added on D-series touchpads */
 	if (psmouse->model < HGPK_MODEL_D)
@@ -279,24 +715,27 @@ static int hgpk_toggle_power(struct psmo
 		 * the controller.  Once we get an ACK back from it, it
 		 * means we can continue with the touchpad re-init.  ALPS
 		 * tells us that 1s should be long enough, so set that as
-		 * the upper bound.
+		 * the upper bound. (in practice, it takes about 3 loops.)
 		 */
 		for (timeo = 20; timeo > 0; timeo--) {
 			if (!ps2_sendbyte(&psmouse->ps2dev,
 					PSMOUSE_CMD_DISABLE, 20))
 				break;
-			msleep(50);
+			msleep(25);
 		}
 
-		psmouse_reset(psmouse);
+		err = hgpk_reset_device(psmouse, false);
+		if (err) {
+			hgpk_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");
 	} else {
 		hgpk_dbg(psmouse, "Powering off touchpad.\n");
-		psmouse_set_state(psmouse, PSMOUSE_IGNORE);
 
 		if (ps2_command(ps2dev, NULL, 0xec) ||
 		    ps2_command(ps2dev, NULL, 0xec) ||
@@ -304,6 +743,8 @@ static int hgpk_toggle_power(struct psmo
 			return -1;
 		}
 
+		psmouse_set_state(psmouse, PSMOUSE_IGNORE);
+
 		/* probably won't see an ACK, the touchpad will be off */
 		ps2_sendbyte(&psmouse->ps2dev, 0xec, 20);
 	}
@@ -319,17 +760,20 @@ static int hgpk_poll(struct psmouse *psm
 
 static int hgpk_reconnect(struct psmouse *psmouse)
 {
-	/* During suspend/resume the ps2 rails remain powered.  We don't want
+	struct hgpk_data *priv = psmouse->private;
+
+	/*
+	 * During suspend/resume the ps2 rails remain powered.  We don't want
 	 * to do a reset because it's flush data out of buffers; however,
-	 * earlier prototypes (B1) had some brokenness that required a reset. */
+	 * earlier prototypes (B1) had some brokenness that required a reset.
+	 */
 	if (olpc_board_at_least(olpc_board(0xb2)))
 		if (psmouse->ps2dev.serio->dev.power.power_state.event !=
 				PM_EVENT_ON)
 			return 0;
 
-	psmouse_reset(psmouse);
-
-	return 0;
+	priv->powered = 1;
+	return hgpk_reset_device(psmouse, false);
 }
 
 static ssize_t hgpk_show_powered(struct psmouse *psmouse, void *data, char *buf)
@@ -355,7 +799,7 @@ static ssize_t hgpk_set_powered(struct p
 		 * hgpk_toggle_power will deal w/ state so
 		 * we're not racing w/ irq
 		 */
-		err = hgpk_toggle_power(psmouse, value);
+		err = hgpk_toggle_powersave(psmouse, value);
 		if (!err)
 			priv->powered = value;
 	}
@@ -366,6 +810,65 @@ static ssize_t hgpk_set_powered(struct p
 __PSMOUSE_DEFINE_ATTR(powered, S_IWUSR | S_IRUGO, NULL,
 		      hgpk_show_powered, hgpk_set_powered, false);
 
+static ssize_t attr_show_mode(struct psmouse *psmouse, void *data, char *buf)
+{
+	struct hgpk_data *priv = psmouse->private;
+
+	return sprintf(buf, "%s\n", hgpk_mode_names[priv->mode]);
+}
+
+static ssize_t attr_set_mode(struct psmouse *psmouse, void *data,
+			     const char *buf, size_t len)
+{
+	struct hgpk_data *priv = psmouse->private;
+	enum hgpk_mode old_mode = priv->mode;
+	enum hgpk_mode new_mode = hgpk_mode_from_name(buf, len);
+	struct input_dev *old_dev = psmouse->dev;
+	struct input_dev *new_dev;
+	int err;
+
+	if (new_mode == HGPK_MODE_INVALID)
+		return -EINVAL;
+
+	if (old_mode == new_mode)
+		return len;
+
+	new_dev = input_allocate_device();
+	if (!new_dev)
+		return -ENOMEM;
+
+	psmouse_set_state(psmouse, PSMOUSE_INITIALIZING);
+
+	/* Switch device into the new mode */
+	priv->mode = new_mode;
+	err = hgpk_reset_device(psmouse, false);
+	if (err)
+		goto err_try_restore;
+
+	hgpk_setup_input_device(new_dev, old_dev, new_mode);
+
+	psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);
+
+	err = input_register_device(new_dev);
+	if (err)
+		goto err_try_restore;
+
+	psmouse->dev = new_dev;
+	input_unregister_device(old_dev);
+
+	return len;
+
+err_try_restore:
+	input_free_device(new_dev);
+	priv->mode = old_mode;
+	hgpk_reset_device(psmouse, false);
+
+	return err;
+}
+
+PSMOUSE_DEFINE_ATTR(hgpk_mode, S_IWUSR | S_IRUGO, NULL,
+		    attr_show_mode, attr_set_mode);
+
 static ssize_t hgpk_trigger_recal_show(struct psmouse *psmouse,
 		void *data, char *buf)
 {
@@ -401,6 +904,8 @@ static void hgpk_disconnect(struct psmou
 
 	device_remove_file(&psmouse->ps2dev.serio->dev,
 			   &psmouse_attr_powered.dattr);
+	device_remove_file(&psmouse->ps2dev.serio->dev,
+			   &psmouse_attr_hgpk_mode.dattr);
 
 	if (psmouse->model >= HGPK_MODEL_C)
 		device_remove_file(&psmouse->ps2dev.serio->dev,
@@ -416,14 +921,13 @@ static void hgpk_recalib_work(struct wor
 	struct hgpk_data *priv = container_of(w, struct hgpk_data, recalib_wq);
 	struct psmouse *psmouse = priv->psmouse;
 
-	hgpk_dbg(psmouse, "recalibrating touchpad..\n");
-
 	if (hgpk_force_recalibrate(psmouse))
 		hgpk_err(psmouse, "recalibration failed!\n");
 }
 
 static int hgpk_register(struct psmouse *psmouse)
 {
+	struct hgpk_data *priv = psmouse->private;
 	int err;
 
 	/* register handlers */
@@ -431,13 +935,14 @@ static int hgpk_register(struct psmouse
 	psmouse->poll = hgpk_poll;
 	psmouse->disconnect = hgpk_disconnect;
 	psmouse->reconnect = hgpk_reconnect;
-	psmouse->pktsize = 3;
 
 	/* Disable the idle resync. */
 	psmouse->resync_time = 0;
 	/* Reset after a lot of bad bytes. */
 	psmouse->resetafter = 1024;
 
+	hgpk_setup_input_device(psmouse->dev, NULL, priv->mode);
+
 	err = device_create_file(&psmouse->ps2dev.serio->dev,
 				 &psmouse_attr_powered.dattr);
 	if (err) {
@@ -445,6 +950,13 @@ static int hgpk_register(struct psmouse
 		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");
+		goto err_remove_powered;
+	}
+
 	/* C-series touchpads added the recalibrate command */
 	if (psmouse->model >= HGPK_MODEL_C) {
 		err = device_create_file(&psmouse->ps2dev.serio->dev,
@@ -452,30 +964,40 @@ static int hgpk_register(struct psmouse
 		if (err) {
 			hgpk_err(psmouse,
 				"Failed creating 'recalibrate' sysfs node\n");
-			device_remove_file(&psmouse->ps2dev.serio->dev,
-					&psmouse_attr_powered.dattr);
-			return err;
+			goto err_remove_mode;
 		}
 	}
 
 	return 0;
+
+err_remove_mode:
+	device_remove_file(&psmouse->ps2dev.serio->dev,
+			   &psmouse_attr_hgpk_mode.dattr);
+err_remove_powered:
+	device_remove_file(&psmouse->ps2dev.serio->dev,
+			   &psmouse_attr_powered.dattr);
+	return err;
 }
 
 int hgpk_init(struct psmouse *psmouse)
 {
 	struct hgpk_data *priv;
-	int err = -ENOMEM;
+	int err;
 
 	priv = kzalloc(sizeof(struct hgpk_data), GFP_KERNEL);
-	if (!priv)
+	if (!priv) {
+		err = -ENOMEM;
 		goto alloc_fail;
+	}
 
 	psmouse->private = priv;
+
 	priv->psmouse = psmouse;
 	priv->powered = true;
+	priv->mode = hgpk_default_mode;
 	INIT_DELAYED_WORK(&priv->recalib_wq, hgpk_recalib_work);
 
-	err = psmouse_reset(psmouse);
+	err = hgpk_reset_device(psmouse, false);
 	if (err)
 		goto init_fail;
 
@@ -531,3 +1053,14 @@ int hgpk_detect(struct psmouse *psmouse,
 
 	return 0;
 }
+
+void hgpk_module_init(void)
+{
+	hgpk_default_mode = hgpk_mode_from_name(hgpk_mode_name,
+						strlen(hgpk_mode_name));
+	if (hgpk_default_mode == HGPK_MODE_INVALID) {
+		hgpk_default_mode = HGPK_MODE_MOUSE;
+		strlcpy(hgpk_mode_name, hgpk_mode_names[HGPK_MODE_MOUSE],
+			sizeof(hgpk_mode_name));
+	}
+}
diff -druNp linux-libre-2.6.37-gnu1/drivers/input/mouse/hgpk.h linux-libre-2.6.38-gnu1/drivers/input/mouse/hgpk.h
--- linux-libre-2.6.37-gnu1/drivers/input/mouse/hgpk.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/input/mouse/hgpk.h	2011-03-14 21:20:32.000000000 -0400
@@ -5,6 +5,9 @@
 #ifndef _HGPK_H
 #define _HGPK_H
 
+#define HGPK_GS		0xff       /* The GlideSensor */
+#define HGPK_PT		0xcf       /* The PenTablet */
+
 enum hgpk_model_t {
 	HGPK_MODEL_PREA = 0x0a,	/* pre-B1s */
 	HGPK_MODEL_A = 0x14,	/* found on B1s, PT disabled in hardware */
@@ -13,12 +16,34 @@ enum hgpk_model_t {
 	HGPK_MODEL_D = 0x50,	/* C1, mass production */
 };
 
+enum hgpk_spew_flag {
+	NO_SPEW,
+	MAYBE_SPEWING,
+	SPEW_DETECTED,
+	RECALIBRATING,
+};
+
+#define SPEW_WATCH_COUNT 42  /* at 12ms/packet, this is 1/2 second */
+
+enum hgpk_mode {
+	HGPK_MODE_MOUSE,
+	HGPK_MODE_GLIDESENSOR,
+	HGPK_MODE_PENTABLET,
+	HGPK_MODE_INVALID
+};
+
 struct hgpk_data {
 	struct psmouse *psmouse;
+	enum hgpk_mode mode;
 	bool powered;
-	int count, x_tally, y_tally;	/* hardware workaround stuff */
+	enum hgpk_spew_flag spew_flag;
+	int spew_count, x_tally, y_tally;	/* spew detection */
 	unsigned long recalib_window;
 	struct delayed_work recalib_wq;
+	int abs_x, abs_y;
+	int dupe_count;
+	int xbigj, ybigj, xlast, ylast; /* jumpiness detection */
+	int xsaw_secondary, ysaw_secondary; /* jumpiness detection */
 };
 
 #define hgpk_dbg(psmouse, format, arg...)		\
@@ -33,9 +58,13 @@ struct hgpk_data {
 	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);
 int hgpk_init(struct psmouse *psmouse);
 #else
+static inline void hgpk_module_init(void)
+{
+}
 static inline int hgpk_detect(struct psmouse *psmouse, bool set_properties)
 {
 	return -ENODEV;
diff -druNp linux-libre-2.6.37-gnu1/drivers/input/mouse/Kconfig linux-libre-2.6.38-gnu1/drivers/input/mouse/Kconfig
--- linux-libre-2.6.37-gnu1/drivers/input/mouse/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/input/mouse/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -39,7 +39,7 @@ config MOUSE_PS2
 	  module will be called psmouse.
 
 config MOUSE_PS2_ALPS
-	bool "ALPS PS/2 mouse protocol extension" if EMBEDDED
+	bool "ALPS PS/2 mouse protocol extension" if EXPERT
 	default y
 	depends on MOUSE_PS2
 	help
@@ -49,7 +49,7 @@ config MOUSE_PS2_ALPS
 	  If unsure, say Y.
 
 config MOUSE_PS2_LOGIPS2PP
-	bool "Logitech PS/2++ mouse protocol extension" if EMBEDDED
+	bool "Logitech PS/2++ mouse protocol extension" if EXPERT
 	default y
 	depends on MOUSE_PS2
 	help
@@ -59,7 +59,7 @@ config MOUSE_PS2_LOGIPS2PP
 	  If unsure, say Y.
 
 config MOUSE_PS2_SYNAPTICS
-	bool "Synaptics PS/2 mouse protocol extension" if EMBEDDED
+	bool "Synaptics PS/2 mouse protocol extension" if EXPERT
 	default y
 	depends on MOUSE_PS2
 	help
@@ -69,7 +69,7 @@ config MOUSE_PS2_SYNAPTICS
 	  If unsure, say Y.
 
 config MOUSE_PS2_LIFEBOOK
-	bool "Fujitsu Lifebook PS/2 mouse protocol extension" if EMBEDDED
+	bool "Fujitsu Lifebook PS/2 mouse protocol extension" if EXPERT
 	default y
 	depends on MOUSE_PS2 && X86 && DMI
 	help
@@ -79,7 +79,7 @@ config MOUSE_PS2_LIFEBOOK
 	  If unsure, say Y.
 
 config MOUSE_PS2_TRACKPOINT
-	bool "IBM Trackpoint PS/2 mouse protocol extension" if EMBEDDED
+	bool "IBM Trackpoint PS/2 mouse protocol extension" if EXPERT
 	default y
 	depends on MOUSE_PS2
 	help
diff -druNp linux-libre-2.6.37-gnu1/drivers/input/mouse/psmouse-base.c linux-libre-2.6.38-gnu1/drivers/input/mouse/psmouse-base.c
--- linux-libre-2.6.37-gnu1/drivers/input/mouse/psmouse-base.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/input/mouse/psmouse-base.c	2011-03-14 21:20:32.000000000 -0400
@@ -1711,6 +1711,7 @@ static int __init psmouse_init(void)
 
 	lifebook_module_init();
 	synaptics_module_init();
+	hgpk_module_init();
 
 	kpsmoused_wq = create_singlethread_workqueue("kpsmoused");
 	if (!kpsmoused_wq) {
diff -druNp linux-libre-2.6.37-gnu1/drivers/input/mouse/synaptics.c linux-libre-2.6.38-gnu1/drivers/input/mouse/synaptics.c
--- linux-libre-2.6.37-gnu1/drivers/input/mouse/synaptics.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/input/mouse/synaptics.c	2011-03-14 21:20:32.000000000 -0400
@@ -25,7 +25,7 @@
 
 #include <linux/module.h>
 #include <linux/dmi.h>
-#include <linux/input.h>
+#include <linux/input/mt.h>
 #include <linux/serio.h>
 #include <linux/libps2.h>
 #include <linux/slab.h>
@@ -279,6 +279,25 @@ static void synaptics_set_rate(struct ps
 	synaptics_mode_cmd(psmouse, priv->mode);
 }
 
+static int synaptics_set_advanced_gesture_mode(struct psmouse *psmouse)
+{
+	static unsigned char param = 0xc8;
+	struct synaptics_data *priv = psmouse->private;
+
+	if (!SYN_CAP_ADV_GESTURE(priv->ext_cap_0c))
+		return 0;
+
+	if (psmouse_sliced_command(psmouse, SYN_QUE_MODEL))
+		return -1;
+	if (ps2_command(&psmouse->ps2dev, &param, PSMOUSE_CMD_SETRATE))
+		return -1;
+
+	/* Advanced gesture mode also sends multi finger data */
+	priv->capabilities |= BIT(1);
+
+	return 0;
+}
+
 /*****************************************************************************
  *	Synaptics pass-through PS/2 port support
  ****************************************************************************/
@@ -380,7 +399,9 @@ static void synaptics_pt_create(struct p
  *	Functions to interpret the absolute mode packets
  ****************************************************************************/
 
-static void synaptics_parse_hw_state(unsigned char buf[], struct synaptics_data *priv, struct synaptics_hw_state *hw)
+static int synaptics_parse_hw_state(const unsigned char buf[],
+				    struct synaptics_data *priv,
+				    struct synaptics_hw_state *hw)
 {
 	memset(hw, 0, sizeof(struct synaptics_hw_state));
 
@@ -397,6 +418,14 @@ static void synaptics_parse_hw_state(uns
 			 ((buf[0] & 0x04) >> 1) |
 			 ((buf[3] & 0x04) >> 2));
 
+		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;
+			return 1;
+		}
+
 		hw->left  = (buf[0] & 0x01) ? 1 : 0;
 		hw->right = (buf[0] & 0x02) ? 1 : 0;
 
@@ -452,6 +481,36 @@ static void synaptics_parse_hw_state(uns
 		hw->left  = (buf[0] & 0x01) ? 1 : 0;
 		hw->right = (buf[0] & 0x02) ? 1 : 0;
 	}
+
+	return 0;
+}
+
+static void set_slot(struct input_dev *dev, int slot, bool active, int x, int y)
+{
+	input_mt_slot(dev, slot);
+	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);
+	}
+}
+
+static void synaptics_report_semi_mt_data(struct input_dev *dev,
+					  const struct synaptics_hw_state *a,
+					  const struct synaptics_hw_state *b,
+					  int num_fingers)
+{
+	if (num_fingers >= 2) {
+		set_slot(dev, 0, true, min(a->x, b->x), min(a->y, b->y));
+		set_slot(dev, 1, true, max(a->x, b->x), max(a->y, b->y));
+	} else if (num_fingers == 1) {
+		set_slot(dev, 0, true, a->x, a->y);
+		set_slot(dev, 1, false, 0, 0);
+	} else {
+		set_slot(dev, 0, false, 0, 0);
+		set_slot(dev, 1, false, 0, 0);
+	}
 }
 
 /*
@@ -466,7 +525,8 @@ static void synaptics_process_packet(str
 	int finger_width;
 	int i;
 
-	synaptics_parse_hw_state(psmouse->packet, priv, &hw);
+	if (synaptics_parse_hw_state(psmouse->packet, priv, &hw))
+		return;
 
 	if (hw.scroll) {
 		priv->scroll += hw.scroll;
@@ -488,7 +548,7 @@ static void synaptics_process_packet(str
 		return;
 	}
 
-	if (hw.z > 0) {
+	if (hw.z > 0 && hw.x > 1) {
 		num_fingers = 1;
 		finger_width = 5;
 		if (SYN_CAP_EXTENDED(priv->capabilities)) {
@@ -512,6 +572,9 @@ static void synaptics_process_packet(str
 		finger_width = 0;
 	}
 
+	if (SYN_CAP_ADV_GESTURE(priv->ext_cap_0c))
+		synaptics_report_semi_mt_data(dev, &hw, &priv->mt, num_fingers);
+
 	/* Post events
 	 * BTN_TOUCH has to be first as mousedev relies on it when doing
 	 * absolute -> relative conversion
@@ -519,7 +582,7 @@ static void synaptics_process_packet(str
 	if (hw.z > 30) input_report_key(dev, BTN_TOUCH, 1);
 	if (hw.z < 25) input_report_key(dev, BTN_TOUCH, 0);
 
-	if (hw.z > 0) {
+	if (num_fingers > 0) {
 		input_report_abs(dev, ABS_X, hw.x);
 		input_report_abs(dev, ABS_Y, YMAX_NOMINAL + YMIN_NOMINAL - hw.y);
 	}
@@ -622,6 +685,8 @@ static void set_input_params(struct inpu
 {
 	int i;
 
+	__set_bit(INPUT_PROP_POINTER, dev->propbit);
+
 	__set_bit(EV_ABS, dev->evbit);
 	input_set_abs_params(dev, ABS_X,
 			     XMIN_NOMINAL, priv->x_max ?: XMAX_NOMINAL, 0, 0);
@@ -629,6 +694,15 @@ static void set_input_params(struct inpu
 			     YMIN_NOMINAL, priv->y_max ?: YMAX_NOMINAL, 0, 0);
 	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);
+		input_mt_init_slots(dev, 2);
+		input_set_abs_params(dev, ABS_MT_POSITION_X, XMIN_NOMINAL,
+				     priv->x_max ?: XMAX_NOMINAL, 0, 0);
+		input_set_abs_params(dev, ABS_MT_POSITION_Y, YMIN_NOMINAL,
+				     priv->y_max ?: YMAX_NOMINAL, 0, 0);
+	}
+
 	if (SYN_CAP_PALMDETECT(priv->capabilities))
 		input_set_abs_params(dev, ABS_TOOL_WIDTH, 0, 15, 0, 0);
 
@@ -663,6 +737,7 @@ static void set_input_params(struct inpu
 	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 */
 		__clear_bit(BTN_RIGHT, dev->keybit);
 		__clear_bit(BTN_MIDDLE, dev->keybit);
@@ -680,25 +755,46 @@ static int synaptics_reconnect(struct ps
 {
 	struct synaptics_data *priv = psmouse->private;
 	struct synaptics_data old_priv = *priv;
+	int retry = 0;
+	int error;
 
-	psmouse_reset(psmouse);
+	do {
+		psmouse_reset(psmouse);
+		error = synaptics_detect(psmouse, 0);
+	} while (error && ++retry < 3);
 
-	if (synaptics_detect(psmouse, 0))
+	if (error)
 		return -1;
 
+	if (retry > 1)
+		printk(KERN_DEBUG "Synaptics reconnected after %d tries\n",
+			retry);
+
 	if (synaptics_query_hardware(psmouse)) {
 		printk(KERN_ERR "Unable to query Synaptics hardware.\n");
 		return -1;
 	}
 
+	if (synaptics_set_absolute_mode(psmouse)) {
+		printk(KERN_ERR "Unable to initialize Synaptics hardware.\n");
+		return -1;
+	}
+
+	if (synaptics_set_advanced_gesture_mode(psmouse)) {
+		printk(KERN_ERR "Advanced gesture mode reconnect failed.\n");
+		return -1;
+	}
+
 	if (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;
-
-	if (synaptics_set_absolute_mode(psmouse)) {
-		printk(KERN_ERR "Unable to initialize Synaptics hardware.\n");
+	    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);
 		return -1;
 	}
 
@@ -744,15 +840,45 @@ static const struct dmi_system_id __init
 #endif
 };
 
+static bool broken_olpc_ec;
+
+static const struct dmi_system_id __initconst olpc_dmi_table[] = {
+#if defined(CONFIG_DMI) && defined(CONFIG_OLPC)
+	{
+		/* OLPC XO-1 or XO-1.5 */
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "OLPC"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "XO"),
+		},
+	},
+	{ }
+#endif
+};
+
 void __init synaptics_module_init(void)
 {
 	impaired_toshiba_kbc = dmi_check_system(toshiba_dmi_table);
+	broken_olpc_ec = dmi_check_system(olpc_dmi_table);
 }
 
 int synaptics_init(struct psmouse *psmouse)
 {
 	struct synaptics_data *priv;
 
+	/*
+	 * The OLPC XO has issues with Synaptics' absolute mode; similarly to
+	 * the HGPK, it quickly degrades and the hardware becomes jumpy and
+	 * overly sensitive.  Not only that, but the constant packet spew
+	 * (even at a lowered 40pps rate) overloads the EC such that key
+	 * presses on the keyboard are missed.  Given all of that, don't
+	 * even attempt to use Synaptics mode.  Relative mode seems to work
+	 * just fine.
+	 */
+	if (broken_olpc_ec) {
+		printk(KERN_INFO "synaptics: OLPC XO detected, not enabling Synaptics protocol.\n");
+		return -ENODEV;
+	}
+
 	psmouse->private = priv = kzalloc(sizeof(struct synaptics_data), GFP_KERNEL);
 	if (!priv)
 		return -ENOMEM;
@@ -769,6 +895,11 @@ int synaptics_init(struct psmouse *psmou
 		goto init_fail;
 	}
 
+	if (synaptics_set_advanced_gesture_mode(psmouse)) {
+		printk(KERN_ERR "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",
@@ -802,8 +933,8 @@ int synaptics_init(struct psmouse *psmou
 
 	/*
 	 * Toshiba's KBC seems to have trouble handling data from
-	 * Synaptics as full rate, switch to lower rate which is roughly
-	 * thye same as rate of standard PS/2 mouse.
+	 * Synaptics at full rate.  Switch to a lower rate (roughly
+	 * 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",
diff -druNp linux-libre-2.6.37-gnu1/drivers/input/mouse/synaptics.h linux-libre-2.6.38-gnu1/drivers/input/mouse/synaptics.h
--- linux-libre-2.6.37-gnu1/drivers/input/mouse/synaptics.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/input/mouse/synaptics.h	2011-03-14 21:20:32.000000000 -0400
@@ -51,9 +51,33 @@
 #define SYN_EXT_CAP_REQUESTS(c)		(((c) & 0x700000) >> 20)
 #define SYN_CAP_MULTI_BUTTON_NO(ec)	(((ec) & 0x00f000) >> 12)
 #define SYN_CAP_PRODUCT_ID(ec)		(((ec) & 0xff0000) >> 16)
+
+/*
+ * The following describes response for the 0x0c query.
+ *
+ * byte	mask	name			meaning
+ * ----	----	-------			------------
+ * 1	0x01	adjustable threshold	capacitive button sensitivity
+ *					can be adjusted
+ * 1	0x02	report max		query 0x0d gives max coord reported
+ * 1	0x04	clearpad		sensor is ClearPad product
+ * 1	0x08	advanced gesture	not particularly meaningful
+ * 1	0x10	clickpad bit 0		1-button ClickPad
+ * 1	0x60	multifinger mode	identifies firmware finger counting
+ *					(not reporting!) algorithm.
+ *					Not particularly meaningful
+ * 1	0x80    covered pad		W clipped to 14, 15 == pad mostly covered
+ * 2	0x01    clickpad bit 1		2-button ClickPad
+ * 2	0x02    deluxe LED controls	touchpad support LED commands
+ *					ala multimedia control bar
+ * 2	0x04	reduced filtering	firmware does less filtering on
+ *					position data, driver should watch
+ *					for noise.
+ */
 #define SYN_CAP_CLICKPAD(ex0c)		((ex0c) & 0x100000) /* 1-button ClickPad */
 #define SYN_CAP_CLICKPAD2BTN(ex0c)	((ex0c) & 0x000100) /* 2-button ClickPad */
 #define SYN_CAP_MAX_DIMENSIONS(ex0c)	((ex0c) & 0x020000)
+#define SYN_CAP_ADV_GESTURE(ex0c)	((ex0c) & 0x080000)
 
 /* synaptics modes query bits */
 #define SYN_MODE_ABSOLUTE(m)		((m) & (1 << 7))
@@ -113,6 +137,8 @@ struct synaptics_data {
 	int scroll;
 
 	struct serio *pt_port;			/* Pass-through serio port */
+
+	struct synaptics_hw_state mt;		/* current gesture packet */
 };
 
 void synaptics_module_init(void);
diff -druNp linux-libre-2.6.37-gnu1/drivers/input/mousedev.c linux-libre-2.6.38-gnu1/drivers/input/mousedev.c
--- linux-libre-2.6.37-gnu1/drivers/input/mousedev.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/input/mousedev.c	2011-03-14 21:20:32.000000000 -0400
@@ -9,6 +9,8 @@
  * the Free Software Foundation.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #define MOUSEDEV_MINOR_BASE	32
 #define MOUSEDEV_MINORS		32
 #define MOUSEDEV_MIX		31
@@ -977,7 +979,7 @@ static int mousedev_connect(struct input
 			break;
 
 	if (minor == MOUSEDEV_MINORS) {
-		printk(KERN_ERR "mousedev: no more free mousedev devices\n");
+		pr_err("no more free mousedev devices\n");
 		return -ENFILE;
 	}
 
@@ -1087,13 +1089,13 @@ static int __init mousedev_init(void)
 #ifdef CONFIG_INPUT_MOUSEDEV_PSAUX
 	error = misc_register(&psaux_mouse);
 	if (error)
-		printk(KERN_WARNING "mice: could not register psaux device, "
-			"error: %d\n", error);
+		pr_warning("could not register psaux device, error: %d\n",
+			   error);
 	else
 		psaux_registered = 1;
 #endif
 
-	printk(KERN_INFO "mice: PS/2 mouse device common for all mice\n");
+	pr_info("PS/2 mouse device common for all mice\n");
 
 	return 0;
 }
diff -druNp linux-libre-2.6.37-gnu1/drivers/input/serio/ams_delta_serio.c linux-libre-2.6.38-gnu1/drivers/input/serio/ams_delta_serio.c
--- linux-libre-2.6.37-gnu1/drivers/input/serio/ams_delta_serio.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/input/serio/ams_delta_serio.c	2011-03-14 21:20:32.000000000 -0400
@@ -172,6 +172,5 @@ static void __exit ams_delta_serio_exit(
 	free_irq(OMAP_GPIO_IRQ(AMS_DELTA_GPIO_PIN_KEYBRD_CLK), 0);
 	gpio_free(AMS_DELTA_GPIO_PIN_KEYBRD_CLK);
 	gpio_free(AMS_DELTA_GPIO_PIN_KEYBRD_DATA);
-	kfree(ams_delta_serio);
 }
 module_exit(ams_delta_serio_exit);
diff -druNp linux-libre-2.6.37-gnu1/drivers/input/serio/ct82c710.c linux-libre-2.6.38-gnu1/drivers/input/serio/ct82c710.c
--- linux-libre-2.6.37-gnu1/drivers/input/serio/ct82c710.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/input/serio/ct82c710.c	2011-03-14 21:20:32.000000000 -0400
@@ -111,9 +111,11 @@ static void ct82c710_close(struct serio
 static int ct82c710_open(struct serio *serio)
 {
 	unsigned char status;
+	int err;
 
-	if (request_irq(CT82C710_IRQ, ct82c710_interrupt, 0, "ct82c710", NULL))
-		return -1;
+	err = request_irq(CT82C710_IRQ, ct82c710_interrupt, 0, "ct82c710", NULL);
+	if (err)
+		return err;
 
 	status = inb_p(CT82C710_STATUS);
 
@@ -131,7 +133,7 @@ static int ct82c710_open(struct serio *s
 		status &= ~(CT82C710_ENABLE | CT82C710_INTS_ON);
 		outb_p(status, CT82C710_STATUS);
 		free_irq(CT82C710_IRQ, NULL);
-		return -1;
+		return -EBUSY;
 	}
 
 	return 0;
@@ -191,6 +193,9 @@ static int __devinit ct82c710_probe(stru
 
 	serio_register_port(ct82c710_port);
 
+	printk(KERN_INFO "serio: C&T 82c710 mouse port at %#llx irq %d\n",
+		(unsigned long long)CT82C710_DATA, CT82C710_IRQ);
+
 	return 0;
 }
 
@@ -237,11 +242,6 @@ static int __init ct82c710_init(void)
 	if (error)
 		goto err_free_device;
 
-	serio_register_port(ct82c710_port);
-
-	printk(KERN_INFO "serio: C&T 82c710 mouse port at %#llx irq %d\n",
-		(unsigned long long)CT82C710_DATA, CT82C710_IRQ);
-
 	return 0;
 
  err_free_device:
diff -druNp linux-libre-2.6.37-gnu1/drivers/input/serio/hil_mlc.c linux-libre-2.6.38-gnu1/drivers/input/serio/hil_mlc.c
--- linux-libre-2.6.37-gnu1/drivers/input/serio/hil_mlc.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/input/serio/hil_mlc.c	2011-03-14 21:20:32.000000000 -0400
@@ -932,6 +932,11 @@ int hil_mlc_register(hil_mlc *mlc)
 		hil_mlc_copy_di_scratch(mlc, i);
 		mlc_serio = kzalloc(sizeof(*mlc_serio), GFP_KERNEL);
 		mlc->serio[i] = mlc_serio;
+		if (!mlc->serio[i]) {
+			for (; i >= 0; i--)
+				kfree(mlc->serio[i]);
+			return -ENOMEM;
+		}
 		snprintf(mlc_serio->name, sizeof(mlc_serio->name)-1, "HIL_SERIO%d", i);
 		snprintf(mlc_serio->phys, sizeof(mlc_serio->phys)-1, "HIL%d", i);
 		mlc_serio->id			= hil_mlc_serio_id;
diff -druNp linux-libre-2.6.37-gnu1/drivers/input/serio/hp_sdc_mlc.c linux-libre-2.6.38-gnu1/drivers/input/serio/hp_sdc_mlc.c
--- linux-libre-2.6.37-gnu1/drivers/input/serio/hp_sdc_mlc.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/input/serio/hp_sdc_mlc.c	2011-03-14 21:20:32.000000000 -0400
@@ -305,6 +305,7 @@ static void hp_sdc_mlc_out(hil_mlc *mlc)
 static int __init hp_sdc_mlc_init(void)
 {
 	hil_mlc *mlc = &hp_sdc_mlc;
+	int err;
 
 #ifdef __mc68000__
 	if (!MACH_IS_HP300)
@@ -323,22 +324,21 @@ static int __init hp_sdc_mlc_init(void)
 	mlc->out = &hp_sdc_mlc_out;
 	mlc->priv = &hp_sdc_mlc_priv;
 
-	if (hil_mlc_register(mlc)) {
+	err = hil_mlc_register(mlc);
+	if (err) {
 		printk(KERN_WARNING PREFIX "Failed to register MLC structure with hil_mlc\n");
-		goto err0;
+		return err;
 	}
 
 	if (hp_sdc_request_hil_irq(&hp_sdc_mlc_isr)) {
 		printk(KERN_WARNING PREFIX "Request for raw HIL ISR hook denied\n");
-		goto err1;
+		if (hil_mlc_unregister(mlc))
+			printk(KERN_ERR PREFIX "Failed to unregister MLC structure with hil_mlc.\n"
+				"This is bad.  Could cause an oops.\n");
+		return -EBUSY;
 	}
+
 	return 0;
- err1:
-	if (hil_mlc_unregister(mlc))
-		printk(KERN_ERR PREFIX "Failed to unregister MLC structure with hil_mlc.\n"
-			"This is bad.  Could cause an oops.\n");
- err0:
-	return -EBUSY;
 }
 
 static void __exit hp_sdc_mlc_exit(void)
diff -druNp linux-libre-2.6.37-gnu1/drivers/input/serio/i8042.c linux-libre-2.6.38-gnu1/drivers/input/serio/i8042.c
--- linux-libre-2.6.37-gnu1/drivers/input/serio/i8042.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/input/serio/i8042.c	2011-03-14 21:20:32.000000000 -0400
@@ -10,6 +10,8 @@
  * the Free Software Foundation.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/types.h>
 #include <linux/delay.h>
 #include <linux/module.h>
@@ -61,6 +63,10 @@ static bool i8042_noloop;
 module_param_named(noloop, i8042_noloop, bool, 0);
 MODULE_PARM_DESC(noloop, "Disable the AUX Loopback command while probing for the AUX port");
 
+static bool i8042_notimeout;
+module_param_named(notimeout, i8042_notimeout, bool, 0);
+MODULE_PARM_DESC(notimeout, "Ignore timeouts signalled by i8042");
+
 #ifdef CONFIG_X86
 static bool i8042_dritek;
 module_param_named(dritek, i8042_dritek, bool, 0);
@@ -225,8 +231,8 @@ static int i8042_flush(void)
 		udelay(50);
 		data = i8042_read_data();
 		i++;
-		dbg("%02x <- i8042 (flush, %s)", data,
-			str & I8042_STR_AUXDATA ? "aux" : "kbd");
+		dbg("%02x <- i8042 (flush, %s)\n",
+		    data, str & I8042_STR_AUXDATA ? "aux" : "kbd");
 	}
 
 	spin_unlock_irqrestore(&i8042_lock, flags);
@@ -253,32 +259,32 @@ static int __i8042_command(unsigned char
 	if (error)
 		return error;
 
-	dbg("%02x -> i8042 (command)", command & 0xff);
+	dbg("%02x -> i8042 (command)\n", command & 0xff);
 	i8042_write_command(command & 0xff);
 
 	for (i = 0; i < ((command >> 12) & 0xf); i++) {
 		error = i8042_wait_write();
 		if (error)
 			return error;
-		dbg("%02x -> i8042 (parameter)", param[i]);
+		dbg("%02x -> i8042 (parameter)\n", param[i]);
 		i8042_write_data(param[i]);
 	}
 
 	for (i = 0; i < ((command >> 8) & 0xf); i++) {
 		error = i8042_wait_read();
 		if (error) {
-			dbg("     -- i8042 (timeout)");
+			dbg("     -- i8042 (timeout)\n");
 			return error;
 		}
 
 		if (command == I8042_CMD_AUX_LOOP &&
 		    !(i8042_read_status() & I8042_STR_AUXDATA)) {
-			dbg("     -- i8042 (auxerr)");
+			dbg("     -- i8042 (auxerr)\n");
 			return -1;
 		}
 
 		param[i] = i8042_read_data();
-		dbg("%02x <- i8042 (return)", param[i]);
+		dbg("%02x <- i8042 (return)\n", param[i]);
 	}
 
 	return 0;
@@ -309,7 +315,7 @@ static int i8042_kbd_write(struct serio
 	spin_lock_irqsave(&i8042_lock, flags);
 
 	if (!(retval = i8042_wait_write())) {
-		dbg("%02x -> i8042 (kbd-data)", c);
+		dbg("%02x -> i8042 (kbd-data)\n", c);
 		i8042_write_data(c);
 	}
 
@@ -355,17 +361,14 @@ static void i8042_port_close(struct seri
 
 	i8042_ctr &= ~irq_bit;
 	if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR))
-		printk(KERN_WARNING
-			"i8042.c: Can't write CTR while closing %s port.\n",
-			port_name);
+		pr_warn("Can't write CTR while closing %s port\n", port_name);
 
 	udelay(50);
 
 	i8042_ctr &= ~disable_bit;
 	i8042_ctr |= irq_bit;
 	if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR))
-		printk(KERN_ERR "i8042.c: Can't reactivate %s port.\n",
-			port_name);
+		pr_err("Can't reactivate %s port\n", port_name);
 
 	/*
 	 * See if there is any data appeared while we were messing with
@@ -456,7 +459,8 @@ static irqreturn_t i8042_interrupt(int i
 	str = i8042_read_status();
 	if (unlikely(~str & I8042_STR_OBF)) {
 		spin_unlock_irqrestore(&i8042_lock, flags);
-		if (irq) dbg("Interrupt %d, without any data", irq);
+		if (irq)
+			dbg("Interrupt %d, without any data\n", irq);
 		ret = 0;
 		goto out;
 	}
@@ -469,7 +473,8 @@ static irqreturn_t i8042_interrupt(int i
 
 		dfl = 0;
 		if (str & I8042_STR_MUXERR) {
-			dbg("MUX error, status is %02x, data is %02x", str, data);
+			dbg("MUX error, status is %02x, data is %02x\n",
+			    str, data);
 /*
  * When MUXERR condition is signalled the data register can only contain
  * 0xfd, 0xfe or 0xff if implementation follows the spec. Unfortunately
@@ -503,7 +508,7 @@ static irqreturn_t i8042_interrupt(int i
 	} else {
 
 		dfl = ((str & I8042_STR_PARITY) ? SERIO_PARITY : 0) |
-		      ((str & I8042_STR_TIMEOUT) ? SERIO_TIMEOUT : 0);
+		      ((str & I8042_STR_TIMEOUT && !i8042_notimeout) ? SERIO_TIMEOUT : 0);
 
 		port_no = (str & I8042_STR_AUXDATA) ?
 				I8042_AUX_PORT_NO : I8042_KBD_PORT_NO;
@@ -512,7 +517,7 @@ static irqreturn_t i8042_interrupt(int i
 	port = &i8042_ports[port_no];
 	serio = port->exists ? port->serio : NULL;
 
-	dbg("%02x <- i8042 (interrupt, %d, %d%s%s)",
+	dbg("%02x <- i8042 (interrupt, %d, %d%s%s)\n",
 	    data, port_no, irq,
 	    dfl & SERIO_PARITY ? ", bad parity" : "",
 	    dfl & SERIO_TIMEOUT ? ", timeout" : "");
@@ -540,7 +545,7 @@ static int i8042_enable_kbd_port(void)
 	if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) {
 		i8042_ctr &= ~I8042_CTR_KBDINT;
 		i8042_ctr |= I8042_CTR_KBDDIS;
-		printk(KERN_ERR "i8042.c: Failed to enable KBD port.\n");
+		pr_err("Failed to enable KBD port\n");
 		return -EIO;
 	}
 
@@ -559,7 +564,7 @@ static int i8042_enable_aux_port(void)
 	if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) {
 		i8042_ctr &= ~I8042_CTR_AUXINT;
 		i8042_ctr |= I8042_CTR_AUXDIS;
-		printk(KERN_ERR "i8042.c: Failed to enable AUX port.\n");
+		pr_err("Failed to enable AUX port\n");
 		return -EIO;
 	}
 
@@ -641,7 +646,7 @@ static int __init i8042_check_mux(void)
 	if (i8042_set_mux_mode(true, &mux_version))
 		return -1;
 
-	printk(KERN_INFO "i8042.c: Detected active multiplexing controller, rev %d.%d.\n",
+	pr_info("Detected active multiplexing controller, rev %d.%d\n",
 		(mux_version >> 4) & 0xf, mux_version & 0xf);
 
 /*
@@ -651,7 +656,7 @@ static int __init i8042_check_mux(void)
 	i8042_ctr &= ~I8042_CTR_AUXINT;
 
 	if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) {
-		printk(KERN_ERR "i8042.c: Failed to disable AUX port, can't use MUX.\n");
+		pr_err("Failed to disable AUX port, can't use MUX\n");
 		return -EIO;
 	}
 
@@ -676,8 +681,8 @@ static irqreturn_t __init i8042_aux_test
 	str = i8042_read_status();
 	if (str & I8042_STR_OBF) {
 		data = i8042_read_data();
-		dbg("%02x <- i8042 (aux_test_irq, %s)",
-			data, str & I8042_STR_AUXDATA ? "aux" : "kbd");
+		dbg("%02x <- i8042 (aux_test_irq, %s)\n",
+		    data, str & I8042_STR_AUXDATA ? "aux" : "kbd");
 		if (i8042_irq_being_tested &&
 		    data == 0xa5 && (str & I8042_STR_AUXDATA))
 			complete(&i8042_aux_irq_delivered);
@@ -770,8 +775,8 @@ static int __init i8042_check_aux(void)
  */
 
 	if (i8042_toggle_aux(false)) {
-		printk(KERN_WARNING "Failed to disable AUX port, but continuing anyway... Is this a SiS?\n");
-		printk(KERN_WARNING "If AUX port is really absent please use the 'i8042.noaux' option.\n");
+		pr_warn("Failed to disable AUX port, but continuing anyway... Is this a SiS?\n");
+		pr_warn("If AUX port is really absent please use the 'i8042.noaux' option\n");
 	}
 
 	if (i8042_toggle_aux(true))
@@ -819,7 +824,7 @@ static int __init i8042_check_aux(void)
  * AUX IRQ was never delivered so we need to flush the controller to
  * get rid of the byte we put there; otherwise keyboard may not work.
  */
-		dbg("     -- i8042 (aux irq test timeout)");
+		dbg("     -- i8042 (aux irq test timeout)\n");
 		i8042_flush();
 		retval = -1;
 	}
@@ -845,7 +850,7 @@ static int __init i8042_check_aux(void)
 static int i8042_controller_check(void)
 {
 	if (i8042_flush() == I8042_BUFFER_SIZE) {
-		printk(KERN_ERR "i8042.c: No controller found.\n");
+		pr_err("No controller found\n");
 		return -ENODEV;
 	}
 
@@ -864,15 +869,15 @@ static int i8042_controller_selftest(voi
 	do {
 
 		if (i8042_command(&param, I8042_CMD_CTL_TEST)) {
-			printk(KERN_ERR "i8042.c: i8042 controller self test timeout.\n");
+			pr_err("i8042 controller self test timeout\n");
 			return -ENODEV;
 		}
 
 		if (param == I8042_RET_CTL_TEST)
 			return 0;
 
-		printk(KERN_ERR "i8042.c: i8042 controller selftest failed. (%#x != %#x)\n",
-			param, I8042_RET_CTL_TEST);
+		pr_err("i8042 controller selftest failed. (%#x != %#x)\n",
+		       param, I8042_RET_CTL_TEST);
 		msleep(50);
 	} while (i++ < 5);
 
@@ -883,8 +888,7 @@ static int i8042_controller_selftest(voi
 	 * and user will still get a working keyboard. This is especially
 	 * important on netbooks. On other arches we trust hardware more.
 	 */
-	printk(KERN_INFO
-		"i8042: giving up on controller selftest, continuing anyway...\n");
+	pr_info("giving up on controller selftest, continuing anyway...\n");
 	return 0;
 #else
 	return -EIO;
@@ -909,8 +913,7 @@ static int i8042_controller_init(void)
 
 	do {
 		if (n >= 10) {
-			printk(KERN_ERR
-				"i8042.c: Unable to get stable CTR read.\n");
+			pr_err("Unable to get stable CTR read\n");
 			return -EIO;
 		}
 
@@ -918,8 +921,7 @@ static int i8042_controller_init(void)
 			udelay(50);
 
 		if (i8042_command(&ctr[n++ % 2], I8042_CMD_CTL_RCTR)) {
-			printk(KERN_ERR
-				"i8042.c: Can't read CTR while initializing i8042.\n");
+			pr_err("Can't read CTR while initializing i8042\n");
 			return -EIO;
 		}
 
@@ -943,7 +945,7 @@ static int i8042_controller_init(void)
 		if (i8042_unlock)
 			i8042_ctr |= I8042_CTR_IGNKEYLOCK;
 		else
-			printk(KERN_WARNING "i8042.c: Warning: Keylock active.\n");
+			pr_warn("Warning: Keylock active\n");
 	}
 	spin_unlock_irqrestore(&i8042_lock, flags);
 
@@ -970,7 +972,7 @@ static int i8042_controller_init(void)
  */
 
 	if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) {
-		printk(KERN_ERR "i8042.c: Can't write CTR while initializing i8042.\n");
+		pr_err("Can't write CTR while initializing i8042\n");
 		return -EIO;
 	}
 
@@ -1000,7 +1002,7 @@ static void i8042_controller_reset(void)
 	i8042_ctr &= ~(I8042_CTR_KBDINT | I8042_CTR_AUXINT);
 
 	if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR))
-		printk(KERN_WARNING "i8042.c: Can't write CTR while resetting.\n");
+		pr_warn("Can't write CTR while resetting\n");
 
 /*
  * Disable MUX mode if present.
@@ -1021,7 +1023,7 @@ static void i8042_controller_reset(void)
  */
 
 	if (i8042_command(&i8042_initial_ctr, I8042_CMD_CTL_WCTR))
-		printk(KERN_WARNING "i8042.c: Can't restore CTR.\n");
+		pr_warn("Can't restore CTR\n");
 }
 
 
@@ -1045,14 +1047,14 @@ static long i8042_panic_blink(int state)
 	led = (state) ? 0x01 | 0x04 : 0;
 	while (i8042_read_status() & I8042_STR_IBF)
 		DELAY;
-	dbg("%02x -> i8042 (panic blink)", 0xed);
+	dbg("%02x -> i8042 (panic blink)\n", 0xed);
 	i8042_suppress_kbd_ack = 2;
 	i8042_write_data(0xed); /* set leds */
 	DELAY;
 	while (i8042_read_status() & I8042_STR_IBF)
 		DELAY;
 	DELAY;
-	dbg("%02x -> i8042 (panic blink)", led);
+	dbg("%02x -> i8042 (panic blink)\n", led);
 	i8042_write_data(led);
 	DELAY;
 	return delay;
@@ -1068,9 +1070,7 @@ static void i8042_dritek_enable(void)
 
 	error = i8042_command(&param, 0x1059);
 	if (error)
-		printk(KERN_WARNING
-			"Failed to enable DRITEK extension: %d\n",
-			error);
+		pr_warn("Failed to enable DRITEK extension: %d\n", error);
 }
 #endif
 
@@ -1105,10 +1105,10 @@ static int i8042_controller_resume(bool
 	i8042_ctr |= I8042_CTR_AUXDIS | I8042_CTR_KBDDIS;
 	i8042_ctr &= ~(I8042_CTR_AUXINT | I8042_CTR_KBDINT);
 	if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) {
-		printk(KERN_WARNING "i8042: Can't write CTR to resume, retrying...\n");
+		pr_warn("Can't write CTR to resume, retrying...\n");
 		msleep(50);
 		if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) {
-			printk(KERN_ERR "i8042: CTR write retry failed\n");
+			pr_err("CTR write retry failed\n");
 			return -EIO;
 		}
 	}
@@ -1121,9 +1121,7 @@ static int i8042_controller_resume(bool
 
 	if (i8042_mux_present) {
 		if (i8042_set_mux_mode(true, NULL) || i8042_enable_mux_ports())
-			printk(KERN_WARNING
-				"i8042: failed to resume active multiplexor, "
-				"mouse won't work.\n");
+			pr_warn("failed to resume active multiplexor, mouse won't work\n");
 	} else if (i8042_ports[I8042_AUX_PORT_NO].serio)
 		i8042_enable_aux_port();
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/input/serio/i8042.h linux-libre-2.6.38-gnu1/drivers/input/serio/i8042.h
--- linux-libre-2.6.37-gnu1/drivers/input/serio/i8042.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/input/serio/i8042.h	2011-03-14 21:20:32.000000000 -0400
@@ -89,15 +89,19 @@
 #ifdef DEBUG
 static unsigned long i8042_start_time;
 #define dbg_init() do { i8042_start_time = jiffies; } while (0)
-#define dbg(format, arg...) 							\
-	do { 									\
+#define dbg(format, arg...)							\
+	do {									\
 		if (i8042_debug)						\
-			printk(KERN_DEBUG __FILE__ ": " format " [%d]\n" ,	\
-	 			## arg, (int) (jiffies - i8042_start_time));	\
+			printk(KERN_DEBUG KBUILD_MODNAME ": [%d] " format,	\
+			       (int) (jiffies - i8042_start_time), ##arg);	\
 	} while (0)
 #else
 #define dbg_init() do { } while (0)
-#define dbg(format, arg...) do {} while (0)
+#define dbg(format, arg...)							\
+	do {									\
+		if (0)								\
+			printk(KERN_DEBUG pr_fmt(format), ##arg);		\
+	} while (0)
 #endif
 
 #endif /* _I8042_H */
diff -druNp linux-libre-2.6.37-gnu1/drivers/input/serio/i8042-x86ia64io.h linux-libre-2.6.38-gnu1/drivers/input/serio/i8042-x86ia64io.h
--- linux-libre-2.6.37-gnu1/drivers/input/serio/i8042-x86ia64io.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/input/serio/i8042-x86ia64io.h	2011-03-14 21:20:32.000000000 -0400
@@ -424,6 +424,13 @@ static const struct dmi_system_id __init
 			DMI_MATCH(DMI_PRODUCT_VERSION, "0100"),
 		},
 	},
+	{
+		/* Dell Vostro V13 */
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Vostro V13"),
+		},
+	},
 	{ }
 };
 
@@ -545,6 +552,17 @@ static const struct dmi_system_id __init
 };
 #endif
 
+static const struct dmi_system_id __initconst i8042_dmi_notimeout_table[] = {
+	{
+		/* Dell Vostro V13 */
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Vostro V13"),
+		},
+	},
+	{ }
+};
+
 /*
  * Some Wistron based laptops need us to explicitly enable the 'Dritek
  * keyboard extension' to make their extra keys start generating scancodes.
@@ -553,6 +571,13 @@ static const struct dmi_system_id __init
  */
 static const struct dmi_system_id __initconst i8042_dmi_dritek_table[] = {
 	{
+		/* Acer Aspire 5100 */
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5100"),
+		},
+	},
+	{
 		/* Acer Aspire 5610 */
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
@@ -752,7 +777,7 @@ static int __init i8042_pnp_init(void)
 #endif
 
 	if (i8042_nopnp) {
-		printk(KERN_INFO "i8042: PNP detection disabled\n");
+		pr_info("PNP detection disabled\n");
 		return 0;
 	}
 
@@ -769,7 +794,7 @@ static int __init i8042_pnp_init(void)
 #if defined(__ia64__)
 		return -ENODEV;
 #else
-		printk(KERN_INFO "PNP: No PS/2 controller found. Probing ports directly.\n");
+		pr_info("PNP: No PS/2 controller found. Probing ports directly.\n");
 		return 0;
 #endif
 	}
@@ -781,7 +806,7 @@ static int __init i8042_pnp_init(void)
 		snprintf(aux_irq_str, sizeof(aux_irq_str),
 			"%d", i8042_pnp_aux_irq);
 
-	printk(KERN_INFO "PNP: PS/2 Controller [%s%s%s] at %#x,%#x irq %s%s%s\n",
+	pr_info("PNP: PS/2 Controller [%s%s%s] at %#x,%#x irq %s%s%s\n",
 		i8042_pnp_kbd_name, (i8042_pnp_kbd_devices && i8042_pnp_aux_devices) ? "," : "",
 		i8042_pnp_aux_name,
 		i8042_pnp_data_reg, i8042_pnp_command_reg,
@@ -798,9 +823,7 @@ static int __init i8042_pnp_init(void)
 	if (((i8042_pnp_data_reg & ~0xf) == (i8042_data_reg & ~0xf) &&
 	      i8042_pnp_data_reg != i8042_data_reg) ||
 	    !i8042_pnp_data_reg) {
-		printk(KERN_WARNING
-			"PNP: PS/2 controller has invalid data port %#x; "
-			"using default %#x\n",
+		pr_warn("PNP: PS/2 controller has invalid data port %#x; using default %#x\n",
 			i8042_pnp_data_reg, i8042_data_reg);
 		i8042_pnp_data_reg = i8042_data_reg;
 		pnp_data_busted = true;
@@ -809,33 +832,27 @@ static int __init i8042_pnp_init(void)
 	if (((i8042_pnp_command_reg & ~0xf) == (i8042_command_reg & ~0xf) &&
 	      i8042_pnp_command_reg != i8042_command_reg) ||
 	    !i8042_pnp_command_reg) {
-		printk(KERN_WARNING
-			"PNP: PS/2 controller has invalid command port %#x; "
-			"using default %#x\n",
+		pr_warn("PNP: PS/2 controller has invalid command port %#x; using default %#x\n",
 			i8042_pnp_command_reg, i8042_command_reg);
 		i8042_pnp_command_reg = i8042_command_reg;
 		pnp_data_busted = true;
 	}
 
 	if (!i8042_nokbd && !i8042_pnp_kbd_irq) {
-		printk(KERN_WARNING
-			"PNP: PS/2 controller doesn't have KBD irq; "
-			"using default %d\n", i8042_kbd_irq);
+		pr_warn("PNP: PS/2 controller doesn't have KBD irq; using default %d\n",
+			i8042_kbd_irq);
 		i8042_pnp_kbd_irq = i8042_kbd_irq;
 		pnp_data_busted = true;
 	}
 
 	if (!i8042_noaux && !i8042_pnp_aux_irq) {
 		if (!pnp_data_busted && i8042_pnp_kbd_irq) {
-			printk(KERN_WARNING
-				"PNP: PS/2 appears to have AUX port disabled, "
-				"if this is incorrect please boot with "
-				"i8042.nopnp\n");
+			pr_warn("PNP: PS/2 appears to have AUX port disabled, "
+				"if this is incorrect please boot with i8042.nopnp\n");
 			i8042_noaux = true;
 		} else {
-			printk(KERN_WARNING
-				"PNP: PS/2 controller doesn't have AUX irq; "
-				"using default %d\n", i8042_aux_irq);
+			pr_warn("PNP: PS/2 controller doesn't have AUX irq; using default %d\n",
+				i8042_aux_irq);
 			i8042_pnp_aux_irq = i8042_aux_irq;
 		}
 	}
@@ -897,6 +914,9 @@ static int __init i8042_platform_init(vo
 	if (dmi_check_system(i8042_dmi_nomux_table))
 		i8042_nomux = true;
 
+	if (dmi_check_system(i8042_dmi_notimeout_table))
+		i8042_notimeout = true;
+
 	if (dmi_check_system(i8042_dmi_dritek_table))
 		i8042_dritek = true;
 #endif /* CONFIG_X86 */
diff -druNp linux-libre-2.6.37-gnu1/drivers/input/serio/Kconfig linux-libre-2.6.38-gnu1/drivers/input/serio/Kconfig
--- linux-libre-2.6.37-gnu1/drivers/input/serio/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/input/serio/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -2,7 +2,7 @@
 # Input core configuration
 #
 config SERIO
-	tristate "Serial I/O support" if EMBEDDED || !X86
+	tristate "Serial I/O support" if EXPERT || !X86
 	default y
 	help
 	  Say Yes here if you have any input device that uses serial I/O to
@@ -19,7 +19,7 @@ config SERIO
 if SERIO
 
 config SERIO_I8042
-	tristate "i8042 PC Keyboard controller" if EMBEDDED || !X86
+	tristate "i8042 PC Keyboard controller" if EXPERT || !X86
 	default y
 	depends on !PARISC && (!ARM || ARCH_SHARK || FOOTBRIDGE_HOST) && \
 		   (!SUPERH || SH_CAYMAN) && !M68K && !BLACKFIN
@@ -168,7 +168,7 @@ config SERIO_MACEPS2
 	  module will be called maceps2.
 
 config SERIO_LIBPS2
-	tristate "PS/2 driver library" if EMBEDDED
+	tristate "PS/2 driver library" if EXPERT
 	depends on SERIO_I8042 || SERIO_I8042=n
 	help
 	  Say Y here if you are using a driver for device connected
@@ -214,7 +214,6 @@ config SERIO_AMS_DELTA
 	tristate "Amstrad Delta (E3) mailboard support"
 	depends on MACH_AMS_DELTA
 	default y
-	select AMS_DELTA_FIQ
 	---help---
 	  Say Y here if you have an E3 and want to use its mailboard,
 	  or any standard AT keyboard connected to the mailboard port.
@@ -230,7 +229,7 @@ config SERIO_PS2MULT
 	tristate "TQC PS/2 multiplexer"
 	help
 	  Say Y here if you have the PS/2 line multiplexer like the one
-	  present on TQC boads.
+	  present on TQC boards.
 
 	  To compile this driver as a module, choose M here: the
 	  module will be called ps2mult.
diff -druNp linux-libre-2.6.37-gnu1/drivers/input/serio/ps2mult.c linux-libre-2.6.38-gnu1/drivers/input/serio/ps2mult.c
--- linux-libre-2.6.37-gnu1/drivers/input/serio/ps2mult.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/input/serio/ps2mult.c	2011-03-14 21:20:32.000000000 -0400
@@ -207,7 +207,7 @@ static int ps2mult_connect(struct serio
 err_out:
 	while (--i >= 0)
 		kfree(psm->ports[i].serio);
-	kfree(serio);
+	kfree(psm);
 	return error;
 }
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/input/serio/serio.c linux-libre-2.6.38-gnu1/drivers/input/serio/serio.c
--- linux-libre-2.6.37-gnu1/drivers/input/serio/serio.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/input/serio/serio.c	2011-03-14 21:20:32.000000000 -0400
@@ -32,10 +32,9 @@
 #include <linux/module.h>
 #include <linux/serio.h>
 #include <linux/errno.h>
-#include <linux/wait.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
-#include <linux/kthread.h>
+#include <linux/workqueue.h>
 #include <linux/mutex.h>
 
 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
@@ -44,7 +43,7 @@ MODULE_LICENSE("GPL");
 
 /*
  * serio_mutex protects entire serio subsystem and is taken every time
- * serio port or driver registrered or unregistered.
+ * serio port or driver registered or unregistered.
  */
 static DEFINE_MUTEX(serio_mutex);
 
@@ -165,58 +164,22 @@ struct serio_event {
 
 static DEFINE_SPINLOCK(serio_event_lock);	/* protects serio_event_list */
 static LIST_HEAD(serio_event_list);
-static DECLARE_WAIT_QUEUE_HEAD(serio_wait);
-static struct task_struct *serio_task;
 
-static int serio_queue_event(void *object, struct module *owner,
-			     enum serio_event_type event_type)
+static struct serio_event *serio_get_event(void)
 {
+	struct serio_event *event = NULL;
 	unsigned long flags;
-	struct serio_event *event;
-	int retval = 0;
 
 	spin_lock_irqsave(&serio_event_lock, flags);
 
-	/*
-	 * Scan event list for the other events for the same serio port,
-	 * starting with the most recent one. If event is the same we
-	 * do not need add new one. If event is of different type we
-	 * need to add this event and should not look further because
-	 * we need to preseve sequence of distinct events.
-	 */
-	list_for_each_entry_reverse(event, &serio_event_list, node) {
-		if (event->object == object) {
-			if (event->type == event_type)
-				goto out;
-			break;
-		}
-	}
-
-	event = kmalloc(sizeof(struct serio_event), GFP_ATOMIC);
-	if (!event) {
-		pr_err("Not enough memory to queue event %d\n", event_type);
-		retval = -ENOMEM;
-		goto out;
-	}
-
-	if (!try_module_get(owner)) {
-		pr_warning("Can't get module reference, dropping event %d\n",
-			   event_type);
-		kfree(event);
-		retval = -EINVAL;
-		goto out;
+	if (!list_empty(&serio_event_list)) {
+		event = list_first_entry(&serio_event_list,
+					 struct serio_event, node);
+		list_del_init(&event->node);
 	}
 
-	event->type = event_type;
-	event->object = object;
-	event->owner = owner;
-
-	list_add_tail(&event->node, &serio_event_list);
-	wake_up(&serio_wait);
-
-out:
 	spin_unlock_irqrestore(&serio_event_lock, flags);
-	return retval;
+	return event;
 }
 
 static void serio_free_event(struct serio_event *event)
@@ -225,7 +188,8 @@ static void serio_free_event(struct seri
 	kfree(event);
 }
 
-static void serio_remove_duplicate_events(struct serio_event *event)
+static void serio_remove_duplicate_events(void *object,
+					  enum serio_event_type type)
 {
 	struct serio_event *e, *next;
 	unsigned long flags;
@@ -233,13 +197,13 @@ static void serio_remove_duplicate_event
 	spin_lock_irqsave(&serio_event_lock, flags);
 
 	list_for_each_entry_safe(e, next, &serio_event_list, node) {
-		if (event->object == e->object) {
+		if (object == e->object) {
 			/*
 			 * If this event is of different type we should not
 			 * look further - we only suppress duplicate events
 			 * that were sent back-to-back.
 			 */
-			if (event->type != e->type)
+			if (type != e->type)
 				break;
 
 			list_del_init(&e->node);
@@ -250,25 +214,7 @@ static void serio_remove_duplicate_event
 	spin_unlock_irqrestore(&serio_event_lock, flags);
 }
 
-
-static struct serio_event *serio_get_event(void)
-{
-	struct serio_event *event = NULL;
-	unsigned long flags;
-
-	spin_lock_irqsave(&serio_event_lock, flags);
-
-	if (!list_empty(&serio_event_list)) {
-		event = list_first_entry(&serio_event_list,
-					 struct serio_event, node);
-		list_del_init(&event->node);
-	}
-
-	spin_unlock_irqrestore(&serio_event_lock, flags);
-	return event;
-}
-
-static void serio_handle_event(void)
+static void serio_handle_event(struct work_struct *work)
 {
 	struct serio_event *event;
 
@@ -300,13 +246,66 @@ static void serio_handle_event(void)
 			break;
 		}
 
-		serio_remove_duplicate_events(event);
+		serio_remove_duplicate_events(event->object, event->type);
 		serio_free_event(event);
 	}
 
 	mutex_unlock(&serio_mutex);
 }
 
+static DECLARE_WORK(serio_event_work, serio_handle_event);
+
+static int serio_queue_event(void *object, struct module *owner,
+			     enum serio_event_type event_type)
+{
+	unsigned long flags;
+	struct serio_event *event;
+	int retval = 0;
+
+	spin_lock_irqsave(&serio_event_lock, flags);
+
+	/*
+	 * Scan event list for the other events for the same serio port,
+	 * starting with the most recent one. If event is the same we
+	 * do not need add new one. If event is of different type we
+	 * need to add this event and should not look further because
+	 * we need to preseve sequence of distinct events.
+	 */
+	list_for_each_entry_reverse(event, &serio_event_list, node) {
+		if (event->object == object) {
+			if (event->type == event_type)
+				goto out;
+			break;
+		}
+	}
+
+	event = kmalloc(sizeof(struct serio_event), GFP_ATOMIC);
+	if (!event) {
+		pr_err("Not enough memory to queue event %d\n", event_type);
+		retval = -ENOMEM;
+		goto out;
+	}
+
+	if (!try_module_get(owner)) {
+		pr_warning("Can't get module reference, dropping event %d\n",
+			   event_type);
+		kfree(event);
+		retval = -EINVAL;
+		goto out;
+	}
+
+	event->type = event_type;
+	event->object = object;
+	event->owner = owner;
+
+	list_add_tail(&event->node, &serio_event_list);
+	queue_work(system_long_wq, &serio_event_work);
+
+out:
+	spin_unlock_irqrestore(&serio_event_lock, flags);
+	return retval;
+}
+
 /*
  * Remove all events that have been submitted for a given
  * object, be it serio port or driver.
@@ -356,18 +355,6 @@ static struct serio *serio_get_pending_c
 	return child;
 }
 
-static int serio_thread(void *nothing)
-{
-	do {
-		serio_handle_event();
-		wait_event_interruptible(serio_wait,
-			kthread_should_stop() || !list_empty(&serio_event_list));
-	} while (!kthread_should_stop());
-
-	return 0;
-}
-
-
 /*
  * Serio port operations
  */
@@ -450,10 +437,12 @@ static ssize_t serio_rebind_driver(struc
 	} else if (!strncmp(buf, "rescan", count)) {
 		serio_disconnect_port(serio);
 		serio_find_driver(serio);
+		serio_remove_duplicate_events(serio, SERIO_RESCAN_PORT);
 	} else if ((drv = driver_find(buf, &serio_bus)) != NULL) {
 		serio_disconnect_port(serio);
 		error = serio_bind_driver(serio, to_serio_driver(drv));
 		put_driver(drv);
+		serio_remove_duplicate_events(serio, SERIO_RESCAN_PORT);
 	} else {
 		error = -EINVAL;
 	}
@@ -1040,21 +1029,18 @@ static int __init serio_init(void)
 		return error;
 	}
 
-	serio_task = kthread_run(serio_thread, NULL, "kseriod");
-	if (IS_ERR(serio_task)) {
-		bus_unregister(&serio_bus);
-		error = PTR_ERR(serio_task);
-		pr_err("Failed to start kseriod, error: %d\n", error);
-		return error;
-	}
-
 	return 0;
 }
 
 static void __exit serio_exit(void)
 {
 	bus_unregister(&serio_bus);
-	kthread_stop(serio_task);
+
+	/*
+	 * There should not be any outstanding events but work may
+	 * still be scheduled so simply cancel it.
+	 */
+	cancel_work_sync(&serio_event_work);
 }
 
 subsys_initcall(serio_init);
diff -druNp linux-libre-2.6.37-gnu1/drivers/input/serio/serport.c linux-libre-2.6.38-gnu1/drivers/input/serio/serport.c
--- linux-libre-2.6.37-gnu1/drivers/input/serio/serport.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/input/serio/serport.c	2011-03-14 21:20:32.000000000 -0400
@@ -116,14 +116,15 @@ static void serport_ldisc_close(struct t
 
 /*
  * serport_ldisc_receive() is called by the low level tty driver when characters
- * are ready for us. We forward the characters, one by one to the 'interrupt'
- * routine.
+ * are ready for us. We forward the characters and flags, one by one to the
+ * 'interrupt' routine.
  */
 
 static void serport_ldisc_receive(struct tty_struct *tty, const unsigned char *cp, char *fp, int count)
 {
 	struct serport *serport = (struct serport*) tty->disc_data;
 	unsigned long flags;
+	unsigned int ch_flags;
 	int i;
 
 	spin_lock_irqsave(&serport->lock, flags);
@@ -131,8 +132,23 @@ static void serport_ldisc_receive(struct
 	if (!test_bit(SERPORT_ACTIVE, &serport->flags))
 		goto out;
 
-	for (i = 0; i < count; i++)
-		serio_interrupt(serport->serio, cp[i], 0);
+	for (i = 0; i < count; i++) {
+		switch (fp[i]) {
+		case TTY_FRAME:
+			ch_flags = SERIO_FRAME;
+			break;
+
+		case TTY_PARITY:
+			ch_flags = SERIO_PARITY;
+			break;
+
+		default:
+			ch_flags = 0;
+			break;
+		}
+
+		serio_interrupt(serport->serio, cp[i], ch_flags);
+	}
 
 out:
 	spin_unlock_irqrestore(&serport->lock, flags);
diff -druNp linux-libre-2.6.37-gnu1/drivers/input/sparse-keymap.c linux-libre-2.6.38-gnu1/drivers/input/sparse-keymap.c
--- linux-libre-2.6.37-gnu1/drivers/input/sparse-keymap.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/input/sparse-keymap.c	2011-03-14 21:20:32.000000000 -0400
@@ -201,6 +201,7 @@ int sparse_keymap_setup(struct input_dev
 			break;
 
 		case KE_SW:
+		case KE_VSW:
 			__set_bit(EV_SW, dev->evbit);
 			__set_bit(entry->sw.code, dev->swbit);
 			break;
diff -druNp linux-libre-2.6.37-gnu1/drivers/input/tablet/wacom.h linux-libre-2.6.38-gnu1/drivers/input/tablet/wacom.h
--- linux-libre-2.6.37-gnu1/drivers/input/tablet/wacom.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/input/tablet/wacom.h	2011-03-14 21:20:32.000000000 -0400
@@ -103,6 +103,7 @@ MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE(DRIVER_LICENSE);
 
 #define USB_VENDOR_ID_WACOM	0x056a
+#define USB_VENDOR_ID_LENOVO	0x17ef
 
 struct wacom {
 	dma_addr_t data_dma;
diff -druNp linux-libre-2.6.37-gnu1/drivers/input/tablet/wacom_sys.c linux-libre-2.6.38-gnu1/drivers/input/tablet/wacom_sys.c
--- linux-libre-2.6.37-gnu1/drivers/input/tablet/wacom_sys.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/input/tablet/wacom_sys.c	2011-03-14 21:20:32.000000000 -0400
@@ -519,7 +519,7 @@ static int wacom_probe(struct usb_interf
 	/* Retrieve the physical and logical size for OEM devices */
 	error = wacom_retrieve_hid_descriptor(intf, features);
 	if (error)
-		goto fail2;
+		goto fail3;
 
 	wacom_setup_device_quirks(features);
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/input/tablet/wacom_wac.c linux-libre-2.6.38-gnu1/drivers/input/tablet/wacom_wac.c
--- linux-libre-2.6.37-gnu1/drivers/input/tablet/wacom_wac.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/input/tablet/wacom_wac.c	2011-03-14 21:20:32.000000000 -0400
@@ -14,6 +14,7 @@
 
 #include "wacom_wac.h"
 #include "wacom.h"
+#include <linux/input/mt.h>
 
 static int wacom_penpartner_irq(struct wacom_wac *wacom)
 {
@@ -862,19 +863,21 @@ static int wacom_bpt_touch(struct wacom_
 	struct wacom_features *features = &wacom->features;
 	struct input_dev *input = wacom->input;
 	unsigned char *data = wacom->data;
-	int sp = 0, sx = 0, sy = 0, count = 0;
 	int i;
 
 	for (i = 0; i < 2; i++) {
 		int p = data[9 * i + 2];
+		bool touch = p && !wacom->shared->stylus_in_proximity;
+
 		input_mt_slot(input, i);
+		input_mt_report_slot_state(input, MT_TOOL_FINGER, touch);
 		/*
 		 * Touch events need to be disabled while stylus is
 		 * in proximity because user's hand is resting on touchpad
 		 * and sending unwanted events.  User expects tablet buttons
 		 * to continue working though.
 		 */
-		if (p && !wacom->shared->stylus_in_proximity) {
+		if (touch) {
 			int x = get_unaligned_be16(&data[9 * i + 3]) & 0x7ff;
 			int y = get_unaligned_be16(&data[9 * i + 5]) & 0x7ff;
 			if (features->quirks & WACOM_QUIRK_BBTOUCH_LOWRES) {
@@ -884,23 +887,10 @@ static int wacom_bpt_touch(struct wacom_
 			input_report_abs(input, ABS_MT_PRESSURE, p);
 			input_report_abs(input, ABS_MT_POSITION_X, x);
 			input_report_abs(input, ABS_MT_POSITION_Y, y);
-			if (wacom->id[i] < 0)
-				wacom->id[i] = wacom->trk_id++ & MAX_TRACKING_ID;
-			if (!count++)
-				sp = p, sx = x, sy = y;
-		} else {
-			wacom->id[i] = -1;
 		}
-		input_report_abs(input, ABS_MT_TRACKING_ID, wacom->id[i]);
 	}
 
-	input_report_key(input, BTN_TOUCH, count > 0);
-	input_report_key(input, BTN_TOOL_FINGER, count == 1);
-	input_report_key(input, BTN_TOOL_DOUBLETAP, count == 2);
-
-	input_report_abs(input, ABS_PRESSURE, sp);
-	input_report_abs(input, ABS_X, sx);
-	input_report_abs(input, ABS_Y, sy);
+	input_mt_report_pointer_emulation(input, true);
 
 	input_report_key(input, BTN_LEFT, (data[1] & 0x08) != 0);
 	input_report_key(input, BTN_FORWARD, (data[1] & 0x04) != 0);
@@ -1111,6 +1101,13 @@ void wacom_setup_device_quirks(struct wa
 	}
 }
 
+static unsigned int wacom_calculate_touch_res(unsigned int logical_max,
+					      unsigned int physical_max)
+{
+       /* Touch physical dimensions are in 100th of mm */
+       return (logical_max * 100) / physical_max;
+}
+
 void wacom_setup_input_capabilities(struct input_dev *input_dev,
 				    struct wacom_wac *wacom_wac)
 {
@@ -1238,8 +1235,12 @@ void wacom_setup_input_capabilities(stru
 	case TABLETPC:
 		if (features->device_type == BTN_TOOL_DOUBLETAP ||
 		    features->device_type == BTN_TOOL_TRIPLETAP) {
-			input_set_abs_params(input_dev, ABS_RX, 0, features->x_phy, 0, 0);
-			input_set_abs_params(input_dev, ABS_RY, 0, features->y_phy, 0, 0);
+			input_abs_set_res(input_dev, ABS_X,
+				wacom_calculate_touch_res(features->x_max,
+							features->x_phy));
+			input_abs_set_res(input_dev, ABS_Y,
+				wacom_calculate_touch_res(features->y_max,
+							features->y_phy));
 			__set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit);
 		}
 
@@ -1272,7 +1273,7 @@ void wacom_setup_input_capabilities(stru
 			__set_bit(BTN_TOOL_FINGER, input_dev->keybit);
 			__set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit);
 
-			input_mt_create_slots(input_dev, 2);
+			input_mt_init_slots(input_dev, 2);
 			input_set_abs_params(input_dev, ABS_MT_POSITION_X,
 					     0, features->x_max,
 					     features->x_fuzz, 0);
@@ -1282,8 +1283,12 @@ void wacom_setup_input_capabilities(stru
 			input_set_abs_params(input_dev, ABS_MT_PRESSURE,
 					     0, features->pressure_max,
 					     features->pressure_fuzz, 0);
-			input_set_abs_params(input_dev, ABS_MT_TRACKING_ID, 0,
-					     MAX_TRACKING_ID, 0, 0);
+			input_abs_set_res(input_dev, ABS_X,
+				wacom_calculate_touch_res(features->x_max,
+							features->x_phy));
+			input_abs_set_res(input_dev, ABS_Y,
+				wacom_calculate_touch_res(features->y_max,
+							features->y_phy));
 		} else if (features->device_type == BTN_TOOL_PEN) {
 			__set_bit(BTN_TOOL_RUBBER, input_dev->keybit);
 			__set_bit(BTN_TOOL_PEN, input_dev->keybit);
@@ -1438,17 +1443,27 @@ static struct wacom_features wacom_featu
 	{ "Wacom Bamboo 2FG 6x8", WACOM_PKGLEN_BBFUN,     21648, 13530, 1023, 63, BAMBOO_PT };
 static const struct wacom_features wacom_features_0xD4 =
 	{ "Wacom Bamboo Pen",     WACOM_PKGLEN_BBFUN,     14720,  9200,  255, 63, BAMBOO_PT };
+static struct wacom_features wacom_features_0xD6 =
+	{ "Wacom BambooPT 2FG 4x5", WACOM_PKGLEN_BBFUN,   14720,  9200, 1023, 63, BAMBOO_PT };
+static struct wacom_features wacom_features_0xD7 =
+	{ "Wacom BambooPT 2FG Small", WACOM_PKGLEN_BBFUN, 14720,  9200, 1023, 63, BAMBOO_PT };
 static struct wacom_features wacom_features_0xD8 =
 	{ "Wacom Bamboo Comic 2FG", WACOM_PKGLEN_BBFUN,   21648, 13530, 1023, 63, BAMBOO_PT };
 static struct wacom_features wacom_features_0xDA =
 	{ "Wacom Bamboo 2FG 4x5 SE", WACOM_PKGLEN_BBFUN,  14720,  9200, 1023, 63, BAMBOO_PT };
 static struct wacom_features wacom_features_0xDB =
 	{ "Wacom Bamboo 2FG 6x8 SE", WACOM_PKGLEN_BBFUN,  21648, 13530, 1023, 63, BAMBOO_PT };
+static const struct wacom_features wacom_features_0x6004 =
+	{ "ISD-V4",               WACOM_PKGLEN_GRAPHIRE,  12800, 8000, 255, 0, TABLETPC };
 
 #define USB_DEVICE_WACOM(prod)					\
 	USB_DEVICE(USB_VENDOR_ID_WACOM, prod),			\
 	.driver_info = (kernel_ulong_t)&wacom_features_##prod
 
+#define USB_DEVICE_LENOVO(prod)					\
+	USB_DEVICE(USB_VENDOR_ID_LENOVO, prod),			\
+	.driver_info = (kernel_ulong_t)&wacom_features_##prod
+
 const struct usb_device_id wacom_ids[] = {
 	{ USB_DEVICE_WACOM(0x00) },
 	{ USB_DEVICE_WACOM(0x10) },
@@ -1513,6 +1528,8 @@ const struct usb_device_id wacom_ids[] =
 	{ USB_DEVICE_WACOM(0xD2) },
 	{ USB_DEVICE_WACOM(0xD3) },
 	{ USB_DEVICE_WACOM(0xD4) },
+	{ USB_DEVICE_WACOM(0xD6) },
+	{ USB_DEVICE_WACOM(0xD7) },
 	{ USB_DEVICE_WACOM(0xD8) },
 	{ USB_DEVICE_WACOM(0xDA) },
 	{ USB_DEVICE_WACOM(0xDB) },
@@ -1525,6 +1542,7 @@ const struct usb_device_id wacom_ids[] =
 	{ USB_DEVICE_WACOM(0xE2) },
 	{ USB_DEVICE_WACOM(0xE3) },
 	{ USB_DEVICE_WACOM(0x47) },
+	{ USB_DEVICE_LENOVO(0x6004) },
 	{ }
 };
 MODULE_DEVICE_TABLE(usb, wacom_ids);
diff -druNp linux-libre-2.6.37-gnu1/drivers/input/tablet/wacom_wac.h linux-libre-2.6.38-gnu1/drivers/input/tablet/wacom_wac.h
--- linux-libre-2.6.37-gnu1/drivers/input/tablet/wacom_wac.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/input/tablet/wacom_wac.h	2011-03-14 21:20:32.000000000 -0400
@@ -42,9 +42,6 @@
 #define WACOM_QUIRK_MULTI_INPUT		0x0001
 #define WACOM_QUIRK_BBTOUCH_LOWRES	0x0002
 
-/* largest reported tracking id */
-#define MAX_TRACKING_ID			0xfff
-
 enum {
 	PENPARTNER = 0,
 	GRAPHIRE,
@@ -100,7 +97,6 @@ struct wacom_wac {
 	int id[3];
 	__u32 serial[2];
 	int last_finger;
-	int trk_id;
 	struct wacom_features features;
 	struct wacom_shared *shared;
 	struct input_dev *input;
diff -druNp linux-libre-2.6.37-gnu1/drivers/input/touchscreen/ad7879-i2c.c linux-libre-2.6.38-gnu1/drivers/input/touchscreen/ad7879-i2c.c
--- linux-libre-2.6.37-gnu1/drivers/input/touchscreen/ad7879-i2c.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/input/touchscreen/ad7879-i2c.c	2011-03-14 21:20:32.000000000 -0400
@@ -10,14 +10,16 @@
 #include <linux/i2c.h>
 #include <linux/module.h>
 #include <linux/types.h>
+#include <linux/pm.h>
 
 #include "ad7879.h"
 
 #define AD7879_DEVID		0x79	/* AD7879-1/AD7889-1 */
 
 #ifdef CONFIG_PM
-static int ad7879_i2c_suspend(struct i2c_client *client, pm_message_t message)
+static int ad7879_i2c_suspend(struct device *dev)
 {
+	struct i2c_client *client = to_i2c_client(dev);
 	struct ad7879 *ts = i2c_get_clientdata(client);
 
 	ad7879_suspend(ts);
@@ -25,17 +27,17 @@ static int ad7879_i2c_suspend(struct i2c
 	return 0;
 }
 
-static int ad7879_i2c_resume(struct i2c_client *client)
+static int ad7879_i2c_resume(struct device *dev)
 {
+	struct i2c_client *client = to_i2c_client(dev);
 	struct ad7879 *ts = i2c_get_clientdata(client);
 
 	ad7879_resume(ts);
 
 	return 0;
 }
-#else
-# define ad7879_i2c_suspend NULL
-# define ad7879_i2c_resume  NULL
+
+static SIMPLE_DEV_PM_OPS(ad7879_i2c_pm, ad7879_i2c_suspend, ad7879_i2c_resume);
 #endif
 
 /* All registers are word-sized.
@@ -117,11 +119,12 @@ 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),
-	.suspend	= ad7879_i2c_suspend,
-	.resume		= ad7879_i2c_resume,
 	.id_table	= ad7879_id,
 };
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/input/touchscreen/ads7846.c linux-libre-2.6.38-gnu1/drivers/input/touchscreen/ads7846.c
--- linux-libre-2.6.37-gnu1/drivers/input/touchscreen/ads7846.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/input/touchscreen/ads7846.c	2011-03-14 21:20:32.000000000 -0400
@@ -941,28 +941,29 @@ static int __devinit ads7846_setup_pendo
 	struct ads7846_platform_data *pdata = spi->dev.platform_data;
 	int err;
 
-	/* REVISIT when the irq can be triggered active-low, or if for some
+	/*
+	 * REVISIT when the irq can be triggered active-low, or if for some
 	 * reason the touchscreen isn't hooked up, we don't need to access
 	 * the pendown state.
 	 */
-	if (!pdata->get_pendown_state && !gpio_is_valid(pdata->gpio_pendown)) {
-		dev_err(&spi->dev, "no get_pendown_state nor gpio_pendown?\n");
-		return -EINVAL;
-	}
 
 	if (pdata->get_pendown_state) {
 		ts->get_pendown_state = pdata->get_pendown_state;
-		return 0;
-	}
+	} else if (gpio_is_valid(pdata->gpio_pendown)) {
 
-	err = gpio_request(pdata->gpio_pendown, "ads7846_pendown");
-	if (err) {
-		dev_err(&spi->dev, "failed to request pendown GPIO%d\n",
-			pdata->gpio_pendown);
-		return err;
-	}
+		err = gpio_request(pdata->gpio_pendown, "ads7846_pendown");
+		if (err) {
+			dev_err(&spi->dev, "failed to request pendown GPIO%d\n",
+				pdata->gpio_pendown);
+			return err;
+		}
 
-	ts->gpio_pendown = pdata->gpio_pendown;
+		ts->gpio_pendown = pdata->gpio_pendown;
+
+	} else {
+		dev_err(&spi->dev, "no get_pendown_state nor gpio_pendown?\n");
+		return -EINVAL;
+	}
 
 	return 0;
 }
@@ -1353,7 +1354,7 @@ static int __devinit ads7846_probe(struc
  err_put_regulator:
 	regulator_put(ts->reg);
  err_free_gpio:
-	if (ts->gpio_pendown != -1)
+	if (!ts->get_pendown_state)
 		gpio_free(ts->gpio_pendown);
  err_cleanup_filter:
 	if (ts->filter_cleanup)
@@ -1383,8 +1384,13 @@ static int __devexit ads7846_remove(stru
 	regulator_disable(ts->reg);
 	regulator_put(ts->reg);
 
-	if (ts->gpio_pendown != -1)
+	if (!ts->get_pendown_state) {
+		/*
+		 * If we are not using specialized pendown method we must
+		 * have been relying on gpio we set up ourselves.
+		 */
 		gpio_free(ts->gpio_pendown);
+	}
 
 	if (ts->filter_cleanup)
 		ts->filter_cleanup(ts->filter_data);
diff -druNp linux-libre-2.6.37-gnu1/drivers/input/touchscreen/bu21013_ts.c linux-libre-2.6.38-gnu1/drivers/input/touchscreen/bu21013_ts.c
--- linux-libre-2.6.37-gnu1/drivers/input/touchscreen/bu21013_ts.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/input/touchscreen/bu21013_ts.c	2011-03-14 21:20:32.000000000 -0400
@@ -12,6 +12,7 @@
 #include <linux/input.h>
 #include <linux/input/bu21013.h>
 #include <linux/slab.h>
+#include <linux/regulator/consumer.h>
 
 #define PEN_DOWN_INTR	0
 #define MAX_FINGERS	2
@@ -139,6 +140,7 @@
  * @chip: pointer to the touch panel controller
  * @in_dev: pointer to the input device structure
  * @intr_pin: interrupt pin value
+ * @regulator: pointer to the Regulator used for touch screen
  *
  * Touch panel device data structure
  */
@@ -149,6 +151,7 @@ struct bu21013_ts_data {
 	const struct bu21013_platform_device *chip;
 	struct input_dev *in_dev;
 	unsigned int intr_pin;
+	struct regulator *regulator;
 };
 
 /**
@@ -365,7 +368,7 @@ static int bu21013_init_chip(struct bu21
 	}
 
 	retval = i2c_smbus_write_byte_data(i2c, BU21013_TH_OFF_REG,
-				BU21013_TH_OFF_4 || BU21013_TH_OFF_3);
+				BU21013_TH_OFF_4 | BU21013_TH_OFF_3);
 	if (retval < 0) {
 		dev_err(&i2c->dev, "BU21013_TH_OFF reg write failed\n");
 		return retval;
@@ -456,6 +459,20 @@ static int __devinit bu21013_probe(struc
 	bu21013_data->in_dev = in_dev;
 	bu21013_data->chip = pdata;
 	bu21013_data->client = client;
+
+	bu21013_data->regulator = regulator_get(&client->dev, "V-TOUCH");
+	if (IS_ERR(bu21013_data->regulator)) {
+		dev_err(&client->dev, "regulator_get failed\n");
+		error = PTR_ERR(bu21013_data->regulator);
+		goto err_free_mem;
+	}
+
+	error = regulator_enable(bu21013_data->regulator);
+	if (error < 0) {
+		dev_err(&client->dev, "regulator enable failed\n");
+		goto err_put_regulator;
+	}
+
 	bu21013_data->touch_stopped = false;
 	init_waitqueue_head(&bu21013_data->wait);
 
@@ -464,7 +481,7 @@ static int __devinit bu21013_probe(struc
 		error = pdata->cs_en(pdata->cs_pin);
 		if (error < 0) {
 			dev_err(&client->dev, "chip init failed\n");
-			goto err_free_mem;
+			goto err_disable_regulator;
 		}
 	}
 
@@ -485,9 +502,9 @@ static int __devinit bu21013_probe(struc
 	__set_bit(EV_ABS, in_dev->evbit);
 
 	input_set_abs_params(in_dev, ABS_MT_POSITION_X, 0,
-						pdata->x_max_res, 0, 0);
+						pdata->touch_x_max, 0, 0);
 	input_set_abs_params(in_dev, ABS_MT_POSITION_Y, 0,
-						pdata->y_max_res, 0, 0);
+						pdata->touch_y_max, 0, 0);
 	input_set_drvdata(in_dev, bu21013_data);
 
 	error = request_threaded_irq(pdata->irq, NULL, bu21013_gpio_irq,
@@ -513,6 +530,10 @@ err_free_irq:
 	bu21013_free_irq(bu21013_data);
 err_cs_disable:
 	pdata->cs_dis(pdata->cs_pin);
+err_disable_regulator:
+	regulator_disable(bu21013_data->regulator);
+err_put_regulator:
+	regulator_put(bu21013_data->regulator);
 err_free_mem:
 	input_free_device(in_dev);
 	kfree(bu21013_data);
@@ -535,6 +556,10 @@ static int __devexit bu21013_remove(stru
 	bu21013_data->chip->cs_dis(bu21013_data->chip->cs_pin);
 
 	input_unregister_device(bu21013_data->in_dev);
+
+	regulator_disable(bu21013_data->regulator);
+	regulator_put(bu21013_data->regulator);
+
 	kfree(bu21013_data);
 
 	device_init_wakeup(&client->dev, false);
@@ -561,6 +586,8 @@ static int bu21013_suspend(struct device
 	else
 		disable_irq(bu21013_data->chip->irq);
 
+	regulator_disable(bu21013_data->regulator);
+
 	return 0;
 }
 
@@ -577,6 +604,12 @@ static int bu21013_resume(struct device
 	struct i2c_client *client = bu21013_data->client;
 	int retval;
 
+	retval = regulator_enable(bu21013_data->regulator);
+	if (retval < 0) {
+		dev_err(&client->dev, "bu21013 regulator enable failed\n");
+		return retval;
+	}
+
 	retval = bu21013_init_chip(bu21013_data);
 	if (retval < 0) {
 		dev_err(&client->dev, "bu21013 controller config failed\n");
diff -druNp linux-libre-2.6.37-gnu1/drivers/input/touchscreen/cy8ctmg110_ts.c linux-libre-2.6.38-gnu1/drivers/input/touchscreen/cy8ctmg110_ts.c
--- linux-libre-2.6.37-gnu1/drivers/input/touchscreen/cy8ctmg110_ts.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/input/touchscreen/cy8ctmg110_ts.c	2011-03-14 21:20:32.000000000 -0400
@@ -280,8 +280,9 @@ err_free_mem:
 }
 
 #ifdef CONFIG_PM
-static int cy8ctmg110_suspend(struct i2c_client *client, pm_message_t mesg)
+static int cy8ctmg110_suspend(struct device *dev)
 {
+	struct i2c_client *client = to_i2c_client(dev);
 	struct cy8ctmg110 *ts = i2c_get_clientdata(client);
 
 	if (device_may_wakeup(&client->dev))
@@ -293,8 +294,9 @@ static int cy8ctmg110_suspend(struct i2c
 	return 0;
 }
 
-static int cy8ctmg110_resume(struct i2c_client *client)
+static int cy8ctmg110_resume(struct device *dev)
 {
+	struct i2c_client *client = to_i2c_client(dev);
 	struct cy8ctmg110 *ts = i2c_get_clientdata(client);
 
 	if (device_may_wakeup(&client->dev))
@@ -305,6 +307,8 @@ static int cy8ctmg110_resume(struct i2c_
 	}
 	return 0;
 }
+
+static SIMPLE_DEV_PM_OPS(cy8ctmg110_pm, cy8ctmg110_suspend, cy8ctmg110_resume);
 #endif
 
 static int __devexit cy8ctmg110_remove(struct i2c_client *client)
@@ -335,14 +339,13 @@ static struct i2c_driver cy8ctmg110_driv
 	.driver		= {
 		.owner	= THIS_MODULE,
 		.name	= CY8CTMG110_DRIVER_NAME,
+#ifdef CONFIG_PM
+		.pm	= &cy8ctmg110_pm,
+#endif
 	},
 	.id_table	= cy8ctmg110_idtable,
 	.probe		= cy8ctmg110_probe,
 	.remove		= __devexit_p(cy8ctmg110_remove),
-#ifdef CONFIG_PM
-	.suspend	= cy8ctmg110_suspend,
-	.resume		= cy8ctmg110_resume,
-#endif
 };
 
 static int __init cy8ctmg110_init(void)
diff -druNp linux-libre-2.6.37-gnu1/drivers/input/touchscreen/eeti_ts.c linux-libre-2.6.38-gnu1/drivers/input/touchscreen/eeti_ts.c
--- linux-libre-2.6.37-gnu1/drivers/input/touchscreen/eeti_ts.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/input/touchscreen/eeti_ts.c	2011-03-14 21:20:32.000000000 -0400
@@ -261,8 +261,9 @@ static int __devexit eeti_ts_remove(stru
 }
 
 #ifdef CONFIG_PM
-static int eeti_ts_suspend(struct i2c_client *client, pm_message_t mesg)
+static int eeti_ts_suspend(struct device *dev)
 {
+	struct i2c_client *client = to_i2c_client(dev);
 	struct eeti_ts_priv *priv = i2c_get_clientdata(client);
 	struct input_dev *input_dev = priv->input;
 
@@ -279,8 +280,9 @@ static int eeti_ts_suspend(struct i2c_cl
 	return 0;
 }
 
-static int eeti_ts_resume(struct i2c_client *client)
+static int eeti_ts_resume(struct device *dev)
 {
+	struct i2c_client *client = to_i2c_client(dev);
 	struct eeti_ts_priv *priv = i2c_get_clientdata(client);
 	struct input_dev *input_dev = priv->input;
 
@@ -296,9 +298,8 @@ static int eeti_ts_resume(struct i2c_cli
 
 	return 0;
 }
-#else
-#define eeti_ts_suspend NULL
-#define eeti_ts_resume NULL
+
+static SIMPLE_DEV_PM_OPS(eeti_ts_pm, eeti_ts_suspend, eeti_ts_resume);
 #endif
 
 static const struct i2c_device_id eeti_ts_id[] = {
@@ -310,11 +311,12 @@ MODULE_DEVICE_TABLE(i2c, eeti_ts_id);
 static struct i2c_driver eeti_ts_driver = {
 	.driver = {
 		.name = "eeti_ts",
+#ifdef CONFIG_PM
+		.pm = &eeti_ts_pm,
+#endif
 	},
 	.probe = eeti_ts_probe,
 	.remove = __devexit_p(eeti_ts_remove),
-	.suspend = eeti_ts_suspend,
-	.resume = eeti_ts_resume,
 	.id_table = eeti_ts_id,
 };
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/input/touchscreen/Kconfig linux-libre-2.6.38-gnu1/drivers/input/touchscreen/Kconfig
--- linux-libre-2.6.37-gnu1/drivers/input/touchscreen/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/input/touchscreen/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -540,62 +540,62 @@ config TOUCHSCREEN_MC13783
 
 config TOUCHSCREEN_USB_EGALAX
 	default y
-	bool "eGalax, eTurboTouch CT-410/510/700 device support" if EMBEDDED
+	bool "eGalax, eTurboTouch CT-410/510/700 device support" if EXPERT
 	depends on TOUCHSCREEN_USB_COMPOSITE
 
 config TOUCHSCREEN_USB_PANJIT
 	default y
-	bool "PanJit device support" if EMBEDDED
+	bool "PanJit device support" if EXPERT
 	depends on TOUCHSCREEN_USB_COMPOSITE
 
 config TOUCHSCREEN_USB_3M
 	default y
-	bool "3M/Microtouch EX II series device support" if EMBEDDED
+	bool "3M/Microtouch EX II series device support" if EXPERT
 	depends on TOUCHSCREEN_USB_COMPOSITE
 
 config TOUCHSCREEN_USB_ITM
 	default y
-	bool "ITM device support" if EMBEDDED
+	bool "ITM device support" if EXPERT
 	depends on TOUCHSCREEN_USB_COMPOSITE
 
 config TOUCHSCREEN_USB_ETURBO
 	default y
-	bool "eTurboTouch (non-eGalax compatible) device support" if EMBEDDED
+	bool "eTurboTouch (non-eGalax compatible) device support" if EXPERT
 	depends on TOUCHSCREEN_USB_COMPOSITE
 
 config TOUCHSCREEN_USB_GUNZE
 	default y
-	bool "Gunze AHL61 device support" if EMBEDDED
+	bool "Gunze AHL61 device support" if EXPERT
 	depends on TOUCHSCREEN_USB_COMPOSITE
 
 config TOUCHSCREEN_USB_DMC_TSC10
 	default y
-	bool "DMC TSC-10/25 device support" if EMBEDDED
+	bool "DMC TSC-10/25 device support" if EXPERT
 	depends on TOUCHSCREEN_USB_COMPOSITE
 
 config TOUCHSCREEN_USB_IRTOUCH
 	default y
-	bool "IRTOUCHSYSTEMS/UNITOP device support" if EMBEDDED
+	bool "IRTOUCHSYSTEMS/UNITOP device support" if EXPERT
 	depends on TOUCHSCREEN_USB_COMPOSITE
 
 config TOUCHSCREEN_USB_IDEALTEK
 	default y
-	bool "IdealTEK URTC1000 device support" if EMBEDDED
+	bool "IdealTEK URTC1000 device support" if EXPERT
 	depends on TOUCHSCREEN_USB_COMPOSITE
 
 config TOUCHSCREEN_USB_GENERAL_TOUCH
 	default y
-	bool "GeneralTouch Touchscreen device support" if EMBEDDED
+	bool "GeneralTouch Touchscreen device support" if EXPERT
 	depends on TOUCHSCREEN_USB_COMPOSITE
 
 config TOUCHSCREEN_USB_GOTOP
 	default y
-	bool "GoTop Super_Q2/GogoPen/PenPower tablet device support" if EMBEDDED
+	bool "GoTop Super_Q2/GogoPen/PenPower tablet device support" if EXPERT
 	depends on TOUCHSCREEN_USB_COMPOSITE
 
 config TOUCHSCREEN_USB_JASTEC
 	default y
-	bool "JASTEC/DigiTech DTR-02U USB touch controller device support" if EMBEDDED
+	bool "JASTEC/DigiTech DTR-02U USB touch controller device support" if EXPERT
 	depends on TOUCHSCREEN_USB_COMPOSITE
 
 config TOUCHSCREEN_USB_E2I
@@ -605,17 +605,17 @@ config TOUCHSCREEN_USB_E2I
 
 config TOUCHSCREEN_USB_ZYTRONIC
 	default y
-	bool "Zytronic controller" if EMBEDDED
+	bool "Zytronic controller" if EXPERT
 	depends on TOUCHSCREEN_USB_COMPOSITE
 
 config TOUCHSCREEN_USB_ETT_TC45USB
 	default y
-	bool "ET&T USB series TC4UM/TC5UH touchscreen controler support" if EMBEDDED
+	bool "ET&T USB series TC4UM/TC5UH touchscreen controller support" if EXPERT
 	depends on TOUCHSCREEN_USB_COMPOSITE
 
 config TOUCHSCREEN_USB_NEXIO
 	default y
-	bool "NEXIO/iNexio device support" if EMBEDDED
+	bool "NEXIO/iNexio device support" if EXPERT
 	depends on TOUCHSCREEN_USB_COMPOSITE
 
 config TOUCHSCREEN_TOUCHIT213
@@ -659,17 +659,17 @@ config TOUCHSCREEN_PCAP
 	  To compile this driver as a module, choose M here: the
 	  module will be called pcap_ts.
 
-config TOUCHSCREEN_TPS6507X
-	tristate "TPS6507x based touchscreens"
+config TOUCHSCREEN_ST1232
+	tristate "Sitronix ST1232 touchscreen controllers"
 	depends on I2C
 	help
-	  Say Y here if you have a TPS6507x based touchscreen
-	  controller.
+	  Say Y here if you want to support Sitronix ST1232
+	  touchscreen controller.
 
 	  If unsure, say N.
 
 	  To compile this driver as a module, choose M here: the
-	  module will be called tps6507x_ts.
+	  module will be called st1232_ts.
 
 config TOUCHSCREEN_STMPE
 	tristate "STMicroelectronics STMPE touchscreens"
@@ -681,4 +681,16 @@ config TOUCHSCREEN_STMPE
 	  To compile this driver as a module, choose M here: the
 	  module will be called stmpe-ts.
 
+config TOUCHSCREEN_TPS6507X
+	tristate "TPS6507x based touchscreens"
+	depends on I2C
+	help
+	  Say Y here if you have a TPS6507x based touchscreen
+	  controller.
+
+	  If unsure, say N.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called tps6507x_ts.
+
 endif
diff -druNp linux-libre-2.6.37-gnu1/drivers/input/touchscreen/Makefile linux-libre-2.6.38-gnu1/drivers/input/touchscreen/Makefile
--- linux-libre-2.6.37-gnu1/drivers/input/touchscreen/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/input/touchscreen/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -39,6 +39,7 @@ obj-$(CONFIG_TOUCHSCREEN_PCAP)		+= pcap_
 obj-$(CONFIG_TOUCHSCREEN_PENMOUNT)	+= penmount.o
 obj-$(CONFIG_TOUCHSCREEN_QT602240)	+= qt602240_ts.o
 obj-$(CONFIG_TOUCHSCREEN_S3C2410)	+= s3c2410_ts.o
+obj-$(CONFIG_TOUCHSCREEN_ST1232)	+= st1232.o
 obj-$(CONFIG_TOUCHSCREEN_STMPE)		+= stmpe-ts.o
 obj-$(CONFIG_TOUCHSCREEN_TNETV107X)	+= tnetv107x-ts.o
 obj-$(CONFIG_TOUCHSCREEN_TOUCHIT213)	+= touchit213.o
diff -druNp linux-libre-2.6.37-gnu1/drivers/input/touchscreen/mcs5000_ts.c linux-libre-2.6.38-gnu1/drivers/input/touchscreen/mcs5000_ts.c
--- linux-libre-2.6.37-gnu1/drivers/input/touchscreen/mcs5000_ts.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/input/touchscreen/mcs5000_ts.c	2011-03-14 21:20:32.000000000 -0400
@@ -261,25 +261,27 @@ static int __devexit mcs5000_ts_remove(s
 }
 
 #ifdef CONFIG_PM
-static int mcs5000_ts_suspend(struct i2c_client *client, pm_message_t mesg)
+static int mcs5000_ts_suspend(struct device *dev)
 {
+	struct i2c_client *client = to_i2c_client(dev);
+
 	/* Touch sleep mode */
 	i2c_smbus_write_byte_data(client, MCS5000_TS_OP_MODE, OP_MODE_SLEEP);
 
 	return 0;
 }
 
-static int mcs5000_ts_resume(struct i2c_client *client)
+static int mcs5000_ts_resume(struct device *dev)
 {
+	struct i2c_client *client = to_i2c_client(dev);
 	struct mcs5000_ts_data *data = i2c_get_clientdata(client);
 
 	mcs5000_ts_phys_init(data);
 
 	return 0;
 }
-#else
-#define mcs5000_ts_suspend	NULL
-#define mcs5000_ts_resume	NULL
+
+static SIMPLE_DEV_PM_OPS(mcs5000_ts_pm, mcs5000_ts_suspend, mcs5000_ts_resume);
 #endif
 
 static const struct i2c_device_id mcs5000_ts_id[] = {
@@ -291,10 +293,11 @@ MODULE_DEVICE_TABLE(i2c, mcs5000_ts_id);
 static struct i2c_driver mcs5000_ts_driver = {
 	.probe		= mcs5000_ts_probe,
 	.remove		= __devexit_p(mcs5000_ts_remove),
-	.suspend	= mcs5000_ts_suspend,
-	.resume		= mcs5000_ts_resume,
 	.driver = {
 		.name = "mcs5000_ts",
+#ifdef CONFIG_PM
+		.pm   = &mcs5000_ts_pm,
+#endif
 	},
 	.id_table	= mcs5000_ts_id,
 };
diff -druNp linux-libre-2.6.37-gnu1/drivers/input/touchscreen/migor_ts.c linux-libre-2.6.38-gnu1/drivers/input/touchscreen/migor_ts.c
--- linux-libre-2.6.37-gnu1/drivers/input/touchscreen/migor_ts.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/input/touchscreen/migor_ts.c	2011-03-14 21:20:32.000000000 -0400
@@ -23,6 +23,7 @@
 #include <linux/kernel.h>
 #include <linux/input.h>
 #include <linux/interrupt.h>
+#include <linux/pm.h>
 #include <linux/slab.h>
 #include <asm/io.h>
 #include <linux/i2c.h>
@@ -226,8 +227,9 @@ static int migor_ts_remove(struct i2c_cl
 	return 0;
 }
 
-static int migor_ts_suspend(struct i2c_client *client, pm_message_t mesg)
+static int migor_ts_suspend(struct device *dev)
 {
+	struct i2c_client *client = to_i2c_client(dev);
 	struct migor_ts_priv *priv = dev_get_drvdata(&client->dev);
 
 	if (device_may_wakeup(&client->dev))
@@ -236,8 +238,9 @@ static int migor_ts_suspend(struct i2c_c
 	return 0;
 }
 
-static int migor_ts_resume(struct i2c_client *client)
+static int migor_ts_resume(struct device *dev)
 {
+	struct i2c_client *client = to_i2c_client(dev);
 	struct migor_ts_priv *priv = dev_get_drvdata(&client->dev);
 
 	if (device_may_wakeup(&client->dev))
@@ -246,6 +249,8 @@ static int migor_ts_resume(struct i2c_cl
 	return 0;
 }
 
+static SIMPLE_DEV_PM_OPS(migor_ts_pm, migor_ts_suspend, migor_ts_resume);
+
 static const struct i2c_device_id migor_ts_id[] = {
 	{ "migor_ts", 0 },
 	{ }
@@ -255,11 +260,10 @@ MODULE_DEVICE_TABLE(i2c, migor_ts);
 static struct i2c_driver migor_ts_driver = {
 	.driver = {
 		.name = "migor_ts",
+		.pm = &migor_ts_pm,
 	},
 	.probe = migor_ts_probe,
 	.remove = migor_ts_remove,
-	.suspend = migor_ts_suspend,
-	.resume = migor_ts_resume,
 	.id_table = migor_ts_id,
 };
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/input/touchscreen/qt602240_ts.c linux-libre-2.6.38-gnu1/drivers/input/touchscreen/qt602240_ts.c
--- linux-libre-2.6.37-gnu1/drivers/input/touchscreen/qt602240_ts.c	2013-05-03 04:03:20.000000000 -0400
+++ linux-libre-2.6.38-gnu1/drivers/input/touchscreen/qt602240_ts.c	2013-05-03 02:04:42.000000000 -0400
@@ -969,7 +969,7 @@ static int qt602240_initialize(struct qt
 		return error;
 
 	data->object_table = kcalloc(info->object_num,
-				     sizeof(struct qt602240_data),
+				     sizeof(struct qt602240_object),
 				     GFP_KERNEL);
 	if (!data->object_table) {
 		dev_err(&client->dev, "Failed to allocate memory\n");
@@ -1324,8 +1324,9 @@ static int __devexit qt602240_remove(str
 }
 
 #ifdef CONFIG_PM
-static int qt602240_suspend(struct i2c_client *client, pm_message_t mesg)
+static int qt602240_suspend(struct device *dev)
 {
+	struct i2c_client *client = to_i2c_client(dev);
 	struct qt602240_data *data = i2c_get_clientdata(client);
 	struct input_dev *input_dev = data->input_dev;
 
@@ -1339,8 +1340,9 @@ static int qt602240_suspend(struct i2c_c
 	return 0;
 }
 
-static int qt602240_resume(struct i2c_client *client)
+static int qt602240_resume(struct device *dev)
 {
+	struct i2c_client *client = to_i2c_client(dev);
 	struct qt602240_data *data = i2c_get_clientdata(client);
 	struct input_dev *input_dev = data->input_dev;
 
@@ -1359,9 +1361,11 @@ static int qt602240_resume(struct i2c_cl
 
 	return 0;
 }
-#else
-#define qt602240_suspend	NULL
-#define qt602240_resume		NULL
+
+static const struct dev_pm_ops qt602240_pm_ops = {
+	.suspend	= qt602240_suspend,
+	.resume		= qt602240_resume,
+};
 #endif
 
 static const struct i2c_device_id qt602240_id[] = {
@@ -1374,11 +1378,12 @@ static struct i2c_driver qt602240_driver
 	.driver = {
 		.name	= "qt602240_ts",
 		.owner	= THIS_MODULE,
+#ifdef CONFIG_PM
+		.pm	= &qt602240_pm_ops,
+#endif
 	},
 	.probe		= qt602240_probe,
 	.remove		= __devexit_p(qt602240_remove),
-	.suspend	= qt602240_suspend,
-	.resume		= qt602240_resume,
 	.id_table	= qt602240_id,
 };
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/input/touchscreen/st1232.c linux-libre-2.6.38-gnu1/drivers/input/touchscreen/st1232.c
--- linux-libre-2.6.37-gnu1/drivers/input/touchscreen/st1232.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/input/touchscreen/st1232.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,274 @@
+/*
+ * ST1232 Touchscreen Controller Driver
+ *
+ * Copyright (C) 2010 Renesas Solutions Corp.
+ *	Tony SIM <chinyeow.sim.xt@renesas.com>
+ *
+ * Using code from:
+ *  - android.git.kernel.org: projects/kernel/common.git: synaptics_i2c_rmi.c
+ *	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.
+ */
+
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+
+#define ST1232_TS_NAME	"st1232-ts"
+
+#define MIN_X		0x00
+#define MIN_Y		0x00
+#define MAX_X		0x31f	/* (800 - 1) */
+#define MAX_Y		0x1df	/* (480 - 1) */
+#define MAX_AREA	0xff
+#define MAX_FINGERS	2
+
+struct st1232_ts_finger {
+	u16 x;
+	u16 y;
+	u8 t;
+	bool is_valid;
+};
+
+struct st1232_ts_data {
+	struct i2c_client *client;
+	struct input_dev *input_dev;
+	struct st1232_ts_finger finger[MAX_FINGERS];
+};
+
+static int st1232_ts_read_data(struct st1232_ts_data *ts)
+{
+	struct st1232_ts_finger *finger = ts->finger;
+	struct i2c_client *client = ts->client;
+	struct i2c_msg msg[2];
+	int error;
+	u8 start_reg;
+	u8 buf[10];
+
+	/* read touchscreen data from ST1232 */
+	msg[0].addr = client->addr;
+	msg[0].flags = 0;
+	msg[0].len = 1;
+	msg[0].buf = &start_reg;
+	start_reg = 0x10;
+
+	msg[1].addr = ts->client->addr;
+	msg[1].flags = I2C_M_RD;
+	msg[1].len = sizeof(buf);
+	msg[1].buf = buf;
+
+	error = i2c_transfer(client->adapter, msg, 2);
+	if (error < 0)
+		return error;
+
+	/* get "valid" bits */
+	finger[0].is_valid = buf[2] >> 7;
+	finger[1].is_valid = buf[5] >> 7;
+
+	/* get xy coordinate */
+	if (finger[0].is_valid) {
+		finger[0].x = ((buf[2] & 0x0070) << 4) | buf[3];
+		finger[0].y = ((buf[2] & 0x0007) << 8) | buf[4];
+		finger[0].t = buf[8];
+	}
+
+	if (finger[1].is_valid) {
+		finger[1].x = ((buf[5] & 0x0070) << 4) | buf[6];
+		finger[1].y = ((buf[5] & 0x0007) << 8) | buf[7];
+		finger[1].t = buf[9];
+	}
+
+	return 0;
+}
+
+static irqreturn_t st1232_ts_irq_handler(int irq, void *dev_id)
+{
+	struct st1232_ts_data *ts = dev_id;
+	struct st1232_ts_finger *finger = ts->finger;
+	struct input_dev *input_dev = ts->input_dev;
+	int count = 0;
+	int i, ret;
+
+	ret = st1232_ts_read_data(ts);
+	if (ret < 0)
+		goto end;
+
+	/* multi touch protocol */
+	for (i = 0; i < MAX_FINGERS; i++) {
+		if (!finger[i].is_valid)
+			continue;
+
+		input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR, finger[i].t);
+		input_report_abs(input_dev, ABS_MT_POSITION_X, finger[i].x);
+		input_report_abs(input_dev, ABS_MT_POSITION_Y, finger[i].y);
+		input_mt_sync(input_dev);
+		count++;
+	}
+
+	/* SYN_MT_REPORT only if no contact */
+	if (!count)
+		input_mt_sync(input_dev);
+
+	/* SYN_REPORT */
+	input_sync(input_dev);
+
+end:
+	return IRQ_HANDLED;
+}
+
+static int __devinit st1232_ts_probe(struct i2c_client *client,
+					const struct i2c_device_id *id)
+{
+	struct st1232_ts_data *ts;
+	struct input_dev *input_dev;
+	int error;
+
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+		dev_err(&client->dev, "need I2C_FUNC_I2C\n");
+		return -EIO;
+	}
+
+	if (!client->irq) {
+		dev_err(&client->dev, "no IRQ?\n");
+		return -EINVAL;
+	}
+
+
+	ts = kzalloc(sizeof(struct st1232_ts_data), GFP_KERNEL);
+	input_dev = input_allocate_device();
+	if (!ts || !input_dev) {
+		error = -ENOMEM;
+		goto err_free_mem;
+	}
+
+	ts->client = client;
+	ts->input_dev = input_dev;
+
+	input_dev->name = "st1232-touchscreen";
+	input_dev->id.bustype = BUS_I2C;
+	input_dev->dev.parent = &client->dev;
+
+	__set_bit(EV_SYN, input_dev->evbit);
+	__set_bit(EV_KEY, input_dev->evbit);
+	__set_bit(EV_ABS, input_dev->evbit);
+
+	input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, MAX_AREA, 0, 0);
+	input_set_abs_params(input_dev, ABS_MT_POSITION_X, MIN_X, MAX_X, 0, 0);
+	input_set_abs_params(input_dev, ABS_MT_POSITION_Y, MIN_Y, MAX_Y, 0, 0);
+
+	error = request_threaded_irq(client->irq, NULL, st1232_ts_irq_handler,
+				     IRQF_ONESHOT, client->name, ts);
+	if (error) {
+		dev_err(&client->dev, "Failed to register interrupt\n");
+		goto err_free_mem;
+	}
+
+	error = input_register_device(ts->input_dev);
+	if (error) {
+		dev_err(&client->dev, "Unable to register %s input device\n",
+			input_dev->name);
+		goto err_free_irq;
+	}
+
+	i2c_set_clientdata(client, ts);
+	device_init_wakeup(&client->dev, 1);
+
+	return 0;
+
+err_free_irq:
+	free_irq(client->irq, ts);
+err_free_mem:
+	input_free_device(input_dev);
+	kfree(ts);
+	return error;
+}
+
+static int __devexit st1232_ts_remove(struct i2c_client *client)
+{
+	struct st1232_ts_data *ts = i2c_get_clientdata(client);
+
+	device_init_wakeup(&client->dev, 0);
+	free_irq(client->irq, ts);
+	input_unregister_device(ts->input_dev);
+	kfree(ts);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int st1232_ts_suspend(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+
+	if (device_may_wakeup(&client->dev))
+		enable_irq_wake(client->irq);
+	else
+		disable_irq(client->irq);
+
+	return 0;
+}
+
+static int st1232_ts_resume(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+
+	if (device_may_wakeup(&client->dev))
+		disable_irq_wake(client->irq);
+	else
+		enable_irq(client->irq);
+
+	return 0;
+}
+
+static const struct dev_pm_ops st1232_ts_pm_ops = {
+	.suspend	= st1232_ts_suspend,
+	.resume		= st1232_ts_resume,
+};
+#endif
+
+static const struct i2c_device_id st1232_ts_id[] = {
+	{ ST1232_TS_NAME, 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, st1232_ts_id);
+
+static struct i2c_driver st1232_ts_driver = {
+	.probe		= st1232_ts_probe,
+	.remove		= __devexit_p(st1232_ts_remove),
+	.id_table	= st1232_ts_id,
+	.driver = {
+		.name	= ST1232_TS_NAME,
+		.owner	= THIS_MODULE,
+#ifdef CONFIG_PM
+		.pm	= &st1232_ts_pm_ops,
+#endif
+	},
+};
+
+static int __init st1232_ts_init(void)
+{
+	return i2c_add_driver(&st1232_ts_driver);
+}
+module_init(st1232_ts_init);
+
+static void __exit st1232_ts_exit(void)
+{
+	i2c_del_driver(&st1232_ts_driver);
+}
+module_exit(st1232_ts_exit);
+
+MODULE_AUTHOR("Tony SIM <chinyeow.sim.xt@renesas.com>");
+MODULE_DESCRIPTION("SITRONIX ST1232 Touchscreen Controller Driver");
+MODULE_LICENSE("GPL");
diff -druNp linux-libre-2.6.37-gnu1/drivers/input/touchscreen/tnetv107x-ts.c linux-libre-2.6.38-gnu1/drivers/input/touchscreen/tnetv107x-ts.c
--- linux-libre-2.6.37-gnu1/drivers/input/touchscreen/tnetv107x-ts.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/input/touchscreen/tnetv107x-ts.c	2011-03-14 21:20:32.000000000 -0400
@@ -14,6 +14,7 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/err.h>
 #include <linux/errno.h>
 #include <linux/input.h>
 #include <linux/platform_device.h>
@@ -289,9 +290,9 @@ static int __devinit tsc_probe(struct pl
 	}
 
 	ts->clk = clk_get(dev, NULL);
-	if (!ts->clk) {
+	if (IS_ERR(ts->clk)) {
 		dev_err(dev, "cannot claim device clock\n");
-		error = -EINVAL;
+		error = PTR_ERR(ts->clk);
 		goto error_clk;
 	}
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/input/touchscreen/wacom_w8001.c linux-libre-2.6.38-gnu1/drivers/input/touchscreen/wacom_w8001.c
--- linux-libre-2.6.37-gnu1/drivers/input/touchscreen/wacom_w8001.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/input/touchscreen/wacom_w8001.c	2011-03-14 21:20:32.000000000 -0400
@@ -3,6 +3,7 @@
  *
  * Copyright (c) 2008 Jaya Kumar
  * Copyright (c) 2010 Red Hat, Inc.
+ * Copyright (c) 2010 - 2011 Ping Cheng, Wacom. <pingc@wacom.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
@@ -15,10 +16,11 @@
 #include <linux/kernel.h>
 #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>
 #include <linux/ctype.h>
+#include <linux/delay.h>
 
 #define DRIVER_DESC	"Wacom W8001 serial touchscreen driver"
 
@@ -37,6 +39,7 @@ MODULE_LICENSE("GPL");
 
 #define W8001_QUERY_PACKET	0x20
 
+#define W8001_CMD_STOP		'0'
 #define W8001_CMD_START		'1'
 #define W8001_CMD_QUERY		'*'
 #define W8001_CMD_TOUCHQUERY	'%'
@@ -48,7 +51,9 @@ MODULE_LICENSE("GPL");
 #define W8001_PKTLEN_TPCCTL	11	/* control packet */
 #define W8001_PKTLEN_TOUCH2FG	13
 
-#define MAX_TRACKING_ID		0xFF	/* arbitrarily chosen */
+/* resolution in points/mm */
+#define W8001_PEN_RESOLUTION    100
+#define W8001_TOUCH_RESOLUTION  10
 
 struct w8001_coord {
 	u8 rdy;
@@ -64,11 +69,11 @@ struct w8001_coord {
 
 /* touch query reply packet */
 struct w8001_touch_query {
+	u16 x;
+	u16 y;
 	u8 panel_res;
 	u8 capacity_res;
 	u8 sensor_id;
-	u16 x;
-	u16 y;
 };
 
 /*
@@ -87,10 +92,14 @@ struct w8001 {
 	char phys[32];
 	int type;
 	unsigned int pktlen;
-	int trkid[2];
+	u16 max_touch_x;
+	u16 max_touch_y;
+	u16 max_pen_x;
+	u16 max_pen_y;
+	char name[64];
 };
 
-static void parse_data(u8 *data, struct w8001_coord *coord)
+static void parse_pen_data(u8 *data, struct w8001_coord *coord)
 {
 	memset(coord, 0, sizeof(*coord));
 
@@ -114,30 +123,58 @@ static void parse_data(u8 *data, struct
 	coord->tilt_y = data[8] & 0x7F;
 }
 
-static void parse_touch(struct w8001 *w8001)
+static void parse_single_touch(u8 *data, struct w8001_coord *coord)
+{
+	coord->x = (data[1] << 7) | data[2];
+	coord->y = (data[3] << 7) | data[4];
+	coord->tsw = data[0] & 0x01;
+}
+
+static void scale_touch_coordinates(struct w8001 *w8001,
+				    unsigned int *x, unsigned int *y)
+{
+	if (w8001->max_pen_x && w8001->max_touch_x)
+		*x = *x * w8001->max_pen_x / w8001->max_touch_x;
+
+	if (w8001->max_pen_y && w8001->max_touch_y)
+		*y = *y * w8001->max_pen_y / w8001->max_touch_y;
+}
+
+static void parse_multi_touch(struct w8001 *w8001)
 {
-	static int trkid;
 	struct input_dev *dev = w8001->dev;
 	unsigned char *data = w8001->data;
+	unsigned int x, y;
 	int i;
+	int count = 0;
 
 	for (i = 0; i < 2; i++) {
-		input_mt_slot(dev, i);
+		bool touch = data[0] & (1 << i);
 
-		if (data[0] & (1 << i)) {
-			int x = (data[6 * i + 1] << 7) | (data[6 * i + 2]);
-			int y = (data[6 * i + 3] << 7) | (data[6 * i + 4]);
+		input_mt_slot(dev, i);
+		input_mt_report_slot_state(dev, MT_TOOL_FINGER, touch);
+		if (touch) {
+			x = (data[6 * i + 1] << 7) | data[6 * i + 2];
+			y = (data[6 * i + 3] << 7) | data[6 * i + 4];
 			/* data[5,6] and [11,12] is finger capacity */
 
+			/* scale to pen maximum */
+			scale_touch_coordinates(w8001, &x, &y);
+
 			input_report_abs(dev, ABS_MT_POSITION_X, x);
 			input_report_abs(dev, ABS_MT_POSITION_Y, y);
-			input_report_abs(dev, ABS_MT_TOOL_TYPE, MT_TOOL_FINGER);
-			if (w8001->trkid[i] < 0)
-				w8001->trkid[i] = trkid++ & MAX_TRACKING_ID;
-		} else {
-			w8001->trkid[i] = -1;
+			count++;
 		}
-		input_report_abs(dev, ABS_MT_TRACKING_ID, w8001->trkid[i]);
+	}
+
+	/* emulate single touch events when stylus is out of proximity.
+	 * This is to make single touch backward support consistent
+	 * across all Wacom single touch devices.
+	 */
+	if (w8001->type != BTN_TOOL_PEN &&
+			    w8001->type != BTN_TOOL_RUBBER) {
+		w8001->type = count == 1 ? BTN_TOOL_FINGER : KEY_RESERVED;
+		input_mt_report_pointer_emulation(dev, true);
 	}
 
 	input_sync(dev);
@@ -158,6 +195,15 @@ static void parse_touchquery(u8 *data, s
 	query->y = data[5] << 9;
 	query->y |= data[6] << 2;
 	query->y |= (data[2] >> 3) & 0x3;
+
+	/* Early days' single-finger touch models need the following defaults */
+	if (!query->x && !query->y) {
+		query->x = 1024;
+		query->y = 1024;
+		if (query->panel_res)
+			query->x = query->y = (1 << query->panel_res);
+		query->panel_res = W8001_TOUCH_RESOLUTION;
+	}
 }
 
 static void report_pen_events(struct w8001 *w8001, struct w8001_coord *coord)
@@ -167,16 +213,15 @@ static void report_pen_events(struct w80
 	/*
 	 * We have 1 bit for proximity (rdy) and 3 bits for tip, side,
 	 * side2/eraser. If rdy && f2 are set, this can be either pen + side2,
-	 * or eraser. assume
+	 * or eraser. Assume:
 	 * - if dev is already in proximity and f2 is toggled → pen + side2
 	 * - if dev comes into proximity with f2 set → eraser
 	 * If f2 disappears after assuming eraser, fake proximity out for
 	 * eraser and in for pen.
 	 */
 
-	if (!w8001->type) {
-		w8001->type = coord->f2 ? BTN_TOOL_RUBBER : BTN_TOOL_PEN;
-	} else if (w8001->type == BTN_TOOL_RUBBER) {
+	switch (w8001->type) {
+	case BTN_TOOL_RUBBER:
 		if (!coord->f2) {
 			input_report_abs(dev, ABS_PRESSURE, 0);
 			input_report_key(dev, BTN_TOUCH, 0);
@@ -186,8 +231,21 @@ static void report_pen_events(struct w80
 			input_sync(dev);
 			w8001->type = BTN_TOOL_PEN;
 		}
-	} else {
+		break;
+
+	case BTN_TOOL_FINGER:
+		input_report_key(dev, BTN_TOUCH, 0);
+		input_report_key(dev, BTN_TOOL_FINGER, 0);
+		input_sync(dev);
+		/* fall through */
+
+	case KEY_RESERVED:
+		w8001->type = coord->f2 ? BTN_TOOL_RUBBER : BTN_TOOL_PEN;
+		break;
+
+	default:
 		input_report_key(dev, BTN_STYLUS2, coord->f2);
+		break;
 	}
 
 	input_report_abs(dev, ABS_X, coord->x);
@@ -199,7 +257,26 @@ static void report_pen_events(struct w80
 	input_sync(dev);
 
 	if (!coord->rdy)
-		w8001->type = 0;
+		w8001->type = KEY_RESERVED;
+}
+
+static void report_single_touch(struct w8001 *w8001, struct w8001_coord *coord)
+{
+	struct input_dev *dev = w8001->dev;
+	unsigned int x = coord->x;
+	unsigned int y = coord->y;
+
+	/* scale to pen maximum */
+	scale_touch_coordinates(w8001, &x, &y);
+
+	input_report_abs(dev, ABS_X, x);
+	input_report_abs(dev, ABS_Y, y);
+	input_report_key(dev, BTN_TOUCH, coord->tsw);
+	input_report_key(dev, BTN_TOOL_FINGER, coord->tsw);
+
+	input_sync(dev);
+
+	w8001->type = coord->tsw ? BTN_TOOL_FINGER : KEY_RESERVED;
 }
 
 static irqreturn_t w8001_interrupt(struct serio *serio,
@@ -220,9 +297,18 @@ static irqreturn_t w8001_interrupt(struc
 
 	case W8001_PKTLEN_TOUCH93 - 1:
 	case W8001_PKTLEN_TOUCH9A - 1:
-		/* ignore one-finger touch packet. */
-		if (w8001->pktlen == w8001->idx)
+		tmp = w8001->data[0] & W8001_TOUCH_BYTE;
+		if (tmp != W8001_TOUCH_BYTE)
+			break;
+
+		if (w8001->pktlen == w8001->idx) {
 			w8001->idx = 0;
+			if (w8001->type != BTN_TOOL_PEN &&
+			    w8001->type != BTN_TOOL_RUBBER) {
+				parse_single_touch(w8001->data, &coord);
+				report_single_touch(w8001, &coord);
+			}
+		}
 		break;
 
 	/* Pen coordinates packet */
@@ -231,18 +317,18 @@ static irqreturn_t w8001_interrupt(struc
 		if (unlikely(tmp == W8001_TAB_BYTE))
 			break;
 
-		tmp = (w8001->data[0] & W8001_TOUCH_BYTE);
+		tmp = w8001->data[0] & W8001_TOUCH_BYTE;
 		if (tmp == W8001_TOUCH_BYTE)
 			break;
 
 		w8001->idx = 0;
-		parse_data(w8001->data, &coord);
+		parse_pen_data(w8001->data, &coord);
 		report_pen_events(w8001, &coord);
 		break;
 
 	/* control packet */
 	case W8001_PKTLEN_TPCCTL - 1:
-		tmp = (w8001->data[0] & W8001_TOUCH_MASK);
+		tmp = w8001->data[0] & W8001_TOUCH_MASK;
 		if (tmp == W8001_TOUCH_BYTE)
 			break;
 
@@ -255,7 +341,7 @@ static irqreturn_t w8001_interrupt(struc
 	/* 2 finger touch packet */
 	case W8001_PKTLEN_TOUCH2FG - 1:
 		w8001->idx = 0;
-		parse_touch(w8001);
+		parse_multi_touch(w8001);
 		break;
 	}
 
@@ -285,52 +371,109 @@ static int w8001_setup(struct w8001 *w80
 {
 	struct input_dev *dev = w8001->dev;
 	struct w8001_coord coord;
+	struct w8001_touch_query touch;
 	int error;
 
-	error = w8001_command(w8001, W8001_CMD_QUERY, true);
+	error = w8001_command(w8001, W8001_CMD_STOP, false);
 	if (error)
 		return error;
 
-	parse_data(w8001->response, &coord);
+	msleep(250);	/* wait 250ms before querying the device */
 
-	input_set_abs_params(dev, ABS_X, 0, coord.x, 0, 0);
-	input_set_abs_params(dev, ABS_Y, 0, coord.y, 0, 0);
-	input_set_abs_params(dev, ABS_PRESSURE, 0, coord.pen_pressure, 0, 0);
-	input_set_abs_params(dev, ABS_TILT_X, 0, coord.tilt_x, 0, 0);
-	input_set_abs_params(dev, ABS_TILT_Y, 0, coord.tilt_y, 0, 0);
+	dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+	strlcat(w8001->name, "Wacom Serial", sizeof(w8001->name));
 
-	error = w8001_command(w8001, W8001_CMD_TOUCHQUERY, true);
+	/* penabled? */
+	error = w8001_command(w8001, W8001_CMD_QUERY, true);
 	if (!error) {
-		struct w8001_touch_query touch;
+		__set_bit(BTN_TOUCH, dev->keybit);
+		__set_bit(BTN_TOOL_PEN, dev->keybit);
+		__set_bit(BTN_TOOL_RUBBER, dev->keybit);
+		__set_bit(BTN_STYLUS, dev->keybit);
+		__set_bit(BTN_STYLUS2, dev->keybit);
+
+		parse_pen_data(w8001->response, &coord);
+		w8001->max_pen_x = coord.x;
+		w8001->max_pen_y = coord.y;
+
+		input_set_abs_params(dev, ABS_X, 0, coord.x, 0, 0);
+		input_set_abs_params(dev, ABS_Y, 0, coord.y, 0, 0);
+		input_abs_set_res(dev, ABS_X, W8001_PEN_RESOLUTION);
+		input_abs_set_res(dev, ABS_Y, W8001_PEN_RESOLUTION);
+		input_set_abs_params(dev, ABS_PRESSURE, 0, coord.pen_pressure, 0, 0);
+		if (coord.tilt_x && coord.tilt_y) {
+			input_set_abs_params(dev, ABS_TILT_X, 0, coord.tilt_x, 0, 0);
+			input_set_abs_params(dev, ABS_TILT_Y, 0, coord.tilt_y, 0, 0);
+		}
+		w8001->id = 0x90;
+		strlcat(w8001->name, " Penabled", sizeof(w8001->name));
+	}
+
+	/* Touch enabled? */
+	error = w8001_command(w8001, W8001_CMD_TOUCHQUERY, true);
+
+	/*
+	 * Some non-touch devices may reply to the touch query. But their
+	 * second byte is empty, which indicates touch is not supported.
+	 */
+	if (!error && w8001->response[1]) {
+		__set_bit(BTN_TOUCH, dev->keybit);
+		__set_bit(BTN_TOOL_FINGER, dev->keybit);
 
 		parse_touchquery(w8001->response, &touch);
+		w8001->max_touch_x = touch.x;
+		w8001->max_touch_y = touch.y;
+
+		if (w8001->max_pen_x && w8001->max_pen_y) {
+			/* if pen is supported scale to pen maximum */
+			touch.x = w8001->max_pen_x;
+			touch.y = w8001->max_pen_y;
+			touch.panel_res = W8001_PEN_RESOLUTION;
+		}
+
+		input_set_abs_params(dev, ABS_X, 0, touch.x, 0, 0);
+		input_set_abs_params(dev, ABS_Y, 0, touch.y, 0, 0);
+		input_abs_set_res(dev, ABS_X, touch.panel_res);
+		input_abs_set_res(dev, ABS_Y, touch.panel_res);
 
 		switch (touch.sensor_id) {
 		case 0:
 		case 2:
 			w8001->pktlen = W8001_PKTLEN_TOUCH93;
+			w8001->id = 0x93;
+			strlcat(w8001->name, " 1FG", sizeof(w8001->name));
 			break;
+
 		case 1:
 		case 3:
 		case 4:
 			w8001->pktlen = W8001_PKTLEN_TOUCH9A;
+			strlcat(w8001->name, " 1FG", sizeof(w8001->name));
+			w8001->id = 0x9a;
 			break;
+
 		case 5:
 			w8001->pktlen = W8001_PKTLEN_TOUCH2FG;
 
-			input_mt_create_slots(dev, 2);
-			input_set_abs_params(dev, ABS_MT_TRACKING_ID,
-						0, MAX_TRACKING_ID, 0, 0);
+			input_mt_init_slots(dev, 2);
 			input_set_abs_params(dev, ABS_MT_POSITION_X,
 						0, touch.x, 0, 0);
 			input_set_abs_params(dev, ABS_MT_POSITION_Y,
 						0, touch.y, 0, 0);
 			input_set_abs_params(dev, ABS_MT_TOOL_TYPE,
-						0, 0, 0, 0);
+						0, MT_TOOL_MAX, 0, 0);
+
+			strlcat(w8001->name, " 2FG", sizeof(w8001->name));
+			if (w8001->max_pen_x && w8001->max_pen_y)
+				w8001->id = 0xE3;
+			else
+				w8001->id = 0xE2;
 			break;
 		}
 	}
 
+	strlcat(w8001->name, " Touchscreen", sizeof(w8001->name));
+
 	return w8001_command(w8001, W8001_CMD_START, false);
 }
 
@@ -370,27 +513,10 @@ static int w8001_connect(struct serio *s
 	}
 
 	w8001->serio = serio;
-	w8001->id = serio->id.id;
 	w8001->dev = input_dev;
-	w8001->trkid[0] = w8001->trkid[1] = -1;
 	init_completion(&w8001->cmd_done);
 	snprintf(w8001->phys, sizeof(w8001->phys), "%s/input0", serio->phys);
 
-	input_dev->name = "Wacom W8001 Penabled Serial TouchScreen";
-	input_dev->phys = w8001->phys;
-	input_dev->id.bustype = BUS_RS232;
-	input_dev->id.vendor = SERIO_W8001;
-	input_dev->id.product = w8001->id;
-	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_dev->keybit[BIT_WORD(BTN_TOOL_PEN)] |= BIT_MASK(BTN_TOOL_PEN);
-	input_dev->keybit[BIT_WORD(BTN_TOOL_RUBBER)] |= BIT_MASK(BTN_TOOL_RUBBER);
-	input_dev->keybit[BIT_WORD(BTN_STYLUS)] |= BIT_MASK(BTN_STYLUS);
-	input_dev->keybit[BIT_WORD(BTN_STYLUS2)] |= BIT_MASK(BTN_STYLUS2);
-
 	serio_set_drvdata(serio, w8001);
 	err = serio_open(serio, drv);
 	if (err)
@@ -400,6 +526,14 @@ static int w8001_connect(struct serio *s
 	if (err)
 		goto fail3;
 
+	input_dev->name = w8001->name;
+	input_dev->phys = w8001->phys;
+	input_dev->id.product = w8001->id;
+	input_dev->id.bustype = BUS_RS232;
+	input_dev->id.vendor = 0x056a;
+	input_dev->id.version = 0x0100;
+	input_dev->dev.parent = &serio->dev;
+
 	err = input_register_device(w8001->dev);
 	if (err)
 		goto fail3;
diff -druNp linux-libre-2.6.37-gnu1/drivers/input/xen-kbdfront.c linux-libre-2.6.38-gnu1/drivers/input/xen-kbdfront.c
--- linux-libre-2.6.37-gnu1/drivers/input/xen-kbdfront.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/input/xen-kbdfront.c	2011-03-14 21:20:32.000000000 -0400
@@ -17,6 +17,8 @@
  * Switch to grant tables together with xen-fbfront.c.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/module.h>
@@ -84,9 +86,8 @@ static irqreturn_t input_handler(int rq,
 				input_report_key(dev, event->key.keycode,
 						 event->key.pressed);
 			else
-				printk(KERN_WARNING
-				       "xenkbd: unhandled keycode 0x%x\n",
-				       event->key.keycode);
+				pr_warning("unhandled keycode 0x%x\n",
+					   event->key.keycode);
 			break;
 		case XENKBD_TYPE_POS:
 			input_report_abs(dev, ABS_X, event->pos.abs_x);
@@ -292,8 +293,7 @@ InitWait:
 			ret = xenbus_printf(XBT_NIL, info->xbdev->nodename,
 					    "request-abs-pointer", "1");
 			if (ret)
-				printk(KERN_WARNING
-				       "xenkbd: can't request abs-pointer");
+				pr_warning("can't request abs-pointer\n");
 		}
 		xenbus_switch_state(dev, XenbusStateConnected);
 		break;
diff -druNp linux-libre-2.6.37-gnu1/drivers/isdn/capi/capidrv.c linux-libre-2.6.38-gnu1/drivers/isdn/capi/capidrv.c
--- linux-libre-2.6.37-gnu1/drivers/isdn/capi/capidrv.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/isdn/capi/capidrv.c	2011-03-14 21:20:32.000000000 -0400
@@ -2297,6 +2297,7 @@ static int __init capidrv_init(void)
 
 	errcode = capi20_get_profile(0, &profile);
 	if (errcode != CAPI_NOERROR) {
+		unregister_capictr_notifier(&capictr_nb);
 		capi20_release(&global.ap);
 		return -EIO;
 	}
diff -druNp linux-libre-2.6.37-gnu1/drivers/isdn/capi/kcapi.c linux-libre-2.6.38-gnu1/drivers/isdn/capi/kcapi.c
--- linux-libre-2.6.37-gnu1/drivers/isdn/capi/kcapi.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/isdn/capi/kcapi.c	2011-03-14 21:20:32.000000000 -0400
@@ -38,6 +38,7 @@
 #include <linux/rcupdate.h>
 
 static int showcapimsgs = 0;
+static struct workqueue_struct *kcapi_wq;
 
 MODULE_DESCRIPTION("CAPI4Linux: kernel CAPI layer");
 MODULE_AUTHOR("Carsten Paeth");
@@ -291,7 +292,7 @@ static int notify_push(unsigned int even
 	event->type = event_type;
 	event->controller = controller;
 
-	schedule_work(&event->work);
+	queue_work(kcapi_wq, &event->work);
 	return 0;
 }
 
@@ -408,7 +409,7 @@ void capi_ctr_handle_message(struct capi
 		goto error;
 	}
 	skb_queue_tail(&ap->recv_queue, skb);
-	schedule_work(&ap->recv_work);
+	queue_work(kcapi_wq, &ap->recv_work);
 	rcu_read_unlock();
 
 	return;
@@ -743,7 +744,7 @@ u16 capi20_release(struct capi20_appl *a
 
 	mutex_unlock(&capi_controller_lock);
 
-	flush_scheduled_work();
+	flush_workqueue(kcapi_wq);
 	skb_queue_purge(&ap->recv_queue);
 
 	if (showcapimsgs & 1) {
@@ -1285,21 +1286,30 @@ static int __init kcapi_init(void)
 {
 	int err;
 
+	kcapi_wq = alloc_workqueue("kcapi", 0, 0);
+	if (!kcapi_wq)
+		return -ENOMEM;
+
 	register_capictr_notifier(&capictr_nb);
 
 	err = cdebug_init();
-	if (!err)
-		kcapi_proc_init();
-	return err;
+	if (err) {
+		unregister_capictr_notifier(&capictr_nb);
+		destroy_workqueue(kcapi_wq);
+		return err;
+	}
+
+	kcapi_proc_init();
+	return 0;
 }
 
 static void __exit kcapi_exit(void)
 {
         kcapi_proc_exit();
 
-	/* make sure all notifiers are finished */
-	flush_scheduled_work();
+	unregister_capictr_notifier(&capictr_nb);
 	cdebug_exit();
+	destroy_workqueue(kcapi_wq);
 }
 
 module_init(kcapi_init);
diff -druNp linux-libre-2.6.37-gnu1/drivers/isdn/gigaset/bas-gigaset.c linux-libre-2.6.38-gnu1/drivers/isdn/gigaset/bas-gigaset.c
--- linux-libre-2.6.37-gnu1/drivers/isdn/gigaset/bas-gigaset.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/isdn/gigaset/bas-gigaset.c	2011-03-14 21:20:32.000000000 -0400
@@ -2318,7 +2318,7 @@ static int gigaset_probe(struct usb_inte
 		 __func__, le16_to_cpu(udev->descriptor.idVendor),
 		 le16_to_cpu(udev->descriptor.idProduct));
 
-	/* allocate memory for our device state and intialize it */
+	/* allocate memory for our device state and initialize it */
 	cs = gigaset_initcs(driver, BAS_CHANNELS, 0, 0, cidmode,
 			    GIGASET_MODULENAME);
 	if (!cs)
@@ -2576,7 +2576,7 @@ static int __init bas_gigaset_init(void)
 {
 	int result;
 
-	/* allocate memory for our driver state and intialize it */
+	/* allocate memory for our driver state and initialize it */
 	driver = gigaset_initdriver(GIGASET_MINOR, GIGASET_MINORS,
 				    GIGASET_MODULENAME, GIGASET_DEVNAME,
 				    &gigops, THIS_MODULE);
diff -druNp linux-libre-2.6.37-gnu1/drivers/isdn/gigaset/ser-gigaset.c linux-libre-2.6.38-gnu1/drivers/isdn/gigaset/ser-gigaset.c
--- linux-libre-2.6.37-gnu1/drivers/isdn/gigaset/ser-gigaset.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/isdn/gigaset/ser-gigaset.c	2011-03-14 21:20:32.000000000 -0400
@@ -513,7 +513,7 @@ gigaset_tty_open(struct tty_struct *tty)
 		return -ENODEV;
 	}
 
-	/* allocate memory for our device state and intialize it */
+	/* allocate memory for our device state and initialize it */
 	cs = gigaset_initcs(driver, 1, 1, 0, cidmode, GIGASET_MODULENAME);
 	if (!cs)
 		goto error;
@@ -771,7 +771,7 @@ static int __init ser_gigaset_init(void)
 		return rc;
 	}
 
-	/* allocate memory for our driver state and intialize it */
+	/* allocate memory for our driver state and initialize it */
 	driver = gigaset_initdriver(GIGASET_MINOR, GIGASET_MINORS,
 					  GIGASET_MODULENAME, GIGASET_DEVNAME,
 					  &ops, THIS_MODULE);
diff -druNp linux-libre-2.6.37-gnu1/drivers/isdn/gigaset/usb-gigaset.c linux-libre-2.6.38-gnu1/drivers/isdn/gigaset/usb-gigaset.c
--- linux-libre-2.6.37-gnu1/drivers/isdn/gigaset/usb-gigaset.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/isdn/gigaset/usb-gigaset.c	2011-03-14 21:20:32.000000000 -0400
@@ -695,7 +695,7 @@ static int gigaset_probe(struct usb_inte
 
 	dev_info(&udev->dev, "%s: Device matched ... !\n", __func__);
 
-	/* allocate memory for our device state and intialize it */
+	/* allocate memory for our device state and initialize it */
 	cs = gigaset_initcs(driver, 1, 1, 0, cidmode, GIGASET_MODULENAME);
 	if (!cs)
 		return -ENODEV;
@@ -894,7 +894,7 @@ static int __init usb_gigaset_init(void)
 {
 	int result;
 
-	/* allocate memory for our driver state and intialize it */
+	/* allocate memory for our driver state and initialize it */
 	driver = gigaset_initdriver(GIGASET_MINOR, GIGASET_MINORS,
 				    GIGASET_MODULENAME, GIGASET_DEVNAME,
 				    &ops, THIS_MODULE);
diff -druNp linux-libre-2.6.37-gnu1/drivers/isdn/hardware/eicon/istream.c linux-libre-2.6.38-gnu1/drivers/isdn/hardware/eicon/istream.c
--- linux-libre-2.6.37-gnu1/drivers/isdn/hardware/eicon/istream.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/isdn/hardware/eicon/istream.c	2011-03-14 21:20:32.000000000 -0400
@@ -62,7 +62,7 @@ void diva_xdi_provide_istream_info (ADAP
   stream interface.
   If synchronous service was requested, then function
   does return amount of data written to stream.
-  'final' does indicate that pice of data to be written is
+  'final' does indicate that piece of data to be written is
   final part of frame (necessary only by structured datatransfer)
   return  0 if zero lengh packet was written
   return -1 if stream is full
diff -druNp linux-libre-2.6.37-gnu1/drivers/isdn/hardware/mISDN/ipac.h linux-libre-2.6.38-gnu1/drivers/isdn/hardware/mISDN/ipac.h
--- linux-libre-2.6.37-gnu1/drivers/isdn/hardware/mISDN/ipac.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/isdn/hardware/mISDN/ipac.h	2011-03-14 21:20:32.000000000 -0400
@@ -29,7 +29,7 @@ struct isac_hw {
 	u32			type;
 	u32			off;		/* offset to isac regs */
 	char			*name;
-	spinlock_t		*hwlock;	/* lock HW acccess */
+	spinlock_t		*hwlock;	/* lock HW access */
 	read_reg_func		*read_reg;
 	write_reg_func		*write_reg;
 	fifo_func		*read_fifo;
@@ -70,7 +70,7 @@ struct ipac_hw {
 	struct hscx_hw		hscx[2];
 	char			*name;
 	void			*hw;
-	spinlock_t		*hwlock;	/* lock HW acccess */
+	spinlock_t		*hwlock;	/* lock HW access */
 	struct module		*owner;
 	u32			type;
 	read_reg_func		*read_reg;
diff -druNp linux-libre-2.6.37-gnu1/drivers/isdn/hardware/mISDN/isar.h linux-libre-2.6.38-gnu1/drivers/isdn/hardware/mISDN/isar.h
--- linux-libre-2.6.37-gnu1/drivers/isdn/hardware/mISDN/isar.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/isdn/hardware/mISDN/isar.h	2011-03-14 21:20:32.000000000 -0400
@@ -44,7 +44,7 @@ struct isar_ch {
 struct isar_hw {
 	struct	isar_ch	ch[2];
 	void		*hw;
-	spinlock_t	*hwlock;	/* lock HW acccess */
+	spinlock_t	*hwlock;	/* lock HW access */
 	char		*name;
 	struct module	*owner;
 	read_reg_func	*read_reg;
diff -druNp linux-libre-2.6.37-gnu1/drivers/isdn/hardware/mISDN/mISDNinfineon.c linux-libre-2.6.38-gnu1/drivers/isdn/hardware/mISDN/mISDNinfineon.c
--- linux-libre-2.6.37-gnu1/drivers/isdn/hardware/mISDN/mISDNinfineon.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/isdn/hardware/mISDN/mISDNinfineon.c	2011-03-14 21:20:32.000000000 -0400
@@ -420,7 +420,7 @@ enable_hwirq(struct inf_hw *hw)
 		break;
 	case INF_NICCY:
 		val = inl((u32)hw->cfg.start + NICCY_IRQ_CTRL_REG);
-		val |= NICCY_IRQ_ENABLE;;
+		val |= NICCY_IRQ_ENABLE;
 		outl(val, (u32)hw->cfg.start + NICCY_IRQ_CTRL_REG);
 		break;
 	case INF_SCT_1:
@@ -924,7 +924,7 @@ setup_instance(struct inf_hw *card)
 		mISDNipac_init(&card->ipac, card);
 
 	if (card->ipac.isac.dch.dev.Bprotocols == 0)
-		goto error_setup;;
+		goto error_setup;
 
 	err = mISDN_register_device(&card->ipac.isac.dch.dev,
 		&card->pdev->dev, card->name);
diff -druNp linux-libre-2.6.37-gnu1/drivers/isdn/hardware/mISDN/mISDNisar.c linux-libre-2.6.38-gnu1/drivers/isdn/hardware/mISDN/mISDNisar.c
--- linux-libre-2.6.37-gnu1/drivers/isdn/hardware/mISDN/mISDNisar.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/isdn/hardware/mISDN/mISDNisar.c	2011-03-14 21:20:32.000000000 -0400
@@ -264,7 +264,7 @@ load_firmware(struct isar_hw *isar, cons
 			while (noc) {
 				val = le16_to_cpu(*sp++);
 				*mp++ = val >> 8;
-				*mp++ = val & 0xFF;;
+				*mp++ = val & 0xFF;
 				noc--;
 			}
 			spin_lock_irqsave(isar->hwlock, flags);
diff -druNp linux-libre-2.6.37-gnu1/drivers/isdn/hisax/avm_pci.c linux-libre-2.6.38-gnu1/drivers/isdn/hisax/avm_pci.c
--- linux-libre-2.6.37-gnu1/drivers/isdn/hisax/avm_pci.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/isdn/hisax/avm_pci.c	2011-03-14 21:20:32.000000000 -0400
@@ -314,7 +314,7 @@ hdlc_fill_fifo(struct BCState *bcs)
 			bcs->hw.hdlc.ctrl.sr.cmd |= HDLC_CMD_XME;
 	}
 	if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
-		debugl1(cs, "hdlc_fill_fifo %d/%ld", count, bcs->tx_skb->len);
+		debugl1(cs, "hdlc_fill_fifo %d/%u", count, bcs->tx_skb->len);
 	p = bcs->tx_skb->data;
 	ptr = (u_int *)p;
 	skb_pull(bcs->tx_skb, count);
diff -druNp linux-libre-2.6.37-gnu1/drivers/isdn/hisax/callc.c linux-libre-2.6.38-gnu1/drivers/isdn/hisax/callc.c
--- linux-libre-2.6.37-gnu1/drivers/isdn/hisax/callc.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/isdn/hisax/callc.c	2011-03-14 21:20:32.000000000 -0400
@@ -65,7 +65,7 @@ hisax_findcard(int driverid)
 	return (struct IsdnCardState *) 0;
 }
 
-static void
+static __attribute__((format(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 void
+static __attribute__((format(printf, 2, 3))) void
 callc_debug(struct FsmInst *fi, char *fmt, ...)
 {
 	va_list args;
diff -druNp linux-libre-2.6.37-gnu1/drivers/isdn/hisax/config.c linux-libre-2.6.38-gnu1/drivers/isdn/hisax/config.c
--- linux-libre-2.6.37-gnu1/drivers/isdn/hisax/config.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/isdn/hisax/config.c	2011-03-14 21:20:32.000000000 -0400
@@ -1917,7 +1917,7 @@ static void EChannel_proc_rcv(struct his
 #ifdef CONFIG_PCI
 #include <linux/pci.h>
 
-static struct pci_device_id hisax_pci_tbl[] __devinitdata = {
+static struct pci_device_id hisax_pci_tbl[] __devinitdata __used = {
 #ifdef CONFIG_HISAX_FRITZPCI
 	{PCI_VDEVICE(AVM,      PCI_DEVICE_ID_AVM_A1)			},
 #endif
diff -druNp linux-libre-2.6.37-gnu1/drivers/isdn/hisax/hfc_2bds0.c linux-libre-2.6.38-gnu1/drivers/isdn/hisax/hfc_2bds0.c
--- linux-libre-2.6.37-gnu1/drivers/isdn/hisax/hfc_2bds0.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/isdn/hisax/hfc_2bds0.c	2011-03-14 21:20:32.000000000 -0400
@@ -292,7 +292,7 @@ hfc_fill_fifo(struct BCState *bcs)
 	}
 	count = GetFreeFifoBytes_B(bcs);
 	if (cs->debug & L1_DEB_HSCX)
-		debugl1(cs, "hfc_fill_fifo %d count(%ld/%d),%lx",
+		debugl1(cs, "hfc_fill_fifo %d count(%u/%d),%lx",
 			bcs->channel, bcs->tx_skb->len,
 			count, current->state);
 	if (count < bcs->tx_skb->len) {
@@ -719,7 +719,7 @@ hfc_fill_dfifo(struct IsdnCardState *cs)
 	}
 	count = GetFreeFifoBytes_D(cs);
 	if (cs->debug & L1_DEB_ISAC)
-		debugl1(cs, "hfc_fill_Dfifo count(%ld/%d)",
+		debugl1(cs, "hfc_fill_Dfifo count(%u/%d)",
 			cs->tx_skb->len, count);
 	if (count < cs->tx_skb->len) {
 		if (cs->debug & L1_DEB_ISAC)
diff -druNp linux-libre-2.6.37-gnu1/drivers/isdn/hisax/hfc_2bs0.c linux-libre-2.6.38-gnu1/drivers/isdn/hisax/hfc_2bs0.c
--- linux-libre-2.6.37-gnu1/drivers/isdn/hisax/hfc_2bs0.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/isdn/hisax/hfc_2bs0.c	2011-03-14 21:20:32.000000000 -0400
@@ -282,7 +282,7 @@ hfc_fill_fifo(struct BCState *bcs)
 	    count += cs->hw.hfc.fifosize; 
 	} /* L1_MODE_TRANS */
 	if (cs->debug & L1_DEB_HSCX)
-		debugl1(cs, "hfc_fill_fifo %d count(%ld/%d)",
+		debugl1(cs, "hfc_fill_fifo %d count(%u/%d)",
 			bcs->channel, bcs->tx_skb->len,
 			count);
 	if (count < bcs->tx_skb->len) {
diff -druNp linux-libre-2.6.37-gnu1/drivers/isdn/hisax/hfc_pci.c linux-libre-2.6.38-gnu1/drivers/isdn/hisax/hfc_pci.c
--- linux-libre-2.6.37-gnu1/drivers/isdn/hisax/hfc_pci.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/isdn/hisax/hfc_pci.c	2011-03-14 21:20:32.000000000 -0400
@@ -550,7 +550,7 @@ hfcpci_fill_dfifo(struct IsdnCardState *
 		count += D_FIFO_SIZE;	/* count now contains available bytes */
 
 	if (cs->debug & L1_DEB_ISAC)
-		debugl1(cs, "hfcpci_fill_Dfifo count(%ld/%d)",
+		debugl1(cs, "hfcpci_fill_Dfifo count(%u/%d)",
 			cs->tx_skb->len, count);
 	if (count < cs->tx_skb->len) {
 		if (cs->debug & L1_DEB_ISAC)
@@ -681,7 +681,7 @@ hfcpci_fill_fifo(struct BCState *bcs)
 		count += B_FIFO_SIZE;	/* count now contains available bytes */
 
 	if (cs->debug & L1_DEB_HSCX)
-		debugl1(cs, "hfcpci_fill_fifo %d count(%ld/%d),%lx",
+		debugl1(cs, "hfcpci_fill_fifo %d count(%u/%d),%lx",
 			bcs->channel, bcs->tx_skb->len,
 			count, current->state);
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/isdn/hisax/hfc_sx.c linux-libre-2.6.38-gnu1/drivers/isdn/hisax/hfc_sx.c
--- linux-libre-2.6.37-gnu1/drivers/isdn/hisax/hfc_sx.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/isdn/hisax/hfc_sx.c	2011-03-14 21:20:32.000000000 -0400
@@ -179,7 +179,7 @@ write_fifo(struct IsdnCardState *cs, str
 	  count += fifo_size;	/* count now contains available bytes */
 
 	if (cs->debug & L1_DEB_ISAC_FIFO)
-	  debugl1(cs, "hfcsx_write_fifo %d count(%ld/%d)",
+	  debugl1(cs, "hfcsx_write_fifo %d count(%u/%d)",
 		  fifo, skb->len, count);
 	if (count < skb->len) {
 	  if (cs->debug & L1_DEB_ISAC_FIFO)
@@ -265,7 +265,7 @@ read_fifo(struct IsdnCardState *cs, u_ch
 	  count++;
 
 	  if (cs->debug & L1_DEB_ISAC_FIFO)
-	    debugl1(cs, "hfcsx_read_fifo %d count %ld)",
+	    debugl1(cs, "hfcsx_read_fifo %d count %u)",
 		    fifo, count);
 
 	  if ((count > fifo_size) || (count < 4)) {
@@ -986,7 +986,7 @@ HFCSX_l1hw(struct PStack *st, int pr, vo
 				default:
 					spin_unlock_irqrestore(&cs->lock, flags);
 					if (cs->debug & L1_DEB_WARN)
-						debugl1(cs, "hfcsx_l1hw loop invalid %4lx", arg);
+						debugl1(cs, "hfcsx_l1hw loop invalid %4lx", (unsigned long)arg);
 					return;
 			}
 			cs->hw.hfcsx.trm |= 0x80;	/* enable IOM-loop */
diff -druNp linux-libre-2.6.37-gnu1/drivers/isdn/hisax/hisax.h linux-libre-2.6.38-gnu1/drivers/isdn/hisax/hisax.h
--- linux-libre-2.6.37-gnu1/drivers/isdn/hisax/hisax.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/isdn/hisax/hisax.h	2011-03-14 21:20:32.000000000 -0400
@@ -1286,7 +1286,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)))
 void HiSax_putstatus(struct IsdnCardState *cs, char *head, char *fmt, ...);
+__attribute__((format(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-2.6.37-gnu1/drivers/isdn/hisax/ipacx.c linux-libre-2.6.38-gnu1/drivers/isdn/hisax/ipacx.c
--- linux-libre-2.6.37-gnu1/drivers/isdn/hisax/ipacx.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/isdn/hisax/ipacx.c	2011-03-14 21:20:32.000000000 -0400
@@ -717,7 +717,7 @@ bch_mode(struct BCState *bcs, int mode,
 
         bc = bc ? 1 : 0;  // in case bc is greater than 1
 	if (cs->debug & L1_DEB_HSCX)
-		debugl1(cs, "mode_bch() switch B-% mode %d chan %d", hscx, mode, bc);
+		debugl1(cs, "mode_bch() switch B-%d mode %d chan %d", hscx, mode, bc);
 	bcs->mode = mode;
 	bcs->channel = bc;
   
diff -druNp linux-libre-2.6.37-gnu1/drivers/isdn/hisax/isar.c linux-libre-2.6.38-gnu1/drivers/isdn/hisax/isar.c
--- linux-libre-2.6.37-gnu1/drivers/isdn/hisax/isar.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/isdn/hisax/isar.c	2011-03-14 21:20:32.000000000 -0400
@@ -189,7 +189,7 @@ ISARVersion(struct IsdnCardState *cs, ch
 static int
 isar_load_firmware(struct IsdnCardState *cs, u_char __user *buf)
 {
-	int ret, size, cnt, debug;
+	int cfu_ret, ret, size, cnt, debug;
 	u_char len, nom, noc;
 	u_short sadr, left, *sp;
 	u_char __user *p = buf;
@@ -212,9 +212,10 @@ isar_load_firmware(struct IsdnCardState
 	cs->debug &= ~(L1_DEB_HSCX | L1_DEB_HSCX_FIFO);
 #endif
 	
-	if ((ret = copy_from_user(&size, p, sizeof(int)))) {
-		printk(KERN_ERR"isar_load_firmware copy_from_user ret %d\n", ret);
-		return ret;
+	cfu_ret = copy_from_user(&size, p, sizeof(int));
+	if (cfu_ret) {
+		printk(KERN_ERR"isar_load_firmware copy_from_user ret %d\n", cfu_ret);
+		return -EFAULT;
 	}
 	p += sizeof(int);
 	printk(KERN_DEBUG"isar_load_firmware size: %d\n", size);
@@ -953,7 +954,7 @@ isar_pump_statev_modem(struct BCState *b
 			break;
 		case PSEV_GSTN_CLR:
 			if (cs->debug & L1_DEB_HSCX)
-				debugl1(cs, "pump stev GSTN CLEAR", devt);
+				debugl1(cs, "pump stev GSTN CLEAR");
 			break;
 		default:
 			if (cs->debug & L1_DEB_HSCX)
@@ -1268,7 +1269,7 @@ isar_int_main(struct IsdnCardState *cs)
 static void
 ftimer_handler(struct BCState *bcs) {
 	if (bcs->cs->debug)
-		debugl1(bcs->cs, "ftimer flags %04x",
+		debugl1(bcs->cs, "ftimer flags %04lx",
 			bcs->Flag);
 	test_and_clear_bit(BC_FLG_FTI_RUN, &bcs->Flag);
 	if (test_and_clear_bit(BC_FLG_LL_CONN, &bcs->Flag)) {
@@ -1748,7 +1749,7 @@ isar_auxcmd(struct IsdnCardState *cs, is
 	struct BCState *bcs;
 
 	if (cs->debug & L1_DEB_HSCX)
-		debugl1(cs, "isar_auxcmd cmd/ch %x/%d", ic->command, ic->arg);
+		debugl1(cs, "isar_auxcmd cmd/ch %x/%ld", ic->command, ic->arg);
 	switch (ic->command) {
 		case (ISDN_CMD_FAXCMD):
 			bcs = cs->channel[ic->arg].bcs;
diff -druNp linux-libre-2.6.37-gnu1/drivers/isdn/hisax/isdnl1.h linux-libre-2.6.38-gnu1/drivers/isdn/hisax/isdnl1.h
--- linux-libre-2.6.37-gnu1/drivers/isdn/hisax/isdnl1.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/isdn/hisax/isdnl1.h	2011-03-14 21:20:32.000000000 -0400
@@ -21,6 +21,7 @@
 #define B_XMTBUFREADY	1
 #define B_ACKPENDING	2
 
+__attribute__((format(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-2.6.37-gnu1/drivers/isdn/hisax/isdnl2.c linux-libre-2.6.38-gnu1/drivers/isdn/hisax/isdnl2.c
--- linux-libre-2.6.37-gnu1/drivers/isdn/hisax/isdnl2.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/isdn/hisax/isdnl2.c	2011-03-14 21:20:32.000000000 -0400
@@ -1247,10 +1247,10 @@ static void
 l2_pull_iqueue(struct FsmInst *fi, int event, void *arg)
 {
 	struct PStack *st = fi->userdata;
-	struct sk_buff *skb, *oskb;
+	struct sk_buff *skb;
 	struct Layer2 *l2 = &st->l2;
 	u_char header[MAX_HEADER_LEN];
-	int i;
+	int i, hdr_space_needed;
 	int unsigned p1;
 	u_long flags;
 
@@ -1261,6 +1261,16 @@ l2_pull_iqueue(struct FsmInst *fi, int e
 	if (!skb)
 		return;
 
+	hdr_space_needed = l2headersize(l2, 0);
+	if (hdr_space_needed > skb_headroom(skb)) {
+		struct sk_buff *orig_skb = skb;
+
+		skb = skb_realloc_headroom(skb, hdr_space_needed);
+		if (!skb) {
+			dev_kfree_skb(orig_skb);
+			return;
+		}
+	}
 	spin_lock_irqsave(&l2->lock, flags);
 	if(test_bit(FLG_MOD128, &l2->flag))
 		p1 = (l2->vs - l2->va) % 128;
@@ -1285,19 +1295,7 @@ l2_pull_iqueue(struct FsmInst *fi, int e
 		l2->vs = (l2->vs + 1) % 8;
 	}
 	spin_unlock_irqrestore(&l2->lock, flags);
-	p1 = skb->data - skb->head;
-	if (p1 >= i)
-		memcpy(skb_push(skb, i), header, i);
-	else {
-		printk(KERN_WARNING
-		"isdl2 pull_iqueue skb header(%d/%d) too short\n", i, p1);
-		oskb = skb;
-		skb = alloc_skb(oskb->len + i, GFP_ATOMIC);
-		memcpy(skb_put(skb, i), header, i);
-		skb_copy_from_linear_data(oskb,
-					  skb_put(skb, oskb->len), oskb->len);
-		dev_kfree_skb(oskb);
-	}
+	memcpy(skb_push(skb, i), header, i);
 	st->l2.l2l1(st, PH_PULL | INDICATION, skb);
 	test_and_clear_bit(FLG_ACK_PEND, &st->l2.flag);
 	if (!test_and_set_bit(FLG_T200_RUN, &st->l2.flag)) {
diff -druNp linux-libre-2.6.37-gnu1/drivers/isdn/hisax/isdnl3.c linux-libre-2.6.38-gnu1/drivers/isdn/hisax/isdnl3.c
--- linux-libre-2.6.37-gnu1/drivers/isdn/hisax/isdnl3.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/isdn/hisax/isdnl3.c	2011-03-14 21:20:32.000000000 -0400
@@ -66,7 +66,7 @@ static char *strL3Event[] =
 	"EV_TIMEOUT",
 };
 
-static void
+static __attribute__((format(printf, 2, 3))) void
 l3m_debug(struct FsmInst *fi, char *fmt, ...)
 {
 	va_list args;
diff -druNp linux-libre-2.6.37-gnu1/drivers/isdn/hisax/netjet.c linux-libre-2.6.38-gnu1/drivers/isdn/hisax/netjet.c
--- linux-libre-2.6.37-gnu1/drivers/isdn/hisax/netjet.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/isdn/hisax/netjet.c	2011-03-14 21:20:32.000000000 -0400
@@ -254,7 +254,7 @@ static int make_raw_data(struct BCState
 		val >>= 1;
 	}
 	if (bcs->cs->debug & L1_DEB_HSCX)
-		debugl1(bcs->cs,"tiger make_raw: in %ld out %d.%d",
+		debugl1(bcs->cs,"tiger make_raw: in %u out %d.%d",
 			bcs->tx_skb->len, s_cnt, bitcnt);
 	if (bitcnt) {
 		while (8>bitcnt++) {
@@ -361,7 +361,7 @@ static int make_raw_data_56k(struct BCSt
 		val >>= 1;
 	}
 	if (bcs->cs->debug & L1_DEB_HSCX)
-		debugl1(bcs->cs,"tiger make_raw_56k: in %ld out %d.%d",
+		debugl1(bcs->cs,"tiger make_raw_56k: in %u out %d.%d",
 			bcs->tx_skb->len, s_cnt, bitcnt);
 	if (bitcnt) {
 		while (8>bitcnt++) {
@@ -612,7 +612,7 @@ void netjet_fill_dma(struct BCState *bcs
 	if (!bcs->tx_skb)
 		return;
 	if (bcs->cs->debug & L1_DEB_HSCX)
-		debugl1(bcs->cs,"tiger fill_dma1: c%d %4x", bcs->channel,
+		debugl1(bcs->cs,"tiger fill_dma1: c%d %4lx", bcs->channel,
 			bcs->Flag);
 	if (test_and_set_bit(BC_FLG_BUSY, &bcs->Flag))
 		return;
@@ -625,7 +625,7 @@ void netjet_fill_dma(struct BCState *bcs
 			return;		
 	};
 	if (bcs->cs->debug & L1_DEB_HSCX)
-		debugl1(bcs->cs,"tiger fill_dma2: c%d %4x", bcs->channel,
+		debugl1(bcs->cs,"tiger fill_dma2: c%d %4lx", bcs->channel,
 			bcs->Flag);
 	if (test_and_clear_bit(BC_FLG_NOFRAME, &bcs->Flag)) {
 		write_raw(bcs, bcs->hw.tiger.sendp, bcs->hw.tiger.free);
@@ -667,7 +667,7 @@ void netjet_fill_dma(struct BCState *bcs
 		write_raw(bcs, p, cnt);
 	}
 	if (bcs->cs->debug & L1_DEB_HSCX)
-		debugl1(bcs->cs,"tiger fill_dma3: c%d %4x", bcs->channel,
+		debugl1(bcs->cs,"tiger fill_dma3: c%d %4lx", bcs->channel,
 			bcs->Flag);
 }
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/isdn/hisax/st5481_d.c linux-libre-2.6.38-gnu1/drivers/isdn/hisax/st5481_d.c
--- linux-libre-2.6.37-gnu1/drivers/isdn/hisax/st5481_d.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/isdn/hisax/st5481_d.c	2011-03-14 21:20:32.000000000 -0400
@@ -167,7 +167,8 @@ static struct FsmNode L1FnList[] __initd
 	{ST_L1_F8, EV_IND_RSY,           l1_ignore},
 };
 
-static void l1m_debug(struct FsmInst *fi, char *fmt, ...)
+static __attribute__((format(printf, 2, 3)))
+void l1m_debug(struct FsmInst *fi, char *fmt, ...)
 {
 	va_list args;
 	char buf[256];
@@ -269,7 +270,8 @@ static char *strDoutEvent[] =
 	"EV_DOUT_UNDERRUN",
 };
 
-static void dout_debug(struct FsmInst *fi, char *fmt, ...)
+static __attribute__((format(printf, 2, 3)))
+void dout_debug(struct FsmInst *fi, char *fmt, ...)
 {
 	va_list args;
 	char buf[256];
diff -druNp linux-libre-2.6.37-gnu1/drivers/isdn/hysdn/hysdn_defs.h linux-libre-2.6.38-gnu1/drivers/isdn/hysdn/hysdn_defs.h
--- linux-libre-2.6.37-gnu1/drivers/isdn/hysdn/hysdn_defs.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/isdn/hysdn/hysdn_defs.h	2011-03-14 21:20:32.000000000 -0400
@@ -227,7 +227,6 @@ extern hysdn_card *card_root;	/* pointer
 /*************************/
 /* im/exported functions */
 /*************************/
-extern char *hysdn_getrev(const char *);
 
 /* hysdn_procconf.c */
 extern int hysdn_procconf_init(void);	/* init proc config filesys */
@@ -259,7 +258,6 @@ extern int hysdn_tx_cfgline(hysdn_card *
 
 /* hysdn_net.c */
 extern unsigned int hynet_enable; 
-extern char *hysdn_net_revision;
 extern int hysdn_net_create(hysdn_card *);	/* create a new net device */
 extern int hysdn_net_release(hysdn_card *);	/* delete the device */
 extern char *hysdn_net_getname(hysdn_card *);	/* get name of net interface */
diff -druNp linux-libre-2.6.37-gnu1/drivers/isdn/hysdn/hysdn_init.c linux-libre-2.6.38-gnu1/drivers/isdn/hysdn/hysdn_init.c
--- linux-libre-2.6.37-gnu1/drivers/isdn/hysdn/hysdn_init.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/isdn/hysdn/hysdn_init.c	2011-03-14 21:20:32.000000000 -0400
@@ -36,7 +36,6 @@ MODULE_DESCRIPTION("ISDN4Linux: Driver f
 MODULE_AUTHOR("Werner Cornelius");
 MODULE_LICENSE("GPL");
 
-static char *hysdn_init_revision = "$Revision: 1.6.6.6 $";
 static int cardmax;		/* number of found cards */
 hysdn_card *card_root = NULL;	/* pointer to first card */
 static hysdn_card *card_last = NULL;	/* pointer to first card */
@@ -49,25 +48,6 @@ static hysdn_card *card_last = NULL;	/*
 /* Additionally newer versions may be activated without rebooting.          */
 /****************************************************************************/
 
-/******************************************************/
-/* extract revision number from string for log output */
-/******************************************************/
-char *
-hysdn_getrev(const char *revision)
-{
-	char *rev;
-	char *p;
-
-	if ((p = strchr(revision, ':'))) {
-		rev = p + 2;
-		p = strchr(rev, '$');
-		*--p = 0;
-	} else
-		rev = "???";
-	return rev;
-}
-
-
 /****************************************************************************/
 /* init_module is called once when the module is loaded to do all necessary */
 /* things like autodetect...                                                */
@@ -175,13 +155,9 @@ static int hysdn_have_procfs;
 static int __init
 hysdn_init(void)
 {
-	char tmp[50];
 	int rc;
 
-	strcpy(tmp, hysdn_init_revision);
-	printk(KERN_NOTICE "HYSDN: module Rev: %s loaded\n", hysdn_getrev(tmp));
-	strcpy(tmp, hysdn_net_revision);
-	printk(KERN_NOTICE "HYSDN: network interface Rev: %s \n", hysdn_getrev(tmp));
+	printk(KERN_NOTICE "HYSDN: module loaded\n");
 
 	rc = pci_register_driver(&hysdn_pci_driver);
 	if (rc)
diff -druNp linux-libre-2.6.37-gnu1/drivers/isdn/hysdn/hysdn_net.c linux-libre-2.6.38-gnu1/drivers/isdn/hysdn/hysdn_net.c
--- linux-libre-2.6.37-gnu1/drivers/isdn/hysdn/hysdn_net.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/isdn/hysdn/hysdn_net.c	2011-03-14 21:20:32.000000000 -0400
@@ -26,9 +26,6 @@
 unsigned int hynet_enable = 0xffffffff; 
 module_param(hynet_enable, uint, 0);
 
-/* store the actual version for log reporting */
-char *hysdn_net_revision = "$Revision: 1.8.6.4 $";
-
 #define MAX_SKB_BUFFERS 20	/* number of buffers for keeping TX-data */
 
 /****************************************************************************/
diff -druNp linux-libre-2.6.37-gnu1/drivers/isdn/hysdn/hysdn_procconf.c linux-libre-2.6.38-gnu1/drivers/isdn/hysdn/hysdn_procconf.c
--- linux-libre-2.6.37-gnu1/drivers/isdn/hysdn/hysdn_procconf.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/isdn/hysdn/hysdn_procconf.c	2011-03-14 21:20:32.000000000 -0400
@@ -23,7 +23,6 @@
 #include "hysdn_defs.h"
 
 static DEFINE_MUTEX(hysdn_conf_mutex);
-static char *hysdn_procconf_revision = "$Revision: 1.8.6.4 $";
 
 #define INFO_OUT_LEN 80		/* length of info line including lf */
 
@@ -404,7 +403,7 @@ hysdn_procconf_init(void)
 		card = card->next;	/* next entry */
 	}
 
-	printk(KERN_NOTICE "HYSDN: procfs Rev. %s initialised\n", hysdn_getrev(hysdn_procconf_revision));
+	printk(KERN_NOTICE "HYSDN: procfs initialised\n");
 	return (0);
 }				/* hysdn_procconf_init */
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/isdn/i4l/isdn_concap.c linux-libre-2.6.38-gnu1/drivers/isdn/i4l/isdn_concap.c
--- linux-libre-2.6.37-gnu1/drivers/isdn/i4l/isdn_concap.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/isdn/i4l/isdn_concap.c	2011-03-14 21:20:32.000000000 -0400
@@ -61,7 +61,7 @@ static int isdn_concap_dl_data_req(struc
 static int isdn_concap_dl_connect_req(struct concap_proto *concap)
 {
 	struct net_device *ndev = concap -> net_dev;
-	isdn_net_local *lp = (isdn_net_local *) netdev_priv(ndev);
+	isdn_net_local *lp = netdev_priv(ndev);
 	int ret;
 	IX25DEBUG( "isdn_concap_dl_connect_req: %s \n", ndev -> name);
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/isdn/i4l/isdn_net.c linux-libre-2.6.38-gnu1/drivers/isdn/i4l/isdn_net.c
--- linux-libre-2.6.37-gnu1/drivers/isdn/i4l/isdn_net.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/isdn/i4l/isdn_net.c	2011-03-14 21:20:32.000000000 -0400
@@ -827,7 +827,7 @@ isdn_net_dial(void)
 void
 isdn_net_hangup(struct net_device *d)
 {
-	isdn_net_local *lp = (isdn_net_local *) netdev_priv(d);
+	isdn_net_local *lp = netdev_priv(d);
 	isdn_ctrl cmd;
 #ifdef CONFIG_ISDN_X25
 	struct concap_proto *cprot = lp->netdev->cprot;
@@ -1052,7 +1052,7 @@ isdn_net_xmit(struct net_device *ndev, s
 {
 	isdn_net_dev *nd;
 	isdn_net_local *slp;
-	isdn_net_local *lp = (isdn_net_local *) netdev_priv(ndev);
+	isdn_net_local *lp = netdev_priv(ndev);
 	int retv = NETDEV_TX_OK;
 
 	if (((isdn_net_local *) netdev_priv(ndev))->master) {
@@ -1116,7 +1116,7 @@ isdn_net_xmit(struct net_device *ndev, s
 static void
 isdn_net_adjust_hdr(struct sk_buff *skb, struct net_device *dev)
 {
-	isdn_net_local *lp = (isdn_net_local *) netdev_priv(dev);
+	isdn_net_local *lp = netdev_priv(dev);
 	if (!skb)
 		return;
 	if (lp->p_encap == ISDN_NET_ENCAP_ETHER) {
@@ -1131,7 +1131,7 @@ isdn_net_adjust_hdr(struct sk_buff *skb,
 
 static void isdn_net_tx_timeout(struct net_device * ndev)
 {
-	isdn_net_local *lp = (isdn_net_local *) netdev_priv(ndev);
+	isdn_net_local *lp = netdev_priv(ndev);
 
 	printk(KERN_WARNING "isdn_tx_timeout dev %s dialstate %d\n", ndev->name, lp->dialstate);
 	if (!lp->dialstate){
@@ -1165,7 +1165,7 @@ static void isdn_net_tx_timeout(struct n
 static netdev_tx_t
 isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev)
 {
-	isdn_net_local *lp = (isdn_net_local *) netdev_priv(ndev);
+	isdn_net_local *lp = netdev_priv(ndev);
 #ifdef CONFIG_ISDN_X25
 	struct concap_proto * cprot = lp -> netdev -> cprot;
 /* At this point hard_start_xmit() passes control to the encapsulation
@@ -1347,7 +1347,7 @@ isdn_net_close(struct net_device *dev)
 static struct net_device_stats *
 isdn_net_get_stats(struct net_device *dev)
 {
-	isdn_net_local *lp = (isdn_net_local *) netdev_priv(dev);
+	isdn_net_local *lp = netdev_priv(dev);
 	return &lp->stats;
 }
 
@@ -1426,7 +1426,7 @@ isdn_net_ciscohdlck_alloc_skb(isdn_net_l
 static int
 isdn_ciscohdlck_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 {
-	isdn_net_local *lp = (isdn_net_local *) netdev_priv(dev);
+	isdn_net_local *lp = netdev_priv(dev);
 	unsigned long len = 0;
 	unsigned long expires = 0;
 	int tmp = 0;
@@ -1493,7 +1493,7 @@ isdn_ciscohdlck_dev_ioctl(struct net_dev
 static int isdn_net_ioctl(struct net_device *dev,
 			  struct ifreq *ifr, int cmd)
 {
-	isdn_net_local *lp = (isdn_net_local *) netdev_priv(dev);
+	isdn_net_local *lp = netdev_priv(dev);
 
 	switch (lp->p_encap) {
 #ifdef CONFIG_ISDN_PPP
@@ -1786,7 +1786,7 @@ isdn_net_ciscohdlck_receive(isdn_net_loc
 static void
 isdn_net_receive(struct net_device *ndev, struct sk_buff *skb)
 {
-	isdn_net_local *lp = (isdn_net_local *) netdev_priv(ndev);
+	isdn_net_local *lp = netdev_priv(ndev);
 	isdn_net_local *olp = lp;	/* original 'lp' */
 #ifdef CONFIG_ISDN_X25
 	struct concap_proto *cprot = lp -> netdev -> cprot;
@@ -1800,7 +1800,7 @@ isdn_net_receive(struct net_device *ndev
 		 * handle master's statistics and hangup-timeout
 		 */
 		ndev = lp->master;
-		lp = (isdn_net_local *) netdev_priv(ndev);
+		lp = netdev_priv(ndev);
 		lp->stats.rx_packets++;
 		lp->stats.rx_bytes += skb->len;
 	}
diff -druNp linux-libre-2.6.37-gnu1/drivers/isdn/i4l/isdn_ppp.c linux-libre-2.6.38-gnu1/drivers/isdn/i4l/isdn_ppp.c
--- linux-libre-2.6.37-gnu1/drivers/isdn/i4l/isdn_ppp.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/isdn/i4l/isdn_ppp.c	2011-03-14 21:20:32.000000000 -0400
@@ -1147,15 +1147,14 @@ isdn_ppp_push_higher(isdn_net_dev * net_
 	}
 
 	if (is->pass_filter
-	    && sk_run_filter(skb, is->pass_filter, is->pass_len) == 0) {
+	    && sk_run_filter(skb, is->pass_filter) == 0) {
 		if (is->debug & 0x2)
 			printk(KERN_DEBUG "IPPP: inbound frame filtered.\n");
 		kfree_skb(skb);
 		return;
 	}
 	if (!(is->active_filter
-	      && sk_run_filter(skb, is->active_filter,
-	                       is->active_len) == 0)) {
+	      && sk_run_filter(skb, is->active_filter) == 0)) {
 		if (is->debug & 0x2)
 			printk(KERN_DEBUG "IPPP: link-active filter: reseting huptimer.\n");
 		lp->huptimer = 0;
@@ -1221,7 +1220,7 @@ isdn_ppp_xmit(struct sk_buff *skb, struc
 	struct ippp_struct *ipt,*ipts;
 	int slot, retval = NETDEV_TX_OK;
 
-	mlp = (isdn_net_local *) netdev_priv(netdev);
+	mlp = netdev_priv(netdev);
 	nd = mlp->netdev;       /* get master lp */
 
 	slot = mlp->ppp_slot;
@@ -1294,15 +1293,14 @@ isdn_ppp_xmit(struct sk_buff *skb, struc
 	}
 
 	if (ipt->pass_filter
-	    && sk_run_filter(skb, ipt->pass_filter, ipt->pass_len) == 0) {
+	    && sk_run_filter(skb, ipt->pass_filter) == 0) {
 		if (ipt->debug & 0x4)
 			printk(KERN_DEBUG "IPPP: outbound frame filtered.\n");
 		kfree_skb(skb);
 		goto unlock;
 	}
 	if (!(ipt->active_filter
-	      && sk_run_filter(skb, ipt->active_filter,
-		               ipt->active_len) == 0)) {
+	      && sk_run_filter(skb, ipt->active_filter) == 0)) {
 		if (ipt->debug & 0x4)
 			printk(KERN_DEBUG "IPPP: link-active filter: reseting huptimer.\n");
 		lp->huptimer = 0;
@@ -1492,9 +1490,9 @@ int isdn_ppp_autodial_filter(struct sk_b
 	}
 	
 	drop |= is->pass_filter
-	        && sk_run_filter(skb, is->pass_filter, is->pass_len) == 0;
+	        && sk_run_filter(skb, is->pass_filter) == 0;
 	drop |= is->active_filter
-	        && sk_run_filter(skb, is->active_filter, is->active_len) == 0;
+	        && sk_run_filter(skb, is->active_filter) == 0;
 	
 	skb_push(skb, IPPP_MAX_HEADER - 4);
 	return drop;
@@ -1985,7 +1983,7 @@ isdn_ppp_dev_ioctl_stats(int slot, struc
 {
 	struct ppp_stats __user *res = ifr->ifr_data;
 	struct ppp_stats t;
-	isdn_net_local *lp = (isdn_net_local *) netdev_priv(dev);
+	isdn_net_local *lp = netdev_priv(dev);
 
 	if (!access_ok(VERIFY_WRITE, res, sizeof(struct ppp_stats)))
 		return -EFAULT;
@@ -2024,7 +2022,7 @@ isdn_ppp_dev_ioctl(struct net_device *de
 {
 	int error=0;
 	int len;
-	isdn_net_local *lp = (isdn_net_local *) netdev_priv(dev);
+	isdn_net_local *lp = netdev_priv(dev);
 
 
 	if (lp->p_encap != ISDN_NET_ENCAP_SYNCPPP)
@@ -2091,7 +2089,7 @@ isdn_ppp_dial_slave(char *name)
 
 	sdev = lp->slave;
 	while (sdev) {
-		isdn_net_local *mlp = (isdn_net_local *) netdev_priv(sdev);
+		isdn_net_local *mlp = netdev_priv(sdev);
 		if (!(mlp->flags & ISDN_NET_CONNECTED))
 			break;
 		sdev = mlp->slave;
@@ -2099,7 +2097,7 @@ isdn_ppp_dial_slave(char *name)
 	if (!sdev)
 		return 2;
 
-	isdn_net_dial_req((isdn_net_local *) netdev_priv(sdev));
+	isdn_net_dial_req(netdev_priv(sdev));
 	return 0;
 #else
 	return -1;
@@ -2122,7 +2120,7 @@ isdn_ppp_hangup_slave(char *name)
 
 	sdev = lp->slave;
 	while (sdev) {
-		isdn_net_local *mlp = (isdn_net_local *) netdev_priv(sdev);
+		isdn_net_local *mlp = netdev_priv(sdev);
 
 		if (mlp->slave) { /* find last connected link in chain */
 			isdn_net_local *nlp = ISDN_SLAVE_PRIV(mlp);
diff -druNp linux-libre-2.6.37-gnu1/drivers/isdn/icn/icn.c linux-libre-2.6.38-gnu1/drivers/isdn/icn/icn.c
--- linux-libre-2.6.37-gnu1/drivers/isdn/icn/icn.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/isdn/icn/icn.c	2011-03-14 21:20:32.000000000 -0400
@@ -1627,7 +1627,7 @@ __setup("icn=", icn_setup);
 static int __init icn_init(void)
 {
 	char *p;
-	char rev[20];
+	char rev[21];
 
 	memset(&dev, 0, sizeof(icn_dev));
 	dev.memaddr = (membase & 0x0ffc000);
@@ -1638,6 +1638,7 @@ static int __init icn_init(void)
 
 	if ((p = strchr(revision, ':'))) {
 		strncpy(rev, p + 1, 20);
+		rev[20] = '\0';
 		p = strchr(rev, '$');
 		if (p)
 			*p = 0;
diff -druNp linux-libre-2.6.37-gnu1/drivers/isdn/mISDN/dsp_cmx.c linux-libre-2.6.38-gnu1/drivers/isdn/mISDN/dsp_cmx.c
--- linux-libre-2.6.37-gnu1/drivers/isdn/mISDN/dsp_cmx.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/isdn/mISDN/dsp_cmx.c	2011-03-14 21:20:32.000000000 -0400
@@ -112,7 +112,7 @@
  * Disable rx-data:
  * If cmx is realized in hardware, rx data will be disabled if requested by
  * the upper layer. If dtmf decoding is done by software and enabled, rx data
- * will not be diabled but blocked to the upper layer.
+ * will not be disabled but blocked to the upper layer.
  *
  * HFC conference engine:
  * If it is possible to realize all features using hardware, hardware will be
diff -druNp linux-libre-2.6.37-gnu1/drivers/isdn/mISDN/hwchannel.c linux-libre-2.6.38-gnu1/drivers/isdn/mISDN/hwchannel.c
--- linux-libre-2.6.37-gnu1/drivers/isdn/mISDN/hwchannel.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/isdn/mISDN/hwchannel.c	2011-03-14 21:20:32.000000000 -0400
@@ -110,7 +110,7 @@ mISDN_freedchannel(struct dchannel *ch)
 	}
 	skb_queue_purge(&ch->squeue);
 	skb_queue_purge(&ch->rqueue);
-	flush_scheduled_work();
+	flush_work_sync(&ch->workq);
 	return 0;
 }
 EXPORT_SYMBOL(mISDN_freedchannel);
@@ -143,7 +143,7 @@ mISDN_freebchannel(struct bchannel *ch)
 	mISDN_clear_bchannel(ch);
 	skb_queue_purge(&ch->rqueue);
 	ch->rcount = 0;
-	flush_scheduled_work();
+	flush_work_sync(&ch->workq);
 	return 0;
 }
 EXPORT_SYMBOL(mISDN_freebchannel);
diff -druNp linux-libre-2.6.37-gnu1/drivers/isdn/mISDN/l1oip_core.c linux-libre-2.6.38-gnu1/drivers/isdn/mISDN/l1oip_core.c
--- linux-libre-2.6.37-gnu1/drivers/isdn/mISDN/l1oip_core.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/isdn/mISDN/l1oip_core.c	2011-03-14 21:20:32.000000000 -0400
@@ -1269,6 +1269,8 @@ release_card(struct l1oip *hc)
 	if (timer_pending(&hc->timeout_tl))
 		del_timer(&hc->timeout_tl);
 
+	cancel_work_sync(&hc->workq);
+
 	if (hc->socket_thread)
 		l1oip_socket_close(hc);
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/isdn/mISDN/layer1.c linux-libre-2.6.38-gnu1/drivers/isdn/mISDN/layer1.c
--- linux-libre-2.6.37-gnu1/drivers/isdn/mISDN/layer1.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/isdn/mISDN/layer1.c	2011-03-14 21:20:32.000000000 -0400
@@ -99,12 +99,16 @@ static void
 l1m_debug(struct FsmInst *fi, char *fmt, ...)
 {
 	struct layer1 *l1 = fi->userdata;
+	struct va_format vaf;
 	va_list va;
 
 	va_start(va, fmt);
-	printk(KERN_DEBUG "%s: ", dev_name(&l1->dch->dev.dev));
-	vprintk(fmt, va);
-	printk("\n");
+
+	vaf.fmt = fmt;
+	vaf.va = &va;
+
+	printk(KERN_DEBUG "%s: %pV\n", dev_name(&l1->dch->dev.dev), &vaf);
+
 	va_end(va);
 }
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/isdn/mISDN/layer2.c linux-libre-2.6.38-gnu1/drivers/isdn/mISDN/layer2.c
--- linux-libre-2.6.37-gnu1/drivers/isdn/mISDN/layer2.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/isdn/mISDN/layer2.c	2011-03-14 21:20:32.000000000 -0400
@@ -95,14 +95,20 @@ static void
 l2m_debug(struct FsmInst *fi, char *fmt, ...)
 {
 	struct layer2 *l2 = fi->userdata;
+	struct va_format vaf;
 	va_list va;
 
 	if (!(*debug & DEBUG_L2_FSM))
 		return;
+
 	va_start(va, fmt);
-	printk(KERN_DEBUG "l2 (sapi %d tei %d): ", l2->sapi, l2->tei);
-	vprintk(fmt, va);
-	printk("\n");
+
+	vaf.fmt = fmt;
+	vaf.va = &va;
+
+	printk(KERN_DEBUG "l2 (sapi %d tei %d): %pV\n",
+	       l2->sapi, l2->tei, &vaf);
+
 	va_end(va);
 }
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/isdn/mISDN/tei.c linux-libre-2.6.38-gnu1/drivers/isdn/mISDN/tei.c
--- linux-libre-2.6.37-gnu1/drivers/isdn/mISDN/tei.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/isdn/mISDN/tei.c	2011-03-14 21:20:32.000000000 -0400
@@ -79,14 +79,19 @@ static void
 da_debug(struct FsmInst *fi, char *fmt, ...)
 {
 	struct manager	*mgr = fi->userdata;
+	struct va_format vaf;
 	va_list va;
 
 	if (!(*debug & DEBUG_L2_TEIFSM))
 		return;
+
 	va_start(va, fmt);
-	printk(KERN_DEBUG "mgr(%d): ", mgr->ch.st->dev->id);
-	vprintk(fmt, va);
-	printk("\n");
+
+	vaf.fmt = fmt;
+	vaf.va = &va;
+
+	printk(KERN_DEBUG "mgr(%d): %pV\n", mgr->ch.st->dev->id, &vaf);
+
 	va_end(va);
 }
 
@@ -223,14 +228,20 @@ static void
 tei_debug(struct FsmInst *fi, char *fmt, ...)
 {
 	struct teimgr	*tm = fi->userdata;
+	struct va_format vaf;
 	va_list va;
 
 	if (!(*debug & DEBUG_L2_TEIFSM))
 		return;
+
 	va_start(va, fmt);
-	printk(KERN_DEBUG "sapi(%d) tei(%d): ", tm->l2->sapi, tm->l2->tei);
-	vprintk(fmt, va);
-	printk("\n");
+
+	vaf.fmt = fmt;
+	vaf.va = &va;
+
+	printk(KERN_DEBUG "sapi(%d) tei(%d): %pV\n",
+	       tm->l2->sapi, tm->l2->tei, &vaf);
+
 	va_end(va);
 }
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/Kconfig linux-libre-2.6.38-gnu1/drivers/Kconfig
--- linux-libre-2.6.37-gnu1/drivers/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -26,6 +26,8 @@ source "drivers/ata/Kconfig"
 
 source "drivers/md/Kconfig"
 
+source "drivers/target/Kconfig"
+
 source "drivers/message/fusion/Kconfig"
 
 source "drivers/firewire/Kconfig"
@@ -88,6 +90,8 @@ source "drivers/memstick/Kconfig"
 
 source "drivers/leds/Kconfig"
 
+source "drivers/nfc/Kconfig"
+
 source "drivers/accessibility/Kconfig"
 
 source "drivers/infiniband/Kconfig"
@@ -111,4 +115,6 @@ source "drivers/xen/Kconfig"
 source "drivers/staging/Kconfig"
 
 source "drivers/platform/Kconfig"
+
+source "drivers/clk/Kconfig"
 endmenu
diff -druNp linux-libre-2.6.37-gnu1/drivers/leds/leds-lp5521.c linux-libre-2.6.38-gnu1/drivers/leds/leds-lp5521.c
--- linux-libre-2.6.37-gnu1/drivers/leds/leds-lp5521.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/leds/leds-lp5521.c	2011-03-14 21:20:32.000000000 -0400
@@ -98,7 +98,6 @@
 #define LP5521_EXT_CLK_USED		0x08
 
 struct lp5521_engine {
-	const struct attribute_group *attributes;
 	int		id;
 	u8		mode;
 	u8		prog_page;
@@ -225,25 +224,22 @@ static int lp5521_set_led_current(struct
 		    curr);
 }
 
-static void lp5521_init_engine(struct lp5521_chip *chip,
-			const struct attribute_group *attr_group)
+static void lp5521_init_engine(struct lp5521_chip *chip)
 {
 	int i;
 	for (i = 0; i < ARRAY_SIZE(chip->engines); i++) {
 		chip->engines[i].id = i + 1;
 		chip->engines[i].engine_mask = LP5521_ENG_MASK_BASE >> (i * 2);
 		chip->engines[i].prog_page = i;
-		chip->engines[i].attributes = &attr_group[i];
 	}
 }
 
-static int lp5521_configure(struct i2c_client *client,
-			const struct attribute_group *attr_group)
+static int lp5521_configure(struct i2c_client *client)
 {
 	struct lp5521_chip *chip = i2c_get_clientdata(client);
 	int ret;
 
-	lp5521_init_engine(chip, attr_group);
+	lp5521_init_engine(chip);
 
 	/* Set all PWMs to direct control mode */
 	ret = lp5521_write(client, LP5521_REG_OP_MODE, 0x3F);
@@ -329,9 +325,6 @@ static int lp5521_detect(struct i2c_clie
 /* Set engine mode and create appropriate sysfs attributes, if required. */
 static int lp5521_set_mode(struct lp5521_engine *engine, u8 mode)
 {
-	struct lp5521_chip *chip = engine_to_lp5521(engine);
-	struct i2c_client *client = chip->client;
-	struct device *dev = &client->dev;
 	int ret = 0;
 
 	/* if in that mode already do nothing, except for run */
@@ -343,18 +336,10 @@ static int lp5521_set_mode(struct lp5521
 	} else if (mode == LP5521_CMD_LOAD) {
 		lp5521_set_engine_mode(engine, LP5521_CMD_DISABLED);
 		lp5521_set_engine_mode(engine, LP5521_CMD_LOAD);
-
-		ret = sysfs_create_group(&dev->kobj, engine->attributes);
-		if (ret)
-			return ret;
 	} else if (mode == LP5521_CMD_DISABLED) {
 		lp5521_set_engine_mode(engine, LP5521_CMD_DISABLED);
 	}
 
-	/* remove load attribute from sysfs if not in load mode */
-	if (engine->mode == LP5521_CMD_LOAD && mode != LP5521_CMD_LOAD)
-		sysfs_remove_group(&dev->kobj, engine->attributes);
-
 	engine->mode = mode;
 
 	return ret;
@@ -373,6 +358,8 @@ static int lp5521_do_store_load(struct l
 	while ((offset < len - 1) && (i < LP5521_PROGRAM_LENGTH)) {
 		/* separate sscanfs because length is working only for %s */
 		ret = sscanf(buf + offset, "%2s%n ", c, &nrchars);
+		if (ret != 2)
+			goto fail;
 		ret = sscanf(c, "%2x", &cmd);
 		if (ret != 1)
 			goto fail;
@@ -387,7 +374,10 @@ static int lp5521_do_store_load(struct l
 		goto fail;
 
 	mutex_lock(&chip->lock);
-	ret = lp5521_load_program(engine, pattern);
+	if (engine->mode == LP5521_CMD_LOAD)
+		ret = lp5521_load_program(engine, pattern);
+	else
+		ret = -EINVAL;
 	mutex_unlock(&chip->lock);
 
 	if (ret) {
@@ -574,20 +564,8 @@ static struct attribute *lp5521_attribut
 	&dev_attr_engine2_mode.attr,
 	&dev_attr_engine3_mode.attr,
 	&dev_attr_selftest.attr,
-	NULL
-};
-
-static struct attribute *lp5521_engine1_attributes[] = {
 	&dev_attr_engine1_load.attr,
-	NULL
-};
-
-static struct attribute *lp5521_engine2_attributes[] = {
 	&dev_attr_engine2_load.attr,
-	NULL
-};
-
-static struct attribute *lp5521_engine3_attributes[] = {
 	&dev_attr_engine3_load.attr,
 	NULL
 };
@@ -596,12 +574,6 @@ static const struct attribute_group lp55
 	.attrs = lp5521_attributes,
 };
 
-static const struct attribute_group lp5521_engine_group[] = {
-	{.attrs = lp5521_engine1_attributes },
-	{.attrs = lp5521_engine2_attributes },
-	{.attrs = lp5521_engine3_attributes },
-};
-
 static int lp5521_register_sysfs(struct i2c_client *client)
 {
 	struct device *dev = &client->dev;
@@ -616,12 +588,6 @@ static void lp5521_unregister_sysfs(stru
 
 	sysfs_remove_group(&dev->kobj, &lp5521_group);
 
-	for (i = 0; i <  ARRAY_SIZE(chip->engines); i++) {
-		if (chip->engines[i].mode == LP5521_CMD_LOAD)
-			sysfs_remove_group(&dev->kobj,
-					chip->engines[i].attributes);
-	}
-
 	for (i = 0; i < chip->num_leds; i++)
 		sysfs_remove_group(&chip->leds[i].cdev.dev->kobj,
 				&lp5521_led_attribute_group);
@@ -651,7 +617,8 @@ static int __init lp5521_init_led(struct
 		return -EINVAL;
 	}
 
-	snprintf(name, sizeof(name), "%s:channel%d", client->name, chan);
+	snprintf(name, sizeof(name), "%s:channel%d",
+			pdata->label ?: client->name, chan);
 	led->cdev.brightness_set = lp5521_set_brightness;
 	led->cdev.name = name;
 	res = led_classdev_register(dev, &led->cdev);
@@ -723,7 +690,7 @@ static int lp5521_probe(struct i2c_clien
 
 	dev_info(&client->dev, "%s programmable led chip found\n", id->name);
 
-	ret = lp5521_configure(client, lp5521_engine_group);
+	ret = lp5521_configure(client);
 	if (ret < 0) {
 		dev_err(&client->dev, "error configuring chip\n");
 		goto fail2;
diff -druNp linux-libre-2.6.37-gnu1/drivers/leds/leds-lp5523.c linux-libre-2.6.38-gnu1/drivers/leds/leds-lp5523.c
--- linux-libre-2.6.37-gnu1/drivers/leds/leds-lp5523.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/leds/leds-lp5523.c	2011-03-14 21:20:32.000000000 -0400
@@ -105,7 +105,6 @@
 #define SHIFT_MASK(id)			(((id) - 1) * 2)
 
 struct lp5523_engine {
-	const struct attribute_group *attributes;
 	int		id;
 	u8		mode;
 	u8		prog_page;
@@ -403,14 +402,23 @@ static ssize_t store_engine_leds(struct
 	struct i2c_client *client = to_i2c_client(dev);
 	struct lp5523_chip *chip = i2c_get_clientdata(client);
 	u16 mux = 0;
+	ssize_t ret;
 
 	if (lp5523_mux_parse(buf, &mux, len))
 		return -EINVAL;
 
+	mutex_lock(&chip->lock);
+	ret = -EINVAL;
+	if (chip->engines[nr - 1].mode != LP5523_CMD_LOAD)
+		goto leave;
+
 	if (lp5523_load_mux(&chip->engines[nr - 1], mux))
-		return -EINVAL;
+		goto leave;
 
-	return len;
+	ret = len;
+leave:
+	mutex_unlock(&chip->lock);
+	return ret;
 }
 
 #define store_leds(nr)						\
@@ -556,7 +564,11 @@ static int lp5523_do_store_load(struct l
 
 	mutex_lock(&chip->lock);
 
-	ret = lp5523_load_program(engine, pattern);
+	if (engine->mode == LP5523_CMD_LOAD)
+		ret = lp5523_load_program(engine, pattern);
+	else
+		ret = -EINVAL;
+
 	mutex_unlock(&chip->lock);
 
 	if (ret) {
@@ -737,37 +749,18 @@ static struct attribute *lp5523_attribut
 	&dev_attr_engine2_mode.attr,
 	&dev_attr_engine3_mode.attr,
 	&dev_attr_selftest.attr,
-	NULL
-};
-
-static struct attribute *lp5523_engine1_attributes[] = {
 	&dev_attr_engine1_load.attr,
 	&dev_attr_engine1_leds.attr,
-	NULL
-};
-
-static struct attribute *lp5523_engine2_attributes[] = {
 	&dev_attr_engine2_load.attr,
 	&dev_attr_engine2_leds.attr,
-	NULL
-};
-
-static struct attribute *lp5523_engine3_attributes[] = {
 	&dev_attr_engine3_load.attr,
 	&dev_attr_engine3_leds.attr,
-	NULL
 };
 
 static const struct attribute_group lp5523_group = {
 	.attrs = lp5523_attributes,
 };
 
-static const struct attribute_group lp5523_engine_group[] = {
-	{.attrs = lp5523_engine1_attributes },
-	{.attrs = lp5523_engine2_attributes },
-	{.attrs = lp5523_engine3_attributes },
-};
-
 static int lp5523_register_sysfs(struct i2c_client *client)
 {
 	struct device *dev = &client->dev;
@@ -788,10 +781,6 @@ static void lp5523_unregister_sysfs(stru
 
 	sysfs_remove_group(&dev->kobj, &lp5523_group);
 
-	for (i = 0; i < ARRAY_SIZE(chip->engines); i++)
-		if (chip->engines[i].mode == LP5523_CMD_LOAD)
-			sysfs_remove_group(&dev->kobj, &lp5523_engine_group[i]);
-
 	for (i = 0; i < chip->num_leds; i++)
 		sysfs_remove_group(&chip->leds[i].cdev.dev->kobj,
 				&lp5523_led_attribute_group);
@@ -802,10 +791,6 @@ static void lp5523_unregister_sysfs(stru
 /*--------------------------------------------------------------*/
 static int lp5523_set_mode(struct lp5523_engine *engine, u8 mode)
 {
-	/*  engine to chip */
-	struct lp5523_chip *chip = engine_to_lp5523(engine);
-	struct i2c_client *client = chip->client;
-	struct device *dev = &client->dev;
 	int ret = 0;
 
 	/* if in that mode already do nothing, except for run */
@@ -817,18 +802,10 @@ static int lp5523_set_mode(struct lp5523
 	} else if (mode == LP5523_CMD_LOAD) {
 		lp5523_set_engine_mode(engine, LP5523_CMD_DISABLED);
 		lp5523_set_engine_mode(engine, LP5523_CMD_LOAD);
-
-		ret = sysfs_create_group(&dev->kobj, engine->attributes);
-		if (ret)
-			return ret;
 	} else if (mode == LP5523_CMD_DISABLED) {
 		lp5523_set_engine_mode(engine, LP5523_CMD_DISABLED);
 	}
 
-	/* remove load attribute from sysfs if not in load mode */
-	if (engine->mode == LP5523_CMD_LOAD && mode != LP5523_CMD_LOAD)
-		sysfs_remove_group(&dev->kobj, engine->attributes);
-
 	engine->mode = mode;
 
 	return ret;
@@ -845,7 +822,6 @@ static int __init lp5523_init_engine(str
 	engine->engine_mask = LP5523_ENG_MASK_BASE >> SHIFT_MASK(id);
 	engine->prog_page = id - 1;
 	engine->mux_page = id + 2;
-	engine->attributes = &lp5523_engine_group[id - 1];
 
 	return 0;
 }
@@ -870,7 +846,8 @@ static int __init lp5523_init_led(struct
 			return -EINVAL;
 		}
 
-		snprintf(name, 32, "lp5523:channel%d", chan);
+		snprintf(name, sizeof(name), "%s:channel%d",
+			pdata->label ?: "lp5523", chan);
 
 		led->cdev.name = name;
 		led->cdev.brightness_set = lp5523_set_brightness;
diff -druNp linux-libre-2.6.37-gnu1/drivers/leds/leds-pca9532.c linux-libre-2.6.38-gnu1/drivers/leds/leds-pca9532.c
--- linux-libre-2.6.37-gnu1/drivers/leds/leds-pca9532.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/leds/leds-pca9532.c	2011-03-14 21:20:32.000000000 -0400
@@ -200,6 +200,32 @@ static void pca9532_led_work(struct work
 	pca9532_setled(led);
 }
 
+static void pca9532_destroy_devices(struct pca9532_data *data, int n_devs)
+{
+	int i = n_devs;
+
+	if (!data)
+		return;
+
+	while (--i >= 0) {
+		switch (data->leds[i].type) {
+		case PCA9532_TYPE_NONE:
+			break;
+		case PCA9532_TYPE_LED:
+			led_classdev_unregister(&data->leds[i].ldev);
+			cancel_work_sync(&data->leds[i].work);
+			break;
+		case PCA9532_TYPE_N2100_BEEP:
+			if (data->idev != NULL) {
+				input_unregister_device(data->idev);
+				cancel_work_sync(&data->work);
+				data->idev = NULL;
+			}
+			break;
+		}
+	}
+}
+
 static int pca9532_configure(struct i2c_client *client,
 	struct pca9532_data *data, struct pca9532_platform_data *pdata)
 {
@@ -274,25 +300,7 @@ static int pca9532_configure(struct i2c_
 	return 0;
 
 exit:
-	if (i > 0)
-		for (i = i - 1; i >= 0; i--)
-			switch (data->leds[i].type) {
-			case PCA9532_TYPE_NONE:
-				break;
-			case PCA9532_TYPE_LED:
-				led_classdev_unregister(&data->leds[i].ldev);
-				cancel_work_sync(&data->leds[i].work);
-				break;
-			case PCA9532_TYPE_N2100_BEEP:
-				if (data->idev != NULL) {
-					input_unregister_device(data->idev);
-					input_free_device(data->idev);
-					cancel_work_sync(&data->work);
-					data->idev = NULL;
-				}
-				break;
-			}
-
+	pca9532_destroy_devices(data, i);
 	return err;
 }
 
@@ -329,25 +337,7 @@ static int pca9532_probe(struct i2c_clie
 static int pca9532_remove(struct i2c_client *client)
 {
 	struct pca9532_data *data = i2c_get_clientdata(client);
-	int i;
-	for (i = 0; i < 16; i++)
-		switch (data->leds[i].type) {
-		case PCA9532_TYPE_NONE:
-			break;
-		case PCA9532_TYPE_LED:
-			led_classdev_unregister(&data->leds[i].ldev);
-			cancel_work_sync(&data->leds[i].work);
-			break;
-		case PCA9532_TYPE_N2100_BEEP:
-			if (data->idev != NULL) {
-				input_unregister_device(data->idev);
-				input_free_device(data->idev);
-				cancel_work_sync(&data->work);
-				data->idev = NULL;
-			}
-			break;
-		}
-
+	pca9532_destroy_devices(data, 16);
 	kfree(data);
 	return 0;
 }
diff -druNp linux-libre-2.6.37-gnu1/drivers/leds/leds-pwm.c linux-libre-2.6.38-gnu1/drivers/leds/leds-pwm.c
--- linux-libre-2.6.37-gnu1/drivers/leds/leds-pwm.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/leds/leds-pwm.c	2011-03-14 21:20:32.000000000 -0400
@@ -69,6 +69,7 @@ static int led_pwm_probe(struct platform
 		led_dat->pwm = pwm_request(cur_led->pwm_id,
 				cur_led->name);
 		if (IS_ERR(led_dat->pwm)) {
+			ret = PTR_ERR(led_dat->pwm);
 			dev_err(&pdev->dev, "unable to request PWM %d\n",
 					cur_led->pwm_id);
 			goto err;
diff -druNp linux-libre-2.6.37-gnu1/drivers/leds/leds-wm8350.c linux-libre-2.6.38-gnu1/drivers/leds/leds-wm8350.c
--- linux-libre-2.6.37-gnu1/drivers/leds/leds-wm8350.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/leds/leds-wm8350.c	2011-03-14 21:20:32.000000000 -0400
@@ -276,7 +276,7 @@ static int wm8350_led_remove(struct plat
 	struct wm8350_led *led = platform_get_drvdata(pdev);
 
 	led_classdev_unregister(&led->cdev);
-	flush_scheduled_work();
+	flush_work_sync(&led->work);
 	wm8350_led_disable(led);
 	regulator_put(led->dcdc);
 	regulator_put(led->isink);
diff -druNp linux-libre-2.6.37-gnu1/drivers/leds/ledtrig-backlight.c linux-libre-2.6.38-gnu1/drivers/leds/ledtrig-backlight.c
--- linux-libre-2.6.37-gnu1/drivers/leds/ledtrig-backlight.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/leds/ledtrig-backlight.c	2011-03-14 21:20:32.000000000 -0400
@@ -26,6 +26,7 @@ struct bl_trig_notifier {
 	int brightness;
 	int old_status;
 	struct notifier_block notifier;
+	unsigned invert;
 };
 
 static int fb_notifier_callback(struct notifier_block *p,
@@ -36,23 +37,64 @@ static int fb_notifier_callback(struct n
 	struct led_classdev *led = n->led;
 	struct fb_event *fb_event = data;
 	int *blank = fb_event->data;
+	int new_status = *blank ? BLANK : UNBLANK;
 
 	switch (event) {
 	case FB_EVENT_BLANK :
-		if (*blank && n->old_status == UNBLANK) {
+		if (new_status == n->old_status)
+			break;
+
+		if ((n->old_status == UNBLANK) ^ n->invert) {
 			n->brightness = led->brightness;
 			led_set_brightness(led, LED_OFF);
-			n->old_status = BLANK;
-		} else if (!*blank && n->old_status == BLANK) {
+		} else {
 			led_set_brightness(led, n->brightness);
-			n->old_status = UNBLANK;
 		}
+
+		n->old_status = new_status;
+
 		break;
 	}
 
 	return 0;
 }
 
+static ssize_t bl_trig_invert_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct led_classdev *led = dev_get_drvdata(dev);
+	struct bl_trig_notifier *n = led->trigger_data;
+
+	return sprintf(buf, "%u\n", n->invert);
+}
+
+static ssize_t bl_trig_invert_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t num)
+{
+	struct led_classdev *led = dev_get_drvdata(dev);
+	struct bl_trig_notifier *n = led->trigger_data;
+	unsigned long invert;
+	int ret;
+
+	ret = strict_strtoul(buf, 10, &invert);
+	if (ret < 0)
+		return ret;
+
+	if (invert > 1)
+		return -EINVAL;
+
+	n->invert = invert;
+
+	/* After inverting, we need to update the LED. */
+	if ((n->old_status == BLANK) ^ n->invert)
+		led_set_brightness(led, LED_OFF);
+	else
+		led_set_brightness(led, n->brightness);
+
+	return num;
+}
+static DEVICE_ATTR(inverted, 0644, bl_trig_invert_show, bl_trig_invert_store);
+
 static void bl_trig_activate(struct led_classdev *led)
 {
 	int ret;
@@ -66,6 +108,10 @@ static void bl_trig_activate(struct led_
 		return;
 	}
 
+	ret = device_create_file(led->dev, &dev_attr_inverted);
+	if (ret)
+		goto err_invert;
+
 	n->led = led;
 	n->brightness = led->brightness;
 	n->old_status = UNBLANK;
@@ -74,6 +120,12 @@ static void bl_trig_activate(struct led_
 	ret = fb_register_client(&n->notifier);
 	if (ret)
 		dev_err(led->dev, "unable to register backlight trigger\n");
+
+	return;
+
+err_invert:
+	led->trigger_data = NULL;
+	kfree(n);
 }
 
 static void bl_trig_deactivate(struct led_classdev *led)
@@ -82,6 +134,7 @@ static void bl_trig_deactivate(struct le
 		(struct bl_trig_notifier *) led->trigger_data;
 
 	if (n) {
+		device_remove_file(led->dev, &dev_attr_inverted);
 		fb_unregister_client(&n->notifier);
 		kfree(n);
 	}
diff -druNp linux-libre-2.6.37-gnu1/drivers/leds/ledtrig-gpio.c linux-libre-2.6.38-gnu1/drivers/leds/ledtrig-gpio.c
--- linux-libre-2.6.37-gnu1/drivers/leds/ledtrig-gpio.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/leds/ledtrig-gpio.c	2011-03-14 21:20:32.000000000 -0400
@@ -99,7 +99,7 @@ static ssize_t gpio_trig_inverted_show(s
 	struct led_classdev *led = dev_get_drvdata(dev);
 	struct gpio_trig_data *gpio_data = led->trigger_data;
 
-	return sprintf(buf, "%s\n", gpio_data->inverted ? "yes" : "no");
+	return sprintf(buf, "%u\n", gpio_data->inverted);
 }
 
 static ssize_t gpio_trig_inverted_store(struct device *dev,
@@ -107,16 +107,17 @@ static ssize_t gpio_trig_inverted_store(
 {
 	struct led_classdev *led = dev_get_drvdata(dev);
 	struct gpio_trig_data *gpio_data = led->trigger_data;
-	unsigned inverted;
+	unsigned long inverted;
 	int ret;
 
-	ret = sscanf(buf, "%u", &inverted);
-	if (ret < 1) {
-		dev_err(dev, "invalid value\n");
+	ret = strict_strtoul(buf, 10, &inverted);
+	if (ret < 0)
+		return ret;
+
+	if (inverted > 1)
 		return -EINVAL;
-	}
 
-	gpio_data->inverted = !!inverted;
+	gpio_data->inverted = inverted;
 
 	/* After inverting, we need to update the LED. */
 	schedule_work(&gpio_data->work);
diff -druNp linux-libre-2.6.37-gnu1/drivers/lguest/page_tables.c linux-libre-2.6.38-gnu1/drivers/lguest/page_tables.c
--- linux-libre-2.6.37-gnu1/drivers/lguest/page_tables.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/lguest/page_tables.c	2011-03-14 21:20:32.000000000 -0400
@@ -1137,7 +1137,7 @@ void free_guest_pagetable(struct lguest
  */
 void map_switcher_in_guest(struct lg_cpu *cpu, struct lguest_pages *pages)
 {
-	pte_t *switcher_pte_page = __get_cpu_var(switcher_pte_pages);
+	pte_t *switcher_pte_page = __this_cpu_read(switcher_pte_pages);
 	pte_t regs_pte;
 
 #ifdef CONFIG_X86_PAE
diff -druNp linux-libre-2.6.37-gnu1/drivers/lguest/x86/core.c linux-libre-2.6.38-gnu1/drivers/lguest/x86/core.c
--- linux-libre-2.6.37-gnu1/drivers/lguest/x86/core.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/lguest/x86/core.c	2011-03-14 21:20:32.000000000 -0400
@@ -90,8 +90,8 @@ static void copy_in_guest_info(struct lg
 	 * meanwhile).  If that's not the case, we pretend everything in the
 	 * Guest has changed.
 	 */
-	if (__get_cpu_var(lg_last_cpu) != cpu || cpu->last_pages != pages) {
-		__get_cpu_var(lg_last_cpu) = cpu;
+	if (__this_cpu_read(lg_last_cpu) != cpu || cpu->last_pages != pages) {
+		__this_cpu_write(lg_last_cpu, cpu);
 		cpu->last_pages = pages;
 		cpu->changed = CHANGED_ALL;
 	}
diff -druNp linux-libre-2.6.37-gnu1/drivers/macintosh/ams/ams-core.c linux-libre-2.6.38-gnu1/drivers/macintosh/ams/ams-core.c
--- linux-libre-2.6.37-gnu1/drivers/macintosh/ams/ams-core.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/macintosh/ams/ams-core.c	2011-03-14 21:20:32.000000000 -0400
@@ -226,7 +226,7 @@ void ams_sensor_detach(void)
 	 * We do this after ams_info.exit(), because an interrupt might
 	 * have arrived before disabling them.
 	 */
-	flush_scheduled_work();
+	flush_work_sync(&ams_info.worker);
 
 	/* Remove device */
 	of_device_unregister(ams_info.of_dev);
diff -druNp linux-libre-2.6.37-gnu1/drivers/macintosh/mac_hid.c linux-libre-2.6.38-gnu1/drivers/macintosh/mac_hid.c
--- linux-libre-2.6.37-gnu1/drivers/macintosh/mac_hid.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/macintosh/mac_hid.c	2011-03-14 21:20:32.000000000 -0400
@@ -23,6 +23,8 @@ static int mouse_button3_keycode = KEY_R
 
 static struct input_dev *mac_hid_emumouse_dev;
 
+static DEFINE_MUTEX(mac_hid_emumouse_mutex);
+
 static int mac_hid_create_emumouse(void)
 {
 	static struct lock_class_key mac_hid_emumouse_dev_event_class;
@@ -187,6 +189,10 @@ static int mac_hid_toggle_emumouse(ctl_t
 	int old_val = *valp;
 	int rc;
 
+	rc = mutex_lock_killable(&mac_hid_emumouse_mutex);
+	if (rc)
+		return rc;
+
 	rc = proc_dointvec(table, write, buffer, lenp, ppos);
 
 	if (rc == 0 && write && *valp != old_val) {
@@ -202,6 +208,8 @@ static int mac_hid_toggle_emumouse(ctl_t
 	if (rc)
 		*valp = old_val;
 
+	mutex_unlock(&mac_hid_emumouse_mutex);
+
 	return rc;
 }
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/macintosh/macio_asic.c linux-libre-2.6.38-gnu1/drivers/macintosh/macio_asic.c
--- linux-libre-2.6.37-gnu1/drivers/macintosh/macio_asic.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/macintosh/macio_asic.c	2011-03-14 21:20:32.000000000 -0400
@@ -387,11 +387,10 @@ static struct macio_dev * macio_add_one_
 	/* Set the DMA ops to the ones from the PCI device, this could be
 	 * fishy if we didn't know that on PowerMac it's always direct ops
 	 * or iommu ops that will work fine
+	 *
+	 * To get all the fields, copy all archdata
 	 */
-	dev->ofdev.dev.archdata.dma_ops =
-		chip->lbus.pdev->dev.archdata.dma_ops;
-	dev->ofdev.dev.archdata.dma_data =
-		chip->lbus.pdev->dev.archdata.dma_data;
+	dev->ofdev.dev.archdata = chip->lbus.pdev->dev.archdata;
 #endif /* CONFIG_PCI */
 
 #ifdef DEBUG
diff -druNp linux-libre-2.6.37-gnu1/drivers/macintosh/rack-meter.c linux-libre-2.6.38-gnu1/drivers/macintosh/rack-meter.c
--- linux-libre-2.6.37-gnu1/drivers/macintosh/rack-meter.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/macintosh/rack-meter.c	2011-03-14 21:20:32.000000000 -0400
@@ -285,8 +285,8 @@ static void __devinit rackmeter_init_cpu
 
 static void __devexit rackmeter_stop_cpu_sniffer(struct rackmeter *rm)
 {
-	cancel_rearming_delayed_work(&rm->cpu[0].sniffer);
-	cancel_rearming_delayed_work(&rm->cpu[1].sniffer);
+	cancel_delayed_work_sync(&rm->cpu[0].sniffer);
+	cancel_delayed_work_sync(&rm->cpu[1].sniffer);
 }
 
 static int __devinit rackmeter_setup(struct rackmeter *rm)
diff -druNp linux-libre-2.6.37-gnu1/drivers/macintosh/therm_pm72.c linux-libre-2.6.38-gnu1/drivers/macintosh/therm_pm72.c
--- linux-libre-2.6.37-gnu1/drivers/macintosh/therm_pm72.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/macintosh/therm_pm72.c	2011-03-14 21:20:32.000000000 -0400
@@ -443,7 +443,7 @@ static int fan_read_reg(int reg, unsigne
 	tries = 0;
 	for (;;) {
 		nr = i2c_master_recv(fcu, buf, nb);
-		if (nr > 0 || (nr < 0 && nr != ENODEV) || tries >= 100)
+		if (nr > 0 || (nr < 0 && nr != -ENODEV) || tries >= 100)
 			break;
 		msleep(10);
 		++tries;
@@ -464,7 +464,7 @@ static int fan_write_reg(int reg, const
 	tries = 0;
 	for (;;) {
 		nw = i2c_master_send(fcu, buf, nb);
-		if (nw > 0 || (nw < 0 && nw != EIO) || tries >= 100)
+		if (nw > 0 || (nw < 0 && nw != -EIO) || tries >= 100)
 			break;
 		msleep(10);
 		++tries;
@@ -2213,6 +2213,9 @@ static void fcu_lookup_fans(struct devic
 static int fcu_of_probe(struct platform_device* dev, const struct of_device_id *match)
 {
 	state = state_detached;
+	of_dev = dev;
+
+	dev_info(&dev->dev, "PowerMac G5 Thermal control driver %s\n", VERSION);
 
 	/* Lookup the fans in the device tree */
 	fcu_lookup_fans(dev->dev.of_node);
@@ -2235,6 +2238,7 @@ static const struct of_device_id fcu_mat
 	},
 	{},
 };
+MODULE_DEVICE_TABLE(of, fcu_match);
 
 static struct of_platform_driver fcu_of_platform_driver = 
 {
@@ -2252,8 +2256,6 @@ static struct of_platform_driver fcu_of_
  */
 static int __init therm_pm72_init(void)
 {
-	struct device_node *np;
-
 	rackmac = of_machine_is_compatible("RackMac3,1");
 
 	if (!of_machine_is_compatible("PowerMac7,2") &&
@@ -2261,34 +2263,12 @@ static int __init therm_pm72_init(void)
 	    !rackmac)
 	    	return -ENODEV;
 
-	printk(KERN_INFO "PowerMac G5 Thermal control driver %s\n", VERSION);
-
-	np = of_find_node_by_type(NULL, "fcu");
-	if (np == NULL) {
-		/* Some machines have strangely broken device-tree */
-		np = of_find_node_by_path("/u3@0,f8000000/i2c@f8001000/fan@15e");
-		if (np == NULL) {
-			    printk(KERN_ERR "Can't find FCU in device-tree !\n");
-			    return -ENODEV;
-		}
-	}
-	of_dev = of_platform_device_create(np, "temperature", NULL);
-	if (of_dev == NULL) {
-		printk(KERN_ERR "Can't register FCU platform device !\n");
-		return -ENODEV;
-	}
-
-	of_register_platform_driver(&fcu_of_platform_driver);
-	
-	return 0;
+	return of_register_platform_driver(&fcu_of_platform_driver);
 }
 
 static void __exit therm_pm72_exit(void)
 {
 	of_unregister_platform_driver(&fcu_of_platform_driver);
-
-	if (of_dev)
-		of_device_unregister(of_dev);
 }
 
 module_init(therm_pm72_init);
diff -druNp linux-libre-2.6.37-gnu1/drivers/macintosh/via-pmu-backlight.c linux-libre-2.6.38-gnu1/drivers/macintosh/via-pmu-backlight.c
--- linux-libre-2.6.37-gnu1/drivers/macintosh/via-pmu-backlight.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/macintosh/via-pmu-backlight.c	2011-03-14 21:20:32.000000000 -0400
@@ -15,7 +15,7 @@
 
 #define MAX_PMU_LEVEL 0xFF
 
-static struct backlight_ops pmu_backlight_data;
+static const struct backlight_ops pmu_backlight_data;
 static DEFINE_SPINLOCK(pmu_backlight_lock);
 static int sleeping, uses_pmu_bl;
 static u8 bl_curve[FB_BACKLIGHT_LEVELS];
@@ -115,7 +115,7 @@ static int pmu_backlight_get_brightness(
 	return bd->props.brightness;
 }
 
-static struct backlight_ops pmu_backlight_data = {
+static const struct backlight_ops pmu_backlight_data = {
 	.get_brightness	= pmu_backlight_get_brightness,
 	.update_status	= pmu_backlight_update_status,
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/macintosh/via-pmu.c linux-libre-2.6.38-gnu1/drivers/macintosh/via-pmu.c
--- linux-libre-2.6.37-gnu1/drivers/macintosh/via-pmu.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/macintosh/via-pmu.c	2011-03-14 21:20:32.000000000 -0400
@@ -2257,7 +2257,7 @@ static int pmu_sleep_valid(suspend_state
 		&& (pmac_call_feature(PMAC_FTR_SLEEP_STATE, NULL, 0, -1) >= 0);
 }
 
-static struct platform_suspend_ops pmu_pm_ops = {
+static const struct platform_suspend_ops pmu_pm_ops = {
 	.enter = powerbook_sleep,
 	.valid = pmu_sleep_valid,
 };
diff -druNp linux-libre-2.6.37-gnu1/drivers/Makefile linux-libre-2.6.38-gnu1/drivers/Makefile
--- linux-libre-2.6.37-gnu1/drivers/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -24,7 +24,7 @@ obj-$(CONFIG_XEN)		+= xen/
 # regulators early, since some subsystems rely on them to initialize
 obj-$(CONFIG_REGULATOR)		+= regulator/
 
-# char/ comes before serial/ etc so that the VT console is the boot-time
+# tty/ comes before char/ so that the VT console is the boot-time
 # default.
 obj-y				+= tty/
 obj-y				+= char/
@@ -38,14 +38,14 @@ obj-$(CONFIG_CONNECTOR)		+= connector/
 obj-$(CONFIG_FB_I810)           += video/i810/
 obj-$(CONFIG_FB_INTEL)          += video/intelfb/
 
-obj-y				+= serial/
 obj-$(CONFIG_PARPORT)		+= parport/
-obj-y				+= base/ block/ misc/ mfd/
+obj-y				+= base/ block/ misc/ mfd/ nfc/
 obj-$(CONFIG_NUBUS)		+= nubus/
 obj-y				+= macintosh/
 obj-$(CONFIG_IDE)		+= ide/
 obj-$(CONFIG_SCSI)		+= scsi/
 obj-$(CONFIG_ATA)		+= ata/
+obj-$(CONFIG_TARGET_CORE)	+= target/
 obj-$(CONFIG_MTD)		+= mtd/
 obj-$(CONFIG_SPI)		+= spi/
 obj-y				+= net/
@@ -115,3 +115,5 @@ obj-$(CONFIG_VLYNQ)		+= vlynq/
 obj-$(CONFIG_STAGING)		+= staging/
 obj-y				+= platform/
 obj-y				+= ieee802154/
+#common clk code
+obj-y				+= clk/
diff -druNp linux-libre-2.6.37-gnu1/drivers/md/bitmap.c linux-libre-2.6.38-gnu1/drivers/md/bitmap.c
--- linux-libre-2.6.37-gnu1/drivers/md/bitmap.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/md/bitmap.c	2011-03-14 21:20:32.000000000 -0400
@@ -210,11 +210,11 @@ static struct page *read_sb_page(mddev_t
 		    || test_bit(Faulty, &rdev->flags))
 			continue;
 
-		target = rdev->sb_start + offset + index * (PAGE_SIZE/512);
+		target = offset + index * (PAGE_SIZE/512);
 
 		if (sync_page_io(rdev, target,
 				 roundup(size, bdev_logical_block_size(rdev->bdev)),
-				 page, READ)) {
+				 page, READ, true)) {
 			page->index = index;
 			attach_page_buffers(page, NULL); /* so that free_buffer will
 							  * quietly no-op */
@@ -264,14 +264,18 @@ 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 block_device *bdev;
 	mddev_t *mddev = bitmap->mddev;
 
 	while ((rdev = next_active_rdev(rdev, mddev)) != NULL) {
 		int size = PAGE_SIZE;
 		loff_t offset = mddev->bitmap_info.offset;
+
+		bdev = (rdev->meta_bdev) ? rdev->meta_bdev : rdev->bdev;
+
 		if (page->index == bitmap->file_pages-1)
 			size = roundup(bitmap->last_page_size,
-				       bdev_logical_block_size(rdev->bdev));
+				       bdev_logical_block_size(bdev));
 		/* Just make sure we aren't corrupting data or
 		 * metadata
 		 */
@@ -1542,7 +1546,7 @@ void bitmap_cond_end_sync(struct bitmap
 	wait_event(bitmap->mddev->recovery_wait,
 		   atomic_read(&bitmap->mddev->recovery_active) == 0);
 
-	bitmap->mddev->curr_resync_completed = bitmap->mddev->curr_resync;
+	bitmap->mddev->curr_resync_completed = sector;
 	set_bit(MD_CHANGE_CLEAN, &bitmap->mddev->flags);
 	sector &= ~((1ULL << CHUNK_BLOCK_SHIFT(bitmap)) - 1);
 	s = 0;
diff -druNp linux-libre-2.6.37-gnu1/drivers/md/dm.c linux-libre-2.6.38-gnu1/drivers/md/dm.c
--- linux-libre-2.6.37-gnu1/drivers/md/dm.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/md/dm.c	2011-03-14 21:20:32.000000000 -0400
@@ -32,7 +32,6 @@
 #define DM_COOKIE_ENV_VAR_NAME "DM_COOKIE"
 #define DM_COOKIE_LENGTH 24
 
-static DEFINE_MUTEX(dm_mutex);
 static const char *_name = DM_NAME;
 
 static unsigned int major = 0;
@@ -328,7 +327,6 @@ static int dm_blk_open(struct block_devi
 {
 	struct mapped_device *md;
 
-	mutex_lock(&dm_mutex);
 	spin_lock(&_minor_lock);
 
 	md = bdev->bd_disk->private_data;
@@ -346,7 +344,6 @@ static int dm_blk_open(struct block_devi
 
 out:
 	spin_unlock(&_minor_lock);
-	mutex_unlock(&dm_mutex);
 
 	return md ? 0 : -ENXIO;
 }
@@ -355,10 +352,12 @@ static int dm_blk_close(struct gendisk *
 {
 	struct mapped_device *md = disk->private_data;
 
-	mutex_lock(&dm_mutex);
+	spin_lock(&_minor_lock);
+
 	atomic_dec(&md->open_count);
 	dm_put(md);
-	mutex_unlock(&dm_mutex);
+
+	spin_unlock(&_minor_lock);
 
 	return 0;
 }
@@ -630,7 +629,7 @@ static void dec_pending(struct dm_io *io
 			queue_io(md, bio);
 		} else {
 			/* done with normal IO or empty flush */
-			trace_block_bio_complete(md->queue, bio);
+			trace_block_bio_complete(md->queue, bio, io_error);
 			bio_endio(bio, io_error);
 		}
 	}
@@ -990,8 +989,8 @@ static void __map_bio(struct dm_target *
 	if (r == DM_MAPIO_REMAPPED) {
 		/* the bio has been remapped so dispatch it */
 
-		trace_block_remap(bdev_get_queue(clone->bi_bdev), clone,
-				    tio->io->bio->bi_bdev->bd_dev, sector);
+		trace_block_bio_remap(bdev_get_queue(clone->bi_bdev), clone,
+				      tio->io->bio->bi_bdev->bd_dev, sector);
 
 		generic_make_request(clone);
 	} else if (r < 0 || r == DM_MAPIO_REQUEUE) {
@@ -1638,13 +1637,15 @@ static void dm_request_fn(struct request
 		if (map_request(ti, clone, md))
 			goto requeued;
 
-		spin_lock_irq(q->queue_lock);
+		BUG_ON(!irqs_disabled());
+		spin_lock(q->queue_lock);
 	}
 
 	goto out;
 
 requeued:
-	spin_lock_irq(q->queue_lock);
+	BUG_ON(!irqs_disabled());
+	spin_lock(q->queue_lock);
 
 plug_and_out:
 	if (!elv_queue_empty(q))
@@ -1884,7 +1885,8 @@ static struct mapped_device *alloc_dev(i
 	add_disk(md->disk);
 	format_dev_t(md->name, MKDEV(_major, minor));
 
-	md->wq = create_singlethread_workqueue("kdmflush");
+	md->wq = alloc_workqueue("kdmflush",
+				 WQ_NON_REENTRANT | WQ_MEM_RECLAIM, 0);
 	if (!md->wq)
 		goto bad_thread;
 
@@ -1992,13 +1994,14 @@ static void event_callback(void *context
 	wake_up(&md->eventq);
 }
 
+/*
+ * Protected by md->suspend_lock obtained by dm_swap_table().
+ */
 static void __set_size(struct mapped_device *md, sector_t size)
 {
 	set_capacity(md->disk, size);
 
-	mutex_lock(&md->bdev->bd_inode->i_mutex);
 	i_size_write(md->bdev->bd_inode, (loff_t)size << SECTOR_SHIFT);
-	mutex_unlock(&md->bdev->bd_inode->i_mutex);
 }
 
 /*
diff -druNp linux-libre-2.6.37-gnu1/drivers/md/dm-crypt.c linux-libre-2.6.38-gnu1/drivers/md/dm-crypt.c
--- linux-libre-2.6.37-gnu1/drivers/md/dm-crypt.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/md/dm-crypt.c	2011-03-14 21:20:32.000000000 -0400
@@ -18,10 +18,14 @@
 #include <linux/crypto.h>
 #include <linux/workqueue.h>
 #include <linux/backing-dev.h>
+#include <linux/percpu.h>
 #include <asm/atomic.h>
 #include <linux/scatterlist.h>
 #include <asm/page.h>
 #include <asm/unaligned.h>
+#include <crypto/hash.h>
+#include <crypto/md5.h>
+#include <crypto/algapi.h>
 
 #include <linux/device-mapper.h>
 
@@ -63,6 +67,7 @@ struct dm_crypt_request {
 	struct convert_context *ctx;
 	struct scatterlist sg_in;
 	struct scatterlist sg_out;
+	sector_t iv_sector;
 };
 
 struct crypt_config;
@@ -73,11 +78,13 @@ struct crypt_iv_operations {
 	void (*dtr)(struct crypt_config *cc);
 	int (*init)(struct crypt_config *cc);
 	int (*wipe)(struct crypt_config *cc);
-	int (*generator)(struct crypt_config *cc, u8 *iv, sector_t sector);
+	int (*generator)(struct crypt_config *cc, u8 *iv,
+			 struct dm_crypt_request *dmreq);
+	int (*post)(struct crypt_config *cc, u8 *iv,
+		    struct dm_crypt_request *dmreq);
 };
 
 struct iv_essiv_private {
-	struct crypto_cipher *tfm;
 	struct crypto_hash *hash_tfm;
 	u8 *salt;
 };
@@ -86,11 +93,32 @@ struct iv_benbi_private {
 	int shift;
 };
 
+#define LMK_SEED_SIZE 64 /* hash + 0 */
+struct iv_lmk_private {
+	struct crypto_shash *hash_tfm;
+	u8 *seed;
+};
+
 /*
  * Crypt: maps a linear range of a block device
  * and encrypts / decrypts at the same time.
  */
 enum flags { DM_CRYPT_SUSPENDED, DM_CRYPT_KEY_VALID };
+
+/*
+ * Duplicated per-CPU state for cipher.
+ */
+struct crypt_cpu {
+	struct ablkcipher_request *req;
+	/* ESSIV: struct crypto_cipher *essiv_tfm */
+	void *iv_private;
+	struct crypto_ablkcipher *tfms[0];
+};
+
+/*
+ * The fields in here must be read only after initialization,
+ * changing state should be in crypt_cpu.
+ */
 struct crypt_config {
 	struct dm_dev *dev;
 	sector_t start;
@@ -108,17 +136,25 @@ struct crypt_config {
 	struct workqueue_struct *crypt_queue;
 
 	char *cipher;
-	char *cipher_mode;
+	char *cipher_string;
 
 	struct crypt_iv_operations *iv_gen_ops;
 	union {
 		struct iv_essiv_private essiv;
 		struct iv_benbi_private benbi;
+		struct iv_lmk_private lmk;
 	} iv_gen_private;
 	sector_t iv_offset;
 	unsigned int iv_size;
 
 	/*
+	 * Duplicated per cpu state. Access through
+	 * per_cpu_ptr() only.
+	 */
+	struct crypt_cpu __percpu *cpu;
+	unsigned tfms_count;
+
+	/*
 	 * Layout of each crypto request:
 	 *
 	 *   struct ablkcipher_request
@@ -132,11 +168,10 @@ struct crypt_config {
 	 * correctly aligned.
 	 */
 	unsigned int dmreq_start;
-	struct ablkcipher_request *req;
 
-	struct crypto_ablkcipher *tfm;
 	unsigned long flags;
 	unsigned int key_size;
+	unsigned int key_parts;
 	u8 key[0];
 };
 
@@ -148,6 +183,20 @@ static struct kmem_cache *_crypt_io_pool
 
 static void clone_init(struct dm_crypt_io *, struct bio *);
 static void kcryptd_queue_crypt(struct dm_crypt_io *io);
+static u8 *iv_of_dmreq(struct crypt_config *cc, struct dm_crypt_request *dmreq);
+
+static struct crypt_cpu *this_crypt_config(struct crypt_config *cc)
+{
+	return this_cpu_ptr(cc->cpu);
+}
+
+/*
+ * Use this to access cipher attributes that are the same for each CPU.
+ */
+static struct crypto_ablkcipher *any_tfm(struct crypt_config *cc)
+{
+	return __this_cpu_ptr(cc->cpu)->tfms[0];
+}
 
 /*
  * Different IV generation algorithms:
@@ -168,23 +217,38 @@ static void kcryptd_queue_crypt(struct d
  * null: the initial vector is always zero.  Provides compatibility with
  *       obsolete loop_fish2 devices.  Do not use for new devices.
  *
+ * lmk:  Compatible implementation of the block chaining mode used
+ *       by the Loop-AES block device encryption system
+ *       designed by Jari Ruusu. See http://loop-aes.sourceforge.net/
+ *       It operates on full 512 byte sectors and uses CBC
+ *       with an IV derived from the sector number, the data and
+ *       optionally extra IV seed.
+ *       This means that after decryption the first block
+ *       of sector must be tweaked according to decrypted data.
+ *       Loop-AES can use three encryption schemes:
+ *         version 1: is plain aes-cbc mode
+ *         version 2: uses 64 multikey scheme with lmk IV generator
+ *         version 3: the same as version 2 with additional IV seed
+ *                   (it uses 65 keys, last key is used as IV seed)
+ *
  * plumb: unimplemented, see:
  * http://article.gmane.org/gmane.linux.kernel.device-mapper.dm-crypt/454
  */
 
-static int crypt_iv_plain_gen(struct crypt_config *cc, u8 *iv, sector_t sector)
+static int crypt_iv_plain_gen(struct crypt_config *cc, u8 *iv,
+			      struct dm_crypt_request *dmreq)
 {
 	memset(iv, 0, cc->iv_size);
-	*(u32 *)iv = cpu_to_le32(sector & 0xffffffff);
+	*(u32 *)iv = cpu_to_le32(dmreq->iv_sector & 0xffffffff);
 
 	return 0;
 }
 
 static int crypt_iv_plain64_gen(struct crypt_config *cc, u8 *iv,
-				sector_t sector)
+				struct dm_crypt_request *dmreq)
 {
 	memset(iv, 0, cc->iv_size);
-	*(u64 *)iv = cpu_to_le64(sector);
+	*(u64 *)iv = cpu_to_le64(dmreq->iv_sector);
 
 	return 0;
 }
@@ -195,7 +259,8 @@ static int crypt_iv_essiv_init(struct cr
 	struct iv_essiv_private *essiv = &cc->iv_gen_private.essiv;
 	struct hash_desc desc;
 	struct scatterlist sg;
-	int err;
+	struct crypto_cipher *essiv_tfm;
+	int err, cpu;
 
 	sg_init_one(&sg, cc->key, cc->key_size);
 	desc.tfm = essiv->hash_tfm;
@@ -205,8 +270,16 @@ static int crypt_iv_essiv_init(struct cr
 	if (err)
 		return err;
 
-	return crypto_cipher_setkey(essiv->tfm, essiv->salt,
+	for_each_possible_cpu(cpu) {
+		essiv_tfm = per_cpu_ptr(cc->cpu, cpu)->iv_private,
+
+		err = crypto_cipher_setkey(essiv_tfm, essiv->salt,
 				    crypto_hash_digestsize(essiv->hash_tfm));
+		if (err)
+			return err;
+	}
+
+	return 0;
 }
 
 /* Wipe salt and reset key derived from volume key */
@@ -214,24 +287,76 @@ static int crypt_iv_essiv_wipe(struct cr
 {
 	struct iv_essiv_private *essiv = &cc->iv_gen_private.essiv;
 	unsigned salt_size = crypto_hash_digestsize(essiv->hash_tfm);
+	struct crypto_cipher *essiv_tfm;
+	int cpu, r, err = 0;
 
 	memset(essiv->salt, 0, salt_size);
 
-	return crypto_cipher_setkey(essiv->tfm, essiv->salt, salt_size);
+	for_each_possible_cpu(cpu) {
+		essiv_tfm = per_cpu_ptr(cc->cpu, cpu)->iv_private;
+		r = crypto_cipher_setkey(essiv_tfm, essiv->salt, salt_size);
+		if (r)
+			err = r;
+	}
+
+	return err;
+}
+
+/* Set up per cpu cipher state */
+static struct crypto_cipher *setup_essiv_cpu(struct crypt_config *cc,
+					     struct dm_target *ti,
+					     u8 *salt, unsigned saltsize)
+{
+	struct crypto_cipher *essiv_tfm;
+	int err;
+
+	/* Setup the essiv_tfm with the given salt */
+	essiv_tfm = crypto_alloc_cipher(cc->cipher, 0, CRYPTO_ALG_ASYNC);
+	if (IS_ERR(essiv_tfm)) {
+		ti->error = "Error allocating crypto tfm for ESSIV";
+		return essiv_tfm;
+	}
+
+	if (crypto_cipher_blocksize(essiv_tfm) !=
+	    crypto_ablkcipher_ivsize(any_tfm(cc))) {
+		ti->error = "Block size of ESSIV cipher does "
+			    "not match IV size of block cipher";
+		crypto_free_cipher(essiv_tfm);
+		return ERR_PTR(-EINVAL);
+	}
+
+	err = crypto_cipher_setkey(essiv_tfm, salt, saltsize);
+	if (err) {
+		ti->error = "Failed to set key for ESSIV cipher";
+		crypto_free_cipher(essiv_tfm);
+		return ERR_PTR(err);
+	}
+
+	return essiv_tfm;
 }
 
 static void crypt_iv_essiv_dtr(struct crypt_config *cc)
 {
+	int cpu;
+	struct crypt_cpu *cpu_cc;
+	struct crypto_cipher *essiv_tfm;
 	struct iv_essiv_private *essiv = &cc->iv_gen_private.essiv;
 
-	crypto_free_cipher(essiv->tfm);
-	essiv->tfm = NULL;
-
 	crypto_free_hash(essiv->hash_tfm);
 	essiv->hash_tfm = NULL;
 
 	kzfree(essiv->salt);
 	essiv->salt = NULL;
+
+	for_each_possible_cpu(cpu) {
+		cpu_cc = per_cpu_ptr(cc->cpu, cpu);
+		essiv_tfm = cpu_cc->iv_private;
+
+		if (essiv_tfm)
+			crypto_free_cipher(essiv_tfm);
+
+		cpu_cc->iv_private = NULL;
+	}
 }
 
 static int crypt_iv_essiv_ctr(struct crypt_config *cc, struct dm_target *ti,
@@ -240,7 +365,7 @@ static int crypt_iv_essiv_ctr(struct cry
 	struct crypto_cipher *essiv_tfm = NULL;
 	struct crypto_hash *hash_tfm = NULL;
 	u8 *salt = NULL;
-	int err;
+	int err, cpu;
 
 	if (!opts) {
 		ti->error = "Digest algorithm missing for ESSIV mode";
@@ -262,48 +387,44 @@ static int crypt_iv_essiv_ctr(struct cry
 		goto bad;
 	}
 
-	/* Allocate essiv_tfm */
-	essiv_tfm = crypto_alloc_cipher(cc->cipher, 0, CRYPTO_ALG_ASYNC);
-	if (IS_ERR(essiv_tfm)) {
-		ti->error = "Error allocating crypto tfm for ESSIV";
-		err = PTR_ERR(essiv_tfm);
-		goto bad;
-	}
-	if (crypto_cipher_blocksize(essiv_tfm) !=
-	    crypto_ablkcipher_ivsize(cc->tfm)) {
-		ti->error = "Block size of ESSIV cipher does "
-			    "not match IV size of block cipher";
-		err = -EINVAL;
-		goto bad;
-	}
-
 	cc->iv_gen_private.essiv.salt = salt;
-	cc->iv_gen_private.essiv.tfm = essiv_tfm;
 	cc->iv_gen_private.essiv.hash_tfm = hash_tfm;
 
+	for_each_possible_cpu(cpu) {
+		essiv_tfm = setup_essiv_cpu(cc, ti, salt,
+					crypto_hash_digestsize(hash_tfm));
+		if (IS_ERR(essiv_tfm)) {
+			crypt_iv_essiv_dtr(cc);
+			return PTR_ERR(essiv_tfm);
+		}
+		per_cpu_ptr(cc->cpu, cpu)->iv_private = essiv_tfm;
+	}
+
 	return 0;
 
 bad:
-	if (essiv_tfm && !IS_ERR(essiv_tfm))
-		crypto_free_cipher(essiv_tfm);
 	if (hash_tfm && !IS_ERR(hash_tfm))
 		crypto_free_hash(hash_tfm);
 	kfree(salt);
 	return err;
 }
 
-static int crypt_iv_essiv_gen(struct crypt_config *cc, u8 *iv, sector_t sector)
+static int crypt_iv_essiv_gen(struct crypt_config *cc, u8 *iv,
+			      struct dm_crypt_request *dmreq)
 {
+	struct crypto_cipher *essiv_tfm = this_crypt_config(cc)->iv_private;
+
 	memset(iv, 0, cc->iv_size);
-	*(u64 *)iv = cpu_to_le64(sector);
-	crypto_cipher_encrypt_one(cc->iv_gen_private.essiv.tfm, iv, iv);
+	*(u64 *)iv = cpu_to_le64(dmreq->iv_sector);
+	crypto_cipher_encrypt_one(essiv_tfm, iv, iv);
+
 	return 0;
 }
 
 static int crypt_iv_benbi_ctr(struct crypt_config *cc, struct dm_target *ti,
 			      const char *opts)
 {
-	unsigned bs = crypto_ablkcipher_blocksize(cc->tfm);
+	unsigned bs = crypto_ablkcipher_blocksize(any_tfm(cc));
 	int log = ilog2(bs);
 
 	/* we need to calculate how far we must shift the sector count
@@ -328,25 +449,177 @@ static void crypt_iv_benbi_dtr(struct cr
 {
 }
 
-static int crypt_iv_benbi_gen(struct crypt_config *cc, u8 *iv, sector_t sector)
+static int crypt_iv_benbi_gen(struct crypt_config *cc, u8 *iv,
+			      struct dm_crypt_request *dmreq)
 {
 	__be64 val;
 
 	memset(iv, 0, cc->iv_size - sizeof(u64)); /* rest is cleared below */
 
-	val = cpu_to_be64(((u64)sector << cc->iv_gen_private.benbi.shift) + 1);
+	val = cpu_to_be64(((u64)dmreq->iv_sector << cc->iv_gen_private.benbi.shift) + 1);
 	put_unaligned(val, (__be64 *)(iv + cc->iv_size - sizeof(u64)));
 
 	return 0;
 }
 
-static int crypt_iv_null_gen(struct crypt_config *cc, u8 *iv, sector_t sector)
+static int crypt_iv_null_gen(struct crypt_config *cc, u8 *iv,
+			     struct dm_crypt_request *dmreq)
 {
 	memset(iv, 0, cc->iv_size);
 
 	return 0;
 }
 
+static void crypt_iv_lmk_dtr(struct crypt_config *cc)
+{
+	struct iv_lmk_private *lmk = &cc->iv_gen_private.lmk;
+
+	if (lmk->hash_tfm && !IS_ERR(lmk->hash_tfm))
+		crypto_free_shash(lmk->hash_tfm);
+	lmk->hash_tfm = NULL;
+
+	kzfree(lmk->seed);
+	lmk->seed = NULL;
+}
+
+static int crypt_iv_lmk_ctr(struct crypt_config *cc, struct dm_target *ti,
+			    const char *opts)
+{
+	struct iv_lmk_private *lmk = &cc->iv_gen_private.lmk;
+
+	lmk->hash_tfm = crypto_alloc_shash("md5", 0, 0);
+	if (IS_ERR(lmk->hash_tfm)) {
+		ti->error = "Error initializing LMK hash";
+		return PTR_ERR(lmk->hash_tfm);
+	}
+
+	/* No seed in LMK version 2 */
+	if (cc->key_parts == cc->tfms_count) {
+		lmk->seed = NULL;
+		return 0;
+	}
+
+	lmk->seed = kzalloc(LMK_SEED_SIZE, GFP_KERNEL);
+	if (!lmk->seed) {
+		crypt_iv_lmk_dtr(cc);
+		ti->error = "Error kmallocing seed storage in LMK";
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+static int crypt_iv_lmk_init(struct crypt_config *cc)
+{
+	struct iv_lmk_private *lmk = &cc->iv_gen_private.lmk;
+	int subkey_size = cc->key_size / cc->key_parts;
+
+	/* LMK seed is on the position of LMK_KEYS + 1 key */
+	if (lmk->seed)
+		memcpy(lmk->seed, cc->key + (cc->tfms_count * subkey_size),
+		       crypto_shash_digestsize(lmk->hash_tfm));
+
+	return 0;
+}
+
+static int crypt_iv_lmk_wipe(struct crypt_config *cc)
+{
+	struct iv_lmk_private *lmk = &cc->iv_gen_private.lmk;
+
+	if (lmk->seed)
+		memset(lmk->seed, 0, LMK_SEED_SIZE);
+
+	return 0;
+}
+
+static int crypt_iv_lmk_one(struct crypt_config *cc, u8 *iv,
+			    struct dm_crypt_request *dmreq,
+			    u8 *data)
+{
+	struct iv_lmk_private *lmk = &cc->iv_gen_private.lmk;
+	struct {
+		struct shash_desc desc;
+		char ctx[crypto_shash_descsize(lmk->hash_tfm)];
+	} sdesc;
+	struct md5_state md5state;
+	u32 buf[4];
+	int i, r;
+
+	sdesc.desc.tfm = lmk->hash_tfm;
+	sdesc.desc.flags = CRYPTO_TFM_REQ_MAY_SLEEP;
+
+	r = crypto_shash_init(&sdesc.desc);
+	if (r)
+		return r;
+
+	if (lmk->seed) {
+		r = crypto_shash_update(&sdesc.desc, lmk->seed, LMK_SEED_SIZE);
+		if (r)
+			return r;
+	}
+
+	/* Sector is always 512B, block size 16, add data of blocks 1-31 */
+	r = crypto_shash_update(&sdesc.desc, data + 16, 16 * 31);
+	if (r)
+		return r;
+
+	/* Sector is cropped to 56 bits here */
+	buf[0] = cpu_to_le32(dmreq->iv_sector & 0xFFFFFFFF);
+	buf[1] = cpu_to_le32((((u64)dmreq->iv_sector >> 32) & 0x00FFFFFF) | 0x80000000);
+	buf[2] = cpu_to_le32(4024);
+	buf[3] = 0;
+	r = crypto_shash_update(&sdesc.desc, (u8 *)buf, sizeof(buf));
+	if (r)
+		return r;
+
+	/* No MD5 padding here */
+	r = crypto_shash_export(&sdesc.desc, &md5state);
+	if (r)
+		return r;
+
+	for (i = 0; i < MD5_HASH_WORDS; i++)
+		__cpu_to_le32s(&md5state.hash[i]);
+	memcpy(iv, &md5state.hash, cc->iv_size);
+
+	return 0;
+}
+
+static int crypt_iv_lmk_gen(struct crypt_config *cc, u8 *iv,
+			    struct dm_crypt_request *dmreq)
+{
+	u8 *src;
+	int r = 0;
+
+	if (bio_data_dir(dmreq->ctx->bio_in) == WRITE) {
+		src = kmap_atomic(sg_page(&dmreq->sg_in), KM_USER0);
+		r = crypt_iv_lmk_one(cc, iv, dmreq, src + dmreq->sg_in.offset);
+		kunmap_atomic(src, KM_USER0);
+	} else
+		memset(iv, 0, cc->iv_size);
+
+	return r;
+}
+
+static int crypt_iv_lmk_post(struct crypt_config *cc, u8 *iv,
+			     struct dm_crypt_request *dmreq)
+{
+	u8 *dst;
+	int r;
+
+	if (bio_data_dir(dmreq->ctx->bio_in) == WRITE)
+		return 0;
+
+	dst = kmap_atomic(sg_page(&dmreq->sg_out), KM_USER0);
+	r = crypt_iv_lmk_one(cc, iv, dmreq, dst + dmreq->sg_out.offset);
+
+	/* Tweak the first block of plaintext sector */
+	if (!r)
+		crypto_xor(dst + dmreq->sg_out.offset, iv, cc->iv_size);
+
+	kunmap_atomic(dst, KM_USER0);
+	return r;
+}
+
 static struct crypt_iv_operations crypt_iv_plain_ops = {
 	.generator = crypt_iv_plain_gen
 };
@@ -373,6 +646,15 @@ static struct crypt_iv_operations crypt_
 	.generator = crypt_iv_null_gen
 };
 
+static struct crypt_iv_operations crypt_iv_lmk_ops = {
+	.ctr	   = crypt_iv_lmk_ctr,
+	.dtr	   = crypt_iv_lmk_dtr,
+	.init	   = crypt_iv_lmk_init,
+	.wipe	   = crypt_iv_lmk_wipe,
+	.generator = crypt_iv_lmk_gen,
+	.post	   = crypt_iv_lmk_post
+};
+
 static void crypt_convert_init(struct crypt_config *cc,
 			       struct convert_context *ctx,
 			       struct bio *bio_out, struct bio *bio_in,
@@ -400,6 +682,13 @@ static struct ablkcipher_request *req_of
 	return (struct ablkcipher_request *)((char *)dmreq - cc->dmreq_start);
 }
 
+static u8 *iv_of_dmreq(struct crypt_config *cc,
+		       struct dm_crypt_request *dmreq)
+{
+	return (u8 *)ALIGN((unsigned long)(dmreq + 1),
+		crypto_ablkcipher_alignmask(any_tfm(cc)) + 1);
+}
+
 static int crypt_convert_block(struct crypt_config *cc,
 			       struct convert_context *ctx,
 			       struct ablkcipher_request *req)
@@ -411,9 +700,9 @@ static int crypt_convert_block(struct cr
 	int r = 0;
 
 	dmreq = dmreq_of_req(cc, req);
-	iv = (u8 *)ALIGN((unsigned long)(dmreq + 1),
-			 crypto_ablkcipher_alignmask(cc->tfm) + 1);
+	iv = iv_of_dmreq(cc, dmreq);
 
+	dmreq->iv_sector = ctx->sector;
 	dmreq->ctx = ctx;
 	sg_init_table(&dmreq->sg_in, 1);
 	sg_set_page(&dmreq->sg_in, bv_in->bv_page, 1 << SECTOR_SHIFT,
@@ -436,7 +725,7 @@ static int crypt_convert_block(struct cr
 	}
 
 	if (cc->iv_gen_ops) {
-		r = cc->iv_gen_ops->generator(cc, iv, ctx->sector);
+		r = cc->iv_gen_ops->generator(cc, iv, dmreq);
 		if (r < 0)
 			return r;
 	}
@@ -449,21 +738,28 @@ static int crypt_convert_block(struct cr
 	else
 		r = crypto_ablkcipher_decrypt(req);
 
+	if (!r && cc->iv_gen_ops && cc->iv_gen_ops->post)
+		r = cc->iv_gen_ops->post(cc, iv, dmreq);
+
 	return r;
 }
 
 static void kcryptd_async_done(struct crypto_async_request *async_req,
 			       int error);
+
 static void crypt_alloc_req(struct crypt_config *cc,
 			    struct convert_context *ctx)
 {
-	if (!cc->req)
-		cc->req = mempool_alloc(cc->req_pool, GFP_NOIO);
-	ablkcipher_request_set_tfm(cc->req, cc->tfm);
-	ablkcipher_request_set_callback(cc->req, CRYPTO_TFM_REQ_MAY_BACKLOG |
-					CRYPTO_TFM_REQ_MAY_SLEEP,
-					kcryptd_async_done,
-					dmreq_of_req(cc, cc->req));
+	struct crypt_cpu *this_cc = this_crypt_config(cc);
+	unsigned key_index = ctx->sector & (cc->tfms_count - 1);
+
+	if (!this_cc->req)
+		this_cc->req = mempool_alloc(cc->req_pool, GFP_NOIO);
+
+	ablkcipher_request_set_tfm(this_cc->req, this_cc->tfms[key_index]);
+	ablkcipher_request_set_callback(this_cc->req,
+	    CRYPTO_TFM_REQ_MAY_BACKLOG | CRYPTO_TFM_REQ_MAY_SLEEP,
+	    kcryptd_async_done, dmreq_of_req(cc, this_cc->req));
 }
 
 /*
@@ -472,6 +768,7 @@ static void crypt_alloc_req(struct crypt
 static int crypt_convert(struct crypt_config *cc,
 			 struct convert_context *ctx)
 {
+	struct crypt_cpu *this_cc = this_crypt_config(cc);
 	int r;
 
 	atomic_set(&ctx->pending, 1);
@@ -483,7 +780,7 @@ static int crypt_convert(struct crypt_co
 
 		atomic_inc(&ctx->pending);
 
-		r = crypt_convert_block(cc, ctx, cc->req);
+		r = crypt_convert_block(cc, ctx, this_cc->req);
 
 		switch (r) {
 		/* async */
@@ -492,7 +789,7 @@ static int crypt_convert(struct crypt_co
 			INIT_COMPLETION(ctx->restart);
 			/* fall through*/
 		case -EINPROGRESS:
-			cc->req = NULL;
+			this_cc->req = NULL;
 			ctx->sector++;
 			continue;
 
@@ -651,6 +948,9 @@ static void crypt_dec_pending(struct dm_
  * They must be separated as otherwise the final stages could be
  * starved by new requests which can block in the first stages due
  * to memory allocation.
+ *
+ * The work is done per CPU global for all dm-crypt instances.
+ * They should not depend on each other and do not block.
  */
 static void crypt_endio(struct bio *clone, int error)
 {
@@ -691,26 +991,30 @@ static void clone_init(struct dm_crypt_i
 	clone->bi_destructor = dm_crypt_bio_destructor;
 }
 
-static void kcryptd_io_read(struct dm_crypt_io *io)
+static void kcryptd_unplug(struct crypt_config *cc)
+{
+	blk_unplug(bdev_get_queue(cc->dev->bdev));
+}
+
+static int kcryptd_io_read(struct dm_crypt_io *io, gfp_t gfp)
 {
 	struct crypt_config *cc = io->target->private;
 	struct bio *base_bio = io->base_bio;
 	struct bio *clone;
 
-	crypt_inc_pending(io);
-
 	/*
 	 * The block layer might modify the bvec array, so always
 	 * copy the required bvecs because we need the original
 	 * one in order to decrypt the whole bio data *afterwards*.
 	 */
-	clone = bio_alloc_bioset(GFP_NOIO, bio_segments(base_bio), cc->bs);
-	if (unlikely(!clone)) {
-		io->error = -ENOMEM;
-		crypt_dec_pending(io);
-		return;
+	clone = bio_alloc_bioset(gfp, bio_segments(base_bio), cc->bs);
+	if (!clone) {
+		kcryptd_unplug(cc);
+		return 1;
 	}
 
+	crypt_inc_pending(io);
+
 	clone_init(io, clone);
 	clone->bi_idx = 0;
 	clone->bi_vcnt = bio_segments(base_bio);
@@ -720,6 +1024,7 @@ static void kcryptd_io_read(struct dm_cr
 	       sizeof(struct bio_vec) * clone->bi_vcnt);
 
 	generic_make_request(clone);
+	return 0;
 }
 
 static void kcryptd_io_write(struct dm_crypt_io *io)
@@ -732,9 +1037,12 @@ static void kcryptd_io(struct work_struc
 {
 	struct dm_crypt_io *io = container_of(work, struct dm_crypt_io, work);
 
-	if (bio_data_dir(io->base_bio) == READ)
-		kcryptd_io_read(io);
-	else
+	if (bio_data_dir(io->base_bio) == READ) {
+		crypt_inc_pending(io);
+		if (kcryptd_io_read(io, GFP_NOIO))
+			io->error = -ENOMEM;
+		crypt_dec_pending(io);
+	} else
 		kcryptd_io_write(io);
 }
 
@@ -901,6 +1209,9 @@ static void kcryptd_async_done(struct cr
 		return;
 	}
 
+	if (!error && cc->iv_gen_ops && cc->iv_gen_ops->post)
+		error = cc->iv_gen_ops->post(cc, iv_of_dmreq(cc, dmreq), dmreq);
+
 	mempool_free(req_of_dmreq(cc, dmreq), cc->req_pool);
 
 	if (!atomic_dec_and_test(&ctx->pending))
@@ -971,34 +1282,84 @@ static void crypt_encode_key(char *hex,
 	}
 }
 
-static int crypt_set_key(struct crypt_config *cc, char *key)
+static void crypt_free_tfms(struct crypt_config *cc, int cpu)
 {
-	unsigned key_size = strlen(key) >> 1;
+	struct crypt_cpu *cpu_cc = per_cpu_ptr(cc->cpu, cpu);
+	unsigned i;
 
-	if (cc->key_size && cc->key_size != key_size)
+	for (i = 0; i < cc->tfms_count; i++)
+		if (cpu_cc->tfms[i] && !IS_ERR(cpu_cc->tfms[i])) {
+			crypto_free_ablkcipher(cpu_cc->tfms[i]);
+			cpu_cc->tfms[i] = NULL;
+		}
+}
+
+static int crypt_alloc_tfms(struct crypt_config *cc, int cpu, char *ciphermode)
+{
+	struct crypt_cpu *cpu_cc = per_cpu_ptr(cc->cpu, cpu);
+	unsigned i;
+	int err;
+
+	for (i = 0; i < cc->tfms_count; i++) {
+		cpu_cc->tfms[i] = crypto_alloc_ablkcipher(ciphermode, 0, 0);
+		if (IS_ERR(cpu_cc->tfms[i])) {
+			err = PTR_ERR(cpu_cc->tfms[i]);
+			crypt_free_tfms(cc, cpu);
+			return err;
+		}
+	}
+
+	return 0;
+}
+
+static int crypt_setkey_allcpus(struct crypt_config *cc)
+{
+	unsigned subkey_size = cc->key_size >> ilog2(cc->tfms_count);
+	int cpu, err = 0, i, r;
+
+	for_each_possible_cpu(cpu) {
+		for (i = 0; i < cc->tfms_count; i++) {
+			r = crypto_ablkcipher_setkey(per_cpu_ptr(cc->cpu, cpu)->tfms[i],
+						     cc->key + (i * subkey_size), subkey_size);
+			if (r)
+				err = r;
+		}
+	}
+
+	return err;
+}
+
+static int crypt_set_key(struct crypt_config *cc, char *key)
+{
+	/* The key size may not be changed. */
+	if (cc->key_size != (strlen(key) >> 1))
 		return -EINVAL;
 
-	cc->key_size = key_size; /* initial settings */
+	/* Hyphen (which gives a key_size of zero) means there is no key. */
+	if (!cc->key_size && strcmp(key, "-"))
+		return -EINVAL;
 
-	if ((!key_size && strcmp(key, "-")) ||
-	   (key_size && crypt_decode_key(cc->key, key, key_size) < 0))
+	if (cc->key_size && crypt_decode_key(cc->key, key, cc->key_size) < 0)
 		return -EINVAL;
 
 	set_bit(DM_CRYPT_KEY_VALID, &cc->flags);
 
-	return crypto_ablkcipher_setkey(cc->tfm, cc->key, cc->key_size);
+	return crypt_setkey_allcpus(cc);
 }
 
 static int crypt_wipe_key(struct crypt_config *cc)
 {
 	clear_bit(DM_CRYPT_KEY_VALID, &cc->flags);
 	memset(&cc->key, 0, cc->key_size * sizeof(u8));
-	return crypto_ablkcipher_setkey(cc->tfm, cc->key, cc->key_size);
+
+	return crypt_setkey_allcpus(cc);
 }
 
 static void crypt_dtr(struct dm_target *ti)
 {
 	struct crypt_config *cc = ti->private;
+	struct crypt_cpu *cpu_cc;
+	int cpu;
 
 	ti->private = NULL;
 
@@ -1010,6 +1371,14 @@ static void crypt_dtr(struct dm_target *
 	if (cc->crypt_queue)
 		destroy_workqueue(cc->crypt_queue);
 
+	if (cc->cpu)
+		for_each_possible_cpu(cpu) {
+			cpu_cc = per_cpu_ptr(cc->cpu, cpu);
+			if (cpu_cc->req)
+				mempool_free(cpu_cc->req, cc->req_pool);
+			crypt_free_tfms(cc, cpu);
+		}
+
 	if (cc->bs)
 		bioset_free(cc->bs);
 
@@ -1023,14 +1392,14 @@ static void crypt_dtr(struct dm_target *
 	if (cc->iv_gen_ops && cc->iv_gen_ops->dtr)
 		cc->iv_gen_ops->dtr(cc);
 
-	if (cc->tfm && !IS_ERR(cc->tfm))
-		crypto_free_ablkcipher(cc->tfm);
-
 	if (cc->dev)
 		dm_put_device(ti, cc->dev);
 
+	if (cc->cpu)
+		free_percpu(cc->cpu);
+
 	kzfree(cc->cipher);
-	kzfree(cc->cipher_mode);
+	kzfree(cc->cipher_string);
 
 	/* Must zero key material before freeing */
 	kzfree(cc);
@@ -1040,9 +1409,9 @@ static int crypt_ctr_cipher(struct dm_ta
 			    char *cipher_in, char *key)
 {
 	struct crypt_config *cc = ti->private;
-	char *tmp, *cipher, *chainmode, *ivmode, *ivopts;
+	char *tmp, *cipher, *chainmode, *ivmode, *ivopts, *keycount;
 	char *cipher_api = NULL;
-	int ret = -EINVAL;
+	int cpu, ret = -EINVAL;
 
 	/* Convert to crypto api definition? */
 	if (strchr(cipher_in, '(')) {
@@ -1050,23 +1419,31 @@ static int crypt_ctr_cipher(struct dm_ta
 		return -EINVAL;
 	}
 
+	cc->cipher_string = kstrdup(cipher_in, GFP_KERNEL);
+	if (!cc->cipher_string)
+		goto bad_mem;
+
 	/*
 	 * Legacy dm-crypt cipher specification
-	 * cipher-mode-iv:ivopts
+	 * cipher[:keycount]-mode-iv:ivopts
 	 */
 	tmp = cipher_in;
-	cipher = strsep(&tmp, "-");
+	keycount = strsep(&tmp, "-");
+	cipher = strsep(&keycount, ":");
+
+	if (!keycount)
+		cc->tfms_count = 1;
+	else if (sscanf(keycount, "%u", &cc->tfms_count) != 1 ||
+		 !is_power_of_2(cc->tfms_count)) {
+		ti->error = "Bad cipher key count specification";
+		return -EINVAL;
+	}
+	cc->key_parts = cc->tfms_count;
 
 	cc->cipher = kstrdup(cipher, GFP_KERNEL);
 	if (!cc->cipher)
 		goto bad_mem;
 
-	if (tmp) {
-		cc->cipher_mode = kstrdup(tmp, GFP_KERNEL);
-		if (!cc->cipher_mode)
-			goto bad_mem;
-	}
-
 	chainmode = strsep(&tmp, "-");
 	ivopts = strsep(&tmp, "-");
 	ivmode = strsep(&ivopts, ":");
@@ -1074,10 +1451,19 @@ static int crypt_ctr_cipher(struct dm_ta
 	if (tmp)
 		DMWARN("Ignoring unexpected additional cipher options");
 
-	/* Compatibility mode for old dm-crypt mappings */
+	cc->cpu = __alloc_percpu(sizeof(*(cc->cpu)) +
+				 cc->tfms_count * sizeof(*(cc->cpu->tfms)),
+				 __alignof__(struct crypt_cpu));
+	if (!cc->cpu) {
+		ti->error = "Cannot allocate per cpu state";
+		goto bad_mem;
+	}
+
+	/*
+	 * For compatibility with the original dm-crypt mapping format, if
+	 * only the cipher name is supplied, use cbc-plain.
+	 */
 	if (!chainmode || (!strcmp(chainmode, "plain") && !ivmode)) {
-		kfree(cc->cipher_mode);
-		cc->cipher_mode = kstrdup("cbc-plain", GFP_KERNEL);
 		chainmode = "cbc";
 		ivmode = "plain";
 	}
@@ -1099,11 +1485,12 @@ static int crypt_ctr_cipher(struct dm_ta
 	}
 
 	/* Allocate cipher */
-	cc->tfm = crypto_alloc_ablkcipher(cipher_api, 0, 0);
-	if (IS_ERR(cc->tfm)) {
-		ret = PTR_ERR(cc->tfm);
-		ti->error = "Error allocating crypto tfm";
-		goto bad;
+	for_each_possible_cpu(cpu) {
+		ret = crypt_alloc_tfms(cc, cpu, cipher_api);
+		if (ret < 0) {
+			ti->error = "Error allocating crypto tfm";
+			goto bad;
+		}
 	}
 
 	/* Initialize and set key */
@@ -1114,7 +1501,7 @@ static int crypt_ctr_cipher(struct dm_ta
 	}
 
 	/* Initialize IV */
-	cc->iv_size = crypto_ablkcipher_ivsize(cc->tfm);
+	cc->iv_size = crypto_ablkcipher_ivsize(any_tfm(cc));
 	if (cc->iv_size)
 		/* at least a 64 bit sector number should fit in our buffer */
 		cc->iv_size = max(cc->iv_size,
@@ -1137,7 +1524,15 @@ static int crypt_ctr_cipher(struct dm_ta
 		cc->iv_gen_ops = &crypt_iv_benbi_ops;
 	else if (strcmp(ivmode, "null") == 0)
 		cc->iv_gen_ops = &crypt_iv_null_ops;
-	else {
+	else if (strcmp(ivmode, "lmk") == 0) {
+		cc->iv_gen_ops = &crypt_iv_lmk_ops;
+		/* Version 2 and 3 is recognised according
+		 * to length of provided multi-key string.
+		 * If present (version 3), last key is used as IV seed.
+		 */
+		if (cc->key_size % cc->key_parts)
+			cc->key_parts++;
+	} else {
 		ret = -EINVAL;
 		ti->error = "Invalid IV mode";
 		goto bad;
@@ -1194,6 +1589,7 @@ static int crypt_ctr(struct dm_target *t
 		ti->error = "Cannot allocate encryption context";
 		return -ENOMEM;
 	}
+	cc->key_size = key_size;
 
 	ti->private = cc;
 	ret = crypt_ctr_cipher(ti, argv[0], argv[1]);
@@ -1208,9 +1604,9 @@ static int crypt_ctr(struct dm_target *t
 	}
 
 	cc->dmreq_start = sizeof(struct ablkcipher_request);
-	cc->dmreq_start += crypto_ablkcipher_reqsize(cc->tfm);
+	cc->dmreq_start += crypto_ablkcipher_reqsize(any_tfm(cc));
 	cc->dmreq_start = ALIGN(cc->dmreq_start, crypto_tfm_ctx_alignment());
-	cc->dmreq_start += crypto_ablkcipher_alignmask(cc->tfm) &
+	cc->dmreq_start += crypto_ablkcipher_alignmask(any_tfm(cc)) &
 			   ~(crypto_tfm_ctx_alignment() - 1);
 
 	cc->req_pool = mempool_create_kmalloc_pool(MIN_IOS, cc->dmreq_start +
@@ -1219,7 +1615,6 @@ static int crypt_ctr(struct dm_target *t
 		ti->error = "Cannot allocate crypt request mempool";
 		goto bad;
 	}
-	cc->req = NULL;
 
 	cc->page_pool = mempool_create_page_pool(MIN_POOL_PAGES, 0);
 	if (!cc->page_pool) {
@@ -1252,13 +1647,20 @@ static int crypt_ctr(struct dm_target *t
 	cc->start = tmpll;
 
 	ret = -ENOMEM;
-	cc->io_queue = create_singlethread_workqueue("kcryptd_io");
+	cc->io_queue = alloc_workqueue("kcryptd_io",
+				       WQ_NON_REENTRANT|
+				       WQ_MEM_RECLAIM,
+				       1);
 	if (!cc->io_queue) {
 		ti->error = "Couldn't create kcryptd io queue";
 		goto bad;
 	}
 
-	cc->crypt_queue = create_singlethread_workqueue("kcryptd");
+	cc->crypt_queue = alloc_workqueue("kcryptd",
+					  WQ_NON_REENTRANT|
+					  WQ_CPU_INTENSIVE|
+					  WQ_MEM_RECLAIM,
+					  1);
 	if (!cc->crypt_queue) {
 		ti->error = "Couldn't create kcryptd queue";
 		goto bad;
@@ -1286,9 +1688,10 @@ static int crypt_map(struct dm_target *t
 
 	io = crypt_io_alloc(ti, bio, dm_target_offset(ti, bio->bi_sector));
 
-	if (bio_data_dir(io->base_bio) == READ)
-		kcryptd_queue_io(io);
-	else
+	if (bio_data_dir(io->base_bio) == READ) {
+		if (kcryptd_io_read(io, GFP_NOWAIT))
+			kcryptd_queue_io(io);
+	} else
 		kcryptd_queue_crypt(io);
 
 	return DM_MAPIO_SUBMITTED;
@@ -1306,10 +1709,7 @@ static int crypt_status(struct dm_target
 		break;
 
 	case STATUSTYPE_TABLE:
-		if (cc->cipher_mode)
-			DMEMIT("%s-%s ", cc->cipher, cc->cipher_mode);
-		else
-			DMEMIT("%s ", cc->cipher);
+		DMEMIT("%s ", cc->cipher_string);
 
 		if (cc->key_size > 0) {
 			if ((maxlen - sz) < ((cc->key_size << 1) + 1))
@@ -1421,7 +1821,7 @@ static int crypt_iterate_devices(struct
 
 static struct target_type crypt_target = {
 	.name   = "crypt",
-	.version = {1, 7, 0},
+	.version = {1, 10, 0},
 	.module = THIS_MODULE,
 	.ctr    = crypt_ctr,
 	.dtr    = crypt_dtr,
diff -druNp linux-libre-2.6.37-gnu1/drivers/md/dm-delay.c linux-libre-2.6.38-gnu1/drivers/md/dm-delay.c
--- linux-libre-2.6.37-gnu1/drivers/md/dm-delay.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/md/dm-delay.c	2011-03-14 21:20:32.000000000 -0400
@@ -352,7 +352,7 @@ static int __init dm_delay_init(void)
 {
 	int r = -ENOMEM;
 
-	kdelayd_wq = create_workqueue("kdelayd");
+	kdelayd_wq = alloc_workqueue("kdelayd", WQ_MEM_RECLAIM, 0);
 	if (!kdelayd_wq) {
 		DMERR("Couldn't start kdelayd");
 		goto bad_queue;
diff -druNp linux-libre-2.6.37-gnu1/drivers/md/dm-ioctl.c linux-libre-2.6.38-gnu1/drivers/md/dm-ioctl.c
--- linux-libre-2.6.37-gnu1/drivers/md/dm-ioctl.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/md/dm-ioctl.c	2011-03-14 21:20:32.000000000 -0400
@@ -295,19 +295,55 @@ retry:
 		DMWARN("remove_all left %d open device(s)", dev_skipped);
 }
 
+/*
+ * Set the uuid of a hash_cell that isn't already set.
+ */
+static void __set_cell_uuid(struct hash_cell *hc, char *new_uuid)
+{
+	mutex_lock(&dm_hash_cells_mutex);
+	hc->uuid = new_uuid;
+	mutex_unlock(&dm_hash_cells_mutex);
+
+	list_add(&hc->uuid_list, _uuid_buckets + hash_str(new_uuid));
+}
+
+/*
+ * Changes the name of a hash_cell and returns the old name for
+ * the caller to free.
+ */
+static char *__change_cell_name(struct hash_cell *hc, char *new_name)
+{
+	char *old_name;
+
+	/*
+	 * Rename and move the name cell.
+	 */
+	list_del(&hc->name_list);
+	old_name = hc->name;
+
+	mutex_lock(&dm_hash_cells_mutex);
+	hc->name = new_name;
+	mutex_unlock(&dm_hash_cells_mutex);
+
+	list_add(&hc->name_list, _name_buckets + hash_str(new_name));
+
+	return old_name;
+}
+
 static struct mapped_device *dm_hash_rename(struct dm_ioctl *param,
 					    const char *new)
 {
-	char *new_name, *old_name;
+	char *new_data, *old_name = NULL;
 	struct hash_cell *hc;
 	struct dm_table *table;
 	struct mapped_device *md;
+	unsigned change_uuid = (param->flags & DM_UUID_FLAG) ? 1 : 0;
 
 	/*
 	 * duplicate new.
 	 */
-	new_name = kstrdup(new, GFP_KERNEL);
-	if (!new_name)
+	new_data = kstrdup(new, GFP_KERNEL);
+	if (!new_data)
 		return ERR_PTR(-ENOMEM);
 
 	down_write(&_hash_lock);
@@ -315,13 +351,19 @@ static struct mapped_device *dm_hash_ren
 	/*
 	 * Is new free ?
 	 */
-	hc = __get_name_cell(new);
+	if (change_uuid)
+		hc = __get_uuid_cell(new);
+	else
+		hc = __get_name_cell(new);
+
 	if (hc) {
-		DMWARN("asked to rename to an already-existing name %s -> %s",
+		DMWARN("Unable to change %s on mapped device %s to one that "
+		       "already exists: %s",
+		       change_uuid ? "uuid" : "name",
 		       param->name, new);
 		dm_put(hc->md);
 		up_write(&_hash_lock);
-		kfree(new_name);
+		kfree(new_data);
 		return ERR_PTR(-EBUSY);
 	}
 
@@ -330,22 +372,30 @@ static struct mapped_device *dm_hash_ren
 	 */
 	hc = __get_name_cell(param->name);
 	if (!hc) {
-		DMWARN("asked to rename a non-existent device %s -> %s",
-		       param->name, new);
+		DMWARN("Unable to rename non-existent device, %s to %s%s",
+		       param->name, change_uuid ? "uuid " : "", new);
 		up_write(&_hash_lock);
-		kfree(new_name);
+		kfree(new_data);
 		return ERR_PTR(-ENXIO);
 	}
 
 	/*
-	 * rename and move the name cell.
+	 * Does this device already have a uuid?
 	 */
-	list_del(&hc->name_list);
-	old_name = hc->name;
-	mutex_lock(&dm_hash_cells_mutex);
-	hc->name = new_name;
-	mutex_unlock(&dm_hash_cells_mutex);
-	list_add(&hc->name_list, _name_buckets + hash_str(new_name));
+	if (change_uuid && hc->uuid) {
+		DMWARN("Unable to change uuid of mapped device %s to %s "
+		       "because uuid is already set to %s",
+		       param->name, new, hc->uuid);
+		dm_put(hc->md);
+		up_write(&_hash_lock);
+		kfree(new_data);
+		return ERR_PTR(-EINVAL);
+	}
+
+	if (change_uuid)
+		__set_cell_uuid(hc, new_data);
+	else
+		old_name = __change_cell_name(hc, new_data);
 
 	/*
 	 * Wake up any dm event waiters.
@@ -729,7 +779,7 @@ static int dev_remove(struct dm_ioctl *p
 	hc = __find_device_hash_cell(param);
 
 	if (!hc) {
-		DMWARN("device doesn't appear to be in the dev hash table.");
+		DMDEBUG_LIMIT("device doesn't appear to be in the dev hash table.");
 		up_write(&_hash_lock);
 		return -ENXIO;
 	}
@@ -741,7 +791,7 @@ static int dev_remove(struct dm_ioctl *p
 	 */
 	r = dm_lock_for_deletion(md);
 	if (r) {
-		DMWARN("unable to remove open device %s", hc->name);
+		DMDEBUG_LIMIT("unable to remove open device %s", hc->name);
 		up_write(&_hash_lock);
 		dm_put(md);
 		return r;
@@ -774,21 +824,24 @@ static int invalid_str(char *str, void *
 static int dev_rename(struct dm_ioctl *param, size_t param_size)
 {
 	int r;
-	char *new_name = (char *) param + param->data_start;
+	char *new_data = (char *) param + param->data_start;
 	struct mapped_device *md;
+	unsigned change_uuid = (param->flags & DM_UUID_FLAG) ? 1 : 0;
 
-	if (new_name < param->data ||
-	    invalid_str(new_name, (void *) param + param_size) ||
-	    strlen(new_name) > DM_NAME_LEN - 1) {
-		DMWARN("Invalid new logical volume name supplied.");
+	if (new_data < param->data ||
+	    invalid_str(new_data, (void *) param + param_size) ||
+	    strlen(new_data) > (change_uuid ? DM_UUID_LEN - 1 : DM_NAME_LEN - 1)) {
+		DMWARN("Invalid new mapped device name or uuid string supplied.");
 		return -EINVAL;
 	}
 
-	r = check_name(new_name);
-	if (r)
-		return r;
+	if (!change_uuid) {
+		r = check_name(new_data);
+		if (r)
+			return r;
+	}
 
-	md = dm_hash_rename(param, new_name);
+	md = dm_hash_rename(param, new_data);
 	if (IS_ERR(md))
 		return PTR_ERR(md);
 
@@ -885,7 +938,7 @@ static int do_resume(struct dm_ioctl *pa
 
 	hc = __find_device_hash_cell(param);
 	if (!hc) {
-		DMWARN("device doesn't appear to be in the dev hash table.");
+		DMDEBUG_LIMIT("device doesn't appear to be in the dev hash table.");
 		up_write(&_hash_lock);
 		return -ENXIO;
 	}
@@ -1212,7 +1265,7 @@ static int table_clear(struct dm_ioctl *
 
 	hc = __find_device_hash_cell(param);
 	if (!hc) {
-		DMWARN("device doesn't appear to be in the dev hash table.");
+		DMDEBUG_LIMIT("device doesn't appear to be in the dev hash table.");
 		up_write(&_hash_lock);
 		return -ENXIO;
 	}
diff -druNp linux-libre-2.6.37-gnu1/drivers/md/dm-kcopyd.c linux-libre-2.6.38-gnu1/drivers/md/dm-kcopyd.c
--- linux-libre-2.6.37-gnu1/drivers/md/dm-kcopyd.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/md/dm-kcopyd.c	2011-03-14 21:20:32.000000000 -0400
@@ -37,6 +37,13 @@ struct dm_kcopyd_client {
 	unsigned int nr_pages;
 	unsigned int nr_free_pages;
 
+	/*
+	 * Block devices to unplug.
+	 * Non-NULL pointer means that a block device has some pending requests
+	 * and needs to be unplugged.
+	 */
+	struct block_device *unplug[2];
+
 	struct dm_io_client *io_client;
 
 	wait_queue_head_t destroyq;
@@ -308,6 +315,31 @@ static int run_complete_job(struct kcopy
 	return 0;
 }
 
+/*
+ * Unplug the block device at the specified index.
+ */
+static void unplug(struct dm_kcopyd_client *kc, int rw)
+{
+	if (kc->unplug[rw] != NULL) {
+		blk_unplug(bdev_get_queue(kc->unplug[rw]));
+		kc->unplug[rw] = NULL;
+	}
+}
+
+/*
+ * Prepare block device unplug. If there's another device
+ * to be unplugged at the same array index, we unplug that
+ * device first.
+ */
+static void prepare_unplug(struct dm_kcopyd_client *kc, int rw,
+			   struct block_device *bdev)
+{
+	if (likely(kc->unplug[rw] == bdev))
+		return;
+	unplug(kc, rw);
+	kc->unplug[rw] = bdev;
+}
+
 static void complete_io(unsigned long error, void *context)
 {
 	struct kcopyd_job *job = (struct kcopyd_job *) context;
@@ -345,7 +377,7 @@ static int run_io_job(struct kcopyd_job
 {
 	int r;
 	struct dm_io_request io_req = {
-		.bi_rw = job->rw | REQ_SYNC | REQ_UNPLUG,
+		.bi_rw = job->rw,
 		.mem.type = DM_IO_PAGE_LIST,
 		.mem.ptr.pl = job->pages,
 		.mem.offset = job->offset,
@@ -354,10 +386,16 @@ static int run_io_job(struct kcopyd_job
 		.client = job->kc->io_client,
 	};
 
-	if (job->rw == READ)
+	if (job->rw == READ) {
 		r = dm_io(&io_req, 1, &job->source, NULL);
-	else
+		prepare_unplug(job->kc, READ, job->source.bdev);
+	} else {
+		if (job->num_dests > 1)
+			io_req.bi_rw |= REQ_UNPLUG;
 		r = dm_io(&io_req, job->num_dests, job->dests, NULL);
+		if (!(io_req.bi_rw & REQ_UNPLUG))
+			prepare_unplug(job->kc, WRITE, job->dests[0].bdev);
+	}
 
 	return r;
 }
@@ -435,10 +473,18 @@ static void do_work(struct work_struct *
 	 * Pages jobs when successful will jump onto the io jobs
 	 * list.  io jobs call wake when they complete and it all
 	 * starts again.
+	 *
+	 * Note that io_jobs add block devices to the unplug array,
+	 * this array is cleared with "unplug" calls. It is thus
+	 * forbidden to run complete_jobs after io_jobs and before
+	 * unplug because the block device could be destroyed in
+	 * job completion callback.
 	 */
 	process_jobs(&kc->complete_jobs, kc, run_complete_job);
 	process_jobs(&kc->pages_jobs, kc, run_pages_job);
 	process_jobs(&kc->io_jobs, kc, run_io_job);
+	unplug(kc, READ);
+	unplug(kc, WRITE);
 }
 
 /*
@@ -619,12 +665,15 @@ int dm_kcopyd_client_create(unsigned int
 	INIT_LIST_HEAD(&kc->io_jobs);
 	INIT_LIST_HEAD(&kc->pages_jobs);
 
+	memset(kc->unplug, 0, sizeof(kc->unplug));
+
 	kc->job_pool = mempool_create_slab_pool(MIN_JOBS, _job_cache);
 	if (!kc->job_pool)
 		goto bad_slab;
 
 	INIT_WORK(&kc->kcopyd_work, do_work);
-	kc->kcopyd_wq = create_singlethread_workqueue("kcopyd");
+	kc->kcopyd_wq = alloc_workqueue("kcopyd",
+					WQ_NON_REENTRANT | WQ_MEM_RECLAIM, 0);
 	if (!kc->kcopyd_wq)
 		goto bad_workqueue;
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/md/dm-log.c linux-libre-2.6.38-gnu1/drivers/md/dm-log.c
--- linux-libre-2.6.37-gnu1/drivers/md/dm-log.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/md/dm-log.c	2011-03-14 21:20:32.000000000 -0400
@@ -455,7 +455,7 @@ static int create_log_context(struct dm_
 			r = PTR_ERR(lc->io_req.client);
 			DMWARN("couldn't allocate disk io client");
 			kfree(lc);
-			return -ENOMEM;
+			return r;
 		}
 
 		lc->disk_header = vmalloc(buf_size);
diff -druNp linux-libre-2.6.37-gnu1/drivers/md/dm-log-userspace-base.c linux-libre-2.6.38-gnu1/drivers/md/dm-log-userspace-base.c
--- linux-libre-2.6.37-gnu1/drivers/md/dm-log-userspace-base.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/md/dm-log-userspace-base.c	2011-03-14 21:20:32.000000000 -0400
@@ -12,12 +12,22 @@
 
 #include "dm-log-userspace-transfer.h"
 
+#define DM_LOG_USERSPACE_VSN "1.1.0"
+
 struct flush_entry {
 	int type;
 	region_t region;
 	struct list_head list;
 };
 
+/*
+ * This limit on the number of mark and clear request is, to a degree,
+ * arbitrary.  However, there is some basis for the choice in the limits
+ * imposed on the size of data payload by dm-log-userspace-transfer.c:
+ * dm_consult_userspace().
+ */
+#define MAX_FLUSH_GROUP_COUNT 32
+
 struct log_c {
 	struct dm_target *ti;
 	uint32_t region_size;
@@ -37,8 +47,15 @@ struct log_c {
 	 */
 	uint64_t in_sync_hint;
 
+	/*
+	 * Mark and clear requests are held until a flush is issued
+	 * so that we can group, and thereby limit, the amount of
+	 * network traffic between kernel and userspace.  The 'flush_lock'
+	 * is used to protect these lists.
+	 */
 	spinlock_t flush_lock;
-	struct list_head flush_list;  /* only for clear and mark requests */
+	struct list_head mark_list;
+	struct list_head clear_list;
 };
 
 static mempool_t *flush_entry_pool;
@@ -169,7 +186,8 @@ static int userspace_ctr(struct dm_dirty
 
 	strncpy(lc->uuid, argv[0], DM_UUID_LEN);
 	spin_lock_init(&lc->flush_lock);
-	INIT_LIST_HEAD(&lc->flush_list);
+	INIT_LIST_HEAD(&lc->mark_list);
+	INIT_LIST_HEAD(&lc->clear_list);
 
 	str_size = build_constructor_string(ti, argc - 1, argv + 1, &ctr_str);
 	if (str_size < 0) {
@@ -181,8 +199,11 @@ static int userspace_ctr(struct dm_dirty
 	r = dm_consult_userspace(lc->uuid, lc->luid, DM_ULOG_CTR,
 				 ctr_str, str_size, NULL, NULL);
 
-	if (r == -ESRCH) {
-		DMERR("Userspace log server not found");
+	if (r < 0) {
+		if (r == -ESRCH)
+			DMERR("Userspace log server not found");
+		else
+			DMERR("Userspace log server failed to create log");
 		goto out;
 	}
 
@@ -214,10 +235,9 @@ out:
 
 static void userspace_dtr(struct dm_dirty_log *log)
 {
-	int r;
 	struct log_c *lc = log->context;
 
-	r = dm_consult_userspace(lc->uuid, lc->luid, DM_ULOG_DTR,
+	(void) dm_consult_userspace(lc->uuid, lc->luid, DM_ULOG_DTR,
 				 NULL, 0,
 				 NULL, NULL);
 
@@ -338,6 +358,71 @@ static int userspace_in_sync(struct dm_d
 	return (r) ? 0 : (int)in_sync;
 }
 
+static int flush_one_by_one(struct log_c *lc, struct list_head *flush_list)
+{
+	int r = 0;
+	struct flush_entry *fe;
+
+	list_for_each_entry(fe, flush_list, list) {
+		r = userspace_do_request(lc, lc->uuid, fe->type,
+					 (char *)&fe->region,
+					 sizeof(fe->region),
+					 NULL, NULL);
+		if (r)
+			break;
+	}
+
+	return r;
+}
+
+static int flush_by_group(struct log_c *lc, struct list_head *flush_list)
+{
+	int r = 0;
+	int count;
+	uint32_t type = 0;
+	struct flush_entry *fe, *tmp_fe;
+	LIST_HEAD(tmp_list);
+	uint64_t group[MAX_FLUSH_GROUP_COUNT];
+
+	/*
+	 * Group process the requests
+	 */
+	while (!list_empty(flush_list)) {
+		count = 0;
+
+		list_for_each_entry_safe(fe, tmp_fe, flush_list, list) {
+			group[count] = fe->region;
+			count++;
+
+			list_del(&fe->list);
+			list_add(&fe->list, &tmp_list);
+
+			type = fe->type;
+			if (count >= MAX_FLUSH_GROUP_COUNT)
+				break;
+		}
+
+		r = userspace_do_request(lc, lc->uuid, type,
+					 (char *)(group),
+					 count * sizeof(uint64_t),
+					 NULL, NULL);
+		if (r) {
+			/* Group send failed.  Attempt one-by-one. */
+			list_splice_init(&tmp_list, flush_list);
+			r = flush_one_by_one(lc, flush_list);
+			break;
+		}
+	}
+
+	/*
+	 * Must collect flush_entrys that were successfully processed
+	 * as a group so that they will be free'd by the caller.
+	 */
+	list_splice_init(&tmp_list, flush_list);
+
+	return r;
+}
+
 /*
  * userspace_flush
  *
@@ -360,31 +445,25 @@ static int userspace_flush(struct dm_dir
 	int r = 0;
 	unsigned long flags;
 	struct log_c *lc = log->context;
-	LIST_HEAD(flush_list);
+	LIST_HEAD(mark_list);
+	LIST_HEAD(clear_list);
 	struct flush_entry *fe, *tmp_fe;
 
 	spin_lock_irqsave(&lc->flush_lock, flags);
-	list_splice_init(&lc->flush_list, &flush_list);
+	list_splice_init(&lc->mark_list, &mark_list);
+	list_splice_init(&lc->clear_list, &clear_list);
 	spin_unlock_irqrestore(&lc->flush_lock, flags);
 
-	if (list_empty(&flush_list))
+	if (list_empty(&mark_list) && list_empty(&clear_list))
 		return 0;
 
-	/*
-	 * FIXME: Count up requests, group request types,
-	 * allocate memory to stick all requests in and
-	 * send to server in one go.  Failing the allocation,
-	 * do it one by one.
-	 */
+	r = flush_by_group(lc, &mark_list);
+	if (r)
+		goto fail;
 
-	list_for_each_entry(fe, &flush_list, list) {
-		r = userspace_do_request(lc, lc->uuid, fe->type,
-					 (char *)&fe->region,
-					 sizeof(fe->region),
-					 NULL, NULL);
-		if (r)
-			goto fail;
-	}
+	r = flush_by_group(lc, &clear_list);
+	if (r)
+		goto fail;
 
 	r = userspace_do_request(lc, lc->uuid, DM_ULOG_FLUSH,
 				 NULL, 0, NULL, NULL);
@@ -395,7 +474,11 @@ fail:
 	 * Calling code will receive an error and will know that
 	 * the log facility has failed.
 	 */
-	list_for_each_entry_safe(fe, tmp_fe, &flush_list, list) {
+	list_for_each_entry_safe(fe, tmp_fe, &mark_list, list) {
+		list_del(&fe->list);
+		mempool_free(fe, flush_entry_pool);
+	}
+	list_for_each_entry_safe(fe, tmp_fe, &clear_list, list) {
 		list_del(&fe->list);
 		mempool_free(fe, flush_entry_pool);
 	}
@@ -425,7 +508,7 @@ static void userspace_mark_region(struct
 	spin_lock_irqsave(&lc->flush_lock, flags);
 	fe->type = DM_ULOG_MARK_REGION;
 	fe->region = region;
-	list_add(&fe->list, &lc->flush_list);
+	list_add(&fe->list, &lc->mark_list);
 	spin_unlock_irqrestore(&lc->flush_lock, flags);
 
 	return;
@@ -462,7 +545,7 @@ static void userspace_clear_region(struc
 	spin_lock_irqsave(&lc->flush_lock, flags);
 	fe->type = DM_ULOG_CLEAR_REGION;
 	fe->region = region;
-	list_add(&fe->list, &lc->flush_list);
+	list_add(&fe->list, &lc->clear_list);
 	spin_unlock_irqrestore(&lc->flush_lock, flags);
 
 	return;
@@ -684,7 +767,7 @@ static int __init userspace_dirty_log_in
 		return r;
 	}
 
-	DMINFO("version 1.0.0 loaded");
+	DMINFO("version " DM_LOG_USERSPACE_VSN " loaded");
 	return 0;
 }
 
@@ -694,7 +777,7 @@ static void __exit userspace_dirty_log_e
 	dm_ulog_tfr_exit();
 	mempool_destroy(flush_entry_pool);
 
-	DMINFO("version 1.0.0 unloaded");
+	DMINFO("version " DM_LOG_USERSPACE_VSN " unloaded");
 	return;
 }
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/md/dm-log-userspace-transfer.c linux-libre-2.6.38-gnu1/drivers/md/dm-log-userspace-transfer.c
--- linux-libre-2.6.37-gnu1/drivers/md/dm-log-userspace-transfer.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/md/dm-log-userspace-transfer.c	2011-03-14 21:20:32.000000000 -0400
@@ -198,6 +198,7 @@ resend:
 
 	memset(tfr, 0, DM_ULOG_PREALLOCED_SIZE - sizeof(struct cn_msg));
 	memcpy(tfr->uuid, uuid, DM_UUID_LEN);
+	tfr->version = DM_ULOG_REQUEST_VERSION;
 	tfr->luid = luid;
 	tfr->seq = dm_ulog_seq++;
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/md/dm-mpath.c linux-libre-2.6.38-gnu1/drivers/md/dm-mpath.c
--- linux-libre-2.6.37-gnu1/drivers/md/dm-mpath.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/md/dm-mpath.c	2011-03-14 21:20:32.000000000 -0400
@@ -23,6 +23,8 @@
 
 #define DM_MSG_PREFIX "multipath"
 #define MESG_STR(x) x, sizeof(x)
+#define DM_PG_INIT_DELAY_MSECS 2000
+#define DM_PG_INIT_DELAY_DEFAULT ((unsigned) -1)
 
 /* Path properties */
 struct pgpath {
@@ -33,8 +35,7 @@ struct pgpath {
 	unsigned fail_count;		/* Cumulative failure count */
 
 	struct dm_path path;
-	struct work_struct deactivate_path;
-	struct work_struct activate_path;
+	struct delayed_work activate_path;
 };
 
 #define path_to_pgpath(__pgp) container_of((__pgp), struct pgpath, path)
@@ -65,11 +66,15 @@ struct multipath {
 
 	const char *hw_handler_name;
 	char *hw_handler_params;
+
 	unsigned nr_priority_groups;
 	struct list_head priority_groups;
+
+	wait_queue_head_t pg_init_wait;	/* Wait for pg_init completion */
+
 	unsigned pg_init_required;	/* pg_init needs calling? */
 	unsigned pg_init_in_progress;	/* Only one pg_init allowed at once */
-	wait_queue_head_t pg_init_wait;	/* Wait for pg_init completion */
+	unsigned pg_init_delay_retry;	/* Delay pg_init retry? */
 
 	unsigned nr_valid_paths;	/* Total number of usable paths */
 	struct pgpath *current_pgpath;
@@ -82,6 +87,7 @@ struct multipath {
 	unsigned saved_queue_if_no_path;/* Saved state during suspension */
 	unsigned pg_init_retries;	/* Number of times to retry pg_init */
 	unsigned pg_init_count;		/* Number of times pg_init called */
+	unsigned pg_init_delay_msecs;	/* Number of msecs before pg_init retry */
 
 	struct work_struct process_queued_ios;
 	struct list_head queued_ios;
@@ -116,7 +122,6 @@ static struct workqueue_struct *kmultipa
 static void process_queued_ios(struct work_struct *work);
 static void trigger_event(struct work_struct *work);
 static void activate_path(struct work_struct *work);
-static void deactivate_path(struct work_struct *work);
 
 
 /*-----------------------------------------------
@@ -129,8 +134,7 @@ static struct pgpath *alloc_pgpath(void)
 
 	if (pgpath) {
 		pgpath->is_active = 1;
-		INIT_WORK(&pgpath->deactivate_path, deactivate_path);
-		INIT_WORK(&pgpath->activate_path, activate_path);
+		INIT_DELAYED_WORK(&pgpath->activate_path, activate_path);
 	}
 
 	return pgpath;
@@ -141,14 +145,6 @@ static void free_pgpath(struct pgpath *p
 	kfree(pgpath);
 }
 
-static void deactivate_path(struct work_struct *work)
-{
-	struct pgpath *pgpath =
-		container_of(work, struct pgpath, deactivate_path);
-
-	blk_abort_queue(pgpath->path.dev->bdev->bd_disk->queue);
-}
-
 static struct priority_group *alloc_priority_group(void)
 {
 	struct priority_group *pg;
@@ -199,6 +195,7 @@ static struct multipath *alloc_multipath
 		INIT_LIST_HEAD(&m->queued_ios);
 		spin_lock_init(&m->lock);
 		m->queue_io = 1;
+		m->pg_init_delay_msecs = DM_PG_INIT_DELAY_DEFAULT;
 		INIT_WORK(&m->process_queued_ios, process_queued_ios);
 		INIT_WORK(&m->trigger_event, trigger_event);
 		init_waitqueue_head(&m->pg_init_wait);
@@ -238,14 +235,19 @@ static void free_multipath(struct multip
 static void __pg_init_all_paths(struct multipath *m)
 {
 	struct pgpath *pgpath;
+	unsigned long pg_init_delay = 0;
 
 	m->pg_init_count++;
 	m->pg_init_required = 0;
+	if (m->pg_init_delay_retry)
+		pg_init_delay = msecs_to_jiffies(m->pg_init_delay_msecs != DM_PG_INIT_DELAY_DEFAULT ?
+						 m->pg_init_delay_msecs : DM_PG_INIT_DELAY_MSECS);
 	list_for_each_entry(pgpath, &m->current_pg->pgpaths, list) {
 		/* Skip failed paths */
 		if (!pgpath->is_active)
 			continue;
-		if (queue_work(kmpath_handlerd, &pgpath->activate_path))
+		if (queue_delayed_work(kmpath_handlerd, &pgpath->activate_path,
+				       pg_init_delay))
 			m->pg_init_in_progress++;
 	}
 }
@@ -793,8 +795,9 @@ static int parse_features(struct arg_set
 	const char *param_name;
 
 	static struct param _params[] = {
-		{0, 3, "invalid number of feature args"},
+		{0, 5, "invalid number of feature args"},
 		{1, 50, "pg_init_retries must be between 1 and 50"},
+		{0, 60000, "pg_init_delay_msecs must be between 0 and 60000"},
 	};
 
 	r = read_param(_params, shift(as), &argc, &ti->error);
@@ -821,6 +824,14 @@ static int parse_features(struct arg_set
 			continue;
 		}
 
+		if (!strnicmp(param_name, MESG_STR("pg_init_delay_msecs")) &&
+		    (argc >= 1)) {
+			r = read_param(_params + 2, shift(as),
+				       &m->pg_init_delay_msecs, &ti->error);
+			argc--;
+			continue;
+		}
+
 		ti->error = "Unrecognised multipath feature request";
 		r = -EINVAL;
 	} while (argc && !r);
@@ -931,7 +942,7 @@ static void flush_multipath_work(struct
 	flush_workqueue(kmpath_handlerd);
 	multipath_wait_for_pg_init_completion(m);
 	flush_workqueue(kmultipathd);
-	flush_scheduled_work();
+	flush_work_sync(&m->trigger_event);
 }
 
 static void multipath_dtr(struct dm_target *ti)
@@ -995,7 +1006,6 @@ static int fail_path(struct pgpath *pgpa
 		      pgpath->path.dev->name, m->nr_valid_paths);
 
 	schedule_work(&m->trigger_event);
-	queue_work(kmultipathd, &pgpath->deactivate_path);
 
 out:
 	spin_unlock_irqrestore(&m->lock, flags);
@@ -1034,7 +1044,7 @@ static int reinstate_path(struct pgpath
 		m->current_pgpath = NULL;
 		queue_work(kmultipathd, &m->process_queued_ios);
 	} else if (m->hw_handler_name && (m->current_pg == pgpath->pg)) {
-		if (queue_work(kmpath_handlerd, &pgpath->activate_path))
+		if (queue_work(kmpath_handlerd, &pgpath->activate_path.work))
 			m->pg_init_in_progress++;
 	}
 
@@ -1169,6 +1179,7 @@ static void pg_init_done(void *data, int
 	struct priority_group *pg = pgpath->pg;
 	struct multipath *m = pg->m;
 	unsigned long flags;
+	unsigned delay_retry = 0;
 
 	/* device or driver problems */
 	switch (errors) {
@@ -1193,8 +1204,9 @@ static void pg_init_done(void *data, int
 		 */
 		bypass_pg(m, pg, 1);
 		break;
-	/* TODO: For SCSI_DH_RETRY we should wait a couple seconds */
 	case SCSI_DH_RETRY:
+		/* Wait before retrying. */
+		delay_retry = 1;
 	case SCSI_DH_IMM_RETRY:
 	case SCSI_DH_RES_TEMP_UNAVAIL:
 		if (pg_init_limit_reached(m, pgpath))
@@ -1227,6 +1239,7 @@ static void pg_init_done(void *data, int
 	if (!m->pg_init_required)
 		m->queue_io = 0;
 
+	m->pg_init_delay_retry = delay_retry;
 	queue_work(kmultipathd, &m->process_queued_ios);
 
 	/*
@@ -1241,7 +1254,7 @@ out:
 static void activate_path(struct work_struct *work)
 {
 	struct pgpath *pgpath =
-		container_of(work, struct pgpath, activate_path);
+		container_of(work, struct pgpath, activate_path.work);
 
 	scsi_dh_activate(bdev_get_queue(pgpath->path.dev->bdev),
 				pg_init_done, pgpath);
@@ -1382,11 +1395,14 @@ static int multipath_status(struct dm_ta
 		DMEMIT("2 %u %u ", m->queue_size, m->pg_init_count);
 	else {
 		DMEMIT("%u ", m->queue_if_no_path +
-			      (m->pg_init_retries > 0) * 2);
+			      (m->pg_init_retries > 0) * 2 +
+			      (m->pg_init_delay_msecs != DM_PG_INIT_DELAY_DEFAULT) * 2);
 		if (m->queue_if_no_path)
 			DMEMIT("queue_if_no_path ");
 		if (m->pg_init_retries)
 			DMEMIT("pg_init_retries %u ", m->pg_init_retries);
+		if (m->pg_init_delay_msecs != DM_PG_INIT_DELAY_DEFAULT)
+			DMEMIT("pg_init_delay_msecs %u ", m->pg_init_delay_msecs);
 	}
 
 	if (!m->hw_handler_name || type == STATUSTYPE_INFO)
@@ -1655,7 +1671,7 @@ out:
  *---------------------------------------------------------------*/
 static struct target_type multipath_target = {
 	.name = "multipath",
-	.version = {1, 1, 1},
+	.version = {1, 2, 0},
 	.module = THIS_MODULE,
 	.ctr = multipath_ctr,
 	.dtr = multipath_dtr,
@@ -1687,7 +1703,7 @@ static int __init dm_multipath_init(void
 		return -EINVAL;
 	}
 
-	kmultipathd = create_workqueue("kmpathd");
+	kmultipathd = alloc_workqueue("kmpathd", WQ_MEM_RECLAIM, 0);
 	if (!kmultipathd) {
 		DMERR("failed to create workqueue kmpathd");
 		dm_unregister_target(&multipath_target);
@@ -1701,7 +1717,8 @@ static int __init dm_multipath_init(void
 	 * old workqueue would also create a bottleneck in the
 	 * path of the storage hardware device activation.
 	 */
-	kmpath_handlerd = create_singlethread_workqueue("kmpath_handlerd");
+	kmpath_handlerd = alloc_ordered_workqueue("kmpath_handlerd",
+						  WQ_MEM_RECLAIM);
 	if (!kmpath_handlerd) {
 		DMERR("failed to create workqueue kmpath_handlerd");
 		destroy_workqueue(kmultipathd);
diff -druNp linux-libre-2.6.37-gnu1/drivers/md/dm-raid1.c linux-libre-2.6.38-gnu1/drivers/md/dm-raid1.c
--- linux-libre-2.6.37-gnu1/drivers/md/dm-raid1.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/md/dm-raid1.c	2011-03-14 21:20:32.000000000 -0400
@@ -261,7 +261,7 @@ static int mirror_flush(struct dm_target
 	struct dm_io_request io_req = {
 		.bi_rw = WRITE_FLUSH,
 		.mem.type = DM_IO_KMEM,
-		.mem.ptr.bvec = NULL,
+		.mem.ptr.addr = NULL,
 		.client = ms->io_client,
 	};
 
@@ -637,6 +637,12 @@ static void do_write(struct mirror_set *
 		.client = ms->io_client,
 	};
 
+	if (bio->bi_rw & REQ_DISCARD) {
+		io_req.bi_rw |= REQ_DISCARD;
+		io_req.mem.type = DM_IO_KMEM;
+		io_req.mem.ptr.addr = NULL;
+	}
+
 	for (i = 0, m = ms->mirror; i < ms->nr_mirrors; i++, m++)
 		map_region(dest++, m, bio);
 
@@ -670,7 +676,8 @@ static void do_writes(struct mirror_set
 	bio_list_init(&requeue);
 
 	while ((bio = bio_list_pop(writes))) {
-		if (bio->bi_rw & REQ_FLUSH) {
+		if ((bio->bi_rw & REQ_FLUSH) ||
+		    (bio->bi_rw & REQ_DISCARD)) {
 			bio_list_add(&sync, bio);
 			continue;
 		}
@@ -1076,8 +1083,10 @@ static int mirror_ctr(struct dm_target *
 	ti->private = ms;
 	ti->split_io = dm_rh_get_region_size(ms->rh);
 	ti->num_flush_requests = 1;
+	ti->num_discard_requests = 1;
 
-	ms->kmirrord_wq = create_singlethread_workqueue("kmirrord");
+	ms->kmirrord_wq = alloc_workqueue("kmirrord",
+					  WQ_NON_REENTRANT | WQ_MEM_RECLAIM, 0);
 	if (!ms->kmirrord_wq) {
 		DMERR("couldn't start kmirrord");
 		r = -ENOMEM;
@@ -1130,7 +1139,7 @@ static void mirror_dtr(struct dm_target
 
 	del_timer_sync(&ms->timer);
 	flush_workqueue(ms->kmirrord_wq);
-	flush_scheduled_work();
+	flush_work_sync(&ms->trigger_event);
 	dm_kcopyd_client_destroy(ms->kcopyd_client);
 	destroy_workqueue(ms->kmirrord_wq);
 	free_context(ms, ti, ms->nr_mirrors);
@@ -1406,7 +1415,7 @@ static int mirror_iterate_devices(struct
 
 static struct target_type mirror_target = {
 	.name	 = "mirror",
-	.version = {1, 12, 0},
+	.version = {1, 12, 1},
 	.module	 = THIS_MODULE,
 	.ctr	 = mirror_ctr,
 	.dtr	 = mirror_dtr,
diff -druNp linux-libre-2.6.37-gnu1/drivers/md/dm-raid.c linux-libre-2.6.38-gnu1/drivers/md/dm-raid.c
--- linux-libre-2.6.37-gnu1/drivers/md/dm-raid.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/md/dm-raid.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,697 @@
+/*
+ * Copyright (C) 2010-2011 Neil Brown
+ * Copyright (C) 2010-2011 Red Hat, Inc. All rights reserved.
+ *
+ * This file is released under the GPL.
+ */
+
+#include <linux/slab.h>
+
+#include "md.h"
+#include "raid5.h"
+#include "dm.h"
+#include "bitmap.h"
+
+#define DM_MSG_PREFIX "raid"
+
+/*
+ * If the MD doesn't support MD_SYNC_STATE_FORCED yet, then
+ * make it so the flag doesn't set anything.
+ */
+#ifndef MD_SYNC_STATE_FORCED
+#define MD_SYNC_STATE_FORCED 0
+#endif
+
+struct raid_dev {
+	/*
+	 * Two DM devices, one to hold metadata and one to hold the
+	 * actual data/parity.  The reason for this is to not confuse
+	 * ti->len and give more flexibility in altering size and
+	 * characteristics.
+	 *
+	 * While it is possible for this device to be associated
+	 * with a different physical device than the data_dev, it
+	 * is intended for it to be the same.
+	 *    |--------- Physical Device ---------|
+	 *    |- meta_dev -|------ data_dev ------|
+	 */
+	struct dm_dev *meta_dev;
+	struct dm_dev *data_dev;
+	struct mdk_rdev_s rdev;
+};
+
+/*
+ * Flags for rs->print_flags field.
+ */
+#define DMPF_DAEMON_SLEEP      0x1
+#define DMPF_MAX_WRITE_BEHIND  0x2
+#define DMPF_SYNC              0x4
+#define DMPF_NOSYNC            0x8
+#define DMPF_STRIPE_CACHE      0x10
+#define DMPF_MIN_RECOVERY_RATE 0x20
+#define DMPF_MAX_RECOVERY_RATE 0x40
+
+struct raid_set {
+	struct dm_target *ti;
+
+	uint64_t print_flags;
+
+	struct mddev_s md;
+	struct raid_type *raid_type;
+	struct dm_target_callbacks callbacks;
+
+	struct raid_dev dev[0];
+};
+
+/* Supported raid types and properties. */
+static struct raid_type {
+	const char *name;		/* RAID algorithm. */
+	const char *descr;		/* Descriptor text for logging. */
+	const unsigned parity_devs;	/* # of parity devices. */
+	const unsigned minimal_devs;	/* minimal # of devices in set. */
+	const unsigned level;		/* RAID level. */
+	const unsigned algorithm;	/* RAID algorithm. */
+} raid_types[] = {
+	{"raid4",    "RAID4 (dedicated parity disk)",	1, 2, 5, ALGORITHM_PARITY_0},
+	{"raid5_la", "RAID5 (left asymmetric)",		1, 2, 5, ALGORITHM_LEFT_ASYMMETRIC},
+	{"raid5_ra", "RAID5 (right asymmetric)",	1, 2, 5, ALGORITHM_RIGHT_ASYMMETRIC},
+	{"raid5_ls", "RAID5 (left symmetric)",		1, 2, 5, ALGORITHM_LEFT_SYMMETRIC},
+	{"raid5_rs", "RAID5 (right symmetric)",		1, 2, 5, ALGORITHM_RIGHT_SYMMETRIC},
+	{"raid6_zr", "RAID6 (zero restart)",		2, 4, 6, ALGORITHM_ROTATING_ZERO_RESTART},
+	{"raid6_nr", "RAID6 (N restart)",		2, 4, 6, ALGORITHM_ROTATING_N_RESTART},
+	{"raid6_nc", "RAID6 (N continue)",		2, 4, 6, ALGORITHM_ROTATING_N_CONTINUE}
+};
+
+static struct raid_type *get_raid_type(char *name)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(raid_types); i++)
+		if (!strcmp(raid_types[i].name, name))
+			return &raid_types[i];
+
+	return NULL;
+}
+
+static struct raid_set *context_alloc(struct dm_target *ti, struct raid_type *raid_type, unsigned raid_devs)
+{
+	unsigned i;
+	struct raid_set *rs;
+	sector_t sectors_per_dev;
+
+	if (raid_devs <= raid_type->parity_devs) {
+		ti->error = "Insufficient number of devices";
+		return ERR_PTR(-EINVAL);
+	}
+
+	sectors_per_dev = ti->len;
+	if (sector_div(sectors_per_dev, (raid_devs - raid_type->parity_devs))) {
+		ti->error = "Target length not divisible by number of data devices";
+		return ERR_PTR(-EINVAL);
+	}
+
+	rs = kzalloc(sizeof(*rs) + raid_devs * sizeof(rs->dev[0]), GFP_KERNEL);
+	if (!rs) {
+		ti->error = "Cannot allocate raid context";
+		return ERR_PTR(-ENOMEM);
+	}
+
+	mddev_init(&rs->md);
+
+	rs->ti = ti;
+	rs->raid_type = raid_type;
+	rs->md.raid_disks = raid_devs;
+	rs->md.level = raid_type->level;
+	rs->md.new_level = rs->md.level;
+	rs->md.dev_sectors = sectors_per_dev;
+	rs->md.layout = raid_type->algorithm;
+	rs->md.new_layout = rs->md.layout;
+	rs->md.delta_disks = 0;
+	rs->md.recovery_cp = 0;
+
+	for (i = 0; i < raid_devs; i++)
+		md_rdev_init(&rs->dev[i].rdev);
+
+	/*
+	 * Remaining items to be initialized by further RAID params:
+	 *  rs->md.persistent
+	 *  rs->md.external
+	 *  rs->md.chunk_sectors
+	 *  rs->md.new_chunk_sectors
+	 */
+
+	return rs;
+}
+
+static void context_free(struct raid_set *rs)
+{
+	int i;
+
+	for (i = 0; i < rs->md.raid_disks; i++)
+		if (rs->dev[i].data_dev)
+			dm_put_device(rs->ti, rs->dev[i].data_dev);
+
+	kfree(rs);
+}
+
+/*
+ * For every device we have two words
+ *  <meta_dev>: meta device name or '-' if missing
+ *  <data_dev>: data device name or '-' if missing
+ *
+ * This code parses those words.
+ */
+static int dev_parms(struct raid_set *rs, char **argv)
+{
+	int i;
+	int rebuild = 0;
+	int metadata_available = 0;
+	int ret = 0;
+
+	for (i = 0; i < rs->md.raid_disks; i++, argv += 2) {
+		rs->dev[i].rdev.raid_disk = i;
+
+		rs->dev[i].meta_dev = NULL;
+		rs->dev[i].data_dev = NULL;
+
+		/*
+		 * There are no offsets, since there is a separate device
+		 * for data and metadata.
+		 */
+		rs->dev[i].rdev.data_offset = 0;
+		rs->dev[i].rdev.mddev = &rs->md;
+
+		if (strcmp(argv[0], "-")) {
+			rs->ti->error = "Metadata devices not supported";
+			return -EINVAL;
+		}
+
+		if (!strcmp(argv[1], "-")) {
+			if (!test_bit(In_sync, &rs->dev[i].rdev.flags) &&
+			    (!rs->dev[i].rdev.recovery_offset)) {
+				rs->ti->error = "Drive designated for rebuild not specified";
+				return -EINVAL;
+			}
+
+			continue;
+		}
+
+		ret = dm_get_device(rs->ti, argv[1],
+				    dm_table_get_mode(rs->ti->table),
+				    &rs->dev[i].data_dev);
+		if (ret) {
+			rs->ti->error = "RAID device lookup failure";
+			return ret;
+		}
+
+		rs->dev[i].rdev.bdev = rs->dev[i].data_dev->bdev;
+		list_add(&rs->dev[i].rdev.same_set, &rs->md.disks);
+		if (!test_bit(In_sync, &rs->dev[i].rdev.flags))
+			rebuild++;
+	}
+
+	if (metadata_available) {
+		rs->md.external = 0;
+		rs->md.persistent = 1;
+		rs->md.major_version = 2;
+	} else if (rebuild && !rs->md.recovery_cp) {
+		/*
+		 * Without metadata, we will not be able to tell if the array
+		 * is in-sync or not - we must assume it is not.  Therefore,
+		 * it is impossible to rebuild a drive.
+		 *
+		 * Even if there is metadata, the on-disk information may
+		 * indicate that the array is not in-sync and it will then
+		 * fail at that time.
+		 *
+		 * User could specify 'nosync' option if desperate.
+		 */
+		DMERR("Unable to rebuild drive while array is not in-sync");
+		rs->ti->error = "RAID device lookup failure";
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/*
+ * Possible arguments are...
+ * RAID456:
+ *	<chunk_size> [optional_args]
+ *
+ * Optional args:
+ *    [[no]sync]			Force or prevent recovery of the entire array
+ *    [rebuild <idx>]			Rebuild the drive indicated by the index
+ *    [daemon_sleep <ms>]		Time between bitmap daemon work to clear bits
+ *    [min_recovery_rate <kB/sec/disk>]	Throttle RAID initialization
+ *    [max_recovery_rate <kB/sec/disk>]	Throttle RAID initialization
+ *    [max_write_behind <sectors>]	See '-write-behind=' (man mdadm)
+ *    [stripe_cache <sectors>]		Stripe cache size for higher RAIDs
+ */
+static int parse_raid_params(struct raid_set *rs, char **argv,
+			     unsigned num_raid_params)
+{
+	unsigned i, rebuild_cnt = 0;
+	unsigned long value;
+	char *key;
+
+	/*
+	 * First, parse the in-order required arguments
+	 */
+	if ((strict_strtoul(argv[0], 10, &value) < 0) ||
+	    !is_power_of_2(value) || (value < 8)) {
+		rs->ti->error = "Bad chunk size";
+		return -EINVAL;
+	}
+
+	rs->md.new_chunk_sectors = rs->md.chunk_sectors = value;
+	argv++;
+	num_raid_params--;
+
+	/*
+	 * Second, parse the unordered optional arguments
+	 */
+	for (i = 0; i < rs->md.raid_disks; i++)
+		set_bit(In_sync, &rs->dev[i].rdev.flags);
+
+	for (i = 0; i < num_raid_params; i++) {
+		if (!strcmp(argv[i], "nosync")) {
+			rs->md.recovery_cp = MaxSector;
+			rs->print_flags |= DMPF_NOSYNC;
+			rs->md.flags |= MD_SYNC_STATE_FORCED;
+			continue;
+		}
+		if (!strcmp(argv[i], "sync")) {
+			rs->md.recovery_cp = 0;
+			rs->print_flags |= DMPF_SYNC;
+			rs->md.flags |= MD_SYNC_STATE_FORCED;
+			continue;
+		}
+
+		/* The rest of the optional arguments come in key/value pairs */
+		if ((i + 1) >= num_raid_params) {
+			rs->ti->error = "Wrong number of raid parameters given";
+			return -EINVAL;
+		}
+
+		key = argv[i++];
+		if (strict_strtoul(argv[i], 10, &value) < 0) {
+			rs->ti->error = "Bad numerical argument given in raid params";
+			return -EINVAL;
+		}
+
+		if (!strcmp(key, "rebuild")) {
+			if (++rebuild_cnt > rs->raid_type->parity_devs) {
+				rs->ti->error = "Too many rebuild drives given";
+				return -EINVAL;
+			}
+			if (value > rs->md.raid_disks) {
+				rs->ti->error = "Invalid rebuild index given";
+				return -EINVAL;
+			}
+			clear_bit(In_sync, &rs->dev[value].rdev.flags);
+			rs->dev[value].rdev.recovery_offset = 0;
+		} else if (!strcmp(key, "max_write_behind")) {
+			rs->print_flags |= DMPF_MAX_WRITE_BEHIND;
+
+			/*
+			 * In device-mapper, we specify things in sectors, but
+			 * MD records this value in kB
+			 */
+			value /= 2;
+			if (value > COUNTER_MAX) {
+				rs->ti->error = "Max write-behind limit out of range";
+				return -EINVAL;
+			}
+			rs->md.bitmap_info.max_write_behind = value;
+		} else if (!strcmp(key, "daemon_sleep")) {
+			rs->print_flags |= DMPF_DAEMON_SLEEP;
+			if (!value || (value > MAX_SCHEDULE_TIMEOUT)) {
+				rs->ti->error = "daemon sleep period out of range";
+				return -EINVAL;
+			}
+			rs->md.bitmap_info.daemon_sleep = value;
+		} else if (!strcmp(key, "stripe_cache")) {
+			rs->print_flags |= DMPF_STRIPE_CACHE;
+
+			/*
+			 * In device-mapper, we specify things in sectors, but
+			 * MD records this value in kB
+			 */
+			value /= 2;
+
+			if (rs->raid_type->level < 5) {
+				rs->ti->error = "Inappropriate argument: stripe_cache";
+				return -EINVAL;
+			}
+			if (raid5_set_cache_size(&rs->md, (int)value)) {
+				rs->ti->error = "Bad stripe_cache size";
+				return -EINVAL;
+			}
+		} else if (!strcmp(key, "min_recovery_rate")) {
+			rs->print_flags |= DMPF_MIN_RECOVERY_RATE;
+			if (value > INT_MAX) {
+				rs->ti->error = "min_recovery_rate out of range";
+				return -EINVAL;
+			}
+			rs->md.sync_speed_min = (int)value;
+		} else if (!strcmp(key, "max_recovery_rate")) {
+			rs->print_flags |= DMPF_MAX_RECOVERY_RATE;
+			if (value > INT_MAX) {
+				rs->ti->error = "max_recovery_rate out of range";
+				return -EINVAL;
+			}
+			rs->md.sync_speed_max = (int)value;
+		} else {
+			DMERR("Unable to parse RAID parameter: %s", key);
+			rs->ti->error = "Unable to parse RAID parameters";
+			return -EINVAL;
+		}
+	}
+
+	/* Assume there are no metadata devices until the drives are parsed */
+	rs->md.persistent = 0;
+	rs->md.external = 1;
+
+	return 0;
+}
+
+static void do_table_event(struct work_struct *ws)
+{
+	struct raid_set *rs = container_of(ws, struct raid_set, md.event_work);
+
+	dm_table_event(rs->ti->table);
+}
+
+static int raid_is_congested(struct dm_target_callbacks *cb, int bits)
+{
+	struct raid_set *rs = container_of(cb, struct raid_set, callbacks);
+
+	return md_raid5_congested(&rs->md, bits);
+}
+
+static void raid_unplug(struct dm_target_callbacks *cb)
+{
+	struct raid_set *rs = container_of(cb, struct raid_set, callbacks);
+
+	md_raid5_unplug_device(rs->md.private);
+}
+
+/*
+ * Construct a RAID4/5/6 mapping:
+ * Args:
+ *	<raid_type> <#raid_params> <raid_params>		\
+ *	<#raid_devs> { <meta_dev1> <dev1> .. <meta_devN> <devN> }
+ *
+ * ** metadata devices are not supported yet, use '-' instead **
+ *
+ * <raid_params> varies by <raid_type>.  See 'parse_raid_params' for
+ * details on possible <raid_params>.
+ */
+static int raid_ctr(struct dm_target *ti, unsigned argc, char **argv)
+{
+	int ret;
+	struct raid_type *rt;
+	unsigned long num_raid_params, num_raid_devs;
+	struct raid_set *rs = NULL;
+
+	/* Must have at least <raid_type> <#raid_params> */
+	if (argc < 2) {
+		ti->error = "Too few arguments";
+		return -EINVAL;
+	}
+
+	/* raid type */
+	rt = get_raid_type(argv[0]);
+	if (!rt) {
+		ti->error = "Unrecognised raid_type";
+		return -EINVAL;
+	}
+	argc--;
+	argv++;
+
+	/* number of RAID parameters */
+	if (strict_strtoul(argv[0], 10, &num_raid_params) < 0) {
+		ti->error = "Cannot understand number of RAID parameters";
+		return -EINVAL;
+	}
+	argc--;
+	argv++;
+
+	/* Skip over RAID params for now and find out # of devices */
+	if (num_raid_params + 1 > argc) {
+		ti->error = "Arguments do not agree with counts given";
+		return -EINVAL;
+	}
+
+	if ((strict_strtoul(argv[num_raid_params], 10, &num_raid_devs) < 0) ||
+	    (num_raid_devs >= INT_MAX)) {
+		ti->error = "Cannot understand number of raid devices";
+		return -EINVAL;
+	}
+
+	rs = context_alloc(ti, rt, (unsigned)num_raid_devs);
+	if (IS_ERR(rs))
+		return PTR_ERR(rs);
+
+	ret = parse_raid_params(rs, argv, (unsigned)num_raid_params);
+	if (ret)
+		goto bad;
+
+	ret = -EINVAL;
+
+	argc -= num_raid_params + 1; /* +1: we already have num_raid_devs */
+	argv += num_raid_params + 1;
+
+	if (argc != (num_raid_devs * 2)) {
+		ti->error = "Supplied RAID devices does not match the count given";
+		goto bad;
+	}
+
+	ret = dev_parms(rs, argv);
+	if (ret)
+		goto bad;
+
+	INIT_WORK(&rs->md.event_work, do_table_event);
+	ti->split_io = rs->md.chunk_sectors;
+	ti->private = rs;
+
+	mutex_lock(&rs->md.reconfig_mutex);
+	ret = md_run(&rs->md);
+	rs->md.in_sync = 0; /* Assume already marked dirty */
+	mutex_unlock(&rs->md.reconfig_mutex);
+
+	if (ret) {
+		ti->error = "Fail to run raid array";
+		goto bad;
+	}
+
+	rs->callbacks.congested_fn = raid_is_congested;
+	rs->callbacks.unplug_fn = raid_unplug;
+	dm_table_add_target_callbacks(ti->table, &rs->callbacks);
+
+	return 0;
+
+bad:
+	context_free(rs);
+
+	return ret;
+}
+
+static void raid_dtr(struct dm_target *ti)
+{
+	struct raid_set *rs = ti->private;
+
+	list_del_init(&rs->callbacks.list);
+	md_stop(&rs->md);
+	context_free(rs);
+}
+
+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;
+
+	mddev->pers->make_request(mddev, bio);
+
+	return DM_MAPIO_SUBMITTED;
+}
+
+static int raid_status(struct dm_target *ti, status_type_t type,
+		       char *result, unsigned maxlen)
+{
+	struct raid_set *rs = ti->private;
+	unsigned raid_param_cnt = 1; /* at least 1 for chunksize */
+	unsigned sz = 0;
+	int i;
+	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)
+			sync = rs->md.resync_max_sectors;
+
+		DMEMIT(" %llu/%llu",
+		       (unsigned long long) sync,
+		       (unsigned long long) rs->md.resync_max_sectors);
+
+		break;
+	case STATUSTYPE_TABLE:
+		/* The string you would use to construct this array */
+		for (i = 0; i < rs->md.raid_disks; i++)
+			if (rs->dev[i].data_dev &&
+			    !test_bit(In_sync, &rs->dev[i].rdev.flags))
+				raid_param_cnt++; /* for rebuilds */
+
+		raid_param_cnt += (hweight64(rs->print_flags) * 2);
+		if (rs->print_flags & (DMPF_SYNC | DMPF_NOSYNC))
+			raid_param_cnt--;
+
+		DMEMIT("%s %u %u", rs->raid_type->name,
+		       raid_param_cnt, rs->md.chunk_sectors);
+
+		if ((rs->print_flags & DMPF_SYNC) &&
+		    (rs->md.recovery_cp == MaxSector))
+			DMEMIT(" sync");
+		if (rs->print_flags & DMPF_NOSYNC)
+			DMEMIT(" nosync");
+
+		for (i = 0; i < rs->md.raid_disks; i++)
+			if (rs->dev[i].data_dev &&
+			    !test_bit(In_sync, &rs->dev[i].rdev.flags))
+				DMEMIT(" rebuild %u", i);
+
+		if (rs->print_flags & DMPF_DAEMON_SLEEP)
+			DMEMIT(" daemon_sleep %lu",
+			       rs->md.bitmap_info.daemon_sleep);
+
+		if (rs->print_flags & DMPF_MIN_RECOVERY_RATE)
+			DMEMIT(" min_recovery_rate %d", rs->md.sync_speed_min);
+
+		if (rs->print_flags & DMPF_MAX_RECOVERY_RATE)
+			DMEMIT(" max_recovery_rate %d", rs->md.sync_speed_max);
+
+		if (rs->print_flags & DMPF_MAX_WRITE_BEHIND)
+			DMEMIT(" max_write_behind %lu",
+			       rs->md.bitmap_info.max_write_behind);
+
+		if (rs->print_flags & DMPF_STRIPE_CACHE) {
+			raid5_conf_t *conf = rs->md.private;
+
+			/* convert from kiB to sectors */
+			DMEMIT(" stripe_cache %d",
+			       conf ? conf->max_nr_stripes * 2 : 0);
+		}
+
+		DMEMIT(" %d", rs->md.raid_disks);
+		for (i = 0; i < rs->md.raid_disks; i++) {
+			DMEMIT(" -"); /* metadata device */
+
+			if (rs->dev[i].data_dev)
+				DMEMIT(" %s", rs->dev[i].data_dev->name);
+			else
+				DMEMIT(" -");
+		}
+	}
+
+	return 0;
+}
+
+static int raid_iterate_devices(struct dm_target *ti, iterate_devices_callout_fn fn, void *data)
+{
+	struct raid_set *rs = ti->private;
+	unsigned i;
+	int ret = 0;
+
+	for (i = 0; !ret && i < rs->md.raid_disks; i++)
+		if (rs->dev[i].data_dev)
+			ret = fn(ti,
+				 rs->dev[i].data_dev,
+				 0, /* No offset on data devs */
+				 rs->md.dev_sectors,
+				 data);
+
+	return ret;
+}
+
+static void raid_io_hints(struct dm_target *ti, struct queue_limits *limits)
+{
+	struct raid_set *rs = ti->private;
+	unsigned chunk_size = rs->md.chunk_sectors << 9;
+	raid5_conf_t *conf = rs->md.private;
+
+	blk_limits_io_min(limits, chunk_size);
+	blk_limits_io_opt(limits, chunk_size * (conf->raid_disks - conf->max_degraded));
+}
+
+static void raid_presuspend(struct dm_target *ti)
+{
+	struct raid_set *rs = ti->private;
+
+	md_stop_writes(&rs->md);
+}
+
+static void raid_postsuspend(struct dm_target *ti)
+{
+	struct raid_set *rs = ti->private;
+
+	mddev_suspend(&rs->md);
+}
+
+static void raid_resume(struct dm_target *ti)
+{
+	struct raid_set *rs = ti->private;
+
+	mddev_resume(&rs->md);
+}
+
+static struct target_type raid_target = {
+	.name = "raid",
+	.version = {1, 0, 0},
+	.module = THIS_MODULE,
+	.ctr = raid_ctr,
+	.dtr = raid_dtr,
+	.map = raid_map,
+	.status = raid_status,
+	.iterate_devices = raid_iterate_devices,
+	.io_hints = raid_io_hints,
+	.presuspend = raid_presuspend,
+	.postsuspend = raid_postsuspend,
+	.resume = raid_resume,
+};
+
+static int __init dm_raid_init(void)
+{
+	return dm_register_target(&raid_target);
+}
+
+static void __exit dm_raid_exit(void)
+{
+	dm_unregister_target(&raid_target);
+}
+
+module_init(dm_raid_init);
+module_exit(dm_raid_exit);
+
+MODULE_DESCRIPTION(DM_NAME " raid4/5/6 target");
+MODULE_ALIAS("dm-raid4");
+MODULE_ALIAS("dm-raid5");
+MODULE_ALIAS("dm-raid6");
+MODULE_AUTHOR("Neil Brown <dm-devel@redhat.com>");
+MODULE_LICENSE("GPL");
diff -druNp linux-libre-2.6.37-gnu1/drivers/md/dm-snap.c linux-libre-2.6.38-gnu1/drivers/md/dm-snap.c
--- linux-libre-2.6.37-gnu1/drivers/md/dm-snap.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/md/dm-snap.c	2011-03-14 21:20:32.000000000 -0400
@@ -19,7 +19,6 @@
 #include <linux/vmalloc.h>
 #include <linux/log2.h>
 #include <linux/dm-kcopyd.h>
-#include <linux/workqueue.h>
 
 #include "dm-exception-store.h"
 
@@ -80,9 +79,6 @@ struct dm_snapshot {
 	/* Origin writes don't trigger exceptions until this is set */
 	int active;
 
-	/* Whether or not owning mapped_device is suspended */
-	int suspended;
-
 	atomic_t pending_exceptions_count;
 
 	mempool_t *pending_pool;
@@ -106,10 +102,6 @@ struct dm_snapshot {
 
 	struct dm_kcopyd_client *kcopyd_client;
 
-	/* Queue of snapshot writes for ksnapd to flush */
-	struct bio_list queued_bios;
-	struct work_struct queued_bios_work;
-
 	/* Wait for events based on state_bits */
 	unsigned long state_bits;
 
@@ -160,9 +152,6 @@ struct dm_dev *dm_snap_cow(struct dm_sna
 }
 EXPORT_SYMBOL(dm_snap_cow);
 
-static struct workqueue_struct *ksnapd;
-static void flush_queued_bios(struct work_struct *work);
-
 static sector_t chunk_to_sector(struct dm_exception_store *store,
 				chunk_t chunk)
 {
@@ -1110,7 +1099,6 @@ static int snapshot_ctr(struct dm_target
 	s->ti = ti;
 	s->valid = 1;
 	s->active = 0;
-	s->suspended = 0;
 	atomic_set(&s->pending_exceptions_count, 0);
 	init_rwsem(&s->lock);
 	INIT_LIST_HEAD(&s->list);
@@ -1153,9 +1141,6 @@ static int snapshot_ctr(struct dm_target
 
 	spin_lock_init(&s->tracked_chunk_lock);
 
-	bio_list_init(&s->queued_bios);
-	INIT_WORK(&s->queued_bios_work, flush_queued_bios);
-
 	ti->private = s;
 	ti->num_flush_requests = num_flush_requests;
 
@@ -1279,8 +1264,6 @@ static void snapshot_dtr(struct dm_targe
 	struct dm_snapshot *s = ti->private;
 	struct dm_snapshot *snap_src = NULL, *snap_dest = NULL;
 
-	flush_workqueue(ksnapd);
-
 	down_read(&_origins_lock);
 	/* Check whether exception handover must be cancelled */
 	(void) __find_snapshots_sharing_cow(s, &snap_src, &snap_dest, NULL);
@@ -1342,20 +1325,6 @@ static void flush_bios(struct bio *bio)
 	}
 }
 
-static void flush_queued_bios(struct work_struct *work)
-{
-	struct dm_snapshot *s =
-		container_of(work, struct dm_snapshot, queued_bios_work);
-	struct bio *queued_bios;
-	unsigned long flags;
-
-	spin_lock_irqsave(&s->pe_lock, flags);
-	queued_bios = bio_list_get(&s->queued_bios);
-	spin_unlock_irqrestore(&s->pe_lock, flags);
-
-	flush_bios(queued_bios);
-}
-
 static int do_origin(struct dm_dev *origin, struct bio *bio);
 
 /*
@@ -1760,15 +1729,6 @@ static void snapshot_merge_presuspend(st
 	stop_merge(s);
 }
 
-static void snapshot_postsuspend(struct dm_target *ti)
-{
-	struct dm_snapshot *s = ti->private;
-
-	down_write(&s->lock);
-	s->suspended = 1;
-	up_write(&s->lock);
-}
-
 static int snapshot_preresume(struct dm_target *ti)
 {
 	int r = 0;
@@ -1783,7 +1743,7 @@ static int snapshot_preresume(struct dm_
 			DMERR("Unable to resume snapshot source until "
 			      "handover completes.");
 			r = -EINVAL;
-		} else if (!snap_src->suspended) {
+		} else if (!dm_suspended(snap_src->ti)) {
 			DMERR("Unable to perform snapshot handover until "
 			      "source is suspended.");
 			r = -EINVAL;
@@ -1816,7 +1776,6 @@ static void snapshot_resume(struct dm_ta
 
 	down_write(&s->lock);
 	s->active = 1;
-	s->suspended = 0;
 	up_write(&s->lock);
 }
 
@@ -2194,7 +2153,7 @@ static int origin_iterate_devices(struct
 
 static struct target_type origin_target = {
 	.name    = "snapshot-origin",
-	.version = {1, 7, 0},
+	.version = {1, 7, 1},
 	.module  = THIS_MODULE,
 	.ctr     = origin_ctr,
 	.dtr     = origin_dtr,
@@ -2207,13 +2166,12 @@ static struct target_type origin_target
 
 static struct target_type snapshot_target = {
 	.name    = "snapshot",
-	.version = {1, 9, 0},
+	.version = {1, 10, 0},
 	.module  = THIS_MODULE,
 	.ctr     = snapshot_ctr,
 	.dtr     = snapshot_dtr,
 	.map     = snapshot_map,
 	.end_io  = snapshot_end_io,
-	.postsuspend = snapshot_postsuspend,
 	.preresume  = snapshot_preresume,
 	.resume  = snapshot_resume,
 	.status  = snapshot_status,
@@ -2222,14 +2180,13 @@ static struct target_type snapshot_targe
 
 static struct target_type merge_target = {
 	.name    = dm_snapshot_merge_target_name,
-	.version = {1, 0, 0},
+	.version = {1, 1, 0},
 	.module  = THIS_MODULE,
 	.ctr     = snapshot_ctr,
 	.dtr     = snapshot_dtr,
 	.map     = snapshot_merge_map,
 	.end_io  = snapshot_end_io,
 	.presuspend = snapshot_merge_presuspend,
-	.postsuspend = snapshot_postsuspend,
 	.preresume  = snapshot_preresume,
 	.resume  = snapshot_merge_resume,
 	.status  = snapshot_status,
@@ -2291,17 +2248,8 @@ static int __init dm_snapshot_init(void)
 		goto bad_tracked_chunk_cache;
 	}
 
-	ksnapd = create_singlethread_workqueue("ksnapd");
-	if (!ksnapd) {
-		DMERR("Failed to create ksnapd workqueue.");
-		r = -ENOMEM;
-		goto bad_pending_pool;
-	}
-
 	return 0;
 
-bad_pending_pool:
-	kmem_cache_destroy(tracked_chunk_cache);
 bad_tracked_chunk_cache:
 	kmem_cache_destroy(pending_cache);
 bad_pending_cache:
@@ -2322,8 +2270,6 @@ bad_register_snapshot_target:
 
 static void __exit dm_snapshot_exit(void)
 {
-	destroy_workqueue(ksnapd);
-
 	dm_unregister_target(&snapshot_target);
 	dm_unregister_target(&origin_target);
 	dm_unregister_target(&merge_target);
diff -druNp linux-libre-2.6.37-gnu1/drivers/md/dm-snap-persistent.c linux-libre-2.6.38-gnu1/drivers/md/dm-snap-persistent.c
--- linux-libre-2.6.37-gnu1/drivers/md/dm-snap-persistent.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/md/dm-snap-persistent.c	2011-03-14 21:20:32.000000000 -0400
@@ -256,7 +256,7 @@ static int chunk_io(struct pstore *ps, v
 	 */
 	INIT_WORK_ONSTACK(&req.work, do_metadata);
 	queue_work(ps->metadata_wq, &req.work);
-	flush_workqueue(ps->metadata_wq);
+	flush_work(&req.work);
 
 	return req.result;
 }
@@ -818,7 +818,7 @@ static int persistent_ctr(struct dm_exce
 	atomic_set(&ps->pending_count, 0);
 	ps->callbacks = NULL;
 
-	ps->metadata_wq = create_singlethread_workqueue("ksnaphd");
+	ps->metadata_wq = alloc_workqueue("ksnaphd", WQ_MEM_RECLAIM, 0);
 	if (!ps->metadata_wq) {
 		kfree(ps);
 		DMERR("couldn't start header metadata update thread");
diff -druNp linux-libre-2.6.37-gnu1/drivers/md/dm-stripe.c linux-libre-2.6.38-gnu1/drivers/md/dm-stripe.c
--- linux-libre-2.6.37-gnu1/drivers/md/dm-stripe.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/md/dm-stripe.c	2011-03-14 21:20:32.000000000 -0400
@@ -39,23 +39,20 @@ struct stripe_c {
 	struct dm_target *ti;
 
 	/* Work struct used for triggering events*/
-	struct work_struct kstriped_ws;
+	struct work_struct trigger_event;
 
 	struct stripe stripe[0];
 };
 
-static struct workqueue_struct *kstriped;
-
 /*
  * An event is triggered whenever a drive
  * drops out of a stripe volume.
  */
 static void trigger_event(struct work_struct *work)
 {
-	struct stripe_c *sc = container_of(work, struct stripe_c, kstriped_ws);
-
+	struct stripe_c *sc = container_of(work, struct stripe_c,
+					   trigger_event);
 	dm_table_event(sc->ti->table);
-
 }
 
 static inline struct stripe_c *alloc_context(unsigned int stripes)
@@ -160,7 +157,7 @@ static int stripe_ctr(struct dm_target *
 		return -ENOMEM;
 	}
 
-	INIT_WORK(&sc->kstriped_ws, trigger_event);
+	INIT_WORK(&sc->trigger_event, trigger_event);
 
 	/* Set pointer to dm target; used in trigger_event */
 	sc->ti = ti;
@@ -211,7 +208,7 @@ static void stripe_dtr(struct dm_target
 	for (i = 0; i < sc->stripes; i++)
 		dm_put_device(ti, sc->stripe[i].dev);
 
-	flush_workqueue(kstriped);
+	flush_work_sync(&sc->trigger_event);
 	kfree(sc);
 }
 
@@ -367,7 +364,7 @@ static int stripe_end_io(struct dm_targe
 			atomic_inc(&(sc->stripe[i].error_count));
 			if (atomic_read(&(sc->stripe[i].error_count)) <
 			    DM_IO_ERROR_THRESHOLD)
-				queue_work(kstriped, &sc->kstriped_ws);
+				schedule_work(&sc->trigger_event);
 		}
 
 	return error;
@@ -401,7 +398,7 @@ static void stripe_io_hints(struct dm_ta
 
 static struct target_type stripe_target = {
 	.name   = "striped",
-	.version = {1, 3, 0},
+	.version = {1, 3, 1},
 	.module = THIS_MODULE,
 	.ctr    = stripe_ctr,
 	.dtr    = stripe_dtr,
@@ -422,20 +419,10 @@ int __init dm_stripe_init(void)
 		return r;
 	}
 
-	kstriped = create_singlethread_workqueue("kstriped");
-	if (!kstriped) {
-		DMERR("failed to create workqueue kstriped");
-		dm_unregister_target(&stripe_target);
-		return -ENOMEM;
-	}
-
 	return r;
 }
 
 void dm_stripe_exit(void)
 {
 	dm_unregister_target(&stripe_target);
-	destroy_workqueue(kstriped);
-
-	return;
 }
diff -druNp linux-libre-2.6.37-gnu1/drivers/md/dm-table.c linux-libre-2.6.38-gnu1/drivers/md/dm-table.c
--- linux-libre-2.6.37-gnu1/drivers/md/dm-table.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/md/dm-table.c	2011-03-14 21:20:32.000000000 -0400
@@ -71,6 +71,8 @@ struct dm_table {
 	void *event_context;
 
 	struct dm_md_mempools *mempools;
+
+	struct list_head target_callbacks;
 };
 
 /*
@@ -204,6 +206,7 @@ int dm_table_create(struct dm_table **re
 		return -ENOMEM;
 
 	INIT_LIST_HEAD(&t->devices);
+	INIT_LIST_HEAD(&t->target_callbacks);
 	atomic_set(&t->holders, 0);
 	t->discards_supported = 1;
 
@@ -325,15 +328,18 @@ static int open_dev(struct dm_dev_intern
 
 	BUG_ON(d->dm_dev.bdev);
 
-	bdev = open_by_devnum(dev, d->dm_dev.mode);
+	bdev = blkdev_get_by_dev(dev, d->dm_dev.mode | FMODE_EXCL, _claim_ptr);
 	if (IS_ERR(bdev))
 		return PTR_ERR(bdev);
-	r = bd_claim_by_disk(bdev, _claim_ptr, dm_disk(md));
-	if (r)
-		blkdev_put(bdev, d->dm_dev.mode);
-	else
-		d->dm_dev.bdev = bdev;
-	return r;
+
+	r = bd_link_disk_holder(bdev, dm_disk(md));
+	if (r) {
+		blkdev_put(bdev, d->dm_dev.mode | FMODE_EXCL);
+		return r;
+	}
+
+	d->dm_dev.bdev = bdev;
+	return 0;
 }
 
 /*
@@ -344,8 +350,8 @@ static void close_dev(struct dm_dev_inte
 	if (!d->dm_dev.bdev)
 		return;
 
-	bd_release_from_disk(d->dm_dev.bdev, dm_disk(md));
-	blkdev_put(d->dm_dev.bdev, d->dm_dev.mode);
+	bd_unlink_disk_holder(d->dm_dev.bdev, dm_disk(md));
+	blkdev_put(d->dm_dev.bdev, d->dm_dev.mode | FMODE_EXCL);
 	d->dm_dev.bdev = NULL;
 }
 
@@ -1223,10 +1229,17 @@ int dm_table_resume_targets(struct dm_ta
 	return 0;
 }
 
+void dm_table_add_target_callbacks(struct dm_table *t, struct dm_target_callbacks *cb)
+{
+	list_add(&cb->list, &t->target_callbacks);
+}
+EXPORT_SYMBOL_GPL(dm_table_add_target_callbacks);
+
 int dm_table_any_congested(struct dm_table *t, int bdi_bits)
 {
 	struct dm_dev_internal *dd;
 	struct list_head *devices = dm_table_get_devices(t);
+	struct dm_target_callbacks *cb;
 	int r = 0;
 
 	list_for_each_entry(dd, devices, list) {
@@ -1241,6 +1254,10 @@ int dm_table_any_congested(struct dm_tab
 				     bdevname(dd->dm_dev.bdev, b));
 	}
 
+	list_for_each_entry(cb, &t->target_callbacks, list)
+		if (cb->congested_fn)
+			r |= cb->congested_fn(cb, bdi_bits);
+
 	return r;
 }
 
@@ -1262,6 +1279,7 @@ void dm_table_unplug_all(struct dm_table
 {
 	struct dm_dev_internal *dd;
 	struct list_head *devices = dm_table_get_devices(t);
+	struct dm_target_callbacks *cb;
 
 	list_for_each_entry(dd, devices, list) {
 		struct request_queue *q = bdev_get_queue(dd->dm_dev.bdev);
@@ -1274,6 +1292,10 @@ void dm_table_unplug_all(struct dm_table
 				     dm_device_name(t->md),
 				     bdevname(dd->dm_dev.bdev, b));
 	}
+
+	list_for_each_entry(cb, &t->target_callbacks, list)
+		if (cb->unplug_fn)
+			cb->unplug_fn(cb);
 }
 
 struct mapped_device *dm_table_get_md(struct dm_table *t)
diff -druNp linux-libre-2.6.37-gnu1/drivers/md/Kconfig linux-libre-2.6.38-gnu1/drivers/md/Kconfig
--- linux-libre-2.6.37-gnu1/drivers/md/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/md/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -240,6 +240,30 @@ config DM_MIRROR
          Allow volume managers to mirror logical volumes, also
          needed for live data migration tools such as 'pvmove'.
 
+config DM_RAID
+       tristate "RAID 4/5/6 target (EXPERIMENTAL)"
+       depends on BLK_DEV_DM && EXPERIMENTAL
+       select MD_RAID456
+       select BLK_DEV_MD
+       ---help---
+	 A dm target that supports RAID4, RAID5 and RAID6 mappings
+
+	 A RAID-5 set of N drives with a capacity of C MB per drive provides
+	 the capacity of C * (N - 1) MB, and protects against a failure
+	 of a single drive. For a given sector (row) number, (N - 1) drives
+	 contain data sectors, and one drive contains the parity protection.
+	 For a RAID-4 set, the parity blocks are present on a single drive,
+	 while a RAID-5 set distributes the parity across the drives in one
+	 of the available parity distribution methods.
+
+	 A RAID-6 set of N drives with a capacity of C MB per drive
+	 provides the capacity of C * (N - 2) MB, and protects
+	 against a failure of any two drives. For a given sector
+	 (row) number, (N - 2) drives contain data sectors, and two
+	 drives contains two independent redundancy syndromes.  Like
+	 RAID-5, RAID-6 distributes the syndromes across the drives
+	 in one of the available parity distribution methods.
+
 config DM_LOG_USERSPACE
 	tristate "Mirror userspace logging (EXPERIMENTAL)"
 	depends on DM_MIRROR && EXPERIMENTAL && NET
diff -druNp linux-libre-2.6.37-gnu1/drivers/md/linear.c linux-libre-2.6.38-gnu1/drivers/md/linear.c
--- linux-libre-2.6.37-gnu1/drivers/md/linear.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/md/linear.c	2011-03-14 21:20:32.000000000 -0400
@@ -216,7 +216,6 @@ static int linear_run (mddev_t *mddev)
 
 	if (md_check_no_bitmap(mddev))
 		return -EINVAL;
-	mddev->queue->queue_lock = &mddev->queue->__queue_lock;
 	conf = linear_conf(mddev, mddev->raid_disks);
 
 	if (!conf)
diff -druNp linux-libre-2.6.37-gnu1/drivers/md/Makefile linux-libre-2.6.38-gnu1/drivers/md/Makefile
--- linux-libre-2.6.37-gnu1/drivers/md/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/md/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -36,6 +36,7 @@ obj-$(CONFIG_DM_SNAPSHOT)	+= dm-snapshot
 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
 
 ifeq ($(CONFIG_DM_UEVENT),y)
 dm-mod-objs			+= dm-uevent.o
diff -druNp linux-libre-2.6.37-gnu1/drivers/md/md.c linux-libre-2.6.38-gnu1/drivers/md/md.c
--- linux-libre-2.6.37-gnu1/drivers/md/md.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/md/md.c	2011-03-14 21:20:32.000000000 -0400
@@ -287,11 +287,14 @@ static int md_make_request(struct reques
 	mddev_t *mddev = q->queuedata;
 	int rv;
 	int cpu;
+	unsigned int sectors;
 
-	if (mddev == NULL || mddev->pers == NULL) {
+	if (mddev == NULL || mddev->pers == NULL
+	    || !mddev->ready) {
 		bio_io_error(bio);
 		return 0;
 	}
+	smp_rmb(); /* Ensure implications of  'active' are visible */
 	rcu_read_lock();
 	if (mddev->suspended) {
 		DEFINE_WAIT(__wait);
@@ -309,12 +312,16 @@ static int md_make_request(struct reques
 	atomic_inc(&mddev->active_io);
 	rcu_read_unlock();
 
+	/*
+	 * save the sectors now since our bio can
+	 * go away inside make_request
+	 */
+	sectors = bio_sectors(bio);
 	rv = mddev->pers->make_request(mddev, bio);
 
 	cpu = part_stat_lock();
 	part_stat_inc(cpu, &mddev->gendisk->part0, ios[rw]);
-	part_stat_add(cpu, &mddev->gendisk->part0, sectors[rw],
-		      bio_sectors(bio));
+	part_stat_add(cpu, &mddev->gendisk->part0, sectors[rw], sectors);
 	part_stat_unlock();
 
 	if (atomic_dec_and_test(&mddev->active_io) && mddev->suspended)
@@ -546,6 +553,9 @@ static mddev_t * mddev_find(dev_t unit)
 {
 	mddev_t *mddev, *new = NULL;
 
+	if (unit && MAJOR(unit) != MD_MAJOR)
+		unit &= ~((1<<MdpMinorShift)-1);
+
  retry:
 	spin_lock(&all_mddevs_lock);
 
@@ -703,9 +713,9 @@ static struct mdk_personality *find_pers
 }
 
 /* return the offset of the super block in 512byte sectors */
-static inline sector_t calc_dev_sboffset(struct block_device *bdev)
+static inline sector_t calc_dev_sboffset(mdk_rdev_t *rdev)
 {
-	sector_t num_sectors = i_size_read(bdev->bd_inode) / 512;
+	sector_t num_sectors = i_size_read(rdev->bdev->bd_inode) / 512;
 	return MD_NEW_SIZE_SECTORS(num_sectors);
 }
 
@@ -763,7 +773,7 @@ void md_super_write(mddev_t *mddev, mdk_
 	 */
 	struct bio *bio = bio_alloc_mddev(GFP_NOIO, 1, mddev);
 
-	bio->bi_bdev = rdev->bdev;
+	bio->bi_bdev = rdev->meta_bdev ? rdev->meta_bdev : rdev->bdev;
 	bio->bi_sector = sector;
 	bio_add_page(bio, page, size, 0);
 	bio->bi_private = rdev;
@@ -793,7 +803,7 @@ static void bi_complete(struct bio *bio,
 }
 
 int sync_page_io(mdk_rdev_t *rdev, sector_t sector, int size,
-		 struct page *page, int rw)
+		 struct page *page, int rw, bool metadata_op)
 {
 	struct bio *bio = bio_alloc_mddev(GFP_NOIO, 1, rdev->mddev);
 	struct completion event;
@@ -801,8 +811,12 @@ int sync_page_io(mdk_rdev_t *rdev, secto
 
 	rw |= REQ_SYNC | REQ_UNPLUG;
 
-	bio->bi_bdev = rdev->bdev;
-	bio->bi_sector = sector;
+	bio->bi_bdev = (metadata_op && rdev->meta_bdev) ?
+		rdev->meta_bdev : rdev->bdev;
+	if (metadata_op)
+		bio->bi_sector = sector + rdev->sb_start;
+	else
+		bio->bi_sector = sector + rdev->data_offset;
 	bio_add_page(bio, page, size, 0);
 	init_completion(&event);
 	bio->bi_private = &event;
@@ -827,7 +841,7 @@ static int read_disk_sb(mdk_rdev_t * rde
 		return 0;
 
 
-	if (!sync_page_io(rdev, rdev->sb_start, size, rdev->sb_page, READ))
+	if (!sync_page_io(rdev, 0, size, rdev->sb_page, READ, true))
 		goto fail;
 	rdev->sb_loaded = 1;
 	return 0;
@@ -989,7 +1003,7 @@ static int super_90_load(mdk_rdev_t *rde
 	 *
 	 * It also happens to be a multiple of 4Kb.
 	 */
-	rdev->sb_start = calc_dev_sboffset(rdev->bdev);
+	rdev->sb_start = calc_dev_sboffset(rdev);
 
 	ret = read_disk_sb(rdev, MD_SB_BYTES);
 	if (ret) return ret;
@@ -1330,7 +1344,7 @@ super_90_rdev_size_change(mdk_rdev_t *rd
 		return 0; /* component must fit device */
 	if (rdev->mddev->bitmap_info.offset)
 		return 0; /* can't move bitmap */
-	rdev->sb_start = calc_dev_sboffset(rdev->bdev);
+	rdev->sb_start = calc_dev_sboffset(rdev);
 	if (!num_sectors || num_sectors > rdev->sb_start)
 		num_sectors = rdev->sb_start;
 	md_super_write(rdev->mddev, rdev, rdev->sb_start, rdev->sb_size,
@@ -1879,7 +1893,7 @@ static int bind_rdev_to_array(mdk_rdev_t
 	rdev->sysfs_state = sysfs_get_dirent_safe(rdev->kobj.sd, "state");
 
 	list_add_rcu(&rdev->same_set, &mddev->disks);
-	bd_claim_by_disk(rdev->bdev, rdev->bdev->bd_holder, mddev->gendisk);
+	bd_link_disk_holder(rdev->bdev, mddev->gendisk);
 
 	/* May as well allow recovery to be retried once */
 	mddev->recovery_disabled = 0;
@@ -1906,7 +1920,7 @@ static void unbind_rdev_from_array(mdk_r
 		MD_BUG();
 		return;
 	}
-	bd_release_from_disk(rdev->bdev, rdev->mddev->gendisk);
+	bd_unlink_disk_holder(rdev->bdev, rdev->mddev->gendisk);
 	list_del_rcu(&rdev->same_set);
 	printk(KERN_INFO "md: unbind<%s>\n", bdevname(rdev->bdev,b));
 	rdev->mddev = NULL;
@@ -1934,21 +1948,13 @@ static int lock_rdev(mdk_rdev_t *rdev, d
 	struct block_device *bdev;
 	char b[BDEVNAME_SIZE];
 
-	bdev = open_by_devnum(dev, FMODE_READ|FMODE_WRITE);
+	bdev = blkdev_get_by_dev(dev, FMODE_READ|FMODE_WRITE|FMODE_EXCL,
+				 shared ? (mdk_rdev_t *)lock_rdev : rdev);
 	if (IS_ERR(bdev)) {
 		printk(KERN_ERR "md: could not open %s.\n",
 			__bdevname(dev, b));
 		return PTR_ERR(bdev);
 	}
-	err = bd_claim(bdev, shared ? (mdk_rdev_t *)lock_rdev : rdev);
-	if (err) {
-		printk(KERN_ERR "md: could not bd_claim %s.\n",
-			bdevname(bdev, b));
-		blkdev_put(bdev, FMODE_READ|FMODE_WRITE);
-		return err;
-	}
-	if (!shared)
-		set_bit(AllReserved, &rdev->flags);
 	rdev->bdev = bdev;
 	return err;
 }
@@ -1959,8 +1965,7 @@ static void unlock_rdev(mdk_rdev_t *rdev
 	rdev->bdev = NULL;
 	if (!bdev)
 		MD_BUG();
-	bd_release(bdev);
-	blkdev_put(bdev, FMODE_READ|FMODE_WRITE);
+	blkdev_put(bdev, FMODE_READ|FMODE_WRITE|FMODE_EXCL);
 }
 
 void md_autodetect_dev(dev_t dev);
@@ -2466,6 +2471,9 @@ slot_store(mdk_rdev_t *rdev, const char
 		if (rdev->raid_disk != -1)
 			return -EBUSY;
 
+		if (test_bit(MD_RECOVERY_RUNNING, &rdev->mddev->recovery))
+			return -EBUSY;
+
 		if (rdev->mddev->pers->hot_add_disk == NULL)
 			return -EINVAL;
 
@@ -2473,6 +2481,10 @@ slot_store(mdk_rdev_t *rdev, const char
 			if (rdev2->raid_disk == slot)
 				return -EEXIST;
 
+		if (slot >= rdev->mddev->raid_disks &&
+		    slot >= rdev->mddev->raid_disks + rdev->mddev->delta_disks)
+			return -ENOSPC;
+
 		rdev->raid_disk = slot;
 		if (test_bit(In_sync, &rdev->flags))
 			rdev->saved_raid_disk = slot;
@@ -2490,7 +2502,8 @@ slot_store(mdk_rdev_t *rdev, const char
 			/* failure here is OK */;
 		/* don't wakeup anyone, leave that to userspace. */
 	} else {
-		if (slot >= rdev->mddev->raid_disks)
+		if (slot >= rdev->mddev->raid_disks &&
+		    slot >= rdev->mddev->raid_disks + rdev->mddev->delta_disks)
 			return -ENOSPC;
 		rdev->raid_disk = slot;
 		/* assume it is working */
@@ -2606,12 +2619,11 @@ rdev_size_store(mdk_rdev_t *rdev, const
 
 			mddev_lock(mddev);
 			list_for_each_entry(rdev2, &mddev->disks, same_set)
-				if (test_bit(AllReserved, &rdev2->flags) ||
-				    (rdev->bdev == rdev2->bdev &&
-				     rdev != rdev2 &&
-				     overlaps(rdev->data_offset, rdev->sectors,
-					      rdev2->data_offset,
-					      rdev2->sectors))) {
+				if (rdev->bdev == rdev2->bdev &&
+				    rdev != rdev2 &&
+				    overlaps(rdev->data_offset, rdev->sectors,
+					     rdev2->data_offset,
+					     rdev2->sectors)) {
 					overlap = 1;
 					break;
 				}
@@ -3115,7 +3127,7 @@ level_store(mddev_t *mddev, const char *
 		char nm[20];
 		if (rdev->raid_disk < 0)
 			continue;
-		if (rdev->new_raid_disk > mddev->raid_disks)
+		if (rdev->new_raid_disk >= mddev->raid_disks)
 			rdev->new_raid_disk = -1;
 		if (rdev->new_raid_disk == rdev->raid_disk)
 			continue;
@@ -3744,6 +3756,8 @@ action_show(mddev_t *mddev, char *page)
 	return sprintf(page, "%s\n", type);
 }
 
+static void reap_sync_thread(mddev_t *mddev);
+
 static ssize_t
 action_store(mddev_t *mddev, const char *page, size_t len)
 {
@@ -3758,9 +3772,7 @@ action_store(mddev_t *mddev, const char
 	if (cmd_match(page, "idle") || cmd_match(page, "frozen")) {
 		if (mddev->sync_thread) {
 			set_bit(MD_RECOVERY_INTR, &mddev->recovery);
-			md_unregister_thread(mddev->sync_thread);
-			mddev->sync_thread = NULL;
-			mddev->recovery = 0;
+			reap_sync_thread(mddev);
 		}
 	} else if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery) ||
 		   test_bit(MD_RECOVERY_NEEDED, &mddev->recovery))
@@ -3912,7 +3924,7 @@ static struct md_sysfs_entry md_sync_spe
 static ssize_t
 sync_completed_show(mddev_t *mddev, char *page)
 {
-	unsigned long max_sectors, resync;
+	unsigned long long max_sectors, resync;
 
 	if (!test_bit(MD_RECOVERY_RUNNING, &mddev->recovery))
 		return sprintf(page, "none\n");
@@ -3923,7 +3935,7 @@ sync_completed_show(mddev_t *mddev, char
 		max_sectors = mddev->dev_sectors;
 
 	resync = mddev->curr_resync_completed;
-	return sprintf(page, "%lu / %lu\n", resync, max_sectors);
+	return sprintf(page, "%llu / %llu\n", resync, max_sectors);
 }
 
 static struct md_sysfs_entry md_sync_completed = __ATTR_RO(sync_completed);
@@ -4010,19 +4022,24 @@ suspend_lo_store(mddev_t *mddev, const c
 {
 	char *e;
 	unsigned long long new = simple_strtoull(buf, &e, 10);
+	unsigned long long old = mddev->suspend_lo;
 
 	if (mddev->pers == NULL || 
 	    mddev->pers->quiesce == NULL)
 		return -EINVAL;
 	if (buf == e || (*e && *e != '\n'))
 		return -EINVAL;
-	if (new >= mddev->suspend_hi ||
-	    (new > mddev->suspend_lo && new < mddev->suspend_hi)) {
-		mddev->suspend_lo = new;
+
+	mddev->suspend_lo = new;
+	if (new >= old)
+		/* Shrinking suspended region */
 		mddev->pers->quiesce(mddev, 2);
-		return len;
-	} else
-		return -EINVAL;
+	else {
+		/* Expanding suspended region - need to wait */
+		mddev->pers->quiesce(mddev, 1);
+		mddev->pers->quiesce(mddev, 0);
+	}
+	return len;
 }
 static struct md_sysfs_entry md_suspend_lo =
 __ATTR(suspend_lo, S_IRUGO|S_IWUSR, suspend_lo_show, suspend_lo_store);
@@ -4039,20 +4056,24 @@ suspend_hi_store(mddev_t *mddev, const c
 {
 	char *e;
 	unsigned long long new = simple_strtoull(buf, &e, 10);
+	unsigned long long old = mddev->suspend_hi;
 
 	if (mddev->pers == NULL ||
 	    mddev->pers->quiesce == NULL)
 		return -EINVAL;
 	if (buf == e || (*e && *e != '\n'))
 		return -EINVAL;
-	if ((new <= mddev->suspend_lo && mddev->suspend_lo >= mddev->suspend_hi) ||
-	    (new > mddev->suspend_lo && new > mddev->suspend_hi)) {
-		mddev->suspend_hi = new;
+
+	mddev->suspend_hi = new;
+	if (new <= old)
+		/* Shrinking suspended region */
+		mddev->pers->quiesce(mddev, 2);
+	else {
+		/* Expanding suspended region - need to wait */
 		mddev->pers->quiesce(mddev, 1);
 		mddev->pers->quiesce(mddev, 0);
-		return len;
-	} else
-		return -EINVAL;
+	}
+	return len;
 }
 static struct md_sysfs_entry md_suspend_hi =
 __ATTR(suspend_hi, S_IRUGO|S_IWUSR, suspend_hi_show, suspend_hi_store);
@@ -4120,10 +4141,10 @@ array_size_store(mddev_t *mddev, const c
 	}
 
 	mddev->array_sectors = sectors;
-	set_capacity(mddev->gendisk, mddev->array_sectors);
-	if (mddev->pers)
+	if (mddev->pers) {
+		set_capacity(mddev->gendisk, mddev->array_sectors);
 		revalidate_disk(mddev->gendisk);
-
+	}
 	return len;
 }
 
@@ -4430,7 +4451,9 @@ int md_run(mddev_t *mddev)
 		 * We don't want the data to overlap the metadata,
 		 * Internal Bitmap issues have been handled elsewhere.
 		 */
-		if (rdev->data_offset < rdev->sb_start) {
+		if (rdev->meta_bdev) {
+			/* Nothing to check */;
+		} else if (rdev->data_offset < rdev->sb_start) {
 			if (mddev->dev_sectors &&
 			    rdev->data_offset + mddev->dev_sectors
 			    > rdev->sb_start) {
@@ -4564,7 +4587,8 @@ int md_run(mddev_t *mddev)
 	mddev->safemode_timer.data = (unsigned long) mddev;
 	mddev->safemode_delay = (200 * HZ)/1000 +1; /* 200 msec delay */
 	mddev->in_sync = 1;
-
+	smp_wmb();
+	mddev->ready = 1;
 	list_for_each_entry(rdev, &mddev->disks, same_set)
 		if (rdev->raid_disk >= 0) {
 			char nm[20];
@@ -4603,6 +4627,7 @@ static int do_md_run(mddev_t *mddev)
 	}
 	set_capacity(mddev->gendisk, mddev->array_sectors);
 	revalidate_disk(mddev->gendisk);
+	mddev->changed = 1;
 	kobject_uevent(&disk_to_dev(mddev->gendisk)->kobj, KOBJ_CHANGE);
 out:
 	return err;
@@ -4691,6 +4716,7 @@ static void md_clean(mddev_t *mddev)
 	mddev->sync_speed_min = mddev->sync_speed_max = 0;
 	mddev->recovery = 0;
 	mddev->in_sync = 0;
+	mddev->changed = 0;
 	mddev->degraded = 0;
 	mddev->safemode = 0;
 	mddev->bitmap_info.offset = 0;
@@ -4701,13 +4727,12 @@ static void md_clean(mddev_t *mddev)
 	mddev->plug = NULL;
 }
 
-void md_stop_writes(mddev_t *mddev)
+static void __md_stop_writes(mddev_t *mddev)
 {
 	if (mddev->sync_thread) {
 		set_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
 		set_bit(MD_RECOVERY_INTR, &mddev->recovery);
-		md_unregister_thread(mddev->sync_thread);
-		mddev->sync_thread = NULL;
+		reap_sync_thread(mddev);
 	}
 
 	del_timer_sync(&mddev->safemode_timer);
@@ -4721,10 +4746,18 @@ void md_stop_writes(mddev_t *mddev)
 		md_update_sb(mddev, 1);
 	}
 }
+
+void md_stop_writes(mddev_t *mddev)
+{
+	mddev_lock(mddev);
+	__md_stop_writes(mddev);
+	mddev_unlock(mddev);
+}
 EXPORT_SYMBOL_GPL(md_stop_writes);
 
 void md_stop(mddev_t *mddev)
 {
+	mddev->ready = 0;
 	mddev->pers->stop(mddev);
 	if (mddev->pers->sync_request && mddev->to_remove == NULL)
 		mddev->to_remove = &md_redundancy_group;
@@ -4744,7 +4777,7 @@ static int md_set_readonly(mddev_t *mdde
 		goto out;
 	}
 	if (mddev->pers) {
-		md_stop_writes(mddev);
+		__md_stop_writes(mddev);
 
 		err  = -ENXIO;
 		if (mddev->ro==1)
@@ -4781,7 +4814,7 @@ static int do_md_stop(mddev_t * mddev, i
 		if (mddev->ro)
 			set_disk_ro(disk, 0);
 
-		md_stop_writes(mddev);
+		__md_stop_writes(mddev);
 		md_stop(mddev);
 		mddev->queue->merge_bvec_fn = NULL;
 		mddev->queue->unplug_fn = NULL;
@@ -4799,6 +4832,7 @@ static int do_md_stop(mddev_t * mddev, i
 
 		set_capacity(disk, 0);
 		mutex_unlock(&mddev->open_mutex);
+		mddev->changed = 1;
 		revalidate_disk(disk);
 
 		if (mddev->ro)
@@ -5159,9 +5193,10 @@ static int add_new_disk(mddev_t * mddev,
 		/* set saved_raid_disk if appropriate */
 		if (!mddev->persistent) {
 			if (info->state & (1<<MD_DISK_SYNC)  &&
-			    info->raid_disk < mddev->raid_disks)
+			    info->raid_disk < mddev->raid_disks) {
 				rdev->raid_disk = info->raid_disk;
-			else
+				set_bit(In_sync, &rdev->flags);
+			} else
 				rdev->raid_disk = -1;
 		} else
 			super_types[mddev->major_version].
@@ -5238,7 +5273,7 @@ static int add_new_disk(mddev_t * mddev,
 			printk(KERN_INFO "md: nonpersistent superblock ...\n");
 			rdev->sb_start = i_size_read(rdev->bdev->bd_inode) / 512;
 		} else
-			rdev->sb_start = calc_dev_sboffset(rdev->bdev);
+			rdev->sb_start = calc_dev_sboffset(rdev);
 		rdev->sectors = rdev->sb_start;
 
 		err = bind_rdev_to_array(rdev, mddev);
@@ -5305,7 +5340,7 @@ static int hot_add_disk(mddev_t * mddev,
 	}
 
 	if (mddev->persistent)
-		rdev->sb_start = calc_dev_sboffset(rdev->bdev);
+		rdev->sb_start = calc_dev_sboffset(rdev);
 	else
 		rdev->sb_start = i_size_read(rdev->bdev->bd_inode) / 512;
 
@@ -5518,7 +5553,6 @@ static int update_size(mddev_t *mddev, s
 	 * sb_start or, if that is <data_offset, it must fit before the size
 	 * of each device.  If num_sectors is zero, we find the largest size
 	 * that fits.
-
 	 */
 	if (mddev->sync_thread)
 		return -EBUSY;
@@ -5555,6 +5589,8 @@ static int update_raid_disks(mddev_t *md
 	mddev->delta_disks = raid_disks - mddev->raid_disks;
 
 	rv = mddev->pers->check_reshape(mddev);
+	if (rv < 0)
+		mddev->delta_disks = 0;
 	return rv;
 }
 
@@ -5981,7 +6017,7 @@ static int md_open(struct block_device *
 	atomic_inc(&mddev->openers);
 	mutex_unlock(&mddev->open_mutex);
 
-	check_disk_size_change(mddev->gendisk, bdev);
+	check_disk_change(bdev);
  out:
 	return err;
 }
@@ -5996,6 +6032,21 @@ static int md_release(struct gendisk *di
 
 	return 0;
 }
+
+static int md_media_changed(struct gendisk *disk)
+{
+	mddev_t *mddev = disk->private_data;
+
+	return mddev->changed;
+}
+
+static int md_revalidate(struct gendisk *disk)
+{
+	mddev_t *mddev = disk->private_data;
+
+	mddev->changed = 0;
+	return 0;
+}
 static const struct block_device_operations md_fops =
 {
 	.owner		= THIS_MODULE,
@@ -6006,6 +6057,8 @@ static const struct block_device_operati
 	.compat_ioctl	= md_compat_ioctl,
 #endif
 	.getgeo		= md_getgeo,
+	.media_changed  = md_media_changed,
+	.revalidate_disk= md_revalidate,
 };
 
 static int md_thread(void * arg)
@@ -6041,7 +6094,8 @@ static int md_thread(void * arg)
 			 || kthread_should_stop(),
 			 thread->timeout);
 
-		if (test_and_clear_bit(THREAD_WAKEUP, &thread->flags))
+		clear_bit(THREAD_WAKEUP, &thread->flags);
+		if (!kthread_should_stop())
 			thread->run(thread->mddev);
 	}
 
@@ -6807,7 +6861,7 @@ void md_do_sync(mddev_t *mddev)
 		       desc, mdname(mddev));
 		mddev->curr_resync = j;
 	}
-	mddev->curr_resync_completed = mddev->curr_resync;
+	mddev->curr_resync_completed = j;
 
 	while (j < max_sectors) {
 		sector_t sectors;
@@ -6825,8 +6879,7 @@ void md_do_sync(mddev_t *mddev)
 			md_unplug(mddev);
 			wait_event(mddev->recovery_wait,
 				   atomic_read(&mddev->recovery_active) == 0);
-			mddev->curr_resync_completed =
-				mddev->curr_resync;
+			mddev->curr_resync_completed = j;
 			set_bit(MD_CHANGE_CLEAN, &mddev->flags);
 			sysfs_notify(&mddev->kobj, NULL, "sync_completed");
 		}
@@ -6962,9 +7015,6 @@ void md_do_sync(mddev_t *mddev)
 	} else if (test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery))
 		mddev->resync_min = mddev->curr_resync_completed;
 	mddev->curr_resync = 0;
-	if (!test_bit(MD_RECOVERY_INTR, &mddev->recovery))
-		mddev->curr_resync_completed = 0;
-	sysfs_notify(&mddev->kobj, NULL, "sync_completed");
 	wake_up(&resync_wait);
 	set_bit(MD_RECOVERY_DONE, &mddev->recovery);
 	md_wakeup_thread(mddev->thread);
@@ -7005,7 +7055,7 @@ static int remove_and_add_spares(mddev_t
 			}
 		}
 
-	if (mddev->degraded && ! mddev->ro && !mddev->recovery_disabled) {
+	if (mddev->degraded && !mddev->recovery_disabled) {
 		list_for_each_entry(rdev, &mddev->disks, same_set) {
 			if (rdev->raid_disk >= 0 &&
 			    !test_bit(In_sync, &rdev->flags) &&
@@ -7031,6 +7081,45 @@ static int remove_and_add_spares(mddev_t
 	}
 	return spares;
 }
+
+static void reap_sync_thread(mddev_t *mddev)
+{
+	mdk_rdev_t *rdev;
+
+	/* resync has finished, collect result */
+	md_unregister_thread(mddev->sync_thread);
+	mddev->sync_thread = NULL;
+	if (!test_bit(MD_RECOVERY_INTR, &mddev->recovery) &&
+	    !test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery)) {
+		/* success...*/
+		/* activate any spares */
+		if (mddev->pers->spare_active(mddev))
+			sysfs_notify(&mddev->kobj, NULL,
+				     "degraded");
+	}
+	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 (!mddev->degraded)
+		list_for_each_entry(rdev, &mddev->disks, same_set)
+			rdev->saved_raid_disk = -1;
+
+	clear_bit(MD_RECOVERY_RUNNING, &mddev->recovery);
+	clear_bit(MD_RECOVERY_SYNC, &mddev->recovery);
+	clear_bit(MD_RECOVERY_RESHAPE, &mddev->recovery);
+	clear_bit(MD_RECOVERY_REQUESTED, &mddev->recovery);
+	clear_bit(MD_RECOVERY_CHECK, &mddev->recovery);
+	/* flag recovery needed just to double check */
+	set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
+	sysfs_notify_dirent_safe(mddev->sysfs_action);
+	md_new_event(mddev);
+}
+
 /*
  * This routine is regularly called by all per-raid-array threads to
  * deal with generic issues like resync and super-block update.
@@ -7055,9 +7144,6 @@ static int remove_and_add_spares(mddev_t
  */
 void md_check_recovery(mddev_t *mddev)
 {
-	mdk_rdev_t *rdev;
-
-
 	if (mddev->bitmap)
 		bitmap_daemon_work(mddev);
 
@@ -7092,7 +7178,20 @@ void md_check_recovery(mddev_t *mddev)
 			/* Only thing we do on a ro array is remove
 			 * failed devices.
 			 */
-			remove_and_add_spares(mddev);
+			mdk_rdev_t *rdev;
+			list_for_each_entry(rdev, &mddev->disks, same_set)
+				if (rdev->raid_disk >= 0 &&
+				    !test_bit(Blocked, &rdev->flags) &&
+				    test_bit(Faulty, &rdev->flags) &&
+				    atomic_read(&rdev->nr_pending)==0) {
+					if (mddev->pers->hot_remove_disk(
+						    mddev, rdev->raid_disk)==0) {
+						char nm[20];
+						sprintf(nm,"rd%d", rdev->raid_disk);
+						sysfs_remove_link(&mddev->kobj, nm);
+						rdev->raid_disk = -1;
+					}
+				}
 			clear_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
 			goto unlock;
 		}
@@ -7125,34 +7224,7 @@ void md_check_recovery(mddev_t *mddev)
 			goto unlock;
 		}
 		if (mddev->sync_thread) {
-			/* resync has finished, collect result */
-			md_unregister_thread(mddev->sync_thread);
-			mddev->sync_thread = NULL;
-			if (!test_bit(MD_RECOVERY_INTR, &mddev->recovery) &&
-			    !test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery)) {
-				/* success...*/
-				/* activate any spares */
-				if (mddev->pers->spare_active(mddev))
-					sysfs_notify(&mddev->kobj, NULL,
-						     "degraded");
-			}
-			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 (!mddev->degraded)
-				list_for_each_entry(rdev, &mddev->disks, same_set)
-					rdev->saved_raid_disk = -1;
-
-			mddev->recovery = 0;
-			/* flag recovery needed just to double check */
-			set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
-			sysfs_notify_dirent_safe(mddev->sysfs_action);
-			md_new_event(mddev);
+			reap_sync_thread(mddev);
 			goto unlock;
 		}
 		/* Set RUNNING before clearing NEEDED to avoid
@@ -7210,7 +7282,11 @@ void md_check_recovery(mddev_t *mddev)
 					" thread...\n", 
 					mdname(mddev));
 				/* leave the spares where they are, it shouldn't hurt */
-				mddev->recovery = 0;
+				clear_bit(MD_RECOVERY_RUNNING, &mddev->recovery);
+				clear_bit(MD_RECOVERY_SYNC, &mddev->recovery);
+				clear_bit(MD_RECOVERY_RESHAPE, &mddev->recovery);
+				clear_bit(MD_RECOVERY_REQUESTED, &mddev->recovery);
+				clear_bit(MD_RECOVERY_CHECK, &mddev->recovery);
 			} else
 				md_wakeup_thread(mddev->sync_thread);
 			sysfs_notify_dirent_safe(mddev->sysfs_action);
diff -druNp linux-libre-2.6.37-gnu1/drivers/md/md.h linux-libre-2.6.38-gnu1/drivers/md/md.h
--- linux-libre-2.6.37-gnu1/drivers/md/md.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/md/md.h	2011-03-14 21:20:32.000000000 -0400
@@ -60,6 +60,12 @@ struct mdk_rdev_s
 	mddev_t *mddev;			/* RAID array if running */
 	int last_events;		/* IO event timestamp */
 
+	/*
+	 * If meta_bdev is non-NULL, it means that a separate device is
+	 * being used to store the metadata (superblock/bitmap) which
+	 * would otherwise be contained on the same device as the data (bdev).
+	 */
+	struct block_device *meta_bdev;
 	struct block_device *bdev;	/* block device handle */
 
 	struct page	*sb_page;
@@ -87,8 +93,6 @@ struct mdk_rdev_s
 #define	Faulty		1		/* device is known to have a fault */
 #define	In_sync		2		/* device is in_sync with rest of array */
 #define	WriteMostly	4		/* Avoid reading if at all possible */
-#define	AllReserved	6		/* If whole device is reserved for
-					 * one array */
 #define	AutoDetected	7		/* added by auto-detect */
 #define Blocked		8		/* An error occured on an externally
 					 * managed array, don't allow writes
@@ -148,7 +152,8 @@ struct mddev_s
 						       * are happening, so run/
 						       * takeover/stop are not safe
 						       */
-
+	int				ready; /* See when safe to pass 
+						* IO requests down */
 	struct gendisk			*gendisk;
 
 	struct kobject			kobj;
@@ -269,6 +274,8 @@ struct mddev_s
 	atomic_t			active;		/* general refcount */
 	atomic_t			openers;	/* number of active opens */
 
+	int				changed;	/* True if we might need to
+							 * reread partition info */
 	int				degraded;	/* whether md should consider
 							 * adding a spare
 							 */
@@ -497,8 +504,8 @@ extern void md_flush_request(mddev_t *md
 extern void md_super_write(mddev_t *mddev, mdk_rdev_t *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,
-			struct page *page, int rw);
+extern int sync_page_io(mdk_rdev_t *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);
diff -druNp linux-libre-2.6.37-gnu1/drivers/md/multipath.c linux-libre-2.6.38-gnu1/drivers/md/multipath.c
--- linux-libre-2.6.37-gnu1/drivers/md/multipath.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/md/multipath.c	2011-03-14 21:20:32.000000000 -0400
@@ -435,7 +435,6 @@ static int multipath_run (mddev_t *mddev
 	 * bookkeeping area. [whatever we allocate in multipath_run(),
 	 * should be freed in multipath_stop()]
 	 */
-	mddev->queue->queue_lock = &mddev->queue->__queue_lock;
 
 	conf = kzalloc(sizeof(multipath_conf_t), GFP_KERNEL);
 	mddev->private = conf;
diff -druNp linux-libre-2.6.37-gnu1/drivers/md/raid0.c linux-libre-2.6.38-gnu1/drivers/md/raid0.c
--- linux-libre-2.6.37-gnu1/drivers/md/raid0.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/md/raid0.c	2011-03-14 21:20:32.000000000 -0400
@@ -179,6 +179,14 @@ static int create_strip_zones(mddev_t *m
 			rdev1->new_raid_disk = j;
 		}
 
+		if (mddev->level == 1) {
+			/* taiking over a raid1 array-
+			 * we have only one active disk
+			 */
+			j = 0;
+			rdev1->new_raid_disk = j;
+		}
+
 		if (j < 0 || j >= mddev->raid_disks) {
 			printk(KERN_ERR "md/raid0:%s: bad disk number %d - "
 			       "aborting!\n", mdname(mddev), j);
@@ -353,7 +361,6 @@ static int raid0_run(mddev_t *mddev)
 	if (md_check_no_bitmap(mddev))
 		return -EINVAL;
 	blk_queue_max_hw_sectors(mddev->queue, mddev->chunk_sectors);
-	mddev->queue->queue_lock = &mddev->queue->__queue_lock;
 
 	/* if private is not null, we are here after takeover */
 	if (mddev->private == NULL) {
@@ -644,12 +651,39 @@ static void *raid0_takeover_raid10(mddev
 	return priv_conf;
 }
 
+static void *raid0_takeover_raid1(mddev_t *mddev)
+{
+	raid0_conf_t *priv_conf;
+
+	/* Check layout:
+	 *  - (N - 1) mirror drives must be already faulty
+	 */
+	if ((mddev->raid_disks - 1) != mddev->degraded) {
+		printk(KERN_ERR "md/raid0:%s: (N - 1) mirrors drives must be already faulty!\n",
+		       mdname(mddev));
+		return ERR_PTR(-EINVAL);
+	}
+
+	/* Set new parameters */
+	mddev->new_level = 0;
+	mddev->new_layout = 0;
+	mddev->new_chunk_sectors = 128; /* by default set chunk size to 64k */
+	mddev->delta_disks = 1 - mddev->raid_disks;
+	mddev->raid_disks = 1;
+	/* make sure it will be not marked as dirty */
+	mddev->recovery_cp = MaxSector;
+
+	create_strip_zones(mddev, &priv_conf);
+	return priv_conf;
+}
+
 static void *raid0_takeover(mddev_t *mddev)
 {
 	/* raid0 can take over:
 	 *  raid4 - if all data disks are active.
 	 *  raid5 - providing it is Raid4 layout and one disk is faulty
 	 *  raid10 - assuming we have all necessary active disks
+	 *  raid1 - with (N -1) mirror drives faulty
 	 */
 	if (mddev->level == 4)
 		return raid0_takeover_raid45(mddev);
@@ -665,6 +699,12 @@ static void *raid0_takeover(mddev_t *mdd
 	if (mddev->level == 10)
 		return raid0_takeover_raid10(mddev);
 
+	if (mddev->level == 1)
+		return raid0_takeover_raid1(mddev);
+
+	printk(KERN_ERR "Takeover from raid%i to raid0 not supported\n",
+		mddev->level);
+
 	return ERR_PTR(-EINVAL);
 }
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/md/raid10.c linux-libre-2.6.38-gnu1/drivers/md/raid10.c
--- linux-libre-2.6.37-gnu1/drivers/md/raid10.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/md/raid10.c	2011-03-14 21:20:32.000000000 -0400
@@ -662,7 +662,10 @@ static int flush_pending_writes(conf_t *
 	if (conf->pending_bio_list.head) {
 		struct bio *bio;
 		bio = bio_list_get(&conf->pending_bio_list);
+		/* Spinlock only taken to quiet a warning */
+		spin_lock(conf->mddev->queue->queue_lock);
 		blk_remove_plug(conf->mddev->queue);
+		spin_unlock(conf->mddev->queue->queue_lock);
 		spin_unlock_irq(&conf->device_lock);
 		/* flush any pending bitmap writes to disk
 		 * before proceeding w/ I/O */
@@ -971,7 +974,7 @@ static int make_request(mddev_t *mddev,
 		atomic_inc(&r10_bio->remaining);
 		spin_lock_irqsave(&conf->device_lock, flags);
 		bio_list_add(&conf->pending_bio_list, mbio);
-		blk_plug_device(mddev->queue);
+		blk_plug_device_unlocked(mddev->queue);
 		spin_unlock_irqrestore(&conf->device_lock, flags);
 	}
 
@@ -1051,8 +1054,9 @@ static void error(mddev_t *mddev, mdk_rd
 	}
 	set_bit(Faulty, &rdev->flags);
 	set_bit(MD_CHANGE_DEVS, &mddev->flags);
-	printk(KERN_ALERT "md/raid10:%s: Disk failure on %s, disabling device.\n"
-	       KERN_ALERT "md/raid10:%s: Operation continuing on %d devices.\n",
+	printk(KERN_ALERT
+	       "md/raid10:%s: Disk failure on %s, disabling device.\n"
+	       "md/raid10:%s: Operation continuing on %d devices.\n",
 	       mdname(mddev), bdevname(rdev->bdev, b),
 	       mdname(mddev), conf->raid_disks - mddev->degraded);
 }
@@ -1559,9 +1563,9 @@ static void fix_read_error(conf_t *conf,
 				rcu_read_unlock();
 				success = sync_page_io(rdev,
 						       r10_bio->devs[sl].addr +
-						       sect + rdev->data_offset,
+						       sect,
 						       s<<9,
-						       conf->tmppage, READ);
+						       conf->tmppage, READ, false);
 				rdev_dec_pending(rdev, mddev);
 				rcu_read_lock();
 				if (success)
@@ -1598,8 +1602,8 @@ static void fix_read_error(conf_t *conf,
 				atomic_add(s, &rdev->corrected_errors);
 				if (sync_page_io(rdev,
 						 r10_bio->devs[sl].addr +
-						 sect + rdev->data_offset,
-						 s<<9, conf->tmppage, WRITE)
+						 sect,
+						 s<<9, conf->tmppage, WRITE, false)
 				    == 0) {
 					/* Well, this device is dead */
 					printk(KERN_NOTICE
@@ -1635,9 +1639,9 @@ static void fix_read_error(conf_t *conf,
 				rcu_read_unlock();
 				if (sync_page_io(rdev,
 						 r10_bio->devs[sl].addr +
-						 sect + rdev->data_offset,
+						 sect,
 						 s<<9, conf->tmppage,
-						 READ) == 0) {
+						 READ, false) == 0) {
 					/* Well, this device is dead */
 					printk(KERN_NOTICE
 					       "md/raid10:%s: unable to read back "
@@ -2303,8 +2307,6 @@ static int run(mddev_t *mddev)
 	if (!conf)
 		goto out;
 
-	mddev->queue->queue_lock = &conf->device_lock;
-
 	mddev->thread = conf->thread;
 	conf->thread = NULL;
 
@@ -2462,11 +2464,13 @@ static void *raid10_takeover_raid0(mddev
 	mddev->recovery_cp = MaxSector;
 
 	conf = setup_conf(mddev);
-	if (!IS_ERR(conf))
+	if (!IS_ERR(conf)) {
 		list_for_each_entry(rdev, &mddev->disks, same_set)
 			if (rdev->raid_disk >= 0)
 				rdev->new_raid_disk = rdev->raid_disk * 2;
-		
+		conf->barrier = 1;
+	}
+
 	return conf;
 }
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/md/raid1.c linux-libre-2.6.38-gnu1/drivers/md/raid1.c
--- linux-libre-2.6.37-gnu1/drivers/md/raid1.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/md/raid1.c	2011-03-14 21:20:32.000000000 -0400
@@ -593,7 +593,10 @@ static int flush_pending_writes(conf_t *
 	if (conf->pending_bio_list.head) {
 		struct bio *bio;
 		bio = bio_list_get(&conf->pending_bio_list);
+		/* Only take the spinlock to quiet a warning */
+		spin_lock(conf->mddev->queue->queue_lock);
 		blk_remove_plug(conf->mddev->queue);
+		spin_unlock(conf->mddev->queue->queue_lock);
 		spin_unlock_irq(&conf->device_lock);
 		/* flush any pending bitmap writes to
 		 * disk before proceeding w/ I/O */
@@ -959,7 +962,7 @@ static int make_request(mddev_t *mddev,
 		atomic_inc(&r1_bio->remaining);
 		spin_lock_irqsave(&conf->device_lock, flags);
 		bio_list_add(&conf->pending_bio_list, mbio);
-		blk_plug_device(mddev->queue);
+		blk_plug_device_unlocked(mddev->queue);
 		spin_unlock_irqrestore(&conf->device_lock, flags);
 	}
 	r1_bio_write_done(r1_bio, bio->bi_vcnt, behind_pages, behind_pages != NULL);
@@ -1027,8 +1030,9 @@ static void error(mddev_t *mddev, mdk_rd
 	} else
 		set_bit(Faulty, &rdev->flags);
 	set_bit(MD_CHANGE_DEVS, &mddev->flags);
-	printk(KERN_ALERT "md/raid1:%s: Disk failure on %s, disabling device.\n"
-	       KERN_ALERT "md/raid1:%s: Operation continuing on %d devices.\n",
+	printk(KERN_ALERT
+	       "md/raid1:%s: Disk failure on %s, disabling device.\n"
+	       "md/raid1:%s: Operation continuing on %d devices.\n",
 	       mdname(mddev), bdevname(rdev->bdev, b),
 	       mdname(mddev), conf->raid_disks - mddev->degraded);
 }
@@ -1364,10 +1368,10 @@ static void sync_request_write(mddev_t *
 					 */
 					rdev = conf->mirrors[d].rdev;
 					if (sync_page_io(rdev,
-							 sect + rdev->data_offset,
+							 sect,
 							 s<<9,
 							 bio->bi_io_vec[idx].bv_page,
-							 READ)) {
+							 READ, false)) {
 						success = 1;
 						break;
 					}
@@ -1390,10 +1394,10 @@ static void sync_request_write(mddev_t *
 					rdev = conf->mirrors[d].rdev;
 					atomic_add(s, &rdev->corrected_errors);
 					if (sync_page_io(rdev,
-							 sect + rdev->data_offset,
+							 sect,
 							 s<<9,
 							 bio->bi_io_vec[idx].bv_page,
-							 WRITE) == 0)
+							 WRITE, false) == 0)
 						md_error(mddev, rdev);
 				}
 				d = start;
@@ -1405,10 +1409,10 @@ static void sync_request_write(mddev_t *
 						continue;
 					rdev = conf->mirrors[d].rdev;
 					if (sync_page_io(rdev,
-							 sect + rdev->data_offset,
+							 sect,
 							 s<<9,
 							 bio->bi_io_vec[idx].bv_page,
-							 READ) == 0)
+							 READ, false) == 0)
 						md_error(mddev, rdev);
 				}
 			} else {
@@ -1488,10 +1492,8 @@ static void fix_read_error(conf_t *conf,
 			rdev = conf->mirrors[d].rdev;
 			if (rdev &&
 			    test_bit(In_sync, &rdev->flags) &&
-			    sync_page_io(rdev,
-					 sect + rdev->data_offset,
-					 s<<9,
-					 conf->tmppage, READ))
+			    sync_page_io(rdev, sect, s<<9,
+					 conf->tmppage, READ, false))
 				success = 1;
 			else {
 				d++;
@@ -1514,9 +1516,8 @@ static void fix_read_error(conf_t *conf,
 			rdev = conf->mirrors[d].rdev;
 			if (rdev &&
 			    test_bit(In_sync, &rdev->flags)) {
-				if (sync_page_io(rdev,
-						 sect + rdev->data_offset,
-						 s<<9, conf->tmppage, WRITE)
+				if (sync_page_io(rdev, sect, s<<9,
+						 conf->tmppage, WRITE, false)
 				    == 0)
 					/* Well, this device is dead */
 					md_error(mddev, rdev);
@@ -1531,9 +1532,8 @@ static void fix_read_error(conf_t *conf,
 			rdev = conf->mirrors[d].rdev;
 			if (rdev &&
 			    test_bit(In_sync, &rdev->flags)) {
-				if (sync_page_io(rdev,
-						 sect + rdev->data_offset,
-						 s<<9, conf->tmppage, READ)
+				if (sync_page_io(rdev, sect, s<<9,
+						 conf->tmppage, READ, false)
 				    == 0)
 					/* Well, this device is dead */
 					md_error(mddev, rdev);
@@ -2024,7 +2024,6 @@ static int run(mddev_t *mddev)
 	if (IS_ERR(conf))
 		return PTR_ERR(conf);
 
-	mddev->queue->queue_lock = &conf->device_lock;
 	list_for_each_entry(rdev, &mddev->disks, same_set) {
 		disk_stack_limits(mddev->gendisk, rdev->bdev,
 				  rdev->data_offset << 9);
diff -druNp linux-libre-2.6.37-gnu1/drivers/md/raid5.c linux-libre-2.6.38-gnu1/drivers/md/raid5.c
--- linux-libre-2.6.37-gnu1/drivers/md/raid5.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/md/raid5.c	2011-03-14 21:20:32.000000000 -0400
@@ -1721,7 +1721,6 @@ static void error(mddev_t *mddev, mdk_rd
 		set_bit(Faulty, &rdev->flags);
 		printk(KERN_ALERT
 		       "md/raid:%s: Disk failure on %s, disabling device.\n"
-		       KERN_ALERT
 		       "md/raid:%s: Operation continuing on %d devices.\n",
 		       mdname(mddev),
 		       bdevname(rdev->bdev, b),
@@ -4237,7 +4236,7 @@ static sector_t reshape_request(mddev_t
 		wait_event(conf->wait_for_overlap,
 			   atomic_read(&conf->reshape_stripes)==0);
 		mddev->reshape_position = conf->reshape_progress;
-		mddev->curr_resync_completed = mddev->curr_resync;
+		mddev->curr_resync_completed = sector_nr;
 		conf->reshape_checkpoint = jiffies;
 		set_bit(MD_CHANGE_DEVS, &mddev->flags);
 		md_wakeup_thread(mddev->thread);
@@ -4338,7 +4337,7 @@ static sector_t reshape_request(mddev_t
 		wait_event(conf->wait_for_overlap,
 			   atomic_read(&conf->reshape_stripes) == 0);
 		mddev->reshape_position = conf->reshape_progress;
-		mddev->curr_resync_completed = mddev->curr_resync + reshape_sectors;
+		mddev->curr_resync_completed = sector_nr;
 		conf->reshape_checkpoint = jiffies;
 		set_bit(MD_CHANGE_DEVS, &mddev->flags);
 		md_wakeup_thread(mddev->thread);
@@ -5205,7 +5204,6 @@ static int run(mddev_t *mddev)
 
 		mddev->queue->backing_dev_info.congested_data = mddev;
 		mddev->queue->backing_dev_info.congested_fn = raid5_congested;
-		mddev->queue->queue_lock = &conf->device_lock;
 		mddev->queue->unplug_fn = raid5_unplug_queue;
 
 		chunk_size = mddev->chunk_sectors << 9;
@@ -5339,7 +5337,7 @@ static int raid5_spare_active(mddev_t *m
 		    && !test_bit(Faulty, &tmp->rdev->flags)
 		    && !test_and_set_bit(In_sync, &tmp->rdev->flags)) {
 			count++;
-			sysfs_notify_dirent(tmp->rdev->sysfs_state);
+			sysfs_notify_dirent_safe(tmp->rdev->sysfs_state);
 		}
 	}
 	spin_lock_irqsave(&conf->device_lock, flags);
@@ -5518,7 +5516,6 @@ static int raid5_start_reshape(mddev_t *
 	raid5_conf_t *conf = mddev->private;
 	mdk_rdev_t *rdev;
 	int spares = 0;
-	int added_devices = 0;
 	unsigned long flags;
 
 	if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery))
@@ -5528,8 +5525,8 @@ static int raid5_start_reshape(mddev_t *
 		return -ENOSPC;
 
 	list_for_each_entry(rdev, &mddev->disks, same_set)
-		if (rdev->raid_disk < 0 &&
-		    !test_bit(Faulty, &rdev->flags))
+		if (!test_bit(In_sync, &rdev->flags)
+		    && !test_bit(Faulty, &rdev->flags))
 			spares++;
 
 	if (spares - mddev->degraded < mddev->delta_disks - conf->max_degraded)
@@ -5572,29 +5569,35 @@ static int raid5_start_reshape(mddev_t *
 	 * to correctly record the "partially reconstructed" state of
 	 * such devices during the reshape and confusion could result.
 	 */
-	if (mddev->delta_disks >= 0)
-	    list_for_each_entry(rdev, &mddev->disks, same_set)
-		if (rdev->raid_disk < 0 &&
-		    !test_bit(Faulty, &rdev->flags)) {
-			if (raid5_add_disk(mddev, rdev) == 0) {
-				char nm[20];
-				if (rdev->raid_disk >= conf->previous_raid_disks) {
-					set_bit(In_sync, &rdev->flags);
-					added_devices++;
-				} else
-					rdev->recovery_offset = 0;
-				sprintf(nm, "rd%d", rdev->raid_disk);
-				if (sysfs_create_link(&mddev->kobj,
-						      &rdev->kobj, nm))
-					/* Failure here is OK */;
-			} else
-				break;
-		}
+	if (mddev->delta_disks >= 0) {
+		int added_devices = 0;
+		list_for_each_entry(rdev, &mddev->disks, same_set)
+			if (rdev->raid_disk < 0 &&
+			    !test_bit(Faulty, &rdev->flags)) {
+				if (raid5_add_disk(mddev, rdev) == 0) {
+					char nm[20];
+					if (rdev->raid_disk
+					    >= conf->previous_raid_disks) {
+						set_bit(In_sync, &rdev->flags);
+						added_devices++;
+					} else
+						rdev->recovery_offset = 0;
+					sprintf(nm, "rd%d", rdev->raid_disk);
+					if (sysfs_create_link(&mddev->kobj,
+							      &rdev->kobj, nm))
+						/* Failure here is OK */;
+				}
+			} else if (rdev->raid_disk >= conf->previous_raid_disks
+				   && !test_bit(Faulty, &rdev->flags)) {
+				/* This is a spare that was manually added */
+				set_bit(In_sync, &rdev->flags);
+				added_devices++;
+			}
 
-	/* When a reshape changes the number of devices, ->degraded
-	 * is measured against the larger of the pre and post number of
-	 * devices.*/
-	if (mddev->delta_disks > 0) {
+		/* When a reshape changes the number of devices,
+		 * ->degraded is measured against the larger of the
+		 * pre and post number of devices.
+		 */
 		spin_lock_irqsave(&conf->device_lock, flags);
 		mddev->degraded += (conf->raid_disks - conf->previous_raid_disks)
 			- added_devices;
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/common/saa7146_core.c linux-libre-2.6.38-gnu1/drivers/media/common/saa7146_core.c
--- linux-libre-2.6.37-gnu1/drivers/media/common/saa7146_core.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/common/saa7146_core.c	2011-03-14 21:20:32.000000000 -0400
@@ -452,7 +452,7 @@ static int saa7146_init_one(struct pci_d
 	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->lock);
+	mutex_init(&dev->v4l2_lock);
 	spin_lock_init(&dev->int_slock);
 	spin_lock_init(&dev->slock);
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/common/saa7146_fops.c linux-libre-2.6.38-gnu1/drivers/media/common/saa7146_fops.c
--- linux-libre-2.6.37-gnu1/drivers/media/common/saa7146_fops.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/common/saa7146_fops.c	2011-03-14 21:20:32.000000000 -0400
@@ -15,18 +15,15 @@ int saa7146_res_get(struct saa7146_fh *f
 	}
 
 	/* is it free? */
-	mutex_lock(&dev->lock);
 	if (vv->resources & bit) {
 		DEB_D(("locked! vv->resources:0x%02x, we want:0x%02x\n",vv->resources,bit));
 		/* no, someone else uses it */
-		mutex_unlock(&dev->lock);
 		return 0;
 	}
 	/* it's free, grab it */
 	fh->resources  |= bit;
 	vv->resources |= bit;
 	DEB_D(("res: get 0x%02x, cur:0x%02x\n",bit,vv->resources));
-	mutex_unlock(&dev->lock);
 	return 1;
 }
 
@@ -37,11 +34,9 @@ void saa7146_res_free(struct saa7146_fh
 
 	BUG_ON((fh->resources & bits) != bits);
 
-	mutex_lock(&dev->lock);
 	fh->resources  &= ~bits;
 	vv->resources &= ~bits;
 	DEB_D(("res: put 0x%02x, cur:0x%02x\n",bits,vv->resources));
-	mutex_unlock(&dev->lock);
 }
 
 
@@ -396,7 +391,7 @@ static const struct v4l2_file_operations
 	.write		= fops_write,
 	.poll		= fops_poll,
 	.mmap		= fops_mmap,
-	.ioctl		= video_ioctl2,
+	.unlocked_ioctl	= video_ioctl2,
 };
 
 static void vv_callback(struct saa7146_dev *dev, unsigned long status)
@@ -505,6 +500,7 @@ int saa7146_register_device(struct video
 	vfd->fops = &video_fops;
 	vfd->ioctl_ops = &dev->ext_vv_data->ops;
 	vfd->release = video_device_release;
+	vfd->lock = &dev->v4l2_lock;
 	vfd->tvnorms = 0;
 	for (i = 0; i < dev->ext_vv_data->num_stds; i++)
 		vfd->tvnorms |= dev->ext_vv_data->stds[i].id;
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/common/saa7146_vbi.c linux-libre-2.6.38-gnu1/drivers/media/common/saa7146_vbi.c
--- linux-libre-2.6.37-gnu1/drivers/media/common/saa7146_vbi.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/common/saa7146_vbi.c	2011-03-14 21:20:32.000000000 -0400
@@ -412,7 +412,7 @@ static int vbi_open(struct saa7146_dev *
 			    V4L2_BUF_TYPE_VBI_CAPTURE,
 			    V4L2_FIELD_SEQ_TB, // FIXME: does this really work?
 			    sizeof(struct saa7146_buf),
-			    file, NULL);
+			    file, &dev->v4l2_lock);
 
 	init_timer(&fh->vbi_read_timeout);
 	fh->vbi_read_timeout.function = vbi_read_timeout;
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/common/saa7146_video.c linux-libre-2.6.38-gnu1/drivers/media/common/saa7146_video.c
--- linux-libre-2.6.37-gnu1/drivers/media/common/saa7146_video.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/common/saa7146_video.c	2011-03-14 21:20:32.000000000 -0400
@@ -553,8 +553,6 @@ static int vidioc_s_fbuf(struct file *fi
 		}
 	}
 
-	mutex_lock(&dev->lock);
-
 	/* ok, accept it */
 	vv->ov_fb = *fb;
 	vv->ov_fmt = fmt;
@@ -563,8 +561,6 @@ static int vidioc_s_fbuf(struct file *fi
 		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));
 	}
-
-	mutex_unlock(&dev->lock);
 	return 0;
 }
 
@@ -649,8 +645,6 @@ static int vidioc_s_ctrl(struct file *fi
 		return -EINVAL;
 	}
 
-	mutex_lock(&dev->lock);
-
 	switch (ctrl->type) {
 	case V4L2_CTRL_TYPE_BOOLEAN:
 	case V4L2_CTRL_TYPE_MENU:
@@ -693,7 +687,6 @@ static int vidioc_s_ctrl(struct file *fi
 		/* fixme: we can support changing VFLIP and HFLIP here... */
 		if (IS_CAPTURE_ACTIVE(fh) != 0) {
 			DEB_D(("V4L2_CID_HFLIP while active capture.\n"));
-			mutex_unlock(&dev->lock);
 			return -EBUSY;
 		}
 		vv->hflip = c->value;
@@ -701,16 +694,13 @@ static int vidioc_s_ctrl(struct file *fi
 	case V4L2_CID_VFLIP:
 		if (IS_CAPTURE_ACTIVE(fh) != 0) {
 			DEB_D(("V4L2_CID_VFLIP while active capture.\n"));
-			mutex_unlock(&dev->lock);
 			return -EBUSY;
 		}
 		vv->vflip = c->value;
 		break;
 	default:
-		mutex_unlock(&dev->lock);
 		return -EINVAL;
 	}
-	mutex_unlock(&dev->lock);
 
 	if (IS_OVERLAY_ACTIVE(fh) != 0) {
 		saa7146_stop_preview(fh);
@@ -902,22 +892,18 @@ static int vidioc_s_fmt_vid_overlay(stru
 	err = vidioc_try_fmt_vid_overlay(file, fh, f);
 	if (0 != err)
 		return err;
-	mutex_lock(&dev->lock);
 	fh->ov.win    = f->fmt.win;
 	fh->ov.nclips = f->fmt.win.clipcount;
 	if (fh->ov.nclips > 16)
 		fh->ov.nclips = 16;
 	if (copy_from_user(fh->ov.clips, f->fmt.win.clips,
 				sizeof(struct v4l2_clip) * fh->ov.nclips)) {
-		mutex_unlock(&dev->lock);
 		return -EFAULT;
 	}
 
 	/* fh->ov.fh is used to indicate that we have valid overlay informations, too */
 	fh->ov.fh = fh;
 
-	mutex_unlock(&dev->lock);
-
 	/* check if our current overlay is active */
 	if (IS_OVERLAY_ACTIVE(fh) != 0) {
 		saa7146_stop_preview(fh);
@@ -976,8 +962,6 @@ static int vidioc_s_std(struct file *fil
 		}
 	}
 
-	mutex_lock(&dev->lock);
-
 	for (i = 0; i < dev->ext_vv_data->num_stds; i++)
 		if (*id & dev->ext_vv_data->stds[i].id)
 			break;
@@ -988,8 +972,6 @@ static int vidioc_s_std(struct file *fil
 		found = 1;
 	}
 
-	mutex_unlock(&dev->lock);
-
 	if (vv->ov_suspend != NULL) {
 		saa7146_start_preview(vv->ov_suspend);
 		vv->ov_suspend = NULL;
@@ -1129,35 +1111,6 @@ static int vidioc_g_chip_ident(struct fi
 			core, g_chip_ident, chip);
 }
 
-#ifdef CONFIG_VIDEO_V4L1_COMPAT
-static int vidiocgmbuf(struct file *file, void *__fh, struct video_mbuf *mbuf)
-{
-	struct saa7146_fh *fh = __fh;
-	struct videobuf_queue *q = &fh->video_q;
-	int err, i;
-
-	/* fixme: number of capture buffers and sizes for v4l apps */
-	int gbuffers = 2;
-	int gbufsize = 768 * 576 * 4;
-
-	DEB_D(("VIDIOCGMBUF \n"));
-
-	q = &fh->video_q;
-	err = videobuf_mmap_setup(q, gbuffers, gbufsize,
-			V4L2_MEMORY_MMAP);
-	if (err < 0)
-		return err;
-
-	gbuffers = err;
-	memset(mbuf, 0, sizeof(*mbuf));
-	mbuf->frames = gbuffers;
-	mbuf->size   = gbuffers * gbufsize;
-	for (i = 0; i < gbuffers; i++)
-		mbuf->offsets[i] = i * gbufsize;
-	return 0;
-}
-#endif
-
 const struct v4l2_ioctl_ops saa7146_video_ioctl_ops = {
 	.vidioc_querycap             = vidioc_querycap,
 	.vidioc_enum_fmt_vid_cap     = vidioc_enum_fmt_vid_cap,
@@ -1186,9 +1139,6 @@ const struct v4l2_ioctl_ops saa7146_vide
 	.vidioc_streamon             = vidioc_streamon,
 	.vidioc_streamoff            = vidioc_streamoff,
 	.vidioc_g_parm 		     = vidioc_g_parm,
-#ifdef CONFIG_VIDEO_V4L1_COMPAT
-	.vidiocgmbuf                 = vidiocgmbuf,
-#endif
 };
 
 /*********************************************************************************/
@@ -1386,7 +1336,7 @@ static int video_open(struct saa7146_dev
 			    V4L2_BUF_TYPE_VIDEO_CAPTURE,
 			    V4L2_FIELD_INTERLACED,
 			    sizeof(struct saa7146_buf),
-			    file, NULL);
+			    file, &dev->v4l2_lock);
 
 	return 0;
 }
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/common/tuners/Kconfig linux-libre-2.6.38-gnu1/drivers/media/common/tuners/Kconfig
--- linux-libre-2.6.37-gnu1/drivers/media/common/tuners/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/common/tuners/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -34,7 +34,7 @@ config MEDIA_TUNER
 config MEDIA_TUNER_CUSTOMISE
 	bool "Customize analog and hybrid tuner modules to build"
 	depends on MEDIA_TUNER
-	default y if EMBEDDED
+	default y if EXPERT
 	help
 	  This allows the user to deselect tuner drivers unnecessary
 	  for their hardware from the build. Use this option with care
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/common/tuners/max2165.c linux-libre-2.6.38-gnu1/drivers/media/common/tuners/max2165.c
--- linux-libre-2.6.37-gnu1/drivers/media/common/tuners/max2165.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/common/tuners/max2165.c	2011-03-14 21:20:32.000000000 -0400
@@ -52,13 +52,12 @@ static int max2165_write_reg(struct max2
 	msg.addr = priv->config->i2c_address;
 
 	if (debug >= 2)
-		printk(KERN_DEBUG "%s: reg=0x%02X, data=0x%02X\n",
-			__func__, reg, data);
+		dprintk("%s: reg=0x%02X, data=0x%02X\n", __func__, reg, data);
 
 	ret = i2c_transfer(priv->i2c, &msg, 1);
 
 	if (ret != 1)
-		dprintk(KERN_DEBUG "%s: error reg=0x%x, data=0x%x, ret=%i\n",
+		dprintk("%s: error reg=0x%x, data=0x%x, ret=%i\n",
 			__func__, reg, data, ret);
 
 	return (ret != 1) ? -EIO : 0;
@@ -78,14 +77,13 @@ static int max2165_read_reg(struct max21
 
 	ret = i2c_transfer(priv->i2c, msg, 2);
 	if (ret != 2) {
-		dprintk(KERN_DEBUG "%s: error reg=0x%x, ret=%i\n",
-			__func__, reg, ret);
+		dprintk("%s: error reg=0x%x, ret=%i\n", __func__, reg, ret);
 		return -EIO;
 	}
 
 	*p_data = b1[0];
 	if (debug >= 2)
-		printk(KERN_DEBUG "%s: reg=0x%02X, data=0x%02X\n",
+		dprintk("%s: reg=0x%02X, data=0x%02X\n",
 			__func__, reg, b1[0]);
 	return 0;
 }
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/common/tuners/tda18218.c linux-libre-2.6.38-gnu1/drivers/media/common/tuners/tda18218.c
--- linux-libre-2.6.37-gnu1/drivers/media/common/tuners/tda18218.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/common/tuners/tda18218.c	2011-03-14 21:20:32.000000000 -0400
@@ -28,7 +28,7 @@ MODULE_PARM_DESC(debug, "Turn on/off deb
 /* write multiple registers */
 static int tda18218_wr_regs(struct tda18218_priv *priv, u8 reg, u8 *val, u8 len)
 {
-	int ret;
+	int ret = 0;
 	u8 buf[1+len], quotient, remainder, i, msg_len, msg_len_max;
 	struct i2c_msg msg[1] = {
 		{
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/common/tuners/tda8290.c linux-libre-2.6.38-gnu1/drivers/media/common/tuners/tda8290.c
--- linux-libre-2.6.37-gnu1/drivers/media/common/tuners/tda8290.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/common/tuners/tda8290.c	2011-03-14 21:20:32.000000000 -0400
@@ -95,8 +95,7 @@ static int tda8295_i2c_bridge(struct dvb
 		msleep(20);
 	} else {
 		msg = disable;
-		tuner_i2c_xfer_send(&priv->i2c_props, msg, 1);
-		tuner_i2c_xfer_recv(&priv->i2c_props, &msg[1], 1);
+		tuner_i2c_xfer_send_recv(&priv->i2c_props, msg, 1, &msg[1], 1);
 
 		buf[2] = msg[1];
 		buf[2] &= ~0x04;
@@ -233,19 +232,22 @@ static void tda8290_set_params(struct dv
 		tuner_i2c_xfer_send(&priv->i2c_props, pll_bw_nom, 2);
 	}
 
+
 	tda8290_i2c_bridge(fe, 1);
 
 	if (fe->ops.tuner_ops.set_analog_params)
 		fe->ops.tuner_ops.set_analog_params(fe, params);
 
 	for (i = 0; i < 3; i++) {
-		tuner_i2c_xfer_send(&priv->i2c_props, &addr_pll_stat, 1);
-		tuner_i2c_xfer_recv(&priv->i2c_props, &pll_stat, 1);
+		tuner_i2c_xfer_send_recv(&priv->i2c_props,
+					 &addr_pll_stat, 1, &pll_stat, 1);
 		if (pll_stat & 0x80) {
-			tuner_i2c_xfer_send(&priv->i2c_props, &addr_adc_sat, 1);
-			tuner_i2c_xfer_recv(&priv->i2c_props, &adc_sat, 1);
-			tuner_i2c_xfer_send(&priv->i2c_props, &addr_agc_stat, 1);
-			tuner_i2c_xfer_recv(&priv->i2c_props, &agc_stat, 1);
+			tuner_i2c_xfer_send_recv(&priv->i2c_props,
+						 &addr_adc_sat, 1,
+						 &adc_sat, 1);
+			tuner_i2c_xfer_send_recv(&priv->i2c_props,
+						 &addr_agc_stat, 1,
+						 &agc_stat, 1);
 			tuner_dbg("tda8290 is locked, AGC: %d\n", agc_stat);
 			break;
 		} else {
@@ -259,20 +261,22 @@ static void tda8290_set_params(struct dv
 			   agc_stat, adc_sat, pll_stat & 0x80);
 		tuner_i2c_xfer_send(&priv->i2c_props, gainset_2, 2);
 		msleep(100);
-		tuner_i2c_xfer_send(&priv->i2c_props, &addr_agc_stat, 1);
-		tuner_i2c_xfer_recv(&priv->i2c_props, &agc_stat, 1);
-		tuner_i2c_xfer_send(&priv->i2c_props, &addr_pll_stat, 1);
-		tuner_i2c_xfer_recv(&priv->i2c_props, &pll_stat, 1);
+		tuner_i2c_xfer_send_recv(&priv->i2c_props,
+					 &addr_agc_stat, 1, &agc_stat, 1);
+		tuner_i2c_xfer_send_recv(&priv->i2c_props,
+					 &addr_pll_stat, 1, &pll_stat, 1);
 		if ((agc_stat > 115) || !(pll_stat & 0x80)) {
 			tuner_dbg("adjust gain, step 2. Agc: %d, lock: %d\n",
 				   agc_stat, pll_stat & 0x80);
 			if (priv->cfg.agcf)
 				priv->cfg.agcf(fe);
 			msleep(100);
-			tuner_i2c_xfer_send(&priv->i2c_props, &addr_agc_stat, 1);
-			tuner_i2c_xfer_recv(&priv->i2c_props, &agc_stat, 1);
-			tuner_i2c_xfer_send(&priv->i2c_props, &addr_pll_stat, 1);
-			tuner_i2c_xfer_recv(&priv->i2c_props, &pll_stat, 1);
+			tuner_i2c_xfer_send_recv(&priv->i2c_props,
+						 &addr_agc_stat, 1,
+						 &agc_stat, 1);
+			tuner_i2c_xfer_send_recv(&priv->i2c_props,
+						 &addr_pll_stat, 1,
+						 &pll_stat, 1);
 			if((agc_stat > 115) || !(pll_stat & 0x80)) {
 				tuner_dbg("adjust gain, step 3. Agc: %d\n", agc_stat);
 				tuner_i2c_xfer_send(&priv->i2c_props, adc_head_12, 2);
@@ -284,10 +288,12 @@ static void tda8290_set_params(struct dv
 
 	/* l/ l' deadlock? */
 	if(priv->tda8290_easy_mode & 0x60) {
-		tuner_i2c_xfer_send(&priv->i2c_props, &addr_adc_sat, 1);
-		tuner_i2c_xfer_recv(&priv->i2c_props, &adc_sat, 1);
-		tuner_i2c_xfer_send(&priv->i2c_props, &addr_pll_stat, 1);
-		tuner_i2c_xfer_recv(&priv->i2c_props, &pll_stat, 1);
+		tuner_i2c_xfer_send_recv(&priv->i2c_props,
+					 &addr_adc_sat, 1,
+					 &adc_sat, 1);
+		tuner_i2c_xfer_send_recv(&priv->i2c_props,
+					 &addr_pll_stat, 1,
+					 &pll_stat, 1);
 		if ((adc_sat > 20) || !(pll_stat & 0x80)) {
 			tuner_dbg("trying to resolve SECAM L deadlock\n");
 			tuner_i2c_xfer_send(&priv->i2c_props, agc_rst_on, 2);
@@ -307,8 +313,7 @@ static void tda8295_power(struct dvb_fro
 	struct tda8290_priv *priv = fe->analog_demod_priv;
 	unsigned char buf[] = { 0x30, 0x00 }; /* clb_stdbt */
 
-	tuner_i2c_xfer_send(&priv->i2c_props, &buf[0], 1);
-	tuner_i2c_xfer_recv(&priv->i2c_props, &buf[1], 1);
+	tuner_i2c_xfer_send_recv(&priv->i2c_props, &buf[0], 1, &buf[1], 1);
 
 	if (enable)
 		buf[1] = 0x01;
@@ -323,8 +328,7 @@ static void tda8295_set_easy_mode(struct
 	struct tda8290_priv *priv = fe->analog_demod_priv;
 	unsigned char buf[] = { 0x01, 0x00 };
 
-	tuner_i2c_xfer_send(&priv->i2c_props, &buf[0], 1);
-	tuner_i2c_xfer_recv(&priv->i2c_props, &buf[1], 1);
+	tuner_i2c_xfer_send_recv(&priv->i2c_props, &buf[0], 1, &buf[1], 1);
 
 	if (enable)
 		buf[1] = 0x01; /* rising edge sets regs 0x02 - 0x23 */
@@ -353,8 +357,7 @@ static void tda8295_agc1_out(struct dvb_
 	struct tda8290_priv *priv = fe->analog_demod_priv;
 	unsigned char buf[] = { 0x02, 0x00 }; /* DIV_FUNC */
 
-	tuner_i2c_xfer_send(&priv->i2c_props, &buf[0], 1);
-	tuner_i2c_xfer_recv(&priv->i2c_props, &buf[1], 1);
+	tuner_i2c_xfer_send_recv(&priv->i2c_props, &buf[0], 1, &buf[1], 1);
 
 	if (enable)
 		buf[1] &= ~0x40;
@@ -370,10 +373,10 @@ static void tda8295_agc2_out(struct dvb_
 	unsigned char set_gpio_cf[]    = { 0x44, 0x00 };
 	unsigned char set_gpio_val[]   = { 0x46, 0x00 };
 
-	tuner_i2c_xfer_send(&priv->i2c_props, &set_gpio_cf[0], 1);
-	tuner_i2c_xfer_recv(&priv->i2c_props, &set_gpio_cf[1], 1);
-	tuner_i2c_xfer_send(&priv->i2c_props, &set_gpio_val[0], 1);
-	tuner_i2c_xfer_recv(&priv->i2c_props, &set_gpio_val[1], 1);
+	tuner_i2c_xfer_send_recv(&priv->i2c_props,
+				 &set_gpio_cf[0], 1, &set_gpio_cf[1], 1);
+	tuner_i2c_xfer_send_recv(&priv->i2c_props,
+				 &set_gpio_val[0], 1, &set_gpio_val[1], 1);
 
 	set_gpio_cf[1] &= 0xf0; /* clear GPIO_0 bits 3-0 */
 
@@ -392,8 +395,7 @@ static int tda8295_has_signal(struct dvb
 	unsigned char hvpll_stat = 0x26;
 	unsigned char ret;
 
-	tuner_i2c_xfer_send(&priv->i2c_props, &hvpll_stat, 1);
-	tuner_i2c_xfer_recv(&priv->i2c_props, &ret, 1);
+	tuner_i2c_xfer_send_recv(&priv->i2c_props, &hvpll_stat, 1, &ret, 1);
 	return (ret & 0x01) ? 65535 : 0;
 }
 
@@ -413,8 +415,8 @@ static void tda8295_set_params(struct dv
 	tda8295_power(fe, 1);
 	tda8295_agc1_out(fe, 1);
 
-	tuner_i2c_xfer_send(&priv->i2c_props, &blanking_mode[0], 1);
-	tuner_i2c_xfer_recv(&priv->i2c_props, &blanking_mode[1], 1);
+	tuner_i2c_xfer_send_recv(&priv->i2c_props,
+				 &blanking_mode[0], 1, &blanking_mode[1], 1);
 
 	tda8295_set_video_std(fe);
 
@@ -447,8 +449,8 @@ static int tda8290_has_signal(struct dvb
 	unsigned char i2c_get_afc[1] = { 0x1B };
 	unsigned char afc = 0;
 
-	tuner_i2c_xfer_send(&priv->i2c_props, i2c_get_afc, ARRAY_SIZE(i2c_get_afc));
-	tuner_i2c_xfer_recv(&priv->i2c_props, &afc, 1);
+	tuner_i2c_xfer_send_recv(&priv->i2c_props,
+				 i2c_get_afc, ARRAY_SIZE(i2c_get_afc), &afc, 1);
 	return (afc & 0x80)? 65535:0;
 }
 
@@ -654,20 +656,26 @@ static int tda829x_find_tuner(struct dvb
 static int tda8290_probe(struct tuner_i2c_props *i2c_props)
 {
 #define TDA8290_ID 0x89
-	unsigned char tda8290_id[] = { 0x1f, 0x00 };
+	u8 reg = 0x1f, id;
+	struct i2c_msg msg_read[] = {
+		{ .addr = i2c_props->addr, .flags = 0, .len = 1, .buf = &reg },
+		{ .addr = i2c_props->addr, .flags = I2C_M_RD, .len = 1, .buf = &id },
+	};
 
 	/* detect tda8290 */
-	tuner_i2c_xfer_send(i2c_props, &tda8290_id[0], 1);
-	tuner_i2c_xfer_recv(i2c_props, &tda8290_id[1], 1);
+	if (i2c_transfer(i2c_props->adap, msg_read, 2) != 2) {
+		printk(KERN_WARNING "%s: couldn't read register 0x%02x\n",
+			       __func__, reg);
+		return -ENODEV;
+	}
 
-	if (tda8290_id[1] == TDA8290_ID) {
+	if (id == TDA8290_ID) {
 		if (debug)
 			printk(KERN_DEBUG "%s: tda8290 detected @ %d-%04x\n",
 			       __func__, i2c_adapter_id(i2c_props->adap),
 			       i2c_props->addr);
 		return 0;
 	}
-
 	return -ENODEV;
 }
 
@@ -675,16 +683,23 @@ static int tda8295_probe(struct tuner_i2
 {
 #define TDA8295_ID 0x8a
 #define TDA8295C2_ID 0x8b
-	unsigned char tda8295_id[] = { 0x2f, 0x00 };
+	u8 reg = 0x2f, id;
+	struct i2c_msg msg_read[] = {
+		{ .addr = i2c_props->addr, .flags = 0, .len = 1, .buf = &reg },
+		{ .addr = i2c_props->addr, .flags = I2C_M_RD, .len = 1, .buf = &id },
+	};
 
 	/* detect tda8295 */
-	tuner_i2c_xfer_send(i2c_props, &tda8295_id[0], 1);
-	tuner_i2c_xfer_recv(i2c_props, &tda8295_id[1], 1);
+	if (i2c_transfer(i2c_props->adap, msg_read, 2) != 2) {
+		printk(KERN_WARNING "%s: couldn't read register 0x%02x\n",
+			       __func__, reg);
+		return -ENODEV;
+	}
 
-	if ((tda8295_id[1] & 0xfe) == TDA8295_ID) {
+	if ((id & 0xfe) == TDA8295_ID) {
 		if (debug)
 			printk(KERN_DEBUG "%s: %s detected @ %d-%04x\n",
-			       __func__, (tda8295_id[1] == TDA8295_ID) ?
+			       __func__, (id == TDA8295_ID) ?
 			       "tda8295c1" : "tda8295c2",
 			       i2c_adapter_id(i2c_props->adap),
 			       i2c_props->addr);
@@ -740,9 +755,11 @@ struct dvb_frontend *tda829x_attach(stru
 		       sizeof(struct analog_demod_ops));
 	}
 
-	if ((!(cfg) || (TDA829X_PROBE_TUNER == cfg->probe_tuner)) &&
-	    (tda829x_find_tuner(fe) < 0))
-		goto fail;
+	if (!(cfg) || (TDA829X_PROBE_TUNER == cfg->probe_tuner)) {
+		tda8295_power(fe, 1);
+		if (tda829x_find_tuner(fe) < 0)
+			goto fail;
+	}
 
 	switch (priv->ver) {
 	case TDA8290:
@@ -786,6 +803,8 @@ struct dvb_frontend *tda829x_attach(stru
 	return fe;
 
 fail:
+	memset(&fe->ops.analog_ops, 0, sizeof(struct analog_demod_ops));
+
 	tda829x_release(fe);
 	return NULL;
 }
@@ -809,8 +828,8 @@ int tda829x_probe(struct i2c_adapter *i2
 	int i;
 
 	/* rule out tda9887, which would return the same byte repeatedly */
-	tuner_i2c_xfer_send(&i2c_props, soft_reset, 1);
-	tuner_i2c_xfer_recv(&i2c_props, buf, PROBE_BUFFER_SIZE);
+	tuner_i2c_xfer_send_recv(&i2c_props,
+				 soft_reset, 1, buf, PROBE_BUFFER_SIZE);
 	for (i = 1; i < PROBE_BUFFER_SIZE; i++) {
 		if (buf[i] != buf[0])
 			break;
@@ -827,13 +846,12 @@ int tda829x_probe(struct i2c_adapter *i2
 	/* fall back to old probing method */
 	tuner_i2c_xfer_send(&i2c_props, easy_mode_b, 2);
 	tuner_i2c_xfer_send(&i2c_props, soft_reset, 2);
-	tuner_i2c_xfer_send(&i2c_props, &addr_dto_lsb, 1);
-	tuner_i2c_xfer_recv(&i2c_props, &data, 1);
+	tuner_i2c_xfer_send_recv(&i2c_props, &addr_dto_lsb, 1, &data, 1);
 	if (data == 0) {
 		tuner_i2c_xfer_send(&i2c_props, easy_mode_g, 2);
 		tuner_i2c_xfer_send(&i2c_props, soft_reset, 2);
-		tuner_i2c_xfer_send(&i2c_props, &addr_dto_lsb, 1);
-		tuner_i2c_xfer_recv(&i2c_props, &data, 1);
+		tuner_i2c_xfer_send_recv(&i2c_props,
+					 &addr_dto_lsb, 1, &data, 1);
 		if (data == 0x7b) {
 			return 0;
 		}
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/dvb/dm1105/dm1105.c linux-libre-2.6.38-gnu1/drivers/media/dvb/dm1105/dm1105.c
--- linux-libre-2.6.37-gnu1/drivers/media/dvb/dm1105/dm1105.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/dvb/dm1105/dm1105.c	2011-03-14 21:20:32.000000000 -0400
@@ -26,9 +26,8 @@
 #include <linux/proc_fs.h>
 #include <linux/pci.h>
 #include <linux/dma-mapping.h>
-#include <linux/input.h>
 #include <linux/slab.h>
-#include <media/ir-core.h>
+#include <media/rc-core.h>
 
 #include "demux.h"
 #include "dmxdev.h"
@@ -266,7 +265,7 @@ static void dm1105_card_list(struct pci_
 
 /* infrared remote control */
 struct infrared {
-	struct input_dev	*input_dev;
+	struct rc_dev		*dev;
 	char			input_phys[32];
 	struct work_struct	work;
 	u32			ir_command;
@@ -532,7 +531,7 @@ static void dm1105_emit_key(struct work_
 
 	data = (ircom >> 8) & 0x7f;
 
-	ir_keydown(ir->input_dev, data, 0);
+	rc_keydown(ir->dev, data, 0);
 }
 
 /* work handler */
@@ -593,46 +592,47 @@ static irqreturn_t dm1105_irq(int irq, v
 
 int __devinit dm1105_ir_init(struct dm1105_dev *dm1105)
 {
-	struct input_dev *input_dev;
-	char *ir_codes = RC_MAP_DM1105_NEC;
+	struct rc_dev *dev;
 	int err = -ENOMEM;
 
-	input_dev = input_allocate_device();
-	if (!input_dev)
+	dev = rc_allocate_device();
+	if (!dev)
 		return -ENOMEM;
 
-	dm1105->ir.input_dev = input_dev;
 	snprintf(dm1105->ir.input_phys, sizeof(dm1105->ir.input_phys),
 		"pci-%s/ir0", pci_name(dm1105->pdev));
 
-	input_dev->name = "DVB on-card IR receiver";
-	input_dev->phys = dm1105->ir.input_phys;
-	input_dev->id.bustype = BUS_PCI;
-	input_dev->id.version = 1;
+	dev->driver_name = MODULE_NAME;
+	dev->map_name = RC_MAP_DM1105_NEC;
+	dev->driver_type = RC_DRIVER_SCANCODE;
+	dev->input_name = "DVB on-card IR receiver";
+	dev->input_phys = dm1105->ir.input_phys;
+	dev->input_id.bustype = BUS_PCI;
+	dev->input_id.version = 1;
 	if (dm1105->pdev->subsystem_vendor) {
-		input_dev->id.vendor = dm1105->pdev->subsystem_vendor;
-		input_dev->id.product = dm1105->pdev->subsystem_device;
+		dev->input_id.vendor = dm1105->pdev->subsystem_vendor;
+		dev->input_id.product = dm1105->pdev->subsystem_device;
 	} else {
-		input_dev->id.vendor = dm1105->pdev->vendor;
-		input_dev->id.product = dm1105->pdev->device;
+		dev->input_id.vendor = dm1105->pdev->vendor;
+		dev->input_id.product = dm1105->pdev->device;
 	}
-
-	input_dev->dev.parent = &dm1105->pdev->dev;
+	dev->dev.parent = &dm1105->pdev->dev;
 
 	INIT_WORK(&dm1105->ir.work, dm1105_emit_key);
 
-	err = ir_input_register(input_dev, ir_codes, NULL, MODULE_NAME);
+	err = rc_register_device(dev);
 	if (err < 0) {
-		input_free_device(input_dev);
+		rc_free_device(dev);
 		return err;
 	}
 
+	dm1105->ir.dev = dev;
 	return 0;
 }
 
 void __devexit dm1105_ir_exit(struct dm1105_dev *dm1105)
 {
-	ir_input_unregister(dm1105->ir.input_dev);
+	rc_unregister_device(dm1105->ir.dev);
 }
 
 static int __devinit dm1105_hw_init(struct dm1105_dev *dev)
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/dvb/dm1105/Kconfig linux-libre-2.6.38-gnu1/drivers/media/dvb/dm1105/Kconfig
--- linux-libre-2.6.37-gnu1/drivers/media/dvb/dm1105/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/dvb/dm1105/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -1,7 +1,6 @@
 config DVB_DM1105
 	tristate "SDMC DM1105 based PCI cards"
 	depends on DVB_CORE && PCI && I2C
-	depends on INPUT
 	select DVB_PLL if !DVB_FE_CUSTOMISE
 	select DVB_STV0299 if !DVB_FE_CUSTOMISE
 	select DVB_STV0288 if !DVB_FE_CUSTOMISE
@@ -9,7 +8,7 @@ config DVB_DM1105
 	select DVB_CX24116 if !DVB_FE_CUSTOMISE
 	select DVB_SI21XX if !DVB_FE_CUSTOMISE
 	select DVB_DS3000 if !DVB_FE_CUSTOMISE
-	depends on VIDEO_IR
+	depends on RC_CORE
 	help
 	  Support for cards based on the SDMC DM1105 PCI chip like
 	  DvbWorld 2002
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/dvb/dvb-core/dmxdev.c linux-libre-2.6.38-gnu1/drivers/media/dvb/dvb-core/dmxdev.c
--- linux-libre-2.6.37-gnu1/drivers/media/dvb/dvb-core/dmxdev.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/dvb/dvb-core/dmxdev.c	2011-03-14 21:20:32.000000000 -0400
@@ -572,13 +572,13 @@ static int dvb_dmxdev_start_feed(struct
 	dmx_output_t otype;
 	int ret;
 	int ts_type;
-	enum dmx_ts_pes ts_pes;
+	dmx_pes_type_t ts_pes;
 	struct dmx_ts_feed *tsfeed;
 
 	feed->ts = NULL;
 	otype = para->output;
 
-	ts_pes = (enum dmx_ts_pes)para->pes_type;
+	ts_pes = para->pes_type;
 
 	if (ts_pes < DMX_PES_OTHER)
 		ts_type = TS_DECODER;
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/dvb/dvb-core/dvb_net.c linux-libre-2.6.38-gnu1/drivers/media/dvb/dvb-core/dvb_net.c
--- linux-libre-2.6.37-gnu1/drivers/media/dvb/dvb-core/dvb_net.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/dvb/dvb-core/dvb_net.c	2011-03-14 21:20:32.000000000 -0400
@@ -1329,7 +1329,8 @@ static int dvb_net_remove_if(struct dvb_
 		return -EBUSY;
 
 	dvb_net_stop(net);
-	flush_scheduled_work();
+	flush_work_sync(&priv->set_multicast_list_wq);
+	flush_work_sync(&priv->restart_net_feed_wq);
 	printk("dvb_net: removed network interface %s\n", net->name);
 	unregister_netdev(net);
 	dvbnet->state[num]=0;
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/dvb/dvb-usb/a800.c linux-libre-2.6.38-gnu1/drivers/media/dvb/dvb-usb/a800.c
--- linux-libre-2.6.37-gnu1/drivers/media/dvb/dvb-usb/a800.c	2013-05-03 03:55:01.000000000 -0400
+++ linux-libre-2.6.38-gnu1/drivers/media/dvb/dvb-usb/a800.c	2013-05-03 01:54:27.000000000 -0400
@@ -37,7 +37,7 @@ static int a800_identify_state(struct us
 	return 0;
 }
 
-static struct ir_scancode ir_codes_a800_table[] = {
+static struct rc_map_table rc_map_a800_table[] = {
 	{ 0x0201, KEY_PROG1 },       /* SOURCE */
 	{ 0x0200, KEY_POWER },       /* POWER */
 	{ 0x0205, KEY_1 },           /* 1 */
@@ -148,8 +148,8 @@ static struct dvb_usb_device_properties
 
 	.rc.legacy = {
 		.rc_interval      = DEFAULT_RC_INTERVAL,
-		.rc_key_map       = ir_codes_a800_table,
-		.rc_key_map_size  = ARRAY_SIZE(ir_codes_a800_table),
+		.rc_map_table     = rc_map_a800_table,
+		.rc_map_size      = ARRAY_SIZE(rc_map_a800_table),
 		.rc_query         = a800_rc_query,
 	},
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/dvb/dvb-usb/af9005.c linux-libre-2.6.38-gnu1/drivers/media/dvb/dvb-usb/af9005.c
--- linux-libre-2.6.37-gnu1/drivers/media/dvb/dvb-usb/af9005.c	2013-05-03 03:55:06.000000000 -0400
+++ linux-libre-2.6.38-gnu1/drivers/media/dvb/dvb-usb/af9005.c	2013-05-03 01:54:38.000000000 -0400
@@ -1027,8 +1027,8 @@ static struct dvb_usb_device_properties
 
 	.rc.legacy = {
 		.rc_interval = 200,
-		.rc_key_map = NULL,
-		.rc_key_map_size = 0,
+		.rc_map_table = NULL,
+		.rc_map_size = 0,
 		.rc_query = af9005_rc_query,
 	},
 
@@ -1070,14 +1070,14 @@ static int __init af9005_usb_module_init
 		return result;
 	}
 	rc_decode = symbol_request(af9005_rc_decode);
-	rc_keys = symbol_request(ir_codes_af9005_table);
-	rc_keys_size = symbol_request(ir_codes_af9005_table_size);
+	rc_keys = symbol_request(rc_map_af9005_table);
+	rc_keys_size = symbol_request(rc_map_af9005_table_size);
 	if (rc_decode == NULL || rc_keys == NULL || rc_keys_size == NULL) {
 		err("af9005_rc_decode function not found, disabling remote");
 		af9005_properties.rc.legacy.rc_query = NULL;
 	} else {
-		af9005_properties.rc.legacy.rc_key_map = rc_keys;
-		af9005_properties.rc.legacy.rc_key_map_size = *rc_keys_size;
+		af9005_properties.rc.legacy.rc_map_table = rc_keys;
+		af9005_properties.rc.legacy.rc_map_size = *rc_keys_size;
 	}
 
 	return 0;
@@ -1089,9 +1089,9 @@ static void __exit af9005_usb_module_exi
 	if (rc_decode != NULL)
 		symbol_put(af9005_rc_decode);
 	if (rc_keys != NULL)
-		symbol_put(ir_codes_af9005_table);
+		symbol_put(rc_map_af9005_table);
 	if (rc_keys_size != NULL)
-		symbol_put(ir_codes_af9005_table_size);
+		symbol_put(rc_map_af9005_table_size);
 	/* deregister this driver from the USB subsystem */
 	usb_deregister(&af9005_usb_driver);
 }
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/dvb/dvb-usb/af9005.h linux-libre-2.6.38-gnu1/drivers/media/dvb/dvb-usb/af9005.h
--- linux-libre-2.6.37-gnu1/drivers/media/dvb/dvb-usb/af9005.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/dvb/dvb-usb/af9005.h	2011-03-14 21:20:32.000000000 -0400
@@ -3490,7 +3490,7 @@ extern u8 regmask[8];
 /* remote control decoder */
 extern int af9005_rc_decode(struct dvb_usb_device *d, u8 * data, int len,
 			    u32 * event, int *state);
-extern struct ir_scancode ir_codes_af9005_table[];
-extern int ir_codes_af9005_table_size;
+extern struct rc_map_table rc_map_af9005_table[];
+extern int rc_map_af9005_table_size;
 
 #endif
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/dvb/dvb-usb/af9005-remote.c linux-libre-2.6.38-gnu1/drivers/media/dvb/dvb-usb/af9005-remote.c
--- linux-libre-2.6.37-gnu1/drivers/media/dvb/dvb-usb/af9005-remote.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/dvb/dvb-usb/af9005-remote.c	2011-03-14 21:20:32.000000000 -0400
@@ -33,7 +33,7 @@ MODULE_PARM_DESC(debug,
 
 #define deb_decode(args...)   dprintk(dvb_usb_af9005_remote_debug,0x01,args)
 
-struct ir_scancode ir_codes_af9005_table[] = {
+struct rc_map_table rc_map_af9005_table[] = {
 
 	{0x01b7, KEY_POWER},
 	{0x01a7, KEY_VOLUMEUP},
@@ -74,7 +74,7 @@ struct ir_scancode ir_codes_af9005_table
 	{0x00d5, KEY_GOTO},	/* marked jump on the remote */
 };
 
-int ir_codes_af9005_table_size = ARRAY_SIZE(ir_codes_af9005_table);
+int rc_map_af9005_table_size = ARRAY_SIZE(rc_map_af9005_table);
 
 static int repeatable_keys[] = {
 	KEY_VOLUMEUP,
@@ -130,10 +130,10 @@ int af9005_rc_decode(struct dvb_usb_devi
 				deb_decode("code != inverted code\n");
 				return 0;
 			}
-			for (i = 0; i < ir_codes_af9005_table_size; i++) {
-				if (rc5_custom(&ir_codes_af9005_table[i]) == cust
-				    && rc5_data(&ir_codes_af9005_table[i]) == dat) {
-					*event = ir_codes_af9005_table[i].keycode;
+			for (i = 0; i < rc_map_af9005_table_size; i++) {
+				if (rc5_custom(&rc_map_af9005_table[i]) == cust
+				    && rc5_data(&rc_map_af9005_table[i]) == dat) {
+					*event = rc_map_af9005_table[i].keycode;
 					*state = REMOTE_KEY_PRESSED;
 					deb_decode
 					    ("key pressed, event %x\n", *event);
@@ -146,8 +146,8 @@ int af9005_rc_decode(struct dvb_usb_devi
 	return 0;
 }
 
-EXPORT_SYMBOL(ir_codes_af9005_table);
-EXPORT_SYMBOL(ir_codes_af9005_table_size);
+EXPORT_SYMBOL(rc_map_af9005_table);
+EXPORT_SYMBOL(rc_map_af9005_table_size);
 EXPORT_SYMBOL(af9005_rc_decode);
 
 MODULE_AUTHOR("Luca Olivetti <luca@ventoso.org>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/dvb/dvb-usb/af9015.c linux-libre-2.6.38-gnu1/drivers/media/dvb/dvb-usb/af9015.c
--- linux-libre-2.6.37-gnu1/drivers/media/dvb/dvb-usb/af9015.c	2013-05-03 03:55:09.000000000 -0400
+++ linux-libre-2.6.38-gnu1/drivers/media/dvb/dvb-usb/af9015.c	2013-05-03 01:54:42.000000000 -0400
@@ -1041,13 +1041,13 @@ static int af9015_rc_query(struct dvb_us
 				priv->rc_keycode = buf[12] << 16 |
 					buf[13] << 8 | buf[14];
 			}
-			ir_keydown(d->rc_input_dev, priv->rc_keycode, 0);
+			rc_keydown(d->rc_dev, priv->rc_keycode, 0);
 		} else {
 			priv->rc_keycode = 0; /* clear just for sure */
 		}
 	} else if (priv->rc_repeat != buf[6] || buf[0]) {
 		deb_rc("%s: key repeated\n", __func__);
-		ir_keydown(d->rc_input_dev, priv->rc_keycode, 0);
+		rc_keydown(d->rc_dev, priv->rc_keycode, 0);
 	} else {
 		deb_rc("%s: no key press\n", __func__);
 	}
@@ -1344,13 +1344,11 @@ static struct dvb_usb_device_properties
 		.identify_state = af9015_identify_state,
 
 		.rc.core = {
-			.protocol         = IR_TYPE_NEC,
+			.protocol         = RC_TYPE_NEC,
 			.module_name      = "af9015",
 			.rc_query         = af9015_rc_query,
 			.rc_interval      = AF9015_RC_INTERVAL,
-			.rc_props = {
-				.allowed_protos = IR_TYPE_NEC,
-			},
+			.allowed_protos   = RC_TYPE_NEC,
 		},
 
 		.i2c_algo = &af9015_i2c_algo,
@@ -1474,13 +1472,11 @@ static struct dvb_usb_device_properties
 		.identify_state = af9015_identify_state,
 
 		.rc.core = {
-			.protocol         = IR_TYPE_NEC,
+			.protocol         = RC_TYPE_NEC,
 			.module_name      = "af9015",
 			.rc_query         = af9015_rc_query,
 			.rc_interval      = AF9015_RC_INTERVAL,
-			.rc_props = {
-				.allowed_protos = IR_TYPE_NEC,
-			},
+			.allowed_protos   = RC_TYPE_NEC,
 		},
 
 		.i2c_algo = &af9015_i2c_algo,
@@ -1588,13 +1584,11 @@ static struct dvb_usb_device_properties
 		.identify_state = af9015_identify_state,
 
 		.rc.core = {
-			.protocol         = IR_TYPE_NEC,
+			.protocol         = RC_TYPE_NEC,
 			.module_name      = "af9015",
 			.rc_query         = af9015_rc_query,
 			.rc_interval      = AF9015_RC_INTERVAL,
-			.rc_props = {
-				.allowed_protos = IR_TYPE_NEC,
-			},
+			.allowed_protos   = RC_TYPE_NEC,
 		},
 
 		.i2c_algo = &af9015_i2c_algo,
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/dvb/dvb-usb/anysee.c linux-libre-2.6.38-gnu1/drivers/media/dvb/dvb-usb/anysee.c
--- linux-libre-2.6.37-gnu1/drivers/media/dvb/dvb-usb/anysee.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/dvb/dvb-usb/anysee.c	2011-03-14 21:20:32.000000000 -0400
@@ -394,7 +394,7 @@ static int anysee_rc_query(struct dvb_us
 
 	if (ircode[0]) {
 		deb_rc("%s: key pressed %02x\n", __func__, ircode[1]);
-		ir_keydown(d->rc_input_dev, 0x08 << 8 | ircode[1], 0);
+		rc_keydown(d->rc_dev, 0x08 << 8 | ircode[1], 0);
 	}
 
 	return 0;
@@ -476,7 +476,7 @@ static struct dvb_usb_device_properties
 
 	.rc.core = {
 		.rc_codes         = RC_MAP_ANYSEE,
-		.protocol         = IR_TYPE_OTHER,
+		.protocol         = RC_TYPE_OTHER,
 		.module_name      = "anysee",
 		.rc_query         = anysee_rc_query,
 		.rc_interval      = 250,  /* windows driver uses 500ms */
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/dvb/dvb-usb/az6027.c linux-libre-2.6.38-gnu1/drivers/media/dvb/dvb-usb/az6027.c
--- linux-libre-2.6.37-gnu1/drivers/media/dvb/dvb-usb/az6027.c	2013-05-03 03:55:11.000000000 -0400
+++ linux-libre-2.6.38-gnu1/drivers/media/dvb/dvb-usb/az6027.c	2013-05-03 01:54:44.000000000 -0400
@@ -386,7 +386,7 @@ static int az6027_streaming_ctrl(struct
 }
 
 /* keys for the enclosed remote control */
-static struct ir_scancode ir_codes_az6027_table[] = {
+static struct rc_map_table rc_map_az6027_table[] = {
 	{ 0x01, KEY_1 },
 	{ 0x02, KEY_2 },
 };
@@ -1089,6 +1089,7 @@ static struct usb_device_id az6027_usb_t
 	{ USB_DEVICE(USB_VID_TERRATEC,  USB_PID_TERRATEC_DVBS2CI_V2) },
 	{ USB_DEVICE(USB_VID_TECHNISAT, USB_PID_TECHNISAT_USB2_HDCI_V1) },
 	{ USB_DEVICE(USB_VID_TECHNISAT, USB_PID_TECHNISAT_USB2_HDCI_V2) },
+	{ USB_DEVICE(USB_VID_ELGATO, USB_PID_ELGATO_EYETV_SAT) },
 	{ },
 };
 
@@ -1126,15 +1127,15 @@ static struct dvb_usb_device_properties
 	.read_mac_address = az6027_read_mac_addr,
  */
 	.rc.legacy = {
-		.rc_key_map       = ir_codes_az6027_table,
-		.rc_key_map_size  = ARRAY_SIZE(ir_codes_az6027_table),
+		.rc_map_table     = rc_map_az6027_table,
+		.rc_map_size      = ARRAY_SIZE(rc_map_az6027_table),
 		.rc_interval      = 400,
 		.rc_query         = az6027_rc_query,
 	},
 
 	.i2c_algo         = &az6027_i2c_algo,
 
-	.num_device_descs = 5,
+	.num_device_descs = 6,
 	.devices = {
 		{
 			.name = "AZUREWAVE DVB-S/S2 USB2.0 (AZ6027)",
@@ -1156,6 +1157,10 @@ static struct dvb_usb_device_properties
 			.name = "Technisat SkyStar USB 2 HD CI",
 			.cold_ids = { &az6027_usb_table[4], NULL },
 			.warm_ids = { NULL },
+		}, {
+			.name = "Elgato EyeTV Sat",
+			.cold_ids = { &az6027_usb_table[5], NULL },
+			.warm_ids = { NULL },
 		},
 		{ NULL },
 	}
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/dvb/dvb-usb/cinergyT2-core.c linux-libre-2.6.38-gnu1/drivers/media/dvb/dvb-usb/cinergyT2-core.c
--- linux-libre-2.6.37-gnu1/drivers/media/dvb/dvb-usb/cinergyT2-core.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/dvb/dvb-usb/cinergyT2-core.c	2011-03-14 21:20:32.000000000 -0400
@@ -84,7 +84,7 @@ static int cinergyt2_frontend_attach(str
 	return 0;
 }
 
-static struct ir_scancode ir_codes_cinergyt2_table[] = {
+static struct rc_map_table rc_map_cinergyt2_table[] = {
 	{ 0x0401, KEY_POWER },
 	{ 0x0402, KEY_1 },
 	{ 0x0403, KEY_2 },
@@ -219,8 +219,8 @@ static struct dvb_usb_device_properties
 
 	.rc.legacy = {
 		.rc_interval      = 50,
-		.rc_key_map       = ir_codes_cinergyt2_table,
-		.rc_key_map_size  = ARRAY_SIZE(ir_codes_cinergyt2_table),
+		.rc_map_table     = rc_map_cinergyt2_table,
+		.rc_map_size      = ARRAY_SIZE(rc_map_cinergyt2_table),
 		.rc_query         = cinergyt2_rc_query,
 	},
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/dvb/dvb-usb/cxusb.c linux-libre-2.6.38-gnu1/drivers/media/dvb/dvb-usb/cxusb.c
--- linux-libre-2.6.37-gnu1/drivers/media/dvb/dvb-usb/cxusb.c	2013-05-03 03:55:14.000000000 -0400
+++ linux-libre-2.6.38-gnu1/drivers/media/dvb/dvb-usb/cxusb.c	2013-05-03 01:54:47.000000000 -0400
@@ -385,7 +385,7 @@ static int cxusb_d680_dmb_streaming_ctrl
 
 static int cxusb_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
 {
-	struct ir_scancode *keymap = d->props.rc.legacy.rc_key_map;
+	struct rc_map_table *keymap = d->props.rc.legacy.rc_map_table;
 	u8 ircode[4];
 	int i;
 
@@ -394,7 +394,7 @@ static int cxusb_rc_query(struct dvb_usb
 	*event = 0;
 	*state = REMOTE_NO_KEY_PRESSED;
 
-	for (i = 0; i < d->props.rc.legacy.rc_key_map_size; i++) {
+	for (i = 0; i < d->props.rc.legacy.rc_map_size; i++) {
 		if (rc5_custom(&keymap[i]) == ircode[2] &&
 		    rc5_data(&keymap[i]) == ircode[3]) {
 			*event = keymap[i].keycode;
@@ -410,7 +410,7 @@ static int cxusb_rc_query(struct dvb_usb
 static int cxusb_bluebird2_rc_query(struct dvb_usb_device *d, u32 *event,
 				    int *state)
 {
-	struct ir_scancode *keymap = d->props.rc.legacy.rc_key_map;
+	struct rc_map_table *keymap = d->props.rc.legacy.rc_map_table;
 	u8 ircode[4];
 	int i;
 	struct i2c_msg msg = { .addr = 0x6b, .flags = I2C_M_RD,
@@ -422,7 +422,7 @@ static int cxusb_bluebird2_rc_query(stru
 	if (cxusb_i2c_xfer(&d->i2c_adap, &msg, 1) != 1)
 		return 0;
 
-	for (i = 0; i < d->props.rc.legacy.rc_key_map_size; i++) {
+	for (i = 0; i < d->props.rc.legacy.rc_map_size; i++) {
 		if (rc5_custom(&keymap[i]) == ircode[1] &&
 		    rc5_data(&keymap[i]) == ircode[2]) {
 			*event = keymap[i].keycode;
@@ -438,7 +438,7 @@ static int cxusb_bluebird2_rc_query(stru
 static int cxusb_d680_dmb_rc_query(struct dvb_usb_device *d, u32 *event,
 		int *state)
 {
-	struct ir_scancode *keymap = d->props.rc.legacy.rc_key_map;
+	struct rc_map_table *keymap = d->props.rc.legacy.rc_map_table;
 	u8 ircode[2];
 	int i;
 
@@ -448,7 +448,7 @@ static int cxusb_d680_dmb_rc_query(struc
 	if (cxusb_ctrl_msg(d, 0x10, NULL, 0, ircode, 2) < 0)
 		return 0;
 
-	for (i = 0; i < d->props.rc.legacy.rc_key_map_size; i++) {
+	for (i = 0; i < d->props.rc.legacy.rc_map_size; i++) {
 		if (rc5_custom(&keymap[i]) == ircode[0] &&
 		    rc5_data(&keymap[i]) == ircode[1]) {
 			*event = keymap[i].keycode;
@@ -461,7 +461,7 @@ static int cxusb_d680_dmb_rc_query(struc
 	return 0;
 }
 
-static struct ir_scancode ir_codes_dvico_mce_table[] = {
+static struct rc_map_table rc_map_dvico_mce_table[] = {
 	{ 0xfe02, KEY_TV },
 	{ 0xfe0e, KEY_MP3 },
 	{ 0xfe1a, KEY_DVD },
@@ -509,7 +509,7 @@ static struct ir_scancode ir_codes_dvico
 	{ 0xfe4e, KEY_POWER },
 };
 
-static struct ir_scancode ir_codes_dvico_portable_table[] = {
+static struct rc_map_table rc_map_dvico_portable_table[] = {
 	{ 0xfc02, KEY_SETUP },       /* Profile */
 	{ 0xfc43, KEY_POWER2 },
 	{ 0xfc06, KEY_EPG },
@@ -548,7 +548,7 @@ static struct ir_scancode ir_codes_dvico
 	{ 0xfc00, KEY_UNKNOWN },    /* HD */
 };
 
-static struct ir_scancode ir_codes_d680_dmb_table[] = {
+static struct rc_map_table rc_map_d680_dmb_table[] = {
 	{ 0x0038, KEY_UNKNOWN },	/* TV/AV */
 	{ 0x080c, KEY_ZOOM },
 	{ 0x0800, KEY_0 },
@@ -923,7 +923,7 @@ static int cxusb_dualdig4_frontend_attac
 		return -EIO;
 
 	/* try to determine if there is no IR decoder on the I2C bus */
-	for (i = 0; adap->dev->props.rc.legacy.rc_key_map != NULL && i < 5; i++) {
+	for (i = 0; adap->dev->props.rc.legacy.rc_map_table != NULL && i < 5; i++) {
 		msleep(20);
 		if (cxusb_i2c_xfer(&adap->dev->i2c_adap, &msg, 1) != 1)
 			goto no_IR;
@@ -931,7 +931,7 @@ static int cxusb_dualdig4_frontend_attac
 			continue;
 		if (ircode[2] + ircode[3] != 0xff) {
 no_IR:
-			adap->dev->props.rc.legacy.rc_key_map = NULL;
+			adap->dev->props.rc.legacy.rc_map_table = NULL;
 			info("No IR receiver detected on this device.");
 			break;
 		}
@@ -1453,8 +1453,8 @@ static struct dvb_usb_device_properties
 
 	.rc.legacy = {
 		.rc_interval      = 100,
-		.rc_key_map       = ir_codes_dvico_portable_table,
-		.rc_key_map_size  = ARRAY_SIZE(ir_codes_dvico_portable_table),
+		.rc_map_table     = rc_map_dvico_portable_table,
+		.rc_map_size      = ARRAY_SIZE(rc_map_dvico_portable_table),
 		.rc_query         = cxusb_rc_query,
 	},
 
@@ -1506,8 +1506,8 @@ static struct dvb_usb_device_properties
 
 	.rc.legacy = {
 		.rc_interval      = 150,
-		.rc_key_map       = ir_codes_dvico_mce_table,
-		.rc_key_map_size  = ARRAY_SIZE(ir_codes_dvico_mce_table),
+		.rc_map_table     = rc_map_dvico_mce_table,
+		.rc_map_size      = ARRAY_SIZE(rc_map_dvico_mce_table),
 		.rc_query         = cxusb_rc_query,
 	},
 
@@ -1567,8 +1567,8 @@ static struct dvb_usb_device_properties
 
 	.rc.legacy = {
 		.rc_interval      = 100,
-		.rc_key_map       = ir_codes_dvico_portable_table,
-		.rc_key_map_size  = ARRAY_SIZE(ir_codes_dvico_portable_table),
+		.rc_map_table     = rc_map_dvico_portable_table,
+		.rc_map_size      = ARRAY_SIZE(rc_map_dvico_portable_table),
 		.rc_query         = cxusb_rc_query,
 	},
 
@@ -1619,8 +1619,8 @@ static struct dvb_usb_device_properties
 
 	.rc.legacy = {
 		.rc_interval      = 100,
-		.rc_key_map       = ir_codes_dvico_portable_table,
-		.rc_key_map_size  = ARRAY_SIZE(ir_codes_dvico_portable_table),
+		.rc_map_table     = rc_map_dvico_portable_table,
+		.rc_map_size      = ARRAY_SIZE(rc_map_dvico_portable_table),
 		.rc_query         = cxusb_rc_query,
 	},
 
@@ -1670,8 +1670,8 @@ static struct dvb_usb_device_properties
 
 	.rc.legacy = {
 		.rc_interval      = 100,
-		.rc_key_map       = ir_codes_dvico_mce_table,
-		.rc_key_map_size  = ARRAY_SIZE(ir_codes_dvico_mce_table),
+		.rc_map_table     = rc_map_dvico_mce_table,
+		.rc_map_size      = ARRAY_SIZE(rc_map_dvico_mce_table),
 		.rc_query         = cxusb_bluebird2_rc_query,
 	},
 
@@ -1720,8 +1720,8 @@ static struct dvb_usb_device_properties
 
 	.rc.legacy = {
 		.rc_interval      = 100,
-		.rc_key_map       = ir_codes_dvico_portable_table,
-		.rc_key_map_size  = ARRAY_SIZE(ir_codes_dvico_portable_table),
+		.rc_map_table     = rc_map_dvico_portable_table,
+		.rc_map_size      = ARRAY_SIZE(rc_map_dvico_portable_table),
 		.rc_query         = cxusb_bluebird2_rc_query,
 	},
 
@@ -1772,8 +1772,8 @@ static struct dvb_usb_device_properties
 
 	.rc.legacy = {
 		.rc_interval      = 100,
-		.rc_key_map       = ir_codes_dvico_portable_table,
-		.rc_key_map_size  = ARRAY_SIZE(ir_codes_dvico_portable_table),
+		.rc_map_table     = rc_map_dvico_portable_table,
+		.rc_map_size      = ARRAY_SIZE(rc_map_dvico_portable_table),
 		.rc_query         = cxusb_rc_query,
 	},
 
@@ -1865,8 +1865,8 @@ struct dvb_usb_device_properties cxusb_b
 
 	.rc.legacy = {
 		.rc_interval      = 100,
-		.rc_key_map       = ir_codes_dvico_mce_table,
-		.rc_key_map_size  = ARRAY_SIZE(ir_codes_dvico_mce_table),
+		.rc_map_table     = rc_map_dvico_mce_table,
+		.rc_map_size      = ARRAY_SIZE(rc_map_dvico_mce_table),
 		.rc_query         = cxusb_rc_query,
 	},
 
@@ -1915,8 +1915,8 @@ static struct dvb_usb_device_properties
 
 	.rc.legacy = {
 		.rc_interval      = 100,
-		.rc_key_map       = ir_codes_d680_dmb_table,
-		.rc_key_map_size  = ARRAY_SIZE(ir_codes_d680_dmb_table),
+		.rc_map_table     = rc_map_d680_dmb_table,
+		.rc_map_size      = ARRAY_SIZE(rc_map_d680_dmb_table),
 		.rc_query         = cxusb_d680_dmb_rc_query,
 	},
 
@@ -1966,8 +1966,8 @@ static struct dvb_usb_device_properties
 
 	.rc.legacy = {
 		.rc_interval      = 100,
-		.rc_key_map       = ir_codes_d680_dmb_table,
-		.rc_key_map_size  = ARRAY_SIZE(ir_codes_d680_dmb_table),
+		.rc_map_table     = rc_map_d680_dmb_table,
+		.rc_map_size      = ARRAY_SIZE(rc_map_d680_dmb_table),
 		.rc_query         = cxusb_d680_dmb_rc_query,
 	},
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/dvb/dvb-usb/dib0700_core.c linux-libre-2.6.38-gnu1/drivers/media/dvb/dvb-usb/dib0700_core.c
--- linux-libre-2.6.37-gnu1/drivers/media/dvb/dvb-usb/dib0700_core.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/dvb/dvb-usb/dib0700_core.c	2011-03-14 21:20:32.000000000 -0400
@@ -471,19 +471,19 @@ int dib0700_streaming_ctrl(struct dvb_us
 	return dib0700_ctrl_wr(adap->dev, b, 4);
 }
 
-int dib0700_change_protocol(void *priv, u64 ir_type)
+int dib0700_change_protocol(struct rc_dev *rc, u64 rc_type)
 {
-	struct dvb_usb_device *d = priv;
+	struct dvb_usb_device *d = rc->priv;
 	struct dib0700_state *st = d->priv;
 	u8 rc_setup[3] = { REQUEST_SET_RC, 0, 0 };
 	int new_proto, ret;
 
 	/* Set the IR mode */
-	if (ir_type == IR_TYPE_RC5)
+	if (rc_type == RC_TYPE_RC5)
 		new_proto = 1;
-	else if (ir_type == IR_TYPE_NEC)
+	else if (rc_type == RC_TYPE_NEC)
 		new_proto = 0;
-	else if (ir_type == IR_TYPE_RC6) {
+	else if (rc_type == RC_TYPE_RC6) {
 		if (st->fw_version < 0x10200)
 			return -EINVAL;
 
@@ -499,7 +499,7 @@ int dib0700_change_protocol(void *priv,
 		return ret;
 	}
 
-	d->props.rc.core.protocol = ir_type;
+	d->props.rc.core.protocol = rc_type;
 
 	return ret;
 }
@@ -514,8 +514,8 @@ struct dib0700_rc_response {
 	union {
 		u16 system16;
 		struct {
-			u8 system;
 			u8 not_system;
+			u8 system;
 		};
 	};
 	u8 data;
@@ -535,7 +535,7 @@ static void dib0700_rc_urb_completion(st
 	if (d == NULL)
 		return;
 
-	if (d->rc_input_dev == NULL) {
+	if (d->rc_dev == NULL) {
 		/* This will occur if disable_rc_polling=1 */
 		usb_free_urb(purb);
 		return;
@@ -562,7 +562,7 @@ static void dib0700_rc_urb_completion(st
 		 purb->actual_length);
 
 	switch (d->props.rc.core.protocol) {
-	case IR_TYPE_NEC:
+	case RC_TYPE_NEC:
 		toggle = 0;
 
 		/* NEC protocol sends repeat code as 0 0 0 FF */
@@ -575,7 +575,7 @@ static void dib0700_rc_urb_completion(st
 		if ((poll_reply->system ^ poll_reply->not_system) != 0xff) {
 			deb_data("NEC extended protocol\n");
 			/* NEC extended code - 24 bits */
-			keycode = poll_reply->system16 << 8 | poll_reply->data;
+			keycode = be16_to_cpu(poll_reply->system16) << 8 | poll_reply->data;
 		} else {
 			deb_data("NEC normal protocol\n");
 			/* normal NEC code - 16 bits */
@@ -587,7 +587,7 @@ static void dib0700_rc_urb_completion(st
 		deb_data("RC5 protocol\n");
 		/* RC5 Protocol */
 		toggle = poll_reply->report_id;
-		keycode = poll_reply->system16 << 8 | poll_reply->data;
+		keycode = poll_reply->system << 8 | poll_reply->data;
 
 		break;
 	}
@@ -600,7 +600,7 @@ static void dib0700_rc_urb_completion(st
 		goto resubmit;
 	}
 
-	ir_keydown(d->rc_input_dev, keycode, toggle);
+	rc_keydown(d->rc_dev, keycode, toggle);
 
 resubmit:
 	/* Clean the buffer before we requeue */
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/dvb/dvb-usb/dib0700_devices.c linux-libre-2.6.38-gnu1/drivers/media/dvb/dvb-usb/dib0700_devices.c
--- linux-libre-2.6.37-gnu1/drivers/media/dvb/dvb-usb/dib0700_devices.c	2013-05-03 03:55:17.000000000 -0400
+++ linux-libre-2.6.38-gnu1/drivers/media/dvb/dvb-usb/dib0700_devices.c	2013-05-03 01:54:50.000000000 -0400
@@ -510,7 +510,7 @@ static int dib0700_rc_query_old_firmware
 
 	d->last_event = 0;
 	switch (d->props.rc.core.protocol) {
-	case IR_TYPE_NEC:
+	case RC_TYPE_NEC:
 		/* NEC protocol sends repeat code as 0 0 0 FF */
 		if ((key[3-2] == 0x00) && (key[3-3] == 0x00) &&
 		    (key[3] == 0xff))
@@ -520,13 +520,13 @@ static int dib0700_rc_query_old_firmware
 			d->last_event = keycode;
 		}
 
-		ir_keydown(d->rc_input_dev, keycode, 0);
+		rc_keydown(d->rc_dev, keycode, 0);
 		break;
 	default:
 		/* RC-5 protocol changes toggle bit on new keypress */
 		keycode = key[3-2] << 8 | key[3-3];
 		toggle = key[3-1];
-		ir_keydown(d->rc_input_dev, keycode, toggle);
+		rc_keydown(d->rc_dev, keycode, toggle);
 
 		break;
 	}
@@ -870,6 +870,23 @@ static int dib7070p_tuner_attach(struct
 	return 0;
 }
 
+static int stk7700p_pid_filter(struct dvb_usb_adapter *adapter, int index,
+		u16 pid, int onoff)
+{
+	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);
+}
+
+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);
+}
+
 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);
@@ -1875,8 +1892,8 @@ struct dvb_usb_device_properties dib0700
 			{
 				.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,
-				.pid_filter_ctrl  = stk70x0p_pid_filter_ctrl,
+				.pid_filter       = stk7700p_pid_filter,
+				.pid_filter_ctrl  = stk7700p_pid_filter_ctrl,
 				.frontend_attach  = stk7700p_frontend_attach,
 				.tuner_attach     = stk7700p_tuner_attach,
 
@@ -1924,12 +1941,10 @@ struct dvb_usb_device_properties dib0700
 			.rc_interval      = DEFAULT_RC_INTERVAL,
 			.rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
 			.rc_query         = dib0700_rc_query_old_firmware,
-			.rc_props = {
-				.allowed_protos = IR_TYPE_RC5 |
-						  IR_TYPE_RC6 |
-						  IR_TYPE_NEC,
-				.change_protocol = dib0700_change_protocol,
-			},
+			.allowed_protos   = RC_TYPE_RC5 |
+					    RC_TYPE_RC6 |
+					    RC_TYPE_NEC,
+			.change_protocol  = dib0700_change_protocol,
 		},
 	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
 
@@ -1960,12 +1975,10 @@ struct dvb_usb_device_properties dib0700
 			.rc_interval      = DEFAULT_RC_INTERVAL,
 			.rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
 			.rc_query         = dib0700_rc_query_old_firmware,
-			.rc_props = {
-				.allowed_protos = IR_TYPE_RC5 |
-						  IR_TYPE_RC6 |
-						  IR_TYPE_NEC,
-				.change_protocol = dib0700_change_protocol,
-			},
+			.allowed_protos   = RC_TYPE_RC5 |
+					    RC_TYPE_RC6 |
+					    RC_TYPE_NEC,
+			.change_protocol = dib0700_change_protocol,
 		},
 	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
 
@@ -2021,12 +2034,10 @@ struct dvb_usb_device_properties dib0700
 			.rc_interval      = DEFAULT_RC_INTERVAL,
 			.rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
 			.rc_query         = dib0700_rc_query_old_firmware,
-			.rc_props = {
-				.allowed_protos = IR_TYPE_RC5 |
-						  IR_TYPE_RC6 |
-						  IR_TYPE_NEC,
-				.change_protocol = dib0700_change_protocol,
-			},
+			.allowed_protos   = RC_TYPE_RC5 |
+					    RC_TYPE_RC6 |
+					    RC_TYPE_NEC,
+			.change_protocol = dib0700_change_protocol,
 		},
 	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
 
@@ -2065,12 +2076,10 @@ struct dvb_usb_device_properties dib0700
 			.rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
 			.module_name	  = "dib0700",
 			.rc_query         = dib0700_rc_query_old_firmware,
-			.rc_props = {
-				.allowed_protos = IR_TYPE_RC5 |
-						  IR_TYPE_RC6 |
-						  IR_TYPE_NEC,
-				.change_protocol = dib0700_change_protocol,
-			},
+			.allowed_protos   = RC_TYPE_RC5 |
+					    RC_TYPE_RC6 |
+					    RC_TYPE_NEC,
+			.change_protocol = dib0700_change_protocol,
 		},
 	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
 
@@ -2143,12 +2152,10 @@ struct dvb_usb_device_properties dib0700
 			.rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
 			.module_name	  = "dib0700",
 			.rc_query         = dib0700_rc_query_old_firmware,
-			.rc_props = {
-				.allowed_protos = IR_TYPE_RC5 |
-						  IR_TYPE_RC6 |
-						  IR_TYPE_NEC,
-				.change_protocol = dib0700_change_protocol,
-			},
+			.allowed_protos   = RC_TYPE_RC5 |
+					    RC_TYPE_RC6 |
+					    RC_TYPE_NEC,
+			.change_protocol  = dib0700_change_protocol,
 		},
 	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
 
@@ -2189,12 +2196,10 @@ struct dvb_usb_device_properties dib0700
 			.rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
 			.module_name	  = "dib0700",
 			.rc_query         = dib0700_rc_query_old_firmware,
-			.rc_props = {
-				.allowed_protos = IR_TYPE_RC5 |
-						  IR_TYPE_RC6 |
-						  IR_TYPE_NEC,
-				.change_protocol = dib0700_change_protocol,
-			},
+			.allowed_protos   = RC_TYPE_RC5 |
+					    RC_TYPE_RC6 |
+					    RC_TYPE_NEC,
+			.change_protocol  = dib0700_change_protocol,
 		},
 	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
 
@@ -2259,12 +2264,10 @@ struct dvb_usb_device_properties dib0700
 			.rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
 			.module_name	  = "dib0700",
 			.rc_query         = dib0700_rc_query_old_firmware,
-			.rc_props = {
-				.allowed_protos = IR_TYPE_RC5 |
-						  IR_TYPE_RC6 |
-						  IR_TYPE_NEC,
-				.change_protocol = dib0700_change_protocol,
-			},
+			.allowed_protos   = RC_TYPE_RC5 |
+					    RC_TYPE_RC6 |
+					    RC_TYPE_NEC,
+			.change_protocol = dib0700_change_protocol,
 		},
 	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
 
@@ -2308,12 +2311,10 @@ struct dvb_usb_device_properties dib0700
 			.rc_codes         = RC_MAP_DIB0700_NEC_TABLE,
 			.module_name	  = "dib0700",
 			.rc_query         = dib0700_rc_query_old_firmware,
-			.rc_props = {
-				.allowed_protos = IR_TYPE_RC5 |
-						  IR_TYPE_RC6 |
-						  IR_TYPE_NEC,
-				.change_protocol = dib0700_change_protocol,
-			},
+			.allowed_protos   = RC_TYPE_RC5 |
+					    RC_TYPE_RC6 |
+					    RC_TYPE_NEC,
+			.change_protocol  = dib0700_change_protocol,
 		},
 	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
 
@@ -2379,12 +2380,10 @@ struct dvb_usb_device_properties dib0700
 			.rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
 			.module_name	  = "dib0700",
 			.rc_query         = dib0700_rc_query_old_firmware,
-			.rc_props = {
-				.allowed_protos = IR_TYPE_RC5 |
-						  IR_TYPE_RC6 |
-						  IR_TYPE_NEC,
-				.change_protocol = dib0700_change_protocol,
-			},
+			.allowed_protos   = RC_TYPE_RC5 |
+					    RC_TYPE_RC6 |
+					    RC_TYPE_NEC,
+			.change_protocol  = dib0700_change_protocol,
 		},
 	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
 		.num_adapters = 1,
@@ -2417,12 +2416,10 @@ struct dvb_usb_device_properties dib0700
 			.rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
 			.module_name	  = "dib0700",
 			.rc_query         = dib0700_rc_query_old_firmware,
-			.rc_props = {
-				.allowed_protos = IR_TYPE_RC5 |
-						  IR_TYPE_RC6 |
-						  IR_TYPE_NEC,
-				.change_protocol = dib0700_change_protocol,
-			},
+			.allowed_protos   = RC_TYPE_RC5 |
+					    RC_TYPE_RC6 |
+					    RC_TYPE_NEC,
+			.change_protocol  = dib0700_change_protocol,
 		},
 	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
 		.num_adapters = 1,
@@ -2487,12 +2484,10 @@ struct dvb_usb_device_properties dib0700
 			.rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
 			.module_name	  = "dib0700",
 			.rc_query         = dib0700_rc_query_old_firmware,
-			.rc_props = {
-				.allowed_protos = IR_TYPE_RC5 |
-						  IR_TYPE_RC6 |
-						  IR_TYPE_NEC,
-				.change_protocol = dib0700_change_protocol,
-			},
+			.allowed_protos   = RC_TYPE_RC5 |
+					    RC_TYPE_RC6 |
+					    RC_TYPE_NEC,
+			.change_protocol  = dib0700_change_protocol,
 		},
 	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
 		.num_adapters = 1,
@@ -2533,12 +2528,10 @@ struct dvb_usb_device_properties dib0700
 			.rc_codes         = RC_MAP_DIB0700_NEC_TABLE,
 			.module_name	  = "dib0700",
 			.rc_query         = dib0700_rc_query_old_firmware,
-			.rc_props = {
-				.allowed_protos = IR_TYPE_RC5 |
-						  IR_TYPE_RC6 |
-						  IR_TYPE_NEC,
-				.change_protocol = dib0700_change_protocol,
-			},
+			.allowed_protos   = RC_TYPE_RC5 |
+					    RC_TYPE_RC6 |
+					    RC_TYPE_NEC,
+			.change_protocol  = dib0700_change_protocol,
 		},
 	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
 		.num_adapters = 2,
@@ -2584,12 +2577,10 @@ struct dvb_usb_device_properties dib0700
 			.rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
 			.module_name	  = "dib0700",
 			.rc_query         = dib0700_rc_query_old_firmware,
-			.rc_props = {
-				.allowed_protos = IR_TYPE_RC5 |
-						  IR_TYPE_RC6 |
-						  IR_TYPE_NEC,
-				.change_protocol = dib0700_change_protocol,
-			},
+			.allowed_protos   = RC_TYPE_RC5 |
+					    RC_TYPE_RC6 |
+					    RC_TYPE_NEC,
+			.change_protocol  = dib0700_change_protocol,
 		},
 	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
 		.num_adapters = 1,
@@ -2623,12 +2614,10 @@ struct dvb_usb_device_properties dib0700
 			.rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
 			.module_name	  = "dib0700",
 			.rc_query         = dib0700_rc_query_old_firmware,
-			.rc_props = {
-				.allowed_protos = IR_TYPE_RC5 |
-						  IR_TYPE_RC6 |
-						  IR_TYPE_NEC,
-				.change_protocol = dib0700_change_protocol,
-			},
+			.allowed_protos   = RC_TYPE_RC5 |
+					    RC_TYPE_RC6 |
+					    RC_TYPE_NEC,
+			.change_protocol  = dib0700_change_protocol,
 		},
 	},
 };
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/dvb/dvb-usb/dib0700.h linux-libre-2.6.38-gnu1/drivers/media/dvb/dvb-usb/dib0700.h
--- linux-libre-2.6.37-gnu1/drivers/media/dvb/dvb-usb/dib0700.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/dvb/dvb-usb/dib0700.h	2011-03-14 21:20:32.000000000 -0400
@@ -60,7 +60,7 @@ extern int dib0700_streaming_ctrl(struct
 extern struct i2c_algorithm dib0700_i2c_algo;
 extern int dib0700_identify_state(struct usb_device *udev, struct dvb_usb_device_properties *props,
 			struct dvb_usb_device_description **desc, int *cold);
-extern int dib0700_change_protocol(void *priv, u64 ir_type);
+extern int dib0700_change_protocol(struct rc_dev *dev, u64 rc_type);
 
 extern int dib0700_device_count;
 extern int dvb_usb_dib0700_ir_proto;
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/dvb/dvb-usb/dibusb-common.c linux-libre-2.6.38-gnu1/drivers/media/dvb/dvb-usb/dibusb-common.c
--- linux-libre-2.6.37-gnu1/drivers/media/dvb/dvb-usb/dibusb-common.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/dvb/dvb-usb/dibusb-common.c	2011-03-14 21:20:32.000000000 -0400
@@ -327,7 +327,7 @@ EXPORT_SYMBOL(dibusb_dib3000mc_tuner_att
 /*
  * common remote control stuff
  */
-struct ir_scancode ir_codes_dibusb_table[] = {
+struct rc_map_table rc_map_dibusb_table[] = {
 	/* Key codes for the little Artec T1/Twinhan/HAMA/ remote. */
 	{ 0x0016, KEY_POWER },
 	{ 0x0010, KEY_MUTE },
@@ -456,7 +456,7 @@ struct ir_scancode ir_codes_dibusb_table
 	{ 0x804e, KEY_ENTER },
 	{ 0x804f, KEY_VOLUMEDOWN },
 };
-EXPORT_SYMBOL(ir_codes_dibusb_table);
+EXPORT_SYMBOL(rc_map_dibusb_table);
 
 int dibusb_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
 {
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/dvb/dvb-usb/dibusb.h linux-libre-2.6.38-gnu1/drivers/media/dvb/dvb-usb/dibusb.h
--- linux-libre-2.6.37-gnu1/drivers/media/dvb/dvb-usb/dibusb.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/dvb/dvb-usb/dibusb.h	2011-03-14 21:20:32.000000000 -0400
@@ -124,7 +124,7 @@ extern int dibusb2_0_power_ctrl(struct d
 #define DEFAULT_RC_INTERVAL 150
 //#define DEFAULT_RC_INTERVAL 100000
 
-extern struct ir_scancode ir_codes_dibusb_table[];
+extern struct rc_map_table rc_map_dibusb_table[];
 extern int dibusb_rc_query(struct dvb_usb_device *, u32 *, int *);
 extern int dibusb_read_eeprom_byte(struct dvb_usb_device *, u8, u8 *);
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/dvb/dvb-usb/dibusb-mb.c linux-libre-2.6.38-gnu1/drivers/media/dvb/dvb-usb/dibusb-mb.c
--- linux-libre-2.6.37-gnu1/drivers/media/dvb/dvb-usb/dibusb-mb.c	2013-05-03 03:55:22.000000000 -0400
+++ linux-libre-2.6.38-gnu1/drivers/media/dvb/dvb-usb/dibusb-mb.c	2013-05-03 01:54:52.000000000 -0400
@@ -213,8 +213,8 @@ static struct dvb_usb_device_properties
 
 	.rc.legacy = {
 		.rc_interval      = DEFAULT_RC_INTERVAL,
-		.rc_key_map       = ir_codes_dibusb_table,
-		.rc_key_map_size  = 111, /* wow, that is ugly ... I want to load it to the driver dynamically */
+		.rc_map_table     = rc_map_dibusb_table,
+		.rc_map_size      = 111, /* wow, that is ugly ... I want to load it to the driver dynamically */
 		.rc_query         = dibusb_rc_query,
 	},
 
@@ -299,8 +299,8 @@ static struct dvb_usb_device_properties
 
 	.rc.legacy = {
 		.rc_interval      = DEFAULT_RC_INTERVAL,
-		.rc_key_map       = ir_codes_dibusb_table,
-		.rc_key_map_size  = 111, /* wow, that is ugly ... I want to load it to the driver dynamically */
+		.rc_map_table     = rc_map_dibusb_table,
+		.rc_map_size      = 111, /* wow, that is ugly ... I want to load it to the driver dynamically */
 		.rc_query         = dibusb_rc_query,
 	},
 
@@ -365,8 +365,8 @@ static struct dvb_usb_device_properties
 
 	.rc.legacy = {
 		.rc_interval      = DEFAULT_RC_INTERVAL,
-		.rc_key_map       = ir_codes_dibusb_table,
-		.rc_key_map_size  = 111, /* wow, that is ugly ... I want to load it to the driver dynamically */
+		.rc_map_table     = rc_map_dibusb_table,
+		.rc_map_size      = 111, /* wow, that is ugly ... I want to load it to the driver dynamically */
 		.rc_query         = dibusb_rc_query,
 	},
 
@@ -424,8 +424,8 @@ static struct dvb_usb_device_properties
 
 	.rc.legacy = {
 		.rc_interval      = DEFAULT_RC_INTERVAL,
-		.rc_key_map       = ir_codes_dibusb_table,
-		.rc_key_map_size  = 111, /* wow, that is ugly ... I want to load it to the driver dynamically */
+		.rc_map_table     = rc_map_dibusb_table,
+		.rc_map_size      = 111, /* wow, that is ugly ... I want to load it to the driver dynamically */
 		.rc_query         = dibusb_rc_query,
 	},
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/dvb/dvb-usb/dibusb-mc.c linux-libre-2.6.38-gnu1/drivers/media/dvb/dvb-usb/dibusb-mc.c
--- linux-libre-2.6.37-gnu1/drivers/media/dvb/dvb-usb/dibusb-mc.c	2013-05-03 03:55:24.000000000 -0400
+++ linux-libre-2.6.38-gnu1/drivers/media/dvb/dvb-usb/dibusb-mc.c	2013-05-03 01:54:54.000000000 -0400
@@ -83,8 +83,8 @@ static struct dvb_usb_device_properties
 
 	.rc.legacy = {
 		.rc_interval      = DEFAULT_RC_INTERVAL,
-		.rc_key_map       = ir_codes_dibusb_table,
-		.rc_key_map_size  = 111, /* FIXME */
+		.rc_map_table     = rc_map_dibusb_table,
+		.rc_map_size      = 111, /* FIXME */
 		.rc_query         = dibusb_rc_query,
 	},
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/dvb/dvb-usb/digitv.c linux-libre-2.6.38-gnu1/drivers/media/dvb/dvb-usb/digitv.c
--- linux-libre-2.6.37-gnu1/drivers/media/dvb/dvb-usb/digitv.c	2013-05-03 03:55:26.000000000 -0400
+++ linux-libre-2.6.38-gnu1/drivers/media/dvb/dvb-usb/digitv.c	2013-05-03 01:54:56.000000000 -0400
@@ -161,7 +161,7 @@ static int digitv_tuner_attach(struct dv
 	return 0;
 }
 
-static struct ir_scancode ir_codes_digitv_table[] = {
+static struct rc_map_table rc_map_digitv_table[] = {
 	{ 0x5f55, KEY_0 },
 	{ 0x6f55, KEY_1 },
 	{ 0x9f55, KEY_2 },
@@ -237,10 +237,10 @@ static int digitv_rc_query(struct dvb_us
 	/* if something is inside the buffer, simulate key press */
 	if (key[1] != 0)
 	{
-		  for (i = 0; i < d->props.rc.legacy.rc_key_map_size; i++) {
-			if (rc5_custom(&d->props.rc.legacy.rc_key_map[i]) == key[1] &&
-			    rc5_data(&d->props.rc.legacy.rc_key_map[i]) == key[2]) {
-				*event = d->props.rc.legacy.rc_key_map[i].keycode;
+		  for (i = 0; i < d->props.rc.legacy.rc_map_size; i++) {
+			if (rc5_custom(&d->props.rc.legacy.rc_map_table[i]) == key[1] &&
+			    rc5_data(&d->props.rc.legacy.rc_map_table[i]) == key[2]) {
+				*event = d->props.rc.legacy.rc_map_table[i].keycode;
 				*state = REMOTE_KEY_PRESSED;
 				return 0;
 			}
@@ -312,8 +312,8 @@ static struct dvb_usb_device_properties
 
 	.rc.legacy = {
 		.rc_interval      = 1000,
-		.rc_key_map       = ir_codes_digitv_table,
-		.rc_key_map_size  = ARRAY_SIZE(ir_codes_digitv_table),
+		.rc_map_table     = rc_map_digitv_table,
+		.rc_map_size      = ARRAY_SIZE(rc_map_digitv_table),
 		.rc_query         = digitv_rc_query,
 	},
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/dvb/dvb-usb/dtt200u.c linux-libre-2.6.38-gnu1/drivers/media/dvb/dvb-usb/dtt200u.c
--- linux-libre-2.6.37-gnu1/drivers/media/dvb/dvb-usb/dtt200u.c	2013-05-03 03:55:28.000000000 -0400
+++ linux-libre-2.6.38-gnu1/drivers/media/dvb/dvb-usb/dtt200u.c	2013-05-03 01:54:58.000000000 -0400
@@ -57,7 +57,7 @@ static int dtt200u_pid_filter(struct dvb
 
 /* remote control */
 /* key list for the tiny remote control (Yakumo, don't know about the others) */
-static struct ir_scancode ir_codes_dtt200u_table[] = {
+static struct rc_map_table rc_map_dtt200u_table[] = {
 	{ 0x8001, KEY_MUTE },
 	{ 0x8002, KEY_CHANNELDOWN },
 	{ 0x8003, KEY_VOLUMEDOWN },
@@ -163,8 +163,8 @@ static struct dvb_usb_device_properties
 
 	.rc.legacy = {
 		.rc_interval     = 300,
-		.rc_key_map      = ir_codes_dtt200u_table,
-		.rc_key_map_size = ARRAY_SIZE(ir_codes_dtt200u_table),
+		.rc_map_table    = rc_map_dtt200u_table,
+		.rc_map_size     = ARRAY_SIZE(rc_map_dtt200u_table),
 		.rc_query        = dtt200u_rc_query,
 	},
 
@@ -210,8 +210,8 @@ static struct dvb_usb_device_properties
 
 	.rc.legacy = {
 		.rc_interval     = 300,
-		.rc_key_map      = ir_codes_dtt200u_table,
-		.rc_key_map_size = ARRAY_SIZE(ir_codes_dtt200u_table),
+		.rc_map_table      = rc_map_dtt200u_table,
+		.rc_map_size = ARRAY_SIZE(rc_map_dtt200u_table),
 		.rc_query        = dtt200u_rc_query,
 	},
 
@@ -257,8 +257,8 @@ static struct dvb_usb_device_properties
 
 	.rc.legacy = {
 		.rc_interval     = 300,
-		.rc_key_map      = ir_codes_dtt200u_table,
-		.rc_key_map_size = ARRAY_SIZE(ir_codes_dtt200u_table),
+		.rc_map_table    = rc_map_dtt200u_table,
+		.rc_map_size     = ARRAY_SIZE(rc_map_dtt200u_table),
 		.rc_query        = dtt200u_rc_query,
 	},
 
@@ -304,8 +304,8 @@ static struct dvb_usb_device_properties
 
 	.rc.legacy = {
 		.rc_interval     = 300,
-		.rc_key_map      = ir_codes_dtt200u_table,
-		.rc_key_map_size = ARRAY_SIZE(ir_codes_dtt200u_table),
+		.rc_map_table    = rc_map_dtt200u_table,
+		.rc_map_size     = ARRAY_SIZE(rc_map_dtt200u_table),
 		.rc_query        = dtt200u_rc_query,
 	},
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/dvb/dvb-usb/dvb-usb.h linux-libre-2.6.38-gnu1/drivers/media/dvb/dvb-usb/dvb-usb.h
--- linux-libre-2.6.37-gnu1/drivers/media/dvb/dvb-usb/dvb-usb.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/dvb/dvb-usb/dvb-usb.h	2011-03-14 21:20:32.000000000 -0400
@@ -14,7 +14,7 @@
 #include <linux/usb.h>
 #include <linux/firmware.h>
 #include <linux/mutex.h>
-#include <media/ir-core.h>
+#include <media/rc-core.h>
 
 #include "dvb_frontend.h"
 #include "dvb_demux.h"
@@ -75,17 +75,17 @@ struct dvb_usb_device_description {
 	struct usb_device_id *warm_ids[DVB_USB_ID_MAX_NUM];
 };
 
-static inline u8 rc5_custom(struct ir_scancode *key)
+static inline u8 rc5_custom(struct rc_map_table *key)
 {
 	return (key->scancode >> 8) & 0xff;
 }
 
-static inline u8 rc5_data(struct ir_scancode *key)
+static inline u8 rc5_data(struct rc_map_table *key)
 {
 	return key->scancode & 0xff;
 }
 
-static inline u8 rc5_scan(struct ir_scancode *key)
+static inline u8 rc5_scan(struct rc_map_table *key)
 {
 	return key->scancode & 0xffff;
 }
@@ -159,9 +159,9 @@ struct dvb_usb_adapter_properties {
 
 /**
  * struct dvb_rc_legacy - old properties of remote controller
- * @rc_key_map: a hard-wired array of struct ir_scancode (NULL to disable
+ * @rc_map_table: a hard-wired array of struct rc_map_table (NULL to disable
  *  remote control handling).
- * @rc_key_map_size: number of items in @rc_key_map.
+ * @rc_map_size: number of items in @rc_map_table.
  * @rc_query: called to query an event event.
  * @rc_interval: time in ms between two queries.
  */
@@ -170,8 +170,8 @@ struct dvb_rc_legacy {
 #define REMOTE_NO_KEY_PRESSED      0x00
 #define REMOTE_KEY_PRESSED         0x01
 #define REMOTE_KEY_REPEAT          0x02
-	struct ir_scancode  *rc_key_map;
-	int rc_key_map_size;
+	struct rc_map_table  *rc_map_table;
+	int rc_map_size;
 	int (*rc_query) (struct dvb_usb_device *, u32 *, int *);
 	int rc_interval;
 };
@@ -180,18 +180,20 @@ struct dvb_rc_legacy {
  * struct dvb_rc properties of remote controller, using rc-core
  * @rc_codes: name of rc codes table
  * @protocol: type of protocol(s) currently used by the driver
+ * @allowed_protos: protocol(s) supported by the driver
+ * @change_protocol: callback to change protocol
  * @rc_query: called to query an event event.
  * @rc_interval: time in ms between two queries.
- * @rc_props: remote controller properties
  * @bulk_mode: device supports bulk mode for RC (disable polling mode)
  */
 struct dvb_rc {
 	char *rc_codes;
 	u64 protocol;
+	u64 allowed_protos;
+	int (*change_protocol)(struct rc_dev *dev, u64 rc_type);
 	char *module_name;
 	int (*rc_query) (struct dvb_usb_device *d);
 	int rc_interval;
-	struct ir_dev_props rc_props;
 	bool bulk_mode;				/* uses bulk mode */
 };
 
@@ -385,7 +387,8 @@ struct dvb_usb_adapter {
  *
  * @i2c_adap: device's i2c_adapter if it uses I2CoverUSB
  *
- * @rc_input_dev: input device for the remote control.
+ * @rc_dev: rc device for the remote control (rc-core mode)
+ * @input_dev: input device for the remote control (legacy mode)
  * @rc_query_work: struct work_struct frequent rc queries
  * @last_event: last triggered event
  * @last_state: last state (no, pressed, repeat)
@@ -418,7 +421,8 @@ struct dvb_usb_device {
 	struct dvb_usb_adapter adapter[MAX_NO_OF_ADAPTER_PER_DEVICE];
 
 	/* remote control */
-	struct input_dev *rc_input_dev;
+	struct rc_dev *rc_dev;
+	struct input_dev *input_dev;
 	char rc_phys[64];
 	struct delayed_work rc_query_work;
 	u32 last_event;
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/dvb/dvb-usb/dvb-usb-ids.h linux-libre-2.6.38-gnu1/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
--- linux-libre-2.6.37-gnu1/drivers/media/dvb/dvb-usb/dvb-usb-ids.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/dvb/dvb-usb/dvb-usb-ids.h	2011-03-14 21:20:32.000000000 -0400
@@ -301,6 +301,7 @@
 #define USB_PID_ELGATO_EYETV_DIVERSITY			0x0011
 #define USB_PID_ELGATO_EYETV_DTT			0x0021
 #define USB_PID_ELGATO_EYETV_DTT_Dlx			0x0020
+#define USB_PID_ELGATO_EYETV_SAT			0x002a
 #define USB_PID_DVB_T_USB_STICK_HIGH_SPEED_COLD		0x5000
 #define USB_PID_DVB_T_USB_STICK_HIGH_SPEED_WARM		0x5001
 #define USB_PID_FRIIO_WHITE				0x0001
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/dvb/dvb-usb/dvb-usb-remote.c linux-libre-2.6.38-gnu1/drivers/media/dvb/dvb-usb/dvb-usb-remote.c
--- linux-libre-2.6.37-gnu1/drivers/media/dvb/dvb-usb/dvb-usb-remote.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/dvb/dvb-usb/dvb-usb-remote.c	2011-03-14 21:20:32.000000000 -0400
@@ -13,11 +13,11 @@ static int legacy_dvb_usb_getkeycode(str
 {
 	struct dvb_usb_device *d = input_get_drvdata(dev);
 
-	struct ir_scancode *keymap = d->props.rc.legacy.rc_key_map;
+	struct rc_map_table *keymap = d->props.rc.legacy.rc_map_table;
 	int i;
 
 	/* See if we can match the raw key code. */
-	for (i = 0; i < d->props.rc.legacy.rc_key_map_size; i++)
+	for (i = 0; i < d->props.rc.legacy.rc_map_size; i++)
 		if (keymap[i].scancode == scancode) {
 			*keycode = keymap[i].keycode;
 			return 0;
@@ -28,7 +28,7 @@ static int legacy_dvb_usb_getkeycode(str
 	 * otherwise, input core won't let legacy_dvb_usb_setkeycode
 	 * to work
 	 */
-	for (i = 0; i < d->props.rc.legacy.rc_key_map_size; i++)
+	for (i = 0; i < d->props.rc.legacy.rc_map_size; i++)
 		if (keymap[i].keycode == KEY_RESERVED ||
 		    keymap[i].keycode == KEY_UNKNOWN) {
 			*keycode = KEY_RESERVED;
@@ -43,18 +43,18 @@ static int legacy_dvb_usb_setkeycode(str
 {
 	struct dvb_usb_device *d = input_get_drvdata(dev);
 
-	struct ir_scancode *keymap = d->props.rc.legacy.rc_key_map;
+	struct rc_map_table *keymap = d->props.rc.legacy.rc_map_table;
 	int i;
 
 	/* Search if it is replacing an existing keycode */
-	for (i = 0; i < d->props.rc.legacy.rc_key_map_size; i++)
+	for (i = 0; i < d->props.rc.legacy.rc_map_size; i++)
 		if (keymap[i].scancode == scancode) {
 			keymap[i].keycode = keycode;
 			return 0;
 		}
 
 	/* Search if is there a clean entry. If so, use it */
-	for (i = 0; i < d->props.rc.legacy.rc_key_map_size; i++)
+	for (i = 0; i < d->props.rc.legacy.rc_map_size; i++)
 		if (keymap[i].keycode == KEY_RESERVED ||
 		    keymap[i].keycode == KEY_UNKNOWN) {
 			keymap[i].scancode = scancode;
@@ -106,10 +106,10 @@ static void legacy_dvb_usb_read_remote_c
 			d->last_event = event;
 		case REMOTE_KEY_REPEAT:
 			deb_rc("key repeated\n");
-			input_event(d->rc_input_dev, EV_KEY, event, 1);
-			input_sync(d->rc_input_dev);
-			input_event(d->rc_input_dev, EV_KEY, d->last_event, 0);
-			input_sync(d->rc_input_dev);
+			input_event(d->input_dev, EV_KEY, event, 1);
+			input_sync(d->input_dev);
+			input_event(d->input_dev, EV_KEY, d->last_event, 0);
+			input_sync(d->input_dev);
 			break;
 		default:
 			break;
@@ -154,20 +154,32 @@ schedule:
 	schedule_delayed_work(&d->rc_query_work,msecs_to_jiffies(d->props.rc.legacy.rc_interval));
 }
 
-static int legacy_dvb_usb_remote_init(struct dvb_usb_device *d,
-				      struct input_dev *input_dev)
+static int legacy_dvb_usb_remote_init(struct dvb_usb_device *d)
 {
 	int i, err, rc_interval;
+	struct input_dev *input_dev;
+
+	input_dev = input_allocate_device();
+	if (!input_dev)
+		return -ENOMEM;
+
+	input_dev->evbit[0] = BIT_MASK(EV_KEY);
+	input_dev->name = "IR-receiver inside an USB DVB receiver";
+	input_dev->phys = d->rc_phys;
+	usb_to_input_id(d->udev, &input_dev->id);
+	input_dev->dev.parent = &d->udev->dev;
+	d->input_dev = input_dev;
+	d->rc_dev = NULL;
 
 	input_dev->getkeycode = legacy_dvb_usb_getkeycode;
 	input_dev->setkeycode = legacy_dvb_usb_setkeycode;
 
 	/* set the bits for the keys */
-	deb_rc("key map size: %d\n", d->props.rc.legacy.rc_key_map_size);
-	for (i = 0; i < d->props.rc.legacy.rc_key_map_size; i++) {
+	deb_rc("key map size: %d\n", d->props.rc.legacy.rc_map_size);
+	for (i = 0; i < d->props.rc.legacy.rc_map_size; i++) {
 		deb_rc("setting bit for event %d item %d\n",
-			d->props.rc.legacy.rc_key_map[i].keycode, i);
-		set_bit(d->props.rc.legacy.rc_key_map[i].keycode, input_dev->keybit);
+			d->props.rc.legacy.rc_map_table[i].keycode, i);
+		set_bit(d->props.rc.legacy.rc_map_table[i].keycode, input_dev->keybit);
 	}
 
 	/* setting these two values to non-zero, we have to manage key repeats */
@@ -221,18 +233,34 @@ static void dvb_usb_read_remote_control(
 			      msecs_to_jiffies(d->props.rc.core.rc_interval));
 }
 
-static int rc_core_dvb_usb_remote_init(struct dvb_usb_device *d,
-				       struct input_dev *input_dev)
+static int rc_core_dvb_usb_remote_init(struct dvb_usb_device *d)
 {
 	int err, rc_interval;
+	struct rc_dev *dev;
 
-	d->props.rc.core.rc_props.priv = d;
-	err = ir_input_register(input_dev,
-				 d->props.rc.core.rc_codes,
-				 &d->props.rc.core.rc_props,
-				 d->props.rc.core.module_name);
-	if (err < 0)
+	dev = rc_allocate_device();
+	if (!dev)
+		return -ENOMEM;
+
+	dev->driver_name = d->props.rc.core.module_name;
+	dev->map_name = d->props.rc.core.rc_codes;
+	dev->change_protocol = d->props.rc.core.change_protocol;
+	dev->allowed_protos = d->props.rc.core.allowed_protos;
+	dev->driver_type = RC_DRIVER_SCANCODE;
+	usb_to_input_id(d->udev, &dev->input_id);
+	dev->input_name = "IR-receiver inside an USB DVB receiver";
+	dev->input_phys = d->rc_phys;
+	dev->dev.parent = &d->udev->dev;
+	dev->priv = d;
+
+	err = rc_register_device(dev);
+	if (err < 0) {
+		rc_free_device(dev);
 		return err;
+	}
+
+	d->input_dev = NULL;
+	d->rc_dev = dev;
 
 	if (!d->props.rc.core.rc_query || d->props.rc.core.bulk_mode)
 		return 0;
@@ -251,13 +279,12 @@ static int rc_core_dvb_usb_remote_init(s
 
 int dvb_usb_remote_init(struct dvb_usb_device *d)
 {
-	struct input_dev *input_dev;
 	int err;
 
 	if (dvb_usb_disable_rc_polling)
 		return 0;
 
-	if (d->props.rc.legacy.rc_key_map && d->props.rc.legacy.rc_query)
+	if (d->props.rc.legacy.rc_map_table && d->props.rc.legacy.rc_query)
 		d->props.rc.mode = DVB_RC_LEGACY;
 	else if (d->props.rc.core.rc_codes)
 		d->props.rc.mode = DVB_RC_CORE;
@@ -267,26 +294,14 @@ int dvb_usb_remote_init(struct dvb_usb_d
 	usb_make_path(d->udev, d->rc_phys, sizeof(d->rc_phys));
 	strlcat(d->rc_phys, "/ir0", sizeof(d->rc_phys));
 
-	input_dev = input_allocate_device();
-	if (!input_dev)
-		return -ENOMEM;
-
-	input_dev->evbit[0] = BIT_MASK(EV_KEY);
-	input_dev->name = "IR-receiver inside an USB DVB receiver";
-	input_dev->phys = d->rc_phys;
-	usb_to_input_id(d->udev, &input_dev->id);
-	input_dev->dev.parent = &d->udev->dev;
-
 	/* Start the remote-control polling. */
 	if (d->props.rc.legacy.rc_interval < 40)
 		d->props.rc.legacy.rc_interval = 100; /* default */
 
-	d->rc_input_dev = input_dev;
-
 	if (d->props.rc.mode == DVB_RC_LEGACY)
-		err = legacy_dvb_usb_remote_init(d, input_dev);
+		err = legacy_dvb_usb_remote_init(d);
 	else
-		err = rc_core_dvb_usb_remote_init(d, input_dev);
+		err = rc_core_dvb_usb_remote_init(d);
 	if (err)
 		return err;
 
@@ -298,12 +313,11 @@ int dvb_usb_remote_init(struct dvb_usb_d
 int dvb_usb_remote_exit(struct dvb_usb_device *d)
 {
 	if (d->state & DVB_USB_STATE_REMOTE) {
-		cancel_rearming_delayed_work(&d->rc_query_work);
-		flush_scheduled_work();
+		cancel_delayed_work_sync(&d->rc_query_work);
 		if (d->props.rc.mode == DVB_RC_LEGACY)
-			input_unregister_device(d->rc_input_dev);
+			input_unregister_device(d->input_dev);
 		else
-			ir_input_unregister(d->rc_input_dev);
+			rc_unregister_device(d->rc_dev);
 	}
 	d->state &= ~DVB_USB_STATE_REMOTE;
 	return 0;
@@ -316,7 +330,7 @@ int dvb_usb_nec_rc_key_to_event(struct d
 		u8 keybuf[5], u32 *event, int *state)
 {
 	int i;
-	struct ir_scancode *keymap = d->props.rc.legacy.rc_key_map;
+	struct rc_map_table *keymap = d->props.rc.legacy.rc_map_table;
 	*event = 0;
 	*state = REMOTE_NO_KEY_PRESSED;
 	switch (keybuf[0]) {
@@ -329,7 +343,7 @@ int dvb_usb_nec_rc_key_to_event(struct d
 				break;
 			}
 			/* See if we can match the raw key code. */
-			for (i = 0; i < d->props.rc.legacy.rc_key_map_size; i++)
+			for (i = 0; i < d->props.rc.legacy.rc_map_size; i++)
 				if (rc5_custom(&keymap[i]) == keybuf[1] &&
 					rc5_data(&keymap[i]) == keybuf[3]) {
 					*event = keymap[i].keycode;
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/dvb/dvb-usb/dw2102.c linux-libre-2.6.38-gnu1/drivers/media/dvb/dvb-usb/dw2102.c
--- linux-libre-2.6.37-gnu1/drivers/media/dvb/dvb-usb/dw2102.c	2013-05-03 03:55:31.000000000 -0400
+++ linux-libre-2.6.38-gnu1/drivers/media/dvb/dvb-usb/dw2102.c	2013-05-03 01:55:00.000000000 -0400
@@ -73,8 +73,8 @@
 		"Please see linux/Documentation/dvb/ for more details " \
 		"on firmware-problems."
 
-struct ir_codes_dvb_usb_table_table {
-	struct ir_scancode *rc_keys;
+struct rc_map_dvb_usb_table_table {
+	struct rc_map_table *rc_keys;
 	int rc_keys_size;
 };
 
@@ -948,7 +948,7 @@ static int dw3101_tuner_attach(struct dv
 	return 0;
 }
 
-static struct ir_scancode ir_codes_dw210x_table[] = {
+static struct rc_map_table rc_map_dw210x_table[] = {
 	{ 0xf80a, KEY_Q },		/*power*/
 	{ 0xf80c, KEY_M },		/*mute*/
 	{ 0xf811, KEY_1 },
@@ -982,7 +982,7 @@ static struct ir_scancode ir_codes_dw210
 	{ 0xf81b, KEY_B },		/*recall*/
 };
 
-static struct ir_scancode ir_codes_tevii_table[] = {
+static struct rc_map_table rc_map_tevii_table[] = {
 	{ 0xf80a, KEY_POWER },
 	{ 0xf80c, KEY_MUTE },
 	{ 0xf811, KEY_1 },
@@ -1032,7 +1032,7 @@ static struct ir_scancode ir_codes_tevii
 	{ 0xf858, KEY_SWITCHVIDEOMODE },
 };
 
-static struct ir_scancode ir_codes_tbs_table[] = {
+static struct rc_map_table rc_map_tbs_table[] = {
 	{ 0xf884, KEY_POWER },
 	{ 0xf894, KEY_MUTE },
 	{ 0xf887, KEY_1 },
@@ -1067,16 +1067,16 @@ static struct ir_scancode ir_codes_tbs_t
 	{ 0xf89b, KEY_MODE }
 };
 
-static struct ir_codes_dvb_usb_table_table keys_tables[] = {
-	{ ir_codes_dw210x_table, ARRAY_SIZE(ir_codes_dw210x_table) },
-	{ ir_codes_tevii_table, ARRAY_SIZE(ir_codes_tevii_table) },
-	{ ir_codes_tbs_table, ARRAY_SIZE(ir_codes_tbs_table) },
+static struct rc_map_dvb_usb_table_table keys_tables[] = {
+	{ rc_map_dw210x_table, ARRAY_SIZE(rc_map_dw210x_table) },
+	{ rc_map_tevii_table, ARRAY_SIZE(rc_map_tevii_table) },
+	{ rc_map_tbs_table, ARRAY_SIZE(rc_map_tbs_table) },
 };
 
 static int dw2102_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
 {
-	struct ir_scancode *keymap = d->props.rc.legacy.rc_key_map;
-	int keymap_size = d->props.rc.legacy.rc_key_map_size;
+	struct rc_map_table *keymap = d->props.rc.legacy.rc_map_table;
+	int keymap_size = d->props.rc.legacy.rc_map_size;
 	u8 key[2];
 	struct i2c_msg msg = {
 		.addr = DW2102_RC_QUERY,
@@ -1185,14 +1185,14 @@ static int dw2102_load_firmware(struct u
 		/* init registers */
 		switch (dev->descriptor.idProduct) {
 		case USB_PID_PROF_1100:
-			s6x0_properties.rc.legacy.rc_key_map = ir_codes_tbs_table;
-			s6x0_properties.rc.legacy.rc_key_map_size =
-					ARRAY_SIZE(ir_codes_tbs_table);
+			s6x0_properties.rc.legacy.rc_map_table = rc_map_tbs_table;
+			s6x0_properties.rc.legacy.rc_map_size =
+					ARRAY_SIZE(rc_map_tbs_table);
 			break;
 		case USB_PID_TEVII_S650:
-			dw2104_properties.rc.legacy.rc_key_map = ir_codes_tevii_table;
-			dw2104_properties.rc.legacy.rc_key_map_size =
-					ARRAY_SIZE(ir_codes_tevii_table);
+			dw2104_properties.rc.legacy.rc_map_table = rc_map_tevii_table;
+			dw2104_properties.rc.legacy.rc_map_size =
+					ARRAY_SIZE(rc_map_tevii_table);
 		case USB_PID_DW2104:
 			reset = 1;
 			dw210x_op_rw(dev, 0xc4, 0x0000, 0, &reset, 1,
@@ -1257,8 +1257,8 @@ static struct dvb_usb_device_properties
 	.i2c_algo = &dw2102_serit_i2c_algo,
 
 	.rc.legacy = {
-		.rc_key_map = ir_codes_dw210x_table,
-		.rc_key_map_size = ARRAY_SIZE(ir_codes_dw210x_table),
+		.rc_map_table = rc_map_dw210x_table,
+		.rc_map_size = ARRAY_SIZE(rc_map_dw210x_table),
 		.rc_interval = 150,
 		.rc_query = dw2102_rc_query,
 	},
@@ -1310,8 +1310,8 @@ static struct dvb_usb_device_properties
 
 	.i2c_algo = &dw2104_i2c_algo,
 	.rc.legacy = {
-		.rc_key_map = ir_codes_dw210x_table,
-		.rc_key_map_size = ARRAY_SIZE(ir_codes_dw210x_table),
+		.rc_map_table = rc_map_dw210x_table,
+		.rc_map_size = ARRAY_SIZE(rc_map_dw210x_table),
 		.rc_interval = 150,
 		.rc_query = dw2102_rc_query,
 	},
@@ -1359,8 +1359,8 @@ static struct dvb_usb_device_properties
 
 	.i2c_algo = &dw3101_i2c_algo,
 	.rc.legacy = {
-		.rc_key_map = ir_codes_dw210x_table,
-		.rc_key_map_size = ARRAY_SIZE(ir_codes_dw210x_table),
+		.rc_map_table = rc_map_dw210x_table,
+		.rc_map_size = ARRAY_SIZE(rc_map_dw210x_table),
 		.rc_interval = 150,
 		.rc_query = dw2102_rc_query,
 	},
@@ -1404,8 +1404,8 @@ static struct dvb_usb_device_properties
 
 	.i2c_algo = &s6x0_i2c_algo,
 	.rc.legacy = {
-		.rc_key_map = ir_codes_tevii_table,
-		.rc_key_map_size = ARRAY_SIZE(ir_codes_tevii_table),
+		.rc_map_table = rc_map_tevii_table,
+		.rc_map_size = ARRAY_SIZE(rc_map_tevii_table),
 		.rc_interval = 150,
 		.rc_query = dw2102_rc_query,
 	},
@@ -1468,8 +1468,8 @@ static int dw2102_probe(struct usb_inter
 	/* fill only different fields */
 	p7500->firmware = "/*(DEBLOBBED)*/";
 	p7500->devices[0] = d7500;
-	p7500->rc.legacy.rc_key_map = ir_codes_tbs_table;
-	p7500->rc.legacy.rc_key_map_size = ARRAY_SIZE(ir_codes_tbs_table);
+	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;
 
 	if (0 == dvb_usb_device_init(intf, &dw2102_properties,
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/dvb/dvb-usb/gp8psk.c linux-libre-2.6.38-gnu1/drivers/media/dvb/dvb-usb/gp8psk.c
--- linux-libre-2.6.37-gnu1/drivers/media/dvb/dvb-usb/gp8psk.c	2013-05-03 03:55:36.000000000 -0400
+++ linux-libre-2.6.38-gnu1/drivers/media/dvb/dvb-usb/gp8psk.c	2013-05-03 01:55:07.000000000 -0400
@@ -24,6 +24,33 @@ MODULE_PARM_DESC(debug, "set debugging l
 
 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
 
+static int gp8psk_get_fw_version(struct dvb_usb_device *d, u8 *fw_vers)
+{
+	return (gp8psk_usb_in_op(d, GET_FW_VERS, 0, 0, fw_vers, 6));
+}
+
+static int gp8psk_get_fpga_version(struct dvb_usb_device *d, u8 *fpga_vers)
+{
+	return (gp8psk_usb_in_op(d, GET_FPGA_VERS, 0, 0, fpga_vers, 1));
+}
+
+static void gp8psk_info(struct dvb_usb_device *d)
+{
+	u8 fpga_vers, fw_vers[6];
+
+	if (!gp8psk_get_fw_version(d, fw_vers))
+		info("FW Version = %i.%02i.%i (0x%x)  Build %4i/%02i/%02i",
+		fw_vers[2], fw_vers[1], fw_vers[0], GP8PSK_FW_VERS(fw_vers),
+		2000 + fw_vers[5], fw_vers[4], fw_vers[3]);
+	else
+		info("failed to get FW version");
+
+	if (!gp8psk_get_fpga_version(d, &fpga_vers))
+		info("FPGA Version = %i", fpga_vers);
+	else
+		info("failed to get FPGA version");
+}
+
 int gp8psk_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen)
 {
 	int ret = 0,try = 0;
@@ -146,6 +173,7 @@ static int gp8psk_power_ctrl(struct dvb_
 				gp8psk_usb_out_op(d, CW3K_INIT, 1, 0, NULL, 0);
 			if (gp8psk_usb_in_op(d, BOOT_8PSK, 1, 0, &buf, 1))
 				return -EINVAL;
+			gp8psk_info(d);
 		}
 
 		if (gp_product_id == USB_PID_GENPIX_8PSK_REV_1_WARM)
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/dvb/dvb-usb/gp8psk.h linux-libre-2.6.38-gnu1/drivers/media/dvb/dvb-usb/gp8psk.h
--- linux-libre-2.6.37-gnu1/drivers/media/dvb/dvb-usb/gp8psk.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/dvb/dvb-usb/gp8psk.h	2011-03-14 21:20:32.000000000 -0400
@@ -25,7 +25,6 @@ extern int dvb_usb_gp8psk_debug;
 #define deb_xfer(args...) dprintk(dvb_usb_gp8psk_debug,0x02,args)
 #define deb_rc(args...)   dprintk(dvb_usb_gp8psk_debug,0x04,args)
 #define deb_fe(args...)   dprintk(dvb_usb_gp8psk_debug,0x08,args)
-/* gp8psk commands */
 
 /* Twinhan Vendor requests */
 #define TH_COMMAND_IN                     0xC0
@@ -49,8 +48,10 @@ extern int dvb_usb_gp8psk_debug;
 #define SET_DVB_MODE                    0x8E
 #define SET_DN_SWITCH                   0x8F
 #define GET_SIGNAL_LOCK                 0x90    /* in */
+#define GET_FW_VERS			0x92
 #define GET_SERIAL_NUMBER               0x93    /* in */
 #define USE_EXTRA_VOLT                  0x94
+#define GET_FPGA_VERS			0x95
 #define CW3K_INIT			0x9d
 
 /* PSK_configuration bits */
@@ -88,6 +89,11 @@ extern int dvb_usb_gp8psk_debug;
 #define PRODUCT_STRING_READ               0x0D
 #define FW_BCD_VERSION_READ               0x14
 
+/* firmware revision id's */
+#define GP8PSK_FW_REV1			0x020604
+#define GP8PSK_FW_REV2			0x020704
+#define GP8PSK_FW_VERS(_fw_vers)	((_fw_vers)[2]<<0x10 | (_fw_vers)[1]<<0x08 | (_fw_vers)[0])
+
 extern struct dvb_frontend * gp8psk_fe_attach(struct dvb_usb_device *d);
 extern int gp8psk_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen);
 extern int gp8psk_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value,
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/dvb/dvb-usb/Kconfig linux-libre-2.6.38-gnu1/drivers/media/dvb/dvb-usb/Kconfig
--- linux-libre-2.6.37-gnu1/drivers/media/dvb/dvb-usb/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/dvb/dvb-usb/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -1,6 +1,6 @@
 config DVB_USB
 	tristate "Support for various USB DVB devices"
-	depends on DVB_CORE && USB && I2C && IR_CORE
+	depends on DVB_CORE && USB && I2C && RC_CORE
 	help
 	  By enabling this you will be able to choose the various supported
 	  USB1.1 and USB2.0 DVB devices.
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/dvb/dvb-usb/lmedm04.c linux-libre-2.6.38-gnu1/drivers/media/dvb/dvb-usb/lmedm04.c
--- linux-libre-2.6.37-gnu1/drivers/media/dvb/dvb-usb/lmedm04.c	2013-05-03 03:55:38.000000000 -0400
+++ linux-libre-2.6.38-gnu1/drivers/media/dvb/dvb-usb/lmedm04.c	2013-05-03 01:55:11.000000000 -0400
@@ -61,7 +61,7 @@
 #define DVB_USB_LOG_PREFIX "LME2510(C)"
 #include <linux/usb.h>
 #include <linux/usb/input.h>
-#include <media/ir-core.h>
+#include <media/rc-core.h>
 
 #include "dvb-usb.h"
 #include "lmedm04.h"
@@ -112,7 +112,6 @@ struct lme2510_state {
 	u8 i2c_tuner_gate_r;
 	u8 i2c_tuner_addr;
 	u8 stream_on;
-	u8 one_tune;
 	void *buffer;
 	struct urb *lme_urb;
 	void *usb_buffer;
@@ -125,7 +124,7 @@ static int lme2510_bulk_write(struct usb
 	int ret, actual_l;
 
 	ret = usb_bulk_msg(dev, usb_sndbulkpipe(dev, pipe),
-				snd, len , &actual_l, 500);
+				snd, len , &actual_l, 100);
 	return ret;
 }
 
@@ -135,7 +134,7 @@ static int lme2510_bulk_read(struct usb_
 	int ret, actual_l;
 
 	ret = usb_bulk_msg(dev, usb_rcvbulkpipe(dev, pipe),
-				 rev, len , &actual_l, 500);
+				 rev, len , &actual_l, 200);
 	return ret;
 }
 
@@ -167,7 +166,7 @@ static int lme2510_usb_talk(struct dvb_u
 
 	ret |= lme2510_bulk_write(d->udev, buff, wlen , 0x01);
 
-	msleep(12);
+	msleep(10);
 
 	ret |= usb_clear_halt(d->udev, usb_rcvbulkpipe(d->udev, 0x01));
 
@@ -182,15 +181,13 @@ static int lme2510_usb_talk(struct dvb_u
 	return (ret < 0) ? -ENODEV : 0;
 }
 
-static int lme2510_usb_talk_restart(struct dvb_usb_device *d,
-		u8 *wbuf, int wlen, u8 *rbuf, int rlen) {
+static int lme2510_stream_restart(struct dvb_usb_device *d)
+{
 	static u8 stream_on[] = LME_ST_ON_W;
 	int ret;
 	u8 rbuff[10];
-	/*Send Normal Command*/
-	ret = lme2510_usb_talk(d, wbuf, wlen, rbuf, rlen);
 	/*Restart Stream Command*/
-	ret |= lme2510_usb_talk(d, stream_on, sizeof(stream_on),
+	ret = lme2510_usb_talk(d, stream_on, sizeof(stream_on),
 			rbuff, sizeof(rbuff));
 	return ret;
 }
@@ -201,7 +198,7 @@ static int lme2510_remote_keypress(struc
 	deb_info(1, "INT Key Keypress =%04x", keypress);
 
 	if (keypress > 0)
-		ir_keydown(d->rc_input_dev, keypress, 0);
+		rc_keydown(d->rc_dev, keypress, 0);
 
 	return 0;
 }
@@ -254,11 +251,16 @@ static void lme2510_int_response(struct
 			case TUNER_S7395:
 				/* Tweak for earlier firmware*/
 				if (ibuf[1] == 0x03) {
+					if (ibuf[2] > 1)
+						st->signal_lock = ibuf[2];
 					st->signal_level = ibuf[3];
 					st->signal_sn = ibuf[4];
 				} else {
 					st->signal_level = ibuf[4];
 					st->signal_sn = ibuf[5];
+					st->signal_lock =
+						(st->signal_lock & 0xf7) +
+						((ibuf[2] & 0x01) << 0x03);
 				}
 				break;
 			default:
@@ -341,11 +343,10 @@ static int lme2510_msg(struct dvb_usb_de
 					st->signal_lock = rbuf[1];
 					if ((st->stream_on & 1) &&
 						(st->signal_lock & 0x10)) {
-						lme2510_usb_talk_restart(d,
-							wbuf, wlen, rbuf, rlen);
+						lme2510_stream_restart(d);
 						st->i2c_talk_onoff = 0;
 					}
-				msleep(80);
+					msleep(80);
 				}
 			}
 			break;
@@ -355,15 +356,12 @@ static int lme2510_msg(struct dvb_usb_de
 					st->signal_lock = rbuf[1];
 					if ((st->stream_on & 1) &&
 						(st->signal_lock & 0x8)) {
-						lme2510_usb_talk_restart(d,
-							wbuf, wlen, rbuf, rlen);
+						lme2510_stream_restart(d);
 						st->i2c_talk_onoff = 0;
 					}
 				}
 				if ((wbuf[3] != 0x6) & (wbuf[3] != 0x5))
 					msleep(5);
-
-
 			}
 			break;
 		default:
@@ -385,18 +383,16 @@ static int lme2510_msg(struct dvb_usb_de
 				rbuf[0] = 0x55;
 				rbuf[1] = st->signal_sn;
 				break;
-			/*DiSEqC functions as per TDA10086*/
-			case 0x36:
-			case 0x48:
-			case 0x49:
-			case 0x4a:
-			case 0x4b:
-			case 0x4c:
-			case 0x4d:
-			if (wbuf[2] == 0x1c)
-					lme2510_usb_talk_restart(d,
-						wbuf, wlen, rbuf, rlen);
+			case 0x15:
+			case 0x16:
+			case 0x17:
+			case 0x18:
+				rbuf[0] = 0x55;
+				rbuf[1] = 0x00;
+				break;
 			default:
+				lme2510_usb_talk(d, wbuf, wlen, rbuf, rlen);
+				st->i2c_talk_onoff = 1;
 				break;
 			}
 			break;
@@ -413,39 +409,22 @@ static int lme2510_msg(struct dvb_usb_de
 				break;
 			case 0x24:
 				rbuf[0] = 0x55;
-				rbuf[1] = (st->signal_level & 0x80)
-						? 0 : st->signal_lock;
-				break;
-			case 0x6:
-				if (wbuf[2] == 0xd0)
-					lme2510_usb_talk(d,
-						wbuf, wlen, rbuf, rlen);
-				break;
-			case 0x1:
-				if (st->one_tune > 0)
-					break;
-				st->one_tune++;
-				st->i2c_talk_onoff = 1;
-			/*DiSEqC functions as per STV0288*/
-			case 0x5:
-			case 0x7:
-			case 0x8:
-			case 0x9:
-			case 0xa:
-			case 0xb:
-				if (wbuf[2] == 0xd0)
-					lme2510_usb_talk_restart(d,
-						wbuf, wlen, rbuf, rlen);
+				rbuf[1] = st->signal_lock;
 				break;
-			default:
+			case 0x2e:
+			case 0x26:
+			case 0x27:
 				rbuf[0] = 0x55;
 				rbuf[1] = 0x00;
 				break;
+			default:
+				lme2510_usb_talk(d, wbuf, wlen, rbuf, rlen);
+				st->i2c_talk_onoff = 1;
+				break;
 			}
 			break;
 		default:
 			break;
-
 		}
 
 		deb_info(4, "I2C From Interupt Message out(%02x) in(%02x)",
@@ -548,35 +527,26 @@ static int lme2510_identify_state(struct
 static int lme2510_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
 {
 	struct lme2510_state *st = adap->dev->priv;
-	static u8 stream_on[] = LME_ST_ON_W;
 	static u8 clear_reg_3[] =  LME_CLEAR_PID;
 	static u8 rbuf[1];
-	static u8 timeout;
-	int ret = 0, len = 2, rlen = sizeof(rbuf);
+	int ret = 0, rlen = sizeof(rbuf);
 
 	deb_info(1, "STM  (%02x)", onoff);
 
-	if (onoff == 1)	{
-		st->i2c_talk_onoff = 0;
-		timeout = 0;
-		/* wait for i2C to be free */
-		while (mutex_lock_interruptible(&adap->dev->i2c_mutex) < 0) {
-			timeout++;
-			if (timeout > 5)
-				return -ENODEV;
-		}
-		msleep(100);
-		ret |= lme2510_usb_talk(adap->dev,
-				 stream_on,  len, rbuf, rlen);
+	/* Streaming is started by FE_HAS_LOCK */
+	if (onoff == 1)
 		st->stream_on = 1;
-		st->one_tune = 0;
-		mutex_unlock(&adap->dev->i2c_mutex);
-	} else {
+	else {
 		deb_info(1, "STM Steam Off");
+		/* mutex is here only to avoid collision with I2C */
+		ret = mutex_lock_interruptible(&adap->dev->i2c_mutex);
+
 		ret |= lme2510_usb_talk(adap->dev, clear_reg_3,
 				sizeof(clear_reg_3), rbuf, rlen);
 		st->stream_on = 0;
 		st->i2c_talk_onoff = 1;
+
+		mutex_unlock(&adap->dev->i2c_mutex);
 	}
 
 	return (ret < 0) ? -ENODEV : 0;
@@ -585,41 +555,40 @@ static int lme2510_streaming_ctrl(struct
 static int lme2510_int_service(struct dvb_usb_adapter *adap)
 {
 	struct dvb_usb_device *d = adap->dev;
-	struct input_dev *input_dev;
-	char *ir_codes = RC_MAP_LME2510;
-	int ret = 0;
+	struct rc_dev *rc;
+	int ret;
 
 	info("STA Configuring Remote");
 
-	usb_make_path(d->udev, d->rc_phys, sizeof(d->rc_phys));
-
-	strlcat(d->rc_phys, "/ir0", sizeof(d->rc_phys));
-
-	input_dev = input_allocate_device();
-	if (!input_dev)
+	rc = rc_allocate_device();
+	if (!rc)
 		return -ENOMEM;
 
-	input_dev->name = "LME2510 Remote Control";
-	input_dev->phys = d->rc_phys;
-
-	usb_to_input_id(d->udev, &input_dev->id);
+	usb_make_path(d->udev, d->rc_phys, sizeof(d->rc_phys));
+	strlcat(d->rc_phys, "/ir0", sizeof(d->rc_phys));
 
-	ret |= ir_input_register(input_dev, ir_codes, NULL, "LME 2510");
+	rc->input_name = "LME2510 Remote Control";
+	rc->input_phys = d->rc_phys;
+	rc->map_name = RC_MAP_LME2510;
+	rc->driver_name = "LME 2510";
+	usb_to_input_id(d->udev, &rc->input_id);
 
+	ret = rc_register_device(rc);
 	if (ret) {
-		input_free_device(input_dev);
+		rc_free_device(rc);
 		return ret;
 	}
+	d->rc_dev = rc;
 
-	d->rc_input_dev = input_dev;
 	/* Start the Interupt */
 	ret = lme2510_int_read(adap);
-
 	if (ret < 0) {
-		ir_input_unregister(input_dev);
-		input_free_device(input_dev);
+		rc_unregister_device(rc);
+		info("INT Unable to start Interupt Service");
+		return -ENODEV;
 	}
-	return (ret < 0) ? -ENODEV : 0;
+
+	return 0;
 }
 
 static u8 check_sum(u8 *p, u8 len)
@@ -668,6 +637,7 @@ static int lme2510_download_firmware(str
 		ret |= (data[0] == 0x88) ? 0 : -1;
 		}
 	}
+
 	usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
 			0x06, 0x80, 0x0200, 0x00, data, 0x0109, 1000);
 
@@ -689,7 +659,7 @@ static int lme2510_download_firmware(str
 }
 
 /* Default firmware for LME2510C */
-const char lme_firmware[50] = "/*(DEBLOBBED)*/";
+char lme_firmware[50] = "/*(DEBLOBBED)*/";
 
 static void lme_coldreset(struct usb_device *dev)
 {
@@ -701,10 +671,11 @@ static void lme_coldreset(struct usb_dev
 	info("FRM Firmware Cold Reset");
 	ret |= lme2510_bulk_write(dev, data , len_in, 1); /*Cold Resetting*/
 	ret |= lme2510_bulk_read(dev, data, len_in, 1);
+
 	return;
 }
 
-static void lme_firmware_switch(struct usb_device *udev, int cold)
+static int lme_firmware_switch(struct usb_device *udev, int cold)
 {
 	const struct firmware *fw = NULL;
 	char lme2510c_s7395[] = "/*(DEBLOBBED)*/";
@@ -712,8 +683,10 @@ static void lme_firmware_switch(struct u
 	char *firm_msg[] = {"Loading", "Switching to"};
 	int ret;
 
+	cold = (cold > 0) ? (cold & 1) : 0;
+
 	if (udev->descriptor.idProduct == 0x1122)
-		return;
+		return 0;
 
 	switch (dvb_usb_lme2510_firmware) {
 	case 0:
@@ -740,22 +713,28 @@ static void lme_firmware_switch(struct u
 		cold = 0;
 		break;
 	}
+
 	release_firmware(fw);
-	if (cold)
+
+	if (cold) {
 		lme_coldreset(udev);
-	return;
+		return -ENODEV;
+	}
+
+	return ret;
 }
 
 static int lme2510_kill_urb(struct usb_data_stream *stream)
 {
 	int i;
+
 	for (i = 0; i < stream->urbs_submitted; i++) {
 		deb_info(3, "killing URB no. %d.", i);
-
 		/* stop the URB */
 		usb_kill_urb(stream->urb_list[i]);
 	}
 	stream->urbs_submitted = 0;
+
 	return 0;
 }
 
@@ -783,18 +762,13 @@ static int dm04_lme2510_set_voltage(stru
 					fe_sec_voltage_t voltage)
 {
 	struct dvb_usb_adapter *adap = fe->dvb->priv;
-	struct lme2510_state *st = adap->dev->priv;
 	static u8 voltage_low[]	= LME_VOLTAGE_L;
 	static u8 voltage_high[] = LME_VOLTAGE_H;
-	static u8 lnb_on[] = LNB_ON;
-	static u8 lnb_off[] = LNB_OFF;
 	static u8 rbuf[1];
 	int ret = 0, len = 3, rlen = 1;
 
-	if (st->stream_on == 1)
-		return 0;
-
-	ret |= lme2510_usb_talk(adap->dev, lnb_on, len, rbuf, rlen);
+	if (mutex_lock_interruptible(&adap->dev->i2c_mutex) < 0)
+			return -EAGAIN;
 
 	switch (voltage) {
 	case SEC_VOLTAGE_18:
@@ -803,94 +777,143 @@ static int dm04_lme2510_set_voltage(stru
 		break;
 
 	case SEC_VOLTAGE_OFF:
-		ret |= lme2510_usb_talk(adap->dev,
-					lnb_off, len, rbuf, rlen);
 	case SEC_VOLTAGE_13:
 	default:
 		ret |= lme2510_usb_talk(adap->dev,
 				voltage_low, len, rbuf, rlen);
 		break;
+	}
 
+	mutex_unlock(&adap->dev->i2c_mutex);
 
-	};
-	st->i2c_talk_onoff = 1;
 	return (ret < 0) ? -ENODEV : 0;
 }
 
+static int lme_name(struct dvb_usb_adapter *adap)
+{
+	struct lme2510_state *st = adap->dev->priv;
+	const char *desc = adap->dev->desc->name;
+	char *fe_name[] = {"", " LG TDQY-P001F", " SHARP:BS2F7HZ7395"};
+	char *name = adap->fe->ops.info.name;
+
+	strlcpy(name, desc, 128);
+	strlcat(name, fe_name[st->tuner_config], 128);
+
+	return 0;
+}
+
 static int dm04_lme2510_frontend_attach(struct dvb_usb_adapter *adap)
 {
-	int ret = 0;
 	struct lme2510_state *st = adap->dev->priv;
 
-	/* Interupt Start  */
-	ret = lme2510_int_service(adap);
-	if (ret < 0) {
-		info("INT Unable to start Interupt Service");
-		return -ENODEV;
-	}
+	int ret = 0;
 
 	st->i2c_talk_onoff = 1;
-	st->i2c_gate = 4;
 
+	st->i2c_gate = 4;
 	adap->fe = dvb_attach(tda10086_attach, &tda10086_config,
 		&adap->dev->i2c_adap);
 
 	if (adap->fe) {
 		info("TUN Found Frontend TDA10086");
-		memcpy(&adap->fe->ops.info.name,
-				&"DM04_LG_TDQY-P001F DVB-S", 24);
-		adap->fe->ops.set_voltage = dm04_lme2510_set_voltage;
 		st->i2c_tuner_gate_w = 4;
 		st->i2c_tuner_gate_r = 4;
 		st->i2c_tuner_addr = 0xc0;
-		if (dvb_attach(tda826x_attach, adap->fe, 0xc0,
-			&adap->dev->i2c_adap, 1)) {
-			info("TUN TDA8263 Found");
-			st->tuner_config = TUNER_LG;
-			if (dvb_usb_lme2510_firmware != 1) {
-				dvb_usb_lme2510_firmware = 1;
-				lme_firmware_switch(adap->dev->udev, 1);
-			}
-			return 0;
-		}
-		kfree(adap->fe);
-		adap->fe = NULL;
+		st->tuner_config = TUNER_LG;
+		if (dvb_usb_lme2510_firmware != 1) {
+			dvb_usb_lme2510_firmware = 1;
+			ret = lme_firmware_switch(adap->dev->udev, 1);
+		} else /*stops LG/Sharp multi tuner problems*/
+			dvb_usb_lme2510_firmware = 0;
+		goto end;
 	}
+
 	st->i2c_gate = 5;
 	adap->fe = dvb_attach(stv0288_attach, &lme_config,
 			&adap->dev->i2c_adap);
 
 	if (adap->fe) {
 		info("FE Found Stv0288");
-		memcpy(&adap->fe->ops.info.name,
-				&"DM04_SHARP:BS2F7HZ7395", 22);
-		adap->fe->ops.set_voltage = dm04_lme2510_set_voltage;
 		st->i2c_tuner_gate_w = 4;
 		st->i2c_tuner_gate_r = 5;
 		st->i2c_tuner_addr = 0xc0;
-		if (dvb_attach(ix2505v_attach , adap->fe, &lme_tuner,
-					&adap->dev->i2c_adap)) {
-			st->tuner_config = TUNER_S7395;
-			info("TUN Sharp IX2505V silicon tuner");
-			if (dvb_usb_lme2510_firmware != 0) {
-				dvb_usb_lme2510_firmware = 0;
-				lme_firmware_switch(adap->dev->udev, 1);
-			}
-			return 0;
+		st->tuner_config = TUNER_S7395;
+		if (dvb_usb_lme2510_firmware != 0) {
+			dvb_usb_lme2510_firmware = 0;
+			ret = lme_firmware_switch(adap->dev->udev, 1);
 		}
+	} else {
+		info("DM04 Not Supported");
+		return -ENODEV;
+	}
+
+end:	if (ret) {
 		kfree(adap->fe);
 		adap->fe = NULL;
+		return -ENODEV;
 	}
 
-	info("DM04 Not Supported");
-	return -ENODEV;
+	adap->fe->ops.set_voltage = dm04_lme2510_set_voltage;
+	ret = lme_name(adap);
+
+	return ret;
+}
+
+static int dm04_lme2510_tuner(struct dvb_usb_adapter *adap)
+{
+	struct lme2510_state *st = adap->dev->priv;
+	char *tun_msg[] = {"", "TDA8263", "IX2505V"};
+	int ret = 0;
+
+	switch (st->tuner_config) {
+	case TUNER_LG:
+		if (dvb_attach(tda826x_attach, adap->fe, 0xc0,
+			&adap->dev->i2c_adap, 1))
+			ret = st->tuner_config;
+		break;
+	case TUNER_S7395:
+		if (dvb_attach(ix2505v_attach , adap->fe, &lme_tuner,
+			&adap->dev->i2c_adap))
+			ret = st->tuner_config;
+		break;
+	default:
+		break;
+	}
+
+	if (ret)
+		info("TUN Found %s tuner", tun_msg[ret]);
+	else {
+		info("TUN No tuner found --- reseting device");
+		lme_coldreset(adap->dev->udev);
+		return -ENODEV;
+	}
+
+	/* Start the Interupt & Remote*/
+	ret = lme2510_int_service(adap);
+
+	return ret;
 }
 
 static int lme2510_powerup(struct dvb_usb_device *d, int onoff)
 {
 	struct lme2510_state *st = d->priv;
+	static u8 lnb_on[] = LNB_ON;
+	static u8 lnb_off[] = LNB_OFF;
+	static u8 rbuf[1];
+	int ret, len = 3, rlen = 1;
+
+	ret = mutex_lock_interruptible(&d->i2c_mutex);
+
+	if (onoff)
+		ret |= lme2510_usb_talk(d, lnb_on, len, rbuf, rlen);
+	else
+		ret |= lme2510_usb_talk(d, lnb_off, len, rbuf, rlen);
+
 	st->i2c_talk_onoff = 1;
-	return 0;
+
+	mutex_unlock(&d->i2c_mutex);
+
+	return ret;
 }
 
 /* DVB USB Driver stuff */
@@ -951,6 +974,7 @@ static struct dvb_usb_device_properties
 		{
 			.streaming_ctrl   = lme2510_streaming_ctrl,
 			.frontend_attach  = dm04_lme2510_frontend_attach,
+			.tuner_attach = dm04_lme2510_tuner,
 			/* parameter for the MPEG2-data transfer */
 			.stream = {
 				.type = USB_BULK,
@@ -971,7 +995,7 @@ static struct dvb_usb_device_properties
 	.generic_bulk_ctrl_endpoint = 0,
 	.num_device_descs = 1,
 	.devices = {
-		{   "DM04 LME2510 DVB-S USB 2.0",
+		{   "DM04_LME2510_DVB-S",
 			{ &lme2510_table[0], NULL },
 			},
 
@@ -982,13 +1006,14 @@ static struct dvb_usb_device_properties
 	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
 	.usb_ctrl = DEVICE_SPECIFIC,
 	.download_firmware = lme2510_download_firmware,
-	.firmware = lme_firmware,
+	.firmware = (const char *)&lme_firmware,
 	.size_of_priv = sizeof(struct lme2510_state),
 	.num_adapters = 1,
 	.adapter = {
 		{
 			.streaming_ctrl   = lme2510_streaming_ctrl,
 			.frontend_attach  = dm04_lme2510_frontend_attach,
+			.tuner_attach = dm04_lme2510_tuner,
 			/* parameter for the MPEG2-data transfer */
 			.stream = {
 				.type = USB_BULK,
@@ -1009,7 +1034,7 @@ static struct dvb_usb_device_properties
 	.generic_bulk_ctrl_endpoint = 0,
 	.num_device_descs = 1,
 	.devices = {
-		{   "DM04 LME2510C USB2.0",
+		{   "DM04_LME2510C_DVB-S",
 			{ &lme2510_table[1], NULL },
 			},
 	}
@@ -1036,7 +1061,7 @@ void *lme2510_exit_int(struct dvb_usb_de
 		usb_free_coherent(d->udev, 5000, st->buffer,
 				  st->lme_urb->transfer_dma);
 		info("Interupt Service Stopped");
-		ir_input_unregister(d->rc_input_dev);
+		rc_unregister_device(d->rc_dev);
 		info("Remote Stopped");
 	}
 	return buffer;
@@ -1055,7 +1080,7 @@ void lme2510_exit(struct usb_interface *
 }
 
 static struct usb_driver lme2510_driver = {
-	.name		= "LME2510C_DVBS",
+	.name		= "LME2510C_DVB-S",
 	.probe		= lme2510_probe,
 	.disconnect	= lme2510_exit,
 	.id_table	= lme2510_table,
@@ -1083,6 +1108,6 @@ module_init(lme2510_module_init);
 module_exit(lme2510_module_exit);
 
 MODULE_AUTHOR("Malcolm Priestley <tvboxspy@gmail.com>");
-MODULE_DESCRIPTION("LM2510(C) DVB-S USB2.0");
-MODULE_VERSION("1.60");
+MODULE_DESCRIPTION("LME2510(C) DVB-S USB2.0");
+MODULE_VERSION("1.75");
 MODULE_LICENSE("GPL");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/dvb/dvb-usb/m920x.c linux-libre-2.6.38-gnu1/drivers/media/dvb/dvb-usb/m920x.c
--- linux-libre-2.6.37-gnu1/drivers/media/dvb/dvb-usb/m920x.c	2013-05-03 03:55:41.000000000 -0400
+++ linux-libre-2.6.38-gnu1/drivers/media/dvb/dvb-usb/m920x.c	2013-05-03 01:55:14.000000000 -0400
@@ -142,9 +142,9 @@ static int m920x_rc_query(struct dvb_usb
 	if ((ret = m920x_read(d->udev, M9206_CORE, 0x0, M9206_RC_KEY, rc_state + 1, 1)) != 0)
 		goto unlock;
 
-	for (i = 0; i < d->props.rc.legacy.rc_key_map_size; i++)
-		if (rc5_data(&d->props.rc.legacy.rc_key_map[i]) == rc_state[1]) {
-			*event = d->props.rc.legacy.rc_key_map[i].keycode;
+	for (i = 0; i < d->props.rc.legacy.rc_map_size; i++)
+		if (rc5_data(&d->props.rc.legacy.rc_map_table[i]) == rc_state[1]) {
+			*event = d->props.rc.legacy.rc_map_table[i].keycode;
 
 			switch(rc_state[0]) {
 			case 0x80:
@@ -589,7 +589,7 @@ static struct m920x_inits pinnacle310e_i
 };
 
 /* ir keymaps */
-static struct ir_scancode ir_codes_megasky_table[] = {
+static struct rc_map_table rc_map_megasky_table[] = {
 	{ 0x0012, KEY_POWER },
 	{ 0x001e, KEY_CYCLEWINDOWS }, /* min/max */
 	{ 0x0002, KEY_CHANNELUP },
@@ -608,7 +608,7 @@ static struct ir_scancode ir_codes_megas
 	{ 0x000e, KEY_COFFEE }, /* "MTS" */
 };
 
-static struct ir_scancode ir_codes_tvwalkertwin_table[] = {
+static struct rc_map_table rc_map_tvwalkertwin_table[] = {
 	{ 0x0001, KEY_ZOOM }, /* Full Screen */
 	{ 0x0002, KEY_CAMERA }, /* snapshot */
 	{ 0x0003, KEY_MUTE },
@@ -628,7 +628,7 @@ static struct ir_scancode ir_codes_tvwal
 	{ 0x001e, KEY_VOLUMEUP },
 };
 
-static struct ir_scancode ir_codes_pinnacle310e_table[] = {
+static struct rc_map_table rc_map_pinnacle310e_table[] = {
 	{ 0x16, KEY_POWER },
 	{ 0x17, KEY_FAVORITES },
 	{ 0x0f, KEY_TEXT },
@@ -786,8 +786,8 @@ static struct dvb_usb_device_properties
 
 	.rc.legacy = {
 		.rc_interval      = 100,
-		.rc_key_map       = ir_codes_megasky_table,
-		.rc_key_map_size  = ARRAY_SIZE(ir_codes_megasky_table),
+		.rc_map_table     = rc_map_megasky_table,
+		.rc_map_size      = ARRAY_SIZE(rc_map_megasky_table),
 		.rc_query         = m920x_rc_query,
 	},
 
@@ -889,8 +889,8 @@ static struct dvb_usb_device_properties
 
 	.rc.legacy = {
 		.rc_interval      = 100,
-		.rc_key_map       = ir_codes_tvwalkertwin_table,
-		.rc_key_map_size  = ARRAY_SIZE(ir_codes_tvwalkertwin_table),
+		.rc_map_table     = rc_map_tvwalkertwin_table,
+		.rc_map_size      = ARRAY_SIZE(rc_map_tvwalkertwin_table),
 		.rc_query         = m920x_rc_query,
 	},
 
@@ -998,8 +998,8 @@ static struct dvb_usb_device_properties
 
 	.rc.legacy = {
 		.rc_interval      = 100,
-		.rc_key_map       = ir_codes_pinnacle310e_table,
-		.rc_key_map_size  = ARRAY_SIZE(ir_codes_pinnacle310e_table),
+		.rc_map_table     = rc_map_pinnacle310e_table,
+		.rc_map_size      = ARRAY_SIZE(rc_map_pinnacle310e_table),
 		.rc_query         = m920x_rc_query,
 	},
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/dvb/dvb-usb/nova-t-usb2.c linux-libre-2.6.38-gnu1/drivers/media/dvb/dvb-usb/nova-t-usb2.c
--- linux-libre-2.6.37-gnu1/drivers/media/dvb/dvb-usb/nova-t-usb2.c	2013-05-03 03:55:43.000000000 -0400
+++ linux-libre-2.6.38-gnu1/drivers/media/dvb/dvb-usb/nova-t-usb2.c	2013-05-03 01:55:16.000000000 -0400
@@ -21,7 +21,7 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr
 #define deb_ee(args...) dprintk(debug,0x02,args)
 
 /* Hauppauge NOVA-T USB2 keys */
-static struct ir_scancode ir_codes_haupp_table[] = {
+static struct rc_map_table rc_map_haupp_table[] = {
 	{ 0x1e00, KEY_0 },
 	{ 0x1e01, KEY_1 },
 	{ 0x1e02, KEY_2 },
@@ -91,14 +91,14 @@ static int nova_t_rc_query(struct dvb_us
 
 			deb_rc("raw key code 0x%02x, 0x%02x, 0x%02x to c: %02x d: %02x toggle: %d\n",key[1],key[2],key[3],custom,data,toggle);
 
-			for (i = 0; i < ARRAY_SIZE(ir_codes_haupp_table); i++) {
-				if (rc5_data(&ir_codes_haupp_table[i]) == data &&
-					rc5_custom(&ir_codes_haupp_table[i]) == custom) {
+			for (i = 0; i < ARRAY_SIZE(rc_map_haupp_table); i++) {
+				if (rc5_data(&rc_map_haupp_table[i]) == data &&
+					rc5_custom(&rc_map_haupp_table[i]) == custom) {
 
-					deb_rc("c: %x, d: %x\n", rc5_data(&ir_codes_haupp_table[i]),
-								 rc5_custom(&ir_codes_haupp_table[i]));
+					deb_rc("c: %x, d: %x\n", rc5_data(&rc_map_haupp_table[i]),
+								 rc5_custom(&rc_map_haupp_table[i]));
 
-					*event = ir_codes_haupp_table[i].keycode;
+					*event = rc_map_haupp_table[i].keycode;
 					*state = REMOTE_KEY_PRESSED;
 					if (st->old_toggle == toggle) {
 						if (st->last_repeat_count++ < 2)
@@ -197,8 +197,8 @@ static struct dvb_usb_device_properties
 
 	.rc.legacy = {
 		.rc_interval      = 100,
-		.rc_key_map       = ir_codes_haupp_table,
-		.rc_key_map_size  = ARRAY_SIZE(ir_codes_haupp_table),
+		.rc_map_table     = rc_map_haupp_table,
+		.rc_map_size      = ARRAY_SIZE(rc_map_haupp_table),
 		.rc_query         = nova_t_rc_query,
 	},
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/dvb/dvb-usb/opera1.c linux-libre-2.6.38-gnu1/drivers/media/dvb/dvb-usb/opera1.c
--- linux-libre-2.6.37-gnu1/drivers/media/dvb/dvb-usb/opera1.c	2013-05-03 03:55:45.000000000 -0400
+++ linux-libre-2.6.38-gnu1/drivers/media/dvb/dvb-usb/opera1.c	2013-05-03 01:55:19.000000000 -0400
@@ -35,7 +35,7 @@
 struct opera1_state {
 	u32 last_key_pressed;
 };
-struct ir_codes_opera_table {
+struct rc_map_opera_table {
 	u32 keycode;
 	u32 event;
 };
@@ -331,7 +331,7 @@ static int opera1_pid_filter_control(str
 	return 0;
 }
 
-static struct ir_scancode ir_codes_opera1_table[] = {
+static struct rc_map_table rc_map_opera1_table[] = {
 	{0x5fa0, KEY_1},
 	{0x51af, KEY_2},
 	{0x5da2, KEY_3},
@@ -404,12 +404,12 @@ static int opera1_rc_query(struct dvb_us
 
 		send_key = (send_key & 0xffff) | 0x0100;
 
-		for (i = 0; i < ARRAY_SIZE(ir_codes_opera1_table); i++) {
-			if (rc5_scan(&ir_codes_opera1_table[i]) == (send_key & 0xffff)) {
+		for (i = 0; i < ARRAY_SIZE(rc_map_opera1_table); i++) {
+			if (rc5_scan(&rc_map_opera1_table[i]) == (send_key & 0xffff)) {
 				*state = REMOTE_KEY_PRESSED;
-				*event = ir_codes_opera1_table[i].keycode;
+				*event = rc_map_opera1_table[i].keycode;
 				opst->last_key_pressed =
-					ir_codes_opera1_table[i].keycode;
+					rc_map_opera1_table[i].keycode;
 				break;
 			}
 			opst->last_key_pressed = 0;
@@ -497,8 +497,8 @@ static struct dvb_usb_device_properties
 	.i2c_algo = &opera1_i2c_algo,
 
 	.rc.legacy = {
-		.rc_key_map = ir_codes_opera1_table,
-		.rc_key_map_size = ARRAY_SIZE(ir_codes_opera1_table),
+		.rc_map_table = rc_map_opera1_table,
+		.rc_map_size = ARRAY_SIZE(rc_map_opera1_table),
 		.rc_interval = 200,
 		.rc_query = opera1_rc_query,
 	},
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/dvb/dvb-usb/ttusb2.c linux-libre-2.6.38-gnu1/drivers/media/dvb/dvb-usb/ttusb2.c
--- linux-libre-2.6.37-gnu1/drivers/media/dvb/dvb-usb/ttusb2.c	2013-05-03 03:55:47.000000000 -0400
+++ linux-libre-2.6.38-gnu1/drivers/media/dvb/dvb-usb/ttusb2.c	2013-05-03 01:55:22.000000000 -0400
@@ -43,6 +43,7 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr
 
 struct ttusb2_state {
 	u8 id;
+	u16 last_rc_key;
 };
 
 static int ttusb2_msg(struct dvb_usb_device *d, u8 cmd,
@@ -128,6 +129,33 @@ static struct i2c_algorithm ttusb2_i2c_a
 	.functionality = ttusb2_i2c_func,
 };
 
+/* command to poll IR receiver (copied from pctv452e.c) */
+#define CMD_GET_IR_CODE     0x1b
+
+/* IR */
+static int tt3650_rc_query(struct dvb_usb_device *d)
+{
+	int ret;
+	u8 rx[9]; /* A CMD_GET_IR_CODE reply is 9 bytes long */
+	struct ttusb2_state *st = d->priv;
+	ret = ttusb2_msg(d, CMD_GET_IR_CODE, NULL, 0, rx, sizeof(rx));
+	if (ret != 0)
+		return ret;
+
+	if (rx[8] & 0x01) {
+		/* got a "press" event */
+		st->last_rc_key = (rx[3] << 8) | rx[2];
+		deb_info("%s: cmd=0x%02x sys=0x%02x\n", __func__, rx[2], rx[3]);
+		rc_keydown(d->rc_dev, st->last_rc_key, 0);
+	} else if (st->last_rc_key) {
+		rc_keyup(d->rc_dev);
+		st->last_rc_key = 0;
+	}
+
+	return 0;
+}
+
+
 /* Callbacks for DVB USB */
 static int ttusb2_identify_state (struct usb_device *udev, struct
 		dvb_usb_device_properties *props, struct dvb_usb_device_description **desc,
@@ -345,6 +373,13 @@ static struct dvb_usb_device_properties
 
 	.size_of_priv = sizeof(struct ttusb2_state),
 
+	.rc.core = {
+		.rc_interval      = 150, /* Less than IR_KEYPRESS_TIMEOUT */
+		.rc_codes         = RC_MAP_TT_1500,
+		.rc_query         = tt3650_rc_query,
+		.allowed_protos   = RC_TYPE_UNKNOWN,
+	},
+
 	.num_adapters = 1,
 	.adapter = {
 		{
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/dvb/dvb-usb/vp702x.c linux-libre-2.6.38-gnu1/drivers/media/dvb/dvb-usb/vp702x.c
--- linux-libre-2.6.37-gnu1/drivers/media/dvb/dvb-usb/vp702x.c	2013-05-03 03:55:51.000000000 -0400
+++ linux-libre-2.6.38-gnu1/drivers/media/dvb/dvb-usb/vp702x.c	2013-05-03 01:55:26.000000000 -0400
@@ -174,7 +174,7 @@ static int vp702x_streaming_ctrl(struct
 }
 
 /* keys for the enclosed remote control */
-static struct ir_scancode ir_codes_vp702x_table[] = {
+static struct rc_map_table rc_map_vp702x_table[] = {
 	{ 0x0001, KEY_1 },
 	{ 0x0002, KEY_2 },
 };
@@ -197,10 +197,10 @@ static int vp702x_rc_query(struct dvb_us
 		return 0;
 	}
 
-	for (i = 0; i < ARRAY_SIZE(ir_codes_vp702x_table); i++)
-		if (rc5_custom(&ir_codes_vp702x_table[i]) == key[1]) {
+	for (i = 0; i < ARRAY_SIZE(rc_map_vp702x_table); i++)
+		if (rc5_custom(&rc_map_vp702x_table[i]) == key[1]) {
 			*state = REMOTE_KEY_PRESSED;
-			*event = ir_codes_vp702x_table[i].keycode;
+			*event = rc_map_vp702x_table[i].keycode;
 			break;
 		}
 	return 0;
@@ -284,8 +284,8 @@ static struct dvb_usb_device_properties
 	.read_mac_address = vp702x_read_mac_addr,
 
 	.rc.legacy = {
-		.rc_key_map       = ir_codes_vp702x_table,
-		.rc_key_map_size  = ARRAY_SIZE(ir_codes_vp702x_table),
+		.rc_map_table       = rc_map_vp702x_table,
+		.rc_map_size  = ARRAY_SIZE(rc_map_vp702x_table),
 		.rc_interval      = 400,
 		.rc_query         = vp702x_rc_query,
 	},
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/dvb/dvb-usb/vp7045.c linux-libre-2.6.38-gnu1/drivers/media/dvb/dvb-usb/vp7045.c
--- linux-libre-2.6.37-gnu1/drivers/media/dvb/dvb-usb/vp7045.c	2013-05-03 03:55:53.000000000 -0400
+++ linux-libre-2.6.38-gnu1/drivers/media/dvb/dvb-usb/vp7045.c	2013-05-03 01:55:29.000000000 -0400
@@ -99,7 +99,7 @@ static int vp7045_power_ctrl(struct dvb_
 
 /* The keymapping struct. Somehow this should be loaded to the driver, but
  * currently it is hardcoded. */
-static struct ir_scancode ir_codes_vp7045_table[] = {
+static struct rc_map_table rc_map_vp7045_table[] = {
 	{ 0x0016, KEY_POWER },
 	{ 0x0010, KEY_MUTE },
 	{ 0x0003, KEY_1 },
@@ -165,10 +165,10 @@ static int vp7045_rc_query(struct dvb_us
 		return 0;
 	}
 
-	for (i = 0; i < ARRAY_SIZE(ir_codes_vp7045_table); i++)
-		if (rc5_data(&ir_codes_vp7045_table[i]) == key) {
+	for (i = 0; i < ARRAY_SIZE(rc_map_vp7045_table); i++)
+		if (rc5_data(&rc_map_vp7045_table[i]) == key) {
 			*state = REMOTE_KEY_PRESSED;
-			*event = ir_codes_vp7045_table[i].keycode;
+			*event = rc_map_vp7045_table[i].keycode;
 			break;
 		}
 	return 0;
@@ -261,8 +261,8 @@ static struct dvb_usb_device_properties
 
 	.rc.legacy = {
 		.rc_interval      = 400,
-		.rc_key_map       = ir_codes_vp7045_table,
-		.rc_key_map_size  = ARRAY_SIZE(ir_codes_vp7045_table),
+		.rc_map_table       = rc_map_vp7045_table,
+		.rc_map_size  = ARRAY_SIZE(rc_map_vp7045_table),
 		.rc_query         = vp7045_rc_query,
 	},
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/dvb/firewire/firedtv-rc.c linux-libre-2.6.38-gnu1/drivers/media/dvb/firewire/firedtv-rc.c
--- linux-libre-2.6.37-gnu1/drivers/media/dvb/firewire/firedtv-rc.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/dvb/firewire/firedtv-rc.c	2011-03-14 21:20:32.000000000 -0400
@@ -172,7 +172,8 @@ void fdtv_unregister_rc(struct firedtv *
 
 void fdtv_handle_rc(struct firedtv *fdtv, unsigned int code)
 {
-	u16 *keycode = fdtv->remote_ctrl_dev->keycode;
+	struct input_dev *idev = fdtv->remote_ctrl_dev;
+	u16 *keycode = idev->keycode;
 
 	if (code >= 0x0300 && code <= 0x031f)
 		code = keycode[code - 0x0300];
@@ -188,6 +189,8 @@ void fdtv_handle_rc(struct firedtv *fdtv
 		return;
 	}
 
-	input_report_key(fdtv->remote_ctrl_dev, code, 1);
-	input_report_key(fdtv->remote_ctrl_dev, code, 0);
+	input_report_key(idev, code, 1);
+	input_sync(idev);
+	input_report_key(idev, code, 0);
+	input_sync(idev);
 }
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/dvb/frontends/af9013.c linux-libre-2.6.38-gnu1/drivers/media/dvb/frontends/af9013.c
--- linux-libre-2.6.37-gnu1/drivers/media/dvb/frontends/af9013.c	2013-05-03 03:55:53.000000000 -0400
+++ linux-libre-2.6.38-gnu1/drivers/media/dvb/frontends/af9013.c	2013-05-03 01:55:29.000000000 -0400
@@ -334,11 +334,11 @@ static int af9013_set_freq_ctrl(struct a
 				if_sample_freq = 3300000; /* 3.3 MHz */
 				break;
 			case BANDWIDTH_7_MHZ:
-				if_sample_freq = 3800000; /* 3.8 MHz */
+				if_sample_freq = 3500000; /* 3.5 MHz */
 				break;
 			case BANDWIDTH_8_MHZ:
 			default:
-				if_sample_freq = 4300000; /* 4.3 MHz */
+				if_sample_freq = 4000000; /* 4.0 MHz */
 				break;
 			}
 		} else if (state->config.tuner == AF9013_TUNER_TDA18218) {
@@ -964,7 +964,7 @@ error:
 static int af9013_update_signal_strength(struct dvb_frontend *fe)
 {
 	struct af9013_state *state = fe->demodulator_priv;
-	int ret;
+	int ret = 0;
 	u8 rf_gain, if_gain;
 	int signal_strength;
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/dvb/frontends/atbm8830.c linux-libre-2.6.38-gnu1/drivers/media/dvb/frontends/atbm8830.c
--- linux-libre-2.6.37-gnu1/drivers/media/dvb/frontends/atbm8830.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/dvb/frontends/atbm8830.c	2011-03-14 21:20:32.000000000 -0400
@@ -50,8 +50,7 @@ static int atbm8830_write_reg(struct atb
 	msg2.addr = dev_addr;
 
 	if (debug >= 2)
-		printk(KERN_DEBUG "%s: reg=0x%04X, data=0x%02X\n",
-			__func__, reg, data);
+		dprintk("%s: reg=0x%04X, data=0x%02X\n", __func__, reg, data);
 
 	ret = i2c_transfer(priv->i2c, &msg1, 1);
 	if (ret != 1)
@@ -77,8 +76,7 @@ static int atbm8830_read_reg(struct atbm
 
 	ret = i2c_transfer(priv->i2c, &msg1, 1);
 	if (ret != 1) {
-		dprintk(KERN_DEBUG "%s: error reg=0x%04x, ret=%i\n",
-			__func__, reg, ret);
+		dprintk("%s: error reg=0x%04x, ret=%i\n", __func__, reg, ret);
 		return -EIO;
 	}
 
@@ -88,7 +86,7 @@ static int atbm8830_read_reg(struct atbm
 
 	*p_data = buf2[0];
 	if (debug >= 2)
-		printk(KERN_DEBUG "%s: reg=0x%04X, data=0x%02X\n",
+		dprintk("%s: reg=0x%04X, data=0x%02X\n",
 			__func__, reg, buf2[0]);
 
 	return 0;
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/dvb/frontends/au8522_decoder.c linux-libre-2.6.38-gnu1/drivers/media/dvb/frontends/au8522_decoder.c
--- linux-libre-2.6.37-gnu1/drivers/media/dvb/frontends/au8522_decoder.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/dvb/frontends/au8522_decoder.c	2011-03-14 21:20:32.000000000 -0400
@@ -278,10 +278,18 @@ static void setup_decoder_defaults(struc
 			AU8522_TVDEC_COMB_HDIF_THR2_REG06AH_CVBS);
 	au8522_writereg(state, AU8522_TVDEC_COMB_HDIF_THR3_REG06BH,
 			AU8522_TVDEC_COMB_HDIF_THR3_REG06BH_CVBS);
-	au8522_writereg(state, AU8522_TVDEC_COMB_DCDIF_THR1_REG06CH,
-			AU8522_TVDEC_COMB_DCDIF_THR1_REG06CH_CVBS);
-	au8522_writereg(state, AU8522_TVDEC_COMB_DCDIF_THR2_REG06DH,
-			AU8522_TVDEC_COMB_DCDIF_THR2_REG06DH_CVBS);
+	if (input_mode == AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH13 ||
+	    input_mode == AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH24) {
+		au8522_writereg(state, AU8522_TVDEC_COMB_DCDIF_THR1_REG06CH,
+				AU8522_TVDEC_COMB_DCDIF_THR1_REG06CH_SVIDEO);
+		au8522_writereg(state, AU8522_TVDEC_COMB_DCDIF_THR2_REG06DH,
+				AU8522_TVDEC_COMB_DCDIF_THR2_REG06DH_SVIDEO);
+	} else {
+		au8522_writereg(state, AU8522_TVDEC_COMB_DCDIF_THR1_REG06CH,
+				AU8522_TVDEC_COMB_DCDIF_THR1_REG06CH_CVBS);
+		au8522_writereg(state, AU8522_TVDEC_COMB_DCDIF_THR2_REG06DH,
+				AU8522_TVDEC_COMB_DCDIF_THR2_REG06DH_CVBS);
+	}
 	au8522_writereg(state, AU8522_TVDEC_COMB_DCDIF_THR3_REG06EH,
 			AU8522_TVDEC_COMB_DCDIF_THR3_REG06EH_CVBS);
 	au8522_writereg(state, AU8522_TVDEC_UV_SEP_THR_REG06FH,
@@ -347,9 +355,11 @@ static void au8522_setup_cvbs_mode(struc
 	au8522_writereg(state, AU8522_MODULE_CLOCK_CONTROL_REG0A3H,
 			AU8522_MODULE_CLOCK_CONTROL_REG0A3H_CVBS);
 
+	/* PGA in automatic mode */
 	au8522_writereg(state, AU8522_PGA_CONTROL_REG082H, 0x00);
-	au8522_writereg(state, AU8522_CLAMPING_CONTROL_REG083H, 0x0e);
-	au8522_writereg(state, AU8522_PGA_CONTROL_REG082H, 0x10);
+
+	/* Enable clamping control */
+	au8522_writereg(state, AU8522_CLAMPING_CONTROL_REG083H, 0x00);
 
 	au8522_writereg(state, AU8522_INPUT_CONTROL_REG081H,
 			AU8522_INPUT_CONTROL_REG081H_CVBS_CH1);
@@ -366,14 +376,14 @@ static void au8522_setup_cvbs_tuner_mode
 	au8522_writereg(state, AU8522_MODULE_CLOCK_CONTROL_REG0A3H,
 			AU8522_MODULE_CLOCK_CONTROL_REG0A3H_CVBS);
 
-	/* It's not clear why they turn off the PGA before enabling the clamp
-	   control, but the Windows trace does it so we will too... */
+	/* It's not clear why we have to have the PGA in automatic mode while
+	   enabling clamp control, but it's what Windows does */
 	au8522_writereg(state, AU8522_PGA_CONTROL_REG082H, 0x00);
 
 	/* Enable clamping control */
 	au8522_writereg(state, AU8522_CLAMPING_CONTROL_REG083H, 0x0e);
 
-	/* Turn on the PGA */
+	/* Disable automatic PGA (since the CVBS is coming from the tuner) */
 	au8522_writereg(state, AU8522_PGA_CONTROL_REG082H, 0x10);
 
 	/* Set input mode to CVBS on channel 4 with SIF audio input enabled */
@@ -396,7 +406,10 @@ static void au8522_setup_svideo_mode(str
 	au8522_writereg(state, AU8522_INPUT_CONTROL_REG081H,
 			AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH13);
 
-	/* Disable clamping control (required for S-video) */
+	/* PGA in automatic mode */
+	au8522_writereg(state, AU8522_PGA_CONTROL_REG082H, 0x00);
+
+	/* Enable clamping control */
 	au8522_writereg(state, AU8522_CLAMPING_CONTROL_REG083H, 0x00);
 
 	setup_decoder_defaults(state,
@@ -410,29 +423,15 @@ static void au8522_setup_svideo_mode(str
 
 static void disable_audio_input(struct au8522_state *state)
 {
-	/* This can probably be optimized */
 	au8522_writereg(state, AU8522_AUDIO_VOLUME_L_REG0F2H, 0x00);
 	au8522_writereg(state, AU8522_AUDIO_VOLUME_R_REG0F3H, 0x00);
 	au8522_writereg(state, AU8522_AUDIO_VOLUME_REG0F4H, 0x00);
-	au8522_writereg(state, AU8522_I2C_CONTROL_REG1_REG091H, 0x80);
-	au8522_writereg(state, AU8522_I2C_CONTROL_REG0_REG090H, 0x84);
-
-	au8522_writereg(state, AU8522_ENA_USB_REG101H, 0x00);
-	au8522_writereg(state, AU8522_AUDIO_VOLUME_L_REG0F2H, 0x7F);
-	au8522_writereg(state, AU8522_AUDIO_VOLUME_R_REG0F3H, 0x7F);
-	au8522_writereg(state, AU8522_REG0F9H, AU8522_REG0F9H_AUDIO);
-	au8522_writereg(state, AU8522_AUDIO_MODE_REG0F1H, 0x40);
-
-	au8522_writereg(state, AU8522_GPIO_DATA_REG0E2H, 0x11);
-	msleep(5);
-	au8522_writereg(state, AU8522_GPIO_DATA_REG0E2H, 0x00);
 
 	au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_1_REG0A5H, 0x04);
-	au8522_writereg(state, AU8522_AUDIOFREQ_REG606H, 0x03);
 	au8522_writereg(state, AU8522_I2S_CTRL_2_REG112H, 0x02);
 
 	au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H,
-			AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_CVBS);
+			AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_SVIDEO);
 }
 
 /* 0=disable, 1=SIF */
@@ -622,7 +621,7 @@ static int au8522_queryctrl(struct v4l2_
 		return v4l2_ctrl_query_fill(qc, 0, 255, 1,
 					    AU8522_TVDEC_CONTRAST_REG00BH_CVBS);
 	case V4L2_CID_BRIGHTNESS:
-		return v4l2_ctrl_query_fill(qc, 0, 255, 1, 128);
+		return v4l2_ctrl_query_fill(qc, 0, 255, 1, 109);
 	case V4L2_CID_SATURATION:
 		return v4l2_ctrl_query_fill(qc, 0, 255, 1, 128);
 	case V4L2_CID_HUE:
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/dvb/frontends/au8522_priv.h linux-libre-2.6.38-gnu1/drivers/media/dvb/frontends/au8522_priv.h
--- linux-libre-2.6.37-gnu1/drivers/media/dvb/frontends/au8522_priv.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/dvb/frontends/au8522_priv.h	2011-03-14 21:20:32.000000000 -0400
@@ -397,7 +397,9 @@ void au8522_release_state(struct au8522_
 #define AU8522_TVDEC_COMB_HDIF_THR2_REG06AH_CVBS		0x0A
 #define AU8522_TVDEC_COMB_HDIF_THR3_REG06BH_CVBS		0x32
 #define AU8522_TVDEC_COMB_DCDIF_THR1_REG06CH_CVBS		0x34
+#define AU8522_TVDEC_COMB_DCDIF_THR1_REG06CH_SVIDEO		0x2a
 #define AU8522_TVDEC_COMB_DCDIF_THR2_REG06DH_CVBS		0x05
+#define AU8522_TVDEC_COMB_DCDIF_THR2_REG06DH_SVIDEO		0x15
 #define AU8522_TVDEC_COMB_DCDIF_THR3_REG06EH_CVBS		0x6E
 #define AU8522_TVDEC_UV_SEP_THR_REG06FH_CVBS			0x0F
 #define AU8522_TVDEC_COMB_DC_THR1_NTSC_REG070H_CVBS		0x80
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/dvb/frontends/dib7000m.c linux-libre-2.6.38-gnu1/drivers/media/dvb/frontends/dib7000m.c
--- linux-libre-2.6.37-gnu1/drivers/media/dvb/frontends/dib7000m.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/dvb/frontends/dib7000m.c	2011-03-14 21:20:32.000000000 -0400
@@ -805,7 +805,7 @@ static void dib7000m_set_channel(struct
 	value = 0;
 	switch (ch->u.ofdm.transmission_mode) {
 		case TRANSMISSION_MODE_2K: value |= (0 << 7); break;
-		case /* 4K MODE */ 255: value |= (2 << 7); break;
+		case TRANSMISSION_MODE_4K: value |= (2 << 7); break;
 		default:
 		case TRANSMISSION_MODE_8K: value |= (1 << 7); break;
 	}
@@ -866,7 +866,7 @@ static void dib7000m_set_channel(struct
 	/* P_dvsy_sync_wait */
 	switch (ch->u.ofdm.transmission_mode) {
 		case TRANSMISSION_MODE_8K: value = 256; break;
-		case /* 4K MODE */ 255: value = 128; break;
+		case TRANSMISSION_MODE_4K: value = 128; break;
 		case TRANSMISSION_MODE_2K:
 		default: value = 64; break;
 	}
@@ -1020,7 +1020,7 @@ static int dib7000m_tune(struct dvb_fron
 	value = (6 << 8) | 0x80;
 	switch (ch->u.ofdm.transmission_mode) {
 		case TRANSMISSION_MODE_2K: value |= (7 << 12); break;
-		case /* 4K MODE */ 255: value |= (8 << 12); break;
+		case TRANSMISSION_MODE_4K: value |= (8 << 12); break;
 		default:
 		case TRANSMISSION_MODE_8K: value |= (9 << 12); break;
 	}
@@ -1030,7 +1030,7 @@ static int dib7000m_tune(struct dvb_fron
 	value = (0 << 4);
 	switch (ch->u.ofdm.transmission_mode) {
 		case TRANSMISSION_MODE_2K: value |= 0x6; break;
-		case /* 4K MODE */ 255: value |= 0x7; break;
+		case TRANSMISSION_MODE_4K: value |= 0x7; break;
 		default:
 		case TRANSMISSION_MODE_8K: value |= 0x8; break;
 	}
@@ -1040,7 +1040,7 @@ static int dib7000m_tune(struct dvb_fron
 	value = (0 << 4);
 	switch (ch->u.ofdm.transmission_mode) {
 		case TRANSMISSION_MODE_2K: value |= 0x6; break;
-		case /* 4K MODE */ 255: value |= 0x7; break;
+		case TRANSMISSION_MODE_4K: value |= 0x7; break;
 		default:
 		case TRANSMISSION_MODE_8K: value |= 0x8; break;
 	}
@@ -1285,6 +1285,25 @@ struct i2c_adapter * dib7000m_get_i2c_ma
 }
 EXPORT_SYMBOL(dib7000m_get_i2c_master);
 
+int dib7000m_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff)
+{
+	struct dib7000m_state *state = fe->demodulator_priv;
+	u16 val = dib7000m_read_word(state, 294 + state->reg_offs) & 0xffef;
+	val |= (onoff & 0x1) << 4;
+	dprintk("PID filter enabled %d", onoff);
+	return dib7000m_write_word(state, 294 + state->reg_offs, val);
+}
+EXPORT_SYMBOL(dib7000m_pid_filter_ctrl);
+
+int dib7000m_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff)
+{
+	struct dib7000m_state *state = fe->demodulator_priv;
+	dprintk("PID filter: index %x, PID %d, OnOff %d", id, pid, onoff);
+	return dib7000m_write_word(state, 300 + state->reg_offs + id,
+			onoff ? (1 << 13) | pid : 0);
+}
+EXPORT_SYMBOL(dib7000m_pid_filter);
+
 #if 0
 /* used with some prototype boards */
 int dib7000m_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods,
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/dvb/frontends/dib7000m.h linux-libre-2.6.38-gnu1/drivers/media/dvb/frontends/dib7000m.h
--- linux-libre-2.6.37-gnu1/drivers/media/dvb/frontends/dib7000m.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/dvb/frontends/dib7000m.h	2011-03-14 21:20:32.000000000 -0400
@@ -46,6 +46,8 @@ extern struct dvb_frontend *dib7000m_att
 extern struct i2c_adapter *dib7000m_get_i2c_master(struct dvb_frontend *,
 						   enum dibx000_i2c_interface,
 						   int);
+extern int dib7000m_pid_filter(struct dvb_frontend *, u8 id, u16 pid, u8 onoff);
+extern int dib7000m_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff);
 #else
 static inline
 struct dvb_frontend *dib7000m_attach(struct i2c_adapter *i2c_adap,
@@ -63,6 +65,19 @@ struct i2c_adapter *dib7000m_get_i2c_mas
 	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
 	return NULL;
 }
+static inline int dib7000m_pid_filter(struct dvb_frontend *fe, u8 id,
+						u16 pid, u8 onoff)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return -ENODEV;
+}
+
+static inline int dib7000m_pid_filter_ctrl(struct dvb_frontend *fe,
+						uint8_t onoff)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return -ENODEV;
+}
 #endif
 
 /* TODO
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/dvb/frontends/dib7000p.c linux-libre-2.6.38-gnu1/drivers/media/dvb/frontends/dib7000p.c
--- linux-libre-2.6.37-gnu1/drivers/media/dvb/frontends/dib7000p.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/dvb/frontends/dib7000p.c	2011-03-14 21:20:32.000000000 -0400
@@ -717,7 +717,7 @@ static void dib7000p_set_channel(struct
 	value = 0;
 	switch (ch->u.ofdm.transmission_mode) {
 		case TRANSMISSION_MODE_2K: value |= (0 << 7); break;
-		case /* 4K MODE */ 255: value |= (2 << 7); break;
+		case TRANSMISSION_MODE_4K: value |= (2 << 7); break;
 		default:
 		case TRANSMISSION_MODE_8K: value |= (1 << 7); break;
 	}
@@ -770,7 +770,7 @@ static void dib7000p_set_channel(struct
 	/* P_dvsy_sync_wait */
 	switch (ch->u.ofdm.transmission_mode) {
 		case TRANSMISSION_MODE_8K: value = 256; break;
-		case /* 4K MODE */ 255: value = 128; break;
+		case TRANSMISSION_MODE_4K: value = 128; break;
 		case TRANSMISSION_MODE_2K:
 		default: value = 64; break;
 	}
@@ -994,7 +994,7 @@ static int dib7000p_tune(struct dvb_fron
 	tmp = (6 << 8) | 0x80;
 	switch (ch->u.ofdm.transmission_mode) {
 		case TRANSMISSION_MODE_2K: tmp |= (7 << 12); break;
-		case /* 4K MODE */ 255: tmp |= (8 << 12); break;
+		case TRANSMISSION_MODE_4K: tmp |= (8 << 12); break;
 		default:
 		case TRANSMISSION_MODE_8K: tmp |= (9 << 12); break;
 	}
@@ -1004,7 +1004,7 @@ static int dib7000p_tune(struct dvb_fron
 	tmp = (0 << 4);
 	switch (ch->u.ofdm.transmission_mode) {
 		case TRANSMISSION_MODE_2K: tmp |= 0x6; break;
-		case /* 4K MODE */ 255: tmp |= 0x7; break;
+		case TRANSMISSION_MODE_4K: tmp |= 0x7; break;
 		default:
 		case TRANSMISSION_MODE_8K: tmp |= 0x8; break;
 	}
@@ -1014,7 +1014,7 @@ static int dib7000p_tune(struct dvb_fron
 	tmp = (0 << 4);
 	switch (ch->u.ofdm.transmission_mode) {
 		case TRANSMISSION_MODE_2K: tmp |= 0x6; break;
-		case /* 4K MODE */ 255: tmp |= 0x7; break;
+		case TRANSMISSION_MODE_4K: tmp |= 0x7; break;
 		default:
 		case TRANSMISSION_MODE_8K: tmp |= 0x8; break;
 	}
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/dvb/frontends/ix2505v.c linux-libre-2.6.38-gnu1/drivers/media/dvb/frontends/ix2505v.c
--- linux-libre-2.6.37-gnu1/drivers/media/dvb/frontends/ix2505v.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/dvb/frontends/ix2505v.c	2011-03-14 21:20:32.000000000 -0400
@@ -72,7 +72,7 @@ static int ix2505v_read_status_reg(struc
 	ret = i2c_transfer(state->i2c, msg, 1);
 	deb_i2c("Read %s ", __func__);
 
-	return (ret = 1) ? (int) b2[0] : -1;
+	return (ret == 1) ? (int) b2[0] : -1;
 }
 
 static int ix2505v_write(struct ix2505v_state *state, u8 buf[], u8 count)
@@ -311,7 +311,7 @@ struct dvb_frontend *ix2505v_attach(stru
 	return fe;
 
 error:
-	ix2505v_release(fe);
+	kfree(state);
 	return NULL;
 }
 EXPORT_SYMBOL(ix2505v_attach);
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/dvb/frontends/Kconfig linux-libre-2.6.38-gnu1/drivers/media/dvb/frontends/Kconfig
--- linux-libre-2.6.37-gnu1/drivers/media/dvb/frontends/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/dvb/frontends/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -1,7 +1,7 @@
 config DVB_FE_CUSTOMISE
 	bool "Customise the frontend modules to build"
 	depends on DVB_CORE
-	default y if EMBEDDED
+	default y if EXPERT
 	help
 	  This allows the user to select/deselect frontend drivers for their
 	  hardware from the build.
@@ -497,7 +497,7 @@ comment "ISDB-T (terrestrial) frontends"
 	depends on DVB_CORE
 
 config DVB_S921
-	tristate "Sharp S921 tuner"
+	tristate "Sharp S921 frontend"
 	depends on DVB_CORE && I2C
 	default m if DVB_FE_CUSTOMISE
 	help
@@ -512,6 +512,14 @@ config DVB_DIB8000
 	  A driver for DiBcom's DiB8000 ISDB-T/ISDB-Tsb demodulator.
 	  Say Y when you want to support this frontend.
 
+config DVB_MB86A20S
+	tristate "Fujitsu mb86a20s"
+	depends on DVB_CORE && I2C
+	default m if DVB_FE_CUSTOMISE
+	help
+	  A driver for Fujitsu mb86a20s ISDB-T/ISDB-Tsb demodulator.
+	  Say Y when you want to support this frontend.
+
 comment "Digital terrestrial only tuners/PLL"
 	depends on DVB_CORE
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/dvb/frontends/lgs8gxx.c linux-libre-2.6.38-gnu1/drivers/media/dvb/frontends/lgs8gxx.c
--- linux-libre-2.6.37-gnu1/drivers/media/dvb/frontends/lgs8gxx.c	2013-05-03 03:56:00.000000000 -0400
+++ linux-libre-2.6.38-gnu1/drivers/media/dvb/frontends/lgs8gxx.c	2013-05-03 01:55:34.000000000 -0400
@@ -60,13 +60,12 @@ static int lgs8gxx_write_reg(struct lgs8
 		msg.addr += 0x02;
 
 	if (debug >= 2)
-		printk(KERN_DEBUG "%s: reg=0x%02X, data=0x%02X\n",
-			__func__, reg, data);
+		dprintk("%s: reg=0x%02X, data=0x%02X\n", __func__, reg, data);
 
 	ret = i2c_transfer(priv->i2c, &msg, 1);
 
 	if (ret != 1)
-		dprintk(KERN_DEBUG "%s: error reg=0x%x, data=0x%x, ret=%i\n",
+		dprintk("%s: error reg=0x%x, data=0x%x, ret=%i\n",
 			__func__, reg, data, ret);
 
 	return (ret != 1) ? -1 : 0;
@@ -91,15 +90,13 @@ static int lgs8gxx_read_reg(struct lgs8g
 
 	ret = i2c_transfer(priv->i2c, msg, 2);
 	if (ret != 2) {
-		dprintk(KERN_DEBUG "%s: error reg=0x%x, ret=%i\n",
-			__func__, reg, ret);
+		dprintk("%s: error reg=0x%x, ret=%i\n", __func__, reg, ret);
 		return -1;
 	}
 
 	*p_data = b1[0];
 	if (debug >= 2)
-		printk(KERN_DEBUG "%s: reg=0x%02X, data=0x%02X\n",
-			__func__, reg, b1[0]);
+		dprintk("%s: reg=0x%02X, data=0x%02X\n", __func__, reg, b1[0]);
 	return 0;
 }
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/dvb/frontends/Makefile linux-libre-2.6.38-gnu1/drivers/media/dvb/frontends/Makefile
--- linux-libre-2.6.37-gnu1/drivers/media/dvb/frontends/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/dvb/frontends/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,6 @@
 EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/
 EXTRA_CFLAGS += -Idrivers/media/common/tuners/
 
-s921-objs := s921_module.o s921_core.o
 stb0899-objs = stb0899_drv.o stb0899_algo.o
 stv0900-objs = stv0900_core.o stv0900_sw.o
 au8522-objs = au8522_dig.o au8522_decoder.o
@@ -82,4 +81,5 @@ obj-$(CONFIG_DVB_ISL6423) += isl6423.o
 obj-$(CONFIG_DVB_EC100) += ec100.o
 obj-$(CONFIG_DVB_DS3000) += ds3000.o
 obj-$(CONFIG_DVB_MB86A16) += mb86a16.o
+obj-$(CONFIG_DVB_MB86A20S) += mb86a20s.o
 obj-$(CONFIG_DVB_IX2505V) += ix2505v.o
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/dvb/frontends/mb86a20s.c linux-libre-2.6.38-gnu1/drivers/media/dvb/frontends/mb86a20s.c
--- linux-libre-2.6.37-gnu1/drivers/media/dvb/frontends/mb86a20s.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/dvb/frontends/mb86a20s.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,639 @@
+/*
+ *   Fujitu mb86a20s ISDB-T/ISDB-Tsb Module driver
+ *
+ *   Copyright (C) 2010 Mauro Carvalho Chehab <mchehab@redhat.com>
+ *   Copyright (C) 2009-2010 Douglas Landgraf <dougsland@redhat.com>
+ *
+ *   FIXME: Need to port to DVB v5.2 API
+ *
+ *   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.
+ */
+
+#include <linux/kernel.h>
+#include <asm/div64.h>
+
+#include "dvb_frontend.h"
+#include "mb86a20s.h"
+
+static int debug = 1;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Activates frontend debugging (default:0)");
+
+#define rc(args...)  do {						\
+	printk(KERN_ERR  "mb86a20s: " args);				\
+} while (0)
+
+#define dprintk(args...)						\
+	do {								\
+		if (debug) {						\
+			printk(KERN_DEBUG "mb86a20s: %s: ", __func__);	\
+			printk(args);					\
+		}							\
+	} while (0)
+
+struct mb86a20s_state {
+	struct i2c_adapter *i2c;
+	const struct mb86a20s_config *config;
+
+	struct dvb_frontend frontend;
+
+	bool need_init;
+};
+
+struct regdata {
+	u8 reg;
+	u8 data;
+};
+
+/*
+ * Initialization sequence: Use whatevere default values that PV SBTVD
+ * does on its initialisation, obtained via USB snoop
+ */
+static struct regdata mb86a20s_init[] = {
+	{ 0x70, 0x0f },
+	{ 0x70, 0xff },
+	{ 0x08, 0x01 },
+	{ 0x09, 0x3e },
+	{ 0x50, 0xd1 },
+	{ 0x51, 0x22 },
+	{ 0x39, 0x01 },
+	{ 0x71, 0x00 },
+	{ 0x28, 0x2a },
+	{ 0x29, 0x00 },
+	{ 0x2a, 0xff },
+	{ 0x2b, 0x80 },
+	{ 0x28, 0x20 },
+	{ 0x29, 0x33 },
+	{ 0x2a, 0xdf },
+	{ 0x2b, 0xa9 },
+	{ 0x3b, 0x21 },
+	{ 0x3c, 0x3a },
+	{ 0x01, 0x0d },
+	{ 0x04, 0x08 },
+	{ 0x05, 0x05 },
+	{ 0x04, 0x0e },
+	{ 0x05, 0x00 },
+	{ 0x04, 0x0f },
+	{ 0x05, 0x14 },
+	{ 0x04, 0x0b },
+	{ 0x05, 0x8c },
+	{ 0x04, 0x00 },
+	{ 0x05, 0x00 },
+	{ 0x04, 0x01 },
+	{ 0x05, 0x07 },
+	{ 0x04, 0x02 },
+	{ 0x05, 0x0f },
+	{ 0x04, 0x03 },
+	{ 0x05, 0xa0 },
+	{ 0x04, 0x09 },
+	{ 0x05, 0x00 },
+	{ 0x04, 0x0a },
+	{ 0x05, 0xff },
+	{ 0x04, 0x27 },
+	{ 0x05, 0x64 },
+	{ 0x04, 0x28 },
+	{ 0x05, 0x00 },
+	{ 0x04, 0x1e },
+	{ 0x05, 0xff },
+	{ 0x04, 0x29 },
+	{ 0x05, 0x0a },
+	{ 0x04, 0x32 },
+	{ 0x05, 0x0a },
+	{ 0x04, 0x14 },
+	{ 0x05, 0x02 },
+	{ 0x04, 0x04 },
+	{ 0x05, 0x00 },
+	{ 0x04, 0x05 },
+	{ 0x05, 0x22 },
+	{ 0x04, 0x06 },
+	{ 0x05, 0x0e },
+	{ 0x04, 0x07 },
+	{ 0x05, 0xd8 },
+	{ 0x04, 0x12 },
+	{ 0x05, 0x00 },
+	{ 0x04, 0x13 },
+	{ 0x05, 0xff },
+	{ 0x52, 0x01 },
+	{ 0x50, 0xa7 },
+	{ 0x51, 0x00 },
+	{ 0x50, 0xa8 },
+	{ 0x51, 0xff },
+	{ 0x50, 0xa9 },
+	{ 0x51, 0xff },
+	{ 0x50, 0xaa },
+	{ 0x51, 0x00 },
+	{ 0x50, 0xab },
+	{ 0x51, 0xff },
+	{ 0x50, 0xac },
+	{ 0x51, 0xff },
+	{ 0x50, 0xad },
+	{ 0x51, 0x00 },
+	{ 0x50, 0xae },
+	{ 0x51, 0xff },
+	{ 0x50, 0xaf },
+	{ 0x51, 0xff },
+	{ 0x5e, 0x07 },
+	{ 0x50, 0xdc },
+	{ 0x51, 0x01 },
+	{ 0x50, 0xdd },
+	{ 0x51, 0xf4 },
+	{ 0x50, 0xde },
+	{ 0x51, 0x01 },
+	{ 0x50, 0xdf },
+	{ 0x51, 0xf4 },
+	{ 0x50, 0xe0 },
+	{ 0x51, 0x01 },
+	{ 0x50, 0xe1 },
+	{ 0x51, 0xf4 },
+	{ 0x50, 0xb0 },
+	{ 0x51, 0x07 },
+	{ 0x50, 0xb2 },
+	{ 0x51, 0xff },
+	{ 0x50, 0xb3 },
+	{ 0x51, 0xff },
+	{ 0x50, 0xb4 },
+	{ 0x51, 0xff },
+	{ 0x50, 0xb5 },
+	{ 0x51, 0xff },
+	{ 0x50, 0xb6 },
+	{ 0x51, 0xff },
+	{ 0x50, 0xb7 },
+	{ 0x51, 0xff },
+	{ 0x50, 0x50 },
+	{ 0x51, 0x02 },
+	{ 0x50, 0x51 },
+	{ 0x51, 0x04 },
+	{ 0x45, 0x04 },
+	{ 0x48, 0x04 },
+	{ 0x50, 0xd5 },
+	{ 0x51, 0x01 },		/* Serial */
+	{ 0x50, 0xd6 },
+	{ 0x51, 0x1f },
+	{ 0x50, 0xd2 },
+	{ 0x51, 0x03 },
+	{ 0x50, 0xd7 },
+	{ 0x51, 0x3f },
+	{ 0x1c, 0x01 },
+	{ 0x28, 0x06 },
+	{ 0x29, 0x00 },
+	{ 0x2a, 0x00 },
+	{ 0x2b, 0x03 },
+	{ 0x28, 0x07 },
+	{ 0x29, 0x00 },
+	{ 0x2a, 0x00 },
+	{ 0x2b, 0x0d },
+	{ 0x28, 0x08 },
+	{ 0x29, 0x00 },
+	{ 0x2a, 0x00 },
+	{ 0x2b, 0x02 },
+	{ 0x28, 0x09 },
+	{ 0x29, 0x00 },
+	{ 0x2a, 0x00 },
+	{ 0x2b, 0x01 },
+	{ 0x28, 0x0a },
+	{ 0x29, 0x00 },
+	{ 0x2a, 0x00 },
+	{ 0x2b, 0x21 },
+	{ 0x28, 0x0b },
+	{ 0x29, 0x00 },
+	{ 0x2a, 0x00 },
+	{ 0x2b, 0x29 },
+	{ 0x28, 0x0c },
+	{ 0x29, 0x00 },
+	{ 0x2a, 0x00 },
+	{ 0x2b, 0x16 },
+	{ 0x28, 0x0d },
+	{ 0x29, 0x00 },
+	{ 0x2a, 0x00 },
+	{ 0x2b, 0x31 },
+	{ 0x28, 0x0e },
+	{ 0x29, 0x00 },
+	{ 0x2a, 0x00 },
+	{ 0x2b, 0x0e },
+	{ 0x28, 0x0f },
+	{ 0x29, 0x00 },
+	{ 0x2a, 0x00 },
+	{ 0x2b, 0x4e },
+	{ 0x28, 0x10 },
+	{ 0x29, 0x00 },
+	{ 0x2a, 0x00 },
+	{ 0x2b, 0x46 },
+	{ 0x28, 0x11 },
+	{ 0x29, 0x00 },
+	{ 0x2a, 0x00 },
+	{ 0x2b, 0x0f },
+	{ 0x28, 0x12 },
+	{ 0x29, 0x00 },
+	{ 0x2a, 0x00 },
+	{ 0x2b, 0x56 },
+	{ 0x28, 0x13 },
+	{ 0x29, 0x00 },
+	{ 0x2a, 0x00 },
+	{ 0x2b, 0x35 },
+	{ 0x28, 0x14 },
+	{ 0x29, 0x00 },
+	{ 0x2a, 0x01 },
+	{ 0x2b, 0xbe },
+	{ 0x28, 0x15 },
+	{ 0x29, 0x00 },
+	{ 0x2a, 0x01 },
+	{ 0x2b, 0x84 },
+	{ 0x28, 0x16 },
+	{ 0x29, 0x00 },
+	{ 0x2a, 0x03 },
+	{ 0x2b, 0xee },
+	{ 0x28, 0x17 },
+	{ 0x29, 0x00 },
+	{ 0x2a, 0x00 },
+	{ 0x2b, 0x98 },
+	{ 0x28, 0x18 },
+	{ 0x29, 0x00 },
+	{ 0x2a, 0x00 },
+	{ 0x2b, 0x9f },
+	{ 0x28, 0x19 },
+	{ 0x29, 0x00 },
+	{ 0x2a, 0x07 },
+	{ 0x2b, 0xb2 },
+	{ 0x28, 0x1a },
+	{ 0x29, 0x00 },
+	{ 0x2a, 0x06 },
+	{ 0x2b, 0xc2 },
+	{ 0x28, 0x1b },
+	{ 0x29, 0x00 },
+	{ 0x2a, 0x07 },
+	{ 0x2b, 0x4a },
+	{ 0x28, 0x1c },
+	{ 0x29, 0x00 },
+	{ 0x2a, 0x01 },
+	{ 0x2b, 0xbc },
+	{ 0x28, 0x1d },
+	{ 0x29, 0x00 },
+	{ 0x2a, 0x04 },
+	{ 0x2b, 0xba },
+	{ 0x28, 0x1e },
+	{ 0x29, 0x00 },
+	{ 0x2a, 0x06 },
+	{ 0x2b, 0x14 },
+	{ 0x50, 0x1e },
+	{ 0x51, 0x5d },
+	{ 0x50, 0x22 },
+	{ 0x51, 0x00 },
+	{ 0x50, 0x23 },
+	{ 0x51, 0xc8 },
+	{ 0x50, 0x24 },
+	{ 0x51, 0x00 },
+	{ 0x50, 0x25 },
+	{ 0x51, 0xf0 },
+	{ 0x50, 0x26 },
+	{ 0x51, 0x00 },
+	{ 0x50, 0x27 },
+	{ 0x51, 0xc3 },
+	{ 0x50, 0x39 },
+	{ 0x51, 0x02 },
+	{ 0x50, 0xd5 },
+	{ 0x51, 0x01 },
+	{ 0xd0, 0x00 },
+};
+
+static struct regdata mb86a20s_reset_reception[] = {
+	{ 0x70, 0xf0 },
+	{ 0x70, 0xff },
+	{ 0x08, 0x01 },
+	{ 0x08, 0x00 },
+};
+
+static int mb86a20s_i2c_writereg(struct mb86a20s_state *state,
+			     u8 i2c_addr, int reg, int data)
+{
+	u8 buf[] = { reg, data };
+	struct i2c_msg msg = {
+		.addr = i2c_addr, .flags = 0, .buf = buf, .len = 2
+	};
+	int rc;
+
+	rc = i2c_transfer(state->i2c, &msg, 1);
+	if (rc != 1) {
+		printk("%s: writereg error (rc == %i, reg == 0x%02x,"
+			 " data == 0x%02x)\n", __func__, rc, reg, data);
+		return rc;
+	}
+
+	return 0;
+}
+
+static int mb86a20s_i2c_writeregdata(struct mb86a20s_state *state,
+				     u8 i2c_addr, struct regdata *rd, int size)
+{
+	int i, rc;
+
+	for (i = 0; i < size; i++) {
+		rc = mb86a20s_i2c_writereg(state, i2c_addr, rd[i].reg,
+					   rd[i].data);
+		if (rc < 0)
+			return rc;
+	}
+	return 0;
+}
+
+static int mb86a20s_i2c_readreg(struct mb86a20s_state *state,
+				u8 i2c_addr, u8 reg)
+{
+	u8 val;
+	int rc;
+	struct i2c_msg msg[] = {
+		{ .addr = i2c_addr, .flags = 0, .buf = &reg, .len = 1 },
+		{ .addr = i2c_addr, .flags = I2C_M_RD, .buf = &val, .len = 1 }
+	};
+
+	rc = i2c_transfer(state->i2c, msg, 2);
+
+	if (rc != 2) {
+		rc("%s: reg=0x%x (error=%d)\n", __func__, reg, rc);
+		return rc;
+	}
+
+	return val;
+}
+
+#define mb86a20s_readreg(state, reg) \
+	mb86a20s_i2c_readreg(state, state->config->demod_address, reg)
+#define mb86a20s_writereg(state, reg, val) \
+	mb86a20s_i2c_writereg(state, state->config->demod_address, reg, val)
+#define mb86a20s_writeregdata(state, regdata) \
+	mb86a20s_i2c_writeregdata(state, state->config->demod_address, \
+	regdata, ARRAY_SIZE(regdata))
+
+static int mb86a20s_initfe(struct dvb_frontend *fe)
+{
+	struct mb86a20s_state *state = fe->demodulator_priv;
+	int rc;
+	u8  regD5 = 1;
+
+	dprintk("\n");
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 0);
+
+	/* Initialize the frontend */
+	rc = mb86a20s_writeregdata(state, mb86a20s_init);
+	if (rc < 0)
+		goto err;
+
+	if (!state->config->is_serial) {
+		regD5 &= ~1;
+
+		rc = mb86a20s_writereg(state, 0x50, 0xd5);
+		if (rc < 0)
+			goto err;
+		rc = mb86a20s_writereg(state, 0x51, regD5);
+		if (rc < 0)
+			goto err;
+	}
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
+
+err:
+	if (rc < 0) {
+		state->need_init = true;
+		printk(KERN_INFO "mb86a20s: Init failed. Will try again later\n");
+	} else {
+		state->need_init = false;
+		dprintk("Initialization succeded.\n");
+	}
+	return rc;
+}
+
+static int mb86a20s_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
+{
+	struct mb86a20s_state *state = fe->demodulator_priv;
+	unsigned rf_max, rf_min, rf;
+	u8	 val;
+
+	dprintk("\n");
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 0);
+
+	/* Does a binary search to get RF strength */
+	rf_max = 0xfff;
+	rf_min = 0;
+	do {
+		rf = (rf_max + rf_min) / 2;
+		mb86a20s_writereg(state, 0x04, 0x1f);
+		mb86a20s_writereg(state, 0x05, rf >> 8);
+		mb86a20s_writereg(state, 0x04, 0x20);
+		mb86a20s_writereg(state, 0x04, rf);
+
+		val = mb86a20s_readreg(state, 0x02);
+		if (val & 0x08)
+			rf_min = (rf_max + rf_min) / 2;
+		else
+			rf_max = (rf_max + rf_min) / 2;
+		if (rf_max - rf_min < 4) {
+			*strength = (((rf_max + rf_min) / 2) * 65535) / 4095;
+			break;
+		}
+	} while (1);
+
+	dprintk("signal strength = %d\n", *strength);
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
+
+	return 0;
+}
+
+static int mb86a20s_read_status(struct dvb_frontend *fe, fe_status_t *status)
+{
+	struct mb86a20s_state *state = fe->demodulator_priv;
+	u8 val;
+
+	dprintk("\n");
+	*status = 0;
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 0);
+	val = mb86a20s_readreg(state, 0x0a) & 0xf;
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
+
+	if (val >= 2)
+		*status |= FE_HAS_SIGNAL;
+
+	if (val >= 4)
+		*status |= FE_HAS_CARRIER;
+
+	if (val >= 5)
+		*status |= FE_HAS_VITERBI;
+
+	if (val >= 7)
+		*status |= FE_HAS_SYNC;
+
+	if (val >= 8)				/* Maybe 9? */
+		*status |= FE_HAS_LOCK;
+
+	dprintk("val = %d, status = 0x%02x\n", val, *status);
+
+	return 0;
+}
+
+static int mb86a20s_set_frontend(struct dvb_frontend *fe,
+	struct dvb_frontend_parameters *p)
+{
+	struct mb86a20s_state *state = fe->demodulator_priv;
+	int rc;
+
+	dprintk("\n");
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
+	dprintk("Calling tuner set parameters\n");
+	fe->ops.tuner_ops.set_params(fe, p);
+
+	/*
+	 * Make it more reliable: if, for some reason, the initial
+	 * device initialization doesn't happen, initialize it when
+	 * a SBTVD parameters are adjusted.
+	 *
+	 * Unfortunately, due to a hard to track bug at tda829x/tda18271,
+	 * the agc callback logic is not called during DVB attach time,
+	 * causing mb86a20s to not be initialized with Kworld SBTVD.
+	 * So, this hack is needed, in order to make Kworld SBTVD to work.
+	 */
+	if (state->need_init)
+		mb86a20s_initfe(fe);
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 0);
+	rc = mb86a20s_writeregdata(state, mb86a20s_reset_reception);
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
+
+	return rc;
+}
+
+static int mb86a20s_get_frontend(struct dvb_frontend *fe,
+	struct dvb_frontend_parameters *p)
+{
+
+	/* FIXME: For now, it does nothing */
+
+	fe->dtv_property_cache.bandwidth_hz = 6000000;
+	fe->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_AUTO;
+	fe->dtv_property_cache.guard_interval = GUARD_INTERVAL_AUTO;
+	fe->dtv_property_cache.isdbt_partial_reception = 0;
+
+	return 0;
+}
+
+static int mb86a20s_tune(struct dvb_frontend *fe,
+			struct dvb_frontend_parameters *params,
+			unsigned int mode_flags,
+			unsigned int *delay,
+			fe_status_t *status)
+{
+	int rc = 0;
+
+	dprintk("\n");
+
+	if (params != NULL)
+		rc = mb86a20s_set_frontend(fe, params);
+
+	if (!(mode_flags & FE_TUNE_MODE_ONESHOT))
+		mb86a20s_read_status(fe, status);
+
+	return rc;
+}
+
+static void mb86a20s_release(struct dvb_frontend *fe)
+{
+	struct mb86a20s_state *state = fe->demodulator_priv;
+
+	dprintk("\n");
+
+	kfree(state);
+}
+
+static struct dvb_frontend_ops mb86a20s_ops;
+
+struct dvb_frontend *mb86a20s_attach(const struct mb86a20s_config *config,
+				    struct i2c_adapter *i2c)
+{
+	u8	rev;
+
+	/* allocate memory for the internal state */
+	struct mb86a20s_state *state =
+		kzalloc(sizeof(struct mb86a20s_state), GFP_KERNEL);
+
+	dprintk("\n");
+	if (state == NULL) {
+		rc("Unable to kzalloc\n");
+		goto error;
+	}
+
+	/* setup the state */
+	state->config = config;
+	state->i2c = i2c;
+
+	/* create dvb_frontend */
+	memcpy(&state->frontend.ops, &mb86a20s_ops,
+		sizeof(struct dvb_frontend_ops));
+	state->frontend.demodulator_priv = state;
+
+	/* Check if it is a mb86a20s frontend */
+	rev = mb86a20s_readreg(state, 0);
+
+	if (rev == 0x13) {
+		printk(KERN_INFO "Detected a Fujitsu mb86a20s frontend\n");
+	} else {
+		printk(KERN_ERR "Frontend revision %d is unknown - aborting.\n",
+		       rev);
+		goto error;
+	}
+
+	return &state->frontend;
+
+error:
+	kfree(state);
+	return NULL;
+}
+EXPORT_SYMBOL(mb86a20s_attach);
+
+static struct dvb_frontend_ops mb86a20s_ops = {
+	/* Use dib8000 values per default */
+	.info = {
+		.name = "Fujitsu mb86A20s",
+		.type = FE_OFDM,
+		.caps = FE_CAN_INVERSION_AUTO | FE_CAN_RECOVER |
+			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_TRANSMISSION_MODE_AUTO | FE_CAN_QAM_AUTO |
+			FE_CAN_GUARD_INTERVAL_AUTO    | FE_CAN_HIERARCHY_AUTO,
+		/* Actually, those values depend on the used tuner */
+		.frequency_min = 45000000,
+		.frequency_max = 864000000,
+		.frequency_stepsize = 62500,
+	},
+
+	.release = mb86a20s_release,
+
+	.init = mb86a20s_initfe,
+	.set_frontend = mb86a20s_set_frontend,
+	.get_frontend = mb86a20s_get_frontend,
+	.read_status = mb86a20s_read_status,
+	.read_signal_strength = mb86a20s_read_signal_strength,
+	.tune = mb86a20s_tune,
+};
+
+MODULE_DESCRIPTION("DVB Frontend module for Fujitsu mb86A20s hardware");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
+MODULE_LICENSE("GPL");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/dvb/frontends/mb86a20s.h linux-libre-2.6.38-gnu1/drivers/media/dvb/frontends/mb86a20s.h
--- linux-libre-2.6.37-gnu1/drivers/media/dvb/frontends/mb86a20s.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/dvb/frontends/mb86a20s.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,52 @@
+/*
+ *   Fujitsu mb86a20s driver
+ *
+ *   Copyright (C) 2010 Mauro Carvalho Chehab <mchehab@redhat.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.
+ *
+ *   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 MB86A20S_H
+#define MB86A20S_H
+
+#include <linux/dvb/frontend.h>
+
+/**
+ * struct mb86a20s_config - Define the per-device attributes of the frontend
+ *
+ * @demod_address:	the demodulator's i2c address
+ */
+
+struct mb86a20s_config {
+	u8 demod_address;
+	bool is_serial;
+};
+
+#if defined(CONFIG_DVB_MB86A20S) || (defined(CONFIG_DVB_MB86A20S_MODULE) \
+	&& defined(MODULE))
+extern struct dvb_frontend *mb86a20s_attach(const struct mb86a20s_config *config,
+					   struct i2c_adapter *i2c);
+extern struct i2c_adapter *mb86a20s_get_tuner_i2c_adapter(struct dvb_frontend *);
+#else
+static inline struct dvb_frontend *mb86a20s_attach(
+	const struct mb86a20s_config *config, struct i2c_adapter *i2c)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+static struct i2c_adapter *
+	mb86a20s_get_tuner_i2c_adapter(struct dvb_frontend *fe)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+#endif
+
+#endif /* MB86A20S */
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/dvb/frontends/s921.c linux-libre-2.6.38-gnu1/drivers/media/dvb/frontends/s921.c
--- linux-libre-2.6.37-gnu1/drivers/media/dvb/frontends/s921.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/dvb/frontends/s921.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,548 @@
+/*
+ *   Sharp VA3A5JZ921 One Seg Broadcast Module driver
+ *   This device is labeled as just S. 921 at the top of the frontend can
+ *
+ *   Copyright (C) 2009-2010 Mauro Carvalho Chehab <mchehab@redhat.com>
+ *   Copyright (C) 2009-2010 Douglas Landgraf <dougsland@redhat.com>
+ *
+ *   Developed for Leadership SBTVD 1seg device sold in Brazil
+ *
+ *   Frontend module based on cx24123 driver, getting some info from
+ *	the old s921 driver.
+ *
+ *   FIXME: Need to port to DVB v5.2 API
+ *
+ *   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.
+ */
+
+#include <linux/kernel.h>
+#include <asm/div64.h>
+
+#include "dvb_frontend.h"
+#include "s921.h"
+
+static int debug = 1;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Activates frontend debugging (default:0)");
+
+#define rc(args...)  do {						\
+	printk(KERN_ERR  "s921: " args);				\
+} while (0)
+
+#define dprintk(args...)						\
+	do {								\
+		if (debug) {						\
+			printk(KERN_DEBUG "s921: %s: ", __func__);	\
+			printk(args);					\
+		}							\
+	} while (0)
+
+struct s921_state {
+	struct i2c_adapter *i2c;
+	const struct s921_config *config;
+
+	struct dvb_frontend frontend;
+
+	/* The Demod can't easily provide these, we cache them */
+	u32 currentfreq;
+};
+
+/*
+ * Various tuner defaults need to be established for a given frequency kHz.
+ * fixme: The bounds on the bands do not match the doc in real life.
+ * fixme: Some of them have been moved, other might need adjustment.
+ */
+static struct s921_bandselect_val {
+	u32 freq_low;
+	u8  band_reg;
+} s921_bandselect[] = {
+	{         0, 0x7b },
+	{ 485140000, 0x5b },
+	{ 515140000, 0x3b },
+	{ 545140000, 0x1b },
+	{ 599140000, 0xfb },
+	{ 623140000, 0xdb },
+	{ 659140000, 0xbb },
+	{ 713140000, 0x9b },
+};
+
+struct regdata {
+	u8 reg;
+	u8 data;
+};
+
+static struct regdata s921_init[] = {
+	{ 0x01, 0x80 },		/* Probably, a reset sequence */
+	{ 0x01, 0x40 },
+	{ 0x01, 0x80 },
+	{ 0x01, 0x40 },
+
+	{ 0x02, 0x00 },
+	{ 0x03, 0x40 },
+	{ 0x04, 0x01 },
+	{ 0x05, 0x00 },
+	{ 0x06, 0x00 },
+	{ 0x07, 0x00 },
+	{ 0x08, 0x00 },
+	{ 0x09, 0x00 },
+	{ 0x0a, 0x00 },
+	{ 0x0b, 0x5a },
+	{ 0x0c, 0x00 },
+	{ 0x0d, 0x00 },
+	{ 0x0f, 0x00 },
+	{ 0x13, 0x1b },
+	{ 0x14, 0x80 },
+	{ 0x15, 0x40 },
+	{ 0x17, 0x70 },
+	{ 0x18, 0x01 },
+	{ 0x19, 0x12 },
+	{ 0x1a, 0x01 },
+	{ 0x1b, 0x12 },
+	{ 0x1c, 0xa0 },
+	{ 0x1d, 0x00 },
+	{ 0x1e, 0x0a },
+	{ 0x1f, 0x08 },
+	{ 0x20, 0x40 },
+	{ 0x21, 0xff },
+	{ 0x22, 0x4c },
+	{ 0x23, 0x4e },
+	{ 0x24, 0x4c },
+	{ 0x25, 0x00 },
+	{ 0x26, 0x00 },
+	{ 0x27, 0xf4 },
+	{ 0x28, 0x60 },
+	{ 0x29, 0x88 },
+	{ 0x2a, 0x40 },
+	{ 0x2b, 0x40 },
+	{ 0x2c, 0xff },
+	{ 0x2d, 0x00 },
+	{ 0x2e, 0xff },
+	{ 0x2f, 0x00 },
+	{ 0x30, 0x20 },
+	{ 0x31, 0x06 },
+	{ 0x32, 0x0c },
+	{ 0x34, 0x0f },
+	{ 0x37, 0xfe },
+	{ 0x38, 0x00 },
+	{ 0x39, 0x63 },
+	{ 0x3a, 0x10 },
+	{ 0x3b, 0x10 },
+	{ 0x47, 0x00 },
+	{ 0x49, 0xe5 },
+	{ 0x4b, 0x00 },
+	{ 0x50, 0xc0 },
+	{ 0x52, 0x20 },
+	{ 0x54, 0x5a },
+	{ 0x55, 0x5b },
+	{ 0x56, 0x40 },
+	{ 0x57, 0x70 },
+	{ 0x5c, 0x50 },
+	{ 0x5d, 0x00 },
+	{ 0x62, 0x17 },
+	{ 0x63, 0x2f },
+	{ 0x64, 0x6f },
+	{ 0x68, 0x00 },
+	{ 0x69, 0x89 },
+	{ 0x6a, 0x00 },
+	{ 0x6b, 0x00 },
+	{ 0x6c, 0x00 },
+	{ 0x6d, 0x00 },
+	{ 0x6e, 0x00 },
+	{ 0x70, 0x10 },
+	{ 0x71, 0x00 },
+	{ 0x75, 0x00 },
+	{ 0x76, 0x30 },
+	{ 0x77, 0x01 },
+	{ 0xaf, 0x00 },
+	{ 0xb0, 0xa0 },
+	{ 0xb2, 0x3d },
+	{ 0xb3, 0x25 },
+	{ 0xb4, 0x8b },
+	{ 0xb5, 0x4b },
+	{ 0xb6, 0x3f },
+	{ 0xb7, 0xff },
+	{ 0xb8, 0xff },
+	{ 0xb9, 0xfc },
+	{ 0xba, 0x00 },
+	{ 0xbb, 0x00 },
+	{ 0xbc, 0x00 },
+	{ 0xd0, 0x30 },
+	{ 0xe4, 0x84 },
+	{ 0xf0, 0x48 },
+	{ 0xf1, 0x19 },
+	{ 0xf2, 0x5a },
+	{ 0xf3, 0x8e },
+	{ 0xf4, 0x2d },
+	{ 0xf5, 0x07 },
+	{ 0xf6, 0x5a },
+	{ 0xf7, 0xba },
+	{ 0xf8, 0xd7 },
+};
+
+static struct regdata s921_prefreq[] = {
+	{ 0x47, 0x60 },
+	{ 0x68, 0x00 },
+	{ 0x69, 0x89 },
+	{ 0xf0, 0x48 },
+	{ 0xf1, 0x19 },
+};
+
+static struct regdata s921_postfreq[] = {
+	{ 0xf5, 0xae },
+	{ 0xf6, 0xb7 },
+	{ 0xf7, 0xba },
+	{ 0xf8, 0xd7 },
+	{ 0x68, 0x0a },
+	{ 0x69, 0x09 },
+};
+
+static int s921_i2c_writereg(struct s921_state *state,
+			     u8 i2c_addr, int reg, int data)
+{
+	u8 buf[] = { reg, data };
+	struct i2c_msg msg = {
+		.addr = i2c_addr, .flags = 0, .buf = buf, .len = 2
+	};
+	int rc;
+
+	rc = i2c_transfer(state->i2c, &msg, 1);
+	if (rc != 1) {
+		printk("%s: writereg rcor(rc == %i, reg == 0x%02x,"
+			 " data == 0x%02x)\n", __func__, rc, reg, data);
+		return rc;
+	}
+
+	return 0;
+}
+
+static int s921_i2c_writeregdata(struct s921_state *state, u8 i2c_addr,
+				 struct regdata *rd, int size)
+{
+	int i, rc;
+
+	for (i = 0; i < size; i++) {
+		rc = s921_i2c_writereg(state, i2c_addr, rd[i].reg, rd[i].data);
+		if (rc < 0)
+			return rc;
+	}
+	return 0;
+}
+
+static int s921_i2c_readreg(struct s921_state *state, u8 i2c_addr, u8 reg)
+{
+	u8 val;
+	int rc;
+	struct i2c_msg msg[] = {
+		{ .addr = i2c_addr, .flags = 0, .buf = &reg, .len = 1 },
+		{ .addr = i2c_addr, .flags = I2C_M_RD, .buf = &val, .len = 1 }
+	};
+
+	rc = i2c_transfer(state->i2c, msg, 2);
+
+	if (rc != 2) {
+		rc("%s: reg=0x%x (rcor=%d)\n", __func__, reg, rc);
+		return rc;
+	}
+
+	return val;
+}
+
+#define s921_readreg(state, reg) \
+	s921_i2c_readreg(state, state->config->demod_address, reg)
+#define s921_writereg(state, reg, val) \
+	s921_i2c_writereg(state, state->config->demod_address, reg, val)
+#define s921_writeregdata(state, regdata) \
+	s921_i2c_writeregdata(state, state->config->demod_address, \
+	regdata, ARRAY_SIZE(regdata))
+
+static int s921_pll_tune(struct dvb_frontend *fe,
+	struct dvb_frontend_parameters *p)
+{
+	struct s921_state *state = fe->demodulator_priv;
+	int band, rc, i;
+	unsigned long f_offset;
+	u8 f_switch;
+	u64 offset;
+
+	dprintk("frequency=%i\n", p->frequency);
+
+	for (band = 0; band < ARRAY_SIZE(s921_bandselect); band++)
+		if (p->frequency < s921_bandselect[band].freq_low)
+			break;
+	band--;
+
+	if (band < 0) {
+		rc("%s: frequency out of range\n", __func__);
+		return -EINVAL;
+	}
+
+	f_switch = s921_bandselect[band].band_reg;
+
+	offset = ((u64)p->frequency) * 258;
+	do_div(offset, 6000000);
+	f_offset = ((unsigned long)offset) + 2321;
+
+	rc = s921_writeregdata(state, s921_prefreq);
+	if (rc < 0)
+		return rc;
+
+	rc = s921_writereg(state, 0xf2, (f_offset >> 8) & 0xff);
+	if (rc < 0)
+		return rc;
+
+	rc = s921_writereg(state, 0xf3, f_offset & 0xff);
+	if (rc < 0)
+		return rc;
+
+	rc = s921_writereg(state, 0xf4, f_switch);
+	if (rc < 0)
+		return rc;
+
+	rc = s921_writeregdata(state, s921_postfreq);
+	if (rc < 0)
+		return rc;
+
+	for (i = 0 ; i < 6; i++) {
+		rc = s921_readreg(state, 0x80);
+		dprintk("status 0x80: %02x\n", rc);
+	}
+	rc = s921_writereg(state, 0x01, 0x40);
+	if (rc < 0)
+		return rc;
+
+	rc = s921_readreg(state, 0x01);
+	dprintk("status 0x01: %02x\n", rc);
+
+	rc = s921_readreg(state, 0x80);
+	dprintk("status 0x80: %02x\n", rc);
+
+	rc = s921_readreg(state, 0x80);
+	dprintk("status 0x80: %02x\n", rc);
+
+	rc = s921_readreg(state, 0x32);
+	dprintk("status 0x32: %02x\n", rc);
+
+	dprintk("pll tune band=%d, pll=%d\n", f_switch, (int)f_offset);
+
+	return 0;
+}
+
+static int s921_initfe(struct dvb_frontend *fe)
+{
+	struct s921_state *state = fe->demodulator_priv;
+	int rc;
+
+	dprintk("\n");
+
+	rc = s921_writeregdata(state, s921_init);
+	if (rc < 0)
+		return rc;
+
+	return 0;
+}
+
+static int s921_read_status(struct dvb_frontend *fe, fe_status_t *status)
+{
+	struct s921_state *state = fe->demodulator_priv;
+	int regstatus, rc;
+
+	*status = 0;
+
+	rc = s921_readreg(state, 0x81);
+	if (rc < 0)
+		return rc;
+
+	regstatus = rc << 8;
+
+	rc = s921_readreg(state, 0x82);
+	if (rc < 0)
+		return rc;
+
+	regstatus |= rc;
+
+	dprintk("status = %04x\n", regstatus);
+
+	/* Full Sync - We don't know what each bit means on regs 0x81/0x82 */
+	if ((regstatus & 0xff) == 0x40) {
+		*status = FE_HAS_SIGNAL  |
+			  FE_HAS_CARRIER |
+			  FE_HAS_VITERBI |
+			  FE_HAS_SYNC    |
+			  FE_HAS_LOCK;
+	} else if (regstatus & 0x40) {
+		/* This is close to Full Sync, but not enough to get useful info */
+		*status = FE_HAS_SIGNAL  |
+			  FE_HAS_CARRIER |
+			  FE_HAS_VITERBI |
+			  FE_HAS_SYNC;
+	}
+
+	return 0;
+}
+
+static int s921_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
+{
+	fe_status_t	status;
+	struct s921_state *state = fe->demodulator_priv;
+	int rc;
+
+	/* FIXME: Use the proper register for it... 0x80? */
+	rc = s921_read_status(fe, &status);
+	if (rc < 0)
+		return rc;
+
+	*strength = (status & FE_HAS_LOCK) ? 0xffff : 0;
+
+	dprintk("strength = 0x%04x\n", *strength);
+
+	rc = s921_readreg(state, 0x01);
+	dprintk("status 0x01: %02x\n", rc);
+
+	rc = s921_readreg(state, 0x80);
+	dprintk("status 0x80: %02x\n", rc);
+
+	rc = s921_readreg(state, 0x32);
+	dprintk("status 0x32: %02x\n", rc);
+
+	return 0;
+}
+
+static int s921_set_frontend(struct dvb_frontend *fe,
+	struct dvb_frontend_parameters *p)
+{
+	struct s921_state *state = fe->demodulator_priv;
+	int rc;
+
+	dprintk("\n");
+
+	/* FIXME: We don't know how to use non-auto mode */
+
+	rc = s921_pll_tune(fe, p);
+	if (rc < 0)
+		return rc;
+
+	state->currentfreq = p->frequency;
+
+	return 0;
+}
+
+static int s921_get_frontend(struct dvb_frontend *fe,
+	struct dvb_frontend_parameters *p)
+{
+	struct s921_state *state = fe->demodulator_priv;
+
+	/* FIXME: Probably it is possible to get it from regs f1 and f2 */
+	p->frequency = state->currentfreq;
+
+	return 0;
+}
+
+static int s921_tune(struct dvb_frontend *fe,
+			struct dvb_frontend_parameters *params,
+			unsigned int mode_flags,
+			unsigned int *delay,
+			fe_status_t *status)
+{
+	int rc = 0;
+
+	dprintk("\n");
+
+	if (params != NULL)
+		rc = s921_set_frontend(fe, params);
+
+	if (!(mode_flags & FE_TUNE_MODE_ONESHOT))
+		s921_read_status(fe, status);
+
+	return rc;
+}
+
+static int s921_get_algo(struct dvb_frontend *fe)
+{
+	return 1; /* FE_ALGO_HW */
+}
+
+static void s921_release(struct dvb_frontend *fe)
+{
+	struct s921_state *state = fe->demodulator_priv;
+
+	dprintk("\n");
+	kfree(state);
+}
+
+static struct dvb_frontend_ops s921_ops;
+
+struct dvb_frontend *s921_attach(const struct s921_config *config,
+				    struct i2c_adapter *i2c)
+{
+	/* allocate memory for the internal state */
+	struct s921_state *state =
+		kzalloc(sizeof(struct s921_state), GFP_KERNEL);
+
+	dprintk("\n");
+	if (state == NULL) {
+		rc("Unable to kzalloc\n");
+		goto rcor;
+	}
+
+	/* setup the state */
+	state->config = config;
+	state->i2c = i2c;
+
+	/* create dvb_frontend */
+	memcpy(&state->frontend.ops, &s921_ops,
+		sizeof(struct dvb_frontend_ops));
+	state->frontend.demodulator_priv = state;
+
+	return &state->frontend;
+
+rcor:
+	kfree(state);
+
+	return NULL;
+}
+EXPORT_SYMBOL(s921_attach);
+
+static struct dvb_frontend_ops s921_ops = {
+	/* Use dib8000 values per default */
+	.info = {
+		.name = "Sharp S921",
+		.type = FE_OFDM,
+		.frequency_min = 470000000,
+		/*
+		 * Max should be 770MHz instead, according with Sharp docs,
+		 * but Leadership doc says it works up to 806 MHz. This is
+		 * required to get channel 69, used in Brazil
+		 */
+		.frequency_max = 806000000,
+		.frequency_tolerance = 0,
+		 .caps = FE_CAN_INVERSION_AUTO |
+			 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_TRANSMISSION_MODE_AUTO |
+			 FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_RECOVER |
+			 FE_CAN_HIERARCHY_AUTO,
+	},
+
+	.release = s921_release,
+
+	.init = s921_initfe,
+	.set_frontend = s921_set_frontend,
+	.get_frontend = s921_get_frontend,
+	.read_status = s921_read_status,
+	.read_signal_strength = s921_read_signal_strength,
+	.tune = s921_tune,
+	.get_frontend_algo = s921_get_algo,
+};
+
+MODULE_DESCRIPTION("DVB Frontend module for Sharp S921 hardware");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
+MODULE_AUTHOR("Douglas Landgraf <dougsland@redhat.com>");
+MODULE_LICENSE("GPL");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/dvb/frontends/s921_core.c linux-libre-2.6.38-gnu1/drivers/media/dvb/frontends/s921_core.c
--- linux-libre-2.6.37-gnu1/drivers/media/dvb/frontends/s921_core.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/dvb/frontends/s921_core.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,216 +0,0 @@
-/*
- * Driver for Sharp s921 driver
- *
- * Copyright (C) 2008 Markus Rechberger <mrechberger@sundtek.de>
- *
- */
-
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/delay.h>
-#include "s921_core.h"
-
-static int s921_isdb_init(struct s921_isdb_t *dev);
-static int s921_isdb_set_parameters(struct s921_isdb_t *dev, struct s921_isdb_t_transmission_mode_params *params);
-static int s921_isdb_tune(struct s921_isdb_t *dev, struct s921_isdb_t_tune_params *params);
-static int s921_isdb_get_status(struct s921_isdb_t *dev, void *data);
-
-static u8 init_table[]={ 0x01, 0x40, 0x02, 0x00, 0x03, 0x40, 0x04, 0x01,
-			 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x08, 0x00,
-			 0x09, 0x00, 0x0a, 0x00, 0x0b, 0x5a, 0x0c, 0x00,
-			 0x0d, 0x00, 0x0f, 0x00, 0x13, 0x1b, 0x14, 0x80,
-			 0x15, 0x40, 0x17, 0x70, 0x18, 0x01, 0x19, 0x12,
-			 0x1a, 0x01, 0x1b, 0x12, 0x1c, 0xa0, 0x1d, 0x00,
-			 0x1e, 0x0a, 0x1f, 0x08, 0x20, 0x40, 0x21, 0xff,
-			 0x22, 0x4c, 0x23, 0x4e, 0x24, 0x4c, 0x25, 0x00,
-			 0x26, 0x00, 0x27, 0xf4, 0x28, 0x60, 0x29, 0x88,
-			 0x2a, 0x40, 0x2b, 0x40, 0x2c, 0xff, 0x2d, 0x00,
-			 0x2e, 0xff, 0x2f, 0x00, 0x30, 0x20, 0x31, 0x06,
-			 0x32, 0x0c, 0x34, 0x0f, 0x37, 0xfe, 0x38, 0x00,
-			 0x39, 0x63, 0x3a, 0x10, 0x3b, 0x10, 0x47, 0x00,
-			 0x49, 0xe5, 0x4b, 0x00, 0x50, 0xc0, 0x52, 0x20,
-			 0x54, 0x5a, 0x55, 0x5b, 0x56, 0x40, 0x57, 0x70,
-			 0x5c, 0x50, 0x5d, 0x00, 0x62, 0x17, 0x63, 0x2f,
-			 0x64, 0x6f, 0x68, 0x00, 0x69, 0x89, 0x6a, 0x00,
-			 0x6b, 0x00, 0x6c, 0x00, 0x6d, 0x00, 0x6e, 0x00,
-			 0x70, 0x00, 0x71, 0x00, 0x75, 0x00, 0x76, 0x30,
-			 0x77, 0x01, 0xaf, 0x00, 0xb0, 0xa0, 0xb2, 0x3d,
-			 0xb3, 0x25, 0xb4, 0x8b, 0xb5, 0x4b, 0xb6, 0x3f,
-			 0xb7, 0xff, 0xb8, 0xff, 0xb9, 0xfc, 0xba, 0x00,
-			 0xbb, 0x00, 0xbc, 0x00, 0xd0, 0x30, 0xe4, 0x84,
-			 0xf0, 0x48, 0xf1, 0x19, 0xf2, 0x5a, 0xf3, 0x8e,
-			 0xf4, 0x2d, 0xf5, 0x07, 0xf6, 0x5a, 0xf7, 0xba,
-			 0xf8, 0xd7 };
-
-static u8 c_table[]={ 0x58, 0x8a, 0x7b, 0x59, 0x8c, 0x7b, 0x5a, 0x8e, 0x5b,
-		      0x5b, 0x90, 0x5b, 0x5c, 0x92, 0x5b, 0x5d, 0x94, 0x5b,
-		      0x5e, 0x96, 0x5b, 0x5f, 0x98, 0x3b, 0x60, 0x9a, 0x3b,
-		      0x61, 0x9c, 0x3b, 0x62, 0x9e, 0x3b, 0x63, 0xa0, 0x3b,
-		      0x64, 0xa2, 0x1b, 0x65, 0xa4, 0x1b, 0x66, 0xa6, 0x1b,
-		      0x67, 0xa8, 0x1b, 0x68, 0xaa, 0x1b, 0x69, 0xac, 0x1b,
-		      0x6a, 0xae, 0x1b, 0x6b, 0xb0, 0x1b, 0x6c, 0xb2, 0x1b,
-		      0x6d, 0xb4, 0xfb, 0x6e, 0xb6, 0xfb, 0x6f, 0xb8, 0xfb,
-		      0x70, 0xba, 0xfb, 0x71, 0xbc, 0xdb, 0x72, 0xbe, 0xdb,
-		      0x73, 0xc0, 0xdb, 0x74, 0xc2, 0xdb, 0x75, 0xc4, 0xdb,
-		      0x76, 0xc6, 0xdb, 0x77, 0xc8, 0xbb, 0x78, 0xca, 0xbb,
-		      0x79, 0xcc, 0xbb, 0x7a, 0xce, 0xbb, 0x7b, 0xd0, 0xbb,
-		      0x7c, 0xd2, 0xbb, 0x7d, 0xd4, 0xbb, 0x7e, 0xd6, 0xbb,
-		      0x7f, 0xd8, 0xbb, 0x80, 0xda, 0x9b, 0x81, 0xdc, 0x9b,
-		      0x82, 0xde, 0x9b, 0x83, 0xe0, 0x9b, 0x84, 0xe2, 0x9b,
-		      0x85, 0xe4, 0x9b, 0x86, 0xe6, 0x9b, 0x87, 0xe8, 0x9b,
-		      0x88, 0xea, 0x9b, 0x89, 0xec, 0x9b };
-
-int s921_isdb_cmd(struct s921_isdb_t *dev, u32 cmd, void *data) {
-	switch(cmd) {
-	case ISDB_T_CMD_INIT:
-		s921_isdb_init(dev);
-		break;
-	case ISDB_T_CMD_SET_PARAM:
-		s921_isdb_set_parameters(dev, data);
-		break;
-	case ISDB_T_CMD_TUNE:
-		s921_isdb_tune(dev, data);
-		break;
-	case ISDB_T_CMD_GET_STATUS:
-		s921_isdb_get_status(dev, data);
-		break;
-	default:
-		printk("unhandled command\n");
-		return -EINVAL;
-	}
-	return 0;
-}
-
-static int s921_isdb_init(struct s921_isdb_t *dev) {
-	unsigned int i;
-	unsigned int ret;
-	printk("isdb_init\n");
-	for (i = 0; i < sizeof(init_table); i+=2) {
-		ret = dev->i2c_write(dev->priv_dev, init_table[i], init_table[i+1]);
-		if (ret != 0) {
-			printk("i2c write failed\n");
-			return ret;
-		}
-	}
-	return 0;
-}
-
-static int s921_isdb_set_parameters(struct s921_isdb_t *dev, struct s921_isdb_t_transmission_mode_params *params) {
-
-	int ret;
-	/* auto is sufficient for now, lateron this should be reflected in an extra interface */
-
-
-
-	ret = dev->i2c_write(dev->priv_dev, 0xb0, 0xa0); //mod_b2);
-	ret = dev->i2c_write(dev->priv_dev, 0xb2, 0x3d); //mod_b2);
-
-	if (ret < 0)
-		return -EINVAL;
-
-	ret = dev->i2c_write(dev->priv_dev, 0xb3, 0x25); //mod_b3);
-	if (ret < 0)
-		return -EINVAL;
-
-	ret = dev->i2c_write(dev->priv_dev, 0xb4, 0x8b); //mod_b4);
-	if (ret < 0)
-		return -EINVAL;
-
-	ret = dev->i2c_write(dev->priv_dev, 0xb5, 0x4b); //mod_b5);
-	if (ret < 0)
-		return -EINVAL;
-
-	ret = dev->i2c_write(dev->priv_dev, 0xb6, 0x3f); //mod_b6);
-	if (ret < 0)
-		return -EINVAL;
-
-	ret = dev->i2c_write(dev->priv_dev, 0xb7, 0x3f); //mod_b7);
-	if (ret < 0)
-		return -EINVAL;
-
-	return E_OK;
-}
-
-static int s921_isdb_tune(struct s921_isdb_t *dev, struct s921_isdb_t_tune_params *params) {
-
-	int ret;
-	int index;
-
-	index = (params->frequency - 473143000)/6000000;
-
-	if (index > 48) {
-		return -EINVAL;
-	}
-
-	dev->i2c_write(dev->priv_dev, 0x47, 0x60);
-
-	ret = dev->i2c_write(dev->priv_dev, 0x68, 0x00);
-	if (ret < 0)
-		return -EINVAL;
-
-	ret = dev->i2c_write(dev->priv_dev, 0x69, 0x89);
-	if (ret < 0)
-		return -EINVAL;
-
-	ret = dev->i2c_write(dev->priv_dev, 0xf0, 0x48);
-	if (ret < 0)
-		return -EINVAL;
-
-	ret = dev->i2c_write(dev->priv_dev, 0xf1, 0x19);
-	if (ret < 0)
-		return -EINVAL;
-
-	ret = dev->i2c_write(dev->priv_dev, 0xf2, c_table[index*3]);
-	if (ret < 0)
-		return -EINVAL;
-
-	ret = dev->i2c_write(dev->priv_dev, 0xf3, c_table[index*3+1]);
-	if (ret < 0)
-		return -EINVAL;
-
-	ret = dev->i2c_write(dev->priv_dev, 0xf4, c_table[index*3+2]);
-	if (ret < 0)
-		return -EINVAL;
-
-	ret = dev->i2c_write(dev->priv_dev, 0xf5, 0xae);
-	if (ret < 0)
-		return -EINVAL;
-
-	ret = dev->i2c_write(dev->priv_dev, 0xf6, 0xb7);
-	if (ret < 0)
-		return -EINVAL;
-
-	ret = dev->i2c_write(dev->priv_dev, 0xf7, 0xba);
-	if (ret < 0)
-		return -EINVAL;
-
-	ret = dev->i2c_write(dev->priv_dev, 0xf8, 0xd7);
-	if (ret < 0)
-		return -EINVAL;
-
-	ret = dev->i2c_write(dev->priv_dev, 0x68, 0x0a);
-	if (ret < 0)
-		return -EINVAL;
-
-	ret = dev->i2c_write(dev->priv_dev, 0x69, 0x09);
-	if (ret < 0)
-		return -EINVAL;
-
-	dev->i2c_write(dev->priv_dev, 0x01, 0x40);
-	return 0;
-}
-
-static int s921_isdb_get_status(struct s921_isdb_t *dev, void *data) {
-	unsigned int *ret = (unsigned int*)data;
-	u8 ifagc_dt;
-	u8 rfagc_dt;
-
-	mdelay(10);
-	ifagc_dt = dev->i2c_read(dev->priv_dev, 0x81);
-	rfagc_dt = dev->i2c_read(dev->priv_dev, 0x82);
-	if (rfagc_dt == 0x40) {
-		*ret = 1;
-	}
-	return 0;
-}
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/dvb/frontends/s921_core.h linux-libre-2.6.38-gnu1/drivers/media/dvb/frontends/s921_core.h
--- linux-libre-2.6.37-gnu1/drivers/media/dvb/frontends/s921_core.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/dvb/frontends/s921_core.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,114 +0,0 @@
-#ifndef _S921_CORE_H
-#define _S921_CORE_H
-//#define u8 unsigned int
-//#define u32 unsigned int
-
-
-
-//#define EINVAL -1
-#define E_OK 0
-
-struct s921_isdb_t {
-	void *priv_dev;
-	int (*i2c_write)(void *dev, u8 reg, u8 val);
-	int (*i2c_read)(void *dev, u8 reg);
-};
-
-#define ISDB_T_CMD_INIT       0
-#define ISDB_T_CMD_SET_PARAM  1
-#define ISDB_T_CMD_TUNE       2
-#define ISDB_T_CMD_GET_STATUS 3
-
-struct s921_isdb_t_tune_params {
-	u32 frequency;
-};
-
-struct s921_isdb_t_status {
-};
-
-struct s921_isdb_t_transmission_mode_params {
-	u8 mode;
-	u8 layer_a_mode;
-#define ISDB_T_LA_MODE_1 0
-#define ISDB_T_LA_MODE_2 1
-#define ISDB_T_LA_MODE_3 2
-	u8 layer_a_carrier_modulation;
-#define ISDB_T_LA_CM_DQPSK 0
-#define ISDB_T_LA_CM_QPSK  1
-#define ISDB_T_LA_CM_16QAM 2
-#define ISDB_T_LA_CM_64QAM 3
-#define ISDB_T_LA_CM_NOLAYER 4
-	u8 layer_a_code_rate;
-#define ISDB_T_LA_CR_1_2   0
-#define ISDB_T_LA_CR_2_3   1
-#define ISDB_T_LA_CR_3_4   2
-#define ISDB_T_LA_CR_5_6   4
-#define ISDB_T_LA_CR_7_8   8
-#define ISDB_T_LA_CR_NOLAYER   16
-	u8 layer_a_time_interleave;
-#define ISDB_T_LA_TI_0  0
-#define ISDB_T_LA_TI_1  1
-#define ISDB_T_LA_TI_2  2
-#define ISDB_T_LA_TI_4  4
-#define ISDB_T_LA_TI_8  8
-#define ISDB_T_LA_TI_16 16
-#define ISDB_T_LA_TI_32 32
-	u8 layer_a_nseg;
-
-	u8 layer_b_mode;
-#define ISDB_T_LB_MODE_1 0
-#define ISDB_T_LB_MODE_2 1
-#define ISDB_T_LB_MODE_3 2
-	u8 layer_b_carrier_modulation;
-#define ISDB_T_LB_CM_DQPSK 0
-#define ISDB_T_LB_CM_QPSK  1
-#define ISDB_T_LB_CM_16QAM 2
-#define ISDB_T_LB_CM_64QAM 3
-#define ISDB_T_LB_CM_NOLAYER 4
-	u8 layer_b_code_rate;
-#define ISDB_T_LB_CR_1_2   0
-#define ISDB_T_LB_CR_2_3   1
-#define ISDB_T_LB_CR_3_4   2
-#define ISDB_T_LB_CR_5_6   4
-#define ISDB_T_LB_CR_7_8   8
-#define ISDB_T_LB_CR_NOLAYER   16
-	u8 layer_b_time_interleave;
-#define ISDB_T_LB_TI_0  0
-#define ISDB_T_LB_TI_1  1
-#define ISDB_T_LB_TI_2  2
-#define ISDB_T_LB_TI_4  4
-#define ISDB_T_LB_TI_8  8
-#define ISDB_T_LB_TI_16 16
-#define ISDB_T_LB_TI_32 32
-	u8 layer_b_nseg;
-
-	u8 layer_c_mode;
-#define ISDB_T_LC_MODE_1 0
-#define ISDB_T_LC_MODE_2 1
-#define ISDB_T_LC_MODE_3 2
-	u8 layer_c_carrier_modulation;
-#define ISDB_T_LC_CM_DQPSK 0
-#define ISDB_T_LC_CM_QPSK  1
-#define ISDB_T_LC_CM_16QAM 2
-#define ISDB_T_LC_CM_64QAM 3
-#define ISDB_T_LC_CM_NOLAYER 4
-	u8 layer_c_code_rate;
-#define ISDB_T_LC_CR_1_2   0
-#define ISDB_T_LC_CR_2_3   1
-#define ISDB_T_LC_CR_3_4   2
-#define ISDB_T_LC_CR_5_6   4
-#define ISDB_T_LC_CR_7_8   8
-#define ISDB_T_LC_CR_NOLAYER   16
-	u8 layer_c_time_interleave;
-#define ISDB_T_LC_TI_0  0
-#define ISDB_T_LC_TI_1  1
-#define ISDB_T_LC_TI_2  2
-#define ISDB_T_LC_TI_4  4
-#define ISDB_T_LC_TI_8  8
-#define ISDB_T_LC_TI_16 16
-#define ISDB_T_LC_TI_32 32
-	u8 layer_c_nseg;
-};
-
-int s921_isdb_cmd(struct s921_isdb_t *dev, u32 cmd, void *data);
-#endif
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/dvb/frontends/s921.h linux-libre-2.6.38-gnu1/drivers/media/dvb/frontends/s921.h
--- linux-libre-2.6.37-gnu1/drivers/media/dvb/frontends/s921.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/dvb/frontends/s921.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,47 @@
+/*
+ *   Sharp s921 driver
+ *
+ *   Copyright (C) 2009 Mauro Carvalho Chehab <mchehab@redhat.com>
+ *   Copyright (C) 2009 Douglas Landgraf <dougsland@redhat.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.
+ *
+ *   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 S921_H
+#define S921_H
+
+#include <linux/dvb/frontend.h>
+
+struct s921_config {
+	/* the demodulator's i2c address */
+	u8 demod_address;
+};
+
+#if defined(CONFIG_DVB_S921) || (defined(CONFIG_DVB_S921_MODULE) \
+	&& defined(MODULE))
+extern struct dvb_frontend *s921_attach(const struct s921_config *config,
+					   struct i2c_adapter *i2c);
+extern struct i2c_adapter *s921_get_tuner_i2c_adapter(struct dvb_frontend *);
+#else
+static inline struct dvb_frontend *s921_attach(
+	const struct s921_config *config, struct i2c_adapter *i2c)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+static struct i2c_adapter *
+	s921_get_tuner_i2c_adapter(struct dvb_frontend *fe)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+#endif
+
+#endif /* S921_H */
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/dvb/frontends/s921_module.c linux-libre-2.6.38-gnu1/drivers/media/dvb/frontends/s921_module.c
--- linux-libre-2.6.37-gnu1/drivers/media/dvb/frontends/s921_module.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/dvb/frontends/s921_module.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,192 +0,0 @@
-/*
- * Driver for Sharp s921 driver
- *
- * Copyright (C) 2008 Markus Rechberger <mrechberger@sundtek.de>
- *
- * All rights reserved.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include "dvb_frontend.h"
-#include "s921_module.h"
-#include "s921_core.h"
-
-static  unsigned int debug = 0;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug,"s921 debugging (default off)");
-
-#define dprintk(fmt, args...) if (debug) do {\
-			printk("s921 debug: " fmt, ##args); } while (0)
-
-struct s921_state
-{
-	struct dvb_frontend frontend;
-	fe_modulation_t current_modulation;
-	__u32 snr;
-	__u32 current_frequency;
-	__u8 addr;
-	struct s921_isdb_t dev;
-	struct i2c_adapter *i2c;
-};
-
-static int s921_set_parameters(struct dvb_frontend *fe, struct dvb_frontend_parameters *param) {
-	struct s921_state *state = (struct s921_state *)fe->demodulator_priv;
-	struct s921_isdb_t_transmission_mode_params params;
-	struct s921_isdb_t_tune_params tune_params;
-
-	tune_params.frequency = param->frequency;
-	s921_isdb_cmd(&state->dev, ISDB_T_CMD_SET_PARAM, &params);
-	s921_isdb_cmd(&state->dev, ISDB_T_CMD_TUNE, &tune_params);
-	mdelay(100);
-	return 0;
-}
-
-static int s921_init(struct dvb_frontend *fe) {
-	printk("s921 init\n");
-	return 0;
-}
-
-static int s921_sleep(struct dvb_frontend *fe) {
-	printk("s921 sleep\n");
-	return 0;
-}
-
-static int s921_read_status(struct dvb_frontend *fe, fe_status_t *status)
-{
-	struct s921_state *state = (struct s921_state *)fe->demodulator_priv;
-	unsigned int ret;
-	mdelay(5);
-	s921_isdb_cmd(&state->dev, ISDB_T_CMD_GET_STATUS, &ret);
-	*status = 0;
-
-	printk("status: %02x\n", ret);
-	if (ret == 1) {
-		*status |= FE_HAS_CARRIER;
-		*status |= FE_HAS_VITERBI;
-		*status |= FE_HAS_LOCK;
-		*status |= FE_HAS_SYNC;
-		*status |= FE_HAS_SIGNAL;
-	}
-
-	return 0;
-}
-
-static int s921_read_ber(struct dvb_frontend *fe, __u32 *ber)
-{
-	dprintk("read ber\n");
-	return 0;
-}
-
-static int s921_read_snr(struct dvb_frontend *fe, __u16 *snr)
-{
-	dprintk("read snr\n");
-	return 0;
-}
-
-static int s921_read_ucblocks(struct dvb_frontend *fe, __u32 *ucblocks)
-{
-	dprintk("read ucblocks\n");
-	return 0;
-}
-
-static void s921_release(struct dvb_frontend *fe)
-{
-	struct s921_state *state = (struct s921_state *)fe->demodulator_priv;
-	kfree(state);
-}
-
-static struct dvb_frontend_ops demod_s921={
-	.info = {
-		.name			= "SHARP S921",
-		.type			= FE_OFDM,
-		.frequency_min		= 473143000,
-		.frequency_max		= 767143000,
-		.frequency_stepsize	=   6000000,
-		.frequency_tolerance	= 0,
-		.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_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO |
-			FE_CAN_HIERARCHY_AUTO | FE_CAN_RECOVER |
-			FE_CAN_MUTE_TS
-	},
-	.init = s921_init,
-	.sleep = s921_sleep,
-	.set_frontend = s921_set_parameters,
-	.read_snr = s921_read_snr,
-	.read_ber = s921_read_ber,
-	.read_status = s921_read_status,
-	.read_ucblocks = s921_read_ucblocks,
-	.release = s921_release,
-};
-
-static int s921_write(void *dev, u8 reg, u8 val) {
-	struct s921_state *state = dev;
-	char buf[2]={reg,val};
-	int err;
-	struct i2c_msg i2cmsgs = {
-		.addr = state->addr,
-		.flags = 0,
-		.len = 2,
-		.buf = buf
-	};
-
-	if((err = i2c_transfer(state->i2c, &i2cmsgs, 1))<0) {
-		printk("%s i2c_transfer error %d\n", __func__, err);
-		if (err < 0)
-			return err;
-		else
-			return -EREMOTEIO;
-	}
-
-	return 0;
-}
-
-static int s921_read(void *dev, u8 reg) {
-	struct s921_state *state = dev;
-	u8 b1;
-	int ret;
-	struct i2c_msg msg[2] = { { .addr = state->addr,
-				    .flags = 0,
-				    .buf = &reg, .len = 1 },
-				  { .addr = state->addr,
-				    .flags = I2C_M_RD,
-				    .buf = &b1, .len = 1 } };
-
-	ret = i2c_transfer(state->i2c, msg, 2);
-	if (ret != 2)
-		return ret;
-	return b1;
-}
-
-struct dvb_frontend* s921_attach(const struct s921_config *config,
-					   struct i2c_adapter *i2c)
-{
-
-	struct s921_state *state;
-	state = kzalloc(sizeof(struct s921_state), GFP_KERNEL);
-	if (state == NULL)
-		return NULL;
-
-	state->addr = config->i2c_address;
-	state->i2c = i2c;
-	state->dev.i2c_write = &s921_write;
-	state->dev.i2c_read = &s921_read;
-	state->dev.priv_dev = state;
-
-	s921_isdb_cmd(&state->dev, ISDB_T_CMD_INIT, NULL);
-
-	memcpy(&state->frontend.ops, &demod_s921, sizeof(struct dvb_frontend_ops));
-	state->frontend.demodulator_priv = state;
-	return &state->frontend;
-}
-
-EXPORT_SYMBOL_GPL(s921_attach);
-MODULE_AUTHOR("Markus Rechberger <mrechberger@empiatech.com>");
-MODULE_DESCRIPTION("Sharp S921 ISDB-T 1Seg");
-MODULE_LICENSE("GPL");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/dvb/frontends/s921_module.h linux-libre-2.6.38-gnu1/drivers/media/dvb/frontends/s921_module.h
--- linux-libre-2.6.37-gnu1/drivers/media/dvb/frontends/s921_module.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/dvb/frontends/s921_module.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,49 +0,0 @@
-/*
- *  Driver for DVB-T s921 demodulator
- *
- *  Copyright (C) 2008 Markus Rechberger <mrechberger@sundtek.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., 675 Mass Ave, Cambridge, MA 02139, USA.=
- */
-
-#ifndef S921_MODULE_H
-#define S921_MODULE_H
-
-#include <linux/dvb/frontend.h>
-#include "s921_core.h"
-
-int s921_isdb_init(struct s921_isdb_t *dev);
-int s921_isdb_cmd(struct s921_isdb_t *dev, u32 cmd, void *data);
-
-struct s921_config
-{
-	/* demodulator's I2C address */
-	u8 i2c_address;
-};
-
-#if defined(CONFIG_DVB_S921) || (defined(CONFIG_DVB_S921_MODULE) && defined(MODULE))
-extern struct dvb_frontend* s921_attach(const struct s921_config *config,
-					   struct i2c_adapter *i2c);
-#else
-static inline struct dvb_frontend* s921_attach(const struct s921_config *config,
-					   struct i2c_adapter *i2c)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-#endif /* CONFIG_DVB_S921 */
-
-#endif /* S921_H */
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/dvb/frontends/stb0899_drv.c linux-libre-2.6.38-gnu1/drivers/media/dvb/frontends/stb0899_drv.c
--- linux-libre-2.6.37-gnu1/drivers/media/dvb/frontends/stb0899_drv.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/dvb/frontends/stb0899_drv.c	2011-03-14 21:20:32.000000000 -0400
@@ -714,7 +714,7 @@ static int stb0899_send_diseqc_msg(struc
 	reg = stb0899_read_reg(state, STB0899_DISCNTRL1);
 	STB0899_SETFIELD_VAL(DISPRECHARGE, reg, 0);
 	stb0899_write_reg(state, STB0899_DISCNTRL1, reg);
-
+	msleep(100);
 	return 0;
 }
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/dvb/frontends/stb6100.c linux-libre-2.6.38-gnu1/drivers/media/dvb/frontends/stb6100.c
--- linux-libre-2.6.37-gnu1/drivers/media/dvb/frontends/stb6100.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/dvb/frontends/stb6100.c	2011-03-14 21:20:32.000000000 -0400
@@ -51,7 +51,7 @@ module_param(verbose, int, 0644);
 		if (x > y)								\
 			printk(format, ##arg);						\
 	}										\
-} while(0)
+} while (0)
 
 struct stb6100_lkup {
 	u32 val_low;
@@ -117,7 +117,10 @@ static const struct stb6100_regmask stb6
 	[STB6100_TEST3]		= { 0x00, 0xde },
 };
 
-static void stb6100_normalise_regs(u8 regs[])
+/*
+ * Currently unused. Some boards might need it in the future
+ */
+static inline void stb6100_normalise_regs(u8 regs[])
 {
 	int i;
 
@@ -157,13 +160,25 @@ static int stb6100_read_reg(struct stb61
 	u8 regs[STB6100_NUMREGS];
 	int rc;
 
+	struct i2c_msg msg = {
+		.addr	= state->config->tuner_address + reg,
+		.flags	= I2C_M_RD,
+		.buf	= regs,
+		.len	= 1
+	};
+
+	rc = i2c_transfer(state->i2c, &msg, 1);
+
 	if (unlikely(reg >= STB6100_NUMREGS)) {
 		dprintk(verbose, FE_ERROR, 1, "Invalid register offset 0x%x", reg);
 		return -EINVAL;
 	}
-	if ((rc = stb6100_read_regs(state, regs)) < 0)
-		return rc;
-	return (unsigned int)regs[reg];
+	if (unlikely(verbose > FE_DEBUG)) {
+		dprintk(verbose, FE_DEBUG, 1, "    Read from 0x%02x", state->config->tuner_address);
+		dprintk(verbose, FE_DEBUG, 1, "        %s: 0x%02x", stb6100_regnames[reg], regs[0]);
+	}
+
+	return (unsigned int)regs[0];
 }
 
 static int stb6100_write_reg_range(struct stb6100_state *state, u8 buf[], int start, int len)
@@ -211,20 +226,17 @@ static int stb6100_write_reg(struct stb6
 	return stb6100_write_reg_range(state, &data, reg, 1);
 }
 
-static int stb6100_write_regs(struct stb6100_state *state, u8 regs[])
-{
-	stb6100_normalise_regs(regs);
-	return stb6100_write_reg_range(state, &regs[1], 1, STB6100_NUMREGS - 1);
-}
 
 static int stb6100_get_status(struct dvb_frontend *fe, u32 *status)
 {
 	int rc;
 	struct stb6100_state *state = fe->tuner_priv;
 
-	if ((rc = stb6100_read_reg(state, STB6100_LD)) < 0)
+	rc = stb6100_read_reg(state, STB6100_LD);
+	if (rc < 0) {
+		dprintk(verbose, FE_ERROR, 1, "%s failed", __func__);
 		return rc;
-
+	}
 	return (rc & STB6100_LD_LOCK) ? TUNER_STATUS_LOCKED : 0;
 }
 
@@ -234,7 +246,8 @@ static int stb6100_get_bandwidth(struct
 	u8 f;
 	struct stb6100_state *state = fe->tuner_priv;
 
-	if ((rc = stb6100_read_reg(state, STB6100_F)) < 0)
+	rc = stb6100_read_reg(state, STB6100_F);
+	if (rc < 0)
 		return rc;
 	f = rc & STB6100_F_F;
 
@@ -265,14 +278,21 @@ static int stb6100_set_bandwidth(struct
 	/* Turn on LPF bandwidth setting clock control,
 	 * set bandwidth, wait 10ms, turn off.
 	 */
-	if ((rc = stb6100_write_reg(state, STB6100_FCCK, 0x0d | STB6100_FCCK_FCCK)) < 0)
+	rc = stb6100_write_reg(state, STB6100_FCCK, 0x0d | STB6100_FCCK_FCCK);
+	if (rc < 0)
 		return rc;
-	if ((rc = stb6100_write_reg(state, STB6100_F, 0xc0 | tmp)) < 0)
+	rc = stb6100_write_reg(state, STB6100_F, 0xc0 | tmp);
+	if (rc < 0)
 		return rc;
-	msleep(1);
-	if ((rc = stb6100_write_reg(state, STB6100_FCCK, 0x0d)) < 0)
+
+	msleep(5);  /*  This is dangerous as another (related) thread may start */
+
+	rc = stb6100_write_reg(state, STB6100_FCCK, 0x0d);
+	if (rc < 0)
 		return rc;
 
+	msleep(10);  /*  This is dangerous as another (related) thread may start */
+
 	return 0;
 }
 
@@ -284,7 +304,8 @@ static int stb6100_get_frequency(struct
 	struct stb6100_state *state = fe->tuner_priv;
 	u8 regs[STB6100_NUMREGS];
 
-	if ((rc = stb6100_read_regs(state, regs)) < 0)
+	rc = stb6100_read_regs(state, regs);
+	if (rc < 0)
 		return rc;
 
 	odiv = (regs[STB6100_VCO] & STB6100_VCO_ODIV) >> STB6100_VCO_ODIV_SHIFT;
@@ -312,8 +333,7 @@ static int stb6100_set_frequency(struct
 	u8 regs[STB6100_NUMREGS];
 	u8 g, psd2, odiv;
 
-	if ((rc = stb6100_read_regs(state, regs)) < 0)
-		return rc;
+	dprintk(verbose, FE_DEBUG, 1, "Version 2010-8-14 13:51");
 
 	if (fe->ops.get_frontend) {
 		dprintk(verbose, FE_DEBUG, 1, "Get frontend parameters");
@@ -321,96 +341,140 @@ static int stb6100_set_frequency(struct
 	}
 	srate = p.u.qpsk.symbol_rate;
 
-	regs[STB6100_DLB] = 0xdc;
-	/* Disable LPEN */
-	regs[STB6100_LPEN] &= ~STB6100_LPEN_LPEN; /* PLL Loop disabled */
+	/* Set up tuner cleanly, LPF calibration on */
+	rc = stb6100_write_reg(state, STB6100_FCCK, 0x4d | STB6100_FCCK_FCCK);
+	if (rc < 0)
+		return rc;  /* allow LPF calibration */
 
-	if ((rc = stb6100_write_regs(state, regs)) < 0)
+	/* PLL Loop disabled, bias on, VCO on, synth on */
+	regs[STB6100_LPEN] = 0xeb;
+	rc = stb6100_write_reg(state, STB6100_LPEN, regs[STB6100_LPEN]);
+	if (rc < 0)
 		return rc;
 
-	/* Baseband gain.	*/
-	if (srate >= 15000000)
-		g = 9;  //  +4 dB
-	else if (srate >= 5000000)
-		g = 11; //  +8 dB
-	else
-		g = 14; // +14 dB
-
-	regs[STB6100_G] = (regs[STB6100_G] & ~STB6100_G_G) | g;
-	regs[STB6100_G] &= ~STB6100_G_GCT; /* mask GCT */
-	regs[STB6100_G] |= (1 << 5); /* 2Vp-p Mode */
+	/* Program the registers with their data values */
 
 	/* VCO divide ratio (LO divide ratio, VCO prescaler enable).	*/
 	if (frequency <= 1075000)
 		odiv = 1;
 	else
 		odiv = 0;
-	regs[STB6100_VCO] = (regs[STB6100_VCO] & ~STB6100_VCO_ODIV) | (odiv << STB6100_VCO_ODIV_SHIFT);
 
-	if ((frequency > 1075000) && (frequency <= 1325000))
-		psd2 = 0;
-	else
-		psd2 = 1;
-	regs[STB6100_K] = (regs[STB6100_K] & ~STB6100_K_PSD2) | (psd2 << STB6100_K_PSD2_SHIFT);
+	/* VCO enabled, seach clock off as per LL3.7, 3.4.1 */
+	regs[STB6100_VCO] = 0xe0 | (odiv << STB6100_VCO_ODIV_SHIFT);
 
 	/* OSM	*/
 	for (ptr = lkup;
 	     (ptr->val_high != 0) && !CHKRANGE(frequency, ptr->val_low, ptr->val_high);
 	     ptr++);
+
 	if (ptr->val_high == 0) {
 		printk(KERN_ERR "%s: frequency out of range: %u kHz\n", __func__, frequency);
 		return -EINVAL;
 	}
 	regs[STB6100_VCO] = (regs[STB6100_VCO] & ~STB6100_VCO_OSM) | ptr->reg;
+	rc = stb6100_write_reg(state, STB6100_VCO, regs[STB6100_VCO]);
+	if (rc < 0)
+		return rc;
 
+	if ((frequency > 1075000) && (frequency <= 1325000))
+		psd2 = 0;
+	else
+		psd2 = 1;
 	/* F(VCO) = F(LO) * (ODIV == 0 ? 2 : 4)			*/
 	fvco = frequency << (1 + odiv);
 	/* N(I) = floor(f(VCO) / (f(XTAL) * (PSD2 ? 2 : 1)))	*/
 	nint = fvco / (state->reference << psd2);
 	/* N(F) = round(f(VCO) / f(XTAL) * (PSD2 ? 2 : 1) - N(I)) * 2 ^ 9	*/
 	nfrac = DIV_ROUND_CLOSEST((fvco - (nint * state->reference << psd2))
-					 << (9 - psd2),
-				  state->reference);
+					 << (9 - psd2), state->reference);
+
+	/* NI */
+	regs[STB6100_NI] = nint;
+	rc = stb6100_write_reg(state, STB6100_NI, regs[STB6100_NI]);
+	if (rc < 0)
+		return rc;
+
+	/* NF */
+	regs[STB6100_NF_LSB] = nfrac;
+	rc = stb6100_write_reg(state, STB6100_NF_LSB, regs[STB6100_NF_LSB]);
+	if (rc < 0)
+		return rc;
+
+	/* K */
+	regs[STB6100_K] = (0x38 & ~STB6100_K_PSD2) | (psd2 << STB6100_K_PSD2_SHIFT);
+	regs[STB6100_K] = (regs[STB6100_K] & ~STB6100_K_NF_MSB) | ((nfrac >> 8) & STB6100_K_NF_MSB);
+	rc = stb6100_write_reg(state, STB6100_K, regs[STB6100_K]);
+	if (rc < 0)
+		return rc;
+
+	/* G Baseband gain. */
+	if (srate >= 15000000)
+		g = 9;  /*  +4 dB */
+	else if (srate >= 5000000)
+		g = 11; /*  +8 dB */
+	else
+		g = 14; /* +14 dB */
+
+	regs[STB6100_G] = (0x10 & ~STB6100_G_G) | g;
+	regs[STB6100_G] &= ~STB6100_G_GCT; /* mask GCT */
+	regs[STB6100_G] |= (1 << 5); /* 2Vp-p Mode */
+	rc = stb6100_write_reg(state, STB6100_G, regs[STB6100_G]);
+	if (rc < 0)
+		return rc;
+
+	/* F we don't write as it is set up in BW set */
+
+	/* DLB set DC servo loop BW to 160Hz (LLA 3.8 / 2.1) */
+	regs[STB6100_DLB] = 0xcc;
+	rc = stb6100_write_reg(state, STB6100_DLB, regs[STB6100_DLB]);
+	if (rc < 0)
+		return rc;
+
 	dprintk(verbose, FE_DEBUG, 1,
 		"frequency = %u, srate = %u, g = %u, odiv = %u, psd2 = %u, fxtal = %u, osm = %u, fvco = %u, N(I) = %u, N(F) = %u",
 		frequency, srate, (unsigned int)g, (unsigned int)odiv,
 		(unsigned int)psd2, state->reference,
 		ptr->reg, fvco, nint, nfrac);
-	regs[STB6100_NI] = nint;
-	regs[STB6100_NF_LSB] = nfrac;
-	regs[STB6100_K] = (regs[STB6100_K] & ~STB6100_K_NF_MSB) | ((nfrac >> 8) & STB6100_K_NF_MSB);
-	regs[STB6100_VCO] |= STB6100_VCO_OSCH;		/* VCO search enabled		*/
-	regs[STB6100_VCO] |= STB6100_VCO_OCK;		/* VCO search clock off		*/
-	regs[STB6100_FCCK] |= STB6100_FCCK_FCCK;	/* LPF BW setting clock enabled	*/
-	regs[STB6100_LPEN] &= ~STB6100_LPEN_LPEN;	/* PLL loop disabled		*/
-	/* Power up. */
-	regs[STB6100_LPEN] |= STB6100_LPEN_SYNP	| STB6100_LPEN_OSCP | STB6100_LPEN_BEN;
 
-	msleep(2);
-	if ((rc = stb6100_write_regs(state, regs)) < 0)
+	/* Set up the test registers */
+	regs[STB6100_TEST1] = 0x8f;
+	rc = stb6100_write_reg(state, STB6100_TEST1, regs[STB6100_TEST1]);
+	if (rc < 0)
+		return rc;
+	regs[STB6100_TEST3] = 0xde;
+	rc = stb6100_write_reg(state, STB6100_TEST3, regs[STB6100_TEST3]);
+	if (rc < 0)
 		return rc;
 
-	msleep(2);
-	regs[STB6100_LPEN] |= STB6100_LPEN_LPEN;	/* PLL loop enabled		*/
-	if ((rc = stb6100_write_reg(state, STB6100_LPEN, regs[STB6100_LPEN])) < 0)
+	/* Bring up tuner according to LLA 3.7 3.4.1, step 2 */
+	regs[STB6100_LPEN] = 0xfb; /* PLL Loop enabled, bias on, VCO on, synth on */
+	rc = stb6100_write_reg(state, STB6100_LPEN, regs[STB6100_LPEN]);
+	if (rc < 0)
 		return rc;
 
+	msleep(2);
+
+	/* Bring up tuner according to LLA 3.7 3.4.1, step 3 */
 	regs[STB6100_VCO] &= ~STB6100_VCO_OCK;		/* VCO fast search		*/
-	if ((rc = stb6100_write_reg(state, STB6100_VCO, regs[STB6100_VCO])) < 0)
+	rc = stb6100_write_reg(state, STB6100_VCO, regs[STB6100_VCO]);
+	if (rc < 0)
 		return rc;
 
-	msleep(10);					/* wait for LO to lock		*/
+	msleep(10);  /*  This is dangerous as another (related) thread may start */ /* wait for LO to lock */
+
 	regs[STB6100_VCO] &= ~STB6100_VCO_OSCH;		/* vco search disabled		*/
 	regs[STB6100_VCO] |= STB6100_VCO_OCK;		/* search clock off		*/
-	if ((rc = stb6100_write_reg(state, STB6100_VCO, regs[STB6100_VCO])) < 0)
-		return rc;
-	regs[STB6100_FCCK] &= ~STB6100_FCCK_FCCK;       /* LPF BW clock disabled	*/
-	stb6100_normalise_regs(regs);
-	if ((rc = stb6100_write_reg_range(state, &regs[1], 1, STB6100_NUMREGS - 3)) < 0)
+	rc = stb6100_write_reg(state, STB6100_VCO, regs[STB6100_VCO]);
+	if (rc < 0)
 		return rc;
 
-	msleep(100);
+	rc = stb6100_write_reg(state, STB6100_FCCK, 0x0d);
+	if (rc < 0)
+		return rc;  /* Stop LPF calibration */
 
+	msleep(10);  /*  This is dangerous as another (related) thread may start */
+		     /* wait for stabilisation, (should not be necessary)		*/
 	return 0;
 }
 
@@ -433,8 +497,8 @@ static int stb6100_init(struct dvb_front
 	state->bandwidth	= status->bandwidth * 1000;	/* Hz	*/
 	state->reference	= status->refclock / 1000;	/* kHz	*/
 
-	/* Set default bandwidth.	*/
-	return stb6100_set_bandwidth(fe, state->bandwidth);
+	/* Set default bandwidth. Modified, PN 13-May-10	*/
+	return 0;
 }
 
 static int stb6100_get_state(struct dvb_frontend *fe,
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/dvb/frontends/stv090x.c linux-libre-2.6.38-gnu1/drivers/media/dvb/frontends/stv090x.c
--- linux-libre-2.6.37-gnu1/drivers/media/dvb/frontends/stv090x.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/dvb/frontends/stv090x.c	2011-03-14 21:20:32.000000000 -0400
@@ -1483,8 +1483,8 @@ static int stv090x_start_search(struct s
 		if (STV090x_WRITE_DEMOD(state, FFECFG, 0x41) < 0)
 			goto err;
 
-		if ((state->search_mode == STV090x_DVBS1)	||
-			(state->search_mode == STV090x_DSS)	||
+		if ((state->search_mode == STV090x_SEARCH_DVBS1)	||
+			(state->search_mode == STV090x_SEARCH_DSS)	||
 			(state->search_mode == STV090x_SEARCH_AUTO)) {
 
 			if (STV090x_WRITE_DEMOD(state, VITSCALE, 0x82) < 0)
@@ -2940,7 +2940,7 @@ static int stv090x_optimize_track(struct
 		STV090x_WRITE_DEMOD(state, ERRCTRL1, 0x67); /* PER */
 		break;
 
-	case STV090x_UNKNOWN:
+	case STV090x_ERROR:
 	default:
 		reg = STV090x_READ_DEMOD(state, DMDCFGMD);
 		STV090x_SETFIELD_Px(reg, DVBS1_ENABLE_FIELD, 1);
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/dvb/mantis/hopper_cards.c linux-libre-2.6.38-gnu1/drivers/media/dvb/mantis/hopper_cards.c
--- linux-libre-2.6.37-gnu1/drivers/media/dvb/mantis/hopper_cards.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/dvb/mantis/hopper_cards.c	2011-03-14 21:20:32.000000000 -0400
@@ -251,6 +251,8 @@ static struct pci_device_id hopper_pci_t
 	{ }
 };
 
+MODULE_DEVICE_TABLE(pci, hopper_pci_table);
+
 static struct pci_driver hopper_pci_driver = {
 	.name		= DRIVER_NAME,
 	.id_table	= hopper_pci_table,
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/dvb/mantis/hopper_vp3028.c linux-libre-2.6.38-gnu1/drivers/media/dvb/mantis/hopper_vp3028.c
--- linux-libre-2.6.37-gnu1/drivers/media/dvb/mantis/hopper_vp3028.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/dvb/mantis/hopper_vp3028.c	2011-03-14 21:20:32.000000000 -0400
@@ -47,17 +47,17 @@ static int vp3028_frontend_init(struct m
 	struct mantis_hwconfig *config	= mantis->hwconfig;
 	int err = 0;
 
-	gpio_set_bits(mantis, config->reset, 0);
+	mantis_gpio_set_bits(mantis, config->reset, 0);
 	msleep(100);
 	err = mantis_frontend_power(mantis, POWER_ON);
 	msleep(100);
-	gpio_set_bits(mantis, config->reset, 1);
+	mantis_gpio_set_bits(mantis, config->reset, 1);
 
 	err = mantis_frontend_power(mantis, POWER_ON);
 	if (err == 0) {
 		msleep(250);
 		dprintk(MANTIS_ERROR, 1, "Probing for 10353 (DVB-T)");
-		fe = zl10353_attach(&hopper_vp3028_config, adapter);
+		fe = dvb_attach(zl10353_attach, &hopper_vp3028_config, adapter);
 
 		if (!fe)
 			return -1;
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/dvb/mantis/Kconfig linux-libre-2.6.38-gnu1/drivers/media/dvb/mantis/Kconfig
--- linux-libre-2.6.37-gnu1/drivers/media/dvb/mantis/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/dvb/mantis/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -1,6 +1,6 @@
 config MANTIS_CORE
 	tristate "Mantis/Hopper PCI bridge based devices"
-	depends on PCI && I2C && INPUT && IR_CORE
+	depends on PCI && I2C && INPUT && RC_CORE
 
 	help
 	  Support for PCI cards based on the Mantis and Hopper PCi bridge.
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/dvb/mantis/mantis_cards.c linux-libre-2.6.38-gnu1/drivers/media/dvb/mantis/mantis_cards.c
--- linux-libre-2.6.37-gnu1/drivers/media/dvb/mantis/mantis_cards.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/dvb/mantis/mantis_cards.c	2011-03-14 21:20:32.000000000 -0400
@@ -281,6 +281,8 @@ static struct pci_device_id mantis_pci_t
 	{ }
 };
 
+MODULE_DEVICE_TABLE(pci, mantis_pci_table);
+
 static struct pci_driver mantis_pci_driver = {
 	.name		= DRIVER_NAME,
 	.id_table	= mantis_pci_table,
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/dvb/mantis/mantis_common.h linux-libre-2.6.38-gnu1/drivers/media/dvb/mantis/mantis_common.h
--- linux-libre-2.6.37-gnu1/drivers/media/dvb/mantis/mantis_common.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/dvb/mantis/mantis_common.h	2011-03-14 21:20:32.000000000 -0400
@@ -171,7 +171,9 @@ struct mantis_pci {
 	struct work_struct	uart_work;
 	spinlock_t		uart_lock;
 
-	struct input_dev	*rc;
+	struct rc_dev		*rc;
+	char			input_name[80];
+	char			input_phys[80];
 };
 
 #define MANTIS_HIF_STATUS	(mantis->gpio_status)
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/dvb/mantis/mantis_dvb.c linux-libre-2.6.38-gnu1/drivers/media/dvb/mantis/mantis_dvb.c
--- linux-libre-2.6.37-gnu1/drivers/media/dvb/mantis/mantis_dvb.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/dvb/mantis/mantis_dvb.c	2011-03-14 21:20:32.000000000 -0400
@@ -47,15 +47,15 @@ int mantis_frontend_power(struct mantis_
 	switch (power) {
 	case POWER_ON:
 		dprintk(MANTIS_DEBUG, 1, "Power ON");
-		gpio_set_bits(mantis, config->power, POWER_ON);
+		mantis_gpio_set_bits(mantis, config->power, POWER_ON);
 		msleep(100);
-		gpio_set_bits(mantis, config->power, POWER_ON);
+		mantis_gpio_set_bits(mantis, config->power, POWER_ON);
 		msleep(100);
 		break;
 
 	case POWER_OFF:
 		dprintk(MANTIS_DEBUG, 1, "Power OFF");
-		gpio_set_bits(mantis, config->power, POWER_OFF);
+		mantis_gpio_set_bits(mantis, config->power, POWER_OFF);
 		msleep(100);
 		break;
 
@@ -73,13 +73,13 @@ void mantis_frontend_soft_reset(struct m
 	struct mantis_hwconfig *config = mantis->hwconfig;
 
 	dprintk(MANTIS_DEBUG, 1, "Frontend RESET");
-	gpio_set_bits(mantis, config->reset, 0);
+	mantis_gpio_set_bits(mantis, config->reset, 0);
 	msleep(100);
-	gpio_set_bits(mantis, config->reset, 0);
+	mantis_gpio_set_bits(mantis, config->reset, 0);
 	msleep(100);
-	gpio_set_bits(mantis, config->reset, 1);
+	mantis_gpio_set_bits(mantis, config->reset, 1);
 	msleep(100);
-	gpio_set_bits(mantis, config->reset, 1);
+	mantis_gpio_set_bits(mantis, config->reset, 1);
 	msleep(100);
 
 	return;
@@ -117,6 +117,7 @@ static int mantis_dvb_start_feed(struct
 	if (mantis->feeds == 1)	 {
 		dprintk(MANTIS_DEBUG, 1, "mantis start feed & dma");
 		mantis_dma_start(mantis);
+		tasklet_enable(&mantis->tasklet);
 	}
 
 	return mantis->feeds;
@@ -136,6 +137,7 @@ static int mantis_dvb_stop_feed(struct d
 	mantis->feeds--;
 	if (mantis->feeds == 0) {
 		dprintk(MANTIS_DEBUG, 1, "mantis stop feed and dma");
+		tasklet_disable(&mantis->tasklet);
 		mantis_dma_stop(mantis);
 	}
 
@@ -216,6 +218,7 @@ int __devinit mantis_dvb_init(struct man
 
 	dvb_net_init(&mantis->dvb_adapter, &mantis->dvbnet, &mantis->demux.dmx);
 	tasklet_init(&mantis->tasklet, mantis_dma_xfer, (unsigned long) mantis);
+	tasklet_disable(&mantis->tasklet);
 	if (mantis->hwconfig) {
 		result = config->frontend_init(mantis, mantis->fe);
 		if (result < 0) {
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/dvb/mantis/mantis_evm.c linux-libre-2.6.38-gnu1/drivers/media/dvb/mantis/mantis_evm.c
--- linux-libre-2.6.37-gnu1/drivers/media/dvb/mantis/mantis_evm.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/dvb/mantis/mantis_evm.c	2011-03-14 21:20:32.000000000 -0400
@@ -111,7 +111,7 @@ void mantis_evmgr_exit(struct mantis_ca
 	struct mantis_pci *mantis = ca->ca_priv;
 
 	dprintk(MANTIS_DEBUG, 1, "Mantis Host I/F Event manager exiting");
-	flush_scheduled_work();
+	flush_work_sync(&ca->hif_evm_work);
 	mantis_hif_exit(ca);
 	mantis_pcmcia_exit(ca);
 }
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/dvb/mantis/mantis_input.c linux-libre-2.6.38-gnu1/drivers/media/dvb/mantis/mantis_input.c
--- linux-libre-2.6.37-gnu1/drivers/media/dvb/mantis/mantis_input.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/dvb/mantis/mantis_input.c	2011-03-14 21:20:32.000000000 -0400
@@ -18,8 +18,7 @@
 	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
-#include <linux/input.h>
-#include <media/ir-core.h>
+#include <media/rc-core.h>
 #include <linux/pci.h>
 
 #include "dmxdev.h"
@@ -33,8 +32,9 @@
 #include "mantis_uart.h"
 
 #define MODULE_NAME "mantis_core"
+#define RC_MAP_MANTIS "rc-mantis"
 
-static struct ir_scancode mantis_ir_table[] = {
+static struct rc_map_table mantis_ir_table[] = {
 	{ 0x29, KEY_POWER	},
 	{ 0x28, KEY_FAVORITES	},
 	{ 0x30, KEY_TEXT	},
@@ -95,53 +95,65 @@ static struct ir_scancode mantis_ir_tabl
 	{ 0x00, KEY_BLUE	},
 };
 
-struct ir_scancode_table ir_mantis = {
-	.scan = mantis_ir_table,
-	.size = ARRAY_SIZE(mantis_ir_table),
+static struct rc_map_list ir_mantis_map = {
+	.map = {
+		.scan = mantis_ir_table,
+		.size = ARRAY_SIZE(mantis_ir_table),
+		.rc_type = RC_TYPE_UNKNOWN,
+		.name = RC_MAP_MANTIS,
+	}
 };
-EXPORT_SYMBOL_GPL(ir_mantis);
 
 int mantis_input_init(struct mantis_pci *mantis)
 {
-	struct input_dev *rc;
-	char name[80], dev[80];
+	struct rc_dev *dev;
 	int err;
 
-	rc = input_allocate_device();
-	if (!rc) {
-		dprintk(MANTIS_ERROR, 1, "Input device allocate failed");
-		return -ENOMEM;
-	}
+	err = rc_map_register(&ir_mantis_map);
+	if (err)
+		goto out;
 
-	sprintf(name, "Mantis %s IR receiver", mantis->hwconfig->model_name);
-	sprintf(dev, "pci-%s/ir0", pci_name(mantis->pdev));
+	dev = rc_allocate_device();
+	if (!dev) {
+		dprintk(MANTIS_ERROR, 1, "Remote device allocation failed");
+		err = -ENOMEM;
+		goto out_map;
+	}
 
-	rc->name = name;
-	rc->phys = dev;
+	sprintf(mantis->input_name, "Mantis %s IR receiver", mantis->hwconfig->model_name);
+	sprintf(mantis->input_phys, "pci-%s/ir0", pci_name(mantis->pdev));
 
-	rc->id.bustype	= BUS_PCI;
-	rc->id.vendor	= mantis->vendor_id;
-	rc->id.product	= mantis->device_id;
-	rc->id.version	= 1;
-	rc->dev		= mantis->pdev->dev;
+	dev->input_name         = mantis->input_name;
+	dev->input_phys         = mantis->input_phys;
+	dev->input_id.bustype   = BUS_PCI;
+	dev->input_id.vendor    = mantis->vendor_id;
+	dev->input_id.product   = mantis->device_id;
+	dev->input_id.version   = 1;
+	dev->driver_name        = MODULE_NAME;
+	dev->map_name           = RC_MAP_MANTIS;
+	dev->dev.parent         = &mantis->pdev->dev;
 
-	err = __ir_input_register(rc, &ir_mantis, NULL, MODULE_NAME);
+	err = rc_register_device(dev);
 	if (err) {
 		dprintk(MANTIS_ERROR, 1, "IR device registration failed, ret = %d", err);
-		input_free_device(rc);
-		return -ENODEV;
+		goto out_dev;
 	}
 
-	mantis->rc = rc;
-
+	mantis->rc = dev;
 	return 0;
+
+out_dev:
+	rc_free_device(dev);
+out_map:
+	rc_map_unregister(&ir_mantis_map);
+out:
+	return err;
 }
 
 int mantis_exit(struct mantis_pci *mantis)
 {
-	struct input_dev *rc = mantis->rc;
-
-	ir_input_unregister(rc);
-
+	rc_unregister_device(mantis->rc);
+	rc_map_unregister(&ir_mantis_map);
 	return 0;
 }
+
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/dvb/mantis/mantis_ioc.c linux-libre-2.6.38-gnu1/drivers/media/dvb/mantis/mantis_ioc.c
--- linux-libre-2.6.37-gnu1/drivers/media/dvb/mantis/mantis_ioc.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/dvb/mantis/mantis_ioc.c	2011-03-14 21:20:32.000000000 -0400
@@ -75,7 +75,7 @@ int mantis_get_mac(struct mantis_pci *ma
 EXPORT_SYMBOL_GPL(mantis_get_mac);
 
 /* Turn the given bit on or off. */
-void gpio_set_bits(struct mantis_pci *mantis, u32 bitpos, u8 value)
+void mantis_gpio_set_bits(struct mantis_pci *mantis, u32 bitpos, u8 value)
 {
 	u32 cur;
 
@@ -90,7 +90,7 @@ void gpio_set_bits(struct mantis_pci *ma
 	mmwrite(mantis->gpio_status, MANTIS_GPIF_ADDR);
 	mmwrite(0x00, MANTIS_GPIF_DOUT);
 }
-EXPORT_SYMBOL_GPL(gpio_set_bits);
+EXPORT_SYMBOL_GPL(mantis_gpio_set_bits);
 
 int mantis_stream_control(struct mantis_pci *mantis, enum mantis_stream_control stream_ctl)
 {
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/dvb/mantis/mantis_ioc.h linux-libre-2.6.38-gnu1/drivers/media/dvb/mantis/mantis_ioc.h
--- linux-libre-2.6.37-gnu1/drivers/media/dvb/mantis/mantis_ioc.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/dvb/mantis/mantis_ioc.h	2011-03-14 21:20:32.000000000 -0400
@@ -44,7 +44,7 @@ enum mantis_stream_control {
 };
 
 extern int mantis_get_mac(struct mantis_pci *mantis);
-extern void gpio_set_bits(struct mantis_pci *mantis, u32 bitpos, u8 value);
+extern void mantis_gpio_set_bits(struct mantis_pci *mantis, u32 bitpos, u8 value);
 
 extern int mantis_stream_control(struct mantis_pci *mantis, enum mantis_stream_control stream_ctl);
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/dvb/mantis/mantis_pci.c linux-libre-2.6.38-gnu1/drivers/media/dvb/mantis/mantis_pci.c
--- linux-libre-2.6.37-gnu1/drivers/media/dvb/mantis/mantis_pci.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/dvb/mantis/mantis_pci.c	2011-03-14 21:20:32.000000000 -0400
@@ -22,7 +22,6 @@
 #include <linux/moduleparam.h>
 #include <linux/kernel.h>
 #include <asm/io.h>
-#include <asm/pgtable.h>
 #include <asm/page.h>
 #include <linux/kmod.h>
 #include <linux/vmalloc.h>
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/dvb/mantis/mantis_uart.c linux-libre-2.6.38-gnu1/drivers/media/dvb/mantis/mantis_uart.c
--- linux-libre-2.6.37-gnu1/drivers/media/dvb/mantis/mantis_uart.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/dvb/mantis/mantis_uart.c	2011-03-14 21:20:32.000000000 -0400
@@ -182,5 +182,6 @@ void mantis_uart_exit(struct mantis_pci
 {
 	/* disable interrupt */
 	mmwrite(mmread(MANTIS_UART_CTL) & 0xffef, MANTIS_UART_CTL);
+	flush_work_sync(&mantis->uart_work);
 }
 EXPORT_SYMBOL_GPL(mantis_uart_exit);
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/dvb/mantis/mantis_vp1033.c linux-libre-2.6.38-gnu1/drivers/media/dvb/mantis/mantis_vp1033.c
--- linux-libre-2.6.37-gnu1/drivers/media/dvb/mantis/mantis_vp1033.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/dvb/mantis/mantis_vp1033.c	2011-03-14 21:20:32.000000000 -0400
@@ -173,7 +173,7 @@ static int vp1033_frontend_init(struct m
 		msleep(250);
 
 		dprintk(MANTIS_ERROR, 1, "Probing for STV0299 (DVB-S)");
-		fe = stv0299_attach(&lgtdqcs001f_config, adapter);
+		fe = dvb_attach(stv0299_attach, &lgtdqcs001f_config, adapter);
 
 		if (fe) {
 			fe->ops.tuner_ops.set_params = lgtdqcs001f_tuner_set;
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/dvb/mantis/mantis_vp1034.c linux-libre-2.6.38-gnu1/drivers/media/dvb/mantis/mantis_vp1034.c
--- linux-libre-2.6.37-gnu1/drivers/media/dvb/mantis/mantis_vp1034.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/dvb/mantis/mantis_vp1034.c	2011-03-14 21:20:32.000000000 -0400
@@ -50,13 +50,13 @@ int vp1034_set_voltage(struct dvb_fronte
 	switch (voltage) {
 	case SEC_VOLTAGE_13:
 		dprintk(MANTIS_ERROR, 1, "Polarization=[13V]");
-		gpio_set_bits(mantis, 13, 1);
-		gpio_set_bits(mantis, 14, 0);
+		mantis_gpio_set_bits(mantis, 13, 1);
+		mantis_gpio_set_bits(mantis, 14, 0);
 		break;
 	case SEC_VOLTAGE_18:
 		dprintk(MANTIS_ERROR, 1, "Polarization=[18V]");
-		gpio_set_bits(mantis, 13, 1);
-		gpio_set_bits(mantis, 14, 1);
+		mantis_gpio_set_bits(mantis, 13, 1);
+		mantis_gpio_set_bits(mantis, 14, 1);
 		break;
 	case SEC_VOLTAGE_OFF:
 		dprintk(MANTIS_ERROR, 1, "Frontend (dummy) POWERDOWN");
@@ -82,7 +82,7 @@ static int vp1034_frontend_init(struct m
 		msleep(250);
 
 		dprintk(MANTIS_ERROR, 1, "Probing for MB86A16 (DVB-S/DSS)");
-		fe = mb86a16_attach(&vp1034_mb86a16_config, adapter);
+		fe = dvb_attach(mb86a16_attach, &vp1034_mb86a16_config, adapter);
 		if (fe) {
 			dprintk(MANTIS_ERROR, 1,
 			"found MB86A16 DVB-S/DSS frontend @0x%02x",
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/dvb/mantis/mantis_vp1041.c linux-libre-2.6.38-gnu1/drivers/media/dvb/mantis/mantis_vp1041.c
--- linux-libre-2.6.37-gnu1/drivers/media/dvb/mantis/mantis_vp1041.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/dvb/mantis/mantis_vp1041.c	2011-03-14 21:20:32.000000000 -0400
@@ -316,14 +316,14 @@ static int vp1041_frontend_init(struct m
 	if (err == 0) {
 		mantis_frontend_soft_reset(mantis);
 		msleep(250);
-		mantis->fe = stb0899_attach(&vp1041_stb0899_config, adapter);
+		mantis->fe = dvb_attach(stb0899_attach, &vp1041_stb0899_config, adapter);
 		if (mantis->fe) {
 			dprintk(MANTIS_ERROR, 1,
 				"found STB0899 DVB-S/DVB-S2 frontend @0x%02x",
 				vp1041_stb0899_config.demod_address);
 
-			if (stb6100_attach(mantis->fe, &vp1041_stb6100_config, adapter)) {
-				if (!lnbp21_attach(mantis->fe, adapter, 0, 0))
+			if (dvb_attach(stb6100_attach, mantis->fe, &vp1041_stb6100_config, adapter)) {
+				if (!dvb_attach(lnbp21_attach, mantis->fe, adapter, 0, 0))
 					dprintk(MANTIS_ERROR, 1, "No LNBP21 found!");
 			}
 		} else {
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/dvb/mantis/mantis_vp2033.c linux-libre-2.6.38-gnu1/drivers/media/dvb/mantis/mantis_vp2033.c
--- linux-libre-2.6.37-gnu1/drivers/media/dvb/mantis/mantis_vp2033.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/dvb/mantis/mantis_vp2033.c	2011-03-14 21:20:32.000000000 -0400
@@ -132,7 +132,7 @@ static int vp2033_frontend_init(struct m
 		msleep(250);
 
 		dprintk(MANTIS_ERROR, 1, "Probing for CU1216 (DVB-C)");
-		fe = tda10021_attach(&vp2033_tda1002x_cu1216_config,
+		fe = dvb_attach(tda10021_attach, &vp2033_tda1002x_cu1216_config,
 				     adapter,
 				     read_pwm(mantis));
 
@@ -141,7 +141,7 @@ static int vp2033_frontend_init(struct m
 				"found Philips CU1216 DVB-C frontend (TDA10021) @ 0x%02x",
 				vp2033_tda1002x_cu1216_config.demod_address);
 		} else {
-			fe = tda10023_attach(&vp2033_tda10023_cu1216_config,
+			fe = dvb_attach(tda10023_attach, &vp2033_tda10023_cu1216_config,
 					     adapter,
 					     read_pwm(mantis));
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/dvb/mantis/mantis_vp2040.c linux-libre-2.6.38-gnu1/drivers/media/dvb/mantis/mantis_vp2040.c
--- linux-libre-2.6.37-gnu1/drivers/media/dvb/mantis/mantis_vp2040.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/dvb/mantis/mantis_vp2040.c	2011-03-14 21:20:32.000000000 -0400
@@ -132,7 +132,7 @@ static int vp2040_frontend_init(struct m
 		msleep(250);
 
 		dprintk(MANTIS_ERROR, 1, "Probing for CU1216 (DVB-C)");
-		fe = tda10021_attach(&vp2040_tda1002x_cu1216_config,
+		fe = dvb_attach(tda10021_attach, &vp2040_tda1002x_cu1216_config,
 				     adapter,
 				     read_pwm(mantis));
 
@@ -141,7 +141,7 @@ static int vp2040_frontend_init(struct m
 				"found Philips CU1216 DVB-C frontend (TDA10021) @ 0x%02x",
 				vp2040_tda1002x_cu1216_config.demod_address);
 		} else {
-			fe = tda10023_attach(&vp2040_tda10023_cu1216_config,
+			fe = dvb_attach(tda10023_attach, &vp2040_tda10023_cu1216_config,
 					     adapter,
 					     read_pwm(mantis));
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/dvb/mantis/mantis_vp3030.c linux-libre-2.6.38-gnu1/drivers/media/dvb/mantis/mantis_vp3030.c
--- linux-libre-2.6.37-gnu1/drivers/media/dvb/mantis/mantis_vp3030.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/dvb/mantis/mantis_vp3030.c	2011-03-14 21:20:32.000000000 -0400
@@ -59,21 +59,21 @@ static int vp3030_frontend_init(struct m
 	struct mantis_hwconfig *config	= mantis->hwconfig;
 	int err = 0;
 
-	gpio_set_bits(mantis, config->reset, 0);
+	mantis_gpio_set_bits(mantis, config->reset, 0);
 	msleep(100);
 	err = mantis_frontend_power(mantis, POWER_ON);
 	msleep(100);
-	gpio_set_bits(mantis, config->reset, 1);
+	mantis_gpio_set_bits(mantis, config->reset, 1);
 
 	if (err == 0) {
 		msleep(250);
 		dprintk(MANTIS_ERROR, 1, "Probing for 10353 (DVB-T)");
-		fe = zl10353_attach(&mantis_vp3030_config, adapter);
+		fe = dvb_attach(zl10353_attach, &mantis_vp3030_config, adapter);
 
 		if (!fe)
 			return -1;
 
-		tda665x_attach(fe, &env57h12d5_config, adapter);
+		dvb_attach(tda665x_attach, fe, &env57h12d5_config, adapter);
 	} else {
 		dprintk(MANTIS_ERROR, 1, "Frontend on <%s> POWER ON failed! <%d>",
 			adapter->name,
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/dvb/ngene/ngene-core.c linux-libre-2.6.38-gnu1/drivers/media/dvb/ngene/ngene-core.c
--- linux-libre-2.6.37-gnu1/drivers/media/dvb/ngene/ngene-core.c	2013-05-03 03:56:22.000000000 -0400
+++ linux-libre-2.6.38-gnu1/drivers/media/dvb/ngene/ngene-core.c	2013-05-03 01:55:59.000000000 -0400
@@ -1304,7 +1304,6 @@ static void ngene_stop(struct ngene *dev
 static int ngene_start(struct ngene *dev)
 {
 	int stat;
-	unsigned long flags;
 	int i;
 
 	pci_set_master(dev->pci_dev);
@@ -1337,6 +1336,8 @@ static int ngene_start(struct ngene *dev
 #ifdef CONFIG_PCI_MSI
 	/* enable MSI if kernel and card support it */
 	if (pci_msi_enabled() && dev->card_info->msi_supported) {
+		unsigned long flags;
+
 		ngwritel(0, NGENE_INT_ENABLE);
 		free_irq(dev->pci_dev->irq, dev);
 		stat = pci_enable_msi(dev->pci_dev);
@@ -1515,7 +1516,7 @@ static int init_channels(struct ngene *d
 
 void __devexit ngene_remove(struct pci_dev *pdev)
 {
-	struct ngene *dev = (struct ngene *)pci_get_drvdata(pdev);
+	struct ngene *dev = pci_get_drvdata(pdev);
 	int i;
 
 	tasklet_kill(&dev->event_tasklet);
@@ -1536,12 +1537,11 @@ int __devinit ngene_probe(struct pci_dev
 	if (pci_enable_device(pci_dev) < 0)
 		return -ENODEV;
 
-	dev = vmalloc(sizeof(struct ngene));
+	dev = vzalloc(sizeof(struct ngene));
 	if (dev == NULL) {
 		stat = -ENOMEM;
 		goto fail0;
 	}
-	memset(dev, 0, sizeof(struct ngene));
 
 	dev->pci_dev = pci_dev;
 	dev->card_info = (struct ngene_info *)id->driver_data;
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/dvb/siano/Kconfig linux-libre-2.6.38-gnu1/drivers/media/dvb/siano/Kconfig
--- linux-libre-2.6.37-gnu1/drivers/media/dvb/siano/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/dvb/siano/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -4,7 +4,7 @@
 
 config SMS_SIANO_MDTV
 	tristate "Siano SMS1xxx based MDTV receiver"
-	depends on DVB_CORE && IR_CORE && HAS_DMA
+	depends on DVB_CORE && RC_CORE && HAS_DMA
 	---help---
 	  Choose Y or M here if you have MDTV receiver with a Siano chipset.
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/dvb/siano/smscoreapi.c linux-libre-2.6.38-gnu1/drivers/media/dvb/siano/smscoreapi.c
--- linux-libre-2.6.37-gnu1/drivers/media/dvb/siano/smscoreapi.c	2013-05-03 03:56:25.000000000 -0400
+++ linux-libre-2.6.38-gnu1/drivers/media/dvb/siano/smscoreapi.c	2013-05-03 01:56:04.000000000 -0400
@@ -438,7 +438,7 @@ static int smscore_init_ir(struct smscor
 	int rc;
 	void *buffer;
 
-	coredev->ir.input_dev = NULL;
+	coredev->ir.dev = NULL;
 	ir_io = sms_get_board(smscore_get_board_id(coredev))->board_cfg.ir;
 	if (ir_io) {/* only if IR port exist we use IR sub-module */
 		sms_info("IR loading");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/dvb/siano/smsir.c linux-libre-2.6.38-gnu1/drivers/media/dvb/siano/smsir.c
--- linux-libre-2.6.37-gnu1/drivers/media/dvb/siano/smsir.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/dvb/siano/smsir.c	2011-03-14 21:20:32.000000000 -0400
@@ -45,25 +45,24 @@ void sms_ir_event(struct smscore_device_
 		ev.duration = abs(samples[i]) * 1000; /* Convert to ns */
 		ev.pulse = (samples[i] > 0) ? false : true;
 
-		ir_raw_event_store(coredev->ir.input_dev, &ev);
+		ir_raw_event_store(coredev->ir.dev, &ev);
 	}
-	ir_raw_event_handle(coredev->ir.input_dev);
+	ir_raw_event_handle(coredev->ir.dev);
 }
 
 int sms_ir_init(struct smscore_device_t *coredev)
 {
-	struct input_dev *input_dev;
+	int err;
 	int board_id = smscore_get_board_id(coredev);
+	struct rc_dev *dev;
 
-	sms_log("Allocating input device");
-	input_dev = input_allocate_device();
-	if (!input_dev)	{
+	sms_log("Allocating rc device");
+	dev = rc_allocate_device();
+	if (!dev) {
 		sms_err("Not enough memory");
 		return -ENOMEM;
 	}
 
-	coredev->ir.input_dev = input_dev;
-
 	coredev->ir.controller = 0;	/* Todo: vega/nova SPI number */
 	coredev->ir.timeout = IR_DEFAULT_TIMEOUT;
 	sms_log("IR port %d, timeout %d ms",
@@ -75,38 +74,41 @@ int sms_ir_init(struct smscore_device_t
 	strlcpy(coredev->ir.phys, coredev->devpath, sizeof(coredev->ir.phys));
 	strlcat(coredev->ir.phys, "/ir0", sizeof(coredev->ir.phys));
 
-	input_dev->name = coredev->ir.name;
-	input_dev->phys = coredev->ir.phys;
-	input_dev->dev.parent = coredev->device;
+	dev->input_name = coredev->ir.name;
+	dev->input_phys = coredev->ir.phys;
+	dev->dev.parent = coredev->device;
 
 #if 0
 	/* TODO: properly initialize the parameters bellow */
-	input_dev->id.bustype = BUS_USB;
-	input_dev->id.version = 1;
-	input_dev->id.vendor = le16_to_cpu(dev->udev->descriptor.idVendor);
-	input_dev->id.product = le16_to_cpu(dev->udev->descriptor.idProduct);
+	dev->input_id.bustype = BUS_USB;
+	dev->input_id.version = 1;
+	dev->input_id.vendor = le16_to_cpu(dev->udev->descriptor.idVendor);
+	dev->input_id.product = le16_to_cpu(dev->udev->descriptor.idProduct);
 #endif
 
-	coredev->ir.props.priv = coredev;
-	coredev->ir.props.driver_type = RC_DRIVER_IR_RAW;
-	coredev->ir.props.allowed_protos = IR_TYPE_ALL;
+	dev->priv = coredev;
+	dev->driver_type = RC_DRIVER_IR_RAW;
+	dev->allowed_protos = RC_TYPE_ALL;
+	dev->map_name = sms_get_board(board_id)->rc_codes;
+	dev->driver_name = MODULE_NAME;
 
-	sms_log("Input device (IR) %s is set for key events", input_dev->name);
+	sms_log("Input device (IR) %s is set for key events", dev->input_name);
 
-	if (ir_input_register(input_dev, sms_get_board(board_id)->rc_codes,
-			      &coredev->ir.props, MODULE_NAME)) {
+	err = rc_register_device(dev);
+	if (err < 0) {
 		sms_err("Failed to register device");
-		input_free_device(input_dev);
-		return -EACCES;
+		rc_free_device(dev);
+		return err;
 	}
 
+	coredev->ir.dev = dev;
 	return 0;
 }
 
 void sms_ir_exit(struct smscore_device_t *coredev)
 {
-	if (coredev->ir.input_dev)
-		ir_input_unregister(coredev->ir.input_dev);
+	if (coredev->ir.dev)
+		rc_unregister_device(coredev->ir.dev);
 
 	sms_log("");
 }
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/dvb/siano/smsir.h linux-libre-2.6.38-gnu1/drivers/media/dvb/siano/smsir.h
--- linux-libre-2.6.37-gnu1/drivers/media/dvb/siano/smsir.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/dvb/siano/smsir.h	2011-03-14 21:20:32.000000000 -0400
@@ -28,20 +28,19 @@ along with this program.  If not, see <h
 #define __SMS_IR_H__
 
 #include <linux/input.h>
-#include <media/ir-core.h>
+#include <media/rc-core.h>
 
 #define IR_DEFAULT_TIMEOUT		100
 
 struct smscore_device_t;
 
 struct ir_t {
-	struct input_dev *input_dev;
+	struct rc_dev *dev;
 	char name[40];
 	char phys[32];
 
 	char *rc_codes;
 	u64 protocol;
-	struct ir_dev_props props;
 
 	u32 timeout;
 	u32 controller;
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/dvb/siano/smsusb.c linux-libre-2.6.38-gnu1/drivers/media/dvb/siano/smsusb.c
--- linux-libre-2.6.37-gnu1/drivers/media/dvb/siano/smsusb.c	2013-05-03 03:56:29.000000000 -0400
+++ linux-libre-2.6.38-gnu1/drivers/media/dvb/siano/smsusb.c	2013-05-03 01:56:09.000000000 -0400
@@ -288,8 +288,7 @@ static int smsusb1_setmode(void *context
 
 static void smsusb_term_device(struct usb_interface *intf)
 {
-	struct smsusb_device_t *dev =
-		(struct smsusb_device_t *) usb_get_intfdata(intf);
+	struct smsusb_device_t *dev = usb_get_intfdata(intf);
 
 	if (dev) {
 		smsusb_stop_streaming(dev);
@@ -445,8 +444,7 @@ static void smsusb_disconnect(struct usb
 
 static int smsusb_suspend(struct usb_interface *intf, pm_message_t msg)
 {
-	struct smsusb_device_t *dev =
-		(struct smsusb_device_t *)usb_get_intfdata(intf);
+	struct smsusb_device_t *dev = usb_get_intfdata(intf);
 	printk(KERN_INFO "%s: Entering status %d.\n", __func__, msg.event);
 	smsusb_stop_streaming(dev);
 	return 0;
@@ -455,8 +453,7 @@ static int smsusb_suspend(struct usb_int
 static int smsusb_resume(struct usb_interface *intf)
 {
 	int rc, i;
-	struct smsusb_device_t *dev =
-		(struct smsusb_device_t *)usb_get_intfdata(intf);
+	struct smsusb_device_t *dev = usb_get_intfdata(intf);
 	struct usb_device *udev = interface_to_usbdev(intf);
 
 	printk(KERN_INFO "%s: Entering.\n", __func__);
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/dvb/ttpci/av7110_ca.c linux-libre-2.6.38-gnu1/drivers/media/dvb/ttpci/av7110_ca.c
--- linux-libre-2.6.37-gnu1/drivers/media/dvb/ttpci/av7110_ca.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/dvb/ttpci/av7110_ca.c	2011-03-14 21:20:32.000000000 -0400
@@ -277,7 +277,7 @@ static int dvb_ca_ioctl(struct file *fil
 	{
 		ca_slot_info_t *info=(ca_slot_info_t *)parg;
 
-		if (info->num > 1)
+		if (info->num < 0 || info->num > 1)
 			return -EINVAL;
 		av7110->ci_slot[info->num].num = info->num;
 		av7110->ci_slot[info->num].type = FW_CI_LL_SUPPORT(av7110->arm_app) ?
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/dvb/ttpci/av7110_v4l.c linux-libre-2.6.38-gnu1/drivers/media/dvb/ttpci/av7110_v4l.c
--- linux-libre-2.6.37-gnu1/drivers/media/dvb/ttpci/av7110_v4l.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/dvb/ttpci/av7110_v4l.c	2011-03-14 21:20:32.000000000 -0400
@@ -100,6 +100,7 @@ static struct v4l2_input inputs[4] = {
 		.tuner		= 0, /* ignored */
 		.std		= V4L2_STD_PAL_BG|V4L2_STD_NTSC_M,
 		.status		= 0,
+		.capabilities	= V4L2_IN_CAP_STD,
 	}, {
 		.index		= 1,
 		.name		= "Television",
@@ -108,6 +109,7 @@ static struct v4l2_input inputs[4] = {
 		.tuner		= 0,
 		.std		= V4L2_STD_PAL_BG|V4L2_STD_NTSC_M,
 		.status		= 0,
+		.capabilities	= V4L2_IN_CAP_STD,
 	}, {
 		.index		= 2,
 		.name		= "Video",
@@ -116,6 +118,7 @@ static struct v4l2_input inputs[4] = {
 		.tuner		= 0,
 		.std		= V4L2_STD_PAL_BG|V4L2_STD_NTSC_M,
 		.status		= 0,
+		.capabilities	= V4L2_IN_CAP_STD,
 	}, {
 		.index		= 3,
 		.name		= "Y/C",
@@ -124,6 +127,7 @@ static struct v4l2_input inputs[4] = {
 		.tuner		= 0,
 		.std		= V4L2_STD_PAL_BG|V4L2_STD_NTSC_M,
 		.status		= 0,
+		.capabilities	= V4L2_IN_CAP_STD,
 	}
 };
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/dvb/ttpci/budget-av.c linux-libre-2.6.38-gnu1/drivers/media/dvb/ttpci/budget-av.c
--- linux-libre-2.6.37-gnu1/drivers/media/dvb/ttpci/budget-av.c	2013-05-03 03:56:17.000000000 -0400
+++ linux-libre-2.6.38-gnu1/drivers/media/dvb/ttpci/budget-av.c	2013-05-03 01:55:54.000000000 -0400
@@ -1406,8 +1406,10 @@ static int budget_av_detach(struct saa71
 
 #define KNC1_INPUTS 2
 static struct v4l2_input knc1_inputs[KNC1_INPUTS] = {
-	{0, "Composite", V4L2_INPUT_TYPE_TUNER, 1, 0, V4L2_STD_PAL_BG | V4L2_STD_NTSC_M, 0},
-	{1, "S-Video", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG | V4L2_STD_NTSC_M, 0},
+	{ 0, "Composite", V4L2_INPUT_TYPE_TUNER, 1, 0,
+		V4L2_STD_PAL_BG | V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD },
+	{ 1, "S-Video", V4L2_INPUT_TYPE_CAMERA, 2, 0,
+		V4L2_STD_PAL_BG | V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD },
 };
 
 static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *i)
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/dvb/ttpci/budget-ci.c linux-libre-2.6.38-gnu1/drivers/media/dvb/ttpci/budget-ci.c
--- linux-libre-2.6.37-gnu1/drivers/media/dvb/ttpci/budget-ci.c	2013-05-03 03:56:17.000000000 -0400
+++ linux-libre-2.6.38-gnu1/drivers/media/dvb/ttpci/budget-ci.c	2013-05-03 01:55:54.000000000 -0400
@@ -33,9 +33,8 @@
 #include <linux/errno.h>
 #include <linux/slab.h>
 #include <linux/interrupt.h>
-#include <linux/input.h>
 #include <linux/spinlock.h>
-#include <media/ir-core.h>
+#include <media/rc-core.h>
 
 #include "budget.h"
 
@@ -96,7 +95,7 @@ MODULE_PARM_DESC(ir_debug, "enable debug
 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
 
 struct budget_ci_ir {
-	struct input_dev *dev;
+	struct rc_dev *dev;
 	struct tasklet_struct msp430_irq_tasklet;
 	char name[72]; /* 40 + 32 for (struct saa7146_dev).name */
 	char phys[32];
@@ -118,7 +117,7 @@ struct budget_ci {
 static void msp430_ir_interrupt(unsigned long data)
 {
 	struct budget_ci *budget_ci = (struct budget_ci *) data;
-	struct input_dev *dev = budget_ci->ir.dev;
+	struct rc_dev *dev = budget_ci->ir.dev;
 	u32 command = ttpci_budget_debiread(&budget_ci->budget, DEBINOSWAP, DEBIADDR_IR, 2, 1, 0) >> 8;
 
 	/*
@@ -160,19 +159,17 @@ static void msp430_ir_interrupt(unsigned
 	    budget_ci->ir.rc5_device != (command & 0x1f))
 		return;
 
-	ir_keydown(dev, budget_ci->ir.ir_key, (command & 0x20) ? 1 : 0);
+	rc_keydown(dev, budget_ci->ir.ir_key, (command & 0x20) ? 1 : 0);
 }
 
 static int msp430_ir_init(struct budget_ci *budget_ci)
 {
 	struct saa7146_dev *saa = budget_ci->budget.dev;
-	struct input_dev *input_dev = budget_ci->ir.dev;
+	struct rc_dev *dev;
 	int error;
-	char *ir_codes = NULL;
-
 
-	budget_ci->ir.dev = input_dev = input_allocate_device();
-	if (!input_dev) {
+	dev = rc_allocate_device();
+	if (!dev) {
 		printk(KERN_ERR "budget_ci: IR interface initialisation failed\n");
 		return -ENOMEM;
 	}
@@ -182,19 +179,20 @@ static int msp430_ir_init(struct budget_
 	snprintf(budget_ci->ir.phys, sizeof(budget_ci->ir.phys),
 		 "pci-%s/ir0", pci_name(saa->pci));
 
-	input_dev->name = budget_ci->ir.name;
-
-	input_dev->phys = budget_ci->ir.phys;
-	input_dev->id.bustype = BUS_PCI;
-	input_dev->id.version = 1;
+	dev->driver_name = MODULE_NAME;
+	dev->input_name = budget_ci->ir.name;
+	dev->input_phys = budget_ci->ir.phys;
+	dev->input_id.bustype = BUS_PCI;
+	dev->input_id.version = 1;
+	dev->scanmask = 0xff;
 	if (saa->pci->subsystem_vendor) {
-		input_dev->id.vendor = saa->pci->subsystem_vendor;
-		input_dev->id.product = saa->pci->subsystem_device;
+		dev->input_id.vendor = saa->pci->subsystem_vendor;
+		dev->input_id.product = saa->pci->subsystem_device;
 	} else {
-		input_dev->id.vendor = saa->pci->vendor;
-		input_dev->id.product = saa->pci->device;
+		dev->input_id.vendor = saa->pci->vendor;
+		dev->input_id.product = saa->pci->device;
 	}
-	input_dev->dev.parent = &saa->pci->dev;
+	dev->dev.parent = &saa->pci->dev;
 
 	if (rc5_device < 0)
 		budget_ci->ir.rc5_device = IR_DEVICE_ANY;
@@ -208,7 +206,7 @@ static int msp430_ir_init(struct budget_
 	case 0x1011:
 	case 0x1012:
 		/* The hauppauge keymap is a superset of these remotes */
-		ir_codes = RC_MAP_HAUPPAUGE_NEW;
+		dev->map_name = RC_MAP_HAUPPAUGE_NEW;
 
 		if (rc5_device < 0)
 			budget_ci->ir.rc5_device = 0x1f;
@@ -218,23 +216,22 @@ static int msp430_ir_init(struct budget_
 	case 0x1019:
 	case 0x101a:
 		/* for the Technotrend 1500 bundled remote */
-		ir_codes = RC_MAP_TT_1500;
+		dev->map_name = RC_MAP_TT_1500;
 		break;
 	default:
 		/* unknown remote */
-		ir_codes = RC_MAP_BUDGET_CI_OLD;
+		dev->map_name = RC_MAP_BUDGET_CI_OLD;
 		break;
 	}
 
-	error = ir_input_register(input_dev, ir_codes, NULL, MODULE_NAME);
+	error = rc_register_device(dev);
 	if (error) {
 		printk(KERN_ERR "budget_ci: could not init driver for IR device (code %d)\n", error);
+		rc_free_device(dev);
 		return error;
 	}
 
-	/* note: these must be after input_register_device */
-	input_dev->rep[REP_DELAY] = 400;
-	input_dev->rep[REP_PERIOD] = 250;
+	budget_ci->ir.dev = dev;
 
 	tasklet_init(&budget_ci->ir.msp430_irq_tasklet, msp430_ir_interrupt,
 		     (unsigned long) budget_ci);
@@ -248,13 +245,12 @@ static int msp430_ir_init(struct budget_
 static void msp430_ir_deinit(struct budget_ci *budget_ci)
 {
 	struct saa7146_dev *saa = budget_ci->budget.dev;
-	struct input_dev *dev = budget_ci->ir.dev;
 
 	SAA7146_IER_DISABLE(saa, MASK_06);
 	saa7146_setgpio(saa, 3, SAA7146_GPIO_INPUT);
 	tasklet_kill(&budget_ci->ir.msp430_irq_tasklet);
 
-	ir_input_unregister(dev);
+	rc_unregister_device(budget_ci->ir.dev);
 }
 
 static int ciintf_read_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address)
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/dvb/ttpci/Kconfig linux-libre-2.6.38-gnu1/drivers/media/dvb/ttpci/Kconfig
--- linux-libre-2.6.37-gnu1/drivers/media/dvb/ttpci/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/dvb/ttpci/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -89,7 +89,6 @@ config DVB_BUDGET
 config DVB_BUDGET_CI
 	tristate "Budget cards with onboard CI connector"
 	depends on DVB_BUDGET_CORE && I2C
-	depends on INPUT # due to IR
 	select DVB_STV0297 if !DVB_FE_CUSTOMISE
 	select DVB_STV0299 if !DVB_FE_CUSTOMISE
 	select DVB_TDA1004X if !DVB_FE_CUSTOMISE
@@ -98,7 +97,7 @@ config DVB_BUDGET_CI
 	select DVB_LNBP21 if !DVB_FE_CUSTOMISE
 	select DVB_TDA10023 if !DVB_FE_CUSTOMISE
 	select MEDIA_TUNER_TDA827X if !MEDIA_TUNER_CUSTOMISE
-	depends on VIDEO_IR
+	depends on RC_CORE
 	help
 	  Support for simple SAA7146 based DVB cards
 	  (so called Budget- or Nova-PCI cards) without onboard
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/ene_ir.c linux-libre-2.6.38-gnu1/drivers/media/IR/ene_ir.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/ene_ir.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/ene_ir.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1217 +0,0 @@
-/*
- * driver for ENE KB3926 B/C/D/E/F CIR (pnp id: ENE0XXX)
- *
- * Copyright (C) 2010 Maxim Levitsky <maximlevitsky@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
- *
- * Special thanks to:
- *   Sami R. <maesesami@gmail.com> for lot of help in debugging and therefore
- *    bringing to life support for transmission & learning mode.
- *
- *   Charlie Andrews <charliethepilot@googlemail.com> for lots of help in
- *   bringing up the support of new firmware buffer that is popular
- *   on latest notebooks
- *
- *   ENE for partial device documentation
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/pnp.h>
-#include <linux/io.h>
-#include <linux/interrupt.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/input.h>
-#include <media/ir-core.h>
-#include <media/ir-common.h>
-#include "ene_ir.h"
-
-static int sample_period;
-static bool learning_mode_force;
-static int debug;
-static bool txsim;
-
-static void ene_set_reg_addr(struct ene_device *dev, u16 reg)
-{
-	outb(reg >> 8, dev->hw_io + ENE_ADDR_HI);
-	outb(reg & 0xFF, dev->hw_io + ENE_ADDR_LO);
-}
-
-/* read a hardware register */
-static u8 ene_read_reg(struct ene_device *dev, u16 reg)
-{
-	u8 retval;
-	ene_set_reg_addr(dev, reg);
-	retval = inb(dev->hw_io + ENE_IO);
-	dbg_regs("reg %04x == %02x", reg, retval);
-	return retval;
-}
-
-/* write a hardware register */
-static void ene_write_reg(struct ene_device *dev, u16 reg, u8 value)
-{
-	dbg_regs("reg %04x <- %02x", reg, value);
-	ene_set_reg_addr(dev, reg);
-	outb(value, dev->hw_io + ENE_IO);
-}
-
-/* Set bits in hardware register */
-static void ene_set_reg_mask(struct ene_device *dev, u16 reg, u8 mask)
-{
-	dbg_regs("reg %04x |= %02x", reg, mask);
-	ene_set_reg_addr(dev, reg);
-	outb(inb(dev->hw_io + ENE_IO) | mask, dev->hw_io + ENE_IO);
-}
-
-/* Clear bits in hardware register */
-static void ene_clear_reg_mask(struct ene_device *dev, u16 reg, u8 mask)
-{
-	dbg_regs("reg %04x &= ~%02x ", reg, mask);
-	ene_set_reg_addr(dev, reg);
-	outb(inb(dev->hw_io + ENE_IO) & ~mask, dev->hw_io + ENE_IO);
-}
-
-/* A helper to set/clear a bit in register according to boolean variable */
-static void ene_set_clear_reg_mask(struct ene_device *dev, u16 reg, u8 mask,
-								bool set)
-{
-	if (set)
-		ene_set_reg_mask(dev, reg, mask);
-	else
-		ene_clear_reg_mask(dev, reg, mask);
-}
-
-/* detect hardware features */
-static int ene_hw_detect(struct ene_device *dev)
-{
-	u8 chip_major, chip_minor;
-	u8 hw_revision, old_ver;
-	u8 fw_reg2, fw_reg1;
-
-	ene_clear_reg_mask(dev, ENE_ECSTS, ENE_ECSTS_RSRVD);
-	chip_major = ene_read_reg(dev, ENE_ECVER_MAJOR);
-	chip_minor = ene_read_reg(dev, ENE_ECVER_MINOR);
-	ene_set_reg_mask(dev, ENE_ECSTS, ENE_ECSTS_RSRVD);
-
-	hw_revision = ene_read_reg(dev, ENE_ECHV);
-	old_ver = ene_read_reg(dev, ENE_HW_VER_OLD);
-
-	dev->pll_freq = (ene_read_reg(dev, ENE_PLLFRH) << 4) +
-		(ene_read_reg(dev, ENE_PLLFRL) >> 4);
-
-	if (sample_period != ENE_DEFAULT_SAMPLE_PERIOD)
-		dev->rx_period_adjust =
-			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");
-		return -ENODEV;
-	}
-
-	ene_notice("chip is 0x%02x%02x - kbver = 0x%02x, rev = 0x%02x",
-		chip_major, chip_minor, old_ver, hw_revision);
-
-	ene_notice("PLL freq = %d", dev->pll_freq);
-
-	if (chip_major == 0x33) {
-		ene_warn("chips 0x33xx aren't supported");
-		return -ENODEV;
-	}
-
-	if (chip_major == 0x39 && chip_minor == 0x26 && hw_revision == 0xC0) {
-		dev->hw_revision = ENE_HW_C;
-		ene_notice("KB3926C detected");
-	} else if (old_ver == 0x24 && hw_revision == 0xC0) {
-		dev->hw_revision = ENE_HW_B;
-		ene_notice("KB3926B detected");
-	} else {
-		dev->hw_revision = ENE_HW_D;
-		ene_notice("KB3926D or higher detected");
-	}
-
-	/* detect features hardware supports */
-	if (dev->hw_revision < ENE_HW_C)
-		return 0;
-
-	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);
-
-	dev->hw_use_gpio_0a = !!(fw_reg2 & ENE_FW2_GP0A);
-	dev->hw_learning_and_tx_capable = !!(fw_reg2 & ENE_FW2_LEARNING);
-	dev->hw_extra_buffer = !!(fw_reg1 & ENE_FW1_HAS_EXTRA_BUF);
-
-	if (dev->hw_learning_and_tx_capable)
-		dev->hw_fan_input = !!(fw_reg2 & ENE_FW2_FAN_INPUT);
-
-	ene_notice("Hardware features:");
-
-	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");
-
-		ene_notice("* Uses GPIO %s for IR raw input",
-			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");
-	}
-
-	if (!dev->hw_fan_input)
-		ene_notice("* Uses GPIO %s for IR demodulated input",
-			dev->hw_use_gpio_0a ? "0A" : "40");
-
-	if (dev->hw_extra_buffer)
-		ene_notice("* Uses new style input buffer");
-	return 0;
-}
-
-/* Read properities of hw sample buffer */
-static void ene_rx_setup_hw_buffer(struct ene_device *dev)
-{
-	u16 tmp;
-
-	ene_rx_read_hw_pointer(dev);
-	dev->r_pointer = dev->w_pointer;
-
-	if (!dev->hw_extra_buffer) {
-		dev->buffer_len = ENE_FW_PACKET_SIZE * 2;
-		return;
-	}
-
-	tmp = ene_read_reg(dev, ENE_FW_SAMPLE_BUFFER);
-	tmp |= ene_read_reg(dev, ENE_FW_SAMPLE_BUFFER+1) << 8;
-	dev->extra_buf1_address = tmp;
-
-	dev->extra_buf1_len = ene_read_reg(dev, ENE_FW_SAMPLE_BUFFER + 2);
-
-	tmp = ene_read_reg(dev, ENE_FW_SAMPLE_BUFFER + 3);
-	tmp |= ene_read_reg(dev, ENE_FW_SAMPLE_BUFFER + 4) << 8;
-	dev->extra_buf2_address = tmp;
-
-	dev->extra_buf2_len = ene_read_reg(dev, ENE_FW_SAMPLE_BUFFER + 5);
-
-	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);
-
-	ene_notice("Total buffer len = %d", dev->buffer_len);
-
-	if (dev->buffer_len > 64 || dev->buffer_len < 16)
-		goto error;
-
-	if (dev->extra_buf1_address > 0xFBFC ||
-					dev->extra_buf1_address < 0xEC00)
-		goto error;
-
-	if (dev->extra_buf2_address > 0xFBFC ||
-					dev->extra_buf2_address < 0xEC00)
-		goto error;
-
-	if (dev->r_pointer > dev->buffer_len)
-		goto error;
-
-	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");
-	dev->hw_extra_buffer = false;
-	ene_clear_reg_mask(dev, ENE_FW1, ENE_FW1_EXTRA_BUF_HND);
-}
-
-
-/* Restore the pointers to extra buffers - to make module reload work*/
-static void ene_rx_restore_hw_buffer(struct ene_device *dev)
-{
-	if (!dev->hw_extra_buffer)
-		return;
-
-	ene_write_reg(dev, ENE_FW_SAMPLE_BUFFER + 0,
-				dev->extra_buf1_address & 0xFF);
-	ene_write_reg(dev, ENE_FW_SAMPLE_BUFFER + 1,
-				dev->extra_buf1_address >> 8);
-	ene_write_reg(dev, ENE_FW_SAMPLE_BUFFER + 2, dev->extra_buf1_len);
-
-	ene_write_reg(dev, ENE_FW_SAMPLE_BUFFER + 3,
-				dev->extra_buf2_address & 0xFF);
-	ene_write_reg(dev, ENE_FW_SAMPLE_BUFFER + 4,
-				dev->extra_buf2_address >> 8);
-	ene_write_reg(dev, ENE_FW_SAMPLE_BUFFER + 5,
-				dev->extra_buf2_len);
-	ene_clear_reg_mask(dev, ENE_FW1, ENE_FW1_EXTRA_BUF_HND);
-}
-
-/* Read hardware write pointer */
-static void ene_rx_read_hw_pointer(struct ene_device *dev)
-{
-	if (dev->hw_extra_buffer)
-		dev->w_pointer = ene_read_reg(dev, ENE_FW_RX_POINTER);
-	else
-		dev->w_pointer = ene_read_reg(dev, ENE_FW2)
-			& ENE_FW2_BUF_WPTR ? 0 : ENE_FW_PACKET_SIZE;
-
-	dbg_verbose("RB: HW write pointer: %02x, driver read pointer: %02x",
-		dev->w_pointer, dev->r_pointer);
-}
-
-/* Gets address of next sample from HW ring buffer */
-static int ene_rx_get_sample_reg(struct ene_device *dev)
-{
-	int r_pointer;
-
-	if (dev->r_pointer == dev->w_pointer) {
-		dbg_verbose("RB: hit end, try update w_pointer");
-		ene_rx_read_hw_pointer(dev);
-	}
-
-	if (dev->r_pointer == dev->w_pointer) {
-		dbg_verbose("RB: end of data at %d", dev->r_pointer);
-		return 0;
-	}
-
-	dbg_verbose("RB: reading at offset %d", dev->r_pointer);
-	r_pointer = dev->r_pointer;
-
-	dev->r_pointer++;
-	if (dev->r_pointer == dev->buffer_len)
-		dev->r_pointer = 0;
-
-	dbg_verbose("RB: next read will be from offset %d", dev->r_pointer);
-
-	if (r_pointer < 8) {
-		dbg_verbose("RB: read at main buffer at %d", r_pointer);
-		return ENE_FW_SAMPLE_BUFFER + r_pointer;
-	}
-
-	r_pointer -= 8;
-
-	if (r_pointer < dev->extra_buf1_len) {
-		dbg_verbose("RB: read at 1st extra buffer at %d", r_pointer);
-		return dev->extra_buf1_address + r_pointer;
-	}
-
-	r_pointer -= dev->extra_buf1_len;
-
-	if (r_pointer < dev->extra_buf2_len) {
-		dbg_verbose("RB: read at 2nd extra buffer at %d", r_pointer);
-		return dev->extra_buf2_address + r_pointer;
-	}
-
-	dbg("attempt to read beyong ring bufer end");
-	return 0;
-}
-
-/* Sense current received carrier */
-void ene_rx_sense_carrier(struct ene_device *dev)
-{
-	DEFINE_IR_RAW_EVENT(ev);
-
-	int carrier, duty_cycle;
-	int period = ene_read_reg(dev, ENE_CIRCAR_PRD);
-	int hperiod = ene_read_reg(dev, ENE_CIRCAR_HPRD);
-
-	if (!(period & ENE_CIRCAR_PRD_VALID))
-		return;
-
-	period &= ~ENE_CIRCAR_PRD_VALID;
-
-	if (!period)
-		return;
-
-	dbg("RX: hardware carrier period = %02x", period);
-	dbg("RX: hardware carrier pulse period = %02x", hperiod);
-
-	carrier = 2000000 / period;
-	duty_cycle = (hperiod * 100) / period;
-	dbg("RX: sensed carrier = %d Hz, duty cycle %d%%",
-						carrier, duty_cycle);
-	if (dev->carrier_detect_enabled) {
-		ev.carrier_report = true;
-		ev.carrier = carrier;
-		ev.duty_cycle = duty_cycle;
-		ir_raw_event_store(dev->idev, &ev);
-	}
-}
-
-/* this enables/disables the CIR RX engine */
-static void ene_rx_enable_cir_engine(struct ene_device *dev, bool enable)
-{
-	ene_set_clear_reg_mask(dev, ENE_CIRCFG,
-			ENE_CIRCFG_RX_EN | ENE_CIRCFG_RX_IRQ, enable);
-}
-
-/* this selects input for CIR engine. Ether GPIO 0A or GPIO40*/
-static void ene_rx_select_input(struct ene_device *dev, bool gpio_0a)
-{
-	ene_set_clear_reg_mask(dev, ENE_CIRCFG2, ENE_CIRCFG2_GPIO0A, gpio_0a);
-}
-
-/*
- * this enables alternative input via fan tachometer sensor and bypasses
- * the hw CIR engine
- */
-static void ene_rx_enable_fan_input(struct ene_device *dev, bool enable)
-{
-	if (!dev->hw_fan_input)
-		return;
-
-	if (!enable)
-		ene_write_reg(dev, ENE_FAN_AS_IN1, 0);
-	else {
-		ene_write_reg(dev, ENE_FAN_AS_IN1, ENE_FAN_AS_IN1_EN);
-		ene_write_reg(dev, ENE_FAN_AS_IN2, ENE_FAN_AS_IN2_EN);
-	}
-}
-
-/* setup the receiver for RX*/
-static void ene_rx_setup(struct ene_device *dev)
-{
-	bool learning_mode = dev->learning_mode_enabled ||
-					dev->carrier_detect_enabled;
-	int sample_period_adjust = 0;
-
-	dbg("RX: setup receiver, learning mode = %d", learning_mode);
-
-
-	/* This selects RLC input and clears CFG2 settings */
-	ene_write_reg(dev, ENE_CIRCFG2, 0x00);
-
-	/* set sample period*/
-	if (sample_period == ENE_DEFAULT_SAMPLE_PERIOD)
-		sample_period_adjust =
-			dev->pll_freq == ENE_DEFAULT_PLL_FREQ ? 1 : 2;
-
-	ene_write_reg(dev, ENE_CIRRLC_CFG,
-			(sample_period + sample_period_adjust) |
-						ENE_CIRRLC_CFG_OVERFLOW);
-	/* revB doesn't support inputs */
-	if (dev->hw_revision < ENE_HW_C)
-		goto select_timeout;
-
-	if (learning_mode) {
-
-		WARN_ON(!dev->hw_learning_and_tx_capable);
-
-		/* Enable the opposite of the normal input
-		That means that if GPIO40 is normally used, use GPIO0A
-		and vice versa.
-		This input will carry non demodulated
-		signal, and we will tell the hw to demodulate it itself */
-		ene_rx_select_input(dev, !dev->hw_use_gpio_0a);
-		dev->rx_fan_input_inuse = false;
-
-		/* Enable carrier demodulation */
-		ene_set_reg_mask(dev, ENE_CIRCFG, ENE_CIRCFG_CARR_DEMOD);
-
-		/* Enable carrier detection */
-		ene_write_reg(dev, ENE_CIRCAR_PULS, 0x63);
-		ene_set_clear_reg_mask(dev, ENE_CIRCFG2, ENE_CIRCFG2_CARR_DETECT,
-			dev->carrier_detect_enabled || debug);
-	} else {
-		if (dev->hw_fan_input)
-			dev->rx_fan_input_inuse = true;
-		else
-			ene_rx_select_input(dev, dev->hw_use_gpio_0a);
-
-		/* Disable carrier detection & demodulation */
-		ene_clear_reg_mask(dev, ENE_CIRCFG, ENE_CIRCFG_CARR_DEMOD);
-		ene_clear_reg_mask(dev, ENE_CIRCFG2, ENE_CIRCFG2_CARR_DETECT);
-	}
-
-select_timeout:
-	if (dev->rx_fan_input_inuse) {
-		dev->props->rx_resolution = MS_TO_NS(ENE_FW_SAMPLE_PERIOD_FAN);
-
-		/* Fan input doesn't support timeouts, it just ends the
-			input with a maximum sample */
-		dev->props->min_timeout = dev->props->max_timeout =
-			MS_TO_NS(ENE_FW_SMPL_BUF_FAN_MSK *
-				ENE_FW_SAMPLE_PERIOD_FAN);
-	} else {
-		dev->props->rx_resolution = MS_TO_NS(sample_period);
-
-		/* Theoreticly timeout is unlimited, but we cap it
-		 * because it was seen that on one device, it
-		 * would stop sending spaces after around 250 msec.
-		 * Besides, this is close to 2^32 anyway and timeout is u32.
-		 */
-		dev->props->min_timeout = MS_TO_NS(127 * sample_period);
-		dev->props->max_timeout = MS_TO_NS(200000);
-	}
-
-	if (dev->hw_learning_and_tx_capable)
-		dev->props->tx_resolution = MS_TO_NS(sample_period);
-
-	if (dev->props->timeout > dev->props->max_timeout)
-		dev->props->timeout = dev->props->max_timeout;
-	if (dev->props->timeout < dev->props->min_timeout)
-		dev->props->timeout = dev->props->min_timeout;
-}
-
-/* Enable the device for receive */
-static void ene_rx_enable(struct ene_device *dev)
-{
-	u8 reg_value;
-
-	/* Enable system interrupt */
-	if (dev->hw_revision < ENE_HW_C) {
-		ene_write_reg(dev, ENEB_IRQ, dev->irq << 1);
-		ene_write_reg(dev, ENEB_IRQ_UNK1, 0x01);
-	} else {
-		reg_value = ene_read_reg(dev, ENE_IRQ) & 0xF0;
-		reg_value |= ENE_IRQ_UNK_EN;
-		reg_value &= ~ENE_IRQ_STATUS;
-		reg_value |= (dev->irq & ENE_IRQ_MASK);
-		ene_write_reg(dev, ENE_IRQ, reg_value);
-	}
-
-	/* Enable inputs */
-	ene_rx_enable_fan_input(dev, dev->rx_fan_input_inuse);
-	ene_rx_enable_cir_engine(dev, !dev->rx_fan_input_inuse);
-
-	/* ack any pending irqs - just in case */
-	ene_irq_status(dev);
-
-	/* enable firmware bits */
-	ene_set_reg_mask(dev, ENE_FW1, ENE_FW1_ENABLE | ENE_FW1_IRQ);
-
-	/* enter idle mode */
-	ir_raw_event_set_idle(dev->idev, true);
-	dev->rx_enabled = true;
-}
-
-/* Disable the device receiver */
-static void ene_rx_disable(struct ene_device *dev)
-{
-	/* disable inputs */
-	ene_rx_enable_cir_engine(dev, false);
-	ene_rx_enable_fan_input(dev, false);
-
-	/* disable hardware IRQ and firmware flag */
-	ene_clear_reg_mask(dev, ENE_FW1, ENE_FW1_ENABLE | ENE_FW1_IRQ);
-
-	ir_raw_event_set_idle(dev->idev, true);
-	dev->rx_enabled = false;
-}
-
-/* This resets the receiver. Usefull to stop stream of spaces at end of
- * transmission
- */
-static void ene_rx_reset(struct ene_device *dev)
-{
-	ene_clear_reg_mask(dev, ENE_CIRCFG, ENE_CIRCFG_RX_EN);
-	ene_set_reg_mask(dev, ENE_CIRCFG, ENE_CIRCFG_RX_EN);
-}
-
-/* Set up the TX carrier frequency and duty cycle */
-static void ene_tx_set_carrier(struct ene_device *dev)
-{
-	u8 tx_puls_width;
-	unsigned long flags;
-
-	spin_lock_irqsave(&dev->hw_lock, flags);
-
-	ene_set_clear_reg_mask(dev, ENE_CIRCFG,
-		ENE_CIRCFG_TX_CARR, dev->tx_period > 0);
-
-	if (!dev->tx_period)
-		goto unlock;
-
-	BUG_ON(dev->tx_duty_cycle >= 100 || dev->tx_duty_cycle <= 0);
-
-	tx_puls_width = dev->tx_period / (100 / dev->tx_duty_cycle);
-
-	if (!tx_puls_width)
-		tx_puls_width = 1;
-
-	dbg("TX: pulse distance = %d * 500 ns", dev->tx_period);
-	dbg("TX: pulse width = %d * 500 ns", tx_puls_width);
-
-	ene_write_reg(dev, ENE_CIRMOD_PRD, dev->tx_period | ENE_CIRMOD_PRD_POL);
-	ene_write_reg(dev, ENE_CIRMOD_HPRD, tx_puls_width);
-unlock:
-	spin_unlock_irqrestore(&dev->hw_lock, flags);
-}
-
-/* Enable/disable transmitters */
-static void ene_tx_set_transmitters(struct ene_device *dev)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&dev->hw_lock, flags);
-	ene_set_clear_reg_mask(dev, ENE_GPIOFS8, ENE_GPIOFS8_GPIO41,
-					!!(dev->transmitter_mask & 0x01));
-	ene_set_clear_reg_mask(dev, ENE_GPIOFS1, ENE_GPIOFS1_GPIO0D,
-					!!(dev->transmitter_mask & 0x02));
-	spin_unlock_irqrestore(&dev->hw_lock, flags);
-}
-
-/* prepare transmission */
-static void ene_tx_enable(struct ene_device *dev)
-{
-	u8 conf1 = ene_read_reg(dev, ENE_CIRCFG);
-	u8 fwreg2 = ene_read_reg(dev, ENE_FW2);
-
-	dev->saved_conf1 = conf1;
-
-	/* Show information about currently connected transmitter jacks */
-	if (fwreg2 & ENE_FW2_EMMITER1_CONN)
-		dbg("TX: Transmitter #1 is connected");
-
-	if (fwreg2 & ENE_FW2_EMMITER2_CONN)
-		dbg("TX: Transmitter #2 is connected");
-
-	if (!(fwreg2 & (ENE_FW2_EMMITER1_CONN | ENE_FW2_EMMITER2_CONN)))
-		ene_warn("TX: transmitter cable isn't connected!");
-
-	/* disable receive on revc */
-	if (dev->hw_revision == ENE_HW_C)
-		conf1 &= ~ENE_CIRCFG_RX_EN;
-
-	/* Enable TX engine */
-	conf1 |= ENE_CIRCFG_TX_EN | ENE_CIRCFG_TX_IRQ;
-	ene_write_reg(dev, ENE_CIRCFG, conf1);
-}
-
-/* end transmission */
-static void ene_tx_disable(struct ene_device *dev)
-{
-	ene_write_reg(dev, ENE_CIRCFG, dev->saved_conf1);
-	dev->tx_buffer = NULL;
-}
-
-
-/* TX one sample - must be called with dev->hw_lock*/
-static void ene_tx_sample(struct ene_device *dev)
-{
-	u8 raw_tx;
-	u32 sample;
-	bool pulse = dev->tx_sample_pulse;
-
-	if (!dev->tx_buffer) {
-		ene_warn("TX: BUG: attempt to transmit NULL buffer");
-		return;
-	}
-
-	/* Grab next TX sample */
-	if (!dev->tx_sample) {
-
-		if (dev->tx_pos == dev->tx_len) {
-			if (!dev->tx_done) {
-				dbg("TX: no more data to send");
-				dev->tx_done = true;
-				goto exit;
-			} else {
-				dbg("TX: last sample sent by hardware");
-				ene_tx_disable(dev);
-				complete(&dev->tx_complete);
-				return;
-			}
-		}
-
-		sample = dev->tx_buffer[dev->tx_pos++];
-		dev->tx_sample_pulse = !dev->tx_sample_pulse;
-
-		dev->tx_sample = DIV_ROUND_CLOSEST(sample, sample_period);
-
-		if (!dev->tx_sample)
-			dev->tx_sample = 1;
-	}
-
-	raw_tx = min(dev->tx_sample , (unsigned int)ENE_CIRRLC_OUT_MASK);
-	dev->tx_sample -= raw_tx;
-
-	dbg("TX: sample %8d (%s)", raw_tx * sample_period,
-						pulse ? "pulse" : "space");
-	if (pulse)
-		raw_tx |= ENE_CIRRLC_OUT_PULSE;
-
-	ene_write_reg(dev,
-		dev->tx_reg ? ENE_CIRRLC_OUT1 : ENE_CIRRLC_OUT0, raw_tx);
-
-	dev->tx_reg = !dev->tx_reg;
-exit:
-	/* simulate TX done interrupt */
-	if (txsim)
-		mod_timer(&dev->tx_sim_timer, jiffies + HZ / 500);
-}
-
-/* timer to simulate tx done interrupt */
-static void ene_tx_irqsim(unsigned long data)
-{
-	struct ene_device *dev = (struct ene_device *)data;
-	unsigned long flags;
-
-	spin_lock_irqsave(&dev->hw_lock, flags);
-	ene_tx_sample(dev);
-	spin_unlock_irqrestore(&dev->hw_lock, flags);
-}
-
-
-/* read irq status and ack it */
-static int ene_irq_status(struct ene_device *dev)
-{
-	u8 irq_status;
-	u8 fw_flags1, fw_flags2;
-	int retval = 0;
-
-	fw_flags2 = ene_read_reg(dev, ENE_FW2);
-
-	if (dev->hw_revision < ENE_HW_C) {
-		irq_status = ene_read_reg(dev, ENEB_IRQ_STATUS);
-
-		if (!(irq_status & ENEB_IRQ_STATUS_IR))
-			return 0;
-
-		ene_clear_reg_mask(dev, ENEB_IRQ_STATUS, ENEB_IRQ_STATUS_IR);
-		return ENE_IRQ_RX;
-	}
-
-	irq_status = ene_read_reg(dev, ENE_IRQ);
-	if (!(irq_status & ENE_IRQ_STATUS))
-		return 0;
-
-	/* original driver does that twice - a workaround ? */
-	ene_write_reg(dev, ENE_IRQ, irq_status & ~ENE_IRQ_STATUS);
-	ene_write_reg(dev, ENE_IRQ, irq_status & ~ENE_IRQ_STATUS);
-
-	/* check RX interrupt */
-	if (fw_flags2 & ENE_FW2_RXIRQ) {
-		retval |= ENE_IRQ_RX;
-		ene_write_reg(dev, ENE_FW2, fw_flags2 & ~ENE_FW2_RXIRQ);
-	}
-
-	/* check TX interrupt */
-	fw_flags1 = ene_read_reg(dev, ENE_FW1);
-	if (fw_flags1 & ENE_FW1_TXIRQ) {
-		ene_write_reg(dev, ENE_FW1, fw_flags1 & ~ENE_FW1_TXIRQ);
-		retval |= ENE_IRQ_TX;
-	}
-
-	return retval;
-}
-
-/* interrupt handler */
-static irqreturn_t ene_isr(int irq, void *data)
-{
-	u16 hw_value, reg;
-	int hw_sample, irq_status;
-	bool pulse;
-	unsigned long flags;
-	irqreturn_t retval = IRQ_NONE;
-	struct ene_device *dev = (struct ene_device *)data;
-	DEFINE_IR_RAW_EVENT(ev);
-
-	spin_lock_irqsave(&dev->hw_lock, flags);
-
-	dbg_verbose("ISR called");
-	ene_rx_read_hw_pointer(dev);
-	irq_status = ene_irq_status(dev);
-
-	if (!irq_status)
-		goto unlock;
-
-	retval = IRQ_HANDLED;
-
-	if (irq_status & ENE_IRQ_TX) {
-		dbg_verbose("TX interrupt");
-		if (!dev->hw_learning_and_tx_capable) {
-			dbg("TX interrupt on unsupported device!");
-			goto unlock;
-		}
-		ene_tx_sample(dev);
-	}
-
-	if (!(irq_status & ENE_IRQ_RX))
-		goto unlock;
-
-	dbg_verbose("RX interrupt");
-
-	if (dev->hw_learning_and_tx_capable)
-		ene_rx_sense_carrier(dev);
-
-	/* On hardware that don't support extra buffer we need to trust
-		the interrupt and not track the read pointer */
-	if (!dev->hw_extra_buffer)
-		dev->r_pointer = dev->w_pointer == 0 ? ENE_FW_PACKET_SIZE : 0;
-
-	while (1) {
-
-		reg = ene_rx_get_sample_reg(dev);
-
-		dbg_verbose("next sample to read at: %04x", reg);
-		if (!reg)
-			break;
-
-		hw_value = ene_read_reg(dev, reg);
-
-		if (dev->rx_fan_input_inuse) {
-
-			int offset = ENE_FW_SMPL_BUF_FAN - ENE_FW_SAMPLE_BUFFER;
-
-			/* read high part of the sample */
-			hw_value |= ene_read_reg(dev, reg + offset) << 8;
-			pulse = hw_value & ENE_FW_SMPL_BUF_FAN_PLS;
-
-			/* clear space bit, and other unused bits */
-			hw_value &= ENE_FW_SMPL_BUF_FAN_MSK;
-			hw_sample = hw_value * ENE_FW_SAMPLE_PERIOD_FAN;
-
-		} else {
-			pulse = !(hw_value & ENE_FW_SAMPLE_SPACE);
-			hw_value &= ~ENE_FW_SAMPLE_SPACE;
-			hw_sample = hw_value * sample_period;
-
-			if (dev->rx_period_adjust) {
-				hw_sample *= 100;
-				hw_sample /= (100 + dev->rx_period_adjust);
-			}
-		}
-
-		if (!dev->hw_extra_buffer && !hw_sample) {
-			dev->r_pointer = dev->w_pointer;
-			continue;
-		}
-
-		dbg("RX: %d (%s)", hw_sample, pulse ? "pulse" : "space");
-
-		ev.duration = MS_TO_NS(hw_sample);
-		ev.pulse = pulse;
-		ir_raw_event_store_with_filter(dev->idev, &ev);
-	}
-
-	ir_raw_event_handle(dev->idev);
-unlock:
-	spin_unlock_irqrestore(&dev->hw_lock, flags);
-	return retval;
-}
-
-/* Initialize default settings */
-static void ene_setup_default_settings(struct ene_device *dev)
-{
-	dev->tx_period = 32;
-	dev->tx_duty_cycle = 50; /*%*/
-	dev->transmitter_mask = 0x03;
-	dev->learning_mode_enabled = learning_mode_force;
-
-	/* Set reasonable default timeout */
-	dev->props->timeout = MS_TO_NS(150000);
-}
-
-/* Upload all hardware settings at once. Used at load and resume time */
-static void ene_setup_hw_settings(struct ene_device *dev)
-{
-	if (dev->hw_learning_and_tx_capable) {
-		ene_tx_set_carrier(dev);
-		ene_tx_set_transmitters(dev);
-	}
-
-	ene_rx_setup(dev);
-}
-
-/* outside interface: called on first open*/
-static int ene_open(void *data)
-{
-	struct ene_device *dev = (struct ene_device *)data;
-	unsigned long flags;
-
-	spin_lock_irqsave(&dev->hw_lock, flags);
-	ene_rx_enable(dev);
-	spin_unlock_irqrestore(&dev->hw_lock, flags);
-	return 0;
-}
-
-/* outside interface: called on device close*/
-static void ene_close(void *data)
-{
-	struct ene_device *dev = (struct ene_device *)data;
-	unsigned long flags;
-	spin_lock_irqsave(&dev->hw_lock, flags);
-
-	ene_rx_disable(dev);
-	spin_unlock_irqrestore(&dev->hw_lock, flags);
-}
-
-/* outside interface: set transmitter mask */
-static int ene_set_tx_mask(void *data, u32 tx_mask)
-{
-	struct ene_device *dev = (struct ene_device *)data;
-	dbg("TX: attempt to set transmitter mask %02x", tx_mask);
-
-	/* invalid txmask */
-	if (!tx_mask || tx_mask & ~0x03) {
-		dbg("TX: invalid mask");
-		/* return count of transmitters */
-		return 2;
-	}
-
-	dev->transmitter_mask = tx_mask;
-	ene_tx_set_transmitters(dev);
-	return 0;
-}
-
-/* outside interface : set tx carrier */
-static int ene_set_tx_carrier(void *data, u32 carrier)
-{
-	struct ene_device *dev = (struct ene_device *)data;
-	u32 period = 2000000 / carrier;
-
-	dbg("TX: attempt to set tx carrier to %d kHz", carrier);
-
-	if (period && (period > ENE_CIRMOD_PRD_MAX ||
-			period < ENE_CIRMOD_PRD_MIN)) {
-
-		dbg("TX: out of range %d-%d kHz carrier",
-			2000 / ENE_CIRMOD_PRD_MIN, 2000 / ENE_CIRMOD_PRD_MAX);
-		return -1;
-	}
-
-	dev->tx_period = period;
-	ene_tx_set_carrier(dev);
-	return 0;
-}
-
-/*outside interface : set tx duty cycle */
-static int ene_set_tx_duty_cycle(void *data, u32 duty_cycle)
-{
-	struct ene_device *dev = (struct ene_device *)data;
-	dbg("TX: setting duty cycle to %d%%", duty_cycle);
-	dev->tx_duty_cycle = duty_cycle;
-	ene_tx_set_carrier(dev);
-	return 0;
-}
-
-/* outside interface: enable learning mode */
-static int ene_set_learning_mode(void *data, int enable)
-{
-	struct ene_device *dev = (struct ene_device *)data;
-	unsigned long flags;
-	if (enable == dev->learning_mode_enabled)
-		return 0;
-
-	spin_lock_irqsave(&dev->hw_lock, flags);
-	dev->learning_mode_enabled = enable;
-	ene_rx_disable(dev);
-	ene_rx_setup(dev);
-	ene_rx_enable(dev);
-	spin_unlock_irqrestore(&dev->hw_lock, flags);
-	return 0;
-}
-
-static int ene_set_carrier_report(void *data, int enable)
-{
-	struct ene_device *dev = (struct ene_device *)data;
-	unsigned long flags;
-
-	if (enable == dev->carrier_detect_enabled)
-		return 0;
-
-	spin_lock_irqsave(&dev->hw_lock, flags);
-	dev->carrier_detect_enabled = enable;
-	ene_rx_disable(dev);
-	ene_rx_setup(dev);
-	ene_rx_enable(dev);
-	spin_unlock_irqrestore(&dev->hw_lock, flags);
-	return 0;
-}
-
-/* outside interface: enable or disable idle mode */
-static void ene_set_idle(void *data, bool idle)
-{
-	if (idle) {
-		ene_rx_reset((struct ene_device *)data);
-		dbg("RX: end of data");
-	}
-}
-
-/* outside interface: transmit */
-static int ene_transmit(void *data, int *buf, u32 n)
-{
-	struct ene_device *dev = (struct ene_device *)data;
-	unsigned long flags;
-
-	dev->tx_buffer = buf;
-	dev->tx_len = n / sizeof(int);
-	dev->tx_pos = 0;
-	dev->tx_reg = 0;
-	dev->tx_done = 0;
-	dev->tx_sample = 0;
-	dev->tx_sample_pulse = 0;
-
-	dbg("TX: %d samples", dev->tx_len);
-
-	spin_lock_irqsave(&dev->hw_lock, flags);
-
-	ene_tx_enable(dev);
-
-	/* Transmit first two samples */
-	ene_tx_sample(dev);
-	ene_tx_sample(dev);
-
-	spin_unlock_irqrestore(&dev->hw_lock, flags);
-
-	if (wait_for_completion_timeout(&dev->tx_complete, 2 * HZ) == 0) {
-		dbg("TX: timeout");
-		spin_lock_irqsave(&dev->hw_lock, flags);
-		ene_tx_disable(dev);
-		spin_unlock_irqrestore(&dev->hw_lock, flags);
-	} else
-		dbg("TX: done");
-	return n;
-}
-
-/* probe entry */
-static int ene_probe(struct pnp_dev *pnp_dev, const struct pnp_device_id *id)
-{
-	int error = -ENOMEM;
-	struct ir_dev_props *ir_props;
-	struct input_dev *input_dev;
-	struct ene_device *dev;
-
-	/* allocate memory */
-	input_dev = input_allocate_device();
-	ir_props = kzalloc(sizeof(struct ir_dev_props), GFP_KERNEL);
-	dev = kzalloc(sizeof(struct ene_device), GFP_KERNEL);
-
-	if (!input_dev || !ir_props || !dev)
-		goto error1;
-
-	/* validate resources */
-	error = -ENODEV;
-
-	if (!pnp_port_valid(pnp_dev, 0) ||
-	    pnp_port_len(pnp_dev, 0) < ENE_IO_SIZE)
-		goto error;
-
-	if (!pnp_irq_valid(pnp_dev, 0))
-		goto error;
-
-	spin_lock_init(&dev->hw_lock);
-
-	/* claim the resources */
-	error = -EBUSY;
-	dev->hw_io = pnp_port_start(pnp_dev, 0);
-	if (!request_region(dev->hw_io, ENE_IO_SIZE, ENE_DRIVER_NAME)) {
-		dev->hw_io = -1;
-		dev->irq = -1;
-		goto error;
-	}
-
-	dev->irq = pnp_irq(pnp_dev, 0);
-	if (request_irq(dev->irq, ene_isr,
-			IRQF_SHARED, ENE_DRIVER_NAME, (void *)dev)) {
-		dev->irq = -1;
-		goto error;
-	}
-
-	pnp_set_drvdata(pnp_dev, dev);
-	dev->pnp_dev = pnp_dev;
-
-	/* don't allow too short/long sample periods */
-	if (sample_period < 5 || sample_period > 0x7F)
-		sample_period = ENE_DEFAULT_SAMPLE_PERIOD;
-
-	/* detect hardware version and features */
-	error = ene_hw_detect(dev);
-	if (error)
-		goto error;
-
-	if (!dev->hw_learning_and_tx_capable && txsim) {
-		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");
-	}
-
-	if (!dev->hw_learning_and_tx_capable)
-		learning_mode_force = false;
-
-	ir_props->driver_type = RC_DRIVER_IR_RAW;
-	ir_props->allowed_protos = IR_TYPE_ALL;
-	ir_props->priv = dev;
-	ir_props->open = ene_open;
-	ir_props->close = ene_close;
-	ir_props->s_idle = ene_set_idle;
-
-	dev->props = ir_props;
-	dev->idev = input_dev;
-
-	if (dev->hw_learning_and_tx_capable) {
-		ir_props->s_learning_mode = ene_set_learning_mode;
-		init_completion(&dev->tx_complete);
-		ir_props->tx_ir = ene_transmit;
-		ir_props->s_tx_mask = ene_set_tx_mask;
-		ir_props->s_tx_carrier = ene_set_tx_carrier;
-		ir_props->s_tx_duty_cycle = ene_set_tx_duty_cycle;
-		ir_props->s_carrier_report = ene_set_carrier_report;
-	}
-
-	ene_rx_setup_hw_buffer(dev);
-	ene_setup_default_settings(dev);
-	ene_setup_hw_settings(dev);
-
-	device_set_wakeup_capable(&pnp_dev->dev, true);
-	device_set_wakeup_enable(&pnp_dev->dev, true);
-
-	if (dev->hw_learning_and_tx_capable)
-		input_dev->name = "ENE eHome Infrared Remote Transceiver";
-	else
-		input_dev->name = "ENE eHome Infrared Remote Receiver";
-
-	error = -ENODEV;
-	if (ir_input_register(input_dev, RC_MAP_RC6_MCE, ir_props,
-							ENE_DRIVER_NAME))
-		goto error;
-
-	ene_notice("driver has been succesfully loaded");
-	return 0;
-error:
-	if (dev && dev->irq >= 0)
-		free_irq(dev->irq, dev);
-	if (dev && dev->hw_io >= 0)
-		release_region(dev->hw_io, ENE_IO_SIZE);
-error1:
-	input_free_device(input_dev);
-	kfree(ir_props);
-	kfree(dev);
-	return error;
-}
-
-/* main unload function */
-static void ene_remove(struct pnp_dev *pnp_dev)
-{
-	struct ene_device *dev = pnp_get_drvdata(pnp_dev);
-	unsigned long flags;
-
-	spin_lock_irqsave(&dev->hw_lock, flags);
-	ene_rx_disable(dev);
-	ene_rx_restore_hw_buffer(dev);
-	spin_unlock_irqrestore(&dev->hw_lock, flags);
-
-	free_irq(dev->irq, dev);
-	release_region(dev->hw_io, ENE_IO_SIZE);
-	ir_input_unregister(dev->idev);
-	kfree(dev->props);
-	kfree(dev);
-}
-
-/* enable wake on IR (wakes on specific button on original remote) */
-static void ene_enable_wake(struct ene_device *dev, int enable)
-{
-	enable = enable && device_may_wakeup(&dev->pnp_dev->dev);
-	dbg("wake on IR %s", enable ? "enabled" : "disabled");
-	ene_set_clear_reg_mask(dev, ENE_FW1, ENE_FW1_WAKE, enable);
-}
-
-#ifdef CONFIG_PM
-static int ene_suspend(struct pnp_dev *pnp_dev, pm_message_t state)
-{
-	struct ene_device *dev = pnp_get_drvdata(pnp_dev);
-	ene_enable_wake(dev, true);
-
-	/* TODO: add support for wake pattern */
-	return 0;
-}
-
-static int ene_resume(struct pnp_dev *pnp_dev)
-{
-	struct ene_device *dev = pnp_get_drvdata(pnp_dev);
-	ene_setup_hw_settings(dev);
-
-	if (dev->rx_enabled)
-		ene_rx_enable(dev);
-
-	ene_enable_wake(dev, false);
-	return 0;
-}
-#endif
-
-static void ene_shutdown(struct pnp_dev *pnp_dev)
-{
-	struct ene_device *dev = pnp_get_drvdata(pnp_dev);
-	ene_enable_wake(dev, true);
-}
-
-static const struct pnp_device_id ene_ids[] = {
-	{.id = "ENE0100",},
-	{.id = "ENE0200",},
-	{.id = "ENE0201",},
-	{.id = "ENE0202",},
-	{},
-};
-
-static struct pnp_driver ene_driver = {
-	.name = ENE_DRIVER_NAME,
-	.id_table = ene_ids,
-	.flags = PNP_DRIVER_RES_DO_NOT_CHANGE,
-
-	.probe = ene_probe,
-	.remove = __devexit_p(ene_remove),
-#ifdef CONFIG_PM
-	.suspend = ene_suspend,
-	.resume = ene_resume,
-#endif
-	.shutdown = ene_shutdown,
-};
-
-static int __init ene_init(void)
-{
-	return pnp_register_driver(&ene_driver);
-}
-
-static void ene_exit(void)
-{
-	pnp_unregister_driver(&ene_driver);
-}
-
-module_param(sample_period, int, S_IRUGO);
-MODULE_PARM_DESC(sample_period, "Hardware sample period (50 us default)");
-
-module_param(learning_mode_force, bool, S_IRUGO);
-MODULE_PARM_DESC(learning_mode_force, "Enable learning mode by default");
-
-module_param(debug, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(debug, "Debug level");
-
-module_param(txsim, bool, S_IRUGO);
-MODULE_PARM_DESC(txsim,
-	"Simulate TX features on unsupported hardware (dangerous)");
-
-MODULE_DEVICE_TABLE(pnp, ene_ids);
-MODULE_DESCRIPTION
-	("Infrared input driver for KB3926B/C/D/E/F "
-	"(aka ENE0100/ENE0200/ENE0201/ENE0202) CIR port");
-
-MODULE_AUTHOR("Maxim Levitsky");
-MODULE_LICENSE("GPL");
-
-module_init(ene_init);
-module_exit(ene_exit);
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/ene_ir.h linux-libre-2.6.38-gnu1/drivers/media/IR/ene_ir.h
--- linux-libre-2.6.37-gnu1/drivers/media/IR/ene_ir.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/ene_ir.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,262 +0,0 @@
-/*
- * driver for ENE KB3926 B/C/D/E/F CIR (also known as ENE0XXX)
- *
- * Copyright (C) 2010 Maxim Levitsky <maximlevitsky@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
- */
-#include <linux/spinlock.h>
-
-
-/* hardware address */
-#define ENE_STATUS		0	/* hardware status - unused */
-#define ENE_ADDR_HI		1	/* hi byte of register address */
-#define ENE_ADDR_LO		2	/* low byte of register address */
-#define ENE_IO			3	/* read/write window */
-#define ENE_IO_SIZE		4
-
-/* 8 bytes of samples, divided in 2 packets*/
-#define ENE_FW_SAMPLE_BUFFER	0xF8F0	/* sample buffer */
-#define ENE_FW_SAMPLE_SPACE	0x80	/* sample is space */
-#define ENE_FW_PACKET_SIZE	4
-
-/* first firmware flag register */
-#define ENE_FW1			0xF8F8  /* flagr */
-#define	ENE_FW1_ENABLE		0x01	/* enable fw processing */
-#define ENE_FW1_TXIRQ		0x02	/* TX interrupt pending */
-#define ENE_FW1_HAS_EXTRA_BUF	0x04	/* fw uses extra buffer*/
-#define ENE_FW1_EXTRA_BUF_HND	0x08	/* extra buffer handshake bit*/
-#define ENE_FW1_LED_ON		0x10	/* turn on a led */
-
-#define ENE_FW1_WPATTERN	0x20	/* enable wake pattern */
-#define ENE_FW1_WAKE		0x40	/* enable wake from S3 */
-#define ENE_FW1_IRQ		0x80	/* enable interrupt */
-
-/* second firmware flag register */
-#define ENE_FW2			0xF8F9  /* flagw */
-#define ENE_FW2_BUF_WPTR	0x01	/* which half of the buffer to read */
-#define ENE_FW2_RXIRQ		0x04	/* RX IRQ pending*/
-#define ENE_FW2_GP0A		0x08	/* Use GPIO0A for demodulated input */
-#define ENE_FW2_EMMITER1_CONN	0x10	/* TX emmiter 1 connected */
-#define ENE_FW2_EMMITER2_CONN	0x20	/* TX emmiter 2 connected */
-
-#define ENE_FW2_FAN_INPUT	0x40	/* fan input used for demodulated data*/
-#define ENE_FW2_LEARNING	0x80	/* hardware supports learning and TX */
-
-/* firmware RX pointer for new style buffer */
-#define ENE_FW_RX_POINTER	0xF8FA
-
-/* high parts of samples for fan input (8 samples)*/
-#define ENE_FW_SMPL_BUF_FAN	0xF8FB
-#define ENE_FW_SMPL_BUF_FAN_PLS	0x8000	/* combined sample is pulse */
-#define ENE_FW_SMPL_BUF_FAN_MSK	0x0FFF  /* combined sample maximum value */
-#define ENE_FW_SAMPLE_PERIOD_FAN 61	/* fan input has fixed sample period */
-
-/* transmitter ports */
-#define ENE_GPIOFS1		0xFC01
-#define ENE_GPIOFS1_GPIO0D	0x20	/* enable tx output on GPIO0D */
-#define ENE_GPIOFS8		0xFC08
-#define ENE_GPIOFS8_GPIO41	0x02	/* enable tx output on GPIO40 */
-
-/* IRQ registers block (for revision B) */
-#define ENEB_IRQ		0xFD09	/* IRQ number */
-#define ENEB_IRQ_UNK1		0xFD17	/* unknown setting = 1 */
-#define ENEB_IRQ_STATUS		0xFD80	/* irq status */
-#define ENEB_IRQ_STATUS_IR	0x20	/* IR irq */
-
-/* fan as input settings */
-#define ENE_FAN_AS_IN1		0xFE30  /* fan init reg 1 */
-#define ENE_FAN_AS_IN1_EN	0xCD
-#define ENE_FAN_AS_IN2		0xFE31  /* fan init reg 2 */
-#define ENE_FAN_AS_IN2_EN	0x03
-
-/* IRQ registers block (for revision C,D) */
-#define ENE_IRQ			0xFE9B	/* new irq settings register */
-#define ENE_IRQ_MASK		0x0F	/* irq number mask */
-#define ENE_IRQ_UNK_EN		0x10	/* always enabled */
-#define ENE_IRQ_STATUS		0x20	/* irq status and ACK */
-
-/* CIR Config register #1 */
-#define ENE_CIRCFG		0xFEC0
-#define ENE_CIRCFG_RX_EN	0x01	/* RX enable */
-#define ENE_CIRCFG_RX_IRQ	0x02	/* Enable hardware interrupt */
-#define ENE_CIRCFG_REV_POL	0x04	/* Input polarity reversed */
-#define ENE_CIRCFG_CARR_DEMOD	0x08	/* Enable carrier demodulator */
-
-#define ENE_CIRCFG_TX_EN	0x10	/* TX enable */
-#define ENE_CIRCFG_TX_IRQ	0x20	/* Send interrupt on TX done */
-#define ENE_CIRCFG_TX_POL_REV	0x40	/* TX polarity reversed */
-#define ENE_CIRCFG_TX_CARR	0x80	/* send TX carrier or not */
-
-/* CIR config register #2 */
-#define ENE_CIRCFG2		0xFEC1
-#define ENE_CIRCFG2_RLC		0x00
-#define ENE_CIRCFG2_RC5		0x01
-#define ENE_CIRCFG2_RC6		0x02
-#define ENE_CIRCFG2_NEC		0x03
-#define ENE_CIRCFG2_CARR_DETECT	0x10	/* Enable carrier detection */
-#define ENE_CIRCFG2_GPIO0A	0x20	/* Use GPIO0A instead of GPIO40 for input */
-#define ENE_CIRCFG2_FAST_SAMPL1	0x40	/* Fast leading pulse detection for RC6 */
-#define ENE_CIRCFG2_FAST_SAMPL2	0x80	/* Fast data detection for RC6 */
-
-/* Knobs for protocol decoding - will document when/if will use them */
-#define ENE_CIRPF		0xFEC2
-#define ENE_CIRHIGH		0xFEC3
-#define ENE_CIRBIT		0xFEC4
-#define ENE_CIRSTART		0xFEC5
-#define ENE_CIRSTART2		0xFEC6
-
-/* Actual register which contains RLC RX data - read by firmware */
-#define ENE_CIRDAT_IN		0xFEC7
-
-
-/* RLC configuration - sample period (1us resulution) + idle mode */
-#define ENE_CIRRLC_CFG		0xFEC8
-#define ENE_CIRRLC_CFG_OVERFLOW	0x80	/* interrupt on overflows if set */
-#define ENE_DEFAULT_SAMPLE_PERIOD 50
-
-/* Two byte RLC TX buffer */
-#define ENE_CIRRLC_OUT0		0xFEC9
-#define ENE_CIRRLC_OUT1		0xFECA
-#define ENE_CIRRLC_OUT_PULSE	0x80	/* Transmitted sample is pulse */
-#define ENE_CIRRLC_OUT_MASK	0x7F
-
-
-/* Carrier detect setting
- * Low nibble  - number of carrier pulses to average
- * High nibble - number of initial carrier pulses to discard
- */
-#define ENE_CIRCAR_PULS		0xFECB
-
-/* detected RX carrier period (resolution: 500 ns) */
-#define ENE_CIRCAR_PRD		0xFECC
-#define ENE_CIRCAR_PRD_VALID	0x80	/* data valid content valid */
-
-/* detected RX carrier pulse width (resolution: 500 ns) */
-#define ENE_CIRCAR_HPRD		0xFECD
-
-/* TX period (resolution: 500 ns, minimum 2)*/
-#define ENE_CIRMOD_PRD		0xFECE
-#define ENE_CIRMOD_PRD_POL	0x80	/* TX carrier polarity*/
-
-#define ENE_CIRMOD_PRD_MAX	0x7F	/* 15.87 kHz */
-#define ENE_CIRMOD_PRD_MIN	0x02	/* 1 Mhz */
-
-/* TX pulse width (resolution: 500 ns)*/
-#define ENE_CIRMOD_HPRD		0xFECF
-
-/* Hardware versions */
-#define ENE_ECHV		0xFF00	/* hardware revision */
-#define ENE_PLLFRH		0xFF16
-#define ENE_PLLFRL		0xFF17
-#define ENE_DEFAULT_PLL_FREQ	1000
-
-#define ENE_ECSTS		0xFF1D
-#define ENE_ECSTS_RSRVD		0x04
-
-#define ENE_ECVER_MAJOR		0xFF1E	/* chip version */
-#define ENE_ECVER_MINOR		0xFF1F
-#define ENE_HW_VER_OLD		0xFD00
-
-/******************************************************************************/
-
-#define ENE_DRIVER_NAME		"ene_ir"
-
-#define ENE_IRQ_RX		1
-#define ENE_IRQ_TX		2
-
-#define  ENE_HW_B		1	/* 3926B */
-#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(format, ...)		__dbg(1, format, ## __VA_ARGS__)
-#define dbg_verbose(format, ...)	__dbg(2, format, ## __VA_ARGS__)
-#define dbg_regs(format, ...)		__dbg(3, format, ## __VA_ARGS__)
-
-#define MS_TO_NS(msec) ((msec) * 1000)
-
-struct ene_device {
-	struct pnp_dev *pnp_dev;
-	struct input_dev *idev;
-	struct ir_dev_props *props;
-
-	/* hw IO settings */
-	long hw_io;
-	int irq;
-	spinlock_t hw_lock;
-
-	/* HW features */
-	int hw_revision;			/* hardware revision */
-	bool hw_use_gpio_0a;			/* gpio0a is demodulated input*/
-	bool hw_extra_buffer;			/* hardware has 'extra buffer' */
-	bool hw_fan_input;			/* fan input is IR data source */
-	bool hw_learning_and_tx_capable;	/* learning & tx capable */
-	int  pll_freq;
-	int buffer_len;
-
-	/* Extra RX buffer location */
-	int extra_buf1_address;
-	int extra_buf1_len;
-	int extra_buf2_address;
-	int extra_buf2_len;
-
-	/* HW state*/
-	int r_pointer;				/* pointer to next sample to read */
-	int w_pointer;				/* pointer to next sample hw will write */
-	bool rx_fan_input_inuse;		/* is fan input in use for rx*/
-	int tx_reg;				/* current reg used for TX */
-	u8  saved_conf1;			/* saved FEC0 reg */
-	unsigned int tx_sample;			/* current sample for TX */
-	bool tx_sample_pulse;			/* current sample is pulse */
-
-	/* TX buffer */
-	int *tx_buffer;				/* input samples buffer*/
-	int tx_pos;				/* position in that bufer */
-	int tx_len;				/* current len of tx buffer */
-	int tx_done;				/* done transmitting */
-						/* one more sample pending*/
-	struct completion tx_complete;		/* TX completion */
-	struct timer_list tx_sim_timer;
-
-	/* TX settings */
-	int tx_period;
-	int tx_duty_cycle;
-	int transmitter_mask;
-
-	/* RX settings */
-	bool learning_mode_enabled;		/* learning input enabled */
-	bool carrier_detect_enabled;		/* carrier detect enabled */
-	int rx_period_adjust;
-	bool rx_enabled;
-};
-
-static int ene_irq_status(struct ene_device *dev);
-static void ene_rx_read_hw_pointer(struct ene_device *dev);
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/imon.c linux-libre-2.6.38-gnu1/drivers/media/IR/imon.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/imon.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/imon.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,2470 +0,0 @@
-/*
- *   imon.c:	input and display driver for SoundGraph iMON IR/VFD/LCD
- *
- *   Copyright(C) 2010  Jarod Wilson <jarod@wilsonet.com>
- *   Portions based on the original lirc_imon driver,
- *	Copyright(C) 2004  Venky Raju(dev@venky.ws)
- *
- *   Huge thanks to R. Geoff Newbury for invaluable debugging on the
- *   0xffdc iMON devices, and for sending me one to hack on, without
- *   which the support for them wouldn't be nearly as good. Thanks
- *   also to the numerous 0xffdc device owners that tested auto-config
- *   support for me and provided debug dumps from their devices.
- *
- *   imon 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 ":%s: " fmt, __func__
-
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/uaccess.h>
-
-#include <linux/input.h>
-#include <linux/usb.h>
-#include <linux/usb/input.h>
-#include <media/ir-core.h>
-
-#include <linux/time.h>
-#include <linux/timer.h>
-
-#define MOD_AUTHOR	"Jarod Wilson <jarod@wilsonet.com>"
-#define MOD_DESC	"Driver for SoundGraph iMON MultiMedia IR/Display"
-#define MOD_NAME	"imon"
-#define MOD_VERSION	"0.9.2"
-
-#define DISPLAY_MINOR_BASE	144
-#define DEVICE_NAME	"lcd%d"
-
-#define BUF_CHUNK_SIZE	8
-#define BUF_SIZE	128
-
-#define BIT_DURATION	250	/* each bit received is 250us */
-
-#define IMON_CLOCK_ENABLE_PACKETS	2
-
-/*** P R O T O T Y P E S ***/
-
-/* USB Callback prototypes */
-static int imon_probe(struct usb_interface *interface,
-		      const struct usb_device_id *id);
-static void imon_disconnect(struct usb_interface *interface);
-static void usb_rx_callback_intf0(struct urb *urb);
-static void usb_rx_callback_intf1(struct urb *urb);
-static void usb_tx_callback(struct urb *urb);
-
-/* suspend/resume support */
-static int imon_resume(struct usb_interface *intf);
-static int imon_suspend(struct usb_interface *intf, pm_message_t message);
-
-/* Display file_operations function prototypes */
-static int display_open(struct inode *inode, struct file *file);
-static int display_close(struct inode *inode, struct file *file);
-
-/* VFD write operation */
-static ssize_t vfd_write(struct file *file, const char *buf,
-			 size_t n_bytes, loff_t *pos);
-
-/* LCD file_operations override function prototypes */
-static ssize_t lcd_write(struct file *file, const char *buf,
-			 size_t n_bytes, loff_t *pos);
-
-/*** G L O B A L S ***/
-
-struct imon_context {
-	struct device *dev;
-	struct ir_dev_props *props;
-	/* Newer devices have two interfaces */
-	struct usb_device *usbdev_intf0;
-	struct usb_device *usbdev_intf1;
-
-	bool display_supported;		/* not all controllers do */
-	bool display_isopen;		/* display port has been opened */
-	bool rf_device;			/* true if iMON 2.4G LT/DT RF device */
-	bool rf_isassociating;		/* RF remote associating */
-	bool dev_present_intf0;		/* USB device presence, interface 0 */
-	bool dev_present_intf1;		/* USB device presence, interface 1 */
-
-	struct mutex lock;		/* to lock this object */
-	wait_queue_head_t remove_ok;	/* For unexpected USB disconnects */
-
-	struct usb_endpoint_descriptor *rx_endpoint_intf0;
-	struct usb_endpoint_descriptor *rx_endpoint_intf1;
-	struct usb_endpoint_descriptor *tx_endpoint;
-	struct urb *rx_urb_intf0;
-	struct urb *rx_urb_intf1;
-	struct urb *tx_urb;
-	bool tx_control;
-	unsigned char usb_rx_buf[8];
-	unsigned char usb_tx_buf[8];
-
-	struct tx_t {
-		unsigned char data_buf[35];	/* user data buffer */
-		struct completion finished;	/* wait for write to finish */
-		bool busy;			/* write in progress */
-		int status;			/* status of tx completion */
-	} tx;
-
-	u16 vendor;			/* usb vendor ID */
-	u16 product;			/* usb product ID */
-
-	struct input_dev *rdev;		/* input device for remote */
-	struct input_dev *idev;		/* input device for panel & IR mouse */
-	struct input_dev *touch;	/* input device for touchscreen */
-
-	spinlock_t kc_lock;		/* make sure we get keycodes right */
-	u32 kc;				/* current input keycode */
-	u32 last_keycode;		/* last reported input keycode */
-	u32 rc_scancode;		/* the computed remote scancode */
-	u8 rc_toggle;			/* the computed remote toggle bit */
-	u64 ir_type;			/* iMON or MCE (RC6) IR protocol? */
-	bool release_code;		/* some keys send a release code */
-
-	u8 display_type;		/* store the display type */
-	bool pad_mouse;			/* toggle kbd(0)/mouse(1) mode */
-
-	char name_rdev[128];		/* rc input device name */
-	char phys_rdev[64];		/* rc input device phys path */
-
-	char name_idev[128];		/* input device name */
-	char phys_idev[64];		/* input device phys path */
-
-	char name_touch[128];		/* touch screen name */
-	char phys_touch[64];		/* touch screen phys path */
-	struct timer_list ttimer;	/* touch screen timer */
-	int touch_x;			/* x coordinate on touchscreen */
-	int touch_y;			/* y coordinate on touchscreen */
-};
-
-#define TOUCH_TIMEOUT	(HZ/30)
-
-/* vfd character device file operations */
-static const struct file_operations vfd_fops = {
-	.owner		= THIS_MODULE,
-	.open		= &display_open,
-	.write		= &vfd_write,
-	.release	= &display_close,
-	.llseek		= noop_llseek,
-};
-
-/* lcd character device file operations */
-static const struct file_operations lcd_fops = {
-	.owner		= THIS_MODULE,
-	.open		= &display_open,
-	.write		= &lcd_write,
-	.release	= &display_close,
-	.llseek		= noop_llseek,
-};
-
-enum {
-	IMON_DISPLAY_TYPE_AUTO = 0,
-	IMON_DISPLAY_TYPE_VFD  = 1,
-	IMON_DISPLAY_TYPE_LCD  = 2,
-	IMON_DISPLAY_TYPE_VGA  = 3,
-	IMON_DISPLAY_TYPE_NONE = 4,
-};
-
-enum {
-	IMON_KEY_IMON	= 0,
-	IMON_KEY_MCE	= 1,
-	IMON_KEY_PANEL	= 2,
-};
-
-/*
- * USB Device ID for iMON USB Control Boards
- *
- * The Windows drivers contain 6 different inf files, more or less one for
- * each new device until the 0x0034-0x0046 devices, which all use the same
- * driver. Some of the devices in the 34-46 range haven't been definitively
- * identified yet. Early devices have either a TriGem Computer, Inc. or a
- * Samsung vendor ID (0x0aa8 and 0x04e8 respectively), while all later
- * devices use the SoundGraph vendor ID (0x15c2). This driver only supports
- * the ffdc and later devices, which do onboard decoding.
- */
-static struct usb_device_id imon_usb_id_table[] = {
-	/*
-	 * Several devices with this same device ID, all use iMON_PAD.inf
-	 * SoundGraph iMON PAD (IR & VFD)
-	 * SoundGraph iMON PAD (IR & LCD)
-	 * SoundGraph iMON Knob (IR only)
-	 */
-	{ USB_DEVICE(0x15c2, 0xffdc) },
-
-	/*
-	 * Newer devices, all driven by the latest iMON Windows driver, full
-	 * list of device IDs extracted via 'strings Setup/data1.hdr |grep 15c2'
-	 * Need user input to fill in details on unknown devices.
-	 */
-	/* SoundGraph iMON OEM Touch LCD (IR & 7" VGA LCD) */
-	{ USB_DEVICE(0x15c2, 0x0034) },
-	/* SoundGraph iMON OEM Touch LCD (IR & 4.3" VGA LCD) */
-	{ USB_DEVICE(0x15c2, 0x0035) },
-	/* SoundGraph iMON OEM VFD (IR & VFD) */
-	{ USB_DEVICE(0x15c2, 0x0036) },
-	/* device specifics unknown */
-	{ USB_DEVICE(0x15c2, 0x0037) },
-	/* SoundGraph iMON OEM LCD (IR & LCD) */
-	{ USB_DEVICE(0x15c2, 0x0038) },
-	/* SoundGraph iMON UltraBay (IR & LCD) */
-	{ USB_DEVICE(0x15c2, 0x0039) },
-	/* device specifics unknown */
-	{ USB_DEVICE(0x15c2, 0x003a) },
-	/* device specifics unknown */
-	{ USB_DEVICE(0x15c2, 0x003b) },
-	/* SoundGraph iMON OEM Inside (IR only) */
-	{ USB_DEVICE(0x15c2, 0x003c) },
-	/* device specifics unknown */
-	{ USB_DEVICE(0x15c2, 0x003d) },
-	/* device specifics unknown */
-	{ USB_DEVICE(0x15c2, 0x003e) },
-	/* device specifics unknown */
-	{ USB_DEVICE(0x15c2, 0x003f) },
-	/* device specifics unknown */
-	{ USB_DEVICE(0x15c2, 0x0040) },
-	/* SoundGraph iMON MINI (IR only) */
-	{ USB_DEVICE(0x15c2, 0x0041) },
-	/* Antec Veris Multimedia Station EZ External (IR only) */
-	{ USB_DEVICE(0x15c2, 0x0042) },
-	/* Antec Veris Multimedia Station Basic Internal (IR only) */
-	{ USB_DEVICE(0x15c2, 0x0043) },
-	/* Antec Veris Multimedia Station Elite (IR & VFD) */
-	{ USB_DEVICE(0x15c2, 0x0044) },
-	/* Antec Veris Multimedia Station Premiere (IR & LCD) */
-	{ USB_DEVICE(0x15c2, 0x0045) },
-	/* device specifics unknown */
-	{ USB_DEVICE(0x15c2, 0x0046) },
-	{}
-};
-
-/* USB Device data */
-static struct usb_driver imon_driver = {
-	.name		= MOD_NAME,
-	.probe		= imon_probe,
-	.disconnect	= imon_disconnect,
-	.suspend	= imon_suspend,
-	.resume		= imon_resume,
-	.id_table	= imon_usb_id_table,
-};
-
-static struct usb_class_driver imon_vfd_class = {
-	.name		= DEVICE_NAME,
-	.fops		= &vfd_fops,
-	.minor_base	= DISPLAY_MINOR_BASE,
-};
-
-static struct usb_class_driver imon_lcd_class = {
-	.name		= DEVICE_NAME,
-	.fops		= &lcd_fops,
-	.minor_base	= DISPLAY_MINOR_BASE,
-};
-
-/* imon receiver front panel/knob key table */
-static const struct {
-	u64 hw_code;
-	u32 keycode;
-} imon_panel_key_table[] = {
-	{ 0x000000000f00ffeell, KEY_PROG1 }, /* Go */
-	{ 0x000000001f00ffeell, KEY_AUDIO },
-	{ 0x000000002000ffeell, KEY_VIDEO },
-	{ 0x000000002100ffeell, KEY_CAMERA },
-	{ 0x000000002700ffeell, KEY_DVD },
-	{ 0x000000002300ffeell, KEY_TV },
-	{ 0x000000000500ffeell, KEY_PREVIOUS },
-	{ 0x000000000700ffeell, KEY_REWIND },
-	{ 0x000000000400ffeell, KEY_STOP },
-	{ 0x000000003c00ffeell, KEY_PLAYPAUSE },
-	{ 0x000000000800ffeell, KEY_FASTFORWARD },
-	{ 0x000000000600ffeell, KEY_NEXT },
-	{ 0x000000010000ffeell, KEY_RIGHT },
-	{ 0x000001000000ffeell, KEY_LEFT },
-	{ 0x000000003d00ffeell, KEY_SELECT },
-	{ 0x000100000000ffeell, KEY_VOLUMEUP },
-	{ 0x010000000000ffeell, KEY_VOLUMEDOWN },
-	{ 0x000000000100ffeell, KEY_MUTE },
-	/* 0xffdc iMON MCE VFD */
-	{ 0x00010000ffffffeell, KEY_VOLUMEUP },
-	{ 0x01000000ffffffeell, KEY_VOLUMEDOWN },
-	/* iMON Knob values */
-	{ 0x000100ffffffffeell, KEY_VOLUMEUP },
-	{ 0x010000ffffffffeell, KEY_VOLUMEDOWN },
-	{ 0x000008ffffffffeell, KEY_MUTE },
-};
-
-/* to prevent races between open() and disconnect(), probing, etc */
-static DEFINE_MUTEX(driver_lock);
-
-/* Module bookkeeping bits */
-MODULE_AUTHOR(MOD_AUTHOR);
-MODULE_DESCRIPTION(MOD_DESC);
-MODULE_VERSION(MOD_VERSION);
-MODULE_LICENSE("GPL");
-MODULE_DEVICE_TABLE(usb, imon_usb_id_table);
-
-static bool debug;
-module_param(debug, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(debug, "Debug messages: 0=no, 1=yes (default: no)");
-
-/* lcd, vfd, vga or none? should be auto-detected, but can be overridden... */
-static int display_type;
-module_param(display_type, int, S_IRUGO);
-MODULE_PARM_DESC(display_type, "Type of attached display. 0=autodetect, "
-		 "1=vfd, 2=lcd, 3=vga, 4=none (default: autodetect)");
-
-static int pad_stabilize = 1;
-module_param(pad_stabilize, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(pad_stabilize, "Apply stabilization algorithm to iMON PAD "
-		 "presses in arrow key mode. 0=disable, 1=enable (default).");
-
-/*
- * In certain use cases, mouse mode isn't really helpful, and could actually
- * cause confusion, so allow disabling it when the IR device is open.
- */
-static bool nomouse;
-module_param(nomouse, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(nomouse, "Disable mouse input device mode when IR device is "
-		 "open. 0=don't disable, 1=disable. (default: don't disable)");
-
-/* threshold at which a pad push registers as an arrow key in kbd mode */
-static int pad_thresh;
-module_param(pad_thresh, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(pad_thresh, "Threshold at which a pad push registers as an "
-		 "arrow key in kbd mode (default: 28)");
-
-
-static void free_imon_context(struct imon_context *ictx)
-{
-	struct device *dev = ictx->dev;
-
-	usb_free_urb(ictx->tx_urb);
-	usb_free_urb(ictx->rx_urb_intf0);
-	usb_free_urb(ictx->rx_urb_intf1);
-	kfree(ictx);
-
-	dev_dbg(dev, "%s: iMON context freed\n", __func__);
-}
-
-/**
- * Called when the Display device (e.g. /dev/lcd0)
- * is opened by the application.
- */
-static int display_open(struct inode *inode, struct file *file)
-{
-	struct usb_interface *interface;
-	struct imon_context *ictx = NULL;
-	int subminor;
-	int retval = 0;
-
-	/* prevent races with disconnect */
-	mutex_lock(&driver_lock);
-
-	subminor = iminor(inode);
-	interface = usb_find_interface(&imon_driver, subminor);
-	if (!interface) {
-		pr_err("could not find interface for minor %d\n", subminor);
-		retval = -ENODEV;
-		goto exit;
-	}
-	ictx = usb_get_intfdata(interface);
-
-	if (!ictx) {
-		pr_err("no context found for minor %d\n", subminor);
-		retval = -ENODEV;
-		goto exit;
-	}
-
-	mutex_lock(&ictx->lock);
-
-	if (!ictx->display_supported) {
-		pr_err("display not supported by device\n");
-		retval = -ENODEV;
-	} else if (ictx->display_isopen) {
-		pr_err("display port is already open\n");
-		retval = -EBUSY;
-	} else {
-		ictx->display_isopen = true;
-		file->private_data = ictx;
-		dev_dbg(ictx->dev, "display port opened\n");
-	}
-
-	mutex_unlock(&ictx->lock);
-
-exit:
-	mutex_unlock(&driver_lock);
-	return retval;
-}
-
-/**
- * Called when the display device (e.g. /dev/lcd0)
- * is closed by the application.
- */
-static int display_close(struct inode *inode, struct file *file)
-{
-	struct imon_context *ictx = NULL;
-	int retval = 0;
-
-	ictx = file->private_data;
-
-	if (!ictx) {
-		pr_err("no context for device\n");
-		return -ENODEV;
-	}
-
-	mutex_lock(&ictx->lock);
-
-	if (!ictx->display_supported) {
-		pr_err("display not supported by device\n");
-		retval = -ENODEV;
-	} else if (!ictx->display_isopen) {
-		pr_err("display is not open\n");
-		retval = -EIO;
-	} else {
-		ictx->display_isopen = false;
-		dev_dbg(ictx->dev, "display port closed\n");
-		if (!ictx->dev_present_intf0) {
-			/*
-			 * Device disconnected before close and IR port is not
-			 * open. If IR port is open, context will be deleted by
-			 * ir_close.
-			 */
-			mutex_unlock(&ictx->lock);
-			free_imon_context(ictx);
-			return retval;
-		}
-	}
-
-	mutex_unlock(&ictx->lock);
-	return retval;
-}
-
-/**
- * Sends a packet to the device -- this function must be called
- * with ictx->lock held.
- */
-static int send_packet(struct imon_context *ictx)
-{
-	unsigned int pipe;
-	unsigned long timeout;
-	int interval = 0;
-	int retval = 0;
-	struct usb_ctrlrequest *control_req = NULL;
-
-	/* Check if we need to use control or interrupt urb */
-	if (!ictx->tx_control) {
-		pipe = usb_sndintpipe(ictx->usbdev_intf0,
-				      ictx->tx_endpoint->bEndpointAddress);
-		interval = ictx->tx_endpoint->bInterval;
-
-		usb_fill_int_urb(ictx->tx_urb, ictx->usbdev_intf0, pipe,
-				 ictx->usb_tx_buf,
-				 sizeof(ictx->usb_tx_buf),
-				 usb_tx_callback, ictx, interval);
-
-		ictx->tx_urb->actual_length = 0;
-	} else {
-		/* fill request into kmalloc'ed space: */
-		control_req = kmalloc(sizeof(struct usb_ctrlrequest),
-				      GFP_KERNEL);
-		if (control_req == NULL)
-			return -ENOMEM;
-
-		/* setup packet is '21 09 0200 0001 0008' */
-		control_req->bRequestType = 0x21;
-		control_req->bRequest = 0x09;
-		control_req->wValue = cpu_to_le16(0x0200);
-		control_req->wIndex = cpu_to_le16(0x0001);
-		control_req->wLength = cpu_to_le16(0x0008);
-
-		/* control pipe is endpoint 0x00 */
-		pipe = usb_sndctrlpipe(ictx->usbdev_intf0, 0);
-
-		/* build the control urb */
-		usb_fill_control_urb(ictx->tx_urb, ictx->usbdev_intf0,
-				     pipe, (unsigned char *)control_req,
-				     ictx->usb_tx_buf,
-				     sizeof(ictx->usb_tx_buf),
-				     usb_tx_callback, ictx);
-		ictx->tx_urb->actual_length = 0;
-	}
-
-	init_completion(&ictx->tx.finished);
-	ictx->tx.busy = true;
-	smp_rmb(); /* ensure later readers know we're busy */
-
-	retval = usb_submit_urb(ictx->tx_urb, GFP_KERNEL);
-	if (retval) {
-		ictx->tx.busy = false;
-		smp_rmb(); /* ensure later readers know we're not busy */
-		pr_err("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");
-		mutex_lock(&ictx->lock);
-
-		retval = ictx->tx.status;
-		if (retval)
-			pr_err("packet tx failed (%d)\n", retval);
-	}
-
-	kfree(control_req);
-
-	/*
-	 * Induce a mandatory 5ms delay before returning, as otherwise,
-	 * send_packet can get called so rapidly as to overwhelm the device,
-	 * particularly on faster systems and/or those with quirky usb.
-	 */
-	timeout = msecs_to_jiffies(5);
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout(timeout);
-
-	return retval;
-}
-
-/**
- * Sends an associate packet to the iMON 2.4G.
- *
- * This might not be such a good idea, since it has an id collision with
- * some versions of the "IR & VFD" combo. The only way to determine if it
- * is an RF version is to look at the product description string. (Which
- * we currently do not fetch).
- */
-static int send_associate_24g(struct imon_context *ictx)
-{
-	int retval;
-	const unsigned char packet[8] = { 0x01, 0x00, 0x00, 0x00,
-					  0x00, 0x00, 0x00, 0x20 };
-
-	if (!ictx) {
-		pr_err("no context for device\n");
-		return -ENODEV;
-	}
-
-	if (!ictx->dev_present_intf0) {
-		pr_err("no iMON device present\n");
-		return -ENODEV;
-	}
-
-	memcpy(ictx->usb_tx_buf, packet, sizeof(packet));
-	retval = send_packet(ictx);
-
-	return retval;
-}
-
-/**
- * Sends packets to setup and show clock on iMON display
- *
- * Arguments: year - last 2 digits of year, month - 1..12,
- * day - 1..31, dow - day of the week (0-Sun...6-Sat),
- * hour - 0..23, minute - 0..59, second - 0..59
- */
-static int send_set_imon_clock(struct imon_context *ictx,
-			       unsigned int year, unsigned int month,
-			       unsigned int day, unsigned int dow,
-			       unsigned int hour, unsigned int minute,
-			       unsigned int second)
-{
-	unsigned char clock_enable_pkt[IMON_CLOCK_ENABLE_PACKETS][8];
-	int retval = 0;
-	int i;
-
-	if (!ictx) {
-		pr_err("no context for device\n");
-		return -ENODEV;
-	}
-
-	switch (ictx->display_type) {
-	case IMON_DISPLAY_TYPE_LCD:
-		clock_enable_pkt[0][0] = 0x80;
-		clock_enable_pkt[0][1] = year;
-		clock_enable_pkt[0][2] = month-1;
-		clock_enable_pkt[0][3] = day;
-		clock_enable_pkt[0][4] = hour;
-		clock_enable_pkt[0][5] = minute;
-		clock_enable_pkt[0][6] = second;
-
-		clock_enable_pkt[1][0] = 0x80;
-		clock_enable_pkt[1][1] = 0;
-		clock_enable_pkt[1][2] = 0;
-		clock_enable_pkt[1][3] = 0;
-		clock_enable_pkt[1][4] = 0;
-		clock_enable_pkt[1][5] = 0;
-		clock_enable_pkt[1][6] = 0;
-
-		if (ictx->product == 0xffdc) {
-			clock_enable_pkt[0][7] = 0x50;
-			clock_enable_pkt[1][7] = 0x51;
-		} else {
-			clock_enable_pkt[0][7] = 0x88;
-			clock_enable_pkt[1][7] = 0x8a;
-		}
-
-		break;
-
-	case IMON_DISPLAY_TYPE_VFD:
-		clock_enable_pkt[0][0] = year;
-		clock_enable_pkt[0][1] = month-1;
-		clock_enable_pkt[0][2] = day;
-		clock_enable_pkt[0][3] = dow;
-		clock_enable_pkt[0][4] = hour;
-		clock_enable_pkt[0][5] = minute;
-		clock_enable_pkt[0][6] = second;
-		clock_enable_pkt[0][7] = 0x40;
-
-		clock_enable_pkt[1][0] = 0;
-		clock_enable_pkt[1][1] = 0;
-		clock_enable_pkt[1][2] = 1;
-		clock_enable_pkt[1][3] = 0;
-		clock_enable_pkt[1][4] = 0;
-		clock_enable_pkt[1][5] = 0;
-		clock_enable_pkt[1][6] = 0;
-		clock_enable_pkt[1][7] = 0x42;
-
-		break;
-
-	default:
-		return -ENODEV;
-	}
-
-	for (i = 0; i < IMON_CLOCK_ENABLE_PACKETS; i++) {
-		memcpy(ictx->usb_tx_buf, clock_enable_pkt[i], 8);
-		retval = send_packet(ictx);
-		if (retval) {
-			pr_err("send_packet failed for packet %d\n", i);
-			break;
-		}
-	}
-
-	return retval;
-}
-
-/**
- * These are the sysfs functions to handle the association on the iMON 2.4G LT.
- */
-static ssize_t show_associate_remote(struct device *d,
-				     struct device_attribute *attr,
-				     char *buf)
-{
-	struct imon_context *ictx = dev_get_drvdata(d);
-
-	if (!ictx)
-		return -ENODEV;
-
-	mutex_lock(&ictx->lock);
-	if (ictx->rf_isassociating)
-		strcpy(buf, "associating\n");
-	else
-		strcpy(buf, "closed\n");
-
-	dev_info(d, "Visit http://www.lirc.org/html/imon-24g.html for "
-		 "instructions on how to associate your iMON 2.4G DT/LT "
-		 "remote\n");
-	mutex_unlock(&ictx->lock);
-	return strlen(buf);
-}
-
-static ssize_t store_associate_remote(struct device *d,
-				      struct device_attribute *attr,
-				      const char *buf, size_t count)
-{
-	struct imon_context *ictx;
-
-	ictx = dev_get_drvdata(d);
-
-	if (!ictx)
-		return -ENODEV;
-
-	mutex_lock(&ictx->lock);
-	ictx->rf_isassociating = true;
-	send_associate_24g(ictx);
-	mutex_unlock(&ictx->lock);
-
-	return count;
-}
-
-/**
- * sysfs functions to control internal imon clock
- */
-static ssize_t show_imon_clock(struct device *d,
-			       struct device_attribute *attr, char *buf)
-{
-	struct imon_context *ictx = dev_get_drvdata(d);
-	size_t len;
-
-	if (!ictx)
-		return -ENODEV;
-
-	mutex_lock(&ictx->lock);
-
-	if (!ictx->display_supported) {
-		len = snprintf(buf, PAGE_SIZE, "Not supported.");
-	} else {
-		len = snprintf(buf, PAGE_SIZE,
-			"To set the clock on your iMON display:\n"
-			"# date \"+%%y %%m %%d %%w %%H %%M %%S\" > imon_clock\n"
-			"%s", ictx->display_isopen ?
-			"\nNOTE: imon device must be closed\n" : "");
-	}
-
-	mutex_unlock(&ictx->lock);
-
-	return len;
-}
-
-static ssize_t store_imon_clock(struct device *d,
-				struct device_attribute *attr,
-				const char *buf, size_t count)
-{
-	struct imon_context *ictx = dev_get_drvdata(d);
-	ssize_t retval;
-	unsigned int year, month, day, dow, hour, minute, second;
-
-	if (!ictx)
-		return -ENODEV;
-
-	mutex_lock(&ictx->lock);
-
-	if (!ictx->display_supported) {
-		retval = -ENODEV;
-		goto exit;
-	} else if (ictx->display_isopen) {
-		retval = -EBUSY;
-		goto exit;
-	}
-
-	if (sscanf(buf, "%u %u %u %u %u %u %u",	&year, &month, &day, &dow,
-		   &hour, &minute, &second) != 7) {
-		retval = -EINVAL;
-		goto exit;
-	}
-
-	if ((month < 1 || month > 12) ||
-	    (day < 1 || day > 31) || (dow > 6) ||
-	    (hour > 23) || (minute > 59) || (second > 59)) {
-		retval = -EINVAL;
-		goto exit;
-	}
-
-	retval = send_set_imon_clock(ictx, year, month, day, dow,
-				     hour, minute, second);
-	if (retval)
-		goto exit;
-
-	retval = count;
-exit:
-	mutex_unlock(&ictx->lock);
-
-	return retval;
-}
-
-
-static DEVICE_ATTR(imon_clock, S_IWUSR | S_IRUGO, show_imon_clock,
-		   store_imon_clock);
-
-static DEVICE_ATTR(associate_remote, S_IWUSR | S_IRUGO, show_associate_remote,
-		   store_associate_remote);
-
-static struct attribute *imon_display_sysfs_entries[] = {
-	&dev_attr_imon_clock.attr,
-	NULL
-};
-
-static struct attribute_group imon_display_attr_group = {
-	.attrs = imon_display_sysfs_entries
-};
-
-static struct attribute *imon_rf_sysfs_entries[] = {
-	&dev_attr_associate_remote.attr,
-	NULL
-};
-
-static struct attribute_group imon_rf_attr_group = {
-	.attrs = imon_rf_sysfs_entries
-};
-
-/**
- * Writes data to the VFD.  The iMON VFD is 2x16 characters
- * and requires data in 5 consecutive USB interrupt packets,
- * each packet but the last carrying 7 bytes.
- *
- * I don't know if the VFD board supports features such as
- * scrolling, clearing rows, blanking, etc. so at
- * the caller must provide a full screen of data.  If fewer
- * than 32 bytes are provided spaces will be appended to
- * generate a full screen.
- */
-static ssize_t vfd_write(struct file *file, const char *buf,
-			 size_t n_bytes, loff_t *pos)
-{
-	int i;
-	int offset;
-	int seq;
-	int retval = 0;
-	struct imon_context *ictx;
-	const unsigned char vfd_packet6[] = {
-		0x01, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF };
-
-	ictx = file->private_data;
-	if (!ictx) {
-		pr_err("no context for device\n");
-		return -ENODEV;
-	}
-
-	mutex_lock(&ictx->lock);
-
-	if (!ictx->dev_present_intf0) {
-		pr_err("no iMON device present\n");
-		retval = -ENODEV;
-		goto exit;
-	}
-
-	if (n_bytes <= 0 || n_bytes > 32) {
-		pr_err("invalid payload size\n");
-		retval = -EINVAL;
-		goto exit;
-	}
-
-	if (copy_from_user(ictx->tx.data_buf, buf, n_bytes)) {
-		retval = -EFAULT;
-		goto exit;
-	}
-
-	/* Pad with spaces */
-	for (i = n_bytes; i < 32; ++i)
-		ictx->tx.data_buf[i] = ' ';
-
-	for (i = 32; i < 35; ++i)
-		ictx->tx.data_buf[i] = 0xFF;
-
-	offset = 0;
-	seq = 0;
-
-	do {
-		memcpy(ictx->usb_tx_buf, ictx->tx.data_buf + offset, 7);
-		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);
-			goto exit;
-		} else {
-			seq += 2;
-			offset += 7;
-		}
-
-	} while (offset < 35);
-
-	/* Send packet #6 */
-	memcpy(ictx->usb_tx_buf, &vfd_packet6, sizeof(vfd_packet6));
-	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);
-
-exit:
-	mutex_unlock(&ictx->lock);
-
-	return (!retval) ? n_bytes : retval;
-}
-
-/**
- * Writes data to the LCD.  The iMON OEM LCD screen expects 8-byte
- * packets. We accept data as 16 hexadecimal digits, followed by a
- * newline (to make it easy to drive the device from a command-line
- * -- even though the actual binary data is a bit complicated).
- *
- * The device itself is not a "traditional" text-mode display. It's
- * actually a 16x96 pixel bitmap display. That means if you want to
- * display text, you've got to have your own "font" and translate the
- * text into bitmaps for display. This is really flexible (you can
- * display whatever diacritics you need, and so on), but it's also
- * a lot more complicated than most LCDs...
- */
-static ssize_t lcd_write(struct file *file, const char *buf,
-			 size_t n_bytes, loff_t *pos)
-{
-	int retval = 0;
-	struct imon_context *ictx;
-
-	ictx = file->private_data;
-	if (!ictx) {
-		pr_err("no context for device\n");
-		return -ENODEV;
-	}
-
-	mutex_lock(&ictx->lock);
-
-	if (!ictx->display_supported) {
-		pr_err("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);
-		retval = -EINVAL;
-		goto exit;
-	}
-
-	if (copy_from_user(ictx->usb_tx_buf, buf, 8)) {
-		retval = -EFAULT;
-		goto exit;
-	}
-
-	retval = send_packet(ictx);
-	if (retval) {
-		pr_err("send packet failed!\n");
-		goto exit;
-	} else {
-		dev_dbg(ictx->dev, "%s: write %d bytes to LCD\n",
-			__func__, (int) n_bytes);
-	}
-exit:
-	mutex_unlock(&ictx->lock);
-	return (!retval) ? n_bytes : retval;
-}
-
-/**
- * Callback function for USB core API: transmit data
- */
-static void usb_tx_callback(struct urb *urb)
-{
-	struct imon_context *ictx;
-
-	if (!urb)
-		return;
-	ictx = (struct imon_context *)urb->context;
-	if (!ictx)
-		return;
-
-	ictx->tx.status = urb->status;
-
-	/* notify waiters that write has finished */
-	ictx->tx.busy = false;
-	smp_rmb(); /* ensure later readers know we're not busy */
-	complete(&ictx->tx.finished);
-}
-
-/**
- * report touchscreen input
- */
-static void imon_touch_display_timeout(unsigned long data)
-{
-	struct imon_context *ictx = (struct imon_context *)data;
-
-	if (ictx->display_type != IMON_DISPLAY_TYPE_VGA)
-		return;
-
-	input_report_abs(ictx->touch, ABS_X, ictx->touch_x);
-	input_report_abs(ictx->touch, ABS_Y, ictx->touch_y);
-	input_report_key(ictx->touch, BTN_TOUCH, 0x00);
-	input_sync(ictx->touch);
-}
-
-/**
- * iMON IR receivers support two different signal sets -- those used by
- * the iMON remotes, and those used by the Windows MCE remotes (which is
- * really just RC-6), but only one or the other at a time, as the signals
- * are decoded onboard the receiver.
- */
-int imon_ir_change_protocol(void *priv, u64 ir_type)
-{
-	int retval;
-	struct imon_context *ictx = priv;
-	struct device *dev = ictx->dev;
-	bool pad_mouse;
-	unsigned char ir_proto_packet[] = {
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86 };
-
-	if (ir_type && !(ir_type & ictx->props->allowed_protos))
-		dev_warn(dev, "Looks like you're trying to use an IR protocol "
-			 "this device does not support\n");
-
-	switch (ir_type) {
-	case IR_TYPE_RC6:
-		dev_dbg(dev, "Configuring IR receiver for MCE protocol\n");
-		ir_proto_packet[0] = 0x01;
-		pad_mouse = false;
-		break;
-	case IR_TYPE_UNKNOWN:
-	case IR_TYPE_OTHER:
-		dev_dbg(dev, "Configuring IR receiver for iMON protocol\n");
-		if (pad_stabilize && !nomouse)
-			pad_mouse = true;
-		else {
-			dev_dbg(dev, "PAD stabilize functionality disabled\n");
-			pad_mouse = false;
-		}
-		/* ir_proto_packet[0] = 0x00; // already the default */
-		ir_type = IR_TYPE_OTHER;
-		break;
-	default:
-		dev_warn(dev, "Unsupported IR protocol specified, overriding "
-			 "to iMON IR protocol\n");
-		if (pad_stabilize && !nomouse)
-			pad_mouse = true;
-		else {
-			dev_dbg(dev, "PAD stabilize functionality disabled\n");
-			pad_mouse = false;
-		}
-		/* ir_proto_packet[0] = 0x00; // already the default */
-		ir_type = IR_TYPE_OTHER;
-		break;
-	}
-
-	memcpy(ictx->usb_tx_buf, &ir_proto_packet, sizeof(ir_proto_packet));
-
-	retval = send_packet(ictx);
-	if (retval)
-		goto out;
-
-	ictx->ir_type = ir_type;
-	ictx->pad_mouse = pad_mouse;
-
-out:
-	return retval;
-}
-
-static inline int tv2int(const struct timeval *a, const struct timeval *b)
-{
-	int usecs = 0;
-	int sec   = 0;
-
-	if (b->tv_usec > a->tv_usec) {
-		usecs = 1000000;
-		sec--;
-	}
-
-	usecs += a->tv_usec - b->tv_usec;
-
-	sec += a->tv_sec - b->tv_sec;
-	sec *= 1000;
-	usecs /= 1000;
-	sec += usecs;
-
-	if (sec < 0)
-		sec = 1000;
-
-	return sec;
-}
-
-/**
- * The directional pad behaves a bit differently, depending on whether this is
- * one of the older ffdc devices or a newer device. Newer devices appear to
- * have a higher resolution matrix for more precise mouse movement, but it
- * makes things overly sensitive in keyboard mode, so we do some interesting
- * contortions to make it less touchy. Older devices run through the same
- * routine with shorter timeout and a smaller threshold.
- */
-static int stabilize(int a, int b, u16 timeout, u16 threshold)
-{
-	struct timeval ct;
-	static struct timeval prev_time = {0, 0};
-	static struct timeval hit_time  = {0, 0};
-	static int x, y, prev_result, hits;
-	int result = 0;
-	int msec, msec_hit;
-
-	do_gettimeofday(&ct);
-	msec = tv2int(&ct, &prev_time);
-	msec_hit = tv2int(&ct, &hit_time);
-
-	if (msec > 100) {
-		x = 0;
-		y = 0;
-		hits = 0;
-	}
-
-	x += a;
-	y += b;
-
-	prev_time = ct;
-
-	if (abs(x) > threshold || abs(y) > threshold) {
-		if (abs(y) > abs(x))
-			result = (y > 0) ? 0x7F : 0x80;
-		else
-			result = (x > 0) ? 0x7F00 : 0x8000;
-
-		x = 0;
-		y = 0;
-
-		if (result == prev_result) {
-			hits++;
-
-			if (hits > 3) {
-				switch (result) {
-				case 0x7F:
-					y = 17 * threshold / 30;
-					break;
-				case 0x80:
-					y -= 17 * threshold / 30;
-					break;
-				case 0x7F00:
-					x = 17 * threshold / 30;
-					break;
-				case 0x8000:
-					x -= 17 * threshold / 30;
-					break;
-				}
-			}
-
-			if (hits == 2 && msec_hit < timeout) {
-				result = 0;
-				hits = 1;
-			}
-		} else {
-			prev_result = result;
-			hits = 1;
-			hit_time = ct;
-		}
-	}
-
-	return result;
-}
-
-static u32 imon_remote_key_lookup(struct imon_context *ictx, u32 scancode)
-{
-	u32 keycode;
-	u32 release;
-	bool is_release_code = false;
-
-	/* Look for the initial press of a button */
-	keycode = ir_g_keycode_from_table(ictx->rdev, scancode);
-	ictx->rc_toggle = 0x0;
-	ictx->rc_scancode = scancode;
-
-	/* Look for the release of a button */
-	if (keycode == KEY_RESERVED) {
-		release = scancode & ~0x4000;
-		keycode = ir_g_keycode_from_table(ictx->rdev, release);
-		if (keycode != KEY_RESERVED)
-			is_release_code = true;
-	}
-
-	ictx->release_code = is_release_code;
-
-	return keycode;
-}
-
-static u32 imon_mce_key_lookup(struct imon_context *ictx, u32 scancode)
-{
-	u32 keycode;
-
-#define MCE_KEY_MASK 0x7000
-#define MCE_TOGGLE_BIT 0x8000
-
-	/*
-	 * On some receivers, mce keys decode to 0x8000f04xx and 0x8000f84xx
-	 * (the toggle bit flipping between alternating key presses), while
-	 * on other receivers, we see 0x8000f74xx and 0x8000ff4xx. To keep
-	 * the table trim, we always or in the bits to look up 0x8000ff4xx,
-	 * but we can't or them into all codes, as some keys are decoded in
-	 * a different way w/o the same use of the toggle bit...
-	 */
-	if (scancode & 0x80000000)
-		scancode = scancode | MCE_KEY_MASK | MCE_TOGGLE_BIT;
-
-	ictx->rc_scancode = scancode;
-	keycode = ir_g_keycode_from_table(ictx->rdev, scancode);
-
-	/* not used in mce mode, but make sure we know its false */
-	ictx->release_code = false;
-
-	return keycode;
-}
-
-static u32 imon_panel_key_lookup(u64 code)
-{
-	int i;
-	u32 keycode = KEY_RESERVED;
-
-	for (i = 0; i < ARRAY_SIZE(imon_panel_key_table); i++) {
-		if (imon_panel_key_table[i].hw_code == (code | 0xffee)) {
-			keycode = imon_panel_key_table[i].keycode;
-			break;
-		}
-	}
-
-	return keycode;
-}
-
-static bool imon_mouse_event(struct imon_context *ictx,
-			     unsigned char *buf, int len)
-{
-	char rel_x = 0x00, rel_y = 0x00;
-	u8 right_shift = 1;
-	bool mouse_input = true;
-	int dir = 0;
-	unsigned long flags;
-
-	spin_lock_irqsave(&ictx->kc_lock, flags);
-
-	/* newer iMON device PAD or mouse button */
-	if (ictx->product != 0xffdc && (buf[0] & 0x01) && len == 5) {
-		rel_x = buf[2];
-		rel_y = buf[3];
-		right_shift = 1;
-	/* 0xffdc iMON PAD or mouse button input */
-	} else if (ictx->product == 0xffdc && (buf[0] & 0x40) &&
-			!((buf[1] & 0x01) || ((buf[1] >> 2) & 0x01))) {
-		rel_x = (buf[1] & 0x08) | (buf[1] & 0x10) >> 2 |
-			(buf[1] & 0x20) >> 4 | (buf[1] & 0x40) >> 6;
-		if (buf[0] & 0x02)
-			rel_x |= ~0x0f;
-		rel_x = rel_x + rel_x / 2;
-		rel_y = (buf[2] & 0x08) | (buf[2] & 0x10) >> 2 |
-			(buf[2] & 0x20) >> 4 | (buf[2] & 0x40) >> 6;
-		if (buf[0] & 0x01)
-			rel_y |= ~0x0f;
-		rel_y = rel_y + rel_y / 2;
-		right_shift = 2;
-	/* some ffdc devices decode mouse buttons differently... */
-	} else if (ictx->product == 0xffdc && (buf[0] == 0x68)) {
-		right_shift = 2;
-	/* ch+/- buttons, which we use for an emulated scroll wheel */
-	} else if (ictx->kc == KEY_CHANNELUP && (buf[2] & 0x40) != 0x40) {
-		dir = 1;
-	} else if (ictx->kc == KEY_CHANNELDOWN && (buf[2] & 0x40) != 0x40) {
-		dir = -1;
-	} else
-		mouse_input = false;
-
-	spin_unlock_irqrestore(&ictx->kc_lock, flags);
-
-	if (mouse_input) {
-		dev_dbg(ictx->dev, "sending mouse data via input subsystem\n");
-
-		if (dir) {
-			input_report_rel(ictx->idev, REL_WHEEL, dir);
-		} else if (rel_x || rel_y) {
-			input_report_rel(ictx->idev, REL_X, rel_x);
-			input_report_rel(ictx->idev, REL_Y, rel_y);
-		} else {
-			input_report_key(ictx->idev, BTN_LEFT, buf[1] & 0x1);
-			input_report_key(ictx->idev, BTN_RIGHT,
-					 buf[1] >> right_shift & 0x1);
-		}
-		input_sync(ictx->idev);
-		spin_lock_irqsave(&ictx->kc_lock, flags);
-		ictx->last_keycode = ictx->kc;
-		spin_unlock_irqrestore(&ictx->kc_lock, flags);
-	}
-
-	return mouse_input;
-}
-
-static void imon_touch_event(struct imon_context *ictx, unsigned char *buf)
-{
-	mod_timer(&ictx->ttimer, jiffies + TOUCH_TIMEOUT);
-	ictx->touch_x = (buf[0] << 4) | (buf[1] >> 4);
-	ictx->touch_y = 0xfff - ((buf[2] << 4) | (buf[1] & 0xf));
-	input_report_abs(ictx->touch, ABS_X, ictx->touch_x);
-	input_report_abs(ictx->touch, ABS_Y, ictx->touch_y);
-	input_report_key(ictx->touch, BTN_TOUCH, 0x01);
-	input_sync(ictx->touch);
-}
-
-static void imon_pad_to_keys(struct imon_context *ictx, unsigned char *buf)
-{
-	int dir = 0;
-	char rel_x = 0x00, rel_y = 0x00;
-	u16 timeout, threshold;
-	u32 scancode = KEY_RESERVED;
-	unsigned long flags;
-
-	/*
-	 * The imon directional pad functions more like a touchpad. Bytes 3 & 4
-	 * contain a position coordinate (x,y), with each component ranging
-	 * from -14 to 14. We want to down-sample this to only 4 discrete values
-	 * for up/down/left/right arrow keys. Also, when you get too close to
-	 * diagonals, it has a tendancy to jump back and forth, so lets try to
-	 * ignore when they get too close.
-	 */
-	if (ictx->product != 0xffdc) {
-		/* first, pad to 8 bytes so it conforms with everything else */
-		buf[5] = buf[6] = buf[7] = 0;
-		timeout = 500;	/* in msecs */
-		/* (2*threshold) x (2*threshold) square */
-		threshold = pad_thresh ? pad_thresh : 28;
-		rel_x = buf[2];
-		rel_y = buf[3];
-
-		if (ictx->ir_type == IR_TYPE_OTHER && pad_stabilize) {
-			if ((buf[1] == 0) && ((rel_x != 0) || (rel_y != 0))) {
-				dir = stabilize((int)rel_x, (int)rel_y,
-						timeout, threshold);
-				if (!dir) {
-					spin_lock_irqsave(&ictx->kc_lock,
-							  flags);
-					ictx->kc = KEY_UNKNOWN;
-					spin_unlock_irqrestore(&ictx->kc_lock,
-							       flags);
-					return;
-				}
-				buf[2] = dir & 0xFF;
-				buf[3] = (dir >> 8) & 0xFF;
-				scancode = be32_to_cpu(*((u32 *)buf));
-			}
-		} else {
-			/*
-			 * Hack alert: instead of using keycodes, we have
-			 * to use hard-coded scancodes here...
-			 */
-			if (abs(rel_y) > abs(rel_x)) {
-				buf[2] = (rel_y > 0) ? 0x7F : 0x80;
-				buf[3] = 0;
-				if (rel_y > 0)
-					scancode = 0x01007f00; /* KEY_DOWN */
-				else
-					scancode = 0x01008000; /* KEY_UP */
-			} else {
-				buf[2] = 0;
-				buf[3] = (rel_x > 0) ? 0x7F : 0x80;
-				if (rel_x > 0)
-					scancode = 0x0100007f; /* KEY_RIGHT */
-				else
-					scancode = 0x01000080; /* KEY_LEFT */
-			}
-		}
-
-	/*
-	 * Handle on-board decoded pad events for e.g. older VFD/iMON-Pad
-	 * device (15c2:ffdc). The remote generates various codes from
-	 * 0x68nnnnB7 to 0x6AnnnnB7, the left mouse button generates
-	 * 0x688301b7 and the right one 0x688481b7. All other keys generate
-	 * 0x2nnnnnnn. Position coordinate is encoded in buf[1] and buf[2] with
-	 * reversed endianess. Extract direction from buffer, rotate endianess,
-	 * adjust sign and feed the values into stabilize(). The resulting codes
-	 * will be 0x01008000, 0x01007F00, which match the newer devices.
-	 */
-	} else {
-		timeout = 10;	/* in msecs */
-		/* (2*threshold) x (2*threshold) square */
-		threshold = pad_thresh ? pad_thresh : 15;
-
-		/* buf[1] is x */
-		rel_x = (buf[1] & 0x08) | (buf[1] & 0x10) >> 2 |
-			(buf[1] & 0x20) >> 4 | (buf[1] & 0x40) >> 6;
-		if (buf[0] & 0x02)
-			rel_x |= ~0x10+1;
-		/* buf[2] is y */
-		rel_y = (buf[2] & 0x08) | (buf[2] & 0x10) >> 2 |
-			(buf[2] & 0x20) >> 4 | (buf[2] & 0x40) >> 6;
-		if (buf[0] & 0x01)
-			rel_y |= ~0x10+1;
-
-		buf[0] = 0x01;
-		buf[1] = buf[4] = buf[5] = buf[6] = buf[7] = 0;
-
-		if (ictx->ir_type == IR_TYPE_OTHER && pad_stabilize) {
-			dir = stabilize((int)rel_x, (int)rel_y,
-					timeout, threshold);
-			if (!dir) {
-				spin_lock_irqsave(&ictx->kc_lock, flags);
-				ictx->kc = KEY_UNKNOWN;
-				spin_unlock_irqrestore(&ictx->kc_lock, flags);
-				return;
-			}
-			buf[2] = dir & 0xFF;
-			buf[3] = (dir >> 8) & 0xFF;
-			scancode = be32_to_cpu(*((u32 *)buf));
-		} else {
-			/*
-			 * Hack alert: instead of using keycodes, we have
-			 * to use hard-coded scancodes here...
-			 */
-			if (abs(rel_y) > abs(rel_x)) {
-				buf[2] = (rel_y > 0) ? 0x7F : 0x80;
-				buf[3] = 0;
-				if (rel_y > 0)
-					scancode = 0x01007f00; /* KEY_DOWN */
-				else
-					scancode = 0x01008000; /* KEY_UP */
-			} else {
-				buf[2] = 0;
-				buf[3] = (rel_x > 0) ? 0x7F : 0x80;
-				if (rel_x > 0)
-					scancode = 0x0100007f; /* KEY_RIGHT */
-				else
-					scancode = 0x01000080; /* KEY_LEFT */
-			}
-		}
-	}
-
-	if (scancode) {
-		spin_lock_irqsave(&ictx->kc_lock, flags);
-		ictx->kc = imon_remote_key_lookup(ictx, scancode);
-		spin_unlock_irqrestore(&ictx->kc_lock, flags);
-	}
-}
-
-/**
- * figure out if these is a press or a release. We don't actually
- * care about repeats, as those will be auto-generated within the IR
- * subsystem for repeating scancodes.
- */
-static int imon_parse_press_type(struct imon_context *ictx,
-				 unsigned char *buf, u8 ktype)
-{
-	int press_type = 0;
-	unsigned long flags;
-
-	spin_lock_irqsave(&ictx->kc_lock, flags);
-
-	/* key release of 0x02XXXXXX key */
-	if (ictx->kc == KEY_RESERVED && buf[0] == 0x02 && buf[3] == 0x00)
-		ictx->kc = ictx->last_keycode;
-
-	/* mouse button release on (some) 0xffdc devices */
-	else if (ictx->kc == KEY_RESERVED && buf[0] == 0x68 && buf[1] == 0x82 &&
-		 buf[2] == 0x81 && buf[3] == 0xb7)
-		ictx->kc = ictx->last_keycode;
-
-	/* mouse button release on (some other) 0xffdc devices */
-	else if (ictx->kc == KEY_RESERVED && buf[0] == 0x01 && buf[1] == 0x00 &&
-		 buf[2] == 0x81 && buf[3] == 0xb7)
-		ictx->kc = ictx->last_keycode;
-
-	/* mce-specific button handling, no keyup events */
-	else if (ktype == IMON_KEY_MCE) {
-		ictx->rc_toggle = buf[2];
-		press_type = 1;
-
-	/* incoherent or irrelevant data */
-	} else if (ictx->kc == KEY_RESERVED)
-		press_type = -EINVAL;
-
-	/* key release of 0xXXXXXXb7 key */
-	else if (ictx->release_code)
-		press_type = 0;
-
-	/* this is a button press */
-	else
-		press_type = 1;
-
-	spin_unlock_irqrestore(&ictx->kc_lock, flags);
-
-	return press_type;
-}
-
-/**
- * Process the incoming packet
- */
-static void imon_incoming_packet(struct imon_context *ictx,
-				 struct urb *urb, int intf)
-{
-	int len = urb->actual_length;
-	unsigned char *buf = urb->transfer_buffer;
-	struct device *dev = ictx->dev;
-	unsigned long flags;
-	u32 kc;
-	bool norelease = false;
-	int i;
-	u64 scancode;
-	struct input_dev *rdev = NULL;
-	struct ir_input_dev *irdev = NULL;
-	int press_type = 0;
-	int msec;
-	struct timeval t;
-	static struct timeval prev_time = { 0, 0 };
-	u8 ktype;
-
-	rdev = ictx->rdev;
-	irdev = input_get_drvdata(rdev);
-
-	/* filter out junk data on the older 0xffdc imon devices */
-	if ((buf[0] == 0xff) && (buf[1] == 0xff) && (buf[2] == 0xff))
-		return;
-
-	/* Figure out what key was pressed */
-	if (len == 8 && buf[7] == 0xee) {
-		scancode = be64_to_cpu(*((u64 *)buf));
-		ktype = IMON_KEY_PANEL;
-		kc = imon_panel_key_lookup(scancode);
-	} else {
-		scancode = be32_to_cpu(*((u32 *)buf));
-		if (ictx->ir_type == IR_TYPE_RC6) {
-			ktype = IMON_KEY_IMON;
-			if (buf[0] == 0x80)
-				ktype = IMON_KEY_MCE;
-			kc = imon_mce_key_lookup(ictx, scancode);
-		} else {
-			ktype = IMON_KEY_IMON;
-			kc = imon_remote_key_lookup(ictx, scancode);
-		}
-	}
-
-	spin_lock_irqsave(&ictx->kc_lock, flags);
-	/* keyboard/mouse mode toggle button */
-	if (kc == KEY_KEYBOARD && !ictx->release_code) {
-		ictx->last_keycode = kc;
-		if (!nomouse) {
-			ictx->pad_mouse = ~(ictx->pad_mouse) & 0x1;
-			dev_dbg(dev, "toggling to %s mode\n",
-				ictx->pad_mouse ? "mouse" : "keyboard");
-			spin_unlock_irqrestore(&ictx->kc_lock, flags);
-			return;
-		} else {
-			ictx->pad_mouse = 0;
-			dev_dbg(dev, "mouse mode disabled, passing key value\n");
-		}
-	}
-
-	ictx->kc = kc;
-	spin_unlock_irqrestore(&ictx->kc_lock, flags);
-
-	/* send touchscreen events through input subsystem if touchpad data */
-	if (ictx->display_type == IMON_DISPLAY_TYPE_VGA && len == 8 &&
-	    buf[7] == 0x86) {
-		imon_touch_event(ictx, buf);
-		return;
-
-	/* look for mouse events with pad in mouse mode */
-	} else if (ictx->pad_mouse) {
-		if (imon_mouse_event(ictx, buf, len))
-			return;
-	}
-
-	/* Now for some special handling to convert pad input to arrow keys */
-	if (((len == 5) && (buf[0] == 0x01) && (buf[4] == 0x00)) ||
-	    ((len == 8) && (buf[0] & 0x40) &&
-	     !(buf[1] & 0x1 || buf[1] >> 2 & 0x1))) {
-		len = 8;
-		imon_pad_to_keys(ictx, buf);
-		norelease = true;
-	}
-
-	if (debug) {
-		printk(KERN_INFO "intf%d decoded packet: ", intf);
-		for (i = 0; i < len; ++i)
-			printk("%02x ", buf[i]);
-		printk("\n");
-	}
-
-	press_type = imon_parse_press_type(ictx, buf, ktype);
-	if (press_type < 0)
-		goto not_input_data;
-
-	spin_lock_irqsave(&ictx->kc_lock, flags);
-	if (ictx->kc == KEY_UNKNOWN)
-		goto unknown_key;
-	spin_unlock_irqrestore(&ictx->kc_lock, flags);
-
-	if (ktype != IMON_KEY_PANEL) {
-		if (press_type == 0)
-			ir_keyup(irdev);
-		else {
-			ir_keydown(rdev, ictx->rc_scancode, ictx->rc_toggle);
-			spin_lock_irqsave(&ictx->kc_lock, flags);
-			ictx->last_keycode = ictx->kc;
-			spin_unlock_irqrestore(&ictx->kc_lock, flags);
-		}
-		return;
-	}
-
-	/* Only panel type events left to process now */
-	spin_lock_irqsave(&ictx->kc_lock, flags);
-
-	/* KEY_MUTE repeats from knob need to be suppressed */
-	if (ictx->kc == KEY_MUTE && ictx->kc == ictx->last_keycode) {
-		do_gettimeofday(&t);
-		msec = tv2int(&t, &prev_time);
-		prev_time = t;
-		if (msec < ictx->idev->rep[REP_DELAY]) {
-			spin_unlock_irqrestore(&ictx->kc_lock, flags);
-			return;
-		}
-	}
-	kc = ictx->kc;
-
-	spin_unlock_irqrestore(&ictx->kc_lock, flags);
-
-	input_report_key(ictx->idev, kc, press_type);
-	input_sync(ictx->idev);
-
-	/* panel keys don't generate a release */
-	input_report_key(ictx->idev, kc, 0);
-	input_sync(ictx->idev);
-
-	ictx->last_keycode = kc;
-
-	return;
-
-unknown_key:
-	spin_unlock_irqrestore(&ictx->kc_lock, flags);
-	dev_info(dev, "%s: unknown keypress, code 0x%llx\n", __func__,
-		 (long long)scancode);
-	return;
-
-not_input_data:
-	if (len != 8) {
-		dev_warn(dev, "imon %s: invalid incoming packet "
-			 "size (len = %d, intf%d)\n", __func__, len, intf);
-		return;
-	}
-
-	/* iMON 2.4G associate frame */
-	if (buf[0] == 0x00 &&
-	    buf[2] == 0xFF &&				/* REFID */
-	    buf[3] == 0xFF &&
-	    buf[4] == 0xFF &&
-	    buf[5] == 0xFF &&				/* iMON 2.4G */
-	   ((buf[6] == 0x4E && buf[7] == 0xDF) ||	/* LT */
-	    (buf[6] == 0x5E && buf[7] == 0xDF))) {	/* DT */
-		dev_warn(dev, "%s: remote associated refid=%02X\n",
-			 __func__, buf[1]);
-		ictx->rf_isassociating = false;
-	}
-}
-
-/**
- * Callback function for USB core API: receive data
- */
-static void usb_rx_callback_intf0(struct urb *urb)
-{
-	struct imon_context *ictx;
-	int intfnum = 0;
-
-	if (!urb)
-		return;
-
-	ictx = (struct imon_context *)urb->context;
-	if (!ictx)
-		return;
-
-	switch (urb->status) {
-	case -ENOENT:		/* usbcore unlink successful! */
-		return;
-
-	case -ESHUTDOWN:	/* transport endpoint was shut down */
-		break;
-
-	case 0:
-		imon_incoming_packet(ictx, urb, intfnum);
-		break;
-
-	default:
-		dev_warn(ictx->dev, "imon %s: status(%d): ignored\n",
-			 __func__, urb->status);
-		break;
-	}
-
-	usb_submit_urb(ictx->rx_urb_intf0, GFP_ATOMIC);
-}
-
-static void usb_rx_callback_intf1(struct urb *urb)
-{
-	struct imon_context *ictx;
-	int intfnum = 1;
-
-	if (!urb)
-		return;
-
-	ictx = (struct imon_context *)urb->context;
-	if (!ictx)
-		return;
-
-	switch (urb->status) {
-	case -ENOENT:		/* usbcore unlink successful! */
-		return;
-
-	case -ESHUTDOWN:	/* transport endpoint was shut down */
-		break;
-
-	case 0:
-		imon_incoming_packet(ictx, urb, intfnum);
-		break;
-
-	default:
-		dev_warn(ictx->dev, "imon %s: status(%d): ignored\n",
-			 __func__, urb->status);
-		break;
-	}
-
-	usb_submit_urb(ictx->rx_urb_intf1, GFP_ATOMIC);
-}
-
-/*
- * The 0x15c2:0xffdc device ID was used for umpteen different imon
- * devices, and all of them constantly spew interrupts, even when there
- * is no actual data to report. However, byte 6 of this buffer looks like
- * its unique across device variants, so we're trying to key off that to
- * figure out which display type (if any) and what IR protocol the device
- * actually supports. These devices have their IR protocol hard-coded into
- * their firmware, they can't be changed on the fly like the newer hardware.
- */
-static void imon_get_ffdc_type(struct imon_context *ictx)
-{
-	u8 ffdc_cfg_byte = ictx->usb_rx_buf[6];
-	u8 detected_display_type = IMON_DISPLAY_TYPE_NONE;
-	u64 allowed_protos = IR_TYPE_OTHER;
-
-	switch (ffdc_cfg_byte) {
-	/* iMON Knob, no display, iMON IR + vol knob */
-	case 0x21:
-		dev_info(ictx->dev, "0xffdc iMON Knob, iMON IR");
-		ictx->display_supported = false;
-		break;
-	/* iMON 2.4G LT (usb stick), no display, iMON RF */
-	case 0x4e:
-		dev_info(ictx->dev, "0xffdc iMON 2.4G LT, iMON RF");
-		ictx->display_supported = false;
-		ictx->rf_device = true;
-		break;
-	/* iMON VFD, no IR (does have vol knob tho) */
-	case 0x35:
-		dev_info(ictx->dev, "0xffdc iMON VFD + knob, no IR");
-		detected_display_type = IMON_DISPLAY_TYPE_VFD;
-		break;
-	/* iMON VFD, iMON IR */
-	case 0x24:
-	case 0x85:
-		dev_info(ictx->dev, "0xffdc iMON VFD, iMON IR");
-		detected_display_type = IMON_DISPLAY_TYPE_VFD;
-		break;
-	/* iMON VFD, MCE IR */
-	case 0x9e:
-		dev_info(ictx->dev, "0xffdc iMON VFD, MCE IR");
-		detected_display_type = IMON_DISPLAY_TYPE_VFD;
-		allowed_protos = IR_TYPE_RC6;
-		break;
-	/* iMON LCD, MCE IR */
-	case 0x9f:
-		dev_info(ictx->dev, "0xffdc iMON LCD, MCE IR");
-		detected_display_type = IMON_DISPLAY_TYPE_LCD;
-		allowed_protos = IR_TYPE_RC6;
-		break;
-	default:
-		dev_info(ictx->dev, "Unknown 0xffdc device, "
-			 "defaulting to VFD and iMON IR");
-		detected_display_type = IMON_DISPLAY_TYPE_VFD;
-		break;
-	}
-
-	printk(KERN_CONT " (id 0x%02x)\n", ffdc_cfg_byte);
-
-	ictx->display_type = detected_display_type;
-	ictx->props->allowed_protos = allowed_protos;
-	ictx->ir_type = allowed_protos;
-}
-
-static void imon_set_display_type(struct imon_context *ictx)
-{
-	u8 configured_display_type = IMON_DISPLAY_TYPE_VFD;
-
-	/*
-	 * Try to auto-detect the type of display if the user hasn't set
-	 * it by hand via the display_type modparam. Default is VFD.
-	 */
-
-	if (display_type == IMON_DISPLAY_TYPE_AUTO) {
-		switch (ictx->product) {
-		case 0xffdc:
-			/* set in imon_get_ffdc_type() */
-			configured_display_type = ictx->display_type;
-			break;
-		case 0x0034:
-		case 0x0035:
-			configured_display_type = IMON_DISPLAY_TYPE_VGA;
-			break;
-		case 0x0038:
-		case 0x0039:
-		case 0x0045:
-			configured_display_type = IMON_DISPLAY_TYPE_LCD;
-			break;
-		case 0x003c:
-		case 0x0041:
-		case 0x0042:
-		case 0x0043:
-			configured_display_type = IMON_DISPLAY_TYPE_NONE;
-			ictx->display_supported = false;
-			break;
-		case 0x0036:
-		case 0x0044:
-		default:
-			configured_display_type = IMON_DISPLAY_TYPE_VFD;
-			break;
-		}
-	} else {
-		configured_display_type = display_type;
-		if (display_type == IMON_DISPLAY_TYPE_NONE)
-			ictx->display_supported = false;
-		else
-			ictx->display_supported = true;
-		dev_info(ictx->dev, "%s: overriding display type to %d via "
-			 "modparam\n", __func__, display_type);
-	}
-
-	ictx->display_type = configured_display_type;
-}
-
-static struct input_dev *imon_init_rdev(struct imon_context *ictx)
-{
-	struct input_dev *rdev;
-	struct ir_dev_props *props;
-	int ret;
-	char *ir_codes = NULL;
-	const unsigned char fp_packet[] = { 0x40, 0x00, 0x00, 0x00,
-					    0x00, 0x00, 0x00, 0x88 };
-
-	rdev = input_allocate_device();
-	props = kzalloc(sizeof(*props), GFP_KERNEL);
-	if (!rdev || !props) {
-		dev_err(ictx->dev, "remote control dev allocation failed\n");
-		goto out;
-	}
-
-	snprintf(ictx->name_rdev, sizeof(ictx->name_rdev),
-		 "iMON Remote (%04x:%04x)", ictx->vendor, ictx->product);
-	usb_make_path(ictx->usbdev_intf0, ictx->phys_rdev,
-		      sizeof(ictx->phys_rdev));
-	strlcat(ictx->phys_rdev, "/input0", sizeof(ictx->phys_rdev));
-
-	rdev->name = ictx->name_rdev;
-	rdev->phys = ictx->phys_rdev;
-	usb_to_input_id(ictx->usbdev_intf0, &rdev->id);
-	rdev->dev.parent = ictx->dev;
-	rdev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP);
-	input_set_drvdata(rdev, ictx);
-
-	props->priv = ictx;
-	props->driver_type = RC_DRIVER_SCANCODE;
-	props->allowed_protos = IR_TYPE_OTHER | IR_TYPE_RC6; /* iMON PAD or MCE */
-	props->change_protocol = imon_ir_change_protocol;
-	ictx->props = props;
-
-	/* Enable front-panel buttons and/or knobs */
-	memcpy(ictx->usb_tx_buf, &fp_packet, sizeof(fp_packet));
-	ret = send_packet(ictx);
-	/* Not fatal, but warn about it */
-	if (ret)
-		dev_info(ictx->dev, "panel buttons/knobs setup failed\n");
-
-	if (ictx->product == 0xffdc)
-		imon_get_ffdc_type(ictx);
-
-	imon_set_display_type(ictx);
-
-	if (ictx->ir_type == IR_TYPE_RC6)
-		ir_codes = RC_MAP_IMON_MCE;
-	else
-		ir_codes = RC_MAP_IMON_PAD;
-
-	ret = ir_input_register(rdev, ir_codes, props, MOD_NAME);
-	if (ret < 0) {
-		dev_err(ictx->dev, "remote input dev register failed\n");
-		goto out;
-	}
-
-	return rdev;
-
-out:
-	kfree(props);
-	input_free_device(rdev);
-	return NULL;
-}
-
-static struct input_dev *imon_init_idev(struct imon_context *ictx)
-{
-	struct input_dev *idev;
-	int ret, i;
-
-	idev = input_allocate_device();
-	if (!idev) {
-		dev_err(ictx->dev, "input dev allocation failed\n");
-		goto out;
-	}
-
-	snprintf(ictx->name_idev, sizeof(ictx->name_idev),
-		 "iMON Panel, Knob and Mouse(%04x:%04x)",
-		 ictx->vendor, ictx->product);
-	idev->name = ictx->name_idev;
-
-	usb_make_path(ictx->usbdev_intf0, ictx->phys_idev,
-		      sizeof(ictx->phys_idev));
-	strlcat(ictx->phys_idev, "/input1", sizeof(ictx->phys_idev));
-	idev->phys = ictx->phys_idev;
-
-	idev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP) | BIT_MASK(EV_REL);
-
-	idev->keybit[BIT_WORD(BTN_MOUSE)] =
-		BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_RIGHT);
-	idev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y) |
-		BIT_MASK(REL_WHEEL);
-
-	/* panel and/or knob code support */
-	for (i = 0; i < ARRAY_SIZE(imon_panel_key_table); i++) {
-		u32 kc = imon_panel_key_table[i].keycode;
-		__set_bit(kc, idev->keybit);
-	}
-
-	usb_to_input_id(ictx->usbdev_intf0, &idev->id);
-	idev->dev.parent = ictx->dev;
-	input_set_drvdata(idev, ictx);
-
-	ret = input_register_device(idev);
-	if (ret < 0) {
-		dev_err(ictx->dev, "input dev register failed\n");
-		goto out;
-	}
-
-	return idev;
-
-out:
-	input_free_device(idev);
-	return NULL;
-}
-
-static struct input_dev *imon_init_touch(struct imon_context *ictx)
-{
-	struct input_dev *touch;
-	int ret;
-
-	touch = input_allocate_device();
-	if (!touch) {
-		dev_err(ictx->dev, "touchscreen input dev allocation failed\n");
-		goto touch_alloc_failed;
-	}
-
-	snprintf(ictx->name_touch, sizeof(ictx->name_touch),
-		 "iMON USB Touchscreen (%04x:%04x)",
-		 ictx->vendor, ictx->product);
-	touch->name = ictx->name_touch;
-
-	usb_make_path(ictx->usbdev_intf1, ictx->phys_touch,
-		      sizeof(ictx->phys_touch));
-	strlcat(ictx->phys_touch, "/input2", sizeof(ictx->phys_touch));
-	touch->phys = ictx->phys_touch;
-
-	touch->evbit[0] =
-		BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
-	touch->keybit[BIT_WORD(BTN_TOUCH)] =
-		BIT_MASK(BTN_TOUCH);
-	input_set_abs_params(touch, ABS_X,
-			     0x00, 0xfff, 0, 0);
-	input_set_abs_params(touch, ABS_Y,
-			     0x00, 0xfff, 0, 0);
-
-	input_set_drvdata(touch, ictx);
-
-	usb_to_input_id(ictx->usbdev_intf1, &touch->id);
-	touch->dev.parent = ictx->dev;
-	ret = input_register_device(touch);
-	if (ret <  0) {
-		dev_info(ictx->dev, "touchscreen input dev register failed\n");
-		goto touch_register_failed;
-	}
-
-	return touch;
-
-touch_register_failed:
-	input_free_device(ictx->touch);
-
-touch_alloc_failed:
-	return NULL;
-}
-
-static bool imon_find_endpoints(struct imon_context *ictx,
-				struct usb_host_interface *iface_desc)
-{
-	struct usb_endpoint_descriptor *ep;
-	struct usb_endpoint_descriptor *rx_endpoint = NULL;
-	struct usb_endpoint_descriptor *tx_endpoint = NULL;
-	int ifnum = iface_desc->desc.bInterfaceNumber;
-	int num_endpts = iface_desc->desc.bNumEndpoints;
-	int i, ep_dir, ep_type;
-	bool ir_ep_found = false;
-	bool display_ep_found = false;
-	bool tx_control = false;
-
-	/*
-	 * Scan the endpoint list and set:
-	 *	first input endpoint = IR endpoint
-	 *	first output endpoint = display endpoint
-	 */
-	for (i = 0; i < num_endpts && !(ir_ep_found && display_ep_found); ++i) {
-		ep = &iface_desc->endpoint[i].desc;
-		ep_dir = ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK;
-		ep_type = ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
-
-		if (!ir_ep_found && ep_dir == USB_DIR_IN &&
-		    ep_type == USB_ENDPOINT_XFER_INT) {
-
-			rx_endpoint = ep;
-			ir_ep_found = true;
-			dev_dbg(ictx->dev, "%s: found IR endpoint\n", __func__);
-
-		} else if (!display_ep_found && ep_dir == USB_DIR_OUT &&
-			   ep_type == USB_ENDPOINT_XFER_INT) {
-			tx_endpoint = ep;
-			display_ep_found = true;
-			dev_dbg(ictx->dev, "%s: found display endpoint\n", __func__);
-		}
-	}
-
-	if (ifnum == 0) {
-		ictx->rx_endpoint_intf0 = rx_endpoint;
-		/*
-		 * tx is used to send characters to lcd/vfd, associate RF
-		 * remotes, set IR protocol, and maybe more...
-		 */
-		ictx->tx_endpoint = tx_endpoint;
-	} else {
-		ictx->rx_endpoint_intf1 = rx_endpoint;
-	}
-
-	/*
-	 * If we didn't find a display endpoint, this is probably one of the
-	 * newer iMON devices that use control urb instead of interrupt
-	 */
-	if (!display_ep_found) {
-		tx_control = true;
-		display_ep_found = true;
-		dev_dbg(ictx->dev, "%s: device uses control endpoint, not "
-			"interface OUT endpoint\n", __func__);
-	}
-
-	/*
-	 * Some iMON receivers have no display. Unfortunately, it seems
-	 * that SoundGraph recycles device IDs between devices both with
-	 * and without... :\
-	 */
-	if (ictx->display_type == IMON_DISPLAY_TYPE_NONE) {
-		display_ep_found = false;
-		dev_dbg(ictx->dev, "%s: device has no display\n", __func__);
-	}
-
-	/*
-	 * iMON Touch devices have a VGA touchscreen, but no "display", as
-	 * that refers to e.g. /dev/lcd0 (a character device LCD or VFD).
-	 */
-	if (ictx->display_type == IMON_DISPLAY_TYPE_VGA) {
-		display_ep_found = false;
-		dev_dbg(ictx->dev, "%s: iMON Touch device found\n", __func__);
-	}
-
-	/* Input endpoint is mandatory */
-	if (!ir_ep_found)
-		pr_err("no valid input (IR) endpoint found\n");
-
-	ictx->tx_control = tx_control;
-
-	if (display_ep_found)
-		ictx->display_supported = true;
-
-	return ir_ep_found;
-
-}
-
-static struct imon_context *imon_init_intf0(struct usb_interface *intf)
-{
-	struct imon_context *ictx;
-	struct urb *rx_urb;
-	struct urb *tx_urb;
-	struct device *dev = &intf->dev;
-	struct usb_host_interface *iface_desc;
-	int ret = -ENOMEM;
-
-	ictx = kzalloc(sizeof(struct imon_context), GFP_KERNEL);
-	if (!ictx) {
-		dev_err(dev, "%s: kzalloc failed for context", __func__);
-		goto exit;
-	}
-	rx_urb = usb_alloc_urb(0, GFP_KERNEL);
-	if (!rx_urb) {
-		dev_err(dev, "%s: usb_alloc_urb failed for IR urb", __func__);
-		goto rx_urb_alloc_failed;
-	}
-	tx_urb = usb_alloc_urb(0, GFP_KERNEL);
-	if (!tx_urb) {
-		dev_err(dev, "%s: usb_alloc_urb failed for display urb",
-			__func__);
-		goto tx_urb_alloc_failed;
-	}
-
-	mutex_init(&ictx->lock);
-	spin_lock_init(&ictx->kc_lock);
-
-	mutex_lock(&ictx->lock);
-
-	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;
-
-	ictx->vendor  = le16_to_cpu(ictx->usbdev_intf0->descriptor.idVendor);
-	ictx->product = le16_to_cpu(ictx->usbdev_intf0->descriptor.idProduct);
-
-	ret = -ENODEV;
-	iface_desc = intf->cur_altsetting;
-	if (!imon_find_endpoints(ictx, iface_desc)) {
-		goto find_endpoint_failed;
-	}
-
-	ictx->idev = imon_init_idev(ictx);
-	if (!ictx->idev) {
-		dev_err(dev, "%s: input device setup failed\n", __func__);
-		goto idev_setup_failed;
-	}
-
-	ictx->rdev = imon_init_rdev(ictx);
-	if (!ictx->rdev) {
-		dev_err(dev, "%s: rc device setup failed\n", __func__);
-		goto rdev_setup_failed;
-	}
-
-	usb_fill_int_urb(ictx->rx_urb_intf0, ictx->usbdev_intf0,
-		usb_rcvintpipe(ictx->usbdev_intf0,
-			ictx->rx_endpoint_intf0->bEndpointAddress),
-		ictx->usb_rx_buf, sizeof(ictx->usb_rx_buf),
-		usb_rx_callback_intf0, ictx,
-		ictx->rx_endpoint_intf0->bInterval);
-
-	ret = usb_submit_urb(ictx->rx_urb_intf0, GFP_KERNEL);
-	if (ret) {
-		pr_err("usb_submit_urb failed for intf0 (%d)\n", ret);
-		goto urb_submit_failed;
-	}
-
-	return ictx;
-
-urb_submit_failed:
-	ir_input_unregister(ictx->rdev);
-rdev_setup_failed:
-	input_unregister_device(ictx->idev);
-idev_setup_failed:
-find_endpoint_failed:
-	mutex_unlock(&ictx->lock);
-	usb_free_urb(tx_urb);
-tx_urb_alloc_failed:
-	usb_free_urb(rx_urb);
-rx_urb_alloc_failed:
-	kfree(ictx);
-exit:
-	dev_err(dev, "unable to initialize intf0, err %d\n", ret);
-
-	return NULL;
-}
-
-static struct imon_context *imon_init_intf1(struct usb_interface *intf,
-					    struct imon_context *ictx)
-{
-	struct urb *rx_urb;
-	struct usb_host_interface *iface_desc;
-	int ret = -ENOMEM;
-
-	rx_urb = usb_alloc_urb(0, GFP_KERNEL);
-	if (!rx_urb) {
-		pr_err("usb_alloc_urb failed for IR urb\n");
-		goto rx_urb_alloc_failed;
-	}
-
-	mutex_lock(&ictx->lock);
-
-	if (ictx->display_type == IMON_DISPLAY_TYPE_VGA) {
-		init_timer(&ictx->ttimer);
-		ictx->ttimer.data = (unsigned long)ictx;
-		ictx->ttimer.function = imon_touch_display_timeout;
-	}
-
-	ictx->usbdev_intf1 = usb_get_dev(interface_to_usbdev(intf));
-	ictx->dev_present_intf1 = true;
-	ictx->rx_urb_intf1 = rx_urb;
-
-	ret = -ENODEV;
-	iface_desc = intf->cur_altsetting;
-	if (!imon_find_endpoints(ictx, iface_desc))
-		goto find_endpoint_failed;
-
-	if (ictx->display_type == IMON_DISPLAY_TYPE_VGA) {
-		ictx->touch = imon_init_touch(ictx);
-		if (!ictx->touch)
-			goto touch_setup_failed;
-	} else
-		ictx->touch = NULL;
-
-	usb_fill_int_urb(ictx->rx_urb_intf1, ictx->usbdev_intf1,
-		usb_rcvintpipe(ictx->usbdev_intf1,
-			ictx->rx_endpoint_intf1->bEndpointAddress),
-		ictx->usb_rx_buf, sizeof(ictx->usb_rx_buf),
-		usb_rx_callback_intf1, ictx,
-		ictx->rx_endpoint_intf1->bInterval);
-
-	ret = usb_submit_urb(ictx->rx_urb_intf1, GFP_KERNEL);
-
-	if (ret) {
-		pr_err("usb_submit_urb failed for intf1 (%d)\n", ret);
-		goto urb_submit_failed;
-	}
-
-	return ictx;
-
-urb_submit_failed:
-	if (ictx->touch)
-		input_unregister_device(ictx->touch);
-touch_setup_failed:
-find_endpoint_failed:
-	mutex_unlock(&ictx->lock);
-	usb_free_urb(rx_urb);
-rx_urb_alloc_failed:
-	dev_err(ictx->dev, "unable to initialize intf0, err %d\n", ret);
-
-	return NULL;
-}
-
-static void imon_init_display(struct imon_context *ictx,
-			      struct usb_interface *intf)
-{
-	int ret;
-
-	dev_dbg(ictx->dev, "Registering iMON display with sysfs\n");
-
-	/* set up sysfs entry for built-in clock */
-	ret = sysfs_create_group(&intf->dev.kobj, &imon_display_attr_group);
-	if (ret)
-		dev_err(ictx->dev, "Could not create display sysfs "
-			"entries(%d)", ret);
-
-	if (ictx->display_type == IMON_DISPLAY_TYPE_LCD)
-		ret = usb_register_dev(intf, &imon_lcd_class);
-	else
-		ret = usb_register_dev(intf, &imon_vfd_class);
-	if (ret)
-		/* Not a fatal error, so ignore */
-		dev_info(ictx->dev, "could not get a minor number for "
-			 "display\n");
-
-}
-
-/**
- * Callback function for USB core API: Probe
- */
-static int __devinit imon_probe(struct usb_interface *interface,
-				const struct usb_device_id *id)
-{
-	struct usb_device *usbdev = NULL;
-	struct usb_host_interface *iface_desc = NULL;
-	struct usb_interface *first_if;
-	struct device *dev = &interface->dev;
-	int ifnum, code_length, sysfs_err;
-	int ret = 0;
-	struct imon_context *ictx = NULL;
-	struct imon_context *first_if_ctx = NULL;
-	u16 vendor, product;
-
-	code_length = BUF_CHUNK_SIZE * 8;
-
-	usbdev     = usb_get_dev(interface_to_usbdev(interface));
-	iface_desc = interface->cur_altsetting;
-	ifnum      = iface_desc->desc.bInterfaceNumber;
-	vendor     = le16_to_cpu(usbdev->descriptor.idVendor);
-	product    = le16_to_cpu(usbdev->descriptor.idProduct);
-
-	dev_dbg(dev, "%s: found iMON device (%04x:%04x, intf%d)\n",
-		__func__, vendor, product, ifnum);
-
-	/* prevent races probing devices w/multiple interfaces */
-	mutex_lock(&driver_lock);
-
-	first_if = usb_ifnum_to_if(usbdev, 0);
-	first_if_ctx = (struct imon_context *)usb_get_intfdata(first_if);
-
-	if (ifnum == 0) {
-		ictx = imon_init_intf0(interface);
-		if (!ictx) {
-			pr_err("failed to initialize context!\n");
-			ret = -ENODEV;
-			goto fail;
-		}
-
-	} else {
-	/* this is the secondary interface on the device */
-		ictx = imon_init_intf1(interface, first_if_ctx);
-		if (!ictx) {
-			pr_err("failed to attach to context!\n");
-			ret = -ENODEV;
-			goto fail;
-		}
-
-	}
-
-	usb_set_intfdata(interface, ictx);
-
-	if (ifnum == 0) {
-		if (product == 0xffdc && ictx->rf_device) {
-			sysfs_err = sysfs_create_group(&interface->dev.kobj,
-						       &imon_rf_attr_group);
-			if (sysfs_err)
-				pr_err("Could not create RF sysfs entries(%d)\n",
-				       sysfs_err);
-		}
-
-		if (ictx->display_supported)
-			imon_init_display(ictx, interface);
-	}
-
-	dev_info(dev, "iMON device (%04x:%04x, intf%d) on "
-		 "usb<%d:%d> initialized\n", vendor, product, ifnum,
-		 usbdev->bus->busnum, usbdev->devnum);
-
-	mutex_unlock(&ictx->lock);
-	mutex_unlock(&driver_lock);
-
-	return 0;
-
-fail:
-	mutex_unlock(&driver_lock);
-	dev_err(dev, "unable to register, err %d\n", ret);
-
-	return ret;
-}
-
-/**
- * Callback function for USB core API: disconnect
- */
-static void __devexit imon_disconnect(struct usb_interface *interface)
-{
-	struct imon_context *ictx;
-	struct device *dev;
-	int ifnum;
-
-	/* prevent races with multi-interface device probing and display_open */
-	mutex_lock(&driver_lock);
-
-	ictx = usb_get_intfdata(interface);
-	dev = ictx->dev;
-	ifnum = interface->cur_altsetting->desc.bInterfaceNumber;
-
-	mutex_lock(&ictx->lock);
-
-	/*
-	 * sysfs_remove_group is safe to call even if sysfs_create_group
-	 * hasn't been called
-	 */
-	sysfs_remove_group(&interface->dev.kobj, &imon_display_attr_group);
-	sysfs_remove_group(&interface->dev.kobj, &imon_rf_attr_group);
-
-	usb_set_intfdata(interface, NULL);
-
-	/* Abort ongoing write */
-	if (ictx->tx.busy) {
-		usb_kill_urb(ictx->tx_urb);
-		complete_all(&ictx->tx.finished);
-	}
-
-	if (ifnum == 0) {
-		ictx->dev_present_intf0 = false;
-		usb_kill_urb(ictx->rx_urb_intf0);
-		input_unregister_device(ictx->idev);
-		ir_input_unregister(ictx->rdev);
-		if (ictx->display_supported) {
-			if (ictx->display_type == IMON_DISPLAY_TYPE_LCD)
-				usb_deregister_dev(interface, &imon_lcd_class);
-			else
-				usb_deregister_dev(interface, &imon_vfd_class);
-		}
-	} else {
-		ictx->dev_present_intf1 = false;
-		usb_kill_urb(ictx->rx_urb_intf1);
-		if (ictx->display_type == IMON_DISPLAY_TYPE_VGA)
-			input_unregister_device(ictx->touch);
-	}
-
-	if (!ictx->dev_present_intf0 && !ictx->dev_present_intf1) {
-		if (ictx->display_type == IMON_DISPLAY_TYPE_VGA)
-			del_timer_sync(&ictx->ttimer);
-		mutex_unlock(&ictx->lock);
-		if (!ictx->display_isopen)
-			free_imon_context(ictx);
-	} else
-		mutex_unlock(&ictx->lock);
-
-	mutex_unlock(&driver_lock);
-
-	dev_dbg(dev, "%s: iMON device (intf%d) disconnected\n",
-		__func__, ifnum);
-}
-
-static int imon_suspend(struct usb_interface *intf, pm_message_t message)
-{
-	struct imon_context *ictx = usb_get_intfdata(intf);
-	int ifnum = intf->cur_altsetting->desc.bInterfaceNumber;
-
-	if (ifnum == 0)
-		usb_kill_urb(ictx->rx_urb_intf0);
-	else
-		usb_kill_urb(ictx->rx_urb_intf1);
-
-	return 0;
-}
-
-static int imon_resume(struct usb_interface *intf)
-{
-	int rc = 0;
-	struct imon_context *ictx = usb_get_intfdata(intf);
-	int ifnum = intf->cur_altsetting->desc.bInterfaceNumber;
-
-	if (ifnum == 0) {
-		usb_fill_int_urb(ictx->rx_urb_intf0, ictx->usbdev_intf0,
-			usb_rcvintpipe(ictx->usbdev_intf0,
-				ictx->rx_endpoint_intf0->bEndpointAddress),
-			ictx->usb_rx_buf, sizeof(ictx->usb_rx_buf),
-			usb_rx_callback_intf0, ictx,
-			ictx->rx_endpoint_intf0->bInterval);
-
-		rc = usb_submit_urb(ictx->rx_urb_intf0, GFP_ATOMIC);
-
-	} else {
-		usb_fill_int_urb(ictx->rx_urb_intf1, ictx->usbdev_intf1,
-			usb_rcvintpipe(ictx->usbdev_intf1,
-				ictx->rx_endpoint_intf1->bEndpointAddress),
-			ictx->usb_rx_buf, sizeof(ictx->usb_rx_buf),
-			usb_rx_callback_intf1, ictx,
-			ictx->rx_endpoint_intf1->bInterval);
-
-		rc = usb_submit_urb(ictx->rx_urb_intf1, GFP_ATOMIC);
-	}
-
-	return rc;
-}
-
-static int __init imon_init(void)
-{
-	int rc;
-
-	rc = usb_register(&imon_driver);
-	if (rc) {
-		pr_err("usb register failed(%d)\n", rc);
-		rc = -ENODEV;
-	}
-
-	return rc;
-}
-
-static void __exit imon_exit(void)
-{
-	usb_deregister(&imon_driver);
-}
-
-module_init(imon_init);
-module_exit(imon_exit);
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/ir-core-priv.h linux-libre-2.6.38-gnu1/drivers/media/IR/ir-core-priv.h
--- linux-libre-2.6.37-gnu1/drivers/media/IR/ir-core-priv.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/ir-core-priv.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,203 +0,0 @@
-/*
- * Remote Controller core raw events header
- *
- * Copyright (C) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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.
- */
-
-#ifndef _IR_RAW_EVENT
-#define _IR_RAW_EVENT
-
-#include <linux/slab.h>
-#include <linux/spinlock.h>
-#include <media/ir-core.h>
-
-struct ir_raw_handler {
-	struct list_head list;
-
-	u64 protocols; /* which are handled by this handler */
-	int (*decode)(struct input_dev *input_dev, struct ir_raw_event event);
-
-	/* These two should only be used by the lirc decoder */
-	int (*raw_register)(struct input_dev *input_dev);
-	int (*raw_unregister)(struct input_dev *input_dev);
-};
-
-struct ir_raw_event_ctrl {
-	struct list_head		list;		/* to keep track of raw clients */
-	struct task_struct		*thread;
-	spinlock_t			lock;
-	struct kfifo			kfifo;		/* fifo for the pulse/space durations */
-	ktime_t				last_event;	/* when last event occurred */
-	enum raw_event_type		last_type;	/* last event type */
-	struct input_dev		*input_dev;	/* pointer to the parent input_dev */
-	u64				enabled_protocols; /* enabled raw protocol decoders */
-
-	/* raw decoder state follows */
-	struct ir_raw_event prev_ev;
-	struct ir_raw_event this_ev;
-	struct nec_dec {
-		int state;
-		unsigned count;
-		u32 bits;
-		bool is_nec_x;
-		bool necx_repeat;
-	} nec;
-	struct rc5_dec {
-		int state;
-		u32 bits;
-		unsigned count;
-		unsigned wanted_bits;
-	} rc5;
-	struct rc6_dec {
-		int state;
-		u8 header;
-		u32 body;
-		bool toggle;
-		unsigned count;
-		unsigned wanted_bits;
-	} rc6;
-	struct sony_dec {
-		int state;
-		u32 bits;
-		unsigned count;
-	} sony;
-	struct jvc_dec {
-		int state;
-		u16 bits;
-		u16 old_bits;
-		unsigned count;
-		bool first;
-		bool toggle;
-	} jvc;
-	struct rc5_sz_dec {
-		int state;
-		u32 bits;
-		unsigned count;
-		unsigned wanted_bits;
-	} rc5_sz;
-	struct lirc_codec {
-		struct ir_input_dev *ir_dev;
-		struct lirc_driver *drv;
-		int carrier_low;
-
-		ktime_t gap_start;
-		u64 gap_duration;
-		bool gap;
-		bool send_timeout_reports;
-
-	} lirc;
-};
-
-/* macros for IR decoders */
-static inline bool geq_margin(unsigned d1, unsigned d2, unsigned margin)
-{
-	return d1 > (d2 - margin);
-}
-
-static inline bool eq_margin(unsigned d1, unsigned d2, unsigned margin)
-{
-	return ((d1 > (d2 - margin)) && (d1 < (d2 + margin)));
-}
-
-static inline bool is_transition(struct ir_raw_event *x, struct ir_raw_event *y)
-{
-	return x->pulse != y->pulse;
-}
-
-static inline void decrease_duration(struct ir_raw_event *ev, unsigned duration)
-{
-	if (duration > ev->duration)
-		ev->duration = 0;
-	else
-		ev->duration -= duration;
-}
-
-/* Returns true if event is normal pulse/space event */
-static inline bool is_timing_event(struct ir_raw_event ev)
-{
-	return !ev.carrier_report && !ev.reset;
-}
-
-#define TO_US(duration)			DIV_ROUND_CLOSEST((duration), 1000)
-#define TO_STR(is_pulse)		((is_pulse) ? "pulse" : "space")
-/*
- * Routines from ir-sysfs.c - Meant to be called only internally inside
- * ir-core
- */
-int ir_register_input(struct input_dev *input_dev);
-
-int ir_register_class(struct input_dev *input_dev);
-void ir_unregister_class(struct input_dev *input_dev);
-
-/*
- * Routines from ir-raw-event.c to be used internally and by decoders
- */
-u64 ir_raw_get_allowed_protocols(void);
-int ir_raw_event_register(struct input_dev *input_dev);
-void ir_raw_event_unregister(struct input_dev *input_dev);
-int ir_raw_handler_register(struct ir_raw_handler *ir_raw_handler);
-void ir_raw_handler_unregister(struct ir_raw_handler *ir_raw_handler);
-void ir_raw_init(void);
-
-int ir_rcmap_init(void);
-void ir_rcmap_cleanup(void);
-/*
- * Decoder initialization code
- *
- * Those load logic are called during ir-core init, and automatically
- * loads the compiled decoders for their usage with IR raw events
- */
-
-/* from ir-nec-decoder.c */
-#ifdef CONFIG_IR_NEC_DECODER_MODULE
-#define load_nec_decode()	request_module("ir-nec-decoder")
-#else
-#define load_nec_decode()	0
-#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
-#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
-#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
-#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
-#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
-#endif
-
-
-#endif /* _IR_RAW_EVENT */
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/ir-functions.c linux-libre-2.6.38-gnu1/drivers/media/IR/ir-functions.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/ir-functions.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/ir-functions.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,356 +0,0 @@
-/*
- *
- * some common structs and functions to handle infrared remotes via
- * input layer ...
- *
- * (c) 2003 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
- *
- *  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/string.h>
-#include <linux/jiffies.h>
-#include <media/ir-common.h>
-#include "ir-core-priv.h"
-
-/* -------------------------------------------------------------------------- */
-
-MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
-MODULE_LICENSE("GPL");
-
-static int repeat = 1;
-module_param(repeat, int, 0444);
-MODULE_PARM_DESC(repeat,"auto-repeat for IR keys (default: on)");
-
-/* -------------------------------------------------------------------------- */
-
-static void ir_input_key_event(struct input_dev *dev, struct ir_input_state *ir)
-{
-	if (KEY_RESERVED == ir->keycode) {
-		printk(KERN_INFO "%s: unknown key: key=0x%02x down=%d\n",
-		       dev->name, ir->ir_key, ir->keypressed);
-		return;
-	}
-	IR_dprintk(1,"%s: key event code=%d down=%d\n",
-		dev->name,ir->keycode,ir->keypressed);
-	input_report_key(dev,ir->keycode,ir->keypressed);
-	input_sync(dev);
-}
-
-/* -------------------------------------------------------------------------- */
-
-int ir_input_init(struct input_dev *dev, struct ir_input_state *ir,
-		  const u64 ir_type)
-{
-	ir->ir_type = ir_type;
-
-	if (repeat)
-		set_bit(EV_REP, dev->evbit);
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(ir_input_init);
-
-
-void ir_input_nokey(struct input_dev *dev, struct ir_input_state *ir)
-{
-	if (ir->keypressed) {
-		ir->keypressed = 0;
-		ir_input_key_event(dev,ir);
-	}
-}
-EXPORT_SYMBOL_GPL(ir_input_nokey);
-
-void ir_input_keydown(struct input_dev *dev, struct ir_input_state *ir,
-		      u32 ir_key)
-{
-	u32 keycode = ir_g_keycode_from_table(dev, ir_key);
-
-	if (ir->keypressed && ir->keycode != keycode) {
-		ir->keypressed = 0;
-		ir_input_key_event(dev,ir);
-	}
-	if (!ir->keypressed) {
-		ir->ir_key  = ir_key;
-		ir->keycode = keycode;
-		ir->keypressed = 1;
-		ir_input_key_event(dev,ir);
-	}
-}
-EXPORT_SYMBOL_GPL(ir_input_keydown);
-
-/* -------------------------------------------------------------------------- */
-/* extract mask bits out of data and pack them into the result */
-u32 ir_extract_bits(u32 data, u32 mask)
-{
-	u32 vbit = 1, value = 0;
-
-	do {
-	    if (mask&1) {
-		if (data&1)
-			value |= vbit;
-		vbit<<=1;
-	    }
-	    data>>=1;
-	} while (mask>>=1);
-
-	return value;
-}
-EXPORT_SYMBOL_GPL(ir_extract_bits);
-
-static int inline getbit(u32 *samples, int bit)
-{
-	return (samples[bit/32] & (1 << (31-(bit%32)))) ? 1 : 0;
-}
-
-/* sump raw samples for visual debugging ;) */
-int ir_dump_samples(u32 *samples, int count)
-{
-	int i, bit, start;
-
-	printk(KERN_DEBUG "ir samples: ");
-	start = 0;
-	for (i = 0; i < count * 32; i++) {
-		bit = getbit(samples,i);
-		if (bit)
-			start = 1;
-		if (0 == start)
-			continue;
-		printk("%s", bit ? "#" : "_");
-	}
-	printk("\n");
-	return 0;
-}
-EXPORT_SYMBOL_GPL(ir_dump_samples);
-
-/* decode raw samples, pulse distance coding used by NEC remotes */
-int ir_decode_pulsedistance(u32 *samples, int count, int low, int high)
-{
-	int i,last,bit,len;
-	u32 curBit;
-	u32 value;
-
-	/* find start burst */
-	for (i = len = 0; i < count * 32; i++) {
-		bit = getbit(samples,i);
-		if (bit) {
-			len++;
-		} else {
-			if (len >= 29)
-				break;
-			len = 0;
-		}
-	}
-
-	/* start burst to short */
-	if (len < 29)
-		return 0xffffffff;
-
-	/* find start silence */
-	for (len = 0; i < count * 32; i++) {
-		bit = getbit(samples,i);
-		if (bit) {
-			break;
-		} else {
-			len++;
-		}
-	}
-
-	/* silence to short */
-	if (len < 7)
-		return 0xffffffff;
-
-	/* go decoding */
-	len   = 0;
-	last = 1;
-	value = 0; curBit = 1;
-	for (; i < count * 32; i++) {
-		bit  = getbit(samples,i);
-		if (last) {
-			if(bit) {
-				continue;
-			} else {
-				len = 1;
-			}
-		} else {
-			if (bit) {
-				if (len > (low + high) /2)
-					value |= curBit;
-				curBit <<= 1;
-				if (curBit == 1)
-					break;
-			} else {
-				len++;
-			}
-		}
-		last = bit;
-	}
-
-	return value;
-}
-EXPORT_SYMBOL_GPL(ir_decode_pulsedistance);
-
-/* decode raw samples, biphase coding, used by rc5 for example */
-int ir_decode_biphase(u32 *samples, int count, int low, int high)
-{
-	int i,last,bit,len,flips;
-	u32 value;
-
-	/* find start bit (1) */
-	for (i = 0; i < 32; i++) {
-		bit = getbit(samples,i);
-		if (bit)
-			break;
-	}
-
-	/* go decoding */
-	len   = 0;
-	flips = 0;
-	value = 1;
-	for (; i < count * 32; i++) {
-		if (len > high)
-			break;
-		if (flips > 1)
-			break;
-		last = bit;
-		bit  = getbit(samples,i);
-		if (last == bit) {
-			len++;
-			continue;
-		}
-		if (len < low) {
-			len++;
-			flips++;
-			continue;
-		}
-		value <<= 1;
-		value |= bit;
-		flips = 0;
-		len   = 1;
-	}
-	return value;
-}
-EXPORT_SYMBOL_GPL(ir_decode_biphase);
-
-/* RC5 decoding stuff, moved from bttv-input.c to share it with
- * saa7134 */
-
-/* decode raw bit pattern to RC5 code */
-u32 ir_rc5_decode(unsigned int code)
-{
-	unsigned int org_code = code;
-	unsigned int pair;
-	unsigned int rc5 = 0;
-	int i;
-
-	for (i = 0; i < 14; ++i) {
-		pair = code & 0x3;
-		code >>= 2;
-
-		rc5 <<= 1;
-		switch (pair) {
-		case 0:
-		case 2:
-			break;
-		case 1:
-			rc5 |= 1;
-			break;
-		case 3:
-			IR_dprintk(1, "ir-common: ir_rc5_decode(%x) bad code\n", org_code);
-			return 0;
-		}
-	}
-	IR_dprintk(1, "ir-common: 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;
-}
-EXPORT_SYMBOL_GPL(ir_rc5_decode);
-
-void ir_rc5_timer_end(unsigned long data)
-{
-	struct card_ir *ir = (struct card_ir *)data;
-	struct timeval tv;
-	unsigned long current_jiffies, timeout;
-	u32 gap;
-	u32 rc5 = 0;
-
-	/* get time */
-	current_jiffies = jiffies;
-	do_gettimeofday(&tv);
-
-	/* avoid overflow with gap >1s */
-	if (tv.tv_sec - ir->base_time.tv_sec > 1) {
-		gap = 200000;
-	} else {
-		gap = 1000000 * (tv.tv_sec - ir->base_time.tv_sec) +
-		    tv.tv_usec - ir->base_time.tv_usec;
-	}
-
-	/* signal we're ready to start a new code */
-	ir->active = 0;
-
-	/* Allow some timer jitter (RC5 is ~24ms anyway so this is ok) */
-	if (gap < 28000) {
-		IR_dprintk(1, "ir-common: spurious timer_end\n");
-		return;
-	}
-
-	if (ir->last_bit < 20) {
-		/* ignore spurious codes (caused by light/other remotes) */
-		IR_dprintk(1, "ir-common: short code: %x\n", ir->code);
-	} else {
-		ir->code = (ir->code << ir->shift_by) | 1;
-		rc5 = ir_rc5_decode(ir->code);
-
-		/* two start bits? */
-		if (RC5_START(rc5) != ir->start) {
-			IR_dprintk(1, "ir-common: rc5 start bits invalid: %u\n", RC5_START(rc5));
-
-			/* right address? */
-		} else if (RC5_ADDR(rc5) == ir->addr) {
-			u32 toggle = RC5_TOGGLE(rc5);
-			u32 instr = RC5_INSTR(rc5);
-
-			/* Good code, decide if repeat/repress */
-			if (toggle != RC5_TOGGLE(ir->last_rc5) ||
-			    instr != RC5_INSTR(ir->last_rc5)) {
-				IR_dprintk(1, "ir-common: instruction %x, toggle %x\n", instr,
-					toggle);
-				ir_input_nokey(ir->dev, &ir->ir);
-				ir_input_keydown(ir->dev, &ir->ir, instr);
-			}
-
-			/* Set/reset key-up timer */
-			timeout = current_jiffies +
-				  msecs_to_jiffies(ir->rc5_key_timeout);
-			mod_timer(&ir->timer_keyup, timeout);
-
-			/* Save code for repeat test */
-			ir->last_rc5 = rc5;
-		}
-	}
-}
-EXPORT_SYMBOL_GPL(ir_rc5_timer_end);
-
-void ir_rc5_timer_keyup(unsigned long data)
-{
-	struct card_ir *ir = (struct card_ir *)data;
-
-	IR_dprintk(1, "ir-common: key released\n");
-	ir_input_nokey(ir->dev, &ir->ir);
-}
-EXPORT_SYMBOL_GPL(ir_rc5_timer_keyup);
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/ir-jvc-decoder.c linux-libre-2.6.38-gnu1/drivers/media/IR/ir-jvc-decoder.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/ir-jvc-decoder.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/ir-jvc-decoder.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,199 +0,0 @@
-/* ir-jvc-decoder.c - handle JVC IR Pulse/Space protocol
- *
- * Copyright (C) 2010 by David Härdeman <david@hardeman.nu>
- *
- * 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.
- */
-
-#include <linux/bitrev.h>
-#include "ir-core-priv.h"
-
-#define JVC_NBITS		16		/* dev(8) + func(8) */
-#define JVC_UNIT		525000		/* ns */
-#define JVC_HEADER_PULSE	(16 * JVC_UNIT) /* lack of header -> repeat */
-#define JVC_HEADER_SPACE	(8  * JVC_UNIT)
-#define JVC_BIT_PULSE		(1  * JVC_UNIT)
-#define JVC_BIT_0_SPACE		(1  * JVC_UNIT)
-#define JVC_BIT_1_SPACE		(3  * JVC_UNIT)
-#define JVC_TRAILER_PULSE	(1  * JVC_UNIT)
-#define	JVC_TRAILER_SPACE	(35 * JVC_UNIT)
-
-enum jvc_state {
-	STATE_INACTIVE,
-	STATE_HEADER_SPACE,
-	STATE_BIT_PULSE,
-	STATE_BIT_SPACE,
-	STATE_TRAILER_PULSE,
-	STATE_TRAILER_SPACE,
-	STATE_CHECK_REPEAT,
-};
-
-/**
- * ir_jvc_decode() - Decode one JVC pulse or space
- * @input_dev:	the struct input_dev descriptor of the device
- * @duration:   the struct ir_raw_event descriptor of the pulse/space
- *
- * This function returns -EINVAL if the pulse violates the state machine
- */
-static int ir_jvc_decode(struct input_dev *input_dev, struct ir_raw_event ev)
-{
-	struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
-	struct jvc_dec *data = &ir_dev->raw->jvc;
-
-	if (!(ir_dev->raw->enabled_protocols & IR_TYPE_JVC))
-		return 0;
-
-	if (!is_timing_event(ev)) {
-		if (ev.reset)
-			data->state = STATE_INACTIVE;
-		return 0;
-	}
-
-	if (!geq_margin(ev.duration, JVC_UNIT, JVC_UNIT / 2))
-		goto out;
-
-	IR_dprintk(2, "JVC decode started at state %d (%uus %s)\n",
-		   data->state, TO_US(ev.duration), TO_STR(ev.pulse));
-
-again:
-	switch (data->state) {
-
-	case STATE_INACTIVE:
-		if (!ev.pulse)
-			break;
-
-		if (!eq_margin(ev.duration, JVC_HEADER_PULSE, JVC_UNIT / 2))
-			break;
-
-		data->count = 0;
-		data->first = true;
-		data->toggle = !data->toggle;
-		data->state = STATE_HEADER_SPACE;
-		return 0;
-
-	case STATE_HEADER_SPACE:
-		if (ev.pulse)
-			break;
-
-		if (!eq_margin(ev.duration, JVC_HEADER_SPACE, JVC_UNIT / 2))
-			break;
-
-		data->state = STATE_BIT_PULSE;
-		return 0;
-
-	case STATE_BIT_PULSE:
-		if (!ev.pulse)
-			break;
-
-		if (!eq_margin(ev.duration, JVC_BIT_PULSE, JVC_UNIT / 2))
-			break;
-
-		data->state = STATE_BIT_SPACE;
-		return 0;
-
-	case STATE_BIT_SPACE:
-		if (ev.pulse)
-			break;
-
-		data->bits <<= 1;
-		if (eq_margin(ev.duration, JVC_BIT_1_SPACE, JVC_UNIT / 2)) {
-			data->bits |= 1;
-			decrease_duration(&ev, JVC_BIT_1_SPACE);
-		} else if (eq_margin(ev.duration, JVC_BIT_0_SPACE, JVC_UNIT / 2))
-			decrease_duration(&ev, JVC_BIT_0_SPACE);
-		else
-			break;
-		data->count++;
-
-		if (data->count == JVC_NBITS)
-			data->state = STATE_TRAILER_PULSE;
-		else
-			data->state = STATE_BIT_PULSE;
-		return 0;
-
-	case STATE_TRAILER_PULSE:
-		if (!ev.pulse)
-			break;
-
-		if (!eq_margin(ev.duration, JVC_TRAILER_PULSE, JVC_UNIT / 2))
-			break;
-
-		data->state = STATE_TRAILER_SPACE;
-		return 0;
-
-	case STATE_TRAILER_SPACE:
-		if (ev.pulse)
-			break;
-
-		if (!geq_margin(ev.duration, JVC_TRAILER_SPACE, JVC_UNIT / 2))
-			break;
-
-		if (data->first) {
-			u32 scancode;
-			scancode = (bitrev8((data->bits >> 8) & 0xff) << 8) |
-				   (bitrev8((data->bits >> 0) & 0xff) << 0);
-			IR_dprintk(1, "JVC scancode 0x%04x\n", scancode);
-			ir_keydown(input_dev, scancode, data->toggle);
-			data->first = false;
-			data->old_bits = data->bits;
-		} else if (data->bits == data->old_bits) {
-			IR_dprintk(1, "JVC repeat\n");
-			ir_repeat(input_dev);
-		} else {
-			IR_dprintk(1, "JVC invalid repeat msg\n");
-			break;
-		}
-
-		data->count = 0;
-		data->state = STATE_CHECK_REPEAT;
-		return 0;
-
-	case STATE_CHECK_REPEAT:
-		if (!ev.pulse)
-			break;
-
-		if (eq_margin(ev.duration, JVC_HEADER_PULSE, JVC_UNIT / 2))
-			data->state = STATE_INACTIVE;
-  else
-			data->state = STATE_BIT_PULSE;
-		goto again;
-	}
-
-out:
-	IR_dprintk(1, "JVC decode failed at state %d (%uus %s)\n",
-		   data->state, TO_US(ev.duration), TO_STR(ev.pulse));
-	data->state = STATE_INACTIVE;
-	return -EINVAL;
-}
-
-static struct ir_raw_handler jvc_handler = {
-	.protocols	= IR_TYPE_JVC,
-	.decode		= ir_jvc_decode,
-};
-
-static int __init ir_jvc_decode_init(void)
-{
-	ir_raw_handler_register(&jvc_handler);
-
-	printk(KERN_INFO "IR JVC protocol handler initialized\n");
-	return 0;
-}
-
-static void __exit ir_jvc_decode_exit(void)
-{
-	ir_raw_handler_unregister(&jvc_handler);
-}
-
-module_init(ir_jvc_decode_init);
-module_exit(ir_jvc_decode_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("David Härdeman <david@hardeman.nu>");
-MODULE_DESCRIPTION("JVC IR protocol decoder");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/ir-keytable.c linux-libre-2.6.38-gnu1/drivers/media/IR/ir-keytable.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/ir-keytable.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/ir-keytable.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,710 +0,0 @@
-/* ir-keytable.c - handle IR scancode->keycode tables
- *
- * Copyright (C) 2009 by Mauro Carvalho Chehab <mchehab@redhat.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.
- */
-
-
-#include <linux/input.h>
-#include <linux/slab.h>
-#include "ir-core-priv.h"
-
-/* Sizes are in bytes, 256 bytes allows for 32 entries on x64 */
-#define IR_TAB_MIN_SIZE	256
-#define IR_TAB_MAX_SIZE	8192
-
-/* FIXME: IR_KEYPRESS_TIMEOUT should be protocol specific */
-#define IR_KEYPRESS_TIMEOUT 250
-
-/**
- * ir_create_table() - initializes a scancode table
- * @rc_tab:	the ir_scancode_table to initialize
- * @name:	name to assign to the table
- * @ir_type:	ir type to assign to the new table
- * @size:	initial size of the table
- * @return:	zero on success or a negative error code
- *
- * This routine will initialize the ir_scancode_table and will allocate
- * memory to hold at least the specified number elements.
- */
-static int ir_create_table(struct ir_scancode_table *rc_tab,
-			   const char *name, u64 ir_type, size_t size)
-{
-	rc_tab->name = name;
-	rc_tab->ir_type = ir_type;
-	rc_tab->alloc = roundup_pow_of_two(size * sizeof(struct ir_scancode));
-	rc_tab->size = rc_tab->alloc / sizeof(struct ir_scancode);
-	rc_tab->scan = kmalloc(rc_tab->alloc, GFP_KERNEL);
-	if (!rc_tab->scan)
-		return -ENOMEM;
-
-	IR_dprintk(1, "Allocated space for %u keycode entries (%u bytes)\n",
-		   rc_tab->size, rc_tab->alloc);
-	return 0;
-}
-
-/**
- * ir_free_table() - frees memory allocated by a scancode table
- * @rc_tab:	the table whose mappings need to be freed
- *
- * This routine will free memory alloctaed for key mappings used by given
- * scancode table.
- */
-static void ir_free_table(struct ir_scancode_table *rc_tab)
-{
-	rc_tab->size = 0;
-	kfree(rc_tab->scan);
-	rc_tab->scan = NULL;
-}
-
-/**
- * ir_resize_table() - resizes a scancode table if necessary
- * @rc_tab:	the ir_scancode_table to resize
- * @gfp_flags:	gfp flags to use when allocating memory
- * @return:	zero on success or a negative error code
- *
- * This routine will shrink the ir_scancode_table if it has lots of
- * unused entries and grow it if it is full.
- */
-static int ir_resize_table(struct ir_scancode_table *rc_tab, gfp_t gfp_flags)
-{
-	unsigned int oldalloc = rc_tab->alloc;
-	unsigned int newalloc = oldalloc;
-	struct ir_scancode *oldscan = rc_tab->scan;
-	struct ir_scancode *newscan;
-
-	if (rc_tab->size == rc_tab->len) {
-		/* All entries in use -> grow keytable */
-		if (rc_tab->alloc >= IR_TAB_MAX_SIZE)
-			return -ENOMEM;
-
-		newalloc *= 2;
-		IR_dprintk(1, "Growing table to %u bytes\n", newalloc);
-	}
-
-	if ((rc_tab->len * 3 < rc_tab->size) && (oldalloc > IR_TAB_MIN_SIZE)) {
-		/* Less than 1/3 of entries in use -> shrink keytable */
-		newalloc /= 2;
-		IR_dprintk(1, "Shrinking table to %u bytes\n", newalloc);
-	}
-
-	if (newalloc == oldalloc)
-		return 0;
-
-	newscan = kmalloc(newalloc, gfp_flags);
-	if (!newscan) {
-		IR_dprintk(1, "Failed to kmalloc %u bytes\n", newalloc);
-		return -ENOMEM;
-	}
-
-	memcpy(newscan, rc_tab->scan, rc_tab->len * sizeof(struct ir_scancode));
-	rc_tab->scan = newscan;
-	rc_tab->alloc = newalloc;
-	rc_tab->size = rc_tab->alloc / sizeof(struct ir_scancode);
-	kfree(oldscan);
-	return 0;
-}
-
-/**
- * ir_update_mapping() - set a keycode in the scancode->keycode table
- * @dev:	the struct input_dev device descriptor
- * @rc_tab:	scancode table to be adjusted
- * @index:	index of the mapping that needs to be updated
- * @keycode:	the desired keycode
- * @return:	previous keycode assigned to the mapping
- *
- * This routine is used to update scancode->keycopde mapping at given
- * position.
- */
-static unsigned int ir_update_mapping(struct input_dev *dev,
-				      struct ir_scancode_table *rc_tab,
-				      unsigned int index,
-				      unsigned int new_keycode)
-{
-	int old_keycode = rc_tab->scan[index].keycode;
-	int i;
-
-	/* Did the user wish to remove the mapping? */
-	if (new_keycode == KEY_RESERVED || new_keycode == KEY_UNKNOWN) {
-		IR_dprintk(1, "#%d: Deleting scan 0x%04x\n",
-			   index, rc_tab->scan[index].scancode);
-		rc_tab->len--;
-		memmove(&rc_tab->scan[index], &rc_tab->scan[index+ 1],
-			(rc_tab->len - index) * sizeof(struct ir_scancode));
-	} else {
-		IR_dprintk(1, "#%d: %s scan 0x%04x with key 0x%04x\n",
-			   index,
-			   old_keycode == KEY_RESERVED ? "New" : "Replacing",
-			   rc_tab->scan[index].scancode, new_keycode);
-		rc_tab->scan[index].keycode = new_keycode;
-		__set_bit(new_keycode, dev->keybit);
-	}
-
-	if (old_keycode != KEY_RESERVED) {
-		/* A previous mapping was updated... */
-		__clear_bit(old_keycode, dev->keybit);
-		/* ... but another scancode might use the same keycode */
-		for (i = 0; i < rc_tab->len; i++) {
-			if (rc_tab->scan[i].keycode == old_keycode) {
-				__set_bit(old_keycode, dev->keybit);
-				break;
-			}
-		}
-
-		/* Possibly shrink the keytable, failure is not a problem */
-		ir_resize_table(rc_tab, GFP_ATOMIC);
-	}
-
-	return old_keycode;
-}
-
-/**
- * ir_locate_scancode() - set a keycode in the scancode->keycode table
- * @ir_dev:	the struct ir_input_dev device descriptor
- * @rc_tab:	scancode table to be searched
- * @scancode:	the desired scancode
- * @resize:	controls whether we allowed to resize the table to
- *		accomodate not yet present scancodes
- * @return:	index of the mapping containing scancode in question
- *		or -1U in case of failure.
- *
- * This routine is used to locate given scancode in ir_scancode_table.
- * If scancode is not yet present the routine will allocate a new slot
- * for it.
- */
-static unsigned int ir_establish_scancode(struct ir_input_dev *ir_dev,
-					  struct ir_scancode_table *rc_tab,
-					  unsigned int scancode,
-					  bool resize)
-{
-	unsigned int i;
-
-	/*
-	 * Unfortunately, some hardware-based IR decoders don't provide
-	 * all bits for the complete IR code. In general, they provide only
-	 * the command part of the IR code. Yet, as it is possible to replace
-	 * the provided IR with another one, it is needed to allow loading
-	 * IR tables from other remotes. So,
-	 */
-	if (ir_dev->props && ir_dev->props->scanmask)
-		scancode &= ir_dev->props->scanmask;
-
-	/* First check if we already have a mapping for this ir command */
-	for (i = 0; i < rc_tab->len; i++) {
-		if (rc_tab->scan[i].scancode == scancode)
-			return i;
-
-		/* Keytable is sorted from lowest to highest scancode */
-		if (rc_tab->scan[i].scancode >= scancode)
-			break;
-	}
-
-	/* No previous mapping found, we might need to grow the table */
-	if (rc_tab->size == rc_tab->len) {
-		if (!resize || ir_resize_table(rc_tab, GFP_ATOMIC))
-			return -1U;
-	}
-
-	/* i is the proper index to insert our new keycode */
-	if (i < rc_tab->len)
-		memmove(&rc_tab->scan[i + 1], &rc_tab->scan[i],
-			(rc_tab->len - i) * sizeof(struct ir_scancode));
-	rc_tab->scan[i].scancode = scancode;
-	rc_tab->scan[i].keycode = KEY_RESERVED;
-	rc_tab->len++;
-
-	return i;
-}
-
-/**
- * ir_setkeycode() - set a keycode in the scancode->keycode table
- * @dev:	the struct input_dev device descriptor
- * @scancode:	the desired scancode
- * @keycode:	result
- * @return:	-EINVAL if the keycode could not be inserted, otherwise zero.
- *
- * This routine is used to handle evdev EVIOCSKEY ioctl.
- */
-static int ir_setkeycode(struct input_dev *dev,
-			 const struct input_keymap_entry *ke,
-			 unsigned int *old_keycode)
-{
-	struct ir_input_dev *ir_dev = input_get_drvdata(dev);
-	struct ir_scancode_table *rc_tab = &ir_dev->rc_tab;
-	unsigned int index;
-	unsigned int scancode;
-	int retval;
-	unsigned long flags;
-
-	spin_lock_irqsave(&rc_tab->lock, flags);
-
-	if (ke->flags & INPUT_KEYMAP_BY_INDEX) {
-		index = ke->index;
-		if (index >= rc_tab->len) {
-			retval = -EINVAL;
-			goto out;
-		}
-	} else {
-		retval = input_scancode_to_scalar(ke, &scancode);
-		if (retval)
-			goto out;
-
-		index = ir_establish_scancode(ir_dev, rc_tab, scancode, true);
-		if (index >= rc_tab->len) {
-			retval = -ENOMEM;
-			goto out;
-		}
-	}
-
-	*old_keycode = ir_update_mapping(dev, rc_tab, index, ke->keycode);
-
-out:
-	spin_unlock_irqrestore(&rc_tab->lock, flags);
-	return retval;
-}
-
-/**
- * ir_setkeytable() - sets several entries in the scancode->keycode table
- * @dev:	the struct input_dev device descriptor
- * @to:		the struct ir_scancode_table to copy entries to
- * @from:	the struct ir_scancode_table to copy entries from
- * @return:	-ENOMEM if all keycodes could not be inserted, otherwise zero.
- *
- * This routine is used to handle table initialization.
- */
-static int ir_setkeytable(struct ir_input_dev *ir_dev,
-			  const struct ir_scancode_table *from)
-{
-	struct ir_scancode_table *rc_tab = &ir_dev->rc_tab;
-	unsigned int i, index;
-	int rc;
-
-	rc = ir_create_table(&ir_dev->rc_tab,
-			     from->name, from->ir_type, from->size);
-	if (rc)
-		return rc;
-
-	IR_dprintk(1, "Allocated space for %u keycode entries (%u bytes)\n",
-		   rc_tab->size, rc_tab->alloc);
-
-	for (i = 0; i < from->size; i++) {
-		index = ir_establish_scancode(ir_dev, rc_tab,
-					      from->scan[i].scancode, false);
-		if (index >= rc_tab->len) {
-			rc = -ENOMEM;
-			break;
-		}
-
-		ir_update_mapping(ir_dev->input_dev, rc_tab, index,
-				  from->scan[i].keycode);
-	}
-
-	if (rc)
-		ir_free_table(rc_tab);
-
-	return rc;
-}
-
-/**
- * ir_lookup_by_scancode() - locate mapping by scancode
- * @rc_tab:	the &struct ir_scancode_table to search
- * @scancode:	scancode to look for in the table
- * @return:	index in the table, -1U if not found
- *
- * This routine performs binary search in RC keykeymap table for
- * given scancode.
- */
-static unsigned int ir_lookup_by_scancode(const struct ir_scancode_table *rc_tab,
-					  unsigned int scancode)
-{
-	int start = 0;
-	int end = rc_tab->len - 1;
-	int mid;
-
-	while (start <= end) {
-		mid = (start + end) / 2;
-		if (rc_tab->scan[mid].scancode < scancode)
-			start = mid + 1;
-		else if (rc_tab->scan[mid].scancode > scancode)
-			end = mid - 1;
-		else
-			return mid;
-	}
-
-	return -1U;
-}
-
-/**
- * ir_getkeycode() - get a keycode from the scancode->keycode table
- * @dev:	the struct input_dev device descriptor
- * @scancode:	the desired scancode
- * @keycode:	used to return the keycode, if found, or KEY_RESERVED
- * @return:	always returns zero.
- *
- * This routine is used to handle evdev EVIOCGKEY ioctl.
- */
-static int ir_getkeycode(struct input_dev *dev,
-			 struct input_keymap_entry *ke)
-{
-	struct ir_input_dev *ir_dev = input_get_drvdata(dev);
-	struct ir_scancode_table *rc_tab = &ir_dev->rc_tab;
-	struct ir_scancode *entry;
-	unsigned long flags;
-	unsigned int index;
-	unsigned int scancode;
-	int retval;
-
-	spin_lock_irqsave(&rc_tab->lock, flags);
-
-	if (ke->flags & INPUT_KEYMAP_BY_INDEX) {
-		index = ke->index;
-	} else {
-		retval = input_scancode_to_scalar(ke, &scancode);
-		if (retval)
-			goto out;
-
-		index = ir_lookup_by_scancode(rc_tab, scancode);
-	}
-
-	if (index >= rc_tab->len) {
-		if (!(ke->flags & INPUT_KEYMAP_BY_INDEX))
-			IR_dprintk(1, "unknown key for scancode 0x%04x\n",
-				   scancode);
-		retval = -EINVAL;
-		goto out;
-	}
-
-	entry = &rc_tab->scan[index];
-
-	ke->index = index;
-	ke->keycode = entry->keycode;
-	ke->len = sizeof(entry->scancode);
-	memcpy(ke->scancode, &entry->scancode, sizeof(entry->scancode));
-
-	retval = 0;
-
-out:
-	spin_unlock_irqrestore(&rc_tab->lock, flags);
-	return retval;
-}
-
-/**
- * ir_g_keycode_from_table() - gets the keycode that corresponds to a scancode
- * @input_dev:	the struct input_dev descriptor of the device
- * @scancode:	the scancode that we're seeking
- *
- * This routine is used by the input routines when a key is pressed at the
- * IR. The scancode is received and needs to be converted into a keycode.
- * If the key is not found, it returns KEY_RESERVED. Otherwise, returns the
- * corresponding keycode from the table.
- */
-u32 ir_g_keycode_from_table(struct input_dev *dev, u32 scancode)
-{
-	struct ir_input_dev *ir_dev = input_get_drvdata(dev);
-	struct ir_scancode_table *rc_tab = &ir_dev->rc_tab;
-	unsigned int keycode;
-	unsigned int index;
-	unsigned long flags;
-
-	spin_lock_irqsave(&rc_tab->lock, flags);
-
-	index = ir_lookup_by_scancode(rc_tab, scancode);
-	keycode = index < rc_tab->len ?
-			rc_tab->scan[index].keycode : KEY_RESERVED;
-
-	spin_unlock_irqrestore(&rc_tab->lock, flags);
-
-	if (keycode != KEY_RESERVED)
-		IR_dprintk(1, "%s: scancode 0x%04x keycode 0x%02x\n",
-			   dev->name, scancode, keycode);
-
-	return keycode;
-}
-EXPORT_SYMBOL_GPL(ir_g_keycode_from_table);
-
-/**
- * ir_keyup() - generates input event to cleanup a key press
- * @ir:         the struct ir_input_dev descriptor of the device
- *
- * This routine is used to signal that a key has been released on the
- * remote control. It reports a keyup input event via input_report_key().
- */
-void ir_keyup(struct ir_input_dev *ir)
-{
-	if (!ir->keypressed)
-		return;
-
-	IR_dprintk(1, "keyup key 0x%04x\n", ir->last_keycode);
-	input_report_key(ir->input_dev, ir->last_keycode, 0);
-	input_sync(ir->input_dev);
-	ir->keypressed = false;
-}
-EXPORT_SYMBOL_GPL(ir_keyup);
-
-/**
- * ir_timer_keyup() - generates a keyup event after a timeout
- * @cookie:     a pointer to struct ir_input_dev passed to setup_timer()
- *
- * This routine will generate a keyup event some time after a keydown event
- * is generated when no further activity has been detected.
- */
-static void ir_timer_keyup(unsigned long cookie)
-{
-	struct ir_input_dev *ir = (struct ir_input_dev *)cookie;
-	unsigned long flags;
-
-	/*
-	 * ir->keyup_jiffies is used to prevent a race condition if a
-	 * hardware interrupt occurs at this point and the keyup timer
-	 * event is moved further into the future as a result.
-	 *
-	 * The timer will then be reactivated and this function called
-	 * again in the future. We need to exit gracefully in that case
-	 * to allow the input subsystem to do its auto-repeat magic or
-	 * a keyup event might follow immediately after the keydown.
-	 */
-	spin_lock_irqsave(&ir->keylock, flags);
-	if (time_is_before_eq_jiffies(ir->keyup_jiffies))
-		ir_keyup(ir);
-	spin_unlock_irqrestore(&ir->keylock, flags);
-}
-
-/**
- * ir_repeat() - notifies the IR core that a key is still pressed
- * @dev:        the struct input_dev descriptor of the device
- *
- * This routine is used by IR decoders when a repeat message which does
- * not include the necessary bits to reproduce the scancode has been
- * received.
- */
-void ir_repeat(struct input_dev *dev)
-{
-	unsigned long flags;
-	struct ir_input_dev *ir = input_get_drvdata(dev);
-
-	spin_lock_irqsave(&ir->keylock, flags);
-
-	input_event(dev, EV_MSC, MSC_SCAN, ir->last_scancode);
-
-	if (!ir->keypressed)
-		goto out;
-
-	ir->keyup_jiffies = jiffies + msecs_to_jiffies(IR_KEYPRESS_TIMEOUT);
-	mod_timer(&ir->timer_keyup, ir->keyup_jiffies);
-
-out:
-	spin_unlock_irqrestore(&ir->keylock, flags);
-}
-EXPORT_SYMBOL_GPL(ir_repeat);
-
-/**
- * ir_keydown() - generates input event for a key press
- * @dev:        the struct input_dev descriptor of the device
- * @scancode:   the scancode that we're seeking
- * @toggle:     the toggle value (protocol dependent, if the protocol doesn't
- *              support toggle values, this should be set to zero)
- *
- * This routine is used by the input routines when a key is pressed at the
- * IR. It gets the keycode for a scancode and reports an input event via
- * input_report_key().
- */
-void ir_keydown(struct input_dev *dev, int scancode, u8 toggle)
-{
-	unsigned long flags;
-	struct ir_input_dev *ir = input_get_drvdata(dev);
-
-	u32 keycode = ir_g_keycode_from_table(dev, scancode);
-
-	spin_lock_irqsave(&ir->keylock, flags);
-
-	input_event(dev, EV_MSC, MSC_SCAN, scancode);
-
-	/* Repeat event? */
-	if (ir->keypressed &&
-	    ir->last_scancode == scancode &&
-	    ir->last_toggle == toggle)
-		goto set_timer;
-
-	/* Release old keypress */
-	ir_keyup(ir);
-
-	ir->last_scancode = scancode;
-	ir->last_toggle = toggle;
-	ir->last_keycode = keycode;
-
-
-	if (keycode == KEY_RESERVED)
-		goto out;
-
-
-	/* Register a keypress */
-	ir->keypressed = true;
-	IR_dprintk(1, "%s: key down event, key 0x%04x, scancode 0x%04x\n",
-		   dev->name, keycode, scancode);
-	input_report_key(dev, ir->last_keycode, 1);
-	input_sync(dev);
-
-set_timer:
-	ir->keyup_jiffies = jiffies + msecs_to_jiffies(IR_KEYPRESS_TIMEOUT);
-	mod_timer(&ir->timer_keyup, ir->keyup_jiffies);
-out:
-	spin_unlock_irqrestore(&ir->keylock, flags);
-}
-EXPORT_SYMBOL_GPL(ir_keydown);
-
-static int ir_open(struct input_dev *input_dev)
-{
-	struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
-
-	return ir_dev->props->open(ir_dev->props->priv);
-}
-
-static void ir_close(struct input_dev *input_dev)
-{
-	struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
-
-	ir_dev->props->close(ir_dev->props->priv);
-}
-
-/**
- * __ir_input_register() - sets the IR keycode table and add the handlers
- *			    for keymap table get/set
- * @input_dev:	the struct input_dev descriptor of the device
- * @rc_tab:	the struct ir_scancode_table table of scancode/keymap
- *
- * This routine is used to initialize the input infrastructure
- * to work with an IR.
- * It will register the input/evdev interface for the device and
- * register the syfs code for IR class
- */
-int __ir_input_register(struct input_dev *input_dev,
-		      const struct ir_scancode_table *rc_tab,
-		      struct ir_dev_props *props,
-		      const char *driver_name)
-{
-	struct ir_input_dev *ir_dev;
-	int rc;
-
-	if (rc_tab->scan == NULL || !rc_tab->size)
-		return -EINVAL;
-
-	ir_dev = kzalloc(sizeof(*ir_dev), GFP_KERNEL);
-	if (!ir_dev)
-		return -ENOMEM;
-
-	ir_dev->driver_name = kasprintf(GFP_KERNEL, "%s", driver_name);
-	if (!ir_dev->driver_name) {
-		rc = -ENOMEM;
-		goto out_dev;
-	}
-
-	input_dev->getkeycode_new = ir_getkeycode;
-	input_dev->setkeycode_new = ir_setkeycode;
-	input_set_drvdata(input_dev, ir_dev);
-	ir_dev->input_dev = input_dev;
-
-	spin_lock_init(&ir_dev->rc_tab.lock);
-	spin_lock_init(&ir_dev->keylock);
-	setup_timer(&ir_dev->timer_keyup, ir_timer_keyup, (unsigned long)ir_dev);
-
-	if (props) {
-		ir_dev->props = props;
-		if (props->open)
-			input_dev->open = ir_open;
-		if (props->close)
-			input_dev->close = ir_close;
-	}
-
-	set_bit(EV_KEY, input_dev->evbit);
-	set_bit(EV_REP, input_dev->evbit);
-	set_bit(EV_MSC, input_dev->evbit);
-	set_bit(MSC_SCAN, input_dev->mscbit);
-
-	rc = ir_setkeytable(ir_dev, rc_tab);
-	if (rc)
-		goto out_name;
-
-	rc = ir_register_class(input_dev);
-	if (rc < 0)
-		goto out_table;
-
-	if (ir_dev->props)
-		if (ir_dev->props->driver_type == RC_DRIVER_IR_RAW) {
-			rc = ir_raw_event_register(input_dev);
-			if (rc < 0)
-				goto out_event;
-		}
-
-	rc = ir_register_input(input_dev);
-	if (rc < 0)
-		goto out_event;
-
-	IR_dprintk(1, "Registered input device on %s for %s remote%s.\n",
-		   driver_name, rc_tab->name,
-		   (ir_dev->props && ir_dev->props->driver_type == RC_DRIVER_IR_RAW) ?
-			" in raw mode" : "");
-
-	/*
-	 * Default delay of 250ms is too short for some protocols, expecially
-	 * since the timeout is currently set to 250ms. Increase it to 500ms,
-	 * to avoid wrong repetition of the keycodes.
-	 */
-	input_dev->rep[REP_DELAY] = 500;
-
-	return 0;
-
-out_event:
-	ir_unregister_class(input_dev);
-out_table:
-	ir_free_table(&ir_dev->rc_tab);
-out_name:
-	kfree(ir_dev->driver_name);
-out_dev:
-	kfree(ir_dev);
-	return rc;
-}
-EXPORT_SYMBOL_GPL(__ir_input_register);
-
-/**
- * ir_input_unregister() - unregisters IR and frees resources
- * @input_dev:	the struct input_dev descriptor of the device
-
- * This routine is used to free memory and de-register interfaces.
- */
-void ir_input_unregister(struct input_dev *input_dev)
-{
-	struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
-
-	if (!ir_dev)
-		return;
-
-	IR_dprintk(1, "Freed keycode table\n");
-
-	del_timer_sync(&ir_dev->timer_keyup);
-	if (ir_dev->props)
-		if (ir_dev->props->driver_type == RC_DRIVER_IR_RAW)
-			ir_raw_event_unregister(input_dev);
-
-	ir_free_table(&ir_dev->rc_tab);
-
-	ir_unregister_class(input_dev);
-
-	kfree(ir_dev->driver_name);
-	kfree(ir_dev);
-}
-EXPORT_SYMBOL_GPL(ir_input_unregister);
-
-int ir_core_debug;    /* ir_debug level (0,1,2) */
-EXPORT_SYMBOL_GPL(ir_core_debug);
-module_param_named(debug, ir_core_debug, int, 0644);
-
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
-MODULE_LICENSE("GPL");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/ir-lirc-codec.c linux-libre-2.6.38-gnu1/drivers/media/IR/ir-lirc-codec.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/ir-lirc-codec.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/ir-lirc-codec.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,410 +0,0 @@
-/* ir-lirc-codec.c - ir-core to classic lirc interface bridge
- *
- * Copyright (C) 2010 by Jarod Wilson <jarod@redhat.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.
- */
-
-#include <linux/sched.h>
-#include <linux/wait.h>
-#include <media/lirc.h>
-#include <media/lirc_dev.h>
-#include <media/ir-core.h>
-#include "ir-core-priv.h"
-
-#define LIRCBUF_SIZE 256
-
-/**
- * ir_lirc_decode() - Send raw IR data to lirc_dev to be relayed to the
- *		      lircd userspace daemon for decoding.
- * @input_dev:	the struct input_dev descriptor of the device
- * @duration:	the struct ir_raw_event descriptor of the pulse/space
- *
- * This function returns -EINVAL if the lirc interfaces aren't wired up.
- */
-static int ir_lirc_decode(struct input_dev *input_dev, struct ir_raw_event ev)
-{
-	struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
-	struct lirc_codec *lirc = &ir_dev->raw->lirc;
-	int sample;
-
-	if (!(ir_dev->raw->enabled_protocols & IR_TYPE_LIRC))
-		return 0;
-
-	if (!ir_dev->raw->lirc.drv || !ir_dev->raw->lirc.drv->rbuf)
-		return -EINVAL;
-
-	/* Packet start */
-	if (ev.reset)
-		return 0;
-
-	/* Carrier reports */
-	if (ev.carrier_report) {
-		sample = LIRC_FREQUENCY(ev.carrier);
-
-	/* Packet end */
-	} else if (ev.timeout) {
-
-		if (lirc->gap)
-			return 0;
-
-		lirc->gap_start = ktime_get();
-		lirc->gap = true;
-		lirc->gap_duration = ev.duration;
-
-		if (!lirc->send_timeout_reports)
-			return 0;
-
-		sample = LIRC_TIMEOUT(ev.duration / 1000);
-
-	/* Normal sample */
-	} else {
-
-		if (lirc->gap) {
-			int gap_sample;
-
-			lirc->gap_duration += ktime_to_ns(ktime_sub(ktime_get(),
-				lirc->gap_start));
-
-			/* Convert to ms and cap by LIRC_VALUE_MASK */
-			do_div(lirc->gap_duration, 1000);
-			lirc->gap_duration = min(lirc->gap_duration,
-							(u64)LIRC_VALUE_MASK);
-
-			gap_sample = LIRC_SPACE(lirc->gap_duration);
-			lirc_buffer_write(ir_dev->raw->lirc.drv->rbuf,
-						(unsigned char *) &gap_sample);
-			lirc->gap = false;
-		}
-
-		sample = ev.pulse ? LIRC_PULSE(ev.duration / 1000) :
-					LIRC_SPACE(ev.duration / 1000);
-	}
-
-	lirc_buffer_write(ir_dev->raw->lirc.drv->rbuf,
-			  (unsigned char *) &sample);
-	wake_up(&ir_dev->raw->lirc.drv->rbuf->wait_poll);
-
-	return 0;
-}
-
-static ssize_t ir_lirc_transmit_ir(struct file *file, const char *buf,
-				   size_t n, loff_t *ppos)
-{
-	struct lirc_codec *lirc;
-	struct ir_input_dev *ir_dev;
-	int *txbuf; /* buffer with values to transmit */
-	int ret = 0, count;
-
-	lirc = lirc_get_pdata(file);
-	if (!lirc)
-		return -EFAULT;
-
-	if (n % sizeof(int))
-		return -EINVAL;
-
-	count = n / sizeof(int);
-	if (count > LIRCBUF_SIZE || count % 2 == 0)
-		return -EINVAL;
-
-	txbuf = memdup_user(buf, n);
-	if (IS_ERR(txbuf))
-		return PTR_ERR(txbuf);
-
-	ir_dev = lirc->ir_dev;
-	if (!ir_dev) {
-		ret = -EFAULT;
-		goto out;
-	}
-
-	if (ir_dev->props && ir_dev->props->tx_ir)
-		ret = ir_dev->props->tx_ir(ir_dev->props->priv, txbuf, (u32)n);
-
-out:
-	kfree(txbuf);
-	return ret;
-}
-
-static long ir_lirc_ioctl(struct file *filep, unsigned int cmd,
-			unsigned long __user arg)
-{
-	struct lirc_codec *lirc;
-	struct ir_input_dev *ir_dev;
-	int ret = 0;
-	void *drv_data;
-	__u32 val = 0, tmp;
-
-	lirc = lirc_get_pdata(filep);
-	if (!lirc)
-		return -EFAULT;
-
-	ir_dev = lirc->ir_dev;
-	if (!ir_dev || !ir_dev->props || !ir_dev->props->priv)
-		return -EFAULT;
-
-	drv_data = ir_dev->props->priv;
-
-	if (_IOC_DIR(cmd) & _IOC_WRITE) {
-		ret = get_user(val, (__u32 *)arg);
-		if (ret)
-			return ret;
-	}
-
-	switch (cmd) {
-
-	/* legacy support */
-	case LIRC_GET_SEND_MODE:
-		val = LIRC_CAN_SEND_PULSE & LIRC_CAN_SEND_MASK;
-		break;
-
-	case LIRC_SET_SEND_MODE:
-		if (val != (LIRC_MODE_PULSE & LIRC_CAN_SEND_MASK))
-			return -EINVAL;
-		return 0;
-
-	/* TX settings */
-	case LIRC_SET_TRANSMITTER_MASK:
-		if (!ir_dev->props->s_tx_mask)
-			return -EINVAL;
-
-		return ir_dev->props->s_tx_mask(drv_data, val);
-
-	case LIRC_SET_SEND_CARRIER:
-		if (!ir_dev->props->s_tx_carrier)
-			return -EINVAL;
-
-		return ir_dev->props->s_tx_carrier(drv_data, val);
-
-	case LIRC_SET_SEND_DUTY_CYCLE:
-		if (!ir_dev->props->s_tx_duty_cycle)
-			return -ENOSYS;
-
-		if (val <= 0 || val >= 100)
-			return -EINVAL;
-
-		return ir_dev->props->s_tx_duty_cycle(drv_data, val);
-
-	/* RX settings */
-	case LIRC_SET_REC_CARRIER:
-		if (!ir_dev->props->s_rx_carrier_range)
-			return -ENOSYS;
-
-		if (val <= 0)
-			return -EINVAL;
-
-		return ir_dev->props->s_rx_carrier_range(drv_data,
-			ir_dev->raw->lirc.carrier_low, val);
-
-	case LIRC_SET_REC_CARRIER_RANGE:
-		if (val <= 0)
-			return -EINVAL;
-
-		ir_dev->raw->lirc.carrier_low = val;
-		return 0;
-
-	case LIRC_GET_REC_RESOLUTION:
-		val = ir_dev->props->rx_resolution;
-		break;
-
-	case LIRC_SET_WIDEBAND_RECEIVER:
-		if (!ir_dev->props->s_learning_mode)
-			return -ENOSYS;
-
-		return ir_dev->props->s_learning_mode(drv_data, !!val);
-
-	case LIRC_SET_MEASURE_CARRIER_MODE:
-		if (!ir_dev->props->s_carrier_report)
-			return -ENOSYS;
-
-		return ir_dev->props->s_carrier_report(drv_data, !!val);
-
-	/* Generic timeout support */
-	case LIRC_GET_MIN_TIMEOUT:
-		if (!ir_dev->props->max_timeout)
-			return -ENOSYS;
-		val = ir_dev->props->min_timeout / 1000;
-		break;
-
-	case LIRC_GET_MAX_TIMEOUT:
-		if (!ir_dev->props->max_timeout)
-			return -ENOSYS;
-		val = ir_dev->props->max_timeout / 1000;
-		break;
-
-	case LIRC_SET_REC_TIMEOUT:
-		if (!ir_dev->props->max_timeout)
-			return -ENOSYS;
-
-		tmp = val * 1000;
-
-		if (tmp < ir_dev->props->min_timeout ||
-			tmp > ir_dev->props->max_timeout)
-				return -EINVAL;
-
-		ir_dev->props->timeout = tmp;
-		break;
-
-	case LIRC_SET_REC_TIMEOUT_REPORTS:
-		lirc->send_timeout_reports = !!val;
-		break;
-
-	default:
-		return lirc_dev_fop_ioctl(filep, cmd, arg);
-	}
-
-	if (_IOC_DIR(cmd) & _IOC_READ)
-		ret = put_user(val, (__u32 *)arg);
-
-	return ret;
-}
-
-static int ir_lirc_open(void *data)
-{
-	return 0;
-}
-
-static void ir_lirc_close(void *data)
-{
-	return;
-}
-
-static struct file_operations lirc_fops = {
-	.owner		= THIS_MODULE,
-	.write		= ir_lirc_transmit_ir,
-	.unlocked_ioctl	= ir_lirc_ioctl,
-#ifdef CONFIG_COMPAT
-	.compat_ioctl	= ir_lirc_ioctl,
-#endif
-	.read		= lirc_dev_fop_read,
-	.poll		= lirc_dev_fop_poll,
-	.open		= lirc_dev_fop_open,
-	.release	= lirc_dev_fop_close,
-	.llseek		= no_llseek,
-};
-
-static int ir_lirc_register(struct input_dev *input_dev)
-{
-	struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
-	struct lirc_driver *drv;
-	struct lirc_buffer *rbuf;
-	int rc = -ENOMEM;
-	unsigned long features;
-
-	drv = kzalloc(sizeof(struct lirc_driver), GFP_KERNEL);
-	if (!drv)
-		return rc;
-
-	rbuf = kzalloc(sizeof(struct lirc_buffer), GFP_KERNEL);
-	if (!rbuf)
-		goto rbuf_alloc_failed;
-
-	rc = lirc_buffer_init(rbuf, sizeof(int), LIRCBUF_SIZE);
-	if (rc)
-		goto rbuf_init_failed;
-
-	features = LIRC_CAN_REC_MODE2;
-	if (ir_dev->props->tx_ir) {
-
-		features |= LIRC_CAN_SEND_PULSE;
-		if (ir_dev->props->s_tx_mask)
-			features |= LIRC_CAN_SET_TRANSMITTER_MASK;
-		if (ir_dev->props->s_tx_carrier)
-			features |= LIRC_CAN_SET_SEND_CARRIER;
-
-		if (ir_dev->props->s_tx_duty_cycle)
-			features |= LIRC_CAN_SET_SEND_DUTY_CYCLE;
-	}
-
-	if (ir_dev->props->s_rx_carrier_range)
-		features |= LIRC_CAN_SET_REC_CARRIER |
-			LIRC_CAN_SET_REC_CARRIER_RANGE;
-
-	if (ir_dev->props->s_learning_mode)
-		features |= LIRC_CAN_USE_WIDEBAND_RECEIVER;
-
-	if (ir_dev->props->s_carrier_report)
-		features |= LIRC_CAN_MEASURE_CARRIER;
-
-
-	if (ir_dev->props->max_timeout)
-		features |= LIRC_CAN_SET_REC_TIMEOUT;
-
-
-	snprintf(drv->name, sizeof(drv->name), "ir-lirc-codec (%s)",
-		 ir_dev->driver_name);
-	drv->minor = -1;
-	drv->features = features;
-	drv->data = &ir_dev->raw->lirc;
-	drv->rbuf = rbuf;
-	drv->set_use_inc = &ir_lirc_open;
-	drv->set_use_dec = &ir_lirc_close;
-	drv->code_length = sizeof(struct ir_raw_event) * 8;
-	drv->fops = &lirc_fops;
-	drv->dev = &ir_dev->dev;
-	drv->owner = THIS_MODULE;
-
-	drv->minor = lirc_register_driver(drv);
-	if (drv->minor < 0) {
-		rc = -ENODEV;
-		goto lirc_register_failed;
-	}
-
-	ir_dev->raw->lirc.drv = drv;
-	ir_dev->raw->lirc.ir_dev = ir_dev;
-	return 0;
-
-lirc_register_failed:
-rbuf_init_failed:
-	kfree(rbuf);
-rbuf_alloc_failed:
-	kfree(drv);
-
-	return rc;
-}
-
-static int ir_lirc_unregister(struct input_dev *input_dev)
-{
-	struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
-	struct lirc_codec *lirc = &ir_dev->raw->lirc;
-
-	lirc_unregister_driver(lirc->drv->minor);
-	lirc_buffer_free(lirc->drv->rbuf);
-	kfree(lirc->drv);
-
-	return 0;
-}
-
-static struct ir_raw_handler lirc_handler = {
-	.protocols	= IR_TYPE_LIRC,
-	.decode		= ir_lirc_decode,
-	.raw_register	= ir_lirc_register,
-	.raw_unregister	= ir_lirc_unregister,
-};
-
-static int __init ir_lirc_codec_init(void)
-{
-	ir_raw_handler_register(&lirc_handler);
-
-	printk(KERN_INFO "IR LIRC bridge handler initialized\n");
-	return 0;
-}
-
-static void __exit ir_lirc_codec_exit(void)
-{
-	ir_raw_handler_unregister(&lirc_handler);
-}
-
-module_init(ir_lirc_codec_init);
-module_exit(ir_lirc_codec_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Jarod Wilson <jarod@redhat.com>");
-MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)");
-MODULE_DESCRIPTION("LIRC IR handler bridge");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/ir-nec-decoder.c linux-libre-2.6.38-gnu1/drivers/media/IR/ir-nec-decoder.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/ir-nec-decoder.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/ir-nec-decoder.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,217 +0,0 @@
-/* ir-nec-decoder.c - handle NEC IR Pulse/Space protocol
- *
- * Copyright (C) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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.
- */
-
-#include <linux/bitrev.h>
-#include "ir-core-priv.h"
-
-#define NEC_NBITS		32
-#define NEC_UNIT		562500  /* ns */
-#define NEC_HEADER_PULSE	(16 * NEC_UNIT)
-#define NECX_HEADER_PULSE	(8  * NEC_UNIT) /* Less common NEC variant */
-#define NEC_HEADER_SPACE	(8  * NEC_UNIT)
-#define NEC_REPEAT_SPACE	(4  * NEC_UNIT)
-#define NEC_BIT_PULSE		(1  * NEC_UNIT)
-#define NEC_BIT_0_SPACE		(1  * NEC_UNIT)
-#define NEC_BIT_1_SPACE		(3  * NEC_UNIT)
-#define	NEC_TRAILER_PULSE	(1  * NEC_UNIT)
-#define	NEC_TRAILER_SPACE	(10 * NEC_UNIT) /* even longer in reality */
-#define NECX_REPEAT_BITS	1
-
-enum nec_state {
-	STATE_INACTIVE,
-	STATE_HEADER_SPACE,
-	STATE_BIT_PULSE,
-	STATE_BIT_SPACE,
-	STATE_TRAILER_PULSE,
-	STATE_TRAILER_SPACE,
-};
-
-/**
- * ir_nec_decode() - Decode one NEC pulse or space
- * @input_dev:	the struct input_dev descriptor of the device
- * @duration:	the struct ir_raw_event descriptor of the pulse/space
- *
- * This function returns -EINVAL if the pulse violates the state machine
- */
-static int ir_nec_decode(struct input_dev *input_dev, struct ir_raw_event ev)
-{
-	struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
-	struct nec_dec *data = &ir_dev->raw->nec;
-	u32 scancode;
-	u8 address, not_address, command, not_command;
-
-	if (!(ir_dev->raw->enabled_protocols & IR_TYPE_NEC))
-		return 0;
-
-	if (!is_timing_event(ev)) {
-		if (ev.reset)
-			data->state = STATE_INACTIVE;
-		return 0;
-	}
-
-	IR_dprintk(2, "NEC decode started at state %d (%uus %s)\n",
-		   data->state, TO_US(ev.duration), TO_STR(ev.pulse));
-
-	switch (data->state) {
-
-	case STATE_INACTIVE:
-		if (!ev.pulse)
-			break;
-
-		if (eq_margin(ev.duration, NEC_HEADER_PULSE, NEC_UNIT / 2)) {
-			data->is_nec_x = false;
-			data->necx_repeat = false;
-		} else if (eq_margin(ev.duration, NECX_HEADER_PULSE, NEC_UNIT / 2))
-			data->is_nec_x = true;
-		else
-			break;
-
-		data->count = 0;
-		data->state = STATE_HEADER_SPACE;
-		return 0;
-
-	case STATE_HEADER_SPACE:
-		if (ev.pulse)
-			break;
-
-		if (eq_margin(ev.duration, NEC_HEADER_SPACE, NEC_UNIT / 2)) {
-			data->state = STATE_BIT_PULSE;
-			return 0;
-		} else if (eq_margin(ev.duration, NEC_REPEAT_SPACE, NEC_UNIT / 2)) {
-			ir_repeat(input_dev);
-			IR_dprintk(1, "Repeat last key\n");
-			data->state = STATE_TRAILER_PULSE;
-			return 0;
-		}
-
-		break;
-
-	case STATE_BIT_PULSE:
-		if (!ev.pulse)
-			break;
-
-		if (!eq_margin(ev.duration, NEC_BIT_PULSE, NEC_UNIT / 2))
-			break;
-
-		data->state = STATE_BIT_SPACE;
-		return 0;
-
-	case STATE_BIT_SPACE:
-		if (ev.pulse)
-			break;
-
-		if (data->necx_repeat && data->count == NECX_REPEAT_BITS &&
-			geq_margin(ev.duration,
-			NEC_TRAILER_SPACE, NEC_UNIT / 2)) {
-				IR_dprintk(1, "Repeat last key\n");
-				ir_repeat(input_dev);
-				data->state = STATE_INACTIVE;
-				return 0;
-
-		} else if (data->count > NECX_REPEAT_BITS)
-			data->necx_repeat = false;
-
-		data->bits <<= 1;
-		if (eq_margin(ev.duration, NEC_BIT_1_SPACE, NEC_UNIT / 2))
-			data->bits |= 1;
-		else if (!eq_margin(ev.duration, NEC_BIT_0_SPACE, NEC_UNIT / 2))
-			break;
-		data->count++;
-
-		if (data->count == NEC_NBITS)
-			data->state = STATE_TRAILER_PULSE;
-		else
-			data->state = STATE_BIT_PULSE;
-
-		return 0;
-
-	case STATE_TRAILER_PULSE:
-		if (!ev.pulse)
-			break;
-
-		if (!eq_margin(ev.duration, NEC_TRAILER_PULSE, NEC_UNIT / 2))
-			break;
-
-		data->state = STATE_TRAILER_SPACE;
-		return 0;
-
-	case STATE_TRAILER_SPACE:
-		if (ev.pulse)
-			break;
-
-		if (!geq_margin(ev.duration, NEC_TRAILER_SPACE, NEC_UNIT / 2))
-			break;
-
-		address     = bitrev8((data->bits >> 24) & 0xff);
-		not_address = bitrev8((data->bits >> 16) & 0xff);
-		command	    = bitrev8((data->bits >>  8) & 0xff);
-		not_command = bitrev8((data->bits >>  0) & 0xff);
-
-		if ((command ^ not_command) != 0xff) {
-			IR_dprintk(1, "NEC checksum error: received 0x%08x\n",
-				   data->bits);
-			break;
-		}
-
-		if ((address ^ not_address) != 0xff) {
-			/* Extended NEC */
-			scancode = address     << 16 |
-				   not_address <<  8 |
-				   command;
-			IR_dprintk(1, "NEC (Ext) scancode 0x%06x\n", scancode);
-		} else {
-			/* Normal NEC */
-			scancode = address << 8 | command;
-			IR_dprintk(1, "NEC scancode 0x%04x\n", scancode);
-		}
-
-		if (data->is_nec_x)
-			data->necx_repeat = true;
-
-		ir_keydown(input_dev, scancode, 0);
-		data->state = STATE_INACTIVE;
-		return 0;
-	}
-
-	IR_dprintk(1, "NEC decode failed at state %d (%uus %s)\n",
-		   data->state, TO_US(ev.duration), TO_STR(ev.pulse));
-	data->state = STATE_INACTIVE;
-	return -EINVAL;
-}
-
-static struct ir_raw_handler nec_handler = {
-	.protocols	= IR_TYPE_NEC,
-	.decode		= ir_nec_decode,
-};
-
-static int __init ir_nec_decode_init(void)
-{
-	ir_raw_handler_register(&nec_handler);
-
-	printk(KERN_INFO "IR NEC protocol handler initialized\n");
-	return 0;
-}
-
-static void __exit ir_nec_decode_exit(void)
-{
-	ir_raw_handler_unregister(&nec_handler);
-}
-
-module_init(ir_nec_decode_init);
-module_exit(ir_nec_decode_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
-MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)");
-MODULE_DESCRIPTION("NEC IR protocol decoder");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/ir-raw-event.c linux-libre-2.6.38-gnu1/drivers/media/IR/ir-raw-event.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/ir-raw-event.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/ir-raw-event.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,382 +0,0 @@
-/* ir-raw-event.c - handle IR Pulse/Space event
- *
- * Copyright (C) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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.
- */
-
-#include <linux/kthread.h>
-#include <linux/mutex.h>
-#include <linux/sched.h>
-#include <linux/freezer.h>
-#include "ir-core-priv.h"
-
-/* Define the max number of pulse/space transitions to buffer */
-#define MAX_IR_EVENT_SIZE      512
-
-/* Used to keep track of IR raw clients, protected by ir_raw_handler_lock */
-static LIST_HEAD(ir_raw_client_list);
-
-/* Used to handle IR raw handler extensions */
-static DEFINE_MUTEX(ir_raw_handler_lock);
-static LIST_HEAD(ir_raw_handler_list);
-static u64 available_protocols;
-
-#ifdef MODULE
-/* Used to load the decoders */
-static struct work_struct wq_load;
-#endif
-
-static int ir_raw_event_thread(void *data)
-{
-	struct ir_raw_event ev;
-	struct ir_raw_handler *handler;
-	struct ir_raw_event_ctrl *raw = (struct ir_raw_event_ctrl *)data;
-	int retval;
-
-	while (!kthread_should_stop()) {
-
-		spin_lock_irq(&raw->lock);
-		retval = kfifo_out(&raw->kfifo, &ev, sizeof(ev));
-
-		if (!retval) {
-			set_current_state(TASK_INTERRUPTIBLE);
-
-			if (kthread_should_stop())
-				set_current_state(TASK_RUNNING);
-
-			spin_unlock_irq(&raw->lock);
-			schedule();
-			continue;
-		}
-
-		spin_unlock_irq(&raw->lock);
-
-
-		BUG_ON(retval != sizeof(ev));
-
-		mutex_lock(&ir_raw_handler_lock);
-		list_for_each_entry(handler, &ir_raw_handler_list, list)
-			handler->decode(raw->input_dev, ev);
-		raw->prev_ev = ev;
-		mutex_unlock(&ir_raw_handler_lock);
-	}
-
-	return 0;
-}
-
-/**
- * ir_raw_event_store() - pass a pulse/space duration to the raw ir decoders
- * @input_dev:	the struct input_dev device descriptor
- * @ev:		the struct ir_raw_event descriptor of the pulse/space
- *
- * This routine (which may be called from an interrupt context) stores a
- * pulse/space duration for the raw ir decoding state machines. Pulses are
- * signalled as positive values and spaces as negative values. A zero value
- * will reset the decoding state machines.
- */
-int ir_raw_event_store(struct input_dev *input_dev, struct ir_raw_event *ev)
-{
-	struct ir_input_dev *ir = input_get_drvdata(input_dev);
-
-	if (!ir->raw)
-		return -EINVAL;
-
-	IR_dprintk(2, "sample: (%05dus %s)\n",
-		TO_US(ev->duration), TO_STR(ev->pulse));
-
-	if (kfifo_in(&ir->raw->kfifo, ev, sizeof(*ev)) != sizeof(*ev))
-		return -ENOMEM;
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(ir_raw_event_store);
-
-/**
- * ir_raw_event_store_edge() - notify raw ir decoders of the start of a pulse/space
- * @input_dev:	the struct input_dev device descriptor
- * @type:	the type of the event that has occurred
- *
- * This routine (which may be called from an interrupt context) is used to
- * store the beginning of an ir pulse or space (or the start/end of ir
- * reception) for the raw ir decoding state machines. This is used by
- * hardware which does not provide durations directly but only interrupts
- * (or similar events) on state change.
- */
-int ir_raw_event_store_edge(struct input_dev *input_dev, enum raw_event_type type)
-{
-	struct ir_input_dev	*ir = input_get_drvdata(input_dev);
-	ktime_t			now;
-	s64			delta; /* ns */
-	struct ir_raw_event	ev;
-	int			rc = 0;
-
-	if (!ir->raw)
-		return -EINVAL;
-
-	now = ktime_get();
-	delta = ktime_to_ns(ktime_sub(now, ir->raw->last_event));
-
-	/* Check for a long duration since last event or if we're
-	 * being called for the first time, note that delta can't
-	 * possibly be negative.
-	 */
-	ev.duration = 0;
-	if (delta > IR_MAX_DURATION || !ir->raw->last_type)
-		type |= IR_START_EVENT;
-	else
-		ev.duration = delta;
-
-	if (type & IR_START_EVENT)
-		ir_raw_event_reset(input_dev);
-	else if (ir->raw->last_type & IR_SPACE) {
-		ev.pulse = false;
-		rc = ir_raw_event_store(input_dev, &ev);
-	} else if (ir->raw->last_type & IR_PULSE) {
-		ev.pulse = true;
-		rc = ir_raw_event_store(input_dev, &ev);
-	} else
-		return 0;
-
-	ir->raw->last_event = now;
-	ir->raw->last_type = type;
-	return rc;
-}
-EXPORT_SYMBOL_GPL(ir_raw_event_store_edge);
-
-/**
- * ir_raw_event_store_with_filter() - pass next pulse/space to decoders with some processing
- * @input_dev:	the struct input_dev device descriptor
- * @type:	the type of the event that has occurred
- *
- * This routine (which may be called from an interrupt context) works
- * in similiar manner to ir_raw_event_store_edge.
- * This routine is intended for devices with limited internal buffer
- * It automerges samples of same type, and handles timeouts
- */
-int ir_raw_event_store_with_filter(struct input_dev *input_dev,
-						struct ir_raw_event *ev)
-{
-	struct ir_input_dev *ir = input_get_drvdata(input_dev);
-	struct ir_raw_event_ctrl *raw = ir->raw;
-
-	if (!raw || !ir->props)
-		return -EINVAL;
-
-	/* Ignore spaces in idle mode */
-	if (ir->idle && !ev->pulse)
-		return 0;
-	else if (ir->idle)
-		ir_raw_event_set_idle(input_dev, false);
-
-	if (!raw->this_ev.duration) {
-		raw->this_ev = *ev;
-	} else if (ev->pulse == raw->this_ev.pulse) {
-		raw->this_ev.duration += ev->duration;
-	} else {
-		ir_raw_event_store(input_dev, &raw->this_ev);
-		raw->this_ev = *ev;
-	}
-
-	/* Enter idle mode if nessesary */
-	if (!ev->pulse && ir->props->timeout &&
-		raw->this_ev.duration >= ir->props->timeout) {
-		ir_raw_event_set_idle(input_dev, true);
-	}
-	return 0;
-}
-EXPORT_SYMBOL_GPL(ir_raw_event_store_with_filter);
-
-/**
- * ir_raw_event_set_idle() - hint the ir core if device is receiving
- * IR data or not
- * @input_dev: the struct input_dev device descriptor
- * @idle: the hint value
- */
-void ir_raw_event_set_idle(struct input_dev *input_dev, bool idle)
-{
-	struct ir_input_dev *ir = input_get_drvdata(input_dev);
-	struct ir_raw_event_ctrl *raw = ir->raw;
-
-	if (!ir->props || !ir->raw)
-		return;
-
-	IR_dprintk(2, "%s idle mode\n", idle ? "enter" : "leave");
-
-	if (idle) {
-		raw->this_ev.timeout = true;
-		ir_raw_event_store(input_dev, &raw->this_ev);
-		init_ir_raw_event(&raw->this_ev);
-	}
-
-	if (ir->props->s_idle)
-		ir->props->s_idle(ir->props->priv, idle);
-	ir->idle = idle;
-}
-EXPORT_SYMBOL_GPL(ir_raw_event_set_idle);
-
-/**
- * ir_raw_event_handle() - schedules the decoding of stored ir data
- * @input_dev:	the struct input_dev device descriptor
- *
- * This routine will signal the workqueue to start decoding stored ir data.
- */
-void ir_raw_event_handle(struct input_dev *input_dev)
-{
-	struct ir_input_dev *ir = input_get_drvdata(input_dev);
-	unsigned long flags;
-
-	if (!ir->raw)
-		return;
-
-	spin_lock_irqsave(&ir->raw->lock, flags);
-	wake_up_process(ir->raw->thread);
-	spin_unlock_irqrestore(&ir->raw->lock, flags);
-}
-EXPORT_SYMBOL_GPL(ir_raw_event_handle);
-
-/* used internally by the sysfs interface */
-u64
-ir_raw_get_allowed_protocols()
-{
-	u64 protocols;
-	mutex_lock(&ir_raw_handler_lock);
-	protocols = available_protocols;
-	mutex_unlock(&ir_raw_handler_lock);
-	return protocols;
-}
-
-/*
- * Used to (un)register raw event clients
- */
-int ir_raw_event_register(struct input_dev *input_dev)
-{
-	struct ir_input_dev *ir = input_get_drvdata(input_dev);
-	int rc;
-	struct ir_raw_handler *handler;
-
-	ir->raw = kzalloc(sizeof(*ir->raw), GFP_KERNEL);
-	if (!ir->raw)
-		return -ENOMEM;
-
-	ir->raw->input_dev = input_dev;
-
-	ir->raw->enabled_protocols = ~0;
-	rc = kfifo_alloc(&ir->raw->kfifo, sizeof(s64) * MAX_IR_EVENT_SIZE,
-			 GFP_KERNEL);
-	if (rc < 0) {
-		kfree(ir->raw);
-		ir->raw = NULL;
-		return rc;
-	}
-
-	spin_lock_init(&ir->raw->lock);
-	ir->raw->thread = kthread_run(ir_raw_event_thread, ir->raw,
-			"rc%u",  (unsigned int)ir->devno);
-
-	if (IS_ERR(ir->raw->thread)) {
-		int ret = PTR_ERR(ir->raw->thread);
-
-		kfree(ir->raw);
-		ir->raw = NULL;
-		return ret;
-	}
-
-	mutex_lock(&ir_raw_handler_lock);
-	list_add_tail(&ir->raw->list, &ir_raw_client_list);
-	list_for_each_entry(handler, &ir_raw_handler_list, list)
-		if (handler->raw_register)
-			handler->raw_register(ir->raw->input_dev);
-	mutex_unlock(&ir_raw_handler_lock);
-
-	return 0;
-}
-
-void ir_raw_event_unregister(struct input_dev *input_dev)
-{
-	struct ir_input_dev *ir = input_get_drvdata(input_dev);
-	struct ir_raw_handler *handler;
-
-	if (!ir->raw)
-		return;
-
-	kthread_stop(ir->raw->thread);
-
-	mutex_lock(&ir_raw_handler_lock);
-	list_del(&ir->raw->list);
-	list_for_each_entry(handler, &ir_raw_handler_list, list)
-		if (handler->raw_unregister)
-			handler->raw_unregister(ir->raw->input_dev);
-	mutex_unlock(&ir_raw_handler_lock);
-
-	kfifo_free(&ir->raw->kfifo);
-	kfree(ir->raw);
-	ir->raw = NULL;
-}
-
-/*
- * Extension interface - used to register the IR decoders
- */
-
-int ir_raw_handler_register(struct ir_raw_handler *ir_raw_handler)
-{
-	struct ir_raw_event_ctrl *raw;
-
-	mutex_lock(&ir_raw_handler_lock);
-	list_add_tail(&ir_raw_handler->list, &ir_raw_handler_list);
-	if (ir_raw_handler->raw_register)
-		list_for_each_entry(raw, &ir_raw_client_list, list)
-			ir_raw_handler->raw_register(raw->input_dev);
-	available_protocols |= ir_raw_handler->protocols;
-	mutex_unlock(&ir_raw_handler_lock);
-
-	return 0;
-}
-EXPORT_SYMBOL(ir_raw_handler_register);
-
-void ir_raw_handler_unregister(struct ir_raw_handler *ir_raw_handler)
-{
-	struct ir_raw_event_ctrl *raw;
-
-	mutex_lock(&ir_raw_handler_lock);
-	list_del(&ir_raw_handler->list);
-	if (ir_raw_handler->raw_unregister)
-		list_for_each_entry(raw, &ir_raw_client_list, list)
-			ir_raw_handler->raw_unregister(raw->input_dev);
-	available_protocols &= ~ir_raw_handler->protocols;
-	mutex_unlock(&ir_raw_handler_lock);
-}
-EXPORT_SYMBOL(ir_raw_handler_unregister);
-
-#ifdef MODULE
-static void init_decoders(struct work_struct *work)
-{
-	/* Load the decoder modules */
-
-	load_nec_decode();
-	load_rc5_decode();
-	load_rc6_decode();
-	load_jvc_decode();
-	load_sony_decode();
-	load_lirc_codec();
-
-	/* If needed, we may later add some init code. In this case,
-	   it is needed to change the CONFIG_MODULE test at ir-core.h
-	 */
-}
-#endif
-
-void ir_raw_init(void)
-{
-#ifdef MODULE
-	INIT_WORK(&wq_load, init_decoders);
-	schedule_work(&wq_load);
-#endif
-}
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/ir-rc5-decoder.c linux-libre-2.6.38-gnu1/drivers/media/IR/ir-rc5-decoder.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/ir-rc5-decoder.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/ir-rc5-decoder.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,190 +0,0 @@
-/* ir-rc5-decoder.c - handle RC5(x) IR Pulse/Space protocol
- *
- * Copyright (C) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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.
- */
-
-/*
- * This code handles 14 bits RC5 protocols and 20 bits RC5x protocols.
- * There are other variants that use a different number of bits.
- * This is currently unsupported.
- * It considers a carrier of 36 kHz, with a total of 14/20 bits, where
- * the first two bits are start bits, and a third one is a filing bit
- */
-
-#include "ir-core-priv.h"
-
-#define RC5_NBITS		14
-#define RC5X_NBITS		20
-#define CHECK_RC5X_NBITS	8
-#define RC5_UNIT		888888 /* ns */
-#define RC5_BIT_START		(1 * RC5_UNIT)
-#define RC5_BIT_END		(1 * RC5_UNIT)
-#define RC5X_SPACE		(4 * RC5_UNIT)
-
-enum rc5_state {
-	STATE_INACTIVE,
-	STATE_BIT_START,
-	STATE_BIT_END,
-	STATE_CHECK_RC5X,
-	STATE_FINISHED,
-};
-
-/**
- * ir_rc5_decode() - Decode one RC-5 pulse or space
- * @input_dev:	the struct input_dev descriptor of the device
- * @ev:		the struct ir_raw_event descriptor of the pulse/space
- *
- * This function returns -EINVAL if the pulse violates the state machine
- */
-static int ir_rc5_decode(struct input_dev *input_dev, struct ir_raw_event ev)
-{
-	struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
-	struct rc5_dec *data = &ir_dev->raw->rc5;
-	u8 toggle;
-	u32 scancode;
-
-        if (!(ir_dev->raw->enabled_protocols & IR_TYPE_RC5))
-                return 0;
-
-	if (!is_timing_event(ev)) {
-		if (ev.reset)
-			data->state = STATE_INACTIVE;
-		return 0;
-	}
-
-	if (!geq_margin(ev.duration, RC5_UNIT, RC5_UNIT / 2))
-		goto out;
-
-again:
-	IR_dprintk(2, "RC5(x) decode started at state %i (%uus %s)\n",
-		   data->state, TO_US(ev.duration), TO_STR(ev.pulse));
-
-	if (!geq_margin(ev.duration, RC5_UNIT, RC5_UNIT / 2))
-		return 0;
-
-	switch (data->state) {
-
-	case STATE_INACTIVE:
-		if (!ev.pulse)
-			break;
-
-		data->state = STATE_BIT_START;
-		data->count = 1;
-		/* We just need enough bits to get to STATE_CHECK_RC5X */
-		data->wanted_bits = RC5X_NBITS;
-		decrease_duration(&ev, RC5_BIT_START);
-		goto again;
-
-	case STATE_BIT_START:
-		if (!eq_margin(ev.duration, RC5_BIT_START, RC5_UNIT / 2))
-			break;
-
-		data->bits <<= 1;
-		if (!ev.pulse)
-			data->bits |= 1;
-		data->count++;
-		data->state = STATE_BIT_END;
-		return 0;
-
-	case STATE_BIT_END:
-		if (!is_transition(&ev, &ir_dev->raw->prev_ev))
-			break;
-
-		if (data->count == data->wanted_bits)
-			data->state = STATE_FINISHED;
-		else if (data->count == CHECK_RC5X_NBITS)
-			data->state = STATE_CHECK_RC5X;
-		else
-			data->state = STATE_BIT_START;
-
-		decrease_duration(&ev, RC5_BIT_END);
-		goto again;
-
-	case STATE_CHECK_RC5X:
-		if (!ev.pulse && geq_margin(ev.duration, RC5X_SPACE, RC5_UNIT / 2)) {
-			/* RC5X */
-			data->wanted_bits = RC5X_NBITS;
-			decrease_duration(&ev, RC5X_SPACE);
-		} else {
-			/* RC5 */
-			data->wanted_bits = RC5_NBITS;
-		}
-		data->state = STATE_BIT_START;
-		goto again;
-
-	case STATE_FINISHED:
-		if (ev.pulse)
-			break;
-
-		if (data->wanted_bits == RC5X_NBITS) {
-			/* RC5X */
-			u8 xdata, command, system;
-			xdata    = (data->bits & 0x0003F) >> 0;
-			command  = (data->bits & 0x00FC0) >> 6;
-			system   = (data->bits & 0x1F000) >> 12;
-			toggle   = (data->bits & 0x20000) ? 1 : 0;
-			command += (data->bits & 0x01000) ? 0 : 0x40;
-			scancode = system << 16 | command << 8 | xdata;
-
-			IR_dprintk(1, "RC5X scancode 0x%06x (toggle: %u)\n",
-				   scancode, toggle);
-
-		} else {
-			/* RC5 */
-			u8 command, system;
-			command  = (data->bits & 0x0003F) >> 0;
-			system   = (data->bits & 0x007C0) >> 6;
-			toggle   = (data->bits & 0x00800) ? 1 : 0;
-			command += (data->bits & 0x01000) ? 0 : 0x40;
-			scancode = system << 8 | command;
-
-			IR_dprintk(1, "RC5 scancode 0x%04x (toggle: %u)\n",
-				   scancode, toggle);
-		}
-
-		ir_keydown(input_dev, scancode, toggle);
-		data->state = STATE_INACTIVE;
-		return 0;
-	}
-
-out:
-	IR_dprintk(1, "RC5(x) decode failed at state %i (%uus %s)\n",
-		   data->state, TO_US(ev.duration), TO_STR(ev.pulse));
-	data->state = STATE_INACTIVE;
-	return -EINVAL;
-}
-
-static struct ir_raw_handler rc5_handler = {
-	.protocols	= IR_TYPE_RC5,
-	.decode		= ir_rc5_decode,
-};
-
-static int __init ir_rc5_decode_init(void)
-{
-	ir_raw_handler_register(&rc5_handler);
-
-	printk(KERN_INFO "IR RC5(x) protocol handler initialized\n");
-	return 0;
-}
-
-static void __exit ir_rc5_decode_exit(void)
-{
-	ir_raw_handler_unregister(&rc5_handler);
-}
-
-module_init(ir_rc5_decode_init);
-module_exit(ir_rc5_decode_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
-MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)");
-MODULE_DESCRIPTION("RC5(x) IR protocol decoder");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/ir-rc5-sz-decoder.c linux-libre-2.6.38-gnu1/drivers/media/IR/ir-rc5-sz-decoder.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/ir-rc5-sz-decoder.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/ir-rc5-sz-decoder.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,154 +0,0 @@
-/* ir-rc5-sz-decoder.c - handle RC5 Streamzap IR Pulse/Space protocol
- *
- * Copyright (C) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
- * Copyright (C) 2010 by Jarod Wilson <jarod@redhat.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.
- */
-
-/*
- * This code handles the 15 bit RC5-ish protocol used by the Streamzap
- * PC Remote.
- * It considers a carrier of 36 kHz, with a total of 15 bits, where
- * the first two bits are start bits, and a third one is a filing bit
- */
-
-#include "ir-core-priv.h"
-
-#define RC5_SZ_NBITS		15
-#define RC5_UNIT		888888 /* ns */
-#define RC5_BIT_START		(1 * RC5_UNIT)
-#define RC5_BIT_END		(1 * RC5_UNIT)
-
-enum rc5_sz_state {
-	STATE_INACTIVE,
-	STATE_BIT_START,
-	STATE_BIT_END,
-	STATE_FINISHED,
-};
-
-/**
- * ir_rc5_sz_decode() - Decode one RC-5 Streamzap pulse or space
- * @input_dev:	the struct input_dev descriptor of the device
- * @ev:		the struct ir_raw_event descriptor of the pulse/space
- *
- * This function returns -EINVAL if the pulse violates the state machine
- */
-static int ir_rc5_sz_decode(struct input_dev *input_dev, struct ir_raw_event ev)
-{
-	struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
-	struct rc5_sz_dec *data = &ir_dev->raw->rc5_sz;
-	u8 toggle, command, system;
-	u32 scancode;
-
-        if (!(ir_dev->raw->enabled_protocols & IR_TYPE_RC5_SZ))
-                return 0;
-
-	if (!is_timing_event(ev)) {
-		if (ev.reset)
-			data->state = STATE_INACTIVE;
-		return 0;
-	}
-
-	if (!geq_margin(ev.duration, RC5_UNIT, RC5_UNIT / 2))
-		goto out;
-
-again:
-	IR_dprintk(2, "RC5-sz decode started at state %i (%uus %s)\n",
-		   data->state, TO_US(ev.duration), TO_STR(ev.pulse));
-
-	if (!geq_margin(ev.duration, RC5_UNIT, RC5_UNIT / 2))
-		return 0;
-
-	switch (data->state) {
-
-	case STATE_INACTIVE:
-		if (!ev.pulse)
-			break;
-
-		data->state = STATE_BIT_START;
-		data->count = 1;
-		data->wanted_bits = RC5_SZ_NBITS;
-		decrease_duration(&ev, RC5_BIT_START);
-		goto again;
-
-	case STATE_BIT_START:
-		if (!eq_margin(ev.duration, RC5_BIT_START, RC5_UNIT / 2))
-			break;
-
-		data->bits <<= 1;
-		if (!ev.pulse)
-			data->bits |= 1;
-		data->count++;
-		data->state = STATE_BIT_END;
-		return 0;
-
-	case STATE_BIT_END:
-		if (!is_transition(&ev, &ir_dev->raw->prev_ev))
-			break;
-
-		if (data->count == data->wanted_bits)
-			data->state = STATE_FINISHED;
-		else
-			data->state = STATE_BIT_START;
-
-		decrease_duration(&ev, RC5_BIT_END);
-		goto again;
-
-	case STATE_FINISHED:
-		if (ev.pulse)
-			break;
-
-		/* RC5-sz */
-		command  = (data->bits & 0x0003F) >> 0;
-		system   = (data->bits & 0x02FC0) >> 6;
-		toggle   = (data->bits & 0x01000) ? 1 : 0;
-		scancode = system << 6 | command;
-
-		IR_dprintk(1, "RC5-sz scancode 0x%04x (toggle: %u)\n",
-			   scancode, toggle);
-
-		ir_keydown(input_dev, scancode, toggle);
-		data->state = STATE_INACTIVE;
-		return 0;
-	}
-
-out:
-	IR_dprintk(1, "RC5-sz decode failed at state %i (%uus %s)\n",
-		   data->state, TO_US(ev.duration), TO_STR(ev.pulse));
-	data->state = STATE_INACTIVE;
-	return -EINVAL;
-}
-
-static struct ir_raw_handler rc5_sz_handler = {
-	.protocols	= IR_TYPE_RC5_SZ,
-	.decode		= ir_rc5_sz_decode,
-};
-
-static int __init ir_rc5_sz_decode_init(void)
-{
-	ir_raw_handler_register(&rc5_sz_handler);
-
-	printk(KERN_INFO "IR RC5 (streamzap) protocol handler initialized\n");
-	return 0;
-}
-
-static void __exit ir_rc5_sz_decode_exit(void)
-{
-	ir_raw_handler_unregister(&rc5_sz_handler);
-}
-
-module_init(ir_rc5_sz_decode_init);
-module_exit(ir_rc5_sz_decode_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Jarod Wilson <jarod@redhat.com>");
-MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)");
-MODULE_DESCRIPTION("RC5 (streamzap) IR protocol decoder");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/ir-rc6-decoder.c linux-libre-2.6.38-gnu1/drivers/media/IR/ir-rc6-decoder.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/ir-rc6-decoder.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/ir-rc6-decoder.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,281 +0,0 @@
-/* ir-rc6-decoder.c - A decoder for the RC6 IR protocol
- *
- * Copyright (C) 2010 by David Härdeman <david@hardeman.nu>
- *
- * 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.
- */
-
-#include "ir-core-priv.h"
-
-/*
- * This decoder currently supports:
- * RC6-0-16	(standard toggle bit in header)
- * RC6-6A-24	(no toggle bit)
- * RC6-6A-32	(MCE version with toggle bit in body)
- */
-
-#define RC6_UNIT		444444	/* us */
-#define RC6_HEADER_NBITS	4	/* not including toggle bit */
-#define RC6_0_NBITS		16
-#define RC6_6A_SMALL_NBITS	24
-#define RC6_6A_LARGE_NBITS	32
-#define RC6_PREFIX_PULSE	(6 * RC6_UNIT)
-#define RC6_PREFIX_SPACE	(2 * RC6_UNIT)
-#define RC6_BIT_START		(1 * RC6_UNIT)
-#define RC6_BIT_END		(1 * RC6_UNIT)
-#define RC6_TOGGLE_START	(2 * RC6_UNIT)
-#define RC6_TOGGLE_END		(2 * RC6_UNIT)
-#define RC6_MODE_MASK		0x07	/* for the header bits */
-#define RC6_STARTBIT_MASK	0x08	/* for the header bits */
-#define RC6_6A_MCE_TOGGLE_MASK	0x8000	/* for the body bits */
-
-enum rc6_mode {
-	RC6_MODE_0,
-	RC6_MODE_6A,
-	RC6_MODE_UNKNOWN,
-};
-
-enum rc6_state {
-	STATE_INACTIVE,
-	STATE_PREFIX_SPACE,
-	STATE_HEADER_BIT_START,
-	STATE_HEADER_BIT_END,
-	STATE_TOGGLE_START,
-	STATE_TOGGLE_END,
-	STATE_BODY_BIT_START,
-	STATE_BODY_BIT_END,
-	STATE_FINISHED,
-};
-
-static enum rc6_mode rc6_mode(struct rc6_dec *data)
-{
-	switch (data->header & RC6_MODE_MASK) {
-	case 0:
-		return RC6_MODE_0;
-	case 6:
-		if (!data->toggle)
-			return RC6_MODE_6A;
-		/* fall through */
-	default:
-		return RC6_MODE_UNKNOWN;
-	}
-}
-
-/**
- * ir_rc6_decode() - Decode one RC6 pulse or space
- * @input_dev:	the struct input_dev descriptor of the device
- * @ev:		the struct ir_raw_event descriptor of the pulse/space
- *
- * This function returns -EINVAL if the pulse violates the state machine
- */
-static int ir_rc6_decode(struct input_dev *input_dev, struct ir_raw_event ev)
-{
-	struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
-	struct rc6_dec *data = &ir_dev->raw->rc6;
-	u32 scancode;
-	u8 toggle;
-
-	if (!(ir_dev->raw->enabled_protocols & IR_TYPE_RC6))
-		return 0;
-
-	if (!is_timing_event(ev)) {
-		if (ev.reset)
-			data->state = STATE_INACTIVE;
-		return 0;
-	}
-
-	if (!geq_margin(ev.duration, RC6_UNIT, RC6_UNIT / 2))
-		goto out;
-
-again:
-	IR_dprintk(2, "RC6 decode started at state %i (%uus %s)\n",
-		   data->state, TO_US(ev.duration), TO_STR(ev.pulse));
-
-	if (!geq_margin(ev.duration, RC6_UNIT, RC6_UNIT / 2))
-		return 0;
-
-	switch (data->state) {
-
-	case STATE_INACTIVE:
-		if (!ev.pulse)
-			break;
-
-		/* Note: larger margin on first pulse since each RC6_UNIT
-		   is quite short and some hardware takes some time to
-		   adjust to the signal */
-		if (!eq_margin(ev.duration, RC6_PREFIX_PULSE, RC6_UNIT))
-			break;
-
-		data->state = STATE_PREFIX_SPACE;
-		data->count = 0;
-		return 0;
-
-	case STATE_PREFIX_SPACE:
-		if (ev.pulse)
-			break;
-
-		if (!eq_margin(ev.duration, RC6_PREFIX_SPACE, RC6_UNIT / 2))
-			break;
-
-		data->state = STATE_HEADER_BIT_START;
-		return 0;
-
-	case STATE_HEADER_BIT_START:
-		if (!eq_margin(ev.duration, RC6_BIT_START, RC6_UNIT / 2))
-			break;
-
-		data->header <<= 1;
-		if (ev.pulse)
-			data->header |= 1;
-		data->count++;
-		data->state = STATE_HEADER_BIT_END;
-		return 0;
-
-	case STATE_HEADER_BIT_END:
-		if (!is_transition(&ev, &ir_dev->raw->prev_ev))
-			break;
-
-		if (data->count == RC6_HEADER_NBITS)
-			data->state = STATE_TOGGLE_START;
-		else
-			data->state = STATE_HEADER_BIT_START;
-
-		decrease_duration(&ev, RC6_BIT_END);
-		goto again;
-
-	case STATE_TOGGLE_START:
-		if (!eq_margin(ev.duration, RC6_TOGGLE_START, RC6_UNIT / 2))
-			break;
-
-		data->toggle = ev.pulse;
-		data->state = STATE_TOGGLE_END;
-		return 0;
-
-	case STATE_TOGGLE_END:
-		if (!is_transition(&ev, &ir_dev->raw->prev_ev) ||
-		    !geq_margin(ev.duration, RC6_TOGGLE_END, RC6_UNIT / 2))
-			break;
-
-		if (!(data->header & RC6_STARTBIT_MASK)) {
-			IR_dprintk(1, "RC6 invalid start bit\n");
-			break;
-		}
-
-		data->state = STATE_BODY_BIT_START;
-		decrease_duration(&ev, RC6_TOGGLE_END);
-		data->count = 0;
-
-		switch (rc6_mode(data)) {
-		case RC6_MODE_0:
-			data->wanted_bits = RC6_0_NBITS;
-			break;
-		case RC6_MODE_6A:
-			/* This might look weird, but we basically
-			   check the value of the first body bit to
-			   determine the number of bits in mode 6A */
-			if ((!ev.pulse && !geq_margin(ev.duration, RC6_UNIT, RC6_UNIT / 2)) ||
-			    geq_margin(ev.duration, RC6_UNIT, RC6_UNIT / 2))
-				data->wanted_bits = RC6_6A_LARGE_NBITS;
-			else
-				data->wanted_bits = RC6_6A_SMALL_NBITS;
-			break;
-		default:
-			IR_dprintk(1, "RC6 unknown mode\n");
-			goto out;
-		}
-		goto again;
-
-	case STATE_BODY_BIT_START:
-		if (!eq_margin(ev.duration, RC6_BIT_START, RC6_UNIT / 2))
-			break;
-
-		data->body <<= 1;
-		if (ev.pulse)
-			data->body |= 1;
-		data->count++;
-		data->state = STATE_BODY_BIT_END;
-		return 0;
-
-	case STATE_BODY_BIT_END:
-		if (!is_transition(&ev, &ir_dev->raw->prev_ev))
-			break;
-
-		if (data->count == data->wanted_bits)
-			data->state = STATE_FINISHED;
-		else
-			data->state = STATE_BODY_BIT_START;
-
-		decrease_duration(&ev, RC6_BIT_END);
-		goto again;
-
-	case STATE_FINISHED:
-		if (ev.pulse)
-			break;
-
-		switch (rc6_mode(data)) {
-		case RC6_MODE_0:
-			scancode = data->body & 0xffff;
-			toggle = data->toggle;
-			IR_dprintk(1, "RC6(0) scancode 0x%04x (toggle: %u)\n",
-				   scancode, toggle);
-			break;
-		case RC6_MODE_6A:
-			if (data->wanted_bits == RC6_6A_LARGE_NBITS) {
-				toggle = data->body & RC6_6A_MCE_TOGGLE_MASK ? 1 : 0;
-				scancode = data->body & ~RC6_6A_MCE_TOGGLE_MASK;
-			} else {
-				toggle = 0;
-				scancode = data->body & 0xffffff;
-			}
-
-			IR_dprintk(1, "RC6(6A) scancode 0x%08x (toggle: %u)\n",
-				   scancode, toggle);
-			break;
-		default:
-			IR_dprintk(1, "RC6 unknown mode\n");
-			goto out;
-		}
-
-		ir_keydown(input_dev, scancode, toggle);
-		data->state = STATE_INACTIVE;
-		return 0;
-	}
-
-out:
-	IR_dprintk(1, "RC6 decode failed at state %i (%uus %s)\n",
-		   data->state, TO_US(ev.duration), TO_STR(ev.pulse));
-	data->state = STATE_INACTIVE;
-	return -EINVAL;
-}
-
-static struct ir_raw_handler rc6_handler = {
-	.protocols	= IR_TYPE_RC6,
-	.decode		= ir_rc6_decode,
-};
-
-static int __init ir_rc6_decode_init(void)
-{
-	ir_raw_handler_register(&rc6_handler);
-
-	printk(KERN_INFO "IR RC6 protocol handler initialized\n");
-	return 0;
-}
-
-static void __exit ir_rc6_decode_exit(void)
-{
-	ir_raw_handler_unregister(&rc6_handler);
-}
-
-module_init(ir_rc6_decode_init);
-module_exit(ir_rc6_decode_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("David Härdeman <david@hardeman.nu>");
-MODULE_DESCRIPTION("RC6 IR protocol decoder");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/ir-sony-decoder.c linux-libre-2.6.38-gnu1/drivers/media/IR/ir-sony-decoder.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/ir-sony-decoder.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/ir-sony-decoder.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,182 +0,0 @@
-/* ir-sony-decoder.c - handle Sony IR Pulse/Space protocol
- *
- * Copyright (C) 2010 by David Härdeman <david@hardeman.nu>
- *
- * 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.
- */
-
-#include <linux/bitrev.h>
-#include "ir-core-priv.h"
-
-#define SONY_UNIT		600000 /* ns */
-#define SONY_HEADER_PULSE	(4 * SONY_UNIT)
-#define	SONY_HEADER_SPACE	(1 * SONY_UNIT)
-#define SONY_BIT_0_PULSE	(1 * SONY_UNIT)
-#define SONY_BIT_1_PULSE	(2 * SONY_UNIT)
-#define SONY_BIT_SPACE		(1 * SONY_UNIT)
-#define SONY_TRAILER_SPACE	(10 * SONY_UNIT) /* minimum */
-
-enum sony_state {
-	STATE_INACTIVE,
-	STATE_HEADER_SPACE,
-	STATE_BIT_PULSE,
-	STATE_BIT_SPACE,
-	STATE_FINISHED,
-};
-
-/**
- * ir_sony_decode() - Decode one Sony pulse or space
- * @input_dev:	the struct input_dev descriptor of the device
- * @ev:         the struct ir_raw_event descriptor of the pulse/space
- *
- * This function returns -EINVAL if the pulse violates the state machine
- */
-static int ir_sony_decode(struct input_dev *input_dev, struct ir_raw_event ev)
-{
-	struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
-	struct sony_dec *data = &ir_dev->raw->sony;
-	u32 scancode;
-	u8 device, subdevice, function;
-
-	if (!(ir_dev->raw->enabled_protocols & IR_TYPE_SONY))
-		return 0;
-
-	if (!is_timing_event(ev)) {
-		if (ev.reset)
-			data->state = STATE_INACTIVE;
-		return 0;
-	}
-
-	if (!geq_margin(ev.duration, SONY_UNIT, SONY_UNIT / 2))
-		goto out;
-
-	IR_dprintk(2, "Sony decode started at state %d (%uus %s)\n",
-		   data->state, TO_US(ev.duration), TO_STR(ev.pulse));
-
-	switch (data->state) {
-
-	case STATE_INACTIVE:
-		if (!ev.pulse)
-			break;
-
-		if (!eq_margin(ev.duration, SONY_HEADER_PULSE, SONY_UNIT / 2))
-			break;
-
-		data->count = 0;
-		data->state = STATE_HEADER_SPACE;
-		return 0;
-
-	case STATE_HEADER_SPACE:
-		if (ev.pulse)
-			break;
-
-		if (!eq_margin(ev.duration, SONY_HEADER_SPACE, SONY_UNIT / 2))
-			break;
-
-		data->state = STATE_BIT_PULSE;
-		return 0;
-
-	case STATE_BIT_PULSE:
-		if (!ev.pulse)
-			break;
-
-		data->bits <<= 1;
-		if (eq_margin(ev.duration, SONY_BIT_1_PULSE, SONY_UNIT / 2))
-			data->bits |= 1;
-		else if (!eq_margin(ev.duration, SONY_BIT_0_PULSE, SONY_UNIT / 2))
-			break;
-
-		data->count++;
-		data->state = STATE_BIT_SPACE;
-		return 0;
-
-	case STATE_BIT_SPACE:
-		if (ev.pulse)
-			break;
-
-		if (!geq_margin(ev.duration, SONY_BIT_SPACE, SONY_UNIT / 2))
-			break;
-
-		decrease_duration(&ev, SONY_BIT_SPACE);
-
-		if (!geq_margin(ev.duration, SONY_UNIT, SONY_UNIT / 2)) {
-			data->state = STATE_BIT_PULSE;
-			return 0;
-		}
-
-		data->state = STATE_FINISHED;
-		/* Fall through */
-
-	case STATE_FINISHED:
-		if (ev.pulse)
-			break;
-
-		if (!geq_margin(ev.duration, SONY_TRAILER_SPACE, SONY_UNIT / 2))
-			break;
-
-		switch (data->count) {
-		case 12:
-			device    = bitrev8((data->bits <<  3) & 0xF8);
-			subdevice = 0;
-			function  = bitrev8((data->bits >>  4) & 0xFE);
-			break;
-		case 15:
-			device    = bitrev8((data->bits >>  0) & 0xFF);
-			subdevice = 0;
-			function  = bitrev8((data->bits >>  7) & 0xFD);
-			break;
-		case 20:
-			device    = bitrev8((data->bits >>  5) & 0xF8);
-			subdevice = bitrev8((data->bits >>  0) & 0xFF);
-			function  = bitrev8((data->bits >> 12) & 0xFE);
-			break;
-		default:
-			IR_dprintk(1, "Sony invalid bitcount %u\n", data->count);
-			goto out;
-		}
-
-		scancode = device << 16 | subdevice << 8 | function;
-		IR_dprintk(1, "Sony(%u) scancode 0x%05x\n", data->count, scancode);
-		ir_keydown(input_dev, scancode, 0);
-		data->state = STATE_INACTIVE;
-		return 0;
-	}
-
-out:
-	IR_dprintk(1, "Sony decode failed at state %d (%uus %s)\n",
-		   data->state, TO_US(ev.duration), TO_STR(ev.pulse));
-	data->state = STATE_INACTIVE;
-	return -EINVAL;
-}
-
-static struct ir_raw_handler sony_handler = {
-	.protocols	= IR_TYPE_SONY,
-	.decode		= ir_sony_decode,
-};
-
-static int __init ir_sony_decode_init(void)
-{
-	ir_raw_handler_register(&sony_handler);
-
-	printk(KERN_INFO "IR Sony protocol handler initialized\n");
-	return 0;
-}
-
-static void __exit ir_sony_decode_exit(void)
-{
-	ir_raw_handler_unregister(&sony_handler);
-}
-
-module_init(ir_sony_decode_init);
-module_exit(ir_sony_decode_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("David Härdeman <david@hardeman.nu>");
-MODULE_DESCRIPTION("Sony IR protocol decoder");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/ir-sysfs.c linux-libre-2.6.38-gnu1/drivers/media/IR/ir-sysfs.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/ir-sysfs.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/ir-sysfs.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,362 +0,0 @@
-/* ir-sysfs.c - sysfs interface for RC devices (/sys/class/rc)
- *
- * Copyright (C) 2009-2010 by Mauro Carvalho Chehab <mchehab@redhat.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.
- */
-
-#include <linux/slab.h>
-#include <linux/input.h>
-#include <linux/device.h>
-#include "ir-core-priv.h"
-
-#define IRRCV_NUM_DEVICES	256
-
-/* bit array to represent IR sysfs device number */
-static unsigned long ir_core_dev_number;
-
-/* class for /sys/class/rc */
-static char *ir_devnode(struct device *dev, mode_t *mode)
-{
-	return kasprintf(GFP_KERNEL, "rc/%s", dev_name(dev));
-}
-
-static struct class ir_input_class = {
-	.name		= "rc",
-	.devnode	= ir_devnode,
-};
-
-static struct {
-	u64	type;
-	char	*name;
-} proto_names[] = {
-	{ IR_TYPE_UNKNOWN,	"unknown"	},
-	{ IR_TYPE_RC5,		"rc-5"		},
-	{ IR_TYPE_NEC,		"nec"		},
-	{ IR_TYPE_RC6,		"rc-6"		},
-	{ IR_TYPE_JVC,		"jvc"		},
-	{ IR_TYPE_SONY,		"sony"		},
-	{ IR_TYPE_RC5_SZ,	"rc-5-sz"	},
-	{ IR_TYPE_LIRC,		"lirc"		},
-};
-
-#define PROTO_NONE	"none"
-
-/**
- * show_protocols() - shows the current IR protocol(s)
- * @d:		the device descriptor
- * @mattr:	the device attribute struct (unused)
- * @buf:	a pointer to the output buffer
- *
- * This routine is a callback routine for input read the IR protocol type(s).
- * it is trigged by reading /sys/class/rc/rc?/protocols.
- * It returns the protocol names of supported protocols.
- * Enabled protocols are printed in brackets.
- */
-static ssize_t show_protocols(struct device *d,
-			      struct device_attribute *mattr, char *buf)
-{
-	struct ir_input_dev *ir_dev = dev_get_drvdata(d);
-	u64 allowed, enabled;
-	char *tmp = buf;
-	int i;
-
-	/* Device is being removed */
-	if (!ir_dev)
-		return -EINVAL;
-
-	if (ir_dev->props && ir_dev->props->driver_type == RC_DRIVER_SCANCODE) {
-		enabled = ir_dev->rc_tab.ir_type;
-		allowed = ir_dev->props->allowed_protos;
-	} else if (ir_dev->raw) {
-		enabled = ir_dev->raw->enabled_protocols;
-		allowed = ir_raw_get_allowed_protocols();
-	} else
-		return sprintf(tmp, "[builtin]\n");
-
-	IR_dprintk(1, "allowed - 0x%llx, enabled - 0x%llx\n",
-		   (long long)allowed,
-		   (long long)enabled);
-
-	for (i = 0; i < ARRAY_SIZE(proto_names); i++) {
-		if (allowed & enabled & proto_names[i].type)
-			tmp += sprintf(tmp, "[%s] ", proto_names[i].name);
-		else if (allowed & proto_names[i].type)
-			tmp += sprintf(tmp, "%s ", proto_names[i].name);
-	}
-
-	if (tmp != buf)
-		tmp--;
-	*tmp = '\n';
-	return tmp + 1 - buf;
-}
-
-/**
- * store_protocols() - changes the current IR protocol(s)
- * @d:		the device descriptor
- * @mattr:	the device attribute struct (unused)
- * @buf:	a pointer to the input buffer
- * @len:	length of the input buffer
- *
- * This routine is a callback routine for changing the IR protocol type.
- * It is trigged by writing to /sys/class/rc/rc?/protocols.
- * Writing "+proto" will add a protocol to the list of enabled protocols.
- * Writing "-proto" will remove a protocol from the list of enabled protocols.
- * Writing "proto" will enable only "proto".
- * Writing "none" will disable all protocols.
- * Returns -EINVAL if an invalid protocol combination or unknown protocol name
- * is used, otherwise @len.
- */
-static ssize_t store_protocols(struct device *d,
-			       struct device_attribute *mattr,
-			       const char *data,
-			       size_t len)
-{
-	struct ir_input_dev *ir_dev = dev_get_drvdata(d);
-	bool enable, disable;
-	const char *tmp;
-	u64 type;
-	u64 mask;
-	int rc, i, count = 0;
-	unsigned long flags;
-
-	/* Device is being removed */
-	if (!ir_dev)
-		return -EINVAL;
-
-	if (ir_dev->props && ir_dev->props->driver_type == RC_DRIVER_SCANCODE)
-		type = ir_dev->rc_tab.ir_type;
-	else if (ir_dev->raw)
-		type = ir_dev->raw->enabled_protocols;
-	else {
-		IR_dprintk(1, "Protocol switching not supported\n");
-		return -EINVAL;
-	}
-
-	while ((tmp = strsep((char **) &data, " \n")) != NULL) {
-		if (!*tmp)
-			break;
-
-		if (*tmp == '+') {
-			enable = true;
-			disable = false;
-			tmp++;
-		} else if (*tmp == '-') {
-			enable = false;
-			disable = true;
-			tmp++;
-		} else {
-			enable = false;
-			disable = false;
-		}
-
-		if (!enable && !disable && !strncasecmp(tmp, PROTO_NONE, sizeof(PROTO_NONE))) {
-			tmp += sizeof(PROTO_NONE);
-			mask = 0;
-			count++;
-		} else {
-			for (i = 0; i < ARRAY_SIZE(proto_names); i++) {
-				if (!strncasecmp(tmp, proto_names[i].name, strlen(proto_names[i].name))) {
-					tmp += strlen(proto_names[i].name);
-					mask = proto_names[i].type;
-					break;
-				}
-			}
-			if (i == ARRAY_SIZE(proto_names)) {
-				IR_dprintk(1, "Unknown protocol: '%s'\n", tmp);
-				return -EINVAL;
-			}
-			count++;
-		}
-
-		if (enable)
-			type |= mask;
-		else if (disable)
-			type &= ~mask;
-		else
-			type = mask;
-	}
-
-	if (!count) {
-		IR_dprintk(1, "Protocol not specified\n");
-		return -EINVAL;
-	}
-
-	if (ir_dev->props && ir_dev->props->change_protocol) {
-		rc = ir_dev->props->change_protocol(ir_dev->props->priv,
-						    type);
-		if (rc < 0) {
-			IR_dprintk(1, "Error setting protocols to 0x%llx\n",
-				   (long long)type);
-			return -EINVAL;
-		}
-	}
-
-	if (ir_dev->props && ir_dev->props->driver_type == RC_DRIVER_SCANCODE) {
-		spin_lock_irqsave(&ir_dev->rc_tab.lock, flags);
-		ir_dev->rc_tab.ir_type = type;
-		spin_unlock_irqrestore(&ir_dev->rc_tab.lock, flags);
-	} else {
-		ir_dev->raw->enabled_protocols = type;
-	}
-
-	IR_dprintk(1, "Current protocol(s): 0x%llx\n",
-		   (long long)type);
-
-	return len;
-}
-
-#define ADD_HOTPLUG_VAR(fmt, val...)					\
-	do {								\
-		int err = add_uevent_var(env, fmt, val);		\
-		if (err)						\
-			return err;					\
-	} while (0)
-
-static int rc_dev_uevent(struct device *device, struct kobj_uevent_env *env)
-{
-	struct ir_input_dev *ir_dev = dev_get_drvdata(device);
-
-	if (ir_dev->rc_tab.name)
-		ADD_HOTPLUG_VAR("NAME=%s", ir_dev->rc_tab.name);
-	if (ir_dev->driver_name)
-		ADD_HOTPLUG_VAR("DRV_NAME=%s", ir_dev->driver_name);
-
-	return 0;
-}
-
-/*
- * Static device attribute struct with the sysfs attributes for IR's
- */
-static DEVICE_ATTR(protocols, S_IRUGO | S_IWUSR,
-		   show_protocols, store_protocols);
-
-static struct attribute *rc_dev_attrs[] = {
-	&dev_attr_protocols.attr,
-	NULL,
-};
-
-static struct attribute_group rc_dev_attr_grp = {
-	.attrs	= rc_dev_attrs,
-};
-
-static const struct attribute_group *rc_dev_attr_groups[] = {
-	&rc_dev_attr_grp,
-	NULL
-};
-
-static struct device_type rc_dev_type = {
-	.groups		= rc_dev_attr_groups,
-	.uevent		= rc_dev_uevent,
-};
-
-/**
- * ir_register_class() - creates the sysfs for /sys/class/rc/rc?
- * @input_dev:	the struct input_dev descriptor of the device
- *
- * This routine is used to register the syfs code for IR class
- */
-int ir_register_class(struct input_dev *input_dev)
-{
-	struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
-	int devno = find_first_zero_bit(&ir_core_dev_number,
-					IRRCV_NUM_DEVICES);
-
-	if (unlikely(devno < 0))
-		return devno;
-
-	ir_dev->dev.type = &rc_dev_type;
-	ir_dev->devno = devno;
-
-	ir_dev->dev.class = &ir_input_class;
-	ir_dev->dev.parent = input_dev->dev.parent;
-	input_dev->dev.parent = &ir_dev->dev;
-	dev_set_name(&ir_dev->dev, "rc%d", devno);
-	dev_set_drvdata(&ir_dev->dev, ir_dev);
-	return  device_register(&ir_dev->dev);
-};
-
-/**
- * ir_register_input - registers ir input device with input subsystem
- * @input_dev:	the struct input_dev descriptor of the device
- */
-
-int ir_register_input(struct input_dev *input_dev)
-{
-	struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
-	int rc;
-	const char *path;
-
-
-	rc = input_register_device(input_dev);
-	if (rc < 0) {
-		device_del(&ir_dev->dev);
-		return rc;
-	}
-
-	__module_get(THIS_MODULE);
-
-	path = kobject_get_path(&ir_dev->dev.kobj, GFP_KERNEL);
-	printk(KERN_INFO "%s: %s as %s\n",
-		dev_name(&ir_dev->dev),
-		input_dev->name ? input_dev->name : "Unspecified device",
-		path ? path : "N/A");
-	kfree(path);
-
-	set_bit(ir_dev->devno, &ir_core_dev_number);
-	return 0;
-}
-
-/**
- * ir_unregister_class() - removes the sysfs for sysfs for
- *			   /sys/class/rc/rc?
- * @input_dev:	the struct input_dev descriptor of the device
- *
- * This routine is used to unregister the syfs code for IR class
- */
-void ir_unregister_class(struct input_dev *input_dev)
-{
-	struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
-
-	input_set_drvdata(input_dev, NULL);
-	clear_bit(ir_dev->devno, &ir_core_dev_number);
-	input_unregister_device(input_dev);
-	device_del(&ir_dev->dev);
-
-	module_put(THIS_MODULE);
-}
-
-/*
- * Init/exit code for the module. Basically, creates/removes /sys/class/rc
- */
-
-static int __init ir_core_init(void)
-{
-	int rc = class_register(&ir_input_class);
-	if (rc) {
-		printk(KERN_ERR "ir_core: unable to register rc class\n");
-		return rc;
-	}
-
-	/* Initialize/load the decoders/keymap code that will be used */
-	ir_raw_init();
-	ir_rcmap_init();
-
-	return 0;
-}
-
-static void __exit ir_core_exit(void)
-{
-	class_unregister(&ir_input_class);
-	ir_rcmap_cleanup();
-}
-
-module_init(ir_core_init);
-module_exit(ir_core_exit);
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/Kconfig linux-libre-2.6.38-gnu1/drivers/media/IR/Kconfig
--- linux-libre-2.6.37-gnu1/drivers/media/IR/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/Kconfig	1969-12-31 19:00:00.000000000 -0500
@@ -1,167 +0,0 @@
-menuconfig IR_CORE
-	tristate "Infrared remote controller adapters"
-	depends on INPUT
-	default INPUT
-	---help---
-	  Enable support for Remote Controllers on Linux. This is
-	  needed in order to support several video capture adapters.
-
-	  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
-	  compile the driver for your adapter.
-
-config VIDEO_IR
-	tristate
-	depends on IR_CORE
-	default IR_CORE
-
-if IR_CORE
-
-config LIRC
-	tristate
-	default y
-
-	---help---
-	   Enable this option to build the Linux Infrared Remote
-	   Control (LIRC) core device interface driver. The LIRC
-	   interface passes raw IR to and from userspace, where the
-	   LIRC daemon handles protocol decoding for IR reception and
-	   encoding for IR transmitting (aka "blasting").
-
-source "drivers/media/IR/keymaps/Kconfig"
-
-config IR_NEC_DECODER
-	tristate "Enable IR raw decoder for the NEC protocol"
-	depends on IR_CORE
-	select BITREVERSE
-	default y
-
-	---help---
-	   Enable this option if you have IR with NEC protocol, and
-	   if the IR is decoded in software
-
-config IR_RC5_DECODER
-	tristate "Enable IR raw decoder for the RC-5 protocol"
-	depends on IR_CORE
-	select BITREVERSE
-	default y
-
-	---help---
-	   Enable this option if you have IR with RC-5 protocol, and
-	   if the IR is decoded in software
-
-config IR_RC6_DECODER
-	tristate "Enable IR raw decoder for the RC6 protocol"
-	depends on IR_CORE
-	select BITREVERSE
-	default y
-
-	---help---
-	   Enable this option if you have an infrared remote control which
-	   uses the RC6 protocol, and you need software decoding support.
-
-config IR_JVC_DECODER
-	tristate "Enable IR raw decoder for the JVC protocol"
-	depends on IR_CORE
-	select BITREVERSE
-	default y
-
-	---help---
-	   Enable this option if you have an infrared remote control which
-	   uses the JVC protocol, and you need software decoding support.
-
-config IR_SONY_DECODER
-	tristate "Enable IR raw decoder for the Sony protocol"
-	depends on IR_CORE
-	default y
-
-	---help---
-	   Enable this option if you have an infrared remote control which
-	   uses the Sony protocol, and you need software decoding support.
-
-config IR_RC5_SZ_DECODER
-	tristate "Enable IR raw decoder for the RC-5 (streamzap) protocol"
-	depends on IR_CORE
-	select BITREVERSE
-	default y
-
-	---help---
-	   Enable this option if you have IR with RC-5 (streamzap) protocol,
-	   and if the IR is decoded in software. (The Streamzap PC Remote
-	   uses an IR protocol that is almost standard RC-5, but not quite,
-	   as it uses an additional bit).
-
-config IR_LIRC_CODEC
-	tristate "Enable IR to LIRC bridge"
-	depends on IR_CORE
-	depends on LIRC
-	default y
-
-	---help---
-	   Enable this option to pass raw IR to and from userspace via
-	   the LIRC interface.
-
-config IR_ENE
-	tristate "ENE eHome Receiver/Transceiver (pnp id: ENE0100/ENE02xxx)"
-	depends on PNP
-	depends on IR_CORE
-	---help---
-	   Say Y here to enable support for integrated infrared receiver
-	   /transceiver made by ENE.
-
-	   You can see if you have it by looking at lspnp output.
-	   Output should include ENE0100 ENE0200 or something similar.
-
-	   To compile this driver as a module, choose M here: the
-	   module will be called ene_ir.
-
-config IR_IMON
-	tristate "SoundGraph iMON Receiver and Display"
-	depends on USB_ARCH_HAS_HCD
-	depends on IR_CORE
-	select USB
-	---help---
-	   Say Y here if you want to use a SoundGraph iMON (aka Antec Veris)
-	   IR Receiver and/or LCD/VFD/VGA display.
-
-	   To compile this driver as a module, choose M here: the
-	   module will be called imon.
-
-config IR_MCEUSB
-	tristate "Windows Media Center Ed. eHome Infrared Transceiver"
-	depends on USB_ARCH_HAS_HCD
-	depends on IR_CORE
-	select USB
-	---help---
-	   Say Y here if you want to use a Windows Media Center Edition
-	   eHome Infrared Transceiver.
-
-	   To compile this driver as a module, choose M here: the
-	   module will be called mceusb.
-
-config IR_NUVOTON
-	tristate "Nuvoton w836x7hg Consumer Infrared Transceiver"
-	depends on PNP
-	depends on IR_CORE
-	---help---
-	   Say Y here to enable support for integrated infrared receiver
-	   /transciever made by Nuvoton (formerly Winbond). This chip is
-	   found in the ASRock ION 330HT, as well as assorted Intel
-	   DP55-series motherboards (and of course, possibly others).
-
-	   To compile this driver as a module, choose M here: the
-	   module will be called nuvoton-cir.
-
-config IR_STREAMZAP
-	tristate "Streamzap PC Remote IR Receiver"
-	depends on USB_ARCH_HAS_HCD
-	depends on IR_CORE
-	select USB
-	---help---
-	   Say Y here if you want to use a Streamzap PC Remote
-	   Infrared Receiver.
-
-	   To compile this driver as a module, choose M here: the
-	   module will be called streamzap.
-
-endif #IR_CORE
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/Kconfig linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/Kconfig
--- linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/Kconfig	1969-12-31 19:00:00.000000000 -0500
@@ -1,15 +0,0 @@
-config RC_MAP
-	tristate "Compile Remote Controller keymap modules"
-	depends on IR_CORE
-	default y
-
-	---help---
-	   This option enables the compilation of lots of Remote
-	   Controller tables. They are short tables, but if you
-	   don't use a remote controller, or prefer to load the
-	   tables on userspace, you should disable it.
-
-	   The ir-keytable program, available at v4l-utils package
-	   provide the tool and the same RC maps for load from
-	   userspace. Its available at
-			http://git.linuxtv.org/v4l-utils
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/Makefile linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/Makefile
--- linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/Makefile	1969-12-31 19:00:00.000000000 -0500
@@ -1,86 +0,0 @@
-obj-$(CONFIG_RC_MAP) += rc-adstech-dvb-t-pci.o \
-			rc-alink-dtu-m.o \
-			rc-anysee.o \
-			rc-apac-viewcomp.o \
-			rc-asus-pc39.o \
-			rc-ati-tv-wonder-hd-600.o \
-			rc-avermedia-a16d.o \
-			rc-avermedia.o \
-			rc-avermedia-cardbus.o \
-			rc-avermedia-dvbt.o \
-			rc-avermedia-m135a.o \
-			rc-avermedia-m733a-rm-k6.o \
-			rc-avermedia-rm-ks.o \
-			rc-avertv-303.o \
-			rc-azurewave-ad-tu700.o \
-			rc-behold.o \
-			rc-behold-columbus.o \
-			rc-budget-ci-old.o \
-			rc-cinergy-1400.o \
-			rc-cinergy.o \
-			rc-dib0700-nec.o \
-			rc-dib0700-rc5.o \
-			rc-digitalnow-tinytwin.o \
-			rc-digittrade.o \
-			rc-dm1105-nec.o \
-			rc-dntv-live-dvb-t.o \
-			rc-dntv-live-dvbt-pro.o \
-			rc-em-terratec.o \
-			rc-encore-enltv2.o \
-			rc-encore-enltv.o \
-			rc-encore-enltv-fm53.o \
-			rc-evga-indtube.o \
-			rc-eztv.o \
-			rc-flydvb.o \
-			rc-flyvideo.o \
-			rc-fusionhdtv-mce.o \
-			rc-gadmei-rm008z.o \
-			rc-genius-tvgo-a11mce.o \
-			rc-gotview7135.o \
-			rc-hauppauge-new.o \
-			rc-imon-mce.o \
-			rc-imon-pad.o \
-			rc-iodata-bctv7e.o \
-			rc-kaiomy.o \
-			rc-kworld-315u.o \
-			rc-kworld-plus-tv-analog.o \
-			rc-leadtek-y04g0051.o \
-			rc-lirc.o \
-			rc-lme2510.o \
-			rc-manli.o \
-			rc-msi-digivox-ii.o \
-			rc-msi-digivox-iii.o \
-			rc-msi-tvanywhere.o \
-			rc-msi-tvanywhere-plus.o \
-			rc-nebula.o \
-			rc-nec-terratec-cinergy-xs.o \
-			rc-norwood.o \
-			rc-npgtech.o \
-			rc-pctv-sedna.o \
-			rc-pinnacle-color.o \
-			rc-pinnacle-grey.o \
-			rc-pinnacle-pctv-hd.o \
-			rc-pixelview.o \
-			rc-pixelview-mk12.o \
-			rc-pixelview-new.o \
-			rc-powercolor-real-angel.o \
-			rc-proteus-2309.o \
-			rc-purpletv.o \
-			rc-pv951.o \
-			rc-rc5-hauppauge-new.o \
-			rc-rc5-tv.o \
-			rc-rc6-mce.o \
-			rc-real-audio-220-32-keys.o \
-			rc-streamzap.o \
-			rc-tbs-nec.o \
-			rc-terratec-cinergy-xs.o \
-			rc-terratec-slim.o \
-			rc-tevii-nec.o \
-			rc-total-media-in-hand.o \
-			rc-trekstor.o \
-			rc-tt-1500.o \
-			rc-twinhan1027.o \
-			rc-videomate-s350.o \
-			rc-videomate-tv-pvr.o \
-			rc-winfast.o \
-			rc-winfast-usbii-deluxe.o
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-adstech-dvb-t-pci.c linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-adstech-dvb-t-pci.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-adstech-dvb-t-pci.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-adstech-dvb-t-pci.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,89 +0,0 @@
-/* adstech-dvb-t-pci.h - Keytable for adstech_dvb_t_pci Remote Controller
- *
- * keymap imported from ir-keymaps.c
- *
- * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
-
-/* ADS Tech Instant TV DVB-T PCI Remote */
-
-static struct ir_scancode adstech_dvb_t_pci[] = {
-	/* Keys 0 to 9 */
-	{ 0x4d, KEY_0 },
-	{ 0x57, KEY_1 },
-	{ 0x4f, KEY_2 },
-	{ 0x53, KEY_3 },
-	{ 0x56, KEY_4 },
-	{ 0x4e, KEY_5 },
-	{ 0x5e, KEY_6 },
-	{ 0x54, KEY_7 },
-	{ 0x4c, KEY_8 },
-	{ 0x5c, KEY_9 },
-
-	{ 0x5b, KEY_POWER },
-	{ 0x5f, KEY_MUTE },
-	{ 0x55, KEY_GOTO },
-	{ 0x5d, KEY_SEARCH },
-	{ 0x17, KEY_EPG },		/* Guide */
-	{ 0x1f, KEY_MENU },
-	{ 0x0f, KEY_UP },
-	{ 0x46, KEY_DOWN },
-	{ 0x16, KEY_LEFT },
-	{ 0x1e, KEY_RIGHT },
-	{ 0x0e, KEY_SELECT },		/* Enter */
-	{ 0x5a, KEY_INFO },
-	{ 0x52, KEY_EXIT },
-	{ 0x59, KEY_PREVIOUS },
-	{ 0x51, KEY_NEXT },
-	{ 0x58, KEY_REWIND },
-	{ 0x50, KEY_FORWARD },
-	{ 0x44, KEY_PLAYPAUSE },
-	{ 0x07, KEY_STOP },
-	{ 0x1b, KEY_RECORD },
-	{ 0x13, KEY_TUNER },		/* Live */
-	{ 0x0a, KEY_A },
-	{ 0x12, KEY_B },
-	{ 0x03, KEY_PROG1 },		/* 1 */
-	{ 0x01, KEY_PROG2 },		/* 2 */
-	{ 0x00, KEY_PROG3 },		/* 3 */
-	{ 0x06, KEY_DVD },
-	{ 0x48, KEY_AUX },		/* Photo */
-	{ 0x40, KEY_VIDEO },
-	{ 0x19, KEY_AUDIO },		/* Music */
-	{ 0x0b, KEY_CHANNELUP },
-	{ 0x08, KEY_CHANNELDOWN },
-	{ 0x15, KEY_VOLUMEUP },
-	{ 0x1c, KEY_VOLUMEDOWN },
-};
-
-static struct rc_keymap adstech_dvb_t_pci_map = {
-	.map = {
-		.scan    = adstech_dvb_t_pci,
-		.size    = ARRAY_SIZE(adstech_dvb_t_pci),
-		.ir_type = IR_TYPE_UNKNOWN,	/* Legacy IR type */
-		.name    = RC_MAP_ADSTECH_DVB_T_PCI,
-	}
-};
-
-static int __init init_rc_map_adstech_dvb_t_pci(void)
-{
-	return ir_register_map(&adstech_dvb_t_pci_map);
-}
-
-static void __exit exit_rc_map_adstech_dvb_t_pci(void)
-{
-	ir_unregister_map(&adstech_dvb_t_pci_map);
-}
-
-module_init(init_rc_map_adstech_dvb_t_pci)
-module_exit(exit_rc_map_adstech_dvb_t_pci)
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-alink-dtu-m.c linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-alink-dtu-m.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-alink-dtu-m.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-alink-dtu-m.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,68 +0,0 @@
-/*
- * A-Link DTU(m) remote controller keytable
- *
- * Copyright (C) 2010 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 <media/rc-map.h>
-
-/* A-Link DTU(m) slim remote, 6 rows, 3 columns. */
-static struct ir_scancode alink_dtu_m[] = {
-	{ 0x0800, KEY_VOLUMEUP },
-	{ 0x0801, KEY_1 },
-	{ 0x0802, KEY_3 },
-	{ 0x0803, KEY_7 },
-	{ 0x0804, KEY_9 },
-	{ 0x0805, KEY_NEW },             /* symbol: PIP */
-	{ 0x0806, KEY_0 },
-	{ 0x0807, KEY_CHANNEL },         /* JUMP */
-	{ 0x080d, KEY_5 },
-	{ 0x080f, KEY_2 },
-	{ 0x0812, KEY_POWER2 },
-	{ 0x0814, KEY_CHANNELUP },
-	{ 0x0816, KEY_VOLUMEDOWN },
-	{ 0x0818, KEY_6 },
-	{ 0x081a, KEY_MUTE },
-	{ 0x081b, KEY_8 },
-	{ 0x081c, KEY_4 },
-	{ 0x081d, KEY_CHANNELDOWN },
-};
-
-static struct rc_keymap alink_dtu_m_map = {
-	.map = {
-		.scan    = alink_dtu_m,
-		.size    = ARRAY_SIZE(alink_dtu_m),
-		.ir_type = IR_TYPE_NEC,
-		.name    = RC_MAP_ALINK_DTU_M,
-	}
-};
-
-static int __init init_rc_map_alink_dtu_m(void)
-{
-	return ir_register_map(&alink_dtu_m_map);
-}
-
-static void __exit exit_rc_map_alink_dtu_m(void)
-{
-	ir_unregister_map(&alink_dtu_m_map);
-}
-
-module_init(init_rc_map_alink_dtu_m)
-module_exit(exit_rc_map_alink_dtu_m)
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-anysee.c linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-anysee.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-anysee.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-anysee.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,93 +0,0 @@
-/*
- * Anysee remote controller keytable
- *
- * Copyright (C) 2010 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 <media/rc-map.h>
-
-static struct ir_scancode anysee[] = {
-	{ 0x0800, KEY_0 },
-	{ 0x0801, KEY_1 },
-	{ 0x0802, KEY_2 },
-	{ 0x0803, KEY_3 },
-	{ 0x0804, KEY_4 },
-	{ 0x0805, KEY_5 },
-	{ 0x0806, KEY_6 },
-	{ 0x0807, KEY_7 },
-	{ 0x0808, KEY_8 },
-	{ 0x0809, KEY_9 },
-	{ 0x080a, KEY_POWER2 },          /* [red power button] */
-	{ 0x080b, KEY_VIDEO },           /* [*] MODE */
-	{ 0x080c, KEY_CHANNEL },         /* [symbol counterclockwise arrow] */
-	{ 0x080d, KEY_NEXT },            /* [>>|] */
-	{ 0x080e, KEY_MENU },            /* MENU */
-	{ 0x080f, KEY_EPG },             /* [EPG] */
-	{ 0x0810, KEY_CLEAR },           /* EXIT */
-	{ 0x0811, KEY_CHANNELUP },
-	{ 0x0812, KEY_VOLUMEDOWN },
-	{ 0x0813, KEY_VOLUMEUP },
-	{ 0x0814, KEY_CHANNELDOWN },
-	{ 0x0815, KEY_OK },
-	{ 0x0816, KEY_RADIO },           /* [symbol TV/radio] */
-	{ 0x0817, KEY_INFO },            /* [i] */
-	{ 0x0818, KEY_PREVIOUS },        /* [|<<] */
-	{ 0x0819, KEY_FAVORITES },       /* FAV. */
-	{ 0x081a, KEY_SUBTITLE },        /* Subtitle */
-	{ 0x081b, KEY_CAMERA },          /* [symbol camera] */
-	{ 0x081c, KEY_YELLOW },
-	{ 0x081d, KEY_RED },
-	{ 0x081e, KEY_LANGUAGE },        /* [symbol Second Audio Program] */
-	{ 0x081f, KEY_GREEN },
-	{ 0x0820, KEY_SLEEP },           /* Sleep */
-	{ 0x0821, KEY_SCREEN },          /* 16:9 / 4:3 */
-	{ 0x0822, KEY_ZOOM },            /* SIZE */
-	{ 0x0824, KEY_FN },              /* [F1] */
-	{ 0x0825, KEY_FN },              /* [F2] */
-	{ 0x0842, KEY_MUTE },            /* symbol mute */
-	{ 0x0844, KEY_BLUE },
-	{ 0x0847, KEY_TEXT },            /* TEXT */
-	{ 0x0848, KEY_STOP },
-	{ 0x0849, KEY_RECORD },
-	{ 0x0850, KEY_PLAY },
-	{ 0x0851, KEY_PAUSE },
-};
-
-static struct rc_keymap anysee_map = {
-	.map = {
-		.scan    = anysee,
-		.size    = ARRAY_SIZE(anysee),
-		.ir_type = IR_TYPE_NEC,
-		.name    = RC_MAP_ANYSEE,
-	}
-};
-
-static int __init init_rc_map_anysee(void)
-{
-	return ir_register_map(&anysee_map);
-}
-
-static void __exit exit_rc_map_anysee(void)
-{
-	ir_unregister_map(&anysee_map);
-}
-
-module_init(init_rc_map_anysee)
-module_exit(exit_rc_map_anysee)
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-apac-viewcomp.c linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-apac-viewcomp.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-apac-viewcomp.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-apac-viewcomp.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,80 +0,0 @@
-/* apac-viewcomp.h - Keytable for apac_viewcomp Remote Controller
- *
- * keymap imported from ir-keymaps.c
- *
- * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
-
-/* Attila Kondoros <attila.kondoros@chello.hu> */
-
-static struct ir_scancode apac_viewcomp[] = {
-
-	{ 0x01, KEY_1 },
-	{ 0x02, KEY_2 },
-	{ 0x03, KEY_3 },
-	{ 0x04, KEY_4 },
-	{ 0x05, KEY_5 },
-	{ 0x06, KEY_6 },
-	{ 0x07, KEY_7 },
-	{ 0x08, KEY_8 },
-	{ 0x09, KEY_9 },
-	{ 0x00, KEY_0 },
-	{ 0x17, KEY_LAST },		/* +100 */
-	{ 0x0a, KEY_LIST },		/* recall */
-
-
-	{ 0x1c, KEY_TUNER },		/* TV/FM */
-	{ 0x15, KEY_SEARCH },		/* scan */
-	{ 0x12, KEY_POWER },		/* power */
-	{ 0x1f, KEY_VOLUMEDOWN },	/* vol up */
-	{ 0x1b, KEY_VOLUMEUP },		/* vol down */
-	{ 0x1e, KEY_CHANNELDOWN },	/* chn up */
-	{ 0x1a, KEY_CHANNELUP },	/* chn down */
-
-	{ 0x11, KEY_VIDEO },		/* video */
-	{ 0x0f, KEY_ZOOM },		/* full screen */
-	{ 0x13, KEY_MUTE },		/* mute/unmute */
-	{ 0x10, KEY_TEXT },		/* min */
-
-	{ 0x0d, KEY_STOP },		/* freeze */
-	{ 0x0e, KEY_RECORD },		/* record */
-	{ 0x1d, KEY_PLAYPAUSE },	/* stop */
-	{ 0x19, KEY_PLAY },		/* play */
-
-	{ 0x16, KEY_GOTO },		/* osd */
-	{ 0x14, KEY_REFRESH },		/* default */
-	{ 0x0c, KEY_KPPLUS },		/* fine tune >>>> */
-	{ 0x18, KEY_KPMINUS },		/* fine tune <<<< */
-};
-
-static struct rc_keymap apac_viewcomp_map = {
-	.map = {
-		.scan    = apac_viewcomp,
-		.size    = ARRAY_SIZE(apac_viewcomp),
-		.ir_type = IR_TYPE_UNKNOWN,	/* Legacy IR type */
-		.name    = RC_MAP_APAC_VIEWCOMP,
-	}
-};
-
-static int __init init_rc_map_apac_viewcomp(void)
-{
-	return ir_register_map(&apac_viewcomp_map);
-}
-
-static void __exit exit_rc_map_apac_viewcomp(void)
-{
-	ir_unregister_map(&apac_viewcomp_map);
-}
-
-module_init(init_rc_map_apac_viewcomp)
-module_exit(exit_rc_map_apac_viewcomp)
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-asus-pc39.c linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-asus-pc39.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-asus-pc39.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-asus-pc39.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,91 +0,0 @@
-/* asus-pc39.h - Keytable for asus_pc39 Remote Controller
- *
- * keymap imported from ir-keymaps.c
- *
- * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
-
-/*
- * Marc Fargas <telenieko@telenieko.com>
- * this is the remote control that comes with the asus p7131
- * which has a label saying is "Model PC-39"
- */
-
-static struct ir_scancode asus_pc39[] = {
-	/* Keys 0 to 9 */
-	{ 0x082a, KEY_0 },
-	{ 0x0816, KEY_1 },
-	{ 0x0812, KEY_2 },
-	{ 0x0814, KEY_3 },
-	{ 0x0836, KEY_4 },
-	{ 0x0832, KEY_5 },
-	{ 0x0834, KEY_6 },
-	{ 0x080e, KEY_7 },
-	{ 0x080a, KEY_8 },
-	{ 0x080c, KEY_9 },
-
-	{ 0x0801, KEY_RADIO },		/* radio */
-	{ 0x083c, KEY_MENU },		/* dvd/menu */
-	{ 0x0815, KEY_VOLUMEUP },
-	{ 0x0826, KEY_VOLUMEDOWN },
-	{ 0x0808, KEY_UP },
-	{ 0x0804, KEY_DOWN },
-	{ 0x0818, KEY_LEFT },
-	{ 0x0810, KEY_RIGHT },
-	{ 0x081a, KEY_VIDEO },		/* video */
-	{ 0x0806, KEY_AUDIO },		/* music */
-
-	{ 0x081e, KEY_TV },		/* tv */
-	{ 0x0822, KEY_EXIT },		/* back */
-	{ 0x0835, KEY_CHANNELUP },	/* channel / program + */
-	{ 0x0824, KEY_CHANNELDOWN },	/* channel / program - */
-	{ 0x0825, KEY_ENTER },		/* enter */
-
-	{ 0x0839, KEY_PAUSE },		/* play/pause */
-	{ 0x0821, KEY_PREVIOUS },		/* rew */
-	{ 0x0819, KEY_NEXT },		/* forward */
-	{ 0x0831, KEY_REWIND },		/* backward << */
-	{ 0x0805, KEY_FASTFORWARD },	/* forward >> */
-	{ 0x0809, KEY_STOP },
-	{ 0x0811, KEY_RECORD },		/* recording */
-	{ 0x0829, KEY_POWER },		/* the button that reads "close" */
-
-	{ 0x082e, KEY_ZOOM },		/* full screen */
-	{ 0x082c, KEY_MACRO },		/* recall */
-	{ 0x081c, KEY_HOME },		/* home */
-	{ 0x083a, KEY_PVR },		/* picture */
-	{ 0x0802, KEY_MUTE },		/* mute */
-	{ 0x083e, KEY_DVD },		/* dvd */
-};
-
-static struct rc_keymap asus_pc39_map = {
-	.map = {
-		.scan    = asus_pc39,
-		.size    = ARRAY_SIZE(asus_pc39),
-		.ir_type = IR_TYPE_RC5,
-		.name    = RC_MAP_ASUS_PC39,
-	}
-};
-
-static int __init init_rc_map_asus_pc39(void)
-{
-	return ir_register_map(&asus_pc39_map);
-}
-
-static void __exit exit_rc_map_asus_pc39(void)
-{
-	ir_unregister_map(&asus_pc39_map);
-}
-
-module_init(init_rc_map_asus_pc39)
-module_exit(exit_rc_map_asus_pc39)
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-ati-tv-wonder-hd-600.c linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-ati-tv-wonder-hd-600.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-ati-tv-wonder-hd-600.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-ati-tv-wonder-hd-600.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,69 +0,0 @@
-/* ati-tv-wonder-hd-600.h - Keytable for ati_tv_wonder_hd_600 Remote Controller
- *
- * keymap imported from ir-keymaps.c
- *
- * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
-
-/* ATI TV Wonder HD 600 USB
-   Devin Heitmueller <devin.heitmueller@gmail.com>
- */
-
-static struct ir_scancode ati_tv_wonder_hd_600[] = {
-	{ 0x00, KEY_RECORD},		/* Row 1 */
-	{ 0x01, KEY_PLAYPAUSE},
-	{ 0x02, KEY_STOP},
-	{ 0x03, KEY_POWER},
-	{ 0x04, KEY_PREVIOUS},	/* Row 2 */
-	{ 0x05, KEY_REWIND},
-	{ 0x06, KEY_FORWARD},
-	{ 0x07, KEY_NEXT},
-	{ 0x08, KEY_EPG},		/* Row 3 */
-	{ 0x09, KEY_HOME},
-	{ 0x0a, KEY_MENU},
-	{ 0x0b, KEY_CHANNELUP},
-	{ 0x0c, KEY_BACK},		/* Row 4 */
-	{ 0x0d, KEY_UP},
-	{ 0x0e, KEY_INFO},
-	{ 0x0f, KEY_CHANNELDOWN},
-	{ 0x10, KEY_LEFT},		/* Row 5 */
-	{ 0x11, KEY_SELECT},
-	{ 0x12, KEY_RIGHT},
-	{ 0x13, KEY_VOLUMEUP},
-	{ 0x14, KEY_LAST},		/* Row 6 */
-	{ 0x15, KEY_DOWN},
-	{ 0x16, KEY_MUTE},
-	{ 0x17, KEY_VOLUMEDOWN},
-};
-
-static struct rc_keymap ati_tv_wonder_hd_600_map = {
-	.map = {
-		.scan    = ati_tv_wonder_hd_600,
-		.size    = ARRAY_SIZE(ati_tv_wonder_hd_600),
-		.ir_type = IR_TYPE_UNKNOWN,	/* Legacy IR type */
-		.name    = RC_MAP_ATI_TV_WONDER_HD_600,
-	}
-};
-
-static int __init init_rc_map_ati_tv_wonder_hd_600(void)
-{
-	return ir_register_map(&ati_tv_wonder_hd_600_map);
-}
-
-static void __exit exit_rc_map_ati_tv_wonder_hd_600(void)
-{
-	ir_unregister_map(&ati_tv_wonder_hd_600_map);
-}
-
-module_init(init_rc_map_ati_tv_wonder_hd_600)
-module_exit(exit_rc_map_ati_tv_wonder_hd_600)
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-avermedia-a16d.c linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-avermedia-a16d.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-avermedia-a16d.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-avermedia-a16d.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,75 +0,0 @@
-/* avermedia-a16d.h - Keytable for avermedia_a16d Remote Controller
- *
- * keymap imported from ir-keymaps.c
- *
- * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
-
-static struct ir_scancode avermedia_a16d[] = {
-	{ 0x20, KEY_LIST},
-	{ 0x00, KEY_POWER},
-	{ 0x28, KEY_1},
-	{ 0x18, KEY_2},
-	{ 0x38, KEY_3},
-	{ 0x24, KEY_4},
-	{ 0x14, KEY_5},
-	{ 0x34, KEY_6},
-	{ 0x2c, KEY_7},
-	{ 0x1c, KEY_8},
-	{ 0x3c, KEY_9},
-	{ 0x12, KEY_SUBTITLE},
-	{ 0x22, KEY_0},
-	{ 0x32, KEY_REWIND},
-	{ 0x3a, KEY_SHUFFLE},
-	{ 0x02, KEY_PRINT},
-	{ 0x11, KEY_CHANNELDOWN},
-	{ 0x31, KEY_CHANNELUP},
-	{ 0x0c, KEY_ZOOM},
-	{ 0x1e, KEY_VOLUMEDOWN},
-	{ 0x3e, KEY_VOLUMEUP},
-	{ 0x0a, KEY_MUTE},
-	{ 0x04, KEY_AUDIO},
-	{ 0x26, KEY_RECORD},
-	{ 0x06, KEY_PLAY},
-	{ 0x36, KEY_STOP},
-	{ 0x16, KEY_PAUSE},
-	{ 0x2e, KEY_REWIND},
-	{ 0x0e, KEY_FASTFORWARD},
-	{ 0x30, KEY_TEXT},
-	{ 0x21, KEY_GREEN},
-	{ 0x01, KEY_BLUE},
-	{ 0x08, KEY_EPG},
-	{ 0x2a, KEY_MENU},
-};
-
-static struct rc_keymap avermedia_a16d_map = {
-	.map = {
-		.scan    = avermedia_a16d,
-		.size    = ARRAY_SIZE(avermedia_a16d),
-		.ir_type = IR_TYPE_UNKNOWN,	/* Legacy IR type */
-		.name    = RC_MAP_AVERMEDIA_A16D,
-	}
-};
-
-static int __init init_rc_map_avermedia_a16d(void)
-{
-	return ir_register_map(&avermedia_a16d_map);
-}
-
-static void __exit exit_rc_map_avermedia_a16d(void)
-{
-	ir_unregister_map(&avermedia_a16d_map);
-}
-
-module_init(init_rc_map_avermedia_a16d)
-module_exit(exit_rc_map_avermedia_a16d)
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-avermedia.c linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-avermedia.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-avermedia.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-avermedia.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,86 +0,0 @@
-/* avermedia.h - Keytable for avermedia Remote Controller
- *
- * keymap imported from ir-keymaps.c
- *
- * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
-
-/* Alex Hermann <gaaf@gmx.net> */
-
-static struct ir_scancode avermedia[] = {
-	{ 0x28, KEY_1 },
-	{ 0x18, KEY_2 },
-	{ 0x38, KEY_3 },
-	{ 0x24, KEY_4 },
-	{ 0x14, KEY_5 },
-	{ 0x34, KEY_6 },
-	{ 0x2c, KEY_7 },
-	{ 0x1c, KEY_8 },
-	{ 0x3c, KEY_9 },
-	{ 0x22, KEY_0 },
-
-	{ 0x20, KEY_TV },		/* TV/FM */
-	{ 0x10, KEY_CD },		/* CD */
-	{ 0x30, KEY_TEXT },		/* TELETEXT */
-	{ 0x00, KEY_POWER },		/* POWER */
-
-	{ 0x08, KEY_VIDEO },		/* VIDEO */
-	{ 0x04, KEY_AUDIO },		/* AUDIO */
-	{ 0x0c, KEY_ZOOM },		/* FULL SCREEN */
-
-	{ 0x12, KEY_SUBTITLE },		/* DISPLAY */
-	{ 0x32, KEY_REWIND },		/* LOOP	*/
-	{ 0x02, KEY_PRINT },		/* PREVIEW */
-
-	{ 0x2a, KEY_SEARCH },		/* AUTOSCAN */
-	{ 0x1a, KEY_SLEEP },		/* FREEZE */
-	{ 0x3a, KEY_CAMERA },		/* SNAPSHOT */
-	{ 0x0a, KEY_MUTE },		/* MUTE */
-
-	{ 0x26, KEY_RECORD },		/* RECORD */
-	{ 0x16, KEY_PAUSE },		/* PAUSE */
-	{ 0x36, KEY_STOP },		/* STOP */
-	{ 0x06, KEY_PLAY },		/* PLAY */
-
-	{ 0x2e, KEY_RED },		/* RED */
-	{ 0x21, KEY_GREEN },		/* GREEN */
-	{ 0x0e, KEY_YELLOW },		/* YELLOW */
-	{ 0x01, KEY_BLUE },		/* BLUE */
-
-	{ 0x1e, KEY_VOLUMEDOWN },	/* VOLUME- */
-	{ 0x3e, KEY_VOLUMEUP },		/* VOLUME+ */
-	{ 0x11, KEY_CHANNELDOWN },	/* CHANNEL/PAGE- */
-	{ 0x31, KEY_CHANNELUP }		/* CHANNEL/PAGE+ */
-};
-
-static struct rc_keymap avermedia_map = {
-	.map = {
-		.scan    = avermedia,
-		.size    = ARRAY_SIZE(avermedia),
-		.ir_type = IR_TYPE_UNKNOWN,	/* Legacy IR type */
-		.name    = RC_MAP_AVERMEDIA,
-	}
-};
-
-static int __init init_rc_map_avermedia(void)
-{
-	return ir_register_map(&avermedia_map);
-}
-
-static void __exit exit_rc_map_avermedia(void)
-{
-	ir_unregister_map(&avermedia_map);
-}
-
-module_init(init_rc_map_avermedia)
-module_exit(exit_rc_map_avermedia)
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-avermedia-cardbus.c linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-avermedia-cardbus.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-avermedia-cardbus.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-avermedia-cardbus.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,97 +0,0 @@
-/* avermedia-cardbus.h - Keytable for avermedia_cardbus Remote Controller
- *
- * keymap imported from ir-keymaps.c
- *
- * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
-
-/* Oldrich Jedlicka <oldium.pro@seznam.cz> */
-
-static struct ir_scancode avermedia_cardbus[] = {
-	{ 0x00, KEY_POWER },
-	{ 0x01, KEY_TUNER },		/* TV/FM */
-	{ 0x03, KEY_TEXT },		/* Teletext */
-	{ 0x04, KEY_EPG },
-	{ 0x05, KEY_1 },
-	{ 0x06, KEY_2 },
-	{ 0x07, KEY_3 },
-	{ 0x08, KEY_AUDIO },
-	{ 0x09, KEY_4 },
-	{ 0x0a, KEY_5 },
-	{ 0x0b, KEY_6 },
-	{ 0x0c, KEY_ZOOM },		/* Full screen */
-	{ 0x0d, KEY_7 },
-	{ 0x0e, KEY_8 },
-	{ 0x0f, KEY_9 },
-	{ 0x10, KEY_PAGEUP },		/* 16-CH PREV */
-	{ 0x11, KEY_0 },
-	{ 0x12, KEY_INFO },
-	{ 0x13, KEY_AGAIN },		/* CH RTN - channel return */
-	{ 0x14, KEY_MUTE },
-	{ 0x15, KEY_EDIT },		/* Autoscan */
-	{ 0x17, KEY_SAVE },		/* Screenshot */
-	{ 0x18, KEY_PLAYPAUSE },
-	{ 0x19, KEY_RECORD },
-	{ 0x1a, KEY_PLAY },
-	{ 0x1b, KEY_STOP },
-	{ 0x1c, KEY_FASTFORWARD },
-	{ 0x1d, KEY_REWIND },
-	{ 0x1e, KEY_VOLUMEDOWN },
-	{ 0x1f, KEY_VOLUMEUP },
-	{ 0x22, KEY_SLEEP },		/* Sleep */
-	{ 0x23, KEY_ZOOM },		/* Aspect */
-	{ 0x26, KEY_SCREEN },		/* Pos */
-	{ 0x27, KEY_ANGLE },		/* Size */
-	{ 0x28, KEY_SELECT },		/* Select */
-	{ 0x29, KEY_BLUE },		/* Blue/Picture */
-	{ 0x2a, KEY_BACKSPACE },	/* Back */
-	{ 0x2b, KEY_MEDIA },		/* PIP (Picture-in-picture) */
-	{ 0x2c, KEY_DOWN },
-	{ 0x2e, KEY_DOT },
-	{ 0x2f, KEY_TV },		/* Live TV */
-	{ 0x32, KEY_LEFT },
-	{ 0x33, KEY_CLEAR },		/* Clear */
-	{ 0x35, KEY_RED },		/* Red/TV */
-	{ 0x36, KEY_UP },
-	{ 0x37, KEY_HOME },		/* Home */
-	{ 0x39, KEY_GREEN },		/* Green/Video */
-	{ 0x3d, KEY_YELLOW },		/* Yellow/Music */
-	{ 0x3e, KEY_OK },		/* Ok */
-	{ 0x3f, KEY_RIGHT },
-	{ 0x40, KEY_NEXT },		/* Next */
-	{ 0x41, KEY_PREVIOUS },		/* Previous */
-	{ 0x42, KEY_CHANNELDOWN },	/* Channel down */
-	{ 0x43, KEY_CHANNELUP },	/* Channel up */
-};
-
-static struct rc_keymap avermedia_cardbus_map = {
-	.map = {
-		.scan    = avermedia_cardbus,
-		.size    = ARRAY_SIZE(avermedia_cardbus),
-		.ir_type = IR_TYPE_UNKNOWN,	/* Legacy IR type */
-		.name    = RC_MAP_AVERMEDIA_CARDBUS,
-	}
-};
-
-static int __init init_rc_map_avermedia_cardbus(void)
-{
-	return ir_register_map(&avermedia_cardbus_map);
-}
-
-static void __exit exit_rc_map_avermedia_cardbus(void)
-{
-	ir_unregister_map(&avermedia_cardbus_map);
-}
-
-module_init(init_rc_map_avermedia_cardbus)
-module_exit(exit_rc_map_avermedia_cardbus)
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-avermedia-dvbt.c linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-avermedia-dvbt.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-avermedia-dvbt.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-avermedia-dvbt.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,78 +0,0 @@
-/* avermedia-dvbt.h - Keytable for avermedia_dvbt Remote Controller
- *
- * keymap imported from ir-keymaps.c
- *
- * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
-
-/* Matt Jesson <dvb@jesson.eclipse.co.uk */
-
-static struct ir_scancode avermedia_dvbt[] = {
-	{ 0x28, KEY_0 },		/* '0' / 'enter' */
-	{ 0x22, KEY_1 },		/* '1' */
-	{ 0x12, KEY_2 },		/* '2' / 'up arrow' */
-	{ 0x32, KEY_3 },		/* '3' */
-	{ 0x24, KEY_4 },		/* '4' / 'left arrow' */
-	{ 0x14, KEY_5 },		/* '5' */
-	{ 0x34, KEY_6 },		/* '6' / 'right arrow' */
-	{ 0x26, KEY_7 },		/* '7' */
-	{ 0x16, KEY_8 },		/* '8' / 'down arrow' */
-	{ 0x36, KEY_9 },		/* '9' */
-
-	{ 0x20, KEY_LIST },		/* 'source' */
-	{ 0x10, KEY_TEXT },		/* 'teletext' */
-	{ 0x00, KEY_POWER },		/* 'power' */
-	{ 0x04, KEY_AUDIO },		/* 'audio' */
-	{ 0x06, KEY_ZOOM },		/* 'full screen' */
-	{ 0x18, KEY_VIDEO },		/* 'display' */
-	{ 0x38, KEY_SEARCH },		/* 'loop' */
-	{ 0x08, KEY_INFO },		/* 'preview' */
-	{ 0x2a, KEY_REWIND },		/* 'backward <<' */
-	{ 0x1a, KEY_FASTFORWARD },	/* 'forward >>' */
-	{ 0x3a, KEY_RECORD },		/* 'capture' */
-	{ 0x0a, KEY_MUTE },		/* 'mute' */
-	{ 0x2c, KEY_RECORD },		/* 'record' */
-	{ 0x1c, KEY_PAUSE },		/* 'pause' */
-	{ 0x3c, KEY_STOP },		/* 'stop' */
-	{ 0x0c, KEY_PLAY },		/* 'play' */
-	{ 0x2e, KEY_RED },		/* 'red' */
-	{ 0x01, KEY_BLUE },		/* 'blue' / 'cancel' */
-	{ 0x0e, KEY_YELLOW },		/* 'yellow' / 'ok' */
-	{ 0x21, KEY_GREEN },		/* 'green' */
-	{ 0x11, KEY_CHANNELDOWN },	/* 'channel -' */
-	{ 0x31, KEY_CHANNELUP },	/* 'channel +' */
-	{ 0x1e, KEY_VOLUMEDOWN },	/* 'volume -' */
-	{ 0x3e, KEY_VOLUMEUP },		/* 'volume +' */
-};
-
-static struct rc_keymap avermedia_dvbt_map = {
-	.map = {
-		.scan    = avermedia_dvbt,
-		.size    = ARRAY_SIZE(avermedia_dvbt),
-		.ir_type = IR_TYPE_UNKNOWN,	/* Legacy IR type */
-		.name    = RC_MAP_AVERMEDIA_DVBT,
-	}
-};
-
-static int __init init_rc_map_avermedia_dvbt(void)
-{
-	return ir_register_map(&avermedia_dvbt_map);
-}
-
-static void __exit exit_rc_map_avermedia_dvbt(void)
-{
-	ir_unregister_map(&avermedia_dvbt_map);
-}
-
-module_init(init_rc_map_avermedia_dvbt)
-module_exit(exit_rc_map_avermedia_dvbt)
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-avermedia-m135a.c linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-avermedia-m135a.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-avermedia-m135a.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-avermedia-m135a.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,147 +0,0 @@
-/* avermedia-m135a.c - Keytable for Avermedia M135A Remote Controllers
- *
- * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
- * Copyright (c) 2010 by Herton Ronaldo Krzesinski <herton@mandriva.com.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.
- */
-
-#include <media/rc-map.h>
-
-/*
- * Avermedia M135A with RM-JX and RM-K6 remote controls
- *
- * On Avermedia M135A with IR model RM-JX, the same codes exist on both
- * Positivo (BR) and original IR, initial version and remote control codes
- * added by Mauro Carvalho Chehab <mchehab@infradead.org>
- *
- * Positivo also ships Avermedia M135A with model RM-K6, extra control
- * codes added by Herton Ronaldo Krzesinski <herton@mandriva.com.br>
- */
-
-static struct ir_scancode avermedia_m135a[] = {
-	/* RM-JX */
-	{ 0x0200, KEY_POWER2 },
-	{ 0x022e, KEY_DOT },		/* '.' */
-	{ 0x0201, KEY_MODE },		/* TV/FM or SOURCE */
-
-	{ 0x0205, KEY_1 },
-	{ 0x0206, KEY_2 },
-	{ 0x0207, KEY_3 },
-	{ 0x0209, KEY_4 },
-	{ 0x020a, KEY_5 },
-	{ 0x020b, KEY_6 },
-	{ 0x020d, KEY_7 },
-	{ 0x020e, KEY_8 },
-	{ 0x020f, KEY_9 },
-	{ 0x0211, KEY_0 },
-
-	{ 0x0213, KEY_RIGHT },		/* -> or L */
-	{ 0x0212, KEY_LEFT },		/* <- or R */
-
-	{ 0x0217, KEY_SLEEP },		/* Capturar Imagem or Snapshot */
-	{ 0x0210, KEY_SHUFFLE },	/* Amostra or 16 chan prev */
-
-	{ 0x0303, KEY_CHANNELUP },
-	{ 0x0302, KEY_CHANNELDOWN },
-	{ 0x021f, KEY_VOLUMEUP },
-	{ 0x021e, KEY_VOLUMEDOWN },
-	{ 0x020c, KEY_ENTER },		/* Full Screen */
-
-	{ 0x0214, KEY_MUTE },
-	{ 0x0208, KEY_AUDIO },
-
-	{ 0x0203, KEY_TEXT },		/* Teletext */
-	{ 0x0204, KEY_EPG },
-	{ 0x022b, KEY_TV2 },		/* TV2 or PIP */
-
-	{ 0x021d, KEY_RED },
-	{ 0x021c, KEY_YELLOW },
-	{ 0x0301, KEY_GREEN },
-	{ 0x0300, KEY_BLUE },
-
-	{ 0x021a, KEY_PLAYPAUSE },
-	{ 0x0219, KEY_RECORD },
-	{ 0x0218, KEY_PLAY },
-	{ 0x021b, KEY_STOP },
-
-	/* RM-K6 */
-	{ 0x0401, KEY_POWER2 },
-	{ 0x0406, KEY_MUTE },
-	{ 0x0408, KEY_MODE },     /* TV/FM */
-
-	{ 0x0409, KEY_1 },
-	{ 0x040a, KEY_2 },
-	{ 0x040b, KEY_3 },
-	{ 0x040c, KEY_4 },
-	{ 0x040d, KEY_5 },
-	{ 0x040e, KEY_6 },
-	{ 0x040f, KEY_7 },
-	{ 0x0410, KEY_8 },
-	{ 0x0411, KEY_9 },
-	{ 0x044c, KEY_DOT },      /* '.' */
-	{ 0x0412, KEY_0 },
-	{ 0x0407, KEY_REFRESH },  /* Refresh/Reload */
-
-	{ 0x0413, KEY_AUDIO },
-	{ 0x0440, KEY_SCREEN },   /* Full Screen toggle */
-	{ 0x0441, KEY_HOME },
-	{ 0x0442, KEY_BACK },
-	{ 0x0447, KEY_UP },
-	{ 0x0448, KEY_DOWN },
-	{ 0x0449, KEY_LEFT },
-	{ 0x044a, KEY_RIGHT },
-	{ 0x044b, KEY_OK },
-	{ 0x0404, KEY_VOLUMEUP },
-	{ 0x0405, KEY_VOLUMEDOWN },
-	{ 0x0402, KEY_CHANNELUP },
-	{ 0x0403, KEY_CHANNELDOWN },
-
-	{ 0x0443, KEY_RED },
-	{ 0x0444, KEY_GREEN },
-	{ 0x0445, KEY_YELLOW },
-	{ 0x0446, KEY_BLUE },
-
-	{ 0x0414, KEY_TEXT },
-	{ 0x0415, KEY_EPG },
-	{ 0x041a, KEY_TV2 },      /* PIP */
-	{ 0x041b, KEY_MHP },      /* Snapshot */
-
-	{ 0x0417, KEY_RECORD },
-	{ 0x0416, KEY_PLAYPAUSE },
-	{ 0x0418, KEY_STOP },
-	{ 0x0419, KEY_PAUSE },
-
-	{ 0x041f, KEY_PREVIOUS },
-	{ 0x041c, KEY_REWIND },
-	{ 0x041d, KEY_FORWARD },
-	{ 0x041e, KEY_NEXT },
-};
-
-static struct rc_keymap avermedia_m135a_map = {
-	.map = {
-		.scan    = avermedia_m135a,
-		.size    = ARRAY_SIZE(avermedia_m135a),
-		.ir_type = IR_TYPE_NEC,
-		.name    = RC_MAP_AVERMEDIA_M135A,
-	}
-};
-
-static int __init init_rc_map_avermedia_m135a(void)
-{
-	return ir_register_map(&avermedia_m135a_map);
-}
-
-static void __exit exit_rc_map_avermedia_m135a(void)
-{
-	ir_unregister_map(&avermedia_m135a_map);
-}
-
-module_init(init_rc_map_avermedia_m135a)
-module_exit(exit_rc_map_avermedia_m135a)
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-avermedia-m733a-rm-k6.c linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-avermedia-m733a-rm-k6.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-avermedia-m733a-rm-k6.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-avermedia-m733a-rm-k6.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,95 +0,0 @@
-/* avermedia-m733a-rm-k6.h - Keytable for avermedia_m733a_rm_k6 Remote Controller
- *
- * Copyright (c) 2010 by Herton Ronaldo Krzesinski <herton@mandriva.com.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.
- */
-
-#include <media/rc-map.h>
-
-/*
- * Avermedia M733A with IR model RM-K6
- * This is the stock remote controller used with Positivo machines with M733A
- * Herton Ronaldo Krzesinski <herton@mandriva.com.br>
- */
-
-static struct ir_scancode avermedia_m733a_rm_k6[] = {
-	{ 0x0401, KEY_POWER2 },
-	{ 0x0406, KEY_MUTE },
-	{ 0x0408, KEY_MODE },     /* TV/FM */
-
-	{ 0x0409, KEY_1 },
-	{ 0x040a, KEY_2 },
-	{ 0x040b, KEY_3 },
-	{ 0x040c, KEY_4 },
-	{ 0x040d, KEY_5 },
-	{ 0x040e, KEY_6 },
-	{ 0x040f, KEY_7 },
-	{ 0x0410, KEY_8 },
-	{ 0x0411, KEY_9 },
-	{ 0x044c, KEY_DOT },      /* '.' */
-	{ 0x0412, KEY_0 },
-	{ 0x0407, KEY_REFRESH },  /* Refresh/Reload */
-
-	{ 0x0413, KEY_AUDIO },
-	{ 0x0440, KEY_SCREEN },   /* Full Screen toggle */
-	{ 0x0441, KEY_HOME },
-	{ 0x0442, KEY_BACK },
-	{ 0x0447, KEY_UP },
-	{ 0x0448, KEY_DOWN },
-	{ 0x0449, KEY_LEFT },
-	{ 0x044a, KEY_RIGHT },
-	{ 0x044b, KEY_OK },
-	{ 0x0404, KEY_VOLUMEUP },
-	{ 0x0405, KEY_VOLUMEDOWN },
-	{ 0x0402, KEY_CHANNELUP },
-	{ 0x0403, KEY_CHANNELDOWN },
-
-	{ 0x0443, KEY_RED },
-	{ 0x0444, KEY_GREEN },
-	{ 0x0445, KEY_YELLOW },
-	{ 0x0446, KEY_BLUE },
-
-	{ 0x0414, KEY_TEXT },
-	{ 0x0415, KEY_EPG },
-	{ 0x041a, KEY_TV2 },      /* PIP */
-	{ 0x041b, KEY_MHP },      /* Snapshot */
-
-	{ 0x0417, KEY_RECORD },
-	{ 0x0416, KEY_PLAYPAUSE },
-	{ 0x0418, KEY_STOP },
-	{ 0x0419, KEY_PAUSE },
-
-	{ 0x041f, KEY_PREVIOUS },
-	{ 0x041c, KEY_REWIND },
-	{ 0x041d, KEY_FORWARD },
-	{ 0x041e, KEY_NEXT },
-};
-
-static struct rc_keymap avermedia_m733a_rm_k6_map = {
-	.map = {
-		.scan    = avermedia_m733a_rm_k6,
-		.size    = ARRAY_SIZE(avermedia_m733a_rm_k6),
-		.ir_type = IR_TYPE_NEC,
-		.name    = RC_MAP_AVERMEDIA_M733A_RM_K6,
-	}
-};
-
-static int __init init_rc_map_avermedia_m733a_rm_k6(void)
-{
-	return ir_register_map(&avermedia_m733a_rm_k6_map);
-}
-
-static void __exit exit_rc_map_avermedia_m733a_rm_k6(void)
-{
-	ir_unregister_map(&avermedia_m733a_rm_k6_map);
-}
-
-module_init(init_rc_map_avermedia_m733a_rm_k6)
-module_exit(exit_rc_map_avermedia_m733a_rm_k6)
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-avermedia-rm-ks.c linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-avermedia-rm-ks.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-avermedia-rm-ks.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-avermedia-rm-ks.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,79 +0,0 @@
-/*
- * AverMedia RM-KS remote controller keytable
- *
- * Copyright (C) 2010 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 <media/rc-map.h>
-
-/* Initial keytable is from Jose Alberto Reguero <jareguero@telefonica.net>
-   and Felipe Morales Moreno <felipe.morales.moreno@gmail.com> */
-/* FIXME: mappings are not 100% correct? */
-static struct ir_scancode avermedia_rm_ks[] = {
-	{ 0x0501, KEY_POWER2 },
-	{ 0x0502, KEY_CHANNELUP },
-	{ 0x0503, KEY_CHANNELDOWN },
-	{ 0x0504, KEY_VOLUMEUP },
-	{ 0x0505, KEY_VOLUMEDOWN },
-	{ 0x0506, KEY_MUTE },
-	{ 0x0507, KEY_RIGHT },
-	{ 0x0508, KEY_PROG1 },
-	{ 0x0509, KEY_1 },
-	{ 0x050a, KEY_2 },
-	{ 0x050b, KEY_3 },
-	{ 0x050c, KEY_4 },
-	{ 0x050d, KEY_5 },
-	{ 0x050e, KEY_6 },
-	{ 0x050f, KEY_7 },
-	{ 0x0510, KEY_8 },
-	{ 0x0511, KEY_9 },
-	{ 0x0512, KEY_0 },
-	{ 0x0513, KEY_AUDIO },
-	{ 0x0515, KEY_EPG },
-	{ 0x0516, KEY_PLAY },
-	{ 0x0517, KEY_RECORD },
-	{ 0x0518, KEY_STOP },
-	{ 0x051c, KEY_BACK },
-	{ 0x051d, KEY_FORWARD },
-	{ 0x054d, KEY_LEFT },
-	{ 0x0556, KEY_ZOOM },
-};
-
-static struct rc_keymap avermedia_rm_ks_map = {
-	.map = {
-		.scan    = avermedia_rm_ks,
-		.size    = ARRAY_SIZE(avermedia_rm_ks),
-		.ir_type = IR_TYPE_NEC,
-		.name    = RC_MAP_AVERMEDIA_RM_KS,
-	}
-};
-
-static int __init init_rc_map_avermedia_rm_ks(void)
-{
-	return ir_register_map(&avermedia_rm_ks_map);
-}
-
-static void __exit exit_rc_map_avermedia_rm_ks(void)
-{
-	ir_unregister_map(&avermedia_rm_ks_map);
-}
-
-module_init(init_rc_map_avermedia_rm_ks)
-module_exit(exit_rc_map_avermedia_rm_ks)
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-avertv-303.c linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-avertv-303.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-avertv-303.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-avertv-303.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,85 +0,0 @@
-/* avertv-303.h - Keytable for avertv_303 Remote Controller
- *
- * keymap imported from ir-keymaps.c
- *
- * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
-
-/* AVERTV STUDIO 303 Remote */
-
-static struct ir_scancode avertv_303[] = {
-	{ 0x2a, KEY_1 },
-	{ 0x32, KEY_2 },
-	{ 0x3a, KEY_3 },
-	{ 0x4a, KEY_4 },
-	{ 0x52, KEY_5 },
-	{ 0x5a, KEY_6 },
-	{ 0x6a, KEY_7 },
-	{ 0x72, KEY_8 },
-	{ 0x7a, KEY_9 },
-	{ 0x0e, KEY_0 },
-
-	{ 0x02, KEY_POWER },
-	{ 0x22, KEY_VIDEO },
-	{ 0x42, KEY_AUDIO },
-	{ 0x62, KEY_ZOOM },
-	{ 0x0a, KEY_TV },
-	{ 0x12, KEY_CD },
-	{ 0x1a, KEY_TEXT },
-
-	{ 0x16, KEY_SUBTITLE },
-	{ 0x1e, KEY_REWIND },
-	{ 0x06, KEY_PRINT },
-
-	{ 0x2e, KEY_SEARCH },
-	{ 0x36, KEY_SLEEP },
-	{ 0x3e, KEY_SHUFFLE },
-	{ 0x26, KEY_MUTE },
-
-	{ 0x4e, KEY_RECORD },
-	{ 0x56, KEY_PAUSE },
-	{ 0x5e, KEY_STOP },
-	{ 0x46, KEY_PLAY },
-
-	{ 0x6e, KEY_RED },
-	{ 0x0b, KEY_GREEN },
-	{ 0x66, KEY_YELLOW },
-	{ 0x03, KEY_BLUE },
-
-	{ 0x76, KEY_LEFT },
-	{ 0x7e, KEY_RIGHT },
-	{ 0x13, KEY_DOWN },
-	{ 0x1b, KEY_UP },
-};
-
-static struct rc_keymap avertv_303_map = {
-	.map = {
-		.scan    = avertv_303,
-		.size    = ARRAY_SIZE(avertv_303),
-		.ir_type = IR_TYPE_UNKNOWN,	/* Legacy IR type */
-		.name    = RC_MAP_AVERTV_303,
-	}
-};
-
-static int __init init_rc_map_avertv_303(void)
-{
-	return ir_register_map(&avertv_303_map);
-}
-
-static void __exit exit_rc_map_avertv_303(void)
-{
-	ir_unregister_map(&avertv_303_map);
-}
-
-module_init(init_rc_map_avertv_303)
-module_exit(exit_rc_map_avertv_303)
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-azurewave-ad-tu700.c linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-azurewave-ad-tu700.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-azurewave-ad-tu700.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-azurewave-ad-tu700.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,102 +0,0 @@
-/*
- * TwinHan AzureWave AD-TU700(704J) remote controller keytable
- *
- * Copyright (C) 2010 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 <media/rc-map.h>
-
-static struct ir_scancode azurewave_ad_tu700[] = {
-	{ 0x0000, KEY_TAB },             /* Tab */
-	{ 0x0001, KEY_2 },
-	{ 0x0002, KEY_CHANNELDOWN },
-	{ 0x0003, KEY_1 },
-	{ 0x0004, KEY_MENU },            /* Record List */
-	{ 0x0005, KEY_CHANNELUP },
-	{ 0x0006, KEY_3 },
-	{ 0x0007, KEY_SLEEP },           /* Hibernate */
-	{ 0x0008, KEY_VIDEO },           /* A/V */
-	{ 0x0009, KEY_4 },
-	{ 0x000a, KEY_VOLUMEDOWN },
-	{ 0x000c, KEY_CANCEL },          /* Cancel */
-	{ 0x000d, KEY_7 },
-	{ 0x000e, KEY_AGAIN },           /* Recall */
-	{ 0x000f, KEY_TEXT },            /* Teletext */
-	{ 0x0010, KEY_MUTE },
-	{ 0x0011, KEY_RECORD },
-	{ 0x0012, KEY_FASTFORWARD },     /* FF >> */
-	{ 0x0013, KEY_BACK },            /* Back */
-	{ 0x0014, KEY_PLAY },
-	{ 0x0015, KEY_0 },
-	{ 0x0016, KEY_POWER2 },          /* [red power button] */
-	{ 0x0017, KEY_FAVORITES },       /* Favorite List */
-	{ 0x0018, KEY_RED },
-	{ 0x0019, KEY_8 },
-	{ 0x001a, KEY_STOP },
-	{ 0x001b, KEY_9 },
-	{ 0x001c, KEY_EPG },             /* Info/EPG */
-	{ 0x001d, KEY_5 },
-	{ 0x001e, KEY_VOLUMEUP },
-	{ 0x001f, KEY_6 },
-	{ 0x0040, KEY_REWIND },          /* FR << */
-	{ 0x0041, KEY_PREVIOUS },        /* Replay */
-	{ 0x0042, KEY_NEXT },            /* Skip */
-	{ 0x0043, KEY_SUBTITLE },        /* Subtitle / CC */
-	{ 0x0045, KEY_KPPLUS },          /* Zoom+ */
-	{ 0x0046, KEY_KPMINUS },         /* Zoom- */
-	{ 0x0047, KEY_NEW },             /* PIP */
-	{ 0x0048, KEY_INFO },            /* Preview */
-	{ 0x0049, KEY_MODE },            /* L/R */
-	{ 0x004a, KEY_CLEAR },           /* Clear */
-	{ 0x004b, KEY_UP },              /* up arrow */
-	{ 0x004c, KEY_PAUSE },
-	{ 0x004d, KEY_ZOOM },            /* Full Screen */
-	{ 0x004e, KEY_LEFT },            /* left arrow */
-	{ 0x004f, KEY_OK },              /* Enter / ok */
-	{ 0x0050, KEY_LANGUAGE },        /* SAP */
-	{ 0x0051, KEY_DOWN },            /* down arrow */
-	{ 0x0052, KEY_RIGHT },           /* right arrow */
-	{ 0x0053, KEY_GREEN },
-	{ 0x0054, KEY_CAMERA },          /* Capture */
-	{ 0x005e, KEY_YELLOW },
-	{ 0x005f, KEY_BLUE },
-};
-
-static struct rc_keymap azurewave_ad_tu700_map = {
-	.map = {
-		.scan    = azurewave_ad_tu700,
-		.size    = ARRAY_SIZE(azurewave_ad_tu700),
-		.ir_type = IR_TYPE_NEC,
-		.name    = RC_MAP_AZUREWAVE_AD_TU700,
-	}
-};
-
-static int __init init_rc_map_azurewave_ad_tu700(void)
-{
-	return ir_register_map(&azurewave_ad_tu700_map);
-}
-
-static void __exit exit_rc_map_azurewave_ad_tu700(void)
-{
-	ir_unregister_map(&azurewave_ad_tu700_map);
-}
-
-module_init(init_rc_map_azurewave_ad_tu700)
-module_exit(exit_rc_map_azurewave_ad_tu700)
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-behold.c linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-behold.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-behold.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-behold.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,141 +0,0 @@
-/* behold.h - Keytable for behold Remote Controller
- *
- * keymap imported from ir-keymaps.c
- *
- * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
-
-/*
- * Igor Kuznetsov <igk72@ya.ru>
- * Andrey J. Melnikov <temnota@kmv.ru>
- *
- * Keytable is used by BeholdTV 60x series, M6 series at
- * least, and probably other cards too.
- * The "ascii-art picture" below (in comments, first row
- * is the keycode in hex, and subsequent row(s) shows
- * the button labels (several variants when appropriate)
- * helps to descide which keycodes to assign to the buttons.
- */
-
-static struct ir_scancode behold[] = {
-
-	/*  0x1c            0x12  *
-	 *  TV/FM          POWER  *
-	 *                        */
-	{ 0x1c, KEY_TUNER },	/* XXX KEY_TV / KEY_RADIO */
-	{ 0x12, KEY_POWER },
-
-	/*  0x01    0x02    0x03  *
-	 *   1       2       3    *
-	 *                        *
-	 *  0x04    0x05    0x06  *
-	 *   4       5       6    *
-	 *                        *
-	 *  0x07    0x08    0x09  *
-	 *   7       8       9    *
-	 *                        */
-	{ 0x01, KEY_1 },
-	{ 0x02, KEY_2 },
-	{ 0x03, KEY_3 },
-	{ 0x04, KEY_4 },
-	{ 0x05, KEY_5 },
-	{ 0x06, KEY_6 },
-	{ 0x07, KEY_7 },
-	{ 0x08, KEY_8 },
-	{ 0x09, KEY_9 },
-
-	/*  0x0a    0x00    0x17  *
-	 * RECALL    0      MODE  *
-	 *                        */
-	{ 0x0a, KEY_AGAIN },
-	{ 0x00, KEY_0 },
-	{ 0x17, KEY_MODE },
-
-	/*  0x14          0x10    *
-	 * ASPECT      FULLSCREEN *
-	 *                        */
-	{ 0x14, KEY_SCREEN },
-	{ 0x10, KEY_ZOOM },
-
-	/*          0x0b          *
-	 *           Up           *
-	 *                        *
-	 *  0x18    0x16    0x0c  *
-	 *  Left     Ok     Right *
-	 *                        *
-	 *         0x015          *
-	 *         Down           *
-	 *                        */
-	{ 0x0b, KEY_CHANNELUP },
-	{ 0x18, KEY_VOLUMEDOWN },
-	{ 0x16, KEY_OK },		/* XXX KEY_ENTER */
-	{ 0x0c, KEY_VOLUMEUP },
-	{ 0x15, KEY_CHANNELDOWN },
-
-	/*  0x11            0x0d  *
-	 *  MUTE            INFO  *
-	 *                        */
-	{ 0x11, KEY_MUTE },
-	{ 0x0d, KEY_INFO },
-
-	/*  0x0f    0x1b    0x1a  *
-	 * RECORD PLAY/PAUSE STOP *
-	 *                        *
-	 *  0x0e    0x1f    0x1e  *
-	 *TELETEXT  AUDIO  SOURCE *
-	 *           RED   YELLOW *
-	 *                        */
-	{ 0x0f, KEY_RECORD },
-	{ 0x1b, KEY_PLAYPAUSE },
-	{ 0x1a, KEY_STOP },
-	{ 0x0e, KEY_TEXT },
-	{ 0x1f, KEY_RED },	/*XXX KEY_AUDIO	*/
-	{ 0x1e, KEY_YELLOW },	/*XXX KEY_SOURCE	*/
-
-	/*  0x1d   0x13     0x19  *
-	 * SLEEP  PREVIEW   DVB   *
-	 *         GREEN    BLUE  *
-	 *                        */
-	{ 0x1d, KEY_SLEEP },
-	{ 0x13, KEY_GREEN },
-	{ 0x19, KEY_BLUE },	/* XXX KEY_SAT	*/
-
-	/*  0x58           0x5c   *
-	 * FREEZE        SNAPSHOT *
-	 *                        */
-	{ 0x58, KEY_SLOW },
-	{ 0x5c, KEY_CAMERA },
-
-};
-
-static struct rc_keymap behold_map = {
-	.map = {
-		.scan    = behold,
-		.size    = ARRAY_SIZE(behold),
-		.ir_type = IR_TYPE_UNKNOWN,	/* Legacy IR type */
-		.name    = RC_MAP_BEHOLD,
-	}
-};
-
-static int __init init_rc_map_behold(void)
-{
-	return ir_register_map(&behold_map);
-}
-
-static void __exit exit_rc_map_behold(void)
-{
-	ir_unregister_map(&behold_map);
-}
-
-module_init(init_rc_map_behold)
-module_exit(exit_rc_map_behold)
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-behold-columbus.c linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-behold-columbus.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-behold-columbus.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-behold-columbus.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,108 +0,0 @@
-/* behold-columbus.h - Keytable for behold_columbus Remote Controller
- *
- * keymap imported from ir-keymaps.c
- *
- * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
-
-/* Beholder Intl. Ltd. 2008
- * Dmitry Belimov d.belimov@google.com
- * Keytable is used by BeholdTV Columbus
- * The "ascii-art picture" below (in comments, first row
- * is the keycode in hex, and subsequent row(s) shows
- * the button labels (several variants when appropriate)
- * helps to descide which keycodes to assign to the buttons.
- */
-
-static struct ir_scancode behold_columbus[] = {
-
-	/*  0x13   0x11   0x1C   0x12  *
-	 *  Mute  Source  TV/FM  Power *
-	 *                             */
-
-	{ 0x13, KEY_MUTE },
-	{ 0x11, KEY_PROPS },
-	{ 0x1C, KEY_TUNER },	/* KEY_TV/KEY_RADIO	*/
-	{ 0x12, KEY_POWER },
-
-	/*  0x01    0x02    0x03  0x0D    *
-	 *   1       2       3   Stereo   *
-	 *                        	  *
-	 *  0x04    0x05    0x06  0x19    *
-	 *   4       5       6   Snapshot *
-	 *                        	  *
-	 *  0x07    0x08    0x09  0x10    *
-	 *   7       8       9    Zoom 	  *
-	 *                                */
-	{ 0x01, KEY_1 },
-	{ 0x02, KEY_2 },
-	{ 0x03, KEY_3 },
-	{ 0x0D, KEY_SETUP },	  /* Setup key */
-	{ 0x04, KEY_4 },
-	{ 0x05, KEY_5 },
-	{ 0x06, KEY_6 },
-	{ 0x19, KEY_CAMERA },	/* Snapshot key */
-	{ 0x07, KEY_7 },
-	{ 0x08, KEY_8 },
-	{ 0x09, KEY_9 },
-	{ 0x10, KEY_ZOOM },
-
-	/*  0x0A    0x00    0x0B       0x0C   *
-	 * RECALL    0    ChannelUp  VolumeUp *
-	 *                                    */
-	{ 0x0A, KEY_AGAIN },
-	{ 0x00, KEY_0 },
-	{ 0x0B, KEY_CHANNELUP },
-	{ 0x0C, KEY_VOLUMEUP },
-
-	/*   0x1B      0x1D      0x15        0x18     *
-	 * Timeshift  Record  ChannelDown  VolumeDown *
-	 *                                            */
-
-	{ 0x1B, KEY_TIME },
-	{ 0x1D, KEY_RECORD },
-	{ 0x15, KEY_CHANNELDOWN },
-	{ 0x18, KEY_VOLUMEDOWN },
-
-	/*   0x0E   0x1E     0x0F     0x1A  *
-	 *   Stop   Pause  Previouse  Next  *
-	 *                                  */
-
-	{ 0x0E, KEY_STOP },
-	{ 0x1E, KEY_PAUSE },
-	{ 0x0F, KEY_PREVIOUS },
-	{ 0x1A, KEY_NEXT },
-
-};
-
-static struct rc_keymap behold_columbus_map = {
-	.map = {
-		.scan    = behold_columbus,
-		.size    = ARRAY_SIZE(behold_columbus),
-		.ir_type = IR_TYPE_UNKNOWN,	/* Legacy IR type */
-		.name    = RC_MAP_BEHOLD_COLUMBUS,
-	}
-};
-
-static int __init init_rc_map_behold_columbus(void)
-{
-	return ir_register_map(&behold_columbus_map);
-}
-
-static void __exit exit_rc_map_behold_columbus(void)
-{
-	ir_unregister_map(&behold_columbus_map);
-}
-
-module_init(init_rc_map_behold_columbus)
-module_exit(exit_rc_map_behold_columbus)
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-budget-ci-old.c linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-budget-ci-old.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-budget-ci-old.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-budget-ci-old.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,92 +0,0 @@
-/* budget-ci-old.h - Keytable for budget_ci_old Remote Controller
- *
- * keymap imported from ir-keymaps.c
- *
- * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
-
-/* From reading the following remotes:
- * Zenith Universal 7 / TV Mode 807 / VCR Mode 837
- * Hauppauge (from NOVA-CI-s box product)
- * This is a "middle of the road" approach, differences are noted
- */
-
-static struct ir_scancode budget_ci_old[] = {
-	{ 0x00, KEY_0 },
-	{ 0x01, KEY_1 },
-	{ 0x02, KEY_2 },
-	{ 0x03, KEY_3 },
-	{ 0x04, KEY_4 },
-	{ 0x05, KEY_5 },
-	{ 0x06, KEY_6 },
-	{ 0x07, KEY_7 },
-	{ 0x08, KEY_8 },
-	{ 0x09, KEY_9 },
-	{ 0x0a, KEY_ENTER },
-	{ 0x0b, KEY_RED },
-	{ 0x0c, KEY_POWER },		/* RADIO on Hauppauge */
-	{ 0x0d, KEY_MUTE },
-	{ 0x0f, KEY_A },		/* TV on Hauppauge */
-	{ 0x10, KEY_VOLUMEUP },
-	{ 0x11, KEY_VOLUMEDOWN },
-	{ 0x14, KEY_B },
-	{ 0x1c, KEY_UP },
-	{ 0x1d, KEY_DOWN },
-	{ 0x1e, KEY_OPTION },		/* RESERVED on Hauppauge */
-	{ 0x1f, KEY_BREAK },
-	{ 0x20, KEY_CHANNELUP },
-	{ 0x21, KEY_CHANNELDOWN },
-	{ 0x22, KEY_PREVIOUS },		/* Prev Ch on Zenith, SOURCE on Hauppauge */
-	{ 0x24, KEY_RESTART },
-	{ 0x25, KEY_OK },
-	{ 0x26, KEY_CYCLEWINDOWS },	/* MINIMIZE on Hauppauge */
-	{ 0x28, KEY_ENTER },		/* VCR mode on Zenith */
-	{ 0x29, KEY_PAUSE },
-	{ 0x2b, KEY_RIGHT },
-	{ 0x2c, KEY_LEFT },
-	{ 0x2e, KEY_MENU },		/* FULL SCREEN on Hauppauge */
-	{ 0x30, KEY_SLOW },
-	{ 0x31, KEY_PREVIOUS },		/* VCR mode on Zenith */
-	{ 0x32, KEY_REWIND },
-	{ 0x34, KEY_FASTFORWARD },
-	{ 0x35, KEY_PLAY },
-	{ 0x36, KEY_STOP },
-	{ 0x37, KEY_RECORD },
-	{ 0x38, KEY_TUNER },		/* TV/VCR on Zenith */
-	{ 0x3a, KEY_C },
-	{ 0x3c, KEY_EXIT },
-	{ 0x3d, KEY_POWER2 },
-	{ 0x3e, KEY_TUNER },
-};
-
-static struct rc_keymap budget_ci_old_map = {
-	.map = {
-		.scan    = budget_ci_old,
-		.size    = ARRAY_SIZE(budget_ci_old),
-		.ir_type = IR_TYPE_UNKNOWN,	/* Legacy IR type */
-		.name    = RC_MAP_BUDGET_CI_OLD,
-	}
-};
-
-static int __init init_rc_map_budget_ci_old(void)
-{
-	return ir_register_map(&budget_ci_old_map);
-}
-
-static void __exit exit_rc_map_budget_ci_old(void)
-{
-	ir_unregister_map(&budget_ci_old_map);
-}
-
-module_init(init_rc_map_budget_ci_old)
-module_exit(exit_rc_map_budget_ci_old)
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-cinergy-1400.c linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-cinergy-1400.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-cinergy-1400.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-cinergy-1400.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,84 +0,0 @@
-/* cinergy-1400.h - Keytable for cinergy_1400 Remote Controller
- *
- * keymap imported from ir-keymaps.c
- *
- * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
-
-/* Cinergy 1400 DVB-T */
-
-static struct ir_scancode cinergy_1400[] = {
-	{ 0x01, KEY_POWER },
-	{ 0x02, KEY_1 },
-	{ 0x03, KEY_2 },
-	{ 0x04, KEY_3 },
-	{ 0x05, KEY_4 },
-	{ 0x06, KEY_5 },
-	{ 0x07, KEY_6 },
-	{ 0x08, KEY_7 },
-	{ 0x09, KEY_8 },
-	{ 0x0a, KEY_9 },
-	{ 0x0c, KEY_0 },
-
-	{ 0x0b, KEY_VIDEO },
-	{ 0x0d, KEY_REFRESH },
-	{ 0x0e, KEY_SELECT },
-	{ 0x0f, KEY_EPG },
-	{ 0x10, KEY_UP },
-	{ 0x11, KEY_LEFT },
-	{ 0x12, KEY_OK },
-	{ 0x13, KEY_RIGHT },
-	{ 0x14, KEY_DOWN },
-	{ 0x15, KEY_TEXT },
-	{ 0x16, KEY_INFO },
-
-	{ 0x17, KEY_RED },
-	{ 0x18, KEY_GREEN },
-	{ 0x19, KEY_YELLOW },
-	{ 0x1a, KEY_BLUE },
-
-	{ 0x1b, KEY_CHANNELUP },
-	{ 0x1c, KEY_VOLUMEUP },
-	{ 0x1d, KEY_MUTE },
-	{ 0x1e, KEY_VOLUMEDOWN },
-	{ 0x1f, KEY_CHANNELDOWN },
-
-	{ 0x40, KEY_PAUSE },
-	{ 0x4c, KEY_PLAY },
-	{ 0x58, KEY_RECORD },
-	{ 0x54, KEY_PREVIOUS },
-	{ 0x48, KEY_STOP },
-	{ 0x5c, KEY_NEXT },
-};
-
-static struct rc_keymap cinergy_1400_map = {
-	.map = {
-		.scan    = cinergy_1400,
-		.size    = ARRAY_SIZE(cinergy_1400),
-		.ir_type = IR_TYPE_UNKNOWN,	/* Legacy IR type */
-		.name    = RC_MAP_CINERGY_1400,
-	}
-};
-
-static int __init init_rc_map_cinergy_1400(void)
-{
-	return ir_register_map(&cinergy_1400_map);
-}
-
-static void __exit exit_rc_map_cinergy_1400(void)
-{
-	ir_unregister_map(&cinergy_1400_map);
-}
-
-module_init(init_rc_map_cinergy_1400)
-module_exit(exit_rc_map_cinergy_1400)
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-cinergy.c linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-cinergy.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-cinergy.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-cinergy.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,78 +0,0 @@
-/* cinergy.h - Keytable for cinergy Remote Controller
- *
- * keymap imported from ir-keymaps.c
- *
- * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
-
-static struct ir_scancode cinergy[] = {
-	{ 0x00, KEY_0 },
-	{ 0x01, KEY_1 },
-	{ 0x02, KEY_2 },
-	{ 0x03, KEY_3 },
-	{ 0x04, KEY_4 },
-	{ 0x05, KEY_5 },
-	{ 0x06, KEY_6 },
-	{ 0x07, KEY_7 },
-	{ 0x08, KEY_8 },
-	{ 0x09, KEY_9 },
-
-	{ 0x0a, KEY_POWER },
-	{ 0x0b, KEY_PROG1 },		/* app */
-	{ 0x0c, KEY_ZOOM },		/* zoom/fullscreen */
-	{ 0x0d, KEY_CHANNELUP },	/* channel */
-	{ 0x0e, KEY_CHANNELDOWN },	/* channel- */
-	{ 0x0f, KEY_VOLUMEUP },
-	{ 0x10, KEY_VOLUMEDOWN },
-	{ 0x11, KEY_TUNER },		/* AV */
-	{ 0x12, KEY_NUMLOCK },		/* -/-- */
-	{ 0x13, KEY_AUDIO },		/* audio */
-	{ 0x14, KEY_MUTE },
-	{ 0x15, KEY_UP },
-	{ 0x16, KEY_DOWN },
-	{ 0x17, KEY_LEFT },
-	{ 0x18, KEY_RIGHT },
-	{ 0x19, BTN_LEFT, },
-	{ 0x1a, BTN_RIGHT, },
-	{ 0x1b, KEY_WWW },		/* text */
-	{ 0x1c, KEY_REWIND },
-	{ 0x1d, KEY_FORWARD },
-	{ 0x1e, KEY_RECORD },
-	{ 0x1f, KEY_PLAY },
-	{ 0x20, KEY_PREVIOUSSONG },
-	{ 0x21, KEY_NEXTSONG },
-	{ 0x22, KEY_PAUSE },
-	{ 0x23, KEY_STOP },
-};
-
-static struct rc_keymap cinergy_map = {
-	.map = {
-		.scan    = cinergy,
-		.size    = ARRAY_SIZE(cinergy),
-		.ir_type = IR_TYPE_UNKNOWN,	/* Legacy IR type */
-		.name    = RC_MAP_CINERGY,
-	}
-};
-
-static int __init init_rc_map_cinergy(void)
-{
-	return ir_register_map(&cinergy_map);
-}
-
-static void __exit exit_rc_map_cinergy(void)
-{
-	ir_unregister_map(&cinergy_map);
-}
-
-module_init(init_rc_map_cinergy)
-module_exit(exit_rc_map_cinergy)
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-dib0700-nec.c linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-dib0700-nec.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-dib0700-nec.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-dib0700-nec.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,124 +0,0 @@
-/* rc-dvb0700-big.c - Keytable for devices in dvb0700
- *
- * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
- *
- * TODO: This table is a real mess, as it merges RC codes from several
- * devices into a big table. It also has both RC-5 and NEC codes inside.
- * It should be broken into small tables, and the protocols should properly
- * be indentificated.
- *
- * The table were imported from dib0700_devices.c.
- *
- * 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 <media/rc-map.h>
-
-static struct ir_scancode dib0700_nec_table[] = {
-	/* Key codes for the Pixelview SBTVD remote */
-	{ 0x8613, KEY_MUTE },
-	{ 0x8612, KEY_POWER },
-	{ 0x8601, KEY_1 },
-	{ 0x8602, KEY_2 },
-	{ 0x8603, KEY_3 },
-	{ 0x8604, KEY_4 },
-	{ 0x8605, KEY_5 },
-	{ 0x8606, KEY_6 },
-	{ 0x8607, KEY_7 },
-	{ 0x8608, KEY_8 },
-	{ 0x8609, KEY_9 },
-	{ 0x8600, KEY_0 },
-	{ 0x860d, KEY_CHANNELUP },
-	{ 0x8619, KEY_CHANNELDOWN },
-	{ 0x8610, KEY_VOLUMEUP },
-	{ 0x860c, KEY_VOLUMEDOWN },
-
-	{ 0x860a, KEY_CAMERA },
-	{ 0x860b, KEY_ZOOM },
-	{ 0x861b, KEY_BACKSPACE },
-	{ 0x8615, KEY_ENTER },
-
-	{ 0x861d, KEY_UP },
-	{ 0x861e, KEY_DOWN },
-	{ 0x860e, KEY_LEFT },
-	{ 0x860f, KEY_RIGHT },
-
-	{ 0x8618, KEY_RECORD },
-	{ 0x861a, KEY_STOP },
-
-	/* Key codes for the EvolutePC TVWay+ remote */
-	{ 0x7a00, KEY_MENU },
-	{ 0x7a01, KEY_RECORD },
-	{ 0x7a02, KEY_PLAY },
-	{ 0x7a03, KEY_STOP },
-	{ 0x7a10, KEY_CHANNELUP },
-	{ 0x7a11, KEY_CHANNELDOWN },
-	{ 0x7a12, KEY_VOLUMEUP },
-	{ 0x7a13, KEY_VOLUMEDOWN },
-	{ 0x7a40, KEY_POWER },
-	{ 0x7a41, KEY_MUTE },
-
-	/* Key codes for the Elgato EyeTV Diversity silver remote */
-	{ 0x4501, KEY_POWER },
-	{ 0x4502, KEY_MUTE },
-	{ 0x4503, KEY_1 },
-	{ 0x4504, KEY_2 },
-	{ 0x4505, KEY_3 },
-	{ 0x4506, KEY_4 },
-	{ 0x4507, KEY_5 },
-	{ 0x4508, KEY_6 },
-	{ 0x4509, KEY_7 },
-	{ 0x450a, KEY_8 },
-	{ 0x450b, KEY_9 },
-	{ 0x450c, KEY_LAST },
-	{ 0x450d, KEY_0 },
-	{ 0x450e, KEY_ENTER },
-	{ 0x450f, KEY_RED },
-	{ 0x4510, KEY_CHANNELUP },
-	{ 0x4511, KEY_GREEN },
-	{ 0x4512, KEY_VOLUMEDOWN },
-	{ 0x4513, KEY_OK },
-	{ 0x4514, KEY_VOLUMEUP },
-	{ 0x4515, KEY_YELLOW },
-	{ 0x4516, KEY_CHANNELDOWN },
-	{ 0x4517, KEY_BLUE },
-	{ 0x4518, KEY_LEFT }, /* Skip backwards */
-	{ 0x4519, KEY_PLAYPAUSE },
-	{ 0x451a, KEY_RIGHT }, /* Skip forward */
-	{ 0x451b, KEY_REWIND },
-	{ 0x451c, KEY_L }, /* Live */
-	{ 0x451d, KEY_FASTFORWARD },
-	{ 0x451e, KEY_STOP }, /* 'Reveal' for Teletext */
-	{ 0x451f, KEY_MENU }, /* KEY_TEXT for Teletext */
-	{ 0x4540, KEY_RECORD }, /* Font 'Size' for Teletext */
-	{ 0x4541, KEY_SCREEN }, /*  Full screen toggle, 'Hold' for Teletext */
-	{ 0x4542, KEY_SELECT }, /* Select video input, 'Select' for Teletext */
-};
-
-static struct rc_keymap dib0700_nec_map = {
-	.map = {
-		.scan    = dib0700_nec_table,
-		.size    = ARRAY_SIZE(dib0700_nec_table),
-		.ir_type = IR_TYPE_NEC,
-		.name    = RC_MAP_DIB0700_NEC_TABLE,
-	}
-};
-
-static int __init init_rc_map(void)
-{
-	return ir_register_map(&dib0700_nec_map);
-}
-
-static void __exit exit_rc_map(void)
-{
-	ir_unregister_map(&dib0700_nec_map);
-}
-
-module_init(init_rc_map)
-module_exit(exit_rc_map)
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-dib0700-rc5.c linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-dib0700-rc5.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-dib0700-rc5.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-dib0700-rc5.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,235 +0,0 @@
-/* rc-dvb0700-big.c - Keytable for devices in dvb0700
- *
- * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
- *
- * TODO: This table is a real mess, as it merges RC codes from several
- * devices into a big table. It also has both RC-5 and NEC codes inside.
- * It should be broken into small tables, and the protocols should properly
- * be indentificated.
- *
- * The table were imported from dib0700_devices.c.
- *
- * 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 <media/rc-map.h>
-
-static struct ir_scancode dib0700_rc5_table[] = {
-	/* Key codes for the tiny Pinnacle remote*/
-	{ 0x0700, KEY_MUTE },
-	{ 0x0701, KEY_MENU }, /* Pinnacle logo */
-	{ 0x0739, KEY_POWER },
-	{ 0x0703, KEY_VOLUMEUP },
-	{ 0x0709, KEY_VOLUMEDOWN },
-	{ 0x0706, KEY_CHANNELUP },
-	{ 0x070c, KEY_CHANNELDOWN },
-	{ 0x070f, KEY_1 },
-	{ 0x0715, KEY_2 },
-	{ 0x0710, KEY_3 },
-	{ 0x0718, KEY_4 },
-	{ 0x071b, KEY_5 },
-	{ 0x071e, KEY_6 },
-	{ 0x0711, KEY_7 },
-	{ 0x0721, KEY_8 },
-	{ 0x0712, KEY_9 },
-	{ 0x0727, KEY_0 },
-	{ 0x0724, KEY_SCREEN }, /* 'Square' key */
-	{ 0x072a, KEY_TEXT },   /* 'T' key */
-	{ 0x072d, KEY_REWIND },
-	{ 0x0730, KEY_PLAY },
-	{ 0x0733, KEY_FASTFORWARD },
-	{ 0x0736, KEY_RECORD },
-	{ 0x073c, KEY_STOP },
-	{ 0x073f, KEY_CANCEL }, /* '?' key */
-
-	/* Key codes for the Terratec Cinergy DT XS Diversity, similar to cinergyT2.c */
-	{ 0xeb01, KEY_POWER },
-	{ 0xeb02, KEY_1 },
-	{ 0xeb03, KEY_2 },
-	{ 0xeb04, KEY_3 },
-	{ 0xeb05, KEY_4 },
-	{ 0xeb06, KEY_5 },
-	{ 0xeb07, KEY_6 },
-	{ 0xeb08, KEY_7 },
-	{ 0xeb09, KEY_8 },
-	{ 0xeb0a, KEY_9 },
-	{ 0xeb0b, KEY_VIDEO },
-	{ 0xeb0c, KEY_0 },
-	{ 0xeb0d, KEY_REFRESH },
-	{ 0xeb0f, KEY_EPG },
-	{ 0xeb10, KEY_UP },
-	{ 0xeb11, KEY_LEFT },
-	{ 0xeb12, KEY_OK },
-	{ 0xeb13, KEY_RIGHT },
-	{ 0xeb14, KEY_DOWN },
-	{ 0xeb16, KEY_INFO },
-	{ 0xeb17, KEY_RED },
-	{ 0xeb18, KEY_GREEN },
-	{ 0xeb19, KEY_YELLOW },
-	{ 0xeb1a, KEY_BLUE },
-	{ 0xeb1b, KEY_CHANNELUP },
-	{ 0xeb1c, KEY_VOLUMEUP },
-	{ 0xeb1d, KEY_MUTE },
-	{ 0xeb1e, KEY_VOLUMEDOWN },
-	{ 0xeb1f, KEY_CHANNELDOWN },
-	{ 0xeb40, KEY_PAUSE },
-	{ 0xeb41, KEY_HOME },
-	{ 0xeb42, KEY_MENU }, /* DVD Menu */
-	{ 0xeb43, KEY_SUBTITLE },
-	{ 0xeb44, KEY_TEXT }, /* Teletext */
-	{ 0xeb45, KEY_DELETE },
-	{ 0xeb46, KEY_TV },
-	{ 0xeb47, KEY_DVD },
-	{ 0xeb48, KEY_STOP },
-	{ 0xeb49, KEY_VIDEO },
-	{ 0xeb4a, KEY_AUDIO }, /* Music */
-	{ 0xeb4b, KEY_SCREEN }, /* Pic */
-	{ 0xeb4c, KEY_PLAY },
-	{ 0xeb4d, KEY_BACK },
-	{ 0xeb4e, KEY_REWIND },
-	{ 0xeb4f, KEY_FASTFORWARD },
-	{ 0xeb54, KEY_PREVIOUS },
-	{ 0xeb58, KEY_RECORD },
-	{ 0xeb5c, KEY_NEXT },
-
-	/* Key codes for the Haupauge WinTV Nova-TD, copied from nova-t-usb2.c (Nova-T USB2) */
-	{ 0x1e00, KEY_0 },
-	{ 0x1e01, KEY_1 },
-	{ 0x1e02, KEY_2 },
-	{ 0x1e03, KEY_3 },
-	{ 0x1e04, KEY_4 },
-	{ 0x1e05, KEY_5 },
-	{ 0x1e06, KEY_6 },
-	{ 0x1e07, KEY_7 },
-	{ 0x1e08, KEY_8 },
-	{ 0x1e09, KEY_9 },
-	{ 0x1e0a, KEY_KPASTERISK },
-	{ 0x1e0b, KEY_RED },
-	{ 0x1e0c, KEY_RADIO },
-	{ 0x1e0d, KEY_MENU },
-	{ 0x1e0e, KEY_GRAVE }, /* # */
-	{ 0x1e0f, KEY_MUTE },
-	{ 0x1e10, KEY_VOLUMEUP },
-	{ 0x1e11, KEY_VOLUMEDOWN },
-	{ 0x1e12, KEY_CHANNEL },
-	{ 0x1e14, KEY_UP },
-	{ 0x1e15, KEY_DOWN },
-	{ 0x1e16, KEY_LEFT },
-	{ 0x1e17, KEY_RIGHT },
-	{ 0x1e18, KEY_VIDEO },
-	{ 0x1e19, KEY_AUDIO },
-	{ 0x1e1a, KEY_MEDIA },
-	{ 0x1e1b, KEY_EPG },
-	{ 0x1e1c, KEY_TV },
-	{ 0x1e1e, KEY_NEXT },
-	{ 0x1e1f, KEY_BACK },
-	{ 0x1e20, KEY_CHANNELUP },
-	{ 0x1e21, KEY_CHANNELDOWN },
-	{ 0x1e24, KEY_LAST }, /* Skip backwards */
-	{ 0x1e25, KEY_OK },
-	{ 0x1e29, KEY_BLUE},
-	{ 0x1e2e, KEY_GREEN },
-	{ 0x1e30, KEY_PAUSE },
-	{ 0x1e32, KEY_REWIND },
-	{ 0x1e34, KEY_FASTFORWARD },
-	{ 0x1e35, KEY_PLAY },
-	{ 0x1e36, KEY_STOP },
-	{ 0x1e37, KEY_RECORD },
-	{ 0x1e38, KEY_YELLOW },
-	{ 0x1e3b, KEY_GOTO },
-	{ 0x1e3d, KEY_POWER },
-
-	/* Key codes for the Leadtek Winfast DTV Dongle */
-	{ 0x0042, KEY_POWER },
-	{ 0x077c, KEY_TUNER },
-	{ 0x0f4e, KEY_PRINT }, /* PREVIEW */
-	{ 0x0840, KEY_SCREEN }, /* full screen toggle*/
-	{ 0x0f71, KEY_DOT }, /* frequency */
-	{ 0x0743, KEY_0 },
-	{ 0x0c41, KEY_1 },
-	{ 0x0443, KEY_2 },
-	{ 0x0b7f, KEY_3 },
-	{ 0x0e41, KEY_4 },
-	{ 0x0643, KEY_5 },
-	{ 0x097f, KEY_6 },
-	{ 0x0d7e, KEY_7 },
-	{ 0x057c, KEY_8 },
-	{ 0x0a40, KEY_9 },
-	{ 0x0e4e, KEY_CLEAR },
-	{ 0x047c, KEY_CHANNEL }, /* show channel number */
-	{ 0x0f41, KEY_LAST }, /* recall */
-	{ 0x0342, KEY_MUTE },
-	{ 0x064c, KEY_RESERVED }, /* PIP button*/
-	{ 0x0172, KEY_SHUFFLE }, /* SNAPSHOT */
-	{ 0x0c4e, KEY_PLAYPAUSE }, /* TIMESHIFT */
-	{ 0x0b70, KEY_RECORD },
-	{ 0x037d, KEY_VOLUMEUP },
-	{ 0x017d, KEY_VOLUMEDOWN },
-	{ 0x0242, KEY_CHANNELUP },
-	{ 0x007d, KEY_CHANNELDOWN },
-
-	/* Key codes for Nova-TD "credit card" remote control. */
-	{ 0x1d00, KEY_0 },
-	{ 0x1d01, KEY_1 },
-	{ 0x1d02, KEY_2 },
-	{ 0x1d03, KEY_3 },
-	{ 0x1d04, KEY_4 },
-	{ 0x1d05, KEY_5 },
-	{ 0x1d06, KEY_6 },
-	{ 0x1d07, KEY_7 },
-	{ 0x1d08, KEY_8 },
-	{ 0x1d09, KEY_9 },
-	{ 0x1d0a, KEY_TEXT },
-	{ 0x1d0d, KEY_MENU },
-	{ 0x1d0f, KEY_MUTE },
-	{ 0x1d10, KEY_VOLUMEUP },
-	{ 0x1d11, KEY_VOLUMEDOWN },
-	{ 0x1d12, KEY_CHANNEL },
-	{ 0x1d14, KEY_UP },
-	{ 0x1d15, KEY_DOWN },
-	{ 0x1d16, KEY_LEFT },
-	{ 0x1d17, KEY_RIGHT },
-	{ 0x1d1c, KEY_TV },
-	{ 0x1d1e, KEY_NEXT },
-	{ 0x1d1f, KEY_BACK },
-	{ 0x1d20, KEY_CHANNELUP },
-	{ 0x1d21, KEY_CHANNELDOWN },
-	{ 0x1d24, KEY_LAST },
-	{ 0x1d25, KEY_OK },
-	{ 0x1d30, KEY_PAUSE },
-	{ 0x1d32, KEY_REWIND },
-	{ 0x1d34, KEY_FASTFORWARD },
-	{ 0x1d35, KEY_PLAY },
-	{ 0x1d36, KEY_STOP },
-	{ 0x1d37, KEY_RECORD },
-	{ 0x1d3b, KEY_GOTO },
-	{ 0x1d3d, KEY_POWER },
-};
-
-static struct rc_keymap dib0700_rc5_map = {
-	.map = {
-		.scan    = dib0700_rc5_table,
-		.size    = ARRAY_SIZE(dib0700_rc5_table),
-		.ir_type = IR_TYPE_RC5,
-		.name    = RC_MAP_DIB0700_RC5_TABLE,
-	}
-};
-
-static int __init init_rc_map(void)
-{
-	return ir_register_map(&dib0700_rc5_map);
-}
-
-static void __exit exit_rc_map(void)
-{
-	ir_unregister_map(&dib0700_rc5_map);
-}
-
-module_init(init_rc_map)
-module_exit(exit_rc_map)
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-digitalnow-tinytwin.c linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-digitalnow-tinytwin.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-digitalnow-tinytwin.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-digitalnow-tinytwin.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,98 +0,0 @@
-/*
- * DigitalNow TinyTwin remote controller keytable
- *
- * Copyright (C) 2010 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 <media/rc-map.h>
-
-static struct ir_scancode digitalnow_tinytwin[] = {
-	{ 0x0000, KEY_MUTE },            /* [symbol speaker] */
-	{ 0x0001, KEY_VOLUMEUP },
-	{ 0x0002, KEY_POWER2 },          /* TV [power button] */
-	{ 0x0003, KEY_2 },
-	{ 0x0004, KEY_3 },
-	{ 0x0005, KEY_4 },
-	{ 0x0006, KEY_6 },
-	{ 0x0007, KEY_7 },
-	{ 0x0008, KEY_8 },
-	{ 0x0009, KEY_NUMERIC_STAR },    /* [*] */
-	{ 0x000a, KEY_0 },
-	{ 0x000b, KEY_NUMERIC_POUND },   /* [#] */
-	{ 0x000c, KEY_RIGHT },           /* [right arrow] */
-	{ 0x000d, KEY_HOMEPAGE },        /* [symbol home] Start */
-	{ 0x000e, KEY_RED },             /* [red] Videos */
-	{ 0x0010, KEY_POWER },           /* PC [power button] */
-	{ 0x0011, KEY_YELLOW },          /* [yellow] Pictures */
-	{ 0x0012, KEY_DOWN },            /* [down arrow] */
-	{ 0x0013, KEY_GREEN },           /* [green] Music */
-	{ 0x0014, KEY_CYCLEWINDOWS },    /* BACK */
-	{ 0x0015, KEY_FAVORITES },       /* MORE */
-	{ 0x0016, KEY_UP },              /* [up arrow] */
-	{ 0x0017, KEY_LEFT },            /* [left arrow] */
-	{ 0x0018, KEY_OK },              /* OK */
-	{ 0x0019, KEY_BLUE },            /* [blue] MyTV */
-	{ 0x001a, KEY_REWIND },          /* REW [<<] */
-	{ 0x001b, KEY_PLAY },            /* PLAY */
-	{ 0x001c, KEY_5 },
-	{ 0x001d, KEY_9 },
-	{ 0x001e, KEY_VOLUMEDOWN },
-	{ 0x001f, KEY_1 },
-	{ 0x0040, KEY_STOP },            /* STOP */
-	{ 0x0042, KEY_PAUSE },           /* PAUSE */
-	{ 0x0043, KEY_SCREEN },          /* Aspect */
-	{ 0x0044, KEY_FORWARD },         /* FWD [>>] */
-	{ 0x0045, KEY_NEXT },            /* SKIP */
-	{ 0x0048, KEY_RECORD },          /* RECORD */
-	{ 0x0049, KEY_VIDEO },           /* RTV */
-	{ 0x004a, KEY_EPG },             /* Guide */
-	{ 0x004b, KEY_CHANNELUP },
-	{ 0x004c, KEY_HELP },            /* Help */
-	{ 0x004d, KEY_RADIO },           /* Radio */
-	{ 0x004f, KEY_CHANNELDOWN },
-	{ 0x0050, KEY_DVD },             /* DVD */
-	{ 0x0051, KEY_AUDIO },           /* Audio */
-	{ 0x0052, KEY_TITLE },           /* Title */
-	{ 0x0053, KEY_NEW },             /* [symbol PIP?] */
-	{ 0x0057, KEY_MENU },            /* Mouse */
-	{ 0x005a, KEY_PREVIOUS },        /* REPLAY */
-};
-
-static struct rc_keymap digitalnow_tinytwin_map = {
-	.map = {
-		.scan    = digitalnow_tinytwin,
-		.size    = ARRAY_SIZE(digitalnow_tinytwin),
-		.ir_type = IR_TYPE_NEC,
-		.name    = RC_MAP_DIGITALNOW_TINYTWIN,
-	}
-};
-
-static int __init init_rc_map_digitalnow_tinytwin(void)
-{
-	return ir_register_map(&digitalnow_tinytwin_map);
-}
-
-static void __exit exit_rc_map_digitalnow_tinytwin(void)
-{
-	ir_unregister_map(&digitalnow_tinytwin_map);
-}
-
-module_init(init_rc_map_digitalnow_tinytwin)
-module_exit(exit_rc_map_digitalnow_tinytwin)
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-digittrade.c linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-digittrade.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-digittrade.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-digittrade.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,82 +0,0 @@
-/*
- * Digittrade DVB-T USB Stick remote controller keytable
- *
- * Copyright (C) 2010 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 <media/rc-map.h>
-
-/* Digittrade DVB-T USB Stick remote controller. */
-/* Imported from af9015.h.
-   Initial keytable was from Alain Kalker <miki@dds.nl> */
-
-/* Digittrade DVB-T USB Stick */
-static struct ir_scancode digittrade[] = {
-	{ 0x0000, KEY_9 },
-	{ 0x0001, KEY_EPG },             /* EPG */
-	{ 0x0002, KEY_VOLUMEDOWN },      /* Vol Dn */
-	{ 0x0003, KEY_TEXT },            /* TELETEXT */
-	{ 0x0004, KEY_8 },
-	{ 0x0005, KEY_MUTE },            /* MUTE */
-	{ 0x0006, KEY_POWER2 },          /* POWER */
-	{ 0x0009, KEY_ZOOM },            /* FULLSCREEN */
-	{ 0x000a, KEY_RECORD },          /* RECORD */
-	{ 0x000d, KEY_SUBTITLE },        /* SUBTITLE */
-	{ 0x000e, KEY_STOP },            /* STOP */
-	{ 0x0010, KEY_OK },              /* RETURN */
-	{ 0x0011, KEY_2 },
-	{ 0x0012, KEY_4 },
-	{ 0x0015, KEY_3 },
-	{ 0x0016, KEY_5 },
-	{ 0x0017, KEY_CHANNELDOWN },     /* Ch Dn */
-	{ 0x0019, KEY_CHANNELUP },       /* CH Up */
-	{ 0x001a, KEY_PAUSE },           /* PAUSE */
-	{ 0x001b, KEY_1 },
-	{ 0x001d, KEY_AUDIO },           /* DUAL SOUND */
-	{ 0x001e, KEY_PLAY },            /* PLAY */
-	{ 0x001f, KEY_CAMERA },          /* SNAPSHOT */
-	{ 0x0040, KEY_VOLUMEUP },        /* Vol Up */
-	{ 0x0048, KEY_7 },
-	{ 0x004c, KEY_6 },
-	{ 0x004d, KEY_PLAYPAUSE },       /* TIMESHIFT */
-	{ 0x0054, KEY_0 },
-};
-
-static struct rc_keymap digittrade_map = {
-	.map = {
-		.scan    = digittrade,
-		.size    = ARRAY_SIZE(digittrade),
-		.ir_type = IR_TYPE_NEC,
-		.name    = RC_MAP_DIGITTRADE,
-	}
-};
-
-static int __init init_rc_map_digittrade(void)
-{
-	return ir_register_map(&digittrade_map);
-}
-
-static void __exit exit_rc_map_digittrade(void)
-{
-	ir_unregister_map(&digittrade_map);
-}
-
-module_init(init_rc_map_digittrade)
-module_exit(exit_rc_map_digittrade)
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-dm1105-nec.c linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-dm1105-nec.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-dm1105-nec.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-dm1105-nec.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,76 +0,0 @@
-/* dm1105-nec.h - Keytable for dm1105_nec Remote Controller
- *
- * keymap imported from ir-keymaps.c
- *
- * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
-
-/* DVBWorld remotes
-   Igor M. Liplianin <liplianin@me.by>
- */
-
-static struct ir_scancode dm1105_nec[] = {
-	{ 0x0a, KEY_POWER2},		/* power */
-	{ 0x0c, KEY_MUTE},		/* mute */
-	{ 0x11, KEY_1},
-	{ 0x12, KEY_2},
-	{ 0x13, KEY_3},
-	{ 0x14, KEY_4},
-	{ 0x15, KEY_5},
-	{ 0x16, KEY_6},
-	{ 0x17, KEY_7},
-	{ 0x18, KEY_8},
-	{ 0x19, KEY_9},
-	{ 0x10, KEY_0},
-	{ 0x1c, KEY_CHANNELUP},		/* ch+ */
-	{ 0x0f, KEY_CHANNELDOWN},	/* ch- */
-	{ 0x1a, KEY_VOLUMEUP},		/* vol+ */
-	{ 0x0e, KEY_VOLUMEDOWN},	/* vol- */
-	{ 0x04, KEY_RECORD},		/* rec */
-	{ 0x09, KEY_CHANNEL},		/* fav */
-	{ 0x08, KEY_BACKSPACE},		/* rewind */
-	{ 0x07, KEY_FASTFORWARD},	/* fast */
-	{ 0x0b, KEY_PAUSE},		/* pause */
-	{ 0x02, KEY_ESC},		/* cancel */
-	{ 0x03, KEY_TAB},		/* tab */
-	{ 0x00, KEY_UP},		/* up */
-	{ 0x1f, KEY_ENTER},		/* ok */
-	{ 0x01, KEY_DOWN},		/* down */
-	{ 0x05, KEY_RECORD},		/* cap */
-	{ 0x06, KEY_STOP},		/* stop */
-	{ 0x40, KEY_ZOOM},		/* full */
-	{ 0x1e, KEY_TV},		/* tvmode */
-	{ 0x1b, KEY_B},			/* recall */
-};
-
-static struct rc_keymap dm1105_nec_map = {
-	.map = {
-		.scan    = dm1105_nec,
-		.size    = ARRAY_SIZE(dm1105_nec),
-		.ir_type = IR_TYPE_UNKNOWN,	/* Legacy IR type */
-		.name    = RC_MAP_DM1105_NEC,
-	}
-};
-
-static int __init init_rc_map_dm1105_nec(void)
-{
-	return ir_register_map(&dm1105_nec_map);
-}
-
-static void __exit exit_rc_map_dm1105_nec(void)
-{
-	ir_unregister_map(&dm1105_nec_map);
-}
-
-module_init(init_rc_map_dm1105_nec)
-module_exit(exit_rc_map_dm1105_nec)
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-dntv-live-dvb-t.c linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-dntv-live-dvb-t.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-dntv-live-dvb-t.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-dntv-live-dvb-t.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,78 +0,0 @@
-/* dntv-live-dvb-t.h - Keytable for dntv_live_dvb_t Remote Controller
- *
- * keymap imported from ir-keymaps.c
- *
- * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
-
-/* DigitalNow DNTV Live DVB-T Remote */
-
-static struct ir_scancode dntv_live_dvb_t[] = {
-	{ 0x00, KEY_ESC },		/* 'go up a level?' */
-	/* Keys 0 to 9 */
-	{ 0x0a, KEY_0 },
-	{ 0x01, KEY_1 },
-	{ 0x02, KEY_2 },
-	{ 0x03, KEY_3 },
-	{ 0x04, KEY_4 },
-	{ 0x05, KEY_5 },
-	{ 0x06, KEY_6 },
-	{ 0x07, KEY_7 },
-	{ 0x08, KEY_8 },
-	{ 0x09, KEY_9 },
-
-	{ 0x0b, KEY_TUNER },		/* tv/fm */
-	{ 0x0c, KEY_SEARCH },		/* scan */
-	{ 0x0d, KEY_STOP },
-	{ 0x0e, KEY_PAUSE },
-	{ 0x0f, KEY_LIST },		/* source */
-
-	{ 0x10, KEY_MUTE },
-	{ 0x11, KEY_REWIND },		/* backward << */
-	{ 0x12, KEY_POWER },
-	{ 0x13, KEY_CAMERA },		/* snap */
-	{ 0x14, KEY_AUDIO },		/* stereo */
-	{ 0x15, KEY_CLEAR },		/* reset */
-	{ 0x16, KEY_PLAY },
-	{ 0x17, KEY_ENTER },
-	{ 0x18, KEY_ZOOM },		/* full screen */
-	{ 0x19, KEY_FASTFORWARD },	/* forward >> */
-	{ 0x1a, KEY_CHANNELUP },
-	{ 0x1b, KEY_VOLUMEUP },
-	{ 0x1c, KEY_INFO },		/* preview */
-	{ 0x1d, KEY_RECORD },		/* record */
-	{ 0x1e, KEY_CHANNELDOWN },
-	{ 0x1f, KEY_VOLUMEDOWN },
-};
-
-static struct rc_keymap dntv_live_dvb_t_map = {
-	.map = {
-		.scan    = dntv_live_dvb_t,
-		.size    = ARRAY_SIZE(dntv_live_dvb_t),
-		.ir_type = IR_TYPE_UNKNOWN,	/* Legacy IR type */
-		.name    = RC_MAP_DNTV_LIVE_DVB_T,
-	}
-};
-
-static int __init init_rc_map_dntv_live_dvb_t(void)
-{
-	return ir_register_map(&dntv_live_dvb_t_map);
-}
-
-static void __exit exit_rc_map_dntv_live_dvb_t(void)
-{
-	ir_unregister_map(&dntv_live_dvb_t_map);
-}
-
-module_init(init_rc_map_dntv_live_dvb_t)
-module_exit(exit_rc_map_dntv_live_dvb_t)
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-dntv-live-dvbt-pro.c linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-dntv-live-dvbt-pro.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-dntv-live-dvbt-pro.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-dntv-live-dvbt-pro.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,97 +0,0 @@
-/* dntv-live-dvbt-pro.h - Keytable for dntv_live_dvbt_pro Remote Controller
- *
- * keymap imported from ir-keymaps.c
- *
- * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
-
-/* DigitalNow DNTV Live! DVB-T Pro Remote */
-
-static struct ir_scancode dntv_live_dvbt_pro[] = {
-	{ 0x16, KEY_POWER },
-	{ 0x5b, KEY_HOME },
-
-	{ 0x55, KEY_TV },		/* live tv */
-	{ 0x58, KEY_TUNER },		/* digital Radio */
-	{ 0x5a, KEY_RADIO },		/* FM radio */
-	{ 0x59, KEY_DVD },		/* dvd menu */
-	{ 0x03, KEY_1 },
-	{ 0x01, KEY_2 },
-	{ 0x06, KEY_3 },
-	{ 0x09, KEY_4 },
-	{ 0x1d, KEY_5 },
-	{ 0x1f, KEY_6 },
-	{ 0x0d, KEY_7 },
-	{ 0x19, KEY_8 },
-	{ 0x1b, KEY_9 },
-	{ 0x0c, KEY_CANCEL },
-	{ 0x15, KEY_0 },
-	{ 0x4a, KEY_CLEAR },
-	{ 0x13, KEY_BACK },
-	{ 0x00, KEY_TAB },
-	{ 0x4b, KEY_UP },
-	{ 0x4e, KEY_LEFT },
-	{ 0x4f, KEY_OK },
-	{ 0x52, KEY_RIGHT },
-	{ 0x51, KEY_DOWN },
-	{ 0x1e, KEY_VOLUMEUP },
-	{ 0x0a, KEY_VOLUMEDOWN },
-	{ 0x02, KEY_CHANNELDOWN },
-	{ 0x05, KEY_CHANNELUP },
-	{ 0x11, KEY_RECORD },
-	{ 0x14, KEY_PLAY },
-	{ 0x4c, KEY_PAUSE },
-	{ 0x1a, KEY_STOP },
-	{ 0x40, KEY_REWIND },
-	{ 0x12, KEY_FASTFORWARD },
-	{ 0x41, KEY_PREVIOUSSONG },	/* replay |< */
-	{ 0x42, KEY_NEXTSONG },		/* skip >| */
-	{ 0x54, KEY_CAMERA },		/* capture */
-	{ 0x50, KEY_LANGUAGE },		/* sap */
-	{ 0x47, KEY_TV2 },		/* pip */
-	{ 0x4d, KEY_SCREEN },
-	{ 0x43, KEY_SUBTITLE },
-	{ 0x10, KEY_MUTE },
-	{ 0x49, KEY_AUDIO },		/* l/r */
-	{ 0x07, KEY_SLEEP },
-	{ 0x08, KEY_VIDEO },		/* a/v */
-	{ 0x0e, KEY_PREVIOUS },		/* recall */
-	{ 0x45, KEY_ZOOM },		/* zoom + */
-	{ 0x46, KEY_ANGLE },		/* zoom - */
-	{ 0x56, KEY_RED },
-	{ 0x57, KEY_GREEN },
-	{ 0x5c, KEY_YELLOW },
-	{ 0x5d, KEY_BLUE },
-};
-
-static struct rc_keymap dntv_live_dvbt_pro_map = {
-	.map = {
-		.scan    = dntv_live_dvbt_pro,
-		.size    = ARRAY_SIZE(dntv_live_dvbt_pro),
-		.ir_type = IR_TYPE_UNKNOWN,	/* Legacy IR type */
-		.name    = RC_MAP_DNTV_LIVE_DVBT_PRO,
-	}
-};
-
-static int __init init_rc_map_dntv_live_dvbt_pro(void)
-{
-	return ir_register_map(&dntv_live_dvbt_pro_map);
-}
-
-static void __exit exit_rc_map_dntv_live_dvbt_pro(void)
-{
-	ir_unregister_map(&dntv_live_dvbt_pro_map);
-}
-
-module_init(init_rc_map_dntv_live_dvbt_pro)
-module_exit(exit_rc_map_dntv_live_dvbt_pro)
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-em-terratec.c linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-em-terratec.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-em-terratec.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-em-terratec.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,69 +0,0 @@
-/* em-terratec.h - Keytable for em_terratec Remote Controller
- *
- * keymap imported from ir-keymaps.c
- *
- * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
-
-static struct ir_scancode em_terratec[] = {
-	{ 0x01, KEY_CHANNEL },
-	{ 0x02, KEY_SELECT },
-	{ 0x03, KEY_MUTE },
-	{ 0x04, KEY_POWER },
-	{ 0x05, KEY_1 },
-	{ 0x06, KEY_2 },
-	{ 0x07, KEY_3 },
-	{ 0x08, KEY_CHANNELUP },
-	{ 0x09, KEY_4 },
-	{ 0x0a, KEY_5 },
-	{ 0x0b, KEY_6 },
-	{ 0x0c, KEY_CHANNELDOWN },
-	{ 0x0d, KEY_7 },
-	{ 0x0e, KEY_8 },
-	{ 0x0f, KEY_9 },
-	{ 0x10, KEY_VOLUMEUP },
-	{ 0x11, KEY_0 },
-	{ 0x12, KEY_MENU },
-	{ 0x13, KEY_PRINT },
-	{ 0x14, KEY_VOLUMEDOWN },
-	{ 0x16, KEY_PAUSE },
-	{ 0x18, KEY_RECORD },
-	{ 0x19, KEY_REWIND },
-	{ 0x1a, KEY_PLAY },
-	{ 0x1b, KEY_FORWARD },
-	{ 0x1c, KEY_BACKSPACE },
-	{ 0x1e, KEY_STOP },
-	{ 0x40, KEY_ZOOM },
-};
-
-static struct rc_keymap em_terratec_map = {
-	.map = {
-		.scan    = em_terratec,
-		.size    = ARRAY_SIZE(em_terratec),
-		.ir_type = IR_TYPE_UNKNOWN,	/* Legacy IR type */
-		.name    = RC_MAP_EM_TERRATEC,
-	}
-};
-
-static int __init init_rc_map_em_terratec(void)
-{
-	return ir_register_map(&em_terratec_map);
-}
-
-static void __exit exit_rc_map_em_terratec(void)
-{
-	ir_unregister_map(&em_terratec_map);
-}
-
-module_init(init_rc_map_em_terratec)
-module_exit(exit_rc_map_em_terratec)
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-encore-enltv2.c linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-encore-enltv2.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-encore-enltv2.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-encore-enltv2.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,90 +0,0 @@
-/* encore-enltv2.h - Keytable for encore_enltv2 Remote Controller
- *
- * keymap imported from ir-keymaps.c
- *
- * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
-
-/* Encore ENLTV2-FM  - silver plastic - "Wand Media" written at the botton
-    Mauro Carvalho Chehab <mchehab@infradead.org> */
-
-static struct ir_scancode encore_enltv2[] = {
-	{ 0x4c, KEY_POWER2 },
-	{ 0x4a, KEY_TUNER },
-	{ 0x40, KEY_1 },
-	{ 0x60, KEY_2 },
-	{ 0x50, KEY_3 },
-	{ 0x70, KEY_4 },
-	{ 0x48, KEY_5 },
-	{ 0x68, KEY_6 },
-	{ 0x58, KEY_7 },
-	{ 0x78, KEY_8 },
-	{ 0x44, KEY_9 },
-	{ 0x54, KEY_0 },
-
-	{ 0x64, KEY_LAST },		/* +100 */
-	{ 0x4e, KEY_AGAIN },		/* Recall */
-
-	{ 0x6c, KEY_SWITCHVIDEOMODE },	/* Video Source */
-	{ 0x5e, KEY_MENU },
-	{ 0x56, KEY_SCREEN },
-	{ 0x7a, KEY_SETUP },
-
-	{ 0x46, KEY_MUTE },
-	{ 0x5c, KEY_MODE },		/* Stereo */
-	{ 0x74, KEY_INFO },
-	{ 0x7c, KEY_CLEAR },
-
-	{ 0x55, KEY_UP },
-	{ 0x49, KEY_DOWN },
-	{ 0x7e, KEY_LEFT },
-	{ 0x59, KEY_RIGHT },
-	{ 0x6a, KEY_ENTER },
-
-	{ 0x42, KEY_VOLUMEUP },
-	{ 0x62, KEY_VOLUMEDOWN },
-	{ 0x52, KEY_CHANNELUP },
-	{ 0x72, KEY_CHANNELDOWN },
-
-	{ 0x41, KEY_RECORD },
-	{ 0x51, KEY_CAMERA },		/* Snapshot */
-	{ 0x75, KEY_TIME },		/* Timeshift */
-	{ 0x71, KEY_TV2 },		/* PIP */
-
-	{ 0x45, KEY_REWIND },
-	{ 0x6f, KEY_PAUSE },
-	{ 0x7d, KEY_FORWARD },
-	{ 0x79, KEY_STOP },
-};
-
-static struct rc_keymap encore_enltv2_map = {
-	.map = {
-		.scan    = encore_enltv2,
-		.size    = ARRAY_SIZE(encore_enltv2),
-		.ir_type = IR_TYPE_UNKNOWN,	/* Legacy IR type */
-		.name    = RC_MAP_ENCORE_ENLTV2,
-	}
-};
-
-static int __init init_rc_map_encore_enltv2(void)
-{
-	return ir_register_map(&encore_enltv2_map);
-}
-
-static void __exit exit_rc_map_encore_enltv2(void)
-{
-	ir_unregister_map(&encore_enltv2_map);
-}
-
-module_init(init_rc_map_encore_enltv2)
-module_exit(exit_rc_map_encore_enltv2)
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-encore-enltv.c linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-encore-enltv.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-encore-enltv.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-encore-enltv.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,112 +0,0 @@
-/* encore-enltv.h - Keytable for encore_enltv Remote Controller
- *
- * keymap imported from ir-keymaps.c
- *
- * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
-
-/* Encore ENLTV-FM  - black plastic, white front cover with white glowing buttons
-    Juan Pablo Sormani <sorman@gmail.com> */
-
-static struct ir_scancode encore_enltv[] = {
-
-	/* Power button does nothing, neither in Windows app,
-	 although it sends data (used for BIOS wakeup?) */
-	{ 0x0d, KEY_MUTE },
-
-	{ 0x1e, KEY_TV },
-	{ 0x00, KEY_VIDEO },
-	{ 0x01, KEY_AUDIO },		/* music */
-	{ 0x02, KEY_MHP },		/* picture */
-
-	{ 0x1f, KEY_1 },
-	{ 0x03, KEY_2 },
-	{ 0x04, KEY_3 },
-	{ 0x05, KEY_4 },
-	{ 0x1c, KEY_5 },
-	{ 0x06, KEY_6 },
-	{ 0x07, KEY_7 },
-	{ 0x08, KEY_8 },
-	{ 0x1d, KEY_9 },
-	{ 0x0a, KEY_0 },
-
-	{ 0x09, KEY_LIST },		/* -/-- */
-	{ 0x0b, KEY_LAST },		/* recall */
-
-	{ 0x14, KEY_HOME },		/* win start menu */
-	{ 0x15, KEY_EXIT },		/* exit */
-	{ 0x16, KEY_CHANNELUP },	/* UP */
-	{ 0x12, KEY_CHANNELDOWN },	/* DOWN */
-	{ 0x0c, KEY_VOLUMEUP },		/* RIGHT */
-	{ 0x17, KEY_VOLUMEDOWN },	/* LEFT */
-
-	{ 0x18, KEY_ENTER },		/* OK */
-
-	{ 0x0e, KEY_ESC },
-	{ 0x13, KEY_CYCLEWINDOWS },	/* desktop */
-	{ 0x11, KEY_TAB },
-	{ 0x19, KEY_SWITCHVIDEOMODE },	/* switch */
-
-	{ 0x1a, KEY_MENU },
-	{ 0x1b, KEY_ZOOM },		/* fullscreen */
-	{ 0x44, KEY_TIME },		/* time shift */
-	{ 0x40, KEY_MODE },		/* source */
-
-	{ 0x5a, KEY_RECORD },
-	{ 0x42, KEY_PLAY },		/* play/pause */
-	{ 0x45, KEY_STOP },
-	{ 0x43, KEY_CAMERA },		/* camera icon */
-
-	{ 0x48, KEY_REWIND },
-	{ 0x4a, KEY_FASTFORWARD },
-	{ 0x49, KEY_PREVIOUS },
-	{ 0x4b, KEY_NEXT },
-
-	{ 0x4c, KEY_FAVORITES },	/* tv wall */
-	{ 0x4d, KEY_SOUND },		/* DVD sound */
-	{ 0x4e, KEY_LANGUAGE },		/* DVD lang */
-	{ 0x4f, KEY_TEXT },		/* DVD text */
-
-	{ 0x50, KEY_SLEEP },		/* shutdown */
-	{ 0x51, KEY_MODE },		/* stereo > main */
-	{ 0x52, KEY_SELECT },		/* stereo > sap */
-	{ 0x53, KEY_PROG1 },		/* teletext */
-
-
-	{ 0x59, KEY_RED },		/* AP1 */
-	{ 0x41, KEY_GREEN },		/* AP2 */
-	{ 0x47, KEY_YELLOW },		/* AP3 */
-	{ 0x57, KEY_BLUE },		/* AP4 */
-};
-
-static struct rc_keymap encore_enltv_map = {
-	.map = {
-		.scan    = encore_enltv,
-		.size    = ARRAY_SIZE(encore_enltv),
-		.ir_type = IR_TYPE_UNKNOWN,	/* Legacy IR type */
-		.name    = RC_MAP_ENCORE_ENLTV,
-	}
-};
-
-static int __init init_rc_map_encore_enltv(void)
-{
-	return ir_register_map(&encore_enltv_map);
-}
-
-static void __exit exit_rc_map_encore_enltv(void)
-{
-	ir_unregister_map(&encore_enltv_map);
-}
-
-module_init(init_rc_map_encore_enltv)
-module_exit(exit_rc_map_encore_enltv)
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-encore-enltv-fm53.c linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-encore-enltv-fm53.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-encore-enltv-fm53.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-encore-enltv-fm53.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,81 +0,0 @@
-/* encore-enltv-fm53.h - Keytable for encore_enltv_fm53 Remote Controller
- *
- * keymap imported from ir-keymaps.c
- *
- * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
-
-/* Encore ENLTV-FM v5.3
-   Mauro Carvalho Chehab <mchehab@infradead.org>
- */
-
-static struct ir_scancode encore_enltv_fm53[] = {
-	{ 0x10, KEY_POWER2},
-	{ 0x06, KEY_MUTE},
-
-	{ 0x09, KEY_1},
-	{ 0x1d, KEY_2},
-	{ 0x1f, KEY_3},
-	{ 0x19, KEY_4},
-	{ 0x1b, KEY_5},
-	{ 0x11, KEY_6},
-	{ 0x17, KEY_7},
-	{ 0x12, KEY_8},
-	{ 0x16, KEY_9},
-	{ 0x48, KEY_0},
-
-	{ 0x04, KEY_LIST},		/* -/-- */
-	{ 0x40, KEY_LAST},		/* recall */
-
-	{ 0x02, KEY_MODE},		/* TV/AV */
-	{ 0x05, KEY_CAMERA},		/* SNAPSHOT */
-
-	{ 0x4c, KEY_CHANNELUP},		/* UP */
-	{ 0x00, KEY_CHANNELDOWN},	/* DOWN */
-	{ 0x0d, KEY_VOLUMEUP},		/* RIGHT */
-	{ 0x15, KEY_VOLUMEDOWN},	/* LEFT */
-	{ 0x49, KEY_ENTER},		/* OK */
-
-	{ 0x54, KEY_RECORD},
-	{ 0x4d, KEY_PLAY},		/* pause */
-
-	{ 0x1e, KEY_MENU},		/* video setting */
-	{ 0x0e, KEY_RIGHT},		/* <- */
-	{ 0x1a, KEY_LEFT},		/* -> */
-
-	{ 0x0a, KEY_CLEAR},		/* video default */
-	{ 0x0c, KEY_ZOOM},		/* hide pannel */
-	{ 0x47, KEY_SLEEP},		/* shutdown */
-};
-
-static struct rc_keymap encore_enltv_fm53_map = {
-	.map = {
-		.scan    = encore_enltv_fm53,
-		.size    = ARRAY_SIZE(encore_enltv_fm53),
-		.ir_type = IR_TYPE_UNKNOWN,	/* Legacy IR type */
-		.name    = RC_MAP_ENCORE_ENLTV_FM53,
-	}
-};
-
-static int __init init_rc_map_encore_enltv_fm53(void)
-{
-	return ir_register_map(&encore_enltv_fm53_map);
-}
-
-static void __exit exit_rc_map_encore_enltv_fm53(void)
-{
-	ir_unregister_map(&encore_enltv_fm53_map);
-}
-
-module_init(init_rc_map_encore_enltv_fm53)
-module_exit(exit_rc_map_encore_enltv_fm53)
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-evga-indtube.c linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-evga-indtube.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-evga-indtube.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-evga-indtube.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,61 +0,0 @@
-/* evga-indtube.h - Keytable for evga_indtube Remote Controller
- *
- * keymap imported from ir-keymaps.c
- *
- * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
-
-/* EVGA inDtube
-   Devin Heitmueller <devin.heitmueller@gmail.com>
- */
-
-static struct ir_scancode evga_indtube[] = {
-	{ 0x12, KEY_POWER},
-	{ 0x02, KEY_MODE},	/* TV */
-	{ 0x14, KEY_MUTE},
-	{ 0x1a, KEY_CHANNELUP},
-	{ 0x16, KEY_TV2},	/* PIP */
-	{ 0x1d, KEY_VOLUMEUP},
-	{ 0x05, KEY_CHANNELDOWN},
-	{ 0x0f, KEY_PLAYPAUSE},
-	{ 0x19, KEY_VOLUMEDOWN},
-	{ 0x1c, KEY_REWIND},
-	{ 0x0d, KEY_RECORD},
-	{ 0x18, KEY_FORWARD},
-	{ 0x1e, KEY_PREVIOUS},
-	{ 0x1b, KEY_STOP},
-	{ 0x1f, KEY_NEXT},
-	{ 0x13, KEY_CAMERA},
-};
-
-static struct rc_keymap evga_indtube_map = {
-	.map = {
-		.scan    = evga_indtube,
-		.size    = ARRAY_SIZE(evga_indtube),
-		.ir_type = IR_TYPE_UNKNOWN,	/* Legacy IR type */
-		.name    = RC_MAP_EVGA_INDTUBE,
-	}
-};
-
-static int __init init_rc_map_evga_indtube(void)
-{
-	return ir_register_map(&evga_indtube_map);
-}
-
-static void __exit exit_rc_map_evga_indtube(void)
-{
-	ir_unregister_map(&evga_indtube_map);
-}
-
-module_init(init_rc_map_evga_indtube)
-module_exit(exit_rc_map_evga_indtube)
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-eztv.c linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-eztv.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-eztv.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-eztv.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,96 +0,0 @@
-/* eztv.h - Keytable for eztv Remote Controller
- *
- * keymap imported from ir-keymaps.c
- *
- * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
-
-/* Alfons Geser <a.geser@cox.net>
- * updates from Job D. R. Borges <jobdrb@ig.com.br> */
-
-static struct ir_scancode eztv[] = {
-	{ 0x12, KEY_POWER },
-	{ 0x01, KEY_TV },	/* DVR */
-	{ 0x15, KEY_DVD },	/* DVD */
-	{ 0x17, KEY_AUDIO },	/* music */
-				/* DVR mode / DVD mode / music mode */
-
-	{ 0x1b, KEY_MUTE },	/* mute */
-	{ 0x02, KEY_LANGUAGE },	/* MTS/SAP / audio / autoseek */
-	{ 0x1e, KEY_SUBTITLE },	/* closed captioning / subtitle / seek */
-	{ 0x16, KEY_ZOOM },	/* full screen */
-	{ 0x1c, KEY_VIDEO },	/* video source / eject / delall */
-	{ 0x1d, KEY_RESTART },	/* playback / angle / del */
-	{ 0x2f, KEY_SEARCH },	/* scan / menu / playlist */
-	{ 0x30, KEY_CHANNEL },	/* CH surfing / bookmark / memo */
-
-	{ 0x31, KEY_HELP },	/* help */
-	{ 0x32, KEY_MODE },	/* num/memo */
-	{ 0x33, KEY_ESC },	/* cancel */
-
-	{ 0x0c, KEY_UP },	/* up */
-	{ 0x10, KEY_DOWN },	/* down */
-	{ 0x08, KEY_LEFT },	/* left */
-	{ 0x04, KEY_RIGHT },	/* right */
-	{ 0x03, KEY_SELECT },	/* select */
-
-	{ 0x1f, KEY_REWIND },	/* rewind */
-	{ 0x20, KEY_PLAYPAUSE },/* play/pause */
-	{ 0x29, KEY_FORWARD },	/* forward */
-	{ 0x14, KEY_AGAIN },	/* repeat */
-	{ 0x2b, KEY_RECORD },	/* recording */
-	{ 0x2c, KEY_STOP },	/* stop */
-	{ 0x2d, KEY_PLAY },	/* play */
-	{ 0x2e, KEY_CAMERA },	/* snapshot / shuffle */
-
-	{ 0x00, KEY_0 },
-	{ 0x05, KEY_1 },
-	{ 0x06, KEY_2 },
-	{ 0x07, KEY_3 },
-	{ 0x09, KEY_4 },
-	{ 0x0a, KEY_5 },
-	{ 0x0b, KEY_6 },
-	{ 0x0d, KEY_7 },
-	{ 0x0e, KEY_8 },
-	{ 0x0f, KEY_9 },
-
-	{ 0x2a, KEY_VOLUMEUP },
-	{ 0x11, KEY_VOLUMEDOWN },
-	{ 0x18, KEY_CHANNELUP },/* CH.tracking up */
-	{ 0x19, KEY_CHANNELDOWN },/* CH.tracking down */
-
-	{ 0x13, KEY_ENTER },	/* enter */
-	{ 0x21, KEY_DOT },	/* . (decimal dot) */
-};
-
-static struct rc_keymap eztv_map = {
-	.map = {
-		.scan    = eztv,
-		.size    = ARRAY_SIZE(eztv),
-		.ir_type = IR_TYPE_UNKNOWN,	/* Legacy IR type */
-		.name    = RC_MAP_EZTV,
-	}
-};
-
-static int __init init_rc_map_eztv(void)
-{
-	return ir_register_map(&eztv_map);
-}
-
-static void __exit exit_rc_map_eztv(void)
-{
-	ir_unregister_map(&eztv_map);
-}
-
-module_init(init_rc_map_eztv)
-module_exit(exit_rc_map_eztv)
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-flydvb.c linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-flydvb.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-flydvb.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-flydvb.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,77 +0,0 @@
-/* flydvb.h - Keytable for flydvb Remote Controller
- *
- * keymap imported from ir-keymaps.c
- *
- * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
-
-static struct ir_scancode flydvb[] = {
-	{ 0x01, KEY_ZOOM },		/* Full Screen */
-	{ 0x00, KEY_POWER },		/* Power */
-
-	{ 0x03, KEY_1 },
-	{ 0x04, KEY_2 },
-	{ 0x05, KEY_3 },
-	{ 0x07, KEY_4 },
-	{ 0x08, KEY_5 },
-	{ 0x09, KEY_6 },
-	{ 0x0b, KEY_7 },
-	{ 0x0c, KEY_8 },
-	{ 0x0d, KEY_9 },
-	{ 0x06, KEY_AGAIN },		/* Recall */
-	{ 0x0f, KEY_0 },
-	{ 0x10, KEY_MUTE },		/* Mute */
-	{ 0x02, KEY_RADIO },		/* TV/Radio */
-	{ 0x1b, KEY_LANGUAGE },		/* SAP (Second Audio Program) */
-
-	{ 0x14, KEY_VOLUMEUP },		/* VOL+ */
-	{ 0x17, KEY_VOLUMEDOWN },	/* VOL- */
-	{ 0x12, KEY_CHANNELUP },	/* CH+ */
-	{ 0x13, KEY_CHANNELDOWN },	/* CH- */
-	{ 0x1d, KEY_ENTER },		/* Enter */
-
-	{ 0x1a, KEY_MODE },		/* PIP */
-	{ 0x18, KEY_TUNER },		/* Source */
-
-	{ 0x1e, KEY_RECORD },		/* Record/Pause */
-	{ 0x15, KEY_ANGLE },		/* Swap (no label on key) */
-	{ 0x1c, KEY_PAUSE },		/* Timeshift/Pause */
-	{ 0x19, KEY_BACK },		/* Rewind << */
-	{ 0x0a, KEY_PLAYPAUSE },	/* Play/Pause */
-	{ 0x1f, KEY_FORWARD },		/* Forward >> */
-	{ 0x16, KEY_PREVIOUS },		/* Back |<< */
-	{ 0x11, KEY_STOP },		/* Stop */
-	{ 0x0e, KEY_NEXT },		/* End >>| */
-};
-
-static struct rc_keymap flydvb_map = {
-	.map = {
-		.scan    = flydvb,
-		.size    = ARRAY_SIZE(flydvb),
-		.ir_type = IR_TYPE_UNKNOWN,	/* Legacy IR type */
-		.name    = RC_MAP_FLYDVB,
-	}
-};
-
-static int __init init_rc_map_flydvb(void)
-{
-	return ir_register_map(&flydvb_map);
-}
-
-static void __exit exit_rc_map_flydvb(void)
-{
-	ir_unregister_map(&flydvb_map);
-}
-
-module_init(init_rc_map_flydvb)
-module_exit(exit_rc_map_flydvb)
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-flyvideo.c linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-flyvideo.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-flyvideo.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-flyvideo.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,70 +0,0 @@
-/* flyvideo.h - Keytable for flyvideo Remote Controller
- *
- * keymap imported from ir-keymaps.c
- *
- * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
-
-static struct ir_scancode flyvideo[] = {
-	{ 0x0f, KEY_0 },
-	{ 0x03, KEY_1 },
-	{ 0x04, KEY_2 },
-	{ 0x05, KEY_3 },
-	{ 0x07, KEY_4 },
-	{ 0x08, KEY_5 },
-	{ 0x09, KEY_6 },
-	{ 0x0b, KEY_7 },
-	{ 0x0c, KEY_8 },
-	{ 0x0d, KEY_9 },
-
-	{ 0x0e, KEY_MODE },	/* Air/Cable */
-	{ 0x11, KEY_VIDEO },	/* Video */
-	{ 0x15, KEY_AUDIO },	/* Audio */
-	{ 0x00, KEY_POWER },	/* Power */
-	{ 0x18, KEY_TUNER },	/* AV Source */
-	{ 0x02, KEY_ZOOM },	/* Fullscreen */
-	{ 0x1a, KEY_LANGUAGE },	/* Stereo */
-	{ 0x1b, KEY_MUTE },	/* Mute */
-	{ 0x14, KEY_VOLUMEUP },	/* Volume + */
-	{ 0x17, KEY_VOLUMEDOWN },/* Volume - */
-	{ 0x12, KEY_CHANNELUP },/* Channel + */
-	{ 0x13, KEY_CHANNELDOWN },/* Channel - */
-	{ 0x06, KEY_AGAIN },	/* Recall */
-	{ 0x10, KEY_ENTER },	/* Enter */
-
-	{ 0x19, KEY_BACK },	/* Rewind  ( <<< ) */
-	{ 0x1f, KEY_FORWARD },	/* Forward ( >>> ) */
-	{ 0x0a, KEY_ANGLE },	/* no label, may be used as the PAUSE button */
-};
-
-static struct rc_keymap flyvideo_map = {
-	.map = {
-		.scan    = flyvideo,
-		.size    = ARRAY_SIZE(flyvideo),
-		.ir_type = IR_TYPE_UNKNOWN,	/* Legacy IR type */
-		.name    = RC_MAP_FLYVIDEO,
-	}
-};
-
-static int __init init_rc_map_flyvideo(void)
-{
-	return ir_register_map(&flyvideo_map);
-}
-
-static void __exit exit_rc_map_flyvideo(void)
-{
-	ir_unregister_map(&flyvideo_map);
-}
-
-module_init(init_rc_map_flyvideo)
-module_exit(exit_rc_map_flyvideo)
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-fusionhdtv-mce.c linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-fusionhdtv-mce.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-fusionhdtv-mce.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-fusionhdtv-mce.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,98 +0,0 @@
-/* fusionhdtv-mce.h - Keytable for fusionhdtv_mce Remote Controller
- *
- * keymap imported from ir-keymaps.c
- *
- * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
-
-/* DViCO FUSION HDTV MCE remote */
-
-static struct ir_scancode fusionhdtv_mce[] = {
-
-	{ 0x0b, KEY_1 },
-	{ 0x17, KEY_2 },
-	{ 0x1b, KEY_3 },
-	{ 0x07, KEY_4 },
-	{ 0x50, KEY_5 },
-	{ 0x54, KEY_6 },
-	{ 0x48, KEY_7 },
-	{ 0x4c, KEY_8 },
-	{ 0x58, KEY_9 },
-	{ 0x03, KEY_0 },
-
-	{ 0x5e, KEY_OK },
-	{ 0x51, KEY_UP },
-	{ 0x53, KEY_DOWN },
-	{ 0x5b, KEY_LEFT },
-	{ 0x5f, KEY_RIGHT },
-
-	{ 0x02, KEY_TV },		/* Labeled DTV on remote */
-	{ 0x0e, KEY_MP3 },
-	{ 0x1a, KEY_DVD },
-	{ 0x1e, KEY_FAVORITES },	/* Labeled CPF on remote */
-	{ 0x16, KEY_SETUP },
-	{ 0x46, KEY_POWER2 },		/* TV On/Off button on remote */
-	{ 0x0a, KEY_EPG },		/* Labeled Guide on remote */
-
-	{ 0x49, KEY_BACK },
-	{ 0x59, KEY_INFO },		/* Labeled MORE on remote */
-	{ 0x4d, KEY_MENU },		/* Labeled DVDMENU on remote */
-	{ 0x55, KEY_CYCLEWINDOWS },	/* Labeled ALT-TAB on remote */
-
-	{ 0x0f, KEY_PREVIOUSSONG },	/* Labeled |<< REPLAY on remote */
-	{ 0x12, KEY_NEXTSONG },		/* Labeled >>| SKIP on remote */
-	{ 0x42, KEY_ENTER },		/* Labeled START with a green
-					   MS windows logo on remote */
-
-	{ 0x15, KEY_VOLUMEUP },
-	{ 0x05, KEY_VOLUMEDOWN },
-	{ 0x11, KEY_CHANNELUP },
-	{ 0x09, KEY_CHANNELDOWN },
-
-	{ 0x52, KEY_CAMERA },
-	{ 0x5a, KEY_TUNER },
-	{ 0x19, KEY_OPEN },
-
-	{ 0x13, KEY_MODE },		/* 4:3 16:9 select */
-	{ 0x1f, KEY_ZOOM },
-
-	{ 0x43, KEY_REWIND },
-	{ 0x47, KEY_PLAYPAUSE },
-	{ 0x4f, KEY_FASTFORWARD },
-	{ 0x57, KEY_MUTE },
-	{ 0x0d, KEY_STOP },
-	{ 0x01, KEY_RECORD },
-	{ 0x4e, KEY_POWER },
-};
-
-static struct rc_keymap fusionhdtv_mce_map = {
-	.map = {
-		.scan    = fusionhdtv_mce,
-		.size    = ARRAY_SIZE(fusionhdtv_mce),
-		.ir_type = IR_TYPE_UNKNOWN,	/* Legacy IR type */
-		.name    = RC_MAP_FUSIONHDTV_MCE,
-	}
-};
-
-static int __init init_rc_map_fusionhdtv_mce(void)
-{
-	return ir_register_map(&fusionhdtv_mce_map);
-}
-
-static void __exit exit_rc_map_fusionhdtv_mce(void)
-{
-	ir_unregister_map(&fusionhdtv_mce_map);
-}
-
-module_init(init_rc_map_fusionhdtv_mce)
-module_exit(exit_rc_map_fusionhdtv_mce)
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-gadmei-rm008z.c linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-gadmei-rm008z.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-gadmei-rm008z.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-gadmei-rm008z.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,81 +0,0 @@
-/* gadmei-rm008z.h - Keytable for gadmei_rm008z Remote Controller
- *
- * keymap imported from ir-keymaps.c
- *
- * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
-
-/* GADMEI UTV330+ RM008Z remote
-   Shine Liu <shinel@foxmail.com>
- */
-
-static struct ir_scancode gadmei_rm008z[] = {
-	{ 0x14, KEY_POWER2},		/* POWER OFF */
-	{ 0x0c, KEY_MUTE},		/* MUTE */
-
-	{ 0x18, KEY_TV},		/* TV */
-	{ 0x0e, KEY_VIDEO},		/* AV */
-	{ 0x0b, KEY_AUDIO},		/* SV */
-	{ 0x0f, KEY_RADIO},		/* FM */
-
-	{ 0x00, KEY_1},
-	{ 0x01, KEY_2},
-	{ 0x02, KEY_3},
-	{ 0x03, KEY_4},
-	{ 0x04, KEY_5},
-	{ 0x05, KEY_6},
-	{ 0x06, KEY_7},
-	{ 0x07, KEY_8},
-	{ 0x08, KEY_9},
-	{ 0x09, KEY_0},
-	{ 0x0a, KEY_INFO},		/* OSD */
-	{ 0x1c, KEY_BACKSPACE},		/* LAST */
-
-	{ 0x0d, KEY_PLAY},		/* PLAY */
-	{ 0x1e, KEY_CAMERA},		/* SNAPSHOT */
-	{ 0x1a, KEY_RECORD},		/* RECORD */
-	{ 0x17, KEY_STOP},		/* STOP */
-
-	{ 0x1f, KEY_UP},		/* UP */
-	{ 0x44, KEY_DOWN},		/* DOWN */
-	{ 0x46, KEY_TAB},		/* BACK */
-	{ 0x4a, KEY_ZOOM},		/* FULLSECREEN */
-
-	{ 0x10, KEY_VOLUMEUP},		/* VOLUMEUP */
-	{ 0x11, KEY_VOLUMEDOWN},	/* VOLUMEDOWN */
-	{ 0x12, KEY_CHANNELUP},		/* CHANNELUP */
-	{ 0x13, KEY_CHANNELDOWN},	/* CHANNELDOWN */
-	{ 0x15, KEY_ENTER},		/* OK */
-};
-
-static struct rc_keymap gadmei_rm008z_map = {
-	.map = {
-		.scan    = gadmei_rm008z,
-		.size    = ARRAY_SIZE(gadmei_rm008z),
-		.ir_type = IR_TYPE_UNKNOWN,	/* Legacy IR type */
-		.name    = RC_MAP_GADMEI_RM008Z,
-	}
-};
-
-static int __init init_rc_map_gadmei_rm008z(void)
-{
-	return ir_register_map(&gadmei_rm008z_map);
-}
-
-static void __exit exit_rc_map_gadmei_rm008z(void)
-{
-	ir_unregister_map(&gadmei_rm008z_map);
-}
-
-module_init(init_rc_map_gadmei_rm008z)
-module_exit(exit_rc_map_gadmei_rm008z)
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-genius-tvgo-a11mce.c linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-genius-tvgo-a11mce.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-genius-tvgo-a11mce.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-genius-tvgo-a11mce.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,84 +0,0 @@
-/* genius-tvgo-a11mce.h - Keytable for genius_tvgo_a11mce Remote Controller
- *
- * keymap imported from ir-keymaps.c
- *
- * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
-
-/*
- * Remote control for the Genius TVGO A11MCE
- * Adrian Pardini <pardo.bsso@gmail.com>
- */
-
-static struct ir_scancode genius_tvgo_a11mce[] = {
-	/* Keys 0 to 9 */
-	{ 0x48, KEY_0 },
-	{ 0x09, KEY_1 },
-	{ 0x1d, KEY_2 },
-	{ 0x1f, KEY_3 },
-	{ 0x19, KEY_4 },
-	{ 0x1b, KEY_5 },
-	{ 0x11, KEY_6 },
-	{ 0x17, KEY_7 },
-	{ 0x12, KEY_8 },
-	{ 0x16, KEY_9 },
-
-	{ 0x54, KEY_RECORD },		/* recording */
-	{ 0x06, KEY_MUTE },		/* mute */
-	{ 0x10, KEY_POWER },
-	{ 0x40, KEY_LAST },		/* recall */
-	{ 0x4c, KEY_CHANNELUP },	/* channel / program + */
-	{ 0x00, KEY_CHANNELDOWN },	/* channel / program - */
-	{ 0x0d, KEY_VOLUMEUP },
-	{ 0x15, KEY_VOLUMEDOWN },
-	{ 0x4d, KEY_OK },		/* also labeled as Pause */
-	{ 0x1c, KEY_ZOOM },		/* full screen and Stop*/
-	{ 0x02, KEY_MODE },		/* AV Source or Rewind*/
-	{ 0x04, KEY_LIST },		/* -/-- */
-	/* small arrows above numbers */
-	{ 0x1a, KEY_NEXT },		/* also Fast Forward */
-	{ 0x0e, KEY_PREVIOUS },		/* also Rewind */
-	/* these are in a rather non standard layout and have
-	an alternate name written */
-	{ 0x1e, KEY_UP },		/* Video Setting */
-	{ 0x0a, KEY_DOWN },		/* Video Default */
-	{ 0x05, KEY_CAMERA },		/* Snapshot */
-	{ 0x0c, KEY_RIGHT },		/* Hide Panel */
-	/* Four buttons without label */
-	{ 0x49, KEY_RED },
-	{ 0x0b, KEY_GREEN },
-	{ 0x13, KEY_YELLOW },
-	{ 0x50, KEY_BLUE },
-};
-
-static struct rc_keymap genius_tvgo_a11mce_map = {
-	.map = {
-		.scan    = genius_tvgo_a11mce,
-		.size    = ARRAY_SIZE(genius_tvgo_a11mce),
-		.ir_type = IR_TYPE_UNKNOWN,	/* Legacy IR type */
-		.name    = RC_MAP_GENIUS_TVGO_A11MCE,
-	}
-};
-
-static int __init init_rc_map_genius_tvgo_a11mce(void)
-{
-	return ir_register_map(&genius_tvgo_a11mce_map);
-}
-
-static void __exit exit_rc_map_genius_tvgo_a11mce(void)
-{
-	ir_unregister_map(&genius_tvgo_a11mce_map);
-}
-
-module_init(init_rc_map_genius_tvgo_a11mce)
-module_exit(exit_rc_map_genius_tvgo_a11mce)
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-gotview7135.c linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-gotview7135.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-gotview7135.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-gotview7135.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,79 +0,0 @@
-/* gotview7135.h - Keytable for gotview7135 Remote Controller
- *
- * keymap imported from ir-keymaps.c
- *
- * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
-
-/* Mike Baikov <mike@baikov.com> */
-
-static struct ir_scancode gotview7135[] = {
-
-	{ 0x11, KEY_POWER },
-	{ 0x35, KEY_TV },
-	{ 0x1b, KEY_0 },
-	{ 0x29, KEY_1 },
-	{ 0x19, KEY_2 },
-	{ 0x39, KEY_3 },
-	{ 0x1f, KEY_4 },
-	{ 0x2c, KEY_5 },
-	{ 0x21, KEY_6 },
-	{ 0x24, KEY_7 },
-	{ 0x18, KEY_8 },
-	{ 0x2b, KEY_9 },
-	{ 0x3b, KEY_AGAIN },	/* LOOP */
-	{ 0x06, KEY_AUDIO },
-	{ 0x31, KEY_PRINT },	/* PREVIEW */
-	{ 0x3e, KEY_VIDEO },
-	{ 0x10, KEY_CHANNELUP },
-	{ 0x20, KEY_CHANNELDOWN },
-	{ 0x0c, KEY_VOLUMEDOWN },
-	{ 0x28, KEY_VOLUMEUP },
-	{ 0x08, KEY_MUTE },
-	{ 0x26, KEY_SEARCH },	/* SCAN */
-	{ 0x3f, KEY_CAMERA },	/* SNAPSHOT */
-	{ 0x12, KEY_RECORD },
-	{ 0x32, KEY_STOP },
-	{ 0x3c, KEY_PLAY },
-	{ 0x1d, KEY_REWIND },
-	{ 0x2d, KEY_PAUSE },
-	{ 0x0d, KEY_FORWARD },
-	{ 0x05, KEY_ZOOM },	/*FULL*/
-
-	{ 0x2a, KEY_F21 },	/* LIVE TIMESHIFT */
-	{ 0x0e, KEY_F22 },	/* MIN TIMESHIFT */
-	{ 0x1e, KEY_TIME },	/* TIMESHIFT */
-	{ 0x38, KEY_F24 },	/* NORMAL TIMESHIFT */
-};
-
-static struct rc_keymap gotview7135_map = {
-	.map = {
-		.scan    = gotview7135,
-		.size    = ARRAY_SIZE(gotview7135),
-		.ir_type = IR_TYPE_UNKNOWN,	/* Legacy IR type */
-		.name    = RC_MAP_GOTVIEW7135,
-	}
-};
-
-static int __init init_rc_map_gotview7135(void)
-{
-	return ir_register_map(&gotview7135_map);
-}
-
-static void __exit exit_rc_map_gotview7135(void)
-{
-	ir_unregister_map(&gotview7135_map);
-}
-
-module_init(init_rc_map_gotview7135)
-module_exit(exit_rc_map_gotview7135)
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-hauppauge-new.c linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-hauppauge-new.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-hauppauge-new.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-hauppauge-new.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,100 +0,0 @@
-/* hauppauge-new.h - Keytable for hauppauge_new Remote Controller
- *
- * keymap imported from ir-keymaps.c
- *
- * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
-
-/* Hauppauge: the newer, gray remotes (seems there are multiple
- * slightly different versions), shipped with cx88+ivtv cards.
- * almost rc5 coding, but some non-standard keys */
-
-static struct ir_scancode hauppauge_new[] = {
-	/* Keys 0 to 9 */
-	{ 0x00, KEY_0 },
-	{ 0x01, KEY_1 },
-	{ 0x02, KEY_2 },
-	{ 0x03, KEY_3 },
-	{ 0x04, KEY_4 },
-	{ 0x05, KEY_5 },
-	{ 0x06, KEY_6 },
-	{ 0x07, KEY_7 },
-	{ 0x08, KEY_8 },
-	{ 0x09, KEY_9 },
-
-	{ 0x0a, KEY_TEXT },		/* keypad asterisk as well */
-	{ 0x0b, KEY_RED },		/* red button */
-	{ 0x0c, KEY_RADIO },
-	{ 0x0d, KEY_MENU },
-	{ 0x0e, KEY_SUBTITLE },		/* also the # key */
-	{ 0x0f, KEY_MUTE },
-	{ 0x10, KEY_VOLUMEUP },
-	{ 0x11, KEY_VOLUMEDOWN },
-	{ 0x12, KEY_PREVIOUS },		/* previous channel */
-	{ 0x14, KEY_UP },
-	{ 0x15, KEY_DOWN },
-	{ 0x16, KEY_LEFT },
-	{ 0x17, KEY_RIGHT },
-	{ 0x18, KEY_VIDEO },		/* Videos */
-	{ 0x19, KEY_AUDIO },		/* Music */
-	/* 0x1a: Pictures - presume this means
-	   "Multimedia Home Platform" -
-	   no "PICTURES" key in input.h
-	 */
-	{ 0x1a, KEY_MHP },
-
-	{ 0x1b, KEY_EPG },		/* Guide */
-	{ 0x1c, KEY_TV },
-	{ 0x1e, KEY_NEXTSONG },		/* skip >| */
-	{ 0x1f, KEY_EXIT },		/* back/exit */
-	{ 0x20, KEY_CHANNELUP },	/* channel / program + */
-	{ 0x21, KEY_CHANNELDOWN },	/* channel / program - */
-	{ 0x22, KEY_CHANNEL },		/* source (old black remote) */
-	{ 0x24, KEY_PREVIOUSSONG },	/* replay |< */
-	{ 0x25, KEY_ENTER },		/* OK */
-	{ 0x26, KEY_SLEEP },		/* minimize (old black remote) */
-	{ 0x29, KEY_BLUE },		/* blue key */
-	{ 0x2e, KEY_GREEN },		/* green button */
-	{ 0x30, KEY_PAUSE },		/* pause */
-	{ 0x32, KEY_REWIND },		/* backward << */
-	{ 0x34, KEY_FASTFORWARD },	/* forward >> */
-	{ 0x35, KEY_PLAY },
-	{ 0x36, KEY_STOP },
-	{ 0x37, KEY_RECORD },		/* recording */
-	{ 0x38, KEY_YELLOW },		/* yellow key */
-	{ 0x3b, KEY_SELECT },		/* top right button */
-	{ 0x3c, KEY_ZOOM },		/* full */
-	{ 0x3d, KEY_POWER },		/* system power (green button) */
-};
-
-static struct rc_keymap hauppauge_new_map = {
-	.map = {
-		.scan    = hauppauge_new,
-		.size    = ARRAY_SIZE(hauppauge_new),
-		.ir_type = IR_TYPE_UNKNOWN,	/* Legacy IR type */
-		.name    = RC_MAP_HAUPPAUGE_NEW,
-	}
-};
-
-static int __init init_rc_map_hauppauge_new(void)
-{
-	return ir_register_map(&hauppauge_new_map);
-}
-
-static void __exit exit_rc_map_hauppauge_new(void)
-{
-	ir_unregister_map(&hauppauge_new_map);
-}
-
-module_init(init_rc_map_hauppauge_new)
-module_exit(exit_rc_map_hauppauge_new)
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-imon-mce.c linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-imon-mce.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-imon-mce.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-imon-mce.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,142 +0,0 @@
-/* rc5-imon-mce.c - Keytable for Windows Media Center RC-6 remotes for use
- * with the SoundGraph iMON/Antec Veris hardware IR decoder
- *
- * Copyright (c) 2010 by Jarod Wilson <jarod@redhat.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 <media/rc-map.h>
-
-/* mce-mode imon mce remote key table */
-static struct ir_scancode imon_mce[] = {
-	/* keys sorted mostly by frequency of use to optimize lookups */
-	{ 0x800ff415, KEY_REWIND },
-	{ 0x800ff414, KEY_FASTFORWARD },
-	{ 0x800ff41b, KEY_PREVIOUS },
-	{ 0x800ff41a, KEY_NEXT },
-
-	{ 0x800ff416, KEY_PLAY },
-	{ 0x800ff418, KEY_PAUSE },
-	{ 0x800ff419, KEY_STOP },
-	{ 0x800ff417, KEY_RECORD },
-
-	{ 0x02000052, KEY_UP },
-	{ 0x02000051, KEY_DOWN },
-	{ 0x02000050, KEY_LEFT },
-	{ 0x0200004f, KEY_RIGHT },
-
-	{ 0x800ff41e, KEY_UP },
-	{ 0x800ff41f, KEY_DOWN },
-	{ 0x800ff420, KEY_LEFT },
-	{ 0x800ff421, KEY_RIGHT },
-
-	/* 0x800ff40b also KEY_NUMERIC_POUND on some receivers */
-	{ 0x800ff40b, KEY_ENTER },
-	{ 0x02000028, KEY_ENTER },
-/* the OK and Enter buttons decode to the same value on some remotes
-	{ 0x02000028, KEY_OK }, */
-	{ 0x800ff422, KEY_OK },
-	{ 0x0200002a, KEY_EXIT },
-	{ 0x800ff423, KEY_EXIT },
-	{ 0x02000029, KEY_DELETE },
-	/* 0x800ff40a also KEY_NUMERIC_STAR on some receivers */
-	{ 0x800ff40a, KEY_DELETE },
-
-	{ 0x800ff40e, KEY_MUTE },
-	{ 0x800ff410, KEY_VOLUMEUP },
-	{ 0x800ff411, KEY_VOLUMEDOWN },
-	{ 0x800ff412, KEY_CHANNELUP },
-	{ 0x800ff413, KEY_CHANNELDOWN },
-
-	{ 0x0200001e, KEY_NUMERIC_1 },
-	{ 0x0200001f, KEY_NUMERIC_2 },
-	{ 0x02000020, KEY_NUMERIC_3 },
-	{ 0x02000021, KEY_NUMERIC_4 },
-	{ 0x02000022, KEY_NUMERIC_5 },
-	{ 0x02000023, KEY_NUMERIC_6 },
-	{ 0x02000024, KEY_NUMERIC_7 },
-	{ 0x02000025, KEY_NUMERIC_8 },
-	{ 0x02000026, KEY_NUMERIC_9 },
-	{ 0x02000027, KEY_NUMERIC_0 },
-
-	{ 0x800ff401, KEY_NUMERIC_1 },
-	{ 0x800ff402, KEY_NUMERIC_2 },
-	{ 0x800ff403, KEY_NUMERIC_3 },
-	{ 0x800ff404, KEY_NUMERIC_4 },
-	{ 0x800ff405, KEY_NUMERIC_5 },
-	{ 0x800ff406, KEY_NUMERIC_6 },
-	{ 0x800ff407, KEY_NUMERIC_7 },
-	{ 0x800ff408, KEY_NUMERIC_8 },
-	{ 0x800ff409, KEY_NUMERIC_9 },
-	{ 0x800ff400, KEY_NUMERIC_0 },
-
-	{ 0x02200025, KEY_NUMERIC_STAR },
-	{ 0x02200020, KEY_NUMERIC_POUND },
-	/* 0x800ff41d also KEY_BLUE on some receivers */
-	{ 0x800ff41d, KEY_NUMERIC_STAR },
-	/* 0x800ff41c also KEY_PREVIOUS on some receivers */
-	{ 0x800ff41c, KEY_NUMERIC_POUND },
-
-	{ 0x800ff446, KEY_TV },
-	{ 0x800ff447, KEY_AUDIO }, /* My Music */
-	{ 0x800ff448, KEY_PVR }, /* RecordedTV */
-	{ 0x800ff449, KEY_CAMERA },
-	{ 0x800ff44a, KEY_VIDEO },
-	/* 0x800ff424 also KEY_MENU on some receivers */
-	{ 0x800ff424, KEY_DVD },
-	/* 0x800ff425 also KEY_GREEN on some receivers */
-	{ 0x800ff425, KEY_TUNER }, /* LiveTV */
-	{ 0x800ff450, KEY_RADIO },
-
-	{ 0x800ff44c, KEY_LANGUAGE },
-	{ 0x800ff427, KEY_ZOOM }, /* Aspect */
-
-	{ 0x800ff45b, KEY_RED },
-	{ 0x800ff45c, KEY_GREEN },
-	{ 0x800ff45d, KEY_YELLOW },
-	{ 0x800ff45e, KEY_BLUE },
-
-	{ 0x800ff466, KEY_RED },
-	/* { 0x800ff425, KEY_GREEN }, */
-	{ 0x800ff468, KEY_YELLOW },
-	/* { 0x800ff41d, KEY_BLUE }, */
-
-	{ 0x800ff40f, KEY_INFO },
-	{ 0x800ff426, KEY_EPG }, /* Guide */
-	{ 0x800ff45a, KEY_SUBTITLE }, /* Caption/Teletext */
-	{ 0x800ff44d, KEY_TITLE },
-
-	{ 0x800ff40c, KEY_POWER },
-	{ 0x800ff40d, KEY_PROG1 }, /* Windows MCE button */
-
-};
-
-static struct rc_keymap imon_mce_map = {
-	.map = {
-		.scan    = imon_mce,
-		.size    = ARRAY_SIZE(imon_mce),
-		/* its RC6, but w/a hardware decoder */
-		.ir_type = IR_TYPE_RC6,
-		.name    = RC_MAP_IMON_MCE,
-	}
-};
-
-static int __init init_rc_map_imon_mce(void)
-{
-	return ir_register_map(&imon_mce_map);
-}
-
-static void __exit exit_rc_map_imon_mce(void)
-{
-	ir_unregister_map(&imon_mce_map);
-}
-
-module_init(init_rc_map_imon_mce)
-module_exit(exit_rc_map_imon_mce)
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Jarod Wilson <jarod@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-imon-pad.c linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-imon-pad.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-imon-pad.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-imon-pad.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,156 +0,0 @@
-/* rc5-imon-pad.c - Keytable for SoundGraph iMON PAD and Antec Veris
- * RM-200 Remote Control
- *
- * Copyright (c) 2010 by Jarod Wilson <jarod@redhat.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 <media/rc-map.h>
-
-/*
- * standard imon remote key table, which isn't really entirely
- * "standard", as different receivers decode the same key on the
- * same remote to different hex codes, and the silkscreened names
- * vary a bit between the SoundGraph and Antec remotes... ugh.
- */
-static struct ir_scancode imon_pad[] = {
-	/* keys sorted mostly by frequency of use to optimize lookups */
-	{ 0x2a8195b7, KEY_REWIND },
-	{ 0x298315b7, KEY_REWIND },
-	{ 0x2b8115b7, KEY_FASTFORWARD },
-	{ 0x2b8315b7, KEY_FASTFORWARD },
-	{ 0x2b9115b7, KEY_PREVIOUS },
-	{ 0x298195b7, KEY_NEXT },
-
-	{ 0x2a8115b7, KEY_PLAY },
-	{ 0x2a8315b7, KEY_PLAY },
-	{ 0x2a9115b7, KEY_PAUSE },
-	{ 0x2b9715b7, KEY_STOP },
-	{ 0x298115b7, KEY_RECORD },
-
-	{ 0x01008000, KEY_UP },
-	{ 0x01007f00, KEY_DOWN },
-	{ 0x01000080, KEY_LEFT },
-	{ 0x0100007f, KEY_RIGHT },
-
-	{ 0x2aa515b7, KEY_UP },
-	{ 0x289515b7, KEY_DOWN },
-	{ 0x29a515b7, KEY_LEFT },
-	{ 0x2ba515b7, KEY_RIGHT },
-
-	{ 0x0200002c, KEY_SPACE }, /* Select/Space */
-	{ 0x2a9315b7, KEY_SPACE }, /* Select/Space */
-	{ 0x02000028, KEY_ENTER },
-	{ 0x28a195b7, KEY_ENTER },
-	{ 0x288195b7, KEY_EXIT },
-	{ 0x02000029, KEY_ESC },
-	{ 0x2bb715b7, KEY_ESC },
-	{ 0x0200002a, KEY_BACKSPACE },
-	{ 0x28a115b7, KEY_BACKSPACE },
-
-	{ 0x2b9595b7, KEY_MUTE },
-	{ 0x28a395b7, KEY_VOLUMEUP },
-	{ 0x28a595b7, KEY_VOLUMEDOWN },
-	{ 0x289395b7, KEY_CHANNELUP },
-	{ 0x288795b7, KEY_CHANNELDOWN },
-
-	{ 0x0200001e, KEY_NUMERIC_1 },
-	{ 0x0200001f, KEY_NUMERIC_2 },
-	{ 0x02000020, KEY_NUMERIC_3 },
-	{ 0x02000021, KEY_NUMERIC_4 },
-	{ 0x02000022, KEY_NUMERIC_5 },
-	{ 0x02000023, KEY_NUMERIC_6 },
-	{ 0x02000024, KEY_NUMERIC_7 },
-	{ 0x02000025, KEY_NUMERIC_8 },
-	{ 0x02000026, KEY_NUMERIC_9 },
-	{ 0x02000027, KEY_NUMERIC_0 },
-
-	{ 0x28b595b7, KEY_NUMERIC_1 },
-	{ 0x2bb195b7, KEY_NUMERIC_2 },
-	{ 0x28b195b7, KEY_NUMERIC_3 },
-	{ 0x2a8595b7, KEY_NUMERIC_4 },
-	{ 0x299595b7, KEY_NUMERIC_5 },
-	{ 0x2aa595b7, KEY_NUMERIC_6 },
-	{ 0x2b9395b7, KEY_NUMERIC_7 },
-	{ 0x2a8515b7, KEY_NUMERIC_8 },
-	{ 0x2aa115b7, KEY_NUMERIC_9 },
-	{ 0x2ba595b7, KEY_NUMERIC_0 },
-
-	{ 0x02200025, KEY_NUMERIC_STAR },
-	{ 0x28b515b7, KEY_NUMERIC_STAR },
-	{ 0x02200020, KEY_NUMERIC_POUND },
-	{ 0x29a115b7, KEY_NUMERIC_POUND },
-
-	{ 0x2b8515b7, KEY_VIDEO },
-	{ 0x299195b7, KEY_AUDIO },
-	{ 0x2ba115b7, KEY_CAMERA },
-	{ 0x28a515b7, KEY_TV },
-	{ 0x29a395b7, KEY_DVD },
-	{ 0x29a295b7, KEY_DVD },
-
-	/* the Menu key between DVD and Subtitle on the RM-200... */
-	{ 0x2ba385b7, KEY_MENU },
-	{ 0x2ba395b7, KEY_MENU },
-
-	{ 0x288515b7, KEY_BOOKMARKS },
-	{ 0x2ab715b7, KEY_MEDIA }, /* Thumbnail */
-	{ 0x298595b7, KEY_SUBTITLE },
-	{ 0x2b8595b7, KEY_LANGUAGE },
-
-	{ 0x29a595b7, KEY_ZOOM },
-	{ 0x2aa395b7, KEY_SCREEN }, /* FullScreen */
-
-	{ 0x299115b7, KEY_KEYBOARD },
-	{ 0x299135b7, KEY_KEYBOARD },
-
-	{ 0x01010000, BTN_LEFT },
-	{ 0x01020000, BTN_RIGHT },
-	{ 0x01010080, BTN_LEFT },
-	{ 0x01020080, BTN_RIGHT },
-	{ 0x688301b7, BTN_LEFT },
-	{ 0x688481b7, BTN_RIGHT },
-
-	{ 0x2a9395b7, KEY_CYCLEWINDOWS }, /* TaskSwitcher */
-	{ 0x2b8395b7, KEY_TIME }, /* Timer */
-
-	{ 0x289115b7, KEY_POWER },
-	{ 0x29b195b7, KEY_EJECTCD }, /* the one next to play */
-	{ 0x299395b7, KEY_EJECTCLOSECD }, /* eject (by TaskSw) */
-
-	{ 0x02800000, KEY_CONTEXT_MENU }, /* Left Menu */
-	{ 0x2b8195b7, KEY_CONTEXT_MENU }, /* Left Menu*/
-	{ 0x02000065, KEY_COMPOSE }, /* RightMenu */
-	{ 0x28b715b7, KEY_COMPOSE }, /* RightMenu */
-	{ 0x2ab195b7, KEY_PROG1 }, /* Go or MultiMon */
-	{ 0x29b715b7, KEY_DASHBOARD }, /* AppLauncher */
-};
-
-static struct rc_keymap imon_pad_map = {
-	.map = {
-		.scan    = imon_pad,
-		.size    = ARRAY_SIZE(imon_pad),
-		/* actual protocol details unknown, hardware decoder */
-		.ir_type = IR_TYPE_OTHER,
-		.name    = RC_MAP_IMON_PAD,
-	}
-};
-
-static int __init init_rc_map_imon_pad(void)
-{
-	return ir_register_map(&imon_pad_map);
-}
-
-static void __exit exit_rc_map_imon_pad(void)
-{
-	ir_unregister_map(&imon_pad_map);
-}
-
-module_init(init_rc_map_imon_pad)
-module_exit(exit_rc_map_imon_pad)
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Jarod Wilson <jarod@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-iodata-bctv7e.c linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-iodata-bctv7e.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-iodata-bctv7e.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-iodata-bctv7e.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,88 +0,0 @@
-/* iodata-bctv7e.h - Keytable for iodata_bctv7e Remote Controller
- *
- * keymap imported from ir-keymaps.c
- *
- * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
-
-/* IO-DATA BCTV7E Remote */
-
-static struct ir_scancode iodata_bctv7e[] = {
-	{ 0x40, KEY_TV },
-	{ 0x20, KEY_RADIO },		/* FM */
-	{ 0x60, KEY_EPG },
-	{ 0x00, KEY_POWER },
-
-	/* Keys 0 to 9 */
-	{ 0x44, KEY_0 },		/* 10 */
-	{ 0x50, KEY_1 },
-	{ 0x30, KEY_2 },
-	{ 0x70, KEY_3 },
-	{ 0x48, KEY_4 },
-	{ 0x28, KEY_5 },
-	{ 0x68, KEY_6 },
-	{ 0x58, KEY_7 },
-	{ 0x38, KEY_8 },
-	{ 0x78, KEY_9 },
-
-	{ 0x10, KEY_L },		/* Live */
-	{ 0x08, KEY_TIME },		/* Time Shift */
-
-	{ 0x18, KEY_PLAYPAUSE },	/* Play */
-
-	{ 0x24, KEY_ENTER },		/* 11 */
-	{ 0x64, KEY_ESC },		/* 12 */
-	{ 0x04, KEY_M },		/* Multi */
-
-	{ 0x54, KEY_VIDEO },
-	{ 0x34, KEY_CHANNELUP },
-	{ 0x74, KEY_VOLUMEUP },
-	{ 0x14, KEY_MUTE },
-
-	{ 0x4c, KEY_VCR },		/* SVIDEO */
-	{ 0x2c, KEY_CHANNELDOWN },
-	{ 0x6c, KEY_VOLUMEDOWN },
-	{ 0x0c, KEY_ZOOM },
-
-	{ 0x5c, KEY_PAUSE },
-	{ 0x3c, KEY_RED },		/* || (red) */
-	{ 0x7c, KEY_RECORD },		/* recording */
-	{ 0x1c, KEY_STOP },
-
-	{ 0x41, KEY_REWIND },		/* backward << */
-	{ 0x21, KEY_PLAY },
-	{ 0x61, KEY_FASTFORWARD },	/* forward >> */
-	{ 0x01, KEY_NEXT },		/* skip >| */
-};
-
-static struct rc_keymap iodata_bctv7e_map = {
-	.map = {
-		.scan    = iodata_bctv7e,
-		.size    = ARRAY_SIZE(iodata_bctv7e),
-		.ir_type = IR_TYPE_UNKNOWN,	/* Legacy IR type */
-		.name    = RC_MAP_IODATA_BCTV7E,
-	}
-};
-
-static int __init init_rc_map_iodata_bctv7e(void)
-{
-	return ir_register_map(&iodata_bctv7e_map);
-}
-
-static void __exit exit_rc_map_iodata_bctv7e(void)
-{
-	ir_unregister_map(&iodata_bctv7e_map);
-}
-
-module_init(init_rc_map_iodata_bctv7e)
-module_exit(exit_rc_map_iodata_bctv7e)
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-kaiomy.c linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-kaiomy.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-kaiomy.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-kaiomy.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,87 +0,0 @@
-/* kaiomy.h - Keytable for kaiomy Remote Controller
- *
- * keymap imported from ir-keymaps.c
- *
- * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
-
-/* Kaiomy TVnPC U2
-   Mauro Carvalho Chehab <mchehab@infradead.org>
- */
-
-static struct ir_scancode kaiomy[] = {
-	{ 0x43, KEY_POWER2},
-	{ 0x01, KEY_LIST},
-	{ 0x0b, KEY_ZOOM},
-	{ 0x03, KEY_POWER},
-
-	{ 0x04, KEY_1},
-	{ 0x08, KEY_2},
-	{ 0x02, KEY_3},
-
-	{ 0x0f, KEY_4},
-	{ 0x05, KEY_5},
-	{ 0x06, KEY_6},
-
-	{ 0x0c, KEY_7},
-	{ 0x0d, KEY_8},
-	{ 0x0a, KEY_9},
-
-	{ 0x11, KEY_0},
-
-	{ 0x09, KEY_CHANNELUP},
-	{ 0x07, KEY_CHANNELDOWN},
-
-	{ 0x0e, KEY_VOLUMEUP},
-	{ 0x13, KEY_VOLUMEDOWN},
-
-	{ 0x10, KEY_HOME},
-	{ 0x12, KEY_ENTER},
-
-	{ 0x14, KEY_RECORD},
-	{ 0x15, KEY_STOP},
-	{ 0x16, KEY_PLAY},
-	{ 0x17, KEY_MUTE},
-
-	{ 0x18, KEY_UP},
-	{ 0x19, KEY_DOWN},
-	{ 0x1a, KEY_LEFT},
-	{ 0x1b, KEY_RIGHT},
-
-	{ 0x1c, KEY_RED},
-	{ 0x1d, KEY_GREEN},
-	{ 0x1e, KEY_YELLOW},
-	{ 0x1f, KEY_BLUE},
-};
-
-static struct rc_keymap kaiomy_map = {
-	.map = {
-		.scan    = kaiomy,
-		.size    = ARRAY_SIZE(kaiomy),
-		.ir_type = IR_TYPE_UNKNOWN,	/* Legacy IR type */
-		.name    = RC_MAP_KAIOMY,
-	}
-};
-
-static int __init init_rc_map_kaiomy(void)
-{
-	return ir_register_map(&kaiomy_map);
-}
-
-static void __exit exit_rc_map_kaiomy(void)
-{
-	ir_unregister_map(&kaiomy_map);
-}
-
-module_init(init_rc_map_kaiomy)
-module_exit(exit_rc_map_kaiomy)
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-kworld-315u.c linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-kworld-315u.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-kworld-315u.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-kworld-315u.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,83 +0,0 @@
-/* kworld-315u.h - Keytable for kworld_315u Remote Controller
- *
- * keymap imported from ir-keymaps.c
- *
- * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
-
-/* Kworld 315U
- */
-
-static struct ir_scancode kworld_315u[] = {
-	{ 0x6143, KEY_POWER },
-	{ 0x6101, KEY_TUNER },		/* source */
-	{ 0x610b, KEY_ZOOM },
-	{ 0x6103, KEY_POWER2 },		/* shutdown */
-
-	{ 0x6104, KEY_1 },
-	{ 0x6108, KEY_2 },
-	{ 0x6102, KEY_3 },
-	{ 0x6109, KEY_CHANNELUP },
-
-	{ 0x610f, KEY_4 },
-	{ 0x6105, KEY_5 },
-	{ 0x6106, KEY_6 },
-	{ 0x6107, KEY_CHANNELDOWN },
-
-	{ 0x610c, KEY_7 },
-	{ 0x610d, KEY_8 },
-	{ 0x610a, KEY_9 },
-	{ 0x610e, KEY_VOLUMEUP },
-
-	{ 0x6110, KEY_LAST },
-	{ 0x6111, KEY_0 },
-	{ 0x6112, KEY_ENTER },
-	{ 0x6113, KEY_VOLUMEDOWN },
-
-	{ 0x6114, KEY_RECORD },
-	{ 0x6115, KEY_STOP },
-	{ 0x6116, KEY_PLAY },
-	{ 0x6117, KEY_MUTE },
-
-	{ 0x6118, KEY_UP },
-	{ 0x6119, KEY_DOWN },
-	{ 0x611a, KEY_LEFT },
-	{ 0x611b, KEY_RIGHT },
-
-	{ 0x611c, KEY_RED },
-	{ 0x611d, KEY_GREEN },
-	{ 0x611e, KEY_YELLOW },
-	{ 0x611f, KEY_BLUE },
-};
-
-static struct rc_keymap kworld_315u_map = {
-	.map = {
-		.scan    = kworld_315u,
-		.size    = ARRAY_SIZE(kworld_315u),
-		.ir_type = IR_TYPE_NEC,
-		.name    = RC_MAP_KWORLD_315U,
-	}
-};
-
-static int __init init_rc_map_kworld_315u(void)
-{
-	return ir_register_map(&kworld_315u_map);
-}
-
-static void __exit exit_rc_map_kworld_315u(void)
-{
-	ir_unregister_map(&kworld_315u_map);
-}
-
-module_init(init_rc_map_kworld_315u)
-module_exit(exit_rc_map_kworld_315u)
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-kworld-plus-tv-analog.c linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-kworld-plus-tv-analog.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-kworld-plus-tv-analog.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-kworld-plus-tv-analog.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,99 +0,0 @@
-/* kworld-plus-tv-analog.h - Keytable for kworld_plus_tv_analog Remote Controller
- *
- * keymap imported from ir-keymaps.c
- *
- * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
-
-/* Kworld Plus TV Analog Lite PCI IR
-   Mauro Carvalho Chehab <mchehab@infradead.org>
- */
-
-static struct ir_scancode kworld_plus_tv_analog[] = {
-	{ 0x0c, KEY_PROG1 },		/* Kworld key */
-	{ 0x16, KEY_CLOSECD },		/* -> ) */
-	{ 0x1d, KEY_POWER2 },
-
-	{ 0x00, KEY_1 },
-	{ 0x01, KEY_2 },
-	{ 0x02, KEY_3 },		/* Two keys have the same code: 3 and left */
-	{ 0x03, KEY_4 },		/* Two keys have the same code: 3 and right */
-	{ 0x04, KEY_5 },
-	{ 0x05, KEY_6 },
-	{ 0x06, KEY_7 },
-	{ 0x07, KEY_8 },
-	{ 0x08, KEY_9 },
-	{ 0x0a, KEY_0 },
-
-	{ 0x09, KEY_AGAIN },
-	{ 0x14, KEY_MUTE },
-
-	{ 0x20, KEY_UP },
-	{ 0x21, KEY_DOWN },
-	{ 0x0b, KEY_ENTER },
-
-	{ 0x10, KEY_CHANNELUP },
-	{ 0x11, KEY_CHANNELDOWN },
-
-	/* Couldn't map key left/key right since those
-	   conflict with '3' and '4' scancodes
-	   I dunno what the original driver does
-	 */
-
-	{ 0x13, KEY_VOLUMEUP },
-	{ 0x12, KEY_VOLUMEDOWN },
-
-	/* The lower part of the IR
-	   There are several duplicated keycodes there.
-	   Most of them conflict with digits.
-	   Add mappings just to the unused scancodes.
-	   Somehow, the original driver has a way to know,
-	   but this doesn't seem to be on some GPIO.
-	   Also, it is not related to the time between keyup
-	   and keydown.
-	 */
-	{ 0x19, KEY_TIME},		/* Timeshift */
-	{ 0x1a, KEY_STOP},
-	{ 0x1b, KEY_RECORD},
-
-	{ 0x22, KEY_TEXT},
-
-	{ 0x15, KEY_AUDIO},		/* ((*)) */
-	{ 0x0f, KEY_ZOOM},
-	{ 0x1c, KEY_CAMERA},		/* snapshot */
-
-	{ 0x18, KEY_RED},		/* B */
-	{ 0x23, KEY_GREEN},		/* C */
-};
-
-static struct rc_keymap kworld_plus_tv_analog_map = {
-	.map = {
-		.scan    = kworld_plus_tv_analog,
-		.size    = ARRAY_SIZE(kworld_plus_tv_analog),
-		.ir_type = IR_TYPE_UNKNOWN,	/* Legacy IR type */
-		.name    = RC_MAP_KWORLD_PLUS_TV_ANALOG,
-	}
-};
-
-static int __init init_rc_map_kworld_plus_tv_analog(void)
-{
-	return ir_register_map(&kworld_plus_tv_analog_map);
-}
-
-static void __exit exit_rc_map_kworld_plus_tv_analog(void)
-{
-	ir_unregister_map(&kworld_plus_tv_analog_map);
-}
-
-module_init(init_rc_map_kworld_plus_tv_analog)
-module_exit(exit_rc_map_kworld_plus_tv_analog)
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-leadtek-y04g0051.c linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-leadtek-y04g0051.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-leadtek-y04g0051.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-leadtek-y04g0051.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,99 +0,0 @@
-/*
- * LeadTek Y04G0051 remote controller keytable
- *
- * Copyright (C) 2010 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 <media/rc-map.h>
-
-static struct ir_scancode leadtek_y04g0051[] = {
-	{ 0x0300, KEY_POWER2 },
-	{ 0x0303, KEY_SCREEN },
-	{ 0x0304, KEY_RIGHT },
-	{ 0x0305, KEY_1 },
-	{ 0x0306, KEY_2 },
-	{ 0x0307, KEY_3 },
-	{ 0x0308, KEY_LEFT },
-	{ 0x0309, KEY_4 },
-	{ 0x030a, KEY_5 },
-	{ 0x030b, KEY_6 },
-	{ 0x030c, KEY_UP },
-	{ 0x030d, KEY_7 },
-	{ 0x030e, KEY_8 },
-	{ 0x030f, KEY_9 },
-	{ 0x0310, KEY_DOWN },
-	{ 0x0311, KEY_AGAIN },
-	{ 0x0312, KEY_0 },
-	{ 0x0313, KEY_OK },              /* 1st ok */
-	{ 0x0314, KEY_MUTE },
-	{ 0x0316, KEY_OK },              /* 2nd ok */
-	{ 0x031e, KEY_VIDEO },           /* 2nd video */
-	{ 0x031b, KEY_AUDIO },
-	{ 0x031f, KEY_TEXT },
-	{ 0x0340, KEY_SLEEP },
-	{ 0x0341, KEY_DOT },
-	{ 0x0342, KEY_REWIND },
-	{ 0x0343, KEY_PLAY },
-	{ 0x0344, KEY_FASTFORWARD },
-	{ 0x0345, KEY_TIME },
-	{ 0x0346, KEY_STOP },            /* 2nd stop */
-	{ 0x0347, KEY_RECORD },
-	{ 0x0348, KEY_CAMERA },
-	{ 0x0349, KEY_ESC },
-	{ 0x034a, KEY_NEW },
-	{ 0x034b, KEY_RED },
-	{ 0x034c, KEY_GREEN },
-	{ 0x034d, KEY_YELLOW },
-	{ 0x034e, KEY_BLUE },
-	{ 0x034f, KEY_MENU },
-	{ 0x0350, KEY_STOP },            /* 1st stop */
-	{ 0x0351, KEY_CHANNEL },
-	{ 0x0352, KEY_VIDEO },           /* 1st video */
-	{ 0x0353, KEY_EPG },
-	{ 0x0354, KEY_PREVIOUS },
-	{ 0x0355, KEY_NEXT },
-	{ 0x0356, KEY_TV },
-	{ 0x035a, KEY_VOLUMEDOWN },
-	{ 0x035b, KEY_CHANNELUP },
-	{ 0x035e, KEY_VOLUMEUP },
-	{ 0x035f, KEY_CHANNELDOWN },
-};
-
-static struct rc_keymap leadtek_y04g0051_map = {
-	.map = {
-		.scan    = leadtek_y04g0051,
-		.size    = ARRAY_SIZE(leadtek_y04g0051),
-		.ir_type = IR_TYPE_NEC,
-		.name    = RC_MAP_LEADTEK_Y04G0051,
-	}
-};
-
-static int __init init_rc_map_leadtek_y04g0051(void)
-{
-	return ir_register_map(&leadtek_y04g0051_map);
-}
-
-static void __exit exit_rc_map_leadtek_y04g0051(void)
-{
-	ir_unregister_map(&leadtek_y04g0051_map);
-}
-
-module_init(init_rc_map_leadtek_y04g0051)
-module_exit(exit_rc_map_leadtek_y04g0051)
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-lirc.c linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-lirc.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-lirc.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-lirc.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,41 +0,0 @@
-/* rc-lirc.c - Empty dummy keytable, for use when its preferred to pass
- * all raw IR data to the lirc userspace decoder.
- *
- * Copyright (c) 2010 by Jarod Wilson <jarod@redhat.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 <media/ir-core.h>
-
-static struct ir_scancode lirc[] = {
-	{ },
-};
-
-static struct rc_keymap lirc_map = {
-	.map = {
-		.scan    = lirc,
-		.size    = ARRAY_SIZE(lirc),
-		.ir_type = IR_TYPE_LIRC,
-		.name    = RC_MAP_LIRC,
-	}
-};
-
-static int __init init_rc_map_lirc(void)
-{
-	return ir_register_map(&lirc_map);
-}
-
-static void __exit exit_rc_map_lirc(void)
-{
-	ir_unregister_map(&lirc_map);
-}
-
-module_init(init_rc_map_lirc)
-module_exit(exit_rc_map_lirc)
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Jarod Wilson <jarod@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-lme2510.c linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-lme2510.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-lme2510.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-lme2510.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,68 +0,0 @@
-/* LME2510 remote control
- *
- *
- * Copyright (C) 2010 Malcolm Priestley (tvboxspy@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 <media/rc-map.h>
-
-
-static struct ir_scancode lme2510_rc[] = {
-	{ 0xba45, KEY_0 },
-	{ 0xa05f, KEY_1 },
-	{ 0xaf50, KEY_2 },
-	{ 0xa25d, KEY_3 },
-	{ 0xbe41, KEY_4 },
-	{ 0xf50a, KEY_5 },
-	{ 0xbd42, KEY_6 },
-	{ 0xb847, KEY_7 },
-	{ 0xb649, KEY_8 },
-	{ 0xfa05, KEY_9 },
-	{ 0xbc43, KEY_POWER },
-	{ 0xb946, KEY_SUBTITLE },
-	{ 0xf906, KEY_PAUSE },
-	{ 0xfc03, KEY_MEDIA_REPEAT},
-	{ 0xfd02, KEY_PAUSE },
-	{ 0xa15e, KEY_VOLUMEUP },
-	{ 0xa35c, KEY_VOLUMEDOWN },
-	{ 0xf609, KEY_CHANNELUP },
-	{ 0xe51a, KEY_CHANNELDOWN },
-	{ 0xe11e, KEY_PLAY },
-	{ 0xe41b, KEY_ZOOM },
-	{ 0xa659, KEY_MUTE },
-	{ 0xa55a, KEY_TV },
-	{ 0xe718, KEY_RECORD },
-	{ 0xf807, KEY_EPG },
-	{ 0xfe01, KEY_STOP },
-
-};
-
-static struct rc_keymap lme2510_map = {
-	.map = {
-		.scan    = lme2510_rc,
-		.size    = ARRAY_SIZE(lme2510_rc),
-		.ir_type = IR_TYPE_UNKNOWN,
-		.name    = RC_MAP_LME2510,
-	}
-};
-
-static int __init init_rc_lme2510_map(void)
-{
-	return ir_register_map(&lme2510_map);
-}
-
-static void __exit exit_rc_lme2510_map(void)
-{
-	ir_unregister_map(&lme2510_map);
-}
-
-module_init(init_rc_lme2510_map)
-module_exit(exit_rc_lme2510_map)
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Malcolm Priestley tvboxspy@gmail.com");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-manli.c linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-manli.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-manli.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-manli.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,134 +0,0 @@
-/* manli.h - Keytable for manli Remote Controller
- *
- * keymap imported from ir-keymaps.c
- *
- * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
-
-/* Michael Tokarev <mjt@tls.msk.ru>
-   keytable is used by MANLI MTV00[0x0c] and BeholdTV 40[13] at
-   least, and probably other cards too.
-   The "ascii-art picture" below (in comments, first row
-   is the keycode in hex, and subsequent row(s) shows
-   the button labels (several variants when appropriate)
-   helps to descide which keycodes to assign to the buttons.
- */
-
-static struct ir_scancode manli[] = {
-
-	/*  0x1c            0x12  *
-	 * FUNCTION         POWER *
-	 *   FM              (|)  *
-	 *                        */
-	{ 0x1c, KEY_RADIO },	/*XXX*/
-	{ 0x12, KEY_POWER },
-
-	/*  0x01    0x02    0x03  *
-	 *   1       2       3    *
-	 *                        *
-	 *  0x04    0x05    0x06  *
-	 *   4       5       6    *
-	 *                        *
-	 *  0x07    0x08    0x09  *
-	 *   7       8       9    *
-	 *                        */
-	{ 0x01, KEY_1 },
-	{ 0x02, KEY_2 },
-	{ 0x03, KEY_3 },
-	{ 0x04, KEY_4 },
-	{ 0x05, KEY_5 },
-	{ 0x06, KEY_6 },
-	{ 0x07, KEY_7 },
-	{ 0x08, KEY_8 },
-	{ 0x09, KEY_9 },
-
-	/*  0x0a    0x00    0x17  *
-	 * RECALL    0      +100  *
-	 *                  PLUS  *
-	 *                        */
-	{ 0x0a, KEY_AGAIN },	/*XXX KEY_REWIND? */
-	{ 0x00, KEY_0 },
-	{ 0x17, KEY_DIGITS },	/*XXX*/
-
-	/*  0x14            0x10  *
-	 *  MENU            INFO  *
-	 *  OSD                   */
-	{ 0x14, KEY_MENU },
-	{ 0x10, KEY_INFO },
-
-	/*          0x0b          *
-	 *           Up           *
-	 *                        *
-	 *  0x18    0x16    0x0c  *
-	 *  Left     Ok     Right *
-	 *                        *
-	 *         0x015          *
-	 *         Down           *
-	 *                        */
-	{ 0x0b, KEY_UP },
-	{ 0x18, KEY_LEFT },
-	{ 0x16, KEY_OK },	/*XXX KEY_SELECT? KEY_ENTER? */
-	{ 0x0c, KEY_RIGHT },
-	{ 0x15, KEY_DOWN },
-
-	/*  0x11            0x0d  *
-	 *  TV/AV           MODE  *
-	 *  SOURCE         STEREO *
-	 *                        */
-	{ 0x11, KEY_TV },	/*XXX*/
-	{ 0x0d, KEY_MODE },	/*XXX there's no KEY_STEREO	*/
-
-	/*  0x0f    0x1b    0x1a  *
-	 *  AUDIO   Vol+    Chan+ *
-	 *        TIMESHIFT???    *
-	 *                        *
-	 *  0x0e    0x1f    0x1e  *
-	 *  SLEEP   Vol-    Chan- *
-	 *                        */
-	{ 0x0f, KEY_AUDIO },
-	{ 0x1b, KEY_VOLUMEUP },
-	{ 0x1a, KEY_CHANNELUP },
-	{ 0x0e, KEY_TIME },
-	{ 0x1f, KEY_VOLUMEDOWN },
-	{ 0x1e, KEY_CHANNELDOWN },
-
-	/*         0x13     0x19  *
-	 *         MUTE   SNAPSHOT*
-	 *                        */
-	{ 0x13, KEY_MUTE },
-	{ 0x19, KEY_CAMERA },
-
-	/* 0x1d unused ? */
-};
-
-static struct rc_keymap manli_map = {
-	.map = {
-		.scan    = manli,
-		.size    = ARRAY_SIZE(manli),
-		.ir_type = IR_TYPE_UNKNOWN,	/* Legacy IR type */
-		.name    = RC_MAP_MANLI,
-	}
-};
-
-static int __init init_rc_map_manli(void)
-{
-	return ir_register_map(&manli_map);
-}
-
-static void __exit exit_rc_map_manli(void)
-{
-	ir_unregister_map(&manli_map);
-}
-
-module_init(init_rc_map_manli)
-module_exit(exit_rc_map_manli)
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-msi-digivox-ii.c linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-msi-digivox-ii.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-msi-digivox-ii.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-msi-digivox-ii.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,67 +0,0 @@
-/*
- * MSI DIGIVOX mini II remote controller keytable
- *
- * Copyright (C) 2010 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 <media/rc-map.h>
-
-static struct ir_scancode msi_digivox_ii[] = {
-	{ 0x0002, KEY_2 },
-	{ 0x0003, KEY_UP },              /* up */
-	{ 0x0004, KEY_3 },
-	{ 0x0005, KEY_CHANNELDOWN },
-	{ 0x0008, KEY_5 },
-	{ 0x0009, KEY_0 },
-	{ 0x000b, KEY_8 },
-	{ 0x000d, KEY_DOWN },            /* down */
-	{ 0x0010, KEY_9 },
-	{ 0x0011, KEY_7 },
-	{ 0x0014, KEY_VOLUMEUP },
-	{ 0x0015, KEY_CHANNELUP },
-	{ 0x0016, KEY_OK },
-	{ 0x0017, KEY_POWER2 },
-	{ 0x001a, KEY_1 },
-	{ 0x001c, KEY_4 },
-	{ 0x001d, KEY_6 },
-	{ 0x001f, KEY_VOLUMEDOWN },
-};
-
-static struct rc_keymap msi_digivox_ii_map = {
-	.map = {
-		.scan    = msi_digivox_ii,
-		.size    = ARRAY_SIZE(msi_digivox_ii),
-		.ir_type = IR_TYPE_NEC,
-		.name    = RC_MAP_MSI_DIGIVOX_II,
-	}
-};
-
-static int __init init_rc_map_msi_digivox_ii(void)
-{
-	return ir_register_map(&msi_digivox_ii_map);
-}
-
-static void __exit exit_rc_map_msi_digivox_ii(void)
-{
-	ir_unregister_map(&msi_digivox_ii_map);
-}
-
-module_init(init_rc_map_msi_digivox_ii)
-module_exit(exit_rc_map_msi_digivox_ii)
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-msi-digivox-iii.c linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-msi-digivox-iii.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-msi-digivox-iii.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-msi-digivox-iii.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,85 +0,0 @@
-/*
- * MSI DIGIVOX mini III remote controller keytable
- *
- * Copyright (C) 2010 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 <media/rc-map.h>
-
-/* MSI DIGIVOX mini III */
-/* Uses NEC extended 0x61d6. */
-/* This remote seems to be same as rc-kworld-315u.c. Anyhow, add new remote
-   since rc-kworld-315u.c lacks NEC extended address byte. */
-static struct ir_scancode msi_digivox_iii[] = {
-	{ 0x61d601, KEY_VIDEO },           /* Source */
-	{ 0x61d602, KEY_3 },
-	{ 0x61d603, KEY_POWER },           /* ShutDown */
-	{ 0x61d604, KEY_1 },
-	{ 0x61d605, KEY_5 },
-	{ 0x61d606, KEY_6 },
-	{ 0x61d607, KEY_CHANNELDOWN },     /* CH- */
-	{ 0x61d608, KEY_2 },
-	{ 0x61d609, KEY_CHANNELUP },       /* CH+ */
-	{ 0x61d60a, KEY_9 },
-	{ 0x61d60b, KEY_ZOOM },            /* Zoom */
-	{ 0x61d60c, KEY_7 },
-	{ 0x61d60d, KEY_8 },
-	{ 0x61d60e, KEY_VOLUMEUP },        /* Vol+ */
-	{ 0x61d60f, KEY_4 },
-	{ 0x61d610, KEY_ESC },             /* [back up arrow] */
-	{ 0x61d611, KEY_0 },
-	{ 0x61d612, KEY_OK },              /* [enter arrow] */
-	{ 0x61d613, KEY_VOLUMEDOWN },      /* Vol- */
-	{ 0x61d614, KEY_RECORD },          /* Rec */
-	{ 0x61d615, KEY_STOP },            /* Stop */
-	{ 0x61d616, KEY_PLAY },            /* Play */
-	{ 0x61d617, KEY_MUTE },            /* Mute */
-	{ 0x61d618, KEY_UP },
-	{ 0x61d619, KEY_DOWN },
-	{ 0x61d61a, KEY_LEFT },
-	{ 0x61d61b, KEY_RIGHT },
-	{ 0x61d61c, KEY_RED },
-	{ 0x61d61d, KEY_GREEN },
-	{ 0x61d61e, KEY_YELLOW },
-	{ 0x61d61f, KEY_BLUE },
-	{ 0x61d643, KEY_POWER2 },          /* [red power button] */
-};
-
-static struct rc_keymap msi_digivox_iii_map = {
-	.map = {
-		.scan    = msi_digivox_iii,
-		.size    = ARRAY_SIZE(msi_digivox_iii),
-		.ir_type = IR_TYPE_NEC,
-		.name    = RC_MAP_MSI_DIGIVOX_III,
-	}
-};
-
-static int __init init_rc_map_msi_digivox_iii(void)
-{
-	return ir_register_map(&msi_digivox_iii_map);
-}
-
-static void __exit exit_rc_map_msi_digivox_iii(void)
-{
-	ir_unregister_map(&msi_digivox_iii_map);
-}
-
-module_init(init_rc_map_msi_digivox_iii)
-module_exit(exit_rc_map_msi_digivox_iii)
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-msi-tvanywhere.c linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-msi-tvanywhere.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-msi-tvanywhere.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-msi-tvanywhere.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,69 +0,0 @@
-/* msi-tvanywhere.h - Keytable for msi_tvanywhere Remote Controller
- *
- * keymap imported from ir-keymaps.c
- *
- * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
-
-/* MSI TV@nywhere MASTER remote */
-
-static struct ir_scancode msi_tvanywhere[] = {
-	/* Keys 0 to 9 */
-	{ 0x00, KEY_0 },
-	{ 0x01, KEY_1 },
-	{ 0x02, KEY_2 },
-	{ 0x03, KEY_3 },
-	{ 0x04, KEY_4 },
-	{ 0x05, KEY_5 },
-	{ 0x06, KEY_6 },
-	{ 0x07, KEY_7 },
-	{ 0x08, KEY_8 },
-	{ 0x09, KEY_9 },
-
-	{ 0x0c, KEY_MUTE },
-	{ 0x0f, KEY_SCREEN },		/* Full Screen */
-	{ 0x10, KEY_FN },		/* Funtion */
-	{ 0x11, KEY_TIME },		/* Time shift */
-	{ 0x12, KEY_POWER },
-	{ 0x13, KEY_MEDIA },		/* MTS */
-	{ 0x14, KEY_SLOW },
-	{ 0x16, KEY_REWIND },		/* backward << */
-	{ 0x17, KEY_ENTER },		/* Return */
-	{ 0x18, KEY_FASTFORWARD },	/* forward >> */
-	{ 0x1a, KEY_CHANNELUP },
-	{ 0x1b, KEY_VOLUMEUP },
-	{ 0x1e, KEY_CHANNELDOWN },
-	{ 0x1f, KEY_VOLUMEDOWN },
-};
-
-static struct rc_keymap msi_tvanywhere_map = {
-	.map = {
-		.scan    = msi_tvanywhere,
-		.size    = ARRAY_SIZE(msi_tvanywhere),
-		.ir_type = IR_TYPE_UNKNOWN,	/* Legacy IR type */
-		.name    = RC_MAP_MSI_TVANYWHERE,
-	}
-};
-
-static int __init init_rc_map_msi_tvanywhere(void)
-{
-	return ir_register_map(&msi_tvanywhere_map);
-}
-
-static void __exit exit_rc_map_msi_tvanywhere(void)
-{
-	ir_unregister_map(&msi_tvanywhere_map);
-}
-
-module_init(init_rc_map_msi_tvanywhere)
-module_exit(exit_rc_map_msi_tvanywhere)
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-msi-tvanywhere-plus.c linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-msi-tvanywhere-plus.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-msi-tvanywhere-plus.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-msi-tvanywhere-plus.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,123 +0,0 @@
-/* msi-tvanywhere-plus.h - Keytable for msi_tvanywhere_plus Remote Controller
- *
- * keymap imported from ir-keymaps.c
- *
- * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
-
-/*
-  Keycodes for remote on the MSI TV@nywhere Plus. The controller IC on the card
-  is marked "KS003". The controller is I2C at address 0x30, but does not seem
-  to respond to probes until a read is performed from a valid device.
-  I don't know why...
-
-  Note: This remote may be of similar or identical design to the
-  Pixelview remote (?).  The raw codes and duplicate button codes
-  appear to be the same.
-
-  Henry Wong <henry@stuffedcow.net>
-  Some changes to formatting and keycodes by Mark Schultz <n9xmj@yahoo.com>
-*/
-
-static struct ir_scancode msi_tvanywhere_plus[] = {
-
-/*  ---- Remote Button Layout ----
-
-    POWER   SOURCE  SCAN    MUTE
-    TV/FM   1       2       3
-    |>      4       5       6
-    <|      7       8       9
-    ^^UP    0       +       RECALL
-    vvDN    RECORD  STOP    PLAY
-
-	MINIMIZE          ZOOM
-
-		  CH+
-      VOL-                   VOL+
-		  CH-
-
-	SNAPSHOT           MTS
-
-     <<      FUNC    >>     RESET
-*/
-
-	{ 0x01, KEY_1 },		/* 1 */
-	{ 0x0b, KEY_2 },		/* 2 */
-	{ 0x1b, KEY_3 },		/* 3 */
-	{ 0x05, KEY_4 },		/* 4 */
-	{ 0x09, KEY_5 },		/* 5 */
-	{ 0x15, KEY_6 },		/* 6 */
-	{ 0x06, KEY_7 },		/* 7 */
-	{ 0x0a, KEY_8 },		/* 8 */
-	{ 0x12, KEY_9 },		/* 9 */
-	{ 0x02, KEY_0 },		/* 0 */
-	{ 0x10, KEY_KPPLUS },		/* + */
-	{ 0x13, KEY_AGAIN },		/* Recall */
-
-	{ 0x1e, KEY_POWER },		/* Power */
-	{ 0x07, KEY_TUNER },		/* Source */
-	{ 0x1c, KEY_SEARCH },		/* Scan */
-	{ 0x18, KEY_MUTE },		/* Mute */
-
-	{ 0x03, KEY_RADIO },		/* TV/FM */
-	/* The next four keys are duplicates that appear to send the
-	   same IR code as Ch+, Ch-, >>, and << .  The raw code assigned
-	   to them is the actual code + 0x20 - they will never be
-	   detected as such unless some way is discovered to distinguish
-	   these buttons from those that have the same code. */
-	{ 0x3f, KEY_RIGHT },		/* |> and Ch+ */
-	{ 0x37, KEY_LEFT },		/* <| and Ch- */
-	{ 0x2c, KEY_UP },		/* ^^Up and >> */
-	{ 0x24, KEY_DOWN },		/* vvDn and << */
-
-	{ 0x00, KEY_RECORD },		/* Record */
-	{ 0x08, KEY_STOP },		/* Stop */
-	{ 0x11, KEY_PLAY },		/* Play */
-
-	{ 0x0f, KEY_CLOSE },		/* Minimize */
-	{ 0x19, KEY_ZOOM },		/* Zoom */
-	{ 0x1a, KEY_CAMERA },		/* Snapshot */
-	{ 0x0d, KEY_LANGUAGE },		/* MTS */
-
-	{ 0x14, KEY_VOLUMEDOWN },	/* Vol- */
-	{ 0x16, KEY_VOLUMEUP },		/* Vol+ */
-	{ 0x17, KEY_CHANNELDOWN },	/* Ch- */
-	{ 0x1f, KEY_CHANNELUP },	/* Ch+ */
-
-	{ 0x04, KEY_REWIND },		/* << */
-	{ 0x0e, KEY_MENU },		/* Function */
-	{ 0x0c, KEY_FASTFORWARD },	/* >> */
-	{ 0x1d, KEY_RESTART },		/* Reset */
-};
-
-static struct rc_keymap msi_tvanywhere_plus_map = {
-	.map = {
-		.scan    = msi_tvanywhere_plus,
-		.size    = ARRAY_SIZE(msi_tvanywhere_plus),
-		.ir_type = IR_TYPE_UNKNOWN,	/* Legacy IR type */
-		.name    = RC_MAP_MSI_TVANYWHERE_PLUS,
-	}
-};
-
-static int __init init_rc_map_msi_tvanywhere_plus(void)
-{
-	return ir_register_map(&msi_tvanywhere_plus_map);
-}
-
-static void __exit exit_rc_map_msi_tvanywhere_plus(void)
-{
-	ir_unregister_map(&msi_tvanywhere_plus_map);
-}
-
-module_init(init_rc_map_msi_tvanywhere_plus)
-module_exit(exit_rc_map_msi_tvanywhere_plus)
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-nebula.c linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-nebula.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-nebula.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-nebula.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,96 +0,0 @@
-/* nebula.h - Keytable for nebula Remote Controller
- *
- * keymap imported from ir-keymaps.c
- *
- * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
-
-static struct ir_scancode nebula[] = {
-	{ 0x00, KEY_0 },
-	{ 0x01, KEY_1 },
-	{ 0x02, KEY_2 },
-	{ 0x03, KEY_3 },
-	{ 0x04, KEY_4 },
-	{ 0x05, KEY_5 },
-	{ 0x06, KEY_6 },
-	{ 0x07, KEY_7 },
-	{ 0x08, KEY_8 },
-	{ 0x09, KEY_9 },
-	{ 0x0a, KEY_TV },
-	{ 0x0b, KEY_AUX },
-	{ 0x0c, KEY_DVD },
-	{ 0x0d, KEY_POWER },
-	{ 0x0e, KEY_MHP },	/* labelled 'Picture' */
-	{ 0x0f, KEY_AUDIO },
-	{ 0x10, KEY_INFO },
-	{ 0x11, KEY_F13 },	/* 16:9 */
-	{ 0x12, KEY_F14 },	/* 14:9 */
-	{ 0x13, KEY_EPG },
-	{ 0x14, KEY_EXIT },
-	{ 0x15, KEY_MENU },
-	{ 0x16, KEY_UP },
-	{ 0x17, KEY_DOWN },
-	{ 0x18, KEY_LEFT },
-	{ 0x19, KEY_RIGHT },
-	{ 0x1a, KEY_ENTER },
-	{ 0x1b, KEY_CHANNELUP },
-	{ 0x1c, KEY_CHANNELDOWN },
-	{ 0x1d, KEY_VOLUMEUP },
-	{ 0x1e, KEY_VOLUMEDOWN },
-	{ 0x1f, KEY_RED },
-	{ 0x20, KEY_GREEN },
-	{ 0x21, KEY_YELLOW },
-	{ 0x22, KEY_BLUE },
-	{ 0x23, KEY_SUBTITLE },
-	{ 0x24, KEY_F15 },	/* AD */
-	{ 0x25, KEY_TEXT },
-	{ 0x26, KEY_MUTE },
-	{ 0x27, KEY_REWIND },
-	{ 0x28, KEY_STOP },
-	{ 0x29, KEY_PLAY },
-	{ 0x2a, KEY_FASTFORWARD },
-	{ 0x2b, KEY_F16 },	/* chapter */
-	{ 0x2c, KEY_PAUSE },
-	{ 0x2d, KEY_PLAY },
-	{ 0x2e, KEY_RECORD },
-	{ 0x2f, KEY_F17 },	/* picture in picture */
-	{ 0x30, KEY_KPPLUS },	/* zoom in */
-	{ 0x31, KEY_KPMINUS },	/* zoom out */
-	{ 0x32, KEY_F18 },	/* capture */
-	{ 0x33, KEY_F19 },	/* web */
-	{ 0x34, KEY_EMAIL },
-	{ 0x35, KEY_PHONE },
-	{ 0x36, KEY_PC },
-};
-
-static struct rc_keymap nebula_map = {
-	.map = {
-		.scan    = nebula,
-		.size    = ARRAY_SIZE(nebula),
-		.ir_type = IR_TYPE_UNKNOWN,	/* Legacy IR type */
-		.name    = RC_MAP_NEBULA,
-	}
-};
-
-static int __init init_rc_map_nebula(void)
-{
-	return ir_register_map(&nebula_map);
-}
-
-static void __exit exit_rc_map_nebula(void)
-{
-	ir_unregister_map(&nebula_map);
-}
-
-module_init(init_rc_map_nebula)
-module_exit(exit_rc_map_nebula)
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-nec-terratec-cinergy-xs.c linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-nec-terratec-cinergy-xs.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-nec-terratec-cinergy-xs.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-nec-terratec-cinergy-xs.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,105 +0,0 @@
-/* nec-terratec-cinergy-xs.h - Keytable for nec_terratec_cinergy_xs Remote Controller
- *
- * keymap imported from ir-keymaps.c
- *
- * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
-
-/* Terratec Cinergy Hybrid T USB XS FM
-   Mauro Carvalho Chehab <mchehab@redhat.com>
- */
-
-static struct ir_scancode nec_terratec_cinergy_xs[] = {
-	{ 0x1441, KEY_HOME},
-	{ 0x1401, KEY_POWER2},
-
-	{ 0x1442, KEY_MENU},		/* DVD menu */
-	{ 0x1443, KEY_SUBTITLE},
-	{ 0x1444, KEY_TEXT},		/* Teletext */
-	{ 0x1445, KEY_DELETE},
-
-	{ 0x1402, KEY_1},
-	{ 0x1403, KEY_2},
-	{ 0x1404, KEY_3},
-	{ 0x1405, KEY_4},
-	{ 0x1406, KEY_5},
-	{ 0x1407, KEY_6},
-	{ 0x1408, KEY_7},
-	{ 0x1409, KEY_8},
-	{ 0x140a, KEY_9},
-	{ 0x140c, KEY_0},
-
-	{ 0x140b, KEY_TUNER},		/* AV */
-	{ 0x140d, KEY_MODE},		/* A.B */
-
-	{ 0x1446, KEY_TV},
-	{ 0x1447, KEY_DVD},
-	{ 0x1449, KEY_VIDEO},
-	{ 0x144a, KEY_RADIO},		/* Music */
-	{ 0x144b, KEY_CAMERA},		/* PIC */
-
-	{ 0x1410, KEY_UP},
-	{ 0x1411, KEY_LEFT},
-	{ 0x1412, KEY_OK},
-	{ 0x1413, KEY_RIGHT},
-	{ 0x1414, KEY_DOWN},
-
-	{ 0x140f, KEY_EPG},
-	{ 0x1416, KEY_INFO},
-	{ 0x144d, KEY_BACKSPACE},
-
-	{ 0x141c, KEY_VOLUMEUP},
-	{ 0x141e, KEY_VOLUMEDOWN},
-
-	{ 0x144c, KEY_PLAY},
-	{ 0x141d, KEY_MUTE},
-
-	{ 0x141b, KEY_CHANNELUP},
-	{ 0x141f, KEY_CHANNELDOWN},
-
-	{ 0x1417, KEY_RED},
-	{ 0x1418, KEY_GREEN},
-	{ 0x1419, KEY_YELLOW},
-	{ 0x141a, KEY_BLUE},
-
-	{ 0x1458, KEY_RECORD},
-	{ 0x1448, KEY_STOP},
-	{ 0x1440, KEY_PAUSE},
-
-	{ 0x1454, KEY_LAST},
-	{ 0x144e, KEY_REWIND},
-	{ 0x144f, KEY_FASTFORWARD},
-	{ 0x145c, KEY_NEXT},
-};
-
-static struct rc_keymap nec_terratec_cinergy_xs_map = {
-	.map = {
-		.scan    = nec_terratec_cinergy_xs,
-		.size    = ARRAY_SIZE(nec_terratec_cinergy_xs),
-		.ir_type = IR_TYPE_NEC,
-		.name    = RC_MAP_NEC_TERRATEC_CINERGY_XS,
-	}
-};
-
-static int __init init_rc_map_nec_terratec_cinergy_xs(void)
-{
-	return ir_register_map(&nec_terratec_cinergy_xs_map);
-}
-
-static void __exit exit_rc_map_nec_terratec_cinergy_xs(void)
-{
-	ir_unregister_map(&nec_terratec_cinergy_xs_map);
-}
-
-module_init(init_rc_map_nec_terratec_cinergy_xs)
-module_exit(exit_rc_map_nec_terratec_cinergy_xs)
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-norwood.c linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-norwood.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-norwood.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-norwood.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,85 +0,0 @@
-/* norwood.h - Keytable for norwood Remote Controller
- *
- * keymap imported from ir-keymaps.c
- *
- * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
-
-/* Norwood Micro (non-Pro) TV Tuner
-   By Peter Naulls <peter@chocky.org>
-   Key comments are the functions given in the manual */
-
-static struct ir_scancode norwood[] = {
-	/* Keys 0 to 9 */
-	{ 0x20, KEY_0 },
-	{ 0x21, KEY_1 },
-	{ 0x22, KEY_2 },
-	{ 0x23, KEY_3 },
-	{ 0x24, KEY_4 },
-	{ 0x25, KEY_5 },
-	{ 0x26, KEY_6 },
-	{ 0x27, KEY_7 },
-	{ 0x28, KEY_8 },
-	{ 0x29, KEY_9 },
-
-	{ 0x78, KEY_TUNER },		/* Video Source        */
-	{ 0x2c, KEY_EXIT },		/* Open/Close software */
-	{ 0x2a, KEY_SELECT },		/* 2 Digit Select      */
-	{ 0x69, KEY_AGAIN },		/* Recall              */
-
-	{ 0x32, KEY_BRIGHTNESSUP },	/* Brightness increase */
-	{ 0x33, KEY_BRIGHTNESSDOWN },	/* Brightness decrease */
-	{ 0x6b, KEY_KPPLUS },		/* (not named >>>>>)   */
-	{ 0x6c, KEY_KPMINUS },		/* (not named <<<<<)   */
-
-	{ 0x2d, KEY_MUTE },		/* Mute                */
-	{ 0x30, KEY_VOLUMEUP },		/* Volume up           */
-	{ 0x31, KEY_VOLUMEDOWN },	/* Volume down         */
-	{ 0x60, KEY_CHANNELUP },	/* Channel up          */
-	{ 0x61, KEY_CHANNELDOWN },	/* Channel down        */
-
-	{ 0x3f, KEY_RECORD },		/* Record              */
-	{ 0x37, KEY_PLAY },		/* Play                */
-	{ 0x36, KEY_PAUSE },		/* Pause               */
-	{ 0x2b, KEY_STOP },		/* Stop                */
-	{ 0x67, KEY_FASTFORWARD },	/* Foward              */
-	{ 0x66, KEY_REWIND },		/* Rewind              */
-	{ 0x3e, KEY_SEARCH },		/* Auto Scan           */
-	{ 0x2e, KEY_CAMERA },		/* Capture Video       */
-	{ 0x6d, KEY_MENU },		/* Show/Hide Control   */
-	{ 0x2f, KEY_ZOOM },		/* Full Screen         */
-	{ 0x34, KEY_RADIO },		/* FM                  */
-	{ 0x65, KEY_POWER },		/* Computer power      */
-};
-
-static struct rc_keymap norwood_map = {
-	.map = {
-		.scan    = norwood,
-		.size    = ARRAY_SIZE(norwood),
-		.ir_type = IR_TYPE_UNKNOWN,	/* Legacy IR type */
-		.name    = RC_MAP_NORWOOD,
-	}
-};
-
-static int __init init_rc_map_norwood(void)
-{
-	return ir_register_map(&norwood_map);
-}
-
-static void __exit exit_rc_map_norwood(void)
-{
-	ir_unregister_map(&norwood_map);
-}
-
-module_init(init_rc_map_norwood)
-module_exit(exit_rc_map_norwood)
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-npgtech.c linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-npgtech.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-npgtech.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-npgtech.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,80 +0,0 @@
-/* npgtech.h - Keytable for npgtech Remote Controller
- *
- * keymap imported from ir-keymaps.c
- *
- * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
-
-static struct ir_scancode npgtech[] = {
-	{ 0x1d, KEY_SWITCHVIDEOMODE },	/* switch inputs */
-	{ 0x2a, KEY_FRONT },
-
-	{ 0x3e, KEY_1 },
-	{ 0x02, KEY_2 },
-	{ 0x06, KEY_3 },
-	{ 0x0a, KEY_4 },
-	{ 0x0e, KEY_5 },
-	{ 0x12, KEY_6 },
-	{ 0x16, KEY_7 },
-	{ 0x1a, KEY_8 },
-	{ 0x1e, KEY_9 },
-	{ 0x3a, KEY_0 },
-	{ 0x22, KEY_NUMLOCK },		/* -/-- */
-	{ 0x20, KEY_REFRESH },
-
-	{ 0x03, KEY_BRIGHTNESSDOWN },
-	{ 0x28, KEY_AUDIO },
-	{ 0x3c, KEY_CHANNELUP },
-	{ 0x3f, KEY_VOLUMEDOWN },
-	{ 0x2e, KEY_MUTE },
-	{ 0x3b, KEY_VOLUMEUP },
-	{ 0x00, KEY_CHANNELDOWN },
-	{ 0x07, KEY_BRIGHTNESSUP },
-	{ 0x2c, KEY_TEXT },
-
-	{ 0x37, KEY_RECORD },
-	{ 0x17, KEY_PLAY },
-	{ 0x13, KEY_PAUSE },
-	{ 0x26, KEY_STOP },
-	{ 0x18, KEY_FASTFORWARD },
-	{ 0x14, KEY_REWIND },
-	{ 0x33, KEY_ZOOM },
-	{ 0x32, KEY_KEYBOARD },
-	{ 0x30, KEY_GOTO },		/* Pointing arrow */
-	{ 0x36, KEY_MACRO },		/* Maximize/Minimize (yellow) */
-	{ 0x0b, KEY_RADIO },
-	{ 0x10, KEY_POWER },
-
-};
-
-static struct rc_keymap npgtech_map = {
-	.map = {
-		.scan    = npgtech,
-		.size    = ARRAY_SIZE(npgtech),
-		.ir_type = IR_TYPE_UNKNOWN,	/* Legacy IR type */
-		.name    = RC_MAP_NPGTECH,
-	}
-};
-
-static int __init init_rc_map_npgtech(void)
-{
-	return ir_register_map(&npgtech_map);
-}
-
-static void __exit exit_rc_map_npgtech(void)
-{
-	ir_unregister_map(&npgtech_map);
-}
-
-module_init(init_rc_map_npgtech)
-module_exit(exit_rc_map_npgtech)
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-pctv-sedna.c linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-pctv-sedna.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-pctv-sedna.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-pctv-sedna.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,80 +0,0 @@
-/* pctv-sedna.h - Keytable for pctv_sedna Remote Controller
- *
- * keymap imported from ir-keymaps.c
- *
- * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
-
-/* Mapping for the 28 key remote control as seen at
-   http://www.sednacomputer.com/photo/cardbus-tv.jpg
-   Pavel Mihaylov <bin@bash.info>
-   Also for the remote bundled with Kozumi KTV-01C card */
-
-static struct ir_scancode pctv_sedna[] = {
-	{ 0x00, KEY_0 },
-	{ 0x01, KEY_1 },
-	{ 0x02, KEY_2 },
-	{ 0x03, KEY_3 },
-	{ 0x04, KEY_4 },
-	{ 0x05, KEY_5 },
-	{ 0x06, KEY_6 },
-	{ 0x07, KEY_7 },
-	{ 0x08, KEY_8 },
-	{ 0x09, KEY_9 },
-
-	{ 0x0a, KEY_AGAIN },	/* Recall */
-	{ 0x0b, KEY_CHANNELUP },
-	{ 0x0c, KEY_VOLUMEUP },
-	{ 0x0d, KEY_MODE },	/* Stereo */
-	{ 0x0e, KEY_STOP },
-	{ 0x0f, KEY_PREVIOUSSONG },
-	{ 0x10, KEY_ZOOM },
-	{ 0x11, KEY_TUNER },	/* Source */
-	{ 0x12, KEY_POWER },
-	{ 0x13, KEY_MUTE },
-	{ 0x15, KEY_CHANNELDOWN },
-	{ 0x18, KEY_VOLUMEDOWN },
-	{ 0x19, KEY_CAMERA },	/* Snapshot */
-	{ 0x1a, KEY_NEXTSONG },
-	{ 0x1b, KEY_TIME },	/* Time Shift */
-	{ 0x1c, KEY_RADIO },	/* FM Radio */
-	{ 0x1d, KEY_RECORD },
-	{ 0x1e, KEY_PAUSE },
-	/* additional codes for Kozumi's remote */
-	{ 0x14, KEY_INFO },	/* OSD */
-	{ 0x16, KEY_OK },	/* OK */
-	{ 0x17, KEY_DIGITS },	/* Plus */
-	{ 0x1f, KEY_PLAY },	/* Play */
-};
-
-static struct rc_keymap pctv_sedna_map = {
-	.map = {
-		.scan    = pctv_sedna,
-		.size    = ARRAY_SIZE(pctv_sedna),
-		.ir_type = IR_TYPE_UNKNOWN,	/* Legacy IR type */
-		.name    = RC_MAP_PCTV_SEDNA,
-	}
-};
-
-static int __init init_rc_map_pctv_sedna(void)
-{
-	return ir_register_map(&pctv_sedna_map);
-}
-
-static void __exit exit_rc_map_pctv_sedna(void)
-{
-	ir_unregister_map(&pctv_sedna_map);
-}
-
-module_init(init_rc_map_pctv_sedna)
-module_exit(exit_rc_map_pctv_sedna)
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-pinnacle-color.c linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-pinnacle-color.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-pinnacle-color.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-pinnacle-color.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,94 +0,0 @@
-/* pinnacle-color.h - Keytable for pinnacle_color Remote Controller
- *
- * keymap imported from ir-keymaps.c
- *
- * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
-
-static struct ir_scancode pinnacle_color[] = {
-	{ 0x59, KEY_MUTE },
-	{ 0x4a, KEY_POWER },
-
-	{ 0x18, KEY_TEXT },
-	{ 0x26, KEY_TV },
-	{ 0x3d, KEY_PRINT },
-
-	{ 0x48, KEY_RED },
-	{ 0x04, KEY_GREEN },
-	{ 0x11, KEY_YELLOW },
-	{ 0x00, KEY_BLUE },
-
-	{ 0x2d, KEY_VOLUMEUP },
-	{ 0x1e, KEY_VOLUMEDOWN },
-
-	{ 0x49, KEY_MENU },
-
-	{ 0x16, KEY_CHANNELUP },
-	{ 0x17, KEY_CHANNELDOWN },
-
-	{ 0x20, KEY_UP },
-	{ 0x21, KEY_DOWN },
-	{ 0x22, KEY_LEFT },
-	{ 0x23, KEY_RIGHT },
-	{ 0x0d, KEY_SELECT },
-
-	{ 0x08, KEY_BACK },
-	{ 0x07, KEY_REFRESH },
-
-	{ 0x2f, KEY_ZOOM },
-	{ 0x29, KEY_RECORD },
-
-	{ 0x4b, KEY_PAUSE },
-	{ 0x4d, KEY_REWIND },
-	{ 0x2e, KEY_PLAY },
-	{ 0x4e, KEY_FORWARD },
-	{ 0x53, KEY_PREVIOUS },
-	{ 0x4c, KEY_STOP },
-	{ 0x54, KEY_NEXT },
-
-	{ 0x69, KEY_0 },
-	{ 0x6a, KEY_1 },
-	{ 0x6b, KEY_2 },
-	{ 0x6c, KEY_3 },
-	{ 0x6d, KEY_4 },
-	{ 0x6e, KEY_5 },
-	{ 0x6f, KEY_6 },
-	{ 0x70, KEY_7 },
-	{ 0x71, KEY_8 },
-	{ 0x72, KEY_9 },
-
-	{ 0x74, KEY_CHANNEL },
-	{ 0x0a, KEY_BACKSPACE },
-};
-
-static struct rc_keymap pinnacle_color_map = {
-	.map = {
-		.scan    = pinnacle_color,
-		.size    = ARRAY_SIZE(pinnacle_color),
-		.ir_type = IR_TYPE_UNKNOWN,	/* Legacy IR type */
-		.name    = RC_MAP_PINNACLE_COLOR,
-	}
-};
-
-static int __init init_rc_map_pinnacle_color(void)
-{
-	return ir_register_map(&pinnacle_color_map);
-}
-
-static void __exit exit_rc_map_pinnacle_color(void)
-{
-	ir_unregister_map(&pinnacle_color_map);
-}
-
-module_init(init_rc_map_pinnacle_color)
-module_exit(exit_rc_map_pinnacle_color)
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-pinnacle-grey.c linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-pinnacle-grey.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-pinnacle-grey.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-pinnacle-grey.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,89 +0,0 @@
-/* pinnacle-grey.h - Keytable for pinnacle_grey Remote Controller
- *
- * keymap imported from ir-keymaps.c
- *
- * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
-
-static struct ir_scancode pinnacle_grey[] = {
-	{ 0x3a, KEY_0 },
-	{ 0x31, KEY_1 },
-	{ 0x32, KEY_2 },
-	{ 0x33, KEY_3 },
-	{ 0x34, KEY_4 },
-	{ 0x35, KEY_5 },
-	{ 0x36, KEY_6 },
-	{ 0x37, KEY_7 },
-	{ 0x38, KEY_8 },
-	{ 0x39, KEY_9 },
-
-	{ 0x2f, KEY_POWER },
-
-	{ 0x2e, KEY_P },
-	{ 0x1f, KEY_L },
-	{ 0x2b, KEY_I },
-
-	{ 0x2d, KEY_SCREEN },
-	{ 0x1e, KEY_ZOOM },
-	{ 0x1b, KEY_VOLUMEUP },
-	{ 0x0f, KEY_VOLUMEDOWN },
-	{ 0x17, KEY_CHANNELUP },
-	{ 0x1c, KEY_CHANNELDOWN },
-	{ 0x25, KEY_INFO },
-
-	{ 0x3c, KEY_MUTE },
-
-	{ 0x3d, KEY_LEFT },
-	{ 0x3b, KEY_RIGHT },
-
-	{ 0x3f, KEY_UP },
-	{ 0x3e, KEY_DOWN },
-	{ 0x1a, KEY_ENTER },
-
-	{ 0x1d, KEY_MENU },
-	{ 0x19, KEY_AGAIN },
-	{ 0x16, KEY_PREVIOUSSONG },
-	{ 0x13, KEY_NEXTSONG },
-	{ 0x15, KEY_PAUSE },
-	{ 0x0e, KEY_REWIND },
-	{ 0x0d, KEY_PLAY },
-	{ 0x0b, KEY_STOP },
-	{ 0x07, KEY_FORWARD },
-	{ 0x27, KEY_RECORD },
-	{ 0x26, KEY_TUNER },
-	{ 0x29, KEY_TEXT },
-	{ 0x2a, KEY_MEDIA },
-	{ 0x18, KEY_EPG },
-};
-
-static struct rc_keymap pinnacle_grey_map = {
-	.map = {
-		.scan    = pinnacle_grey,
-		.size    = ARRAY_SIZE(pinnacle_grey),
-		.ir_type = IR_TYPE_UNKNOWN,	/* Legacy IR type */
-		.name    = RC_MAP_PINNACLE_GREY,
-	}
-};
-
-static int __init init_rc_map_pinnacle_grey(void)
-{
-	return ir_register_map(&pinnacle_grey_map);
-}
-
-static void __exit exit_rc_map_pinnacle_grey(void)
-{
-	ir_unregister_map(&pinnacle_grey_map);
-}
-
-module_init(init_rc_map_pinnacle_grey)
-module_exit(exit_rc_map_pinnacle_grey)
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-pinnacle-pctv-hd.c linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-pinnacle-pctv-hd.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-pinnacle-pctv-hd.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-pinnacle-pctv-hd.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,73 +0,0 @@
-/* pinnacle-pctv-hd.h - Keytable for pinnacle_pctv_hd Remote Controller
- *
- * keymap imported from ir-keymaps.c
- *
- * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
-
-/* Pinnacle PCTV HD 800i mini remote */
-
-static struct ir_scancode pinnacle_pctv_hd[] = {
-
-	{ 0x0f, KEY_1 },
-	{ 0x15, KEY_2 },
-	{ 0x10, KEY_3 },
-	{ 0x18, KEY_4 },
-	{ 0x1b, KEY_5 },
-	{ 0x1e, KEY_6 },
-	{ 0x11, KEY_7 },
-	{ 0x21, KEY_8 },
-	{ 0x12, KEY_9 },
-	{ 0x27, KEY_0 },
-
-	{ 0x24, KEY_ZOOM },
-	{ 0x2a, KEY_SUBTITLE },
-
-	{ 0x00, KEY_MUTE },
-	{ 0x01, KEY_ENTER },	/* Pinnacle Logo */
-	{ 0x39, KEY_POWER },
-
-	{ 0x03, KEY_VOLUMEUP },
-	{ 0x09, KEY_VOLUMEDOWN },
-	{ 0x06, KEY_CHANNELUP },
-	{ 0x0c, KEY_CHANNELDOWN },
-
-	{ 0x2d, KEY_REWIND },
-	{ 0x30, KEY_PLAYPAUSE },
-	{ 0x33, KEY_FASTFORWARD },
-	{ 0x3c, KEY_STOP },
-	{ 0x36, KEY_RECORD },
-	{ 0x3f, KEY_EPG },	/* Labeled "?" */
-};
-
-static struct rc_keymap pinnacle_pctv_hd_map = {
-	.map = {
-		.scan    = pinnacle_pctv_hd,
-		.size    = ARRAY_SIZE(pinnacle_pctv_hd),
-		.ir_type = IR_TYPE_UNKNOWN,	/* Legacy IR type */
-		.name    = RC_MAP_PINNACLE_PCTV_HD,
-	}
-};
-
-static int __init init_rc_map_pinnacle_pctv_hd(void)
-{
-	return ir_register_map(&pinnacle_pctv_hd_map);
-}
-
-static void __exit exit_rc_map_pinnacle_pctv_hd(void)
-{
-	ir_unregister_map(&pinnacle_pctv_hd_map);
-}
-
-module_init(init_rc_map_pinnacle_pctv_hd)
-module_exit(exit_rc_map_pinnacle_pctv_hd)
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-pixelview.c linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-pixelview.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-pixelview.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-pixelview.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,82 +0,0 @@
-/* pixelview.h - Keytable for pixelview Remote Controller
- *
- * keymap imported from ir-keymaps.c
- *
- * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
-
-static struct ir_scancode pixelview[] = {
-
-	{ 0x1e, KEY_POWER },	/* power */
-	{ 0x07, KEY_MEDIA },	/* source */
-	{ 0x1c, KEY_SEARCH },	/* scan */
-
-
-	{ 0x03, KEY_TUNER },		/* TV/FM */
-
-	{ 0x00, KEY_RECORD },
-	{ 0x08, KEY_STOP },
-	{ 0x11, KEY_PLAY },
-
-	{ 0x1a, KEY_PLAYPAUSE },	/* freeze */
-	{ 0x19, KEY_ZOOM },		/* zoom */
-	{ 0x0f, KEY_TEXT },		/* min */
-
-	{ 0x01, KEY_1 },
-	{ 0x0b, KEY_2 },
-	{ 0x1b, KEY_3 },
-	{ 0x05, KEY_4 },
-	{ 0x09, KEY_5 },
-	{ 0x15, KEY_6 },
-	{ 0x06, KEY_7 },
-	{ 0x0a, KEY_8 },
-	{ 0x12, KEY_9 },
-	{ 0x02, KEY_0 },
-	{ 0x10, KEY_LAST },		/* +100 */
-	{ 0x13, KEY_LIST },		/* recall */
-
-	{ 0x1f, KEY_CHANNELUP },	/* chn down */
-	{ 0x17, KEY_CHANNELDOWN },	/* chn up */
-	{ 0x16, KEY_VOLUMEUP },		/* vol down */
-	{ 0x14, KEY_VOLUMEDOWN },	/* vol up */
-
-	{ 0x04, KEY_KPMINUS },		/* <<< */
-	{ 0x0e, KEY_SETUP },		/* function */
-	{ 0x0c, KEY_KPPLUS },		/* >>> */
-
-	{ 0x0d, KEY_GOTO },		/* mts */
-	{ 0x1d, KEY_REFRESH },		/* reset */
-	{ 0x18, KEY_MUTE },		/* mute/unmute */
-};
-
-static struct rc_keymap pixelview_map = {
-	.map = {
-		.scan    = pixelview,
-		.size    = ARRAY_SIZE(pixelview),
-		.ir_type = IR_TYPE_UNKNOWN,	/* Legacy IR type */
-		.name    = RC_MAP_PIXELVIEW,
-	}
-};
-
-static int __init init_rc_map_pixelview(void)
-{
-	return ir_register_map(&pixelview_map);
-}
-
-static void __exit exit_rc_map_pixelview(void)
-{
-	ir_unregister_map(&pixelview_map);
-}
-
-module_init(init_rc_map_pixelview)
-module_exit(exit_rc_map_pixelview)
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-pixelview-mk12.c linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-pixelview-mk12.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-pixelview-mk12.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-pixelview-mk12.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,83 +0,0 @@
-/* rc-pixelview-mk12.h - Keytable for pixelview Remote Controller
- *
- * keymap imported from ir-keymaps.c
- *
- * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
-
-/*
- * Keytable for MK-F12 IR remote provided together with Pixelview
- * Ultra Pro Remote Controller. Uses NEC extended format.
- */
-static struct ir_scancode pixelview_mk12[] = {
-	{ 0x866b03, KEY_TUNER },	/* Timeshift */
-	{ 0x866b1e, KEY_POWER2 },	/* power */
-
-	{ 0x866b01, KEY_1 },
-	{ 0x866b0b, KEY_2 },
-	{ 0x866b1b, KEY_3 },
-	{ 0x866b05, KEY_4 },
-	{ 0x866b09, KEY_5 },
-	{ 0x866b15, KEY_6 },
-	{ 0x866b06, KEY_7 },
-	{ 0x866b0a, KEY_8 },
-	{ 0x866b12, KEY_9 },
-	{ 0x866b02, KEY_0 },
-
-	{ 0x866b13, KEY_AGAIN },	/* loop */
-	{ 0x866b10, KEY_DIGITS },	/* +100 */
-
-	{ 0x866b00, KEY_MEDIA },	/* source */
-	{ 0x866b18, KEY_MUTE },		/* mute */
-	{ 0x866b19, KEY_CAMERA },	/* snapshot */
-	{ 0x866b1a, KEY_SEARCH },	/* scan */
-
-	{ 0x866b16, KEY_CHANNELUP },	/* chn + */
-	{ 0x866b14, KEY_CHANNELDOWN },	/* chn - */
-	{ 0x866b1f, KEY_VOLUMEUP },	/* vol + */
-	{ 0x866b17, KEY_VOLUMEDOWN },	/* vol - */
-	{ 0x866b1c, KEY_ZOOM },		/* zoom */
-
-	{ 0x866b04, KEY_REWIND },
-	{ 0x866b0e, KEY_RECORD },
-	{ 0x866b0c, KEY_FORWARD },
-
-	{ 0x866b1d, KEY_STOP },
-	{ 0x866b08, KEY_PLAY },
-	{ 0x866b0f, KEY_PAUSE },
-
-	{ 0x866b0d, KEY_TV },
-	{ 0x866b07, KEY_RADIO },	/* FM */
-};
-
-static struct rc_keymap pixelview_map = {
-	.map = {
-		.scan    = pixelview_mk12,
-		.size    = ARRAY_SIZE(pixelview_mk12),
-		.ir_type = IR_TYPE_NEC,
-		.name    = RC_MAP_PIXELVIEW_MK12,
-	}
-};
-
-static int __init init_rc_map_pixelview(void)
-{
-	return ir_register_map(&pixelview_map);
-}
-
-static void __exit exit_rc_map_pixelview(void)
-{
-	ir_unregister_map(&pixelview_map);
-}
-
-module_init(init_rc_map_pixelview)
-module_exit(exit_rc_map_pixelview)
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-pixelview-new.c linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-pixelview-new.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-pixelview-new.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-pixelview-new.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,83 +0,0 @@
-/* pixelview-new.h - Keytable for pixelview_new Remote Controller
- *
- * keymap imported from ir-keymaps.c
- *
- * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
-
-/*
-   Mauro Carvalho Chehab <mchehab@infradead.org>
-   present on PV MPEG 8000GT
- */
-
-static struct ir_scancode pixelview_new[] = {
-	{ 0x3c, KEY_TIME },		/* Timeshift */
-	{ 0x12, KEY_POWER },
-
-	{ 0x3d, KEY_1 },
-	{ 0x38, KEY_2 },
-	{ 0x18, KEY_3 },
-	{ 0x35, KEY_4 },
-	{ 0x39, KEY_5 },
-	{ 0x15, KEY_6 },
-	{ 0x36, KEY_7 },
-	{ 0x3a, KEY_8 },
-	{ 0x1e, KEY_9 },
-	{ 0x3e, KEY_0 },
-
-	{ 0x1c, KEY_AGAIN },		/* LOOP	*/
-	{ 0x3f, KEY_MEDIA },		/* Source */
-	{ 0x1f, KEY_LAST },		/* +100 */
-	{ 0x1b, KEY_MUTE },
-
-	{ 0x17, KEY_CHANNELDOWN },
-	{ 0x16, KEY_CHANNELUP },
-	{ 0x10, KEY_VOLUMEUP },
-	{ 0x14, KEY_VOLUMEDOWN },
-	{ 0x13, KEY_ZOOM },
-
-	{ 0x19, KEY_CAMERA },		/* SNAPSHOT */
-	{ 0x1a, KEY_SEARCH },		/* scan */
-
-	{ 0x37, KEY_REWIND },		/* << */
-	{ 0x32, KEY_RECORD },		/* o (red) */
-	{ 0x33, KEY_FORWARD },		/* >> */
-	{ 0x11, KEY_STOP },		/* square */
-	{ 0x3b, KEY_PLAY },		/* > */
-	{ 0x30, KEY_PLAYPAUSE },	/* || */
-
-	{ 0x31, KEY_TV },
-	{ 0x34, KEY_RADIO },
-};
-
-static struct rc_keymap pixelview_new_map = {
-	.map = {
-		.scan    = pixelview_new,
-		.size    = ARRAY_SIZE(pixelview_new),
-		.ir_type = IR_TYPE_UNKNOWN,	/* Legacy IR type */
-		.name    = RC_MAP_PIXELVIEW_NEW,
-	}
-};
-
-static int __init init_rc_map_pixelview_new(void)
-{
-	return ir_register_map(&pixelview_new_map);
-}
-
-static void __exit exit_rc_map_pixelview_new(void)
-{
-	ir_unregister_map(&pixelview_new_map);
-}
-
-module_init(init_rc_map_pixelview_new)
-module_exit(exit_rc_map_pixelview_new)
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-powercolor-real-angel.c linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-powercolor-real-angel.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-powercolor-real-angel.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-powercolor-real-angel.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,81 +0,0 @@
-/* powercolor-real-angel.h - Keytable for powercolor_real_angel Remote Controller
- *
- * keymap imported from ir-keymaps.c
- *
- * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
-
-/*
- * Remote control for Powercolor Real Angel 330
- * Daniel Fraga <fragabr@gmail.com>
- */
-
-static struct ir_scancode powercolor_real_angel[] = {
-	{ 0x38, KEY_SWITCHVIDEOMODE },	/* switch inputs */
-	{ 0x0c, KEY_MEDIA },		/* Turn ON/OFF App */
-	{ 0x00, KEY_0 },
-	{ 0x01, KEY_1 },
-	{ 0x02, KEY_2 },
-	{ 0x03, KEY_3 },
-	{ 0x04, KEY_4 },
-	{ 0x05, KEY_5 },
-	{ 0x06, KEY_6 },
-	{ 0x07, KEY_7 },
-	{ 0x08, KEY_8 },
-	{ 0x09, KEY_9 },
-	{ 0x0a, KEY_DIGITS },		/* single, double, tripple digit */
-	{ 0x29, KEY_PREVIOUS },		/* previous channel */
-	{ 0x12, KEY_BRIGHTNESSUP },
-	{ 0x13, KEY_BRIGHTNESSDOWN },
-	{ 0x2b, KEY_MODE },		/* stereo/mono */
-	{ 0x2c, KEY_TEXT },		/* teletext */
-	{ 0x20, KEY_CHANNELUP },	/* channel up */
-	{ 0x21, KEY_CHANNELDOWN },	/* channel down */
-	{ 0x10, KEY_VOLUMEUP },		/* volume up */
-	{ 0x11, KEY_VOLUMEDOWN },	/* volume down */
-	{ 0x0d, KEY_MUTE },
-	{ 0x1f, KEY_RECORD },
-	{ 0x17, KEY_PLAY },
-	{ 0x16, KEY_PAUSE },
-	{ 0x0b, KEY_STOP },
-	{ 0x27, KEY_FASTFORWARD },
-	{ 0x26, KEY_REWIND },
-	{ 0x1e, KEY_SEARCH },		/* autoscan */
-	{ 0x0e, KEY_CAMERA },		/* snapshot */
-	{ 0x2d, KEY_SETUP },
-	{ 0x0f, KEY_SCREEN },		/* full screen */
-	{ 0x14, KEY_RADIO },		/* FM radio */
-	{ 0x25, KEY_POWER },		/* power */
-};
-
-static struct rc_keymap powercolor_real_angel_map = {
-	.map = {
-		.scan    = powercolor_real_angel,
-		.size    = ARRAY_SIZE(powercolor_real_angel),
-		.ir_type = IR_TYPE_UNKNOWN,	/* Legacy IR type */
-		.name    = RC_MAP_POWERCOLOR_REAL_ANGEL,
-	}
-};
-
-static int __init init_rc_map_powercolor_real_angel(void)
-{
-	return ir_register_map(&powercolor_real_angel_map);
-}
-
-static void __exit exit_rc_map_powercolor_real_angel(void)
-{
-	ir_unregister_map(&powercolor_real_angel_map);
-}
-
-module_init(init_rc_map_powercolor_real_angel)
-module_exit(exit_rc_map_powercolor_real_angel)
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-proteus-2309.c linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-proteus-2309.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-proteus-2309.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-proteus-2309.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,69 +0,0 @@
-/* proteus-2309.h - Keytable for proteus_2309 Remote Controller
- *
- * keymap imported from ir-keymaps.c
- *
- * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
-
-/* Michal Majchrowicz <mmajchrowicz@gmail.com> */
-
-static struct ir_scancode proteus_2309[] = {
-	/* numeric */
-	{ 0x00, KEY_0 },
-	{ 0x01, KEY_1 },
-	{ 0x02, KEY_2 },
-	{ 0x03, KEY_3 },
-	{ 0x04, KEY_4 },
-	{ 0x05, KEY_5 },
-	{ 0x06, KEY_6 },
-	{ 0x07, KEY_7 },
-	{ 0x08, KEY_8 },
-	{ 0x09, KEY_9 },
-
-	{ 0x5c, KEY_POWER },		/* power       */
-	{ 0x20, KEY_ZOOM },		/* full screen */
-	{ 0x0f, KEY_BACKSPACE },	/* recall      */
-	{ 0x1b, KEY_ENTER },		/* mute        */
-	{ 0x41, KEY_RECORD },		/* record      */
-	{ 0x43, KEY_STOP },		/* stop        */
-	{ 0x16, KEY_S },
-	{ 0x1a, KEY_POWER2 },		/* off         */
-	{ 0x2e, KEY_RED },
-	{ 0x1f, KEY_CHANNELDOWN },	/* channel -   */
-	{ 0x1c, KEY_CHANNELUP },	/* channel +   */
-	{ 0x10, KEY_VOLUMEDOWN },	/* volume -    */
-	{ 0x1e, KEY_VOLUMEUP },		/* volume +    */
-	{ 0x14, KEY_F1 },
-};
-
-static struct rc_keymap proteus_2309_map = {
-	.map = {
-		.scan    = proteus_2309,
-		.size    = ARRAY_SIZE(proteus_2309),
-		.ir_type = IR_TYPE_UNKNOWN,	/* Legacy IR type */
-		.name    = RC_MAP_PROTEUS_2309,
-	}
-};
-
-static int __init init_rc_map_proteus_2309(void)
-{
-	return ir_register_map(&proteus_2309_map);
-}
-
-static void __exit exit_rc_map_proteus_2309(void)
-{
-	ir_unregister_map(&proteus_2309_map);
-}
-
-module_init(init_rc_map_proteus_2309)
-module_exit(exit_rc_map_proteus_2309)
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-purpletv.c linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-purpletv.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-purpletv.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-purpletv.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,81 +0,0 @@
-/* purpletv.h - Keytable for purpletv Remote Controller
- *
- * keymap imported from ir-keymaps.c
- *
- * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
-
-static struct ir_scancode purpletv[] = {
-	{ 0x03, KEY_POWER },
-	{ 0x6f, KEY_MUTE },
-	{ 0x10, KEY_BACKSPACE },	/* Recall */
-
-	{ 0x11, KEY_0 },
-	{ 0x04, KEY_1 },
-	{ 0x05, KEY_2 },
-	{ 0x06, KEY_3 },
-	{ 0x08, KEY_4 },
-	{ 0x09, KEY_5 },
-	{ 0x0a, KEY_6 },
-	{ 0x0c, KEY_7 },
-	{ 0x0d, KEY_8 },
-	{ 0x0e, KEY_9 },
-	{ 0x12, KEY_DOT },	/* 100+ */
-
-	{ 0x07, KEY_VOLUMEUP },
-	{ 0x0b, KEY_VOLUMEDOWN },
-	{ 0x1a, KEY_KPPLUS },
-	{ 0x18, KEY_KPMINUS },
-	{ 0x15, KEY_UP },
-	{ 0x1d, KEY_DOWN },
-	{ 0x0f, KEY_CHANNELUP },
-	{ 0x13, KEY_CHANNELDOWN },
-	{ 0x48, KEY_ZOOM },
-
-	{ 0x1b, KEY_VIDEO },	/* Video source */
-	{ 0x1f, KEY_CAMERA },	/* Snapshot */
-	{ 0x49, KEY_LANGUAGE },	/* MTS Select */
-	{ 0x19, KEY_SEARCH },	/* Auto Scan */
-
-	{ 0x4b, KEY_RECORD },
-	{ 0x46, KEY_PLAY },
-	{ 0x45, KEY_PAUSE },	/* Pause */
-	{ 0x44, KEY_STOP },
-	{ 0x43, KEY_TIME },	/* Time Shift */
-	{ 0x17, KEY_CHANNEL },	/* SURF CH */
-	{ 0x40, KEY_FORWARD },	/* Forward ? */
-	{ 0x42, KEY_REWIND },	/* Backward ? */
-
-};
-
-static struct rc_keymap purpletv_map = {
-	.map = {
-		.scan    = purpletv,
-		.size    = ARRAY_SIZE(purpletv),
-		.ir_type = IR_TYPE_UNKNOWN,	/* Legacy IR type */
-		.name    = RC_MAP_PURPLETV,
-	}
-};
-
-static int __init init_rc_map_purpletv(void)
-{
-	return ir_register_map(&purpletv_map);
-}
-
-static void __exit exit_rc_map_purpletv(void)
-{
-	ir_unregister_map(&purpletv_map);
-}
-
-module_init(init_rc_map_purpletv)
-module_exit(exit_rc_map_purpletv)
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-pv951.c linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-pv951.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-pv951.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-pv951.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,78 +0,0 @@
-/* pv951.h - Keytable for pv951 Remote Controller
- *
- * keymap imported from ir-keymaps.c
- *
- * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
-
-/* Mark Phalan <phalanm@o2.ie> */
-
-static struct ir_scancode pv951[] = {
-	{ 0x00, KEY_0 },
-	{ 0x01, KEY_1 },
-	{ 0x02, KEY_2 },
-	{ 0x03, KEY_3 },
-	{ 0x04, KEY_4 },
-	{ 0x05, KEY_5 },
-	{ 0x06, KEY_6 },
-	{ 0x07, KEY_7 },
-	{ 0x08, KEY_8 },
-	{ 0x09, KEY_9 },
-
-	{ 0x12, KEY_POWER },
-	{ 0x10, KEY_MUTE },
-	{ 0x1f, KEY_VOLUMEDOWN },
-	{ 0x1b, KEY_VOLUMEUP },
-	{ 0x1a, KEY_CHANNELUP },
-	{ 0x1e, KEY_CHANNELDOWN },
-	{ 0x0e, KEY_PAGEUP },
-	{ 0x1d, KEY_PAGEDOWN },
-	{ 0x13, KEY_SOUND },
-
-	{ 0x18, KEY_KPPLUSMINUS },	/* CH +/- */
-	{ 0x16, KEY_SUBTITLE },		/* CC */
-	{ 0x0d, KEY_TEXT },		/* TTX */
-	{ 0x0b, KEY_TV },		/* AIR/CBL */
-	{ 0x11, KEY_PC },		/* PC/TV */
-	{ 0x17, KEY_OK },		/* CH RTN */
-	{ 0x19, KEY_MODE },		/* FUNC */
-	{ 0x0c, KEY_SEARCH },		/* AUTOSCAN */
-
-	/* Not sure what to do with these ones! */
-	{ 0x0f, KEY_SELECT },		/* SOURCE */
-	{ 0x0a, KEY_KPPLUS },		/* +100 */
-	{ 0x14, KEY_EQUAL },		/* SYNC */
-	{ 0x1c, KEY_MEDIA },		/* PC/TV */
-};
-
-static struct rc_keymap pv951_map = {
-	.map = {
-		.scan    = pv951,
-		.size    = ARRAY_SIZE(pv951),
-		.ir_type = IR_TYPE_UNKNOWN,	/* Legacy IR type */
-		.name    = RC_MAP_PV951,
-	}
-};
-
-static int __init init_rc_map_pv951(void)
-{
-	return ir_register_map(&pv951_map);
-}
-
-static void __exit exit_rc_map_pv951(void)
-{
-	ir_unregister_map(&pv951_map);
-}
-
-module_init(init_rc_map_pv951)
-module_exit(exit_rc_map_pv951)
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-rc5-hauppauge-new.c linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-rc5-hauppauge-new.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-rc5-hauppauge-new.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-rc5-hauppauge-new.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,103 +0,0 @@
-/* rc5-hauppauge-new.h - Keytable for rc5_hauppauge_new Remote Controller
- *
- * keymap imported from ir-keymaps.c
- *
- * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
-
-/*
- * Hauppauge:the newer, gray remotes (seems there are multiple
- * slightly different versions), shipped with cx88+ivtv cards.
- *
- * This table contains the complete RC5 code, instead of just the data part
- */
-
-static struct ir_scancode rc5_hauppauge_new[] = {
-	/* Keys 0 to 9 */
-	{ 0x1e00, KEY_0 },
-	{ 0x1e01, KEY_1 },
-	{ 0x1e02, KEY_2 },
-	{ 0x1e03, KEY_3 },
-	{ 0x1e04, KEY_4 },
-	{ 0x1e05, KEY_5 },
-	{ 0x1e06, KEY_6 },
-	{ 0x1e07, KEY_7 },
-	{ 0x1e08, KEY_8 },
-	{ 0x1e09, KEY_9 },
-
-	{ 0x1e0a, KEY_TEXT },		/* keypad asterisk as well */
-	{ 0x1e0b, KEY_RED },		/* red button */
-	{ 0x1e0c, KEY_RADIO },
-	{ 0x1e0d, KEY_MENU },
-	{ 0x1e0e, KEY_SUBTITLE },		/* also the # key */
-	{ 0x1e0f, KEY_MUTE },
-	{ 0x1e10, KEY_VOLUMEUP },
-	{ 0x1e11, KEY_VOLUMEDOWN },
-	{ 0x1e12, KEY_PREVIOUS },		/* previous channel */
-	{ 0x1e14, KEY_UP },
-	{ 0x1e15, KEY_DOWN },
-	{ 0x1e16, KEY_LEFT },
-	{ 0x1e17, KEY_RIGHT },
-	{ 0x1e18, KEY_VIDEO },		/* Videos */
-	{ 0x1e19, KEY_AUDIO },		/* Music */
-	/* 0x1e1a: Pictures - presume this means
-	   "Multimedia Home Platform" -
-	   no "PICTURES" key in input.h
-	 */
-	{ 0x1e1a, KEY_MHP },
-
-	{ 0x1e1b, KEY_EPG },		/* Guide */
-	{ 0x1e1c, KEY_TV },
-	{ 0x1e1e, KEY_NEXTSONG },		/* skip >| */
-	{ 0x1e1f, KEY_EXIT },		/* back/exit */
-	{ 0x1e20, KEY_CHANNELUP },	/* channel / program + */
-	{ 0x1e21, KEY_CHANNELDOWN },	/* channel / program - */
-	{ 0x1e22, KEY_CHANNEL },		/* source (old black remote) */
-	{ 0x1e24, KEY_PREVIOUSSONG },	/* replay |< */
-	{ 0x1e25, KEY_ENTER },		/* OK */
-	{ 0x1e26, KEY_SLEEP },		/* minimize (old black remote) */
-	{ 0x1e29, KEY_BLUE },		/* blue key */
-	{ 0x1e2e, KEY_GREEN },		/* green button */
-	{ 0x1e30, KEY_PAUSE },		/* pause */
-	{ 0x1e32, KEY_REWIND },		/* backward << */
-	{ 0x1e34, KEY_FASTFORWARD },	/* forward >> */
-	{ 0x1e35, KEY_PLAY },
-	{ 0x1e36, KEY_STOP },
-	{ 0x1e37, KEY_RECORD },		/* recording */
-	{ 0x1e38, KEY_YELLOW },		/* yellow key */
-	{ 0x1e3b, KEY_SELECT },		/* top right button */
-	{ 0x1e3c, KEY_ZOOM },		/* full */
-	{ 0x1e3d, KEY_POWER },		/* system power (green button) */
-};
-
-static struct rc_keymap rc5_hauppauge_new_map = {
-	.map = {
-		.scan    = rc5_hauppauge_new,
-		.size    = ARRAY_SIZE(rc5_hauppauge_new),
-		.ir_type = IR_TYPE_RC5,
-		.name    = RC_MAP_RC5_HAUPPAUGE_NEW,
-	}
-};
-
-static int __init init_rc_map_rc5_hauppauge_new(void)
-{
-	return ir_register_map(&rc5_hauppauge_new_map);
-}
-
-static void __exit exit_rc_map_rc5_hauppauge_new(void)
-{
-	ir_unregister_map(&rc5_hauppauge_new_map);
-}
-
-module_init(init_rc_map_rc5_hauppauge_new)
-module_exit(exit_rc_map_rc5_hauppauge_new)
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-rc5-tv.c linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-rc5-tv.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-rc5-tv.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-rc5-tv.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,81 +0,0 @@
-/* rc5-tv.h - Keytable for rc5_tv Remote Controller
- *
- * keymap imported from ir-keymaps.c
- *
- * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
-
-/* generic RC5 keytable                                          */
-/* see http://users.pandora.be/nenya/electronics/rc5/codes00.htm */
-/* used by old (black) Hauppauge remotes                         */
-
-static struct ir_scancode rc5_tv[] = {
-	/* Keys 0 to 9 */
-	{ 0x00, KEY_0 },
-	{ 0x01, KEY_1 },
-	{ 0x02, KEY_2 },
-	{ 0x03, KEY_3 },
-	{ 0x04, KEY_4 },
-	{ 0x05, KEY_5 },
-	{ 0x06, KEY_6 },
-	{ 0x07, KEY_7 },
-	{ 0x08, KEY_8 },
-	{ 0x09, KEY_9 },
-
-	{ 0x0b, KEY_CHANNEL },		/* channel / program (japan: 11) */
-	{ 0x0c, KEY_POWER },		/* standby */
-	{ 0x0d, KEY_MUTE },		/* mute / demute */
-	{ 0x0f, KEY_TV },		/* display */
-	{ 0x10, KEY_VOLUMEUP },
-	{ 0x11, KEY_VOLUMEDOWN },
-	{ 0x12, KEY_BRIGHTNESSUP },
-	{ 0x13, KEY_BRIGHTNESSDOWN },
-	{ 0x1e, KEY_SEARCH },		/* search + */
-	{ 0x20, KEY_CHANNELUP },	/* channel / program + */
-	{ 0x21, KEY_CHANNELDOWN },	/* channel / program - */
-	{ 0x22, KEY_CHANNEL },		/* alt / channel */
-	{ 0x23, KEY_LANGUAGE },		/* 1st / 2nd language */
-	{ 0x26, KEY_SLEEP },		/* sleeptimer */
-	{ 0x2e, KEY_MENU },		/* 2nd controls (USA: menu) */
-	{ 0x30, KEY_PAUSE },
-	{ 0x32, KEY_REWIND },
-	{ 0x33, KEY_GOTO },
-	{ 0x35, KEY_PLAY },
-	{ 0x36, KEY_STOP },
-	{ 0x37, KEY_RECORD },		/* recording */
-	{ 0x3c, KEY_TEXT },		/* teletext submode (Japan: 12) */
-	{ 0x3d, KEY_SUSPEND },		/* system standby */
-
-};
-
-static struct rc_keymap rc5_tv_map = {
-	.map = {
-		.scan    = rc5_tv,
-		.size    = ARRAY_SIZE(rc5_tv),
-		.ir_type = IR_TYPE_UNKNOWN,	/* Legacy IR type */
-		.name    = RC_MAP_RC5_TV,
-	}
-};
-
-static int __init init_rc_map_rc5_tv(void)
-{
-	return ir_register_map(&rc5_tv_map);
-}
-
-static void __exit exit_rc_map_rc5_tv(void)
-{
-	ir_unregister_map(&rc5_tv_map);
-}
-
-module_init(init_rc_map_rc5_tv)
-module_exit(exit_rc_map_rc5_tv)
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-rc6-mce.c linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-rc6-mce.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-rc6-mce.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-rc6-mce.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,113 +0,0 @@
-/* rc-rc6-mce.c - Keytable for Windows Media Center RC-6 remotes for use
- * with the Media Center Edition eHome Infrared Transceiver.
- *
- * Copyright (c) 2010 by Jarod Wilson <jarod@redhat.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 <media/rc-map.h>
-
-static struct ir_scancode rc6_mce[] = {
-
-	{ 0x800f0400, KEY_NUMERIC_0 },
-	{ 0x800f0401, KEY_NUMERIC_1 },
-	{ 0x800f0402, KEY_NUMERIC_2 },
-	{ 0x800f0403, KEY_NUMERIC_3 },
-	{ 0x800f0404, KEY_NUMERIC_4 },
-	{ 0x800f0405, KEY_NUMERIC_5 },
-	{ 0x800f0406, KEY_NUMERIC_6 },
-	{ 0x800f0407, KEY_NUMERIC_7 },
-	{ 0x800f0408, KEY_NUMERIC_8 },
-	{ 0x800f0409, KEY_NUMERIC_9 },
-
-	{ 0x800f040a, KEY_DELETE },
-	{ 0x800f040b, KEY_ENTER },
-	{ 0x800f040c, KEY_POWER },		/* PC Power */
-	{ 0x800f040d, KEY_PROG1 },		/* Windows MCE button */
-	{ 0x800f040e, KEY_MUTE },
-	{ 0x800f040f, KEY_INFO },
-
-	{ 0x800f0410, KEY_VOLUMEUP },
-	{ 0x800f0411, KEY_VOLUMEDOWN },
-	{ 0x800f0412, KEY_CHANNELUP },
-	{ 0x800f0413, KEY_CHANNELDOWN },
-
-	{ 0x800f0414, KEY_FASTFORWARD },
-	{ 0x800f0415, KEY_REWIND },
-	{ 0x800f0416, KEY_PLAY },
-	{ 0x800f0417, KEY_RECORD },
-	{ 0x800f0418, KEY_PAUSE },
-	{ 0x800f046e, KEY_PLAYPAUSE },
-	{ 0x800f0419, KEY_STOP },
-	{ 0x800f041a, KEY_NEXT },
-	{ 0x800f041b, KEY_PREVIOUS },
-	{ 0x800f041c, KEY_NUMERIC_POUND },
-	{ 0x800f041d, KEY_NUMERIC_STAR },
-
-	{ 0x800f041e, KEY_UP },
-	{ 0x800f041f, KEY_DOWN },
-	{ 0x800f0420, KEY_LEFT },
-	{ 0x800f0421, KEY_RIGHT },
-
-	{ 0x800f0422, KEY_OK },
-	{ 0x800f0423, KEY_EXIT },
-	{ 0x800f0424, KEY_DVD },
-	{ 0x800f0425, KEY_TUNER },		/* LiveTV */
-	{ 0x800f0426, KEY_EPG },		/* Guide */
-	{ 0x800f0427, KEY_ZOOM },		/* Aspect */
-
-	{ 0x800f043a, KEY_BRIGHTNESSUP },
-
-	{ 0x800f0446, KEY_TV },
-	{ 0x800f0447, KEY_AUDIO },		/* My Music */
-	{ 0x800f0448, KEY_PVR },		/* RecordedTV */
-	{ 0x800f0449, KEY_CAMERA },
-	{ 0x800f044a, KEY_VIDEO },
-	{ 0x800f044c, KEY_LANGUAGE },
-	{ 0x800f044d, KEY_TITLE },
-	{ 0x800f044e, KEY_PRINT },	/* Print - HP OEM version of remote */
-
-	{ 0x800f0450, KEY_RADIO },
-
-	{ 0x800f045a, KEY_SUBTITLE },		/* Caption/Teletext */
-	{ 0x800f045b, KEY_RED },
-	{ 0x800f045c, KEY_GREEN },
-	{ 0x800f045d, KEY_YELLOW },
-	{ 0x800f045e, KEY_BLUE },
-
-	{ 0x800f0465, KEY_POWER2 },	/* TV Power */
-	{ 0x800f046e, KEY_PLAYPAUSE },
-	{ 0x800f046f, KEY_MEDIA },	/* Start media application (NEW) */
-
-	{ 0x800f0480, KEY_BRIGHTNESSDOWN },
-	{ 0x800f0481, KEY_PLAYPAUSE },
-};
-
-static struct rc_keymap rc6_mce_map = {
-	.map = {
-		.scan    = rc6_mce,
-		.size    = ARRAY_SIZE(rc6_mce),
-		.ir_type = IR_TYPE_RC6,
-		.name    = RC_MAP_RC6_MCE,
-	}
-};
-
-static int __init init_rc_map_rc6_mce(void)
-{
-	return ir_register_map(&rc6_mce_map);
-}
-
-static void __exit exit_rc_map_rc6_mce(void)
-{
-	ir_unregister_map(&rc6_mce_map);
-}
-
-module_init(init_rc_map_rc6_mce)
-module_exit(exit_rc_map_rc6_mce)
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Jarod Wilson <jarod@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-real-audio-220-32-keys.c linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-real-audio-220-32-keys.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-real-audio-220-32-keys.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-real-audio-220-32-keys.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,78 +0,0 @@
-/* real-audio-220-32-keys.h - Keytable for real_audio_220_32_keys Remote Controller
- *
- * keymap imported from ir-keymaps.c
- *
- * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
-
-/* Zogis Real Audio 220 - 32 keys IR */
-
-static struct ir_scancode real_audio_220_32_keys[] = {
-	{ 0x1c, KEY_RADIO},
-	{ 0x12, KEY_POWER2},
-
-	{ 0x01, KEY_1},
-	{ 0x02, KEY_2},
-	{ 0x03, KEY_3},
-	{ 0x04, KEY_4},
-	{ 0x05, KEY_5},
-	{ 0x06, KEY_6},
-	{ 0x07, KEY_7},
-	{ 0x08, KEY_8},
-	{ 0x09, KEY_9},
-	{ 0x00, KEY_0},
-
-	{ 0x0c, KEY_VOLUMEUP},
-	{ 0x18, KEY_VOLUMEDOWN},
-	{ 0x0b, KEY_CHANNELUP},
-	{ 0x15, KEY_CHANNELDOWN},
-	{ 0x16, KEY_ENTER},
-
-	{ 0x11, KEY_LIST},		/* Source */
-	{ 0x0d, KEY_AUDIO},		/* stereo */
-
-	{ 0x0f, KEY_PREVIOUS},		/* Prev */
-	{ 0x1b, KEY_TIME},		/* Timeshift */
-	{ 0x1a, KEY_NEXT},		/* Next */
-
-	{ 0x0e, KEY_STOP},
-	{ 0x1f, KEY_PLAY},
-	{ 0x1e, KEY_PLAYPAUSE},		/* Pause */
-
-	{ 0x1d, KEY_RECORD},
-	{ 0x13, KEY_MUTE},
-	{ 0x19, KEY_CAMERA},		/* Snapshot */
-
-};
-
-static struct rc_keymap real_audio_220_32_keys_map = {
-	.map = {
-		.scan    = real_audio_220_32_keys,
-		.size    = ARRAY_SIZE(real_audio_220_32_keys),
-		.ir_type = IR_TYPE_UNKNOWN,	/* Legacy IR type */
-		.name    = RC_MAP_REAL_AUDIO_220_32_KEYS,
-	}
-};
-
-static int __init init_rc_map_real_audio_220_32_keys(void)
-{
-	return ir_register_map(&real_audio_220_32_keys_map);
-}
-
-static void __exit exit_rc_map_real_audio_220_32_keys(void)
-{
-	ir_unregister_map(&real_audio_220_32_keys_map);
-}
-
-module_init(init_rc_map_real_audio_220_32_keys)
-module_exit(exit_rc_map_real_audio_220_32_keys)
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-streamzap.c linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-streamzap.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-streamzap.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-streamzap.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,82 +0,0 @@
-/* rc-streamzap.c - Keytable for Streamzap PC Remote, for use
- * with the Streamzap PC Remote IR Receiver.
- *
- * Copyright (c) 2010 by Jarod Wilson <jarod@redhat.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 <media/rc-map.h>
-
-static struct ir_scancode streamzap[] = {
-/*
- * The Streamzap remote is almost, but not quite, RC-5, as it has an extra
- * bit in it, which throws the in-kernel RC-5 decoder for a loop. Currently,
- * an additional RC-5-sz decoder is being deployed to support it, but it
- * may be possible to merge it back with the standard RC-5 decoder.
- */
-	{ 0x28c0, KEY_NUMERIC_0 },
-	{ 0x28c1, KEY_NUMERIC_1 },
-	{ 0x28c2, KEY_NUMERIC_2 },
-	{ 0x28c3, KEY_NUMERIC_3 },
-	{ 0x28c4, KEY_NUMERIC_4 },
-	{ 0x28c5, KEY_NUMERIC_5 },
-	{ 0x28c6, KEY_NUMERIC_6 },
-	{ 0x28c7, KEY_NUMERIC_7 },
-	{ 0x28c8, KEY_NUMERIC_8 },
-	{ 0x28c9, KEY_NUMERIC_9 },
-	{ 0x28ca, KEY_POWER },
-	{ 0x28cb, KEY_MUTE },
-	{ 0x28cc, KEY_CHANNELUP },
-	{ 0x28cd, KEY_VOLUMEUP },
-	{ 0x28ce, KEY_CHANNELDOWN },
-	{ 0x28cf, KEY_VOLUMEDOWN },
-	{ 0x28d0, KEY_UP },
-	{ 0x28d1, KEY_LEFT },
-	{ 0x28d2, KEY_OK },
-	{ 0x28d3, KEY_RIGHT },
-	{ 0x28d4, KEY_DOWN },
-	{ 0x28d5, KEY_MENU },
-	{ 0x28d6, KEY_EXIT },
-	{ 0x28d7, KEY_PLAY },
-	{ 0x28d8, KEY_PAUSE },
-	{ 0x28d9, KEY_STOP },
-	{ 0x28da, KEY_BACK },
-	{ 0x28db, KEY_FORWARD },
-	{ 0x28dc, KEY_RECORD },
-	{ 0x28dd, KEY_REWIND },
-	{ 0x28de, KEY_FASTFORWARD },
-	{ 0x28e0, KEY_RED },
-	{ 0x28e1, KEY_GREEN },
-	{ 0x28e2, KEY_YELLOW },
-	{ 0x28e3, KEY_BLUE },
-
-};
-
-static struct rc_keymap streamzap_map = {
-	.map = {
-		.scan    = streamzap,
-		.size    = ARRAY_SIZE(streamzap),
-		.ir_type = IR_TYPE_RC5_SZ,
-		.name    = RC_MAP_STREAMZAP,
-	}
-};
-
-static int __init init_rc_map_streamzap(void)
-{
-	return ir_register_map(&streamzap_map);
-}
-
-static void __exit exit_rc_map_streamzap(void)
-{
-	ir_unregister_map(&streamzap_map);
-}
-
-module_init(init_rc_map_streamzap)
-module_exit(exit_rc_map_streamzap)
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Jarod Wilson <jarod@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-tbs-nec.c linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-tbs-nec.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-tbs-nec.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-tbs-nec.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,73 +0,0 @@
-/* tbs-nec.h - Keytable for tbs_nec Remote Controller
- *
- * keymap imported from ir-keymaps.c
- *
- * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
-
-static struct ir_scancode tbs_nec[] = {
-	{ 0x04, KEY_POWER2},	/*power*/
-	{ 0x14, KEY_MUTE},	/*mute*/
-	{ 0x07, KEY_1},
-	{ 0x06, KEY_2},
-	{ 0x05, KEY_3},
-	{ 0x0b, KEY_4},
-	{ 0x0a, KEY_5},
-	{ 0x09, KEY_6},
-	{ 0x0f, KEY_7},
-	{ 0x0e, KEY_8},
-	{ 0x0d, KEY_9},
-	{ 0x12, KEY_0},
-	{ 0x16, KEY_CHANNELUP},	/*ch+*/
-	{ 0x11, KEY_CHANNELDOWN},/*ch-*/
-	{ 0x13, KEY_VOLUMEUP},	/*vol+*/
-	{ 0x0c, KEY_VOLUMEDOWN},/*vol-*/
-	{ 0x03, KEY_RECORD},	/*rec*/
-	{ 0x18, KEY_PAUSE},	/*pause*/
-	{ 0x19, KEY_OK},	/*ok*/
-	{ 0x1a, KEY_CAMERA},	/* snapshot */
-	{ 0x01, KEY_UP},
-	{ 0x10, KEY_LEFT},
-	{ 0x02, KEY_RIGHT},
-	{ 0x08, KEY_DOWN},
-	{ 0x15, KEY_FAVORITES},
-	{ 0x17, KEY_SUBTITLE},
-	{ 0x1d, KEY_ZOOM},
-	{ 0x1f, KEY_EXIT},
-	{ 0x1e, KEY_MENU},
-	{ 0x1c, KEY_EPG},
-	{ 0x00, KEY_PREVIOUS},
-	{ 0x1b, KEY_MODE},
-};
-
-static struct rc_keymap tbs_nec_map = {
-	.map = {
-		.scan    = tbs_nec,
-		.size    = ARRAY_SIZE(tbs_nec),
-		.ir_type = IR_TYPE_UNKNOWN,	/* Legacy IR type */
-		.name    = RC_MAP_TBS_NEC,
-	}
-};
-
-static int __init init_rc_map_tbs_nec(void)
-{
-	return ir_register_map(&tbs_nec_map);
-}
-
-static void __exit exit_rc_map_tbs_nec(void)
-{
-	ir_unregister_map(&tbs_nec_map);
-}
-
-module_init(init_rc_map_tbs_nec)
-module_exit(exit_rc_map_tbs_nec)
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-terratec-cinergy-xs.c linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-terratec-cinergy-xs.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-terratec-cinergy-xs.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-terratec-cinergy-xs.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,92 +0,0 @@
-/* terratec-cinergy-xs.h - Keytable for terratec_cinergy_xs Remote Controller
- *
- * keymap imported from ir-keymaps.c
- *
- * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
-
-/* Terratec Cinergy Hybrid T USB XS
-   Devin Heitmueller <dheitmueller@linuxtv.org>
- */
-
-static struct ir_scancode terratec_cinergy_xs[] = {
-	{ 0x41, KEY_HOME},
-	{ 0x01, KEY_POWER},
-	{ 0x42, KEY_MENU},
-	{ 0x02, KEY_1},
-	{ 0x03, KEY_2},
-	{ 0x04, KEY_3},
-	{ 0x43, KEY_SUBTITLE},
-	{ 0x05, KEY_4},
-	{ 0x06, KEY_5},
-	{ 0x07, KEY_6},
-	{ 0x44, KEY_TEXT},
-	{ 0x08, KEY_7},
-	{ 0x09, KEY_8},
-	{ 0x0a, KEY_9},
-	{ 0x45, KEY_DELETE},
-	{ 0x0b, KEY_TUNER},
-	{ 0x0c, KEY_0},
-	{ 0x0d, KEY_MODE},
-	{ 0x46, KEY_TV},
-	{ 0x47, KEY_DVD},
-	{ 0x49, KEY_VIDEO},
-	{ 0x4b, KEY_AUX},
-	{ 0x10, KEY_UP},
-	{ 0x11, KEY_LEFT},
-	{ 0x12, KEY_OK},
-	{ 0x13, KEY_RIGHT},
-	{ 0x14, KEY_DOWN},
-	{ 0x0f, KEY_EPG},
-	{ 0x16, KEY_INFO},
-	{ 0x4d, KEY_BACKSPACE},
-	{ 0x1c, KEY_VOLUMEUP},
-	{ 0x4c, KEY_PLAY},
-	{ 0x1b, KEY_CHANNELUP},
-	{ 0x1e, KEY_VOLUMEDOWN},
-	{ 0x1d, KEY_MUTE},
-	{ 0x1f, KEY_CHANNELDOWN},
-	{ 0x17, KEY_RED},
-	{ 0x18, KEY_GREEN},
-	{ 0x19, KEY_YELLOW},
-	{ 0x1a, KEY_BLUE},
-	{ 0x58, KEY_RECORD},
-	{ 0x48, KEY_STOP},
-	{ 0x40, KEY_PAUSE},
-	{ 0x54, KEY_LAST},
-	{ 0x4e, KEY_REWIND},
-	{ 0x4f, KEY_FASTFORWARD},
-	{ 0x5c, KEY_NEXT},
-};
-
-static struct rc_keymap terratec_cinergy_xs_map = {
-	.map = {
-		.scan    = terratec_cinergy_xs,
-		.size    = ARRAY_SIZE(terratec_cinergy_xs),
-		.ir_type = IR_TYPE_UNKNOWN,	/* Legacy IR type */
-		.name    = RC_MAP_TERRATEC_CINERGY_XS,
-	}
-};
-
-static int __init init_rc_map_terratec_cinergy_xs(void)
-{
-	return ir_register_map(&terratec_cinergy_xs_map);
-}
-
-static void __exit exit_rc_map_terratec_cinergy_xs(void)
-{
-	ir_unregister_map(&terratec_cinergy_xs_map);
-}
-
-module_init(init_rc_map_terratec_cinergy_xs)
-module_exit(exit_rc_map_terratec_cinergy_xs)
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-terratec-slim.c linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-terratec-slim.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-terratec-slim.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-terratec-slim.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,79 +0,0 @@
-/*
- * TerraTec remote controller keytable
- *
- * Copyright (C) 2010 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 <media/rc-map.h>
-
-/* TerraTec slim remote, 7 rows, 4 columns. */
-/* Uses NEC extended 0x02bd. */
-static struct ir_scancode terratec_slim[] = {
-	{ 0x02bd00, KEY_1 },
-	{ 0x02bd01, KEY_2 },
-	{ 0x02bd02, KEY_3 },
-	{ 0x02bd03, KEY_4 },
-	{ 0x02bd04, KEY_5 },
-	{ 0x02bd05, KEY_6 },
-	{ 0x02bd06, KEY_7 },
-	{ 0x02bd07, KEY_8 },
-	{ 0x02bd08, KEY_9 },
-	{ 0x02bd09, KEY_0 },
-	{ 0x02bd0a, KEY_MUTE },
-	{ 0x02bd0b, KEY_NEW },             /* symbol: PIP */
-	{ 0x02bd0e, KEY_VOLUMEDOWN },
-	{ 0x02bd0f, KEY_PLAYPAUSE },
-	{ 0x02bd10, KEY_RIGHT },
-	{ 0x02bd11, KEY_LEFT },
-	{ 0x02bd12, KEY_UP },
-	{ 0x02bd13, KEY_DOWN },
-	{ 0x02bd15, KEY_OK },
-	{ 0x02bd16, KEY_STOP },
-	{ 0x02bd17, KEY_CAMERA },          /* snapshot */
-	{ 0x02bd18, KEY_CHANNELUP },
-	{ 0x02bd19, KEY_RECORD },
-	{ 0x02bd1a, KEY_CHANNELDOWN },
-	{ 0x02bd1c, KEY_ESC },
-	{ 0x02bd1f, KEY_VOLUMEUP },
-	{ 0x02bd44, KEY_EPG },
-	{ 0x02bd45, KEY_POWER2 },          /* [red power button] */
-};
-
-static struct rc_keymap terratec_slim_map = {
-	.map = {
-		.scan    = terratec_slim,
-		.size    = ARRAY_SIZE(terratec_slim),
-		.ir_type = IR_TYPE_NEC,
-		.name    = RC_MAP_TERRATEC_SLIM,
-	}
-};
-
-static int __init init_rc_map_terratec_slim(void)
-{
-	return ir_register_map(&terratec_slim_map);
-}
-
-static void __exit exit_rc_map_terratec_slim(void)
-{
-	ir_unregister_map(&terratec_slim_map);
-}
-
-module_init(init_rc_map_terratec_slim)
-module_exit(exit_rc_map_terratec_slim)
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-tevii-nec.c linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-tevii-nec.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-tevii-nec.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-tevii-nec.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,88 +0,0 @@
-/* tevii-nec.h - Keytable for tevii_nec Remote Controller
- *
- * keymap imported from ir-keymaps.c
- *
- * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
-
-static struct ir_scancode tevii_nec[] = {
-	{ 0x0a, KEY_POWER2},
-	{ 0x0c, KEY_MUTE},
-	{ 0x11, KEY_1},
-	{ 0x12, KEY_2},
-	{ 0x13, KEY_3},
-	{ 0x14, KEY_4},
-	{ 0x15, KEY_5},
-	{ 0x16, KEY_6},
-	{ 0x17, KEY_7},
-	{ 0x18, KEY_8},
-	{ 0x19, KEY_9},
-	{ 0x10, KEY_0},
-	{ 0x1c, KEY_MENU},
-	{ 0x0f, KEY_VOLUMEDOWN},
-	{ 0x1a, KEY_LAST},
-	{ 0x0e, KEY_OPEN},
-	{ 0x04, KEY_RECORD},
-	{ 0x09, KEY_VOLUMEUP},
-	{ 0x08, KEY_CHANNELUP},
-	{ 0x07, KEY_PVR},
-	{ 0x0b, KEY_TIME},
-	{ 0x02, KEY_RIGHT},
-	{ 0x03, KEY_LEFT},
-	{ 0x00, KEY_UP},
-	{ 0x1f, KEY_OK},
-	{ 0x01, KEY_DOWN},
-	{ 0x05, KEY_TUNER},
-	{ 0x06, KEY_CHANNELDOWN},
-	{ 0x40, KEY_PLAYPAUSE},
-	{ 0x1e, KEY_REWIND},
-	{ 0x1b, KEY_FAVORITES},
-	{ 0x1d, KEY_BACK},
-	{ 0x4d, KEY_FASTFORWARD},
-	{ 0x44, KEY_EPG},
-	{ 0x4c, KEY_INFO},
-	{ 0x41, KEY_AB},
-	{ 0x43, KEY_AUDIO},
-	{ 0x45, KEY_SUBTITLE},
-	{ 0x4a, KEY_LIST},
-	{ 0x46, KEY_F1},
-	{ 0x47, KEY_F2},
-	{ 0x5e, KEY_F3},
-	{ 0x5c, KEY_F4},
-	{ 0x52, KEY_F5},
-	{ 0x5a, KEY_F6},
-	{ 0x56, KEY_MODE},
-	{ 0x58, KEY_SWITCHVIDEOMODE},
-};
-
-static struct rc_keymap tevii_nec_map = {
-	.map = {
-		.scan    = tevii_nec,
-		.size    = ARRAY_SIZE(tevii_nec),
-		.ir_type = IR_TYPE_UNKNOWN,	/* Legacy IR type */
-		.name    = RC_MAP_TEVII_NEC,
-	}
-};
-
-static int __init init_rc_map_tevii_nec(void)
-{
-	return ir_register_map(&tevii_nec_map);
-}
-
-static void __exit exit_rc_map_tevii_nec(void)
-{
-	ir_unregister_map(&tevii_nec_map);
-}
-
-module_init(init_rc_map_tevii_nec)
-module_exit(exit_rc_map_tevii_nec)
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-total-media-in-hand.c linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-total-media-in-hand.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-total-media-in-hand.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-total-media-in-hand.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,85 +0,0 @@
-/*
- * Total Media In Hand remote controller keytable
- *
- * Copyright (C) 2010 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 <media/rc-map.h>
-
-/* Uses NEC extended 0x02bd */
-static struct ir_scancode total_media_in_hand[] = {
-	{ 0x02bd00, KEY_1 },
-	{ 0x02bd01, KEY_2 },
-	{ 0x02bd02, KEY_3 },
-	{ 0x02bd03, KEY_4 },
-	{ 0x02bd04, KEY_5 },
-	{ 0x02bd05, KEY_6 },
-	{ 0x02bd06, KEY_7 },
-	{ 0x02bd07, KEY_8 },
-	{ 0x02bd08, KEY_9 },
-	{ 0x02bd09, KEY_0 },
-	{ 0x02bd0a, KEY_MUTE },
-	{ 0x02bd0b, KEY_CYCLEWINDOWS },    /* yellow, [min / max] */
-	{ 0x02bd0c, KEY_VIDEO },           /* TV / AV */
-	{ 0x02bd0e, KEY_VOLUMEDOWN },
-	{ 0x02bd0f, KEY_TIME },            /* TimeShift */
-	{ 0x02bd10, KEY_RIGHT },           /* right arrow */
-	{ 0x02bd11, KEY_LEFT },            /* left arrow */
-	{ 0x02bd12, KEY_UP },              /* up arrow */
-	{ 0x02bd13, KEY_DOWN },            /* down arrow */
-	{ 0x02bd14, KEY_POWER2 },          /* [red] */
-	{ 0x02bd15, KEY_OK },              /* OK */
-	{ 0x02bd16, KEY_STOP },
-	{ 0x02bd17, KEY_CAMERA },          /* Snapshot */
-	{ 0x02bd18, KEY_CHANNELUP },
-	{ 0x02bd19, KEY_RECORD },
-	{ 0x02bd1a, KEY_CHANNELDOWN },
-	{ 0x02bd1c, KEY_ESC },             /* Esc */
-	{ 0x02bd1e, KEY_PLAY },
-	{ 0x02bd1f, KEY_VOLUMEUP },
-	{ 0x02bd40, KEY_PAUSE },
-	{ 0x02bd41, KEY_FASTFORWARD },     /* FF >> */
-	{ 0x02bd42, KEY_REWIND },          /* FR << */
-	{ 0x02bd43, KEY_ZOOM },            /* [window + mouse pointer] */
-	{ 0x02bd44, KEY_SHUFFLE },         /* Shuffle */
-	{ 0x02bd45, KEY_INFO },            /* [red (I)] */
-};
-
-static struct rc_keymap total_media_in_hand_map = {
-	.map = {
-		.scan    = total_media_in_hand,
-		.size    = ARRAY_SIZE(total_media_in_hand),
-		.ir_type = IR_TYPE_NEC,
-		.name    = RC_MAP_TOTAL_MEDIA_IN_HAND,
-	}
-};
-
-static int __init init_rc_map_total_media_in_hand(void)
-{
-	return ir_register_map(&total_media_in_hand_map);
-}
-
-static void __exit exit_rc_map_total_media_in_hand(void)
-{
-	ir_unregister_map(&total_media_in_hand_map);
-}
-
-module_init(init_rc_map_total_media_in_hand)
-module_exit(exit_rc_map_total_media_in_hand)
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-trekstor.c linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-trekstor.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-trekstor.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-trekstor.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,80 +0,0 @@
-/*
- * TrekStor remote controller keytable
- *
- * Copyright (C) 2010 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 <media/rc-map.h>
-
-/* TrekStor DVB-T USB Stick remote controller. */
-/* Imported from af9015.h.
-   Initial keytable was from Marc Schneider <macke@macke.org> */
-static struct ir_scancode trekstor[] = {
-	{ 0x0084, KEY_0 },
-	{ 0x0085, KEY_MUTE },            /* Mute */
-	{ 0x0086, KEY_HOMEPAGE },        /* Home */
-	{ 0x0087, KEY_UP },              /* Up */
-	{ 0x0088, KEY_OK },              /* OK */
-	{ 0x0089, KEY_RIGHT },           /* Right */
-	{ 0x008a, KEY_FASTFORWARD },     /* Fast forward */
-	{ 0x008b, KEY_VOLUMEUP },        /* Volume + */
-	{ 0x008c, KEY_DOWN },            /* Down */
-	{ 0x008d, KEY_PLAY },            /* Play/Pause */
-	{ 0x008e, KEY_STOP },            /* Stop */
-	{ 0x008f, KEY_EPG },             /* Info/EPG */
-	{ 0x0090, KEY_7 },
-	{ 0x0091, KEY_4 },
-	{ 0x0092, KEY_1 },
-	{ 0x0093, KEY_CHANNELDOWN },     /* Channel - */
-	{ 0x0094, KEY_8 },
-	{ 0x0095, KEY_5 },
-	{ 0x0096, KEY_2 },
-	{ 0x0097, KEY_CHANNELUP },       /* Channel + */
-	{ 0x0098, KEY_9 },
-	{ 0x0099, KEY_6 },
-	{ 0x009a, KEY_3 },
-	{ 0x009b, KEY_VOLUMEDOWN },      /* Volume - */
-	{ 0x009c, KEY_TV },              /* TV */
-	{ 0x009d, KEY_RECORD },          /* Record */
-	{ 0x009e, KEY_REWIND },          /* Rewind */
-	{ 0x009f, KEY_LEFT },            /* Left */
-};
-
-static struct rc_keymap trekstor_map = {
-	.map = {
-		.scan    = trekstor,
-		.size    = ARRAY_SIZE(trekstor),
-		.ir_type = IR_TYPE_NEC,
-		.name    = RC_MAP_TREKSTOR,
-	}
-};
-
-static int __init init_rc_map_trekstor(void)
-{
-	return ir_register_map(&trekstor_map);
-}
-
-static void __exit exit_rc_map_trekstor(void)
-{
-	ir_unregister_map(&trekstor_map);
-}
-
-module_init(init_rc_map_trekstor)
-module_exit(exit_rc_map_trekstor)
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-tt-1500.c linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-tt-1500.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-tt-1500.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-tt-1500.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,82 +0,0 @@
-/* tt-1500.h - Keytable for tt_1500 Remote Controller
- *
- * keymap imported from ir-keymaps.c
- *
- * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
-
-/* for the Technotrend 1500 bundled remotes (grey and black): */
-
-static struct ir_scancode tt_1500[] = {
-	{ 0x01, KEY_POWER },
-	{ 0x02, KEY_SHUFFLE },		/* ? double-arrow key */
-	{ 0x03, KEY_1 },
-	{ 0x04, KEY_2 },
-	{ 0x05, KEY_3 },
-	{ 0x06, KEY_4 },
-	{ 0x07, KEY_5 },
-	{ 0x08, KEY_6 },
-	{ 0x09, KEY_7 },
-	{ 0x0a, KEY_8 },
-	{ 0x0b, KEY_9 },
-	{ 0x0c, KEY_0 },
-	{ 0x0d, KEY_UP },
-	{ 0x0e, KEY_LEFT },
-	{ 0x0f, KEY_OK },
-	{ 0x10, KEY_RIGHT },
-	{ 0x11, KEY_DOWN },
-	{ 0x12, KEY_INFO },
-	{ 0x13, KEY_EXIT },
-	{ 0x14, KEY_RED },
-	{ 0x15, KEY_GREEN },
-	{ 0x16, KEY_YELLOW },
-	{ 0x17, KEY_BLUE },
-	{ 0x18, KEY_MUTE },
-	{ 0x19, KEY_TEXT },
-	{ 0x1a, KEY_MODE },		/* ? TV/Radio */
-	{ 0x21, KEY_OPTION },
-	{ 0x22, KEY_EPG },
-	{ 0x23, KEY_CHANNELUP },
-	{ 0x24, KEY_CHANNELDOWN },
-	{ 0x25, KEY_VOLUMEUP },
-	{ 0x26, KEY_VOLUMEDOWN },
-	{ 0x27, KEY_SETUP },
-	{ 0x3a, KEY_RECORD },		/* these keys are only in the black remote */
-	{ 0x3b, KEY_PLAY },
-	{ 0x3c, KEY_STOP },
-	{ 0x3d, KEY_REWIND },
-	{ 0x3e, KEY_PAUSE },
-	{ 0x3f, KEY_FORWARD },
-};
-
-static struct rc_keymap tt_1500_map = {
-	.map = {
-		.scan    = tt_1500,
-		.size    = ARRAY_SIZE(tt_1500),
-		.ir_type = IR_TYPE_UNKNOWN,	/* Legacy IR type */
-		.name    = RC_MAP_TT_1500,
-	}
-};
-
-static int __init init_rc_map_tt_1500(void)
-{
-	return ir_register_map(&tt_1500_map);
-}
-
-static void __exit exit_rc_map_tt_1500(void)
-{
-	ir_unregister_map(&tt_1500_map);
-}
-
-module_init(init_rc_map_tt_1500)
-module_exit(exit_rc_map_tt_1500)
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-twinhan1027.c linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-twinhan1027.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-twinhan1027.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-twinhan1027.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,87 +0,0 @@
-#include <media/rc-map.h>
-
-static struct ir_scancode twinhan_vp1027[] = {
-	{ 0x16, KEY_POWER2 },
-	{ 0x17, KEY_FAVORITES },
-	{ 0x0f, KEY_TEXT },
-	{ 0x48, KEY_INFO},
-	{ 0x1c, KEY_EPG },
-	{ 0x04, KEY_LIST },
-
-	{ 0x03, KEY_1 },
-	{ 0x01, KEY_2 },
-	{ 0x06, KEY_3 },
-	{ 0x09, KEY_4 },
-	{ 0x1d, KEY_5 },
-	{ 0x1f, KEY_6 },
-	{ 0x0d, KEY_7 },
-	{ 0x19, KEY_8 },
-	{ 0x1b, KEY_9 },
-	{ 0x15, KEY_0 },
-
-	{ 0x0c, KEY_CANCEL },
-	{ 0x4a, KEY_CLEAR },
-	{ 0x13, KEY_BACKSPACE },
-	{ 0x00, KEY_TAB },
-
-	{ 0x4b, KEY_UP },
-	{ 0x51, KEY_DOWN },
-	{ 0x4e, KEY_LEFT },
-	{ 0x52, KEY_RIGHT },
-	{ 0x4f, KEY_ENTER },
-
-	{ 0x1e, KEY_VOLUMEUP },
-	{ 0x0a, KEY_VOLUMEDOWN },
-	{ 0x02, KEY_CHANNELDOWN },
-	{ 0x05, KEY_CHANNELUP },
-	{ 0x11, KEY_RECORD },
-
-	{ 0x14, KEY_PLAY },
-	{ 0x4c, KEY_PAUSE },
-	{ 0x1a, KEY_STOP },
-	{ 0x40, KEY_REWIND },
-	{ 0x12, KEY_FASTFORWARD },
-	{ 0x41, KEY_PREVIOUSSONG },
-	{ 0x42, KEY_NEXTSONG },
-	{ 0x54, KEY_SAVE },
-	{ 0x50, KEY_LANGUAGE },
-	{ 0x47, KEY_MEDIA },
-	{ 0x4d, KEY_SCREEN },
-	{ 0x43, KEY_SUBTITLE },
-	{ 0x10, KEY_MUTE },
-	{ 0x49, KEY_AUDIO },
-	{ 0x07, KEY_SLEEP },
-	{ 0x08, KEY_VIDEO },
-	{ 0x0e, KEY_AGAIN },
-	{ 0x45, KEY_EQUAL },
-	{ 0x46, KEY_MINUS },
-	{ 0x18, KEY_RED },
-	{ 0x53, KEY_GREEN },
-	{ 0x5e, KEY_YELLOW },
-	{ 0x5f, KEY_BLUE },
-};
-
-static struct rc_keymap twinhan_vp1027_map = {
-	.map = {
-		.scan    = twinhan_vp1027,
-		.size    = ARRAY_SIZE(twinhan_vp1027),
-		.ir_type = IR_TYPE_UNKNOWN,	/* Legacy IR type */
-		.name    = RC_MAP_TWINHAN_VP1027_DVBS,
-	}
-};
-
-static int __init init_rc_map_twinhan_vp1027(void)
-{
-	return ir_register_map(&twinhan_vp1027_map);
-}
-
-static void __exit exit_rc_map_twinhan_vp1027(void)
-{
-	ir_unregister_map(&twinhan_vp1027_map);
-}
-
-module_init(init_rc_map_twinhan_vp1027)
-module_exit(exit_rc_map_twinhan_vp1027)
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Sergey Ivanov <123kash@gmail.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-videomate-s350.c linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-videomate-s350.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-videomate-s350.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-videomate-s350.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,85 +0,0 @@
-/* videomate-s350.h - Keytable for videomate_s350 Remote Controller
- *
- * keymap imported from ir-keymaps.c
- *
- * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
-
-static struct ir_scancode videomate_s350[] = {
-	{ 0x00, KEY_TV},
-	{ 0x01, KEY_DVD},
-	{ 0x04, KEY_RECORD},
-	{ 0x05, KEY_VIDEO},	/* TV/Video */
-	{ 0x07, KEY_STOP},
-	{ 0x08, KEY_PLAYPAUSE},
-	{ 0x0a, KEY_REWIND},
-	{ 0x0f, KEY_FASTFORWARD},
-	{ 0x10, KEY_CHANNELUP},
-	{ 0x12, KEY_VOLUMEUP},
-	{ 0x13, KEY_CHANNELDOWN},
-	{ 0x14, KEY_MUTE},
-	{ 0x15, KEY_VOLUMEDOWN},
-	{ 0x16, KEY_1},
-	{ 0x17, KEY_2},
-	{ 0x18, KEY_3},
-	{ 0x19, KEY_4},
-	{ 0x1a, KEY_5},
-	{ 0x1b, KEY_6},
-	{ 0x1c, KEY_7},
-	{ 0x1d, KEY_8},
-	{ 0x1e, KEY_9},
-	{ 0x1f, KEY_0},
-	{ 0x21, KEY_SLEEP},
-	{ 0x24, KEY_ZOOM},
-	{ 0x25, KEY_LAST},	/* Recall */
-	{ 0x26, KEY_SUBTITLE},	/* CC */
-	{ 0x27, KEY_LANGUAGE},	/* MTS */
-	{ 0x29, KEY_CHANNEL},	/* SURF */
-	{ 0x2b, KEY_A},
-	{ 0x2c, KEY_B},
-	{ 0x2f, KEY_CAMERA},	/* Snapshot */
-	{ 0x23, KEY_RADIO},
-	{ 0x02, KEY_PREVIOUSSONG},
-	{ 0x06, KEY_NEXTSONG},
-	{ 0x03, KEY_EPG},
-	{ 0x09, KEY_SETUP},
-	{ 0x22, KEY_BACKSPACE},
-	{ 0x0c, KEY_UP},
-	{ 0x0e, KEY_DOWN},
-	{ 0x0b, KEY_LEFT},
-	{ 0x0d, KEY_RIGHT},
-	{ 0x11, KEY_ENTER},
-	{ 0x20, KEY_TEXT},
-};
-
-static struct rc_keymap videomate_s350_map = {
-	.map = {
-		.scan    = videomate_s350,
-		.size    = ARRAY_SIZE(videomate_s350),
-		.ir_type = IR_TYPE_UNKNOWN,	/* Legacy IR type */
-		.name    = RC_MAP_VIDEOMATE_S350,
-	}
-};
-
-static int __init init_rc_map_videomate_s350(void)
-{
-	return ir_register_map(&videomate_s350_map);
-}
-
-static void __exit exit_rc_map_videomate_s350(void)
-{
-	ir_unregister_map(&videomate_s350_map);
-}
-
-module_init(init_rc_map_videomate_s350)
-module_exit(exit_rc_map_videomate_s350)
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-videomate-tv-pvr.c linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-videomate-tv-pvr.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-videomate-tv-pvr.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-videomate-tv-pvr.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,87 +0,0 @@
-/* videomate-tv-pvr.h - Keytable for videomate_tv_pvr Remote Controller
- *
- * keymap imported from ir-keymaps.c
- *
- * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
-
-static struct ir_scancode videomate_tv_pvr[] = {
-	{ 0x14, KEY_MUTE },
-	{ 0x24, KEY_ZOOM },
-
-	{ 0x01, KEY_DVD },
-	{ 0x23, KEY_RADIO },
-	{ 0x00, KEY_TV },
-
-	{ 0x0a, KEY_REWIND },
-	{ 0x08, KEY_PLAYPAUSE },
-	{ 0x0f, KEY_FORWARD },
-
-	{ 0x02, KEY_PREVIOUS },
-	{ 0x07, KEY_STOP },
-	{ 0x06, KEY_NEXT },
-
-	{ 0x0c, KEY_UP },
-	{ 0x0e, KEY_DOWN },
-	{ 0x0b, KEY_LEFT },
-	{ 0x0d, KEY_RIGHT },
-	{ 0x11, KEY_OK },
-
-	{ 0x03, KEY_MENU },
-	{ 0x09, KEY_SETUP },
-	{ 0x05, KEY_VIDEO },
-	{ 0x22, KEY_CHANNEL },
-
-	{ 0x12, KEY_VOLUMEUP },
-	{ 0x15, KEY_VOLUMEDOWN },
-	{ 0x10, KEY_CHANNELUP },
-	{ 0x13, KEY_CHANNELDOWN },
-
-	{ 0x04, KEY_RECORD },
-
-	{ 0x16, KEY_1 },
-	{ 0x17, KEY_2 },
-	{ 0x18, KEY_3 },
-	{ 0x19, KEY_4 },
-	{ 0x1a, KEY_5 },
-	{ 0x1b, KEY_6 },
-	{ 0x1c, KEY_7 },
-	{ 0x1d, KEY_8 },
-	{ 0x1e, KEY_9 },
-	{ 0x1f, KEY_0 },
-
-	{ 0x20, KEY_LANGUAGE },
-	{ 0x21, KEY_SLEEP },
-};
-
-static struct rc_keymap videomate_tv_pvr_map = {
-	.map = {
-		.scan    = videomate_tv_pvr,
-		.size    = ARRAY_SIZE(videomate_tv_pvr),
-		.ir_type = IR_TYPE_UNKNOWN,	/* Legacy IR type */
-		.name    = RC_MAP_VIDEOMATE_TV_PVR,
-	}
-};
-
-static int __init init_rc_map_videomate_tv_pvr(void)
-{
-	return ir_register_map(&videomate_tv_pvr_map);
-}
-
-static void __exit exit_rc_map_videomate_tv_pvr(void)
-{
-	ir_unregister_map(&videomate_tv_pvr_map);
-}
-
-module_init(init_rc_map_videomate_tv_pvr)
-module_exit(exit_rc_map_videomate_tv_pvr)
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-winfast.c linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-winfast.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-winfast.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-winfast.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,102 +0,0 @@
-/* winfast.h - Keytable for winfast Remote Controller
- *
- * keymap imported from ir-keymaps.c
- *
- * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
-
-/* Table for Leadtek Winfast Remote Controls - used by both bttv and cx88 */
-
-static struct ir_scancode winfast[] = {
-	/* Keys 0 to 9 */
-	{ 0x12, KEY_0 },
-	{ 0x05, KEY_1 },
-	{ 0x06, KEY_2 },
-	{ 0x07, KEY_3 },
-	{ 0x09, KEY_4 },
-	{ 0x0a, KEY_5 },
-	{ 0x0b, KEY_6 },
-	{ 0x0d, KEY_7 },
-	{ 0x0e, KEY_8 },
-	{ 0x0f, KEY_9 },
-
-	{ 0x00, KEY_POWER },
-	{ 0x1b, KEY_AUDIO },		/* Audio Source */
-	{ 0x02, KEY_TUNER },		/* TV/FM, not on Y0400052 */
-	{ 0x1e, KEY_VIDEO },		/* Video Source */
-	{ 0x16, KEY_INFO },		/* Display information */
-	{ 0x04, KEY_VOLUMEUP },
-	{ 0x08, KEY_VOLUMEDOWN },
-	{ 0x0c, KEY_CHANNELUP },
-	{ 0x10, KEY_CHANNELDOWN },
-	{ 0x03, KEY_ZOOM },		/* fullscreen */
-	{ 0x1f, KEY_TEXT },		/* closed caption/teletext */
-	{ 0x20, KEY_SLEEP },
-	{ 0x29, KEY_CLEAR },		/* boss key */
-	{ 0x14, KEY_MUTE },
-	{ 0x2b, KEY_RED },
-	{ 0x2c, KEY_GREEN },
-	{ 0x2d, KEY_YELLOW },
-	{ 0x2e, KEY_BLUE },
-	{ 0x18, KEY_KPPLUS },		/* fine tune + , not on Y040052 */
-	{ 0x19, KEY_KPMINUS },		/* fine tune - , not on Y040052 */
-	{ 0x2a, KEY_MEDIA },		/* PIP (Picture in picture */
-	{ 0x21, KEY_DOT },
-	{ 0x13, KEY_ENTER },
-	{ 0x11, KEY_LAST },		/* Recall (last channel */
-	{ 0x22, KEY_PREVIOUS },
-	{ 0x23, KEY_PLAYPAUSE },
-	{ 0x24, KEY_NEXT },
-	{ 0x25, KEY_TIME },		/* Time Shifting */
-	{ 0x26, KEY_STOP },
-	{ 0x27, KEY_RECORD },
-	{ 0x28, KEY_SAVE },		/* Screenshot */
-	{ 0x2f, KEY_MENU },
-	{ 0x30, KEY_CANCEL },
-	{ 0x31, KEY_CHANNEL },		/* Channel Surf */
-	{ 0x32, KEY_SUBTITLE },
-	{ 0x33, KEY_LANGUAGE },
-	{ 0x34, KEY_REWIND },
-	{ 0x35, KEY_FASTFORWARD },
-	{ 0x36, KEY_TV },
-	{ 0x37, KEY_RADIO },		/* FM */
-	{ 0x38, KEY_DVD },
-
-	{ 0x1a, KEY_MODE},		/* change to MCE mode on Y04G0051 */
-	{ 0x3e, KEY_F21 },		/* MCE +VOL, on Y04G0033 */
-	{ 0x3a, KEY_F22 },		/* MCE -VOL, on Y04G0033 */
-	{ 0x3b, KEY_F23 },		/* MCE +CH,  on Y04G0033 */
-	{ 0x3f, KEY_F24 }		/* MCE -CH,  on Y04G0033 */
-};
-
-static struct rc_keymap winfast_map = {
-	.map = {
-		.scan    = winfast,
-		.size    = ARRAY_SIZE(winfast),
-		.ir_type = IR_TYPE_UNKNOWN,	/* Legacy IR type */
-		.name    = RC_MAP_WINFAST,
-	}
-};
-
-static int __init init_rc_map_winfast(void)
-{
-	return ir_register_map(&winfast_map);
-}
-
-static void __exit exit_rc_map_winfast(void)
-{
-	ir_unregister_map(&winfast_map);
-}
-
-module_init(init_rc_map_winfast)
-module_exit(exit_rc_map_winfast)
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-winfast-usbii-deluxe.c linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-winfast-usbii-deluxe.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/keymaps/rc-winfast-usbii-deluxe.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/keymaps/rc-winfast-usbii-deluxe.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,82 +0,0 @@
-/* winfast-usbii-deluxe.h - Keytable for winfast_usbii_deluxe Remote Controller
- *
- * keymap imported from ir-keymaps.c
- *
- * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
-
-/* Leadtek Winfast TV USB II Deluxe remote
-   Magnus Alm <magnus.alm@gmail.com>
- */
-
-static struct ir_scancode winfast_usbii_deluxe[] = {
-	{ 0x62, KEY_0},
-	{ 0x75, KEY_1},
-	{ 0x76, KEY_2},
-	{ 0x77, KEY_3},
-	{ 0x79, KEY_4},
-	{ 0x7a, KEY_5},
-	{ 0x7b, KEY_6},
-	{ 0x7d, KEY_7},
-	{ 0x7e, KEY_8},
-	{ 0x7f, KEY_9},
-
-	{ 0x38, KEY_CAMERA},		/* SNAPSHOT */
-	{ 0x37, KEY_RECORD},		/* RECORD */
-	{ 0x35, KEY_TIME},		/* TIMESHIFT */
-
-	{ 0x74, KEY_VOLUMEUP},		/* VOLUMEUP */
-	{ 0x78, KEY_VOLUMEDOWN},	/* VOLUMEDOWN */
-	{ 0x64, KEY_MUTE},		/* MUTE */
-
-	{ 0x21, KEY_CHANNEL},		/* SURF */
-	{ 0x7c, KEY_CHANNELUP},		/* CHANNELUP */
-	{ 0x60, KEY_CHANNELDOWN},	/* CHANNELDOWN */
-	{ 0x61, KEY_LAST},		/* LAST CHANNEL (RECALL) */
-
-	{ 0x72, KEY_VIDEO}, 		/* INPUT MODES (TV/FM) */
-
-	{ 0x70, KEY_POWER2},		/* TV ON/OFF */
-
-	{ 0x39, KEY_CYCLEWINDOWS},	/* MINIMIZE (BOSS) */
-	{ 0x3a, KEY_NEW},		/* PIP */
-	{ 0x73, KEY_ZOOM},		/* FULLSECREEN */
-
-	{ 0x66, KEY_INFO},		/* OSD (DISPLAY) */
-
-	{ 0x31, KEY_DOT},		/* '.' */
-	{ 0x63, KEY_ENTER},		/* ENTER */
-
-};
-
-static struct rc_keymap winfast_usbii_deluxe_map = {
-	.map = {
-		.scan    = winfast_usbii_deluxe,
-		.size    = ARRAY_SIZE(winfast_usbii_deluxe),
-		.ir_type = IR_TYPE_UNKNOWN,	/* Legacy IR type */
-		.name    = RC_MAP_WINFAST_USBII_DELUXE,
-	}
-};
-
-static int __init init_rc_map_winfast_usbii_deluxe(void)
-{
-	return ir_register_map(&winfast_usbii_deluxe_map);
-}
-
-static void __exit exit_rc_map_winfast_usbii_deluxe(void)
-{
-	ir_unregister_map(&winfast_usbii_deluxe_map);
-}
-
-module_init(init_rc_map_winfast_usbii_deluxe)
-module_exit(exit_rc_map_winfast_usbii_deluxe)
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/lirc_dev.c linux-libre-2.6.38-gnu1/drivers/media/IR/lirc_dev.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/lirc_dev.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/lirc_dev.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,814 +0,0 @@
-/*
- * LIRC base driver
- *
- * by Artur Lipowski <alipowski@interia.pl>
- *
- *  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/kernel.h>
-#include <linux/sched.h>
-#include <linux/errno.h>
-#include <linux/ioctl.h>
-#include <linux/fs.h>
-#include <linux/poll.h>
-#include <linux/completion.h>
-#include <linux/mutex.h>
-#include <linux/wait.h>
-#include <linux/unistd.h>
-#include <linux/kthread.h>
-#include <linux/bitops.h>
-#include <linux/device.h>
-#include <linux/cdev.h>
-
-#include <media/lirc.h>
-#include <media/lirc_dev.h>
-
-static int debug;
-
-#define IRCTL_DEV_NAME	"BaseRemoteCtl"
-#define NOPLUG		-1
-#define LOGHEAD		"lirc_dev (%s[%d]): "
-
-static dev_t lirc_base_dev;
-
-struct irctl {
-	struct lirc_driver d;
-	int attached;
-	int open;
-
-	struct mutex irctl_lock;
-	struct lirc_buffer *buf;
-	unsigned int chunk_size;
-
-	struct task_struct *task;
-	long jiffies_to_wait;
-};
-
-static DEFINE_MUTEX(lirc_dev_lock);
-
-static struct irctl *irctls[MAX_IRCTL_DEVICES];
-static struct cdev cdevs[MAX_IRCTL_DEVICES];
-
-/* Only used for sysfs but defined to void otherwise */
-static struct class *lirc_class;
-
-/*  helper function
- *  initializes the irctl structure
- */
-static void lirc_irctl_init(struct irctl *ir)
-{
-	mutex_init(&ir->irctl_lock);
-	ir->d.minor = NOPLUG;
-}
-
-static void lirc_irctl_cleanup(struct irctl *ir)
-{
-	dev_dbg(ir->d.dev, LOGHEAD "cleaning up\n", ir->d.name, ir->d.minor);
-
-	device_destroy(lirc_class, MKDEV(MAJOR(lirc_base_dev), ir->d.minor));
-
-	if (ir->buf != ir->d.rbuf) {
-		lirc_buffer_free(ir->buf);
-		kfree(ir->buf);
-	}
-	ir->buf = NULL;
-}
-
-/*  helper function
- *  reads key codes from driver and puts them into buffer
- *  returns 0 on success
- */
-static int lirc_add_to_buf(struct irctl *ir)
-{
-	if (ir->d.add_to_buf) {
-		int res = -ENODATA;
-		int got_data = 0;
-
-		/*
-		 * service the device as long as it is returning
-		 * data and we have space
-		 */
-get_data:
-		res = ir->d.add_to_buf(ir->d.data, ir->buf);
-		if (res == 0) {
-			got_data++;
-			goto get_data;
-		}
-
-		if (res == -ENODEV)
-			kthread_stop(ir->task);
-
-		return got_data ? 0 : res;
-	}
-
-	return 0;
-}
-
-/* main function of the polling thread
- */
-static int lirc_thread(void *irctl)
-{
-	struct irctl *ir = irctl;
-
-	dev_dbg(ir->d.dev, LOGHEAD "poll thread started\n",
-		ir->d.name, ir->d.minor);
-
-	do {
-		if (ir->open) {
-			if (ir->jiffies_to_wait) {
-				set_current_state(TASK_INTERRUPTIBLE);
-				schedule_timeout(ir->jiffies_to_wait);
-			}
-			if (kthread_should_stop())
-				break;
-			if (!lirc_add_to_buf(ir))
-				wake_up_interruptible(&ir->buf->wait_poll);
-		} else {
-			set_current_state(TASK_INTERRUPTIBLE);
-			schedule();
-		}
-	} while (!kthread_should_stop());
-
-	dev_dbg(ir->d.dev, LOGHEAD "poll thread ended\n",
-		ir->d.name, ir->d.minor);
-
-	return 0;
-}
-
-
-static struct file_operations lirc_dev_fops = {
-	.owner		= THIS_MODULE,
-	.read		= lirc_dev_fop_read,
-	.write		= lirc_dev_fop_write,
-	.poll		= lirc_dev_fop_poll,
-	.unlocked_ioctl	= lirc_dev_fop_ioctl,
-#ifdef CONFIG_COMPAT
-	.compat_ioctl	= lirc_dev_fop_ioctl,
-#endif
-	.open		= lirc_dev_fop_open,
-	.release	= lirc_dev_fop_close,
-	.llseek		= noop_llseek,
-};
-
-static int lirc_cdev_add(struct irctl *ir)
-{
-	int retval;
-	struct lirc_driver *d = &ir->d;
-	struct cdev *cdev = &cdevs[d->minor];
-
-	if (d->fops) {
-		cdev_init(cdev, d->fops);
-		cdev->owner = d->owner;
-	} else {
-		cdev_init(cdev, &lirc_dev_fops);
-		cdev->owner = THIS_MODULE;
-	}
-	kobject_set_name(&cdev->kobj, "lirc%d", d->minor);
-
-	retval = cdev_add(cdev, MKDEV(MAJOR(lirc_base_dev), d->minor), 1);
-	if (retval)
-		kobject_put(&cdev->kobj);
-
-	return retval;
-}
-
-int lirc_register_driver(struct lirc_driver *d)
-{
-	struct irctl *ir;
-	int minor;
-	int bytes_in_key;
-	unsigned int chunk_size;
-	unsigned int buffer_size;
-	int err;
-
-	if (!d) {
-		printk(KERN_ERR "lirc_dev: lirc_register_driver: "
-		       "driver pointer must be not NULL!\n");
-		err = -EBADRQC;
-		goto out;
-	}
-
-	if (!d->dev) {
-		printk(KERN_ERR "%s: dev pointer not filled in!\n", __func__);
-		err = -EINVAL;
-		goto out;
-	}
-
-	if (MAX_IRCTL_DEVICES <= d->minor) {
-		dev_err(d->dev, "lirc_dev: lirc_register_driver: "
-			"\"minor\" must be between 0 and %d (%d)!\n",
-			MAX_IRCTL_DEVICES-1, d->minor);
-		err = -EBADRQC;
-		goto out;
-	}
-
-	if (1 > d->code_length || (BUFLEN * 8) < d->code_length) {
-		dev_err(d->dev, "lirc_dev: lirc_register_driver: "
-			"code length in bits for minor (%d) "
-			"must be less than %d!\n",
-			d->minor, BUFLEN * 8);
-		err = -EBADRQC;
-		goto out;
-	}
-
-	dev_dbg(d->dev, "lirc_dev: lirc_register_driver: sample_rate: %d\n",
-		d->sample_rate);
-	if (d->sample_rate) {
-		if (2 > d->sample_rate || HZ < d->sample_rate) {
-			dev_err(d->dev, "lirc_dev: lirc_register_driver: "
-				"sample_rate must be between 2 and %d!\n", HZ);
-			err = -EBADRQC;
-			goto out;
-		}
-		if (!d->add_to_buf) {
-			dev_err(d->dev, "lirc_dev: lirc_register_driver: "
-				"add_to_buf cannot be NULL when "
-				"sample_rate is set\n");
-			err = -EBADRQC;
-			goto out;
-		}
-	} else if (!(d->fops && d->fops->read) && !d->rbuf) {
-		dev_err(d->dev, "lirc_dev: lirc_register_driver: "
-			"fops->read and rbuf cannot all be NULL!\n");
-		err = -EBADRQC;
-		goto out;
-	} else if (!d->rbuf) {
-		if (!(d->fops && d->fops->read && d->fops->poll &&
-		      d->fops->unlocked_ioctl)) {
-			dev_err(d->dev, "lirc_dev: lirc_register_driver: "
-				"neither read, poll nor unlocked_ioctl can be NULL!\n");
-			err = -EBADRQC;
-			goto out;
-		}
-	}
-
-	mutex_lock(&lirc_dev_lock);
-
-	minor = d->minor;
-
-	if (minor < 0) {
-		/* find first free slot for driver */
-		for (minor = 0; minor < MAX_IRCTL_DEVICES; minor++)
-			if (!irctls[minor])
-				break;
-		if (MAX_IRCTL_DEVICES == minor) {
-			dev_err(d->dev, "lirc_dev: lirc_register_driver: "
-				"no free slots for drivers!\n");
-			err = -ENOMEM;
-			goto out_lock;
-		}
-	} else if (irctls[minor]) {
-		dev_err(d->dev, "lirc_dev: lirc_register_driver: "
-			"minor (%d) just registered!\n", minor);
-		err = -EBUSY;
-		goto out_lock;
-	}
-
-	ir = kzalloc(sizeof(struct irctl), GFP_KERNEL);
-	if (!ir) {
-		err = -ENOMEM;
-		goto out_lock;
-	}
-	lirc_irctl_init(ir);
-	irctls[minor] = ir;
-	d->minor = minor;
-
-	if (d->sample_rate) {
-		ir->jiffies_to_wait = HZ / d->sample_rate;
-	} else {
-		/* it means - wait for external event in task queue */
-		ir->jiffies_to_wait = 0;
-	}
-
-	/* some safety check 8-) */
-	d->name[sizeof(d->name)-1] = '\0';
-
-	bytes_in_key = BITS_TO_LONGS(d->code_length) +
-			(d->code_length % 8 ? 1 : 0);
-	buffer_size = d->buffer_size ? d->buffer_size : BUFLEN / bytes_in_key;
-	chunk_size  = d->chunk_size  ? d->chunk_size  : bytes_in_key;
-
-	if (d->rbuf) {
-		ir->buf = d->rbuf;
-	} else {
-		ir->buf = kmalloc(sizeof(struct lirc_buffer), GFP_KERNEL);
-		if (!ir->buf) {
-			err = -ENOMEM;
-			goto out_lock;
-		}
-		err = lirc_buffer_init(ir->buf, chunk_size, buffer_size);
-		if (err) {
-			kfree(ir->buf);
-			goto out_lock;
-		}
-	}
-	ir->chunk_size = ir->buf->chunk_size;
-
-	if (d->features == 0)
-		d->features = LIRC_CAN_REC_LIRCCODE;
-
-	ir->d = *d;
-
-	device_create(lirc_class, ir->d.dev,
-		      MKDEV(MAJOR(lirc_base_dev), ir->d.minor), NULL,
-		      "lirc%u", ir->d.minor);
-
-	if (d->sample_rate) {
-		/* try to fire up polling thread */
-		ir->task = kthread_run(lirc_thread, (void *)ir, "lirc_dev");
-		if (IS_ERR(ir->task)) {
-			dev_err(d->dev, "lirc_dev: lirc_register_driver: "
-				"cannot run poll thread for minor = %d\n",
-				d->minor);
-			err = -ECHILD;
-			goto out_sysfs;
-		}
-	}
-
-	err = lirc_cdev_add(ir);
-	if (err)
-		goto out_sysfs;
-
-	ir->attached = 1;
-	mutex_unlock(&lirc_dev_lock);
-
-	dev_info(ir->d.dev, "lirc_dev: driver %s registered at minor = %d\n",
-		 ir->d.name, ir->d.minor);
-	return minor;
-
-out_sysfs:
-	device_destroy(lirc_class, MKDEV(MAJOR(lirc_base_dev), ir->d.minor));
-out_lock:
-	mutex_unlock(&lirc_dev_lock);
-out:
-	return err;
-}
-EXPORT_SYMBOL(lirc_register_driver);
-
-int lirc_unregister_driver(int minor)
-{
-	struct irctl *ir;
-	struct cdev *cdev;
-
-	if (minor < 0 || minor >= MAX_IRCTL_DEVICES) {
-		printk(KERN_ERR "lirc_dev: %s: minor (%d) must be between "
-		       "0 and %d!\n", __func__, minor, MAX_IRCTL_DEVICES-1);
-		return -EBADRQC;
-	}
-
-	ir = irctls[minor];
-	if (!ir) {
-		printk(KERN_ERR "lirc_dev: %s: failed to get irctl struct "
-		       "for minor %d!\n", __func__, minor);
-		return -ENOENT;
-	}
-
-	cdev = &cdevs[minor];
-
-	mutex_lock(&lirc_dev_lock);
-
-	if (ir->d.minor != minor) {
-		printk(KERN_ERR "lirc_dev: %s: minor (%d) device not "
-		       "registered!\n", __func__, minor);
-		mutex_unlock(&lirc_dev_lock);
-		return -ENOENT;
-	}
-
-	/* end up polling thread */
-	if (ir->task)
-		kthread_stop(ir->task);
-
-	dev_dbg(ir->d.dev, "lirc_dev: driver %s unregistered from minor = %d\n",
-		ir->d.name, ir->d.minor);
-
-	ir->attached = 0;
-	if (ir->open) {
-		dev_dbg(ir->d.dev, LOGHEAD "releasing opened driver\n",
-			ir->d.name, ir->d.minor);
-		wake_up_interruptible(&ir->buf->wait_poll);
-		mutex_lock(&ir->irctl_lock);
-		ir->d.set_use_dec(ir->d.data);
-		module_put(cdev->owner);
-		mutex_unlock(&ir->irctl_lock);
-	} else {
-		lirc_irctl_cleanup(ir);
-		cdev_del(cdev);
-		kfree(ir);
-		irctls[minor] = NULL;
-	}
-
-	mutex_unlock(&lirc_dev_lock);
-
-	return 0;
-}
-EXPORT_SYMBOL(lirc_unregister_driver);
-
-int lirc_dev_fop_open(struct inode *inode, struct file *file)
-{
-	struct irctl *ir;
-	struct cdev *cdev;
-	int retval = 0;
-
-	if (iminor(inode) >= MAX_IRCTL_DEVICES) {
-		printk(KERN_WARNING "lirc_dev [%d]: open result = -ENODEV\n",
-		       iminor(inode));
-		return -ENODEV;
-	}
-
-	if (mutex_lock_interruptible(&lirc_dev_lock))
-		return -ERESTARTSYS;
-
-	ir = irctls[iminor(inode)];
-	if (!ir) {
-		retval = -ENODEV;
-		goto error;
-	}
-
-	dev_dbg(ir->d.dev, LOGHEAD "open called\n", ir->d.name, ir->d.minor);
-
-	if (ir->d.minor == NOPLUG) {
-		retval = -ENODEV;
-		goto error;
-	}
-
-	if (ir->open) {
-		retval = -EBUSY;
-		goto error;
-	}
-
-	cdev = &cdevs[iminor(inode)];
-	if (try_module_get(cdev->owner)) {
-		ir->open++;
-		retval = ir->d.set_use_inc(ir->d.data);
-
-		if (retval) {
-			module_put(cdev->owner);
-			ir->open--;
-		} else {
-			lirc_buffer_clear(ir->buf);
-		}
-		if (ir->task)
-			wake_up_process(ir->task);
-	}
-
-error:
-	if (ir)
-		dev_dbg(ir->d.dev, LOGHEAD "open result = %d\n",
-			ir->d.name, ir->d.minor, retval);
-
-	mutex_unlock(&lirc_dev_lock);
-
-	nonseekable_open(inode, file);
-
-	return retval;
-}
-EXPORT_SYMBOL(lirc_dev_fop_open);
-
-int lirc_dev_fop_close(struct inode *inode, struct file *file)
-{
-	struct irctl *ir = irctls[iminor(inode)];
-	struct cdev *cdev = &cdevs[iminor(inode)];
-
-	if (!ir) {
-		printk(KERN_ERR "%s: called with invalid irctl\n", __func__);
-		return -EINVAL;
-	}
-
-	dev_dbg(ir->d.dev, LOGHEAD "close called\n", ir->d.name, ir->d.minor);
-
-	WARN_ON(mutex_lock_killable(&lirc_dev_lock));
-
-	ir->open--;
-	if (ir->attached) {
-		ir->d.set_use_dec(ir->d.data);
-		module_put(cdev->owner);
-	} else {
-		lirc_irctl_cleanup(ir);
-		cdev_del(cdev);
-		irctls[ir->d.minor] = NULL;
-		kfree(ir);
-	}
-
-	mutex_unlock(&lirc_dev_lock);
-
-	return 0;
-}
-EXPORT_SYMBOL(lirc_dev_fop_close);
-
-unsigned int lirc_dev_fop_poll(struct file *file, poll_table *wait)
-{
-	struct irctl *ir = irctls[iminor(file->f_dentry->d_inode)];
-	unsigned int ret;
-
-	if (!ir) {
-		printk(KERN_ERR "%s: called with invalid irctl\n", __func__);
-		return POLLERR;
-	}
-
-	dev_dbg(ir->d.dev, LOGHEAD "poll called\n", ir->d.name, ir->d.minor);
-
-	if (!ir->attached)
-		return POLLERR;
-
-	poll_wait(file, &ir->buf->wait_poll, wait);
-
-	if (ir->buf)
-		if (lirc_buffer_empty(ir->buf))
-			ret = 0;
-		else
-			ret = POLLIN | POLLRDNORM;
-	else
-		ret = POLLERR;
-
-	dev_dbg(ir->d.dev, LOGHEAD "poll result = %d\n",
-		ir->d.name, ir->d.minor, ret);
-
-	return ret;
-}
-EXPORT_SYMBOL(lirc_dev_fop_poll);
-
-long lirc_dev_fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
-{
-	__u32 mode;
-	int result = 0;
-	struct irctl *ir = irctls[iminor(file->f_dentry->d_inode)];
-
-	if (!ir) {
-		printk(KERN_ERR "lirc_dev: %s: no irctl found!\n", __func__);
-		return -ENODEV;
-	}
-
-	dev_dbg(ir->d.dev, LOGHEAD "ioctl called (0x%x)\n",
-		ir->d.name, ir->d.minor, cmd);
-
-	if (ir->d.minor == NOPLUG || !ir->attached) {
-		dev_dbg(ir->d.dev, LOGHEAD "ioctl result = -ENODEV\n",
-			ir->d.name, ir->d.minor);
-		return -ENODEV;
-	}
-
-	mutex_lock(&ir->irctl_lock);
-
-	switch (cmd) {
-	case LIRC_GET_FEATURES:
-		result = put_user(ir->d.features, (__u32 *)arg);
-		break;
-	case LIRC_GET_REC_MODE:
-		if (!(ir->d.features & LIRC_CAN_REC_MASK)) {
-			result = -ENOSYS;
-			break;
-		}
-
-		result = put_user(LIRC_REC2MODE
-				  (ir->d.features & LIRC_CAN_REC_MASK),
-				  (__u32 *)arg);
-		break;
-	case LIRC_SET_REC_MODE:
-		if (!(ir->d.features & LIRC_CAN_REC_MASK)) {
-			result = -ENOSYS;
-			break;
-		}
-
-		result = get_user(mode, (__u32 *)arg);
-		if (!result && !(LIRC_MODE2REC(mode) & ir->d.features))
-			result = -EINVAL;
-		/*
-		 * FIXME: We should actually set the mode somehow but
-		 * for now, lirc_serial doesn't support mode changing either
-		 */
-		break;
-	case LIRC_GET_LENGTH:
-		result = put_user(ir->d.code_length, (__u32 *)arg);
-		break;
-	case LIRC_GET_MIN_TIMEOUT:
-		if (!(ir->d.features & LIRC_CAN_SET_REC_TIMEOUT) ||
-		    ir->d.min_timeout == 0) {
-			result = -ENOSYS;
-			break;
-		}
-
-		result = put_user(ir->d.min_timeout, (__u32 *)arg);
-		break;
-	case LIRC_GET_MAX_TIMEOUT:
-		if (!(ir->d.features & LIRC_CAN_SET_REC_TIMEOUT) ||
-		    ir->d.max_timeout == 0) {
-			result = -ENOSYS;
-			break;
-		}
-
-		result = put_user(ir->d.max_timeout, (__u32 *)arg);
-		break;
-	default:
-		result = -EINVAL;
-	}
-
-	dev_dbg(ir->d.dev, LOGHEAD "ioctl result = %d\n",
-		ir->d.name, ir->d.minor, result);
-
-	mutex_unlock(&ir->irctl_lock);
-
-	return result;
-}
-EXPORT_SYMBOL(lirc_dev_fop_ioctl);
-
-ssize_t lirc_dev_fop_read(struct file *file,
-			  char *buffer,
-			  size_t length,
-			  loff_t *ppos)
-{
-	struct irctl *ir = irctls[iminor(file->f_dentry->d_inode)];
-	unsigned char *buf;
-	int ret = 0, written = 0;
-	DECLARE_WAITQUEUE(wait, current);
-
-	if (!ir) {
-		printk(KERN_ERR "%s: called with invalid irctl\n", __func__);
-		return -ENODEV;
-	}
-
-	dev_dbg(ir->d.dev, LOGHEAD "read called\n", ir->d.name, ir->d.minor);
-
-	buf = kzalloc(ir->chunk_size, GFP_KERNEL);
-	if (!buf)
-		return -ENOMEM;
-
-	if (mutex_lock_interruptible(&ir->irctl_lock)) {
-		ret = -ERESTARTSYS;
-		goto out_unlocked;
-	}
-	if (!ir->attached) {
-		ret = -ENODEV;
-		goto out_locked;
-	}
-
-	if (length % ir->chunk_size) {
-		ret = -EINVAL;
-		goto out_locked;
-	}
-
-	/*
-	 * we add ourselves to the task queue before buffer check
-	 * to avoid losing scan code (in case when queue is awaken somewhere
-	 * between while condition checking and scheduling)
-	 */
-	add_wait_queue(&ir->buf->wait_poll, &wait);
-	set_current_state(TASK_INTERRUPTIBLE);
-
-	/*
-	 * while we didn't provide 'length' bytes, device is opened in blocking
-	 * mode and 'copy_to_user' is happy, wait for data.
-	 */
-	while (written < length && ret == 0) {
-		if (lirc_buffer_empty(ir->buf)) {
-			/* According to the read(2) man page, 'written' can be
-			 * returned as less than 'length', instead of blocking
-			 * again, returning -EWOULDBLOCK, or returning
-			 * -ERESTARTSYS */
-			if (written)
-				break;
-			if (file->f_flags & O_NONBLOCK) {
-				ret = -EWOULDBLOCK;
-				break;
-			}
-			if (signal_pending(current)) {
-				ret = -ERESTARTSYS;
-				break;
-			}
-
-			mutex_unlock(&ir->irctl_lock);
-			schedule();
-			set_current_state(TASK_INTERRUPTIBLE);
-
-			if (mutex_lock_interruptible(&ir->irctl_lock)) {
-				ret = -ERESTARTSYS;
-				remove_wait_queue(&ir->buf->wait_poll, &wait);
-				set_current_state(TASK_RUNNING);
-				goto out_unlocked;
-			}
-
-			if (!ir->attached) {
-				ret = -ENODEV;
-				break;
-			}
-		} else {
-			lirc_buffer_read(ir->buf, buf);
-			ret = copy_to_user((void *)buffer+written, buf,
-					   ir->buf->chunk_size);
-			if (!ret)
-				written += ir->buf->chunk_size;
-			else
-				ret = -EFAULT;
-		}
-	}
-
-	remove_wait_queue(&ir->buf->wait_poll, &wait);
-	set_current_state(TASK_RUNNING);
-
-out_locked:
-	mutex_unlock(&ir->irctl_lock);
-
-out_unlocked:
-	kfree(buf);
-	dev_dbg(ir->d.dev, LOGHEAD "read result = %s (%d)\n",
-		ir->d.name, ir->d.minor, ret ? "<fail>" : "<ok>", ret);
-
-	return ret ? ret : written;
-}
-EXPORT_SYMBOL(lirc_dev_fop_read);
-
-void *lirc_get_pdata(struct file *file)
-{
-	void *data = NULL;
-
-	if (file && file->f_dentry && file->f_dentry->d_inode &&
-	    file->f_dentry->d_inode->i_rdev) {
-		struct irctl *ir;
-		ir = irctls[iminor(file->f_dentry->d_inode)];
-		data = ir->d.data;
-	}
-
-	return data;
-}
-EXPORT_SYMBOL(lirc_get_pdata);
-
-
-ssize_t lirc_dev_fop_write(struct file *file, const char *buffer,
-			   size_t length, loff_t *ppos)
-{
-	struct irctl *ir = irctls[iminor(file->f_dentry->d_inode)];
-
-	if (!ir) {
-		printk(KERN_ERR "%s: called with invalid irctl\n", __func__);
-		return -ENODEV;
-	}
-
-	dev_dbg(ir->d.dev, LOGHEAD "write called\n", ir->d.name, ir->d.minor);
-
-	if (!ir->attached)
-		return -ENODEV;
-
-	return -EINVAL;
-}
-EXPORT_SYMBOL(lirc_dev_fop_write);
-
-
-static int __init lirc_dev_init(void)
-{
-	int retval;
-
-	lirc_class = class_create(THIS_MODULE, "lirc");
-	if (IS_ERR(lirc_class)) {
-		retval = PTR_ERR(lirc_class);
-		printk(KERN_ERR "lirc_dev: class_create failed\n");
-		goto error;
-	}
-
-	retval = alloc_chrdev_region(&lirc_base_dev, 0, MAX_IRCTL_DEVICES,
-				     IRCTL_DEV_NAME);
-	if (retval) {
-		class_destroy(lirc_class);
-		printk(KERN_ERR "lirc_dev: alloc_chrdev_region failed\n");
-		goto error;
-	}
-
-
-	printk(KERN_INFO "lirc_dev: IR Remote Control driver registered, "
-	       "major %d \n", MAJOR(lirc_base_dev));
-
-error:
-	return retval;
-}
-
-
-
-static void __exit lirc_dev_exit(void)
-{
-	class_destroy(lirc_class);
-	unregister_chrdev_region(lirc_base_dev, MAX_IRCTL_DEVICES);
-	printk(KERN_INFO "lirc_dev: module unloaded\n");
-}
-
-module_init(lirc_dev_init);
-module_exit(lirc_dev_exit);
-
-MODULE_DESCRIPTION("LIRC base driver module");
-MODULE_AUTHOR("Artur Lipowski");
-MODULE_LICENSE("GPL");
-
-module_param(debug, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(debug, "Enable debugging messages");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/Makefile linux-libre-2.6.38-gnu1/drivers/media/IR/Makefile
--- linux-libre-2.6.37-gnu1/drivers/media/IR/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/Makefile	1969-12-31 19:00:00.000000000 -0500
@@ -1,22 +0,0 @@
-ir-common-objs  := ir-functions.o
-ir-core-objs	:= ir-keytable.o ir-sysfs.o ir-raw-event.o rc-map.o
-
-obj-y += keymaps/
-
-obj-$(CONFIG_IR_CORE) += ir-core.o
-obj-$(CONFIG_VIDEO_IR) += ir-common.o
-obj-$(CONFIG_LIRC) += lirc_dev.o
-obj-$(CONFIG_IR_NEC_DECODER) += ir-nec-decoder.o
-obj-$(CONFIG_IR_RC5_DECODER) += ir-rc5-decoder.o
-obj-$(CONFIG_IR_RC6_DECODER) += ir-rc6-decoder.o
-obj-$(CONFIG_IR_JVC_DECODER) += ir-jvc-decoder.o
-obj-$(CONFIG_IR_SONY_DECODER) += ir-sony-decoder.o
-obj-$(CONFIG_IR_RC5_SZ_DECODER) += ir-rc5-sz-decoder.o
-obj-$(CONFIG_IR_LIRC_CODEC) += ir-lirc-codec.o
-
-# stand-alone IR receivers/transmitters
-obj-$(CONFIG_IR_IMON) += imon.o
-obj-$(CONFIG_IR_MCEUSB) += mceusb.o
-obj-$(CONFIG_IR_NUVOTON) += nuvoton-cir.o
-obj-$(CONFIG_IR_ENE) += ene_ir.o
-obj-$(CONFIG_IR_STREAMZAP) += streamzap.o
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/mceusb.c linux-libre-2.6.38-gnu1/drivers/media/IR/mceusb.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/mceusb.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/mceusb.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1333 +0,0 @@
-/*
- * Driver for USB Windows Media Center Ed. eHome Infrared Transceivers
- *
- * Copyright (c) 2010 by 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
- * in turn also based on the lirc_atiusb driver by Paul Miller. The
- * two mce drivers were merged into one by Jarod Wilson, with transmit
- * support for the 1st-gen device added primarily by Patrick Calhoun,
- * with a bit of tweaks by Jarod. Debugging improvements and proper
- * support for what appears to be 3rd-gen hardware added by Jarod.
- * Initial port from lirc driver to ir-core drivery by Jarod, based
- * partially on a port to an earlier proposed IR infrastructure by
- * Jon Smirl, which included enhancements and simplifications to the
- * incoming IR buffer parsing routines.
- *
- *
- * 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/device.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/input.h>
-#include <linux/usb.h>
-#include <linux/usb/input.h>
-#include <media/ir-core.h>
-
-#define DRIVER_VERSION	"1.91"
-#define DRIVER_AUTHOR	"Jarod Wilson <jarod@wilsonet.com>"
-#define DRIVER_DESC	"Windows Media Center Ed. eHome Infrared Transceiver " \
-			"device driver"
-#define DRIVER_NAME	"mceusb"
-
-#define USB_BUFLEN		32 /* USB reception buffer length */
-#define USB_CTRL_MSG_SZ		2  /* Size of usb ctrl msg on gen1 hw */
-#define MCE_G1_INIT_MSGS	40 /* Init messages on gen1 hw to throw out */
-#define MS_TO_NS(msec)		((msec) * 1000)
-
-/* MCE constants */
-#define MCE_CMDBUF_SIZE		384  /* MCE Command buffer length */
-#define MCE_TIME_UNIT		50   /* Approx 50us resolution */
-#define MCE_CODE_LENGTH		5    /* Normal length of packet (with header) */
-#define MCE_PACKET_SIZE		4    /* Normal length of packet (without header) */
-#define MCE_IRDATA_HEADER	0x84 /* Actual header format is 0x80 + num_bytes */
-#define MCE_IRDATA_TRAILER	0x80 /* End of IR data */
-#define MCE_TX_HEADER_LENGTH	3    /* # of bytes in the initializing tx header */
-#define MCE_MAX_CHANNELS	2    /* Two transmitters, hardware dependent? */
-#define MCE_DEFAULT_TX_MASK	0x03 /* Vals: TX1=0x01, TX2=0x02, ALL=0x03 */
-#define MCE_PULSE_BIT		0x80 /* Pulse bit, MSB set == PULSE else SPACE */
-#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 */
-
-/* Sub-commands, which follow MCE_COMMAND_HEADER or MCE_HW_CMD_HEADER */
-#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 */
-
-
-/* module parameters */
-#ifdef CONFIG_USB_DEBUG
-static int debug = 1;
-#else
-static int debug;
-#endif
-
-/* general constants */
-#define SEND_FLAG_IN_PROGRESS	1
-#define SEND_FLAG_COMPLETE	2
-#define RECV_FLAG_IN_PROGRESS	3
-#define RECV_FLAG_COMPLETE	4
-
-#define MCEUSB_RX		1
-#define MCEUSB_TX		2
-
-#define VENDOR_PHILIPS		0x0471
-#define VENDOR_SMK		0x0609
-#define VENDOR_TATUNG		0x1460
-#define VENDOR_GATEWAY		0x107b
-#define VENDOR_SHUTTLE		0x1308
-#define VENDOR_SHUTTLE2		0x051c
-#define VENDOR_MITSUMI		0x03ee
-#define VENDOR_TOPSEED		0x1784
-#define VENDOR_RICAVISION	0x179d
-#define VENDOR_ITRON		0x195d
-#define VENDOR_FIC		0x1509
-#define VENDOR_LG		0x043e
-#define VENDOR_MICROSOFT	0x045e
-#define VENDOR_FORMOSA		0x147a
-#define VENDOR_FINTEK		0x1934
-#define VENDOR_PINNACLE		0x2304
-#define VENDOR_ECS		0x1019
-#define VENDOR_WISTRON		0x0fb8
-#define VENDOR_COMPRO		0x185b
-#define VENDOR_NORTHSTAR	0x04eb
-#define VENDOR_REALTEK		0x0bda
-#define VENDOR_TIVO		0x105a
-#define VENDOR_CONEXANT		0x0572
-
-enum mceusb_model_type {
-	MCE_GEN2 = 0,		/* Most boards */
-	MCE_GEN1,
-	MCE_GEN3,
-	MCE_GEN2_TX_INV,
-	POLARIS_EVK,
-	CX_HYBRID_TV,
-};
-
-struct mceusb_model {
-	u32 mce_gen1:1;
-	u32 mce_gen2:1;
-	u32 mce_gen3:1;
-	u32 tx_mask_normal:1;
-	u32 is_polaris:1;
-	u32 no_tx:1;
-
-	const char *rc_map;	/* Allow specify a per-board map */
-	const char *name;	/* per-board name */
-};
-
-static const struct mceusb_model mceusb_model[] = {
-	[MCE_GEN1] = {
-		.mce_gen1 = 1,
-		.tx_mask_normal = 1,
-	},
-	[MCE_GEN2] = {
-		.mce_gen2 = 1,
-	},
-	[MCE_GEN2_TX_INV] = {
-		.mce_gen2 = 1,
-		.tx_mask_normal = 1,
-	},
-	[MCE_GEN3] = {
-		.mce_gen3 = 1,
-		.tx_mask_normal = 1,
-	},
-	[POLARIS_EVK] = {
-		.is_polaris = 1,
-		/*
-		 * In fact, the EVK is shipped without
-		 * remotes, but we should have something handy,
-		 * to allow testing it
-		 */
-		.rc_map = RC_MAP_RC5_HAUPPAUGE_NEW,
-		.name = "Conexant Hybrid TV (cx231xx) MCE IR",
-	},
-	[CX_HYBRID_TV] = {
-		.is_polaris = 1,
-		.no_tx = 1, /* tx isn't wired up at all */
-		.name = "Conexant Hybrid TV (cx231xx) MCE IR",
-	},
-};
-
-static struct usb_device_id mceusb_dev_table[] = {
-	/* Original Microsoft MCE IR Transceiver (often HP-branded) */
-	{ USB_DEVICE(VENDOR_MICROSOFT, 0x006d),
-	  .driver_info = MCE_GEN1 },
-	/* Philips Infrared Transceiver - Sahara branded */
-	{ USB_DEVICE(VENDOR_PHILIPS, 0x0608) },
-	/* Philips Infrared Transceiver - HP branded */
-	{ USB_DEVICE(VENDOR_PHILIPS, 0x060c),
-	  .driver_info = MCE_GEN2_TX_INV },
-	/* Philips SRM5100 */
-	{ USB_DEVICE(VENDOR_PHILIPS, 0x060d) },
-	/* Philips Infrared Transceiver - Omaura */
-	{ USB_DEVICE(VENDOR_PHILIPS, 0x060f) },
-	/* Philips Infrared Transceiver - Spinel plus */
-	{ USB_DEVICE(VENDOR_PHILIPS, 0x0613) },
-	/* Philips eHome Infrared Transceiver */
-	{ USB_DEVICE(VENDOR_PHILIPS, 0x0815) },
-	/* Philips/Spinel plus IR transceiver for ASUS */
-	{ USB_DEVICE(VENDOR_PHILIPS, 0x206c) },
-	/* Philips/Spinel plus IR transceiver for ASUS */
-	{ USB_DEVICE(VENDOR_PHILIPS, 0x2088) },
-	/* Realtek MCE IR Receiver */
-	{ USB_DEVICE(VENDOR_REALTEK, 0x0161) },
-	/* SMK/Toshiba G83C0004D410 */
-	{ USB_DEVICE(VENDOR_SMK, 0x031d),
-	  .driver_info = MCE_GEN2_TX_INV },
-	/* SMK eHome Infrared Transceiver (Sony VAIO) */
-	{ USB_DEVICE(VENDOR_SMK, 0x0322),
-	  .driver_info = MCE_GEN2_TX_INV },
-	/* bundled with Hauppauge PVR-150 */
-	{ USB_DEVICE(VENDOR_SMK, 0x0334),
-	  .driver_info = MCE_GEN2_TX_INV },
-	/* SMK eHome Infrared Transceiver */
-	{ USB_DEVICE(VENDOR_SMK, 0x0338) },
-	/* Tatung eHome Infrared Transceiver */
-	{ USB_DEVICE(VENDOR_TATUNG, 0x9150) },
-	/* Shuttle eHome Infrared Transceiver */
-	{ USB_DEVICE(VENDOR_SHUTTLE, 0xc001) },
-	/* Shuttle eHome Infrared Transceiver */
-	{ USB_DEVICE(VENDOR_SHUTTLE2, 0xc001) },
-	/* Gateway eHome Infrared Transceiver */
-	{ USB_DEVICE(VENDOR_GATEWAY, 0x3009) },
-	/* Mitsumi */
-	{ USB_DEVICE(VENDOR_MITSUMI, 0x2501) },
-	/* Topseed eHome Infrared Transceiver */
-	{ USB_DEVICE(VENDOR_TOPSEED, 0x0001),
-	  .driver_info = MCE_GEN2_TX_INV },
-	/* Topseed HP eHome Infrared Transceiver */
-	{ USB_DEVICE(VENDOR_TOPSEED, 0x0006),
-	  .driver_info = MCE_GEN2_TX_INV },
-	/* Topseed eHome Infrared Transceiver */
-	{ USB_DEVICE(VENDOR_TOPSEED, 0x0007),
-	  .driver_info = MCE_GEN2_TX_INV },
-	/* Topseed eHome Infrared Transceiver */
-	{ USB_DEVICE(VENDOR_TOPSEED, 0x0008),
-	  .driver_info = MCE_GEN3 },
-	/* Topseed eHome Infrared Transceiver */
-	{ USB_DEVICE(VENDOR_TOPSEED, 0x000a),
-	  .driver_info = MCE_GEN2_TX_INV },
-	/* Topseed eHome Infrared Transceiver */
-	{ USB_DEVICE(VENDOR_TOPSEED, 0x0011),
-	  .driver_info = MCE_GEN2_TX_INV },
-	/* Ricavision internal Infrared Transceiver */
-	{ USB_DEVICE(VENDOR_RICAVISION, 0x0010) },
-	/* Itron ione Libra Q-11 */
-	{ USB_DEVICE(VENDOR_ITRON, 0x7002) },
-	/* FIC eHome Infrared Transceiver */
-	{ USB_DEVICE(VENDOR_FIC, 0x9242) },
-	/* LG eHome Infrared Transceiver */
-	{ USB_DEVICE(VENDOR_LG, 0x9803) },
-	/* Microsoft MCE Infrared Transceiver */
-	{ USB_DEVICE(VENDOR_MICROSOFT, 0x00a0) },
-	/* Formosa eHome Infrared Transceiver */
-	{ USB_DEVICE(VENDOR_FORMOSA, 0xe015) },
-	/* Formosa21 / eHome Infrared Receiver */
-	{ USB_DEVICE(VENDOR_FORMOSA, 0xe016) },
-	/* Formosa aim / Trust MCE Infrared Receiver */
-	{ USB_DEVICE(VENDOR_FORMOSA, 0xe017) },
-	/* Formosa Industrial Computing / Beanbag Emulation Device */
-	{ USB_DEVICE(VENDOR_FORMOSA, 0xe018) },
-	/* Formosa21 / eHome Infrared Receiver */
-	{ USB_DEVICE(VENDOR_FORMOSA, 0xe03a) },
-	/* Formosa Industrial Computing AIM IR605/A */
-	{ USB_DEVICE(VENDOR_FORMOSA, 0xe03c) },
-	/* Formosa Industrial Computing */
-	{ USB_DEVICE(VENDOR_FORMOSA, 0xe03e) },
-	/* Fintek eHome Infrared Transceiver (HP branded) */
-	{ USB_DEVICE(VENDOR_FINTEK, 0x5168) },
-	/* Fintek eHome Infrared Transceiver */
-	{ USB_DEVICE(VENDOR_FINTEK, 0x0602) },
-	/* Fintek eHome Infrared Transceiver (in the AOpen MP45) */
-	{ USB_DEVICE(VENDOR_FINTEK, 0x0702) },
-	/* Pinnacle Remote Kit */
-	{ USB_DEVICE(VENDOR_PINNACLE, 0x0225),
-	  .driver_info = MCE_GEN3 },
-	/* Elitegroup Computer Systems IR */
-	{ USB_DEVICE(VENDOR_ECS, 0x0f38) },
-	/* Wistron Corp. eHome Infrared Receiver */
-	{ USB_DEVICE(VENDOR_WISTRON, 0x0002) },
-	/* Compro K100 */
-	{ USB_DEVICE(VENDOR_COMPRO, 0x3020) },
-	/* Compro K100 v2 */
-	{ USB_DEVICE(VENDOR_COMPRO, 0x3082) },
-	/* Northstar Systems, Inc. eHome Infrared Transceiver */
-	{ USB_DEVICE(VENDOR_NORTHSTAR, 0xe004) },
-	/* TiVo PC IR Receiver */
-	{ USB_DEVICE(VENDOR_TIVO, 0x2000) },
-	/* Conexant Hybrid TV "Shelby" Polaris SDK */
-	{ USB_DEVICE(VENDOR_CONEXANT, 0x58a1),
-	  .driver_info = POLARIS_EVK },
-	/* Conexant Hybrid TV RDU253S Polaris */
-	{ USB_DEVICE(VENDOR_CONEXANT, 0x58a5),
-	  .driver_info = CX_HYBRID_TV },
-	/* Terminating entry */
-	{ }
-};
-
-/* data structure for each usb transceiver */
-struct mceusb_dev {
-	/* ir-core bits */
-	struct ir_dev_props *props;
-
-	/* optional features we can enable */
-	bool carrier_report_enabled;
-	bool learning_enabled;
-
-	/* core device bits */
-	struct device *dev;
-	struct input_dev *idev;
-
-	/* usb */
-	struct usb_device *usbdev;
-	struct urb *urb_in;
-	struct usb_endpoint_descriptor *usb_ep_in;
-	struct usb_endpoint_descriptor *usb_ep_out;
-
-	/* buffers and dma */
-	unsigned char *buf_in;
-	unsigned int len_in;
-	dma_addr_t dma_in;
-	dma_addr_t dma_out;
-
-	enum {
-		CMD_HEADER = 0,
-		SUBCMD,
-		CMD_DATA,
-		PARSE_IRDATA,
-	} parser_state;
-
-	u8 cmd, rem;		/* Remaining IR data bytes in packet */
-
-	struct {
-		u32 connected:1;
-		u32 tx_mask_normal:1;
-		u32 microsoft_gen1:1;
-		u32 no_tx:1;
-	} flags;
-
-	/* transmit support */
-	int send_flags;
-	u32 carrier;
-	unsigned char tx_mask;
-
-	char name[128];
-	char phys[64];
-	enum mceusb_model_type model;
-};
-
-/*
- * 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};
-/* 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 int mceusb_cmdsize(u8 cmd, u8 subcmd)
-{
-	int datasize = 0;
-
-	switch (cmd) {
-	case MCE_COMMAND_NULL:
-		if (subcmd == MCE_HW_CMD_HEADER)
-			datasize = 1;
-		break;
-	case MCE_HW_CMD_HEADER:
-		switch (subcmd) {
-		case MCE_CMD_G_REVISION:
-			datasize = 2;
-			break;
-		}
-	case MCE_COMMAND_HEADER:
-		switch (subcmd) {
-		case MCE_CMD_UNKNOWN:
-		case MCE_CMD_S_CARRIER:
-		case MCE_CMD_S_TIMEOUT:
-		case MCE_RSP_PULSE_COUNT:
-			datasize = 2;
-			break;
-		case MCE_CMD_SIG_END:
-		case MCE_CMD_S_TXMASK:
-		case MCE_CMD_S_RXSENSOR:
-			datasize = 1;
-			break;
-		}
-	}
-	return datasize;
-}
-
-static void mceusb_dev_printdata(struct mceusb_dev *ir, char *buf,
-				 int offset, int len, bool out)
-{
-	char codes[USB_BUFLEN * 3 + 1];
-	char inout[9];
-	u8 cmd, subcmd, data1, data2;
-	struct device *dev = ir->dev;
-	int i, start, skip = 0;
-
-	if (!debug)
-		return;
-
-	/* skip meaningless 0xb1 0x60 header bytes on orig receiver */
-	if (ir->flags.microsoft_gen1 && !out && !offset)
-		skip = 2;
-
-	if (len <= skip)
-		return;
-
-	for (i = 0; i < len && i < USB_BUFLEN; i++)
-		snprintf(codes + i * 3, 4, "%02x ", buf[i + offset] & 0xff);
-
-	dev_info(dev, "%sx data: %s(length=%d)\n",
-		 (out ? "t" : "r"), codes, len);
-
-	if (out)
-		strcpy(inout, "Request\0");
-	else
-		strcpy(inout, "Got\0");
-
-	start  = offset + skip;
-	cmd    = buf[start] & 0xff;
-	subcmd = buf[start + 1] & 0xff;
-	data1  = buf[start + 2] & 0xff;
-	data2  = buf[start + 3] & 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");
-		else
-			dev_info(dev, "Unknown command 0x%02x 0x%02x\n",
-				 cmd, subcmd);
-		break;
-	case MCE_HW_CMD_HEADER:
-		switch (subcmd) {
-		case MCE_CMD_G_REVISION:
-			if (len == 2)
-				dev_info(dev, "Get hw/sw rev?\n");
-			else
-				dev_info(dev, "hw/sw rev 0x%02x 0x%02x "
-					 "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");
-			break;
-		case MCE_RSP_CMD_INVALID:
-			dev_info(dev, "Previous command not supported\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:
-		switch (subcmd) {
-		case MCE_CMD_SIG_END:
-			dev_info(dev, "End of signal\n");
-			break;
-		case MCE_CMD_PING:
-			dev_info(dev, "Ping\n");
-			break;
-		case MCE_CMD_UNKNOWN:
-			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);
-			break;
-		case MCE_CMD_G_CARRIER:
-			dev_info(dev, "Get carrier mode and freq\n");
-			break;
-		case MCE_CMD_S_TXMASK:
-			dev_info(dev, "%s transmit blaster mask of 0x%02x\n",
-				 inout, data1);
-			break;
-		case MCE_CMD_S_TIMEOUT:
-			/* value is in units of 50us, so x*50/100 or x/2 ms */
-			dev_info(dev, "%s receive timeout of %d ms\n",
-				 inout, ((data1 << 8) | data2) / 2);
-			break;
-		case MCE_CMD_G_TIMEOUT:
-			dev_info(dev, "Get receive timeout\n");
-			break;
-		case MCE_CMD_G_TXMASK:
-			dev_info(dev, "Get transmit blaster mask\n");
-			break;
-		case MCE_CMD_S_RXSENSOR:
-			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 */
-			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");
-			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);
-			break;
-		}
-		break;
-	default:
-		break;
-	}
-
-	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))
-		dev_info(dev, "Raw IR data, %d pulse/space samples\n", ir->rem);
-}
-
-static void mce_async_callback(struct urb *urb, struct pt_regs *regs)
-{
-	struct mceusb_dev *ir;
-	int len;
-
-	if (!urb)
-		return;
-
-	ir = urb->context;
-	if (ir) {
-		len = urb->actual_length;
-
-		dev_dbg(ir->dev, "callback called (status=%d len=%d)\n",
-			urb->status, len);
-
-		mceusb_dev_printdata(ir, urb->transfer_buffer, 0, len, true);
-	}
-
-}
-
-/* request incoming or send outgoing usb packet - used to initialize remote */
-static void mce_request_packet(struct mceusb_dev *ir,
-			       struct usb_endpoint_descriptor *ep,
-			       unsigned char *data, int size, int urb_type)
-{
-	int res;
-	struct urb *async_urb;
-	struct device *dev = ir->dev;
-	unsigned char *async_buf;
-
-	if (urb_type == MCEUSB_TX) {
-		async_urb = usb_alloc_urb(0, GFP_KERNEL);
-		if (unlikely(!async_urb)) {
-			dev_err(dev, "Error, couldn't allocate urb!\n");
-			return;
-		}
-
-		async_buf = kzalloc(size, GFP_KERNEL);
-		if (!async_buf) {
-			dev_err(dev, "Error, couldn't allocate buf!\n");
-			usb_free_urb(async_urb);
-			return;
-		}
-
-		/* outbound data */
-		usb_fill_int_urb(async_urb, ir->usbdev,
-			usb_sndintpipe(ir->usbdev, ep->bEndpointAddress),
-			async_buf, size, (usb_complete_t)mce_async_callback,
-			ir, ep->bInterval);
-		memcpy(async_buf, data, size);
-
-	} else if (urb_type == MCEUSB_RX) {
-		/* standard request */
-		async_urb = ir->urb_in;
-		ir->send_flags = RECV_FLAG_IN_PROGRESS;
-
-	} else {
-		dev_err(dev, "Error! Unknown urb type %d\n", urb_type);
-		return;
-	}
-
-	dev_dbg(dev, "receive request called (size=%#x)\n", size);
-
-	async_urb->transfer_buffer_length = size;
-	async_urb->dev = ir->usbdev;
-
-	res = usb_submit_urb(async_urb, GFP_ATOMIC);
-	if (res) {
-		dev_dbg(dev, "receive request FAILED! (res=%d)\n", res);
-		return;
-	}
-	dev_dbg(dev, "receive request complete (res=%d)\n", res);
-}
-
-static void mce_async_out(struct mceusb_dev *ir, unsigned char *data, int size)
-{
-	mce_request_packet(ir, ir->usb_ep_out, data, size, MCEUSB_TX);
-}
-
-static void mce_sync_in(struct mceusb_dev *ir, unsigned char *data, int size)
-{
-	mce_request_packet(ir, ir->usb_ep_in, data, size, MCEUSB_RX);
-}
-
-/* Send data out the IR blaster port(s) */
-static int mceusb_tx_ir(void *priv, int *txbuf, u32 n)
-{
-	struct mceusb_dev *ir = priv;
-	int i, ret = 0;
-	int count, cmdcount = 0;
-	unsigned char *cmdbuf; /* MCE command buffer */
-	long signal_duration = 0; /* Singnal length in us */
-	struct timeval start_time, end_time;
-
-	do_gettimeofday(&start_time);
-
-	count = n / sizeof(int);
-
-	cmdbuf = kzalloc(sizeof(int) * MCE_CMDBUF_SIZE, GFP_KERNEL);
-	if (!cmdbuf)
-		return -ENOMEM;
-
-	/* MCE tx init header */
-	cmdbuf[cmdcount++] = MCE_COMMAND_HEADER;
-	cmdbuf[cmdcount++] = MCE_CMD_S_TXMASK;
-	cmdbuf[cmdcount++] = ir->tx_mask;
-
-	/* Generate mce packet data */
-	for (i = 0; (i < count) && (cmdcount < MCE_CMDBUF_SIZE); i++) {
-		signal_duration += txbuf[i];
-		txbuf[i] = txbuf[i] / MCE_TIME_UNIT;
-
-		do { /* loop to support long pulses/spaces > 127*50us=6.35ms */
-
-			/* Insert mce packet header every 4th entry */
-			if ((cmdcount < MCE_CMDBUF_SIZE) &&
-			    (cmdcount - MCE_TX_HEADER_LENGTH) %
-			     MCE_CODE_LENGTH == 0)
-				cmdbuf[cmdcount++] = MCE_IRDATA_HEADER;
-
-			/* Insert mce packet data */
-			if (cmdcount < MCE_CMDBUF_SIZE)
-				cmdbuf[cmdcount++] =
-					(txbuf[i] < MCE_PULSE_BIT ?
-					 txbuf[i] : MCE_MAX_PULSE_LENGTH) |
-					 (i & 1 ? 0x00 : MCE_PULSE_BIT);
-			else {
-				ret = -EINVAL;
-				goto out;
-			}
-
-		} while ((txbuf[i] > MCE_MAX_PULSE_LENGTH) &&
-			 (txbuf[i] -= MCE_MAX_PULSE_LENGTH));
-	}
-
-	/* Fix packet length in last header */
-	cmdbuf[cmdcount - (cmdcount - MCE_TX_HEADER_LENGTH) % MCE_CODE_LENGTH] =
-		MCE_COMMAND_IRDATA + (cmdcount - MCE_TX_HEADER_LENGTH) %
-		MCE_CODE_LENGTH - 1;
-
-	/* Check if we have room for the empty packet at the end */
-	if (cmdcount >= MCE_CMDBUF_SIZE) {
-		ret = -EINVAL;
-		goto out;
-	}
-
-	/* All mce commands end with an empty packet (0x80) */
-	cmdbuf[cmdcount++] = MCE_IRDATA_TRAILER;
-
-	/* Transmit the command to the mce device */
-	mce_async_out(ir, cmdbuf, cmdcount);
-
-	/*
-	 * The lircd gap calculation expects the write function to
-	 * wait the time it takes for the ircommand to be sent before
-	 * it returns.
-	 */
-	do_gettimeofday(&end_time);
-	signal_duration -= (end_time.tv_usec - start_time.tv_usec) +
-			   (end_time.tv_sec - start_time.tv_sec) * 1000000;
-
-	/* delay with the closest number of ticks */
-	set_current_state(TASK_INTERRUPTIBLE);
-	schedule_timeout(usecs_to_jiffies(signal_duration));
-
-out:
-	kfree(cmdbuf);
-	return ret ? ret : n;
-}
-
-/* Sets active IR outputs -- mce devices typically have two */
-static int mceusb_set_tx_mask(void *priv, u32 mask)
-{
-	struct mceusb_dev *ir = priv;
-
-	if (ir->flags.tx_mask_normal)
-		ir->tx_mask = mask;
-	else
-		ir->tx_mask = (mask != MCE_DEFAULT_TX_MASK ?
-				mask ^ MCE_DEFAULT_TX_MASK : mask) << 1;
-
-	return 0;
-}
-
-/* Sets the send carrier frequency and mode */
-static int mceusb_set_tx_carrier(void *priv, u32 carrier)
-{
-	struct mceusb_dev *ir = priv;
-	int clk = 10000000;
-	int prescaler = 0, divisor = 0;
-	unsigned char cmdbuf[4] = { MCE_COMMAND_HEADER,
-				    MCE_CMD_S_CARRIER, 0x00, 0x00 };
-
-	/* Carrier has changed */
-	if (ir->carrier != carrier) {
-
-		if (carrier == 0) {
-			ir->carrier = carrier;
-			cmdbuf[2] = MCE_CMD_SIG_END;
-			cmdbuf[3] = MCE_IRDATA_TRAILER;
-			dev_dbg(ir->dev, "%s: disabling carrier "
-				"modulation\n", __func__);
-			mce_async_out(ir, cmdbuf, sizeof(cmdbuf));
-			return carrier;
-		}
-
-		for (prescaler = 0; prescaler < 4; ++prescaler) {
-			divisor = (clk >> (2 * prescaler)) / carrier;
-			if (divisor <= 0xff) {
-				ir->carrier = carrier;
-				cmdbuf[2] = prescaler;
-				cmdbuf[3] = divisor;
-				dev_dbg(ir->dev, "%s: requesting %u HZ "
-					"carrier\n", __func__, carrier);
-
-				/* Transmit new carrier to mce device */
-				mce_async_out(ir, cmdbuf, sizeof(cmdbuf));
-				return carrier;
-			}
-		}
-
-		return -EINVAL;
-
-	}
-
-	return carrier;
-}
-
-/*
- * We don't do anything but print debug spew for many of the command bits
- * we receive from the hardware, but some of them are useful information
- * we want to store so that we can use them.
- */
-static void mceusb_handle_command(struct mceusb_dev *ir, int index)
-{
-	u8 hi = ir->buf_in[index + 1] & 0xff;
-	u8 lo = ir->buf_in[index + 2] & 0xff;
-
-	switch (ir->buf_in[index]) {
-	/* 2-byte return value commands */
-	case MCE_CMD_S_TIMEOUT:
-		ir->props->timeout = MS_TO_NS((hi << 8 | lo) / 2);
-		break;
-
-	/* 1-byte return value commands */
-	case MCE_CMD_S_TXMASK:
-		ir->tx_mask = hi;
-		break;
-	case MCE_CMD_S_RXSENSOR:
-		ir->learning_enabled = (hi == 0x02);
-		break;
-	default:
-		break;
-	}
-}
-
-static void mceusb_process_ir_data(struct mceusb_dev *ir, int buf_len)
-{
-	DEFINE_IR_RAW_EVENT(rawir);
-	int i = 0;
-
-	/* skip meaningless 0xb1 0x60 header bytes on orig receiver */
-	if (ir->flags.microsoft_gen1)
-		i = 2;
-
-	/* if there's no data, just return now */
-	if (buf_len <= i)
-		return;
-
-	for (; i < buf_len; i++) {
-		switch (ir->parser_state) {
-		case SUBCMD:
-			ir->rem = mceusb_cmdsize(ir->cmd, ir->buf_in[i]);
-			mceusb_dev_printdata(ir, ir->buf_in, i - 1,
-					     ir->rem + 2, false);
-			mceusb_handle_command(ir, i);
-			ir->parser_state = CMD_DATA;
-			break;
-		case PARSE_IRDATA:
-			ir->rem--;
-			rawir.pulse = ((ir->buf_in[i] & MCE_PULSE_BIT) != 0);
-			rawir.duration = (ir->buf_in[i] & MCE_PULSE_MASK)
-					 * MS_TO_NS(MCE_TIME_UNIT);
-
-			dev_dbg(ir->dev, "Storing %s with duration %d\n",
-				rawir.pulse ? "pulse" : "space",
-				rawir.duration);
-
-			ir_raw_event_store_with_filter(ir->idev, &rawir);
-			break;
-		case CMD_DATA:
-			ir->rem--;
-			break;
-		case CMD_HEADER:
-			/* 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) !=
-			     MCE_COMMAND_IRDATA)) {
-				ir->parser_state = SUBCMD;
-				continue;
-			}
-			ir->rem = (ir->cmd & MCE_PACKET_LENGTH_MASK);
-			mceusb_dev_printdata(ir, ir->buf_in,
-					     i, ir->rem + 1, false);
-			if (ir->rem)
-				ir->parser_state = PARSE_IRDATA;
-			break;
-		}
-
-		if (ir->parser_state != CMD_HEADER && !ir->rem)
-			ir->parser_state = CMD_HEADER;
-	}
-	dev_dbg(ir->dev, "processed IR data, calling ir_raw_event_handle\n");
-	ir_raw_event_handle(ir->idev);
-}
-
-static void mceusb_dev_recv(struct urb *urb, struct pt_regs *regs)
-{
-	struct mceusb_dev *ir;
-	int buf_len;
-
-	if (!urb)
-		return;
-
-	ir = urb->context;
-	if (!ir) {
-		usb_unlink_urb(urb);
-		return;
-	}
-
-	buf_len = urb->actual_length;
-
-	if (ir->send_flags == RECV_FLAG_IN_PROGRESS) {
-		ir->send_flags = SEND_FLAG_COMPLETE;
-		dev_dbg(ir->dev, "setup answer received %d bytes\n",
-			buf_len);
-	}
-
-	switch (urb->status) {
-	/* success */
-	case 0:
-		mceusb_process_ir_data(ir, buf_len);
-		break;
-
-	case -ECONNRESET:
-	case -ENOENT:
-	case -ESHUTDOWN:
-		usb_unlink_urb(urb);
-		return;
-
-	case -EPIPE:
-	default:
-		dev_dbg(ir->dev, "Error: urb status = %d\n", urb->status);
-		break;
-	}
-
-	usb_submit_urb(urb, GFP_ATOMIC);
-}
-
-static void mceusb_gen1_init(struct mceusb_dev *ir)
-{
-	int ret;
-	int maxp = ir->len_in;
-	struct device *dev = ir->dev;
-	char *data;
-
-	data = kzalloc(USB_CTRL_MSG_SZ, GFP_KERNEL);
-	if (!data) {
-		dev_err(dev, "%s: memory allocation failed!\n", __func__);
-		return;
-	}
-
-	/*
-	 * This is a strange one. Windows issues a set address to the device
-	 * on the receive control pipe and expect a certain value pair back
-	 */
-	ret = usb_control_msg(ir->usbdev, usb_rcvctrlpipe(ir->usbdev, 0),
-			      USB_REQ_SET_ADDRESS, USB_TYPE_VENDOR, 0, 0,
-			      data, USB_CTRL_MSG_SZ, HZ * 3);
-	dev_dbg(dev, "%s - ret = %d\n", __func__, ret);
-	dev_dbg(dev, "%s - data[0] = %d, data[1] = %d\n",
-		__func__, data[0], data[1]);
-
-	/* set feature: bit rate 38400 bps */
-	ret = usb_control_msg(ir->usbdev, usb_sndctrlpipe(ir->usbdev, 0),
-			      USB_REQ_SET_FEATURE, USB_TYPE_VENDOR,
-			      0xc04e, 0x0000, NULL, 0, HZ * 3);
-
-	dev_dbg(dev, "%s - ret = %d\n", __func__, ret);
-
-	/* bRequest 4: set char length to 8 bits */
-	ret = usb_control_msg(ir->usbdev, usb_sndctrlpipe(ir->usbdev, 0),
-			      4, USB_TYPE_VENDOR,
-			      0x0808, 0x0000, NULL, 0, HZ * 3);
-	dev_dbg(dev, "%s - retB = %d\n", __func__, ret);
-
-	/* bRequest 2: set handshaking to use DTR/DSR */
-	ret = usb_control_msg(ir->usbdev, usb_sndctrlpipe(ir->usbdev, 0),
-			      2, USB_TYPE_VENDOR,
-			      0x0000, 0x0100, NULL, 0, HZ * 3);
-	dev_dbg(dev, "%s - retC = %d\n", __func__, ret);
-
-	/* device reset */
-	mce_async_out(ir, DEVICE_RESET, sizeof(DEVICE_RESET));
-	mce_sync_in(ir, NULL, maxp);
-
-	/* get hw/sw revision? */
-	mce_async_out(ir, GET_REVISION, sizeof(GET_REVISION));
-	mce_sync_in(ir, NULL, maxp);
-
-	kfree(data);
-};
-
-static void mceusb_gen2_init(struct mceusb_dev *ir)
-{
-	int maxp = ir->len_in;
-
-	/* device reset */
-	mce_async_out(ir, DEVICE_RESET, sizeof(DEVICE_RESET));
-	mce_sync_in(ir, NULL, maxp);
-
-	/* get hw/sw revision? */
-	mce_async_out(ir, GET_REVISION, sizeof(GET_REVISION));
-	mce_sync_in(ir, NULL, maxp);
-
-	/* unknown what the next two actually return... */
-	mce_async_out(ir, GET_UNKNOWN, sizeof(GET_UNKNOWN));
-	mce_sync_in(ir, NULL, maxp);
-	mce_async_out(ir, GET_UNKNOWN2, sizeof(GET_UNKNOWN2));
-	mce_sync_in(ir, NULL, maxp);
-}
-
-static void mceusb_get_parameters(struct mceusb_dev *ir)
-{
-	int maxp = ir->len_in;
-
-	/* get the carrier and frequency */
-	mce_async_out(ir, GET_CARRIER_FREQ, sizeof(GET_CARRIER_FREQ));
-	mce_sync_in(ir, NULL, maxp);
-
-	if (!ir->flags.no_tx) {
-		/* get the transmitter bitmask */
-		mce_async_out(ir, GET_TX_BITMASK, sizeof(GET_TX_BITMASK));
-		mce_sync_in(ir, NULL, maxp);
-	}
-
-	/* get receiver timeout value */
-	mce_async_out(ir, GET_RX_TIMEOUT, sizeof(GET_RX_TIMEOUT));
-	mce_sync_in(ir, NULL, maxp);
-
-	/* get receiver sensor setting */
-	mce_async_out(ir, GET_RX_SENSOR, sizeof(GET_RX_SENSOR));
-	mce_sync_in(ir, NULL, maxp);
-}
-
-static struct input_dev *mceusb_init_input_dev(struct mceusb_dev *ir)
-{
-	struct input_dev *idev;
-	struct ir_dev_props *props;
-	struct device *dev = ir->dev;
-	const char *rc_map = RC_MAP_RC6_MCE;
-	const char *name = "Media Center Ed. eHome Infrared Remote Transceiver";
-	int ret = -ENODEV;
-
-	idev = input_allocate_device();
-	if (!idev) {
-		dev_err(dev, "remote input dev allocation failed\n");
-		goto idev_alloc_failed;
-	}
-
-	ret = -ENOMEM;
-	props = kzalloc(sizeof(struct ir_dev_props), GFP_KERNEL);
-	if (!props) {
-		dev_err(dev, "remote ir dev props allocation failed\n");
-		goto props_alloc_failed;
-	}
-
-	if (mceusb_model[ir->model].name)
-		name = mceusb_model[ir->model].name;
-
-	snprintf(ir->name, sizeof(ir->name), "%s (%04x:%04x)",
-		 name,
-		 le16_to_cpu(ir->usbdev->descriptor.idVendor),
-		 le16_to_cpu(ir->usbdev->descriptor.idProduct));
-
-	idev->name = ir->name;
-	usb_make_path(ir->usbdev, ir->phys, sizeof(ir->phys));
-	strlcat(ir->phys, "/input0", sizeof(ir->phys));
-	idev->phys = ir->phys;
-
-	props->priv = ir;
-	props->driver_type = RC_DRIVER_IR_RAW;
-	props->allowed_protos = IR_TYPE_ALL;
-	props->timeout = MS_TO_NS(1000);
-	if (!ir->flags.no_tx) {
-		props->s_tx_mask = mceusb_set_tx_mask;
-		props->s_tx_carrier = mceusb_set_tx_carrier;
-		props->tx_ir = mceusb_tx_ir;
-	}
-
-	ir->props = props;
-
-	usb_to_input_id(ir->usbdev, &idev->id);
-	idev->dev.parent = ir->dev;
-
-	if (mceusb_model[ir->model].rc_map)
-		rc_map = mceusb_model[ir->model].rc_map;
-
-	ret = ir_input_register(idev, rc_map, props, DRIVER_NAME);
-	if (ret < 0) {
-		dev_err(dev, "remote input device register failed\n");
-		goto irdev_failed;
-	}
-
-	return idev;
-
-irdev_failed:
-	kfree(props);
-props_alloc_failed:
-	input_free_device(idev);
-idev_alloc_failed:
-	return NULL;
-}
-
-static int __devinit mceusb_dev_probe(struct usb_interface *intf,
-				      const struct usb_device_id *id)
-{
-	struct usb_device *dev = interface_to_usbdev(intf);
-	struct usb_host_interface *idesc;
-	struct usb_endpoint_descriptor *ep = NULL;
-	struct usb_endpoint_descriptor *ep_in = NULL;
-	struct usb_endpoint_descriptor *ep_out = NULL;
-	struct mceusb_dev *ir = NULL;
-	int pipe, maxp, i;
-	char buf[63], name[128] = "";
-	enum mceusb_model_type model = id->driver_info;
-	bool is_gen3;
-	bool is_microsoft_gen1;
-	bool tx_mask_normal;
-	bool is_polaris;
-
-	dev_dbg(&intf->dev, "%s called\n", __func__);
-
-	idesc  = intf->cur_altsetting;
-
-	is_gen3 = mceusb_model[model].mce_gen3;
-	is_microsoft_gen1 = mceusb_model[model].mce_gen1;
-	tx_mask_normal = mceusb_model[model].tx_mask_normal;
-	is_polaris = mceusb_model[model].is_polaris;
-
-	if (is_polaris) {
-		/* Interface 0 is IR */
-		if (idesc->desc.bInterfaceNumber)
-			return -ENODEV;
-	}
-
-	/* step through the endpoints to find first bulk in and out endpoint */
-	for (i = 0; i < idesc->desc.bNumEndpoints; ++i) {
-		ep = &idesc->endpoint[i].desc;
-
-		if ((ep_in == NULL)
-			&& ((ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
-			    == USB_DIR_IN)
-			&& (((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
-			    == USB_ENDPOINT_XFER_BULK)
-			|| ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
-			    == USB_ENDPOINT_XFER_INT))) {
-
-			ep_in = ep;
-			ep_in->bmAttributes = USB_ENDPOINT_XFER_INT;
-			ep_in->bInterval = 1;
-			dev_dbg(&intf->dev, "acceptable inbound endpoint "
-				"found\n");
-		}
-
-		if ((ep_out == NULL)
-			&& ((ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
-			    == USB_DIR_OUT)
-			&& (((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
-			    == USB_ENDPOINT_XFER_BULK)
-			|| ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
-			    == USB_ENDPOINT_XFER_INT))) {
-
-			ep_out = ep;
-			ep_out->bmAttributes = USB_ENDPOINT_XFER_INT;
-			ep_out->bInterval = 1;
-			dev_dbg(&intf->dev, "acceptable outbound endpoint "
-				"found\n");
-		}
-	}
-	if (ep_in == NULL) {
-		dev_dbg(&intf->dev, "inbound and/or endpoint not found\n");
-		return -ENODEV;
-	}
-
-	pipe = usb_rcvintpipe(dev, ep_in->bEndpointAddress);
-	maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
-
-	ir = kzalloc(sizeof(struct mceusb_dev), GFP_KERNEL);
-	if (!ir)
-		goto mem_alloc_fail;
-
-	ir->buf_in = usb_alloc_coherent(dev, maxp, GFP_ATOMIC, &ir->dma_in);
-	if (!ir->buf_in)
-		goto buf_in_alloc_fail;
-
-	ir->urb_in = usb_alloc_urb(0, GFP_KERNEL);
-	if (!ir->urb_in)
-		goto urb_in_alloc_fail;
-
-	ir->usbdev = dev;
-	ir->dev = &intf->dev;
-	ir->len_in = maxp;
-	ir->flags.microsoft_gen1 = is_microsoft_gen1;
-	ir->flags.tx_mask_normal = tx_mask_normal;
-	ir->flags.no_tx = mceusb_model[model].no_tx;
-	ir->model = model;
-
-	/* Saving usb interface data for use by the transmitter routine */
-	ir->usb_ep_in = ep_in;
-	ir->usb_ep_out = ep_out;
-
-	if (dev->descriptor.iManufacturer
-	    && usb_string(dev, dev->descriptor.iManufacturer,
-			  buf, sizeof(buf)) > 0)
-		strlcpy(name, buf, sizeof(name));
-	if (dev->descriptor.iProduct
-	    && usb_string(dev, dev->descriptor.iProduct,
-			  buf, sizeof(buf)) > 0)
-		snprintf(name + strlen(name), sizeof(name) - strlen(name),
-			 " %s", buf);
-
-	ir->idev = mceusb_init_input_dev(ir);
-	if (!ir->idev)
-		goto input_dev_fail;
-
-	/* flush buffers on the device */
-	mce_sync_in(ir, NULL, maxp);
-	mce_sync_in(ir, NULL, maxp);
-
-	/* wire up inbound data handler */
-	usb_fill_int_urb(ir->urb_in, dev, pipe, ir->buf_in,
-		maxp, (usb_complete_t) mceusb_dev_recv, ir, ep_in->bInterval);
-	ir->urb_in->transfer_dma = ir->dma_in;
-	ir->urb_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
-
-	/* initialize device */
-	if (ir->flags.microsoft_gen1)
-		mceusb_gen1_init(ir);
-	else if (!is_gen3)
-		mceusb_gen2_init(ir);
-
-	mceusb_get_parameters(ir);
-
-	if (!ir->flags.no_tx)
-		mceusb_set_tx_mask(ir, 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);
-
-	return 0;
-
-	/* Error-handling path */
-input_dev_fail:
-	usb_free_urb(ir->urb_in);
-urb_in_alloc_fail:
-	usb_free_coherent(dev, maxp, ir->buf_in, ir->dma_in);
-buf_in_alloc_fail:
-	kfree(ir);
-mem_alloc_fail:
-	dev_err(&intf->dev, "%s: device setup failed!\n", __func__);
-
-	return -ENOMEM;
-}
-
-
-static void __devexit mceusb_dev_disconnect(struct usb_interface *intf)
-{
-	struct usb_device *dev = interface_to_usbdev(intf);
-	struct mceusb_dev *ir = usb_get_intfdata(intf);
-
-	usb_set_intfdata(intf, NULL);
-
-	if (!ir)
-		return;
-
-	ir->usbdev = NULL;
-	ir_input_unregister(ir->idev);
-	usb_kill_urb(ir->urb_in);
-	usb_free_urb(ir->urb_in);
-	usb_free_coherent(dev, ir->len_in, ir->buf_in, ir->dma_in);
-
-	kfree(ir);
-}
-
-static int mceusb_dev_suspend(struct usb_interface *intf, pm_message_t message)
-{
-	struct mceusb_dev *ir = usb_get_intfdata(intf);
-	dev_info(ir->dev, "suspend\n");
-	usb_kill_urb(ir->urb_in);
-	return 0;
-}
-
-static int mceusb_dev_resume(struct usb_interface *intf)
-{
-	struct mceusb_dev *ir = usb_get_intfdata(intf);
-	dev_info(ir->dev, "resume\n");
-	if (usb_submit_urb(ir->urb_in, GFP_ATOMIC))
-		return -EIO;
-	return 0;
-}
-
-static struct usb_driver mceusb_dev_driver = {
-	.name =		DRIVER_NAME,
-	.probe =	mceusb_dev_probe,
-	.disconnect =	mceusb_dev_disconnect,
-	.suspend =	mceusb_dev_suspend,
-	.resume =	mceusb_dev_resume,
-	.reset_resume =	mceusb_dev_resume,
-	.id_table =	mceusb_dev_table
-};
-
-static int __init mceusb_dev_init(void)
-{
-	int ret;
-
-	ret = usb_register(&mceusb_dev_driver);
-	if (ret < 0)
-		printk(KERN_ERR DRIVER_NAME
-		       ": usb register failed, result = %d\n", ret);
-
-	return ret;
-}
-
-static void __exit mceusb_dev_exit(void)
-{
-	usb_deregister(&mceusb_dev_driver);
-}
-
-module_init(mceusb_dev_init);
-module_exit(mceusb_dev_exit);
-
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_LICENSE("GPL");
-MODULE_DEVICE_TABLE(usb, mceusb_dev_table);
-
-module_param(debug, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(debug, "Debug enabled or not");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/nuvoton-cir.c linux-libre-2.6.38-gnu1/drivers/media/IR/nuvoton-cir.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/nuvoton-cir.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/nuvoton-cir.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1252 +0,0 @@
-/*
- * Driver for Nuvoton Technology Corporation w83667hg/w83677hg-i CIR
- *
- * Copyright (C) 2010 Jarod Wilson <jarod@redhat.com>
- * Copyright (C) 2009 Nuvoton PS Team
- *
- * Special thanks to Nuvoton for providing hardware, spec sheets and
- * sample code upon which portions of this driver are based. Indirect
- * thanks also to Maxim Levitsky, whose ene_ir driver this driver is
- * modeled after.
- *
- * 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/module.h>
-#include <linux/pnp.h>
-#include <linux/io.h>
-#include <linux/interrupt.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/input.h>
-#include <media/ir-core.h>
-#include <linux/pci_ids.h>
-
-#include "nuvoton-cir.h"
-
-static char *chip_id = "w836x7hg";
-
-/* write val to config reg */
-static inline void nvt_cr_write(struct nvt_dev *nvt, u8 val, u8 reg)
-{
-	outb(reg, nvt->cr_efir);
-	outb(val, nvt->cr_efdr);
-}
-
-/* read val from config reg */
-static inline u8 nvt_cr_read(struct nvt_dev *nvt, u8 reg)
-{
-	outb(reg, nvt->cr_efir);
-	return inb(nvt->cr_efdr);
-}
-
-/* update config register bit without changing other bits */
-static inline void nvt_set_reg_bit(struct nvt_dev *nvt, u8 val, u8 reg)
-{
-	u8 tmp = nvt_cr_read(nvt, reg) | val;
-	nvt_cr_write(nvt, tmp, reg);
-}
-
-/* clear config register bit without changing other bits */
-static inline void nvt_clear_reg_bit(struct nvt_dev *nvt, u8 val, u8 reg)
-{
-	u8 tmp = nvt_cr_read(nvt, reg) & ~val;
-	nvt_cr_write(nvt, tmp, reg);
-}
-
-/* enter extended function mode */
-static inline void nvt_efm_enable(struct nvt_dev *nvt)
-{
-	/* Enabling Extended Function Mode explicitly requires writing 2x */
-	outb(EFER_EFM_ENABLE, nvt->cr_efir);
-	outb(EFER_EFM_ENABLE, nvt->cr_efir);
-}
-
-/* exit extended function mode */
-static inline void nvt_efm_disable(struct nvt_dev *nvt)
-{
-	outb(EFER_EFM_DISABLE, nvt->cr_efir);
-}
-
-/*
- * When you want to address a specific logical device, write its logical
- * device number to CR_LOGICAL_DEV_SEL, then enable/disable by writing
- * 0x1/0x0 respectively to CR_LOGICAL_DEV_EN.
- */
-static inline void nvt_select_logical_dev(struct nvt_dev *nvt, u8 ldev)
-{
-	outb(CR_LOGICAL_DEV_SEL, nvt->cr_efir);
-	outb(ldev, nvt->cr_efdr);
-}
-
-/* write val to cir config register */
-static inline void nvt_cir_reg_write(struct nvt_dev *nvt, u8 val, u8 offset)
-{
-	outb(val, nvt->cir_addr + offset);
-}
-
-/* read val from cir config register */
-static u8 nvt_cir_reg_read(struct nvt_dev *nvt, u8 offset)
-{
-	u8 val;
-
-	val = inb(nvt->cir_addr + offset);
-
-	return val;
-}
-
-/* write val to cir wake register */
-static inline void nvt_cir_wake_reg_write(struct nvt_dev *nvt,
-					  u8 val, u8 offset)
-{
-	outb(val, nvt->cir_wake_addr + offset);
-}
-
-/* read val from cir wake config register */
-static u8 nvt_cir_wake_reg_read(struct nvt_dev *nvt, u8 offset)
-{
-	u8 val;
-
-	val = inb(nvt->cir_wake_addr + offset);
-
-	return val;
-}
-
-#define pr_reg(text, ...) \
-	printk(KERN_INFO KBUILD_MODNAME ": " text, ## __VA_ARGS__)
-
-/* dump current cir register contents */
-static void cir_dump_regs(struct nvt_dev *nvt)
-{
-	nvt_efm_enable(nvt);
-	nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR);
-
-	pr_reg("%s: Dump CIR logical device registers:\n", NVT_DRIVER_NAME);
-	pr_reg(" * CR CIR ACTIVE :   0x%x\n",
-	       nvt_cr_read(nvt, CR_LOGICAL_DEV_EN));
-	pr_reg(" * CR CIR BASE ADDR: 0x%x\n",
-	       (nvt_cr_read(nvt, CR_CIR_BASE_ADDR_HI) << 8) |
-		nvt_cr_read(nvt, CR_CIR_BASE_ADDR_LO));
-	pr_reg(" * CR CIR IRQ NUM:   0x%x\n",
-	       nvt_cr_read(nvt, CR_CIR_IRQ_RSRC));
-
-	nvt_efm_disable(nvt);
-
-	pr_reg("%s: Dump CIR registers:\n", NVT_DRIVER_NAME);
-	pr_reg(" * IRCON:     0x%x\n", nvt_cir_reg_read(nvt, CIR_IRCON));
-	pr_reg(" * IRSTS:     0x%x\n", nvt_cir_reg_read(nvt, CIR_IRSTS));
-	pr_reg(" * IREN:      0x%x\n", nvt_cir_reg_read(nvt, CIR_IREN));
-	pr_reg(" * RXFCONT:   0x%x\n", nvt_cir_reg_read(nvt, CIR_RXFCONT));
-	pr_reg(" * CP:        0x%x\n", nvt_cir_reg_read(nvt, CIR_CP));
-	pr_reg(" * CC:        0x%x\n", nvt_cir_reg_read(nvt, CIR_CC));
-	pr_reg(" * SLCH:      0x%x\n", nvt_cir_reg_read(nvt, CIR_SLCH));
-	pr_reg(" * SLCL:      0x%x\n", nvt_cir_reg_read(nvt, CIR_SLCL));
-	pr_reg(" * FIFOCON:   0x%x\n", nvt_cir_reg_read(nvt, CIR_FIFOCON));
-	pr_reg(" * IRFIFOSTS: 0x%x\n", nvt_cir_reg_read(nvt, CIR_IRFIFOSTS));
-	pr_reg(" * SRXFIFO:   0x%x\n", nvt_cir_reg_read(nvt, CIR_SRXFIFO));
-	pr_reg(" * TXFCONT:   0x%x\n", nvt_cir_reg_read(nvt, CIR_TXFCONT));
-	pr_reg(" * STXFIFO:   0x%x\n", nvt_cir_reg_read(nvt, CIR_STXFIFO));
-	pr_reg(" * FCCH:      0x%x\n", nvt_cir_reg_read(nvt, CIR_FCCH));
-	pr_reg(" * FCCL:      0x%x\n", nvt_cir_reg_read(nvt, CIR_FCCL));
-	pr_reg(" * IRFSM:     0x%x\n", nvt_cir_reg_read(nvt, CIR_IRFSM));
-}
-
-/* dump current cir wake register contents */
-static void cir_wake_dump_regs(struct nvt_dev *nvt)
-{
-	u8 i, fifo_len;
-
-	nvt_efm_enable(nvt);
-	nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR_WAKE);
-
-	pr_reg("%s: Dump CIR WAKE logical device registers:\n",
-	       NVT_DRIVER_NAME);
-	pr_reg(" * CR CIR WAKE ACTIVE :   0x%x\n",
-	       nvt_cr_read(nvt, CR_LOGICAL_DEV_EN));
-	pr_reg(" * CR CIR WAKE BASE ADDR: 0x%x\n",
-	       (nvt_cr_read(nvt, CR_CIR_BASE_ADDR_HI) << 8) |
-		nvt_cr_read(nvt, CR_CIR_BASE_ADDR_LO));
-	pr_reg(" * CR CIR WAKE IRQ NUM:   0x%x\n",
-	       nvt_cr_read(nvt, CR_CIR_IRQ_RSRC));
-
-	nvt_efm_disable(nvt);
-
-	pr_reg("%s: Dump CIR WAKE registers\n", NVT_DRIVER_NAME);
-	pr_reg(" * IRCON:          0x%x\n",
-	       nvt_cir_wake_reg_read(nvt, CIR_WAKE_IRCON));
-	pr_reg(" * IRSTS:          0x%x\n",
-	       nvt_cir_wake_reg_read(nvt, CIR_WAKE_IRSTS));
-	pr_reg(" * IREN:           0x%x\n",
-	       nvt_cir_wake_reg_read(nvt, CIR_WAKE_IREN));
-	pr_reg(" * FIFO CMP DEEP:  0x%x\n",
-	       nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFO_CMP_DEEP));
-	pr_reg(" * FIFO CMP TOL:   0x%x\n",
-	       nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFO_CMP_TOL));
-	pr_reg(" * FIFO COUNT:     0x%x\n",
-	       nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFO_COUNT));
-	pr_reg(" * SLCH:           0x%x\n",
-	       nvt_cir_wake_reg_read(nvt, CIR_WAKE_SLCH));
-	pr_reg(" * SLCL:           0x%x\n",
-	       nvt_cir_wake_reg_read(nvt, CIR_WAKE_SLCL));
-	pr_reg(" * FIFOCON:        0x%x\n",
-	       nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFOCON));
-	pr_reg(" * SRXFSTS:        0x%x\n",
-	       nvt_cir_wake_reg_read(nvt, CIR_WAKE_SRXFSTS));
-	pr_reg(" * SAMPLE RX FIFO: 0x%x\n",
-	       nvt_cir_wake_reg_read(nvt, CIR_WAKE_SAMPLE_RX_FIFO));
-	pr_reg(" * WR FIFO DATA:   0x%x\n",
-	       nvt_cir_wake_reg_read(nvt, CIR_WAKE_WR_FIFO_DATA));
-	pr_reg(" * RD FIFO ONLY:   0x%x\n",
-	       nvt_cir_wake_reg_read(nvt, CIR_WAKE_RD_FIFO_ONLY));
-	pr_reg(" * RD FIFO ONLY IDX: 0x%x\n",
-	       nvt_cir_wake_reg_read(nvt, CIR_WAKE_RD_FIFO_ONLY_IDX));
-	pr_reg(" * FIFO IGNORE:    0x%x\n",
-	       nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFO_IGNORE));
-	pr_reg(" * IRFSM:          0x%x\n",
-	       nvt_cir_wake_reg_read(nvt, CIR_WAKE_IRFSM));
-
-	fifo_len = nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFO_COUNT);
-	pr_reg("%s: Dump CIR WAKE FIFO (len %d)\n", NVT_DRIVER_NAME, fifo_len);
-	pr_reg("* Contents = ");
-	for (i = 0; i < fifo_len; i++)
-		printk(KERN_CONT "%02x ",
-		       nvt_cir_wake_reg_read(nvt, CIR_WAKE_RD_FIFO_ONLY));
-	printk(KERN_CONT "\n");
-}
-
-/* detect hardware features */
-static int nvt_hw_detect(struct nvt_dev *nvt)
-{
-	unsigned long flags;
-	u8 chip_major, chip_minor;
-	int ret = 0;
-
-	nvt_efm_enable(nvt);
-
-	/* Check if we're wired for the alternate EFER setup */
-	chip_major = nvt_cr_read(nvt, CR_CHIP_ID_HI);
-	if (chip_major == 0xff) {
-		nvt->cr_efir = CR_EFIR2;
-		nvt->cr_efdr = CR_EFDR2;
-		nvt_efm_enable(nvt);
-		chip_major = nvt_cr_read(nvt, CR_CHIP_ID_HI);
-	}
-
-	chip_minor = nvt_cr_read(nvt, CR_CHIP_ID_LO);
-	nvt_dbg("%s: chip id: 0x%02x 0x%02x", chip_id, chip_major, chip_minor);
-
-	if (chip_major != CHIP_ID_HIGH &&
-	    (chip_minor != CHIP_ID_LOW || chip_minor != CHIP_ID_LOW2))
-		ret = -ENODEV;
-
-	nvt_efm_disable(nvt);
-
-	spin_lock_irqsave(&nvt->nvt_lock, flags);
-	nvt->chip_major = chip_major;
-	nvt->chip_minor = chip_minor;
-	spin_unlock_irqrestore(&nvt->nvt_lock, flags);
-
-	return ret;
-}
-
-static void nvt_cir_ldev_init(struct nvt_dev *nvt)
-{
-	u8 val;
-
-	/* output pin selection (Pin95=CIRRX, Pin96=CIRTX1, WB enabled */
-	val = nvt_cr_read(nvt, CR_OUTPUT_PIN_SEL);
-	val &= OUTPUT_PIN_SEL_MASK;
-	val |= (OUTPUT_ENABLE_CIR | OUTPUT_ENABLE_CIRWB);
-	nvt_cr_write(nvt, val, CR_OUTPUT_PIN_SEL);
-
-	/* Select CIR logical device and enable */
-	nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR);
-	nvt_cr_write(nvt, LOGICAL_DEV_ENABLE, CR_LOGICAL_DEV_EN);
-
-	nvt_cr_write(nvt, nvt->cir_addr >> 8, CR_CIR_BASE_ADDR_HI);
-	nvt_cr_write(nvt, nvt->cir_addr & 0xff, CR_CIR_BASE_ADDR_LO);
-
-	nvt_cr_write(nvt, nvt->cir_irq, CR_CIR_IRQ_RSRC);
-
-	nvt_dbg("CIR initialized, base io port address: 0x%lx, irq: %d",
-		nvt->cir_addr, nvt->cir_irq);
-}
-
-static void nvt_cir_wake_ldev_init(struct nvt_dev *nvt)
-{
-	/* Select ACPI logical device, enable it and CIR Wake */
-	nvt_select_logical_dev(nvt, LOGICAL_DEV_ACPI);
-	nvt_cr_write(nvt, LOGICAL_DEV_ENABLE, CR_LOGICAL_DEV_EN);
-
-	/* Enable CIR Wake via PSOUT# (Pin60) */
-	nvt_set_reg_bit(nvt, CIR_WAKE_ENABLE_BIT, CR_ACPI_CIR_WAKE);
-
-	/* enable cir interrupt of mouse/keyboard IRQ event */
-	nvt_set_reg_bit(nvt, CIR_INTR_MOUSE_IRQ_BIT, CR_ACPI_IRQ_EVENTS);
-
-	/* enable pme interrupt of cir wakeup event */
-	nvt_set_reg_bit(nvt, PME_INTR_CIR_PASS_BIT, CR_ACPI_IRQ_EVENTS2);
-
-	/* Select CIR Wake logical device and enable */
-	nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR_WAKE);
-	nvt_cr_write(nvt, LOGICAL_DEV_ENABLE, CR_LOGICAL_DEV_EN);
-
-	nvt_cr_write(nvt, nvt->cir_wake_addr >> 8, CR_CIR_BASE_ADDR_HI);
-	nvt_cr_write(nvt, nvt->cir_wake_addr & 0xff, CR_CIR_BASE_ADDR_LO);
-
-	nvt_cr_write(nvt, nvt->cir_wake_irq, CR_CIR_IRQ_RSRC);
-
-	nvt_dbg("CIR Wake initialized, base io port address: 0x%lx, irq: %d",
-		nvt->cir_wake_addr, nvt->cir_wake_irq);
-}
-
-/* clear out the hardware's cir rx fifo */
-static void nvt_clear_cir_fifo(struct nvt_dev *nvt)
-{
-	u8 val;
-
-	val = nvt_cir_reg_read(nvt, CIR_FIFOCON);
-	nvt_cir_reg_write(nvt, val | CIR_FIFOCON_RXFIFOCLR, CIR_FIFOCON);
-}
-
-/* clear out the hardware's cir wake rx fifo */
-static void nvt_clear_cir_wake_fifo(struct nvt_dev *nvt)
-{
-	u8 val;
-
-	val = nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFOCON);
-	nvt_cir_wake_reg_write(nvt, val | CIR_WAKE_FIFOCON_RXFIFOCLR,
-			       CIR_WAKE_FIFOCON);
-}
-
-/* clear out the hardware's cir tx fifo */
-static void nvt_clear_tx_fifo(struct nvt_dev *nvt)
-{
-	u8 val;
-
-	val = nvt_cir_reg_read(nvt, CIR_FIFOCON);
-	nvt_cir_reg_write(nvt, val | CIR_FIFOCON_TXFIFOCLR, CIR_FIFOCON);
-}
-
-/* enable RX Trigger Level Reach and Packet End interrupts */
-static void nvt_set_cir_iren(struct nvt_dev *nvt)
-{
-	u8 iren;
-
-	iren = CIR_IREN_RTR | CIR_IREN_PE;
-	nvt_cir_reg_write(nvt, iren, CIR_IREN);
-}
-
-static void nvt_cir_regs_init(struct nvt_dev *nvt)
-{
-	/* set sample limit count (PE interrupt raised when reached) */
-	nvt_cir_reg_write(nvt, CIR_RX_LIMIT_COUNT >> 8, CIR_SLCH);
-	nvt_cir_reg_write(nvt, CIR_RX_LIMIT_COUNT & 0xff, CIR_SLCL);
-
-	/* set fifo irq trigger levels */
-	nvt_cir_reg_write(nvt, CIR_FIFOCON_TX_TRIGGER_LEV |
-			  CIR_FIFOCON_RX_TRIGGER_LEV, CIR_FIFOCON);
-
-	/*
-	 * Enable TX and RX, specify carrier on = low, off = high, and set
-	 * sample period (currently 50us)
-	 */
-	nvt_cir_reg_write(nvt,
-			  CIR_IRCON_TXEN | CIR_IRCON_RXEN |
-			  CIR_IRCON_RXINV | CIR_IRCON_SAMPLE_PERIOD_SEL,
-			  CIR_IRCON);
-
-	/* clear hardware rx and tx fifos */
-	nvt_clear_cir_fifo(nvt);
-	nvt_clear_tx_fifo(nvt);
-
-	/* clear any and all stray interrupts */
-	nvt_cir_reg_write(nvt, 0xff, CIR_IRSTS);
-
-	/* and finally, enable interrupts */
-	nvt_set_cir_iren(nvt);
-}
-
-static void nvt_cir_wake_regs_init(struct nvt_dev *nvt)
-{
-	/* set number of bytes needed for wake key comparison (default 67) */
-	nvt_cir_wake_reg_write(nvt, CIR_WAKE_FIFO_LEN, CIR_WAKE_FIFO_CMP_DEEP);
-
-	/* set tolerance/variance allowed per byte during wake compare */
-	nvt_cir_wake_reg_write(nvt, CIR_WAKE_CMP_TOLERANCE,
-			       CIR_WAKE_FIFO_CMP_TOL);
-
-	/* set sample limit count (PE interrupt raised when reached) */
-	nvt_cir_wake_reg_write(nvt, CIR_RX_LIMIT_COUNT >> 8, CIR_WAKE_SLCH);
-	nvt_cir_wake_reg_write(nvt, CIR_RX_LIMIT_COUNT & 0xff, CIR_WAKE_SLCL);
-
-	/* set cir wake fifo rx trigger level (currently 67) */
-	nvt_cir_wake_reg_write(nvt, CIR_WAKE_FIFOCON_RX_TRIGGER_LEV,
-			       CIR_WAKE_FIFOCON);
-
-	/*
-	 * Enable TX and RX, specific carrier on = low, off = high, and set
-	 * sample period (currently 50us)
-	 */
-	nvt_cir_wake_reg_write(nvt, CIR_WAKE_IRCON_MODE0 | CIR_WAKE_IRCON_RXEN |
-			       CIR_WAKE_IRCON_R | CIR_WAKE_IRCON_RXINV |
-			       CIR_WAKE_IRCON_SAMPLE_PERIOD_SEL,
-			       CIR_WAKE_IRCON);
-
-	/* clear cir wake rx fifo */
-	nvt_clear_cir_wake_fifo(nvt);
-
-	/* clear any and all stray interrupts */
-	nvt_cir_wake_reg_write(nvt, 0xff, CIR_WAKE_IRSTS);
-}
-
-static void nvt_enable_wake(struct nvt_dev *nvt)
-{
-	nvt_efm_enable(nvt);
-
-	nvt_select_logical_dev(nvt, LOGICAL_DEV_ACPI);
-	nvt_set_reg_bit(nvt, CIR_WAKE_ENABLE_BIT, CR_ACPI_CIR_WAKE);
-	nvt_set_reg_bit(nvt, CIR_INTR_MOUSE_IRQ_BIT, CR_ACPI_IRQ_EVENTS);
-	nvt_set_reg_bit(nvt, PME_INTR_CIR_PASS_BIT, CR_ACPI_IRQ_EVENTS2);
-
-	nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR_WAKE);
-	nvt_cr_write(nvt, LOGICAL_DEV_ENABLE, CR_LOGICAL_DEV_EN);
-
-	nvt_efm_disable(nvt);
-
-	nvt_cir_wake_reg_write(nvt, CIR_WAKE_IRCON_MODE0 | CIR_WAKE_IRCON_RXEN |
-			       CIR_WAKE_IRCON_R | CIR_WAKE_IRCON_RXINV |
-			       CIR_WAKE_IRCON_SAMPLE_PERIOD_SEL,
-			       CIR_WAKE_IRCON);
-	nvt_cir_wake_reg_write(nvt, 0xff, CIR_WAKE_IRSTS);
-	nvt_cir_wake_reg_write(nvt, 0, CIR_WAKE_IREN);
-}
-
-/* rx carrier detect only works in learning mode, must be called w/nvt_lock */
-static u32 nvt_rx_carrier_detect(struct nvt_dev *nvt)
-{
-	u32 count, carrier, duration = 0;
-	int i;
-
-	count = nvt_cir_reg_read(nvt, CIR_FCCL) |
-		nvt_cir_reg_read(nvt, CIR_FCCH) << 8;
-
-	for (i = 0; i < nvt->pkts; i++) {
-		if (nvt->buf[i] & BUF_PULSE_BIT)
-			duration += nvt->buf[i] & BUF_LEN_MASK;
-	}
-
-	duration *= SAMPLE_PERIOD;
-
-	if (!count || !duration) {
-		nvt_pr(KERN_NOTICE, "Unable to determine carrier! (c:%u, d:%u)",
-		       count, duration);
-		return 0;
-	}
-
-	carrier = (count * 1000000) / duration;
-
-	if ((carrier > MAX_CARRIER) || (carrier < MIN_CARRIER))
-		nvt_dbg("WTF? Carrier frequency out of range!");
-
-	nvt_dbg("Carrier frequency: %u (count %u, duration %u)",
-		carrier, count, duration);
-
-	return carrier;
-}
-
-/*
- * set carrier frequency
- *
- * set carrier on 2 registers: CP & CC
- * always set CP as 0x81
- * set CC by SPEC, CC = 3MHz/carrier - 1
- */
-static int nvt_set_tx_carrier(void *data, u32 carrier)
-{
-	struct nvt_dev *nvt = data;
-	u16 val;
-
-	nvt_cir_reg_write(nvt, 1, CIR_CP);
-	val = 3000000 / (carrier) - 1;
-	nvt_cir_reg_write(nvt, val & 0xff, CIR_CC);
-
-	nvt_dbg("cp: 0x%x cc: 0x%x\n",
-		nvt_cir_reg_read(nvt, CIR_CP), nvt_cir_reg_read(nvt, CIR_CC));
-
-	return 0;
-}
-
-/*
- * nvt_tx_ir
- *
- * 1) clean TX fifo first (handled by AP)
- * 2) copy data from user space
- * 3) disable RX interrupts, enable TX interrupts: TTR & TFU
- * 4) send 9 packets to TX FIFO to open TTR
- * in interrupt_handler:
- * 5) send all data out
- * go back to write():
- * 6) disable TX interrupts, re-enable RX interupts
- *
- * The key problem of this function is user space data may larger than
- * driver's data buf length. So nvt_tx_ir() will only copy TX_BUF_LEN data to
- * buf, and keep current copied data buf num in cur_buf_num. But driver's buf
- * number may larger than TXFCONT (0xff). So in interrupt_handler, it has to
- * set TXFCONT as 0xff, until buf_count less than 0xff.
- */
-static int nvt_tx_ir(void *priv, int *txbuf, u32 n)
-{
-	struct nvt_dev *nvt = priv;
-	unsigned long flags;
-	size_t cur_count;
-	unsigned int i;
-	u8 iren;
-	int ret;
-
-	spin_lock_irqsave(&nvt->tx.lock, flags);
-
-	if (n >= TX_BUF_LEN) {
-		nvt->tx.buf_count = cur_count = TX_BUF_LEN;
-		ret = TX_BUF_LEN;
-	} else {
-		nvt->tx.buf_count = cur_count = n;
-		ret = n;
-	}
-
-	memcpy(nvt->tx.buf, txbuf, nvt->tx.buf_count);
-
-	nvt->tx.cur_buf_num = 0;
-
-	/* save currently enabled interrupts */
-	iren = nvt_cir_reg_read(nvt, CIR_IREN);
-
-	/* now disable all interrupts, save TFU & TTR */
-	nvt_cir_reg_write(nvt, CIR_IREN_TFU | CIR_IREN_TTR, CIR_IREN);
-
-	nvt->tx.tx_state = ST_TX_REPLY;
-
-	nvt_cir_reg_write(nvt, CIR_FIFOCON_TX_TRIGGER_LEV_8 |
-			  CIR_FIFOCON_RXFIFOCLR, CIR_FIFOCON);
-
-	/* trigger TTR interrupt by writing out ones, (yes, it's ugly) */
-	for (i = 0; i < 9; i++)
-		nvt_cir_reg_write(nvt, 0x01, CIR_STXFIFO);
-
-	spin_unlock_irqrestore(&nvt->tx.lock, flags);
-
-	wait_event(nvt->tx.queue, nvt->tx.tx_state == ST_TX_REQUEST);
-
-	spin_lock_irqsave(&nvt->tx.lock, flags);
-	nvt->tx.tx_state = ST_TX_NONE;
-	spin_unlock_irqrestore(&nvt->tx.lock, flags);
-
-	/* restore enabled interrupts to prior state */
-	nvt_cir_reg_write(nvt, iren, CIR_IREN);
-
-	return ret;
-}
-
-/* dump contents of the last rx buffer we got from the hw rx fifo */
-static void nvt_dump_rx_buf(struct nvt_dev *nvt)
-{
-	int i;
-
-	printk(KERN_DEBUG "%s (len %d): ", __func__, nvt->pkts);
-	for (i = 0; (i < nvt->pkts) && (i < RX_BUF_LEN); i++)
-		printk(KERN_CONT "0x%02x ", nvt->buf[i]);
-	printk(KERN_CONT "\n");
-}
-
-/*
- * Process raw data in rx driver buffer, store it in raw IR event kfifo,
- * trigger decode when appropriate.
- *
- * We get IR data samples one byte at a time. If the msb is set, its a pulse,
- * otherwise its a space. The lower 7 bits are the count of SAMPLE_PERIOD
- * (default 50us) intervals for that pulse/space. A discrete signal is
- * followed by a series of 0x7f packets, then either 0x7<something> or 0x80
- * to signal more IR coming (repeats) or end of IR, respectively. We store
- * sample data in the raw event kfifo until we see 0x7<something> (except f)
- * or 0x80, at which time, we trigger a decode operation.
- */
-static void nvt_process_rx_ir_data(struct nvt_dev *nvt)
-{
-	DEFINE_IR_RAW_EVENT(rawir);
-	unsigned int count;
-	u32 carrier;
-	u8 sample;
-	int i;
-
-	nvt_dbg_verbose("%s firing", __func__);
-
-	if (debug)
-		nvt_dump_rx_buf(nvt);
-
-	if (nvt->carrier_detect_enabled)
-		carrier = nvt_rx_carrier_detect(nvt);
-
-	count = nvt->pkts;
-	nvt_dbg_verbose("Processing buffer of len %d", count);
-
-	init_ir_raw_event(&rawir);
-
-	for (i = 0; i < count; i++) {
-		nvt->pkts--;
-		sample = nvt->buf[i];
-
-		rawir.pulse = ((sample & BUF_PULSE_BIT) != 0);
-		rawir.duration = (sample & BUF_LEN_MASK)
-					* SAMPLE_PERIOD * 1000;
-
-		if ((sample & BUF_LEN_MASK) == BUF_LEN_MASK) {
-			if (nvt->rawir.pulse == rawir.pulse)
-				nvt->rawir.duration += rawir.duration;
-			else {
-				nvt->rawir.duration = rawir.duration;
-				nvt->rawir.pulse = rawir.pulse;
-			}
-			continue;
-		}
-
-		rawir.duration += nvt->rawir.duration;
-
-		init_ir_raw_event(&nvt->rawir);
-		nvt->rawir.duration = 0;
-		nvt->rawir.pulse = rawir.pulse;
-
-		if (sample == BUF_PULSE_BIT)
-			rawir.pulse = false;
-
-		if (rawir.duration) {
-			nvt_dbg("Storing %s with duration %d",
-				rawir.pulse ? "pulse" : "space",
-				rawir.duration);
-
-			ir_raw_event_store(nvt->rdev, &rawir);
-		}
-
-		/*
-		 * BUF_PULSE_BIT indicates end of IR data, BUF_REPEAT_BYTE
-		 * indicates end of IR signal, but new data incoming. In both
-		 * cases, it means we're ready to call ir_raw_event_handle
-		 */
-		if ((sample == BUF_PULSE_BIT) && nvt->pkts) {
-			nvt_dbg("Calling ir_raw_event_handle (signal end)\n");
-			ir_raw_event_handle(nvt->rdev);
-		}
-	}
-
-	nvt_dbg("Calling ir_raw_event_handle (buffer empty)\n");
-	ir_raw_event_handle(nvt->rdev);
-
-	if (nvt->pkts) {
-		nvt_dbg("Odd, pkts should be 0 now... (its %u)", nvt->pkts);
-		nvt->pkts = 0;
-	}
-
-	nvt_dbg_verbose("%s done", __func__);
-}
-
-static void nvt_handle_rx_fifo_overrun(struct nvt_dev *nvt)
-{
-	nvt_pr(KERN_WARNING, "RX FIFO overrun detected, flushing data!");
-
-	nvt->pkts = 0;
-	nvt_clear_cir_fifo(nvt);
-	ir_raw_event_reset(nvt->rdev);
-}
-
-/* copy data from hardware rx fifo into driver buffer */
-static void nvt_get_rx_ir_data(struct nvt_dev *nvt)
-{
-	unsigned long flags;
-	u8 fifocount, val;
-	unsigned int b_idx;
-	bool overrun = false;
-	int i;
-
-	/* Get count of how many bytes to read from RX FIFO */
-	fifocount = nvt_cir_reg_read(nvt, CIR_RXFCONT);
-	/* if we get 0xff, probably means the logical dev is disabled */
-	if (fifocount == 0xff)
-		return;
-	/* watch out for a fifo overrun condition */
-	else if (fifocount > RX_BUF_LEN) {
-		overrun = true;
-		fifocount = RX_BUF_LEN;
-	}
-
-	nvt_dbg("attempting to fetch %u bytes from hw rx fifo", fifocount);
-
-	spin_lock_irqsave(&nvt->nvt_lock, flags);
-
-	b_idx = nvt->pkts;
-
-	/* This should never happen, but lets check anyway... */
-	if (b_idx + fifocount > RX_BUF_LEN) {
-		nvt_process_rx_ir_data(nvt);
-		b_idx = 0;
-	}
-
-	/* Read fifocount bytes from CIR Sample RX FIFO register */
-	for (i = 0; i < fifocount; i++) {
-		val = nvt_cir_reg_read(nvt, CIR_SRXFIFO);
-		nvt->buf[b_idx + i] = val;
-	}
-
-	nvt->pkts += fifocount;
-	nvt_dbg("%s: pkts now %d", __func__, nvt->pkts);
-
-	nvt_process_rx_ir_data(nvt);
-
-	if (overrun)
-		nvt_handle_rx_fifo_overrun(nvt);
-
-	spin_unlock_irqrestore(&nvt->nvt_lock, flags);
-}
-
-static void nvt_cir_log_irqs(u8 status, u8 iren)
-{
-	nvt_pr(KERN_INFO, "IRQ 0x%02x (IREN 0x%02x) :%s%s%s%s%s%s%s%s%s",
-		status, iren,
-		status & CIR_IRSTS_RDR	? " RDR"	: "",
-		status & CIR_IRSTS_RTR	? " RTR"	: "",
-		status & CIR_IRSTS_PE	? " PE"		: "",
-		status & CIR_IRSTS_RFO	? " RFO"	: "",
-		status & CIR_IRSTS_TE	? " TE"		: "",
-		status & CIR_IRSTS_TTR	? " TTR"	: "",
-		status & CIR_IRSTS_TFU	? " TFU"	: "",
-		status & CIR_IRSTS_GH	? " GH"		: "",
-		status & ~(CIR_IRSTS_RDR | CIR_IRSTS_RTR | CIR_IRSTS_PE |
-			   CIR_IRSTS_RFO | CIR_IRSTS_TE | CIR_IRSTS_TTR |
-			   CIR_IRSTS_TFU | CIR_IRSTS_GH) ? " ?" : "");
-}
-
-static bool nvt_cir_tx_inactive(struct nvt_dev *nvt)
-{
-	unsigned long flags;
-	bool tx_inactive;
-	u8 tx_state;
-
-	spin_lock_irqsave(&nvt->tx.lock, flags);
-	tx_state = nvt->tx.tx_state;
-	spin_unlock_irqrestore(&nvt->tx.lock, flags);
-
-	tx_inactive = (tx_state == ST_TX_NONE);
-
-	return tx_inactive;
-}
-
-/* interrupt service routine for incoming and outgoing CIR data */
-static irqreturn_t nvt_cir_isr(int irq, void *data)
-{
-	struct nvt_dev *nvt = data;
-	u8 status, iren, cur_state;
-	unsigned long flags;
-
-	nvt_dbg_verbose("%s firing", __func__);
-
-	nvt_efm_enable(nvt);
-	nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR);
-	nvt_efm_disable(nvt);
-
-	/*
-	 * Get IR Status register contents. Write 1 to ack/clear
-	 *
-	 * bit: reg name      - description
-	 *   7: CIR_IRSTS_RDR - RX Data Ready
-	 *   6: CIR_IRSTS_RTR - RX FIFO Trigger Level Reach
-	 *   5: CIR_IRSTS_PE  - Packet End
-	 *   4: CIR_IRSTS_RFO - RX FIFO Overrun (RDR will also be set)
-	 *   3: CIR_IRSTS_TE  - TX FIFO Empty
-	 *   2: CIR_IRSTS_TTR - TX FIFO Trigger Level Reach
-	 *   1: CIR_IRSTS_TFU - TX FIFO Underrun
-	 *   0: CIR_IRSTS_GH  - Min Length Detected
-	 */
-	status = nvt_cir_reg_read(nvt, CIR_IRSTS);
-	if (!status) {
-		nvt_dbg_verbose("%s exiting, IRSTS 0x0", __func__);
-		nvt_cir_reg_write(nvt, 0xff, CIR_IRSTS);
-		return IRQ_RETVAL(IRQ_NONE);
-	}
-
-	/* ack/clear all irq flags we've got */
-	nvt_cir_reg_write(nvt, status, CIR_IRSTS);
-	nvt_cir_reg_write(nvt, 0, CIR_IRSTS);
-
-	/* Interrupt may be shared with CIR Wake, bail if CIR not enabled */
-	iren = nvt_cir_reg_read(nvt, CIR_IREN);
-	if (!iren) {
-		nvt_dbg_verbose("%s exiting, CIR not enabled", __func__);
-		return IRQ_RETVAL(IRQ_NONE);
-	}
-
-	if (debug)
-		nvt_cir_log_irqs(status, iren);
-
-	if (status & CIR_IRSTS_RTR) {
-		/* FIXME: add code for study/learn mode */
-		/* We only do rx if not tx'ing */
-		if (nvt_cir_tx_inactive(nvt))
-			nvt_get_rx_ir_data(nvt);
-	}
-
-	if (status & CIR_IRSTS_PE) {
-		if (nvt_cir_tx_inactive(nvt))
-			nvt_get_rx_ir_data(nvt);
-
-		spin_lock_irqsave(&nvt->nvt_lock, flags);
-
-		cur_state = nvt->study_state;
-
-		spin_unlock_irqrestore(&nvt->nvt_lock, flags);
-
-		if (cur_state == ST_STUDY_NONE)
-			nvt_clear_cir_fifo(nvt);
-	}
-
-	if (status & CIR_IRSTS_TE)
-		nvt_clear_tx_fifo(nvt);
-
-	if (status & CIR_IRSTS_TTR) {
-		unsigned int pos, count;
-		u8 tmp;
-
-		spin_lock_irqsave(&nvt->tx.lock, flags);
-
-		pos = nvt->tx.cur_buf_num;
-		count = nvt->tx.buf_count;
-
-		/* Write data into the hardware tx fifo while pos < count */
-		if (pos < count) {
-			nvt_cir_reg_write(nvt, nvt->tx.buf[pos], CIR_STXFIFO);
-			nvt->tx.cur_buf_num++;
-		/* Disable TX FIFO Trigger Level Reach (TTR) interrupt */
-		} else {
-			tmp = nvt_cir_reg_read(nvt, CIR_IREN);
-			nvt_cir_reg_write(nvt, tmp & ~CIR_IREN_TTR, CIR_IREN);
-		}
-
-		spin_unlock_irqrestore(&nvt->tx.lock, flags);
-
-	}
-
-	if (status & CIR_IRSTS_TFU) {
-		spin_lock_irqsave(&nvt->tx.lock, flags);
-		if (nvt->tx.tx_state == ST_TX_REPLY) {
-			nvt->tx.tx_state = ST_TX_REQUEST;
-			wake_up(&nvt->tx.queue);
-		}
-		spin_unlock_irqrestore(&nvt->tx.lock, flags);
-	}
-
-	nvt_dbg_verbose("%s done", __func__);
-	return IRQ_RETVAL(IRQ_HANDLED);
-}
-
-/* Interrupt service routine for CIR Wake */
-static irqreturn_t nvt_cir_wake_isr(int irq, void *data)
-{
-	u8 status, iren, val;
-	struct nvt_dev *nvt = data;
-	unsigned long flags;
-
-	nvt_dbg_wake("%s firing", __func__);
-
-	status = nvt_cir_wake_reg_read(nvt, CIR_WAKE_IRSTS);
-	if (!status)
-		return IRQ_RETVAL(IRQ_NONE);
-
-	if (status & CIR_WAKE_IRSTS_IR_PENDING)
-		nvt_clear_cir_wake_fifo(nvt);
-
-	nvt_cir_wake_reg_write(nvt, status, CIR_WAKE_IRSTS);
-	nvt_cir_wake_reg_write(nvt, 0, CIR_WAKE_IRSTS);
-
-	/* Interrupt may be shared with CIR, bail if Wake not enabled */
-	iren = nvt_cir_wake_reg_read(nvt, CIR_WAKE_IREN);
-	if (!iren) {
-		nvt_dbg_wake("%s exiting, wake not enabled", __func__);
-		return IRQ_RETVAL(IRQ_HANDLED);
-	}
-
-	if ((status & CIR_WAKE_IRSTS_PE) &&
-	    (nvt->wake_state == ST_WAKE_START)) {
-		while (nvt_cir_wake_reg_read(nvt, CIR_WAKE_RD_FIFO_ONLY_IDX)) {
-			val = nvt_cir_wake_reg_read(nvt, CIR_WAKE_RD_FIFO_ONLY);
-			nvt_dbg("setting wake up key: 0x%x", val);
-		}
-
-		nvt_cir_wake_reg_write(nvt, 0, CIR_WAKE_IREN);
-		spin_lock_irqsave(&nvt->nvt_lock, flags);
-		nvt->wake_state = ST_WAKE_FINISH;
-		spin_unlock_irqrestore(&nvt->nvt_lock, flags);
-	}
-
-	nvt_dbg_wake("%s done", __func__);
-	return IRQ_RETVAL(IRQ_HANDLED);
-}
-
-static void nvt_enable_cir(struct nvt_dev *nvt)
-{
-	/* set function enable flags */
-	nvt_cir_reg_write(nvt, CIR_IRCON_TXEN | CIR_IRCON_RXEN |
-			  CIR_IRCON_RXINV | CIR_IRCON_SAMPLE_PERIOD_SEL,
-			  CIR_IRCON);
-
-	nvt_efm_enable(nvt);
-
-	/* enable the CIR logical device */
-	nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR);
-	nvt_cr_write(nvt, LOGICAL_DEV_ENABLE, CR_LOGICAL_DEV_EN);
-
-	nvt_efm_disable(nvt);
-
-	/* clear all pending interrupts */
-	nvt_cir_reg_write(nvt, 0xff, CIR_IRSTS);
-
-	/* enable interrupts */
-	nvt_set_cir_iren(nvt);
-}
-
-static void nvt_disable_cir(struct nvt_dev *nvt)
-{
-	/* disable CIR interrupts */
-	nvt_cir_reg_write(nvt, 0, CIR_IREN);
-
-	/* clear any and all pending interrupts */
-	nvt_cir_reg_write(nvt, 0xff, CIR_IRSTS);
-
-	/* clear all function enable flags */
-	nvt_cir_reg_write(nvt, 0, CIR_IRCON);
-
-	/* clear hardware rx and tx fifos */
-	nvt_clear_cir_fifo(nvt);
-	nvt_clear_tx_fifo(nvt);
-
-	nvt_efm_enable(nvt);
-
-	/* disable the CIR logical device */
-	nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR);
-	nvt_cr_write(nvt, LOGICAL_DEV_DISABLE, CR_LOGICAL_DEV_EN);
-
-	nvt_efm_disable(nvt);
-}
-
-static int nvt_open(void *data)
-{
-	struct nvt_dev *nvt = (struct nvt_dev *)data;
-	unsigned long flags;
-
-	spin_lock_irqsave(&nvt->nvt_lock, flags);
-	nvt->in_use = true;
-	nvt_enable_cir(nvt);
-	spin_unlock_irqrestore(&nvt->nvt_lock, flags);
-
-	return 0;
-}
-
-static void nvt_close(void *data)
-{
-	struct nvt_dev *nvt = (struct nvt_dev *)data;
-	unsigned long flags;
-
-	spin_lock_irqsave(&nvt->nvt_lock, flags);
-	nvt->in_use = false;
-	nvt_disable_cir(nvt);
-	spin_unlock_irqrestore(&nvt->nvt_lock, flags);
-}
-
-/* Allocate memory, probe hardware, and initialize everything */
-static int nvt_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id)
-{
-	struct nvt_dev *nvt = NULL;
-	struct input_dev *rdev = NULL;
-	struct ir_dev_props *props = NULL;
-	int ret = -ENOMEM;
-
-	nvt = kzalloc(sizeof(struct nvt_dev), GFP_KERNEL);
-	if (!nvt)
-		return ret;
-
-	props = kzalloc(sizeof(struct ir_dev_props), GFP_KERNEL);
-	if (!props)
-		goto failure;
-
-	/* input device for IR remote (and tx) */
-	rdev = input_allocate_device();
-	if (!rdev)
-		goto failure;
-
-	ret = -ENODEV;
-	/* validate pnp resources */
-	if (!pnp_port_valid(pdev, 0) ||
-	    pnp_port_len(pdev, 0) < CIR_IOREG_LENGTH) {
-		dev_err(&pdev->dev, "IR PNP Port not valid!\n");
-		goto failure;
-	}
-
-	if (!pnp_irq_valid(pdev, 0)) {
-		dev_err(&pdev->dev, "PNP IRQ not valid!\n");
-		goto failure;
-	}
-
-	if (!pnp_port_valid(pdev, 1) ||
-	    pnp_port_len(pdev, 1) < CIR_IOREG_LENGTH) {
-		dev_err(&pdev->dev, "Wake PNP Port not valid!\n");
-		goto failure;
-	}
-
-	nvt->cir_addr = pnp_port_start(pdev, 0);
-	nvt->cir_irq  = pnp_irq(pdev, 0);
-
-	nvt->cir_wake_addr = pnp_port_start(pdev, 1);
-	/* irq is always shared between cir and cir wake */
-	nvt->cir_wake_irq  = nvt->cir_irq;
-
-	nvt->cr_efir = CR_EFIR;
-	nvt->cr_efdr = CR_EFDR;
-
-	spin_lock_init(&nvt->nvt_lock);
-	spin_lock_init(&nvt->tx.lock);
-	init_ir_raw_event(&nvt->rawir);
-
-	ret = -EBUSY;
-	/* now claim resources */
-	if (!request_region(nvt->cir_addr,
-			    CIR_IOREG_LENGTH, NVT_DRIVER_NAME))
-		goto failure;
-
-	if (request_irq(nvt->cir_irq, nvt_cir_isr, IRQF_SHARED,
-			NVT_DRIVER_NAME, (void *)nvt))
-		goto failure;
-
-	if (!request_region(nvt->cir_wake_addr,
-			    CIR_IOREG_LENGTH, NVT_DRIVER_NAME))
-		goto failure;
-
-	if (request_irq(nvt->cir_wake_irq, nvt_cir_wake_isr, IRQF_SHARED,
-			NVT_DRIVER_NAME, (void *)nvt))
-		goto failure;
-
-	pnp_set_drvdata(pdev, nvt);
-	nvt->pdev = pdev;
-
-	init_waitqueue_head(&nvt->tx.queue);
-
-	ret = nvt_hw_detect(nvt);
-	if (ret)
-		goto failure;
-
-	/* Initialize CIR & CIR Wake Logical Devices */
-	nvt_efm_enable(nvt);
-	nvt_cir_ldev_init(nvt);
-	nvt_cir_wake_ldev_init(nvt);
-	nvt_efm_disable(nvt);
-
-	/* Initialize CIR & CIR Wake Config Registers */
-	nvt_cir_regs_init(nvt);
-	nvt_cir_wake_regs_init(nvt);
-
-	/* Set up ir-core props */
-	props->priv = nvt;
-	props->driver_type = RC_DRIVER_IR_RAW;
-	props->allowed_protos = IR_TYPE_ALL;
-	props->open = nvt_open;
-	props->close = nvt_close;
-#if 0
-	props->min_timeout = XYZ;
-	props->max_timeout = XYZ;
-	props->timeout = XYZ;
-	/* rx resolution is hardwired to 50us atm, 1, 25, 100 also possible */
-	props->rx_resolution = XYZ;
-
-	/* tx bits */
-	props->tx_resolution = XYZ;
-#endif
-	props->tx_ir = nvt_tx_ir;
-	props->s_tx_carrier = nvt_set_tx_carrier;
-
-	rdev->name = "Nuvoton w836x7hg Infrared Remote Transceiver";
-	rdev->id.bustype = BUS_HOST;
-	rdev->id.vendor = PCI_VENDOR_ID_WINBOND2;
-	rdev->id.product = nvt->chip_major;
-	rdev->id.version = nvt->chip_minor;
-
-	nvt->props = props;
-	nvt->rdev = rdev;
-
-	device_set_wakeup_capable(&pdev->dev, 1);
-	device_set_wakeup_enable(&pdev->dev, 1);
-
-	ret = ir_input_register(rdev, RC_MAP_RC6_MCE, props, NVT_DRIVER_NAME);
-	if (ret)
-		goto failure;
-
-	nvt_pr(KERN_NOTICE, "driver has been successfully loaded\n");
-	if (debug) {
-		cir_dump_regs(nvt);
-		cir_wake_dump_regs(nvt);
-	}
-
-	return 0;
-
-failure:
-	if (nvt->cir_irq)
-		free_irq(nvt->cir_irq, nvt);
-	if (nvt->cir_addr)
-		release_region(nvt->cir_addr, CIR_IOREG_LENGTH);
-
-	if (nvt->cir_wake_irq)
-		free_irq(nvt->cir_wake_irq, nvt);
-	if (nvt->cir_wake_addr)
-		release_region(nvt->cir_wake_addr, CIR_IOREG_LENGTH);
-
-	input_free_device(rdev);
-	kfree(props);
-	kfree(nvt);
-
-	return ret;
-}
-
-static void __devexit nvt_remove(struct pnp_dev *pdev)
-{
-	struct nvt_dev *nvt = pnp_get_drvdata(pdev);
-	unsigned long flags;
-
-	spin_lock_irqsave(&nvt->nvt_lock, flags);
-	/* disable CIR */
-	nvt_cir_reg_write(nvt, 0, CIR_IREN);
-	nvt_disable_cir(nvt);
-	/* enable CIR Wake (for IR power-on) */
-	nvt_enable_wake(nvt);
-	spin_unlock_irqrestore(&nvt->nvt_lock, flags);
-
-	/* free resources */
-	free_irq(nvt->cir_irq, nvt);
-	free_irq(nvt->cir_wake_irq, nvt);
-	release_region(nvt->cir_addr, CIR_IOREG_LENGTH);
-	release_region(nvt->cir_wake_addr, CIR_IOREG_LENGTH);
-
-	ir_input_unregister(nvt->rdev);
-
-	kfree(nvt->props);
-	kfree(nvt);
-}
-
-static int nvt_suspend(struct pnp_dev *pdev, pm_message_t state)
-{
-	struct nvt_dev *nvt = pnp_get_drvdata(pdev);
-	unsigned long flags;
-
-	nvt_dbg("%s called", __func__);
-
-	/* zero out misc state tracking */
-	spin_lock_irqsave(&nvt->nvt_lock, flags);
-	nvt->study_state = ST_STUDY_NONE;
-	nvt->wake_state = ST_WAKE_NONE;
-	spin_unlock_irqrestore(&nvt->nvt_lock, flags);
-
-	spin_lock_irqsave(&nvt->tx.lock, flags);
-	nvt->tx.tx_state = ST_TX_NONE;
-	spin_unlock_irqrestore(&nvt->tx.lock, flags);
-
-	/* disable all CIR interrupts */
-	nvt_cir_reg_write(nvt, 0, CIR_IREN);
-
-	nvt_efm_enable(nvt);
-
-	/* disable cir logical dev */
-	nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR);
-	nvt_cr_write(nvt, LOGICAL_DEV_DISABLE, CR_LOGICAL_DEV_EN);
-
-	nvt_efm_disable(nvt);
-
-	/* make sure wake is enabled */
-	nvt_enable_wake(nvt);
-
-	return 0;
-}
-
-static int nvt_resume(struct pnp_dev *pdev)
-{
-	int ret = 0;
-	struct nvt_dev *nvt = pnp_get_drvdata(pdev);
-
-	nvt_dbg("%s called", __func__);
-
-	/* open interrupt */
-	nvt_set_cir_iren(nvt);
-
-	/* Enable CIR logical device */
-	nvt_efm_enable(nvt);
-	nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR);
-	nvt_cr_write(nvt, LOGICAL_DEV_ENABLE, CR_LOGICAL_DEV_EN);
-
-	nvt_efm_disable(nvt);
-
-	nvt_cir_regs_init(nvt);
-	nvt_cir_wake_regs_init(nvt);
-
-	return ret;
-}
-
-static void nvt_shutdown(struct pnp_dev *pdev)
-{
-	struct nvt_dev *nvt = pnp_get_drvdata(pdev);
-	nvt_enable_wake(nvt);
-}
-
-static const struct pnp_device_id nvt_ids[] = {
-	{ "WEC0530", 0 },   /* CIR */
-	{ "NTN0530", 0 },   /* CIR for new chip's pnp id*/
-	{ "", 0 },
-};
-
-static struct pnp_driver nvt_driver = {
-	.name		= NVT_DRIVER_NAME,
-	.id_table	= nvt_ids,
-	.flags		= PNP_DRIVER_RES_DO_NOT_CHANGE,
-	.probe		= nvt_probe,
-	.remove		= __devexit_p(nvt_remove),
-	.suspend	= nvt_suspend,
-	.resume		= nvt_resume,
-	.shutdown	= nvt_shutdown,
-};
-
-int nvt_init(void)
-{
-	return pnp_register_driver(&nvt_driver);
-}
-
-void nvt_exit(void)
-{
-	pnp_unregister_driver(&nvt_driver);
-}
-
-module_param(debug, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(debug, "Enable debugging output");
-
-MODULE_DEVICE_TABLE(pnp, nvt_ids);
-MODULE_DESCRIPTION("Nuvoton W83667HG-A & W83677HG-I CIR driver");
-
-MODULE_AUTHOR("Jarod Wilson <jarod@redhat.com>");
-MODULE_LICENSE("GPL");
-
-module_init(nvt_init);
-module_exit(nvt_exit);
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/nuvoton-cir.h linux-libre-2.6.38-gnu1/drivers/media/IR/nuvoton-cir.h
--- linux-libre-2.6.37-gnu1/drivers/media/IR/nuvoton-cir.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/nuvoton-cir.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,408 +0,0 @@
-/*
- * Driver for Nuvoton Technology Corporation w83667hg/w83677hg-i CIR
- *
- * Copyright (C) 2010 Jarod Wilson <jarod@redhat.com>
- * Copyright (C) 2009 Nuvoton PS Team
- *
- * Special thanks to Nuvoton for providing hardware, spec sheets and
- * sample code upon which portions of this driver are based. Indirect
- * thanks also to Maxim Levitsky, whose ene_ir driver this driver is
- * modeled after.
- *
- * 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/spinlock.h>
-#include <linux/ioctl.h>
-
-/* platform driver name to register */
-#define NVT_DRIVER_NAME "nuvoton-cir"
-
-/* debugging module parameter */
-static int debug;
-
-
-#define nvt_pr(level, text, ...) \
-	printk(level KBUILD_MODNAME ": " text, ## __VA_ARGS__)
-
-#define nvt_dbg(text, ...) \
-	if (debug) \
-		printk(KERN_DEBUG \
-			KBUILD_MODNAME ": " text "\n" , ## __VA_ARGS__)
-
-#define nvt_dbg_verbose(text, ...) \
-	if (debug > 1) \
-		printk(KERN_DEBUG \
-			KBUILD_MODNAME ": " text "\n" , ## __VA_ARGS__)
-
-#define nvt_dbg_wake(text, ...) \
-	if (debug > 2) \
-		printk(KERN_DEBUG \
-			KBUILD_MODNAME ": " text "\n" , ## __VA_ARGS__)
-
-
-/*
- * Original lirc driver said min value of 76, and recommended value of 256
- * for the buffer length, but then used 2048. Never mind that the size of the
- * RX FIFO is 32 bytes... So I'm using 32 for RX and 256 for TX atm, but I'm
- * not sure if maybe that TX value is off by a factor of 8 (bits vs. bytes),
- * and I don't have TX-capable hardware to test/debug on...
- */
-#define TX_BUF_LEN 256
-#define RX_BUF_LEN 32
-
-struct nvt_dev {
-	struct pnp_dev *pdev;
-	struct input_dev *rdev;
-	struct ir_dev_props *props;
-	struct ir_raw_event rawir;
-
-	spinlock_t nvt_lock;
-	bool in_use;
-
-	/* for rx */
-	u8 buf[RX_BUF_LEN];
-	unsigned int pkts;
-
-	struct {
-		spinlock_t lock;
-		u8 buf[TX_BUF_LEN];
-		unsigned int buf_count;
-		unsigned int cur_buf_num;
-		wait_queue_head_t queue;
-		u8 tx_state;
-	} tx;
-
-	/* EFER Config register index/data pair */
-	u8 cr_efir;
-	u8 cr_efdr;
-
-	/* hardware I/O settings */
-	unsigned long cir_addr;
-	unsigned long cir_wake_addr;
-	int cir_irq;
-	int cir_wake_irq;
-
-	/* hardware id */
-	u8 chip_major;
-	u8 chip_minor;
-
-	/* hardware features */
-	bool hw_learning_capable;
-	bool hw_tx_capable;
-
-	/* rx settings */
-	bool learning_enabled;
-	bool carrier_detect_enabled;
-
-	/* track cir wake state */
-	u8 wake_state;
-	/* for study */
-	u8 study_state;
-	/* carrier period = 1 / frequency */
-	u32 carrier;
-};
-
-/* study states */
-#define ST_STUDY_NONE      0x0
-#define ST_STUDY_START     0x1
-#define ST_STUDY_CARRIER   0x2
-#define ST_STUDY_ALL_RECV  0x4
-
-/* wake states */
-#define ST_WAKE_NONE	0x0
-#define ST_WAKE_START	0x1
-#define ST_WAKE_FINISH	0x2
-
-/* receive states */
-#define ST_RX_WAIT_7F		0x1
-#define ST_RX_WAIT_HEAD		0x2
-#define ST_RX_WAIT_SILENT_END	0x4
-
-/* send states */
-#define ST_TX_NONE	0x0
-#define ST_TX_REQUEST	0x2
-#define ST_TX_REPLY	0x4
-
-/* buffer packet constants */
-#define BUF_PULSE_BIT	0x80
-#define BUF_LEN_MASK	0x7f
-#define BUF_REPEAT_BYTE	0x70
-#define BUF_REPEAT_MASK	0xf0
-
-/* CIR settings */
-
-/* total length of CIR and CIR WAKE */
-#define CIR_IOREG_LENGTH	0x0f
-
-/* RX limit length, 8 high bits for SLCH, 8 low bits for SLCL (0x7d0 = 2000) */
-#define CIR_RX_LIMIT_COUNT	0x7d0
-
-/* CIR Regs */
-#define CIR_IRCON	0x00
-#define CIR_IRSTS	0x01
-#define CIR_IREN	0x02
-#define CIR_RXFCONT	0x03
-#define CIR_CP		0x04
-#define CIR_CC		0x05
-#define CIR_SLCH	0x06
-#define CIR_SLCL	0x07
-#define CIR_FIFOCON	0x08
-#define CIR_IRFIFOSTS	0x09
-#define CIR_SRXFIFO	0x0a
-#define CIR_TXFCONT	0x0b
-#define CIR_STXFIFO	0x0c
-#define CIR_FCCH	0x0d
-#define CIR_FCCL	0x0e
-#define CIR_IRFSM	0x0f
-
-/* CIR IRCON settings */
-#define CIR_IRCON_RECV	 0x80
-#define CIR_IRCON_WIREN	 0x40
-#define CIR_IRCON_TXEN	 0x20
-#define CIR_IRCON_RXEN	 0x10
-#define CIR_IRCON_WRXINV 0x08
-#define CIR_IRCON_RXINV	 0x04
-
-#define CIR_IRCON_SAMPLE_PERIOD_SEL_1	0x00
-#define CIR_IRCON_SAMPLE_PERIOD_SEL_25	0x01
-#define CIR_IRCON_SAMPLE_PERIOD_SEL_50	0x02
-#define CIR_IRCON_SAMPLE_PERIOD_SEL_100	0x03
-
-/* FIXME: make this a runtime option */
-/* select sample period as 50us */
-#define CIR_IRCON_SAMPLE_PERIOD_SEL	CIR_IRCON_SAMPLE_PERIOD_SEL_50
-
-/* CIR IRSTS settings */
-#define CIR_IRSTS_RDR	0x80
-#define CIR_IRSTS_RTR	0x40
-#define CIR_IRSTS_PE	0x20
-#define CIR_IRSTS_RFO	0x10
-#define CIR_IRSTS_TE	0x08
-#define CIR_IRSTS_TTR	0x04
-#define CIR_IRSTS_TFU	0x02
-#define CIR_IRSTS_GH	0x01
-
-/* CIR IREN settings */
-#define CIR_IREN_RDR	0x80
-#define CIR_IREN_RTR	0x40
-#define CIR_IREN_PE	0x20
-#define CIR_IREN_RFO	0x10
-#define CIR_IREN_TE	0x08
-#define CIR_IREN_TTR	0x04
-#define CIR_IREN_TFU	0x02
-#define CIR_IREN_GH	0x01
-
-/* CIR FIFOCON settings */
-#define CIR_FIFOCON_TXFIFOCLR		0x80
-
-#define CIR_FIFOCON_TX_TRIGGER_LEV_31	0x00
-#define CIR_FIFOCON_TX_TRIGGER_LEV_24	0x10
-#define CIR_FIFOCON_TX_TRIGGER_LEV_16	0x20
-#define CIR_FIFOCON_TX_TRIGGER_LEV_8	0x30
-
-/* FIXME: make this a runtime option */
-/* select TX trigger level as 16 */
-#define CIR_FIFOCON_TX_TRIGGER_LEV	CIR_FIFOCON_TX_TRIGGER_LEV_16
-
-#define CIR_FIFOCON_RXFIFOCLR		0x08
-
-#define CIR_FIFOCON_RX_TRIGGER_LEV_1	0x00
-#define CIR_FIFOCON_RX_TRIGGER_LEV_8	0x01
-#define CIR_FIFOCON_RX_TRIGGER_LEV_16	0x02
-#define CIR_FIFOCON_RX_TRIGGER_LEV_24	0x03
-
-/* FIXME: make this a runtime option */
-/* select RX trigger level as 24 */
-#define CIR_FIFOCON_RX_TRIGGER_LEV	CIR_FIFOCON_RX_TRIGGER_LEV_24
-
-/* CIR IRFIFOSTS settings */
-#define CIR_IRFIFOSTS_IR_PENDING	0x80
-#define CIR_IRFIFOSTS_RX_GS		0x40
-#define CIR_IRFIFOSTS_RX_FTA		0x20
-#define CIR_IRFIFOSTS_RX_EMPTY		0x10
-#define CIR_IRFIFOSTS_RX_FULL		0x08
-#define CIR_IRFIFOSTS_TX_FTA		0x04
-#define CIR_IRFIFOSTS_TX_EMPTY		0x02
-#define CIR_IRFIFOSTS_TX_FULL		0x01
-
-
-/* CIR WAKE UP Regs */
-#define CIR_WAKE_IRCON			0x00
-#define CIR_WAKE_IRSTS			0x01
-#define CIR_WAKE_IREN			0x02
-#define CIR_WAKE_FIFO_CMP_DEEP		0x03
-#define CIR_WAKE_FIFO_CMP_TOL		0x04
-#define CIR_WAKE_FIFO_COUNT		0x05
-#define CIR_WAKE_SLCH			0x06
-#define CIR_WAKE_SLCL			0x07
-#define CIR_WAKE_FIFOCON		0x08
-#define CIR_WAKE_SRXFSTS		0x09
-#define CIR_WAKE_SAMPLE_RX_FIFO		0x0a
-#define CIR_WAKE_WR_FIFO_DATA		0x0b
-#define CIR_WAKE_RD_FIFO_ONLY		0x0c
-#define CIR_WAKE_RD_FIFO_ONLY_IDX	0x0d
-#define CIR_WAKE_FIFO_IGNORE		0x0e
-#define CIR_WAKE_IRFSM			0x0f
-
-/* CIR WAKE UP IRCON settings */
-#define CIR_WAKE_IRCON_DEC_RST		0x80
-#define CIR_WAKE_IRCON_MODE1		0x40
-#define CIR_WAKE_IRCON_MODE0		0x20
-#define CIR_WAKE_IRCON_RXEN		0x10
-#define CIR_WAKE_IRCON_R		0x08
-#define CIR_WAKE_IRCON_RXINV		0x04
-
-/* FIXME/jarod: make this a runtime option */
-/* select a same sample period like cir register */
-#define CIR_WAKE_IRCON_SAMPLE_PERIOD_SEL	CIR_IRCON_SAMPLE_PERIOD_SEL_50
-
-/* CIR WAKE IRSTS Bits */
-#define CIR_WAKE_IRSTS_RDR		0x80
-#define CIR_WAKE_IRSTS_RTR		0x40
-#define CIR_WAKE_IRSTS_PE		0x20
-#define CIR_WAKE_IRSTS_RFO		0x10
-#define CIR_WAKE_IRSTS_GH		0x08
-#define CIR_WAKE_IRSTS_IR_PENDING	0x01
-
-/* CIR WAKE UP IREN Bits */
-#define CIR_WAKE_IREN_RDR		0x80
-#define CIR_WAKE_IREN_RTR		0x40
-#define CIR_WAKE_IREN_PE		0x20
-#define CIR_WAKE_IREN_RFO		0x10
-#define CIR_WAKE_IREN_TE		0x08
-#define CIR_WAKE_IREN_TTR		0x04
-#define CIR_WAKE_IREN_TFU		0x02
-#define CIR_WAKE_IREN_GH		0x01
-
-/* CIR WAKE FIFOCON settings */
-#define CIR_WAKE_FIFOCON_RXFIFOCLR	0x08
-
-#define CIR_WAKE_FIFOCON_RX_TRIGGER_LEV_67	0x00
-#define CIR_WAKE_FIFOCON_RX_TRIGGER_LEV_66	0x01
-#define CIR_WAKE_FIFOCON_RX_TRIGGER_LEV_65	0x02
-#define CIR_WAKE_FIFOCON_RX_TRIGGER_LEV_64	0x03
-
-/* FIXME: make this a runtime option */
-/* select WAKE UP RX trigger level as 67 */
-#define CIR_WAKE_FIFOCON_RX_TRIGGER_LEV	CIR_WAKE_FIFOCON_RX_TRIGGER_LEV_67
-
-/* CIR WAKE SRXFSTS settings */
-#define CIR_WAKE_IRFIFOSTS_RX_GS	0x80
-#define CIR_WAKE_IRFIFOSTS_RX_FTA	0x40
-#define CIR_WAKE_IRFIFOSTS_RX_EMPTY	0x20
-#define CIR_WAKE_IRFIFOSTS_RX_FULL	0x10
-
-/* CIR Wake FIFO buffer is 67 bytes long */
-#define CIR_WAKE_FIFO_LEN		67
-/* CIR Wake byte comparison tolerance */
-#define CIR_WAKE_CMP_TOLERANCE		5
-
-/*
- * Extended Function Enable Registers:
- *  Extended Function Index Register
- *  Extended Function Data Register
- */
-#define CR_EFIR			0x2e
-#define CR_EFDR			0x2f
-
-/* Possible alternate EFER values, depends on how the chip is wired */
-#define CR_EFIR2		0x4e
-#define CR_EFDR2		0x4f
-
-/* Extended Function Mode enable/disable magic values */
-#define EFER_EFM_ENABLE		0x87
-#define EFER_EFM_DISABLE	0xaa
-
-/* Chip IDs found in CR_CHIP_ID_{HI,LO} */
-#define CHIP_ID_HIGH		0xb4
-#define CHIP_ID_LOW		0x72
-#define CHIP_ID_LOW2		0x73
-
-/* Config regs we need to care about */
-#define CR_SOFTWARE_RESET	0x02
-#define CR_LOGICAL_DEV_SEL	0x07
-#define CR_CHIP_ID_HI		0x20
-#define CR_CHIP_ID_LO		0x21
-#define CR_DEV_POWER_DOWN	0x22 /* bit 2 is CIR power, default power on */
-#define CR_OUTPUT_PIN_SEL	0x27
-#define CR_LOGICAL_DEV_EN	0x30 /* valid for all logical devices */
-/* next three regs valid for both the CIR and CIR_WAKE logical devices */
-#define CR_CIR_BASE_ADDR_HI	0x60
-#define CR_CIR_BASE_ADDR_LO	0x61
-#define CR_CIR_IRQ_RSRC		0x70
-/* next three regs valid only for ACPI logical dev */
-#define CR_ACPI_CIR_WAKE	0xe0
-#define CR_ACPI_IRQ_EVENTS	0xf6
-#define CR_ACPI_IRQ_EVENTS2	0xf7
-
-/* Logical devices that we need to care about */
-#define LOGICAL_DEV_LPT		0x01
-#define LOGICAL_DEV_CIR		0x06
-#define LOGICAL_DEV_ACPI	0x0a
-#define LOGICAL_DEV_CIR_WAKE	0x0e
-
-#define LOGICAL_DEV_DISABLE	0x00
-#define LOGICAL_DEV_ENABLE	0x01
-
-#define CIR_WAKE_ENABLE_BIT	0x08
-#define CIR_INTR_MOUSE_IRQ_BIT	0x80
-#define PME_INTR_CIR_PASS_BIT	0x08
-
-#define OUTPUT_PIN_SEL_MASK	0xbc
-#define OUTPUT_ENABLE_CIR	0x01 /* Pin95=CIRRX, Pin96=CIRTX1 */
-#define OUTPUT_ENABLE_CIRWB	0x40 /* enable wide-band sensor */
-
-/* MCE CIR signal length, related on sample period */
-
-/* MCE CIR controller signal length: about 43ms
- * 43ms / 50us (sample period) * 0.85 (inaccuracy)
- */
-#define CONTROLLER_BUF_LEN_MIN 830
-
-/* MCE CIR keyboard signal length: about 26ms
- * 26ms / 50us (sample period) * 0.85 (inaccuracy)
- */
-#define KEYBOARD_BUF_LEN_MAX 650
-#define KEYBOARD_BUF_LEN_MIN 610
-
-/* MCE CIR mouse signal length: about 24ms
- * 24ms / 50us (sample period) * 0.85 (inaccuracy)
- */
-#define MOUSE_BUF_LEN_MIN 565
-
-#define CIR_SAMPLE_PERIOD 50
-#define CIR_SAMPLE_LOW_INACCURACY 0.85
-
-/* MAX silence time that driver will sent to lirc */
-#define MAX_SILENCE_TIME 60000
-
-#if CIR_IRCON_SAMPLE_PERIOD_SEL == CIR_IRCON_SAMPLE_PERIOD_SEL_100
-#define SAMPLE_PERIOD 100
-
-#elif CIR_IRCON_SAMPLE_PERIOD_SEL == CIR_IRCON_SAMPLE_PERIOD_SEL_50
-#define SAMPLE_PERIOD 50
-
-#elif CIR_IRCON_SAMPLE_PERIOD_SEL == CIR_IRCON_SAMPLE_PERIOD_SEL_25
-#define SAMPLE_PERIOD 25
-
-#else
-#define SAMPLE_PERIOD 1
-#endif
-
-/* as VISTA MCE definition, valid carrier value */
-#define MAX_CARRIER 60000
-#define MIN_CARRIER 30000
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/rc-map.c linux-libre-2.6.38-gnu1/drivers/media/IR/rc-map.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/rc-map.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/rc-map.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,107 +0,0 @@
-/* ir-raw-event.c - handle IR Pulse/Space event
- *
- * Copyright (C) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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.
- */
-
-#include <media/ir-core.h>
-#include <linux/spinlock.h>
-#include <linux/delay.h>
-
-/* Used to handle IR raw handler extensions */
-static LIST_HEAD(rc_map_list);
-static DEFINE_SPINLOCK(rc_map_lock);
-
-static struct rc_keymap *seek_rc_map(const char *name)
-{
-	struct rc_keymap *map = NULL;
-
-	spin_lock(&rc_map_lock);
-	list_for_each_entry(map, &rc_map_list, list) {
-		if (!strcmp(name, map->map.name)) {
-			spin_unlock(&rc_map_lock);
-			return map;
-		}
-	}
-	spin_unlock(&rc_map_lock);
-
-	return NULL;
-}
-
-struct ir_scancode_table *get_rc_map(const char *name)
-{
-
-	struct rc_keymap *map;
-
-	map = seek_rc_map(name);
-#ifdef MODULE
-	if (!map) {
-		int rc = request_module(name);
-		if (rc < 0) {
-			printk(KERN_ERR "Couldn't load IR keymap %s\n", name);
-			return NULL;
-		}
-		msleep(20);	/* Give some time for IR to register */
-
-		map = seek_rc_map(name);
-	}
-#endif
-	if (!map) {
-		printk(KERN_ERR "IR keymap %s not found\n", name);
-		return NULL;
-	}
-
-	printk(KERN_INFO "Registered IR keymap %s\n", map->map.name);
-
-	return &map->map;
-}
-EXPORT_SYMBOL_GPL(get_rc_map);
-
-int ir_register_map(struct rc_keymap *map)
-{
-	spin_lock(&rc_map_lock);
-	list_add_tail(&map->list, &rc_map_list);
-	spin_unlock(&rc_map_lock);
-	return 0;
-}
-EXPORT_SYMBOL_GPL(ir_register_map);
-
-void ir_unregister_map(struct rc_keymap *map)
-{
-	spin_lock(&rc_map_lock);
-	list_del(&map->list);
-	spin_unlock(&rc_map_lock);
-}
-EXPORT_SYMBOL_GPL(ir_unregister_map);
-
-
-static struct ir_scancode empty[] = {
-	{ 0x2a, KEY_COFFEE },
-};
-
-static struct rc_keymap empty_map = {
-	.map = {
-		.scan    = empty,
-		.size    = ARRAY_SIZE(empty),
-		.ir_type = IR_TYPE_UNKNOWN,	/* Legacy IR type */
-		.name    = RC_MAP_EMPTY,
-	}
-};
-
-int ir_rcmap_init(void)
-{
-	return ir_register_map(&empty_map);
-}
-
-void ir_rcmap_cleanup(void)
-{
-	ir_unregister_map(&empty_map);
-}
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/IR/streamzap.c linux-libre-2.6.38-gnu1/drivers/media/IR/streamzap.c
--- linux-libre-2.6.37-gnu1/drivers/media/IR/streamzap.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/IR/streamzap.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,572 +0,0 @@
-/*
- * Streamzap Remote Control driver
- *
- * Copyright (c) 2005 Christoph Bartelmus <lirc@bartelmus.de>
- * Copyright (c) 2010 Jarod Wilson <jarod@wilsonet.com>
- *
- * This driver was based on the work of Greg Wickham and Adrian
- * Dewhurst. It was substantially rewritten to support correct signal
- * gaps and now maintains a delay buffer, which is used to present
- * consistent timing behaviour to user space applications. Without the
- * delay buffer an ugly hack would be required in lircd, which can
- * cause sluggish signal decoding in certain situations.
- *
- * Ported to in-kernel ir-core interface by Jarod Wilson
- *
- * This driver is based on the USB skeleton driver packaged with the
- * kernel; copyright (C) 2001-2003 Greg Kroah-Hartman (greg@kroah.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/device.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/input.h>
-#include <linux/usb.h>
-#include <linux/usb/input.h>
-#include <media/ir-core.h>
-
-#define DRIVER_VERSION	"1.61"
-#define DRIVER_NAME	"streamzap"
-#define DRIVER_DESC	"Streamzap Remote Control driver"
-
-#ifdef CONFIG_USB_DEBUG
-static int debug = 1;
-#else
-static int debug;
-#endif
-
-#define USB_STREAMZAP_VENDOR_ID		0x0e9c
-#define USB_STREAMZAP_PRODUCT_ID	0x0000
-
-/* table of devices that work with this driver */
-static struct usb_device_id streamzap_table[] = {
-	/* Streamzap Remote Control */
-	{ USB_DEVICE(USB_STREAMZAP_VENDOR_ID, USB_STREAMZAP_PRODUCT_ID) },
-	/* Terminating entry */
-	{ }
-};
-
-MODULE_DEVICE_TABLE(usb, streamzap_table);
-
-#define SZ_PULSE_MASK 0xf0
-#define SZ_SPACE_MASK 0x0f
-#define SZ_TIMEOUT    0xff
-#define SZ_RESOLUTION 256
-
-/* number of samples buffered */
-#define SZ_BUF_LEN 128
-
-/* from ir-rc5-sz-decoder.c */
-#ifdef CONFIG_IR_RC5_SZ_DECODER_MODULE
-#define load_rc5_sz_decode()    request_module("ir-rc5-sz-decoder")
-#else
-#define load_rc5_sz_decode()    0
-#endif
-
-enum StreamzapDecoderState {
-	PulseSpace,
-	FullPulse,
-	FullSpace,
-	IgnorePulse
-};
-
-/* structure to hold our device specific stuff */
-struct streamzap_ir {
-
-	/* ir-core */
-	struct ir_dev_props *props;
-
-	/* core device info */
-	struct device *dev;
-	struct input_dev *idev;
-
-	/* usb */
-	struct usb_device	*usbdev;
-	struct usb_interface	*interface;
-	struct usb_endpoint_descriptor *endpoint;
-	struct urb		*urb_in;
-
-	/* buffer & dma */
-	unsigned char		*buf_in;
-	dma_addr_t		dma_in;
-	unsigned int		buf_in_len;
-
-	/* track what state we're in */
-	enum StreamzapDecoderState decoder_state;
-	/* tracks whether we are currently receiving some signal */
-	bool			idle;
-	/* sum of signal lengths received since signal start */
-	unsigned long		sum;
-	/* start time of signal; necessary for gap tracking */
-	struct timeval		signal_last;
-	struct timeval		signal_start;
-	bool			timeout_enabled;
-
-	char			name[128];
-	char			phys[64];
-};
-
-
-/* local function prototypes */
-static int streamzap_probe(struct usb_interface *interface,
-			   const struct usb_device_id *id);
-static void streamzap_disconnect(struct usb_interface *interface);
-static void streamzap_callback(struct urb *urb);
-static int streamzap_suspend(struct usb_interface *intf, pm_message_t message);
-static int streamzap_resume(struct usb_interface *intf);
-
-/* usb specific object needed to register this driver with the usb subsystem */
-static struct usb_driver streamzap_driver = {
-	.name =		DRIVER_NAME,
-	.probe =	streamzap_probe,
-	.disconnect =	streamzap_disconnect,
-	.suspend =	streamzap_suspend,
-	.resume =	streamzap_resume,
-	.id_table =	streamzap_table,
-};
-
-static void sz_push(struct streamzap_ir *sz, struct ir_raw_event rawir)
-{
-	dev_dbg(sz->dev, "Storing %s with duration %u us\n",
-		(rawir.pulse ? "pulse" : "space"), rawir.duration);
-	ir_raw_event_store_with_filter(sz->idev, &rawir);
-}
-
-static void sz_push_full_pulse(struct streamzap_ir *sz,
-			       unsigned char value)
-{
-	DEFINE_IR_RAW_EVENT(rawir);
-
-	if (sz->idle) {
-		long deltv;
-
-		sz->signal_last = sz->signal_start;
-		do_gettimeofday(&sz->signal_start);
-
-		deltv = sz->signal_start.tv_sec - sz->signal_last.tv_sec;
-		rawir.pulse = false;
-		if (deltv > 15) {
-			/* really long time */
-			rawir.duration = IR_MAX_DURATION;
-		} else {
-			rawir.duration = (int)(deltv * 1000000 +
-				sz->signal_start.tv_usec -
-				sz->signal_last.tv_usec);
-			rawir.duration -= sz->sum;
-			rawir.duration *= 1000;
-			rawir.duration &= IR_MAX_DURATION;
-		}
-		sz_push(sz, rawir);
-
-		sz->idle = false;
-		sz->sum = 0;
-	}
-
-	rawir.pulse = true;
-	rawir.duration = ((int) value) * SZ_RESOLUTION;
-	rawir.duration += SZ_RESOLUTION / 2;
-	sz->sum += rawir.duration;
-	rawir.duration *= 1000;
-	rawir.duration &= IR_MAX_DURATION;
-	sz_push(sz, rawir);
-}
-
-static void sz_push_half_pulse(struct streamzap_ir *sz,
-			       unsigned char value)
-{
-	sz_push_full_pulse(sz, (value & SZ_PULSE_MASK) >> 4);
-}
-
-static void sz_push_full_space(struct streamzap_ir *sz,
-			       unsigned char value)
-{
-	DEFINE_IR_RAW_EVENT(rawir);
-
-	rawir.pulse = false;
-	rawir.duration = ((int) value) * SZ_RESOLUTION;
-	rawir.duration += SZ_RESOLUTION / 2;
-	sz->sum += rawir.duration;
-	rawir.duration *= 1000;
-	sz_push(sz, rawir);
-}
-
-static void sz_push_half_space(struct streamzap_ir *sz,
-			       unsigned long value)
-{
-	sz_push_full_space(sz, value & SZ_SPACE_MASK);
-}
-
-/**
- * streamzap_callback - usb IRQ handler callback
- *
- * This procedure is invoked on reception of data from
- * the usb remote.
- */
-static void streamzap_callback(struct urb *urb)
-{
-	struct streamzap_ir *sz;
-	unsigned int i;
-	int len;
-
-	if (!urb)
-		return;
-
-	sz = urb->context;
-	len = urb->actual_length;
-
-	switch (urb->status) {
-	case -ECONNRESET:
-	case -ENOENT:
-	case -ESHUTDOWN:
-		/*
-		 * this urb is terminated, clean up.
-		 * sz might already be invalid at this point
-		 */
-		dev_err(sz->dev, "urb terminated, status: %d\n", urb->status);
-		return;
-	default:
-		break;
-	}
-
-	dev_dbg(sz->dev, "%s: received urb, len %d\n", __func__, len);
-	for (i = 0; i < len; i++) {
-		dev_dbg(sz->dev, "sz->buf_in[%d]: %x\n",
-			i, (unsigned char)sz->buf_in[i]);
-		switch (sz->decoder_state) {
-		case PulseSpace:
-			if ((sz->buf_in[i] & SZ_PULSE_MASK) ==
-				SZ_PULSE_MASK) {
-				sz->decoder_state = FullPulse;
-				continue;
-			} else if ((sz->buf_in[i] & SZ_SPACE_MASK)
-					== SZ_SPACE_MASK) {
-				sz_push_half_pulse(sz, sz->buf_in[i]);
-				sz->decoder_state = FullSpace;
-				continue;
-			} else {
-				sz_push_half_pulse(sz, sz->buf_in[i]);
-				sz_push_half_space(sz, sz->buf_in[i]);
-			}
-			break;
-		case FullPulse:
-			sz_push_full_pulse(sz, sz->buf_in[i]);
-			sz->decoder_state = IgnorePulse;
-			break;
-		case FullSpace:
-			if (sz->buf_in[i] == SZ_TIMEOUT) {
-				DEFINE_IR_RAW_EVENT(rawir);
-
-				rawir.pulse = false;
-				rawir.duration = sz->props->timeout;
-				sz->idle = true;
-				if (sz->timeout_enabled)
-					sz_push(sz, rawir);
-				ir_raw_event_handle(sz->idev);
-			} else {
-				sz_push_full_space(sz, sz->buf_in[i]);
-			}
-			sz->decoder_state = PulseSpace;
-			break;
-		case IgnorePulse:
-			if ((sz->buf_in[i] & SZ_SPACE_MASK) ==
-				SZ_SPACE_MASK) {
-				sz->decoder_state = FullSpace;
-				continue;
-			}
-			sz_push_half_space(sz, sz->buf_in[i]);
-			sz->decoder_state = PulseSpace;
-			break;
-		}
-	}
-
-	usb_submit_urb(urb, GFP_ATOMIC);
-
-	return;
-}
-
-static struct input_dev *streamzap_init_input_dev(struct streamzap_ir *sz)
-{
-	struct input_dev *idev;
-	struct ir_dev_props *props;
-	struct device *dev = sz->dev;
-	int ret;
-
-	idev = input_allocate_device();
-	if (!idev) {
-		dev_err(dev, "remote input dev allocation failed\n");
-		goto idev_alloc_failed;
-	}
-
-	props = kzalloc(sizeof(struct ir_dev_props), GFP_KERNEL);
-	if (!props) {
-		dev_err(dev, "remote ir dev props allocation failed\n");
-		goto props_alloc_failed;
-	}
-
-	snprintf(sz->name, sizeof(sz->name), "Streamzap PC Remote Infrared "
-		 "Receiver (%04x:%04x)",
-		 le16_to_cpu(sz->usbdev->descriptor.idVendor),
-		 le16_to_cpu(sz->usbdev->descriptor.idProduct));
-
-	idev->name = sz->name;
-	usb_make_path(sz->usbdev, sz->phys, sizeof(sz->phys));
-	strlcat(sz->phys, "/input0", sizeof(sz->phys));
-	idev->phys = sz->phys;
-
-	props->priv = sz;
-	props->driver_type = RC_DRIVER_IR_RAW;
-	props->allowed_protos = IR_TYPE_ALL;
-
-	sz->props = props;
-
-	usb_to_input_id(sz->usbdev, &idev->id);
-	idev->dev.parent = sz->dev;
-
-	ret = ir_input_register(idev, RC_MAP_STREAMZAP, props, DRIVER_NAME);
-	if (ret < 0) {
-		dev_err(dev, "remote input device register failed\n");
-		goto irdev_failed;
-	}
-
-	return idev;
-
-irdev_failed:
-	kfree(props);
-props_alloc_failed:
-	input_free_device(idev);
-idev_alloc_failed:
-	return NULL;
-}
-
-/**
- *	streamzap_probe
- *
- *	Called by usb-core to associated with a candidate device
- *	On any failure the return value is the ERROR
- *	On success return 0
- */
-static int __devinit streamzap_probe(struct usb_interface *intf,
-				     const struct usb_device_id *id)
-{
-	struct usb_device *usbdev = interface_to_usbdev(intf);
-	struct usb_host_interface *iface_host;
-	struct streamzap_ir *sz = NULL;
-	char buf[63], name[128] = "";
-	int retval = -ENOMEM;
-	int pipe, maxp;
-
-	/* Allocate space for device driver specific data */
-	sz = kzalloc(sizeof(struct streamzap_ir), GFP_KERNEL);
-	if (!sz)
-		return -ENOMEM;
-
-	sz->usbdev = usbdev;
-	sz->interface = intf;
-
-	/* Check to ensure endpoint information matches requirements */
-	iface_host = intf->cur_altsetting;
-
-	if (iface_host->desc.bNumEndpoints != 1) {
-		dev_err(&intf->dev, "%s: Unexpected desc.bNumEndpoints (%d)\n",
-			__func__, iface_host->desc.bNumEndpoints);
-		retval = -ENODEV;
-		goto free_sz;
-	}
-
-	sz->endpoint = &(iface_host->endpoint[0].desc);
-	if ((sz->endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
-	    != USB_DIR_IN) {
-		dev_err(&intf->dev, "%s: endpoint doesn't match input device "
-			"02%02x\n", __func__, sz->endpoint->bEndpointAddress);
-		retval = -ENODEV;
-		goto free_sz;
-	}
-
-	if ((sz->endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
-	    != USB_ENDPOINT_XFER_INT) {
-		dev_err(&intf->dev, "%s: endpoint attributes don't match xfer "
-			"02%02x\n", __func__, sz->endpoint->bmAttributes);
-		retval = -ENODEV;
-		goto free_sz;
-	}
-
-	pipe = usb_rcvintpipe(usbdev, sz->endpoint->bEndpointAddress);
-	maxp = usb_maxpacket(usbdev, pipe, usb_pipeout(pipe));
-
-	if (maxp == 0) {
-		dev_err(&intf->dev, "%s: endpoint Max Packet Size is 0!?!\n",
-			__func__);
-		retval = -ENODEV;
-		goto free_sz;
-	}
-
-	/* Allocate the USB buffer and IRQ URB */
-	sz->buf_in = usb_alloc_coherent(usbdev, maxp, GFP_ATOMIC, &sz->dma_in);
-	if (!sz->buf_in)
-		goto free_sz;
-
-	sz->urb_in = usb_alloc_urb(0, GFP_KERNEL);
-	if (!sz->urb_in)
-		goto free_buf_in;
-
-	sz->dev = &intf->dev;
-	sz->buf_in_len = maxp;
-
-	if (usbdev->descriptor.iManufacturer
-	    && usb_string(usbdev, usbdev->descriptor.iManufacturer,
-			  buf, sizeof(buf)) > 0)
-		strlcpy(name, buf, sizeof(name));
-
-	if (usbdev->descriptor.iProduct
-	    && usb_string(usbdev, usbdev->descriptor.iProduct,
-			  buf, sizeof(buf)) > 0)
-		snprintf(name + strlen(name), sizeof(name) - strlen(name),
-			 " %s", buf);
-
-	sz->idev = streamzap_init_input_dev(sz);
-	if (!sz->idev)
-		goto input_dev_fail;
-
-	sz->idle = true;
-	sz->decoder_state = PulseSpace;
-	/* FIXME: don't yet have a way to set this */
-	sz->timeout_enabled = true;
-	sz->props->timeout = (((SZ_TIMEOUT * SZ_RESOLUTION * 1000) &
-				IR_MAX_DURATION) | 0x03000000);
-	#if 0
-	/* not yet supported, depends on patches from maxim */
-	/* see also: LIRC_GET_REC_RESOLUTION and LIRC_SET_REC_TIMEOUT */
-	sz->min_timeout = SZ_TIMEOUT * SZ_RESOLUTION * 1000;
-	sz->max_timeout = SZ_TIMEOUT * SZ_RESOLUTION * 1000;
-	#endif
-
-	do_gettimeofday(&sz->signal_start);
-
-	/* Complete final initialisations */
-	usb_fill_int_urb(sz->urb_in, usbdev, pipe, sz->buf_in,
-			 maxp, (usb_complete_t)streamzap_callback,
-			 sz, sz->endpoint->bInterval);
-	sz->urb_in->transfer_dma = sz->dma_in;
-	sz->urb_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
-
-	usb_set_intfdata(intf, sz);
-
-	if (usb_submit_urb(sz->urb_in, GFP_ATOMIC))
-		dev_err(sz->dev, "urb submit failed\n");
-
-	dev_info(sz->dev, "Registered %s on usb%d:%d\n", name,
-		 usbdev->bus->busnum, usbdev->devnum);
-
-	/* Load the streamzap not-quite-rc5 decoder too */
-	load_rc5_sz_decode();
-
-	return 0;
-
-input_dev_fail:
-	usb_free_urb(sz->urb_in);
-free_buf_in:
-	usb_free_coherent(usbdev, maxp, sz->buf_in, sz->dma_in);
-free_sz:
-	kfree(sz);
-
-	return retval;
-}
-
-/**
- * streamzap_disconnect
- *
- * Called by the usb core when the device is removed from the system.
- *
- * This routine guarantees that the driver will not submit any more urbs
- * by clearing dev->usbdev.  It is also supposed to terminate any currently
- * active urbs.  Unfortunately, usb_bulk_msg(), used in streamzap_read(),
- * does not provide any way to do this.
- */
-static void streamzap_disconnect(struct usb_interface *interface)
-{
-	struct streamzap_ir *sz = usb_get_intfdata(interface);
-	struct usb_device *usbdev = interface_to_usbdev(interface);
-
-	usb_set_intfdata(interface, NULL);
-
-	if (!sz)
-		return;
-
-	sz->usbdev = NULL;
-	ir_input_unregister(sz->idev);
-	usb_kill_urb(sz->urb_in);
-	usb_free_urb(sz->urb_in);
-	usb_free_coherent(usbdev, sz->buf_in_len, sz->buf_in, sz->dma_in);
-
-	kfree(sz);
-}
-
-static int streamzap_suspend(struct usb_interface *intf, pm_message_t message)
-{
-	struct streamzap_ir *sz = usb_get_intfdata(intf);
-
-	usb_kill_urb(sz->urb_in);
-
-	return 0;
-}
-
-static int streamzap_resume(struct usb_interface *intf)
-{
-	struct streamzap_ir *sz = usb_get_intfdata(intf);
-
-	if (usb_submit_urb(sz->urb_in, GFP_ATOMIC)) {
-		dev_err(sz->dev, "Error sumbiting urb\n");
-		return -EIO;
-	}
-
-	return 0;
-}
-
-/**
- *	streamzap_init
- */
-static int __init streamzap_init(void)
-{
-	int ret;
-
-	/* register this driver with the USB subsystem */
-	ret = usb_register(&streamzap_driver);
-	if (ret < 0)
-		printk(KERN_ERR DRIVER_NAME ": usb register failed, "
-		       "result = %d\n", ret);
-
-	return ret;
-}
-
-/**
- *	streamzap_exit
- */
-static void __exit streamzap_exit(void)
-{
-	usb_deregister(&streamzap_driver);
-}
-
-
-module_init(streamzap_init);
-module_exit(streamzap_exit);
-
-MODULE_AUTHOR("Jarod Wilson <jarod@wilsonet.com>");
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE("GPL");
-
-module_param(debug, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(debug, "Enable debugging messages");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/Kconfig linux-libre-2.6.38-gnu1/drivers/media/Kconfig
--- linux-libre-2.6.37-gnu1/drivers/media/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -40,35 +40,6 @@ config VIDEO_V4L2_COMMON
 	depends on (I2C || I2C=n) && VIDEO_DEV
 	default (I2C || I2C=n) && VIDEO_DEV
 
-config VIDEO_ALLOW_V4L1
-	bool "Enable Video For Linux API 1 (DEPRECATED)"
-	depends on VIDEO_DEV && VIDEO_V4L2_COMMON
-	default VIDEO_DEV && VIDEO_V4L2_COMMON
-	---help---
-	  Enables drivers based on the legacy V4L1 API.
-
-	  This api were developed to be used at Kernel 2.2 and 2.4, but
-	  lacks support for several video standards. There are several
-	  drivers at kernel that still depends on it.
-
-	  If you are unsure as to whether this is required, answer Y.
-
-config VIDEO_V4L1_COMPAT
-	bool "Enable Video For Linux API 1 compatible Layer" if !VIDEO_ALLOW_V4L1
-	depends on VIDEO_DEV
-	default y
-	---help---
-	  Enables a compatibility API used by most V4L2 devices to allow
-	  its usage with legacy applications that supports only V4L1 api.
-
-	  Documentation for the original API is included in the file
-	  <Documentation/video4linux/API.html>.
-
-	  User tools for this are available from
-	  <ftp://ftp.uk.linux.org/pub/linux/video4linux/>.
-
-	  If you are unsure as to whether this is required, answer Y.
-
 #
 # DVB Core
 #
@@ -99,7 +70,7 @@ config VIDEO_MEDIA
 comment "Multimedia drivers"
 
 source "drivers/media/common/Kconfig"
-source "drivers/media/IR/Kconfig"
+source "drivers/media/rc/Kconfig"
 
 #
 # Tuner drivers for DVB and V4L
@@ -121,26 +92,4 @@ source "drivers/media/radio/Kconfig"
 
 source "drivers/media/dvb/Kconfig"
 
-config DAB
-	boolean "DAB adapters"
-	---help---
-	  Allow selecting support for Digital Audio Broadcasting (DAB)
-	  Receiver adapters.
-
-if DAB
-config USB_DABUSB
-	tristate "DABUSB driver"
-	depends on USB
-	---help---
-	  A Digital Audio Broadcasting (DAB) Receiver for USB and Linux
-	  brought to you by the DAB-Team
-	  <http://wwwbode.cs.tum.edu/Par/arch/dab/>.  This driver can be taken
-	  as an example for URB-based bulk, control, and isochronous
-	  transactions. URB's are explained in
-	  <Documentation/usb/URB.txt>.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called dabusb.
-endif # DAB
-
 endif # MEDIA_SUPPORT
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/Makefile linux-libre-2.6.38-gnu1/drivers/media/Makefile
--- linux-libre-2.6.37-gnu1/drivers/media/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -2,7 +2,7 @@
 # Makefile for the kernel multimedia device drivers.
 #
 
-obj-y += common/ IR/ video/
+obj-y += common/ rc/ video/
 
 obj-$(CONFIG_VIDEO_DEV) += radio/
 obj-$(CONFIG_DVB_CORE)  += dvb/
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/radio/Kconfig linux-libre-2.6.38-gnu1/drivers/media/radio/Kconfig
--- linux-libre-2.6.37-gnu1/drivers/media/radio/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/radio/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -151,20 +151,6 @@ config RADIO_GEMTEK_PROBE
 	  following ports will be probed: 0x20c, 0x30c, 0x24c, 0x34c, 0x248 and
 	  0x28c.
 
-config RADIO_GEMTEK_PCI
-	tristate "GemTek PCI Radio Card support"
-	depends on VIDEO_V4L2 && PCI
-	---help---
-	  Choose Y here if you have this PCI FM radio card.
-
-	  In order to control your radio card, you will need to use programs
-	  that are compatible with the Video for Linux API.  Information on
-	  this API and pointers to "v4l" programs may be found at
-	  <file:Documentation/video4linux/API.html>.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called radio-gemtek-pci.
-
 config RADIO_MAXIRADIO
 	tristate "Guillemot MAXI Radio FM 2000 radio"
 	depends on VIDEO_V4L2 && PCI
@@ -452,4 +438,20 @@ config RADIO_TIMBERDALE
 	  found behind the Timberdale FPGA on the Russellville board.
 	  Enabling this driver will automatically select the DSP and tuner.
 
+config RADIO_WL1273
+	tristate "Texas Instruments WL1273 I2C FM Radio"
+	depends on I2C && VIDEO_V4L2
+	select MFD_WL1273_CORE
+	select FW_LOADER
+	---help---
+	  Choose Y here if you have this FM radio chip.
+
+	  In order to control your radio card, you will need to use programs
+	  that are compatible with the Video For Linux 2 API.  Information on
+	  this API and pointers to "v4l2" programs may be found at
+	  <file:Documentation/video4linux/API.html>.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called radio-wl1273.
+
 endif # RADIO_ADAPTERS
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/radio/Makefile linux-libre-2.6.38-gnu1/drivers/media/radio/Makefile
--- linux-libre-2.6.37-gnu1/drivers/media/radio/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/radio/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -13,7 +13,6 @@ obj-$(CONFIG_RADIO_MAXIRADIO) += radio-m
 obj-$(CONFIG_RADIO_RTRACK) += radio-aimslab.o
 obj-$(CONFIG_RADIO_ZOLTRIX) += radio-zoltrix.o
 obj-$(CONFIG_RADIO_GEMTEK) += radio-gemtek.o
-obj-$(CONFIG_RADIO_GEMTEK_PCI) += radio-gemtek-pci.o
 obj-$(CONFIG_RADIO_TRUST) += radio-trust.o
 obj-$(CONFIG_I2C_SI4713) += si4713-i2c.o
 obj-$(CONFIG_RADIO_SI4713) += radio-si4713.o
@@ -26,5 +25,6 @@ obj-$(CONFIG_RADIO_TEA5764) += radio-tea
 obj-$(CONFIG_RADIO_SAA7706H) += saa7706h.o
 obj-$(CONFIG_RADIO_TEF6862) += tef6862.o
 obj-$(CONFIG_RADIO_TIMBERDALE) += radio-timb.o
+obj-$(CONFIG_RADIO_WL1273) += radio-wl1273.o
 
 EXTRA_CFLAGS += -Isound
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/radio/radio-aimslab.c linux-libre-2.6.38-gnu1/drivers/media/radio/radio-aimslab.c
--- linux-libre-2.6.37-gnu1/drivers/media/radio/radio-aimslab.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/radio/radio-aimslab.c	2011-03-14 21:20:32.000000000 -0400
@@ -31,7 +31,7 @@
 #include <linux/module.h>	/* Modules 			*/
 #include <linux/init.h>		/* Initdata			*/
 #include <linux/ioport.h>	/* request_region		*/
-#include <linux/delay.h>	/* udelay			*/
+#include <linux/delay.h>	/* msleep			*/
 #include <linux/videodev2.h>	/* kernel radio structs		*/
 #include <linux/version.h>	/* for KERNEL_VERSION MACRO	*/
 #include <linux/io.h>		/* outb, outb_p			*/
@@ -71,27 +71,17 @@ static struct rtrack rtrack_card;
 
 /* local things */
 
-static void sleep_delay(long n)
-{
-	/* Sleep nicely for 'n' uS */
-	int d = n / msecs_to_jiffies(1000);
-	if (!d)
-		udelay(n);
-	else
-		msleep(jiffies_to_msecs(d));
-}
-
 static void rt_decvol(struct rtrack *rt)
 {
 	outb(0x58, rt->io);		/* volume down + sigstr + on	*/
-	sleep_delay(100000);
+	msleep(100);
 	outb(0xd8, rt->io);		/* volume steady + sigstr + on	*/
 }
 
 static void rt_incvol(struct rtrack *rt)
 {
 	outb(0x98, rt->io);		/* volume up + sigstr + on	*/
-	sleep_delay(100000);
+	msleep(100);
 	outb(0xd8, rt->io);		/* volume steady + sigstr + on	*/
 }
 
@@ -120,7 +110,7 @@ static int rt_setvol(struct rtrack *rt,
 
 	if (vol == 0) {			/* volume = 0 means mute the card */
 		outb(0x48, rt->io);	/* volume down but still "on"	*/
-		sleep_delay(2000000);	/* make sure it's totally down	*/
+		msleep(2000);	/* make sure it's totally down	*/
 		outb(0xd0, rt->io);	/* volume steady, off		*/
 		rt->curvol = 0;		/* track the volume state!	*/
 		mutex_unlock(&rt->lock);
@@ -155,7 +145,7 @@ static void send_0_byte(struct rtrack *r
 		outb_p(128+64+16+8+  1, rt->io);  /* on + wr-enable + data low */
 		outb_p(128+64+16+8+2+1, rt->io);  /* clock */
 	}
-	sleep_delay(1000);
+	msleep(1);
 }
 
 static void send_1_byte(struct rtrack *rt)
@@ -169,7 +159,7 @@ static void send_1_byte(struct rtrack *r
 		outb_p(128+64+16+8+4+2+1, rt->io); /* clock */
 	}
 
-	sleep_delay(1000);
+	msleep(1);
 }
 
 static int rt_setfreq(struct rtrack *rt, unsigned long freq)
@@ -420,7 +410,7 @@ static int __init rtrack_init(void)
 
 	/* this ensures that the volume is all the way down  */
 	outb(0x48, rt->io);		/* volume down but still "on"	*/
-	sleep_delay(2000000);	/* make sure it's totally down	*/
+	msleep(2000);	/* make sure it's totally down	*/
 	outb(0xc0, rt->io);		/* steady volume, mute card	*/
 
 	if (video_register_device(&rt->vdev, VFL_TYPE_RADIO, radio_nr) < 0) {
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/radio/radio-gemtek-pci.c linux-libre-2.6.38-gnu1/drivers/media/radio/radio-gemtek-pci.c
--- linux-libre-2.6.37-gnu1/drivers/media/radio/radio-gemtek-pci.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/radio/radio-gemtek-pci.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,478 +0,0 @@
-/*
- ***************************************************************************
- *
- *     radio-gemtek-pci.c - Gemtek PCI Radio driver
- *     (C) 2001 Vladimir Shebordaev <vshebordaev@mail.ru>
- *
- ***************************************************************************
- *
- *     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.
- *
- ***************************************************************************
- *
- *     Gemtek Corp still silently refuses to release any specifications
- *     of their multimedia devices, so the protocol still has to be
- *     reverse engineered.
- *
- *     The v4l code was inspired by Jonas Munsin's  Gemtek serial line
- *     radio device driver.
- *
- *     Please, let me know if this piece of code was useful :)
- *
- *     TODO: multiple device support and portability were not tested
- *
- *     Converted to V4L2 API by Mauro Carvalho Chehab <mchehab@infradead.org>
- *
- ***************************************************************************
- */
-
-#include <linux/types.h>
-#include <linux/list.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/videodev2.h>
-#include <linux/errno.h>
-#include <linux/version.h>      /* for KERNEL_VERSION MACRO     */
-#include <linux/io.h>
-#include <linux/slab.h>
-#include <media/v4l2-device.h>
-#include <media/v4l2-ioctl.h>
-
-MODULE_AUTHOR("Vladimir Shebordaev <vshebordaev@mail.ru>");
-MODULE_DESCRIPTION("The video4linux driver for the Gemtek PCI Radio Card");
-MODULE_LICENSE("GPL");
-
-static int nr_radio = -1;
-static int mx = 1;
-
-module_param(mx, bool, 0);
-MODULE_PARM_DESC(mx, "single digit: 1 - turn off the turner upon module exit (default), 0 - do not");
-module_param(nr_radio, int, 0);
-MODULE_PARM_DESC(nr_radio, "video4linux device number to use");
-
-#define RADIO_VERSION KERNEL_VERSION(0, 0, 2)
-
-#ifndef PCI_VENDOR_ID_GEMTEK
-#define PCI_VENDOR_ID_GEMTEK 0x5046
-#endif
-
-#ifndef PCI_DEVICE_ID_GEMTEK_PR103
-#define PCI_DEVICE_ID_GEMTEK_PR103 0x1001
-#endif
-
-#ifndef GEMTEK_PCI_RANGE_LOW
-#define GEMTEK_PCI_RANGE_LOW (87*16000)
-#endif
-
-#ifndef GEMTEK_PCI_RANGE_HIGH
-#define GEMTEK_PCI_RANGE_HIGH (108*16000)
-#endif
-
-struct gemtek_pci {
-	struct v4l2_device v4l2_dev;
-	struct video_device vdev;
-	struct mutex lock;
-	struct pci_dev *pdev;
-
-	u32 iobase;
-	u32 length;
-
-	u32 current_frequency;
-	u8  mute;
-};
-
-static inline struct gemtek_pci *to_gemtek_pci(struct v4l2_device *v4l2_dev)
-{
-	return container_of(v4l2_dev, struct gemtek_pci, v4l2_dev);
-}
-
-static inline u8 gemtek_pci_out(u16 value, u32 port)
-{
-	outw(value, port);
-
-	return (u8)value;
-}
-
-#define _b0(v) (*((u8 *)&v))
-
-static void __gemtek_pci_cmd(u16 value, u32 port, u8 *last_byte, int keep)
-{
-	u8 byte = *last_byte;
-
-	if (!value) {
-		if (!keep)
-			value = (u16)port;
-		byte &= 0xfd;
-	} else
-		byte |= 2;
-
-	_b0(value) = byte;
-	outw(value, port);
-	byte |= 1;
-	_b0(value) = byte;
-	outw(value, port);
-	byte &= 0xfe;
-	_b0(value) = byte;
-	outw(value, port);
-
-	*last_byte = byte;
-}
-
-static inline void gemtek_pci_nil(u32 port, u8 *last_byte)
-{
-	__gemtek_pci_cmd(0x00, port, last_byte, false);
-}
-
-static inline void gemtek_pci_cmd(u16 cmd, u32 port, u8 *last_byte)
-{
-	__gemtek_pci_cmd(cmd, port, last_byte, true);
-}
-
-static void gemtek_pci_setfrequency(struct gemtek_pci *card, unsigned long frequency)
-{
-	int i;
-	u32 value = frequency / 200 + 856;
-	u16 mask = 0x8000;
-	u8 last_byte;
-	u32 port = card->iobase;
-
-	mutex_lock(&card->lock);
-	card->current_frequency = frequency;
-	last_byte = gemtek_pci_out(0x06, port);
-
-	i = 0;
-	do {
-		gemtek_pci_nil(port, &last_byte);
-		i++;
-	} while (i < 9);
-
-	i = 0;
-	do {
-		gemtek_pci_cmd(value & mask, port, &last_byte);
-		mask >>= 1;
-		i++;
-	} while (i < 16);
-
-	outw(0x10, port);
-	mutex_unlock(&card->lock);
-}
-
-
-static void gemtek_pci_mute(struct gemtek_pci *card)
-{
-	mutex_lock(&card->lock);
-	outb(0x1f, card->iobase);
-	card->mute = true;
-	mutex_unlock(&card->lock);
-}
-
-static void gemtek_pci_unmute(struct gemtek_pci *card)
-{
-	if (card->mute) {
-		gemtek_pci_setfrequency(card, card->current_frequency);
-		card->mute = false;
-	}
-}
-
-static int gemtek_pci_getsignal(struct gemtek_pci *card)
-{
-	int sig;
-
-	mutex_lock(&card->lock);
-	sig = (inb(card->iobase) & 0x08) ? 0 : 1;
-	mutex_unlock(&card->lock);
-	return sig;
-}
-
-static int vidioc_querycap(struct file *file, void *priv,
-					struct v4l2_capability *v)
-{
-	struct gemtek_pci *card = video_drvdata(file);
-
-	strlcpy(v->driver, "radio-gemtek-pci", sizeof(v->driver));
-	strlcpy(v->card, "GemTek PCI Radio", sizeof(v->card));
-	snprintf(v->bus_info, sizeof(v->bus_info), "PCI:%s", pci_name(card->pdev));
-	v->version = RADIO_VERSION;
-	v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO;
-	return 0;
-}
-
-static int vidioc_g_tuner(struct file *file, void *priv,
-					struct v4l2_tuner *v)
-{
-	struct gemtek_pci *card = video_drvdata(file);
-
-	if (v->index > 0)
-		return -EINVAL;
-
-	strlcpy(v->name, "FM", sizeof(v->name));
-	v->type = V4L2_TUNER_RADIO;
-	v->rangelow = GEMTEK_PCI_RANGE_LOW;
-	v->rangehigh = GEMTEK_PCI_RANGE_HIGH;
-	v->rxsubchans = V4L2_TUNER_SUB_MONO;
-	v->capability = V4L2_TUNER_CAP_LOW;
-	v->audmode = V4L2_TUNER_MODE_MONO;
-	v->signal = 0xffff * gemtek_pci_getsignal(card);
-	return 0;
-}
-
-static int vidioc_s_tuner(struct file *file, void *priv,
-					struct v4l2_tuner *v)
-{
-	return v->index ? -EINVAL : 0;
-}
-
-static int vidioc_s_frequency(struct file *file, void *priv,
-					struct v4l2_frequency *f)
-{
-	struct gemtek_pci *card = video_drvdata(file);
-
-	if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO)
-		return -EINVAL;
-	if (f->frequency < GEMTEK_PCI_RANGE_LOW ||
-	    f->frequency > GEMTEK_PCI_RANGE_HIGH)
-		return -EINVAL;
-	gemtek_pci_setfrequency(card, f->frequency);
-	card->mute = false;
-	return 0;
-}
-
-static int vidioc_g_frequency(struct file *file, void *priv,
-					struct v4l2_frequency *f)
-{
-	struct gemtek_pci *card = video_drvdata(file);
-
-	if (f->tuner != 0)
-		return -EINVAL;
-	f->type = V4L2_TUNER_RADIO;
-	f->frequency = card->current_frequency;
-	return 0;
-}
-
-static int vidioc_queryctrl(struct file *file, void *priv,
-					struct v4l2_queryctrl *qc)
-{
-	switch (qc->id) {
-	case V4L2_CID_AUDIO_MUTE:
-		return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1);
-	case V4L2_CID_AUDIO_VOLUME:
-		return v4l2_ctrl_query_fill(qc, 0, 65535, 65535, 65535);
-	}
-	return -EINVAL;
-}
-
-static int vidioc_g_ctrl(struct file *file, void *priv,
-					struct v4l2_control *ctrl)
-{
-	struct gemtek_pci *card = video_drvdata(file);
-
-	switch (ctrl->id) {
-	case V4L2_CID_AUDIO_MUTE:
-		ctrl->value = card->mute;
-		return 0;
-	case V4L2_CID_AUDIO_VOLUME:
-		if (card->mute)
-			ctrl->value = 0;
-		else
-			ctrl->value = 65535;
-		return 0;
-	}
-	return -EINVAL;
-}
-
-static int vidioc_s_ctrl(struct file *file, void *priv,
-					struct v4l2_control *ctrl)
-{
-	struct gemtek_pci *card = video_drvdata(file);
-
-	switch (ctrl->id) {
-	case V4L2_CID_AUDIO_MUTE:
-		if (ctrl->value)
-			gemtek_pci_mute(card);
-		else
-			gemtek_pci_unmute(card);
-		return 0;
-	case V4L2_CID_AUDIO_VOLUME:
-		if (ctrl->value)
-			gemtek_pci_unmute(card);
-		else
-			gemtek_pci_mute(card);
-		return 0;
-	}
-	return -EINVAL;
-}
-
-static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i)
-{
-	*i = 0;
-	return 0;
-}
-
-static int vidioc_s_input(struct file *filp, void *priv, unsigned int i)
-{
-	return i ? -EINVAL : 0;
-}
-
-static int vidioc_g_audio(struct file *file, void *priv,
-					struct v4l2_audio *a)
-{
-	a->index = 0;
-	strlcpy(a->name, "Radio", sizeof(a->name));
-	a->capability = V4L2_AUDCAP_STEREO;
-	return 0;
-}
-
-static int vidioc_s_audio(struct file *file, void *priv,
-					struct v4l2_audio *a)
-{
-	return a->index ? -EINVAL : 0;
-}
-
-enum {
-	GEMTEK_PR103
-};
-
-static char *card_names[] __devinitdata = {
-	"GEMTEK_PR103"
-};
-
-static struct pci_device_id gemtek_pci_id[] =
-{
-	{ PCI_VENDOR_ID_GEMTEK, PCI_DEVICE_ID_GEMTEK_PR103,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, GEMTEK_PR103 },
-	{ 0 }
-};
-
-MODULE_DEVICE_TABLE(pci, gemtek_pci_id);
-
-static const struct v4l2_file_operations gemtek_pci_fops = {
-	.owner		= THIS_MODULE,
-	.unlocked_ioctl	= video_ioctl2,
-};
-
-static const struct v4l2_ioctl_ops gemtek_pci_ioctl_ops = {
-	.vidioc_querycap    = vidioc_querycap,
-	.vidioc_g_tuner     = vidioc_g_tuner,
-	.vidioc_s_tuner     = vidioc_s_tuner,
-	.vidioc_g_audio     = vidioc_g_audio,
-	.vidioc_s_audio     = vidioc_s_audio,
-	.vidioc_g_input     = vidioc_g_input,
-	.vidioc_s_input     = vidioc_s_input,
-	.vidioc_g_frequency = vidioc_g_frequency,
-	.vidioc_s_frequency = vidioc_s_frequency,
-	.vidioc_queryctrl   = vidioc_queryctrl,
-	.vidioc_g_ctrl      = vidioc_g_ctrl,
-	.vidioc_s_ctrl      = vidioc_s_ctrl,
-};
-
-static int __devinit gemtek_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id)
-{
-	struct gemtek_pci *card;
-	struct v4l2_device *v4l2_dev;
-	int res;
-
-	card = kzalloc(sizeof(struct gemtek_pci), GFP_KERNEL);
-	if (card == NULL) {
-		dev_err(&pdev->dev, "out of memory\n");
-		return -ENOMEM;
-	}
-
-	v4l2_dev = &card->v4l2_dev;
-	mutex_init(&card->lock);
-	card->pdev = pdev;
-
-	strlcpy(v4l2_dev->name, "gemtek_pci", sizeof(v4l2_dev->name));
-
-	res = v4l2_device_register(&pdev->dev, v4l2_dev);
-	if (res < 0) {
-		v4l2_err(v4l2_dev, "Could not register v4l2_device\n");
-		kfree(card);
-		return res;
-	}
-
-	if (pci_enable_device(pdev))
-		goto err_pci;
-
-	card->iobase = pci_resource_start(pdev, 0);
-	card->length = pci_resource_len(pdev, 0);
-
-	if (request_region(card->iobase, card->length, card_names[pci_id->driver_data]) == NULL) {
-		v4l2_err(v4l2_dev, "i/o port already in use\n");
-		goto err_pci;
-	}
-
-	strlcpy(card->vdev.name, v4l2_dev->name, sizeof(card->vdev.name));
-	card->vdev.v4l2_dev = v4l2_dev;
-	card->vdev.fops = &gemtek_pci_fops;
-	card->vdev.ioctl_ops = &gemtek_pci_ioctl_ops;
-	card->vdev.release = video_device_release_empty;
-	video_set_drvdata(&card->vdev, card);
-
-	gemtek_pci_mute(card);
-
-	if (video_register_device(&card->vdev, VFL_TYPE_RADIO, nr_radio) < 0)
-		goto err_video;
-
-	v4l2_info(v4l2_dev, "Gemtek PCI Radio (rev. %d) found at 0x%04x-0x%04x.\n",
-		pdev->revision, card->iobase, card->iobase + card->length - 1);
-
-	return 0;
-
-err_video:
-	release_region(card->iobase, card->length);
-
-err_pci:
-	v4l2_device_unregister(v4l2_dev);
-	kfree(card);
-	return -ENODEV;
-}
-
-static void __devexit gemtek_pci_remove(struct pci_dev *pdev)
-{
-	struct v4l2_device *v4l2_dev = dev_get_drvdata(&pdev->dev);
-	struct gemtek_pci *card = to_gemtek_pci(v4l2_dev);
-
-	video_unregister_device(&card->vdev);
-	v4l2_device_unregister(v4l2_dev);
-
-	release_region(card->iobase, card->length);
-
-	if (mx)
-		gemtek_pci_mute(card);
-
-	kfree(card);
-}
-
-static struct pci_driver gemtek_pci_driver = {
-	.name		= "gemtek_pci",
-	.id_table	= gemtek_pci_id,
-	.probe		= gemtek_pci_probe,
-	.remove		= __devexit_p(gemtek_pci_remove),
-};
-
-static int __init gemtek_pci_init(void)
-{
-	return pci_register_driver(&gemtek_pci_driver);
-}
-
-static void __exit gemtek_pci_exit(void)
-{
-	pci_unregister_driver(&gemtek_pci_driver);
-}
-
-module_init(gemtek_pci_init);
-module_exit(gemtek_pci_exit);
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/radio/radio-maxiradio.c linux-libre-2.6.38-gnu1/drivers/media/radio/radio-maxiradio.c
--- linux-libre-2.6.37-gnu1/drivers/media/radio/radio-maxiradio.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/radio/radio-maxiradio.c	2011-03-14 21:20:32.000000000 -0400
@@ -77,8 +77,8 @@ MODULE_PARM_DESC(debug, "activates debug
 /* TEA5757 pin mappings */
 static const int clk = 1, data = 2, wren = 4, mo_st = 8, power = 16;
 
-#define FREQ_LO		(50 * 16000)
-#define FREQ_HI		(150 * 16000)
+#define FREQ_LO		(87 * 16000)
+#define FREQ_HI		(108 * 16000)
 
 #define FREQ_IF         171200 /* 10.7*16000   */
 #define FREQ_STEP       200    /* 12.5*16      */
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/radio/radio-wl1273.c linux-libre-2.6.38-gnu1/drivers/media/radio/radio-wl1273.c
--- linux-libre-2.6.37-gnu1/drivers/media/radio/radio-wl1273.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/radio/radio-wl1273.c	2013-05-03 01:57:31.000000000 -0400
@@ -0,0 +1,2330 @@
+/*
+ * Driver for the Texas Instruments WL1273 FM radio.
+ *
+ * Copyright (C) 2010 Nokia Corporation
+ * Author: Matti J. Aaltonen <matti.j.aaltonen@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.
+ *
+ * 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/delay.h>
+#include <linux/firmware.h>
+#include <linux/interrupt.h>
+#include <linux/mfd/wl1273-core.h>
+#include <linux/slab.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-ioctl.h>
+
+#define DRIVER_DESC "Wl1273 FM Radio"
+
+#define WL1273_POWER_SET_OFF		0
+#define WL1273_POWER_SET_FM		BIT(0)
+#define WL1273_POWER_SET_RDS		BIT(1)
+#define WL1273_POWER_SET_RETENTION	BIT(4)
+
+#define WL1273_PUPD_SET_OFF		0x00
+#define WL1273_PUPD_SET_ON		0x01
+#define WL1273_PUPD_SET_RETENTION	0x10
+
+#define WL1273_FREQ(x)		(x * 10000 / 625)
+#define WL1273_INV_FREQ(x)	(x * 625 / 10000)
+
+/*
+ * static int radio_nr - The number of the radio device
+ *
+ * The default is 0.
+ */
+static int radio_nr;
+module_param(radio_nr, int, 0);
+MODULE_PARM_DESC(radio_nr, "The number of the radio device. Default = 0");
+
+struct wl1273_device {
+	char *bus_type;
+
+	u8 forbidden;
+	unsigned int preemphasis;
+	unsigned int spacing;
+	unsigned int tx_power;
+	unsigned int rx_frequency;
+	unsigned int tx_frequency;
+	unsigned int rangelow;
+	unsigned int rangehigh;
+	unsigned int band;
+	bool stereo;
+
+	/* RDS */
+	unsigned int rds_on;
+	struct delayed_work work;
+
+	wait_queue_head_t read_queue;
+	struct mutex lock; /* for serializing fm radio operations */
+	struct completion busy;
+
+	unsigned char *buffer;
+	unsigned int buf_size;
+	unsigned int rd_index;
+	unsigned int wr_index;
+
+	/* Selected interrupts */
+	u16 irq_flags;
+	u16 irq_received;
+
+	struct v4l2_ctrl_handler ctrl_handler;
+	struct v4l2_device v4l2dev;
+	struct video_device videodev;
+	struct device *dev;
+	struct wl1273_core *core;
+	struct file *owner;
+	char *write_buf;
+	unsigned int rds_users;
+};
+
+#define WL1273_IRQ_MASK	 (WL1273_FR_EVENT		|	\
+			  WL1273_POW_ENB_EVENT)
+
+/*
+ * static unsigned int rds_buf - the number of RDS buffer blocks used.
+ *
+ * The default number is 100.
+ */
+static unsigned int rds_buf = 100;
+module_param(rds_buf, uint, 0);
+MODULE_PARM_DESC(rds_buf, "Number of RDS buffer entries. Default = 100");
+
+static int wl1273_fm_read_reg(struct wl1273_core *core, u8 reg, u16 *value)
+{
+	struct i2c_client *client = core->client;
+	u8 b[2];
+	int r;
+
+	r = i2c_smbus_read_i2c_block_data(client, reg, sizeof(b), b);
+	if (r != 2) {
+		dev_err(&client->dev, "%s: Read: %d fails.\n", __func__, reg);
+		return -EREMOTEIO;
+	}
+
+	*value = (u16)b[0] << 8 | b[1];
+
+	return 0;
+}
+
+static int wl1273_fm_write_cmd(struct wl1273_core *core, u8 cmd, u16 param)
+{
+	struct i2c_client *client = core->client;
+	u8 buf[] = { (param >> 8) & 0xff, param & 0xff };
+	int r;
+
+	r = i2c_smbus_write_i2c_block_data(client, cmd, sizeof(buf), buf);
+	if (r) {
+		dev_err(&client->dev, "%s: Cmd: %d fails.\n", __func__, cmd);
+		return r;
+	}
+
+	return 0;
+}
+
+static int wl1273_fm_write_data(struct wl1273_core *core, u8 *data, u16 len)
+{
+	struct i2c_client *client = core->client;
+	struct i2c_msg msg;
+	int r;
+
+	msg.addr = client->addr;
+	msg.flags = 0;
+	msg.buf = data;
+	msg.len = len;
+
+	r = i2c_transfer(client->adapter, &msg, 1);
+	if (r != 1) {
+		dev_err(&client->dev, "%s: write error.\n", __func__);
+		return -EREMOTEIO;
+	}
+
+	return 0;
+}
+
+static int wl1273_fm_write_fw(struct wl1273_core *core,
+			      __u8 *fw, int len)
+{
+	struct i2c_client *client = core->client;
+	struct i2c_msg msg;
+	int i, r = 0;
+
+	msg.addr = client->addr;
+	msg.flags = 0;
+
+	for (i = 0; i <= len; i++) {
+		msg.len = fw[0];
+		msg.buf = fw + 1;
+
+		fw += msg.len + 1;
+		dev_dbg(&client->dev, "%s:len[%d]: %d\n", __func__, i, msg.len);
+
+		r = i2c_transfer(client->adapter, &msg, 1);
+		if (r < 0 && i < len + 1)
+			break;
+	}
+
+	dev_dbg(&client->dev, "%s: i: %d\n", __func__, i);
+	dev_dbg(&client->dev, "%s: len + 1: %d\n", __func__, len + 1);
+
+	/* Last transfer always fails. */
+	if (i == len || r == 1)
+		r = 0;
+
+	return r;
+}
+
+/**
+ * wl1273_fm_set_audio() -	Set audio mode.
+ * @core:			A pointer to the device struct.
+ * @new_mode:			The new audio mode.
+ *
+ * Audio modes are WL1273_AUDIO_DIGITAL and WL1273_AUDIO_ANALOG.
+ */
+static int wl1273_fm_set_audio(struct wl1273_core *core, unsigned int new_mode)
+{
+	int r = 0;
+
+	if (core->mode == WL1273_MODE_OFF ||
+	    core->mode == WL1273_MODE_SUSPENDED)
+		return -EPERM;
+
+	if (core->mode == WL1273_MODE_RX && new_mode == WL1273_AUDIO_DIGITAL) {
+		r = wl1273_fm_write_cmd(core, WL1273_PCM_MODE_SET,
+					WL1273_PCM_DEF_MODE);
+		if (r)
+			goto out;
+
+		r = wl1273_fm_write_cmd(core, WL1273_I2S_MODE_CONFIG_SET,
+					core->i2s_mode);
+		if (r)
+			goto out;
+
+		r = wl1273_fm_write_cmd(core, WL1273_AUDIO_ENABLE,
+					WL1273_AUDIO_ENABLE_I2S);
+		if (r)
+			goto out;
+
+	} else if (core->mode == WL1273_MODE_RX &&
+		   new_mode == WL1273_AUDIO_ANALOG) {
+		r = wl1273_fm_write_cmd(core, WL1273_AUDIO_ENABLE,
+					WL1273_AUDIO_ENABLE_ANALOG);
+		if (r)
+			goto out;
+
+	} else if (core->mode == WL1273_MODE_TX &&
+		   new_mode == WL1273_AUDIO_DIGITAL) {
+		r = wl1273_fm_write_cmd(core, WL1273_I2S_MODE_CONFIG_SET,
+					core->i2s_mode);
+		if (r)
+			goto out;
+
+		r = wl1273_fm_write_cmd(core, WL1273_AUDIO_IO_SET,
+					WL1273_AUDIO_IO_SET_I2S);
+		if (r)
+			goto out;
+
+	} else if (core->mode == WL1273_MODE_TX &&
+		   new_mode == WL1273_AUDIO_ANALOG) {
+		r = wl1273_fm_write_cmd(core, WL1273_AUDIO_IO_SET,
+					WL1273_AUDIO_IO_SET_ANALOG);
+		if (r)
+			goto out;
+	}
+
+	core->audio_mode = new_mode;
+out:
+	return r;
+}
+
+/**
+ * wl1273_fm_set_volume() -	Set volume.
+ * @core:			A pointer to the device struct.
+ * @volume:			The new volume value.
+ */
+static int wl1273_fm_set_volume(struct wl1273_core *core, unsigned int volume)
+{
+	u16 val;
+	int r;
+
+	if (volume > WL1273_MAX_VOLUME)
+		return -EINVAL;
+
+	if (core->volume == volume)
+		return 0;
+
+	val = volume;
+	r = wl1273_fm_read_reg(core, WL1273_VOLUME_SET, &val);
+	if (r)
+		return r;
+
+	core->volume = volume;
+	return 0;
+}
+
+#define WL1273_FIFO_HAS_DATA(status)	(1 << 5 & status)
+#define WL1273_RDS_CORRECTABLE_ERROR	(1 << 3)
+#define WL1273_RDS_UNCORRECTABLE_ERROR	(1 << 4)
+
+static int wl1273_fm_rds(struct wl1273_device *radio)
+{
+	struct wl1273_core *core = radio->core;
+	struct i2c_client *client = core->client;
+	u16 val;
+	u8 b0 = WL1273_RDS_DATA_GET, status;
+	struct v4l2_rds_data rds = { 0, 0, 0 };
+	struct i2c_msg msg[] = {
+		{
+			.addr = client->addr,
+			.flags = 0,
+			.buf = &b0,
+			.len = 1,
+		},
+		{
+			.addr = client->addr,
+			.flags = I2C_M_RD,
+			.buf = (u8 *) &rds,
+			.len = sizeof(rds),
+		}
+	};
+	int r;
+
+	if (core->mode != WL1273_MODE_RX)
+		return 0;
+
+	r = wl1273_fm_read_reg(core, WL1273_RDS_SYNC_GET, &val);
+	if (r)
+		return r;
+
+	if ((val & 0x01) == 0) {
+		/* RDS decoder not synchronized */
+		return -EAGAIN;
+	}
+
+	/* copy all four RDS blocks to internal buffer */
+	do {
+		r = i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg));
+		if (r != ARRAY_SIZE(msg)) {
+			dev_err(radio->dev, WL1273_FM_DRIVER_NAME
+				": %s: read_rds error r == %i)\n",
+				__func__, r);
+		}
+
+		status = rds.block;
+
+		if (!WL1273_FIFO_HAS_DATA(status))
+			break;
+
+		/* copy bits 0-2 (the block ID) to bits 3-5 */
+		rds.block = V4L2_RDS_BLOCK_MSK & status;
+		rds.block |= rds.block << 3;
+
+		/* copy the error bits to standard positions */
+		if (WL1273_RDS_UNCORRECTABLE_ERROR & status) {
+			rds.block |= V4L2_RDS_BLOCK_ERROR;
+			rds.block &= ~V4L2_RDS_BLOCK_CORRECTED;
+		} else if  (WL1273_RDS_CORRECTABLE_ERROR & status) {
+			rds.block &= ~V4L2_RDS_BLOCK_ERROR;
+			rds.block |= V4L2_RDS_BLOCK_CORRECTED;
+		}
+
+		/* copy RDS block to internal buffer */
+		memcpy(&radio->buffer[radio->wr_index], &rds, RDS_BLOCK_SIZE);
+		radio->wr_index += 3;
+
+		/* wrap write pointer */
+		if (radio->wr_index >= radio->buf_size)
+			radio->wr_index = 0;
+
+		/* check for overflow & start over */
+		if (radio->wr_index == radio->rd_index) {
+			dev_dbg(radio->dev, "RDS OVERFLOW");
+
+			radio->rd_index = 0;
+			radio->wr_index = 0;
+			break;
+		}
+	} while (WL1273_FIFO_HAS_DATA(status));
+
+	/* wake up read queue */
+	if (radio->wr_index != radio->rd_index)
+		wake_up_interruptible(&radio->read_queue);
+
+	return 0;
+}
+
+static irqreturn_t wl1273_fm_irq_thread_handler(int irq, void *dev_id)
+{
+	struct wl1273_device *radio = dev_id;
+	struct wl1273_core *core = radio->core;
+	u16 flags;
+	int r;
+
+	r = wl1273_fm_read_reg(core, WL1273_FLAG_GET, &flags);
+	if (r)
+		goto out;
+
+	if (flags & WL1273_BL_EVENT) {
+		radio->irq_received = flags;
+		dev_dbg(radio->dev, "IRQ: BL\n");
+	}
+
+	if (flags & WL1273_RDS_EVENT) {
+		msleep(200);
+
+		wl1273_fm_rds(radio);
+	}
+
+	if (flags & WL1273_BBLK_EVENT)
+		dev_dbg(radio->dev, "IRQ: BBLK\n");
+
+	if (flags & WL1273_LSYNC_EVENT)
+		dev_dbg(radio->dev, "IRQ: LSYNC\n");
+
+	if (flags & WL1273_LEV_EVENT) {
+		u16 level;
+
+		r = wl1273_fm_read_reg(core, WL1273_RSSI_LVL_GET, &level);
+		if (r)
+			goto out;
+
+		if (level > 14)
+			dev_dbg(radio->dev, "IRQ: LEV: 0x%x04\n", level);
+	}
+
+	if (flags & WL1273_IFFR_EVENT)
+		dev_dbg(radio->dev, "IRQ: IFFR\n");
+
+	if (flags & WL1273_PI_EVENT)
+		dev_dbg(radio->dev, "IRQ: PI\n");
+
+	if (flags & WL1273_PD_EVENT)
+		dev_dbg(radio->dev, "IRQ: PD\n");
+
+	if (flags & WL1273_STIC_EVENT)
+		dev_dbg(radio->dev, "IRQ: STIC\n");
+
+	if (flags & WL1273_MAL_EVENT)
+		dev_dbg(radio->dev, "IRQ: MAL\n");
+
+	if (flags & WL1273_POW_ENB_EVENT) {
+		complete(&radio->busy);
+		dev_dbg(radio->dev, "NOT BUSY\n");
+		dev_dbg(radio->dev, "IRQ: POW_ENB\n");
+	}
+
+	if (flags & WL1273_SCAN_OVER_EVENT)
+		dev_dbg(radio->dev, "IRQ: SCAN_OVER\n");
+
+	if (flags & WL1273_ERROR_EVENT)
+		dev_dbg(radio->dev, "IRQ: ERROR\n");
+
+	if (flags & WL1273_FR_EVENT) {
+		u16 freq;
+
+		dev_dbg(radio->dev, "IRQ: FR:\n");
+
+		if (core->mode == WL1273_MODE_RX) {
+			r = wl1273_fm_write_cmd(core, WL1273_TUNER_MODE_SET,
+						TUNER_MODE_STOP_SEARCH);
+			if (r) {
+				dev_err(radio->dev,
+					"%s: TUNER_MODE_SET fails: %d\n",
+					__func__, r);
+				goto out;
+			}
+
+			r = wl1273_fm_read_reg(core, WL1273_FREQ_SET, &freq);
+			if (r)
+				goto out;
+
+			if (radio->band == WL1273_BAND_JAPAN)
+				radio->rx_frequency = WL1273_BAND_JAPAN_LOW +
+					freq * 50;
+			else
+				radio->rx_frequency = WL1273_BAND_OTHER_LOW +
+					freq * 50;
+			/*
+			 *  The driver works better with this msleep,
+			 *  the documentation doesn't mention it.
+			 */
+			usleep_range(10000, 15000);
+
+			dev_dbg(radio->dev, "%dkHz\n", radio->rx_frequency);
+
+		} else {
+			r = wl1273_fm_read_reg(core, WL1273_CHANL_SET, &freq);
+			if (r)
+				goto out;
+
+			dev_dbg(radio->dev, "%dkHz\n", freq);
+		}
+		dev_dbg(radio->dev, "%s: NOT BUSY\n", __func__);
+	}
+
+out:
+	wl1273_fm_write_cmd(core, WL1273_INT_MASK_SET,
+			    radio->irq_flags);
+	complete(&radio->busy);
+
+	return IRQ_HANDLED;
+}
+
+static int wl1273_fm_set_tx_freq(struct wl1273_device *radio, unsigned int freq)
+{
+	struct wl1273_core *core = radio->core;
+	int r = 0;
+
+	if (freq < WL1273_BAND_TX_LOW) {
+		dev_err(radio->dev,
+			"Frequency out of range: %d < %d\n", freq,
+			WL1273_BAND_TX_LOW);
+		return -ERANGE;
+	}
+
+	if (freq > WL1273_BAND_TX_HIGH) {
+		dev_err(radio->dev,
+			"Frequency out of range: %d > %d\n", freq,
+			WL1273_BAND_TX_HIGH);
+		return -ERANGE;
+	}
+
+	/*
+	 *  The driver works better with this sleep,
+	 *  the documentation doesn't mention it.
+	 */
+	usleep_range(5000, 10000);
+
+	dev_dbg(radio->dev, "%s: freq: %d kHz\n", __func__, freq);
+
+	/* Set the current tx channel */
+	r = wl1273_fm_write_cmd(core, WL1273_CHANL_SET, freq / 10);
+	if (r)
+		return r;
+
+	INIT_COMPLETION(radio->busy);
+
+	/* wait for the FR IRQ */
+	r = wait_for_completion_timeout(&radio->busy, msecs_to_jiffies(2000));
+	if (!r)
+		return -ETIMEDOUT;
+
+	dev_dbg(radio->dev, "WL1273_CHANL_SET: %d\n", r);
+
+	/* Enable the output power */
+	r = wl1273_fm_write_cmd(core, WL1273_POWER_ENB_SET, 1);
+	if (r)
+		return r;
+
+	INIT_COMPLETION(radio->busy);
+
+	/* wait for the POWER_ENB IRQ */
+	r = wait_for_completion_timeout(&radio->busy, msecs_to_jiffies(1000));
+	if (!r)
+		return -ETIMEDOUT;
+
+	radio->tx_frequency = freq;
+	dev_dbg(radio->dev, "WL1273_POWER_ENB_SET: %d\n", r);
+
+	return	0;
+}
+
+static int wl1273_fm_set_rx_freq(struct wl1273_device *radio, unsigned int freq)
+{
+	struct wl1273_core *core = radio->core;
+	int r, f;
+
+	if (freq < radio->rangelow) {
+		dev_err(radio->dev,
+			"Frequency out of range: %d < %d\n", freq,
+			radio->rangelow);
+		r = -ERANGE;
+		goto err;
+	}
+
+	if (freq > radio->rangehigh) {
+		dev_err(radio->dev,
+			"Frequency out of range: %d > %d\n", freq,
+			radio->rangehigh);
+		r = -ERANGE;
+		goto err;
+	}
+
+	dev_dbg(radio->dev, "%s: %dkHz\n", __func__, freq);
+
+	wl1273_fm_write_cmd(core, WL1273_INT_MASK_SET, radio->irq_flags);
+
+	if (radio->band == WL1273_BAND_JAPAN)
+		f = (freq - WL1273_BAND_JAPAN_LOW) / 50;
+	else
+		f = (freq - WL1273_BAND_OTHER_LOW) / 50;
+
+	r = wl1273_fm_write_cmd(core, WL1273_FREQ_SET, f);
+	if (r) {
+		dev_err(radio->dev, "FREQ_SET fails\n");
+		goto err;
+	}
+
+	r = wl1273_fm_write_cmd(core, WL1273_TUNER_MODE_SET, TUNER_MODE_PRESET);
+	if (r) {
+		dev_err(radio->dev, "TUNER_MODE_SET fails\n");
+		goto err;
+	}
+
+	INIT_COMPLETION(radio->busy);
+
+	r = wait_for_completion_timeout(&radio->busy, msecs_to_jiffies(2000));
+	if (!r) {
+		dev_err(radio->dev, "%s: TIMEOUT\n", __func__);
+		return -ETIMEDOUT;
+	}
+
+	radio->rd_index = 0;
+	radio->wr_index = 0;
+	radio->rx_frequency = freq;
+	return 0;
+err:
+	return r;
+}
+
+static int wl1273_fm_get_freq(struct wl1273_device *radio)
+{
+	struct wl1273_core *core = radio->core;
+	unsigned int freq;
+	u16 f;
+	int r;
+
+	if (core->mode == WL1273_MODE_RX) {
+		r = wl1273_fm_read_reg(core, WL1273_FREQ_SET, &f);
+		if (r)
+			return r;
+
+		dev_dbg(radio->dev, "Freq get: 0x%04x\n", f);
+		if (radio->band == WL1273_BAND_JAPAN)
+			freq = WL1273_BAND_JAPAN_LOW + 50 * f;
+		else
+			freq = WL1273_BAND_OTHER_LOW + 50 * f;
+	} else {
+		r = wl1273_fm_read_reg(core, WL1273_CHANL_SET, &f);
+		if (r)
+			return r;
+
+		freq = f * 10;
+	}
+
+	return freq;
+}
+
+/**
+ * wl1273_fm_upload_firmware_patch() -	Upload the firmware.
+ * @radio:				A pointer to the device struct.
+ *
+ * The firmware file consists of arrays of bytes where the first byte
+ * gives the array length. The first byte in the file gives the
+ * number of these arrays.
+ */
+static int wl1273_fm_upload_firmware_patch(struct wl1273_device *radio)
+{
+	struct wl1273_core *core = radio->core;
+	unsigned int packet_num;
+	const struct firmware *fw_p;
+	const char *fw_name = "/*(DEBLOBBED)*/";
+	struct device *dev = radio->dev;
+	__u8 *ptr;
+	int r;
+
+	dev_dbg(dev, "%s:\n", __func__);
+
+	/*
+	 * Uploading the firmware patch is not always necessary,
+	 * so we only print an info message.
+	 */
+	if (reject_firmware(&fw_p, fw_name, dev)) {
+		dev_info(dev, "%s - %s not found\n", __func__, fw_name);
+
+		return 0;
+	}
+
+	ptr = (__u8 *) fw_p->data;
+	packet_num = ptr[0];
+	dev_dbg(dev, "%s: packets: %d\n", __func__, packet_num);
+
+	r = wl1273_fm_write_fw(core, ptr + 1, packet_num);
+	if (r) {
+		dev_err(dev, "FW upload error: %d\n", r);
+		goto out;
+	}
+
+	/* ignore possible error here */
+	wl1273_fm_write_cmd(core, WL1273_RESET, 0);
+
+	dev_dbg(dev, "%s - download OK, r: %d\n", __func__, r);
+out:
+	release_firmware(fw_p);
+	return r;
+}
+
+static int wl1273_fm_stop(struct wl1273_device *radio)
+{
+	struct wl1273_core *core = radio->core;
+
+	if (core->mode == WL1273_MODE_RX) {
+		int r = wl1273_fm_write_cmd(core, WL1273_POWER_SET,
+				    WL1273_POWER_SET_OFF);
+		if (r)
+			dev_err(radio->dev, "%s: POWER_SET fails: %d\n",
+				__func__, r);
+	} else if (core->mode == WL1273_MODE_TX) {
+		int r = wl1273_fm_write_cmd(core, WL1273_PUPD_SET,
+					    WL1273_PUPD_SET_OFF);
+		if (r)
+			dev_err(radio->dev,
+				"%s: PUPD_SET fails: %d\n", __func__, r);
+	}
+
+	if (core->pdata->disable) {
+		core->pdata->disable();
+		dev_dbg(radio->dev, "Back to reset\n");
+	}
+
+	return 0;
+}
+
+static int wl1273_fm_start(struct wl1273_device *radio, int new_mode)
+{
+	struct wl1273_core *core = radio->core;
+	struct wl1273_fm_platform_data *pdata = core->pdata;
+	struct device *dev = radio->dev;
+	int r = -EINVAL;
+
+	if (pdata->enable && core->mode == WL1273_MODE_OFF) {
+		dev_dbg(radio->dev, "Out of reset\n");
+
+		pdata->enable();
+		msleep(250);
+	}
+
+	if (new_mode == WL1273_MODE_RX) {
+		u16 val = WL1273_POWER_SET_FM;
+
+		if (radio->rds_on)
+			val |= WL1273_POWER_SET_RDS;
+
+		/* If this fails try again */
+		r = wl1273_fm_write_cmd(core, WL1273_POWER_SET, val);
+		if (r) {
+			msleep(100);
+
+			r = wl1273_fm_write_cmd(core, WL1273_POWER_SET, val);
+			if (r) {
+				dev_err(dev, "%s: POWER_SET fails\n", __func__);
+				goto fail;
+			}
+		}
+
+		/* rds buffer configuration */
+		radio->wr_index = 0;
+		radio->rd_index = 0;
+
+	} else if (new_mode == WL1273_MODE_TX) {
+		/* If this fails try again once */
+		r = wl1273_fm_write_cmd(core, WL1273_PUPD_SET,
+					WL1273_PUPD_SET_ON);
+		if (r) {
+			msleep(100);
+			r = wl1273_fm_write_cmd(core, WL1273_PUPD_SET,
+					WL1273_PUPD_SET_ON);
+			if (r) {
+				dev_err(dev, "%s: PUPD_SET fails\n", __func__);
+				goto fail;
+			}
+		}
+
+		if (radio->rds_on)
+			r = wl1273_fm_write_cmd(core, WL1273_RDS_DATA_ENB, 1);
+		else
+			r = wl1273_fm_write_cmd(core, WL1273_RDS_DATA_ENB, 0);
+	} else {
+		dev_warn(dev, "%s: Illegal mode.\n", __func__);
+	}
+
+	if (core->mode == WL1273_MODE_OFF) {
+		r = wl1273_fm_upload_firmware_patch(radio);
+		if (r)
+			dev_warn(dev, "Firmware upload failed.\n");
+
+		/*
+		 * Sometimes the chip is in a wrong power state at this point.
+		 * So we set the power once again.
+		 */
+		if (new_mode == WL1273_MODE_RX) {
+			u16 val = WL1273_POWER_SET_FM;
+
+			if (radio->rds_on)
+				val |= WL1273_POWER_SET_RDS;
+
+			r = wl1273_fm_write_cmd(core, WL1273_POWER_SET, val);
+			if (r) {
+				dev_err(dev, "%s: POWER_SET fails\n", __func__);
+				goto fail;
+			}
+		} else if (new_mode == WL1273_MODE_TX) {
+			r = wl1273_fm_write_cmd(core, WL1273_PUPD_SET,
+						WL1273_PUPD_SET_ON);
+			if (r) {
+				dev_err(dev, "%s: PUPD_SET fails\n", __func__);
+				goto fail;
+			}
+		}
+	}
+
+	return 0;
+fail:
+	if (pdata->disable)
+		pdata->disable();
+
+	dev_dbg(dev, "%s: return: %d\n", __func__, r);
+	return r;
+}
+
+static int wl1273_fm_suspend(struct wl1273_device *radio)
+{
+	struct wl1273_core *core = radio->core;
+	int r = 0;
+
+	/* Cannot go from OFF to SUSPENDED */
+	if (core->mode == WL1273_MODE_RX)
+		r = wl1273_fm_write_cmd(core, WL1273_POWER_SET,
+				WL1273_POWER_SET_RETENTION);
+	else if (core->mode == WL1273_MODE_TX)
+		r = wl1273_fm_write_cmd(core, WL1273_PUPD_SET,
+				WL1273_PUPD_SET_RETENTION);
+	else
+		r = -EINVAL;
+
+	if (r) {
+		dev_err(radio->dev, "%s: POWER_SET fails: %d\n", __func__, r);
+		goto out;
+	}
+
+out:
+	return r;
+}
+
+static int wl1273_fm_set_mode(struct wl1273_device *radio, int mode)
+{
+	struct wl1273_core *core = radio->core;
+	struct device *dev = radio->dev;
+	int old_mode;
+	int r;
+
+	dev_dbg(dev, "%s\n", __func__);
+	dev_dbg(dev, "Forbidden modes: 0x%02x\n", radio->forbidden);
+
+	old_mode = core->mode;
+	if (mode & radio->forbidden) {
+		r = -EPERM;
+		goto out;
+	}
+
+	switch (mode) {
+	case WL1273_MODE_RX:
+	case WL1273_MODE_TX:
+		r = wl1273_fm_start(radio, mode);
+		if (r) {
+			dev_err(dev, "%s: Cannot start.\n", __func__);
+			wl1273_fm_stop(radio);
+			goto out;
+		}
+
+		core->mode = mode;
+		r = wl1273_fm_write_cmd(core, WL1273_INT_MASK_SET,
+					radio->irq_flags);
+		if (r) {
+			dev_err(dev, "INT_MASK_SET fails.\n");
+			goto out;
+		}
+
+		/* remember previous settings */
+		if (mode == WL1273_MODE_RX) {
+			r = wl1273_fm_set_rx_freq(radio, radio->rx_frequency);
+			if (r) {
+				dev_err(dev, "set freq fails: %d.\n", r);
+				goto out;
+			}
+
+			r = core->set_volume(core, core->volume);
+			if (r) {
+				dev_err(dev, "set volume fails: %d.\n", r);
+				goto out;
+			}
+
+			dev_dbg(dev, "%s: Set vol: %d.\n", __func__,
+				core->volume);
+		} else {
+			r = wl1273_fm_set_tx_freq(radio, radio->tx_frequency);
+			if (r) {
+				dev_err(dev, "set freq fails: %d.\n", r);
+				goto out;
+			}
+		}
+
+		dev_dbg(radio->dev, "%s: Set audio mode.\n", __func__);
+
+		r = core->set_audio(core, core->audio_mode);
+		if (r)
+			dev_err(dev, "Cannot set audio mode.\n");
+		break;
+
+	case WL1273_MODE_OFF:
+		r = wl1273_fm_stop(radio);
+		if (r)
+			dev_err(dev, "%s: Off fails: %d\n", __func__, r);
+		else
+			core->mode = WL1273_MODE_OFF;
+
+		break;
+
+	case WL1273_MODE_SUSPENDED:
+		r = wl1273_fm_suspend(radio);
+		if (r)
+			dev_err(dev, "%s: Suspend fails: %d\n", __func__, r);
+		else
+			core->mode = WL1273_MODE_SUSPENDED;
+
+		break;
+
+	default:
+		dev_err(dev, "%s: Unknown mode: %d\n", __func__, mode);
+		r = -EINVAL;
+		break;
+	}
+out:
+	if (r)
+		core->mode = old_mode;
+
+	return r;
+}
+
+static int wl1273_fm_set_seek(struct wl1273_device *radio,
+			      unsigned int wrap_around,
+			      unsigned int seek_upward,
+			      int level)
+{
+	struct wl1273_core *core = radio->core;
+	int r = 0;
+	unsigned int dir = (seek_upward == 0) ? 0 : 1;
+	unsigned int f;
+
+	f = radio->rx_frequency;
+	dev_dbg(radio->dev, "rx_frequency: %d\n", f);
+
+	if (dir && f + radio->spacing <= radio->rangehigh)
+		r = wl1273_fm_set_rx_freq(radio, f + radio->spacing);
+	else if (dir && wrap_around)
+		r = wl1273_fm_set_rx_freq(radio, radio->rangelow);
+	else if (f - radio->spacing >= radio->rangelow)
+		r = wl1273_fm_set_rx_freq(radio, f - radio->spacing);
+	else if (wrap_around)
+		r = wl1273_fm_set_rx_freq(radio, radio->rangehigh);
+
+	if (r)
+		goto out;
+
+	if (level < SCHAR_MIN || level > SCHAR_MAX)
+		return -EINVAL;
+
+	INIT_COMPLETION(radio->busy);
+	dev_dbg(radio->dev, "%s: BUSY\n", __func__);
+
+	r = wl1273_fm_write_cmd(core, WL1273_INT_MASK_SET, radio->irq_flags);
+	if (r)
+		goto out;
+
+	dev_dbg(radio->dev, "%s\n", __func__);
+
+	r = wl1273_fm_write_cmd(core, WL1273_SEARCH_LVL_SET, level);
+	if (r)
+		goto out;
+
+	r = wl1273_fm_write_cmd(core, WL1273_SEARCH_DIR_SET, dir);
+	if (r)
+		goto out;
+
+	r = wl1273_fm_write_cmd(core, WL1273_TUNER_MODE_SET,
+				TUNER_MODE_AUTO_SEEK);
+	if (r)
+		goto out;
+
+	wait_for_completion_timeout(&radio->busy, msecs_to_jiffies(1000));
+	if (!(radio->irq_received & WL1273_BL_EVENT))
+		goto out;
+
+	radio->irq_received &= ~WL1273_BL_EVENT;
+
+	if (!wrap_around)
+		goto out;
+
+	/* Wrap around */
+	dev_dbg(radio->dev, "Wrap around in HW seek.\n");
+
+	if (seek_upward)
+		f = radio->rangelow;
+	else
+		f = radio->rangehigh;
+
+	r = wl1273_fm_set_rx_freq(radio, f);
+	if (r)
+		goto out;
+
+	INIT_COMPLETION(radio->busy);
+	dev_dbg(radio->dev, "%s: BUSY\n", __func__);
+
+	r = wl1273_fm_write_cmd(core, WL1273_TUNER_MODE_SET,
+				TUNER_MODE_AUTO_SEEK);
+	if (r)
+		goto out;
+
+	wait_for_completion_timeout(&radio->busy, msecs_to_jiffies(1000));
+out:
+	dev_dbg(radio->dev, "%s: Err: %d\n", __func__, r);
+	return r;
+}
+
+/**
+ * wl1273_fm_get_tx_ctune() -	Get the TX tuning capacitor value.
+ * @radio:			A pointer to the device struct.
+ */
+static unsigned int wl1273_fm_get_tx_ctune(struct wl1273_device *radio)
+{
+	struct wl1273_core *core = radio->core;
+	struct device *dev = radio->dev;
+	u16 val;
+	int r;
+
+	if (core->mode == WL1273_MODE_OFF ||
+	    core->mode == WL1273_MODE_SUSPENDED)
+		return -EPERM;
+
+	r = wl1273_fm_read_reg(core, WL1273_READ_FMANT_TUNE_VALUE, &val);
+	if (r) {
+		dev_err(dev, "%s: read error: %d\n", __func__, r);
+		goto out;
+	}
+
+out:
+	return val;
+}
+
+/**
+ * wl1273_fm_set_preemphasis() - Set the TX pre-emphasis value.
+ * @radio:			 A pointer to the device struct.
+ * @preemphasis:		 The new pre-amphasis value.
+ *
+ * Possible pre-emphasis values are: V4L2_PREEMPHASIS_DISABLED,
+ * V4L2_PREEMPHASIS_50_uS and V4L2_PREEMPHASIS_75_uS.
+ */
+static int wl1273_fm_set_preemphasis(struct wl1273_device *radio,
+				     unsigned int preemphasis)
+{
+	struct wl1273_core *core = radio->core;
+	int r;
+	u16 em;
+
+	if (core->mode == WL1273_MODE_OFF ||
+	    core->mode == WL1273_MODE_SUSPENDED)
+		return -EPERM;
+
+	mutex_lock(&core->lock);
+
+	switch (preemphasis) {
+	case V4L2_PREEMPHASIS_DISABLED:
+		em = 1;
+		break;
+	case V4L2_PREEMPHASIS_50_uS:
+		em = 0;
+		break;
+	case V4L2_PREEMPHASIS_75_uS:
+		em = 2;
+		break;
+	default:
+		r = -EINVAL;
+		goto out;
+	}
+
+	r = wl1273_fm_write_cmd(core, WL1273_PREMPH_SET, em);
+	if (r)
+		goto out;
+
+	radio->preemphasis = preemphasis;
+
+out:
+	mutex_unlock(&core->lock);
+	return r;
+}
+
+static int wl1273_fm_rds_on(struct wl1273_device *radio)
+{
+	struct wl1273_core *core = radio->core;
+	int r;
+
+	dev_dbg(radio->dev, "%s\n", __func__);
+	if (radio->rds_on)
+		return 0;
+
+	r = wl1273_fm_write_cmd(core, WL1273_POWER_SET,
+			WL1273_POWER_SET_FM | WL1273_POWER_SET_RDS);
+	if (r)
+		goto out;
+
+	r = wl1273_fm_set_rx_freq(radio, radio->rx_frequency);
+	if (r)
+		dev_err(radio->dev, "set freq fails: %d.\n", r);
+out:
+	return r;
+}
+
+static int wl1273_fm_rds_off(struct wl1273_device *radio)
+{
+	struct wl1273_core *core = radio->core;
+	int r;
+
+	if (!radio->rds_on)
+		return 0;
+
+	radio->irq_flags &= ~WL1273_RDS_EVENT;
+
+	r = wl1273_fm_write_cmd(core, WL1273_INT_MASK_SET, radio->irq_flags);
+	if (r)
+		goto out;
+
+	/* stop rds reception */
+	cancel_delayed_work(&radio->work);
+
+	/* Service pending read */
+	wake_up_interruptible(&radio->read_queue);
+
+	dev_dbg(radio->dev, "%s\n", __func__);
+
+	r = wl1273_fm_write_cmd(core, WL1273_POWER_SET, WL1273_POWER_SET_FM);
+	if (r)
+		goto out;
+
+	r = wl1273_fm_set_rx_freq(radio, radio->rx_frequency);
+	if (r)
+		dev_err(radio->dev, "set freq fails: %d.\n", r);
+out:
+	dev_dbg(radio->dev, "%s: exiting...\n", __func__);
+
+	return r;
+}
+
+static int wl1273_fm_set_rds(struct wl1273_device *radio, unsigned int new_mode)
+{
+	int r = 0;
+	struct wl1273_core *core = radio->core;
+
+	if (core->mode == WL1273_MODE_OFF ||
+	    core->mode == WL1273_MODE_SUSPENDED)
+		return -EPERM;
+
+	if (new_mode == WL1273_RDS_RESET) {
+		r = wl1273_fm_write_cmd(core, WL1273_RDS_CNTRL_SET, 1);
+		return r;
+	}
+
+	if (core->mode == WL1273_MODE_TX && new_mode == WL1273_RDS_OFF) {
+		r = wl1273_fm_write_cmd(core, WL1273_RDS_DATA_ENB, 0);
+	} else if (core->mode == WL1273_MODE_TX && new_mode == WL1273_RDS_ON) {
+		r = wl1273_fm_write_cmd(core, WL1273_RDS_DATA_ENB, 1);
+	} else if (core->mode == WL1273_MODE_RX && new_mode == WL1273_RDS_OFF) {
+		r = wl1273_fm_rds_off(radio);
+	} else if (core->mode == WL1273_MODE_RX && new_mode == WL1273_RDS_ON) {
+		r = wl1273_fm_rds_on(radio);
+	} else {
+		dev_err(radio->dev, "%s: Unknown mode: %d\n",
+			__func__, new_mode);
+		r = -EINVAL;
+	}
+
+	if (!r)
+		radio->rds_on = (new_mode == WL1273_RDS_ON) ? true : false;
+
+	return r;
+}
+
+static ssize_t wl1273_fm_fops_write(struct file *file, const char __user *buf,
+				    size_t count, loff_t *ppos)
+{
+	struct wl1273_device *radio = video_get_drvdata(video_devdata(file));
+	u16 val;
+	int r;
+
+	dev_dbg(radio->dev, "%s\n", __func__);
+
+	if (radio->core->mode != WL1273_MODE_TX)
+		return count;
+
+	if (radio->rds_users == 0) {
+		dev_warn(radio->dev, "%s: RDS not on.\n", __func__);
+		return 0;
+	}
+
+	if (mutex_lock_interruptible(&radio->core->lock))
+		return -EINTR;
+	/*
+	 * Multiple processes can open the device, but only
+	 * one gets to write to it.
+	 */
+	if (radio->owner && radio->owner != file) {
+		r = -EBUSY;
+		goto out;
+	}
+	radio->owner = file;
+
+	/* Manual Mode */
+	if (count > 255)
+		val = 255;
+	else
+		val = count;
+
+	wl1273_fm_write_cmd(radio->core, WL1273_RDS_CONFIG_DATA_SET, val);
+
+	if (copy_from_user(radio->write_buf + 1, buf, val)) {
+		r = -EFAULT;
+		goto out;
+	}
+
+	dev_dbg(radio->dev, "Count: %d\n", val);
+	dev_dbg(radio->dev, "From user: \"%s\"\n", radio->write_buf);
+
+	radio->write_buf[0] = WL1273_RDS_DATA_SET;
+	wl1273_fm_write_data(radio->core, radio->write_buf, val + 1);
+
+	r = val;
+out:
+	mutex_unlock(&radio->core->lock);
+
+	return r;
+}
+
+static unsigned int wl1273_fm_fops_poll(struct file *file,
+					struct poll_table_struct *pts)
+{
+	struct wl1273_device *radio = video_get_drvdata(video_devdata(file));
+	struct wl1273_core *core = radio->core;
+
+	if (radio->owner && radio->owner != file)
+		return -EBUSY;
+
+	radio->owner = file;
+
+	if (core->mode == WL1273_MODE_RX) {
+		poll_wait(file, &radio->read_queue, pts);
+
+		if (radio->rd_index != radio->wr_index)
+			return POLLIN | POLLRDNORM;
+
+	} else if (core->mode == WL1273_MODE_TX) {
+		return POLLOUT | POLLWRNORM;
+	}
+
+	return 0;
+}
+
+static int wl1273_fm_fops_open(struct file *file)
+{
+	struct wl1273_device *radio = video_get_drvdata(video_devdata(file));
+	struct wl1273_core *core = radio->core;
+	int r = 0;
+
+	dev_dbg(radio->dev, "%s\n", __func__);
+
+	if (core->mode == WL1273_MODE_RX && radio->rds_on &&
+	    !radio->rds_users) {
+		dev_dbg(radio->dev, "%s: Mode: %d\n", __func__, core->mode);
+
+		if (mutex_lock_interruptible(&core->lock))
+			return -EINTR;
+
+		radio->irq_flags |= WL1273_RDS_EVENT;
+
+		r = wl1273_fm_write_cmd(core, WL1273_INT_MASK_SET,
+					radio->irq_flags);
+		if (r) {
+			mutex_unlock(&core->lock);
+			goto out;
+		}
+
+		radio->rds_users++;
+
+		mutex_unlock(&core->lock);
+	}
+out:
+	return r;
+}
+
+static int wl1273_fm_fops_release(struct file *file)
+{
+	struct wl1273_device *radio = video_get_drvdata(video_devdata(file));
+	struct wl1273_core *core = radio->core;
+	int r = 0;
+
+	dev_dbg(radio->dev, "%s\n", __func__);
+
+	if (radio->rds_users > 0) {
+		radio->rds_users--;
+		if (radio->rds_users == 0) {
+			if (mutex_lock_interruptible(&core->lock))
+				return -EINTR;
+
+			radio->irq_flags &= ~WL1273_RDS_EVENT;
+
+			if (core->mode == WL1273_MODE_RX) {
+				r = wl1273_fm_write_cmd(core,
+							WL1273_INT_MASK_SET,
+							radio->irq_flags);
+				if (r) {
+					mutex_unlock(&core->lock);
+					goto out;
+				}
+			}
+			mutex_unlock(&core->lock);
+		}
+	}
+
+	if (file == radio->owner)
+		radio->owner = NULL;
+out:
+	return r;
+}
+
+static ssize_t wl1273_fm_fops_read(struct file *file, char __user *buf,
+				   size_t count, loff_t *ppos)
+{
+	int r = 0;
+	struct wl1273_device *radio = video_get_drvdata(video_devdata(file));
+	struct wl1273_core *core = radio->core;
+	unsigned int block_count = 0;
+	u16 val;
+
+	dev_dbg(radio->dev, "%s\n", __func__);
+
+	if (radio->core->mode != WL1273_MODE_RX)
+		return 0;
+
+	if (radio->rds_users == 0) {
+		dev_warn(radio->dev, "%s: RDS not on.\n", __func__);
+		return 0;
+	}
+
+	if (mutex_lock_interruptible(&core->lock))
+		return -EINTR;
+
+	/*
+	 * Multiple processes can open the device, but only
+	 * one at a time gets read access.
+	 */
+	if (radio->owner && radio->owner != file) {
+		r = -EBUSY;
+		goto out;
+	}
+	radio->owner = file;
+
+	r = wl1273_fm_read_reg(core, WL1273_RDS_SYNC_GET, &val);
+	if (r) {
+		dev_err(radio->dev, "%s: Get RDS_SYNC fails.\n", __func__);
+		goto out;
+	} else if (val == 0) {
+		dev_info(radio->dev, "RDS_SYNC: Not synchronized\n");
+		r = -ENODATA;
+		goto out;
+	}
+
+	/* block if no new data available */
+	while (radio->wr_index == radio->rd_index) {
+		if (file->f_flags & O_NONBLOCK) {
+			r = -EWOULDBLOCK;
+			goto out;
+		}
+
+		dev_dbg(radio->dev, "%s: Wait for RDS data.\n", __func__);
+		if (wait_event_interruptible(radio->read_queue,
+					     radio->wr_index !=
+					     radio->rd_index) < 0) {
+			r = -EINTR;
+			goto out;
+		}
+	}
+
+	/* calculate block count from byte count */
+	count /= RDS_BLOCK_SIZE;
+
+	/* copy RDS blocks from the internal buffer and to user buffer */
+	while (block_count < count) {
+		if (radio->rd_index == radio->wr_index)
+			break;
+
+		/* always transfer complete RDS blocks */
+		if (copy_to_user(buf, &radio->buffer[radio->rd_index],
+				 RDS_BLOCK_SIZE))
+			break;
+
+		/* increment and wrap the read pointer */
+		radio->rd_index += RDS_BLOCK_SIZE;
+		if (radio->rd_index >= radio->buf_size)
+			radio->rd_index = 0;
+
+		/* increment counters */
+		block_count++;
+		buf += RDS_BLOCK_SIZE;
+		r += RDS_BLOCK_SIZE;
+	}
+
+out:
+	dev_dbg(radio->dev, "%s: exit\n", __func__);
+	mutex_unlock(&core->lock);
+
+	return r;
+}
+
+static const struct v4l2_file_operations wl1273_fops = {
+	.owner		= THIS_MODULE,
+	.read		= wl1273_fm_fops_read,
+	.write		= wl1273_fm_fops_write,
+	.poll		= wl1273_fm_fops_poll,
+	.unlocked_ioctl	= video_ioctl2,
+	.open		= wl1273_fm_fops_open,
+	.release	= wl1273_fm_fops_release,
+};
+
+static int wl1273_fm_vidioc_querycap(struct file *file, void *priv,
+				     struct v4l2_capability *capability)
+{
+	struct wl1273_device *radio = video_get_drvdata(video_devdata(file));
+
+	dev_dbg(radio->dev, "%s\n", __func__);
+
+	strlcpy(capability->driver, WL1273_FM_DRIVER_NAME,
+		sizeof(capability->driver));
+	strlcpy(capability->card, "Texas Instruments Wl1273 FM Radio",
+		sizeof(capability->card));
+	strlcpy(capability->bus_info, radio->bus_type,
+		sizeof(capability->bus_info));
+
+	capability->capabilities = V4L2_CAP_HW_FREQ_SEEK |
+		V4L2_CAP_TUNER | V4L2_CAP_RADIO | V4L2_CAP_AUDIO |
+		V4L2_CAP_RDS_CAPTURE | V4L2_CAP_MODULATOR |
+		V4L2_CAP_RDS_OUTPUT;
+
+	return 0;
+}
+
+static int wl1273_fm_vidioc_g_input(struct file *file, void *priv,
+				    unsigned int *i)
+{
+	struct wl1273_device *radio = video_get_drvdata(video_devdata(file));
+
+	dev_dbg(radio->dev, "%s\n", __func__);
+
+	*i = 0;
+
+	return 0;
+}
+
+static int wl1273_fm_vidioc_s_input(struct file *file, void *priv,
+				    unsigned int i)
+{
+	struct wl1273_device *radio = video_get_drvdata(video_devdata(file));
+
+	dev_dbg(radio->dev, "%s\n", __func__);
+
+	if (i != 0)
+		return -EINVAL;
+
+	return 0;
+}
+
+/**
+ * wl1273_fm_set_tx_power() -	Set the transmission power value.
+ * @core:			A pointer to the device struct.
+ * @power:			The new power value.
+ */
+static int wl1273_fm_set_tx_power(struct wl1273_device *radio, u16 power)
+{
+	int r;
+
+	if (radio->core->mode == WL1273_MODE_OFF ||
+	    radio->core->mode == WL1273_MODE_SUSPENDED)
+		return -EPERM;
+
+	mutex_lock(&radio->core->lock);
+
+	/* Convert the dBuV value to chip presentation */
+	r = wl1273_fm_write_cmd(radio->core, WL1273_POWER_LEV_SET, 122 - power);
+	if (r)
+		goto out;
+
+	radio->tx_power = power;
+
+out:
+	mutex_unlock(&radio->core->lock);
+	return r;
+}
+
+#define WL1273_SPACING_50kHz	1
+#define WL1273_SPACING_100kHz	2
+#define WL1273_SPACING_200kHz	4
+
+static int wl1273_fm_tx_set_spacing(struct wl1273_device *radio,
+				    unsigned int spacing)
+{
+	int r;
+
+	if (spacing == 0) {
+		r = wl1273_fm_write_cmd(radio->core, WL1273_SCAN_SPACING_SET,
+					WL1273_SPACING_100kHz);
+		radio->spacing = 100;
+	} else if (spacing - 50000 < 25000) {
+		r = wl1273_fm_write_cmd(radio->core, WL1273_SCAN_SPACING_SET,
+					WL1273_SPACING_50kHz);
+		radio->spacing = 50;
+	} else if (spacing - 100000 < 50000) {
+		r = wl1273_fm_write_cmd(radio->core, WL1273_SCAN_SPACING_SET,
+					WL1273_SPACING_100kHz);
+		radio->spacing = 100;
+	} else {
+		r = wl1273_fm_write_cmd(radio->core, WL1273_SCAN_SPACING_SET,
+					WL1273_SPACING_200kHz);
+		radio->spacing = 200;
+	}
+
+	return r;
+}
+
+static int wl1273_fm_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct wl1273_device *radio = ctrl->priv;
+	struct wl1273_core *core = radio->core;
+
+	dev_dbg(radio->dev, "%s\n", __func__);
+
+	if (mutex_lock_interruptible(&core->lock))
+		return -EINTR;
+
+	switch (ctrl->id) {
+	case  V4L2_CID_TUNE_ANTENNA_CAPACITOR:
+		ctrl->val = wl1273_fm_get_tx_ctune(radio);
+		break;
+
+	default:
+		dev_warn(radio->dev, "%s: Unknown IOCTL: %d\n",
+			 __func__, ctrl->id);
+		break;
+	}
+
+	mutex_unlock(&core->lock);
+
+	return 0;
+}
+
+#define WL1273_MUTE_SOFT_ENABLE    (1 << 0)
+#define WL1273_MUTE_AC             (1 << 1)
+#define WL1273_MUTE_HARD_LEFT      (1 << 2)
+#define WL1273_MUTE_HARD_RIGHT     (1 << 3)
+#define WL1273_MUTE_SOFT_FORCE     (1 << 4)
+
+static inline struct wl1273_device *to_radio(struct v4l2_ctrl *ctrl)
+{
+	return container_of(ctrl->handler, struct wl1273_device, ctrl_handler);
+}
+
+static int wl1273_fm_vidioc_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct wl1273_device *radio = to_radio(ctrl);
+	struct wl1273_core *core = radio->core;
+	int r = 0;
+
+	dev_dbg(radio->dev, "%s\n", __func__);
+
+	switch (ctrl->id) {
+	case V4L2_CID_AUDIO_MUTE:
+		if (mutex_lock_interruptible(&core->lock))
+			return -EINTR;
+
+		if (core->mode == WL1273_MODE_RX && ctrl->val)
+			r = wl1273_fm_write_cmd(core,
+						WL1273_MUTE_STATUS_SET,
+						WL1273_MUTE_HARD_LEFT |
+						WL1273_MUTE_HARD_RIGHT);
+		else if (core->mode == WL1273_MODE_RX)
+			r = wl1273_fm_write_cmd(core,
+						WL1273_MUTE_STATUS_SET, 0x0);
+		else if (core->mode == WL1273_MODE_TX && ctrl->val)
+			r = wl1273_fm_write_cmd(core, WL1273_MUTE, 1);
+		else if (core->mode == WL1273_MODE_TX)
+			r = wl1273_fm_write_cmd(core, WL1273_MUTE, 0);
+
+		mutex_unlock(&core->lock);
+		break;
+
+	case V4L2_CID_AUDIO_VOLUME:
+		if (ctrl->val == 0)
+			r = wl1273_fm_set_mode(radio, WL1273_MODE_OFF);
+		else
+			r =  core->set_volume(core, core->volume);
+		break;
+
+	case V4L2_CID_TUNE_PREEMPHASIS:
+		r = wl1273_fm_set_preemphasis(radio, ctrl->val);
+		break;
+
+	case V4L2_CID_TUNE_POWER_LEVEL:
+		r = wl1273_fm_set_tx_power(radio, ctrl->val);
+		break;
+
+	default:
+		dev_warn(radio->dev, "%s: Unknown IOCTL: %d\n",
+			 __func__, ctrl->id);
+		break;
+	}
+
+	dev_dbg(radio->dev, "%s\n", __func__);
+	return r;
+}
+
+static int wl1273_fm_vidioc_g_audio(struct file *file, void *priv,
+				    struct v4l2_audio *audio)
+{
+	struct wl1273_device *radio = video_get_drvdata(video_devdata(file));
+
+	dev_dbg(radio->dev, "%s\n", __func__);
+
+	if (audio->index > 1)
+		return -EINVAL;
+
+	strlcpy(audio->name, "Radio", sizeof(audio->name));
+	audio->capability = V4L2_AUDCAP_STEREO;
+
+	return 0;
+}
+
+static int wl1273_fm_vidioc_s_audio(struct file *file, void *priv,
+				    struct v4l2_audio *audio)
+{
+	struct wl1273_device *radio = video_get_drvdata(video_devdata(file));
+
+	dev_dbg(radio->dev, "%s\n", __func__);
+
+	if (audio->index != 0)
+		return -EINVAL;
+
+	return 0;
+}
+
+#define WL1273_RDS_NOT_SYNCHRONIZED 0
+#define WL1273_RDS_SYNCHRONIZED 1
+
+static int wl1273_fm_vidioc_g_tuner(struct file *file, void *priv,
+				    struct v4l2_tuner *tuner)
+{
+	struct wl1273_device *radio = video_get_drvdata(video_devdata(file));
+	struct wl1273_core *core = radio->core;
+	u16 val;
+	int r;
+
+	dev_dbg(radio->dev, "%s\n", __func__);
+
+	if (tuner->index > 0)
+		return -EINVAL;
+
+	strlcpy(tuner->name, WL1273_FM_DRIVER_NAME, sizeof(tuner->name));
+	tuner->type = V4L2_TUNER_RADIO;
+
+	tuner->rangelow	= WL1273_FREQ(WL1273_BAND_JAPAN_LOW);
+	tuner->rangehigh = WL1273_FREQ(WL1273_BAND_OTHER_HIGH);
+
+	tuner->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_RDS |
+		V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_RDS_BLOCK_IO;
+
+	if (radio->stereo)
+		tuner->audmode = V4L2_TUNER_MODE_STEREO;
+	else
+		tuner->audmode = V4L2_TUNER_MODE_MONO;
+
+	if (core->mode != WL1273_MODE_RX)
+		return 0;
+
+	if (mutex_lock_interruptible(&core->lock))
+		return -EINTR;
+
+	r = wl1273_fm_read_reg(core, WL1273_STEREO_GET, &val);
+	if (r)
+		goto out;
+
+	if (val == 1)
+		tuner->rxsubchans = V4L2_TUNER_SUB_STEREO;
+	else
+		tuner->rxsubchans = V4L2_TUNER_SUB_MONO;
+
+	r = wl1273_fm_read_reg(core, WL1273_RSSI_LVL_GET, &val);
+	if (r)
+		goto out;
+
+	tuner->signal = (s16) val;
+	dev_dbg(radio->dev, "Signal: %d\n", tuner->signal);
+
+	tuner->afc = 0;
+
+	r = wl1273_fm_read_reg(core, WL1273_RDS_SYNC_GET, &val);
+	if (r)
+		goto out;
+
+	if (val == WL1273_RDS_SYNCHRONIZED)
+		tuner->rxsubchans |= V4L2_TUNER_SUB_RDS;
+out:
+	mutex_unlock(&core->lock);
+
+	return r;
+}
+
+static int wl1273_fm_vidioc_s_tuner(struct file *file, void *priv,
+				    struct v4l2_tuner *tuner)
+{
+	struct wl1273_device *radio = video_get_drvdata(video_devdata(file));
+	struct wl1273_core *core = radio->core;
+	int r = 0;
+
+	dev_dbg(radio->dev, "%s\n", __func__);
+	dev_dbg(radio->dev, "tuner->index: %d\n", tuner->index);
+	dev_dbg(radio->dev, "tuner->name: %s\n", tuner->name);
+	dev_dbg(radio->dev, "tuner->capability: 0x%04x\n", tuner->capability);
+	dev_dbg(radio->dev, "tuner->rxsubchans: 0x%04x\n", tuner->rxsubchans);
+	dev_dbg(radio->dev, "tuner->rangelow: %d\n", tuner->rangelow);
+	dev_dbg(radio->dev, "tuner->rangehigh: %d\n", tuner->rangehigh);
+
+	if (tuner->index > 0)
+		return -EINVAL;
+
+	if (mutex_lock_interruptible(&core->lock))
+		return -EINTR;
+
+	r = wl1273_fm_set_mode(radio, WL1273_MODE_RX);
+	if (r)
+		goto out;
+
+	if (tuner->rxsubchans & V4L2_TUNER_SUB_RDS)
+		r = wl1273_fm_set_rds(radio, WL1273_RDS_ON);
+	else
+		r = wl1273_fm_set_rds(radio, WL1273_RDS_OFF);
+
+	if (r)
+		dev_warn(radio->dev, "%s: RDS fails: %d\n", __func__, r);
+
+	if (tuner->audmode == V4L2_TUNER_MODE_MONO) {
+		r = wl1273_fm_write_cmd(core, WL1273_MOST_MODE_SET,
+					WL1273_RX_MONO);
+		if (r < 0) {
+			dev_warn(radio->dev, "%s: MOST_MODE fails: %d\n",
+				 __func__, r);
+			goto out;
+		}
+		radio->stereo = false;
+	} else if (tuner->audmode == V4L2_TUNER_MODE_STEREO) {
+		r = wl1273_fm_write_cmd(core, WL1273_MOST_MODE_SET,
+					WL1273_RX_STEREO);
+		if (r < 0) {
+			dev_warn(radio->dev, "%s: MOST_MODE fails: %d\n",
+				 __func__, r);
+			goto out;
+		}
+		radio->stereo = true;
+	} else {
+		dev_err(radio->dev, "%s: tuner->audmode: %d\n",
+			 __func__, tuner->audmode);
+		r = -EINVAL;
+		goto out;
+	}
+
+out:
+	mutex_unlock(&core->lock);
+
+	return r;
+}
+
+static int wl1273_fm_vidioc_g_frequency(struct file *file, void *priv,
+					struct v4l2_frequency *freq)
+{
+	struct wl1273_device *radio = video_get_drvdata(video_devdata(file));
+	struct wl1273_core *core = radio->core;
+
+	dev_dbg(radio->dev, "%s\n", __func__);
+
+	if (mutex_lock_interruptible(&core->lock))
+		return -EINTR;
+
+	freq->type = V4L2_TUNER_RADIO;
+	freq->frequency = WL1273_FREQ(wl1273_fm_get_freq(radio));
+
+	mutex_unlock(&core->lock);
+
+	return 0;
+}
+
+static int wl1273_fm_vidioc_s_frequency(struct file *file, void *priv,
+					struct v4l2_frequency *freq)
+{
+	struct wl1273_device *radio = video_get_drvdata(video_devdata(file));
+	struct wl1273_core *core = radio->core;
+	int r;
+
+	dev_dbg(radio->dev, "%s: %d\n", __func__, freq->frequency);
+
+	if (freq->type != V4L2_TUNER_RADIO) {
+		dev_dbg(radio->dev,
+			"freq->type != V4L2_TUNER_RADIO: %d\n", freq->type);
+		return -EINVAL;
+	}
+
+	if (mutex_lock_interruptible(&core->lock))
+		return -EINTR;
+
+	if (core->mode == WL1273_MODE_RX) {
+		dev_dbg(radio->dev, "freq: %d\n", freq->frequency);
+
+		r = wl1273_fm_set_rx_freq(radio,
+					  WL1273_INV_FREQ(freq->frequency));
+		if (r)
+			dev_warn(radio->dev, WL1273_FM_DRIVER_NAME
+				 ": set frequency failed with %d\n", r);
+	} else {
+		r = wl1273_fm_set_tx_freq(radio,
+					  WL1273_INV_FREQ(freq->frequency));
+		if (r)
+			dev_warn(radio->dev, WL1273_FM_DRIVER_NAME
+				 ": set frequency failed with %d\n", r);
+	}
+
+	mutex_unlock(&core->lock);
+
+	dev_dbg(radio->dev, "wl1273_vidioc_s_frequency: DONE\n");
+	return r;
+}
+
+#define WL1273_DEFAULT_SEEK_LEVEL	7
+
+static int wl1273_fm_vidioc_s_hw_freq_seek(struct file *file, void *priv,
+					   struct v4l2_hw_freq_seek *seek)
+{
+	struct wl1273_device *radio = video_get_drvdata(video_devdata(file));
+	struct wl1273_core *core = radio->core;
+	int r;
+
+	dev_dbg(radio->dev, "%s\n", __func__);
+
+	if (seek->tuner != 0 || seek->type != V4L2_TUNER_RADIO)
+		return -EINVAL;
+
+	if (mutex_lock_interruptible(&core->lock))
+		return -EINTR;
+
+	r = wl1273_fm_set_mode(radio, WL1273_MODE_RX);
+	if (r)
+		goto out;
+
+	r = wl1273_fm_tx_set_spacing(radio, seek->spacing);
+	if (r)
+		dev_warn(radio->dev, "HW seek failed: %d\n", r);
+
+	r = wl1273_fm_set_seek(radio, seek->wrap_around, seek->seek_upward,
+			       WL1273_DEFAULT_SEEK_LEVEL);
+	if (r)
+		dev_warn(radio->dev, "HW seek failed: %d\n", r);
+
+out:
+	mutex_unlock(&core->lock);
+	return r;
+}
+
+static int wl1273_fm_vidioc_s_modulator(struct file *file, void *priv,
+					struct v4l2_modulator *modulator)
+{
+	struct wl1273_device *radio = video_get_drvdata(video_devdata(file));
+	struct wl1273_core *core = radio->core;
+	int r = 0;
+
+	dev_dbg(radio->dev, "%s\n", __func__);
+
+	if (modulator->index > 0)
+		return -EINVAL;
+
+	if (mutex_lock_interruptible(&core->lock))
+		return -EINTR;
+
+	r = wl1273_fm_set_mode(radio, WL1273_MODE_TX);
+	if (r)
+		goto out;
+
+	if (modulator->txsubchans & V4L2_TUNER_SUB_RDS)
+		r = wl1273_fm_set_rds(radio, WL1273_RDS_ON);
+	else
+		r = wl1273_fm_set_rds(radio, WL1273_RDS_OFF);
+
+	if (modulator->txsubchans & V4L2_TUNER_SUB_MONO)
+		r = wl1273_fm_write_cmd(core, WL1273_MONO_SET, WL1273_TX_MONO);
+	else
+		r = wl1273_fm_write_cmd(core, WL1273_MONO_SET,
+					WL1273_RX_STEREO);
+	if (r < 0)
+		dev_warn(radio->dev, WL1273_FM_DRIVER_NAME
+			 "MONO_SET fails: %d\n", r);
+out:
+	mutex_unlock(&core->lock);
+
+	return r;
+}
+
+static int wl1273_fm_vidioc_g_modulator(struct file *file, void *priv,
+					struct v4l2_modulator *modulator)
+{
+	struct wl1273_device *radio = video_get_drvdata(video_devdata(file));
+	struct wl1273_core *core = radio->core;
+	u16 val;
+	int r;
+
+	dev_dbg(radio->dev, "%s\n", __func__);
+
+	strlcpy(modulator->name, WL1273_FM_DRIVER_NAME,
+		sizeof(modulator->name));
+
+	modulator->rangelow = WL1273_FREQ(WL1273_BAND_JAPAN_LOW);
+	modulator->rangehigh = WL1273_FREQ(WL1273_BAND_OTHER_HIGH);
+
+	modulator->capability =  V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_RDS |
+		V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_RDS_BLOCK_IO;
+
+	if (core->mode != WL1273_MODE_TX)
+		return 0;
+
+	if (mutex_lock_interruptible(&core->lock))
+		return -EINTR;
+
+	r = wl1273_fm_read_reg(core, WL1273_MONO_SET, &val);
+	if (r)
+		goto out;
+
+	if (val == WL1273_TX_STEREO)
+		modulator->txsubchans = V4L2_TUNER_SUB_STEREO;
+	else
+		modulator->txsubchans = V4L2_TUNER_SUB_MONO;
+
+	if (radio->rds_on)
+		modulator->txsubchans |= V4L2_TUNER_SUB_RDS;
+out:
+	mutex_unlock(&core->lock);
+
+	return 0;
+}
+
+static int wl1273_fm_vidioc_log_status(struct file *file, void *priv)
+{
+	struct wl1273_device *radio = video_get_drvdata(video_devdata(file));
+	struct wl1273_core *core = radio->core;
+	struct device *dev = radio->dev;
+	u16 val;
+	int r;
+
+	dev_info(dev, DRIVER_DESC);
+
+	if (core->mode == WL1273_MODE_OFF) {
+		dev_info(dev, "Mode: Off\n");
+		return 0;
+	}
+
+	if (core->mode == WL1273_MODE_SUSPENDED) {
+		dev_info(dev, "Mode: Suspended\n");
+		return 0;
+	}
+
+	r = wl1273_fm_read_reg(core, WL1273_ASIC_ID_GET, &val);
+	if (r)
+		dev_err(dev, "%s: Get ASIC_ID fails.\n", __func__);
+	else
+		dev_info(dev, "ASIC_ID: 0x%04x\n", val);
+
+	r = wl1273_fm_read_reg(core, WL1273_ASIC_VER_GET, &val);
+	if (r)
+		dev_err(dev, "%s: Get ASIC_VER fails.\n", __func__);
+	else
+		dev_info(dev, "ASIC Version: 0x%04x\n", val);
+
+	r = wl1273_fm_read_reg(core, WL1273_FIRM_VER_GET, &val);
+	if (r)
+		dev_err(dev, "%s: Get FIRM_VER fails.\n", __func__);
+	else
+		dev_info(dev, "FW version: %d(0x%04x)\n", val, val);
+
+	r = wl1273_fm_read_reg(core, WL1273_BAND_SET, &val);
+	if (r)
+		dev_err(dev, "%s: Get BAND fails.\n", __func__);
+	else
+		dev_info(dev, "BAND: %d\n", val);
+
+	if (core->mode == WL1273_MODE_TX) {
+		r = wl1273_fm_read_reg(core, WL1273_PUPD_SET, &val);
+		if (r)
+			dev_err(dev, "%s: Get PUPD fails.\n", __func__);
+		else
+			dev_info(dev, "PUPD: 0x%04x\n", val);
+
+		r = wl1273_fm_read_reg(core, WL1273_CHANL_SET, &val);
+		if (r)
+			dev_err(dev, "%s: Get CHANL fails.\n", __func__);
+		else
+			dev_info(dev, "Tx frequency: %dkHz\n", val*10);
+	} else if (core->mode == WL1273_MODE_RX) {
+		int bf = radio->rangelow;
+
+		r = wl1273_fm_read_reg(core, WL1273_FREQ_SET, &val);
+		if (r)
+			dev_err(dev, "%s: Get FREQ fails.\n", __func__);
+		else
+			dev_info(dev, "RX Frequency: %dkHz\n", bf + val*50);
+
+		r = wl1273_fm_read_reg(core, WL1273_MOST_MODE_SET, &val);
+		if (r)
+			dev_err(dev, "%s: Get MOST_MODE fails.\n",
+				__func__);
+		else if (val == 0)
+			dev_info(dev, "MOST_MODE: Stereo according to blend\n");
+		else if (val == 1)
+			dev_info(dev, "MOST_MODE: Force mono output\n");
+		else
+			dev_info(dev, "MOST_MODE: Unexpected value: %d\n", val);
+
+		r = wl1273_fm_read_reg(core, WL1273_MOST_BLEND_SET, &val);
+		if (r)
+			dev_err(dev, "%s: Get MOST_BLEND fails.\n", __func__);
+		else if (val == 0)
+			dev_info(dev,
+				 "MOST_BLEND: Switched blend & hysteresis.\n");
+		else if (val == 1)
+			dev_info(dev, "MOST_BLEND: Soft blend.\n");
+		else
+			dev_info(dev, "MOST_BLEND: Unexpected val: %d\n", val);
+
+		r = wl1273_fm_read_reg(core, WL1273_STEREO_GET, &val);
+		if (r)
+			dev_err(dev, "%s: Get STEREO fails.\n", __func__);
+		else if (val == 0)
+			dev_info(dev, "STEREO: Not detected\n");
+		else if (val == 1)
+			dev_info(dev, "STEREO: Detected\n");
+		else
+			dev_info(dev, "STEREO: Unexpected value: %d\n", val);
+
+		r = wl1273_fm_read_reg(core, WL1273_RSSI_LVL_GET, &val);
+		if (r)
+			dev_err(dev, "%s: Get RSSI_LVL fails.\n", __func__);
+		else
+			dev_info(dev, "RX signal strength: %d\n", (s16) val);
+
+		r = wl1273_fm_read_reg(core, WL1273_POWER_SET, &val);
+		if (r)
+			dev_err(dev, "%s: Get POWER fails.\n", __func__);
+		else
+			dev_info(dev, "POWER: 0x%04x\n", val);
+
+		r = wl1273_fm_read_reg(core, WL1273_INT_MASK_SET, &val);
+		if (r)
+			dev_err(dev, "%s: Get INT_MASK fails.\n", __func__);
+		else
+			dev_info(dev, "INT_MASK: 0x%04x\n", val);
+
+		r = wl1273_fm_read_reg(core, WL1273_RDS_SYNC_GET, &val);
+		if (r)
+			dev_err(dev, "%s: Get RDS_SYNC fails.\n",
+				__func__);
+		else if (val == 0)
+			dev_info(dev, "RDS_SYNC: Not synchronized\n");
+
+		else if (val == 1)
+			dev_info(dev, "RDS_SYNC: Synchronized\n");
+		else
+			dev_info(dev, "RDS_SYNC: Unexpected value: %d\n", val);
+
+		r = wl1273_fm_read_reg(core, WL1273_I2S_MODE_CONFIG_SET, &val);
+		if (r)
+			dev_err(dev, "%s: Get I2S_MODE_CONFIG fails.\n",
+				__func__);
+		else
+			dev_info(dev, "I2S_MODE_CONFIG: 0x%04x\n", val);
+
+		r = wl1273_fm_read_reg(core, WL1273_VOLUME_SET, &val);
+		if (r)
+			dev_err(dev, "%s: Get VOLUME fails.\n", __func__);
+		else
+			dev_info(dev, "VOLUME: 0x%04x\n", val);
+	}
+
+	return 0;
+}
+
+static void wl1273_vdev_release(struct video_device *dev)
+{
+}
+
+static const struct v4l2_ctrl_ops wl1273_ctrl_ops = {
+	.s_ctrl = wl1273_fm_vidioc_s_ctrl,
+	.g_volatile_ctrl = wl1273_fm_g_volatile_ctrl,
+};
+
+static const struct v4l2_ioctl_ops wl1273_ioctl_ops = {
+	.vidioc_querycap	= wl1273_fm_vidioc_querycap,
+	.vidioc_g_input		= wl1273_fm_vidioc_g_input,
+	.vidioc_s_input		= wl1273_fm_vidioc_s_input,
+	.vidioc_g_audio		= wl1273_fm_vidioc_g_audio,
+	.vidioc_s_audio		= wl1273_fm_vidioc_s_audio,
+	.vidioc_g_tuner		= wl1273_fm_vidioc_g_tuner,
+	.vidioc_s_tuner		= wl1273_fm_vidioc_s_tuner,
+	.vidioc_g_frequency	= wl1273_fm_vidioc_g_frequency,
+	.vidioc_s_frequency	= wl1273_fm_vidioc_s_frequency,
+	.vidioc_s_hw_freq_seek	= wl1273_fm_vidioc_s_hw_freq_seek,
+	.vidioc_g_modulator	= wl1273_fm_vidioc_g_modulator,
+	.vidioc_s_modulator	= wl1273_fm_vidioc_s_modulator,
+	.vidioc_log_status      = wl1273_fm_vidioc_log_status,
+};
+
+static struct video_device wl1273_viddev_template = {
+	.fops			= &wl1273_fops,
+	.ioctl_ops		= &wl1273_ioctl_ops,
+	.name			= WL1273_FM_DRIVER_NAME,
+	.release		= wl1273_vdev_release,
+};
+
+static int wl1273_fm_radio_remove(struct platform_device *pdev)
+{
+	struct wl1273_device *radio = platform_get_drvdata(pdev);
+	struct wl1273_core *core = radio->core;
+
+	dev_info(&pdev->dev, "%s.\n", __func__);
+
+	free_irq(core->client->irq, radio);
+	core->pdata->free_resources();
+
+	v4l2_ctrl_handler_free(&radio->ctrl_handler);
+	video_unregister_device(&radio->videodev);
+	v4l2_device_unregister(&radio->v4l2dev);
+	kfree(radio->buffer);
+	kfree(radio->write_buf);
+	kfree(radio);
+
+	return 0;
+}
+
+static int __devinit wl1273_fm_radio_probe(struct platform_device *pdev)
+{
+	struct wl1273_core **core = pdev->dev.platform_data;
+	struct wl1273_device *radio;
+	struct v4l2_ctrl *ctrl;
+	int r = 0;
+
+	pr_debug("%s\n", __func__);
+
+	if (!core) {
+		dev_err(&pdev->dev, "No platform data.\n");
+		r = -EINVAL;
+		goto pdata_err;
+	}
+
+	radio = kzalloc(sizeof(*radio), GFP_KERNEL);
+	if (!radio) {
+		r = -ENOMEM;
+		goto pdata_err;
+	}
+
+	/* RDS buffer allocation */
+	radio->buf_size = rds_buf * RDS_BLOCK_SIZE;
+	radio->buffer = kmalloc(radio->buf_size, GFP_KERNEL);
+	if (!radio->buffer) {
+		pr_err("Cannot allocate memory for RDS buffer.\n");
+		r = -ENOMEM;
+		goto err_kmalloc;
+	}
+
+	radio->core = *core;
+	radio->irq_flags = WL1273_IRQ_MASK;
+	radio->dev = &radio->core->client->dev;
+	radio->rds_on = false;
+	radio->core->mode = WL1273_MODE_OFF;
+	radio->tx_power = 118;
+	radio->core->audio_mode = WL1273_AUDIO_ANALOG;
+	radio->band = WL1273_BAND_OTHER;
+	radio->core->i2s_mode = WL1273_I2S_DEF_MODE;
+	radio->core->channel_number = 2;
+	radio->core->volume = WL1273_DEFAULT_VOLUME;
+	radio->rx_frequency = WL1273_BAND_OTHER_LOW;
+	radio->tx_frequency = WL1273_BAND_OTHER_HIGH;
+	radio->rangelow = WL1273_BAND_OTHER_LOW;
+	radio->rangehigh = WL1273_BAND_OTHER_HIGH;
+	radio->stereo = true;
+	radio->bus_type = "I2C";
+
+	radio->core->write = wl1273_fm_write_cmd;
+	radio->core->set_audio = wl1273_fm_set_audio;
+	radio->core->set_volume = wl1273_fm_set_volume;
+
+	if (radio->core->pdata->request_resources) {
+		r = radio->core->pdata->request_resources(radio->core->client);
+		if (r) {
+			dev_err(radio->dev, WL1273_FM_DRIVER_NAME
+				": Cannot get platform data\n");
+			goto err_resources;
+		}
+
+		dev_dbg(radio->dev, "irq: %d\n", radio->core->client->irq);
+
+		r = request_threaded_irq(radio->core->client->irq, NULL,
+					 wl1273_fm_irq_thread_handler,
+					 IRQF_ONESHOT | IRQF_TRIGGER_FALLING,
+					 "wl1273-fm", radio);
+		if (r < 0) {
+			dev_err(radio->dev, WL1273_FM_DRIVER_NAME
+				": Unable to register IRQ handler: %d\n", r);
+			goto err_request_irq;
+		}
+	} else {
+		dev_err(radio->dev, WL1273_FM_DRIVER_NAME ": Core WL1273 IRQ"
+			" not configured");
+		r = -EINVAL;
+		goto err_resources;
+	}
+
+	init_completion(&radio->busy);
+	init_waitqueue_head(&radio->read_queue);
+
+	radio->write_buf = kmalloc(256, GFP_KERNEL);
+	if (!radio->write_buf) {
+		r = -ENOMEM;
+		goto write_buf_err;
+	}
+
+	radio->dev = &pdev->dev;
+	radio->v4l2dev.ctrl_handler = &radio->ctrl_handler;
+	radio->rds_users = 0;
+
+	r = v4l2_device_register(&pdev->dev, &radio->v4l2dev);
+	if (r) {
+		dev_err(&pdev->dev, "Cannot register v4l2_device.\n");
+		goto device_register_err;
+	}
+
+	/* V4L2 configuration */
+	memcpy(&radio->videodev, &wl1273_viddev_template,
+	       sizeof(wl1273_viddev_template));
+
+	radio->videodev.v4l2_dev = &radio->v4l2dev;
+
+	v4l2_ctrl_handler_init(&radio->ctrl_handler, 6);
+
+	/* add in ascending ID order */
+	v4l2_ctrl_new_std(&radio->ctrl_handler, &wl1273_ctrl_ops,
+			  V4L2_CID_AUDIO_VOLUME, 0, WL1273_MAX_VOLUME, 1,
+			  WL1273_DEFAULT_VOLUME);
+
+	v4l2_ctrl_new_std(&radio->ctrl_handler, &wl1273_ctrl_ops,
+			  V4L2_CID_AUDIO_MUTE, 0, 1, 1, 1);
+
+	v4l2_ctrl_new_std_menu(&radio->ctrl_handler, &wl1273_ctrl_ops,
+			       V4L2_CID_TUNE_PREEMPHASIS,
+			       V4L2_PREEMPHASIS_75_uS, 0x03,
+			       V4L2_PREEMPHASIS_50_uS);
+
+	v4l2_ctrl_new_std(&radio->ctrl_handler, &wl1273_ctrl_ops,
+			  V4L2_CID_TUNE_POWER_LEVEL, 91, 122, 1, 118);
+
+	ctrl = v4l2_ctrl_new_std(&radio->ctrl_handler, &wl1273_ctrl_ops,
+				 V4L2_CID_TUNE_ANTENNA_CAPACITOR,
+				 0, 255, 1, 255);
+	if (ctrl)
+		ctrl->is_volatile = 1;
+
+	if (radio->ctrl_handler.error) {
+		r = radio->ctrl_handler.error;
+		dev_err(&pdev->dev, "Ctrl handler error: %d\n", r);
+		goto handler_init_err;
+	}
+
+	video_set_drvdata(&radio->videodev, radio);
+	platform_set_drvdata(pdev, radio);
+
+	/* register video device */
+	r = video_register_device(&radio->videodev, VFL_TYPE_RADIO, radio_nr);
+	if (r) {
+		dev_err(&pdev->dev, WL1273_FM_DRIVER_NAME
+			": Could not register video device\n");
+		goto handler_init_err;
+	}
+
+	return 0;
+
+handler_init_err:
+	v4l2_ctrl_handler_free(&radio->ctrl_handler);
+	v4l2_device_unregister(&radio->v4l2dev);
+device_register_err:
+	kfree(radio->write_buf);
+write_buf_err:
+	free_irq(radio->core->client->irq, radio);
+err_request_irq:
+	radio->core->pdata->free_resources();
+err_resources:
+	kfree(radio->buffer);
+err_kmalloc:
+	kfree(radio);
+pdata_err:
+	return r;
+}
+
+MODULE_ALIAS("platform:wl1273_fm_radio");
+
+static struct platform_driver wl1273_fm_radio_driver = {
+	.probe		= wl1273_fm_radio_probe,
+	.remove		= __devexit_p(wl1273_fm_radio_remove),
+	.driver		= {
+		.name	= "wl1273_fm_radio",
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init wl1273_fm_module_init(void)
+{
+	pr_info("%s\n", __func__);
+	return platform_driver_register(&wl1273_fm_radio_driver);
+}
+module_init(wl1273_fm_module_init);
+
+static void __exit wl1273_fm_module_exit(void)
+{
+	flush_scheduled_work();
+	platform_driver_unregister(&wl1273_fm_radio_driver);
+	pr_info(DRIVER_DESC ", Exiting.\n");
+}
+module_exit(wl1273_fm_module_exit);
+
+MODULE_AUTHOR("Matti Aaltonen <matti.j.aaltonen@nokia.com>");
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/radio/si470x/radio-si470x-common.c linux-libre-2.6.38-gnu1/drivers/media/radio/si470x/radio-si470x-common.c
--- linux-libre-2.6.37-gnu1/drivers/media/radio/si470x/radio-si470x-common.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/radio/si470x/radio-si470x-common.c	2011-03-14 21:20:32.000000000 -0400
@@ -357,7 +357,8 @@ int si470x_start(struct si470x_device *r
 		goto done;
 
 	/* sysconfig 1 */
-	radio->registers[SYSCONFIG1] = SYSCONFIG1_DE;
+	radio->registers[SYSCONFIG1] =
+		(de << 11) & SYSCONFIG1_DE;		/* DE*/
 	retval = si470x_set_register(radio, SYSCONFIG1);
 	if (retval < 0)
 		goto done;
@@ -687,12 +688,8 @@ static int si470x_vidioc_g_tuner(struct
 	/* driver constants */
 	strcpy(tuner->name, "FM");
 	tuner->type = V4L2_TUNER_RADIO;
-#if defined(CONFIG_USB_SI470X) || defined(CONFIG_USB_SI470X_MODULE)
 	tuner->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO |
 			    V4L2_TUNER_CAP_RDS | V4L2_TUNER_CAP_RDS_BLOCK_IO;
-#else
-	tuner->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO;
-#endif
 
 	/* range limits */
 	switch ((radio->registers[SYSCONFIG2] & SYSCONFIG2_BAND) >> 6) {
@@ -718,12 +715,10 @@ static int si470x_vidioc_g_tuner(struct
 		tuner->rxsubchans = V4L2_TUNER_SUB_MONO;
 	else
 		tuner->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO;
-#if defined(CONFIG_USB_SI470X) || defined(CONFIG_USB_SI470X_MODULE)
 	/* If there is a reliable method of detecting an RDS channel,
 	   then this code should check for that before setting this
 	   RDS subchannel. */
 	tuner->rxsubchans |= V4L2_TUNER_SUB_RDS;
-#endif
 
 	/* mono/stereo selector */
 	if ((radio->registers[POWERCFG] & POWERCFG_MONO) == 0)
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/radio/si470x/radio-si470x.h linux-libre-2.6.38-gnu1/drivers/media/radio/si470x/radio-si470x.h
--- linux-libre-2.6.37-gnu1/drivers/media/radio/si470x/radio-si470x.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/radio/si470x/radio-si470x.h	2011-03-14 21:20:32.000000000 -0400
@@ -37,7 +37,6 @@
 #include <linux/mutex.h>
 #include <media/v4l2-common.h>
 #include <media/v4l2-ioctl.h>
-#include <media/rds.h>
 #include <asm/unaligned.h>
 
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/radio/si4713-i2c.c linux-libre-2.6.38-gnu1/drivers/media/radio/si4713-i2c.c
--- linux-libre-2.6.37-gnu1/drivers/media/radio/si4713-i2c.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/radio/si4713-i2c.c	2011-03-14 21:20:32.000000000 -0400
@@ -27,6 +27,8 @@
 #include <linux/interrupt.h>
 #include <linux/i2c.h>
 #include <linux/slab.h>
+#include <linux/gpio.h>
+#include <linux/regulator/consumer.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-ioctl.h>
 #include <media/v4l2-common.h>
@@ -43,6 +45,11 @@ MODULE_AUTHOR("Eduardo Valentin <eduardo
 MODULE_DESCRIPTION("I2C driver for Si4713 FM Radio Transmitter");
 MODULE_VERSION("0.0.1");
 
+static const char *si4713_supply_names[SI4713_NUM_SUPPLIES] = {
+	"vio",
+	"vdd",
+};
+
 #define DEFAULT_RDS_PI			0x00
 #define DEFAULT_RDS_PTY			0x00
 #define DEFAULT_RDS_PS_NAME		""
@@ -369,7 +376,17 @@ static int si4713_powerup(struct si4713_
 	if (sdev->power_state)
 		return 0;
 
-	sdev->platform_data->set_power(1);
+	err = regulator_bulk_enable(ARRAY_SIZE(sdev->supplies),
+				    sdev->supplies);
+	if (err) {
+		v4l2_err(&sdev->sd, "Failed to enable supplies: %d\n", err);
+		return err;
+	}
+	if (gpio_is_valid(sdev->gpio_reset)) {
+		udelay(50);
+		gpio_set_value(sdev->gpio_reset, 1);
+	}
+
 	err = si4713_send_command(sdev, SI4713_CMD_POWER_UP,
 					args, ARRAY_SIZE(args),
 					resp, ARRAY_SIZE(resp),
@@ -384,7 +401,13 @@ static int si4713_powerup(struct si4713_
 		err = si4713_write_property(sdev, SI4713_GPO_IEN,
 						SI4713_STC_INT | SI4713_CTS);
 	} else {
-		sdev->platform_data->set_power(0);
+		if (gpio_is_valid(sdev->gpio_reset))
+			gpio_set_value(sdev->gpio_reset, 0);
+		err = regulator_bulk_disable(ARRAY_SIZE(sdev->supplies),
+					     sdev->supplies);
+		if (err)
+			v4l2_err(&sdev->sd,
+				 "Failed to disable supplies: %d\n", err);
 	}
 
 	return err;
@@ -411,7 +434,13 @@ static int si4713_powerdown(struct si471
 		v4l2_dbg(1, debug, &sdev->sd, "Power down response: 0x%02x\n",
 				resp[0]);
 		v4l2_dbg(1, debug, &sdev->sd, "Device in reset mode\n");
-		sdev->platform_data->set_power(0);
+		if (gpio_is_valid(sdev->gpio_reset))
+			gpio_set_value(sdev->gpio_reset, 0);
+		err = regulator_bulk_disable(ARRAY_SIZE(sdev->supplies),
+					     sdev->supplies);
+		if (err)
+			v4l2_err(&sdev->sd,
+				 "Failed to disable supplies: %d\n", err);
 		sdev->power_state = POWER_OFF;
 	}
 
@@ -1967,7 +1996,8 @@ static int si4713_probe(struct i2c_clien
 					const struct i2c_device_id *id)
 {
 	struct si4713_device *sdev;
-	int rval;
+	struct si4713_platform_data *pdata = client->dev.platform_data;
+	int rval, i;
 
 	sdev = kzalloc(sizeof *sdev, GFP_KERNEL);
 	if (!sdev) {
@@ -1976,11 +2006,26 @@ static int si4713_probe(struct i2c_clien
 		goto exit;
 	}
 
-	sdev->platform_data = client->dev.platform_data;
-	if (!sdev->platform_data) {
-		v4l2_err(&sdev->sd, "No platform data registered.\n");
-		rval = -ENODEV;
-		goto free_sdev;
+	sdev->gpio_reset = -1;
+	if (pdata && gpio_is_valid(pdata->gpio_reset)) {
+		rval = gpio_request(pdata->gpio_reset, "si4713 reset");
+		if (rval) {
+			dev_err(&client->dev,
+				"Failed to request gpio: %d\n", rval);
+			goto free_sdev;
+		}
+		sdev->gpio_reset = pdata->gpio_reset;
+		gpio_direction_output(sdev->gpio_reset, 0);
+	}
+
+	for (i = 0; i < ARRAY_SIZE(sdev->supplies); i++)
+		sdev->supplies[i].supply = si4713_supply_names[i];
+
+	rval = regulator_bulk_get(&client->dev, ARRAY_SIZE(sdev->supplies),
+				  sdev->supplies);
+	if (rval) {
+		dev_err(&client->dev, "Cannot get regulators: %d\n", rval);
+		goto free_gpio;
 	}
 
 	v4l2_i2c_subdev_init(&sdev->sd, client, &si4713_subdev_ops);
@@ -1994,7 +2039,7 @@ static int si4713_probe(struct i2c_clien
 			client->name, sdev);
 		if (rval < 0) {
 			v4l2_err(&sdev->sd, "Could not request IRQ\n");
-			goto free_sdev;
+			goto put_reg;
 		}
 		v4l2_dbg(1, debug, &sdev->sd, "IRQ requested.\n");
 	} else {
@@ -2012,6 +2057,11 @@ static int si4713_probe(struct i2c_clien
 free_irq:
 	if (client->irq)
 		free_irq(client->irq, sdev);
+put_reg:
+	regulator_bulk_free(ARRAY_SIZE(sdev->supplies), sdev->supplies);
+free_gpio:
+	if (gpio_is_valid(sdev->gpio_reset))
+		gpio_free(sdev->gpio_reset);
 free_sdev:
 	kfree(sdev);
 exit:
@@ -2031,7 +2081,9 @@ static int si4713_remove(struct i2c_clie
 		free_irq(client->irq, sdev);
 
 	v4l2_device_unregister_subdev(sd);
-
+	regulator_bulk_free(ARRAY_SIZE(sdev->supplies), sdev->supplies);
+	if (gpio_is_valid(sdev->gpio_reset))
+		gpio_free(sdev->gpio_reset);
 	kfree(sdev);
 
 	return 0;
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/radio/si4713-i2c.h linux-libre-2.6.38-gnu1/drivers/media/radio/si4713-i2c.h
--- linux-libre-2.6.37-gnu1/drivers/media/radio/si4713-i2c.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/radio/si4713-i2c.h	2011-03-14 21:20:32.000000000 -0400
@@ -211,6 +211,8 @@ struct acomp_info {
 	u32 enabled;
 };
 
+#define SI4713_NUM_SUPPLIES		2
+
 /*
  * si4713_device - private data
  */
@@ -220,11 +222,12 @@ struct si4713_device {
 	/* private data structures */
 	struct mutex mutex;
 	struct completion work;
-	struct si4713_platform_data *platform_data;
 	struct rds_info rds_info;
 	struct limiter_info limiter_info;
 	struct pilot_info pilot_info;
 	struct acomp_info acomp_info;
+	struct regulator_bulk_data supplies[SI4713_NUM_SUPPLIES];
+	int gpio_reset;
 	u32 frequency;
 	u32 preemphasis;
 	u32 mute;
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/ene_ir.c linux-libre-2.6.38-gnu1/drivers/media/rc/ene_ir.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/ene_ir.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/ene_ir.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,1213 @@
+/*
+ * driver for ENE KB3926 B/C/D/E/F CIR (pnp id: ENE0XXX)
+ *
+ * Copyright (C) 2010 Maxim Levitsky <maximlevitsky@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
+ *
+ * Special thanks to:
+ *   Sami R. <maesesami@gmail.com> for lot of help in debugging and therefore
+ *    bringing to life support for transmission & learning mode.
+ *
+ *   Charlie Andrews <charliethepilot@googlemail.com> for lots of help in
+ *   bringing up the support of new firmware buffer that is popular
+ *   on latest notebooks
+ *
+ *   ENE for partial device documentation
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pnp.h>
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <media/rc-core.h>
+#include "ene_ir.h"
+
+static int sample_period;
+static bool learning_mode_force;
+static int debug;
+static bool txsim;
+
+static void ene_set_reg_addr(struct ene_device *dev, u16 reg)
+{
+	outb(reg >> 8, dev->hw_io + ENE_ADDR_HI);
+	outb(reg & 0xFF, dev->hw_io + ENE_ADDR_LO);
+}
+
+/* read a hardware register */
+static u8 ene_read_reg(struct ene_device *dev, u16 reg)
+{
+	u8 retval;
+	ene_set_reg_addr(dev, reg);
+	retval = inb(dev->hw_io + ENE_IO);
+	dbg_regs("reg %04x == %02x", reg, retval);
+	return retval;
+}
+
+/* write a hardware register */
+static void ene_write_reg(struct ene_device *dev, u16 reg, u8 value)
+{
+	dbg_regs("reg %04x <- %02x", reg, value);
+	ene_set_reg_addr(dev, reg);
+	outb(value, dev->hw_io + ENE_IO);
+}
+
+/* Set bits in hardware register */
+static void ene_set_reg_mask(struct ene_device *dev, u16 reg, u8 mask)
+{
+	dbg_regs("reg %04x |= %02x", reg, mask);
+	ene_set_reg_addr(dev, reg);
+	outb(inb(dev->hw_io + ENE_IO) | mask, dev->hw_io + ENE_IO);
+}
+
+/* Clear bits in hardware register */
+static void ene_clear_reg_mask(struct ene_device *dev, u16 reg, u8 mask)
+{
+	dbg_regs("reg %04x &= ~%02x ", reg, mask);
+	ene_set_reg_addr(dev, reg);
+	outb(inb(dev->hw_io + ENE_IO) & ~mask, dev->hw_io + ENE_IO);
+}
+
+/* A helper to set/clear a bit in register according to boolean variable */
+static void ene_set_clear_reg_mask(struct ene_device *dev, u16 reg, u8 mask,
+								bool set)
+{
+	if (set)
+		ene_set_reg_mask(dev, reg, mask);
+	else
+		ene_clear_reg_mask(dev, reg, mask);
+}
+
+/* detect hardware features */
+static int ene_hw_detect(struct ene_device *dev)
+{
+	u8 chip_major, chip_minor;
+	u8 hw_revision, old_ver;
+	u8 fw_reg2, fw_reg1;
+
+	ene_clear_reg_mask(dev, ENE_ECSTS, ENE_ECSTS_RSRVD);
+	chip_major = ene_read_reg(dev, ENE_ECVER_MAJOR);
+	chip_minor = ene_read_reg(dev, ENE_ECVER_MINOR);
+	ene_set_reg_mask(dev, ENE_ECSTS, ENE_ECSTS_RSRVD);
+
+	hw_revision = ene_read_reg(dev, ENE_ECHV);
+	old_ver = ene_read_reg(dev, ENE_HW_VER_OLD);
+
+	dev->pll_freq = (ene_read_reg(dev, ENE_PLLFRH) << 4) +
+		(ene_read_reg(dev, ENE_PLLFRL) >> 4);
+
+	if (sample_period != ENE_DEFAULT_SAMPLE_PERIOD)
+		dev->rx_period_adjust =
+			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");
+		return -ENODEV;
+	}
+
+	ene_notice("chip is 0x%02x%02x - kbver = 0x%02x, rev = 0x%02x",
+		chip_major, chip_minor, old_ver, hw_revision);
+
+	ene_notice("PLL freq = %d", dev->pll_freq);
+
+	if (chip_major == 0x33) {
+		ene_warn("chips 0x33xx aren't supported");
+		return -ENODEV;
+	}
+
+	if (chip_major == 0x39 && chip_minor == 0x26 && hw_revision == 0xC0) {
+		dev->hw_revision = ENE_HW_C;
+		ene_notice("KB3926C detected");
+	} else if (old_ver == 0x24 && hw_revision == 0xC0) {
+		dev->hw_revision = ENE_HW_B;
+		ene_notice("KB3926B detected");
+	} else {
+		dev->hw_revision = ENE_HW_D;
+		ene_notice("KB3926D or higher detected");
+	}
+
+	/* detect features hardware supports */
+	if (dev->hw_revision < ENE_HW_C)
+		return 0;
+
+	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);
+
+	dev->hw_use_gpio_0a = !!(fw_reg2 & ENE_FW2_GP0A);
+	dev->hw_learning_and_tx_capable = !!(fw_reg2 & ENE_FW2_LEARNING);
+	dev->hw_extra_buffer = !!(fw_reg1 & ENE_FW1_HAS_EXTRA_BUF);
+
+	if (dev->hw_learning_and_tx_capable)
+		dev->hw_fan_input = !!(fw_reg2 & ENE_FW2_FAN_INPUT);
+
+	ene_notice("Hardware features:");
+
+	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");
+
+		ene_notice("* Uses GPIO %s for IR raw input",
+			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");
+	}
+
+	if (!dev->hw_fan_input)
+		ene_notice("* Uses GPIO %s for IR demodulated input",
+			dev->hw_use_gpio_0a ? "0A" : "40");
+
+	if (dev->hw_extra_buffer)
+		ene_notice("* Uses new style input buffer");
+	return 0;
+}
+
+/* Read properities of hw sample buffer */
+static void ene_rx_setup_hw_buffer(struct ene_device *dev)
+{
+	u16 tmp;
+
+	ene_rx_read_hw_pointer(dev);
+	dev->r_pointer = dev->w_pointer;
+
+	if (!dev->hw_extra_buffer) {
+		dev->buffer_len = ENE_FW_PACKET_SIZE * 2;
+		return;
+	}
+
+	tmp = ene_read_reg(dev, ENE_FW_SAMPLE_BUFFER);
+	tmp |= ene_read_reg(dev, ENE_FW_SAMPLE_BUFFER+1) << 8;
+	dev->extra_buf1_address = tmp;
+
+	dev->extra_buf1_len = ene_read_reg(dev, ENE_FW_SAMPLE_BUFFER + 2);
+
+	tmp = ene_read_reg(dev, ENE_FW_SAMPLE_BUFFER + 3);
+	tmp |= ene_read_reg(dev, ENE_FW_SAMPLE_BUFFER + 4) << 8;
+	dev->extra_buf2_address = tmp;
+
+	dev->extra_buf2_len = ene_read_reg(dev, ENE_FW_SAMPLE_BUFFER + 5);
+
+	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);
+
+	ene_notice("Total buffer len = %d", dev->buffer_len);
+
+	if (dev->buffer_len > 64 || dev->buffer_len < 16)
+		goto error;
+
+	if (dev->extra_buf1_address > 0xFBFC ||
+					dev->extra_buf1_address < 0xEC00)
+		goto error;
+
+	if (dev->extra_buf2_address > 0xFBFC ||
+					dev->extra_buf2_address < 0xEC00)
+		goto error;
+
+	if (dev->r_pointer > dev->buffer_len)
+		goto error;
+
+	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");
+	dev->hw_extra_buffer = false;
+	ene_clear_reg_mask(dev, ENE_FW1, ENE_FW1_EXTRA_BUF_HND);
+}
+
+
+/* Restore the pointers to extra buffers - to make module reload work*/
+static void ene_rx_restore_hw_buffer(struct ene_device *dev)
+{
+	if (!dev->hw_extra_buffer)
+		return;
+
+	ene_write_reg(dev, ENE_FW_SAMPLE_BUFFER + 0,
+				dev->extra_buf1_address & 0xFF);
+	ene_write_reg(dev, ENE_FW_SAMPLE_BUFFER + 1,
+				dev->extra_buf1_address >> 8);
+	ene_write_reg(dev, ENE_FW_SAMPLE_BUFFER + 2, dev->extra_buf1_len);
+
+	ene_write_reg(dev, ENE_FW_SAMPLE_BUFFER + 3,
+				dev->extra_buf2_address & 0xFF);
+	ene_write_reg(dev, ENE_FW_SAMPLE_BUFFER + 4,
+				dev->extra_buf2_address >> 8);
+	ene_write_reg(dev, ENE_FW_SAMPLE_BUFFER + 5,
+				dev->extra_buf2_len);
+	ene_clear_reg_mask(dev, ENE_FW1, ENE_FW1_EXTRA_BUF_HND);
+}
+
+/* Read hardware write pointer */
+static void ene_rx_read_hw_pointer(struct ene_device *dev)
+{
+	if (dev->hw_extra_buffer)
+		dev->w_pointer = ene_read_reg(dev, ENE_FW_RX_POINTER);
+	else
+		dev->w_pointer = ene_read_reg(dev, ENE_FW2)
+			& ENE_FW2_BUF_WPTR ? 0 : ENE_FW_PACKET_SIZE;
+
+	dbg_verbose("RB: HW write pointer: %02x, driver read pointer: %02x",
+		dev->w_pointer, dev->r_pointer);
+}
+
+/* Gets address of next sample from HW ring buffer */
+static int ene_rx_get_sample_reg(struct ene_device *dev)
+{
+	int r_pointer;
+
+	if (dev->r_pointer == dev->w_pointer) {
+		dbg_verbose("RB: hit end, try update w_pointer");
+		ene_rx_read_hw_pointer(dev);
+	}
+
+	if (dev->r_pointer == dev->w_pointer) {
+		dbg_verbose("RB: end of data at %d", dev->r_pointer);
+		return 0;
+	}
+
+	dbg_verbose("RB: reading at offset %d", dev->r_pointer);
+	r_pointer = dev->r_pointer;
+
+	dev->r_pointer++;
+	if (dev->r_pointer == dev->buffer_len)
+		dev->r_pointer = 0;
+
+	dbg_verbose("RB: next read will be from offset %d", dev->r_pointer);
+
+	if (r_pointer < 8) {
+		dbg_verbose("RB: read at main buffer at %d", r_pointer);
+		return ENE_FW_SAMPLE_BUFFER + r_pointer;
+	}
+
+	r_pointer -= 8;
+
+	if (r_pointer < dev->extra_buf1_len) {
+		dbg_verbose("RB: read at 1st extra buffer at %d", r_pointer);
+		return dev->extra_buf1_address + r_pointer;
+	}
+
+	r_pointer -= dev->extra_buf1_len;
+
+	if (r_pointer < dev->extra_buf2_len) {
+		dbg_verbose("RB: read at 2nd extra buffer at %d", r_pointer);
+		return dev->extra_buf2_address + r_pointer;
+	}
+
+	dbg("attempt to read beyong ring bufer end");
+	return 0;
+}
+
+/* Sense current received carrier */
+void ene_rx_sense_carrier(struct ene_device *dev)
+{
+	DEFINE_IR_RAW_EVENT(ev);
+
+	int carrier, duty_cycle;
+	int period = ene_read_reg(dev, ENE_CIRCAR_PRD);
+	int hperiod = ene_read_reg(dev, ENE_CIRCAR_HPRD);
+
+	if (!(period & ENE_CIRCAR_PRD_VALID))
+		return;
+
+	period &= ~ENE_CIRCAR_PRD_VALID;
+
+	if (!period)
+		return;
+
+	dbg("RX: hardware carrier period = %02x", period);
+	dbg("RX: hardware carrier pulse period = %02x", hperiod);
+
+	carrier = 2000000 / period;
+	duty_cycle = (hperiod * 100) / period;
+	dbg("RX: sensed carrier = %d Hz, duty cycle %d%%",
+						carrier, duty_cycle);
+	if (dev->carrier_detect_enabled) {
+		ev.carrier_report = true;
+		ev.carrier = carrier;
+		ev.duty_cycle = duty_cycle;
+		ir_raw_event_store(dev->rdev, &ev);
+	}
+}
+
+/* this enables/disables the CIR RX engine */
+static void ene_rx_enable_cir_engine(struct ene_device *dev, bool enable)
+{
+	ene_set_clear_reg_mask(dev, ENE_CIRCFG,
+			ENE_CIRCFG_RX_EN | ENE_CIRCFG_RX_IRQ, enable);
+}
+
+/* this selects input for CIR engine. Ether GPIO 0A or GPIO40*/
+static void ene_rx_select_input(struct ene_device *dev, bool gpio_0a)
+{
+	ene_set_clear_reg_mask(dev, ENE_CIRCFG2, ENE_CIRCFG2_GPIO0A, gpio_0a);
+}
+
+/*
+ * this enables alternative input via fan tachometer sensor and bypasses
+ * the hw CIR engine
+ */
+static void ene_rx_enable_fan_input(struct ene_device *dev, bool enable)
+{
+	if (!dev->hw_fan_input)
+		return;
+
+	if (!enable)
+		ene_write_reg(dev, ENE_FAN_AS_IN1, 0);
+	else {
+		ene_write_reg(dev, ENE_FAN_AS_IN1, ENE_FAN_AS_IN1_EN);
+		ene_write_reg(dev, ENE_FAN_AS_IN2, ENE_FAN_AS_IN2_EN);
+	}
+}
+
+/* setup the receiver for RX*/
+static void ene_rx_setup(struct ene_device *dev)
+{
+	bool learning_mode = dev->learning_mode_enabled ||
+					dev->carrier_detect_enabled;
+	int sample_period_adjust = 0;
+
+	dbg("RX: setup receiver, learning mode = %d", learning_mode);
+
+
+	/* This selects RLC input and clears CFG2 settings */
+	ene_write_reg(dev, ENE_CIRCFG2, 0x00);
+
+	/* set sample period*/
+	if (sample_period == ENE_DEFAULT_SAMPLE_PERIOD)
+		sample_period_adjust =
+			dev->pll_freq == ENE_DEFAULT_PLL_FREQ ? 1 : 2;
+
+	ene_write_reg(dev, ENE_CIRRLC_CFG,
+			(sample_period + sample_period_adjust) |
+						ENE_CIRRLC_CFG_OVERFLOW);
+	/* revB doesn't support inputs */
+	if (dev->hw_revision < ENE_HW_C)
+		goto select_timeout;
+
+	if (learning_mode) {
+
+		WARN_ON(!dev->hw_learning_and_tx_capable);
+
+		/* Enable the opposite of the normal input
+		That means that if GPIO40 is normally used, use GPIO0A
+		and vice versa.
+		This input will carry non demodulated
+		signal, and we will tell the hw to demodulate it itself */
+		ene_rx_select_input(dev, !dev->hw_use_gpio_0a);
+		dev->rx_fan_input_inuse = false;
+
+		/* Enable carrier demodulation */
+		ene_set_reg_mask(dev, ENE_CIRCFG, ENE_CIRCFG_CARR_DEMOD);
+
+		/* Enable carrier detection */
+		ene_write_reg(dev, ENE_CIRCAR_PULS, 0x63);
+		ene_set_clear_reg_mask(dev, ENE_CIRCFG2, ENE_CIRCFG2_CARR_DETECT,
+			dev->carrier_detect_enabled || debug);
+	} else {
+		if (dev->hw_fan_input)
+			dev->rx_fan_input_inuse = true;
+		else
+			ene_rx_select_input(dev, dev->hw_use_gpio_0a);
+
+		/* Disable carrier detection & demodulation */
+		ene_clear_reg_mask(dev, ENE_CIRCFG, ENE_CIRCFG_CARR_DEMOD);
+		ene_clear_reg_mask(dev, ENE_CIRCFG2, ENE_CIRCFG2_CARR_DETECT);
+	}
+
+select_timeout:
+	if (dev->rx_fan_input_inuse) {
+		dev->rdev->rx_resolution = US_TO_NS(ENE_FW_SAMPLE_PERIOD_FAN);
+
+		/* Fan input doesn't support timeouts, it just ends the
+			input with a maximum sample */
+		dev->rdev->min_timeout = dev->rdev->max_timeout =
+			US_TO_NS(ENE_FW_SMPL_BUF_FAN_MSK *
+				ENE_FW_SAMPLE_PERIOD_FAN);
+	} else {
+		dev->rdev->rx_resolution = US_TO_NS(sample_period);
+
+		/* Theoreticly timeout is unlimited, but we cap it
+		 * because it was seen that on one device, it
+		 * would stop sending spaces after around 250 msec.
+		 * Besides, this is close to 2^32 anyway and timeout is u32.
+		 */
+		dev->rdev->min_timeout = US_TO_NS(127 * sample_period);
+		dev->rdev->max_timeout = US_TO_NS(200000);
+	}
+
+	if (dev->hw_learning_and_tx_capable)
+		dev->rdev->tx_resolution = US_TO_NS(sample_period);
+
+	if (dev->rdev->timeout > dev->rdev->max_timeout)
+		dev->rdev->timeout = dev->rdev->max_timeout;
+	if (dev->rdev->timeout < dev->rdev->min_timeout)
+		dev->rdev->timeout = dev->rdev->min_timeout;
+}
+
+/* Enable the device for receive */
+static void ene_rx_enable(struct ene_device *dev)
+{
+	u8 reg_value;
+
+	/* Enable system interrupt */
+	if (dev->hw_revision < ENE_HW_C) {
+		ene_write_reg(dev, ENEB_IRQ, dev->irq << 1);
+		ene_write_reg(dev, ENEB_IRQ_UNK1, 0x01);
+	} else {
+		reg_value = ene_read_reg(dev, ENE_IRQ) & 0xF0;
+		reg_value |= ENE_IRQ_UNK_EN;
+		reg_value &= ~ENE_IRQ_STATUS;
+		reg_value |= (dev->irq & ENE_IRQ_MASK);
+		ene_write_reg(dev, ENE_IRQ, reg_value);
+	}
+
+	/* Enable inputs */
+	ene_rx_enable_fan_input(dev, dev->rx_fan_input_inuse);
+	ene_rx_enable_cir_engine(dev, !dev->rx_fan_input_inuse);
+
+	/* ack any pending irqs - just in case */
+	ene_irq_status(dev);
+
+	/* enable firmware bits */
+	ene_set_reg_mask(dev, ENE_FW1, ENE_FW1_ENABLE | ENE_FW1_IRQ);
+
+	/* enter idle mode */
+	ir_raw_event_set_idle(dev->rdev, true);
+	dev->rx_enabled = true;
+}
+
+/* Disable the device receiver */
+static void ene_rx_disable(struct ene_device *dev)
+{
+	/* disable inputs */
+	ene_rx_enable_cir_engine(dev, false);
+	ene_rx_enable_fan_input(dev, false);
+
+	/* disable hardware IRQ and firmware flag */
+	ene_clear_reg_mask(dev, ENE_FW1, ENE_FW1_ENABLE | ENE_FW1_IRQ);
+
+	ir_raw_event_set_idle(dev->rdev, true);
+	dev->rx_enabled = false;
+}
+
+/* This resets the receiver. Usefull to stop stream of spaces at end of
+ * transmission
+ */
+static void ene_rx_reset(struct ene_device *dev)
+{
+	ene_clear_reg_mask(dev, ENE_CIRCFG, ENE_CIRCFG_RX_EN);
+	ene_set_reg_mask(dev, ENE_CIRCFG, ENE_CIRCFG_RX_EN);
+}
+
+/* Set up the TX carrier frequency and duty cycle */
+static void ene_tx_set_carrier(struct ene_device *dev)
+{
+	u8 tx_puls_width;
+	unsigned long flags;
+
+	spin_lock_irqsave(&dev->hw_lock, flags);
+
+	ene_set_clear_reg_mask(dev, ENE_CIRCFG,
+		ENE_CIRCFG_TX_CARR, dev->tx_period > 0);
+
+	if (!dev->tx_period)
+		goto unlock;
+
+	BUG_ON(dev->tx_duty_cycle >= 100 || dev->tx_duty_cycle <= 0);
+
+	tx_puls_width = dev->tx_period / (100 / dev->tx_duty_cycle);
+
+	if (!tx_puls_width)
+		tx_puls_width = 1;
+
+	dbg("TX: pulse distance = %d * 500 ns", dev->tx_period);
+	dbg("TX: pulse width = %d * 500 ns", tx_puls_width);
+
+	ene_write_reg(dev, ENE_CIRMOD_PRD, dev->tx_period | ENE_CIRMOD_PRD_POL);
+	ene_write_reg(dev, ENE_CIRMOD_HPRD, tx_puls_width);
+unlock:
+	spin_unlock_irqrestore(&dev->hw_lock, flags);
+}
+
+/* Enable/disable transmitters */
+static void ene_tx_set_transmitters(struct ene_device *dev)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&dev->hw_lock, flags);
+	ene_set_clear_reg_mask(dev, ENE_GPIOFS8, ENE_GPIOFS8_GPIO41,
+					!!(dev->transmitter_mask & 0x01));
+	ene_set_clear_reg_mask(dev, ENE_GPIOFS1, ENE_GPIOFS1_GPIO0D,
+					!!(dev->transmitter_mask & 0x02));
+	spin_unlock_irqrestore(&dev->hw_lock, flags);
+}
+
+/* prepare transmission */
+static void ene_tx_enable(struct ene_device *dev)
+{
+	u8 conf1 = ene_read_reg(dev, ENE_CIRCFG);
+	u8 fwreg2 = ene_read_reg(dev, ENE_FW2);
+
+	dev->saved_conf1 = conf1;
+
+	/* Show information about currently connected transmitter jacks */
+	if (fwreg2 & ENE_FW2_EMMITER1_CONN)
+		dbg("TX: Transmitter #1 is connected");
+
+	if (fwreg2 & ENE_FW2_EMMITER2_CONN)
+		dbg("TX: Transmitter #2 is connected");
+
+	if (!(fwreg2 & (ENE_FW2_EMMITER1_CONN | ENE_FW2_EMMITER2_CONN)))
+		ene_warn("TX: transmitter cable isn't connected!");
+
+	/* disable receive on revc */
+	if (dev->hw_revision == ENE_HW_C)
+		conf1 &= ~ENE_CIRCFG_RX_EN;
+
+	/* Enable TX engine */
+	conf1 |= ENE_CIRCFG_TX_EN | ENE_CIRCFG_TX_IRQ;
+	ene_write_reg(dev, ENE_CIRCFG, conf1);
+}
+
+/* end transmission */
+static void ene_tx_disable(struct ene_device *dev)
+{
+	ene_write_reg(dev, ENE_CIRCFG, dev->saved_conf1);
+	dev->tx_buffer = NULL;
+}
+
+
+/* TX one sample - must be called with dev->hw_lock*/
+static void ene_tx_sample(struct ene_device *dev)
+{
+	u8 raw_tx;
+	u32 sample;
+	bool pulse = dev->tx_sample_pulse;
+
+	if (!dev->tx_buffer) {
+		ene_warn("TX: BUG: attempt to transmit NULL buffer");
+		return;
+	}
+
+	/* Grab next TX sample */
+	if (!dev->tx_sample) {
+
+		if (dev->tx_pos == dev->tx_len) {
+			if (!dev->tx_done) {
+				dbg("TX: no more data to send");
+				dev->tx_done = true;
+				goto exit;
+			} else {
+				dbg("TX: last sample sent by hardware");
+				ene_tx_disable(dev);
+				complete(&dev->tx_complete);
+				return;
+			}
+		}
+
+		sample = dev->tx_buffer[dev->tx_pos++];
+		dev->tx_sample_pulse = !dev->tx_sample_pulse;
+
+		dev->tx_sample = DIV_ROUND_CLOSEST(sample, sample_period);
+
+		if (!dev->tx_sample)
+			dev->tx_sample = 1;
+	}
+
+	raw_tx = min(dev->tx_sample , (unsigned int)ENE_CIRRLC_OUT_MASK);
+	dev->tx_sample -= raw_tx;
+
+	dbg("TX: sample %8d (%s)", raw_tx * sample_period,
+						pulse ? "pulse" : "space");
+	if (pulse)
+		raw_tx |= ENE_CIRRLC_OUT_PULSE;
+
+	ene_write_reg(dev,
+		dev->tx_reg ? ENE_CIRRLC_OUT1 : ENE_CIRRLC_OUT0, raw_tx);
+
+	dev->tx_reg = !dev->tx_reg;
+exit:
+	/* simulate TX done interrupt */
+	if (txsim)
+		mod_timer(&dev->tx_sim_timer, jiffies + HZ / 500);
+}
+
+/* timer to simulate tx done interrupt */
+static void ene_tx_irqsim(unsigned long data)
+{
+	struct ene_device *dev = (struct ene_device *)data;
+	unsigned long flags;
+
+	spin_lock_irqsave(&dev->hw_lock, flags);
+	ene_tx_sample(dev);
+	spin_unlock_irqrestore(&dev->hw_lock, flags);
+}
+
+
+/* read irq status and ack it */
+static int ene_irq_status(struct ene_device *dev)
+{
+	u8 irq_status;
+	u8 fw_flags1, fw_flags2;
+	int retval = 0;
+
+	fw_flags2 = ene_read_reg(dev, ENE_FW2);
+
+	if (dev->hw_revision < ENE_HW_C) {
+		irq_status = ene_read_reg(dev, ENEB_IRQ_STATUS);
+
+		if (!(irq_status & ENEB_IRQ_STATUS_IR))
+			return 0;
+
+		ene_clear_reg_mask(dev, ENEB_IRQ_STATUS, ENEB_IRQ_STATUS_IR);
+		return ENE_IRQ_RX;
+	}
+
+	irq_status = ene_read_reg(dev, ENE_IRQ);
+	if (!(irq_status & ENE_IRQ_STATUS))
+		return 0;
+
+	/* original driver does that twice - a workaround ? */
+	ene_write_reg(dev, ENE_IRQ, irq_status & ~ENE_IRQ_STATUS);
+	ene_write_reg(dev, ENE_IRQ, irq_status & ~ENE_IRQ_STATUS);
+
+	/* check RX interrupt */
+	if (fw_flags2 & ENE_FW2_RXIRQ) {
+		retval |= ENE_IRQ_RX;
+		ene_write_reg(dev, ENE_FW2, fw_flags2 & ~ENE_FW2_RXIRQ);
+	}
+
+	/* check TX interrupt */
+	fw_flags1 = ene_read_reg(dev, ENE_FW1);
+	if (fw_flags1 & ENE_FW1_TXIRQ) {
+		ene_write_reg(dev, ENE_FW1, fw_flags1 & ~ENE_FW1_TXIRQ);
+		retval |= ENE_IRQ_TX;
+	}
+
+	return retval;
+}
+
+/* interrupt handler */
+static irqreturn_t ene_isr(int irq, void *data)
+{
+	u16 hw_value, reg;
+	int hw_sample, irq_status;
+	bool pulse;
+	unsigned long flags;
+	irqreturn_t retval = IRQ_NONE;
+	struct ene_device *dev = (struct ene_device *)data;
+	DEFINE_IR_RAW_EVENT(ev);
+
+	spin_lock_irqsave(&dev->hw_lock, flags);
+
+	dbg_verbose("ISR called");
+	ene_rx_read_hw_pointer(dev);
+	irq_status = ene_irq_status(dev);
+
+	if (!irq_status)
+		goto unlock;
+
+	retval = IRQ_HANDLED;
+
+	if (irq_status & ENE_IRQ_TX) {
+		dbg_verbose("TX interrupt");
+		if (!dev->hw_learning_and_tx_capable) {
+			dbg("TX interrupt on unsupported device!");
+			goto unlock;
+		}
+		ene_tx_sample(dev);
+	}
+
+	if (!(irq_status & ENE_IRQ_RX))
+		goto unlock;
+
+	dbg_verbose("RX interrupt");
+
+	if (dev->hw_learning_and_tx_capable)
+		ene_rx_sense_carrier(dev);
+
+	/* On hardware that don't support extra buffer we need to trust
+		the interrupt and not track the read pointer */
+	if (!dev->hw_extra_buffer)
+		dev->r_pointer = dev->w_pointer == 0 ? ENE_FW_PACKET_SIZE : 0;
+
+	while (1) {
+
+		reg = ene_rx_get_sample_reg(dev);
+
+		dbg_verbose("next sample to read at: %04x", reg);
+		if (!reg)
+			break;
+
+		hw_value = ene_read_reg(dev, reg);
+
+		if (dev->rx_fan_input_inuse) {
+
+			int offset = ENE_FW_SMPL_BUF_FAN - ENE_FW_SAMPLE_BUFFER;
+
+			/* read high part of the sample */
+			hw_value |= ene_read_reg(dev, reg + offset) << 8;
+			pulse = hw_value & ENE_FW_SMPL_BUF_FAN_PLS;
+
+			/* clear space bit, and other unused bits */
+			hw_value &= ENE_FW_SMPL_BUF_FAN_MSK;
+			hw_sample = hw_value * ENE_FW_SAMPLE_PERIOD_FAN;
+
+		} else {
+			pulse = !(hw_value & ENE_FW_SAMPLE_SPACE);
+			hw_value &= ~ENE_FW_SAMPLE_SPACE;
+			hw_sample = hw_value * sample_period;
+
+			if (dev->rx_period_adjust) {
+				hw_sample *= 100;
+				hw_sample /= (100 + dev->rx_period_adjust);
+			}
+		}
+
+		if (!dev->hw_extra_buffer && !hw_sample) {
+			dev->r_pointer = dev->w_pointer;
+			continue;
+		}
+
+		dbg("RX: %d (%s)", hw_sample, pulse ? "pulse" : "space");
+
+		ev.duration = US_TO_NS(hw_sample);
+		ev.pulse = pulse;
+		ir_raw_event_store_with_filter(dev->rdev, &ev);
+	}
+
+	ir_raw_event_handle(dev->rdev);
+unlock:
+	spin_unlock_irqrestore(&dev->hw_lock, flags);
+	return retval;
+}
+
+/* Initialize default settings */
+static void ene_setup_default_settings(struct ene_device *dev)
+{
+	dev->tx_period = 32;
+	dev->tx_duty_cycle = 50; /*%*/
+	dev->transmitter_mask = 0x03;
+	dev->learning_mode_enabled = learning_mode_force;
+
+	/* Set reasonable default timeout */
+	dev->rdev->timeout = US_TO_NS(150000);
+}
+
+/* Upload all hardware settings at once. Used at load and resume time */
+static void ene_setup_hw_settings(struct ene_device *dev)
+{
+	if (dev->hw_learning_and_tx_capable) {
+		ene_tx_set_carrier(dev);
+		ene_tx_set_transmitters(dev);
+	}
+
+	ene_rx_setup(dev);
+}
+
+/* outside interface: called on first open*/
+static int ene_open(struct rc_dev *rdev)
+{
+	struct ene_device *dev = rdev->priv;
+	unsigned long flags;
+
+	spin_lock_irqsave(&dev->hw_lock, flags);
+	ene_rx_enable(dev);
+	spin_unlock_irqrestore(&dev->hw_lock, flags);
+	return 0;
+}
+
+/* outside interface: called on device close*/
+static void ene_close(struct rc_dev *rdev)
+{
+	struct ene_device *dev = rdev->priv;
+	unsigned long flags;
+	spin_lock_irqsave(&dev->hw_lock, flags);
+
+	ene_rx_disable(dev);
+	spin_unlock_irqrestore(&dev->hw_lock, flags);
+}
+
+/* outside interface: set transmitter mask */
+static int ene_set_tx_mask(struct rc_dev *rdev, u32 tx_mask)
+{
+	struct ene_device *dev = rdev->priv;
+	dbg("TX: attempt to set transmitter mask %02x", tx_mask);
+
+	/* invalid txmask */
+	if (!tx_mask || tx_mask & ~0x03) {
+		dbg("TX: invalid mask");
+		/* return count of transmitters */
+		return 2;
+	}
+
+	dev->transmitter_mask = tx_mask;
+	ene_tx_set_transmitters(dev);
+	return 0;
+}
+
+/* outside interface : set tx carrier */
+static int ene_set_tx_carrier(struct rc_dev *rdev, u32 carrier)
+{
+	struct ene_device *dev = rdev->priv;
+	u32 period = 2000000 / carrier;
+
+	dbg("TX: attempt to set tx carrier to %d kHz", carrier);
+
+	if (period && (period > ENE_CIRMOD_PRD_MAX ||
+			period < ENE_CIRMOD_PRD_MIN)) {
+
+		dbg("TX: out of range %d-%d kHz carrier",
+			2000 / ENE_CIRMOD_PRD_MIN, 2000 / ENE_CIRMOD_PRD_MAX);
+		return -1;
+	}
+
+	dev->tx_period = period;
+	ene_tx_set_carrier(dev);
+	return 0;
+}
+
+/*outside interface : set tx duty cycle */
+static int ene_set_tx_duty_cycle(struct rc_dev *rdev, u32 duty_cycle)
+{
+	struct ene_device *dev = rdev->priv;
+	dbg("TX: setting duty cycle to %d%%", duty_cycle);
+	dev->tx_duty_cycle = duty_cycle;
+	ene_tx_set_carrier(dev);
+	return 0;
+}
+
+/* outside interface: enable learning mode */
+static int ene_set_learning_mode(struct rc_dev *rdev, int enable)
+{
+	struct ene_device *dev = rdev->priv;
+	unsigned long flags;
+	if (enable == dev->learning_mode_enabled)
+		return 0;
+
+	spin_lock_irqsave(&dev->hw_lock, flags);
+	dev->learning_mode_enabled = enable;
+	ene_rx_disable(dev);
+	ene_rx_setup(dev);
+	ene_rx_enable(dev);
+	spin_unlock_irqrestore(&dev->hw_lock, flags);
+	return 0;
+}
+
+static int ene_set_carrier_report(struct rc_dev *rdev, int enable)
+{
+	struct ene_device *dev = rdev->priv;
+	unsigned long flags;
+
+	if (enable == dev->carrier_detect_enabled)
+		return 0;
+
+	spin_lock_irqsave(&dev->hw_lock, flags);
+	dev->carrier_detect_enabled = enable;
+	ene_rx_disable(dev);
+	ene_rx_setup(dev);
+	ene_rx_enable(dev);
+	spin_unlock_irqrestore(&dev->hw_lock, flags);
+	return 0;
+}
+
+/* outside interface: enable or disable idle mode */
+static void ene_set_idle(struct rc_dev *rdev, bool idle)
+{
+	struct ene_device *dev = rdev->priv;
+
+	if (idle) {
+		ene_rx_reset(dev);
+		dbg("RX: end of data");
+	}
+}
+
+/* outside interface: transmit */
+static int ene_transmit(struct rc_dev *rdev, int *buf, u32 n)
+{
+	struct ene_device *dev = rdev->priv;
+	unsigned long flags;
+
+	dev->tx_buffer = buf;
+	dev->tx_len = n / sizeof(int);
+	dev->tx_pos = 0;
+	dev->tx_reg = 0;
+	dev->tx_done = 0;
+	dev->tx_sample = 0;
+	dev->tx_sample_pulse = 0;
+
+	dbg("TX: %d samples", dev->tx_len);
+
+	spin_lock_irqsave(&dev->hw_lock, flags);
+
+	ene_tx_enable(dev);
+
+	/* Transmit first two samples */
+	ene_tx_sample(dev);
+	ene_tx_sample(dev);
+
+	spin_unlock_irqrestore(&dev->hw_lock, flags);
+
+	if (wait_for_completion_timeout(&dev->tx_complete, 2 * HZ) == 0) {
+		dbg("TX: timeout");
+		spin_lock_irqsave(&dev->hw_lock, flags);
+		ene_tx_disable(dev);
+		spin_unlock_irqrestore(&dev->hw_lock, flags);
+	} else
+		dbg("TX: done");
+	return n;
+}
+
+/* probe entry */
+static int ene_probe(struct pnp_dev *pnp_dev, const struct pnp_device_id *id)
+{
+	int error = -ENOMEM;
+	struct rc_dev *rdev;
+	struct ene_device *dev;
+
+	/* allocate memory */
+	dev = kzalloc(sizeof(struct ene_device), GFP_KERNEL);
+	rdev = rc_allocate_device();
+	if (!dev || !rdev)
+		goto error1;
+
+	/* validate resources */
+	error = -ENODEV;
+
+	/* init these to -1, as 0 is valid for both */
+	dev->hw_io = -1;
+	dev->irq = -1;
+
+	if (!pnp_port_valid(pnp_dev, 0) ||
+	    pnp_port_len(pnp_dev, 0) < ENE_IO_SIZE)
+		goto error;
+
+	if (!pnp_irq_valid(pnp_dev, 0))
+		goto error;
+
+	spin_lock_init(&dev->hw_lock);
+
+	/* claim the resources */
+	error = -EBUSY;
+	dev->hw_io = pnp_port_start(pnp_dev, 0);
+	if (!request_region(dev->hw_io, ENE_IO_SIZE, ENE_DRIVER_NAME)) {
+		dev->hw_io = -1;
+		dev->irq = -1;
+		goto error;
+	}
+
+	dev->irq = pnp_irq(pnp_dev, 0);
+	if (request_irq(dev->irq, ene_isr,
+			IRQF_SHARED, ENE_DRIVER_NAME, (void *)dev)) {
+		dev->irq = -1;
+		goto error;
+	}
+
+	pnp_set_drvdata(pnp_dev, dev);
+	dev->pnp_dev = pnp_dev;
+
+	/* don't allow too short/long sample periods */
+	if (sample_period < 5 || sample_period > 0x7F)
+		sample_period = ENE_DEFAULT_SAMPLE_PERIOD;
+
+	/* detect hardware version and features */
+	error = ene_hw_detect(dev);
+	if (error)
+		goto error;
+
+	if (!dev->hw_learning_and_tx_capable && txsim) {
+		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");
+	}
+
+	if (!dev->hw_learning_and_tx_capable)
+		learning_mode_force = false;
+
+	rdev->driver_type = RC_DRIVER_IR_RAW;
+	rdev->allowed_protos = RC_TYPE_ALL;
+	rdev->priv = dev;
+	rdev->open = ene_open;
+	rdev->close = ene_close;
+	rdev->s_idle = ene_set_idle;
+	rdev->driver_name = ENE_DRIVER_NAME;
+	rdev->map_name = RC_MAP_RC6_MCE;
+	rdev->input_name = "ENE eHome Infrared Remote Receiver";
+
+	if (dev->hw_learning_and_tx_capable) {
+		rdev->s_learning_mode = ene_set_learning_mode;
+		init_completion(&dev->tx_complete);
+		rdev->tx_ir = ene_transmit;
+		rdev->s_tx_mask = ene_set_tx_mask;
+		rdev->s_tx_carrier = ene_set_tx_carrier;
+		rdev->s_tx_duty_cycle = ene_set_tx_duty_cycle;
+		rdev->s_carrier_report = ene_set_carrier_report;
+		rdev->input_name = "ENE eHome Infrared Remote Transceiver";
+	}
+
+	dev->rdev = rdev;
+
+	ene_rx_setup_hw_buffer(dev);
+	ene_setup_default_settings(dev);
+	ene_setup_hw_settings(dev);
+
+	device_set_wakeup_capable(&pnp_dev->dev, true);
+	device_set_wakeup_enable(&pnp_dev->dev, true);
+
+	error = rc_register_device(rdev);
+	if (error < 0)
+		goto error;
+
+	ene_notice("driver has been succesfully loaded");
+	return 0;
+error:
+	if (dev && dev->irq >= 0)
+		free_irq(dev->irq, dev);
+	if (dev && dev->hw_io >= 0)
+		release_region(dev->hw_io, ENE_IO_SIZE);
+error1:
+	rc_free_device(rdev);
+	kfree(dev);
+	return error;
+}
+
+/* main unload function */
+static void ene_remove(struct pnp_dev *pnp_dev)
+{
+	struct ene_device *dev = pnp_get_drvdata(pnp_dev);
+	unsigned long flags;
+
+	spin_lock_irqsave(&dev->hw_lock, flags);
+	ene_rx_disable(dev);
+	ene_rx_restore_hw_buffer(dev);
+	spin_unlock_irqrestore(&dev->hw_lock, flags);
+
+	free_irq(dev->irq, dev);
+	release_region(dev->hw_io, ENE_IO_SIZE);
+	rc_unregister_device(dev->rdev);
+	kfree(dev);
+}
+
+/* enable wake on IR (wakes on specific button on original remote) */
+static void ene_enable_wake(struct ene_device *dev, int enable)
+{
+	enable = enable && device_may_wakeup(&dev->pnp_dev->dev);
+	dbg("wake on IR %s", enable ? "enabled" : "disabled");
+	ene_set_clear_reg_mask(dev, ENE_FW1, ENE_FW1_WAKE, enable);
+}
+
+#ifdef CONFIG_PM
+static int ene_suspend(struct pnp_dev *pnp_dev, pm_message_t state)
+{
+	struct ene_device *dev = pnp_get_drvdata(pnp_dev);
+	ene_enable_wake(dev, true);
+
+	/* TODO: add support for wake pattern */
+	return 0;
+}
+
+static int ene_resume(struct pnp_dev *pnp_dev)
+{
+	struct ene_device *dev = pnp_get_drvdata(pnp_dev);
+	ene_setup_hw_settings(dev);
+
+	if (dev->rx_enabled)
+		ene_rx_enable(dev);
+
+	ene_enable_wake(dev, false);
+	return 0;
+}
+#endif
+
+static void ene_shutdown(struct pnp_dev *pnp_dev)
+{
+	struct ene_device *dev = pnp_get_drvdata(pnp_dev);
+	ene_enable_wake(dev, true);
+}
+
+static const struct pnp_device_id ene_ids[] = {
+	{.id = "ENE0100",},
+	{.id = "ENE0200",},
+	{.id = "ENE0201",},
+	{.id = "ENE0202",},
+	{},
+};
+
+static struct pnp_driver ene_driver = {
+	.name = ENE_DRIVER_NAME,
+	.id_table = ene_ids,
+	.flags = PNP_DRIVER_RES_DO_NOT_CHANGE,
+
+	.probe = ene_probe,
+	.remove = __devexit_p(ene_remove),
+#ifdef CONFIG_PM
+	.suspend = ene_suspend,
+	.resume = ene_resume,
+#endif
+	.shutdown = ene_shutdown,
+};
+
+static int __init ene_init(void)
+{
+	return pnp_register_driver(&ene_driver);
+}
+
+static void ene_exit(void)
+{
+	pnp_unregister_driver(&ene_driver);
+}
+
+module_param(sample_period, int, S_IRUGO);
+MODULE_PARM_DESC(sample_period, "Hardware sample period (50 us default)");
+
+module_param(learning_mode_force, bool, S_IRUGO);
+MODULE_PARM_DESC(learning_mode_force, "Enable learning mode by default");
+
+module_param(debug, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Debug level");
+
+module_param(txsim, bool, S_IRUGO);
+MODULE_PARM_DESC(txsim,
+	"Simulate TX features on unsupported hardware (dangerous)");
+
+MODULE_DEVICE_TABLE(pnp, ene_ids);
+MODULE_DESCRIPTION
+	("Infrared input driver for KB3926B/C/D/E/F "
+	"(aka ENE0100/ENE0200/ENE0201/ENE0202) CIR port");
+
+MODULE_AUTHOR("Maxim Levitsky");
+MODULE_LICENSE("GPL");
+
+module_init(ene_init);
+module_exit(ene_exit);
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/ene_ir.h linux-libre-2.6.38-gnu1/drivers/media/rc/ene_ir.h
--- linux-libre-2.6.37-gnu1/drivers/media/rc/ene_ir.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/ene_ir.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,259 @@
+/*
+ * driver for ENE KB3926 B/C/D/E/F CIR (also known as ENE0XXX)
+ *
+ * Copyright (C) 2010 Maxim Levitsky <maximlevitsky@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
+ */
+#include <linux/spinlock.h>
+
+
+/* hardware address */
+#define ENE_STATUS		0	/* hardware status - unused */
+#define ENE_ADDR_HI		1	/* hi byte of register address */
+#define ENE_ADDR_LO		2	/* low byte of register address */
+#define ENE_IO			3	/* read/write window */
+#define ENE_IO_SIZE		4
+
+/* 8 bytes of samples, divided in 2 packets*/
+#define ENE_FW_SAMPLE_BUFFER	0xF8F0	/* sample buffer */
+#define ENE_FW_SAMPLE_SPACE	0x80	/* sample is space */
+#define ENE_FW_PACKET_SIZE	4
+
+/* first firmware flag register */
+#define ENE_FW1			0xF8F8  /* flagr */
+#define	ENE_FW1_ENABLE		0x01	/* enable fw processing */
+#define ENE_FW1_TXIRQ		0x02	/* TX interrupt pending */
+#define ENE_FW1_HAS_EXTRA_BUF	0x04	/* fw uses extra buffer*/
+#define ENE_FW1_EXTRA_BUF_HND	0x08	/* extra buffer handshake bit*/
+#define ENE_FW1_LED_ON		0x10	/* turn on a led */
+
+#define ENE_FW1_WPATTERN	0x20	/* enable wake pattern */
+#define ENE_FW1_WAKE		0x40	/* enable wake from S3 */
+#define ENE_FW1_IRQ		0x80	/* enable interrupt */
+
+/* second firmware flag register */
+#define ENE_FW2			0xF8F9  /* flagw */
+#define ENE_FW2_BUF_WPTR	0x01	/* which half of the buffer to read */
+#define ENE_FW2_RXIRQ		0x04	/* RX IRQ pending*/
+#define ENE_FW2_GP0A		0x08	/* Use GPIO0A for demodulated input */
+#define ENE_FW2_EMMITER1_CONN	0x10	/* TX emmiter 1 connected */
+#define ENE_FW2_EMMITER2_CONN	0x20	/* TX emmiter 2 connected */
+
+#define ENE_FW2_FAN_INPUT	0x40	/* fan input used for demodulated data*/
+#define ENE_FW2_LEARNING	0x80	/* hardware supports learning and TX */
+
+/* firmware RX pointer for new style buffer */
+#define ENE_FW_RX_POINTER	0xF8FA
+
+/* high parts of samples for fan input (8 samples)*/
+#define ENE_FW_SMPL_BUF_FAN	0xF8FB
+#define ENE_FW_SMPL_BUF_FAN_PLS	0x8000	/* combined sample is pulse */
+#define ENE_FW_SMPL_BUF_FAN_MSK	0x0FFF  /* combined sample maximum value */
+#define ENE_FW_SAMPLE_PERIOD_FAN 61	/* fan input has fixed sample period */
+
+/* transmitter ports */
+#define ENE_GPIOFS1		0xFC01
+#define ENE_GPIOFS1_GPIO0D	0x20	/* enable tx output on GPIO0D */
+#define ENE_GPIOFS8		0xFC08
+#define ENE_GPIOFS8_GPIO41	0x02	/* enable tx output on GPIO40 */
+
+/* IRQ registers block (for revision B) */
+#define ENEB_IRQ		0xFD09	/* IRQ number */
+#define ENEB_IRQ_UNK1		0xFD17	/* unknown setting = 1 */
+#define ENEB_IRQ_STATUS		0xFD80	/* irq status */
+#define ENEB_IRQ_STATUS_IR	0x20	/* IR irq */
+
+/* fan as input settings */
+#define ENE_FAN_AS_IN1		0xFE30  /* fan init reg 1 */
+#define ENE_FAN_AS_IN1_EN	0xCD
+#define ENE_FAN_AS_IN2		0xFE31  /* fan init reg 2 */
+#define ENE_FAN_AS_IN2_EN	0x03
+
+/* IRQ registers block (for revision C,D) */
+#define ENE_IRQ			0xFE9B	/* new irq settings register */
+#define ENE_IRQ_MASK		0x0F	/* irq number mask */
+#define ENE_IRQ_UNK_EN		0x10	/* always enabled */
+#define ENE_IRQ_STATUS		0x20	/* irq status and ACK */
+
+/* CIR Config register #1 */
+#define ENE_CIRCFG		0xFEC0
+#define ENE_CIRCFG_RX_EN	0x01	/* RX enable */
+#define ENE_CIRCFG_RX_IRQ	0x02	/* Enable hardware interrupt */
+#define ENE_CIRCFG_REV_POL	0x04	/* Input polarity reversed */
+#define ENE_CIRCFG_CARR_DEMOD	0x08	/* Enable carrier demodulator */
+
+#define ENE_CIRCFG_TX_EN	0x10	/* TX enable */
+#define ENE_CIRCFG_TX_IRQ	0x20	/* Send interrupt on TX done */
+#define ENE_CIRCFG_TX_POL_REV	0x40	/* TX polarity reversed */
+#define ENE_CIRCFG_TX_CARR	0x80	/* send TX carrier or not */
+
+/* CIR config register #2 */
+#define ENE_CIRCFG2		0xFEC1
+#define ENE_CIRCFG2_RLC		0x00
+#define ENE_CIRCFG2_RC5		0x01
+#define ENE_CIRCFG2_RC6		0x02
+#define ENE_CIRCFG2_NEC		0x03
+#define ENE_CIRCFG2_CARR_DETECT	0x10	/* Enable carrier detection */
+#define ENE_CIRCFG2_GPIO0A	0x20	/* Use GPIO0A instead of GPIO40 for input */
+#define ENE_CIRCFG2_FAST_SAMPL1	0x40	/* Fast leading pulse detection for RC6 */
+#define ENE_CIRCFG2_FAST_SAMPL2	0x80	/* Fast data detection for RC6 */
+
+/* Knobs for protocol decoding - will document when/if will use them */
+#define ENE_CIRPF		0xFEC2
+#define ENE_CIRHIGH		0xFEC3
+#define ENE_CIRBIT		0xFEC4
+#define ENE_CIRSTART		0xFEC5
+#define ENE_CIRSTART2		0xFEC6
+
+/* Actual register which contains RLC RX data - read by firmware */
+#define ENE_CIRDAT_IN		0xFEC7
+
+
+/* RLC configuration - sample period (1us resulution) + idle mode */
+#define ENE_CIRRLC_CFG		0xFEC8
+#define ENE_CIRRLC_CFG_OVERFLOW	0x80	/* interrupt on overflows if set */
+#define ENE_DEFAULT_SAMPLE_PERIOD 50
+
+/* Two byte RLC TX buffer */
+#define ENE_CIRRLC_OUT0		0xFEC9
+#define ENE_CIRRLC_OUT1		0xFECA
+#define ENE_CIRRLC_OUT_PULSE	0x80	/* Transmitted sample is pulse */
+#define ENE_CIRRLC_OUT_MASK	0x7F
+
+
+/* Carrier detect setting
+ * Low nibble  - number of carrier pulses to average
+ * High nibble - number of initial carrier pulses to discard
+ */
+#define ENE_CIRCAR_PULS		0xFECB
+
+/* detected RX carrier period (resolution: 500 ns) */
+#define ENE_CIRCAR_PRD		0xFECC
+#define ENE_CIRCAR_PRD_VALID	0x80	/* data valid content valid */
+
+/* detected RX carrier pulse width (resolution: 500 ns) */
+#define ENE_CIRCAR_HPRD		0xFECD
+
+/* TX period (resolution: 500 ns, minimum 2)*/
+#define ENE_CIRMOD_PRD		0xFECE
+#define ENE_CIRMOD_PRD_POL	0x80	/* TX carrier polarity*/
+
+#define ENE_CIRMOD_PRD_MAX	0x7F	/* 15.87 kHz */
+#define ENE_CIRMOD_PRD_MIN	0x02	/* 1 Mhz */
+
+/* TX pulse width (resolution: 500 ns)*/
+#define ENE_CIRMOD_HPRD		0xFECF
+
+/* Hardware versions */
+#define ENE_ECHV		0xFF00	/* hardware revision */
+#define ENE_PLLFRH		0xFF16
+#define ENE_PLLFRL		0xFF17
+#define ENE_DEFAULT_PLL_FREQ	1000
+
+#define ENE_ECSTS		0xFF1D
+#define ENE_ECSTS_RSRVD		0x04
+
+#define ENE_ECVER_MAJOR		0xFF1E	/* chip version */
+#define ENE_ECVER_MINOR		0xFF1F
+#define ENE_HW_VER_OLD		0xFD00
+
+/******************************************************************************/
+
+#define ENE_DRIVER_NAME		"ene_ir"
+
+#define ENE_IRQ_RX		1
+#define ENE_IRQ_TX		2
+
+#define  ENE_HW_B		1	/* 3926B */
+#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(format, ...)		__dbg(1, format, ## __VA_ARGS__)
+#define dbg_verbose(format, ...)	__dbg(2, format, ## __VA_ARGS__)
+#define dbg_regs(format, ...)		__dbg(3, format, ## __VA_ARGS__)
+
+struct ene_device {
+	struct pnp_dev *pnp_dev;
+	struct rc_dev *rdev;
+
+	/* hw IO settings */
+	long hw_io;
+	int irq;
+	spinlock_t hw_lock;
+
+	/* HW features */
+	int hw_revision;			/* hardware revision */
+	bool hw_use_gpio_0a;			/* gpio0a is demodulated input*/
+	bool hw_extra_buffer;			/* hardware has 'extra buffer' */
+	bool hw_fan_input;			/* fan input is IR data source */
+	bool hw_learning_and_tx_capable;	/* learning & tx capable */
+	int  pll_freq;
+	int buffer_len;
+
+	/* Extra RX buffer location */
+	int extra_buf1_address;
+	int extra_buf1_len;
+	int extra_buf2_address;
+	int extra_buf2_len;
+
+	/* HW state*/
+	int r_pointer;				/* pointer to next sample to read */
+	int w_pointer;				/* pointer to next sample hw will write */
+	bool rx_fan_input_inuse;		/* is fan input in use for rx*/
+	int tx_reg;				/* current reg used for TX */
+	u8  saved_conf1;			/* saved FEC0 reg */
+	unsigned int tx_sample;			/* current sample for TX */
+	bool tx_sample_pulse;			/* current sample is pulse */
+
+	/* TX buffer */
+	int *tx_buffer;				/* input samples buffer*/
+	int tx_pos;				/* position in that bufer */
+	int tx_len;				/* current len of tx buffer */
+	int tx_done;				/* done transmitting */
+						/* one more sample pending*/
+	struct completion tx_complete;		/* TX completion */
+	struct timer_list tx_sim_timer;
+
+	/* TX settings */
+	int tx_period;
+	int tx_duty_cycle;
+	int transmitter_mask;
+
+	/* RX settings */
+	bool learning_mode_enabled;		/* learning input enabled */
+	bool carrier_detect_enabled;		/* carrier detect enabled */
+	int rx_period_adjust;
+	bool rx_enabled;
+};
+
+static int ene_irq_status(struct ene_device *dev);
+static void ene_rx_read_hw_pointer(struct ene_device *dev);
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/imon.c linux-libre-2.6.38-gnu1/drivers/media/rc/imon.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/imon.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/imon.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,2449 @@
+/*
+ *   imon.c:	input and display driver for SoundGraph iMON IR/VFD/LCD
+ *
+ *   Copyright(C) 2010  Jarod Wilson <jarod@wilsonet.com>
+ *   Portions based on the original lirc_imon driver,
+ *	Copyright(C) 2004  Venky Raju(dev@venky.ws)
+ *
+ *   Huge thanks to R. Geoff Newbury for invaluable debugging on the
+ *   0xffdc iMON devices, and for sending me one to hack on, without
+ *   which the support for them wouldn't be nearly as good. Thanks
+ *   also to the numerous 0xffdc device owners that tested auto-config
+ *   support for me and provided debug dumps from their devices.
+ *
+ *   imon 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 ":%s: " fmt, __func__
+
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+
+#include <linux/input.h>
+#include <linux/usb.h>
+#include <linux/usb/input.h>
+#include <media/rc-core.h>
+
+#include <linux/time.h>
+#include <linux/timer.h>
+
+#define MOD_AUTHOR	"Jarod Wilson <jarod@wilsonet.com>"
+#define MOD_DESC	"Driver for SoundGraph iMON MultiMedia IR/Display"
+#define MOD_NAME	"imon"
+#define MOD_VERSION	"0.9.2"
+
+#define DISPLAY_MINOR_BASE	144
+#define DEVICE_NAME	"lcd%d"
+
+#define BUF_CHUNK_SIZE	8
+#define BUF_SIZE	128
+
+#define BIT_DURATION	250	/* each bit received is 250us */
+
+#define IMON_CLOCK_ENABLE_PACKETS	2
+
+/*** P R O T O T Y P E S ***/
+
+/* USB Callback prototypes */
+static int imon_probe(struct usb_interface *interface,
+		      const struct usb_device_id *id);
+static void imon_disconnect(struct usb_interface *interface);
+static void usb_rx_callback_intf0(struct urb *urb);
+static void usb_rx_callback_intf1(struct urb *urb);
+static void usb_tx_callback(struct urb *urb);
+
+/* suspend/resume support */
+static int imon_resume(struct usb_interface *intf);
+static int imon_suspend(struct usb_interface *intf, pm_message_t message);
+
+/* Display file_operations function prototypes */
+static int display_open(struct inode *inode, struct file *file);
+static int display_close(struct inode *inode, struct file *file);
+
+/* VFD write operation */
+static ssize_t vfd_write(struct file *file, const char *buf,
+			 size_t n_bytes, loff_t *pos);
+
+/* LCD file_operations override function prototypes */
+static ssize_t lcd_write(struct file *file, const char *buf,
+			 size_t n_bytes, loff_t *pos);
+
+/*** G L O B A L S ***/
+
+struct imon_context {
+	struct device *dev;
+	/* Newer devices have two interfaces */
+	struct usb_device *usbdev_intf0;
+	struct usb_device *usbdev_intf1;
+
+	bool display_supported;		/* not all controllers do */
+	bool display_isopen;		/* display port has been opened */
+	bool rf_device;			/* true if iMON 2.4G LT/DT RF device */
+	bool rf_isassociating;		/* RF remote associating */
+	bool dev_present_intf0;		/* USB device presence, interface 0 */
+	bool dev_present_intf1;		/* USB device presence, interface 1 */
+
+	struct mutex lock;		/* to lock this object */
+	wait_queue_head_t remove_ok;	/* For unexpected USB disconnects */
+
+	struct usb_endpoint_descriptor *rx_endpoint_intf0;
+	struct usb_endpoint_descriptor *rx_endpoint_intf1;
+	struct usb_endpoint_descriptor *tx_endpoint;
+	struct urb *rx_urb_intf0;
+	struct urb *rx_urb_intf1;
+	struct urb *tx_urb;
+	bool tx_control;
+	unsigned char usb_rx_buf[8];
+	unsigned char usb_tx_buf[8];
+
+	struct tx_t {
+		unsigned char data_buf[35];	/* user data buffer */
+		struct completion finished;	/* wait for write to finish */
+		bool busy;			/* write in progress */
+		int status;			/* status of tx completion */
+	} tx;
+
+	u16 vendor;			/* usb vendor ID */
+	u16 product;			/* usb product ID */
+
+	struct rc_dev *rdev;		/* rc-core device for remote */
+	struct input_dev *idev;		/* input device for panel & IR mouse */
+	struct input_dev *touch;	/* input device for touchscreen */
+
+	spinlock_t kc_lock;		/* make sure we get keycodes right */
+	u32 kc;				/* current input keycode */
+	u32 last_keycode;		/* last reported input keycode */
+	u32 rc_scancode;		/* the computed remote scancode */
+	u8 rc_toggle;			/* the computed remote toggle bit */
+	u64 rc_type;			/* iMON or MCE (RC6) IR protocol? */
+	bool release_code;		/* some keys send a release code */
+
+	u8 display_type;		/* store the display type */
+	bool pad_mouse;			/* toggle kbd(0)/mouse(1) mode */
+
+	char name_rdev[128];		/* rc input device name */
+	char phys_rdev[64];		/* rc input device phys path */
+
+	char name_idev[128];		/* input device name */
+	char phys_idev[64];		/* input device phys path */
+
+	char name_touch[128];		/* touch screen name */
+	char phys_touch[64];		/* touch screen phys path */
+	struct timer_list ttimer;	/* touch screen timer */
+	int touch_x;			/* x coordinate on touchscreen */
+	int touch_y;			/* y coordinate on touchscreen */
+};
+
+#define TOUCH_TIMEOUT	(HZ/30)
+
+/* vfd character device file operations */
+static const struct file_operations vfd_fops = {
+	.owner		= THIS_MODULE,
+	.open		= &display_open,
+	.write		= &vfd_write,
+	.release	= &display_close,
+	.llseek		= noop_llseek,
+};
+
+/* lcd character device file operations */
+static const struct file_operations lcd_fops = {
+	.owner		= THIS_MODULE,
+	.open		= &display_open,
+	.write		= &lcd_write,
+	.release	= &display_close,
+	.llseek		= noop_llseek,
+};
+
+enum {
+	IMON_DISPLAY_TYPE_AUTO = 0,
+	IMON_DISPLAY_TYPE_VFD  = 1,
+	IMON_DISPLAY_TYPE_LCD  = 2,
+	IMON_DISPLAY_TYPE_VGA  = 3,
+	IMON_DISPLAY_TYPE_NONE = 4,
+};
+
+enum {
+	IMON_KEY_IMON	= 0,
+	IMON_KEY_MCE	= 1,
+	IMON_KEY_PANEL	= 2,
+};
+
+/*
+ * USB Device ID for iMON USB Control Boards
+ *
+ * The Windows drivers contain 6 different inf files, more or less one for
+ * each new device until the 0x0034-0x0046 devices, which all use the same
+ * driver. Some of the devices in the 34-46 range haven't been definitively
+ * identified yet. Early devices have either a TriGem Computer, Inc. or a
+ * Samsung vendor ID (0x0aa8 and 0x04e8 respectively), while all later
+ * devices use the SoundGraph vendor ID (0x15c2). This driver only supports
+ * the ffdc and later devices, which do onboard decoding.
+ */
+static struct usb_device_id imon_usb_id_table[] = {
+	/*
+	 * Several devices with this same device ID, all use iMON_PAD.inf
+	 * SoundGraph iMON PAD (IR & VFD)
+	 * SoundGraph iMON PAD (IR & LCD)
+	 * SoundGraph iMON Knob (IR only)
+	 */
+	{ USB_DEVICE(0x15c2, 0xffdc) },
+
+	/*
+	 * Newer devices, all driven by the latest iMON Windows driver, full
+	 * list of device IDs extracted via 'strings Setup/data1.hdr |grep 15c2'
+	 * Need user input to fill in details on unknown devices.
+	 */
+	/* SoundGraph iMON OEM Touch LCD (IR & 7" VGA LCD) */
+	{ USB_DEVICE(0x15c2, 0x0034) },
+	/* SoundGraph iMON OEM Touch LCD (IR & 4.3" VGA LCD) */
+	{ USB_DEVICE(0x15c2, 0x0035) },
+	/* SoundGraph iMON OEM VFD (IR & VFD) */
+	{ USB_DEVICE(0x15c2, 0x0036) },
+	/* device specifics unknown */
+	{ USB_DEVICE(0x15c2, 0x0037) },
+	/* SoundGraph iMON OEM LCD (IR & LCD) */
+	{ USB_DEVICE(0x15c2, 0x0038) },
+	/* SoundGraph iMON UltraBay (IR & LCD) */
+	{ USB_DEVICE(0x15c2, 0x0039) },
+	/* device specifics unknown */
+	{ USB_DEVICE(0x15c2, 0x003a) },
+	/* device specifics unknown */
+	{ USB_DEVICE(0x15c2, 0x003b) },
+	/* SoundGraph iMON OEM Inside (IR only) */
+	{ USB_DEVICE(0x15c2, 0x003c) },
+	/* device specifics unknown */
+	{ USB_DEVICE(0x15c2, 0x003d) },
+	/* device specifics unknown */
+	{ USB_DEVICE(0x15c2, 0x003e) },
+	/* device specifics unknown */
+	{ USB_DEVICE(0x15c2, 0x003f) },
+	/* device specifics unknown */
+	{ USB_DEVICE(0x15c2, 0x0040) },
+	/* SoundGraph iMON MINI (IR only) */
+	{ USB_DEVICE(0x15c2, 0x0041) },
+	/* Antec Veris Multimedia Station EZ External (IR only) */
+	{ USB_DEVICE(0x15c2, 0x0042) },
+	/* Antec Veris Multimedia Station Basic Internal (IR only) */
+	{ USB_DEVICE(0x15c2, 0x0043) },
+	/* Antec Veris Multimedia Station Elite (IR & VFD) */
+	{ USB_DEVICE(0x15c2, 0x0044) },
+	/* Antec Veris Multimedia Station Premiere (IR & LCD) */
+	{ USB_DEVICE(0x15c2, 0x0045) },
+	/* device specifics unknown */
+	{ USB_DEVICE(0x15c2, 0x0046) },
+	{}
+};
+
+/* USB Device data */
+static struct usb_driver imon_driver = {
+	.name		= MOD_NAME,
+	.probe		= imon_probe,
+	.disconnect	= imon_disconnect,
+	.suspend	= imon_suspend,
+	.resume		= imon_resume,
+	.id_table	= imon_usb_id_table,
+};
+
+static struct usb_class_driver imon_vfd_class = {
+	.name		= DEVICE_NAME,
+	.fops		= &vfd_fops,
+	.minor_base	= DISPLAY_MINOR_BASE,
+};
+
+static struct usb_class_driver imon_lcd_class = {
+	.name		= DEVICE_NAME,
+	.fops		= &lcd_fops,
+	.minor_base	= DISPLAY_MINOR_BASE,
+};
+
+/* imon receiver front panel/knob key table */
+static const struct {
+	u64 hw_code;
+	u32 keycode;
+} imon_panel_key_table[] = {
+	{ 0x000000000f00ffeell, KEY_PROG1 }, /* Go */
+	{ 0x000000001f00ffeell, KEY_AUDIO },
+	{ 0x000000002000ffeell, KEY_VIDEO },
+	{ 0x000000002100ffeell, KEY_CAMERA },
+	{ 0x000000002700ffeell, KEY_DVD },
+	{ 0x000000002300ffeell, KEY_TV },
+	{ 0x000000000500ffeell, KEY_PREVIOUS },
+	{ 0x000000000700ffeell, KEY_REWIND },
+	{ 0x000000000400ffeell, KEY_STOP },
+	{ 0x000000003c00ffeell, KEY_PLAYPAUSE },
+	{ 0x000000000800ffeell, KEY_FASTFORWARD },
+	{ 0x000000000600ffeell, KEY_NEXT },
+	{ 0x000000010000ffeell, KEY_RIGHT },
+	{ 0x000001000000ffeell, KEY_LEFT },
+	{ 0x000000003d00ffeell, KEY_SELECT },
+	{ 0x000100000000ffeell, KEY_VOLUMEUP },
+	{ 0x010000000000ffeell, KEY_VOLUMEDOWN },
+	{ 0x000000000100ffeell, KEY_MUTE },
+	/* 0xffdc iMON MCE VFD */
+	{ 0x00010000ffffffeell, KEY_VOLUMEUP },
+	{ 0x01000000ffffffeell, KEY_VOLUMEDOWN },
+	/* iMON Knob values */
+	{ 0x000100ffffffffeell, KEY_VOLUMEUP },
+	{ 0x010000ffffffffeell, KEY_VOLUMEDOWN },
+	{ 0x000008ffffffffeell, KEY_MUTE },
+};
+
+/* to prevent races between open() and disconnect(), probing, etc */
+static DEFINE_MUTEX(driver_lock);
+
+/* Module bookkeeping bits */
+MODULE_AUTHOR(MOD_AUTHOR);
+MODULE_DESCRIPTION(MOD_DESC);
+MODULE_VERSION(MOD_VERSION);
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(usb, imon_usb_id_table);
+
+static bool debug;
+module_param(debug, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Debug messages: 0=no, 1=yes (default: no)");
+
+/* lcd, vfd, vga or none? should be auto-detected, but can be overridden... */
+static int display_type;
+module_param(display_type, int, S_IRUGO);
+MODULE_PARM_DESC(display_type, "Type of attached display. 0=autodetect, "
+		 "1=vfd, 2=lcd, 3=vga, 4=none (default: autodetect)");
+
+static int pad_stabilize = 1;
+module_param(pad_stabilize, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(pad_stabilize, "Apply stabilization algorithm to iMON PAD "
+		 "presses in arrow key mode. 0=disable, 1=enable (default).");
+
+/*
+ * In certain use cases, mouse mode isn't really helpful, and could actually
+ * cause confusion, so allow disabling it when the IR device is open.
+ */
+static bool nomouse;
+module_param(nomouse, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(nomouse, "Disable mouse input device mode when IR device is "
+		 "open. 0=don't disable, 1=disable. (default: don't disable)");
+
+/* threshold at which a pad push registers as an arrow key in kbd mode */
+static int pad_thresh;
+module_param(pad_thresh, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(pad_thresh, "Threshold at which a pad push registers as an "
+		 "arrow key in kbd mode (default: 28)");
+
+
+static void free_imon_context(struct imon_context *ictx)
+{
+	struct device *dev = ictx->dev;
+
+	usb_free_urb(ictx->tx_urb);
+	usb_free_urb(ictx->rx_urb_intf0);
+	usb_free_urb(ictx->rx_urb_intf1);
+	kfree(ictx);
+
+	dev_dbg(dev, "%s: iMON context freed\n", __func__);
+}
+
+/**
+ * Called when the Display device (e.g. /dev/lcd0)
+ * is opened by the application.
+ */
+static int display_open(struct inode *inode, struct file *file)
+{
+	struct usb_interface *interface;
+	struct imon_context *ictx = NULL;
+	int subminor;
+	int retval = 0;
+
+	/* prevent races with disconnect */
+	mutex_lock(&driver_lock);
+
+	subminor = iminor(inode);
+	interface = usb_find_interface(&imon_driver, subminor);
+	if (!interface) {
+		pr_err("could not find interface for minor %d\n", subminor);
+		retval = -ENODEV;
+		goto exit;
+	}
+	ictx = usb_get_intfdata(interface);
+
+	if (!ictx) {
+		pr_err("no context found for minor %d\n", subminor);
+		retval = -ENODEV;
+		goto exit;
+	}
+
+	mutex_lock(&ictx->lock);
+
+	if (!ictx->display_supported) {
+		pr_err("display not supported by device\n");
+		retval = -ENODEV;
+	} else if (ictx->display_isopen) {
+		pr_err("display port is already open\n");
+		retval = -EBUSY;
+	} else {
+		ictx->display_isopen = true;
+		file->private_data = ictx;
+		dev_dbg(ictx->dev, "display port opened\n");
+	}
+
+	mutex_unlock(&ictx->lock);
+
+exit:
+	mutex_unlock(&driver_lock);
+	return retval;
+}
+
+/**
+ * Called when the display device (e.g. /dev/lcd0)
+ * is closed by the application.
+ */
+static int display_close(struct inode *inode, struct file *file)
+{
+	struct imon_context *ictx = NULL;
+	int retval = 0;
+
+	ictx = file->private_data;
+
+	if (!ictx) {
+		pr_err("no context for device\n");
+		return -ENODEV;
+	}
+
+	mutex_lock(&ictx->lock);
+
+	if (!ictx->display_supported) {
+		pr_err("display not supported by device\n");
+		retval = -ENODEV;
+	} else if (!ictx->display_isopen) {
+		pr_err("display is not open\n");
+		retval = -EIO;
+	} else {
+		ictx->display_isopen = false;
+		dev_dbg(ictx->dev, "display port closed\n");
+		if (!ictx->dev_present_intf0) {
+			/*
+			 * Device disconnected before close and IR port is not
+			 * open. If IR port is open, context will be deleted by
+			 * ir_close.
+			 */
+			mutex_unlock(&ictx->lock);
+			free_imon_context(ictx);
+			return retval;
+		}
+	}
+
+	mutex_unlock(&ictx->lock);
+	return retval;
+}
+
+/**
+ * Sends a packet to the device -- this function must be called
+ * with ictx->lock held.
+ */
+static int send_packet(struct imon_context *ictx)
+{
+	unsigned int pipe;
+	unsigned long timeout;
+	int interval = 0;
+	int retval = 0;
+	struct usb_ctrlrequest *control_req = NULL;
+
+	/* Check if we need to use control or interrupt urb */
+	if (!ictx->tx_control) {
+		pipe = usb_sndintpipe(ictx->usbdev_intf0,
+				      ictx->tx_endpoint->bEndpointAddress);
+		interval = ictx->tx_endpoint->bInterval;
+
+		usb_fill_int_urb(ictx->tx_urb, ictx->usbdev_intf0, pipe,
+				 ictx->usb_tx_buf,
+				 sizeof(ictx->usb_tx_buf),
+				 usb_tx_callback, ictx, interval);
+
+		ictx->tx_urb->actual_length = 0;
+	} else {
+		/* fill request into kmalloc'ed space: */
+		control_req = kmalloc(sizeof(struct usb_ctrlrequest),
+				      GFP_KERNEL);
+		if (control_req == NULL)
+			return -ENOMEM;
+
+		/* setup packet is '21 09 0200 0001 0008' */
+		control_req->bRequestType = 0x21;
+		control_req->bRequest = 0x09;
+		control_req->wValue = cpu_to_le16(0x0200);
+		control_req->wIndex = cpu_to_le16(0x0001);
+		control_req->wLength = cpu_to_le16(0x0008);
+
+		/* control pipe is endpoint 0x00 */
+		pipe = usb_sndctrlpipe(ictx->usbdev_intf0, 0);
+
+		/* build the control urb */
+		usb_fill_control_urb(ictx->tx_urb, ictx->usbdev_intf0,
+				     pipe, (unsigned char *)control_req,
+				     ictx->usb_tx_buf,
+				     sizeof(ictx->usb_tx_buf),
+				     usb_tx_callback, ictx);
+		ictx->tx_urb->actual_length = 0;
+	}
+
+	init_completion(&ictx->tx.finished);
+	ictx->tx.busy = true;
+	smp_rmb(); /* ensure later readers know we're busy */
+
+	retval = usb_submit_urb(ictx->tx_urb, GFP_KERNEL);
+	if (retval) {
+		ictx->tx.busy = false;
+		smp_rmb(); /* ensure later readers know we're not busy */
+		pr_err("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");
+		mutex_lock(&ictx->lock);
+
+		retval = ictx->tx.status;
+		if (retval)
+			pr_err("packet tx failed (%d)\n", retval);
+	}
+
+	kfree(control_req);
+
+	/*
+	 * Induce a mandatory 5ms delay before returning, as otherwise,
+	 * send_packet can get called so rapidly as to overwhelm the device,
+	 * particularly on faster systems and/or those with quirky usb.
+	 */
+	timeout = msecs_to_jiffies(5);
+	set_current_state(TASK_UNINTERRUPTIBLE);
+	schedule_timeout(timeout);
+
+	return retval;
+}
+
+/**
+ * Sends an associate packet to the iMON 2.4G.
+ *
+ * This might not be such a good idea, since it has an id collision with
+ * some versions of the "IR & VFD" combo. The only way to determine if it
+ * is an RF version is to look at the product description string. (Which
+ * we currently do not fetch).
+ */
+static int send_associate_24g(struct imon_context *ictx)
+{
+	int retval;
+	const unsigned char packet[8] = { 0x01, 0x00, 0x00, 0x00,
+					  0x00, 0x00, 0x00, 0x20 };
+
+	if (!ictx) {
+		pr_err("no context for device\n");
+		return -ENODEV;
+	}
+
+	if (!ictx->dev_present_intf0) {
+		pr_err("no iMON device present\n");
+		return -ENODEV;
+	}
+
+	memcpy(ictx->usb_tx_buf, packet, sizeof(packet));
+	retval = send_packet(ictx);
+
+	return retval;
+}
+
+/**
+ * Sends packets to setup and show clock on iMON display
+ *
+ * Arguments: year - last 2 digits of year, month - 1..12,
+ * day - 1..31, dow - day of the week (0-Sun...6-Sat),
+ * hour - 0..23, minute - 0..59, second - 0..59
+ */
+static int send_set_imon_clock(struct imon_context *ictx,
+			       unsigned int year, unsigned int month,
+			       unsigned int day, unsigned int dow,
+			       unsigned int hour, unsigned int minute,
+			       unsigned int second)
+{
+	unsigned char clock_enable_pkt[IMON_CLOCK_ENABLE_PACKETS][8];
+	int retval = 0;
+	int i;
+
+	if (!ictx) {
+		pr_err("no context for device\n");
+		return -ENODEV;
+	}
+
+	switch (ictx->display_type) {
+	case IMON_DISPLAY_TYPE_LCD:
+		clock_enable_pkt[0][0] = 0x80;
+		clock_enable_pkt[0][1] = year;
+		clock_enable_pkt[0][2] = month-1;
+		clock_enable_pkt[0][3] = day;
+		clock_enable_pkt[0][4] = hour;
+		clock_enable_pkt[0][5] = minute;
+		clock_enable_pkt[0][6] = second;
+
+		clock_enable_pkt[1][0] = 0x80;
+		clock_enable_pkt[1][1] = 0;
+		clock_enable_pkt[1][2] = 0;
+		clock_enable_pkt[1][3] = 0;
+		clock_enable_pkt[1][4] = 0;
+		clock_enable_pkt[1][5] = 0;
+		clock_enable_pkt[1][6] = 0;
+
+		if (ictx->product == 0xffdc) {
+			clock_enable_pkt[0][7] = 0x50;
+			clock_enable_pkt[1][7] = 0x51;
+		} else {
+			clock_enable_pkt[0][7] = 0x88;
+			clock_enable_pkt[1][7] = 0x8a;
+		}
+
+		break;
+
+	case IMON_DISPLAY_TYPE_VFD:
+		clock_enable_pkt[0][0] = year;
+		clock_enable_pkt[0][1] = month-1;
+		clock_enable_pkt[0][2] = day;
+		clock_enable_pkt[0][3] = dow;
+		clock_enable_pkt[0][4] = hour;
+		clock_enable_pkt[0][5] = minute;
+		clock_enable_pkt[0][6] = second;
+		clock_enable_pkt[0][7] = 0x40;
+
+		clock_enable_pkt[1][0] = 0;
+		clock_enable_pkt[1][1] = 0;
+		clock_enable_pkt[1][2] = 1;
+		clock_enable_pkt[1][3] = 0;
+		clock_enable_pkt[1][4] = 0;
+		clock_enable_pkt[1][5] = 0;
+		clock_enable_pkt[1][6] = 0;
+		clock_enable_pkt[1][7] = 0x42;
+
+		break;
+
+	default:
+		return -ENODEV;
+	}
+
+	for (i = 0; i < IMON_CLOCK_ENABLE_PACKETS; i++) {
+		memcpy(ictx->usb_tx_buf, clock_enable_pkt[i], 8);
+		retval = send_packet(ictx);
+		if (retval) {
+			pr_err("send_packet failed for packet %d\n", i);
+			break;
+		}
+	}
+
+	return retval;
+}
+
+/**
+ * These are the sysfs functions to handle the association on the iMON 2.4G LT.
+ */
+static ssize_t show_associate_remote(struct device *d,
+				     struct device_attribute *attr,
+				     char *buf)
+{
+	struct imon_context *ictx = dev_get_drvdata(d);
+
+	if (!ictx)
+		return -ENODEV;
+
+	mutex_lock(&ictx->lock);
+	if (ictx->rf_isassociating)
+		strcpy(buf, "associating\n");
+	else
+		strcpy(buf, "closed\n");
+
+	dev_info(d, "Visit http://www.lirc.org/html/imon-24g.html for "
+		 "instructions on how to associate your iMON 2.4G DT/LT "
+		 "remote\n");
+	mutex_unlock(&ictx->lock);
+	return strlen(buf);
+}
+
+static ssize_t store_associate_remote(struct device *d,
+				      struct device_attribute *attr,
+				      const char *buf, size_t count)
+{
+	struct imon_context *ictx;
+
+	ictx = dev_get_drvdata(d);
+
+	if (!ictx)
+		return -ENODEV;
+
+	mutex_lock(&ictx->lock);
+	ictx->rf_isassociating = true;
+	send_associate_24g(ictx);
+	mutex_unlock(&ictx->lock);
+
+	return count;
+}
+
+/**
+ * sysfs functions to control internal imon clock
+ */
+static ssize_t show_imon_clock(struct device *d,
+			       struct device_attribute *attr, char *buf)
+{
+	struct imon_context *ictx = dev_get_drvdata(d);
+	size_t len;
+
+	if (!ictx)
+		return -ENODEV;
+
+	mutex_lock(&ictx->lock);
+
+	if (!ictx->display_supported) {
+		len = snprintf(buf, PAGE_SIZE, "Not supported.");
+	} else {
+		len = snprintf(buf, PAGE_SIZE,
+			"To set the clock on your iMON display:\n"
+			"# date \"+%%y %%m %%d %%w %%H %%M %%S\" > imon_clock\n"
+			"%s", ictx->display_isopen ?
+			"\nNOTE: imon device must be closed\n" : "");
+	}
+
+	mutex_unlock(&ictx->lock);
+
+	return len;
+}
+
+static ssize_t store_imon_clock(struct device *d,
+				struct device_attribute *attr,
+				const char *buf, size_t count)
+{
+	struct imon_context *ictx = dev_get_drvdata(d);
+	ssize_t retval;
+	unsigned int year, month, day, dow, hour, minute, second;
+
+	if (!ictx)
+		return -ENODEV;
+
+	mutex_lock(&ictx->lock);
+
+	if (!ictx->display_supported) {
+		retval = -ENODEV;
+		goto exit;
+	} else if (ictx->display_isopen) {
+		retval = -EBUSY;
+		goto exit;
+	}
+
+	if (sscanf(buf, "%u %u %u %u %u %u %u",	&year, &month, &day, &dow,
+		   &hour, &minute, &second) != 7) {
+		retval = -EINVAL;
+		goto exit;
+	}
+
+	if ((month < 1 || month > 12) ||
+	    (day < 1 || day > 31) || (dow > 6) ||
+	    (hour > 23) || (minute > 59) || (second > 59)) {
+		retval = -EINVAL;
+		goto exit;
+	}
+
+	retval = send_set_imon_clock(ictx, year, month, day, dow,
+				     hour, minute, second);
+	if (retval)
+		goto exit;
+
+	retval = count;
+exit:
+	mutex_unlock(&ictx->lock);
+
+	return retval;
+}
+
+
+static DEVICE_ATTR(imon_clock, S_IWUSR | S_IRUGO, show_imon_clock,
+		   store_imon_clock);
+
+static DEVICE_ATTR(associate_remote, S_IWUSR | S_IRUGO, show_associate_remote,
+		   store_associate_remote);
+
+static struct attribute *imon_display_sysfs_entries[] = {
+	&dev_attr_imon_clock.attr,
+	NULL
+};
+
+static struct attribute_group imon_display_attr_group = {
+	.attrs = imon_display_sysfs_entries
+};
+
+static struct attribute *imon_rf_sysfs_entries[] = {
+	&dev_attr_associate_remote.attr,
+	NULL
+};
+
+static struct attribute_group imon_rf_attr_group = {
+	.attrs = imon_rf_sysfs_entries
+};
+
+/**
+ * Writes data to the VFD.  The iMON VFD is 2x16 characters
+ * and requires data in 5 consecutive USB interrupt packets,
+ * each packet but the last carrying 7 bytes.
+ *
+ * I don't know if the VFD board supports features such as
+ * scrolling, clearing rows, blanking, etc. so at
+ * the caller must provide a full screen of data.  If fewer
+ * than 32 bytes are provided spaces will be appended to
+ * generate a full screen.
+ */
+static ssize_t vfd_write(struct file *file, const char *buf,
+			 size_t n_bytes, loff_t *pos)
+{
+	int i;
+	int offset;
+	int seq;
+	int retval = 0;
+	struct imon_context *ictx;
+	const unsigned char vfd_packet6[] = {
+		0x01, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF };
+
+	ictx = file->private_data;
+	if (!ictx) {
+		pr_err("no context for device\n");
+		return -ENODEV;
+	}
+
+	mutex_lock(&ictx->lock);
+
+	if (!ictx->dev_present_intf0) {
+		pr_err("no iMON device present\n");
+		retval = -ENODEV;
+		goto exit;
+	}
+
+	if (n_bytes <= 0 || n_bytes > 32) {
+		pr_err("invalid payload size\n");
+		retval = -EINVAL;
+		goto exit;
+	}
+
+	if (copy_from_user(ictx->tx.data_buf, buf, n_bytes)) {
+		retval = -EFAULT;
+		goto exit;
+	}
+
+	/* Pad with spaces */
+	for (i = n_bytes; i < 32; ++i)
+		ictx->tx.data_buf[i] = ' ';
+
+	for (i = 32; i < 35; ++i)
+		ictx->tx.data_buf[i] = 0xFF;
+
+	offset = 0;
+	seq = 0;
+
+	do {
+		memcpy(ictx->usb_tx_buf, ictx->tx.data_buf + offset, 7);
+		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);
+			goto exit;
+		} else {
+			seq += 2;
+			offset += 7;
+		}
+
+	} while (offset < 35);
+
+	/* Send packet #6 */
+	memcpy(ictx->usb_tx_buf, &vfd_packet6, sizeof(vfd_packet6));
+	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);
+
+exit:
+	mutex_unlock(&ictx->lock);
+
+	return (!retval) ? n_bytes : retval;
+}
+
+/**
+ * Writes data to the LCD.  The iMON OEM LCD screen expects 8-byte
+ * packets. We accept data as 16 hexadecimal digits, followed by a
+ * newline (to make it easy to drive the device from a command-line
+ * -- even though the actual binary data is a bit complicated).
+ *
+ * The device itself is not a "traditional" text-mode display. It's
+ * actually a 16x96 pixel bitmap display. That means if you want to
+ * display text, you've got to have your own "font" and translate the
+ * text into bitmaps for display. This is really flexible (you can
+ * display whatever diacritics you need, and so on), but it's also
+ * a lot more complicated than most LCDs...
+ */
+static ssize_t lcd_write(struct file *file, const char *buf,
+			 size_t n_bytes, loff_t *pos)
+{
+	int retval = 0;
+	struct imon_context *ictx;
+
+	ictx = file->private_data;
+	if (!ictx) {
+		pr_err("no context for device\n");
+		return -ENODEV;
+	}
+
+	mutex_lock(&ictx->lock);
+
+	if (!ictx->display_supported) {
+		pr_err("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);
+		retval = -EINVAL;
+		goto exit;
+	}
+
+	if (copy_from_user(ictx->usb_tx_buf, buf, 8)) {
+		retval = -EFAULT;
+		goto exit;
+	}
+
+	retval = send_packet(ictx);
+	if (retval) {
+		pr_err("send packet failed!\n");
+		goto exit;
+	} else {
+		dev_dbg(ictx->dev, "%s: write %d bytes to LCD\n",
+			__func__, (int) n_bytes);
+	}
+exit:
+	mutex_unlock(&ictx->lock);
+	return (!retval) ? n_bytes : retval;
+}
+
+/**
+ * Callback function for USB core API: transmit data
+ */
+static void usb_tx_callback(struct urb *urb)
+{
+	struct imon_context *ictx;
+
+	if (!urb)
+		return;
+	ictx = (struct imon_context *)urb->context;
+	if (!ictx)
+		return;
+
+	ictx->tx.status = urb->status;
+
+	/* notify waiters that write has finished */
+	ictx->tx.busy = false;
+	smp_rmb(); /* ensure later readers know we're not busy */
+	complete(&ictx->tx.finished);
+}
+
+/**
+ * report touchscreen input
+ */
+static void imon_touch_display_timeout(unsigned long data)
+{
+	struct imon_context *ictx = (struct imon_context *)data;
+
+	if (ictx->display_type != IMON_DISPLAY_TYPE_VGA)
+		return;
+
+	input_report_abs(ictx->touch, ABS_X, ictx->touch_x);
+	input_report_abs(ictx->touch, ABS_Y, ictx->touch_y);
+	input_report_key(ictx->touch, BTN_TOUCH, 0x00);
+	input_sync(ictx->touch);
+}
+
+/**
+ * iMON IR receivers support two different signal sets -- those used by
+ * the iMON remotes, and those used by the Windows MCE remotes (which is
+ * really just RC-6), but only one or the other at a time, as the signals
+ * are decoded onboard the receiver.
+ */
+static int imon_ir_change_protocol(struct rc_dev *rc, u64 rc_type)
+{
+	int retval;
+	struct imon_context *ictx = rc->priv;
+	struct device *dev = ictx->dev;
+	unsigned char ir_proto_packet[] = {
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86 };
+
+	if (rc_type && !(rc_type & rc->allowed_protos))
+		dev_warn(dev, "Looks like you're trying to use an IR protocol "
+			 "this device does not support\n");
+
+	switch (rc_type) {
+	case RC_TYPE_RC6:
+		dev_dbg(dev, "Configuring IR receiver for MCE protocol\n");
+		ir_proto_packet[0] = 0x01;
+		break;
+	case RC_TYPE_UNKNOWN:
+	case RC_TYPE_OTHER:
+		dev_dbg(dev, "Configuring IR receiver for iMON protocol\n");
+		if (!pad_stabilize)
+			dev_dbg(dev, "PAD stabilize functionality disabled\n");
+		/* ir_proto_packet[0] = 0x00; // already the default */
+		rc_type = RC_TYPE_OTHER;
+		break;
+	default:
+		dev_warn(dev, "Unsupported IR protocol specified, overriding "
+			 "to iMON IR protocol\n");
+		if (!pad_stabilize)
+			dev_dbg(dev, "PAD stabilize functionality disabled\n");
+		/* ir_proto_packet[0] = 0x00; // already the default */
+		rc_type = RC_TYPE_OTHER;
+		break;
+	}
+
+	memcpy(ictx->usb_tx_buf, &ir_proto_packet, sizeof(ir_proto_packet));
+
+	retval = send_packet(ictx);
+	if (retval)
+		goto out;
+
+	ictx->rc_type = rc_type;
+	ictx->pad_mouse = false;
+
+out:
+	return retval;
+}
+
+static inline int tv2int(const struct timeval *a, const struct timeval *b)
+{
+	int usecs = 0;
+	int sec   = 0;
+
+	if (b->tv_usec > a->tv_usec) {
+		usecs = 1000000;
+		sec--;
+	}
+
+	usecs += a->tv_usec - b->tv_usec;
+
+	sec += a->tv_sec - b->tv_sec;
+	sec *= 1000;
+	usecs /= 1000;
+	sec += usecs;
+
+	if (sec < 0)
+		sec = 1000;
+
+	return sec;
+}
+
+/**
+ * The directional pad behaves a bit differently, depending on whether this is
+ * one of the older ffdc devices or a newer device. Newer devices appear to
+ * have a higher resolution matrix for more precise mouse movement, but it
+ * makes things overly sensitive in keyboard mode, so we do some interesting
+ * contortions to make it less touchy. Older devices run through the same
+ * routine with shorter timeout and a smaller threshold.
+ */
+static int stabilize(int a, int b, u16 timeout, u16 threshold)
+{
+	struct timeval ct;
+	static struct timeval prev_time = {0, 0};
+	static struct timeval hit_time  = {0, 0};
+	static int x, y, prev_result, hits;
+	int result = 0;
+	int msec, msec_hit;
+
+	do_gettimeofday(&ct);
+	msec = tv2int(&ct, &prev_time);
+	msec_hit = tv2int(&ct, &hit_time);
+
+	if (msec > 100) {
+		x = 0;
+		y = 0;
+		hits = 0;
+	}
+
+	x += a;
+	y += b;
+
+	prev_time = ct;
+
+	if (abs(x) > threshold || abs(y) > threshold) {
+		if (abs(y) > abs(x))
+			result = (y > 0) ? 0x7F : 0x80;
+		else
+			result = (x > 0) ? 0x7F00 : 0x8000;
+
+		x = 0;
+		y = 0;
+
+		if (result == prev_result) {
+			hits++;
+
+			if (hits > 3) {
+				switch (result) {
+				case 0x7F:
+					y = 17 * threshold / 30;
+					break;
+				case 0x80:
+					y -= 17 * threshold / 30;
+					break;
+				case 0x7F00:
+					x = 17 * threshold / 30;
+					break;
+				case 0x8000:
+					x -= 17 * threshold / 30;
+					break;
+				}
+			}
+
+			if (hits == 2 && msec_hit < timeout) {
+				result = 0;
+				hits = 1;
+			}
+		} else {
+			prev_result = result;
+			hits = 1;
+			hit_time = ct;
+		}
+	}
+
+	return result;
+}
+
+static u32 imon_remote_key_lookup(struct imon_context *ictx, u32 scancode)
+{
+	u32 keycode;
+	u32 release;
+	bool is_release_code = false;
+
+	/* Look for the initial press of a button */
+	keycode = rc_g_keycode_from_table(ictx->rdev, scancode);
+	ictx->rc_toggle = 0x0;
+	ictx->rc_scancode = scancode;
+
+	/* Look for the release of a button */
+	if (keycode == KEY_RESERVED) {
+		release = scancode & ~0x4000;
+		keycode = rc_g_keycode_from_table(ictx->rdev, release);
+		if (keycode != KEY_RESERVED)
+			is_release_code = true;
+	}
+
+	ictx->release_code = is_release_code;
+
+	return keycode;
+}
+
+static u32 imon_mce_key_lookup(struct imon_context *ictx, u32 scancode)
+{
+	u32 keycode;
+
+#define MCE_KEY_MASK 0x7000
+#define MCE_TOGGLE_BIT 0x8000
+
+	/*
+	 * On some receivers, mce keys decode to 0x8000f04xx and 0x8000f84xx
+	 * (the toggle bit flipping between alternating key presses), while
+	 * on other receivers, we see 0x8000f74xx and 0x8000ff4xx. To keep
+	 * the table trim, we always or in the bits to look up 0x8000ff4xx,
+	 * but we can't or them into all codes, as some keys are decoded in
+	 * a different way w/o the same use of the toggle bit...
+	 */
+	if (scancode & 0x80000000)
+		scancode = scancode | MCE_KEY_MASK | MCE_TOGGLE_BIT;
+
+	ictx->rc_scancode = scancode;
+	keycode = rc_g_keycode_from_table(ictx->rdev, scancode);
+
+	/* not used in mce mode, but make sure we know its false */
+	ictx->release_code = false;
+
+	return keycode;
+}
+
+static u32 imon_panel_key_lookup(u64 code)
+{
+	int i;
+	u32 keycode = KEY_RESERVED;
+
+	for (i = 0; i < ARRAY_SIZE(imon_panel_key_table); i++) {
+		if (imon_panel_key_table[i].hw_code == (code | 0xffee)) {
+			keycode = imon_panel_key_table[i].keycode;
+			break;
+		}
+	}
+
+	return keycode;
+}
+
+static bool imon_mouse_event(struct imon_context *ictx,
+			     unsigned char *buf, int len)
+{
+	char rel_x = 0x00, rel_y = 0x00;
+	u8 right_shift = 1;
+	bool mouse_input = true;
+	int dir = 0;
+	unsigned long flags;
+
+	spin_lock_irqsave(&ictx->kc_lock, flags);
+
+	/* newer iMON device PAD or mouse button */
+	if (ictx->product != 0xffdc && (buf[0] & 0x01) && len == 5) {
+		rel_x = buf[2];
+		rel_y = buf[3];
+		right_shift = 1;
+	/* 0xffdc iMON PAD or mouse button input */
+	} else if (ictx->product == 0xffdc && (buf[0] & 0x40) &&
+			!((buf[1] & 0x01) || ((buf[1] >> 2) & 0x01))) {
+		rel_x = (buf[1] & 0x08) | (buf[1] & 0x10) >> 2 |
+			(buf[1] & 0x20) >> 4 | (buf[1] & 0x40) >> 6;
+		if (buf[0] & 0x02)
+			rel_x |= ~0x0f;
+		rel_x = rel_x + rel_x / 2;
+		rel_y = (buf[2] & 0x08) | (buf[2] & 0x10) >> 2 |
+			(buf[2] & 0x20) >> 4 | (buf[2] & 0x40) >> 6;
+		if (buf[0] & 0x01)
+			rel_y |= ~0x0f;
+		rel_y = rel_y + rel_y / 2;
+		right_shift = 2;
+	/* some ffdc devices decode mouse buttons differently... */
+	} else if (ictx->product == 0xffdc && (buf[0] == 0x68)) {
+		right_shift = 2;
+	/* ch+/- buttons, which we use for an emulated scroll wheel */
+	} else if (ictx->kc == KEY_CHANNELUP && (buf[2] & 0x40) != 0x40) {
+		dir = 1;
+	} else if (ictx->kc == KEY_CHANNELDOWN && (buf[2] & 0x40) != 0x40) {
+		dir = -1;
+	} else
+		mouse_input = false;
+
+	spin_unlock_irqrestore(&ictx->kc_lock, flags);
+
+	if (mouse_input) {
+		dev_dbg(ictx->dev, "sending mouse data via input subsystem\n");
+
+		if (dir) {
+			input_report_rel(ictx->idev, REL_WHEEL, dir);
+		} else if (rel_x || rel_y) {
+			input_report_rel(ictx->idev, REL_X, rel_x);
+			input_report_rel(ictx->idev, REL_Y, rel_y);
+		} else {
+			input_report_key(ictx->idev, BTN_LEFT, buf[1] & 0x1);
+			input_report_key(ictx->idev, BTN_RIGHT,
+					 buf[1] >> right_shift & 0x1);
+		}
+		input_sync(ictx->idev);
+		spin_lock_irqsave(&ictx->kc_lock, flags);
+		ictx->last_keycode = ictx->kc;
+		spin_unlock_irqrestore(&ictx->kc_lock, flags);
+	}
+
+	return mouse_input;
+}
+
+static void imon_touch_event(struct imon_context *ictx, unsigned char *buf)
+{
+	mod_timer(&ictx->ttimer, jiffies + TOUCH_TIMEOUT);
+	ictx->touch_x = (buf[0] << 4) | (buf[1] >> 4);
+	ictx->touch_y = 0xfff - ((buf[2] << 4) | (buf[1] & 0xf));
+	input_report_abs(ictx->touch, ABS_X, ictx->touch_x);
+	input_report_abs(ictx->touch, ABS_Y, ictx->touch_y);
+	input_report_key(ictx->touch, BTN_TOUCH, 0x01);
+	input_sync(ictx->touch);
+}
+
+static void imon_pad_to_keys(struct imon_context *ictx, unsigned char *buf)
+{
+	int dir = 0;
+	char rel_x = 0x00, rel_y = 0x00;
+	u16 timeout, threshold;
+	u32 scancode = KEY_RESERVED;
+	unsigned long flags;
+
+	/*
+	 * The imon directional pad functions more like a touchpad. Bytes 3 & 4
+	 * contain a position coordinate (x,y), with each component ranging
+	 * from -14 to 14. We want to down-sample this to only 4 discrete values
+	 * for up/down/left/right arrow keys. Also, when you get too close to
+	 * diagonals, it has a tendancy to jump back and forth, so lets try to
+	 * ignore when they get too close.
+	 */
+	if (ictx->product != 0xffdc) {
+		/* first, pad to 8 bytes so it conforms with everything else */
+		buf[5] = buf[6] = buf[7] = 0;
+		timeout = 500;	/* in msecs */
+		/* (2*threshold) x (2*threshold) square */
+		threshold = pad_thresh ? pad_thresh : 28;
+		rel_x = buf[2];
+		rel_y = buf[3];
+
+		if (ictx->rc_type == RC_TYPE_OTHER && pad_stabilize) {
+			if ((buf[1] == 0) && ((rel_x != 0) || (rel_y != 0))) {
+				dir = stabilize((int)rel_x, (int)rel_y,
+						timeout, threshold);
+				if (!dir) {
+					spin_lock_irqsave(&ictx->kc_lock,
+							  flags);
+					ictx->kc = KEY_UNKNOWN;
+					spin_unlock_irqrestore(&ictx->kc_lock,
+							       flags);
+					return;
+				}
+				buf[2] = dir & 0xFF;
+				buf[3] = (dir >> 8) & 0xFF;
+				scancode = be32_to_cpu(*((u32 *)buf));
+			}
+		} else {
+			/*
+			 * Hack alert: instead of using keycodes, we have
+			 * to use hard-coded scancodes here...
+			 */
+			if (abs(rel_y) > abs(rel_x)) {
+				buf[2] = (rel_y > 0) ? 0x7F : 0x80;
+				buf[3] = 0;
+				if (rel_y > 0)
+					scancode = 0x01007f00; /* KEY_DOWN */
+				else
+					scancode = 0x01008000; /* KEY_UP */
+			} else {
+				buf[2] = 0;
+				buf[3] = (rel_x > 0) ? 0x7F : 0x80;
+				if (rel_x > 0)
+					scancode = 0x0100007f; /* KEY_RIGHT */
+				else
+					scancode = 0x01000080; /* KEY_LEFT */
+			}
+		}
+
+	/*
+	 * Handle on-board decoded pad events for e.g. older VFD/iMON-Pad
+	 * device (15c2:ffdc). The remote generates various codes from
+	 * 0x68nnnnB7 to 0x6AnnnnB7, the left mouse button generates
+	 * 0x688301b7 and the right one 0x688481b7. All other keys generate
+	 * 0x2nnnnnnn. Position coordinate is encoded in buf[1] and buf[2] with
+	 * reversed endianess. Extract direction from buffer, rotate endianess,
+	 * adjust sign and feed the values into stabilize(). The resulting codes
+	 * will be 0x01008000, 0x01007F00, which match the newer devices.
+	 */
+	} else {
+		timeout = 10;	/* in msecs */
+		/* (2*threshold) x (2*threshold) square */
+		threshold = pad_thresh ? pad_thresh : 15;
+
+		/* buf[1] is x */
+		rel_x = (buf[1] & 0x08) | (buf[1] & 0x10) >> 2 |
+			(buf[1] & 0x20) >> 4 | (buf[1] & 0x40) >> 6;
+		if (buf[0] & 0x02)
+			rel_x |= ~0x10+1;
+		/* buf[2] is y */
+		rel_y = (buf[2] & 0x08) | (buf[2] & 0x10) >> 2 |
+			(buf[2] & 0x20) >> 4 | (buf[2] & 0x40) >> 6;
+		if (buf[0] & 0x01)
+			rel_y |= ~0x10+1;
+
+		buf[0] = 0x01;
+		buf[1] = buf[4] = buf[5] = buf[6] = buf[7] = 0;
+
+		if (ictx->rc_type == RC_TYPE_OTHER && pad_stabilize) {
+			dir = stabilize((int)rel_x, (int)rel_y,
+					timeout, threshold);
+			if (!dir) {
+				spin_lock_irqsave(&ictx->kc_lock, flags);
+				ictx->kc = KEY_UNKNOWN;
+				spin_unlock_irqrestore(&ictx->kc_lock, flags);
+				return;
+			}
+			buf[2] = dir & 0xFF;
+			buf[3] = (dir >> 8) & 0xFF;
+			scancode = be32_to_cpu(*((u32 *)buf));
+		} else {
+			/*
+			 * Hack alert: instead of using keycodes, we have
+			 * to use hard-coded scancodes here...
+			 */
+			if (abs(rel_y) > abs(rel_x)) {
+				buf[2] = (rel_y > 0) ? 0x7F : 0x80;
+				buf[3] = 0;
+				if (rel_y > 0)
+					scancode = 0x01007f00; /* KEY_DOWN */
+				else
+					scancode = 0x01008000; /* KEY_UP */
+			} else {
+				buf[2] = 0;
+				buf[3] = (rel_x > 0) ? 0x7F : 0x80;
+				if (rel_x > 0)
+					scancode = 0x0100007f; /* KEY_RIGHT */
+				else
+					scancode = 0x01000080; /* KEY_LEFT */
+			}
+		}
+	}
+
+	if (scancode) {
+		spin_lock_irqsave(&ictx->kc_lock, flags);
+		ictx->kc = imon_remote_key_lookup(ictx, scancode);
+		spin_unlock_irqrestore(&ictx->kc_lock, flags);
+	}
+}
+
+/**
+ * figure out if these is a press or a release. We don't actually
+ * care about repeats, as those will be auto-generated within the IR
+ * subsystem for repeating scancodes.
+ */
+static int imon_parse_press_type(struct imon_context *ictx,
+				 unsigned char *buf, u8 ktype)
+{
+	int press_type = 0;
+	unsigned long flags;
+
+	spin_lock_irqsave(&ictx->kc_lock, flags);
+
+	/* key release of 0x02XXXXXX key */
+	if (ictx->kc == KEY_RESERVED && buf[0] == 0x02 && buf[3] == 0x00)
+		ictx->kc = ictx->last_keycode;
+
+	/* mouse button release on (some) 0xffdc devices */
+	else if (ictx->kc == KEY_RESERVED && buf[0] == 0x68 && buf[1] == 0x82 &&
+		 buf[2] == 0x81 && buf[3] == 0xb7)
+		ictx->kc = ictx->last_keycode;
+
+	/* mouse button release on (some other) 0xffdc devices */
+	else if (ictx->kc == KEY_RESERVED && buf[0] == 0x01 && buf[1] == 0x00 &&
+		 buf[2] == 0x81 && buf[3] == 0xb7)
+		ictx->kc = ictx->last_keycode;
+
+	/* mce-specific button handling, no keyup events */
+	else if (ktype == IMON_KEY_MCE) {
+		ictx->rc_toggle = buf[2];
+		press_type = 1;
+
+	/* incoherent or irrelevant data */
+	} else if (ictx->kc == KEY_RESERVED)
+		press_type = -EINVAL;
+
+	/* key release of 0xXXXXXXb7 key */
+	else if (ictx->release_code)
+		press_type = 0;
+
+	/* this is a button press */
+	else
+		press_type = 1;
+
+	spin_unlock_irqrestore(&ictx->kc_lock, flags);
+
+	return press_type;
+}
+
+/**
+ * Process the incoming packet
+ */
+static void imon_incoming_packet(struct imon_context *ictx,
+				 struct urb *urb, int intf)
+{
+	int len = urb->actual_length;
+	unsigned char *buf = urb->transfer_buffer;
+	struct device *dev = ictx->dev;
+	unsigned long flags;
+	u32 kc;
+	bool norelease = false;
+	int i;
+	u64 scancode;
+	int press_type = 0;
+	int msec;
+	struct timeval t;
+	static struct timeval prev_time = { 0, 0 };
+	u8 ktype;
+
+	/* filter out junk data on the older 0xffdc imon devices */
+	if ((buf[0] == 0xff) && (buf[1] == 0xff) && (buf[2] == 0xff))
+		return;
+
+	/* Figure out what key was pressed */
+	if (len == 8 && buf[7] == 0xee) {
+		scancode = be64_to_cpu(*((u64 *)buf));
+		ktype = IMON_KEY_PANEL;
+		kc = imon_panel_key_lookup(scancode);
+	} else {
+		scancode = be32_to_cpu(*((u32 *)buf));
+		if (ictx->rc_type == RC_TYPE_RC6) {
+			ktype = IMON_KEY_IMON;
+			if (buf[0] == 0x80)
+				ktype = IMON_KEY_MCE;
+			kc = imon_mce_key_lookup(ictx, scancode);
+		} else {
+			ktype = IMON_KEY_IMON;
+			kc = imon_remote_key_lookup(ictx, scancode);
+		}
+	}
+
+	spin_lock_irqsave(&ictx->kc_lock, flags);
+	/* keyboard/mouse mode toggle button */
+	if (kc == KEY_KEYBOARD && !ictx->release_code) {
+		ictx->last_keycode = kc;
+		if (!nomouse) {
+			ictx->pad_mouse = ~(ictx->pad_mouse) & 0x1;
+			dev_dbg(dev, "toggling to %s mode\n",
+				ictx->pad_mouse ? "mouse" : "keyboard");
+			spin_unlock_irqrestore(&ictx->kc_lock, flags);
+			return;
+		} else {
+			ictx->pad_mouse = false;
+			dev_dbg(dev, "mouse mode disabled, passing key value\n");
+		}
+	}
+
+	ictx->kc = kc;
+	spin_unlock_irqrestore(&ictx->kc_lock, flags);
+
+	/* send touchscreen events through input subsystem if touchpad data */
+	if (ictx->display_type == IMON_DISPLAY_TYPE_VGA && len == 8 &&
+	    buf[7] == 0x86) {
+		imon_touch_event(ictx, buf);
+		return;
+
+	/* look for mouse events with pad in mouse mode */
+	} else if (ictx->pad_mouse) {
+		if (imon_mouse_event(ictx, buf, len))
+			return;
+	}
+
+	/* Now for some special handling to convert pad input to arrow keys */
+	if (((len == 5) && (buf[0] == 0x01) && (buf[4] == 0x00)) ||
+	    ((len == 8) && (buf[0] & 0x40) &&
+	     !(buf[1] & 0x1 || buf[1] >> 2 & 0x1))) {
+		len = 8;
+		imon_pad_to_keys(ictx, buf);
+		norelease = true;
+	}
+
+	if (debug) {
+		printk(KERN_INFO "intf%d decoded packet: ", intf);
+		for (i = 0; i < len; ++i)
+			printk("%02x ", buf[i]);
+		printk("\n");
+	}
+
+	press_type = imon_parse_press_type(ictx, buf, ktype);
+	if (press_type < 0)
+		goto not_input_data;
+
+	spin_lock_irqsave(&ictx->kc_lock, flags);
+	if (ictx->kc == KEY_UNKNOWN)
+		goto unknown_key;
+	spin_unlock_irqrestore(&ictx->kc_lock, flags);
+
+	if (ktype != IMON_KEY_PANEL) {
+		if (press_type == 0)
+			rc_keyup(ictx->rdev);
+		else {
+			rc_keydown(ictx->rdev, ictx->rc_scancode, ictx->rc_toggle);
+			spin_lock_irqsave(&ictx->kc_lock, flags);
+			ictx->last_keycode = ictx->kc;
+			spin_unlock_irqrestore(&ictx->kc_lock, flags);
+		}
+		return;
+	}
+
+	/* Only panel type events left to process now */
+	spin_lock_irqsave(&ictx->kc_lock, flags);
+
+	/* KEY_MUTE repeats from knob need to be suppressed */
+	if (ictx->kc == KEY_MUTE && ictx->kc == ictx->last_keycode) {
+		do_gettimeofday(&t);
+		msec = tv2int(&t, &prev_time);
+		prev_time = t;
+		if (msec < ictx->idev->rep[REP_DELAY]) {
+			spin_unlock_irqrestore(&ictx->kc_lock, flags);
+			return;
+		}
+	}
+	kc = ictx->kc;
+
+	spin_unlock_irqrestore(&ictx->kc_lock, flags);
+
+	input_report_key(ictx->idev, kc, press_type);
+	input_sync(ictx->idev);
+
+	/* panel keys don't generate a release */
+	input_report_key(ictx->idev, kc, 0);
+	input_sync(ictx->idev);
+
+	ictx->last_keycode = kc;
+
+	return;
+
+unknown_key:
+	spin_unlock_irqrestore(&ictx->kc_lock, flags);
+	dev_info(dev, "%s: unknown keypress, code 0x%llx\n", __func__,
+		 (long long)scancode);
+	return;
+
+not_input_data:
+	if (len != 8) {
+		dev_warn(dev, "imon %s: invalid incoming packet "
+			 "size (len = %d, intf%d)\n", __func__, len, intf);
+		return;
+	}
+
+	/* iMON 2.4G associate frame */
+	if (buf[0] == 0x00 &&
+	    buf[2] == 0xFF &&				/* REFID */
+	    buf[3] == 0xFF &&
+	    buf[4] == 0xFF &&
+	    buf[5] == 0xFF &&				/* iMON 2.4G */
+	   ((buf[6] == 0x4E && buf[7] == 0xDF) ||	/* LT */
+	    (buf[6] == 0x5E && buf[7] == 0xDF))) {	/* DT */
+		dev_warn(dev, "%s: remote associated refid=%02X\n",
+			 __func__, buf[1]);
+		ictx->rf_isassociating = false;
+	}
+}
+
+/**
+ * Callback function for USB core API: receive data
+ */
+static void usb_rx_callback_intf0(struct urb *urb)
+{
+	struct imon_context *ictx;
+	int intfnum = 0;
+
+	if (!urb)
+		return;
+
+	ictx = (struct imon_context *)urb->context;
+	if (!ictx)
+		return;
+
+	switch (urb->status) {
+	case -ENOENT:		/* usbcore unlink successful! */
+		return;
+
+	case -ESHUTDOWN:	/* transport endpoint was shut down */
+		break;
+
+	case 0:
+		imon_incoming_packet(ictx, urb, intfnum);
+		break;
+
+	default:
+		dev_warn(ictx->dev, "imon %s: status(%d): ignored\n",
+			 __func__, urb->status);
+		break;
+	}
+
+	usb_submit_urb(ictx->rx_urb_intf0, GFP_ATOMIC);
+}
+
+static void usb_rx_callback_intf1(struct urb *urb)
+{
+	struct imon_context *ictx;
+	int intfnum = 1;
+
+	if (!urb)
+		return;
+
+	ictx = (struct imon_context *)urb->context;
+	if (!ictx)
+		return;
+
+	switch (urb->status) {
+	case -ENOENT:		/* usbcore unlink successful! */
+		return;
+
+	case -ESHUTDOWN:	/* transport endpoint was shut down */
+		break;
+
+	case 0:
+		imon_incoming_packet(ictx, urb, intfnum);
+		break;
+
+	default:
+		dev_warn(ictx->dev, "imon %s: status(%d): ignored\n",
+			 __func__, urb->status);
+		break;
+	}
+
+	usb_submit_urb(ictx->rx_urb_intf1, GFP_ATOMIC);
+}
+
+/*
+ * The 0x15c2:0xffdc device ID was used for umpteen different imon
+ * devices, and all of them constantly spew interrupts, even when there
+ * is no actual data to report. However, byte 6 of this buffer looks like
+ * its unique across device variants, so we're trying to key off that to
+ * figure out which display type (if any) and what IR protocol the device
+ * actually supports. These devices have their IR protocol hard-coded into
+ * their firmware, they can't be changed on the fly like the newer hardware.
+ */
+static void imon_get_ffdc_type(struct imon_context *ictx)
+{
+	u8 ffdc_cfg_byte = ictx->usb_rx_buf[6];
+	u8 detected_display_type = IMON_DISPLAY_TYPE_NONE;
+	u64 allowed_protos = RC_TYPE_OTHER;
+
+	switch (ffdc_cfg_byte) {
+	/* iMON Knob, no display, iMON IR + vol knob */
+	case 0x21:
+		dev_info(ictx->dev, "0xffdc iMON Knob, iMON IR");
+		ictx->display_supported = false;
+		break;
+	/* iMON 2.4G LT (usb stick), no display, iMON RF */
+	case 0x4e:
+		dev_info(ictx->dev, "0xffdc iMON 2.4G LT, iMON RF");
+		ictx->display_supported = false;
+		ictx->rf_device = true;
+		break;
+	/* iMON VFD, no IR (does have vol knob tho) */
+	case 0x35:
+		dev_info(ictx->dev, "0xffdc iMON VFD + knob, no IR");
+		detected_display_type = IMON_DISPLAY_TYPE_VFD;
+		break;
+	/* iMON VFD, iMON IR */
+	case 0x24:
+	case 0x85:
+		dev_info(ictx->dev, "0xffdc iMON VFD, iMON IR");
+		detected_display_type = IMON_DISPLAY_TYPE_VFD;
+		break;
+	/* iMON VFD, MCE IR */
+	case 0x9e:
+		dev_info(ictx->dev, "0xffdc iMON VFD, MCE IR");
+		detected_display_type = IMON_DISPLAY_TYPE_VFD;
+		allowed_protos = RC_TYPE_RC6;
+		break;
+	/* iMON LCD, MCE IR */
+	case 0x9f:
+		dev_info(ictx->dev, "0xffdc iMON LCD, MCE IR");
+		detected_display_type = IMON_DISPLAY_TYPE_LCD;
+		allowed_protos = RC_TYPE_RC6;
+		break;
+	default:
+		dev_info(ictx->dev, "Unknown 0xffdc device, "
+			 "defaulting to VFD and iMON IR");
+		detected_display_type = IMON_DISPLAY_TYPE_VFD;
+		break;
+	}
+
+	printk(KERN_CONT " (id 0x%02x)\n", ffdc_cfg_byte);
+
+	ictx->display_type = detected_display_type;
+	ictx->rc_type = allowed_protos;
+}
+
+static void imon_set_display_type(struct imon_context *ictx)
+{
+	u8 configured_display_type = IMON_DISPLAY_TYPE_VFD;
+
+	/*
+	 * Try to auto-detect the type of display if the user hasn't set
+	 * it by hand via the display_type modparam. Default is VFD.
+	 */
+
+	if (display_type == IMON_DISPLAY_TYPE_AUTO) {
+		switch (ictx->product) {
+		case 0xffdc:
+			/* set in imon_get_ffdc_type() */
+			configured_display_type = ictx->display_type;
+			break;
+		case 0x0034:
+		case 0x0035:
+			configured_display_type = IMON_DISPLAY_TYPE_VGA;
+			break;
+		case 0x0038:
+		case 0x0039:
+		case 0x0045:
+			configured_display_type = IMON_DISPLAY_TYPE_LCD;
+			break;
+		case 0x003c:
+		case 0x0041:
+		case 0x0042:
+		case 0x0043:
+			configured_display_type = IMON_DISPLAY_TYPE_NONE;
+			ictx->display_supported = false;
+			break;
+		case 0x0036:
+		case 0x0044:
+		default:
+			configured_display_type = IMON_DISPLAY_TYPE_VFD;
+			break;
+		}
+	} else {
+		configured_display_type = display_type;
+		if (display_type == IMON_DISPLAY_TYPE_NONE)
+			ictx->display_supported = false;
+		else
+			ictx->display_supported = true;
+		dev_info(ictx->dev, "%s: overriding display type to %d via "
+			 "modparam\n", __func__, display_type);
+	}
+
+	ictx->display_type = configured_display_type;
+}
+
+static struct rc_dev *imon_init_rdev(struct imon_context *ictx)
+{
+	struct rc_dev *rdev;
+	int ret;
+	const unsigned char fp_packet[] = { 0x40, 0x00, 0x00, 0x00,
+					    0x00, 0x00, 0x00, 0x88 };
+
+	rdev = rc_allocate_device();
+	if (!rdev) {
+		dev_err(ictx->dev, "remote control dev allocation failed\n");
+		goto out;
+	}
+
+	snprintf(ictx->name_rdev, sizeof(ictx->name_rdev),
+		 "iMON Remote (%04x:%04x)", ictx->vendor, ictx->product);
+	usb_make_path(ictx->usbdev_intf0, ictx->phys_rdev,
+		      sizeof(ictx->phys_rdev));
+	strlcat(ictx->phys_rdev, "/input0", sizeof(ictx->phys_rdev));
+
+	rdev->input_name = ictx->name_rdev;
+	rdev->input_phys = ictx->phys_rdev;
+	usb_to_input_id(ictx->usbdev_intf0, &rdev->input_id);
+	rdev->dev.parent = ictx->dev;
+
+	rdev->priv = ictx;
+	rdev->driver_type = RC_DRIVER_SCANCODE;
+	rdev->allowed_protos = RC_TYPE_OTHER | RC_TYPE_RC6; /* iMON PAD or MCE */
+	rdev->change_protocol = imon_ir_change_protocol;
+	rdev->driver_name = MOD_NAME;
+
+	/* Enable front-panel buttons and/or knobs */
+	memcpy(ictx->usb_tx_buf, &fp_packet, sizeof(fp_packet));
+	ret = send_packet(ictx);
+	/* Not fatal, but warn about it */
+	if (ret)
+		dev_info(ictx->dev, "panel buttons/knobs setup failed\n");
+
+	if (ictx->product == 0xffdc) {
+		imon_get_ffdc_type(ictx);
+		rdev->allowed_protos = ictx->rc_type;
+	}
+
+	imon_set_display_type(ictx);
+
+	if (ictx->rc_type == RC_TYPE_RC6)
+		rdev->map_name = RC_MAP_IMON_MCE;
+	else
+		rdev->map_name = RC_MAP_IMON_PAD;
+
+	ret = rc_register_device(rdev);
+	if (ret < 0) {
+		dev_err(ictx->dev, "remote input dev register failed\n");
+		goto out;
+	}
+
+	return rdev;
+
+out:
+	rc_free_device(rdev);
+	return NULL;
+}
+
+static struct input_dev *imon_init_idev(struct imon_context *ictx)
+{
+	struct input_dev *idev;
+	int ret, i;
+
+	idev = input_allocate_device();
+	if (!idev) {
+		dev_err(ictx->dev, "input dev allocation failed\n");
+		goto out;
+	}
+
+	snprintf(ictx->name_idev, sizeof(ictx->name_idev),
+		 "iMON Panel, Knob and Mouse(%04x:%04x)",
+		 ictx->vendor, ictx->product);
+	idev->name = ictx->name_idev;
+
+	usb_make_path(ictx->usbdev_intf0, ictx->phys_idev,
+		      sizeof(ictx->phys_idev));
+	strlcat(ictx->phys_idev, "/input1", sizeof(ictx->phys_idev));
+	idev->phys = ictx->phys_idev;
+
+	idev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP) | BIT_MASK(EV_REL);
+
+	idev->keybit[BIT_WORD(BTN_MOUSE)] =
+		BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_RIGHT);
+	idev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y) |
+		BIT_MASK(REL_WHEEL);
+
+	/* panel and/or knob code support */
+	for (i = 0; i < ARRAY_SIZE(imon_panel_key_table); i++) {
+		u32 kc = imon_panel_key_table[i].keycode;
+		__set_bit(kc, idev->keybit);
+	}
+
+	usb_to_input_id(ictx->usbdev_intf0, &idev->id);
+	idev->dev.parent = ictx->dev;
+	input_set_drvdata(idev, ictx);
+
+	ret = input_register_device(idev);
+	if (ret < 0) {
+		dev_err(ictx->dev, "input dev register failed\n");
+		goto out;
+	}
+
+	return idev;
+
+out:
+	input_free_device(idev);
+	return NULL;
+}
+
+static struct input_dev *imon_init_touch(struct imon_context *ictx)
+{
+	struct input_dev *touch;
+	int ret;
+
+	touch = input_allocate_device();
+	if (!touch) {
+		dev_err(ictx->dev, "touchscreen input dev allocation failed\n");
+		goto touch_alloc_failed;
+	}
+
+	snprintf(ictx->name_touch, sizeof(ictx->name_touch),
+		 "iMON USB Touchscreen (%04x:%04x)",
+		 ictx->vendor, ictx->product);
+	touch->name = ictx->name_touch;
+
+	usb_make_path(ictx->usbdev_intf1, ictx->phys_touch,
+		      sizeof(ictx->phys_touch));
+	strlcat(ictx->phys_touch, "/input2", sizeof(ictx->phys_touch));
+	touch->phys = ictx->phys_touch;
+
+	touch->evbit[0] =
+		BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+	touch->keybit[BIT_WORD(BTN_TOUCH)] =
+		BIT_MASK(BTN_TOUCH);
+	input_set_abs_params(touch, ABS_X,
+			     0x00, 0xfff, 0, 0);
+	input_set_abs_params(touch, ABS_Y,
+			     0x00, 0xfff, 0, 0);
+
+	input_set_drvdata(touch, ictx);
+
+	usb_to_input_id(ictx->usbdev_intf1, &touch->id);
+	touch->dev.parent = ictx->dev;
+	ret = input_register_device(touch);
+	if (ret <  0) {
+		dev_info(ictx->dev, "touchscreen input dev register failed\n");
+		goto touch_register_failed;
+	}
+
+	return touch;
+
+touch_register_failed:
+	input_free_device(ictx->touch);
+
+touch_alloc_failed:
+	return NULL;
+}
+
+static bool imon_find_endpoints(struct imon_context *ictx,
+				struct usb_host_interface *iface_desc)
+{
+	struct usb_endpoint_descriptor *ep;
+	struct usb_endpoint_descriptor *rx_endpoint = NULL;
+	struct usb_endpoint_descriptor *tx_endpoint = NULL;
+	int ifnum = iface_desc->desc.bInterfaceNumber;
+	int num_endpts = iface_desc->desc.bNumEndpoints;
+	int i, ep_dir, ep_type;
+	bool ir_ep_found = false;
+	bool display_ep_found = false;
+	bool tx_control = false;
+
+	/*
+	 * Scan the endpoint list and set:
+	 *	first input endpoint = IR endpoint
+	 *	first output endpoint = display endpoint
+	 */
+	for (i = 0; i < num_endpts && !(ir_ep_found && display_ep_found); ++i) {
+		ep = &iface_desc->endpoint[i].desc;
+		ep_dir = ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK;
+		ep_type = ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
+
+		if (!ir_ep_found && ep_dir == USB_DIR_IN &&
+		    ep_type == USB_ENDPOINT_XFER_INT) {
+
+			rx_endpoint = ep;
+			ir_ep_found = true;
+			dev_dbg(ictx->dev, "%s: found IR endpoint\n", __func__);
+
+		} else if (!display_ep_found && ep_dir == USB_DIR_OUT &&
+			   ep_type == USB_ENDPOINT_XFER_INT) {
+			tx_endpoint = ep;
+			display_ep_found = true;
+			dev_dbg(ictx->dev, "%s: found display endpoint\n", __func__);
+		}
+	}
+
+	if (ifnum == 0) {
+		ictx->rx_endpoint_intf0 = rx_endpoint;
+		/*
+		 * tx is used to send characters to lcd/vfd, associate RF
+		 * remotes, set IR protocol, and maybe more...
+		 */
+		ictx->tx_endpoint = tx_endpoint;
+	} else {
+		ictx->rx_endpoint_intf1 = rx_endpoint;
+	}
+
+	/*
+	 * If we didn't find a display endpoint, this is probably one of the
+	 * newer iMON devices that use control urb instead of interrupt
+	 */
+	if (!display_ep_found) {
+		tx_control = true;
+		display_ep_found = true;
+		dev_dbg(ictx->dev, "%s: device uses control endpoint, not "
+			"interface OUT endpoint\n", __func__);
+	}
+
+	/*
+	 * Some iMON receivers have no display. Unfortunately, it seems
+	 * that SoundGraph recycles device IDs between devices both with
+	 * and without... :\
+	 */
+	if (ictx->display_type == IMON_DISPLAY_TYPE_NONE) {
+		display_ep_found = false;
+		dev_dbg(ictx->dev, "%s: device has no display\n", __func__);
+	}
+
+	/*
+	 * iMON Touch devices have a VGA touchscreen, but no "display", as
+	 * that refers to e.g. /dev/lcd0 (a character device LCD or VFD).
+	 */
+	if (ictx->display_type == IMON_DISPLAY_TYPE_VGA) {
+		display_ep_found = false;
+		dev_dbg(ictx->dev, "%s: iMON Touch device found\n", __func__);
+	}
+
+	/* Input endpoint is mandatory */
+	if (!ir_ep_found)
+		pr_err("no valid input (IR) endpoint found\n");
+
+	ictx->tx_control = tx_control;
+
+	if (display_ep_found)
+		ictx->display_supported = true;
+
+	return ir_ep_found;
+
+}
+
+static struct imon_context *imon_init_intf0(struct usb_interface *intf)
+{
+	struct imon_context *ictx;
+	struct urb *rx_urb;
+	struct urb *tx_urb;
+	struct device *dev = &intf->dev;
+	struct usb_host_interface *iface_desc;
+	int ret = -ENOMEM;
+
+	ictx = kzalloc(sizeof(struct imon_context), GFP_KERNEL);
+	if (!ictx) {
+		dev_err(dev, "%s: kzalloc failed for context", __func__);
+		goto exit;
+	}
+	rx_urb = usb_alloc_urb(0, GFP_KERNEL);
+	if (!rx_urb) {
+		dev_err(dev, "%s: usb_alloc_urb failed for IR urb", __func__);
+		goto rx_urb_alloc_failed;
+	}
+	tx_urb = usb_alloc_urb(0, GFP_KERNEL);
+	if (!tx_urb) {
+		dev_err(dev, "%s: usb_alloc_urb failed for display urb",
+			__func__);
+		goto tx_urb_alloc_failed;
+	}
+
+	mutex_init(&ictx->lock);
+	spin_lock_init(&ictx->kc_lock);
+
+	mutex_lock(&ictx->lock);
+
+	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;
+
+	ictx->vendor  = le16_to_cpu(ictx->usbdev_intf0->descriptor.idVendor);
+	ictx->product = le16_to_cpu(ictx->usbdev_intf0->descriptor.idProduct);
+
+	ret = -ENODEV;
+	iface_desc = intf->cur_altsetting;
+	if (!imon_find_endpoints(ictx, iface_desc)) {
+		goto find_endpoint_failed;
+	}
+
+	usb_fill_int_urb(ictx->rx_urb_intf0, ictx->usbdev_intf0,
+		usb_rcvintpipe(ictx->usbdev_intf0,
+			ictx->rx_endpoint_intf0->bEndpointAddress),
+		ictx->usb_rx_buf, sizeof(ictx->usb_rx_buf),
+		usb_rx_callback_intf0, ictx,
+		ictx->rx_endpoint_intf0->bInterval);
+
+	ret = usb_submit_urb(ictx->rx_urb_intf0, GFP_KERNEL);
+	if (ret) {
+		pr_err("usb_submit_urb failed for intf0 (%d)\n", ret);
+		goto urb_submit_failed;
+	}
+
+	ictx->idev = imon_init_idev(ictx);
+	if (!ictx->idev) {
+		dev_err(dev, "%s: input device setup failed\n", __func__);
+		goto idev_setup_failed;
+	}
+
+	ictx->rdev = imon_init_rdev(ictx);
+	if (!ictx->rdev) {
+		dev_err(dev, "%s: rc device setup failed\n", __func__);
+		goto rdev_setup_failed;
+	}
+
+	return ictx;
+
+rdev_setup_failed:
+	input_unregister_device(ictx->idev);
+idev_setup_failed:
+	usb_kill_urb(ictx->rx_urb_intf0);
+urb_submit_failed:
+find_endpoint_failed:
+	mutex_unlock(&ictx->lock);
+	usb_free_urb(tx_urb);
+tx_urb_alloc_failed:
+	usb_free_urb(rx_urb);
+rx_urb_alloc_failed:
+	kfree(ictx);
+exit:
+	dev_err(dev, "unable to initialize intf0, err %d\n", ret);
+
+	return NULL;
+}
+
+static struct imon_context *imon_init_intf1(struct usb_interface *intf,
+					    struct imon_context *ictx)
+{
+	struct urb *rx_urb;
+	struct usb_host_interface *iface_desc;
+	int ret = -ENOMEM;
+
+	rx_urb = usb_alloc_urb(0, GFP_KERNEL);
+	if (!rx_urb) {
+		pr_err("usb_alloc_urb failed for IR urb\n");
+		goto rx_urb_alloc_failed;
+	}
+
+	mutex_lock(&ictx->lock);
+
+	if (ictx->display_type == IMON_DISPLAY_TYPE_VGA) {
+		init_timer(&ictx->ttimer);
+		ictx->ttimer.data = (unsigned long)ictx;
+		ictx->ttimer.function = imon_touch_display_timeout;
+	}
+
+	ictx->usbdev_intf1 = usb_get_dev(interface_to_usbdev(intf));
+	ictx->dev_present_intf1 = true;
+	ictx->rx_urb_intf1 = rx_urb;
+
+	ret = -ENODEV;
+	iface_desc = intf->cur_altsetting;
+	if (!imon_find_endpoints(ictx, iface_desc))
+		goto find_endpoint_failed;
+
+	if (ictx->display_type == IMON_DISPLAY_TYPE_VGA) {
+		ictx->touch = imon_init_touch(ictx);
+		if (!ictx->touch)
+			goto touch_setup_failed;
+	} else
+		ictx->touch = NULL;
+
+	usb_fill_int_urb(ictx->rx_urb_intf1, ictx->usbdev_intf1,
+		usb_rcvintpipe(ictx->usbdev_intf1,
+			ictx->rx_endpoint_intf1->bEndpointAddress),
+		ictx->usb_rx_buf, sizeof(ictx->usb_rx_buf),
+		usb_rx_callback_intf1, ictx,
+		ictx->rx_endpoint_intf1->bInterval);
+
+	ret = usb_submit_urb(ictx->rx_urb_intf1, GFP_KERNEL);
+
+	if (ret) {
+		pr_err("usb_submit_urb failed for intf1 (%d)\n", ret);
+		goto urb_submit_failed;
+	}
+
+	return ictx;
+
+urb_submit_failed:
+	if (ictx->touch)
+		input_unregister_device(ictx->touch);
+touch_setup_failed:
+find_endpoint_failed:
+	mutex_unlock(&ictx->lock);
+	usb_free_urb(rx_urb);
+rx_urb_alloc_failed:
+	dev_err(ictx->dev, "unable to initialize intf0, err %d\n", ret);
+
+	return NULL;
+}
+
+static void imon_init_display(struct imon_context *ictx,
+			      struct usb_interface *intf)
+{
+	int ret;
+
+	dev_dbg(ictx->dev, "Registering iMON display with sysfs\n");
+
+	/* set up sysfs entry for built-in clock */
+	ret = sysfs_create_group(&intf->dev.kobj, &imon_display_attr_group);
+	if (ret)
+		dev_err(ictx->dev, "Could not create display sysfs "
+			"entries(%d)", ret);
+
+	if (ictx->display_type == IMON_DISPLAY_TYPE_LCD)
+		ret = usb_register_dev(intf, &imon_lcd_class);
+	else
+		ret = usb_register_dev(intf, &imon_vfd_class);
+	if (ret)
+		/* Not a fatal error, so ignore */
+		dev_info(ictx->dev, "could not get a minor number for "
+			 "display\n");
+
+}
+
+/**
+ * Callback function for USB core API: Probe
+ */
+static int __devinit imon_probe(struct usb_interface *interface,
+				const struct usb_device_id *id)
+{
+	struct usb_device *usbdev = NULL;
+	struct usb_host_interface *iface_desc = NULL;
+	struct usb_interface *first_if;
+	struct device *dev = &interface->dev;
+	int ifnum, code_length, sysfs_err;
+	int ret = 0;
+	struct imon_context *ictx = NULL;
+	struct imon_context *first_if_ctx = NULL;
+	u16 vendor, product;
+
+	code_length = BUF_CHUNK_SIZE * 8;
+
+	usbdev     = usb_get_dev(interface_to_usbdev(interface));
+	iface_desc = interface->cur_altsetting;
+	ifnum      = iface_desc->desc.bInterfaceNumber;
+	vendor     = le16_to_cpu(usbdev->descriptor.idVendor);
+	product    = le16_to_cpu(usbdev->descriptor.idProduct);
+
+	dev_dbg(dev, "%s: found iMON device (%04x:%04x, intf%d)\n",
+		__func__, vendor, product, ifnum);
+
+	/* prevent races probing devices w/multiple interfaces */
+	mutex_lock(&driver_lock);
+
+	first_if = usb_ifnum_to_if(usbdev, 0);
+	first_if_ctx = usb_get_intfdata(first_if);
+
+	if (ifnum == 0) {
+		ictx = imon_init_intf0(interface);
+		if (!ictx) {
+			pr_err("failed to initialize context!\n");
+			ret = -ENODEV;
+			goto fail;
+		}
+
+	} else {
+	/* this is the secondary interface on the device */
+		ictx = imon_init_intf1(interface, first_if_ctx);
+		if (!ictx) {
+			pr_err("failed to attach to context!\n");
+			ret = -ENODEV;
+			goto fail;
+		}
+
+	}
+
+	usb_set_intfdata(interface, ictx);
+
+	if (ifnum == 0) {
+		if (product == 0xffdc && ictx->rf_device) {
+			sysfs_err = sysfs_create_group(&interface->dev.kobj,
+						       &imon_rf_attr_group);
+			if (sysfs_err)
+				pr_err("Could not create RF sysfs entries(%d)\n",
+				       sysfs_err);
+		}
+
+		if (ictx->display_supported)
+			imon_init_display(ictx, interface);
+	}
+
+	dev_info(dev, "iMON device (%04x:%04x, intf%d) on "
+		 "usb<%d:%d> initialized\n", vendor, product, ifnum,
+		 usbdev->bus->busnum, usbdev->devnum);
+
+	mutex_unlock(&ictx->lock);
+	mutex_unlock(&driver_lock);
+
+	return 0;
+
+fail:
+	mutex_unlock(&driver_lock);
+	dev_err(dev, "unable to register, err %d\n", ret);
+
+	return ret;
+}
+
+/**
+ * Callback function for USB core API: disconnect
+ */
+static void __devexit imon_disconnect(struct usb_interface *interface)
+{
+	struct imon_context *ictx;
+	struct device *dev;
+	int ifnum;
+
+	/* prevent races with multi-interface device probing and display_open */
+	mutex_lock(&driver_lock);
+
+	ictx = usb_get_intfdata(interface);
+	dev = ictx->dev;
+	ifnum = interface->cur_altsetting->desc.bInterfaceNumber;
+
+	mutex_lock(&ictx->lock);
+
+	/*
+	 * sysfs_remove_group is safe to call even if sysfs_create_group
+	 * hasn't been called
+	 */
+	sysfs_remove_group(&interface->dev.kobj, &imon_display_attr_group);
+	sysfs_remove_group(&interface->dev.kobj, &imon_rf_attr_group);
+
+	usb_set_intfdata(interface, NULL);
+
+	/* Abort ongoing write */
+	if (ictx->tx.busy) {
+		usb_kill_urb(ictx->tx_urb);
+		complete_all(&ictx->tx.finished);
+	}
+
+	if (ifnum == 0) {
+		ictx->dev_present_intf0 = false;
+		usb_kill_urb(ictx->rx_urb_intf0);
+		input_unregister_device(ictx->idev);
+		rc_unregister_device(ictx->rdev);
+		if (ictx->display_supported) {
+			if (ictx->display_type == IMON_DISPLAY_TYPE_LCD)
+				usb_deregister_dev(interface, &imon_lcd_class);
+			else
+				usb_deregister_dev(interface, &imon_vfd_class);
+		}
+	} else {
+		ictx->dev_present_intf1 = false;
+		usb_kill_urb(ictx->rx_urb_intf1);
+		if (ictx->display_type == IMON_DISPLAY_TYPE_VGA)
+			input_unregister_device(ictx->touch);
+	}
+
+	if (!ictx->dev_present_intf0 && !ictx->dev_present_intf1) {
+		if (ictx->display_type == IMON_DISPLAY_TYPE_VGA)
+			del_timer_sync(&ictx->ttimer);
+		mutex_unlock(&ictx->lock);
+		if (!ictx->display_isopen)
+			free_imon_context(ictx);
+	} else
+		mutex_unlock(&ictx->lock);
+
+	mutex_unlock(&driver_lock);
+
+	dev_dbg(dev, "%s: iMON device (intf%d) disconnected\n",
+		__func__, ifnum);
+}
+
+static int imon_suspend(struct usb_interface *intf, pm_message_t message)
+{
+	struct imon_context *ictx = usb_get_intfdata(intf);
+	int ifnum = intf->cur_altsetting->desc.bInterfaceNumber;
+
+	if (ifnum == 0)
+		usb_kill_urb(ictx->rx_urb_intf0);
+	else
+		usb_kill_urb(ictx->rx_urb_intf1);
+
+	return 0;
+}
+
+static int imon_resume(struct usb_interface *intf)
+{
+	int rc = 0;
+	struct imon_context *ictx = usb_get_intfdata(intf);
+	int ifnum = intf->cur_altsetting->desc.bInterfaceNumber;
+
+	if (ifnum == 0) {
+		usb_fill_int_urb(ictx->rx_urb_intf0, ictx->usbdev_intf0,
+			usb_rcvintpipe(ictx->usbdev_intf0,
+				ictx->rx_endpoint_intf0->bEndpointAddress),
+			ictx->usb_rx_buf, sizeof(ictx->usb_rx_buf),
+			usb_rx_callback_intf0, ictx,
+			ictx->rx_endpoint_intf0->bInterval);
+
+		rc = usb_submit_urb(ictx->rx_urb_intf0, GFP_ATOMIC);
+
+	} else {
+		usb_fill_int_urb(ictx->rx_urb_intf1, ictx->usbdev_intf1,
+			usb_rcvintpipe(ictx->usbdev_intf1,
+				ictx->rx_endpoint_intf1->bEndpointAddress),
+			ictx->usb_rx_buf, sizeof(ictx->usb_rx_buf),
+			usb_rx_callback_intf1, ictx,
+			ictx->rx_endpoint_intf1->bInterval);
+
+		rc = usb_submit_urb(ictx->rx_urb_intf1, GFP_ATOMIC);
+	}
+
+	return rc;
+}
+
+static int __init imon_init(void)
+{
+	int rc;
+
+	rc = usb_register(&imon_driver);
+	if (rc) {
+		pr_err("usb register failed(%d)\n", rc);
+		rc = -ENODEV;
+	}
+
+	return rc;
+}
+
+static void __exit imon_exit(void)
+{
+	usb_deregister(&imon_driver);
+}
+
+module_init(imon_init);
+module_exit(imon_exit);
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/ir-jvc-decoder.c linux-libre-2.6.38-gnu1/drivers/media/rc/ir-jvc-decoder.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/ir-jvc-decoder.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/ir-jvc-decoder.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,198 @@
+/* ir-jvc-decoder.c - handle JVC IR Pulse/Space protocol
+ *
+ * Copyright (C) 2010 by David Härdeman <david@hardeman.nu>
+ *
+ * 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.
+ */
+
+#include <linux/bitrev.h>
+#include "rc-core-priv.h"
+
+#define JVC_NBITS		16		/* dev(8) + func(8) */
+#define JVC_UNIT		525000		/* ns */
+#define JVC_HEADER_PULSE	(16 * JVC_UNIT) /* lack of header -> repeat */
+#define JVC_HEADER_SPACE	(8  * JVC_UNIT)
+#define JVC_BIT_PULSE		(1  * JVC_UNIT)
+#define JVC_BIT_0_SPACE		(1  * JVC_UNIT)
+#define JVC_BIT_1_SPACE		(3  * JVC_UNIT)
+#define JVC_TRAILER_PULSE	(1  * JVC_UNIT)
+#define	JVC_TRAILER_SPACE	(35 * JVC_UNIT)
+
+enum jvc_state {
+	STATE_INACTIVE,
+	STATE_HEADER_SPACE,
+	STATE_BIT_PULSE,
+	STATE_BIT_SPACE,
+	STATE_TRAILER_PULSE,
+	STATE_TRAILER_SPACE,
+	STATE_CHECK_REPEAT,
+};
+
+/**
+ * ir_jvc_decode() - Decode one JVC pulse or space
+ * @dev:	the struct rc_dev descriptor of the device
+ * @duration:   the struct ir_raw_event descriptor of the pulse/space
+ *
+ * This function returns -EINVAL if the pulse violates the state machine
+ */
+static int ir_jvc_decode(struct rc_dev *dev, struct ir_raw_event ev)
+{
+	struct jvc_dec *data = &dev->raw->jvc;
+
+	if (!(dev->raw->enabled_protocols & RC_TYPE_JVC))
+		return 0;
+
+	if (!is_timing_event(ev)) {
+		if (ev.reset)
+			data->state = STATE_INACTIVE;
+		return 0;
+	}
+
+	if (!geq_margin(ev.duration, JVC_UNIT, JVC_UNIT / 2))
+		goto out;
+
+	IR_dprintk(2, "JVC decode started at state %d (%uus %s)\n",
+		   data->state, TO_US(ev.duration), TO_STR(ev.pulse));
+
+again:
+	switch (data->state) {
+
+	case STATE_INACTIVE:
+		if (!ev.pulse)
+			break;
+
+		if (!eq_margin(ev.duration, JVC_HEADER_PULSE, JVC_UNIT / 2))
+			break;
+
+		data->count = 0;
+		data->first = true;
+		data->toggle = !data->toggle;
+		data->state = STATE_HEADER_SPACE;
+		return 0;
+
+	case STATE_HEADER_SPACE:
+		if (ev.pulse)
+			break;
+
+		if (!eq_margin(ev.duration, JVC_HEADER_SPACE, JVC_UNIT / 2))
+			break;
+
+		data->state = STATE_BIT_PULSE;
+		return 0;
+
+	case STATE_BIT_PULSE:
+		if (!ev.pulse)
+			break;
+
+		if (!eq_margin(ev.duration, JVC_BIT_PULSE, JVC_UNIT / 2))
+			break;
+
+		data->state = STATE_BIT_SPACE;
+		return 0;
+
+	case STATE_BIT_SPACE:
+		if (ev.pulse)
+			break;
+
+		data->bits <<= 1;
+		if (eq_margin(ev.duration, JVC_BIT_1_SPACE, JVC_UNIT / 2)) {
+			data->bits |= 1;
+			decrease_duration(&ev, JVC_BIT_1_SPACE);
+		} else if (eq_margin(ev.duration, JVC_BIT_0_SPACE, JVC_UNIT / 2))
+			decrease_duration(&ev, JVC_BIT_0_SPACE);
+		else
+			break;
+		data->count++;
+
+		if (data->count == JVC_NBITS)
+			data->state = STATE_TRAILER_PULSE;
+		else
+			data->state = STATE_BIT_PULSE;
+		return 0;
+
+	case STATE_TRAILER_PULSE:
+		if (!ev.pulse)
+			break;
+
+		if (!eq_margin(ev.duration, JVC_TRAILER_PULSE, JVC_UNIT / 2))
+			break;
+
+		data->state = STATE_TRAILER_SPACE;
+		return 0;
+
+	case STATE_TRAILER_SPACE:
+		if (ev.pulse)
+			break;
+
+		if (!geq_margin(ev.duration, JVC_TRAILER_SPACE, JVC_UNIT / 2))
+			break;
+
+		if (data->first) {
+			u32 scancode;
+			scancode = (bitrev8((data->bits >> 8) & 0xff) << 8) |
+				   (bitrev8((data->bits >> 0) & 0xff) << 0);
+			IR_dprintk(1, "JVC scancode 0x%04x\n", scancode);
+			rc_keydown(dev, scancode, data->toggle);
+			data->first = false;
+			data->old_bits = data->bits;
+		} else if (data->bits == data->old_bits) {
+			IR_dprintk(1, "JVC repeat\n");
+			rc_repeat(dev);
+		} else {
+			IR_dprintk(1, "JVC invalid repeat msg\n");
+			break;
+		}
+
+		data->count = 0;
+		data->state = STATE_CHECK_REPEAT;
+		return 0;
+
+	case STATE_CHECK_REPEAT:
+		if (!ev.pulse)
+			break;
+
+		if (eq_margin(ev.duration, JVC_HEADER_PULSE, JVC_UNIT / 2))
+			data->state = STATE_INACTIVE;
+  else
+			data->state = STATE_BIT_PULSE;
+		goto again;
+	}
+
+out:
+	IR_dprintk(1, "JVC decode failed at state %d (%uus %s)\n",
+		   data->state, TO_US(ev.duration), TO_STR(ev.pulse));
+	data->state = STATE_INACTIVE;
+	return -EINVAL;
+}
+
+static struct ir_raw_handler jvc_handler = {
+	.protocols	= RC_TYPE_JVC,
+	.decode		= ir_jvc_decode,
+};
+
+static int __init ir_jvc_decode_init(void)
+{
+	ir_raw_handler_register(&jvc_handler);
+
+	printk(KERN_INFO "IR JVC protocol handler initialized\n");
+	return 0;
+}
+
+static void __exit ir_jvc_decode_exit(void)
+{
+	ir_raw_handler_unregister(&jvc_handler);
+}
+
+module_init(ir_jvc_decode_init);
+module_exit(ir_jvc_decode_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("David Härdeman <david@hardeman.nu>");
+MODULE_DESCRIPTION("JVC IR protocol decoder");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/ir-lirc-codec.c linux-libre-2.6.38-gnu1/drivers/media/rc/ir-lirc-codec.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/ir-lirc-codec.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/ir-lirc-codec.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,406 @@
+/* ir-lirc-codec.c - rc-core to classic lirc interface bridge
+ *
+ * Copyright (C) 2010 by Jarod Wilson <jarod@redhat.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.
+ */
+
+#include <linux/sched.h>
+#include <linux/wait.h>
+#include <media/lirc.h>
+#include <media/lirc_dev.h>
+#include <media/rc-core.h>
+#include "rc-core-priv.h"
+
+#define LIRCBUF_SIZE 256
+
+/**
+ * ir_lirc_decode() - Send raw IR data to lirc_dev to be relayed to the
+ *		      lircd userspace daemon for decoding.
+ * @input_dev:	the struct rc_dev descriptor of the device
+ * @duration:	the struct ir_raw_event descriptor of the pulse/space
+ *
+ * This function returns -EINVAL if the lirc interfaces aren't wired up.
+ */
+static int ir_lirc_decode(struct rc_dev *dev, struct ir_raw_event ev)
+{
+	struct lirc_codec *lirc = &dev->raw->lirc;
+	int sample;
+
+	if (!(dev->raw->enabled_protocols & RC_TYPE_LIRC))
+		return 0;
+
+	if (!dev->raw->lirc.drv || !dev->raw->lirc.drv->rbuf)
+		return -EINVAL;
+
+	/* Packet start */
+	if (ev.reset)
+		return 0;
+
+	/* Carrier reports */
+	if (ev.carrier_report) {
+		sample = LIRC_FREQUENCY(ev.carrier);
+		IR_dprintk(2, "carrier report (freq: %d)\n", sample);
+
+	/* Packet end */
+	} else if (ev.timeout) {
+
+		if (lirc->gap)
+			return 0;
+
+		lirc->gap_start = ktime_get();
+		lirc->gap = true;
+		lirc->gap_duration = ev.duration;
+
+		if (!lirc->send_timeout_reports)
+			return 0;
+
+		sample = LIRC_TIMEOUT(ev.duration / 1000);
+		IR_dprintk(2, "timeout report (duration: %d)\n", sample);
+
+	/* Normal sample */
+	} else {
+
+		if (lirc->gap) {
+			int gap_sample;
+
+			lirc->gap_duration += ktime_to_ns(ktime_sub(ktime_get(),
+				lirc->gap_start));
+
+			/* Convert to ms and cap by LIRC_VALUE_MASK */
+			do_div(lirc->gap_duration, 1000);
+			lirc->gap_duration = min(lirc->gap_duration,
+							(u64)LIRC_VALUE_MASK);
+
+			gap_sample = LIRC_SPACE(lirc->gap_duration);
+			lirc_buffer_write(dev->raw->lirc.drv->rbuf,
+						(unsigned char *) &gap_sample);
+			lirc->gap = false;
+		}
+
+		sample = ev.pulse ? LIRC_PULSE(ev.duration / 1000) :
+					LIRC_SPACE(ev.duration / 1000);
+		IR_dprintk(2, "delivering %uus %s to lirc_dev\n",
+			   TO_US(ev.duration), TO_STR(ev.pulse));
+	}
+
+	lirc_buffer_write(dev->raw->lirc.drv->rbuf,
+			  (unsigned char *) &sample);
+	wake_up(&dev->raw->lirc.drv->rbuf->wait_poll);
+
+	return 0;
+}
+
+static ssize_t ir_lirc_transmit_ir(struct file *file, const char *buf,
+				   size_t n, loff_t *ppos)
+{
+	struct lirc_codec *lirc;
+	struct rc_dev *dev;
+	int *txbuf; /* buffer with values to transmit */
+	int ret = 0;
+	size_t count;
+
+	lirc = lirc_get_pdata(file);
+	if (!lirc)
+		return -EFAULT;
+
+	if (n % sizeof(int))
+		return -EINVAL;
+
+	count = n / sizeof(int);
+	if (count > LIRCBUF_SIZE || count % 2 == 0 || n % sizeof(int) != 0)
+		return -EINVAL;
+
+	txbuf = memdup_user(buf, n);
+	if (IS_ERR(txbuf))
+		return PTR_ERR(txbuf);
+
+	dev = lirc->dev;
+	if (!dev) {
+		ret = -EFAULT;
+		goto out;
+	}
+
+	if (dev->tx_ir)
+		ret = dev->tx_ir(dev, txbuf, (u32)n);
+
+out:
+	kfree(txbuf);
+	return ret;
+}
+
+static long ir_lirc_ioctl(struct file *filep, unsigned int cmd,
+			unsigned long __user arg)
+{
+	struct lirc_codec *lirc;
+	struct rc_dev *dev;
+	int ret = 0;
+	__u32 val = 0, tmp;
+
+	lirc = lirc_get_pdata(filep);
+	if (!lirc)
+		return -EFAULT;
+
+	dev = lirc->dev;
+	if (!dev)
+		return -EFAULT;
+
+	if (_IOC_DIR(cmd) & _IOC_WRITE) {
+		ret = get_user(val, (__u32 *)arg);
+		if (ret)
+			return ret;
+	}
+
+	switch (cmd) {
+
+	/* legacy support */
+	case LIRC_GET_SEND_MODE:
+		val = LIRC_CAN_SEND_PULSE & LIRC_CAN_SEND_MASK;
+		break;
+
+	case LIRC_SET_SEND_MODE:
+		if (val != (LIRC_MODE_PULSE & LIRC_CAN_SEND_MASK))
+			return -EINVAL;
+		return 0;
+
+	/* TX settings */
+	case LIRC_SET_TRANSMITTER_MASK:
+		if (!dev->s_tx_mask)
+			return -EINVAL;
+
+		return dev->s_tx_mask(dev, val);
+
+	case LIRC_SET_SEND_CARRIER:
+		if (!dev->s_tx_carrier)
+			return -EINVAL;
+
+		return dev->s_tx_carrier(dev, val);
+
+	case LIRC_SET_SEND_DUTY_CYCLE:
+		if (!dev->s_tx_duty_cycle)
+			return -ENOSYS;
+
+		if (val <= 0 || val >= 100)
+			return -EINVAL;
+
+		return dev->s_tx_duty_cycle(dev, val);
+
+	/* RX settings */
+	case LIRC_SET_REC_CARRIER:
+		if (!dev->s_rx_carrier_range)
+			return -ENOSYS;
+
+		if (val <= 0)
+			return -EINVAL;
+
+		return dev->s_rx_carrier_range(dev,
+					       dev->raw->lirc.carrier_low,
+					       val);
+
+	case LIRC_SET_REC_CARRIER_RANGE:
+		if (val <= 0)
+			return -EINVAL;
+
+		dev->raw->lirc.carrier_low = val;
+		return 0;
+
+	case LIRC_GET_REC_RESOLUTION:
+		val = dev->rx_resolution;
+		break;
+
+	case LIRC_SET_WIDEBAND_RECEIVER:
+		if (!dev->s_learning_mode)
+			return -ENOSYS;
+
+		return dev->s_learning_mode(dev, !!val);
+
+	case LIRC_SET_MEASURE_CARRIER_MODE:
+		if (!dev->s_carrier_report)
+			return -ENOSYS;
+
+		return dev->s_carrier_report(dev, !!val);
+
+	/* Generic timeout support */
+	case LIRC_GET_MIN_TIMEOUT:
+		if (!dev->max_timeout)
+			return -ENOSYS;
+		val = dev->min_timeout / 1000;
+		break;
+
+	case LIRC_GET_MAX_TIMEOUT:
+		if (!dev->max_timeout)
+			return -ENOSYS;
+		val = dev->max_timeout / 1000;
+		break;
+
+	case LIRC_SET_REC_TIMEOUT:
+		if (!dev->max_timeout)
+			return -ENOSYS;
+
+		tmp = val * 1000;
+
+		if (tmp < dev->min_timeout ||
+		    tmp > dev->max_timeout)
+				return -EINVAL;
+
+		dev->timeout = tmp;
+		break;
+
+	case LIRC_SET_REC_TIMEOUT_REPORTS:
+		lirc->send_timeout_reports = !!val;
+		break;
+
+	default:
+		return lirc_dev_fop_ioctl(filep, cmd, arg);
+	}
+
+	if (_IOC_DIR(cmd) & _IOC_READ)
+		ret = put_user(val, (__u32 *)arg);
+
+	return ret;
+}
+
+static int ir_lirc_open(void *data)
+{
+	return 0;
+}
+
+static void ir_lirc_close(void *data)
+{
+	return;
+}
+
+static struct file_operations lirc_fops = {
+	.owner		= THIS_MODULE,
+	.write		= ir_lirc_transmit_ir,
+	.unlocked_ioctl	= ir_lirc_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl	= ir_lirc_ioctl,
+#endif
+	.read		= lirc_dev_fop_read,
+	.poll		= lirc_dev_fop_poll,
+	.open		= lirc_dev_fop_open,
+	.release	= lirc_dev_fop_close,
+	.llseek		= no_llseek,
+};
+
+static int ir_lirc_register(struct rc_dev *dev)
+{
+	struct lirc_driver *drv;
+	struct lirc_buffer *rbuf;
+	int rc = -ENOMEM;
+	unsigned long features;
+
+	drv = kzalloc(sizeof(struct lirc_driver), GFP_KERNEL);
+	if (!drv)
+		return rc;
+
+	rbuf = kzalloc(sizeof(struct lirc_buffer), GFP_KERNEL);
+	if (!rbuf)
+		goto rbuf_alloc_failed;
+
+	rc = lirc_buffer_init(rbuf, sizeof(int), LIRCBUF_SIZE);
+	if (rc)
+		goto rbuf_init_failed;
+
+	features = LIRC_CAN_REC_MODE2;
+	if (dev->tx_ir) {
+		features |= LIRC_CAN_SEND_PULSE;
+		if (dev->s_tx_mask)
+			features |= LIRC_CAN_SET_TRANSMITTER_MASK;
+		if (dev->s_tx_carrier)
+			features |= LIRC_CAN_SET_SEND_CARRIER;
+		if (dev->s_tx_duty_cycle)
+			features |= LIRC_CAN_SET_SEND_DUTY_CYCLE;
+	}
+
+	if (dev->s_rx_carrier_range)
+		features |= LIRC_CAN_SET_REC_CARRIER |
+			LIRC_CAN_SET_REC_CARRIER_RANGE;
+
+	if (dev->s_learning_mode)
+		features |= LIRC_CAN_USE_WIDEBAND_RECEIVER;
+
+	if (dev->s_carrier_report)
+		features |= LIRC_CAN_MEASURE_CARRIER;
+
+	if (dev->max_timeout)
+		features |= LIRC_CAN_SET_REC_TIMEOUT;
+
+	snprintf(drv->name, sizeof(drv->name), "ir-lirc-codec (%s)",
+		 dev->driver_name);
+	drv->minor = -1;
+	drv->features = features;
+	drv->data = &dev->raw->lirc;
+	drv->rbuf = rbuf;
+	drv->set_use_inc = &ir_lirc_open;
+	drv->set_use_dec = &ir_lirc_close;
+	drv->code_length = sizeof(struct ir_raw_event) * 8;
+	drv->fops = &lirc_fops;
+	drv->dev = &dev->dev;
+	drv->owner = THIS_MODULE;
+
+	drv->minor = lirc_register_driver(drv);
+	if (drv->minor < 0) {
+		rc = -ENODEV;
+		goto lirc_register_failed;
+	}
+
+	dev->raw->lirc.drv = drv;
+	dev->raw->lirc.dev = dev;
+	return 0;
+
+lirc_register_failed:
+rbuf_init_failed:
+	kfree(rbuf);
+rbuf_alloc_failed:
+	kfree(drv);
+
+	return rc;
+}
+
+static int ir_lirc_unregister(struct rc_dev *dev)
+{
+	struct lirc_codec *lirc = &dev->raw->lirc;
+
+	lirc_unregister_driver(lirc->drv->minor);
+	lirc_buffer_free(lirc->drv->rbuf);
+	kfree(lirc->drv);
+
+	return 0;
+}
+
+static struct ir_raw_handler lirc_handler = {
+	.protocols	= RC_TYPE_LIRC,
+	.decode		= ir_lirc_decode,
+	.raw_register	= ir_lirc_register,
+	.raw_unregister	= ir_lirc_unregister,
+};
+
+static int __init ir_lirc_codec_init(void)
+{
+	ir_raw_handler_register(&lirc_handler);
+
+	printk(KERN_INFO "IR LIRC bridge handler initialized\n");
+	return 0;
+}
+
+static void __exit ir_lirc_codec_exit(void)
+{
+	ir_raw_handler_unregister(&lirc_handler);
+}
+
+module_init(ir_lirc_codec_init);
+module_exit(ir_lirc_codec_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Jarod Wilson <jarod@redhat.com>");
+MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)");
+MODULE_DESCRIPTION("LIRC IR handler bridge");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/ir-nec-decoder.c linux-libre-2.6.38-gnu1/drivers/media/rc/ir-nec-decoder.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/ir-nec-decoder.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/ir-nec-decoder.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,220 @@
+/* ir-nec-decoder.c - handle NEC IR Pulse/Space protocol
+ *
+ * Copyright (C) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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.
+ */
+
+#include <linux/bitrev.h>
+#include "rc-core-priv.h"
+
+#define NEC_NBITS		32
+#define NEC_UNIT		562500  /* ns */
+#define NEC_HEADER_PULSE	(16 * NEC_UNIT)
+#define NECX_HEADER_PULSE	(8  * NEC_UNIT) /* Less common NEC variant */
+#define NEC_HEADER_SPACE	(8  * NEC_UNIT)
+#define NEC_REPEAT_SPACE	(4  * NEC_UNIT)
+#define NEC_BIT_PULSE		(1  * NEC_UNIT)
+#define NEC_BIT_0_SPACE		(1  * NEC_UNIT)
+#define NEC_BIT_1_SPACE		(3  * NEC_UNIT)
+#define	NEC_TRAILER_PULSE	(1  * NEC_UNIT)
+#define	NEC_TRAILER_SPACE	(10 * NEC_UNIT) /* even longer in reality */
+#define NECX_REPEAT_BITS	1
+
+enum nec_state {
+	STATE_INACTIVE,
+	STATE_HEADER_SPACE,
+	STATE_BIT_PULSE,
+	STATE_BIT_SPACE,
+	STATE_TRAILER_PULSE,
+	STATE_TRAILER_SPACE,
+};
+
+/**
+ * ir_nec_decode() - Decode one NEC pulse or space
+ * @dev:	the struct rc_dev descriptor of the device
+ * @duration:	the struct ir_raw_event descriptor of the pulse/space
+ *
+ * This function returns -EINVAL if the pulse violates the state machine
+ */
+static int ir_nec_decode(struct rc_dev *dev, struct ir_raw_event ev)
+{
+	struct nec_dec *data = &dev->raw->nec;
+	u32 scancode;
+	u8 address, not_address, command, not_command;
+
+	if (!(dev->raw->enabled_protocols & RC_TYPE_NEC))
+		return 0;
+
+	if (!is_timing_event(ev)) {
+		if (ev.reset)
+			data->state = STATE_INACTIVE;
+		return 0;
+	}
+
+	IR_dprintk(2, "NEC decode started at state %d (%uus %s)\n",
+		   data->state, TO_US(ev.duration), TO_STR(ev.pulse));
+
+	switch (data->state) {
+
+	case STATE_INACTIVE:
+		if (!ev.pulse)
+			break;
+
+		if (eq_margin(ev.duration, NEC_HEADER_PULSE, NEC_UNIT / 2)) {
+			data->is_nec_x = false;
+			data->necx_repeat = false;
+		} else if (eq_margin(ev.duration, NECX_HEADER_PULSE, NEC_UNIT / 2))
+			data->is_nec_x = true;
+		else
+			break;
+
+		data->count = 0;
+		data->state = STATE_HEADER_SPACE;
+		return 0;
+
+	case STATE_HEADER_SPACE:
+		if (ev.pulse)
+			break;
+
+		if (eq_margin(ev.duration, NEC_HEADER_SPACE, NEC_UNIT / 2)) {
+			data->state = STATE_BIT_PULSE;
+			return 0;
+		} else if (eq_margin(ev.duration, NEC_REPEAT_SPACE, NEC_UNIT / 2)) {
+			if (!dev->keypressed) {
+				IR_dprintk(1, "Discarding last key repeat: event after key up\n");
+			} else {
+				rc_repeat(dev);
+				IR_dprintk(1, "Repeat last key\n");
+				data->state = STATE_TRAILER_PULSE;
+			}
+			return 0;
+		}
+
+		break;
+
+	case STATE_BIT_PULSE:
+		if (!ev.pulse)
+			break;
+
+		if (!eq_margin(ev.duration, NEC_BIT_PULSE, NEC_UNIT / 2))
+			break;
+
+		data->state = STATE_BIT_SPACE;
+		return 0;
+
+	case STATE_BIT_SPACE:
+		if (ev.pulse)
+			break;
+
+		if (data->necx_repeat && data->count == NECX_REPEAT_BITS &&
+			geq_margin(ev.duration,
+			NEC_TRAILER_SPACE, NEC_UNIT / 2)) {
+				IR_dprintk(1, "Repeat last key\n");
+				rc_repeat(dev);
+				data->state = STATE_INACTIVE;
+				return 0;
+
+		} else if (data->count > NECX_REPEAT_BITS)
+			data->necx_repeat = false;
+
+		data->bits <<= 1;
+		if (eq_margin(ev.duration, NEC_BIT_1_SPACE, NEC_UNIT / 2))
+			data->bits |= 1;
+		else if (!eq_margin(ev.duration, NEC_BIT_0_SPACE, NEC_UNIT / 2))
+			break;
+		data->count++;
+
+		if (data->count == NEC_NBITS)
+			data->state = STATE_TRAILER_PULSE;
+		else
+			data->state = STATE_BIT_PULSE;
+
+		return 0;
+
+	case STATE_TRAILER_PULSE:
+		if (!ev.pulse)
+			break;
+
+		if (!eq_margin(ev.duration, NEC_TRAILER_PULSE, NEC_UNIT / 2))
+			break;
+
+		data->state = STATE_TRAILER_SPACE;
+		return 0;
+
+	case STATE_TRAILER_SPACE:
+		if (ev.pulse)
+			break;
+
+		if (!geq_margin(ev.duration, NEC_TRAILER_SPACE, NEC_UNIT / 2))
+			break;
+
+		address     = bitrev8((data->bits >> 24) & 0xff);
+		not_address = bitrev8((data->bits >> 16) & 0xff);
+		command	    = bitrev8((data->bits >>  8) & 0xff);
+		not_command = bitrev8((data->bits >>  0) & 0xff);
+
+		if ((command ^ not_command) != 0xff) {
+			IR_dprintk(1, "NEC checksum error: received 0x%08x\n",
+				   data->bits);
+			break;
+		}
+
+		if ((address ^ not_address) != 0xff) {
+			/* Extended NEC */
+			scancode = address     << 16 |
+				   not_address <<  8 |
+				   command;
+			IR_dprintk(1, "NEC (Ext) scancode 0x%06x\n", scancode);
+		} else {
+			/* Normal NEC */
+			scancode = address << 8 | command;
+			IR_dprintk(1, "NEC scancode 0x%04x\n", scancode);
+		}
+
+		if (data->is_nec_x)
+			data->necx_repeat = true;
+
+		rc_keydown(dev, scancode, 0);
+		data->state = STATE_INACTIVE;
+		return 0;
+	}
+
+	IR_dprintk(1, "NEC decode failed at state %d (%uus %s)\n",
+		   data->state, TO_US(ev.duration), TO_STR(ev.pulse));
+	data->state = STATE_INACTIVE;
+	return -EINVAL;
+}
+
+static struct ir_raw_handler nec_handler = {
+	.protocols	= RC_TYPE_NEC,
+	.decode		= ir_nec_decode,
+};
+
+static int __init ir_nec_decode_init(void)
+{
+	ir_raw_handler_register(&nec_handler);
+
+	printk(KERN_INFO "IR NEC protocol handler initialized\n");
+	return 0;
+}
+
+static void __exit ir_nec_decode_exit(void)
+{
+	ir_raw_handler_unregister(&nec_handler);
+}
+
+module_init(ir_nec_decode_init);
+module_exit(ir_nec_decode_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
+MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)");
+MODULE_DESCRIPTION("NEC IR protocol decoder");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/ir-raw.c linux-libre-2.6.38-gnu1/drivers/media/rc/ir-raw.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/ir-raw.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/ir-raw.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,370 @@
+/* ir-raw.c - handle IR pulse/space events
+ *
+ * Copyright (C) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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.
+ */
+
+#include <linux/kthread.h>
+#include <linux/mutex.h>
+#include <linux/sched.h>
+#include <linux/freezer.h>
+#include "rc-core-priv.h"
+
+/* Define the max number of pulse/space transitions to buffer */
+#define MAX_IR_EVENT_SIZE      512
+
+/* Used to keep track of IR raw clients, protected by ir_raw_handler_lock */
+static LIST_HEAD(ir_raw_client_list);
+
+/* Used to handle IR raw handler extensions */
+static DEFINE_MUTEX(ir_raw_handler_lock);
+static LIST_HEAD(ir_raw_handler_list);
+static u64 available_protocols;
+
+#ifdef MODULE
+/* Used to load the decoders */
+static struct work_struct wq_load;
+#endif
+
+static int ir_raw_event_thread(void *data)
+{
+	struct ir_raw_event ev;
+	struct ir_raw_handler *handler;
+	struct ir_raw_event_ctrl *raw = (struct ir_raw_event_ctrl *)data;
+	int retval;
+
+	while (!kthread_should_stop()) {
+
+		spin_lock_irq(&raw->lock);
+		retval = kfifo_out(&raw->kfifo, &ev, sizeof(ev));
+
+		if (!retval) {
+			set_current_state(TASK_INTERRUPTIBLE);
+
+			if (kthread_should_stop())
+				set_current_state(TASK_RUNNING);
+
+			spin_unlock_irq(&raw->lock);
+			schedule();
+			continue;
+		}
+
+		spin_unlock_irq(&raw->lock);
+
+
+		BUG_ON(retval != sizeof(ev));
+
+		mutex_lock(&ir_raw_handler_lock);
+		list_for_each_entry(handler, &ir_raw_handler_list, list)
+			handler->decode(raw->dev, ev);
+		raw->prev_ev = ev;
+		mutex_unlock(&ir_raw_handler_lock);
+	}
+
+	return 0;
+}
+
+/**
+ * ir_raw_event_store() - pass a pulse/space duration to the raw ir decoders
+ * @dev:	the struct rc_dev device descriptor
+ * @ev:		the struct ir_raw_event descriptor of the pulse/space
+ *
+ * This routine (which may be called from an interrupt context) stores a
+ * pulse/space duration for the raw ir decoding state machines. Pulses are
+ * signalled as positive values and spaces as negative values. A zero value
+ * will reset the decoding state machines.
+ */
+int ir_raw_event_store(struct rc_dev *dev, struct ir_raw_event *ev)
+{
+	if (!dev->raw)
+		return -EINVAL;
+
+	IR_dprintk(2, "sample: (%05dus %s)\n",
+		   TO_US(ev->duration), TO_STR(ev->pulse));
+
+	if (kfifo_in(&dev->raw->kfifo, ev, sizeof(*ev)) != sizeof(*ev))
+		return -ENOMEM;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(ir_raw_event_store);
+
+/**
+ * ir_raw_event_store_edge() - notify raw ir decoders of the start of a pulse/space
+ * @dev:	the struct rc_dev device descriptor
+ * @type:	the type of the event that has occurred
+ *
+ * This routine (which may be called from an interrupt context) is used to
+ * store the beginning of an ir pulse or space (or the start/end of ir
+ * reception) for the raw ir decoding state machines. This is used by
+ * hardware which does not provide durations directly but only interrupts
+ * (or similar events) on state change.
+ */
+int ir_raw_event_store_edge(struct rc_dev *dev, enum raw_event_type type)
+{
+	ktime_t			now;
+	s64			delta; /* ns */
+	DEFINE_IR_RAW_EVENT(ev);
+	int			rc = 0;
+
+	if (!dev->raw)
+		return -EINVAL;
+
+	now = ktime_get();
+	delta = ktime_to_ns(ktime_sub(now, dev->raw->last_event));
+
+	/* Check for a long duration since last event or if we're
+	 * being called for the first time, note that delta can't
+	 * possibly be negative.
+	 */
+	if (delta > IR_MAX_DURATION || !dev->raw->last_type)
+		type |= IR_START_EVENT;
+	else
+		ev.duration = delta;
+
+	if (type & IR_START_EVENT)
+		ir_raw_event_reset(dev);
+	else if (dev->raw->last_type & IR_SPACE) {
+		ev.pulse = false;
+		rc = ir_raw_event_store(dev, &ev);
+	} else if (dev->raw->last_type & IR_PULSE) {
+		ev.pulse = true;
+		rc = ir_raw_event_store(dev, &ev);
+	} else
+		return 0;
+
+	dev->raw->last_event = now;
+	dev->raw->last_type = type;
+	return rc;
+}
+EXPORT_SYMBOL_GPL(ir_raw_event_store_edge);
+
+/**
+ * ir_raw_event_store_with_filter() - pass next pulse/space to decoders with some processing
+ * @dev:	the struct rc_dev device descriptor
+ * @type:	the type of the event that has occurred
+ *
+ * This routine (which may be called from an interrupt context) works
+ * in similiar manner to ir_raw_event_store_edge.
+ * This routine is intended for devices with limited internal buffer
+ * It automerges samples of same type, and handles timeouts
+ */
+int ir_raw_event_store_with_filter(struct rc_dev *dev, struct ir_raw_event *ev)
+{
+	if (!dev->raw)
+		return -EINVAL;
+
+	/* Ignore spaces in idle mode */
+	if (dev->idle && !ev->pulse)
+		return 0;
+	else if (dev->idle)
+		ir_raw_event_set_idle(dev, false);
+
+	if (!dev->raw->this_ev.duration)
+		dev->raw->this_ev = *ev;
+	else if (ev->pulse == dev->raw->this_ev.pulse)
+		dev->raw->this_ev.duration += ev->duration;
+	else {
+		ir_raw_event_store(dev, &dev->raw->this_ev);
+		dev->raw->this_ev = *ev;
+	}
+
+	/* Enter idle mode if nessesary */
+	if (!ev->pulse && dev->timeout &&
+	    dev->raw->this_ev.duration >= dev->timeout)
+		ir_raw_event_set_idle(dev, true);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(ir_raw_event_store_with_filter);
+
+/**
+ * ir_raw_event_set_idle() - provide hint to rc-core when the device is idle or not
+ * @dev:	the struct rc_dev device descriptor
+ * @idle:	whether the device is idle or not
+ */
+void ir_raw_event_set_idle(struct rc_dev *dev, bool idle)
+{
+	if (!dev->raw)
+		return;
+
+	IR_dprintk(2, "%s idle mode\n", idle ? "enter" : "leave");
+
+	if (idle) {
+		dev->raw->this_ev.timeout = true;
+		ir_raw_event_store(dev, &dev->raw->this_ev);
+		init_ir_raw_event(&dev->raw->this_ev);
+	}
+
+	if (dev->s_idle)
+		dev->s_idle(dev, idle);
+
+	dev->idle = idle;
+}
+EXPORT_SYMBOL_GPL(ir_raw_event_set_idle);
+
+/**
+ * ir_raw_event_handle() - schedules the decoding of stored ir data
+ * @dev:	the struct rc_dev device descriptor
+ *
+ * This routine will tell rc-core to start decoding stored ir data.
+ */
+void ir_raw_event_handle(struct rc_dev *dev)
+{
+	unsigned long flags;
+
+	if (!dev->raw)
+		return;
+
+	spin_lock_irqsave(&dev->raw->lock, flags);
+	wake_up_process(dev->raw->thread);
+	spin_unlock_irqrestore(&dev->raw->lock, flags);
+}
+EXPORT_SYMBOL_GPL(ir_raw_event_handle);
+
+/* used internally by the sysfs interface */
+u64
+ir_raw_get_allowed_protocols(void)
+{
+	u64 protocols;
+	mutex_lock(&ir_raw_handler_lock);
+	protocols = available_protocols;
+	mutex_unlock(&ir_raw_handler_lock);
+	return protocols;
+}
+
+/*
+ * Used to (un)register raw event clients
+ */
+int ir_raw_event_register(struct rc_dev *dev)
+{
+	int rc;
+	struct ir_raw_handler *handler;
+
+	if (!dev)
+		return -EINVAL;
+
+	dev->raw = kzalloc(sizeof(*dev->raw), GFP_KERNEL);
+	if (!dev->raw)
+		return -ENOMEM;
+
+	dev->raw->dev = dev;
+	dev->raw->enabled_protocols = ~0;
+	rc = kfifo_alloc(&dev->raw->kfifo,
+			 sizeof(struct ir_raw_event) * MAX_IR_EVENT_SIZE,
+			 GFP_KERNEL);
+	if (rc < 0)
+		goto out;
+
+	spin_lock_init(&dev->raw->lock);
+	dev->raw->thread = kthread_run(ir_raw_event_thread, dev->raw,
+				       "rc%ld", dev->devno);
+
+	if (IS_ERR(dev->raw->thread)) {
+		rc = PTR_ERR(dev->raw->thread);
+		goto out;
+	}
+
+	mutex_lock(&ir_raw_handler_lock);
+	list_add_tail(&dev->raw->list, &ir_raw_client_list);
+	list_for_each_entry(handler, &ir_raw_handler_list, list)
+		if (handler->raw_register)
+			handler->raw_register(dev);
+	mutex_unlock(&ir_raw_handler_lock);
+
+	return 0;
+
+out:
+	kfree(dev->raw);
+	dev->raw = NULL;
+	return rc;
+}
+
+void ir_raw_event_unregister(struct rc_dev *dev)
+{
+	struct ir_raw_handler *handler;
+
+	if (!dev || !dev->raw)
+		return;
+
+	kthread_stop(dev->raw->thread);
+
+	mutex_lock(&ir_raw_handler_lock);
+	list_del(&dev->raw->list);
+	list_for_each_entry(handler, &ir_raw_handler_list, list)
+		if (handler->raw_unregister)
+			handler->raw_unregister(dev);
+	mutex_unlock(&ir_raw_handler_lock);
+
+	kfifo_free(&dev->raw->kfifo);
+	kfree(dev->raw);
+	dev->raw = NULL;
+}
+
+/*
+ * Extension interface - used to register the IR decoders
+ */
+
+int ir_raw_handler_register(struct ir_raw_handler *ir_raw_handler)
+{
+	struct ir_raw_event_ctrl *raw;
+
+	mutex_lock(&ir_raw_handler_lock);
+	list_add_tail(&ir_raw_handler->list, &ir_raw_handler_list);
+	if (ir_raw_handler->raw_register)
+		list_for_each_entry(raw, &ir_raw_client_list, list)
+			ir_raw_handler->raw_register(raw->dev);
+	available_protocols |= ir_raw_handler->protocols;
+	mutex_unlock(&ir_raw_handler_lock);
+
+	return 0;
+}
+EXPORT_SYMBOL(ir_raw_handler_register);
+
+void ir_raw_handler_unregister(struct ir_raw_handler *ir_raw_handler)
+{
+	struct ir_raw_event_ctrl *raw;
+
+	mutex_lock(&ir_raw_handler_lock);
+	list_del(&ir_raw_handler->list);
+	if (ir_raw_handler->raw_unregister)
+		list_for_each_entry(raw, &ir_raw_client_list, list)
+			ir_raw_handler->raw_unregister(raw->dev);
+	available_protocols &= ~ir_raw_handler->protocols;
+	mutex_unlock(&ir_raw_handler_lock);
+}
+EXPORT_SYMBOL(ir_raw_handler_unregister);
+
+#ifdef MODULE
+static void init_decoders(struct work_struct *work)
+{
+	/* Load the decoder modules */
+
+	load_nec_decode();
+	load_rc5_decode();
+	load_rc6_decode();
+	load_jvc_decode();
+	load_sony_decode();
+	load_lirc_codec();
+
+	/* If needed, we may later add some init code. In this case,
+	   it is needed to change the CONFIG_MODULE test at rc-core.h
+	 */
+}
+#endif
+
+void ir_raw_init(void)
+{
+#ifdef MODULE
+	INIT_WORK(&wq_load, init_decoders);
+	schedule_work(&wq_load);
+#endif
+}
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/ir-rc5-decoder.c linux-libre-2.6.38-gnu1/drivers/media/rc/ir-rc5-decoder.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/ir-rc5-decoder.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/ir-rc5-decoder.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,189 @@
+/* ir-rc5-decoder.c - handle RC5(x) IR Pulse/Space protocol
+ *
+ * Copyright (C) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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.
+ */
+
+/*
+ * This code handles 14 bits RC5 protocols and 20 bits RC5x protocols.
+ * There are other variants that use a different number of bits.
+ * This is currently unsupported.
+ * It considers a carrier of 36 kHz, with a total of 14/20 bits, where
+ * the first two bits are start bits, and a third one is a filing bit
+ */
+
+#include "rc-core-priv.h"
+
+#define RC5_NBITS		14
+#define RC5X_NBITS		20
+#define CHECK_RC5X_NBITS	8
+#define RC5_UNIT		888888 /* ns */
+#define RC5_BIT_START		(1 * RC5_UNIT)
+#define RC5_BIT_END		(1 * RC5_UNIT)
+#define RC5X_SPACE		(4 * RC5_UNIT)
+
+enum rc5_state {
+	STATE_INACTIVE,
+	STATE_BIT_START,
+	STATE_BIT_END,
+	STATE_CHECK_RC5X,
+	STATE_FINISHED,
+};
+
+/**
+ * ir_rc5_decode() - Decode one RC-5 pulse or space
+ * @dev:	the struct rc_dev descriptor of the device
+ * @ev:		the struct ir_raw_event descriptor of the pulse/space
+ *
+ * This function returns -EINVAL if the pulse violates the state machine
+ */
+static int ir_rc5_decode(struct rc_dev *dev, struct ir_raw_event ev)
+{
+	struct rc5_dec *data = &dev->raw->rc5;
+	u8 toggle;
+	u32 scancode;
+
+        if (!(dev->raw->enabled_protocols & RC_TYPE_RC5))
+                return 0;
+
+	if (!is_timing_event(ev)) {
+		if (ev.reset)
+			data->state = STATE_INACTIVE;
+		return 0;
+	}
+
+	if (!geq_margin(ev.duration, RC5_UNIT, RC5_UNIT / 2))
+		goto out;
+
+again:
+	IR_dprintk(2, "RC5(x) decode started at state %i (%uus %s)\n",
+		   data->state, TO_US(ev.duration), TO_STR(ev.pulse));
+
+	if (!geq_margin(ev.duration, RC5_UNIT, RC5_UNIT / 2))
+		return 0;
+
+	switch (data->state) {
+
+	case STATE_INACTIVE:
+		if (!ev.pulse)
+			break;
+
+		data->state = STATE_BIT_START;
+		data->count = 1;
+		/* We just need enough bits to get to STATE_CHECK_RC5X */
+		data->wanted_bits = RC5X_NBITS;
+		decrease_duration(&ev, RC5_BIT_START);
+		goto again;
+
+	case STATE_BIT_START:
+		if (!eq_margin(ev.duration, RC5_BIT_START, RC5_UNIT / 2))
+			break;
+
+		data->bits <<= 1;
+		if (!ev.pulse)
+			data->bits |= 1;
+		data->count++;
+		data->state = STATE_BIT_END;
+		return 0;
+
+	case STATE_BIT_END:
+		if (!is_transition(&ev, &dev->raw->prev_ev))
+			break;
+
+		if (data->count == data->wanted_bits)
+			data->state = STATE_FINISHED;
+		else if (data->count == CHECK_RC5X_NBITS)
+			data->state = STATE_CHECK_RC5X;
+		else
+			data->state = STATE_BIT_START;
+
+		decrease_duration(&ev, RC5_BIT_END);
+		goto again;
+
+	case STATE_CHECK_RC5X:
+		if (!ev.pulse && geq_margin(ev.duration, RC5X_SPACE, RC5_UNIT / 2)) {
+			/* RC5X */
+			data->wanted_bits = RC5X_NBITS;
+			decrease_duration(&ev, RC5X_SPACE);
+		} else {
+			/* RC5 */
+			data->wanted_bits = RC5_NBITS;
+		}
+		data->state = STATE_BIT_START;
+		goto again;
+
+	case STATE_FINISHED:
+		if (ev.pulse)
+			break;
+
+		if (data->wanted_bits == RC5X_NBITS) {
+			/* RC5X */
+			u8 xdata, command, system;
+			xdata    = (data->bits & 0x0003F) >> 0;
+			command  = (data->bits & 0x00FC0) >> 6;
+			system   = (data->bits & 0x1F000) >> 12;
+			toggle   = (data->bits & 0x20000) ? 1 : 0;
+			command += (data->bits & 0x01000) ? 0 : 0x40;
+			scancode = system << 16 | command << 8 | xdata;
+
+			IR_dprintk(1, "RC5X scancode 0x%06x (toggle: %u)\n",
+				   scancode, toggle);
+
+		} else {
+			/* RC5 */
+			u8 command, system;
+			command  = (data->bits & 0x0003F) >> 0;
+			system   = (data->bits & 0x007C0) >> 6;
+			toggle   = (data->bits & 0x00800) ? 1 : 0;
+			command += (data->bits & 0x01000) ? 0 : 0x40;
+			scancode = system << 8 | command;
+
+			IR_dprintk(1, "RC5 scancode 0x%04x (toggle: %u)\n",
+				   scancode, toggle);
+		}
+
+		rc_keydown(dev, scancode, toggle);
+		data->state = STATE_INACTIVE;
+		return 0;
+	}
+
+out:
+	IR_dprintk(1, "RC5(x) decode failed at state %i (%uus %s)\n",
+		   data->state, TO_US(ev.duration), TO_STR(ev.pulse));
+	data->state = STATE_INACTIVE;
+	return -EINVAL;
+}
+
+static struct ir_raw_handler rc5_handler = {
+	.protocols	= RC_TYPE_RC5,
+	.decode		= ir_rc5_decode,
+};
+
+static int __init ir_rc5_decode_init(void)
+{
+	ir_raw_handler_register(&rc5_handler);
+
+	printk(KERN_INFO "IR RC5(x) protocol handler initialized\n");
+	return 0;
+}
+
+static void __exit ir_rc5_decode_exit(void)
+{
+	ir_raw_handler_unregister(&rc5_handler);
+}
+
+module_init(ir_rc5_decode_init);
+module_exit(ir_rc5_decode_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
+MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)");
+MODULE_DESCRIPTION("RC5(x) IR protocol decoder");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/ir-rc5-sz-decoder.c linux-libre-2.6.38-gnu1/drivers/media/rc/ir-rc5-sz-decoder.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/ir-rc5-sz-decoder.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/ir-rc5-sz-decoder.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,153 @@
+/* ir-rc5-sz-decoder.c - handle RC5 Streamzap IR Pulse/Space protocol
+ *
+ * Copyright (C) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
+ * Copyright (C) 2010 by Jarod Wilson <jarod@redhat.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.
+ */
+
+/*
+ * This code handles the 15 bit RC5-ish protocol used by the Streamzap
+ * PC Remote.
+ * It considers a carrier of 36 kHz, with a total of 15 bits, where
+ * the first two bits are start bits, and a third one is a filing bit
+ */
+
+#include "rc-core-priv.h"
+
+#define RC5_SZ_NBITS		15
+#define RC5_UNIT		888888 /* ns */
+#define RC5_BIT_START		(1 * RC5_UNIT)
+#define RC5_BIT_END		(1 * RC5_UNIT)
+
+enum rc5_sz_state {
+	STATE_INACTIVE,
+	STATE_BIT_START,
+	STATE_BIT_END,
+	STATE_FINISHED,
+};
+
+/**
+ * ir_rc5_sz_decode() - Decode one RC-5 Streamzap pulse or space
+ * @dev:	the struct rc_dev descriptor of the device
+ * @ev:		the struct ir_raw_event descriptor of the pulse/space
+ *
+ * This function returns -EINVAL if the pulse violates the state machine
+ */
+static int ir_rc5_sz_decode(struct rc_dev *dev, struct ir_raw_event ev)
+{
+	struct rc5_sz_dec *data = &dev->raw->rc5_sz;
+	u8 toggle, command, system;
+	u32 scancode;
+
+        if (!(dev->raw->enabled_protocols & RC_TYPE_RC5_SZ))
+                return 0;
+
+	if (!is_timing_event(ev)) {
+		if (ev.reset)
+			data->state = STATE_INACTIVE;
+		return 0;
+	}
+
+	if (!geq_margin(ev.duration, RC5_UNIT, RC5_UNIT / 2))
+		goto out;
+
+again:
+	IR_dprintk(2, "RC5-sz decode started at state %i (%uus %s)\n",
+		   data->state, TO_US(ev.duration), TO_STR(ev.pulse));
+
+	if (!geq_margin(ev.duration, RC5_UNIT, RC5_UNIT / 2))
+		return 0;
+
+	switch (data->state) {
+
+	case STATE_INACTIVE:
+		if (!ev.pulse)
+			break;
+
+		data->state = STATE_BIT_START;
+		data->count = 1;
+		data->wanted_bits = RC5_SZ_NBITS;
+		decrease_duration(&ev, RC5_BIT_START);
+		goto again;
+
+	case STATE_BIT_START:
+		if (!eq_margin(ev.duration, RC5_BIT_START, RC5_UNIT / 2))
+			break;
+
+		data->bits <<= 1;
+		if (!ev.pulse)
+			data->bits |= 1;
+		data->count++;
+		data->state = STATE_BIT_END;
+		return 0;
+
+	case STATE_BIT_END:
+		if (!is_transition(&ev, &dev->raw->prev_ev))
+			break;
+
+		if (data->count == data->wanted_bits)
+			data->state = STATE_FINISHED;
+		else
+			data->state = STATE_BIT_START;
+
+		decrease_duration(&ev, RC5_BIT_END);
+		goto again;
+
+	case STATE_FINISHED:
+		if (ev.pulse)
+			break;
+
+		/* RC5-sz */
+		command  = (data->bits & 0x0003F) >> 0;
+		system   = (data->bits & 0x02FC0) >> 6;
+		toggle   = (data->bits & 0x01000) ? 1 : 0;
+		scancode = system << 6 | command;
+
+		IR_dprintk(1, "RC5-sz scancode 0x%04x (toggle: %u)\n",
+			   scancode, toggle);
+
+		rc_keydown(dev, scancode, toggle);
+		data->state = STATE_INACTIVE;
+		return 0;
+	}
+
+out:
+	IR_dprintk(1, "RC5-sz decode failed at state %i (%uus %s)\n",
+		   data->state, TO_US(ev.duration), TO_STR(ev.pulse));
+	data->state = STATE_INACTIVE;
+	return -EINVAL;
+}
+
+static struct ir_raw_handler rc5_sz_handler = {
+	.protocols	= RC_TYPE_RC5_SZ,
+	.decode		= ir_rc5_sz_decode,
+};
+
+static int __init ir_rc5_sz_decode_init(void)
+{
+	ir_raw_handler_register(&rc5_sz_handler);
+
+	printk(KERN_INFO "IR RC5 (streamzap) protocol handler initialized\n");
+	return 0;
+}
+
+static void __exit ir_rc5_sz_decode_exit(void)
+{
+	ir_raw_handler_unregister(&rc5_sz_handler);
+}
+
+module_init(ir_rc5_sz_decode_init);
+module_exit(ir_rc5_sz_decode_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Jarod Wilson <jarod@redhat.com>");
+MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)");
+MODULE_DESCRIPTION("RC5 (streamzap) IR protocol decoder");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/ir-rc6-decoder.c linux-libre-2.6.38-gnu1/drivers/media/rc/ir-rc6-decoder.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/ir-rc6-decoder.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/ir-rc6-decoder.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,280 @@
+/* ir-rc6-decoder.c - A decoder for the RC6 IR protocol
+ *
+ * Copyright (C) 2010 by David Härdeman <david@hardeman.nu>
+ *
+ * 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.
+ */
+
+#include "rc-core-priv.h"
+
+/*
+ * This decoder currently supports:
+ * RC6-0-16	(standard toggle bit in header)
+ * RC6-6A-24	(no toggle bit)
+ * RC6-6A-32	(MCE version with toggle bit in body)
+ */
+
+#define RC6_UNIT		444444	/* us */
+#define RC6_HEADER_NBITS	4	/* not including toggle bit */
+#define RC6_0_NBITS		16
+#define RC6_6A_SMALL_NBITS	24
+#define RC6_6A_LARGE_NBITS	32
+#define RC6_PREFIX_PULSE	(6 * RC6_UNIT)
+#define RC6_PREFIX_SPACE	(2 * RC6_UNIT)
+#define RC6_BIT_START		(1 * RC6_UNIT)
+#define RC6_BIT_END		(1 * RC6_UNIT)
+#define RC6_TOGGLE_START	(2 * RC6_UNIT)
+#define RC6_TOGGLE_END		(2 * RC6_UNIT)
+#define RC6_MODE_MASK		0x07	/* for the header bits */
+#define RC6_STARTBIT_MASK	0x08	/* for the header bits */
+#define RC6_6A_MCE_TOGGLE_MASK	0x8000	/* for the body bits */
+
+enum rc6_mode {
+	RC6_MODE_0,
+	RC6_MODE_6A,
+	RC6_MODE_UNKNOWN,
+};
+
+enum rc6_state {
+	STATE_INACTIVE,
+	STATE_PREFIX_SPACE,
+	STATE_HEADER_BIT_START,
+	STATE_HEADER_BIT_END,
+	STATE_TOGGLE_START,
+	STATE_TOGGLE_END,
+	STATE_BODY_BIT_START,
+	STATE_BODY_BIT_END,
+	STATE_FINISHED,
+};
+
+static enum rc6_mode rc6_mode(struct rc6_dec *data)
+{
+	switch (data->header & RC6_MODE_MASK) {
+	case 0:
+		return RC6_MODE_0;
+	case 6:
+		if (!data->toggle)
+			return RC6_MODE_6A;
+		/* fall through */
+	default:
+		return RC6_MODE_UNKNOWN;
+	}
+}
+
+/**
+ * ir_rc6_decode() - Decode one RC6 pulse or space
+ * @dev:	the struct rc_dev descriptor of the device
+ * @ev:		the struct ir_raw_event descriptor of the pulse/space
+ *
+ * This function returns -EINVAL if the pulse violates the state machine
+ */
+static int ir_rc6_decode(struct rc_dev *dev, struct ir_raw_event ev)
+{
+	struct rc6_dec *data = &dev->raw->rc6;
+	u32 scancode;
+	u8 toggle;
+
+	if (!(dev->raw->enabled_protocols & RC_TYPE_RC6))
+		return 0;
+
+	if (!is_timing_event(ev)) {
+		if (ev.reset)
+			data->state = STATE_INACTIVE;
+		return 0;
+	}
+
+	if (!geq_margin(ev.duration, RC6_UNIT, RC6_UNIT / 2))
+		goto out;
+
+again:
+	IR_dprintk(2, "RC6 decode started at state %i (%uus %s)\n",
+		   data->state, TO_US(ev.duration), TO_STR(ev.pulse));
+
+	if (!geq_margin(ev.duration, RC6_UNIT, RC6_UNIT / 2))
+		return 0;
+
+	switch (data->state) {
+
+	case STATE_INACTIVE:
+		if (!ev.pulse)
+			break;
+
+		/* Note: larger margin on first pulse since each RC6_UNIT
+		   is quite short and some hardware takes some time to
+		   adjust to the signal */
+		if (!eq_margin(ev.duration, RC6_PREFIX_PULSE, RC6_UNIT))
+			break;
+
+		data->state = STATE_PREFIX_SPACE;
+		data->count = 0;
+		return 0;
+
+	case STATE_PREFIX_SPACE:
+		if (ev.pulse)
+			break;
+
+		if (!eq_margin(ev.duration, RC6_PREFIX_SPACE, RC6_UNIT / 2))
+			break;
+
+		data->state = STATE_HEADER_BIT_START;
+		return 0;
+
+	case STATE_HEADER_BIT_START:
+		if (!eq_margin(ev.duration, RC6_BIT_START, RC6_UNIT / 2))
+			break;
+
+		data->header <<= 1;
+		if (ev.pulse)
+			data->header |= 1;
+		data->count++;
+		data->state = STATE_HEADER_BIT_END;
+		return 0;
+
+	case STATE_HEADER_BIT_END:
+		if (!is_transition(&ev, &dev->raw->prev_ev))
+			break;
+
+		if (data->count == RC6_HEADER_NBITS)
+			data->state = STATE_TOGGLE_START;
+		else
+			data->state = STATE_HEADER_BIT_START;
+
+		decrease_duration(&ev, RC6_BIT_END);
+		goto again;
+
+	case STATE_TOGGLE_START:
+		if (!eq_margin(ev.duration, RC6_TOGGLE_START, RC6_UNIT / 2))
+			break;
+
+		data->toggle = ev.pulse;
+		data->state = STATE_TOGGLE_END;
+		return 0;
+
+	case STATE_TOGGLE_END:
+		if (!is_transition(&ev, &dev->raw->prev_ev) ||
+		    !geq_margin(ev.duration, RC6_TOGGLE_END, RC6_UNIT / 2))
+			break;
+
+		if (!(data->header & RC6_STARTBIT_MASK)) {
+			IR_dprintk(1, "RC6 invalid start bit\n");
+			break;
+		}
+
+		data->state = STATE_BODY_BIT_START;
+		decrease_duration(&ev, RC6_TOGGLE_END);
+		data->count = 0;
+
+		switch (rc6_mode(data)) {
+		case RC6_MODE_0:
+			data->wanted_bits = RC6_0_NBITS;
+			break;
+		case RC6_MODE_6A:
+			/* This might look weird, but we basically
+			   check the value of the first body bit to
+			   determine the number of bits in mode 6A */
+			if ((!ev.pulse && !geq_margin(ev.duration, RC6_UNIT, RC6_UNIT / 2)) ||
+			    geq_margin(ev.duration, RC6_UNIT, RC6_UNIT / 2))
+				data->wanted_bits = RC6_6A_LARGE_NBITS;
+			else
+				data->wanted_bits = RC6_6A_SMALL_NBITS;
+			break;
+		default:
+			IR_dprintk(1, "RC6 unknown mode\n");
+			goto out;
+		}
+		goto again;
+
+	case STATE_BODY_BIT_START:
+		if (!eq_margin(ev.duration, RC6_BIT_START, RC6_UNIT / 2))
+			break;
+
+		data->body <<= 1;
+		if (ev.pulse)
+			data->body |= 1;
+		data->count++;
+		data->state = STATE_BODY_BIT_END;
+		return 0;
+
+	case STATE_BODY_BIT_END:
+		if (!is_transition(&ev, &dev->raw->prev_ev))
+			break;
+
+		if (data->count == data->wanted_bits)
+			data->state = STATE_FINISHED;
+		else
+			data->state = STATE_BODY_BIT_START;
+
+		decrease_duration(&ev, RC6_BIT_END);
+		goto again;
+
+	case STATE_FINISHED:
+		if (ev.pulse)
+			break;
+
+		switch (rc6_mode(data)) {
+		case RC6_MODE_0:
+			scancode = data->body & 0xffff;
+			toggle = data->toggle;
+			IR_dprintk(1, "RC6(0) scancode 0x%04x (toggle: %u)\n",
+				   scancode, toggle);
+			break;
+		case RC6_MODE_6A:
+			if (data->wanted_bits == RC6_6A_LARGE_NBITS) {
+				toggle = data->body & RC6_6A_MCE_TOGGLE_MASK ? 1 : 0;
+				scancode = data->body & ~RC6_6A_MCE_TOGGLE_MASK;
+			} else {
+				toggle = 0;
+				scancode = data->body & 0xffffff;
+			}
+
+			IR_dprintk(1, "RC6(6A) scancode 0x%08x (toggle: %u)\n",
+				   scancode, toggle);
+			break;
+		default:
+			IR_dprintk(1, "RC6 unknown mode\n");
+			goto out;
+		}
+
+		rc_keydown(dev, scancode, toggle);
+		data->state = STATE_INACTIVE;
+		return 0;
+	}
+
+out:
+	IR_dprintk(1, "RC6 decode failed at state %i (%uus %s)\n",
+		   data->state, TO_US(ev.duration), TO_STR(ev.pulse));
+	data->state = STATE_INACTIVE;
+	return -EINVAL;
+}
+
+static struct ir_raw_handler rc6_handler = {
+	.protocols	= RC_TYPE_RC6,
+	.decode		= ir_rc6_decode,
+};
+
+static int __init ir_rc6_decode_init(void)
+{
+	ir_raw_handler_register(&rc6_handler);
+
+	printk(KERN_INFO "IR RC6 protocol handler initialized\n");
+	return 0;
+}
+
+static void __exit ir_rc6_decode_exit(void)
+{
+	ir_raw_handler_unregister(&rc6_handler);
+}
+
+module_init(ir_rc6_decode_init);
+module_exit(ir_rc6_decode_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("David Härdeman <david@hardeman.nu>");
+MODULE_DESCRIPTION("RC6 IR protocol decoder");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/ir-sony-decoder.c linux-libre-2.6.38-gnu1/drivers/media/rc/ir-sony-decoder.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/ir-sony-decoder.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/ir-sony-decoder.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,181 @@
+/* ir-sony-decoder.c - handle Sony IR Pulse/Space protocol
+ *
+ * Copyright (C) 2010 by David Härdeman <david@hardeman.nu>
+ *
+ * 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.
+ */
+
+#include <linux/bitrev.h>
+#include "rc-core-priv.h"
+
+#define SONY_UNIT		600000 /* ns */
+#define SONY_HEADER_PULSE	(4 * SONY_UNIT)
+#define	SONY_HEADER_SPACE	(1 * SONY_UNIT)
+#define SONY_BIT_0_PULSE	(1 * SONY_UNIT)
+#define SONY_BIT_1_PULSE	(2 * SONY_UNIT)
+#define SONY_BIT_SPACE		(1 * SONY_UNIT)
+#define SONY_TRAILER_SPACE	(10 * SONY_UNIT) /* minimum */
+
+enum sony_state {
+	STATE_INACTIVE,
+	STATE_HEADER_SPACE,
+	STATE_BIT_PULSE,
+	STATE_BIT_SPACE,
+	STATE_FINISHED,
+};
+
+/**
+ * ir_sony_decode() - Decode one Sony pulse or space
+ * @dev:	the struct rc_dev descriptor of the device
+ * @ev:         the struct ir_raw_event descriptor of the pulse/space
+ *
+ * This function returns -EINVAL if the pulse violates the state machine
+ */
+static int ir_sony_decode(struct rc_dev *dev, struct ir_raw_event ev)
+{
+	struct sony_dec *data = &dev->raw->sony;
+	u32 scancode;
+	u8 device, subdevice, function;
+
+	if (!(dev->raw->enabled_protocols & RC_TYPE_SONY))
+		return 0;
+
+	if (!is_timing_event(ev)) {
+		if (ev.reset)
+			data->state = STATE_INACTIVE;
+		return 0;
+	}
+
+	if (!geq_margin(ev.duration, SONY_UNIT, SONY_UNIT / 2))
+		goto out;
+
+	IR_dprintk(2, "Sony decode started at state %d (%uus %s)\n",
+		   data->state, TO_US(ev.duration), TO_STR(ev.pulse));
+
+	switch (data->state) {
+
+	case STATE_INACTIVE:
+		if (!ev.pulse)
+			break;
+
+		if (!eq_margin(ev.duration, SONY_HEADER_PULSE, SONY_UNIT / 2))
+			break;
+
+		data->count = 0;
+		data->state = STATE_HEADER_SPACE;
+		return 0;
+
+	case STATE_HEADER_SPACE:
+		if (ev.pulse)
+			break;
+
+		if (!eq_margin(ev.duration, SONY_HEADER_SPACE, SONY_UNIT / 2))
+			break;
+
+		data->state = STATE_BIT_PULSE;
+		return 0;
+
+	case STATE_BIT_PULSE:
+		if (!ev.pulse)
+			break;
+
+		data->bits <<= 1;
+		if (eq_margin(ev.duration, SONY_BIT_1_PULSE, SONY_UNIT / 2))
+			data->bits |= 1;
+		else if (!eq_margin(ev.duration, SONY_BIT_0_PULSE, SONY_UNIT / 2))
+			break;
+
+		data->count++;
+		data->state = STATE_BIT_SPACE;
+		return 0;
+
+	case STATE_BIT_SPACE:
+		if (ev.pulse)
+			break;
+
+		if (!geq_margin(ev.duration, SONY_BIT_SPACE, SONY_UNIT / 2))
+			break;
+
+		decrease_duration(&ev, SONY_BIT_SPACE);
+
+		if (!geq_margin(ev.duration, SONY_UNIT, SONY_UNIT / 2)) {
+			data->state = STATE_BIT_PULSE;
+			return 0;
+		}
+
+		data->state = STATE_FINISHED;
+		/* Fall through */
+
+	case STATE_FINISHED:
+		if (ev.pulse)
+			break;
+
+		if (!geq_margin(ev.duration, SONY_TRAILER_SPACE, SONY_UNIT / 2))
+			break;
+
+		switch (data->count) {
+		case 12:
+			device    = bitrev8((data->bits <<  3) & 0xF8);
+			subdevice = 0;
+			function  = bitrev8((data->bits >>  4) & 0xFE);
+			break;
+		case 15:
+			device    = bitrev8((data->bits >>  0) & 0xFF);
+			subdevice = 0;
+			function  = bitrev8((data->bits >>  7) & 0xFD);
+			break;
+		case 20:
+			device    = bitrev8((data->bits >>  5) & 0xF8);
+			subdevice = bitrev8((data->bits >>  0) & 0xFF);
+			function  = bitrev8((data->bits >> 12) & 0xFE);
+			break;
+		default:
+			IR_dprintk(1, "Sony invalid bitcount %u\n", data->count);
+			goto out;
+		}
+
+		scancode = device << 16 | subdevice << 8 | function;
+		IR_dprintk(1, "Sony(%u) scancode 0x%05x\n", data->count, scancode);
+		rc_keydown(dev, scancode, 0);
+		data->state = STATE_INACTIVE;
+		return 0;
+	}
+
+out:
+	IR_dprintk(1, "Sony decode failed at state %d (%uus %s)\n",
+		   data->state, TO_US(ev.duration), TO_STR(ev.pulse));
+	data->state = STATE_INACTIVE;
+	return -EINVAL;
+}
+
+static struct ir_raw_handler sony_handler = {
+	.protocols	= RC_TYPE_SONY,
+	.decode		= ir_sony_decode,
+};
+
+static int __init ir_sony_decode_init(void)
+{
+	ir_raw_handler_register(&sony_handler);
+
+	printk(KERN_INFO "IR Sony protocol handler initialized\n");
+	return 0;
+}
+
+static void __exit ir_sony_decode_exit(void)
+{
+	ir_raw_handler_unregister(&sony_handler);
+}
+
+module_init(ir_sony_decode_init);
+module_exit(ir_sony_decode_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("David Härdeman <david@hardeman.nu>");
+MODULE_DESCRIPTION("Sony IR protocol decoder");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/Kconfig linux-libre-2.6.38-gnu1/drivers/media/rc/Kconfig
--- linux-libre-2.6.37-gnu1/drivers/media/rc/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,193 @@
+menuconfig RC_CORE
+	tristate "Remote Controller adapters"
+	depends on INPUT
+	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.
+
+	  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
+	  compile the driver for your adapter.
+
+if RC_CORE
+
+config LIRC
+	tristate
+	default y
+
+	---help---
+	   Enable this option to build the Linux Infrared Remote
+	   Control (LIRC) core device interface driver. The LIRC
+	   interface passes raw IR to and from userspace, where the
+	   LIRC daemon handles protocol decoding for IR reception and
+	   encoding for IR transmitting (aka "blasting").
+
+source "drivers/media/rc/keymaps/Kconfig"
+
+config IR_NEC_DECODER
+	tristate "Enable IR raw decoder for the NEC protocol"
+	depends on RC_CORE
+	select BITREVERSE
+	default y
+
+	---help---
+	   Enable this option if you have IR with NEC protocol, and
+	   if the IR is decoded in software
+
+config IR_RC5_DECODER
+	tristate "Enable IR raw decoder for the RC-5 protocol"
+	depends on RC_CORE
+	select BITREVERSE
+	default y
+
+	---help---
+	   Enable this option if you have IR with RC-5 protocol, and
+	   if the IR is decoded in software
+
+config IR_RC6_DECODER
+	tristate "Enable IR raw decoder for the RC6 protocol"
+	depends on RC_CORE
+	select BITREVERSE
+	default y
+
+	---help---
+	   Enable this option if you have an infrared remote control which
+	   uses the RC6 protocol, and you need software decoding support.
+
+config IR_JVC_DECODER
+	tristate "Enable IR raw decoder for the JVC protocol"
+	depends on RC_CORE
+	select BITREVERSE
+	default y
+
+	---help---
+	   Enable this option if you have an infrared remote control which
+	   uses the JVC protocol, and you need software decoding support.
+
+config IR_SONY_DECODER
+	tristate "Enable IR raw decoder for the Sony protocol"
+	depends on RC_CORE
+	default y
+
+	---help---
+	   Enable this option if you have an infrared remote control which
+	   uses the Sony protocol, and you need software decoding support.
+
+config IR_RC5_SZ_DECODER
+	tristate "Enable IR raw decoder for the RC-5 (streamzap) protocol"
+	depends on RC_CORE
+	select BITREVERSE
+	default y
+
+	---help---
+	   Enable this option if you have IR with RC-5 (streamzap) protocol,
+	   and if the IR is decoded in software. (The Streamzap PC Remote
+	   uses an IR protocol that is almost standard RC-5, but not quite,
+	   as it uses an additional bit).
+
+config IR_LIRC_CODEC
+	tristate "Enable IR to LIRC bridge"
+	depends on RC_CORE
+	depends on LIRC
+	default y
+
+	---help---
+	   Enable this option to pass raw IR to and from userspace via
+	   the LIRC interface.
+
+config IR_ENE
+	tristate "ENE eHome Receiver/Transceiver (pnp id: ENE0100/ENE02xxx)"
+	depends on PNP
+	depends on RC_CORE
+	---help---
+	   Say Y here to enable support for integrated infrared receiver
+	   /transceiver made by ENE.
+
+	   You can see if you have it by looking at lspnp output.
+	   Output should include ENE0100 ENE0200 or something similar.
+
+	   To compile this driver as a module, choose M here: the
+	   module will be called ene_ir.
+
+config IR_IMON
+	tristate "SoundGraph iMON Receiver and Display"
+	depends on USB_ARCH_HAS_HCD
+	depends on RC_CORE
+	select USB
+	---help---
+	   Say Y here if you want to use a SoundGraph iMON (aka Antec Veris)
+	   IR Receiver and/or LCD/VFD/VGA display.
+
+	   To compile this driver as a module, choose M here: the
+	   module will be called imon.
+
+config IR_MCEUSB
+	tristate "Windows Media Center Ed. eHome Infrared Transceiver"
+	depends on USB_ARCH_HAS_HCD
+	depends on RC_CORE
+	select USB
+	---help---
+	   Say Y here if you want to use a Windows Media Center Edition
+	   eHome Infrared Transceiver.
+
+	   To compile this driver as a module, choose M here: the
+	   module will be called mceusb.
+
+config IR_NUVOTON
+	tristate "Nuvoton w836x7hg Consumer Infrared Transceiver"
+	depends on PNP
+	depends on RC_CORE
+	---help---
+	   Say Y here to enable support for integrated infrared receiver
+	   /transciever made by Nuvoton (formerly Winbond). This chip is
+	   found in the ASRock ION 330HT, as well as assorted Intel
+	   DP55-series motherboards (and of course, possibly others).
+
+	   To compile this driver as a module, choose M here: the
+	   module will be called nuvoton-cir.
+
+config IR_STREAMZAP
+	tristate "Streamzap PC Remote IR Receiver"
+	depends on USB_ARCH_HAS_HCD
+	depends on RC_CORE
+	select USB
+	---help---
+	   Say Y here if you want to use a Streamzap PC Remote
+	   Infrared Receiver.
+
+	   To compile this driver as a module, choose M here: the
+	   module will be called streamzap.
+
+config IR_WINBOND_CIR
+        tristate "Winbond IR remote control"
+        depends on X86 && PNP
+	depends on RC_CORE
+        select NEW_LEDS
+        select LEDS_CLASS
+        select LEDS_TRIGGERS
+        select BITREVERSE
+	---help---
+           Say Y here if you want to use the IR remote functionality found
+           in some Winbond SuperI/O chips. Currently only the WPCD376I
+           chip is supported (included in some Intel Media series
+	   motherboards).
+
+           To compile this driver as a module, choose M here: the module will
+	   be called winbond_cir.
+
+config RC_LOOPBACK
+	tristate "Remote Control Loopback Driver"
+	depends on RC_CORE
+	---help---
+	   Say Y here if you want support for the remote control loopback
+	   driver which allows TX data to be sent back as RX data.
+	   This is mostly useful for debugging purposes.
+
+	   If you're not sure, select N here.
+
+	   To compile this driver as a module, choose M here: the module will
+	   be called rc_loopback.
+
+endif #RC_CORE
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/Kconfig linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/Kconfig
--- linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,15 @@
+config RC_MAP
+	tristate "Compile Remote Controller keymap modules"
+	depends on RC_CORE
+	default y
+
+	---help---
+	   This option enables the compilation of lots of Remote
+	   Controller tables. They are short tables, but if you
+	   don't use a remote controller, or prefer to load the
+	   tables on userspace, you should disable it.
+
+	   The ir-keytable program, available at v4l-utils package
+	   provide the tool and the same RC maps for load from
+	   userspace. Its available at
+			http://git.linuxtv.org/v4l-utils
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/Makefile linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/Makefile
--- linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,88 @@
+obj-$(CONFIG_RC_MAP) += rc-adstech-dvb-t-pci.o \
+			rc-alink-dtu-m.o \
+			rc-anysee.o \
+			rc-apac-viewcomp.o \
+			rc-asus-pc39.o \
+			rc-ati-tv-wonder-hd-600.o \
+			rc-avermedia-a16d.o \
+			rc-avermedia.o \
+			rc-avermedia-cardbus.o \
+			rc-avermedia-dvbt.o \
+			rc-avermedia-m135a.o \
+			rc-avermedia-m733a-rm-k6.o \
+			rc-avermedia-rm-ks.o \
+			rc-avertv-303.o \
+			rc-azurewave-ad-tu700.o \
+			rc-behold.o \
+			rc-behold-columbus.o \
+			rc-budget-ci-old.o \
+			rc-cinergy-1400.o \
+			rc-cinergy.o \
+			rc-dib0700-nec.o \
+			rc-dib0700-rc5.o \
+			rc-digitalnow-tinytwin.o \
+			rc-digittrade.o \
+			rc-dm1105-nec.o \
+			rc-dntv-live-dvb-t.o \
+			rc-dntv-live-dvbt-pro.o \
+			rc-em-terratec.o \
+			rc-encore-enltv2.o \
+			rc-encore-enltv.o \
+			rc-encore-enltv-fm53.o \
+			rc-evga-indtube.o \
+			rc-eztv.o \
+			rc-flydvb.o \
+			rc-flyvideo.o \
+			rc-fusionhdtv-mce.o \
+			rc-gadmei-rm008z.o \
+			rc-genius-tvgo-a11mce.o \
+			rc-gotview7135.o \
+			rc-hauppauge-new.o \
+			rc-imon-mce.o \
+			rc-imon-pad.o \
+			rc-iodata-bctv7e.o \
+			rc-kaiomy.o \
+			rc-kworld-315u.o \
+			rc-kworld-plus-tv-analog.o \
+			rc-leadtek-y04g0051.o \
+			rc-lirc.o \
+			rc-lme2510.o \
+			rc-manli.o \
+			rc-msi-digivox-ii.o \
+			rc-msi-digivox-iii.o \
+			rc-msi-tvanywhere.o \
+			rc-msi-tvanywhere-plus.o \
+			rc-nebula.o \
+			rc-nec-terratec-cinergy-xs.o \
+			rc-norwood.o \
+			rc-npgtech.o \
+			rc-pctv-sedna.o \
+			rc-pinnacle-color.o \
+			rc-pinnacle-grey.o \
+			rc-pinnacle-pctv-hd.o \
+			rc-pixelview.o \
+			rc-pixelview-mk12.o \
+			rc-pixelview-002t.o \
+			rc-pixelview-new.o \
+			rc-powercolor-real-angel.o \
+			rc-proteus-2309.o \
+			rc-purpletv.o \
+			rc-pv951.o \
+			rc-rc5-hauppauge-new.o \
+			rc-rc5-tv.o \
+			rc-rc6-mce.o \
+			rc-real-audio-220-32-keys.o \
+			rc-streamzap.o \
+			rc-tbs-nec.o \
+			rc-terratec-cinergy-xs.o \
+			rc-terratec-slim.o \
+			rc-tevii-nec.o \
+			rc-total-media-in-hand.o \
+			rc-trekstor.o \
+			rc-tt-1500.o \
+			rc-twinhan1027.o \
+			rc-videomate-m1f.o \
+			rc-videomate-s350.o \
+			rc-videomate-tv-pvr.o \
+			rc-winfast.o \
+			rc-winfast-usbii-deluxe.o
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-adstech-dvb-t-pci.c linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-adstech-dvb-t-pci.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-adstech-dvb-t-pci.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-adstech-dvb-t-pci.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,89 @@
+/* adstech-dvb-t-pci.h - Keytable for adstech_dvb_t_pci Remote Controller
+ *
+ * keymap imported from ir-keymaps.c
+ *
+ * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
+
+/* ADS Tech Instant TV DVB-T PCI Remote */
+
+static struct rc_map_table adstech_dvb_t_pci[] = {
+	/* Keys 0 to 9 */
+	{ 0x4d, KEY_0 },
+	{ 0x57, KEY_1 },
+	{ 0x4f, KEY_2 },
+	{ 0x53, KEY_3 },
+	{ 0x56, KEY_4 },
+	{ 0x4e, KEY_5 },
+	{ 0x5e, KEY_6 },
+	{ 0x54, KEY_7 },
+	{ 0x4c, KEY_8 },
+	{ 0x5c, KEY_9 },
+
+	{ 0x5b, KEY_POWER },
+	{ 0x5f, KEY_MUTE },
+	{ 0x55, KEY_GOTO },
+	{ 0x5d, KEY_SEARCH },
+	{ 0x17, KEY_EPG },		/* Guide */
+	{ 0x1f, KEY_MENU },
+	{ 0x0f, KEY_UP },
+	{ 0x46, KEY_DOWN },
+	{ 0x16, KEY_LEFT },
+	{ 0x1e, KEY_RIGHT },
+	{ 0x0e, KEY_SELECT },		/* Enter */
+	{ 0x5a, KEY_INFO },
+	{ 0x52, KEY_EXIT },
+	{ 0x59, KEY_PREVIOUS },
+	{ 0x51, KEY_NEXT },
+	{ 0x58, KEY_REWIND },
+	{ 0x50, KEY_FORWARD },
+	{ 0x44, KEY_PLAYPAUSE },
+	{ 0x07, KEY_STOP },
+	{ 0x1b, KEY_RECORD },
+	{ 0x13, KEY_TUNER },		/* Live */
+	{ 0x0a, KEY_A },
+	{ 0x12, KEY_B },
+	{ 0x03, KEY_PROG1 },		/* 1 */
+	{ 0x01, KEY_PROG2 },		/* 2 */
+	{ 0x00, KEY_PROG3 },		/* 3 */
+	{ 0x06, KEY_DVD },
+	{ 0x48, KEY_AUX },		/* Photo */
+	{ 0x40, KEY_VIDEO },
+	{ 0x19, KEY_AUDIO },		/* Music */
+	{ 0x0b, KEY_CHANNELUP },
+	{ 0x08, KEY_CHANNELDOWN },
+	{ 0x15, KEY_VOLUMEUP },
+	{ 0x1c, KEY_VOLUMEDOWN },
+};
+
+static struct rc_map_list adstech_dvb_t_pci_map = {
+	.map = {
+		.scan    = adstech_dvb_t_pci,
+		.size    = ARRAY_SIZE(adstech_dvb_t_pci),
+		.rc_type = RC_TYPE_UNKNOWN,	/* Legacy IR type */
+		.name    = RC_MAP_ADSTECH_DVB_T_PCI,
+	}
+};
+
+static int __init init_rc_map_adstech_dvb_t_pci(void)
+{
+	return rc_map_register(&adstech_dvb_t_pci_map);
+}
+
+static void __exit exit_rc_map_adstech_dvb_t_pci(void)
+{
+	rc_map_unregister(&adstech_dvb_t_pci_map);
+}
+
+module_init(init_rc_map_adstech_dvb_t_pci)
+module_exit(exit_rc_map_adstech_dvb_t_pci)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-alink-dtu-m.c linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-alink-dtu-m.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-alink-dtu-m.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-alink-dtu-m.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,68 @@
+/*
+ * A-Link DTU(m) remote controller keytable
+ *
+ * Copyright (C) 2010 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 <media/rc-map.h>
+
+/* A-Link DTU(m) slim remote, 6 rows, 3 columns. */
+static struct rc_map_table alink_dtu_m[] = {
+	{ 0x0800, KEY_VOLUMEUP },
+	{ 0x0801, KEY_1 },
+	{ 0x0802, KEY_3 },
+	{ 0x0803, KEY_7 },
+	{ 0x0804, KEY_9 },
+	{ 0x0805, KEY_NEW },             /* symbol: PIP */
+	{ 0x0806, KEY_0 },
+	{ 0x0807, KEY_CHANNEL },         /* JUMP */
+	{ 0x080d, KEY_5 },
+	{ 0x080f, KEY_2 },
+	{ 0x0812, KEY_POWER2 },
+	{ 0x0814, KEY_CHANNELUP },
+	{ 0x0816, KEY_VOLUMEDOWN },
+	{ 0x0818, KEY_6 },
+	{ 0x081a, KEY_MUTE },
+	{ 0x081b, KEY_8 },
+	{ 0x081c, KEY_4 },
+	{ 0x081d, KEY_CHANNELDOWN },
+};
+
+static struct rc_map_list alink_dtu_m_map = {
+	.map = {
+		.scan    = alink_dtu_m,
+		.size    = ARRAY_SIZE(alink_dtu_m),
+		.rc_type = RC_TYPE_NEC,
+		.name    = RC_MAP_ALINK_DTU_M,
+	}
+};
+
+static int __init init_rc_map_alink_dtu_m(void)
+{
+	return rc_map_register(&alink_dtu_m_map);
+}
+
+static void __exit exit_rc_map_alink_dtu_m(void)
+{
+	rc_map_unregister(&alink_dtu_m_map);
+}
+
+module_init(init_rc_map_alink_dtu_m)
+module_exit(exit_rc_map_alink_dtu_m)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-anysee.c linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-anysee.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-anysee.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-anysee.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,93 @@
+/*
+ * Anysee remote controller keytable
+ *
+ * Copyright (C) 2010 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 <media/rc-map.h>
+
+static struct rc_map_table anysee[] = {
+	{ 0x0800, KEY_0 },
+	{ 0x0801, KEY_1 },
+	{ 0x0802, KEY_2 },
+	{ 0x0803, KEY_3 },
+	{ 0x0804, KEY_4 },
+	{ 0x0805, KEY_5 },
+	{ 0x0806, KEY_6 },
+	{ 0x0807, KEY_7 },
+	{ 0x0808, KEY_8 },
+	{ 0x0809, KEY_9 },
+	{ 0x080a, KEY_POWER2 },          /* [red power button] */
+	{ 0x080b, KEY_VIDEO },           /* [*] MODE */
+	{ 0x080c, KEY_CHANNEL },         /* [symbol counterclockwise arrow] */
+	{ 0x080d, KEY_NEXT },            /* [>>|] */
+	{ 0x080e, KEY_MENU },            /* MENU */
+	{ 0x080f, KEY_EPG },             /* [EPG] */
+	{ 0x0810, KEY_CLEAR },           /* EXIT */
+	{ 0x0811, KEY_CHANNELUP },
+	{ 0x0812, KEY_VOLUMEDOWN },
+	{ 0x0813, KEY_VOLUMEUP },
+	{ 0x0814, KEY_CHANNELDOWN },
+	{ 0x0815, KEY_OK },
+	{ 0x0816, KEY_RADIO },           /* [symbol TV/radio] */
+	{ 0x0817, KEY_INFO },            /* [i] */
+	{ 0x0818, KEY_PREVIOUS },        /* [|<<] */
+	{ 0x0819, KEY_FAVORITES },       /* FAV. */
+	{ 0x081a, KEY_SUBTITLE },        /* Subtitle */
+	{ 0x081b, KEY_CAMERA },          /* [symbol camera] */
+	{ 0x081c, KEY_YELLOW },
+	{ 0x081d, KEY_RED },
+	{ 0x081e, KEY_LANGUAGE },        /* [symbol Second Audio Program] */
+	{ 0x081f, KEY_GREEN },
+	{ 0x0820, KEY_SLEEP },           /* Sleep */
+	{ 0x0821, KEY_SCREEN },          /* 16:9 / 4:3 */
+	{ 0x0822, KEY_ZOOM },            /* SIZE */
+	{ 0x0824, KEY_FN },              /* [F1] */
+	{ 0x0825, KEY_FN },              /* [F2] */
+	{ 0x0842, KEY_MUTE },            /* symbol mute */
+	{ 0x0844, KEY_BLUE },
+	{ 0x0847, KEY_TEXT },            /* TEXT */
+	{ 0x0848, KEY_STOP },
+	{ 0x0849, KEY_RECORD },
+	{ 0x0850, KEY_PLAY },
+	{ 0x0851, KEY_PAUSE },
+};
+
+static struct rc_map_list anysee_map = {
+	.map = {
+		.scan    = anysee,
+		.size    = ARRAY_SIZE(anysee),
+		.rc_type = RC_TYPE_NEC,
+		.name    = RC_MAP_ANYSEE,
+	}
+};
+
+static int __init init_rc_map_anysee(void)
+{
+	return rc_map_register(&anysee_map);
+}
+
+static void __exit exit_rc_map_anysee(void)
+{
+	rc_map_unregister(&anysee_map);
+}
+
+module_init(init_rc_map_anysee)
+module_exit(exit_rc_map_anysee)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-apac-viewcomp.c linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-apac-viewcomp.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-apac-viewcomp.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-apac-viewcomp.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,80 @@
+/* apac-viewcomp.h - Keytable for apac_viewcomp Remote Controller
+ *
+ * keymap imported from ir-keymaps.c
+ *
+ * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
+
+/* Attila Kondoros <attila.kondoros@chello.hu> */
+
+static struct rc_map_table apac_viewcomp[] = {
+
+	{ 0x01, KEY_1 },
+	{ 0x02, KEY_2 },
+	{ 0x03, KEY_3 },
+	{ 0x04, KEY_4 },
+	{ 0x05, KEY_5 },
+	{ 0x06, KEY_6 },
+	{ 0x07, KEY_7 },
+	{ 0x08, KEY_8 },
+	{ 0x09, KEY_9 },
+	{ 0x00, KEY_0 },
+	{ 0x17, KEY_LAST },		/* +100 */
+	{ 0x0a, KEY_LIST },		/* recall */
+
+
+	{ 0x1c, KEY_TUNER },		/* TV/FM */
+	{ 0x15, KEY_SEARCH },		/* scan */
+	{ 0x12, KEY_POWER },		/* power */
+	{ 0x1f, KEY_VOLUMEDOWN },	/* vol up */
+	{ 0x1b, KEY_VOLUMEUP },		/* vol down */
+	{ 0x1e, KEY_CHANNELDOWN },	/* chn up */
+	{ 0x1a, KEY_CHANNELUP },	/* chn down */
+
+	{ 0x11, KEY_VIDEO },		/* video */
+	{ 0x0f, KEY_ZOOM },		/* full screen */
+	{ 0x13, KEY_MUTE },		/* mute/unmute */
+	{ 0x10, KEY_TEXT },		/* min */
+
+	{ 0x0d, KEY_STOP },		/* freeze */
+	{ 0x0e, KEY_RECORD },		/* record */
+	{ 0x1d, KEY_PLAYPAUSE },	/* stop */
+	{ 0x19, KEY_PLAY },		/* play */
+
+	{ 0x16, KEY_GOTO },		/* osd */
+	{ 0x14, KEY_REFRESH },		/* default */
+	{ 0x0c, KEY_KPPLUS },		/* fine tune >>>> */
+	{ 0x18, KEY_KPMINUS },		/* fine tune <<<< */
+};
+
+static struct rc_map_list apac_viewcomp_map = {
+	.map = {
+		.scan    = apac_viewcomp,
+		.size    = ARRAY_SIZE(apac_viewcomp),
+		.rc_type = RC_TYPE_UNKNOWN,	/* Legacy IR type */
+		.name    = RC_MAP_APAC_VIEWCOMP,
+	}
+};
+
+static int __init init_rc_map_apac_viewcomp(void)
+{
+	return rc_map_register(&apac_viewcomp_map);
+}
+
+static void __exit exit_rc_map_apac_viewcomp(void)
+{
+	rc_map_unregister(&apac_viewcomp_map);
+}
+
+module_init(init_rc_map_apac_viewcomp)
+module_exit(exit_rc_map_apac_viewcomp)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-asus-pc39.c linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-asus-pc39.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-asus-pc39.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-asus-pc39.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,91 @@
+/* asus-pc39.h - Keytable for asus_pc39 Remote Controller
+ *
+ * keymap imported from ir-keymaps.c
+ *
+ * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
+
+/*
+ * Marc Fargas <telenieko@telenieko.com>
+ * this is the remote control that comes with the asus p7131
+ * which has a label saying is "Model PC-39"
+ */
+
+static struct rc_map_table asus_pc39[] = {
+	/* Keys 0 to 9 */
+	{ 0x082a, KEY_0 },
+	{ 0x0816, KEY_1 },
+	{ 0x0812, KEY_2 },
+	{ 0x0814, KEY_3 },
+	{ 0x0836, KEY_4 },
+	{ 0x0832, KEY_5 },
+	{ 0x0834, KEY_6 },
+	{ 0x080e, KEY_7 },
+	{ 0x080a, KEY_8 },
+	{ 0x080c, KEY_9 },
+
+	{ 0x0801, KEY_RADIO },		/* radio */
+	{ 0x083c, KEY_MENU },		/* dvd/menu */
+	{ 0x0815, KEY_VOLUMEUP },
+	{ 0x0826, KEY_VOLUMEDOWN },
+	{ 0x0808, KEY_UP },
+	{ 0x0804, KEY_DOWN },
+	{ 0x0818, KEY_LEFT },
+	{ 0x0810, KEY_RIGHT },
+	{ 0x081a, KEY_VIDEO },		/* video */
+	{ 0x0806, KEY_AUDIO },		/* music */
+
+	{ 0x081e, KEY_TV },		/* tv */
+	{ 0x0822, KEY_EXIT },		/* back */
+	{ 0x0835, KEY_CHANNELUP },	/* channel / program + */
+	{ 0x0824, KEY_CHANNELDOWN },	/* channel / program - */
+	{ 0x0825, KEY_ENTER },		/* enter */
+
+	{ 0x0839, KEY_PAUSE },		/* play/pause */
+	{ 0x0821, KEY_PREVIOUS },		/* rew */
+	{ 0x0819, KEY_NEXT },		/* forward */
+	{ 0x0831, KEY_REWIND },		/* backward << */
+	{ 0x0805, KEY_FASTFORWARD },	/* forward >> */
+	{ 0x0809, KEY_STOP },
+	{ 0x0811, KEY_RECORD },		/* recording */
+	{ 0x0829, KEY_POWER },		/* the button that reads "close" */
+
+	{ 0x082e, KEY_ZOOM },		/* full screen */
+	{ 0x082c, KEY_MACRO },		/* recall */
+	{ 0x081c, KEY_HOME },		/* home */
+	{ 0x083a, KEY_PVR },		/* picture */
+	{ 0x0802, KEY_MUTE },		/* mute */
+	{ 0x083e, KEY_DVD },		/* dvd */
+};
+
+static struct rc_map_list asus_pc39_map = {
+	.map = {
+		.scan    = asus_pc39,
+		.size    = ARRAY_SIZE(asus_pc39),
+		.rc_type = RC_TYPE_RC5,
+		.name    = RC_MAP_ASUS_PC39,
+	}
+};
+
+static int __init init_rc_map_asus_pc39(void)
+{
+	return rc_map_register(&asus_pc39_map);
+}
+
+static void __exit exit_rc_map_asus_pc39(void)
+{
+	rc_map_unregister(&asus_pc39_map);
+}
+
+module_init(init_rc_map_asus_pc39)
+module_exit(exit_rc_map_asus_pc39)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-ati-tv-wonder-hd-600.c linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-ati-tv-wonder-hd-600.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-ati-tv-wonder-hd-600.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-ati-tv-wonder-hd-600.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,69 @@
+/* ati-tv-wonder-hd-600.h - Keytable for ati_tv_wonder_hd_600 Remote Controller
+ *
+ * keymap imported from ir-keymaps.c
+ *
+ * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
+
+/* ATI TV Wonder HD 600 USB
+   Devin Heitmueller <devin.heitmueller@gmail.com>
+ */
+
+static struct rc_map_table ati_tv_wonder_hd_600[] = {
+	{ 0x00, KEY_RECORD},		/* Row 1 */
+	{ 0x01, KEY_PLAYPAUSE},
+	{ 0x02, KEY_STOP},
+	{ 0x03, KEY_POWER},
+	{ 0x04, KEY_PREVIOUS},	/* Row 2 */
+	{ 0x05, KEY_REWIND},
+	{ 0x06, KEY_FORWARD},
+	{ 0x07, KEY_NEXT},
+	{ 0x08, KEY_EPG},		/* Row 3 */
+	{ 0x09, KEY_HOME},
+	{ 0x0a, KEY_MENU},
+	{ 0x0b, KEY_CHANNELUP},
+	{ 0x0c, KEY_BACK},		/* Row 4 */
+	{ 0x0d, KEY_UP},
+	{ 0x0e, KEY_INFO},
+	{ 0x0f, KEY_CHANNELDOWN},
+	{ 0x10, KEY_LEFT},		/* Row 5 */
+	{ 0x11, KEY_SELECT},
+	{ 0x12, KEY_RIGHT},
+	{ 0x13, KEY_VOLUMEUP},
+	{ 0x14, KEY_LAST},		/* Row 6 */
+	{ 0x15, KEY_DOWN},
+	{ 0x16, KEY_MUTE},
+	{ 0x17, KEY_VOLUMEDOWN},
+};
+
+static struct rc_map_list ati_tv_wonder_hd_600_map = {
+	.map = {
+		.scan    = ati_tv_wonder_hd_600,
+		.size    = ARRAY_SIZE(ati_tv_wonder_hd_600),
+		.rc_type = RC_TYPE_UNKNOWN,	/* Legacy IR type */
+		.name    = RC_MAP_ATI_TV_WONDER_HD_600,
+	}
+};
+
+static int __init init_rc_map_ati_tv_wonder_hd_600(void)
+{
+	return rc_map_register(&ati_tv_wonder_hd_600_map);
+}
+
+static void __exit exit_rc_map_ati_tv_wonder_hd_600(void)
+{
+	rc_map_unregister(&ati_tv_wonder_hd_600_map);
+}
+
+module_init(init_rc_map_ati_tv_wonder_hd_600)
+module_exit(exit_rc_map_ati_tv_wonder_hd_600)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-avermedia-a16d.c linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-avermedia-a16d.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-avermedia-a16d.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-avermedia-a16d.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,75 @@
+/* avermedia-a16d.h - Keytable for avermedia_a16d Remote Controller
+ *
+ * keymap imported from ir-keymaps.c
+ *
+ * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
+
+static struct rc_map_table avermedia_a16d[] = {
+	{ 0x20, KEY_LIST},
+	{ 0x00, KEY_POWER},
+	{ 0x28, KEY_1},
+	{ 0x18, KEY_2},
+	{ 0x38, KEY_3},
+	{ 0x24, KEY_4},
+	{ 0x14, KEY_5},
+	{ 0x34, KEY_6},
+	{ 0x2c, KEY_7},
+	{ 0x1c, KEY_8},
+	{ 0x3c, KEY_9},
+	{ 0x12, KEY_SUBTITLE},
+	{ 0x22, KEY_0},
+	{ 0x32, KEY_REWIND},
+	{ 0x3a, KEY_SHUFFLE},
+	{ 0x02, KEY_PRINT},
+	{ 0x11, KEY_CHANNELDOWN},
+	{ 0x31, KEY_CHANNELUP},
+	{ 0x0c, KEY_ZOOM},
+	{ 0x1e, KEY_VOLUMEDOWN},
+	{ 0x3e, KEY_VOLUMEUP},
+	{ 0x0a, KEY_MUTE},
+	{ 0x04, KEY_AUDIO},
+	{ 0x26, KEY_RECORD},
+	{ 0x06, KEY_PLAY},
+	{ 0x36, KEY_STOP},
+	{ 0x16, KEY_PAUSE},
+	{ 0x2e, KEY_REWIND},
+	{ 0x0e, KEY_FASTFORWARD},
+	{ 0x30, KEY_TEXT},
+	{ 0x21, KEY_GREEN},
+	{ 0x01, KEY_BLUE},
+	{ 0x08, KEY_EPG},
+	{ 0x2a, KEY_MENU},
+};
+
+static struct rc_map_list avermedia_a16d_map = {
+	.map = {
+		.scan    = avermedia_a16d,
+		.size    = ARRAY_SIZE(avermedia_a16d),
+		.rc_type = RC_TYPE_UNKNOWN,	/* Legacy IR type */
+		.name    = RC_MAP_AVERMEDIA_A16D,
+	}
+};
+
+static int __init init_rc_map_avermedia_a16d(void)
+{
+	return rc_map_register(&avermedia_a16d_map);
+}
+
+static void __exit exit_rc_map_avermedia_a16d(void)
+{
+	rc_map_unregister(&avermedia_a16d_map);
+}
+
+module_init(init_rc_map_avermedia_a16d)
+module_exit(exit_rc_map_avermedia_a16d)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-avermedia.c linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-avermedia.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-avermedia.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-avermedia.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,86 @@
+/* avermedia.h - Keytable for avermedia Remote Controller
+ *
+ * keymap imported from ir-keymaps.c
+ *
+ * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
+
+/* Alex Hermann <gaaf@gmx.net> */
+
+static struct rc_map_table avermedia[] = {
+	{ 0x28, KEY_1 },
+	{ 0x18, KEY_2 },
+	{ 0x38, KEY_3 },
+	{ 0x24, KEY_4 },
+	{ 0x14, KEY_5 },
+	{ 0x34, KEY_6 },
+	{ 0x2c, KEY_7 },
+	{ 0x1c, KEY_8 },
+	{ 0x3c, KEY_9 },
+	{ 0x22, KEY_0 },
+
+	{ 0x20, KEY_TV },		/* TV/FM */
+	{ 0x10, KEY_CD },		/* CD */
+	{ 0x30, KEY_TEXT },		/* TELETEXT */
+	{ 0x00, KEY_POWER },		/* POWER */
+
+	{ 0x08, KEY_VIDEO },		/* VIDEO */
+	{ 0x04, KEY_AUDIO },		/* AUDIO */
+	{ 0x0c, KEY_ZOOM },		/* FULL SCREEN */
+
+	{ 0x12, KEY_SUBTITLE },		/* DISPLAY */
+	{ 0x32, KEY_REWIND },		/* LOOP	*/
+	{ 0x02, KEY_PRINT },		/* PREVIEW */
+
+	{ 0x2a, KEY_SEARCH },		/* AUTOSCAN */
+	{ 0x1a, KEY_SLEEP },		/* FREEZE */
+	{ 0x3a, KEY_CAMERA },		/* SNAPSHOT */
+	{ 0x0a, KEY_MUTE },		/* MUTE */
+
+	{ 0x26, KEY_RECORD },		/* RECORD */
+	{ 0x16, KEY_PAUSE },		/* PAUSE */
+	{ 0x36, KEY_STOP },		/* STOP */
+	{ 0x06, KEY_PLAY },		/* PLAY */
+
+	{ 0x2e, KEY_RED },		/* RED */
+	{ 0x21, KEY_GREEN },		/* GREEN */
+	{ 0x0e, KEY_YELLOW },		/* YELLOW */
+	{ 0x01, KEY_BLUE },		/* BLUE */
+
+	{ 0x1e, KEY_VOLUMEDOWN },	/* VOLUME- */
+	{ 0x3e, KEY_VOLUMEUP },		/* VOLUME+ */
+	{ 0x11, KEY_CHANNELDOWN },	/* CHANNEL/PAGE- */
+	{ 0x31, KEY_CHANNELUP }		/* CHANNEL/PAGE+ */
+};
+
+static struct rc_map_list avermedia_map = {
+	.map = {
+		.scan    = avermedia,
+		.size    = ARRAY_SIZE(avermedia),
+		.rc_type = RC_TYPE_UNKNOWN,	/* Legacy IR type */
+		.name    = RC_MAP_AVERMEDIA,
+	}
+};
+
+static int __init init_rc_map_avermedia(void)
+{
+	return rc_map_register(&avermedia_map);
+}
+
+static void __exit exit_rc_map_avermedia(void)
+{
+	rc_map_unregister(&avermedia_map);
+}
+
+module_init(init_rc_map_avermedia)
+module_exit(exit_rc_map_avermedia)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-avermedia-cardbus.c linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-avermedia-cardbus.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-avermedia-cardbus.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-avermedia-cardbus.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,97 @@
+/* avermedia-cardbus.h - Keytable for avermedia_cardbus Remote Controller
+ *
+ * keymap imported from ir-keymaps.c
+ *
+ * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
+
+/* Oldrich Jedlicka <oldium.pro@seznam.cz> */
+
+static struct rc_map_table avermedia_cardbus[] = {
+	{ 0x00, KEY_POWER },
+	{ 0x01, KEY_TUNER },		/* TV/FM */
+	{ 0x03, KEY_TEXT },		/* Teletext */
+	{ 0x04, KEY_EPG },
+	{ 0x05, KEY_1 },
+	{ 0x06, KEY_2 },
+	{ 0x07, KEY_3 },
+	{ 0x08, KEY_AUDIO },
+	{ 0x09, KEY_4 },
+	{ 0x0a, KEY_5 },
+	{ 0x0b, KEY_6 },
+	{ 0x0c, KEY_ZOOM },		/* Full screen */
+	{ 0x0d, KEY_7 },
+	{ 0x0e, KEY_8 },
+	{ 0x0f, KEY_9 },
+	{ 0x10, KEY_PAGEUP },		/* 16-CH PREV */
+	{ 0x11, KEY_0 },
+	{ 0x12, KEY_INFO },
+	{ 0x13, KEY_AGAIN },		/* CH RTN - channel return */
+	{ 0x14, KEY_MUTE },
+	{ 0x15, KEY_EDIT },		/* Autoscan */
+	{ 0x17, KEY_SAVE },		/* Screenshot */
+	{ 0x18, KEY_PLAYPAUSE },
+	{ 0x19, KEY_RECORD },
+	{ 0x1a, KEY_PLAY },
+	{ 0x1b, KEY_STOP },
+	{ 0x1c, KEY_FASTFORWARD },
+	{ 0x1d, KEY_REWIND },
+	{ 0x1e, KEY_VOLUMEDOWN },
+	{ 0x1f, KEY_VOLUMEUP },
+	{ 0x22, KEY_SLEEP },		/* Sleep */
+	{ 0x23, KEY_ZOOM },		/* Aspect */
+	{ 0x26, KEY_SCREEN },		/* Pos */
+	{ 0x27, KEY_ANGLE },		/* Size */
+	{ 0x28, KEY_SELECT },		/* Select */
+	{ 0x29, KEY_BLUE },		/* Blue/Picture */
+	{ 0x2a, KEY_BACKSPACE },	/* Back */
+	{ 0x2b, KEY_MEDIA },		/* PIP (Picture-in-picture) */
+	{ 0x2c, KEY_DOWN },
+	{ 0x2e, KEY_DOT },
+	{ 0x2f, KEY_TV },		/* Live TV */
+	{ 0x32, KEY_LEFT },
+	{ 0x33, KEY_CLEAR },		/* Clear */
+	{ 0x35, KEY_RED },		/* Red/TV */
+	{ 0x36, KEY_UP },
+	{ 0x37, KEY_HOME },		/* Home */
+	{ 0x39, KEY_GREEN },		/* Green/Video */
+	{ 0x3d, KEY_YELLOW },		/* Yellow/Music */
+	{ 0x3e, KEY_OK },		/* Ok */
+	{ 0x3f, KEY_RIGHT },
+	{ 0x40, KEY_NEXT },		/* Next */
+	{ 0x41, KEY_PREVIOUS },		/* Previous */
+	{ 0x42, KEY_CHANNELDOWN },	/* Channel down */
+	{ 0x43, KEY_CHANNELUP },	/* Channel up */
+};
+
+static struct rc_map_list avermedia_cardbus_map = {
+	.map = {
+		.scan    = avermedia_cardbus,
+		.size    = ARRAY_SIZE(avermedia_cardbus),
+		.rc_type = RC_TYPE_UNKNOWN,	/* Legacy IR type */
+		.name    = RC_MAP_AVERMEDIA_CARDBUS,
+	}
+};
+
+static int __init init_rc_map_avermedia_cardbus(void)
+{
+	return rc_map_register(&avermedia_cardbus_map);
+}
+
+static void __exit exit_rc_map_avermedia_cardbus(void)
+{
+	rc_map_unregister(&avermedia_cardbus_map);
+}
+
+module_init(init_rc_map_avermedia_cardbus)
+module_exit(exit_rc_map_avermedia_cardbus)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-avermedia-dvbt.c linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-avermedia-dvbt.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-avermedia-dvbt.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-avermedia-dvbt.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,78 @@
+/* avermedia-dvbt.h - Keytable for avermedia_dvbt Remote Controller
+ *
+ * keymap imported from ir-keymaps.c
+ *
+ * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
+
+/* Matt Jesson <dvb@jesson.eclipse.co.uk */
+
+static struct rc_map_table avermedia_dvbt[] = {
+	{ 0x28, KEY_0 },		/* '0' / 'enter' */
+	{ 0x22, KEY_1 },		/* '1' */
+	{ 0x12, KEY_2 },		/* '2' / 'up arrow' */
+	{ 0x32, KEY_3 },		/* '3' */
+	{ 0x24, KEY_4 },		/* '4' / 'left arrow' */
+	{ 0x14, KEY_5 },		/* '5' */
+	{ 0x34, KEY_6 },		/* '6' / 'right arrow' */
+	{ 0x26, KEY_7 },		/* '7' */
+	{ 0x16, KEY_8 },		/* '8' / 'down arrow' */
+	{ 0x36, KEY_9 },		/* '9' */
+
+	{ 0x20, KEY_LIST },		/* 'source' */
+	{ 0x10, KEY_TEXT },		/* 'teletext' */
+	{ 0x00, KEY_POWER },		/* 'power' */
+	{ 0x04, KEY_AUDIO },		/* 'audio' */
+	{ 0x06, KEY_ZOOM },		/* 'full screen' */
+	{ 0x18, KEY_VIDEO },		/* 'display' */
+	{ 0x38, KEY_SEARCH },		/* 'loop' */
+	{ 0x08, KEY_INFO },		/* 'preview' */
+	{ 0x2a, KEY_REWIND },		/* 'backward <<' */
+	{ 0x1a, KEY_FASTFORWARD },	/* 'forward >>' */
+	{ 0x3a, KEY_RECORD },		/* 'capture' */
+	{ 0x0a, KEY_MUTE },		/* 'mute' */
+	{ 0x2c, KEY_RECORD },		/* 'record' */
+	{ 0x1c, KEY_PAUSE },		/* 'pause' */
+	{ 0x3c, KEY_STOP },		/* 'stop' */
+	{ 0x0c, KEY_PLAY },		/* 'play' */
+	{ 0x2e, KEY_RED },		/* 'red' */
+	{ 0x01, KEY_BLUE },		/* 'blue' / 'cancel' */
+	{ 0x0e, KEY_YELLOW },		/* 'yellow' / 'ok' */
+	{ 0x21, KEY_GREEN },		/* 'green' */
+	{ 0x11, KEY_CHANNELDOWN },	/* 'channel -' */
+	{ 0x31, KEY_CHANNELUP },	/* 'channel +' */
+	{ 0x1e, KEY_VOLUMEDOWN },	/* 'volume -' */
+	{ 0x3e, KEY_VOLUMEUP },		/* 'volume +' */
+};
+
+static struct rc_map_list avermedia_dvbt_map = {
+	.map = {
+		.scan    = avermedia_dvbt,
+		.size    = ARRAY_SIZE(avermedia_dvbt),
+		.rc_type = RC_TYPE_UNKNOWN,	/* Legacy IR type */
+		.name    = RC_MAP_AVERMEDIA_DVBT,
+	}
+};
+
+static int __init init_rc_map_avermedia_dvbt(void)
+{
+	return rc_map_register(&avermedia_dvbt_map);
+}
+
+static void __exit exit_rc_map_avermedia_dvbt(void)
+{
+	rc_map_unregister(&avermedia_dvbt_map);
+}
+
+module_init(init_rc_map_avermedia_dvbt)
+module_exit(exit_rc_map_avermedia_dvbt)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-avermedia-m135a.c linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-avermedia-m135a.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-avermedia-m135a.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-avermedia-m135a.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,147 @@
+/* avermedia-m135a.c - Keytable for Avermedia M135A Remote Controllers
+ *
+ * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
+ * Copyright (c) 2010 by Herton Ronaldo Krzesinski <herton@mandriva.com.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.
+ */
+
+#include <media/rc-map.h>
+
+/*
+ * Avermedia M135A with RM-JX and RM-K6 remote controls
+ *
+ * On Avermedia M135A with IR model RM-JX, the same codes exist on both
+ * Positivo (BR) and original IR, initial version and remote control codes
+ * added by Mauro Carvalho Chehab <mchehab@infradead.org>
+ *
+ * Positivo also ships Avermedia M135A with model RM-K6, extra control
+ * codes added by Herton Ronaldo Krzesinski <herton@mandriva.com.br>
+ */
+
+static struct rc_map_table avermedia_m135a[] = {
+	/* RM-JX */
+	{ 0x0200, KEY_POWER2 },
+	{ 0x022e, KEY_DOT },		/* '.' */
+	{ 0x0201, KEY_MODE },		/* TV/FM or SOURCE */
+
+	{ 0x0205, KEY_1 },
+	{ 0x0206, KEY_2 },
+	{ 0x0207, KEY_3 },
+	{ 0x0209, KEY_4 },
+	{ 0x020a, KEY_5 },
+	{ 0x020b, KEY_6 },
+	{ 0x020d, KEY_7 },
+	{ 0x020e, KEY_8 },
+	{ 0x020f, KEY_9 },
+	{ 0x0211, KEY_0 },
+
+	{ 0x0213, KEY_RIGHT },		/* -> or L */
+	{ 0x0212, KEY_LEFT },		/* <- or R */
+
+	{ 0x0217, KEY_SLEEP },		/* Capturar Imagem or Snapshot */
+	{ 0x0210, KEY_SHUFFLE },	/* Amostra or 16 chan prev */
+
+	{ 0x0303, KEY_CHANNELUP },
+	{ 0x0302, KEY_CHANNELDOWN },
+	{ 0x021f, KEY_VOLUMEUP },
+	{ 0x021e, KEY_VOLUMEDOWN },
+	{ 0x020c, KEY_ENTER },		/* Full Screen */
+
+	{ 0x0214, KEY_MUTE },
+	{ 0x0208, KEY_AUDIO },
+
+	{ 0x0203, KEY_TEXT },		/* Teletext */
+	{ 0x0204, KEY_EPG },
+	{ 0x022b, KEY_TV2 },		/* TV2 or PIP */
+
+	{ 0x021d, KEY_RED },
+	{ 0x021c, KEY_YELLOW },
+	{ 0x0301, KEY_GREEN },
+	{ 0x0300, KEY_BLUE },
+
+	{ 0x021a, KEY_PLAYPAUSE },
+	{ 0x0219, KEY_RECORD },
+	{ 0x0218, KEY_PLAY },
+	{ 0x021b, KEY_STOP },
+
+	/* RM-K6 */
+	{ 0x0401, KEY_POWER2 },
+	{ 0x0406, KEY_MUTE },
+	{ 0x0408, KEY_MODE },     /* TV/FM */
+
+	{ 0x0409, KEY_1 },
+	{ 0x040a, KEY_2 },
+	{ 0x040b, KEY_3 },
+	{ 0x040c, KEY_4 },
+	{ 0x040d, KEY_5 },
+	{ 0x040e, KEY_6 },
+	{ 0x040f, KEY_7 },
+	{ 0x0410, KEY_8 },
+	{ 0x0411, KEY_9 },
+	{ 0x044c, KEY_DOT },      /* '.' */
+	{ 0x0412, KEY_0 },
+	{ 0x0407, KEY_REFRESH },  /* Refresh/Reload */
+
+	{ 0x0413, KEY_AUDIO },
+	{ 0x0440, KEY_SCREEN },   /* Full Screen toggle */
+	{ 0x0441, KEY_HOME },
+	{ 0x0442, KEY_BACK },
+	{ 0x0447, KEY_UP },
+	{ 0x0448, KEY_DOWN },
+	{ 0x0449, KEY_LEFT },
+	{ 0x044a, KEY_RIGHT },
+	{ 0x044b, KEY_OK },
+	{ 0x0404, KEY_VOLUMEUP },
+	{ 0x0405, KEY_VOLUMEDOWN },
+	{ 0x0402, KEY_CHANNELUP },
+	{ 0x0403, KEY_CHANNELDOWN },
+
+	{ 0x0443, KEY_RED },
+	{ 0x0444, KEY_GREEN },
+	{ 0x0445, KEY_YELLOW },
+	{ 0x0446, KEY_BLUE },
+
+	{ 0x0414, KEY_TEXT },
+	{ 0x0415, KEY_EPG },
+	{ 0x041a, KEY_TV2 },      /* PIP */
+	{ 0x041b, KEY_MHP },      /* Snapshot */
+
+	{ 0x0417, KEY_RECORD },
+	{ 0x0416, KEY_PLAYPAUSE },
+	{ 0x0418, KEY_STOP },
+	{ 0x0419, KEY_PAUSE },
+
+	{ 0x041f, KEY_PREVIOUS },
+	{ 0x041c, KEY_REWIND },
+	{ 0x041d, KEY_FORWARD },
+	{ 0x041e, KEY_NEXT },
+};
+
+static struct rc_map_list avermedia_m135a_map = {
+	.map = {
+		.scan    = avermedia_m135a,
+		.size    = ARRAY_SIZE(avermedia_m135a),
+		.rc_type = RC_TYPE_NEC,
+		.name    = RC_MAP_AVERMEDIA_M135A,
+	}
+};
+
+static int __init init_rc_map_avermedia_m135a(void)
+{
+	return rc_map_register(&avermedia_m135a_map);
+}
+
+static void __exit exit_rc_map_avermedia_m135a(void)
+{
+	rc_map_unregister(&avermedia_m135a_map);
+}
+
+module_init(init_rc_map_avermedia_m135a)
+module_exit(exit_rc_map_avermedia_m135a)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-avermedia-m733a-rm-k6.c linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-avermedia-m733a-rm-k6.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-avermedia-m733a-rm-k6.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-avermedia-m733a-rm-k6.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,95 @@
+/* avermedia-m733a-rm-k6.h - Keytable for avermedia_m733a_rm_k6 Remote Controller
+ *
+ * Copyright (c) 2010 by Herton Ronaldo Krzesinski <herton@mandriva.com.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.
+ */
+
+#include <media/rc-map.h>
+
+/*
+ * Avermedia M733A with IR model RM-K6
+ * This is the stock remote controller used with Positivo machines with M733A
+ * Herton Ronaldo Krzesinski <herton@mandriva.com.br>
+ */
+
+static struct rc_map_table avermedia_m733a_rm_k6[] = {
+	{ 0x0401, KEY_POWER2 },
+	{ 0x0406, KEY_MUTE },
+	{ 0x0408, KEY_MODE },     /* TV/FM */
+
+	{ 0x0409, KEY_1 },
+	{ 0x040a, KEY_2 },
+	{ 0x040b, KEY_3 },
+	{ 0x040c, KEY_4 },
+	{ 0x040d, KEY_5 },
+	{ 0x040e, KEY_6 },
+	{ 0x040f, KEY_7 },
+	{ 0x0410, KEY_8 },
+	{ 0x0411, KEY_9 },
+	{ 0x044c, KEY_DOT },      /* '.' */
+	{ 0x0412, KEY_0 },
+	{ 0x0407, KEY_REFRESH },  /* Refresh/Reload */
+
+	{ 0x0413, KEY_AUDIO },
+	{ 0x0440, KEY_SCREEN },   /* Full Screen toggle */
+	{ 0x0441, KEY_HOME },
+	{ 0x0442, KEY_BACK },
+	{ 0x0447, KEY_UP },
+	{ 0x0448, KEY_DOWN },
+	{ 0x0449, KEY_LEFT },
+	{ 0x044a, KEY_RIGHT },
+	{ 0x044b, KEY_OK },
+	{ 0x0404, KEY_VOLUMEUP },
+	{ 0x0405, KEY_VOLUMEDOWN },
+	{ 0x0402, KEY_CHANNELUP },
+	{ 0x0403, KEY_CHANNELDOWN },
+
+	{ 0x0443, KEY_RED },
+	{ 0x0444, KEY_GREEN },
+	{ 0x0445, KEY_YELLOW },
+	{ 0x0446, KEY_BLUE },
+
+	{ 0x0414, KEY_TEXT },
+	{ 0x0415, KEY_EPG },
+	{ 0x041a, KEY_TV2 },      /* PIP */
+	{ 0x041b, KEY_MHP },      /* Snapshot */
+
+	{ 0x0417, KEY_RECORD },
+	{ 0x0416, KEY_PLAYPAUSE },
+	{ 0x0418, KEY_STOP },
+	{ 0x0419, KEY_PAUSE },
+
+	{ 0x041f, KEY_PREVIOUS },
+	{ 0x041c, KEY_REWIND },
+	{ 0x041d, KEY_FORWARD },
+	{ 0x041e, KEY_NEXT },
+};
+
+static struct rc_map_list avermedia_m733a_rm_k6_map = {
+	.map = {
+		.scan    = avermedia_m733a_rm_k6,
+		.size    = ARRAY_SIZE(avermedia_m733a_rm_k6),
+		.rc_type = RC_TYPE_NEC,
+		.name    = RC_MAP_AVERMEDIA_M733A_RM_K6,
+	}
+};
+
+static int __init init_rc_map_avermedia_m733a_rm_k6(void)
+{
+	return rc_map_register(&avermedia_m733a_rm_k6_map);
+}
+
+static void __exit exit_rc_map_avermedia_m733a_rm_k6(void)
+{
+	rc_map_unregister(&avermedia_m733a_rm_k6_map);
+}
+
+module_init(init_rc_map_avermedia_m733a_rm_k6)
+module_exit(exit_rc_map_avermedia_m733a_rm_k6)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-avermedia-rm-ks.c linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-avermedia-rm-ks.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-avermedia-rm-ks.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-avermedia-rm-ks.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,79 @@
+/*
+ * AverMedia RM-KS remote controller keytable
+ *
+ * Copyright (C) 2010 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 <media/rc-map.h>
+
+/* Initial keytable is from Jose Alberto Reguero <jareguero@telefonica.net>
+   and Felipe Morales Moreno <felipe.morales.moreno@gmail.com> */
+/* FIXME: mappings are not 100% correct? */
+static struct rc_map_table avermedia_rm_ks[] = {
+	{ 0x0501, KEY_POWER2 },
+	{ 0x0502, KEY_CHANNELUP },
+	{ 0x0503, KEY_CHANNELDOWN },
+	{ 0x0504, KEY_VOLUMEUP },
+	{ 0x0505, KEY_VOLUMEDOWN },
+	{ 0x0506, KEY_MUTE },
+	{ 0x0507, KEY_RIGHT },
+	{ 0x0508, KEY_PROG1 },
+	{ 0x0509, KEY_1 },
+	{ 0x050a, KEY_2 },
+	{ 0x050b, KEY_3 },
+	{ 0x050c, KEY_4 },
+	{ 0x050d, KEY_5 },
+	{ 0x050e, KEY_6 },
+	{ 0x050f, KEY_7 },
+	{ 0x0510, KEY_8 },
+	{ 0x0511, KEY_9 },
+	{ 0x0512, KEY_0 },
+	{ 0x0513, KEY_AUDIO },
+	{ 0x0515, KEY_EPG },
+	{ 0x0516, KEY_PLAY },
+	{ 0x0517, KEY_RECORD },
+	{ 0x0518, KEY_STOP },
+	{ 0x051c, KEY_BACK },
+	{ 0x051d, KEY_FORWARD },
+	{ 0x054d, KEY_LEFT },
+	{ 0x0556, KEY_ZOOM },
+};
+
+static struct rc_map_list avermedia_rm_ks_map = {
+	.map = {
+		.scan    = avermedia_rm_ks,
+		.size    = ARRAY_SIZE(avermedia_rm_ks),
+		.rc_type = RC_TYPE_NEC,
+		.name    = RC_MAP_AVERMEDIA_RM_KS,
+	}
+};
+
+static int __init init_rc_map_avermedia_rm_ks(void)
+{
+	return rc_map_register(&avermedia_rm_ks_map);
+}
+
+static void __exit exit_rc_map_avermedia_rm_ks(void)
+{
+	rc_map_unregister(&avermedia_rm_ks_map);
+}
+
+module_init(init_rc_map_avermedia_rm_ks)
+module_exit(exit_rc_map_avermedia_rm_ks)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-avertv-303.c linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-avertv-303.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-avertv-303.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-avertv-303.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,85 @@
+/* avertv-303.h - Keytable for avertv_303 Remote Controller
+ *
+ * keymap imported from ir-keymaps.c
+ *
+ * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
+
+/* AVERTV STUDIO 303 Remote */
+
+static struct rc_map_table avertv_303[] = {
+	{ 0x2a, KEY_1 },
+	{ 0x32, KEY_2 },
+	{ 0x3a, KEY_3 },
+	{ 0x4a, KEY_4 },
+	{ 0x52, KEY_5 },
+	{ 0x5a, KEY_6 },
+	{ 0x6a, KEY_7 },
+	{ 0x72, KEY_8 },
+	{ 0x7a, KEY_9 },
+	{ 0x0e, KEY_0 },
+
+	{ 0x02, KEY_POWER },
+	{ 0x22, KEY_VIDEO },
+	{ 0x42, KEY_AUDIO },
+	{ 0x62, KEY_ZOOM },
+	{ 0x0a, KEY_TV },
+	{ 0x12, KEY_CD },
+	{ 0x1a, KEY_TEXT },
+
+	{ 0x16, KEY_SUBTITLE },
+	{ 0x1e, KEY_REWIND },
+	{ 0x06, KEY_PRINT },
+
+	{ 0x2e, KEY_SEARCH },
+	{ 0x36, KEY_SLEEP },
+	{ 0x3e, KEY_SHUFFLE },
+	{ 0x26, KEY_MUTE },
+
+	{ 0x4e, KEY_RECORD },
+	{ 0x56, KEY_PAUSE },
+	{ 0x5e, KEY_STOP },
+	{ 0x46, KEY_PLAY },
+
+	{ 0x6e, KEY_RED },
+	{ 0x0b, KEY_GREEN },
+	{ 0x66, KEY_YELLOW },
+	{ 0x03, KEY_BLUE },
+
+	{ 0x76, KEY_LEFT },
+	{ 0x7e, KEY_RIGHT },
+	{ 0x13, KEY_DOWN },
+	{ 0x1b, KEY_UP },
+};
+
+static struct rc_map_list avertv_303_map = {
+	.map = {
+		.scan    = avertv_303,
+		.size    = ARRAY_SIZE(avertv_303),
+		.rc_type = RC_TYPE_UNKNOWN,	/* Legacy IR type */
+		.name    = RC_MAP_AVERTV_303,
+	}
+};
+
+static int __init init_rc_map_avertv_303(void)
+{
+	return rc_map_register(&avertv_303_map);
+}
+
+static void __exit exit_rc_map_avertv_303(void)
+{
+	rc_map_unregister(&avertv_303_map);
+}
+
+module_init(init_rc_map_avertv_303)
+module_exit(exit_rc_map_avertv_303)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-azurewave-ad-tu700.c linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-azurewave-ad-tu700.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-azurewave-ad-tu700.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-azurewave-ad-tu700.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,102 @@
+/*
+ * TwinHan AzureWave AD-TU700(704J) remote controller keytable
+ *
+ * Copyright (C) 2010 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 <media/rc-map.h>
+
+static struct rc_map_table azurewave_ad_tu700[] = {
+	{ 0x0000, KEY_TAB },             /* Tab */
+	{ 0x0001, KEY_2 },
+	{ 0x0002, KEY_CHANNELDOWN },
+	{ 0x0003, KEY_1 },
+	{ 0x0004, KEY_MENU },            /* Record List */
+	{ 0x0005, KEY_CHANNELUP },
+	{ 0x0006, KEY_3 },
+	{ 0x0007, KEY_SLEEP },           /* Hibernate */
+	{ 0x0008, KEY_VIDEO },           /* A/V */
+	{ 0x0009, KEY_4 },
+	{ 0x000a, KEY_VOLUMEDOWN },
+	{ 0x000c, KEY_CANCEL },          /* Cancel */
+	{ 0x000d, KEY_7 },
+	{ 0x000e, KEY_AGAIN },           /* Recall */
+	{ 0x000f, KEY_TEXT },            /* Teletext */
+	{ 0x0010, KEY_MUTE },
+	{ 0x0011, KEY_RECORD },
+	{ 0x0012, KEY_FASTFORWARD },     /* FF >> */
+	{ 0x0013, KEY_BACK },            /* Back */
+	{ 0x0014, KEY_PLAY },
+	{ 0x0015, KEY_0 },
+	{ 0x0016, KEY_POWER2 },          /* [red power button] */
+	{ 0x0017, KEY_FAVORITES },       /* Favorite List */
+	{ 0x0018, KEY_RED },
+	{ 0x0019, KEY_8 },
+	{ 0x001a, KEY_STOP },
+	{ 0x001b, KEY_9 },
+	{ 0x001c, KEY_EPG },             /* Info/EPG */
+	{ 0x001d, KEY_5 },
+	{ 0x001e, KEY_VOLUMEUP },
+	{ 0x001f, KEY_6 },
+	{ 0x0040, KEY_REWIND },          /* FR << */
+	{ 0x0041, KEY_PREVIOUS },        /* Replay */
+	{ 0x0042, KEY_NEXT },            /* Skip */
+	{ 0x0043, KEY_SUBTITLE },        /* Subtitle / CC */
+	{ 0x0045, KEY_KPPLUS },          /* Zoom+ */
+	{ 0x0046, KEY_KPMINUS },         /* Zoom- */
+	{ 0x0047, KEY_NEW },             /* PIP */
+	{ 0x0048, KEY_INFO },            /* Preview */
+	{ 0x0049, KEY_MODE },            /* L/R */
+	{ 0x004a, KEY_CLEAR },           /* Clear */
+	{ 0x004b, KEY_UP },              /* up arrow */
+	{ 0x004c, KEY_PAUSE },
+	{ 0x004d, KEY_ZOOM },            /* Full Screen */
+	{ 0x004e, KEY_LEFT },            /* left arrow */
+	{ 0x004f, KEY_OK },              /* Enter / ok */
+	{ 0x0050, KEY_LANGUAGE },        /* SAP */
+	{ 0x0051, KEY_DOWN },            /* down arrow */
+	{ 0x0052, KEY_RIGHT },           /* right arrow */
+	{ 0x0053, KEY_GREEN },
+	{ 0x0054, KEY_CAMERA },          /* Capture */
+	{ 0x005e, KEY_YELLOW },
+	{ 0x005f, KEY_BLUE },
+};
+
+static struct rc_map_list azurewave_ad_tu700_map = {
+	.map = {
+		.scan    = azurewave_ad_tu700,
+		.size    = ARRAY_SIZE(azurewave_ad_tu700),
+		.rc_type = RC_TYPE_NEC,
+		.name    = RC_MAP_AZUREWAVE_AD_TU700,
+	}
+};
+
+static int __init init_rc_map_azurewave_ad_tu700(void)
+{
+	return rc_map_register(&azurewave_ad_tu700_map);
+}
+
+static void __exit exit_rc_map_azurewave_ad_tu700(void)
+{
+	rc_map_unregister(&azurewave_ad_tu700_map);
+}
+
+module_init(init_rc_map_azurewave_ad_tu700)
+module_exit(exit_rc_map_azurewave_ad_tu700)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-behold.c linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-behold.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-behold.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-behold.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,141 @@
+/* behold.h - Keytable for behold Remote Controller
+ *
+ * keymap imported from ir-keymaps.c
+ *
+ * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
+
+/*
+ * Igor Kuznetsov <igk72@ya.ru>
+ * Andrey J. Melnikov <temnota@kmv.ru>
+ *
+ * Keytable is used by BeholdTV 60x series, M6 series at
+ * least, and probably other cards too.
+ * The "ascii-art picture" below (in comments, first row
+ * is the keycode in hex, and subsequent row(s) shows
+ * the button labels (several variants when appropriate)
+ * helps to descide which keycodes to assign to the buttons.
+ */
+
+static struct rc_map_table behold[] = {
+
+	/*  0x1c            0x12  *
+	 *  TV/FM          POWER  *
+	 *                        */
+	{ 0x6b861c, KEY_TUNER },	/* XXX KEY_TV / KEY_RADIO */
+	{ 0x6b8612, KEY_POWER },
+
+	/*  0x01    0x02    0x03  *
+	 *   1       2       3    *
+	 *                        *
+	 *  0x04    0x05    0x06  *
+	 *   4       5       6    *
+	 *                        *
+	 *  0x07    0x08    0x09  *
+	 *   7       8       9    *
+	 *                        */
+	{ 0x6b8601, KEY_1 },
+	{ 0x6b8602, KEY_2 },
+	{ 0x6b8603, KEY_3 },
+	{ 0x6b8604, KEY_4 },
+	{ 0x6b8605, KEY_5 },
+	{ 0x6b8606, KEY_6 },
+	{ 0x6b8607, KEY_7 },
+	{ 0x6b8608, KEY_8 },
+	{ 0x6b8609, KEY_9 },
+
+	/*  0x0a    0x00    0x17  *
+	 * RECALL    0      MODE  *
+	 *                        */
+	{ 0x6b860a, KEY_AGAIN },
+	{ 0x6b8600, KEY_0 },
+	{ 0x6b8617, KEY_MODE },
+
+	/*  0x14          0x10    *
+	 * ASPECT      FULLSCREEN *
+	 *                        */
+	{ 0x6b8614, KEY_SCREEN },
+	{ 0x6b8610, KEY_ZOOM },
+
+	/*          0x0b          *
+	 *           Up           *
+	 *                        *
+	 *  0x18    0x16    0x0c  *
+	 *  Left     Ok     Right *
+	 *                        *
+	 *         0x015          *
+	 *         Down           *
+	 *                        */
+	{ 0x6b860b, KEY_CHANNELUP },
+	{ 0x6b8618, KEY_VOLUMEDOWN },
+	{ 0x6b8616, KEY_OK },		/* XXX KEY_ENTER */
+	{ 0x6b860c, KEY_VOLUMEUP },
+	{ 0x6b8615, KEY_CHANNELDOWN },
+
+	/*  0x11            0x0d  *
+	 *  MUTE            INFO  *
+	 *                        */
+	{ 0x6b8611, KEY_MUTE },
+	{ 0x6b860d, KEY_INFO },
+
+	/*  0x0f    0x1b    0x1a  *
+	 * RECORD PLAY/PAUSE STOP *
+	 *                        *
+	 *  0x0e    0x1f    0x1e  *
+	 *TELETEXT  AUDIO  SOURCE *
+	 *           RED   YELLOW *
+	 *                        */
+	{ 0x6b860f, KEY_RECORD },
+	{ 0x6b861b, KEY_PLAYPAUSE },
+	{ 0x6b861a, KEY_STOP },
+	{ 0x6b860e, KEY_TEXT },
+	{ 0x6b861f, KEY_RED },	/*XXX KEY_AUDIO	*/
+	{ 0x6b861e, KEY_YELLOW },	/*XXX KEY_SOURCE	*/
+
+	/*  0x1d   0x13     0x19  *
+	 * SLEEP  PREVIEW   DVB   *
+	 *         GREEN    BLUE  *
+	 *                        */
+	{ 0x6b861d, KEY_SLEEP },
+	{ 0x6b8613, KEY_GREEN },
+	{ 0x6b8619, KEY_BLUE },	/* XXX KEY_SAT	*/
+
+	/*  0x58           0x5c   *
+	 * FREEZE        SNAPSHOT *
+	 *                        */
+	{ 0x6b8658, KEY_SLOW },
+	{ 0x6b865c, KEY_CAMERA },
+
+};
+
+static struct rc_map_list behold_map = {
+	.map = {
+		.scan    = behold,
+		.size    = ARRAY_SIZE(behold),
+		.rc_type = RC_TYPE_NEC,
+		.name    = RC_MAP_BEHOLD,
+	}
+};
+
+static int __init init_rc_map_behold(void)
+{
+	return rc_map_register(&behold_map);
+}
+
+static void __exit exit_rc_map_behold(void)
+{
+	rc_map_unregister(&behold_map);
+}
+
+module_init(init_rc_map_behold)
+module_exit(exit_rc_map_behold)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-behold-columbus.c linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-behold-columbus.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-behold-columbus.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-behold-columbus.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,108 @@
+/* behold-columbus.h - Keytable for behold_columbus Remote Controller
+ *
+ * keymap imported from ir-keymaps.c
+ *
+ * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
+
+/* Beholder Intl. Ltd. 2008
+ * Dmitry Belimov d.belimov@google.com
+ * Keytable is used by BeholdTV Columbus
+ * The "ascii-art picture" below (in comments, first row
+ * is the keycode in hex, and subsequent row(s) shows
+ * the button labels (several variants when appropriate)
+ * helps to descide which keycodes to assign to the buttons.
+ */
+
+static struct rc_map_table behold_columbus[] = {
+
+	/*  0x13   0x11   0x1C   0x12  *
+	 *  Mute  Source  TV/FM  Power *
+	 *                             */
+
+	{ 0x13, KEY_MUTE },
+	{ 0x11, KEY_PROPS },
+	{ 0x1C, KEY_TUNER },	/* KEY_TV/KEY_RADIO	*/
+	{ 0x12, KEY_POWER },
+
+	/*  0x01    0x02    0x03  0x0D    *
+	 *   1       2       3   Stereo   *
+	 *                        	  *
+	 *  0x04    0x05    0x06  0x19    *
+	 *   4       5       6   Snapshot *
+	 *                        	  *
+	 *  0x07    0x08    0x09  0x10    *
+	 *   7       8       9    Zoom 	  *
+	 *                                */
+	{ 0x01, KEY_1 },
+	{ 0x02, KEY_2 },
+	{ 0x03, KEY_3 },
+	{ 0x0D, KEY_SETUP },	  /* Setup key */
+	{ 0x04, KEY_4 },
+	{ 0x05, KEY_5 },
+	{ 0x06, KEY_6 },
+	{ 0x19, KEY_CAMERA },	/* Snapshot key */
+	{ 0x07, KEY_7 },
+	{ 0x08, KEY_8 },
+	{ 0x09, KEY_9 },
+	{ 0x10, KEY_ZOOM },
+
+	/*  0x0A    0x00    0x0B       0x0C   *
+	 * RECALL    0    ChannelUp  VolumeUp *
+	 *                                    */
+	{ 0x0A, KEY_AGAIN },
+	{ 0x00, KEY_0 },
+	{ 0x0B, KEY_CHANNELUP },
+	{ 0x0C, KEY_VOLUMEUP },
+
+	/*   0x1B      0x1D      0x15        0x18     *
+	 * Timeshift  Record  ChannelDown  VolumeDown *
+	 *                                            */
+
+	{ 0x1B, KEY_TIME },
+	{ 0x1D, KEY_RECORD },
+	{ 0x15, KEY_CHANNELDOWN },
+	{ 0x18, KEY_VOLUMEDOWN },
+
+	/*   0x0E   0x1E     0x0F     0x1A  *
+	 *   Stop   Pause  Previouse  Next  *
+	 *                                  */
+
+	{ 0x0E, KEY_STOP },
+	{ 0x1E, KEY_PAUSE },
+	{ 0x0F, KEY_PREVIOUS },
+	{ 0x1A, KEY_NEXT },
+
+};
+
+static struct rc_map_list behold_columbus_map = {
+	.map = {
+		.scan    = behold_columbus,
+		.size    = ARRAY_SIZE(behold_columbus),
+		.rc_type = RC_TYPE_UNKNOWN,	/* Legacy IR type */
+		.name    = RC_MAP_BEHOLD_COLUMBUS,
+	}
+};
+
+static int __init init_rc_map_behold_columbus(void)
+{
+	return rc_map_register(&behold_columbus_map);
+}
+
+static void __exit exit_rc_map_behold_columbus(void)
+{
+	rc_map_unregister(&behold_columbus_map);
+}
+
+module_init(init_rc_map_behold_columbus)
+module_exit(exit_rc_map_behold_columbus)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-budget-ci-old.c linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-budget-ci-old.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-budget-ci-old.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-budget-ci-old.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,92 @@
+/* budget-ci-old.h - Keytable for budget_ci_old Remote Controller
+ *
+ * keymap imported from ir-keymaps.c
+ *
+ * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
+
+/* From reading the following remotes:
+ * Zenith Universal 7 / TV Mode 807 / VCR Mode 837
+ * Hauppauge (from NOVA-CI-s box product)
+ * This is a "middle of the road" approach, differences are noted
+ */
+
+static struct rc_map_table budget_ci_old[] = {
+	{ 0x00, KEY_0 },
+	{ 0x01, KEY_1 },
+	{ 0x02, KEY_2 },
+	{ 0x03, KEY_3 },
+	{ 0x04, KEY_4 },
+	{ 0x05, KEY_5 },
+	{ 0x06, KEY_6 },
+	{ 0x07, KEY_7 },
+	{ 0x08, KEY_8 },
+	{ 0x09, KEY_9 },
+	{ 0x0a, KEY_ENTER },
+	{ 0x0b, KEY_RED },
+	{ 0x0c, KEY_POWER },		/* RADIO on Hauppauge */
+	{ 0x0d, KEY_MUTE },
+	{ 0x0f, KEY_A },		/* TV on Hauppauge */
+	{ 0x10, KEY_VOLUMEUP },
+	{ 0x11, KEY_VOLUMEDOWN },
+	{ 0x14, KEY_B },
+	{ 0x1c, KEY_UP },
+	{ 0x1d, KEY_DOWN },
+	{ 0x1e, KEY_OPTION },		/* RESERVED on Hauppauge */
+	{ 0x1f, KEY_BREAK },
+	{ 0x20, KEY_CHANNELUP },
+	{ 0x21, KEY_CHANNELDOWN },
+	{ 0x22, KEY_PREVIOUS },		/* Prev Ch on Zenith, SOURCE on Hauppauge */
+	{ 0x24, KEY_RESTART },
+	{ 0x25, KEY_OK },
+	{ 0x26, KEY_CYCLEWINDOWS },	/* MINIMIZE on Hauppauge */
+	{ 0x28, KEY_ENTER },		/* VCR mode on Zenith */
+	{ 0x29, KEY_PAUSE },
+	{ 0x2b, KEY_RIGHT },
+	{ 0x2c, KEY_LEFT },
+	{ 0x2e, KEY_MENU },		/* FULL SCREEN on Hauppauge */
+	{ 0x30, KEY_SLOW },
+	{ 0x31, KEY_PREVIOUS },		/* VCR mode on Zenith */
+	{ 0x32, KEY_REWIND },
+	{ 0x34, KEY_FASTFORWARD },
+	{ 0x35, KEY_PLAY },
+	{ 0x36, KEY_STOP },
+	{ 0x37, KEY_RECORD },
+	{ 0x38, KEY_TUNER },		/* TV/VCR on Zenith */
+	{ 0x3a, KEY_C },
+	{ 0x3c, KEY_EXIT },
+	{ 0x3d, KEY_POWER2 },
+	{ 0x3e, KEY_TUNER },
+};
+
+static struct rc_map_list budget_ci_old_map = {
+	.map = {
+		.scan    = budget_ci_old,
+		.size    = ARRAY_SIZE(budget_ci_old),
+		.rc_type = RC_TYPE_UNKNOWN,	/* Legacy IR type */
+		.name    = RC_MAP_BUDGET_CI_OLD,
+	}
+};
+
+static int __init init_rc_map_budget_ci_old(void)
+{
+	return rc_map_register(&budget_ci_old_map);
+}
+
+static void __exit exit_rc_map_budget_ci_old(void)
+{
+	rc_map_unregister(&budget_ci_old_map);
+}
+
+module_init(init_rc_map_budget_ci_old)
+module_exit(exit_rc_map_budget_ci_old)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-cinergy-1400.c linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-cinergy-1400.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-cinergy-1400.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-cinergy-1400.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,84 @@
+/* cinergy-1400.h - Keytable for cinergy_1400 Remote Controller
+ *
+ * keymap imported from ir-keymaps.c
+ *
+ * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
+
+/* Cinergy 1400 DVB-T */
+
+static struct rc_map_table cinergy_1400[] = {
+	{ 0x01, KEY_POWER },
+	{ 0x02, KEY_1 },
+	{ 0x03, KEY_2 },
+	{ 0x04, KEY_3 },
+	{ 0x05, KEY_4 },
+	{ 0x06, KEY_5 },
+	{ 0x07, KEY_6 },
+	{ 0x08, KEY_7 },
+	{ 0x09, KEY_8 },
+	{ 0x0a, KEY_9 },
+	{ 0x0c, KEY_0 },
+
+	{ 0x0b, KEY_VIDEO },
+	{ 0x0d, KEY_REFRESH },
+	{ 0x0e, KEY_SELECT },
+	{ 0x0f, KEY_EPG },
+	{ 0x10, KEY_UP },
+	{ 0x11, KEY_LEFT },
+	{ 0x12, KEY_OK },
+	{ 0x13, KEY_RIGHT },
+	{ 0x14, KEY_DOWN },
+	{ 0x15, KEY_TEXT },
+	{ 0x16, KEY_INFO },
+
+	{ 0x17, KEY_RED },
+	{ 0x18, KEY_GREEN },
+	{ 0x19, KEY_YELLOW },
+	{ 0x1a, KEY_BLUE },
+
+	{ 0x1b, KEY_CHANNELUP },
+	{ 0x1c, KEY_VOLUMEUP },
+	{ 0x1d, KEY_MUTE },
+	{ 0x1e, KEY_VOLUMEDOWN },
+	{ 0x1f, KEY_CHANNELDOWN },
+
+	{ 0x40, KEY_PAUSE },
+	{ 0x4c, KEY_PLAY },
+	{ 0x58, KEY_RECORD },
+	{ 0x54, KEY_PREVIOUS },
+	{ 0x48, KEY_STOP },
+	{ 0x5c, KEY_NEXT },
+};
+
+static struct rc_map_list cinergy_1400_map = {
+	.map = {
+		.scan    = cinergy_1400,
+		.size    = ARRAY_SIZE(cinergy_1400),
+		.rc_type = RC_TYPE_UNKNOWN,	/* Legacy IR type */
+		.name    = RC_MAP_CINERGY_1400,
+	}
+};
+
+static int __init init_rc_map_cinergy_1400(void)
+{
+	return rc_map_register(&cinergy_1400_map);
+}
+
+static void __exit exit_rc_map_cinergy_1400(void)
+{
+	rc_map_unregister(&cinergy_1400_map);
+}
+
+module_init(init_rc_map_cinergy_1400)
+module_exit(exit_rc_map_cinergy_1400)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-cinergy.c linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-cinergy.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-cinergy.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-cinergy.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,78 @@
+/* cinergy.h - Keytable for cinergy Remote Controller
+ *
+ * keymap imported from ir-keymaps.c
+ *
+ * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
+
+static struct rc_map_table cinergy[] = {
+	{ 0x00, KEY_0 },
+	{ 0x01, KEY_1 },
+	{ 0x02, KEY_2 },
+	{ 0x03, KEY_3 },
+	{ 0x04, KEY_4 },
+	{ 0x05, KEY_5 },
+	{ 0x06, KEY_6 },
+	{ 0x07, KEY_7 },
+	{ 0x08, KEY_8 },
+	{ 0x09, KEY_9 },
+
+	{ 0x0a, KEY_POWER },
+	{ 0x0b, KEY_PROG1 },		/* app */
+	{ 0x0c, KEY_ZOOM },		/* zoom/fullscreen */
+	{ 0x0d, KEY_CHANNELUP },	/* channel */
+	{ 0x0e, KEY_CHANNELDOWN },	/* channel- */
+	{ 0x0f, KEY_VOLUMEUP },
+	{ 0x10, KEY_VOLUMEDOWN },
+	{ 0x11, KEY_TUNER },		/* AV */
+	{ 0x12, KEY_NUMLOCK },		/* -/-- */
+	{ 0x13, KEY_AUDIO },		/* audio */
+	{ 0x14, KEY_MUTE },
+	{ 0x15, KEY_UP },
+	{ 0x16, KEY_DOWN },
+	{ 0x17, KEY_LEFT },
+	{ 0x18, KEY_RIGHT },
+	{ 0x19, BTN_LEFT, },
+	{ 0x1a, BTN_RIGHT, },
+	{ 0x1b, KEY_WWW },		/* text */
+	{ 0x1c, KEY_REWIND },
+	{ 0x1d, KEY_FORWARD },
+	{ 0x1e, KEY_RECORD },
+	{ 0x1f, KEY_PLAY },
+	{ 0x20, KEY_PREVIOUSSONG },
+	{ 0x21, KEY_NEXTSONG },
+	{ 0x22, KEY_PAUSE },
+	{ 0x23, KEY_STOP },
+};
+
+static struct rc_map_list cinergy_map = {
+	.map = {
+		.scan    = cinergy,
+		.size    = ARRAY_SIZE(cinergy),
+		.rc_type = RC_TYPE_UNKNOWN,	/* Legacy IR type */
+		.name    = RC_MAP_CINERGY,
+	}
+};
+
+static int __init init_rc_map_cinergy(void)
+{
+	return rc_map_register(&cinergy_map);
+}
+
+static void __exit exit_rc_map_cinergy(void)
+{
+	rc_map_unregister(&cinergy_map);
+}
+
+module_init(init_rc_map_cinergy)
+module_exit(exit_rc_map_cinergy)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-dib0700-nec.c linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-dib0700-nec.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-dib0700-nec.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-dib0700-nec.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,124 @@
+/* rc-dvb0700-big.c - Keytable for devices in dvb0700
+ *
+ * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
+ *
+ * TODO: This table is a real mess, as it merges RC codes from several
+ * devices into a big table. It also has both RC-5 and NEC codes inside.
+ * It should be broken into small tables, and the protocols should properly
+ * be indentificated.
+ *
+ * The table were imported from dib0700_devices.c.
+ *
+ * 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 <media/rc-map.h>
+
+static struct rc_map_table dib0700_nec_table[] = {
+	/* Key codes for the Pixelview SBTVD remote */
+	{ 0x866b13, KEY_MUTE },
+	{ 0x866b12, KEY_POWER },
+	{ 0x866b01, KEY_1 },
+	{ 0x866b02, KEY_2 },
+	{ 0x866b03, KEY_3 },
+	{ 0x866b04, KEY_4 },
+	{ 0x866b05, KEY_5 },
+	{ 0x866b06, KEY_6 },
+	{ 0x866b07, KEY_7 },
+	{ 0x866b08, KEY_8 },
+	{ 0x866b09, KEY_9 },
+	{ 0x866b00, KEY_0 },
+	{ 0x866b0d, KEY_CHANNELUP },
+	{ 0x866b19, KEY_CHANNELDOWN },
+	{ 0x866b10, KEY_VOLUMEUP },
+	{ 0x866b0c, KEY_VOLUMEDOWN },
+
+	{ 0x866b0a, KEY_CAMERA },
+	{ 0x866b0b, KEY_ZOOM },
+	{ 0x866b1b, KEY_BACKSPACE },
+	{ 0x866b15, KEY_ENTER },
+
+	{ 0x866b1d, KEY_UP },
+	{ 0x866b1e, KEY_DOWN },
+	{ 0x866b0e, KEY_LEFT },
+	{ 0x866b0f, KEY_RIGHT },
+
+	{ 0x866b18, KEY_RECORD },
+	{ 0x866b1a, KEY_STOP },
+
+	/* Key codes for the EvolutePC TVWay+ remote */
+	{ 0x7a00, KEY_MENU },
+	{ 0x7a01, KEY_RECORD },
+	{ 0x7a02, KEY_PLAY },
+	{ 0x7a03, KEY_STOP },
+	{ 0x7a10, KEY_CHANNELUP },
+	{ 0x7a11, KEY_CHANNELDOWN },
+	{ 0x7a12, KEY_VOLUMEUP },
+	{ 0x7a13, KEY_VOLUMEDOWN },
+	{ 0x7a40, KEY_POWER },
+	{ 0x7a41, KEY_MUTE },
+
+	/* Key codes for the Elgato EyeTV Diversity silver remote */
+	{ 0x4501, KEY_POWER },
+	{ 0x4502, KEY_MUTE },
+	{ 0x4503, KEY_1 },
+	{ 0x4504, KEY_2 },
+	{ 0x4505, KEY_3 },
+	{ 0x4506, KEY_4 },
+	{ 0x4507, KEY_5 },
+	{ 0x4508, KEY_6 },
+	{ 0x4509, KEY_7 },
+	{ 0x450a, KEY_8 },
+	{ 0x450b, KEY_9 },
+	{ 0x450c, KEY_LAST },
+	{ 0x450d, KEY_0 },
+	{ 0x450e, KEY_ENTER },
+	{ 0x450f, KEY_RED },
+	{ 0x4510, KEY_CHANNELUP },
+	{ 0x4511, KEY_GREEN },
+	{ 0x4512, KEY_VOLUMEDOWN },
+	{ 0x4513, KEY_OK },
+	{ 0x4514, KEY_VOLUMEUP },
+	{ 0x4515, KEY_YELLOW },
+	{ 0x4516, KEY_CHANNELDOWN },
+	{ 0x4517, KEY_BLUE },
+	{ 0x4518, KEY_LEFT }, /* Skip backwards */
+	{ 0x4519, KEY_PLAYPAUSE },
+	{ 0x451a, KEY_RIGHT }, /* Skip forward */
+	{ 0x451b, KEY_REWIND },
+	{ 0x451c, KEY_L }, /* Live */
+	{ 0x451d, KEY_FASTFORWARD },
+	{ 0x451e, KEY_STOP }, /* 'Reveal' for Teletext */
+	{ 0x451f, KEY_MENU }, /* KEY_TEXT for Teletext */
+	{ 0x4540, KEY_RECORD }, /* Font 'Size' for Teletext */
+	{ 0x4541, KEY_SCREEN }, /*  Full screen toggle, 'Hold' for Teletext */
+	{ 0x4542, KEY_SELECT }, /* Select video input, 'Select' for Teletext */
+};
+
+static struct rc_map_list dib0700_nec_map = {
+	.map = {
+		.scan    = dib0700_nec_table,
+		.size    = ARRAY_SIZE(dib0700_nec_table),
+		.rc_type = RC_TYPE_NEC,
+		.name    = RC_MAP_DIB0700_NEC_TABLE,
+	}
+};
+
+static int __init init_rc_map(void)
+{
+	return rc_map_register(&dib0700_nec_map);
+}
+
+static void __exit exit_rc_map(void)
+{
+	rc_map_unregister(&dib0700_nec_map);
+}
+
+module_init(init_rc_map)
+module_exit(exit_rc_map)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-dib0700-rc5.c linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-dib0700-rc5.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-dib0700-rc5.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-dib0700-rc5.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,235 @@
+/* rc-dvb0700-big.c - Keytable for devices in dvb0700
+ *
+ * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
+ *
+ * TODO: This table is a real mess, as it merges RC codes from several
+ * devices into a big table. It also has both RC-5 and NEC codes inside.
+ * It should be broken into small tables, and the protocols should properly
+ * be indentificated.
+ *
+ * The table were imported from dib0700_devices.c.
+ *
+ * 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 <media/rc-map.h>
+
+static struct rc_map_table dib0700_rc5_table[] = {
+	/* Key codes for the tiny Pinnacle remote*/
+	{ 0x0700, KEY_MUTE },
+	{ 0x0701, KEY_MENU }, /* Pinnacle logo */
+	{ 0x0739, KEY_POWER },
+	{ 0x0703, KEY_VOLUMEUP },
+	{ 0x0709, KEY_VOLUMEDOWN },
+	{ 0x0706, KEY_CHANNELUP },
+	{ 0x070c, KEY_CHANNELDOWN },
+	{ 0x070f, KEY_1 },
+	{ 0x0715, KEY_2 },
+	{ 0x0710, KEY_3 },
+	{ 0x0718, KEY_4 },
+	{ 0x071b, KEY_5 },
+	{ 0x071e, KEY_6 },
+	{ 0x0711, KEY_7 },
+	{ 0x0721, KEY_8 },
+	{ 0x0712, KEY_9 },
+	{ 0x0727, KEY_0 },
+	{ 0x0724, KEY_SCREEN }, /* 'Square' key */
+	{ 0x072a, KEY_TEXT },   /* 'T' key */
+	{ 0x072d, KEY_REWIND },
+	{ 0x0730, KEY_PLAY },
+	{ 0x0733, KEY_FASTFORWARD },
+	{ 0x0736, KEY_RECORD },
+	{ 0x073c, KEY_STOP },
+	{ 0x073f, KEY_CANCEL }, /* '?' key */
+
+	/* Key codes for the Terratec Cinergy DT XS Diversity, similar to cinergyT2.c */
+	{ 0xeb01, KEY_POWER },
+	{ 0xeb02, KEY_1 },
+	{ 0xeb03, KEY_2 },
+	{ 0xeb04, KEY_3 },
+	{ 0xeb05, KEY_4 },
+	{ 0xeb06, KEY_5 },
+	{ 0xeb07, KEY_6 },
+	{ 0xeb08, KEY_7 },
+	{ 0xeb09, KEY_8 },
+	{ 0xeb0a, KEY_9 },
+	{ 0xeb0b, KEY_VIDEO },
+	{ 0xeb0c, KEY_0 },
+	{ 0xeb0d, KEY_REFRESH },
+	{ 0xeb0f, KEY_EPG },
+	{ 0xeb10, KEY_UP },
+	{ 0xeb11, KEY_LEFT },
+	{ 0xeb12, KEY_OK },
+	{ 0xeb13, KEY_RIGHT },
+	{ 0xeb14, KEY_DOWN },
+	{ 0xeb16, KEY_INFO },
+	{ 0xeb17, KEY_RED },
+	{ 0xeb18, KEY_GREEN },
+	{ 0xeb19, KEY_YELLOW },
+	{ 0xeb1a, KEY_BLUE },
+	{ 0xeb1b, KEY_CHANNELUP },
+	{ 0xeb1c, KEY_VOLUMEUP },
+	{ 0xeb1d, KEY_MUTE },
+	{ 0xeb1e, KEY_VOLUMEDOWN },
+	{ 0xeb1f, KEY_CHANNELDOWN },
+	{ 0xeb40, KEY_PAUSE },
+	{ 0xeb41, KEY_HOME },
+	{ 0xeb42, KEY_MENU }, /* DVD Menu */
+	{ 0xeb43, KEY_SUBTITLE },
+	{ 0xeb44, KEY_TEXT }, /* Teletext */
+	{ 0xeb45, KEY_DELETE },
+	{ 0xeb46, KEY_TV },
+	{ 0xeb47, KEY_DVD },
+	{ 0xeb48, KEY_STOP },
+	{ 0xeb49, KEY_VIDEO },
+	{ 0xeb4a, KEY_AUDIO }, /* Music */
+	{ 0xeb4b, KEY_SCREEN }, /* Pic */
+	{ 0xeb4c, KEY_PLAY },
+	{ 0xeb4d, KEY_BACK },
+	{ 0xeb4e, KEY_REWIND },
+	{ 0xeb4f, KEY_FASTFORWARD },
+	{ 0xeb54, KEY_PREVIOUS },
+	{ 0xeb58, KEY_RECORD },
+	{ 0xeb5c, KEY_NEXT },
+
+	/* Key codes for the Haupauge WinTV Nova-TD, copied from nova-t-usb2.c (Nova-T USB2) */
+	{ 0x1e00, KEY_0 },
+	{ 0x1e01, KEY_1 },
+	{ 0x1e02, KEY_2 },
+	{ 0x1e03, KEY_3 },
+	{ 0x1e04, KEY_4 },
+	{ 0x1e05, KEY_5 },
+	{ 0x1e06, KEY_6 },
+	{ 0x1e07, KEY_7 },
+	{ 0x1e08, KEY_8 },
+	{ 0x1e09, KEY_9 },
+	{ 0x1e0a, KEY_KPASTERISK },
+	{ 0x1e0b, KEY_RED },
+	{ 0x1e0c, KEY_RADIO },
+	{ 0x1e0d, KEY_MENU },
+	{ 0x1e0e, KEY_GRAVE }, /* # */
+	{ 0x1e0f, KEY_MUTE },
+	{ 0x1e10, KEY_VOLUMEUP },
+	{ 0x1e11, KEY_VOLUMEDOWN },
+	{ 0x1e12, KEY_CHANNEL },
+	{ 0x1e14, KEY_UP },
+	{ 0x1e15, KEY_DOWN },
+	{ 0x1e16, KEY_LEFT },
+	{ 0x1e17, KEY_RIGHT },
+	{ 0x1e18, KEY_VIDEO },
+	{ 0x1e19, KEY_AUDIO },
+	{ 0x1e1a, KEY_MEDIA },
+	{ 0x1e1b, KEY_EPG },
+	{ 0x1e1c, KEY_TV },
+	{ 0x1e1e, KEY_NEXT },
+	{ 0x1e1f, KEY_BACK },
+	{ 0x1e20, KEY_CHANNELUP },
+	{ 0x1e21, KEY_CHANNELDOWN },
+	{ 0x1e24, KEY_LAST }, /* Skip backwards */
+	{ 0x1e25, KEY_OK },
+	{ 0x1e29, KEY_BLUE},
+	{ 0x1e2e, KEY_GREEN },
+	{ 0x1e30, KEY_PAUSE },
+	{ 0x1e32, KEY_REWIND },
+	{ 0x1e34, KEY_FASTFORWARD },
+	{ 0x1e35, KEY_PLAY },
+	{ 0x1e36, KEY_STOP },
+	{ 0x1e37, KEY_RECORD },
+	{ 0x1e38, KEY_YELLOW },
+	{ 0x1e3b, KEY_GOTO },
+	{ 0x1e3d, KEY_POWER },
+
+	/* Key codes for the Leadtek Winfast DTV Dongle */
+	{ 0x0042, KEY_POWER },
+	{ 0x077c, KEY_TUNER },
+	{ 0x0f4e, KEY_PRINT }, /* PREVIEW */
+	{ 0x0840, KEY_SCREEN }, /* full screen toggle*/
+	{ 0x0f71, KEY_DOT }, /* frequency */
+	{ 0x0743, KEY_0 },
+	{ 0x0c41, KEY_1 },
+	{ 0x0443, KEY_2 },
+	{ 0x0b7f, KEY_3 },
+	{ 0x0e41, KEY_4 },
+	{ 0x0643, KEY_5 },
+	{ 0x097f, KEY_6 },
+	{ 0x0d7e, KEY_7 },
+	{ 0x057c, KEY_8 },
+	{ 0x0a40, KEY_9 },
+	{ 0x0e4e, KEY_CLEAR },
+	{ 0x047c, KEY_CHANNEL }, /* show channel number */
+	{ 0x0f41, KEY_LAST }, /* recall */
+	{ 0x0342, KEY_MUTE },
+	{ 0x064c, KEY_RESERVED }, /* PIP button*/
+	{ 0x0172, KEY_SHUFFLE }, /* SNAPSHOT */
+	{ 0x0c4e, KEY_PLAYPAUSE }, /* TIMESHIFT */
+	{ 0x0b70, KEY_RECORD },
+	{ 0x037d, KEY_VOLUMEUP },
+	{ 0x017d, KEY_VOLUMEDOWN },
+	{ 0x0242, KEY_CHANNELUP },
+	{ 0x007d, KEY_CHANNELDOWN },
+
+	/* Key codes for Nova-TD "credit card" remote control. */
+	{ 0x1d00, KEY_0 },
+	{ 0x1d01, KEY_1 },
+	{ 0x1d02, KEY_2 },
+	{ 0x1d03, KEY_3 },
+	{ 0x1d04, KEY_4 },
+	{ 0x1d05, KEY_5 },
+	{ 0x1d06, KEY_6 },
+	{ 0x1d07, KEY_7 },
+	{ 0x1d08, KEY_8 },
+	{ 0x1d09, KEY_9 },
+	{ 0x1d0a, KEY_TEXT },
+	{ 0x1d0d, KEY_MENU },
+	{ 0x1d0f, KEY_MUTE },
+	{ 0x1d10, KEY_VOLUMEUP },
+	{ 0x1d11, KEY_VOLUMEDOWN },
+	{ 0x1d12, KEY_CHANNEL },
+	{ 0x1d14, KEY_UP },
+	{ 0x1d15, KEY_DOWN },
+	{ 0x1d16, KEY_LEFT },
+	{ 0x1d17, KEY_RIGHT },
+	{ 0x1d1c, KEY_TV },
+	{ 0x1d1e, KEY_NEXT },
+	{ 0x1d1f, KEY_BACK },
+	{ 0x1d20, KEY_CHANNELUP },
+	{ 0x1d21, KEY_CHANNELDOWN },
+	{ 0x1d24, KEY_LAST },
+	{ 0x1d25, KEY_OK },
+	{ 0x1d30, KEY_PAUSE },
+	{ 0x1d32, KEY_REWIND },
+	{ 0x1d34, KEY_FASTFORWARD },
+	{ 0x1d35, KEY_PLAY },
+	{ 0x1d36, KEY_STOP },
+	{ 0x1d37, KEY_RECORD },
+	{ 0x1d3b, KEY_GOTO },
+	{ 0x1d3d, KEY_POWER },
+};
+
+static struct rc_map_list dib0700_rc5_map = {
+	.map = {
+		.scan    = dib0700_rc5_table,
+		.size    = ARRAY_SIZE(dib0700_rc5_table),
+		.rc_type = RC_TYPE_RC5,
+		.name    = RC_MAP_DIB0700_RC5_TABLE,
+	}
+};
+
+static int __init init_rc_map(void)
+{
+	return rc_map_register(&dib0700_rc5_map);
+}
+
+static void __exit exit_rc_map(void)
+{
+	rc_map_unregister(&dib0700_rc5_map);
+}
+
+module_init(init_rc_map)
+module_exit(exit_rc_map)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-digitalnow-tinytwin.c linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-digitalnow-tinytwin.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-digitalnow-tinytwin.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-digitalnow-tinytwin.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,98 @@
+/*
+ * DigitalNow TinyTwin remote controller keytable
+ *
+ * Copyright (C) 2010 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 <media/rc-map.h>
+
+static struct rc_map_table digitalnow_tinytwin[] = {
+	{ 0x0000, KEY_MUTE },            /* [symbol speaker] */
+	{ 0x0001, KEY_VOLUMEUP },
+	{ 0x0002, KEY_POWER2 },          /* TV [power button] */
+	{ 0x0003, KEY_2 },
+	{ 0x0004, KEY_3 },
+	{ 0x0005, KEY_4 },
+	{ 0x0006, KEY_6 },
+	{ 0x0007, KEY_7 },
+	{ 0x0008, KEY_8 },
+	{ 0x0009, KEY_NUMERIC_STAR },    /* [*] */
+	{ 0x000a, KEY_0 },
+	{ 0x000b, KEY_NUMERIC_POUND },   /* [#] */
+	{ 0x000c, KEY_RIGHT },           /* [right arrow] */
+	{ 0x000d, KEY_HOMEPAGE },        /* [symbol home] Start */
+	{ 0x000e, KEY_RED },             /* [red] Videos */
+	{ 0x0010, KEY_POWER },           /* PC [power button] */
+	{ 0x0011, KEY_YELLOW },          /* [yellow] Pictures */
+	{ 0x0012, KEY_DOWN },            /* [down arrow] */
+	{ 0x0013, KEY_GREEN },           /* [green] Music */
+	{ 0x0014, KEY_CYCLEWINDOWS },    /* BACK */
+	{ 0x0015, KEY_FAVORITES },       /* MORE */
+	{ 0x0016, KEY_UP },              /* [up arrow] */
+	{ 0x0017, KEY_LEFT },            /* [left arrow] */
+	{ 0x0018, KEY_OK },              /* OK */
+	{ 0x0019, KEY_BLUE },            /* [blue] MyTV */
+	{ 0x001a, KEY_REWIND },          /* REW [<<] */
+	{ 0x001b, KEY_PLAY },            /* PLAY */
+	{ 0x001c, KEY_5 },
+	{ 0x001d, KEY_9 },
+	{ 0x001e, KEY_VOLUMEDOWN },
+	{ 0x001f, KEY_1 },
+	{ 0x0040, KEY_STOP },            /* STOP */
+	{ 0x0042, KEY_PAUSE },           /* PAUSE */
+	{ 0x0043, KEY_SCREEN },          /* Aspect */
+	{ 0x0044, KEY_FORWARD },         /* FWD [>>] */
+	{ 0x0045, KEY_NEXT },            /* SKIP */
+	{ 0x0048, KEY_RECORD },          /* RECORD */
+	{ 0x0049, KEY_VIDEO },           /* RTV */
+	{ 0x004a, KEY_EPG },             /* Guide */
+	{ 0x004b, KEY_CHANNELUP },
+	{ 0x004c, KEY_HELP },            /* Help */
+	{ 0x004d, KEY_RADIO },           /* Radio */
+	{ 0x004f, KEY_CHANNELDOWN },
+	{ 0x0050, KEY_DVD },             /* DVD */
+	{ 0x0051, KEY_AUDIO },           /* Audio */
+	{ 0x0052, KEY_TITLE },           /* Title */
+	{ 0x0053, KEY_NEW },             /* [symbol PIP?] */
+	{ 0x0057, KEY_MENU },            /* Mouse */
+	{ 0x005a, KEY_PREVIOUS },        /* REPLAY */
+};
+
+static struct rc_map_list digitalnow_tinytwin_map = {
+	.map = {
+		.scan    = digitalnow_tinytwin,
+		.size    = ARRAY_SIZE(digitalnow_tinytwin),
+		.rc_type = RC_TYPE_NEC,
+		.name    = RC_MAP_DIGITALNOW_TINYTWIN,
+	}
+};
+
+static int __init init_rc_map_digitalnow_tinytwin(void)
+{
+	return rc_map_register(&digitalnow_tinytwin_map);
+}
+
+static void __exit exit_rc_map_digitalnow_tinytwin(void)
+{
+	rc_map_unregister(&digitalnow_tinytwin_map);
+}
+
+module_init(init_rc_map_digitalnow_tinytwin)
+module_exit(exit_rc_map_digitalnow_tinytwin)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-digittrade.c linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-digittrade.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-digittrade.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-digittrade.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,82 @@
+/*
+ * Digittrade DVB-T USB Stick remote controller keytable
+ *
+ * Copyright (C) 2010 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 <media/rc-map.h>
+
+/* Digittrade DVB-T USB Stick remote controller. */
+/* Imported from af9015.h.
+   Initial keytable was from Alain Kalker <miki@dds.nl> */
+
+/* Digittrade DVB-T USB Stick */
+static struct rc_map_table digittrade[] = {
+	{ 0x0000, KEY_9 },
+	{ 0x0001, KEY_EPG },             /* EPG */
+	{ 0x0002, KEY_VOLUMEDOWN },      /* Vol Dn */
+	{ 0x0003, KEY_TEXT },            /* TELETEXT */
+	{ 0x0004, KEY_8 },
+	{ 0x0005, KEY_MUTE },            /* MUTE */
+	{ 0x0006, KEY_POWER2 },          /* POWER */
+	{ 0x0009, KEY_ZOOM },            /* FULLSCREEN */
+	{ 0x000a, KEY_RECORD },          /* RECORD */
+	{ 0x000d, KEY_SUBTITLE },        /* SUBTITLE */
+	{ 0x000e, KEY_STOP },            /* STOP */
+	{ 0x0010, KEY_OK },              /* RETURN */
+	{ 0x0011, KEY_2 },
+	{ 0x0012, KEY_4 },
+	{ 0x0015, KEY_3 },
+	{ 0x0016, KEY_5 },
+	{ 0x0017, KEY_CHANNELDOWN },     /* Ch Dn */
+	{ 0x0019, KEY_CHANNELUP },       /* CH Up */
+	{ 0x001a, KEY_PAUSE },           /* PAUSE */
+	{ 0x001b, KEY_1 },
+	{ 0x001d, KEY_AUDIO },           /* DUAL SOUND */
+	{ 0x001e, KEY_PLAY },            /* PLAY */
+	{ 0x001f, KEY_CAMERA },          /* SNAPSHOT */
+	{ 0x0040, KEY_VOLUMEUP },        /* Vol Up */
+	{ 0x0048, KEY_7 },
+	{ 0x004c, KEY_6 },
+	{ 0x004d, KEY_PLAYPAUSE },       /* TIMESHIFT */
+	{ 0x0054, KEY_0 },
+};
+
+static struct rc_map_list digittrade_map = {
+	.map = {
+		.scan    = digittrade,
+		.size    = ARRAY_SIZE(digittrade),
+		.rc_type = RC_TYPE_NEC,
+		.name    = RC_MAP_DIGITTRADE,
+	}
+};
+
+static int __init init_rc_map_digittrade(void)
+{
+	return rc_map_register(&digittrade_map);
+}
+
+static void __exit exit_rc_map_digittrade(void)
+{
+	rc_map_unregister(&digittrade_map);
+}
+
+module_init(init_rc_map_digittrade)
+module_exit(exit_rc_map_digittrade)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-dm1105-nec.c linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-dm1105-nec.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-dm1105-nec.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-dm1105-nec.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,76 @@
+/* dm1105-nec.h - Keytable for dm1105_nec Remote Controller
+ *
+ * keymap imported from ir-keymaps.c
+ *
+ * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
+
+/* DVBWorld remotes
+   Igor M. Liplianin <liplianin@me.by>
+ */
+
+static struct rc_map_table dm1105_nec[] = {
+	{ 0x0a, KEY_POWER2},		/* power */
+	{ 0x0c, KEY_MUTE},		/* mute */
+	{ 0x11, KEY_1},
+	{ 0x12, KEY_2},
+	{ 0x13, KEY_3},
+	{ 0x14, KEY_4},
+	{ 0x15, KEY_5},
+	{ 0x16, KEY_6},
+	{ 0x17, KEY_7},
+	{ 0x18, KEY_8},
+	{ 0x19, KEY_9},
+	{ 0x10, KEY_0},
+	{ 0x1c, KEY_CHANNELUP},		/* ch+ */
+	{ 0x0f, KEY_CHANNELDOWN},	/* ch- */
+	{ 0x1a, KEY_VOLUMEUP},		/* vol+ */
+	{ 0x0e, KEY_VOLUMEDOWN},	/* vol- */
+	{ 0x04, KEY_RECORD},		/* rec */
+	{ 0x09, KEY_CHANNEL},		/* fav */
+	{ 0x08, KEY_BACKSPACE},		/* rewind */
+	{ 0x07, KEY_FASTFORWARD},	/* fast */
+	{ 0x0b, KEY_PAUSE},		/* pause */
+	{ 0x02, KEY_ESC},		/* cancel */
+	{ 0x03, KEY_TAB},		/* tab */
+	{ 0x00, KEY_UP},		/* up */
+	{ 0x1f, KEY_ENTER},		/* ok */
+	{ 0x01, KEY_DOWN},		/* down */
+	{ 0x05, KEY_RECORD},		/* cap */
+	{ 0x06, KEY_STOP},		/* stop */
+	{ 0x40, KEY_ZOOM},		/* full */
+	{ 0x1e, KEY_TV},		/* tvmode */
+	{ 0x1b, KEY_B},			/* recall */
+};
+
+static struct rc_map_list dm1105_nec_map = {
+	.map = {
+		.scan    = dm1105_nec,
+		.size    = ARRAY_SIZE(dm1105_nec),
+		.rc_type = RC_TYPE_UNKNOWN,	/* Legacy IR type */
+		.name    = RC_MAP_DM1105_NEC,
+	}
+};
+
+static int __init init_rc_map_dm1105_nec(void)
+{
+	return rc_map_register(&dm1105_nec_map);
+}
+
+static void __exit exit_rc_map_dm1105_nec(void)
+{
+	rc_map_unregister(&dm1105_nec_map);
+}
+
+module_init(init_rc_map_dm1105_nec)
+module_exit(exit_rc_map_dm1105_nec)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-dntv-live-dvb-t.c linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-dntv-live-dvb-t.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-dntv-live-dvb-t.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-dntv-live-dvb-t.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,78 @@
+/* dntv-live-dvb-t.h - Keytable for dntv_live_dvb_t Remote Controller
+ *
+ * keymap imported from ir-keymaps.c
+ *
+ * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
+
+/* DigitalNow DNTV Live DVB-T Remote */
+
+static struct rc_map_table dntv_live_dvb_t[] = {
+	{ 0x00, KEY_ESC },		/* 'go up a level?' */
+	/* Keys 0 to 9 */
+	{ 0x0a, KEY_0 },
+	{ 0x01, KEY_1 },
+	{ 0x02, KEY_2 },
+	{ 0x03, KEY_3 },
+	{ 0x04, KEY_4 },
+	{ 0x05, KEY_5 },
+	{ 0x06, KEY_6 },
+	{ 0x07, KEY_7 },
+	{ 0x08, KEY_8 },
+	{ 0x09, KEY_9 },
+
+	{ 0x0b, KEY_TUNER },		/* tv/fm */
+	{ 0x0c, KEY_SEARCH },		/* scan */
+	{ 0x0d, KEY_STOP },
+	{ 0x0e, KEY_PAUSE },
+	{ 0x0f, KEY_LIST },		/* source */
+
+	{ 0x10, KEY_MUTE },
+	{ 0x11, KEY_REWIND },		/* backward << */
+	{ 0x12, KEY_POWER },
+	{ 0x13, KEY_CAMERA },		/* snap */
+	{ 0x14, KEY_AUDIO },		/* stereo */
+	{ 0x15, KEY_CLEAR },		/* reset */
+	{ 0x16, KEY_PLAY },
+	{ 0x17, KEY_ENTER },
+	{ 0x18, KEY_ZOOM },		/* full screen */
+	{ 0x19, KEY_FASTFORWARD },	/* forward >> */
+	{ 0x1a, KEY_CHANNELUP },
+	{ 0x1b, KEY_VOLUMEUP },
+	{ 0x1c, KEY_INFO },		/* preview */
+	{ 0x1d, KEY_RECORD },		/* record */
+	{ 0x1e, KEY_CHANNELDOWN },
+	{ 0x1f, KEY_VOLUMEDOWN },
+};
+
+static struct rc_map_list dntv_live_dvb_t_map = {
+	.map = {
+		.scan    = dntv_live_dvb_t,
+		.size    = ARRAY_SIZE(dntv_live_dvb_t),
+		.rc_type = RC_TYPE_UNKNOWN,	/* Legacy IR type */
+		.name    = RC_MAP_DNTV_LIVE_DVB_T,
+	}
+};
+
+static int __init init_rc_map_dntv_live_dvb_t(void)
+{
+	return rc_map_register(&dntv_live_dvb_t_map);
+}
+
+static void __exit exit_rc_map_dntv_live_dvb_t(void)
+{
+	rc_map_unregister(&dntv_live_dvb_t_map);
+}
+
+module_init(init_rc_map_dntv_live_dvb_t)
+module_exit(exit_rc_map_dntv_live_dvb_t)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-dntv-live-dvbt-pro.c linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-dntv-live-dvbt-pro.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-dntv-live-dvbt-pro.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-dntv-live-dvbt-pro.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,97 @@
+/* dntv-live-dvbt-pro.h - Keytable for dntv_live_dvbt_pro Remote Controller
+ *
+ * keymap imported from ir-keymaps.c
+ *
+ * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
+
+/* DigitalNow DNTV Live! DVB-T Pro Remote */
+
+static struct rc_map_table dntv_live_dvbt_pro[] = {
+	{ 0x16, KEY_POWER },
+	{ 0x5b, KEY_HOME },
+
+	{ 0x55, KEY_TV },		/* live tv */
+	{ 0x58, KEY_TUNER },		/* digital Radio */
+	{ 0x5a, KEY_RADIO },		/* FM radio */
+	{ 0x59, KEY_DVD },		/* dvd menu */
+	{ 0x03, KEY_1 },
+	{ 0x01, KEY_2 },
+	{ 0x06, KEY_3 },
+	{ 0x09, KEY_4 },
+	{ 0x1d, KEY_5 },
+	{ 0x1f, KEY_6 },
+	{ 0x0d, KEY_7 },
+	{ 0x19, KEY_8 },
+	{ 0x1b, KEY_9 },
+	{ 0x0c, KEY_CANCEL },
+	{ 0x15, KEY_0 },
+	{ 0x4a, KEY_CLEAR },
+	{ 0x13, KEY_BACK },
+	{ 0x00, KEY_TAB },
+	{ 0x4b, KEY_UP },
+	{ 0x4e, KEY_LEFT },
+	{ 0x4f, KEY_OK },
+	{ 0x52, KEY_RIGHT },
+	{ 0x51, KEY_DOWN },
+	{ 0x1e, KEY_VOLUMEUP },
+	{ 0x0a, KEY_VOLUMEDOWN },
+	{ 0x02, KEY_CHANNELDOWN },
+	{ 0x05, KEY_CHANNELUP },
+	{ 0x11, KEY_RECORD },
+	{ 0x14, KEY_PLAY },
+	{ 0x4c, KEY_PAUSE },
+	{ 0x1a, KEY_STOP },
+	{ 0x40, KEY_REWIND },
+	{ 0x12, KEY_FASTFORWARD },
+	{ 0x41, KEY_PREVIOUSSONG },	/* replay |< */
+	{ 0x42, KEY_NEXTSONG },		/* skip >| */
+	{ 0x54, KEY_CAMERA },		/* capture */
+	{ 0x50, KEY_LANGUAGE },		/* sap */
+	{ 0x47, KEY_TV2 },		/* pip */
+	{ 0x4d, KEY_SCREEN },
+	{ 0x43, KEY_SUBTITLE },
+	{ 0x10, KEY_MUTE },
+	{ 0x49, KEY_AUDIO },		/* l/r */
+	{ 0x07, KEY_SLEEP },
+	{ 0x08, KEY_VIDEO },		/* a/v */
+	{ 0x0e, KEY_PREVIOUS },		/* recall */
+	{ 0x45, KEY_ZOOM },		/* zoom + */
+	{ 0x46, KEY_ANGLE },		/* zoom - */
+	{ 0x56, KEY_RED },
+	{ 0x57, KEY_GREEN },
+	{ 0x5c, KEY_YELLOW },
+	{ 0x5d, KEY_BLUE },
+};
+
+static struct rc_map_list dntv_live_dvbt_pro_map = {
+	.map = {
+		.scan    = dntv_live_dvbt_pro,
+		.size    = ARRAY_SIZE(dntv_live_dvbt_pro),
+		.rc_type = RC_TYPE_UNKNOWN,	/* Legacy IR type */
+		.name    = RC_MAP_DNTV_LIVE_DVBT_PRO,
+	}
+};
+
+static int __init init_rc_map_dntv_live_dvbt_pro(void)
+{
+	return rc_map_register(&dntv_live_dvbt_pro_map);
+}
+
+static void __exit exit_rc_map_dntv_live_dvbt_pro(void)
+{
+	rc_map_unregister(&dntv_live_dvbt_pro_map);
+}
+
+module_init(init_rc_map_dntv_live_dvbt_pro)
+module_exit(exit_rc_map_dntv_live_dvbt_pro)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-em-terratec.c linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-em-terratec.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-em-terratec.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-em-terratec.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,69 @@
+/* em-terratec.h - Keytable for em_terratec Remote Controller
+ *
+ * keymap imported from ir-keymaps.c
+ *
+ * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
+
+static struct rc_map_table em_terratec[] = {
+	{ 0x01, KEY_CHANNEL },
+	{ 0x02, KEY_SELECT },
+	{ 0x03, KEY_MUTE },
+	{ 0x04, KEY_POWER },
+	{ 0x05, KEY_1 },
+	{ 0x06, KEY_2 },
+	{ 0x07, KEY_3 },
+	{ 0x08, KEY_CHANNELUP },
+	{ 0x09, KEY_4 },
+	{ 0x0a, KEY_5 },
+	{ 0x0b, KEY_6 },
+	{ 0x0c, KEY_CHANNELDOWN },
+	{ 0x0d, KEY_7 },
+	{ 0x0e, KEY_8 },
+	{ 0x0f, KEY_9 },
+	{ 0x10, KEY_VOLUMEUP },
+	{ 0x11, KEY_0 },
+	{ 0x12, KEY_MENU },
+	{ 0x13, KEY_PRINT },
+	{ 0x14, KEY_VOLUMEDOWN },
+	{ 0x16, KEY_PAUSE },
+	{ 0x18, KEY_RECORD },
+	{ 0x19, KEY_REWIND },
+	{ 0x1a, KEY_PLAY },
+	{ 0x1b, KEY_FORWARD },
+	{ 0x1c, KEY_BACKSPACE },
+	{ 0x1e, KEY_STOP },
+	{ 0x40, KEY_ZOOM },
+};
+
+static struct rc_map_list em_terratec_map = {
+	.map = {
+		.scan    = em_terratec,
+		.size    = ARRAY_SIZE(em_terratec),
+		.rc_type = RC_TYPE_UNKNOWN,	/* Legacy IR type */
+		.name    = RC_MAP_EM_TERRATEC,
+	}
+};
+
+static int __init init_rc_map_em_terratec(void)
+{
+	return rc_map_register(&em_terratec_map);
+}
+
+static void __exit exit_rc_map_em_terratec(void)
+{
+	rc_map_unregister(&em_terratec_map);
+}
+
+module_init(init_rc_map_em_terratec)
+module_exit(exit_rc_map_em_terratec)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-encore-enltv2.c linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-encore-enltv2.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-encore-enltv2.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-encore-enltv2.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,90 @@
+/* encore-enltv2.h - Keytable for encore_enltv2 Remote Controller
+ *
+ * keymap imported from ir-keymaps.c
+ *
+ * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
+
+/* Encore ENLTV2-FM  - silver plastic - "Wand Media" written at the botton
+    Mauro Carvalho Chehab <mchehab@infradead.org> */
+
+static struct rc_map_table encore_enltv2[] = {
+	{ 0x4c, KEY_POWER2 },
+	{ 0x4a, KEY_TUNER },
+	{ 0x40, KEY_1 },
+	{ 0x60, KEY_2 },
+	{ 0x50, KEY_3 },
+	{ 0x70, KEY_4 },
+	{ 0x48, KEY_5 },
+	{ 0x68, KEY_6 },
+	{ 0x58, KEY_7 },
+	{ 0x78, KEY_8 },
+	{ 0x44, KEY_9 },
+	{ 0x54, KEY_0 },
+
+	{ 0x64, KEY_LAST },		/* +100 */
+	{ 0x4e, KEY_AGAIN },		/* Recall */
+
+	{ 0x6c, KEY_SWITCHVIDEOMODE },	/* Video Source */
+	{ 0x5e, KEY_MENU },
+	{ 0x56, KEY_SCREEN },
+	{ 0x7a, KEY_SETUP },
+
+	{ 0x46, KEY_MUTE },
+	{ 0x5c, KEY_MODE },		/* Stereo */
+	{ 0x74, KEY_INFO },
+	{ 0x7c, KEY_CLEAR },
+
+	{ 0x55, KEY_UP },
+	{ 0x49, KEY_DOWN },
+	{ 0x7e, KEY_LEFT },
+	{ 0x59, KEY_RIGHT },
+	{ 0x6a, KEY_ENTER },
+
+	{ 0x42, KEY_VOLUMEUP },
+	{ 0x62, KEY_VOLUMEDOWN },
+	{ 0x52, KEY_CHANNELUP },
+	{ 0x72, KEY_CHANNELDOWN },
+
+	{ 0x41, KEY_RECORD },
+	{ 0x51, KEY_CAMERA },		/* Snapshot */
+	{ 0x75, KEY_TIME },		/* Timeshift */
+	{ 0x71, KEY_TV2 },		/* PIP */
+
+	{ 0x45, KEY_REWIND },
+	{ 0x6f, KEY_PAUSE },
+	{ 0x7d, KEY_FORWARD },
+	{ 0x79, KEY_STOP },
+};
+
+static struct rc_map_list encore_enltv2_map = {
+	.map = {
+		.scan    = encore_enltv2,
+		.size    = ARRAY_SIZE(encore_enltv2),
+		.rc_type = RC_TYPE_UNKNOWN,	/* Legacy IR type */
+		.name    = RC_MAP_ENCORE_ENLTV2,
+	}
+};
+
+static int __init init_rc_map_encore_enltv2(void)
+{
+	return rc_map_register(&encore_enltv2_map);
+}
+
+static void __exit exit_rc_map_encore_enltv2(void)
+{
+	rc_map_unregister(&encore_enltv2_map);
+}
+
+module_init(init_rc_map_encore_enltv2)
+module_exit(exit_rc_map_encore_enltv2)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-encore-enltv.c linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-encore-enltv.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-encore-enltv.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-encore-enltv.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,112 @@
+/* encore-enltv.h - Keytable for encore_enltv Remote Controller
+ *
+ * keymap imported from ir-keymaps.c
+ *
+ * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
+
+/* Encore ENLTV-FM  - black plastic, white front cover with white glowing buttons
+    Juan Pablo Sormani <sorman@gmail.com> */
+
+static struct rc_map_table encore_enltv[] = {
+
+	/* Power button does nothing, neither in Windows app,
+	 although it sends data (used for BIOS wakeup?) */
+	{ 0x0d, KEY_MUTE },
+
+	{ 0x1e, KEY_TV },
+	{ 0x00, KEY_VIDEO },
+	{ 0x01, KEY_AUDIO },		/* music */
+	{ 0x02, KEY_MHP },		/* picture */
+
+	{ 0x1f, KEY_1 },
+	{ 0x03, KEY_2 },
+	{ 0x04, KEY_3 },
+	{ 0x05, KEY_4 },
+	{ 0x1c, KEY_5 },
+	{ 0x06, KEY_6 },
+	{ 0x07, KEY_7 },
+	{ 0x08, KEY_8 },
+	{ 0x1d, KEY_9 },
+	{ 0x0a, KEY_0 },
+
+	{ 0x09, KEY_LIST },		/* -/-- */
+	{ 0x0b, KEY_LAST },		/* recall */
+
+	{ 0x14, KEY_HOME },		/* win start menu */
+	{ 0x15, KEY_EXIT },		/* exit */
+	{ 0x16, KEY_CHANNELUP },	/* UP */
+	{ 0x12, KEY_CHANNELDOWN },	/* DOWN */
+	{ 0x0c, KEY_VOLUMEUP },		/* RIGHT */
+	{ 0x17, KEY_VOLUMEDOWN },	/* LEFT */
+
+	{ 0x18, KEY_ENTER },		/* OK */
+
+	{ 0x0e, KEY_ESC },
+	{ 0x13, KEY_CYCLEWINDOWS },	/* desktop */
+	{ 0x11, KEY_TAB },
+	{ 0x19, KEY_SWITCHVIDEOMODE },	/* switch */
+
+	{ 0x1a, KEY_MENU },
+	{ 0x1b, KEY_ZOOM },		/* fullscreen */
+	{ 0x44, KEY_TIME },		/* time shift */
+	{ 0x40, KEY_MODE },		/* source */
+
+	{ 0x5a, KEY_RECORD },
+	{ 0x42, KEY_PLAY },		/* play/pause */
+	{ 0x45, KEY_STOP },
+	{ 0x43, KEY_CAMERA },		/* camera icon */
+
+	{ 0x48, KEY_REWIND },
+	{ 0x4a, KEY_FASTFORWARD },
+	{ 0x49, KEY_PREVIOUS },
+	{ 0x4b, KEY_NEXT },
+
+	{ 0x4c, KEY_FAVORITES },	/* tv wall */
+	{ 0x4d, KEY_SOUND },		/* DVD sound */
+	{ 0x4e, KEY_LANGUAGE },		/* DVD lang */
+	{ 0x4f, KEY_TEXT },		/* DVD text */
+
+	{ 0x50, KEY_SLEEP },		/* shutdown */
+	{ 0x51, KEY_MODE },		/* stereo > main */
+	{ 0x52, KEY_SELECT },		/* stereo > sap */
+	{ 0x53, KEY_PROG1 },		/* teletext */
+
+
+	{ 0x59, KEY_RED },		/* AP1 */
+	{ 0x41, KEY_GREEN },		/* AP2 */
+	{ 0x47, KEY_YELLOW },		/* AP3 */
+	{ 0x57, KEY_BLUE },		/* AP4 */
+};
+
+static struct rc_map_list encore_enltv_map = {
+	.map = {
+		.scan    = encore_enltv,
+		.size    = ARRAY_SIZE(encore_enltv),
+		.rc_type = RC_TYPE_UNKNOWN,	/* Legacy IR type */
+		.name    = RC_MAP_ENCORE_ENLTV,
+	}
+};
+
+static int __init init_rc_map_encore_enltv(void)
+{
+	return rc_map_register(&encore_enltv_map);
+}
+
+static void __exit exit_rc_map_encore_enltv(void)
+{
+	rc_map_unregister(&encore_enltv_map);
+}
+
+module_init(init_rc_map_encore_enltv)
+module_exit(exit_rc_map_encore_enltv)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-encore-enltv-fm53.c linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-encore-enltv-fm53.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-encore-enltv-fm53.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-encore-enltv-fm53.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,81 @@
+/* encore-enltv-fm53.h - Keytable for encore_enltv_fm53 Remote Controller
+ *
+ * keymap imported from ir-keymaps.c
+ *
+ * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
+
+/* Encore ENLTV-FM v5.3
+   Mauro Carvalho Chehab <mchehab@infradead.org>
+ */
+
+static struct rc_map_table encore_enltv_fm53[] = {
+	{ 0x10, KEY_POWER2},
+	{ 0x06, KEY_MUTE},
+
+	{ 0x09, KEY_1},
+	{ 0x1d, KEY_2},
+	{ 0x1f, KEY_3},
+	{ 0x19, KEY_4},
+	{ 0x1b, KEY_5},
+	{ 0x11, KEY_6},
+	{ 0x17, KEY_7},
+	{ 0x12, KEY_8},
+	{ 0x16, KEY_9},
+	{ 0x48, KEY_0},
+
+	{ 0x04, KEY_LIST},		/* -/-- */
+	{ 0x40, KEY_LAST},		/* recall */
+
+	{ 0x02, KEY_MODE},		/* TV/AV */
+	{ 0x05, KEY_CAMERA},		/* SNAPSHOT */
+
+	{ 0x4c, KEY_CHANNELUP},		/* UP */
+	{ 0x00, KEY_CHANNELDOWN},	/* DOWN */
+	{ 0x0d, KEY_VOLUMEUP},		/* RIGHT */
+	{ 0x15, KEY_VOLUMEDOWN},	/* LEFT */
+	{ 0x49, KEY_ENTER},		/* OK */
+
+	{ 0x54, KEY_RECORD},
+	{ 0x4d, KEY_PLAY},		/* pause */
+
+	{ 0x1e, KEY_MENU},		/* video setting */
+	{ 0x0e, KEY_RIGHT},		/* <- */
+	{ 0x1a, KEY_LEFT},		/* -> */
+
+	{ 0x0a, KEY_CLEAR},		/* video default */
+	{ 0x0c, KEY_ZOOM},		/* hide pannel */
+	{ 0x47, KEY_SLEEP},		/* shutdown */
+};
+
+static struct rc_map_list encore_enltv_fm53_map = {
+	.map = {
+		.scan    = encore_enltv_fm53,
+		.size    = ARRAY_SIZE(encore_enltv_fm53),
+		.rc_type = RC_TYPE_UNKNOWN,	/* Legacy IR type */
+		.name    = RC_MAP_ENCORE_ENLTV_FM53,
+	}
+};
+
+static int __init init_rc_map_encore_enltv_fm53(void)
+{
+	return rc_map_register(&encore_enltv_fm53_map);
+}
+
+static void __exit exit_rc_map_encore_enltv_fm53(void)
+{
+	rc_map_unregister(&encore_enltv_fm53_map);
+}
+
+module_init(init_rc_map_encore_enltv_fm53)
+module_exit(exit_rc_map_encore_enltv_fm53)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-evga-indtube.c linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-evga-indtube.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-evga-indtube.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-evga-indtube.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,61 @@
+/* evga-indtube.h - Keytable for evga_indtube Remote Controller
+ *
+ * keymap imported from ir-keymaps.c
+ *
+ * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
+
+/* EVGA inDtube
+   Devin Heitmueller <devin.heitmueller@gmail.com>
+ */
+
+static struct rc_map_table evga_indtube[] = {
+	{ 0x12, KEY_POWER},
+	{ 0x02, KEY_MODE},	/* TV */
+	{ 0x14, KEY_MUTE},
+	{ 0x1a, KEY_CHANNELUP},
+	{ 0x16, KEY_TV2},	/* PIP */
+	{ 0x1d, KEY_VOLUMEUP},
+	{ 0x05, KEY_CHANNELDOWN},
+	{ 0x0f, KEY_PLAYPAUSE},
+	{ 0x19, KEY_VOLUMEDOWN},
+	{ 0x1c, KEY_REWIND},
+	{ 0x0d, KEY_RECORD},
+	{ 0x18, KEY_FORWARD},
+	{ 0x1e, KEY_PREVIOUS},
+	{ 0x1b, KEY_STOP},
+	{ 0x1f, KEY_NEXT},
+	{ 0x13, KEY_CAMERA},
+};
+
+static struct rc_map_list evga_indtube_map = {
+	.map = {
+		.scan    = evga_indtube,
+		.size    = ARRAY_SIZE(evga_indtube),
+		.rc_type = RC_TYPE_UNKNOWN,	/* Legacy IR type */
+		.name    = RC_MAP_EVGA_INDTUBE,
+	}
+};
+
+static int __init init_rc_map_evga_indtube(void)
+{
+	return rc_map_register(&evga_indtube_map);
+}
+
+static void __exit exit_rc_map_evga_indtube(void)
+{
+	rc_map_unregister(&evga_indtube_map);
+}
+
+module_init(init_rc_map_evga_indtube)
+module_exit(exit_rc_map_evga_indtube)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-eztv.c linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-eztv.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-eztv.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-eztv.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,96 @@
+/* eztv.h - Keytable for eztv Remote Controller
+ *
+ * keymap imported from ir-keymaps.c
+ *
+ * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
+
+/* Alfons Geser <a.geser@cox.net>
+ * updates from Job D. R. Borges <jobdrb@ig.com.br> */
+
+static struct rc_map_table eztv[] = {
+	{ 0x12, KEY_POWER },
+	{ 0x01, KEY_TV },	/* DVR */
+	{ 0x15, KEY_DVD },	/* DVD */
+	{ 0x17, KEY_AUDIO },	/* music */
+				/* DVR mode / DVD mode / music mode */
+
+	{ 0x1b, KEY_MUTE },	/* mute */
+	{ 0x02, KEY_LANGUAGE },	/* MTS/SAP / audio / autoseek */
+	{ 0x1e, KEY_SUBTITLE },	/* closed captioning / subtitle / seek */
+	{ 0x16, KEY_ZOOM },	/* full screen */
+	{ 0x1c, KEY_VIDEO },	/* video source / eject / delall */
+	{ 0x1d, KEY_RESTART },	/* playback / angle / del */
+	{ 0x2f, KEY_SEARCH },	/* scan / menu / playlist */
+	{ 0x30, KEY_CHANNEL },	/* CH surfing / bookmark / memo */
+
+	{ 0x31, KEY_HELP },	/* help */
+	{ 0x32, KEY_MODE },	/* num/memo */
+	{ 0x33, KEY_ESC },	/* cancel */
+
+	{ 0x0c, KEY_UP },	/* up */
+	{ 0x10, KEY_DOWN },	/* down */
+	{ 0x08, KEY_LEFT },	/* left */
+	{ 0x04, KEY_RIGHT },	/* right */
+	{ 0x03, KEY_SELECT },	/* select */
+
+	{ 0x1f, KEY_REWIND },	/* rewind */
+	{ 0x20, KEY_PLAYPAUSE },/* play/pause */
+	{ 0x29, KEY_FORWARD },	/* forward */
+	{ 0x14, KEY_AGAIN },	/* repeat */
+	{ 0x2b, KEY_RECORD },	/* recording */
+	{ 0x2c, KEY_STOP },	/* stop */
+	{ 0x2d, KEY_PLAY },	/* play */
+	{ 0x2e, KEY_CAMERA },	/* snapshot / shuffle */
+
+	{ 0x00, KEY_0 },
+	{ 0x05, KEY_1 },
+	{ 0x06, KEY_2 },
+	{ 0x07, KEY_3 },
+	{ 0x09, KEY_4 },
+	{ 0x0a, KEY_5 },
+	{ 0x0b, KEY_6 },
+	{ 0x0d, KEY_7 },
+	{ 0x0e, KEY_8 },
+	{ 0x0f, KEY_9 },
+
+	{ 0x2a, KEY_VOLUMEUP },
+	{ 0x11, KEY_VOLUMEDOWN },
+	{ 0x18, KEY_CHANNELUP },/* CH.tracking up */
+	{ 0x19, KEY_CHANNELDOWN },/* CH.tracking down */
+
+	{ 0x13, KEY_ENTER },	/* enter */
+	{ 0x21, KEY_DOT },	/* . (decimal dot) */
+};
+
+static struct rc_map_list eztv_map = {
+	.map = {
+		.scan    = eztv,
+		.size    = ARRAY_SIZE(eztv),
+		.rc_type = RC_TYPE_UNKNOWN,	/* Legacy IR type */
+		.name    = RC_MAP_EZTV,
+	}
+};
+
+static int __init init_rc_map_eztv(void)
+{
+	return rc_map_register(&eztv_map);
+}
+
+static void __exit exit_rc_map_eztv(void)
+{
+	rc_map_unregister(&eztv_map);
+}
+
+module_init(init_rc_map_eztv)
+module_exit(exit_rc_map_eztv)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-flydvb.c linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-flydvb.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-flydvb.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-flydvb.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,77 @@
+/* flydvb.h - Keytable for flydvb Remote Controller
+ *
+ * keymap imported from ir-keymaps.c
+ *
+ * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
+
+static struct rc_map_table flydvb[] = {
+	{ 0x01, KEY_ZOOM },		/* Full Screen */
+	{ 0x00, KEY_POWER },		/* Power */
+
+	{ 0x03, KEY_1 },
+	{ 0x04, KEY_2 },
+	{ 0x05, KEY_3 },
+	{ 0x07, KEY_4 },
+	{ 0x08, KEY_5 },
+	{ 0x09, KEY_6 },
+	{ 0x0b, KEY_7 },
+	{ 0x0c, KEY_8 },
+	{ 0x0d, KEY_9 },
+	{ 0x06, KEY_AGAIN },		/* Recall */
+	{ 0x0f, KEY_0 },
+	{ 0x10, KEY_MUTE },		/* Mute */
+	{ 0x02, KEY_RADIO },		/* TV/Radio */
+	{ 0x1b, KEY_LANGUAGE },		/* SAP (Second Audio Program) */
+
+	{ 0x14, KEY_VOLUMEUP },		/* VOL+ */
+	{ 0x17, KEY_VOLUMEDOWN },	/* VOL- */
+	{ 0x12, KEY_CHANNELUP },	/* CH+ */
+	{ 0x13, KEY_CHANNELDOWN },	/* CH- */
+	{ 0x1d, KEY_ENTER },		/* Enter */
+
+	{ 0x1a, KEY_MODE },		/* PIP */
+	{ 0x18, KEY_TUNER },		/* Source */
+
+	{ 0x1e, KEY_RECORD },		/* Record/Pause */
+	{ 0x15, KEY_ANGLE },		/* Swap (no label on key) */
+	{ 0x1c, KEY_PAUSE },		/* Timeshift/Pause */
+	{ 0x19, KEY_BACK },		/* Rewind << */
+	{ 0x0a, KEY_PLAYPAUSE },	/* Play/Pause */
+	{ 0x1f, KEY_FORWARD },		/* Forward >> */
+	{ 0x16, KEY_PREVIOUS },		/* Back |<< */
+	{ 0x11, KEY_STOP },		/* Stop */
+	{ 0x0e, KEY_NEXT },		/* End >>| */
+};
+
+static struct rc_map_list flydvb_map = {
+	.map = {
+		.scan    = flydvb,
+		.size    = ARRAY_SIZE(flydvb),
+		.rc_type = RC_TYPE_UNKNOWN,	/* Legacy IR type */
+		.name    = RC_MAP_FLYDVB,
+	}
+};
+
+static int __init init_rc_map_flydvb(void)
+{
+	return rc_map_register(&flydvb_map);
+}
+
+static void __exit exit_rc_map_flydvb(void)
+{
+	rc_map_unregister(&flydvb_map);
+}
+
+module_init(init_rc_map_flydvb)
+module_exit(exit_rc_map_flydvb)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-flyvideo.c linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-flyvideo.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-flyvideo.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-flyvideo.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,70 @@
+/* flyvideo.h - Keytable for flyvideo Remote Controller
+ *
+ * keymap imported from ir-keymaps.c
+ *
+ * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
+
+static struct rc_map_table flyvideo[] = {
+	{ 0x0f, KEY_0 },
+	{ 0x03, KEY_1 },
+	{ 0x04, KEY_2 },
+	{ 0x05, KEY_3 },
+	{ 0x07, KEY_4 },
+	{ 0x08, KEY_5 },
+	{ 0x09, KEY_6 },
+	{ 0x0b, KEY_7 },
+	{ 0x0c, KEY_8 },
+	{ 0x0d, KEY_9 },
+
+	{ 0x0e, KEY_MODE },	/* Air/Cable */
+	{ 0x11, KEY_VIDEO },	/* Video */
+	{ 0x15, KEY_AUDIO },	/* Audio */
+	{ 0x00, KEY_POWER },	/* Power */
+	{ 0x18, KEY_TUNER },	/* AV Source */
+	{ 0x02, KEY_ZOOM },	/* Fullscreen */
+	{ 0x1a, KEY_LANGUAGE },	/* Stereo */
+	{ 0x1b, KEY_MUTE },	/* Mute */
+	{ 0x14, KEY_VOLUMEUP },	/* Volume + */
+	{ 0x17, KEY_VOLUMEDOWN },/* Volume - */
+	{ 0x12, KEY_CHANNELUP },/* Channel + */
+	{ 0x13, KEY_CHANNELDOWN },/* Channel - */
+	{ 0x06, KEY_AGAIN },	/* Recall */
+	{ 0x10, KEY_ENTER },	/* Enter */
+
+	{ 0x19, KEY_BACK },	/* Rewind  ( <<< ) */
+	{ 0x1f, KEY_FORWARD },	/* Forward ( >>> ) */
+	{ 0x0a, KEY_ANGLE },	/* no label, may be used as the PAUSE button */
+};
+
+static struct rc_map_list flyvideo_map = {
+	.map = {
+		.scan    = flyvideo,
+		.size    = ARRAY_SIZE(flyvideo),
+		.rc_type = RC_TYPE_UNKNOWN,	/* Legacy IR type */
+		.name    = RC_MAP_FLYVIDEO,
+	}
+};
+
+static int __init init_rc_map_flyvideo(void)
+{
+	return rc_map_register(&flyvideo_map);
+}
+
+static void __exit exit_rc_map_flyvideo(void)
+{
+	rc_map_unregister(&flyvideo_map);
+}
+
+module_init(init_rc_map_flyvideo)
+module_exit(exit_rc_map_flyvideo)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-fusionhdtv-mce.c linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-fusionhdtv-mce.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-fusionhdtv-mce.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-fusionhdtv-mce.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,98 @@
+/* fusionhdtv-mce.h - Keytable for fusionhdtv_mce Remote Controller
+ *
+ * keymap imported from ir-keymaps.c
+ *
+ * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
+
+/* DViCO FUSION HDTV MCE remote */
+
+static struct rc_map_table fusionhdtv_mce[] = {
+
+	{ 0x0b, KEY_1 },
+	{ 0x17, KEY_2 },
+	{ 0x1b, KEY_3 },
+	{ 0x07, KEY_4 },
+	{ 0x50, KEY_5 },
+	{ 0x54, KEY_6 },
+	{ 0x48, KEY_7 },
+	{ 0x4c, KEY_8 },
+	{ 0x58, KEY_9 },
+	{ 0x03, KEY_0 },
+
+	{ 0x5e, KEY_OK },
+	{ 0x51, KEY_UP },
+	{ 0x53, KEY_DOWN },
+	{ 0x5b, KEY_LEFT },
+	{ 0x5f, KEY_RIGHT },
+
+	{ 0x02, KEY_TV },		/* Labeled DTV on remote */
+	{ 0x0e, KEY_MP3 },
+	{ 0x1a, KEY_DVD },
+	{ 0x1e, KEY_FAVORITES },	/* Labeled CPF on remote */
+	{ 0x16, KEY_SETUP },
+	{ 0x46, KEY_POWER2 },		/* TV On/Off button on remote */
+	{ 0x0a, KEY_EPG },		/* Labeled Guide on remote */
+
+	{ 0x49, KEY_BACK },
+	{ 0x59, KEY_INFO },		/* Labeled MORE on remote */
+	{ 0x4d, KEY_MENU },		/* Labeled DVDMENU on remote */
+	{ 0x55, KEY_CYCLEWINDOWS },	/* Labeled ALT-TAB on remote */
+
+	{ 0x0f, KEY_PREVIOUSSONG },	/* Labeled |<< REPLAY on remote */
+	{ 0x12, KEY_NEXTSONG },		/* Labeled >>| SKIP on remote */
+	{ 0x42, KEY_ENTER },		/* Labeled START with a green
+					   MS windows logo on remote */
+
+	{ 0x15, KEY_VOLUMEUP },
+	{ 0x05, KEY_VOLUMEDOWN },
+	{ 0x11, KEY_CHANNELUP },
+	{ 0x09, KEY_CHANNELDOWN },
+
+	{ 0x52, KEY_CAMERA },
+	{ 0x5a, KEY_TUNER },
+	{ 0x19, KEY_OPEN },
+
+	{ 0x13, KEY_MODE },		/* 4:3 16:9 select */
+	{ 0x1f, KEY_ZOOM },
+
+	{ 0x43, KEY_REWIND },
+	{ 0x47, KEY_PLAYPAUSE },
+	{ 0x4f, KEY_FASTFORWARD },
+	{ 0x57, KEY_MUTE },
+	{ 0x0d, KEY_STOP },
+	{ 0x01, KEY_RECORD },
+	{ 0x4e, KEY_POWER },
+};
+
+static struct rc_map_list fusionhdtv_mce_map = {
+	.map = {
+		.scan    = fusionhdtv_mce,
+		.size    = ARRAY_SIZE(fusionhdtv_mce),
+		.rc_type = RC_TYPE_UNKNOWN,	/* Legacy IR type */
+		.name    = RC_MAP_FUSIONHDTV_MCE,
+	}
+};
+
+static int __init init_rc_map_fusionhdtv_mce(void)
+{
+	return rc_map_register(&fusionhdtv_mce_map);
+}
+
+static void __exit exit_rc_map_fusionhdtv_mce(void)
+{
+	rc_map_unregister(&fusionhdtv_mce_map);
+}
+
+module_init(init_rc_map_fusionhdtv_mce)
+module_exit(exit_rc_map_fusionhdtv_mce)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-gadmei-rm008z.c linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-gadmei-rm008z.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-gadmei-rm008z.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-gadmei-rm008z.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,81 @@
+/* gadmei-rm008z.h - Keytable for gadmei_rm008z Remote Controller
+ *
+ * keymap imported from ir-keymaps.c
+ *
+ * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
+
+/* GADMEI UTV330+ RM008Z remote
+   Shine Liu <shinel@foxmail.com>
+ */
+
+static struct rc_map_table gadmei_rm008z[] = {
+	{ 0x14, KEY_POWER2},		/* POWER OFF */
+	{ 0x0c, KEY_MUTE},		/* MUTE */
+
+	{ 0x18, KEY_TV},		/* TV */
+	{ 0x0e, KEY_VIDEO},		/* AV */
+	{ 0x0b, KEY_AUDIO},		/* SV */
+	{ 0x0f, KEY_RADIO},		/* FM */
+
+	{ 0x00, KEY_1},
+	{ 0x01, KEY_2},
+	{ 0x02, KEY_3},
+	{ 0x03, KEY_4},
+	{ 0x04, KEY_5},
+	{ 0x05, KEY_6},
+	{ 0x06, KEY_7},
+	{ 0x07, KEY_8},
+	{ 0x08, KEY_9},
+	{ 0x09, KEY_0},
+	{ 0x0a, KEY_INFO},		/* OSD */
+	{ 0x1c, KEY_BACKSPACE},		/* LAST */
+
+	{ 0x0d, KEY_PLAY},		/* PLAY */
+	{ 0x1e, KEY_CAMERA},		/* SNAPSHOT */
+	{ 0x1a, KEY_RECORD},		/* RECORD */
+	{ 0x17, KEY_STOP},		/* STOP */
+
+	{ 0x1f, KEY_UP},		/* UP */
+	{ 0x44, KEY_DOWN},		/* DOWN */
+	{ 0x46, KEY_TAB},		/* BACK */
+	{ 0x4a, KEY_ZOOM},		/* FULLSECREEN */
+
+	{ 0x10, KEY_VOLUMEUP},		/* VOLUMEUP */
+	{ 0x11, KEY_VOLUMEDOWN},	/* VOLUMEDOWN */
+	{ 0x12, KEY_CHANNELUP},		/* CHANNELUP */
+	{ 0x13, KEY_CHANNELDOWN},	/* CHANNELDOWN */
+	{ 0x15, KEY_ENTER},		/* OK */
+};
+
+static struct rc_map_list gadmei_rm008z_map = {
+	.map = {
+		.scan    = gadmei_rm008z,
+		.size    = ARRAY_SIZE(gadmei_rm008z),
+		.rc_type = RC_TYPE_UNKNOWN,	/* Legacy IR type */
+		.name    = RC_MAP_GADMEI_RM008Z,
+	}
+};
+
+static int __init init_rc_map_gadmei_rm008z(void)
+{
+	return rc_map_register(&gadmei_rm008z_map);
+}
+
+static void __exit exit_rc_map_gadmei_rm008z(void)
+{
+	rc_map_unregister(&gadmei_rm008z_map);
+}
+
+module_init(init_rc_map_gadmei_rm008z)
+module_exit(exit_rc_map_gadmei_rm008z)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-genius-tvgo-a11mce.c linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-genius-tvgo-a11mce.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-genius-tvgo-a11mce.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-genius-tvgo-a11mce.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,84 @@
+/* genius-tvgo-a11mce.h - Keytable for genius_tvgo_a11mce Remote Controller
+ *
+ * keymap imported from ir-keymaps.c
+ *
+ * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
+
+/*
+ * Remote control for the Genius TVGO A11MCE
+ * Adrian Pardini <pardo.bsso@gmail.com>
+ */
+
+static struct rc_map_table genius_tvgo_a11mce[] = {
+	/* Keys 0 to 9 */
+	{ 0x48, KEY_0 },
+	{ 0x09, KEY_1 },
+	{ 0x1d, KEY_2 },
+	{ 0x1f, KEY_3 },
+	{ 0x19, KEY_4 },
+	{ 0x1b, KEY_5 },
+	{ 0x11, KEY_6 },
+	{ 0x17, KEY_7 },
+	{ 0x12, KEY_8 },
+	{ 0x16, KEY_9 },
+
+	{ 0x54, KEY_RECORD },		/* recording */
+	{ 0x06, KEY_MUTE },		/* mute */
+	{ 0x10, KEY_POWER },
+	{ 0x40, KEY_LAST },		/* recall */
+	{ 0x4c, KEY_CHANNELUP },	/* channel / program + */
+	{ 0x00, KEY_CHANNELDOWN },	/* channel / program - */
+	{ 0x0d, KEY_VOLUMEUP },
+	{ 0x15, KEY_VOLUMEDOWN },
+	{ 0x4d, KEY_OK },		/* also labeled as Pause */
+	{ 0x1c, KEY_ZOOM },		/* full screen and Stop*/
+	{ 0x02, KEY_MODE },		/* AV Source or Rewind*/
+	{ 0x04, KEY_LIST },		/* -/-- */
+	/* small arrows above numbers */
+	{ 0x1a, KEY_NEXT },		/* also Fast Forward */
+	{ 0x0e, KEY_PREVIOUS },		/* also Rewind */
+	/* these are in a rather non standard layout and have
+	an alternate name written */
+	{ 0x1e, KEY_UP },		/* Video Setting */
+	{ 0x0a, KEY_DOWN },		/* Video Default */
+	{ 0x05, KEY_CAMERA },		/* Snapshot */
+	{ 0x0c, KEY_RIGHT },		/* Hide Panel */
+	/* Four buttons without label */
+	{ 0x49, KEY_RED },
+	{ 0x0b, KEY_GREEN },
+	{ 0x13, KEY_YELLOW },
+	{ 0x50, KEY_BLUE },
+};
+
+static struct rc_map_list genius_tvgo_a11mce_map = {
+	.map = {
+		.scan    = genius_tvgo_a11mce,
+		.size    = ARRAY_SIZE(genius_tvgo_a11mce),
+		.rc_type = RC_TYPE_UNKNOWN,	/* Legacy IR type */
+		.name    = RC_MAP_GENIUS_TVGO_A11MCE,
+	}
+};
+
+static int __init init_rc_map_genius_tvgo_a11mce(void)
+{
+	return rc_map_register(&genius_tvgo_a11mce_map);
+}
+
+static void __exit exit_rc_map_genius_tvgo_a11mce(void)
+{
+	rc_map_unregister(&genius_tvgo_a11mce_map);
+}
+
+module_init(init_rc_map_genius_tvgo_a11mce)
+module_exit(exit_rc_map_genius_tvgo_a11mce)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-gotview7135.c linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-gotview7135.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-gotview7135.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-gotview7135.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,79 @@
+/* gotview7135.h - Keytable for gotview7135 Remote Controller
+ *
+ * keymap imported from ir-keymaps.c
+ *
+ * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
+
+/* Mike Baikov <mike@baikov.com> */
+
+static struct rc_map_table gotview7135[] = {
+
+	{ 0x11, KEY_POWER },
+	{ 0x35, KEY_TV },
+	{ 0x1b, KEY_0 },
+	{ 0x29, KEY_1 },
+	{ 0x19, KEY_2 },
+	{ 0x39, KEY_3 },
+	{ 0x1f, KEY_4 },
+	{ 0x2c, KEY_5 },
+	{ 0x21, KEY_6 },
+	{ 0x24, KEY_7 },
+	{ 0x18, KEY_8 },
+	{ 0x2b, KEY_9 },
+	{ 0x3b, KEY_AGAIN },	/* LOOP */
+	{ 0x06, KEY_AUDIO },
+	{ 0x31, KEY_PRINT },	/* PREVIEW */
+	{ 0x3e, KEY_VIDEO },
+	{ 0x10, KEY_CHANNELUP },
+	{ 0x20, KEY_CHANNELDOWN },
+	{ 0x0c, KEY_VOLUMEDOWN },
+	{ 0x28, KEY_VOLUMEUP },
+	{ 0x08, KEY_MUTE },
+	{ 0x26, KEY_SEARCH },	/* SCAN */
+	{ 0x3f, KEY_CAMERA },	/* SNAPSHOT */
+	{ 0x12, KEY_RECORD },
+	{ 0x32, KEY_STOP },
+	{ 0x3c, KEY_PLAY },
+	{ 0x1d, KEY_REWIND },
+	{ 0x2d, KEY_PAUSE },
+	{ 0x0d, KEY_FORWARD },
+	{ 0x05, KEY_ZOOM },	/*FULL*/
+
+	{ 0x2a, KEY_F21 },	/* LIVE TIMESHIFT */
+	{ 0x0e, KEY_F22 },	/* MIN TIMESHIFT */
+	{ 0x1e, KEY_TIME },	/* TIMESHIFT */
+	{ 0x38, KEY_F24 },	/* NORMAL TIMESHIFT */
+};
+
+static struct rc_map_list gotview7135_map = {
+	.map = {
+		.scan    = gotview7135,
+		.size    = ARRAY_SIZE(gotview7135),
+		.rc_type = RC_TYPE_UNKNOWN,	/* Legacy IR type */
+		.name    = RC_MAP_GOTVIEW7135,
+	}
+};
+
+static int __init init_rc_map_gotview7135(void)
+{
+	return rc_map_register(&gotview7135_map);
+}
+
+static void __exit exit_rc_map_gotview7135(void)
+{
+	rc_map_unregister(&gotview7135_map);
+}
+
+module_init(init_rc_map_gotview7135)
+module_exit(exit_rc_map_gotview7135)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-hauppauge-new.c linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-hauppauge-new.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-hauppauge-new.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-hauppauge-new.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,100 @@
+/* hauppauge-new.h - Keytable for hauppauge_new Remote Controller
+ *
+ * keymap imported from ir-keymaps.c
+ *
+ * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
+
+/* Hauppauge: the newer, gray remotes (seems there are multiple
+ * slightly different versions), shipped with cx88+ivtv cards.
+ * almost rc5 coding, but some non-standard keys */
+
+static struct rc_map_table hauppauge_new[] = {
+	/* Keys 0 to 9 */
+	{ 0x00, KEY_0 },
+	{ 0x01, KEY_1 },
+	{ 0x02, KEY_2 },
+	{ 0x03, KEY_3 },
+	{ 0x04, KEY_4 },
+	{ 0x05, KEY_5 },
+	{ 0x06, KEY_6 },
+	{ 0x07, KEY_7 },
+	{ 0x08, KEY_8 },
+	{ 0x09, KEY_9 },
+
+	{ 0x0a, KEY_TEXT },		/* keypad asterisk as well */
+	{ 0x0b, KEY_RED },		/* red button */
+	{ 0x0c, KEY_RADIO },
+	{ 0x0d, KEY_MENU },
+	{ 0x0e, KEY_SUBTITLE },		/* also the # key */
+	{ 0x0f, KEY_MUTE },
+	{ 0x10, KEY_VOLUMEUP },
+	{ 0x11, KEY_VOLUMEDOWN },
+	{ 0x12, KEY_PREVIOUS },		/* previous channel */
+	{ 0x14, KEY_UP },
+	{ 0x15, KEY_DOWN },
+	{ 0x16, KEY_LEFT },
+	{ 0x17, KEY_RIGHT },
+	{ 0x18, KEY_VIDEO },		/* Videos */
+	{ 0x19, KEY_AUDIO },		/* Music */
+	/* 0x1a: Pictures - presume this means
+	   "Multimedia Home Platform" -
+	   no "PICTURES" key in input.h
+	 */
+	{ 0x1a, KEY_MHP },
+
+	{ 0x1b, KEY_EPG },		/* Guide */
+	{ 0x1c, KEY_TV },
+	{ 0x1e, KEY_NEXTSONG },		/* skip >| */
+	{ 0x1f, KEY_EXIT },		/* back/exit */
+	{ 0x20, KEY_CHANNELUP },	/* channel / program + */
+	{ 0x21, KEY_CHANNELDOWN },	/* channel / program - */
+	{ 0x22, KEY_CHANNEL },		/* source (old black remote) */
+	{ 0x24, KEY_PREVIOUSSONG },	/* replay |< */
+	{ 0x25, KEY_ENTER },		/* OK */
+	{ 0x26, KEY_SLEEP },		/* minimize (old black remote) */
+	{ 0x29, KEY_BLUE },		/* blue key */
+	{ 0x2e, KEY_GREEN },		/* green button */
+	{ 0x30, KEY_PAUSE },		/* pause */
+	{ 0x32, KEY_REWIND },		/* backward << */
+	{ 0x34, KEY_FASTFORWARD },	/* forward >> */
+	{ 0x35, KEY_PLAY },
+	{ 0x36, KEY_STOP },
+	{ 0x37, KEY_RECORD },		/* recording */
+	{ 0x38, KEY_YELLOW },		/* yellow key */
+	{ 0x3b, KEY_SELECT },		/* top right button */
+	{ 0x3c, KEY_ZOOM },		/* full */
+	{ 0x3d, KEY_POWER },		/* system power (green button) */
+};
+
+static struct rc_map_list hauppauge_new_map = {
+	.map = {
+		.scan    = hauppauge_new,
+		.size    = ARRAY_SIZE(hauppauge_new),
+		.rc_type = RC_TYPE_UNKNOWN,	/* Legacy IR type */
+		.name    = RC_MAP_HAUPPAUGE_NEW,
+	}
+};
+
+static int __init init_rc_map_hauppauge_new(void)
+{
+	return rc_map_register(&hauppauge_new_map);
+}
+
+static void __exit exit_rc_map_hauppauge_new(void)
+{
+	rc_map_unregister(&hauppauge_new_map);
+}
+
+module_init(init_rc_map_hauppauge_new)
+module_exit(exit_rc_map_hauppauge_new)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-imon-mce.c linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-imon-mce.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-imon-mce.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-imon-mce.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,142 @@
+/* rc5-imon-mce.c - Keytable for Windows Media Center RC-6 remotes for use
+ * with the SoundGraph iMON/Antec Veris hardware IR decoder
+ *
+ * Copyright (c) 2010 by Jarod Wilson <jarod@redhat.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 <media/rc-map.h>
+
+/* mce-mode imon mce remote key table */
+static struct rc_map_table imon_mce[] = {
+	/* keys sorted mostly by frequency of use to optimize lookups */
+	{ 0x800ff415, KEY_REWIND },
+	{ 0x800ff414, KEY_FASTFORWARD },
+	{ 0x800ff41b, KEY_PREVIOUS },
+	{ 0x800ff41a, KEY_NEXT },
+
+	{ 0x800ff416, KEY_PLAY },
+	{ 0x800ff418, KEY_PAUSE },
+	{ 0x800ff419, KEY_STOP },
+	{ 0x800ff417, KEY_RECORD },
+
+	{ 0x02000052, KEY_UP },
+	{ 0x02000051, KEY_DOWN },
+	{ 0x02000050, KEY_LEFT },
+	{ 0x0200004f, KEY_RIGHT },
+
+	{ 0x800ff41e, KEY_UP },
+	{ 0x800ff41f, KEY_DOWN },
+	{ 0x800ff420, KEY_LEFT },
+	{ 0x800ff421, KEY_RIGHT },
+
+	/* 0x800ff40b also KEY_NUMERIC_POUND on some receivers */
+	{ 0x800ff40b, KEY_ENTER },
+	{ 0x02000028, KEY_ENTER },
+/* the OK and Enter buttons decode to the same value on some remotes
+	{ 0x02000028, KEY_OK }, */
+	{ 0x800ff422, KEY_OK },
+	{ 0x0200002a, KEY_EXIT },
+	{ 0x800ff423, KEY_EXIT },
+	{ 0x02000029, KEY_DELETE },
+	/* 0x800ff40a also KEY_NUMERIC_STAR on some receivers */
+	{ 0x800ff40a, KEY_DELETE },
+
+	{ 0x800ff40e, KEY_MUTE },
+	{ 0x800ff410, KEY_VOLUMEUP },
+	{ 0x800ff411, KEY_VOLUMEDOWN },
+	{ 0x800ff412, KEY_CHANNELUP },
+	{ 0x800ff413, KEY_CHANNELDOWN },
+
+	{ 0x0200001e, KEY_NUMERIC_1 },
+	{ 0x0200001f, KEY_NUMERIC_2 },
+	{ 0x02000020, KEY_NUMERIC_3 },
+	{ 0x02000021, KEY_NUMERIC_4 },
+	{ 0x02000022, KEY_NUMERIC_5 },
+	{ 0x02000023, KEY_NUMERIC_6 },
+	{ 0x02000024, KEY_NUMERIC_7 },
+	{ 0x02000025, KEY_NUMERIC_8 },
+	{ 0x02000026, KEY_NUMERIC_9 },
+	{ 0x02000027, KEY_NUMERIC_0 },
+
+	{ 0x800ff401, KEY_NUMERIC_1 },
+	{ 0x800ff402, KEY_NUMERIC_2 },
+	{ 0x800ff403, KEY_NUMERIC_3 },
+	{ 0x800ff404, KEY_NUMERIC_4 },
+	{ 0x800ff405, KEY_NUMERIC_5 },
+	{ 0x800ff406, KEY_NUMERIC_6 },
+	{ 0x800ff407, KEY_NUMERIC_7 },
+	{ 0x800ff408, KEY_NUMERIC_8 },
+	{ 0x800ff409, KEY_NUMERIC_9 },
+	{ 0x800ff400, KEY_NUMERIC_0 },
+
+	{ 0x02200025, KEY_NUMERIC_STAR },
+	{ 0x02200020, KEY_NUMERIC_POUND },
+	/* 0x800ff41d also KEY_BLUE on some receivers */
+	{ 0x800ff41d, KEY_NUMERIC_STAR },
+	/* 0x800ff41c also KEY_PREVIOUS on some receivers */
+	{ 0x800ff41c, KEY_NUMERIC_POUND },
+
+	{ 0x800ff446, KEY_TV },
+	{ 0x800ff447, KEY_AUDIO }, /* My Music */
+	{ 0x800ff448, KEY_PVR }, /* RecordedTV */
+	{ 0x800ff449, KEY_CAMERA },
+	{ 0x800ff44a, KEY_VIDEO },
+	/* 0x800ff424 also KEY_MENU on some receivers */
+	{ 0x800ff424, KEY_DVD },
+	/* 0x800ff425 also KEY_GREEN on some receivers */
+	{ 0x800ff425, KEY_TUNER }, /* LiveTV */
+	{ 0x800ff450, KEY_RADIO },
+
+	{ 0x800ff44c, KEY_LANGUAGE },
+	{ 0x800ff427, KEY_ZOOM }, /* Aspect */
+
+	{ 0x800ff45b, KEY_RED },
+	{ 0x800ff45c, KEY_GREEN },
+	{ 0x800ff45d, KEY_YELLOW },
+	{ 0x800ff45e, KEY_BLUE },
+
+	{ 0x800ff466, KEY_RED },
+	/* { 0x800ff425, KEY_GREEN }, */
+	{ 0x800ff468, KEY_YELLOW },
+	/* { 0x800ff41d, KEY_BLUE }, */
+
+	{ 0x800ff40f, KEY_INFO },
+	{ 0x800ff426, KEY_EPG }, /* Guide */
+	{ 0x800ff45a, KEY_SUBTITLE }, /* Caption/Teletext */
+	{ 0x800ff44d, KEY_TITLE },
+
+	{ 0x800ff40c, KEY_POWER },
+	{ 0x800ff40d, KEY_PROG1 }, /* Windows MCE button */
+
+};
+
+static struct rc_map_list imon_mce_map = {
+	.map = {
+		.scan    = imon_mce,
+		.size    = ARRAY_SIZE(imon_mce),
+		/* its RC6, but w/a hardware decoder */
+		.rc_type = RC_TYPE_RC6,
+		.name    = RC_MAP_IMON_MCE,
+	}
+};
+
+static int __init init_rc_map_imon_mce(void)
+{
+	return rc_map_register(&imon_mce_map);
+}
+
+static void __exit exit_rc_map_imon_mce(void)
+{
+	rc_map_unregister(&imon_mce_map);
+}
+
+module_init(init_rc_map_imon_mce)
+module_exit(exit_rc_map_imon_mce)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Jarod Wilson <jarod@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-imon-pad.c linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-imon-pad.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-imon-pad.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-imon-pad.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,156 @@
+/* rc5-imon-pad.c - Keytable for SoundGraph iMON PAD and Antec Veris
+ * RM-200 Remote Control
+ *
+ * Copyright (c) 2010 by Jarod Wilson <jarod@redhat.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 <media/rc-map.h>
+
+/*
+ * standard imon remote key table, which isn't really entirely
+ * "standard", as different receivers decode the same key on the
+ * same remote to different hex codes, and the silkscreened names
+ * vary a bit between the SoundGraph and Antec remotes... ugh.
+ */
+static struct rc_map_table imon_pad[] = {
+	/* keys sorted mostly by frequency of use to optimize lookups */
+	{ 0x2a8195b7, KEY_REWIND },
+	{ 0x298315b7, KEY_REWIND },
+	{ 0x2b8115b7, KEY_FASTFORWARD },
+	{ 0x2b8315b7, KEY_FASTFORWARD },
+	{ 0x2b9115b7, KEY_PREVIOUS },
+	{ 0x298195b7, KEY_NEXT },
+
+	{ 0x2a8115b7, KEY_PLAY },
+	{ 0x2a8315b7, KEY_PLAY },
+	{ 0x2a9115b7, KEY_PAUSE },
+	{ 0x2b9715b7, KEY_STOP },
+	{ 0x298115b7, KEY_RECORD },
+
+	{ 0x01008000, KEY_UP },
+	{ 0x01007f00, KEY_DOWN },
+	{ 0x01000080, KEY_LEFT },
+	{ 0x0100007f, KEY_RIGHT },
+
+	{ 0x2aa515b7, KEY_UP },
+	{ 0x289515b7, KEY_DOWN },
+	{ 0x29a515b7, KEY_LEFT },
+	{ 0x2ba515b7, KEY_RIGHT },
+
+	{ 0x0200002c, KEY_SPACE }, /* Select/Space */
+	{ 0x2a9315b7, KEY_SPACE }, /* Select/Space */
+	{ 0x02000028, KEY_ENTER },
+	{ 0x28a195b7, KEY_ENTER },
+	{ 0x288195b7, KEY_EXIT },
+	{ 0x02000029, KEY_ESC },
+	{ 0x2bb715b7, KEY_ESC },
+	{ 0x0200002a, KEY_BACKSPACE },
+	{ 0x28a115b7, KEY_BACKSPACE },
+
+	{ 0x2b9595b7, KEY_MUTE },
+	{ 0x28a395b7, KEY_VOLUMEUP },
+	{ 0x28a595b7, KEY_VOLUMEDOWN },
+	{ 0x289395b7, KEY_CHANNELUP },
+	{ 0x288795b7, KEY_CHANNELDOWN },
+
+	{ 0x0200001e, KEY_NUMERIC_1 },
+	{ 0x0200001f, KEY_NUMERIC_2 },
+	{ 0x02000020, KEY_NUMERIC_3 },
+	{ 0x02000021, KEY_NUMERIC_4 },
+	{ 0x02000022, KEY_NUMERIC_5 },
+	{ 0x02000023, KEY_NUMERIC_6 },
+	{ 0x02000024, KEY_NUMERIC_7 },
+	{ 0x02000025, KEY_NUMERIC_8 },
+	{ 0x02000026, KEY_NUMERIC_9 },
+	{ 0x02000027, KEY_NUMERIC_0 },
+
+	{ 0x28b595b7, KEY_NUMERIC_1 },
+	{ 0x2bb195b7, KEY_NUMERIC_2 },
+	{ 0x28b195b7, KEY_NUMERIC_3 },
+	{ 0x2a8595b7, KEY_NUMERIC_4 },
+	{ 0x299595b7, KEY_NUMERIC_5 },
+	{ 0x2aa595b7, KEY_NUMERIC_6 },
+	{ 0x2b9395b7, KEY_NUMERIC_7 },
+	{ 0x2a8515b7, KEY_NUMERIC_8 },
+	{ 0x2aa115b7, KEY_NUMERIC_9 },
+	{ 0x2ba595b7, KEY_NUMERIC_0 },
+
+	{ 0x02200025, KEY_NUMERIC_STAR },
+	{ 0x28b515b7, KEY_NUMERIC_STAR },
+	{ 0x02200020, KEY_NUMERIC_POUND },
+	{ 0x29a115b7, KEY_NUMERIC_POUND },
+
+	{ 0x2b8515b7, KEY_VIDEO },
+	{ 0x299195b7, KEY_AUDIO },
+	{ 0x2ba115b7, KEY_CAMERA },
+	{ 0x28a515b7, KEY_TV },
+	{ 0x29a395b7, KEY_DVD },
+	{ 0x29a295b7, KEY_DVD },
+
+	/* the Menu key between DVD and Subtitle on the RM-200... */
+	{ 0x2ba385b7, KEY_MENU },
+	{ 0x2ba395b7, KEY_MENU },
+
+	{ 0x288515b7, KEY_BOOKMARKS },
+	{ 0x2ab715b7, KEY_MEDIA }, /* Thumbnail */
+	{ 0x298595b7, KEY_SUBTITLE },
+	{ 0x2b8595b7, KEY_LANGUAGE },
+
+	{ 0x29a595b7, KEY_ZOOM },
+	{ 0x2aa395b7, KEY_SCREEN }, /* FullScreen */
+
+	{ 0x299115b7, KEY_KEYBOARD },
+	{ 0x299135b7, KEY_KEYBOARD },
+
+	{ 0x01010000, BTN_LEFT },
+	{ 0x01020000, BTN_RIGHT },
+	{ 0x01010080, BTN_LEFT },
+	{ 0x01020080, BTN_RIGHT },
+	{ 0x688301b7, BTN_LEFT },
+	{ 0x688481b7, BTN_RIGHT },
+
+	{ 0x2a9395b7, KEY_CYCLEWINDOWS }, /* TaskSwitcher */
+	{ 0x2b8395b7, KEY_TIME }, /* Timer */
+
+	{ 0x289115b7, KEY_POWER },
+	{ 0x29b195b7, KEY_EJECTCD }, /* the one next to play */
+	{ 0x299395b7, KEY_EJECTCLOSECD }, /* eject (by TaskSw) */
+
+	{ 0x02800000, KEY_CONTEXT_MENU }, /* Left Menu */
+	{ 0x2b8195b7, KEY_CONTEXT_MENU }, /* Left Menu*/
+	{ 0x02000065, KEY_COMPOSE }, /* RightMenu */
+	{ 0x28b715b7, KEY_COMPOSE }, /* RightMenu */
+	{ 0x2ab195b7, KEY_PROG1 }, /* Go or MultiMon */
+	{ 0x29b715b7, KEY_DASHBOARD }, /* AppLauncher */
+};
+
+static struct rc_map_list imon_pad_map = {
+	.map = {
+		.scan    = imon_pad,
+		.size    = ARRAY_SIZE(imon_pad),
+		/* actual protocol details unknown, hardware decoder */
+		.rc_type = RC_TYPE_OTHER,
+		.name    = RC_MAP_IMON_PAD,
+	}
+};
+
+static int __init init_rc_map_imon_pad(void)
+{
+	return rc_map_register(&imon_pad_map);
+}
+
+static void __exit exit_rc_map_imon_pad(void)
+{
+	rc_map_unregister(&imon_pad_map);
+}
+
+module_init(init_rc_map_imon_pad)
+module_exit(exit_rc_map_imon_pad)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Jarod Wilson <jarod@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-iodata-bctv7e.c linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-iodata-bctv7e.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-iodata-bctv7e.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-iodata-bctv7e.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,88 @@
+/* iodata-bctv7e.h - Keytable for iodata_bctv7e Remote Controller
+ *
+ * keymap imported from ir-keymaps.c
+ *
+ * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
+
+/* IO-DATA BCTV7E Remote */
+
+static struct rc_map_table iodata_bctv7e[] = {
+	{ 0x40, KEY_TV },
+	{ 0x20, KEY_RADIO },		/* FM */
+	{ 0x60, KEY_EPG },
+	{ 0x00, KEY_POWER },
+
+	/* Keys 0 to 9 */
+	{ 0x44, KEY_0 },		/* 10 */
+	{ 0x50, KEY_1 },
+	{ 0x30, KEY_2 },
+	{ 0x70, KEY_3 },
+	{ 0x48, KEY_4 },
+	{ 0x28, KEY_5 },
+	{ 0x68, KEY_6 },
+	{ 0x58, KEY_7 },
+	{ 0x38, KEY_8 },
+	{ 0x78, KEY_9 },
+
+	{ 0x10, KEY_L },		/* Live */
+	{ 0x08, KEY_TIME },		/* Time Shift */
+
+	{ 0x18, KEY_PLAYPAUSE },	/* Play */
+
+	{ 0x24, KEY_ENTER },		/* 11 */
+	{ 0x64, KEY_ESC },		/* 12 */
+	{ 0x04, KEY_M },		/* Multi */
+
+	{ 0x54, KEY_VIDEO },
+	{ 0x34, KEY_CHANNELUP },
+	{ 0x74, KEY_VOLUMEUP },
+	{ 0x14, KEY_MUTE },
+
+	{ 0x4c, KEY_VCR },		/* SVIDEO */
+	{ 0x2c, KEY_CHANNELDOWN },
+	{ 0x6c, KEY_VOLUMEDOWN },
+	{ 0x0c, KEY_ZOOM },
+
+	{ 0x5c, KEY_PAUSE },
+	{ 0x3c, KEY_RED },		/* || (red) */
+	{ 0x7c, KEY_RECORD },		/* recording */
+	{ 0x1c, KEY_STOP },
+
+	{ 0x41, KEY_REWIND },		/* backward << */
+	{ 0x21, KEY_PLAY },
+	{ 0x61, KEY_FASTFORWARD },	/* forward >> */
+	{ 0x01, KEY_NEXT },		/* skip >| */
+};
+
+static struct rc_map_list iodata_bctv7e_map = {
+	.map = {
+		.scan    = iodata_bctv7e,
+		.size    = ARRAY_SIZE(iodata_bctv7e),
+		.rc_type = RC_TYPE_UNKNOWN,	/* Legacy IR type */
+		.name    = RC_MAP_IODATA_BCTV7E,
+	}
+};
+
+static int __init init_rc_map_iodata_bctv7e(void)
+{
+	return rc_map_register(&iodata_bctv7e_map);
+}
+
+static void __exit exit_rc_map_iodata_bctv7e(void)
+{
+	rc_map_unregister(&iodata_bctv7e_map);
+}
+
+module_init(init_rc_map_iodata_bctv7e)
+module_exit(exit_rc_map_iodata_bctv7e)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-kaiomy.c linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-kaiomy.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-kaiomy.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-kaiomy.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,87 @@
+/* kaiomy.h - Keytable for kaiomy Remote Controller
+ *
+ * keymap imported from ir-keymaps.c
+ *
+ * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
+
+/* Kaiomy TVnPC U2
+   Mauro Carvalho Chehab <mchehab@infradead.org>
+ */
+
+static struct rc_map_table kaiomy[] = {
+	{ 0x43, KEY_POWER2},
+	{ 0x01, KEY_LIST},
+	{ 0x0b, KEY_ZOOM},
+	{ 0x03, KEY_POWER},
+
+	{ 0x04, KEY_1},
+	{ 0x08, KEY_2},
+	{ 0x02, KEY_3},
+
+	{ 0x0f, KEY_4},
+	{ 0x05, KEY_5},
+	{ 0x06, KEY_6},
+
+	{ 0x0c, KEY_7},
+	{ 0x0d, KEY_8},
+	{ 0x0a, KEY_9},
+
+	{ 0x11, KEY_0},
+
+	{ 0x09, KEY_CHANNELUP},
+	{ 0x07, KEY_CHANNELDOWN},
+
+	{ 0x0e, KEY_VOLUMEUP},
+	{ 0x13, KEY_VOLUMEDOWN},
+
+	{ 0x10, KEY_HOME},
+	{ 0x12, KEY_ENTER},
+
+	{ 0x14, KEY_RECORD},
+	{ 0x15, KEY_STOP},
+	{ 0x16, KEY_PLAY},
+	{ 0x17, KEY_MUTE},
+
+	{ 0x18, KEY_UP},
+	{ 0x19, KEY_DOWN},
+	{ 0x1a, KEY_LEFT},
+	{ 0x1b, KEY_RIGHT},
+
+	{ 0x1c, KEY_RED},
+	{ 0x1d, KEY_GREEN},
+	{ 0x1e, KEY_YELLOW},
+	{ 0x1f, KEY_BLUE},
+};
+
+static struct rc_map_list kaiomy_map = {
+	.map = {
+		.scan    = kaiomy,
+		.size    = ARRAY_SIZE(kaiomy),
+		.rc_type = RC_TYPE_UNKNOWN,	/* Legacy IR type */
+		.name    = RC_MAP_KAIOMY,
+	}
+};
+
+static int __init init_rc_map_kaiomy(void)
+{
+	return rc_map_register(&kaiomy_map);
+}
+
+static void __exit exit_rc_map_kaiomy(void)
+{
+	rc_map_unregister(&kaiomy_map);
+}
+
+module_init(init_rc_map_kaiomy)
+module_exit(exit_rc_map_kaiomy)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-kworld-315u.c linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-kworld-315u.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-kworld-315u.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-kworld-315u.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,83 @@
+/* kworld-315u.h - Keytable for kworld_315u Remote Controller
+ *
+ * keymap imported from ir-keymaps.c
+ *
+ * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
+
+/* Kworld 315U
+ */
+
+static struct rc_map_table kworld_315u[] = {
+	{ 0x6143, KEY_POWER },
+	{ 0x6101, KEY_TUNER },		/* source */
+	{ 0x610b, KEY_ZOOM },
+	{ 0x6103, KEY_POWER2 },		/* shutdown */
+
+	{ 0x6104, KEY_1 },
+	{ 0x6108, KEY_2 },
+	{ 0x6102, KEY_3 },
+	{ 0x6109, KEY_CHANNELUP },
+
+	{ 0x610f, KEY_4 },
+	{ 0x6105, KEY_5 },
+	{ 0x6106, KEY_6 },
+	{ 0x6107, KEY_CHANNELDOWN },
+
+	{ 0x610c, KEY_7 },
+	{ 0x610d, KEY_8 },
+	{ 0x610a, KEY_9 },
+	{ 0x610e, KEY_VOLUMEUP },
+
+	{ 0x6110, KEY_LAST },
+	{ 0x6111, KEY_0 },
+	{ 0x6112, KEY_ENTER },
+	{ 0x6113, KEY_VOLUMEDOWN },
+
+	{ 0x6114, KEY_RECORD },
+	{ 0x6115, KEY_STOP },
+	{ 0x6116, KEY_PLAY },
+	{ 0x6117, KEY_MUTE },
+
+	{ 0x6118, KEY_UP },
+	{ 0x6119, KEY_DOWN },
+	{ 0x611a, KEY_LEFT },
+	{ 0x611b, KEY_RIGHT },
+
+	{ 0x611c, KEY_RED },
+	{ 0x611d, KEY_GREEN },
+	{ 0x611e, KEY_YELLOW },
+	{ 0x611f, KEY_BLUE },
+};
+
+static struct rc_map_list kworld_315u_map = {
+	.map = {
+		.scan    = kworld_315u,
+		.size    = ARRAY_SIZE(kworld_315u),
+		.rc_type = RC_TYPE_NEC,
+		.name    = RC_MAP_KWORLD_315U,
+	}
+};
+
+static int __init init_rc_map_kworld_315u(void)
+{
+	return rc_map_register(&kworld_315u_map);
+}
+
+static void __exit exit_rc_map_kworld_315u(void)
+{
+	rc_map_unregister(&kworld_315u_map);
+}
+
+module_init(init_rc_map_kworld_315u)
+module_exit(exit_rc_map_kworld_315u)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-kworld-plus-tv-analog.c linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-kworld-plus-tv-analog.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-kworld-plus-tv-analog.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-kworld-plus-tv-analog.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,99 @@
+/* kworld-plus-tv-analog.h - Keytable for kworld_plus_tv_analog Remote Controller
+ *
+ * keymap imported from ir-keymaps.c
+ *
+ * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
+
+/* Kworld Plus TV Analog Lite PCI IR
+   Mauro Carvalho Chehab <mchehab@infradead.org>
+ */
+
+static struct rc_map_table kworld_plus_tv_analog[] = {
+	{ 0x0c, KEY_PROG1 },		/* Kworld key */
+	{ 0x16, KEY_CLOSECD },		/* -> ) */
+	{ 0x1d, KEY_POWER2 },
+
+	{ 0x00, KEY_1 },
+	{ 0x01, KEY_2 },
+	{ 0x02, KEY_3 },		/* Two keys have the same code: 3 and left */
+	{ 0x03, KEY_4 },		/* Two keys have the same code: 3 and right */
+	{ 0x04, KEY_5 },
+	{ 0x05, KEY_6 },
+	{ 0x06, KEY_7 },
+	{ 0x07, KEY_8 },
+	{ 0x08, KEY_9 },
+	{ 0x0a, KEY_0 },
+
+	{ 0x09, KEY_AGAIN },
+	{ 0x14, KEY_MUTE },
+
+	{ 0x20, KEY_UP },
+	{ 0x21, KEY_DOWN },
+	{ 0x0b, KEY_ENTER },
+
+	{ 0x10, KEY_CHANNELUP },
+	{ 0x11, KEY_CHANNELDOWN },
+
+	/* Couldn't map key left/key right since those
+	   conflict with '3' and '4' scancodes
+	   I dunno what the original driver does
+	 */
+
+	{ 0x13, KEY_VOLUMEUP },
+	{ 0x12, KEY_VOLUMEDOWN },
+
+	/* The lower part of the IR
+	   There are several duplicated keycodes there.
+	   Most of them conflict with digits.
+	   Add mappings just to the unused scancodes.
+	   Somehow, the original driver has a way to know,
+	   but this doesn't seem to be on some GPIO.
+	   Also, it is not related to the time between keyup
+	   and keydown.
+	 */
+	{ 0x19, KEY_TIME},		/* Timeshift */
+	{ 0x1a, KEY_STOP},
+	{ 0x1b, KEY_RECORD},
+
+	{ 0x22, KEY_TEXT},
+
+	{ 0x15, KEY_AUDIO},		/* ((*)) */
+	{ 0x0f, KEY_ZOOM},
+	{ 0x1c, KEY_CAMERA},		/* snapshot */
+
+	{ 0x18, KEY_RED},		/* B */
+	{ 0x23, KEY_GREEN},		/* C */
+};
+
+static struct rc_map_list kworld_plus_tv_analog_map = {
+	.map = {
+		.scan    = kworld_plus_tv_analog,
+		.size    = ARRAY_SIZE(kworld_plus_tv_analog),
+		.rc_type = RC_TYPE_UNKNOWN,	/* Legacy IR type */
+		.name    = RC_MAP_KWORLD_PLUS_TV_ANALOG,
+	}
+};
+
+static int __init init_rc_map_kworld_plus_tv_analog(void)
+{
+	return rc_map_register(&kworld_plus_tv_analog_map);
+}
+
+static void __exit exit_rc_map_kworld_plus_tv_analog(void)
+{
+	rc_map_unregister(&kworld_plus_tv_analog_map);
+}
+
+module_init(init_rc_map_kworld_plus_tv_analog)
+module_exit(exit_rc_map_kworld_plus_tv_analog)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-leadtek-y04g0051.c linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-leadtek-y04g0051.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-leadtek-y04g0051.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-leadtek-y04g0051.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,99 @@
+/*
+ * LeadTek Y04G0051 remote controller keytable
+ *
+ * Copyright (C) 2010 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 <media/rc-map.h>
+
+static struct rc_map_table leadtek_y04g0051[] = {
+	{ 0x0300, KEY_POWER2 },
+	{ 0x0303, KEY_SCREEN },
+	{ 0x0304, KEY_RIGHT },
+	{ 0x0305, KEY_1 },
+	{ 0x0306, KEY_2 },
+	{ 0x0307, KEY_3 },
+	{ 0x0308, KEY_LEFT },
+	{ 0x0309, KEY_4 },
+	{ 0x030a, KEY_5 },
+	{ 0x030b, KEY_6 },
+	{ 0x030c, KEY_UP },
+	{ 0x030d, KEY_7 },
+	{ 0x030e, KEY_8 },
+	{ 0x030f, KEY_9 },
+	{ 0x0310, KEY_DOWN },
+	{ 0x0311, KEY_AGAIN },
+	{ 0x0312, KEY_0 },
+	{ 0x0313, KEY_OK },              /* 1st ok */
+	{ 0x0314, KEY_MUTE },
+	{ 0x0316, KEY_OK },              /* 2nd ok */
+	{ 0x031e, KEY_VIDEO },           /* 2nd video */
+	{ 0x031b, KEY_AUDIO },
+	{ 0x031f, KEY_TEXT },
+	{ 0x0340, KEY_SLEEP },
+	{ 0x0341, KEY_DOT },
+	{ 0x0342, KEY_REWIND },
+	{ 0x0343, KEY_PLAY },
+	{ 0x0344, KEY_FASTFORWARD },
+	{ 0x0345, KEY_TIME },
+	{ 0x0346, KEY_STOP },            /* 2nd stop */
+	{ 0x0347, KEY_RECORD },
+	{ 0x0348, KEY_CAMERA },
+	{ 0x0349, KEY_ESC },
+	{ 0x034a, KEY_NEW },
+	{ 0x034b, KEY_RED },
+	{ 0x034c, KEY_GREEN },
+	{ 0x034d, KEY_YELLOW },
+	{ 0x034e, KEY_BLUE },
+	{ 0x034f, KEY_MENU },
+	{ 0x0350, KEY_STOP },            /* 1st stop */
+	{ 0x0351, KEY_CHANNEL },
+	{ 0x0352, KEY_VIDEO },           /* 1st video */
+	{ 0x0353, KEY_EPG },
+	{ 0x0354, KEY_PREVIOUS },
+	{ 0x0355, KEY_NEXT },
+	{ 0x0356, KEY_TV },
+	{ 0x035a, KEY_VOLUMEDOWN },
+	{ 0x035b, KEY_CHANNELUP },
+	{ 0x035e, KEY_VOLUMEUP },
+	{ 0x035f, KEY_CHANNELDOWN },
+};
+
+static struct rc_map_list leadtek_y04g0051_map = {
+	.map = {
+		.scan    = leadtek_y04g0051,
+		.size    = ARRAY_SIZE(leadtek_y04g0051),
+		.rc_type = RC_TYPE_NEC,
+		.name    = RC_MAP_LEADTEK_Y04G0051,
+	}
+};
+
+static int __init init_rc_map_leadtek_y04g0051(void)
+{
+	return rc_map_register(&leadtek_y04g0051_map);
+}
+
+static void __exit exit_rc_map_leadtek_y04g0051(void)
+{
+	rc_map_unregister(&leadtek_y04g0051_map);
+}
+
+module_init(init_rc_map_leadtek_y04g0051)
+module_exit(exit_rc_map_leadtek_y04g0051)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-lirc.c linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-lirc.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-lirc.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-lirc.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,41 @@
+/* rc-lirc.c - Empty dummy keytable, for use when its preferred to pass
+ * all raw IR data to the lirc userspace decoder.
+ *
+ * Copyright (c) 2010 by Jarod Wilson <jarod@redhat.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 <media/rc-core.h>
+
+static struct rc_map_table lirc[] = {
+	{ },
+};
+
+static struct rc_map_list lirc_map = {
+	.map = {
+		.scan    = lirc,
+		.size    = ARRAY_SIZE(lirc),
+		.rc_type = RC_TYPE_LIRC,
+		.name    = RC_MAP_LIRC,
+	}
+};
+
+static int __init init_rc_map_lirc(void)
+{
+	return rc_map_register(&lirc_map);
+}
+
+static void __exit exit_rc_map_lirc(void)
+{
+	rc_map_unregister(&lirc_map);
+}
+
+module_init(init_rc_map_lirc)
+module_exit(exit_rc_map_lirc)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Jarod Wilson <jarod@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-lme2510.c linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-lme2510.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-lme2510.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-lme2510.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,68 @@
+/* LME2510 remote control
+ *
+ *
+ * Copyright (C) 2010 Malcolm Priestley (tvboxspy@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 <media/rc-map.h>
+
+
+static struct rc_map_table lme2510_rc[] = {
+	{ 0xba45, KEY_0 },
+	{ 0xa05f, KEY_1 },
+	{ 0xaf50, KEY_2 },
+	{ 0xa25d, KEY_3 },
+	{ 0xbe41, KEY_4 },
+	{ 0xf50a, KEY_5 },
+	{ 0xbd42, KEY_6 },
+	{ 0xb847, KEY_7 },
+	{ 0xb649, KEY_8 },
+	{ 0xfa05, KEY_9 },
+	{ 0xbc43, KEY_POWER },
+	{ 0xb946, KEY_SUBTITLE },
+	{ 0xf906, KEY_PAUSE },
+	{ 0xfc03, KEY_MEDIA_REPEAT},
+	{ 0xfd02, KEY_PAUSE },
+	{ 0xa15e, KEY_VOLUMEUP },
+	{ 0xa35c, KEY_VOLUMEDOWN },
+	{ 0xf609, KEY_CHANNELUP },
+	{ 0xe51a, KEY_CHANNELDOWN },
+	{ 0xe11e, KEY_PLAY },
+	{ 0xe41b, KEY_ZOOM },
+	{ 0xa659, KEY_MUTE },
+	{ 0xa55a, KEY_TV },
+	{ 0xe718, KEY_RECORD },
+	{ 0xf807, KEY_EPG },
+	{ 0xfe01, KEY_STOP },
+
+};
+
+static struct rc_map_list lme2510_map = {
+	.map = {
+		.scan    = lme2510_rc,
+		.size    = ARRAY_SIZE(lme2510_rc),
+		.rc_type = RC_TYPE_UNKNOWN,
+		.name    = RC_MAP_LME2510,
+	}
+};
+
+static int __init init_rc_lme2510_map(void)
+{
+	return rc_map_register(&lme2510_map);
+}
+
+static void __exit exit_rc_lme2510_map(void)
+{
+	rc_map_unregister(&lme2510_map);
+}
+
+module_init(init_rc_lme2510_map)
+module_exit(exit_rc_lme2510_map)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Malcolm Priestley tvboxspy@gmail.com");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-manli.c linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-manli.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-manli.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-manli.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,134 @@
+/* manli.h - Keytable for manli Remote Controller
+ *
+ * keymap imported from ir-keymaps.c
+ *
+ * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
+
+/* Michael Tokarev <mjt@tls.msk.ru>
+   keytable is used by MANLI MTV00[0x0c] and BeholdTV 40[13] at
+   least, and probably other cards too.
+   The "ascii-art picture" below (in comments, first row
+   is the keycode in hex, and subsequent row(s) shows
+   the button labels (several variants when appropriate)
+   helps to descide which keycodes to assign to the buttons.
+ */
+
+static struct rc_map_table manli[] = {
+
+	/*  0x1c            0x12  *
+	 * FUNCTION         POWER *
+	 *   FM              (|)  *
+	 *                        */
+	{ 0x1c, KEY_RADIO },	/*XXX*/
+	{ 0x12, KEY_POWER },
+
+	/*  0x01    0x02    0x03  *
+	 *   1       2       3    *
+	 *                        *
+	 *  0x04    0x05    0x06  *
+	 *   4       5       6    *
+	 *                        *
+	 *  0x07    0x08    0x09  *
+	 *   7       8       9    *
+	 *                        */
+	{ 0x01, KEY_1 },
+	{ 0x02, KEY_2 },
+	{ 0x03, KEY_3 },
+	{ 0x04, KEY_4 },
+	{ 0x05, KEY_5 },
+	{ 0x06, KEY_6 },
+	{ 0x07, KEY_7 },
+	{ 0x08, KEY_8 },
+	{ 0x09, KEY_9 },
+
+	/*  0x0a    0x00    0x17  *
+	 * RECALL    0      +100  *
+	 *                  PLUS  *
+	 *                        */
+	{ 0x0a, KEY_AGAIN },	/*XXX KEY_REWIND? */
+	{ 0x00, KEY_0 },
+	{ 0x17, KEY_DIGITS },	/*XXX*/
+
+	/*  0x14            0x10  *
+	 *  MENU            INFO  *
+	 *  OSD                   */
+	{ 0x14, KEY_MENU },
+	{ 0x10, KEY_INFO },
+
+	/*          0x0b          *
+	 *           Up           *
+	 *                        *
+	 *  0x18    0x16    0x0c  *
+	 *  Left     Ok     Right *
+	 *                        *
+	 *         0x015          *
+	 *         Down           *
+	 *                        */
+	{ 0x0b, KEY_UP },
+	{ 0x18, KEY_LEFT },
+	{ 0x16, KEY_OK },	/*XXX KEY_SELECT? KEY_ENTER? */
+	{ 0x0c, KEY_RIGHT },
+	{ 0x15, KEY_DOWN },
+
+	/*  0x11            0x0d  *
+	 *  TV/AV           MODE  *
+	 *  SOURCE         STEREO *
+	 *                        */
+	{ 0x11, KEY_TV },	/*XXX*/
+	{ 0x0d, KEY_MODE },	/*XXX there's no KEY_STEREO	*/
+
+	/*  0x0f    0x1b    0x1a  *
+	 *  AUDIO   Vol+    Chan+ *
+	 *        TIMESHIFT???    *
+	 *                        *
+	 *  0x0e    0x1f    0x1e  *
+	 *  SLEEP   Vol-    Chan- *
+	 *                        */
+	{ 0x0f, KEY_AUDIO },
+	{ 0x1b, KEY_VOLUMEUP },
+	{ 0x1a, KEY_CHANNELUP },
+	{ 0x0e, KEY_TIME },
+	{ 0x1f, KEY_VOLUMEDOWN },
+	{ 0x1e, KEY_CHANNELDOWN },
+
+	/*         0x13     0x19  *
+	 *         MUTE   SNAPSHOT*
+	 *                        */
+	{ 0x13, KEY_MUTE },
+	{ 0x19, KEY_CAMERA },
+
+	/* 0x1d unused ? */
+};
+
+static struct rc_map_list manli_map = {
+	.map = {
+		.scan    = manli,
+		.size    = ARRAY_SIZE(manli),
+		.rc_type = RC_TYPE_UNKNOWN,	/* Legacy IR type */
+		.name    = RC_MAP_MANLI,
+	}
+};
+
+static int __init init_rc_map_manli(void)
+{
+	return rc_map_register(&manli_map);
+}
+
+static void __exit exit_rc_map_manli(void)
+{
+	rc_map_unregister(&manli_map);
+}
+
+module_init(init_rc_map_manli)
+module_exit(exit_rc_map_manli)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-msi-digivox-ii.c linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-msi-digivox-ii.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-msi-digivox-ii.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-msi-digivox-ii.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,67 @@
+/*
+ * MSI DIGIVOX mini II remote controller keytable
+ *
+ * Copyright (C) 2010 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 <media/rc-map.h>
+
+static struct rc_map_table msi_digivox_ii[] = {
+	{ 0x0002, KEY_2 },
+	{ 0x0003, KEY_UP },              /* up */
+	{ 0x0004, KEY_3 },
+	{ 0x0005, KEY_CHANNELDOWN },
+	{ 0x0008, KEY_5 },
+	{ 0x0009, KEY_0 },
+	{ 0x000b, KEY_8 },
+	{ 0x000d, KEY_DOWN },            /* down */
+	{ 0x0010, KEY_9 },
+	{ 0x0011, KEY_7 },
+	{ 0x0014, KEY_VOLUMEUP },
+	{ 0x0015, KEY_CHANNELUP },
+	{ 0x0016, KEY_OK },
+	{ 0x0017, KEY_POWER2 },
+	{ 0x001a, KEY_1 },
+	{ 0x001c, KEY_4 },
+	{ 0x001d, KEY_6 },
+	{ 0x001f, KEY_VOLUMEDOWN },
+};
+
+static struct rc_map_list msi_digivox_ii_map = {
+	.map = {
+		.scan    = msi_digivox_ii,
+		.size    = ARRAY_SIZE(msi_digivox_ii),
+		.rc_type = RC_TYPE_NEC,
+		.name    = RC_MAP_MSI_DIGIVOX_II,
+	}
+};
+
+static int __init init_rc_map_msi_digivox_ii(void)
+{
+	return rc_map_register(&msi_digivox_ii_map);
+}
+
+static void __exit exit_rc_map_msi_digivox_ii(void)
+{
+	rc_map_unregister(&msi_digivox_ii_map);
+}
+
+module_init(init_rc_map_msi_digivox_ii)
+module_exit(exit_rc_map_msi_digivox_ii)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-msi-digivox-iii.c linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-msi-digivox-iii.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-msi-digivox-iii.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-msi-digivox-iii.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,85 @@
+/*
+ * MSI DIGIVOX mini III remote controller keytable
+ *
+ * Copyright (C) 2010 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 <media/rc-map.h>
+
+/* MSI DIGIVOX mini III */
+/* Uses NEC extended 0x61d6. */
+/* This remote seems to be same as rc-kworld-315u.c. Anyhow, add new remote
+   since rc-kworld-315u.c lacks NEC extended address byte. */
+static struct rc_map_table msi_digivox_iii[] = {
+	{ 0x61d601, KEY_VIDEO },           /* Source */
+	{ 0x61d602, KEY_3 },
+	{ 0x61d603, KEY_POWER },           /* ShutDown */
+	{ 0x61d604, KEY_1 },
+	{ 0x61d605, KEY_5 },
+	{ 0x61d606, KEY_6 },
+	{ 0x61d607, KEY_CHANNELDOWN },     /* CH- */
+	{ 0x61d608, KEY_2 },
+	{ 0x61d609, KEY_CHANNELUP },       /* CH+ */
+	{ 0x61d60a, KEY_9 },
+	{ 0x61d60b, KEY_ZOOM },            /* Zoom */
+	{ 0x61d60c, KEY_7 },
+	{ 0x61d60d, KEY_8 },
+	{ 0x61d60e, KEY_VOLUMEUP },        /* Vol+ */
+	{ 0x61d60f, KEY_4 },
+	{ 0x61d610, KEY_ESC },             /* [back up arrow] */
+	{ 0x61d611, KEY_0 },
+	{ 0x61d612, KEY_OK },              /* [enter arrow] */
+	{ 0x61d613, KEY_VOLUMEDOWN },      /* Vol- */
+	{ 0x61d614, KEY_RECORD },          /* Rec */
+	{ 0x61d615, KEY_STOP },            /* Stop */
+	{ 0x61d616, KEY_PLAY },            /* Play */
+	{ 0x61d617, KEY_MUTE },            /* Mute */
+	{ 0x61d618, KEY_UP },
+	{ 0x61d619, KEY_DOWN },
+	{ 0x61d61a, KEY_LEFT },
+	{ 0x61d61b, KEY_RIGHT },
+	{ 0x61d61c, KEY_RED },
+	{ 0x61d61d, KEY_GREEN },
+	{ 0x61d61e, KEY_YELLOW },
+	{ 0x61d61f, KEY_BLUE },
+	{ 0x61d643, KEY_POWER2 },          /* [red power button] */
+};
+
+static struct rc_map_list msi_digivox_iii_map = {
+	.map = {
+		.scan    = msi_digivox_iii,
+		.size    = ARRAY_SIZE(msi_digivox_iii),
+		.rc_type = RC_TYPE_NEC,
+		.name    = RC_MAP_MSI_DIGIVOX_III,
+	}
+};
+
+static int __init init_rc_map_msi_digivox_iii(void)
+{
+	return rc_map_register(&msi_digivox_iii_map);
+}
+
+static void __exit exit_rc_map_msi_digivox_iii(void)
+{
+	rc_map_unregister(&msi_digivox_iii_map);
+}
+
+module_init(init_rc_map_msi_digivox_iii)
+module_exit(exit_rc_map_msi_digivox_iii)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-msi-tvanywhere.c linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-msi-tvanywhere.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-msi-tvanywhere.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-msi-tvanywhere.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,69 @@
+/* msi-tvanywhere.h - Keytable for msi_tvanywhere Remote Controller
+ *
+ * keymap imported from ir-keymaps.c
+ *
+ * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
+
+/* MSI TV@nywhere MASTER remote */
+
+static struct rc_map_table msi_tvanywhere[] = {
+	/* Keys 0 to 9 */
+	{ 0x00, KEY_0 },
+	{ 0x01, KEY_1 },
+	{ 0x02, KEY_2 },
+	{ 0x03, KEY_3 },
+	{ 0x04, KEY_4 },
+	{ 0x05, KEY_5 },
+	{ 0x06, KEY_6 },
+	{ 0x07, KEY_7 },
+	{ 0x08, KEY_8 },
+	{ 0x09, KEY_9 },
+
+	{ 0x0c, KEY_MUTE },
+	{ 0x0f, KEY_SCREEN },		/* Full Screen */
+	{ 0x10, KEY_FN },		/* Funtion */
+	{ 0x11, KEY_TIME },		/* Time shift */
+	{ 0x12, KEY_POWER },
+	{ 0x13, KEY_MEDIA },		/* MTS */
+	{ 0x14, KEY_SLOW },
+	{ 0x16, KEY_REWIND },		/* backward << */
+	{ 0x17, KEY_ENTER },		/* Return */
+	{ 0x18, KEY_FASTFORWARD },	/* forward >> */
+	{ 0x1a, KEY_CHANNELUP },
+	{ 0x1b, KEY_VOLUMEUP },
+	{ 0x1e, KEY_CHANNELDOWN },
+	{ 0x1f, KEY_VOLUMEDOWN },
+};
+
+static struct rc_map_list msi_tvanywhere_map = {
+	.map = {
+		.scan    = msi_tvanywhere,
+		.size    = ARRAY_SIZE(msi_tvanywhere),
+		.rc_type = RC_TYPE_UNKNOWN,	/* Legacy IR type */
+		.name    = RC_MAP_MSI_TVANYWHERE,
+	}
+};
+
+static int __init init_rc_map_msi_tvanywhere(void)
+{
+	return rc_map_register(&msi_tvanywhere_map);
+}
+
+static void __exit exit_rc_map_msi_tvanywhere(void)
+{
+	rc_map_unregister(&msi_tvanywhere_map);
+}
+
+module_init(init_rc_map_msi_tvanywhere)
+module_exit(exit_rc_map_msi_tvanywhere)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-msi-tvanywhere-plus.c linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-msi-tvanywhere-plus.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-msi-tvanywhere-plus.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-msi-tvanywhere-plus.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,123 @@
+/* msi-tvanywhere-plus.h - Keytable for msi_tvanywhere_plus Remote Controller
+ *
+ * keymap imported from ir-keymaps.c
+ *
+ * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
+
+/*
+  Keycodes for remote on the MSI TV@nywhere Plus. The controller IC on the card
+  is marked "KS003". The controller is I2C at address 0x30, but does not seem
+  to respond to probes until a read is performed from a valid device.
+  I don't know why...
+
+  Note: This remote may be of similar or identical design to the
+  Pixelview remote (?).  The raw codes and duplicate button codes
+  appear to be the same.
+
+  Henry Wong <henry@stuffedcow.net>
+  Some changes to formatting and keycodes by Mark Schultz <n9xmj@yahoo.com>
+*/
+
+static struct rc_map_table msi_tvanywhere_plus[] = {
+
+/*  ---- Remote Button Layout ----
+
+    POWER   SOURCE  SCAN    MUTE
+    TV/FM   1       2       3
+    |>      4       5       6
+    <|      7       8       9
+    ^^UP    0       +       RECALL
+    vvDN    RECORD  STOP    PLAY
+
+	MINIMIZE          ZOOM
+
+		  CH+
+      VOL-                   VOL+
+		  CH-
+
+	SNAPSHOT           MTS
+
+     <<      FUNC    >>     RESET
+*/
+
+	{ 0x01, KEY_1 },		/* 1 */
+	{ 0x0b, KEY_2 },		/* 2 */
+	{ 0x1b, KEY_3 },		/* 3 */
+	{ 0x05, KEY_4 },		/* 4 */
+	{ 0x09, KEY_5 },		/* 5 */
+	{ 0x15, KEY_6 },		/* 6 */
+	{ 0x06, KEY_7 },		/* 7 */
+	{ 0x0a, KEY_8 },		/* 8 */
+	{ 0x12, KEY_9 },		/* 9 */
+	{ 0x02, KEY_0 },		/* 0 */
+	{ 0x10, KEY_KPPLUS },		/* + */
+	{ 0x13, KEY_AGAIN },		/* Recall */
+
+	{ 0x1e, KEY_POWER },		/* Power */
+	{ 0x07, KEY_TUNER },		/* Source */
+	{ 0x1c, KEY_SEARCH },		/* Scan */
+	{ 0x18, KEY_MUTE },		/* Mute */
+
+	{ 0x03, KEY_RADIO },		/* TV/FM */
+	/* The next four keys are duplicates that appear to send the
+	   same IR code as Ch+, Ch-, >>, and << .  The raw code assigned
+	   to them is the actual code + 0x20 - they will never be
+	   detected as such unless some way is discovered to distinguish
+	   these buttons from those that have the same code. */
+	{ 0x3f, KEY_RIGHT },		/* |> and Ch+ */
+	{ 0x37, KEY_LEFT },		/* <| and Ch- */
+	{ 0x2c, KEY_UP },		/* ^^Up and >> */
+	{ 0x24, KEY_DOWN },		/* vvDn and << */
+
+	{ 0x00, KEY_RECORD },		/* Record */
+	{ 0x08, KEY_STOP },		/* Stop */
+	{ 0x11, KEY_PLAY },		/* Play */
+
+	{ 0x0f, KEY_CLOSE },		/* Minimize */
+	{ 0x19, KEY_ZOOM },		/* Zoom */
+	{ 0x1a, KEY_CAMERA },		/* Snapshot */
+	{ 0x0d, KEY_LANGUAGE },		/* MTS */
+
+	{ 0x14, KEY_VOLUMEDOWN },	/* Vol- */
+	{ 0x16, KEY_VOLUMEUP },		/* Vol+ */
+	{ 0x17, KEY_CHANNELDOWN },	/* Ch- */
+	{ 0x1f, KEY_CHANNELUP },	/* Ch+ */
+
+	{ 0x04, KEY_REWIND },		/* << */
+	{ 0x0e, KEY_MENU },		/* Function */
+	{ 0x0c, KEY_FASTFORWARD },	/* >> */
+	{ 0x1d, KEY_RESTART },		/* Reset */
+};
+
+static struct rc_map_list msi_tvanywhere_plus_map = {
+	.map = {
+		.scan    = msi_tvanywhere_plus,
+		.size    = ARRAY_SIZE(msi_tvanywhere_plus),
+		.rc_type = RC_TYPE_UNKNOWN,	/* Legacy IR type */
+		.name    = RC_MAP_MSI_TVANYWHERE_PLUS,
+	}
+};
+
+static int __init init_rc_map_msi_tvanywhere_plus(void)
+{
+	return rc_map_register(&msi_tvanywhere_plus_map);
+}
+
+static void __exit exit_rc_map_msi_tvanywhere_plus(void)
+{
+	rc_map_unregister(&msi_tvanywhere_plus_map);
+}
+
+module_init(init_rc_map_msi_tvanywhere_plus)
+module_exit(exit_rc_map_msi_tvanywhere_plus)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-nebula.c linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-nebula.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-nebula.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-nebula.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,96 @@
+/* nebula.h - Keytable for nebula Remote Controller
+ *
+ * keymap imported from ir-keymaps.c
+ *
+ * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
+
+static struct rc_map_table nebula[] = {
+	{ 0x00, KEY_0 },
+	{ 0x01, KEY_1 },
+	{ 0x02, KEY_2 },
+	{ 0x03, KEY_3 },
+	{ 0x04, KEY_4 },
+	{ 0x05, KEY_5 },
+	{ 0x06, KEY_6 },
+	{ 0x07, KEY_7 },
+	{ 0x08, KEY_8 },
+	{ 0x09, KEY_9 },
+	{ 0x0a, KEY_TV },
+	{ 0x0b, KEY_AUX },
+	{ 0x0c, KEY_DVD },
+	{ 0x0d, KEY_POWER },
+	{ 0x0e, KEY_MHP },	/* labelled 'Picture' */
+	{ 0x0f, KEY_AUDIO },
+	{ 0x10, KEY_INFO },
+	{ 0x11, KEY_F13 },	/* 16:9 */
+	{ 0x12, KEY_F14 },	/* 14:9 */
+	{ 0x13, KEY_EPG },
+	{ 0x14, KEY_EXIT },
+	{ 0x15, KEY_MENU },
+	{ 0x16, KEY_UP },
+	{ 0x17, KEY_DOWN },
+	{ 0x18, KEY_LEFT },
+	{ 0x19, KEY_RIGHT },
+	{ 0x1a, KEY_ENTER },
+	{ 0x1b, KEY_CHANNELUP },
+	{ 0x1c, KEY_CHANNELDOWN },
+	{ 0x1d, KEY_VOLUMEUP },
+	{ 0x1e, KEY_VOLUMEDOWN },
+	{ 0x1f, KEY_RED },
+	{ 0x20, KEY_GREEN },
+	{ 0x21, KEY_YELLOW },
+	{ 0x22, KEY_BLUE },
+	{ 0x23, KEY_SUBTITLE },
+	{ 0x24, KEY_F15 },	/* AD */
+	{ 0x25, KEY_TEXT },
+	{ 0x26, KEY_MUTE },
+	{ 0x27, KEY_REWIND },
+	{ 0x28, KEY_STOP },
+	{ 0x29, KEY_PLAY },
+	{ 0x2a, KEY_FASTFORWARD },
+	{ 0x2b, KEY_F16 },	/* chapter */
+	{ 0x2c, KEY_PAUSE },
+	{ 0x2d, KEY_PLAY },
+	{ 0x2e, KEY_RECORD },
+	{ 0x2f, KEY_F17 },	/* picture in picture */
+	{ 0x30, KEY_KPPLUS },	/* zoom in */
+	{ 0x31, KEY_KPMINUS },	/* zoom out */
+	{ 0x32, KEY_F18 },	/* capture */
+	{ 0x33, KEY_F19 },	/* web */
+	{ 0x34, KEY_EMAIL },
+	{ 0x35, KEY_PHONE },
+	{ 0x36, KEY_PC },
+};
+
+static struct rc_map_list nebula_map = {
+	.map = {
+		.scan    = nebula,
+		.size    = ARRAY_SIZE(nebula),
+		.rc_type = RC_TYPE_UNKNOWN,	/* Legacy IR type */
+		.name    = RC_MAP_NEBULA,
+	}
+};
+
+static int __init init_rc_map_nebula(void)
+{
+	return rc_map_register(&nebula_map);
+}
+
+static void __exit exit_rc_map_nebula(void)
+{
+	rc_map_unregister(&nebula_map);
+}
+
+module_init(init_rc_map_nebula)
+module_exit(exit_rc_map_nebula)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-nec-terratec-cinergy-xs.c linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-nec-terratec-cinergy-xs.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-nec-terratec-cinergy-xs.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-nec-terratec-cinergy-xs.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,105 @@
+/* nec-terratec-cinergy-xs.h - Keytable for nec_terratec_cinergy_xs Remote Controller
+ *
+ * keymap imported from ir-keymaps.c
+ *
+ * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
+
+/* Terratec Cinergy Hybrid T USB XS FM
+   Mauro Carvalho Chehab <mchehab@redhat.com>
+ */
+
+static struct rc_map_table nec_terratec_cinergy_xs[] = {
+	{ 0x1441, KEY_HOME},
+	{ 0x1401, KEY_POWER2},
+
+	{ 0x1442, KEY_MENU},		/* DVD menu */
+	{ 0x1443, KEY_SUBTITLE},
+	{ 0x1444, KEY_TEXT},		/* Teletext */
+	{ 0x1445, KEY_DELETE},
+
+	{ 0x1402, KEY_1},
+	{ 0x1403, KEY_2},
+	{ 0x1404, KEY_3},
+	{ 0x1405, KEY_4},
+	{ 0x1406, KEY_5},
+	{ 0x1407, KEY_6},
+	{ 0x1408, KEY_7},
+	{ 0x1409, KEY_8},
+	{ 0x140a, KEY_9},
+	{ 0x140c, KEY_0},
+
+	{ 0x140b, KEY_TUNER},		/* AV */
+	{ 0x140d, KEY_MODE},		/* A.B */
+
+	{ 0x1446, KEY_TV},
+	{ 0x1447, KEY_DVD},
+	{ 0x1449, KEY_VIDEO},
+	{ 0x144a, KEY_RADIO},		/* Music */
+	{ 0x144b, KEY_CAMERA},		/* PIC */
+
+	{ 0x1410, KEY_UP},
+	{ 0x1411, KEY_LEFT},
+	{ 0x1412, KEY_OK},
+	{ 0x1413, KEY_RIGHT},
+	{ 0x1414, KEY_DOWN},
+
+	{ 0x140f, KEY_EPG},
+	{ 0x1416, KEY_INFO},
+	{ 0x144d, KEY_BACKSPACE},
+
+	{ 0x141c, KEY_VOLUMEUP},
+	{ 0x141e, KEY_VOLUMEDOWN},
+
+	{ 0x144c, KEY_PLAY},
+	{ 0x141d, KEY_MUTE},
+
+	{ 0x141b, KEY_CHANNELUP},
+	{ 0x141f, KEY_CHANNELDOWN},
+
+	{ 0x1417, KEY_RED},
+	{ 0x1418, KEY_GREEN},
+	{ 0x1419, KEY_YELLOW},
+	{ 0x141a, KEY_BLUE},
+
+	{ 0x1458, KEY_RECORD},
+	{ 0x1448, KEY_STOP},
+	{ 0x1440, KEY_PAUSE},
+
+	{ 0x1454, KEY_LAST},
+	{ 0x144e, KEY_REWIND},
+	{ 0x144f, KEY_FASTFORWARD},
+	{ 0x145c, KEY_NEXT},
+};
+
+static struct rc_map_list nec_terratec_cinergy_xs_map = {
+	.map = {
+		.scan    = nec_terratec_cinergy_xs,
+		.size    = ARRAY_SIZE(nec_terratec_cinergy_xs),
+		.rc_type = RC_TYPE_NEC,
+		.name    = RC_MAP_NEC_TERRATEC_CINERGY_XS,
+	}
+};
+
+static int __init init_rc_map_nec_terratec_cinergy_xs(void)
+{
+	return rc_map_register(&nec_terratec_cinergy_xs_map);
+}
+
+static void __exit exit_rc_map_nec_terratec_cinergy_xs(void)
+{
+	rc_map_unregister(&nec_terratec_cinergy_xs_map);
+}
+
+module_init(init_rc_map_nec_terratec_cinergy_xs)
+module_exit(exit_rc_map_nec_terratec_cinergy_xs)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-norwood.c linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-norwood.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-norwood.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-norwood.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,85 @@
+/* norwood.h - Keytable for norwood Remote Controller
+ *
+ * keymap imported from ir-keymaps.c
+ *
+ * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
+
+/* Norwood Micro (non-Pro) TV Tuner
+   By Peter Naulls <peter@chocky.org>
+   Key comments are the functions given in the manual */
+
+static struct rc_map_table norwood[] = {
+	/* Keys 0 to 9 */
+	{ 0x20, KEY_0 },
+	{ 0x21, KEY_1 },
+	{ 0x22, KEY_2 },
+	{ 0x23, KEY_3 },
+	{ 0x24, KEY_4 },
+	{ 0x25, KEY_5 },
+	{ 0x26, KEY_6 },
+	{ 0x27, KEY_7 },
+	{ 0x28, KEY_8 },
+	{ 0x29, KEY_9 },
+
+	{ 0x78, KEY_TUNER },		/* Video Source        */
+	{ 0x2c, KEY_EXIT },		/* Open/Close software */
+	{ 0x2a, KEY_SELECT },		/* 2 Digit Select      */
+	{ 0x69, KEY_AGAIN },		/* Recall              */
+
+	{ 0x32, KEY_BRIGHTNESSUP },	/* Brightness increase */
+	{ 0x33, KEY_BRIGHTNESSDOWN },	/* Brightness decrease */
+	{ 0x6b, KEY_KPPLUS },		/* (not named >>>>>)   */
+	{ 0x6c, KEY_KPMINUS },		/* (not named <<<<<)   */
+
+	{ 0x2d, KEY_MUTE },		/* Mute                */
+	{ 0x30, KEY_VOLUMEUP },		/* Volume up           */
+	{ 0x31, KEY_VOLUMEDOWN },	/* Volume down         */
+	{ 0x60, KEY_CHANNELUP },	/* Channel up          */
+	{ 0x61, KEY_CHANNELDOWN },	/* Channel down        */
+
+	{ 0x3f, KEY_RECORD },		/* Record              */
+	{ 0x37, KEY_PLAY },		/* Play                */
+	{ 0x36, KEY_PAUSE },		/* Pause               */
+	{ 0x2b, KEY_STOP },		/* Stop                */
+	{ 0x67, KEY_FASTFORWARD },	/* Foward              */
+	{ 0x66, KEY_REWIND },		/* Rewind              */
+	{ 0x3e, KEY_SEARCH },		/* Auto Scan           */
+	{ 0x2e, KEY_CAMERA },		/* Capture Video       */
+	{ 0x6d, KEY_MENU },		/* Show/Hide Control   */
+	{ 0x2f, KEY_ZOOM },		/* Full Screen         */
+	{ 0x34, KEY_RADIO },		/* FM                  */
+	{ 0x65, KEY_POWER },		/* Computer power      */
+};
+
+static struct rc_map_list norwood_map = {
+	.map = {
+		.scan    = norwood,
+		.size    = ARRAY_SIZE(norwood),
+		.rc_type = RC_TYPE_UNKNOWN,	/* Legacy IR type */
+		.name    = RC_MAP_NORWOOD,
+	}
+};
+
+static int __init init_rc_map_norwood(void)
+{
+	return rc_map_register(&norwood_map);
+}
+
+static void __exit exit_rc_map_norwood(void)
+{
+	rc_map_unregister(&norwood_map);
+}
+
+module_init(init_rc_map_norwood)
+module_exit(exit_rc_map_norwood)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-npgtech.c linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-npgtech.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-npgtech.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-npgtech.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,80 @@
+/* npgtech.h - Keytable for npgtech Remote Controller
+ *
+ * keymap imported from ir-keymaps.c
+ *
+ * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
+
+static struct rc_map_table npgtech[] = {
+	{ 0x1d, KEY_SWITCHVIDEOMODE },	/* switch inputs */
+	{ 0x2a, KEY_FRONT },
+
+	{ 0x3e, KEY_1 },
+	{ 0x02, KEY_2 },
+	{ 0x06, KEY_3 },
+	{ 0x0a, KEY_4 },
+	{ 0x0e, KEY_5 },
+	{ 0x12, KEY_6 },
+	{ 0x16, KEY_7 },
+	{ 0x1a, KEY_8 },
+	{ 0x1e, KEY_9 },
+	{ 0x3a, KEY_0 },
+	{ 0x22, KEY_NUMLOCK },		/* -/-- */
+	{ 0x20, KEY_REFRESH },
+
+	{ 0x03, KEY_BRIGHTNESSDOWN },
+	{ 0x28, KEY_AUDIO },
+	{ 0x3c, KEY_CHANNELUP },
+	{ 0x3f, KEY_VOLUMEDOWN },
+	{ 0x2e, KEY_MUTE },
+	{ 0x3b, KEY_VOLUMEUP },
+	{ 0x00, KEY_CHANNELDOWN },
+	{ 0x07, KEY_BRIGHTNESSUP },
+	{ 0x2c, KEY_TEXT },
+
+	{ 0x37, KEY_RECORD },
+	{ 0x17, KEY_PLAY },
+	{ 0x13, KEY_PAUSE },
+	{ 0x26, KEY_STOP },
+	{ 0x18, KEY_FASTFORWARD },
+	{ 0x14, KEY_REWIND },
+	{ 0x33, KEY_ZOOM },
+	{ 0x32, KEY_KEYBOARD },
+	{ 0x30, KEY_GOTO },		/* Pointing arrow */
+	{ 0x36, KEY_MACRO },		/* Maximize/Minimize (yellow) */
+	{ 0x0b, KEY_RADIO },
+	{ 0x10, KEY_POWER },
+
+};
+
+static struct rc_map_list npgtech_map = {
+	.map = {
+		.scan    = npgtech,
+		.size    = ARRAY_SIZE(npgtech),
+		.rc_type = RC_TYPE_UNKNOWN,	/* Legacy IR type */
+		.name    = RC_MAP_NPGTECH,
+	}
+};
+
+static int __init init_rc_map_npgtech(void)
+{
+	return rc_map_register(&npgtech_map);
+}
+
+static void __exit exit_rc_map_npgtech(void)
+{
+	rc_map_unregister(&npgtech_map);
+}
+
+module_init(init_rc_map_npgtech)
+module_exit(exit_rc_map_npgtech)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-pctv-sedna.c linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-pctv-sedna.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-pctv-sedna.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-pctv-sedna.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,80 @@
+/* pctv-sedna.h - Keytable for pctv_sedna Remote Controller
+ *
+ * keymap imported from ir-keymaps.c
+ *
+ * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
+
+/* Mapping for the 28 key remote control as seen at
+   http://www.sednacomputer.com/photo/cardbus-tv.jpg
+   Pavel Mihaylov <bin@bash.info>
+   Also for the remote bundled with Kozumi KTV-01C card */
+
+static struct rc_map_table pctv_sedna[] = {
+	{ 0x00, KEY_0 },
+	{ 0x01, KEY_1 },
+	{ 0x02, KEY_2 },
+	{ 0x03, KEY_3 },
+	{ 0x04, KEY_4 },
+	{ 0x05, KEY_5 },
+	{ 0x06, KEY_6 },
+	{ 0x07, KEY_7 },
+	{ 0x08, KEY_8 },
+	{ 0x09, KEY_9 },
+
+	{ 0x0a, KEY_AGAIN },	/* Recall */
+	{ 0x0b, KEY_CHANNELUP },
+	{ 0x0c, KEY_VOLUMEUP },
+	{ 0x0d, KEY_MODE },	/* Stereo */
+	{ 0x0e, KEY_STOP },
+	{ 0x0f, KEY_PREVIOUSSONG },
+	{ 0x10, KEY_ZOOM },
+	{ 0x11, KEY_TUNER },	/* Source */
+	{ 0x12, KEY_POWER },
+	{ 0x13, KEY_MUTE },
+	{ 0x15, KEY_CHANNELDOWN },
+	{ 0x18, KEY_VOLUMEDOWN },
+	{ 0x19, KEY_CAMERA },	/* Snapshot */
+	{ 0x1a, KEY_NEXTSONG },
+	{ 0x1b, KEY_TIME },	/* Time Shift */
+	{ 0x1c, KEY_RADIO },	/* FM Radio */
+	{ 0x1d, KEY_RECORD },
+	{ 0x1e, KEY_PAUSE },
+	/* additional codes for Kozumi's remote */
+	{ 0x14, KEY_INFO },	/* OSD */
+	{ 0x16, KEY_OK },	/* OK */
+	{ 0x17, KEY_DIGITS },	/* Plus */
+	{ 0x1f, KEY_PLAY },	/* Play */
+};
+
+static struct rc_map_list pctv_sedna_map = {
+	.map = {
+		.scan    = pctv_sedna,
+		.size    = ARRAY_SIZE(pctv_sedna),
+		.rc_type = RC_TYPE_UNKNOWN,	/* Legacy IR type */
+		.name    = RC_MAP_PCTV_SEDNA,
+	}
+};
+
+static int __init init_rc_map_pctv_sedna(void)
+{
+	return rc_map_register(&pctv_sedna_map);
+}
+
+static void __exit exit_rc_map_pctv_sedna(void)
+{
+	rc_map_unregister(&pctv_sedna_map);
+}
+
+module_init(init_rc_map_pctv_sedna)
+module_exit(exit_rc_map_pctv_sedna)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-pinnacle-color.c linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-pinnacle-color.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-pinnacle-color.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-pinnacle-color.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,94 @@
+/* pinnacle-color.h - Keytable for pinnacle_color Remote Controller
+ *
+ * keymap imported from ir-keymaps.c
+ *
+ * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
+
+static struct rc_map_table pinnacle_color[] = {
+	{ 0x59, KEY_MUTE },
+	{ 0x4a, KEY_POWER },
+
+	{ 0x18, KEY_TEXT },
+	{ 0x26, KEY_TV },
+	{ 0x3d, KEY_PRINT },
+
+	{ 0x48, KEY_RED },
+	{ 0x04, KEY_GREEN },
+	{ 0x11, KEY_YELLOW },
+	{ 0x00, KEY_BLUE },
+
+	{ 0x2d, KEY_VOLUMEUP },
+	{ 0x1e, KEY_VOLUMEDOWN },
+
+	{ 0x49, KEY_MENU },
+
+	{ 0x16, KEY_CHANNELUP },
+	{ 0x17, KEY_CHANNELDOWN },
+
+	{ 0x20, KEY_UP },
+	{ 0x21, KEY_DOWN },
+	{ 0x22, KEY_LEFT },
+	{ 0x23, KEY_RIGHT },
+	{ 0x0d, KEY_SELECT },
+
+	{ 0x08, KEY_BACK },
+	{ 0x07, KEY_REFRESH },
+
+	{ 0x2f, KEY_ZOOM },
+	{ 0x29, KEY_RECORD },
+
+	{ 0x4b, KEY_PAUSE },
+	{ 0x4d, KEY_REWIND },
+	{ 0x2e, KEY_PLAY },
+	{ 0x4e, KEY_FORWARD },
+	{ 0x53, KEY_PREVIOUS },
+	{ 0x4c, KEY_STOP },
+	{ 0x54, KEY_NEXT },
+
+	{ 0x69, KEY_0 },
+	{ 0x6a, KEY_1 },
+	{ 0x6b, KEY_2 },
+	{ 0x6c, KEY_3 },
+	{ 0x6d, KEY_4 },
+	{ 0x6e, KEY_5 },
+	{ 0x6f, KEY_6 },
+	{ 0x70, KEY_7 },
+	{ 0x71, KEY_8 },
+	{ 0x72, KEY_9 },
+
+	{ 0x74, KEY_CHANNEL },
+	{ 0x0a, KEY_BACKSPACE },
+};
+
+static struct rc_map_list pinnacle_color_map = {
+	.map = {
+		.scan    = pinnacle_color,
+		.size    = ARRAY_SIZE(pinnacle_color),
+		.rc_type = RC_TYPE_UNKNOWN,	/* Legacy IR type */
+		.name    = RC_MAP_PINNACLE_COLOR,
+	}
+};
+
+static int __init init_rc_map_pinnacle_color(void)
+{
+	return rc_map_register(&pinnacle_color_map);
+}
+
+static void __exit exit_rc_map_pinnacle_color(void)
+{
+	rc_map_unregister(&pinnacle_color_map);
+}
+
+module_init(init_rc_map_pinnacle_color)
+module_exit(exit_rc_map_pinnacle_color)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-pinnacle-grey.c linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-pinnacle-grey.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-pinnacle-grey.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-pinnacle-grey.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,89 @@
+/* pinnacle-grey.h - Keytable for pinnacle_grey Remote Controller
+ *
+ * keymap imported from ir-keymaps.c
+ *
+ * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
+
+static struct rc_map_table pinnacle_grey[] = {
+	{ 0x3a, KEY_0 },
+	{ 0x31, KEY_1 },
+	{ 0x32, KEY_2 },
+	{ 0x33, KEY_3 },
+	{ 0x34, KEY_4 },
+	{ 0x35, KEY_5 },
+	{ 0x36, KEY_6 },
+	{ 0x37, KEY_7 },
+	{ 0x38, KEY_8 },
+	{ 0x39, KEY_9 },
+
+	{ 0x2f, KEY_POWER },
+
+	{ 0x2e, KEY_P },
+	{ 0x1f, KEY_L },
+	{ 0x2b, KEY_I },
+
+	{ 0x2d, KEY_SCREEN },
+	{ 0x1e, KEY_ZOOM },
+	{ 0x1b, KEY_VOLUMEUP },
+	{ 0x0f, KEY_VOLUMEDOWN },
+	{ 0x17, KEY_CHANNELUP },
+	{ 0x1c, KEY_CHANNELDOWN },
+	{ 0x25, KEY_INFO },
+
+	{ 0x3c, KEY_MUTE },
+
+	{ 0x3d, KEY_LEFT },
+	{ 0x3b, KEY_RIGHT },
+
+	{ 0x3f, KEY_UP },
+	{ 0x3e, KEY_DOWN },
+	{ 0x1a, KEY_ENTER },
+
+	{ 0x1d, KEY_MENU },
+	{ 0x19, KEY_AGAIN },
+	{ 0x16, KEY_PREVIOUSSONG },
+	{ 0x13, KEY_NEXTSONG },
+	{ 0x15, KEY_PAUSE },
+	{ 0x0e, KEY_REWIND },
+	{ 0x0d, KEY_PLAY },
+	{ 0x0b, KEY_STOP },
+	{ 0x07, KEY_FORWARD },
+	{ 0x27, KEY_RECORD },
+	{ 0x26, KEY_TUNER },
+	{ 0x29, KEY_TEXT },
+	{ 0x2a, KEY_MEDIA },
+	{ 0x18, KEY_EPG },
+};
+
+static struct rc_map_list pinnacle_grey_map = {
+	.map = {
+		.scan    = pinnacle_grey,
+		.size    = ARRAY_SIZE(pinnacle_grey),
+		.rc_type = RC_TYPE_UNKNOWN,	/* Legacy IR type */
+		.name    = RC_MAP_PINNACLE_GREY,
+	}
+};
+
+static int __init init_rc_map_pinnacle_grey(void)
+{
+	return rc_map_register(&pinnacle_grey_map);
+}
+
+static void __exit exit_rc_map_pinnacle_grey(void)
+{
+	rc_map_unregister(&pinnacle_grey_map);
+}
+
+module_init(init_rc_map_pinnacle_grey)
+module_exit(exit_rc_map_pinnacle_grey)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-pinnacle-pctv-hd.c linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-pinnacle-pctv-hd.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-pinnacle-pctv-hd.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-pinnacle-pctv-hd.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,73 @@
+/* pinnacle-pctv-hd.h - Keytable for pinnacle_pctv_hd Remote Controller
+ *
+ * keymap imported from ir-keymaps.c
+ *
+ * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
+
+/* Pinnacle PCTV HD 800i mini remote */
+
+static struct rc_map_table pinnacle_pctv_hd[] = {
+
+	{ 0x0f, KEY_1 },
+	{ 0x15, KEY_2 },
+	{ 0x10, KEY_3 },
+	{ 0x18, KEY_4 },
+	{ 0x1b, KEY_5 },
+	{ 0x1e, KEY_6 },
+	{ 0x11, KEY_7 },
+	{ 0x21, KEY_8 },
+	{ 0x12, KEY_9 },
+	{ 0x27, KEY_0 },
+
+	{ 0x24, KEY_ZOOM },
+	{ 0x2a, KEY_SUBTITLE },
+
+	{ 0x00, KEY_MUTE },
+	{ 0x01, KEY_ENTER },	/* Pinnacle Logo */
+	{ 0x39, KEY_POWER },
+
+	{ 0x03, KEY_VOLUMEUP },
+	{ 0x09, KEY_VOLUMEDOWN },
+	{ 0x06, KEY_CHANNELUP },
+	{ 0x0c, KEY_CHANNELDOWN },
+
+	{ 0x2d, KEY_REWIND },
+	{ 0x30, KEY_PLAYPAUSE },
+	{ 0x33, KEY_FASTFORWARD },
+	{ 0x3c, KEY_STOP },
+	{ 0x36, KEY_RECORD },
+	{ 0x3f, KEY_EPG },	/* Labeled "?" */
+};
+
+static struct rc_map_list pinnacle_pctv_hd_map = {
+	.map = {
+		.scan    = pinnacle_pctv_hd,
+		.size    = ARRAY_SIZE(pinnacle_pctv_hd),
+		.rc_type = RC_TYPE_UNKNOWN,	/* Legacy IR type */
+		.name    = RC_MAP_PINNACLE_PCTV_HD,
+	}
+};
+
+static int __init init_rc_map_pinnacle_pctv_hd(void)
+{
+	return rc_map_register(&pinnacle_pctv_hd_map);
+}
+
+static void __exit exit_rc_map_pinnacle_pctv_hd(void)
+{
+	rc_map_unregister(&pinnacle_pctv_hd_map);
+}
+
+module_init(init_rc_map_pinnacle_pctv_hd)
+module_exit(exit_rc_map_pinnacle_pctv_hd)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-pixelview-002t.c linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-pixelview-002t.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-pixelview-002t.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-pixelview-002t.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,77 @@
+/* rc-pixelview-mk12.h - Keytable for pixelview Remote Controller
+ *
+ * keymap imported from ir-keymaps.c
+ *
+ * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
+
+/*
+ * Keytable for 002-T IR remote provided together with Pixelview
+ * SBTVD Hybrid Remote Controller. Uses NEC extended format.
+ */
+static struct rc_map_table pixelview_002t[] = {
+	{ 0x866b13, KEY_MUTE },
+	{ 0x866b12, KEY_POWER2 },	/* power */
+
+	{ 0x866b01, KEY_1 },
+	{ 0x866b02, KEY_2 },
+	{ 0x866b03, KEY_3 },
+	{ 0x866b04, KEY_4 },
+	{ 0x866b05, KEY_5 },
+	{ 0x866b06, KEY_6 },
+	{ 0x866b07, KEY_7 },
+	{ 0x866b08, KEY_8 },
+	{ 0x866b09, KEY_9 },
+	{ 0x866b00, KEY_0 },
+
+	{ 0x866b0d, KEY_CHANNELUP },
+	{ 0x866b19, KEY_CHANNELDOWN },
+	{ 0x866b10, KEY_VOLUMEUP },	/* vol + */
+	{ 0x866b0c, KEY_VOLUMEDOWN },	/* vol - */
+
+	{ 0x866b0a, KEY_CAMERA },	/* snapshot */
+	{ 0x866b0b, KEY_ZOOM },		/* zoom */
+
+	{ 0x866b1b, KEY_BACKSPACE },
+	{ 0x866b15, KEY_ENTER },
+
+	{ 0x866b1d, KEY_UP },
+	{ 0x866b1e, KEY_DOWN },
+	{ 0x866b0e, KEY_LEFT },
+	{ 0x866b0f, KEY_RIGHT },
+
+	{ 0x866b18, KEY_RECORD },
+	{ 0x866b1a, KEY_STOP },
+};
+
+static struct rc_map_list pixelview_map = {
+	.map = {
+		.scan    = pixelview_002t,
+		.size    = ARRAY_SIZE(pixelview_002t),
+		.rc_type = RC_TYPE_NEC,
+		.name    = RC_MAP_PIXELVIEW_002T,
+	}
+};
+
+static int __init init_rc_map_pixelview(void)
+{
+	return rc_map_register(&pixelview_map);
+}
+
+static void __exit exit_rc_map_pixelview(void)
+{
+	rc_map_unregister(&pixelview_map);
+}
+
+module_init(init_rc_map_pixelview)
+module_exit(exit_rc_map_pixelview)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-pixelview.c linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-pixelview.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-pixelview.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-pixelview.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,82 @@
+/* pixelview.h - Keytable for pixelview Remote Controller
+ *
+ * keymap imported from ir-keymaps.c
+ *
+ * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
+
+static struct rc_map_table pixelview[] = {
+
+	{ 0x1e, KEY_POWER },	/* power */
+	{ 0x07, KEY_MEDIA },	/* source */
+	{ 0x1c, KEY_SEARCH },	/* scan */
+
+
+	{ 0x03, KEY_TUNER },		/* TV/FM */
+
+	{ 0x00, KEY_RECORD },
+	{ 0x08, KEY_STOP },
+	{ 0x11, KEY_PLAY },
+
+	{ 0x1a, KEY_PLAYPAUSE },	/* freeze */
+	{ 0x19, KEY_ZOOM },		/* zoom */
+	{ 0x0f, KEY_TEXT },		/* min */
+
+	{ 0x01, KEY_1 },
+	{ 0x0b, KEY_2 },
+	{ 0x1b, KEY_3 },
+	{ 0x05, KEY_4 },
+	{ 0x09, KEY_5 },
+	{ 0x15, KEY_6 },
+	{ 0x06, KEY_7 },
+	{ 0x0a, KEY_8 },
+	{ 0x12, KEY_9 },
+	{ 0x02, KEY_0 },
+	{ 0x10, KEY_LAST },		/* +100 */
+	{ 0x13, KEY_LIST },		/* recall */
+
+	{ 0x1f, KEY_CHANNELUP },	/* chn down */
+	{ 0x17, KEY_CHANNELDOWN },	/* chn up */
+	{ 0x16, KEY_VOLUMEUP },		/* vol down */
+	{ 0x14, KEY_VOLUMEDOWN },	/* vol up */
+
+	{ 0x04, KEY_KPMINUS },		/* <<< */
+	{ 0x0e, KEY_SETUP },		/* function */
+	{ 0x0c, KEY_KPPLUS },		/* >>> */
+
+	{ 0x0d, KEY_GOTO },		/* mts */
+	{ 0x1d, KEY_REFRESH },		/* reset */
+	{ 0x18, KEY_MUTE },		/* mute/unmute */
+};
+
+static struct rc_map_list pixelview_map = {
+	.map = {
+		.scan    = pixelview,
+		.size    = ARRAY_SIZE(pixelview),
+		.rc_type = RC_TYPE_UNKNOWN,	/* Legacy IR type */
+		.name    = RC_MAP_PIXELVIEW,
+	}
+};
+
+static int __init init_rc_map_pixelview(void)
+{
+	return rc_map_register(&pixelview_map);
+}
+
+static void __exit exit_rc_map_pixelview(void)
+{
+	rc_map_unregister(&pixelview_map);
+}
+
+module_init(init_rc_map_pixelview)
+module_exit(exit_rc_map_pixelview)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-pixelview-mk12.c linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-pixelview-mk12.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-pixelview-mk12.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-pixelview-mk12.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,83 @@
+/* rc-pixelview-mk12.h - Keytable for pixelview Remote Controller
+ *
+ * keymap imported from ir-keymaps.c
+ *
+ * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
+
+/*
+ * Keytable for MK-F12 IR remote provided together with Pixelview
+ * Ultra Pro Remote Controller. Uses NEC extended format.
+ */
+static struct rc_map_table pixelview_mk12[] = {
+	{ 0x866b03, KEY_TUNER },	/* Timeshift */
+	{ 0x866b1e, KEY_POWER2 },	/* power */
+
+	{ 0x866b01, KEY_1 },
+	{ 0x866b0b, KEY_2 },
+	{ 0x866b1b, KEY_3 },
+	{ 0x866b05, KEY_4 },
+	{ 0x866b09, KEY_5 },
+	{ 0x866b15, KEY_6 },
+	{ 0x866b06, KEY_7 },
+	{ 0x866b0a, KEY_8 },
+	{ 0x866b12, KEY_9 },
+	{ 0x866b02, KEY_0 },
+
+	{ 0x866b13, KEY_AGAIN },	/* loop */
+	{ 0x866b10, KEY_DIGITS },	/* +100 */
+
+	{ 0x866b00, KEY_MEDIA },	/* source */
+	{ 0x866b18, KEY_MUTE },		/* mute */
+	{ 0x866b19, KEY_CAMERA },	/* snapshot */
+	{ 0x866b1a, KEY_SEARCH },	/* scan */
+
+	{ 0x866b16, KEY_CHANNELUP },	/* chn + */
+	{ 0x866b14, KEY_CHANNELDOWN },	/* chn - */
+	{ 0x866b1f, KEY_VOLUMEUP },	/* vol + */
+	{ 0x866b17, KEY_VOLUMEDOWN },	/* vol - */
+	{ 0x866b1c, KEY_ZOOM },		/* zoom */
+
+	{ 0x866b04, KEY_REWIND },
+	{ 0x866b0e, KEY_RECORD },
+	{ 0x866b0c, KEY_FORWARD },
+
+	{ 0x866b1d, KEY_STOP },
+	{ 0x866b08, KEY_PLAY },
+	{ 0x866b0f, KEY_PAUSE },
+
+	{ 0x866b0d, KEY_TV },
+	{ 0x866b07, KEY_RADIO },	/* FM */
+};
+
+static struct rc_map_list pixelview_map = {
+	.map = {
+		.scan    = pixelview_mk12,
+		.size    = ARRAY_SIZE(pixelview_mk12),
+		.rc_type = RC_TYPE_NEC,
+		.name    = RC_MAP_PIXELVIEW_MK12,
+	}
+};
+
+static int __init init_rc_map_pixelview(void)
+{
+	return rc_map_register(&pixelview_map);
+}
+
+static void __exit exit_rc_map_pixelview(void)
+{
+	rc_map_unregister(&pixelview_map);
+}
+
+module_init(init_rc_map_pixelview)
+module_exit(exit_rc_map_pixelview)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-pixelview-new.c linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-pixelview-new.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-pixelview-new.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-pixelview-new.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,83 @@
+/* pixelview-new.h - Keytable for pixelview_new Remote Controller
+ *
+ * keymap imported from ir-keymaps.c
+ *
+ * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
+
+/*
+   Mauro Carvalho Chehab <mchehab@infradead.org>
+   present on PV MPEG 8000GT
+ */
+
+static struct rc_map_table pixelview_new[] = {
+	{ 0x3c, KEY_TIME },		/* Timeshift */
+	{ 0x12, KEY_POWER },
+
+	{ 0x3d, KEY_1 },
+	{ 0x38, KEY_2 },
+	{ 0x18, KEY_3 },
+	{ 0x35, KEY_4 },
+	{ 0x39, KEY_5 },
+	{ 0x15, KEY_6 },
+	{ 0x36, KEY_7 },
+	{ 0x3a, KEY_8 },
+	{ 0x1e, KEY_9 },
+	{ 0x3e, KEY_0 },
+
+	{ 0x1c, KEY_AGAIN },		/* LOOP	*/
+	{ 0x3f, KEY_MEDIA },		/* Source */
+	{ 0x1f, KEY_LAST },		/* +100 */
+	{ 0x1b, KEY_MUTE },
+
+	{ 0x17, KEY_CHANNELDOWN },
+	{ 0x16, KEY_CHANNELUP },
+	{ 0x10, KEY_VOLUMEUP },
+	{ 0x14, KEY_VOLUMEDOWN },
+	{ 0x13, KEY_ZOOM },
+
+	{ 0x19, KEY_CAMERA },		/* SNAPSHOT */
+	{ 0x1a, KEY_SEARCH },		/* scan */
+
+	{ 0x37, KEY_REWIND },		/* << */
+	{ 0x32, KEY_RECORD },		/* o (red) */
+	{ 0x33, KEY_FORWARD },		/* >> */
+	{ 0x11, KEY_STOP },		/* square */
+	{ 0x3b, KEY_PLAY },		/* > */
+	{ 0x30, KEY_PLAYPAUSE },	/* || */
+
+	{ 0x31, KEY_TV },
+	{ 0x34, KEY_RADIO },
+};
+
+static struct rc_map_list pixelview_new_map = {
+	.map = {
+		.scan    = pixelview_new,
+		.size    = ARRAY_SIZE(pixelview_new),
+		.rc_type = RC_TYPE_UNKNOWN,	/* Legacy IR type */
+		.name    = RC_MAP_PIXELVIEW_NEW,
+	}
+};
+
+static int __init init_rc_map_pixelview_new(void)
+{
+	return rc_map_register(&pixelview_new_map);
+}
+
+static void __exit exit_rc_map_pixelview_new(void)
+{
+	rc_map_unregister(&pixelview_new_map);
+}
+
+module_init(init_rc_map_pixelview_new)
+module_exit(exit_rc_map_pixelview_new)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-powercolor-real-angel.c linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-powercolor-real-angel.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-powercolor-real-angel.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-powercolor-real-angel.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,81 @@
+/* powercolor-real-angel.h - Keytable for powercolor_real_angel Remote Controller
+ *
+ * keymap imported from ir-keymaps.c
+ *
+ * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
+
+/*
+ * Remote control for Powercolor Real Angel 330
+ * Daniel Fraga <fragabr@gmail.com>
+ */
+
+static struct rc_map_table powercolor_real_angel[] = {
+	{ 0x38, KEY_SWITCHVIDEOMODE },	/* switch inputs */
+	{ 0x0c, KEY_MEDIA },		/* Turn ON/OFF App */
+	{ 0x00, KEY_0 },
+	{ 0x01, KEY_1 },
+	{ 0x02, KEY_2 },
+	{ 0x03, KEY_3 },
+	{ 0x04, KEY_4 },
+	{ 0x05, KEY_5 },
+	{ 0x06, KEY_6 },
+	{ 0x07, KEY_7 },
+	{ 0x08, KEY_8 },
+	{ 0x09, KEY_9 },
+	{ 0x0a, KEY_DIGITS },		/* single, double, tripple digit */
+	{ 0x29, KEY_PREVIOUS },		/* previous channel */
+	{ 0x12, KEY_BRIGHTNESSUP },
+	{ 0x13, KEY_BRIGHTNESSDOWN },
+	{ 0x2b, KEY_MODE },		/* stereo/mono */
+	{ 0x2c, KEY_TEXT },		/* teletext */
+	{ 0x20, KEY_CHANNELUP },	/* channel up */
+	{ 0x21, KEY_CHANNELDOWN },	/* channel down */
+	{ 0x10, KEY_VOLUMEUP },		/* volume up */
+	{ 0x11, KEY_VOLUMEDOWN },	/* volume down */
+	{ 0x0d, KEY_MUTE },
+	{ 0x1f, KEY_RECORD },
+	{ 0x17, KEY_PLAY },
+	{ 0x16, KEY_PAUSE },
+	{ 0x0b, KEY_STOP },
+	{ 0x27, KEY_FASTFORWARD },
+	{ 0x26, KEY_REWIND },
+	{ 0x1e, KEY_SEARCH },		/* autoscan */
+	{ 0x0e, KEY_CAMERA },		/* snapshot */
+	{ 0x2d, KEY_SETUP },
+	{ 0x0f, KEY_SCREEN },		/* full screen */
+	{ 0x14, KEY_RADIO },		/* FM radio */
+	{ 0x25, KEY_POWER },		/* power */
+};
+
+static struct rc_map_list powercolor_real_angel_map = {
+	.map = {
+		.scan    = powercolor_real_angel,
+		.size    = ARRAY_SIZE(powercolor_real_angel),
+		.rc_type = RC_TYPE_UNKNOWN,	/* Legacy IR type */
+		.name    = RC_MAP_POWERCOLOR_REAL_ANGEL,
+	}
+};
+
+static int __init init_rc_map_powercolor_real_angel(void)
+{
+	return rc_map_register(&powercolor_real_angel_map);
+}
+
+static void __exit exit_rc_map_powercolor_real_angel(void)
+{
+	rc_map_unregister(&powercolor_real_angel_map);
+}
+
+module_init(init_rc_map_powercolor_real_angel)
+module_exit(exit_rc_map_powercolor_real_angel)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-proteus-2309.c linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-proteus-2309.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-proteus-2309.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-proteus-2309.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,69 @@
+/* proteus-2309.h - Keytable for proteus_2309 Remote Controller
+ *
+ * keymap imported from ir-keymaps.c
+ *
+ * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
+
+/* Michal Majchrowicz <mmajchrowicz@gmail.com> */
+
+static struct rc_map_table proteus_2309[] = {
+	/* numeric */
+	{ 0x00, KEY_0 },
+	{ 0x01, KEY_1 },
+	{ 0x02, KEY_2 },
+	{ 0x03, KEY_3 },
+	{ 0x04, KEY_4 },
+	{ 0x05, KEY_5 },
+	{ 0x06, KEY_6 },
+	{ 0x07, KEY_7 },
+	{ 0x08, KEY_8 },
+	{ 0x09, KEY_9 },
+
+	{ 0x5c, KEY_POWER },		/* power       */
+	{ 0x20, KEY_ZOOM },		/* full screen */
+	{ 0x0f, KEY_BACKSPACE },	/* recall      */
+	{ 0x1b, KEY_ENTER },		/* mute        */
+	{ 0x41, KEY_RECORD },		/* record      */
+	{ 0x43, KEY_STOP },		/* stop        */
+	{ 0x16, KEY_S },
+	{ 0x1a, KEY_POWER2 },		/* off         */
+	{ 0x2e, KEY_RED },
+	{ 0x1f, KEY_CHANNELDOWN },	/* channel -   */
+	{ 0x1c, KEY_CHANNELUP },	/* channel +   */
+	{ 0x10, KEY_VOLUMEDOWN },	/* volume -    */
+	{ 0x1e, KEY_VOLUMEUP },		/* volume +    */
+	{ 0x14, KEY_F1 },
+};
+
+static struct rc_map_list proteus_2309_map = {
+	.map = {
+		.scan    = proteus_2309,
+		.size    = ARRAY_SIZE(proteus_2309),
+		.rc_type = RC_TYPE_UNKNOWN,	/* Legacy IR type */
+		.name    = RC_MAP_PROTEUS_2309,
+	}
+};
+
+static int __init init_rc_map_proteus_2309(void)
+{
+	return rc_map_register(&proteus_2309_map);
+}
+
+static void __exit exit_rc_map_proteus_2309(void)
+{
+	rc_map_unregister(&proteus_2309_map);
+}
+
+module_init(init_rc_map_proteus_2309)
+module_exit(exit_rc_map_proteus_2309)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-purpletv.c linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-purpletv.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-purpletv.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-purpletv.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,81 @@
+/* purpletv.h - Keytable for purpletv Remote Controller
+ *
+ * keymap imported from ir-keymaps.c
+ *
+ * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
+
+static struct rc_map_table purpletv[] = {
+	{ 0x03, KEY_POWER },
+	{ 0x6f, KEY_MUTE },
+	{ 0x10, KEY_BACKSPACE },	/* Recall */
+
+	{ 0x11, KEY_0 },
+	{ 0x04, KEY_1 },
+	{ 0x05, KEY_2 },
+	{ 0x06, KEY_3 },
+	{ 0x08, KEY_4 },
+	{ 0x09, KEY_5 },
+	{ 0x0a, KEY_6 },
+	{ 0x0c, KEY_7 },
+	{ 0x0d, KEY_8 },
+	{ 0x0e, KEY_9 },
+	{ 0x12, KEY_DOT },	/* 100+ */
+
+	{ 0x07, KEY_VOLUMEUP },
+	{ 0x0b, KEY_VOLUMEDOWN },
+	{ 0x1a, KEY_KPPLUS },
+	{ 0x18, KEY_KPMINUS },
+	{ 0x15, KEY_UP },
+	{ 0x1d, KEY_DOWN },
+	{ 0x0f, KEY_CHANNELUP },
+	{ 0x13, KEY_CHANNELDOWN },
+	{ 0x48, KEY_ZOOM },
+
+	{ 0x1b, KEY_VIDEO },	/* Video source */
+	{ 0x1f, KEY_CAMERA },	/* Snapshot */
+	{ 0x49, KEY_LANGUAGE },	/* MTS Select */
+	{ 0x19, KEY_SEARCH },	/* Auto Scan */
+
+	{ 0x4b, KEY_RECORD },
+	{ 0x46, KEY_PLAY },
+	{ 0x45, KEY_PAUSE },	/* Pause */
+	{ 0x44, KEY_STOP },
+	{ 0x43, KEY_TIME },	/* Time Shift */
+	{ 0x17, KEY_CHANNEL },	/* SURF CH */
+	{ 0x40, KEY_FORWARD },	/* Forward ? */
+	{ 0x42, KEY_REWIND },	/* Backward ? */
+
+};
+
+static struct rc_map_list purpletv_map = {
+	.map = {
+		.scan    = purpletv,
+		.size    = ARRAY_SIZE(purpletv),
+		.rc_type = RC_TYPE_UNKNOWN,	/* Legacy IR type */
+		.name    = RC_MAP_PURPLETV,
+	}
+};
+
+static int __init init_rc_map_purpletv(void)
+{
+	return rc_map_register(&purpletv_map);
+}
+
+static void __exit exit_rc_map_purpletv(void)
+{
+	rc_map_unregister(&purpletv_map);
+}
+
+module_init(init_rc_map_purpletv)
+module_exit(exit_rc_map_purpletv)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-pv951.c linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-pv951.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-pv951.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-pv951.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,78 @@
+/* pv951.h - Keytable for pv951 Remote Controller
+ *
+ * keymap imported from ir-keymaps.c
+ *
+ * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
+
+/* Mark Phalan <phalanm@o2.ie> */
+
+static struct rc_map_table pv951[] = {
+	{ 0x00, KEY_0 },
+	{ 0x01, KEY_1 },
+	{ 0x02, KEY_2 },
+	{ 0x03, KEY_3 },
+	{ 0x04, KEY_4 },
+	{ 0x05, KEY_5 },
+	{ 0x06, KEY_6 },
+	{ 0x07, KEY_7 },
+	{ 0x08, KEY_8 },
+	{ 0x09, KEY_9 },
+
+	{ 0x12, KEY_POWER },
+	{ 0x10, KEY_MUTE },
+	{ 0x1f, KEY_VOLUMEDOWN },
+	{ 0x1b, KEY_VOLUMEUP },
+	{ 0x1a, KEY_CHANNELUP },
+	{ 0x1e, KEY_CHANNELDOWN },
+	{ 0x0e, KEY_PAGEUP },
+	{ 0x1d, KEY_PAGEDOWN },
+	{ 0x13, KEY_SOUND },
+
+	{ 0x18, KEY_KPPLUSMINUS },	/* CH +/- */
+	{ 0x16, KEY_SUBTITLE },		/* CC */
+	{ 0x0d, KEY_TEXT },		/* TTX */
+	{ 0x0b, KEY_TV },		/* AIR/CBL */
+	{ 0x11, KEY_PC },		/* PC/TV */
+	{ 0x17, KEY_OK },		/* CH RTN */
+	{ 0x19, KEY_MODE },		/* FUNC */
+	{ 0x0c, KEY_SEARCH },		/* AUTOSCAN */
+
+	/* Not sure what to do with these ones! */
+	{ 0x0f, KEY_SELECT },		/* SOURCE */
+	{ 0x0a, KEY_KPPLUS },		/* +100 */
+	{ 0x14, KEY_EQUAL },		/* SYNC */
+	{ 0x1c, KEY_MEDIA },		/* PC/TV */
+};
+
+static struct rc_map_list pv951_map = {
+	.map = {
+		.scan    = pv951,
+		.size    = ARRAY_SIZE(pv951),
+		.rc_type = RC_TYPE_UNKNOWN,	/* Legacy IR type */
+		.name    = RC_MAP_PV951,
+	}
+};
+
+static int __init init_rc_map_pv951(void)
+{
+	return rc_map_register(&pv951_map);
+}
+
+static void __exit exit_rc_map_pv951(void)
+{
+	rc_map_unregister(&pv951_map);
+}
+
+module_init(init_rc_map_pv951)
+module_exit(exit_rc_map_pv951)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-rc5-hauppauge-new.c linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-rc5-hauppauge-new.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-rc5-hauppauge-new.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-rc5-hauppauge-new.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,141 @@
+/* rc5-hauppauge-new.h - Keytable for rc5_hauppauge_new Remote Controller
+ *
+ * keymap imported from ir-keymaps.c
+ *
+ * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
+
+/*
+ * Hauppauge:the newer, gray remotes (seems there are multiple
+ * slightly different versions), shipped with cx88+ivtv cards.
+ *
+ * This table contains the complete RC5 code, instead of just the data part
+ */
+
+static struct rc_map_table rc5_hauppauge_new[] = {
+	/* Keys 0 to 9 */
+	{ 0x1e00, KEY_0 },
+	{ 0x1e01, KEY_1 },
+	{ 0x1e02, KEY_2 },
+	{ 0x1e03, KEY_3 },
+	{ 0x1e04, KEY_4 },
+	{ 0x1e05, KEY_5 },
+	{ 0x1e06, KEY_6 },
+	{ 0x1e07, KEY_7 },
+	{ 0x1e08, KEY_8 },
+	{ 0x1e09, KEY_9 },
+
+	{ 0x1e0a, KEY_TEXT },		/* keypad asterisk as well */
+	{ 0x1e0b, KEY_RED },		/* red button */
+	{ 0x1e0c, KEY_RADIO },
+	{ 0x1e0d, KEY_MENU },
+	{ 0x1e0e, KEY_SUBTITLE },		/* also the # key */
+	{ 0x1e0f, KEY_MUTE },
+	{ 0x1e10, KEY_VOLUMEUP },
+	{ 0x1e11, KEY_VOLUMEDOWN },
+	{ 0x1e12, KEY_PREVIOUS },		/* previous channel */
+	{ 0x1e14, KEY_UP },
+	{ 0x1e15, KEY_DOWN },
+	{ 0x1e16, KEY_LEFT },
+	{ 0x1e17, KEY_RIGHT },
+	{ 0x1e18, KEY_VIDEO },		/* Videos */
+	{ 0x1e19, KEY_AUDIO },		/* Music */
+	/* 0x1e1a: Pictures - presume this means
+	   "Multimedia Home Platform" -
+	   no "PICTURES" key in input.h
+	 */
+	{ 0x1e1a, KEY_MHP },
+
+	{ 0x1e1b, KEY_EPG },		/* Guide */
+	{ 0x1e1c, KEY_TV },
+	{ 0x1e1e, KEY_NEXTSONG },		/* skip >| */
+	{ 0x1e1f, KEY_EXIT },		/* back/exit */
+	{ 0x1e20, KEY_CHANNELUP },	/* channel / program + */
+	{ 0x1e21, KEY_CHANNELDOWN },	/* channel / program - */
+	{ 0x1e22, KEY_CHANNEL },		/* source (old black remote) */
+	{ 0x1e24, KEY_PREVIOUSSONG },	/* replay |< */
+	{ 0x1e25, KEY_ENTER },		/* OK */
+	{ 0x1e26, KEY_SLEEP },		/* minimize (old black remote) */
+	{ 0x1e29, KEY_BLUE },		/* blue key */
+	{ 0x1e2e, KEY_GREEN },		/* green button */
+	{ 0x1e30, KEY_PAUSE },		/* pause */
+	{ 0x1e32, KEY_REWIND },		/* backward << */
+	{ 0x1e34, KEY_FASTFORWARD },	/* forward >> */
+	{ 0x1e35, KEY_PLAY },
+	{ 0x1e36, KEY_STOP },
+	{ 0x1e37, KEY_RECORD },		/* recording */
+	{ 0x1e38, KEY_YELLOW },		/* yellow key */
+	{ 0x1e3b, KEY_SELECT },		/* top right button */
+	{ 0x1e3c, KEY_ZOOM },		/* full */
+	{ 0x1e3d, KEY_POWER },		/* system power (green button) */
+
+	/* Keycodes for DSR-0112 remote bundled with Haupauge MiniStick */
+	{ 0x1d00, KEY_0 },
+	{ 0x1d01, KEY_1 },
+	{ 0x1d02, KEY_2 },
+	{ 0x1d03, KEY_3 },
+	{ 0x1d04, KEY_4 },
+	{ 0x1d05, KEY_5 },
+	{ 0x1d06, KEY_6 },
+	{ 0x1d07, KEY_7 },
+	{ 0x1d08, KEY_8 },
+	{ 0x1d09, KEY_9 },
+	{ 0x1d0a, KEY_TEXT },
+	{ 0x1d0d, KEY_MENU },
+	{ 0x1d0f, KEY_MUTE },
+	{ 0x1d10, KEY_VOLUMEUP },
+	{ 0x1d11, KEY_VOLUMEDOWN },
+	{ 0x1d12, KEY_PREVIOUS },        /* Prev.Ch .. ??? */
+	{ 0x1d14, KEY_UP },
+	{ 0x1d15, KEY_DOWN },
+	{ 0x1d16, KEY_LEFT },
+	{ 0x1d17, KEY_RIGHT },
+	{ 0x1d1c, KEY_TV },
+	{ 0x1d1e, KEY_NEXT },           /* >|             */
+	{ 0x1d1f, KEY_EXIT },
+	{ 0x1d20, KEY_CHANNELUP },
+	{ 0x1d21, KEY_CHANNELDOWN },
+	{ 0x1d24, KEY_LAST },           /* <|             */
+	{ 0x1d25, KEY_OK },
+	{ 0x1d30, KEY_PAUSE },
+	{ 0x1d32, KEY_REWIND },
+	{ 0x1d34, KEY_FASTFORWARD },
+	{ 0x1d35, KEY_PLAY },
+	{ 0x1d36, KEY_STOP },
+	{ 0x1d37, KEY_RECORD },
+	{ 0x1d3b, KEY_GOTO },
+	{ 0x1d3d, KEY_POWER },
+	{ 0x1d3f, KEY_HOME },
+};
+
+static struct rc_map_list rc5_hauppauge_new_map = {
+	.map = {
+		.scan    = rc5_hauppauge_new,
+		.size    = ARRAY_SIZE(rc5_hauppauge_new),
+		.rc_type = RC_TYPE_RC5,
+		.name    = RC_MAP_RC5_HAUPPAUGE_NEW,
+	}
+};
+
+static int __init init_rc_map_rc5_hauppauge_new(void)
+{
+	return rc_map_register(&rc5_hauppauge_new_map);
+}
+
+static void __exit exit_rc_map_rc5_hauppauge_new(void)
+{
+	rc_map_unregister(&rc5_hauppauge_new_map);
+}
+
+module_init(init_rc_map_rc5_hauppauge_new)
+module_exit(exit_rc_map_rc5_hauppauge_new)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-rc5-tv.c linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-rc5-tv.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-rc5-tv.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-rc5-tv.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,81 @@
+/* rc5-tv.h - Keytable for rc5_tv Remote Controller
+ *
+ * keymap imported from ir-keymaps.c
+ *
+ * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
+
+/* generic RC5 keytable                                          */
+/* see http://users.pandora.be/nenya/electronics/rc5/codes00.htm */
+/* used by old (black) Hauppauge remotes                         */
+
+static struct rc_map_table rc5_tv[] = {
+	/* Keys 0 to 9 */
+	{ 0x00, KEY_0 },
+	{ 0x01, KEY_1 },
+	{ 0x02, KEY_2 },
+	{ 0x03, KEY_3 },
+	{ 0x04, KEY_4 },
+	{ 0x05, KEY_5 },
+	{ 0x06, KEY_6 },
+	{ 0x07, KEY_7 },
+	{ 0x08, KEY_8 },
+	{ 0x09, KEY_9 },
+
+	{ 0x0b, KEY_CHANNEL },		/* channel / program (japan: 11) */
+	{ 0x0c, KEY_POWER },		/* standby */
+	{ 0x0d, KEY_MUTE },		/* mute / demute */
+	{ 0x0f, KEY_TV },		/* display */
+	{ 0x10, KEY_VOLUMEUP },
+	{ 0x11, KEY_VOLUMEDOWN },
+	{ 0x12, KEY_BRIGHTNESSUP },
+	{ 0x13, KEY_BRIGHTNESSDOWN },
+	{ 0x1e, KEY_SEARCH },		/* search + */
+	{ 0x20, KEY_CHANNELUP },	/* channel / program + */
+	{ 0x21, KEY_CHANNELDOWN },	/* channel / program - */
+	{ 0x22, KEY_CHANNEL },		/* alt / channel */
+	{ 0x23, KEY_LANGUAGE },		/* 1st / 2nd language */
+	{ 0x26, KEY_SLEEP },		/* sleeptimer */
+	{ 0x2e, KEY_MENU },		/* 2nd controls (USA: menu) */
+	{ 0x30, KEY_PAUSE },
+	{ 0x32, KEY_REWIND },
+	{ 0x33, KEY_GOTO },
+	{ 0x35, KEY_PLAY },
+	{ 0x36, KEY_STOP },
+	{ 0x37, KEY_RECORD },		/* recording */
+	{ 0x3c, KEY_TEXT },		/* teletext submode (Japan: 12) */
+	{ 0x3d, KEY_SUSPEND },		/* system standby */
+
+};
+
+static struct rc_map_list rc5_tv_map = {
+	.map = {
+		.scan    = rc5_tv,
+		.size    = ARRAY_SIZE(rc5_tv),
+		.rc_type = RC_TYPE_UNKNOWN,	/* Legacy IR type */
+		.name    = RC_MAP_RC5_TV,
+	}
+};
+
+static int __init init_rc_map_rc5_tv(void)
+{
+	return rc_map_register(&rc5_tv_map);
+}
+
+static void __exit exit_rc_map_rc5_tv(void)
+{
+	rc_map_unregister(&rc5_tv_map);
+}
+
+module_init(init_rc_map_rc5_tv)
+module_exit(exit_rc_map_rc5_tv)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-rc6-mce.c linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-rc6-mce.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-rc6-mce.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-rc6-mce.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,119 @@
+/* rc-rc6-mce.c - Keytable for Windows Media Center RC-6 remotes for use
+ * with the Media Center Edition eHome Infrared Transceiver.
+ *
+ * Copyright (c) 2010 by Jarod Wilson <jarod@redhat.com>
+ *
+ * See http://mediacenterguides.com/book/export/html/31 for details on
+ * key mappings.
+ *
+ * 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 <media/rc-map.h>
+
+static struct rc_map_table rc6_mce[] = {
+
+	{ 0x800f0400, KEY_NUMERIC_0 },
+	{ 0x800f0401, KEY_NUMERIC_1 },
+	{ 0x800f0402, KEY_NUMERIC_2 },
+	{ 0x800f0403, KEY_NUMERIC_3 },
+	{ 0x800f0404, KEY_NUMERIC_4 },
+	{ 0x800f0405, KEY_NUMERIC_5 },
+	{ 0x800f0406, KEY_NUMERIC_6 },
+	{ 0x800f0407, KEY_NUMERIC_7 },
+	{ 0x800f0408, KEY_NUMERIC_8 },
+	{ 0x800f0409, KEY_NUMERIC_9 },
+
+	{ 0x800f040a, KEY_DELETE },
+	{ 0x800f040b, KEY_ENTER },
+	{ 0x800f040c, KEY_POWER },		/* PC Power */
+	{ 0x800f040d, KEY_PROG1 },		/* Windows MCE button */
+	{ 0x800f040e, KEY_MUTE },
+	{ 0x800f040f, KEY_INFO },
+
+	{ 0x800f0410, KEY_VOLUMEUP },
+	{ 0x800f0411, KEY_VOLUMEDOWN },
+	{ 0x800f0412, KEY_CHANNELUP },
+	{ 0x800f0413, KEY_CHANNELDOWN },
+
+	{ 0x800f0414, KEY_FASTFORWARD },
+	{ 0x800f0415, KEY_REWIND },
+	{ 0x800f0416, KEY_PLAY },
+	{ 0x800f0417, KEY_RECORD },
+	{ 0x800f0418, KEY_PAUSE },
+	{ 0x800f046e, KEY_PLAYPAUSE },
+	{ 0x800f0419, KEY_STOP },
+	{ 0x800f041a, KEY_NEXT },
+	{ 0x800f041b, KEY_PREVIOUS },
+	{ 0x800f041c, KEY_NUMERIC_POUND },
+	{ 0x800f041d, KEY_NUMERIC_STAR },
+
+	{ 0x800f041e, KEY_UP },
+	{ 0x800f041f, KEY_DOWN },
+	{ 0x800f0420, KEY_LEFT },
+	{ 0x800f0421, KEY_RIGHT },
+
+	{ 0x800f0422, KEY_OK },
+	{ 0x800f0423, KEY_EXIT },
+	{ 0x800f0424, KEY_DVD },
+	{ 0x800f0425, KEY_TUNER },		/* LiveTV */
+	{ 0x800f0426, KEY_EPG },		/* Guide */
+	{ 0x800f0427, KEY_ZOOM },		/* Aspect */
+
+	{ 0x800f0432, KEY_MODE },		/* Visualization */
+	{ 0x800f0433, KEY_PRESENTATION },	/* Slide Show */
+	{ 0x800f0434, KEY_EJECTCD },
+	{ 0x800f043a, KEY_BRIGHTNESSUP },
+
+	{ 0x800f0446, KEY_TV },
+	{ 0x800f0447, KEY_AUDIO },		/* My Music */
+	{ 0x800f0448, KEY_PVR },		/* RecordedTV */
+	{ 0x800f0449, KEY_CAMERA },
+	{ 0x800f044a, KEY_VIDEO },
+	{ 0x800f044c, KEY_LANGUAGE },
+	{ 0x800f044d, KEY_TITLE },
+	{ 0x800f044e, KEY_PRINT },	/* Print - HP OEM version of remote */
+
+	{ 0x800f0450, KEY_RADIO },
+
+	{ 0x800f045a, KEY_SUBTITLE },		/* Caption/Teletext */
+	{ 0x800f045b, KEY_RED },
+	{ 0x800f045c, KEY_GREEN },
+	{ 0x800f045d, KEY_YELLOW },
+	{ 0x800f045e, KEY_BLUE },
+
+	{ 0x800f0465, KEY_POWER2 },	/* TV Power */
+	{ 0x800f046e, KEY_PLAYPAUSE },
+	{ 0x800f046f, KEY_MEDIA },	/* Start media application (NEW) */
+
+	{ 0x800f0480, KEY_BRIGHTNESSDOWN },
+	{ 0x800f0481, KEY_PLAYPAUSE },
+};
+
+static struct rc_map_list rc6_mce_map = {
+	.map = {
+		.scan    = rc6_mce,
+		.size    = ARRAY_SIZE(rc6_mce),
+		.rc_type = RC_TYPE_RC6,
+		.name    = RC_MAP_RC6_MCE,
+	}
+};
+
+static int __init init_rc_map_rc6_mce(void)
+{
+	return rc_map_register(&rc6_mce_map);
+}
+
+static void __exit exit_rc_map_rc6_mce(void)
+{
+	rc_map_unregister(&rc6_mce_map);
+}
+
+module_init(init_rc_map_rc6_mce)
+module_exit(exit_rc_map_rc6_mce)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Jarod Wilson <jarod@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-real-audio-220-32-keys.c linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-real-audio-220-32-keys.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-real-audio-220-32-keys.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-real-audio-220-32-keys.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,78 @@
+/* real-audio-220-32-keys.h - Keytable for real_audio_220_32_keys Remote Controller
+ *
+ * keymap imported from ir-keymaps.c
+ *
+ * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
+
+/* Zogis Real Audio 220 - 32 keys IR */
+
+static struct rc_map_table real_audio_220_32_keys[] = {
+	{ 0x1c, KEY_RADIO},
+	{ 0x12, KEY_POWER2},
+
+	{ 0x01, KEY_1},
+	{ 0x02, KEY_2},
+	{ 0x03, KEY_3},
+	{ 0x04, KEY_4},
+	{ 0x05, KEY_5},
+	{ 0x06, KEY_6},
+	{ 0x07, KEY_7},
+	{ 0x08, KEY_8},
+	{ 0x09, KEY_9},
+	{ 0x00, KEY_0},
+
+	{ 0x0c, KEY_VOLUMEUP},
+	{ 0x18, KEY_VOLUMEDOWN},
+	{ 0x0b, KEY_CHANNELUP},
+	{ 0x15, KEY_CHANNELDOWN},
+	{ 0x16, KEY_ENTER},
+
+	{ 0x11, KEY_LIST},		/* Source */
+	{ 0x0d, KEY_AUDIO},		/* stereo */
+
+	{ 0x0f, KEY_PREVIOUS},		/* Prev */
+	{ 0x1b, KEY_TIME},		/* Timeshift */
+	{ 0x1a, KEY_NEXT},		/* Next */
+
+	{ 0x0e, KEY_STOP},
+	{ 0x1f, KEY_PLAY},
+	{ 0x1e, KEY_PLAYPAUSE},		/* Pause */
+
+	{ 0x1d, KEY_RECORD},
+	{ 0x13, KEY_MUTE},
+	{ 0x19, KEY_CAMERA},		/* Snapshot */
+
+};
+
+static struct rc_map_list real_audio_220_32_keys_map = {
+	.map = {
+		.scan    = real_audio_220_32_keys,
+		.size    = ARRAY_SIZE(real_audio_220_32_keys),
+		.rc_type = RC_TYPE_UNKNOWN,	/* Legacy IR type */
+		.name    = RC_MAP_REAL_AUDIO_220_32_KEYS,
+	}
+};
+
+static int __init init_rc_map_real_audio_220_32_keys(void)
+{
+	return rc_map_register(&real_audio_220_32_keys_map);
+}
+
+static void __exit exit_rc_map_real_audio_220_32_keys(void)
+{
+	rc_map_unregister(&real_audio_220_32_keys_map);
+}
+
+module_init(init_rc_map_real_audio_220_32_keys)
+module_exit(exit_rc_map_real_audio_220_32_keys)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-streamzap.c linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-streamzap.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-streamzap.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-streamzap.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,82 @@
+/* rc-streamzap.c - Keytable for Streamzap PC Remote, for use
+ * with the Streamzap PC Remote IR Receiver.
+ *
+ * Copyright (c) 2010 by Jarod Wilson <jarod@redhat.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 <media/rc-map.h>
+
+static struct rc_map_table streamzap[] = {
+/*
+ * The Streamzap remote is almost, but not quite, RC-5, as it has an extra
+ * bit in it, which throws the in-kernel RC-5 decoder for a loop. Currently,
+ * an additional RC-5-sz decoder is being deployed to support it, but it
+ * may be possible to merge it back with the standard RC-5 decoder.
+ */
+	{ 0x28c0, KEY_NUMERIC_0 },
+	{ 0x28c1, KEY_NUMERIC_1 },
+	{ 0x28c2, KEY_NUMERIC_2 },
+	{ 0x28c3, KEY_NUMERIC_3 },
+	{ 0x28c4, KEY_NUMERIC_4 },
+	{ 0x28c5, KEY_NUMERIC_5 },
+	{ 0x28c6, KEY_NUMERIC_6 },
+	{ 0x28c7, KEY_NUMERIC_7 },
+	{ 0x28c8, KEY_NUMERIC_8 },
+	{ 0x28c9, KEY_NUMERIC_9 },
+	{ 0x28ca, KEY_POWER },
+	{ 0x28cb, KEY_MUTE },
+	{ 0x28cc, KEY_CHANNELUP },
+	{ 0x28cd, KEY_VOLUMEUP },
+	{ 0x28ce, KEY_CHANNELDOWN },
+	{ 0x28cf, KEY_VOLUMEDOWN },
+	{ 0x28d0, KEY_UP },
+	{ 0x28d1, KEY_LEFT },
+	{ 0x28d2, KEY_OK },
+	{ 0x28d3, KEY_RIGHT },
+	{ 0x28d4, KEY_DOWN },
+	{ 0x28d5, KEY_MENU },
+	{ 0x28d6, KEY_EXIT },
+	{ 0x28d7, KEY_PLAY },
+	{ 0x28d8, KEY_PAUSE },
+	{ 0x28d9, KEY_STOP },
+	{ 0x28da, KEY_BACK },
+	{ 0x28db, KEY_FORWARD },
+	{ 0x28dc, KEY_RECORD },
+	{ 0x28dd, KEY_REWIND },
+	{ 0x28de, KEY_FASTFORWARD },
+	{ 0x28e0, KEY_RED },
+	{ 0x28e1, KEY_GREEN },
+	{ 0x28e2, KEY_YELLOW },
+	{ 0x28e3, KEY_BLUE },
+
+};
+
+static struct rc_map_list streamzap_map = {
+	.map = {
+		.scan    = streamzap,
+		.size    = ARRAY_SIZE(streamzap),
+		.rc_type = RC_TYPE_RC5_SZ,
+		.name    = RC_MAP_STREAMZAP,
+	}
+};
+
+static int __init init_rc_map_streamzap(void)
+{
+	return rc_map_register(&streamzap_map);
+}
+
+static void __exit exit_rc_map_streamzap(void)
+{
+	rc_map_unregister(&streamzap_map);
+}
+
+module_init(init_rc_map_streamzap)
+module_exit(exit_rc_map_streamzap)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Jarod Wilson <jarod@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-tbs-nec.c linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-tbs-nec.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-tbs-nec.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-tbs-nec.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,75 @@
+/* tbs-nec.h - Keytable for tbs_nec Remote Controller
+ *
+ * keymap imported from ir-keymaps.c
+ *
+ * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
+
+static struct rc_map_table tbs_nec[] = {
+	{ 0x84, KEY_POWER2},		/* power */
+	{ 0x94, KEY_MUTE},		/* mute */
+	{ 0x87, KEY_1},
+	{ 0x86, KEY_2},
+	{ 0x85, KEY_3},
+	{ 0x8b, KEY_4},
+	{ 0x8a, KEY_5},
+	{ 0x89, KEY_6},
+	{ 0x8f, KEY_7},
+	{ 0x8e, KEY_8},
+	{ 0x8d, KEY_9},
+	{ 0x92, KEY_0},
+	{ 0xc0, KEY_10CHANNELSUP},	/* 10+ */
+	{ 0xd0, KEY_10CHANNELSDOWN},	/* 10- */
+	{ 0x96, KEY_CHANNELUP},		/* ch+ */
+	{ 0x91, KEY_CHANNELDOWN},	/* ch- */
+	{ 0x93, KEY_VOLUMEUP},		/* vol+ */
+	{ 0x8c, KEY_VOLUMEDOWN},	/* vol- */
+	{ 0x83, KEY_RECORD},		/* rec */
+	{ 0x98, KEY_PAUSE},		/* pause, yellow */
+	{ 0x99, KEY_OK},		/* ok */
+	{ 0x9a, KEY_CAMERA},		/* snapshot */
+	{ 0x81, KEY_UP},
+	{ 0x90, KEY_LEFT},
+	{ 0x82, KEY_RIGHT},
+	{ 0x88, KEY_DOWN},
+	{ 0x95, KEY_FAVORITES},		/* blue */
+	{ 0x97, KEY_SUBTITLE},		/* green */
+	{ 0x9d, KEY_ZOOM},
+	{ 0x9f, KEY_EXIT},
+	{ 0x9e, KEY_MENU},
+	{ 0x9c, KEY_EPG},
+	{ 0x80, KEY_PREVIOUS},		/* red */
+	{ 0x9b, KEY_MODE},
+};
+
+static struct rc_map_list tbs_nec_map = {
+	.map = {
+		.scan    = tbs_nec,
+		.size    = ARRAY_SIZE(tbs_nec),
+		.rc_type = RC_TYPE_UNKNOWN,	/* Legacy IR type */
+		.name    = RC_MAP_TBS_NEC,
+	}
+};
+
+static int __init init_rc_map_tbs_nec(void)
+{
+	return rc_map_register(&tbs_nec_map);
+}
+
+static void __exit exit_rc_map_tbs_nec(void)
+{
+	rc_map_unregister(&tbs_nec_map);
+}
+
+module_init(init_rc_map_tbs_nec)
+module_exit(exit_rc_map_tbs_nec)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-terratec-cinergy-xs.c linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-terratec-cinergy-xs.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-terratec-cinergy-xs.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-terratec-cinergy-xs.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,92 @@
+/* terratec-cinergy-xs.h - Keytable for terratec_cinergy_xs Remote Controller
+ *
+ * keymap imported from ir-keymaps.c
+ *
+ * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
+
+/* Terratec Cinergy Hybrid T USB XS
+   Devin Heitmueller <dheitmueller@linuxtv.org>
+ */
+
+static struct rc_map_table terratec_cinergy_xs[] = {
+	{ 0x41, KEY_HOME},
+	{ 0x01, KEY_POWER},
+	{ 0x42, KEY_MENU},
+	{ 0x02, KEY_1},
+	{ 0x03, KEY_2},
+	{ 0x04, KEY_3},
+	{ 0x43, KEY_SUBTITLE},
+	{ 0x05, KEY_4},
+	{ 0x06, KEY_5},
+	{ 0x07, KEY_6},
+	{ 0x44, KEY_TEXT},
+	{ 0x08, KEY_7},
+	{ 0x09, KEY_8},
+	{ 0x0a, KEY_9},
+	{ 0x45, KEY_DELETE},
+	{ 0x0b, KEY_TUNER},
+	{ 0x0c, KEY_0},
+	{ 0x0d, KEY_MODE},
+	{ 0x46, KEY_TV},
+	{ 0x47, KEY_DVD},
+	{ 0x49, KEY_VIDEO},
+	{ 0x4b, KEY_AUX},
+	{ 0x10, KEY_UP},
+	{ 0x11, KEY_LEFT},
+	{ 0x12, KEY_OK},
+	{ 0x13, KEY_RIGHT},
+	{ 0x14, KEY_DOWN},
+	{ 0x0f, KEY_EPG},
+	{ 0x16, KEY_INFO},
+	{ 0x4d, KEY_BACKSPACE},
+	{ 0x1c, KEY_VOLUMEUP},
+	{ 0x4c, KEY_PLAY},
+	{ 0x1b, KEY_CHANNELUP},
+	{ 0x1e, KEY_VOLUMEDOWN},
+	{ 0x1d, KEY_MUTE},
+	{ 0x1f, KEY_CHANNELDOWN},
+	{ 0x17, KEY_RED},
+	{ 0x18, KEY_GREEN},
+	{ 0x19, KEY_YELLOW},
+	{ 0x1a, KEY_BLUE},
+	{ 0x58, KEY_RECORD},
+	{ 0x48, KEY_STOP},
+	{ 0x40, KEY_PAUSE},
+	{ 0x54, KEY_LAST},
+	{ 0x4e, KEY_REWIND},
+	{ 0x4f, KEY_FASTFORWARD},
+	{ 0x5c, KEY_NEXT},
+};
+
+static struct rc_map_list terratec_cinergy_xs_map = {
+	.map = {
+		.scan    = terratec_cinergy_xs,
+		.size    = ARRAY_SIZE(terratec_cinergy_xs),
+		.rc_type = RC_TYPE_UNKNOWN,	/* Legacy IR type */
+		.name    = RC_MAP_TERRATEC_CINERGY_XS,
+	}
+};
+
+static int __init init_rc_map_terratec_cinergy_xs(void)
+{
+	return rc_map_register(&terratec_cinergy_xs_map);
+}
+
+static void __exit exit_rc_map_terratec_cinergy_xs(void)
+{
+	rc_map_unregister(&terratec_cinergy_xs_map);
+}
+
+module_init(init_rc_map_terratec_cinergy_xs)
+module_exit(exit_rc_map_terratec_cinergy_xs)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-terratec-slim.c linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-terratec-slim.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-terratec-slim.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-terratec-slim.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,79 @@
+/*
+ * TerraTec remote controller keytable
+ *
+ * Copyright (C) 2010 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 <media/rc-map.h>
+
+/* TerraTec slim remote, 7 rows, 4 columns. */
+/* Uses NEC extended 0x02bd. */
+static struct rc_map_table terratec_slim[] = {
+	{ 0x02bd00, KEY_1 },
+	{ 0x02bd01, KEY_2 },
+	{ 0x02bd02, KEY_3 },
+	{ 0x02bd03, KEY_4 },
+	{ 0x02bd04, KEY_5 },
+	{ 0x02bd05, KEY_6 },
+	{ 0x02bd06, KEY_7 },
+	{ 0x02bd07, KEY_8 },
+	{ 0x02bd08, KEY_9 },
+	{ 0x02bd09, KEY_0 },
+	{ 0x02bd0a, KEY_MUTE },
+	{ 0x02bd0b, KEY_NEW },             /* symbol: PIP */
+	{ 0x02bd0e, KEY_VOLUMEDOWN },
+	{ 0x02bd0f, KEY_PLAYPAUSE },
+	{ 0x02bd10, KEY_RIGHT },
+	{ 0x02bd11, KEY_LEFT },
+	{ 0x02bd12, KEY_UP },
+	{ 0x02bd13, KEY_DOWN },
+	{ 0x02bd15, KEY_OK },
+	{ 0x02bd16, KEY_STOP },
+	{ 0x02bd17, KEY_CAMERA },          /* snapshot */
+	{ 0x02bd18, KEY_CHANNELUP },
+	{ 0x02bd19, KEY_RECORD },
+	{ 0x02bd1a, KEY_CHANNELDOWN },
+	{ 0x02bd1c, KEY_ESC },
+	{ 0x02bd1f, KEY_VOLUMEUP },
+	{ 0x02bd44, KEY_EPG },
+	{ 0x02bd45, KEY_POWER2 },          /* [red power button] */
+};
+
+static struct rc_map_list terratec_slim_map = {
+	.map = {
+		.scan    = terratec_slim,
+		.size    = ARRAY_SIZE(terratec_slim),
+		.rc_type = RC_TYPE_NEC,
+		.name    = RC_MAP_TERRATEC_SLIM,
+	}
+};
+
+static int __init init_rc_map_terratec_slim(void)
+{
+	return rc_map_register(&terratec_slim_map);
+}
+
+static void __exit exit_rc_map_terratec_slim(void)
+{
+	rc_map_unregister(&terratec_slim_map);
+}
+
+module_init(init_rc_map_terratec_slim)
+module_exit(exit_rc_map_terratec_slim)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-tevii-nec.c linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-tevii-nec.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-tevii-nec.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-tevii-nec.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,88 @@
+/* tevii-nec.h - Keytable for tevii_nec Remote Controller
+ *
+ * keymap imported from ir-keymaps.c
+ *
+ * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
+
+static struct rc_map_table tevii_nec[] = {
+	{ 0x0a, KEY_POWER2},
+	{ 0x0c, KEY_MUTE},
+	{ 0x11, KEY_1},
+	{ 0x12, KEY_2},
+	{ 0x13, KEY_3},
+	{ 0x14, KEY_4},
+	{ 0x15, KEY_5},
+	{ 0x16, KEY_6},
+	{ 0x17, KEY_7},
+	{ 0x18, KEY_8},
+	{ 0x19, KEY_9},
+	{ 0x10, KEY_0},
+	{ 0x1c, KEY_MENU},
+	{ 0x0f, KEY_VOLUMEDOWN},
+	{ 0x1a, KEY_LAST},
+	{ 0x0e, KEY_OPEN},
+	{ 0x04, KEY_RECORD},
+	{ 0x09, KEY_VOLUMEUP},
+	{ 0x08, KEY_CHANNELUP},
+	{ 0x07, KEY_PVR},
+	{ 0x0b, KEY_TIME},
+	{ 0x02, KEY_RIGHT},
+	{ 0x03, KEY_LEFT},
+	{ 0x00, KEY_UP},
+	{ 0x1f, KEY_OK},
+	{ 0x01, KEY_DOWN},
+	{ 0x05, KEY_TUNER},
+	{ 0x06, KEY_CHANNELDOWN},
+	{ 0x40, KEY_PLAYPAUSE},
+	{ 0x1e, KEY_REWIND},
+	{ 0x1b, KEY_FAVORITES},
+	{ 0x1d, KEY_BACK},
+	{ 0x4d, KEY_FASTFORWARD},
+	{ 0x44, KEY_EPG},
+	{ 0x4c, KEY_INFO},
+	{ 0x41, KEY_AB},
+	{ 0x43, KEY_AUDIO},
+	{ 0x45, KEY_SUBTITLE},
+	{ 0x4a, KEY_LIST},
+	{ 0x46, KEY_F1},
+	{ 0x47, KEY_F2},
+	{ 0x5e, KEY_F3},
+	{ 0x5c, KEY_F4},
+	{ 0x52, KEY_F5},
+	{ 0x5a, KEY_F6},
+	{ 0x56, KEY_MODE},
+	{ 0x58, KEY_SWITCHVIDEOMODE},
+};
+
+static struct rc_map_list tevii_nec_map = {
+	.map = {
+		.scan    = tevii_nec,
+		.size    = ARRAY_SIZE(tevii_nec),
+		.rc_type = RC_TYPE_UNKNOWN,	/* Legacy IR type */
+		.name    = RC_MAP_TEVII_NEC,
+	}
+};
+
+static int __init init_rc_map_tevii_nec(void)
+{
+	return rc_map_register(&tevii_nec_map);
+}
+
+static void __exit exit_rc_map_tevii_nec(void)
+{
+	rc_map_unregister(&tevii_nec_map);
+}
+
+module_init(init_rc_map_tevii_nec)
+module_exit(exit_rc_map_tevii_nec)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-total-media-in-hand.c linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-total-media-in-hand.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-total-media-in-hand.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-total-media-in-hand.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,85 @@
+/*
+ * Total Media In Hand remote controller keytable
+ *
+ * Copyright (C) 2010 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 <media/rc-map.h>
+
+/* Uses NEC extended 0x02bd */
+static struct rc_map_table total_media_in_hand[] = {
+	{ 0x02bd00, KEY_1 },
+	{ 0x02bd01, KEY_2 },
+	{ 0x02bd02, KEY_3 },
+	{ 0x02bd03, KEY_4 },
+	{ 0x02bd04, KEY_5 },
+	{ 0x02bd05, KEY_6 },
+	{ 0x02bd06, KEY_7 },
+	{ 0x02bd07, KEY_8 },
+	{ 0x02bd08, KEY_9 },
+	{ 0x02bd09, KEY_0 },
+	{ 0x02bd0a, KEY_MUTE },
+	{ 0x02bd0b, KEY_CYCLEWINDOWS },    /* yellow, [min / max] */
+	{ 0x02bd0c, KEY_VIDEO },           /* TV / AV */
+	{ 0x02bd0e, KEY_VOLUMEDOWN },
+	{ 0x02bd0f, KEY_TIME },            /* TimeShift */
+	{ 0x02bd10, KEY_RIGHT },           /* right arrow */
+	{ 0x02bd11, KEY_LEFT },            /* left arrow */
+	{ 0x02bd12, KEY_UP },              /* up arrow */
+	{ 0x02bd13, KEY_DOWN },            /* down arrow */
+	{ 0x02bd14, KEY_POWER2 },          /* [red] */
+	{ 0x02bd15, KEY_OK },              /* OK */
+	{ 0x02bd16, KEY_STOP },
+	{ 0x02bd17, KEY_CAMERA },          /* Snapshot */
+	{ 0x02bd18, KEY_CHANNELUP },
+	{ 0x02bd19, KEY_RECORD },
+	{ 0x02bd1a, KEY_CHANNELDOWN },
+	{ 0x02bd1c, KEY_ESC },             /* Esc */
+	{ 0x02bd1e, KEY_PLAY },
+	{ 0x02bd1f, KEY_VOLUMEUP },
+	{ 0x02bd40, KEY_PAUSE },
+	{ 0x02bd41, KEY_FASTFORWARD },     /* FF >> */
+	{ 0x02bd42, KEY_REWIND },          /* FR << */
+	{ 0x02bd43, KEY_ZOOM },            /* [window + mouse pointer] */
+	{ 0x02bd44, KEY_SHUFFLE },         /* Shuffle */
+	{ 0x02bd45, KEY_INFO },            /* [red (I)] */
+};
+
+static struct rc_map_list total_media_in_hand_map = {
+	.map = {
+		.scan    = total_media_in_hand,
+		.size    = ARRAY_SIZE(total_media_in_hand),
+		.rc_type = RC_TYPE_NEC,
+		.name    = RC_MAP_TOTAL_MEDIA_IN_HAND,
+	}
+};
+
+static int __init init_rc_map_total_media_in_hand(void)
+{
+	return rc_map_register(&total_media_in_hand_map);
+}
+
+static void __exit exit_rc_map_total_media_in_hand(void)
+{
+	rc_map_unregister(&total_media_in_hand_map);
+}
+
+module_init(init_rc_map_total_media_in_hand)
+module_exit(exit_rc_map_total_media_in_hand)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-trekstor.c linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-trekstor.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-trekstor.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-trekstor.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,80 @@
+/*
+ * TrekStor remote controller keytable
+ *
+ * Copyright (C) 2010 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 <media/rc-map.h>
+
+/* TrekStor DVB-T USB Stick remote controller. */
+/* Imported from af9015.h.
+   Initial keytable was from Marc Schneider <macke@macke.org> */
+static struct rc_map_table trekstor[] = {
+	{ 0x0084, KEY_0 },
+	{ 0x0085, KEY_MUTE },            /* Mute */
+	{ 0x0086, KEY_HOMEPAGE },        /* Home */
+	{ 0x0087, KEY_UP },              /* Up */
+	{ 0x0088, KEY_OK },              /* OK */
+	{ 0x0089, KEY_RIGHT },           /* Right */
+	{ 0x008a, KEY_FASTFORWARD },     /* Fast forward */
+	{ 0x008b, KEY_VOLUMEUP },        /* Volume + */
+	{ 0x008c, KEY_DOWN },            /* Down */
+	{ 0x008d, KEY_PLAY },            /* Play/Pause */
+	{ 0x008e, KEY_STOP },            /* Stop */
+	{ 0x008f, KEY_EPG },             /* Info/EPG */
+	{ 0x0090, KEY_7 },
+	{ 0x0091, KEY_4 },
+	{ 0x0092, KEY_1 },
+	{ 0x0093, KEY_CHANNELDOWN },     /* Channel - */
+	{ 0x0094, KEY_8 },
+	{ 0x0095, KEY_5 },
+	{ 0x0096, KEY_2 },
+	{ 0x0097, KEY_CHANNELUP },       /* Channel + */
+	{ 0x0098, KEY_9 },
+	{ 0x0099, KEY_6 },
+	{ 0x009a, KEY_3 },
+	{ 0x009b, KEY_VOLUMEDOWN },      /* Volume - */
+	{ 0x009c, KEY_TV },              /* TV */
+	{ 0x009d, KEY_RECORD },          /* Record */
+	{ 0x009e, KEY_REWIND },          /* Rewind */
+	{ 0x009f, KEY_LEFT },            /* Left */
+};
+
+static struct rc_map_list trekstor_map = {
+	.map = {
+		.scan    = trekstor,
+		.size    = ARRAY_SIZE(trekstor),
+		.rc_type = RC_TYPE_NEC,
+		.name    = RC_MAP_TREKSTOR,
+	}
+};
+
+static int __init init_rc_map_trekstor(void)
+{
+	return rc_map_register(&trekstor_map);
+}
+
+static void __exit exit_rc_map_trekstor(void)
+{
+	rc_map_unregister(&trekstor_map);
+}
+
+module_init(init_rc_map_trekstor)
+module_exit(exit_rc_map_trekstor)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-tt-1500.c linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-tt-1500.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-tt-1500.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-tt-1500.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,82 @@
+/* tt-1500.h - Keytable for tt_1500 Remote Controller
+ *
+ * keymap imported from ir-keymaps.c
+ *
+ * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
+
+/* for the Technotrend 1500 bundled remotes (grey and black): */
+
+static struct rc_map_table tt_1500[] = {
+	{ 0x1501, KEY_POWER },
+	{ 0x1502, KEY_SHUFFLE },		/* ? double-arrow key */
+	{ 0x1503, KEY_1 },
+	{ 0x1504, KEY_2 },
+	{ 0x1505, KEY_3 },
+	{ 0x1506, KEY_4 },
+	{ 0x1507, KEY_5 },
+	{ 0x1508, KEY_6 },
+	{ 0x1509, KEY_7 },
+	{ 0x150a, KEY_8 },
+	{ 0x150b, KEY_9 },
+	{ 0x150c, KEY_0 },
+	{ 0x150d, KEY_UP },
+	{ 0x150e, KEY_LEFT },
+	{ 0x150f, KEY_OK },
+	{ 0x1510, KEY_RIGHT },
+	{ 0x1511, KEY_DOWN },
+	{ 0x1512, KEY_INFO },
+	{ 0x1513, KEY_EXIT },
+	{ 0x1514, KEY_RED },
+	{ 0x1515, KEY_GREEN },
+	{ 0x1516, KEY_YELLOW },
+	{ 0x1517, KEY_BLUE },
+	{ 0x1518, KEY_MUTE },
+	{ 0x1519, KEY_TEXT },
+	{ 0x151a, KEY_MODE },		/* ? TV/Radio */
+	{ 0x1521, KEY_OPTION },
+	{ 0x1522, KEY_EPG },
+	{ 0x1523, KEY_CHANNELUP },
+	{ 0x1524, KEY_CHANNELDOWN },
+	{ 0x1525, KEY_VOLUMEUP },
+	{ 0x1526, KEY_VOLUMEDOWN },
+	{ 0x1527, KEY_SETUP },
+	{ 0x153a, KEY_RECORD },		/* these keys are only in the black remote */
+	{ 0x153b, KEY_PLAY },
+	{ 0x153c, KEY_STOP },
+	{ 0x153d, KEY_REWIND },
+	{ 0x153e, KEY_PAUSE },
+	{ 0x153f, KEY_FORWARD },
+};
+
+static struct rc_map_list tt_1500_map = {
+	.map = {
+		.scan    = tt_1500,
+		.size    = ARRAY_SIZE(tt_1500),
+		.rc_type = RC_TYPE_UNKNOWN,	/* Legacy IR type */
+		.name    = RC_MAP_TT_1500,
+	}
+};
+
+static int __init init_rc_map_tt_1500(void)
+{
+	return rc_map_register(&tt_1500_map);
+}
+
+static void __exit exit_rc_map_tt_1500(void)
+{
+	rc_map_unregister(&tt_1500_map);
+}
+
+module_init(init_rc_map_tt_1500)
+module_exit(exit_rc_map_tt_1500)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-twinhan1027.c linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-twinhan1027.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-twinhan1027.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-twinhan1027.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,87 @@
+#include <media/rc-map.h>
+
+static struct rc_map_table twinhan_vp1027[] = {
+	{ 0x16, KEY_POWER2 },
+	{ 0x17, KEY_FAVORITES },
+	{ 0x0f, KEY_TEXT },
+	{ 0x48, KEY_INFO},
+	{ 0x1c, KEY_EPG },
+	{ 0x04, KEY_LIST },
+
+	{ 0x03, KEY_1 },
+	{ 0x01, KEY_2 },
+	{ 0x06, KEY_3 },
+	{ 0x09, KEY_4 },
+	{ 0x1d, KEY_5 },
+	{ 0x1f, KEY_6 },
+	{ 0x0d, KEY_7 },
+	{ 0x19, KEY_8 },
+	{ 0x1b, KEY_9 },
+	{ 0x15, KEY_0 },
+
+	{ 0x0c, KEY_CANCEL },
+	{ 0x4a, KEY_CLEAR },
+	{ 0x13, KEY_BACKSPACE },
+	{ 0x00, KEY_TAB },
+
+	{ 0x4b, KEY_UP },
+	{ 0x51, KEY_DOWN },
+	{ 0x4e, KEY_LEFT },
+	{ 0x52, KEY_RIGHT },
+	{ 0x4f, KEY_ENTER },
+
+	{ 0x1e, KEY_VOLUMEUP },
+	{ 0x0a, KEY_VOLUMEDOWN },
+	{ 0x02, KEY_CHANNELDOWN },
+	{ 0x05, KEY_CHANNELUP },
+	{ 0x11, KEY_RECORD },
+
+	{ 0x14, KEY_PLAY },
+	{ 0x4c, KEY_PAUSE },
+	{ 0x1a, KEY_STOP },
+	{ 0x40, KEY_REWIND },
+	{ 0x12, KEY_FASTFORWARD },
+	{ 0x41, KEY_PREVIOUSSONG },
+	{ 0x42, KEY_NEXTSONG },
+	{ 0x54, KEY_SAVE },
+	{ 0x50, KEY_LANGUAGE },
+	{ 0x47, KEY_MEDIA },
+	{ 0x4d, KEY_SCREEN },
+	{ 0x43, KEY_SUBTITLE },
+	{ 0x10, KEY_MUTE },
+	{ 0x49, KEY_AUDIO },
+	{ 0x07, KEY_SLEEP },
+	{ 0x08, KEY_VIDEO },
+	{ 0x0e, KEY_AGAIN },
+	{ 0x45, KEY_EQUAL },
+	{ 0x46, KEY_MINUS },
+	{ 0x18, KEY_RED },
+	{ 0x53, KEY_GREEN },
+	{ 0x5e, KEY_YELLOW },
+	{ 0x5f, KEY_BLUE },
+};
+
+static struct rc_map_list twinhan_vp1027_map = {
+	.map = {
+		.scan    = twinhan_vp1027,
+		.size    = ARRAY_SIZE(twinhan_vp1027),
+		.rc_type = RC_TYPE_UNKNOWN,	/* Legacy IR type */
+		.name    = RC_MAP_TWINHAN_VP1027_DVBS,
+	}
+};
+
+static int __init init_rc_map_twinhan_vp1027(void)
+{
+	return rc_map_register(&twinhan_vp1027_map);
+}
+
+static void __exit exit_rc_map_twinhan_vp1027(void)
+{
+	rc_map_unregister(&twinhan_vp1027_map);
+}
+
+module_init(init_rc_map_twinhan_vp1027)
+module_exit(exit_rc_map_twinhan_vp1027)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Sergey Ivanov <123kash@gmail.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-videomate-m1f.c linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-videomate-m1f.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-videomate-m1f.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-videomate-m1f.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,92 @@
+/* videomate-m1f.h - Keytable for videomate_m1f Remote Controller
+ *
+ * keymap imported from ir-keymaps.c
+ *
+ * Copyright (c) 2010 by Pavel Osnova <pvosnova@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 <media/rc-map.h>
+
+static struct rc_map_table videomate_m1f[] = {
+	{ 0x01, KEY_POWER },
+	{ 0x31, KEY_TUNER },
+	{ 0x33, KEY_VIDEO },
+	{ 0x2f, KEY_RADIO },
+	{ 0x30, KEY_CAMERA },
+	{ 0x2d, KEY_NEW }, /* TV record button */
+	{ 0x17, KEY_CYCLEWINDOWS },
+	{ 0x2c, KEY_ANGLE },
+	{ 0x2b, KEY_LANGUAGE },
+	{ 0x32, KEY_SEARCH }, /* '...' button */
+	{ 0x11, KEY_UP },
+	{ 0x13, KEY_LEFT },
+	{ 0x15, KEY_OK },
+	{ 0x14, KEY_RIGHT },
+	{ 0x12, KEY_DOWN },
+	{ 0x16, KEY_BACKSPACE },
+	{ 0x02, KEY_ZOOM }, /* WIN key */
+	{ 0x04, KEY_INFO },
+	{ 0x05, KEY_VOLUMEUP },
+	{ 0x03, KEY_MUTE },
+	{ 0x07, KEY_CHANNELUP },
+	{ 0x06, KEY_VOLUMEDOWN },
+	{ 0x08, KEY_CHANNELDOWN },
+	{ 0x0c, KEY_RECORD },
+	{ 0x0e, KEY_STOP },
+	{ 0x0a, KEY_BACK },
+	{ 0x0b, KEY_PLAY },
+	{ 0x09, KEY_FORWARD },
+	{ 0x10, KEY_PREVIOUS },
+	{ 0x0d, KEY_PAUSE },
+	{ 0x0f, KEY_NEXT },
+	{ 0x1e, KEY_1 },
+	{ 0x1f, KEY_2 },
+	{ 0x20, KEY_3 },
+	{ 0x21, KEY_4 },
+	{ 0x22, KEY_5 },
+	{ 0x23, KEY_6 },
+	{ 0x24, KEY_7 },
+	{ 0x25, KEY_8 },
+	{ 0x26, KEY_9 },
+	{ 0x2a, KEY_NUMERIC_STAR }, /* * key */
+	{ 0x1d, KEY_0 },
+	{ 0x29, KEY_SUBTITLE }, /* # key */
+	{ 0x27, KEY_CLEAR },
+	{ 0x34, KEY_SCREEN },
+	{ 0x28, KEY_ENTER },
+	{ 0x19, KEY_RED },
+	{ 0x1a, KEY_GREEN },
+	{ 0x1b, KEY_YELLOW },
+	{ 0x1c, KEY_BLUE },
+	{ 0x18, KEY_TEXT },
+};
+
+static struct rc_map_list videomate_m1f_map = {
+	.map = {
+		.scan    = videomate_m1f,
+		.size    = ARRAY_SIZE(videomate_m1f),
+		.rc_type = RC_TYPE_UNKNOWN,     /* Legacy IR type */
+		.name    = RC_MAP_VIDEOMATE_M1F,
+	}
+};
+
+static int __init init_rc_map_videomate_m1f(void)
+{
+	return rc_map_register(&videomate_m1f_map);
+}
+
+static void __exit exit_rc_map_videomate_m1f(void)
+{
+	rc_map_unregister(&videomate_m1f_map);
+}
+
+module_init(init_rc_map_videomate_m1f)
+module_exit(exit_rc_map_videomate_m1f)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Pavel Osnova <pvosnova@gmail.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-videomate-s350.c linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-videomate-s350.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-videomate-s350.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-videomate-s350.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,85 @@
+/* videomate-s350.h - Keytable for videomate_s350 Remote Controller
+ *
+ * keymap imported from ir-keymaps.c
+ *
+ * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
+
+static struct rc_map_table videomate_s350[] = {
+	{ 0x00, KEY_TV},
+	{ 0x01, KEY_DVD},
+	{ 0x04, KEY_RECORD},
+	{ 0x05, KEY_VIDEO},	/* TV/Video */
+	{ 0x07, KEY_STOP},
+	{ 0x08, KEY_PLAYPAUSE},
+	{ 0x0a, KEY_REWIND},
+	{ 0x0f, KEY_FASTFORWARD},
+	{ 0x10, KEY_CHANNELUP},
+	{ 0x12, KEY_VOLUMEUP},
+	{ 0x13, KEY_CHANNELDOWN},
+	{ 0x14, KEY_MUTE},
+	{ 0x15, KEY_VOLUMEDOWN},
+	{ 0x16, KEY_1},
+	{ 0x17, KEY_2},
+	{ 0x18, KEY_3},
+	{ 0x19, KEY_4},
+	{ 0x1a, KEY_5},
+	{ 0x1b, KEY_6},
+	{ 0x1c, KEY_7},
+	{ 0x1d, KEY_8},
+	{ 0x1e, KEY_9},
+	{ 0x1f, KEY_0},
+	{ 0x21, KEY_SLEEP},
+	{ 0x24, KEY_ZOOM},
+	{ 0x25, KEY_LAST},	/* Recall */
+	{ 0x26, KEY_SUBTITLE},	/* CC */
+	{ 0x27, KEY_LANGUAGE},	/* MTS */
+	{ 0x29, KEY_CHANNEL},	/* SURF */
+	{ 0x2b, KEY_A},
+	{ 0x2c, KEY_B},
+	{ 0x2f, KEY_CAMERA},	/* Snapshot */
+	{ 0x23, KEY_RADIO},
+	{ 0x02, KEY_PREVIOUSSONG},
+	{ 0x06, KEY_NEXTSONG},
+	{ 0x03, KEY_EPG},
+	{ 0x09, KEY_SETUP},
+	{ 0x22, KEY_BACKSPACE},
+	{ 0x0c, KEY_UP},
+	{ 0x0e, KEY_DOWN},
+	{ 0x0b, KEY_LEFT},
+	{ 0x0d, KEY_RIGHT},
+	{ 0x11, KEY_ENTER},
+	{ 0x20, KEY_TEXT},
+};
+
+static struct rc_map_list videomate_s350_map = {
+	.map = {
+		.scan    = videomate_s350,
+		.size    = ARRAY_SIZE(videomate_s350),
+		.rc_type = RC_TYPE_UNKNOWN,	/* Legacy IR type */
+		.name    = RC_MAP_VIDEOMATE_S350,
+	}
+};
+
+static int __init init_rc_map_videomate_s350(void)
+{
+	return rc_map_register(&videomate_s350_map);
+}
+
+static void __exit exit_rc_map_videomate_s350(void)
+{
+	rc_map_unregister(&videomate_s350_map);
+}
+
+module_init(init_rc_map_videomate_s350)
+module_exit(exit_rc_map_videomate_s350)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-videomate-tv-pvr.c linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-videomate-tv-pvr.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-videomate-tv-pvr.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-videomate-tv-pvr.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,87 @@
+/* videomate-tv-pvr.h - Keytable for videomate_tv_pvr Remote Controller
+ *
+ * keymap imported from ir-keymaps.c
+ *
+ * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
+
+static struct rc_map_table videomate_tv_pvr[] = {
+	{ 0x14, KEY_MUTE },
+	{ 0x24, KEY_ZOOM },
+
+	{ 0x01, KEY_DVD },
+	{ 0x23, KEY_RADIO },
+	{ 0x00, KEY_TV },
+
+	{ 0x0a, KEY_REWIND },
+	{ 0x08, KEY_PLAYPAUSE },
+	{ 0x0f, KEY_FORWARD },
+
+	{ 0x02, KEY_PREVIOUS },
+	{ 0x07, KEY_STOP },
+	{ 0x06, KEY_NEXT },
+
+	{ 0x0c, KEY_UP },
+	{ 0x0e, KEY_DOWN },
+	{ 0x0b, KEY_LEFT },
+	{ 0x0d, KEY_RIGHT },
+	{ 0x11, KEY_OK },
+
+	{ 0x03, KEY_MENU },
+	{ 0x09, KEY_SETUP },
+	{ 0x05, KEY_VIDEO },
+	{ 0x22, KEY_CHANNEL },
+
+	{ 0x12, KEY_VOLUMEUP },
+	{ 0x15, KEY_VOLUMEDOWN },
+	{ 0x10, KEY_CHANNELUP },
+	{ 0x13, KEY_CHANNELDOWN },
+
+	{ 0x04, KEY_RECORD },
+
+	{ 0x16, KEY_1 },
+	{ 0x17, KEY_2 },
+	{ 0x18, KEY_3 },
+	{ 0x19, KEY_4 },
+	{ 0x1a, KEY_5 },
+	{ 0x1b, KEY_6 },
+	{ 0x1c, KEY_7 },
+	{ 0x1d, KEY_8 },
+	{ 0x1e, KEY_9 },
+	{ 0x1f, KEY_0 },
+
+	{ 0x20, KEY_LANGUAGE },
+	{ 0x21, KEY_SLEEP },
+};
+
+static struct rc_map_list videomate_tv_pvr_map = {
+	.map = {
+		.scan    = videomate_tv_pvr,
+		.size    = ARRAY_SIZE(videomate_tv_pvr),
+		.rc_type = RC_TYPE_UNKNOWN,	/* Legacy IR type */
+		.name    = RC_MAP_VIDEOMATE_TV_PVR,
+	}
+};
+
+static int __init init_rc_map_videomate_tv_pvr(void)
+{
+	return rc_map_register(&videomate_tv_pvr_map);
+}
+
+static void __exit exit_rc_map_videomate_tv_pvr(void)
+{
+	rc_map_unregister(&videomate_tv_pvr_map);
+}
+
+module_init(init_rc_map_videomate_tv_pvr)
+module_exit(exit_rc_map_videomate_tv_pvr)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-winfast.c linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-winfast.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-winfast.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-winfast.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,102 @@
+/* winfast.h - Keytable for winfast Remote Controller
+ *
+ * keymap imported from ir-keymaps.c
+ *
+ * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
+
+/* Table for Leadtek Winfast Remote Controls - used by both bttv and cx88 */
+
+static struct rc_map_table winfast[] = {
+	/* Keys 0 to 9 */
+	{ 0x12, KEY_0 },
+	{ 0x05, KEY_1 },
+	{ 0x06, KEY_2 },
+	{ 0x07, KEY_3 },
+	{ 0x09, KEY_4 },
+	{ 0x0a, KEY_5 },
+	{ 0x0b, KEY_6 },
+	{ 0x0d, KEY_7 },
+	{ 0x0e, KEY_8 },
+	{ 0x0f, KEY_9 },
+
+	{ 0x00, KEY_POWER },
+	{ 0x1b, KEY_AUDIO },		/* Audio Source */
+	{ 0x02, KEY_TUNER },		/* TV/FM, not on Y0400052 */
+	{ 0x1e, KEY_VIDEO },		/* Video Source */
+	{ 0x16, KEY_INFO },		/* Display information */
+	{ 0x04, KEY_VOLUMEUP },
+	{ 0x08, KEY_VOLUMEDOWN },
+	{ 0x0c, KEY_CHANNELUP },
+	{ 0x10, KEY_CHANNELDOWN },
+	{ 0x03, KEY_ZOOM },		/* fullscreen */
+	{ 0x1f, KEY_TEXT },		/* closed caption/teletext */
+	{ 0x20, KEY_SLEEP },
+	{ 0x29, KEY_CLEAR },		/* boss key */
+	{ 0x14, KEY_MUTE },
+	{ 0x2b, KEY_RED },
+	{ 0x2c, KEY_GREEN },
+	{ 0x2d, KEY_YELLOW },
+	{ 0x2e, KEY_BLUE },
+	{ 0x18, KEY_KPPLUS },		/* fine tune + , not on Y040052 */
+	{ 0x19, KEY_KPMINUS },		/* fine tune - , not on Y040052 */
+	{ 0x2a, KEY_MEDIA },		/* PIP (Picture in picture */
+	{ 0x21, KEY_DOT },
+	{ 0x13, KEY_ENTER },
+	{ 0x11, KEY_LAST },		/* Recall (last channel */
+	{ 0x22, KEY_PREVIOUS },
+	{ 0x23, KEY_PLAYPAUSE },
+	{ 0x24, KEY_NEXT },
+	{ 0x25, KEY_TIME },		/* Time Shifting */
+	{ 0x26, KEY_STOP },
+	{ 0x27, KEY_RECORD },
+	{ 0x28, KEY_SAVE },		/* Screenshot */
+	{ 0x2f, KEY_MENU },
+	{ 0x30, KEY_CANCEL },
+	{ 0x31, KEY_CHANNEL },		/* Channel Surf */
+	{ 0x32, KEY_SUBTITLE },
+	{ 0x33, KEY_LANGUAGE },
+	{ 0x34, KEY_REWIND },
+	{ 0x35, KEY_FASTFORWARD },
+	{ 0x36, KEY_TV },
+	{ 0x37, KEY_RADIO },		/* FM */
+	{ 0x38, KEY_DVD },
+
+	{ 0x1a, KEY_MODE},		/* change to MCE mode on Y04G0051 */
+	{ 0x3e, KEY_F21 },		/* MCE +VOL, on Y04G0033 */
+	{ 0x3a, KEY_F22 },		/* MCE -VOL, on Y04G0033 */
+	{ 0x3b, KEY_F23 },		/* MCE +CH,  on Y04G0033 */
+	{ 0x3f, KEY_F24 }		/* MCE -CH,  on Y04G0033 */
+};
+
+static struct rc_map_list winfast_map = {
+	.map = {
+		.scan    = winfast,
+		.size    = ARRAY_SIZE(winfast),
+		.rc_type = RC_TYPE_UNKNOWN,	/* Legacy IR type */
+		.name    = RC_MAP_WINFAST,
+	}
+};
+
+static int __init init_rc_map_winfast(void)
+{
+	return rc_map_register(&winfast_map);
+}
+
+static void __exit exit_rc_map_winfast(void)
+{
+	rc_map_unregister(&winfast_map);
+}
+
+module_init(init_rc_map_winfast)
+module_exit(exit_rc_map_winfast)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-winfast-usbii-deluxe.c linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-winfast-usbii-deluxe.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/keymaps/rc-winfast-usbii-deluxe.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/keymaps/rc-winfast-usbii-deluxe.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,82 @@
+/* winfast-usbii-deluxe.h - Keytable for winfast_usbii_deluxe Remote Controller
+ *
+ * keymap imported from ir-keymaps.c
+ *
+ * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 <media/rc-map.h>
+
+/* Leadtek Winfast TV USB II Deluxe remote
+   Magnus Alm <magnus.alm@gmail.com>
+ */
+
+static struct rc_map_table winfast_usbii_deluxe[] = {
+	{ 0x62, KEY_0},
+	{ 0x75, KEY_1},
+	{ 0x76, KEY_2},
+	{ 0x77, KEY_3},
+	{ 0x79, KEY_4},
+	{ 0x7a, KEY_5},
+	{ 0x7b, KEY_6},
+	{ 0x7d, KEY_7},
+	{ 0x7e, KEY_8},
+	{ 0x7f, KEY_9},
+
+	{ 0x38, KEY_CAMERA},		/* SNAPSHOT */
+	{ 0x37, KEY_RECORD},		/* RECORD */
+	{ 0x35, KEY_TIME},		/* TIMESHIFT */
+
+	{ 0x74, KEY_VOLUMEUP},		/* VOLUMEUP */
+	{ 0x78, KEY_VOLUMEDOWN},	/* VOLUMEDOWN */
+	{ 0x64, KEY_MUTE},		/* MUTE */
+
+	{ 0x21, KEY_CHANNEL},		/* SURF */
+	{ 0x7c, KEY_CHANNELUP},		/* CHANNELUP */
+	{ 0x60, KEY_CHANNELDOWN},	/* CHANNELDOWN */
+	{ 0x61, KEY_LAST},		/* LAST CHANNEL (RECALL) */
+
+	{ 0x72, KEY_VIDEO}, 		/* INPUT MODES (TV/FM) */
+
+	{ 0x70, KEY_POWER2},		/* TV ON/OFF */
+
+	{ 0x39, KEY_CYCLEWINDOWS},	/* MINIMIZE (BOSS) */
+	{ 0x3a, KEY_NEW},		/* PIP */
+	{ 0x73, KEY_ZOOM},		/* FULLSECREEN */
+
+	{ 0x66, KEY_INFO},		/* OSD (DISPLAY) */
+
+	{ 0x31, KEY_DOT},		/* '.' */
+	{ 0x63, KEY_ENTER},		/* ENTER */
+
+};
+
+static struct rc_map_list winfast_usbii_deluxe_map = {
+	.map = {
+		.scan    = winfast_usbii_deluxe,
+		.size    = ARRAY_SIZE(winfast_usbii_deluxe),
+		.rc_type = RC_TYPE_UNKNOWN,	/* Legacy IR type */
+		.name    = RC_MAP_WINFAST_USBII_DELUXE,
+	}
+};
+
+static int __init init_rc_map_winfast_usbii_deluxe(void)
+{
+	return rc_map_register(&winfast_usbii_deluxe_map);
+}
+
+static void __exit exit_rc_map_winfast_usbii_deluxe(void)
+{
+	rc_map_unregister(&winfast_usbii_deluxe_map);
+}
+
+module_init(init_rc_map_winfast_usbii_deluxe)
+module_exit(exit_rc_map_winfast_usbii_deluxe)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/lirc_dev.c linux-libre-2.6.38-gnu1/drivers/media/rc/lirc_dev.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/lirc_dev.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/lirc_dev.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,816 @@
+/*
+ * LIRC base driver
+ *
+ * by Artur Lipowski <alipowski@interia.pl>
+ *
+ *  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/kernel.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/ioctl.h>
+#include <linux/fs.h>
+#include <linux/poll.h>
+#include <linux/completion.h>
+#include <linux/mutex.h>
+#include <linux/wait.h>
+#include <linux/unistd.h>
+#include <linux/kthread.h>
+#include <linux/bitops.h>
+#include <linux/device.h>
+#include <linux/cdev.h>
+
+#include <media/lirc.h>
+#include <media/lirc_dev.h>
+
+static int debug;
+
+#define IRCTL_DEV_NAME	"BaseRemoteCtl"
+#define NOPLUG		-1
+#define LOGHEAD		"lirc_dev (%s[%d]): "
+
+static dev_t lirc_base_dev;
+
+struct irctl {
+	struct lirc_driver d;
+	int attached;
+	int open;
+
+	struct mutex irctl_lock;
+	struct lirc_buffer *buf;
+	unsigned int chunk_size;
+
+	struct task_struct *task;
+	long jiffies_to_wait;
+};
+
+static DEFINE_MUTEX(lirc_dev_lock);
+
+static struct irctl *irctls[MAX_IRCTL_DEVICES];
+static struct cdev cdevs[MAX_IRCTL_DEVICES];
+
+/* Only used for sysfs but defined to void otherwise */
+static struct class *lirc_class;
+
+/*  helper function
+ *  initializes the irctl structure
+ */
+static void lirc_irctl_init(struct irctl *ir)
+{
+	mutex_init(&ir->irctl_lock);
+	ir->d.minor = NOPLUG;
+}
+
+static void lirc_irctl_cleanup(struct irctl *ir)
+{
+	dev_dbg(ir->d.dev, LOGHEAD "cleaning up\n", ir->d.name, ir->d.minor);
+
+	device_destroy(lirc_class, MKDEV(MAJOR(lirc_base_dev), ir->d.minor));
+
+	if (ir->buf != ir->d.rbuf) {
+		lirc_buffer_free(ir->buf);
+		kfree(ir->buf);
+	}
+	ir->buf = NULL;
+}
+
+/*  helper function
+ *  reads key codes from driver and puts them into buffer
+ *  returns 0 on success
+ */
+static int lirc_add_to_buf(struct irctl *ir)
+{
+	if (ir->d.add_to_buf) {
+		int res = -ENODATA;
+		int got_data = 0;
+
+		/*
+		 * service the device as long as it is returning
+		 * data and we have space
+		 */
+get_data:
+		res = ir->d.add_to_buf(ir->d.data, ir->buf);
+		if (res == 0) {
+			got_data++;
+			goto get_data;
+		}
+
+		if (res == -ENODEV)
+			kthread_stop(ir->task);
+
+		return got_data ? 0 : res;
+	}
+
+	return 0;
+}
+
+/* main function of the polling thread
+ */
+static int lirc_thread(void *irctl)
+{
+	struct irctl *ir = irctl;
+
+	dev_dbg(ir->d.dev, LOGHEAD "poll thread started\n",
+		ir->d.name, ir->d.minor);
+
+	do {
+		if (ir->open) {
+			if (ir->jiffies_to_wait) {
+				set_current_state(TASK_INTERRUPTIBLE);
+				schedule_timeout(ir->jiffies_to_wait);
+			}
+			if (kthread_should_stop())
+				break;
+			if (!lirc_add_to_buf(ir))
+				wake_up_interruptible(&ir->buf->wait_poll);
+		} else {
+			set_current_state(TASK_INTERRUPTIBLE);
+			schedule();
+		}
+	} while (!kthread_should_stop());
+
+	dev_dbg(ir->d.dev, LOGHEAD "poll thread ended\n",
+		ir->d.name, ir->d.minor);
+
+	return 0;
+}
+
+
+static struct file_operations lirc_dev_fops = {
+	.owner		= THIS_MODULE,
+	.read		= lirc_dev_fop_read,
+	.write		= lirc_dev_fop_write,
+	.poll		= lirc_dev_fop_poll,
+	.unlocked_ioctl	= lirc_dev_fop_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl	= lirc_dev_fop_ioctl,
+#endif
+	.open		= lirc_dev_fop_open,
+	.release	= lirc_dev_fop_close,
+	.llseek		= noop_llseek,
+};
+
+static int lirc_cdev_add(struct irctl *ir)
+{
+	int retval;
+	struct lirc_driver *d = &ir->d;
+	struct cdev *cdev = &cdevs[d->minor];
+
+	if (d->fops) {
+		cdev_init(cdev, d->fops);
+		cdev->owner = d->owner;
+	} else {
+		cdev_init(cdev, &lirc_dev_fops);
+		cdev->owner = THIS_MODULE;
+	}
+	retval = kobject_set_name(&cdev->kobj, "lirc%d", d->minor);
+	if (retval)
+		return retval;
+
+	retval = cdev_add(cdev, MKDEV(MAJOR(lirc_base_dev), d->minor), 1);
+	if (retval)
+		kobject_put(&cdev->kobj);
+
+	return retval;
+}
+
+int lirc_register_driver(struct lirc_driver *d)
+{
+	struct irctl *ir;
+	int minor;
+	int bytes_in_key;
+	unsigned int chunk_size;
+	unsigned int buffer_size;
+	int err;
+
+	if (!d) {
+		printk(KERN_ERR "lirc_dev: lirc_register_driver: "
+		       "driver pointer must be not NULL!\n");
+		err = -EBADRQC;
+		goto out;
+	}
+
+	if (!d->dev) {
+		printk(KERN_ERR "%s: dev pointer not filled in!\n", __func__);
+		err = -EINVAL;
+		goto out;
+	}
+
+	if (MAX_IRCTL_DEVICES <= d->minor) {
+		dev_err(d->dev, "lirc_dev: lirc_register_driver: "
+			"\"minor\" must be between 0 and %d (%d)!\n",
+			MAX_IRCTL_DEVICES-1, d->minor);
+		err = -EBADRQC;
+		goto out;
+	}
+
+	if (1 > d->code_length || (BUFLEN * 8) < d->code_length) {
+		dev_err(d->dev, "lirc_dev: lirc_register_driver: "
+			"code length in bits for minor (%d) "
+			"must be less than %d!\n",
+			d->minor, BUFLEN * 8);
+		err = -EBADRQC;
+		goto out;
+	}
+
+	dev_dbg(d->dev, "lirc_dev: lirc_register_driver: sample_rate: %d\n",
+		d->sample_rate);
+	if (d->sample_rate) {
+		if (2 > d->sample_rate || HZ < d->sample_rate) {
+			dev_err(d->dev, "lirc_dev: lirc_register_driver: "
+				"sample_rate must be between 2 and %d!\n", HZ);
+			err = -EBADRQC;
+			goto out;
+		}
+		if (!d->add_to_buf) {
+			dev_err(d->dev, "lirc_dev: lirc_register_driver: "
+				"add_to_buf cannot be NULL when "
+				"sample_rate is set\n");
+			err = -EBADRQC;
+			goto out;
+		}
+	} else if (!(d->fops && d->fops->read) && !d->rbuf) {
+		dev_err(d->dev, "lirc_dev: lirc_register_driver: "
+			"fops->read and rbuf cannot all be NULL!\n");
+		err = -EBADRQC;
+		goto out;
+	} else if (!d->rbuf) {
+		if (!(d->fops && d->fops->read && d->fops->poll &&
+		      d->fops->unlocked_ioctl)) {
+			dev_err(d->dev, "lirc_dev: lirc_register_driver: "
+				"neither read, poll nor unlocked_ioctl can be NULL!\n");
+			err = -EBADRQC;
+			goto out;
+		}
+	}
+
+	mutex_lock(&lirc_dev_lock);
+
+	minor = d->minor;
+
+	if (minor < 0) {
+		/* find first free slot for driver */
+		for (minor = 0; minor < MAX_IRCTL_DEVICES; minor++)
+			if (!irctls[minor])
+				break;
+		if (MAX_IRCTL_DEVICES == minor) {
+			dev_err(d->dev, "lirc_dev: lirc_register_driver: "
+				"no free slots for drivers!\n");
+			err = -ENOMEM;
+			goto out_lock;
+		}
+	} else if (irctls[minor]) {
+		dev_err(d->dev, "lirc_dev: lirc_register_driver: "
+			"minor (%d) just registered!\n", minor);
+		err = -EBUSY;
+		goto out_lock;
+	}
+
+	ir = kzalloc(sizeof(struct irctl), GFP_KERNEL);
+	if (!ir) {
+		err = -ENOMEM;
+		goto out_lock;
+	}
+	lirc_irctl_init(ir);
+	irctls[minor] = ir;
+	d->minor = minor;
+
+	if (d->sample_rate) {
+		ir->jiffies_to_wait = HZ / d->sample_rate;
+	} else {
+		/* it means - wait for external event in task queue */
+		ir->jiffies_to_wait = 0;
+	}
+
+	/* some safety check 8-) */
+	d->name[sizeof(d->name)-1] = '\0';
+
+	bytes_in_key = BITS_TO_LONGS(d->code_length) +
+			(d->code_length % 8 ? 1 : 0);
+	buffer_size = d->buffer_size ? d->buffer_size : BUFLEN / bytes_in_key;
+	chunk_size  = d->chunk_size  ? d->chunk_size  : bytes_in_key;
+
+	if (d->rbuf) {
+		ir->buf = d->rbuf;
+	} else {
+		ir->buf = kmalloc(sizeof(struct lirc_buffer), GFP_KERNEL);
+		if (!ir->buf) {
+			err = -ENOMEM;
+			goto out_lock;
+		}
+		err = lirc_buffer_init(ir->buf, chunk_size, buffer_size);
+		if (err) {
+			kfree(ir->buf);
+			goto out_lock;
+		}
+	}
+	ir->chunk_size = ir->buf->chunk_size;
+
+	if (d->features == 0)
+		d->features = LIRC_CAN_REC_LIRCCODE;
+
+	ir->d = *d;
+
+	device_create(lirc_class, ir->d.dev,
+		      MKDEV(MAJOR(lirc_base_dev), ir->d.minor), NULL,
+		      "lirc%u", ir->d.minor);
+
+	if (d->sample_rate) {
+		/* try to fire up polling thread */
+		ir->task = kthread_run(lirc_thread, (void *)ir, "lirc_dev");
+		if (IS_ERR(ir->task)) {
+			dev_err(d->dev, "lirc_dev: lirc_register_driver: "
+				"cannot run poll thread for minor = %d\n",
+				d->minor);
+			err = -ECHILD;
+			goto out_sysfs;
+		}
+	}
+
+	err = lirc_cdev_add(ir);
+	if (err)
+		goto out_sysfs;
+
+	ir->attached = 1;
+	mutex_unlock(&lirc_dev_lock);
+
+	dev_info(ir->d.dev, "lirc_dev: driver %s registered at minor = %d\n",
+		 ir->d.name, ir->d.minor);
+	return minor;
+
+out_sysfs:
+	device_destroy(lirc_class, MKDEV(MAJOR(lirc_base_dev), ir->d.minor));
+out_lock:
+	mutex_unlock(&lirc_dev_lock);
+out:
+	return err;
+}
+EXPORT_SYMBOL(lirc_register_driver);
+
+int lirc_unregister_driver(int minor)
+{
+	struct irctl *ir;
+	struct cdev *cdev;
+
+	if (minor < 0 || minor >= MAX_IRCTL_DEVICES) {
+		printk(KERN_ERR "lirc_dev: %s: minor (%d) must be between "
+		       "0 and %d!\n", __func__, minor, MAX_IRCTL_DEVICES-1);
+		return -EBADRQC;
+	}
+
+	ir = irctls[minor];
+	if (!ir) {
+		printk(KERN_ERR "lirc_dev: %s: failed to get irctl struct "
+		       "for minor %d!\n", __func__, minor);
+		return -ENOENT;
+	}
+
+	cdev = &cdevs[minor];
+
+	mutex_lock(&lirc_dev_lock);
+
+	if (ir->d.minor != minor) {
+		printk(KERN_ERR "lirc_dev: %s: minor (%d) device not "
+		       "registered!\n", __func__, minor);
+		mutex_unlock(&lirc_dev_lock);
+		return -ENOENT;
+	}
+
+	/* end up polling thread */
+	if (ir->task)
+		kthread_stop(ir->task);
+
+	dev_dbg(ir->d.dev, "lirc_dev: driver %s unregistered from minor = %d\n",
+		ir->d.name, ir->d.minor);
+
+	ir->attached = 0;
+	if (ir->open) {
+		dev_dbg(ir->d.dev, LOGHEAD "releasing opened driver\n",
+			ir->d.name, ir->d.minor);
+		wake_up_interruptible(&ir->buf->wait_poll);
+		mutex_lock(&ir->irctl_lock);
+		ir->d.set_use_dec(ir->d.data);
+		module_put(cdev->owner);
+		mutex_unlock(&ir->irctl_lock);
+	} else {
+		lirc_irctl_cleanup(ir);
+		cdev_del(cdev);
+		kfree(ir);
+		irctls[minor] = NULL;
+	}
+
+	mutex_unlock(&lirc_dev_lock);
+
+	return 0;
+}
+EXPORT_SYMBOL(lirc_unregister_driver);
+
+int lirc_dev_fop_open(struct inode *inode, struct file *file)
+{
+	struct irctl *ir;
+	struct cdev *cdev;
+	int retval = 0;
+
+	if (iminor(inode) >= MAX_IRCTL_DEVICES) {
+		printk(KERN_WARNING "lirc_dev [%d]: open result = -ENODEV\n",
+		       iminor(inode));
+		return -ENODEV;
+	}
+
+	if (mutex_lock_interruptible(&lirc_dev_lock))
+		return -ERESTARTSYS;
+
+	ir = irctls[iminor(inode)];
+	if (!ir) {
+		retval = -ENODEV;
+		goto error;
+	}
+
+	dev_dbg(ir->d.dev, LOGHEAD "open called\n", ir->d.name, ir->d.minor);
+
+	if (ir->d.minor == NOPLUG) {
+		retval = -ENODEV;
+		goto error;
+	}
+
+	if (ir->open) {
+		retval = -EBUSY;
+		goto error;
+	}
+
+	cdev = &cdevs[iminor(inode)];
+	if (try_module_get(cdev->owner)) {
+		ir->open++;
+		retval = ir->d.set_use_inc(ir->d.data);
+
+		if (retval) {
+			module_put(cdev->owner);
+			ir->open--;
+		} else {
+			lirc_buffer_clear(ir->buf);
+		}
+		if (ir->task)
+			wake_up_process(ir->task);
+	}
+
+error:
+	if (ir)
+		dev_dbg(ir->d.dev, LOGHEAD "open result = %d\n",
+			ir->d.name, ir->d.minor, retval);
+
+	mutex_unlock(&lirc_dev_lock);
+
+	nonseekable_open(inode, file);
+
+	return retval;
+}
+EXPORT_SYMBOL(lirc_dev_fop_open);
+
+int lirc_dev_fop_close(struct inode *inode, struct file *file)
+{
+	struct irctl *ir = irctls[iminor(inode)];
+	struct cdev *cdev = &cdevs[iminor(inode)];
+
+	if (!ir) {
+		printk(KERN_ERR "%s: called with invalid irctl\n", __func__);
+		return -EINVAL;
+	}
+
+	dev_dbg(ir->d.dev, LOGHEAD "close called\n", ir->d.name, ir->d.minor);
+
+	WARN_ON(mutex_lock_killable(&lirc_dev_lock));
+
+	ir->open--;
+	if (ir->attached) {
+		ir->d.set_use_dec(ir->d.data);
+		module_put(cdev->owner);
+	} else {
+		lirc_irctl_cleanup(ir);
+		cdev_del(cdev);
+		irctls[ir->d.minor] = NULL;
+		kfree(ir);
+	}
+
+	mutex_unlock(&lirc_dev_lock);
+
+	return 0;
+}
+EXPORT_SYMBOL(lirc_dev_fop_close);
+
+unsigned int lirc_dev_fop_poll(struct file *file, poll_table *wait)
+{
+	struct irctl *ir = irctls[iminor(file->f_dentry->d_inode)];
+	unsigned int ret;
+
+	if (!ir) {
+		printk(KERN_ERR "%s: called with invalid irctl\n", __func__);
+		return POLLERR;
+	}
+
+	dev_dbg(ir->d.dev, LOGHEAD "poll called\n", ir->d.name, ir->d.minor);
+
+	if (!ir->attached)
+		return POLLERR;
+
+	poll_wait(file, &ir->buf->wait_poll, wait);
+
+	if (ir->buf)
+		if (lirc_buffer_empty(ir->buf))
+			ret = 0;
+		else
+			ret = POLLIN | POLLRDNORM;
+	else
+		ret = POLLERR;
+
+	dev_dbg(ir->d.dev, LOGHEAD "poll result = %d\n",
+		ir->d.name, ir->d.minor, ret);
+
+	return ret;
+}
+EXPORT_SYMBOL(lirc_dev_fop_poll);
+
+long lirc_dev_fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+	__u32 mode;
+	int result = 0;
+	struct irctl *ir = irctls[iminor(file->f_dentry->d_inode)];
+
+	if (!ir) {
+		printk(KERN_ERR "lirc_dev: %s: no irctl found!\n", __func__);
+		return -ENODEV;
+	}
+
+	dev_dbg(ir->d.dev, LOGHEAD "ioctl called (0x%x)\n",
+		ir->d.name, ir->d.minor, cmd);
+
+	if (ir->d.minor == NOPLUG || !ir->attached) {
+		dev_dbg(ir->d.dev, LOGHEAD "ioctl result = -ENODEV\n",
+			ir->d.name, ir->d.minor);
+		return -ENODEV;
+	}
+
+	mutex_lock(&ir->irctl_lock);
+
+	switch (cmd) {
+	case LIRC_GET_FEATURES:
+		result = put_user(ir->d.features, (__u32 *)arg);
+		break;
+	case LIRC_GET_REC_MODE:
+		if (!(ir->d.features & LIRC_CAN_REC_MASK)) {
+			result = -ENOSYS;
+			break;
+		}
+
+		result = put_user(LIRC_REC2MODE
+				  (ir->d.features & LIRC_CAN_REC_MASK),
+				  (__u32 *)arg);
+		break;
+	case LIRC_SET_REC_MODE:
+		if (!(ir->d.features & LIRC_CAN_REC_MASK)) {
+			result = -ENOSYS;
+			break;
+		}
+
+		result = get_user(mode, (__u32 *)arg);
+		if (!result && !(LIRC_MODE2REC(mode) & ir->d.features))
+			result = -EINVAL;
+		/*
+		 * FIXME: We should actually set the mode somehow but
+		 * for now, lirc_serial doesn't support mode changing either
+		 */
+		break;
+	case LIRC_GET_LENGTH:
+		result = put_user(ir->d.code_length, (__u32 *)arg);
+		break;
+	case LIRC_GET_MIN_TIMEOUT:
+		if (!(ir->d.features & LIRC_CAN_SET_REC_TIMEOUT) ||
+		    ir->d.min_timeout == 0) {
+			result = -ENOSYS;
+			break;
+		}
+
+		result = put_user(ir->d.min_timeout, (__u32 *)arg);
+		break;
+	case LIRC_GET_MAX_TIMEOUT:
+		if (!(ir->d.features & LIRC_CAN_SET_REC_TIMEOUT) ||
+		    ir->d.max_timeout == 0) {
+			result = -ENOSYS;
+			break;
+		}
+
+		result = put_user(ir->d.max_timeout, (__u32 *)arg);
+		break;
+	default:
+		result = -EINVAL;
+	}
+
+	dev_dbg(ir->d.dev, LOGHEAD "ioctl result = %d\n",
+		ir->d.name, ir->d.minor, result);
+
+	mutex_unlock(&ir->irctl_lock);
+
+	return result;
+}
+EXPORT_SYMBOL(lirc_dev_fop_ioctl);
+
+ssize_t lirc_dev_fop_read(struct file *file,
+			  char __user *buffer,
+			  size_t length,
+			  loff_t *ppos)
+{
+	struct irctl *ir = irctls[iminor(file->f_dentry->d_inode)];
+	unsigned char *buf;
+	int ret = 0, written = 0;
+	DECLARE_WAITQUEUE(wait, current);
+
+	if (!ir) {
+		printk(KERN_ERR "%s: called with invalid irctl\n", __func__);
+		return -ENODEV;
+	}
+
+	dev_dbg(ir->d.dev, LOGHEAD "read called\n", ir->d.name, ir->d.minor);
+
+	buf = kzalloc(ir->chunk_size, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	if (mutex_lock_interruptible(&ir->irctl_lock)) {
+		ret = -ERESTARTSYS;
+		goto out_unlocked;
+	}
+	if (!ir->attached) {
+		ret = -ENODEV;
+		goto out_locked;
+	}
+
+	if (length % ir->chunk_size) {
+		ret = -EINVAL;
+		goto out_locked;
+	}
+
+	/*
+	 * we add ourselves to the task queue before buffer check
+	 * to avoid losing scan code (in case when queue is awaken somewhere
+	 * between while condition checking and scheduling)
+	 */
+	add_wait_queue(&ir->buf->wait_poll, &wait);
+	set_current_state(TASK_INTERRUPTIBLE);
+
+	/*
+	 * while we didn't provide 'length' bytes, device is opened in blocking
+	 * mode and 'copy_to_user' is happy, wait for data.
+	 */
+	while (written < length && ret == 0) {
+		if (lirc_buffer_empty(ir->buf)) {
+			/* According to the read(2) man page, 'written' can be
+			 * returned as less than 'length', instead of blocking
+			 * again, returning -EWOULDBLOCK, or returning
+			 * -ERESTARTSYS */
+			if (written)
+				break;
+			if (file->f_flags & O_NONBLOCK) {
+				ret = -EWOULDBLOCK;
+				break;
+			}
+			if (signal_pending(current)) {
+				ret = -ERESTARTSYS;
+				break;
+			}
+
+			mutex_unlock(&ir->irctl_lock);
+			schedule();
+			set_current_state(TASK_INTERRUPTIBLE);
+
+			if (mutex_lock_interruptible(&ir->irctl_lock)) {
+				ret = -ERESTARTSYS;
+				remove_wait_queue(&ir->buf->wait_poll, &wait);
+				set_current_state(TASK_RUNNING);
+				goto out_unlocked;
+			}
+
+			if (!ir->attached) {
+				ret = -ENODEV;
+				break;
+			}
+		} else {
+			lirc_buffer_read(ir->buf, buf);
+			ret = copy_to_user((void *)buffer+written, buf,
+					   ir->buf->chunk_size);
+			if (!ret)
+				written += ir->buf->chunk_size;
+			else
+				ret = -EFAULT;
+		}
+	}
+
+	remove_wait_queue(&ir->buf->wait_poll, &wait);
+	set_current_state(TASK_RUNNING);
+
+out_locked:
+	mutex_unlock(&ir->irctl_lock);
+
+out_unlocked:
+	kfree(buf);
+	dev_dbg(ir->d.dev, LOGHEAD "read result = %s (%d)\n",
+		ir->d.name, ir->d.minor, ret ? "<fail>" : "<ok>", ret);
+
+	return ret ? ret : written;
+}
+EXPORT_SYMBOL(lirc_dev_fop_read);
+
+void *lirc_get_pdata(struct file *file)
+{
+	void *data = NULL;
+
+	if (file && file->f_dentry && file->f_dentry->d_inode &&
+	    file->f_dentry->d_inode->i_rdev) {
+		struct irctl *ir;
+		ir = irctls[iminor(file->f_dentry->d_inode)];
+		data = ir->d.data;
+	}
+
+	return data;
+}
+EXPORT_SYMBOL(lirc_get_pdata);
+
+
+ssize_t lirc_dev_fop_write(struct file *file, const char __user *buffer,
+			   size_t length, loff_t *ppos)
+{
+	struct irctl *ir = irctls[iminor(file->f_dentry->d_inode)];
+
+	if (!ir) {
+		printk(KERN_ERR "%s: called with invalid irctl\n", __func__);
+		return -ENODEV;
+	}
+
+	dev_dbg(ir->d.dev, LOGHEAD "write called\n", ir->d.name, ir->d.minor);
+
+	if (!ir->attached)
+		return -ENODEV;
+
+	return -EINVAL;
+}
+EXPORT_SYMBOL(lirc_dev_fop_write);
+
+
+static int __init lirc_dev_init(void)
+{
+	int retval;
+
+	lirc_class = class_create(THIS_MODULE, "lirc");
+	if (IS_ERR(lirc_class)) {
+		retval = PTR_ERR(lirc_class);
+		printk(KERN_ERR "lirc_dev: class_create failed\n");
+		goto error;
+	}
+
+	retval = alloc_chrdev_region(&lirc_base_dev, 0, MAX_IRCTL_DEVICES,
+				     IRCTL_DEV_NAME);
+	if (retval) {
+		class_destroy(lirc_class);
+		printk(KERN_ERR "lirc_dev: alloc_chrdev_region failed\n");
+		goto error;
+	}
+
+
+	printk(KERN_INFO "lirc_dev: IR Remote Control driver registered, "
+	       "major %d \n", MAJOR(lirc_base_dev));
+
+error:
+	return retval;
+}
+
+
+
+static void __exit lirc_dev_exit(void)
+{
+	class_destroy(lirc_class);
+	unregister_chrdev_region(lirc_base_dev, MAX_IRCTL_DEVICES);
+	printk(KERN_INFO "lirc_dev: module unloaded\n");
+}
+
+module_init(lirc_dev_init);
+module_exit(lirc_dev_exit);
+
+MODULE_DESCRIPTION("LIRC base driver module");
+MODULE_AUTHOR("Artur Lipowski");
+MODULE_LICENSE("GPL");
+
+module_param(debug, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Enable debugging messages");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/Makefile linux-libre-2.6.38-gnu1/drivers/media/rc/Makefile
--- linux-libre-2.6.37-gnu1/drivers/media/rc/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,22 @@
+rc-core-objs	:= rc-main.o ir-raw.o
+
+obj-y += keymaps/
+
+obj-$(CONFIG_RC_CORE) += rc-core.o
+obj-$(CONFIG_LIRC) += lirc_dev.o
+obj-$(CONFIG_IR_NEC_DECODER) += ir-nec-decoder.o
+obj-$(CONFIG_IR_RC5_DECODER) += ir-rc5-decoder.o
+obj-$(CONFIG_IR_RC6_DECODER) += ir-rc6-decoder.o
+obj-$(CONFIG_IR_JVC_DECODER) += ir-jvc-decoder.o
+obj-$(CONFIG_IR_SONY_DECODER) += ir-sony-decoder.o
+obj-$(CONFIG_IR_RC5_SZ_DECODER) += ir-rc5-sz-decoder.o
+obj-$(CONFIG_IR_LIRC_CODEC) += ir-lirc-codec.o
+
+# stand-alone IR receivers/transmitters
+obj-$(CONFIG_IR_IMON) += imon.o
+obj-$(CONFIG_IR_MCEUSB) += mceusb.o
+obj-$(CONFIG_IR_NUVOTON) += nuvoton-cir.o
+obj-$(CONFIG_IR_ENE) += ene_ir.o
+obj-$(CONFIG_IR_STREAMZAP) += streamzap.o
+obj-$(CONFIG_IR_WINBOND_CIR) += winbond-cir.o
+obj-$(CONFIG_RC_LOOPBACK) += rc-loopback.o
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/mceusb.c linux-libre-2.6.38-gnu1/drivers/media/rc/mceusb.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/mceusb.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/mceusb.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,1318 @@
+/*
+ * Driver for USB Windows Media Center Ed. eHome Infrared Transceivers
+ *
+ * Copyright (c) 2010 by 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
+ * in turn also based on the lirc_atiusb driver by Paul Miller. The
+ * two mce drivers were merged into one by Jarod Wilson, with transmit
+ * support for the 1st-gen device added primarily by Patrick Calhoun,
+ * with a bit of tweaks by Jarod. Debugging improvements and proper
+ * support for what appears to be 3rd-gen hardware added by Jarod.
+ * Initial port from lirc driver to ir-core drivery by Jarod, based
+ * partially on a port to an earlier proposed IR infrastructure by
+ * Jon Smirl, which included enhancements and simplifications to the
+ * incoming IR buffer parsing routines.
+ *
+ *
+ * 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/device.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/usb.h>
+#include <linux/usb/input.h>
+#include <media/rc-core.h>
+
+#define DRIVER_VERSION	"1.91"
+#define DRIVER_AUTHOR	"Jarod Wilson <jarod@wilsonet.com>"
+#define DRIVER_DESC	"Windows Media Center Ed. eHome Infrared Transceiver " \
+			"device driver"
+#define DRIVER_NAME	"mceusb"
+
+#define USB_BUFLEN		32 /* USB reception buffer length */
+#define USB_CTRL_MSG_SZ		2  /* Size of usb ctrl msg on gen1 hw */
+#define MCE_G1_INIT_MSGS	40 /* Init messages on gen1 hw to throw out */
+
+/* MCE constants */
+#define MCE_CMDBUF_SIZE		384  /* MCE Command buffer length */
+#define MCE_TIME_UNIT		50   /* Approx 50us resolution */
+#define MCE_CODE_LENGTH		5    /* Normal length of packet (with header) */
+#define MCE_PACKET_SIZE		4    /* Normal length of packet (without header) */
+#define MCE_IRDATA_HEADER	0x84 /* Actual header format is 0x80 + num_bytes */
+#define MCE_IRDATA_TRAILER	0x80 /* End of IR data */
+#define MCE_TX_HEADER_LENGTH	3    /* # of bytes in the initializing tx header */
+#define MCE_MAX_CHANNELS	2    /* Two transmitters, hardware dependent? */
+#define MCE_DEFAULT_TX_MASK	0x03 /* Vals: TX1=0x01, TX2=0x02, ALL=0x03 */
+#define MCE_PULSE_BIT		0x80 /* Pulse bit, MSB set == PULSE else SPACE */
+#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 */
+
+/* Sub-commands, which follow MCE_COMMAND_HEADER or MCE_HW_CMD_HEADER */
+#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 */
+
+
+/* module parameters */
+#ifdef CONFIG_USB_DEBUG
+static int debug = 1;
+#else
+static int debug;
+#endif
+
+/* general constants */
+#define SEND_FLAG_IN_PROGRESS	1
+#define SEND_FLAG_COMPLETE	2
+#define RECV_FLAG_IN_PROGRESS	3
+#define RECV_FLAG_COMPLETE	4
+
+#define MCEUSB_RX		1
+#define MCEUSB_TX		2
+
+#define VENDOR_PHILIPS		0x0471
+#define VENDOR_SMK		0x0609
+#define VENDOR_TATUNG		0x1460
+#define VENDOR_GATEWAY		0x107b
+#define VENDOR_SHUTTLE		0x1308
+#define VENDOR_SHUTTLE2		0x051c
+#define VENDOR_MITSUMI		0x03ee
+#define VENDOR_TOPSEED		0x1784
+#define VENDOR_RICAVISION	0x179d
+#define VENDOR_ITRON		0x195d
+#define VENDOR_FIC		0x1509
+#define VENDOR_LG		0x043e
+#define VENDOR_MICROSOFT	0x045e
+#define VENDOR_FORMOSA		0x147a
+#define VENDOR_FINTEK		0x1934
+#define VENDOR_PINNACLE		0x2304
+#define VENDOR_ECS		0x1019
+#define VENDOR_WISTRON		0x0fb8
+#define VENDOR_COMPRO		0x185b
+#define VENDOR_NORTHSTAR	0x04eb
+#define VENDOR_REALTEK		0x0bda
+#define VENDOR_TIVO		0x105a
+#define VENDOR_CONEXANT		0x0572
+
+enum mceusb_model_type {
+	MCE_GEN2 = 0,		/* Most boards */
+	MCE_GEN1,
+	MCE_GEN3,
+	MCE_GEN2_TX_INV,
+	POLARIS_EVK,
+	CX_HYBRID_TV,
+	MULTIFUNCTION,
+};
+
+struct mceusb_model {
+	u32 mce_gen1:1;
+	u32 mce_gen2:1;
+	u32 mce_gen3:1;
+	u32 tx_mask_normal:1;
+	u32 no_tx:1;
+
+	int ir_intfnum;
+
+	const char *rc_map;	/* Allow specify a per-board map */
+	const char *name;	/* per-board name */
+};
+
+static const struct mceusb_model mceusb_model[] = {
+	[MCE_GEN1] = {
+		.mce_gen1 = 1,
+		.tx_mask_normal = 1,
+	},
+	[MCE_GEN2] = {
+		.mce_gen2 = 1,
+	},
+	[MCE_GEN2_TX_INV] = {
+		.mce_gen2 = 1,
+		.tx_mask_normal = 1,
+	},
+	[MCE_GEN3] = {
+		.mce_gen3 = 1,
+		.tx_mask_normal = 1,
+	},
+	[POLARIS_EVK] = {
+		/*
+		 * In fact, the EVK is shipped without
+		 * remotes, but we should have something handy,
+		 * to allow testing it
+		 */
+		.rc_map = RC_MAP_RC5_HAUPPAUGE_NEW,
+		.name = "Conexant Hybrid TV (cx231xx) MCE IR",
+	},
+	[CX_HYBRID_TV] = {
+		.no_tx = 1, /* tx isn't wired up at all */
+		.name = "Conexant Hybrid TV (cx231xx) MCE IR",
+	},
+	[MULTIFUNCTION] = {
+		.mce_gen2 = 1,
+		.ir_intfnum = 2,
+	},
+};
+
+static struct usb_device_id mceusb_dev_table[] = {
+	/* Original Microsoft MCE IR Transceiver (often HP-branded) */
+	{ USB_DEVICE(VENDOR_MICROSOFT, 0x006d),
+	  .driver_info = MCE_GEN1 },
+	/* Philips Infrared Transceiver - Sahara branded */
+	{ USB_DEVICE(VENDOR_PHILIPS, 0x0608) },
+	/* Philips Infrared Transceiver - HP branded */
+	{ USB_DEVICE(VENDOR_PHILIPS, 0x060c),
+	  .driver_info = MCE_GEN2_TX_INV },
+	/* Philips SRM5100 */
+	{ USB_DEVICE(VENDOR_PHILIPS, 0x060d) },
+	/* Philips Infrared Transceiver - Omaura */
+	{ USB_DEVICE(VENDOR_PHILIPS, 0x060f) },
+	/* Philips Infrared Transceiver - Spinel plus */
+	{ USB_DEVICE(VENDOR_PHILIPS, 0x0613) },
+	/* Philips eHome Infrared Transceiver */
+	{ USB_DEVICE(VENDOR_PHILIPS, 0x0815) },
+	/* Philips/Spinel plus IR transceiver for ASUS */
+	{ USB_DEVICE(VENDOR_PHILIPS, 0x206c) },
+	/* Philips/Spinel plus IR transceiver for ASUS */
+	{ USB_DEVICE(VENDOR_PHILIPS, 0x2088) },
+	/* Realtek MCE IR Receiver and card reader */
+	{ USB_DEVICE(VENDOR_REALTEK, 0x0161),
+	  .driver_info = MULTIFUNCTION },
+	/* SMK/Toshiba G83C0004D410 */
+	{ USB_DEVICE(VENDOR_SMK, 0x031d),
+	  .driver_info = MCE_GEN2_TX_INV },
+	/* SMK eHome Infrared Transceiver (Sony VAIO) */
+	{ USB_DEVICE(VENDOR_SMK, 0x0322),
+	  .driver_info = MCE_GEN2_TX_INV },
+	/* bundled with Hauppauge PVR-150 */
+	{ USB_DEVICE(VENDOR_SMK, 0x0334),
+	  .driver_info = MCE_GEN2_TX_INV },
+	/* SMK eHome Infrared Transceiver */
+	{ USB_DEVICE(VENDOR_SMK, 0x0338) },
+	/* Tatung eHome Infrared Transceiver */
+	{ USB_DEVICE(VENDOR_TATUNG, 0x9150) },
+	/* Shuttle eHome Infrared Transceiver */
+	{ USB_DEVICE(VENDOR_SHUTTLE, 0xc001) },
+	/* Shuttle eHome Infrared Transceiver */
+	{ USB_DEVICE(VENDOR_SHUTTLE2, 0xc001) },
+	/* Gateway eHome Infrared Transceiver */
+	{ USB_DEVICE(VENDOR_GATEWAY, 0x3009) },
+	/* Mitsumi */
+	{ USB_DEVICE(VENDOR_MITSUMI, 0x2501) },
+	/* Topseed eHome Infrared Transceiver */
+	{ USB_DEVICE(VENDOR_TOPSEED, 0x0001),
+	  .driver_info = MCE_GEN2_TX_INV },
+	/* Topseed HP eHome Infrared Transceiver */
+	{ USB_DEVICE(VENDOR_TOPSEED, 0x0006),
+	  .driver_info = MCE_GEN2_TX_INV },
+	/* Topseed eHome Infrared Transceiver */
+	{ USB_DEVICE(VENDOR_TOPSEED, 0x0007),
+	  .driver_info = MCE_GEN2_TX_INV },
+	/* Topseed eHome Infrared Transceiver */
+	{ USB_DEVICE(VENDOR_TOPSEED, 0x0008),
+	  .driver_info = MCE_GEN3 },
+	/* Topseed eHome Infrared Transceiver */
+	{ USB_DEVICE(VENDOR_TOPSEED, 0x000a),
+	  .driver_info = MCE_GEN2_TX_INV },
+	/* Topseed eHome Infrared Transceiver */
+	{ USB_DEVICE(VENDOR_TOPSEED, 0x0011),
+	  .driver_info = MCE_GEN2_TX_INV },
+	/* Ricavision internal Infrared Transceiver */
+	{ USB_DEVICE(VENDOR_RICAVISION, 0x0010) },
+	/* Itron ione Libra Q-11 */
+	{ USB_DEVICE(VENDOR_ITRON, 0x7002) },
+	/* FIC eHome Infrared Transceiver */
+	{ USB_DEVICE(VENDOR_FIC, 0x9242) },
+	/* LG eHome Infrared Transceiver */
+	{ USB_DEVICE(VENDOR_LG, 0x9803) },
+	/* Microsoft MCE Infrared Transceiver */
+	{ USB_DEVICE(VENDOR_MICROSOFT, 0x00a0) },
+	/* Formosa eHome Infrared Transceiver */
+	{ USB_DEVICE(VENDOR_FORMOSA, 0xe015) },
+	/* Formosa21 / eHome Infrared Receiver */
+	{ USB_DEVICE(VENDOR_FORMOSA, 0xe016) },
+	/* Formosa aim / Trust MCE Infrared Receiver */
+	{ USB_DEVICE(VENDOR_FORMOSA, 0xe017) },
+	/* Formosa Industrial Computing / Beanbag Emulation Device */
+	{ USB_DEVICE(VENDOR_FORMOSA, 0xe018) },
+	/* Formosa21 / eHome Infrared Receiver */
+	{ USB_DEVICE(VENDOR_FORMOSA, 0xe03a) },
+	/* Formosa Industrial Computing AIM IR605/A */
+	{ USB_DEVICE(VENDOR_FORMOSA, 0xe03c) },
+	/* Formosa Industrial Computing */
+	{ USB_DEVICE(VENDOR_FORMOSA, 0xe03e) },
+	/* Fintek eHome Infrared Transceiver (HP branded) */
+	{ USB_DEVICE(VENDOR_FINTEK, 0x5168) },
+	/* Fintek eHome Infrared Transceiver */
+	{ USB_DEVICE(VENDOR_FINTEK, 0x0602) },
+	/* Fintek eHome Infrared Transceiver (in the AOpen MP45) */
+	{ USB_DEVICE(VENDOR_FINTEK, 0x0702) },
+	/* Pinnacle Remote Kit */
+	{ USB_DEVICE(VENDOR_PINNACLE, 0x0225),
+	  .driver_info = MCE_GEN3 },
+	/* Elitegroup Computer Systems IR */
+	{ USB_DEVICE(VENDOR_ECS, 0x0f38) },
+	/* Wistron Corp. eHome Infrared Receiver */
+	{ USB_DEVICE(VENDOR_WISTRON, 0x0002) },
+	/* Compro K100 */
+	{ USB_DEVICE(VENDOR_COMPRO, 0x3020) },
+	/* Compro K100 v2 */
+	{ USB_DEVICE(VENDOR_COMPRO, 0x3082) },
+	/* Northstar Systems, Inc. eHome Infrared Transceiver */
+	{ USB_DEVICE(VENDOR_NORTHSTAR, 0xe004) },
+	/* TiVo PC IR Receiver */
+	{ USB_DEVICE(VENDOR_TIVO, 0x2000) },
+	/* Conexant Hybrid TV "Shelby" Polaris SDK */
+	{ USB_DEVICE(VENDOR_CONEXANT, 0x58a1),
+	  .driver_info = POLARIS_EVK },
+	/* Conexant Hybrid TV RDU253S Polaris */
+	{ USB_DEVICE(VENDOR_CONEXANT, 0x58a5),
+	  .driver_info = CX_HYBRID_TV },
+	/* Terminating entry */
+	{ }
+};
+
+/* data structure for each usb transceiver */
+struct mceusb_dev {
+	/* ir-core bits */
+	struct rc_dev *rc;
+
+	/* optional features we can enable */
+	bool carrier_report_enabled;
+	bool learning_enabled;
+
+	/* core device bits */
+	struct device *dev;
+
+	/* usb */
+	struct usb_device *usbdev;
+	struct urb *urb_in;
+	struct usb_endpoint_descriptor *usb_ep_in;
+	struct usb_endpoint_descriptor *usb_ep_out;
+
+	/* buffers and dma */
+	unsigned char *buf_in;
+	unsigned int len_in;
+	dma_addr_t dma_in;
+	dma_addr_t dma_out;
+
+	enum {
+		CMD_HEADER = 0,
+		SUBCMD,
+		CMD_DATA,
+		PARSE_IRDATA,
+	} parser_state;
+
+	u8 cmd, rem;		/* Remaining IR data bytes in packet */
+
+	struct {
+		u32 connected:1;
+		u32 tx_mask_normal:1;
+		u32 microsoft_gen1:1;
+		u32 no_tx:1;
+	} flags;
+
+	/* transmit support */
+	int send_flags;
+	u32 carrier;
+	unsigned char tx_mask;
+
+	char name[128];
+	char phys[64];
+	enum mceusb_model_type model;
+};
+
+/*
+ * 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};
+/* 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 int mceusb_cmdsize(u8 cmd, u8 subcmd)
+{
+	int datasize = 0;
+
+	switch (cmd) {
+	case MCE_COMMAND_NULL:
+		if (subcmd == MCE_HW_CMD_HEADER)
+			datasize = 1;
+		break;
+	case MCE_HW_CMD_HEADER:
+		switch (subcmd) {
+		case MCE_CMD_G_REVISION:
+			datasize = 2;
+			break;
+		}
+	case MCE_COMMAND_HEADER:
+		switch (subcmd) {
+		case MCE_CMD_UNKNOWN:
+		case MCE_CMD_S_CARRIER:
+		case MCE_CMD_S_TIMEOUT:
+		case MCE_RSP_PULSE_COUNT:
+			datasize = 2;
+			break;
+		case MCE_CMD_SIG_END:
+		case MCE_CMD_S_TXMASK:
+		case MCE_CMD_S_RXSENSOR:
+			datasize = 1;
+			break;
+		}
+	}
+	return datasize;
+}
+
+static void mceusb_dev_printdata(struct mceusb_dev *ir, char *buf,
+				 int offset, int len, bool out)
+{
+	char codes[USB_BUFLEN * 3 + 1];
+	char inout[9];
+	u8 cmd, subcmd, data1, data2;
+	struct device *dev = ir->dev;
+	int i, start, skip = 0;
+
+	if (!debug)
+		return;
+
+	/* skip meaningless 0xb1 0x60 header bytes on orig receiver */
+	if (ir->flags.microsoft_gen1 && !out && !offset)
+		skip = 2;
+
+	if (len <= skip)
+		return;
+
+	for (i = 0; i < len && i < USB_BUFLEN; i++)
+		snprintf(codes + i * 3, 4, "%02x ", buf[i + offset] & 0xff);
+
+	dev_info(dev, "%sx data: %s(length=%d)\n",
+		 (out ? "t" : "r"), codes, len);
+
+	if (out)
+		strcpy(inout, "Request\0");
+	else
+		strcpy(inout, "Got\0");
+
+	start  = offset + skip;
+	cmd    = buf[start] & 0xff;
+	subcmd = buf[start + 1] & 0xff;
+	data1  = buf[start + 2] & 0xff;
+	data2  = buf[start + 3] & 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");
+		else
+			dev_info(dev, "Unknown command 0x%02x 0x%02x\n",
+				 cmd, subcmd);
+		break;
+	case MCE_HW_CMD_HEADER:
+		switch (subcmd) {
+		case MCE_CMD_G_REVISION:
+			if (len == 2)
+				dev_info(dev, "Get hw/sw rev?\n");
+			else
+				dev_info(dev, "hw/sw rev 0x%02x 0x%02x "
+					 "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");
+			break;
+		case MCE_RSP_CMD_INVALID:
+			dev_info(dev, "Previous command not supported\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:
+		switch (subcmd) {
+		case MCE_CMD_SIG_END:
+			dev_info(dev, "End of signal\n");
+			break;
+		case MCE_CMD_PING:
+			dev_info(dev, "Ping\n");
+			break;
+		case MCE_CMD_UNKNOWN:
+			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);
+			break;
+		case MCE_CMD_G_CARRIER:
+			dev_info(dev, "Get carrier mode and freq\n");
+			break;
+		case MCE_CMD_S_TXMASK:
+			dev_info(dev, "%s transmit blaster mask of 0x%02x\n",
+				 inout, data1);
+			break;
+		case MCE_CMD_S_TIMEOUT:
+			/* value is in units of 50us, so x*50/100 or x/2 ms */
+			dev_info(dev, "%s receive timeout of %d ms\n",
+				 inout, ((data1 << 8) | data2) / 2);
+			break;
+		case MCE_CMD_G_TIMEOUT:
+			dev_info(dev, "Get receive timeout\n");
+			break;
+		case MCE_CMD_G_TXMASK:
+			dev_info(dev, "Get transmit blaster mask\n");
+			break;
+		case MCE_CMD_S_RXSENSOR:
+			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 */
+			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");
+			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);
+			break;
+		}
+		break;
+	default:
+		break;
+	}
+
+	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))
+		dev_info(dev, "Raw IR data, %d pulse/space samples\n", ir->rem);
+}
+
+static void mce_async_callback(struct urb *urb, struct pt_regs *regs)
+{
+	struct mceusb_dev *ir;
+	int len;
+
+	if (!urb)
+		return;
+
+	ir = urb->context;
+	if (ir) {
+		len = urb->actual_length;
+
+		dev_dbg(ir->dev, "callback called (status=%d len=%d)\n",
+			urb->status, len);
+
+		mceusb_dev_printdata(ir, urb->transfer_buffer, 0, len, true);
+	}
+
+}
+
+/* request incoming or send outgoing usb packet - used to initialize remote */
+static void mce_request_packet(struct mceusb_dev *ir,
+			       struct usb_endpoint_descriptor *ep,
+			       unsigned char *data, int size, int urb_type)
+{
+	int res;
+	struct urb *async_urb;
+	struct device *dev = ir->dev;
+	unsigned char *async_buf;
+
+	if (urb_type == MCEUSB_TX) {
+		async_urb = usb_alloc_urb(0, GFP_KERNEL);
+		if (unlikely(!async_urb)) {
+			dev_err(dev, "Error, couldn't allocate urb!\n");
+			return;
+		}
+
+		async_buf = kzalloc(size, GFP_KERNEL);
+		if (!async_buf) {
+			dev_err(dev, "Error, couldn't allocate buf!\n");
+			usb_free_urb(async_urb);
+			return;
+		}
+
+		/* outbound data */
+		usb_fill_int_urb(async_urb, ir->usbdev,
+			usb_sndintpipe(ir->usbdev, ep->bEndpointAddress),
+			async_buf, size, (usb_complete_t)mce_async_callback,
+			ir, ep->bInterval);
+		memcpy(async_buf, data, size);
+
+	} else if (urb_type == MCEUSB_RX) {
+		/* standard request */
+		async_urb = ir->urb_in;
+		ir->send_flags = RECV_FLAG_IN_PROGRESS;
+
+	} else {
+		dev_err(dev, "Error! Unknown urb type %d\n", urb_type);
+		return;
+	}
+
+	dev_dbg(dev, "receive request called (size=%#x)\n", size);
+
+	async_urb->transfer_buffer_length = size;
+	async_urb->dev = ir->usbdev;
+
+	res = usb_submit_urb(async_urb, GFP_ATOMIC);
+	if (res) {
+		dev_dbg(dev, "receive request FAILED! (res=%d)\n", res);
+		return;
+	}
+	dev_dbg(dev, "receive request complete (res=%d)\n", res);
+}
+
+static void mce_async_out(struct mceusb_dev *ir, unsigned char *data, int size)
+{
+	mce_request_packet(ir, ir->usb_ep_out, data, size, MCEUSB_TX);
+}
+
+static void mce_sync_in(struct mceusb_dev *ir, unsigned char *data, int size)
+{
+	mce_request_packet(ir, ir->usb_ep_in, data, size, MCEUSB_RX);
+}
+
+/* Send data out the IR blaster port(s) */
+static int mceusb_tx_ir(struct rc_dev *dev, int *txbuf, u32 n)
+{
+	struct mceusb_dev *ir = dev->priv;
+	int i, ret = 0;
+	int count, cmdcount = 0;
+	unsigned char *cmdbuf; /* MCE command buffer */
+	long signal_duration = 0; /* Singnal length in us */
+	struct timeval start_time, end_time;
+
+	do_gettimeofday(&start_time);
+
+	count = n / sizeof(int);
+
+	cmdbuf = kzalloc(sizeof(int) * MCE_CMDBUF_SIZE, GFP_KERNEL);
+	if (!cmdbuf)
+		return -ENOMEM;
+
+	/* MCE tx init header */
+	cmdbuf[cmdcount++] = MCE_COMMAND_HEADER;
+	cmdbuf[cmdcount++] = MCE_CMD_S_TXMASK;
+	cmdbuf[cmdcount++] = ir->tx_mask;
+
+	/* Generate mce packet data */
+	for (i = 0; (i < count) && (cmdcount < MCE_CMDBUF_SIZE); i++) {
+		signal_duration += txbuf[i];
+		txbuf[i] = txbuf[i] / MCE_TIME_UNIT;
+
+		do { /* loop to support long pulses/spaces > 127*50us=6.35ms */
+
+			/* Insert mce packet header every 4th entry */
+			if ((cmdcount < MCE_CMDBUF_SIZE) &&
+			    (cmdcount - MCE_TX_HEADER_LENGTH) %
+			     MCE_CODE_LENGTH == 0)
+				cmdbuf[cmdcount++] = MCE_IRDATA_HEADER;
+
+			/* Insert mce packet data */
+			if (cmdcount < MCE_CMDBUF_SIZE)
+				cmdbuf[cmdcount++] =
+					(txbuf[i] < MCE_PULSE_BIT ?
+					 txbuf[i] : MCE_MAX_PULSE_LENGTH) |
+					 (i & 1 ? 0x00 : MCE_PULSE_BIT);
+			else {
+				ret = -EINVAL;
+				goto out;
+			}
+
+		} while ((txbuf[i] > MCE_MAX_PULSE_LENGTH) &&
+			 (txbuf[i] -= MCE_MAX_PULSE_LENGTH));
+	}
+
+	/* Fix packet length in last header */
+	cmdbuf[cmdcount - (cmdcount - MCE_TX_HEADER_LENGTH) % MCE_CODE_LENGTH] =
+		MCE_COMMAND_IRDATA + (cmdcount - MCE_TX_HEADER_LENGTH) %
+		MCE_CODE_LENGTH - 1;
+
+	/* Check if we have room for the empty packet at the end */
+	if (cmdcount >= MCE_CMDBUF_SIZE) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	/* All mce commands end with an empty packet (0x80) */
+	cmdbuf[cmdcount++] = MCE_IRDATA_TRAILER;
+
+	/* Transmit the command to the mce device */
+	mce_async_out(ir, cmdbuf, cmdcount);
+
+	/*
+	 * The lircd gap calculation expects the write function to
+	 * wait the time it takes for the ircommand to be sent before
+	 * it returns.
+	 */
+	do_gettimeofday(&end_time);
+	signal_duration -= (end_time.tv_usec - start_time.tv_usec) +
+			   (end_time.tv_sec - start_time.tv_sec) * 1000000;
+
+	/* delay with the closest number of ticks */
+	set_current_state(TASK_INTERRUPTIBLE);
+	schedule_timeout(usecs_to_jiffies(signal_duration));
+
+out:
+	kfree(cmdbuf);
+	return ret ? ret : n;
+}
+
+/* Sets active IR outputs -- mce devices typically have two */
+static int mceusb_set_tx_mask(struct rc_dev *dev, u32 mask)
+{
+	struct mceusb_dev *ir = dev->priv;
+
+	if (ir->flags.tx_mask_normal)
+		ir->tx_mask = mask;
+	else
+		ir->tx_mask = (mask != MCE_DEFAULT_TX_MASK ?
+				mask ^ MCE_DEFAULT_TX_MASK : mask) << 1;
+
+	return 0;
+}
+
+/* Sets the send carrier frequency and mode */
+static int mceusb_set_tx_carrier(struct rc_dev *dev, u32 carrier)
+{
+	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 };
+
+	/* Carrier has changed */
+	if (ir->carrier != carrier) {
+
+		if (carrier == 0) {
+			ir->carrier = carrier;
+			cmdbuf[2] = MCE_CMD_SIG_END;
+			cmdbuf[3] = MCE_IRDATA_TRAILER;
+			dev_dbg(ir->dev, "%s: disabling carrier "
+				"modulation\n", __func__);
+			mce_async_out(ir, cmdbuf, sizeof(cmdbuf));
+			return carrier;
+		}
+
+		for (prescaler = 0; prescaler < 4; ++prescaler) {
+			divisor = (clk >> (2 * prescaler)) / carrier;
+			if (divisor <= 0xff) {
+				ir->carrier = carrier;
+				cmdbuf[2] = prescaler;
+				cmdbuf[3] = divisor;
+				dev_dbg(ir->dev, "%s: requesting %u HZ "
+					"carrier\n", __func__, carrier);
+
+				/* Transmit new carrier to mce device */
+				mce_async_out(ir, cmdbuf, sizeof(cmdbuf));
+				return carrier;
+			}
+		}
+
+		return -EINVAL;
+
+	}
+
+	return carrier;
+}
+
+/*
+ * We don't do anything but print debug spew for many of the command bits
+ * we receive from the hardware, but some of them are useful information
+ * we want to store so that we can use them.
+ */
+static void mceusb_handle_command(struct mceusb_dev *ir, int index)
+{
+	u8 hi = ir->buf_in[index + 1] & 0xff;
+	u8 lo = ir->buf_in[index + 2] & 0xff;
+
+	switch (ir->buf_in[index]) {
+	/* 2-byte return value commands */
+	case MCE_CMD_S_TIMEOUT:
+		ir->rc->timeout = US_TO_NS((hi << 8 | lo) / 2);
+		break;
+
+	/* 1-byte return value commands */
+	case MCE_CMD_S_TXMASK:
+		ir->tx_mask = hi;
+		break;
+	case MCE_CMD_S_RXSENSOR:
+		ir->learning_enabled = (hi == 0x02);
+		break;
+	default:
+		break;
+	}
+}
+
+static void mceusb_process_ir_data(struct mceusb_dev *ir, int buf_len)
+{
+	DEFINE_IR_RAW_EVENT(rawir);
+	int i = 0;
+
+	/* skip meaningless 0xb1 0x60 header bytes on orig receiver */
+	if (ir->flags.microsoft_gen1)
+		i = 2;
+
+	/* if there's no data, just return now */
+	if (buf_len <= i)
+		return;
+
+	for (; i < buf_len; i++) {
+		switch (ir->parser_state) {
+		case SUBCMD:
+			ir->rem = mceusb_cmdsize(ir->cmd, ir->buf_in[i]);
+			mceusb_dev_printdata(ir, ir->buf_in, i - 1,
+					     ir->rem + 2, false);
+			mceusb_handle_command(ir, i);
+			ir->parser_state = CMD_DATA;
+			break;
+		case PARSE_IRDATA:
+			ir->rem--;
+			init_ir_raw_event(&rawir);
+			rawir.pulse = ((ir->buf_in[i] & MCE_PULSE_BIT) != 0);
+			rawir.duration = (ir->buf_in[i] & MCE_PULSE_MASK)
+					 * US_TO_NS(MCE_TIME_UNIT);
+
+			dev_dbg(ir->dev, "Storing %s with duration %d\n",
+				rawir.pulse ? "pulse" : "space",
+				rawir.duration);
+
+			ir_raw_event_store_with_filter(ir->rc, &rawir);
+			break;
+		case CMD_DATA:
+			ir->rem--;
+			break;
+		case CMD_HEADER:
+			/* 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) !=
+			     MCE_COMMAND_IRDATA)) {
+				ir->parser_state = SUBCMD;
+				continue;
+			}
+			ir->rem = (ir->cmd & MCE_PACKET_LENGTH_MASK);
+			mceusb_dev_printdata(ir, ir->buf_in,
+					     i, ir->rem + 1, false);
+			if (ir->rem)
+				ir->parser_state = PARSE_IRDATA;
+			else
+				ir_raw_event_reset(ir->rc);
+			break;
+		}
+
+		if (ir->parser_state != CMD_HEADER && !ir->rem)
+			ir->parser_state = CMD_HEADER;
+	}
+	dev_dbg(ir->dev, "processed IR data, calling ir_raw_event_handle\n");
+	ir_raw_event_handle(ir->rc);
+}
+
+static void mceusb_dev_recv(struct urb *urb, struct pt_regs *regs)
+{
+	struct mceusb_dev *ir;
+	int buf_len;
+
+	if (!urb)
+		return;
+
+	ir = urb->context;
+	if (!ir) {
+		usb_unlink_urb(urb);
+		return;
+	}
+
+	buf_len = urb->actual_length;
+
+	if (ir->send_flags == RECV_FLAG_IN_PROGRESS) {
+		ir->send_flags = SEND_FLAG_COMPLETE;
+		dev_dbg(ir->dev, "setup answer received %d bytes\n",
+			buf_len);
+	}
+
+	switch (urb->status) {
+	/* success */
+	case 0:
+		mceusb_process_ir_data(ir, buf_len);
+		break;
+
+	case -ECONNRESET:
+	case -ENOENT:
+	case -ESHUTDOWN:
+		usb_unlink_urb(urb);
+		return;
+
+	case -EPIPE:
+	default:
+		dev_dbg(ir->dev, "Error: urb status = %d\n", urb->status);
+		break;
+	}
+
+	usb_submit_urb(urb, GFP_ATOMIC);
+}
+
+static void mceusb_gen1_init(struct mceusb_dev *ir)
+{
+	int ret;
+	int maxp = ir->len_in;
+	struct device *dev = ir->dev;
+	char *data;
+
+	data = kzalloc(USB_CTRL_MSG_SZ, GFP_KERNEL);
+	if (!data) {
+		dev_err(dev, "%s: memory allocation failed!\n", __func__);
+		return;
+	}
+
+	/*
+	 * This is a strange one. Windows issues a set address to the device
+	 * on the receive control pipe and expect a certain value pair back
+	 */
+	ret = usb_control_msg(ir->usbdev, usb_rcvctrlpipe(ir->usbdev, 0),
+			      USB_REQ_SET_ADDRESS, USB_TYPE_VENDOR, 0, 0,
+			      data, USB_CTRL_MSG_SZ, HZ * 3);
+	dev_dbg(dev, "%s - ret = %d\n", __func__, ret);
+	dev_dbg(dev, "%s - data[0] = %d, data[1] = %d\n",
+		__func__, data[0], data[1]);
+
+	/* set feature: bit rate 38400 bps */
+	ret = usb_control_msg(ir->usbdev, usb_sndctrlpipe(ir->usbdev, 0),
+			      USB_REQ_SET_FEATURE, USB_TYPE_VENDOR,
+			      0xc04e, 0x0000, NULL, 0, HZ * 3);
+
+	dev_dbg(dev, "%s - ret = %d\n", __func__, ret);
+
+	/* bRequest 4: set char length to 8 bits */
+	ret = usb_control_msg(ir->usbdev, usb_sndctrlpipe(ir->usbdev, 0),
+			      4, USB_TYPE_VENDOR,
+			      0x0808, 0x0000, NULL, 0, HZ * 3);
+	dev_dbg(dev, "%s - retB = %d\n", __func__, ret);
+
+	/* bRequest 2: set handshaking to use DTR/DSR */
+	ret = usb_control_msg(ir->usbdev, usb_sndctrlpipe(ir->usbdev, 0),
+			      2, USB_TYPE_VENDOR,
+			      0x0000, 0x0100, NULL, 0, HZ * 3);
+	dev_dbg(dev, "%s - retC = %d\n", __func__, ret);
+
+	/* device reset */
+	mce_async_out(ir, DEVICE_RESET, sizeof(DEVICE_RESET));
+	mce_sync_in(ir, NULL, maxp);
+
+	/* get hw/sw revision? */
+	mce_async_out(ir, GET_REVISION, sizeof(GET_REVISION));
+	mce_sync_in(ir, NULL, maxp);
+
+	kfree(data);
+};
+
+static void mceusb_gen2_init(struct mceusb_dev *ir)
+{
+	int maxp = ir->len_in;
+
+	/* device reset */
+	mce_async_out(ir, DEVICE_RESET, sizeof(DEVICE_RESET));
+	mce_sync_in(ir, NULL, maxp);
+
+	/* get hw/sw revision? */
+	mce_async_out(ir, GET_REVISION, sizeof(GET_REVISION));
+	mce_sync_in(ir, NULL, maxp);
+
+	/* unknown what the next two actually return... */
+	mce_async_out(ir, GET_UNKNOWN, sizeof(GET_UNKNOWN));
+	mce_sync_in(ir, NULL, maxp);
+	mce_async_out(ir, GET_UNKNOWN2, sizeof(GET_UNKNOWN2));
+	mce_sync_in(ir, NULL, maxp);
+}
+
+static void mceusb_get_parameters(struct mceusb_dev *ir)
+{
+	int maxp = ir->len_in;
+
+	/* get the carrier and frequency */
+	mce_async_out(ir, GET_CARRIER_FREQ, sizeof(GET_CARRIER_FREQ));
+	mce_sync_in(ir, NULL, maxp);
+
+	if (!ir->flags.no_tx) {
+		/* get the transmitter bitmask */
+		mce_async_out(ir, GET_TX_BITMASK, sizeof(GET_TX_BITMASK));
+		mce_sync_in(ir, NULL, maxp);
+	}
+
+	/* get receiver timeout value */
+	mce_async_out(ir, GET_RX_TIMEOUT, sizeof(GET_RX_TIMEOUT));
+	mce_sync_in(ir, NULL, maxp);
+
+	/* get receiver sensor setting */
+	mce_async_out(ir, GET_RX_SENSOR, sizeof(GET_RX_SENSOR));
+	mce_sync_in(ir, NULL, maxp);
+}
+
+static struct rc_dev *mceusb_init_rc_dev(struct mceusb_dev *ir)
+{
+	struct device *dev = ir->dev;
+	struct rc_dev *rc;
+	int ret;
+
+	rc = rc_allocate_device();
+	if (!rc) {
+		dev_err(dev, "remote dev allocation failed\n");
+		goto out;
+	}
+
+	snprintf(ir->name, sizeof(ir->name), "%s (%04x:%04x)",
+		 mceusb_model[ir->model].name ?
+			mceusb_model[ir->model].name :
+			"Media Center Ed. eHome Infrared Remote Transceiver",
+		 le16_to_cpu(ir->usbdev->descriptor.idVendor),
+		 le16_to_cpu(ir->usbdev->descriptor.idProduct));
+
+	usb_make_path(ir->usbdev, ir->phys, sizeof(ir->phys));
+
+	rc->input_name = ir->name;
+	rc->input_phys = ir->phys;
+	usb_to_input_id(ir->usbdev, &rc->input_id);
+	rc->dev.parent = dev;
+	rc->priv = ir;
+	rc->driver_type = RC_DRIVER_IR_RAW;
+	rc->allowed_protos = RC_TYPE_ALL;
+	rc->timeout = US_TO_NS(1000);
+	if (!ir->flags.no_tx) {
+		rc->s_tx_mask = mceusb_set_tx_mask;
+		rc->s_tx_carrier = mceusb_set_tx_carrier;
+		rc->tx_ir = mceusb_tx_ir;
+	}
+	rc->driver_name = DRIVER_NAME;
+	rc->map_name = mceusb_model[ir->model].rc_map ?
+			mceusb_model[ir->model].rc_map : RC_MAP_RC6_MCE;
+
+	ret = rc_register_device(rc);
+	if (ret < 0) {
+		dev_err(dev, "remote dev registration failed\n");
+		goto out;
+	}
+
+	return rc;
+
+out:
+	rc_free_device(rc);
+	return NULL;
+}
+
+static int __devinit mceusb_dev_probe(struct usb_interface *intf,
+				      const struct usb_device_id *id)
+{
+	struct usb_device *dev = interface_to_usbdev(intf);
+	struct usb_host_interface *idesc;
+	struct usb_endpoint_descriptor *ep = NULL;
+	struct usb_endpoint_descriptor *ep_in = NULL;
+	struct usb_endpoint_descriptor *ep_out = NULL;
+	struct mceusb_dev *ir = NULL;
+	int pipe, maxp, i;
+	char buf[63], name[128] = "";
+	enum mceusb_model_type model = id->driver_info;
+	bool is_gen3;
+	bool is_microsoft_gen1;
+	bool tx_mask_normal;
+	int ir_intfnum;
+
+	dev_dbg(&intf->dev, "%s called\n", __func__);
+
+	idesc  = intf->cur_altsetting;
+
+	is_gen3 = mceusb_model[model].mce_gen3;
+	is_microsoft_gen1 = mceusb_model[model].mce_gen1;
+	tx_mask_normal = mceusb_model[model].tx_mask_normal;
+	ir_intfnum = mceusb_model[model].ir_intfnum;
+
+	/* There are multi-function devices with non-IR interfaces */
+	if (idesc->desc.bInterfaceNumber != ir_intfnum)
+		return -ENODEV;
+
+	/* step through the endpoints to find first bulk in and out endpoint */
+	for (i = 0; i < idesc->desc.bNumEndpoints; ++i) {
+		ep = &idesc->endpoint[i].desc;
+
+		if ((ep_in == NULL)
+			&& ((ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
+			    == USB_DIR_IN)
+			&& (((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
+			    == USB_ENDPOINT_XFER_BULK)
+			|| ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
+			    == USB_ENDPOINT_XFER_INT))) {
+
+			ep_in = ep;
+			ep_in->bmAttributes = USB_ENDPOINT_XFER_INT;
+			ep_in->bInterval = 1;
+			dev_dbg(&intf->dev, "acceptable inbound endpoint "
+				"found\n");
+		}
+
+		if ((ep_out == NULL)
+			&& ((ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
+			    == USB_DIR_OUT)
+			&& (((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
+			    == USB_ENDPOINT_XFER_BULK)
+			|| ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
+			    == USB_ENDPOINT_XFER_INT))) {
+
+			ep_out = ep;
+			ep_out->bmAttributes = USB_ENDPOINT_XFER_INT;
+			ep_out->bInterval = 1;
+			dev_dbg(&intf->dev, "acceptable outbound endpoint "
+				"found\n");
+		}
+	}
+	if (ep_in == NULL) {
+		dev_dbg(&intf->dev, "inbound and/or endpoint not found\n");
+		return -ENODEV;
+	}
+
+	pipe = usb_rcvintpipe(dev, ep_in->bEndpointAddress);
+	maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
+
+	ir = kzalloc(sizeof(struct mceusb_dev), GFP_KERNEL);
+	if (!ir)
+		goto mem_alloc_fail;
+
+	ir->buf_in = usb_alloc_coherent(dev, maxp, GFP_ATOMIC, &ir->dma_in);
+	if (!ir->buf_in)
+		goto buf_in_alloc_fail;
+
+	ir->urb_in = usb_alloc_urb(0, GFP_KERNEL);
+	if (!ir->urb_in)
+		goto urb_in_alloc_fail;
+
+	ir->usbdev = dev;
+	ir->dev = &intf->dev;
+	ir->len_in = maxp;
+	ir->flags.microsoft_gen1 = is_microsoft_gen1;
+	ir->flags.tx_mask_normal = tx_mask_normal;
+	ir->flags.no_tx = mceusb_model[model].no_tx;
+	ir->model = model;
+
+	/* Saving usb interface data for use by the transmitter routine */
+	ir->usb_ep_in = ep_in;
+	ir->usb_ep_out = ep_out;
+
+	if (dev->descriptor.iManufacturer
+	    && usb_string(dev, dev->descriptor.iManufacturer,
+			  buf, sizeof(buf)) > 0)
+		strlcpy(name, buf, sizeof(name));
+	if (dev->descriptor.iProduct
+	    && usb_string(dev, dev->descriptor.iProduct,
+			  buf, sizeof(buf)) > 0)
+		snprintf(name + strlen(name), sizeof(name) - strlen(name),
+			 " %s", buf);
+
+	ir->rc = mceusb_init_rc_dev(ir);
+	if (!ir->rc)
+		goto rc_dev_fail;
+
+	/* flush buffers on the device */
+	mce_sync_in(ir, NULL, maxp);
+	mce_sync_in(ir, NULL, maxp);
+
+	/* wire up inbound data handler */
+	usb_fill_int_urb(ir->urb_in, dev, pipe, ir->buf_in,
+		maxp, (usb_complete_t) mceusb_dev_recv, ir, ep_in->bInterval);
+	ir->urb_in->transfer_dma = ir->dma_in;
+	ir->urb_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
+	/* initialize device */
+	if (ir->flags.microsoft_gen1)
+		mceusb_gen1_init(ir);
+	else if (!is_gen3)
+		mceusb_gen2_init(ir);
+
+	mceusb_get_parameters(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);
+
+	return 0;
+
+	/* Error-handling path */
+rc_dev_fail:
+	usb_free_urb(ir->urb_in);
+urb_in_alloc_fail:
+	usb_free_coherent(dev, maxp, ir->buf_in, ir->dma_in);
+buf_in_alloc_fail:
+	kfree(ir);
+mem_alloc_fail:
+	dev_err(&intf->dev, "%s: device setup failed!\n", __func__);
+
+	return -ENOMEM;
+}
+
+
+static void __devexit mceusb_dev_disconnect(struct usb_interface *intf)
+{
+	struct usb_device *dev = interface_to_usbdev(intf);
+	struct mceusb_dev *ir = usb_get_intfdata(intf);
+
+	usb_set_intfdata(intf, NULL);
+
+	if (!ir)
+		return;
+
+	ir->usbdev = NULL;
+	rc_unregister_device(ir->rc);
+	usb_kill_urb(ir->urb_in);
+	usb_free_urb(ir->urb_in);
+	usb_free_coherent(dev, ir->len_in, ir->buf_in, ir->dma_in);
+
+	kfree(ir);
+}
+
+static int mceusb_dev_suspend(struct usb_interface *intf, pm_message_t message)
+{
+	struct mceusb_dev *ir = usb_get_intfdata(intf);
+	dev_info(ir->dev, "suspend\n");
+	usb_kill_urb(ir->urb_in);
+	return 0;
+}
+
+static int mceusb_dev_resume(struct usb_interface *intf)
+{
+	struct mceusb_dev *ir = usb_get_intfdata(intf);
+	dev_info(ir->dev, "resume\n");
+	if (usb_submit_urb(ir->urb_in, GFP_ATOMIC))
+		return -EIO;
+	return 0;
+}
+
+static struct usb_driver mceusb_dev_driver = {
+	.name =		DRIVER_NAME,
+	.probe =	mceusb_dev_probe,
+	.disconnect =	mceusb_dev_disconnect,
+	.suspend =	mceusb_dev_suspend,
+	.resume =	mceusb_dev_resume,
+	.reset_resume =	mceusb_dev_resume,
+	.id_table =	mceusb_dev_table
+};
+
+static int __init mceusb_dev_init(void)
+{
+	int ret;
+
+	ret = usb_register(&mceusb_dev_driver);
+	if (ret < 0)
+		printk(KERN_ERR DRIVER_NAME
+		       ": usb register failed, result = %d\n", ret);
+
+	return ret;
+}
+
+static void __exit mceusb_dev_exit(void)
+{
+	usb_deregister(&mceusb_dev_driver);
+}
+
+module_init(mceusb_dev_init);
+module_exit(mceusb_dev_exit);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(usb, mceusb_dev_table);
+
+module_param(debug, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Debug enabled or not");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/nuvoton-cir.c linux-libre-2.6.38-gnu1/drivers/media/rc/nuvoton-cir.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/nuvoton-cir.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/nuvoton-cir.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,1245 @@
+/*
+ * Driver for Nuvoton Technology Corporation w83667hg/w83677hg-i CIR
+ *
+ * Copyright (C) 2010 Jarod Wilson <jarod@redhat.com>
+ * Copyright (C) 2009 Nuvoton PS Team
+ *
+ * Special thanks to Nuvoton for providing hardware, spec sheets and
+ * sample code upon which portions of this driver are based. Indirect
+ * thanks also to Maxim Levitsky, whose ene_ir driver this driver is
+ * modeled after.
+ *
+ * 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/module.h>
+#include <linux/pnp.h>
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <media/rc-core.h>
+#include <linux/pci_ids.h>
+
+#include "nuvoton-cir.h"
+
+static char *chip_id = "w836x7hg";
+
+/* write val to config reg */
+static inline void nvt_cr_write(struct nvt_dev *nvt, u8 val, u8 reg)
+{
+	outb(reg, nvt->cr_efir);
+	outb(val, nvt->cr_efdr);
+}
+
+/* read val from config reg */
+static inline u8 nvt_cr_read(struct nvt_dev *nvt, u8 reg)
+{
+	outb(reg, nvt->cr_efir);
+	return inb(nvt->cr_efdr);
+}
+
+/* update config register bit without changing other bits */
+static inline void nvt_set_reg_bit(struct nvt_dev *nvt, u8 val, u8 reg)
+{
+	u8 tmp = nvt_cr_read(nvt, reg) | val;
+	nvt_cr_write(nvt, tmp, reg);
+}
+
+/* clear config register bit without changing other bits */
+static inline void nvt_clear_reg_bit(struct nvt_dev *nvt, u8 val, u8 reg)
+{
+	u8 tmp = nvt_cr_read(nvt, reg) & ~val;
+	nvt_cr_write(nvt, tmp, reg);
+}
+
+/* enter extended function mode */
+static inline void nvt_efm_enable(struct nvt_dev *nvt)
+{
+	/* Enabling Extended Function Mode explicitly requires writing 2x */
+	outb(EFER_EFM_ENABLE, nvt->cr_efir);
+	outb(EFER_EFM_ENABLE, nvt->cr_efir);
+}
+
+/* exit extended function mode */
+static inline void nvt_efm_disable(struct nvt_dev *nvt)
+{
+	outb(EFER_EFM_DISABLE, nvt->cr_efir);
+}
+
+/*
+ * When you want to address a specific logical device, write its logical
+ * device number to CR_LOGICAL_DEV_SEL, then enable/disable by writing
+ * 0x1/0x0 respectively to CR_LOGICAL_DEV_EN.
+ */
+static inline void nvt_select_logical_dev(struct nvt_dev *nvt, u8 ldev)
+{
+	outb(CR_LOGICAL_DEV_SEL, nvt->cr_efir);
+	outb(ldev, nvt->cr_efdr);
+}
+
+/* write val to cir config register */
+static inline void nvt_cir_reg_write(struct nvt_dev *nvt, u8 val, u8 offset)
+{
+	outb(val, nvt->cir_addr + offset);
+}
+
+/* read val from cir config register */
+static u8 nvt_cir_reg_read(struct nvt_dev *nvt, u8 offset)
+{
+	u8 val;
+
+	val = inb(nvt->cir_addr + offset);
+
+	return val;
+}
+
+/* write val to cir wake register */
+static inline void nvt_cir_wake_reg_write(struct nvt_dev *nvt,
+					  u8 val, u8 offset)
+{
+	outb(val, nvt->cir_wake_addr + offset);
+}
+
+/* read val from cir wake config register */
+static u8 nvt_cir_wake_reg_read(struct nvt_dev *nvt, u8 offset)
+{
+	u8 val;
+
+	val = inb(nvt->cir_wake_addr + offset);
+
+	return val;
+}
+
+#define pr_reg(text, ...) \
+	printk(KERN_INFO KBUILD_MODNAME ": " text, ## __VA_ARGS__)
+
+/* dump current cir register contents */
+static void cir_dump_regs(struct nvt_dev *nvt)
+{
+	nvt_efm_enable(nvt);
+	nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR);
+
+	pr_reg("%s: Dump CIR logical device registers:\n", NVT_DRIVER_NAME);
+	pr_reg(" * CR CIR ACTIVE :   0x%x\n",
+	       nvt_cr_read(nvt, CR_LOGICAL_DEV_EN));
+	pr_reg(" * CR CIR BASE ADDR: 0x%x\n",
+	       (nvt_cr_read(nvt, CR_CIR_BASE_ADDR_HI) << 8) |
+		nvt_cr_read(nvt, CR_CIR_BASE_ADDR_LO));
+	pr_reg(" * CR CIR IRQ NUM:   0x%x\n",
+	       nvt_cr_read(nvt, CR_CIR_IRQ_RSRC));
+
+	nvt_efm_disable(nvt);
+
+	pr_reg("%s: Dump CIR registers:\n", NVT_DRIVER_NAME);
+	pr_reg(" * IRCON:     0x%x\n", nvt_cir_reg_read(nvt, CIR_IRCON));
+	pr_reg(" * IRSTS:     0x%x\n", nvt_cir_reg_read(nvt, CIR_IRSTS));
+	pr_reg(" * IREN:      0x%x\n", nvt_cir_reg_read(nvt, CIR_IREN));
+	pr_reg(" * RXFCONT:   0x%x\n", nvt_cir_reg_read(nvt, CIR_RXFCONT));
+	pr_reg(" * CP:        0x%x\n", nvt_cir_reg_read(nvt, CIR_CP));
+	pr_reg(" * CC:        0x%x\n", nvt_cir_reg_read(nvt, CIR_CC));
+	pr_reg(" * SLCH:      0x%x\n", nvt_cir_reg_read(nvt, CIR_SLCH));
+	pr_reg(" * SLCL:      0x%x\n", nvt_cir_reg_read(nvt, CIR_SLCL));
+	pr_reg(" * FIFOCON:   0x%x\n", nvt_cir_reg_read(nvt, CIR_FIFOCON));
+	pr_reg(" * IRFIFOSTS: 0x%x\n", nvt_cir_reg_read(nvt, CIR_IRFIFOSTS));
+	pr_reg(" * SRXFIFO:   0x%x\n", nvt_cir_reg_read(nvt, CIR_SRXFIFO));
+	pr_reg(" * TXFCONT:   0x%x\n", nvt_cir_reg_read(nvt, CIR_TXFCONT));
+	pr_reg(" * STXFIFO:   0x%x\n", nvt_cir_reg_read(nvt, CIR_STXFIFO));
+	pr_reg(" * FCCH:      0x%x\n", nvt_cir_reg_read(nvt, CIR_FCCH));
+	pr_reg(" * FCCL:      0x%x\n", nvt_cir_reg_read(nvt, CIR_FCCL));
+	pr_reg(" * IRFSM:     0x%x\n", nvt_cir_reg_read(nvt, CIR_IRFSM));
+}
+
+/* dump current cir wake register contents */
+static void cir_wake_dump_regs(struct nvt_dev *nvt)
+{
+	u8 i, fifo_len;
+
+	nvt_efm_enable(nvt);
+	nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR_WAKE);
+
+	pr_reg("%s: Dump CIR WAKE logical device registers:\n",
+	       NVT_DRIVER_NAME);
+	pr_reg(" * CR CIR WAKE ACTIVE :   0x%x\n",
+	       nvt_cr_read(nvt, CR_LOGICAL_DEV_EN));
+	pr_reg(" * CR CIR WAKE BASE ADDR: 0x%x\n",
+	       (nvt_cr_read(nvt, CR_CIR_BASE_ADDR_HI) << 8) |
+		nvt_cr_read(nvt, CR_CIR_BASE_ADDR_LO));
+	pr_reg(" * CR CIR WAKE IRQ NUM:   0x%x\n",
+	       nvt_cr_read(nvt, CR_CIR_IRQ_RSRC));
+
+	nvt_efm_disable(nvt);
+
+	pr_reg("%s: Dump CIR WAKE registers\n", NVT_DRIVER_NAME);
+	pr_reg(" * IRCON:          0x%x\n",
+	       nvt_cir_wake_reg_read(nvt, CIR_WAKE_IRCON));
+	pr_reg(" * IRSTS:          0x%x\n",
+	       nvt_cir_wake_reg_read(nvt, CIR_WAKE_IRSTS));
+	pr_reg(" * IREN:           0x%x\n",
+	       nvt_cir_wake_reg_read(nvt, CIR_WAKE_IREN));
+	pr_reg(" * FIFO CMP DEEP:  0x%x\n",
+	       nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFO_CMP_DEEP));
+	pr_reg(" * FIFO CMP TOL:   0x%x\n",
+	       nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFO_CMP_TOL));
+	pr_reg(" * FIFO COUNT:     0x%x\n",
+	       nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFO_COUNT));
+	pr_reg(" * SLCH:           0x%x\n",
+	       nvt_cir_wake_reg_read(nvt, CIR_WAKE_SLCH));
+	pr_reg(" * SLCL:           0x%x\n",
+	       nvt_cir_wake_reg_read(nvt, CIR_WAKE_SLCL));
+	pr_reg(" * FIFOCON:        0x%x\n",
+	       nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFOCON));
+	pr_reg(" * SRXFSTS:        0x%x\n",
+	       nvt_cir_wake_reg_read(nvt, CIR_WAKE_SRXFSTS));
+	pr_reg(" * SAMPLE RX FIFO: 0x%x\n",
+	       nvt_cir_wake_reg_read(nvt, CIR_WAKE_SAMPLE_RX_FIFO));
+	pr_reg(" * WR FIFO DATA:   0x%x\n",
+	       nvt_cir_wake_reg_read(nvt, CIR_WAKE_WR_FIFO_DATA));
+	pr_reg(" * RD FIFO ONLY:   0x%x\n",
+	       nvt_cir_wake_reg_read(nvt, CIR_WAKE_RD_FIFO_ONLY));
+	pr_reg(" * RD FIFO ONLY IDX: 0x%x\n",
+	       nvt_cir_wake_reg_read(nvt, CIR_WAKE_RD_FIFO_ONLY_IDX));
+	pr_reg(" * FIFO IGNORE:    0x%x\n",
+	       nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFO_IGNORE));
+	pr_reg(" * IRFSM:          0x%x\n",
+	       nvt_cir_wake_reg_read(nvt, CIR_WAKE_IRFSM));
+
+	fifo_len = nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFO_COUNT);
+	pr_reg("%s: Dump CIR WAKE FIFO (len %d)\n", NVT_DRIVER_NAME, fifo_len);
+	pr_reg("* Contents = ");
+	for (i = 0; i < fifo_len; i++)
+		printk(KERN_CONT "%02x ",
+		       nvt_cir_wake_reg_read(nvt, CIR_WAKE_RD_FIFO_ONLY));
+	printk(KERN_CONT "\n");
+}
+
+/* detect hardware features */
+static int nvt_hw_detect(struct nvt_dev *nvt)
+{
+	unsigned long flags;
+	u8 chip_major, chip_minor;
+	int ret = 0;
+
+	nvt_efm_enable(nvt);
+
+	/* Check if we're wired for the alternate EFER setup */
+	chip_major = nvt_cr_read(nvt, CR_CHIP_ID_HI);
+	if (chip_major == 0xff) {
+		nvt->cr_efir = CR_EFIR2;
+		nvt->cr_efdr = CR_EFDR2;
+		nvt_efm_enable(nvt);
+		chip_major = nvt_cr_read(nvt, CR_CHIP_ID_HI);
+	}
+
+	chip_minor = nvt_cr_read(nvt, CR_CHIP_ID_LO);
+	nvt_dbg("%s: chip id: 0x%02x 0x%02x", chip_id, chip_major, chip_minor);
+
+	if (chip_major != CHIP_ID_HIGH ||
+	    (chip_minor != CHIP_ID_LOW && chip_minor != CHIP_ID_LOW2)) {
+		nvt_pr(KERN_ERR, "%s: unsupported chip, id: 0x%02x 0x%02x",
+		       chip_id, chip_major, chip_minor);
+		ret = -ENODEV;
+	}
+
+	nvt_efm_disable(nvt);
+
+	spin_lock_irqsave(&nvt->nvt_lock, flags);
+	nvt->chip_major = chip_major;
+	nvt->chip_minor = chip_minor;
+	spin_unlock_irqrestore(&nvt->nvt_lock, flags);
+
+	return ret;
+}
+
+static void nvt_cir_ldev_init(struct nvt_dev *nvt)
+{
+	u8 val;
+
+	/* output pin selection (Pin95=CIRRX, Pin96=CIRTX1, WB enabled */
+	val = nvt_cr_read(nvt, CR_OUTPUT_PIN_SEL);
+	val &= OUTPUT_PIN_SEL_MASK;
+	val |= (OUTPUT_ENABLE_CIR | OUTPUT_ENABLE_CIRWB);
+	nvt_cr_write(nvt, val, CR_OUTPUT_PIN_SEL);
+
+	/* Select CIR logical device and enable */
+	nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR);
+	nvt_cr_write(nvt, LOGICAL_DEV_ENABLE, CR_LOGICAL_DEV_EN);
+
+	nvt_cr_write(nvt, nvt->cir_addr >> 8, CR_CIR_BASE_ADDR_HI);
+	nvt_cr_write(nvt, nvt->cir_addr & 0xff, CR_CIR_BASE_ADDR_LO);
+
+	nvt_cr_write(nvt, nvt->cir_irq, CR_CIR_IRQ_RSRC);
+
+	nvt_dbg("CIR initialized, base io port address: 0x%lx, irq: %d",
+		nvt->cir_addr, nvt->cir_irq);
+}
+
+static void nvt_cir_wake_ldev_init(struct nvt_dev *nvt)
+{
+	/* Select ACPI logical device, enable it and CIR Wake */
+	nvt_select_logical_dev(nvt, LOGICAL_DEV_ACPI);
+	nvt_cr_write(nvt, LOGICAL_DEV_ENABLE, CR_LOGICAL_DEV_EN);
+
+	/* Enable CIR Wake via PSOUT# (Pin60) */
+	nvt_set_reg_bit(nvt, CIR_WAKE_ENABLE_BIT, CR_ACPI_CIR_WAKE);
+
+	/* enable cir interrupt of mouse/keyboard IRQ event */
+	nvt_set_reg_bit(nvt, CIR_INTR_MOUSE_IRQ_BIT, CR_ACPI_IRQ_EVENTS);
+
+	/* enable pme interrupt of cir wakeup event */
+	nvt_set_reg_bit(nvt, PME_INTR_CIR_PASS_BIT, CR_ACPI_IRQ_EVENTS2);
+
+	/* Select CIR Wake logical device and enable */
+	nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR_WAKE);
+	nvt_cr_write(nvt, LOGICAL_DEV_ENABLE, CR_LOGICAL_DEV_EN);
+
+	nvt_cr_write(nvt, nvt->cir_wake_addr >> 8, CR_CIR_BASE_ADDR_HI);
+	nvt_cr_write(nvt, nvt->cir_wake_addr & 0xff, CR_CIR_BASE_ADDR_LO);
+
+	nvt_cr_write(nvt, nvt->cir_wake_irq, CR_CIR_IRQ_RSRC);
+
+	nvt_dbg("CIR Wake initialized, base io port address: 0x%lx, irq: %d",
+		nvt->cir_wake_addr, nvt->cir_wake_irq);
+}
+
+/* clear out the hardware's cir rx fifo */
+static void nvt_clear_cir_fifo(struct nvt_dev *nvt)
+{
+	u8 val;
+
+	val = nvt_cir_reg_read(nvt, CIR_FIFOCON);
+	nvt_cir_reg_write(nvt, val | CIR_FIFOCON_RXFIFOCLR, CIR_FIFOCON);
+}
+
+/* clear out the hardware's cir wake rx fifo */
+static void nvt_clear_cir_wake_fifo(struct nvt_dev *nvt)
+{
+	u8 val;
+
+	val = nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFOCON);
+	nvt_cir_wake_reg_write(nvt, val | CIR_WAKE_FIFOCON_RXFIFOCLR,
+			       CIR_WAKE_FIFOCON);
+}
+
+/* clear out the hardware's cir tx fifo */
+static void nvt_clear_tx_fifo(struct nvt_dev *nvt)
+{
+	u8 val;
+
+	val = nvt_cir_reg_read(nvt, CIR_FIFOCON);
+	nvt_cir_reg_write(nvt, val | CIR_FIFOCON_TXFIFOCLR, CIR_FIFOCON);
+}
+
+/* enable RX Trigger Level Reach and Packet End interrupts */
+static void nvt_set_cir_iren(struct nvt_dev *nvt)
+{
+	u8 iren;
+
+	iren = CIR_IREN_RTR | CIR_IREN_PE;
+	nvt_cir_reg_write(nvt, iren, CIR_IREN);
+}
+
+static void nvt_cir_regs_init(struct nvt_dev *nvt)
+{
+	/* set sample limit count (PE interrupt raised when reached) */
+	nvt_cir_reg_write(nvt, CIR_RX_LIMIT_COUNT >> 8, CIR_SLCH);
+	nvt_cir_reg_write(nvt, CIR_RX_LIMIT_COUNT & 0xff, CIR_SLCL);
+
+	/* set fifo irq trigger levels */
+	nvt_cir_reg_write(nvt, CIR_FIFOCON_TX_TRIGGER_LEV |
+			  CIR_FIFOCON_RX_TRIGGER_LEV, CIR_FIFOCON);
+
+	/*
+	 * Enable TX and RX, specify carrier on = low, off = high, and set
+	 * sample period (currently 50us)
+	 */
+	nvt_cir_reg_write(nvt,
+			  CIR_IRCON_TXEN | CIR_IRCON_RXEN |
+			  CIR_IRCON_RXINV | CIR_IRCON_SAMPLE_PERIOD_SEL,
+			  CIR_IRCON);
+
+	/* clear hardware rx and tx fifos */
+	nvt_clear_cir_fifo(nvt);
+	nvt_clear_tx_fifo(nvt);
+
+	/* clear any and all stray interrupts */
+	nvt_cir_reg_write(nvt, 0xff, CIR_IRSTS);
+
+	/* and finally, enable interrupts */
+	nvt_set_cir_iren(nvt);
+}
+
+static void nvt_cir_wake_regs_init(struct nvt_dev *nvt)
+{
+	/* set number of bytes needed for wake from s3 (default 65) */
+	nvt_cir_wake_reg_write(nvt, CIR_WAKE_FIFO_CMP_BYTES,
+			       CIR_WAKE_FIFO_CMP_DEEP);
+
+	/* set tolerance/variance allowed per byte during wake compare */
+	nvt_cir_wake_reg_write(nvt, CIR_WAKE_CMP_TOLERANCE,
+			       CIR_WAKE_FIFO_CMP_TOL);
+
+	/* set sample limit count (PE interrupt raised when reached) */
+	nvt_cir_wake_reg_write(nvt, CIR_RX_LIMIT_COUNT >> 8, CIR_WAKE_SLCH);
+	nvt_cir_wake_reg_write(nvt, CIR_RX_LIMIT_COUNT & 0xff, CIR_WAKE_SLCL);
+
+	/* set cir wake fifo rx trigger level (currently 67) */
+	nvt_cir_wake_reg_write(nvt, CIR_WAKE_FIFOCON_RX_TRIGGER_LEV,
+			       CIR_WAKE_FIFOCON);
+
+	/*
+	 * Enable TX and RX, specific carrier on = low, off = high, and set
+	 * sample period (currently 50us)
+	 */
+	nvt_cir_wake_reg_write(nvt, CIR_WAKE_IRCON_MODE0 | CIR_WAKE_IRCON_RXEN |
+			       CIR_WAKE_IRCON_R | CIR_WAKE_IRCON_RXINV |
+			       CIR_WAKE_IRCON_SAMPLE_PERIOD_SEL,
+			       CIR_WAKE_IRCON);
+
+	/* clear cir wake rx fifo */
+	nvt_clear_cir_wake_fifo(nvt);
+
+	/* clear any and all stray interrupts */
+	nvt_cir_wake_reg_write(nvt, 0xff, CIR_WAKE_IRSTS);
+}
+
+static void nvt_enable_wake(struct nvt_dev *nvt)
+{
+	nvt_efm_enable(nvt);
+
+	nvt_select_logical_dev(nvt, LOGICAL_DEV_ACPI);
+	nvt_set_reg_bit(nvt, CIR_WAKE_ENABLE_BIT, CR_ACPI_CIR_WAKE);
+	nvt_set_reg_bit(nvt, CIR_INTR_MOUSE_IRQ_BIT, CR_ACPI_IRQ_EVENTS);
+	nvt_set_reg_bit(nvt, PME_INTR_CIR_PASS_BIT, CR_ACPI_IRQ_EVENTS2);
+
+	nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR_WAKE);
+	nvt_cr_write(nvt, LOGICAL_DEV_ENABLE, CR_LOGICAL_DEV_EN);
+
+	nvt_efm_disable(nvt);
+
+	nvt_cir_wake_reg_write(nvt, CIR_WAKE_IRCON_MODE0 | CIR_WAKE_IRCON_RXEN |
+			       CIR_WAKE_IRCON_R | CIR_WAKE_IRCON_RXINV |
+			       CIR_WAKE_IRCON_SAMPLE_PERIOD_SEL,
+			       CIR_WAKE_IRCON);
+	nvt_cir_wake_reg_write(nvt, 0xff, CIR_WAKE_IRSTS);
+	nvt_cir_wake_reg_write(nvt, 0, CIR_WAKE_IREN);
+}
+
+/* rx carrier detect only works in learning mode, must be called w/nvt_lock */
+static u32 nvt_rx_carrier_detect(struct nvt_dev *nvt)
+{
+	u32 count, carrier, duration = 0;
+	int i;
+
+	count = nvt_cir_reg_read(nvt, CIR_FCCL) |
+		nvt_cir_reg_read(nvt, CIR_FCCH) << 8;
+
+	for (i = 0; i < nvt->pkts; i++) {
+		if (nvt->buf[i] & BUF_PULSE_BIT)
+			duration += nvt->buf[i] & BUF_LEN_MASK;
+	}
+
+	duration *= SAMPLE_PERIOD;
+
+	if (!count || !duration) {
+		nvt_pr(KERN_NOTICE, "Unable to determine carrier! (c:%u, d:%u)",
+		       count, duration);
+		return 0;
+	}
+
+	carrier = MS_TO_NS(count) / duration;
+
+	if ((carrier > MAX_CARRIER) || (carrier < MIN_CARRIER))
+		nvt_dbg("WTF? Carrier frequency out of range!");
+
+	nvt_dbg("Carrier frequency: %u (count %u, duration %u)",
+		carrier, count, duration);
+
+	return carrier;
+}
+
+/*
+ * set carrier frequency
+ *
+ * set carrier on 2 registers: CP & CC
+ * always set CP as 0x81
+ * set CC by SPEC, CC = 3MHz/carrier - 1
+ */
+static int nvt_set_tx_carrier(struct rc_dev *dev, u32 carrier)
+{
+	struct nvt_dev *nvt = dev->priv;
+	u16 val;
+
+	nvt_cir_reg_write(nvt, 1, CIR_CP);
+	val = 3000000 / (carrier) - 1;
+	nvt_cir_reg_write(nvt, val & 0xff, CIR_CC);
+
+	nvt_dbg("cp: 0x%x cc: 0x%x\n",
+		nvt_cir_reg_read(nvt, CIR_CP), nvt_cir_reg_read(nvt, CIR_CC));
+
+	return 0;
+}
+
+/*
+ * nvt_tx_ir
+ *
+ * 1) clean TX fifo first (handled by AP)
+ * 2) copy data from user space
+ * 3) disable RX interrupts, enable TX interrupts: TTR & TFU
+ * 4) send 9 packets to TX FIFO to open TTR
+ * in interrupt_handler:
+ * 5) send all data out
+ * go back to write():
+ * 6) disable TX interrupts, re-enable RX interupts
+ *
+ * The key problem of this function is user space data may larger than
+ * driver's data buf length. So nvt_tx_ir() will only copy TX_BUF_LEN data to
+ * buf, and keep current copied data buf num in cur_buf_num. But driver's buf
+ * number may larger than TXFCONT (0xff). So in interrupt_handler, it has to
+ * set TXFCONT as 0xff, until buf_count less than 0xff.
+ */
+static int nvt_tx_ir(struct rc_dev *dev, int *txbuf, u32 n)
+{
+	struct nvt_dev *nvt = dev->priv;
+	unsigned long flags;
+	size_t cur_count;
+	unsigned int i;
+	u8 iren;
+	int ret;
+
+	spin_lock_irqsave(&nvt->tx.lock, flags);
+
+	if (n >= TX_BUF_LEN) {
+		nvt->tx.buf_count = cur_count = TX_BUF_LEN;
+		ret = TX_BUF_LEN;
+	} else {
+		nvt->tx.buf_count = cur_count = n;
+		ret = n;
+	}
+
+	memcpy(nvt->tx.buf, txbuf, nvt->tx.buf_count);
+
+	nvt->tx.cur_buf_num = 0;
+
+	/* save currently enabled interrupts */
+	iren = nvt_cir_reg_read(nvt, CIR_IREN);
+
+	/* now disable all interrupts, save TFU & TTR */
+	nvt_cir_reg_write(nvt, CIR_IREN_TFU | CIR_IREN_TTR, CIR_IREN);
+
+	nvt->tx.tx_state = ST_TX_REPLY;
+
+	nvt_cir_reg_write(nvt, CIR_FIFOCON_TX_TRIGGER_LEV_8 |
+			  CIR_FIFOCON_RXFIFOCLR, CIR_FIFOCON);
+
+	/* trigger TTR interrupt by writing out ones, (yes, it's ugly) */
+	for (i = 0; i < 9; i++)
+		nvt_cir_reg_write(nvt, 0x01, CIR_STXFIFO);
+
+	spin_unlock_irqrestore(&nvt->tx.lock, flags);
+
+	wait_event(nvt->tx.queue, nvt->tx.tx_state == ST_TX_REQUEST);
+
+	spin_lock_irqsave(&nvt->tx.lock, flags);
+	nvt->tx.tx_state = ST_TX_NONE;
+	spin_unlock_irqrestore(&nvt->tx.lock, flags);
+
+	/* restore enabled interrupts to prior state */
+	nvt_cir_reg_write(nvt, iren, CIR_IREN);
+
+	return ret;
+}
+
+/* dump contents of the last rx buffer we got from the hw rx fifo */
+static void nvt_dump_rx_buf(struct nvt_dev *nvt)
+{
+	int i;
+
+	printk(KERN_DEBUG "%s (len %d): ", __func__, nvt->pkts);
+	for (i = 0; (i < nvt->pkts) && (i < RX_BUF_LEN); i++)
+		printk(KERN_CONT "0x%02x ", nvt->buf[i]);
+	printk(KERN_CONT "\n");
+}
+
+/*
+ * Process raw data in rx driver buffer, store it in raw IR event kfifo,
+ * trigger decode when appropriate.
+ *
+ * We get IR data samples one byte at a time. If the msb is set, its a pulse,
+ * otherwise its a space. The lower 7 bits are the count of SAMPLE_PERIOD
+ * (default 50us) intervals for that pulse/space. A discrete signal is
+ * followed by a series of 0x7f packets, then either 0x7<something> or 0x80
+ * to signal more IR coming (repeats) or end of IR, respectively. We store
+ * sample data in the raw event kfifo until we see 0x7<something> (except f)
+ * or 0x80, at which time, we trigger a decode operation.
+ */
+static void nvt_process_rx_ir_data(struct nvt_dev *nvt)
+{
+	DEFINE_IR_RAW_EVENT(rawir);
+	unsigned int count;
+	u32 carrier;
+	u8 sample;
+	int i;
+
+	nvt_dbg_verbose("%s firing", __func__);
+
+	if (debug)
+		nvt_dump_rx_buf(nvt);
+
+	if (nvt->carrier_detect_enabled)
+		carrier = nvt_rx_carrier_detect(nvt);
+
+	count = nvt->pkts;
+	nvt_dbg_verbose("Processing buffer of len %d", count);
+
+	init_ir_raw_event(&rawir);
+
+	for (i = 0; i < count; i++) {
+		nvt->pkts--;
+		sample = nvt->buf[i];
+
+		rawir.pulse = ((sample & BUF_PULSE_BIT) != 0);
+		rawir.duration = US_TO_NS((sample & BUF_LEN_MASK)
+					  * SAMPLE_PERIOD);
+
+		if ((sample & BUF_LEN_MASK) == BUF_LEN_MASK) {
+			if (nvt->rawir.pulse == rawir.pulse)
+				nvt->rawir.duration += rawir.duration;
+			else {
+				nvt->rawir.duration = rawir.duration;
+				nvt->rawir.pulse = rawir.pulse;
+			}
+			continue;
+		}
+
+		rawir.duration += nvt->rawir.duration;
+
+		init_ir_raw_event(&nvt->rawir);
+		nvt->rawir.duration = 0;
+		nvt->rawir.pulse = rawir.pulse;
+
+		if (sample == BUF_PULSE_BIT)
+			rawir.pulse = false;
+
+		if (rawir.duration) {
+			nvt_dbg("Storing %s with duration %d",
+				rawir.pulse ? "pulse" : "space",
+				rawir.duration);
+
+			ir_raw_event_store(nvt->rdev, &rawir);
+		}
+
+		/*
+		 * BUF_PULSE_BIT indicates end of IR data, BUF_REPEAT_BYTE
+		 * indicates end of IR signal, but new data incoming. In both
+		 * cases, it means we're ready to call ir_raw_event_handle
+		 */
+		if ((sample == BUF_PULSE_BIT) && nvt->pkts) {
+			nvt_dbg("Calling ir_raw_event_handle (signal end)\n");
+			ir_raw_event_handle(nvt->rdev);
+		}
+	}
+
+	nvt_dbg("Calling ir_raw_event_handle (buffer empty)\n");
+	ir_raw_event_handle(nvt->rdev);
+
+	if (nvt->pkts) {
+		nvt_dbg("Odd, pkts should be 0 now... (its %u)", nvt->pkts);
+		nvt->pkts = 0;
+	}
+
+	nvt_dbg_verbose("%s done", __func__);
+}
+
+static void nvt_handle_rx_fifo_overrun(struct nvt_dev *nvt)
+{
+	nvt_pr(KERN_WARNING, "RX FIFO overrun detected, flushing data!");
+
+	nvt->pkts = 0;
+	nvt_clear_cir_fifo(nvt);
+	ir_raw_event_reset(nvt->rdev);
+}
+
+/* copy data from hardware rx fifo into driver buffer */
+static void nvt_get_rx_ir_data(struct nvt_dev *nvt)
+{
+	unsigned long flags;
+	u8 fifocount, val;
+	unsigned int b_idx;
+	bool overrun = false;
+	int i;
+
+	/* Get count of how many bytes to read from RX FIFO */
+	fifocount = nvt_cir_reg_read(nvt, CIR_RXFCONT);
+	/* if we get 0xff, probably means the logical dev is disabled */
+	if (fifocount == 0xff)
+		return;
+	/* watch out for a fifo overrun condition */
+	else if (fifocount > RX_BUF_LEN) {
+		overrun = true;
+		fifocount = RX_BUF_LEN;
+	}
+
+	nvt_dbg("attempting to fetch %u bytes from hw rx fifo", fifocount);
+
+	spin_lock_irqsave(&nvt->nvt_lock, flags);
+
+	b_idx = nvt->pkts;
+
+	/* This should never happen, but lets check anyway... */
+	if (b_idx + fifocount > RX_BUF_LEN) {
+		nvt_process_rx_ir_data(nvt);
+		b_idx = 0;
+	}
+
+	/* Read fifocount bytes from CIR Sample RX FIFO register */
+	for (i = 0; i < fifocount; i++) {
+		val = nvt_cir_reg_read(nvt, CIR_SRXFIFO);
+		nvt->buf[b_idx + i] = val;
+	}
+
+	nvt->pkts += fifocount;
+	nvt_dbg("%s: pkts now %d", __func__, nvt->pkts);
+
+	nvt_process_rx_ir_data(nvt);
+
+	if (overrun)
+		nvt_handle_rx_fifo_overrun(nvt);
+
+	spin_unlock_irqrestore(&nvt->nvt_lock, flags);
+}
+
+static void nvt_cir_log_irqs(u8 status, u8 iren)
+{
+	nvt_pr(KERN_INFO, "IRQ 0x%02x (IREN 0x%02x) :%s%s%s%s%s%s%s%s%s",
+		status, iren,
+		status & CIR_IRSTS_RDR	? " RDR"	: "",
+		status & CIR_IRSTS_RTR	? " RTR"	: "",
+		status & CIR_IRSTS_PE	? " PE"		: "",
+		status & CIR_IRSTS_RFO	? " RFO"	: "",
+		status & CIR_IRSTS_TE	? " TE"		: "",
+		status & CIR_IRSTS_TTR	? " TTR"	: "",
+		status & CIR_IRSTS_TFU	? " TFU"	: "",
+		status & CIR_IRSTS_GH	? " GH"		: "",
+		status & ~(CIR_IRSTS_RDR | CIR_IRSTS_RTR | CIR_IRSTS_PE |
+			   CIR_IRSTS_RFO | CIR_IRSTS_TE | CIR_IRSTS_TTR |
+			   CIR_IRSTS_TFU | CIR_IRSTS_GH) ? " ?" : "");
+}
+
+static bool nvt_cir_tx_inactive(struct nvt_dev *nvt)
+{
+	unsigned long flags;
+	bool tx_inactive;
+	u8 tx_state;
+
+	spin_lock_irqsave(&nvt->tx.lock, flags);
+	tx_state = nvt->tx.tx_state;
+	spin_unlock_irqrestore(&nvt->tx.lock, flags);
+
+	tx_inactive = (tx_state == ST_TX_NONE);
+
+	return tx_inactive;
+}
+
+/* interrupt service routine for incoming and outgoing CIR data */
+static irqreturn_t nvt_cir_isr(int irq, void *data)
+{
+	struct nvt_dev *nvt = data;
+	u8 status, iren, cur_state;
+	unsigned long flags;
+
+	nvt_dbg_verbose("%s firing", __func__);
+
+	nvt_efm_enable(nvt);
+	nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR);
+	nvt_efm_disable(nvt);
+
+	/*
+	 * Get IR Status register contents. Write 1 to ack/clear
+	 *
+	 * bit: reg name      - description
+	 *   7: CIR_IRSTS_RDR - RX Data Ready
+	 *   6: CIR_IRSTS_RTR - RX FIFO Trigger Level Reach
+	 *   5: CIR_IRSTS_PE  - Packet End
+	 *   4: CIR_IRSTS_RFO - RX FIFO Overrun (RDR will also be set)
+	 *   3: CIR_IRSTS_TE  - TX FIFO Empty
+	 *   2: CIR_IRSTS_TTR - TX FIFO Trigger Level Reach
+	 *   1: CIR_IRSTS_TFU - TX FIFO Underrun
+	 *   0: CIR_IRSTS_GH  - Min Length Detected
+	 */
+	status = nvt_cir_reg_read(nvt, CIR_IRSTS);
+	if (!status) {
+		nvt_dbg_verbose("%s exiting, IRSTS 0x0", __func__);
+		nvt_cir_reg_write(nvt, 0xff, CIR_IRSTS);
+		return IRQ_RETVAL(IRQ_NONE);
+	}
+
+	/* ack/clear all irq flags we've got */
+	nvt_cir_reg_write(nvt, status, CIR_IRSTS);
+	nvt_cir_reg_write(nvt, 0, CIR_IRSTS);
+
+	/* Interrupt may be shared with CIR Wake, bail if CIR not enabled */
+	iren = nvt_cir_reg_read(nvt, CIR_IREN);
+	if (!iren) {
+		nvt_dbg_verbose("%s exiting, CIR not enabled", __func__);
+		return IRQ_RETVAL(IRQ_NONE);
+	}
+
+	if (debug)
+		nvt_cir_log_irqs(status, iren);
+
+	if (status & CIR_IRSTS_RTR) {
+		/* FIXME: add code for study/learn mode */
+		/* We only do rx if not tx'ing */
+		if (nvt_cir_tx_inactive(nvt))
+			nvt_get_rx_ir_data(nvt);
+	}
+
+	if (status & CIR_IRSTS_PE) {
+		if (nvt_cir_tx_inactive(nvt))
+			nvt_get_rx_ir_data(nvt);
+
+		spin_lock_irqsave(&nvt->nvt_lock, flags);
+
+		cur_state = nvt->study_state;
+
+		spin_unlock_irqrestore(&nvt->nvt_lock, flags);
+
+		if (cur_state == ST_STUDY_NONE)
+			nvt_clear_cir_fifo(nvt);
+	}
+
+	if (status & CIR_IRSTS_TE)
+		nvt_clear_tx_fifo(nvt);
+
+	if (status & CIR_IRSTS_TTR) {
+		unsigned int pos, count;
+		u8 tmp;
+
+		spin_lock_irqsave(&nvt->tx.lock, flags);
+
+		pos = nvt->tx.cur_buf_num;
+		count = nvt->tx.buf_count;
+
+		/* Write data into the hardware tx fifo while pos < count */
+		if (pos < count) {
+			nvt_cir_reg_write(nvt, nvt->tx.buf[pos], CIR_STXFIFO);
+			nvt->tx.cur_buf_num++;
+		/* Disable TX FIFO Trigger Level Reach (TTR) interrupt */
+		} else {
+			tmp = nvt_cir_reg_read(nvt, CIR_IREN);
+			nvt_cir_reg_write(nvt, tmp & ~CIR_IREN_TTR, CIR_IREN);
+		}
+
+		spin_unlock_irqrestore(&nvt->tx.lock, flags);
+
+	}
+
+	if (status & CIR_IRSTS_TFU) {
+		spin_lock_irqsave(&nvt->tx.lock, flags);
+		if (nvt->tx.tx_state == ST_TX_REPLY) {
+			nvt->tx.tx_state = ST_TX_REQUEST;
+			wake_up(&nvt->tx.queue);
+		}
+		spin_unlock_irqrestore(&nvt->tx.lock, flags);
+	}
+
+	nvt_dbg_verbose("%s done", __func__);
+	return IRQ_RETVAL(IRQ_HANDLED);
+}
+
+/* Interrupt service routine for CIR Wake */
+static irqreturn_t nvt_cir_wake_isr(int irq, void *data)
+{
+	u8 status, iren, val;
+	struct nvt_dev *nvt = data;
+	unsigned long flags;
+
+	nvt_dbg_wake("%s firing", __func__);
+
+	status = nvt_cir_wake_reg_read(nvt, CIR_WAKE_IRSTS);
+	if (!status)
+		return IRQ_RETVAL(IRQ_NONE);
+
+	if (status & CIR_WAKE_IRSTS_IR_PENDING)
+		nvt_clear_cir_wake_fifo(nvt);
+
+	nvt_cir_wake_reg_write(nvt, status, CIR_WAKE_IRSTS);
+	nvt_cir_wake_reg_write(nvt, 0, CIR_WAKE_IRSTS);
+
+	/* Interrupt may be shared with CIR, bail if Wake not enabled */
+	iren = nvt_cir_wake_reg_read(nvt, CIR_WAKE_IREN);
+	if (!iren) {
+		nvt_dbg_wake("%s exiting, wake not enabled", __func__);
+		return IRQ_RETVAL(IRQ_HANDLED);
+	}
+
+	if ((status & CIR_WAKE_IRSTS_PE) &&
+	    (nvt->wake_state == ST_WAKE_START)) {
+		while (nvt_cir_wake_reg_read(nvt, CIR_WAKE_RD_FIFO_ONLY_IDX)) {
+			val = nvt_cir_wake_reg_read(nvt, CIR_WAKE_RD_FIFO_ONLY);
+			nvt_dbg("setting wake up key: 0x%x", val);
+		}
+
+		nvt_cir_wake_reg_write(nvt, 0, CIR_WAKE_IREN);
+		spin_lock_irqsave(&nvt->nvt_lock, flags);
+		nvt->wake_state = ST_WAKE_FINISH;
+		spin_unlock_irqrestore(&nvt->nvt_lock, flags);
+	}
+
+	nvt_dbg_wake("%s done", __func__);
+	return IRQ_RETVAL(IRQ_HANDLED);
+}
+
+static void nvt_enable_cir(struct nvt_dev *nvt)
+{
+	/* set function enable flags */
+	nvt_cir_reg_write(nvt, CIR_IRCON_TXEN | CIR_IRCON_RXEN |
+			  CIR_IRCON_RXINV | CIR_IRCON_SAMPLE_PERIOD_SEL,
+			  CIR_IRCON);
+
+	nvt_efm_enable(nvt);
+
+	/* enable the CIR logical device */
+	nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR);
+	nvt_cr_write(nvt, LOGICAL_DEV_ENABLE, CR_LOGICAL_DEV_EN);
+
+	nvt_efm_disable(nvt);
+
+	/* clear all pending interrupts */
+	nvt_cir_reg_write(nvt, 0xff, CIR_IRSTS);
+
+	/* enable interrupts */
+	nvt_set_cir_iren(nvt);
+}
+
+static void nvt_disable_cir(struct nvt_dev *nvt)
+{
+	/* disable CIR interrupts */
+	nvt_cir_reg_write(nvt, 0, CIR_IREN);
+
+	/* clear any and all pending interrupts */
+	nvt_cir_reg_write(nvt, 0xff, CIR_IRSTS);
+
+	/* clear all function enable flags */
+	nvt_cir_reg_write(nvt, 0, CIR_IRCON);
+
+	/* clear hardware rx and tx fifos */
+	nvt_clear_cir_fifo(nvt);
+	nvt_clear_tx_fifo(nvt);
+
+	nvt_efm_enable(nvt);
+
+	/* disable the CIR logical device */
+	nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR);
+	nvt_cr_write(nvt, LOGICAL_DEV_DISABLE, CR_LOGICAL_DEV_EN);
+
+	nvt_efm_disable(nvt);
+}
+
+static int nvt_open(struct rc_dev *dev)
+{
+	struct nvt_dev *nvt = dev->priv;
+	unsigned long flags;
+
+	spin_lock_irqsave(&nvt->nvt_lock, flags);
+	nvt->in_use = true;
+	nvt_enable_cir(nvt);
+	spin_unlock_irqrestore(&nvt->nvt_lock, flags);
+
+	return 0;
+}
+
+static void nvt_close(struct rc_dev *dev)
+{
+	struct nvt_dev *nvt = dev->priv;
+	unsigned long flags;
+
+	spin_lock_irqsave(&nvt->nvt_lock, flags);
+	nvt->in_use = false;
+	nvt_disable_cir(nvt);
+	spin_unlock_irqrestore(&nvt->nvt_lock, flags);
+}
+
+/* Allocate memory, probe hardware, and initialize everything */
+static int nvt_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id)
+{
+	struct nvt_dev *nvt;
+	struct rc_dev *rdev;
+	int ret = -ENOMEM;
+
+	nvt = kzalloc(sizeof(struct nvt_dev), GFP_KERNEL);
+	if (!nvt)
+		return ret;
+
+	/* input device for IR remote (and tx) */
+	rdev = rc_allocate_device();
+	if (!rdev)
+		goto failure;
+
+	ret = -ENODEV;
+	/* validate pnp resources */
+	if (!pnp_port_valid(pdev, 0) ||
+	    pnp_port_len(pdev, 0) < CIR_IOREG_LENGTH) {
+		dev_err(&pdev->dev, "IR PNP Port not valid!\n");
+		goto failure;
+	}
+
+	if (!pnp_irq_valid(pdev, 0)) {
+		dev_err(&pdev->dev, "PNP IRQ not valid!\n");
+		goto failure;
+	}
+
+	if (!pnp_port_valid(pdev, 1) ||
+	    pnp_port_len(pdev, 1) < CIR_IOREG_LENGTH) {
+		dev_err(&pdev->dev, "Wake PNP Port not valid!\n");
+		goto failure;
+	}
+
+	nvt->cir_addr = pnp_port_start(pdev, 0);
+	nvt->cir_irq  = pnp_irq(pdev, 0);
+
+	nvt->cir_wake_addr = pnp_port_start(pdev, 1);
+	/* irq is always shared between cir and cir wake */
+	nvt->cir_wake_irq  = nvt->cir_irq;
+
+	nvt->cr_efir = CR_EFIR;
+	nvt->cr_efdr = CR_EFDR;
+
+	spin_lock_init(&nvt->nvt_lock);
+	spin_lock_init(&nvt->tx.lock);
+	init_ir_raw_event(&nvt->rawir);
+
+	ret = -EBUSY;
+	/* now claim resources */
+	if (!request_region(nvt->cir_addr,
+			    CIR_IOREG_LENGTH, NVT_DRIVER_NAME))
+		goto failure;
+
+	if (request_irq(nvt->cir_irq, nvt_cir_isr, IRQF_SHARED,
+			NVT_DRIVER_NAME, (void *)nvt))
+		goto failure;
+
+	if (!request_region(nvt->cir_wake_addr,
+			    CIR_IOREG_LENGTH, NVT_DRIVER_NAME))
+		goto failure;
+
+	if (request_irq(nvt->cir_wake_irq, nvt_cir_wake_isr, IRQF_SHARED,
+			NVT_DRIVER_NAME, (void *)nvt))
+		goto failure;
+
+	pnp_set_drvdata(pdev, nvt);
+	nvt->pdev = pdev;
+
+	init_waitqueue_head(&nvt->tx.queue);
+
+	ret = nvt_hw_detect(nvt);
+	if (ret)
+		goto failure;
+
+	/* Initialize CIR & CIR Wake Logical Devices */
+	nvt_efm_enable(nvt);
+	nvt_cir_ldev_init(nvt);
+	nvt_cir_wake_ldev_init(nvt);
+	nvt_efm_disable(nvt);
+
+	/* Initialize CIR & CIR Wake Config Registers */
+	nvt_cir_regs_init(nvt);
+	nvt_cir_wake_regs_init(nvt);
+
+	/* Set up the rc device */
+	rdev->priv = nvt;
+	rdev->driver_type = RC_DRIVER_IR_RAW;
+	rdev->allowed_protos = RC_TYPE_ALL;
+	rdev->open = nvt_open;
+	rdev->close = nvt_close;
+	rdev->tx_ir = nvt_tx_ir;
+	rdev->s_tx_carrier = nvt_set_tx_carrier;
+	rdev->input_name = "Nuvoton w836x7hg Infrared Remote Transceiver";
+	rdev->input_id.bustype = BUS_HOST;
+	rdev->input_id.vendor = PCI_VENDOR_ID_WINBOND2;
+	rdev->input_id.product = nvt->chip_major;
+	rdev->input_id.version = nvt->chip_minor;
+	rdev->driver_name = NVT_DRIVER_NAME;
+	rdev->map_name = RC_MAP_RC6_MCE;
+#if 0
+	rdev->min_timeout = XYZ;
+	rdev->max_timeout = XYZ;
+	rdev->timeout = XYZ;
+	/* rx resolution is hardwired to 50us atm, 1, 25, 100 also possible */
+	rdev->rx_resolution = XYZ;
+	/* tx bits */
+	rdev->tx_resolution = XYZ;
+#endif
+
+	ret = rc_register_device(rdev);
+	if (ret)
+		goto failure;
+
+	device_set_wakeup_capable(&pdev->dev, 1);
+	device_set_wakeup_enable(&pdev->dev, 1);
+	nvt->rdev = rdev;
+	nvt_pr(KERN_NOTICE, "driver has been successfully loaded\n");
+	if (debug) {
+		cir_dump_regs(nvt);
+		cir_wake_dump_regs(nvt);
+	}
+
+	return 0;
+
+failure:
+	if (nvt->cir_irq)
+		free_irq(nvt->cir_irq, nvt);
+	if (nvt->cir_addr)
+		release_region(nvt->cir_addr, CIR_IOREG_LENGTH);
+
+	if (nvt->cir_wake_irq)
+		free_irq(nvt->cir_wake_irq, nvt);
+	if (nvt->cir_wake_addr)
+		release_region(nvt->cir_wake_addr, CIR_IOREG_LENGTH);
+
+	rc_free_device(rdev);
+	kfree(nvt);
+
+	return ret;
+}
+
+static void __devexit nvt_remove(struct pnp_dev *pdev)
+{
+	struct nvt_dev *nvt = pnp_get_drvdata(pdev);
+	unsigned long flags;
+
+	spin_lock_irqsave(&nvt->nvt_lock, flags);
+	/* disable CIR */
+	nvt_cir_reg_write(nvt, 0, CIR_IREN);
+	nvt_disable_cir(nvt);
+	/* enable CIR Wake (for IR power-on) */
+	nvt_enable_wake(nvt);
+	spin_unlock_irqrestore(&nvt->nvt_lock, flags);
+
+	/* free resources */
+	free_irq(nvt->cir_irq, nvt);
+	free_irq(nvt->cir_wake_irq, nvt);
+	release_region(nvt->cir_addr, CIR_IOREG_LENGTH);
+	release_region(nvt->cir_wake_addr, CIR_IOREG_LENGTH);
+
+	rc_unregister_device(nvt->rdev);
+
+	kfree(nvt);
+}
+
+static int nvt_suspend(struct pnp_dev *pdev, pm_message_t state)
+{
+	struct nvt_dev *nvt = pnp_get_drvdata(pdev);
+	unsigned long flags;
+
+	nvt_dbg("%s called", __func__);
+
+	/* zero out misc state tracking */
+	spin_lock_irqsave(&nvt->nvt_lock, flags);
+	nvt->study_state = ST_STUDY_NONE;
+	nvt->wake_state = ST_WAKE_NONE;
+	spin_unlock_irqrestore(&nvt->nvt_lock, flags);
+
+	spin_lock_irqsave(&nvt->tx.lock, flags);
+	nvt->tx.tx_state = ST_TX_NONE;
+	spin_unlock_irqrestore(&nvt->tx.lock, flags);
+
+	/* disable all CIR interrupts */
+	nvt_cir_reg_write(nvt, 0, CIR_IREN);
+
+	nvt_efm_enable(nvt);
+
+	/* disable cir logical dev */
+	nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR);
+	nvt_cr_write(nvt, LOGICAL_DEV_DISABLE, CR_LOGICAL_DEV_EN);
+
+	nvt_efm_disable(nvt);
+
+	/* make sure wake is enabled */
+	nvt_enable_wake(nvt);
+
+	return 0;
+}
+
+static int nvt_resume(struct pnp_dev *pdev)
+{
+	int ret = 0;
+	struct nvt_dev *nvt = pnp_get_drvdata(pdev);
+
+	nvt_dbg("%s called", __func__);
+
+	/* open interrupt */
+	nvt_set_cir_iren(nvt);
+
+	/* Enable CIR logical device */
+	nvt_efm_enable(nvt);
+	nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR);
+	nvt_cr_write(nvt, LOGICAL_DEV_ENABLE, CR_LOGICAL_DEV_EN);
+
+	nvt_efm_disable(nvt);
+
+	nvt_cir_regs_init(nvt);
+	nvt_cir_wake_regs_init(nvt);
+
+	return ret;
+}
+
+static void nvt_shutdown(struct pnp_dev *pdev)
+{
+	struct nvt_dev *nvt = pnp_get_drvdata(pdev);
+	nvt_enable_wake(nvt);
+}
+
+static const struct pnp_device_id nvt_ids[] = {
+	{ "WEC0530", 0 },   /* CIR */
+	{ "NTN0530", 0 },   /* CIR for new chip's pnp id*/
+	{ "", 0 },
+};
+
+static struct pnp_driver nvt_driver = {
+	.name		= NVT_DRIVER_NAME,
+	.id_table	= nvt_ids,
+	.flags		= PNP_DRIVER_RES_DO_NOT_CHANGE,
+	.probe		= nvt_probe,
+	.remove		= __devexit_p(nvt_remove),
+	.suspend	= nvt_suspend,
+	.resume		= nvt_resume,
+	.shutdown	= nvt_shutdown,
+};
+
+int nvt_init(void)
+{
+	return pnp_register_driver(&nvt_driver);
+}
+
+void nvt_exit(void)
+{
+	pnp_unregister_driver(&nvt_driver);
+}
+
+module_param(debug, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Enable debugging output");
+
+MODULE_DEVICE_TABLE(pnp, nvt_ids);
+MODULE_DESCRIPTION("Nuvoton W83667HG-A & W83677HG-I CIR driver");
+
+MODULE_AUTHOR("Jarod Wilson <jarod@redhat.com>");
+MODULE_LICENSE("GPL");
+
+module_init(nvt_init);
+module_exit(nvt_exit);
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/nuvoton-cir.h linux-libre-2.6.38-gnu1/drivers/media/rc/nuvoton-cir.h
--- linux-libre-2.6.37-gnu1/drivers/media/rc/nuvoton-cir.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/nuvoton-cir.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,410 @@
+/*
+ * Driver for Nuvoton Technology Corporation w83667hg/w83677hg-i CIR
+ *
+ * Copyright (C) 2010 Jarod Wilson <jarod@redhat.com>
+ * Copyright (C) 2009 Nuvoton PS Team
+ *
+ * Special thanks to Nuvoton for providing hardware, spec sheets and
+ * sample code upon which portions of this driver are based. Indirect
+ * thanks also to Maxim Levitsky, whose ene_ir driver this driver is
+ * modeled after.
+ *
+ * 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/spinlock.h>
+#include <linux/ioctl.h>
+
+/* platform driver name to register */
+#define NVT_DRIVER_NAME "nuvoton-cir"
+
+/* debugging module parameter */
+static int debug;
+
+
+#define nvt_pr(level, text, ...) \
+	printk(level KBUILD_MODNAME ": " text, ## __VA_ARGS__)
+
+#define nvt_dbg(text, ...) \
+	if (debug) \
+		printk(KERN_DEBUG \
+			KBUILD_MODNAME ": " text "\n" , ## __VA_ARGS__)
+
+#define nvt_dbg_verbose(text, ...) \
+	if (debug > 1) \
+		printk(KERN_DEBUG \
+			KBUILD_MODNAME ": " text "\n" , ## __VA_ARGS__)
+
+#define nvt_dbg_wake(text, ...) \
+	if (debug > 2) \
+		printk(KERN_DEBUG \
+			KBUILD_MODNAME ": " text "\n" , ## __VA_ARGS__)
+
+
+/*
+ * Original lirc driver said min value of 76, and recommended value of 256
+ * for the buffer length, but then used 2048. Never mind that the size of the
+ * RX FIFO is 32 bytes... So I'm using 32 for RX and 256 for TX atm, but I'm
+ * not sure if maybe that TX value is off by a factor of 8 (bits vs. bytes),
+ * and I don't have TX-capable hardware to test/debug on...
+ */
+#define TX_BUF_LEN 256
+#define RX_BUF_LEN 32
+
+struct nvt_dev {
+	struct pnp_dev *pdev;
+	struct rc_dev *rdev;
+	struct ir_raw_event rawir;
+
+	spinlock_t nvt_lock;
+	bool in_use;
+
+	/* for rx */
+	u8 buf[RX_BUF_LEN];
+	unsigned int pkts;
+
+	struct {
+		spinlock_t lock;
+		u8 buf[TX_BUF_LEN];
+		unsigned int buf_count;
+		unsigned int cur_buf_num;
+		wait_queue_head_t queue;
+		u8 tx_state;
+	} tx;
+
+	/* EFER Config register index/data pair */
+	u8 cr_efir;
+	u8 cr_efdr;
+
+	/* hardware I/O settings */
+	unsigned long cir_addr;
+	unsigned long cir_wake_addr;
+	int cir_irq;
+	int cir_wake_irq;
+
+	/* hardware id */
+	u8 chip_major;
+	u8 chip_minor;
+
+	/* hardware features */
+	bool hw_learning_capable;
+	bool hw_tx_capable;
+
+	/* rx settings */
+	bool learning_enabled;
+	bool carrier_detect_enabled;
+
+	/* track cir wake state */
+	u8 wake_state;
+	/* for study */
+	u8 study_state;
+	/* carrier period = 1 / frequency */
+	u32 carrier;
+};
+
+/* study states */
+#define ST_STUDY_NONE      0x0
+#define ST_STUDY_START     0x1
+#define ST_STUDY_CARRIER   0x2
+#define ST_STUDY_ALL_RECV  0x4
+
+/* wake states */
+#define ST_WAKE_NONE	0x0
+#define ST_WAKE_START	0x1
+#define ST_WAKE_FINISH	0x2
+
+/* receive states */
+#define ST_RX_WAIT_7F		0x1
+#define ST_RX_WAIT_HEAD		0x2
+#define ST_RX_WAIT_SILENT_END	0x4
+
+/* send states */
+#define ST_TX_NONE	0x0
+#define ST_TX_REQUEST	0x2
+#define ST_TX_REPLY	0x4
+
+/* buffer packet constants */
+#define BUF_PULSE_BIT	0x80
+#define BUF_LEN_MASK	0x7f
+#define BUF_REPEAT_BYTE	0x70
+#define BUF_REPEAT_MASK	0xf0
+
+/* CIR settings */
+
+/* total length of CIR and CIR WAKE */
+#define CIR_IOREG_LENGTH	0x0f
+
+/* RX limit length, 8 high bits for SLCH, 8 low bits for SLCL (0x7d0 = 2000) */
+#define CIR_RX_LIMIT_COUNT	0x7d0
+
+/* CIR Regs */
+#define CIR_IRCON	0x00
+#define CIR_IRSTS	0x01
+#define CIR_IREN	0x02
+#define CIR_RXFCONT	0x03
+#define CIR_CP		0x04
+#define CIR_CC		0x05
+#define CIR_SLCH	0x06
+#define CIR_SLCL	0x07
+#define CIR_FIFOCON	0x08
+#define CIR_IRFIFOSTS	0x09
+#define CIR_SRXFIFO	0x0a
+#define CIR_TXFCONT	0x0b
+#define CIR_STXFIFO	0x0c
+#define CIR_FCCH	0x0d
+#define CIR_FCCL	0x0e
+#define CIR_IRFSM	0x0f
+
+/* CIR IRCON settings */
+#define CIR_IRCON_RECV	 0x80
+#define CIR_IRCON_WIREN	 0x40
+#define CIR_IRCON_TXEN	 0x20
+#define CIR_IRCON_RXEN	 0x10
+#define CIR_IRCON_WRXINV 0x08
+#define CIR_IRCON_RXINV	 0x04
+
+#define CIR_IRCON_SAMPLE_PERIOD_SEL_1	0x00
+#define CIR_IRCON_SAMPLE_PERIOD_SEL_25	0x01
+#define CIR_IRCON_SAMPLE_PERIOD_SEL_50	0x02
+#define CIR_IRCON_SAMPLE_PERIOD_SEL_100	0x03
+
+/* FIXME: make this a runtime option */
+/* select sample period as 50us */
+#define CIR_IRCON_SAMPLE_PERIOD_SEL	CIR_IRCON_SAMPLE_PERIOD_SEL_50
+
+/* CIR IRSTS settings */
+#define CIR_IRSTS_RDR	0x80
+#define CIR_IRSTS_RTR	0x40
+#define CIR_IRSTS_PE	0x20
+#define CIR_IRSTS_RFO	0x10
+#define CIR_IRSTS_TE	0x08
+#define CIR_IRSTS_TTR	0x04
+#define CIR_IRSTS_TFU	0x02
+#define CIR_IRSTS_GH	0x01
+
+/* CIR IREN settings */
+#define CIR_IREN_RDR	0x80
+#define CIR_IREN_RTR	0x40
+#define CIR_IREN_PE	0x20
+#define CIR_IREN_RFO	0x10
+#define CIR_IREN_TE	0x08
+#define CIR_IREN_TTR	0x04
+#define CIR_IREN_TFU	0x02
+#define CIR_IREN_GH	0x01
+
+/* CIR FIFOCON settings */
+#define CIR_FIFOCON_TXFIFOCLR		0x80
+
+#define CIR_FIFOCON_TX_TRIGGER_LEV_31	0x00
+#define CIR_FIFOCON_TX_TRIGGER_LEV_24	0x10
+#define CIR_FIFOCON_TX_TRIGGER_LEV_16	0x20
+#define CIR_FIFOCON_TX_TRIGGER_LEV_8	0x30
+
+/* FIXME: make this a runtime option */
+/* select TX trigger level as 16 */
+#define CIR_FIFOCON_TX_TRIGGER_LEV	CIR_FIFOCON_TX_TRIGGER_LEV_16
+
+#define CIR_FIFOCON_RXFIFOCLR		0x08
+
+#define CIR_FIFOCON_RX_TRIGGER_LEV_1	0x00
+#define CIR_FIFOCON_RX_TRIGGER_LEV_8	0x01
+#define CIR_FIFOCON_RX_TRIGGER_LEV_16	0x02
+#define CIR_FIFOCON_RX_TRIGGER_LEV_24	0x03
+
+/* FIXME: make this a runtime option */
+/* select RX trigger level as 24 */
+#define CIR_FIFOCON_RX_TRIGGER_LEV	CIR_FIFOCON_RX_TRIGGER_LEV_24
+
+/* CIR IRFIFOSTS settings */
+#define CIR_IRFIFOSTS_IR_PENDING	0x80
+#define CIR_IRFIFOSTS_RX_GS		0x40
+#define CIR_IRFIFOSTS_RX_FTA		0x20
+#define CIR_IRFIFOSTS_RX_EMPTY		0x10
+#define CIR_IRFIFOSTS_RX_FULL		0x08
+#define CIR_IRFIFOSTS_TX_FTA		0x04
+#define CIR_IRFIFOSTS_TX_EMPTY		0x02
+#define CIR_IRFIFOSTS_TX_FULL		0x01
+
+
+/* CIR WAKE UP Regs */
+#define CIR_WAKE_IRCON			0x00
+#define CIR_WAKE_IRSTS			0x01
+#define CIR_WAKE_IREN			0x02
+#define CIR_WAKE_FIFO_CMP_DEEP		0x03
+#define CIR_WAKE_FIFO_CMP_TOL		0x04
+#define CIR_WAKE_FIFO_COUNT		0x05
+#define CIR_WAKE_SLCH			0x06
+#define CIR_WAKE_SLCL			0x07
+#define CIR_WAKE_FIFOCON		0x08
+#define CIR_WAKE_SRXFSTS		0x09
+#define CIR_WAKE_SAMPLE_RX_FIFO		0x0a
+#define CIR_WAKE_WR_FIFO_DATA		0x0b
+#define CIR_WAKE_RD_FIFO_ONLY		0x0c
+#define CIR_WAKE_RD_FIFO_ONLY_IDX	0x0d
+#define CIR_WAKE_FIFO_IGNORE		0x0e
+#define CIR_WAKE_IRFSM			0x0f
+
+/* CIR WAKE UP IRCON settings */
+#define CIR_WAKE_IRCON_DEC_RST		0x80
+#define CIR_WAKE_IRCON_MODE1		0x40
+#define CIR_WAKE_IRCON_MODE0		0x20
+#define CIR_WAKE_IRCON_RXEN		0x10
+#define CIR_WAKE_IRCON_R		0x08
+#define CIR_WAKE_IRCON_RXINV		0x04
+
+/* FIXME/jarod: make this a runtime option */
+/* select a same sample period like cir register */
+#define CIR_WAKE_IRCON_SAMPLE_PERIOD_SEL	CIR_IRCON_SAMPLE_PERIOD_SEL_50
+
+/* CIR WAKE IRSTS Bits */
+#define CIR_WAKE_IRSTS_RDR		0x80
+#define CIR_WAKE_IRSTS_RTR		0x40
+#define CIR_WAKE_IRSTS_PE		0x20
+#define CIR_WAKE_IRSTS_RFO		0x10
+#define CIR_WAKE_IRSTS_GH		0x08
+#define CIR_WAKE_IRSTS_IR_PENDING	0x01
+
+/* CIR WAKE UP IREN Bits */
+#define CIR_WAKE_IREN_RDR		0x80
+#define CIR_WAKE_IREN_RTR		0x40
+#define CIR_WAKE_IREN_PE		0x20
+#define CIR_WAKE_IREN_RFO		0x10
+#define CIR_WAKE_IREN_TE		0x08
+#define CIR_WAKE_IREN_TTR		0x04
+#define CIR_WAKE_IREN_TFU		0x02
+#define CIR_WAKE_IREN_GH		0x01
+
+/* CIR WAKE FIFOCON settings */
+#define CIR_WAKE_FIFOCON_RXFIFOCLR	0x08
+
+#define CIR_WAKE_FIFOCON_RX_TRIGGER_LEV_67	0x00
+#define CIR_WAKE_FIFOCON_RX_TRIGGER_LEV_66	0x01
+#define CIR_WAKE_FIFOCON_RX_TRIGGER_LEV_65	0x02
+#define CIR_WAKE_FIFOCON_RX_TRIGGER_LEV_64	0x03
+
+/* FIXME: make this a runtime option */
+/* select WAKE UP RX trigger level as 67 */
+#define CIR_WAKE_FIFOCON_RX_TRIGGER_LEV	CIR_WAKE_FIFOCON_RX_TRIGGER_LEV_67
+
+/* CIR WAKE SRXFSTS settings */
+#define CIR_WAKE_IRFIFOSTS_RX_GS	0x80
+#define CIR_WAKE_IRFIFOSTS_RX_FTA	0x40
+#define CIR_WAKE_IRFIFOSTS_RX_EMPTY	0x20
+#define CIR_WAKE_IRFIFOSTS_RX_FULL	0x10
+
+/*
+ * The CIR Wake FIFO buffer is 67 bytes long, but the stock remote wakes
+ * the system comparing only 65 bytes (fails with this set to 67)
+ */
+#define CIR_WAKE_FIFO_CMP_BYTES		65
+/* CIR Wake byte comparison tolerance */
+#define CIR_WAKE_CMP_TOLERANCE		5
+
+/*
+ * Extended Function Enable Registers:
+ *  Extended Function Index Register
+ *  Extended Function Data Register
+ */
+#define CR_EFIR			0x2e
+#define CR_EFDR			0x2f
+
+/* Possible alternate EFER values, depends on how the chip is wired */
+#define CR_EFIR2		0x4e
+#define CR_EFDR2		0x4f
+
+/* Extended Function Mode enable/disable magic values */
+#define EFER_EFM_ENABLE		0x87
+#define EFER_EFM_DISABLE	0xaa
+
+/* Chip IDs found in CR_CHIP_ID_{HI,LO} */
+#define CHIP_ID_HIGH		0xb4
+#define CHIP_ID_LOW		0x72
+#define CHIP_ID_LOW2		0x73
+
+/* Config regs we need to care about */
+#define CR_SOFTWARE_RESET	0x02
+#define CR_LOGICAL_DEV_SEL	0x07
+#define CR_CHIP_ID_HI		0x20
+#define CR_CHIP_ID_LO		0x21
+#define CR_DEV_POWER_DOWN	0x22 /* bit 2 is CIR power, default power on */
+#define CR_OUTPUT_PIN_SEL	0x27
+#define CR_LOGICAL_DEV_EN	0x30 /* valid for all logical devices */
+/* next three regs valid for both the CIR and CIR_WAKE logical devices */
+#define CR_CIR_BASE_ADDR_HI	0x60
+#define CR_CIR_BASE_ADDR_LO	0x61
+#define CR_CIR_IRQ_RSRC		0x70
+/* next three regs valid only for ACPI logical dev */
+#define CR_ACPI_CIR_WAKE	0xe0
+#define CR_ACPI_IRQ_EVENTS	0xf6
+#define CR_ACPI_IRQ_EVENTS2	0xf7
+
+/* Logical devices that we need to care about */
+#define LOGICAL_DEV_LPT		0x01
+#define LOGICAL_DEV_CIR		0x06
+#define LOGICAL_DEV_ACPI	0x0a
+#define LOGICAL_DEV_CIR_WAKE	0x0e
+
+#define LOGICAL_DEV_DISABLE	0x00
+#define LOGICAL_DEV_ENABLE	0x01
+
+#define CIR_WAKE_ENABLE_BIT	0x08
+#define CIR_INTR_MOUSE_IRQ_BIT	0x80
+#define PME_INTR_CIR_PASS_BIT	0x08
+
+#define OUTPUT_PIN_SEL_MASK	0xbc
+#define OUTPUT_ENABLE_CIR	0x01 /* Pin95=CIRRX, Pin96=CIRTX1 */
+#define OUTPUT_ENABLE_CIRWB	0x40 /* enable wide-band sensor */
+
+/* MCE CIR signal length, related on sample period */
+
+/* MCE CIR controller signal length: about 43ms
+ * 43ms / 50us (sample period) * 0.85 (inaccuracy)
+ */
+#define CONTROLLER_BUF_LEN_MIN 830
+
+/* MCE CIR keyboard signal length: about 26ms
+ * 26ms / 50us (sample period) * 0.85 (inaccuracy)
+ */
+#define KEYBOARD_BUF_LEN_MAX 650
+#define KEYBOARD_BUF_LEN_MIN 610
+
+/* MCE CIR mouse signal length: about 24ms
+ * 24ms / 50us (sample period) * 0.85 (inaccuracy)
+ */
+#define MOUSE_BUF_LEN_MIN 565
+
+#define CIR_SAMPLE_PERIOD 50
+#define CIR_SAMPLE_LOW_INACCURACY 0.85
+
+/* MAX silence time that driver will sent to lirc */
+#define MAX_SILENCE_TIME 60000
+
+#if CIR_IRCON_SAMPLE_PERIOD_SEL == CIR_IRCON_SAMPLE_PERIOD_SEL_100
+#define SAMPLE_PERIOD 100
+
+#elif CIR_IRCON_SAMPLE_PERIOD_SEL == CIR_IRCON_SAMPLE_PERIOD_SEL_50
+#define SAMPLE_PERIOD 50
+
+#elif CIR_IRCON_SAMPLE_PERIOD_SEL == CIR_IRCON_SAMPLE_PERIOD_SEL_25
+#define SAMPLE_PERIOD 25
+
+#else
+#define SAMPLE_PERIOD 1
+#endif
+
+/* as VISTA MCE definition, valid carrier value */
+#define MAX_CARRIER 60000
+#define MIN_CARRIER 30000
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/rc-core-priv.h linux-libre-2.6.38-gnu1/drivers/media/rc/rc-core-priv.h
--- linux-libre-2.6.37-gnu1/drivers/media/rc/rc-core-priv.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/rc-core-priv.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,193 @@
+/*
+ * Remote Controller core raw events header
+ *
+ * Copyright (C) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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.
+ */
+
+#ifndef _RC_CORE_PRIV
+#define _RC_CORE_PRIV
+
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <media/rc-core.h>
+
+struct ir_raw_handler {
+	struct list_head list;
+
+	u64 protocols; /* which are handled by this handler */
+	int (*decode)(struct rc_dev *dev, struct ir_raw_event event);
+
+	/* These two should only be used by the lirc decoder */
+	int (*raw_register)(struct rc_dev *dev);
+	int (*raw_unregister)(struct rc_dev *dev);
+};
+
+struct ir_raw_event_ctrl {
+	struct list_head		list;		/* to keep track of raw clients */
+	struct task_struct		*thread;
+	spinlock_t			lock;
+	struct kfifo			kfifo;		/* fifo for the pulse/space durations */
+	ktime_t				last_event;	/* when last event occurred */
+	enum raw_event_type		last_type;	/* last event type */
+	struct rc_dev			*dev;		/* pointer to the parent rc_dev */
+	u64				enabled_protocols; /* enabled raw protocol decoders */
+
+	/* raw decoder state follows */
+	struct ir_raw_event prev_ev;
+	struct ir_raw_event this_ev;
+	struct nec_dec {
+		int state;
+		unsigned count;
+		u32 bits;
+		bool is_nec_x;
+		bool necx_repeat;
+	} nec;
+	struct rc5_dec {
+		int state;
+		u32 bits;
+		unsigned count;
+		unsigned wanted_bits;
+	} rc5;
+	struct rc6_dec {
+		int state;
+		u8 header;
+		u32 body;
+		bool toggle;
+		unsigned count;
+		unsigned wanted_bits;
+	} rc6;
+	struct sony_dec {
+		int state;
+		u32 bits;
+		unsigned count;
+	} sony;
+	struct jvc_dec {
+		int state;
+		u16 bits;
+		u16 old_bits;
+		unsigned count;
+		bool first;
+		bool toggle;
+	} jvc;
+	struct rc5_sz_dec {
+		int state;
+		u32 bits;
+		unsigned count;
+		unsigned wanted_bits;
+	} rc5_sz;
+	struct lirc_codec {
+		struct rc_dev *dev;
+		struct lirc_driver *drv;
+		int carrier_low;
+
+		ktime_t gap_start;
+		u64 gap_duration;
+		bool gap;
+		bool send_timeout_reports;
+
+	} lirc;
+};
+
+/* macros for IR decoders */
+static inline bool geq_margin(unsigned d1, unsigned d2, unsigned margin)
+{
+	return d1 > (d2 - margin);
+}
+
+static inline bool eq_margin(unsigned d1, unsigned d2, unsigned margin)
+{
+	return ((d1 > (d2 - margin)) && (d1 < (d2 + margin)));
+}
+
+static inline bool is_transition(struct ir_raw_event *x, struct ir_raw_event *y)
+{
+	return x->pulse != y->pulse;
+}
+
+static inline void decrease_duration(struct ir_raw_event *ev, unsigned duration)
+{
+	if (duration > ev->duration)
+		ev->duration = 0;
+	else
+		ev->duration -= duration;
+}
+
+/* Returns true if event is normal pulse/space event */
+static inline bool is_timing_event(struct ir_raw_event ev)
+{
+	return !ev.carrier_report && !ev.reset;
+}
+
+#define TO_US(duration)			DIV_ROUND_CLOSEST((duration), 1000)
+#define TO_STR(is_pulse)		((is_pulse) ? "pulse" : "space")
+
+/*
+ * Routines from rc-raw.c to be used internally and by decoders
+ */
+u64 ir_raw_get_allowed_protocols(void);
+int ir_raw_event_register(struct rc_dev *dev);
+void ir_raw_event_unregister(struct rc_dev *dev);
+int ir_raw_handler_register(struct ir_raw_handler *ir_raw_handler);
+void ir_raw_handler_unregister(struct ir_raw_handler *ir_raw_handler);
+void ir_raw_init(void);
+
+/*
+ * Decoder initialization code
+ *
+ * Those load logic are called during ir-core init, and automatically
+ * loads the compiled decoders for their usage with IR raw events
+ */
+
+/* from ir-nec-decoder.c */
+#ifdef CONFIG_IR_NEC_DECODER_MODULE
+#define load_nec_decode()	request_module("ir-nec-decoder")
+#else
+#define load_nec_decode()	0
+#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
+#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
+#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
+#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
+#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
+#endif
+
+
+#endif /* _RC_CORE_PRIV */
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/rc-loopback.c linux-libre-2.6.38-gnu1/drivers/media/rc/rc-loopback.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/rc-loopback.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/rc-loopback.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,260 @@
+/*
+ * Loopback driver for rc-core,
+ *
+ * Copyright (c) 2010 David Härdeman <david@hardeman.nu>
+ *
+ * This driver receives TX data and passes it back as RX data,
+ * which is useful for (scripted) debugging of rc-core without
+ * having to use actual hardware.
+ *
+ * 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/device.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <media/rc-core.h>
+
+#define DRIVER_NAME	"rc-loopback"
+#define dprintk(x...)	if (debug) printk(KERN_INFO DRIVER_NAME ": " x)
+#define RXMASK_REGULAR	0x1
+#define RXMASK_LEARNING	0x2
+
+static bool debug;
+
+struct loopback_dev {
+	struct rc_dev *dev;
+	u32 txmask;
+	u32 txcarrier;
+	u32 txduty;
+	bool idle;
+	bool learning;
+	bool carrierreport;
+	u32 rxcarriermin;
+	u32 rxcarriermax;
+};
+
+static struct loopback_dev loopdev;
+
+static int loop_set_tx_mask(struct rc_dev *dev, u32 mask)
+{
+	struct loopback_dev *lodev = dev->priv;
+
+	if ((mask & (RXMASK_REGULAR | RXMASK_LEARNING)) != mask) {
+		dprintk("invalid tx mask: %u\n", mask);
+		return -EINVAL;
+	}
+
+	dprintk("setting tx mask: %u\n", mask);
+	lodev->txmask = mask;
+	return 0;
+}
+
+static int loop_set_tx_carrier(struct rc_dev *dev, u32 carrier)
+{
+	struct loopback_dev *lodev = dev->priv;
+
+	dprintk("setting tx carrier: %u\n", carrier);
+	lodev->txcarrier = carrier;
+	return 0;
+}
+
+static int loop_set_tx_duty_cycle(struct rc_dev *dev, u32 duty_cycle)
+{
+	struct loopback_dev *lodev = dev->priv;
+
+	if (duty_cycle < 1 || duty_cycle > 99) {
+		dprintk("invalid duty cycle: %u\n", duty_cycle);
+		return -EINVAL;
+	}
+
+	dprintk("setting duty cycle: %u\n", duty_cycle);
+	lodev->txduty = duty_cycle;
+	return 0;
+}
+
+static int loop_set_rx_carrier_range(struct rc_dev *dev, u32 min, u32 max)
+{
+	struct loopback_dev *lodev = dev->priv;
+
+	if (min < 1 || min > max) {
+		dprintk("invalid rx carrier range %u to %u\n", min, max);
+		return -EINVAL;
+	}
+
+	dprintk("setting rx carrier range %u to %u\n", min, max);
+	lodev->rxcarriermin = min;
+	lodev->rxcarriermax = max;
+	return 0;
+}
+
+static int loop_tx_ir(struct rc_dev *dev, int *txbuf, u32 n)
+{
+	struct loopback_dev *lodev = dev->priv;
+	u32 rxmask;
+	unsigned count;
+	unsigned total_duration = 0;
+	unsigned i;
+	DEFINE_IR_RAW_EVENT(rawir);
+
+	if (n == 0 || n % sizeof(int)) {
+		dprintk("invalid tx buffer size\n");
+		return -EINVAL;
+	}
+
+	count = n / sizeof(int);
+	for (i = 0; i < count; i++)
+		total_duration += abs(txbuf[i]);
+
+	if (total_duration == 0) {
+		dprintk("invalid tx data, total duration zero\n");
+		return -EINVAL;
+	}
+
+	if (lodev->txcarrier < lodev->rxcarriermin ||
+	    lodev->txcarrier > lodev->rxcarriermax) {
+		dprintk("ignoring tx, carrier out of range\n");
+		goto out;
+	}
+
+	if (lodev->learning)
+		rxmask = RXMASK_LEARNING;
+	else
+		rxmask = RXMASK_REGULAR;
+
+	if (!(rxmask & lodev->txmask)) {
+		dprintk("ignoring tx, rx mask mismatch\n");
+		goto out;
+	}
+
+	for (i = 0; i < count; i++) {
+		rawir.pulse = i % 2 ? false : true;
+		rawir.duration = abs(txbuf[i]) * 1000;
+		if (rawir.duration)
+			ir_raw_event_store_with_filter(dev, &rawir);
+	}
+	ir_raw_event_handle(dev);
+
+out:
+	/* Lirc expects this function to take as long as the total duration */
+	set_current_state(TASK_INTERRUPTIBLE);
+	schedule_timeout(usecs_to_jiffies(total_duration));
+	return n;
+}
+
+static void loop_set_idle(struct rc_dev *dev, bool enable)
+{
+	struct loopback_dev *lodev = dev->priv;
+
+	if (lodev->idle != enable) {
+		dprintk("%sing idle mode\n", enable ? "enter" : "exit");
+		lodev->idle = enable;
+	}
+}
+
+static int loop_set_learning_mode(struct rc_dev *dev, int enable)
+{
+	struct loopback_dev *lodev = dev->priv;
+
+	if (lodev->learning != enable) {
+		dprintk("%sing learning mode\n", enable ? "enter" : "exit");
+		lodev->learning = !!enable;
+	}
+
+	return 0;
+}
+
+static int loop_set_carrier_report(struct rc_dev *dev, int enable)
+{
+	struct loopback_dev *lodev = dev->priv;
+
+	if (lodev->carrierreport != enable) {
+		dprintk("%sabling carrier reports\n", enable ? "en" : "dis");
+		lodev->carrierreport = !!enable;
+	}
+
+	return 0;
+}
+
+static int __init loop_init(void)
+{
+	struct rc_dev *rc;
+	int ret;
+
+	rc = rc_allocate_device();
+	if (!rc) {
+		printk(KERN_ERR DRIVER_NAME ": rc_dev allocation failed\n");
+		return -ENOMEM;
+	}
+
+	rc->input_name		= "rc-core loopback device";
+	rc->input_phys		= "rc-core/virtual";
+	rc->input_id.bustype	= BUS_VIRTUAL;
+	rc->input_id.version	= 1;
+	rc->driver_name		= DRIVER_NAME;
+	rc->map_name		= RC_MAP_EMPTY;
+	rc->priv		= &loopdev;
+	rc->driver_type		= RC_DRIVER_IR_RAW;
+	rc->allowed_protos	= RC_TYPE_ALL;
+	rc->timeout		= 100 * 1000 * 1000; /* 100 ms */
+	rc->min_timeout		= 1;
+	rc->max_timeout		= UINT_MAX;
+	rc->rx_resolution	= 1000;
+	rc->tx_resolution	= 1000;
+	rc->s_tx_mask		= loop_set_tx_mask;
+	rc->s_tx_carrier	= loop_set_tx_carrier;
+	rc->s_tx_duty_cycle	= loop_set_tx_duty_cycle;
+	rc->s_rx_carrier_range	= loop_set_rx_carrier_range;
+	rc->tx_ir		= loop_tx_ir;
+	rc->s_idle		= loop_set_idle;
+	rc->s_learning_mode	= loop_set_learning_mode;
+	rc->s_carrier_report	= loop_set_carrier_report;
+	rc->priv		= &loopdev;
+
+	loopdev.txmask		= RXMASK_REGULAR;
+	loopdev.txcarrier	= 36000;
+	loopdev.txduty		= 50;
+	loopdev.rxcarriermin	= 1;
+	loopdev.rxcarriermax	= ~0;
+	loopdev.idle		= true;
+	loopdev.learning	= false;
+	loopdev.carrierreport	= false;
+
+	ret = rc_register_device(rc);
+	if (ret < 0) {
+		printk(KERN_ERR DRIVER_NAME ": rc_dev registration failed\n");
+		rc_free_device(rc);
+		return ret;
+	}
+
+	loopdev.dev = rc;
+	return 0;
+}
+
+static void __exit loop_exit(void)
+{
+	rc_unregister_device(loopdev.dev);
+}
+
+module_init(loop_init);
+module_exit(loop_exit);
+
+module_param(debug, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Enable debug messages");
+
+MODULE_DESCRIPTION("Loopback device for rc-core debugging");
+MODULE_AUTHOR("David Härdeman <david@hardeman.nu>");
+MODULE_LICENSE("GPL");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/rc-main.c linux-libre-2.6.38-gnu1/drivers/media/rc/rc-main.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/rc-main.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/rc-main.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,1141 @@
+/* rc-main.c - Remote Controller core module
+ *
+ * Copyright (C) 2009-2010 by Mauro Carvalho Chehab <mchehab@redhat.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.
+ */
+
+#include <media/rc-core.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <linux/input.h>
+#include <linux/slab.h>
+#include <linux/device.h>
+#include "rc-core-priv.h"
+
+/* Sizes are in bytes, 256 bytes allows for 32 entries on x64 */
+#define IR_TAB_MIN_SIZE	256
+#define IR_TAB_MAX_SIZE	8192
+
+/* FIXME: IR_KEYPRESS_TIMEOUT should be protocol specific */
+#define IR_KEYPRESS_TIMEOUT 250
+
+/* Used to keep track of known keymaps */
+static LIST_HEAD(rc_map_list);
+static DEFINE_SPINLOCK(rc_map_lock);
+
+static struct rc_map_list *seek_rc_map(const char *name)
+{
+	struct rc_map_list *map = NULL;
+
+	spin_lock(&rc_map_lock);
+	list_for_each_entry(map, &rc_map_list, list) {
+		if (!strcmp(name, map->map.name)) {
+			spin_unlock(&rc_map_lock);
+			return map;
+		}
+	}
+	spin_unlock(&rc_map_lock);
+
+	return NULL;
+}
+
+struct rc_map *rc_map_get(const char *name)
+{
+
+	struct rc_map_list *map;
+
+	map = seek_rc_map(name);
+#ifdef MODULE
+	if (!map) {
+		int rc = request_module(name);
+		if (rc < 0) {
+			printk(KERN_ERR "Couldn't load IR keymap %s\n", name);
+			return NULL;
+		}
+		msleep(20);	/* Give some time for IR to register */
+
+		map = seek_rc_map(name);
+	}
+#endif
+	if (!map) {
+		printk(KERN_ERR "IR keymap %s not found\n", name);
+		return NULL;
+	}
+
+	printk(KERN_INFO "Registered IR keymap %s\n", map->map.name);
+
+	return &map->map;
+}
+EXPORT_SYMBOL_GPL(rc_map_get);
+
+int rc_map_register(struct rc_map_list *map)
+{
+	spin_lock(&rc_map_lock);
+	list_add_tail(&map->list, &rc_map_list);
+	spin_unlock(&rc_map_lock);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(rc_map_register);
+
+void rc_map_unregister(struct rc_map_list *map)
+{
+	spin_lock(&rc_map_lock);
+	list_del(&map->list);
+	spin_unlock(&rc_map_lock);
+}
+EXPORT_SYMBOL_GPL(rc_map_unregister);
+
+
+static struct rc_map_table empty[] = {
+	{ 0x2a, KEY_COFFEE },
+};
+
+static struct rc_map_list empty_map = {
+	.map = {
+		.scan    = empty,
+		.size    = ARRAY_SIZE(empty),
+		.rc_type = RC_TYPE_UNKNOWN,	/* Legacy IR type */
+		.name    = RC_MAP_EMPTY,
+	}
+};
+
+/**
+ * ir_create_table() - initializes a scancode table
+ * @rc_map:	the rc_map to initialize
+ * @name:	name to assign to the table
+ * @rc_type:	ir type to assign to the new table
+ * @size:	initial size of the table
+ * @return:	zero on success or a negative error code
+ *
+ * This routine will initialize the rc_map and will allocate
+ * memory to hold at least the specified number of elements.
+ */
+static int ir_create_table(struct rc_map *rc_map,
+			   const char *name, u64 rc_type, size_t size)
+{
+	rc_map->name = name;
+	rc_map->rc_type = rc_type;
+	rc_map->alloc = roundup_pow_of_two(size * sizeof(struct rc_map_table));
+	rc_map->size = rc_map->alloc / sizeof(struct rc_map_table);
+	rc_map->scan = kmalloc(rc_map->alloc, GFP_KERNEL);
+	if (!rc_map->scan)
+		return -ENOMEM;
+
+	IR_dprintk(1, "Allocated space for %u keycode entries (%u bytes)\n",
+		   rc_map->size, rc_map->alloc);
+	return 0;
+}
+
+/**
+ * ir_free_table() - frees memory allocated by a scancode table
+ * @rc_map:	the table whose mappings need to be freed
+ *
+ * This routine will free memory alloctaed for key mappings used by given
+ * scancode table.
+ */
+static void ir_free_table(struct rc_map *rc_map)
+{
+	rc_map->size = 0;
+	kfree(rc_map->scan);
+	rc_map->scan = NULL;
+}
+
+/**
+ * ir_resize_table() - resizes a scancode table if necessary
+ * @rc_map:	the rc_map to resize
+ * @gfp_flags:	gfp flags to use when allocating memory
+ * @return:	zero on success or a negative error code
+ *
+ * This routine will shrink the rc_map if it has lots of
+ * unused entries and grow it if it is full.
+ */
+static int ir_resize_table(struct rc_map *rc_map, gfp_t gfp_flags)
+{
+	unsigned int oldalloc = rc_map->alloc;
+	unsigned int newalloc = oldalloc;
+	struct rc_map_table *oldscan = rc_map->scan;
+	struct rc_map_table *newscan;
+
+	if (rc_map->size == rc_map->len) {
+		/* All entries in use -> grow keytable */
+		if (rc_map->alloc >= IR_TAB_MAX_SIZE)
+			return -ENOMEM;
+
+		newalloc *= 2;
+		IR_dprintk(1, "Growing table to %u bytes\n", newalloc);
+	}
+
+	if ((rc_map->len * 3 < rc_map->size) && (oldalloc > IR_TAB_MIN_SIZE)) {
+		/* Less than 1/3 of entries in use -> shrink keytable */
+		newalloc /= 2;
+		IR_dprintk(1, "Shrinking table to %u bytes\n", newalloc);
+	}
+
+	if (newalloc == oldalloc)
+		return 0;
+
+	newscan = kmalloc(newalloc, gfp_flags);
+	if (!newscan) {
+		IR_dprintk(1, "Failed to kmalloc %u bytes\n", newalloc);
+		return -ENOMEM;
+	}
+
+	memcpy(newscan, rc_map->scan, rc_map->len * sizeof(struct rc_map_table));
+	rc_map->scan = newscan;
+	rc_map->alloc = newalloc;
+	rc_map->size = rc_map->alloc / sizeof(struct rc_map_table);
+	kfree(oldscan);
+	return 0;
+}
+
+/**
+ * ir_update_mapping() - set a keycode in the scancode->keycode table
+ * @dev:	the struct rc_dev device descriptor
+ * @rc_map:	scancode table to be adjusted
+ * @index:	index of the mapping that needs to be updated
+ * @keycode:	the desired keycode
+ * @return:	previous keycode assigned to the mapping
+ *
+ * This routine is used to update scancode->keycode mapping at given
+ * position.
+ */
+static unsigned int ir_update_mapping(struct rc_dev *dev,
+				      struct rc_map *rc_map,
+				      unsigned int index,
+				      unsigned int new_keycode)
+{
+	int old_keycode = rc_map->scan[index].keycode;
+	int i;
+
+	/* Did the user wish to remove the mapping? */
+	if (new_keycode == KEY_RESERVED || new_keycode == KEY_UNKNOWN) {
+		IR_dprintk(1, "#%d: Deleting scan 0x%04x\n",
+			   index, rc_map->scan[index].scancode);
+		rc_map->len--;
+		memmove(&rc_map->scan[index], &rc_map->scan[index+ 1],
+			(rc_map->len - index) * sizeof(struct rc_map_table));
+	} else {
+		IR_dprintk(1, "#%d: %s scan 0x%04x with key 0x%04x\n",
+			   index,
+			   old_keycode == KEY_RESERVED ? "New" : "Replacing",
+			   rc_map->scan[index].scancode, new_keycode);
+		rc_map->scan[index].keycode = new_keycode;
+		__set_bit(new_keycode, dev->input_dev->keybit);
+	}
+
+	if (old_keycode != KEY_RESERVED) {
+		/* A previous mapping was updated... */
+		__clear_bit(old_keycode, dev->input_dev->keybit);
+		/* ... but another scancode might use the same keycode */
+		for (i = 0; i < rc_map->len; i++) {
+			if (rc_map->scan[i].keycode == old_keycode) {
+				__set_bit(old_keycode, dev->input_dev->keybit);
+				break;
+			}
+		}
+
+		/* Possibly shrink the keytable, failure is not a problem */
+		ir_resize_table(rc_map, GFP_ATOMIC);
+	}
+
+	return old_keycode;
+}
+
+/**
+ * ir_establish_scancode() - set a keycode in the scancode->keycode table
+ * @dev:	the struct rc_dev device descriptor
+ * @rc_map:	scancode table to be searched
+ * @scancode:	the desired scancode
+ * @resize:	controls whether we allowed to resize the table to
+ *		accomodate not yet present scancodes
+ * @return:	index of the mapping containing scancode in question
+ *		or -1U in case of failure.
+ *
+ * This routine is used to locate given scancode in rc_map.
+ * If scancode is not yet present the routine will allocate a new slot
+ * for it.
+ */
+static unsigned int ir_establish_scancode(struct rc_dev *dev,
+					  struct rc_map *rc_map,
+					  unsigned int scancode,
+					  bool resize)
+{
+	unsigned int i;
+
+	/*
+	 * Unfortunately, some hardware-based IR decoders don't provide
+	 * all bits for the complete IR code. In general, they provide only
+	 * the command part of the IR code. Yet, as it is possible to replace
+	 * the provided IR with another one, it is needed to allow loading
+	 * IR tables from other remotes. So, we support specifying a mask to
+	 * indicate the valid bits of the scancodes.
+	 */
+	if (dev->scanmask)
+		scancode &= dev->scanmask;
+
+	/* First check if we already have a mapping for this ir command */
+	for (i = 0; i < rc_map->len; i++) {
+		if (rc_map->scan[i].scancode == scancode)
+			return i;
+
+		/* Keytable is sorted from lowest to highest scancode */
+		if (rc_map->scan[i].scancode >= scancode)
+			break;
+	}
+
+	/* No previous mapping found, we might need to grow the table */
+	if (rc_map->size == rc_map->len) {
+		if (!resize || ir_resize_table(rc_map, GFP_ATOMIC))
+			return -1U;
+	}
+
+	/* i is the proper index to insert our new keycode */
+	if (i < rc_map->len)
+		memmove(&rc_map->scan[i + 1], &rc_map->scan[i],
+			(rc_map->len - i) * sizeof(struct rc_map_table));
+	rc_map->scan[i].scancode = scancode;
+	rc_map->scan[i].keycode = KEY_RESERVED;
+	rc_map->len++;
+
+	return i;
+}
+
+/**
+ * ir_setkeycode() - set a keycode in the scancode->keycode table
+ * @idev:	the struct input_dev device descriptor
+ * @scancode:	the desired scancode
+ * @keycode:	result
+ * @return:	-EINVAL if the keycode could not be inserted, otherwise zero.
+ *
+ * This routine is used to handle evdev EVIOCSKEY ioctl.
+ */
+static int ir_setkeycode(struct input_dev *idev,
+			 const struct input_keymap_entry *ke,
+			 unsigned int *old_keycode)
+{
+	struct rc_dev *rdev = input_get_drvdata(idev);
+	struct rc_map *rc_map = &rdev->rc_map;
+	unsigned int index;
+	unsigned int scancode;
+	int retval = 0;
+	unsigned long flags;
+
+	spin_lock_irqsave(&rc_map->lock, flags);
+
+	if (ke->flags & INPUT_KEYMAP_BY_INDEX) {
+		index = ke->index;
+		if (index >= rc_map->len) {
+			retval = -EINVAL;
+			goto out;
+		}
+	} else {
+		retval = input_scancode_to_scalar(ke, &scancode);
+		if (retval)
+			goto out;
+
+		index = ir_establish_scancode(rdev, rc_map, scancode, true);
+		if (index >= rc_map->len) {
+			retval = -ENOMEM;
+			goto out;
+		}
+	}
+
+	*old_keycode = ir_update_mapping(rdev, rc_map, index, ke->keycode);
+
+out:
+	spin_unlock_irqrestore(&rc_map->lock, flags);
+	return retval;
+}
+
+/**
+ * ir_setkeytable() - sets several entries in the scancode->keycode table
+ * @dev:	the struct rc_dev device descriptor
+ * @to:		the struct rc_map to copy entries to
+ * @from:	the struct rc_map to copy entries from
+ * @return:	-ENOMEM if all keycodes could not be inserted, otherwise zero.
+ *
+ * This routine is used to handle table initialization.
+ */
+static int ir_setkeytable(struct rc_dev *dev,
+			  const struct rc_map *from)
+{
+	struct rc_map *rc_map = &dev->rc_map;
+	unsigned int i, index;
+	int rc;
+
+	rc = ir_create_table(rc_map, from->name,
+			     from->rc_type, from->size);
+	if (rc)
+		return rc;
+
+	IR_dprintk(1, "Allocated space for %u keycode entries (%u bytes)\n",
+		   rc_map->size, rc_map->alloc);
+
+	for (i = 0; i < from->size; i++) {
+		index = ir_establish_scancode(dev, rc_map,
+					      from->scan[i].scancode, false);
+		if (index >= rc_map->len) {
+			rc = -ENOMEM;
+			break;
+		}
+
+		ir_update_mapping(dev, rc_map, index,
+				  from->scan[i].keycode);
+	}
+
+	if (rc)
+		ir_free_table(rc_map);
+
+	return rc;
+}
+
+/**
+ * ir_lookup_by_scancode() - locate mapping by scancode
+ * @rc_map:	the struct rc_map to search
+ * @scancode:	scancode to look for in the table
+ * @return:	index in the table, -1U if not found
+ *
+ * This routine performs binary search in RC keykeymap table for
+ * given scancode.
+ */
+static unsigned int ir_lookup_by_scancode(const struct rc_map *rc_map,
+					  unsigned int scancode)
+{
+	int start = 0;
+	int end = rc_map->len - 1;
+	int mid;
+
+	while (start <= end) {
+		mid = (start + end) / 2;
+		if (rc_map->scan[mid].scancode < scancode)
+			start = mid + 1;
+		else if (rc_map->scan[mid].scancode > scancode)
+			end = mid - 1;
+		else
+			return mid;
+	}
+
+	return -1U;
+}
+
+/**
+ * ir_getkeycode() - get a keycode from the scancode->keycode table
+ * @idev:	the struct input_dev device descriptor
+ * @scancode:	the desired scancode
+ * @keycode:	used to return the keycode, if found, or KEY_RESERVED
+ * @return:	always returns zero.
+ *
+ * This routine is used to handle evdev EVIOCGKEY ioctl.
+ */
+static int ir_getkeycode(struct input_dev *idev,
+			 struct input_keymap_entry *ke)
+{
+	struct rc_dev *rdev = input_get_drvdata(idev);
+	struct rc_map *rc_map = &rdev->rc_map;
+	struct rc_map_table *entry;
+	unsigned long flags;
+	unsigned int index;
+	unsigned int scancode;
+	int retval;
+
+	spin_lock_irqsave(&rc_map->lock, flags);
+
+	if (ke->flags & INPUT_KEYMAP_BY_INDEX) {
+		index = ke->index;
+	} else {
+		retval = input_scancode_to_scalar(ke, &scancode);
+		if (retval)
+			goto out;
+
+		index = ir_lookup_by_scancode(rc_map, scancode);
+	}
+
+	if (index < rc_map->len) {
+		entry = &rc_map->scan[index];
+
+		ke->index = index;
+		ke->keycode = entry->keycode;
+		ke->len = sizeof(entry->scancode);
+		memcpy(ke->scancode, &entry->scancode, sizeof(entry->scancode));
+
+	} else if (!(ke->flags & INPUT_KEYMAP_BY_INDEX)) {
+		/*
+		 * We do not really know the valid range of scancodes
+		 * so let's respond with KEY_RESERVED to anything we
+		 * do not have mapping for [yet].
+		 */
+		ke->index = index;
+		ke->keycode = KEY_RESERVED;
+	} else {
+		retval = -EINVAL;
+		goto out;
+	}
+
+	retval = 0;
+
+out:
+	spin_unlock_irqrestore(&rc_map->lock, flags);
+	return retval;
+}
+
+/**
+ * rc_g_keycode_from_table() - gets the keycode that corresponds to a scancode
+ * @dev:	the struct rc_dev descriptor of the device
+ * @scancode:	the scancode to look for
+ * @return:	the corresponding keycode, or KEY_RESERVED
+ *
+ * This routine is used by drivers which need to convert a scancode to a
+ * keycode. Normally it should not be used since drivers should have no
+ * interest in keycodes.
+ */
+u32 rc_g_keycode_from_table(struct rc_dev *dev, u32 scancode)
+{
+	struct rc_map *rc_map = &dev->rc_map;
+	unsigned int keycode;
+	unsigned int index;
+	unsigned long flags;
+
+	spin_lock_irqsave(&rc_map->lock, flags);
+
+	index = ir_lookup_by_scancode(rc_map, scancode);
+	keycode = index < rc_map->len ?
+			rc_map->scan[index].keycode : KEY_RESERVED;
+
+	spin_unlock_irqrestore(&rc_map->lock, flags);
+
+	if (keycode != KEY_RESERVED)
+		IR_dprintk(1, "%s: scancode 0x%04x keycode 0x%02x\n",
+			   dev->input_name, scancode, keycode);
+
+	return keycode;
+}
+EXPORT_SYMBOL_GPL(rc_g_keycode_from_table);
+
+/**
+ * ir_do_keyup() - internal function to signal the release of a keypress
+ * @dev:	the struct rc_dev descriptor of the device
+ *
+ * This function is used internally to release a keypress, it must be
+ * called with keylock held.
+ */
+static void ir_do_keyup(struct rc_dev *dev)
+{
+	if (!dev->keypressed)
+		return;
+
+	IR_dprintk(1, "keyup key 0x%04x\n", dev->last_keycode);
+	input_report_key(dev->input_dev, dev->last_keycode, 0);
+	input_sync(dev->input_dev);
+	dev->keypressed = false;
+}
+
+/**
+ * rc_keyup() - signals the release of a keypress
+ * @dev:	the struct rc_dev descriptor of the device
+ *
+ * This routine is used to signal that a key has been released on the
+ * remote control.
+ */
+void rc_keyup(struct rc_dev *dev)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&dev->keylock, flags);
+	ir_do_keyup(dev);
+	spin_unlock_irqrestore(&dev->keylock, flags);
+}
+EXPORT_SYMBOL_GPL(rc_keyup);
+
+/**
+ * ir_timer_keyup() - generates a keyup event after a timeout
+ * @cookie:	a pointer to the struct rc_dev for the device
+ *
+ * This routine will generate a keyup event some time after a keydown event
+ * is generated when no further activity has been detected.
+ */
+static void ir_timer_keyup(unsigned long cookie)
+{
+	struct rc_dev *dev = (struct rc_dev *)cookie;
+	unsigned long flags;
+
+	/*
+	 * ir->keyup_jiffies is used to prevent a race condition if a
+	 * hardware interrupt occurs at this point and the keyup timer
+	 * event is moved further into the future as a result.
+	 *
+	 * The timer will then be reactivated and this function called
+	 * again in the future. We need to exit gracefully in that case
+	 * to allow the input subsystem to do its auto-repeat magic or
+	 * a keyup event might follow immediately after the keydown.
+	 */
+	spin_lock_irqsave(&dev->keylock, flags);
+	if (time_is_before_eq_jiffies(dev->keyup_jiffies))
+		ir_do_keyup(dev);
+	spin_unlock_irqrestore(&dev->keylock, flags);
+}
+
+/**
+ * rc_repeat() - signals that a key is still pressed
+ * @dev:	the struct rc_dev descriptor of the device
+ *
+ * This routine is used by IR decoders when a repeat message which does
+ * not include the necessary bits to reproduce the scancode has been
+ * received.
+ */
+void rc_repeat(struct rc_dev *dev)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&dev->keylock, flags);
+
+	input_event(dev->input_dev, EV_MSC, MSC_SCAN, dev->last_scancode);
+
+	if (!dev->keypressed)
+		goto out;
+
+	dev->keyup_jiffies = jiffies + msecs_to_jiffies(IR_KEYPRESS_TIMEOUT);
+	mod_timer(&dev->timer_keyup, dev->keyup_jiffies);
+
+out:
+	spin_unlock_irqrestore(&dev->keylock, flags);
+}
+EXPORT_SYMBOL_GPL(rc_repeat);
+
+/**
+ * ir_do_keydown() - internal function to process a keypress
+ * @dev:	the struct rc_dev descriptor of the device
+ * @scancode:   the scancode of the keypress
+ * @keycode:    the keycode of the keypress
+ * @toggle:     the toggle value of the keypress
+ *
+ * This function is used internally to register a keypress, it must be
+ * called with keylock held.
+ */
+static void ir_do_keydown(struct rc_dev *dev, int scancode,
+			  u32 keycode, u8 toggle)
+{
+	input_event(dev->input_dev, EV_MSC, MSC_SCAN, scancode);
+
+	/* Repeat event? */
+	if (dev->keypressed &&
+	    dev->last_scancode == scancode &&
+	    dev->last_toggle == toggle)
+		return;
+
+	/* Release old keypress */
+	ir_do_keyup(dev);
+
+	dev->last_scancode = scancode;
+	dev->last_toggle = toggle;
+	dev->last_keycode = keycode;
+
+	if (keycode == KEY_RESERVED)
+		return;
+
+	/* Register a keypress */
+	dev->keypressed = true;
+	IR_dprintk(1, "%s: key down event, key 0x%04x, scancode 0x%04x\n",
+		   dev->input_name, keycode, scancode);
+	input_report_key(dev->input_dev, dev->last_keycode, 1);
+	input_sync(dev->input_dev);
+}
+
+/**
+ * rc_keydown() - generates input event for a key press
+ * @dev:	the struct rc_dev descriptor of the device
+ * @scancode:   the scancode that we're seeking
+ * @toggle:     the toggle value (protocol dependent, if the protocol doesn't
+ *              support toggle values, this should be set to zero)
+ *
+ * This routine is used to signal that a key has been pressed on the
+ * remote control.
+ */
+void rc_keydown(struct rc_dev *dev, int scancode, u8 toggle)
+{
+	unsigned long flags;
+	u32 keycode = rc_g_keycode_from_table(dev, scancode);
+
+	spin_lock_irqsave(&dev->keylock, flags);
+	ir_do_keydown(dev, scancode, keycode, toggle);
+
+	if (dev->keypressed) {
+		dev->keyup_jiffies = jiffies + msecs_to_jiffies(IR_KEYPRESS_TIMEOUT);
+		mod_timer(&dev->timer_keyup, dev->keyup_jiffies);
+	}
+	spin_unlock_irqrestore(&dev->keylock, flags);
+}
+EXPORT_SYMBOL_GPL(rc_keydown);
+
+/**
+ * rc_keydown_notimeout() - generates input event for a key press without
+ *                          an automatic keyup event at a later time
+ * @dev:	the struct rc_dev descriptor of the device
+ * @scancode:   the scancode that we're seeking
+ * @toggle:     the toggle value (protocol dependent, if the protocol doesn't
+ *              support toggle values, this should be set to zero)
+ *
+ * This routine is used to signal that a key has been pressed on the
+ * remote control. The driver must manually call rc_keyup() at a later stage.
+ */
+void rc_keydown_notimeout(struct rc_dev *dev, int scancode, u8 toggle)
+{
+	unsigned long flags;
+	u32 keycode = rc_g_keycode_from_table(dev, scancode);
+
+	spin_lock_irqsave(&dev->keylock, flags);
+	ir_do_keydown(dev, scancode, keycode, toggle);
+	spin_unlock_irqrestore(&dev->keylock, flags);
+}
+EXPORT_SYMBOL_GPL(rc_keydown_notimeout);
+
+static int ir_open(struct input_dev *idev)
+{
+	struct rc_dev *rdev = input_get_drvdata(idev);
+
+	return rdev->open(rdev);
+}
+
+static void ir_close(struct input_dev *idev)
+{
+	struct rc_dev *rdev = input_get_drvdata(idev);
+
+	rdev->close(rdev);
+}
+
+/* class for /sys/class/rc */
+static char *ir_devnode(struct device *dev, mode_t *mode)
+{
+	return kasprintf(GFP_KERNEL, "rc/%s", dev_name(dev));
+}
+
+static struct class ir_input_class = {
+	.name		= "rc",
+	.devnode	= ir_devnode,
+};
+
+static struct {
+	u64	type;
+	char	*name;
+} proto_names[] = {
+	{ RC_TYPE_UNKNOWN,	"unknown"	},
+	{ RC_TYPE_RC5,		"rc-5"		},
+	{ RC_TYPE_NEC,		"nec"		},
+	{ RC_TYPE_RC6,		"rc-6"		},
+	{ RC_TYPE_JVC,		"jvc"		},
+	{ RC_TYPE_SONY,		"sony"		},
+	{ RC_TYPE_RC5_SZ,	"rc-5-sz"	},
+	{ RC_TYPE_LIRC,		"lirc"		},
+};
+
+#define PROTO_NONE	"none"
+
+/**
+ * show_protocols() - shows the current IR protocol(s)
+ * @device:	the device descriptor
+ * @mattr:	the device attribute struct (unused)
+ * @buf:	a pointer to the output buffer
+ *
+ * This routine is a callback routine for input read the IR protocol type(s).
+ * it is trigged by reading /sys/class/rc/rc?/protocols.
+ * It returns the protocol names of supported protocols.
+ * Enabled protocols are printed in brackets.
+ */
+static ssize_t show_protocols(struct device *device,
+			      struct device_attribute *mattr, char *buf)
+{
+	struct rc_dev *dev = to_rc_dev(device);
+	u64 allowed, enabled;
+	char *tmp = buf;
+	int i;
+
+	/* Device is being removed */
+	if (!dev)
+		return -EINVAL;
+
+	if (dev->driver_type == RC_DRIVER_SCANCODE) {
+		enabled = dev->rc_map.rc_type;
+		allowed = dev->allowed_protos;
+	} else {
+		enabled = dev->raw->enabled_protocols;
+		allowed = ir_raw_get_allowed_protocols();
+	}
+
+	IR_dprintk(1, "allowed - 0x%llx, enabled - 0x%llx\n",
+		   (long long)allowed,
+		   (long long)enabled);
+
+	for (i = 0; i < ARRAY_SIZE(proto_names); i++) {
+		if (allowed & enabled & proto_names[i].type)
+			tmp += sprintf(tmp, "[%s] ", proto_names[i].name);
+		else if (allowed & proto_names[i].type)
+			tmp += sprintf(tmp, "%s ", proto_names[i].name);
+	}
+
+	if (tmp != buf)
+		tmp--;
+	*tmp = '\n';
+	return tmp + 1 - buf;
+}
+
+/**
+ * store_protocols() - changes the current IR protocol(s)
+ * @device:	the device descriptor
+ * @mattr:	the device attribute struct (unused)
+ * @buf:	a pointer to the input buffer
+ * @len:	length of the input buffer
+ *
+ * This routine is for changing the IR protocol type.
+ * It is trigged by writing to /sys/class/rc/rc?/protocols.
+ * Writing "+proto" will add a protocol to the list of enabled protocols.
+ * Writing "-proto" will remove a protocol from the list of enabled protocols.
+ * Writing "proto" will enable only "proto".
+ * Writing "none" will disable all protocols.
+ * Returns -EINVAL if an invalid protocol combination or unknown protocol name
+ * is used, otherwise @len.
+ */
+static ssize_t store_protocols(struct device *device,
+			       struct device_attribute *mattr,
+			       const char *data,
+			       size_t len)
+{
+	struct rc_dev *dev = to_rc_dev(device);
+	bool enable, disable;
+	const char *tmp;
+	u64 type;
+	u64 mask;
+	int rc, i, count = 0;
+	unsigned long flags;
+
+	/* Device is being removed */
+	if (!dev)
+		return -EINVAL;
+
+	if (dev->driver_type == RC_DRIVER_SCANCODE)
+		type = dev->rc_map.rc_type;
+	else if (dev->raw)
+		type = dev->raw->enabled_protocols;
+	else {
+		IR_dprintk(1, "Protocol switching not supported\n");
+		return -EINVAL;
+	}
+
+	while ((tmp = strsep((char **) &data, " \n")) != NULL) {
+		if (!*tmp)
+			break;
+
+		if (*tmp == '+') {
+			enable = true;
+			disable = false;
+			tmp++;
+		} else if (*tmp == '-') {
+			enable = false;
+			disable = true;
+			tmp++;
+		} else {
+			enable = false;
+			disable = false;
+		}
+
+		if (!enable && !disable && !strncasecmp(tmp, PROTO_NONE, sizeof(PROTO_NONE))) {
+			tmp += sizeof(PROTO_NONE);
+			mask = 0;
+			count++;
+		} else {
+			for (i = 0; i < ARRAY_SIZE(proto_names); i++) {
+				if (!strcasecmp(tmp, proto_names[i].name)) {
+					tmp += strlen(proto_names[i].name);
+					mask = proto_names[i].type;
+					break;
+				}
+			}
+			if (i == ARRAY_SIZE(proto_names)) {
+				IR_dprintk(1, "Unknown protocol: '%s'\n", tmp);
+				return -EINVAL;
+			}
+			count++;
+		}
+
+		if (enable)
+			type |= mask;
+		else if (disable)
+			type &= ~mask;
+		else
+			type = mask;
+	}
+
+	if (!count) {
+		IR_dprintk(1, "Protocol not specified\n");
+		return -EINVAL;
+	}
+
+	if (dev->change_protocol) {
+		rc = dev->change_protocol(dev, type);
+		if (rc < 0) {
+			IR_dprintk(1, "Error setting protocols to 0x%llx\n",
+				   (long long)type);
+			return -EINVAL;
+		}
+	}
+
+	if (dev->driver_type == RC_DRIVER_SCANCODE) {
+		spin_lock_irqsave(&dev->rc_map.lock, flags);
+		dev->rc_map.rc_type = type;
+		spin_unlock_irqrestore(&dev->rc_map.lock, flags);
+	} else {
+		dev->raw->enabled_protocols = type;
+	}
+
+	IR_dprintk(1, "Current protocol(s): 0x%llx\n",
+		   (long long)type);
+
+	return len;
+}
+
+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...)					\
+	do {								\
+		int err = add_uevent_var(env, fmt, val);		\
+		if (err)						\
+			return err;					\
+	} while (0)
+
+static int rc_dev_uevent(struct device *device, struct kobj_uevent_env *env)
+{
+	struct rc_dev *dev = to_rc_dev(device);
+
+	if (dev->rc_map.name)
+		ADD_HOTPLUG_VAR("NAME=%s", dev->rc_map.name);
+	if (dev->driver_name)
+		ADD_HOTPLUG_VAR("DRV_NAME=%s", dev->driver_name);
+
+	return 0;
+}
+
+/*
+ * Static device attribute struct with the sysfs attributes for IR's
+ */
+static DEVICE_ATTR(protocols, S_IRUGO | S_IWUSR,
+		   show_protocols, store_protocols);
+
+static struct attribute *rc_dev_attrs[] = {
+	&dev_attr_protocols.attr,
+	NULL,
+};
+
+static struct attribute_group rc_dev_attr_grp = {
+	.attrs	= rc_dev_attrs,
+};
+
+static const struct attribute_group *rc_dev_attr_groups[] = {
+	&rc_dev_attr_grp,
+	NULL
+};
+
+static struct device_type rc_dev_type = {
+	.groups		= rc_dev_attr_groups,
+	.release	= rc_dev_release,
+	.uevent		= rc_dev_uevent,
+};
+
+struct rc_dev *rc_allocate_device(void)
+{
+	struct rc_dev *dev;
+
+	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+	if (!dev)
+		return NULL;
+
+	dev->input_dev = input_allocate_device();
+	if (!dev->input_dev) {
+		kfree(dev);
+		return NULL;
+	}
+
+	dev->input_dev->getkeycode_new = ir_getkeycode;
+	dev->input_dev->setkeycode_new = ir_setkeycode;
+	input_set_drvdata(dev->input_dev, dev);
+
+	spin_lock_init(&dev->rc_map.lock);
+	spin_lock_init(&dev->keylock);
+	setup_timer(&dev->timer_keyup, ir_timer_keyup, (unsigned long)dev);
+
+	dev->dev.type = &rc_dev_type;
+	dev->dev.class = &ir_input_class;
+	device_initialize(&dev->dev);
+
+	__module_get(THIS_MODULE);
+	return dev;
+}
+EXPORT_SYMBOL_GPL(rc_allocate_device);
+
+void rc_free_device(struct rc_dev *dev)
+{
+	if (dev) {
+		input_free_device(dev->input_dev);
+		put_device(&dev->dev);
+	}
+}
+EXPORT_SYMBOL_GPL(rc_free_device);
+
+int rc_register_device(struct rc_dev *dev)
+{
+	static atomic_t devno = ATOMIC_INIT(0);
+	struct rc_map *rc_map;
+	const char *path;
+	int rc;
+
+	if (!dev || !dev->map_name)
+		return -EINVAL;
+
+	rc_map = rc_map_get(dev->map_name);
+	if (!rc_map)
+		rc_map = rc_map_get(RC_MAP_EMPTY);
+	if (!rc_map || !rc_map->scan || rc_map->size == 0)
+		return -EINVAL;
+
+	set_bit(EV_KEY, dev->input_dev->evbit);
+	set_bit(EV_REP, dev->input_dev->evbit);
+	set_bit(EV_MSC, dev->input_dev->evbit);
+	set_bit(MSC_SCAN, dev->input_dev->mscbit);
+	if (dev->open)
+		dev->input_dev->open = ir_open;
+	if (dev->close)
+		dev->input_dev->close = ir_close;
+
+	dev->devno = (unsigned long)(atomic_inc_return(&devno) - 1);
+	dev_set_name(&dev->dev, "rc%ld", dev->devno);
+	dev_set_drvdata(&dev->dev, dev);
+	rc = device_add(&dev->dev);
+	if (rc)
+		return rc;
+
+	rc = ir_setkeytable(dev, rc_map);
+	if (rc)
+		goto out_dev;
+
+	dev->input_dev->dev.parent = &dev->dev;
+	memcpy(&dev->input_dev->id, &dev->input_id, sizeof(dev->input_id));
+	dev->input_dev->phys = dev->input_phys;
+	dev->input_dev->name = dev->input_name;
+	rc = input_register_device(dev->input_dev);
+	if (rc)
+		goto out_table;
+
+	/*
+	 * Default delay of 250ms is too short for some protocols, expecially
+	 * since the timeout is currently set to 250ms. Increase it to 500ms,
+	 * to avoid wrong repetition of the keycodes. Note that this must be
+	 * set after the call to input_register_device().
+	 */
+	dev->input_dev->rep[REP_DELAY] = 500;
+
+	path = kobject_get_path(&dev->dev.kobj, GFP_KERNEL);
+	printk(KERN_INFO "%s: %s as %s\n",
+		dev_name(&dev->dev),
+		dev->input_name ? dev->input_name : "Unspecified device",
+		path ? path : "N/A");
+	kfree(path);
+
+	if (dev->driver_type == RC_DRIVER_IR_RAW) {
+		rc = ir_raw_event_register(dev);
+		if (rc < 0)
+			goto out_input;
+	}
+
+	if (dev->change_protocol) {
+		rc = dev->change_protocol(dev, rc_map->rc_type);
+		if (rc < 0)
+			goto out_raw;
+	}
+
+	IR_dprintk(1, "Registered rc%ld (driver: %s, remote: %s, mode %s)\n",
+		   dev->devno,
+		   dev->driver_name ? dev->driver_name : "unknown",
+		   rc_map->name ? rc_map->name : "unknown",
+		   dev->driver_type == RC_DRIVER_IR_RAW ? "raw" : "cooked");
+
+	return 0;
+
+out_raw:
+	if (dev->driver_type == RC_DRIVER_IR_RAW)
+		ir_raw_event_unregister(dev);
+out_input:
+	input_unregister_device(dev->input_dev);
+	dev->input_dev = NULL;
+out_table:
+	ir_free_table(&dev->rc_map);
+out_dev:
+	device_del(&dev->dev);
+	return rc;
+}
+EXPORT_SYMBOL_GPL(rc_register_device);
+
+void rc_unregister_device(struct rc_dev *dev)
+{
+	if (!dev)
+		return;
+
+	del_timer_sync(&dev->timer_keyup);
+
+	if (dev->driver_type == RC_DRIVER_IR_RAW)
+		ir_raw_event_unregister(dev);
+
+	input_unregister_device(dev->input_dev);
+	dev->input_dev = NULL;
+
+	ir_free_table(&dev->rc_map);
+	IR_dprintk(1, "Freed keycode table\n");
+
+	device_unregister(&dev->dev);
+}
+EXPORT_SYMBOL_GPL(rc_unregister_device);
+
+/*
+ * Init/exit code for the module. Basically, creates/removes /sys/class/rc
+ */
+
+static int __init rc_core_init(void)
+{
+	int rc = class_register(&ir_input_class);
+	if (rc) {
+		printk(KERN_ERR "rc_core: unable to register rc class\n");
+		return rc;
+	}
+
+	/* Initialize/load the decoders/keymap code that will be used */
+	ir_raw_init();
+	rc_map_register(&empty_map);
+
+	return 0;
+}
+
+static void __exit rc_core_exit(void)
+{
+	class_unregister(&ir_input_class);
+	rc_map_unregister(&empty_map);
+}
+
+module_init(rc_core_init);
+module_exit(rc_core_exit);
+
+int rc_core_debug;    /* ir_debug level (0,1,2) */
+EXPORT_SYMBOL_GPL(rc_core_debug);
+module_param_named(debug, rc_core_debug, int, 0644);
+
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
+MODULE_LICENSE("GPL");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/streamzap.c linux-libre-2.6.38-gnu1/drivers/media/rc/streamzap.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/streamzap.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/streamzap.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,559 @@
+/*
+ * Streamzap Remote Control driver
+ *
+ * Copyright (c) 2005 Christoph Bartelmus <lirc@bartelmus.de>
+ * Copyright (c) 2010 Jarod Wilson <jarod@wilsonet.com>
+ *
+ * This driver was based on the work of Greg Wickham and Adrian
+ * Dewhurst. It was substantially rewritten to support correct signal
+ * gaps and now maintains a delay buffer, which is used to present
+ * consistent timing behaviour to user space applications. Without the
+ * delay buffer an ugly hack would be required in lircd, which can
+ * cause sluggish signal decoding in certain situations.
+ *
+ * Ported to in-kernel ir-core interface by Jarod Wilson
+ *
+ * This driver is based on the USB skeleton driver packaged with the
+ * kernel; copyright (C) 2001-2003 Greg Kroah-Hartman (greg@kroah.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/device.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/usb.h>
+#include <linux/usb/input.h>
+#include <media/rc-core.h>
+
+#define DRIVER_VERSION	"1.61"
+#define DRIVER_NAME	"streamzap"
+#define DRIVER_DESC	"Streamzap Remote Control driver"
+
+#ifdef CONFIG_USB_DEBUG
+static int debug = 1;
+#else
+static int debug;
+#endif
+
+#define USB_STREAMZAP_VENDOR_ID		0x0e9c
+#define USB_STREAMZAP_PRODUCT_ID	0x0000
+
+/* table of devices that work with this driver */
+static struct usb_device_id streamzap_table[] = {
+	/* Streamzap Remote Control */
+	{ USB_DEVICE(USB_STREAMZAP_VENDOR_ID, USB_STREAMZAP_PRODUCT_ID) },
+	/* Terminating entry */
+	{ }
+};
+
+MODULE_DEVICE_TABLE(usb, streamzap_table);
+
+#define SZ_PULSE_MASK 0xf0
+#define SZ_SPACE_MASK 0x0f
+#define SZ_TIMEOUT    0xff
+#define SZ_RESOLUTION 256
+
+/* number of samples buffered */
+#define SZ_BUF_LEN 128
+
+/* from ir-rc5-sz-decoder.c */
+#ifdef CONFIG_IR_RC5_SZ_DECODER_MODULE
+#define load_rc5_sz_decode()    request_module("ir-rc5-sz-decoder")
+#else
+#define load_rc5_sz_decode()    {}
+#endif
+
+enum StreamzapDecoderState {
+	PulseSpace,
+	FullPulse,
+	FullSpace,
+	IgnorePulse
+};
+
+/* structure to hold our device specific stuff */
+struct streamzap_ir {
+	/* ir-core */
+	struct rc_dev *rdev;
+
+	/* core device info */
+	struct device *dev;
+
+	/* usb */
+	struct usb_device	*usbdev;
+	struct usb_interface	*interface;
+	struct usb_endpoint_descriptor *endpoint;
+	struct urb		*urb_in;
+
+	/* buffer & dma */
+	unsigned char		*buf_in;
+	dma_addr_t		dma_in;
+	unsigned int		buf_in_len;
+
+	/* track what state we're in */
+	enum StreamzapDecoderState decoder_state;
+	/* tracks whether we are currently receiving some signal */
+	bool			idle;
+	/* sum of signal lengths received since signal start */
+	unsigned long		sum;
+	/* start time of signal; necessary for gap tracking */
+	struct timeval		signal_last;
+	struct timeval		signal_start;
+	bool			timeout_enabled;
+
+	char			name[128];
+	char			phys[64];
+};
+
+
+/* local function prototypes */
+static int streamzap_probe(struct usb_interface *interface,
+			   const struct usb_device_id *id);
+static void streamzap_disconnect(struct usb_interface *interface);
+static void streamzap_callback(struct urb *urb);
+static int streamzap_suspend(struct usb_interface *intf, pm_message_t message);
+static int streamzap_resume(struct usb_interface *intf);
+
+/* usb specific object needed to register this driver with the usb subsystem */
+static struct usb_driver streamzap_driver = {
+	.name =		DRIVER_NAME,
+	.probe =	streamzap_probe,
+	.disconnect =	streamzap_disconnect,
+	.suspend =	streamzap_suspend,
+	.resume =	streamzap_resume,
+	.id_table =	streamzap_table,
+};
+
+static void sz_push(struct streamzap_ir *sz, struct ir_raw_event rawir)
+{
+	dev_dbg(sz->dev, "Storing %s with duration %u us\n",
+		(rawir.pulse ? "pulse" : "space"), rawir.duration);
+	ir_raw_event_store_with_filter(sz->rdev, &rawir);
+}
+
+static void sz_push_full_pulse(struct streamzap_ir *sz,
+			       unsigned char value)
+{
+	DEFINE_IR_RAW_EVENT(rawir);
+
+	if (sz->idle) {
+		long deltv;
+
+		sz->signal_last = sz->signal_start;
+		do_gettimeofday(&sz->signal_start);
+
+		deltv = sz->signal_start.tv_sec - sz->signal_last.tv_sec;
+		rawir.pulse = false;
+		if (deltv > 15) {
+			/* really long time */
+			rawir.duration = IR_MAX_DURATION;
+		} else {
+			rawir.duration = (int)(deltv * 1000000 +
+				sz->signal_start.tv_usec -
+				sz->signal_last.tv_usec);
+			rawir.duration -= sz->sum;
+			rawir.duration = US_TO_NS(rawir.duration);
+			rawir.duration &= IR_MAX_DURATION;
+		}
+		sz_push(sz, rawir);
+
+		sz->idle = false;
+		sz->sum = 0;
+	}
+
+	rawir.pulse = true;
+	rawir.duration = ((int) value) * SZ_RESOLUTION;
+	rawir.duration += SZ_RESOLUTION / 2;
+	sz->sum += rawir.duration;
+	rawir.duration = US_TO_NS(rawir.duration);
+	rawir.duration &= IR_MAX_DURATION;
+	sz_push(sz, rawir);
+}
+
+static void sz_push_half_pulse(struct streamzap_ir *sz,
+			       unsigned char value)
+{
+	sz_push_full_pulse(sz, (value & SZ_PULSE_MASK) >> 4);
+}
+
+static void sz_push_full_space(struct streamzap_ir *sz,
+			       unsigned char value)
+{
+	DEFINE_IR_RAW_EVENT(rawir);
+
+	rawir.pulse = false;
+	rawir.duration = ((int) value) * SZ_RESOLUTION;
+	rawir.duration += SZ_RESOLUTION / 2;
+	sz->sum += rawir.duration;
+	rawir.duration = US_TO_NS(rawir.duration);
+	sz_push(sz, rawir);
+}
+
+static void sz_push_half_space(struct streamzap_ir *sz,
+			       unsigned long value)
+{
+	sz_push_full_space(sz, value & SZ_SPACE_MASK);
+}
+
+/**
+ * streamzap_callback - usb IRQ handler callback
+ *
+ * This procedure is invoked on reception of data from
+ * the usb remote.
+ */
+static void streamzap_callback(struct urb *urb)
+{
+	struct streamzap_ir *sz;
+	unsigned int i;
+	int len;
+
+	if (!urb)
+		return;
+
+	sz = urb->context;
+	len = urb->actual_length;
+
+	switch (urb->status) {
+	case -ECONNRESET:
+	case -ENOENT:
+	case -ESHUTDOWN:
+		/*
+		 * this urb is terminated, clean up.
+		 * sz might already be invalid at this point
+		 */
+		dev_err(sz->dev, "urb terminated, status: %d\n", urb->status);
+		return;
+	default:
+		break;
+	}
+
+	dev_dbg(sz->dev, "%s: received urb, len %d\n", __func__, len);
+	for (i = 0; i < len; i++) {
+		dev_dbg(sz->dev, "sz->buf_in[%d]: %x\n",
+			i, (unsigned char)sz->buf_in[i]);
+		switch (sz->decoder_state) {
+		case PulseSpace:
+			if ((sz->buf_in[i] & SZ_PULSE_MASK) ==
+				SZ_PULSE_MASK) {
+				sz->decoder_state = FullPulse;
+				continue;
+			} else if ((sz->buf_in[i] & SZ_SPACE_MASK)
+					== SZ_SPACE_MASK) {
+				sz_push_half_pulse(sz, sz->buf_in[i]);
+				sz->decoder_state = FullSpace;
+				continue;
+			} else {
+				sz_push_half_pulse(sz, sz->buf_in[i]);
+				sz_push_half_space(sz, sz->buf_in[i]);
+			}
+			break;
+		case FullPulse:
+			sz_push_full_pulse(sz, sz->buf_in[i]);
+			sz->decoder_state = IgnorePulse;
+			break;
+		case FullSpace:
+			if (sz->buf_in[i] == SZ_TIMEOUT) {
+				DEFINE_IR_RAW_EVENT(rawir);
+
+				rawir.pulse = false;
+				rawir.duration = sz->rdev->timeout;
+				sz->idle = true;
+				if (sz->timeout_enabled)
+					sz_push(sz, rawir);
+				ir_raw_event_handle(sz->rdev);
+				ir_raw_event_reset(sz->rdev);
+			} else {
+				sz_push_full_space(sz, sz->buf_in[i]);
+			}
+			sz->decoder_state = PulseSpace;
+			break;
+		case IgnorePulse:
+			if ((sz->buf_in[i] & SZ_SPACE_MASK) ==
+				SZ_SPACE_MASK) {
+				sz->decoder_state = FullSpace;
+				continue;
+			}
+			sz_push_half_space(sz, sz->buf_in[i]);
+			sz->decoder_state = PulseSpace;
+			break;
+		}
+	}
+
+	ir_raw_event_handle(sz->rdev);
+	usb_submit_urb(urb, GFP_ATOMIC);
+
+	return;
+}
+
+static struct rc_dev *streamzap_init_rc_dev(struct streamzap_ir *sz)
+{
+	struct rc_dev *rdev;
+	struct device *dev = sz->dev;
+	int ret;
+
+	rdev = rc_allocate_device();
+	if (!rdev) {
+		dev_err(dev, "remote dev allocation failed\n");
+		goto out;
+	}
+
+	snprintf(sz->name, sizeof(sz->name), "Streamzap PC Remote Infrared "
+		 "Receiver (%04x:%04x)",
+		 le16_to_cpu(sz->usbdev->descriptor.idVendor),
+		 le16_to_cpu(sz->usbdev->descriptor.idProduct));
+	usb_make_path(sz->usbdev, sz->phys, sizeof(sz->phys));
+	strlcat(sz->phys, "/input0", sizeof(sz->phys));
+
+	rdev->input_name = sz->name;
+	rdev->input_phys = sz->phys;
+	usb_to_input_id(sz->usbdev, &rdev->input_id);
+	rdev->dev.parent = dev;
+	rdev->priv = sz;
+	rdev->driver_type = RC_DRIVER_IR_RAW;
+	rdev->allowed_protos = RC_TYPE_ALL;
+	rdev->driver_name = DRIVER_NAME;
+	rdev->map_name = RC_MAP_STREAMZAP;
+
+	ret = rc_register_device(rdev);
+	if (ret < 0) {
+		dev_err(dev, "remote input device register failed\n");
+		goto out;
+	}
+
+	return rdev;
+
+out:
+	rc_free_device(rdev);
+	return NULL;
+}
+
+/**
+ *	streamzap_probe
+ *
+ *	Called by usb-core to associated with a candidate device
+ *	On any failure the return value is the ERROR
+ *	On success return 0
+ */
+static int __devinit streamzap_probe(struct usb_interface *intf,
+				     const struct usb_device_id *id)
+{
+	struct usb_device *usbdev = interface_to_usbdev(intf);
+	struct usb_host_interface *iface_host;
+	struct streamzap_ir *sz = NULL;
+	char buf[63], name[128] = "";
+	int retval = -ENOMEM;
+	int pipe, maxp;
+
+	/* Allocate space for device driver specific data */
+	sz = kzalloc(sizeof(struct streamzap_ir), GFP_KERNEL);
+	if (!sz)
+		return -ENOMEM;
+
+	sz->usbdev = usbdev;
+	sz->interface = intf;
+
+	/* Check to ensure endpoint information matches requirements */
+	iface_host = intf->cur_altsetting;
+
+	if (iface_host->desc.bNumEndpoints != 1) {
+		dev_err(&intf->dev, "%s: Unexpected desc.bNumEndpoints (%d)\n",
+			__func__, iface_host->desc.bNumEndpoints);
+		retval = -ENODEV;
+		goto free_sz;
+	}
+
+	sz->endpoint = &(iface_host->endpoint[0].desc);
+	if ((sz->endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
+	    != USB_DIR_IN) {
+		dev_err(&intf->dev, "%s: endpoint doesn't match input device "
+			"02%02x\n", __func__, sz->endpoint->bEndpointAddress);
+		retval = -ENODEV;
+		goto free_sz;
+	}
+
+	if ((sz->endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
+	    != USB_ENDPOINT_XFER_INT) {
+		dev_err(&intf->dev, "%s: endpoint attributes don't match xfer "
+			"02%02x\n", __func__, sz->endpoint->bmAttributes);
+		retval = -ENODEV;
+		goto free_sz;
+	}
+
+	pipe = usb_rcvintpipe(usbdev, sz->endpoint->bEndpointAddress);
+	maxp = usb_maxpacket(usbdev, pipe, usb_pipeout(pipe));
+
+	if (maxp == 0) {
+		dev_err(&intf->dev, "%s: endpoint Max Packet Size is 0!?!\n",
+			__func__);
+		retval = -ENODEV;
+		goto free_sz;
+	}
+
+	/* Allocate the USB buffer and IRQ URB */
+	sz->buf_in = usb_alloc_coherent(usbdev, maxp, GFP_ATOMIC, &sz->dma_in);
+	if (!sz->buf_in)
+		goto free_sz;
+
+	sz->urb_in = usb_alloc_urb(0, GFP_KERNEL);
+	if (!sz->urb_in)
+		goto free_buf_in;
+
+	sz->dev = &intf->dev;
+	sz->buf_in_len = maxp;
+
+	if (usbdev->descriptor.iManufacturer
+	    && usb_string(usbdev, usbdev->descriptor.iManufacturer,
+			  buf, sizeof(buf)) > 0)
+		strlcpy(name, buf, sizeof(name));
+
+	if (usbdev->descriptor.iProduct
+	    && usb_string(usbdev, usbdev->descriptor.iProduct,
+			  buf, sizeof(buf)) > 0)
+		snprintf(name + strlen(name), sizeof(name) - strlen(name),
+			 " %s", buf);
+
+	sz->rdev = streamzap_init_rc_dev(sz);
+	if (!sz->rdev)
+		goto rc_dev_fail;
+
+	sz->idle = true;
+	sz->decoder_state = PulseSpace;
+	/* FIXME: don't yet have a way to set this */
+	sz->timeout_enabled = true;
+	sz->rdev->timeout = ((US_TO_NS(SZ_TIMEOUT * SZ_RESOLUTION) &
+				IR_MAX_DURATION) | 0x03000000);
+	#if 0
+	/* not yet supported, depends on patches from maxim */
+	/* see also: LIRC_GET_REC_RESOLUTION and LIRC_SET_REC_TIMEOUT */
+	sz->min_timeout = US_TO_NS(SZ_TIMEOUT * SZ_RESOLUTION);
+	sz->max_timeout = US_TO_NS(SZ_TIMEOUT * SZ_RESOLUTION);
+	#endif
+
+	do_gettimeofday(&sz->signal_start);
+
+	/* Complete final initialisations */
+	usb_fill_int_urb(sz->urb_in, usbdev, pipe, sz->buf_in,
+			 maxp, (usb_complete_t)streamzap_callback,
+			 sz, sz->endpoint->bInterval);
+	sz->urb_in->transfer_dma = sz->dma_in;
+	sz->urb_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
+	usb_set_intfdata(intf, sz);
+
+	if (usb_submit_urb(sz->urb_in, GFP_ATOMIC))
+		dev_err(sz->dev, "urb submit failed\n");
+
+	dev_info(sz->dev, "Registered %s on usb%d:%d\n", name,
+		 usbdev->bus->busnum, usbdev->devnum);
+
+	/* Load the streamzap not-quite-rc5 decoder too */
+	load_rc5_sz_decode();
+
+	return 0;
+
+rc_dev_fail:
+	usb_free_urb(sz->urb_in);
+free_buf_in:
+	usb_free_coherent(usbdev, maxp, sz->buf_in, sz->dma_in);
+free_sz:
+	kfree(sz);
+
+	return retval;
+}
+
+/**
+ * streamzap_disconnect
+ *
+ * Called by the usb core when the device is removed from the system.
+ *
+ * This routine guarantees that the driver will not submit any more urbs
+ * by clearing dev->usbdev.  It is also supposed to terminate any currently
+ * active urbs.  Unfortunately, usb_bulk_msg(), used in streamzap_read(),
+ * does not provide any way to do this.
+ */
+static void streamzap_disconnect(struct usb_interface *interface)
+{
+	struct streamzap_ir *sz = usb_get_intfdata(interface);
+	struct usb_device *usbdev = interface_to_usbdev(interface);
+
+	usb_set_intfdata(interface, NULL);
+
+	if (!sz)
+		return;
+
+	sz->usbdev = NULL;
+	rc_unregister_device(sz->rdev);
+	usb_kill_urb(sz->urb_in);
+	usb_free_urb(sz->urb_in);
+	usb_free_coherent(usbdev, sz->buf_in_len, sz->buf_in, sz->dma_in);
+
+	kfree(sz);
+}
+
+static int streamzap_suspend(struct usb_interface *intf, pm_message_t message)
+{
+	struct streamzap_ir *sz = usb_get_intfdata(intf);
+
+	usb_kill_urb(sz->urb_in);
+
+	return 0;
+}
+
+static int streamzap_resume(struct usb_interface *intf)
+{
+	struct streamzap_ir *sz = usb_get_intfdata(intf);
+
+	if (usb_submit_urb(sz->urb_in, GFP_ATOMIC)) {
+		dev_err(sz->dev, "Error sumbiting urb\n");
+		return -EIO;
+	}
+
+	return 0;
+}
+
+/**
+ *	streamzap_init
+ */
+static int __init streamzap_init(void)
+{
+	int ret;
+
+	/* register this driver with the USB subsystem */
+	ret = usb_register(&streamzap_driver);
+	if (ret < 0)
+		printk(KERN_ERR DRIVER_NAME ": usb register failed, "
+		       "result = %d\n", ret);
+
+	return ret;
+}
+
+/**
+ *	streamzap_exit
+ */
+static void __exit streamzap_exit(void)
+{
+	usb_deregister(&streamzap_driver);
+}
+
+
+module_init(streamzap_init);
+module_exit(streamzap_exit);
+
+MODULE_AUTHOR("Jarod Wilson <jarod@wilsonet.com>");
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
+
+module_param(debug, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Enable debugging messages");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/rc/winbond-cir.c linux-libre-2.6.38-gnu1/drivers/media/rc/winbond-cir.c
--- linux-libre-2.6.37-gnu1/drivers/media/rc/winbond-cir.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/rc/winbond-cir.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,932 @@
+/*
+ *  winbond-cir.c - Driver for the Consumer IR functionality of Winbond
+ *                  SuperI/O chips.
+ *
+ *  Currently supports the Winbond WPCD376i chip (PNP id WEC1022), but
+ *  could probably support others (Winbond WEC102X, NatSemi, etc)
+ *  with minor modifications.
+ *
+ *  Original Author: David H�rdeman <david@hardeman.nu>
+ *     Copyright (C) 2009 - 2010 David H�rdeman <david@hardeman.nu>
+ *
+ *  Dedicated to my daughter Matilda, without whose loving attention this
+ *  driver would have been finished in half the time and with a fraction
+ *  of the bugs.
+ *
+ *  Written using:
+ *    o Winbond WPCD376I datasheet helpfully provided by Jesse Barnes at Intel
+ *    o NatSemi PC87338/PC97338 datasheet (for the serial port stuff)
+ *    o DSDT dumps
+ *
+ *  Supported features:
+ *    o Wake-On-CIR functionality
+ *
+ *  To do:
+ *    o Learning
+ *    o IR Transmit
+ *
+ *  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/pnp.h>
+#include <linux/interrupt.h>
+#include <linux/timer.h>
+#include <linux/leds.h>
+#include <linux/spinlock.h>
+#include <linux/pci_ids.h>
+#include <linux/io.h>
+#include <linux/bitrev.h>
+#include <linux/slab.h>
+#include <media/rc-core.h>
+
+#define DRVNAME "winbond-cir"
+
+/* CEIR Wake-Up Registers, relative to data->wbase                      */
+#define WBCIR_REG_WCEIR_CTL	0x03 /* CEIR Receiver Control		*/
+#define WBCIR_REG_WCEIR_STS	0x04 /* CEIR Receiver Status		*/
+#define WBCIR_REG_WCEIR_EV_EN	0x05 /* CEIR Receiver Event Enable	*/
+#define WBCIR_REG_WCEIR_CNTL	0x06 /* CEIR Receiver Counter Low	*/
+#define WBCIR_REG_WCEIR_CNTH	0x07 /* CEIR Receiver Counter High	*/
+#define WBCIR_REG_WCEIR_INDEX	0x08 /* CEIR Receiver Index		*/
+#define WBCIR_REG_WCEIR_DATA	0x09 /* CEIR Receiver Data		*/
+#define WBCIR_REG_WCEIR_CSL	0x0A /* CEIR Re. Compare Strlen		*/
+#define WBCIR_REG_WCEIR_CFG1	0x0B /* CEIR Re. Configuration 1	*/
+#define WBCIR_REG_WCEIR_CFG2	0x0C /* CEIR Re. Configuration 2	*/
+
+/* CEIR Enhanced Functionality Registers, relative to data->ebase       */
+#define WBCIR_REG_ECEIR_CTS	0x00 /* Enhanced IR Control Status	*/
+#define WBCIR_REG_ECEIR_CCTL	0x01 /* Infrared Counter Control	*/
+#define WBCIR_REG_ECEIR_CNT_LO	0x02 /* Infrared Counter LSB		*/
+#define WBCIR_REG_ECEIR_CNT_HI	0x03 /* Infrared Counter MSB		*/
+#define WBCIR_REG_ECEIR_IREM	0x04 /* Infrared Emitter Status		*/
+
+/* SP3 Banked Registers, relative to data->sbase                        */
+#define WBCIR_REG_SP3_BSR	0x03 /* Bank Select, all banks		*/
+				      /* Bank 0				*/
+#define WBCIR_REG_SP3_RXDATA	0x00 /* FIFO RX data (r)		*/
+#define WBCIR_REG_SP3_TXDATA	0x00 /* FIFO TX data (w)		*/
+#define WBCIR_REG_SP3_IER	0x01 /* Interrupt Enable		*/
+#define WBCIR_REG_SP3_EIR	0x02 /* Event Identification (r)	*/
+#define WBCIR_REG_SP3_FCR	0x02 /* FIFO Control (w)		*/
+#define WBCIR_REG_SP3_MCR	0x04 /* Mode Control			*/
+#define WBCIR_REG_SP3_LSR	0x05 /* Link Status			*/
+#define WBCIR_REG_SP3_MSR	0x06 /* Modem Status			*/
+#define WBCIR_REG_SP3_ASCR	0x07 /* Aux Status and Control		*/
+				      /* Bank 2				*/
+#define WBCIR_REG_SP3_BGDL	0x00 /* Baud Divisor LSB		*/
+#define WBCIR_REG_SP3_BGDH	0x01 /* Baud Divisor MSB		*/
+#define WBCIR_REG_SP3_EXCR1	0x02 /* Extended Control 1		*/
+#define WBCIR_REG_SP3_EXCR2	0x04 /* Extended Control 2		*/
+#define WBCIR_REG_SP3_TXFLV	0x06 /* TX FIFO Level			*/
+#define WBCIR_REG_SP3_RXFLV	0x07 /* RX FIFO Level			*/
+				      /* Bank 3				*/
+#define WBCIR_REG_SP3_MRID	0x00 /* Module Identification		*/
+#define WBCIR_REG_SP3_SH_LCR	0x01 /* LCR Shadow			*/
+#define WBCIR_REG_SP3_SH_FCR	0x02 /* FCR Shadow			*/
+				      /* Bank 4				*/
+#define WBCIR_REG_SP3_IRCR1	0x02 /* Infrared Control 1		*/
+				      /* Bank 5				*/
+#define WBCIR_REG_SP3_IRCR2	0x04 /* Infrared Control 2		*/
+				      /* Bank 6				*/
+#define WBCIR_REG_SP3_IRCR3	0x00 /* Infrared Control 3		*/
+#define WBCIR_REG_SP3_SIR_PW	0x02 /* SIR Pulse Width			*/
+				      /* Bank 7				*/
+#define WBCIR_REG_SP3_IRRXDC	0x00 /* IR RX Demod Control		*/
+#define WBCIR_REG_SP3_IRTXMC	0x01 /* IR TX Mod Control		*/
+#define WBCIR_REG_SP3_RCCFG	0x02 /* CEIR Config			*/
+#define WBCIR_REG_SP3_IRCFG1	0x04 /* Infrared Config 1		*/
+#define WBCIR_REG_SP3_IRCFG4	0x07 /* Infrared Config 4		*/
+
+/*
+ * Magic values follow
+ */
+
+/* No interrupts for WBCIR_REG_SP3_IER and WBCIR_REG_SP3_EIR */
+#define WBCIR_IRQ_NONE		0x00
+/* RX data bit for WBCIR_REG_SP3_IER and WBCIR_REG_SP3_EIR */
+#define WBCIR_IRQ_RX		0x01
+/* Over/Under-flow bit for WBCIR_REG_SP3_IER and WBCIR_REG_SP3_EIR */
+#define WBCIR_IRQ_ERR		0x04
+/* Led enable/disable bit for WBCIR_REG_ECEIR_CTS */
+#define WBCIR_LED_ENABLE	0x80
+/* RX data available bit for WBCIR_REG_SP3_LSR */
+#define WBCIR_RX_AVAIL		0x01
+/* RX disable bit for WBCIR_REG_SP3_ASCR */
+#define WBCIR_RX_DISABLE	0x20
+/* Extended mode enable bit for WBCIR_REG_SP3_EXCR1 */
+#define WBCIR_EXT_ENABLE	0x01
+/* Select compare register in WBCIR_REG_WCEIR_INDEX (bits 5 & 6) */
+#define WBCIR_REGSEL_COMPARE	0x10
+/* Select mask register in WBCIR_REG_WCEIR_INDEX (bits 5 & 6) */
+#define WBCIR_REGSEL_MASK	0x20
+/* Starting address of selected register in WBCIR_REG_WCEIR_INDEX */
+#define WBCIR_REG_ADDR0		0x00
+
+/* Valid banks for the SP3 UART */
+enum wbcir_bank {
+	WBCIR_BANK_0          = 0x00,
+	WBCIR_BANK_1          = 0x80,
+	WBCIR_BANK_2          = 0xE0,
+	WBCIR_BANK_3          = 0xE4,
+	WBCIR_BANK_4          = 0xE8,
+	WBCIR_BANK_5          = 0xEC,
+	WBCIR_BANK_6          = 0xF0,
+	WBCIR_BANK_7          = 0xF4,
+};
+
+/* Supported power-on IR Protocols */
+enum wbcir_protocol {
+	IR_PROTOCOL_RC5          = 0x0,
+	IR_PROTOCOL_NEC          = 0x1,
+	IR_PROTOCOL_RC6          = 0x2,
+};
+
+/* Misc */
+#define WBCIR_NAME	"Winbond CIR"
+#define WBCIR_ID_FAMILY          0xF1 /* Family ID for the WPCD376I	*/
+#define	WBCIR_ID_CHIP            0x04 /* Chip ID for the WPCD376I	*/
+#define INVALID_SCANCODE   0x7FFFFFFF /* Invalid with all protos	*/
+#define WAKEUP_IOMEM_LEN         0x10 /* Wake-Up I/O Reg Len		*/
+#define EHFUNC_IOMEM_LEN         0x10 /* Enhanced Func I/O Reg Len	*/
+#define SP_IOMEM_LEN             0x08 /* Serial Port 3 (IR) Reg Len	*/
+
+/* Per-device data */
+struct wbcir_data {
+	spinlock_t spinlock;
+
+	unsigned long wbase;        /* Wake-Up Baseaddr		*/
+	unsigned long ebase;        /* Enhanced Func. Baseaddr	*/
+	unsigned long sbase;        /* Serial Port Baseaddr	*/
+	unsigned int  irq;          /* Serial Port IRQ		*/
+
+	struct rc_dev *dev;
+
+	struct led_trigger *rxtrigger;
+	struct led_trigger *txtrigger;
+	struct led_classdev led;
+
+	/* RX irdata state */
+	bool irdata_active;
+	bool irdata_error;
+	struct ir_raw_event ev;
+};
+
+static enum wbcir_protocol protocol = IR_PROTOCOL_RC6;
+module_param(protocol, uint, 0444);
+MODULE_PARM_DESC(protocol, "IR protocol to use for the power-on command "
+		 "(0 = RC5, 1 = NEC, 2 = RC6A, default)");
+
+static int invert; /* default = 0 */
+module_param(invert, bool, 0444);
+MODULE_PARM_DESC(invert, "Invert the signal from the IR receiver");
+
+static unsigned int wake_sc = 0x800F040C;
+module_param(wake_sc, uint, 0644);
+MODULE_PARM_DESC(wake_sc, "Scancode of the power-on IR command");
+
+static unsigned int wake_rc6mode = 6;
+module_param(wake_rc6mode, uint, 0644);
+MODULE_PARM_DESC(wake_rc6mode, "RC6 mode for the power-on command "
+		 "(0 = 0, 6 = 6A, default)");
+
+
+
+/*****************************************************************************
+ *
+ * UTILITY FUNCTIONS
+ *
+ *****************************************************************************/
+
+/* Caller needs to hold wbcir_lock */
+static void
+wbcir_set_bits(unsigned long addr, u8 bits, u8 mask)
+{
+	u8 val;
+
+	val = inb(addr);
+	val = ((val & ~mask) | (bits & mask));
+	outb(val, addr);
+}
+
+/* Selects the register bank for the serial port */
+static inline void
+wbcir_select_bank(struct wbcir_data *data, enum wbcir_bank bank)
+{
+	outb(bank, data->sbase + WBCIR_REG_SP3_BSR);
+}
+
+static enum led_brightness
+wbcir_led_brightness_get(struct led_classdev *led_cdev)
+{
+	struct wbcir_data *data = container_of(led_cdev,
+					       struct wbcir_data,
+					       led);
+
+	if (inb(data->ebase + WBCIR_REG_ECEIR_CTS) & WBCIR_LED_ENABLE)
+		return LED_FULL;
+	else
+		return LED_OFF;
+}
+
+static void
+wbcir_led_brightness_set(struct led_classdev *led_cdev,
+			 enum led_brightness brightness)
+{
+	struct wbcir_data *data = container_of(led_cdev,
+					       struct wbcir_data,
+					       led);
+
+	wbcir_set_bits(data->ebase + WBCIR_REG_ECEIR_CTS,
+		       brightness == LED_OFF ? 0x00 : WBCIR_LED_ENABLE,
+		       WBCIR_LED_ENABLE);
+}
+
+/* Manchester encodes bits to RC6 message cells (see wbcir_shutdown) */
+static u8
+wbcir_to_rc6cells(u8 val)
+{
+	u8 coded = 0x00;
+	int i;
+
+	val &= 0x0F;
+	for (i = 0; i < 4; i++) {
+		if (val & 0x01)
+			coded |= 0x02 << (i * 2);
+		else
+			coded |= 0x01 << (i * 2);
+		val >>= 1;
+	}
+
+	return coded;
+}
+
+/*****************************************************************************
+ *
+ * INTERRUPT FUNCTIONS
+ *
+ *****************************************************************************/
+
+static irqreturn_t
+wbcir_irq_handler(int irqno, void *cookie)
+{
+	struct pnp_dev *device = cookie;
+	struct wbcir_data *data = pnp_get_drvdata(device);
+	unsigned long flags;
+	u8 irdata[8];
+	u8 disable = true;
+	u8 status;
+	int i;
+
+	spin_lock_irqsave(&data->spinlock, flags);
+
+	wbcir_select_bank(data, WBCIR_BANK_0);
+
+	status = inb(data->sbase + WBCIR_REG_SP3_EIR);
+
+	if (!(status & (WBCIR_IRQ_RX | WBCIR_IRQ_ERR))) {
+		spin_unlock_irqrestore(&data->spinlock, flags);
+		return IRQ_NONE;
+	}
+
+	/* Check for e.g. buffer overflow */
+	if (status & WBCIR_IRQ_ERR) {
+		data->irdata_error = true;
+		ir_raw_event_reset(data->dev);
+	}
+
+	if (!(status & WBCIR_IRQ_RX))
+		goto out;
+
+	if (!data->irdata_active) {
+		data->irdata_active = true;
+		led_trigger_event(data->rxtrigger, LED_FULL);
+	}
+
+	/* Since RXHDLEV is set, at least 8 bytes are in the FIFO */
+	insb(data->sbase + WBCIR_REG_SP3_RXDATA, &irdata[0], 8);
+
+	for (i = 0; i < 8; i++) {
+		u8 pulse;
+		u32 duration;
+
+		if (irdata[i] != 0xFF && irdata[i] != 0x00)
+			disable = false;
+
+		if (data->irdata_error)
+			continue;
+
+		pulse = irdata[i] & 0x80 ? false : true;
+		duration = (irdata[i] & 0x7F) * 10000; /* ns */
+
+		if (data->ev.pulse != pulse) {
+			if (data->ev.duration != 0) {
+				ir_raw_event_store(data->dev, &data->ev);
+				data->ev.duration = 0;
+			}
+
+			data->ev.pulse = pulse;
+		}
+
+		data->ev.duration += duration;
+	}
+
+	if (disable) {
+		if (data->ev.duration != 0 && !data->irdata_error) {
+			ir_raw_event_store(data->dev, &data->ev);
+			data->ev.duration = 0;
+		}
+
+		/* Set RXINACTIVE */
+		outb(WBCIR_RX_DISABLE, data->sbase + WBCIR_REG_SP3_ASCR);
+
+		/* Drain the FIFO */
+		while (inb(data->sbase + WBCIR_REG_SP3_LSR) & WBCIR_RX_AVAIL)
+			inb(data->sbase + WBCIR_REG_SP3_RXDATA);
+
+		ir_raw_event_reset(data->dev);
+		data->irdata_error = false;
+		data->irdata_active = false;
+		led_trigger_event(data->rxtrigger, LED_OFF);
+	}
+
+	ir_raw_event_handle(data->dev);
+
+out:
+	spin_unlock_irqrestore(&data->spinlock, flags);
+	return IRQ_HANDLED;
+}
+
+
+
+/*****************************************************************************
+ *
+ * SETUP/INIT/SUSPEND/RESUME FUNCTIONS
+ *
+ *****************************************************************************/
+
+static void
+wbcir_shutdown(struct pnp_dev *device)
+{
+	struct device *dev = &device->dev;
+	struct wbcir_data *data = pnp_get_drvdata(device);
+	int do_wake = 1;
+	u8 match[11];
+	u8 mask[11];
+	u8 rc6_csl = 0;
+	int i;
+
+	memset(match, 0, sizeof(match));
+	memset(mask, 0, sizeof(mask));
+
+	if (wake_sc == INVALID_SCANCODE || !device_may_wakeup(dev)) {
+		do_wake = 0;
+		goto finish;
+	}
+
+	switch (protocol) {
+	case IR_PROTOCOL_RC5:
+		if (wake_sc > 0xFFF) {
+			do_wake = 0;
+			dev_err(dev, "RC5 - Invalid wake scancode\n");
+			break;
+		}
+
+		/* Mask = 13 bits, ex toggle */
+		mask[0] = 0xFF;
+		mask[1] = 0x17;
+
+		match[0]  = (wake_sc & 0x003F);      /* 6 command bits */
+		match[0] |= (wake_sc & 0x0180) >> 1; /* 2 address bits */
+		match[1]  = (wake_sc & 0x0E00) >> 9; /* 3 address bits */
+		if (!(wake_sc & 0x0040))             /* 2nd start bit  */
+			match[1] |= 0x10;
+
+		break;
+
+	case IR_PROTOCOL_NEC:
+		if (wake_sc > 0xFFFFFF) {
+			do_wake = 0;
+			dev_err(dev, "NEC - Invalid wake scancode\n");
+			break;
+		}
+
+		mask[0] = mask[1] = mask[2] = mask[3] = 0xFF;
+
+		match[1] = bitrev8((wake_sc & 0xFF));
+		match[0] = ~match[1];
+
+		match[3] = bitrev8((wake_sc & 0xFF00) >> 8);
+		if (wake_sc > 0xFFFF)
+			match[2] = bitrev8((wake_sc & 0xFF0000) >> 16);
+		else
+			match[2] = ~match[3];
+
+		break;
+
+	case IR_PROTOCOL_RC6:
+
+		if (wake_rc6mode == 0) {
+			if (wake_sc > 0xFFFF) {
+				do_wake = 0;
+				dev_err(dev, "RC6 - Invalid wake scancode\n");
+				break;
+			}
+
+			/* Command */
+			match[0] = wbcir_to_rc6cells(wake_sc >>  0);
+			mask[0]  = 0xFF;
+			match[1] = wbcir_to_rc6cells(wake_sc >>  4);
+			mask[1]  = 0xFF;
+
+			/* Address */
+			match[2] = wbcir_to_rc6cells(wake_sc >>  8);
+			mask[2]  = 0xFF;
+			match[3] = wbcir_to_rc6cells(wake_sc >> 12);
+			mask[3]  = 0xFF;
+
+			/* Header */
+			match[4] = 0x50; /* mode1 = mode0 = 0, ignore toggle */
+			mask[4]  = 0xF0;
+			match[5] = 0x09; /* start bit = 1, mode2 = 0 */
+			mask[5]  = 0x0F;
+
+			rc6_csl = 44;
+
+		} else if (wake_rc6mode == 6) {
+			i = 0;
+
+			/* Command */
+			match[i]  = wbcir_to_rc6cells(wake_sc >>  0);
+			mask[i++] = 0xFF;
+			match[i]  = wbcir_to_rc6cells(wake_sc >>  4);
+			mask[i++] = 0xFF;
+
+			/* Address + Toggle */
+			match[i]  = wbcir_to_rc6cells(wake_sc >>  8);
+			mask[i++] = 0xFF;
+			match[i]  = wbcir_to_rc6cells(wake_sc >> 12);
+			mask[i++] = 0x3F;
+
+			/* Customer bits 7 - 0 */
+			match[i]  = wbcir_to_rc6cells(wake_sc >> 16);
+			mask[i++] = 0xFF;
+			match[i]  = wbcir_to_rc6cells(wake_sc >> 20);
+			mask[i++] = 0xFF;
+
+			if (wake_sc & 0x80000000) {
+				/* Customer range bit and bits 15 - 8 */
+				match[i]  = wbcir_to_rc6cells(wake_sc >> 24);
+				mask[i++] = 0xFF;
+				match[i]  = wbcir_to_rc6cells(wake_sc >> 28);
+				mask[i++] = 0xFF;
+				rc6_csl = 76;
+			} else if (wake_sc <= 0x007FFFFF) {
+				rc6_csl = 60;
+			} else {
+				do_wake = 0;
+				dev_err(dev, "RC6 - Invalid wake scancode\n");
+				break;
+			}
+
+			/* Header */
+			match[i]  = 0x93; /* mode1 = mode0 = 1, submode = 0 */
+			mask[i++] = 0xFF;
+			match[i]  = 0x0A; /* start bit = 1, mode2 = 1 */
+			mask[i++] = 0x0F;
+
+		} else {
+			do_wake = 0;
+			dev_err(dev, "RC6 - Invalid wake mode\n");
+		}
+
+		break;
+
+	default:
+		do_wake = 0;
+		break;
+	}
+
+finish:
+	if (do_wake) {
+		/* Set compare and compare mask */
+		wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_INDEX,
+			       WBCIR_REGSEL_COMPARE | WBCIR_REG_ADDR0,
+			       0x3F);
+		outsb(data->wbase + WBCIR_REG_WCEIR_DATA, match, 11);
+		wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_INDEX,
+			       WBCIR_REGSEL_MASK | WBCIR_REG_ADDR0,
+			       0x3F);
+		outsb(data->wbase + WBCIR_REG_WCEIR_DATA, mask, 11);
+
+		/* RC6 Compare String Len */
+		outb(rc6_csl, data->wbase + WBCIR_REG_WCEIR_CSL);
+
+		/* Clear status bits NEC_REP, BUFF, MSG_END, MATCH */
+		wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_STS, 0x17, 0x17);
+
+		/* Clear BUFF_EN, Clear END_EN, Set MATCH_EN */
+		wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_EV_EN, 0x01, 0x07);
+
+		/* Set CEIR_EN */
+		wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_CTL, 0x01, 0x01);
+
+	} else {
+		/* Clear BUFF_EN, Clear END_EN, Clear MATCH_EN */
+		wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_EV_EN, 0x00, 0x07);
+
+		/* Clear CEIR_EN */
+		wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_CTL, 0x00, 0x01);
+	}
+
+	/* Disable interrupts */
+	wbcir_select_bank(data, WBCIR_BANK_0);
+	outb(WBCIR_IRQ_NONE, data->sbase + WBCIR_REG_SP3_IER);
+
+	/* Disable LED */
+	data->irdata_active = false;
+	led_trigger_event(data->rxtrigger, LED_OFF);
+
+	/*
+	 * ACPI will set the HW disable bit for SP3 which means that the
+	 * output signals are left in an undefined state which may cause
+	 * spurious interrupts which we need to ignore until the hardware
+	 * is reinitialized.
+	 */
+	disable_irq(data->irq);
+}
+
+static int
+wbcir_suspend(struct pnp_dev *device, pm_message_t state)
+{
+	wbcir_shutdown(device);
+	return 0;
+}
+
+static void
+wbcir_init_hw(struct wbcir_data *data)
+{
+	u8 tmp;
+
+	/* Disable interrupts */
+	wbcir_select_bank(data, WBCIR_BANK_0);
+	outb(WBCIR_IRQ_NONE, data->sbase + WBCIR_REG_SP3_IER);
+
+	/* Set PROT_SEL, RX_INV, Clear CEIR_EN (needed for the led) */
+	tmp = protocol << 4;
+	if (invert)
+		tmp |= 0x08;
+	outb(tmp, data->wbase + WBCIR_REG_WCEIR_CTL);
+
+	/* Clear status bits NEC_REP, BUFF, MSG_END, MATCH */
+	wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_STS, 0x17, 0x17);
+
+	/* Clear BUFF_EN, Clear END_EN, Clear MATCH_EN */
+	wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_EV_EN, 0x00, 0x07);
+
+	/* Set RC5 cell time to correspond to 36 kHz */
+	wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_CFG1, 0x4A, 0x7F);
+
+	/* Set IRTX_INV */
+	if (invert)
+		outb(0x04, data->ebase + WBCIR_REG_ECEIR_CCTL);
+	else
+		outb(0x00, data->ebase + WBCIR_REG_ECEIR_CCTL);
+
+	/*
+	 * Clear IR LED, set SP3 clock to 24Mhz
+	 * set SP3_IRRX_SW to binary 01, helpfully not documented
+	 */
+	outb(0x10, data->ebase + WBCIR_REG_ECEIR_CTS);
+
+	/* Enable extended mode */
+	wbcir_select_bank(data, WBCIR_BANK_2);
+	outb(WBCIR_EXT_ENABLE, data->sbase + WBCIR_REG_SP3_EXCR1);
+
+	/*
+	 * Configure baud generator, IR data will be sampled at
+	 * a bitrate of: (24Mhz * prescaler) / (divisor * 16).
+	 *
+	 * The ECIR registers include a flag to change the
+	 * 24Mhz clock freq to 48Mhz.
+	 *
+	 * It's not documented in the specs, but fifo levels
+	 * other than 16 seems to be unsupported.
+	 */
+
+	/* prescaler 1.0, tx/rx fifo lvl 16 */
+	outb(0x30, data->sbase + WBCIR_REG_SP3_EXCR2);
+
+	/* Set baud divisor to generate one byte per bit/cell */
+	switch (protocol) {
+	case IR_PROTOCOL_RC5:
+		outb(0xA7, data->sbase + WBCIR_REG_SP3_BGDL);
+		break;
+	case IR_PROTOCOL_RC6:
+		outb(0x53, data->sbase + WBCIR_REG_SP3_BGDL);
+		break;
+	case IR_PROTOCOL_NEC:
+		outb(0x69, data->sbase + WBCIR_REG_SP3_BGDL);
+		break;
+	}
+	outb(0x00, data->sbase + WBCIR_REG_SP3_BGDH);
+
+	/* Set CEIR mode */
+	wbcir_select_bank(data, WBCIR_BANK_0);
+	outb(0xC0, data->sbase + WBCIR_REG_SP3_MCR);
+	inb(data->sbase + WBCIR_REG_SP3_LSR); /* Clear LSR */
+	inb(data->sbase + WBCIR_REG_SP3_MSR); /* Clear MSR */
+
+	/* Disable RX demod, run-length encoding/decoding, set freq span */
+	wbcir_select_bank(data, WBCIR_BANK_7);
+	outb(0x10, data->sbase + WBCIR_REG_SP3_RCCFG);
+
+	/* Disable timer */
+	wbcir_select_bank(data, WBCIR_BANK_4);
+	outb(0x00, data->sbase + WBCIR_REG_SP3_IRCR1);
+
+	/* Enable MSR interrupt, Clear AUX_IRX */
+	wbcir_select_bank(data, WBCIR_BANK_5);
+	outb(0x00, data->sbase + WBCIR_REG_SP3_IRCR2);
+
+	/* Disable CRC */
+	wbcir_select_bank(data, WBCIR_BANK_6);
+	outb(0x20, data->sbase + WBCIR_REG_SP3_IRCR3);
+
+	/* Set RX/TX (de)modulation freq, not really used */
+	wbcir_select_bank(data, WBCIR_BANK_7);
+	outb(0xF2, data->sbase + WBCIR_REG_SP3_IRRXDC);
+	outb(0x69, data->sbase + WBCIR_REG_SP3_IRTXMC);
+
+	/* Set invert and pin direction */
+	if (invert)
+		outb(0x10, data->sbase + WBCIR_REG_SP3_IRCFG4);
+	else
+		outb(0x00, data->sbase + WBCIR_REG_SP3_IRCFG4);
+
+	/* Set FIFO thresholds (RX = 8, TX = 3), reset RX/TX */
+	wbcir_select_bank(data, WBCIR_BANK_0);
+	outb(0x97, data->sbase + WBCIR_REG_SP3_FCR);
+
+	/* Clear AUX status bits */
+	outb(0xE0, data->sbase + WBCIR_REG_SP3_ASCR);
+
+	/* Clear IR decoding state */
+	data->irdata_active = false;
+	led_trigger_event(data->rxtrigger, LED_OFF);
+	data->irdata_error = false;
+	data->ev.duration = 0;
+	ir_raw_event_reset(data->dev);
+	ir_raw_event_handle(data->dev);
+
+	/* Enable interrupts */
+	outb(WBCIR_IRQ_RX | WBCIR_IRQ_ERR, data->sbase + WBCIR_REG_SP3_IER);
+}
+
+static int
+wbcir_resume(struct pnp_dev *device)
+{
+	struct wbcir_data *data = pnp_get_drvdata(device);
+
+	wbcir_init_hw(data);
+	enable_irq(data->irq);
+
+	return 0;
+}
+
+static int __devinit
+wbcir_probe(struct pnp_dev *device, const struct pnp_device_id *dev_id)
+{
+	struct device *dev = &device->dev;
+	struct wbcir_data *data;
+	int err;
+
+	if (!(pnp_port_len(device, 0) == EHFUNC_IOMEM_LEN &&
+	      pnp_port_len(device, 1) == WAKEUP_IOMEM_LEN &&
+	      pnp_port_len(device, 2) == SP_IOMEM_LEN)) {
+		dev_err(dev, "Invalid resources\n");
+		return -ENODEV;
+	}
+
+	data = kzalloc(sizeof(*data), GFP_KERNEL);
+	if (!data) {
+		err = -ENOMEM;
+		goto exit;
+	}
+
+	pnp_set_drvdata(device, data);
+
+	spin_lock_init(&data->spinlock);
+	data->ebase = pnp_port_start(device, 0);
+	data->wbase = pnp_port_start(device, 1);
+	data->sbase = pnp_port_start(device, 2);
+	data->irq = pnp_irq(device, 0);
+
+	if (data->wbase == 0 || data->ebase == 0 ||
+	    data->sbase == 0 || data->irq == 0) {
+		err = -ENODEV;
+		dev_err(dev, "Invalid resources\n");
+		goto exit_free_data;
+	}
+
+	dev_dbg(&device->dev, "Found device "
+		"(w: 0x%lX, e: 0x%lX, s: 0x%lX, i: %u)\n",
+		data->wbase, data->ebase, data->sbase, data->irq);
+
+	if (!request_region(data->wbase, WAKEUP_IOMEM_LEN, DRVNAME)) {
+		dev_err(dev, "Region 0x%lx-0x%lx already in use!\n",
+			data->wbase, data->wbase + WAKEUP_IOMEM_LEN - 1);
+		err = -EBUSY;
+		goto exit_free_data;
+	}
+
+	if (!request_region(data->ebase, EHFUNC_IOMEM_LEN, DRVNAME)) {
+		dev_err(dev, "Region 0x%lx-0x%lx already in use!\n",
+			data->ebase, data->ebase + EHFUNC_IOMEM_LEN - 1);
+		err = -EBUSY;
+		goto exit_release_wbase;
+	}
+
+	if (!request_region(data->sbase, SP_IOMEM_LEN, DRVNAME)) {
+		dev_err(dev, "Region 0x%lx-0x%lx already in use!\n",
+			data->sbase, data->sbase + SP_IOMEM_LEN - 1);
+		err = -EBUSY;
+		goto exit_release_ebase;
+	}
+
+	err = request_irq(data->irq, wbcir_irq_handler,
+			  IRQF_DISABLED, DRVNAME, device);
+	if (err) {
+		dev_err(dev, "Failed to claim IRQ %u\n", data->irq);
+		err = -EBUSY;
+		goto exit_release_sbase;
+	}
+
+	led_trigger_register_simple("cir-tx", &data->txtrigger);
+	if (!data->txtrigger) {
+		err = -ENOMEM;
+		goto exit_free_irq;
+	}
+
+	led_trigger_register_simple("cir-rx", &data->rxtrigger);
+	if (!data->rxtrigger) {
+		err = -ENOMEM;
+		goto exit_unregister_txtrigger;
+	}
+
+	data->led.name = "cir::activity";
+	data->led.default_trigger = "cir-rx";
+	data->led.brightness_set = wbcir_led_brightness_set;
+	data->led.brightness_get = wbcir_led_brightness_get;
+	err = led_classdev_register(&device->dev, &data->led);
+	if (err)
+		goto exit_unregister_rxtrigger;
+
+	data->dev = rc_allocate_device();
+	if (!data->dev) {
+		err = -ENOMEM;
+		goto exit_unregister_led;
+	}
+
+	data->dev->driver_name = WBCIR_NAME;
+	data->dev->input_name = WBCIR_NAME;
+	data->dev->input_phys = "wbcir/cir0";
+	data->dev->input_id.bustype = BUS_HOST;
+	data->dev->input_id.vendor = PCI_VENDOR_ID_WINBOND;
+	data->dev->input_id.product = WBCIR_ID_FAMILY;
+	data->dev->input_id.version = WBCIR_ID_CHIP;
+	data->dev->priv = data;
+	data->dev->dev.parent = &device->dev;
+
+	err = rc_register_device(data->dev);
+	if (err)
+		goto exit_free_rc;
+
+	device_init_wakeup(&device->dev, 1);
+
+	wbcir_init_hw(data);
+
+	return 0;
+
+exit_free_rc:
+	rc_free_device(data->dev);
+exit_unregister_led:
+	led_classdev_unregister(&data->led);
+exit_unregister_rxtrigger:
+	led_trigger_unregister_simple(data->rxtrigger);
+exit_unregister_txtrigger:
+	led_trigger_unregister_simple(data->txtrigger);
+exit_free_irq:
+	free_irq(data->irq, device);
+exit_release_sbase:
+	release_region(data->sbase, SP_IOMEM_LEN);
+exit_release_ebase:
+	release_region(data->ebase, EHFUNC_IOMEM_LEN);
+exit_release_wbase:
+	release_region(data->wbase, WAKEUP_IOMEM_LEN);
+exit_free_data:
+	kfree(data);
+	pnp_set_drvdata(device, NULL);
+exit:
+	return err;
+}
+
+static void __devexit
+wbcir_remove(struct pnp_dev *device)
+{
+	struct wbcir_data *data = pnp_get_drvdata(device);
+
+	/* Disable interrupts */
+	wbcir_select_bank(data, WBCIR_BANK_0);
+	outb(WBCIR_IRQ_NONE, data->sbase + WBCIR_REG_SP3_IER);
+
+	free_irq(data->irq, device);
+
+	/* Clear status bits NEC_REP, BUFF, MSG_END, MATCH */
+	wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_STS, 0x17, 0x17);
+
+	/* Clear CEIR_EN */
+	wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_CTL, 0x00, 0x01);
+
+	/* Clear BUFF_EN, END_EN, MATCH_EN */
+	wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_EV_EN, 0x00, 0x07);
+
+	rc_unregister_device(data->dev);
+
+	led_trigger_unregister_simple(data->rxtrigger);
+	led_trigger_unregister_simple(data->txtrigger);
+	led_classdev_unregister(&data->led);
+
+	/* This is ok since &data->led isn't actually used */
+	wbcir_led_brightness_set(&data->led, LED_OFF);
+
+	release_region(data->wbase, WAKEUP_IOMEM_LEN);
+	release_region(data->ebase, EHFUNC_IOMEM_LEN);
+	release_region(data->sbase, SP_IOMEM_LEN);
+
+	kfree(data);
+
+	pnp_set_drvdata(device, NULL);
+}
+
+static const struct pnp_device_id wbcir_ids[] = {
+	{ "WEC1022", 0 },
+	{ "", 0 }
+};
+MODULE_DEVICE_TABLE(pnp, wbcir_ids);
+
+static struct pnp_driver wbcir_driver = {
+	.name     = WBCIR_NAME,
+	.id_table = wbcir_ids,
+	.probe    = wbcir_probe,
+	.remove   = __devexit_p(wbcir_remove),
+	.suspend  = wbcir_suspend,
+	.resume   = wbcir_resume,
+	.shutdown = wbcir_shutdown
+};
+
+static int __init
+wbcir_init(void)
+{
+	int ret;
+
+	switch (protocol) {
+	case IR_PROTOCOL_RC5:
+	case IR_PROTOCOL_NEC:
+	case IR_PROTOCOL_RC6:
+		break;
+	default:
+		printk(KERN_ERR DRVNAME ": Invalid power-on protocol\n");
+	}
+
+	ret = pnp_register_driver(&wbcir_driver);
+	if (ret)
+		printk(KERN_ERR DRVNAME ": Unable to register driver\n");
+
+	return ret;
+}
+
+static void __exit
+wbcir_exit(void)
+{
+	pnp_unregister_driver(&wbcir_driver);
+}
+
+module_init(wbcir_init);
+module_exit(wbcir_exit);
+
+MODULE_AUTHOR("David H�rdeman <david@hardeman.nu>");
+MODULE_DESCRIPTION("Winbond SuperI/O Consumer IR Driver");
+MODULE_LICENSE("GPL");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/adv7175.c linux-libre-2.6.38-gnu1/drivers/media/video/adv7175.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/adv7175.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/adv7175.c	2011-03-14 21:20:32.000000000 -0400
@@ -303,11 +303,22 @@ static int adv7175_g_chip_ident(struct v
 	return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_ADV7175, 0);
 }
 
+static int adv7175_s_power(struct v4l2_subdev *sd, int on)
+{
+	if (on)
+		adv7175_write(sd, 0x01, 0x00);
+	else
+		adv7175_write(sd, 0x01, 0x78);
+
+	return 0;
+}
+
 /* ----------------------------------------------------------------------- */
 
 static const struct v4l2_subdev_core_ops adv7175_core_ops = {
 	.g_chip_ident = adv7175_g_chip_ident,
 	.init = adv7175_init,
+	.s_power = adv7175_s_power,
 };
 
 static const struct v4l2_subdev_video_ops adv7175_video_ops = {
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/au0828/au0828.h linux-libre-2.6.38-gnu1/drivers/media/video/au0828/au0828.h
--- linux-libre-2.6.37-gnu1/drivers/media/video/au0828/au0828.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/au0828/au0828.h	2011-03-14 21:20:32.000000000 -0400
@@ -53,7 +53,7 @@
 
 /* Defination for AU0828 USB transfer */
 #define AU0828_MAX_ISO_BUFS    12  /* maybe resize this value in the future */
-#define AU0828_ISO_PACKETS_PER_URB      10
+#define AU0828_ISO_PACKETS_PER_URB      128
 
 #define AU0828_MIN_BUF 4
 #define AU0828_DEF_BUF 8
@@ -204,6 +204,10 @@ struct au0828_dev {
 	unsigned int resources;	/* resources in use */
 	struct video_device *vdev;
 	struct video_device *vbi_dev;
+	struct timer_list vid_timeout;
+	int vid_timeout_running;
+	struct timer_list vbi_timeout;
+	int vbi_timeout_running;
 	int width;
 	int height;
 	int vbi_width;
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/au0828/au0828-video.c linux-libre-2.6.38-gnu1/drivers/media/video/au0828/au0828-video.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/au0828/au0828-video.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/au0828/au0828-video.c	2011-03-14 21:20:32.000000000 -0400
@@ -122,6 +122,7 @@ static void au0828_irq_callback(struct u
 {
 	struct au0828_dmaqueue  *dma_q = urb->context;
 	struct au0828_dev *dev = container_of(dma_q, struct au0828_dev, vidq);
+	unsigned long flags = 0;
 	int rc, i;
 
 	switch (urb->status) {
@@ -139,9 +140,9 @@ static void au0828_irq_callback(struct u
 	}
 
 	/* Copy data from URB */
-	spin_lock(&dev->slock);
+	spin_lock_irqsave(&dev->slock, flags);
 	rc = dev->isoc_ctl.isoc_copy(dev, urb);
-	spin_unlock(&dev->slock);
+	spin_unlock_irqrestore(&dev->slock, flags);
 
 	/* Reset urb buffers */
 	for (i = 0; i < urb->number_of_packets; i++) {
@@ -576,7 +577,7 @@ static inline int au0828_isoc_copy(struc
 			p += 4;
 			au0828_isocdbg("Video frame %s\n",
 				       (fbyte & 0x40) ? "odd" : "even");
-			if (!(fbyte & 0x40)) {
+			if (fbyte & 0x40) {
 				/* VBI */
 				if (vbi_buf != NULL)
 					vbi_buffer_filled(dev,
@@ -597,6 +598,15 @@ static inline int au0828_isoc_copy(struc
 					outp = NULL;
 				else
 					outp = videobuf_to_vmalloc(&buf->vb);
+
+				/* As long as isoc traffic is arriving, keep
+				   resetting the timer */
+				if (dev->vid_timeout_running)
+					mod_timer(&dev->vid_timeout,
+						  jiffies + (HZ / 10));
+				if (dev->vbi_timeout_running)
+					mod_timer(&dev->vbi_timeout,
+						  jiffies + (HZ / 10));
 			}
 
 			if (buf != NULL) {
@@ -907,6 +917,57 @@ static int get_ressource(struct au0828_f
 	}
 }
 
+/* This function ensures that video frames continue to be delivered even if
+   the ITU-656 input isn't receiving any data (thereby preventing applications
+   such as tvtime from hanging) */
+void au0828_vid_buffer_timeout(unsigned long data)
+{
+	struct au0828_dev *dev = (struct au0828_dev *) data;
+	struct au0828_dmaqueue *dma_q = &dev->vidq;
+	struct au0828_buffer *buf;
+	unsigned char *vid_data;
+	unsigned long flags = 0;
+
+	spin_lock_irqsave(&dev->slock, flags);
+
+	buf = dev->isoc_ctl.buf;
+	if (buf != NULL) {
+		vid_data = videobuf_to_vmalloc(&buf->vb);
+		memset(vid_data, 0x00, buf->vb.size); /* Blank green frame */
+		buffer_filled(dev, dma_q, buf);
+	}
+	get_next_buf(dma_q, &buf);
+
+	if (dev->vid_timeout_running == 1)
+		mod_timer(&dev->vid_timeout, jiffies + (HZ / 10));
+
+	spin_unlock_irqrestore(&dev->slock, flags);
+}
+
+void au0828_vbi_buffer_timeout(unsigned long data)
+{
+	struct au0828_dev *dev = (struct au0828_dev *) data;
+	struct au0828_dmaqueue *dma_q = &dev->vbiq;
+	struct au0828_buffer *buf;
+	unsigned char *vbi_data;
+	unsigned long flags = 0;
+
+	spin_lock_irqsave(&dev->slock, flags);
+
+	buf = dev->isoc_ctl.vbi_buf;
+	if (buf != NULL) {
+		vbi_data = videobuf_to_vmalloc(&buf->vb);
+		memset(vbi_data, 0x00, buf->vb.size);
+		vbi_buffer_filled(dev, dma_q, buf);
+	}
+	vbi_get_next_buf(dma_q, &buf);
+
+	if (dev->vbi_timeout_running == 1)
+		mod_timer(&dev->vbi_timeout, jiffies + (HZ / 10));
+	spin_unlock_irqrestore(&dev->slock, flags);
+}
+
+
 static int au0828_v4l2_open(struct file *filp)
 {
 	int ret = 0;
@@ -976,7 +1037,6 @@ static int au0828_v4l2_open(struct file
 				    V4L2_FIELD_SEQ_TB,
 				    sizeof(struct au0828_buffer), fh, NULL);
 
-
 	return ret;
 }
 
@@ -987,11 +1047,19 @@ static int au0828_v4l2_close(struct file
 	struct au0828_dev *dev = fh->dev;
 
 	if (res_check(fh, AU0828_RESOURCE_VIDEO)) {
+		/* Cancel timeout thread in case they didn't call streamoff */
+		dev->vid_timeout_running = 0;
+		del_timer_sync(&dev->vid_timeout);
+
 		videobuf_stop(&fh->vb_vidq);
 		res_free(fh, AU0828_RESOURCE_VIDEO);
 	}
 
 	if (res_check(fh, AU0828_RESOURCE_VBI)) {
+		/* Cancel timeout thread in case they didn't call streamoff */
+		dev->vbi_timeout_running = 0;
+		del_timer_sync(&dev->vbi_timeout);
+
 		videobuf_stop(&fh->vb_vbiq);
 		res_free(fh, AU0828_RESOURCE_VBI);
 	}
@@ -1048,6 +1116,13 @@ static ssize_t au0828_v4l2_read(struct f
 		if (!res_get(fh, AU0828_RESOURCE_VBI))
 			return -EBUSY;
 
+		if (dev->vbi_timeout_running == 0) {
+			/* Handle case where caller tries to read without
+			   calling streamon first */
+			dev->vbi_timeout_running = 1;
+			mod_timer(&dev->vbi_timeout, jiffies + (HZ / 10));
+		}
+
 		return videobuf_read_stream(&fh->vb_vbiq, buf, count, pos, 0,
 					    filp->f_flags & O_NONBLOCK);
 	}
@@ -1577,10 +1652,15 @@ static int vidioc_streamon(struct file *
 		v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 1);
 	}
 
-	if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
+	if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
 		rc = videobuf_streamon(&fh->vb_vidq);
-	else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE)
+		dev->vid_timeout_running = 1;
+		mod_timer(&dev->vid_timeout, jiffies + (HZ / 10));
+	} else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
 		rc = videobuf_streamon(&fh->vb_vbiq);
+		dev->vbi_timeout_running = 1;
+		mod_timer(&dev->vbi_timeout, jiffies + (HZ / 10));
+	}
 
 	return rc;
 }
@@ -1607,6 +1687,9 @@ static int vidioc_streamoff(struct file
 		fh, type, fh->resources, dev->resources);
 
 	if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+		dev->vid_timeout_running = 0;
+		del_timer_sync(&dev->vid_timeout);
+
 		v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 0);
 		rc = au0828_stream_interrupt(dev);
 		if (rc != 0)
@@ -1621,6 +1704,9 @@ static int vidioc_streamoff(struct file
 		videobuf_streamoff(&fh->vb_vidq);
 		res_free(fh, AU0828_RESOURCE_VIDEO);
 	} else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
+		dev->vbi_timeout_running = 0;
+		del_timer_sync(&dev->vbi_timeout);
+
 		videobuf_streamoff(&fh->vb_vbiq);
 		res_free(fh, AU0828_RESOURCE_VBI);
 	}
@@ -1672,7 +1758,12 @@ static int vidioc_reqbufs(struct file *f
 	if (rc < 0)
 		return rc;
 
-	return videobuf_reqbufs(&fh->vb_vidq, rb);
+	if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		rc = videobuf_reqbufs(&fh->vb_vidq, rb);
+	else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE)
+		rc = videobuf_reqbufs(&fh->vb_vbiq, rb);
+
+	return rc;
 }
 
 static int vidioc_querybuf(struct file *file, void *priv,
@@ -1686,7 +1777,12 @@ static int vidioc_querybuf(struct file *
 	if (rc < 0)
 		return rc;
 
-	return videobuf_querybuf(&fh->vb_vidq, b);
+	if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		rc = videobuf_querybuf(&fh->vb_vidq, b);
+	else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE)
+		rc = videobuf_querybuf(&fh->vb_vbiq, b);
+
+	return rc;
 }
 
 static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *b)
@@ -1699,7 +1795,12 @@ static int vidioc_qbuf(struct file *file
 	if (rc < 0)
 		return rc;
 
-	return videobuf_qbuf(&fh->vb_vidq, b);
+	if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		rc = videobuf_qbuf(&fh->vb_vidq, b);
+	else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE)
+		rc = videobuf_qbuf(&fh->vb_vbiq, b);
+
+	return rc;
 }
 
 static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b)
@@ -1720,17 +1821,13 @@ static int vidioc_dqbuf(struct file *fil
 		dev->greenscreen_detected = 0;
 	}
 
-	return videobuf_dqbuf(&fh->vb_vidq, b, file->f_flags & O_NONBLOCK);
-}
-
-#ifdef CONFIG_VIDEO_V4L1_COMPAT
-static int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf)
-{
-	struct au0828_fh *fh = priv;
+	if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		rc = videobuf_dqbuf(&fh->vb_vidq, b, file->f_flags & O_NONBLOCK);
+	else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE)
+		rc = videobuf_dqbuf(&fh->vb_vbiq, b, file->f_flags & O_NONBLOCK);
 
-	return videobuf_cgmbuf(&fh->vb_vidq, mbuf, 8);
+	return rc;
 }
-#endif
 
 static struct v4l2_file_operations au0828_v4l_fops = {
 	.owner      = THIS_MODULE,
@@ -1775,9 +1872,6 @@ static const struct v4l2_ioctl_ops video
 	.vidioc_s_register          = vidioc_s_register,
 #endif
 	.vidioc_g_chip_ident        = vidioc_g_chip_ident,
-#ifdef CONFIG_VIDEO_V4L1_COMPAT
-	.vidiocgmbuf                = vidiocgmbuf,
-#endif
 };
 
 static const struct video_device au0828_video_template = {
@@ -1840,6 +1934,14 @@ int au0828_analog_register(struct au0828
 	INIT_LIST_HEAD(&dev->vbiq.active);
 	INIT_LIST_HEAD(&dev->vbiq.queued);
 
+	dev->vid_timeout.function = au0828_vid_buffer_timeout;
+	dev->vid_timeout.data = (unsigned long) dev;
+	init_timer(&dev->vid_timeout);
+
+	dev->vbi_timeout.function = au0828_vbi_buffer_timeout;
+	dev->vbi_timeout.data = (unsigned long) dev;
+	init_timer(&dev->vbi_timeout);
+
 	dev->width = NTSC_STD_W;
 	dev->height = NTSC_STD_H;
 	dev->field_size = dev->width * dev->height;
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/bt8xx/bttv-cards.c linux-libre-2.6.38-gnu1/drivers/media/video/bt8xx/bttv-cards.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/bt8xx/bttv-cards.c	2013-05-03 03:56:41.000000000 -0400
+++ linux-libre-2.6.38-gnu1/drivers/media/video/bt8xx/bttv-cards.c	2013-05-03 01:56:23.000000000 -0400
@@ -1373,7 +1373,6 @@ struct tvcard bttv_tvcards[] = {
 		.gpiomute 	= 0x1800,
 		.audio_mode_gpio= fv2000s_audio,
 		.no_msp34xx	= 1,
-		.no_tda9875	= 1,
 		.needs_tvaudio  = 1,
 		.pll            = PLL_28,
 		.tuner_type     = TUNER_PHILIPS_PAL,
@@ -1511,7 +1510,6 @@ struct tvcard bttv_tvcards[] = {
 		.gpiomute 	= 0x09,
 		.needs_tvaudio  = 1,
 		.no_msp34xx	= 1,
-		.no_tda9875	= 1,
 		.pll		= PLL_28,
 		.tuner_type	= TUNER_PHILIPS_PAL,
 		.tuner_addr	= ADDR_UNSET,
@@ -1550,7 +1548,6 @@ struct tvcard bttv_tvcards[] = {
 		.gpiomask2      = 0x07ff,
 		.muxsel         = MUXSEL(3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3),
 		.no_msp34xx     = 1,
-		.no_tda9875     = 1,
 		.tuner_type     = TUNER_ABSENT,
 		.tuner_addr	= ADDR_UNSET,
 		.muxsel_hook    = rv605_muxsel,
@@ -1686,7 +1683,6 @@ struct tvcard bttv_tvcards[] = {
 		.tuner_type     = TUNER_ABSENT,
 		.tuner_addr	= ADDR_UNSET,
 		.no_msp34xx     = 1,
-		.no_tda9875     = 1,
 		.no_tda7432     = 1,
 	},
 	[BTTV_BOARD_OSPREY1x0_848] = {
@@ -1699,7 +1695,6 @@ struct tvcard bttv_tvcards[] = {
 		.tuner_type     = TUNER_ABSENT,
 		.tuner_addr	= ADDR_UNSET,
 		.no_msp34xx     = 1,
-		.no_tda9875     = 1,
 		.no_tda7432     = 1,
 	},
 
@@ -1714,7 +1709,6 @@ struct tvcard bttv_tvcards[] = {
 		.tuner_type     = TUNER_ABSENT,
 		.tuner_addr	= ADDR_UNSET,
 		.no_msp34xx     = 1,
-		.no_tda9875     = 1,
 		.no_tda7432     = 1,
 	},
 	[BTTV_BOARD_OSPREY1x1] = {
@@ -1727,7 +1721,6 @@ struct tvcard bttv_tvcards[] = {
 		.tuner_type     = TUNER_ABSENT,
 		.tuner_addr	= ADDR_UNSET,
 		.no_msp34xx     = 1,
-		.no_tda9875     = 1,
 		.no_tda7432     = 1,
 	},
 	[BTTV_BOARD_OSPREY1x1_SVID] = {
@@ -1740,7 +1733,6 @@ struct tvcard bttv_tvcards[] = {
 		.tuner_type     = TUNER_ABSENT,
 		.tuner_addr	= ADDR_UNSET,
 		.no_msp34xx     = 1,
-		.no_tda9875     = 1,
 		.no_tda7432     = 1,
 	},
 	[BTTV_BOARD_OSPREY2xx] = {
@@ -1753,7 +1745,6 @@ struct tvcard bttv_tvcards[] = {
 		.tuner_type	= TUNER_ABSENT,
 		.tuner_addr	= ADDR_UNSET,
 		.no_msp34xx     = 1,
-		.no_tda9875     = 1,
 		.no_tda7432     = 1,
 	},
 
@@ -1768,7 +1759,6 @@ struct tvcard bttv_tvcards[] = {
 		.tuner_type	= TUNER_ABSENT,
 		.tuner_addr	= ADDR_UNSET,
 		.no_msp34xx     = 1,
-		.no_tda9875     = 1,
 		.no_tda7432     = 1,
 	},
 	[BTTV_BOARD_OSPREY2x0] = {
@@ -1781,7 +1771,6 @@ struct tvcard bttv_tvcards[] = {
 		.tuner_type	= TUNER_ABSENT,
 		.tuner_addr	= ADDR_UNSET,
 		.no_msp34xx     = 1,
-		.no_tda9875     = 1,
 		.no_tda7432     = 1,
 	},
 	[BTTV_BOARD_OSPREY500] = {
@@ -1794,7 +1783,6 @@ struct tvcard bttv_tvcards[] = {
 		.tuner_type     = TUNER_ABSENT,
 		.tuner_addr	= ADDR_UNSET,
 		.no_msp34xx     = 1,
-		.no_tda9875     = 1,
 		.no_tda7432     = 1,
 	},
 	[BTTV_BOARD_OSPREY540] = {
@@ -1805,7 +1793,6 @@ struct tvcard bttv_tvcards[] = {
 		.tuner_type     = TUNER_ABSENT,
 		.tuner_addr	= ADDR_UNSET,
 		.no_msp34xx     = 1,
-		.no_tda9875     = 1,
 		.no_tda7432     = 1,
 	},
 
@@ -1820,7 +1807,6 @@ struct tvcard bttv_tvcards[] = {
 		.tuner_type	= TUNER_ABSENT,
 		.tuner_addr	= ADDR_UNSET,
 		.no_msp34xx     = 1,
-		.no_tda9875     = 1,
 		.no_tda7432     = 1,      /* must avoid, conflicts with the bt860 */
 	},
 	[BTTV_BOARD_IDS_EAGLE] = {
@@ -1835,7 +1821,6 @@ struct tvcard bttv_tvcards[] = {
 		.muxsel         = MUXSEL(2, 2, 2, 2),
 		.muxsel_hook    = eagle_muxsel,
 		.no_msp34xx     = 1,
-		.no_tda9875     = 1,
 		.pll            = PLL_28,
 	},
 	[BTTV_BOARD_PINNACLESAT] = {
@@ -1846,7 +1831,6 @@ struct tvcard bttv_tvcards[] = {
 		.tuner_type     = TUNER_ABSENT,
 		.tuner_addr	= ADDR_UNSET,
 		.no_msp34xx     = 1,
-		.no_tda9875     = 1,
 		.no_tda7432     = 1,
 		.muxsel         = MUXSEL(3, 1),
 		.pll            = PLL_28,
@@ -1897,7 +1881,6 @@ struct tvcard bttv_tvcards[] = {
 		.svhs           = 2,
 		.gpiomask       = 0,
 		.no_msp34xx     = 1,
-		.no_tda9875     = 1,
 		.no_tda7432     = 1,
 		.muxsel         = MUXSEL(2, 0, 1),
 		.pll            = PLL_28,
@@ -1970,7 +1953,6 @@ struct tvcard bttv_tvcards[] = {
 		/* Tuner, CVid, SVid, CVid over SVid connector */
 		.muxsel         = MUXSEL(2, 3, 1, 1),
 		.gpiomask       = 0,
-		.no_tda9875     = 1,
 		.no_tda7432     = 1,
 		.tuner_type     = TUNER_PHILIPS_PAL_I,
 		.tuner_addr	= ADDR_UNSET,
@@ -2017,7 +1999,6 @@ struct tvcard bttv_tvcards[] = {
 		.muxsel         = MUXSEL(2,2,2,2, 3,3,3,3, 1,1,1,1, 0,0,0,0),
 		.muxsel_hook    = xguard_muxsel,
 		.no_msp34xx     = 1,
-		.no_tda9875     = 1,
 		.no_tda7432     = 1,
 		.pll            = PLL_28,
 	},
@@ -2029,7 +2010,6 @@ struct tvcard bttv_tvcards[] = {
 		.svhs           = NO_SVHS,
 		.muxsel         = MUXSEL(2, 3, 1, 0),
 		.no_msp34xx     = 1,
-		.no_tda9875     = 1,
 		.no_tda7432     = 1,
 		.pll            = PLL_28,
 		.tuner_type     = TUNER_ABSENT,
@@ -2134,7 +2114,6 @@ struct tvcard bttv_tvcards[] = {
 		.svhs           = NO_SVHS,   /* card has no svhs */
 		.needs_tvaudio  = 0,
 		.no_msp34xx     = 1,
-		.no_tda9875     = 1,
 		.no_tda7432     = 1,
 		.gpiomask       = 0x00,
 		.muxsel         = MUXSEL(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
@@ -2156,7 +2135,6 @@ struct tvcard bttv_tvcards[] = {
 	[BTTV_BOARD_TWINHAN_DST] = {
 		.name           = "Twinhan DST + clones",
 		.no_msp34xx     = 1,
-		.no_tda9875     = 1,
 		.no_tda7432     = 1,
 		.tuner_type     = TUNER_ABSENT,
 		.tuner_addr	= ADDR_UNSET,
@@ -2171,7 +2149,6 @@ struct tvcard bttv_tvcards[] = {
 		/* Vid In, SVid In, Vid over SVid in connector */
 		.muxsel		= MUXSEL(3, 1, 1, 3),
 		.no_msp34xx     = 1,
-		.no_tda9875     = 1,
 		.no_tda7432     = 1,
 		.tuner_type     = TUNER_ABSENT,
 		.tuner_addr	= ADDR_UNSET,
@@ -2226,7 +2203,6 @@ struct tvcard bttv_tvcards[] = {
 		.svhs           = NO_SVHS,
 		.muxsel         = MUXSEL(2, 3, 1, 0),
 		.no_msp34xx     = 1,
-		.no_tda9875     = 1,
 		.no_tda7432     = 1,
 		.needs_tvaudio  = 0,
 		.tuner_type     = TUNER_ABSENT,
@@ -2278,7 +2254,6 @@ struct tvcard bttv_tvcards[] = {
 		.gpiomask       = 0,
 		.gpiomask2      = 0x3C<<16,/*Set the GPIO[18]->GPIO[21] as output pin.==> drive the video inputs through analog multiplexers*/
 		.no_msp34xx     = 1,
-		.no_tda9875     = 1,
 		.no_tda7432     = 1,
 		/*878A input is always MUX0, see above.*/
 		.muxsel         = MUXSEL(2, 2, 2, 2),
@@ -2302,7 +2277,6 @@ struct tvcard bttv_tvcards[] = {
 		.tuner_type     = TUNER_TEMIC_PAL,
 		.tuner_addr	= ADDR_UNSET,
 		.no_msp34xx     = 1,
-		.no_tda9875     = 1,
 	},
 	[BTTV_BOARD_AVDVBT_771] = {
 		/* Wolfram Joost <wojo@frokaschwei.de> */
@@ -2313,7 +2287,6 @@ struct tvcard bttv_tvcards[] = {
 		.tuner_addr	= ADDR_UNSET,
 		.muxsel         = MUXSEL(3, 3),
 		.no_msp34xx     = 1,
-		.no_tda9875     = 1,
 		.no_tda7432     = 1,
 		.pll            = PLL_28,
 		.has_dvb        = 1,
@@ -2329,7 +2302,6 @@ struct tvcard bttv_tvcards[] = {
 		.svhs           = 1,
 		.muxsel         = MUXSEL(3, 1, 2, 0), /* Comp0, S-Video, ?, ? */
 		.no_msp34xx     = 1,
-		.no_tda9875     = 1,
 		.no_tda7432     = 1,
 		.pll            = PLL_28,
 		.tuner_type     = TUNER_ABSENT,
@@ -2393,7 +2365,6 @@ struct tvcard bttv_tvcards[] = {
 		/* Chris Pascoe <c.pascoe@itee.uq.edu.au> */
 		.name           = "DViCO FusionHDTV DVB-T Lite",
 		.no_msp34xx     = 1,
-		.no_tda9875     = 1,
 		.no_tda7432     = 1,
 		.pll            = PLL_28,
 		.no_video       = 1,
@@ -2440,7 +2411,6 @@ struct tvcard bttv_tvcards[] = {
 		.muxsel         = MUXSEL(2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2),
 		.pll		= PLL_28,
 		.no_msp34xx     = 1,
-		.no_tda9875     = 1,
 		.no_tda7432	= 1,
 		.tuner_type     = TUNER_ABSENT,
 		.tuner_addr	= ADDR_UNSET,
@@ -2478,7 +2448,6 @@ struct tvcard bttv_tvcards[] = {
 		.pll		= PLL_28,
 		.no_msp34xx	= 1,
 		.no_tda7432	= 1,
-		.no_tda9875	= 1,
 		.muxsel_hook	= kodicom4400r_muxsel,
 	},
 	[BTTV_BOARD_KODICOM_4400R_SL] = {
@@ -2500,7 +2469,6 @@ struct tvcard bttv_tvcards[] = {
 		.pll		= PLL_28,
 		.no_msp34xx	= 1,
 		.no_tda7432	= 1,
-		.no_tda9875	= 1,
 		.muxsel_hook	= kodicom4400r_muxsel,
 	},
 		/* ---- card 0x86---------------------------------- */
@@ -2530,7 +2498,6 @@ struct tvcard bttv_tvcards[] = {
 		.gpiomux        = { 0x00400005, 0, 0x00000001, 0 },
 		.gpiomute 	= 0x00c00007,
 		.no_msp34xx     = 1,
-		.no_tda9875     = 1,
 		.no_tda7432     = 1,
 		.has_dvb        = 1,
 	},
@@ -2630,7 +2597,6 @@ struct tvcard bttv_tvcards[] = {
 		.tuner_type     = TUNER_ABSENT,
 		.tuner_addr     = ADDR_UNSET,
 		.no_msp34xx     = 1,
-		.no_tda9875     = 1,
 		.no_tda7432     = 1,
 	},
 		/* ---- card 0x8d ---------------------------------- */
@@ -2658,7 +2624,6 @@ struct tvcard bttv_tvcards[] = {
 		.muxsel		= MUXSEL(2, 3, 1, 1),
 		.gpiomux 	= { 100000, 100002, 100002, 100000 },
 		.no_msp34xx	= 1,
-		.no_tda9875     = 1,
 		.no_tda7432     = 1,
 		.pll		= PLL_28,
 		.tuner_type	= TUNER_TNF_5335MF,
@@ -2674,7 +2639,6 @@ struct tvcard bttv_tvcards[] = {
 		.gpiomask	= 0x0f, /* old: 7 */
 		.muxsel		= MUXSEL(0, 1, 3, 2), /* Composite 0-3 */
 		.no_msp34xx	= 1,
-		.no_tda9875     = 1,
 		.no_tda7432     = 1,
 		.tuner_type	= TUNER_ABSENT,
 		.tuner_addr	= ADDR_UNSET,
@@ -2732,7 +2696,6 @@ struct tvcard bttv_tvcards[] = {
 		.gpiomux        = { 0x00400005, 0, 0x00000001, 0 },
 		.gpiomute 	= 0x00c00007,
 		.no_msp34xx     = 1,
-		.no_tda9875     = 1,
 		.no_tda7432     = 1,
 	},
 	/* ---- card 0x95---------------------------------- */
@@ -2874,7 +2837,6 @@ struct tvcard bttv_tvcards[] = {
 		.pll		= PLL_28,
 		.no_msp34xx	= 1,
 		.no_tda7432	= 1,
-		.no_tda9875	= 1,
 		.muxsel_hook    = gv800s_muxsel,
 	},
 		[BTTV_BOARD_GEOVISION_GV800S_SL] = {
@@ -2899,7 +2861,6 @@ struct tvcard bttv_tvcards[] = {
 		.pll		= PLL_28,
 		.no_msp34xx	= 1,
 		.no_tda7432	= 1,
-		.no_tda9875	= 1,
 		.muxsel_hook    = gv800s_muxsel,
 	},
 	[BTTV_BOARD_PV183] = {
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/bt8xx/bttv-driver.c linux-libre-2.6.38-gnu1/drivers/media/video/bt8xx/bttv-driver.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/bt8xx/bttv-driver.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/bt8xx/bttv-driver.c	2011-03-14 21:20:32.000000000 -0400
@@ -55,7 +55,7 @@
 #include <asm/io.h>
 #include <asm/byteorder.h>
 
-#include <media/rds.h>
+#include <media/saa6588.h>
 
 
 unsigned int bttv_num;			/* number of Bt848s in use */
@@ -189,8 +189,14 @@ static void request_modules(struct bttv
 	INIT_WORK(&dev->request_module_wk, request_module_async);
 	schedule_work(&dev->request_module_wk);
 }
+
+static void flush_request_modules(struct bttv *dev)
+{
+	flush_work_sync(&dev->request_module_wk);
+}
 #else
 #define request_modules(dev)
+#define flush_request_modules(dev)
 #endif /* CONFIG_MODULES */
 
 
@@ -2597,31 +2603,6 @@ static int bttv_s_fmt_vid_overlay(struct
 	return setup_window_lock(fh, btv, &f->fmt.win, 1);
 }
 
-#ifdef CONFIG_VIDEO_V4L1_COMPAT
-static int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf)
-{
-	int retval;
-	unsigned int i;
-	struct bttv_fh *fh = priv;
-
-	retval = __videobuf_mmap_setup(&fh->cap, gbuffers, gbufsize,
-				     V4L2_MEMORY_MMAP);
-	if (retval < 0) {
-		return retval;
-	}
-
-	gbuffers = retval;
-	memset(mbuf, 0, sizeof(*mbuf));
-	mbuf->frames = gbuffers;
-	mbuf->size   = gbuffers * gbufsize;
-
-	for (i = 0; i < gbuffers; i++)
-		mbuf->offsets[i] = i * gbufsize;
-
-	return 0;
-}
-#endif
-
 static int bttv_querycap(struct file *file, void  *priv,
 				struct v4l2_capability *cap)
 {
@@ -3354,9 +3335,6 @@ static const struct v4l2_ioctl_ops bttv_
 	.vidioc_streamoff               = bttv_streamoff,
 	.vidioc_g_tuner                 = bttv_g_tuner,
 	.vidioc_s_tuner                 = bttv_s_tuner,
-#ifdef CONFIG_VIDEO_V4L1_COMPAT
-	.vidiocgmbuf                    = vidiocgmbuf,
-#endif
 	.vidioc_g_crop                  = bttv_g_crop,
 	.vidioc_s_crop                  = bttv_s_crop,
 	.vidioc_g_fbuf                  = bttv_g_fbuf,
@@ -3416,7 +3394,7 @@ static int radio_release(struct file *fi
 {
 	struct bttv_fh *fh = file->private_data;
 	struct bttv *btv = fh->btv;
-	struct rds_command cmd;
+	struct saa6588_command cmd;
 
 	v4l2_prio_close(&btv->prio, fh->prio);
 	file->private_data = NULL;
@@ -3424,7 +3402,7 @@ static int radio_release(struct file *fi
 
 	btv->radio_user--;
 
-	bttv_call_all(btv, core, ioctl, RDS_CMD_CLOSE, &cmd);
+	bttv_call_all(btv, core, ioctl, SAA6588_CMD_CLOSE, &cmd);
 
 	return 0;
 }
@@ -3551,13 +3529,13 @@ static ssize_t radio_read(struct file *f
 {
 	struct bttv_fh *fh = file->private_data;
 	struct bttv *btv = fh->btv;
-	struct rds_command cmd;
+	struct saa6588_command cmd;
 	cmd.block_count = count/3;
 	cmd.buffer = data;
 	cmd.instance = file;
 	cmd.result = -ENODEV;
 
-	bttv_call_all(btv, core, ioctl, RDS_CMD_READ, &cmd);
+	bttv_call_all(btv, core, ioctl, SAA6588_CMD_READ, &cmd);
 
 	return cmd.result;
 }
@@ -3566,11 +3544,11 @@ static unsigned int radio_poll(struct fi
 {
 	struct bttv_fh *fh = file->private_data;
 	struct bttv *btv = fh->btv;
-	struct rds_command cmd;
+	struct saa6588_command cmd;
 	cmd.instance = file;
 	cmd.event_list = wait;
 	cmd.result = -ENODEV;
-	bttv_call_all(btv, core, ioctl, RDS_CMD_POLL, &cmd);
+	bttv_call_all(btv, core, ioctl, SAA6588_CMD_POLL, &cmd);
 
 	return cmd.result;
 }
@@ -4041,9 +4019,6 @@ static irqreturn_t bttv_irq(int irq, voi
 
 	btv=(struct bttv *)dev_id;
 
-	if (btv->custom_irq)
-		handled = btv->custom_irq(btv);
-
 	count=0;
 	while (1) {
 		/* get/clear interrupt status bits */
@@ -4079,7 +4054,6 @@ static irqreturn_t bttv_irq(int irq, voi
 			btv->field_count++;
 
 		if ((astat & BT848_INT_GPINT) && btv->remote) {
-			wake_up(&btv->gpioq);
 			bttv_input_irq(btv);
 		}
 
@@ -4284,7 +4258,6 @@ static int __devinit bttv_probe(struct p
 	mutex_init(&btv->lock);
 	spin_lock_init(&btv->s_lock);
 	spin_lock_init(&btv->gpio_lock);
-	init_waitqueue_head(&btv->gpioq);
 	init_waitqueue_head(&btv->i2c_queue);
 	INIT_LIST_HEAD(&btv->c.subs);
 	INIT_LIST_HEAD(&btv->capture);
@@ -4462,6 +4435,9 @@ static void __devexit bttv_remove(struct
 	if (bttv_verbose)
 		printk("bttv%d: unloading\n",btv->c.nr);
 
+	if (bttv_tvcards[btv->c.type].has_dvb)
+		flush_request_modules(btv);
+
 	/* shutdown everything (DMA+IRQs) */
 	btand(~15, BT848_GPIO_DMA_CTL);
 	btwrite(0, BT848_INT_MASK);
@@ -4472,7 +4448,6 @@ static void __devexit bttv_remove(struct
 
 	/* tell gpio modules we are leaving ... */
 	btv->shutdown=1;
-	wake_up(&btv->gpioq);
 	bttv_input_fini(btv);
 	bttv_sub_del_devices(&btv->c);
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/bt8xx/bttv.h linux-libre-2.6.38-gnu1/drivers/media/video/bt8xx/bttv.h
--- linux-libre-2.6.37-gnu1/drivers/media/video/bt8xx/bttv.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/bt8xx/bttv.h	2011-03-14 21:20:32.000000000 -0400
@@ -17,7 +17,6 @@
 #include <linux/videodev2.h>
 #include <linux/i2c.h>
 #include <media/v4l2-device.h>
-#include <media/ir-common.h>
 #include <media/i2c-addr.h>
 #include <media/tuner.h>
 
@@ -235,7 +234,6 @@ struct tvcard {
 
 	/* i2c audio flags */
 	unsigned int no_msp34xx:1;
-	unsigned int no_tda9875:1;
 	unsigned int no_tda7432:1;
 	unsigned int needs_tvaudio:1;
 	unsigned int msp34xx_alt:1;
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/bt8xx/bttv-input.c linux-libre-2.6.38-gnu1/drivers/media/video/bt8xx/bttv-input.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/bt8xx/bttv-input.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/bt8xx/bttv-input.c	2011-03-14 21:20:32.000000000 -0400
@@ -31,15 +31,9 @@
 
 static int ir_debug;
 module_param(ir_debug, int, 0644);
-static int repeat_delay = 500;
-module_param(repeat_delay, int, 0644);
-static int repeat_period = 33;
-module_param(repeat_period, int, 0644);
 
 static int ir_rc5_remote_gap = 885;
 module_param(ir_rc5_remote_gap, int, 0644);
-static int ir_rc5_key_timeout = 200;
-module_param(ir_rc5_key_timeout, int, 0644);
 
 #undef dprintk
 #define dprintk(arg...) do {	\
@@ -55,7 +49,7 @@ module_param(ir_rc5_key_timeout, int, 06
 
 static void ir_handle_key(struct bttv *btv)
 {
-	struct card_ir *ir = btv->remote;
+	struct bttv_ir *ir = btv->remote;
 	u32 gpio,data;
 
 	/* read gpio value */
@@ -74,23 +68,22 @@ static void ir_handle_key(struct bttv *b
 		(gpio & ir->mask_keydown) ? " down" : "",
 		(gpio & ir->mask_keyup)   ? " up"   : "");
 
-	if ((ir->mask_keydown  &&  (0 != (gpio & ir->mask_keydown))) ||
-	    (ir->mask_keyup    &&  (0 == (gpio & ir->mask_keyup)))) {
-		ir_input_keydown(ir->dev, &ir->ir, data);
+	if ((ir->mask_keydown && (gpio & ir->mask_keydown)) ||
+	    (ir->mask_keyup   && !(gpio & ir->mask_keyup))) {
+		rc_keydown_notimeout(ir->dev, data, 0);
 	} else {
 		/* HACK: Probably, ir->mask_keydown is missing
 		   for this board */
 		if (btv->c.type == BTTV_BOARD_WINFAST2000)
-			ir_input_keydown(ir->dev, &ir->ir, data);
+			rc_keydown_notimeout(ir->dev, data, 0);
 
-		ir_input_nokey(ir->dev,&ir->ir);
+		rc_keyup(ir->dev);
 	}
-
 }
 
 static void ir_enltv_handle_key(struct bttv *btv)
 {
-	struct card_ir *ir = btv->remote;
+	struct bttv_ir *ir = btv->remote;
 	u32 gpio, data, keyup;
 
 	/* read gpio value */
@@ -107,9 +100,9 @@ static void ir_enltv_handle_key(struct b
 			gpio, data,
 			(gpio & ir->mask_keyup) ? " up" : "up/down");
 
-		ir_input_keydown(ir->dev, &ir->ir, data);
+		rc_keydown_notimeout(ir->dev, data, 0);
 		if (keyup)
-			ir_input_nokey(ir->dev, &ir->ir);
+			rc_keyup(ir->dev);
 	} else {
 		if ((ir->last_gpio & 1 << 31) == keyup)
 			return;
@@ -119,26 +112,30 @@ static void ir_enltv_handle_key(struct b
 			(gpio & ir->mask_keyup) ? " up" : "down");
 
 		if (keyup)
-			ir_input_nokey(ir->dev, &ir->ir);
+			rc_keyup(ir->dev);
 		else
-			ir_input_keydown(ir->dev, &ir->ir, data);
+			rc_keydown_notimeout(ir->dev, data, 0);
 	}
 
 	ir->last_gpio = data | keyup;
 }
 
+static int bttv_rc5_irq(struct bttv *btv);
+
 void bttv_input_irq(struct bttv *btv)
 {
-	struct card_ir *ir = btv->remote;
+	struct bttv_ir *ir = btv->remote;
 
-	if (!ir->polling)
+	if (ir->rc5_gpio)
+		bttv_rc5_irq(btv);
+	else if (!ir->polling)
 		ir_handle_key(btv);
 }
 
 static void bttv_input_timer(unsigned long data)
 {
 	struct bttv *btv = (struct bttv*)data;
-	struct card_ir *ir = btv->remote;
+	struct bttv_ir *ir = btv->remote;
 
 	if (btv->c.type == BTTV_BOARD_ENLTV_FM_2)
 		ir_enltv_handle_key(btv);
@@ -147,11 +144,109 @@ static void bttv_input_timer(unsigned lo
 	mod_timer(&ir->timer, jiffies + msecs_to_jiffies(ir->polling));
 }
 
-/* ---------------------------------------------------------------*/
+/*
+ * FIXME: Nebula digi uses the legacy way to decode RC5, instead of relying
+ * on the rc-core way. As we need to be sure that both IRQ transitions are
+ * properly triggered, Better to touch it only with this hardware for
+ * testing.
+ */
+
+#define RC5_START(x)	(((x) >> 12) & 3)
+#define RC5_TOGGLE(x)	(((x) >> 11) & 1)
+#define RC5_ADDR(x)	(((x) >> 6) & 31)
+#define RC5_INSTR(x)	((x) & 63)
+
+/* decode raw bit pattern to RC5 code */
+static u32 bttv_rc5_decode(unsigned int code)
+{
+	unsigned int org_code = code;
+	unsigned int pair;
+	unsigned int rc5 = 0;
+	int i;
+
+	for (i = 0; i < 14; ++i) {
+		pair = code & 0x3;
+		code >>= 2;
+
+		rc5 <<= 1;
+		switch (pair) {
+		case 0:
+		case 2:
+			break;
+		case 1:
+			rc5 |= 1;
+		break;
+		case 3:
+			dprintk(KERN_INFO DEVNAME ":rc5_decode(%x) bad code\n",
+				org_code);
+			return 0;
+		}
+	}
+	dprintk(KERN_INFO DEVNAME ":"
+		"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;
+}
+
+static void bttv_rc5_timer_end(unsigned long data)
+{
+	struct bttv_ir *ir = (struct bttv_ir *)data;
+	struct timeval tv;
+	unsigned long current_jiffies;
+	u32 gap;
+	u32 rc5 = 0;
+
+	/* get time */
+	current_jiffies = jiffies;
+	do_gettimeofday(&tv);
+
+	/* avoid overflow with gap >1s */
+	if (tv.tv_sec - ir->base_time.tv_sec > 1) {
+		gap = 200000;
+	} else {
+		gap = 1000000 * (tv.tv_sec - ir->base_time.tv_sec) +
+		    tv.tv_usec - ir->base_time.tv_usec;
+	}
+
+	/* signal we're ready to start a new code */
+	ir->active = false;
+
+	/* Allow some timer jitter (RC5 is ~24ms anyway so this is ok) */
+	if (gap < 28000) {
+		dprintk(KERN_INFO DEVNAME ": 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);
+	} 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 ":"
+			       " rc5 start bits invalid: %u\n", RC5_START(rc5));
+
+			/* right address? */
+		} else if (RC5_ADDR(rc5) == ir->addr) {
+			u32 toggle = RC5_TOGGLE(rc5);
+			u32 instr = RC5_INSTR(rc5);
+
+			/* Good code */
+			rc_keydown(ir->dev, instr, toggle);
+			dprintk(KERN_INFO DEVNAME ":"
+				" instruction %x, toggle %x\n",
+				instr, toggle);
+		}
+	}
+}
 
 static int bttv_rc5_irq(struct bttv *btv)
 {
-	struct card_ir *ir = btv->remote;
+	struct bttv_ir *ir = btv->remote;
 	struct timeval tv;
 	u32 gpio;
 	u32 gap;
@@ -160,10 +255,6 @@ static int bttv_rc5_irq(struct bttv *btv
 	/* read gpio port */
 	gpio = bttv_gpio_read(&btv->c);
 
-	/* remote IRQ? */
-	if (!(gpio & 0x20))
-		return 0;
-
 	/* get time of bit */
 	current_jiffies = jiffies;
 	do_gettimeofday(&tv);
@@ -176,6 +267,13 @@ 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",
+		gap, (gpio & 0x20) ? "mark" : "space");
+
+	/* remote IRQ? */
+	if (!(gpio & 0x20))
+		return 0;
+
 	/* active code => add bit */
 	if (ir->active) {
 		/* only if in the code (otherwise spurious IRQ or timer
@@ -187,13 +285,12 @@ static int bttv_rc5_irq(struct bttv *btv
 		}
 		/* starting new code */
 	} else {
-		ir->active = 1;
+		ir->active = true;
 		ir->code = 0;
 		ir->base_time = tv;
 		ir->last_bit = 0;
 
-		mod_timer(&ir->timer_end,
-			  current_jiffies + msecs_to_jiffies(30));
+		mod_timer(&ir->timer, current_jiffies + msecs_to_jiffies(30));
 	}
 
 	/* toggle GPIO pin 4 to reset the irq */
@@ -204,7 +301,7 @@ static int bttv_rc5_irq(struct bttv *btv
 
 /* ---------------------------------------------------------------------- */
 
-static void bttv_ir_start(struct bttv *btv, struct card_ir *ir)
+static void bttv_ir_start(struct bttv *btv, struct bttv_ir *ir)
 {
 	if (ir->polling) {
 		setup_timer(&ir->timer, bttv_input_timer, (unsigned long)btv);
@@ -212,33 +309,23 @@ static void bttv_ir_start(struct bttv *b
 		add_timer(&ir->timer);
 	} else if (ir->rc5_gpio) {
 		/* set timer_end for code completion */
-		init_timer(&ir->timer_end);
-		ir->timer_end.function = ir_rc5_timer_end;
-		ir->timer_end.data = (unsigned long)ir;
-
-		init_timer(&ir->timer_keyup);
-		ir->timer_keyup.function = ir_rc5_timer_keyup;
-		ir->timer_keyup.data = (unsigned long)ir;
+		setup_timer(&ir->timer, bttv_rc5_timer_end, (unsigned long)ir);
 		ir->shift_by = 1;
 		ir->start = 3;
 		ir->addr = 0x0;
-		ir->rc5_key_timeout = ir_rc5_key_timeout;
 		ir->rc5_remote_gap = ir_rc5_remote_gap;
 	}
 }
 
 static void bttv_ir_stop(struct bttv *btv)
 {
-	if (btv->remote->polling) {
+	if (btv->remote->polling)
 		del_timer_sync(&btv->remote->timer);
-		flush_scheduled_work();
-	}
 
 	if (btv->remote->rc5_gpio) {
 		u32 gpio;
 
-		del_timer_sync(&btv->remote->timer_end);
-		flush_scheduled_work();
+		del_timer_sync(&btv->remote->timer);
 
 		gpio = bttv_gpio_read(&btv->c);
 		bttv_gpio_write(&btv->c, gpio & ~(1 << 4));
@@ -264,6 +351,18 @@ static int get_key_pv951(struct IR_i2c *
 		return 0;
 	dprintk(KERN_INFO DEVNAME ": key %02x\n", b);
 
+	/*
+	 * NOTE:
+	 * lirc_i2c maps the pv951 code as:
+	 *	addr = 0x61D6
+	 * 	cmd = bit_reverse (b)
+	 * So, it seems that this device uses NEC extended
+	 * I decided to not fix the table, due to two reasons:
+	 * 	1) Without the actual device, this is only a guess;
+	 * 	2) As the addr is not reported via I2C, nor can be changed,
+	 * 	   the device is bound to the vendor-provided RC.
+	 */
+
 	*ir_key = b;
 	*ir_raw = b;
 	return 1;
@@ -290,16 +389,15 @@ void __devinit init_bttv_i2c_ir(struct b
 		btv->init_data.name = "PV951";
 		btv->init_data.get_key = get_key_pv951;
 		btv->init_data.ir_codes = RC_MAP_PV951;
-		btv->init_data.type = IR_TYPE_OTHER;
 		info.addr = 0x4b;
 		break;
 	default:
 		/*
 		 * The external IR receiver is at i2c address 0x34 (0x35 for
-                 * reads).  Future Hauppauge cards will have an internal
-                 * receiver at 0x30 (0x31 for reads).  In theory, both can be
-                 * fitted, and Hauppauge suggest an external overrides an
-                 * internal.
+		 * reads).  Future Hauppauge cards will have an internal
+		 * receiver at 0x30 (0x31 for reads).  In theory, both can be
+		 * fitted, and Hauppauge suggest an external overrides an
+		 * internal.
 		 * That's why we probe 0x1a (~0x34) first. CB
 		 */
 
@@ -324,18 +422,17 @@ int __devexit fini_bttv_i2c(struct bttv
 
 int bttv_input_init(struct bttv *btv)
 {
-	struct card_ir *ir;
+	struct bttv_ir *ir;
 	char *ir_codes = NULL;
-	struct input_dev *input_dev;
-	u64 ir_type = IR_TYPE_OTHER;
+	struct rc_dev *rc;
 	int err = -ENOMEM;
 
 	if (!btv->has_remote)
 		return -ENODEV;
 
 	ir = kzalloc(sizeof(*ir),GFP_KERNEL);
-	input_dev = input_allocate_device();
-	if (!ir || !input_dev)
+	rc = rc_allocate_device();
+	if (!ir || !rc)
 		goto err_out_free;
 
 	/* detect & configure */
@@ -398,8 +495,7 @@ int bttv_input_init(struct bttv *btv)
 		break;
 	case BTTV_BOARD_NEBULA_DIGITV:
 		ir_codes = RC_MAP_NEBULA;
-		btv->custom_irq = bttv_rc5_irq;
-		ir->rc5_gpio = 1;
+		ir->rc5_gpio = true;
 		break;
 	case BTTV_BOARD_MACHTV_MAGICTV:
 		ir_codes         = RC_MAP_APAC_VIEWCOMP;
@@ -441,48 +537,43 @@ int bttv_input_init(struct bttv *btv)
 	}
 
 	/* init input device */
-	ir->dev = input_dev;
+	ir->dev = rc;
 
 	snprintf(ir->name, sizeof(ir->name), "bttv IR (card=%d)",
 		 btv->c.type);
 	snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0",
 		 pci_name(btv->c.pci));
 
-	err = ir_input_init(input_dev, &ir->ir, ir_type);
-	if (err < 0)
-		goto err_out_free;
-
-	input_dev->name = ir->name;
-	input_dev->phys = ir->phys;
-	input_dev->id.bustype = BUS_PCI;
-	input_dev->id.version = 1;
+	rc->input_name = ir->name;
+	rc->input_phys = ir->phys;
+	rc->input_id.bustype = BUS_PCI;
+	rc->input_id.version = 1;
 	if (btv->c.pci->subsystem_vendor) {
-		input_dev->id.vendor  = btv->c.pci->subsystem_vendor;
-		input_dev->id.product = btv->c.pci->subsystem_device;
+		rc->input_id.vendor  = btv->c.pci->subsystem_vendor;
+		rc->input_id.product = btv->c.pci->subsystem_device;
 	} else {
-		input_dev->id.vendor  = btv->c.pci->vendor;
-		input_dev->id.product = btv->c.pci->device;
+		rc->input_id.vendor  = btv->c.pci->vendor;
+		rc->input_id.product = btv->c.pci->device;
 	}
-	input_dev->dev.parent = &btv->c.pci->dev;
+	rc->dev.parent = &btv->c.pci->dev;
+	rc->map_name = ir_codes;
+	rc->driver_name = MODULE_NAME;
 
 	btv->remote = ir;
 	bttv_ir_start(btv, ir);
 
 	/* all done */
-	err = ir_input_register(btv->remote->dev, ir_codes, NULL, MODULE_NAME);
+	err = rc_register_device(rc);
 	if (err)
 		goto err_out_stop;
 
-	/* the remote isn't as bouncy as a keyboard */
-	ir->dev->rep[REP_DELAY] = repeat_delay;
-	ir->dev->rep[REP_PERIOD] = repeat_period;
-
 	return 0;
 
  err_out_stop:
 	bttv_ir_stop(btv);
 	btv->remote = NULL;
  err_out_free:
+	rc_free_device(rc);
 	kfree(ir);
 	return err;
 }
@@ -493,7 +584,7 @@ void bttv_input_fini(struct bttv *btv)
 		return;
 
 	bttv_ir_stop(btv);
-	ir_input_unregister(btv->remote->dev);
+	rc_unregister_device(btv->remote->dev);
 	kfree(btv->remote);
 	btv->remote = NULL;
 }
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/bt8xx/bttvp.h linux-libre-2.6.38-gnu1/drivers/media/video/bt8xx/bttvp.h
--- linux-libre-2.6.37-gnu1/drivers/media/video/bt8xx/bttvp.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/bt8xx/bttvp.h	2011-03-14 21:20:32.000000000 -0400
@@ -41,7 +41,7 @@
 #include <linux/device.h>
 #include <media/videobuf-dma-sg.h>
 #include <media/tveeprom.h>
-#include <media/ir-common.h>
+#include <media/rc-core.h>
 #include <media/ir-kbd-i2c.h>
 
 #include "bt848.h"
@@ -120,6 +120,33 @@ struct bttv_format {
 	int  hshift,vshift;   /* for planar modes   */
 };
 
+struct bttv_ir {
+	struct rc_dev           *dev;
+	struct timer_list       timer;
+
+	char                    name[32];
+	char                    phys[32];
+
+	/* Usual gpio signalling */
+	u32                     mask_keycode;
+	u32                     mask_keydown;
+	u32                     mask_keyup;
+	u32                     polling;
+	u32                     last_gpio;
+	int                     shift_by;
+	int                     start; // What should RC5_START() be
+	int                     addr; // What RC5_ADDR() should be.
+	int                     rc5_remote_gap;
+
+	/* RC5 gpio */
+	bool			rc5_gpio;   /* Is RC5 legacy GPIO enabled? */
+	u32                     last_bit;   /* last raw bit seen */
+	u32                     code;       /* raw code under construction */
+	struct timeval          base_time;  /* time of last seen code */
+	bool                    active;     /* building raw code */
+};
+
+
 /* ---------------------------------------------------------- */
 
 struct bttv_geometry {
@@ -305,7 +332,6 @@ struct bttv_pll_info {
 /* for gpio-connected remote control */
 struct bttv_input {
 	struct input_dev      *dev;
-	struct ir_input_state ir;
 	char                  name[32];
 	char                  phys[32];
 	u32                   mask_keycode;
@@ -338,12 +364,10 @@ struct bttv {
 	struct bttv_pll_info pll;
 	int triton1;
 	int gpioirq;
-	int (*custom_irq)(struct bttv *btv);
 
 	int use_i2c_hw;
 
 	/* old gpio interface */
-	wait_queue_head_t gpioq;
 	int shutdown;
 
 	void (*volume_gpio)(struct bttv *btv, __u16 volume);
@@ -368,7 +392,7 @@ struct bttv {
 
 	/* infrared remote */
 	int has_remote;
-	struct card_ir *remote;
+	struct bttv_ir *remote;
 
 	/* I2C remote data */
 	struct IR_i2c_init_data    init_data;
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/bt8xx/Kconfig linux-libre-2.6.38-gnu1/drivers/media/video/bt8xx/Kconfig
--- linux-libre-2.6.37-gnu1/drivers/media/video/bt8xx/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/bt8xx/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -1,10 +1,10 @@
 config VIDEO_BT848
 	tristate "BT848 Video For Linux"
-	depends on VIDEO_DEV && PCI && I2C && VIDEO_V4L2 && INPUT
+	depends on VIDEO_DEV && PCI && I2C && VIDEO_V4L2
 	select I2C_ALGOBIT
 	select VIDEO_BTCX
 	select VIDEOBUF_DMA_SG
-	depends on VIDEO_IR
+	depends on RC_CORE
 	select VIDEO_TUNER
 	select VIDEO_TVEEPROM
 	select VIDEO_MSP3400 if VIDEO_HELPER_CHIPS_AUTO
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/cafe_ccic.c linux-libre-2.6.38-gnu1/drivers/media/video/cafe_ccic.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/cafe_ccic.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/cafe_ccic.c	2011-03-14 21:20:32.000000000 -0400
@@ -859,8 +859,6 @@ static int cafe_cam_configure(struct caf
 	struct v4l2_mbus_framefmt mbus_fmt;
 	int ret;
 
-	if (cam->state != S_IDLE)
-		return -EINVAL;
 	v4l2_fill_mbus_format(&mbus_fmt, &cam->pix_format, cam->mbus_code);
 	ret = sensor_call(cam, core, init, 0);
 	if (ret == 0)
@@ -2003,6 +2001,11 @@ static int cafe_pci_probe(struct pci_dev
 		.min_width = 320,
 		.min_height = 240,
 	};
+	struct i2c_board_info ov7670_info = {
+		.type = "ov7670",
+		.addr = 0x42,
+		.platform_data = &sensor_cfg,
+	};
 
 	/*
 	 * Start putting together one of our big camera structures.
@@ -2064,9 +2067,9 @@ static int cafe_pci_probe(struct pci_dev
 	if (dmi_check_system(olpc_xo1_dmi))
 		sensor_cfg.clock_speed = 45;
 
-	cam->sensor_addr = 0x42;
-	cam->sensor = v4l2_i2c_new_subdev_cfg(&cam->v4l2_dev, &cam->i2c_adapter,
-			"ov7670", 0, &sensor_cfg, cam->sensor_addr, NULL);
+	cam->sensor_addr = ov7670_info.addr;
+	cam->sensor = v4l2_i2c_new_subdev_board(&cam->v4l2_dev, &cam->i2c_adapter,
+			&ov7670_info, NULL);
 	if (cam->sensor == NULL) {
 		ret = -ENODEV;
 		goto out_smbus;
@@ -2186,9 +2189,7 @@ static int cafe_pci_resume(struct pci_de
 	struct cafe_camera *cam = to_cam(v4l2_dev);
 	int ret = 0;
 
-	ret = pci_restore_state(pdev);
-	if (ret)
-		return ret;
+	pci_restore_state(pdev);
 	ret = pci_enable_device(pdev);
 
 	if (ret) {
@@ -2196,12 +2197,13 @@ static int cafe_pci_resume(struct pci_de
 		return ret;
 	}
 	cafe_ctlr_init(cam);
-	cafe_ctlr_power_down(cam);
 
 	mutex_lock(&cam->s_mutex);
 	if (cam->users > 0) {
 		cafe_ctlr_power_up(cam);
 		__cafe_cam_reset(cam);
+	} else {
+		cafe_ctlr_power_down(cam);
 	}
 	mutex_unlock(&cam->s_mutex);
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/cpia2/cpia2_core.c linux-libre-2.6.38-gnu1/drivers/media/video/cpia2/cpia2_core.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/cpia2/cpia2_core.c	2013-05-03 03:56:49.000000000 -0400
+++ linux-libre-2.6.38-gnu1/drivers/media/video/cpia2/cpia2_core.c	2013-05-03 01:56:31.000000000 -0400
@@ -2247,7 +2247,7 @@ struct camera_data *cpia2_init_camera_st
 
 
 	cam->present = 1;
-	mutex_init(&cam->busy_lock);
+	mutex_init(&cam->v4l2_lock);
 	init_waitqueue_head(&cam->wq_stream);
 
 	return cam;
@@ -2365,9 +2365,9 @@ long cpia2_read(struct camera_data *cam,
 		char __user *buf, unsigned long count, int noblock)
 {
 	struct framebuf *frame;
-	if (!count) {
+
+	if (!count)
 		return 0;
-	}
 
 	if (!buf) {
 		ERR("%s: buffer NULL\n",__func__);
@@ -2379,17 +2379,12 @@ long cpia2_read(struct camera_data *cam,
 		return -EINVAL;
 	}
 
-	/* make this _really_ smp and multithread-safe */
-	if (mutex_lock_interruptible(&cam->busy_lock))
-		return -ERESTARTSYS;
-
 	if (!cam->present) {
 		LOG("%s: camera removed\n",__func__);
-		mutex_unlock(&cam->busy_lock);
 		return 0;	/* EOF */
 	}
 
-	if(!cam->streaming) {
+	if (!cam->streaming) {
 		/* Start streaming */
 		cpia2_usb_stream_start(cam,
 				       cam->params.camera_state.stream_mode);
@@ -2398,42 +2393,31 @@ long cpia2_read(struct camera_data *cam,
 	/* Copy cam->curbuff in case it changes while we're processing */
 	frame = cam->curbuff;
 	if (noblock && frame->status != FRAME_READY) {
-		mutex_unlock(&cam->busy_lock);
 		return -EAGAIN;
 	}
 
-	if(frame->status != FRAME_READY) {
-		mutex_unlock(&cam->busy_lock);
+	if (frame->status != FRAME_READY) {
+		mutex_unlock(&cam->v4l2_lock);
 		wait_event_interruptible(cam->wq_stream,
 			       !cam->present ||
 			       (frame = cam->curbuff)->status == FRAME_READY);
+		mutex_lock(&cam->v4l2_lock);
 		if (signal_pending(current))
 			return -ERESTARTSYS;
-		/* make this _really_ smp and multithread-safe */
-		if (mutex_lock_interruptible(&cam->busy_lock)) {
-			return -ERESTARTSYS;
-		}
-		if(!cam->present) {
-			mutex_unlock(&cam->busy_lock);
+		if (!cam->present)
 			return 0;
-		}
 	}
 
 	/* copy data to user space */
-	if (frame->length > count) {
-		mutex_unlock(&cam->busy_lock);
+	if (frame->length > count)
 		return -EFAULT;
-	}
-	if (copy_to_user(buf, frame->data, frame->length)) {
-		mutex_unlock(&cam->busy_lock);
+	if (copy_to_user(buf, frame->data, frame->length))
 		return -EFAULT;
-	}
 
 	count = frame->length;
 
 	frame->status = FRAME_EMPTY;
 
-	mutex_unlock(&cam->busy_lock);
 	return count;
 }
 
@@ -2447,17 +2431,13 @@ unsigned int cpia2_poll(struct camera_da
 {
 	unsigned int status=0;
 
-	if(!cam) {
+	if (!cam) {
 		ERR("%s: Internal error, camera_data not found!\n",__func__);
 		return POLLERR;
 	}
 
-	mutex_lock(&cam->busy_lock);
-
-	if(!cam->present) {
-		mutex_unlock(&cam->busy_lock);
+	if (!cam->present)
 		return POLLHUP;
-	}
 
 	if(!cam->streaming) {
 		/* Start streaming */
@@ -2465,16 +2445,13 @@ unsigned int cpia2_poll(struct camera_da
 				       cam->params.camera_state.stream_mode);
 	}
 
-	mutex_unlock(&cam->busy_lock);
 	poll_wait(filp, &cam->wq_stream, wait);
-	mutex_lock(&cam->busy_lock);
 
 	if(!cam->present)
 		status = POLLHUP;
 	else if(cam->curbuff->status == FRAME_READY)
 		status = POLLIN | POLLRDNORM;
 
-	mutex_unlock(&cam->busy_lock);
 	return status;
 }
 
@@ -2496,29 +2473,19 @@ int cpia2_remap_buffer(struct camera_dat
 
 	DBG("mmap offset:%ld size:%ld\n", start_offset, size);
 
-	/* make this _really_ smp-safe */
-	if (mutex_lock_interruptible(&cam->busy_lock))
-		return -ERESTARTSYS;
-
-	if (!cam->present) {
-		mutex_unlock(&cam->busy_lock);
+	if (!cam->present)
 		return -ENODEV;
-	}
 
 	if (size > cam->frame_size*cam->num_frames  ||
 	    (start_offset % cam->frame_size) != 0 ||
-	    (start_offset+size > cam->frame_size*cam->num_frames)) {
-		mutex_unlock(&cam->busy_lock);
+	    (start_offset+size > cam->frame_size*cam->num_frames))
 		return -EINVAL;
-	}
 
 	pos = ((unsigned long) (cam->frame_buffer)) + start_offset;
 	while (size > 0) {
 		page = kvirt_to_pa(pos);
-		if (remap_pfn_range(vma, start, page >> PAGE_SHIFT, PAGE_SIZE, PAGE_SHARED)) {
-			mutex_unlock(&cam->busy_lock);
+		if (remap_pfn_range(vma, start, page >> PAGE_SHIFT, PAGE_SIZE, PAGE_SHARED))
 			return -EAGAIN;
-		}
 		start += PAGE_SIZE;
 		pos += PAGE_SIZE;
 		if (size > PAGE_SIZE)
@@ -2528,7 +2495,5 @@ int cpia2_remap_buffer(struct camera_dat
 	}
 
 	cam->mmapped = true;
-	mutex_unlock(&cam->busy_lock);
 	return 0;
 }
-
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/cpia2/cpia2.h linux-libre-2.6.38-gnu1/drivers/media/video/cpia2/cpia2.h
--- linux-libre-2.6.37-gnu1/drivers/media/video/cpia2/cpia2.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/cpia2/cpia2.h	2011-03-14 21:20:32.000000000 -0400
@@ -378,7 +378,7 @@ struct cpia2_fh {
 
 struct camera_data {
 	/* locks */
-	struct mutex busy_lock;	/* guard against SMP multithreading */
+	struct mutex v4l2_lock;	/* serialize file operations */
 	struct v4l2_prio_state prio;
 
 	/* camera status */
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/cpia2/cpia2_v4l.c linux-libre-2.6.38-gnu1/drivers/media/video/cpia2/cpia2_v4l.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/cpia2/cpia2_v4l.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/cpia2/cpia2_v4l.c	2011-03-14 21:20:32.000000000 -0400
@@ -238,59 +238,40 @@ static struct v4l2_queryctrl controls[]
 static int cpia2_open(struct file *file)
 {
 	struct camera_data *cam = video_drvdata(file);
-	int retval = 0;
+	struct cpia2_fh *fh;
 
 	if (!cam) {
 		ERR("Internal error, camera_data not found!\n");
 		return -ENODEV;
 	}
 
-	if(mutex_lock_interruptible(&cam->busy_lock))
-		return -ERESTARTSYS;
-
-	if(!cam->present) {
-		retval = -ENODEV;
-		goto err_return;
-	}
+	if (!cam->present)
+		return -ENODEV;
 
-	if (cam->open_count > 0) {
-		goto skip_init;
-	}
+	if (cam->open_count == 0) {
+		if (cpia2_allocate_buffers(cam))
+			return -ENOMEM;
 
-	if (cpia2_allocate_buffers(cam)) {
-		retval = -ENOMEM;
-		goto err_return;
-	}
+		/* reset the camera */
+		if (cpia2_reset_camera(cam) < 0)
+			return -EIO;
 
-	/* reset the camera */
-	if (cpia2_reset_camera(cam) < 0) {
-		retval = -EIO;
-		goto err_return;
+		cam->APP_len = 0;
+		cam->COM_len = 0;
 	}
 
-	cam->APP_len = 0;
-	cam->COM_len = 0;
-
-skip_init:
-	{
-		struct cpia2_fh *fh = kmalloc(sizeof(*fh),GFP_KERNEL);
-		if(!fh) {
-			retval = -ENOMEM;
-			goto err_return;
-		}
-		file->private_data = fh;
-		fh->prio = V4L2_PRIORITY_UNSET;
-		v4l2_prio_open(&cam->prio, &fh->prio);
-		fh->mmapped = 0;
-	}
+	fh = kmalloc(sizeof(*fh), GFP_KERNEL);
+	if (!fh)
+		return -ENOMEM;
+	file->private_data = fh;
+	fh->prio = V4L2_PRIORITY_UNSET;
+	v4l2_prio_open(&cam->prio, &fh->prio);
+	fh->mmapped = 0;
 
 	++cam->open_count;
 
 	cpia2_dbg_dump_registers(cam);
-
-err_return:
-	mutex_unlock(&cam->busy_lock);
-	return retval;
+	return 0;
 }
 
 /******************************************************************************
@@ -304,15 +285,11 @@ static int cpia2_close(struct file *file
 	struct camera_data *cam = video_get_drvdata(dev);
 	struct cpia2_fh *fh = file->private_data;
 
-	mutex_lock(&cam->busy_lock);
-
 	if (cam->present &&
-	    (cam->open_count == 1
-	     || fh->prio == V4L2_PRIORITY_RECORD
-	    )) {
+	    (cam->open_count == 1 || fh->prio == V4L2_PRIORITY_RECORD)) {
 		cpia2_usb_stream_stop(cam);
 
-		if(cam->open_count == 1) {
+		if (cam->open_count == 1) {
 			/* save camera state for later open */
 			cpia2_save_camera_state(cam);
 
@@ -321,26 +298,21 @@ static int cpia2_close(struct file *file
 		}
 	}
 
-	{
-		if(fh->mmapped)
-			cam->mmapped = 0;
-		v4l2_prio_close(&cam->prio, fh->prio);
-		file->private_data = NULL;
-		kfree(fh);
-	}
+	if (fh->mmapped)
+		cam->mmapped = 0;
+	v4l2_prio_close(&cam->prio, fh->prio);
+	file->private_data = NULL;
+	kfree(fh);
 
 	if (--cam->open_count == 0) {
 		cpia2_free_buffers(cam);
 		if (!cam->present) {
 			video_unregister_device(dev);
-			mutex_unlock(&cam->busy_lock);
 			kfree(cam);
 			return 0;
 		}
 	}
 
-	mutex_unlock(&cam->busy_lock);
-
 	return 0;
 }
 
@@ -405,11 +377,11 @@ static int sync(struct camera_data *cam,
 			return 0;
 		}
 
-		mutex_unlock(&cam->busy_lock);
+		mutex_unlock(&cam->v4l2_lock);
 		wait_event_interruptible(cam->wq_stream,
 					 !cam->streaming ||
 					 frame->status == FRAME_READY);
-		mutex_lock(&cam->busy_lock);
+		mutex_lock(&cam->v4l2_lock);
 		if (signal_pending(current))
 			return -ERESTARTSYS;
 		if(!cam->present)
@@ -419,28 +391,6 @@ static int sync(struct camera_data *cam,
 
 /******************************************************************************
  *
- *  ioctl_get_mbuf
- *
- *****************************************************************************/
-#ifdef CONFIG_VIDEO_V4L1_COMPAT
-static int ioctl_get_mbuf(void *arg, struct camera_data *cam)
-{
-	struct video_mbuf *vm;
-	int i;
-	vm = arg;
-
-	memset(vm, 0, sizeof(*vm));
-	vm->size = cam->frame_size*cam->num_frames;
-	vm->frames = cam->num_frames;
-	for (i = 0; i < cam->num_frames; i++)
-		vm->offsets[i] = cam->frame_size * i;
-
-	return 0;
-}
-#endif
-
-/******************************************************************************
- *
  *  ioctl_set_gpio
  *
  *****************************************************************************/
@@ -1315,11 +1265,11 @@ static int ioctl_dqbuf(void *arg,struct
 	if(frame < 0) {
 		/* Wait for a frame to become available */
 		struct framebuf *cb=cam->curbuff;
-		mutex_unlock(&cam->busy_lock);
+		mutex_unlock(&cam->v4l2_lock);
 		wait_event_interruptible(cam->wq_stream,
 					 !cam->present ||
 					 (cb=cam->curbuff)->status == FRAME_READY);
-		mutex_lock(&cam->busy_lock);
+		mutex_lock(&cam->v4l2_lock);
 		if (signal_pending(current))
 			return -ERESTARTSYS;
 		if(!cam->present)
@@ -1359,14 +1309,8 @@ static long cpia2_do_ioctl(struct file *
 	if (!cam)
 		return -ENOTTY;
 
-	/* make this _really_ smp-safe */
-	if (mutex_lock_interruptible(&cam->busy_lock))
-		return -ERESTARTSYS;
-
-	if (!cam->present) {
-		mutex_unlock(&cam->busy_lock);
+	if (!cam->present)
 		return -ENODEV;
-	}
 
 	/* Priority check */
 	switch (cmd) {
@@ -1374,23 +1318,10 @@ static long cpia2_do_ioctl(struct file *
 	{
 		struct cpia2_fh *fh = file->private_data;
 		retval = v4l2_prio_check(&cam->prio, fh->prio);
-		if(retval) {
-			mutex_unlock(&cam->busy_lock);
+		if (retval)
 			return retval;
-		}
 		break;
 	}
-#ifdef CONFIG_VIDEO_V4L1_COMPAT
-	case VIDIOCGMBUF:
-	{
-		struct cpia2_fh *fh = file->private_data;
-		if(fh->prio != V4L2_PRIORITY_RECORD) {
-			mutex_unlock(&cam->busy_lock);
-			return -EBUSY;
-		}
-		break;
-	}
-#endif
 	default:
 		break;
 	}
@@ -1400,11 +1331,6 @@ static long cpia2_do_ioctl(struct file *
 	case CPIA2_IOC_SET_GPIO:
 		retval = ioctl_set_gpio(arg, cam);
 		break;
-#ifdef CONFIG_VIDEO_V4L1_COMPAT
-	case VIDIOCGMBUF:	/* mmap interface */
-		retval = ioctl_get_mbuf(arg, cam);
-		break;
-#endif
 	case VIDIOC_QUERYCAP:
 		retval = ioctl_querycap(arg,cam);
 		break;
@@ -1567,7 +1493,6 @@ static long cpia2_do_ioctl(struct file *
 		break;
 	}
 
-	mutex_unlock(&cam->busy_lock);
 	return retval;
 }
 
@@ -1634,7 +1559,7 @@ static const struct v4l2_file_operations
 	.release	= cpia2_close,
 	.read		= cpia2_v4l_read,
 	.poll		= cpia2_v4l_poll,
-	.ioctl		= cpia2_ioctl,
+	.unlocked_ioctl	= cpia2_ioctl,
 	.mmap		= cpia2_mmap,
 };
 
@@ -1658,6 +1583,7 @@ int cpia2_register_camera(struct camera_
 
 	memcpy(cam->vdev, &cpia2_template, sizeof(cpia2_template));
 	video_set_drvdata(cam->vdev, cam);
+	cam->vdev->lock = &cam->v4l2_lock;
 
 	reset_camera_struct_v4l(cam);
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/cx18/cx18-cards.c linux-libre-2.6.38-gnu1/drivers/media/video/cx18/cx18-cards.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/cx18/cx18-cards.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/cx18/cx18-cards.c	2011-03-14 21:20:32.000000000 -0400
@@ -39,7 +39,7 @@ static struct cx18_card_tuner_i2c cx18_i
 	.tv    = { 0x61, 0x60, I2C_CLIENT_END },
 };
 
-/* Please add new PCI IDs to: http://pci-ids.ucw.cz/ 
+/* Please add new PCI IDs to: http://pci-ids.ucw.cz/
    This keeps the PCI ID database up to date. Note that the entries
    must be added under vendor 0x4444 (Conexant) as subsystem IDs.
    New vendor IDs should still be added to the vendor ID list. */
@@ -95,6 +95,53 @@ static const struct cx18_card cx18_card_
 	.i2c = &cx18_i2c_std,
 };
 
+static const struct cx18_card cx18_card_hvr1600_s5h1411 = {
+	.type = CX18_CARD_HVR_1600_S5H1411,
+	.name = "Hauppauge HVR-1600",
+	.comment = "Simultaneous Digital and Analog TV capture supported\n",
+	.v4l2_capabilities = CX18_CAP_ENCODER,
+	.hw_audio_ctrl = CX18_HW_418_AV,
+	.hw_muxer = CX18_HW_CS5345,
+	.hw_all = CX18_HW_TVEEPROM | CX18_HW_418_AV | CX18_HW_TUNER |
+		  CX18_HW_CS5345 | CX18_HW_DVB | CX18_HW_GPIO_RESET_CTRL |
+		  CX18_HW_Z8F0811_IR_HAUP,
+	.video_inputs = {
+		{ CX18_CARD_INPUT_VID_TUNER,  0, CX18_AV_COMPOSITE7 },
+		{ CX18_CARD_INPUT_SVIDEO1,    1, CX18_AV_SVIDEO1    },
+		{ CX18_CARD_INPUT_COMPOSITE1, 1, CX18_AV_COMPOSITE3 },
+		{ CX18_CARD_INPUT_SVIDEO2,    2, CX18_AV_SVIDEO2    },
+		{ CX18_CARD_INPUT_COMPOSITE2, 2, CX18_AV_COMPOSITE4 },
+	},
+	.audio_inputs = {
+		{ CX18_CARD_INPUT_AUD_TUNER,
+		  CX18_AV_AUDIO8, CS5345_IN_1 | CS5345_MCLK_1_5 },
+		{ CX18_CARD_INPUT_LINE_IN1,
+		  CX18_AV_AUDIO_SERIAL1, CS5345_IN_2 },
+		{ CX18_CARD_INPUT_LINE_IN2,
+		  CX18_AV_AUDIO_SERIAL1, CS5345_IN_3 },
+	},
+	.radio_input = { CX18_CARD_INPUT_AUD_TUNER,
+			 CX18_AV_AUDIO_SERIAL1, CS5345_IN_4 },
+	.ddr = {
+		/* ESMT M13S128324A-5B memory */
+		.chip_config = 0x003,
+		.refresh = 0x30c,
+		.timing1 = 0x44220e82,
+		.timing2 = 0x08,
+		.tune_lane = 0,
+		.initial_emrs = 0,
+	},
+	.gpio_init.initial_value = 0x3001,
+	.gpio_init.direction = 0x3001,
+	.gpio_i2c_slave_reset = {
+		.active_lo_mask = 0x3001,
+		.msecs_asserted = 10,
+		.msecs_recovery = 40,
+		.ir_reset_mask  = 0x0001,
+	},
+	.i2c = &cx18_i2c_std,
+};
+
 static const struct cx18_card cx18_card_hvr1600_samsung = {
 	.type = CX18_CARD_HVR_1600_SAMSUNG,
 	.name = "Hauppauge HVR-1600 (Preproduction)",
@@ -251,6 +298,66 @@ static const struct cx18_card cx18_card_
 
 /* ------------------------------------------------------------------------- */
 
+/* GoTView PCI */
+
+static const struct cx18_card_pci_info cx18_pci_gotview_dvd3[] = {
+	{ PCI_DEVICE_ID_CX23418, CX18_PCI_ID_GOTVIEW, 0x3343 },
+	{ 0, 0, 0 }
+};
+
+static const struct cx18_card cx18_card_gotview_dvd3 = {
+	.type = CX18_CARD_GOTVIEW_PCI_DVD3,
+	.name = "GoTView PCI DVD3 Hybrid",
+	.comment = "Experimenters needed for device to work well.\n"
+		  "\tTo help, mail the ivtv-devel list (www.ivtvdriver.org).\n",
+	.v4l2_capabilities = CX18_CAP_ENCODER,
+	.hw_audio_ctrl = CX18_HW_418_AV,
+	.hw_muxer = CX18_HW_GPIO_MUX,
+	.hw_all = CX18_HW_TVEEPROM | CX18_HW_418_AV | CX18_HW_TUNER |
+		  CX18_HW_GPIO_MUX | CX18_HW_DVB | CX18_HW_GPIO_RESET_CTRL,
+	.video_inputs = {
+		{ CX18_CARD_INPUT_VID_TUNER,  0, CX18_AV_COMPOSITE2 },
+		{ CX18_CARD_INPUT_SVIDEO1,    1,
+				CX18_AV_SVIDEO_LUMA3 | CX18_AV_SVIDEO_CHROMA4 },
+		{ CX18_CARD_INPUT_COMPOSITE1, 1, CX18_AV_COMPOSITE1 },
+		{ CX18_CARD_INPUT_SVIDEO2,    2,
+				CX18_AV_SVIDEO_LUMA7 | CX18_AV_SVIDEO_CHROMA8 },
+		{ CX18_CARD_INPUT_COMPOSITE2, 2, CX18_AV_COMPOSITE6 },
+	},
+	.audio_inputs = {
+		{ CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO5,        0 },
+		{ CX18_CARD_INPUT_LINE_IN1,  CX18_AV_AUDIO_SERIAL1, 1 },
+		{ CX18_CARD_INPUT_LINE_IN2,  CX18_AV_AUDIO_SERIAL2, 1 },
+	},
+	.tuners = {
+		/* XC3028 tuner */
+		{ .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 },
+	},
+	/* FIXME - the FM radio is just a guess and driver doesn't use SIF */
+	.radio_input = { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO5, 2 },
+	.ddr = {
+		/* Hynix HY5DU283222B DDR RAM */
+		.chip_config = 0x303,
+		.refresh = 0x3bd,
+		.timing1 = 0x36320966,
+		.timing2 = 0x1f,
+		.tune_lane = 0,
+		.initial_emrs = 2,
+	},
+	.gpio_init.initial_value = 0x1,
+	.gpio_init.direction = 0x3,
+
+	.gpio_audio_input = { .mask   = 0x3,
+			      .tuner  = 0x1,
+			      .linein = 0x2,
+			      .radio  = 0x1 },
+	.xceive_pin = 0,
+	.pci_list = cx18_pci_gotview_dvd3,
+	.i2c = &cx18_i2c_std,
+};
+
+/* ------------------------------------------------------------------------- */
+
 /* Conexant Raptor PAL/SECAM: note that this card is analog only! */
 
 static const struct cx18_card_pci_info cx18_pci_cnxt_raptor_pal[] = {
@@ -463,6 +570,8 @@ static const struct cx18_card *cx18_card
 	&cx18_card_toshiba_qosmio_dvbt,
 	&cx18_card_leadtek_pvr2100,
 	&cx18_card_leadtek_dvr3100h,
+	&cx18_card_gotview_dvd3,
+	&cx18_card_hvr1600_s5h1411
 };
 
 const struct cx18_card *cx18_get_card(u16 index)
@@ -485,7 +594,6 @@ int cx18_get_input(struct cx18 *cx, u16
 		"Component 1"
 	};
 
-	memset(input, 0, sizeof(*input));
 	if (index >= cx->nof_inputs)
 		return -EINVAL;
 	input->index = index;
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/cx18/cx18-controls.c linux-libre-2.6.38-gnu1/drivers/media/video/cx18/cx18-controls.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/cx18/cx18-controls.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/cx18/cx18-controls.c	2011-03-14 21:20:32.000000000 -0400
@@ -108,7 +108,7 @@ static int cx18_try_ctrl(struct file *fi
 					struct v4l2_ext_control *vctrl)
 {
 	struct v4l2_queryctrl qctrl;
-	const char **menu_items = NULL;
+	const char * const *menu_items = NULL;
 	int err;
 
 	qctrl.id = vctrl->id;
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/cx18/cx18-driver.c linux-libre-2.6.38-gnu1/drivers/media/video/cx18/cx18-driver.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/cx18/cx18-driver.c	2013-05-03 03:54:56.000000000 -0400
+++ linux-libre-2.6.38-gnu1/drivers/media/video/cx18/cx18-driver.c	2013-05-03 01:54:14.000000000 -0400
@@ -156,6 +156,8 @@ MODULE_PARM_DESC(cardtype,
 		 "\t\t\t 6 = Toshiba Qosmio DVB-T/Analog\n"
 		 "\t\t\t 7 = Leadtek WinFast PVR2100\n"
 		 "\t\t\t 8 = Leadtek WinFast DVR3100 H\n"
+		 "\t\t\t 9 = GoTView PCI DVD3 Hybrid\n"
+		 "\t\t\t 10 = Hauppauge HVR 1600 (S5H1411)\n"
 		 "\t\t\t 0 = Autodetect (default)\n"
 		 "\t\t\t-1 = Ignore this card\n\t\t");
 MODULE_PARM_DESC(pal, "Set PAL standard: B, G, H, D, K, I, M, N, Nc, 60");
@@ -266,8 +268,14 @@ static void request_modules(struct cx18
 	INIT_WORK(&dev->request_module_wk, request_module_async);
 	schedule_work(&dev->request_module_wk);
 }
+
+static void flush_request_modules(struct cx18 *dev)
+{
+	flush_work_sync(&dev->request_module_wk);
+}
 #else
 #define request_modules(dev)
+#define flush_request_modules(dev)
 #endif /* CONFIG_MODULES */
 
 /* Generic utility functions */
@@ -330,9 +338,11 @@ void cx18_read_eeprom(struct cx18 *cx, s
 	switch (cx->card->type) {
 	case CX18_CARD_HVR_1600_ESMT:
 	case CX18_CARD_HVR_1600_SAMSUNG:
+	case CX18_CARD_HVR_1600_S5H1411:
 		tveeprom_hauppauge_analog(&c, tv, eedata);
 		break;
 	case CX18_CARD_YUAN_MPC718:
+	case CX18_CARD_GOTVIEW_PCI_DVD3:
 		tv->model = 0x718;
 		cx18_eeprom_dump(cx, eedata, sizeof(eedata));
 		CX18_INFO("eeprom PCI ID: %02x%02x:%02x%02x\n",
@@ -357,7 +367,25 @@ static void cx18_process_eeprom(struct c
 	   from the model number. Use the cardtype module option if you
 	   have one of these preproduction models. */
 	switch (tv.model) {
-	case 74000 ... 74999:
+	case 74301: /* Retail models */
+	case 74321:
+	case 74351: /* OEM models */
+	case 74361:
+		/* Digital side is s5h1411/tda18271 */
+		cx->card = cx18_get_card(CX18_CARD_HVR_1600_S5H1411);
+		break;
+	case 74021: /* Retail models */
+	case 74031:
+	case 74041:
+	case 74141:
+	case 74541: /* OEM models */
+	case 74551:
+	case 74591:
+	case 74651:
+	case 74691:
+	case 74751:
+	case 74891:
+		/* Digital side is s5h1409/mxl5005s */
 		cx->card = cx18_get_card(CX18_CARD_HVR_1600_ESMT);
 		break;
 	case 0x718:
@@ -369,7 +397,8 @@ static void cx18_process_eeprom(struct c
 		CX18_ERR("Invalid EEPROM\n");
 		return;
 	default:
-		CX18_ERR("Unknown model %d, defaulting to HVR-1600\n", tv.model);
+		CX18_ERR("Unknown model %d, defaulting to original HVR-1600 "
+			 "(cardtype=1)\n", tv.model);
 		cx->card = cx18_get_card(CX18_CARD_HVR_1600_ESMT);
 		break;
 	}
@@ -656,7 +685,7 @@ static int __devinit cx18_create_in_work
 {
 	snprintf(cx->in_workq_name, sizeof(cx->in_workq_name), "%s-in",
 		 cx->v4l2_dev.name);
-	cx->in_work_queue = create_singlethread_workqueue(cx->in_workq_name);
+	cx->in_work_queue = alloc_ordered_workqueue(cx->in_workq_name, 0);
 	if (cx->in_work_queue == NULL) {
 		CX18_ERR("Unable to create incoming mailbox handler thread\n");
 		return -ENOMEM;
@@ -664,18 +693,6 @@ static int __devinit cx18_create_in_work
 	return 0;
 }
 
-static int __devinit cx18_create_out_workq(struct cx18 *cx)
-{
-	snprintf(cx->out_workq_name, sizeof(cx->out_workq_name), "%s-out",
-		 cx->v4l2_dev.name);
-	cx->out_work_queue = create_workqueue(cx->out_workq_name);
-	if (cx->out_work_queue == NULL) {
-		CX18_ERR("Unable to create outgoing mailbox handler threads\n");
-		return -ENOMEM;
-	}
-	return 0;
-}
-
 static void __devinit cx18_init_in_work_orders(struct cx18 *cx)
 {
 	int i;
@@ -702,15 +719,9 @@ static int __devinit cx18_init_struct1(s
 	mutex_init(&cx->epu2apu_mb_lock);
 	mutex_init(&cx->epu2cpu_mb_lock);
 
-	ret = cx18_create_out_workq(cx);
-	if (ret)
-		return ret;
-
 	ret = cx18_create_in_workq(cx);
-	if (ret) {
-		destroy_workqueue(cx->out_work_queue);
+	if (ret)
 		return ret;
-	}
 
 	cx18_init_in_work_orders(cx);
 
@@ -923,8 +934,13 @@ static int __devinit cx18_probe(struct p
 	cx->enc_mem = ioremap_nocache(cx->base_addr + CX18_MEM_OFFSET,
 				       CX18_MEM_SIZE);
 	if (!cx->enc_mem) {
-		CX18_ERR("ioremap failed, perhaps increasing __VMALLOC_RESERVE in page.h\n");
-		CX18_ERR("or disabling CONFIG_HIGHMEM4G into the kernel would help\n");
+		CX18_ERR("ioremap failed. Can't get a window into CX23418 "
+			 "memory and register space\n");
+		CX18_ERR("Each capture card with a CX23418 needs 64 MB of "
+			 "vmalloc address space for the window\n");
+		CX18_ERR("Check the output of 'grep Vmalloc /proc/meminfo'\n");
+		CX18_ERR("Use the vmalloc= kernel command line option to set "
+			 "VmallocTotal to a larger value\n");
 		retval = -ENOMEM;
 		goto free_mem;
 	}
@@ -1094,7 +1110,6 @@ free_mem:
 	release_mem_region(cx->base_addr, CX18_MEM_SIZE);
 free_workqueues:
 	destroy_workqueue(cx->in_work_queue);
-	destroy_workqueue(cx->out_work_queue);
 err:
 	if (retval == 0)
 		retval = -ENODEV;
@@ -1226,6 +1241,8 @@ static void cx18_remove(struct pci_dev *
 
 	CX18_DEBUG_INFO("Removing Card\n");
 
+	flush_request_modules(cx);
+
 	/* Stop all captures */
 	CX18_DEBUG_INFO("Stopping all streams\n");
 	if (atomic_read(&cx->tot_capturing) > 0)
@@ -1244,7 +1261,6 @@ static void cx18_remove(struct pci_dev *
 	cx18_halt_firmware(cx);
 
 	destroy_workqueue(cx->in_work_queue);
-	destroy_workqueue(cx->out_work_queue);
 
 	cx18_streams_cleanup(cx, 1);
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/cx18/cx18-driver.h linux-libre-2.6.38-gnu1/drivers/media/video/cx18/cx18-driver.h
--- linux-libre-2.6.37-gnu1/drivers/media/video/cx18/cx18-driver.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/cx18/cx18-driver.h	2011-03-14 21:20:32.000000000 -0400
@@ -84,7 +84,9 @@
 #define CX18_CARD_TOSHIBA_QOSMIO_DVBT 5 /* Toshiba Qosmio Interal DVB-T/Analog*/
 #define CX18_CARD_LEADTEK_PVR2100     6 /* Leadtek WinFast PVR2100 */
 #define CX18_CARD_LEADTEK_DVR3100H    7 /* Leadtek WinFast DVR3100 H */
-#define CX18_CARD_LAST 		      7
+#define CX18_CARD_GOTVIEW_PCI_DVD3    8 /* GoTView PCI DVD3 Hybrid */
+#define CX18_CARD_HVR_1600_S5H1411    9 /* Hauppauge HVR 1600 s5h1411/tda18271*/
+#define CX18_CARD_LAST		      9
 
 #define CX18_ENC_STREAM_TYPE_MPG  0
 #define CX18_ENC_STREAM_TYPE_TS   1
@@ -106,6 +108,7 @@
 #define CX18_PCI_ID_CONEXANT		0x14f1
 #define CX18_PCI_ID_TOSHIBA		0x1179
 #define CX18_PCI_ID_LEADTEK		0x107D
+#define CX18_PCI_ID_GOTVIEW		0x5854
 
 /* ======================================================================== */
 /* ========================== START USER SETTABLE DMA VARIABLES =========== */
@@ -323,7 +326,10 @@ struct cx18_queue {
 	spinlock_t lock;
 };
 
+struct cx18_stream; /* forward reference */
+
 struct cx18_dvb {
+	struct cx18_stream *stream;
 	struct dmx_frontend hw_frontend;
 	struct dmx_frontend mem_frontend;
 	struct dmxdev dmxdev;
@@ -363,9 +369,10 @@ struct cx18_in_work_order {
 #define CX18_INVALID_TASK_HANDLE 0xffffffff
 
 struct cx18_stream {
-	/* These first four fields are always set, even if the stream
+	/* These first five fields are always set, even if the stream
 	   is not actually created. */
 	struct video_device *video_dev;	/* NULL when stream not created */
+	struct cx18_dvb *dvb;		/* DVB / Digital Transport */
 	struct cx18 *cx; 		/* for ease of use */
 	const char *name;		/* name of the stream */
 	int type;			/* stream type */
@@ -395,9 +402,6 @@ struct cx18_stream {
 	struct cx18_queue q_idle;	/* idle - not in rotation */
 
 	struct work_struct out_work_order;
-
-	/* DVB / Digital Transport */
-	struct cx18_dvb dvb;
 };
 
 struct cx18_open_id {
@@ -614,9 +618,6 @@ struct cx18 {
 	struct cx18_in_work_order in_work_order[CX18_MAX_IN_WORK_ORDERS];
 	char epu_debug_str[256]; /* CX18_EPU_DEBUG is rare: use shared space */
 
-	struct workqueue_struct *out_work_queue;
-	char out_workq_name[12]; /* "cx18-NN-out" */
-
 	/* i2c */
 	struct i2c_adapter i2c_adap[2];
 	struct i2c_algo_bit_data i2c_algo[2];
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/cx18/cx18-dvb.c linux-libre-2.6.38-gnu1/drivers/media/video/cx18/cx18-dvb.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/cx18/cx18-dvb.c	2013-05-03 03:56:53.000000000 -0400
+++ linux-libre-2.6.38-gnu1/drivers/media/video/cx18/cx18-dvb.c	2013-05-03 01:56:36.000000000 -0400
@@ -29,6 +29,8 @@
 #include "cx18-gpio.h"
 #include "s5h1409.h"
 #include "mxl5005s.h"
+#include "s5h1411.h"
+#include "tda18271.h"
 #include "zl10353.h"
 
 #include <linux/firmware.h>
@@ -77,6 +79,32 @@ static struct s5h1409_config hauppauge_h
 };
 
 /*
+ * CX18_CARD_HVR_1600_S5H1411
+ */
+static struct s5h1411_config hcw_s5h1411_config = {
+	.output_mode   = S5H1411_SERIAL_OUTPUT,
+	.gpio          = S5H1411_GPIO_OFF,
+	.vsb_if        = S5H1411_IF_44000,
+	.qam_if        = S5H1411_IF_4000,
+	.inversion     = S5H1411_INVERSION_ON,
+	.status_mode   = S5H1411_DEMODLOCKING,
+	.mpeg_timing   = S5H1411_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK,
+};
+
+static struct tda18271_std_map hauppauge_tda18271_std_map = {
+	.atsc_6   = { .if_freq = 5380, .agc_mode = 3, .std = 3,
+		      .if_lvl = 6, .rfagc_top = 0x37 },
+	.qam_6    = { .if_freq = 4000, .agc_mode = 3, .std = 0,
+		      .if_lvl = 6, .rfagc_top = 0x37 },
+};
+
+static struct tda18271_config hauppauge_tda18271_config = {
+	.std_map = &hauppauge_tda18271_std_map,
+	.gate    = TDA18271_GATE_DIGITAL,
+	.output_opt = TDA18271_OUTPUT_LT_OFF,
+};
+
+/*
  * CX18_CARD_LEADTEK_DVR3100H
  */
 /* Information/confirmation of proper config values provided by Terry Wu */
@@ -137,7 +165,7 @@ static int yuan_mpc718_mt352_init(struct
 {
 	struct cx18_dvb *dvb = container_of(fe->dvb,
 					    struct cx18_dvb, dvb_adapter);
-	struct cx18_stream *stream = container_of(dvb, struct cx18_stream, dvb);
+	struct cx18_stream *stream = dvb->stream;
 	const struct firmware *fw = NULL;
 	int ret;
 	int i;
@@ -203,6 +231,14 @@ static struct zl10353_config yuan_mpc718
 	.disable_i2c_gate_ctrl = 1,         /* Disable the I2C gate */
 };
 
+static struct zl10353_config gotview_dvd3_zl10353_demod = {
+	.demod_address         = 0x1e >> 1, /* Datasheet suggested straps */
+	.if2                   = 45600,     /* 4.560 MHz IF from the XC3028 */
+	.parallel_ts           = 1,         /* Not a serial TS */
+	.no_tuner              = 1,         /* XC3028 is not behind the gate */
+	.disable_i2c_gate_ctrl = 1,         /* Disable the I2C gate */
+};
+
 static int dvb_register(struct cx18_stream *stream);
 
 /* Kernel DVB framework calls this when the feed needs to start.
@@ -236,6 +272,7 @@ static int cx18_dvb_start_feed(struct dv
 	switch (cx->card->type) {
 	case CX18_CARD_HVR_1600_ESMT:
 	case CX18_CARD_HVR_1600_SAMSUNG:
+	case CX18_CARD_HVR_1600_S5H1411:
 		v = cx18_read_reg(cx, CX18_REG_DMUX_NUM_PORT_0_CONTROL);
 		v |= 0x00400000; /* Serial Mode */
 		v |= 0x00002000; /* Data Length - Byte */
@@ -247,6 +284,7 @@ static int cx18_dvb_start_feed(struct dv
 
 	case CX18_CARD_LEADTEK_DVR3100H:
 	case CX18_CARD_YUAN_MPC718:
+	case CX18_CARD_GOTVIEW_PCI_DVD3:
 	default:
 		/* Assumption - Parallel transport - Signalling
 		 * undefined or default.
@@ -257,22 +295,22 @@ static int cx18_dvb_start_feed(struct dv
 	if (!demux->dmx.frontend)
 		return -EINVAL;
 
-	mutex_lock(&stream->dvb.feedlock);
-	if (stream->dvb.feeding++ == 0) {
+	mutex_lock(&stream->dvb->feedlock);
+	if (stream->dvb->feeding++ == 0) {
 		CX18_DEBUG_INFO("Starting Transport DMA\n");
 		mutex_lock(&cx->serialize_lock);
 		set_bit(CX18_F_S_STREAMING, &stream->s_flags);
 		ret = cx18_start_v4l2_encode_stream(stream);
 		if (ret < 0) {
 			CX18_DEBUG_INFO("Failed to start Transport DMA\n");
-			stream->dvb.feeding--;
-			if (stream->dvb.feeding == 0)
+			stream->dvb->feeding--;
+			if (stream->dvb->feeding == 0)
 				clear_bit(CX18_F_S_STREAMING, &stream->s_flags);
 		}
 		mutex_unlock(&cx->serialize_lock);
 	} else
 		ret = 0;
-	mutex_unlock(&stream->dvb.feedlock);
+	mutex_unlock(&stream->dvb->feedlock);
 
 	return ret;
 }
@@ -290,15 +328,15 @@ static int cx18_dvb_stop_feed(struct dvb
 		CX18_DEBUG_INFO("Stop feed: pid = 0x%x index = %d\n",
 				feed->pid, feed->index);
 
-		mutex_lock(&stream->dvb.feedlock);
-		if (--stream->dvb.feeding == 0) {
+		mutex_lock(&stream->dvb->feedlock);
+		if (--stream->dvb->feeding == 0) {
 			CX18_DEBUG_INFO("Stopping Transport DMA\n");
 			mutex_lock(&cx->serialize_lock);
 			ret = cx18_stop_v4l2_encode_stream(stream, 0);
 			mutex_unlock(&cx->serialize_lock);
 		} else
 			ret = 0;
-		mutex_unlock(&stream->dvb.feedlock);
+		mutex_unlock(&stream->dvb->feedlock);
 	}
 
 	return ret;
@@ -307,7 +345,7 @@ static int cx18_dvb_stop_feed(struct dvb
 int cx18_dvb_register(struct cx18_stream *stream)
 {
 	struct cx18 *cx = stream->cx;
-	struct cx18_dvb *dvb = &stream->dvb;
+	struct cx18_dvb *dvb = stream->dvb;
 	struct dvb_adapter *dvb_adapter;
 	struct dvb_demux *dvbdemux;
 	struct dmx_demux *dmx;
@@ -316,6 +354,9 @@ int cx18_dvb_register(struct cx18_stream
 	if (!dvb)
 		return -EINVAL;
 
+	dvb->enabled = 0;
+	dvb->stream = stream;
+
 	ret = dvb_register_adapter(&dvb->dvb_adapter,
 			CX18_DRIVER_NAME,
 			THIS_MODULE, &cx->pci_dev->dev, adapter_nr);
@@ -369,7 +410,7 @@ int cx18_dvb_register(struct cx18_stream
 
 	CX18_INFO("DVB Frontend registered\n");
 	CX18_INFO("Registered DVB adapter%d for %s (%d x %d.%02d kB)\n",
-		  stream->dvb.dvb_adapter.num, stream->name,
+		  stream->dvb->dvb_adapter.num, stream->name,
 		  stream->buffers, stream->buf_size/1024,
 		  (stream->buf_size * 100 / 1024) % 100);
 
@@ -396,13 +437,16 @@ err_out:
 void cx18_dvb_unregister(struct cx18_stream *stream)
 {
 	struct cx18 *cx = stream->cx;
-	struct cx18_dvb *dvb = &stream->dvb;
+	struct cx18_dvb *dvb = stream->dvb;
 	struct dvb_adapter *dvb_adapter;
 	struct dvb_demux *dvbdemux;
 	struct dmx_demux *dmx;
 
 	CX18_INFO("unregister DVB\n");
 
+	if (dvb == NULL || !dvb->enabled)
+		return;
+
 	dvb_adapter = &dvb->dvb_adapter;
 	dvbdemux = &dvb->demux;
 	dmx = &dvbdemux->dmx;
@@ -423,7 +467,7 @@ void cx18_dvb_unregister(struct cx18_str
  */
 static int dvb_register(struct cx18_stream *stream)
 {
-	struct cx18_dvb *dvb = &stream->dvb;
+	struct cx18_dvb *dvb = stream->dvb;
 	struct cx18 *cx = stream->cx;
 	int ret = 0;
 
@@ -440,6 +484,15 @@ static int dvb_register(struct cx18_stre
 			ret = 0;
 		}
 		break;
+	case CX18_CARD_HVR_1600_S5H1411:
+		dvb->fe = dvb_attach(s5h1411_attach,
+				     &hcw_s5h1411_config,
+				     &cx->i2c_adap[0]);
+		if (dvb->fe != NULL)
+			dvb_attach(tda18271_attach, dvb->fe,
+				   0x60, &cx->i2c_adap[0],
+				   &hauppauge_tda18271_config);
+		break;
 	case CX18_CARD_LEADTEK_DVR3100H:
 		dvb->fe = dvb_attach(zl10353_attach,
 				     &leadtek_dvr3100h_demod,
@@ -478,6 +531,29 @@ static int dvb_register(struct cx18_stre
 					     &cx->i2c_adap[1]);
 		if (dvb->fe != NULL) {
 			struct dvb_frontend *fe;
+			struct xc2028_config cfg = {
+				.i2c_adap = &cx->i2c_adap[1],
+				.i2c_addr = 0xc2 >> 1,
+				.ctrl = NULL,
+			};
+			static struct xc2028_ctrl ctrl = {
+				.fname   = "/*(DEBLOBBED)*/",
+				.max_len = 64,
+				.demod   = XC3028_FE_ZARLINK456,
+				.type    = XC2028_AUTO,
+			};
+
+			fe = dvb_attach(xc2028_attach, dvb->fe, &cfg);
+			if (fe != NULL && fe->ops.tuner_ops.set_config != NULL)
+				fe->ops.tuner_ops.set_config(fe, &ctrl);
+		}
+		break;
+	case CX18_CARD_GOTVIEW_PCI_DVD3:
+			dvb->fe = dvb_attach(zl10353_attach,
+					     &gotview_dvd3_zl10353_demod,
+					     &cx->i2c_adap[1]);
+		if (dvb->fe != NULL) {
+			struct dvb_frontend *fe;
 			struct xc2028_config cfg = {
 				.i2c_adap = &cx->i2c_adap[1],
 				.i2c_addr = 0xc2 >> 1,
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/cx18/cx18-i2c.c linux-libre-2.6.38-gnu1/drivers/media/video/cx18/cx18-i2c.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/cx18/cx18-i2c.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/cx18/cx18-i2c.c	2011-03-14 21:20:32.000000000 -0400
@@ -98,7 +98,7 @@ static int cx18_i2c_new_ir(struct cx18 *
 	case CX18_HW_Z8F0811_IR_RX_HAUP:
 		init_data->ir_codes = RC_MAP_HAUPPAUGE_NEW;
 		init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR;
-		init_data->type = IR_TYPE_RC5;
+		init_data->type = RC_TYPE_RC5;
 		init_data->name = cx->card_name;
 		info.platform_data = init_data;
 		break;
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/cx18/cx18-mailbox.c linux-libre-2.6.38-gnu1/drivers/media/video/cx18/cx18-mailbox.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/cx18/cx18-mailbox.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/cx18/cx18-mailbox.c	2011-03-14 21:20:32.000000000 -0400
@@ -136,7 +136,7 @@ static void cx18_mdl_send_to_dvb(struct
 {
 	struct cx18_buffer *buf;
 
-	if (!s->dvb.enabled || mdl->bytesused == 0)
+	if (s->dvb == NULL || !s->dvb->enabled || mdl->bytesused == 0)
 		return;
 
 	/* We ignore mdl and buf readpos accounting here - it doesn't matter */
@@ -146,7 +146,7 @@ static void cx18_mdl_send_to_dvb(struct
 		buf = list_first_entry(&mdl->buf_list, struct cx18_buffer,
 				       list);
 		if (buf->bytesused)
-			dvb_dmx_swfilter(&s->dvb.demux,
+			dvb_dmx_swfilter(&s->dvb->demux,
 					 buf->buf, buf->bytesused);
 		return;
 	}
@@ -154,7 +154,7 @@ static void cx18_mdl_send_to_dvb(struct
 	list_for_each_entry(buf, &mdl->buf_list, list) {
 		if (buf->bytesused == 0)
 			break;
-		dvb_dmx_swfilter(&s->dvb.demux, buf->buf, buf->bytesused);
+		dvb_dmx_swfilter(&s->dvb->demux, buf->buf, buf->bytesused);
 	}
 }
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/cx18/cx18-streams.c linux-libre-2.6.38-gnu1/drivers/media/video/cx18/cx18-streams.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/cx18/cx18-streams.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/cx18/cx18-streams.c	2011-03-14 21:20:32.000000000 -0400
@@ -107,6 +107,7 @@ static void cx18_stream_init(struct cx18
 	s->video_dev = video_dev;
 
 	/* initialize cx18_stream fields */
+	s->dvb = NULL;
 	s->cx = cx;
 	s->type = type;
 	s->name = cx18_stream_info[type].name;
@@ -140,10 +141,15 @@ static int cx18_prep_dev(struct cx18 *cx
 	int num_offset = cx18_stream_info[type].num_offset;
 	int num = cx->instance + cx18_first_minor + num_offset;
 
-	/* These four fields are always initialized. If video_dev == NULL, then
-	   this stream is not in use. In that case no other fields but these
-	   four can be used. */
+	/*
+	 * These five fields are always initialized.
+	 * For analog capture related streams, if video_dev == NULL then the
+	 * stream is not in use.
+	 * For the TS stream, if dvb == NULL then the stream is not in use.
+	 * In those cases no other fields but these four can be used.
+	 */
 	s->video_dev = NULL;
+	s->dvb = NULL;
 	s->cx = cx;
 	s->type = type;
 	s->name = cx18_stream_info[type].name;
@@ -167,6 +173,21 @@ static int cx18_prep_dev(struct cx18 *cx
 
 	cx18_stream_init(cx, type);
 
+	/* Allocate the cx18_dvb struct only for the TS on cards with DTV */
+	if (type == CX18_ENC_STREAM_TYPE_TS) {
+		if (cx->card->hw_all & CX18_HW_DVB) {
+			s->dvb = kzalloc(sizeof(struct cx18_dvb), GFP_KERNEL);
+			if (s->dvb == NULL) {
+				CX18_ERR("Couldn't allocate cx18_dvb structure"
+					 " for %s\n", s->name);
+				return -ENOMEM;
+			}
+		} else {
+			/* Don't need buffers for the TS, if there is no DVB */
+			s->buffers = 0;
+		}
+	}
+
 	if (num_offset == -1)
 		return 0;
 
@@ -222,13 +243,7 @@ static int cx18_reg_dev(struct cx18 *cx,
 	const char *name;
 	int num, ret;
 
-	/* TODO: Shouldn't this be a VFL_TYPE_TRANSPORT or something?
-	 * We need a VFL_TYPE_TS defined.
-	 */
-	if (strcmp("TS", s->name) == 0) {
-		/* just return if no DVB is supported */
-		if ((cx->card->hw_all & CX18_HW_DVB) == 0)
-			return 0;
+	if (type == CX18_ENC_STREAM_TYPE_TS && s->dvb != NULL) {
 		ret = cx18_dvb_register(s);
 		if (ret < 0) {
 			CX18_ERR("DVB failed to register\n");
@@ -320,11 +335,13 @@ void cx18_streams_cleanup(struct cx18 *c
 	/* Teardown all streams */
 	for (type = 0; type < CX18_MAX_STREAMS; type++) {
 
-		/* No struct video_device, but can have buffers allocated */
+		/* The TS has a cx18_dvb structure, not a video_device */
 		if (type == CX18_ENC_STREAM_TYPE_TS) {
-			if (cx->streams[type].dvb.enabled) {
-				cx18_dvb_unregister(&cx->streams[type]);
-				cx->streams[type].dvb.enabled = false;
+			if (cx->streams[type].dvb != NULL) {
+				if (unregister)
+					cx18_dvb_unregister(&cx->streams[type]);
+				kfree(cx->streams[type].dvb);
+				cx->streams[type].dvb = NULL;
 				cx18_stream_free(&cx->streams[type]);
 			}
 			continue;
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/cx18/cx18-streams.h linux-libre-2.6.38-gnu1/drivers/media/video/cx18/cx18-streams.h
--- linux-libre-2.6.37-gnu1/drivers/media/video/cx18/cx18-streams.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/cx18/cx18-streams.h	2011-03-14 21:20:32.000000000 -0400
@@ -33,7 +33,8 @@ void cx18_stream_rotate_idx_mdls(struct
 
 static inline bool cx18_stream_enabled(struct cx18_stream *s)
 {
-	return s->video_dev || s->dvb.enabled ||
+	return s->video_dev ||
+	       (s->dvb && s->dvb->enabled) ||
 	       (s->type == CX18_ENC_STREAM_TYPE_IDX &&
 		s->cx->stream_buffers[CX18_ENC_STREAM_TYPE_IDX] != 0);
 }
@@ -41,8 +42,7 @@ static inline bool cx18_stream_enabled(s
 /* Related to submission of mdls to firmware */
 static inline void cx18_stream_load_fw_queue(struct cx18_stream *s)
 {
-	struct cx18 *cx = s->cx;
-	queue_work(cx->out_work_queue, &s->out_work_order);
+	schedule_work(&s->out_work_order);
 }
 
 static inline void cx18_stream_put_mdl_fw(struct cx18_stream *s,
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/cx18/cx23418.h linux-libre-2.6.38-gnu1/drivers/media/video/cx18/cx23418.h
--- linux-libre-2.6.37-gnu1/drivers/media/video/cx18/cx23418.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/cx18/cx23418.h	2011-03-14 21:20:32.000000000 -0400
@@ -177,7 +177,7 @@
    IN[0] - Task handle.
    IN[1] - luma type: 0 = disable, 1 = 1D horizontal only, 2 = 1D vertical only,
 		      3 = 2D H/V separable, 4 = 2D symmetric non-separable
-   IN[2] - chroma type: 0 - diable, 1 = 1D horizontal
+   IN[2] - chroma type: 0 - disable, 1 = 1D horizontal
    ReturnCode - One of the ERR_CAPTURE_... */
 #define CX18_CPU_SET_SPATIAL_FILTER_TYPE     	(CPU_CMD_MASK_CAPTURE | 0x000C)
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/cx18/Kconfig linux-libre-2.6.38-gnu1/drivers/media/video/cx18/Kconfig
--- linux-libre-2.6.37-gnu1/drivers/media/video/cx18/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/cx18/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -1,9 +1,8 @@
 config VIDEO_CX18
 	tristate "Conexant cx23418 MPEG encoder support"
 	depends on VIDEO_V4L2 && DVB_CORE && PCI && I2C && EXPERIMENTAL
-	depends on INPUT	# due to VIDEO_IR
 	select I2C_ALGOBIT
-	depends on VIDEO_IR
+	depends on RC_CORE
 	select VIDEO_TUNER
 	select VIDEO_TVEEPROM
 	select VIDEO_CX2341X
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/cx231xx/cx231xx-417.c linux-libre-2.6.38-gnu1/drivers/media/video/cx231xx/cx231xx-417.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/cx231xx/cx231xx-417.c	2013-05-03 03:56:58.000000000 -0400
+++ linux-libre-2.6.38-gnu1/drivers/media/video/cx231xx/cx231xx-417.c	2013-05-03 01:56:43.000000000 -0400
@@ -940,14 +940,14 @@ static int cx231xx_load_firmware(struct
 	u16 _buffer_size = 4096;
 	u8 *p_buffer;
 
-	p_current_fw = (u32 *)vmalloc(1884180*4);
+	p_current_fw = vmalloc(1884180 * 4);
 	p_fw = p_current_fw;
 	if (p_current_fw == 0) {
 		dprintk(2, "FAIL!!!\n");
 		return -1;
 	}
 
-	p_buffer = (u8 *)vmalloc(4096);
+	p_buffer = vmalloc(4096);
 	if (p_buffer == 0) {
 		dprintk(2, "FAIL!!!\n");
 		return -1;
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/cx231xx/cx231xx-avcore.c linux-libre-2.6.38-gnu1/drivers/media/video/cx231xx/cx231xx-avcore.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/cx231xx/cx231xx-avcore.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/cx231xx/cx231xx-avcore.c	2011-03-14 21:20:32.000000000 -0400
@@ -274,7 +274,7 @@ int cx231xx_afe_set_input_mux(struct cx2
 
 	if (ch1_setting != 0) {
 		status = afe_read_byte(dev, ADC_INPUT_CH1, &value);
-		value &= (!INPUT_SEL_MASK);
+		value &= ~INPUT_SEL_MASK;
 		value |= (ch1_setting - 1) << 4;
 		value &= 0xff;
 		status = afe_write_byte(dev, ADC_INPUT_CH1, value);
@@ -282,7 +282,7 @@ int cx231xx_afe_set_input_mux(struct cx2
 
 	if (ch2_setting != 0) {
 		status = afe_read_byte(dev, ADC_INPUT_CH2, &value);
-		value &= (!INPUT_SEL_MASK);
+		value &= ~INPUT_SEL_MASK;
 		value |= (ch2_setting - 1) << 4;
 		value &= 0xff;
 		status = afe_write_byte(dev, ADC_INPUT_CH2, value);
@@ -292,7 +292,7 @@ int cx231xx_afe_set_input_mux(struct cx2
 	   7 less than the input number */
 	if (ch3_setting != 0) {
 		status = afe_read_byte(dev, ADC_INPUT_CH3, &value);
-		value &= (!INPUT_SEL_MASK);
+		value &= ~INPUT_SEL_MASK;
 		value |= (ch3_setting - 1) << 4;
 		value &= 0xff;
 		status = afe_write_byte(dev, ADC_INPUT_CH3, value);
@@ -354,6 +354,7 @@ int cx231xx_afe_update_power_control(str
 	case CX231XX_BOARD_CNXT_VIDEO_GRABBER:
 	case CX231XX_BOARD_HAUPPAUGE_EXETER:
 	case CX231XX_BOARD_HAUPPAUGE_USBLIVE2:
+	case CX231XX_BOARD_PV_PLAYTV_USB_HYBRID:
 		if (avmode == POLARIS_AVMODE_ANALOGT_TV) {
 			while (afe_power_status != (FLD_PWRDN_TUNING_BIAS |
 						FLD_PWRDN_ENABLE_PLL)) {
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/cx231xx/cx231xx-cards.c linux-libre-2.6.38-gnu1/drivers/media/video/cx231xx/cx231xx-cards.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/cx231xx/cx231xx-cards.c	2013-05-03 03:54:59.000000000 -0400
+++ linux-libre-2.6.38-gnu1/drivers/media/video/cx231xx/cx231xx-cards.c	2013-05-03 01:54:24.000000000 -0400
@@ -34,6 +34,7 @@
 #include <media/cx25840.h>
 #include "dvb-usb-ids.h"
 #include "xc5000.h"
+#include "tda18271.h"
 
 #include "cx231xx.h"
 
@@ -395,6 +396,45 @@ struct cx231xx_board cx231xx_boards[] =
 			.gpio = 0,
 		} },
 	},
+	[CX231XX_BOARD_PV_PLAYTV_USB_HYBRID] = {
+		.name = "Pixelview PlayTV USB Hybrid",
+		.tuner_type = TUNER_NXP_TDA18271,
+		.tuner_addr = 0x60,
+		.decoder = CX231XX_AVDECODER,
+		.output_mode = OUT_MODE_VIP11,
+		.demod_xfer_mode = 0,
+		.ctl_pin_status_mask = 0xFFFFFFC4,
+		.agc_analog_digital_select_gpio = 0x00,	/* According with PV cxPolaris.inf file */
+		.tuner_sif_gpio = -1,
+		.tuner_scl_gpio = -1,
+		.tuner_sda_gpio = -1,
+		.gpio_pin_status_mask = 0x4001000,
+		.tuner_i2c_master = 2,
+		.demod_i2c_master = 1,
+		.ir_i2c_master = 2,
+		.rc_map_name = RC_MAP_PIXELVIEW_002T,
+		.has_dvb = 1,
+		.demod_addr = 0x10,
+		.norm = V4L2_STD_PAL_M,
+		.input = {{
+			.type = CX231XX_VMUX_TELEVISION,
+			.vmux = CX231XX_VIN_3_1,
+			.amux = CX231XX_AMUX_VIDEO,
+			.gpio = 0,
+		}, {
+			.type = CX231XX_VMUX_COMPOSITE1,
+			.vmux = CX231XX_VIN_2_1,
+			.amux = CX231XX_AMUX_LINE_IN,
+			.gpio = 0,
+		}, {
+			.type = CX231XX_VMUX_SVIDEO,
+			.vmux = CX231XX_VIN_1_1 |
+				(CX231XX_VIN_1_2 << 8) |
+				CX25840_SVIDEO_ON,
+			.amux = CX231XX_AMUX_LINE_IN,
+			.gpio = 0,
+		} },
+	},
 };
 const unsigned int cx231xx_bcount = ARRAY_SIZE(cx231xx_boards);
 
@@ -402,8 +442,6 @@ const unsigned int cx231xx_bcount = ARRA
 struct usb_device_id cx231xx_id_table[] = {
 	{USB_DEVICE(0x0572, 0x5A3C),
 	 .driver_info = CX231XX_BOARD_UNKNOWN},
-	{USB_DEVICE_VER(USB_VID_PIXELVIEW, USB_PID_PIXELVIEW_SBTVD, 0x4000,0x4fff),
-	 .driver_info = CX231XX_BOARD_UNKNOWN},
 	{USB_DEVICE(0x0572, 0x58A2),
 	 .driver_info = CX231XX_BOARD_CNXT_CARRAERA},
 	{USB_DEVICE(0x0572, 0x58A1),
@@ -424,6 +462,8 @@ struct usb_device_id cx231xx_id_table[]
 	 .driver_info = CX231XX_BOARD_HAUPPAUGE_EXETER},
 	{USB_DEVICE(0x2040, 0xc200),
 	 .driver_info = CX231XX_BOARD_HAUPPAUGE_USBLIVE2},
+	{USB_DEVICE_VER(USB_VID_PIXELVIEW, USB_PID_PIXELVIEW_SBTVD, 0x4000, 0x4001),
+	 .driver_info = CX231XX_BOARD_PV_PLAYTV_USB_HYBRID},
 	{},
 };
 
@@ -453,6 +493,16 @@ int cx231xx_tuner_callback(void *ptr, in
 					       1);
 			msleep(10);
 		}
+	} else if (dev->tuner_type == TUNER_NXP_TDA18271) {
+		switch (command) {
+		case TDA18271_CALLBACK_CMD_AGC_ENABLE:
+			if (dev->model == CX231XX_BOARD_PV_PLAYTV_USB_HYBRID)
+				rc = cx231xx_set_agc_analog_digital_mux_select(dev, arg);
+			break;
+		default:
+			rc = -EINVAL;
+			break;
+		}
 	}
 	return rc;
 }
@@ -615,8 +665,11 @@ void cx231xx_release_resources(struct cx
 
 	cx231xx_remove_from_devlist(dev);
 
+	/* Release I2C buses */
 	cx231xx_dev_uninit(dev);
 
+	cx231xx_ir_exit(dev);
+
 	usb_put_dev(dev->udev);
 
 	/* Mark device as unused */
@@ -731,16 +784,14 @@ static int cx231xx_init_dev(struct cx231
 	retval = cx231xx_register_analog_devices(dev);
 	if (retval < 0) {
 		cx231xx_release_resources(dev);
-		goto fail_reg_devices;
+		return retval;
 	}
 
+	cx231xx_ir_init(dev);
+
 	cx231xx_init_extension(dev);
 
 	return 0;
-
-fail_reg_devices:
-	mutex_unlock(&dev->lock);
-	return retval;
 }
 
 #if defined(CONFIG_MODULES) && defined(MODULE)
@@ -762,8 +813,14 @@ static void request_modules(struct cx231
 	INIT_WORK(&dev->request_module_wk, request_module_async);
 	schedule_work(&dev->request_module_wk);
 }
+
+static void flush_request_modules(struct cx231xx *dev)
+{
+	flush_work_sync(&dev->request_module_wk);
+}
 #else
 #define request_modules(dev)
+#define flush_request_modules(dev)
 #endif /* CONFIG_MODULES */
 
 /*
@@ -1096,6 +1153,8 @@ static void cx231xx_usb_disconnect(struc
 	if (!dev->udev)
 		return;
 
+	flush_request_modules(dev);
+
 	/* delete v4l2 device */
 	v4l2_device_unregister(&dev->v4l2_dev);
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/cx231xx/cx231xx-core.c linux-libre-2.6.38-gnu1/drivers/media/video/cx231xx/cx231xx-core.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/cx231xx/cx231xx-core.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/cx231xx/cx231xx-core.c	2011-03-14 21:20:32.000000000 -0400
@@ -740,6 +740,7 @@ int cx231xx_set_mode(struct cx231xx *dev
 		case CX231XX_BOARD_CNXT_RDE_253S:
 		case CX231XX_BOARD_CNXT_RDU_253S:
 		case CX231XX_BOARD_HAUPPAUGE_EXETER:
+		case CX231XX_BOARD_PV_PLAYTV_USB_HYBRID:
 		errCode = cx231xx_set_agc_analog_digital_mux_select(dev, 0);
 			break;
 		default:
@@ -1288,7 +1289,7 @@ int cx231xx_dev_init(struct cx231xx *dev
 	/* Internal Master 3 Bus */
 	dev->i2c_bus[2].nr = 2;
 	dev->i2c_bus[2].dev = dev;
-	dev->i2c_bus[2].i2c_period = I2C_SPEED_400K;	/* 400kHz */
+	dev->i2c_bus[2].i2c_period = I2C_SPEED_100K;	/* 100kHz */
 	dev->i2c_bus[2].i2c_nostop = 0;
 	dev->i2c_bus[2].i2c_reserve = 0;
 
@@ -1381,6 +1382,7 @@ int cx231xx_dev_init(struct cx231xx *dev
 	case CX231XX_BOARD_CNXT_RDE_253S:
 	case CX231XX_BOARD_CNXT_RDU_253S:
 	case CX231XX_BOARD_HAUPPAUGE_EXETER:
+	case CX231XX_BOARD_PV_PLAYTV_USB_HYBRID:
 	errCode = cx231xx_set_agc_analog_digital_mux_select(dev, 0);
 		break;
 	default:
@@ -1513,7 +1515,7 @@ int cx231xx_read_i2c_master(struct cx231
 
 	if (saddr_len == 0)
 		saddr = 0;
-	else if (saddr_len == 0)
+	else if (saddr_len == 1)
 		saddr &= 0xff;
 
 	/* prepare xfer_data struct */
@@ -1564,7 +1566,7 @@ int cx231xx_write_i2c_master(struct cx23
 
 	if (saddr_len == 0)
 		saddr = 0;
-	else if (saddr_len == 0)
+	else if (saddr_len == 1)
 		saddr &= 0xff;
 
 	/* prepare xfer_data struct */
@@ -1598,7 +1600,7 @@ int cx231xx_read_i2c_data(struct cx231xx
 
 	if (saddr_len == 0)
 		saddr = 0;
-	else if (saddr_len == 0)
+	else if (saddr_len == 1)
 		saddr &= 0xff;
 
 	/* prepare xfer_data struct */
@@ -1639,7 +1641,7 @@ int cx231xx_write_i2c_data(struct cx231x
 
 	if (saddr_len == 0)
 		saddr = 0;
-	else if (saddr_len == 0)
+	else if (saddr_len == 1)
 		saddr &= 0xff;
 
 	/* prepare xfer_data struct */
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/cx231xx/cx231xx-dvb.c linux-libre-2.6.38-gnu1/drivers/media/video/cx231xx/cx231xx-dvb.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/cx231xx/cx231xx-dvb.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/cx231xx/cx231xx-dvb.c	2011-03-14 21:20:32.000000000 -0400
@@ -28,11 +28,11 @@
 #include <media/videobuf-vmalloc.h>
 
 #include "xc5000.h"
-#include "dvb_dummy_fe.h"
 #include "s5h1432.h"
 #include "tda18271.h"
 #include "s5h1411.h"
 #include "lgdt3305.h"
+#include "mb86a20s.h"
 
 MODULE_DESCRIPTION("driver for cx231xx based DVB cards");
 MODULE_AUTHOR("Srinivasa Deevi <srinivasa.deevi@conexant.com>");
@@ -88,6 +88,11 @@ static struct tda18271_std_map cnxt_rde2
 		      .if_lvl = 1, .rfagc_top = 0x37, },
 };
 
+static struct tda18271_std_map mb86a20s_tda18271_config = {
+	.dvbt_6   = { .if_freq = 3300, .agc_mode = 3, .std = 4,
+		      .if_lvl = 7, .rfagc_top = 0x37, },
+};
+
 static struct tda18271_config cnxt_rde253s_tunerconfig = {
 	.std_map = &cnxt_rde253s_tda18271_std_map,
 	.gate    = TDA18271_GATE_ANALOG,
@@ -135,6 +140,17 @@ static struct tda18271_config hcw_tda182
 	.gate    = TDA18271_GATE_DIGITAL,
 };
 
+static const struct mb86a20s_config pv_mb86a20s_config = {
+	.demod_address = 0x10,
+	.is_serial = true,
+};
+
+static struct tda18271_config pv_tda18271_config = {
+	.std_map = &mb86a20s_tda18271_config,
+	.gate    = TDA18271_GATE_DIGITAL,
+	.small_i2c = TDA18271_03_BYTE_CHUNK_INIT,
+};
+
 static inline void print_err_status(struct cx231xx *dev, int packet, int status)
 {
 	char *errmsg = "Unknown";
@@ -602,7 +618,7 @@ static int dvb_init(struct cx231xx *dev)
 
 		if (dev->dvb->frontend == NULL) {
 			printk(DRIVER_NAME
-			       ": Failed to attach dummy front end\n");
+			       ": Failed to attach s5h1411 front end\n");
 			result = -EINVAL;
 			goto out_free;
 		}
@@ -648,7 +664,7 @@ static int dvb_init(struct cx231xx *dev)
 
 		if (dev->dvb->frontend == NULL) {
 			printk(DRIVER_NAME
-			       ": Failed to attach dummy front end\n");
+			       ": Failed to attach s5h1411 front end\n");
 			result = -EINVAL;
 			goto out_free;
 		}
@@ -687,6 +703,29 @@ static int dvb_init(struct cx231xx *dev)
 			   &hcw_tda18271_config);
 		break;
 
+	case CX231XX_BOARD_PV_PLAYTV_USB_HYBRID:
+
+		printk(KERN_INFO "%s: looking for demod on i2c bus: %d\n",
+		       __func__, i2c_adapter_id(&dev->i2c_bus[dev->board.tuner_i2c_master].i2c_adap));
+
+		dev->dvb->frontend = dvb_attach(mb86a20s_attach,
+						&pv_mb86a20s_config,
+						&dev->i2c_bus[dev->board.demod_i2c_master].i2c_adap);
+
+		if (dev->dvb->frontend == NULL) {
+			printk(DRIVER_NAME
+			       ": Failed to attach mb86a20s demod\n");
+			result = -EINVAL;
+			goto out_free;
+		}
+
+		/* define general-purpose callback pointer */
+		dvb->frontend->callback = cx231xx_tuner_callback;
+
+		dvb_attach(tda18271_attach, dev->dvb->frontend,
+			   0x60, &dev->i2c_bus[dev->board.tuner_i2c_master].i2c_adap,
+			   &pv_tda18271_config);
+		break;
 
 	default:
 		printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card"
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/cx231xx/cx231xx.h linux-libre-2.6.38-gnu1/drivers/media/video/cx231xx/cx231xx.h
--- linux-libre-2.6.37-gnu1/drivers/media/video/cx231xx/cx231xx.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/cx231xx/cx231xx.h	2011-03-14 21:20:32.000000000 -0400
@@ -34,7 +34,8 @@
 
 #include <media/videobuf-vmalloc.h>
 #include <media/v4l2-device.h>
-#include <media/ir-core.h>
+#include <media/rc-core.h>
+#include <media/ir-kbd-i2c.h>
 #include <media/videobuf-dvb.h>
 
 #include "cx231xx-reg.h"
@@ -62,6 +63,7 @@
 #define CX231XX_BOARD_CNXT_RDU_250	7
 #define CX231XX_BOARD_HAUPPAUGE_EXETER  8
 #define CX231XX_BOARD_HAUPPAUGE_USBLIVE2 9
+#define CX231XX_BOARD_PV_PLAYTV_USB_HYBRID 10
 
 /* Limits minimum and default number of buffers */
 #define CX231XX_MIN_BUF                 4
@@ -344,6 +346,10 @@ struct cx231xx_board {
 	/* i2c masters */
 	u8 tuner_i2c_master;
 	u8 demod_i2c_master;
+	u8 ir_i2c_master;
+
+	/* for devices with I2C chips for IR */
+	char *rc_map_name;
 
 	unsigned int max_range_640_480:1;
 	unsigned int has_dvb:1;
@@ -356,7 +362,7 @@ struct cx231xx_board {
 
 	struct cx231xx_input input[MAX_CX231XX_INPUT];
 	struct cx231xx_input radio;
-	struct ir_scancode_table *ir_codes;
+	struct rc_map *ir_codes;
 };
 
 /* device states */
@@ -605,6 +611,9 @@ struct cx231xx {
 
 	struct cx231xx_board board;
 
+	/* For I2C IR support */
+	struct IR_i2c_init_data    init_data;
+
 	unsigned int stream_on:1;	/* Locks streams */
 	unsigned int vbi_stream_on:1;	/* Locks streams for VBI */
 	unsigned int has_audio_class:1;
@@ -616,8 +625,6 @@ struct cx231xx {
 	struct v4l2_subdev *sd_cx25840;
 	struct v4l2_subdev *sd_tuner;
 
-	struct cx231xx_IR *ir;
-
 	struct work_struct wq_trigger;		/* Trigger to start/stop audio for alsa module */
 	atomic_t	   stream_started;	/* stream should be running if true */
 
@@ -954,6 +961,17 @@ int cx231xx_tuner_callback(void *ptr, in
 extern int cx231xx_417_register(struct cx231xx *dev);
 extern void cx231xx_417_unregister(struct cx231xx *dev);
 
+/* cx23885-input.c                                             */
+
+#if defined(CONFIG_VIDEO_CX231XX_RC)
+int cx231xx_ir_init(struct cx231xx *dev);
+void cx231xx_ir_exit(struct cx231xx *dev);
+#else
+#define cx231xx_ir_init(dev)	(0)
+#define cx231xx_ir_exit(dev)	(0)
+#endif
+
+
 /* printk macros */
 
 #define cx231xx_err(fmt, arg...) do {\
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/cx231xx/cx231xx-input.c linux-libre-2.6.38-gnu1/drivers/media/video/cx231xx/cx231xx-input.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/cx231xx/cx231xx-input.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/cx231xx/cx231xx-input.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,112 @@
+/*
+ *   cx231xx IR glue driver
+ *
+ *   Copyright (C) 2010 Mauro Carvalho Chehab <mchehab@redhat.com>
+ *
+ *   Polaris (cx231xx) has its support for IR's with a design close to MCE.
+ *   however, a few designs are using an external I2C chip for IR, instead
+ *   of using the one provided by the chip.
+ *   This driver provides support for those extra 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 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.
+ */
+
+#include "cx231xx.h"
+#include <linux/usb.h>
+#include <linux/slab.h>
+
+#define MODULE_NAME "cx231xx-input"
+
+static int get_key_isdbt(struct IR_i2c *ir, u32 *ir_key,
+			 u32 *ir_raw)
+{
+	u8	cmd, scancode;
+
+	dev_dbg(&ir->rc->input_dev->dev, "%s\n", __func__);
+
+		/* poll IR chip */
+	if (1 != i2c_master_recv(ir->c, &cmd, 1))
+		return -EIO;
+
+	/* it seems that 0xFE indicates that a button is still hold
+	   down, while 0xff indicates that no button is hold
+	   down. 0xfe sequences are sometimes interrupted by 0xFF */
+
+	if (cmd == 0xff)
+		return 0;
+
+	scancode =
+		 ((cmd & 0x01) ? 0x80 : 0) |
+		 ((cmd & 0x02) ? 0x40 : 0) |
+		 ((cmd & 0x04) ? 0x20 : 0) |
+		 ((cmd & 0x08) ? 0x10 : 0) |
+		 ((cmd & 0x10) ? 0x08 : 0) |
+		 ((cmd & 0x20) ? 0x04 : 0) |
+		 ((cmd & 0x40) ? 0x02 : 0) |
+		 ((cmd & 0x80) ? 0x01 : 0);
+
+	dev_dbg(&ir->rc->input_dev->dev, "cmd %02x, scan = %02x\n",
+		cmd, scancode);
+
+	*ir_key = scancode;
+	*ir_raw = scancode;
+	return 1;
+}
+
+int cx231xx_ir_init(struct cx231xx *dev)
+{
+	struct i2c_board_info info;
+	u8 ir_i2c_bus;
+
+	dev_dbg(&dev->udev->dev, "%s\n", __func__);
+
+	/* Only initialize if a rc keycode map is defined */
+	if (!cx231xx_boards[dev->model].rc_map_name)
+		return -ENODEV;
+
+	request_module("ir-kbd-i2c");
+
+	memset(&info, 0, sizeof(struct i2c_board_info));
+	memset(&dev->init_data, 0, sizeof(dev->init_data));
+	dev->init_data.rc_dev = rc_allocate_device();
+	if (!dev->init_data.rc_dev)
+		return -ENOMEM;
+
+	dev->init_data.name = cx231xx_boards[dev->model].name;
+
+	strlcpy(info.type, "ir_video", I2C_NAME_SIZE);
+	info.platform_data = &dev->init_data;
+
+	/*
+	 * Board-dependent values
+	 *
+	 * For now, there's just one type of hardware design using
+	 * an i2c device.
+	 */
+	dev->init_data.get_key = get_key_isdbt;
+	dev->init_data.ir_codes = cx231xx_boards[dev->model].rc_map_name;
+	/* The i2c micro-controller only outputs the cmd part of NEC protocol */
+	dev->init_data.rc_dev->scanmask = 0xff;
+	dev->init_data.rc_dev->driver_name = "cx231xx";
+	dev->init_data.type = RC_TYPE_NEC;
+	info.addr = 0x30;
+
+	/* Load and bind ir-kbd-i2c */
+	ir_i2c_bus = cx231xx_boards[dev->model].ir_i2c_master;
+	dev_dbg(&dev->udev->dev, "Trying to bind ir at bus %d, addr 0x%02x\n",
+		ir_i2c_bus, info.addr);
+	i2c_new_device(&dev->i2c_bus[ir_i2c_bus].i2c_adap, &info);
+
+	return 0;
+}
+
+void cx231xx_ir_exit(struct cx231xx *dev)
+{
+}
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/cx231xx/cx231xx-video.c linux-libre-2.6.38-gnu1/drivers/media/video/cx231xx/cx231xx-video.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/cx231xx/cx231xx-video.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/cx231xx/cx231xx-video.c	2011-03-14 21:20:32.000000000 -0400
@@ -2044,15 +2044,6 @@ static int vidioc_dqbuf(struct file *fil
 	return videobuf_dqbuf(&fh->vb_vidq, b, file->f_flags & O_NONBLOCK);
 }
 
-#ifdef CONFIG_VIDEO_V4L1_COMPAT
-static int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf)
-{
-	struct cx231xx_fh *fh = priv;
-
-	return videobuf_cgmbuf(&fh->vb_vidq, mbuf, 8);
-}
-#endif
-
 /* ----------------------------------------------------------- */
 /* RADIO ESPECIFIC IOCTLS                                      */
 /* ----------------------------------------------------------- */
@@ -2507,9 +2498,6 @@ static const struct v4l2_ioctl_ops video
 	.vidioc_g_register             = vidioc_g_register,
 	.vidioc_s_register             = vidioc_s_register,
 #endif
-#ifdef CONFIG_VIDEO_V4L1_COMPAT
-	.vidiocgmbuf                   = vidiocgmbuf,
-#endif
 };
 
 static struct video_device cx231xx_vbi_template;
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/cx231xx/Kconfig linux-libre-2.6.38-gnu1/drivers/media/video/cx231xx/Kconfig
--- linux-libre-2.6.37-gnu1/drivers/media/video/cx231xx/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/cx231xx/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -1,9 +1,9 @@
 config VIDEO_CX231XX
 	tristate "Conexant cx231xx USB video capture support"
-	depends on VIDEO_DEV && I2C && INPUT
+	depends on VIDEO_DEV && I2C
 	select VIDEO_TUNER
 	select VIDEO_TVEEPROM
-	depends on VIDEO_IR
+	depends on RC_CORE
 	select VIDEOBUF_VMALLOC
 	select VIDEO_CX25840
 	select VIDEO_CX2341X
@@ -14,6 +14,19 @@ config VIDEO_CX231XX
 	  To compile this driver as a module, choose M here: the
 	  module will be called cx231xx
 
+config VIDEO_CX231XX_RC
+	bool "Conexant cx231xx Remote Controller additional support"
+	depends on RC_CORE
+	depends on VIDEO_CX231XX
+	default y
+	---help---
+	  cx231xx hardware has a builtin RX/TX support. However, a few
+	  designs opted to not use it, but, instead, some other hardware.
+	  This module enables the usage of those other hardware, like the
+	  ones used with ISDB-T boards.
+
+	  On most cases, all you need for IR is mceusb module.
+
 config VIDEO_CX231XX_ALSA
 	tristate "Conexant Cx231xx ALSA audio module"
 	depends on VIDEO_CX231XX && SND
@@ -30,6 +43,8 @@ config VIDEO_CX231XX_DVB
 	depends on VIDEO_CX231XX && DVB_CORE
 	select VIDEOBUF_DVB
 	select MEDIA_TUNER_XC5000 if !DVB_FE_CUSTOMISE
+	select MEDIA_TUNER_NXP18271 if !DVB_FE_CUSTOMISE
+	select DVB_MB86A20S if !DVB_FE_CUSTOMISE
 
 	---help---
 	  This adds support for DVB cards based on the
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/cx231xx/Makefile linux-libre-2.6.38-gnu1/drivers/media/video/cx231xx/Makefile
--- linux-libre-2.6.37-gnu1/drivers/media/video/cx231xx/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/cx231xx/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -1,5 +1,6 @@
-cx231xx-objs     := cx231xx-video.o cx231xx-i2c.o cx231xx-cards.o cx231xx-core.o \
-		    cx231xx-avcore.o cx231xx-417.o cx231xx-pcb-cfg.o cx231xx-vbi.o
+cx231xx-y += cx231xx-video.o cx231xx-i2c.o cx231xx-cards.o cx231xx-core.o
+cx231xx-y += cx231xx-avcore.o cx231xx-417.o cx231xx-pcb-cfg.o cx231xx-vbi.o
+cx231xx-$(CONFIG_VIDEO_CX231XX_RC) += cx231xx-input.o
 
 cx231xx-alsa-objs := cx231xx-audio.o
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/cx2341x.c linux-libre-2.6.38-gnu1/drivers/media/video/cx2341x.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/cx2341x.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/cx2341x.c	2011-03-14 21:20:32.000000000 -0400
@@ -853,9 +853,9 @@ int cx2341x_ctrl_query(const struct cx23
 }
 EXPORT_SYMBOL(cx2341x_ctrl_query);
 
-const char **cx2341x_ctrl_get_menu(const struct cx2341x_mpeg_params *p, u32 id)
+const char * const *cx2341x_ctrl_get_menu(const struct cx2341x_mpeg_params *p, u32 id)
 {
-	static const char *mpeg_stream_type_without_ts[] = {
+	static const char * const mpeg_stream_type_without_ts[] = {
 		"MPEG-2 Program Stream",
 		"",
 		"MPEG-1 System Stream",
@@ -952,7 +952,7 @@ int cx2341x_ext_ctrls(struct cx2341x_mpe
 	for (i = 0; i < ctrls->count; i++) {
 		struct v4l2_ext_control *ctrl = ctrls->controls + i;
 		struct v4l2_queryctrl qctrl;
-		const char **menu_items = NULL;
+		const char * const *menu_items = NULL;
 
 		qctrl.id = ctrl->id;
 		err = cx2341x_ctrl_query(params, &qctrl);
@@ -1135,7 +1135,7 @@ EXPORT_SYMBOL(cx2341x_update);
 
 static const char *cx2341x_menu_item(const struct cx2341x_mpeg_params *p, u32 id)
 {
-	const char **menu = cx2341x_ctrl_get_menu(p, id);
+	const char * const *menu = cx2341x_ctrl_get_menu(p, id);
 	struct v4l2_ext_control ctrl;
 
 	if (menu == NULL)
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/cx23885/cimax2.c linux-libre-2.6.38-gnu1/drivers/media/video/cx23885/cimax2.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/cx23885/cimax2.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/cx23885/cimax2.c	2011-03-14 21:20:32.000000000 -0400
@@ -368,7 +368,7 @@ static void netup_read_ci_status(struct
 				DVB_CA_EN50221_POLL_CAM_READY;
 		else
 			state->status = 0;
-	};
+	}
 }
 
 /* CI irq handler */
@@ -377,16 +377,24 @@ int netup_ci_slot_status(struct cx23885_
 	struct cx23885_tsport *port = NULL;
 	struct netup_ci_state *state = NULL;
 
-	if (pci_status & PCI_MSK_GPIO0)
-		port = &dev->ts1;
-	else if (pci_status & PCI_MSK_GPIO1)
-		port = &dev->ts2;
-	else /* who calls ? */
+	ci_dbg_print("%s:\n", __func__);
+
+	if (0 == (pci_status & (PCI_MSK_GPIO0 | PCI_MSK_GPIO1)))
 		return 0;
 
-	state = port->port_priv;
+	if (pci_status & PCI_MSK_GPIO0) {
+		port = &dev->ts1;
+		state = port->port_priv;
+		schedule_work(&state->work);
+		ci_dbg_print("%s: Wakeup CI0\n", __func__);
+	}
 
-	schedule_work(&state->work);
+	if (pci_status & PCI_MSK_GPIO1) {
+		port = &dev->ts2;
+		state = port->port_priv;
+		schedule_work(&state->work);
+		ci_dbg_print("%s: Wakeup CI1\n", __func__);
+	}
 
 	return 1;
 }
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/cx23885/cx23885-cards.c linux-libre-2.6.38-gnu1/drivers/media/video/cx23885/cx23885-cards.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/cx23885/cx23885-cards.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/cx23885/cx23885-cards.c	2011-03-14 21:20:32.000000000 -0400
@@ -309,6 +309,26 @@ struct cx23885_board cx23885_boards[] =
 				  CX25840_COMPONENT_ON,
 		} },
 	},
+	[CX23885_BOARD_GOTVIEW_X5_3D_HYBRID] = {
+		.name		= "GoTView X5 3D Hybrid",
+		.tuner_type	= TUNER_XC5000,
+		.tuner_addr	= 0x64,
+		.porta		= CX23885_ANALOG_VIDEO,
+		.portb		= CX23885_MPEG_DVB,
+		.input          = {{
+			.type   = CX23885_VMUX_TELEVISION,
+			.vmux   = CX25840_VIN2_CH1 |
+				  CX25840_VIN5_CH2,
+			.gpio0	= 0x02,
+		}, {
+			.type   = CX23885_VMUX_COMPOSITE1,
+			.vmux   = CX23885_VMUX_COMPOSITE1,
+		}, {
+			.type   = CX23885_VMUX_SVIDEO,
+			.vmux   = CX25840_SVIDEO_LUMA3 |
+				  CX25840_SVIDEO_CHROMA4,
+		} },
+	},
 };
 const unsigned int cx23885_bcount = ARRAY_SIZE(cx23885_boards);
 
@@ -496,6 +516,10 @@ struct cx23885_subid cx23885_subids[] =
 		.subvendor = 0x107d,
 		.subdevice = 0x6f22,
 		.card      = CX23885_BOARD_LEADTEK_WINFAST_PXTV1200,
+	}, {
+		.subvendor = 0x5654,
+		.subdevice = 0x2390,
+		.card      = CX23885_BOARD_GOTVIEW_X5_3D_HYBRID,
 	},
 };
 const unsigned int cx23885_idcount = ARRAY_SIZE(cx23885_subids);
@@ -712,6 +736,10 @@ int cx23885_tuner_callback(void *priv, i
 		else if (port->nr == 2)
 			bitmask = 0x04;
 		break;
+	case CX23885_BOARD_GOTVIEW_X5_3D_HYBRID:
+		/* Tuner Reset Command */
+		bitmask = 0x02;
+		break;
 	}
 
 	if (bitmask) {
@@ -967,6 +995,9 @@ void cx23885_gpio_setup(struct cx23885_d
 		/* CX24228 GPIO */
 		/* Connected to IF / Mux */
 		break;
+	case CX23885_BOARD_GOTVIEW_X5_3D_HYBRID:
+		cx_set(GP0_IO, 0x00010001); /* Bring the part out of reset */
+		break;
 	}
 }
 
@@ -1218,6 +1249,7 @@ void cx23885_card_setup(struct cx23885_d
 	case CX23885_BOARD_HAUPPAUGE_HVR1850:
 	case CX23885_BOARD_COMPRO_VIDEOMATE_E800:
 	case CX23885_BOARD_HAUPPAUGE_HVR1290:
+	case CX23885_BOARD_GOTVIEW_X5_3D_HYBRID:
 	default:
 		ts2->gen_ctrl_val  = 0xc; /* Serial bus + punctured clock */
 		ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */
@@ -1245,6 +1277,7 @@ void cx23885_card_setup(struct cx23885_d
 	case CX23885_BOARD_MAGICPRO_PROHDTVE2:
 	case CX23885_BOARD_HAUPPAUGE_HVR1290:
 	case CX23885_BOARD_LEADTEK_WINFAST_PXTV1200:
+	case CX23885_BOARD_GOTVIEW_X5_3D_HYBRID:
 		dev->sd_cx25840 = v4l2_i2c_new_subdev(&dev->v4l2_dev,
 				&dev->i2c_bus[2].i2c_adap,
 				"cx25840", 0x88 >> 1, NULL);
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/cx23885/cx23885.h linux-libre-2.6.38-gnu1/drivers/media/video/cx23885/cx23885.h
--- linux-libre-2.6.37-gnu1/drivers/media/video/cx23885/cx23885.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/cx23885/cx23885.h	2011-03-14 21:20:32.000000000 -0400
@@ -30,7 +30,7 @@
 #include <media/tveeprom.h>
 #include <media/videobuf-dma-sg.h>
 #include <media/videobuf-dvb.h>
-#include <media/ir-core.h>
+#include <media/rc-core.h>
 
 #include "btcx-risc.h"
 #include "cx23885-reg.h"
@@ -84,6 +84,7 @@
 #define CX23885_BOARD_HAUPPAUGE_HVR1290        26
 #define CX23885_BOARD_MYGICA_X8558PRO          27
 #define CX23885_BOARD_LEADTEK_WINFAST_PXTV1200 28
+#define CX23885_BOARD_GOTVIEW_X5_3D_HYBRID     29
 
 #define GPIO_0 0x00000001
 #define GPIO_1 0x00000002
@@ -310,8 +311,7 @@ struct cx23885_kernel_ir {
 	char			*name;
 	char			*phys;
 
-	struct input_dev	*inp_dev;
-	struct ir_dev_props	props;
+	struct rc_dev		*rc;
 };
 
 struct cx23885_dev {
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/cx23885/cx23885-i2c.c linux-libre-2.6.38-gnu1/drivers/media/video/cx23885/cx23885-i2c.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/cx23885/cx23885-i2c.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/cx23885/cx23885-i2c.c	2011-03-14 21:20:32.000000000 -0400
@@ -122,10 +122,6 @@ static int i2c_sendbytes(struct i2c_adap
 
 	if (!i2c_wait_done(i2c_adap))
 		goto eio;
-	if (!i2c_slave_did_ack(i2c_adap)) {
-		retval = -ENXIO;
-		goto err;
-	}
 	if (i2c_debug) {
 		printk(" <W %02x %02x", msg->addr << 1, msg->buf[0]);
 		if (!(ctrl & I2C_NOSTOP))
@@ -158,7 +154,6 @@ static int i2c_sendbytes(struct i2c_adap
 
  eio:
 	retval = -EIO;
- err:
 	if (i2c_debug)
 		printk(KERN_ERR " ERR: %d\n", retval);
 	return retval;
@@ -209,10 +204,6 @@ static int i2c_readbytes(struct i2c_adap
 
 		if (!i2c_wait_done(i2c_adap))
 			goto eio;
-		if (cnt == 0 && !i2c_slave_did_ack(i2c_adap)) {
-			retval = -ENXIO;
-			goto err;
-		}
 		msg->buf[cnt] = cx_read(bus->reg_rdata) & 0xff;
 		if (i2c_debug) {
 			dprintk(1, " %02x", msg->buf[cnt]);
@@ -224,7 +215,6 @@ static int i2c_readbytes(struct i2c_adap
 
  eio:
 	retval = -EIO;
- err:
 	if (i2c_debug)
 		printk(KERN_ERR " ERR: %d\n", retval);
 	return retval;
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/cx23885/cx23885-input.c linux-libre-2.6.38-gnu1/drivers/media/video/cx23885/cx23885-input.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/cx23885/cx23885-input.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/cx23885/cx23885-input.c	2011-03-14 21:20:32.000000000 -0400
@@ -35,9 +35,8 @@
  *  02110-1301, USA.
  */
 
-#include <linux/input.h>
 #include <linux/slab.h>
-#include <media/ir-core.h>
+#include <media/rc-core.h>
 #include <media/v4l2-subdev.h>
 
 #include "cx23885.h"
@@ -62,16 +61,16 @@ static void cx23885_input_process_measur
 		count = num / sizeof(struct ir_raw_event);
 
 		for (i = 0; i < count; i++) {
-			ir_raw_event_store(kernel_ir->inp_dev,
+			ir_raw_event_store(kernel_ir->rc,
 					   &ir_core_event[i]);
 			handle = true;
 		}
 	} while (num != 0);
 
 	if (overrun)
-		ir_raw_event_reset(kernel_ir->inp_dev);
+		ir_raw_event_reset(kernel_ir->rc);
 	else if (handle)
-		ir_raw_event_handle(kernel_ir->inp_dev);
+		ir_raw_event_handle(kernel_ir->rc);
 }
 
 void cx23885_input_rx_work_handler(struct cx23885_dev *dev, u32 events)
@@ -197,9 +196,9 @@ static int cx23885_input_ir_start(struct
 	return 0;
 }
 
-static int cx23885_input_ir_open(void *priv)
+static int cx23885_input_ir_open(struct rc_dev *rc)
 {
-	struct cx23885_kernel_ir *kernel_ir = priv;
+	struct cx23885_kernel_ir *kernel_ir = rc->priv;
 
 	if (kernel_ir->cx == NULL)
 		return -ENODEV;
@@ -230,13 +229,11 @@ static void cx23885_input_ir_stop(struct
 		v4l2_subdev_call(dev->sd_ir, ir, rx_s_parameters, &params);
 		v4l2_subdev_call(dev->sd_ir, ir, rx_g_parameters, &params);
 	}
-
-	flush_scheduled_work();
 }
 
-static void cx23885_input_ir_close(void *priv)
+static void cx23885_input_ir_close(struct rc_dev *rc)
 {
-	struct cx23885_kernel_ir *kernel_ir = priv;
+	struct cx23885_kernel_ir *kernel_ir = rc->priv;
 
 	if (kernel_ir->cx != NULL)
 		cx23885_input_ir_stop(kernel_ir->cx);
@@ -245,9 +242,7 @@ static void cx23885_input_ir_close(void
 int cx23885_input_init(struct cx23885_dev *dev)
 {
 	struct cx23885_kernel_ir *kernel_ir;
-	struct input_dev *inp_dev;
-	struct ir_dev_props *props;
-
+	struct rc_dev *rc;
 	char *rc_map;
 	enum rc_driver_type driver_type;
 	unsigned long allowed_protos;
@@ -267,14 +262,14 @@ int cx23885_input_init(struct cx23885_de
 	case CX23885_BOARD_HAUPPAUGE_HVR1250:
 		/* Integrated CX2388[58] IR controller */
 		driver_type = RC_DRIVER_IR_RAW;
-		allowed_protos = IR_TYPE_ALL;
+		allowed_protos = RC_TYPE_ALL;
 		/* The grey Hauppauge RC-5 remote */
 		rc_map = RC_MAP_RC5_HAUPPAUGE_NEW;
 		break;
 	case CX23885_BOARD_TEVII_S470:
 		/* Integrated CX23885 IR controller */
 		driver_type = RC_DRIVER_IR_RAW;
-		allowed_protos = IR_TYPE_ALL;
+		allowed_protos = RC_TYPE_ALL;
 		/* A guess at the remote */
 		rc_map = RC_MAP_TEVII_NEC;
 		break;
@@ -294,37 +289,36 @@ int cx23885_input_init(struct cx23885_de
 				    pci_name(dev->pci));
 
 	/* input device */
-	inp_dev = input_allocate_device();
-	if (inp_dev == NULL) {
+	rc = rc_allocate_device();
+	if (!rc) {
 		ret = -ENOMEM;
 		goto err_out_free;
 	}
 
-	kernel_ir->inp_dev = inp_dev;
-	inp_dev->name = kernel_ir->name;
-	inp_dev->phys = kernel_ir->phys;
-	inp_dev->id.bustype = BUS_PCI;
-	inp_dev->id.version = 1;
+	kernel_ir->rc = rc;
+	rc->input_name = kernel_ir->name;
+	rc->input_phys = kernel_ir->phys;
+	rc->input_id.bustype = BUS_PCI;
+	rc->input_id.version = 1;
 	if (dev->pci->subsystem_vendor) {
-		inp_dev->id.vendor  = dev->pci->subsystem_vendor;
-		inp_dev->id.product = dev->pci->subsystem_device;
+		rc->input_id.vendor  = dev->pci->subsystem_vendor;
+		rc->input_id.product = dev->pci->subsystem_device;
 	} else {
-		inp_dev->id.vendor  = dev->pci->vendor;
-		inp_dev->id.product = dev->pci->device;
+		rc->input_id.vendor  = dev->pci->vendor;
+		rc->input_id.product = dev->pci->device;
 	}
-	inp_dev->dev.parent = &dev->pci->dev;
-
-	/* kernel ir device properties */
-	props = &kernel_ir->props;
-	props->driver_type = driver_type;
-	props->allowed_protos = allowed_protos;
-	props->priv = kernel_ir;
-	props->open = cx23885_input_ir_open;
-	props->close = cx23885_input_ir_close;
+	rc->dev.parent = &dev->pci->dev;
+	rc->driver_type = driver_type;
+	rc->allowed_protos = allowed_protos;
+	rc->priv = kernel_ir;
+	rc->open = cx23885_input_ir_open;
+	rc->close = cx23885_input_ir_close;
+	rc->map_name = rc_map;
+	rc->driver_name = MODULE_NAME;
 
 	/* Go */
 	dev->kernel_ir = kernel_ir;
-	ret = ir_input_register(inp_dev, rc_map, props, MODULE_NAME);
+	ret = rc_register_device(rc);
 	if (ret)
 		goto err_out_stop;
 
@@ -333,7 +327,7 @@ int cx23885_input_init(struct cx23885_de
 err_out_stop:
 	cx23885_input_ir_stop(dev);
 	dev->kernel_ir = NULL;
-	/* TODO: double check clean-up of kernel_ir->inp_dev */
+	rc_free_device(rc);
 err_out_free:
 	kfree(kernel_ir->phys);
 	kfree(kernel_ir->name);
@@ -348,7 +342,7 @@ void cx23885_input_fini(struct cx23885_d
 
 	if (dev->kernel_ir == NULL)
 		return;
-	ir_input_unregister(dev->kernel_ir->inp_dev);
+	rc_unregister_device(dev->kernel_ir->rc);
 	kfree(dev->kernel_ir->phys);
 	kfree(dev->kernel_ir->name);
 	kfree(dev->kernel_ir);
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/cx23885/cx23885-video.c linux-libre-2.6.38-gnu1/drivers/media/video/cx23885/cx23885-video.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/cx23885/cx23885-video.c	2013-05-03 03:54:56.000000000 -0400
+++ linux-libre-2.6.38-gnu1/drivers/media/video/cx23885/cx23885-video.c	2013-05-03 01:54:14.000000000 -0400
@@ -1024,35 +1024,6 @@ static int vidioc_enum_fmt_vid_cap(struc
 	return 0;
 }
 
-#ifdef CONFIG_VIDEO_V4L1_COMPAT
-static int vidiocgmbuf(struct file *file, void *priv,
-	struct video_mbuf *mbuf)
-{
-	struct cx23885_fh *fh = priv;
-	struct videobuf_queue *q;
-	struct v4l2_requestbuffers req;
-	unsigned int i;
-	int err;
-
-	q = get_queue(fh);
-	memset(&req, 0, sizeof(req));
-	req.type   = q->type;
-	req.count  = 8;
-	req.memory = V4L2_MEMORY_MMAP;
-	err = videobuf_reqbufs(q, &req);
-	if (err < 0)
-		return err;
-
-	mbuf->frames = req.count;
-	mbuf->size   = 0;
-	for (i = 0; i < mbuf->frames; i++) {
-		mbuf->offsets[i]  = q->bufs[i]->boff;
-		mbuf->size       += q->bufs[i]->bsize;
-	}
-	return 0;
-}
-#endif
-
 static int vidioc_reqbufs(struct file *file, void *priv,
 	struct v4l2_requestbuffers *p)
 {
@@ -1155,7 +1126,6 @@ static int cx23885_enum_input(struct cx2
 	if (0 == INPUT(n)->type)
 		return -EINVAL;
 
-	memset(i, 0, sizeof(*i));
 	i->index = n;
 	i->type  = V4L2_INPUT_TYPE_CAMERA;
 	strcpy(i->name, iname[INPUT(n)->type]);
@@ -1427,9 +1397,6 @@ static const struct v4l2_ioctl_ops video
 	.vidioc_s_ctrl        = vidioc_s_ctrl,
 	.vidioc_streamon      = vidioc_streamon,
 	.vidioc_streamoff     = vidioc_streamoff,
-#ifdef CONFIG_VIDEO_V4L1_COMPAT
-	.vidiocgmbuf          = vidiocgmbuf,
-#endif
 	.vidioc_g_tuner       = vidioc_g_tuner,
 	.vidioc_s_tuner       = vidioc_s_tuner,
 	.vidioc_g_frequency   = vidioc_g_frequency,
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/cx23885/cx23888-ir.c linux-libre-2.6.38-gnu1/drivers/media/video/cx23885/cx23888-ir.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/cx23885/cx23888-ir.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/cx23885/cx23888-ir.c	2011-03-14 21:20:32.000000000 -0400
@@ -26,7 +26,7 @@
 
 #include <media/v4l2-device.h>
 #include <media/v4l2-chip-ident.h>
-#include <media/ir-core.h>
+#include <media/rc-core.h>
 
 #include "cx23885.h"
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/cx23885/Kconfig linux-libre-2.6.38-gnu1/drivers/media/video/cx23885/Kconfig
--- linux-libre-2.6.37-gnu1/drivers/media/video/cx23885/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/cx23885/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -5,7 +5,7 @@ config VIDEO_CX23885
 	select VIDEO_BTCX
 	select VIDEO_TUNER
 	select VIDEO_TVEEPROM
-	depends on IR_CORE
+	depends on RC_CORE
 	select VIDEOBUF_DVB
 	select VIDEOBUF_DMA_SG
 	select VIDEO_CX25840
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/cx25840/cx25840-core.c linux-libre-2.6.38-gnu1/drivers/media/video/cx25840/cx25840-core.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/cx25840/cx25840-core.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/cx25840/cx25840-core.c	2011-03-14 21:20:32.000000000 -0400
@@ -1682,20 +1682,6 @@ static int cx25840_log_status(struct v4l
 	return 0;
 }
 
-static int cx25840_s_config(struct v4l2_subdev *sd, int irq, void *platform_data)
-{
-	struct cx25840_state *state = to_state(sd);
-	struct i2c_client *client = v4l2_get_subdevdata(sd);
-
-	if (platform_data) {
-		struct cx25840_platform_data *pdata = platform_data;
-
-		state->pvr150_workaround = pdata->pvr150_workaround;
-		set_input(client, state->vid_input, state->aud_input);
-	}
-	return 0;
-}
-
 static int cx23885_irq_handler(struct v4l2_subdev *sd, u32 status,
 			       bool *handled)
 {
@@ -1787,7 +1773,6 @@ static const struct v4l2_ctrl_ops cx2584
 
 static const struct v4l2_subdev_core_ops cx25840_core_ops = {
 	.log_status = cx25840_log_status,
-	.s_config = cx25840_s_config,
 	.g_chip_ident = cx25840_g_chip_ident,
 	.g_ctrl = v4l2_subdev_g_ctrl,
 	.s_ctrl = v4l2_subdev_s_ctrl,
@@ -1974,7 +1959,6 @@ static int cx25840_probe(struct i2c_clie
 	state->vid_input = CX25840_COMPOSITE7;
 	state->aud_input = CX25840_AUDIO8;
 	state->audclk_freq = 48000;
-	state->pvr150_workaround = 0;
 	state->audmode = V4L2_TUNER_MODE_LANG1;
 	state->vbi_line_offset = 8;
 	state->id = id;
@@ -2031,9 +2015,16 @@ static int cx25840_probe(struct i2c_clie
 		kfree(state);
 		return err;
 	}
-	v4l2_ctrl_cluster(2, &state->volume);
+	if (!is_cx2583x(state))
+		v4l2_ctrl_cluster(2, &state->volume);
 	v4l2_ctrl_handler_setup(&state->hdl);
 
+	if (client->dev.platform_data) {
+		struct cx25840_platform_data *pdata = client->dev.platform_data;
+
+		state->pvr150_workaround = pdata->pvr150_workaround;
+	}
+
 	cx25840_ir_probe(sd);
 	return 0;
 }
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/cx25840/cx25840-ir.c linux-libre-2.6.38-gnu1/drivers/media/video/cx25840/cx25840-ir.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/cx25840/cx25840-ir.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/cx25840/cx25840-ir.c	2011-03-14 21:20:32.000000000 -0400
@@ -24,7 +24,7 @@
 #include <linux/slab.h>
 #include <linux/kfifo.h>
 #include <media/cx25840.h>
-#include <media/ir-core.h>
+#include <media/rc-core.h>
 
 #include "cx25840-core.h"
 
@@ -261,7 +261,7 @@ static u16 ns_to_pulse_width_count(u32 n
 	u32 rem;
 
 	/*
-	 * The 2 lsb's of the pulse width timer count are not accessable, hence
+	 * The 2 lsb's of the pulse width timer count are not accessible, hence
 	 * the (1 << 2)
 	 */
 	n = ((u64) ns) * CX25840_IR_REFCLK_FREQ / 1000000; /* millicycles */
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/cx88/cx88-blackbird.c linux-libre-2.6.38-gnu1/drivers/media/video/cx88/cx88-blackbird.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/cx88/cx88-blackbird.c	2013-05-03 03:57:03.000000000 -0400
+++ linux-libre-2.6.38-gnu1/drivers/media/video/cx88/cx88-blackbird.c	2013-05-03 01:56:49.000000000 -0400
@@ -1064,7 +1064,7 @@ static int mpeg_open(struct file *file)
 		err = drv->request_acquire(drv);
 		if(err != 0) {
 			dprintk(1,"%s: Unable to acquire hardware, %d\n", __func__, err);
-			mutex_unlock(&dev->core->lock);;
+			mutex_unlock(&dev->core->lock);
 			return err;
 		}
 	}
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/cx88/cx88-cards.c linux-libre-2.6.38-gnu1/drivers/media/video/cx88/cx88-cards.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/cx88/cx88-cards.c	2013-05-03 03:54:56.000000000 -0400
+++ linux-libre-2.6.38-gnu1/drivers/media/video/cx88/cx88-cards.c	2013-05-03 01:54:15.000000000 -0400
@@ -47,7 +47,7 @@ MODULE_PARM_DESC(latency,"pci latency ti
 
 static int disable_ir;
 module_param(disable_ir, int, 0444);
-MODULE_PARM_DESC(latency, "Disable IR support");
+MODULE_PARM_DESC(disable_ir, "Disable IR support");
 
 #define info_printk(core, fmt, arg...) \
 	printk(KERN_INFO "%s: " fmt, core->name , ## arg)
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/cx88/cx88-dvb.c linux-libre-2.6.38-gnu1/drivers/media/video/cx88/cx88-dvb.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/cx88/cx88-dvb.c	2013-05-03 03:54:56.000000000 -0400
+++ linux-libre-2.6.38-gnu1/drivers/media/video/cx88/cx88-dvb.c	2013-05-03 01:54:14.000000000 -0400
@@ -67,6 +67,10 @@ static unsigned int debug;
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug,"enable debug messages [dvb]");
 
+static unsigned int dvb_buf_tscnt = 32;
+module_param(dvb_buf_tscnt, int, 0644);
+MODULE_PARM_DESC(dvb_buf_tscnt, "DVB Buffer TS count [dvb]");
+
 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
 
 #define dprintk(level,fmt, arg...)	if (debug >= level) \
@@ -80,10 +84,10 @@ static int dvb_buf_setup(struct videobuf
 	struct cx8802_dev *dev = q->priv_data;
 
 	dev->ts_packet_size  = 188 * 4;
-	dev->ts_packet_count = 32;
+	dev->ts_packet_count = dvb_buf_tscnt;
 
 	*size  = dev->ts_packet_size * dev->ts_packet_count;
-	*count = 32;
+	*count = dvb_buf_tscnt;
 	return 0;
 }
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/cx88/cx88-i2c.c linux-libre-2.6.38-gnu1/drivers/media/video/cx88/cx88-i2c.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/cx88/cx88-i2c.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/cx88/cx88-i2c.c	2011-03-14 21:20:32.000000000 -0400
@@ -146,7 +146,6 @@ int cx88_i2c_init(struct cx88_core *core
 	core->i2c_adap.dev.parent = &pci->dev;
 	strlcpy(core->i2c_adap.name,core->name,sizeof(core->i2c_adap.name));
 	core->i2c_adap.owner = THIS_MODULE;
-	core->i2c_adap.id = I2C_HW_B_CX2388x;
 	core->i2c_algo.udelay = i2c_udelay;
 	core->i2c_algo.data = core;
 	i2c_set_adapdata(&core->i2c_adap, &core->v4l2_dev);
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/cx88/cx88-input.c linux-libre-2.6.38-gnu1/drivers/media/video/cx88/cx88-input.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/cx88/cx88-input.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/cx88/cx88-input.c	2011-03-14 21:20:32.000000000 -0400
@@ -24,14 +24,12 @@
 
 #include <linux/init.h>
 #include <linux/hrtimer.h>
-#include <linux/input.h>
 #include <linux/pci.h>
 #include <linux/slab.h>
 #include <linux/module.h>
 
 #include "cx88.h"
-#include <media/ir-core.h>
-#include <media/ir-common.h>
+#include <media/rc-core.h>
 
 #define MODULE_NAME "cx88xx"
 
@@ -39,9 +37,7 @@
 
 struct cx88_IR {
 	struct cx88_core *core;
-	struct input_dev *input;
-	struct ir_dev_props props;
-	u64 ir_type;
+	struct rc_dev *dev;
 
 	int users;
 
@@ -50,8 +46,6 @@ struct cx88_IR {
 
 	/* sample from gpio pin 16 */
 	u32 sampling;
-	u32 samples[16];
-	int scount;
 
 	/* poll external decoder */
 	int polling;
@@ -63,6 +57,10 @@ struct cx88_IR {
 	u32 mask_keyup;
 };
 
+static unsigned ir_samplerate = 4;
+module_param(ir_samplerate, uint, 0444);
+MODULE_PARM_DESC(ir_samplerate, "IR samplerate in kHz, 1 - 20, default 4");
+
 static int ir_debug;
 module_param(ir_debug, int, 0644);	/* debug level [IR] */
 MODULE_PARM_DESC(ir_debug, "enable debug messages [IR]");
@@ -70,6 +68,9 @@ MODULE_PARM_DESC(ir_debug, "enable debug
 #define ir_dprintk(fmt, arg...)	if (ir_debug) \
 	printk(KERN_DEBUG "%s IR: " fmt , ir->core->name , ##arg)
 
+#define dprintk(fmt, arg...)	if (ir_debug) \
+	printk(KERN_DEBUG "cx88 IR: " fmt , ##arg)
+
 /* ---------------------------------------------------------------------- */
 
 static void cx88_ir_handle_key(struct cx88_IR *ir)
@@ -125,21 +126,26 @@ static void cx88_ir_handle_key(struct cx
 
 		data = (data << 4) | ((gpio_key & 0xf0) >> 4);
 
-		ir_keydown(ir->input, data, 0);
+		rc_keydown(ir->dev, data, 0);
 
 	} else if (ir->mask_keydown) {
 		/* bit set on keydown */
 		if (gpio & ir->mask_keydown)
-			ir_keydown(ir->input, data, 0);
+			rc_keydown_notimeout(ir->dev, data, 0);
+		else
+			rc_keyup(ir->dev);
 
 	} else if (ir->mask_keyup) {
 		/* bit cleared on keydown */
 		if (0 == (gpio & ir->mask_keyup))
-			ir_keydown(ir->input, data, 0);
+			rc_keydown_notimeout(ir->dev, data, 0);
+		else
+			rc_keyup(ir->dev);
 
 	} else {
 		/* can't distinguish keydown/up :-/ */
-		ir_keydown(ir->input, data, 0);
+		rc_keydown_notimeout(ir->dev, data, 0);
+		rc_keyup(ir->dev);
 	}
 }
 
@@ -176,8 +182,8 @@ static int __cx88_ir_start(void *priv)
 	}
 	if (ir->sampling) {
 		core->pci_irqmask |= PCI_INT_IR_SMPINT;
-		cx_write(MO_DDS_IO, 0xa80a80);	/* 4 kHz sample rate */
-		cx_write(MO_DDSCFG_IO, 0x5);	/* enable */
+		cx_write(MO_DDS_IO, 0x33F286 * ir_samplerate); /* samplerate */
+		cx_write(MO_DDSCFG_IO, 0x5); /* enable */
 	}
 	return 0;
 }
@@ -214,17 +220,17 @@ void cx88_ir_stop(struct cx88_core *core
 		__cx88_ir_stop(core);
 }
 
-static int cx88_ir_open(void *priv)
+static int cx88_ir_open(struct rc_dev *rc)
 {
-	struct cx88_core *core = priv;
+	struct cx88_core *core = rc->priv;
 
 	core->ir->users++;
 	return __cx88_ir_start(core);
 }
 
-static void cx88_ir_close(void *priv)
+static void cx88_ir_close(struct rc_dev *rc)
 {
-	struct cx88_core *core = priv;
+	struct cx88_core *core = rc->priv;
 
 	core->ir->users--;
 	if (!core->ir->users)
@@ -236,20 +242,20 @@ static void cx88_ir_close(void *priv)
 int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
 {
 	struct cx88_IR *ir;
-	struct input_dev *input_dev;
+	struct rc_dev *dev;
 	char *ir_codes = NULL;
-	u64 ir_type = IR_TYPE_OTHER;
+	u64 rc_type = RC_TYPE_OTHER;
 	int err = -ENOMEM;
 	u32 hardware_mask = 0;	/* For devices with a hardware mask, when
 				 * used with a full-code IR table
 				 */
 
 	ir = kzalloc(sizeof(*ir), GFP_KERNEL);
-	input_dev = input_allocate_device();
-	if (!ir || !input_dev)
+	dev = rc_allocate_device();
+	if (!ir || !dev)
 		goto err_out_free;
 
-	ir->input = input_dev;
+	ir->dev = dev;
 
 	/* detect & configure */
 	switch (core->boardnr) {
@@ -264,7 +270,6 @@ int cx88_ir_init(struct cx88_core *core,
 		break;
 	case CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1:
 		ir_codes = RC_MAP_CINERGY_1400;
-		ir_type = IR_TYPE_NEC;
 		ir->sampling = 0xeb04; /* address */
 		break;
 	case CX88_BOARD_HAUPPAUGE:
@@ -279,7 +284,6 @@ int cx88_ir_init(struct cx88_core *core,
 	case CX88_BOARD_PCHDTV_HD5500:
 	case CX88_BOARD_HAUPPAUGE_IRONLY:
 		ir_codes = RC_MAP_HAUPPAUGE_NEW;
-		ir_type = IR_TYPE_RC5;
 		ir->sampling = 1;
 		break;
 	case CX88_BOARD_WINFAST_DTV2000H:
@@ -367,18 +371,15 @@ int cx88_ir_init(struct cx88_core *core,
 	case CX88_BOARD_PROF_7301:
 	case CX88_BOARD_PROF_6200:
 		ir_codes = RC_MAP_TBS_NEC;
-		ir_type = IR_TYPE_NEC;
 		ir->sampling = 0xff00; /* address */
 		break;
 	case CX88_BOARD_TEVII_S460:
 	case CX88_BOARD_TEVII_S420:
 		ir_codes = RC_MAP_TEVII_NEC;
-		ir_type = IR_TYPE_NEC;
 		ir->sampling = 0xff00; /* address */
 		break;
 	case CX88_BOARD_DNTV_LIVE_DVB_T_PRO:
 		ir_codes         = RC_MAP_DNTV_LIVE_DVBT_PRO;
-		ir_type          = IR_TYPE_NEC;
 		ir->sampling     = 0xff00; /* address */
 		break;
 	case CX88_BOARD_NORWOOD_MICRO:
@@ -396,7 +397,6 @@ int cx88_ir_init(struct cx88_core *core,
 		break;
 	case CX88_BOARD_PINNACLE_PCTV_HD_800i:
 		ir_codes         = RC_MAP_PINNACLE_PCTV_HD;
-		ir_type          = IR_TYPE_RC5;
 		ir->sampling     = 1;
 		break;
 	case CX88_BOARD_POWERCOLOR_REAL_ANGEL:
@@ -407,12 +407,12 @@ int cx88_ir_init(struct cx88_core *core,
 		break;
 	case CX88_BOARD_TWINHAN_VP1027_DVBS:
 		ir_codes         = RC_MAP_TWINHAN_VP1027_DVBS;
-		ir_type          = IR_TYPE_NEC;
+		rc_type          = RC_TYPE_NEC;
 		ir->sampling     = 0xff00; /* address */
 		break;
 	}
 
-	if (NULL == ir_codes) {
+	if (!ir_codes) {
 		err = -ENODEV;
 		goto err_out_free;
 	}
@@ -436,37 +436,45 @@ int cx88_ir_init(struct cx88_core *core,
 	snprintf(ir->name, sizeof(ir->name), "cx88 IR (%s)", core->board.name);
 	snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0", pci_name(pci));
 
-	ir->ir_type = ir_type;
-
-	input_dev->name = ir->name;
-	input_dev->phys = ir->phys;
-	input_dev->id.bustype = BUS_PCI;
-	input_dev->id.version = 1;
+	dev->input_name = ir->name;
+	dev->input_phys = ir->phys;
+	dev->input_id.bustype = BUS_PCI;
+	dev->input_id.version = 1;
 	if (pci->subsystem_vendor) {
-		input_dev->id.vendor = pci->subsystem_vendor;
-		input_dev->id.product = pci->subsystem_device;
+		dev->input_id.vendor = pci->subsystem_vendor;
+		dev->input_id.product = pci->subsystem_device;
 	} else {
-		input_dev->id.vendor = pci->vendor;
-		input_dev->id.product = pci->device;
+		dev->input_id.vendor = pci->vendor;
+		dev->input_id.product = pci->device;
 	}
-	input_dev->dev.parent = &pci->dev;
-	/* record handles to ourself */
+	dev->dev.parent = &pci->dev;
+	dev->map_name = ir_codes;
+	dev->driver_name = MODULE_NAME;
+	dev->priv = core;
+	dev->open = cx88_ir_open;
+	dev->close = cx88_ir_close;
+	dev->scanmask = hardware_mask;
+
+	if (ir->sampling) {
+		dev->driver_type = RC_DRIVER_IR_RAW;
+		dev->timeout = 10 * 1000 * 1000; /* 10 ms */
+	} else {
+		dev->driver_type = RC_DRIVER_SCANCODE;
+		dev->allowed_protos = rc_type;
+	}
+
 	ir->core = core;
 	core->ir = ir;
 
-	ir->props.priv = core;
-	ir->props.open = cx88_ir_open;
-	ir->props.close = cx88_ir_close;
-	ir->props.scanmask = hardware_mask;
-
 	/* all done */
-	err = ir_input_register(ir->input, ir_codes, &ir->props, MODULE_NAME);
+	err = rc_register_device(dev);
 	if (err)
 		goto err_out_free;
 
 	return 0;
 
- err_out_free:
+err_out_free:
+	rc_free_device(dev);
 	core->ir = NULL;
 	kfree(ir);
 	return err;
@@ -481,7 +489,7 @@ int cx88_ir_fini(struct cx88_core *core)
 		return 0;
 
 	cx88_ir_stop(core);
-	ir_input_unregister(ir->input);
+	rc_unregister_device(ir->dev);
 	kfree(ir);
 
 	/* done */
@@ -494,135 +502,75 @@ int cx88_ir_fini(struct cx88_core *core)
 void cx88_ir_irq(struct cx88_core *core)
 {
 	struct cx88_IR *ir = core->ir;
-	u32 samples, ircode;
-	int i, start, range, toggle, dev, code;
+	u32 samples;
+	unsigned todo, bits;
+	struct ir_raw_event ev;
 
-	if (NULL == ir)
-		return;
-	if (!ir->sampling)
+	if (!ir || !ir->sampling)
 		return;
 
+	/*
+	 * Samples are stored in a 32 bit register, oldest sample in
+	 * the msb. A set bit represents space and an unset bit
+	 * represents a pulse.
+	 */
 	samples = cx_read(MO_SAMPLE_IO);
-	if (0 != samples && 0xffffffff != samples) {
-		/* record sample data */
-		if (ir->scount < ARRAY_SIZE(ir->samples))
-			ir->samples[ir->scount++] = samples;
-		return;
-	}
-	if (!ir->scount) {
-		/* nothing to sample */
-		return;
-	}
-
-	/* have a complete sample */
-	if (ir->scount < ARRAY_SIZE(ir->samples))
-		ir->samples[ir->scount++] = samples;
-	for (i = 0; i < ir->scount; i++)
-		ir->samples[i] = ~ir->samples[i];
-	if (ir_debug)
-		ir_dump_samples(ir->samples, ir->scount);
-
-	/* decode it */
-	switch (core->boardnr) {
-	case CX88_BOARD_TEVII_S460:
-	case CX88_BOARD_TEVII_S420:
-	case CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1:
-	case CX88_BOARD_DNTV_LIVE_DVB_T_PRO:
-	case CX88_BOARD_OMICOM_SS4_PCI:
-	case CX88_BOARD_SATTRADE_ST4200:
-	case CX88_BOARD_TBS_8920:
-	case CX88_BOARD_TBS_8910:
-	case CX88_BOARD_PROF_7300:
-	case CX88_BOARD_PROF_7301:
-	case CX88_BOARD_PROF_6200:
-	case CX88_BOARD_TWINHAN_VP1027_DVBS:
-		ircode = ir_decode_pulsedistance(ir->samples, ir->scount, 1, 4);
-
-		if (ircode == 0xffffffff) { /* decoding error */
-			ir_dprintk("pulse distance decoding error\n");
-			break;
-		}
 
-		ir_dprintk("pulse distance decoded: %x\n", ircode);
+	if (samples == 0xff && ir->dev->idle)
+		return;
 
-		if (ircode == 0) { /* key still pressed */
-			ir_dprintk("pulse distance decoded repeat code\n");
-			ir_repeat(ir->input);
-			break;
-		}
+	init_ir_raw_event(&ev);
+	for (todo = 32; todo > 0; todo -= bits) {
+		ev.pulse = samples & 0x80000000 ? false : true;
+		bits = min(todo, 32U - fls(ev.pulse ? samples : ~samples));
+		ev.duration = (bits * NSEC_PER_SEC) / (1000 * ir_samplerate);
+		ir_raw_event_store_with_filter(ir->dev, &ev);
+		samples <<= bits;
+	}
+	ir_raw_event_handle(ir->dev);
+}
 
-		if ((ircode & 0xffff) != (ir->sampling & 0xffff)) { /* wrong address */
-			ir_dprintk("pulse distance decoded wrong address\n");
-			break;
-		}
+static int get_key_pvr2000(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
+{
+	int flags, code;
 
-		if (((~ircode >> 24) & 0xff) != ((ircode >> 16) & 0xff)) { /* wrong checksum */
-			ir_dprintk("pulse distance decoded wrong check sum\n");
-			break;
-		}
+	/* poll IR chip */
+	flags = i2c_smbus_read_byte_data(ir->c, 0x10);
+	if (flags < 0) {
+		dprintk("read error\n");
+		return 0;
+	}
+	/* key pressed ? */
+	if (0 == (flags & 0x80))
+		return 0;
 
-		ir_dprintk("Key Code: %x\n", (ircode >> 16) & 0xff);
-		ir_keydown(ir->input, (ircode >> 16) & 0xff, 0);
-		break;
-	case CX88_BOARD_HAUPPAUGE:
-	case CX88_BOARD_HAUPPAUGE_DVB_T1:
-	case CX88_BOARD_HAUPPAUGE_NOVASE2_S1:
-	case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1:
-	case CX88_BOARD_HAUPPAUGE_HVR1100:
-	case CX88_BOARD_HAUPPAUGE_HVR3000:
-	case CX88_BOARD_HAUPPAUGE_HVR4000:
-	case CX88_BOARD_HAUPPAUGE_HVR4000LITE:
-	case CX88_BOARD_PCHDTV_HD3000:
-	case CX88_BOARD_PCHDTV_HD5500:
-	case CX88_BOARD_HAUPPAUGE_IRONLY:
-		ircode = ir_decode_biphase(ir->samples, ir->scount, 5, 7);
-		ir_dprintk("biphase decoded: %x\n", ircode);
-		/*
-		 * RC5 has an extension bit which adds a new range
-		 * of available codes, this is detected here. Also
-		 * hauppauge remotes (black/silver) always use
-		 * specific device ids. If we do not filter the
-		 * device ids then messages destined for devices
-		 * such as TVs (id=0) will get through to the
-		 * device causing mis-fired events.
-		 */
-		/* split rc5 data block ... */
-		start = (ircode & 0x2000) >> 13;
-		range = (ircode & 0x1000) >> 12;
-		toggle= (ircode & 0x0800) >> 11;
-		dev   = (ircode & 0x07c0) >> 6;
-		code  = (ircode & 0x003f) | ((range << 6) ^ 0x0040);
-		if( start != 1)
-			/* no key pressed */
-			break;
-		if ( dev != 0x1e && dev != 0x1f )
-			/* not a hauppauge remote */
-			break;
-		ir_keydown(ir->input, code, toggle);
-		break;
-	case CX88_BOARD_PINNACLE_PCTV_HD_800i:
-		ircode = ir_decode_biphase(ir->samples, ir->scount, 5, 7);
-		ir_dprintk("biphase decoded: %x\n", ircode);
-		if ((ircode & 0xfffff000) != 0x3000)
-			break;
-		/* Note: bit 0x800 being the toggle is assumed, not checked
-		   with real hardware  */
-		ir_keydown(ir->input, ircode & 0x3f, ircode & 0x0800 ? 1 : 0);
-		break;
+	/* read actual key code */
+	code = i2c_smbus_read_byte_data(ir->c, 0x00);
+	if (code < 0) {
+		dprintk("read error\n");
+		return 0;
 	}
 
-	ir->scount = 0;
-	return;
-}
+	dprintk("IR Key/Flags: (0x%02x/0x%02x)\n",
+		   code & 0xff, flags & 0xff);
 
+	*ir_key = code & 0xff;
+	*ir_raw = code;
+	return 1;
+}
 
 void cx88_i2c_init_ir(struct cx88_core *core)
 {
 	struct i2c_board_info info;
-	const unsigned short addr_list[] = {
+	const unsigned short default_addr_list[] = {
 		0x18, 0x6b, 0x71,
 		I2C_CLIENT_END
 	};
+	const unsigned short pvr2000_addr_list[] = {
+		0x18, 0x1a,
+		I2C_CLIENT_END
+	};
+	const unsigned short *addr_list = default_addr_list;
 	const unsigned short *addrp;
 	/* Instantiate the IR receiver device, if present */
 	if (0 != core->i2c_rc)
@@ -631,6 +579,16 @@ void cx88_i2c_init_ir(struct cx88_core *
 	memset(&info, 0, sizeof(struct i2c_board_info));
 	strlcpy(info.type, "ir_video", I2C_NAME_SIZE);
 
+	switch (core->boardnr) {
+	case CX88_BOARD_LEADTEK_PVR2000:
+		addr_list = pvr2000_addr_list;
+		core->init_data.name = "cx88 Leadtek PVR 2000 remote";
+		core->init_data.type = RC_TYPE_UNKNOWN;
+		core->init_data.get_key = get_key_pvr2000;
+		core->init_data.ir_codes = RC_MAP_EMPTY;
+		break;
+	}
+
 	/*
 	 * We can't call i2c_new_probed_device() because it uses
 	 * quick writes for probing and at least some RC receiver
@@ -646,7 +604,7 @@ void cx88_i2c_init_ir(struct cx88_core *
 			/* Hauppauge XVR */
 			core->init_data.name = "cx88 Hauppauge XVR remote";
 			core->init_data.ir_codes = RC_MAP_HAUPPAUGE_NEW;
-			core->init_data.type = IR_TYPE_RC5;
+			core->init_data.type = RC_TYPE_RC5;
 			core->init_data.internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR;
 
 			info.platform_data = &core->init_data;
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/cx88/cx88-mpeg.c linux-libre-2.6.38-gnu1/drivers/media/video/cx88/cx88-mpeg.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/cx88/cx88-mpeg.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/cx88/cx88-mpeg.c	2011-03-14 21:20:32.000000000 -0400
@@ -66,8 +66,14 @@ static void request_modules(struct cx880
 	INIT_WORK(&dev->request_module_wk, request_module_async);
 	schedule_work(&dev->request_module_wk);
 }
+
+static void flush_request_modules(struct cx8802_dev *dev)
+{
+	flush_work_sync(&dev->request_module_wk);
+}
 #else
 #define request_modules(dev)
+#define flush_request_modules(dev)
 #endif /* CONFIG_MODULES */
 
 
@@ -819,6 +825,8 @@ static void __devexit cx8802_remove(stru
 
 	dprintk( 1, "%s\n", __func__);
 
+	flush_request_modules(dev);
+
 	if (!list_empty(&dev->drvlist)) {
 		struct cx8802_driver *drv, *tmp;
 		int err;
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/cx88/cx88-video.c linux-libre-2.6.38-gnu1/drivers/media/video/cx88/cx88-video.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/cx88/cx88-video.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/cx88/cx88-video.c	2011-03-14 21:20:32.000000000 -0400
@@ -1156,15 +1156,6 @@ static int vidioc_enum_fmt_vid_cap (stru
 	return 0;
 }
 
-#ifdef CONFIG_VIDEO_V4L1_COMPAT
-static int vidiocgmbuf (struct file *file, void *priv, struct video_mbuf *mbuf)
-{
-	struct cx8800_fh           *fh  = priv;
-
-	return videobuf_cgmbuf (get_queue(fh), mbuf, 8);
-}
-#endif
-
 static int vidioc_reqbufs (struct file *file, void *priv, struct v4l2_requestbuffers *p)
 {
 	struct cx8800_fh  *fh   = priv;
@@ -1706,9 +1697,6 @@ static const struct v4l2_ioctl_ops video
 	.vidioc_s_ctrl        = vidioc_s_ctrl,
 	.vidioc_streamon      = vidioc_streamon,
 	.vidioc_streamoff     = vidioc_streamoff,
-#ifdef CONFIG_VIDEO_V4L1_COMPAT
-	.vidiocgmbuf          = vidiocgmbuf,
-#endif
 	.vidioc_g_tuner       = vidioc_g_tuner,
 	.vidioc_s_tuner       = vidioc_s_tuner,
 	.vidioc_g_frequency   = vidioc_g_frequency,
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/cx88/cx88-vp3054-i2c.c linux-libre-2.6.38-gnu1/drivers/media/video/cx88/cx88-vp3054-i2c.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/cx88/cx88-vp3054-i2c.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/cx88/cx88-vp3054-i2c.c	2011-03-14 21:20:32.000000000 -0400
@@ -125,7 +125,6 @@ int vp3054_i2c_probe(struct cx8802_dev *
 	strlcpy(vp3054_i2c->adap.name, core->name,
 		sizeof(vp3054_i2c->adap.name));
 	vp3054_i2c->adap.owner = THIS_MODULE;
-	vp3054_i2c->adap.id = I2C_HW_B_CX2388x;
 	vp3054_i2c->algo.data = dev;
 	i2c_set_adapdata(&vp3054_i2c->adap, dev);
 	vp3054_i2c->adap.algo_data = &vp3054_i2c->algo;
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/cx88/Kconfig linux-libre-2.6.38-gnu1/drivers/media/video/cx88/Kconfig
--- linux-libre-2.6.37-gnu1/drivers/media/video/cx88/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/cx88/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -1,12 +1,11 @@
 config VIDEO_CX88
 	tristate "Conexant 2388x (bt878 successor) support"
-	depends on VIDEO_DEV && PCI && I2C && INPUT
+	depends on VIDEO_DEV && PCI && I2C && RC_CORE
 	select I2C_ALGOBIT
 	select VIDEO_BTCX
 	select VIDEOBUF_DMA_SG
 	select VIDEO_TUNER
 	select VIDEO_TVEEPROM
-	depends on VIDEO_IR
 	select VIDEO_WM8775 if VIDEO_HELPER_CHIPS_AUTO
 	---help---
 	  This is a video4linux driver for Conexant 2388x based
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/dabusb.c linux-libre-2.6.38-gnu1/drivers/media/video/dabusb.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/dabusb.c	2013-05-03 03:57:30.000000000 -0400
+++ linux-libre-2.6.38-gnu1/drivers/media/video/dabusb.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,913 +0,0 @@
-/*****************************************************************************/
-
-/*
- *      dabusb.c  --  dab usb driver.
- *
- *      Copyright (C) 1999  Deti Fliegl (deti@fliegl.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., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- *
- *
- *  $Id: dabusb.c,v 1.54 2000/07/24 21:39:39 deti Exp $
- *
- */
-
-/*****************************************************************************/
-
-#include <linux/module.h>
-#include <linux/socket.h>
-#include <linux/list.h>
-#include <linux/vmalloc.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <asm/uaccess.h>
-#include <asm/atomic.h>
-#include <linux/delay.h>
-#include <linux/usb.h>
-#include <linux/mutex.h>
-#include <linux/firmware.h>
-#include <linux/ihex.h>
-
-#include "dabusb.h"
-
-/*
- * Version Information
- */
-#define DRIVER_VERSION "v1.54"
-#define DRIVER_AUTHOR "Deti Fliegl, deti@fliegl.de"
-#define DRIVER_DESC "DAB-USB Interface Driver for Linux (c)1999"
-
-/* --------------------------------------------------------------------- */
-
-#ifdef CONFIG_USB_DYNAMIC_MINORS
-#define NRDABUSB 256
-#else
-#define NRDABUSB 4
-#endif
-
-/*-------------------------------------------------------------------*/
-
-static dabusb_t dabusb[NRDABUSB];
-static int buffers = 256;
-static struct usb_driver dabusb_driver;
-
-/*-------------------------------------------------------------------*/
-
-static int dabusb_add_buf_tail (pdabusb_t s, struct list_head *dst, struct list_head *src)
-{
-	unsigned long flags;
-	struct list_head *tmp;
-	int ret = 0;
-
-	spin_lock_irqsave (&s->lock, flags);
-
-	if (list_empty (src)) {
-		// no elements in source buffer
-		ret = -1;
-		goto err;
-	}
-	tmp = src->next;
-	list_move_tail (tmp, dst);
-
-  err:	spin_unlock_irqrestore (&s->lock, flags);
-	return ret;
-}
-/*-------------------------------------------------------------------*/
-#ifdef DEBUG
-static void dump_urb (struct urb *urb)
-{
-	dbg("urb                   :%p", urb);
-	dbg("dev                   :%p", urb->dev);
-	dbg("pipe                  :%08X", urb->pipe);
-	dbg("status                :%d", urb->status);
-	dbg("transfer_flags        :%08X", urb->transfer_flags);
-	dbg("transfer_buffer       :%p", urb->transfer_buffer);
-	dbg("transfer_buffer_length:%d", urb->transfer_buffer_length);
-	dbg("actual_length         :%d", urb->actual_length);
-	dbg("setup_packet          :%p", urb->setup_packet);
-	dbg("start_frame           :%d", urb->start_frame);
-	dbg("number_of_packets     :%d", urb->number_of_packets);
-	dbg("interval              :%d", urb->interval);
-	dbg("error_count           :%d", urb->error_count);
-	dbg("context               :%p", urb->context);
-	dbg("complete              :%p", urb->complete);
-}
-#endif
-/*-------------------------------------------------------------------*/
-static int dabusb_cancel_queue (pdabusb_t s, struct list_head *q)
-{
-	unsigned long flags;
-	pbuff_t b;
-
-	dbg("dabusb_cancel_queue");
-
-	spin_lock_irqsave (&s->lock, flags);
-
-	list_for_each_entry(b, q, buff_list) {
-#ifdef DEBUG
-		dump_urb(b->purb);
-#endif
-		usb_unlink_urb (b->purb);
-	}
-	spin_unlock_irqrestore (&s->lock, flags);
-	return 0;
-}
-/*-------------------------------------------------------------------*/
-static int dabusb_free_queue (struct list_head *q)
-{
-	struct list_head *tmp;
-	struct list_head *p;
-	pbuff_t b;
-
-	dbg("dabusb_free_queue");
-	for (p = q->next; p != q;) {
-		b = list_entry (p, buff_t, buff_list);
-
-#ifdef DEBUG
-		dump_urb(b->purb);
-#endif
-		kfree(b->purb->transfer_buffer);
-		usb_free_urb(b->purb);
-		tmp = p->next;
-		list_del (p);
-		kfree (b);
-		p = tmp;
-	}
-
-	return 0;
-}
-/*-------------------------------------------------------------------*/
-static int dabusb_free_buffers (pdabusb_t s)
-{
-	unsigned long flags;
-	dbg("dabusb_free_buffers");
-
-	spin_lock_irqsave(&s->lock, flags);
-
-	dabusb_free_queue (&s->free_buff_list);
-	dabusb_free_queue (&s->rec_buff_list);
-
-	spin_unlock_irqrestore(&s->lock, flags);
-
-	s->got_mem = 0;
-	return 0;
-}
-/*-------------------------------------------------------------------*/
-static void dabusb_iso_complete (struct urb *purb)
-{
-	pbuff_t b = purb->context;
-	pdabusb_t s = b->s;
-	int i;
-	int len;
-	int dst = 0;
-	void *buf = purb->transfer_buffer;
-
-	dbg("dabusb_iso_complete");
-
-	// process if URB was not killed
-	if (purb->status != -ENOENT) {
-		unsigned int pipe = usb_rcvisocpipe (purb->dev, _DABUSB_ISOPIPE);
-		int pipesize = usb_maxpacket (purb->dev, pipe, usb_pipeout (pipe));
-		for (i = 0; i < purb->number_of_packets; i++)
-			if (!purb->iso_frame_desc[i].status) {
-				len = purb->iso_frame_desc[i].actual_length;
-				if (len <= pipesize) {
-					memcpy (buf + dst, buf + purb->iso_frame_desc[i].offset, len);
-					dst += len;
-				}
-				else
-					dev_err(&purb->dev->dev,
-						"dabusb_iso_complete: invalid len %d\n", len);
-			}
-			else
-				dev_warn(&purb->dev->dev, "dabusb_iso_complete: corrupted packet status: %d\n", purb->iso_frame_desc[i].status);
-		if (dst != purb->actual_length)
-			dev_err(&purb->dev->dev,
-				"dst!=purb->actual_length:%d!=%d\n",
-					dst, purb->actual_length);
-	}
-
-	if (atomic_dec_and_test (&s->pending_io) && !s->remove_pending && s->state != _stopped) {
-		s->overruns++;
-		dev_err(&purb->dev->dev, "overrun (%d)\n", s->overruns);
-	}
-	wake_up (&s->wait);
-}
-/*-------------------------------------------------------------------*/
-static int dabusb_alloc_buffers (pdabusb_t s)
-{
-	int transfer_len = 0;
-	pbuff_t b;
-	unsigned int pipe = usb_rcvisocpipe (s->usbdev, _DABUSB_ISOPIPE);
-	int pipesize = usb_maxpacket (s->usbdev, pipe, usb_pipeout (pipe));
-	int packets = _ISOPIPESIZE / pipesize;
-	int transfer_buffer_length = packets * pipesize;
-	int i;
-
-	dbg("dabusb_alloc_buffers pipesize:%d packets:%d transfer_buffer_len:%d",
-		 pipesize, packets, transfer_buffer_length);
-
-	while (transfer_len < (s->total_buffer_size << 10)) {
-		b = kzalloc(sizeof (buff_t), GFP_KERNEL);
-		if (!b) {
-			dev_err(&s->usbdev->dev,
-				"kzalloc(sizeof(buff_t))==NULL\n");
-			goto err;
-		}
-		b->s = s;
-		b->purb = usb_alloc_urb(packets, GFP_KERNEL);
-		if (!b->purb) {
-			dev_err(&s->usbdev->dev, "usb_alloc_urb == NULL\n");
-			kfree (b);
-			goto err;
-		}
-
-		b->purb->transfer_buffer = kmalloc (transfer_buffer_length, GFP_KERNEL);
-		if (!b->purb->transfer_buffer) {
-			kfree (b->purb);
-			kfree (b);
-			dev_err(&s->usbdev->dev,
-				"kmalloc(%d)==NULL\n", transfer_buffer_length);
-			goto err;
-		}
-
-		b->purb->transfer_buffer_length = transfer_buffer_length;
-		b->purb->number_of_packets = packets;
-		b->purb->complete = dabusb_iso_complete;
-		b->purb->context = b;
-		b->purb->dev = s->usbdev;
-		b->purb->pipe = pipe;
-		b->purb->transfer_flags = URB_ISO_ASAP;
-
-		for (i = 0; i < packets; i++) {
-			b->purb->iso_frame_desc[i].offset = i * pipesize;
-			b->purb->iso_frame_desc[i].length = pipesize;
-		}
-
-		transfer_len += transfer_buffer_length;
-		list_add_tail (&b->buff_list, &s->free_buff_list);
-	}
-	s->got_mem = transfer_len;
-
-	return 0;
-
-	err:
-	dabusb_free_buffers (s);
-	return -ENOMEM;
-}
-/*-------------------------------------------------------------------*/
-static int dabusb_bulk (pdabusb_t s, pbulk_transfer_t pb)
-{
-	int ret;
-	unsigned int pipe;
-	int actual_length;
-
-	dbg("dabusb_bulk");
-
-	if (!pb->pipe)
-		pipe = usb_rcvbulkpipe (s->usbdev, 2);
-	else
-		pipe = usb_sndbulkpipe (s->usbdev, 2);
-
-	ret=usb_bulk_msg(s->usbdev, pipe, pb->data, pb->size, &actual_length, 100);
-	if(ret<0) {
-		dev_err(&s->usbdev->dev,
-			"usb_bulk_msg failed(%d)\n", ret);
-
-		if (usb_set_interface (s->usbdev, _DABUSB_IF, 1) < 0) {
-			dev_err(&s->usbdev->dev, "set_interface failed\n");
-			return -EINVAL;
-		}
-
-	}
-
-	if( ret == -EPIPE ) {
-		dev_warn(&s->usbdev->dev, "CLEAR_FEATURE request to remove STALL condition.\n");
-		if(usb_clear_halt(s->usbdev, usb_pipeendpoint(pipe)))
-			dev_err(&s->usbdev->dev, "request failed\n");
-	}
-
-	pb->size = actual_length;
-	return ret;
-}
-/* --------------------------------------------------------------------- */
-static int dabusb_writemem (pdabusb_t s, int pos, const unsigned char *data,
-			    int len)
-{
-	int ret;
-	unsigned char *transfer_buffer =  kmalloc (len, GFP_KERNEL);
-
-	if (!transfer_buffer) {
-		dev_err(&s->usbdev->dev,
-			"dabusb_writemem: kmalloc(%d) failed.\n", len);
-		return -ENOMEM;
-	}
-
-	memcpy (transfer_buffer, data, len);
-
-	ret=usb_control_msg(s->usbdev, usb_sndctrlpipe( s->usbdev, 0 ), 0xa0, 0x40, pos, 0, transfer_buffer, len, 300);
-
-	kfree (transfer_buffer);
-	return ret;
-}
-/* --------------------------------------------------------------------- */
-static int dabusb_8051_reset (pdabusb_t s, unsigned char reset_bit)
-{
-	dbg("dabusb_8051_reset: %d",reset_bit);
-	return dabusb_writemem (s, CPUCS_REG, &reset_bit, 1);
-}
-/* --------------------------------------------------------------------- */
-static int dabusb_loadmem (pdabusb_t s, const char *fname)
-{
-	int ret;
-	const struct ihex_binrec *rec;
-	const struct firmware *uninitialized_var(fw);
-
-	dbg("Enter dabusb_loadmem (internal)");
-
-	ret = reject_firmware(&fw, "/*(DEBLOBBED)*/", &s->usbdev->dev);
-	if (ret) {
-		dev_err(&s->usbdev->dev,
-			"Failed to load \"/*(DEBLOBBED)*/\": %d\n", ret);
-		goto out;
-	}
-	ret = dabusb_8051_reset (s, 1);
-
-	for (rec = (const struct ihex_binrec *)fw->data; rec;
-	     rec = ihex_next_binrec(rec)) {
-		dbg("dabusb_writemem: %04X %p %d)", be32_to_cpu(rec->addr),
-		    rec->data, be16_to_cpu(rec->len));
-
-		ret = dabusb_writemem(s, be32_to_cpu(rec->addr), rec->data,
-				       be16_to_cpu(rec->len));
-		if (ret < 0) {
-			dev_err(&s->usbdev->dev,
-				"dabusb_writemem failed (%d %04X %p %d)\n",
-				ret, be32_to_cpu(rec->addr),
-				rec->data, be16_to_cpu(rec->len));
-			break;
-		}
-	}
-	ret = dabusb_8051_reset (s, 0);
-	release_firmware(fw);
- out:
-	dbg("dabusb_loadmem: exit");
-
-	return ret;
-}
-/* --------------------------------------------------------------------- */
-static int dabusb_fpga_clear (pdabusb_t s, pbulk_transfer_t b)
-{
-	b->size = 4;
-	b->data[0] = 0x2a;
-	b->data[1] = 0;
-	b->data[2] = 0;
-	b->data[3] = 0;
-
-	dbg("dabusb_fpga_clear");
-
-	return dabusb_bulk (s, b);
-}
-/* --------------------------------------------------------------------- */
-static int dabusb_fpga_init (pdabusb_t s, pbulk_transfer_t b)
-{
-	b->size = 4;
-	b->data[0] = 0x2c;
-	b->data[1] = 0;
-	b->data[2] = 0;
-	b->data[3] = 0;
-
-	dbg("dabusb_fpga_init");
-
-	return dabusb_bulk (s, b);
-}
-/* --------------------------------------------------------------------- */
-static int dabusb_fpga_download (pdabusb_t s, const char *fname)
-{
-	pbulk_transfer_t b = kmalloc (sizeof (bulk_transfer_t), GFP_KERNEL);
-	const struct firmware *fw;
-	unsigned int blen, n;
-	int ret;
-
-	dbg("Enter dabusb_fpga_download (internal)");
-
-	if (!b) {
-		dev_err(&s->usbdev->dev,
-			"kmalloc(sizeof(bulk_transfer_t))==NULL\n");
-		return -ENOMEM;
-	}
-
-	ret = reject_firmware(&fw, "/*(DEBLOBBED)*/", &s->usbdev->dev);
-	if (ret) {
-		dev_err(&s->usbdev->dev,
-			"Failed to load \"/*(DEBLOBBED)*/\": %d\n", ret);
-		kfree(b);
-		return ret;
-	}
-
-	b->pipe = 1;
-	ret = dabusb_fpga_clear (s, b);
-	mdelay (10);
-	blen = fw->data[73] + (fw->data[72] << 8);
-
-	dbg("Bitstream len: %i", blen);
-
-	b->data[0] = 0x2b;
-	b->data[1] = 0;
-	b->data[2] = 0;
-	b->data[3] = 60;
-
-	for (n = 0; n <= blen + 60; n += 60) {
-		// some cclks for startup
-		b->size = 64;
-		memcpy (b->data + 4, fw->data + 74 + n, 60);
-		ret = dabusb_bulk (s, b);
-		if (ret < 0) {
-			dev_err(&s->usbdev->dev, "dabusb_bulk failed.\n");
-			break;
-		}
-		mdelay (1);
-	}
-
-	ret = dabusb_fpga_init (s, b);
-	kfree (b);
-	release_firmware(fw);
-
-	dbg("exit dabusb_fpga_download");
-
-	return ret;
-}
-
-static int dabusb_stop (pdabusb_t s)
-{
-	dbg("dabusb_stop");
-
-	s->state = _stopped;
-	dabusb_cancel_queue (s, &s->rec_buff_list);
-
-	dbg("pending_io: %d", s->pending_io.counter);
-
-	s->pending_io.counter = 0;
-	return 0;
-}
-
-static int dabusb_startrek (pdabusb_t s)
-{
-	if (!s->got_mem && s->state != _started) {
-
-		dbg("dabusb_startrek");
-
-		if (dabusb_alloc_buffers (s) < 0)
-			return -ENOMEM;
-		dabusb_stop (s);
-		s->state = _started;
-		s->readptr = 0;
-	}
-
-	if (!list_empty (&s->free_buff_list)) {
-		pbuff_t end;
-		int ret;
-
-	while (!dabusb_add_buf_tail (s, &s->rec_buff_list, &s->free_buff_list)) {
-
-			dbg("submitting: end:%p s->rec_buff_list:%p", s->rec_buff_list.prev, &s->rec_buff_list);
-
-			end = list_entry (s->rec_buff_list.prev, buff_t, buff_list);
-
-			ret = usb_submit_urb (end->purb, GFP_KERNEL);
-			if (ret) {
-				dev_err(&s->usbdev->dev,
-					"usb_submit_urb returned:%d\n", ret);
-				if (dabusb_add_buf_tail (s, &s->free_buff_list, &s->rec_buff_list))
-					dev_err(&s->usbdev->dev,
-						"startrek: dabusb_add_buf_tail failed\n");
-				break;
-			}
-			else
-				atomic_inc (&s->pending_io);
-		}
-		dbg("pending_io: %d",s->pending_io.counter);
-	}
-
-	return 0;
-}
-
-static ssize_t dabusb_read (struct file *file, char __user *buf, size_t count, loff_t * ppos)
-{
-	pdabusb_t s = (pdabusb_t) file->private_data;
-	unsigned long flags;
-	unsigned ret = 0;
-	int rem;
-	int cnt;
-	pbuff_t b;
-	struct urb *purb = NULL;
-
-	dbg("dabusb_read");
-
-	if (*ppos)
-		return -ESPIPE;
-
-	if (s->remove_pending)
-		return -EIO;
-
-
-	if (!s->usbdev)
-		return -EIO;
-
-	while (count > 0) {
-		dabusb_startrek (s);
-
-		spin_lock_irqsave (&s->lock, flags);
-
-		if (list_empty (&s->rec_buff_list)) {
-
-			spin_unlock_irqrestore(&s->lock, flags);
-
-			dev_err(&s->usbdev->dev,
-				"error: rec_buf_list is empty\n");
-			goto err;
-		}
-
-		b = list_entry (s->rec_buff_list.next, buff_t, buff_list);
-		purb = b->purb;
-
-		spin_unlock_irqrestore(&s->lock, flags);
-
-		if (purb->status == -EINPROGRESS) {
-			if (file->f_flags & O_NONBLOCK)		// return nonblocking
-			 {
-				if (!ret)
-					ret = -EAGAIN;
-				goto err;
-			}
-
-			interruptible_sleep_on (&s->wait);
-
-			if (signal_pending (current)) {
-				if (!ret)
-					ret = -ERESTARTSYS;
-				goto err;
-			}
-
-			spin_lock_irqsave (&s->lock, flags);
-
-			if (list_empty (&s->rec_buff_list)) {
-				spin_unlock_irqrestore(&s->lock, flags);
-				dev_err(&s->usbdev->dev,
-					"error: still no buffer available.\n");
-				goto err;
-			}
-			spin_unlock_irqrestore(&s->lock, flags);
-			s->readptr = 0;
-		}
-		if (s->remove_pending) {
-			ret = -EIO;
-			goto err;
-		}
-
-		rem = purb->actual_length - s->readptr;		// set remaining bytes to copy
-
-		if (count >= rem)
-			cnt = rem;
-		else
-			cnt = count;
-
-		dbg("copy_to_user:%p %p %d",buf, purb->transfer_buffer + s->readptr, cnt);
-
-		if (copy_to_user (buf, purb->transfer_buffer + s->readptr, cnt)) {
-			dev_err(&s->usbdev->dev, "read: copy_to_user failed\n");
-			if (!ret)
-				ret = -EFAULT;
-			goto err;
-		}
-
-		s->readptr += cnt;
-		count -= cnt;
-		buf += cnt;
-		ret += cnt;
-
-		if (s->readptr == purb->actual_length) {
-			// finished, take next buffer
-			if (dabusb_add_buf_tail (s, &s->free_buff_list, &s->rec_buff_list))
-				dev_err(&s->usbdev->dev,
-					"read: dabusb_add_buf_tail failed\n");
-			s->readptr = 0;
-		}
-	}
-      err:			//mutex_unlock(&s->mutex);
-	return ret;
-}
-
-static int dabusb_open (struct inode *inode, struct file *file)
-{
-	int devnum = iminor(inode);
-	pdabusb_t s;
-	int r;
-
-	if (devnum < DABUSB_MINOR || devnum >= (DABUSB_MINOR + NRDABUSB))
-		return -EIO;
-
-	s = &dabusb[devnum - DABUSB_MINOR];
-
-	dbg("dabusb_open");
-	mutex_lock(&s->mutex);
-
-	while (!s->usbdev || s->opened) {
-		mutex_unlock(&s->mutex);
-
-		if (file->f_flags & O_NONBLOCK)
-			return -EBUSY;
-		msleep_interruptible(500);
-
-		if (signal_pending (current))
-			return -EAGAIN;
-		mutex_lock(&s->mutex);
-	}
-	if (usb_set_interface (s->usbdev, _DABUSB_IF, 1) < 0) {
-		mutex_unlock(&s->mutex);
-		dev_err(&s->usbdev->dev, "set_interface failed\n");
-		return -EINVAL;
-	}
-	s->opened = 1;
-	mutex_unlock(&s->mutex);
-
-	file->f_pos = 0;
-	file->private_data = s;
-
-	r = nonseekable_open(inode, file);
-	return r;
-}
-
-static int dabusb_release (struct inode *inode, struct file *file)
-{
-	pdabusb_t s = (pdabusb_t) file->private_data;
-
-	dbg("dabusb_release");
-
-	mutex_lock(&s->mutex);
-	dabusb_stop (s);
-	dabusb_free_buffers (s);
-	mutex_unlock(&s->mutex);
-
-	if (!s->remove_pending) {
-		if (usb_set_interface (s->usbdev, _DABUSB_IF, 0) < 0)
-			dev_err(&s->usbdev->dev, "set_interface failed\n");
-	}
-	else
-		wake_up (&s->remove_ok);
-
-	s->opened = 0;
-	return 0;
-}
-
-static long dabusb_ioctl (struct file *file, unsigned int cmd, unsigned long arg)
-{
-	pdabusb_t s = (pdabusb_t) file->private_data;
-	pbulk_transfer_t pbulk;
-	int ret = 0;
-	int version = DABUSB_VERSION;
-
-	dbg("dabusb_ioctl");
-
-	if (s->remove_pending)
-		return -EIO;
-
-	mutex_lock(&s->mutex);
-
-	if (!s->usbdev) {
-		mutex_unlock(&s->mutex);
-		return -EIO;
-	}
-
-	switch (cmd) {
-
-	case IOCTL_DAB_BULK:
-		pbulk = memdup_user((void __user *)arg,
-				    sizeof(bulk_transfer_t));
-
-		if (IS_ERR(pbulk)) {
-			ret = PTR_ERR(pbulk);
-			break;
-		}
-
-		ret=dabusb_bulk (s, pbulk);
-		if(ret==0)
-			if (copy_to_user((void __user *)arg, pbulk,
-					 sizeof(bulk_transfer_t)))
-				ret = -EFAULT;
-		kfree (pbulk);
-		break;
-
-	case IOCTL_DAB_OVERRUNS:
-		ret = put_user (s->overruns, (unsigned int __user *) arg);
-		break;
-
-	case IOCTL_DAB_VERSION:
-		ret = put_user (version, (unsigned int __user *) arg);
-		break;
-
-	default:
-		ret = -ENOIOCTLCMD;
-		break;
-	}
-	mutex_unlock(&s->mutex);
-	return ret;
-}
-
-static const struct file_operations dabusb_fops =
-{
-	.owner =	THIS_MODULE,
-	.llseek =	no_llseek,
-	.read =		dabusb_read,
-	.unlocked_ioctl =	dabusb_ioctl,
-	.open =		dabusb_open,
-	.release =	dabusb_release,
-};
-
-static char *dabusb_devnode(struct device *dev, mode_t *mode)
-{
-	return kasprintf(GFP_KERNEL, "usb/%s", dev_name(dev));
-}
-
-static struct usb_class_driver dabusb_class = {
-	.name =		"dabusb%d",
-	.devnode =	dabusb_devnode,
-	.fops =		&dabusb_fops,
-	.minor_base =	DABUSB_MINOR,
-};
-
-
-/* --------------------------------------------------------------------- */
-static int dabusb_probe (struct usb_interface *intf,
-			 const struct usb_device_id *id)
-{
-	struct usb_device *usbdev = interface_to_usbdev(intf);
-	int retval;
-	pdabusb_t s;
-
-	dbg("dabusb: probe: vendor id 0x%x, device id 0x%x ifnum:%d",
-	    le16_to_cpu(usbdev->descriptor.idVendor),
-	    le16_to_cpu(usbdev->descriptor.idProduct),
-	    intf->altsetting->desc.bInterfaceNumber);
-
-	/* We don't handle multiple configurations */
-	if (usbdev->descriptor.bNumConfigurations != 1)
-		return -ENODEV;
-
-	if (intf->altsetting->desc.bInterfaceNumber != _DABUSB_IF &&
-	    le16_to_cpu(usbdev->descriptor.idProduct) == 0x9999)
-		return -ENODEV;
-
-
-
-	s = &dabusb[intf->minor];
-
-	mutex_lock(&s->mutex);
-	s->remove_pending = 0;
-	s->usbdev = usbdev;
-	s->devnum = intf->minor;
-
-	if (usb_reset_configuration (usbdev) < 0) {
-		dev_err(&intf->dev, "reset_configuration failed\n");
-		goto reject;
-	}
-	if (le16_to_cpu(usbdev->descriptor.idProduct) == 0x2131) {
-		dabusb_loadmem (s, NULL);
-		goto reject;
-	}
-	else {
-		dabusb_fpga_download (s, NULL);
-
-		if (usb_set_interface (s->usbdev, _DABUSB_IF, 0) < 0) {
-			dev_err(&intf->dev, "set_interface failed\n");
-			goto reject;
-		}
-	}
-	dbg("bound to interface: %d", intf->altsetting->desc.bInterfaceNumber);
-	usb_set_intfdata (intf, s);
-	mutex_unlock(&s->mutex);
-
-	retval = usb_register_dev(intf, &dabusb_class);
-	if (retval) {
-		usb_set_intfdata (intf, NULL);
-		return -ENOMEM;
-	}
-
-	return 0;
-
-      reject:
-	mutex_unlock(&s->mutex);
-	s->usbdev = NULL;
-	return -ENODEV;
-}
-
-static void dabusb_disconnect (struct usb_interface *intf)
-{
-	wait_queue_t __wait;
-	pdabusb_t s = usb_get_intfdata (intf);
-
-	dbg("dabusb_disconnect");
-
-	init_waitqueue_entry(&__wait, current);
-
-	usb_set_intfdata (intf, NULL);
-	if (s) {
-		usb_deregister_dev (intf, &dabusb_class);
-		s->remove_pending = 1;
-		wake_up (&s->wait);
-		add_wait_queue(&s->remove_ok, &__wait);
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		if (s->state == _started)
-			schedule();
-		current->state = TASK_RUNNING;
-		remove_wait_queue(&s->remove_ok, &__wait);
-
-		s->usbdev = NULL;
-		s->overruns = 0;
-	}
-}
-
-static struct usb_device_id dabusb_ids [] = {
-	// { USB_DEVICE(0x0547, 0x2131) },	/* An2131 chip, no boot ROM */
-	{ USB_DEVICE(0x0547, 0x9999) },
-	{ }						/* Terminating entry */
-};
-
-MODULE_DEVICE_TABLE (usb, dabusb_ids);
-
-static struct usb_driver dabusb_driver = {
-	.name =		"dabusb",
-	.probe =	dabusb_probe,
-	.disconnect =	dabusb_disconnect,
-	.id_table =	dabusb_ids,
-};
-
-/* --------------------------------------------------------------------- */
-
-static int __init dabusb_init (void)
-{
-	int retval;
-	unsigned u;
-
-	/* initialize struct */
-	for (u = 0; u < NRDABUSB; u++) {
-		pdabusb_t s = &dabusb[u];
-		memset (s, 0, sizeof (dabusb_t));
-		mutex_init (&s->mutex);
-		s->usbdev = NULL;
-		s->total_buffer_size = buffers;
-		init_waitqueue_head (&s->wait);
-		init_waitqueue_head (&s->remove_ok);
-		spin_lock_init (&s->lock);
-		INIT_LIST_HEAD (&s->free_buff_list);
-		INIT_LIST_HEAD (&s->rec_buff_list);
-	}
-
-	/* register misc device */
-	retval = usb_register(&dabusb_driver);
-	if (retval)
-		goto out;
-
-	dbg("dabusb_init: driver registered");
-
-	printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
-	       DRIVER_DESC "\n");
-
-out:
-	return retval;
-}
-
-static void __exit dabusb_cleanup (void)
-{
-	dbg("dabusb_cleanup");
-
-	usb_deregister (&dabusb_driver);
-}
-
-/* --------------------------------------------------------------------- */
-
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
-MODULE_LICENSE("GPL");
-/*(DEBLOBBED)*/
-
-module_param(buffers, int, 0);
-MODULE_PARM_DESC (buffers, "Number of buffers (default=256)");
-
-module_init (dabusb_init);
-module_exit (dabusb_cleanup);
-
-/* --------------------------------------------------------------------- */
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/dabusb.h linux-libre-2.6.38-gnu1/drivers/media/video/dabusb.h
--- linux-libre-2.6.37-gnu1/drivers/media/video/dabusb.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/dabusb.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,85 +0,0 @@
-#define _BULK_DATA_LEN 64
-typedef struct
-{
-	unsigned char data[_BULK_DATA_LEN];
-	unsigned int size;
-	unsigned int pipe;
-}bulk_transfer_t,*pbulk_transfer_t;
-
-#define DABUSB_MINOR 240		/* some unassigned USB minor */
-#define DABUSB_VERSION 0x1000
-#define IOCTL_DAB_BULK              _IOWR('d', 0x30, bulk_transfer_t)
-#define IOCTL_DAB_OVERRUNS	    _IOR('d',  0x15, int)
-#define IOCTL_DAB_VERSION           _IOR('d', 0x3f, int)
-
-#ifdef __KERNEL__
-
-typedef enum { _stopped=0, _started } driver_state_t;
-
-typedef struct
-{
-	struct mutex mutex;
-	struct usb_device *usbdev;
-	wait_queue_head_t wait;
-	wait_queue_head_t remove_ok;
-	spinlock_t lock;
-	atomic_t pending_io;
-	driver_state_t state;
-	int remove_pending;
-	int got_mem;
-	int total_buffer_size;
-	unsigned int overruns;
-	int readptr;
-	int opened;
-	int devnum;
-	struct list_head free_buff_list;
-	struct list_head rec_buff_list;
-} dabusb_t,*pdabusb_t;
-
-typedef struct
-{
-	pdabusb_t s;
-	struct urb *purb;
-	struct list_head buff_list;
-} buff_t,*pbuff_t;
-
-typedef struct
-{
-	wait_queue_head_t wait;
-} bulk_completion_context_t, *pbulk_completion_context_t;
-
-
-#define _DABUSB_IF 2
-#define _DABUSB_ISOPIPE 0x09
-#define _ISOPIPESIZE	16384
-
-#define _BULK_DATA_LEN 64
-// Vendor specific request code for Anchor Upload/Download
-// This one is implemented in the core
-#define ANCHOR_LOAD_INTERNAL  0xA0
-
-// EZ-USB Control and Status Register.  Bit 0 controls 8051 reset
-#define CPUCS_REG    0x7F92
-#define _TOTAL_BUFFERS 384
-
-#define MAX_INTEL_HEX_RECORD_LENGTH 16
-
-#ifndef _BYTE_DEFINED
-#define _BYTE_DEFINED
-typedef unsigned char BYTE;
-#endif // !_BYTE_DEFINED
-
-#ifndef _WORD_DEFINED
-#define _WORD_DEFINED
-typedef unsigned short WORD;
-#endif // !_WORD_DEFINED
-
-typedef struct _INTEL_HEX_RECORD
-{
-   BYTE  Length;
-   WORD  Address;
-   BYTE  Type;
-   BYTE  Data[MAX_INTEL_HEX_RECORD_LENGTH];
-} INTEL_HEX_RECORD, *PINTEL_HEX_RECORD;
-
-#endif
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/davinci/vpfe_capture.c linux-libre-2.6.38-gnu1/drivers/media/video/davinci/vpfe_capture.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/davinci/vpfe_capture.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/davinci/vpfe_capture.c	2011-03-14 21:20:32.000000000 -0400
@@ -1276,7 +1276,7 @@ static int vpfe_videobuf_prepare(struct
 		vb->size = vpfe_dev->fmt.fmt.pix.sizeimage;
 		vb->field = field;
 
-		ret = videobuf_iolock(vq, vb, NULL);;
+		ret = videobuf_iolock(vq, vb, NULL);
 		if (ret < 0)
 			return ret;
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/davinci/vpif.c linux-libre-2.6.38-gnu1/drivers/media/video/davinci/vpif.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/davinci/vpif.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/davinci/vpif.c	2011-03-14 21:20:32.000000000 -0400
@@ -41,6 +41,183 @@ spinlock_t vpif_lock;
 
 void __iomem *vpif_base;
 
+/**
+ * ch_params: video standard configuration parameters for vpif
+ * The table must include all presets from supported subdevices.
+ */
+const struct vpif_channel_config_params ch_params[] = {
+	/* HDTV formats */
+	{
+		.name = "480p59_94",
+		.width = 720,
+		.height = 480,
+		.frm_fmt = 1,
+		.ycmux_mode = 0,
+		.eav2sav = 138-8,
+		.sav2eav = 720,
+		.l1 = 1,
+		.l3 = 43,
+		.l5 = 523,
+		.vsize = 525,
+		.capture_format = 0,
+		.vbi_supported = 0,
+		.hd_sd = 1,
+		.dv_preset = V4L2_DV_480P59_94,
+	},
+	{
+		.name = "576p50",
+		.width = 720,
+		.height = 576,
+		.frm_fmt = 1,
+		.ycmux_mode = 0,
+		.eav2sav = 144-8,
+		.sav2eav = 720,
+		.l1 = 1,
+		.l3 = 45,
+		.l5 = 621,
+		.vsize = 625,
+		.capture_format = 0,
+		.vbi_supported = 0,
+		.hd_sd = 1,
+		.dv_preset = V4L2_DV_576P50,
+	},
+	{
+		.name = "720p50",
+		.width = 1280,
+		.height = 720,
+		.frm_fmt = 1,
+		.ycmux_mode = 0,
+		.eav2sav = 700-8,
+		.sav2eav = 1280,
+		.l1 = 1,
+		.l3 = 26,
+		.l5 = 746,
+		.vsize = 750,
+		.capture_format = 0,
+		.vbi_supported = 0,
+		.hd_sd = 1,
+		.dv_preset = V4L2_DV_720P50,
+	},
+	{
+		.name = "720p60",
+		.width = 1280,
+		.height = 720,
+		.frm_fmt = 1,
+		.ycmux_mode = 0,
+		.eav2sav = 370 - 8,
+		.sav2eav = 1280,
+		.l1 = 1,
+		.l3 = 26,
+		.l5 = 746,
+		.vsize = 750,
+		.capture_format = 0,
+		.vbi_supported = 0,
+		.hd_sd = 1,
+		.dv_preset = V4L2_DV_720P60,
+	},
+	{
+		.name = "1080I50",
+		.width = 1920,
+		.height = 1080,
+		.frm_fmt = 0,
+		.ycmux_mode = 0,
+		.eav2sav = 720 - 8,
+		.sav2eav = 1920,
+		.l1 = 1,
+		.l3 = 21,
+		.l5 = 561,
+		.l7 = 563,
+		.l9 = 584,
+		.l11 = 1124,
+		.vsize = 1125,
+		.capture_format = 0,
+		.vbi_supported = 0,
+		.hd_sd = 1,
+		.dv_preset = V4L2_DV_1080I50,
+	},
+	{
+		.name = "1080I60",
+		.width = 1920,
+		.height = 1080,
+		.frm_fmt = 0,
+		.ycmux_mode = 0,
+		.eav2sav = 280 - 8,
+		.sav2eav = 1920,
+		.l1 = 1,
+		.l3 = 21,
+		.l5 = 561,
+		.l7 = 563,
+		.l9 = 584,
+		.l11 = 1124,
+		.vsize = 1125,
+		.capture_format = 0,
+		.vbi_supported = 0,
+		.hd_sd = 1,
+		.dv_preset = V4L2_DV_1080I60,
+	},
+	{
+		.name = "1080p60",
+		.width = 1920,
+		.height = 1080,
+		.frm_fmt = 1,
+		.ycmux_mode = 0,
+		.eav2sav = 280 - 8,
+		.sav2eav = 1920,
+		.l1 = 1,
+		.l3 = 42,
+		.l5 = 1122,
+		.vsize = 1125,
+		.capture_format = 0,
+		.vbi_supported = 0,
+		.hd_sd = 1,
+		.dv_preset = V4L2_DV_1080P60,
+	},
+
+	/* SDTV formats */
+	{
+		.name = "NTSC_M",
+		.width = 720,
+		.height = 480,
+		.frm_fmt = 0,
+		.ycmux_mode = 1,
+		.eav2sav = 268,
+		.sav2eav = 1440,
+		.l1 = 1,
+		.l3 = 23,
+		.l5 = 263,
+		.l7 = 266,
+		.l9 = 286,
+		.l11 = 525,
+		.vsize = 525,
+		.capture_format = 0,
+		.vbi_supported = 1,
+		.hd_sd = 0,
+		.stdid = V4L2_STD_525_60,
+	},
+	{
+		.name = "PAL_BDGHIK",
+		.width = 720,
+		.height = 576,
+		.frm_fmt = 0,
+		.ycmux_mode = 1,
+		.eav2sav = 280,
+		.sav2eav = 1440,
+		.l1 = 1,
+		.l3 = 23,
+		.l5 = 311,
+		.l7 = 313,
+		.l9 = 336,
+		.l11 = 624,
+		.vsize = 625,
+		.capture_format = 0,
+		.vbi_supported = 1,
+		.hd_sd = 0,
+		.stdid = V4L2_STD_625_50,
+	},
+};
+
+const unsigned int vpif_ch_params_count = ARRAY_SIZE(ch_params);
+
 static inline void vpif_wr_bit(u32 reg, u32 bit, u32 val)
 {
 	if (val)
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/davinci/vpif_capture.c linux-libre-2.6.38-gnu1/drivers/media/video/davinci/vpif_capture.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/davinci/vpif_capture.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/davinci/vpif_capture.c	2011-03-14 21:20:32.000000000 -0400
@@ -37,6 +37,7 @@
 #include <linux/slab.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-ioctl.h>
+#include <media/v4l2-chip-ident.h>
 
 #include "vpif_capture.h"
 #include "vpif.h"
@@ -81,20 +82,6 @@ static struct vpif_device vpif_obj = { {
 static struct device *vpif_dev;
 
 /**
- * ch_params: video standard configuration parameters for vpif
- */
-static const struct vpif_channel_config_params ch_params[] = {
-	{
-		"NTSC_M", 720, 480, 30, 0, 1, 268, 1440, 1, 23, 263, 266,
-		286, 525, 525, 0, 1, 0, V4L2_STD_525_60,
-	},
-	{
-		"PAL_BDGHIK", 720, 576, 25, 0, 1, 280, 1440, 1, 23, 311, 313,
-		336, 624, 625, 0, 1, 0, V4L2_STD_625_50,
-	},
-};
-
-/**
  * vpif_uservirt_to_phys : translate user/virtual address to phy address
  * @virtp: user/virtual address
  *
@@ -342,7 +329,7 @@ static void vpif_schedule_next_buffer(st
  * @dev_id: dev_id ptr
  *
  * It changes status of the captured buffer, takes next buffer from the queue
- * and sets its address in VPIF  registers
+ * and sets its address in VPIF registers
  */
 static irqreturn_t vpif_channel_isr(int irq, void *dev_id)
 {
@@ -435,24 +422,31 @@ static int vpif_update_std_info(struct c
 	struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];
 	struct vpif_params *vpifparams = &ch->vpifparams;
 	const struct vpif_channel_config_params *config;
-	struct vpif_channel_config_params *std_info;
+	struct vpif_channel_config_params *std_info = &vpifparams->std_info;
 	struct video_obj *vid_ch = &ch->video;
 	int index;
 
 	vpif_dbg(2, debug, "vpif_update_std_info\n");
 
-	std_info = &vpifparams->std_info;
-
-	for (index = 0; index < ARRAY_SIZE(ch_params); index++) {
+	for (index = 0; index < vpif_ch_params_count; index++) {
 		config = &ch_params[index];
-		if (config->stdid & vid_ch->stdid) {
-			memcpy(std_info, config, sizeof(*config));
-			break;
+		if (config->hd_sd == 0) {
+			vpif_dbg(2, debug, "SD format\n");
+			if (config->stdid & vid_ch->stdid) {
+				memcpy(std_info, config, sizeof(*config));
+				break;
+			}
+		} else {
+			vpif_dbg(2, debug, "HD format\n");
+			if (config->dv_preset == vid_ch->dv_preset) {
+				memcpy(std_info, config, sizeof(*config));
+				break;
+			}
 		}
 	}
 
 	/* standard not found */
-	if (index == ARRAY_SIZE(ch_params))
+	if (index == vpif_ch_params_count)
 		return -EINVAL;
 
 	common->fmt.fmt.pix.width = std_info->width;
@@ -462,6 +456,7 @@ static int vpif_update_std_info(struct c
 	common->fmt.fmt.pix.bytesperline = std_info->width;
 	vpifparams->video_params.hpitch = std_info->width;
 	vpifparams->video_params.storage_mode = std_info->frm_fmt;
+
 	return 0;
 }
 
@@ -757,7 +752,7 @@ static int vpif_open(struct file *filep)
 	struct video_obj *vid_ch;
 	struct channel_obj *ch;
 	struct vpif_fh *fh;
-	int i, ret = 0;
+	int i;
 
 	vpif_dbg(2, debug, "vpif_open\n");
 
@@ -766,9 +761,6 @@ static int vpif_open(struct file *filep)
 	vid_ch = &ch->video;
 	common = &ch->common[VPIF_VIDEO_INDEX];
 
-	if (mutex_lock_interruptible(&common->lock))
-		return -ERESTARTSYS;
-
 	if (NULL == ch->curr_subdev_info) {
 		/**
 		 * search through the sub device to see a registered
@@ -785,8 +777,7 @@ static int vpif_open(struct file *filep)
 		}
 		if (i == config->subdev_count) {
 			vpif_err("No sub device registered\n");
-			ret = -ENOENT;
-			goto exit;
+			return -ENOENT;
 		}
 	}
 
@@ -794,8 +785,7 @@ static int vpif_open(struct file *filep)
 	fh = kzalloc(sizeof(struct vpif_fh), GFP_KERNEL);
 	if (NULL == fh) {
 		vpif_err("unable to allocate memory for file handle object\n");
-		ret = -ENOMEM;
-		goto exit;
+		return -ENOMEM;
 	}
 
 	/* store pointer to fh in private_data member of filep */
@@ -815,9 +805,7 @@ static int vpif_open(struct file *filep)
 	/* Initialize priority of this instance to default priority */
 	fh->prio = V4L2_PRIORITY_UNSET;
 	v4l2_prio_open(&ch->prio, &fh->prio);
-exit:
-	mutex_unlock(&common->lock);
-	return ret;
+	return 0;
 }
 
 /**
@@ -837,9 +825,6 @@ static int vpif_release(struct file *fil
 
 	common = &ch->common[VPIF_VIDEO_INDEX];
 
-	if (mutex_lock_interruptible(&common->lock))
-		return -ERESTARTSYS;
-
 	/* if this instance is doing IO */
 	if (fh->io_allowed[VPIF_VIDEO_INDEX]) {
 		/* Reset io_usrs member of channel object */
@@ -863,9 +848,6 @@ static int vpif_release(struct file *fil
 	/* Decrement channel usrs counter */
 	ch->usrs--;
 
-	/* unlock mutex on channel object */
-	mutex_unlock(&common->lock);
-
 	/* Close the priority */
 	v4l2_prio_close(&ch->prio, fh->prio);
 
@@ -890,7 +872,6 @@ static int vpif_reqbufs(struct file *fil
 	struct channel_obj *ch = fh->channel;
 	struct common_obj *common;
 	u8 index = 0;
-	int ret = 0;
 
 	vpif_dbg(2, debug, "vpif_reqbufs\n");
 
@@ -913,13 +894,8 @@ static int vpif_reqbufs(struct file *fil
 
 	common = &ch->common[index];
 
-	if (mutex_lock_interruptible(&common->lock))
-		return -ERESTARTSYS;
-
-	if (0 != common->io_usrs) {
-		ret = -EBUSY;
-		goto reqbuf_exit;
-	}
+	if (0 != common->io_usrs)
+		return -EBUSY;
 
 	/* Initialize videobuf queue as per the buffer type */
 	videobuf_queue_dma_contig_init(&common->buffer_queue,
@@ -928,7 +904,7 @@ static int vpif_reqbufs(struct file *fil
 					    reqbuf->type,
 					    common->fmt.fmt.pix.field,
 					    sizeof(struct videobuf_buffer), fh,
-					    NULL);
+					    &common->lock);
 
 	/* Set io allowed member of file handle to TRUE */
 	fh->io_allowed[index] = 1;
@@ -939,11 +915,7 @@ static int vpif_reqbufs(struct file *fil
 	INIT_LIST_HEAD(&common->dma_queue);
 
 	/* Allocate buffers */
-	ret = videobuf_reqbufs(&common->buffer_queue, reqbuf);
-
-reqbuf_exit:
-	mutex_unlock(&common->lock);
-	return ret;
+	return videobuf_reqbufs(&common->buffer_queue, reqbuf);
 }
 
 /**
@@ -1157,11 +1129,6 @@ static int vpif_streamon(struct file *fi
 		return ret;
 	}
 
-	if (mutex_lock_interruptible(&common->lock)) {
-		ret = -ERESTARTSYS;
-		goto streamoff_exit;
-	}
-
 	/* If buffer queue is empty, return error */
 	if (list_empty(&common->dma_queue)) {
 		vpif_dbg(1, debug, "buffer queue is empty\n");
@@ -1240,13 +1207,10 @@ static int vpif_streamon(struct file *fi
 		enable_channel1(1);
 	}
 	channel_first_int[VPIF_VIDEO_INDEX][ch->channel_id] = 1;
-	mutex_unlock(&common->lock);
 	return ret;
 
 exit:
-	mutex_unlock(&common->lock);
-streamoff_exit:
-	ret = videobuf_streamoff(&common->buffer_queue);
+	videobuf_streamoff(&common->buffer_queue);
 	return ret;
 }
 
@@ -1284,9 +1248,6 @@ static int vpif_streamoff(struct file *f
 		return -EINVAL;
 	}
 
-	if (mutex_lock_interruptible(&common->lock))
-		return -ERESTARTSYS;
-
 	/* disable channel */
 	if (VPIF_CHANNEL0_VIDEO == ch->channel_id) {
 		enable_channel0(0);
@@ -1304,8 +1265,6 @@ static int vpif_streamoff(struct file *f
 	if (ret && (ret != -ENOIOCTLCMD))
 		vpif_dbg(1, debug, "stream off failed in subdev\n");
 
-	mutex_unlock(&common->lock);
-
 	return videobuf_streamoff(&common->buffer_queue);
 }
 
@@ -1381,21 +1340,16 @@ static int vpif_querystd(struct file *fi
 {
 	struct vpif_fh *fh = priv;
 	struct channel_obj *ch = fh->channel;
-	struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];
 	int ret = 0;
 
 	vpif_dbg(2, debug, "vpif_querystd\n");
 
-	if (mutex_lock_interruptible(&common->lock))
-		return -ERESTARTSYS;
-
 	/* Call querystd function of decoder device */
 	ret = v4l2_subdev_call(vpif_obj.sd[ch->curr_sd_index], video,
 				querystd, std_id);
 	if (ret < 0)
 		vpif_dbg(1, debug, "Failed to set standard for sub devices\n");
 
-	mutex_unlock(&common->lock);
 	return ret;
 }
 
@@ -1451,16 +1405,14 @@ static int vpif_s_std(struct file *file,
 	fh->initialized = 1;
 
 	/* Call encoder subdevice function to set the standard */
-	if (mutex_lock_interruptible(&common->lock))
-		return -ERESTARTSYS;
-
 	ch->video.stdid = *std_id;
+	ch->video.dv_preset = V4L2_DV_INVALID;
+	memset(&ch->video.bt_timings, 0, sizeof(ch->video.bt_timings));
 
 	/* Get the information about the standard */
 	if (vpif_update_std_info(ch)) {
-		ret = -EINVAL;
 		vpif_err("Error getting the standard info\n");
-		goto s_std_exit;
+		return -EINVAL;
 	}
 
 	/* Configure the default format information */
@@ -1471,9 +1423,6 @@ static int vpif_s_std(struct file *file,
 				s_std, *std_id);
 	if (ret < 0)
 		vpif_dbg(1, debug, "Failed to set standard for sub devices\n");
-
-s_std_exit:
-	mutex_unlock(&common->lock);
 	return ret;
 }
 
@@ -1567,9 +1516,6 @@ static int vpif_s_input(struct file *fil
 		return -EINVAL;
 	}
 
-	if (mutex_lock_interruptible(&common->lock))
-		return -ERESTARTSYS;
-
 	/* first setup input path from sub device to vpif */
 	if (config->setup_input_path) {
 		ret = config->setup_input_path(ch->channel_id,
@@ -1578,7 +1524,7 @@ static int vpif_s_input(struct file *fil
 			vpif_dbg(1, debug, "couldn't setup input path for the"
 				" sub device %s, for input index %d\n",
 				subdev_info->name, index);
-			goto exit;
+			return ret;
 		}
 	}
 
@@ -1589,7 +1535,7 @@ static int vpif_s_input(struct file *fil
 					input, output, 0);
 		if (ret < 0) {
 			vpif_dbg(1, debug, "Failed to set input\n");
-			goto exit;
+			return ret;
 		}
 	}
 	vid_ch->input_idx = index;
@@ -1600,9 +1546,6 @@ static int vpif_s_input(struct file *fil
 
 	/* update tvnorms from the sub device input info */
 	ch->video_dev->tvnorms = chan_cfg->inputs[index].input.std;
-
-exit:
-	mutex_unlock(&common->lock);
 	return ret;
 }
 
@@ -1671,11 +1614,7 @@ static int vpif_g_fmt_vid_cap(struct fil
 		return -EINVAL;
 
 	/* Fill in the information about format */
-	if (mutex_lock_interruptible(&common->lock))
-		return -ERESTARTSYS;
-
 	*fmt = common->fmt;
-	mutex_unlock(&common->lock);
 	return 0;
 }
 
@@ -1694,7 +1633,7 @@ static int vpif_s_fmt_vid_cap(struct fil
 	struct v4l2_pix_format *pixfmt;
 	int ret = 0;
 
-	vpif_dbg(2, debug, "VIDIOC_S_FMT\n");
+	vpif_dbg(2, debug, "%s\n", __func__);
 
 	/* If streaming is started, return error */
 	if (common->started) {
@@ -1723,12 +1662,7 @@ static int vpif_s_fmt_vid_cap(struct fil
 	if (ret)
 		return ret;
 	/* store the format in the channel object */
-	if (mutex_lock_interruptible(&common->lock))
-		return -ERESTARTSYS;
-
 	common->fmt = *fmt;
-	mutex_unlock(&common->lock);
-
 	return 0;
 }
 
@@ -1807,6 +1741,306 @@ static int vpif_cropcap(struct file *fil
 	return 0;
 }
 
+/**
+ * vpif_enum_dv_presets() - ENUM_DV_PRESETS handler
+ * @file: file ptr
+ * @priv: file handle
+ * @preset: input preset
+ */
+static int vpif_enum_dv_presets(struct file *file, void *priv,
+		struct v4l2_dv_enum_preset *preset)
+{
+	struct vpif_fh *fh = priv;
+	struct channel_obj *ch = fh->channel;
+
+	return v4l2_subdev_call(vpif_obj.sd[ch->curr_sd_index],
+			video, enum_dv_presets, preset);
+}
+
+/**
+ * vpif_query_dv_presets() - QUERY_DV_PRESET handler
+ * @file: file ptr
+ * @priv: file handle
+ * @preset: input preset
+ */
+static int vpif_query_dv_preset(struct file *file, void *priv,
+		struct v4l2_dv_preset *preset)
+{
+	struct vpif_fh *fh = priv;
+	struct channel_obj *ch = fh->channel;
+
+	return v4l2_subdev_call(vpif_obj.sd[ch->curr_sd_index],
+		       video, query_dv_preset, preset);
+}
+/**
+ * vpif_s_dv_presets() - S_DV_PRESETS handler
+ * @file: file ptr
+ * @priv: file handle
+ * @preset: input preset
+ */
+static int vpif_s_dv_preset(struct file *file, void *priv,
+		struct v4l2_dv_preset *preset)
+{
+	struct vpif_fh *fh = priv;
+	struct channel_obj *ch = fh->channel;
+	struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];
+	int ret = 0;
+
+	if (common->started) {
+		vpif_dbg(1, debug, "streaming in progress\n");
+		return -EBUSY;
+	}
+
+	if ((VPIF_CHANNEL0_VIDEO == ch->channel_id) ||
+	    (VPIF_CHANNEL1_VIDEO == ch->channel_id)) {
+		if (!fh->initialized) {
+			vpif_dbg(1, debug, "Channel Busy\n");
+			return -EBUSY;
+		}
+	}
+
+	ret = v4l2_prio_check(&ch->prio, fh->prio);
+	if (ret)
+		return ret;
+
+	fh->initialized = 1;
+
+	/* Call encoder subdevice function to set the standard */
+	if (mutex_lock_interruptible(&common->lock))
+		return -ERESTARTSYS;
+
+	ch->video.dv_preset = preset->preset;
+	ch->video.stdid = V4L2_STD_UNKNOWN;
+	memset(&ch->video.bt_timings, 0, sizeof(ch->video.bt_timings));
+
+	/* Get the information about the standard */
+	if (vpif_update_std_info(ch)) {
+		vpif_dbg(1, debug, "Error getting the standard info\n");
+		ret = -EINVAL;
+	} else {
+		/* Configure the default format information */
+		vpif_config_format(ch);
+
+		ret = v4l2_subdev_call(vpif_obj.sd[ch->curr_sd_index],
+				video, s_dv_preset, preset);
+	}
+
+	mutex_unlock(&common->lock);
+
+	return ret;
+}
+/**
+ * vpif_g_dv_presets() - G_DV_PRESETS handler
+ * @file: file ptr
+ * @priv: file handle
+ * @preset: input preset
+ */
+static int vpif_g_dv_preset(struct file *file, void *priv,
+		struct v4l2_dv_preset *preset)
+{
+	struct vpif_fh *fh = priv;
+	struct channel_obj *ch = fh->channel;
+
+	preset->preset = ch->video.dv_preset;
+
+	return 0;
+}
+
+/**
+ * vpif_s_dv_timings() - S_DV_TIMINGS handler
+ * @file: file ptr
+ * @priv: file handle
+ * @timings: digital video timings
+ */
+static int vpif_s_dv_timings(struct file *file, void *priv,
+		struct v4l2_dv_timings *timings)
+{
+	struct vpif_fh *fh = priv;
+	struct channel_obj *ch = fh->channel;
+	struct vpif_params *vpifparams = &ch->vpifparams;
+	struct vpif_channel_config_params *std_info = &vpifparams->std_info;
+	struct video_obj *vid_ch = &ch->video;
+	struct v4l2_bt_timings *bt = &vid_ch->bt_timings;
+	int ret;
+
+	if (timings->type != V4L2_DV_BT_656_1120) {
+		vpif_dbg(2, debug, "Timing type not defined\n");
+		return -EINVAL;
+	}
+
+	/* Configure subdevice timings, if any */
+	ret = v4l2_subdev_call(vpif_obj.sd[ch->curr_sd_index],
+			video, s_dv_timings, timings);
+	if (ret == -ENOIOCTLCMD) {
+		vpif_dbg(2, debug, "Custom DV timings not supported by "
+				"subdevice\n");
+		return -EINVAL;
+	}
+	if (ret < 0) {
+		vpif_dbg(2, debug, "Error setting custom DV timings\n");
+		return ret;
+	}
+
+	if (!(timings->bt.width && timings->bt.height &&
+				(timings->bt.hbackporch ||
+				 timings->bt.hfrontporch ||
+				 timings->bt.hsync) &&
+				timings->bt.vfrontporch &&
+				(timings->bt.vbackporch ||
+				 timings->bt.vsync))) {
+		vpif_dbg(2, debug, "Timings for width, height, "
+				"horizontal back porch, horizontal sync, "
+				"horizontal front porch, vertical back porch, "
+				"vertical sync and vertical back porch "
+				"must be defined\n");
+		return -EINVAL;
+	}
+
+	*bt = timings->bt;
+
+	/* Configure video port timings */
+
+	std_info->eav2sav = bt->hbackporch + bt->hfrontporch +
+		bt->hsync - 8;
+	std_info->sav2eav = bt->width;
+
+	std_info->l1 = 1;
+	std_info->l3 = bt->vsync + bt->vbackporch + 1;
+
+	if (bt->interlaced) {
+		if (bt->il_vbackporch || bt->il_vfrontporch || bt->il_vsync) {
+			std_info->vsize = bt->height * 2 +
+				bt->vfrontporch + bt->vsync + bt->vbackporch +
+				bt->il_vfrontporch + bt->il_vsync +
+				bt->il_vbackporch;
+			std_info->l5 = std_info->vsize/2 -
+				(bt->vfrontporch - 1);
+			std_info->l7 = std_info->vsize/2 + 1;
+			std_info->l9 = std_info->l7 + bt->il_vsync +
+				bt->il_vbackporch + 1;
+			std_info->l11 = std_info->vsize -
+				(bt->il_vfrontporch - 1);
+		} else {
+			vpif_dbg(2, debug, "Required timing values for "
+					"interlaced BT format missing\n");
+			return -EINVAL;
+		}
+	} else {
+		std_info->vsize = bt->height + bt->vfrontporch +
+			bt->vsync + bt->vbackporch;
+		std_info->l5 = std_info->vsize - (bt->vfrontporch - 1);
+	}
+	strncpy(std_info->name, "Custom timings BT656/1120", VPIF_MAX_NAME);
+	std_info->width = bt->width;
+	std_info->height = bt->height;
+	std_info->frm_fmt = bt->interlaced ? 0 : 1;
+	std_info->ycmux_mode = 0;
+	std_info->capture_format = 0;
+	std_info->vbi_supported = 0;
+	std_info->hd_sd = 1;
+	std_info->stdid = 0;
+	std_info->dv_preset = V4L2_DV_INVALID;
+
+	vid_ch->stdid = 0;
+	vid_ch->dv_preset = V4L2_DV_INVALID;
+	return 0;
+}
+
+/**
+ * vpif_g_dv_timings() - G_DV_TIMINGS handler
+ * @file: file ptr
+ * @priv: file handle
+ * @timings: digital video timings
+ */
+static int vpif_g_dv_timings(struct file *file, void *priv,
+		struct v4l2_dv_timings *timings)
+{
+	struct vpif_fh *fh = priv;
+	struct channel_obj *ch = fh->channel;
+	struct video_obj *vid_ch = &ch->video;
+	struct v4l2_bt_timings *bt = &vid_ch->bt_timings;
+
+	timings->bt = *bt;
+
+	return 0;
+}
+
+/*
+ * vpif_g_chip_ident() - Identify the chip
+ * @file: file ptr
+ * @priv: file handle
+ * @chip: chip identity
+ *
+ * Returns zero or -EINVAL if read operations fails.
+ */
+static int vpif_g_chip_ident(struct file *file, void *priv,
+		struct v4l2_dbg_chip_ident *chip)
+{
+	chip->ident = V4L2_IDENT_NONE;
+	chip->revision = 0;
+	if (chip->match.type != V4L2_CHIP_MATCH_I2C_DRIVER &&
+			chip->match.type != V4L2_CHIP_MATCH_I2C_ADDR) {
+		vpif_dbg(2, debug, "match_type is invalid.\n");
+		return -EINVAL;
+	}
+
+	return v4l2_device_call_until_err(&vpif_obj.v4l2_dev, 0, core,
+			g_chip_ident, chip);
+}
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+/*
+ * vpif_dbg_g_register() - Read register
+ * @file: file ptr
+ * @priv: file handle
+ * @reg: register to be read
+ *
+ * Debugging only
+ * Returns zero or -EINVAL if read operations fails.
+ */
+static int vpif_dbg_g_register(struct file *file, void *priv,
+		struct v4l2_dbg_register *reg){
+	struct vpif_fh *fh = priv;
+	struct channel_obj *ch = fh->channel;
+
+	return v4l2_subdev_call(vpif_obj.sd[ch->curr_sd_index], core,
+			g_register, reg);
+}
+
+/*
+ * vpif_dbg_s_register() - Write to register
+ * @file: file ptr
+ * @priv: file handle
+ * @reg: register to be modified
+ *
+ * Debugging only
+ * Returns zero or -EINVAL if write operations fails.
+ */
+static int vpif_dbg_s_register(struct file *file, void *priv,
+		struct v4l2_dbg_register *reg){
+	struct vpif_fh *fh = priv;
+	struct channel_obj *ch = fh->channel;
+
+	return v4l2_subdev_call(vpif_obj.sd[ch->curr_sd_index], core,
+			s_register, reg);
+}
+#endif
+
+/*
+ * vpif_log_status() - Status information
+ * @file: file ptr
+ * @priv: file handle
+ *
+ * Returns zero.
+ */
+static int vpif_log_status(struct file *filep, void *priv)
+{
+	/* status for sub devices */
+	v4l2_device_call_all(&vpif_obj.v4l2_dev, 0, core, log_status);
+
+	return 0;
+}
+
 /* vpif capture ioctl operations */
 static const struct v4l2_ioctl_ops vpif_ioctl_ops = {
 	.vidioc_querycap        	= vpif_querycap,
@@ -1829,6 +2063,18 @@ static const struct v4l2_ioctl_ops vpif_
 	.vidioc_streamon        	= vpif_streamon,
 	.vidioc_streamoff       	= vpif_streamoff,
 	.vidioc_cropcap         	= vpif_cropcap,
+	.vidioc_enum_dv_presets         = vpif_enum_dv_presets,
+	.vidioc_s_dv_preset             = vpif_s_dv_preset,
+	.vidioc_g_dv_preset             = vpif_g_dv_preset,
+	.vidioc_query_dv_preset         = vpif_query_dv_preset,
+	.vidioc_s_dv_timings            = vpif_s_dv_timings,
+	.vidioc_g_dv_timings            = vpif_g_dv_timings,
+	.vidioc_g_chip_ident		= vpif_g_chip_ident,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+	.vidioc_g_register		= vpif_dbg_g_register,
+	.vidioc_s_register		= vpif_dbg_s_register,
+#endif
+	.vidioc_log_status		= vpif_log_status,
 };
 
 /* vpif file operations */
@@ -1836,7 +2082,7 @@ static struct v4l2_file_operations vpif_
 	.owner = THIS_MODULE,
 	.open = vpif_open,
 	.release = vpif_release,
-	.ioctl = video_ioctl2,
+	.unlocked_ioctl = video_ioctl2,
 	.mmap = vpif_mmap,
 	.poll = vpif_poll
 };
@@ -1979,6 +2225,7 @@ static __init int vpif_probe(struct plat
 		common = &(ch->common[VPIF_VIDEO_INDEX]);
 		spin_lock_init(&common->irqlock);
 		mutex_init(&common->lock);
+		ch->video_dev->lock = &common->lock;
 		/* Initialize prio member of channel object */
 		v4l2_prio_init(&ch->prio);
 		err = video_register_device(ch->video_dev,
@@ -2026,9 +2273,9 @@ static __init int vpif_probe(struct plat
 		if (vpif_obj.sd[i])
 			vpif_obj.sd[i]->grp_id = 1 << i;
 	}
-	v4l2_info(&vpif_obj.v4l2_dev, "DM646x VPIF Capture driver"
-		  " initialized\n");
 
+	v4l2_info(&vpif_obj.v4l2_dev,
+			"DM646x VPIF capture driver initialized\n");
 	return 0;
 
 probe_subdev_out:
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/davinci/vpif_capture.h linux-libre-2.6.38-gnu1/drivers/media/video/davinci/vpif_capture.h
--- linux-libre-2.6.37-gnu1/drivers/media/video/davinci/vpif_capture.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/davinci/vpif_capture.h	2011-03-14 21:20:32.000000000 -0400
@@ -59,6 +59,8 @@ struct video_obj {
 	enum v4l2_field buf_field;
 	/* Currently selected or default standard */
 	v4l2_std_id stdid;
+	u32 dv_preset;
+	struct v4l2_bt_timings bt_timings;
 	/* This is to track the last input that is passed to application */
 	u32 input_idx;
 };
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/davinci/vpif_display.c linux-libre-2.6.38-gnu1/drivers/media/video/davinci/vpif_display.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/davinci/vpif_display.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/davinci/vpif_display.c	2011-03-14 21:20:32.000000000 -0400
@@ -38,6 +38,7 @@
 #include <media/adv7343.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-ioctl.h>
+#include <media/v4l2-chip-ident.h>
 
 #include <mach/dm646x.h>
 
@@ -84,17 +85,6 @@ static struct vpif_config_params config_
 static struct vpif_device vpif_obj = { {NULL} };
 static struct device *vpif_dev;
 
-static const struct vpif_channel_config_params ch_params[] = {
-	{
-		"NTSC", 720, 480, 30, 0, 1, 268, 1440, 1, 23, 263, 266,
-		286, 525, 525, 0, 1, 0, V4L2_STD_525_60,
-	},
-	{
-		"PAL", 720, 576, 25, 0, 1, 280, 1440, 1, 23, 311, 313,
-		336, 624, 625, 0, 1, 0, V4L2_STD_625_50,
-	},
-};
-
 /*
  * vpif_uservirt_to_phys: This function is used to convert user
  * space virtual address to physical address.
@@ -373,30 +363,54 @@ static irqreturn_t vpif_channel_isr(int
 	return IRQ_HANDLED;
 }
 
-static int vpif_get_std_info(struct channel_obj *ch)
+static int vpif_update_std_info(struct channel_obj *ch)
 {
-	struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];
 	struct video_obj *vid_ch = &ch->video;
 	struct vpif_params *vpifparams = &ch->vpifparams;
 	struct vpif_channel_config_params *std_info = &vpifparams->std_info;
 	const struct vpif_channel_config_params *config;
 
-	int index;
-
-	std_info->stdid = vid_ch->stdid;
-	if (!std_info->stdid)
-		return -1;
+	int i;
 
-	for (index = 0; index < ARRAY_SIZE(ch_params); index++) {
-		config = &ch_params[index];
-		if (config->stdid & std_info->stdid) {
-			memcpy(std_info, config, sizeof(*config));
-			break;
+	for (i = 0; i < vpif_ch_params_count; i++) {
+		config = &ch_params[i];
+		if (config->hd_sd == 0) {
+			vpif_dbg(2, debug, "SD format\n");
+			if (config->stdid & vid_ch->stdid) {
+				memcpy(std_info, config, sizeof(*config));
+				break;
+			}
+		} else {
+			vpif_dbg(2, debug, "HD format\n");
+			if (config->dv_preset == vid_ch->dv_preset) {
+				memcpy(std_info, config, sizeof(*config));
+				break;
+			}
 		}
 	}
 
-	if (index == ARRAY_SIZE(ch_params))
-		return -1;
+	if (i == vpif_ch_params_count) {
+		vpif_dbg(1, debug, "Format not found\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int vpif_update_resolution(struct channel_obj *ch)
+{
+	struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];
+	struct video_obj *vid_ch = &ch->video;
+	struct vpif_params *vpifparams = &ch->vpifparams;
+	struct vpif_channel_config_params *std_info = &vpifparams->std_info;
+
+	if (!vid_ch->stdid && !vid_ch->dv_preset && !vid_ch->bt_timings.height)
+		return -EINVAL;
+
+	if (vid_ch->stdid || vid_ch->dv_preset) {
+		if (vpif_update_std_info(ch))
+			return -EINVAL;
+	}
 
 	common->fmt.fmt.pix.width = std_info->width;
 	common->fmt.fmt.pix.height = std_info->height;
@@ -404,8 +418,8 @@ static int vpif_get_std_info(struct chan
 			common->fmt.fmt.pix.width, common->fmt.fmt.pix.height);
 
 	/* Set height and width paramateres */
-	ch->common[VPIF_VIDEO_INDEX].height = std_info->height;
-	ch->common[VPIF_VIDEO_INDEX].width = std_info->width;
+	common->height = std_info->height;
+	common->width = std_info->width;
 
 	return 0;
 }
@@ -516,10 +530,8 @@ static int vpif_check_format(struct chan
 	else
 		sizeimage = config_params.channel_bufsize[ch->channel_id];
 
-	if (vpif_get_std_info(ch)) {
-		vpif_err("Error getting the standard info\n");
+	if (vpif_update_resolution(ch))
 		return -EINVAL;
-	}
 
 	hpitch = pixfmt->bytesperline;
 	vpitch = sizeimage / (hpitch * 2);
@@ -568,7 +580,10 @@ static void vpif_config_addr(struct chan
 static int vpif_mmap(struct file *filep, struct vm_area_struct *vma)
 {
 	struct vpif_fh *fh = filep->private_data;
-	struct common_obj *common = &fh->channel->common[VPIF_VIDEO_INDEX];
+	struct channel_obj *ch = fh->channel;
+	struct common_obj *common = &(ch->common[VPIF_VIDEO_INDEX]);
+
+	vpif_dbg(2, debug, "vpif_mmap\n");
 
 	return videobuf_mmap_mapper(&common->buffer_queue, vma);
 }
@@ -637,9 +652,6 @@ static int vpif_release(struct file *fil
 	struct channel_obj *ch = fh->channel;
 	struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];
 
-	if (mutex_lock_interruptible(&common->lock))
-		return -ERESTARTSYS;
-
 	/* if this instance is doing IO */
 	if (fh->io_allowed[VPIF_VIDEO_INDEX]) {
 		/* Reset io_usrs member of channel object */
@@ -662,8 +674,6 @@ static int vpif_release(struct file *fil
 		    config_params.numbuffers[ch->channel_id];
 	}
 
-	mutex_unlock(&common->lock);
-
 	/* Decrement channel usrs counter */
 	atomic_dec(&ch->usrs);
 	/* If this file handle has initialize encoder device, reset it */
@@ -680,7 +690,12 @@ static int vpif_release(struct file *fil
 }
 
 /* functions implementing ioctls */
-
+/**
+ * vpif_querycap() - QUERYCAP handler
+ * @file: file ptr
+ * @priv: file handle
+ * @cap: ptr to v4l2_capability structure
+ */
 static int vpif_querycap(struct file *file, void  *priv,
 				struct v4l2_capability *cap)
 {
@@ -722,17 +737,9 @@ static int vpif_g_fmt_vid_out(struct fil
 	if (common->fmt.type != fmt->type)
 		return -EINVAL;
 
-	/* Fill in the information about format */
-	if (mutex_lock_interruptible(&common->lock))
-		return -ERESTARTSYS;
-
-	if (vpif_get_std_info(ch)) {
-		vpif_err("Error getting the standard info\n");
+	if (vpif_update_resolution(ch))
 		return -EINVAL;
-	}
-
 	*fmt = common->fmt;
-	mutex_unlock(&common->lock);
 	return 0;
 }
 
@@ -773,12 +780,7 @@ static int vpif_s_fmt_vid_out(struct fil
 	/* store the pix format in the channel object */
 	common->fmt.fmt.pix = *pixfmt;
 	/* store the format in the channel object */
-	if (mutex_lock_interruptible(&common->lock))
-		return -ERESTARTSYS;
-
 	common->fmt = *fmt;
-	mutex_unlock(&common->lock);
-
 	return 0;
 }
 
@@ -808,7 +810,6 @@ static int vpif_reqbufs(struct file *fil
 	struct common_obj *common;
 	enum v4l2_field field;
 	u8 index = 0;
-	int ret = 0;
 
 	/* This file handle has not initialized the channel,
 	   It is not allowed to do settings */
@@ -826,18 +827,12 @@ static int vpif_reqbufs(struct file *fil
 	index = VPIF_VIDEO_INDEX;
 
 	common = &ch->common[index];
-	if (mutex_lock_interruptible(&common->lock))
-		return -ERESTARTSYS;
 
-	if (common->fmt.type != reqbuf->type) {
-		ret = -EINVAL;
-		goto reqbuf_exit;
-	}
+	if (common->fmt.type != reqbuf->type)
+		return -EINVAL;
 
-	if (0 != common->io_usrs) {
-		ret = -EBUSY;
-		goto reqbuf_exit;
-	}
+	if (0 != common->io_usrs)
+		return -EBUSY;
 
 	if (reqbuf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
 		if (common->fmt.fmt.pix.field == V4L2_FIELD_ANY)
@@ -854,7 +849,7 @@ static int vpif_reqbufs(struct file *fil
 					    &common->irqlock,
 					    reqbuf->type, field,
 					    sizeof(struct videobuf_buffer), fh,
-					    NULL);
+					    &common->lock);
 
 	/* Set io allowed member of file handle to TRUE */
 	fh->io_allowed[index] = 1;
@@ -865,11 +860,7 @@ static int vpif_reqbufs(struct file *fil
 	INIT_LIST_HEAD(&common->dma_queue);
 
 	/* Allocate buffers */
-	ret = videobuf_reqbufs(&common->buffer_queue, reqbuf);
-
-reqbuf_exit:
-	mutex_unlock(&common->lock);
-	return ret;
+	return videobuf_reqbufs(&common->buffer_queue, reqbuf);
 }
 
 static int vpif_querybuf(struct file *file, void *priv,
@@ -990,22 +981,19 @@ static int vpif_s_std(struct file *file,
 	}
 
 	/* Call encoder subdevice function to set the standard */
-	if (mutex_lock_interruptible(&common->lock))
-		return -ERESTARTSYS;
-
 	ch->video.stdid = *std_id;
+	ch->video.dv_preset = V4L2_DV_INVALID;
+	memset(&ch->video.bt_timings, 0, sizeof(ch->video.bt_timings));
+
 	/* Get the information about the standard */
-	if (vpif_get_std_info(ch)) {
-		vpif_err("Error getting the standard info\n");
+	if (vpif_update_resolution(ch))
 		return -EINVAL;
-	}
 
 	if ((ch->vpifparams.std_info.width *
 		ch->vpifparams.std_info.height * 2) >
 		config_params.channel_bufsize[ch->channel_id]) {
 		vpif_err("invalid std for this size\n");
-		ret = -EINVAL;
-		goto s_std_exit;
+		return -EINVAL;
 	}
 
 	common->fmt.fmt.pix.bytesperline = common->fmt.fmt.pix.width;
@@ -1016,16 +1004,13 @@ static int vpif_s_std(struct file *file,
 						s_std_output, *std_id);
 	if (ret < 0) {
 		vpif_err("Failed to set output standard\n");
-		goto s_std_exit;
+		return ret;
 	}
 
 	ret = v4l2_device_call_until_err(&vpif_obj.v4l2_dev, 1, core,
 							s_std, *std_id);
 	if (ret < 0)
 		vpif_err("Failed to set standard for sub devices\n");
-
-s_std_exit:
-	mutex_unlock(&common->lock);
 	return ret;
 }
 
@@ -1090,21 +1075,17 @@ static int vpif_streamon(struct file *fi
 	if (ret < 0)
 		return ret;
 
-	/* Call videobuf_streamon to start streaming  in videobuf */
+	/* Call videobuf_streamon to start streaming in videobuf */
 	ret = videobuf_streamon(&common->buffer_queue);
 	if (ret < 0) {
 		vpif_err("videobuf_streamon\n");
 		return ret;
 	}
 
-	if (mutex_lock_interruptible(&common->lock))
-		return -ERESTARTSYS;
-
 	/* If buffer queue is empty, return error */
 	if (list_empty(&common->dma_queue)) {
 		vpif_err("buffer queue is empty\n");
-		ret = -EIO;
-		goto streamon_exit;
+		return -EIO;
 	}
 
 	/* Get the next frame from the buffer queue */
@@ -1130,8 +1111,7 @@ static int vpif_streamon(struct file *fi
 			|| (!ch->vpifparams.std_info.frm_fmt
 			&& (common->fmt.fmt.pix.field == V4L2_FIELD_NONE))) {
 			vpif_err("conflict in field format and std format\n");
-			ret = -EINVAL;
-			goto streamon_exit;
+			return -EINVAL;
 		}
 
 		/* clock settings */
@@ -1140,13 +1120,13 @@ static int vpif_streamon(struct file *fi
 						ch->vpifparams.std_info.hd_sd);
 		if (ret < 0) {
 			vpif_err("can't set clock\n");
-			goto streamon_exit;
+			return ret;
 		}
 
 		/* set the parameters and addresses */
 		ret = vpif_set_video_params(vpif, ch->channel_id + 2);
 		if (ret < 0)
-			goto streamon_exit;
+			return ret;
 
 		common->started = ret;
 		vpif_config_addr(ch, ret);
@@ -1171,9 +1151,6 @@ static int vpif_streamon(struct file *fi
 		}
 		channel_first_int[VPIF_VIDEO_INDEX][ch->channel_id] = 1;
 	}
-
-streamon_exit:
-	mutex_unlock(&common->lock);
 	return ret;
 }
 
@@ -1199,9 +1176,6 @@ static int vpif_streamoff(struct file *f
 		return -EINVAL;
 	}
 
-	if (mutex_lock_interruptible(&common->lock))
-		return -ERESTARTSYS;
-
 	if (buftype == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
 		/* disable channel */
 		if (VPIF_CHANNEL2_VIDEO == ch->channel_id) {
@@ -1216,8 +1190,6 @@ static int vpif_streamoff(struct file *f
 	}
 
 	common->started = 0;
-	mutex_unlock(&common->lock);
-
 	return videobuf_streamoff(&common->buffer_queue);
 }
 
@@ -1264,13 +1236,9 @@ static int vpif_s_output(struct file *fi
 	struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];
 	int ret = 0;
 
-	if (mutex_lock_interruptible(&common->lock))
-		return -ERESTARTSYS;
-
 	if (common->started) {
 		vpif_err("Streaming in progress\n");
-		ret = -EBUSY;
-		goto s_output_exit;
+		return -EBUSY;
 	}
 
 	ret = v4l2_device_call_until_err(&vpif_obj.v4l2_dev, 1, video,
@@ -1280,9 +1248,6 @@ static int vpif_s_output(struct file *fi
 		vpif_err("Failed to set output standard\n");
 
 	vid_ch->output_id = i;
-
-s_output_exit:
-	mutex_unlock(&common->lock);
 	return ret;
 }
 
@@ -1315,6 +1280,287 @@ static int vpif_s_priority(struct file *
 	return v4l2_prio_change(&ch->prio, &fh->prio, p);
 }
 
+/**
+ * vpif_enum_dv_presets() - ENUM_DV_PRESETS handler
+ * @file: file ptr
+ * @priv: file handle
+ * @preset: input preset
+ */
+static int vpif_enum_dv_presets(struct file *file, void *priv,
+		struct v4l2_dv_enum_preset *preset)
+{
+	struct vpif_fh *fh = priv;
+	struct channel_obj *ch = fh->channel;
+	struct video_obj *vid_ch = &ch->video;
+
+	return v4l2_subdev_call(vpif_obj.sd[vid_ch->output_id],
+			video, enum_dv_presets, preset);
+}
+
+/**
+ * vpif_s_dv_presets() - S_DV_PRESETS handler
+ * @file: file ptr
+ * @priv: file handle
+ * @preset: input preset
+ */
+static int vpif_s_dv_preset(struct file *file, void *priv,
+		struct v4l2_dv_preset *preset)
+{
+	struct vpif_fh *fh = priv;
+	struct channel_obj *ch = fh->channel;
+	struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];
+	struct video_obj *vid_ch = &ch->video;
+	int ret = 0;
+
+	if (common->started) {
+		vpif_dbg(1, debug, "streaming in progress\n");
+		return -EBUSY;
+	}
+
+	ret = v4l2_prio_check(&ch->prio, fh->prio);
+	if (ret != 0)
+		return ret;
+
+	fh->initialized = 1;
+
+	/* Call encoder subdevice function to set the standard */
+	if (mutex_lock_interruptible(&common->lock))
+		return -ERESTARTSYS;
+
+	ch->video.dv_preset = preset->preset;
+	ch->video.stdid = V4L2_STD_UNKNOWN;
+	memset(&ch->video.bt_timings, 0, sizeof(ch->video.bt_timings));
+
+	/* Get the information about the standard */
+	if (vpif_update_resolution(ch)) {
+		ret = -EINVAL;
+	} else {
+		/* Configure the default format information */
+		vpif_config_format(ch);
+
+		ret = v4l2_subdev_call(vpif_obj.sd[vid_ch->output_id],
+				video, s_dv_preset, preset);
+	}
+
+	mutex_unlock(&common->lock);
+
+	return ret;
+}
+/**
+ * vpif_g_dv_presets() - G_DV_PRESETS handler
+ * @file: file ptr
+ * @priv: file handle
+ * @preset: input preset
+ */
+static int vpif_g_dv_preset(struct file *file, void *priv,
+		struct v4l2_dv_preset *preset)
+{
+	struct vpif_fh *fh = priv;
+	struct channel_obj *ch = fh->channel;
+
+	preset->preset = ch->video.dv_preset;
+
+	return 0;
+}
+/**
+ * vpif_s_dv_timings() - S_DV_TIMINGS handler
+ * @file: file ptr
+ * @priv: file handle
+ * @timings: digital video timings
+ */
+static int vpif_s_dv_timings(struct file *file, void *priv,
+		struct v4l2_dv_timings *timings)
+{
+	struct vpif_fh *fh = priv;
+	struct channel_obj *ch = fh->channel;
+	struct vpif_params *vpifparams = &ch->vpifparams;
+	struct vpif_channel_config_params *std_info = &vpifparams->std_info;
+	struct video_obj *vid_ch = &ch->video;
+	struct v4l2_bt_timings *bt = &vid_ch->bt_timings;
+	int ret;
+
+	if (timings->type != V4L2_DV_BT_656_1120) {
+		vpif_dbg(2, debug, "Timing type not defined\n");
+		return -EINVAL;
+	}
+
+	/* Configure subdevice timings, if any */
+	ret = v4l2_subdev_call(vpif_obj.sd[vid_ch->output_id],
+			video, s_dv_timings, timings);
+	if (ret == -ENOIOCTLCMD) {
+		vpif_dbg(2, debug, "Custom DV timings not supported by "
+				"subdevice\n");
+		return -EINVAL;
+	}
+	if (ret < 0) {
+		vpif_dbg(2, debug, "Error setting custom DV timings\n");
+		return ret;
+	}
+
+	if (!(timings->bt.width && timings->bt.height &&
+				(timings->bt.hbackporch ||
+				 timings->bt.hfrontporch ||
+				 timings->bt.hsync) &&
+				timings->bt.vfrontporch &&
+				(timings->bt.vbackporch ||
+				 timings->bt.vsync))) {
+		vpif_dbg(2, debug, "Timings for width, height, "
+				"horizontal back porch, horizontal sync, "
+				"horizontal front porch, vertical back porch, "
+				"vertical sync and vertical back porch "
+				"must be defined\n");
+		return -EINVAL;
+	}
+
+	*bt = timings->bt;
+
+	/* Configure video port timings */
+
+	std_info->eav2sav = bt->hbackporch + bt->hfrontporch +
+		bt->hsync - 8;
+	std_info->sav2eav = bt->width;
+
+	std_info->l1 = 1;
+	std_info->l3 = bt->vsync + bt->vbackporch + 1;
+
+	if (bt->interlaced) {
+		if (bt->il_vbackporch || bt->il_vfrontporch || bt->il_vsync) {
+			std_info->vsize = bt->height * 2 +
+				bt->vfrontporch + bt->vsync + bt->vbackporch +
+				bt->il_vfrontporch + bt->il_vsync +
+				bt->il_vbackporch;
+			std_info->l5 = std_info->vsize/2 -
+				(bt->vfrontporch - 1);
+			std_info->l7 = std_info->vsize/2 + 1;
+			std_info->l9 = std_info->l7 + bt->il_vsync +
+				bt->il_vbackporch + 1;
+			std_info->l11 = std_info->vsize -
+				(bt->il_vfrontporch - 1);
+		} else {
+			vpif_dbg(2, debug, "Required timing values for "
+					"interlaced BT format missing\n");
+			return -EINVAL;
+		}
+	} else {
+		std_info->vsize = bt->height + bt->vfrontporch +
+			bt->vsync + bt->vbackporch;
+		std_info->l5 = std_info->vsize - (bt->vfrontporch - 1);
+	}
+	strncpy(std_info->name, "Custom timings BT656/1120",
+			VPIF_MAX_NAME);
+	std_info->width = bt->width;
+	std_info->height = bt->height;
+	std_info->frm_fmt = bt->interlaced ? 0 : 1;
+	std_info->ycmux_mode = 0;
+	std_info->capture_format = 0;
+	std_info->vbi_supported = 0;
+	std_info->hd_sd = 1;
+	std_info->stdid = 0;
+	std_info->dv_preset = V4L2_DV_INVALID;
+
+	vid_ch->stdid = 0;
+	vid_ch->dv_preset = V4L2_DV_INVALID;
+
+	return 0;
+}
+
+/**
+ * vpif_g_dv_timings() - G_DV_TIMINGS handler
+ * @file: file ptr
+ * @priv: file handle
+ * @timings: digital video timings
+ */
+static int vpif_g_dv_timings(struct file *file, void *priv,
+		struct v4l2_dv_timings *timings)
+{
+	struct vpif_fh *fh = priv;
+	struct channel_obj *ch = fh->channel;
+	struct video_obj *vid_ch = &ch->video;
+	struct v4l2_bt_timings *bt = &vid_ch->bt_timings;
+
+	timings->bt = *bt;
+
+	return 0;
+}
+
+/*
+ * vpif_g_chip_ident() - Identify the chip
+ * @file: file ptr
+ * @priv: file handle
+ * @chip: chip identity
+ *
+ * Returns zero or -EINVAL if read operations fails.
+ */
+static int vpif_g_chip_ident(struct file *file, void *priv,
+		struct v4l2_dbg_chip_ident *chip)
+{
+	chip->ident = V4L2_IDENT_NONE;
+	chip->revision = 0;
+	if (chip->match.type != V4L2_CHIP_MATCH_I2C_DRIVER &&
+			chip->match.type != V4L2_CHIP_MATCH_I2C_ADDR) {
+		vpif_dbg(2, debug, "match_type is invalid.\n");
+		return -EINVAL;
+	}
+
+	return v4l2_device_call_until_err(&vpif_obj.v4l2_dev, 0, core,
+			g_chip_ident, chip);
+}
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+/*
+ * vpif_dbg_g_register() - Read register
+ * @file: file ptr
+ * @priv: file handle
+ * @reg: register to be read
+ *
+ * Debugging only
+ * Returns zero or -EINVAL if read operations fails.
+ */
+static int vpif_dbg_g_register(struct file *file, void *priv,
+		struct v4l2_dbg_register *reg){
+	struct vpif_fh *fh = priv;
+	struct channel_obj *ch = fh->channel;
+	struct video_obj *vid_ch = &ch->video;
+
+	return v4l2_subdev_call(vpif_obj.sd[vid_ch->output_id], core,
+			g_register, reg);
+}
+
+/*
+ * vpif_dbg_s_register() - Write to register
+ * @file: file ptr
+ * @priv: file handle
+ * @reg: register to be modified
+ *
+ * Debugging only
+ * Returns zero or -EINVAL if write operations fails.
+ */
+static int vpif_dbg_s_register(struct file *file, void *priv,
+		struct v4l2_dbg_register *reg){
+	struct vpif_fh *fh = priv;
+	struct channel_obj *ch = fh->channel;
+	struct video_obj *vid_ch = &ch->video;
+
+	return v4l2_subdev_call(vpif_obj.sd[vid_ch->output_id], core,
+			s_register, reg);
+}
+#endif
+
+/*
+ * vpif_log_status() - Status information
+ * @file: file ptr
+ * @priv: file handle
+ *
+ * Returns zero.
+ */
+static int vpif_log_status(struct file *filep, void *priv)
+{
+	/* status for sub devices */
+	v4l2_device_call_all(&vpif_obj.v4l2_dev, 0, core, log_status);
+
+	return 0;
+}
+
 /* vpif display ioctl operations */
 static const struct v4l2_ioctl_ops vpif_ioctl_ops = {
 	.vidioc_querycap        	= vpif_querycap,
@@ -1336,13 +1582,24 @@ static const struct v4l2_ioctl_ops vpif_
 	.vidioc_s_output		= vpif_s_output,
 	.vidioc_g_output		= vpif_g_output,
 	.vidioc_cropcap         	= vpif_cropcap,
+	.vidioc_enum_dv_presets         = vpif_enum_dv_presets,
+	.vidioc_s_dv_preset             = vpif_s_dv_preset,
+	.vidioc_g_dv_preset             = vpif_g_dv_preset,
+	.vidioc_s_dv_timings            = vpif_s_dv_timings,
+	.vidioc_g_dv_timings            = vpif_g_dv_timings,
+	.vidioc_g_chip_ident		= vpif_g_chip_ident,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+	.vidioc_g_register		= vpif_dbg_g_register,
+	.vidioc_s_register		= vpif_dbg_s_register,
+#endif
+	.vidioc_log_status		= vpif_log_status,
 };
 
 static const struct v4l2_file_operations vpif_fops = {
 	.owner		= THIS_MODULE,
 	.open		= vpif_open,
 	.release	= vpif_release,
-	.ioctl		= video_ioctl2,
+	.unlocked_ioctl	= video_ioctl2,
 	.mmap		= vpif_mmap,
 	.poll		= vpif_poll
 };
@@ -1526,6 +1783,7 @@ static __init int vpif_probe(struct plat
 		v4l2_prio_init(&ch->prio);
 		ch->common[VPIF_VIDEO_INDEX].fmt.type =
 						V4L2_BUF_TYPE_VIDEO_OUTPUT;
+		ch->video_dev->lock = &common->lock;
 
 		/* register video device */
 		vpif_dbg(1, debug, "channel=%x,channel->video_dev=%x\n",
@@ -1565,6 +1823,8 @@ static __init int vpif_probe(struct plat
 			vpif_obj.sd[i]->grp_id = 1 << i;
 	}
 
+	v4l2_info(&vpif_obj.v4l2_dev,
+			"DM646x VPIF display driver initialized\n");
 	return 0;
 
 probe_subdev_out:
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/davinci/vpif_display.h linux-libre-2.6.38-gnu1/drivers/media/video/davinci/vpif_display.h
--- linux-libre-2.6.37-gnu1/drivers/media/video/davinci/vpif_display.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/davinci/vpif_display.h	2011-03-14 21:20:32.000000000 -0400
@@ -67,6 +67,8 @@ struct video_obj {
 					 * most recent displayed frame only */
 	v4l2_std_id stdid;		/* Currently selected or default
 					 * standard */
+	u32 dv_preset;
+	struct v4l2_bt_timings bt_timings;
 	u32 output_id;			/* Current output id */
 };
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/davinci/vpif.h linux-libre-2.6.38-gnu1/drivers/media/video/davinci/vpif.h
--- linux-libre-2.6.37-gnu1/drivers/media/video/davinci/vpif.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/davinci/vpif.h	2011-03-14 21:20:32.000000000 -0400
@@ -33,7 +33,7 @@ extern spinlock_t vpif_lock;
 #define regr(reg)               readl((reg) + vpif_base)
 #define regw(value, reg)        writel(value, (reg + vpif_base))
 
-/* Register Addresss Offsets */
+/* Register Address Offsets */
 #define VPIF_PID			(0x0000)
 #define VPIF_CH0_CTRL			(0x0004)
 #define VPIF_CH1_CTRL			(0x0008)
@@ -577,12 +577,10 @@ struct vpif_channel_config_params {
 	char name[VPIF_MAX_NAME];	/* Name of the mode */
 	u16 width;			/* Indicates width of the image */
 	u16 height;			/* Indicates height of the image */
-	u8 fps;
-	u8 frm_fmt;			/* Indicates whether this is interlaced
-					 * or progressive format */
-	u8 ycmux_mode;			/* Indicates whether this mode requires
-					 * single or two channels */
-	u16 eav2sav;			/* length of sav 2 eav */
+	u8 frm_fmt;			/* Interlaced (0) or progressive (1) */
+	u8 ycmux_mode;			/* This mode requires one (0) or two (1)
+					   channels */
+	u16 eav2sav;			/* length of eav 2 sav */
 	u16 sav2eav;			/* length of sav 2 eav */
 	u16 l1, l3, l5, l7, l9, l11;	/* Other parameter configurations */
 	u16 vsize;			/* Vertical size of the image */
@@ -590,10 +588,14 @@ struct vpif_channel_config_params {
 					 * is in BT or in CCD/CMOS */
 	u8  vbi_supported;		/* Indicates whether this mode
 					 * supports capturing vbi or not */
-	u8 hd_sd;
-	v4l2_std_id stdid;
+	u8 hd_sd;			/* HDTV (1) or SDTV (0) format */
+	v4l2_std_id stdid;		/* SDTV format */
+	u32 dv_preset;			/* HDTV format */
 };
 
+extern const unsigned int vpif_ch_params_count;
+extern const struct vpif_channel_config_params ch_params[];
+
 struct vpif_video_params;
 struct vpif_params;
 struct vpif_vbi_params;
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/davinci/vpss.c linux-libre-2.6.38-gnu1/drivers/media/video/davinci/vpss.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/davinci/vpss.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/davinci/vpss.c	2011-03-14 21:20:32.000000000 -0400
@@ -85,7 +85,7 @@ enum vpss_platform_type {
 /*
  * vpss operations. Depends on platform. Not all functions are available
  * on all platforms. The api, first check if a functio is available before
- * invoking it. In the probe, the function ptrs are intialized based on
+ * invoking it. In the probe, the function ptrs are initialized based on
  * vpss name. vpss name can be "dm355_vpss", "dm644x_vpss" etc.
  */
 struct vpss_hw_ops {
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/em28xx/em28xx-cards.c linux-libre-2.6.38-gnu1/drivers/media/video/em28xx/em28xx-cards.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/em28xx/em28xx-cards.c	2013-05-03 03:54:56.000000000 -0400
+++ linux-libre-2.6.38-gnu1/drivers/media/video/em28xx/em28xx-cards.c	2013-05-03 01:54:15.000000000 -0400
@@ -33,6 +33,7 @@
 #include <media/saa7115.h>
 #include <media/tvp5150.h>
 #include <media/tvaudio.h>
+#include <media/mt9v011.h>
 #include <media/i2c-addr.h>
 #include <media/tveeprom.h>
 #include <media/v4l2-common.h>
@@ -268,6 +269,20 @@ static struct em28xx_reg_seq dikom_dk300
 };
 
 
+/* Reset for the most [digital] boards */
+static struct em28xx_reg_seq leadership_digital[] = {
+	{EM2874_R80_GPIO,	0x70,	0xff,	10},
+	{	-1,		-1,	-1,	-1},
+};
+
+static struct em28xx_reg_seq leadership_reset[] = {
+	{EM2874_R80_GPIO,	0xf0,	0xff,	10},
+	{EM2874_R80_GPIO,	0xb0,	0xff,	10},
+	{EM2874_R80_GPIO,	0xf0,	0xff,	10},
+	{	-1,		-1,	-1,	-1},
+};
+
+
 /*
  *  Board definitions
  */
@@ -1224,6 +1239,19 @@ struct em28xx_board em28xx_boards[] = {
 			.vmux     = SAA7115_COMPOSITE0,
 		} },
 	},
+
+	[EM2874_LEADERSHIP_ISDBT] = {
+		.i2c_speed      = EM2874_I2C_SECONDARY_BUS_SELECT |
+				  EM28XX_I2C_CLK_WAIT_ENABLE |
+				  EM28XX_I2C_FREQ_100_KHZ,
+		.xclk		= EM28XX_XCLK_FREQUENCY_10MHZ,
+		.name		= "EM2874 Leadership ISDBT",
+		.tuner_type	= TUNER_ABSENT,
+		.tuner_gpio     = leadership_reset,
+		.dvb_gpio       = leadership_digital,
+		.has_dvb	= 1,
+	},
+
 	[EM2880_BOARD_MSI_DIGIVOX_AD] = {
 		.name         = "MSI DigiVox A/D",
 		.valid        = EM28XX_BOARD_NOT_VALIDATED,
@@ -1469,7 +1497,7 @@ struct em28xx_board em28xx_boards[] = {
 		} },
 	},
 	[EM2882_BOARD_TERRATEC_HYBRID_XS] = {
-		.name         = "Terratec Hybrid XS (em2882)",
+		.name         = "Terratec Cinnergy Hybrid T USB XS (em2882)",
 		.tuner_type   = TUNER_XC2028,
 		.tuner_gpio   = default_tuner_gpio,
 		.mts_firmware = 1,
@@ -1633,11 +1661,11 @@ struct em28xx_board em28xx_boards[] = {
 		.input           = { {
 			.type     = EM28XX_VMUX_COMPOSITE1,
 			.vmux     = SAA7115_COMPOSITE0,
-			.amux     = EM28XX_AMUX_VIDEO2,
+			.amux     = EM28XX_AMUX_LINE_IN,
 		}, {
 			.type     = EM28XX_VMUX_SVIDEO,
 			.vmux     = SAA7115_SVIDEO3,
-			.amux     = EM28XX_AMUX_VIDEO2,
+			.amux     = EM28XX_AMUX_LINE_IN,
 		} },
 	},
 	[EM2860_BOARD_TERRATEC_AV350] = {
@@ -1754,6 +1782,8 @@ struct usb_device_id em28xx_id_table[] =
 			.driver_info = EM2820_BOARD_UNKNOWN },
 	{ USB_DEVICE(0xeb1a, 0x2868),
 			.driver_info = EM2820_BOARD_UNKNOWN },
+	{ USB_DEVICE(0xeb1a, 0x2875),
+			.driver_info = EM2820_BOARD_UNKNOWN },
 	{ USB_DEVICE(0xeb1a, 0xe300),
 			.driver_info = EM2861_BOARD_KWORLD_PVRTV_300U },
 	{ USB_DEVICE(0xeb1a, 0xe303),
@@ -1791,7 +1821,7 @@ struct usb_device_id em28xx_id_table[] =
 	{ USB_DEVICE(0x0ccd, 0x005e),
 			.driver_info = EM2882_BOARD_TERRATEC_HYBRID_XS },
 	{ USB_DEVICE(0x0ccd, 0x0042),
-			.driver_info = EM2880_BOARD_TERRATEC_HYBRID_XS },
+			.driver_info = EM2882_BOARD_TERRATEC_HYBRID_XS },
 	{ USB_DEVICE(0x0ccd, 0x0043),
 			.driver_info = EM2870_BOARD_TERRATEC_XS },
 	{ USB_DEVICE(0x0ccd, 0x0047),
@@ -1873,6 +1903,7 @@ static struct em28xx_hash_table em28xx_i
 	{0x77800080, EM2860_BOARD_TVP5150_REFERENCE_DESIGN, TUNER_ABSENT},
 	{0xc51200e3, EM2820_BOARD_GADMEI_TVR200, TUNER_LG_PAL_NEW_TAPC},
 	{0x4ba50080, EM2861_BOARD_GADMEI_UTV330PLUS, TUNER_TNF_5335MF},
+	{0x6b800080, EM2874_LEADERSHIP_ISDBT, TUNER_ABSENT},
 };
 
 /* I2C possible address to saa7115, tvp5150, msp3400, tvaudio */
@@ -1887,11 +1918,6 @@ static unsigned short tvp5150_addrs[] =
 	I2C_CLIENT_END
 };
 
-static unsigned short mt9v011_addrs[] = {
-	0xba >> 1,
-	I2C_CLIENT_END
-};
-
 static unsigned short msp3400_addrs[] = {
 	0x80 >> 1,
 	0x88 >> 1,
@@ -2407,8 +2433,9 @@ void em28xx_register_i2c_ir(struct em28x
 		dev->init_data.ir_codes = RC_MAP_RC5_HAUPPAUGE_NEW;
 		dev->init_data.get_key = em28xx_get_key_em_haup;
 		dev->init_data.name = "i2c IR (EM2840 Hauppauge)";
+		break;
 	case EM2820_BOARD_LEADTEK_WINFAST_USBII_DELUXE:
-		dev->init_data.ir_codes = RC_MAP_WINFAST_USBII_DELUXE;;
+		dev->init_data.ir_codes = RC_MAP_WINFAST_USBII_DELUXE;
 		dev->init_data.get_key = em28xx_get_key_winfast_usbii_deluxe;
 		dev->init_data.name = "i2c IR (EM2820 Winfast TV USBII Deluxe)";
 		break;
@@ -2430,8 +2457,36 @@ void em28xx_card_setup(struct em28xx *de
 			dev->board.is_webcam = 0;
 		else
 			dev->progressive = 1;
-	} else
-		em28xx_set_model(dev);
+	}
+
+	if (!dev->board.is_webcam) {
+		switch (dev->model) {
+		case EM2820_BOARD_UNKNOWN:
+		case EM2800_BOARD_UNKNOWN:
+		/*
+		 * The K-WORLD DVB-T 310U is detected as an MSI Digivox AD.
+		 *
+		 * This occurs because they share identical USB vendor and
+		 * product IDs.
+		 *
+		 * What we do here is look up the EEPROM hash of the K-WORLD
+		 * and if it is found then we decide that we do not have
+		 * a DIGIVOX and reset the device to the K-WORLD instead.
+		 *
+		 * This solution is only valid if they do not share eeprom
+		 * hash identities which has not been determined as yet.
+		 */
+		if (em28xx_hint_board(dev) < 0)
+			em28xx_errdev("Board not discovered\n");
+		else {
+			em28xx_set_model(dev);
+			em28xx_pre_card_setup(dev);
+		}
+		break;
+		default:
+			em28xx_set_model(dev);
+		}
+	}
 
 	em28xx_info("Identified as %s (card=%d)\n",
 		    dev->board.name, dev->model);
@@ -2565,11 +2620,17 @@ void em28xx_card_setup(struct em28xx *de
 			"tvp5150", 0, tvp5150_addrs);
 
 	if (dev->em28xx_sensor == EM28XX_MT9V011) {
+		struct mt9v011_platform_data pdata;
+		struct i2c_board_info mt9v011_info = {
+			.type = "mt9v011",
+			.addr = 0xba >> 1,
+			.platform_data = &pdata,
+		};
 		struct v4l2_subdev *sd;
 
-		sd = v4l2_i2c_new_subdev(&dev->v4l2_dev,
-			 &dev->i2c_adap, "mt9v011", 0, mt9v011_addrs);
-		v4l2_subdev_call(sd, core, s_config, 0, &dev->sensor_xtal);
+		pdata.xtal = dev->sensor_xtal;
+		sd = v4l2_i2c_new_subdev_board(&dev->v4l2_dev, &dev->i2c_adap,
+				&mt9v011_info, NULL);
 	}
 
 
@@ -2632,8 +2693,14 @@ static void request_modules(struct em28x
 	INIT_WORK(&dev->request_module_wk, request_module_async);
 	schedule_work(&dev->request_module_wk);
 }
+
+static void flush_request_modules(struct em28xx *dev)
+{
+	flush_work_sync(&dev->request_module_wk);
+}
 #else
 #define request_modules(dev)
+#define flush_request_modules(dev)
 #endif /* CONFIG_MODULES */
 
 /*
@@ -2749,8 +2816,8 @@ static int em28xx_init_dev(struct em28xx
 	em28xx_pre_card_setup(dev);
 
 	if (!dev->board.is_em2800) {
-		/* Sets I2C speed to 100 KHz */
-		retval = em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x40);
+		/* 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!"
 				      " retval [%d]\n",
@@ -3060,6 +3127,8 @@ static void em28xx_usb_disconnect(struct
 
 	em28xx_info("disconnecting %s\n", dev->vdev->name);
 
+	flush_request_modules(dev);
+
 	/* wait until all current v4l2 io is finished then deallocate
 	   resources */
 	mutex_lock(&dev->lock);
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/em28xx/em28xx-dvb.c linux-libre-2.6.38-gnu1/drivers/media/video/em28xx/em28xx-dvb.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/em28xx/em28xx-dvb.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/em28xx/em28xx-dvb.c	2011-03-14 21:20:32.000000000 -0400
@@ -37,6 +37,7 @@
 #include "mt352_priv.h" /* FIXME */
 #include "tda1002x.h"
 #include "tda18271.h"
+#include "s921.h"
 
 MODULE_DESCRIPTION("driver for em28xx based DVB cards");
 MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>");
@@ -245,6 +246,10 @@ static struct lgdt3305_config em2870_lgd
 	.qam_if_khz         = 4000,
 };
 
+static struct s921_config sharp_isdbt = {
+	.demod_address = 0x30 >> 1
+};
+
 static struct zl10353_config em28xx_zl10353_with_xc3028 = {
 	.demod_address = (0x1e >> 1),
 	.no_tuner = 1,
@@ -481,6 +486,7 @@ static int dvb_init(struct em28xx *dev)
 
 	if (!dev->board.has_dvb) {
 		/* This device does not support the extension */
+		printk(KERN_INFO "em28xx_dvb: This device does not support the extension\n");
 		return 0;
 	}
 
@@ -496,6 +502,16 @@ static int dvb_init(struct em28xx *dev)
 	em28xx_set_mode(dev, EM28XX_DIGITAL_MODE);
 	/* init frontend */
 	switch (dev->model) {
+	case EM2874_LEADERSHIP_ISDBT:
+		dvb->frontend = dvb_attach(s921_attach,
+				&sharp_isdbt, &dev->i2c_adap);
+
+		if (!dvb->frontend) {
+			result = -EINVAL;
+			goto out_free;
+		}
+
+		break;
 	case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_850:
 	case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950:
 	case EM2880_BOARD_PINNACLE_PCTV_HD_PRO:
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/em28xx/em28xx.h linux-libre-2.6.38-gnu1/drivers/media/video/em28xx/em28xx.h
--- linux-libre-2.6.37-gnu1/drivers/media/video/em28xx/em28xx.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/em28xx/em28xx.h	2011-03-14 21:20:32.000000000 -0400
@@ -33,7 +33,7 @@
 #include <media/videobuf-vmalloc.h>
 #include <media/v4l2-device.h>
 #include <media/ir-kbd-i2c.h>
-#include <media/ir-core.h>
+#include <media/rc-core.h>
 #if defined(CONFIG_VIDEO_EM28XX_DVB) || defined(CONFIG_VIDEO_EM28XX_DVB_MODULE)
 #include <media/videobuf-dvb.h>
 #endif
@@ -117,6 +117,8 @@
 #define EM2800_BOARD_VC211A			  74
 #define EM2882_BOARD_DIKOM_DK300		  75
 #define EM2870_BOARD_KWORLD_A340		  76
+#define EM2874_LEADERSHIP_ISDBT			  77
+
 
 /* Limits minimum and default number of buffers */
 #define EM28XX_MIN_BUF 4
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/em28xx/em28xx-input.c linux-libre-2.6.38-gnu1/drivers/media/video/em28xx/em28xx-input.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/em28xx/em28xx-input.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/em28xx/em28xx-input.c	2011-03-14 21:20:32.000000000 -0400
@@ -25,7 +25,6 @@
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
-#include <linux/input.h>
 #include <linux/usb.h>
 #include <linux/slab.h>
 
@@ -64,7 +63,7 @@ struct em28xx_ir_poll_result {
 
 struct em28xx_IR {
 	struct em28xx *dev;
-	struct input_dev *input;
+	struct rc_dev *rc;
 	char name[32];
 	char phys[32];
 
@@ -75,10 +74,6 @@ struct em28xx_IR {
 	unsigned int last_readcount;
 
 	int  (*get_key)(struct em28xx_IR *, struct em28xx_ir_poll_result *);
-
-	/* IR device properties */
-
-	struct ir_dev_props props;
 };
 
 /**********************************************************
@@ -302,12 +297,12 @@ static void em28xx_ir_handle_key(struct
 			poll_result.toggle_bit, poll_result.read_count,
 			poll_result.rc_address, poll_result.rc_data[0]);
 		if (ir->full_code)
-			ir_keydown(ir->input,
+			rc_keydown(ir->rc,
 				   poll_result.rc_address << 8 |
 				   poll_result.rc_data[0],
 				   poll_result.toggle_bit);
 		else
-			ir_keydown(ir->input,
+			rc_keydown(ir->rc,
 				   poll_result.rc_data[0],
 				   poll_result.toggle_bit);
 
@@ -331,9 +326,9 @@ static void em28xx_ir_work(struct work_s
 	schedule_delayed_work(&ir->work, msecs_to_jiffies(ir->polling));
 }
 
-static int em28xx_ir_start(void *priv)
+static int em28xx_ir_start(struct rc_dev *rc)
 {
-	struct em28xx_IR *ir = priv;
+	struct em28xx_IR *ir = rc->priv;
 
 	INIT_DELAYED_WORK(&ir->work, em28xx_ir_work);
 	schedule_delayed_work(&ir->work, 0);
@@ -341,30 +336,30 @@ static int em28xx_ir_start(void *priv)
 	return 0;
 }
 
-static void em28xx_ir_stop(void *priv)
+static void em28xx_ir_stop(struct rc_dev *rc)
 {
-	struct em28xx_IR *ir = priv;
+	struct em28xx_IR *ir = rc->priv;
 
 	cancel_delayed_work_sync(&ir->work);
 }
 
-int em28xx_ir_change_protocol(void *priv, u64 ir_type)
+int em28xx_ir_change_protocol(struct rc_dev *rc_dev, u64 rc_type)
 {
 	int rc = 0;
-	struct em28xx_IR *ir = priv;
+	struct em28xx_IR *ir = rc_dev->priv;
 	struct em28xx *dev = ir->dev;
 	u8 ir_config = EM2874_IR_RC5;
 
 	/* Adjust xclk based o IR table for RC5/NEC tables */
 
-	if (ir_type == IR_TYPE_RC5) {
+	if (rc_type == RC_TYPE_RC5) {
 		dev->board.xclk |= EM28XX_XCLK_IR_RC5_MODE;
 		ir->full_code = 1;
-	} else if (ir_type == IR_TYPE_NEC) {
+	} else if (rc_type == RC_TYPE_NEC) {
 		dev->board.xclk &= ~EM28XX_XCLK_IR_RC5_MODE;
 		ir_config = EM2874_IR_NEC;
 		ir->full_code = 1;
-	} else if (ir_type != IR_TYPE_UNKNOWN)
+	} else if (rc_type != RC_TYPE_UNKNOWN)
 		rc = -EINVAL;
 
 	em28xx_write_reg_bits(dev, EM28XX_R0F_XCLK, dev->board.xclk,
@@ -391,7 +386,7 @@ int em28xx_ir_change_protocol(void *priv
 int em28xx_ir_init(struct em28xx *dev)
 {
 	struct em28xx_IR *ir;
-	struct input_dev *input_dev;
+	struct rc_dev *rc;
 	int err = -ENOMEM;
 
 	if (dev->board.ir_codes == NULL) {
@@ -400,28 +395,27 @@ int em28xx_ir_init(struct em28xx *dev)
 	}
 
 	ir = kzalloc(sizeof(*ir), GFP_KERNEL);
-	input_dev = input_allocate_device();
-	if (!ir || !input_dev)
+	rc = rc_allocate_device();
+	if (!ir || !rc)
 		goto err_out_free;
 
 	/* record handles to ourself */
 	ir->dev = dev;
 	dev->ir = ir;
-
-	ir->input = input_dev;
+	ir->rc = rc;
 
 	/*
 	 * em2874 supports more protocols. For now, let's just announce
 	 * the two protocols that were already tested
 	 */
-	ir->props.allowed_protos = IR_TYPE_RC5 | IR_TYPE_NEC;
-	ir->props.priv = ir;
-	ir->props.change_protocol = em28xx_ir_change_protocol;
-	ir->props.open = em28xx_ir_start;
-	ir->props.close = em28xx_ir_stop;
+	rc->allowed_protos = RC_TYPE_RC5 | RC_TYPE_NEC;
+	rc->priv = ir;
+	rc->change_protocol = em28xx_ir_change_protocol;
+	rc->open = em28xx_ir_start;
+	rc->close = em28xx_ir_stop;
 
 	/* By default, keep protocol field untouched */
-	err = em28xx_ir_change_protocol(ir, IR_TYPE_UNKNOWN);
+	err = em28xx_ir_change_protocol(rc, RC_TYPE_UNKNOWN);
 	if (err)
 		goto err_out_free;
 
@@ -435,27 +429,27 @@ int em28xx_ir_init(struct em28xx *dev)
 	usb_make_path(dev->udev, ir->phys, sizeof(ir->phys));
 	strlcat(ir->phys, "/input0", sizeof(ir->phys));
 
-	input_dev->name = ir->name;
-	input_dev->phys = ir->phys;
-	input_dev->id.bustype = BUS_USB;
-	input_dev->id.version = 1;
-	input_dev->id.vendor = le16_to_cpu(dev->udev->descriptor.idVendor);
-	input_dev->id.product = le16_to_cpu(dev->udev->descriptor.idProduct);
-
-	input_dev->dev.parent = &dev->udev->dev;
-
-
+	rc->input_name = ir->name;
+	rc->input_phys = ir->phys;
+	rc->input_id.bustype = BUS_USB;
+	rc->input_id.version = 1;
+	rc->input_id.vendor = le16_to_cpu(dev->udev->descriptor.idVendor);
+	rc->input_id.product = le16_to_cpu(dev->udev->descriptor.idProduct);
+	rc->dev.parent = &dev->udev->dev;
+	rc->map_name = dev->board.ir_codes;
+	rc->driver_name = MODULE_NAME;
 
 	/* all done */
-	err = ir_input_register(ir->input, dev->board.ir_codes,
-				&ir->props, MODULE_NAME);
+	err = rc_register_device(rc);
 	if (err)
 		goto err_out_stop;
 
 	return 0;
+
  err_out_stop:
 	dev->ir = NULL;
  err_out_free:
+	rc_free_device(rc);
 	kfree(ir);
 	return err;
 }
@@ -468,8 +462,8 @@ int em28xx_ir_fini(struct em28xx *dev)
 	if (!ir)
 		return 0;
 
-	em28xx_ir_stop(ir);
-	ir_input_unregister(ir->input);
+	em28xx_ir_stop(ir->rc);
+	rc_unregister_device(ir->rc);
 	kfree(ir);
 
 	/* done */
@@ -557,7 +551,7 @@ void em28xx_deregister_snapshot_button(s
 {
 	if (dev->sbutton_input_dev != NULL) {
 		em28xx_info("Deregistering snapshot button\n");
-		cancel_rearming_delayed_work(&dev->sbutton_query_work);
+		cancel_delayed_work_sync(&dev->sbutton_query_work);
 		input_unregister_device(dev->sbutton_input_dev);
 		dev->sbutton_input_dev = NULL;
 	}
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/em28xx/em28xx-vbi.c linux-libre-2.6.38-gnu1/drivers/media/video/em28xx/em28xx-vbi.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/em28xx/em28xx-vbi.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/em28xx/em28xx-vbi.c	2011-03-14 21:20:32.000000000 -0400
@@ -23,6 +23,7 @@
 
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/hardirq.h>
 #include <linux/init.h>
 
 #include "em28xx.h"
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/em28xx/em28xx-video.c linux-libre-2.6.38-gnu1/drivers/media/video/em28xx/em28xx-video.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/em28xx/em28xx-video.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/em28xx/em28xx-video.c	2011-03-14 21:20:32.000000000 -0400
@@ -1434,7 +1434,7 @@ static int vidioc_s_ctrl(struct file *fi
 
 	/* It isn't an AC97 control. Sends it to the v4l2 dev interface */
 	if (rc == 1) {
-		v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_ctrl, ctrl);
+		rc = v4l2_device_call_until_err(&dev->v4l2_dev, 0, core, s_ctrl, ctrl);
 
 		/*
 		 * In the case of non-AC97 volume controls, we still need
@@ -1708,11 +1708,15 @@ static int vidioc_streamoff(struct file
 			fh, type, fh->resources, dev->resources);
 
 	if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
-		videobuf_streamoff(&fh->vb_vidq);
-		res_free(fh, EM28XX_RESOURCE_VIDEO);
+		if (res_check(fh, EM28XX_RESOURCE_VIDEO)) {
+			videobuf_streamoff(&fh->vb_vidq);
+			res_free(fh, EM28XX_RESOURCE_VIDEO);
+		}
 	} else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
-		videobuf_streamoff(&fh->vb_vbiq);
-		res_free(fh, EM28XX_RESOURCE_VBI);
+		if (res_check(fh, EM28XX_RESOURCE_VBI)) {
+			videobuf_streamoff(&fh->vb_vbiq);
+			res_free(fh, EM28XX_RESOURCE_VBI);
+		}
 	}
 
 	return 0;
@@ -1934,19 +1938,6 @@ static int vidioc_dqbuf(struct file *fil
 				      O_NONBLOCK);
 }
 
-#ifdef CONFIG_VIDEO_V4L1_COMPAT
-static int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf)
-{
-	struct em28xx_fh  *fh = priv;
-
-	if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
-		return videobuf_cgmbuf(&fh->vb_vidq, mbuf, 8);
-	else
-		return videobuf_cgmbuf(&fh->vb_vbiq, mbuf, 8);
-}
-#endif
-
-
 /* ----------------------------------------------------------- */
 /* RADIO ESPECIFIC IOCTLS                                      */
 /* ----------------------------------------------------------- */
@@ -2359,9 +2350,6 @@ static const struct v4l2_ioctl_ops video
 	.vidioc_s_register          = vidioc_s_register,
 	.vidioc_g_chip_ident        = vidioc_g_chip_ident,
 #endif
-#ifdef CONFIG_VIDEO_V4L1_COMPAT
-	.vidiocgmbuf                = vidiocgmbuf,
-#endif
 };
 
 static const struct video_device em28xx_video_template = {
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/em28xx/Kconfig linux-libre-2.6.38-gnu1/drivers/media/video/em28xx/Kconfig
--- linux-libre-2.6.37-gnu1/drivers/media/video/em28xx/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/em28xx/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -1,9 +1,9 @@
 config VIDEO_EM28XX
 	tristate "Empia EM28xx USB video capture support"
-	depends on VIDEO_DEV && I2C && INPUT
+	depends on VIDEO_DEV && I2C
 	select VIDEO_TUNER
 	select VIDEO_TVEEPROM
-	depends on VIDEO_IR
+	depends on RC_CORE
 	select VIDEOBUF_VMALLOC
 	select VIDEO_SAA711X if VIDEO_HELPER_CHIPS_AUTO
 	select VIDEO_TVP5150 if VIDEO_HELPER_CHIPS_AUTO
@@ -37,6 +37,7 @@ config VIDEO_EM28XX_DVB
 	select DVB_LGDT330X if !DVB_FE_CUSTOMISE
 	select DVB_ZL10353 if !DVB_FE_CUSTOMISE
 	select DVB_TDA10023 if !DVB_FE_CUSTOMISE
+	select DVB_S921 if !DVB_FE_CUSTOMISE
 	select VIDEOBUF_DVB
 	---help---
 	  This adds support for DVB cards based on the
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/et61x251/et61x251_core.c linux-libre-2.6.38-gnu1/drivers/media/video/et61x251/et61x251_core.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/et61x251/et61x251_core.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/et61x251/et61x251_core.c	2011-03-14 21:20:32.000000000 -0400
@@ -1610,6 +1610,7 @@ et61x251_vidioc_enuminput(struct et61x25
 	memset(&i, 0, sizeof(i));
 	strcpy(i.name, "Camera");
 	i.type = V4L2_INPUT_TYPE_CAMERA;
+	i.capabilities = V4L2_IN_CAP_STD;
 
 	if (copy_to_user(arg, &i, sizeof(i)))
 		return -EFAULT;
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/et61x251/et61x251.h linux-libre-2.6.38-gnu1/drivers/media/video/et61x251/et61x251.h
--- linux-libre-2.6.37-gnu1/drivers/media/video/et61x251/et61x251.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/et61x251/et61x251.h	2011-03-14 21:20:32.000000000 -0400
@@ -59,31 +59,7 @@
 /*****************************************************************************/
 
 static const struct usb_device_id et61x251_id_table[] = {
-	{ USB_DEVICE(0x102c, 0x6151), },
 	{ USB_DEVICE(0x102c, 0x6251), },
-	{ USB_DEVICE(0x102c, 0x6253), },
-	{ USB_DEVICE(0x102c, 0x6254), },
-	{ USB_DEVICE(0x102c, 0x6255), },
-	{ USB_DEVICE(0x102c, 0x6256), },
-	{ USB_DEVICE(0x102c, 0x6257), },
-	{ USB_DEVICE(0x102c, 0x6258), },
-	{ USB_DEVICE(0x102c, 0x6259), },
-	{ USB_DEVICE(0x102c, 0x625a), },
-	{ USB_DEVICE(0x102c, 0x625b), },
-	{ USB_DEVICE(0x102c, 0x625c), },
-	{ USB_DEVICE(0x102c, 0x625d), },
-	{ USB_DEVICE(0x102c, 0x625e), },
-	{ USB_DEVICE(0x102c, 0x625f), },
-	{ USB_DEVICE(0x102c, 0x6260), },
-	{ USB_DEVICE(0x102c, 0x6261), },
-	{ USB_DEVICE(0x102c, 0x6262), },
-	{ USB_DEVICE(0x102c, 0x6263), },
-	{ USB_DEVICE(0x102c, 0x6264), },
-	{ USB_DEVICE(0x102c, 0x6265), },
-	{ USB_DEVICE(0x102c, 0x6266), },
-	{ USB_DEVICE(0x102c, 0x6267), },
-	{ USB_DEVICE(0x102c, 0x6268), },
-	{ USB_DEVICE(0x102c, 0x6269), },
 	{ }
 };
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/fsl-viu.c linux-libre-2.6.38-gnu1/drivers/media/video/fsl-viu.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/fsl-viu.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/fsl-viu.c	2011-03-14 21:20:32.000000000 -0400
@@ -194,6 +194,8 @@ struct viu_dev {
 
 	/* decoder */
 	struct v4l2_subdev	*decoder;
+
+	v4l2_std_id		std;
 };
 
 struct viu_fh {
@@ -915,6 +917,8 @@ static int vidioc_streamon(struct file *
 	if (fh->type != i)
 		return -EINVAL;
 
+	viu_start_dma(fh->dev);
+
 	return videobuf_streamon(&fh->vb_vidq);
 }
 
@@ -927,20 +931,39 @@ static int vidioc_streamoff(struct file
 	if (fh->type != i)
 		return -EINVAL;
 
+	viu_stop_dma(fh->dev);
+
 	return videobuf_streamoff(&fh->vb_vidq);
 }
 
 #define decoder_call(viu, o, f, args...) \
 	v4l2_subdev_call(viu->decoder, o, f, ##args)
 
+static int vidioc_querystd(struct file *file, void *priv, v4l2_std_id *std_id)
+{
+	struct viu_fh *fh = priv;
+
+	decoder_call(fh->dev, video, querystd, std_id);
+	return 0;
+}
+
 static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *id)
 {
 	struct viu_fh *fh = priv;
 
+	fh->dev->std = *id;
 	decoder_call(fh->dev, core, s_std, *id);
 	return 0;
 }
 
+static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *std_id)
+{
+	struct viu_fh *fh = priv;
+
+	*std_id = fh->dev->std;
+	return 0;
+}
+
 /* only one input in this driver */
 static int vidioc_enum_input(struct file *file, void *priv,
 					struct v4l2_input *inp)
@@ -1331,6 +1354,7 @@ static int viu_release(struct file *file
 
 	viu_stop_dma(dev);
 	videobuf_stop(&fh->vb_vidq);
+	videobuf_mmap_free(&fh->vb_vidq);
 
 	kfree(fh);
 
@@ -1397,7 +1421,9 @@ static const struct v4l2_ioctl_ops viu_i
 	.vidioc_querybuf      = vidioc_querybuf,
 	.vidioc_qbuf          = vidioc_qbuf,
 	.vidioc_dqbuf         = vidioc_dqbuf,
+	.vidioc_g_std         = vidioc_g_std,
 	.vidioc_s_std         = vidioc_s_std,
+	.vidioc_querystd      = vidioc_querystd,
 	.vidioc_enum_input    = vidioc_enum_input,
 	.vidioc_g_input       = vidioc_g_input,
 	.vidioc_s_input       = vidioc_s_input,
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/gspca/benq.c linux-libre-2.6.38-gnu1/drivers/media/video/gspca/benq.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/gspca/benq.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/gspca/benq.c	2011-03-14 21:20:32.000000000 -0400
@@ -276,7 +276,7 @@ static const struct sd_desc sd_desc = {
 };
 
 /* -- module initialisation -- */
-static const __devinitdata struct usb_device_id device_table[] = {
+static const struct usb_device_id device_table[] = {
 	{USB_DEVICE(0x04a5, 0x3035)},
 	{}
 };
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/gspca/conex.c linux-libre-2.6.38-gnu1/drivers/media/video/gspca/conex.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/gspca/conex.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/gspca/conex.c	2011-03-14 21:20:32.000000000 -0400
@@ -1040,14 +1040,14 @@ static const struct sd_desc sd_desc = {
 };
 
 /* -- module initialisation -- */
-static const struct usb_device_id device_table[] __devinitconst = {
+static const struct usb_device_id device_table[] = {
 	{USB_DEVICE(0x0572, 0x0041)},
 	{}
 };
 MODULE_DEVICE_TABLE(usb, device_table);
 
 /* -- device connect -- */
-static int __devinit sd_probe(struct usb_interface *intf,
+static int sd_probe(struct usb_interface *intf,
 			const struct usb_device_id *id)
 {
 	return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/gspca/cpia1.c linux-libre-2.6.38-gnu1/drivers/media/video/gspca/cpia1.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/gspca/cpia1.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/gspca/cpia1.c	2011-03-14 21:20:32.000000000 -0400
@@ -37,7 +37,7 @@ MODULE_LICENSE("GPL");
 /* constant value's */
 #define MAGIC_0		0x19
 #define MAGIC_1		0x68
-#define DATA_IN		0xC0
+#define DATA_IN		0xc0
 #define DATA_OUT	0x40
 #define VIDEOSIZE_QCIF	0	/* 176x144 */
 #define VIDEOSIZE_CIF	1	/* 352x288 */
@@ -660,9 +660,9 @@ static int do_command(struct gspca_dev *
 		if (sd->params.qx3.button) {
 			/* button pressed - unlock the latch */
 			do_command(gspca_dev, CPIA_COMMAND_WriteMCPort,
-				   3, 0xDF, 0xDF, 0);
+				   3, 0xdf, 0xdf, 0);
 			do_command(gspca_dev, CPIA_COMMAND_WriteMCPort,
-				   3, 0xFF, 0xFF, 0);
+				   3, 0xff, 0xff, 0);
 		}
 
 		/* test whether microscope is cradled */
@@ -829,7 +829,7 @@ static int goto_low_power(struct gspca_d
 	if (ret)
 		return ret;
 
-	do_command(gspca_dev, CPIA_COMMAND_GetCameraStatus, 0, 0, 0, 0);
+	ret = do_command(gspca_dev, CPIA_COMMAND_GetCameraStatus, 0, 0, 0, 0);
 	if (ret)
 		return ret;
 
@@ -1110,12 +1110,12 @@ static int command_setlights(struct gspc
 	p2 = (sd->params.qx3.toplight == 0) << 3;
 
 	ret = do_command(gspca_dev, CPIA_COMMAND_WriteVCReg,
-			 0x90, 0x8F, 0x50, 0);
+			 0x90, 0x8f, 0x50, 0);
 	if (ret)
 		return ret;
 
 	return do_command(gspca_dev, CPIA_COMMAND_WriteMCPort, 2, 0,
-			  p1 | p2 | 0xE0, 0);
+			  p1 | p2 | 0xe0, 0);
 }
 
 static int set_flicker(struct gspca_dev *gspca_dev, int on, int apply)
@@ -2088,7 +2088,7 @@ static const struct sd_desc sd_desc = {
 };
 
 /* -- module initialisation -- */
-static const __devinitdata struct usb_device_id device_table[] = {
+static const struct usb_device_id device_table[] = {
 	{USB_DEVICE(0x0553, 0x0002)},
 	{USB_DEVICE(0x0813, 0x0001)},
 	{}
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/gspca/etoms.c linux-libre-2.6.38-gnu1/drivers/media/video/gspca/etoms.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/gspca/etoms.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/gspca/etoms.c	2011-03-14 21:20:32.000000000 -0400
@@ -864,7 +864,7 @@ static const struct sd_desc sd_desc = {
 };
 
 /* -- module initialisation -- */
-static const struct usb_device_id device_table[] __devinitconst = {
+static const struct usb_device_id device_table[] = {
 	{USB_DEVICE(0x102c, 0x6151), .driver_info = SENSOR_PAS106},
 #if !defined CONFIG_USB_ET61X251 && !defined CONFIG_USB_ET61X251_MODULE
 	{USB_DEVICE(0x102c, 0x6251), .driver_info = SENSOR_TAS5130CXX},
@@ -875,7 +875,7 @@ static const struct usb_device_id device
 MODULE_DEVICE_TABLE(usb, device_table);
 
 /* -- device connect -- */
-static int __devinit sd_probe(struct usb_interface *intf,
+static int sd_probe(struct usb_interface *intf,
 		    const struct usb_device_id *id)
 {
 	return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/gspca/finepix.c linux-libre-2.6.38-gnu1/drivers/media/video/gspca/finepix.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/gspca/finepix.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/gspca/finepix.c	2011-03-14 21:20:32.000000000 -0400
@@ -229,7 +229,7 @@ static void sd_stop0(struct gspca_dev *g
 }
 
 /* Table of supported USB devices */
-static const __devinitdata struct usb_device_id device_table[] = {
+static const struct usb_device_id device_table[] = {
 	{USB_DEVICE(0x04cb, 0x0104)},
 	{USB_DEVICE(0x04cb, 0x0109)},
 	{USB_DEVICE(0x04cb, 0x010b)},
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/gspca/gl860/gl860.c linux-libre-2.6.38-gnu1/drivers/media/video/gspca/gl860/gl860.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/gspca/gl860/gl860.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/gspca/gl860/gl860.c	2011-03-14 21:20:32.000000000 -0400
@@ -488,7 +488,7 @@ static void sd_callback(struct gspca_dev
 
 /*=================== USB driver structure initialisation ==================*/
 
-static const __devinitdata struct usb_device_id device_table[] = {
+static const struct usb_device_id device_table[] = {
 	{USB_DEVICE(0x05e3, 0x0503)},
 	{USB_DEVICE(0x05e3, 0xf191)},
 	{}
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/gspca/gspca.c linux-libre-2.6.38-gnu1/drivers/media/video/gspca/gspca.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/gspca/gspca.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/gspca/gspca.c	2011-03-14 21:20:32.000000000 -0400
@@ -55,7 +55,7 @@ MODULE_AUTHOR("Jean-François Moine <htt
 MODULE_DESCRIPTION("GSPCA USB Camera Driver");
 MODULE_LICENSE("GPL");
 
-#define DRIVER_VERSION_NUMBER	KERNEL_VERSION(2, 10, 0)
+#define DRIVER_VERSION_NUMBER	KERNEL_VERSION(2, 12, 0)
 
 #ifdef GSPCA_DEBUG
 int gspca_debug = D_ERR | D_PROBE;
@@ -224,12 +224,12 @@ static int alloc_and_submit_int_urb(stru
 		buffer, buffer_len,
 		int_irq, (void *)gspca_dev, interval);
 	urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
-	gspca_dev->int_urb = urb;
 	ret = usb_submit_urb(urb, GFP_KERNEL);
 	if (ret < 0) {
 		PDEBUG(D_ERR, "submit int URB failed with error %i", ret);
 		goto error_submit;
 	}
+	gspca_dev->int_urb = urb;
 	return ret;
 
 error_submit:
@@ -318,14 +318,9 @@ static void fill_frame(struct gspca_dev
 	}
 	pkt_scan = gspca_dev->sd_desc->pkt_scan;
 	for (i = 0; i < urb->number_of_packets; i++) {
+		len = urb->iso_frame_desc[i].actual_length;
 
 		/* check the packet status and length */
-		len = urb->iso_frame_desc[i].actual_length;
-		if (len == 0) {
-			if (gspca_dev->empty_packet == 0)
-				gspca_dev->empty_packet = 1;
-			continue;
-		}
 		st = urb->iso_frame_desc[i].status;
 		if (st) {
 			err("ISOC data error: [%d] len=%d, status=%d",
@@ -333,6 +328,11 @@ static void fill_frame(struct gspca_dev
 			gspca_dev->last_packet_type = DISCARD_PACKET;
 			continue;
 		}
+		if (len == 0) {
+			if (gspca_dev->empty_packet == 0)
+				gspca_dev->empty_packet = 1;
+			continue;
+		}
 
 		/* let the packet be analyzed by the subdriver */
 		PDEBUG(D_PACK, "packet [%d] o:%d l:%d",
@@ -508,8 +508,8 @@ static int gspca_is_compressed(__u32 for
 	return 0;
 }
 
-static int frame_alloc(struct gspca_dev *gspca_dev,
-			unsigned int count)
+static int frame_alloc(struct gspca_dev *gspca_dev, struct file *file,
+			enum v4l2_memory memory, unsigned int count)
 {
 	struct gspca_frame *frame;
 	unsigned int frsz;
@@ -519,7 +519,6 @@ static int frame_alloc(struct gspca_dev
 	frsz = gspca_dev->cam.cam_mode[i].sizeimage;
 	PDEBUG(D_STREAM, "frame alloc frsz: %d", frsz);
 	frsz = PAGE_ALIGN(frsz);
-	gspca_dev->frsz = frsz;
 	if (count >= GSPCA_MAX_FRAMES)
 		count = GSPCA_MAX_FRAMES - 1;
 	gspca_dev->frbuf = vmalloc_32(frsz * count);
@@ -527,6 +526,9 @@ static int frame_alloc(struct gspca_dev
 		err("frame alloc failed");
 		return -ENOMEM;
 	}
+	gspca_dev->capt_file = file;
+	gspca_dev->memory = memory;
+	gspca_dev->frsz = frsz;
 	gspca_dev->nframes = count;
 	for (i = 0; i < count; i++) {
 		frame = &gspca_dev->frame[i];
@@ -535,7 +537,7 @@ static int frame_alloc(struct gspca_dev
 		frame->v4l2_buf.flags = 0;
 		frame->v4l2_buf.field = V4L2_FIELD_NONE;
 		frame->v4l2_buf.length = frsz;
-		frame->v4l2_buf.memory = gspca_dev->memory;
+		frame->v4l2_buf.memory = memory;
 		frame->v4l2_buf.sequence = 0;
 		frame->data = gspca_dev->frbuf + i * frsz;
 		frame->v4l2_buf.m.offset = i * frsz;
@@ -558,6 +560,9 @@ static void frame_free(struct gspca_dev
 			gspca_dev->frame[i].data = NULL;
 	}
 	gspca_dev->nframes = 0;
+	gspca_dev->frsz = 0;
+	gspca_dev->capt_file = NULL;
+	gspca_dev->memory = GSPCA_MEMORY_NO;
 }
 
 static void destroy_urbs(struct gspca_dev *gspca_dev)
@@ -652,16 +657,12 @@ static struct usb_host_endpoint *get_ep(
 				   : USB_ENDPOINT_XFER_ISOC;
 	i = gspca_dev->alt;			/* previous alt setting */
 	if (gspca_dev->cam.reverse_alts) {
-		if (gspca_dev->audio && i < gspca_dev->nbalt - 2)
-			i++;
 		while (++i < gspca_dev->nbalt) {
 			ep = alt_xfer(&intf->altsetting[i], xfer);
 			if (ep)
 				break;
 		}
 	} else {
-		if (gspca_dev->audio && i > 1)
-			i--;
 		while (--i >= 0) {
 			ep = alt_xfer(&intf->altsetting[i], xfer);
 			if (ep)
@@ -676,13 +677,11 @@ static struct usb_host_endpoint *get_ep(
 			i, ep->desc.bEndpointAddress);
 	gspca_dev->alt = i;		/* memorize the current alt setting */
 	if (gspca_dev->nbalt > 1) {
-		gspca_input_destroy_urb(gspca_dev);
 		ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, i);
 		if (ret < 0) {
 			err("set alt %d err %d", i, ret);
 			ep = NULL;
 		}
-		gspca_input_create_urb(gspca_dev);
 	}
 	return ep;
 }
@@ -759,7 +758,7 @@ static int create_urbs(struct gspca_dev
 			}
 		} else {		/* bulk */
 			urb->pipe = usb_rcvbulkpipe(gspca_dev->dev,
-						ep->desc.bEndpointAddress),
+						ep->desc.bEndpointAddress);
 			urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP;
 			urb->complete = bulk_irq;
 		}
@@ -781,7 +780,7 @@ static int gspca_init_transfer(struct gs
 
 	if (!gspca_dev->present) {
 		ret = -ENODEV;
-		goto out;
+		goto unlock;
 	}
 
 	/* reset the streaming variables */
@@ -802,8 +801,10 @@ static int gspca_init_transfer(struct gs
 	if (gspca_dev->sd_desc->isoc_init) {
 		ret = gspca_dev->sd_desc->isoc_init(gspca_dev);
 		if (ret < 0)
-			goto out;
+			goto unlock;
 	}
+
+	gspca_input_destroy_urb(gspca_dev);
 	ep = get_ep(gspca_dev);
 	if (ep == NULL) {
 		ret = -EIO;
@@ -873,6 +874,8 @@ static int gspca_init_transfer(struct gs
 		}
 	}
 out:
+	gspca_input_create_urb(gspca_dev);
+unlock:
 	mutex_unlock(&gspca_dev->usb_lock);
 	return ret;
 }
@@ -1212,29 +1215,15 @@ static void gspca_release(struct video_d
 static int dev_open(struct file *file)
 {
 	struct gspca_dev *gspca_dev;
-	int ret;
 
 	PDEBUG(D_STREAM, "[%s] open", current->comm);
 	gspca_dev = (struct gspca_dev *) video_devdata(file);
-	if (mutex_lock_interruptible(&gspca_dev->queue_lock))
-		return -ERESTARTSYS;
-	if (!gspca_dev->present) {
-		ret = -ENODEV;
-		goto out;
-	}
-
-	if (gspca_dev->users > 4) {	/* (arbitrary value) */
-		ret = -EBUSY;
-		goto out;
-	}
+	if (!gspca_dev->present)
+		return -ENODEV;
 
 	/* protect the subdriver against rmmod */
-	if (!try_module_get(gspca_dev->module)) {
-		ret = -ENODEV;
-		goto out;
-	}
-
-	gspca_dev->users++;
+	if (!try_module_get(gspca_dev->module))
+		return -ENODEV;
 
 	file->private_data = gspca_dev;
 #ifdef GSPCA_DEBUG
@@ -1246,14 +1235,7 @@ static int dev_open(struct file *file)
 		gspca_dev->vdev.debug &= ~(V4L2_DEBUG_IOCTL
 					| V4L2_DEBUG_IOCTL_ARG);
 #endif
-	ret = 0;
-out:
-	mutex_unlock(&gspca_dev->queue_lock);
-	if (ret != 0)
-		PDEBUG(D_ERR|D_STREAM, "open failed err %d", ret);
-	else
-		PDEBUG(D_STREAM, "open done");
-	return ret;
+	return 0;
 }
 
 static int dev_close(struct file *file)
@@ -1263,7 +1245,6 @@ static int dev_close(struct file *file)
 	PDEBUG(D_STREAM, "[%s] close", current->comm);
 	if (mutex_lock_interruptible(&gspca_dev->queue_lock))
 		return -ERESTARTSYS;
-	gspca_dev->users--;
 
 	/* if the file did the capture, free the streaming resources */
 	if (gspca_dev->capt_file == file) {
@@ -1274,8 +1255,6 @@ static int dev_close(struct file *file)
 			mutex_unlock(&gspca_dev->usb_lock);
 		}
 		frame_free(gspca_dev);
-		gspca_dev->capt_file = NULL;
-		gspca_dev->memory = GSPCA_MEMORY_NO;
 	}
 	file->private_data = NULL;
 	module_put(gspca_dev->module);
@@ -1299,17 +1278,19 @@ static int vidioc_querycap(struct file *
 		ret = -ENODEV;
 		goto out;
 	}
-	strncpy(cap->driver, gspca_dev->sd_desc->name, sizeof cap->driver);
+	strncpy((char *) cap->driver, gspca_dev->sd_desc->name,
+			sizeof cap->driver);
 	if (gspca_dev->dev->product != NULL) {
-		strncpy(cap->card, gspca_dev->dev->product,
+		strncpy((char *) cap->card, gspca_dev->dev->product,
 			sizeof cap->card);
 	} else {
-		snprintf(cap->card, sizeof cap->card,
+		snprintf((char *) cap->card, sizeof cap->card,
 			"USB Camera (%04x:%04x)",
 			le16_to_cpu(gspca_dev->dev->descriptor.idVendor),
 			le16_to_cpu(gspca_dev->dev->descriptor.idProduct));
 	}
-	usb_make_path(gspca_dev->dev, cap->bus_info, sizeof(cap->bus_info));
+	usb_make_path(gspca_dev->dev, (char *) cap->bus_info,
+			sizeof(cap->bus_info));
 	cap->version = DRIVER_VERSION_NUMBER;
 	cap->capabilities = V4L2_CAP_VIDEO_CAPTURE
 			  | V4L2_CAP_STREAMING
@@ -1516,6 +1497,7 @@ static int vidioc_reqbufs(struct file *f
 		return -ERESTARTSYS;
 
 	if (gspca_dev->memory != GSPCA_MEMORY_NO
+	    && gspca_dev->memory != GSPCA_MEMORY_READ
 	    && gspca_dev->memory != rb->memory) {
 		ret = -EBUSY;
 		goto out;
@@ -1544,19 +1526,18 @@ static int vidioc_reqbufs(struct file *f
 		gspca_stream_off(gspca_dev);
 		mutex_unlock(&gspca_dev->usb_lock);
 	}
+	/* Don't restart the stream when switching from read to mmap mode */
+	if (gspca_dev->memory == GSPCA_MEMORY_READ)
+		streaming = 0;
 
 	/* free the previous allocated buffers, if any */
-	if (gspca_dev->nframes != 0) {
+	if (gspca_dev->nframes != 0)
 		frame_free(gspca_dev);
-		gspca_dev->capt_file = NULL;
-	}
 	if (rb->count == 0)			/* unrequest */
 		goto out;
-	gspca_dev->memory = rb->memory;
-	ret = frame_alloc(gspca_dev, rb->count);
+	ret = frame_alloc(gspca_dev, file, rb->memory, rb->count);
 	if (ret == 0) {
 		rb->count = gspca_dev->nframes;
-		gspca_dev->capt_file = file;
 		if (streaming)
 			ret = gspca_init_transfer(gspca_dev);
 	}
@@ -1630,11 +1611,15 @@ static int vidioc_streamoff(struct file
 
 	if (buf_type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
 		return -EINVAL;
-	if (!gspca_dev->streaming)
-		return 0;
+
 	if (mutex_lock_interruptible(&gspca_dev->queue_lock))
 		return -ERESTARTSYS;
 
+	if (!gspca_dev->streaming) {
+		ret = 0;
+		goto out;
+	}
+
 	/* check the capture file */
 	if (gspca_dev->capt_file != file) {
 		ret = -EBUSY;
@@ -1649,6 +1634,8 @@ static int vidioc_streamoff(struct file
 	gspca_dev->usb_err = 0;
 	gspca_stream_off(gspca_dev);
 	mutex_unlock(&gspca_dev->usb_lock);
+	/* In case another thread is waiting in dqbuf */
+	wake_up_interruptible(&gspca_dev->wq);
 
 	/* empty the transfer queues */
 	atomic_set(&gspca_dev->fr_q, 0);
@@ -1710,12 +1697,13 @@ static int vidioc_g_parm(struct file *fi
 
 		if (mutex_lock_interruptible(&gspca_dev->usb_lock))
 			return -ERESTARTSYS;
-		gspca_dev->usb_err = 0;
-		if (gspca_dev->present)
-			ret = gspca_dev->sd_desc->get_streamparm(gspca_dev,
-								 parm);
-		else
+		if (gspca_dev->present) {
+			gspca_dev->usb_err = 0;
+			gspca_dev->sd_desc->get_streamparm(gspca_dev, parm);
+			ret = gspca_dev->usb_err;
+		} else {
 			ret = -ENODEV;
+		}
 		mutex_unlock(&gspca_dev->usb_lock);
 		return ret;
 	}
@@ -1740,12 +1728,13 @@ static int vidioc_s_parm(struct file *fi
 
 		if (mutex_lock_interruptible(&gspca_dev->usb_lock))
 			return -ERESTARTSYS;
-		gspca_dev->usb_err = 0;
-		if (gspca_dev->present)
-			ret = gspca_dev->sd_desc->set_streamparm(gspca_dev,
-								 parm);
-		else
+		if (gspca_dev->present) {
+			gspca_dev->usb_err = 0;
+			gspca_dev->sd_desc->set_streamparm(gspca_dev, parm);
+			ret = gspca_dev->usb_err;
+		} else {
 			ret = -ENODEV;
+		}
 		mutex_unlock(&gspca_dev->usb_lock);
 		return ret;
 	}
@@ -1825,33 +1814,77 @@ out:
 	return ret;
 }
 
+static int frame_ready_nolock(struct gspca_dev *gspca_dev, struct file *file,
+				enum v4l2_memory memory)
+{
+	if (!gspca_dev->present)
+		return -ENODEV;
+	if (gspca_dev->capt_file != file || gspca_dev->memory != memory ||
+			!gspca_dev->streaming)
+		return -EINVAL;
+
+	/* check if a frame is ready */
+	return gspca_dev->fr_o != atomic_read(&gspca_dev->fr_i);
+}
+
+static int frame_ready(struct gspca_dev *gspca_dev, struct file *file,
+			enum v4l2_memory memory)
+{
+	int ret;
+
+	if (mutex_lock_interruptible(&gspca_dev->queue_lock))
+		return -ERESTARTSYS;
+	ret = frame_ready_nolock(gspca_dev, file, memory);
+	mutex_unlock(&gspca_dev->queue_lock);
+	return ret;
+}
+
 /*
- * wait for a video frame
+ * dequeue a video buffer
  *
- * If a frame is ready, its index is returned.
+ * If nonblock_ing is false, block until a buffer is available.
  */
-static int frame_wait(struct gspca_dev *gspca_dev,
-			int nonblock_ing)
+static int vidioc_dqbuf(struct file *file, void *priv,
+			struct v4l2_buffer *v4l2_buf)
 {
-	int i, ret;
+	struct gspca_dev *gspca_dev = priv;
+	struct gspca_frame *frame;
+	int i, j, ret;
 
-	/* check if a frame is ready */
-	i = gspca_dev->fr_o;
-	if (i == atomic_read(&gspca_dev->fr_i)) {
-		if (nonblock_ing)
+	PDEBUG(D_FRAM, "dqbuf");
+
+	if (mutex_lock_interruptible(&gspca_dev->queue_lock))
+		return -ERESTARTSYS;
+
+	for (;;) {
+		ret = frame_ready_nolock(gspca_dev, file, v4l2_buf->memory);
+		if (ret < 0)
+			goto out;
+		if (ret > 0)
+			break;
+
+		mutex_unlock(&gspca_dev->queue_lock);
+
+		if (file->f_flags & O_NONBLOCK)
 			return -EAGAIN;
 
 		/* wait till a frame is ready */
 		ret = wait_event_interruptible_timeout(gspca_dev->wq,
-			i != atomic_read(&gspca_dev->fr_i) ||
-			!gspca_dev->streaming || !gspca_dev->present,
+			frame_ready(gspca_dev, file, v4l2_buf->memory),
 			msecs_to_jiffies(3000));
 		if (ret < 0)
 			return ret;
-		if (ret == 0 || !gspca_dev->streaming || !gspca_dev->present)
+		if (ret == 0)
 			return -EIO;
+
+		if (mutex_lock_interruptible(&gspca_dev->queue_lock))
+			return -ERESTARTSYS;
 	}
 
+	i = gspca_dev->fr_o;
+	j = gspca_dev->fr_queue[i];
+	frame = &gspca_dev->frame[j];
+
 	gspca_dev->fr_o = (i + 1) % GSPCA_MAX_FRAMES;
 
 	if (gspca_dev->sd_desc->dq_callback) {
@@ -1861,46 +1894,12 @@ static int frame_wait(struct gspca_dev *
 			gspca_dev->sd_desc->dq_callback(gspca_dev);
 		mutex_unlock(&gspca_dev->usb_lock);
 	}
-	return gspca_dev->fr_queue[i];
-}
-
-/*
- * dequeue a video buffer
- *
- * If nonblock_ing is false, block until a buffer is available.
- */
-static int vidioc_dqbuf(struct file *file, void *priv,
-			struct v4l2_buffer *v4l2_buf)
-{
-	struct gspca_dev *gspca_dev = priv;
-	struct gspca_frame *frame;
-	int i, ret;
-
-	PDEBUG(D_FRAM, "dqbuf");
-	if (v4l2_buf->memory != gspca_dev->memory)
-		return -EINVAL;
-
-	if (!gspca_dev->present)
-		return -ENODEV;
 
-	/* if not streaming, be sure the application will not loop forever */
-	if (!(file->f_flags & O_NONBLOCK)
-	    && !gspca_dev->streaming && gspca_dev->users == 1)
-		return -EINVAL;
-
-	/* only the capturing file may dequeue */
-	if (gspca_dev->capt_file != file)
-		return -EINVAL;
-
-	/* only one dequeue / read at a time */
-	if (mutex_lock_interruptible(&gspca_dev->read_lock))
-		return -ERESTARTSYS;
+	frame->v4l2_buf.flags &= ~V4L2_BUF_FLAG_DONE;
+	memcpy(v4l2_buf, &frame->v4l2_buf, sizeof *v4l2_buf);
+	PDEBUG(D_FRAM, "dqbuf %d", j);
+	ret = 0;
 
-	ret = frame_wait(gspca_dev, file->f_flags & O_NONBLOCK);
-	if (ret < 0)
-		goto out;
-	i = ret;				/* frame index */
-	frame = &gspca_dev->frame[i];
 	if (gspca_dev->memory == V4L2_MEMORY_USERPTR) {
 		if (copy_to_user((__u8 __user *) frame->v4l2_buf.m.userptr,
 				 frame->data,
@@ -1908,15 +1907,10 @@ static int vidioc_dqbuf(struct file *fil
 			PDEBUG(D_ERR|D_STREAM,
 				"dqbuf cp to user failed");
 			ret = -EFAULT;
-			goto out;
 		}
 	}
-	frame->v4l2_buf.flags &= ~V4L2_BUF_FLAG_DONE;
-	memcpy(v4l2_buf, &frame->v4l2_buf, sizeof *v4l2_buf);
-	PDEBUG(D_FRAM, "dqbuf %d", i);
-	ret = 0;
 out:
-	mutex_unlock(&gspca_dev->read_lock);
+	mutex_unlock(&gspca_dev->queue_lock);
 	return ret;
 }
 
@@ -2031,9 +2025,7 @@ static unsigned int dev_poll(struct file
 	poll_wait(file, &gspca_dev->wq, wait);
 
 	/* if reqbufs is not done, the user would use read() */
-	if (gspca_dev->nframes == 0) {
-		if (gspca_dev->memory != GSPCA_MEMORY_NO)
-			return POLLERR;		/* not the 1st time */
+	if (gspca_dev->memory == GSPCA_MEMORY_NO) {
 		ret = read_alloc(gspca_dev, file);
 		if (ret != 0)
 			return POLLERR;
@@ -2065,18 +2057,10 @@ static ssize_t dev_read(struct file *fil
 	PDEBUG(D_FRAM, "read (%zd)", count);
 	if (!gspca_dev->present)
 		return -ENODEV;
-	switch (gspca_dev->memory) {
-	case GSPCA_MEMORY_NO:			/* first time */
+	if (gspca_dev->memory == GSPCA_MEMORY_NO) { /* first time ? */
 		ret = read_alloc(gspca_dev, file);
 		if (ret != 0)
 			return ret;
-		break;
-	case GSPCA_MEMORY_READ:
-		if (gspca_dev->capt_file == file)
-			break;
-		/* fall thru */
-	default:
-		return -EINVAL;
 	}
 
 	/* get a frame */
@@ -2264,7 +2248,6 @@ int gspca_dev_probe2(struct usb_interfac
 		goto out;
 
 	mutex_init(&gspca_dev->usb_lock);
-	mutex_init(&gspca_dev->read_lock);
 	mutex_init(&gspca_dev->queue_lock);
 	init_waitqueue_head(&gspca_dev->wq);
 
@@ -2339,12 +2322,11 @@ void gspca_disconnect(struct usb_interfa
 	PDEBUG(D_PROBE, "%s disconnect",
 		video_device_node_name(&gspca_dev->vdev));
 	mutex_lock(&gspca_dev->usb_lock);
+
 	gspca_dev->present = 0;
+	wake_up_interruptible(&gspca_dev->wq);
 
-	if (gspca_dev->streaming) {
-		destroy_urbs(gspca_dev);
-		wake_up_interruptible(&gspca_dev->wq);
-	}
+	destroy_urbs(gspca_dev);
 
 #if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
 	gspca_input_destroy_urb(gspca_dev);
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/gspca/gspca.h linux-libre-2.6.38-gnu1/drivers/media/video/gspca/gspca.h
--- linux-libre-2.6.37-gnu1/drivers/media/video/gspca/gspca.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/gspca/gspca.h	2011-03-14 21:20:32.000000000 -0400
@@ -62,7 +62,7 @@ struct gspca_ctrl {
 /* device information - set at probe time */
 struct cam {
 	const struct v4l2_pix_format *cam_mode;	/* size nmodes */
-	const struct framerates *mode_framerates; /* must have size nmode,
+	const struct framerates *mode_framerates; /* must have size nmodes,
 						   * just like cam_mode */
 	struct gspca_ctrl *ctrls;	/* control table - size nctrls */
 					/* may be NULL */
@@ -93,7 +93,7 @@ typedef int (*cam_reg_op) (struct gspca_
 				struct v4l2_dbg_register *);
 typedef int (*cam_ident_op) (struct gspca_dev *,
 				struct v4l2_dbg_chip_ident *);
-typedef int (*cam_streamparm_op) (struct gspca_dev *,
+typedef void (*cam_streamparm_op) (struct gspca_dev *,
 				  struct v4l2_streamparm *);
 typedef int (*cam_qmnu_op) (struct gspca_dev *,
 			struct v4l2_querymenu *);
@@ -205,14 +205,12 @@ struct gspca_dev {
 
 	wait_queue_head_t wq;		/* wait queue */
 	struct mutex usb_lock;		/* usb exchange protection */
-	struct mutex read_lock;		/* read protection */
 	struct mutex queue_lock;	/* ISOC queue protection */
 	int usb_err;			/* USB error - protected by usb_lock */
 	u16 pkt_size;			/* ISOC packet size */
 #ifdef CONFIG_PM
 	char frozen;			/* suspend - resume */
 #endif
-	char users;			/* number of opens */
 	char present;			/* device connected */
 	char nbufread;			/* number of buffers for read() */
 	char memory;			/* memory type (V4L2_MEMORY_xxx) */
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/gspca/jeilinj.c linux-libre-2.6.38-gnu1/drivers/media/video/gspca/jeilinj.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/gspca/jeilinj.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/gspca/jeilinj.c	2011-03-14 21:20:32.000000000 -0400
@@ -314,7 +314,7 @@ static int sd_start(struct gspca_dev *gs
 }
 
 /* Table of supported USB devices */
-static const __devinitdata struct usb_device_id device_table[] = {
+static const struct usb_device_id device_table[] = {
 	{USB_DEVICE(0x0979, 0x0280)},
 	{}
 };
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/gspca/jpeg.h linux-libre-2.6.38-gnu1/drivers/media/video/gspca/jpeg.h
--- linux-libre-2.6.37-gnu1/drivers/media/video/gspca/jpeg.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/gspca/jpeg.h	2011-03-14 21:20:32.000000000 -0400
@@ -141,9 +141,9 @@ static void jpeg_define(u8 *jpeg_hdr,
 	memcpy(jpeg_hdr, jpeg_head, sizeof jpeg_head);
 #ifndef CONEX_CAM
 	jpeg_hdr[JPEG_HEIGHT_OFFSET + 0] = height >> 8;
-	jpeg_hdr[JPEG_HEIGHT_OFFSET + 1] = height & 0xff;
+	jpeg_hdr[JPEG_HEIGHT_OFFSET + 1] = height;
 	jpeg_hdr[JPEG_HEIGHT_OFFSET + 2] = width >> 8;
-	jpeg_hdr[JPEG_HEIGHT_OFFSET + 3] = width & 0xff;
+	jpeg_hdr[JPEG_HEIGHT_OFFSET + 3] = width;
 	jpeg_hdr[JPEG_HEIGHT_OFFSET + 6] = samplesY;
 #endif
 }
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/gspca/konica.c linux-libre-2.6.38-gnu1/drivers/media/video/gspca/konica.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/gspca/konica.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/gspca/konica.c	2011-03-14 21:20:32.000000000 -0400
@@ -607,7 +607,7 @@ static const struct sd_desc sd_desc = {
 };
 
 /* -- module initialisation -- */
-static const __devinitdata struct usb_device_id device_table[] = {
+static const struct usb_device_id device_table[] = {
 	{USB_DEVICE(0x04c8, 0x0720)}, /* Intel YC 76 */
 	{}
 };
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/gspca/m5602/m5602_core.c linux-libre-2.6.38-gnu1/drivers/media/video/gspca/m5602/m5602_core.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/gspca/m5602/m5602_core.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/gspca/m5602/m5602_core.c	2011-03-14 21:20:32.000000000 -0400
@@ -28,7 +28,7 @@ int force_sensor;
 static int dump_bridge;
 int dump_sensor;
 
-static const __devinitdata struct usb_device_id m5602_table[] = {
+static const struct usb_device_id m5602_table[] = {
 	{USB_DEVICE(0x0402, 0x5602)},
 	{}
 };
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/gspca/m5602/m5602_ov9650.c linux-libre-2.6.38-gnu1/drivers/media/video/gspca/m5602/m5602_ov9650.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/gspca/m5602/m5602_ov9650.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/gspca/m5602/m5602_ov9650.c	2011-03-14 21:20:32.000000000 -0400
@@ -624,7 +624,7 @@ static int ov9650_set_gain(struct gspca_
 
 	/* Mask away all uninteresting bits */
 	i2c_data = ((val & 0x0300) >> 2) |
-			(i2c_data & 0x3F);
+			(i2c_data & 0x3f);
 	err = m5602_write_sensor(sd, OV9650_VREF, &i2c_data, 1);
 	if (err < 0)
 		return err;
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/gspca/mars.c linux-libre-2.6.38-gnu1/drivers/media/video/gspca/mars.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/gspca/mars.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/gspca/mars.c	2011-03-14 21:20:32.000000000 -0400
@@ -490,7 +490,7 @@ static const struct sd_desc sd_desc = {
 };
 
 /* -- module initialisation -- */
-static const __devinitdata struct usb_device_id device_table[] = {
+static const struct usb_device_id device_table[] = {
 	{USB_DEVICE(0x093a, 0x050f)},
 	{}
 };
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/gspca/mr97310a.c linux-libre-2.6.38-gnu1/drivers/media/video/gspca/mr97310a.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/gspca/mr97310a.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/gspca/mr97310a.c	2011-03-14 21:20:32.000000000 -0400
@@ -1229,7 +1229,7 @@ static const struct sd_desc sd_desc = {
 };
 
 /* -- module initialisation -- */
-static const __devinitdata struct usb_device_id device_table[] = {
+static const struct usb_device_id device_table[] = {
 	{USB_DEVICE(0x08ca, 0x0110)},	/* Trust Spyc@m 100 */
 	{USB_DEVICE(0x08ca, 0x0111)},	/* Aiptek Pencam VGA+ */
 	{USB_DEVICE(0x093a, 0x010f)},	/* All other known MR97310A VGA cams */
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/gspca/ov519.c linux-libre-2.6.38-gnu1/drivers/media/video/gspca/ov519.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/gspca/ov519.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/gspca/ov519.c	2011-03-14 21:20:32.000000000 -0400
@@ -75,14 +75,14 @@ struct sd {
 
 	struct gspca_ctrl ctrls[NCTRL];
 
-	__u8 packet_nr;
+	u8 packet_nr;
 
 	char bridge;
 #define BRIDGE_OV511		0
 #define BRIDGE_OV511PLUS	1
 #define BRIDGE_OV518		2
 #define BRIDGE_OV518PLUS	3
-#define BRIDGE_OV519		4
+#define BRIDGE_OV519		4		/* = ov530 */
 #define BRIDGE_OVFX2		5
 #define BRIDGE_W9968CF		6
 #define BRIDGE_MASK		7
@@ -94,42 +94,44 @@ struct sd {
 	char snapshot_needs_reset;
 
 	/* Determined by sensor type */
-	__u8 sif;
+	u8 sif;
 
-	__u8 quality;
+	u8 quality;
 #define QUALITY_MIN 50
 #define QUALITY_MAX 70
 #define QUALITY_DEF 50
 
-	__u8 stopped;		/* Streaming is temporarily paused */
-	__u8 first_frame;
+	u8 stopped;		/* Streaming is temporarily paused */
+	u8 first_frame;
 
-	__u8 frame_rate;	/* current Framerate */
-	__u8 clockdiv;		/* clockdiv override */
+	u8 frame_rate;		/* current Framerate */
+	u8 clockdiv;		/* clockdiv override */
 
-	char sensor;		/* Type of image sensor chip (SEN_*) */
-#define SEN_UNKNOWN 0
-#define SEN_OV2610 1
-#define SEN_OV3610 2
-#define SEN_OV6620 3
-#define SEN_OV6630 4
-#define SEN_OV66308AF 5
-#define SEN_OV7610 6
-#define SEN_OV7620 7
-#define SEN_OV7620AE 8
-#define SEN_OV7640 9
-#define SEN_OV7648 10
-#define SEN_OV7670 11
-#define SEN_OV76BE 12
-#define SEN_OV8610 13
+	s8 sensor;		/* Type of image sensor chip (SEN_*) */
 
 	u8 sensor_addr;
-	int sensor_width;
-	int sensor_height;
-	int sensor_reg_cache[256];
+	u16 sensor_width;
+	u16 sensor_height;
+	s16 sensor_reg_cache[256];
 
 	u8 jpeg_hdr[JPEG_HDR_SZ];
 };
+enum sensors {
+	SEN_OV2610,
+	SEN_OV3610,
+	SEN_OV6620,
+	SEN_OV6630,
+	SEN_OV66308AF,
+	SEN_OV7610,
+	SEN_OV7620,
+	SEN_OV7620AE,
+	SEN_OV7640,
+	SEN_OV7648,
+	SEN_OV7660,
+	SEN_OV7670,
+	SEN_OV76BE,
+	SEN_OV8610,
+};
 
 /* Note this is a bit of a hack, but the w9968cf driver needs the code for all
    the ov sensors which is already present here. When we have the time we
@@ -182,7 +184,7 @@ static const struct ctrl sd_ctrls[] = {
 	    },
 	    .set_control = setcolors,
 	},
-/* The flip controls work with ov7670 only */
+/* The flip controls work for sensors ov7660 and ov7670 only */
 [HFLIP] = {
 	    {
 		.id      = V4L2_CID_HFLIP,
@@ -225,7 +227,7 @@ static const struct ctrl sd_ctrls[] = {
 		.type    = V4L2_CTRL_TYPE_MENU,
 		.name    = "Light frequency filter",
 		.minimum = 0,
-		.maximum = 2,	/* 0: 0, 1: 50Hz, 2:60Hz */
+		.maximum = 2,	/* 0: no flicker, 1: 50Hz, 2:60Hz, 3: auto */
 		.step    = 1,
 		.default_value = 0,
 	    },
@@ -233,6 +235,53 @@ static const struct ctrl sd_ctrls[] = {
 	},
 };
 
+/* table of the disabled controls */
+static const unsigned ctrl_dis[] = {
+[SEN_OV2610] =		(1 << NCTRL) - 1,	/* no control */
+
+[SEN_OV3610] =		(1 << NCTRL) - 1,	/* no control */
+
+[SEN_OV6620] =		(1 << HFLIP) |
+			(1 << VFLIP),
+
+[SEN_OV6630] =		(1 << HFLIP) |
+			(1 << VFLIP),
+
+[SEN_OV66308AF] =	(1 << HFLIP) |
+			(1 << VFLIP),
+
+[SEN_OV7610] =		(1 << HFLIP) |
+			(1 << VFLIP),
+
+[SEN_OV7620] =		(1 << HFLIP) |
+			(1 << VFLIP),
+
+[SEN_OV7620AE] =	(1 << HFLIP) |
+			(1 << VFLIP),
+
+[SEN_OV7640] =		(1 << HFLIP) |
+			(1 << VFLIP) |
+			(1 << AUTOBRIGHT) |
+			(1 << CONTRAST),
+
+[SEN_OV7648] =		(1 << HFLIP) |
+			(1 << VFLIP) |
+			(1 << AUTOBRIGHT) |
+			(1 << CONTRAST),
+
+[SEN_OV7660] =		(1 << AUTOBRIGHT),
+
+[SEN_OV7670] =		(1 << COLORS) |
+			(1 << AUTOBRIGHT),
+
+[SEN_OV76BE] =		(1 << HFLIP) |
+			(1 << VFLIP),
+
+[SEN_OV8610] =		(1 << HFLIP) |
+			(1 << VFLIP) |
+			(1 << FREQ),
+};
+
 static const struct v4l2_pix_format ov519_vga_mode[] = {
 	{320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
 		.bytesperline = 320,
@@ -412,7 +461,6 @@ static const struct v4l2_pix_format ovfx
 		.priv = 0},
 };
 
-
 /* Registers common to OV511 / OV518 */
 #define R51x_FIFO_PSIZE			0x30	/* 2 bytes wide w/ OV518(+) */
 #define R51x_SYS_RESET			0x50
@@ -420,7 +468,7 @@ static const struct v4l2_pix_format ovfx
 	#define	OV511_RESET_OMNICE	0x08
 #define R51x_SYS_INIT			0x53
 #define R51x_SYS_SNAP			0x52
-#define R51x_SYS_CUST_ID		0x5F
+#define R51x_SYS_CUST_ID		0x5f
 #define R51x_COMP_LUT_BEGIN		0x80
 
 /* OV511 Camera interface register numbers */
@@ -435,13 +483,12 @@ static const struct v4l2_pix_format ovfx
 #define R511_CAM_OPTS			0x18
 
 #define R511_SNAP_FRAME			0x19
-#define R511_SNAP_PXCNT			0x1A
-#define R511_SNAP_LNCNT			0x1B
-#define R511_SNAP_PXDIV			0x1C
-#define R511_SNAP_LNDIV			0x1D
-#define R511_SNAP_UV_EN			0x1E
-#define R511_SNAP_UV_EN			0x1E
-#define R511_SNAP_OPTS			0x1F
+#define R511_SNAP_PXCNT			0x1a
+#define R511_SNAP_LNCNT			0x1b
+#define R511_SNAP_PXDIV			0x1c
+#define R511_SNAP_LNDIV			0x1d
+#define R511_SNAP_UV_EN			0x1e
+#define R511_SNAP_OPTS			0x1f
 
 #define R511_DRAM_FLOW_CTL		0x20
 #define R511_FIFO_OPTS			0x31
@@ -466,13 +513,14 @@ static const struct v4l2_pix_format ovfx
 #define OV519_R25_FORMAT		0x25
 
 /* OV519 System Controller register numbers */
-#define OV519_SYS_RESET1 0x51
-#define OV519_SYS_EN_CLK1 0x54
+#define OV519_R51_RESET1		0x51
+#define OV519_R54_EN_CLK1		0x54
+#define OV519_R57_SNAPSHOT		0x57
 
 #define OV519_GPIO_DATA_OUT0		0x71
 #define OV519_GPIO_IO_CTRL0		0x72
 
-#define OV511_ENDPOINT_ADDRESS  1	/* Isoc endpoint number */
+/*#define OV511_ENDPOINT_ADDRESS 1	 * Isoc endpoint number */
 
 /*
  * The FX2 chip does not give us a zero length read at end of frame.
@@ -526,80 +574,81 @@ static const struct v4l2_pix_format ovfx
 #define OV7610_REG_ID_LOW	0x1d	/* manufacturer ID LSB */
 #define OV7610_REG_COM_I	0x29	/* misc settings */
 
-/* OV7670 registers */
-#define OV7670_REG_GAIN        0x00    /* Gain lower 8 bits (rest in vref) */
-#define OV7670_REG_BLUE        0x01    /* blue gain */
-#define OV7670_REG_RED         0x02    /* red gain */
-#define OV7670_REG_VREF        0x03    /* Pieces of GAIN, VSTART, VSTOP */
-#define OV7670_REG_COM1        0x04    /* Control 1 */
-#define OV7670_REG_AECHH       0x07    /* AEC MS 5 bits */
-#define OV7670_REG_COM3        0x0c    /* Control 3 */
-#define OV7670_REG_COM4        0x0d    /* Control 4 */
-#define OV7670_REG_COM5        0x0e    /* All "reserved" */
-#define OV7670_REG_COM6        0x0f    /* Control 6 */
-#define OV7670_REG_AECH        0x10    /* More bits of AEC value */
-#define OV7670_REG_CLKRC       0x11    /* Clock control */
-#define OV7670_REG_COM7        0x12    /* Control 7 */
-#define   OV7670_COM7_FMT_VGA    0x00
-#define   OV7670_COM7_YUV        0x00    /* YUV */
-#define   OV7670_COM7_FMT_QVGA   0x10    /* QVGA format */
-#define   OV7670_COM7_FMT_MASK   0x38
-#define   OV7670_COM7_RESET      0x80    /* Register reset */
-#define OV7670_REG_COM8        0x13    /* Control 8 */
-#define   OV7670_COM8_AEC        0x01    /* Auto exposure enable */
-#define   OV7670_COM8_AWB        0x02    /* White balance enable */
-#define   OV7670_COM8_AGC        0x04    /* Auto gain enable */
-#define   OV7670_COM8_BFILT      0x20    /* Band filter enable */
-#define   OV7670_COM8_AECSTEP    0x40    /* Unlimited AEC step size */
-#define   OV7670_COM8_FASTAEC    0x80    /* Enable fast AGC/AEC */
-#define OV7670_REG_COM9        0x14    /* Control 9  - gain ceiling */
-#define OV7670_REG_COM10       0x15    /* Control 10 */
-#define OV7670_REG_HSTART      0x17    /* Horiz start high bits */
-#define OV7670_REG_HSTOP       0x18    /* Horiz stop high bits */
-#define OV7670_REG_VSTART      0x19    /* Vert start high bits */
-#define OV7670_REG_VSTOP       0x1a    /* Vert stop high bits */
-#define OV7670_REG_MVFP        0x1e    /* Mirror / vflip */
-#define   OV7670_MVFP_VFLIP	 0x10    /* vertical flip */
-#define   OV7670_MVFP_MIRROR     0x20    /* Mirror image */
-#define OV7670_REG_AEW         0x24    /* AGC upper limit */
-#define OV7670_REG_AEB         0x25    /* AGC lower limit */
-#define OV7670_REG_VPT         0x26    /* AGC/AEC fast mode op region */
-#define OV7670_REG_HREF        0x32    /* HREF pieces */
-#define OV7670_REG_TSLB        0x3a    /* lots of stuff */
-#define OV7670_REG_COM11       0x3b    /* Control 11 */
-#define   OV7670_COM11_EXP       0x02
-#define   OV7670_COM11_HZAUTO    0x10    /* Auto detect 50/60 Hz */
-#define OV7670_REG_COM12       0x3c    /* Control 12 */
-#define OV7670_REG_COM13       0x3d    /* Control 13 */
-#define   OV7670_COM13_GAMMA     0x80    /* Gamma enable */
-#define   OV7670_COM13_UVSAT     0x40    /* UV saturation auto adjustment */
-#define OV7670_REG_COM14       0x3e    /* Control 14 */
-#define OV7670_REG_EDGE        0x3f    /* Edge enhancement factor */
-#define OV7670_REG_COM15       0x40    /* Control 15 */
-#define   OV7670_COM15_R00FF     0xc0    /*            00 to FF */
-#define OV7670_REG_COM16       0x41    /* Control 16 */
-#define   OV7670_COM16_AWBGAIN   0x08    /* AWB gain enable */
-#define OV7670_REG_BRIGHT      0x55    /* Brightness */
-#define OV7670_REG_CONTRAS     0x56    /* Contrast control */
-#define OV7670_REG_GFIX        0x69    /* Fix gain control */
-#define OV7670_REG_RGB444      0x8c    /* RGB 444 control */
-#define OV7670_REG_HAECC1      0x9f    /* Hist AEC/AGC control 1 */
-#define OV7670_REG_HAECC2      0xa0    /* Hist AEC/AGC control 2 */
-#define OV7670_REG_BD50MAX     0xa5    /* 50hz banding step limit */
-#define OV7670_REG_HAECC3      0xa6    /* Hist AEC/AGC control 3 */
-#define OV7670_REG_HAECC4      0xa7    /* Hist AEC/AGC control 4 */
-#define OV7670_REG_HAECC5      0xa8    /* Hist AEC/AGC control 5 */
-#define OV7670_REG_HAECC6      0xa9    /* Hist AEC/AGC control 6 */
-#define OV7670_REG_HAECC7      0xaa    /* Hist AEC/AGC control 7 */
-#define OV7670_REG_BD60MAX     0xab    /* 60hz banding step limit */
+/* OV7660 and OV7670 registers */
+#define OV7670_R00_GAIN		0x00	/* Gain lower 8 bits (rest in vref) */
+#define OV7670_R01_BLUE		0x01	/* blue gain */
+#define OV7670_R02_RED		0x02	/* red gain */
+#define OV7670_R03_VREF		0x03	/* Pieces of GAIN, VSTART, VSTOP */
+#define OV7670_R04_COM1		0x04	/* Control 1 */
+/*#define OV7670_R07_AECHH	0x07	 * AEC MS 5 bits */
+#define OV7670_R0C_COM3		0x0c	/* Control 3 */
+#define OV7670_R0D_COM4		0x0d	/* Control 4 */
+#define OV7670_R0E_COM5		0x0e	/* All "reserved" */
+#define OV7670_R0F_COM6		0x0f	/* Control 6 */
+#define OV7670_R10_AECH		0x10	/* More bits of AEC value */
+#define OV7670_R11_CLKRC	0x11	/* Clock control */
+#define OV7670_R12_COM7		0x12	/* Control 7 */
+#define   OV7670_COM7_FMT_VGA	 0x00
+/*#define   OV7670_COM7_YUV	 0x00	 * YUV */
+#define   OV7670_COM7_FMT_QVGA	 0x10	/* QVGA format */
+#define   OV7670_COM7_FMT_MASK	 0x38
+#define   OV7670_COM7_RESET	 0x80	/* Register reset */
+#define OV7670_R13_COM8		0x13	/* Control 8 */
+#define   OV7670_COM8_AEC	 0x01	/* Auto exposure enable */
+#define   OV7670_COM8_AWB	 0x02	/* White balance enable */
+#define   OV7670_COM8_AGC	 0x04	/* Auto gain enable */
+#define   OV7670_COM8_BFILT	 0x20	/* Band filter enable */
+#define   OV7670_COM8_AECSTEP	 0x40	/* Unlimited AEC step size */
+#define   OV7670_COM8_FASTAEC	 0x80	/* Enable fast AGC/AEC */
+#define OV7670_R14_COM9		0x14	/* Control 9 - gain ceiling */
+#define OV7670_R15_COM10	0x15	/* Control 10 */
+#define OV7670_R17_HSTART	0x17	/* Horiz start high bits */
+#define OV7670_R18_HSTOP	0x18	/* Horiz stop high bits */
+#define OV7670_R19_VSTART	0x19	/* Vert start high bits */
+#define OV7670_R1A_VSTOP	0x1a	/* Vert stop high bits */
+#define OV7670_R1E_MVFP		0x1e	/* Mirror / vflip */
+#define   OV7670_MVFP_VFLIP	 0x10	/* vertical flip */
+#define   OV7670_MVFP_MIRROR	 0x20	/* Mirror image */
+#define OV7670_R24_AEW		0x24	/* AGC upper limit */
+#define OV7670_R25_AEB		0x25	/* AGC lower limit */
+#define OV7670_R26_VPT		0x26	/* AGC/AEC fast mode op region */
+#define OV7670_R32_HREF		0x32	/* HREF pieces */
+#define OV7670_R3A_TSLB		0x3a	/* lots of stuff */
+#define OV7670_R3B_COM11	0x3b	/* Control 11 */
+#define   OV7670_COM11_EXP	 0x02
+#define   OV7670_COM11_HZAUTO	 0x10	/* Auto detect 50/60 Hz */
+#define OV7670_R3C_COM12	0x3c	/* Control 12 */
+#define OV7670_R3D_COM13	0x3d	/* Control 13 */
+#define   OV7670_COM13_GAMMA	 0x80	/* Gamma enable */
+#define   OV7670_COM13_UVSAT	 0x40	/* UV saturation auto adjustment */
+#define OV7670_R3E_COM14	0x3e	/* Control 14 */
+#define OV7670_R3F_EDGE		0x3f	/* Edge enhancement factor */
+#define OV7670_R40_COM15	0x40	/* Control 15 */
+/*#define   OV7670_COM15_R00FF	 0xc0	 *	00 to FF */
+#define OV7670_R41_COM16	0x41	/* Control 16 */
+#define   OV7670_COM16_AWBGAIN	 0x08	/* AWB gain enable */
+/* end of ov7660 common registers */
+#define OV7670_R55_BRIGHT	0x55	/* Brightness */
+#define OV7670_R56_CONTRAS	0x56	/* Contrast control */
+#define OV7670_R69_GFIX		0x69	/* Fix gain control */
+/*#define OV7670_R8C_RGB444	0x8c	 * RGB 444 control */
+#define OV7670_R9F_HAECC1	0x9f	/* Hist AEC/AGC control 1 */
+#define OV7670_RA0_HAECC2	0xa0	/* Hist AEC/AGC control 2 */
+#define OV7670_RA5_BD50MAX	0xa5	/* 50hz banding step limit */
+#define OV7670_RA6_HAECC3	0xa6	/* Hist AEC/AGC control 3 */
+#define OV7670_RA7_HAECC4	0xa7	/* Hist AEC/AGC control 4 */
+#define OV7670_RA8_HAECC5	0xa8	/* Hist AEC/AGC control 5 */
+#define OV7670_RA9_HAECC6	0xa9	/* Hist AEC/AGC control 6 */
+#define OV7670_RAA_HAECC7	0xaa	/* Hist AEC/AGC control 7 */
+#define OV7670_RAB_BD60MAX	0xab	/* 60hz banding step limit */
 
 struct ov_regvals {
-	__u8 reg;
-	__u8 val;
+	u8 reg;
+	u8 val;
 };
 struct ov_i2c_regvals {
-	__u8 reg;
-	__u8 val;
+	u8 reg;
+	u8 val;
 };
 
 /* Settings for OV2610 camera chip */
@@ -617,7 +666,6 @@ static const struct ov_i2c_regvals norm_
 	 * "wait 4096 external clock ... to make sure the sensor is
 	 * stable and ready to access registers" i.e. 160us at 24MHz
 	 */
-
 	{ 0x12, 0x80 }, /* COMH reset */
 	{ 0x12, 0x00 }, /* QXGA, master */
 
@@ -650,7 +698,7 @@ static const struct ov_i2c_regvals norm_
 	 *    COMI[0] "Exposure control"
 	 *                  =   0 (0x00) .......0 "Manual"
 	 */
-	{ 0x13, 0xC0 },
+	{ 0x13, 0xc0 },
 
 	/*
 	 * 09 COMC "Common Control C"
@@ -706,7 +754,7 @@ static const struct ov_i2c_regvals norm_
 	 *    COME[0] "Auto zero circuit select"
 	 *                  =   1 (0x01) .......1 "On"
 	 */
-	{ 0x0d, 0xA1 },
+	{ 0x0d, 0xa1 },
 
 	/*
 	 * 0E COMF "Common Control F"
@@ -770,7 +818,7 @@ static const struct ov_i2c_regvals norm_
 	 *    COMJ[0] "Reserved"
 	 *                  =   0 (0x00) .......0
 	 */
-	{ 0x14, 0xC6 },
+	{ 0x14, 0xc6 },
 
 	/*
 	 * 15 COMK "Common Control K"
@@ -876,7 +924,7 @@ static const struct ov_i2c_regvals norm_
 	 *    FVOPT[7:0] "Range"
 	 *                  =  31 (0x1F) 00011111
 	 */
-	{ 0x3c, 0x1F },
+	{ 0x3c, 0x1f },
 
 	/*
 	 * 44 Undocumented  =   0 (0x00) 00000000
@@ -925,7 +973,7 @@ static const struct ov_i2c_regvals norm_
 	 *    48[7:0] "It's a secret"
 	 *                  = 192 (0xC0) 11000000
 	 */
-	{ 0x48, 0xC0 },
+	{ 0x48, 0xc0 },
 
 	/*
 	 * 49 Undocumented  =  25 (0x19) 00011001
@@ -939,18 +987,18 @@ static const struct ov_i2c_regvals norm_
 	 *    4B[7:0] "It's a secret"
 	 *                  = 128 (0x80) 10000000
 	 */
-	{ 0x4B, 0x80 },
+	{ 0x4b, 0x80 },
 
 	/*
 	 * 4D Undocumented  = 196 (0xC4) 11000100
 	 *    4D[7:0] "It's a secret"
 	 *                  = 196 (0xC4) 11000100
 	 */
-	{ 0x4D, 0xC4 },
+	{ 0x4d, 0xc4 },
 
 	/*
 	 * 35 VREF "Reference Voltage Control"
-	 *                  =  76 (0x4C) 01001100
+	 *                  =  76 (0x4c) 01001100
 	 *    VREF[7:5] "Column high reference control"
 	 *                  =   2 (0x02) 010..... "higher voltage"
 	 *    VREF[4:2] "Column low reference control"
@@ -958,21 +1006,21 @@ static const struct ov_i2c_regvals norm_
 	 *    VREF[1:0] "Reserved"
 	 *                  =   0 (0x00) ......00
 	 */
-	{ 0x35, 0x4C },
+	{ 0x35, 0x4c },
 
 	/*
 	 * 3D Undocumented  =   0 (0x00) 00000000
 	 *    3D[7:0] "It's a secret"
 	 *                  =   0 (0x00) 00000000
 	 */
-	{ 0x3D, 0x00 },
+	{ 0x3d, 0x00 },
 
 	/*
 	 * 3E Undocumented  =   0 (0x00) 00000000
 	 *    3E[7:0] "It's a secret"
 	 *                  =   0 (0x00) 00000000
 	 */
-	{ 0x3E, 0x00 },
+	{ 0x3e, 0x00 },
 
 	/*
 	 * 3B FREFB "Internal Reference Adjustment"
@@ -1012,7 +1060,7 @@ static const struct ov_i2c_regvals norm_
 	 *    VBLM[3:0] "Sensor current control"
 	 *                  =  10 (0x0A) ....1010
 	 */
-	{ 0x34, 0x5A },
+	{ 0x34, 0x5a },
 
 	/*
 	 * 3B FREFB "Internal Reference Adjustment"
@@ -1078,7 +1126,7 @@ static const struct ov_i2c_regvals norm_
 	 *    HREFST[7:0] "Horizontal window start, 8 MSBs"
 	 *                  =  31 (0x1F) 00011111
 	 */
-	{ 0x17, 0x1F },
+	{ 0x17, 0x1f },
 
 	/*
 	 * 18 HREFEND "Horizontal window end"
@@ -1086,7 +1134,7 @@ static const struct ov_i2c_regvals norm_
 	 *    HREFEND[7:0] "Horizontal Window End, 8 MSBs"
 	 *                  =  95 (0x5F) 01011111
 	 */
-	{ 0x18, 0x5F },
+	{ 0x18, 0x5f },
 
 	/*
 	 * 19 VSTRT "Vertical window start"
@@ -1126,7 +1174,7 @@ static const struct ov_i2c_regvals norm_
 	 *    COMA[1:0] "Vertical window start line control 2 LSBs"
 	 *                  =   2 (0x02) ......10
 	 */
-	{ 0x03, 0x4A },
+	{ 0x03, 0x4a },
 
 	/*
 	 * 11 CLKRC "Clock Rate Control"
@@ -1183,7 +1231,7 @@ static const struct ov_i2c_regvals norm_
 	 *    HREFST[7:0] "Horizontal window start, 8 MSBs"
 	 *                  =  31 (0x1F) 00011111
 	 */
-	{ 0x17, 0x1F },
+	{ 0x17, 0x1f },
 
 	/*
 	 * 18 HREFEND "Horizontal window end"
@@ -1191,7 +1239,7 @@ static const struct ov_i2c_regvals norm_
 	 *    HREFEND[7:0] "Horizontal Window End, 8 MSBs"
 	 *                  =  95 (0x5F) 01011111
 	 */
-	{ 0x18, 0x5F },
+	{ 0x18, 0x5f },
 
 	/*
 	 * 19 VSTRT "Vertical window start"
@@ -1231,7 +1279,7 @@ static const struct ov_i2c_regvals norm_
 	 *    COMA[1:0] "Vertical window start line control 2 LSBs"
 	 *                  =   2 (0x02) ......10
 	 */
-	{ 0x03, 0x4A },
+	{ 0x03, 0x4a },
 
 	/*
 	 * 02 RED "Red Gain Control"
@@ -1241,7 +1289,7 @@ static const struct ov_i2c_regvals norm_
 	 *    RED[6:0] "Value"
 	 *                  =  47 (0x2F) .0101111
 	 */
-	{ 0x02, 0xAF },
+	{ 0x02, 0xaf },
 
 	/*
 	 * 2D ADDVSL "VSYNC Pulse Width"
@@ -1249,7 +1297,7 @@ static const struct ov_i2c_regvals norm_
 	 *    ADDVSL[7:0] "VSYNC pulse width, LSB"
 	 *                  = 210 (0xD2) 11010010
 	 */
-	{ 0x2d, 0xD2 },
+	{ 0x2d, 0xd2 },
 
 	/*
 	 * 00 GAIN          =  24 (0x18) 00011000
@@ -1272,7 +1320,7 @@ static const struct ov_i2c_regvals norm_
 	 *    BLUE[6:0] "Value"
 	 *                  = 112 (0x70) .1110000
 	 */
-	{ 0x01, 0xF0 },
+	{ 0x01, 0xf0 },
 
 	/*
 	 * 10 AEC "Automatic Exposure Control"
@@ -1280,14 +1328,14 @@ static const struct ov_i2c_regvals norm_
 	 *    AEC[7:0] "Automatic Exposure Control, 8 MSBs"
 	 *                  =  10 (0x0A) 00001010
 	 */
-	{ 0x10, 0x0A },
+	{ 0x10, 0x0a },
 
-	{ 0xE1, 0x67 },
-	{ 0xE3, 0x03 },
-	{ 0xE4, 0x26 },
-	{ 0xE5, 0x3E },
-	{ 0xF8, 0x01 },
-	{ 0xFF, 0x01 },
+	{ 0xe1, 0x67 },
+	{ 0xe3, 0x03 },
+	{ 0xe4, 0x26 },
+	{ 0xe5, 0x3e },
+	{ 0xf8, 0x01 },
+	{ 0xff, 0x01 },
 };
 
 static const struct ov_i2c_regvals norm_6x20[] = {
@@ -1296,7 +1344,7 @@ static const struct ov_i2c_regvals norm_
 	{ 0x03, 0x60 },
 	{ 0x05, 0x7f }, /* For when autoadjust is off */
 	{ 0x07, 0xa8 },
-	/* The ratio of 0x0c and 0x0d  controls the white point */
+	/* The ratio of 0x0c and 0x0d controls the white point */
 	{ 0x0c, 0x24 },
 	{ 0x0d, 0x24 },
 	{ 0x0f, 0x15 }, /* COMS */
@@ -1464,7 +1512,7 @@ static const struct ov_i2c_regvals norm_
 	{ 0x00, 0x00 },		/* gain */
 	{ 0x01, 0x80 },		/* blue gain */
 	{ 0x02, 0x80 },		/* red gain */
-	{ 0x03, 0xc0 },		/* OV7670_REG_VREF */
+	{ 0x03, 0xc0 },		/* OV7670_R03_VREF */
 	{ 0x06, 0x60 },
 	{ 0x07, 0x00 },
 	{ 0x0c, 0x24 },
@@ -1532,33 +1580,177 @@ static const struct ov_i2c_regvals norm_
 	{ 0x12, 0x14 },
 };
 
+static const struct ov_regvals init_519_ov7660[] = {
+	{ 0x5d,	0x03 }, /* Turn off suspend mode */
+	{ 0x53,	0x9b }, /* 0x9f enables the (unused) microcontroller */
+	{ 0x54,	0x0f }, /* bit2 (jpeg enable) */
+	{ 0xa2,	0x20 }, /* a2-a5 are undocumented */
+	{ 0xa3,	0x18 },
+	{ 0xa4,	0x04 },
+	{ 0xa5,	0x28 },
+	{ 0x37,	0x00 },	/* SetUsbInit */
+	{ 0x55,	0x02 }, /* 4.096 Mhz audio clock */
+	/* Enable both fields, YUV Input, disable defect comp (why?) */
+	{ 0x20,	0x0c },	/* 0x0d does U <-> V swap */
+	{ 0x21,	0x38 },
+	{ 0x22,	0x1d },
+	{ 0x17,	0x50 }, /* undocumented */
+	{ 0x37,	0x00 }, /* undocumented */
+	{ 0x40,	0xff }, /* I2C timeout counter */
+	{ 0x46,	0x00 }, /* I2C clock prescaler */
+};
+static const struct ov_i2c_regvals norm_7660[] = {
+	{OV7670_R12_COM7, OV7670_COM7_RESET},
+	{OV7670_R11_CLKRC, 0x81},
+	{0x92, 0x00},			/* DM_LNL */
+	{0x93, 0x00},			/* DM_LNH */
+	{0x9d, 0x4c},			/* BD50ST */
+	{0x9e, 0x3f},			/* BD60ST */
+	{OV7670_R3B_COM11, 0x02},
+	{OV7670_R13_COM8, 0xf5},
+	{OV7670_R10_AECH, 0x00},
+	{OV7670_R00_GAIN, 0x00},
+	{OV7670_R01_BLUE, 0x7c},
+	{OV7670_R02_RED, 0x9d},
+	{OV7670_R12_COM7, 0x00},
+	{OV7670_R04_COM1, 00},
+	{OV7670_R18_HSTOP, 0x01},
+	{OV7670_R17_HSTART, 0x13},
+	{OV7670_R32_HREF, 0x92},
+	{OV7670_R19_VSTART, 0x02},
+	{OV7670_R1A_VSTOP, 0x7a},
+	{OV7670_R03_VREF, 0x00},
+	{OV7670_R0E_COM5, 0x04},
+	{OV7670_R0F_COM6, 0x62},
+	{OV7670_R15_COM10, 0x00},
+	{0x16, 0x02},			/* RSVD */
+	{0x1b, 0x00},			/* PSHFT */
+	{OV7670_R1E_MVFP, 0x01},
+	{0x29, 0x3c},			/* RSVD */
+	{0x33, 0x00},			/* CHLF */
+	{0x34, 0x07},			/* ARBLM */
+	{0x35, 0x84},			/* RSVD */
+	{0x36, 0x00},			/* RSVD */
+	{0x37, 0x04},			/* ADC */
+	{0x39, 0x43},			/* OFON */
+	{OV7670_R3A_TSLB, 0x00},
+	{OV7670_R3C_COM12, 0x6c},
+	{OV7670_R3D_COM13, 0x98},
+	{OV7670_R3F_EDGE, 0x23},
+	{OV7670_R40_COM15, 0xc1},
+	{OV7670_R41_COM16, 0x22},
+	{0x6b, 0x0a},			/* DBLV */
+	{0xa1, 0x08},			/* RSVD */
+	{0x69, 0x80},			/* HV */
+	{0x43, 0xf0},			/* RSVD.. */
+	{0x44, 0x10},
+	{0x45, 0x78},
+	{0x46, 0xa8},
+	{0x47, 0x60},
+	{0x48, 0x80},
+	{0x59, 0xba},
+	{0x5a, 0x9a},
+	{0x5b, 0x22},
+	{0x5c, 0xb9},
+	{0x5d, 0x9b},
+	{0x5e, 0x10},
+	{0x5f, 0xe0},
+	{0x60, 0x85},
+	{0x61, 0x60},
+	{0x9f, 0x9d},			/* RSVD */
+	{0xa0, 0xa0},			/* DSPC2 */
+	{0x4f, 0x60},			/* matrix */
+	{0x50, 0x64},
+	{0x51, 0x04},
+	{0x52, 0x18},
+	{0x53, 0x3c},
+	{0x54, 0x54},
+	{0x55, 0x40},
+	{0x56, 0x40},
+	{0x57, 0x40},
+	{0x58, 0x0d},			/* matrix sign */
+	{0x8b, 0xcc},			/* RSVD */
+	{0x8c, 0xcc},
+	{0x8d, 0xcf},
+	{0x6c, 0x40},			/* gamma curve */
+	{0x6d, 0xe0},
+	{0x6e, 0xa0},
+	{0x6f, 0x80},
+	{0x70, 0x70},
+	{0x71, 0x80},
+	{0x72, 0x60},
+	{0x73, 0x60},
+	{0x74, 0x50},
+	{0x75, 0x40},
+	{0x76, 0x38},
+	{0x77, 0x3c},
+	{0x78, 0x32},
+	{0x79, 0x1a},
+	{0x7a, 0x28},
+	{0x7b, 0x24},
+	{0x7c, 0x04},			/* gamma curve */
+	{0x7d, 0x12},
+	{0x7e, 0x26},
+	{0x7f, 0x46},
+	{0x80, 0x54},
+	{0x81, 0x64},
+	{0x82, 0x70},
+	{0x83, 0x7c},
+	{0x84, 0x86},
+	{0x85, 0x8e},
+	{0x86, 0x9c},
+	{0x87, 0xab},
+	{0x88, 0xc4},
+	{0x89, 0xd1},
+	{0x8a, 0xe5},
+	{OV7670_R14_COM9, 0x1e},
+	{OV7670_R24_AEW, 0x80},
+	{OV7670_R25_AEB, 0x72},
+	{OV7670_R26_VPT, 0xb3},
+	{0x62, 0x80},			/* LCC1 */
+	{0x63, 0x80},			/* LCC2 */
+	{0x64, 0x06},			/* LCC3 */
+	{0x65, 0x00},			/* LCC4 */
+	{0x66, 0x01},			/* LCC5 */
+	{0x94, 0x0e},			/* RSVD.. */
+	{0x95, 0x14},
+	{OV7670_R13_COM8, OV7670_COM8_FASTAEC
+			| OV7670_COM8_AECSTEP
+			| OV7670_COM8_BFILT
+			| 0x10
+			| OV7670_COM8_AGC
+			| OV7670_COM8_AWB
+			| OV7670_COM8_AEC},
+	{0xa1, 0xc8}
+};
+
 /* 7670. Defaults taken from OmniVision provided data,
 *  as provided by Jonathan Corbet of OLPC		*/
 static const struct ov_i2c_regvals norm_7670[] = {
-	{ OV7670_REG_COM7, OV7670_COM7_RESET },
-	{ OV7670_REG_TSLB, 0x04 },		/* OV */
-	{ OV7670_REG_COM7, OV7670_COM7_FMT_VGA }, /* VGA */
-	{ OV7670_REG_CLKRC, 0x01 },
+	{ OV7670_R12_COM7, OV7670_COM7_RESET },
+	{ OV7670_R3A_TSLB, 0x04 },		/* OV */
+	{ OV7670_R12_COM7, OV7670_COM7_FMT_VGA }, /* VGA */
+	{ OV7670_R11_CLKRC, 0x01 },
 /*
  * Set the hardware window.  These values from OV don't entirely
  * make sense - hstop is less than hstart.  But they work...
  */
-	{ OV7670_REG_HSTART, 0x13 },
-	{ OV7670_REG_HSTOP, 0x01 },
-	{ OV7670_REG_HREF, 0xb6 },
-	{ OV7670_REG_VSTART, 0x02 },
-	{ OV7670_REG_VSTOP, 0x7a },
-	{ OV7670_REG_VREF, 0x0a },
+	{ OV7670_R17_HSTART, 0x13 },
+	{ OV7670_R18_HSTOP, 0x01 },
+	{ OV7670_R32_HREF, 0xb6 },
+	{ OV7670_R19_VSTART, 0x02 },
+	{ OV7670_R1A_VSTOP, 0x7a },
+	{ OV7670_R03_VREF, 0x0a },
 
-	{ OV7670_REG_COM3, 0x00 },
-	{ OV7670_REG_COM14, 0x00 },
+	{ OV7670_R0C_COM3, 0x00 },
+	{ OV7670_R3E_COM14, 0x00 },
 /* Mystery scaling numbers */
 	{ 0x70, 0x3a },
 	{ 0x71, 0x35 },
 	{ 0x72, 0x11 },
 	{ 0x73, 0xf0 },
 	{ 0xa2, 0x02 },
-/*	{ OV7670_REG_COM10, 0x0 }, */
+/*	{ OV7670_R15_COM10, 0x0 }, */
 
 /* Gamma curve values */
 	{ 0x7a, 0x20 },
@@ -1580,37 +1772,37 @@ static const struct ov_i2c_regvals norm_
 
 /* AGC and AEC parameters.  Note we start by disabling those features,
    then turn them only after tweaking the values. */
-	{ OV7670_REG_COM8, OV7670_COM8_FASTAEC
+	{ OV7670_R13_COM8, OV7670_COM8_FASTAEC
 			 | OV7670_COM8_AECSTEP
 			 | OV7670_COM8_BFILT },
-	{ OV7670_REG_GAIN, 0x00 },
-	{ OV7670_REG_AECH, 0x00 },
-	{ OV7670_REG_COM4, 0x40 }, /* magic reserved bit */
-	{ OV7670_REG_COM9, 0x18 }, /* 4x gain + magic rsvd bit */
-	{ OV7670_REG_BD50MAX, 0x05 },
-	{ OV7670_REG_BD60MAX, 0x07 },
-	{ OV7670_REG_AEW, 0x95 },
-	{ OV7670_REG_AEB, 0x33 },
-	{ OV7670_REG_VPT, 0xe3 },
-	{ OV7670_REG_HAECC1, 0x78 },
-	{ OV7670_REG_HAECC2, 0x68 },
+	{ OV7670_R00_GAIN, 0x00 },
+	{ OV7670_R10_AECH, 0x00 },
+	{ OV7670_R0D_COM4, 0x40 }, /* magic reserved bit */
+	{ OV7670_R14_COM9, 0x18 }, /* 4x gain + magic rsvd bit */
+	{ OV7670_RA5_BD50MAX, 0x05 },
+	{ OV7670_RAB_BD60MAX, 0x07 },
+	{ OV7670_R24_AEW, 0x95 },
+	{ OV7670_R25_AEB, 0x33 },
+	{ OV7670_R26_VPT, 0xe3 },
+	{ OV7670_R9F_HAECC1, 0x78 },
+	{ OV7670_RA0_HAECC2, 0x68 },
 	{ 0xa1, 0x03 }, /* magic */
-	{ OV7670_REG_HAECC3, 0xd8 },
-	{ OV7670_REG_HAECC4, 0xd8 },
-	{ OV7670_REG_HAECC5, 0xf0 },
-	{ OV7670_REG_HAECC6, 0x90 },
-	{ OV7670_REG_HAECC7, 0x94 },
-	{ OV7670_REG_COM8, OV7670_COM8_FASTAEC
+	{ OV7670_RA6_HAECC3, 0xd8 },
+	{ OV7670_RA7_HAECC4, 0xd8 },
+	{ OV7670_RA8_HAECC5, 0xf0 },
+	{ OV7670_RA9_HAECC6, 0x90 },
+	{ OV7670_RAA_HAECC7, 0x94 },
+	{ OV7670_R13_COM8, OV7670_COM8_FASTAEC
 			| OV7670_COM8_AECSTEP
 			| OV7670_COM8_BFILT
 			| OV7670_COM8_AGC
 			| OV7670_COM8_AEC },
 
 /* Almost all of these are magic "reserved" values.  */
-	{ OV7670_REG_COM5, 0x61 },
-	{ OV7670_REG_COM6, 0x4b },
+	{ OV7670_R0E_COM5, 0x61 },
+	{ OV7670_R0F_COM6, 0x4b },
 	{ 0x16, 0x02 },
-	{ OV7670_REG_MVFP, 0x07 },
+	{ OV7670_R1E_MVFP, 0x07 },
 	{ 0x21, 0x02 },
 	{ 0x22, 0x91 },
 	{ 0x29, 0x07 },
@@ -1619,10 +1811,10 @@ static const struct ov_i2c_regvals norm_
 	{ 0x37, 0x1d },
 	{ 0x38, 0x71 },
 	{ 0x39, 0x2a },
-	{ OV7670_REG_COM12, 0x78 },
+	{ OV7670_R3C_COM12, 0x78 },
 	{ 0x4d, 0x40 },
 	{ 0x4e, 0x20 },
-	{ OV7670_REG_GFIX, 0x00 },
+	{ OV7670_R69_GFIX, 0x00 },
 	{ 0x6b, 0x4a },
 	{ 0x74, 0x10 },
 	{ 0x8d, 0x4f },
@@ -1654,12 +1846,11 @@ static const struct ov_i2c_regvals norm_
 	{ 0x6c, 0x0a },
 	{ 0x6d, 0x55 },
 	{ 0x6e, 0x11 },
-	{ 0x6f, 0x9f },
-					/* "9e for advance AWB" */
+	{ 0x6f, 0x9f },			/* "9e for advance AWB" */
 	{ 0x6a, 0x40 },
-	{ OV7670_REG_BLUE, 0x40 },
-	{ OV7670_REG_RED, 0x60 },
-	{ OV7670_REG_COM8, OV7670_COM8_FASTAEC
+	{ OV7670_R01_BLUE, 0x40 },
+	{ OV7670_R02_RED, 0x60 },
+	{ OV7670_R13_COM8, OV7670_COM8_FASTAEC
 			| OV7670_COM8_AECSTEP
 			| OV7670_COM8_BFILT
 			| OV7670_COM8_AGC
@@ -1675,22 +1866,22 @@ static const struct ov_i2c_regvals norm_
 	{ 0x54, 0x80 },
 	{ 0x58, 0x9e },
 
-	{ OV7670_REG_COM16, OV7670_COM16_AWBGAIN },
-	{ OV7670_REG_EDGE, 0x00 },
+	{ OV7670_R41_COM16, OV7670_COM16_AWBGAIN },
+	{ OV7670_R3F_EDGE, 0x00 },
 	{ 0x75, 0x05 },
 	{ 0x76, 0xe1 },
 	{ 0x4c, 0x00 },
 	{ 0x77, 0x01 },
-	{ OV7670_REG_COM13, OV7670_COM13_GAMMA
+	{ OV7670_R3D_COM13, OV7670_COM13_GAMMA
 			  | OV7670_COM13_UVSAT
 			  | 2},		/* was 3 */
 	{ 0x4b, 0x09 },
 	{ 0xc9, 0x60 },
-	{ OV7670_REG_COM16, 0x38 },
+	{ OV7670_R41_COM16, 0x38 },
 	{ 0x56, 0x40 },
 
 	{ 0x34, 0x11 },
-	{ OV7670_REG_COM11, OV7670_COM11_EXP|OV7670_COM11_HZAUTO },
+	{ OV7670_R3B_COM11, OV7670_COM11_EXP|OV7670_COM11_HZAUTO },
 	{ 0xa4, 0x88 },
 	{ 0x96, 0x00 },
 	{ 0x97, 0x30 },
@@ -1825,10 +2016,13 @@ static unsigned char ov7670_abs_to_sm(un
 }
 
 /* Write a OV519 register */
-static int reg_w(struct sd *sd, __u16 index, __u16 value)
+static void reg_w(struct sd *sd, u16 index, u16 value)
 {
 	int ret, req = 0;
 
+	if (sd->gspca_dev.usb_err < 0)
+		return;
+
 	switch (sd->bridge) {
 	case BRIDGE_OV511:
 	case BRIDGE_OV511PLUS:
@@ -1838,6 +2032,8 @@ static int reg_w(struct sd *sd, __u16 in
 		req = 0x0a;
 		/* fall through */
 	case BRIDGE_W9968CF:
+		PDEBUG(D_USBO, "SET %02x %04x %04x",
+				req, value, index);
 		ret = usb_control_msg(sd->gspca_dev.dev,
 			usb_sndctrlpipe(sd->gspca_dev.dev, 0),
 			req,
@@ -1848,6 +2044,8 @@ static int reg_w(struct sd *sd, __u16 in
 		req = 1;
 	}
 
+	PDEBUG(D_USBO, "SET %02x 0000 %04x %02x",
+			req, index, value);
 	sd->gspca_dev.usb_buf[0] = value;
 	ret = usb_control_msg(sd->gspca_dev.dev,
 			usb_sndctrlpipe(sd->gspca_dev.dev, 0),
@@ -1857,22 +2055,22 @@ static int reg_w(struct sd *sd, __u16 in
 			sd->gspca_dev.usb_buf, 1, 500);
 leave:
 	if (ret < 0) {
-		err("Write reg 0x%04x -> [0x%02x] failed",
-		       value, index);
-		return ret;
+		err("reg_w %02x failed %d", index, ret);
+		sd->gspca_dev.usb_err = ret;
+		return;
 	}
-
-	PDEBUG(D_USBO, "Write reg 0x%04x -> [0x%02x]", value, index);
-	return 0;
 }
 
 /* Read from a OV519 register, note not valid for the w9968cf!! */
 /* returns: negative is error, pos or zero is data */
-static int reg_r(struct sd *sd, __u16 index)
+static int reg_r(struct sd *sd, u16 index)
 {
 	int ret;
 	int req;
 
+	if (sd->gspca_dev.usb_err < 0)
+		return -1;
+
 	switch (sd->bridge) {
 	case BRIDGE_OV511:
 	case BRIDGE_OV511PLUS:
@@ -1893,29 +2091,37 @@ static int reg_r(struct sd *sd, __u16 in
 
 	if (ret >= 0) {
 		ret = sd->gspca_dev.usb_buf[0];
-		PDEBUG(D_USBI, "Read reg [0x%02X] -> 0x%04X", index, ret);
-	} else
-		err("Read reg [0x%02x] failed", index);
+		PDEBUG(D_USBI, "GET %02x 0000 %04x %02x",
+			req, index, ret);
+	} else {
+		err("reg_r %02x failed %d", index, ret);
+		sd->gspca_dev.usb_err = ret;
+	}
 
 	return ret;
 }
 
 /* Read 8 values from a OV519 register */
 static int reg_r8(struct sd *sd,
-		  __u16 index)
+		  u16 index)
 {
 	int ret;
 
+	if (sd->gspca_dev.usb_err < 0)
+		return -1;
+
 	ret = usb_control_msg(sd->gspca_dev.dev,
 			usb_rcvctrlpipe(sd->gspca_dev.dev, 0),
 			1,			/* REQ_IO */
 			USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 			0, index, sd->gspca_dev.usb_buf, 8, 500);
 
-	if (ret >= 0)
+	if (ret >= 0) {
 		ret = sd->gspca_dev.usb_buf[0];
-	else
-		err("Read reg 8 [0x%02x] failed", index);
+	} else {
+		err("reg_r8 %02x failed %d", index, ret);
+		sd->gspca_dev.usb_err = ret;
+	}
 
 	return ret;
 }
@@ -1926,34 +2132,37 @@ static int reg_r8(struct sd *sd,
  * that are in the same position as 0's in "mask" are preserved, regardless
  * of their respective state in "value".
  */
-static int reg_w_mask(struct sd *sd,
-			__u16 index,
-			__u8 value,
-			__u8 mask)
+static void reg_w_mask(struct sd *sd,
+			u16 index,
+			u8 value,
+			u8 mask)
 {
 	int ret;
-	__u8 oldval;
+	u8 oldval;
 
 	if (mask != 0xff) {
 		value &= mask;			/* Enforce mask on value */
 		ret = reg_r(sd, index);
 		if (ret < 0)
-			return ret;
+			return;
 
 		oldval = ret & ~mask;		/* Clear the masked bits */
 		value |= oldval;		/* Set the desired bits */
 	}
-	return reg_w(sd, index, value);
+	reg_w(sd, index, value);
 }
 
 /*
  * Writes multiple (n) byte value to a single register. Only valid with certain
  * registers (0x30 and 0xc4 - 0xce).
  */
-static int ov518_reg_w32(struct sd *sd, __u16 index, u32 value, int n)
+static void ov518_reg_w32(struct sd *sd, u16 index, u32 value, int n)
 {
 	int ret;
 
+	if (sd->gspca_dev.usb_err < 0)
+		return;
+
 	*((__le32 *) sd->gspca_dev.usb_buf) = __cpu_to_le32(value);
 
 	ret = usb_control_msg(sd->gspca_dev.dev,
@@ -1963,69 +2172,55 @@ static int ov518_reg_w32(struct sd *sd,
 			0, index,
 			sd->gspca_dev.usb_buf, n, 500);
 	if (ret < 0) {
-		err("Write reg32 [%02x] %08x failed", index, value);
-		return ret;
+		err("reg_w32 %02x failed %d", index, ret);
+		sd->gspca_dev.usb_err = ret;
 	}
-
-	return 0;
 }
 
-static int ov511_i2c_w(struct sd *sd, __u8 reg, __u8 value)
+static void ov511_i2c_w(struct sd *sd, u8 reg, u8 value)
 {
 	int rc, retries;
 
-	PDEBUG(D_USBO, "i2c 0x%02x -> [0x%02x]", value, reg);
+	PDEBUG(D_USBO, "ov511_i2c_w %02x %02x", reg, value);
 
 	/* Three byte write cycle */
 	for (retries = 6; ; ) {
 		/* Select camera register */
-		rc = reg_w(sd, R51x_I2C_SADDR_3, reg);
-		if (rc < 0)
-			return rc;
+		reg_w(sd, R51x_I2C_SADDR_3, reg);
 
 		/* Write "value" to I2C data port of OV511 */
-		rc = reg_w(sd, R51x_I2C_DATA, value);
-		if (rc < 0)
-			return rc;
+		reg_w(sd, R51x_I2C_DATA, value);
 
 		/* Initiate 3-byte write cycle */
-		rc = reg_w(sd, R511_I2C_CTL, 0x01);
-		if (rc < 0)
-			return rc;
+		reg_w(sd, R511_I2C_CTL, 0x01);
 
 		do {
 			rc = reg_r(sd, R511_I2C_CTL);
 		} while (rc > 0 && ((rc & 1) == 0)); /* Retry until idle */
 
 		if (rc < 0)
-			return rc;
+			return;
 
 		if ((rc & 2) == 0) /* Ack? */
 			break;
 		if (--retries < 0) {
 			PDEBUG(D_USBO, "i2c write retries exhausted");
-			return -1;
+			return;
 		}
 	}
-
-	return 0;
 }
 
-static int ov511_i2c_r(struct sd *sd, __u8 reg)
+static int ov511_i2c_r(struct sd *sd, u8 reg)
 {
 	int rc, value, retries;
 
 	/* Two byte write cycle */
 	for (retries = 6; ; ) {
 		/* Select camera register */
-		rc = reg_w(sd, R51x_I2C_SADDR_2, reg);
-		if (rc < 0)
-			return rc;
+		reg_w(sd, R51x_I2C_SADDR_2, reg);
 
 		/* Initiate 2-byte write cycle */
-		rc = reg_w(sd, R511_I2C_CTL, 0x03);
-		if (rc < 0)
-			return rc;
+		reg_w(sd, R511_I2C_CTL, 0x03);
 
 		do {
 			rc = reg_r(sd, R511_I2C_CTL);
@@ -2049,9 +2244,7 @@ static int ov511_i2c_r(struct sd *sd, __
 	/* Two byte read cycle */
 	for (retries = 6; ; ) {
 		/* Initiate 2-byte read cycle */
-		rc = reg_w(sd, R511_I2C_CTL, 0x05);
-		if (rc < 0)
-			return rc;
+		reg_w(sd, R511_I2C_CTL, 0x05);
 
 		do {
 			rc = reg_r(sd, R511_I2C_CTL);
@@ -2064,9 +2257,7 @@ static int ov511_i2c_r(struct sd *sd, __
 			break;
 
 		/* I2C abort */
-		rc = reg_w(sd, R511_I2C_CTL, 0x10);
-		if (rc < 0)
-			return rc;
+		reg_w(sd, R511_I2C_CTL, 0x10);
 
 		if (--retries < 0) {
 			PDEBUG(D_USBI, "i2c read retries exhausted");
@@ -2076,12 +2267,10 @@ static int ov511_i2c_r(struct sd *sd, __
 
 	value = reg_r(sd, R51x_I2C_DATA);
 
-	PDEBUG(D_USBI, "i2c [0x%02X] -> 0x%02X", reg, value);
+	PDEBUG(D_USBI, "ov511_i2c_r %02x %02x", reg, value);
 
 	/* This is needed to make i2c_w() work */
-	rc = reg_w(sd, R511_I2C_CTL, 0x05);
-	if (rc < 0)
-		return rc;
+	reg_w(sd, R511_I2C_CTL, 0x05);
 
 	return value;
 }
@@ -2091,32 +2280,24 @@ static int ov511_i2c_r(struct sd *sd, __
  * This is normally only called from i2c_w(). Note that this function
  * always succeeds regardless of whether the sensor is present and working.
  */
-static int ov518_i2c_w(struct sd *sd,
-		__u8 reg,
-		__u8 value)
+static void ov518_i2c_w(struct sd *sd,
+		u8 reg,
+		u8 value)
 {
-	int rc;
-
-	PDEBUG(D_USBO, "i2c 0x%02x -> [0x%02x]", value, reg);
+	PDEBUG(D_USBO, "ov518_i2c_w %02x %02x", reg, value);
 
 	/* Select camera register */
-	rc = reg_w(sd, R51x_I2C_SADDR_3, reg);
-	if (rc < 0)
-		return rc;
+	reg_w(sd, R51x_I2C_SADDR_3, reg);
 
 	/* Write "value" to I2C data port of OV511 */
-	rc = reg_w(sd, R51x_I2C_DATA, value);
-	if (rc < 0)
-		return rc;
+	reg_w(sd, R51x_I2C_DATA, value);
 
 	/* Initiate 3-byte write cycle */
-	rc = reg_w(sd, R518_I2C_CTL, 0x01);
-	if (rc < 0)
-		return rc;
+	reg_w(sd, R518_I2C_CTL, 0x01);
 
 	/* wait for write complete */
 	msleep(4);
-	return reg_r8(sd, R518_I2C_CTL);
+	reg_r8(sd, R518_I2C_CTL);
 }
 
 /*
@@ -2126,105 +2307,102 @@ static int ov518_i2c_w(struct sd *sd,
  * This is normally only called from i2c_r(). Note that this function
  * always succeeds regardless of whether the sensor is present and working.
  */
-static int ov518_i2c_r(struct sd *sd, __u8 reg)
+static int ov518_i2c_r(struct sd *sd, u8 reg)
 {
-	int rc, value;
+	int value;
 
 	/* Select camera register */
-	rc = reg_w(sd, R51x_I2C_SADDR_2, reg);
-	if (rc < 0)
-		return rc;
+	reg_w(sd, R51x_I2C_SADDR_2, reg);
 
 	/* Initiate 2-byte write cycle */
-	rc = reg_w(sd, R518_I2C_CTL, 0x03);
-	if (rc < 0)
-		return rc;
+	reg_w(sd, R518_I2C_CTL, 0x03);
 
 	/* Initiate 2-byte read cycle */
-	rc = reg_w(sd, R518_I2C_CTL, 0x05);
-	if (rc < 0)
-		return rc;
+	reg_w(sd, R518_I2C_CTL, 0x05);
 	value = reg_r(sd, R51x_I2C_DATA);
-	PDEBUG(D_USBI, "i2c [0x%02X] -> 0x%02X", reg, value);
+	PDEBUG(D_USBI, "ov518_i2c_r %02x %02x", reg, value);
 	return value;
 }
 
-static int ovfx2_i2c_w(struct sd *sd, __u8 reg, __u8 value)
+static void ovfx2_i2c_w(struct sd *sd, u8 reg, u8 value)
 {
 	int ret;
 
+	if (sd->gspca_dev.usb_err < 0)
+		return;
+
 	ret = usb_control_msg(sd->gspca_dev.dev,
 			usb_sndctrlpipe(sd->gspca_dev.dev, 0),
 			0x02,
 			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-			(__u16)value, (__u16)reg, NULL, 0, 500);
+			(u16) value, (u16) reg, NULL, 0, 500);
 
 	if (ret < 0) {
-		err("i2c 0x%02x -> [0x%02x] failed", value, reg);
-		return ret;
+		err("ovfx2_i2c_w %02x failed %d", reg, ret);
+		sd->gspca_dev.usb_err = ret;
 	}
 
-	PDEBUG(D_USBO, "i2c 0x%02x -> [0x%02x]", value, reg);
-	return 0;
+	PDEBUG(D_USBO, "ovfx2_i2c_w %02x %02x", reg, value);
 }
 
-static int ovfx2_i2c_r(struct sd *sd, __u8 reg)
+static int ovfx2_i2c_r(struct sd *sd, u8 reg)
 {
 	int ret;
 
+	if (sd->gspca_dev.usb_err < 0)
+		return -1;
+
 	ret = usb_control_msg(sd->gspca_dev.dev,
 			usb_rcvctrlpipe(sd->gspca_dev.dev, 0),
 			0x03,
 			USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-			0, (__u16)reg, sd->gspca_dev.usb_buf, 1, 500);
+			0, (u16) reg, sd->gspca_dev.usb_buf, 1, 500);
 
 	if (ret >= 0) {
 		ret = sd->gspca_dev.usb_buf[0];
-		PDEBUG(D_USBI, "i2c [0x%02X] -> 0x%02X", reg, ret);
-	} else
-		err("i2c read [0x%02x] failed", reg);
+		PDEBUG(D_USBI, "ovfx2_i2c_r %02x %02x", reg, ret);
+	} else {
+		err("ovfx2_i2c_r %02x failed %d", reg, ret);
+		sd->gspca_dev.usb_err = ret;
+	}
 
 	return ret;
 }
 
-static int i2c_w(struct sd *sd, __u8 reg, __u8 value)
+static void i2c_w(struct sd *sd, u8 reg, u8 value)
 {
-	int ret = -1;
-
 	if (sd->sensor_reg_cache[reg] == value)
-		return 0;
+		return;
 
 	switch (sd->bridge) {
 	case BRIDGE_OV511:
 	case BRIDGE_OV511PLUS:
-		ret = ov511_i2c_w(sd, reg, value);
+		ov511_i2c_w(sd, reg, value);
 		break;
 	case BRIDGE_OV518:
 	case BRIDGE_OV518PLUS:
 	case BRIDGE_OV519:
-		ret = ov518_i2c_w(sd, reg, value);
+		ov518_i2c_w(sd, reg, value);
 		break;
 	case BRIDGE_OVFX2:
-		ret = ovfx2_i2c_w(sd, reg, value);
+		ovfx2_i2c_w(sd, reg, value);
 		break;
 	case BRIDGE_W9968CF:
-		ret = w9968cf_i2c_w(sd, reg, value);
+		w9968cf_i2c_w(sd, reg, value);
 		break;
 	}
 
-	if (ret >= 0) {
+	if (sd->gspca_dev.usb_err >= 0) {
 		/* Up on sensor reset empty the register cache */
 		if (reg == 0x12 && (value & 0x80))
 			memset(sd->sensor_reg_cache, -1,
-			       sizeof(sd->sensor_reg_cache));
+				sizeof(sd->sensor_reg_cache));
 		else
 			sd->sensor_reg_cache[reg] = value;
 	}
-
-	return ret;
 }
 
-static int i2c_r(struct sd *sd, __u8 reg)
+static int i2c_r(struct sd *sd, u8 reg)
 {
 	int ret = -1;
 
@@ -2260,95 +2438,99 @@ static int i2c_r(struct sd *sd, __u8 reg
  * that are in the same position as 0's in "mask" are preserved, regardless
  * of their respective state in "value".
  */
-static int i2c_w_mask(struct sd *sd,
-		   __u8 reg,
-		   __u8 value,
-		   __u8 mask)
+static void i2c_w_mask(struct sd *sd,
+			u8 reg,
+			u8 value,
+			u8 mask)
 {
 	int rc;
-	__u8 oldval;
+	u8 oldval;
 
 	value &= mask;			/* Enforce mask on value */
 	rc = i2c_r(sd, reg);
 	if (rc < 0)
-		return rc;
+		return;
 	oldval = rc & ~mask;		/* Clear the masked bits */
 	value |= oldval;		/* Set the desired bits */
-	return i2c_w(sd, reg, value);
+	i2c_w(sd, reg, value);
 }
 
 /* Temporarily stops OV511 from functioning. Must do this before changing
  * registers while the camera is streaming */
-static inline int ov51x_stop(struct sd *sd)
+static inline void ov51x_stop(struct sd *sd)
 {
 	PDEBUG(D_STREAM, "stopping");
 	sd->stopped = 1;
 	switch (sd->bridge) {
 	case BRIDGE_OV511:
 	case BRIDGE_OV511PLUS:
-		return reg_w(sd, R51x_SYS_RESET, 0x3d);
+		reg_w(sd, R51x_SYS_RESET, 0x3d);
+		break;
 	case BRIDGE_OV518:
 	case BRIDGE_OV518PLUS:
-		return reg_w_mask(sd, R51x_SYS_RESET, 0x3a, 0x3a);
+		reg_w_mask(sd, R51x_SYS_RESET, 0x3a, 0x3a);
+		break;
 	case BRIDGE_OV519:
-		return reg_w(sd, OV519_SYS_RESET1, 0x0f);
+		reg_w(sd, OV519_R51_RESET1, 0x0f);
+		reg_w(sd, OV519_R51_RESET1, 0x00);
+		reg_w(sd, 0x22, 0x00);		/* FRAR */
+		break;
 	case BRIDGE_OVFX2:
-		return reg_w_mask(sd, 0x0f, 0x00, 0x02);
+		reg_w_mask(sd, 0x0f, 0x00, 0x02);
+		break;
 	case BRIDGE_W9968CF:
-		return reg_w(sd, 0x3c, 0x0a05); /* stop USB transfer */
+		reg_w(sd, 0x3c, 0x0a05); /* stop USB transfer */
+		break;
 	}
-
-	return 0;
 }
 
 /* Restarts OV511 after ov511_stop() is called. Has no effect if it is not
  * actually stopped (for performance). */
-static inline int ov51x_restart(struct sd *sd)
+static inline void ov51x_restart(struct sd *sd)
 {
-	int rc;
-
 	PDEBUG(D_STREAM, "restarting");
 	if (!sd->stopped)
-		return 0;
+		return;
 	sd->stopped = 0;
 
 	/* Reinitialize the stream */
 	switch (sd->bridge) {
 	case BRIDGE_OV511:
 	case BRIDGE_OV511PLUS:
-		return reg_w(sd, R51x_SYS_RESET, 0x00);
+		reg_w(sd, R51x_SYS_RESET, 0x00);
+		break;
 	case BRIDGE_OV518:
 	case BRIDGE_OV518PLUS:
-		rc = reg_w(sd, 0x2f, 0x80);
-		if (rc < 0)
-			return rc;
-		return reg_w(sd, R51x_SYS_RESET, 0x00);
+		reg_w(sd, 0x2f, 0x80);
+		reg_w(sd, R51x_SYS_RESET, 0x00);
+		break;
 	case BRIDGE_OV519:
-		return reg_w(sd, OV519_SYS_RESET1, 0x00);
+		reg_w(sd, OV519_R51_RESET1, 0x0f);
+		reg_w(sd, OV519_R51_RESET1, 0x00);
+		reg_w(sd, 0x22, 0x1d);		/* FRAR */
+		break;
 	case BRIDGE_OVFX2:
-		return reg_w_mask(sd, 0x0f, 0x02, 0x02);
+		reg_w_mask(sd, 0x0f, 0x02, 0x02);
+		break;
 	case BRIDGE_W9968CF:
-		return reg_w(sd, 0x3c, 0x8a05); /* USB FIFO enable */
+		reg_w(sd, 0x3c, 0x8a05); /* USB FIFO enable */
+		break;
 	}
-
-	return 0;
 }
 
-static int ov51x_set_slave_ids(struct sd *sd, __u8 slave);
+static void ov51x_set_slave_ids(struct sd *sd, u8 slave);
 
 /* This does an initial reset of an OmniVision sensor and ensures that I2C
  * is synchronized. Returns <0 on failure.
  */
-static int init_ov_sensor(struct sd *sd, __u8 slave)
+static int init_ov_sensor(struct sd *sd, u8 slave)
 {
 	int i;
 
-	if (ov51x_set_slave_ids(sd, slave) < 0)
-		return -EIO;
+	ov51x_set_slave_ids(sd, slave);
 
 	/* Reset the sensor */
-	if (i2c_w(sd, 0x12, 0x80) < 0)
-		return -EIO;
+	i2c_w(sd, 0x12, 0x80);
 
 	/* Wait for it to initialize */
 	msleep(150);
@@ -2361,15 +2543,16 @@ static int init_ov_sensor(struct sd *sd,
 		}
 
 		/* Reset the sensor */
-		if (i2c_w(sd, 0x12, 0x80) < 0)
-			return -EIO;
+		i2c_w(sd, 0x12, 0x80);
+
 		/* Wait for it to initialize */
 		msleep(150);
+
 		/* Dummy read to sync I2C */
 		if (i2c_r(sd, 0x00) < 0)
-			return -EIO;
+			return -1;
 	}
-	return -EIO;
+	return -1;
 }
 
 /* Set the read and write slave IDs. The "slave" argument is the write slave,
@@ -2377,53 +2560,40 @@ static int init_ov_sensor(struct sd *sd,
  * This should not be called from outside the i2c I/O functions.
  * Sets I2C read and write slave IDs. Returns <0 for error
  */
-static int ov51x_set_slave_ids(struct sd *sd,
-				__u8 slave)
+static void ov51x_set_slave_ids(struct sd *sd,
+				u8 slave)
 {
-	int rc;
-
 	switch (sd->bridge) {
 	case BRIDGE_OVFX2:
-		return reg_w(sd, OVFX2_I2C_ADDR, slave);
+		reg_w(sd, OVFX2_I2C_ADDR, slave);
+		return;
 	case BRIDGE_W9968CF:
 		sd->sensor_addr = slave;
-		return 0;
+		return;
 	}
 
-	rc = reg_w(sd, R51x_I2C_W_SID, slave);
-	if (rc < 0)
-		return rc;
-	return reg_w(sd, R51x_I2C_R_SID, slave + 1);
+	reg_w(sd, R51x_I2C_W_SID, slave);
+	reg_w(sd, R51x_I2C_R_SID, slave + 1);
 }
 
-static int write_regvals(struct sd *sd,
+static void write_regvals(struct sd *sd,
 			 const struct ov_regvals *regvals,
 			 int n)
 {
-	int rc;
-
 	while (--n >= 0) {
-		rc = reg_w(sd, regvals->reg, regvals->val);
-		if (rc < 0)
-			return rc;
+		reg_w(sd, regvals->reg, regvals->val);
 		regvals++;
 	}
-	return 0;
 }
 
-static int write_i2c_regvals(struct sd *sd,
-			     const struct ov_i2c_regvals *regvals,
-			     int n)
+static void write_i2c_regvals(struct sd *sd,
+			const struct ov_i2c_regvals *regvals,
+			int n)
 {
-	int rc;
-
 	while (--n >= 0) {
-		rc = i2c_w(sd, regvals->reg, regvals->val);
-		if (rc < 0)
-			return rc;
+		i2c_w(sd, regvals->reg, regvals->val);
 		regvals++;
 	}
-	return 0;
 }
 
 /****************************************************************************
@@ -2433,13 +2603,13 @@ static int write_i2c_regvals(struct sd *
  ***************************************************************************/
 
 /* This initializes the OV2x10 / OV3610 / OV3620 */
-static int ov_hires_configure(struct sd *sd)
+static void ov_hires_configure(struct sd *sd)
 {
 	int high, low;
 
 	if (sd->bridge != BRIDGE_OVFX2) {
 		err("error hires sensors only supported with ovfx2");
-		return -1;
+		return;
 	}
 
 	PDEBUG(D_PROBE, "starting ov hires configuration");
@@ -2455,20 +2625,15 @@ static int ov_hires_configure(struct sd
 		PDEBUG(D_PROBE, "Sensor is an OV3610");
 		sd->sensor = SEN_OV3610;
 	} else {
-		err("Error unknown sensor type: 0x%02x%02x",
-		       high, low);
-		return -1;
+		err("Error unknown sensor type: %02x%02x",
+			high, low);
 	}
-
-	/* Set sensor-specific vars */
-	return 0;
 }
 
-
 /* This initializes the OV8110, OV8610 sensor. The OV8110 uses
  * the same register settings as the OV8610, since they are very similar.
  */
-static int ov8xx0_configure(struct sd *sd)
+static void ov8xx0_configure(struct sd *sd)
 {
 	int rc;
 
@@ -2478,27 +2643,21 @@ static int ov8xx0_configure(struct sd *s
 	rc = i2c_r(sd, OV7610_REG_COM_I);
 	if (rc < 0) {
 		PDEBUG(D_ERR, "Error detecting sensor type");
-		return -1;
+		return;
 	}
-	if ((rc & 3) == 1) {
+	if ((rc & 3) == 1)
 		sd->sensor = SEN_OV8610;
-	} else {
+	else
 		err("Unknown image sensor version: %d", rc & 3);
-		return -1;
-	}
-
-	/* Set sensor-specific vars */
-	return 0;
 }
 
 /* This initializes the OV7610, OV7620, or OV76BE sensor. The OV76BE uses
  * the same register settings as the OV7610, since they are very similar.
  */
-static int ov7xx0_configure(struct sd *sd)
+static void ov7xx0_configure(struct sd *sd)
 {
 	int rc, high, low;
 
-
 	PDEBUG(D_PROBE, "starting OV7xx0 configuration");
 
 	/* Detect sensor (sub)type */
@@ -2508,15 +2667,15 @@ static int ov7xx0_configure(struct sd *s
 	 * it appears to be wrongly detected as a 7610 by default */
 	if (rc < 0) {
 		PDEBUG(D_ERR, "Error detecting sensor type");
-		return -1;
+		return;
 	}
 	if ((rc & 3) == 3) {
 		/* quick hack to make OV7670s work */
 		high = i2c_r(sd, 0x0a);
 		low = i2c_r(sd, 0x0b);
 		/* info("%x, %x", high, low); */
-		if (high == 0x76 && low == 0x73) {
-			PDEBUG(D_PROBE, "Sensor is an OV7670");
+		if (high == 0x76 && (low & 0xf0) == 0x70) {
+			PDEBUG(D_PROBE, "Sensor is an OV76%02x", low);
 			sd->sensor = SEN_OV7670;
 		} else {
 			PDEBUG(D_PROBE, "Sensor is an OV7610");
@@ -2536,19 +2695,19 @@ static int ov7xx0_configure(struct sd *s
 		high = i2c_r(sd, 0x0a);
 		if (high < 0) {
 			PDEBUG(D_ERR, "Error detecting camera chip PID");
-			return high;
+			return;
 		}
 		low = i2c_r(sd, 0x0b);
 		if (low < 0) {
 			PDEBUG(D_ERR, "Error detecting camera chip VER");
-			return low;
+			return;
 		}
 		if (high == 0x76) {
 			switch (low) {
 			case 0x30:
 				err("Sensor is an OV7630/OV7635");
 				err("7630 is not supported by this driver");
-				return -1;
+				return;
 			case 0x40:
 				PDEBUG(D_PROBE, "Sensor is an OV7645");
 				sd->sensor = SEN_OV7640; /* FIXME */
@@ -2561,9 +2720,14 @@ static int ov7xx0_configure(struct sd *s
 				PDEBUG(D_PROBE, "Sensor is an OV7648");
 				sd->sensor = SEN_OV7648;
 				break;
+			case 0x60:
+				PDEBUG(D_PROBE, "Sensor is a OV7660");
+				sd->sensor = SEN_OV7660;
+				sd->invert_led = 0;
+				break;
 			default:
 				PDEBUG(D_PROBE, "Unknown sensor: 0x76%x", low);
-				return -1;
+				return;
 			}
 		} else {
 			PDEBUG(D_PROBE, "Sensor is an OV7620");
@@ -2571,15 +2735,11 @@ static int ov7xx0_configure(struct sd *s
 		}
 	} else {
 		err("Unknown image sensor version: %d", rc & 3);
-		return -1;
 	}
-
-	/* Set sensor-specific vars */
-	return 0;
 }
 
 /* This initializes the OV6620, OV6630, OV6630AE, or OV6630AF sensor. */
-static int ov6xx0_configure(struct sd *sd)
+static void ov6xx0_configure(struct sd *sd)
 {
 	int rc;
 	PDEBUG(D_PROBE, "starting OV6xx0 configuration");
@@ -2588,7 +2748,7 @@ static int ov6xx0_configure(struct sd *s
 	rc = i2c_r(sd, OV7610_REG_COM_I);
 	if (rc < 0) {
 		PDEBUG(D_ERR, "Error detecting sensor type");
-		return -1;
+		return;
 	}
 
 	/* Ugh. The first two bits are the version bits, but
@@ -2619,13 +2779,11 @@ static int ov6xx0_configure(struct sd *s
 		break;
 	default:
 		err("FATAL: Unknown sensor version: 0x%02x", rc);
-		return -1;
+		return;
 	}
 
 	/* Set sensor-specific vars */
 	sd->sif = 1;
-
-	return 0;
 }
 
 /* Turns on or off the LED. Only has an effect with OV511+/OV518(+)/OV519 */
@@ -2637,14 +2795,14 @@ static void ov51x_led_control(struct sd
 	switch (sd->bridge) {
 	/* OV511 has no LED control */
 	case BRIDGE_OV511PLUS:
-		reg_w(sd, R511_SYS_LED_CTL, on ? 1 : 0);
+		reg_w(sd, R511_SYS_LED_CTL, on);
 		break;
 	case BRIDGE_OV518:
 	case BRIDGE_OV518PLUS:
-		reg_w_mask(sd, R518_GPIO_OUT, on ? 0x02 : 0x00, 0x02);
+		reg_w_mask(sd, R518_GPIO_OUT, 0x02 * on, 0x02);
 		break;
 	case BRIDGE_OV519:
-		reg_w_mask(sd, OV519_GPIO_DATA_OUT0, !on, 1);	/* 0 / 1 */
+		reg_w_mask(sd, OV519_GPIO_DATA_OUT0, on, 1);
 		break;
 	}
 }
@@ -2679,7 +2837,7 @@ static void sd_reset_snapshot(struct gsp
 	}
 }
 
-static int ov51x_upload_quan_tables(struct sd *sd)
+static void ov51x_upload_quan_tables(struct sd *sd)
 {
 	const unsigned char yQuanTable511[] = {
 		0, 1, 1, 2, 2, 3, 3, 4,
@@ -2710,7 +2868,6 @@ static int ov51x_upload_quan_tables(stru
 		6, 6, 6, 6, 7, 7, 7, 8,
 		7, 7, 6, 7, 7, 7, 8, 8
 	};
-
 	const unsigned char uvQuanTable518[] = {
 		6, 6, 6, 7, 7, 7, 7, 7,
 		6, 6, 6, 7, 7, 7, 7, 7,
@@ -2720,18 +2877,18 @@ static int ov51x_upload_quan_tables(stru
 
 	const unsigned char *pYTable, *pUVTable;
 	unsigned char val0, val1;
-	int i, size, rc, reg = R51x_COMP_LUT_BEGIN;
+	int i, size, reg = R51x_COMP_LUT_BEGIN;
 
 	PDEBUG(D_PROBE, "Uploading quantization tables");
 
 	if (sd->bridge == BRIDGE_OV511 || sd->bridge == BRIDGE_OV511PLUS) {
 		pYTable = yQuanTable511;
 		pUVTable = uvQuanTable511;
-		size  = 32;
+		size = 32;
 	} else {
 		pYTable = yQuanTable518;
 		pUVTable = uvQuanTable518;
-		size  = 16;
+		size = 16;
 	}
 
 	for (i = 0; i < size; i++) {
@@ -2740,30 +2897,23 @@ static int ov51x_upload_quan_tables(stru
 		val0 &= 0x0f;
 		val1 &= 0x0f;
 		val0 |= val1 << 4;
-		rc = reg_w(sd, reg, val0);
-		if (rc < 0)
-			return rc;
+		reg_w(sd, reg, val0);
 
 		val0 = *pUVTable++;
 		val1 = *pUVTable++;
 		val0 &= 0x0f;
 		val1 &= 0x0f;
 		val0 |= val1 << 4;
-		rc = reg_w(sd, reg + size, val0);
-		if (rc < 0)
-			return rc;
+		reg_w(sd, reg + size, val0);
 
 		reg++;
 	}
-
-	return 0;
 }
 
 /* This initializes the OV511/OV511+ and the sensor */
-static int ov511_configure(struct gspca_dev *gspca_dev)
+static void ov511_configure(struct gspca_dev *gspca_dev)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
-	int rc;
 
 	/* For 511 and 511+ */
 	const struct ov_regvals init_511[] = {
@@ -2809,42 +2959,27 @@ static int ov511_configure(struct gspca_
 
 	PDEBUG(D_PROBE, "Device custom id %x", reg_r(sd, R51x_SYS_CUST_ID));
 
-	rc = write_regvals(sd, init_511, ARRAY_SIZE(init_511));
-	if (rc < 0)
-		return rc;
+	write_regvals(sd, init_511, ARRAY_SIZE(init_511));
 
 	switch (sd->bridge) {
 	case BRIDGE_OV511:
-		rc = write_regvals(sd, norm_511, ARRAY_SIZE(norm_511));
-		if (rc < 0)
-			return rc;
+		write_regvals(sd, norm_511, ARRAY_SIZE(norm_511));
 		break;
 	case BRIDGE_OV511PLUS:
-		rc = write_regvals(sd, norm_511_p, ARRAY_SIZE(norm_511_p));
-		if (rc < 0)
-			return rc;
+		write_regvals(sd, norm_511_p, ARRAY_SIZE(norm_511_p));
 		break;
 	}
 
 	/* Init compression */
-	rc = write_regvals(sd, compress_511, ARRAY_SIZE(compress_511));
-	if (rc < 0)
-		return rc;
-
-	rc = ov51x_upload_quan_tables(sd);
-	if (rc < 0) {
-		PDEBUG(D_ERR, "Error uploading quantization tables");
-		return rc;
-	}
+	write_regvals(sd, compress_511, ARRAY_SIZE(compress_511));
 
-	return 0;
+	ov51x_upload_quan_tables(sd);
 }
 
 /* This initializes the OV518/OV518+ and the sensor */
-static int ov518_configure(struct gspca_dev *gspca_dev)
+static void ov518_configure(struct gspca_dev *gspca_dev)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
-	int rc;
 
 	/* For 518 and 518+ */
 	const struct ov_regvals init_518[] = {
@@ -2892,65 +3027,49 @@ static int ov518_configure(struct gspca_
 
 	/* First 5 bits of custom ID reg are a revision ID on OV518 */
 	PDEBUG(D_PROBE, "Device revision %d",
-	       0x1F & reg_r(sd, R51x_SYS_CUST_ID));
+		0x1f & reg_r(sd, R51x_SYS_CUST_ID));
 
-	rc = write_regvals(sd, init_518, ARRAY_SIZE(init_518));
-	if (rc < 0)
-		return rc;
+	write_regvals(sd, init_518, ARRAY_SIZE(init_518));
 
 	/* Set LED GPIO pin to output mode */
-	rc = reg_w_mask(sd, R518_GPIO_CTL, 0x00, 0x02);
-	if (rc < 0)
-		return rc;
+	reg_w_mask(sd, R518_GPIO_CTL, 0x00, 0x02);
 
 	switch (sd->bridge) {
 	case BRIDGE_OV518:
-		rc = write_regvals(sd, norm_518, ARRAY_SIZE(norm_518));
-		if (rc < 0)
-			return rc;
+		write_regvals(sd, norm_518, ARRAY_SIZE(norm_518));
 		break;
 	case BRIDGE_OV518PLUS:
-		rc = write_regvals(sd, norm_518_p, ARRAY_SIZE(norm_518_p));
-		if (rc < 0)
-			return rc;
+		write_regvals(sd, norm_518_p, ARRAY_SIZE(norm_518_p));
 		break;
 	}
 
-	rc = ov51x_upload_quan_tables(sd);
-	if (rc < 0) {
-		PDEBUG(D_ERR, "Error uploading quantization tables");
-		return rc;
-	}
-
-	rc = reg_w(sd, 0x2f, 0x80);
-	if (rc < 0)
-		return rc;
+	ov51x_upload_quan_tables(sd);
 
-	return 0;
+	reg_w(sd, 0x2f, 0x80);
 }
 
-static int ov519_configure(struct sd *sd)
+static void ov519_configure(struct sd *sd)
 {
 	static const struct ov_regvals init_519[] = {
-		{ 0x5a,  0x6d }, /* EnableSystem */
-		{ 0x53,  0x9b },
-		{ 0x54,  0xff }, /* set bit2 to enable jpeg */
-		{ 0x5d,  0x03 },
-		{ 0x49,  0x01 },
-		{ 0x48,  0x00 },
+		{ 0x5a, 0x6d }, /* EnableSystem */
+		{ 0x53, 0x9b }, /* don't enable the microcontroller */
+		{ OV519_R54_EN_CLK1, 0xff }, /* set bit2 to enable jpeg */
+		{ 0x5d, 0x03 },
+		{ 0x49, 0x01 },
+		{ 0x48, 0x00 },
 		/* Set LED pin to output mode. Bit 4 must be cleared or sensor
 		 * detection will fail. This deserves further investigation. */
 		{ OV519_GPIO_IO_CTRL0,   0xee },
-		{ 0x51,  0x0f }, /* SetUsbInit */
-		{ 0x51,  0x00 },
-		{ 0x22,  0x00 },
+		{ OV519_R51_RESET1, 0x0f },
+		{ OV519_R51_RESET1, 0x00 },
+		{ 0x22, 0x00 },
 		/* windows reads 0x55 at this point*/
 	};
 
-	return write_regvals(sd, init_519, ARRAY_SIZE(init_519));
+	write_regvals(sd, init_519, ARRAY_SIZE(init_519));
 }
 
-static int ovfx2_configure(struct sd *sd)
+static void ovfx2_configure(struct sd *sd)
 {
 	static const struct ov_regvals init_fx2[] = {
 		{ 0x00, 0x60 },
@@ -2964,7 +3083,92 @@ static int ovfx2_configure(struct sd *sd
 
 	sd->stopped = 1;
 
-	return write_regvals(sd, init_fx2, ARRAY_SIZE(init_fx2));
+	write_regvals(sd, init_fx2, ARRAY_SIZE(init_fx2));
+}
+
+/* set the mode */
+/* This function works for ov7660 only */
+static void ov519_set_mode(struct sd *sd)
+{
+	static const struct ov_regvals bridge_ov7660[2][10] = {
+		{{0x10, 0x14}, {0x11, 0x1e}, {0x12, 0x00}, {0x13, 0x00},
+		 {0x14, 0x00}, {0x15, 0x00}, {0x16, 0x00}, {0x20, 0x0c},
+		 {0x25, 0x01}, {0x26, 0x00}},
+		{{0x10, 0x28}, {0x11, 0x3c}, {0x12, 0x00}, {0x13, 0x00},
+		 {0x14, 0x00}, {0x15, 0x00}, {0x16, 0x00}, {0x20, 0x0c},
+		 {0x25, 0x03}, {0x26, 0x00}}
+	};
+	static const struct ov_i2c_regvals sensor_ov7660[2][3] = {
+		{{0x12, 0x00}, {0x24, 0x00}, {0x0c, 0x0c}},
+		{{0x12, 0x00}, {0x04, 0x00}, {0x0c, 0x00}}
+	};
+	static const struct ov_i2c_regvals sensor_ov7660_2[] = {
+		{OV7670_R17_HSTART, 0x13},
+		{OV7670_R18_HSTOP, 0x01},
+		{OV7670_R32_HREF, 0x92},
+		{OV7670_R19_VSTART, 0x02},
+		{OV7670_R1A_VSTOP, 0x7a},
+		{OV7670_R03_VREF, 0x00},
+/*		{0x33, 0x00}, */
+/*		{0x34, 0x07}, */
+/*		{0x36, 0x00}, */
+/*		{0x6b, 0x0a}, */
+	};
+
+	write_regvals(sd, bridge_ov7660[sd->gspca_dev.curr_mode],
+			ARRAY_SIZE(bridge_ov7660[0]));
+	write_i2c_regvals(sd, sensor_ov7660[sd->gspca_dev.curr_mode],
+			ARRAY_SIZE(sensor_ov7660[0]));
+	write_i2c_regvals(sd, sensor_ov7660_2,
+			ARRAY_SIZE(sensor_ov7660_2));
+}
+
+/* set the frame rate */
+/* This function works for sensors ov7640, ov7648 ov7660 and ov7670 only */
+static void ov519_set_fr(struct sd *sd)
+{
+	int fr;
+	u8 clock;
+	/* frame rate table with indices:
+	 *	- mode = 0: 320x240, 1: 640x480
+	 *	- fr rate = 0: 30, 1: 25, 2: 20, 3: 15, 4: 10, 5: 5
+	 *	- reg = 0: bridge a4, 1: bridge 23, 2: sensor 11 (clock)
+	 */
+	static const u8 fr_tb[2][6][3] = {
+		{{0x04, 0xff, 0x00},
+		 {0x04, 0x1f, 0x00},
+		 {0x04, 0x1b, 0x00},
+		 {0x04, 0x15, 0x00},
+		 {0x04, 0x09, 0x00},
+		 {0x04, 0x01, 0x00}},
+		{{0x0c, 0xff, 0x00},
+		 {0x0c, 0x1f, 0x00},
+		 {0x0c, 0x1b, 0x00},
+		 {0x04, 0xff, 0x01},
+		 {0x04, 0x1f, 0x01},
+		 {0x04, 0x1b, 0x01}},
+	};
+
+	if (frame_rate > 0)
+		sd->frame_rate = frame_rate;
+	if (sd->frame_rate >= 30)
+		fr = 0;
+	else if (sd->frame_rate >= 25)
+		fr = 1;
+	else if (sd->frame_rate >= 20)
+		fr = 2;
+	else if (sd->frame_rate >= 15)
+		fr = 3;
+	else if (sd->frame_rate >= 10)
+		fr = 4;
+	else
+		fr = 5;
+	reg_w(sd, 0xa4, fr_tb[sd->gspca_dev.curr_mode][fr][0]);
+	reg_w(sd, 0x23, fr_tb[sd->gspca_dev.curr_mode][fr][1]);
+	clock = fr_tb[sd->gspca_dev.curr_mode][fr][2];
+	if (sd->sensor == SEN_OV7660)
+		clock |= 0x80;		/* enable double clock */
+	ov518_i2c_w(sd, OV7670_R11_CLKRC, clock);
 }
 
 /* this function is called at probe time */
@@ -2973,99 +3177,119 @@ static int sd_config(struct gspca_dev *g
 {
 	struct sd *sd = (struct sd *) gspca_dev;
 	struct cam *cam = &gspca_dev->cam;
-	int ret = 0;
 
 	sd->bridge = id->driver_info & BRIDGE_MASK;
-	sd->invert_led = id->driver_info & BRIDGE_INVERT_LED;
+	sd->invert_led = (id->driver_info & BRIDGE_INVERT_LED) != 0;
 
 	switch (sd->bridge) {
 	case BRIDGE_OV511:
 	case BRIDGE_OV511PLUS:
-		ret = ov511_configure(gspca_dev);
+		cam->cam_mode = ov511_vga_mode;
+		cam->nmodes = ARRAY_SIZE(ov511_vga_mode);
 		break;
 	case BRIDGE_OV518:
 	case BRIDGE_OV518PLUS:
-		ret = ov518_configure(gspca_dev);
+		cam->cam_mode = ov518_vga_mode;
+		cam->nmodes = ARRAY_SIZE(ov518_vga_mode);
 		break;
 	case BRIDGE_OV519:
-		ret = ov519_configure(sd);
+		cam->cam_mode = ov519_vga_mode;
+		cam->nmodes = ARRAY_SIZE(ov519_vga_mode);
+		sd->invert_led = !sd->invert_led;
 		break;
 	case BRIDGE_OVFX2:
-		ret = ovfx2_configure(sd);
+		cam->cam_mode = ov519_vga_mode;
+		cam->nmodes = ARRAY_SIZE(ov519_vga_mode);
 		cam->bulk_size = OVFX2_BULK_SIZE;
 		cam->bulk_nurbs = MAX_NURBS;
 		cam->bulk = 1;
 		break;
 	case BRIDGE_W9968CF:
-		ret = w9968cf_configure(sd);
+		cam->cam_mode = w9968cf_vga_mode;
+		cam->nmodes = ARRAY_SIZE(w9968cf_vga_mode);
 		cam->reverse_alts = 1;
 		break;
 	}
 
-	if (ret)
-		goto error;
+	gspca_dev->cam.ctrls = sd->ctrls;
+	sd->quality = QUALITY_DEF;
 
-	ov51x_led_control(sd, 0);	/* turn LED off */
+	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;
+	struct cam *cam = &gspca_dev->cam;
+
+	switch (sd->bridge) {
+	case BRIDGE_OV511:
+	case BRIDGE_OV511PLUS:
+		ov511_configure(gspca_dev);
+		break;
+	case BRIDGE_OV518:
+	case BRIDGE_OV518PLUS:
+		ov518_configure(gspca_dev);
+		break;
+	case BRIDGE_OV519:
+		ov519_configure(sd);
+		break;
+	case BRIDGE_OVFX2:
+		ovfx2_configure(sd);
+		break;
+	case BRIDGE_W9968CF:
+		w9968cf_configure(sd);
+		break;
+	}
 
 	/* The OV519 must be more aggressive about sensor detection since
 	 * I2C write will never fail if the sensor is not present. We have
 	 * to try to initialize the sensor to detect its presence */
+	sd->sensor = -1;
 
 	/* Test for 76xx */
 	if (init_ov_sensor(sd, OV7xx0_SID) >= 0) {
-		if (ov7xx0_configure(sd) < 0) {
-			PDEBUG(D_ERR, "Failed to configure OV7xx0");
-			goto error;
-		}
+		ov7xx0_configure(sd);
+
 	/* Test for 6xx0 */
 	} else if (init_ov_sensor(sd, OV6xx0_SID) >= 0) {
-		if (ov6xx0_configure(sd) < 0) {
-			PDEBUG(D_ERR, "Failed to configure OV6xx0");
-			goto error;
-		}
+		ov6xx0_configure(sd);
+
 	/* Test for 8xx0 */
 	} else if (init_ov_sensor(sd, OV8xx0_SID) >= 0) {
-		if (ov8xx0_configure(sd) < 0) {
-			PDEBUG(D_ERR, "Failed to configure OV8xx0");
-			goto error;
-		}
+		ov8xx0_configure(sd);
+
 	/* Test for 3xxx / 2xxx */
 	} else if (init_ov_sensor(sd, OV_HIRES_SID) >= 0) {
-		if (ov_hires_configure(sd) < 0) {
-			PDEBUG(D_ERR, "Failed to configure high res OV");
-			goto error;
-		}
+		ov_hires_configure(sd);
 	} else {
 		err("Can't determine sensor slave IDs");
 		goto error;
 	}
 
+	if (sd->sensor < 0)
+		goto error;
+
+	ov51x_led_control(sd, 0);	/* turn LED off */
+
 	switch (sd->bridge) {
 	case BRIDGE_OV511:
 	case BRIDGE_OV511PLUS:
-		if (!sd->sif) {
-			cam->cam_mode = ov511_vga_mode;
-			cam->nmodes = ARRAY_SIZE(ov511_vga_mode);
-		} else {
+		if (sd->sif) {
 			cam->cam_mode = ov511_sif_mode;
 			cam->nmodes = ARRAY_SIZE(ov511_sif_mode);
 		}
 		break;
 	case BRIDGE_OV518:
 	case BRIDGE_OV518PLUS:
-		if (!sd->sif) {
-			cam->cam_mode = ov518_vga_mode;
-			cam->nmodes = ARRAY_SIZE(ov518_vga_mode);
-		} else {
+		if (sd->sif) {
 			cam->cam_mode = ov518_sif_mode;
 			cam->nmodes = ARRAY_SIZE(ov518_sif_mode);
 		}
 		break;
 	case BRIDGE_OV519:
-		if (!sd->sif) {
-			cam->cam_mode = ov519_vga_mode;
-			cam->nmodes = ARRAY_SIZE(ov519_vga_mode);
-		} else {
+		if (sd->sif) {
 			cam->cam_mode = ov519_sif_mode;
 			cam->nmodes = ARRAY_SIZE(ov519_sif_mode);
 		}
@@ -3077,118 +3301,107 @@ static int sd_config(struct gspca_dev *g
 		} else if (sd->sensor == SEN_OV3610) {
 			cam->cam_mode = ovfx2_ov3610_mode;
 			cam->nmodes = ARRAY_SIZE(ovfx2_ov3610_mode);
-		} else if (!sd->sif) {
-			cam->cam_mode = ov519_vga_mode;
-			cam->nmodes = ARRAY_SIZE(ov519_vga_mode);
-		} else {
+		} else if (sd->sif) {
 			cam->cam_mode = ov519_sif_mode;
 			cam->nmodes = ARRAY_SIZE(ov519_sif_mode);
 		}
 		break;
 	case BRIDGE_W9968CF:
-		cam->cam_mode = w9968cf_vga_mode;
-		cam->nmodes = ARRAY_SIZE(w9968cf_vga_mode);
 		if (sd->sif)
-			cam->nmodes--;
+			cam->nmodes = ARRAY_SIZE(w9968cf_vga_mode) - 1;
 
 		/* w9968cf needs initialisation once the sensor is known */
-		if (w9968cf_init(sd) < 0)
-			goto error;
+		w9968cf_init(sd);
 		break;
 	}
-	gspca_dev->cam.ctrls = sd->ctrls;
-	if (sd->sensor == SEN_OV7670)
-		gspca_dev->ctrl_dis = 1 << COLORS;
-	else
-		gspca_dev->ctrl_dis = (1 << HFLIP) | (1 << VFLIP);
-	sd->quality = QUALITY_DEF;
-	if (sd->sensor == SEN_OV7640 ||
-	    sd->sensor == SEN_OV7648)
-		gspca_dev->ctrl_dis |= (1 << AUTOBRIGHT) | (1 << CONTRAST);
-	if (sd->sensor == SEN_OV7670)
-		gspca_dev->ctrl_dis |= 1 << AUTOBRIGHT;
-	/* OV8610 Frequency filter control should work but needs testing */
-	if (sd->sensor == SEN_OV8610)
-		gspca_dev->ctrl_dis |= 1 << FREQ;
-	/* No controls for the OV2610/OV3610 */
-	if (sd->sensor == SEN_OV2610 || sd->sensor == SEN_OV3610)
-		gspca_dev->ctrl_dis |= (1 << NCTRL) - 1;
 
-	return 0;
-error:
-	PDEBUG(D_ERR, "OV519 Config failed");
-	return -EBUSY;
-}
-
-/* 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;
+	gspca_dev->ctrl_dis = ctrl_dis[sd->sensor];
 
 	/* initialize the sensor */
 	switch (sd->sensor) {
 	case SEN_OV2610:
-		if (write_i2c_regvals(sd, norm_2610, ARRAY_SIZE(norm_2610)))
-			return -EIO;
+		write_i2c_regvals(sd, norm_2610, ARRAY_SIZE(norm_2610));
+
 		/* Enable autogain, autoexpo, awb, bandfilter */
-		if (i2c_w_mask(sd, 0x13, 0x27, 0x27) < 0)
-			return -EIO;
+		i2c_w_mask(sd, 0x13, 0x27, 0x27);
 		break;
 	case SEN_OV3610:
-		if (write_i2c_regvals(sd, norm_3620b, ARRAY_SIZE(norm_3620b)))
-			return -EIO;
+		write_i2c_regvals(sd, norm_3620b, ARRAY_SIZE(norm_3620b));
+
 		/* Enable autogain, autoexpo, awb, bandfilter */
-		if (i2c_w_mask(sd, 0x13, 0x27, 0x27) < 0)
-			return -EIO;
+		i2c_w_mask(sd, 0x13, 0x27, 0x27);
 		break;
 	case SEN_OV6620:
-		if (write_i2c_regvals(sd, norm_6x20, ARRAY_SIZE(norm_6x20)))
-			return -EIO;
+		write_i2c_regvals(sd, norm_6x20, ARRAY_SIZE(norm_6x20));
 		break;
 	case SEN_OV6630:
 	case SEN_OV66308AF:
 		sd->ctrls[CONTRAST].def = 200;
 				 /* The default is too low for the ov6630 */
-		if (write_i2c_regvals(sd, norm_6x30, ARRAY_SIZE(norm_6x30)))
-			return -EIO;
+		write_i2c_regvals(sd, norm_6x30, ARRAY_SIZE(norm_6x30));
 		break;
 	default:
 /*	case SEN_OV7610: */
 /*	case SEN_OV76BE: */
-		if (write_i2c_regvals(sd, norm_7610, ARRAY_SIZE(norm_7610)))
-			return -EIO;
-		if (i2c_w_mask(sd, 0x0e, 0x00, 0x40))
-			return -EIO;
+		write_i2c_regvals(sd, norm_7610, ARRAY_SIZE(norm_7610));
+		i2c_w_mask(sd, 0x0e, 0x00, 0x40);
 		break;
 	case SEN_OV7620:
 	case SEN_OV7620AE:
-		if (write_i2c_regvals(sd, norm_7620, ARRAY_SIZE(norm_7620)))
-			return -EIO;
+		write_i2c_regvals(sd, norm_7620, ARRAY_SIZE(norm_7620));
 		break;
 	case SEN_OV7640:
 	case SEN_OV7648:
-		if (write_i2c_regvals(sd, norm_7640, ARRAY_SIZE(norm_7640)))
-			return -EIO;
+		write_i2c_regvals(sd, norm_7640, ARRAY_SIZE(norm_7640));
+		break;
+	case SEN_OV7660:
+		i2c_w(sd, OV7670_R12_COM7, OV7670_COM7_RESET);
+		msleep(14);
+		reg_w(sd, OV519_R57_SNAPSHOT, 0x23);
+		write_regvals(sd, init_519_ov7660,
+				ARRAY_SIZE(init_519_ov7660));
+		write_i2c_regvals(sd, norm_7660, ARRAY_SIZE(norm_7660));
+		sd->gspca_dev.curr_mode = 1;	/* 640x480 */
+		sd->frame_rate = 15;
+		ov519_set_mode(sd);
+		ov519_set_fr(sd);
+		sd->ctrls[COLORS].max = 4;	/* 0..4 */
+		sd->ctrls[COLORS].val =
+			sd->ctrls[COLORS].def = 2;
+		setcolors(gspca_dev);
+		sd->ctrls[CONTRAST].max = 6;	/* 0..6 */
+		sd->ctrls[CONTRAST].val =
+			sd->ctrls[CONTRAST].def = 3;
+		setcontrast(gspca_dev);
+		sd->ctrls[BRIGHTNESS].max = 6;	/* 0..6 */
+		sd->ctrls[BRIGHTNESS].val =
+			sd->ctrls[BRIGHTNESS].def = 3;
+		setbrightness(gspca_dev);
+		sd_reset_snapshot(gspca_dev);
+		ov51x_restart(sd);
+		ov51x_stop(sd);			/* not in win traces */
+		ov51x_led_control(sd, 0);
 		break;
 	case SEN_OV7670:
 		sd->ctrls[FREQ].max = 3;	/* auto */
 		sd->ctrls[FREQ].def = 3;
-		if (write_i2c_regvals(sd, norm_7670, ARRAY_SIZE(norm_7670)))
-			return -EIO;
+		write_i2c_regvals(sd, norm_7670, ARRAY_SIZE(norm_7670));
 		break;
 	case SEN_OV8610:
-		if (write_i2c_regvals(sd, norm_8610, ARRAY_SIZE(norm_8610)))
-			return -EIO;
+		write_i2c_regvals(sd, norm_8610, ARRAY_SIZE(norm_8610));
 		break;
 	}
-	return 0;
+	return gspca_dev->usb_err;
+error:
+	PDEBUG(D_ERR, "OV519 Config failed");
+	return -EINVAL;
 }
 
 /* Set up the OV511/OV511+ with the given image parameters.
  *
  * Do not put any sensor-specific code in here (including I2C I/O functions)
  */
-static int ov511_mode_init_regs(struct sd *sd)
+static void ov511_mode_init_regs(struct sd *sd)
 {
 	int hsegs, vsegs, packet_size, fps, needed;
 	int interlaced = 0;
@@ -3199,7 +3412,8 @@ static int ov511_mode_init_regs(struct s
 	alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt);
 	if (!alt) {
 		err("Couldn't get altsetting");
-		return -EIO;
+		sd->gspca_dev.usb_err = -EIO;
+		return;
 	}
 
 	packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
@@ -3302,8 +3516,6 @@ static int ov511_mode_init_regs(struct s
 
 	reg_w(sd, R51x_SYS_RESET, OV511_RESET_OMNICE);
 	reg_w(sd, R51x_SYS_RESET, 0);
-
-	return 0;
 }
 
 /* Sets up the OV518/OV518+ with the given image parameters
@@ -3313,7 +3525,7 @@ static int ov511_mode_init_regs(struct s
  *
  * Do not put any sensor-specific code in here (including I2C I/O functions)
  */
-static int ov518_mode_init_regs(struct sd *sd)
+static void ov518_mode_init_regs(struct sd *sd)
 {
 	int hsegs, vsegs, packet_size;
 	struct usb_host_interface *alt;
@@ -3323,14 +3535,14 @@ static int ov518_mode_init_regs(struct s
 	alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt);
 	if (!alt) {
 		err("Couldn't get altsetting");
-		return -EIO;
+		sd->gspca_dev.usb_err = -EIO;
+		return;
 	}
 
 	packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
 	ov518_reg_w32(sd, R51x_FIFO_PSIZE, packet_size & ~7, 2);
 
 	/******** Set the mode ********/
-
 	reg_w(sd, 0x2b, 0);
 	reg_w(sd, 0x2c, 0);
 	reg_w(sd, 0x2d, 0);
@@ -3364,7 +3576,7 @@ static int ov518_mode_init_regs(struct s
 	/* Windows driver does this here; who knows why */
 	reg_w(sd, 0x2f, 0x80);
 
-	/******** Set the framerate  ********/
+	/******** Set the framerate ********/
 	sd->clockdiv = 1;
 
 	/* Mode independent, but framerate dependent, regs */
@@ -3427,11 +3639,8 @@ static int ov518_mode_init_regs(struct s
 	}
 
 	reg_w(sd, 0x2f, 0x80);
-
-	return 0;
 }
 
-
 /* Sets up the OV519 with the given image parameters
  *
  * OV519 needs a completely different approach, until we can figure out what
@@ -3439,12 +3648,12 @@ static int ov518_mode_init_regs(struct s
  *
  * Do not put any sensor-specific code in here (including I2C I/O functions)
  */
-static int ov519_mode_init_regs(struct sd *sd)
+static void ov519_mode_init_regs(struct sd *sd)
 {
 	static const struct ov_regvals mode_init_519_ov7670[] = {
 		{ 0x5d,	0x03 }, /* Turn off suspend mode */
 		{ 0x53,	0x9f }, /* was 9b in 1.65-1.08 */
-		{ 0x54,	0x0f }, /* bit2 (jpeg enable) */
+		{ OV519_R54_EN_CLK1, 0x0f }, /* bit2 (jpeg enable) */
 		{ 0xa2,	0x20 }, /* a2-a5 are undocumented */
 		{ 0xa3,	0x18 },
 		{ 0xa4,	0x04 },
@@ -3467,7 +3676,7 @@ static int ov519_mode_init_regs(struct s
 	static const struct ov_regvals mode_init_519[] = {
 		{ 0x5d,	0x03 }, /* Turn off suspend mode */
 		{ 0x53,	0x9f }, /* was 9b in 1.65-1.08 */
-		{ 0x54,	0x0f }, /* bit2 (jpeg enable) */
+		{ OV519_R54_EN_CLK1, 0x0f }, /* bit2 (jpeg enable) */
 		{ 0xa2,	0x20 }, /* a2-a5 are undocumented */
 		{ 0xa3,	0x18 },
 		{ 0xa4,	0x04 },
@@ -3486,19 +3695,21 @@ static int ov519_mode_init_regs(struct s
 	};
 
 	/******** Set the mode ********/
-	if (sd->sensor != SEN_OV7670) {
-		if (write_regvals(sd, mode_init_519,
-				  ARRAY_SIZE(mode_init_519)))
-			return -EIO;
+	switch (sd->sensor) {
+	default:
+		write_regvals(sd, mode_init_519, ARRAY_SIZE(mode_init_519));
 		if (sd->sensor == SEN_OV7640 ||
 		    sd->sensor == SEN_OV7648) {
 			/* Select 8-bit input mode */
 			reg_w_mask(sd, OV519_R20_DFR, 0x10, 0x10);
 		}
-	} else {
-		if (write_regvals(sd, mode_init_519_ov7670,
-				  ARRAY_SIZE(mode_init_519_ov7670)))
-			return -EIO;
+		break;
+	case SEN_OV7660:
+		return;		/* done by ov519_set_mode/fr() */
+	case SEN_OV7670:
+		write_regvals(sd, mode_init_519_ov7670,
+				ARRAY_SIZE(mode_init_519_ov7670));
+		break;
 	}
 
 	reg_w(sd, OV519_R10_H_SIZE,	sd->gspca_dev.width >> 4);
@@ -3594,17 +3805,16 @@ static int ov519_mode_init_regs(struct s
 		}
 		break;
 	}
-	return 0;
 }
 
-static int mode_init_ov_sensor_regs(struct sd *sd)
+static void mode_init_ov_sensor_regs(struct sd *sd)
 {
 	struct gspca_dev *gspca_dev;
 	int qvga, xstart, xend, ystart, yend;
-	__u8 v;
+	u8 v;
 
 	gspca_dev = &sd->gspca_dev;
-	qvga = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv & 1;
+	qvga = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv & 1;
 
 	/******** Mode (VGA/QVGA) and sensor specific regs ********/
 	switch (sd->sensor) {
@@ -3616,7 +3826,7 @@ static int mode_init_ov_sensor_regs(stru
 		i2c_w_mask(sd, 0x2d, qvga ? 0x40 : 0x00, 0x40);
 		i2c_w_mask(sd, 0x67, qvga ? 0xf0 : 0x90, 0xf0);
 		i2c_w_mask(sd, 0x74, qvga ? 0x20 : 0x00, 0x20);
-		return 0;
+		return;
 	case SEN_OV3610:
 		if (qvga) {
 			xstart = (1040 - gspca_dev->width) / 2 + (0x1f << 4);
@@ -3640,7 +3850,7 @@ static int mode_init_ov_sensor_regs(stru
 		i2c_w(sd, 0x18, xend >> 4);
 		i2c_w(sd, 0x19, ystart >> 3);
 		i2c_w(sd, 0x1a, yend >> 3);
-		return 0;
+		return;
 	case SEN_OV8610:
 		/* For OV8610 qvga means qsvga */
 		i2c_w_mask(sd, OV7610_REG_COM_C, qvga ? (1 << 5) : 0, 1 << 5);
@@ -3687,11 +3897,11 @@ static int mode_init_ov_sensor_regs(stru
 		/* set COM7_FMT_VGA or COM7_FMT_QVGA
 		 * do we need to set anything else?
 		 *	HSTART etc are set in set_ov_sensor_window itself */
-		i2c_w_mask(sd, OV7670_REG_COM7,
+		i2c_w_mask(sd, OV7670_R12_COM7,
 			 qvga ? OV7670_COM7_FMT_QVGA : OV7670_COM7_FMT_VGA,
 			 OV7670_COM7_FMT_MASK);
 		i2c_w_mask(sd, 0x13, 0x00, 0x20); /* Select 16 bit data bus */
-		i2c_w_mask(sd, OV7670_REG_COM8, OV7670_COM8_AWB,
+		i2c_w_mask(sd, OV7670_R13_COM8, OV7670_COM8_AWB,
 				OV7670_COM8_AWB);
 		if (qvga) {		/* QVGA from ov7670.c by
 					 * Jonathan Corbet */
@@ -3707,21 +3917,21 @@ static int mode_init_ov_sensor_regs(stru
 		}
 		/* OV7670 hardware window registers are split across
 		 * multiple locations */
-		i2c_w(sd, OV7670_REG_HSTART, xstart >> 3);
-		i2c_w(sd, OV7670_REG_HSTOP, xend >> 3);
-		v = i2c_r(sd, OV7670_REG_HREF);
+		i2c_w(sd, OV7670_R17_HSTART, xstart >> 3);
+		i2c_w(sd, OV7670_R18_HSTOP, xend >> 3);
+		v = i2c_r(sd, OV7670_R32_HREF);
 		v = (v & 0xc0) | ((xend & 0x7) << 3) | (xstart & 0x07);
 		msleep(10);	/* need to sleep between read and write to
 				 * same reg! */
-		i2c_w(sd, OV7670_REG_HREF, v);
+		i2c_w(sd, OV7670_R32_HREF, v);
 
-		i2c_w(sd, OV7670_REG_VSTART, ystart >> 2);
-		i2c_w(sd, OV7670_REG_VSTOP, yend >> 2);
-		v = i2c_r(sd, OV7670_REG_VREF);
+		i2c_w(sd, OV7670_R19_VSTART, ystart >> 2);
+		i2c_w(sd, OV7670_R1A_VSTOP, yend >> 2);
+		v = i2c_r(sd, OV7670_R03_VREF);
 		v = (v & 0xc0) | ((yend & 0x3) << 2) | (ystart & 0x03);
 		msleep(10);	/* need to sleep between read and write to
 				 * same reg! */
-		i2c_w(sd, OV7670_REG_VREF, v);
+		i2c_w(sd, OV7670_R03_VREF, v);
 		break;
 	case SEN_OV6620:
 		i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20);
@@ -3734,46 +3944,50 @@ static int mode_init_ov_sensor_regs(stru
 		i2c_w_mask(sd, 0x12, 0x04, 0x06); /* AWB: 1 Test pattern: 0 */
 		break;
 	default:
-		return -EINVAL;
+		return;
 	}
 
 	/******** Clock programming ********/
 	i2c_w(sd, 0x11, sd->clockdiv);
-
-	return 0;
 }
 
+/* this function works for bridge ov519 and sensors ov7660 and ov7670 only */
 static void sethvflip(struct gspca_dev *gspca_dev)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
 
-	if (sd->sensor != SEN_OV7670)
-		return;
 	if (sd->gspca_dev.streaming)
-		ov51x_stop(sd);
-	i2c_w_mask(sd, OV7670_REG_MVFP,
+		reg_w(sd, OV519_R51_RESET1, 0x0f);	/* block stream */
+	i2c_w_mask(sd, OV7670_R1E_MVFP,
 		OV7670_MVFP_MIRROR * sd->ctrls[HFLIP].val
 			| OV7670_MVFP_VFLIP * sd->ctrls[VFLIP].val,
 		OV7670_MVFP_MIRROR | OV7670_MVFP_VFLIP);
 	if (sd->gspca_dev.streaming)
-		ov51x_restart(sd);
+		reg_w(sd, OV519_R51_RESET1, 0x00);	/* restart stream */
 }
 
-static int set_ov_sensor_window(struct sd *sd)
+static void set_ov_sensor_window(struct sd *sd)
 {
 	struct gspca_dev *gspca_dev;
 	int qvga, crop;
 	int hwsbase, hwebase, vwsbase, vwebase, hwscale, vwscale;
-	int ret;
 
 	/* mode setup is fully handled in mode_init_ov_sensor_regs for these */
-	if (sd->sensor == SEN_OV2610 || sd->sensor == SEN_OV3610 ||
-	    sd->sensor == SEN_OV7670)
-		return mode_init_ov_sensor_regs(sd);
+	switch (sd->sensor) {
+	case SEN_OV2610:
+	case SEN_OV3610:
+	case SEN_OV7670:
+		mode_init_ov_sensor_regs(sd);
+		return;
+	case SEN_OV7660:
+		ov519_set_mode(sd);
+		ov519_set_fr(sd);
+		return;
+	}
 
 	gspca_dev = &sd->gspca_dev;
-	qvga = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv & 1;
-	crop = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv & 2;
+	qvga = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv & 1;
+	crop = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv & 2;
 
 	/* The different sensor ICs handle setting up of window differently.
 	 * IF YOU SET IT WRONG, YOU WILL GET ALL ZERO ISOC DATA FROM OV51x!! */
@@ -3820,7 +4034,7 @@ static int set_ov_sensor_window(struct s
 		vwsbase = vwebase = 0x03;
 		break;
 	default:
-		return -EINVAL;
+		return;
 	}
 
 	switch (sd->sensor) {
@@ -3855,23 +4069,18 @@ static int set_ov_sensor_window(struct s
 		}
 	}
 
-	ret = mode_init_ov_sensor_regs(sd);
-	if (ret < 0)
-		return ret;
+	mode_init_ov_sensor_regs(sd);
 
 	i2c_w(sd, 0x17, hwsbase);
 	i2c_w(sd, 0x18, hwebase + (sd->sensor_width >> hwscale));
 	i2c_w(sd, 0x19, vwsbase);
 	i2c_w(sd, 0x1a, vwebase + (sd->sensor_height >> vwscale));
-
-	return 0;
 }
 
 /* -- start the camera -- */
 static int sd_start(struct gspca_dev *gspca_dev)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
-	int ret = 0;
 
 	/* Default for most bridges, allow bridge_mode_init_regs to override */
 	sd->sensor_width = sd->gspca_dev.width;
@@ -3880,50 +4089,46 @@ static int sd_start(struct gspca_dev *gs
 	switch (sd->bridge) {
 	case BRIDGE_OV511:
 	case BRIDGE_OV511PLUS:
-		ret = ov511_mode_init_regs(sd);
+		ov511_mode_init_regs(sd);
 		break;
 	case BRIDGE_OV518:
 	case BRIDGE_OV518PLUS:
-		ret = ov518_mode_init_regs(sd);
+		ov518_mode_init_regs(sd);
 		break;
 	case BRIDGE_OV519:
-		ret = ov519_mode_init_regs(sd);
+		ov519_mode_init_regs(sd);
 		break;
 	/* case BRIDGE_OVFX2: nothing to do */
 	case BRIDGE_W9968CF:
-		ret = w9968cf_mode_init_regs(sd);
+		w9968cf_mode_init_regs(sd);
 		break;
 	}
-	if (ret < 0)
-		goto out;
 
-	ret = set_ov_sensor_window(sd);
-	if (ret < 0)
-		goto out;
+	set_ov_sensor_window(sd);
 
-	setcontrast(gspca_dev);
-	setbrightness(gspca_dev);
-	setcolors(gspca_dev);
-	sethvflip(gspca_dev);
-	setautobright(gspca_dev);
-	setfreq_i(sd);
+	if (!(sd->gspca_dev.ctrl_dis & (1 << CONTRAST)))
+		setcontrast(gspca_dev);
+	if (!(sd->gspca_dev.ctrl_dis & (1 << BRIGHTNESS)))
+		setbrightness(gspca_dev);
+	if (!(sd->gspca_dev.ctrl_dis & (1 << COLORS)))
+		setcolors(gspca_dev);
+	if (!(sd->gspca_dev.ctrl_dis & ((1 << HFLIP) | (1 << VFLIP))))
+		sethvflip(gspca_dev);
+	if (!(sd->gspca_dev.ctrl_dis & (1 << AUTOBRIGHT)))
+		setautobright(gspca_dev);
+	if (!(sd->gspca_dev.ctrl_dis & (1 << FREQ)))
+		setfreq_i(sd);
 
 	/* Force clear snapshot state in case the snapshot button was
 	   pressed while we weren't streaming */
 	sd->snapshot_needs_reset = 1;
 	sd_reset_snapshot(gspca_dev);
-	sd->snapshot_pressed = 0;
 
 	sd->first_frame = 3;
 
-	ret = ov51x_restart(sd);
-	if (ret < 0)
-		goto out;
+	ov51x_restart(sd);
 	ov51x_led_control(sd, 1);
-	return 0;
-out:
-	PDEBUG(D_ERR, "camera start error:%d", ret);
-	return ret;
+	return gspca_dev->usb_err;
 }
 
 static void sd_stopN(struct gspca_dev *gspca_dev)
@@ -3938,8 +4143,21 @@ static void sd_stop0(struct gspca_dev *g
 {
 	struct sd *sd = (struct sd *) gspca_dev;
 
+	if (!sd->gspca_dev.present)
+		return;
 	if (sd->bridge == BRIDGE_W9968CF)
 		w9968cf_stop0(sd);
+
+#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
+	/* If the last button state is pressed, release it now! */
+	if (sd->snapshot_pressed) {
+		input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
+		input_sync(gspca_dev->input_dev);
+		sd->snapshot_pressed = 0;
+	}
+#endif
+	if (sd->bridge == BRIDGE_OV519)
+		reg_w(sd, OV519_R57_SNAPSHOT, 0x23);
 }
 
 static void ov51x_handle_button(struct gspca_dev *gspca_dev, u8 state)
@@ -4160,6 +4378,22 @@ static void setbrightness(struct gspca_d
 {
 	struct sd *sd = (struct sd *) gspca_dev;
 	int val;
+	static const struct ov_i2c_regvals brit_7660[][7] = {
+		{{0x0f, 0x6a}, {0x24, 0x40}, {0x25, 0x2b}, {0x26, 0x90},
+			{0x27, 0xe0}, {0x28, 0xe0}, {0x2c, 0xe0}},
+		{{0x0f, 0x6a}, {0x24, 0x50}, {0x25, 0x40}, {0x26, 0xa1},
+			{0x27, 0xc0}, {0x28, 0xc0}, {0x2c, 0xc0}},
+		{{0x0f, 0x6a}, {0x24, 0x68}, {0x25, 0x58}, {0x26, 0xc2},
+			{0x27, 0xa0}, {0x28, 0xa0}, {0x2c, 0xa0}},
+		{{0x0f, 0x6a}, {0x24, 0x70}, {0x25, 0x68}, {0x26, 0xd3},
+			{0x27, 0x80}, {0x28, 0x80}, {0x2c, 0x80}},
+		{{0x0f, 0x6a}, {0x24, 0x80}, {0x25, 0x70}, {0x26, 0xd3},
+			{0x27, 0x20}, {0x28, 0x20}, {0x2c, 0x20}},
+		{{0x0f, 0x6a}, {0x24, 0x88}, {0x25, 0x78}, {0x26, 0xd3},
+			{0x27, 0x40}, {0x28, 0x40}, {0x2c, 0x40}},
+		{{0x0f, 0x6a}, {0x24, 0x90}, {0x25, 0x80}, {0x26, 0xd4},
+			{0x27, 0x60}, {0x28, 0x60}, {0x2c, 0x60}}
+	};
 
 	val = sd->ctrls[BRIGHTNESS].val;
 	switch (sd->sensor) {
@@ -4179,10 +4413,14 @@ static void setbrightness(struct gspca_d
 		if (!sd->ctrls[AUTOBRIGHT].val)
 			i2c_w(sd, OV7610_REG_BRT, val);
 		break;
+	case SEN_OV7660:
+		write_i2c_regvals(sd, brit_7660[val],
+				ARRAY_SIZE(brit_7660[0]));
+		break;
 	case SEN_OV7670:
 /*win trace
- *		i2c_w_mask(sd, OV7670_REG_COM8, 0, OV7670_COM8_AEC); */
-		i2c_w(sd, OV7670_REG_BRIGHT, ov7670_abs_to_sm(val));
+ *		i2c_w_mask(sd, OV7670_R13_COM8, 0, OV7670_COM8_AEC); */
+		i2c_w(sd, OV7670_R55_BRIGHT, ov7670_abs_to_sm(val));
 		break;
 	}
 }
@@ -4191,6 +4429,64 @@ static void setcontrast(struct gspca_dev
 {
 	struct sd *sd = (struct sd *) gspca_dev;
 	int val;
+	static const struct ov_i2c_regvals contrast_7660[][31] = {
+		{{0x6c, 0xf0}, {0x6d, 0xf0}, {0x6e, 0xf8}, {0x6f, 0xa0},
+		 {0x70, 0x58}, {0x71, 0x38}, {0x72, 0x30}, {0x73, 0x30},
+		 {0x74, 0x28}, {0x75, 0x28}, {0x76, 0x24}, {0x77, 0x24},
+		 {0x78, 0x22}, {0x79, 0x28}, {0x7a, 0x2a}, {0x7b, 0x34},
+		 {0x7c, 0x0f}, {0x7d, 0x1e}, {0x7e, 0x3d}, {0x7f, 0x65},
+		 {0x80, 0x70}, {0x81, 0x77}, {0x82, 0x7d}, {0x83, 0x83},
+		 {0x84, 0x88}, {0x85, 0x8d}, {0x86, 0x96}, {0x87, 0x9f},
+		 {0x88, 0xb0}, {0x89, 0xc4}, {0x8a, 0xd9}},
+		{{0x6c, 0xf0}, {0x6d, 0xf0}, {0x6e, 0xf8}, {0x6f, 0x94},
+		 {0x70, 0x58}, {0x71, 0x40}, {0x72, 0x30}, {0x73, 0x30},
+		 {0x74, 0x30}, {0x75, 0x30}, {0x76, 0x2c}, {0x77, 0x24},
+		 {0x78, 0x22}, {0x79, 0x28}, {0x7a, 0x2a}, {0x7b, 0x31},
+		 {0x7c, 0x0f}, {0x7d, 0x1e}, {0x7e, 0x3d}, {0x7f, 0x62},
+		 {0x80, 0x6d}, {0x81, 0x75}, {0x82, 0x7b}, {0x83, 0x81},
+		 {0x84, 0x87}, {0x85, 0x8d}, {0x86, 0x98}, {0x87, 0xa1},
+		 {0x88, 0xb2}, {0x89, 0xc6}, {0x8a, 0xdb}},
+		{{0x6c, 0xf0}, {0x6d, 0xf0}, {0x6e, 0xf0}, {0x6f, 0x84},
+		 {0x70, 0x58}, {0x71, 0x48}, {0x72, 0x40}, {0x73, 0x40},
+		 {0x74, 0x28}, {0x75, 0x28}, {0x76, 0x28}, {0x77, 0x24},
+		 {0x78, 0x26}, {0x79, 0x28}, {0x7a, 0x28}, {0x7b, 0x34},
+		 {0x7c, 0x0f}, {0x7d, 0x1e}, {0x7e, 0x3c}, {0x7f, 0x5d},
+		 {0x80, 0x68}, {0x81, 0x71}, {0x82, 0x79}, {0x83, 0x81},
+		 {0x84, 0x86}, {0x85, 0x8b}, {0x86, 0x95}, {0x87, 0x9e},
+		 {0x88, 0xb1}, {0x89, 0xc5}, {0x8a, 0xd9}},
+		{{0x6c, 0xf0}, {0x6d, 0xf0}, {0x6e, 0xf0}, {0x6f, 0x70},
+		 {0x70, 0x58}, {0x71, 0x58}, {0x72, 0x48}, {0x73, 0x48},
+		 {0x74, 0x38}, {0x75, 0x40}, {0x76, 0x34}, {0x77, 0x34},
+		 {0x78, 0x2e}, {0x79, 0x28}, {0x7a, 0x24}, {0x7b, 0x22},
+		 {0x7c, 0x0f}, {0x7d, 0x1e}, {0x7e, 0x3c}, {0x7f, 0x58},
+		 {0x80, 0x63}, {0x81, 0x6e}, {0x82, 0x77}, {0x83, 0x80},
+		 {0x84, 0x87}, {0x85, 0x8f}, {0x86, 0x9c}, {0x87, 0xa9},
+		 {0x88, 0xc0}, {0x89, 0xd4}, {0x8a, 0xe6}},
+		{{0x6c, 0xa0}, {0x6d, 0xf0}, {0x6e, 0x90}, {0x6f, 0x80},
+		 {0x70, 0x70}, {0x71, 0x80}, {0x72, 0x60}, {0x73, 0x60},
+		 {0x74, 0x58}, {0x75, 0x60}, {0x76, 0x4c}, {0x77, 0x38},
+		 {0x78, 0x38}, {0x79, 0x2a}, {0x7a, 0x20}, {0x7b, 0x0e},
+		 {0x7c, 0x0a}, {0x7d, 0x14}, {0x7e, 0x26}, {0x7f, 0x46},
+		 {0x80, 0x54}, {0x81, 0x64}, {0x82, 0x70}, {0x83, 0x7c},
+		 {0x84, 0x87}, {0x85, 0x93}, {0x86, 0xa6}, {0x87, 0xb4},
+		 {0x88, 0xd0}, {0x89, 0xe5}, {0x8a, 0xf5}},
+		{{0x6c, 0x60}, {0x6d, 0x80}, {0x6e, 0x60}, {0x6f, 0x80},
+		 {0x70, 0x80}, {0x71, 0x80}, {0x72, 0x88}, {0x73, 0x30},
+		 {0x74, 0x70}, {0x75, 0x68}, {0x76, 0x64}, {0x77, 0x50},
+		 {0x78, 0x3c}, {0x79, 0x22}, {0x7a, 0x10}, {0x7b, 0x08},
+		 {0x7c, 0x06}, {0x7d, 0x0e}, {0x7e, 0x1a}, {0x7f, 0x3a},
+		 {0x80, 0x4a}, {0x81, 0x5a}, {0x82, 0x6b}, {0x83, 0x7b},
+		 {0x84, 0x89}, {0x85, 0x96}, {0x86, 0xaf}, {0x87, 0xc3},
+		 {0x88, 0xe1}, {0x89, 0xf2}, {0x8a, 0xfa}},
+		{{0x6c, 0x20}, {0x6d, 0x40}, {0x6e, 0x20}, {0x6f, 0x60},
+		 {0x70, 0x88}, {0x71, 0xc8}, {0x72, 0xc0}, {0x73, 0xb8},
+		 {0x74, 0xa8}, {0x75, 0xb8}, {0x76, 0x80}, {0x77, 0x5c},
+		 {0x78, 0x26}, {0x79, 0x10}, {0x7a, 0x08}, {0x7b, 0x04},
+		 {0x7c, 0x02}, {0x7d, 0x06}, {0x7e, 0x0a}, {0x7f, 0x22},
+		 {0x80, 0x33}, {0x81, 0x4c}, {0x82, 0x64}, {0x83, 0x7b},
+		 {0x84, 0x90}, {0x85, 0xa7}, {0x86, 0xc7}, {0x87, 0xde},
+		 {0x88, 0xf1}, {0x89, 0xf9}, {0x8a, 0xfd}},
+	};
 
 	val = sd->ctrls[CONTRAST].val;
 	switch (sd->sensor) {
@@ -4203,7 +4499,7 @@ static void setcontrast(struct gspca_dev
 		i2c_w_mask(sd, OV7610_REG_CNT, val >> 4, 0x0f);
 		break;
 	case SEN_OV8610: {
-		static const __u8 ctab[] = {
+		static const u8 ctab[] = {
 			0x03, 0x09, 0x0b, 0x0f, 0x53, 0x6f, 0x35, 0x7f
 		};
 
@@ -4213,7 +4509,7 @@ static void setcontrast(struct gspca_dev
 	    }
 	case SEN_OV7620:
 	case SEN_OV7620AE: {
-		static const __u8 ctab[] = {
+		static const u8 ctab[] = {
 			0x01, 0x05, 0x09, 0x11, 0x15, 0x35, 0x37, 0x57,
 			0x5b, 0xa5, 0xa7, 0xc7, 0xc9, 0xcf, 0xef, 0xff
 		};
@@ -4222,9 +4518,13 @@ static void setcontrast(struct gspca_dev
 		i2c_w(sd, 0x64, ctab[val >> 4]);
 		break;
 	    }
+	case SEN_OV7660:
+		write_i2c_regvals(sd, contrast_7660[val],
+					ARRAY_SIZE(contrast_7660[0]));
+		break;
 	case SEN_OV7670:
 		/* check that this isn't just the same as ov7610 */
-		i2c_w(sd, OV7670_REG_CONTRAS, val >> 1);
+		i2c_w(sd, OV7670_R56_CONTRAS, val >> 1);
 		break;
 	}
 }
@@ -4233,6 +4533,18 @@ static void setcolors(struct gspca_dev *
 {
 	struct sd *sd = (struct sd *) gspca_dev;
 	int val;
+	static const struct ov_i2c_regvals colors_7660[][6] = {
+		{{0x4f, 0x28}, {0x50, 0x2a}, {0x51, 0x02}, {0x52, 0x0a},
+		 {0x53, 0x19}, {0x54, 0x23}},
+		{{0x4f, 0x47}, {0x50, 0x4a}, {0x51, 0x03}, {0x52, 0x11},
+		 {0x53, 0x2c}, {0x54, 0x3e}},
+		{{0x4f, 0x66}, {0x50, 0x6b}, {0x51, 0x05}, {0x52, 0x19},
+		 {0x53, 0x40}, {0x54, 0x59}},
+		{{0x4f, 0x84}, {0x50, 0x8b}, {0x51, 0x06}, {0x52, 0x20},
+		 {0x53, 0x53}, {0x54, 0x73}},
+		{{0x4f, 0xa3}, {0x50, 0xab}, {0x51, 0x08}, {0x52, 0x28},
+		 {0x53, 0x66}, {0x54, 0x8e}},
+	};
 
 	val = sd->ctrls[COLORS].val;
 	switch (sd->sensor) {
@@ -4256,6 +4568,10 @@ static void setcolors(struct gspca_dev *
 	case SEN_OV7648:
 		i2c_w(sd, OV7610_REG_SAT, val & 0xf0);
 		break;
+	case SEN_OV7660:
+		write_i2c_regvals(sd, colors_7660[val],
+					ARRAY_SIZE(colors_7660[0]));
+		break;
 	case SEN_OV7670:
 		/* supported later once I work out how to do it
 		 * transparently fail now! */
@@ -4268,38 +4584,31 @@ static void setautobright(struct gspca_d
 {
 	struct sd *sd = (struct sd *) gspca_dev;
 
-	if (sd->sensor == SEN_OV7640 || sd->sensor == SEN_OV7648 ||
-	    sd->sensor == SEN_OV7670 ||
-	    sd->sensor == SEN_OV2610 || sd->sensor == SEN_OV3610)
-		return;
-
 	i2c_w_mask(sd, 0x2d, sd->ctrls[AUTOBRIGHT].val ? 0x10 : 0x00, 0x10);
 }
 
 static void setfreq_i(struct sd *sd)
 {
-	if (sd->sensor == SEN_OV2610 || sd->sensor == SEN_OV3610)
-		return;
-
-	if (sd->sensor == SEN_OV7670) {
+	if (sd->sensor == SEN_OV7660
+	 || sd->sensor == SEN_OV7670) {
 		switch (sd->ctrls[FREQ].val) {
 		case 0: /* Banding filter disabled */
-			i2c_w_mask(sd, OV7670_REG_COM8, 0, OV7670_COM8_BFILT);
+			i2c_w_mask(sd, OV7670_R13_COM8, 0, OV7670_COM8_BFILT);
 			break;
 		case 1: /* 50 hz */
-			i2c_w_mask(sd, OV7670_REG_COM8, OV7670_COM8_BFILT,
+			i2c_w_mask(sd, OV7670_R13_COM8, OV7670_COM8_BFILT,
 				   OV7670_COM8_BFILT);
-			i2c_w_mask(sd, OV7670_REG_COM11, 0x08, 0x18);
+			i2c_w_mask(sd, OV7670_R3B_COM11, 0x08, 0x18);
 			break;
 		case 2: /* 60 hz */
-			i2c_w_mask(sd, OV7670_REG_COM8, OV7670_COM8_BFILT,
+			i2c_w_mask(sd, OV7670_R13_COM8, OV7670_COM8_BFILT,
 				   OV7670_COM8_BFILT);
-			i2c_w_mask(sd, OV7670_REG_COM11, 0x00, 0x18);
+			i2c_w_mask(sd, OV7670_R3B_COM11, 0x00, 0x18);
 			break;
-		case 3: /* Auto hz */
-			i2c_w_mask(sd, OV7670_REG_COM8, OV7670_COM8_BFILT,
+		case 3: /* Auto hz - ov7670 only */
+			i2c_w_mask(sd, OV7670_R13_COM8, OV7670_COM8_BFILT,
 				   OV7670_COM8_BFILT);
-			i2c_w_mask(sd, OV7670_REG_COM11, OV7670_COM11_HZAUTO,
+			i2c_w_mask(sd, OV7670_R3B_COM11, OV7670_COM11_HZAUTO,
 				   0x18);
 			break;
 		}
@@ -4436,21 +4745,21 @@ static const struct sd_desc sd_desc = {
 };
 
 /* -- module initialisation -- */
-static const __devinitdata struct usb_device_id device_table[] = {
+static const struct usb_device_id device_table[] = {
 	{USB_DEVICE(0x041e, 0x4003), .driver_info = BRIDGE_W9968CF },
 	{USB_DEVICE(0x041e, 0x4052), .driver_info = BRIDGE_OV519 },
 	{USB_DEVICE(0x041e, 0x405f), .driver_info = BRIDGE_OV519 },
 	{USB_DEVICE(0x041e, 0x4060), .driver_info = BRIDGE_OV519 },
 	{USB_DEVICE(0x041e, 0x4061), .driver_info = BRIDGE_OV519 },
 	{USB_DEVICE(0x041e, 0x4064),
-	 .driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED },
+		.driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED },
 	{USB_DEVICE(0x041e, 0x4067), .driver_info = BRIDGE_OV519 },
 	{USB_DEVICE(0x041e, 0x4068),
-	 .driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED },
+		.driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED },
 	{USB_DEVICE(0x045e, 0x028c), .driver_info = BRIDGE_OV519 },
 	{USB_DEVICE(0x054c, 0x0154), .driver_info = BRIDGE_OV519 },
 	{USB_DEVICE(0x054c, 0x0155),
-	 .driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED },
+		.driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED },
 	{USB_DEVICE(0x05a9, 0x0511), .driver_info = BRIDGE_OV511 },
 	{USB_DEVICE(0x05a9, 0x0518), .driver_info = BRIDGE_OV518 },
 	{USB_DEVICE(0x05a9, 0x0519), .driver_info = BRIDGE_OV519 },
@@ -4464,7 +4773,7 @@ static const __devinitdata struct usb_de
 	{USB_DEVICE(0x0b62, 0x0059), .driver_info = BRIDGE_OVFX2 },
 	{USB_DEVICE(0x0e96, 0xc001), .driver_info = BRIDGE_OVFX2 },
 	{USB_DEVICE(0x1046, 0x9967), .driver_info = BRIDGE_W9968CF },
-	{USB_DEVICE(0x8020, 0xEF04), .driver_info = BRIDGE_OVFX2 },
+	{USB_DEVICE(0x8020, 0xef04), .driver_info = BRIDGE_OVFX2 },
 	{}
 };
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/gspca/ov534_9.c linux-libre-2.6.38-gnu1/drivers/media/video/gspca/ov534_9.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/gspca/ov534_9.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/gspca/ov534_9.c	2011-03-14 21:20:32.000000000 -0400
@@ -945,7 +945,6 @@ static void setautogain(struct gspca_dev
 	u8 val;
 
 /*fixme: should adjust agc/awb/aec by different controls */
-	val = sd->autogain;
 	val = sccb_read(gspca_dev, 0x13);		/* com8 */
 	sccb_write(gspca_dev, 0xff, 0x00);
 	if (sd->autogain)
@@ -1430,7 +1429,7 @@ static const struct sd_desc sd_desc = {
 };
 
 /* -- module initialisation -- */
-static const __devinitdata struct usb_device_id device_table[] = {
+static const struct usb_device_id device_table[] = {
 	{USB_DEVICE(0x06f8, 0x3003)},
 	{}
 };
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/gspca/ov534.c linux-libre-2.6.38-gnu1/drivers/media/video/gspca/ov534.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/gspca/ov534.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/gspca/ov534.c	2011-03-14 21:20:32.000000000 -0400
@@ -479,15 +479,20 @@ static void ov534_reg_write(struct gspca
 	struct usb_device *udev = gspca_dev->dev;
 	int ret;
 
-	PDEBUG(D_USBO, "reg=0x%04x, val=0%02x", reg, val);
+	if (gspca_dev->usb_err < 0)
+		return;
+
+	PDEBUG(D_USBO, "SET 01 0000 %04x %02x", reg, val);
 	gspca_dev->usb_buf[0] = val;
 	ret = usb_control_msg(udev,
 			      usb_sndctrlpipe(udev, 0),
 			      0x01,
 			      USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 			      0x00, reg, gspca_dev->usb_buf, 1, CTRL_TIMEOUT);
-	if (ret < 0)
+	if (ret < 0) {
 		err("write failed %d", ret);
+		gspca_dev->usb_err = ret;
+	}
 }
 
 static u8 ov534_reg_read(struct gspca_dev *gspca_dev, u16 reg)
@@ -495,14 +500,18 @@ static u8 ov534_reg_read(struct gspca_de
 	struct usb_device *udev = gspca_dev->dev;
 	int ret;
 
+	if (gspca_dev->usb_err < 0)
+		return 0;
 	ret = usb_control_msg(udev,
 			      usb_rcvctrlpipe(udev, 0),
 			      0x01,
 			      USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 			      0x00, reg, gspca_dev->usb_buf, 1, CTRL_TIMEOUT);
-	PDEBUG(D_USBI, "reg=0x%04x, data=0x%02x", reg, gspca_dev->usb_buf[0]);
-	if (ret < 0)
+	PDEBUG(D_USBI, "GET 01 0000 %04x %02x", reg, gspca_dev->usb_buf[0]);
+	if (ret < 0) {
 		err("read failed %d", ret);
+		gspca_dev->usb_err = ret;
+	}
 	return gspca_dev->usb_buf[0];
 }
 
@@ -558,13 +567,15 @@ static int sccb_check_status(struct gspc
 
 static void sccb_reg_write(struct gspca_dev *gspca_dev, u8 reg, u8 val)
 {
-	PDEBUG(D_USBO, "reg: 0x%02x, val: 0x%02x", reg, val);
+	PDEBUG(D_USBO, "sccb write: %02x %02x", reg, val);
 	ov534_reg_write(gspca_dev, OV534_REG_SUBADDR, reg);
 	ov534_reg_write(gspca_dev, OV534_REG_WRITE, val);
 	ov534_reg_write(gspca_dev, OV534_REG_OPERATION, OV534_OP_WRITE_3);
 
-	if (!sccb_check_status(gspca_dev))
+	if (!sccb_check_status(gspca_dev)) {
 		err("sccb_reg_write failed");
+		gspca_dev->usb_err = -EIO;
+	}
 }
 
 static u8 sccb_reg_read(struct gspca_dev *gspca_dev, u16 reg)
@@ -885,7 +896,7 @@ static int sd_init(struct gspca_dev *gsp
 	ov534_set_led(gspca_dev, 0);
 	set_frame_rate(gspca_dev);
 
-	return 0;
+	return gspca_dev->usb_err;
 }
 
 static int sd_start(struct gspca_dev *gspca_dev)
@@ -920,7 +931,7 @@ static int sd_start(struct gspca_dev *gs
 
 	ov534_set_led(gspca_dev, 1);
 	ov534_reg_write(gspca_dev, 0xe0, 0x00);
-	return 0;
+	return gspca_dev->usb_err;
 }
 
 static void sd_stopN(struct gspca_dev *gspca_dev)
@@ -1243,34 +1254,26 @@ static int sd_querymenu(struct gspca_dev
 }
 
 /* get stream parameters (framerate) */
-static int sd_get_streamparm(struct gspca_dev *gspca_dev,
+static void sd_get_streamparm(struct gspca_dev *gspca_dev,
 			     struct v4l2_streamparm *parm)
 {
 	struct v4l2_captureparm *cp = &parm->parm.capture;
 	struct v4l2_fract *tpf = &cp->timeperframe;
 	struct sd *sd = (struct sd *) gspca_dev;
 
-	if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-		return -EINVAL;
-
 	cp->capability |= V4L2_CAP_TIMEPERFRAME;
 	tpf->numerator = 1;
 	tpf->denominator = sd->frame_rate;
-
-	return 0;
 }
 
 /* set stream parameters (framerate) */
-static int sd_set_streamparm(struct gspca_dev *gspca_dev,
+static void sd_set_streamparm(struct gspca_dev *gspca_dev,
 			     struct v4l2_streamparm *parm)
 {
 	struct v4l2_captureparm *cp = &parm->parm.capture;
 	struct v4l2_fract *tpf = &cp->timeperframe;
 	struct sd *sd = (struct sd *) gspca_dev;
 
-	if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-		return -EINVAL;
-
 	/* Set requested framerate */
 	sd->frame_rate = tpf->denominator / tpf->numerator;
 	if (gspca_dev->streaming)
@@ -1279,8 +1282,6 @@ static int sd_set_streamparm(struct gspc
 	/* Return the actual framerate */
 	tpf->numerator = 1;
 	tpf->denominator = sd->frame_rate;
-
-	return 0;
 }
 
 /* sub-driver description */
@@ -1299,7 +1300,7 @@ static const struct sd_desc sd_desc = {
 };
 
 /* -- module initialisation -- */
-static const __devinitdata struct usb_device_id device_table[] = {
+static const struct usb_device_id device_table[] = {
 	{USB_DEVICE(0x1415, 0x2000)},
 	{}
 };
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/gspca/pac207.c linux-libre-2.6.38-gnu1/drivers/media/video/gspca/pac207.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/gspca/pac207.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/gspca/pac207.c	2011-03-14 21:20:32.000000000 -0400
@@ -162,7 +162,7 @@ static const __u8 pac207_sensor_init[][8
 	{0x10, 0x12, 0x0d, 0x12, 0x0c, 0x01, 0x29, 0x84},
 	{0x49, 0x64, 0x64, 0x64, 0x04, 0x10, 0xf0, 0x30},
 	{0x00, 0x00, 0x00, 0x70, 0xa0, 0xf8, 0x00, 0x00},
-	{0x32, 0x00, 0x96, 0x00, 0xA2, 0x02, 0xaf, 0x00},
+	{0x32, 0x00, 0x96, 0x00, 0xa2, 0x02, 0xaf, 0x00},
 };
 
 static int pac207_write_regs(struct gspca_dev *gspca_dev, u16 index,
@@ -228,7 +228,7 @@ static int sd_config(struct gspca_dev *g
 
 	idreg[0] = pac207_read_reg(gspca_dev, 0x0000);
 	idreg[1] = pac207_read_reg(gspca_dev, 0x0001);
-	idreg[0] = ((idreg[0] & 0x0F) << 4) | ((idreg[1] & 0xf0) >> 4);
+	idreg[0] = ((idreg[0] & 0x0f) << 4) | ((idreg[1] & 0xf0) >> 4);
 	idreg[1] = idreg[1] & 0x0f;
 	PDEBUG(D_PROBE, "Pixart Sensor ID 0x%02X Chips ID 0x%02X",
 		idreg[0], idreg[1]);
@@ -530,7 +530,7 @@ static const struct sd_desc sd_desc = {
 };
 
 /* -- module initialisation -- */
-static const __devinitdata struct usb_device_id device_table[] = {
+static const struct usb_device_id device_table[] = {
 	{USB_DEVICE(0x041e, 0x4028)},
 	{USB_DEVICE(0x093a, 0x2460)},
 	{USB_DEVICE(0x093a, 0x2461)},
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/gspca/pac7302.c linux-libre-2.6.38-gnu1/drivers/media/video/gspca/pac7302.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/gspca/pac7302.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/gspca/pac7302.c	2011-03-14 21:20:32.000000000 -0400
@@ -393,7 +393,7 @@ static const __u8 page3_7302[] = {
 
 static void reg_w_buf(struct gspca_dev *gspca_dev,
 		  __u8 index,
-		  const char *buffer, int len)
+		  const u8 *buffer, int len)
 {
 	int ret;
 
@@ -1184,7 +1184,7 @@ static const struct sd_desc sd_desc = {
 };
 
 /* -- module initialisation -- */
-static const struct usb_device_id device_table[] __devinitconst = {
+static const struct usb_device_id device_table[] = {
 	{USB_DEVICE(0x06f8, 0x3009)},
 	{USB_DEVICE(0x093a, 0x2620)},
 	{USB_DEVICE(0x093a, 0x2621)},
@@ -1201,7 +1201,7 @@ static const struct usb_device_id device
 MODULE_DEVICE_TABLE(usb, device_table);
 
 /* -- device connect -- */
-static int __devinit sd_probe(struct usb_interface *intf,
+static int sd_probe(struct usb_interface *intf,
 			const struct usb_device_id *id)
 {
 	return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/gspca/pac7311.c linux-libre-2.6.38-gnu1/drivers/media/video/gspca/pac7311.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/gspca/pac7311.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/gspca/pac7311.c	2011-03-14 21:20:32.000000000 -0400
@@ -261,7 +261,7 @@ static const __u8 page4_7311[] = {
 
 static void reg_w_buf(struct gspca_dev *gspca_dev,
 		  __u8 index,
-		  const char *buffer, int len)
+		  const u8 *buffer, int len)
 {
 	int ret;
 
@@ -837,7 +837,7 @@ static const struct sd_desc sd_desc = {
 };
 
 /* -- module initialisation -- */
-static const struct usb_device_id device_table[] __devinitconst = {
+static const struct usb_device_id device_table[] = {
 	{USB_DEVICE(0x093a, 0x2600)},
 	{USB_DEVICE(0x093a, 0x2601)},
 	{USB_DEVICE(0x093a, 0x2603)},
@@ -849,7 +849,7 @@ static const struct usb_device_id device
 MODULE_DEVICE_TABLE(usb, device_table);
 
 /* -- device connect -- */
-static int __devinit sd_probe(struct usb_interface *intf,
+static int sd_probe(struct usb_interface *intf,
 			const struct usb_device_id *id)
 {
 	return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/gspca/sn9c2028.c linux-libre-2.6.38-gnu1/drivers/media/video/gspca/sn9c2028.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/gspca/sn9c2028.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/gspca/sn9c2028.c	2011-03-14 21:20:32.000000000 -0400
@@ -703,7 +703,7 @@ static const struct sd_desc sd_desc = {
 };
 
 /* -- module initialisation -- */
-static const __devinitdata struct usb_device_id device_table[] = {
+static const struct usb_device_id device_table[] = {
 	{USB_DEVICE(0x0458, 0x7005)}, /* Genius Smart 300, version 2 */
 	/* The Genius Smart is untested. I can't find an owner ! */
 	/* {USB_DEVICE(0x0c45, 0x8000)}, DC31VC, Don't know this camera */
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/gspca/sn9c20x.c linux-libre-2.6.38-gnu1/drivers/media/video/gspca/sn9c20x.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/gspca/sn9c20x.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/gspca/sn9c20x.c	2011-03-14 21:20:32.000000000 -0400
@@ -33,6 +33,14 @@ MODULE_LICENSE("GPL");
 
 #define MODULE_NAME "sn9c20x"
 
+/*
+ * Pixel format private data
+ */
+#define SCALE_MASK	0x0f
+#define SCALE_160x120	0
+#define SCALE_320x240	1
+#define SCALE_640x480	2
+#define SCALE_1280x1024	3
 #define MODE_RAW	0x10
 #define MODE_JPEG	0x20
 #define MODE_SXGA	0x80
@@ -348,47 +356,47 @@ static const struct v4l2_pix_format vga_
 		.bytesperline = 160,
 		.sizeimage = 160 * 120 * 4 / 8 + 590,
 		.colorspace = V4L2_COLORSPACE_JPEG,
-		.priv = 0 | MODE_JPEG},
+		.priv = SCALE_160x120 | MODE_JPEG},
 	{160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
 		.bytesperline = 160,
 		.sizeimage = 160 * 120,
 		.colorspace = V4L2_COLORSPACE_SRGB,
-		.priv = 0 | MODE_RAW},
+		.priv = SCALE_160x120 | MODE_RAW},
 	{160, 120, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
 		.bytesperline = 160,
 		.sizeimage = 240 * 120,
 		.colorspace = V4L2_COLORSPACE_SRGB,
-		.priv = 0},
+		.priv = SCALE_160x120},
 	{320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
 		.bytesperline = 320,
 		.sizeimage = 320 * 240 * 3 / 8 + 590,
 		.colorspace = V4L2_COLORSPACE_JPEG,
-		.priv = 1 | MODE_JPEG},
+		.priv = SCALE_320x240 | MODE_JPEG},
 	{320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
 		.bytesperline = 320,
 		.sizeimage = 320 * 240 ,
 		.colorspace = V4L2_COLORSPACE_SRGB,
-		.priv = 1 | MODE_RAW},
+		.priv = SCALE_320x240 | MODE_RAW},
 	{320, 240, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
 		.bytesperline = 320,
 		.sizeimage = 480 * 240 ,
 		.colorspace = V4L2_COLORSPACE_SRGB,
-		.priv = 1},
+		.priv = SCALE_320x240},
 	{640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
 		.bytesperline = 640,
 		.sizeimage = 640 * 480 * 3 / 8 + 590,
 		.colorspace = V4L2_COLORSPACE_JPEG,
-		.priv = 2 | MODE_JPEG},
+		.priv = SCALE_640x480 | MODE_JPEG},
 	{640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
 		.bytesperline = 640,
 		.sizeimage = 640 * 480,
 		.colorspace = V4L2_COLORSPACE_SRGB,
-		.priv = 2 | MODE_RAW},
+		.priv = SCALE_640x480 | MODE_RAW},
 	{640, 480, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
 		.bytesperline = 640,
 		.sizeimage = 960 * 480,
 		.colorspace = V4L2_COLORSPACE_SRGB,
-		.priv = 2},
+		.priv = SCALE_640x480},
 };
 
 static const struct v4l2_pix_format sxga_mode[] = {
@@ -396,52 +404,75 @@ static const struct v4l2_pix_format sxga
 		.bytesperline = 160,
 		.sizeimage = 160 * 120 * 4 / 8 + 590,
 		.colorspace = V4L2_COLORSPACE_JPEG,
-		.priv = 0 | MODE_JPEG},
+		.priv = SCALE_160x120 | MODE_JPEG},
 	{160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
 		.bytesperline = 160,
 		.sizeimage = 160 * 120,
 		.colorspace = V4L2_COLORSPACE_SRGB,
-		.priv = 0 | MODE_RAW},
+		.priv = SCALE_160x120 | MODE_RAW},
 	{160, 120, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
 		.bytesperline = 160,
 		.sizeimage = 240 * 120,
 		.colorspace = V4L2_COLORSPACE_SRGB,
-		.priv = 0},
+		.priv = SCALE_160x120},
 	{320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
 		.bytesperline = 320,
 		.sizeimage = 320 * 240 * 3 / 8 + 590,
 		.colorspace = V4L2_COLORSPACE_JPEG,
-		.priv = 1 | MODE_JPEG},
+		.priv = SCALE_320x240 | MODE_JPEG},
 	{320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
 		.bytesperline = 320,
 		.sizeimage = 320 * 240 ,
 		.colorspace = V4L2_COLORSPACE_SRGB,
-		.priv = 1 | MODE_RAW},
+		.priv = SCALE_320x240 | MODE_RAW},
 	{320, 240, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
 		.bytesperline = 320,
 		.sizeimage = 480 * 240 ,
 		.colorspace = V4L2_COLORSPACE_SRGB,
-		.priv = 1},
+		.priv = SCALE_320x240},
 	{640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
 		.bytesperline = 640,
 		.sizeimage = 640 * 480 * 3 / 8 + 590,
 		.colorspace = V4L2_COLORSPACE_JPEG,
-		.priv = 2 | MODE_JPEG},
+		.priv = SCALE_640x480 | MODE_JPEG},
 	{640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
 		.bytesperline = 640,
 		.sizeimage = 640 * 480,
 		.colorspace = V4L2_COLORSPACE_SRGB,
-		.priv = 2 | MODE_RAW},
+		.priv = SCALE_640x480 | MODE_RAW},
 	{640, 480, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
 		.bytesperline = 640,
 		.sizeimage = 960 * 480,
 		.colorspace = V4L2_COLORSPACE_SRGB,
-		.priv = 2},
+		.priv = SCALE_640x480},
 	{1280, 1024, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
 		.bytesperline = 1280,
 		.sizeimage = 1280 * 1024,
 		.colorspace = V4L2_COLORSPACE_SRGB,
-		.priv = 3 | MODE_RAW | MODE_SXGA},
+		.priv = SCALE_1280x1024 | MODE_RAW | MODE_SXGA},
+};
+
+static const struct v4l2_pix_format mono_mode[] = {
+	{160, 120, V4L2_PIX_FMT_GREY, V4L2_FIELD_NONE,
+		.bytesperline = 160,
+		.sizeimage = 160 * 120,
+		.colorspace = V4L2_COLORSPACE_SRGB,
+		.priv = SCALE_160x120 | MODE_RAW},
+	{320, 240, V4L2_PIX_FMT_GREY, V4L2_FIELD_NONE,
+		.bytesperline = 320,
+		.sizeimage = 320 * 240 ,
+		.colorspace = V4L2_COLORSPACE_SRGB,
+		.priv = SCALE_320x240 | MODE_RAW},
+	{640, 480, V4L2_PIX_FMT_GREY, V4L2_FIELD_NONE,
+		.bytesperline = 640,
+		.sizeimage = 640 * 480,
+		.colorspace = V4L2_COLORSPACE_SRGB,
+		.priv = SCALE_640x480 | MODE_RAW},
+	{1280, 1024, V4L2_PIX_FMT_GREY, V4L2_FIELD_NONE,
+		.bytesperline = 1280,
+		.sizeimage = 1280 * 1024,
+		.colorspace = V4L2_COLORSPACE_SRGB,
+		.priv = SCALE_1280x1024 | MODE_RAW | MODE_SXGA},
 };
 
 static const s16 hsv_red_x[] = {
@@ -1029,16 +1060,19 @@ static struct i2c_reg_u16 mt9v011_init[]
 };
 
 static struct i2c_reg_u16 mt9m001_init[] = {
-	{0x0d, 0x0001}, {0x0d, 0x0000}, {0x01, 0x000e},
-	{0x02, 0x0014}, {0x03, 0x03c1}, {0x04, 0x0501},
-	{0x05, 0x0083}, {0x06, 0x0006}, {0x0d, 0x0002},
-	{0x0a, 0x0000}, {0x0c, 0x0000}, {0x11, 0x0000},
-	{0x1e, 0x8000}, {0x5f, 0x8904}, {0x60, 0x0000},
-	{0x61, 0x0000}, {0x62, 0x0498}, {0x63, 0x0000},
-	{0x64, 0x0000}, {0x20, 0x111d}, {0x06, 0x00f2},
-	{0x05, 0x0013}, {0x09, 0x10f2}, {0x07, 0x0003},
-	{0x2b, 0x002a}, {0x2d, 0x002a}, {0x2c, 0x002a},
-	{0x2e, 0x0029}, {0x07, 0x0002},
+	{0x0d, 0x0001},
+	{0x0d, 0x0000},
+	{0x04, 0x0500},		/* hres = 1280 */
+	{0x03, 0x0400},		/* vres = 1024 */
+	{0x20, 0x1100},
+	{0x06, 0x0010},
+	{0x2b, 0x0024},
+	{0x2e, 0x0024},
+	{0x35, 0x0024},
+	{0x2d, 0x0020},
+	{0x2c, 0x0020},
+	{0x09, 0x0ad4},
+	{0x35, 0x0057},
 };
 
 static struct i2c_reg_u16 mt9m111_init[] = {
@@ -1224,8 +1258,17 @@ static int i2c_r2(struct gspca_dev *gspc
 static int ov9650_init_sensor(struct gspca_dev *gspca_dev)
 {
 	int i;
+	u16 id;
 	struct sd *sd = (struct sd *) gspca_dev;
 
+	if (i2c_r2(gspca_dev, 0x1c, &id) < 0)
+		return -EINVAL;
+
+	if (id != 0x7fa2) {
+		err("sensor id for ov9650 doesn't match (0x%04x)", 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) {
@@ -1425,6 +1468,25 @@ static int mt9m001_init_sensor(struct gs
 {
 	struct sd *sd = (struct sd *) gspca_dev;
 	int i;
+	u16 id;
+
+	if (i2c_r2(gspca_dev, 0x00, &id) < 0)
+		return -EINVAL;
+
+	/* must be 0x8411 or 0x8421 for colour sensor and 8431 for bw */
+	switch (id) {
+	case 0x8411:
+	case 0x8421:
+		info("MT9M001 color sensor detected");
+		break;
+	case 0x8431:
+		info("MT9M001 mono sensor detected");
+		break;
+	default:
+		err("No MT9M001 chip detected, ID = %x\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) {
@@ -1434,8 +1496,8 @@ static int mt9m001_init_sensor(struct gs
 	}
 	/* disable hflip and vflip */
 	gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | (1 << VFLIP_IDX);
-	sd->hstart = 2;
-	sd->vstart = 2;
+	sd->hstart = 1;
+	sd->vstart = 1;
 	return 0;
 }
 
@@ -1977,6 +2039,10 @@ static int sd_config(struct gspca_dev *g
 		cam->cam_mode = sxga_mode;
 		cam->nmodes = ARRAY_SIZE(sxga_mode);
 		break;
+	case SENSOR_MT9M001:
+		cam->cam_mode = mono_mode;
+		cam->nmodes = ARRAY_SIZE(mono_mode);
+		break;
 	default:
 		cam->cam_mode = vga_mode;
 		cam->nmodes = ARRAY_SIZE(vga_mode);
@@ -2075,7 +2141,6 @@ static int sd_init(struct gspca_dev *gsp
 	case SENSOR_MT9M001:
 		if (mt9m001_init_sensor(gspca_dev) < 0)
 			return -ENODEV;
-		info("MT9M001 sensor detected");
 		break;
 	case SENSOR_HV7131R:
 		if (hv7131r_init_sensor(gspca_dev) < 0)
@@ -2173,22 +2238,22 @@ static int sd_start(struct gspca_dev *gs
 	else if (mode & MODE_JPEG)
 		fmt = 0x2c;
 	else
-		fmt = 0x2f;
+		fmt = 0x2f;	/* YUV 420 */
 
-	switch (mode & 0x0f) {
-	case 3:
+	switch (mode & SCALE_MASK) {
+	case SCALE_1280x1024:
 		scale = 0xc0;
 		info("Set 1280x1024");
 		break;
-	case 2:
+	case SCALE_640x480:
 		scale = 0x80;
 		info("Set 640x480");
 		break;
-	case 1:
+	case SCALE_320x240:
 		scale = 0x90;
 		info("Set 320x240");
 		break;
-	case 0:
+	case SCALE_160x120:
 		scale = 0xa0;
 		info("Set 160x120");
 		break;
@@ -2405,7 +2470,7 @@ static const struct sd_desc sd_desc = {
 			| (SENSOR_ ## sensor << 8) \
 			| (i2c_addr)
 
-static const __devinitdata struct usb_device_id device_table[] = {
+static const struct usb_device_id device_table[] = {
 	{USB_DEVICE(0x0c45, 0x6240), SN9C20X(MT9M001, 0x5d, 0)},
 	{USB_DEVICE(0x0c45, 0x6242), SN9C20X(MT9M111, 0x5d, 0)},
 	{USB_DEVICE(0x0c45, 0x6248), SN9C20X(OV9655, 0x30, 0)},
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/gspca/sonixb.c linux-libre-2.6.38-gnu1/drivers/media/video/gspca/sonixb.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/gspca/sonixb.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/gspca/sonixb.c	2011-03-14 21:20:32.000000000 -0400
@@ -23,8 +23,15 @@
 /* Some documentation on known sonixb registers:
 
 Reg	Use
+sn9c101 / sn9c102:
 0x10	high nibble red gain low nibble blue gain
 0x11	low nibble green gain
+sn9c103:
+0x05	red gain 0-127
+0x06	blue gain 0-127
+0x07	green gain 0-127
+all:
+0x08-0x0f i2c / 3wire registers
 0x12	hstart
 0x13	vstart
 0x15	hsize (hsize = register-value * 16)
@@ -56,6 +63,8 @@ struct sd {
 	int prev_avg_lum;
 	int exp_too_low_cnt;
 	int exp_too_high_cnt;
+	int header_read;
+	u8 header[12]; /* Header without sof marker */
 
 	unsigned short exposure;
 	unsigned char gain;
@@ -71,26 +80,24 @@ struct sd {
 #define BRIDGE_103 1
 
 	__u8 sensor;			/* Type of image sensor chip */
-#define SENSOR_HV7131R 0
-#define SENSOR_OV6650 1
-#define SENSOR_OV7630 2
-#define SENSOR_PAS106 3
-#define SENSOR_PAS202 4
-#define SENSOR_TAS5110C 5
-#define SENSOR_TAS5110D 6
-#define SENSOR_TAS5130CXX 7
+#define SENSOR_HV7131D 0
+#define SENSOR_HV7131R 1
+#define SENSOR_OV6650 2
+#define SENSOR_OV7630 3
+#define SENSOR_PAS106 4
+#define SENSOR_PAS202 5
+#define SENSOR_TAS5110C 6
+#define SENSOR_TAS5110D 7
+#define SENSOR_TAS5130CXX 8
 	__u8 reg11;
 };
 
 typedef const __u8 sensor_init_t[8];
 
 struct sensor_data {
-	const __u8 *bridge_init[2];
-	int bridge_init_size[2];
+	const __u8 *bridge_init;
 	sensor_init_t *sensor_init;
 	int sensor_init_size;
-	sensor_init_t *sensor_bridge_init[2];
-	int sensor_bridge_init_size[2];
 	int flags;
 	unsigned ctrl_dis;
 	__u8 sensor_addr;
@@ -111,7 +118,6 @@ struct sensor_data {
 #define NO_FREQ (1 << FREQ_IDX)
 #define NO_BRIGHTNESS (1 << BRIGHTNESS_IDX)
 
-#define COMP2 0x8f
 #define COMP 0xc7		/* 0x87 //0x07 */
 #define COMP1 0xc9		/* 0x89 //0x09 */
 
@@ -120,15 +126,11 @@ struct sensor_data {
 
 #define SYS_CLK 0x04
 
-#define SENS(bridge_1, bridge_3, sensor, sensor_1, \
-	sensor_3, _flags, _ctrl_dis, _sensor_addr) \
+#define SENS(bridge, sensor, _flags, _ctrl_dis, _sensor_addr) \
 { \
-	.bridge_init = { bridge_1, bridge_3 }, \
-	.bridge_init_size = { sizeof(bridge_1), sizeof(bridge_3) }, \
+	.bridge_init = bridge, \
 	.sensor_init = sensor, \
 	.sensor_init_size = sizeof(sensor), \
-	.sensor_bridge_init = { sensor_1, sensor_3,}, \
-	.sensor_bridge_init_size = { sizeof(sensor_1), sizeof(sensor_3)}, \
 	.flags = _flags, .ctrl_dis = _ctrl_dis, .sensor_addr = _sensor_addr \
 }
 
@@ -303,14 +305,27 @@ static const struct v4l2_pix_format sif_
 		.priv = 0},
 };
 
-static const __u8 initHv7131[] = {
+static const __u8 initHv7131d[] = {
+	0x04, 0x03, 0x00, 0x04, 0x00, 0x00, 0x00, 0x80, 0x11, 0x00, 0x00, 0x00,
+	0x00, 0x00,
+	0x00, 0x00, 0x00, 0x02, 0x02, 0x00,
+	0x28, 0x1e, 0x60, 0x8e, 0x42,
+};
+static const __u8 hv7131d_sensor_init[][8] = {
+	{0xa0, 0x11, 0x01, 0x04, 0x00, 0x00, 0x00, 0x17},
+	{0xa0, 0x11, 0x02, 0x00, 0x00, 0x00, 0x00, 0x17},
+	{0xa0, 0x11, 0x28, 0x00, 0x00, 0x00, 0x00, 0x17},
+	{0xa0, 0x11, 0x30, 0x30, 0x00, 0x00, 0x00, 0x17}, /* reset level */
+	{0xa0, 0x11, 0x34, 0x02, 0x00, 0x00, 0x00, 0x17}, /* pixel bias volt */
+};
+
+static const __u8 initHv7131r[] = {
 	0x46, 0x77, 0x00, 0x04, 0x00, 0x00, 0x00, 0x80, 0x11, 0x00, 0x00, 0x00,
 	0x00, 0x00,
 	0x00, 0x00, 0x00, 0x02, 0x01, 0x00,
 	0x28, 0x1e, 0x60, 0x8a, 0x20,
-	0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c
 };
-static const __u8 hv7131_sensor_init[][8] = {
+static const __u8 hv7131r_sensor_init[][8] = {
 	{0xc0, 0x11, 0x31, 0x38, 0x2a, 0x2e, 0x00, 0x10},
 	{0xa0, 0x11, 0x01, 0x08, 0x2a, 0x2e, 0x00, 0x10},
 	{0xb0, 0x11, 0x20, 0x00, 0xd0, 0x2e, 0x00, 0x10},
@@ -321,7 +336,7 @@ static const __u8 initOv6650[] = {
 	0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
 	0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 	0x00, 0x01, 0x01, 0x0a, 0x16, 0x12, 0x68, 0x8b,
-	0x10, 0x1d, 0x10, 0x02, 0x02, 0x09, 0x07
+	0x10,
 };
 static const __u8 ov6650_sensor_init[][8] = {
 	/* Bright, contrast, etc are set through SCBB interface.
@@ -340,7 +355,7 @@ static const __u8 ov6650_sensor_init[][8
 		 * but blue wont be there. Avoid this data ... */
 	{0xd0, 0x60, 0x26, 0x01, 0x14, 0xd8, 0xa4, 0x10}, /* format out? */
 	{0xd0, 0x60, 0x26, 0x01, 0x14, 0xd8, 0xa4, 0x10},
-	{0xa0, 0x60, 0x30, 0x3d, 0x0A, 0xd8, 0xa4, 0x10},
+	{0xa0, 0x60, 0x30, 0x3d, 0x0a, 0xd8, 0xa4, 0x10},
 	/* Enable rgb brightness control */
 	{0xa0, 0x60, 0x61, 0x08, 0x00, 0x00, 0x00, 0x10},
 	/* HDG: Note windows uses the line below, which sets both register 0x60
@@ -360,24 +375,13 @@ static const __u8 initOv7630[] = {
 	0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	/* r09 .. r10 */
 	0x00, 0x01, 0x01, 0x0a,				/* r11 .. r14 */
 	0x28, 0x1e,			/* H & V sizes     r15 .. r16 */
-	0x68, COMP2, MCK_INIT1,				/* r17 .. r19 */
-	0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c		/* r1a .. r1f */
-};
-static const __u8 initOv7630_3[] = {
-	0x44, 0x44, 0x00, 0x1a, 0x20, 0x20, 0x20, 0x80,	/* r01 .. r08 */
-	0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	/* r09 .. r10 */
-	0x00, 0x02, 0x01, 0x0a,				/* r11 .. r14 */
-	0x28, 0x1e,			/* H & V sizes     r15 .. r16 */
 	0x68, 0x8f, MCK_INIT1,				/* r17 .. r19 */
-	0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c, 0x00,	/* r1a .. r20 */
-	0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, /* r21 .. r28 */
-	0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0, 0xff  /* r29 .. r30 */
 };
 static const __u8 ov7630_sensor_init[][8] = {
 	{0xa0, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10},
 	{0xb0, 0x21, 0x01, 0x77, 0x3a, 0x00, 0x00, 0x10},
 /*	{0xd0, 0x21, 0x12, 0x7c, 0x01, 0x80, 0x34, 0x10},	   jfm */
-	{0xd0, 0x21, 0x12, 0x1c, 0x00, 0x80, 0x34, 0x10},	/* jfm */
+	{0xd0, 0x21, 0x12, 0x5c, 0x00, 0x80, 0x34, 0x10},	/* jfm */
 	{0xa0, 0x21, 0x1b, 0x04, 0x00, 0x80, 0x34, 0x10},
 	{0xa0, 0x21, 0x20, 0x44, 0x00, 0x80, 0x34, 0x10},
 	{0xa0, 0x21, 0x23, 0xee, 0x00, 0x80, 0x34, 0x10},
@@ -395,16 +399,11 @@ static const __u8 ov7630_sensor_init[][8
 	{0xd0, 0x21, 0x17, 0x1c, 0xbd, 0x06, 0xf6, 0x10},
 };
 
-static const __u8 ov7630_sensor_init_3[][8] = {
-	{0xa0, 0x21, 0x13, 0x80, 0x00,	0x00, 0x00, 0x10},
-};
-
 static const __u8 initPas106[] = {
 	0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x40, 0x00, 0x00, 0x00,
 	0x00, 0x00,
 	0x00, 0x00, 0x00, 0x04, 0x01, 0x00,
 	0x16, 0x12, 0x24, COMP1, MCK_INIT1,
-	0x18, 0x10, 0x02, 0x02, 0x09, 0x07
 };
 /* compression 0x86 mckinit1 0x2b */
 
@@ -478,7 +477,6 @@ static const __u8 initPas202[] = {
 	0x00, 0x00,
 	0x00, 0x00, 0x00, 0x06, 0x03, 0x0a,
 	0x28, 0x1e, 0x20, 0x89, 0x20,
-	0x00, 0x00, 0x02, 0x03, 0x0f, 0x0c
 };
 
 /* "Known" PAS202BCB registers:
@@ -505,7 +503,7 @@ static const __u8 pas202_sensor_init[][8
 	{0xa0, 0x40, 0x02, 0x04, 0x00, 0x00, 0x00, 0x10},
 	{0xd0, 0x40, 0x04, 0x07, 0x34, 0x00, 0x09, 0x10},
 	{0xd0, 0x40, 0x08, 0x01, 0x00, 0x00, 0x01, 0x10},
-	{0xd0, 0x40, 0x0C, 0x00, 0x0C, 0x01, 0x32, 0x10},
+	{0xd0, 0x40, 0x0c, 0x00, 0x0c, 0x01, 0x32, 0x10},
 	{0xd0, 0x40, 0x10, 0x00, 0x01, 0x00, 0x63, 0x10},
 	{0xa0, 0x40, 0x15, 0x70, 0x01, 0x00, 0x63, 0x10},
 	{0xa0, 0x40, 0x18, 0x00, 0x01, 0x00, 0x63, 0x10},
@@ -519,7 +517,6 @@ static const __u8 initTas5110c[] = {
 	0x00, 0x00,
 	0x00, 0x00, 0x00, 0x45, 0x09, 0x0a,
 	0x16, 0x12, 0x60, 0x86, 0x2b,
-	0x14, 0x0a, 0x02, 0x02, 0x09, 0x07
 };
 /* Same as above, except a different hstart */
 static const __u8 initTas5110d[] = {
@@ -527,12 +524,19 @@ static const __u8 initTas5110d[] = {
 	0x00, 0x00,
 	0x00, 0x00, 0x00, 0x41, 0x09, 0x0a,
 	0x16, 0x12, 0x60, 0x86, 0x2b,
-	0x14, 0x0a, 0x02, 0x02, 0x09, 0x07
 };
-static const __u8 tas5110_sensor_init[][8] = {
+/* tas5110c is 3 wire, tas5110d is 2 wire (regular i2c) */
+static const __u8 tas5110c_sensor_init[][8] = {
 	{0x30, 0x11, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x10},
 	{0x30, 0x11, 0x02, 0x20, 0xa9, 0x00, 0x00, 0x10},
-	{0xa0, 0x61, 0x9a, 0xca, 0x00, 0x00, 0x00, 0x17},
+};
+/* Known TAS5110D registers
+ * reg02: gain, bit order reversed!! 0 == max gain, 255 == min gain
+ * reg03: bit3: vflip, bit4: ~hflip, bit7: ~gainboost (~ == inverted)
+ *        Note: writing reg03 seems to only work when written together with 02
+ */
+static const __u8 tas5110d_sensor_init[][8] = {
+	{0xa0, 0x61, 0x9a, 0xca, 0x00, 0x00, 0x00, 0x17}, /* reset */
 };
 
 static const __u8 initTas5130[] = {
@@ -540,7 +544,6 @@ static const __u8 initTas5130[] = {
 	0x00, 0x00,
 	0x00, 0x00, 0x00, 0x68, 0x0c, 0x0a,
 	0x28, 0x1e, 0x60, COMP, MCK_INIT,
-	0x18, 0x10, 0x04, 0x03, 0x11, 0x0c
 };
 static const __u8 tas5130_sensor_init[][8] = {
 /*	{0x30, 0x11, 0x00, 0x40, 0x47, 0x00, 0x00, 0x10},
@@ -551,20 +554,18 @@ static const __u8 tas5130_sensor_init[][
 };
 
 static struct sensor_data sensor_data[] = {
-SENS(initHv7131, NULL, hv7131_sensor_init, NULL, NULL, 0, NO_EXPO|NO_FREQ, 0),
-SENS(initOv6650, NULL, ov6650_sensor_init, NULL, NULL, F_GAIN|F_SIF, 0, 0x60),
-SENS(initOv7630, initOv7630_3, ov7630_sensor_init, NULL, ov7630_sensor_init_3,
-	F_GAIN, 0, 0x21),
-SENS(initPas106, NULL, pas106_sensor_init, NULL, NULL, F_GAIN|F_SIF, NO_FREQ,
-	0),
-SENS(initPas202, initPas202, pas202_sensor_init, NULL, NULL, F_GAIN,
-	NO_FREQ, 0),
-SENS(initTas5110c, NULL, tas5110_sensor_init, NULL, NULL,
-	F_GAIN|F_SIF|F_COARSE_EXPO, NO_BRIGHTNESS|NO_FREQ, 0),
-SENS(initTas5110d, NULL, tas5110_sensor_init, NULL, NULL,
-	F_GAIN|F_SIF|F_COARSE_EXPO, NO_BRIGHTNESS|NO_FREQ, 0),
-SENS(initTas5130, NULL, tas5130_sensor_init, NULL, NULL, 0, NO_EXPO|NO_FREQ,
-	0),
+SENS(initHv7131d, hv7131d_sensor_init, F_GAIN, NO_BRIGHTNESS|NO_FREQ, 0),
+SENS(initHv7131r, hv7131r_sensor_init, 0, NO_BRIGHTNESS|NO_EXPO|NO_FREQ, 0),
+SENS(initOv6650, ov6650_sensor_init, F_GAIN|F_SIF, 0, 0x60),
+SENS(initOv7630, ov7630_sensor_init, F_GAIN, 0, 0x21),
+SENS(initPas106, pas106_sensor_init, F_GAIN|F_SIF, NO_FREQ, 0),
+SENS(initPas202, pas202_sensor_init, F_GAIN, NO_FREQ, 0),
+SENS(initTas5110c, tas5110c_sensor_init, F_GAIN|F_SIF|F_COARSE_EXPO,
+	NO_BRIGHTNESS|NO_FREQ, 0),
+SENS(initTas5110d, tas5110d_sensor_init, F_GAIN|F_SIF|F_COARSE_EXPO,
+	NO_BRIGHTNESS|NO_FREQ, 0),
+SENS(initTas5130, tas5130_sensor_init, F_GAIN,
+	NO_BRIGHTNESS|NO_EXPO|NO_FREQ, 0),
 };
 
 /* get one byte in gspca_dev->usb_buf */
@@ -636,7 +637,6 @@ static void i2c_w_vector(struct gspca_de
 static void setbrightness(struct gspca_dev *gspca_dev)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
-	__u8 value;
 
 	switch (sd->sensor) {
 	case  SENSOR_OV6650:
@@ -678,17 +678,6 @@ static void setbrightness(struct gspca_d
 			goto err;
 		break;
 	    }
-	case SENSOR_TAS5130CXX: {
-		__u8 i2c[] =
-			{0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10};
-
-		value = 0xff - sd->brightness;
-		i2c[4] = value;
-		PDEBUG(D_CONF, "brightness %d : %d", value, i2c[4]);
-		if (i2c_w(gspca_dev, i2c) < 0)
-			goto err;
-		break;
-	    }
 	}
 	return;
 err:
@@ -701,9 +690,20 @@ static void setsensorgain(struct gspca_d
 	unsigned char gain = sd->gain;
 
 	switch (sd->sensor) {
+	case SENSOR_HV7131D: {
+		__u8 i2c[] =
+			{0xc0, 0x11, 0x31, 0x00, 0x00, 0x00, 0x00, 0x17};
 
+		i2c[3] = 0x3f - (sd->gain / 4);
+		i2c[4] = 0x3f - (sd->gain / 4);
+		i2c[5] = 0x3f - (sd->gain / 4);
+
+		if (i2c_w(gspca_dev, i2c) < 0)
+			goto err;
+		break;
+	    }
 	case SENSOR_TAS5110C:
-	case SENSOR_TAS5110D: {
+	case SENSOR_TAS5130CXX: {
 		__u8 i2c[] =
 			{0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10};
 
@@ -712,6 +712,23 @@ static void setsensorgain(struct gspca_d
 			goto err;
 		break;
 	    }
+	case SENSOR_TAS5110D: {
+		__u8 i2c[] = {
+			0xb0, 0x61, 0x02, 0x00, 0x10, 0x00, 0x00, 0x17 };
+		gain = 255 - gain;
+		/* The bits in the register are the wrong way around!! */
+		i2c[3] |= (gain & 0x80) >> 7;
+		i2c[3] |= (gain & 0x40) >> 5;
+		i2c[3] |= (gain & 0x20) >> 3;
+		i2c[3] |= (gain & 0x10) >> 1;
+		i2c[3] |= (gain & 0x08) << 1;
+		i2c[3] |= (gain & 0x04) << 3;
+		i2c[3] |= (gain & 0x02) << 5;
+		i2c[3] |= (gain & 0x01) << 7;
+		if (i2c_w(gspca_dev, i2c) < 0)
+			goto err;
+		break;
+	    }
 
 	case SENSOR_OV6650:
 		gain >>= 1;
@@ -766,7 +783,7 @@ static void setgain(struct gspca_dev *gs
 {
 	struct sd *sd = (struct sd *) gspca_dev;
 	__u8 gain;
-	__u8 buf[2] = { 0, 0 };
+	__u8 buf[3] = { 0, 0, 0 };
 
 	if (sensor_data[sd->sensor].flags & F_GAIN) {
 		/* Use the sensor gain to do the actual gain */
@@ -774,13 +791,18 @@ static void setgain(struct gspca_dev *gs
 		return;
 	}
 
-	gain = sd->gain >> 4;
-
-	/* red and blue gain */
-	buf[0] = gain << 4 | gain;
-	/* green gain */
-	buf[1] = gain;
-	reg_w(gspca_dev, 0x10, buf, 2);
+	if (sd->bridge == BRIDGE_103) {
+		gain = sd->gain >> 1;
+		buf[0] = gain; /* Red */
+		buf[1] = gain; /* Green */
+		buf[2] = gain; /* Blue */
+		reg_w(gspca_dev, 0x05, buf, 3);
+	} else {
+		gain = sd->gain >> 4;
+		buf[0] = gain << 4 | gain; /* Red and blue */
+		buf[1] = gain; /* Green */
+		reg_w(gspca_dev, 0x10, buf, 2);
+	}
 }
 
 static void setexposure(struct gspca_dev *gspca_dev)
@@ -788,6 +810,23 @@ static void setexposure(struct gspca_dev
 	struct sd *sd = (struct sd *) gspca_dev;
 
 	switch (sd->sensor) {
+	case SENSOR_HV7131D: {
+		/* Note the datasheet wrongly says line mode exposure uses reg
+		   0x26 and 0x27, testing has shown 0x25 + 0x26 */
+		__u8 i2c[] = {0xc0, 0x11, 0x25, 0x00, 0x00, 0x00, 0x00, 0x17};
+		/* The HV7131D's exposure goes from 0 - 65535, we scale our
+		   exposure of 0-1023 to 0-6138. There are 2 reasons for this:
+		   1) This puts our exposure knee of 200 at approx the point
+		      where the framerate starts dropping
+		   2) At 6138 the framerate has already dropped to 2 fps,
+		      going any lower makes little sense */
+		__u16 reg = sd->exposure * 6;
+		i2c[3] = reg >> 8;
+		i2c[4] = reg & 0xff;
+		if (i2c_w(gspca_dev, i2c) != 0)
+			goto err;
+		break;
+	    }
 	case SENSOR_TAS5110C:
 	case SENSOR_TAS5110D: {
 		/* register 19's high nibble contains the sn9c10x clock divider
@@ -1002,7 +1041,7 @@ static void do_autogain(struct gspca_dev
 		desired_avg_lum = 5000;
 	} else {
 		deadzone = 1500;
-		desired_avg_lum = 18000;
+		desired_avg_lum = 13000;
 	}
 
 	if (sensor_data[sd->sensor].flags & F_COARSE_EXPO)
@@ -1080,53 +1119,91 @@ static int sd_start(struct gspca_dev *gs
 {
 	struct sd *sd = (struct sd *) gspca_dev;
 	struct cam *cam = &gspca_dev->cam;
-	int mode, l;
-	const __u8 *sn9c10x;
-	__u8 reg12_19[8];
+	int i, mode;
+	__u8 regs[0x31];
 
 	mode = cam->cam_mode[gspca_dev->curr_mode].priv & 0x07;
-	sn9c10x = sensor_data[sd->sensor].bridge_init[sd->bridge];
-	l = sensor_data[sd->sensor].bridge_init_size[sd->bridge];
-	memcpy(reg12_19, &sn9c10x[0x12 - 1], 8);
-	reg12_19[6] = sn9c10x[0x18 - 1] | (mode << 4);
-	/* Special cases where reg 17 and or 19 value depends on mode */
+	/* Copy registers 0x01 - 0x19 from the template */
+	memcpy(&regs[0x01], sensor_data[sd->sensor].bridge_init, 0x19);
+	/* Set the mode */
+	regs[0x18] |= mode << 4;
+
+	/* Set bridge gain to 1.0 */
+	if (sd->bridge == BRIDGE_103) {
+		regs[0x05] = 0x20; /* Red */
+		regs[0x06] = 0x20; /* Green */
+		regs[0x07] = 0x20; /* Blue */
+	} else {
+		regs[0x10] = 0x00; /* Red and blue */
+		regs[0x11] = 0x00; /* Green */
+	}
+
+	/* Setup pixel numbers and auto exposure window */
+	if (sensor_data[sd->sensor].flags & F_SIF) {
+		regs[0x1a] = 0x14; /* HO_SIZE 640, makes no sense */
+		regs[0x1b] = 0x0a; /* VO_SIZE 320, makes no sense */
+		regs[0x1c] = 0x02; /* AE H-start 64 */
+		regs[0x1d] = 0x02; /* AE V-start 64 */
+		regs[0x1e] = 0x09; /* AE H-end 288 */
+		regs[0x1f] = 0x07; /* AE V-end 224 */
+	} else {
+		regs[0x1a] = 0x1d; /* HO_SIZE 960, makes no sense */
+		regs[0x1b] = 0x10; /* VO_SIZE 512, makes no sense */
+		regs[0x1c] = 0x05; /* AE H-start 160 */
+		regs[0x1d] = 0x03; /* AE V-start 96 */
+		regs[0x1e] = 0x0f; /* AE H-end 480 */
+		regs[0x1f] = 0x0c; /* AE V-end 384 */
+	}
+
+	/* Setup the gamma table (only used with the sn9c103 bridge) */
+	for (i = 0; i < 16; i++)
+		regs[0x20 + i] = i * 16;
+	regs[0x20 + i] = 255;
+
+	/* Special cases where some regs depend on mode or bridge */
 	switch (sd->sensor) {
 	case SENSOR_TAS5130CXX:
-		/* probably not mode specific at all most likely the upper
+		/* FIXME / TESTME
+		   probably not mode specific at all most likely the upper
 		   nibble of 0x19 is exposure (clock divider) just as with
 		   the tas5110, we need someone to test this. */
-		reg12_19[7] = mode ? 0x23 : 0x43;
+		regs[0x19] = mode ? 0x23 : 0x43;
 		break;
+	case SENSOR_OV7630:
+		/* FIXME / TESTME for some reason with the 101/102 bridge the
+		   clock is set to 12 Mhz (reg1 == 0x04), rather then 24.
+		   Also the hstart needs to go from 1 to 2 when using a 103,
+		   which is likely related. This does not seem right. */
+		if (sd->bridge == BRIDGE_103) {
+			regs[0x01] = 0x44; /* Select 24 Mhz clock */
+			regs[0x12] = 0x02; /* Set hstart to 2 */
+		}
 	}
 	/* Disable compression when the raw bayer format has been selected */
 	if (cam->cam_mode[gspca_dev->curr_mode].priv & MODE_RAW)
-		reg12_19[6] &= ~0x80;
+		regs[0x18] &= ~0x80;
 
 	/* Vga mode emulation on SIF sensor? */
 	if (cam->cam_mode[gspca_dev->curr_mode].priv & MODE_REDUCED_SIF) {
-		reg12_19[0] += 16; /* 0x12: hstart adjust */
-		reg12_19[1] += 24; /* 0x13: vstart adjust */
-		reg12_19[3] = 320 / 16; /* 0x15: hsize */
-		reg12_19[4] = 240 / 16; /* 0x16: vsize */
+		regs[0x12] += 16;	/* hstart adjust */
+		regs[0x13] += 24;	/* vstart adjust */
+		regs[0x15]  = 320 / 16; /* hsize */
+		regs[0x16]  = 240 / 16; /* vsize */
 	}
 
 	/* reg 0x01 bit 2 video transfert on */
-	reg_w(gspca_dev, 0x01, &sn9c10x[0x01 - 1], 1);
+	reg_w(gspca_dev, 0x01, &regs[0x01], 1);
 	/* reg 0x17 SensorClk enable inv Clk 0x60 */
-	reg_w(gspca_dev, 0x17, &sn9c10x[0x17 - 1], 1);
+	reg_w(gspca_dev, 0x17, &regs[0x17], 1);
 	/* Set the registers from the template */
-	reg_w(gspca_dev, 0x01, sn9c10x, l);
+	reg_w(gspca_dev, 0x01, &regs[0x01],
+	      (sd->bridge == BRIDGE_103) ? 0x30 : 0x1f);
 
 	/* Init the sensor */
 	i2c_w_vector(gspca_dev, sensor_data[sd->sensor].sensor_init,
 			sensor_data[sd->sensor].sensor_init_size);
-	if (sensor_data[sd->sensor].sensor_bridge_init[sd->bridge])
-		i2c_w_vector(gspca_dev,
-			sensor_data[sd->sensor].sensor_bridge_init[sd->bridge],
-			sensor_data[sd->sensor].sensor_bridge_init_size[
-				sd->bridge]);
 
-	/* Mode specific sensor setup */
+	/* Mode / bridge specific sensor setup */
 	switch (sd->sensor) {
 	case SENSOR_PAS202: {
 		const __u8 i2cpclockdiv[] =
@@ -1134,27 +1211,37 @@ static int sd_start(struct gspca_dev *gs
 		/* clockdiv from 4 to 3 (7.5 -> 10 fps) when in low res mode */
 		if (mode)
 			i2c_w(gspca_dev, i2cpclockdiv);
+		break;
 	    }
+	case SENSOR_OV7630:
+		/* FIXME / TESTME We should be able to handle this identical
+		   for the 101/102 and the 103 case */
+		if (sd->bridge == BRIDGE_103) {
+			const __u8 i2c[] = { 0xa0, 0x21, 0x13,
+					     0x80, 0x00, 0x00, 0x00, 0x10 };
+			i2c_w(gspca_dev, i2c);
+		}
+		break;
 	}
 	/* H_size V_size 0x28, 0x1e -> 640x480. 0x16, 0x12 -> 352x288 */
-	reg_w(gspca_dev, 0x15, &reg12_19[3], 2);
+	reg_w(gspca_dev, 0x15, &regs[0x15], 2);
 	/* compression register */
-	reg_w(gspca_dev, 0x18, &reg12_19[6], 1);
+	reg_w(gspca_dev, 0x18, &regs[0x18], 1);
 	/* H_start */
-	reg_w(gspca_dev, 0x12, &reg12_19[0], 1);
+	reg_w(gspca_dev, 0x12, &regs[0x12], 1);
 	/* V_START */
-	reg_w(gspca_dev, 0x13, &reg12_19[1], 1);
+	reg_w(gspca_dev, 0x13, &regs[0x13], 1);
 	/* reset 0x17 SensorClk enable inv Clk 0x60 */
 				/*fixme: ov7630 [17]=68 8f (+20 if 102)*/
-	reg_w(gspca_dev, 0x17, &reg12_19[5], 1);
+	reg_w(gspca_dev, 0x17, &regs[0x17], 1);
 	/*MCKSIZE ->3 */	/*fixme: not ov7630*/
-	reg_w(gspca_dev, 0x19, &reg12_19[7], 1);
+	reg_w(gspca_dev, 0x19, &regs[0x19], 1);
 	/* AE_STRX AE_STRY AE_ENDX AE_ENDY */
-	reg_w(gspca_dev, 0x1c, &sn9c10x[0x1c - 1], 4);
+	reg_w(gspca_dev, 0x1c, &regs[0x1c], 4);
 	/* Enable video transfert */
-	reg_w(gspca_dev, 0x01, &sn9c10x[0], 1);
+	reg_w(gspca_dev, 0x01, &regs[0x01], 1);
 	/* Compression */
-	reg_w(gspca_dev, 0x18, &reg12_19[6], 2);
+	reg_w(gspca_dev, 0x18, &regs[0x18], 2);
 	msleep(20);
 
 	sd->reg11 = -1;
@@ -1177,13 +1264,10 @@ static void sd_stopN(struct gspca_dev *g
 	sd_init(gspca_dev);
 }
 
-static void sd_pkt_scan(struct gspca_dev *gspca_dev,
-			u8 *data,			/* isoc packet */
-			int len)			/* iso packet length */
+static u8* find_sof(struct gspca_dev *gspca_dev, u8 *data, int len)
 {
-	int i;
 	struct sd *sd = (struct sd *) gspca_dev;
-	struct cam *cam = &gspca_dev->cam;
+	int i, header_size = (sd->bridge == BRIDGE_103) ? 18 : 12;
 
 	/* frames start with:
 	 *	ff ff 00 c4 c4 96	synchro
@@ -1194,57 +1278,83 @@ static void sd_pkt_scan(struct gspca_dev
 	 *	ll mm		brightness sum outside auto exposure
 	 *	(xx xx xx xx xx)	audio values for snc103
 	 */
-	if (len > 6 && len < 24) {
-		for (i = 0; i < len - 6; i++) {
-			if (data[0 + i] == 0xff
-			    && data[1 + i] == 0xff
-			    && data[2 + i] == 0x00
-			    && data[3 + i] == 0xc4
-			    && data[4 + i] == 0xc4
-			    && data[5 + i] == 0x96) {	/* start of frame */
-				int lum = -1;
-				int pkt_type = LAST_PACKET;
-				int fr_h_sz = (sd->bridge == BRIDGE_103) ?
-					18 : 12;
-
-				if (len - i < fr_h_sz) {
-					PDEBUG(D_STREAM, "packet too short to"
-						" get avg brightness");
-				} else if (sd->bridge == BRIDGE_103) {
-					lum = data[i + 9] +
-						(data[i + 10] << 8);
-				} else {
-					lum = data[i + 8] + (data[i + 9] << 8);
-				}
-				/* When exposure changes midway a frame we
-				   get a lum of 0 in this case drop 2 frames
-				   as the frames directly after an exposure
-				   change have an unstable image. Sometimes lum
-				   *really* is 0 (cam used in low light with
-				   low exposure setting), so do not drop frames
-				   if the previous lum was 0 too. */
-				if (lum == 0 && sd->prev_avg_lum != 0) {
-					lum = -1;
-					sd->frames_to_drop = 2;
-					sd->prev_avg_lum = 0;
-				} else
-					sd->prev_avg_lum = lum;
-				atomic_set(&sd->avg_lum, lum);
+	for (i = 0; i < len; i++) {
+		switch (sd->header_read) {
+		case 0:
+			if (data[i] == 0xff)
+				sd->header_read++;
+			break;
+		case 1:
+			if (data[i] == 0xff)
+				sd->header_read++;
+			else
+				sd->header_read = 0;
+			break;
+		case 2:
+			if (data[i] == 0x00)
+				sd->header_read++;
+			else if (data[i] != 0xff)
+				sd->header_read = 0;
+			break;
+		case 3:
+			if (data[i] == 0xc4)
+				sd->header_read++;
+			else if (data[i] == 0xff)
+				sd->header_read = 1;
+			else
+				sd->header_read = 0;
+			break;
+		case 4:
+			if (data[i] == 0xc4)
+				sd->header_read++;
+			else if (data[i] == 0xff)
+				sd->header_read = 1;
+			else
+				sd->header_read = 0;
+			break;
+		case 5:
+			if (data[i] == 0x96)
+				sd->header_read++;
+			else if (data[i] == 0xff)
+				sd->header_read = 1;
+			else
+				sd->header_read = 0;
+			break;
+		default:
+			sd->header[sd->header_read - 6] = data[i];
+			sd->header_read++;
+			if (sd->header_read == header_size) {
+				sd->header_read = 0;
+				return data + i + 1;
+			}
+		}
+	}
+	return NULL;
+}
 
-				if (sd->frames_to_drop) {
-					sd->frames_to_drop--;
-					pkt_type = DISCARD_PACKET;
-				}
+static void sd_pkt_scan(struct gspca_dev *gspca_dev,
+			u8 *data,			/* isoc packet */
+			int len)			/* iso packet length */
+{
+	int fr_h_sz = 0, lum_offset = 0, len_after_sof = 0;
+	struct sd *sd = (struct sd *) gspca_dev;
+	struct cam *cam = &gspca_dev->cam;
+	u8 *sof;
 
-				gspca_frame_add(gspca_dev, pkt_type,
-						NULL, 0);
-				data += i + fr_h_sz;
-				len -= i + fr_h_sz;
-				gspca_frame_add(gspca_dev, FIRST_PACKET,
-						data, len);
-				return;
-			}
+	sof = find_sof(gspca_dev, data, len);
+	if (sof) {
+		if (sd->bridge == BRIDGE_103) {
+			fr_h_sz = 18;
+			lum_offset = 3;
+		} else {
+			fr_h_sz = 12;
+			lum_offset = 2;
 		}
+
+		len_after_sof = len - (sof - data);
+		len = (sof - data) - fr_h_sz;
+		if (len < 0)
+			len = 0;
 	}
 
 	if (cam->cam_mode[gspca_dev->curr_mode].priv & MODE_RAW) {
@@ -1259,6 +1369,33 @@ static void sd_pkt_scan(struct gspca_dev
 	}
 
 	gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
+
+	if (sof) {
+		int  lum = sd->header[lum_offset] +
+			  (sd->header[lum_offset + 1] << 8);
+
+		/* When exposure changes midway a frame we
+		   get a lum of 0 in this case drop 2 frames
+		   as the frames directly after an exposure
+		   change have an unstable image. Sometimes lum
+		   *really* is 0 (cam used in low light with
+		   low exposure setting), so do not drop frames
+		   if the previous lum was 0 too. */
+		if (lum == 0 && sd->prev_avg_lum != 0) {
+			lum = -1;
+			sd->frames_to_drop = 2;
+			sd->prev_avg_lum = 0;
+		} else
+			sd->prev_avg_lum = lum;
+		atomic_set(&sd->avg_lum, lum);
+
+		if (sd->frames_to_drop)
+			sd->frames_to_drop--;
+		else
+			gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
+
+		gspca_frame_add(gspca_dev, FIRST_PACKET, sof, len_after_sof);
+	}
 }
 
 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
@@ -1428,36 +1565,41 @@ static const struct sd_desc sd_desc = {
 	.driver_info = (SENSOR_ ## sensor << 8) | BRIDGE_ ## bridge
 
 
-static const struct usb_device_id device_table[] __devinitconst = {
+static const struct usb_device_id device_table[] = {
 	{USB_DEVICE(0x0c45, 0x6001), SB(TAS5110C, 102)}, /* TAS5110C1B */
 	{USB_DEVICE(0x0c45, 0x6005), SB(TAS5110C, 101)}, /* TAS5110C1B */
-#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
 	{USB_DEVICE(0x0c45, 0x6007), SB(TAS5110D, 101)}, /* TAS5110D */
-#endif
 	{USB_DEVICE(0x0c45, 0x6009), SB(PAS106, 101)},
 	{USB_DEVICE(0x0c45, 0x600d), SB(PAS106, 101)},
 	{USB_DEVICE(0x0c45, 0x6011), SB(OV6650, 101)},
-#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
 	{USB_DEVICE(0x0c45, 0x6019), SB(OV7630, 101)},
+#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
 	{USB_DEVICE(0x0c45, 0x6024), SB(TAS5130CXX, 102)},
 	{USB_DEVICE(0x0c45, 0x6025), SB(TAS5130CXX, 102)},
 #endif
 	{USB_DEVICE(0x0c45, 0x6028), SB(PAS202, 102)},
 	{USB_DEVICE(0x0c45, 0x6029), SB(PAS106, 102)},
+	{USB_DEVICE(0x0c45, 0x602a), SB(HV7131D, 102)},
+	/* {USB_DEVICE(0x0c45, 0x602b), SB(MI0343, 102)}, */
 	{USB_DEVICE(0x0c45, 0x602c), SB(OV7630, 102)},
 	{USB_DEVICE(0x0c45, 0x602d), SB(HV7131R, 102)},
 	{USB_DEVICE(0x0c45, 0x602e), SB(OV7630, 102)},
+	/* {USB_DEVICE(0x0c45, 0x6030), SB(MI03XX, 102)}, */ /* MI0343 MI0360 MI0330 */
+	/* {USB_DEVICE(0x0c45, 0x6082), SB(MI03XX, 103)}, */ /* MI0343 MI0360 */
+	{USB_DEVICE(0x0c45, 0x6083), SB(HV7131D, 103)},
+	{USB_DEVICE(0x0c45, 0x608c), SB(HV7131R, 103)},
+	/* {USB_DEVICE(0x0c45, 0x608e), SB(CISVF10, 103)}, */
 	{USB_DEVICE(0x0c45, 0x608f), SB(OV7630, 103)},
-#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
+	{USB_DEVICE(0x0c45, 0x60a8), SB(PAS106, 103)},
+	{USB_DEVICE(0x0c45, 0x60aa), SB(TAS5130CXX, 103)},
 	{USB_DEVICE(0x0c45, 0x60af), SB(PAS202, 103)},
-#endif
 	{USB_DEVICE(0x0c45, 0x60b0), SB(OV7630, 103)},
 	{}
 };
 MODULE_DEVICE_TABLE(usb, device_table);
 
 /* -- device connect -- */
-static int __devinit sd_probe(struct usb_interface *intf,
+static int sd_probe(struct usb_interface *intf,
 			const struct usb_device_id *id)
 {
 	return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/gspca/sonixj.c linux-libre-2.6.38-gnu1/drivers/media/video/gspca/sonixj.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/gspca/sonixj.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/gspca/sonixj.c	2011-03-14 21:20:32.000000000 -0400
@@ -25,12 +25,12 @@
 #include "gspca.h"
 #include "jpeg.h"
 
-#define V4L2_CID_INFRARED (V4L2_CID_PRIVATE_BASE + 0)
-
 MODULE_AUTHOR("Jean-François Moine <http://moinejf.free.fr>");
 MODULE_DESCRIPTION("GSPCA/SONIX JPEG USB Camera Driver");
 MODULE_LICENSE("GPL");
 
+static int starcam;
+
 /* controls */
 enum e_ctrl {
 	BRIGHTNESS,
@@ -43,7 +43,7 @@ enum e_ctrl {
 	HFLIP,
 	VFLIP,
 	SHARPNESS,
-	INFRARED,
+	ILLUM,
 	FREQ,
 	NCTRLS		/* number of controls */
 };
@@ -100,7 +100,8 @@ enum sensors {
 };
 
 /* device flags */
-#define PDN_INV	1		/* inverse pin S_PWR_DN / sn_xxx tables */
+#define F_PDN_INV	0x01	/* inverse pin S_PWR_DN / sn_xxx tables */
+#define F_ILLUM		0x02	/* presence of illuminator */
 
 /* sn9c1xx definitions */
 /* register 0x01 */
@@ -124,7 +125,7 @@ static void setgamma(struct gspca_dev *g
 static void setautogain(struct gspca_dev *gspca_dev);
 static void sethvflip(struct gspca_dev *gspca_dev);
 static void setsharpness(struct gspca_dev *gspca_dev);
-static void setinfrared(struct gspca_dev *gspca_dev);
+static void setillum(struct gspca_dev *gspca_dev);
 static void setfreq(struct gspca_dev *gspca_dev);
 
 static const struct ctrl sd_ctrls[NCTRLS] = {
@@ -251,18 +252,17 @@ static const struct ctrl sd_ctrls[NCTRLS
 	    },
 	    .set_control = setsharpness
 	},
-/* mt9v111 only */
-[INFRARED] = {
+[ILLUM] = {
 	    {
-		.id      = V4L2_CID_INFRARED,
+		.id      = V4L2_CID_ILLUMINATORS_1,
 		.type    = V4L2_CTRL_TYPE_BOOLEAN,
-		.name    = "Infrared",
+		.name    = "Illuminator / infrared",
 		.minimum = 0,
 		.maximum = 1,
 		.step    = 1,
 		.default_value = 0,
 	    },
-	    .set_control = setinfrared
+	    .set_control = setillum
 	},
 /* ov7630/ov7648/ov7660 only */
 [FREQ] = {
@@ -282,32 +282,26 @@ static const struct ctrl sd_ctrls[NCTRLS
 /* table of the disabled controls */
 static const __u32 ctrl_dis[] = {
 [SENSOR_ADCM1700] =	(1 << AUTOGAIN) |
-			(1 << INFRARED) |
 			(1 << HFLIP) |
 			(1 << VFLIP) |
 			(1 << FREQ),
 
-[SENSOR_GC0307] =	(1 << INFRARED) |
-			(1 << HFLIP) |
+[SENSOR_GC0307] =	(1 << HFLIP) |
 			(1 << VFLIP) |
 			(1 << FREQ),
 
-[SENSOR_HV7131R] =	(1 << INFRARED) |
-			(1 << HFLIP) |
+[SENSOR_HV7131R] =	(1 << HFLIP) |
 			(1 << FREQ),
 
-[SENSOR_MI0360] =	(1 << INFRARED) |
-			(1 << HFLIP) |
+[SENSOR_MI0360] =	(1 << HFLIP) |
 			(1 << VFLIP) |
 			(1 << FREQ),
 
-[SENSOR_MI0360B] =	(1 << INFRARED) |
-			(1 << HFLIP) |
+[SENSOR_MI0360B] =	(1 << HFLIP) |
 			(1 << VFLIP) |
 			(1 << FREQ),
 
-[SENSOR_MO4000] =	(1 << INFRARED) |
-			(1 << HFLIP) |
+[SENSOR_MO4000] =	(1 << HFLIP) |
 			(1 << VFLIP) |
 			(1 << FREQ),
 
@@ -315,40 +309,32 @@ static const __u32 ctrl_dis[] = {
 			(1 << VFLIP) |
 			(1 << FREQ),
 
-[SENSOR_OM6802] =	(1 << INFRARED) |
-			(1 << HFLIP) |
+[SENSOR_OM6802] =	(1 << HFLIP) |
 			(1 << VFLIP) |
 			(1 << FREQ),
 
-[SENSOR_OV7630] =	(1 << INFRARED) |
-			(1 << HFLIP),
+[SENSOR_OV7630] =	(1 << HFLIP),
 
-[SENSOR_OV7648] =	(1 << INFRARED) |
-			(1 << HFLIP),
+[SENSOR_OV7648] =	(1 << HFLIP),
 
 [SENSOR_OV7660] =	(1 << AUTOGAIN) |
-			(1 << INFRARED) |
 			(1 << HFLIP) |
 			(1 << VFLIP),
 
 [SENSOR_PO1030] =	(1 << AUTOGAIN) |
-			(1 << INFRARED) |
 			(1 << HFLIP) |
 			(1 << VFLIP) |
 			(1 << FREQ),
 
 [SENSOR_PO2030N] =	(1 << AUTOGAIN) |
-			(1 << INFRARED) |
 			(1 << FREQ),
 
 [SENSOR_SOI768] =	(1 << AUTOGAIN) |
-			(1 << INFRARED) |
 			(1 << HFLIP) |
 			(1 << VFLIP) |
 			(1 << FREQ),
 
 [SENSOR_SP80708] =	(1 << AUTOGAIN) |
-			(1 << INFRARED) |
 			(1 << HFLIP) |
 			(1 << VFLIP) |
 			(1 << FREQ),
@@ -1598,22 +1584,22 @@ static void i2c_w_seq(struct gspca_dev *
 	}
 }
 
+/* check the ID of the hv7131 sensor */
+/* this sequence is needed because it activates the sensor */
 static void hv7131r_probe(struct gspca_dev *gspca_dev)
 {
-	i2c_w1(gspca_dev, 0x02, 0);			/* sensor wakeup */
+	i2c_w1(gspca_dev, 0x02, 0);		/* sensor wakeup */
 	msleep(10);
-	reg_w1(gspca_dev, 0x02, 0x66);			/* Gpio on */
+	reg_w1(gspca_dev, 0x02, 0x66);		/* Gpio on */
 	msleep(10);
-	i2c_r(gspca_dev, 0, 5);				/* read sensor id */
-	if (gspca_dev->usb_buf[0] == 0x02
+	i2c_r(gspca_dev, 0, 5);			/* read sensor id */
+	if (gspca_dev->usb_buf[0] == 0x02	/* chip ID (02 is R) */
 	    && gspca_dev->usb_buf[1] == 0x09
-	    && gspca_dev->usb_buf[2] == 0x01
-	    && gspca_dev->usb_buf[3] == 0x00
-	    && gspca_dev->usb_buf[4] == 0x00) {
-		PDEBUG(D_PROBE, "Sensor sn9c102P HV7131R found");
+	    && gspca_dev->usb_buf[2] == 0x01) {
+		PDEBUG(D_PROBE, "Sensor HV7131R found");
 		return;
 	}
-	PDEBUG(D_PROBE, "Sensor 0x%02x 0x%02x 0x%02x - sn9c102P not found",
+	warn("Erroneous HV7131R ID 0x%02x 0x%02x 0x%02x",
 		gspca_dev->usb_buf[0], gspca_dev->usb_buf[1],
 		gspca_dev->usb_buf[2]);
 }
@@ -1822,44 +1808,46 @@ static int sd_init(struct gspca_dev *gsp
 	PDEBUG(D_PROBE, "Sonix chip id: %02x", regF1);
 	switch (sd->bridge) {
 	case BRIDGE_SN9C102P:
+	case BRIDGE_SN9C105:
 		if (regF1 != 0x11)
 			return -ENODEV;
+		break;
+	default:
+/*	case BRIDGE_SN9C110: */
+/*	case BRIDGE_SN9C120: */
+		if (regF1 != 0x12)
+			return -ENODEV;
+	}
+
+	switch (sd->sensor) {
+	case SENSOR_MI0360:
+		mi0360_probe(gspca_dev);
+		break;
+	case SENSOR_OV7630:
+		ov7630_probe(gspca_dev);
+		break;
+	case SENSOR_OV7648:
+		ov7648_probe(gspca_dev);
+		break;
+	case SENSOR_PO2030N:
+		po2030n_probe(gspca_dev);
+		break;
+	}
+
+	switch (sd->bridge) {
+	case BRIDGE_SN9C102P:
 		reg_w1(gspca_dev, 0x02, regGpio[1]);
 		break;
 	case BRIDGE_SN9C105:
-		if (regF1 != 0x11)
-			return -ENODEV;
-		if (sd->sensor == SENSOR_MI0360)
-			mi0360_probe(gspca_dev);
 		reg_w(gspca_dev, 0x01, regGpio, 2);
 		break;
+	case BRIDGE_SN9C110:
+		reg_w1(gspca_dev, 0x02, 0x62);
+		break;
 	case BRIDGE_SN9C120:
-		if (regF1 != 0x12)
-			return -ENODEV;
-		switch (sd->sensor) {
-		case SENSOR_MI0360:
-			mi0360_probe(gspca_dev);
-			break;
-		case SENSOR_OV7630:
-			ov7630_probe(gspca_dev);
-			break;
-		case SENSOR_OV7648:
-			ov7648_probe(gspca_dev);
-			break;
-		case SENSOR_PO2030N:
-			po2030n_probe(gspca_dev);
-			break;
-		}
 		regGpio[1] = 0x70;		/* no audio */
 		reg_w(gspca_dev, 0x01, regGpio, 2);
 		break;
-	default:
-/*	case BRIDGE_SN9C110: */
-/*	case BRIDGE_SN9C325: */
-		if (regF1 != 0x12)
-			return -ENODEV;
-		reg_w1(gspca_dev, 0x02, 0x62);
-		break;
 	}
 
 	if (sd->sensor == SENSOR_OM6802)
@@ -1874,6 +1862,8 @@ static int sd_init(struct gspca_dev *gsp
 	sd->i2c_addr = sn9c1xx[9];
 
 	gspca_dev->ctrl_dis = ctrl_dis[sd->sensor];
+	if (!(sd->flags & F_ILLUM))
+		gspca_dev->ctrl_dis |= (1 << ILLUM);
 
 	return gspca_dev->usb_err;
 }
@@ -2197,16 +2187,28 @@ static void setsharpness(struct gspca_de
 	reg_w1(gspca_dev, 0x99, sd->ctrls[SHARPNESS].val);
 }
 
-static void setinfrared(struct gspca_dev *gspca_dev)
+static void setillum(struct gspca_dev *gspca_dev)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
 
-	if (gspca_dev->ctrl_dis & (1 << INFRARED))
+	if (gspca_dev->ctrl_dis & (1 << ILLUM))
 		return;
-/*fixme: different sequence for StarCam Clip and StarCam 370i */
-/* Clip */
-	i2c_w1(gspca_dev, 0x02,				/* gpio */
-		sd->ctrls[INFRARED].val ? 0x66 : 0x64);
+	switch (sd->sensor) {
+	case SENSOR_ADCM1700:
+		reg_w1(gspca_dev, 0x02,				/* gpio */
+			sd->ctrls[ILLUM].val ? 0x64 : 0x60);
+		break;
+	case SENSOR_MT9V111:
+		if (starcam)
+			reg_w1(gspca_dev, 0x02,
+				sd->ctrls[ILLUM].val ?
+						0x55 : 0x54);	/* 370i */
+		else
+			reg_w1(gspca_dev, 0x02,
+				sd->ctrls[ILLUM].val ?
+						0x66 : 0x64);	/* Clip */
+		break;
+	}
 }
 
 static void setfreq(struct gspca_dev *gspca_dev)
@@ -2344,7 +2346,7 @@ static int sd_start(struct gspca_dev *gs
 	/* sensor clock already enabled in sd_init */
 	/* reg_w1(gspca_dev, 0xf1, 0x00); */
 	reg01 = sn9c1xx[1];
-	if (sd->flags & PDN_INV)
+	if (sd->flags & F_PDN_INV)
 		reg01 ^= S_PDN_INV;		/* power down inverted */
 	reg_w1(gspca_dev, 0x01, reg01);
 
@@ -2533,7 +2535,7 @@ static int sd_start(struct gspca_dev *gs
 		init = om6802_sensor_param1;
 		if (!mode) {			/* if 640x480 */
 			reg17 &= ~MCK_SIZE_MASK;
-			reg17 |= 0x01;		/* clock / 4 */
+			reg17 |= 0x04;		/* clock / 4 */
 		}
 		break;
 	case SENSOR_OV7630:
@@ -2907,13 +2909,11 @@ static const struct sd_desc sd_desc = {
 	.driver_info = (BRIDGE_ ## bridge << 16) \
 			| (SENSOR_ ## sensor << 8) \
 			| (flags)
-static const __devinitdata struct usb_device_id device_table[] = {
-#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
+static const struct usb_device_id device_table[] = {
 	{USB_DEVICE(0x0458, 0x7025), BS(SN9C120, MI0360)},
 	{USB_DEVICE(0x0458, 0x702e), BS(SN9C120, OV7660)},
-#endif
-	{USB_DEVICE(0x045e, 0x00f5), BSF(SN9C105, OV7660, PDN_INV)},
-	{USB_DEVICE(0x045e, 0x00f7), BSF(SN9C105, OV7660, PDN_INV)},
+	{USB_DEVICE(0x045e, 0x00f5), BSF(SN9C105, OV7660, F_PDN_INV)},
+	{USB_DEVICE(0x045e, 0x00f7), BSF(SN9C105, OV7660, F_PDN_INV)},
 	{USB_DEVICE(0x0471, 0x0327), BS(SN9C105, MI0360)},
 	{USB_DEVICE(0x0471, 0x0328), BS(SN9C105, MI0360)},
 	{USB_DEVICE(0x0471, 0x0330), BS(SN9C105, MI0360)},
@@ -2925,7 +2925,7 @@ static const __devinitdata struct usb_de
 /*	{USB_DEVICE(0x0c45, 0x607b), BS(SN9C102P, OV7660)}, */
 	{USB_DEVICE(0x0c45, 0x607c), BS(SN9C102P, HV7131R)},
 /*	{USB_DEVICE(0x0c45, 0x607e), BS(SN9C102P, OV7630)}, */
-	{USB_DEVICE(0x0c45, 0x60c0), BS(SN9C105, MI0360)},
+	{USB_DEVICE(0x0c45, 0x60c0), BSF(SN9C105, MI0360, F_ILLUM)},
 						/* or MT9V111 */
 /*	{USB_DEVICE(0x0c45, 0x60c2), BS(SN9C105, P1030xC)}, */
 /*	{USB_DEVICE(0x0c45, 0x60c8), BS(SN9C105, OM6802)}, */
@@ -2936,10 +2936,8 @@ static const __devinitdata struct usb_de
 /*	{USB_DEVICE(0x0c45, 0x60fa), BS(SN9C105, OV7648)}, */
 /*	{USB_DEVICE(0x0c45, 0x60f2), BS(SN9C105, OV7660)}, */
 	{USB_DEVICE(0x0c45, 0x60fb), BS(SN9C105, OV7660)},
-#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
 	{USB_DEVICE(0x0c45, 0x60fc), BS(SN9C105, HV7131R)},
 	{USB_DEVICE(0x0c45, 0x60fe), BS(SN9C105, OV7630)},
-#endif
 	{USB_DEVICE(0x0c45, 0x6100), BS(SN9C120, MI0360)},	/*sn9c128*/
 	{USB_DEVICE(0x0c45, 0x6102), BS(SN9C120, PO2030N)},	/* /GC0305*/
 /*	{USB_DEVICE(0x0c45, 0x6108), BS(SN9C120, OM6802)}, */
@@ -2962,16 +2960,15 @@ static const __devinitdata struct usb_de
 /*	{USB_DEVICE(0x0c45, 0x6132), BS(SN9C120, OV7670)}, */
 	{USB_DEVICE(0x0c45, 0x6138), BS(SN9C120, MO4000)},
 	{USB_DEVICE(0x0c45, 0x613a), BS(SN9C120, OV7648)},
-#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
 	{USB_DEVICE(0x0c45, 0x613b), BS(SN9C120, OV7660)},
-#endif
 	{USB_DEVICE(0x0c45, 0x613c), BS(SN9C120, HV7131R)},
 	{USB_DEVICE(0x0c45, 0x613e), BS(SN9C120, OV7630)},
 	{USB_DEVICE(0x0c45, 0x6142), BS(SN9C120, PO2030N)},	/*sn9c120b*/
 						/* or GC0305 / GC0307 */
 	{USB_DEVICE(0x0c45, 0x6143), BS(SN9C120, SP80708)},	/*sn9c120b*/
 	{USB_DEVICE(0x0c45, 0x6148), BS(SN9C120, OM6802)},	/*sn9c120b*/
-	{USB_DEVICE(0x0c45, 0x614a), BS(SN9C120, ADCM1700)},	/*sn9c120b*/
+	{USB_DEVICE(0x0c45, 0x614a), BSF(SN9C120, ADCM1700, F_ILLUM)},
+/*	{USB_DEVICE(0x0c45, 0x614c), BS(SN9C120, GC0306)}, */	/*sn9c120b*/
 	{}
 };
 MODULE_DEVICE_TABLE(usb, device_table);
@@ -3007,3 +3004,7 @@ static void __exit sd_mod_exit(void)
 
 module_init(sd_mod_init);
 module_exit(sd_mod_exit);
+
+module_param(starcam, int, 0644);
+MODULE_PARM_DESC(starcam,
+	"StarCam model. 0: Clip, 1: 370i");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/gspca/spca1528.c linux-libre-2.6.38-gnu1/drivers/media/video/gspca/spca1528.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/gspca/spca1528.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/gspca/spca1528.c	2011-03-14 21:20:32.000000000 -0400
@@ -555,7 +555,7 @@ static const struct sd_desc sd_desc = {
 };
 
 /* -- module initialisation -- */
-static const __devinitdata struct usb_device_id device_table[] = {
+static const struct usb_device_id device_table[] = {
 	{USB_DEVICE(0x04fc, 0x1528)},
 	{}
 };
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/gspca/spca500.c linux-libre-2.6.38-gnu1/drivers/media/video/gspca/spca500.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/gspca/spca500.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/gspca/spca500.c	2011-03-14 21:20:32.000000000 -0400
@@ -1051,7 +1051,7 @@ static const struct sd_desc sd_desc = {
 };
 
 /* -- module initialisation -- */
-static const __devinitdata struct usb_device_id device_table[] = {
+static const struct usb_device_id device_table[] = {
 	{USB_DEVICE(0x040a, 0x0300), .driver_info = KodakEZ200},
 	{USB_DEVICE(0x041e, 0x400a), .driver_info = CreativePCCam300},
 	{USB_DEVICE(0x046d, 0x0890), .driver_info = LogitechTraveler},
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/gspca/spca501.c linux-libre-2.6.38-gnu1/drivers/media/video/gspca/spca501.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/gspca/spca501.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/gspca/spca501.c	2011-03-14 21:20:32.000000000 -0400
@@ -2155,7 +2155,7 @@ static const struct sd_desc sd_desc = {
 };
 
 /* -- module initialisation -- */
-static const __devinitdata struct usb_device_id device_table[] = {
+static const struct usb_device_id device_table[] = {
 	{USB_DEVICE(0x040a, 0x0002), .driver_info = KodakDVC325},
 	{USB_DEVICE(0x0497, 0xc001), .driver_info = SmileIntlCamera},
 	{USB_DEVICE(0x0506, 0x00df), .driver_info = ThreeComHomeConnectLite},
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/gspca/spca505.c linux-libre-2.6.38-gnu1/drivers/media/video/gspca/spca505.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/gspca/spca505.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/gspca/spca505.c	2011-03-14 21:20:32.000000000 -0400
@@ -786,7 +786,7 @@ static const struct sd_desc sd_desc = {
 };
 
 /* -- module initialisation -- */
-static const __devinitdata struct usb_device_id device_table[] = {
+static const struct usb_device_id device_table[] = {
 	{USB_DEVICE(0x041e, 0x401d), .driver_info = Nxultra},
 	{USB_DEVICE(0x0733, 0x0430), .driver_info = IntelPCCameraPro},
 /*fixme: may be UsbGrabberPV321 BRIDGE_SPCA506 SENSOR_SAA7113 */
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/gspca/spca508.c linux-libre-2.6.38-gnu1/drivers/media/video/gspca/spca508.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/gspca/spca508.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/gspca/spca508.c	2011-03-14 21:20:32.000000000 -0400
@@ -1509,7 +1509,7 @@ static const struct sd_desc sd_desc = {
 };
 
 /* -- module initialisation -- */
-static const __devinitdata struct usb_device_id device_table[] = {
+static const struct usb_device_id device_table[] = {
 	{USB_DEVICE(0x0130, 0x0130), .driver_info = HamaUSBSightcam},
 	{USB_DEVICE(0x041e, 0x4018), .driver_info = CreativeVista},
 	{USB_DEVICE(0x0733, 0x0110), .driver_info = ViewQuestVQ110},
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/gspca/spca561.c linux-libre-2.6.38-gnu1/drivers/media/video/gspca/spca561.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/gspca/spca561.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/gspca/spca561.c	2011-03-14 21:20:32.000000000 -0400
@@ -597,7 +597,7 @@ static void setgain(struct gspca_dev *gs
 	else if (sd->gain < 128)
 		gspca_dev->usb_buf[0] = (sd->gain / 2) | 0x40;
 	else
-		gspca_dev->usb_buf[0] = (sd->gain / 4) | 0xC0;
+		gspca_dev->usb_buf[0] = (sd->gain / 4) | 0xc0;
 
 	gspca_dev->usb_buf[1] = 0;
 	reg_w_buf(gspca_dev, 0x8335, 2);
@@ -1061,7 +1061,7 @@ static const struct sd_desc *sd_desc[2]
 };
 
 /* -- module initialisation -- */
-static const __devinitdata struct usb_device_id device_table[] = {
+static const struct usb_device_id device_table[] = {
 	{USB_DEVICE(0x041e, 0x401a), .driver_info = Rev072A},
 	{USB_DEVICE(0x041e, 0x403b), .driver_info = Rev012A},
 	{USB_DEVICE(0x0458, 0x7004), .driver_info = Rev072A},
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/gspca/sq905.c linux-libre-2.6.38-gnu1/drivers/media/video/gspca/sq905.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/gspca/sq905.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/gspca/sq905.c	2011-03-14 21:20:32.000000000 -0400
@@ -396,7 +396,7 @@ static int sd_start(struct gspca_dev *gs
 }
 
 /* Table of supported USB devices */
-static const __devinitdata struct usb_device_id device_table[] = {
+static const struct usb_device_id device_table[] = {
 	{USB_DEVICE(0x2770, 0x9120)},
 	{}
 };
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/gspca/sq905c.c linux-libre-2.6.38-gnu1/drivers/media/video/gspca/sq905c.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/gspca/sq905c.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/gspca/sq905c.c	2011-03-14 21:20:32.000000000 -0400
@@ -298,9 +298,10 @@ static int sd_start(struct gspca_dev *gs
 }
 
 /* Table of supported USB devices */
-static const __devinitdata struct usb_device_id device_table[] = {
+static const struct usb_device_id device_table[] = {
 	{USB_DEVICE(0x2770, 0x905c)},
 	{USB_DEVICE(0x2770, 0x9050)},
+	{USB_DEVICE(0x2770, 0x9051)},
 	{USB_DEVICE(0x2770, 0x9052)},
 	{USB_DEVICE(0x2770, 0x913d)},
 	{}
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/gspca/sq930x.c linux-libre-2.6.38-gnu1/drivers/media/video/gspca/sq930x.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/gspca/sq930x.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/gspca/sq930x.c	2011-03-14 21:20:32.000000000 -0400
@@ -687,10 +687,19 @@ static void cmos_probe(struct gspca_dev
 		if (gspca_dev->usb_buf[0] != 0)
 			break;
 	}
-	if (i >= ARRAY_SIZE(probe_order))
+	if (i >= ARRAY_SIZE(probe_order)) {
 		err("Unknown sensor");
-	else
-		sd->sensor = probe_order[i];
+		gspca_dev->usb_err = -EINVAL;
+		return;
+	}
+	sd->sensor = probe_order[i];
+	switch (sd->sensor) {
+	case SENSOR_OV7660:
+	case SENSOR_OV9630:
+		err("Sensor %s not yet treated", sensor_tb[sd->sensor].name);
+		gspca_dev->usb_err = -EINVAL;
+		break;
+	}
 }
 
 static void mt9v111_init(struct gspca_dev *gspca_dev)
@@ -867,6 +876,9 @@ static int sd_init(struct gspca_dev *gsp
  */
 
 	reg_r(gspca_dev, SQ930_CTRL_GET_DEV_INFO, 8);
+	if (gspca_dev->usb_err < 0)
+		return gspca_dev->usb_err;
+
 /* it returns:
  * 03 00 12 93 0b f6 c9 00	live! ultra
  * 03 00 07 93 0b f6 ca 00	live! ultra for notebook
@@ -900,15 +912,15 @@ static int sd_init(struct gspca_dev *gsp
 	if (sd->sensor == SENSOR_MI0360) {
 
 		/* no sensor probe for icam tracer */
-		if (gspca_dev->usb_buf[5] == 0xf6)	/* if CMOS */
+		if (gspca_dev->usb_buf[5] == 0xf6)	/* if ccd */
 			sd->sensor = SENSOR_ICX098BQ;
 		else
 			cmos_probe(gspca_dev);
 	}
-
-	PDEBUG(D_PROBE, "Sensor %s", sensor_tb[sd->sensor].name);
-
-	global_init(sd, 1);
+	if (gspca_dev->usb_err >= 0) {
+		PDEBUG(D_PROBE, "Sensor %s", sensor_tb[sd->sensor].name);
+		global_init(sd, 1);
+	}
 	return gspca_dev->usb_err;
 }
 
@@ -1151,7 +1163,7 @@ static const struct sd_desc sd_desc = {
 #define ST(sensor, type) \
 	.driver_info = (SENSOR_ ## sensor << 8) \
 			| (type)
-static const __devinitdata struct usb_device_id device_table[] = {
+static const struct usb_device_id device_table[] = {
 	{USB_DEVICE(0x041e, 0x4038), ST(MI0360, 0)},
 	{USB_DEVICE(0x041e, 0x403c), ST(LZ24BP, 0)},
 	{USB_DEVICE(0x041e, 0x403d), ST(LZ24BP, 0)},
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/gspca/stk014.c linux-libre-2.6.38-gnu1/drivers/media/video/gspca/stk014.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/gspca/stk014.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/gspca/stk014.c	2011-03-14 21:20:32.000000000 -0400
@@ -495,7 +495,7 @@ static const struct sd_desc sd_desc = {
 };
 
 /* -- module initialisation -- */
-static const __devinitdata struct usb_device_id device_table[] = {
+static const struct usb_device_id device_table[] = {
 	{USB_DEVICE(0x05e1, 0x0893)},
 	{}
 };
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/gspca/stv0680.c linux-libre-2.6.38-gnu1/drivers/media/video/gspca/stv0680.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/gspca/stv0680.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/gspca/stv0680.c	2011-03-14 21:20:32.000000000 -0400
@@ -327,7 +327,7 @@ static const struct sd_desc sd_desc = {
 };
 
 /* -- module initialisation -- */
-static const __devinitdata struct usb_device_id device_table[] = {
+static const struct usb_device_id device_table[] = {
 	{USB_DEVICE(0x0553, 0x0202)},
 	{USB_DEVICE(0x041e, 0x4007)},
 	{}
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/gspca/stv06xx/stv06xx.c linux-libre-2.6.38-gnu1/drivers/media/video/gspca/stv06xx/stv06xx.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/gspca/stv06xx/stv06xx.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/gspca/stv06xx/stv06xx.c	2011-03-14 21:20:32.000000000 -0400
@@ -263,7 +263,21 @@ static int stv06xx_init(struct gspca_dev
 static int stv06xx_start(struct gspca_dev *gspca_dev)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
-	int err;
+	struct usb_host_interface *alt;
+	struct usb_interface *intf;
+	int err, packet_size;
+
+	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) {
+		PDEBUG(D_ERR, "Couldn't get altsetting");
+		return -EIO;
+	}
+
+	packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
+	err = stv06xx_write_bridge(sd, STV_ISO_SIZE_L, packet_size);
+	if (err < 0)
+		return err;
 
 	/* Prepare the sensor for start */
 	err = sd->sensor->start(sd);
@@ -282,6 +296,43 @@ out:
 	return (err < 0) ? err : 0;
 }
 
+static int stv06xx_isoc_init(struct gspca_dev *gspca_dev)
+{
+	struct usb_host_interface *alt;
+	struct sd *sd = (struct sd *) gspca_dev;
+
+	/* Start isoc bandwidth "negotiation" at max isoc bandwidth */
+	alt = &gspca_dev->dev->config->intf_cache[0]->altsetting[1];
+	alt->endpoint[0].desc.wMaxPacketSize =
+		cpu_to_le16(sd->sensor->max_packet_size[gspca_dev->curr_mode]);
+
+	return 0;
+}
+
+static int stv06xx_isoc_nego(struct gspca_dev *gspca_dev)
+{
+	int ret, packet_size, min_packet_size;
+	struct usb_host_interface *alt;
+	struct sd *sd = (struct sd *) gspca_dev;
+
+	alt = &gspca_dev->dev->config->intf_cache[0]->altsetting[1];
+	packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
+	min_packet_size = sd->sensor->min_packet_size[gspca_dev->curr_mode];
+	if (packet_size <= min_packet_size)
+		return -EIO;
+
+	packet_size -= 100;
+	if (packet_size < min_packet_size)
+		packet_size = min_packet_size;
+	alt->endpoint[0].desc.wMaxPacketSize = cpu_to_le16(packet_size);
+
+	ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, 1);
+	if (ret < 0)
+		PDEBUG(D_ERR|D_STREAM, "set alt 1 err %d", ret);
+
+	return ret;
+}
+
 static void stv06xx_stopN(struct gspca_dev *gspca_dev)
 {
 	int err;
@@ -349,7 +400,7 @@ static void stv06xx_pkt_scan(struct gspc
 		}
 
 		/* First byte seem to be 02=data 2nd byte is unknown??? */
-		if (sd->bridge == BRIDGE_ST6422 && (id & 0xFF00) == 0x0200)
+		if (sd->bridge == BRIDGE_ST6422 && (id & 0xff00) == 0x0200)
 			goto frame_data;
 
 		switch (id) {
@@ -462,6 +513,8 @@ static const struct sd_desc sd_desc = {
 	.start = stv06xx_start,
 	.stopN = stv06xx_stopN,
 	.pkt_scan = stv06xx_pkt_scan,
+	.isoc_init = stv06xx_isoc_init,
+	.isoc_nego = stv06xx_isoc_nego,
 #if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
 	.int_pkt_scan = sd_int_pkt_scan,
 #endif
@@ -511,7 +564,7 @@ static int stv06xx_config(struct gspca_d
 
 
 /* -- module initialisation -- */
-static const __devinitdata struct usb_device_id device_table[] = {
+static const struct usb_device_id device_table[] = {
 	/* QuickCam Express */
 	{USB_DEVICE(0x046d, 0x0840), .driver_info = BRIDGE_STV600 },
 	/* LEGO cam / QuickCam Web */
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.h linux-libre-2.6.38-gnu1/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.h
--- linux-libre-2.6.37-gnu1/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.h	2011-03-14 21:20:32.000000000 -0400
@@ -146,6 +146,11 @@ const struct stv06xx_sensor stv06xx_sens
 	.i2c_addr = (0x55 << 1),
 	.i2c_len = 1,
 
+	/* FIXME (see if we can lower min_packet_size, needs testing, and also
+	   adjusting framerate when the bandwidth gets lower) */
+	.min_packet_size = { 847 },
+	.max_packet_size = { 847 },
+
 	.init = hdcs_init,
 	.probe = hdcs_probe_1x00,
 	.start = hdcs_start,
@@ -160,6 +165,11 @@ const struct stv06xx_sensor stv06xx_sens
 	.i2c_addr = (0x55 << 1),
 	.i2c_len = 1,
 
+	/* FIXME (see if we can lower min_packet_size, needs testing, and also
+	   adjusting framerate when the bandwidthm gets lower) */
+	.min_packet_size = { 847 },
+	.max_packet_size = { 847 },
+
 	.init = hdcs_init,
 	.probe = hdcs_probe_1020,
 	.start = hdcs_start,
@@ -177,7 +187,6 @@ static const u16 stv_bridge_init[][2] =
 	{STV_REG04, 0x07},
 
 	{STV_SCAN_RATE, 0x20},
-	{STV_ISO_SIZE_L, 847},
 	{STV_Y_CTRL, 0x01},
 	{STV_X_CTRL, 0x0a}
 };
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.c linux-libre-2.6.38-gnu1/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.c	2011-03-14 21:20:32.000000000 -0400
@@ -208,11 +208,24 @@ static int pb0100_probe(struct sd *sd)
 
 static int pb0100_start(struct sd *sd)
 {
-	int err;
+	int err, packet_size, max_packet_size;
+	struct usb_host_interface *alt;
+	struct usb_interface *intf;
 	struct cam *cam = &sd->gspca_dev.cam;
 	s32 *sensor_settings = sd->sensor_priv;
 	u32 mode = cam->cam_mode[sd->gspca_dev.curr_mode].priv;
 
+	intf = usb_ifnum_to_if(sd->gspca_dev.dev, sd->gspca_dev.iface);
+	alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt);
+	packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
+
+	/* If we don't have enough bandwidth use a lower framerate */
+	max_packet_size = sd->sensor->max_packet_size[sd->gspca_dev.curr_mode];
+	if (packet_size < max_packet_size)
+		stv06xx_write_sensor(sd, PB_ROWSPEED, BIT(4)|BIT(3)|BIT(1));
+	else
+		stv06xx_write_sensor(sd, PB_ROWSPEED, BIT(5)|BIT(3)|BIT(1));
+
 	/* Setup sensor window */
 	if (mode & PB0100_CROP_TO_VGA) {
 		stv06xx_write_sensor(sd, PB_RSTART, 30);
@@ -328,9 +341,6 @@ static int pb0100_init(struct sd *sd)
 	stv06xx_write_bridge(sd, STV_REG03, 0x45);
 	stv06xx_write_bridge(sd, STV_REG04, 0x07);
 
-	/* ISO-Size (0x27b: 635... why? - HDCS uses 847) */
-	stv06xx_write_bridge(sd, STV_ISO_SIZE_L, 847);
-
 	/* Scan/timing for the sensor */
 	stv06xx_write_sensor(sd, PB_ROWSPEED, BIT(4)|BIT(3)|BIT(1));
 	stv06xx_write_sensor(sd, PB_CFILLIN, 14);
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.h linux-libre-2.6.38-gnu1/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.h
--- linux-libre-2.6.37-gnu1/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.h	2011-03-14 21:20:32.000000000 -0400
@@ -138,6 +138,9 @@ const struct stv06xx_sensor stv06xx_sens
 	.i2c_addr = 0xba,
 	.i2c_len = 2,
 
+	.min_packet_size = { 635, 847 },
+	.max_packet_size = { 847, 923 },
+
 	.init = pb0100_init,
 	.probe = pb0100_probe,
 	.start = pb0100_start,
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/gspca/stv06xx/stv06xx_sensor.h linux-libre-2.6.38-gnu1/drivers/media/video/gspca/stv06xx/stv06xx_sensor.h
--- linux-libre-2.6.37-gnu1/drivers/media/video/gspca/stv06xx/stv06xx_sensor.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/gspca/stv06xx/stv06xx_sensor.h	2011-03-14 21:20:32.000000000 -0400
@@ -53,6 +53,10 @@ struct stv06xx_sensor {
 	/* length of an i2c word */
 	u8 i2c_len;
 
+	/* Isoc packet size (per mode) */
+	int min_packet_size[4];
+	int max_packet_size[4];
+
 	/* Probes if the sensor is connected */
 	int (*probe)(struct sd *sd);
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/gspca/stv06xx/stv06xx_st6422.c linux-libre-2.6.38-gnu1/drivers/media/video/gspca/stv06xx/stv06xx_st6422.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/gspca/stv06xx/stv06xx_st6422.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/gspca/stv06xx/stv06xx_st6422.c	2011-03-14 21:20:32.000000000 -0400
@@ -28,6 +28,20 @@
 
 #include "stv06xx_st6422.h"
 
+/* controls */
+enum e_ctrl {
+	BRIGHTNESS,
+	CONTRAST,
+	GAIN,
+	EXPOSURE,
+	NCTRLS		/* number of controls */
+};
+
+/* sensor settings */
+struct st6422_settings {
+	struct gspca_ctrl ctrls[NCTRLS];
+};
+
 static struct v4l2_pix_format st6422_mode[] = {
 	/* Note we actually get 124 lines of data, of which we skip the 4st
 	   4 as they are garbage */
@@ -57,9 +71,14 @@ static struct v4l2_pix_format st6422_mod
 	},
 };
 
-static const struct ctrl st6422_ctrl[] = {
-#define BRIGHTNESS_IDX 0
-	{
+/* V4L2 controls supported by the driver */
+static void st6422_set_brightness(struct gspca_dev *gspca_dev);
+static void st6422_set_contrast(struct gspca_dev *gspca_dev);
+static void st6422_set_gain(struct gspca_dev *gspca_dev);
+static void st6422_set_exposure(struct gspca_dev *gspca_dev);
+
+static const struct ctrl st6422_ctrl[NCTRLS] = {
+[BRIGHTNESS] = {
 		{
 			.id		= V4L2_CID_BRIGHTNESS,
 			.type		= V4L2_CTRL_TYPE_INTEGER,
@@ -69,11 +88,9 @@ static const struct ctrl st6422_ctrl[] =
 			.step		= 1,
 			.default_value  = 3
 		},
-		.set = st6422_set_brightness,
-		.get = st6422_get_brightness
+		.set_control = st6422_set_brightness
 	},
-#define CONTRAST_IDX 1
-	{
+[CONTRAST] = {
 		{
 			.id		= V4L2_CID_CONTRAST,
 			.type		= V4L2_CTRL_TYPE_INTEGER,
@@ -83,11 +100,9 @@ static const struct ctrl st6422_ctrl[] =
 			.step		= 1,
 			.default_value  = 11
 		},
-		.set = st6422_set_contrast,
-		.get = st6422_get_contrast
+		.set_control = st6422_set_contrast
 	},
-#define GAIN_IDX 2
-	{
+[GAIN] = {
 		{
 			.id		= V4L2_CID_GAIN,
 			.type		= V4L2_CTRL_TYPE_INTEGER,
@@ -97,49 +112,43 @@ static const struct ctrl st6422_ctrl[] =
 			.step		= 1,
 			.default_value  = 64
 		},
-		.set = st6422_set_gain,
-		.get = st6422_get_gain
+		.set_control = st6422_set_gain
 	},
-#define EXPOSURE_IDX 3
-	{
+[EXPOSURE] = {
 		{
 			.id		= V4L2_CID_EXPOSURE,
 			.type		= V4L2_CTRL_TYPE_INTEGER,
 			.name		= "Exposure",
 			.minimum	= 0,
-			.maximum	= 1023,
+#define EXPOSURE_MAX 1023
+			.maximum	= EXPOSURE_MAX,
 			.step		= 1,
 			.default_value  = 256
 		},
-		.set = st6422_set_exposure,
-		.get = st6422_get_exposure
+		.set_control = st6422_set_exposure
 	},
 };
 
 static int st6422_probe(struct sd *sd)
 {
-	int i;
-	s32 *sensor_settings;
+	struct st6422_settings *sensor_settings;
 
 	if (sd->bridge != BRIDGE_ST6422)
 		return -ENODEV;
 
 	info("st6422 sensor detected");
 
-	sensor_settings = kmalloc(ARRAY_SIZE(st6422_ctrl) * sizeof(s32),
-				  GFP_KERNEL);
+	sensor_settings = kmalloc(sizeof *sensor_settings, GFP_KERNEL);
 	if (!sensor_settings)
 		return -ENOMEM;
 
 	sd->gspca_dev.cam.cam_mode = st6422_mode;
 	sd->gspca_dev.cam.nmodes = ARRAY_SIZE(st6422_mode);
+	sd->gspca_dev.cam.ctrls = sensor_settings->ctrls;
 	sd->desc.ctrls = st6422_ctrl;
 	sd->desc.nctrls = ARRAY_SIZE(st6422_ctrl);
 	sd->sensor_priv = sensor_settings;
 
-	for (i = 0; i < sd->desc.nctrls; i++)
-		sensor_settings[i] = st6422_ctrl[i].qctrl.default_value;
-
 	return 0;
 }
 
@@ -151,11 +160,11 @@ static int st6422_init(struct sd *sd)
 		{ STV_ISO_ENABLE, 0x00 }, /* disable capture */
 		{ 0x1436, 0x00 },
 		{ 0x1432, 0x03 },	/* 0x00-0x1F brightness */
-		{ 0x143a, 0xF9 },	/* 0x00-0x0F contrast */
+		{ 0x143a, 0xf9 },	/* 0x00-0x0F contrast */
 		{ 0x0509, 0x38 },	/* R */
 		{ 0x050a, 0x38 },	/* G */
 		{ 0x050b, 0x38 },	/* B */
-		{ 0x050c, 0x2A },
+		{ 0x050c, 0x2a },
 		{ 0x050d, 0x01 },
 
 
@@ -213,7 +222,6 @@ static int st6422_init(struct sd *sd)
 		{ 0x150e, 0x8e },
 		{ 0x150f, 0x37 },
 		{ 0x15c0, 0x00 },
-		{ 0x15c1, 1023 }, /* 160x120, ISOC_PACKET_SIZE */
 		{ 0x15c3, 0x08 },	/* 0x04/0x14 ... test pictures ??? */
 
 
@@ -235,91 +243,92 @@ static void st6422_disconnect(struct sd
 	kfree(sd->sensor_priv);
 }
 
-static int st6422_start(struct sd *sd)
+static int setbrightness(struct sd *sd)
 {
-	int err, packet_size;
-	struct cam *cam = &sd->gspca_dev.cam;
-	s32 *sensor_settings = sd->sensor_priv;
-	struct usb_host_interface *alt;
-	struct usb_interface *intf;
+	struct st6422_settings *sensor_settings = sd->sensor_priv;
 
-	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");
-		return -EIO;
-	}
+	/* val goes from 0 -> 31 */
+	return stv06xx_write_bridge(sd, 0x1432,
+			sensor_settings->ctrls[BRIGHTNESS].val);
+}
 
-	packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
-	err = stv06xx_write_bridge(sd, 0x15c1, packet_size);
-	if (err < 0)
-		return err;
+static int setcontrast(struct sd *sd)
+{
+	struct st6422_settings *sensor_settings = sd->sensor_priv;
 
-	if (cam->cam_mode[sd->gspca_dev.curr_mode].priv)
-		err = stv06xx_write_bridge(sd, 0x1505, 0x0f);
-	else
-		err = stv06xx_write_bridge(sd, 0x1505, 0x02);
-	if (err < 0)
-		return err;
+	/* Val goes from 0 -> 15 */
+	return stv06xx_write_bridge(sd, 0x143a,
+			sensor_settings->ctrls[CONTRAST].val | 0xf0);
+}
 
-	err = st6422_set_brightness(&sd->gspca_dev,
-				    sensor_settings[BRIGHTNESS_IDX]);
+static int setgain(struct sd *sd)
+{
+	struct st6422_settings *sensor_settings = sd->sensor_priv;
+	u8 gain;
+	int err;
+
+	gain = sensor_settings->ctrls[GAIN].val;
+
+	/* Set red, green, blue, gain */
+	err = stv06xx_write_bridge(sd, 0x0509, gain);
 	if (err < 0)
 		return err;
 
-	err = st6422_set_contrast(&sd->gspca_dev,
-				  sensor_settings[CONTRAST_IDX]);
+	err = stv06xx_write_bridge(sd, 0x050a, gain);
 	if (err < 0)
 		return err;
 
-	err = st6422_set_exposure(&sd->gspca_dev,
-				  sensor_settings[EXPOSURE_IDX]);
+	err = stv06xx_write_bridge(sd, 0x050b, gain);
 	if (err < 0)
 		return err;
 
-	err = st6422_set_gain(&sd->gspca_dev,
-			      sensor_settings[GAIN_IDX]);
+	/* 2 mystery writes */
+	err = stv06xx_write_bridge(sd, 0x050c, 0x2a);
 	if (err < 0)
 		return err;
 
-	PDEBUG(D_STREAM, "Starting stream");
-
-	return 0;
-}
-
-static int st6422_stop(struct sd *sd)
-{
-	PDEBUG(D_STREAM, "Halting stream");
-
-	return 0;
+	return stv06xx_write_bridge(sd, 0x050d, 0x01);
 }
 
-static int st6422_get_brightness(struct gspca_dev *gspca_dev, __s32 *val)
+static int setexposure(struct sd *sd)
 {
-	struct sd *sd = (struct sd *) gspca_dev;
-	s32 *sensor_settings = sd->sensor_priv;
-
-	*val = sensor_settings[BRIGHTNESS_IDX];
+	struct st6422_settings *sensor_settings = sd->sensor_priv;
+	u16 expo;
+	int err;
 
-	PDEBUG(D_V4L2, "Read brightness %d", *val);
+	expo = sensor_settings->ctrls[EXPOSURE].val;
+	err = stv06xx_write_bridge(sd, 0x143d, expo & 0xff);
+	if (err < 0)
+		return err;
 
-	return 0;
+	return stv06xx_write_bridge(sd, 0x143e, expo >> 8);
 }
 
-static int st6422_set_brightness(struct gspca_dev *gspca_dev, __s32 val)
+static int st6422_start(struct sd *sd)
 {
 	int err;
-	struct sd *sd = (struct sd *) gspca_dev;
-	s32 *sensor_settings = sd->sensor_priv;
+	struct cam *cam = &sd->gspca_dev.cam;
 
-	sensor_settings[BRIGHTNESS_IDX] = val;
+	if (cam->cam_mode[sd->gspca_dev.curr_mode].priv)
+		err = stv06xx_write_bridge(sd, 0x1505, 0x0f);
+	else
+		err = stv06xx_write_bridge(sd, 0x1505, 0x02);
+	if (err < 0)
+		return err;
 
-	if (!gspca_dev->streaming)
-		return 0;
+	err = setbrightness(sd);
+	if (err < 0)
+		return err;
 
-	/* val goes from 0 -> 31 */
-	PDEBUG(D_V4L2, "Set brightness to %d", val);
-	err = stv06xx_write_bridge(sd, 0x1432, val);
+	err = setcontrast(sd);
+	if (err < 0)
+		return err;
+
+	err = setexposure(sd);
+	if (err < 0)
+		return err;
+
+	err = setgain(sd);
 	if (err < 0)
 		return err;
 
@@ -328,125 +337,65 @@ static int st6422_set_brightness(struct
 	return (err < 0) ? err : 0;
 }
 
-static int st6422_get_contrast(struct gspca_dev *gspca_dev, __s32 *val)
+static int st6422_stop(struct sd *sd)
 {
-	struct sd *sd = (struct sd *) gspca_dev;
-	s32 *sensor_settings = sd->sensor_priv;
-
-	*val = sensor_settings[CONTRAST_IDX];
-
-	PDEBUG(D_V4L2, "Read contrast %d", *val);
+	PDEBUG(D_STREAM, "Halting stream");
 
 	return 0;
 }
 
-static int st6422_set_contrast(struct gspca_dev *gspca_dev, __s32 val)
+static void st6422_set_brightness(struct gspca_dev *gspca_dev)
 {
 	int err;
 	struct sd *sd = (struct sd *) gspca_dev;
-	s32 *sensor_settings = sd->sensor_priv;
-
-	sensor_settings[CONTRAST_IDX] = val;
 
-	if (!gspca_dev->streaming)
-		return 0;
-
-	/* Val goes from 0 -> 15 */
-	PDEBUG(D_V4L2, "Set contrast to %d\n", val);
-	err = stv06xx_write_bridge(sd, 0x143a, 0xf0 | val);
-	if (err < 0)
-		return err;
+	err = setbrightness(sd);
 
 	/* commit settings */
-	err = stv06xx_write_bridge(sd, 0x143f, 0x01);
-	return (err < 0) ? err : 0;
-}
-
-static int st6422_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-	s32 *sensor_settings = sd->sensor_priv;
-
-	*val = sensor_settings[GAIN_IDX];
-
-	PDEBUG(D_V4L2, "Read gain %d", *val);
+	if (err >= 0)
+		err = stv06xx_write_bridge(sd, 0x143f, 0x01);
 
-	return 0;
+	gspca_dev->usb_err = err;
 }
 
-static int st6422_set_gain(struct gspca_dev *gspca_dev, __s32 val)
+static void st6422_set_contrast(struct gspca_dev *gspca_dev)
 {
 	int err;
 	struct sd *sd = (struct sd *) gspca_dev;
-	s32 *sensor_settings = sd->sensor_priv;
-
-	sensor_settings[GAIN_IDX] = val;
-
-	if (!gspca_dev->streaming)
-		return 0;
-
-	PDEBUG(D_V4L2, "Set gain to %d", val);
-
-	/* Set red, green, blue, gain */
-	err = stv06xx_write_bridge(sd, 0x0509, val);
-	if (err < 0)
-		return err;
-
-	err = stv06xx_write_bridge(sd, 0x050a, val);
-	if (err < 0)
-		return err;
 
-	err = stv06xx_write_bridge(sd, 0x050b, val);
-	if (err < 0)
-		return err;
-
-	/* 2 mystery writes */
-	err = stv06xx_write_bridge(sd, 0x050c, 0x2a);
-	if (err < 0)
-		return err;
-
-	err = stv06xx_write_bridge(sd, 0x050d, 0x01);
-	if (err < 0)
-		return err;
+	err = setcontrast(sd);
 
 	/* commit settings */
-	err = stv06xx_write_bridge(sd, 0x143f, 0x01);
-	return (err < 0) ? err : 0;
+	if (err >= 0)
+		err = stv06xx_write_bridge(sd, 0x143f, 0x01);
+
+	gspca_dev->usb_err = err;
 }
 
-static int st6422_get_exposure(struct gspca_dev *gspca_dev, __s32 *val)
+static void st6422_set_gain(struct gspca_dev *gspca_dev)
 {
+	int err;
 	struct sd *sd = (struct sd *) gspca_dev;
-	s32 *sensor_settings = sd->sensor_priv;
 
-	*val = sensor_settings[EXPOSURE_IDX];
+	err = setgain(sd);
 
-	PDEBUG(D_V4L2, "Read exposure %d", *val);
+	/* commit settings */
+	if (err >= 0)
+		err = stv06xx_write_bridge(sd, 0x143f, 0x01);
 
-	return 0;
+	gspca_dev->usb_err = err;
 }
 
-static int st6422_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
+static void st6422_set_exposure(struct gspca_dev *gspca_dev)
 {
 	int err;
 	struct sd *sd = (struct sd *) gspca_dev;
-	s32 *sensor_settings = sd->sensor_priv;
-
-	sensor_settings[EXPOSURE_IDX] = val;
 
-	if (!gspca_dev->streaming)
-		return 0;
-
-	PDEBUG(D_V4L2, "Set exposure to %d\n", val);
-	err = stv06xx_write_bridge(sd, 0x143d, val & 0xff);
-	if (err < 0)
-		return err;
-
-	err = stv06xx_write_bridge(sd, 0x143e, val >> 8);
-	if (err < 0)
-		return err;
+	err = setexposure(sd);
 
 	/* commit settings */
-	err = stv06xx_write_bridge(sd, 0x143f, 0x01);
-	return (err < 0) ? err : 0;
+	if (err >= 0)
+		err = stv06xx_write_bridge(sd, 0x143f, 0x01);
+
+	gspca_dev->usb_err = err;
 }
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/gspca/stv06xx/stv06xx_st6422.h linux-libre-2.6.38-gnu1/drivers/media/video/gspca/stv06xx/stv06xx_st6422.h
--- linux-libre-2.6.37-gnu1/drivers/media/video/gspca/stv06xx/stv06xx_st6422.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/gspca/stv06xx/stv06xx_st6422.h	2011-03-14 21:20:32.000000000 -0400
@@ -37,18 +37,11 @@ static int st6422_init(struct sd *sd);
 static int st6422_stop(struct sd *sd);
 static void st6422_disconnect(struct sd *sd);
 
-/* V4L2 controls supported by the driver */
-static int st6422_get_brightness(struct gspca_dev *gspca_dev, __s32 *val);
-static int st6422_set_brightness(struct gspca_dev *gspca_dev, __s32 val);
-static int st6422_get_contrast(struct gspca_dev *gspca_dev, __s32 *val);
-static int st6422_set_contrast(struct gspca_dev *gspca_dev, __s32 val);
-static int st6422_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
-static int st6422_set_gain(struct gspca_dev *gspca_dev, __s32 val);
-static int st6422_get_exposure(struct gspca_dev *gspca_dev, __s32 *val);
-static int st6422_set_exposure(struct gspca_dev *gspca_dev, __s32 val);
-
 const struct stv06xx_sensor stv06xx_sensor_st6422 = {
 	.name = "ST6422",
+	/* No known way to lower framerate in case of less bandwidth */
+	.min_packet_size = { 300, 847 },
+	.max_packet_size = { 300, 847 },
 	.init = st6422_init,
 	.probe = st6422_probe,
 	.start = st6422_start,
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h linux-libre-2.6.38-gnu1/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h
--- linux-libre-2.6.37-gnu1/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h	2011-03-14 21:20:32.000000000 -0400
@@ -197,6 +197,10 @@ const struct stv06xx_sensor stv06xx_sens
 	.i2c_flush = 5,
 	.i2c_addr = 0x20,
 	.i2c_len = 1,
+	/* FIXME (see if we can lower packet_size-s, needs testing, and also
+	   adjusting framerate when the bandwidth gets lower) */
+	.min_packet_size = { 1023 },
+	.max_packet_size = { 1023 },
 	.init = vv6410_init,
 	.probe = vv6410_probe,
 	.start = vv6410_start,
@@ -220,10 +224,6 @@ static const u8 x1536[] = {	/* 0x1536 -
 	0x02, 0x00, 0x60, 0x01, 0x20, 0x01
 };
 
-static const u8 x15c1[] = {	/* 0x15c1 - 0x15c2 */
-	0xff, 0x03 /* Output word 0x03ff = 1023 (ISO size) */
-};
-
 static const struct stv_init stv_bridge_init[] = {
 	/* This reg is written twice. Some kind of reset? */
 	{NULL,  0x1620, 0x80},
@@ -232,7 +232,6 @@ static const struct stv_init stv_bridge_
 	{NULL,  0x1423, 0x04},
 	{x1500, 0x1500, ARRAY_SIZE(x1500)},
 	{x1536, 0x1536, ARRAY_SIZE(x1536)},
-	{x15c1, 0x15c1, ARRAY_SIZE(x15c1)}
 };
 
 static const u8 vv6410_sensor_init[][2] = {
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/gspca/sunplus.c linux-libre-2.6.38-gnu1/drivers/media/video/gspca/sunplus.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/gspca/sunplus.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/gspca/sunplus.c	2011-03-14 21:20:32.000000000 -0400
@@ -1162,7 +1162,7 @@ static const struct sd_desc sd_desc = {
 #define BS(bridge, subtype) \
 	.driver_info = (BRIDGE_ ## bridge << 8) \
 			| (subtype)
-static const __devinitdata struct usb_device_id device_table[] = {
+static const struct usb_device_id device_table[] = {
 	{USB_DEVICE(0x041e, 0x400b), BS(SPCA504C, 0)},
 	{USB_DEVICE(0x041e, 0x4012), BS(SPCA504C, 0)},
 	{USB_DEVICE(0x041e, 0x4013), BS(SPCA504C, 0)},
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/gspca/t613.c linux-libre-2.6.38-gnu1/drivers/media/video/gspca/t613.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/gspca/t613.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/gspca/t613.c	2011-03-14 21:20:32.000000000 -0400
@@ -487,7 +487,7 @@ static const u8 gamma_table[GAMMA_MAX][1
 	{0x00, 0x02, 0x07, 0x0f, 0x18, 0x24, 0x30, 0x3f,	/* 3 */
 	 0x4f, 0x61, 0x73, 0x88, 0x9d, 0xb4, 0xcd, 0xe6,
 	 0xff},
-	{0x00, 0x04, 0x0B, 0x15, 0x20, 0x2d, 0x3b, 0x4a,	/* 4 */
+	{0x00, 0x04, 0x0b, 0x15, 0x20, 0x2d, 0x3b, 0x4a,	/* 4 */
 	 0x5b, 0x6c, 0x7f, 0x92, 0xa7, 0xbc, 0xd2, 0xe9,
 	 0xff},
 	{0x00, 0x07, 0x11, 0x15, 0x20, 0x2d, 0x48, 0x58,	/* 5 */
@@ -1416,7 +1416,7 @@ static const struct sd_desc sd_desc = {
 };
 
 /* -- module initialisation -- */
-static const __devinitdata struct usb_device_id device_table[] = {
+static const struct usb_device_id device_table[] = {
 	{USB_DEVICE(0x17a1, 0x0128)},
 	{}
 };
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/gspca/tv8532.c linux-libre-2.6.38-gnu1/drivers/media/video/gspca/tv8532.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/gspca/tv8532.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/gspca/tv8532.c	2011-03-14 21:20:32.000000000 -0400
@@ -132,7 +132,7 @@ static const struct v4l2_pix_format sif_
 #define R36_PID		0x36
 #define R37_PIDH	0x37
 #define R39_Test1	0x39		/* GPIO */
-#define R3B_Test3	0x3B		/* GPIO */
+#define R3B_Test3	0x3b		/* GPIO */
 #define R83_AD_IDH	0x83
 #define R91_AD_SLOPEREG 0x91
 #define R94_AD_BITCONTROL 0x94
@@ -388,7 +388,7 @@ static const struct sd_desc sd_desc = {
 };
 
 /* -- module initialisation -- */
-static const __devinitdata struct usb_device_id device_table[] = {
+static const struct usb_device_id device_table[] = {
 	{USB_DEVICE(0x046d, 0x0920)},
 	{USB_DEVICE(0x046d, 0x0921)},
 	{USB_DEVICE(0x0545, 0x808b)},
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/gspca/vc032x.c linux-libre-2.6.38-gnu1/drivers/media/video/gspca/vc032x.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/gspca/vc032x.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/gspca/vc032x.c	2011-03-14 21:20:32.000000000 -0400
@@ -47,24 +47,29 @@ struct sd {
 	u8 image_offset;
 
 	u8 bridge;
-#define BRIDGE_VC0321 0
-#define BRIDGE_VC0323 1
 	u8 sensor;
-#define SENSOR_HV7131R 0
-#define SENSOR_MI0360 1
-#define SENSOR_MI1310_SOC 2
-#define SENSOR_MI1320 3
-#define SENSOR_MI1320_SOC 4
-#define SENSOR_OV7660 5
-#define SENSOR_OV7670 6
-#define SENSOR_PO1200 7
-#define SENSOR_PO3130NC 8
-#define SENSOR_POxxxx 9
 	u8 flags;
 #define FL_SAMSUNG 0x01		/* SamsungQ1 (2 sensors) */
 #define FL_HFLIP 0x02		/* mirrored by default */
 #define FL_VFLIP 0x04		/* vertical flipped by default */
 };
+enum bridges {
+	BRIDGE_VC0321,
+	BRIDGE_VC0323,
+};
+enum sensors {
+	SENSOR_HV7131R,
+	SENSOR_MI0360,
+	SENSOR_MI1310_SOC,
+	SENSOR_MI1320,
+	SENSOR_MI1320_SOC,
+	SENSOR_OV7660,
+	SENSOR_OV7670,
+	SENSOR_PO1200,
+	SENSOR_PO3130NC,
+	SENSOR_POxxxx,
+	NSENSORS
+};
 
 /* V4L2 controls supported by the driver */
 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
@@ -260,56 +265,56 @@ static const struct ctrl sd_ctrls[] = {
 };
 
 /* table of the disabled controls */
-static u32 ctrl_dis[] = {
-/* SENSOR_HV7131R 0 */
+static u32 ctrl_dis[NSENSORS] = {
+    [SENSOR_HV7131R] =
 	(1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX)
 		| (1 << HFLIP_IDX) | (1 << VFLIP_IDX) | (1 << LIGHTFREQ_IDX)
 		| (1 << SHARPNESS_IDX)
 		| (1 << GAIN_IDX) | (1 << EXPOSURE_IDX)
 		| (1 << AUTOGAIN_IDX) | (1 << BACKLIGHT_IDX),
-/* SENSOR_MI0360 1 */
+    [SENSOR_MI0360] =
 	(1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX)
 		| (1 << HFLIP_IDX) | (1 << VFLIP_IDX) | (1 << LIGHTFREQ_IDX)
 		| (1 << SHARPNESS_IDX)
 		| (1 << GAIN_IDX) | (1 << EXPOSURE_IDX)
 		| (1 << AUTOGAIN_IDX) | (1 << BACKLIGHT_IDX),
-/* SENSOR_MI1310_SOC 2 */
+    [SENSOR_MI1310_SOC] =
 	(1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX)
 		| (1 << LIGHTFREQ_IDX) | (1 << SHARPNESS_IDX)
 		| (1 << GAIN_IDX) | (1 << EXPOSURE_IDX)
 		| (1 << AUTOGAIN_IDX) | (1 << BACKLIGHT_IDX),
-/* SENSOR_MI1320 3 */
+    [SENSOR_MI1320] =
 	(1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX)
 		| (1 << LIGHTFREQ_IDX) | (1 << SHARPNESS_IDX)
 		| (1 << GAIN_IDX) | (1 << EXPOSURE_IDX)
 		| (1 << AUTOGAIN_IDX) | (1 << BACKLIGHT_IDX),
-/* SENSOR_MI1320_SOC 4 */
+    [SENSOR_MI1320_SOC] =
 	(1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX)
 		| (1 << LIGHTFREQ_IDX) | (1 << SHARPNESS_IDX)
 		| (1 << GAIN_IDX) | (1 << EXPOSURE_IDX)
 		| (1 << AUTOGAIN_IDX) | (1 << BACKLIGHT_IDX),
-/* SENSOR_OV7660 5 */
+    [SENSOR_OV7660] =
 	(1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX)
 		| (1 << LIGHTFREQ_IDX) | (1 << SHARPNESS_IDX)
 		| (1 << GAIN_IDX) | (1 << EXPOSURE_IDX)
 		| (1 << AUTOGAIN_IDX) | (1 << BACKLIGHT_IDX),
-/* SENSOR_OV7670 6 */
+    [SENSOR_OV7670] =
 	(1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX)
 		| (1 << SHARPNESS_IDX)
 		| (1 << GAIN_IDX) | (1 << EXPOSURE_IDX)
 		| (1 << AUTOGAIN_IDX) | (1 << BACKLIGHT_IDX),
-/* SENSOR_PO1200 7 */
+    [SENSOR_PO1200] =
 	(1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX)
 		| (1 << LIGHTFREQ_IDX)
 		| (1 << GAIN_IDX) | (1 << EXPOSURE_IDX)
 		| (1 << AUTOGAIN_IDX) | (1 << BACKLIGHT_IDX),
-/* SENSOR_PO3130NC 8 */
+    [SENSOR_PO3130NC] =
 	(1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX)
 		| (1 << HFLIP_IDX) | (1 << VFLIP_IDX) | (1 << LIGHTFREQ_IDX)
 		| (1 << SHARPNESS_IDX)
 		| (1 << GAIN_IDX) | (1 << EXPOSURE_IDX)
 		| (1 << AUTOGAIN_IDX) | (1 << BACKLIGHT_IDX),
-/* SENSOR_POxxxx 9 */
+    [SENSOR_POxxxx] =
 	(1 << HFLIP_IDX) | (1 << VFLIP_IDX) | (1 << LIGHTFREQ_IDX),
 };
 
@@ -3420,17 +3425,18 @@ static int sd_init(struct gspca_dev *gsp
 	struct sd *sd = (struct sd *) gspca_dev;
 	struct cam *cam;
 	int sensor;
-	static u8 npkt[] = {	/* number of packets per ISOC message */
-		64,		/* HV7131R 0 */
-		32,		/* MI0360 1 */
-		32,		/* MI1310_SOC 2 */
-		64,		/* MI1320 3 */
-		128,		/* MI1320_SOC 4 */
-		32,		/* OV7660 5 */
-		64,		/* OV7670 6 */
-		128,		/* PO1200 7 */
-		128,		/* PO3130NC 8 */
-		128,		/* POxxxx 9 */
+	/* number of packets per ISOC message */
+	static u8 npkt[NSENSORS] = {
+		[SENSOR_HV7131R] =	64,
+		[SENSOR_MI0360] =	32,
+		[SENSOR_MI1310_SOC] =	32,
+		[SENSOR_MI1320] =	64,
+		[SENSOR_MI1320_SOC] =	128,
+		[SENSOR_OV7660] =	32,
+		[SENSOR_OV7670] =	64,
+		[SENSOR_PO1200] =	128,
+		[SENSOR_PO3130NC] =	128,
+		[SENSOR_POxxxx] =	128,
 	};
 
 	if (sd->sensor != SENSOR_POxxxx)
@@ -4186,7 +4192,7 @@ static const struct sd_desc sd_desc = {
 #define BF(bridge, flags) \
 	.driver_info = (BRIDGE_ ## bridge << 8) \
 		| (flags)
-static const __devinitdata struct usb_device_id device_table[] = {
+static const struct usb_device_id device_table[] = {
 	{USB_DEVICE(0x041e, 0x405b), BF(VC0323, FL_VFLIP)},
 	{USB_DEVICE(0x046d, 0x0892), BF(VC0321, 0)},
 	{USB_DEVICE(0x046d, 0x0896), BF(VC0321, 0)},
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/gspca/w996Xcf.c linux-libre-2.6.38-gnu1/drivers/media/video/gspca/w996Xcf.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/gspca/w996Xcf.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/gspca/w996Xcf.c	2011-03-14 21:20:32.000000000 -0400
@@ -59,18 +59,21 @@ static const struct v4l2_pix_format w996
 		.colorspace = V4L2_COLORSPACE_JPEG},
 };
 
-static int reg_w(struct sd *sd, __u16 index, __u16 value);
+static void reg_w(struct sd *sd, u16 index, u16 value);
 
 /*--------------------------------------------------------------------------
   Write 64-bit data to the fast serial bus registers.
   Return 0 on success, -1 otherwise.
   --------------------------------------------------------------------------*/
-static int w9968cf_write_fsb(struct sd *sd, u16* data)
+static void w9968cf_write_fsb(struct sd *sd, u16* data)
 {
 	struct usb_device *udev = sd->gspca_dev.dev;
 	u16 value;
 	int ret;
 
+	if (sd->gspca_dev.usb_err < 0)
+		return;
+
 	value = *data++;
 	memcpy(sd->gspca_dev.usb_buf, data, 6);
 
@@ -79,20 +82,21 @@ static int w9968cf_write_fsb(struct sd *
 			      value, 0x06, sd->gspca_dev.usb_buf, 6, 500);
 	if (ret < 0) {
 		err("Write FSB registers failed (%d)", ret);
-		return ret;
+		sd->gspca_dev.usb_err = ret;
 	}
-
-	return 0;
 }
 
 /*--------------------------------------------------------------------------
   Write data to the serial bus control register.
   Return 0 on success, a negative number otherwise.
   --------------------------------------------------------------------------*/
-static int w9968cf_write_sb(struct sd *sd, u16 value)
+static void w9968cf_write_sb(struct sd *sd, u16 value)
 {
 	int ret;
 
+	if (sd->gspca_dev.usb_err < 0)
+		return;
+
 	/* We don't use reg_w here, as that would cause all writes when
 	   bitbanging i2c to be logged, making the logs impossible to read */
 	ret = usb_control_msg(sd->gspca_dev.dev,
@@ -105,10 +109,8 @@ static int w9968cf_write_sb(struct sd *s
 
 	if (ret < 0) {
 		err("Write SB reg [01] %04x failed", value);
-		return ret;
+		sd->gspca_dev.usb_err = ret;
 	}
-
-	return 0;
 }
 
 /*--------------------------------------------------------------------------
@@ -119,6 +121,9 @@ static int w9968cf_read_sb(struct sd *sd
 {
 	int ret;
 
+	if (sd->gspca_dev.usb_err < 0)
+		return -1;
+
 	/* We don't use reg_r here, as the w9968cf is special and has 16
 	   bit registers instead of 8 bit */
 	ret = usb_control_msg(sd->gspca_dev.dev,
@@ -126,11 +131,13 @@ static int w9968cf_read_sb(struct sd *sd
 			1,
 			USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 			0, 0x01, sd->gspca_dev.usb_buf, 2, 500);
-	if (ret >= 0)
+	if (ret >= 0) {
 		ret = sd->gspca_dev.usb_buf[0] |
 		      (sd->gspca_dev.usb_buf[1] << 8);
-	else
+	} else {
 		err("Read SB reg [01] failed");
+		sd->gspca_dev.usb_err = ret;
+	}
 
 	udelay(W9968CF_I2C_BUS_DELAY);
 
@@ -142,22 +149,20 @@ static int w9968cf_read_sb(struct sd *sd
   This function is called by w9968cf_start_transfer().
   Return 0 on success, a negative number otherwise.
   --------------------------------------------------------------------------*/
-static int w9968cf_upload_quantizationtables(struct sd *sd)
+static void w9968cf_upload_quantizationtables(struct sd *sd)
 {
 	u16 a, b;
-	int ret = 0, i, j;
+	int i, j;
 
-	ret += reg_w(sd, 0x39, 0x0010); /* JPEG clock enable */
+	reg_w(sd, 0x39, 0x0010); /* JPEG clock enable */
 
 	for (i = 0, j = 0; i < 32; i++, j += 2) {
-		a = Y_QUANTABLE[j] | ((unsigned)(Y_QUANTABLE[j+1]) << 8);
-		b = UV_QUANTABLE[j] | ((unsigned)(UV_QUANTABLE[j+1]) << 8);
-		ret += reg_w(sd, 0x40+i, a);
-		ret += reg_w(sd, 0x60+i, b);
+		a = Y_QUANTABLE[j] | ((unsigned)(Y_QUANTABLE[j + 1]) << 8);
+		b = UV_QUANTABLE[j] | ((unsigned)(UV_QUANTABLE[j + 1]) << 8);
+		reg_w(sd, 0x40 + i, a);
+		reg_w(sd, 0x60 + i, b);
 	}
-	ret += reg_w(sd, 0x39, 0x0012); /* JPEG encoder enable */
-
-	return ret;
+	reg_w(sd, 0x39, 0x0012); /* JPEG encoder enable */
 }
 
 /****************************************************************************
@@ -168,50 +173,39 @@ static int w9968cf_upload_quantizationta
  * i2c_adap_read_byte()                                                     *
  ****************************************************************************/
 
-static int w9968cf_smbus_start(struct sd *sd)
+static void w9968cf_smbus_start(struct sd *sd)
 {
-	int ret = 0;
-
-	ret += w9968cf_write_sb(sd, 0x0011); /* SDE=1, SDA=0, SCL=1 */
-	ret += w9968cf_write_sb(sd, 0x0010); /* SDE=1, SDA=0, SCL=0 */
-
-	return ret;
+	w9968cf_write_sb(sd, 0x0011); /* SDE=1, SDA=0, SCL=1 */
+	w9968cf_write_sb(sd, 0x0010); /* SDE=1, SDA=0, SCL=0 */
 }
 
-static int w9968cf_smbus_stop(struct sd *sd)
+static void w9968cf_smbus_stop(struct sd *sd)
 {
-	int ret = 0;
-
-	ret += w9968cf_write_sb(sd, 0x0010); /* SDE=1, SDA=0, SCL=0 */
-	ret += w9968cf_write_sb(sd, 0x0011); /* SDE=1, SDA=0, SCL=1 */
-	ret += w9968cf_write_sb(sd, 0x0013); /* SDE=1, SDA=1, SCL=1 */
-
-	return ret;
+	w9968cf_write_sb(sd, 0x0010); /* SDE=1, SDA=0, SCL=0 */
+	w9968cf_write_sb(sd, 0x0011); /* SDE=1, SDA=0, SCL=1 */
+	w9968cf_write_sb(sd, 0x0013); /* SDE=1, SDA=1, SCL=1 */
 }
 
-static int w9968cf_smbus_write_byte(struct sd *sd, u8 v)
+static void w9968cf_smbus_write_byte(struct sd *sd, u8 v)
 {
 	u8 bit;
-	int ret = 0, sda;
+	int sda;
 
 	for (bit = 0 ; bit < 8 ; bit++) {
 		sda = (v & 0x80) ? 2 : 0;
 		v <<= 1;
 		/* SDE=1, SDA=sda, SCL=0 */
-		ret += w9968cf_write_sb(sd, 0x10 | sda);
+		w9968cf_write_sb(sd, 0x10 | sda);
 		/* SDE=1, SDA=sda, SCL=1 */
-		ret += w9968cf_write_sb(sd, 0x11 | sda);
+		w9968cf_write_sb(sd, 0x11 | sda);
 		/* SDE=1, SDA=sda, SCL=0 */
-		ret += w9968cf_write_sb(sd, 0x10 | sda);
+		w9968cf_write_sb(sd, 0x10 | sda);
 	}
-
-	return ret;
 }
 
-static int w9968cf_smbus_read_byte(struct sd *sd, u8* v)
+static void w9968cf_smbus_read_byte(struct sd *sd, u8 *v)
 {
 	u8 bit;
-	int ret = 0;
 
 	/* No need to ensure SDA is high as we are always called after
 	   read_ack which ends with SDA high */
@@ -219,51 +213,40 @@ static int w9968cf_smbus_read_byte(struc
 	for (bit = 0 ; bit < 8 ; bit++) {
 		*v <<= 1;
 		/* SDE=1, SDA=1, SCL=1 */
-		ret += w9968cf_write_sb(sd, 0x0013);
+		w9968cf_write_sb(sd, 0x0013);
 		*v |= (w9968cf_read_sb(sd) & 0x0008) ? 1 : 0;
 		/* SDE=1, SDA=1, SCL=0 */
-		ret += w9968cf_write_sb(sd, 0x0012);
+		w9968cf_write_sb(sd, 0x0012);
 	}
-
-	return ret;
 }
 
-static int w9968cf_smbus_write_nack(struct sd *sd)
+static void w9968cf_smbus_write_nack(struct sd *sd)
 {
-	int ret = 0;
-
 	/* No need to ensure SDA is high as we are always called after
 	   read_byte which ends with SDA high */
-	ret += w9968cf_write_sb(sd, 0x0013); /* SDE=1, SDA=1, SCL=1 */
-	ret += w9968cf_write_sb(sd, 0x0012); /* SDE=1, SDA=1, SCL=0 */
-
-	return ret;
+	w9968cf_write_sb(sd, 0x0013); /* SDE=1, SDA=1, SCL=1 */
+	w9968cf_write_sb(sd, 0x0012); /* SDE=1, SDA=1, SCL=0 */
 }
 
-static int w9968cf_smbus_read_ack(struct sd *sd)
+static void w9968cf_smbus_read_ack(struct sd *sd)
 {
-	int ret = 0, sda;
+	int sda;
 
 	/* Ensure SDA is high before raising clock to avoid a spurious stop */
-	ret += w9968cf_write_sb(sd, 0x0012); /* SDE=1, SDA=1, SCL=0 */
-	ret += w9968cf_write_sb(sd, 0x0013); /* SDE=1, SDA=1, SCL=1 */
+	w9968cf_write_sb(sd, 0x0012); /* SDE=1, SDA=1, SCL=0 */
+	w9968cf_write_sb(sd, 0x0013); /* SDE=1, SDA=1, SCL=1 */
 	sda = w9968cf_read_sb(sd);
-	ret += w9968cf_write_sb(sd, 0x0012); /* SDE=1, SDA=1, SCL=0 */
-	if (sda < 0)
-		ret += sda;
-	else if (sda & 0x08) {
+	w9968cf_write_sb(sd, 0x0012); /* SDE=1, SDA=1, SCL=0 */
+	if (sda >= 0 && (sda & 0x08)) {
 		PDEBUG(D_USBI, "Did not receive i2c ACK");
-		ret += -1;
+		sd->gspca_dev.usb_err = -EIO;
 	}
-
-	return ret;
 }
 
 /* SMBus protocol: S Addr Wr [A] Subaddr [A] Value [A] P */
-static int w9968cf_i2c_w(struct sd *sd, u8 reg, u8 value)
+static void w9968cf_i2c_w(struct sd *sd, u8 reg, u8 value)
 {
 	u16* data = (u16 *)sd->gspca_dev.usb_buf;
-	int ret = 0;
 
 	data[0] = 0x082f | ((sd->sensor_addr & 0x80) ? 0x1500 : 0x0);
 	data[0] |= (sd->sensor_addr & 0x40) ? 0x4000 : 0x0;
@@ -276,7 +259,7 @@ static int w9968cf_i2c_w(struct sd *sd,
 	data[3] = 0x1d20 | ((sd->sensor_addr & 0x02) ? 0x0001 : 0x0);
 	data[3] |= (sd->sensor_addr & 0x01) ? 0x0054 : 0x0;
 
-	ret += w9968cf_write_fsb(sd, data);
+	w9968cf_write_fsb(sd, data);
 
 	data[0] = 0x8208 | ((reg & 0x80) ? 0x0015 : 0x0);
 	data[0] |= (reg & 0x40) ? 0x0540 : 0x0;
@@ -290,7 +273,7 @@ static int w9968cf_i2c_w(struct sd *sd,
 	data[2] |= (reg & 0x01) ? 0x5400 : 0x0;
 	data[3] = 0x001d;
 
-	ret += w9968cf_write_fsb(sd, data);
+	w9968cf_write_fsb(sd, data);
 
 	data[0] = 0x8208 | ((value & 0x80) ? 0x0015 : 0x0);
 	data[0] |= (value & 0x40) ? 0x0540 : 0x0;
@@ -304,14 +287,9 @@ static int w9968cf_i2c_w(struct sd *sd,
 	data[2] |= (value & 0x01) ? 0x5400 : 0x0;
 	data[3] = 0xfe1d;
 
-	ret += w9968cf_write_fsb(sd, data);
-
-	if (!ret)
-		PDEBUG(D_USBO, "i2c 0x%02x -> [0x%02x]", value, reg);
-	else
-		PDEBUG(D_ERR, "i2c 0x%02x -> [0x%02x] failed", value, reg);
+	w9968cf_write_fsb(sd, data);
 
-	return ret;
+	PDEBUG(D_USBO, "i2c 0x%02x -> [0x%02x]", value, reg);
 }
 
 /* SMBus protocol: S Addr Wr [A] Subaddr [A] P S Addr+1 Rd [A] [Value] NA P */
@@ -321,28 +299,28 @@ static int w9968cf_i2c_r(struct sd *sd,
 	u8 value;
 
 	/* Fast serial bus data control disable */
-	ret += w9968cf_write_sb(sd, 0x0013); /* don't change ! */
+	w9968cf_write_sb(sd, 0x0013); /* don't change ! */
 
-	ret += w9968cf_smbus_start(sd);
-	ret += w9968cf_smbus_write_byte(sd, sd->sensor_addr);
-	ret += w9968cf_smbus_read_ack(sd);
-	ret += w9968cf_smbus_write_byte(sd, reg);
-	ret += w9968cf_smbus_read_ack(sd);
-	ret += w9968cf_smbus_stop(sd);
-	ret += w9968cf_smbus_start(sd);
-	ret += w9968cf_smbus_write_byte(sd, sd->sensor_addr + 1);
-	ret += w9968cf_smbus_read_ack(sd);
-	ret += w9968cf_smbus_read_byte(sd, &value);
+	w9968cf_smbus_start(sd);
+	w9968cf_smbus_write_byte(sd, sd->sensor_addr);
+	w9968cf_smbus_read_ack(sd);
+	w9968cf_smbus_write_byte(sd, reg);
+	w9968cf_smbus_read_ack(sd);
+	w9968cf_smbus_stop(sd);
+	w9968cf_smbus_start(sd);
+	w9968cf_smbus_write_byte(sd, sd->sensor_addr + 1);
+	w9968cf_smbus_read_ack(sd);
+	w9968cf_smbus_read_byte(sd, &value);
 	/* signal we don't want to read anymore, the v4l1 driver used to
 	   send an ack here which is very wrong! (and then fixed
 	   the issues this gave by retrying reads) */
-	ret += w9968cf_smbus_write_nack(sd);
-	ret += w9968cf_smbus_stop(sd);
+	w9968cf_smbus_write_nack(sd);
+	w9968cf_smbus_stop(sd);
 
 	/* Fast serial bus data control re-enable */
-	ret += w9968cf_write_sb(sd, 0x0030);
+	w9968cf_write_sb(sd, 0x0030);
 
-	if (!ret) {
+	if (sd->gspca_dev.usb_err >= 0) {
 		ret = value;
 		PDEBUG(D_USBI, "i2c [0x%02X] -> 0x%02X", reg, value);
 	} else
@@ -351,79 +329,68 @@ static int w9968cf_i2c_r(struct sd *sd,
 	return ret;
 }
 
-
 /*--------------------------------------------------------------------------
   Turn on the LED on some webcams. A beep should be heard too.
   Return 0 on success, a negative number otherwise.
   --------------------------------------------------------------------------*/
-static int w9968cf_configure(struct sd *sd)
+static void w9968cf_configure(struct sd *sd)
 {
-	int ret = 0;
-
-	ret += reg_w(sd, 0x00, 0xff00); /* power-down */
-	ret += reg_w(sd, 0x00, 0xbf17); /* reset everything */
-	ret += reg_w(sd, 0x00, 0xbf10); /* normal operation */
-	ret += reg_w(sd, 0x01, 0x0010); /* serial bus, SDS high */
-	ret += reg_w(sd, 0x01, 0x0000); /* serial bus, SDS low */
-	ret += reg_w(sd, 0x01, 0x0010); /* ..high 'beep-beep' */
-	ret += reg_w(sd, 0x01, 0x0030); /* Set sda scl to FSB mode */
-
-	if (ret)
-		PDEBUG(D_ERR, "Couldn't turn on the LED");
+	reg_w(sd, 0x00, 0xff00); /* power-down */
+	reg_w(sd, 0x00, 0xbf17); /* reset everything */
+	reg_w(sd, 0x00, 0xbf10); /* normal operation */
+	reg_w(sd, 0x01, 0x0010); /* serial bus, SDS high */
+	reg_w(sd, 0x01, 0x0000); /* serial bus, SDS low */
+	reg_w(sd, 0x01, 0x0010); /* ..high 'beep-beep' */
+	reg_w(sd, 0x01, 0x0030); /* Set sda scl to FSB mode */
 
 	sd->stopped = 1;
-
-	return ret;
 }
 
-static int w9968cf_init(struct sd *sd)
+static void w9968cf_init(struct sd *sd)
 {
-	int ret = 0;
 	unsigned long hw_bufsize = sd->sif ? (352 * 288 * 2) : (640 * 480 * 2),
 		      y0 = 0x0000,
-		      u0 = y0 + hw_bufsize/2,
-		      v0 = u0 + hw_bufsize/4,
-		      y1 = v0 + hw_bufsize/4,
-		      u1 = y1 + hw_bufsize/2,
-		      v1 = u1 + hw_bufsize/4;
-
-	ret += reg_w(sd, 0x00, 0xff00); /* power off */
-	ret += reg_w(sd, 0x00, 0xbf10); /* power on */
+		      u0 = y0 + hw_bufsize / 2,
+		      v0 = u0 + hw_bufsize / 4,
+		      y1 = v0 + hw_bufsize / 4,
+		      u1 = y1 + hw_bufsize / 2,
+		      v1 = u1 + hw_bufsize / 4;
 
-	ret += reg_w(sd, 0x03, 0x405d); /* DRAM timings */
-	ret += reg_w(sd, 0x04, 0x0030); /* SDRAM timings */
+	reg_w(sd, 0x00, 0xff00); /* power off */
+	reg_w(sd, 0x00, 0xbf10); /* power on */
 
-	ret += reg_w(sd, 0x20, y0 & 0xffff); /* Y buf.0, low */
-	ret += reg_w(sd, 0x21, y0 >> 16);    /* Y buf.0, high */
-	ret += reg_w(sd, 0x24, u0 & 0xffff); /* U buf.0, low */
-	ret += reg_w(sd, 0x25, u0 >> 16);    /* U buf.0, high */
-	ret += reg_w(sd, 0x28, v0 & 0xffff); /* V buf.0, low */
-	ret += reg_w(sd, 0x29, v0 >> 16);    /* V buf.0, high */
+	reg_w(sd, 0x03, 0x405d); /* DRAM timings */
+	reg_w(sd, 0x04, 0x0030); /* SDRAM timings */
 
-	ret += reg_w(sd, 0x22, y1 & 0xffff); /* Y buf.1, low */
-	ret += reg_w(sd, 0x23, y1 >> 16);    /* Y buf.1, high */
-	ret += reg_w(sd, 0x26, u1 & 0xffff); /* U buf.1, low */
-	ret += reg_w(sd, 0x27, u1 >> 16);    /* U buf.1, high */
-	ret += reg_w(sd, 0x2a, v1 & 0xffff); /* V buf.1, low */
-	ret += reg_w(sd, 0x2b, v1 >> 16);    /* V buf.1, high */
+	reg_w(sd, 0x20, y0 & 0xffff); /* Y buf.0, low */
+	reg_w(sd, 0x21, y0 >> 16);    /* Y buf.0, high */
+	reg_w(sd, 0x24, u0 & 0xffff); /* U buf.0, low */
+	reg_w(sd, 0x25, u0 >> 16);    /* U buf.0, high */
+	reg_w(sd, 0x28, v0 & 0xffff); /* V buf.0, low */
+	reg_w(sd, 0x29, v0 >> 16);    /* V buf.0, high */
 
-	ret += reg_w(sd, 0x32, y1 & 0xffff); /* JPEG buf 0 low */
-	ret += reg_w(sd, 0x33, y1 >> 16);    /* JPEG buf 0 high */
+	reg_w(sd, 0x22, y1 & 0xffff); /* Y buf.1, low */
+	reg_w(sd, 0x23, y1 >> 16);    /* Y buf.1, high */
+	reg_w(sd, 0x26, u1 & 0xffff); /* U buf.1, low */
+	reg_w(sd, 0x27, u1 >> 16);    /* U buf.1, high */
+	reg_w(sd, 0x2a, v1 & 0xffff); /* V buf.1, low */
+	reg_w(sd, 0x2b, v1 >> 16);    /* V buf.1, high */
 
-	ret += reg_w(sd, 0x34, y1 & 0xffff); /* JPEG buf 1 low */
-	ret += reg_w(sd, 0x35, y1 >> 16);    /* JPEG bug 1 high */
+	reg_w(sd, 0x32, y1 & 0xffff); /* JPEG buf 0 low */
+	reg_w(sd, 0x33, y1 >> 16);    /* JPEG buf 0 high */
 
-	ret += reg_w(sd, 0x36, 0x0000);/* JPEG restart interval */
-	ret += reg_w(sd, 0x37, 0x0804);/*JPEG VLE FIFO threshold*/
-	ret += reg_w(sd, 0x38, 0x0000);/* disable hw up-scaling */
-	ret += reg_w(sd, 0x3f, 0x0000); /* JPEG/MCTL test data */
+	reg_w(sd, 0x34, y1 & 0xffff); /* JPEG buf 1 low */
+	reg_w(sd, 0x35, y1 >> 16);    /* JPEG bug 1 high */
 
-	return ret;
+	reg_w(sd, 0x36, 0x0000);/* JPEG restart interval */
+	reg_w(sd, 0x37, 0x0804);/*JPEG VLE FIFO threshold*/
+	reg_w(sd, 0x38, 0x0000);/* disable hw up-scaling */
+	reg_w(sd, 0x3f, 0x0000); /* JPEG/MCTL test data */
 }
 
-static int w9968cf_set_crop_window(struct sd *sd)
+static void w9968cf_set_crop_window(struct sd *sd)
 {
-	int ret = 0, start_cropx, start_cropy,  x, y, fw, fh, cw, ch,
+	int start_cropx, start_cropy,  x, y, fw, fh, cw, ch,
 	    max_width, max_height;
 
 	if (sd->sif) {
@@ -456,8 +423,8 @@ static int w9968cf_set_crop_window(struc
 	fw = SC(sd->gspca_dev.width) / max_width;
 	fh = SC(sd->gspca_dev.height) / max_height;
 
-	cw = (fw >= fh) ? max_width : SC(sd->gspca_dev.width)/fh;
-	ch = (fw >= fh) ? SC(sd->gspca_dev.height)/fw : max_height;
+	cw = (fw >= fh) ? max_width : SC(sd->gspca_dev.width) / fh;
+	ch = (fw >= fh) ? SC(sd->gspca_dev.height) / fw : max_height;
 
 	sd->sensor_width = max_width;
 	sd->sensor_height = max_height;
@@ -465,42 +432,40 @@ static int w9968cf_set_crop_window(struc
 	x = (max_width - cw) / 2;
 	y = (max_height - ch) / 2;
 
-	ret += reg_w(sd, 0x10, start_cropx + x);
-	ret += reg_w(sd, 0x11, start_cropy + y);
-	ret += reg_w(sd, 0x12, start_cropx + x + cw);
-	ret += reg_w(sd, 0x13, start_cropy + y + ch);
-
-	return ret;
+	reg_w(sd, 0x10, start_cropx + x);
+	reg_w(sd, 0x11, start_cropy + y);
+	reg_w(sd, 0x12, start_cropx + x + cw);
+	reg_w(sd, 0x13, start_cropy + y + ch);
 }
 
-static int w9968cf_mode_init_regs(struct sd *sd)
+static void w9968cf_mode_init_regs(struct sd *sd)
 {
-	int ret = 0, val, vs_polarity, hs_polarity;
+	int val, vs_polarity, hs_polarity;
 
-	ret += w9968cf_set_crop_window(sd);
+	w9968cf_set_crop_window(sd);
 
-	ret += reg_w(sd, 0x14, sd->gspca_dev.width);
-	ret += reg_w(sd, 0x15, sd->gspca_dev.height);
+	reg_w(sd, 0x14, sd->gspca_dev.width);
+	reg_w(sd, 0x15, sd->gspca_dev.height);
 
 	/* JPEG width & height */
-	ret += reg_w(sd, 0x30, sd->gspca_dev.width);
-	ret += reg_w(sd, 0x31, sd->gspca_dev.height);
+	reg_w(sd, 0x30, sd->gspca_dev.width);
+	reg_w(sd, 0x31, sd->gspca_dev.height);
 
 	/* Y & UV frame buffer strides (in WORD) */
 	if (w9968cf_vga_mode[sd->gspca_dev.curr_mode].pixelformat ==
 	    V4L2_PIX_FMT_JPEG) {
-		ret += reg_w(sd, 0x2c, sd->gspca_dev.width/2);
-		ret += reg_w(sd, 0x2d, sd->gspca_dev.width/4);
+		reg_w(sd, 0x2c, sd->gspca_dev.width / 2);
+		reg_w(sd, 0x2d, sd->gspca_dev.width / 4);
 	} else
-		ret += reg_w(sd, 0x2c, sd->gspca_dev.width);
+		reg_w(sd, 0x2c, sd->gspca_dev.width);
 
-	ret += reg_w(sd, 0x00, 0xbf17); /* reset everything */
-	ret += reg_w(sd, 0x00, 0xbf10); /* normal operation */
+	reg_w(sd, 0x00, 0xbf17); /* reset everything */
+	reg_w(sd, 0x00, 0xbf10); /* normal operation */
 
 	/* Transfer size in WORDS (for UYVY format only) */
 	val = sd->gspca_dev.width * sd->gspca_dev.height;
-	ret += reg_w(sd, 0x3d, val & 0xffff); /* low bits */
-	ret += reg_w(sd, 0x3e, val >> 16);    /* high bits */
+	reg_w(sd, 0x3d, val & 0xffff); /* low bits */
+	reg_w(sd, 0x3e, val >> 16);    /* high bits */
 
 	if (w9968cf_vga_mode[sd->gspca_dev.curr_mode].pixelformat ==
 	    V4L2_PIX_FMT_JPEG) {
@@ -508,7 +473,7 @@ static int w9968cf_mode_init_regs(struct
 		jpeg_define(sd->jpeg_hdr, sd->gspca_dev.height,
 			    sd->gspca_dev.width, 0x22); /* JPEG 420 */
 		jpeg_set_qual(sd->jpeg_hdr, sd->quality);
-		ret += w9968cf_upload_quantizationtables(sd);
+		w9968cf_upload_quantizationtables(sd);
 	}
 
 	/* Video Capture Control Register */
@@ -540,19 +505,15 @@ static int w9968cf_mode_init_regs(struct
 
 	val |= 0x8000; /* capt. enable */
 
-	ret += reg_w(sd, 0x16, val);
+	reg_w(sd, 0x16, val);
 
 	sd->gspca_dev.empty_packet = 0;
-
-	return ret;
 }
 
 static void w9968cf_stop0(struct sd *sd)
 {
-	if (sd->gspca_dev.present) {
-		reg_w(sd, 0x39, 0x0000); /* disable JPEG encoder */
-		reg_w(sd, 0x16, 0x0000); /* stop video capture */
-	}
+	reg_w(sd, 0x39, 0x0000); /* disable JPEG encoder */
+	reg_w(sd, 0x16, 0x0000); /* stop video capture */
 }
 
 /* The w9968cf docs say that a 0 sized packet means EOF (and also SOF
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/gspca/xirlink_cit.c linux-libre-2.6.38-gnu1/drivers/media/video/gspca/xirlink_cit.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/gspca/xirlink_cit.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/gspca/xirlink_cit.c	2011-03-14 21:20:32.000000000 -0400
@@ -29,6 +29,7 @@
 
 #define MODULE_NAME "xirlink-cit"
 
+#include <linux/input.h>
 #include "gspca.h"
 
 MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
@@ -58,6 +59,7 @@ struct sd {
 #define CIT_MODEL4 4
 #define CIT_IBM_NETCAM_PRO 5
 	u8 input_index;
+	u8 button_state;
 	u8 stop_on_control_change;
 	u8 sof_read;
 	u8 sof_len;
@@ -185,60 +187,60 @@ static const struct ctrl sd_ctrls[] = {
 static const struct v4l2_pix_format cif_yuv_mode[] = {
 	{176, 144, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE,
 		.bytesperline = 176,
-		.sizeimage = 176 * 144 * 3 / 2,
+		.sizeimage = 176 * 144 * 3 / 2 + 4,
 		.colorspace = V4L2_COLORSPACE_SRGB},
 	{352, 288, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE,
 		.bytesperline = 352,
-		.sizeimage = 352 * 288 * 3 / 2,
+		.sizeimage = 352 * 288 * 3 / 2 + 4,
 		.colorspace = V4L2_COLORSPACE_SRGB},
 };
 
 static const struct v4l2_pix_format vga_yuv_mode[] = {
 	{160, 120, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE,
 		.bytesperline = 160,
-		.sizeimage = 160 * 120 * 3 / 2,
+		.sizeimage = 160 * 120 * 3 / 2 + 4,
 		.colorspace = V4L2_COLORSPACE_SRGB},
 	{320, 240, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE,
 		.bytesperline = 320,
-		.sizeimage = 320 * 240 * 3 / 2,
+		.sizeimage = 320 * 240 * 3 / 2 + 4,
 		.colorspace = V4L2_COLORSPACE_SRGB},
 	{640, 480, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE,
 		.bytesperline = 640,
-		.sizeimage = 640 * 480 * 3 / 2,
+		.sizeimage = 640 * 480 * 3 / 2 + 4,
 		.colorspace = V4L2_COLORSPACE_SRGB},
 };
 
 static const struct v4l2_pix_format model0_mode[] = {
 	{160, 120, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE,
 		.bytesperline = 160,
-		.sizeimage = 160 * 120 * 3 / 2,
+		.sizeimage = 160 * 120 * 3 / 2 + 4,
 		.colorspace = V4L2_COLORSPACE_SRGB},
 	{176, 144, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE,
 		.bytesperline = 176,
-		.sizeimage = 176 * 144 * 3 / 2,
+		.sizeimage = 176 * 144 * 3 / 2 + 4,
 		.colorspace = V4L2_COLORSPACE_SRGB},
 	{320, 240, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE,
 		.bytesperline = 320,
-		.sizeimage = 320 * 240 * 3 / 2,
+		.sizeimage = 320 * 240 * 3 / 2 + 4,
 		.colorspace = V4L2_COLORSPACE_SRGB},
 };
 
 static const struct v4l2_pix_format model2_mode[] = {
 	{160, 120, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE,
 		.bytesperline = 160,
-		.sizeimage = 160 * 120 * 3 / 2,
+		.sizeimage = 160 * 120 * 3 / 2 + 4,
 		.colorspace = V4L2_COLORSPACE_SRGB},
 	{176, 144, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE,
 		.bytesperline = 176,
-		.sizeimage = 176 * 144 * 3 / 2,
+		.sizeimage = 176 * 144 * 3 / 2 + 4,
 		.colorspace = V4L2_COLORSPACE_SRGB},
 	{320, 240, V4L2_PIX_FMT_SGRBG8, V4L2_FIELD_NONE,
 		.bytesperline = 320,
-		.sizeimage = 320 * 240,
+		.sizeimage = 320 * 240 + 4,
 		.colorspace = V4L2_COLORSPACE_SRGB},
 	{352, 288, V4L2_PIX_FMT_SGRBG8, V4L2_FIELD_NONE,
 		.bytesperline = 352,
-		.sizeimage = 352 * 288,
+		.sizeimage = 352 * 288 + 4,
 		.colorspace = V4L2_COLORSPACE_SRGB},
 };
 
@@ -804,7 +806,7 @@ static int cit_write_reg(struct gspca_de
 	return 0;
 }
 
-static int cit_read_reg(struct gspca_dev *gspca_dev, u16 index)
+static int cit_read_reg(struct gspca_dev *gspca_dev, u16 index, int verbose)
 {
 	struct usb_device *udev = gspca_dev->dev;
 	__u8 *buf = gspca_dev->usb_buf;
@@ -819,10 +821,8 @@ static int cit_read_reg(struct gspca_dev
 		return res;
 	}
 
-	PDEBUG(D_PROBE,
-	       "Register %04x value: %02x %02x %02x %02x %02x %02x %02x %02x",
-	       index,
-	       buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]);
+	if (verbose)
+		PDEBUG(D_PROBE, "Register %04x value: %02x", index, buf[0]);
 
 	return 0;
 }
@@ -907,7 +907,7 @@ static void cit_Packet_Format1(struct gs
 	cit_send_x_00_05(gspca_dev, 0x0089);
 	cit_send_x_00(gspca_dev, fkey);
 	cit_send_00_04_06(gspca_dev);
-	cit_read_reg(gspca_dev, 0x0126);
+	cit_read_reg(gspca_dev, 0x0126, 0);
 	cit_send_FF_04_02(gspca_dev);
 }
 
@@ -1074,12 +1074,12 @@ static int cit_init_model0(struct gspca_
 
 static int cit_init_ibm_netcam_pro(struct gspca_dev *gspca_dev)
 {
-	cit_read_reg(gspca_dev, 0x128);
+	cit_read_reg(gspca_dev, 0x128, 1);
 	cit_write_reg(gspca_dev, 0x0003, 0x0133);
 	cit_write_reg(gspca_dev, 0x0000, 0x0117);
 	cit_write_reg(gspca_dev, 0x0008, 0x0123);
 	cit_write_reg(gspca_dev, 0x0000, 0x0100);
-	cit_read_reg(gspca_dev, 0x0116);
+	cit_read_reg(gspca_dev, 0x0116, 0);
 	cit_write_reg(gspca_dev, 0x0060, 0x0116);
 	cit_write_reg(gspca_dev, 0x0002, 0x0112);
 	cit_write_reg(gspca_dev, 0x0000, 0x0133);
@@ -1098,7 +1098,7 @@ static int cit_init_ibm_netcam_pro(struc
 	cit_write_reg(gspca_dev, 0x00ff, 0x0130);
 	cit_write_reg(gspca_dev, 0xcd41, 0x0124);
 	cit_write_reg(gspca_dev, 0xfffa, 0x0124);
-	cit_read_reg(gspca_dev, 0x0126);
+	cit_read_reg(gspca_dev, 0x0126, 1);
 
 	cit_model3_Packet1(gspca_dev, 0x0000, 0x0000);
 	cit_model3_Packet1(gspca_dev, 0x0000, 0x0001);
@@ -1557,18 +1557,20 @@ static int cit_restart_stream(struct gsp
 	switch (sd->model) {
 	case CIT_MODEL0:
 	case CIT_MODEL1:
-	case CIT_MODEL3:
-	case CIT_IBM_NETCAM_PRO:
 		cit_write_reg(gspca_dev, 0x0001, 0x0114);
 		/* Fall through */
 	case CIT_MODEL2:
 	case CIT_MODEL4:
 		cit_write_reg(gspca_dev, 0x00c0, 0x010c); /* Go! */
 		usb_clear_halt(gspca_dev->dev, gspca_dev->urb[0]->pipe);
-		/* This happens repeatedly while streaming with the ibm netcam
-		   pro and the ibmcam driver did it for model3 after changing
-		   settings, but it does not seem to have any effect. */
-		/* cit_write_reg(gspca_dev, 0x0001, 0x0113); */
+		break;
+	case CIT_MODEL3:
+	case CIT_IBM_NETCAM_PRO:
+		cit_write_reg(gspca_dev, 0x0001, 0x0114);
+		cit_write_reg(gspca_dev, 0x00c0, 0x010c); /* Go! */
+		usb_clear_halt(gspca_dev->dev, gspca_dev->urb[0]->pipe);
+		/* Clear button events from while we were not streaming */
+		cit_write_reg(gspca_dev, 0x0001, 0x0113);
 		break;
 	}
 
@@ -1680,23 +1682,23 @@ static int cit_start_model1(struct gspca
 	if (clock_div < 0)
 		return clock_div;
 
-	cit_read_reg(gspca_dev, 0x0128);
-	cit_read_reg(gspca_dev, 0x0100);
+	cit_read_reg(gspca_dev, 0x0128, 1);
+	cit_read_reg(gspca_dev, 0x0100, 0);
 	cit_write_reg(gspca_dev, 0x01, 0x0100);	/* LED On  */
-	cit_read_reg(gspca_dev, 0x0100);
+	cit_read_reg(gspca_dev, 0x0100, 0);
 	cit_write_reg(gspca_dev, 0x81, 0x0100);	/* LED Off */
-	cit_read_reg(gspca_dev, 0x0100);
+	cit_read_reg(gspca_dev, 0x0100, 0);
 	cit_write_reg(gspca_dev, 0x01, 0x0100);	/* LED On  */
 	cit_write_reg(gspca_dev, 0x01, 0x0108);
 
 	cit_write_reg(gspca_dev, 0x03, 0x0112);
-	cit_read_reg(gspca_dev, 0x0115);
+	cit_read_reg(gspca_dev, 0x0115, 0);
 	cit_write_reg(gspca_dev, 0x06, 0x0115);
-	cit_read_reg(gspca_dev, 0x0116);
+	cit_read_reg(gspca_dev, 0x0116, 0);
 	cit_write_reg(gspca_dev, 0x44, 0x0116);
-	cit_read_reg(gspca_dev, 0x0116);
+	cit_read_reg(gspca_dev, 0x0116, 0);
 	cit_write_reg(gspca_dev, 0x40, 0x0116);
-	cit_read_reg(gspca_dev, 0x0115);
+	cit_read_reg(gspca_dev, 0x0115, 0);
 	cit_write_reg(gspca_dev, 0x0e, 0x0115);
 	cit_write_reg(gspca_dev, 0x19, 0x012c);
 
@@ -1878,7 +1880,7 @@ static int cit_start_model2(struct gspca
 	int clock_div = 0;
 
 	cit_write_reg(gspca_dev, 0x0000, 0x0100);	/* LED on */
-	cit_read_reg(gspca_dev, 0x0116);
+	cit_read_reg(gspca_dev, 0x0116, 0);
 	cit_write_reg(gspca_dev, 0x0060, 0x0116);
 	cit_write_reg(gspca_dev, 0x0002, 0x0112);
 	cit_write_reg(gspca_dev, 0x00bc, 0x012c);
@@ -2070,10 +2072,10 @@ static int cit_start_model3(struct gspca
 
 	/* HDG not in ibmcam driver, added to see if it helps with
 	   auto-detecting between model3 and ibm netcamera pro */
-	cit_read_reg(gspca_dev, 0x128);
+	cit_read_reg(gspca_dev, 0x128, 1);
 
 	cit_write_reg(gspca_dev, 0x0000, 0x0100);
-	cit_read_reg(gspca_dev, 0x0116);
+	cit_read_reg(gspca_dev, 0x0116, 0);
 	cit_write_reg(gspca_dev, 0x0060, 0x0116);
 	cit_write_reg(gspca_dev, 0x0002, 0x0112);
 	cit_write_reg(gspca_dev, 0x0000, 0x0123);
@@ -2083,7 +2085,7 @@ static int cit_start_model3(struct gspca
 	cit_write_reg(gspca_dev, 0x0060, 0x0116);
 	cit_write_reg(gspca_dev, 0x0002, 0x0115);
 	cit_write_reg(gspca_dev, 0x0003, 0x0115);
-	cit_read_reg(gspca_dev, 0x0115);
+	cit_read_reg(gspca_dev, 0x0115, 0);
 	cit_write_reg(gspca_dev, 0x000b, 0x0115);
 
 	/* TESTME HDG not in ibmcam driver, added to see if it helps with
@@ -2096,7 +2098,7 @@ static int cit_start_model3(struct gspca
 		cit_write_reg(gspca_dev, 0x00ff, 0x0130);
 		cit_write_reg(gspca_dev, 0xcd41, 0x0124);
 		cit_write_reg(gspca_dev, 0xfffa, 0x0124);
-		cit_read_reg(gspca_dev, 0x0126);
+		cit_read_reg(gspca_dev, 0x0126, 1);
 	}
 
 	cit_model3_Packet1(gspca_dev, 0x000a, 0x0040);
@@ -2293,7 +2295,7 @@ static int cit_start_model3(struct gspca
 	if (rca_input) {
 		for (i = 0; i < ARRAY_SIZE(rca_initdata); i++) {
 			if (rca_initdata[i][0])
-				cit_read_reg(gspca_dev, rca_initdata[i][2]);
+				cit_read_reg(gspca_dev, rca_initdata[i][2], 0);
 			else
 				cit_write_reg(gspca_dev, rca_initdata[i][1],
 					      rca_initdata[i][2]);
@@ -2712,7 +2714,7 @@ static int cit_start_ibm_netcam_pro(stru
 	if (rca_input) {
 		for (i = 0; i < ARRAY_SIZE(rca_initdata); i++) {
 			if (rca_initdata[i][0])
-				cit_read_reg(gspca_dev, rca_initdata[i][2]);
+				cit_read_reg(gspca_dev, rca_initdata[i][2], 0);
 			else
 				cit_write_reg(gspca_dev, rca_initdata[i][1],
 					      rca_initdata[i][2]);
@@ -2769,16 +2771,55 @@ static int sd_start(struct gspca_dev *gs
 	return 0;
 }
 
+static int sd_isoc_init(struct gspca_dev *gspca_dev)
+{
+	struct usb_host_interface *alt;
+	int max_packet_size;
+
+	switch (gspca_dev->width) {
+	case 160:
+		max_packet_size = 450;
+		break;
+	case 176:
+		max_packet_size = 600;
+		break;
+	default:
+		max_packet_size = 1022;
+		break;
+	}
+
+	/* Start isoc bandwidth "negotiation" at max isoc bandwidth */
+	alt = &gspca_dev->dev->config->intf_cache[0]->altsetting[1];
+	alt->endpoint[0].desc.wMaxPacketSize = cpu_to_le16(max_packet_size);
+
+	return 0;
+}
+
 static int sd_isoc_nego(struct gspca_dev *gspca_dev)
 {
-	int ret, packet_size;
+	int ret, packet_size, min_packet_size;
 	struct usb_host_interface *alt;
 
+	switch (gspca_dev->width) {
+	case 160:
+		min_packet_size = 200;
+		break;
+	case 176:
+		min_packet_size = 266;
+		break;
+	default:
+		min_packet_size = 400;
+		break;
+	}
+
 	alt = &gspca_dev->dev->config->intf_cache[0]->altsetting[1];
 	packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
-	packet_size -= 100;
-	if (packet_size < 300)
+	if (packet_size <= min_packet_size)
 		return -EIO;
+
+	packet_size -= 100;
+	if (packet_size < min_packet_size)
+		packet_size = min_packet_size;
 	alt->endpoint[0].desc.wMaxPacketSize = cpu_to_le16(packet_size);
 
 	ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, 1);
@@ -2796,15 +2837,12 @@ static void sd_stopN(struct gspca_dev *g
 static void sd_stop0(struct gspca_dev *gspca_dev)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
-	struct usb_host_interface *alt;
 
 	/* We cannot use gspca_dev->present here as that is not set when
 	   sd_init gets called and we get called from sd_init */
 	if (!gspca_dev->dev)
 		return;
 
-	alt = &gspca_dev->dev->config->intf_cache[0]->altsetting[1];
-
 	switch (sd->model) {
 	case CIT_MODEL0:
 		/* HDG windows does this, but it causes the cams autogain to
@@ -2815,7 +2853,7 @@ static void sd_stop0(struct gspca_dev *g
 		break;
 	case CIT_MODEL1:
 		cit_send_FF_04_02(gspca_dev);
-		cit_read_reg(gspca_dev, 0x0100);
+		cit_read_reg(gspca_dev, 0x0100, 0);
 		cit_write_reg(gspca_dev, 0x81, 0x0100);	/* LED Off */
 		break;
 	case CIT_MODEL2:
@@ -2834,9 +2872,9 @@ static void sd_stop0(struct gspca_dev *g
 	case CIT_MODEL3:
 		cit_write_reg(gspca_dev, 0x0006, 0x012c);
 		cit_model3_Packet1(gspca_dev, 0x0046, 0x0000);
-		cit_read_reg(gspca_dev, 0x0116);
+		cit_read_reg(gspca_dev, 0x0116, 0);
 		cit_write_reg(gspca_dev, 0x0064, 0x0116);
-		cit_read_reg(gspca_dev, 0x0115);
+		cit_read_reg(gspca_dev, 0x0115, 0);
 		cit_write_reg(gspca_dev, 0x0003, 0x0115);
 		cit_write_reg(gspca_dev, 0x0008, 0x0123);
 		cit_write_reg(gspca_dev, 0x0000, 0x0117);
@@ -2859,12 +2897,17 @@ static void sd_stop0(struct gspca_dev *g
 		   restarting the stream after this */
 		/* cit_write_reg(gspca_dev, 0x0000, 0x0112); */
 		cit_write_reg(gspca_dev, 0x00c0, 0x0100);
-
-		/* Start isoc bandwidth "negotiation" at max isoc bandwith
-		   next stream start */
-		alt->endpoint[0].desc.wMaxPacketSize = cpu_to_le16(1022);
 		break;
 	}
+
+#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
+	/* If the last button state is pressed, release it now! */
+	if (sd->button_state) {
+		input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
+		input_sync(gspca_dev->input_dev);
+		sd->button_state = 0;
+	}
+#endif
 }
 
 static u8 *cit_find_sof(struct gspca_dev *gspca_dev, u8 *data, int len)
@@ -3158,6 +3201,38 @@ static int sd_gethflip(struct gspca_dev
 	return 0;
 }
 
+#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
+static void cit_check_button(struct gspca_dev *gspca_dev)
+{
+	int new_button_state;
+	struct sd *sd = (struct sd *)gspca_dev;
+
+	switch (sd->model) {
+	case CIT_MODEL3:
+	case CIT_IBM_NETCAM_PRO:
+		break;
+	default: /* TEST ME unknown if this works on other models too */
+		return;
+	}
+
+	/* Read the button state */
+	cit_read_reg(gspca_dev, 0x0113, 0);
+	new_button_state = !gspca_dev->usb_buf[0];
+
+	/* Tell the cam we've seen the button press, notice that this
+	   is a nop (iow the cam keeps reporting pressed) until the
+	   button is actually released. */
+	if (new_button_state)
+		cit_write_reg(gspca_dev, 0x01, 0x0113);
+
+	if (sd->button_state != new_button_state) {
+		input_report_key(gspca_dev->input_dev, KEY_CAMERA,
+				 new_button_state);
+		input_sync(gspca_dev->input_dev);
+		sd->button_state = new_button_state;
+	}
+}
+#endif
 
 /* sub-driver description */
 static const struct sd_desc sd_desc = {
@@ -3170,6 +3245,10 @@ static const struct sd_desc sd_desc = {
 	.stopN = sd_stopN,
 	.stop0 = sd_stop0,
 	.pkt_scan = sd_pkt_scan,
+#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
+	.dq_callback = cit_check_button,
+	.other_input = 1,
+#endif
 };
 
 static const struct sd_desc sd_desc_isoc_nego = {
@@ -3179,14 +3258,19 @@ static const struct sd_desc sd_desc_isoc
 	.config = sd_config,
 	.init = sd_init,
 	.start = sd_start,
+	.isoc_init = sd_isoc_init,
 	.isoc_nego = sd_isoc_nego,
 	.stopN = sd_stopN,
 	.stop0 = sd_stop0,
 	.pkt_scan = sd_pkt_scan,
+#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
+	.dq_callback = cit_check_button,
+	.other_input = 1,
+#endif
 };
 
 /* -- module initialisation -- */
-static const __devinitdata struct usb_device_id device_table[] = {
+static const struct usb_device_id device_table[] = {
 	{ USB_DEVICE_VER(0x0545, 0x8080, 0x0001, 0x0001), .driver_info = CIT_MODEL0 },
 	{ USB_DEVICE_VER(0x0545, 0x8080, 0x0002, 0x0002), .driver_info = CIT_MODEL1 },
 	{ USB_DEVICE_VER(0x0545, 0x8080, 0x030a, 0x030a), .driver_info = CIT_MODEL2 },
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/gspca/zc3xx.c linux-libre-2.6.38-gnu1/drivers/media/video/gspca/zc3xx.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/gspca/zc3xx.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/gspca/zc3xx.c	2011-03-14 21:20:32.000000000 -0400
@@ -35,16 +35,23 @@ static int force_sensor = -1;
 #define QUANT_VAL 1		/* quantization table */
 #include "zc3xx-reg.h"
 
+/* controls */
+enum e_ctrl {
+	BRIGHTNESS,
+	CONTRAST,
+	GAMMA,
+	AUTOGAIN,
+	LIGHTFREQ,
+	SHARPNESS,
+	NCTRLS		/* number of controls */
+};
+
 /* specific webcam descriptor */
 struct sd {
 	struct gspca_dev gspca_dev;	/* !! must be the first item */
 
-	u8 brightness;
-	u8 contrast;
-	u8 gamma;
-	u8 autogain;
-	u8 lightfreq;
-	u8 sharpness;
+	struct gspca_ctrl ctrls[NCTRLS];
+
 	u8 quality;			/* image quality */
 #define QUALITY_MIN 50
 #define QUALITY_MAX 80
@@ -64,6 +71,7 @@ enum sensors {
 	SENSOR_ADCM2700,
 	SENSOR_CS2102,
 	SENSOR_CS2102K,
+	SENSOR_GC0303,
 	SENSOR_GC0305,
 	SENSOR_HDCS2020b,
 	SENSOR_HV7131B,
@@ -79,26 +87,17 @@ enum sensors {
 	SENSOR_PB0330,
 	SENSOR_PO2030,
 	SENSOR_TAS5130C,
-	SENSOR_TAS5130C_VF0250,
 	SENSOR_MAX
 };
 
 /* 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_setgamma(struct gspca_dev *gspca_dev, __s32 val);
-static int sd_getgamma(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 int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val);
-static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val);
+static void setcontrast(struct gspca_dev *gspca_dev);
+static void setautogain(struct gspca_dev *gspca_dev);
+static void setlightfreq(struct gspca_dev *gspca_dev);
+static void setsharpness(struct gspca_dev *gspca_dev);
 
-static const struct ctrl sd_ctrls[] = {
-	{
+static const struct ctrl sd_ctrls[NCTRLS] = {
+[BRIGHTNESS] = {
 	    {
 		.id      = V4L2_CID_BRIGHTNESS,
 		.type    = V4L2_CTRL_TYPE_INTEGER,
@@ -106,13 +105,11 @@ static const struct ctrl sd_ctrls[] = {
 		.minimum = 0,
 		.maximum = 255,
 		.step    = 1,
-#define BRIGHTNESS_DEF 128
-		.default_value = BRIGHTNESS_DEF,
+		.default_value = 128,
 	    },
-	    .set = sd_setbrightness,
-	    .get = sd_getbrightness,
+	    .set_control = setcontrast
 	},
-	{
+[CONTRAST] = {
 	    {
 		.id      = V4L2_CID_CONTRAST,
 		.type    = V4L2_CTRL_TYPE_INTEGER,
@@ -120,13 +117,11 @@ static const struct ctrl sd_ctrls[] = {
 		.minimum = 0,
 		.maximum = 255,
 		.step    = 1,
-#define CONTRAST_DEF 128
-		.default_value = CONTRAST_DEF,
+		.default_value = 128,
 	    },
-	    .set = sd_setcontrast,
-	    .get = sd_getcontrast,
+	    .set_control = setcontrast
 	},
-	{
+[GAMMA] = {
 	    {
 		.id      = V4L2_CID_GAMMA,
 		.type    = V4L2_CTRL_TYPE_INTEGER,
@@ -136,10 +131,9 @@ static const struct ctrl sd_ctrls[] = {
 		.step    = 1,
 		.default_value = 4,
 	    },
-	    .set = sd_setgamma,
-	    .get = sd_getgamma,
+	    .set_control = setcontrast
 	},
-	{
+[AUTOGAIN] = {
 	    {
 		.id      = V4L2_CID_AUTOGAIN,
 		.type    = V4L2_CTRL_TYPE_BOOLEAN,
@@ -147,14 +141,11 @@ static const struct ctrl sd_ctrls[] = {
 		.minimum = 0,
 		.maximum = 1,
 		.step    = 1,
-#define AUTOGAIN_DEF 1
-		.default_value = AUTOGAIN_DEF,
+		.default_value = 1,
 	    },
-	    .set = sd_setautogain,
-	    .get = sd_getautogain,
+	    .set_control = setautogain
 	},
-#define LIGHTFREQ_IDX 4
-	{
+[LIGHTFREQ] = {
 	    {
 		.id	 = V4L2_CID_POWER_LINE_FREQUENCY,
 		.type    = V4L2_CTRL_TYPE_MENU,
@@ -162,13 +153,11 @@ 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
 	},
-	{
+[SHARPNESS] = {
 	    {
 		.id	 = V4L2_CID_SHARPNESS,
 		.type    = V4L2_CTRL_TYPE_INTEGER,
@@ -176,11 +165,9 @@ static const struct ctrl sd_ctrls[] = {
 		.minimum = 0,
 		.maximum = 3,
 		.step    = 1,
-#define SHARPNESS_DEF 2
-		.default_value = SHARPNESS_DEF,
+		.default_value = 2,
 	    },
-	    .set = sd_setsharpness,
-	    .get = sd_getsharpness,
+	    .set_control = setsharpness
 	},
 };
 
@@ -4499,7 +4486,7 @@ static const struct usb_action mt9v111_3
 	{0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
 	{0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
 	{0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT},
-	{0xa0, 0x04, ZC3XX_R002_CLOCKSELECT},
+	{0xa0, 0x00, ZC3XX_R002_CLOCKSELECT},
 	{0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
 	{0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
 	{0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
@@ -5406,7 +5393,7 @@ static const struct usb_action tas5130c_
 	{}
 };
 
-static const struct usb_action tas5130c_vf0250_InitialScale[] = {
+static const struct usb_action gc0303_InitialScale[] = {
 	{0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},		/* 00,00,01,cc, */
 	{0xa0, 0x02, ZC3XX_R008_CLOCKSETTING},		/* 00,08,02,cc, */
 	{0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT},	/* 00,10,01,cc, */
@@ -5473,7 +5460,7 @@ static const struct usb_action tas5130c_
 	{}
 };
 
-static const struct usb_action tas5130c_vf0250_Initial[] = {
+static const struct usb_action gc0303_Initial[] = {
 	{0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},		/* 00,00,01,cc, */
 	{0xa0, 0x02, ZC3XX_R008_CLOCKSETTING},		/* 00,08,02,cc, */
 	{0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT},	/* 00,10,01,cc, */
@@ -5538,7 +5525,7 @@ static const struct usb_action tas5130c_
 	{0xa0, 0x65, ZC3XX_R118_BGAIN},		/* 01,18,65,cc */
 	{}
 };
-static const struct usb_action tas5130c_vf0250_50HZScale[] = {
+static const struct usb_action gc0303_50HZScale[] = {
 	{0xaa, 0x82, 0x0000},		/* 00,82,00,aa */
 	{0xaa, 0x83, 0x0001},		/* 00,83,01,aa */
 	{0xaa, 0x84, 0x00aa},		/* 00,84,aa,aa */
@@ -5562,7 +5549,7 @@ static const struct usb_action tas5130c_
 	{}
 };
 
-static const struct usb_action tas5130c_vf0250_50HZ[] = {
+static const struct usb_action gc0303_50HZ[] = {
 	{0xaa, 0x82, 0x0000},		/* 00,82,00,aa */
 	{0xaa, 0x83, 0x0003},		/* 00,83,03,aa */
 	{0xaa, 0x84, 0x0054},		/* 00,84,54,aa */
@@ -5586,7 +5573,7 @@ static const struct usb_action tas5130c_
 	{}
 };
 
-static const struct usb_action tas5130c_vf0250_60HZScale[] = {
+static const struct usb_action gc0303_60HZScale[] = {
 	{0xaa, 0x82, 0x0000},		/* 00,82,00,aa */
 	{0xaa, 0x83, 0x0001},		/* 00,83,01,aa */
 	{0xaa, 0x84, 0x0062},		/* 00,84,62,aa */
@@ -5610,7 +5597,7 @@ static const struct usb_action tas5130c_
 	{}
 };
 
-static const struct usb_action tas5130c_vf0250_60HZ[] = {
+static const struct usb_action gc0303_60HZ[] = {
 	{0xaa, 0x82, 0x0000},		/* 00,82,00,aa */
 	{0xaa, 0x83, 0x0002},		/* 00,83,02,aa */
 	{0xaa, 0x84, 0x00c4},		/* 00,84,c4,aa */
@@ -5634,7 +5621,7 @@ static const struct usb_action tas5130c_
 	{}
 };
 
-static const struct usb_action tas5130c_vf0250_NoFlikerScale[] = {
+static const struct usb_action gc0303_NoFlikerScale[] = {
 	{0xa0, 0x0c, ZC3XX_R100_OPERATIONMODE},		/* 01,00,0c,cc, */
 	{0xaa, 0x82, 0x0000},		/* 00,82,00,aa */
 	{0xaa, 0x83, 0x0000},		/* 00,83,00,aa */
@@ -5656,7 +5643,7 @@ static const struct usb_action tas5130c_
 	{}
 };
 
-static const struct usb_action tas5130c_vf0250_NoFliker[] = {
+static const struct usb_action gc0303_NoFliker[] = {
 	{0xa0, 0x0c, ZC3XX_R100_OPERATIONMODE},		/* 01,00,0c,cc, */
 	{0xaa, 0x82, 0x0000},		/* 00,82,00,aa */
 	{0xaa, 0x83, 0x0000},		/* 00,83,00,aa */
@@ -5806,7 +5793,7 @@ static void usb_exchange(struct gspca_de
 			break;
 		default:
 /*		case 0xdd:	 * delay */
-			msleep(action->val / 64 + 10);
+			msleep(action->idx);
 			break;
 		}
 		action++;
@@ -5833,16 +5820,17 @@ static void setmatrix(struct gspca_dev *
 		{0x60, 0xf0, 0xf0, 0xf0, 0x60, 0xf0, 0xf0, 0xf0, 0x60};
 	static const u8 tas5130c_matrix[9] =
 		{0x68, 0xec, 0xec, 0xec, 0x68, 0xec, 0xec, 0xec, 0x68};
-	static const u8 vf0250_matrix[9] =
+	static const u8 gc0303_matrix[9] =
 		{0x7b, 0xea, 0xea, 0xea, 0x7b, 0xea, 0xea, 0xea, 0x7b};
 	static const u8 *matrix_tb[SENSOR_MAX] = {
 		[SENSOR_ADCM2700] =	adcm2700_matrix,
 		[SENSOR_CS2102] =	ov7620_matrix,
 		[SENSOR_CS2102K] =	NULL,
+		[SENSOR_GC0303] =	gc0303_matrix,
 		[SENSOR_GC0305] =	gc0305_matrix,
 		[SENSOR_HDCS2020b] =	NULL,
 		[SENSOR_HV7131B] =	NULL,
-		[SENSOR_HV7131R] =	NULL,
+		[SENSOR_HV7131R] =	po2030_matrix,
 		[SENSOR_ICM105A] =	po2030_matrix,
 		[SENSOR_MC501CB] =	NULL,
 		[SENSOR_MT9V111_1] =	gc0305_matrix,
@@ -5854,7 +5842,6 @@ static void setmatrix(struct gspca_dev *
 		[SENSOR_PB0330] =	gc0305_matrix,
 		[SENSOR_PO2030] =	po2030_matrix,
 		[SENSOR_TAS5130C] =	tas5130c_matrix,
-		[SENSOR_TAS5130C_VF0250] = vf0250_matrix,
 	};
 
 	matrix = matrix_tb[sd->sensor];
@@ -5875,7 +5862,7 @@ static void setsharpness(struct gspca_de
 		{0x10, 0x1e}
 	};
 
-	sharpness = sd->sharpness;
+	sharpness = sd->ctrls[SHARPNESS].val;
 	reg_w(gspca_dev, sharpness_tb[sharpness][0], 0x01c6);
 	reg_r(gspca_dev, 0x01c8);
 	reg_r(gspca_dev, 0x01c9);
@@ -5910,10 +5897,10 @@ static void setcontrast(struct gspca_dev
 		 0xe0, 0xeb, 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff},
 	};
 
-	Tgamma = gamma_tb[sd->gamma - 1];
+	Tgamma = gamma_tb[sd->ctrls[GAMMA].val - 1];
 
-	contrast = ((int) sd->contrast - 128);		/* -128 / 127 */
-	brightness = ((int) sd->brightness - 128);	/* -128 / 92 */
+	contrast = ((int) sd->ctrls[CONTRAST].val - 128); /* -128 / 127 */
+	brightness = ((int) sd->ctrls[BRIGHTNESS].val - 128); /* -128 / 92 */
 	adj = 0;
 	gp1 = gp2 = 0;
 	for (i = 0; i < 16; i++) {
@@ -5949,6 +5936,7 @@ static void setquality(struct gspca_dev
 	case SENSOR_ADCM2700:
 	case SENSOR_GC0305:
 	case SENSOR_HV7131B:
+	case SENSOR_HV7131R:
 	case SENSOR_OV7620:
 	case SENSOR_PAS202B:
 	case SENSOR_PO2030:
@@ -5994,6 +5982,10 @@ static void setlightfreq(struct gspca_de
 		{cs2102_NoFliker, cs2102_NoFlikerScale,
 		 NULL, NULL, /* currently disabled */
 		 NULL, NULL},
+	[SENSOR_GC0303] =
+		{gc0303_NoFliker, gc0303_NoFlikerScale,
+		 gc0303_50HZ, gc0303_50HZScale,
+		 gc0303_60HZ, gc0303_60HZScale},
 	[SENSOR_GC0305] =
 		{gc0305_NoFliker, gc0305_NoFliker,
 		 gc0305_50HZ, gc0305_50HZ,
@@ -6054,14 +6046,10 @@ static void setlightfreq(struct gspca_de
 		{tas5130c_NoFliker, tas5130c_NoFlikerScale,
 		 tas5130c_50HZ, tas5130c_50HZScale,
 		 tas5130c_60HZ, tas5130c_60HZScale},
-	[SENSOR_TAS5130C_VF0250] =
-		{tas5130c_vf0250_NoFliker, tas5130c_vf0250_NoFlikerScale,
-		 tas5130c_vf0250_50HZ, tas5130c_vf0250_50HZScale,
-		 tas5130c_vf0250_60HZ, tas5130c_vf0250_60HZScale},
 	};
 
-	i = sd->lightfreq * 2;
-	mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
+	i = sd->ctrls[LIGHTFREQ].val * 2;
+	mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
 	if (mode)
 		i++;			/* 320x240 */
 	zc3_freq = freq_tb[sd->sensor][i];
@@ -6070,14 +6058,14 @@ static void setlightfreq(struct gspca_de
 	usb_exchange(gspca_dev, zc3_freq);
 	switch (sd->sensor) {
 	case SENSOR_GC0305:
-		if (mode			/* if 320x240 */
-		    && sd->lightfreq == 1)	/* and 50Hz */
+		if (mode				/* if 320x240 */
+		    && sd->ctrls[LIGHTFREQ].val == 1)	/* and 50Hz */
 			reg_w(gspca_dev, 0x85, 0x018d);
 					/* win: 0x80, 0x018d */
 		break;
 	case SENSOR_OV7620:
-		if (!mode) {			/* if 640x480 */
-			if (sd->lightfreq != 0)	/* and 50 or 60 Hz */
+		if (!mode) {				/* if 640x480 */
+			if (sd->ctrls[LIGHTFREQ].val != 0) /* and filter */
 				reg_w(gspca_dev, 0x40, 0x0002);
 			else
 				reg_w(gspca_dev, 0x44, 0x0002);
@@ -6094,7 +6082,7 @@ static void setautogain(struct gspca_dev
 	struct sd *sd = (struct sd *) gspca_dev;
 	u8 autoval;
 
-	if (sd->autogain)
+	if (sd->ctrls[AUTOGAIN].val)
 		autoval = 0x42;
 	else
 		autoval = 0x02;
@@ -6121,11 +6109,13 @@ static void send_unknown(struct gspca_de
 		reg_w(gspca_dev, 0x02, 0x003b);
 		reg_w(gspca_dev, 0x00, 0x0038);
 		break;
+	case SENSOR_HV7131R:
 	case SENSOR_PAS202B:
 		reg_w(gspca_dev, 0x03, 0x003b);
 		reg_w(gspca_dev, 0x0c, 0x003a);
 		reg_w(gspca_dev, 0x0b, 0x0039);
-		reg_w(gspca_dev, 0x0b, 0x0038);
+		if (sensor == SENSOR_PAS202B)
+			reg_w(gspca_dev, 0x0b, 0x0038);
 		break;
 	}
 }
@@ -6330,8 +6320,8 @@ static int vga_3wr_probe(struct gspca_de
 	retword = i2c_read(gspca_dev, 0x00);
 	if (retword != 0) {
 		PDEBUG(D_PROBE, "probe 3wr vga type %02x", retword);
-		if (retword == 0x0011)			/* VF0250 */
-			return 0x0250;
+		if (retword == 0x0011)			/* gc0303 */
+			return 0x0303;
 		if (retword == 0x0029)			/* gc0305 */
 			send_unknown(gspca_dev, SENSOR_GC0305);
 		return retword;
@@ -6392,7 +6382,7 @@ static int zcxx_probeSensor(struct gspca
 	switch (sd->sensor) {
 	case SENSOR_MC501CB:
 		return -1;		/* don't probe */
-	case SENSOR_TAS5130C_VF0250:
+	case SENSOR_GC0303:
 			/* may probe but with no write in reg 0x0010 */
 		return -1;		/* don't probe */
 	case SENSOR_PAS106:
@@ -6421,11 +6411,7 @@ static int sd_config(struct gspca_dev *g
 	/* define some sensors from the vendor/product */
 	sd->sensor = id->driver_info;
 
-	sd->sharpness = SHARPNESS_DEF;
-	sd->brightness = BRIGHTNESS_DEF;
-	sd->contrast = CONTRAST_DEF;
-	sd->autogain = AUTOGAIN_DEF;
-	sd->lightfreq = FREQ_DEF;
+	gspca_dev->cam.ctrls = sd->ctrls;
 	sd->quality = QUALITY_DEF;
 
 	return 0;
@@ -6441,6 +6427,7 @@ static int sd_init(struct gspca_dev *gsp
 		[SENSOR_ADCM2700] =	4,
 		[SENSOR_CS2102] =	4,
 		[SENSOR_CS2102K] =	5,
+		[SENSOR_GC0303] =	3,
 		[SENSOR_GC0305] =	4,
 		[SENSOR_HDCS2020b] =	4,
 		[SENSOR_HV7131B] =	4,
@@ -6456,12 +6443,12 @@ static int sd_init(struct gspca_dev *gsp
 		[SENSOR_PB0330] =	4,
 		[SENSOR_PO2030] =	4,
 		[SENSOR_TAS5130C] =	3,
-		[SENSOR_TAS5130C_VF0250] = 3,
 	};
 	static const u8 mode_tb[SENSOR_MAX] = {
 		[SENSOR_ADCM2700] =	2,
 		[SENSOR_CS2102] =	1,
 		[SENSOR_CS2102K] =	1,
+		[SENSOR_GC0303] =	1,
 		[SENSOR_GC0305] =	1,
 		[SENSOR_HDCS2020b] =	1,
 		[SENSOR_HV7131B] =	1,
@@ -6477,7 +6464,6 @@ static int sd_init(struct gspca_dev *gsp
 		[SENSOR_PB0330] =	1,
 		[SENSOR_PO2030] =	1,
 		[SENSOR_TAS5130C] =	1,
-		[SENSOR_TAS5130C_VF0250] = 1,
 	};
 
 	sensor = zcxx_probeSensor(gspca_dev);
@@ -6493,8 +6479,8 @@ static int sd_init(struct gspca_dev *gsp
 			case SENSOR_MC501CB:
 				PDEBUG(D_PROBE, "Sensor MC501CB");
 				break;
-			case SENSOR_TAS5130C_VF0250:
-				PDEBUG(D_PROBE, "Sensor Tas5130 (VF0250)");
+			case SENSOR_GC0303:
+				PDEBUG(D_PROBE, "Sensor GC0303");
 				break;
 			default:
 				warn("Unknown sensor - set to TAS5130C");
@@ -6581,14 +6567,14 @@ static int sd_init(struct gspca_dev *gsp
 			PDEBUG(D_PROBE, "Find Sensor GC0305");
 			sd->sensor = SENSOR_GC0305;
 			break;
-		case 0x0250:
-			PDEBUG(D_PROBE, "Sensor Tas5130 (VF0250)");
-			sd->sensor =  SENSOR_TAS5130C_VF0250;
+		case 0x0303:
+			PDEBUG(D_PROBE, "Sensor GC0303");
+			sd->sensor =  SENSOR_GC0303;
 			break;
 		case 0x2030:
 			PDEBUG(D_PROBE, "Find Sensor PO2030");
 			sd->sensor = SENSOR_PO2030;
-			sd->sharpness = 0;		/* from win traces */
+			sd->ctrls[SHARPNESS].def = 0;	/* from win traces */
 			break;
 		case 0x7620:
 			PDEBUG(D_PROBE, "Find Sensor OV7620");
@@ -6629,11 +6615,12 @@ static int sd_init(struct gspca_dev *gsp
 		cam->nmodes = ARRAY_SIZE(broken_vga_mode);
 		break;
 	}
-	sd->gamma = gamma[sd->sensor];
+
+	sd->ctrls[GAMMA].def = gamma[sd->sensor];
 
 	switch (sd->sensor) {
 	case SENSOR_OV7630C:
-		gspca_dev->ctrl_dis = (1 << LIGHTFREQ_IDX);
+		gspca_dev->ctrl_dis = (1 << LIGHTFREQ);
 		break;
 	}
 
@@ -6653,6 +6640,8 @@ static int sd_start(struct gspca_dev *gs
 			{cs2102_Initial, cs2102_InitialScale},
 	[SENSOR_CS2102K] =
 			{cs2102K_Initial, cs2102K_InitialScale},
+	[SENSOR_GC0303] =
+		{gc0303_Initial, gc0303_InitialScale},
 	[SENSOR_GC0305] =
 			{gc0305_Initial, gc0305_InitialScale},
 	[SENSOR_HDCS2020b] =
@@ -6683,8 +6672,6 @@ static int sd_start(struct gspca_dev *gs
 			{po2030_Initial, po2030_InitialScale},
 	[SENSOR_TAS5130C] =
 			{tas5130c_Initial, tas5130c_InitialScale},
-	[SENSOR_TAS5130C_VF0250] =
-		{tas5130c_vf0250_Initial, tas5130c_vf0250_InitialScale},
 	};
 
 	/* create the JPEG header */
@@ -6709,7 +6696,7 @@ static int sd_start(struct gspca_dev *gs
 	case SENSOR_OV7620:
 	case SENSOR_PO2030:
 	case SENSOR_TAS5130C:
-	case SENSOR_TAS5130C_VF0250:
+	case SENSOR_GC0303:
 /*		msleep(100);			 * ?? */
 		reg_r(gspca_dev, 0x0002);	/* --> 0x40 */
 		reg_w(gspca_dev, 0x09, 0x01ad);	/* (from win traces) */
@@ -6720,10 +6707,13 @@ static int sd_start(struct gspca_dev *gs
 		reg_w(gspca_dev, 0x02, 0x003b);
 		reg_w(gspca_dev, 0x00, 0x0038);
 		break;
+	case SENSOR_HV7131R:
 	case SENSOR_PAS202B:
 		reg_w(gspca_dev, 0x03, 0x003b);
 		reg_w(gspca_dev, 0x0c, 0x003a);
 		reg_w(gspca_dev, 0x0b, 0x0039);
+		if (sd->sensor == SENSOR_HV7131R)
+			reg_w(gspca_dev, 0x50, ZC3XX_R11D_GLOBALGAIN);
 		break;
 	}
 
@@ -6736,6 +6726,7 @@ static int sd_start(struct gspca_dev *gs
 		break;
 	case SENSOR_PAS202B:
 	case SENSOR_GC0305:
+	case SENSOR_HV7131R:
 	case SENSOR_TAS5130C:
 		reg_r(gspca_dev, 0x0008);
 		/* fall thru */
@@ -6776,6 +6767,12 @@ static int sd_start(struct gspca_dev *gs
 						/* ms-win + */
 		reg_w(gspca_dev, 0x40, 0x0117);
 		break;
+	case SENSOR_HV7131R:
+		i2c_write(gspca_dev, 0x25, 0x04, 0x00);	/* exposure */
+		i2c_write(gspca_dev, 0x26, 0x93, 0x00);
+		i2c_write(gspca_dev, 0x27, 0xe0, 0x00);
+		reg_w(gspca_dev, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN);
+		break;
 	case SENSOR_GC0305:
 	case SENSOR_TAS5130C:
 		reg_w(gspca_dev, 0x09, 0x01ad);	/* (from win traces) */
@@ -6824,9 +6821,17 @@ static void sd_pkt_scan(struct gspca_dev
 {
 	struct sd *sd = (struct sd *) gspca_dev;
 
-	if (data[0] == 0xff && data[1] == 0xd8) {	/* start of frame */
+	/* check the JPEG end of frame */
+	if (len >= 3
+	 && data[len - 3] == 0xff && data[len - 2] == 0xd9) {
+/*fixme: what does the last byte mean?*/
 		gspca_frame_add(gspca_dev, LAST_PACKET,
-					NULL, 0);
+					data, len - 1);
+		return;
+	}
+
+	/* check the JPEG start of a frame */
+	if (data[0] == 0xff && data[1] == 0xd8) {
 		/* put the JPEG header in the new frame */
 		gspca_frame_add(gspca_dev, FIRST_PACKET,
 			sd->jpeg_hdr, JPEG_HDR_SZ);
@@ -6843,114 +6848,6 @@ static void sd_pkt_scan(struct gspca_dev
 	gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
 }
 
-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)
-		setcontrast(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)
-		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_setgamma(struct gspca_dev *gspca_dev, __s32 val)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-
-	sd->gamma = val;
-	if (gspca_dev->streaming)
-		setcontrast(gspca_dev);
-	return gspca_dev->usb_err;
-}
-
-static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-
-	*val = sd->gamma;
-	return 0;
-}
-
-static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-
-	sd->lightfreq = val;
-	if (gspca_dev->streaming)
-		setlightfreq(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->lightfreq;
-	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_querymenu(struct gspca_dev *gspca_dev,
 			struct v4l2_querymenu *menu)
 {
@@ -7033,7 +6930,7 @@ static const struct sd_desc sd_desc = {
 #endif
 };
 
-static const __devinitdata struct usb_device_id device_table[] = {
+static const struct usb_device_id device_table[] = {
 	{USB_DEVICE(0x041e, 0x041e)},
 	{USB_DEVICE(0x041e, 0x4017)},
 	{USB_DEVICE(0x041e, 0x401c), .driver_info = SENSOR_PAS106},
@@ -7045,8 +6942,8 @@ static const __devinitdata struct usb_de
 	{USB_DEVICE(0x041e, 0x4035), .driver_info = SENSOR_PAS106},
 	{USB_DEVICE(0x041e, 0x4036)},
 	{USB_DEVICE(0x041e, 0x403a)},
-	{USB_DEVICE(0x041e, 0x4051), .driver_info = SENSOR_TAS5130C_VF0250},
-	{USB_DEVICE(0x041e, 0x4053), .driver_info = SENSOR_TAS5130C_VF0250},
+	{USB_DEVICE(0x041e, 0x4051), .driver_info = SENSOR_GC0303},
+	{USB_DEVICE(0x041e, 0x4053), .driver_info = SENSOR_GC0303},
 	{USB_DEVICE(0x0458, 0x7007)},
 	{USB_DEVICE(0x0458, 0x700c)},
 	{USB_DEVICE(0x0458, 0x700f)},
@@ -7066,8 +6963,8 @@ static const __devinitdata struct usb_de
 	{USB_DEVICE(0x046d, 0x08af)},
 	{USB_DEVICE(0x046d, 0x08b9)},
 	{USB_DEVICE(0x046d, 0x08d7)},
-	{USB_DEVICE(0x046d, 0x08d9)},
 	{USB_DEVICE(0x046d, 0x08d8)},
+	{USB_DEVICE(0x046d, 0x08d9)},
 	{USB_DEVICE(0x046d, 0x08da)},
 	{USB_DEVICE(0x046d, 0x08dd), .driver_info = SENSOR_MC501CB},
 	{USB_DEVICE(0x0471, 0x0325), .driver_info = SENSOR_PAS106},
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/hdpvr/hdpvr-core.c linux-libre-2.6.38-gnu1/drivers/media/video/hdpvr/hdpvr-core.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/hdpvr/hdpvr-core.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/hdpvr/hdpvr-core.c	2011-03-14 21:20:32.000000000 -0400
@@ -283,6 +283,7 @@ static int hdpvr_probe(struct usb_interf
 	struct hdpvr_device *dev;
 	struct usb_host_interface *iface_desc;
 	struct usb_endpoint_descriptor *endpoint;
+	struct i2c_client *client;
 	size_t buffer_size;
 	int i;
 	int retval = -ENOMEM;
@@ -378,20 +379,35 @@ static int hdpvr_probe(struct usb_interf
 		goto error;
 	}
 
-#ifdef CONFIG_I2C
-	/* until i2c is working properly */
-	retval = 0; /* hdpvr_register_i2c_adapter(dev); */
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+	retval = hdpvr_register_i2c_adapter(dev);
 	if (retval < 0) {
-		v4l2_err(&dev->v4l2_dev, "registering i2c adapter failed\n");
+		v4l2_err(&dev->v4l2_dev, "i2c adapter register failed\n");
 		goto error;
 	}
-#endif /* CONFIG_I2C */
+
+	client = hdpvr_register_ir_rx_i2c(dev);
+	if (!client) {
+		v4l2_err(&dev->v4l2_dev, "i2c IR RX device register failed\n");
+		goto reg_fail;
+	}
+
+	client = hdpvr_register_ir_tx_i2c(dev);
+	if (!client) {
+		v4l2_err(&dev->v4l2_dev, "i2c IR TX device register failed\n");
+		goto reg_fail;
+	}
+#endif
 
 	/* let the user know what node this device is now attached to */
 	v4l2_info(&dev->v4l2_dev, "device now attached to %s\n",
 		  video_device_node_name(dev->video_dev));
 	return 0;
 
+reg_fail:
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+	i2c_del_adapter(&dev->i2c_adapter);
+#endif
 error:
 	if (dev) {
 		/* Destroy single thread */
@@ -421,6 +437,9 @@ static void hdpvr_disconnect(struct usb_
 	mutex_lock(&dev->io_mutex);
 	hdpvr_cancel_queue(dev);
 	mutex_unlock(&dev->io_mutex);
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+	i2c_del_adapter(&dev->i2c_adapter);
+#endif
 	video_unregister_device(dev->video_dev);
 	atomic_dec(&dev_nr);
 }
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/hdpvr/hdpvr.h linux-libre-2.6.38-gnu1/drivers/media/video/hdpvr/hdpvr.h
--- linux-libre-2.6.37-gnu1/drivers/media/video/hdpvr/hdpvr.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/hdpvr/hdpvr.h	2011-03-14 21:20:32.000000000 -0400
@@ -16,6 +16,7 @@
 #include <linux/videodev2.h>
 
 #include <media/v4l2-device.h>
+#include <media/ir-kbd-i2c.h>
 
 #define HDPVR_MAJOR_VERSION 0
 #define HDPVR_MINOR_VERSION 2
@@ -24,6 +25,7 @@
 	KERNEL_VERSION(HDPVR_MAJOR_VERSION, HDPVR_MINOR_VERSION, HDPVR_RELEASE)
 
 #define HDPVR_MAX 8
+#define HDPVR_I2C_MAX_SIZE 128
 
 /* Define these values to match your devices */
 #define HD_PVR_VENDOR_ID	0x2040
@@ -105,9 +107,14 @@ struct hdpvr_device {
 	struct work_struct	worker;
 
 	/* I2C adapter */
-	struct i2c_adapter	*i2c_adapter;
+	struct i2c_adapter	i2c_adapter;
 	/* I2C lock */
 	struct mutex		i2c_mutex;
+	/* I2C message buffer space */
+	char			i2c_buf[HDPVR_I2C_MAX_SIZE];
+
+	/* For passing data to ir-kbd-i2c */
+	struct IR_i2c_init_data	ir_i2c_init_data;
 
 	/* usb control transfer buffer and lock */
 	struct mutex		usbc_mutex;
@@ -306,6 +313,9 @@ int hdpvr_cancel_queue(struct hdpvr_devi
 /* i2c adapter registration */
 int hdpvr_register_i2c_adapter(struct hdpvr_device *dev);
 
+struct i2c_client *hdpvr_register_ir_rx_i2c(struct hdpvr_device *dev);
+struct i2c_client *hdpvr_register_ir_tx_i2c(struct hdpvr_device *dev);
+
 /*========================================================================*/
 /* buffer management */
 int hdpvr_free_buffers(struct hdpvr_device *dev);
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/hdpvr/hdpvr-i2c.c linux-libre-2.6.38-gnu1/drivers/media/video/hdpvr/hdpvr-i2c.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/hdpvr/hdpvr-i2c.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/hdpvr/hdpvr-i2c.c	2011-03-14 21:20:32.000000000 -0400
@@ -4,12 +4,17 @@
  *
  * Copyright (C) 2008      Janne Grunau (j@jannau.net)
  *
+ * IR device registration code is
+ * Copyright (C) 2010	Andy Walls <awalls@md.metrocast.net>
+ *
  *	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.
  *
  */
 
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+
 #include <linux/i2c.h>
 #include <linux/slab.h>
 
@@ -22,59 +27,89 @@
 #define REQTYPE_I2C_WRITE	0xb0
 #define REQTYPE_I2C_WRITE_STATT	0xd0
 
-static int hdpvr_i2c_read(struct hdpvr_device *dev, unsigned char addr,
-			  char *data, int len)
+#define Z8F0811_IR_TX_I2C_ADDR	0x70
+#define Z8F0811_IR_RX_I2C_ADDR	0x71
+
+
+struct i2c_client *hdpvr_register_ir_tx_i2c(struct hdpvr_device *dev)
+{
+	struct IR_i2c_init_data *init_data = &dev->ir_i2c_init_data;
+	struct i2c_board_info hdpvr_ir_tx_i2c_board_info = {
+		I2C_BOARD_INFO("ir_tx_z8f0811_hdpvr", Z8F0811_IR_TX_I2C_ADDR),
+	};
+
+	init_data->name = "HD-PVR";
+	hdpvr_ir_tx_i2c_board_info.platform_data = init_data;
+
+	return i2c_new_device(&dev->i2c_adapter, &hdpvr_ir_tx_i2c_board_info);
+}
+
+struct i2c_client *hdpvr_register_ir_rx_i2c(struct hdpvr_device *dev)
+{
+	struct IR_i2c_init_data *init_data = &dev->ir_i2c_init_data;
+	struct i2c_board_info hdpvr_ir_rx_i2c_board_info = {
+		I2C_BOARD_INFO("ir_rx_z8f0811_hdpvr", Z8F0811_IR_RX_I2C_ADDR),
+	};
+
+	/* Our default information for ir-kbd-i2c.c to use */
+	init_data->ir_codes = RC_MAP_HAUPPAUGE_NEW;
+	init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR;
+	init_data->type = RC_TYPE_RC5;
+	init_data->name = "HD-PVR";
+	hdpvr_ir_rx_i2c_board_info.platform_data = init_data;
+
+	return i2c_new_device(&dev->i2c_adapter, &hdpvr_ir_rx_i2c_board_info);
+}
+
+static int hdpvr_i2c_read(struct hdpvr_device *dev, int bus,
+			  unsigned char addr, char *data, int len)
 {
 	int ret;
-	char *buf = kmalloc(len, GFP_KERNEL);
-	if (!buf)
-		return -ENOMEM;
+
+	if (len > sizeof(dev->i2c_buf))
+		return -EINVAL;
 
 	ret = usb_control_msg(dev->udev,
 			      usb_rcvctrlpipe(dev->udev, 0),
 			      REQTYPE_I2C_READ, CTRL_READ_REQUEST,
-			      0x100|addr, 0, buf, len, 1000);
+			      (bus << 8) | addr, 0, &dev->i2c_buf, len, 1000);
 
 	if (ret == len) {
-		memcpy(data, buf, len);
+		memcpy(data, &dev->i2c_buf, len);
 		ret = 0;
 	} else if (ret >= 0)
 		ret = -EIO;
 
-	kfree(buf);
-
 	return ret;
 }
 
-static int hdpvr_i2c_write(struct hdpvr_device *dev, unsigned char addr,
-			   char *data, int len)
+static int hdpvr_i2c_write(struct hdpvr_device *dev, int bus,
+			   unsigned char addr, char *data, int len)
 {
 	int ret;
-	char *buf = kmalloc(len, GFP_KERNEL);
-	if (!buf)
-		return -ENOMEM;
 
-	memcpy(buf, data, len);
+	if (len > sizeof(dev->i2c_buf))
+		return -EINVAL;
+
+	memcpy(&dev->i2c_buf, data, len);
 	ret = usb_control_msg(dev->udev,
 			      usb_sndctrlpipe(dev->udev, 0),
 			      REQTYPE_I2C_WRITE, CTRL_WRITE_REQUEST,
-			      0x100|addr, 0, buf, len, 1000);
+			      (bus << 8) | addr, 0, &dev->i2c_buf, len, 1000);
 
 	if (ret < 0)
-		goto error;
+		return ret;
 
 	ret = usb_control_msg(dev->udev,
 			      usb_rcvctrlpipe(dev->udev, 0),
 			      REQTYPE_I2C_WRITE_STATT, CTRL_READ_REQUEST,
-			      0, 0, buf, 2, 1000);
+			      0, 0, &dev->i2c_buf, 2, 1000);
 
-	if (ret == 2)
+	if ((ret == 2) && (dev->i2c_buf[1] == (len - 1)))
 		ret = 0;
 	else if (ret >= 0)
 		ret = -EIO;
 
-error:
-	kfree(buf);
 	return ret;
 }
 
@@ -93,10 +128,10 @@ static int hdpvr_transfer(struct i2c_ada
 		addr = msgs[i].addr << 1;
 
 		if (msgs[i].flags & I2C_M_RD)
-			retval = hdpvr_i2c_read(dev, addr, msgs[i].buf,
+			retval = hdpvr_i2c_read(dev, 1, addr, msgs[i].buf,
 						msgs[i].len);
 		else
-			retval = hdpvr_i2c_write(dev, addr, msgs[i].buf,
+			retval = hdpvr_i2c_write(dev, 1, addr, msgs[i].buf,
 						 msgs[i].len);
 	}
 
@@ -115,30 +150,47 @@ static struct i2c_algorithm hdpvr_algo =
 	.functionality = hdpvr_functionality,
 };
 
+static struct i2c_adapter hdpvr_i2c_adapter_template = {
+	.name   = "Hauppage HD PVR I2C",
+	.owner  = THIS_MODULE,
+	.algo   = &hdpvr_algo,
+};
+
+static int hdpvr_activate_ir(struct hdpvr_device *dev)
+{
+	char buffer[8];
+
+	mutex_lock(&dev->i2c_mutex);
+
+	hdpvr_i2c_read(dev, 0, 0x54, buffer, 1);
+
+	buffer[0] = 0;
+	buffer[1] = 0x8;
+	hdpvr_i2c_write(dev, 1, 0x54, buffer, 2);
+
+	buffer[1] = 0x18;
+	hdpvr_i2c_write(dev, 1, 0x54, buffer, 2);
+
+	mutex_unlock(&dev->i2c_mutex);
+
+	return 0;
+}
+
 int hdpvr_register_i2c_adapter(struct hdpvr_device *dev)
 {
-	struct i2c_adapter *i2c_adap;
 	int retval = -ENOMEM;
 
-	i2c_adap = kzalloc(sizeof(struct i2c_adapter), GFP_KERNEL);
-	if (i2c_adap == NULL)
-		goto error;
-
-	strlcpy(i2c_adap->name, "Hauppauge HD PVR I2C",
-		sizeof(i2c_adap->name));
-	i2c_adap->algo  = &hdpvr_algo;
-	i2c_adap->owner = THIS_MODULE;
-	i2c_adap->dev.parent = &dev->udev->dev;
+	hdpvr_activate_ir(dev);
 
-	i2c_set_adapdata(i2c_adap, dev);
+	memcpy(&dev->i2c_adapter, &hdpvr_i2c_adapter_template,
+	       sizeof(struct i2c_adapter));
+	dev->i2c_adapter.dev.parent = &dev->udev->dev;
 
-	retval = i2c_add_adapter(i2c_adap);
+	i2c_set_adapdata(&dev->i2c_adapter, dev);
 
-	if (!retval)
-		dev->i2c_adapter = i2c_adap;
-	else
-		kfree(i2c_adap);
+	retval = i2c_add_adapter(&dev->i2c_adapter);
 
-error:
 	return retval;
 }
+
+#endif
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/hdpvr/hdpvr-video.c linux-libre-2.6.38-gnu1/drivers/media/video/hdpvr/hdpvr-video.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/hdpvr/hdpvr-video.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/hdpvr/hdpvr-video.c	2011-03-14 21:20:32.000000000 -0400
@@ -1220,12 +1220,9 @@ static void hdpvr_device_release(struct
 	v4l2_device_unregister(&dev->v4l2_dev);
 
 	/* deregister I2C adapter */
-#ifdef CONFIG_I2C
+#if defined(CONFIG_I2C) || (CONFIG_I2C_MODULE)
 	mutex_lock(&dev->i2c_mutex);
-	if (dev->i2c_adapter)
-		i2c_del_adapter(dev->i2c_adapter);
-	kfree(dev->i2c_adapter);
-	dev->i2c_adapter = NULL;
+	i2c_del_adapter(&dev->i2c_adapter);
 	mutex_unlock(&dev->i2c_mutex);
 #endif /* CONFIG_I2C */
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/hdpvr/Makefile linux-libre-2.6.38-gnu1/drivers/media/video/hdpvr/Makefile
--- linux-libre-2.6.37-gnu1/drivers/media/video/hdpvr/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/hdpvr/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -1,6 +1,4 @@
-hdpvr-objs	:= hdpvr-control.o hdpvr-core.o hdpvr-video.o
-
-hdpvr-$(CONFIG_I2C) += hdpvr-i2c.o
+hdpvr-objs	:= hdpvr-control.o hdpvr-core.o hdpvr-video.o hdpvr-i2c.o
 
 obj-$(CONFIG_VIDEO_HDPVR) += hdpvr.o
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/hexium_gemini.c linux-libre-2.6.38-gnu1/drivers/media/video/hexium_gemini.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/hexium_gemini.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/hexium_gemini.c	2011-03-14 21:20:32.000000000 -0400
@@ -37,15 +37,15 @@ static int hexium_num;
 
 #define HEXIUM_INPUTS	9
 static struct v4l2_input hexium_inputs[HEXIUM_INPUTS] = {
-	{ 0, "CVBS 1",	V4L2_INPUT_TYPE_CAMERA,	2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
-	{ 1, "CVBS 2",	V4L2_INPUT_TYPE_CAMERA,	2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
-	{ 2, "CVBS 3",	V4L2_INPUT_TYPE_CAMERA,	2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
-	{ 3, "CVBS 4",	V4L2_INPUT_TYPE_CAMERA,	2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
-	{ 4, "CVBS 5",	V4L2_INPUT_TYPE_CAMERA,	2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
-	{ 5, "CVBS 6",	V4L2_INPUT_TYPE_CAMERA,	2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
-	{ 6, "Y/C 1",	V4L2_INPUT_TYPE_CAMERA,	2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
-	{ 7, "Y/C 2",	V4L2_INPUT_TYPE_CAMERA,	2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
-	{ 8, "Y/C 3",	V4L2_INPUT_TYPE_CAMERA,	2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
+	{ 0, "CVBS 1",	V4L2_INPUT_TYPE_CAMERA,	2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD },
+	{ 1, "CVBS 2",	V4L2_INPUT_TYPE_CAMERA,	2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD },
+	{ 2, "CVBS 3",	V4L2_INPUT_TYPE_CAMERA,	2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD },
+	{ 3, "CVBS 4",	V4L2_INPUT_TYPE_CAMERA,	2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD },
+	{ 4, "CVBS 5",	V4L2_INPUT_TYPE_CAMERA,	2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD },
+	{ 5, "CVBS 6",	V4L2_INPUT_TYPE_CAMERA,	2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD },
+	{ 6, "Y/C 1",	V4L2_INPUT_TYPE_CAMERA,	2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD },
+	{ 7, "Y/C 2",	V4L2_INPUT_TYPE_CAMERA,	2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD },
+	{ 8, "Y/C 3",	V4L2_INPUT_TYPE_CAMERA,	2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD },
 };
 
 #define HEXIUM_AUDIOS	0
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/hexium_orion.c linux-libre-2.6.38-gnu1/drivers/media/video/hexium_orion.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/hexium_orion.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/hexium_orion.c	2011-03-14 21:20:32.000000000 -0400
@@ -38,15 +38,15 @@ static int hexium_num;
 
 #define HEXIUM_INPUTS	9
 static struct v4l2_input hexium_inputs[HEXIUM_INPUTS] = {
-	{ 0, "CVBS 1",	V4L2_INPUT_TYPE_CAMERA,	2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
-	{ 1, "CVBS 2",	V4L2_INPUT_TYPE_CAMERA,	2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
-	{ 2, "CVBS 3",	V4L2_INPUT_TYPE_CAMERA,	2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
-	{ 3, "CVBS 4",	V4L2_INPUT_TYPE_CAMERA,	2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
-	{ 4, "CVBS 5",	V4L2_INPUT_TYPE_CAMERA,	2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
-	{ 5, "CVBS 6",	V4L2_INPUT_TYPE_CAMERA,	2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
-	{ 6, "Y/C 1",	V4L2_INPUT_TYPE_CAMERA,	2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
-	{ 7, "Y/C 2",	V4L2_INPUT_TYPE_CAMERA,	2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
-	{ 8, "Y/C 3",	V4L2_INPUT_TYPE_CAMERA,	2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
+	{ 0, "CVBS 1",	V4L2_INPUT_TYPE_CAMERA,	2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD },
+	{ 1, "CVBS 2",	V4L2_INPUT_TYPE_CAMERA,	2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD },
+	{ 2, "CVBS 3",	V4L2_INPUT_TYPE_CAMERA,	2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD },
+	{ 3, "CVBS 4",	V4L2_INPUT_TYPE_CAMERA,	2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD },
+	{ 4, "CVBS 5",	V4L2_INPUT_TYPE_CAMERA,	2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD },
+	{ 5, "CVBS 6",	V4L2_INPUT_TYPE_CAMERA,	2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD },
+	{ 6, "Y/C 1",	V4L2_INPUT_TYPE_CAMERA,	2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD },
+	{ 7, "Y/C 2",	V4L2_INPUT_TYPE_CAMERA,	2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD },
+	{ 8, "Y/C 3",	V4L2_INPUT_TYPE_CAMERA,	2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD },
 };
 
 #define HEXIUM_AUDIOS	0
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/imx074.c linux-libre-2.6.38-gnu1/drivers/media/video/imx074.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/imx074.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/imx074.c	2011-03-14 21:20:32.000000000 -0400
@@ -467,7 +467,6 @@ static int imx074_remove(struct i2c_clie
 	icd->ops = NULL;
 	if (icl->free_bus)
 		icl->free_bus(icl);
-	client->driver = NULL;
 	kfree(priv);
 
 	return 0;
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/ir-kbd-i2c.c linux-libre-2.6.38-gnu1/drivers/media/video/ir-kbd-i2c.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/ir-kbd-i2c.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/ir-kbd-i2c.c	2011-03-14 21:20:32.000000000 -0400
@@ -46,7 +46,7 @@
 #include <linux/i2c.h>
 #include <linux/workqueue.h>
 
-#include <media/ir-core.h>
+#include <media/rc-core.h>
 #include <media/ir-kbd-i2c.h>
 
 /* ----------------------------------------------------------------------- */
@@ -128,6 +128,19 @@ static int get_key_haup(struct IR_i2c *i
 
 static int get_key_haup_xvr(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
 {
+	int ret;
+	unsigned char buf[1] = { 0 };
+
+	/*
+	 * This is the same apparent "are you ready?" poll command observed
+	 * watching Windows driver traffic and implemented in lirc_zilog. With
+	 * this added, we get far saner remote behavior with z8 chips on usb
+	 * connected devices, even with the default polling interval of 100ms.
+	 */
+	ret = i2c_master_send(ir->c, buf, 1);
+	if (ret != 1)
+		return (ret < 0) ? ret : -EINVAL;
+
 	return get_key_haup_common (ir, ir_key, ir_raw, 6, 3);
 }
 
@@ -244,15 +257,17 @@ static void ir_key_poll(struct IR_i2c *i
 	static u32 ir_key, ir_raw;
 	int rc;
 
-	dprintk(2,"ir_poll_key\n");
+	dprintk(3, "%s\n", __func__);
 	rc = ir->get_key(ir, &ir_key, &ir_raw);
 	if (rc < 0) {
 		dprintk(2,"error\n");
 		return;
 	}
 
-	if (rc)
-		ir_keydown(ir->input, ir_key, 0);
+	if (rc) {
+		dprintk(1, "%s: keycode = 0x%04x\n", __func__, ir_key);
+		rc_keydown(ir->rc, ir_key, 0);
+	}
 }
 
 static void ir_work(struct work_struct *work)
@@ -269,22 +284,18 @@ static int ir_probe(struct i2c_client *c
 {
 	char *ir_codes = NULL;
 	const char *name = NULL;
-	u64 ir_type = 0;
+	u64 rc_type = RC_TYPE_UNKNOWN;
 	struct IR_i2c *ir;
-	struct input_dev *input_dev;
+	struct rc_dev *rc = NULL;
 	struct i2c_adapter *adap = client->adapter;
 	unsigned short addr = client->addr;
 	int err;
 
-	ir = kzalloc(sizeof(struct IR_i2c),GFP_KERNEL);
-	input_dev = input_allocate_device();
-	if (!ir || !input_dev) {
-		err = -ENOMEM;
-		goto err_out_free;
-	}
+	ir = kzalloc(sizeof(struct IR_i2c), GFP_KERNEL);
+	if (!ir)
+		return -ENOMEM;
 
 	ir->c = client;
-	ir->input = input_dev;
 	ir->polling_interval = DEFAULT_POLLING_INTERVAL;
 	i2c_set_clientdata(client, ir);
 
@@ -292,7 +303,7 @@ static int ir_probe(struct i2c_client *c
 	case 0x64:
 		name        = "Pixelview";
 		ir->get_key = get_key_pixelview;
-		ir_type     = IR_TYPE_OTHER;
+		rc_type     = RC_TYPE_OTHER;
 		ir_codes    = RC_MAP_EMPTY;
 		break;
 	case 0x18:
@@ -300,7 +311,7 @@ static int ir_probe(struct i2c_client *c
 	case 0x1a:
 		name        = "Hauppauge";
 		ir->get_key = get_key_haup;
-		ir_type     = IR_TYPE_RC5;
+		rc_type     = RC_TYPE_RC5;
 		if (hauppauge == 1) {
 			ir_codes    = RC_MAP_HAUPPAUGE_NEW;
 		} else {
@@ -310,21 +321,27 @@ static int ir_probe(struct i2c_client *c
 	case 0x30:
 		name        = "KNC One";
 		ir->get_key = get_key_knc1;
-		ir_type     = IR_TYPE_OTHER;
+		rc_type     = RC_TYPE_OTHER;
 		ir_codes    = RC_MAP_EMPTY;
 		break;
 	case 0x6b:
 		name        = "FusionHDTV";
 		ir->get_key = get_key_fusionhdtv;
-		ir_type     = IR_TYPE_RC5;
+		rc_type     = RC_TYPE_RC5;
 		ir_codes    = RC_MAP_FUSIONHDTV_MCE;
 		break;
 	case 0x40:
 		name        = "AVerMedia Cardbus remote";
 		ir->get_key = get_key_avermedia_cardbus;
-		ir_type     = IR_TYPE_OTHER;
+		rc_type     = RC_TYPE_OTHER;
 		ir_codes    = RC_MAP_AVERMEDIA_CARDBUS;
 		break;
+	case 0x71:
+		name        = "Hauppauge/Zilog Z8";
+		ir->get_key = get_key_haup_xvr;
+		rc_type     = RC_TYPE_RC5;
+		ir_codes    = hauppauge ? RC_MAP_HAUPPAUGE_NEW : RC_MAP_RC5_TV;
+		break;
 	}
 
 	/* Let the caller override settings */
@@ -333,9 +350,11 @@ static int ir_probe(struct i2c_client *c
 						client->dev.platform_data;
 
 		ir_codes = init_data->ir_codes;
+		rc = init_data->rc_dev;
+
 		name = init_data->name;
 		if (init_data->type)
-			ir_type = init_data->type;
+			rc_type = init_data->type;
 
 		if (init_data->polling_interval)
 			ir->polling_interval = init_data->polling_interval;
@@ -366,8 +385,21 @@ static int ir_probe(struct i2c_client *c
 		}
 	}
 
+	if (!rc) {
+		/*
+		 * If platform_data doesn't specify rc_dev, initilize it
+		 * internally
+		 */
+		rc = rc_allocate_device();
+		if (!rc) {
+			err = -ENOMEM;
+			goto err_out_free;
+		}
+	}
+	ir->rc = rc;
+
 	/* Make sure we are all setup before going on */
-	if (!name || !ir->get_key || !ir_type || !ir_codes) {
+	if (!name || !ir->get_key || !rc_type || !ir_codes) {
 		dprintk(1, ": Unsupported device at address 0x%02x\n",
 			addr);
 		err = -ENODEV;
@@ -382,18 +414,28 @@ static int ir_probe(struct i2c_client *c
 		 dev_name(&adap->dev),
 		 dev_name(&client->dev));
 
-	/* init + register input device */
-	ir->ir_type = ir_type;
-	input_dev->id.bustype = BUS_I2C;
-	input_dev->name       = ir->name;
-	input_dev->phys       = ir->phys;
+	/*
+	 * Initialize input_dev fields
+	 * It doesn't make sense to allow overriding them via platform_data
+	 */
+	rc->input_id.bustype = BUS_I2C;
+	rc->input_phys       = ir->phys;
+	rc->input_name	     = ir->name;
 
-	err = ir_input_register(ir->input, ir->ir_codes, NULL, MODULE_NAME);
+	/*
+	 * Initialize the other fields of rc_dev
+	 */
+	rc->map_name       = ir->ir_codes;
+	rc->allowed_protos = rc_type;
+	if (!rc->driver_name)
+		rc->driver_name = MODULE_NAME;
+
+	err = rc_register_device(rc);
 	if (err)
 		goto err_out_free;
 
 	printk(MODULE_NAME ": %s detected at %s [%s]\n",
-	       ir->input->name, ir->input->phys, adap->name);
+	       ir->name, ir->phys, adap->name);
 
 	/* start polling via eventd */
 	INIT_DELAYED_WORK(&ir->work, ir_work);
@@ -402,6 +444,8 @@ static int ir_probe(struct i2c_client *c
 	return 0;
 
  err_out_free:
+	/* Only frees rc if it were allocated internally */
+	rc_free_device(rc);
 	kfree(ir);
 	return err;
 }
@@ -414,7 +458,7 @@ static int ir_remove(struct i2c_client *
 	cancel_delayed_work_sync(&ir->work);
 
 	/* unregister device */
-	ir_input_unregister(ir->input);
+	rc_unregister_device(ir->rc);
 
 	/* free memory */
 	kfree(ir);
@@ -426,6 +470,7 @@ static const struct i2c_device_id ir_kbd
 	{ "ir_video", 0 },
 	/* IR device specific entries should be added here */
 	{ "ir_rx_z8f0811_haup", 0 },
+	{ "ir_rx_z8f0811_hdpvr", 0 },
 	{ }
 };
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/ivtv/ivtv-cards.c linux-libre-2.6.38-gnu1/drivers/media/video/ivtv/ivtv-cards.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/ivtv/ivtv-cards.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/ivtv/ivtv-cards.c	2011-03-14 21:20:32.000000000 -0400
@@ -405,7 +405,8 @@ static const struct ivtv_card ivtv_card_
 	.hw_audio_ctrl = IVTV_HW_MSP34XX,
 	.hw_muxer = IVTV_HW_CS53L32A,
 	.hw_all = IVTV_HW_MSP34XX | IVTV_HW_CS53L32A |
-		  IVTV_HW_SAA7115 | IVTV_HW_TUNER,
+		  IVTV_HW_SAA7115 | IVTV_HW_TUNER |
+		  IVTV_HW_I2C_IR_RX_ADAPTEC,
 	.video_inputs = {
 		{ IVTV_CARD_INPUT_VID_TUNER,  0, IVTV_SAA71XX_COMPOSITE4 },
 		{ IVTV_CARD_INPUT_SVIDEO1,    1, IVTV_SAA71XX_SVIDEO0    },
@@ -1313,7 +1314,6 @@ int ivtv_get_input(struct ivtv *itv, u16
 		"Composite 3"
 	};
 
-	memset(input, 0, sizeof(*input));
 	if (index >= itv->nof_inputs)
 		return -EINVAL;
 	input->index = index;
@@ -1331,7 +1331,6 @@ int ivtv_get_output(struct ivtv *itv, u1
 {
 	const struct ivtv_card_output *card_output = itv->card->video_outputs + index;
 
-	memset(output, 0, sizeof(*output));
 	if (index >= itv->card->nof_outputs)
 		return -EINVAL;
 	output->index = index;
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/ivtv/ivtv-cards.h linux-libre-2.6.38-gnu1/drivers/media/video/ivtv/ivtv-cards.h
--- linux-libre-2.6.37-gnu1/drivers/media/video/ivtv/ivtv-cards.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/ivtv/ivtv-cards.h	2011-03-14 21:20:32.000000000 -0400
@@ -111,6 +111,7 @@
 #define IVTV_HW_I2C_IR_RX_HAUP_INT	(1 << 18)
 #define IVTV_HW_Z8F0811_IR_TX_HAUP	(1 << 19)
 #define IVTV_HW_Z8F0811_IR_RX_HAUP	(1 << 20)
+#define IVTV_HW_I2C_IR_RX_ADAPTEC	(1 << 21)
 
 #define IVTV_HW_Z8F0811_IR_HAUP	(IVTV_HW_Z8F0811_IR_RX_HAUP | \
 				 IVTV_HW_Z8F0811_IR_TX_HAUP)
@@ -120,7 +121,8 @@
 #define IVTV_HW_IR_RX_ANY (IVTV_HW_I2C_IR_RX_AVER | \
 			   IVTV_HW_I2C_IR_RX_HAUP_EXT | \
 			   IVTV_HW_I2C_IR_RX_HAUP_INT | \
-			   IVTV_HW_Z8F0811_IR_RX_HAUP)
+			   IVTV_HW_Z8F0811_IR_RX_HAUP | \
+			   IVTV_HW_I2C_IR_RX_ADAPTEC)
 
 #define IVTV_HW_IR_TX_ANY (IVTV_HW_Z8F0811_IR_TX_HAUP)
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/ivtv/ivtv-driver.c linux-libre-2.6.38-gnu1/drivers/media/video/ivtv/ivtv-driver.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/ivtv/ivtv-driver.c	2013-05-03 03:54:56.000000000 -0400
+++ linux-libre-2.6.38-gnu1/drivers/media/video/ivtv/ivtv-driver.c	2013-05-03 01:54:13.000000000 -0400
@@ -1029,8 +1029,13 @@ static int __devinit ivtv_probe(struct p
 	itv->enc_mem = ioremap_nocache(itv->base_addr + IVTV_ENCODER_OFFSET,
 				       IVTV_ENCODER_SIZE);
 	if (!itv->enc_mem) {
-		IVTV_ERR("ioremap failed, perhaps increasing __VMALLOC_RESERVE in page.h\n");
-		IVTV_ERR("or disabling CONFIG_HIGHMEM4G into the kernel would help\n");
+		IVTV_ERR("ioremap failed. Can't get a window into CX23415/6 "
+			 "encoder memory\n");
+		IVTV_ERR("Each capture card with a CX23415/6 needs 8 MB of "
+			 "vmalloc address space for this window\n");
+		IVTV_ERR("Check the output of 'grep Vmalloc /proc/meminfo'\n");
+		IVTV_ERR("Use the vmalloc= kernel command line option to set "
+			 "VmallocTotal to a larger value\n");
 		retval = -ENOMEM;
 		goto free_mem;
 	}
@@ -1041,8 +1046,14 @@ static int __devinit ivtv_probe(struct p
 		itv->dec_mem = ioremap_nocache(itv->base_addr + IVTV_DECODER_OFFSET,
 				IVTV_DECODER_SIZE);
 		if (!itv->dec_mem) {
-			IVTV_ERR("ioremap failed, perhaps increasing __VMALLOC_RESERVE in page.h\n");
-			IVTV_ERR("or disabling CONFIG_HIGHMEM4G into the kernel would help\n");
+			IVTV_ERR("ioremap failed. Can't get a window into "
+				 "CX23415 decoder memory\n");
+			IVTV_ERR("Each capture card with a CX23415 needs 8 MB "
+				 "of vmalloc address space for this window\n");
+			IVTV_ERR("Check the output of 'grep Vmalloc "
+				 "/proc/meminfo'\n");
+			IVTV_ERR("Use the vmalloc= kernel command line option "
+				 "to set VmallocTotal to a larger value\n");
 			retval = -ENOMEM;
 			goto free_mem;
 		}
@@ -1057,8 +1068,13 @@ static int __devinit ivtv_probe(struct p
 	itv->reg_mem =
 	    ioremap_nocache(itv->base_addr + IVTV_REG_OFFSET, IVTV_REG_SIZE);
 	if (!itv->reg_mem) {
-		IVTV_ERR("ioremap failed, perhaps increasing __VMALLOC_RESERVE in page.h\n");
-		IVTV_ERR("or disabling CONFIG_HIGHMEM4G into the kernel would help\n");
+		IVTV_ERR("ioremap failed. Can't get a window into CX23415/6 "
+			 "register space\n");
+		IVTV_ERR("Each capture card with a CX23415/6 needs 64 kB of "
+			 "vmalloc address space for this window\n");
+		IVTV_ERR("Check the output of 'grep Vmalloc /proc/meminfo'\n");
+		IVTV_ERR("Use the vmalloc= kernel command line option to set "
+			 "VmallocTotal to a larger value\n");
 		retval = -ENOMEM;
 		goto free_io;
 	}
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/ivtv/ivtv-fileops.c linux-libre-2.6.38-gnu1/drivers/media/video/ivtv/ivtv-fileops.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/ivtv/ivtv-fileops.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/ivtv/ivtv-fileops.c	2011-03-14 21:20:32.000000000 -0400
@@ -570,8 +570,8 @@ ssize_t ivtv_v4l2_write(struct file *fil
 		int elems = count / sizeof(struct v4l2_sliced_vbi_data);
 
 		set_bit(IVTV_F_S_APPL_IO, &s->s_flags);
-		ivtv_write_vbi(itv, (const struct v4l2_sliced_vbi_data *)user_buf, elems);
-		return elems * sizeof(struct v4l2_sliced_vbi_data);
+		return ivtv_write_vbi_from_user(itv,
+		   (const struct v4l2_sliced_vbi_data __user *)user_buf, elems);
 	}
 
 	mode = s->type == IVTV_DEC_STREAM_TYPE_MPG ? OUT_MPG : OUT_YUV;
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/ivtv/ivtv-i2c.c linux-libre-2.6.38-gnu1/drivers/media/video/ivtv/ivtv-i2c.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/ivtv/ivtv-i2c.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/ivtv/ivtv-i2c.c	2011-03-14 21:20:32.000000000 -0400
@@ -94,6 +94,7 @@
 #define IVTV_HAUP_INT_IR_RX_I2C_ADDR 	0x18
 #define IVTV_Z8F0811_IR_TX_I2C_ADDR	0x70
 #define IVTV_Z8F0811_IR_RX_I2C_ADDR	0x71
+#define IVTV_ADAPTEC_IR_ADDR		0x6b
 
 /* This array should match the IVTV_HW_ defines */
 static const u8 hw_addrs[] = {
@@ -118,6 +119,7 @@ static const u8 hw_addrs[] = {
 	IVTV_HAUP_INT_IR_RX_I2C_ADDR,	/* IVTV_HW_I2C_IR_RX_HAUP_INT */
 	IVTV_Z8F0811_IR_TX_I2C_ADDR,	/* IVTV_HW_Z8F0811_IR_TX_HAUP */
 	IVTV_Z8F0811_IR_RX_I2C_ADDR,	/* IVTV_HW_Z8F0811_IR_RX_HAUP */
+	IVTV_ADAPTEC_IR_ADDR,		/* IVTV_HW_I2C_IR_RX_ADAPTEC */
 };
 
 /* This array should match the IVTV_HW_ defines */
@@ -143,8 +145,34 @@ static const char * const hw_devicenames
 	"ir_video",		/* IVTV_HW_I2C_IR_RX_HAUP_INT */
 	"ir_tx_z8f0811_haup",	/* IVTV_HW_Z8F0811_IR_TX_HAUP */
 	"ir_rx_z8f0811_haup",	/* IVTV_HW_Z8F0811_IR_RX_HAUP */
+	"ir_video",		/* IVTV_HW_I2C_IR_RX_ADAPTEC */
 };
 
+static int get_key_adaptec(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
+{
+	unsigned char keybuf[4];
+
+	keybuf[0] = 0x00;
+	i2c_master_send(ir->c, keybuf, 1);
+	/* poll IR chip */
+	if (i2c_master_recv(ir->c, keybuf, sizeof(keybuf)) != sizeof(keybuf)) {
+		return 0;
+	}
+
+	/* key pressed ? */
+	if (keybuf[2] == 0xff)
+		return 0;
+
+	/* remove repeat bit */
+	keybuf[2] &= 0x7f;
+	keybuf[3] |= 0x80;
+
+	*ir_key = keybuf[3] | keybuf[2] << 8 | keybuf[1] << 16 |keybuf[0] << 24;
+	*ir_raw = *ir_key;
+
+	return 1;
+}
+
 static int ivtv_i2c_new_ir(struct ivtv *itv, u32 hw, const char *type, u8 addr)
 {
 	struct i2c_board_info info;
@@ -172,7 +200,7 @@ static int ivtv_i2c_new_ir(struct ivtv *
 		init_data->ir_codes = RC_MAP_AVERMEDIA_CARDBUS;
 		init_data->internal_get_key_func =
 					IR_KBD_GET_KEY_AVERMEDIA_CARDBUS;
-		init_data->type = IR_TYPE_OTHER;
+		init_data->type = RC_TYPE_OTHER;
 		init_data->name = "AVerMedia AVerTV card";
 		break;
 	case IVTV_HW_I2C_IR_RX_HAUP_EXT:
@@ -180,15 +208,22 @@ static int ivtv_i2c_new_ir(struct ivtv *
 		/* Default to old black remote */
 		init_data->ir_codes = RC_MAP_RC5_TV;
 		init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP;
-		init_data->type = IR_TYPE_RC5;
+		init_data->type = RC_TYPE_RC5;
 		init_data->name = itv->card_name;
 		break;
 	case IVTV_HW_Z8F0811_IR_RX_HAUP:
 		/* Default to grey remote */
 		init_data->ir_codes = RC_MAP_HAUPPAUGE_NEW;
 		init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR;
-		init_data->type = IR_TYPE_RC5;
+		init_data->type = RC_TYPE_RC5;
+		init_data->name = itv->card_name;
+		break;
+	case IVTV_HW_I2C_IR_RX_ADAPTEC:
+		init_data->get_key = get_key_adaptec;
 		init_data->name = itv->card_name;
+		/* FIXME: The protocol and RC_MAP needs to be corrected */
+		init_data->ir_codes = RC_MAP_EMPTY;
+		init_data->type = RC_TYPE_UNKNOWN;
 		break;
 	}
 
@@ -218,8 +253,6 @@ struct i2c_client *ivtv_i2c_new_ir_legac
 	const unsigned short addr_list[] = {
 		0x1a,	/* Hauppauge IR external - collides with WM8739 */
 		0x18,	/* Hauppauge IR internal */
-		0x71,	/* Hauppauge IR (PVR150) */
-		0x6b,	/* Adaptec IR */
 		I2C_CLIENT_END
 	};
 
@@ -267,10 +300,15 @@ int ivtv_i2c_register(struct ivtv *itv,
 				adap, type, 0, I2C_ADDRS(hw_addrs[idx]));
 	} else if (hw == IVTV_HW_CX25840) {
 		struct cx25840_platform_data pdata;
+		struct i2c_board_info cx25840_info = {
+			.type = "cx25840",
+			.addr = hw_addrs[idx],
+			.platform_data = &pdata,
+		};
 
 		pdata.pvr150_workaround = itv->pvr150_workaround;
-		sd = v4l2_i2c_new_subdev_cfg(&itv->v4l2_dev,
-				adap, type, 0, &pdata, hw_addrs[idx], NULL);
+		sd = v4l2_i2c_new_subdev_board(&itv->v4l2_dev, adap,
+				&cx25840_info, NULL);
 	} else {
 		sd = v4l2_i2c_new_subdev(&itv->v4l2_dev,
 				adap, type, hw_addrs[idx], NULL);
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/ivtv/ivtv-irq.c linux-libre-2.6.38-gnu1/drivers/media/video/ivtv/ivtv-irq.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/ivtv/ivtv-irq.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/ivtv/ivtv-irq.c	2011-03-14 21:20:32.000000000 -0400
@@ -628,22 +628,66 @@ static void ivtv_irq_enc_pio_complete(st
 static void ivtv_irq_dma_err(struct ivtv *itv)
 {
 	u32 data[CX2341X_MBOX_MAX_DATA];
+	u32 status;
 
 	del_timer(&itv->dma_timer);
+
 	ivtv_api_get_data(&itv->enc_mbox, IVTV_MBOX_DMA_END, 2, data);
+	status = read_reg(IVTV_REG_DMASTATUS);
 	IVTV_DEBUG_WARN("DMA ERROR %08x %08x %08x %d\n", data[0], data[1],
-				read_reg(IVTV_REG_DMASTATUS), itv->cur_dma_stream);
-	write_reg(read_reg(IVTV_REG_DMASTATUS) & 3, IVTV_REG_DMASTATUS);
+				status, itv->cur_dma_stream);
+	/*
+	 * We do *not* write back to the IVTV_REG_DMASTATUS register to
+	 * clear the error status, if either the encoder write (0x02) or
+	 * decoder read (0x01) bus master DMA operation do not indicate
+	 * completed.  We can race with the DMA engine, which may have
+	 * transitioned to completed status *after* we read the register.
+	 * Setting a IVTV_REG_DMASTATUS flag back to "busy" status, after the
+	 * DMA engine has completed, will cause the DMA engine to stop working.
+	 */
+	status &= 0x3;
+	if (status == 0x3)
+		write_reg(status, IVTV_REG_DMASTATUS);
+
 	if (!test_bit(IVTV_F_I_UDMA, &itv->i_flags) &&
 	    itv->cur_dma_stream >= 0 && itv->cur_dma_stream < IVTV_MAX_STREAMS) {
 		struct ivtv_stream *s = &itv->streams[itv->cur_dma_stream];
 
-		/* retry */
-		if (s->type >= IVTV_DEC_STREAM_TYPE_MPG)
+		if (s->type >= IVTV_DEC_STREAM_TYPE_MPG) {
+			/* retry */
+			/*
+			 * FIXME - handle cases of DMA error similar to
+			 * encoder below, except conditioned on status & 0x1
+			 */
 			ivtv_dma_dec_start(s);
-		else
-			ivtv_dma_enc_start(s);
-		return;
+			return;
+		} else {
+			if ((status & 0x2) == 0) {
+				/*
+				 * CX2341x Bus Master DMA write is ongoing.
+				 * Reset the timer and let it complete.
+				 */
+				itv->dma_timer.expires =
+						jiffies + msecs_to_jiffies(600);
+				add_timer(&itv->dma_timer);
+				return;
+			}
+
+			if (itv->dma_retries < 3) {
+				/*
+				 * CX2341x Bus Master DMA write has ended.
+				 * Retry the write, starting with the first
+				 * xfer segment. Just retrying the current
+				 * segment is not sufficient.
+				 */
+				s->sg_processed = 0;
+				itv->dma_retries++;
+				ivtv_dma_enc_start_xfer(s);
+				return;
+			}
+			/* Too many retries, give up on this one */
+		}
+
 	}
 	if (test_bit(IVTV_F_I_UDMA, &itv->i_flags)) {
 		ivtv_udma_start(itv);
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/ivtv/ivtv-vbi.c linux-libre-2.6.38-gnu1/drivers/media/video/ivtv/ivtv-vbi.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/ivtv/ivtv-vbi.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/ivtv/ivtv-vbi.c	2011-03-14 21:20:32.000000000 -0400
@@ -92,54 +92,97 @@ static int odd_parity(u8 c)
 	return c & 1;
 }
 
-void ivtv_write_vbi(struct ivtv *itv, const struct v4l2_sliced_vbi_data *sliced, size_t cnt)
+static void ivtv_write_vbi_line(struct ivtv *itv,
+				const struct v4l2_sliced_vbi_data *d,
+				struct vbi_cc *cc, int *found_cc)
 {
 	struct vbi_info *vi = &itv->vbi;
-	struct vbi_cc cc = { .odd = { 0x80, 0x80 }, .even = { 0x80, 0x80 } };
-	int found_cc = 0;
-	size_t i;
 
-	for (i = 0; i < cnt; i++) {
-		const struct v4l2_sliced_vbi_data *d = sliced + i;
-
-		if (d->id == V4L2_SLICED_CAPTION_525 && d->line == 21) {
-			if (d->field) {
-				cc.even[0] = d->data[0];
-				cc.even[1] = d->data[1];
-			} else {
-				cc.odd[0] = d->data[0];
-				cc.odd[1] = d->data[1];
-			}
-			found_cc = 1;
+	if (d->id == V4L2_SLICED_CAPTION_525 && d->line == 21) {
+		if (d->field) {
+			cc->even[0] = d->data[0];
+			cc->even[1] = d->data[1];
+		} else {
+			cc->odd[0] = d->data[0];
+			cc->odd[1] = d->data[1];
 		}
-		else if (d->id == V4L2_SLICED_VPS && d->line == 16 && d->field == 0) {
-			struct vbi_vps vps;
+		*found_cc = 1;
+	} else if (d->id == V4L2_SLICED_VPS && d->line == 16 && d->field == 0) {
+		struct vbi_vps vps;
 
-			vps.data[0] = d->data[2];
-			vps.data[1] = d->data[8];
-			vps.data[2] = d->data[9];
-			vps.data[3] = d->data[10];
-			vps.data[4] = d->data[11];
-			if (memcmp(&vps, &vi->vps_payload, sizeof(vps))) {
-				vi->vps_payload = vps;
-				set_bit(IVTV_F_I_UPDATE_VPS, &itv->i_flags);
-			}
+		vps.data[0] = d->data[2];
+		vps.data[1] = d->data[8];
+		vps.data[2] = d->data[9];
+		vps.data[3] = d->data[10];
+		vps.data[4] = d->data[11];
+		if (memcmp(&vps, &vi->vps_payload, sizeof(vps))) {
+			vi->vps_payload = vps;
+			set_bit(IVTV_F_I_UPDATE_VPS, &itv->i_flags);
 		}
-		else if (d->id == V4L2_SLICED_WSS_625 && d->line == 23 && d->field == 0) {
-			int wss = d->data[0] | d->data[1] << 8;
+	} else if (d->id == V4L2_SLICED_WSS_625 &&
+		   d->line == 23 && d->field == 0) {
+		int wss = d->data[0] | d->data[1] << 8;
 
-			if (vi->wss_payload != wss) {
-				vi->wss_payload = wss;
-				set_bit(IVTV_F_I_UPDATE_WSS, &itv->i_flags);
-			}
+		if (vi->wss_payload != wss) {
+			vi->wss_payload = wss;
+			set_bit(IVTV_F_I_UPDATE_WSS, &itv->i_flags);
 		}
 	}
-	if (found_cc && vi->cc_payload_idx < ARRAY_SIZE(vi->cc_payload)) {
-		vi->cc_payload[vi->cc_payload_idx++] = cc;
+}
+
+static void ivtv_write_vbi_cc_lines(struct ivtv *itv, const struct vbi_cc *cc)
+{
+	struct vbi_info *vi = &itv->vbi;
+
+	if (vi->cc_payload_idx < ARRAY_SIZE(vi->cc_payload)) {
+		memcpy(&vi->cc_payload[vi->cc_payload_idx], cc,
+		       sizeof(struct vbi_cc));
+		vi->cc_payload_idx++;
 		set_bit(IVTV_F_I_UPDATE_CC, &itv->i_flags);
 	}
 }
 
+static void ivtv_write_vbi(struct ivtv *itv,
+			   const struct v4l2_sliced_vbi_data *sliced,
+			   size_t cnt)
+{
+	struct vbi_cc cc = { .odd = { 0x80, 0x80 }, .even = { 0x80, 0x80 } };
+	int found_cc = 0;
+	size_t i;
+
+	for (i = 0; i < cnt; i++)
+		ivtv_write_vbi_line(itv, sliced + i, &cc, &found_cc);
+
+	if (found_cc)
+		ivtv_write_vbi_cc_lines(itv, &cc);
+}
+
+ssize_t
+ivtv_write_vbi_from_user(struct ivtv *itv,
+			 const struct v4l2_sliced_vbi_data __user *sliced,
+			 size_t cnt)
+{
+	struct vbi_cc cc = { .odd = { 0x80, 0x80 }, .even = { 0x80, 0x80 } };
+	int found_cc = 0;
+	size_t i;
+	struct v4l2_sliced_vbi_data d;
+	ssize_t ret = cnt * sizeof(struct v4l2_sliced_vbi_data);
+
+	for (i = 0; i < cnt; i++) {
+		if (copy_from_user(&d, sliced + i,
+				   sizeof(struct v4l2_sliced_vbi_data))) {
+			ret = -EFAULT;
+			break;
+		}
+		ivtv_write_vbi_line(itv, sliced + i, &cc, &found_cc);
+	}
+
+	if (found_cc)
+		ivtv_write_vbi_cc_lines(itv, &cc);
+
+	return ret;
+}
+
 static void copy_vbi_data(struct ivtv *itv, int lines, u32 pts_stamp)
 {
 	int line = 0;
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/ivtv/ivtv-vbi.h linux-libre-2.6.38-gnu1/drivers/media/video/ivtv/ivtv-vbi.h
--- linux-libre-2.6.37-gnu1/drivers/media/video/ivtv/ivtv-vbi.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/ivtv/ivtv-vbi.h	2011-03-14 21:20:32.000000000 -0400
@@ -20,7 +20,10 @@
 #ifndef IVTV_VBI_H
 #define IVTV_VBI_H
 
-void ivtv_write_vbi(struct ivtv *itv, const struct v4l2_sliced_vbi_data *sliced, size_t count);
+ssize_t
+ivtv_write_vbi_from_user(struct ivtv *itv,
+			 const struct v4l2_sliced_vbi_data __user *sliced,
+			 size_t count);
 void ivtv_process_vbi_data(struct ivtv *itv, struct ivtv_buffer *buf,
 			   u64 pts_stamp, int streamtype);
 int ivtv_used_line(struct ivtv *itv, int line, int field);
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/ivtv/Kconfig linux-libre-2.6.38-gnu1/drivers/media/video/ivtv/Kconfig
--- linux-libre-2.6.37-gnu1/drivers/media/video/ivtv/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/ivtv/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -1,9 +1,8 @@
 config VIDEO_IVTV
 	tristate "Conexant cx23416/cx23415 MPEG encoder/decoder support"
 	depends on VIDEO_V4L2 && PCI && I2C
-	depends on INPUT   # due to VIDEO_IR
 	select I2C_ALGOBIT
-	depends on VIDEO_IR
+	depends on RC_CORE
 	select VIDEO_TUNER
 	select VIDEO_TVEEPROM
 	select VIDEO_CX2341X
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/Kconfig linux-libre-2.6.38-gnu1/drivers/media/video/Kconfig
--- linux-libre-2.6.37-gnu1/drivers/media/video/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -7,11 +7,6 @@ config VIDEO_V4L2
 	depends on VIDEO_DEV && VIDEO_V4L2_COMMON
 	default VIDEO_DEV && VIDEO_V4L2_COMMON
 
-config VIDEO_V4L1
-	tristate
-	depends on VIDEO_DEV && VIDEO_V4L2_COMMON && VIDEO_ALLOW_V4L1
-	default VIDEO_DEV && VIDEO_V4L2_COMMON && VIDEO_ALLOW_V4L1
-
 config VIDEOBUF_GEN
 	tristate
 
@@ -83,7 +78,7 @@ config VIDEO_FIXED_MINOR_RANGES
 
 config VIDEO_HELPER_CHIPS_AUTO
 	bool "Autoselect pertinent encoders/decoders and other helper chips"
-	default y if !EMBEDDED
+	default y if !EXPERT
 	---help---
 	  Most video cards may require additional modules to encode or
 	  decode audio/video standards. This option will autoselect
@@ -96,7 +91,7 @@ config VIDEO_HELPER_CHIPS_AUTO
 
 config VIDEO_IR_I2C
 	tristate "I2C module for IR" if !VIDEO_HELPER_CHIPS_AUTO
-	depends on I2C && VIDEO_IR
+	depends on I2C && RC_CORE
 	default y
 	---help---
 	  Most boards have an IR chip directly connected via GPIO. However,
@@ -146,15 +141,6 @@ config VIDEO_TDA9840
 	  To compile this driver as a module, choose M here: the
 	  module will be called tda9840.
 
-config VIDEO_TDA9875
-	tristate "Philips TDA9875 audio processor"
-	depends on VIDEO_V4L2 && I2C
-	---help---
-	  Support for tda9875 audio decoder chip found on some bt8xx boards.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called tda9875.
-
 config VIDEO_TEA6415C
 	tristate "Philips TEA6415C audio processor"
 	depends on I2C
@@ -666,6 +652,16 @@ config VIDEO_HEXIUM_GEMINI
 	  To compile this driver as a module, choose M here: the
 	  module will be called hexium_gemini.
 
+config VIDEO_TIMBERDALE
+	tristate "Support for timberdale Video In/LogiWIN"
+	depends on VIDEO_V4L2 && I2C
+	select DMA_ENGINE
+	select TIMB_DMA
+	select VIDEO_ADV7180
+	select VIDEOBUF_DMA_CONTIG
+	---help---
+	Add support for the Video In peripherial of the timberdale FPGA.
+
 source "drivers/media/video/cx88/Kconfig"
 
 source "drivers/media/video/cx23885/Kconfig"
@@ -789,6 +785,12 @@ config SOC_CAMERA_PLATFORM
 	help
 	  This is a generic SoC camera platform driver, useful for testing
 
+config SOC_CAMERA_OV2640
+	tristate "ov2640 camera support"
+	depends on SOC_CAMERA && I2C
+	help
+	  This is a ov2640 camera driver
+
 config SOC_CAMERA_OV6650
 	tristate "ov6650 sensor support"
 	depends on SOC_CAMERA && I2C
@@ -905,21 +907,8 @@ source "drivers/media/video/cx231xx/Kcon
 
 source "drivers/media/video/usbvision/Kconfig"
 
-source "drivers/media/video/usbvideo/Kconfig"
-
 source "drivers/media/video/et61x251/Kconfig"
 
-config USB_SE401
-	tristate "USB SE401 Camera support"
-	depends on VIDEO_V4L1
-	---help---
-	  Say Y here if you want to connect this type of camera to your
-	  computer's USB port. See <file:Documentation/video4linux/se401.txt>
-	  for more information and for a list of supported cameras.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called se401.
-
 source "drivers/media/video/sn9c102/Kconfig"
 
 source "drivers/media/video/pwc/Kconfig"
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/Makefile linux-libre-2.6.38-gnu1/drivers/media/video/Makefile
--- linux-libre-2.6.37-gnu1/drivers/media/video/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -22,16 +22,11 @@ endif
 
 obj-$(CONFIG_VIDEO_V4L2_COMMON) += v4l2-common.o
 
-ifeq ($(CONFIG_VIDEO_V4L1_COMPAT),y)
-  obj-$(CONFIG_VIDEO_DEV) += v4l1-compat.o
-endif
-
 # All i2c modules must come first:
 
 obj-$(CONFIG_VIDEO_TUNER) += tuner.o
 obj-$(CONFIG_VIDEO_TVAUDIO) += tvaudio.o
 obj-$(CONFIG_VIDEO_TDA7432) += tda7432.o
-obj-$(CONFIG_VIDEO_TDA9875) += tda9875.o
 obj-$(CONFIG_VIDEO_SAA6588) += saa6588.o
 obj-$(CONFIG_VIDEO_TDA9840) += tda9840.o
 obj-$(CONFIG_VIDEO_TEA6415C) += tea6415c.o
@@ -79,6 +74,7 @@ obj-$(CONFIG_SOC_CAMERA_MT9M111)	+= mt9m
 obj-$(CONFIG_SOC_CAMERA_MT9T031)	+= mt9t031.o
 obj-$(CONFIG_SOC_CAMERA_MT9T112)	+= mt9t112.o
 obj-$(CONFIG_SOC_CAMERA_MT9V022)	+= mt9v022.o
+obj-$(CONFIG_SOC_CAMERA_OV2640)		+= ov2640.o
 obj-$(CONFIG_SOC_CAMERA_OV6650)		+= ov6650.o
 obj-$(CONFIG_SOC_CAMERA_OV772X)		+= ov772x.o
 obj-$(CONFIG_SOC_CAMERA_OV9640)		+= ov9640.o
@@ -106,6 +102,7 @@ obj-$(CONFIG_VIDEO_CPIA2) += cpia2/
 obj-$(CONFIG_VIDEO_MXB) += mxb.o
 obj-$(CONFIG_VIDEO_HEXIUM_ORION) += hexium_orion.o
 obj-$(CONFIG_VIDEO_HEXIUM_GEMINI) += hexium_gemini.o
+obj-$(CONFIG_VIDEO_TIMBERDALE)	+= timblogiw.o
 
 obj-$(CONFIG_VIDEOBUF_GEN) += videobuf-core.o
 obj-$(CONFIG_VIDEOBUF_DMA_SG) += videobuf-dma-sg.o
@@ -124,8 +121,6 @@ obj-$(CONFIG_VIDEO_CAFE_CCIC) += cafe_cc
 
 obj-$(CONFIG_VIDEO_VIA_CAMERA) += via-camera.o
 
-obj-$(CONFIG_USB_DABUSB)        += dabusb.o
-obj-$(CONFIG_USB_SE401)         += se401.o
 obj-$(CONFIG_USB_ZR364XX)       += zr364xx.o
 obj-$(CONFIG_USB_STKWEBCAM)     += stkwebcam.o
 
@@ -136,10 +131,6 @@ obj-$(CONFIG_USB_GSPCA)         += gspca
 
 obj-$(CONFIG_VIDEO_HDPVR)	+= hdpvr/
 
-obj-$(CONFIG_USB_IBMCAM)        += usbvideo/
-obj-$(CONFIG_USB_KONICAWC)      += usbvideo/
-obj-$(CONFIG_USB_VICAM)         += usbvideo/
-obj-$(CONFIG_USB_QUICKCAM_MESSENGER)	+= usbvideo/
 obj-$(CONFIG_USB_S2255)		+= s2255drv.o
 
 obj-$(CONFIG_VIDEO_IVTV) += ivtv/
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/mem2mem_testdev.c linux-libre-2.6.38-gnu1/drivers/media/video/mem2mem_testdev.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/mem2mem_testdev.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/mem2mem_testdev.c	2011-03-14 21:20:32.000000000 -0400
@@ -524,7 +524,6 @@ static int vidioc_s_fmt(struct m2mtest_c
 {
 	struct m2mtest_q_data *q_data;
 	struct videobuf_queue *vq;
-	int ret = 0;
 
 	vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type);
 	if (!vq)
@@ -534,12 +533,9 @@ static int vidioc_s_fmt(struct m2mtest_c
 	if (!q_data)
 		return -EINVAL;
 
-	mutex_lock(&vq->vb_lock);
-
 	if (videobuf_queue_is_busy(vq)) {
 		v4l2_err(&ctx->dev->v4l2_dev, "%s queue busy\n", __func__);
-		ret = -EBUSY;
-		goto out;
+		return -EBUSY;
 	}
 
 	q_data->fmt		= find_format(f);
@@ -553,9 +549,7 @@ static int vidioc_s_fmt(struct m2mtest_c
 		"Setting format for type %d, wxh: %dx%d, fmt: %d\n",
 		f->type, q_data->width, q_data->height, q_data->fmt->fourcc);
 
-out:
-	mutex_unlock(&vq->vb_lock);
-	return ret;
+	return 0;
 }
 
 static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
@@ -845,10 +839,12 @@ static void queue_init(void *priv, struc
 		       enum v4l2_buf_type type)
 {
 	struct m2mtest_ctx *ctx = priv;
+	struct m2mtest_dev *dev = ctx->dev;
 
-	videobuf_queue_vmalloc_init(vq, &m2mtest_qops, ctx->dev->v4l2_dev.dev,
-				    &ctx->dev->irqlock, type, V4L2_FIELD_NONE,
-				    sizeof(struct m2mtest_buffer), priv, NULL);
+	videobuf_queue_vmalloc_init(vq, &m2mtest_qops, dev->v4l2_dev.dev,
+				    &dev->irqlock, type, V4L2_FIELD_NONE,
+				    sizeof(struct m2mtest_buffer), priv,
+				    &dev->dev_mutex);
 }
 
 
@@ -920,7 +916,7 @@ static const struct v4l2_file_operations
 	.open		= m2mtest_open,
 	.release	= m2mtest_release,
 	.poll		= m2mtest_poll,
-	.ioctl		= video_ioctl2,
+	.unlocked_ioctl	= video_ioctl2,
 	.mmap		= m2mtest_mmap,
 };
 
@@ -965,6 +961,7 @@ static int m2mtest_probe(struct platform
 	}
 
 	*vfd = m2mtest_videodev;
+	vfd->lock = &dev->dev_mutex;
 
 	ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0);
 	if (ret) {
@@ -1014,7 +1011,6 @@ static int m2mtest_remove(struct platfor
 	v4l2_m2m_release(dev->m2m_dev);
 	del_timer_sync(&dev->timer);
 	video_unregister_device(dev->vfd);
-	video_device_release(dev->vfd);
 	v4l2_device_unregister(&dev->v4l2_dev);
 	kfree(dev);
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/mt9m001.c linux-libre-2.6.38-gnu1/drivers/media/video/mt9m001.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/mt9m001.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/mt9m001.c	2011-03-14 21:20:32.000000000 -0400
@@ -798,7 +798,6 @@ static int mt9m001_remove(struct i2c_cli
 
 	icd->ops = NULL;
 	mt9m001_video_remove(icd);
-	client->driver = NULL;
 	kfree(mt9m001);
 
 	return 0;
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/mt9m111.c linux-libre-2.6.38-gnu1/drivers/media/video/mt9m111.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/mt9m111.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/mt9m111.c	2011-03-14 21:20:32.000000000 -0400
@@ -1092,7 +1092,6 @@ static int mt9m111_remove(struct i2c_cli
 	struct soc_camera_device *icd = client->dev.platform_data;
 
 	icd->ops = NULL;
-	client->driver = NULL;
 	kfree(mt9m111);
 
 	return 0;
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/mt9t031.c linux-libre-2.6.38-gnu1/drivers/media/video/mt9t031.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/mt9t031.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/mt9t031.c	2011-03-14 21:20:32.000000000 -0400
@@ -896,7 +896,6 @@ static int mt9t031_remove(struct i2c_cli
 
 	if (icd)
 		icd->ops = NULL;
-	client->driver = NULL;
 	kfree(mt9t031);
 
 	return 0;
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/mt9v011.c linux-libre-2.6.38-gnu1/drivers/media/video/mt9v011.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/mt9v011.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/mt9v011.c	2011-03-14 21:20:32.000000000 -0400
@@ -12,17 +12,41 @@
 #include <asm/div64.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-chip-ident.h>
-#include "mt9v011.h"
+#include <media/mt9v011.h>
 
 MODULE_DESCRIPTION("Micron mt9v011 sensor driver");
 MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
 MODULE_LICENSE("GPL");
 
-
 static int debug;
 module_param(debug, int, 0);
 MODULE_PARM_DESC(debug, "Debug level (0-2)");
 
+#define R00_MT9V011_CHIP_VERSION	0x00
+#define R01_MT9V011_ROWSTART		0x01
+#define R02_MT9V011_COLSTART		0x02
+#define R03_MT9V011_HEIGHT		0x03
+#define R04_MT9V011_WIDTH		0x04
+#define R05_MT9V011_HBLANK		0x05
+#define R06_MT9V011_VBLANK		0x06
+#define R07_MT9V011_OUT_CTRL		0x07
+#define R09_MT9V011_SHUTTER_WIDTH	0x09
+#define R0A_MT9V011_CLK_SPEED		0x0a
+#define R0B_MT9V011_RESTART		0x0b
+#define R0C_MT9V011_SHUTTER_DELAY	0x0c
+#define R0D_MT9V011_RESET		0x0d
+#define R1E_MT9V011_DIGITAL_ZOOM	0x1e
+#define R20_MT9V011_READ_MODE		0x20
+#define R2B_MT9V011_GREEN_1_GAIN	0x2b
+#define R2C_MT9V011_BLUE_GAIN		0x2c
+#define R2D_MT9V011_RED_GAIN		0x2d
+#define R2E_MT9V011_GREEN_2_GAIN	0x2e
+#define R35_MT9V011_GLOBAL_GAIN		0x35
+#define RF1_MT9V011_CHIP_ENABLE		0xf1
+
+#define MT9V011_VERSION			0x8232
+#define MT9V011_REV_B_VERSION		0x8243
+
 /* supported controls */
 static struct v4l2_queryctrl mt9v011_qctrl[] = {
 	{
@@ -469,23 +493,6 @@ static int mt9v011_s_mbus_fmt(struct v4l
 	return 0;
 }
 
-static int mt9v011_s_config(struct v4l2_subdev *sd, int dumb, void *data)
-{
-	struct mt9v011 *core = to_mt9v011(sd);
-	unsigned *xtal = data;
-
-	v4l2_dbg(1, debug, sd, "s_config called\n");
-
-	if (xtal) {
-		core->xtal = *xtal;
-		v4l2_dbg(1, debug, sd, "xtal set to %d.%03d MHz\n",
-			 *xtal / 1000000, (*xtal / 1000) % 1000);
-	}
-
-	return 0;
-}
-
-
 #ifdef CONFIG_VIDEO_ADV_DEBUG
 static int mt9v011_g_register(struct v4l2_subdev *sd,
 			      struct v4l2_dbg_register *reg)
@@ -536,7 +543,6 @@ static const struct v4l2_subdev_core_ops
 	.g_ctrl = mt9v011_g_ctrl,
 	.s_ctrl = mt9v011_s_ctrl,
 	.reset = mt9v011_reset,
-	.s_config = mt9v011_s_config,
 	.g_chip_ident = mt9v011_g_chip_ident,
 #ifdef CONFIG_VIDEO_ADV_DEBUG
 	.g_register = mt9v011_g_register,
@@ -596,6 +602,14 @@ static int mt9v011_probe(struct i2c_clie
 	core->height = 480;
 	core->xtal = 27000000;	/* Hz */
 
+	if (c->dev.platform_data) {
+		struct mt9v011_platform_data *pdata = c->dev.platform_data;
+
+		core->xtal = pdata->xtal;
+		v4l2_dbg(1, debug, sd, "xtal set to %d.%03d MHz\n",
+			core->xtal / 1000000, (core->xtal / 1000) % 1000);
+	}
+
 	v4l_info(c, "chip found @ 0x%02x (%s - chip version 0x%04x)\n",
 		 c->addr << 1, c->adapter->name, version);
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/mt9v011.h linux-libre-2.6.38-gnu1/drivers/media/video/mt9v011.h
--- linux-libre-2.6.37-gnu1/drivers/media/video/mt9v011.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/mt9v011.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,36 +0,0 @@
-/*
- * mt9v011 -Micron 1/4-Inch VGA Digital Image Sensor
- *
- * Copyright (c) 2009 Mauro Carvalho Chehab (mchehab@redhat.com)
- * This code is placed under the terms of the GNU General Public License v2
- */
-
-#ifndef MT9V011_H_
-#define MT9V011_H_
-
-#define R00_MT9V011_CHIP_VERSION	0x00
-#define R01_MT9V011_ROWSTART		0x01
-#define R02_MT9V011_COLSTART		0x02
-#define R03_MT9V011_HEIGHT		0x03
-#define R04_MT9V011_WIDTH		0x04
-#define R05_MT9V011_HBLANK		0x05
-#define R06_MT9V011_VBLANK		0x06
-#define R07_MT9V011_OUT_CTRL		0x07
-#define R09_MT9V011_SHUTTER_WIDTH	0x09
-#define R0A_MT9V011_CLK_SPEED		0x0a
-#define R0B_MT9V011_RESTART		0x0b
-#define R0C_MT9V011_SHUTTER_DELAY	0x0c
-#define R0D_MT9V011_RESET		0x0d
-#define R1E_MT9V011_DIGITAL_ZOOM	0x1e
-#define R20_MT9V011_READ_MODE		0x20
-#define R2B_MT9V011_GREEN_1_GAIN	0x2b
-#define R2C_MT9V011_BLUE_GAIN		0x2c
-#define R2D_MT9V011_RED_GAIN		0x2d
-#define R2E_MT9V011_GREEN_2_GAIN	0x2e
-#define R35_MT9V011_GLOBAL_GAIN		0x35
-#define RF1_MT9V011_CHIP_ENABLE		0xf1
-
-#define MT9V011_VERSION			0x8232
-#define MT9V011_REV_B_VERSION		0x8243
-
-#endif
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/mt9v022.c linux-libre-2.6.38-gnu1/drivers/media/video/mt9v022.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/mt9v022.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/mt9v022.c	2011-03-14 21:20:32.000000000 -0400
@@ -930,7 +930,6 @@ static int mt9v022_remove(struct i2c_cli
 
 	icd->ops = NULL;
 	mt9v022_video_remove(icd);
-	client->driver = NULL;
 	kfree(mt9v022);
 
 	return 0;
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/mx1_camera.c linux-libre-2.6.38-gnu1/drivers/media/video/mx1_camera.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/mx1_camera.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/mx1_camera.c	2011-03-14 21:20:32.000000000 -0400
@@ -382,10 +382,9 @@ static void mx1_camera_init_videobuf(str
 	struct mx1_camera_dev *pcdev = ici->priv;
 
 	videobuf_queue_dma_contig_init(q, &mx1_videobuf_ops, icd->dev.parent,
-					&pcdev->lock,
-					V4L2_BUF_TYPE_VIDEO_CAPTURE,
-					V4L2_FIELD_NONE,
-					sizeof(struct mx1_buffer), icd, NULL);
+				&pcdev->lock, V4L2_BUF_TYPE_VIDEO_CAPTURE,
+				V4L2_FIELD_NONE,
+				sizeof(struct mx1_buffer), icd, &icd->video_lock);
 }
 
 static int mclk_get_divisor(struct mx1_camera_dev *pcdev)
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/mx2_camera.c linux-libre-2.6.38-gnu1/drivers/media/video/mx2_camera.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/mx2_camera.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/mx2_camera.c	2011-03-14 21:20:32.000000000 -0400
@@ -683,7 +683,8 @@ static void mx2_camera_init_videobuf(str
 
 	videobuf_queue_dma_contig_init(q, &mx2_videobuf_ops, pcdev->dev,
 			&pcdev->lock, V4L2_BUF_TYPE_VIDEO_CAPTURE,
-			V4L2_FIELD_NONE, sizeof(struct mx2_buffer), icd, NULL);
+			V4L2_FIELD_NONE, sizeof(struct mx2_buffer),
+			icd, &icd->video_lock);
 }
 
 #define MX2_BUS_FLAGS	(SOCAM_DATAWIDTH_8 | \
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/mx3_camera.c linux-libre-2.6.38-gnu1/drivers/media/video/mx3_camera.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/mx3_camera.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/mx3_camera.c	2011-03-14 21:20:32.000000000 -0400
@@ -443,7 +443,7 @@ static void mx3_camera_init_videobuf(str
 				       V4L2_BUF_TYPE_VIDEO_CAPTURE,
 				       V4L2_FIELD_NONE,
 				       sizeof(struct mx3_camera_buffer), icd,
-				       NULL);
+				       &icd->video_lock);
 }
 
 /* First part of ipu_csi_init_interface() */
@@ -1186,13 +1186,12 @@ static int __devinit mx3_camera_probe(st
 		goto egetres;
 	}
 
-	mx3_cam = vmalloc(sizeof(*mx3_cam));
+	mx3_cam = vzalloc(sizeof(*mx3_cam));
 	if (!mx3_cam) {
 		dev_err(&pdev->dev, "Could not allocate mx3 camera object\n");
 		err = -ENOMEM;
 		goto ealloc;
 	}
-	memset(mx3_cam, 0, sizeof(*mx3_cam));
 
 	mx3_cam->clk = clk_get(&pdev->dev, NULL);
 	if (IS_ERR(mx3_cam->clk)) {
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/mxb.c linux-libre-2.6.38-gnu1/drivers/media/video/mxb.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/mxb.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/mxb.c	2011-03-14 21:20:32.000000000 -0400
@@ -59,10 +59,10 @@ MODULE_PARM_DESC(debug, "Turn on/off dev
 enum { TUNER, AUX1, AUX3, AUX3_YC };
 
 static struct v4l2_input mxb_inputs[MXB_INPUTS] = {
-	{ TUNER,	"Tuner",		V4L2_INPUT_TYPE_TUNER,	1, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
-	{ AUX1,		"AUX1",			V4L2_INPUT_TYPE_CAMERA,	2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
-	{ AUX3,		"AUX3 Composite",	V4L2_INPUT_TYPE_CAMERA,	4, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
-	{ AUX3_YC,	"AUX3 S-Video",		V4L2_INPUT_TYPE_CAMERA,	4, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
+	{ TUNER,	"Tuner",		V4L2_INPUT_TYPE_TUNER,	1, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD },
+	{ AUX1,		"AUX1",			V4L2_INPUT_TYPE_CAMERA,	2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD },
+	{ AUX3,		"AUX3 Composite",	V4L2_INPUT_TYPE_CAMERA,	4, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD },
+	{ AUX3_YC,	"AUX3 S-Video",		V4L2_INPUT_TYPE_CAMERA,	4, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD },
 };
 
 /* this array holds the information, which port of the saa7146 each
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/omap/omap_vout.c linux-libre-2.6.38-gnu1/drivers/media/video/omap/omap_vout.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/omap/omap_vout.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/omap/omap_vout.c	2011-03-14 21:20:32.000000000 -0400
@@ -1286,7 +1286,7 @@ static int omap_vout_release(struct file
 	videobuf_mmap_free(q);
 
 	/* Even if apply changes fails we should continue
-	   freeing allocated memeory */
+	   freeing allocated memory */
 	if (vout->streaming) {
 		u32 mask = 0;
 
@@ -2230,7 +2230,6 @@ static int __init omap_vout_setup_video_
 
 	strlcpy(vfd->name, VOUT_NAME, sizeof(vfd->name));
 
-	/* need to register for a VID_HARDWARE_* ID in videodev.h */
 	vfd->fops = &omap_vout_fops;
 	vfd->v4l2_dev = &vout->vid_dev->v4l2_dev;
 	mutex_init(&vout->lock);
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/omap1_camera.c linux-libre-2.6.38-gnu1/drivers/media/video/omap1_camera.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/omap1_camera.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/omap1_camera.c	2011-03-14 21:20:32.000000000 -0400
@@ -1365,12 +1365,12 @@ static void omap1_cam_init_videobuf(stru
 		videobuf_queue_dma_contig_init(q, &omap1_videobuf_ops,
 				icd->dev.parent, &pcdev->lock,
 				V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_NONE,
-				sizeof(struct omap1_cam_buf), icd, NULL);
+				sizeof(struct omap1_cam_buf), icd, &icd->video_lock);
 	else
 		videobuf_queue_sg_init(q, &omap1_videobuf_ops,
 				icd->dev.parent, &pcdev->lock,
 				V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_NONE,
-				sizeof(struct omap1_cam_buf), icd, NULL);
+				sizeof(struct omap1_cam_buf), icd, &icd->video_lock);
 
 	/* use videobuf mode (auto)selected with the module parameter */
 	pcdev->vb_mode = sg_mode ? OMAP1_CAM_DMA_SG : OMAP1_CAM_DMA_CONTIG;
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/omap24xxcam.c linux-libre-2.6.38-gnu1/drivers/media/video/omap24xxcam.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/omap24xxcam.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/omap24xxcam.c	2011-03-14 21:20:32.000000000 -0400
@@ -1198,7 +1198,7 @@ static int vidioc_streamoff(struct file
 
 	atomic_inc(&cam->reset_disable);
 
-	flush_scheduled_work();
+	flush_work_sync(&cam->sensor_reset_work);
 
 	rval = videobuf_streamoff(q);
 	if (!rval) {
@@ -1512,7 +1512,7 @@ static int omap24xxcam_release(struct fi
 
 	atomic_inc(&cam->reset_disable);
 
-	flush_scheduled_work();
+	flush_work_sync(&cam->sensor_reset_work);
 
 	/* stop streaming capture */
 	videobuf_streamoff(&fh->vbq);
@@ -1536,7 +1536,7 @@ static int omap24xxcam_release(struct fi
 	 * not be scheduled anymore since streaming is already
 	 * disabled.)
 	 */
-	flush_scheduled_work();
+	flush_work_sync(&cam->sensor_reset_work);
 
 	mutex_lock(&cam->mutex);
 	if (atomic_dec_return(&cam->users) == 0) {
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/ov2640.c linux-libre-2.6.38-gnu1/drivers/media/video/ov2640.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/ov2640.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/ov2640.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,1205 @@
+/*
+ * ov2640 Camera Driver
+ *
+ * Copyright (C) 2010 Alberto Panizzo <maramaopercheseimorto@gmail.com>
+ *
+ * Based on ov772x, ov9640 drivers and previous non merged implementations.
+ *
+ * Copyright 2005-2009 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (C) 2006, OmniVision
+ *
+ * This program is free software; you can 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 <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/v4l2-subdev.h>
+#include <media/soc_camera.h>
+#include <media/soc_mediabus.h>
+
+#define VAL_SET(x, mask, rshift, lshift)  \
+		((((x) >> rshift) & mask) << lshift)
+/*
+ * DSP registers
+ * register offset for BANK_SEL == BANK_SEL_DSP
+ */
+#define R_BYPASS    0x05 /* Bypass DSP */
+#define   R_BYPASS_DSP_BYPAS    0x01 /* Bypass DSP, sensor out directly */
+#define   R_BYPASS_USE_DSP      0x00 /* Use the internal DSP */
+#define QS          0x44 /* Quantization Scale Factor */
+#define CTRLI       0x50
+#define   CTRLI_LP_DP           0x80
+#define   CTRLI_ROUND           0x40
+#define   CTRLI_V_DIV_SET(x)    VAL_SET(x, 0x3, 0, 3)
+#define   CTRLI_H_DIV_SET(x)    VAL_SET(x, 0x3, 0, 0)
+#define HSIZE       0x51 /* H_SIZE[7:0] (real/4) */
+#define   HSIZE_SET(x)          VAL_SET(x, 0xFF, 2, 0)
+#define VSIZE       0x52 /* V_SIZE[7:0] (real/4) */
+#define   VSIZE_SET(x)          VAL_SET(x, 0xFF, 2, 0)
+#define XOFFL       0x53 /* OFFSET_X[7:0] */
+#define   XOFFL_SET(x)          VAL_SET(x, 0xFF, 0, 0)
+#define YOFFL       0x54 /* OFFSET_Y[7:0] */
+#define   YOFFL_SET(x)          VAL_SET(x, 0xFF, 0, 0)
+#define VHYX        0x55 /* Offset and size completion */
+#define   VHYX_VSIZE_SET(x)     VAL_SET(x, 0x1, (8+2), 7)
+#define   VHYX_HSIZE_SET(x)     VAL_SET(x, 0x1, (8+2), 3)
+#define   VHYX_YOFF_SET(x)      VAL_SET(x, 0x3, 8, 4)
+#define   VHYX_XOFF_SET(x)      VAL_SET(x, 0x3, 8, 0)
+#define DPRP        0x56
+#define TEST        0x57 /* Horizontal size completion */
+#define   TEST_HSIZE_SET(x)     VAL_SET(x, 0x1, (9+2), 7)
+#define ZMOW        0x5A /* Zoom: Out Width  OUTW[7:0] (real/4) */
+#define   ZMOW_OUTW_SET(x)      VAL_SET(x, 0xFF, 2, 0)
+#define ZMOH        0x5B /* Zoom: Out Height OUTH[7:0] (real/4) */
+#define   ZMOH_OUTH_SET(x)      VAL_SET(x, 0xFF, 2, 0)
+#define ZMHH        0x5C /* Zoom: Speed and H&W completion */
+#define   ZMHH_ZSPEED_SET(x)    VAL_SET(x, 0x0F, 0, 4)
+#define   ZMHH_OUTH_SET(x)      VAL_SET(x, 0x1, (8+2), 2)
+#define   ZMHH_OUTW_SET(x)      VAL_SET(x, 0x3, (8+2), 0)
+#define BPADDR      0x7C /* SDE Indirect Register Access: Address */
+#define BPDATA      0x7D /* SDE Indirect Register Access: Data */
+#define CTRL2       0x86 /* DSP Module enable 2 */
+#define   CTRL2_DCW_EN          0x20
+#define   CTRL2_SDE_EN          0x10
+#define   CTRL2_UV_ADJ_EN       0x08
+#define   CTRL2_UV_AVG_EN       0x04
+#define   CTRL2_CMX_EN          0x01
+#define CTRL3       0x87 /* DSP Module enable 3 */
+#define   CTRL3_BPC_EN          0x80
+#define   CTRL3_WPC_EN          0x40
+#define SIZEL       0x8C /* Image Size Completion */
+#define   SIZEL_HSIZE8_11_SET(x) VAL_SET(x, 0x1, 11, 6)
+#define   SIZEL_HSIZE8_SET(x)    VAL_SET(x, 0x7, 0, 3)
+#define   SIZEL_VSIZE8_SET(x)    VAL_SET(x, 0x7, 0, 0)
+#define HSIZE8      0xC0 /* Image Horizontal Size HSIZE[10:3] */
+#define   HSIZE8_SET(x)         VAL_SET(x, 0xFF, 3, 0)
+#define VSIZE8      0xC1 /* Image Vertical Size VSIZE[10:3] */
+#define   VSIZE8_SET(x)         VAL_SET(x, 0xFF, 3, 0)
+#define CTRL0       0xC2 /* DSP Module enable 0 */
+#define   CTRL0_AEC_EN       0x80
+#define   CTRL0_AEC_SEL      0x40
+#define   CTRL0_STAT_SEL     0x20
+#define   CTRL0_VFIRST       0x10
+#define   CTRL0_YUV422       0x08
+#define   CTRL0_YUV_EN       0x04
+#define   CTRL0_RGB_EN       0x02
+#define   CTRL0_RAW_EN       0x01
+#define CTRL1       0xC3 /* DSP Module enable 1 */
+#define   CTRL1_CIP          0x80
+#define   CTRL1_DMY          0x40
+#define   CTRL1_RAW_GMA      0x20
+#define   CTRL1_DG           0x10
+#define   CTRL1_AWB          0x08
+#define   CTRL1_AWB_GAIN     0x04
+#define   CTRL1_LENC         0x02
+#define   CTRL1_PRE          0x01
+#define R_DVP_SP    0xD3 /* DVP output speed control */
+#define   R_DVP_SP_AUTO_MODE 0x80
+#define   R_DVP_SP_DVP_MASK  0x3F /* DVP PCLK = sysclk (48)/[6:0] (YUV0);
+				   *          = sysclk (48)/(2*[6:0]) (RAW);*/
+#define IMAGE_MODE  0xDA /* Image Output Format Select */
+#define   IMAGE_MODE_Y8_DVP_EN   0x40
+#define   IMAGE_MODE_JPEG_EN     0x10
+#define   IMAGE_MODE_YUV422      0x00
+#define   IMAGE_MODE_RAW10       0x04 /* (DVP) */
+#define   IMAGE_MODE_RGB565      0x08
+#define   IMAGE_MODE_HREF_VSYNC  0x02 /* HREF timing select in DVP JPEG output
+				       * mode (0 for HREF is same as sensor) */
+#define   IMAGE_MODE_LBYTE_FIRST 0x01 /* Byte swap enable for DVP
+				       *    1: Low byte first UYVY (C2[4] =0)
+				       *        VYUY (C2[4] =1)
+				       *    0: High byte first YUYV (C2[4]=0)
+				       *        YVYU (C2[4] = 1) */
+#define RESET       0xE0 /* Reset */
+#define   RESET_MICROC       0x40
+#define   RESET_SCCB         0x20
+#define   RESET_JPEG         0x10
+#define   RESET_DVP          0x04
+#define   RESET_IPU          0x02
+#define   RESET_CIF          0x01
+#define REGED       0xED /* Register ED */
+#define   REGED_CLK_OUT_DIS  0x10
+#define MS_SP       0xF0 /* SCCB Master Speed */
+#define SS_ID       0xF7 /* SCCB Slave ID */
+#define SS_CTRL     0xF8 /* SCCB Slave Control */
+#define   SS_CTRL_ADD_AUTO_INC  0x20
+#define   SS_CTRL_EN            0x08
+#define   SS_CTRL_DELAY_CLK     0x04
+#define   SS_CTRL_ACC_EN        0x02
+#define   SS_CTRL_SEN_PASS_THR  0x01
+#define MC_BIST     0xF9 /* Microcontroller misc register */
+#define   MC_BIST_RESET           0x80 /* Microcontroller Reset */
+#define   MC_BIST_BOOT_ROM_SEL    0x40
+#define   MC_BIST_12KB_SEL        0x20
+#define   MC_BIST_12KB_MASK       0x30
+#define   MC_BIST_512KB_SEL       0x08
+#define   MC_BIST_512KB_MASK      0x0C
+#define   MC_BIST_BUSY_BIT_R      0x02
+#define   MC_BIST_MC_RES_ONE_SH_W 0x02
+#define   MC_BIST_LAUNCH          0x01
+#define BANK_SEL    0xFF /* Register Bank Select */
+#define   BANK_SEL_DSP     0x00
+#define   BANK_SEL_SENS    0x01
+
+/*
+ * Sensor registers
+ * register offset for BANK_SEL == BANK_SEL_SENS
+ */
+#define GAIN        0x00 /* AGC - Gain control gain setting */
+#define COM1        0x03 /* Common control 1 */
+#define   COM1_1_DUMMY_FR          0x40
+#define   COM1_3_DUMMY_FR          0x80
+#define   COM1_7_DUMMY_FR          0xC0
+#define   COM1_VWIN_LSB_UXGA       0x0F
+#define   COM1_VWIN_LSB_SVGA       0x0A
+#define   COM1_VWIN_LSB_CIF        0x06
+#define REG04       0x04 /* Register 04 */
+#define   REG04_DEF             0x20 /* Always set */
+#define   REG04_HFLIP_IMG       0x80 /* Horizontal mirror image ON/OFF */
+#define   REG04_VFLIP_IMG       0x40 /* Vertical flip image ON/OFF */
+#define   REG04_VREF_EN         0x10
+#define   REG04_HREF_EN         0x08
+#define   REG04_AEC_SET(x)      VAL_SET(x, 0x3, 0, 0)
+#define REG08       0x08 /* Frame Exposure One-pin Control Pre-charge Row Num */
+#define COM2        0x09 /* Common control 2 */
+#define   COM2_SOFT_SLEEP_MODE  0x10 /* Soft sleep mode */
+				     /* Output drive capability */
+#define   COM2_OCAP_Nx_SET(N)   (((N) - 1) & 0x03) /* N = [1x .. 4x] */
+#define PID         0x0A /* Product ID Number MSB */
+#define VER         0x0B /* Product ID Number LSB */
+#define COM3        0x0C /* Common control 3 */
+#define   COM3_BAND_50H        0x04 /* 0 For Banding at 60H */
+#define   COM3_BAND_AUTO       0x02 /* Auto Banding */
+#define   COM3_SING_FR_SNAPSH  0x01 /* 0 For enable live video output after the
+				     * snapshot sequence*/
+#define AEC         0x10 /* AEC[9:2] Exposure Value */
+#define CLKRC       0x11 /* Internal clock */
+#define   CLKRC_EN             0x80
+#define   CLKRC_DIV_SET(x)     (((x) - 1) & 0x1F) /* CLK = XVCLK/(x) */
+#define COM7        0x12 /* Common control 7 */
+#define   COM7_SRST            0x80 /* Initiates system reset. All registers are
+				     * set to factory default values after which
+				     * the chip resumes normal operation */
+#define   COM7_RES_UXGA        0x00 /* Resolution selectors for UXGA */
+#define   COM7_RES_SVGA        0x40 /* SVGA */
+#define   COM7_RES_CIF         0x20 /* CIF */
+#define   COM7_ZOOM_EN         0x04 /* Enable Zoom mode */
+#define   COM7_COLOR_BAR_TEST  0x02 /* Enable Color Bar Test Pattern */
+#define COM8        0x13 /* Common control 8 */
+#define   COM8_DEF             0xC0 /* Banding filter ON/OFF */
+#define   COM8_BNDF_EN         0x20 /* Banding filter ON/OFF */
+#define   COM8_AGC_EN          0x04 /* AGC Auto/Manual control selection */
+#define   COM8_AEC_EN          0x01 /* Auto/Manual Exposure control */
+#define COM9        0x14 /* Common control 9
+			  * Automatic gain ceiling - maximum AGC value [7:5]*/
+#define   COM9_AGC_GAIN_2x     0x00 /* 000 :   2x */
+#define   COM9_AGC_GAIN_4x     0x20 /* 001 :   4x */
+#define   COM9_AGC_GAIN_8x     0x40 /* 010 :   8x */
+#define   COM9_AGC_GAIN_16x    0x60 /* 011 :  16x */
+#define   COM9_AGC_GAIN_32x    0x80 /* 100 :  32x */
+#define   COM9_AGC_GAIN_64x    0xA0 /* 101 :  64x */
+#define   COM9_AGC_GAIN_128x   0xC0 /* 110 : 128x */
+#define COM10       0x15 /* Common control 10 */
+#define   COM10_PCLK_HREF      0x20 /* PCLK output qualified by HREF */
+#define   COM10_PCLK_RISE      0x10 /* Data is updated at the rising edge of
+				     * PCLK (user can latch data at the next
+				     * falling edge of PCLK).
+				     * 0 otherwise. */
+#define   COM10_HREF_INV       0x08 /* Invert HREF polarity:
+				     * HREF negative for valid data*/
+#define   COM10_VSINC_INV      0x02 /* Invert VSYNC polarity */
+#define HSTART      0x17 /* Horizontal Window start MSB 8 bit */
+#define HEND        0x18 /* Horizontal Window end MSB 8 bit */
+#define VSTART      0x19 /* Vertical Window start MSB 8 bit */
+#define VEND        0x1A /* Vertical Window end MSB 8 bit */
+#define MIDH        0x1C /* Manufacturer ID byte - high */
+#define MIDL        0x1D /* Manufacturer ID byte - low  */
+#define AEW         0x24 /* AGC/AEC - Stable operating region (upper limit) */
+#define AEB         0x25 /* AGC/AEC - Stable operating region (lower limit) */
+#define VV          0x26 /* AGC/AEC Fast mode operating region */
+#define   VV_HIGH_TH_SET(x)      VAL_SET(x, 0xF, 0, 4)
+#define   VV_LOW_TH_SET(x)       VAL_SET(x, 0xF, 0, 0)
+#define REG2A       0x2A /* Dummy pixel insert MSB */
+#define FRARL       0x2B /* Dummy pixel insert LSB */
+#define ADDVFL      0x2D /* LSB of insert dummy lines in Vertical direction */
+#define ADDVFH      0x2E /* MSB of insert dummy lines in Vertical direction */
+#define YAVG        0x2F /* Y/G Channel Average value */
+#define REG32       0x32 /* Common Control 32 */
+#define   REG32_PCLK_DIV_2    0x80 /* PCLK freq divided by 2 */
+#define   REG32_PCLK_DIV_4    0xC0 /* PCLK freq divided by 4 */
+#define ARCOM2      0x34 /* Zoom: Horizontal start point */
+#define REG45       0x45 /* Register 45 */
+#define FLL         0x46 /* Frame Length Adjustment LSBs */
+#define FLH         0x47 /* Frame Length Adjustment MSBs */
+#define COM19       0x48 /* Zoom: Vertical start point */
+#define ZOOMS       0x49 /* Zoom: Vertical start point */
+#define COM22       0x4B /* Flash light control */
+#define COM25       0x4E /* For Banding operations */
+#define BD50        0x4F /* 50Hz Banding AEC 8 LSBs */
+#define BD60        0x50 /* 60Hz Banding AEC 8 LSBs */
+#define REG5D       0x5D /* AVGsel[7:0],   16-zone average weight option */
+#define REG5E       0x5E /* AVGsel[15:8],  16-zone average weight option */
+#define REG5F       0x5F /* AVGsel[23:16], 16-zone average weight option */
+#define REG60       0x60 /* AVGsel[31:24], 16-zone average weight option */
+#define HISTO_LOW   0x61 /* Histogram Algorithm Low Level */
+#define HISTO_HIGH  0x62 /* Histogram Algorithm High Level */
+
+/*
+ * ID
+ */
+#define MANUFACTURER_ID	0x7FA2
+#define PID_OV2640	0x2642
+#define VERSION(pid, ver) ((pid << 8) | (ver & 0xFF))
+
+/*
+ * Struct
+ */
+struct regval_list {
+	u8 reg_num;
+	u8 value;
+};
+
+/* Supported resolutions */
+enum ov2640_width {
+	W_QCIF	= 176,
+	W_QVGA	= 320,
+	W_CIF	= 352,
+	W_VGA	= 640,
+	W_SVGA	= 800,
+	W_XGA	= 1024,
+	W_SXGA	= 1280,
+	W_UXGA	= 1600,
+};
+
+enum ov2640_height {
+	H_QCIF	= 144,
+	H_QVGA	= 240,
+	H_CIF	= 288,
+	H_VGA	= 480,
+	H_SVGA	= 600,
+	H_XGA	= 768,
+	H_SXGA	= 1024,
+	H_UXGA	= 1200,
+};
+
+struct ov2640_win_size {
+	char				*name;
+	enum ov2640_width		width;
+	enum ov2640_height		height;
+	const struct regval_list	*regs;
+};
+
+
+struct ov2640_priv {
+	struct v4l2_subdev		subdev;
+	struct ov2640_camera_info	*info;
+	enum v4l2_mbus_pixelcode	cfmt_code;
+	const struct ov2640_win_size	*win;
+	int				model;
+	u16				flag_vflip:1;
+	u16				flag_hflip:1;
+};
+
+/*
+ * Registers settings
+ */
+
+#define ENDMARKER { 0xff, 0xff }
+
+static const struct regval_list ov2640_init_regs[] = {
+	{ BANK_SEL, BANK_SEL_DSP },
+	{ 0x2c,   0xff },
+	{ 0x2e,   0xdf },
+	{ BANK_SEL, BANK_SEL_SENS },
+	{ 0x3c,   0x32 },
+	{ CLKRC, CLKRC_DIV_SET(1) },
+	{ COM2, COM2_OCAP_Nx_SET(3) },
+	{ REG04, REG04_DEF | REG04_HREF_EN },
+	{ COM8,  COM8_DEF | COM8_BNDF_EN | COM8_AGC_EN | COM8_AEC_EN },
+	{ COM9, COM9_AGC_GAIN_8x | 0x08},
+	{ 0x2c,   0x0c },
+	{ 0x33,   0x78 },
+	{ 0x3a,   0x33 },
+	{ 0x3b,   0xfb },
+	{ 0x3e,   0x00 },
+	{ 0x43,   0x11 },
+	{ 0x16,   0x10 },
+	{ 0x39,   0x02 },
+	{ 0x35,   0x88 },
+	{ 0x22,   0x0a },
+	{ 0x37,   0x40 },
+	{ 0x23,   0x00 },
+	{ ARCOM2, 0xa0 },
+	{ 0x06,   0x02 },
+	{ 0x06,   0x88 },
+	{ 0x07,   0xc0 },
+	{ 0x0d,   0xb7 },
+	{ 0x0e,   0x01 },
+	{ 0x4c,   0x00 },
+	{ 0x4a,   0x81 },
+	{ 0x21,   0x99 },
+	{ AEW,    0x40 },
+	{ AEB,    0x38 },
+	{ VV,     VV_HIGH_TH_SET(0x08) | VV_LOW_TH_SET(0x02) },
+	{ 0x5c,   0x00 },
+	{ 0x63,   0x00 },
+	{ FLL,    0x22 },
+	{ COM3,   0x38 | COM3_BAND_AUTO },
+	{ REG5D,  0x55 },
+	{ REG5E,  0x7d },
+	{ REG5F,  0x7d },
+	{ REG60,  0x55 },
+	{ HISTO_LOW,   0x70 },
+	{ HISTO_HIGH,  0x80 },
+	{ 0x7c,   0x05 },
+	{ 0x20,   0x80 },
+	{ 0x28,   0x30 },
+	{ 0x6c,   0x00 },
+	{ 0x6d,   0x80 },
+	{ 0x6e,   0x00 },
+	{ 0x70,   0x02 },
+	{ 0x71,   0x94 },
+	{ 0x73,   0xc1 },
+	{ 0x3d,   0x34 },
+	{ COM7, COM7_RES_UXGA | COM7_ZOOM_EN },
+	{ 0x5a,   0x57 },
+	{ BD50,   0xbb },
+	{ BD60,   0x9c },
+	{ BANK_SEL, BANK_SEL_DSP },
+	{ 0xe5,   0x7f },
+	{ MC_BIST, MC_BIST_RESET | MC_BIST_BOOT_ROM_SEL },
+	{ 0x41,   0x24 },
+	{ RESET, RESET_JPEG | RESET_DVP },
+	{ 0x76,   0xff },
+	{ 0x33,   0xa0 },
+	{ 0x42,   0x20 },
+	{ 0x43,   0x18 },
+	{ 0x4c,   0x00 },
+	{ CTRL3, CTRL3_BPC_EN | CTRL3_WPC_EN | 0x10 },
+	{ 0x88,   0x3f },
+	{ 0xd7,   0x03 },
+	{ 0xd9,   0x10 },
+	{ R_DVP_SP , R_DVP_SP_AUTO_MODE | 0x2 },
+	{ 0xc8,   0x08 },
+	{ 0xc9,   0x80 },
+	{ BPADDR, 0x00 },
+	{ BPDATA, 0x00 },
+	{ BPADDR, 0x03 },
+	{ BPDATA, 0x48 },
+	{ BPDATA, 0x48 },
+	{ BPADDR, 0x08 },
+	{ BPDATA, 0x20 },
+	{ BPDATA, 0x10 },
+	{ BPDATA, 0x0e },
+	{ 0x90,   0x00 },
+	{ 0x91,   0x0e },
+	{ 0x91,   0x1a },
+	{ 0x91,   0x31 },
+	{ 0x91,   0x5a },
+	{ 0x91,   0x69 },
+	{ 0x91,   0x75 },
+	{ 0x91,   0x7e },
+	{ 0x91,   0x88 },
+	{ 0x91,   0x8f },
+	{ 0x91,   0x96 },
+	{ 0x91,   0xa3 },
+	{ 0x91,   0xaf },
+	{ 0x91,   0xc4 },
+	{ 0x91,   0xd7 },
+	{ 0x91,   0xe8 },
+	{ 0x91,   0x20 },
+	{ 0x92,   0x00 },
+	{ 0x93,   0x06 },
+	{ 0x93,   0xe3 },
+	{ 0x93,   0x03 },
+	{ 0x93,   0x03 },
+	{ 0x93,   0x00 },
+	{ 0x93,   0x02 },
+	{ 0x93,   0x00 },
+	{ 0x93,   0x00 },
+	{ 0x93,   0x00 },
+	{ 0x93,   0x00 },
+	{ 0x93,   0x00 },
+	{ 0x93,   0x00 },
+	{ 0x93,   0x00 },
+	{ 0x96,   0x00 },
+	{ 0x97,   0x08 },
+	{ 0x97,   0x19 },
+	{ 0x97,   0x02 },
+	{ 0x97,   0x0c },
+	{ 0x97,   0x24 },
+	{ 0x97,   0x30 },
+	{ 0x97,   0x28 },
+	{ 0x97,   0x26 },
+	{ 0x97,   0x02 },
+	{ 0x97,   0x98 },
+	{ 0x97,   0x80 },
+	{ 0x97,   0x00 },
+	{ 0x97,   0x00 },
+	{ 0xa4,   0x00 },
+	{ 0xa8,   0x00 },
+	{ 0xc5,   0x11 },
+	{ 0xc6,   0x51 },
+	{ 0xbf,   0x80 },
+	{ 0xc7,   0x10 },
+	{ 0xb6,   0x66 },
+	{ 0xb8,   0xA5 },
+	{ 0xb7,   0x64 },
+	{ 0xb9,   0x7C },
+	{ 0xb3,   0xaf },
+	{ 0xb4,   0x97 },
+	{ 0xb5,   0xFF },
+	{ 0xb0,   0xC5 },
+	{ 0xb1,   0x94 },
+	{ 0xb2,   0x0f },
+	{ 0xc4,   0x5c },
+	{ 0xa6,   0x00 },
+	{ 0xa7,   0x20 },
+	{ 0xa7,   0xd8 },
+	{ 0xa7,   0x1b },
+	{ 0xa7,   0x31 },
+	{ 0xa7,   0x00 },
+	{ 0xa7,   0x18 },
+	{ 0xa7,   0x20 },
+	{ 0xa7,   0xd8 },
+	{ 0xa7,   0x19 },
+	{ 0xa7,   0x31 },
+	{ 0xa7,   0x00 },
+	{ 0xa7,   0x18 },
+	{ 0xa7,   0x20 },
+	{ 0xa7,   0xd8 },
+	{ 0xa7,   0x19 },
+	{ 0xa7,   0x31 },
+	{ 0xa7,   0x00 },
+	{ 0xa7,   0x18 },
+	{ 0x7f,   0x00 },
+	{ 0xe5,   0x1f },
+	{ 0xe1,   0x77 },
+	{ 0xdd,   0x7f },
+	{ CTRL0,  CTRL0_YUV422 | CTRL0_YUV_EN | CTRL0_RGB_EN },
+	ENDMARKER,
+};
+
+/*
+ * Register settings for window size
+ * The preamble, setup the internal DSP to input an UXGA (1600x1200) image.
+ * Then the different zooming configurations will setup the output image size.
+ */
+static const struct regval_list ov2640_size_change_preamble_regs[] = {
+	{ BANK_SEL, BANK_SEL_DSP },
+	{ RESET, RESET_DVP },
+	{ HSIZE8, HSIZE8_SET(W_UXGA) },
+	{ VSIZE8, VSIZE8_SET(H_UXGA) },
+	{ CTRL2, CTRL2_DCW_EN | CTRL2_SDE_EN |
+		 CTRL2_UV_AVG_EN | CTRL2_CMX_EN | CTRL2_UV_ADJ_EN },
+	{ HSIZE, HSIZE_SET(W_UXGA) },
+	{ VSIZE, VSIZE_SET(H_UXGA) },
+	{ XOFFL, XOFFL_SET(0) },
+	{ YOFFL, YOFFL_SET(0) },
+	{ VHYX, VHYX_HSIZE_SET(W_UXGA) | VHYX_VSIZE_SET(H_UXGA) |
+		VHYX_XOFF_SET(0) | VHYX_YOFF_SET(0)},
+	{ TEST, TEST_HSIZE_SET(W_UXGA) },
+	ENDMARKER,
+};
+
+#define PER_SIZE_REG_SEQ(x, y, v_div, h_div, pclk_div)	\
+	{ CTRLI, CTRLI_LP_DP | CTRLI_V_DIV_SET(v_div) |	\
+		 CTRLI_H_DIV_SET(h_div)},		\
+	{ ZMOW, ZMOW_OUTW_SET(x) },			\
+	{ ZMOH, ZMOH_OUTH_SET(y) },			\
+	{ ZMHH, ZMHH_OUTW_SET(x) | ZMHH_OUTH_SET(y) },	\
+	{ R_DVP_SP, pclk_div },				\
+	{ RESET, 0x00}
+
+static const struct regval_list ov2640_qcif_regs[] = {
+	PER_SIZE_REG_SEQ(W_QCIF, H_QCIF, 3, 3, 4),
+	ENDMARKER,
+};
+
+static const struct regval_list ov2640_qvga_regs[] = {
+	PER_SIZE_REG_SEQ(W_QVGA, H_QVGA, 2, 2, 4),
+	ENDMARKER,
+};
+
+static const struct regval_list ov2640_cif_regs[] = {
+	PER_SIZE_REG_SEQ(W_CIF, H_CIF, 2, 2, 8),
+	ENDMARKER,
+};
+
+static const struct regval_list ov2640_vga_regs[] = {
+	PER_SIZE_REG_SEQ(W_VGA, H_VGA, 0, 0, 2),
+	ENDMARKER,
+};
+
+static const struct regval_list ov2640_svga_regs[] = {
+	PER_SIZE_REG_SEQ(W_SVGA, H_SVGA, 1, 1, 2),
+	ENDMARKER,
+};
+
+static const struct regval_list ov2640_xga_regs[] = {
+	PER_SIZE_REG_SEQ(W_XGA, H_XGA, 0, 0, 2),
+	{ CTRLI,    0x00},
+	ENDMARKER,
+};
+
+static const struct regval_list ov2640_sxga_regs[] = {
+	PER_SIZE_REG_SEQ(W_SXGA, H_SXGA, 0, 0, 2),
+	{ CTRLI,    0x00},
+	{ R_DVP_SP, 2 | R_DVP_SP_AUTO_MODE },
+	ENDMARKER,
+};
+
+static const struct regval_list ov2640_uxga_regs[] = {
+	PER_SIZE_REG_SEQ(W_UXGA, H_UXGA, 0, 0, 0),
+	{ CTRLI,    0x00},
+	{ R_DVP_SP, 0 | R_DVP_SP_AUTO_MODE },
+	ENDMARKER,
+};
+
+#define OV2640_SIZE(n, w, h, r) \
+	{.name = n, .width = w , .height = h, .regs = r }
+
+static const struct ov2640_win_size ov2640_supported_win_sizes[] = {
+	OV2640_SIZE("QCIF", W_QCIF, H_QCIF, ov2640_qcif_regs),
+	OV2640_SIZE("QVGA", W_QVGA, H_QVGA, ov2640_qvga_regs),
+	OV2640_SIZE("CIF", W_CIF, H_CIF, ov2640_cif_regs),
+	OV2640_SIZE("VGA", W_VGA, H_VGA, ov2640_vga_regs),
+	OV2640_SIZE("SVGA", W_SVGA, H_SVGA, ov2640_svga_regs),
+	OV2640_SIZE("XGA", W_XGA, H_XGA, ov2640_xga_regs),
+	OV2640_SIZE("SXGA", W_SXGA, H_SXGA, ov2640_sxga_regs),
+	OV2640_SIZE("UXGA", W_UXGA, H_UXGA, ov2640_uxga_regs),
+};
+
+/*
+ * Register settings for pixel formats
+ */
+static const struct regval_list ov2640_format_change_preamble_regs[] = {
+	{ BANK_SEL, BANK_SEL_DSP },
+	{ R_BYPASS, R_BYPASS_USE_DSP },
+	ENDMARKER,
+};
+
+static const struct regval_list ov2640_yuv422_regs[] = {
+	{ IMAGE_MODE, IMAGE_MODE_LBYTE_FIRST | IMAGE_MODE_YUV422 },
+	{ 0xD7, 0x01 },
+	{ 0x33, 0xa0 },
+	{ 0xe1, 0x67 },
+	{ RESET,  0x00 },
+	{ R_BYPASS, R_BYPASS_USE_DSP },
+	ENDMARKER,
+};
+
+static const struct regval_list ov2640_rgb565_regs[] = {
+	{ IMAGE_MODE, IMAGE_MODE_LBYTE_FIRST | IMAGE_MODE_RGB565 },
+	{ 0xd7, 0x03 },
+	{ RESET,  0x00 },
+	{ R_BYPASS, R_BYPASS_USE_DSP },
+	ENDMARKER,
+};
+
+static enum v4l2_mbus_pixelcode ov2640_codes[] = {
+	V4L2_MBUS_FMT_UYVY8_2X8,
+	V4L2_MBUS_FMT_RGB565_2X8_LE,
+};
+
+/*
+ * Supported controls
+ */
+static const struct v4l2_queryctrl ov2640_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_HFLIP,
+		.type		= V4L2_CTRL_TYPE_BOOLEAN,
+		.name		= "Flip Horizontally",
+		.minimum	= 0,
+		.maximum	= 1,
+		.step		= 1,
+		.default_value	= 0,
+	},
+};
+
+/*
+ * General functions
+ */
+static struct ov2640_priv *to_ov2640(const struct i2c_client *client)
+{
+	return container_of(i2c_get_clientdata(client), struct ov2640_priv,
+			    subdev);
+}
+
+static int ov2640_write_array(struct i2c_client *client,
+			      const struct regval_list *vals)
+{
+	int ret;
+
+	while ((vals->reg_num != 0xff) || (vals->value != 0xff)) {
+		ret = i2c_smbus_write_byte_data(client,
+						vals->reg_num, vals->value);
+		dev_vdbg(&client->dev, "array: 0x%02x, 0x%02x",
+			 vals->reg_num, vals->value);
+
+		if (ret < 0)
+			return ret;
+		vals++;
+	}
+	return 0;
+}
+
+static int ov2640_mask_set(struct i2c_client *client,
+			   u8  reg, u8  mask, u8  set)
+{
+	s32 val = i2c_smbus_read_byte_data(client, reg);
+	if (val < 0)
+		return val;
+
+	val &= ~mask;
+	val |= set & mask;
+
+	dev_vdbg(&client->dev, "masks: 0x%02x, 0x%02x", reg, val);
+
+	return i2c_smbus_write_byte_data(client, reg, val);
+}
+
+static int ov2640_reset(struct i2c_client *client)
+{
+	int ret;
+	const struct regval_list reset_seq[] = {
+		{BANK_SEL, BANK_SEL_SENS},
+		{COM7, COM7_SRST},
+		ENDMARKER,
+	};
+
+	ret = ov2640_write_array(client, reset_seq);
+	if (ret)
+		goto err;
+
+	msleep(5);
+err:
+	dev_dbg(&client->dev, "%s: (ret %d)", __func__, ret);
+	return ret;
+}
+
+/*
+ * soc_camera_ops functions
+ */
+static int ov2640_s_stream(struct v4l2_subdev *sd, int enable)
+{
+	return 0;
+}
+
+static int ov2640_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 support only the
+	 * sensors native bus width witch are tested working
+	 */
+	if (width_flag & (SOCAM_DATAWIDTH_10 | SOCAM_DATAWIDTH_8))
+		return 0;
+
+	return 0;
+}
+
+static unsigned long ov2640_query_bus_param(struct soc_camera_device *icd)
+{
+	struct soc_camera_link *icl = to_soc_camera_link(icd);
+	unsigned long flags = SOCAM_PCLK_SAMPLE_RISING | SOCAM_MASTER |
+		SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_HIGH |
+		SOCAM_DATA_ACTIVE_HIGH;
+
+	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 ov2640_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+{
+	struct i2c_client  *client = v4l2_get_subdevdata(sd);
+	struct ov2640_priv *priv = to_ov2640(client);
+
+	switch (ctrl->id) {
+	case V4L2_CID_VFLIP:
+		ctrl->value = priv->flag_vflip;
+		break;
+	case V4L2_CID_HFLIP:
+		ctrl->value = priv->flag_hflip;
+		break;
+	}
+	return 0;
+}
+
+static int ov2640_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+{
+	struct i2c_client  *client = v4l2_get_subdevdata(sd);
+	struct ov2640_priv *priv = to_ov2640(client);
+	int ret = 0;
+	u8 val;
+
+	switch (ctrl->id) {
+	case V4L2_CID_VFLIP:
+		val = ctrl->value ? REG04_VFLIP_IMG : 0x00;
+		priv->flag_vflip = ctrl->value ? 1 : 0;
+		ret = ov2640_mask_set(client, REG04, REG04_VFLIP_IMG, val);
+		break;
+	case V4L2_CID_HFLIP:
+		val = ctrl->value ? REG04_HFLIP_IMG : 0x00;
+		priv->flag_hflip = ctrl->value ? 1 : 0;
+		ret = ov2640_mask_set(client, REG04, REG04_HFLIP_IMG, val);
+		break;
+	}
+
+	return ret;
+}
+
+static int ov2640_g_chip_ident(struct v4l2_subdev *sd,
+			       struct v4l2_dbg_chip_ident *id)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct ov2640_priv *priv = to_ov2640(client);
+
+	id->ident    = priv->model;
+	id->revision = 0;
+
+	return 0;
+}
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static int ov2640_g_register(struct v4l2_subdev *sd,
+			     struct v4l2_dbg_register *reg)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	int ret;
+
+	reg->size = 1;
+	if (reg->reg > 0xff)
+		return -EINVAL;
+
+	ret = i2c_smbus_read_byte_data(client, reg->reg);
+	if (ret < 0)
+		return ret;
+
+	reg->val = ret;
+
+	return 0;
+}
+
+static int ov2640_s_register(struct v4l2_subdev *sd,
+			     struct v4l2_dbg_register *reg)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	if (reg->reg > 0xff ||
+	    reg->val > 0xff)
+		return -EINVAL;
+
+	return i2c_smbus_write_byte_data(client, reg->reg, reg->val);
+}
+#endif
+
+/* Select the nearest higher resolution for capture */
+static const struct ov2640_win_size *ov2640_select_win(u32 *width, u32 *height)
+{
+	int i, default_size = ARRAY_SIZE(ov2640_supported_win_sizes) - 1;
+
+	for (i = 0; i < ARRAY_SIZE(ov2640_supported_win_sizes); i++) {
+		if (ov2640_supported_win_sizes[i].width  >= *width &&
+		    ov2640_supported_win_sizes[i].height >= *height) {
+			*width = ov2640_supported_win_sizes[i].width;
+			*height = ov2640_supported_win_sizes[i].height;
+			return &ov2640_supported_win_sizes[i];
+		}
+	}
+
+	*width = ov2640_supported_win_sizes[default_size].width;
+	*height = ov2640_supported_win_sizes[default_size].height;
+	return &ov2640_supported_win_sizes[default_size];
+}
+
+static int ov2640_set_params(struct i2c_client *client, u32 *width, u32 *height,
+			     enum v4l2_mbus_pixelcode code)
+{
+	struct ov2640_priv       *priv = to_ov2640(client);
+	const struct regval_list *selected_cfmt_regs;
+	int ret;
+
+	/* select win */
+	priv->win = ov2640_select_win(width, height);
+
+	/* select format */
+	priv->cfmt_code = 0;
+	switch (code) {
+	case V4L2_MBUS_FMT_RGB565_2X8_LE:
+		dev_dbg(&client->dev, "%s: Selected cfmt RGB565", __func__);
+		selected_cfmt_regs = ov2640_rgb565_regs;
+		break;
+	default:
+	case V4L2_MBUS_FMT_UYVY8_2X8:
+		dev_dbg(&client->dev, "%s: Selected cfmt YUV422", __func__);
+		selected_cfmt_regs = ov2640_yuv422_regs;
+	}
+
+	/* reset hardware */
+	ov2640_reset(client);
+
+	/* initialize the sensor with default data */
+	dev_dbg(&client->dev, "%s: Init default", __func__);
+	ret = ov2640_write_array(client, ov2640_init_regs);
+	if (ret < 0)
+		goto err;
+
+	/* select preamble */
+	dev_dbg(&client->dev, "%s: Set size to %s", __func__, priv->win->name);
+	ret = ov2640_write_array(client, ov2640_size_change_preamble_regs);
+	if (ret < 0)
+		goto err;
+
+	/* set size win */
+	ret = ov2640_write_array(client, priv->win->regs);
+	if (ret < 0)
+		goto err;
+
+	/* cfmt preamble */
+	dev_dbg(&client->dev, "%s: Set cfmt", __func__);
+	ret = ov2640_write_array(client, ov2640_format_change_preamble_regs);
+	if (ret < 0)
+		goto err;
+
+	/* set cfmt */
+	ret = ov2640_write_array(client, selected_cfmt_regs);
+	if (ret < 0)
+		goto err;
+
+	priv->cfmt_code = code;
+	*width = priv->win->width;
+	*height = priv->win->height;
+
+	return 0;
+
+err:
+	dev_err(&client->dev, "%s: Error %d", __func__, ret);
+	ov2640_reset(client);
+	priv->win = NULL;
+
+	return ret;
+}
+
+static int ov2640_g_fmt(struct v4l2_subdev *sd,
+			struct v4l2_mbus_framefmt *mf)
+{
+	struct i2c_client  *client = v4l2_get_subdevdata(sd);
+	struct ov2640_priv *priv = to_ov2640(client);
+
+	if (!priv->win) {
+		u32 width = W_SVGA, height = H_SVGA;
+		int ret = ov2640_set_params(client, &width, &height,
+					    V4L2_MBUS_FMT_UYVY8_2X8);
+		if (ret < 0)
+			return ret;
+	}
+
+	mf->width	= priv->win->width;
+	mf->height	= priv->win->height;
+	mf->code	= priv->cfmt_code;
+
+	switch (mf->code) {
+	case V4L2_MBUS_FMT_RGB565_2X8_LE:
+		mf->colorspace = V4L2_COLORSPACE_SRGB;
+		break;
+	default:
+	case V4L2_MBUS_FMT_UYVY8_2X8:
+		mf->colorspace = V4L2_COLORSPACE_JPEG;
+	}
+	mf->field	= V4L2_FIELD_NONE;
+
+	return 0;
+}
+
+static int ov2640_s_fmt(struct v4l2_subdev *sd,
+			struct v4l2_mbus_framefmt *mf)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	int ret;
+
+
+	switch (mf->code) {
+	case V4L2_MBUS_FMT_RGB565_2X8_LE:
+		mf->colorspace = V4L2_COLORSPACE_SRGB;
+		break;
+	default:
+		mf->code = V4L2_MBUS_FMT_UYVY8_2X8;
+	case V4L2_MBUS_FMT_UYVY8_2X8:
+		mf->colorspace = V4L2_COLORSPACE_JPEG;
+	}
+
+	ret = ov2640_set_params(client, &mf->width, &mf->height, mf->code);
+
+	return ret;
+}
+
+static int ov2640_try_fmt(struct v4l2_subdev *sd,
+			  struct v4l2_mbus_framefmt *mf)
+{
+	const struct ov2640_win_size *win;
+
+	/*
+	 * select suitable win
+	 */
+	win = ov2640_select_win(&mf->width, &mf->height);
+
+	mf->field	= V4L2_FIELD_NONE;
+
+	switch (mf->code) {
+	case V4L2_MBUS_FMT_RGB565_2X8_LE:
+		mf->colorspace = V4L2_COLORSPACE_SRGB;
+		break;
+	default:
+		mf->code = V4L2_MBUS_FMT_UYVY8_2X8;
+	case V4L2_MBUS_FMT_UYVY8_2X8:
+		mf->colorspace = V4L2_COLORSPACE_JPEG;
+	}
+
+	return 0;
+}
+
+static int ov2640_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
+			   enum v4l2_mbus_pixelcode *code)
+{
+	if (index >= ARRAY_SIZE(ov2640_codes))
+		return -EINVAL;
+
+	*code = ov2640_codes[index];
+	return 0;
+}
+
+static int ov2640_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
+{
+	a->c.left	= 0;
+	a->c.top	= 0;
+	a->c.width	= W_UXGA;
+	a->c.height	= H_UXGA;
+	a->type		= V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+	return 0;
+}
+
+static int ov2640_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a)
+{
+	a->bounds.left			= 0;
+	a->bounds.top			= 0;
+	a->bounds.width			= W_UXGA;
+	a->bounds.height		= H_UXGA;
+	a->defrect			= a->bounds;
+	a->type				= V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	a->pixelaspect.numerator	= 1;
+	a->pixelaspect.denominator	= 1;
+
+	return 0;
+}
+
+static int ov2640_video_probe(struct soc_camera_device *icd,
+			      struct i2c_client *client)
+{
+	struct ov2640_priv *priv = to_ov2640(client);
+	u8 pid, ver, midh, midl;
+	const char *devname;
+	int ret;
+
+	/*
+	 * we must have a parent by now. And it cannot be a wrong one.
+	 * So this entire test is completely redundant.
+	 */
+	if (!icd->dev.parent ||
+	    to_soc_camera_host(icd->dev.parent)->nr != icd->iface) {
+		dev_err(&client->dev, "Parent missing or invalid!\n");
+		ret = -ENODEV;
+		goto err;
+	}
+
+	/*
+	 * check and show product ID and manufacturer ID
+	 */
+	i2c_smbus_write_byte_data(client, BANK_SEL, BANK_SEL_SENS);
+	pid  = i2c_smbus_read_byte_data(client, PID);
+	ver  = i2c_smbus_read_byte_data(client, VER);
+	midh = i2c_smbus_read_byte_data(client, MIDH);
+	midl = i2c_smbus_read_byte_data(client, MIDL);
+
+	switch (VERSION(pid, ver)) {
+	case PID_OV2640:
+		devname     = "ov2640";
+		priv->model = V4L2_IDENT_OV2640;
+		break;
+	default:
+		dev_err(&client->dev,
+			"Product ID error %x:%x\n", pid, ver);
+		ret = -ENODEV;
+		goto err;
+	}
+
+	dev_info(&client->dev,
+		 "%s Product ID %0x:%0x Manufacturer ID %x:%x\n",
+		 devname, pid, ver, midh, midl);
+
+	return 0;
+
+err:
+	return ret;
+}
+
+static struct soc_camera_ops ov2640_ops = {
+	.set_bus_param		= ov2640_set_bus_param,
+	.query_bus_param	= ov2640_query_bus_param,
+	.controls		= ov2640_controls,
+	.num_controls		= ARRAY_SIZE(ov2640_controls),
+};
+
+static struct v4l2_subdev_core_ops ov2640_subdev_core_ops = {
+	.g_ctrl		= ov2640_g_ctrl,
+	.s_ctrl		= ov2640_s_ctrl,
+	.g_chip_ident	= ov2640_g_chip_ident,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+	.g_register	= ov2640_g_register,
+	.s_register	= ov2640_s_register,
+#endif
+};
+
+static struct v4l2_subdev_video_ops ov2640_subdev_video_ops = {
+	.s_stream	= ov2640_s_stream,
+	.g_mbus_fmt	= ov2640_g_fmt,
+	.s_mbus_fmt	= ov2640_s_fmt,
+	.try_mbus_fmt	= ov2640_try_fmt,
+	.cropcap	= ov2640_cropcap,
+	.g_crop		= ov2640_g_crop,
+	.enum_mbus_fmt	= ov2640_enum_fmt,
+};
+
+static struct v4l2_subdev_ops ov2640_subdev_ops = {
+	.core	= &ov2640_subdev_core_ops,
+	.video	= &ov2640_subdev_video_ops,
+};
+
+/*
+ * i2c_driver functions
+ */
+static int ov2640_probe(struct i2c_client *client,
+			const struct i2c_device_id *did)
+{
+	struct ov2640_priv        *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;
+	int                        ret;
+
+	if (!icd) {
+		dev_err(&adapter->dev, "OV2640: missing soc-camera data!\n");
+		return -EINVAL;
+	}
+
+	icl = to_soc_camera_link(icd);
+	if (!icl) {
+		dev_err(&adapter->dev,
+			"OV2640: Missing platform_data for driver\n");
+		return -EINVAL;
+	}
+
+	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
+		dev_err(&adapter->dev,
+			"OV2640: I2C-Adapter doesn't support SMBUS\n");
+		return -EIO;
+	}
+
+	priv = kzalloc(sizeof(struct ov2640_priv), GFP_KERNEL);
+	if (!priv) {
+		dev_err(&adapter->dev,
+			"Failed to allocate memory for private data!\n");
+		return -ENOMEM;
+	}
+
+	priv->info = icl->priv;
+
+	v4l2_i2c_subdev_init(&priv->subdev, client, &ov2640_subdev_ops);
+
+	icd->ops = &ov2640_ops;
+
+	ret = ov2640_video_probe(icd, client);
+	if (ret) {
+		icd->ops = NULL;
+		kfree(priv);
+	} else {
+		dev_info(&adapter->dev, "OV2640 Probed\n");
+	}
+
+	return ret;
+}
+
+static int ov2640_remove(struct i2c_client *client)
+{
+	struct ov2640_priv       *priv = to_ov2640(client);
+	struct soc_camera_device *icd = client->dev.platform_data;
+
+	icd->ops = NULL;
+	kfree(priv);
+	return 0;
+}
+
+static const struct i2c_device_id ov2640_id[] = {
+	{ "ov2640", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, ov2640_id);
+
+static struct i2c_driver ov2640_i2c_driver = {
+	.driver = {
+		.name = "ov2640",
+	},
+	.probe    = ov2640_probe,
+	.remove   = ov2640_remove,
+	.id_table = ov2640_id,
+};
+
+/*
+ * Module functions
+ */
+static int __init ov2640_module_init(void)
+{
+	return i2c_add_driver(&ov2640_i2c_driver);
+}
+
+static void __exit ov2640_module_exit(void)
+{
+	i2c_del_driver(&ov2640_i2c_driver);
+}
+
+module_init(ov2640_module_init);
+module_exit(ov2640_module_exit);
+
+MODULE_DESCRIPTION("SoC Camera driver for Omni Vision 2640 sensor");
+MODULE_AUTHOR("Alberto Panizzo");
+MODULE_LICENSE("GPL v2");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/ov7670.c linux-libre-2.6.38-gnu1/drivers/media/video/ov7670.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/ov7670.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/ov7670.c	2011-03-14 21:20:32.000000000 -0400
@@ -1449,47 +1449,6 @@ static int ov7670_g_chip_ident(struct v4
 	return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_OV7670, 0);
 }
 
-static int ov7670_s_config(struct v4l2_subdev *sd, int dumb, void *data)
-{
-	struct i2c_client *client = v4l2_get_subdevdata(sd);
-	struct ov7670_config *config = data;
-	struct ov7670_info *info = to_state(sd);
-	int ret;
-
-	info->clock_speed = 30; /* default: a guess */
-
-	/*
-	 * Must apply configuration before initializing device, because it
-	 * selects I/O method.
-	 */
-	if (config) {
-		info->min_width = config->min_width;
-		info->min_height = config->min_height;
-		info->use_smbus = config->use_smbus;
-
-		if (config->clock_speed)
-			info->clock_speed = config->clock_speed;
-	}
-
-	/* Make sure it's an ov7670 */
-	ret = ov7670_detect(sd);
-	if (ret) {
-		v4l_dbg(1, debug, client,
-			"chip found @ 0x%x (%s) is not an ov7670 chip.\n",
-			client->addr << 1, client->adapter->name);
-		kfree(info);
-		return ret;
-	}
-	v4l_info(client, "chip found @ 0x%02x (%s)\n",
-			client->addr << 1, client->adapter->name);
-
-	info->fmt = &ov7670_formats[0];
-	info->sat = 128;	/* Review this */
-	info->clkrc = info->clock_speed / 30;
-
-	return 0;
-}
-
 #ifdef CONFIG_VIDEO_ADV_DEBUG
 static int ov7670_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
 {
@@ -1528,7 +1487,6 @@ static const struct v4l2_subdev_core_ops
 	.s_ctrl = ov7670_s_ctrl,
 	.queryctrl = ov7670_queryctrl,
 	.reset = ov7670_reset,
-	.s_config = ov7670_s_config,
 	.init = ov7670_init,
 #ifdef CONFIG_VIDEO_ADV_DEBUG
 	.g_register = ov7670_g_register,
@@ -1558,6 +1516,7 @@ static int ov7670_probe(struct i2c_clien
 {
 	struct v4l2_subdev *sd;
 	struct ov7670_info *info;
+	int ret;
 
 	info = kzalloc(sizeof(struct ov7670_info), GFP_KERNEL);
 	if (info == NULL)
@@ -1565,6 +1524,37 @@ static int ov7670_probe(struct i2c_clien
 	sd = &info->sd;
 	v4l2_i2c_subdev_init(sd, client, &ov7670_ops);
 
+	info->clock_speed = 30; /* default: a guess */
+	if (client->dev.platform_data) {
+		struct ov7670_config *config = client->dev.platform_data;
+
+		/*
+		 * Must apply configuration before initializing device, because it
+		 * selects I/O method.
+		 */
+		info->min_width = config->min_width;
+		info->min_height = config->min_height;
+		info->use_smbus = config->use_smbus;
+
+		if (config->clock_speed)
+			info->clock_speed = config->clock_speed;
+	}
+
+	/* Make sure it's an ov7670 */
+	ret = ov7670_detect(sd);
+	if (ret) {
+		v4l_dbg(1, debug, client,
+			"chip found @ 0x%x (%s) is not an ov7670 chip.\n",
+			client->addr << 1, client->adapter->name);
+		kfree(info);
+		return ret;
+	}
+	v4l_info(client, "chip found @ 0x%02x (%s)\n",
+			client->addr << 1, client->adapter->name);
+
+	info->fmt = &ov7670_formats[0];
+	info->sat = 128;	/* Review this */
+	info->clkrc = info->clock_speed / 30;
 	return 0;
 }
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/ov772x.c linux-libre-2.6.38-gnu1/drivers/media/video/ov772x.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/ov772x.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/ov772x.c	2011-03-14 21:20:32.000000000 -0400
@@ -600,7 +600,7 @@ static int ov772x_reset(struct i2c_clien
 static int ov772x_s_stream(struct v4l2_subdev *sd, int enable)
 {
 	struct i2c_client *client = v4l2_get_subdevdata(sd);
-	struct ov772x_priv *priv = to_ov772x(client);
+	struct ov772x_priv *priv = container_of(sd, struct ov772x_priv, subdev);
 
 	if (!enable) {
 		ov772x_mask_set(client, COM2, SOFT_SLEEP_MODE, SOFT_SLEEP_MODE);
@@ -645,8 +645,7 @@ static unsigned long ov772x_query_bus_pa
 
 static int ov772x_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
 {
-	struct i2c_client *client = v4l2_get_subdevdata(sd);
-	struct ov772x_priv *priv = to_ov772x(client);
+	struct ov772x_priv *priv = container_of(sd, struct ov772x_priv, subdev);
 
 	switch (ctrl->id) {
 	case V4L2_CID_VFLIP:
@@ -665,7 +664,7 @@ static int ov772x_g_ctrl(struct v4l2_sub
 static int ov772x_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
 {
 	struct i2c_client *client = v4l2_get_subdevdata(sd);
-	struct ov772x_priv *priv = to_ov772x(client);
+	struct ov772x_priv *priv = container_of(sd, struct ov772x_priv, subdev);
 	int ret = 0;
 	u8 val;
 
@@ -715,8 +714,7 @@ static int ov772x_s_ctrl(struct v4l2_sub
 static int ov772x_g_chip_ident(struct v4l2_subdev *sd,
 			       struct v4l2_dbg_chip_ident *id)
 {
-	struct i2c_client *client = v4l2_get_subdevdata(sd);
-	struct ov772x_priv *priv = to_ov772x(client);
+	struct ov772x_priv *priv = container_of(sd, struct ov772x_priv, subdev);
 
 	id->ident    = priv->model;
 	id->revision = 0;
@@ -955,7 +953,7 @@ static int ov772x_g_fmt(struct v4l2_subd
 			struct v4l2_mbus_framefmt *mf)
 {
 	struct i2c_client *client = v4l2_get_subdevdata(sd);
-	struct ov772x_priv *priv = to_ov772x(client);
+	struct ov772x_priv *priv = container_of(sd, struct ov772x_priv, subdev);
 
 	if (!priv->win || !priv->cfmt) {
 		u32 width = VGA_WIDTH, height = VGA_HEIGHT;
@@ -978,7 +976,7 @@ static int ov772x_s_fmt(struct v4l2_subd
 			struct v4l2_mbus_framefmt *mf)
 {
 	struct i2c_client *client = v4l2_get_subdevdata(sd);
-	struct ov772x_priv *priv = to_ov772x(client);
+	struct ov772x_priv *priv = container_of(sd, struct ov772x_priv, subdev);
 	int ret = ov772x_set_params(client, &mf->width, &mf->height,
 				    mf->code);
 
@@ -991,8 +989,7 @@ static int ov772x_s_fmt(struct v4l2_subd
 static int ov772x_try_fmt(struct v4l2_subdev *sd,
 			  struct v4l2_mbus_framefmt *mf)
 {
-	struct i2c_client *client = v4l2_get_subdevdata(sd);
-	struct ov772x_priv *priv = to_ov772x(client);
+	struct ov772x_priv *priv = container_of(sd, struct ov772x_priv, subdev);
 	const struct ov772x_win_size *win;
 	int i;
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/ov9640.c linux-libre-2.6.38-gnu1/drivers/media/video/ov9640.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/ov9640.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/ov9640.c	2011-03-14 21:20:32.000000000 -0400
@@ -31,6 +31,8 @@
 
 #include "ov9640.h"
 
+#define to_ov9640_sensor(sd)	container_of(sd, struct ov9640_priv, subdev)
+
 /* default register setup */
 static const struct ov9640_reg ov9640_regs_dflt[] = {
 	{ OV9640_COM5,	OV9640_COM5_SYSCLK | OV9640_COM5_LONGEXP },
@@ -308,9 +310,7 @@ static unsigned long ov9640_query_bus_pa
 /* Get status of additional camera capabilities */
 static int ov9640_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
 {
-	struct i2c_client *client = v4l2_get_subdevdata(sd);
-	struct ov9640_priv *priv = container_of(i2c_get_clientdata(client),
-					struct ov9640_priv, subdev);
+	struct ov9640_priv *priv = to_ov9640_sensor(sd);
 
 	switch (ctrl->id) {
 	case V4L2_CID_VFLIP:
@@ -327,8 +327,7 @@ static int ov9640_g_ctrl(struct v4l2_sub
 static int ov9640_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
 {
 	struct i2c_client *client = v4l2_get_subdevdata(sd);
-	struct ov9640_priv *priv = container_of(i2c_get_clientdata(client),
-					struct ov9640_priv, subdev);
+	struct ov9640_priv *priv = to_ov9640_sensor(sd);
 
 	int ret = 0;
 
@@ -360,9 +359,7 @@ static int ov9640_s_ctrl(struct v4l2_sub
 static int ov9640_g_chip_ident(struct v4l2_subdev *sd,
 				struct v4l2_dbg_chip_ident *id)
 {
-	struct i2c_client *client = v4l2_get_subdevdata(sd);
-	struct ov9640_priv *priv = container_of(i2c_get_clientdata(client),
-					struct ov9640_priv, subdev);
+	struct ov9640_priv *priv = to_ov9640_sensor(sd);
 
 	id->ident	= priv->model;
 	id->revision	= priv->revision;
@@ -654,7 +651,8 @@ static int ov9640_cropcap(struct v4l2_su
 static int ov9640_video_probe(struct soc_camera_device *icd,
 				struct i2c_client *client)
 {
-	struct ov9640_priv *priv = i2c_get_clientdata(client);
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+	struct ov9640_priv *priv = to_ov9640_sensor(sd);
 	u8		pid, ver, midh, midl;
 	const char	*devname;
 	int		ret = 0;
@@ -791,7 +789,8 @@ static int ov9640_probe(struct i2c_clien
 
 static int ov9640_remove(struct i2c_client *client)
 {
-	struct ov9640_priv *priv = i2c_get_clientdata(client);
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+	struct ov9640_priv *priv = to_ov9640_sensor(sd);
 
 	kfree(priv);
 	return 0;
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/pvrusb2/pvrusb2-ctrl.c linux-libre-2.6.38-gnu1/drivers/media/video/pvrusb2/pvrusb2-ctrl.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/pvrusb2/pvrusb2-ctrl.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/pvrusb2/pvrusb2-ctrl.c	2011-03-14 21:20:32.000000000 -0400
@@ -203,7 +203,7 @@ int pvr2_ctrl_get_valname(struct pvr2_ct
 	*blen = 0;
 	LOCK_TAKE(cptr->hdw->big_lock); do {
 		if (cptr->info->type == pvr2_ctl_enum) {
-			const char **names;
+			const char * const *names;
 			names = cptr->info->def.type_enum.value_names;
 			if (pvr2_ctrl_range_check(cptr,val) == 0) {
 				if (names[val]) {
@@ -367,7 +367,7 @@ static const char *boolNames[] = {
 
 static int parse_token(const char *ptr,unsigned int len,
 		       int *valptr,
-		       const char **names,unsigned int namecnt)
+		       const char * const *names, unsigned int namecnt)
 {
 	char buf[33];
 	unsigned int slen;
@@ -559,7 +559,7 @@ int pvr2_ctrl_value_to_sym_internal(stru
 		*len = scnprintf(buf,maxlen,"%s",val ? "true" : "false");
 		ret = 0;
 	} else if (cptr->info->type == pvr2_ctl_enum) {
-		const char **names;
+		const char * const *names;
 		names = cptr->info->def.type_enum.value_names;
 		if ((val >= 0) &&
 		    (val < cptr->info->def.type_enum.count)) {
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h linux-libre-2.6.38-gnu1/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h
--- linux-libre-2.6.37-gnu1/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h	2011-03-14 21:20:32.000000000 -0400
@@ -40,6 +40,7 @@
 #include "pvrusb2-io.h"
 #include <media/v4l2-device.h>
 #include <media/cx2341x.h>
+#include <media/ir-kbd-i2c.h>
 #include "pvrusb2-devattr.h"
 
 /* Legal values for PVR2_CID_HSM */
@@ -115,7 +116,7 @@ struct pvr2_ctl_info {
 		} type_int;
 		struct { /* enumerated control */
 			unsigned int count;       /* enum value count */
-			const char **value_names; /* symbol names */
+			const char * const *value_names; /* symbol names */
 		} type_enum;
 		struct { /* bitmask control */
 			unsigned int valid_bits; /* bits in use */
@@ -202,6 +203,7 @@ struct pvr2_hdw {
 
 	/* IR related */
 	unsigned int ir_scheme_active; /* IR scheme as seen from the outside */
+	struct IR_i2c_init_data ir_init_data; /* params passed to IR modules */
 
 	/* Frequency table */
 	unsigned int freqTable[FREQTABLE_SIZE];
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c linux-libre-2.6.38-gnu1/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c	2011-03-14 21:20:32.000000000 -0400
@@ -19,6 +19,7 @@
  */
 
 #include <linux/i2c.h>
+#include <media/ir-kbd-i2c.h>
 #include "pvrusb2-i2c-core.h"
 #include "pvrusb2-hdw-internal.h"
 #include "pvrusb2-debug.h"
@@ -48,13 +49,6 @@ module_param_named(disable_autoload_ir_v
 MODULE_PARM_DESC(disable_autoload_ir_video,
 		 "1=do not try to autoload ir_video IR receiver");
 
-/* Mapping of IR schemes to known I2C addresses - if any */
-static const unsigned char ir_video_addresses[] = {
-	[PVR2_IR_SCHEME_ZILOG] = 0x71,
-	[PVR2_IR_SCHEME_29XXX] = 0x18,
-	[PVR2_IR_SCHEME_24XXX] = 0x18,
-};
-
 static int pvr2_i2c_write(struct pvr2_hdw *hdw, /* Context */
 			  u8 i2c_addr,      /* I2C address we're talking to */
 			  u8 *data,         /* Data to write */
@@ -574,26 +568,55 @@ static void do_i2c_scan(struct pvr2_hdw
 static void pvr2_i2c_register_ir(struct pvr2_hdw *hdw)
 {
 	struct i2c_board_info info;
-	unsigned char addr = 0;
+	struct IR_i2c_init_data *init_data = &hdw->ir_init_data;
 	if (pvr2_disable_ir_video) {
 		pvr2_trace(PVR2_TRACE_INFO,
 			   "Automatic binding of ir_video has been disabled.");
 		return;
 	}
-	if (hdw->ir_scheme_active < ARRAY_SIZE(ir_video_addresses)) {
-		addr = ir_video_addresses[hdw->ir_scheme_active];
-	}
-	if (!addr) {
+	memset(&info, 0, sizeof(struct i2c_board_info));
+	switch (hdw->ir_scheme_active) {
+	case PVR2_IR_SCHEME_24XXX: /* FX2-controlled IR */
+	case PVR2_IR_SCHEME_29XXX: /* Original 29xxx device */
+		init_data->ir_codes              = RC_MAP_HAUPPAUGE_NEW;
+		init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP;
+		init_data->type                  = RC_TYPE_RC5;
+		init_data->name                  = hdw->hdw_desc->description;
+		init_data->polling_interval      = 100; /* ms From ir-kbd-i2c */
+		/* IR Receiver */
+		info.addr          = 0x18;
+		info.platform_data = init_data;
+		strlcpy(info.type, "ir_video", I2C_NAME_SIZE);
+		pvr2_trace(PVR2_TRACE_INFO, "Binding %s to i2c address 0x%02x.",
+			   info.type, info.addr);
+		i2c_new_device(&hdw->i2c_adap, &info);
+		break;
+	case PVR2_IR_SCHEME_ZILOG:     /* HVR-1950 style */
+	case PVR2_IR_SCHEME_24XXX_MCE: /* 24xxx MCE device */
+		init_data->ir_codes              = RC_MAP_HAUPPAUGE_NEW;
+		init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR;
+		init_data->type                  = RC_TYPE_RC5;
+		init_data->name                  = hdw->hdw_desc->description;
+		/* IR Receiver */
+		info.addr          = 0x71;
+		info.platform_data = init_data;
+		strlcpy(info.type, "ir_rx_z8f0811_haup", I2C_NAME_SIZE);
+		pvr2_trace(PVR2_TRACE_INFO, "Binding %s to i2c address 0x%02x.",
+			   info.type, info.addr);
+		i2c_new_device(&hdw->i2c_adap, &info);
+		/* IR Trasmitter */
+		info.addr          = 0x70;
+		info.platform_data = init_data;
+		strlcpy(info.type, "ir_tx_z8f0811_haup", I2C_NAME_SIZE);
+		pvr2_trace(PVR2_TRACE_INFO, "Binding %s to i2c address 0x%02x.",
+			   info.type, info.addr);
+		i2c_new_device(&hdw->i2c_adap, &info);
+		break;
+	default:
 		/* The device either doesn't support I2C-based IR or we
 		   don't know (yet) how to operate IR on the device. */
-		return;
+		break;
 	}
-	pvr2_trace(PVR2_TRACE_INFO,
-		   "Binding ir_video to i2c address 0x%02x.", addr);
-	memset(&info, 0, sizeof(struct i2c_board_info));
-	strlcpy(info.type, "ir_video", I2C_NAME_SIZE);
-	info.addr = addr;
-	i2c_new_device(&hdw->i2c_adap, &info);
 }
 
 void pvr2_i2c_core_init(struct pvr2_hdw *hdw)
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/pvrusb2/pvrusb2-sysfs.c linux-libre-2.6.38-gnu1/drivers/media/video/pvrusb2/pvrusb2-sysfs.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/pvrusb2/pvrusb2-sysfs.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/pvrusb2/pvrusb2-sysfs.c	2011-03-14 21:20:32.000000000 -0400
@@ -647,7 +647,7 @@ static void class_dev_create(struct pvr2
 	if (ret) {
 		pvr2_trace(PVR2_TRACE_ERROR_LEGS,
 			   "device_register failed");
-		kfree(class_dev);
+		put_device(class_dev);
 		return;
 	}
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/pvrusb2/pvrusb2-v4l2.c linux-libre-2.6.38-gnu1/drivers/media/video/pvrusb2/pvrusb2-v4l2.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/pvrusb2/pvrusb2-v4l2.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/pvrusb2/pvrusb2-v4l2.c	2011-03-14 21:20:32.000000000 -0400
@@ -852,8 +852,8 @@ static long pvr2_v4l2_do_ioctl(struct fi
 #endif
 
 	default :
-		ret = v4l_compat_translate_ioctl(file, cmd,
-						 arg, pvr2_v4l2_do_ioctl);
+		ret = -EINVAL;
+		break;
 	}
 
 	pvr2_hdw_commit_ctl(hdw);
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/pwc/pwc-ctrl.c linux-libre-2.6.38-gnu1/drivers/media/video/pwc/pwc-ctrl.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/pwc/pwc-ctrl.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/pwc/pwc-ctrl.c	2011-03-14 21:20:32.000000000 -0400
@@ -1386,11 +1386,16 @@ long pwc_ioctl(struct pwc_device *pdev,
 	{
 		ARG_DEF(int, qual)
 
+		if (pdev->iso_init) {
+			ret = -EBUSY;
+			break;
+		}
+
 		ARG_IN(qual)
 		if (ARGR(qual) < 0 || ARGR(qual) > 3)
 			ret = -EINVAL;
 		else
-			ret = pwc_try_video_mode(pdev, pdev->view.x, pdev->view.y, pdev->vframes, ARGR(qual), pdev->vsnapshot);
+			ret = pwc_set_video_mode(pdev, pdev->view.x, pdev->view.y, pdev->vframes, ARGR(qual), pdev->vsnapshot);
 		if (ret >= 0)
 			pdev->vcompression = ARGR(qual);
 		break;
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/pwc/pwc.h linux-libre-2.6.38-gnu1/drivers/media/video/pwc/pwc.h
--- linux-libre-2.6.37-gnu1/drivers/media/video/pwc/pwc.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/pwc/pwc.h	2011-03-14 21:20:32.000000000 -0400
@@ -275,7 +275,6 @@ extern int pwc_trace;
 extern int pwc_mbufs;
 
 /** functions in pwc-if.c */
-int pwc_try_video_mode(struct pwc_device *pdev, int width, int height, int new_fps, int new_compression, int new_snapshot);
 int pwc_handle_frame(struct pwc_device *pdev);
 void pwc_next_image(struct pwc_device *pdev);
 int pwc_isoc_init(struct pwc_device *pdev);
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/pwc/pwc-if.c linux-libre-2.6.38-gnu1/drivers/media/video/pwc/pwc-if.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/pwc/pwc-if.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/pwc/pwc-if.c	2011-03-14 21:20:32.000000000 -0400
@@ -287,14 +287,13 @@ static int pwc_allocate_buffers(struct p
 	/* create frame buffers, and make circular ring */
 	for (i = 0; i < default_fbufs; i++) {
 		if (pdev->fbuf[i].data == NULL) {
-			kbuf = vmalloc(PWC_FRAME_SIZE); /* need vmalloc since frame buffer > 128K */
+			kbuf = vzalloc(PWC_FRAME_SIZE); /* need vmalloc since frame buffer > 128K */
 			if (kbuf == NULL) {
 				PWC_ERROR("Failed to allocate frame buffer %d.\n", i);
 				return -ENOMEM;
 			}
 			PWC_DEBUG_MEMORY("Allocated frame buffer %d at %p.\n", i, kbuf);
 			pdev->fbuf[i].data = kbuf;
-			memset(kbuf, 0, PWC_FRAME_SIZE);
 		}
 	}
 
@@ -899,10 +898,13 @@ int pwc_isoc_init(struct pwc_device *pde
 	/* link */
 	for (i = 0; i < MAX_ISO_BUFS; i++) {
 		ret = usb_submit_urb(pdev->sbuf[i].urb, GFP_KERNEL);
-		if (ret)
+		if (ret) {
 			PWC_ERROR("isoc_init() submit_urb %d failed with error %d\n", i, ret);
-		else
-			PWC_DEBUG_MEMORY("URB 0x%p submitted.\n", pdev->sbuf[i].urb);
+			pdev->iso_init = 1;
+			pwc_isoc_cleanup(pdev);
+			return ret;
+		}
+		PWC_DEBUG_MEMORY("URB 0x%p submitted.\n", pdev->sbuf[i].urb);
 	}
 
 	/* All is done... */
@@ -958,7 +960,7 @@ void pwc_isoc_cleanup(struct pwc_device
 	/* Stop camera, but only if we are sure the camera is still there (unplug
 	   is signalled by EPIPE)
 	 */
-	if (pdev->error_status && pdev->error_status != EPIPE) {
+	if (pdev->error_status != EPIPE) {
 		PWC_DEBUG_OPEN("Setting alternate interface 0.\n");
 		usb_set_interface(pdev->udev, 0, 0);
 	}
@@ -967,36 +969,6 @@ void pwc_isoc_cleanup(struct pwc_device
 	PWC_DEBUG_OPEN("<< pwc_isoc_cleanup()\n");
 }
 
-int pwc_try_video_mode(struct pwc_device *pdev, int width, int height, int new_fps, int new_compression, int new_snapshot)
-{
-	int ret, start;
-
-	/* Stop isoc stuff */
-	pwc_isoc_cleanup(pdev);
-	/* Reset parameters */
-	pwc_reset_buffers(pdev);
-	/* Try to set video mode... */
-	start = ret = pwc_set_video_mode(pdev, width, height, new_fps, new_compression, new_snapshot);
-	if (ret) {
-		PWC_DEBUG_FLOW("pwc_set_video_mode attempt 1 failed.\n");
-		/* That failed... restore old mode (we know that worked) */
-		start = pwc_set_video_mode(pdev, pdev->view.x, pdev->view.y, pdev->vframes, pdev->vcompression, pdev->vsnapshot);
-		if (start) {
-			PWC_DEBUG_FLOW("pwc_set_video_mode attempt 2 failed.\n");
-		}
-	}
-	if (start == 0)
-	{
-		if (pwc_isoc_init(pdev) < 0)
-		{
-			PWC_WARNING("Failed to restart ISOC transfers in pwc_try_video_mode.\n");
-			ret = -EAGAIN; /* let's try again, who knows if it works a second time */
-		}
-	}
-	pdev->drop_frames++; /* try to avoid garbage during switch */
-	return ret; /* Return original error code */
-}
-
 /*********
  * sysfs
  *********/
@@ -1176,7 +1148,7 @@ static int pwc_video_open(struct file *f
 	/* Set some defaults */
 	pdev->vsnapshot = 0;
 
-	/* Start iso pipe for video; first try the last used video size
+	/* Set video size, first try the last used video size
 	   (or the default one); if that fails try QCIF/10 or QSIF/10;
 	   it that fails too, give up.
 	 */
@@ -1203,15 +1175,6 @@ static int pwc_video_open(struct file *f
 		return i;
 	}
 
-	i = pwc_isoc_init(pdev);
-	if (i) {
-		PWC_DEBUG_OPEN("Failed to init ISOC stuff = %d.\n", i);
-		pwc_isoc_cleanup(pdev);
-		pwc_free_buffers(pdev);
-		mutex_unlock(&pdev->modlock);
-		return i;
-	}
-
 	/* Initialize the webcam to sane value */
 	pwc_set_brightness(pdev, 0x7fff);
 	pwc_set_agc(pdev, 1, 0);
@@ -1326,6 +1289,11 @@ static ssize_t pwc_video_read(struct fil
 		goto err_out;
 	}
 
+	/* Start the stream (if not already started) */
+	rv = pwc_isoc_init(pdev);
+	if (rv)
+		goto err_out;
+
 	/* In case we're doing partial reads, we don't have to wait for a frame */
 	if (pdev->image_read_pos == 0) {
 		/* Do wait queueing according to the (doc)book */
@@ -1395,6 +1363,7 @@ static unsigned int pwc_video_poll(struc
 {
 	struct video_device *vdev = file->private_data;
 	struct pwc_device *pdev;
+	int ret;
 
 	if (vdev == NULL)
 		return -EFAULT;
@@ -1402,6 +1371,13 @@ static unsigned int pwc_video_poll(struc
 	if (pdev == NULL)
 		return -EFAULT;
 
+	/* Start the stream (if not already started) */
+	mutex_lock(&pdev->modlock);
+	ret = pwc_isoc_init(pdev);
+	mutex_unlock(&pdev->modlock);
+	if (ret)
+		return ret;
+
 	poll_wait(file, &pdev->frameq, wait);
 	if (pdev->error_status)
 		return POLLERR;
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/pwc/pwc-v4l.c linux-libre-2.6.38-gnu1/drivers/media/video/pwc/pwc-v4l.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/pwc/pwc-v4l.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/pwc/pwc-v4l.c	2011-03-14 21:20:32.000000000 -0400
@@ -309,7 +309,10 @@ static int pwc_vidioc_set_fmt(struct pwc
 	    pixelformat != V4L2_PIX_FMT_PWC2)
 		return -EINVAL;
 
-	PWC_DEBUG_IOCTL("Try to change format to: width=%d height=%d fps=%d "
+	if (pdev->iso_init)
+		return -EBUSY;
+
+	PWC_DEBUG_IOCTL("Trying to set format to: width=%d height=%d fps=%d "
 			"compression=%d snapshot=%d format=%c%c%c%c\n",
 			f->fmt.pix.width, f->fmt.pix.height, fps,
 			compression, snapshot,
@@ -318,14 +321,14 @@ static int pwc_vidioc_set_fmt(struct pwc
 			(pixelformat>>16)&255,
 			(pixelformat>>24)&255);
 
-	ret = pwc_try_video_mode(pdev,
+	ret = pwc_set_video_mode(pdev,
 				 f->fmt.pix.width,
 				 f->fmt.pix.height,
 				 fps,
 				 compression,
 				 snapshot);
 
-	PWC_DEBUG_IOCTL("pwc_try_video_mode(), return=%d\n", ret);
+	PWC_DEBUG_IOCTL("pwc_set_video_mode(), return=%d\n", ret);
 
 	if (ret)
 		return ret;
@@ -359,23 +362,6 @@ long pwc_video_do_ioctl(struct file *fil
 
 
 	switch (cmd) {
-#ifdef CONFIG_VIDEO_V4L1_COMPAT
-		/* mmap() functions */
-		case VIDIOCGMBUF:
-		{
-			/* Tell the user program how much memory is needed for a mmap() */
-			struct video_mbuf *vm = arg;
-			int i;
-
-			memset(vm, 0, sizeof(*vm));
-			vm->size = pwc_mbufs * pdev->len_per_image;
-			vm->frames = pwc_mbufs; /* double buffering should be enough for most applications */
-			for (i = 0; i < pwc_mbufs; i++)
-				vm->offsets[i] = i * pdev->len_per_image;
-			break;
-		}
-#endif
-
 		/* V4L2 Layer */
 		case VIDIOC_QUERYCAP:
 		{
@@ -882,9 +868,7 @@ long pwc_video_do_ioctl(struct file *fil
 
 		case VIDIOC_STREAMON:
 		{
-			/* WARNING: pwc_try_video_mode() called pwc_isoc_init */
-			pwc_isoc_init(pdev);
-			return 0;
+			return pwc_isoc_init(pdev);
 		}
 
 		case VIDIOC_STREAMOFF:
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/pxa_camera.c linux-libre-2.6.38-gnu1/drivers/media/video/pxa_camera.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/pxa_camera.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/pxa_camera.c	2011-03-14 21:20:32.000000000 -0400
@@ -852,7 +852,7 @@ static void pxa_camera_init_videobuf(str
 	 */
 	videobuf_queue_sg_init(q, &pxa_videobuf_ops, NULL, &pcdev->lock,
 				V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_NONE,
-				sizeof(struct pxa_buffer), icd, NULL);
+				sizeof(struct pxa_buffer), icd, &icd->video_lock);
 }
 
 static u32 mclk_get_divisor(struct platform_device *pdev,
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/rj54n1cb0c.c linux-libre-2.6.38-gnu1/drivers/media/video/rj54n1cb0c.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/rj54n1cb0c.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/rj54n1cb0c.c	2011-03-14 21:20:32.000000000 -0400
@@ -1460,7 +1460,6 @@ static int rj54n1_remove(struct i2c_clie
 	icd->ops = NULL;
 	if (icl->free_bus)
 		icl->free_bus(icl);
-	client->driver = NULL;
 	kfree(rj54n1);
 
 	return 0;
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/s2255drv.c linux-libre-2.6.38-gnu1/drivers/media/video/s2255drv.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/s2255drv.c	2013-05-03 03:57:33.000000000 -0400
+++ linux-libre-2.6.38-gnu1/drivers/media/video/s2255drv.c	2013-05-03 01:57:25.000000000 -0400
@@ -57,7 +57,7 @@
 #include <linux/usb.h>
 
 #define S2255_MAJOR_VERSION	1
-#define S2255_MINOR_VERSION	20
+#define S2255_MINOR_VERSION	21
 #define S2255_RELEASE		0
 #define S2255_VERSION		KERNEL_VERSION(S2255_MAJOR_VERSION, \
 					       S2255_MINOR_VERSION, \
@@ -268,7 +268,7 @@ struct s2255_dev {
 	struct v4l2_device 	v4l2_dev;
 	atomic_t                num_channels;
 	int			frames;
-	struct mutex		lock;
+	struct mutex		lock;	/* channels[].vdev.lock */
 	struct mutex		open_lock;
 	struct usb_device	*udev;
 	struct usb_interface	*interface;
@@ -312,9 +312,9 @@ struct s2255_fh {
 };
 
 /* current cypress EEPROM firmware version */
-#define S2255_CUR_USB_FWVER	((3 << 8) | 6)
+#define S2255_CUR_USB_FWVER	((3 << 8) | 11)
 /* current DSP FW version */
-#define S2255_CUR_DSP_FWVER     8
+#define S2255_CUR_DSP_FWVER     10102
 /* Need DSP version 5+ for video status feature */
 #define S2255_MIN_DSP_STATUS      5
 #define S2255_MIN_DSP_COLORFILTER 8
@@ -492,9 +492,11 @@ static void planar422p_to_yuv_packed(con
 
 static void s2255_reset_dsppower(struct s2255_dev *dev)
 {
-	s2255_vendor_req(dev, 0x40, 0x0b0b, 0x0b0b, NULL, 0, 1);
+	s2255_vendor_req(dev, 0x40, 0x0b0b, 0x0b01, NULL, 0, 1);
 	msleep(10);
 	s2255_vendor_req(dev, 0x50, 0x0000, 0x0000, NULL, 0, 1);
+	msleep(600);
+	s2255_vendor_req(dev, 0x10, 0x0000, 0x0000, NULL, 0, 1);
 	return;
 }
 
@@ -780,20 +782,14 @@ static struct videobuf_queue_ops s2255_v
 
 static int res_get(struct s2255_fh *fh)
 {
-	struct s2255_dev *dev = fh->dev;
-	/* is it free? */
 	struct s2255_channel *channel = fh->channel;
-	mutex_lock(&dev->lock);
-	if (channel->resources) {
-		/* no, someone else uses it */
-		mutex_unlock(&dev->lock);
-		return 0;
-	}
+	/* is it free? */
+	if (channel->resources)
+		return 0; /* no, someone else uses it */
 	/* it's free, grab it */
 	channel->resources = 1;
 	fh->resources = 1;
 	dprintk(1, "s2255: res: get\n");
-	mutex_unlock(&dev->lock);
 	return 1;
 }
 
@@ -811,11 +807,8 @@ static int res_check(struct s2255_fh *fh
 static void res_free(struct s2255_fh *fh)
 {
 	struct s2255_channel *channel = fh->channel;
-	struct s2255_dev *dev = fh->dev;
-	mutex_lock(&dev->lock);
 	channel->resources = 0;
 	fh->resources = 0;
-	mutex_unlock(&dev->lock);
 	dprintk(1, "res: put\n");
 }
 
@@ -1106,15 +1099,6 @@ static int vidioc_dqbuf(struct file *fil
 	return rc;
 }
 
-#ifdef CONFIG_VIDEO_V4L1_COMPAT
-static int vidioc_cgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf)
-{
-	struct s2255_fh *fh = priv;
-
-	return videobuf_cgmbuf(&fh->vb_vidq, mbuf, 8);
-}
-#endif
-
 /* write to the configuration pipe, synchronously */
 static int s2255_write_config(struct usb_device *udev, unsigned char *pbuf,
 			      int size)
@@ -1218,7 +1202,6 @@ static int s2255_set_mode(struct s2255_c
 	__le32 *buffer;
 	unsigned long chn_rev;
 	struct s2255_dev *dev = to_s2255_dev(channel->vdev.v4l2_dev);
-	mutex_lock(&dev->lock);
 	chn_rev = G_chnmap[channel->idx];
 	dprintk(3, "%s channel: %d\n", __func__, channel->idx);
 	/* if JPEG, set the quality */
@@ -1235,7 +1218,6 @@ static int s2255_set_mode(struct s2255_c
 	buffer = kzalloc(512, GFP_KERNEL);
 	if (buffer == NULL) {
 		dev_err(&dev->udev->dev, "out of mem\n");
-		mutex_unlock(&dev->lock);
 		return -ENOMEM;
 	}
 	/* set the mode */
@@ -1260,7 +1242,6 @@ static int s2255_set_mode(struct s2255_c
 	}
 	/* clear the restart flag */
 	channel->mode.restart = 0;
-	mutex_unlock(&dev->lock);
 	dprintk(1, "%s chn %d, result: %d\n", __func__, channel->idx, res);
 	return res;
 }
@@ -1271,13 +1252,11 @@ static int s2255_cmd_status(struct s2255
 	__le32 *buffer;
 	u32 chn_rev;
 	struct s2255_dev *dev = to_s2255_dev(channel->vdev.v4l2_dev);
-	mutex_lock(&dev->lock);
 	chn_rev = G_chnmap[channel->idx];
 	dprintk(4, "%s chan %d\n", __func__, channel->idx);
 	buffer = kzalloc(512, GFP_KERNEL);
 	if (buffer == NULL) {
 		dev_err(&dev->udev->dev, "out of mem\n");
-		mutex_unlock(&dev->lock);
 		return -ENOMEM;
 	}
 	/* form the get vid status command */
@@ -1297,7 +1276,6 @@ static int s2255_cmd_status(struct s2255
 	}
 	*pstatus = channel->vidstatus;
 	dprintk(4, "%s, vid status %d\n", __func__, *pstatus);
-	mutex_unlock(&dev->lock);
 	return res;
 }
 
@@ -1816,7 +1794,8 @@ static int s2255_open(struct file *file)
 				    NULL, &dev->slock,
 				    fh->type,
 				    V4L2_FIELD_INTERLACED,
-				    sizeof(struct s2255_buffer), fh, NULL);
+				    sizeof(struct s2255_buffer),
+				    fh, vdev->lock);
 	return 0;
 }
 
@@ -1899,7 +1878,7 @@ static const struct v4l2_file_operations
 	.open = s2255_open,
 	.release = s2255_release,
 	.poll = s2255_poll,
-	.ioctl = video_ioctl2,	/* V4L2 ioctl handler */
+	.unlocked_ioctl = video_ioctl2,	/* V4L2 ioctl handler */
 	.mmap = s2255_mmap_v4l,
 };
 
@@ -1923,9 +1902,6 @@ static const struct v4l2_ioctl_ops s2255
 	.vidioc_s_ctrl = vidioc_s_ctrl,
 	.vidioc_streamon = vidioc_streamon,
 	.vidioc_streamoff = vidioc_streamoff,
-#ifdef CONFIG_VIDEO_V4L1_COMPAT
-	.vidiocgmbuf = vidioc_cgmbuf,
-#endif
 	.vidioc_s_jpegcomp = vidioc_s_jpegcomp,
 	.vidioc_g_jpegcomp = vidioc_g_jpegcomp,
 	.vidioc_s_parm = vidioc_s_parm,
@@ -1969,6 +1945,7 @@ static int s2255_probe_v4l(struct s2255_
 		channel->vidq.dev = dev;
 		/* register 4 video devices */
 		channel->vdev = template;
+		channel->vdev.lock = &dev->lock;
 		channel->vdev.v4l2_dev = &dev->v4l2_dev;
 		video_set_drvdata(&channel->vdev, channel);
 		if (video_nr == -1)
@@ -2675,7 +2652,9 @@ static void s2255_disconnect(struct usb_
 	struct s2255_dev *dev = to_s2255_dev(usb_get_intfdata(interface));
 	int i;
 	int channels = atomic_read(&dev->num_channels);
+	mutex_lock(&dev->lock);
 	v4l2_device_disconnect(&dev->v4l2_dev);
+	mutex_unlock(&dev->lock);
 	/*see comments in the uvc_driver.c usb disconnect function */
 	atomic_inc(&dev->num_channels);
 	/* unregister each video device. */
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/s5p-fimc/fimc-core.c linux-libre-2.6.38-gnu1/drivers/media/video/s5p-fimc/fimc-core.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/s5p-fimc/fimc-core.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/s5p-fimc/fimc-core.c	2011-03-14 21:20:32.000000000 -0400
@@ -543,7 +543,7 @@ static void fimc_dma_run(void *priv)
 	unsigned long flags;
 	u32 ret;
 
-	if (WARN(!ctx, "null hardware context"))
+	if (WARN(!ctx, "null hardware context\n"))
 		return;
 
 	fimc = ctx->fimc_dev;
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/saa6588.c linux-libre-2.6.38-gnu1/drivers/media/video/saa6588.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/saa6588.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/saa6588.c	2011-03-14 21:20:32.000000000 -0400
@@ -31,7 +31,7 @@
 #include <linux/wait.h>
 #include <asm/uaccess.h>
 
-#include <media/rds.h>
+#include <media/saa6588.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-chip-ident.h>
 
@@ -181,7 +181,7 @@ static int block_to_user_buf(struct saa6
 	return 1;
 }
 
-static void read_from_buf(struct saa6588 *s, struct rds_command *a)
+static void read_from_buf(struct saa6588 *s, struct saa6588_command *a)
 {
 	unsigned long flags;
 
@@ -392,25 +392,25 @@ static void saa6588_configure(struct saa
 static long saa6588_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
 {
 	struct saa6588 *s = to_saa6588(sd);
-	struct rds_command *a = arg;
+	struct saa6588_command *a = arg;
 
 	switch (cmd) {
 		/* --- open() for /dev/radio --- */
-	case RDS_CMD_OPEN:
+	case SAA6588_CMD_OPEN:
 		a->result = 0;	/* return error if chip doesn't work ??? */
 		break;
 		/* --- close() for /dev/radio --- */
-	case RDS_CMD_CLOSE:
+	case SAA6588_CMD_CLOSE:
 		s->data_available_for_read = 1;
 		wake_up_interruptible(&s->read_queue);
 		a->result = 0;
 		break;
 		/* --- read() for /dev/radio --- */
-	case RDS_CMD_READ:
+	case SAA6588_CMD_READ:
 		read_from_buf(s, a);
 		break;
 		/* --- poll() for /dev/radio --- */
-	case RDS_CMD_POLL:
+	case SAA6588_CMD_POLL:
 		a->result = 0;
 		if (s->data_available_for_read) {
 			a->result |= POLLIN | POLLRDNORM;
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/saa7115.c linux-libre-2.6.38-gnu1/drivers/media/video/saa7115.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/saa7115.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/saa7115.c	2011-03-14 21:20:32.000000000 -0400
@@ -1348,8 +1348,17 @@ static int saa711x_querystd(struct v4l2_
 	int reg1e;
 
 	*std = V4L2_STD_ALL;
-	if (state->ident != V4L2_IDENT_SAA7115)
+	if (state->ident != V4L2_IDENT_SAA7115) {
+		int reg1f = saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC);
+
+		if (reg1f & 0x20)
+			*std = V4L2_STD_525_60;
+		else
+			*std = V4L2_STD_625_50;
+
 		return 0;
+	}
+
 	reg1e = saa711x_read(sd, R_1E_STATUS_BYTE_1_VD_DEC);
 
 	switch (reg1e & 0x03) {
@@ -1556,7 +1565,7 @@ static int saa711x_probe(struct i2c_clie
 	chip_id = name[5];
 
 	/* Check whether this chip is part of the saa711x series */
-	if (memcmp(name, "1f711", 5)) {
+	if (memcmp(name + 1, "f711", 4)) {
 		v4l_dbg(1, debug, client, "chip found @ 0x%x (ID %s) does not match a known saa711x chip.\n",
 			client->addr << 1, name);
 		return -ENODEV;
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/saa7134/Kconfig linux-libre-2.6.38-gnu1/drivers/media/video/saa7134/Kconfig
--- linux-libre-2.6.37-gnu1/drivers/media/video/saa7134/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/saa7134/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -26,7 +26,7 @@ config VIDEO_SAA7134_ALSA
 
 config VIDEO_SAA7134_RC
 	bool "Philips SAA7134 Remote Controller support"
-	depends on VIDEO_IR
+	depends on RC_CORE
 	depends on VIDEO_SAA7134
 	default y
 	---help---
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/saa7134/saa7134-cards.c linux-libre-2.6.38-gnu1/drivers/media/video/saa7134/saa7134-cards.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/saa7134/saa7134-cards.c	2013-05-03 03:54:56.000000000 -0400
+++ linux-libre-2.6.38-gnu1/drivers/media/video/saa7134/saa7134-cards.c	2013-05-03 01:54:13.000000000 -0400
@@ -5176,6 +5176,48 @@ struct saa7134_board saa7134_boards[] =
 			.amux = 2,
 		},
 	},
+	[SAA7134_BOARD_KWORLD_PCI_SBTVD_FULLSEG] = {
+		.name           = "Kworld PCI SBTVD/ISDB-T Full-Seg Hybrid",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_TDA8290,
+		.tuner_addr     = ADDR_UNSET,
+		.radio_type     = UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.gpiomask       = 0x8e054000,
+		.mpeg           = SAA7134_MPEG_DVB,
+		.ts_type	= SAA7134_MPEG_TS_PARALLEL,
+		.inputs = { {
+			.name   = name_tv,
+			.vmux   = 1,
+			.amux   = TV,
+			.tv     = 1,
+#if 0	/* FIXME */
+		}, {
+			.name   = name_comp1,
+			.vmux   = 3,
+			.amux   = LINE1,
+			.gpio   = 0x200,
+		}, {
+			.name   = name_svideo,
+			.vmux   = 8,
+			.amux   = LINE1,
+			.gpio   = 0x200,
+#endif
+		} },
+#if 0
+		.radio = {
+			.name   = name_radio,
+			.vmux   = 1,
+			.amux   = LINE1,
+			.gpio   = 0x100,
+		},
+#endif
+		.mute = {
+			.name = name_mute,
+			.vmux = 0,
+			.amux = TV,
+		},
+	},
 	[SAA7134_BOARD_AVERMEDIA_GO_007_FM_PLUS] = {
 		.name           = "Avermedia AVerTV GO 007 FM Plus",
 		.audio_clock    = 0x00187de7,
@@ -5486,6 +5528,37 @@ struct saa7134_board saa7134_boards[] =
 			.amux   = LINE2,
 		} },
 	},
+	[SAA7134_BOARD_VIDEOMATE_M1F] = {
+		/* Pavel Osnova <pvosnova@gmail.com> */
+		.name           = "Compro VideoMate Vista M1F",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_LG_PAL_NEW_TAPC,
+		.radio_type     = TUNER_TEA5767,
+		.tuner_addr     = ADDR_UNSET,
+		.radio_addr     = 0x60,
+		.inputs         = { {
+			.name = name_tv,
+			.vmux = 1,
+			.amux = TV,
+			.tv   = 1,
+		}, {
+			.name = name_comp1,
+			.vmux = 3,
+			.amux = LINE2,
+		}, {
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE2,
+		} },
+		.radio = {
+			.name = name_radio,
+			.amux = LINE1,
+		},
+		.mute = {
+			.name = name_mute,
+			.amux = TV,
+		},
+	},
 
 };
 
@@ -6615,6 +6688,12 @@ struct pci_device_id saa7134_pci_tbl[] =
 	}, {
 		.vendor       = PCI_VENDOR_ID_PHILIPS,
 		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x17de,
+		.subdevice    = 0xb136,
+		.driver_data  = SAA7134_BOARD_KWORLD_PCI_SBTVD_FULLSEG,
+	}, {
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
 		.subvendor    = 0x1461, /* Avermedia Technologies Inc */
 		.subdevice    = 0xf31d,
 		.driver_data  = SAA7134_BOARD_AVERMEDIA_GO_007_FM_PLUS,
@@ -6673,6 +6752,12 @@ struct pci_device_id saa7134_pci_tbl[] =
 		.subdevice    = 0x7090,
 		.driver_data  = SAA7134_BOARD_BEHOLD_A7,
 	}, {
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7135,
+		.subvendor    = 0x185b,
+		.subdevice    = 0xc900,
+		.driver_data  = SAA7134_BOARD_VIDEOMATE_M1F,
+	}, {
 		/* --- boards without eeprom + subsystem ID --- */
 		.vendor       = PCI_VENDOR_ID_PHILIPS,
 		.device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
@@ -6831,6 +6916,30 @@ static inline int saa7134_tda18271_hvr11
 	return 0;
 }
 
+static inline int saa7134_kworld_sbtvd_toggle_agc(struct saa7134_dev *dev,
+						  enum tda18271_mode mode)
+{
+	/* toggle AGC switch through GPIO 27 */
+	switch (mode) {
+	case TDA18271_ANALOG:
+		saa_writel(SAA7134_GPIO_GPMODE0 >> 2, 0x4000);
+		saa_writel(SAA7134_GPIO_GPSTATUS0 >> 2, 0x4000);
+		msleep(20);
+		break;
+	case TDA18271_DIGITAL:
+		saa_writel(SAA7134_GPIO_GPMODE0 >> 2, 0x14000);
+		saa_writel(SAA7134_GPIO_GPSTATUS0 >> 2, 0x14000);
+		msleep(20);
+		saa_writel(SAA7134_GPIO_GPMODE0 >> 2, 0x54000);
+		saa_writel(SAA7134_GPIO_GPSTATUS0 >> 2, 0x54000);
+		msleep(30);
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
 static int saa7134_tda8290_18271_callback(struct saa7134_dev *dev,
 					  int command, int arg)
 {
@@ -6843,6 +6952,9 @@ static int saa7134_tda8290_18271_callbac
 		case SAA7134_BOARD_HAUPPAUGE_HVR1120:
 			ret = saa7134_tda18271_hvr11x0_toggle_agc(dev, arg);
 			break;
+		case SAA7134_BOARD_KWORLD_PCI_SBTVD_FULLSEG:
+			ret = saa7134_kworld_sbtvd_toggle_agc(dev, arg);
+			break;
 		default:
 			break;
 		}
@@ -6863,6 +6975,7 @@ static int saa7134_tda8290_callback(stru
 	case SAA7134_BOARD_HAUPPAUGE_HVR1150:
 	case SAA7134_BOARD_HAUPPAUGE_HVR1120:
 	case SAA7134_BOARD_AVERMEDIA_M733A:
+	case SAA7134_BOARD_KWORLD_PCI_SBTVD_FULLSEG:
 		/* tda8290 + tda18271 */
 		ret = saa7134_tda8290_18271_callback(dev, command, arg);
 		break;
@@ -6877,6 +6990,7 @@ static int saa7134_tda8290_callback(stru
 int saa7134_tuner_callback(void *priv, int component, int command, int arg)
 {
 	struct saa7134_dev *dev = priv;
+
 	if (dev != NULL) {
 		switch (dev->tuner_type) {
 		case TUNER_PHILIPS_TDA8290:
@@ -6967,6 +7081,7 @@ int saa7134_board_init1(struct saa7134_d
 	case SAA7134_BOARD_VIDEOMATE_TV_PVR:
 	case SAA7134_BOARD_VIDEOMATE_GOLD_PLUS:
 	case SAA7134_BOARD_VIDEOMATE_TV_GOLD_PLUSII:
+	case SAA7134_BOARD_VIDEOMATE_M1F:
 	case SAA7134_BOARD_VIDEOMATE_DVBT_300:
 	case SAA7134_BOARD_VIDEOMATE_DVBT_200:
 	case SAA7134_BOARD_VIDEOMATE_DVBT_200A:
@@ -7541,6 +7656,12 @@ int saa7134_board_init2(struct saa7134_d
 				       dev->name);
 		break;
 	}
+	case SAA7134_BOARD_KWORLD_PCI_SBTVD_FULLSEG:
+		saa_writel(SAA7134_GPIO_GPMODE0 >> 2, 0x4000);
+		saa_writel(SAA7134_GPIO_GPSTATUS0 >> 2, 0x4000);
+
+		saa7134_set_gpio(dev, 27, 0);
+		break;
 	} /* switch() */
 
 	/* initialize tuner */
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/saa7134/saa7134-core.c linux-libre-2.6.38-gnu1/drivers/media/video/saa7134/saa7134-core.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/saa7134/saa7134-core.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/saa7134/saa7134-core.c	2011-03-14 21:20:32.000000000 -0400
@@ -166,8 +166,14 @@ static void request_submodules(struct sa
 	schedule_work(&dev->request_module_wk);
 }
 
+static void flush_request_submodules(struct saa7134_dev *dev)
+{
+	flush_work_sync(&dev->request_module_wk);
+}
+
 #else
 #define request_submodules(dev)
+#define flush_request_submodules(dev)
 #endif /* CONFIG_MODULES */
 
 /* ------------------------------------------------------------------ */
@@ -1010,8 +1016,6 @@ static int __devinit saa7134_initdev(str
 		}
 	}
 
-	request_submodules(dev);
-
 	v4l2_prio_init(&dev->prio);
 
 	mutex_lock(&saa7134_devlist_lock);
@@ -1066,6 +1070,7 @@ static int __devinit saa7134_initdev(str
 	if (saa7134_dmasound_init && !dev->dmasound.priv_data)
 		saa7134_dmasound_init(dev);
 
+	request_submodules(dev);
 	return 0;
 
  fail4:
@@ -1091,6 +1096,8 @@ static void __devexit saa7134_finidev(st
 	struct saa7134_dev *dev = container_of(v4l2_dev, struct saa7134_dev, v4l2_dev);
 	struct saa7134_mpeg_ops *mops;
 
+	flush_request_submodules(dev);
+
 	/* Release DMA sound modules if present */
 	if (saa7134_dmasound_exit && dev->dmasound.priv_data) {
 		saa7134_dmasound_exit(dev);
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/saa7134/saa7134-dvb.c linux-libre-2.6.38-gnu1/drivers/media/video/saa7134/saa7134-dvb.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/saa7134/saa7134-dvb.c	2013-05-03 03:57:19.000000000 -0400
+++ linux-libre-2.6.38-gnu1/drivers/media/video/saa7134/saa7134-dvb.c	2013-05-03 01:57:08.000000000 -0400
@@ -52,6 +52,7 @@
 #include "tda18271.h"
 #include "lgdt3305.h"
 #include "tda8290.h"
+#include "mb86a20s.h"
 
 #include "zl10353.h"
 
@@ -228,6 +229,47 @@ static struct mt352_config avermedia_xc3
 	.demod_init      = mt352_avermedia_xc3028_init,
 };
 
+static struct tda18271_std_map mb86a20s_tda18271_std_map = {
+	.dvbt_6   = { .if_freq = 3300, .agc_mode = 3, .std = 4,
+		      .if_lvl = 7, .rfagc_top = 0x37, },
+};
+
+static struct tda18271_config kworld_tda18271_config = {
+	.std_map = &mb86a20s_tda18271_std_map,
+	.gate    = TDA18271_GATE_DIGITAL,
+	.config  = 3,	/* Use tuner callback for AGC */
+
+};
+
+static const struct mb86a20s_config kworld_mb86a20s_config = {
+	.demod_address = 0x10,
+};
+
+static int kworld_sbtvd_gate_ctrl(struct dvb_frontend* fe, int enable)
+{
+	struct saa7134_dev *dev = fe->dvb->priv;
+
+	unsigned char initmsg[] = {0x45, 0x97};
+	unsigned char msg_enable[] = {0x45, 0xc1};
+	unsigned char msg_disable[] = {0x45, 0x81};
+	struct i2c_msg msg = {.addr = 0x4b, .flags = 0, .buf = initmsg, .len = 2};
+
+	if (i2c_transfer(&dev->i2c_adap, &msg, 1) != 1) {
+		wprintk("could not access the I2C gate\n");
+		return -EIO;
+	}
+	if (enable)
+		msg.buf = msg_enable;
+	else
+		msg.buf = msg_disable;
+	if (i2c_transfer(&dev->i2c_adap, &msg, 1) != 1) {
+		wprintk("could not access the I2C gate\n");
+		return -EIO;
+	}
+	msleep(20);
+	return 0;
+}
+
 /* ==================================================================
  * tda1004x based DVB-T cards, helper functions
  */
@@ -1613,6 +1655,25 @@ static int dvb_init(struct saa7134_dev *
 				   &dtv1000s_tda18271_config);
 		}
 		break;
+	case SAA7134_BOARD_KWORLD_PCI_SBTVD_FULLSEG:
+		/* Switch to digital mode */
+		saa7134_tuner_callback(dev, 0,
+				       TDA18271_CALLBACK_CMD_AGC_ENABLE, 1);
+		fe0->dvb.frontend = dvb_attach(mb86a20s_attach,
+					       &kworld_mb86a20s_config,
+					       &dev->i2c_adap);
+		if (fe0->dvb.frontend != NULL) {
+			dvb_attach(tda829x_attach, fe0->dvb.frontend,
+				   &dev->i2c_adap, 0x4b,
+				   &tda829x_no_probe);
+			dvb_attach(tda18271_attach, fe0->dvb.frontend,
+				   0x60, &dev->i2c_adap,
+				   &kworld_tda18271_config);
+			fe0->dvb.frontend->ops.i2c_gate_ctrl = kworld_sbtvd_gate_ctrl;
+		}
+
+		/* mb86a20s need to use the I2C gateway */
+		break;
 	default:
 		wprintk("Huh? unknown DVB card?\n");
 		break;
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/saa7134/saa7134-empress.c linux-libre-2.6.38-gnu1/drivers/media/video/saa7134/saa7134-empress.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/saa7134/saa7134-empress.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/saa7134/saa7134-empress.c	2011-03-14 21:20:32.000000000 -0400
@@ -553,7 +553,7 @@ static int empress_fini(struct saa7134_d
 
 	if (NULL == dev->empress_dev)
 		return 0;
-	flush_scheduled_work();
+	flush_work_sync(&dev->empress_workqueue);
 	video_unregister_device(dev->empress_dev);
 	dev->empress_dev = NULL;
 	return 0;
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/saa7134/saa7134.h linux-libre-2.6.38-gnu1/drivers/media/video/saa7134/saa7134.h
--- linux-libre-2.6.37-gnu1/drivers/media/video/saa7134/saa7134.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/saa7134/saa7134.h	2011-03-14 21:20:32.000000000 -0400
@@ -37,7 +37,7 @@
 #include <media/v4l2-ioctl.h>
 #include <media/v4l2-device.h>
 #include <media/tuner.h>
-#include <media/ir-common.h>
+#include <media/rc-core.h>
 #include <media/ir-kbd-i2c.h>
 #include <media/videobuf-dma-sg.h>
 #include <sound/core.h>
@@ -119,6 +119,26 @@ struct saa7134_format {
 	unsigned int   uvswap:1;
 };
 
+struct saa7134_card_ir {
+	struct rc_dev		*dev;
+
+	char                    name[32];
+	char                    phys[32];
+	unsigned                users;
+
+	u32			polling;
+        u32			last_gpio;
+        u32			mask_keycode, mask_keydown, mask_keyup;
+
+	bool                    running;
+	bool			active;
+
+	struct timer_list       timer;
+
+	/* IR core raw decoding */
+	u32                     raw_decode;
+};
+
 /* ----------------------------------------------------------- */
 /* card configuration                                          */
 
@@ -305,6 +325,8 @@ struct saa7134_format {
 #define SAA7134_BOARD_BEHOLD_A7             179
 #define SAA7134_BOARD_AVERMEDIA_M733A       180
 #define SAA7134_BOARD_TECHNOTREND_BUDGET_T3000 181
+#define SAA7134_BOARD_KWORLD_PCI_SBTVD_FULLSEG 182
+#define SAA7134_BOARD_VIDEOMATE_M1F         183
 
 #define SAA7134_MAXBOARDS 32
 #define SAA7134_INPUT_MAX 8
@@ -529,7 +551,7 @@ struct saa7134_dev {
 
 	/* infrared remote */
 	int                        has_remote;
-	struct card_ir		   *remote;
+	struct saa7134_card_ir     *remote;
 
 	/* pci i/o */
 	char                       name[32];
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/saa7134/saa7134-input.c linux-libre-2.6.38-gnu1/drivers/media/video/saa7134/saa7134-input.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/saa7134/saa7134-input.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/saa7134/saa7134-input.c	2011-03-14 21:20:32.000000000 -0400
@@ -22,7 +22,6 @@
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
-#include <linux/input.h>
 #include <linux/slab.h>
 
 #include "saa7134-reg.h"
@@ -42,41 +41,19 @@ static int pinnacle_remote;
 module_param(pinnacle_remote, int, 0644);    /* Choose Pinnacle PCTV remote */
 MODULE_PARM_DESC(pinnacle_remote, "Specify Pinnacle PCTV remote: 0=coloured, 1=grey (defaults to 0)");
 
-static int ir_rc5_remote_gap = 885;
-module_param(ir_rc5_remote_gap, int, 0644);
-static int ir_rc5_key_timeout = 115;
-module_param(ir_rc5_key_timeout, int, 0644);
-
-static int repeat_delay = 500;
-module_param(repeat_delay, int, 0644);
-MODULE_PARM_DESC(repeat_delay, "delay before key repeat started");
-static int repeat_period = 33;
-module_param(repeat_period, int, 0644);
-MODULE_PARM_DESC(repeat_period, "repeat period between "
-    "keypresses when key is down");
-
-static unsigned int disable_other_ir;
-module_param(disable_other_ir, int, 0644);
-MODULE_PARM_DESC(disable_other_ir, "disable full codes of "
-    "alternative remotes from other manufacturers");
-
 #define dprintk(fmt, arg...)	if (ir_debug) \
 	printk(KERN_DEBUG "%s/ir: " fmt, dev->name , ## arg)
 #define i2cdprintk(fmt, arg...)    if (ir_debug) \
 	printk(KERN_DEBUG "%s/ir: " fmt, ir->name , ## arg)
 
-/* Helper functions for RC5 and NEC decoding at GPIO16 or GPIO18 */
-static int saa7134_rc5_irq(struct saa7134_dev *dev);
-static int saa7134_nec_irq(struct saa7134_dev *dev);
+/* Helper function for raw decoding at GPIO16 or GPIO18 */
 static int saa7134_raw_decode_irq(struct saa7134_dev *dev);
-static void nec_task(unsigned long data);
-static void saa7134_nec_timer(unsigned long data);
 
 /* -------------------- GPIO generic keycode builder -------------------- */
 
 static int build_key(struct saa7134_dev *dev)
 {
-	struct card_ir *ir = dev->remote;
+	struct saa7134_card_ir *ir = dev->remote;
 	u32 gpio, data;
 
 	/* here comes the additional handshake steps for some cards */
@@ -104,25 +81,25 @@ static int build_key(struct saa7134_dev
 	switch (dev->board) {
 	case SAA7134_BOARD_KWORLD_PLUS_TV_ANALOG:
 		if (data == ir->mask_keycode)
-			ir_input_nokey(ir->dev, &ir->ir);
+			rc_keyup(ir->dev);
 		else
-			ir_input_keydown(ir->dev, &ir->ir, data);
+			rc_keydown_notimeout(ir->dev, data, 0);
 		return 0;
 	}
 
 	if (ir->polling) {
 		if ((ir->mask_keydown  &&  (0 != (gpio & ir->mask_keydown))) ||
 		    (ir->mask_keyup    &&  (0 == (gpio & ir->mask_keyup)))) {
-			ir_input_keydown(ir->dev, &ir->ir, data);
+			rc_keydown_notimeout(ir->dev, data, 0);
 		} else {
-			ir_input_nokey(ir->dev, &ir->ir);
+			rc_keyup(ir->dev);
 		}
 	}
 	else {	/* IRQ driven mode - handle key press and release in one go */
 		if ((ir->mask_keydown  &&  (0 != (gpio & ir->mask_keydown))) ||
 		    (ir->mask_keyup    &&  (0 == (gpio & ir->mask_keyup)))) {
-			ir_input_keydown(ir->dev, &ir->ir, data);
-			ir_input_nokey(ir->dev, &ir->ir);
+			rc_keydown_notimeout(ir->dev, data, 0);
+			rc_keyup(ir->dev);
 		}
 	}
 
@@ -300,22 +277,12 @@ static int get_key_beholdm6xx(struct IR_
 		i2cdprintk("read error\n");
 		return -EIO;
 	}
-	/* IR of this card normally decode signals NEC-standard from
-	 * - Sven IHOO MT 5.1R remote. xxyye718
-	 * - Sven DVD HD-10xx remote. xxyyf708
-	 * - BBK ...
-	 * - mayby others
-	 * So, skip not our, if disable full codes mode.
-	 */
-	if (data[10] != 0x6b && data[11] != 0x86 && disable_other_ir)
-		return 0;
 
-	/* Wrong data decode fix */
 	if (data[9] != (unsigned char)(~data[8]))
 		return 0;
 
-	*ir_key = data[9];
-	*ir_raw = data[9];
+	*ir_raw = ((data[10] << 16) | (data[11] << 8) | (data[9] << 0));
+	*ir_key = *ir_raw;
 
 	return 1;
 }
@@ -400,7 +367,7 @@ static int get_key_pinnacle_color(struct
 
 void saa7134_input_irq(struct saa7134_dev *dev)
 {
-	struct card_ir *ir;
+	struct saa7134_card_ir *ir;
 
 	if (!dev || !dev->remote)
 		return;
@@ -409,12 +376,8 @@ void saa7134_input_irq(struct saa7134_de
 	if (!ir->running)
 		return;
 
-	if (ir->nec_gpio) {
-		saa7134_nec_irq(dev);
-	} else if (!ir->polling && !ir->rc5_gpio && !ir->raw_decode) {
+	if (!ir->polling && !ir->raw_decode) {
 		build_key(dev);
-	} else if (ir->rc5_gpio) {
-		saa7134_rc5_irq(dev);
 	} else if (ir->raw_decode) {
 		saa7134_raw_decode_irq(dev);
 	}
@@ -423,7 +386,7 @@ void saa7134_input_irq(struct saa7134_de
 static void saa7134_input_timer(unsigned long data)
 {
 	struct saa7134_dev *dev = (struct saa7134_dev *)data;
-	struct card_ir *ir = dev->remote;
+	struct saa7134_card_ir *ir = dev->remote;
 
 	build_key(dev);
 	mod_timer(&ir->timer, jiffies + msecs_to_jiffies(ir->polling));
@@ -432,57 +395,37 @@ static void saa7134_input_timer(unsigned
 static void ir_raw_decode_timer_end(unsigned long data)
 {
 	struct saa7134_dev *dev = (struct saa7134_dev *)data;
-	struct card_ir *ir = dev->remote;
+	struct saa7134_card_ir *ir = dev->remote;
 
 	ir_raw_event_handle(dev->remote->dev);
 
-	ir->active = 0;
+	ir->active = false;
 }
 
 static int __saa7134_ir_start(void *priv)
 {
 	struct saa7134_dev *dev = priv;
-	struct card_ir *ir;
+	struct saa7134_card_ir *ir;
 
-	if (!dev)
+	if (!dev || !dev->remote)
 		return -EINVAL;
 
 	ir  = dev->remote;
-	if (!ir)
-		return -EINVAL;
-
 	if (ir->running)
 		return 0;
 
-	ir->running = 1;
+	ir->running = true;
+	ir->active = false;
+
 	if (ir->polling) {
 		setup_timer(&ir->timer, saa7134_input_timer,
 			    (unsigned long)dev);
-		ir->timer.expires  = jiffies + HZ;
+		ir->timer.expires = jiffies + HZ;
 		add_timer(&ir->timer);
-	} else if (ir->rc5_gpio) {
-		/* set timer_end for code completion */
-		init_timer(&ir->timer_end);
-		ir->timer_end.function = ir_rc5_timer_end;
-		ir->timer_end.data = (unsigned long)ir;
-		init_timer(&ir->timer_keyup);
-		ir->timer_keyup.function = ir_rc5_timer_keyup;
-		ir->timer_keyup.data = (unsigned long)ir;
-		ir->shift_by = 2;
-		ir->start = 0x2;
-		ir->addr = 0x17;
-		ir->rc5_key_timeout = ir_rc5_key_timeout;
-		ir->rc5_remote_gap = ir_rc5_remote_gap;
-	} else if (ir->nec_gpio) {
-		setup_timer(&ir->timer_keyup, saa7134_nec_timer,
-			    (unsigned long)dev);
-		tasklet_init(&ir->tlet, nec_task, (unsigned long)dev);
 	} else if (ir->raw_decode) {
 		/* set timer_end for code completion */
-		init_timer(&ir->timer_end);
-		ir->timer_end.function = ir_raw_decode_timer_end;
-		ir->timer_end.data = (unsigned long)dev;
-		ir->active = 0;
+		setup_timer(&ir->timer, ir_raw_decode_timer_end,
+			    (unsigned long)dev);
 	}
 
 	return 0;
@@ -491,29 +434,20 @@ static int __saa7134_ir_start(void *priv
 static void __saa7134_ir_stop(void *priv)
 {
 	struct saa7134_dev *dev = priv;
-	struct card_ir *ir;
+	struct saa7134_card_ir *ir;
 
-	if (!dev)
+	if (!dev || !dev->remote)
 		return;
 
 	ir  = dev->remote;
-	if (!ir)
-		return;
-
 	if (!ir->running)
 		return;
-	if (dev->remote->polling)
-		del_timer_sync(&dev->remote->timer);
-	else if (ir->rc5_gpio)
-		del_timer_sync(&ir->timer_end);
-	else if (ir->nec_gpio)
-		tasklet_kill(&ir->tlet);
-	else if (ir->raw_decode) {
-		del_timer_sync(&ir->timer_end);
-		ir->active = 0;
-	}
 
-	ir->running = 0;
+	if (ir->polling || ir->raw_decode)
+		del_timer_sync(&ir->timer);
+
+	ir->active = false;
+	ir->running = false;
 
 	return;
 }
@@ -532,71 +466,33 @@ void saa7134_ir_stop(struct saa7134_dev
 		__saa7134_ir_stop(dev);
 }
 
-static int saa7134_ir_open(void *priv)
+static int saa7134_ir_open(struct rc_dev *rc)
 {
-	struct saa7134_dev *dev = priv;
+	struct saa7134_dev *dev = rc->priv;
 
 	dev->remote->users++;
 	return __saa7134_ir_start(dev);
 }
 
-static void saa7134_ir_close(void *priv)
+static void saa7134_ir_close(struct rc_dev *rc)
 {
-	struct saa7134_dev *dev = priv;
+	struct saa7134_dev *dev = rc->priv;
 
 	dev->remote->users--;
 	if (!dev->remote->users)
 		__saa7134_ir_stop(dev);
 }
 
-
-static int saa7134_ir_change_protocol(void *priv, u64 ir_type)
-{
-	struct saa7134_dev *dev = priv;
-	struct card_ir *ir = dev->remote;
-	u32 nec_gpio, rc5_gpio;
-
-	if (ir_type == IR_TYPE_RC5) {
-		dprintk("Changing protocol to RC5\n");
-		nec_gpio = 0;
-		rc5_gpio = 1;
-	} else if (ir_type == IR_TYPE_NEC) {
-		dprintk("Changing protocol to NEC\n");
-		nec_gpio = 1;
-		rc5_gpio = 0;
-	} else {
-		dprintk("IR protocol type %ud is not supported\n",
-			(unsigned)ir_type);
-		return -EINVAL;
-	}
-
-	if (ir->running) {
-		saa7134_ir_stop(dev);
-		ir->nec_gpio = nec_gpio;
-		ir->rc5_gpio = rc5_gpio;
-		saa7134_ir_start(dev);
-	} else {
-		ir->nec_gpio = nec_gpio;
-		ir->rc5_gpio = rc5_gpio;
-	}
-
-	return 0;
-}
-
 int saa7134_input_init1(struct saa7134_dev *dev)
 {
-	struct card_ir *ir;
-	struct input_dev *input_dev;
+	struct saa7134_card_ir *ir;
+	struct rc_dev *rc;
 	char *ir_codes = NULL;
 	u32 mask_keycode = 0;
 	u32 mask_keydown = 0;
 	u32 mask_keyup   = 0;
-	int polling      = 0;
-	int rc5_gpio	 = 0;
-	int nec_gpio	 = 0;
-	int raw_decode   = 0;
-	int allow_protocol_change = 0;
-	u64 ir_type = IR_TYPE_OTHER;
+	unsigned polling = 0;
+	bool raw_decode  = false;
 	int err;
 
 	if (dev->has_remote != SAA7134_REMOTE_GPIO)
@@ -661,14 +557,14 @@ int saa7134_input_init1(struct saa7134_d
 		mask_keydown = 0x0040000;	/* Enable GPIO18 line on both edges */
 		mask_keyup   = 0x0040000;
 		mask_keycode = 0xffff;
-		raw_decode   = 1;
+		raw_decode   = true;
 		break;
 	case SAA7134_BOARD_AVERMEDIA_M733A:
 		ir_codes     = RC_MAP_AVERMEDIA_M733A_RM_K6;
 		mask_keydown = 0x0040000;
 		mask_keyup   = 0x0040000;
 		mask_keycode = 0xffff;
-		raw_decode   = 1;
+		raw_decode   = true;
 		break;
 	case SAA7134_BOARD_AVERMEDIA_777:
 	case SAA7134_BOARD_AVERMEDIA_A16AR:
@@ -775,7 +671,7 @@ int saa7134_input_init1(struct saa7134_d
 		mask_keydown = 0x0040000;	/* Enable GPIO18 line on both edges */
 		mask_keyup   = 0x0040000;
 		mask_keycode = 0xffff;
-		raw_decode   = 1;
+		raw_decode   = true;
 		break;
 	case SAA7134_BOARD_ENCORE_ENLTV:
 	case SAA7134_BOARD_ENCORE_ENLTV_FM:
@@ -786,9 +682,10 @@ int saa7134_input_init1(struct saa7134_d
 		break;
 	case SAA7134_BOARD_ENCORE_ENLTV_FM53:
 		ir_codes     = RC_MAP_ENCORE_ENLTV_FM53;
-		mask_keydown = 0x0040000;
-		mask_keycode = 0x00007f;
-		nec_gpio = 1;
+		mask_keydown = 0x0040000;	/* Enable GPIO18 line on both edges */
+		mask_keyup   = 0x0040000;
+		mask_keycode = 0xffff;
+		raw_decode   = true;
 		break;
 	case SAA7134_BOARD_10MOONSTVMASTER3:
 		ir_codes     = RC_MAP_ENCORE_ENLTV;
@@ -824,6 +721,11 @@ int saa7134_input_init1(struct saa7134_d
 		mask_keyup   = 0x020000;
 		polling      = 50; /* ms */
 		break;
+	case SAA7134_BOARD_VIDEOMATE_M1F:
+		ir_codes     = RC_MAP_VIDEOMATE_M1F;
+		mask_keycode = 0x0ff00;
+		mask_keyup   = 0x040000;
+		break;
 	}
 	if (NULL == ir_codes) {
 		printk("%s: Oops: IR config error [card=%d]\n",
@@ -832,24 +734,20 @@ int saa7134_input_init1(struct saa7134_d
 	}
 
 	ir = kzalloc(sizeof(*ir), GFP_KERNEL);
-	input_dev = input_allocate_device();
-	if (!ir || !input_dev) {
+	rc = rc_allocate_device();
+	if (!ir || !rc) {
 		err = -ENOMEM;
 		goto err_out_free;
 	}
 
-	ir->dev = input_dev;
+	ir->dev = rc;
 	dev->remote = ir;
 
-	ir->running = 0;
-
 	/* init hardware-specific stuff */
 	ir->mask_keycode = mask_keycode;
 	ir->mask_keydown = mask_keydown;
 	ir->mask_keyup   = mask_keyup;
 	ir->polling      = polling;
-	ir->rc5_gpio	 = rc5_gpio;
-	ir->nec_gpio	 = nec_gpio;
 	ir->raw_decode	 = raw_decode;
 
 	/* init input device */
@@ -858,47 +756,35 @@ int saa7134_input_init1(struct saa7134_d
 	snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0",
 		 pci_name(dev->pci));
 
-
-	ir->props.priv = dev;
-	ir->props.open = saa7134_ir_open;
-	ir->props.close = saa7134_ir_close;
-
+	rc->priv = dev;
+	rc->open = saa7134_ir_open;
+	rc->close = saa7134_ir_close;
 	if (raw_decode)
-		ir->props.driver_type = RC_DRIVER_IR_RAW;
-
-	if (!raw_decode && allow_protocol_change) {
-		ir->props.allowed_protos = IR_TYPE_RC5 | IR_TYPE_NEC;
-		ir->props.change_protocol = saa7134_ir_change_protocol;
-	}
-
-	err = ir_input_init(input_dev, &ir->ir, ir_type);
-	if (err < 0)
-		goto err_out_free;
+		rc->driver_type = RC_DRIVER_IR_RAW;
 
-	input_dev->name = ir->name;
-	input_dev->phys = ir->phys;
-	input_dev->id.bustype = BUS_PCI;
-	input_dev->id.version = 1;
+	rc->input_name = ir->name;
+	rc->input_phys = ir->phys;
+	rc->input_id.bustype = BUS_PCI;
+	rc->input_id.version = 1;
 	if (dev->pci->subsystem_vendor) {
-		input_dev->id.vendor  = dev->pci->subsystem_vendor;
-		input_dev->id.product = dev->pci->subsystem_device;
+		rc->input_id.vendor  = dev->pci->subsystem_vendor;
+		rc->input_id.product = dev->pci->subsystem_device;
 	} else {
-		input_dev->id.vendor  = dev->pci->vendor;
-		input_dev->id.product = dev->pci->device;
+		rc->input_id.vendor  = dev->pci->vendor;
+		rc->input_id.product = dev->pci->device;
 	}
-	input_dev->dev.parent = &dev->pci->dev;
+	rc->dev.parent = &dev->pci->dev;
+	rc->map_name = ir_codes;
+	rc->driver_name = MODULE_NAME;
 
-	err = ir_input_register(ir->dev, ir_codes, &ir->props, MODULE_NAME);
+	err = rc_register_device(rc);
 	if (err)
 		goto err_out_free;
 
-	/* the remote isn't as bouncy as a keyboard */
-	ir->dev->rep[REP_DELAY] = repeat_delay;
-	ir->dev->rep[REP_PERIOD] = repeat_period;
-
 	return 0;
 
 err_out_free:
+	rc_free_device(rc);
 	dev->remote = NULL;
 	kfree(ir);
 	return err;
@@ -910,7 +796,7 @@ void saa7134_input_fini(struct saa7134_d
 		return;
 
 	saa7134_ir_stop(dev);
-	ir_input_unregister(dev->remote->dev);
+	rc_unregister_device(dev->remote->dev);
 	kfree(dev->remote);
 	dev->remote = NULL;
 }
@@ -918,14 +804,12 @@ void saa7134_input_fini(struct saa7134_d
 void saa7134_probe_i2c_ir(struct saa7134_dev *dev)
 {
 	struct i2c_board_info info;
-
 	struct i2c_msg msg_msi = {
 		.addr = 0x50,
 		.flags = I2C_M_RD,
 		.len = 0,
 		.buf = NULL,
 	};
-
 	int rc;
 
 	if (disable_ir) {
@@ -972,7 +856,7 @@ void saa7134_probe_i2c_ir(struct saa7134
 		   an existing device. Weird...
 		   REVISIT: might no longer be needed */
 		rc = i2c_transfer(&dev->i2c_adap, &msg_msi, 1);
-		dprintk(KERN_DEBUG "probe 0x%02x @ %s: %s\n",
+		dprintk("probe 0x%02x @ %s: %s\n",
 			msg_msi.addr, dev->i2c_adap.name,
 			(1 == rc) ? "yes" : "no");
 		break;
@@ -1000,7 +884,7 @@ void saa7134_probe_i2c_ir(struct saa7134
 		dev->init_data.name = "BeholdTV";
 		dev->init_data.get_key = get_key_beholdm6xx;
 		dev->init_data.ir_codes = RC_MAP_BEHOLD;
-		dev->init_data.type = IR_TYPE_NEC;
+		dev->init_data.type = RC_TYPE_NEC;
 		info.addr = 0x2d;
 		break;
 	case SAA7134_BOARD_AVERMEDIA_CARDBUS_501:
@@ -1025,8 +909,8 @@ void saa7134_probe_i2c_ir(struct saa7134
 
 static int saa7134_raw_decode_irq(struct saa7134_dev *dev)
 {
-	struct card_ir	*ir = dev->remote;
-	unsigned long 	timeout;
+	struct saa7134_card_ir *ir = dev->remote;
+	unsigned long timeout;
 	int space;
 
 	/* Generate initial event */
@@ -1035,7 +919,6 @@ static int saa7134_raw_decode_irq(struct
 	space = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2) & ir->mask_keydown;
 	ir_raw_event_store_edge(dev->remote->dev, space ? IR_SPACE : IR_PULSE);
 
-
 	/*
 	 * Wait 15 ms from the start of the first IR event before processing
 	 * the event. This time is enough for NEC protocol. May need adjustments
@@ -1043,173 +926,9 @@ static int saa7134_raw_decode_irq(struct
 	 */
 	if (!ir->active) {
 		timeout = jiffies + jiffies_to_msecs(15);
-		mod_timer(&ir->timer_end, timeout);
-		ir->active = 1;
-	}
-
-	return 1;
-}
-
-static int saa7134_rc5_irq(struct saa7134_dev *dev)
-{
-	struct card_ir *ir = dev->remote;
-	struct timeval tv;
-	u32 gap;
-	unsigned long current_jiffies, timeout;
-
-	/* get time of bit */
-	current_jiffies = jiffies;
-	do_gettimeofday(&tv);
-
-	/* avoid overflow with gap >1s */
-	if (tv.tv_sec - ir->base_time.tv_sec > 1) {
-		gap = 200000;
-	} else {
-		gap = 1000000 * (tv.tv_sec - ir->base_time.tv_sec) +
-		    tv.tv_usec - ir->base_time.tv_usec;
-	}
-
-	/* active code => add bit */
-	if (ir->active) {
-		/* only if in the code (otherwise spurious IRQ or timer
-		   late) */
-		if (ir->last_bit < 28) {
-			ir->last_bit = (gap - ir_rc5_remote_gap / 2) /
-			    ir_rc5_remote_gap;
-			ir->code |= 1 << ir->last_bit;
-		}
-		/* starting new code */
-	} else {
-		ir->active = 1;
-		ir->code = 0;
-		ir->base_time = tv;
-		ir->last_bit = 0;
-
-		timeout = current_jiffies + (500 + 30 * HZ) / 1000;
-		mod_timer(&ir->timer_end, timeout);
-	}
-
-	return 1;
-}
-
-/* On NEC protocol, One has 2.25 ms, and zero has 1.125 ms
-   The first pulse (start) has 9 + 4.5 ms
- */
-
-static void saa7134_nec_timer(unsigned long data)
-{
-	struct saa7134_dev *dev = (struct saa7134_dev *) data;
-	struct card_ir *ir = dev->remote;
-
-	dprintk("Cancel key repeat\n");
-
-	ir_input_nokey(ir->dev, &ir->ir);
-}
-
-static void nec_task(unsigned long data)
-{
-	struct saa7134_dev *dev = (struct saa7134_dev *) data;
-	struct card_ir *ir;
-	struct timeval tv;
-	int count, pulse, oldpulse, gap;
-	u32 ircode = 0, not_code = 0;
-	int ngap = 0;
-
-	if (!data) {
-		printk(KERN_ERR "saa713x/ir: Can't recover dev struct\n");
-		/* GPIO will be kept disabled */
-		return;
+		mod_timer(&ir->timer, timeout);
+		ir->active = true;
 	}
 
-	ir = dev->remote;
-
-	/* rising SAA7134_GPIO_GPRESCAN reads the status */
-	saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN);
-	saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN);
-
-	oldpulse = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2) & ir->mask_keydown;
-	pulse = oldpulse;
-
-	do_gettimeofday(&tv);
-	ir->base_time = tv;
-
-	/* Decode NEC pulsecode. This code can take up to 76.5 ms to run.
-	   Unfortunately, using IRQ to decode pulse didn't work, since it uses
-	   a pulse train of 38KHz. This means one pulse on each 52 us
-	 */
-	do {
-		/* Wait until the end of pulse/space or 5 ms */
-		for (count = 0; count < 500; count++)  {
-			udelay(10);
-			/* rising SAA7134_GPIO_GPRESCAN reads the status */
-			saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN);
-			saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN);
-			pulse = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2)
-				& ir->mask_keydown;
-			if (pulse != oldpulse)
-				break;
-		}
-
-		do_gettimeofday(&tv);
-		gap = 1000000 * (tv.tv_sec - ir->base_time.tv_sec) +
-				tv.tv_usec - ir->base_time.tv_usec;
-
-		if (!pulse) {
-			/* Bit 0 has 560 us, while bit 1 has 1120 us.
-			   Do something only if bit == 1
-			 */
-			if (ngap && (gap > 560 + 280)) {
-				unsigned int shift = ngap - 1;
-
-				/* Address first, then command */
-				if (shift < 8) {
-					shift += 8;
-					ircode |= 1 << shift;
-				} else if (shift < 16) {
-					not_code |= 1 << shift;
-				} else if (shift < 24) {
-					shift -= 16;
-					ircode |= 1 << shift;
-				} else {
-					shift -= 24;
-					not_code |= 1 << shift;
-				}
-			}
-			ngap++;
-		}
-
-
-		ir->base_time = tv;
-
-		/* TIMEOUT - Long pulse */
-		if (gap >= 5000)
-			break;
-		oldpulse = pulse;
-	} while (ngap < 32);
-
-	if (ngap == 32) {
-		/* FIXME: should check if not_code == ~ircode */
-		ir->code = ir_extract_bits(ircode, ir->mask_keycode);
-
-		dprintk("scancode = 0x%02x (code = 0x%02x, notcode= 0x%02x)\n",
-			 ir->code, ircode, not_code);
-
-		ir_input_keydown(ir->dev, &ir->ir, ir->code);
-	} else
-		dprintk("Repeat last key\n");
-
-	/* Keep repeating the last key */
-	mod_timer(&ir->timer_keyup, jiffies + msecs_to_jiffies(150));
-
-	saa_setl(SAA7134_IRQ2, SAA7134_IRQ2_INTE_GPIO18_P);
-}
-
-static int saa7134_nec_irq(struct saa7134_dev *dev)
-{
-	struct card_ir *ir = dev->remote;
-
-	saa_clearl(SAA7134_IRQ2, SAA7134_IRQ2_INTE_GPIO18_P);
-	tasklet_schedule(&ir->tlet);
-
 	return 1;
 }
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/saa7134/saa7134-tvaudio.c linux-libre-2.6.38-gnu1/drivers/media/video/saa7134/saa7134-tvaudio.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/saa7134/saa7134-tvaudio.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/saa7134/saa7134-tvaudio.c	2011-03-14 21:20:32.000000000 -0400
@@ -550,16 +550,16 @@ static int tvaudio_thread(void *data)
 		} else if (0 != dev->last_carrier) {
 			/* no carrier -- try last detected one as fallback */
 			carrier = dev->last_carrier;
-			dprintk(KERN_WARNING "%s/audio: audio carrier scan failed, "
-			       "using %d.%03d MHz [last detected]\n",
-			       dev->name, carrier/1000, carrier%1000);
+			dprintk("audio carrier scan failed, "
+				"using %d.%03d MHz [last detected]\n",
+				carrier/1000, carrier%1000);
 
 		} else {
 			/* no carrier + no fallback -- use default */
 			carrier = default_carrier;
-			dprintk(KERN_WARNING "%s/audio: audio carrier scan failed, "
-			       "using %d.%03d MHz [default]\n",
-			       dev->name, carrier/1000, carrier%1000);
+			dprintk("audio carrier scan failed, "
+				"using %d.%03d MHz [default]\n",
+				carrier/1000, carrier%1000);
 		}
 		tvaudio_setcarrier(dev,carrier,carrier);
 		dev->automute = 0;
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/saa7134/saa7134-video.c linux-libre-2.6.38-gnu1/drivers/media/video/saa7134/saa7134-video.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/saa7134/saa7134-video.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/saa7134/saa7134-video.c	2011-03-14 21:20:32.000000000 -0400
@@ -30,7 +30,7 @@
 #include "saa7134-reg.h"
 #include "saa7134.h"
 #include <media/v4l2-common.h>
-#include <media/rds.h>
+#include <media/saa6588.h>
 
 /* ------------------------------------------------------------------ */
 
@@ -1459,7 +1459,7 @@ static int video_release(struct file *fi
 {
 	struct saa7134_fh  *fh  = file->private_data;
 	struct saa7134_dev *dev = fh->dev;
-	struct rds_command cmd;
+	struct saa6588_command cmd;
 	unsigned long flags;
 
 	/* turn off overlay */
@@ -1494,7 +1494,7 @@ static int video_release(struct file *fi
 
 	saa_call_all(dev, core, s_power, 0);
 	if (fh->radio)
-		saa_call_all(dev, core, ioctl, RDS_CMD_CLOSE, &cmd);
+		saa_call_all(dev, core, ioctl, SAA6588_CMD_CLOSE, &cmd);
 
 	/* free stuff */
 	videobuf_mmap_free(&fh->cap);
@@ -1520,14 +1520,14 @@ static ssize_t radio_read(struct file *f
 {
 	struct saa7134_fh *fh = file->private_data;
 	struct saa7134_dev *dev = fh->dev;
-	struct rds_command cmd;
+	struct saa6588_command cmd;
 
 	cmd.block_count = count/3;
 	cmd.buffer = data;
 	cmd.instance = file;
 	cmd.result = -ENODEV;
 
-	saa_call_all(dev, core, ioctl, RDS_CMD_READ, &cmd);
+	saa_call_all(dev, core, ioctl, SAA6588_CMD_READ, &cmd);
 
 	return cmd.result;
 }
@@ -1536,12 +1536,12 @@ static unsigned int radio_poll(struct fi
 {
 	struct saa7134_fh *fh = file->private_data;
 	struct saa7134_dev *dev = fh->dev;
-	struct rds_command cmd;
+	struct saa6588_command cmd;
 
 	cmd.instance = file;
 	cmd.event_list = wait;
 	cmd.result = -ENODEV;
-	saa_call_all(dev, core, ioctl, RDS_CMD_POLL, &cmd);
+	saa_call_all(dev, core, ioctl, SAA6588_CMD_POLL, &cmd);
 
 	return cmd.result;
 }
@@ -1748,7 +1748,6 @@ static int saa7134_enum_input(struct fil
 		return -EINVAL;
 	if (NULL == card_in(dev, i->index).name)
 		return -EINVAL;
-	memset(i, 0, sizeof(*i));
 	i->index = n;
 	i->type  = V4L2_INPUT_TYPE_CAMERA;
 	strcpy(i->name, card_in(dev, n).name);
@@ -2211,14 +2210,6 @@ static int saa7134_overlay(struct file *
 	return 0;
 }
 
-#ifdef CONFIG_VIDEO_V4L1_COMPAT
-static int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf)
-{
-	struct saa7134_fh *fh = file->private_data;
-	return videobuf_cgmbuf(saa7134_queue(fh), mbuf, 8);
-}
-#endif
-
 static int saa7134_reqbufs(struct file *file, void *priv,
 					struct v4l2_requestbuffers *p)
 {
@@ -2456,9 +2447,6 @@ static const struct v4l2_ioctl_ops video
 	.vidioc_streamoff		= saa7134_streamoff,
 	.vidioc_g_tuner			= saa7134_g_tuner,
 	.vidioc_s_tuner			= saa7134_s_tuner,
-#ifdef CONFIG_VIDEO_V4L1_COMPAT
-	.vidiocgmbuf			= vidiocgmbuf,
-#endif
 	.vidioc_g_crop			= saa7134_g_crop,
 	.vidioc_s_crop			= saa7134_s_crop,
 	.vidioc_g_fbuf			= saa7134_g_fbuf,
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/saa7164/saa7164-api.c linux-libre-2.6.38-gnu1/drivers/media/video/saa7164/saa7164-api.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/saa7164/saa7164-api.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/saa7164/saa7164-api.c	2011-03-14 21:20:32.000000000 -0400
@@ -40,9 +40,8 @@ int saa7164_api_get_load_info(struct saa
 
 	ret = saa7164_cmd_send(dev, 0, GET_CUR,
 		GET_FW_STATUS_CONTROL, sizeof(struct tmFwInfoStruct), i);
-	if (ret != SAA_OK) {
+	if (ret != SAA_OK)
 		printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
-	}
 
 	printk(KERN_INFO "saa7164[%d]-CPU: %d percent", dev->nr, i->CPULoad);
 
@@ -63,14 +62,15 @@ int saa7164_api_collect_debug(struct saa
 
 		ret = saa7164_cmd_send(dev, 0, GET_CUR,
 			GET_DEBUG_DATA_CONTROL, sizeof(d), &d);
-		if (ret != SAA_OK) {
-			printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
-		}
+		if (ret != SAA_OK)
+			printk(KERN_ERR "%s() error, ret = 0x%x\n",
+				__func__, ret);
 
 		if (d.dwResult != SAA_OK)
 			break;
 
-		printk(KERN_INFO "saa7164[%d]-FWMSG: %s", dev->nr, d.ucDebugData);
+		printk(KERN_INFO "saa7164[%d]-FWMSG: %s", dev->nr,
+			d.ucDebugData);
 	}
 
 	return 0;
@@ -86,9 +86,9 @@ int saa7164_api_set_debug(struct saa7164
 	/* Retrieve current state */
 	ret = saa7164_cmd_send(dev, 0, GET_CUR,
 		SET_DEBUG_LEVEL_CONTROL, sizeof(lvl), &lvl);
-	if (ret != SAA_OK) {
+	if (ret != SAA_OK)
 		printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
-	}
+
 	dprintk(DBGLVL_API, "%s() Was %d\n", __func__, lvl.dwDebugLevel);
 
 	lvl.dwDebugLevel = level;
@@ -96,9 +96,8 @@ int saa7164_api_set_debug(struct saa7164
 	/* set new state */
 	ret = saa7164_cmd_send(dev, 0, SET_CUR,
 		SET_DEBUG_LEVEL_CONTROL, sizeof(lvl), &lvl);
-	if (ret != SAA_OK) {
+	if (ret != SAA_OK)
 		printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
-	}
 
 	return ret;
 }
@@ -152,8 +151,10 @@ int saa7164_api_set_vbi_format(struct sa
 				dprintk(DBGLVL_API, "SET/COMMIT Verified\n");
 
 			dprintk(DBGLVL_API, "rsp.bmHint = 0x%x\n", rsp.bmHint);
-			dprintk(DBGLVL_API, "rsp.bFormatIndex = 0x%x\n", rsp.bFormatIndex);
-			dprintk(DBGLVL_API, "rsp.bFrameIndex = 0x%x\n", rsp.bFrameIndex);
+			dprintk(DBGLVL_API, "rsp.bFormatIndex = 0x%x\n",
+				rsp.bFormatIndex);
+			dprintk(DBGLVL_API, "rsp.bFrameIndex = 0x%x\n",
+				rsp.bFrameIndex);
 		} else
 			printk(KERN_ERR "%s() compare failed\n", __func__);
 	}
@@ -210,14 +211,17 @@ int saa7164_api_set_encoder(struct saa71
 		printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
 
 	/* Establish video bitrates */
-	if (port->encoder_params.bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_CBR)
+	if (port->encoder_params.bitrate_mode ==
+		V4L2_MPEG_VIDEO_BITRATE_MODE_CBR)
 		vb.ucVideoBitRateMode = EU_VIDEO_BIT_RATE_MODE_CONSTANT;
 	else
 		vb.ucVideoBitRateMode = EU_VIDEO_BIT_RATE_MODE_VARIABLE_PEAK;
 	vb.dwVideoBitRate = port->encoder_params.bitrate;
 	vb.dwVideoBitRatePeak = port->encoder_params.bitrate_peak;
 	ret = saa7164_cmd_send(port->dev, port->hwcfg.sourceid, SET_CUR,
-		EU_VIDEO_BIT_RATE_CONTROL, sizeof(struct tmComResEncVideoBitRate), &vb);
+		EU_VIDEO_BIT_RATE_CONTROL,
+		sizeof(struct tmComResEncVideoBitRate),
+		&vb);
 	if (ret != SAA_OK)
 		printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
 
@@ -226,9 +230,12 @@ int saa7164_api_set_encoder(struct saa71
 	ab.dwAudioBitRate = 384000;
 	ab.dwAudioBitRatePeak = ab.dwAudioBitRate;
 	ret = saa7164_cmd_send(port->dev, port->hwcfg.sourceid, SET_CUR,
-		EU_AUDIO_BIT_RATE_CONTROL, sizeof(struct tmComResEncAudioBitRate), &ab);
+		EU_AUDIO_BIT_RATE_CONTROL,
+		sizeof(struct tmComResEncAudioBitRate),
+		&ab);
 	if (ret != SAA_OK)
-		printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
+		printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__,
+			ret);
 
 	saa7164_api_set_aspect_ratio(port);
 	saa7164_api_set_gop_size(port);
@@ -244,7 +251,8 @@ int saa7164_api_get_encoder(struct saa71
 	struct tmComResEncVideoInputAspectRatio ar;
 	int ret;
 
-	dprintk(DBGLVL_ENC, "%s() unitid=0x%x\n", __func__, port->hwcfg.sourceid);
+	dprintk(DBGLVL_ENC, "%s() unitid=0x%x\n", __func__,
+		port->hwcfg.sourceid);
 
 	port->encoder_profile = 0;
 	port->video_format = 0;
@@ -257,7 +265,8 @@ int saa7164_api_get_encoder(struct saa71
 		printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
 
 	ret = saa7164_cmd_send(port->dev, port->hwcfg.sourceid, GET_CUR,
-		EU_VIDEO_RESOLUTION_CONTROL, sizeof(u8), &port->video_resolution);
+		EU_VIDEO_RESOLUTION_CONTROL, sizeof(u8),
+		&port->video_resolution);
 	if (ret != SAA_OK)
 		printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
 
@@ -294,13 +303,20 @@ int saa7164_api_get_encoder(struct saa71
 	dprintk(DBGLVL_ENC, "video_format    = %d\n", port->video_format);
 	dprintk(DBGLVL_ENC, "audio_format    = %d\n", port->audio_format);
 	dprintk(DBGLVL_ENC, "video_resolution= %d\n", port->video_resolution);
-	dprintk(DBGLVL_ENC, "v.ucVideoBitRateMode = %d\n", v.ucVideoBitRateMode);
-	dprintk(DBGLVL_ENC, "v.dwVideoBitRate     = %d\n", v.dwVideoBitRate);
-	dprintk(DBGLVL_ENC, "v.dwVideoBitRatePeak = %d\n", v.dwVideoBitRatePeak);
-	dprintk(DBGLVL_ENC, "a.ucVideoBitRateMode = %d\n", a.ucAudioBitRateMode);
-	dprintk(DBGLVL_ENC, "a.dwVideoBitRate     = %d\n", a.dwAudioBitRate);
-	dprintk(DBGLVL_ENC, "a.dwVideoBitRatePeak = %d\n", a.dwAudioBitRatePeak);
-	dprintk(DBGLVL_ENC, "aspect.width / height = %d:%d\n", ar.width, ar.height);
+	dprintk(DBGLVL_ENC, "v.ucVideoBitRateMode = %d\n",
+		v.ucVideoBitRateMode);
+	dprintk(DBGLVL_ENC, "v.dwVideoBitRate     = %d\n",
+		v.dwVideoBitRate);
+	dprintk(DBGLVL_ENC, "v.dwVideoBitRatePeak = %d\n",
+		v.dwVideoBitRatePeak);
+	dprintk(DBGLVL_ENC, "a.ucVideoBitRateMode = %d\n",
+		a.ucAudioBitRateMode);
+	dprintk(DBGLVL_ENC, "a.dwVideoBitRate     = %d\n",
+		a.dwAudioBitRate);
+	dprintk(DBGLVL_ENC, "a.dwVideoBitRatePeak = %d\n",
+		a.dwAudioBitRatePeak);
+	dprintk(DBGLVL_ENC, "aspect.width / height = %d:%d\n",
+		ar.width, ar.height);
 
 	return ret;
 }
@@ -439,7 +455,8 @@ int saa7164_api_set_videomux(struct saa7
 
 	/* Audio Mux */
 	ret = saa7164_cmd_send(port->dev, port->audfeat.sourceid, SET_CUR,
-		SU_INPUT_SELECT_CONTROL, sizeof(u8), &inputs[port->mux_input - 1]);
+		SU_INPUT_SELECT_CONTROL, sizeof(u8),
+		&inputs[port->mux_input - 1]);
 	if (ret != SAA_OK)
 		printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
 
@@ -492,7 +509,8 @@ int saa7164_api_set_audio_volume(struct
 	if (ret != SAA_OK)
 		printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
 
-	dprintk(DBGLVL_API, "%s(%d) min=%d max=%d cur=%d\n", __func__, level, min, max, v);
+	dprintk(DBGLVL_API, "%s(%d) min=%d max=%d cur=%d\n", __func__,
+		level, min, max, v);
 
 	v = level;
 	if (v < min)
@@ -517,7 +535,8 @@ int saa7164_api_set_audio_volume(struct
 	if (ret != SAA_OK)
 		printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
 
-	dprintk(DBGLVL_API, "%s(%d) min=%d max=%d cur=%d\n", __func__, level, min, max, v);
+	dprintk(DBGLVL_API, "%s(%d) min=%d max=%d cur=%d\n", __func__,
+		level, min, max, v);
 
 	return ret;
 }
@@ -539,7 +558,8 @@ int saa7164_api_set_audio_std(struct saa
 	lvl.ucSAP_Level = TMHW_LEV_ADJ_SAPLEV_DEFAULT;
 	lvl.ucADC_Level = TMHW_LEV_ADJ_ADCLEV_DEFAULT;
 	ret = saa7164_cmd_send(port->dev, port->audfeat.unitid, SET_CUR,
-		AUDIO_DEFAULT_CONTROL, sizeof(struct tmComResAudioDefaults), &lvl);
+		AUDIO_DEFAULT_CONTROL, sizeof(struct tmComResAudioDefaults),
+		&lvl);
 	if (ret != SAA_OK)
 		printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
 
@@ -555,7 +575,8 @@ int saa7164_api_set_audio_std(struct saa
 	ret = saa7164_cmd_send(port->dev, port->tunerunit.unitid, SET_CUR,
 		TU_STANDARD_CONTROL, sizeof(tvaudio), &tvaudio);
 	if (ret != SAA_OK)
-		printk(KERN_ERR "%s() TU_STANDARD_CONTROL error, ret = 0x%x\n", __func__, ret);
+		printk(KERN_ERR "%s() TU_STANDARD_CONTROL error, ret = 0x%x\n",
+			__func__, ret);
 	return ret;
 }
 
@@ -575,7 +596,9 @@ int saa7164_api_set_audio_detection(stru
 	ret = saa7164_cmd_send(port->dev, port->tunerunit.unitid, SET_CUR,
 		TU_STANDARD_AUTO_CONTROL, sizeof(p), &p);
 	if (ret != SAA_OK)
-		printk(KERN_ERR "%s() TU_STANDARD_AUTO_CONTROL error, ret = 0x%x\n", __func__, ret);
+		printk(KERN_ERR
+			"%s() TU_STANDARD_AUTO_CONTROL error, ret = 0x%x\n",
+			__func__, ret);
 
 	return ret;
 }
@@ -646,9 +669,9 @@ int saa7164_api_set_dif(struct saa7164_p
 		EXU_REGISTER_ACCESS_CONTROL, len, &buf);
 	if (ret != SAA_OK)
 		printk(KERN_ERR "%s() error, ret(2) = 0x%x\n", __func__, ret);
-
-	//saa7164_dumphex16(dev, buf, 16);
-
+#if 0
+	saa7164_dumphex16(dev, buf, 16);
+#endif
 	return ret == SAA_OK ? 0 : -EIO;
 }
 
@@ -696,7 +719,8 @@ int saa7164_api_configure_dif(struct saa
 	} else {
 		/* Unknown standard, assume DTV */
 		dprintk(DBGLVL_API, " Unknown (assuming DTV)\n");
-		saa7164_api_set_dif(port, 0x00, 0x80); /* Undefined Video Standard */
+		/* Undefinded Video Standard */
+		saa7164_api_set_dif(port, 0x00, 0x80);
 		agc_disable = 1;
 	}
 
@@ -933,7 +957,7 @@ int saa7164_api_dump_subdevs(struct saa7
 		if (hdr->type != CS_INTERFACE)
 			return SAA_ERR_NOT_SUPPORTED;
 
-		dprintk(DBGLVL_API, "@ 0x%x = \n", idx);
+		dprintk(DBGLVL_API, "@ 0x%x =\n", idx);
 		switch (hdr->subtype) {
 		case GENERAL_REQUEST:
 			dprintk(DBGLVL_API, " GENERAL_REQUEST\n");
@@ -1085,7 +1109,8 @@ int saa7164_api_dump_subdevs(struct saa7
 						vbiport = &dev->ports[SAA7164_PORT_VBI2];
 					memcpy(&vbiport->hwcfg, vcoutputtermhdr,
 						sizeof(*vcoutputtermhdr));
-					memcpy(&vbiport->vbi_fmt_ntsc, vbifmt, sizeof(*vbifmt));
+					memcpy(&vbiport->vbi_fmt_ntsc, vbifmt,
+						sizeof(*vbifmt));
 					saa7164_api_configure_port_vbi(dev,
 						vbiport);
 					break;
@@ -1134,7 +1159,9 @@ int saa7164_api_dump_subdevs(struct saa7
 					encport = &dev->ports[SAA7164_PORT_ENC2];
 				memcpy(&encport->tunerunit, tunerunithdr,
 					sizeof(struct tmComResTunerDescrHeader));
-				dprintk(DBGLVL_API, "  (becomes dev->enc[%d] tuner)\n", encport->nr);
+				dprintk(DBGLVL_API,
+					"  (becomes dev->enc[%d] tuner)\n",
+					encport->nr);
 			}
 			break;
 		case VC_SELECTOR_UNIT:
@@ -1163,7 +1190,8 @@ int saa7164_api_dump_subdevs(struct saa7
 					encport = &dev->ports[SAA7164_PORT_ENC2];
 				memcpy(&encport->vidproc, pdh,
 					sizeof(struct tmComResProcDescrHeader));
-				dprintk(DBGLVL_API, "  (becomes dev->enc[%d])\n", encport->nr);
+				dprintk(DBGLVL_API, "  (becomes dev->enc[%d])\n",
+					encport->nr);
 			}
 			break;
 		case FEATURE_UNIT:
@@ -1181,15 +1209,18 @@ int saa7164_api_dump_subdevs(struct saa7
 				encport = &dev->ports[SAA7164_PORT_ENC2];
 			memcpy(&encport->audfeat, afd,
 				sizeof(struct tmComResAFeatureDescrHeader));
-			dprintk(DBGLVL_API, "  (becomes dev->enc[%d])\n", encport->nr);
+			dprintk(DBGLVL_API, "  (becomes dev->enc[%d])\n",
+				encport->nr);
 			break;
 		case ENCODER_UNIT:
 			edh = (struct tmComResEncoderDescrHeader *)(buf + idx);
 			dprintk(DBGLVL_API, " ENCODER_UNIT\n");
 			dprintk(DBGLVL_API, "  subtype = 0x%x\n", edh->subtype);
 			dprintk(DBGLVL_API, "  unitid = 0x%x\n", edh->unitid);
-			dprintk(DBGLVL_API, "  vsourceid = 0x%x\n", edh->vsourceid);
-			dprintk(DBGLVL_API, "  asourceid = 0x%x\n", edh->asourceid);
+			dprintk(DBGLVL_API, "  vsourceid = 0x%x\n",
+			edh->vsourceid);
+			dprintk(DBGLVL_API, "  asourceid = 0x%x\n",
+				edh->asourceid);
 			dprintk(DBGLVL_API, "  iunit = 0x%x\n", edh->iunit);
 			if (edh->iunit == edh->unitid) {
 				if (currpath == 1)
@@ -1198,7 +1229,9 @@ int saa7164_api_dump_subdevs(struct saa7
 					encport = &dev->ports[SAA7164_PORT_ENC2];
 				memcpy(&encport->encunit, edh,
 					sizeof(struct tmComResEncoderDescrHeader));
-				dprintk(DBGLVL_API, "  (becomes dev->enc[%d])\n", encport->nr);
+				dprintk(DBGLVL_API,
+					"  (becomes dev->enc[%d])\n",
+					encport->nr);
 			}
 			break;
 		case EXTENSION_UNIT:
@@ -1262,7 +1295,9 @@ int saa7164_api_dump_subdevs(struct saa7
 					encport = &dev->ports[SAA7164_PORT_ENC2];
 				memcpy(&encport->ifunit, exthdr,
 					sizeof(struct tmComResExtDevDescrHeader));
-				dprintk(DBGLVL_API, "  (becomes dev->enc[%d])\n", encport->nr);
+				dprintk(DBGLVL_API,
+					"  (becomes dev->enc[%d])\n",
+					encport->nr);
 			}
 			break;
 		case PVC_INFRARED_UNIT:
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/saa7164/saa7164-buffer.c linux-libre-2.6.38-gnu1/drivers/media/video/saa7164/saa7164-buffer.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/saa7164/saa7164-buffer.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/saa7164/saa7164-buffer.c	2011-03-14 21:20:32.000000000 -0400
@@ -24,46 +24,46 @@
 #include "saa7164.h"
 
 /* The PCI address space for buffer handling looks like this:
-
- +-u32 wide-------------+
- |                      +
- +-u64 wide------------------------------------+
- +                                             +
- +----------------------+
- | CurrentBufferPtr     + Pointer to current PCI buffer >-+
- +----------------------+                                 |
- | Unused               +                                 |
- +----------------------+                                 |
- | Pitch                + = 188 (bytes)                   |
- +----------------------+                                 |
- | PCI buffer size      + = pitch * number of lines (312) |
- +----------------------+                                 |
- |0| Buf0 Write Offset  +                                 |
- +----------------------+                                 v
- |1| Buf1 Write Offset  +                                 |
- +----------------------+                                 |
- |2| Buf2 Write Offset  +                                 |
- +----------------------+                                 |
- |3| Buf3 Write Offset  +                                 |
- +----------------------+                                 |
- ... More write offsets                                   |
- +---------------------------------------------+          |
- +0| set of ptrs to PCI pagetables             +          |
- +---------------------------------------------+          |
- +1| set of ptrs to PCI pagetables             + <--------+
- +---------------------------------------------+
- +2| set of ptrs to PCI pagetables             +
- +---------------------------------------------+
- +3| set of ptrs to PCI pagetables             + >--+
- +---------------------------------------------+    |
- ... More buffer pointers                           |  +----------------+
-						    +->| pt[0] TS data  |
-						    |  +----------------+
-						    |
-						    |  +----------------+
-						    +->| pt[1] TS data  |
-						    |  +----------------+
-						    | etc
+ *
+ * +-u32 wide-------------+
+ * |                      +
+ * +-u64 wide------------------------------------+
+ * +                                             +
+ * +----------------------+
+ * | CurrentBufferPtr     + Pointer to current PCI buffer >-+
+ * +----------------------+                                 |
+ * | Unused               +                                 |
+ * +----------------------+                                 |
+ * | Pitch                + = 188 (bytes)                   |
+ * +----------------------+                                 |
+ * | PCI buffer size      + = pitch * number of lines (312) |
+ * +----------------------+                                 |
+ * |0| Buf0 Write Offset  +                                 |
+ * +----------------------+                                 v
+ * |1| Buf1 Write Offset  +                                 |
+ * +----------------------+                                 |
+ * |2| Buf2 Write Offset  +                                 |
+ * +----------------------+                                 |
+ * |3| Buf3 Write Offset  +                                 |
+ * +----------------------+                                 |
+ * ... More write offsets                                   |
+ * +---------------------------------------------+          |
+ * +0| set of ptrs to PCI pagetables             +          |
+ * +---------------------------------------------+          |
+ * +1| set of ptrs to PCI pagetables             + <--------+
+ * +---------------------------------------------+
+ * +2| set of ptrs to PCI pagetables             +
+ * +---------------------------------------------+
+ * +3| set of ptrs to PCI pagetables             + >--+
+ * +---------------------------------------------+    |
+ * ... More buffer pointers                           |  +----------------+
+ *						    +->| pt[0] TS data  |
+ *						    |  +----------------+
+ *						    |
+ *						    |  +----------------+
+ *						    +->| pt[1] TS data  |
+ *						    |  +----------------+
+ *						    | etc
  */
 
 void saa7164_buffer_display(struct saa7164_buffer *buf)
@@ -283,7 +283,8 @@ int saa7164_buffer_cfg_port(struct saa71
 	return 0;
 }
 
-struct saa7164_user_buffer *saa7164_buffer_alloc_user(struct saa7164_dev *dev, u32 len)
+struct saa7164_user_buffer *saa7164_buffer_alloc_user(struct saa7164_dev *dev,
+	u32 len)
 {
 	struct saa7164_user_buffer *buf;
 
@@ -313,12 +314,9 @@ void saa7164_buffer_dealloc_user(struct
 	if (!buf)
 		return;
 
-	if (buf->data) {
-		kfree(buf->data);
-		buf->data = 0;
-	}
+	kfree(buf->data);
+	buf->data = 0;
 
-	if (buf)
-		kfree(buf);
+	kfree(buf);
 }
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/saa7164/saa7164-bus.c linux-libre-2.6.38-gnu1/drivers/media/video/saa7164/saa7164-bus.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/saa7164/saa7164-bus.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/saa7164/saa7164-bus.c	2011-03-14 21:20:32.000000000 -0400
@@ -43,7 +43,8 @@ int saa7164_bus_setup(struct saa7164_dev
 
 	b->m_dwSizeGetRing	= SAA_DEVICE_BUFFERBLOCKSIZE;
 
-	b->m_dwSetWritePos	= ((u32)dev->intfdesc.BARLocation) + (2 * sizeof(u64));
+	b->m_dwSetWritePos	= ((u32)dev->intfdesc.BARLocation) +
+		(2 * sizeof(u64));
 	b->m_dwSetReadPos	= b->m_dwSetWritePos + (1 * sizeof(u32));
 
 	b->m_dwGetWritePos	= b->m_dwSetWritePos + (2 * sizeof(u32));
@@ -105,7 +106,8 @@ void saa7164_bus_verify(struct saa7164_d
 	}
 }
 
-void saa7164_bus_dumpmsg(struct saa7164_dev *dev, struct tmComResInfo* m, void *buf)
+void saa7164_bus_dumpmsg(struct saa7164_dev *dev, struct tmComResInfo* m,
+	void *buf)
 {
 	dprintk(DBGLVL_BUS, "Dumping msg structure:\n");
 	dprintk(DBGLVL_BUS, " .id               = %d\n",   m->id);
@@ -129,7 +131,8 @@ void saa7164_bus_dumpmsg(struct saa7164_
  *  SAA_OK     The function executed successfully.
  *  < 0        One or more members are not initialized.
  */
-int saa7164_bus_set(struct saa7164_dev *dev, struct tmComResInfo* msg, void *buf)
+int saa7164_bus_set(struct saa7164_dev *dev, struct tmComResInfo* msg,
+	void *buf)
 {
 	struct tmComResBusInfo *bus = &dev->bus;
 	u32 bytes_to_write, free_write_space, timeout, curr_srp, curr_swp;
@@ -294,14 +297,15 @@ out:
 /*
  * Receive a command or a response from the bus. The implementation does not
  * know if it is a command or a response it simply dequeues the data,
- * depending on the bus information given in the struct tmComResBusInfo structure.
+ * depending on the bus information given in the struct tmComResBusInfo
+ * structure.
  *
  * Return Value:
  *  0          The function executed successfully.
  *  < 0        One or more members are not initialized.
  */
-int saa7164_bus_get(struct saa7164_dev *dev, struct tmComResInfo* msg, void *buf,
-	int peekonly)
+int saa7164_bus_get(struct saa7164_dev *dev, struct tmComResInfo* msg,
+	void *buf, int peekonly)
 {
 	struct tmComResBusInfo *bus = &dev->bus;
 	u32 bytes_to_read, write_distance, curr_grp, curr_gwp,
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/saa7164/saa7164-cards.c linux-libre-2.6.38-gnu1/drivers/media/video/saa7164/saa7164-cards.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/saa7164/saa7164-cards.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/saa7164/saa7164-cards.c	2011-03-14 21:20:32.000000000 -0400
@@ -482,7 +482,7 @@ void saa7164_gpio_setup(struct saa7164_d
 		saa7164_api_clear_gpiobit(dev, PCIEBRIDGE_UNITID, 2);
 		saa7164_api_clear_gpiobit(dev, PCIEBRIDGE_UNITID, 3);
 
-		msleep(10);
+		msleep(20);
 
 		saa7164_api_set_gpiobit(dev, PCIEBRIDGE_UNITID, 2);
 		saa7164_api_set_gpiobit(dev, PCIEBRIDGE_UNITID, 3);
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/saa7164/saa7164-cmd.c linux-libre-2.6.38-gnu1/drivers/media/video/saa7164/saa7164-cmd.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/saa7164/saa7164-cmd.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/saa7164/saa7164-cmd.c	2011-03-14 21:20:32.000000000 -0400
@@ -122,8 +122,8 @@ int saa7164_irq_dequeue(struct saa7164_d
 				return ret;
 		}
 
-		/* It's unlikely to have more than 4 or 5 pending messages, ensure we exit
-		 * at some point regardles.
+		/* It's unlikely to have more than 4 or 5 pending messages,
+		 * ensure we exit at some point regardless.
 		 */
 	} while (i++ < 32);
 
@@ -186,7 +186,8 @@ int saa7164_cmd_dequeue(struct saa7164_d
 	return SAA_OK;
 }
 
-int saa7164_cmd_set(struct saa7164_dev *dev, struct tmComResInfo* msg, void *buf)
+int saa7164_cmd_set(struct saa7164_dev *dev, struct tmComResInfo *msg,
+	void *buf)
 {
 	struct tmComResBusInfo *bus = &dev->bus;
 	u8 cmd_sent;
@@ -292,7 +293,8 @@ int saa7164_cmd_wait(struct saa7164_dev
 			 * We typically are signalled in < 50ms but it can
 			 * take MUCH longer.
 			 */
-			wait_event_timeout(*q, dev->cmds[seqno].signalled, (HZ * waitsecs));
+			wait_event_timeout(*q, dev->cmds[seqno].signalled,
+				(HZ * waitsecs));
 			r = time_before(jiffies, stamp + (HZ * waitsecs));
 			if (r)
 				ret = SAA_OK;
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/saa7164/saa7164-core.c linux-libre-2.6.38-gnu1/drivers/media/video/saa7164/saa7164-core.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/saa7164/saa7164-core.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/saa7164/saa7164-core.c	2011-03-14 21:20:32.000000000 -0400
@@ -40,12 +40,12 @@ MODULE_AUTHOR("Steven Toth <stoth@kernel
 MODULE_LICENSE("GPL");
 
 /*
-  1 Basic
-  2
-  4 i2c
-  8 api
- 16 cmd
- 32 bus
+ *  1 Basic
+ *  2
+ *  4 i2c
+ *  8 api
+ * 16 cmd
+ * 32 bus
  */
 
 unsigned int saa_debug;
@@ -82,7 +82,8 @@ MODULE_PARM_DESC(crc_checking, "enable c
 
 unsigned int guard_checking = 1;
 module_param(guard_checking, int, 0644);
-MODULE_PARM_DESC(guard_checking, "enable dma sanity checking for buffer overruns");
+MODULE_PARM_DESC(guard_checking,
+	"enable dma sanity checking for buffer overruns");
 
 static unsigned int saa7164_devcount;
 
@@ -123,7 +124,9 @@ static void saa7164_pack_verifier(struct
 		if ((*(p + i + 0) != 0x00) || (*(p + i + 1) != 0x00) ||
 			(*(p + i + 2) != 0x01) || (*(p + i + 3) != 0xBA)) {
 			printk(KERN_ERR "No pack at 0x%x\n", i);
-//			saa7164_dumphex16FF(buf->port->dev, (p + i), 32);
+#if 0
+			saa7164_dumphex16FF(buf->port->dev, (p + i), 32);
+#endif
 		}
 	}
 }
@@ -199,19 +202,16 @@ static void saa7164_histogram_reset(stru
 	strcpy(hg->name, name);
 
 	/* First 30ms x 1ms */
-	for (i = 0; i < 30; i++) {
+	for (i = 0; i < 30; i++)
 		hg->counter1[0 + i].val = i;
-	}
 
 	/* 30 - 200ms x 10ms  */
-	for (i = 0; i < 18; i++) {
+	for (i = 0; i < 18; i++)
 		hg->counter1[30 + i].val = 30 + (i * 10);
-	}
 
 	/* 200 - 2000ms x 100ms  */
-	for (i = 0; i < 15; i++) {
+	for (i = 0; i < 15; i++)
 		hg->counter1[48 + i].val = 200 + (i * 200);
-	}
 
 	/* Catch all massive value (2secs) */
 	hg->counter1[55].val = 2000;
@@ -315,7 +315,9 @@ static void saa7164_work_enchandler_help
 					(*(p + buf->actual_size + 0x13) != 0xff)) {
 						printk(KERN_ERR "%s() buf %p guard buffer breach\n",
 							__func__, buf);
-//						saa7164_dumphex16FF(dev, (p + buf->actual_size) - 32 , 64);
+#if 0
+						saa7164_dumphex16FF(dev, (p + buf->actual_size) - 32 , 64);
+#endif
 				}
 			}
 
@@ -653,8 +655,8 @@ static irqreturn_t saa7164_irq(int irq,
 		goto out;
 	}
 
-	/* Check that the hardware is accessable. If the status bytes are
-	 * 0xFF then the device is not accessable, the the IRQ belongs
+	/* Check that the hardware is accessible. If the status bytes are
+	 * 0xFF then the device is not accessible, the the IRQ belongs
 	 * to another driver.
 	 * 4 x u32 interrupt registers.
 	 */
@@ -961,9 +963,7 @@ static int saa7164_port_init(struct saa7
 
 		/* We need a deferred interrupt handler for cmd handling */
 		INIT_WORK(&port->workenc, saa7164_work_enchandler);
-	}
-	else
-	if ((portnr == SAA7164_PORT_VBI1) || (portnr == SAA7164_PORT_VBI2)) {
+	} else if ((portnr == SAA7164_PORT_VBI1) || (portnr == SAA7164_PORT_VBI2)) {
 		port->type = SAA7164_MPEG_VBI;
 
 		/* We need a deferred interrupt handler for cmd handling */
@@ -1001,7 +1001,7 @@ static int saa7164_dev_setup(struct saa7
 	atomic_inc(&dev->refcount);
 	dev->nr = saa7164_devcount++;
 
-	sprintf(dev->name, "saa7164[%d]", dev->nr);
+	snprintf(dev->name, sizeof(dev->name), "saa7164[%d]", dev->nr);
 
 	mutex_lock(&devlist);
 	list_add_tail(&dev->devlist, &saa7164_devlist);
@@ -1169,7 +1169,7 @@ static int saa7164_proc_open(struct inod
 	return single_open(filp, saa7164_proc_show, NULL);
 }
 
-static struct file_operations saa7164_proc_fops = {
+static const struct file_operations saa7164_proc_fops = {
 	.open		= saa7164_proc_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/saa7164/saa7164-encoder.c linux-libre-2.6.38-gnu1/drivers/media/video/saa7164/saa7164-encoder.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/saa7164/saa7164-encoder.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/saa7164/saa7164-encoder.c	2011-03-14 21:20:32.000000000 -0400
@@ -125,16 +125,22 @@ static int saa7164_encoder_buffers_alloc
 
 	dprintk(DBGLVL_ENC, "%s()\n", __func__);
 
-	if (port->encoder_params.stream_type == V4L2_MPEG_STREAM_TYPE_MPEG2_PS) {
-		dprintk(DBGLVL_ENC, "%s() type=V4L2_MPEG_STREAM_TYPE_MPEG2_PS\n", __func__);
+	if (port->encoder_params.stream_type ==
+		V4L2_MPEG_STREAM_TYPE_MPEG2_PS) {
+		dprintk(DBGLVL_ENC,
+			"%s() type=V4L2_MPEG_STREAM_TYPE_MPEG2_PS\n",
+			__func__);
 		params->samplesperline = 128;
 		params->numberoflines = 256;
 		params->pitch = 128;
 		params->numpagetables = 2 +
 			((SAA7164_PS_NUMBER_OF_LINES * 128) / PAGE_SIZE);
 	} else
-	if (port->encoder_params.stream_type == V4L2_MPEG_STREAM_TYPE_MPEG2_TS) {
-		dprintk(DBGLVL_ENC, "%s() type=V4L2_MPEG_STREAM_TYPE_MPEG2_TS\n", __func__);
+	if (port->encoder_params.stream_type ==
+		V4L2_MPEG_STREAM_TYPE_MPEG2_TS) {
+		dprintk(DBGLVL_ENC,
+			"%s() type=V4L2_MPEG_STREAM_TYPE_MPEG2_TS\n",
+			__func__);
 		params->samplesperline = 188;
 		params->numberoflines = 312;
 		params->pitch = 188;
@@ -826,7 +832,8 @@ static int fill_queryctrl(struct saa7164
 		return v4l2_ctrl_query_fill(c, 1, 255, 1, 15);
 	case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
 		return v4l2_ctrl_query_fill(c,
-			V4L2_MPEG_VIDEO_BITRATE_MODE_VBR, V4L2_MPEG_VIDEO_BITRATE_MODE_CBR,
+			V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
+			V4L2_MPEG_VIDEO_BITRATE_MODE_CBR,
 			1, V4L2_MPEG_VIDEO_BITRATE_MODE_VBR);
 	case V4L2_CID_MPEG_VIDEO_B_FRAMES:
 		return v4l2_ctrl_query_fill(c,
@@ -1113,7 +1120,9 @@ struct saa7164_user_buffer *saa7164_enc_
 		if (crc_checking) {
 			crc = crc32(0, ubuf->data, ubuf->actual_size);
 			if (crc != ubuf->crc) {
-				printk(KERN_ERR "%s() ubuf %p crc became invalid, was 0x%x became 0x%x\n", __func__,
+				printk(KERN_ERR
+		"%s() ubuf %p crc became invalid, was 0x%x became 0x%x\n",
+					__func__,
 					ubuf, ubuf->crc, crc);
 			}
 		}
@@ -1201,9 +1210,8 @@ static ssize_t fops_read(struct file *fi
 		buffer += cnt;
 		ret += cnt;
 
-		if (ubuf->pos > ubuf->actual_size) {
+		if (ubuf->pos > ubuf->actual_size)
 			printk(KERN_ERR "read() pos > actual, huh?\n");
-		}
 
 		if (ubuf->pos == ubuf->actual_size) {
 
@@ -1227,16 +1235,16 @@ static ssize_t fops_read(struct file *fi
 		}
 	}
 err:
-	if (!ret && !ubuf) {
+	if (!ret && !ubuf)
 		ret = -EAGAIN;
-	}
 
 	return ret;
 }
 
 static unsigned int fops_poll(struct file *file, poll_table *wait)
 {
-	struct saa7164_encoder_fh *fh = (struct saa7164_encoder_fh *)file->private_data;
+	struct saa7164_encoder_fh *fh =
+		(struct saa7164_encoder_fh *)file->private_data;
 	struct saa7164_port *port = fh->port;
 	struct saa7164_user_buffer *ubuf;
 	unsigned int mask = 0;
@@ -1249,9 +1257,8 @@ static unsigned int fops_poll(struct fil
 	saa7164_histogram_update(&port->poll_interval,
 		port->last_poll_msecs_diff);
 
-	if (!video_is_registered(port->v4l_device)) {
+	if (!video_is_registered(port->v4l_device))
 		return -EIO;
-	}
 
 	if (atomic_cmpxchg(&fh->v4l_reading, 0, 1) == 0) {
 		if (atomic_inc_return(&port->v4l_reader_count) == 1) {
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/saa7164/saa7164-fw.c linux-libre-2.6.38-gnu1/drivers/media/video/saa7164/saa7164-fw.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/saa7164/saa7164-fw.c	2013-05-03 03:57:21.000000000 -0400
+++ linux-libre-2.6.38-gnu1/drivers/media/video/saa7164/saa7164-fw.c	2013-05-03 01:57:10.000000000 -0400
@@ -178,7 +178,7 @@ int saa7164_downloadimage(struct saa7164
 			goto out;
 		}
 
-		msleep(10);
+		msleep(10); /* Checkpatch throws a < 20ms warning */
 		if (timeout++ > 60)
 			break;
 	}
@@ -235,7 +235,7 @@ int saa7164_downloadfirmware(struct saa7
 		while (err_flags != SAA_DEVICE_IMAGE_BOOTING) {
 			dprintk(DBGLVL_FW, "%s() err_flags = %x\n",
 				__func__, err_flags);
-			msleep(10);
+			msleep(10); /* Checkpatch throws a < 20ms warning */
 
 			if (err_flags & SAA_DEVICE_IMAGE_CORRUPT) {
 				printk(KERN_ERR "%s() firmware corrupt\n",
@@ -294,7 +294,7 @@ int saa7164_downloadfirmware(struct saa7
 			while (err_flags != SAA_DEVICE_IMAGE_BOOTING) {
 				dprintk(DBGLVL_FW, "%s() err_flags2 = %x\n",
 					__func__, err_flags);
-				msleep(10);
+				msleep(10); /* Checkpatch throws a < 20ms warning */
 
 				if (err_flags & SAA_DEVICE_IMAGE_CORRUPT) {
 					printk(KERN_ERR
@@ -365,7 +365,7 @@ int saa7164_downloadfirmware(struct saa7
 
 			first_timeout = SAA_DEVICE_TIMEOUT;
 			while (first_timeout) {
-				msleep(10);
+				msleep(10); /* Checkpatch throws a < 20ms warning */
 
 				version =
 					saa7164_getcurrentfirmwareversion(dev);
@@ -608,8 +608,6 @@ int saa7164_downloadfirmware(struct saa7
 	ret = 0;
 
 out:
-	if (fw)
-		release_firmware(fw);
-
+	release_firmware(fw);
 	return ret;
 }
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/saa7164/saa7164.h linux-libre-2.6.38-gnu1/drivers/media/video/saa7164/saa7164.h
--- linux-libre-2.6.37-gnu1/drivers/media/video/saa7164/saa7164.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/saa7164/saa7164.h	2011-03-14 21:20:32.000000000 -0400
@@ -113,7 +113,8 @@
 #define DBGLVL_THR 4096
 #define DBGLVL_CPU 8192
 
-#define SAA7164_NORMS (V4L2_STD_NTSC_M |  V4L2_STD_NTSC_M_JP |  V4L2_STD_NTSC_443)
+#define SAA7164_NORMS \
+	(V4L2_STD_NTSC_M |  V4L2_STD_NTSC_M_JP |  V4L2_STD_NTSC_443)
 
 enum port_t {
 	SAA7164_MPEG_UNDEFINED = 0,
@@ -182,15 +183,11 @@ struct saa7164_subid {
 
 struct saa7164_encoder_fh {
 	struct saa7164_port *port;
-//	u32 freq;
-//	u32 tuner_type;
 	atomic_t v4l_reading;
 };
 
 struct saa7164_vbi_fh {
 	struct saa7164_port *port;
-//	u32 freq;
-//	u32 tuner_type;
 	atomic_t v4l_reading;
 };
 
@@ -265,8 +262,6 @@ struct saa7164_ctrl {
 struct saa7164_tvnorm {
 	char		*name;
 	v4l2_std_id	id;
-//	u32		cxiformat;
-//	u32		cxoformat;
 };
 
 struct saa7164_encoder_params {
@@ -447,7 +442,7 @@ struct saa7164_dev {
 	int	nr;
 	int	hwrevision;
 	u32	board;
-	char	name[32];
+	char	name[16];
 
 	/* firmware status */
 	struct saa7164_fw_status	fw_status;
@@ -510,7 +505,8 @@ extern void saa7164_call_i2c_clients(str
 /* saa7164-bus.c                                               */
 int saa7164_bus_setup(struct saa7164_dev *dev);
 void saa7164_bus_dump(struct saa7164_dev *dev);
-int saa7164_bus_set(struct saa7164_dev *dev, struct tmComResInfo* msg, void *buf);
+int saa7164_bus_set(struct saa7164_dev *dev, struct tmComResInfo* msg,
+	void *buf);
 int saa7164_bus_get(struct saa7164_dev *dev, struct tmComResInfo* msg,
 	void *buf, int peekonly);
 
@@ -552,7 +548,8 @@ int saa7164_api_get_videomux(struct saa7
 int saa7164_api_set_vbi_format(struct saa7164_port *port);
 int saa7164_api_set_debug(struct saa7164_dev *dev, u8 level);
 int saa7164_api_collect_debug(struct saa7164_dev *dev);
-int saa7164_api_get_load_info(struct saa7164_dev *dev, struct tmFwInfoStruct *i);
+int saa7164_api_get_load_info(struct saa7164_dev *dev,
+	struct tmFwInfoStruct *i);
 
 /* ----------------------------------------------------------- */
 /* saa7164-cards.c                                             */
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/saa7164/saa7164-i2c.c linux-libre-2.6.38-gnu1/drivers/media/video/saa7164/saa7164-i2c.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/saa7164/saa7164-i2c.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/saa7164/saa7164-i2c.c	2011-03-14 21:20:32.000000000 -0400
@@ -23,7 +23,7 @@
 #include <linux/moduleparam.h>
 #include <linux/init.h>
 #include <linux/delay.h>
-#include <asm/io.h>
+#include <linux/io.h>
 
 #include "saa7164.h"
 
@@ -65,7 +65,7 @@ static int i2c_xfer(struct i2c_adapter *
 	}
 	return num;
 
- err:
+err:
 	return retval;
 }
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/saa7164/saa7164-vbi.c linux-libre-2.6.38-gnu1/drivers/media/video/saa7164/saa7164-vbi.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/saa7164/saa7164-vbi.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/saa7164/saa7164-vbi.c	2011-03-14 21:20:32.000000000 -0400
@@ -51,11 +51,15 @@ static void saa7164_vbi_configure(struct
 	/* Set up the DIF (enable it) for analog mode by default */
 	saa7164_api_initialize_dif(port);
 
-//	/* Configure the correct video standard */
-//	saa7164_api_configure_dif(port, port->encodernorm.id);
+	/* Configure the correct video standard */
+#if 0
+	saa7164_api_configure_dif(port, port->encodernorm.id);
+#endif
 
-//	/* Ensure the audio decoder is correct configured */
-//	saa7164_api_set_audio_std(port);
+#if 0
+	/* Ensure the audio decoder is correct configured */
+	saa7164_api_set_audio_std(port);
+#endif
 	dprintk(DBGLVL_VBI, "%s() ends\n", __func__);
 }
 
@@ -919,8 +923,10 @@ static int saa7164_vbi_start_streaming(s
 	saa7164_vbi_buffers_alloc(port);
 
 	/* Configure the encoder with any cache values */
-//	saa7164_api_set_encoder(port);
-//	saa7164_api_get_encoder(port);
+#if 0
+	saa7164_api_set_encoder(port);
+	saa7164_api_get_encoder(port);
+#endif
 
 	/* Place the empty buffers on the hardware */
 	saa7164_buffer_cfg_port(port);
@@ -1060,7 +1066,8 @@ struct saa7164_user_buffer *saa7164_vbi_
 		if (crc_checking) {
 			crc = crc32(0, ubuf->data, ubuf->actual_size);
 			if (crc != ubuf->crc) {
-				printk(KERN_ERR "%s() ubuf %p crc became invalid, was 0x%x became 0x%x\n", __func__,
+				printk(KERN_ERR "%s() ubuf %p crc became invalid, was 0x%x became 0x%x\n",
+					__func__,
 					ubuf, ubuf->crc, crc);
 			}
 		}
@@ -1148,9 +1155,8 @@ static ssize_t fops_read(struct file *fi
 		buffer += cnt;
 		ret += cnt;
 
-		if (ubuf->pos > ubuf->actual_size) {
+		if (ubuf->pos > ubuf->actual_size)
 			printk(KERN_ERR "read() pos > actual, huh?\n");
-		}
 
 		if (ubuf->pos == ubuf->actual_size) {
 
@@ -1197,9 +1203,8 @@ static unsigned int fops_poll(struct fil
 	saa7164_histogram_update(&port->poll_interval,
 		port->last_poll_msecs_diff);
 
-	if (!video_is_registered(port->v4l_device)) {
+	if (!video_is_registered(port->v4l_device))
 		return -EIO;
-	}
 
 	if (atomic_cmpxchg(&fh->v4l_reading, 0, 1) == 0) {
 		if (atomic_inc_return(&port->v4l_reader_count) == 1) {
@@ -1257,10 +1262,14 @@ static const struct v4l2_ioctl_ops vbi_i
 	.vidioc_try_ext_ctrls	 = vidioc_try_ext_ctrls,
 	.vidioc_log_status	 = vidioc_log_status,
 	.vidioc_queryctrl	 = vidioc_queryctrl,
-//	.vidioc_g_chip_ident	 = saa7164_g_chip_ident,
+#if 0
+	.vidioc_g_chip_ident	 = saa7164_g_chip_ident,
+#endif
 #ifdef CONFIG_VIDEO_ADV_DEBUG
-//	.vidioc_g_register	 = saa7164_g_register,
-//	.vidioc_s_register	 = saa7164_s_register,
+#if 0
+	.vidioc_g_register	 = saa7164_g_register,
+	.vidioc_s_register	 = saa7164_s_register,
+#endif
 #endif
 	.vidioc_g_fmt_vbi_cap	 = saa7164_vbi_fmt,
 	.vidioc_try_fmt_vbi_cap	 = saa7164_vbi_fmt,
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/se401.c linux-libre-2.6.38-gnu1/drivers/media/video/se401.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/se401.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/se401.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1492 +0,0 @@
-/*
- * Endpoints (formerly known as AOX) se401 USB Camera Driver
- *
- * Copyright (c) 2000 Jeroen B. Vreeken (pe1rxq@amsat.org)
- *
- * Still somewhat based on the Linux ov511 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.
- *
- *
- * Thanks to Endpoints Inc. (www.endpoints.com) for making documentation on
- * their chipset available and supporting me while writing this driver.
- * 	- Jeroen Vreeken
- */
-
-static const char version[] = "0.24";
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/vmalloc.h>
-#include <linux/slab.h>
-#include <linux/pagemap.h>
-#include <linux/usb.h>
-#include "se401.h"
-
-static int flickerless;
-static int video_nr = -1;
-
-static struct usb_device_id device_table[] = {
-	{ USB_DEVICE(0x03e8, 0x0004) },/* Endpoints/Aox SE401 */
-	{ USB_DEVICE(0x0471, 0x030b) },/* Philips PCVC665K */
-	{ USB_DEVICE(0x047d, 0x5001) },/* Kensington 67014 */
-	{ USB_DEVICE(0x047d, 0x5002) },/* Kensington 6701(5/7) */
-	{ USB_DEVICE(0x047d, 0x5003) },/* Kensington 67016 */
-	{ }
-};
-
-MODULE_DEVICE_TABLE(usb, device_table);
-
-MODULE_AUTHOR("Jeroen Vreeken <pe1rxq@amsat.org>");
-MODULE_DESCRIPTION("SE401 USB Camera Driver");
-MODULE_LICENSE("GPL");
-module_param(flickerless, int, 0);
-MODULE_PARM_DESC(flickerless,
-		"Net frequency to adjust exposure time to (0/50/60)");
-module_param(video_nr, int, 0);
-
-static struct usb_driver se401_driver;
-
-
-/**********************************************************************
- *
- * Memory management
- *
- **********************************************************************/
-static void *rvmalloc(unsigned long size)
-{
-	void *mem;
-	unsigned long adr;
-
-	size = PAGE_ALIGN(size);
-	mem = vmalloc_32(size);
-	if (!mem)
-		return NULL;
-
-	memset(mem, 0, size); /* Clear the ram out, no junk to the user */
-	adr = (unsigned long) mem;
-	while (size > 0) {
-		SetPageReserved(vmalloc_to_page((void *)adr));
-		adr +=  PAGE_SIZE;
-		size -=  PAGE_SIZE;
-	}
-
-	return mem;
-}
-
-static void rvfree(void *mem, unsigned long size)
-{
-	unsigned long adr;
-
-	if (!mem)
-		return;
-
-	adr = (unsigned long) mem;
-	while ((long) size > 0) {
-		ClearPageReserved(vmalloc_to_page((void *)adr));
-		adr +=  PAGE_SIZE;
-		size -=  PAGE_SIZE;
-	}
-	vfree(mem);
-}
-
-
-
-/****************************************************************************
- *
- * se401 register read/write functions
- *
- ***************************************************************************/
-
-static int se401_sndctrl(int set, struct usb_se401 *se401, unsigned short req,
-			 unsigned short value, unsigned char *cp, int size)
-{
-	return usb_control_msg(
-		se401->dev,
-		set ? usb_sndctrlpipe(se401->dev, 0) : usb_rcvctrlpipe(se401->dev, 0),
-		req,
-		(set ? USB_DIR_OUT : USB_DIR_IN) | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-		value,
-		0,
-		cp,
-		size,
-		1000
-	);
-}
-
-static int se401_set_feature(struct usb_se401 *se401, unsigned short selector,
-			     unsigned short param)
-{
-	/* specs say that the selector (address) should go in the value field
-	   and the param in index, but in the logs of the windows driver they do
-	   this the other way around...
-	 */
-	return usb_control_msg(
-		se401->dev,
-		usb_sndctrlpipe(se401->dev, 0),
-		SE401_REQ_SET_EXT_FEATURE,
-		USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-		param,
-		selector,
-		NULL,
-		0,
-		1000
-	);
-}
-
-static unsigned short se401_get_feature(struct usb_se401 *se401,
-					unsigned short selector)
-{
-	/* For 'set' the selecetor should be in index, not sure if the spec is
-	   wrong here to....
-	 */
-	unsigned char cp[2];
-	usb_control_msg(
-		se401->dev,
-		usb_rcvctrlpipe(se401->dev, 0),
-		SE401_REQ_GET_EXT_FEATURE,
-		USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-		0,
-		selector,
-		cp,
-		2,
-		1000
-	);
-	return cp[0]+cp[1]*256;
-}
-
-/****************************************************************************
- *
- * Camera control
- *
- ***************************************************************************/
-
-
-static int se401_send_pict(struct usb_se401 *se401)
-{
-	/* integration time low */
-	se401_set_feature(se401, HV7131_REG_TITL, se401->expose_l);
-	/* integration time mid */
-	se401_set_feature(se401, HV7131_REG_TITM, se401->expose_m);
-	/* integration time mid */
-	se401_set_feature(se401, HV7131_REG_TITU, se401->expose_h);
-	/* reset level value */
-	se401_set_feature(se401, HV7131_REG_ARLV, se401->resetlevel);
-	/* red color gain */
-	se401_set_feature(se401, HV7131_REG_ARCG, se401->rgain);
-	/* green color gain */
-	se401_set_feature(se401, HV7131_REG_AGCG, se401->ggain);
-	/* blue color gain */
-	se401_set_feature(se401, HV7131_REG_ABCG, se401->bgain);
-
-	return 0;
-}
-
-static void se401_set_exposure(struct usb_se401 *se401, int brightness)
-{
-	int integration = brightness << 5;
-
-	if (flickerless == 50)
-		integration = integration-integration % 106667;
-	if (flickerless == 60)
-		integration = integration-integration % 88889;
-	se401->brightness = integration >> 5;
-	se401->expose_h = (integration >> 16) & 0xff;
-	se401->expose_m = (integration >> 8) & 0xff;
-	se401->expose_l = integration & 0xff;
-}
-
-static int se401_get_pict(struct usb_se401 *se401, struct video_picture *p)
-{
-	p->brightness = se401->brightness;
-	if (se401->enhance)
-		p->whiteness = 32768;
-	else
-		p->whiteness = 0;
-
-	p->colour = 65535;
-	p->contrast = 65535;
-	p->hue = se401->rgain << 10;
-	p->palette = se401->palette;
-	p->depth = 3; /* rgb24 */
-	return 0;
-}
-
-
-static int se401_set_pict(struct usb_se401 *se401, struct video_picture *p)
-{
-	if (p->palette != VIDEO_PALETTE_RGB24)
-		return 1;
-	se401->palette = p->palette;
-	if (p->hue != se401->hue) {
-		se401->rgain =  p->hue >> 10;
-		se401->bgain =  0x40-(p->hue >> 10);
-		se401->hue = p->hue;
-	}
-	if (p->brightness != se401->brightness)
-		se401_set_exposure(se401, p->brightness);
-
-	if (p->whiteness >= 32768)
-		se401->enhance = 1;
-	else
-		se401->enhance = 0;
-	se401_send_pict(se401);
-	se401_send_pict(se401);
-	return 0;
-}
-
-/*
-	Hyundai have some really nice docs about this and other sensor related
-	stuff on their homepage: www.hei.co.kr
-*/
-static void se401_auto_resetlevel(struct usb_se401 *se401)
-{
-	unsigned int ahrc, alrc;
-	int oldreset = se401->resetlevel;
-
-	/* For some reason this normally read-only register doesn't get reset
-	   to zero after reading them just once...
-	 */
-	se401_get_feature(se401, HV7131_REG_HIREFNOH);
-	se401_get_feature(se401, HV7131_REG_HIREFNOL);
-	se401_get_feature(se401, HV7131_REG_LOREFNOH);
-	se401_get_feature(se401, HV7131_REG_LOREFNOL);
-	ahrc = 256*se401_get_feature(se401, HV7131_REG_HIREFNOH) +
-	    se401_get_feature(se401, HV7131_REG_HIREFNOL);
-	alrc = 256*se401_get_feature(se401, HV7131_REG_LOREFNOH) +
-	    se401_get_feature(se401, HV7131_REG_LOREFNOL);
-
-	/* Not an exact science, but it seems to work pretty well... */
-	if (alrc > 10) {
-		while (alrc >= 10 && se401->resetlevel < 63) {
-			se401->resetlevel++;
-			alrc /= 2;
-		}
-	} else if (ahrc > 20) {
-		while (ahrc >= 20 && se401->resetlevel > 0) {
-			se401->resetlevel--;
-			ahrc /= 2;
-		}
-	}
-	if (se401->resetlevel != oldreset)
-		se401_set_feature(se401, HV7131_REG_ARLV, se401->resetlevel);
-
-	return;
-}
-
-/* irq handler for snapshot button */
-static void se401_button_irq(struct urb *urb)
-{
-	struct usb_se401 *se401 = urb->context;
-	int status;
-
-	if (!se401->dev) {
-		dev_info(&urb->dev->dev, "device vapourished\n");
-		return;
-	}
-
-	switch (urb->status) {
-	case 0:
-		/* success */
-		break;
-	case -ECONNRESET:
-	case -ENOENT:
-	case -ESHUTDOWN:
-		/* this urb is terminated, clean up */
-		dbg("%s - urb shutting down with status: %d",
-							__func__, urb->status);
-		return;
-	default:
-		dbg("%s - nonzero urb status received: %d",
-							__func__, urb->status);
-		goto exit;
-	}
-
-	if (urb->actual_length  >= 2)
-		if (se401->button)
-			se401->buttonpressed = 1;
-exit:
-	status = usb_submit_urb(urb, GFP_ATOMIC);
-	if (status)
-		err("%s - usb_submit_urb failed with result %d",
-		     __func__, status);
-}
-
-static void se401_video_irq(struct urb *urb)
-{
-	struct usb_se401 *se401 = urb->context;
-	int length = urb->actual_length;
-
-	/* ohoh... */
-	if (!se401->streaming)
-		return;
-
-	if (!se401->dev) {
-		dev_info(&urb->dev->dev, "device vapourished\n");
-		return;
-	}
-
-	/* 0 sized packets happen if we are to fast, but sometimes the camera
-	   keeps sending them forever...
-	 */
-	if (length && !urb->status) {
-		se401->nullpackets = 0;
-		switch (se401->scratch[se401->scratch_next].state) {
-		case BUFFER_READY:
-		case BUFFER_BUSY:
-			se401->dropped++;
-			break;
-		case BUFFER_UNUSED:
-			memcpy(se401->scratch[se401->scratch_next].data,
-				(unsigned char *)urb->transfer_buffer, length);
-			se401->scratch[se401->scratch_next].state
-							= BUFFER_READY;
-			se401->scratch[se401->scratch_next].offset
-							= se401->bayeroffset;
-			se401->scratch[se401->scratch_next].length = length;
-			if (waitqueue_active(&se401->wq))
-				wake_up_interruptible(&se401->wq);
-			se401->scratch_overflow = 0;
-			se401->scratch_next++;
-			if (se401->scratch_next >= SE401_NUMSCRATCH)
-				se401->scratch_next = 0;
-			break;
-		}
-		se401->bayeroffset += length;
-		if (se401->bayeroffset >= se401->cheight * se401->cwidth)
-			se401->bayeroffset = 0;
-	} else {
-		se401->nullpackets++;
-		if (se401->nullpackets > SE401_MAX_NULLPACKETS)
-			if (waitqueue_active(&se401->wq))
-				wake_up_interruptible(&se401->wq);
-	}
-
-	/* Resubmit urb for new data */
-	urb->status = 0;
-	urb->dev = se401->dev;
-	if (usb_submit_urb(urb, GFP_KERNEL))
-		dev_info(&urb->dev->dev, "urb burned down\n");
-	return;
-}
-
-static void se401_send_size(struct usb_se401 *se401, int width, int height)
-{
-	int i = 0;
-	int mode = 0x03; /* No compression */
-	int sendheight = height;
-	int sendwidth = width;
-
-	/* JangGu compression can only be used with the camera supported sizes,
-	   but bayer seems to work with any size that fits on the sensor.
-	   We check if we can use compression with the current size with either
-	   4 or 16 times subcapturing, if not we use uncompressed bayer data
-	   but this will result in cutouts of the maximum size....
-	 */
-	while (i < se401->sizes && !(se401->width[i] == width &&
-						se401->height[i] == height))
-		i++;
-	while (i < se401->sizes) {
-		if (se401->width[i] == width * 2 &&
-				se401->height[i] == height * 2) {
-			sendheight = se401->height[i];
-			sendwidth = se401->width[i];
-			mode = 0x40;
-		}
-		if (se401->width[i] == width * 4 &&
-				se401->height[i] == height * 4) {
-			sendheight = se401->height[i];
-			sendwidth = se401->width[i];
-			mode = 0x42;
-		}
-		i++;
-	}
-
-	se401_sndctrl(1, se401, SE401_REQ_SET_WIDTH, sendwidth, NULL, 0);
-	se401_sndctrl(1, se401, SE401_REQ_SET_HEIGHT, sendheight, NULL, 0);
-	se401_set_feature(se401, SE401_OPERATINGMODE, mode);
-
-	if (mode == 0x03)
-		se401->format = FMT_BAYER;
-	else
-		se401->format = FMT_JANGGU;
-}
-
-/*
-	In this function se401_send_pict is called several times,
-	for some reason (depending on the state of the sensor and the phase of
-	the moon :) doing this only in either place doesn't always work...
-*/
-static int se401_start_stream(struct usb_se401 *se401)
-{
-	struct urb *urb;
-	int err = 0, i;
-	se401->streaming = 1;
-
-	se401_sndctrl(1, se401, SE401_REQ_CAMERA_POWER, 1, NULL, 0);
-	se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 1, NULL, 0);
-
-	/* Set picture settings */
-	/* windowed + pix intg */
-	se401_set_feature(se401, HV7131_REG_MODE_B, 0x05);
-	se401_send_pict(se401);
-
-	se401_send_size(se401, se401->cwidth, se401->cheight);
-
-	se401_sndctrl(1, se401, SE401_REQ_START_CONTINUOUS_CAPTURE,
-								0, NULL, 0);
-
-	/* Do some memory allocation */
-	for (i = 0; i < SE401_NUMFRAMES; i++) {
-		se401->frame[i].data = se401->fbuf + i * se401->maxframesize;
-		se401->frame[i].curpix = 0;
-	}
-	for (i = 0; i < SE401_NUMSBUF; i++) {
-		se401->sbuf[i].data = kmalloc(SE401_PACKETSIZE, GFP_KERNEL);
-		if (!se401->sbuf[i].data) {
-			for (i = i - 1; i >= 0; i--) {
-				kfree(se401->sbuf[i].data);
-				se401->sbuf[i].data = NULL;
-			}
-			return -ENOMEM;
-		}
-	}
-
-	se401->bayeroffset = 0;
-	se401->scratch_next = 0;
-	se401->scratch_use = 0;
-	se401->scratch_overflow = 0;
-	for (i = 0; i < SE401_NUMSCRATCH; i++) {
-		se401->scratch[i].data = kmalloc(SE401_PACKETSIZE, GFP_KERNEL);
-		if (!se401->scratch[i].data) {
-			for (i = i - 1; i >= 0; i--) {
-				kfree(se401->scratch[i].data);
-				se401->scratch[i].data = NULL;
-			}
-			goto nomem_sbuf;
-		}
-		se401->scratch[i].state = BUFFER_UNUSED;
-	}
-
-	for (i = 0; i < SE401_NUMSBUF; i++) {
-		urb = usb_alloc_urb(0, GFP_KERNEL);
-		if (!urb) {
-			for (i = i - 1; i >= 0; i--) {
-				usb_kill_urb(se401->urb[i]);
-				usb_free_urb(se401->urb[i]);
-				se401->urb[i] = NULL;
-			}
-			goto nomem_scratch;
-		}
-
-		usb_fill_bulk_urb(urb, se401->dev,
-			usb_rcvbulkpipe(se401->dev, SE401_VIDEO_ENDPOINT),
-			se401->sbuf[i].data, SE401_PACKETSIZE,
-			se401_video_irq,
-			se401);
-
-		se401->urb[i] = urb;
-
-		err = usb_submit_urb(se401->urb[i], GFP_KERNEL);
-		if (err)
-			err("urb burned down");
-	}
-
-	se401->framecount = 0;
-
-	return 0;
-
- nomem_scratch:
-	for (i = 0; i < SE401_NUMSCRATCH; i++) {
-		kfree(se401->scratch[i].data);
-		se401->scratch[i].data = NULL;
-	}
- nomem_sbuf:
-	for (i = 0; i < SE401_NUMSBUF; i++) {
-		kfree(se401->sbuf[i].data);
-		se401->sbuf[i].data = NULL;
-	}
-	return -ENOMEM;
-}
-
-static int se401_stop_stream(struct usb_se401 *se401)
-{
-	int i;
-
-	if (!se401->streaming || !se401->dev)
-		return 1;
-
-	se401->streaming = 0;
-
-	se401_sndctrl(1, se401, SE401_REQ_STOP_CONTINUOUS_CAPTURE, 0, NULL, 0);
-
-	se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 0, NULL, 0);
-	se401_sndctrl(1, se401, SE401_REQ_CAMERA_POWER, 0, NULL, 0);
-
-	for (i = 0; i < SE401_NUMSBUF; i++)
-		if (se401->urb[i]) {
-			usb_kill_urb(se401->urb[i]);
-			usb_free_urb(se401->urb[i]);
-			se401->urb[i] = NULL;
-			kfree(se401->sbuf[i].data);
-		}
-	for (i = 0; i < SE401_NUMSCRATCH; i++) {
-		kfree(se401->scratch[i].data);
-		se401->scratch[i].data = NULL;
-	}
-
-	return 0;
-}
-
-static int se401_set_size(struct usb_se401 *se401, int width, int height)
-{
-	int wasstreaming = se401->streaming;
-	/* Check to see if we need to change */
-	if (se401->cwidth == width && se401->cheight == height)
-		return 0;
-
-	/* Check for a valid mode */
-	if (!width || !height)
-		return 1;
-	if ((width & 1) || (height & 1))
-		return 1;
-	if (width > se401->width[se401->sizes-1])
-		return 1;
-	if (height > se401->height[se401->sizes-1])
-		return 1;
-
-	/* Stop a current stream and start it again at the new size */
-	if (wasstreaming)
-		se401_stop_stream(se401);
-	se401->cwidth = width;
-	se401->cheight = height;
-	if (wasstreaming)
-		se401_start_stream(se401);
-	return 0;
-}
-
-
-/****************************************************************************
- *
- * Video Decoding
- *
- ***************************************************************************/
-
-/*
-	This shouldn't really be done in a v4l driver....
-	But it does make the image look a lot more usable.
-	Basically it lifts the dark pixels more than the light pixels.
-*/
-static inline void enhance_picture(unsigned char *frame, int len)
-{
-	while (len--) {
-		*frame = (((*frame^255)*(*frame^255))/255)^255;
-		frame++;
-	}
-}
-
-static inline void decode_JangGu_integrate(struct usb_se401 *se401, int data)
-{
-	struct se401_frame *frame = &se401->frame[se401->curframe];
-	int linelength = se401->cwidth * 3;
-
-	if (frame->curlinepix >= linelength) {
-		frame->curlinepix = 0;
-		frame->curline += linelength;
-	}
-
-	/* First three are absolute, all others relative.
-	 * Format is rgb from right to left (mirrorred image),
-	 * we flip it to get bgr from left to right. */
-	if (frame->curlinepix < 3)
-		*(frame->curline-frame->curlinepix) = 1 + data * 4;
-	else
-		*(frame->curline-frame->curlinepix) =
-		    *(frame->curline-frame->curlinepix + 3) + data * 4;
-	frame->curlinepix++;
-}
-
-static inline void decode_JangGu_vlc(struct usb_se401 *se401,
-			unsigned char *data, int bit_exp, int packetlength)
-{
-	int pos = 0;
-	int vlc_cod = 0;
-	int vlc_size = 0;
-	int vlc_data = 0;
-	int bit_cur;
-	int bit;
-	data += 4;
-	while (pos < packetlength) {
-		bit_cur = 8;
-		while (bit_cur && bit_exp) {
-			bit = ((*data) >> (bit_cur-1))&1;
-			if (!vlc_cod) {
-				if (bit) {
-					vlc_size++;
-				} else {
-					if (!vlc_size)
-						decode_JangGu_integrate(se401, 0);
-					else {
-						vlc_cod = 2;
-						vlc_data = 0;
-					}
-				}
-			} else {
-				if (vlc_cod == 2) {
-					if (!bit)
-						vlc_data =  -(1 << vlc_size) + 1;
-					vlc_cod--;
-				}
-				vlc_size--;
-				vlc_data += bit << vlc_size;
-				if (!vlc_size) {
-					decode_JangGu_integrate(se401, vlc_data);
-					vlc_cod = 0;
-				}
-			}
-			bit_cur--;
-			bit_exp--;
-		}
-		pos++;
-		data++;
-	}
-}
-
-static inline void decode_JangGu(struct usb_se401 *se401,
-						struct se401_scratch *buffer)
-{
-	unsigned char *data = buffer->data;
-	int len = buffer->length;
-	int bit_exp = 0, pix_exp = 0, frameinfo = 0, packetlength = 0, size;
-	int datapos = 0;
-
-	/* New image? */
-	if (!se401->frame[se401->curframe].curpix) {
-		se401->frame[se401->curframe].curlinepix = 0;
-		se401->frame[se401->curframe].curline =
-		    se401->frame[se401->curframe].data+
-		    se401->cwidth * 3 - 1;
-		if (se401->frame[se401->curframe].grabstate == FRAME_READY)
-			se401->frame[se401->curframe].grabstate = FRAME_GRABBING;
-		se401->vlcdatapos = 0;
-	}
-	while (datapos < len) {
-		size = 1024 - se401->vlcdatapos;
-		if (size+datapos > len)
-			size = len-datapos;
-		memcpy(se401->vlcdata+se401->vlcdatapos, data+datapos, size);
-		se401->vlcdatapos += size;
-		packetlength = 0;
-		if (se401->vlcdatapos >= 4) {
-			bit_exp = se401->vlcdata[3] + (se401->vlcdata[2] << 8);
-			pix_exp = se401->vlcdata[1] +
-					((se401->vlcdata[0] & 0x3f) << 8);
-			frameinfo = se401->vlcdata[0] & 0xc0;
-			packetlength = ((bit_exp + 47) >> 4) << 1;
-			if (packetlength > 1024) {
-				se401->vlcdatapos = 0;
-				datapos = len;
-				packetlength = 0;
-				se401->error++;
-				se401->frame[se401->curframe].curpix = 0;
-			}
-		}
-		if (packetlength && se401->vlcdatapos >= packetlength) {
-			decode_JangGu_vlc(se401, se401->vlcdata, bit_exp,
-								packetlength);
-			se401->frame[se401->curframe].curpix += pix_exp * 3;
-			datapos += size-(se401->vlcdatapos-packetlength);
-			se401->vlcdatapos = 0;
-			if (se401->frame[se401->curframe].curpix >= se401->cwidth * se401->cheight * 3) {
-				if (se401->frame[se401->curframe].curpix == se401->cwidth * se401->cheight * 3) {
-					if (se401->frame[se401->curframe].grabstate == FRAME_GRABBING) {
-						se401->frame[se401->curframe].grabstate = FRAME_DONE;
-						se401->framecount++;
-						se401->readcount++;
-					}
-					if (se401->frame[(se401->curframe + 1) & (SE401_NUMFRAMES - 1)].grabstate == FRAME_READY)
-						se401->curframe = (se401->curframe + 1) & (SE401_NUMFRAMES - 1);
-				} else
-					se401->error++;
-				se401->frame[se401->curframe].curpix = 0;
-				datapos = len;
-			}
-		} else
-			datapos += size;
-	}
-}
-
-static inline void decode_bayer(struct usb_se401 *se401,
-						struct se401_scratch *buffer)
-{
-	unsigned char *data = buffer->data;
-	int len = buffer->length;
-	int offset = buffer->offset;
-	int datasize = se401->cwidth * se401->cheight;
-	struct se401_frame *frame = &se401->frame[se401->curframe];
-	unsigned char *framedata = frame->data, *curline, *nextline;
-	int width = se401->cwidth;
-	int blineoffset = 0, bline;
-	int linelength = width * 3, i;
-
-
-	if (frame->curpix == 0) {
-		if (frame->grabstate == FRAME_READY)
-			frame->grabstate = FRAME_GRABBING;
-
-		frame->curline = framedata + linelength;
-		frame->curlinepix = 0;
-	}
-
-	if (offset != frame->curpix) {
-		/* Regard frame as lost :( */
-		frame->curpix = 0;
-		se401->error++;
-		return;
-	}
-
-	/* Check if we have to much data */
-	if (frame->curpix + len > datasize)
-		len = datasize-frame->curpix;
-
-	if (se401->cheight % 4)
-		blineoffset = 1;
-	bline = frame->curpix / se401->cwidth+blineoffset;
-
-	curline = frame->curline;
-	nextline = curline + linelength;
-	if (nextline >= framedata+datasize * 3)
-		nextline = curline;
-	while (len) {
-		if (frame->curlinepix >= width) {
-			frame->curlinepix -= width;
-			bline = frame->curpix / width + blineoffset;
-			curline += linelength*2;
-			nextline += linelength*2;
-			if (curline >= framedata+datasize * 3) {
-				frame->curlinepix++;
-				curline -= 3;
-				nextline -= 3;
-				len--;
-				data++;
-				frame->curpix++;
-			}
-			if (nextline >= framedata+datasize*3)
-				nextline = curline;
-		}
-		if (bline & 1) {
-			if (frame->curlinepix & 1) {
-				*(curline + 2) = *data;
-				*(curline - 1) = *data;
-				*(nextline + 2) = *data;
-				*(nextline - 1) = *data;
-			} else {
-				*(curline + 1) =
-					(*(curline + 1) + *data) / 2;
-				*(curline-2) =
-					(*(curline - 2) + *data) / 2;
-				*(nextline + 1) = *data;
-				*(nextline - 2) = *data;
-			}
-		} else {
-			if (frame->curlinepix & 1) {
-				*(curline + 1) =
-					(*(curline + 1) + *data) / 2;
-				*(curline - 2) =
-					(*(curline - 2) + *data) / 2;
-				*(nextline + 1) = *data;
-				*(nextline - 2) = *data;
-			} else {
-				*curline = *data;
-				*(curline - 3) = *data;
-				*nextline = *data;
-				*(nextline - 3) = *data;
-			}
-		}
-		frame->curlinepix++;
-		curline -= 3;
-		nextline -= 3;
-		len--;
-		data++;
-		frame->curpix++;
-	}
-	frame->curline = curline;
-
-	if (frame->curpix >= datasize) {
-		/* Fix the top line */
-		framedata += linelength;
-		for (i = 0; i < linelength; i++) {
-			framedata--;
-			*framedata = *(framedata + linelength);
-		}
-		/* Fix the left side (green is already present) */
-		for (i = 0; i < se401->cheight; i++) {
-			*framedata = *(framedata + 3);
-			*(framedata + 1) = *(framedata + 4);
-			*(framedata + 2) = *(framedata + 5);
-			framedata += linelength;
-		}
-		frame->curpix = 0;
-		frame->grabstate = FRAME_DONE;
-		se401->framecount++;
-		se401->readcount++;
-		if (se401->frame[(se401->curframe + 1) &
-		    (SE401_NUMFRAMES - 1)].grabstate == FRAME_READY) {
-			se401->curframe = (se401->curframe+1) &
-							(SE401_NUMFRAMES-1);
-		}
-	}
-}
-
-static int se401_newframe(struct usb_se401 *se401, int framenr)
-{
-	DECLARE_WAITQUEUE(wait, current);
-	int errors = 0;
-
-	while (se401->streaming &&
-	    (se401->frame[framenr].grabstate == FRAME_READY ||
-	     se401->frame[framenr].grabstate == FRAME_GRABBING)) {
-		if (!se401->frame[framenr].curpix)
-			errors++;
-
-		wait_interruptible(
-		    se401->scratch[se401->scratch_use].state != BUFFER_READY,
-						    &se401->wq, &wait);
-		if (se401->nullpackets > SE401_MAX_NULLPACKETS) {
-			se401->nullpackets = 0;
-			dev_info(&se401->dev->dev,
-			 "too many null length packets, restarting capture\n");
-			se401_stop_stream(se401);
-			se401_start_stream(se401);
-		} else {
-			if (se401->scratch[se401->scratch_use].state !=
-								BUFFER_READY) {
-				se401->frame[framenr].grabstate = FRAME_ERROR;
-				return -EIO;
-			}
-			se401->scratch[se401->scratch_use].state = BUFFER_BUSY;
-			if (se401->format == FMT_JANGGU)
-				decode_JangGu(se401,
-					&se401->scratch[se401->scratch_use]);
-			else
-				decode_bayer(se401,
-					&se401->scratch[se401->scratch_use]);
-
-			se401->scratch[se401->scratch_use].state =
-							BUFFER_UNUSED;
-			se401->scratch_use++;
-			if (se401->scratch_use >= SE401_NUMSCRATCH)
-				se401->scratch_use = 0;
-			if (errors > SE401_MAX_ERRORS) {
-				errors = 0;
-				dev_info(&se401->dev->dev,
-				      "too many errors, restarting capture\n");
-				se401_stop_stream(se401);
-				se401_start_stream(se401);
-			}
-		}
-	}
-
-	if (se401->frame[framenr].grabstate == FRAME_DONE)
-		if (se401->enhance)
-			enhance_picture(se401->frame[framenr].data,
-					se401->cheight * se401->cwidth * 3);
-	return 0;
-}
-
-static void usb_se401_remove_disconnected(struct usb_se401 *se401)
-{
-	int i;
-
-	se401->dev = NULL;
-
-	for (i = 0; i < SE401_NUMSBUF; i++)
-		if (se401->urb[i]) {
-			usb_kill_urb(se401->urb[i]);
-			usb_free_urb(se401->urb[i]);
-			se401->urb[i] = NULL;
-			kfree(se401->sbuf[i].data);
-		}
-
-	for (i = 0; i < SE401_NUMSCRATCH; i++)
-		kfree(se401->scratch[i].data);
-
-	if (se401->inturb) {
-		usb_kill_urb(se401->inturb);
-		usb_free_urb(se401->inturb);
-	}
-	dev_info(&se401->dev->dev, "%s disconnected", se401->camera_name);
-
-	/* Free the memory */
-	kfree(se401->width);
-	kfree(se401->height);
-	kfree(se401);
-}
-
-
-
-/****************************************************************************
- *
- * Video4Linux
- *
- ***************************************************************************/
-
-
-static int se401_open(struct file *file)
-{
-	struct video_device *dev = video_devdata(file);
-	struct usb_se401 *se401 = (struct usb_se401 *)dev;
-	int err = 0;
-
-	mutex_lock(&se401->lock);
-	if (se401->user) {
-		mutex_unlock(&se401->lock);
-		return -EBUSY;
-	}
-	se401->fbuf = rvmalloc(se401->maxframesize * SE401_NUMFRAMES);
-	if (se401->fbuf)
-		file->private_data = dev;
-	else
-		err = -ENOMEM;
-	se401->user = !err;
-	mutex_unlock(&se401->lock);
-
-	return err;
-}
-
-static int se401_close(struct file *file)
-{
-	struct video_device *dev = file->private_data;
-	struct usb_se401 *se401 = (struct usb_se401 *)dev;
-	int i;
-
-	rvfree(se401->fbuf, se401->maxframesize * SE401_NUMFRAMES);
-	if (se401->removed) {
-		dev_info(&se401->dev->dev, "device unregistered\n");
-		usb_se401_remove_disconnected(se401);
-	} else {
-		for (i = 0; i < SE401_NUMFRAMES; i++)
-			se401->frame[i].grabstate = FRAME_UNUSED;
-		if (se401->streaming)
-			se401_stop_stream(se401);
-		se401->user = 0;
-	}
-	file->private_data = NULL;
-	return 0;
-}
-
-static long se401_do_ioctl(struct file *file, unsigned int cmd, void *arg)
-{
-	struct video_device *vdev = file->private_data;
-	struct usb_se401 *se401 = (struct usb_se401 *)vdev;
-
-	if (!se401->dev)
-		return -EIO;
-
-	switch (cmd) {
-	case VIDIOCGCAP:
-	{
-		struct video_capability *b = arg;
-		strcpy(b->name, se401->camera_name);
-		b->type = VID_TYPE_CAPTURE;
-		b->channels = 1;
-		b->audios = 0;
-		b->maxwidth = se401->width[se401->sizes-1];
-		b->maxheight = se401->height[se401->sizes-1];
-		b->minwidth = se401->width[0];
-		b->minheight = se401->height[0];
-		return 0;
-	}
-	case VIDIOCGCHAN:
-	{
-		struct video_channel *v = arg;
-
-		if (v->channel != 0)
-			return -EINVAL;
-		v->flags = 0;
-		v->tuners = 0;
-		v->type = VIDEO_TYPE_CAMERA;
-		strcpy(v->name, "Camera");
-		return 0;
-	}
-	case VIDIOCSCHAN:
-	{
-		struct video_channel *v = arg;
-
-		if (v->channel != 0)
-			return -EINVAL;
-		return 0;
-	}
-	case VIDIOCGPICT:
-	{
-		struct video_picture *p = arg;
-
-		se401_get_pict(se401, p);
-		return 0;
-	}
-	case VIDIOCSPICT:
-	{
-		struct video_picture *p = arg;
-
-		if (se401_set_pict(se401, p))
-			return -EINVAL;
-		return 0;
-	}
-	case VIDIOCSWIN:
-	{
-		struct video_window *vw = arg;
-
-		if (vw->flags)
-			return -EINVAL;
-		if (vw->clipcount)
-			return -EINVAL;
-		if (se401_set_size(se401, vw->width, vw->height))
-			return -EINVAL;
-		return 0;
-	}
-	case VIDIOCGWIN:
-	{
-		struct video_window *vw = arg;
-
-		vw->x = 0;               /* FIXME */
-		vw->y = 0;
-		vw->chromakey = 0;
-		vw->flags = 0;
-		vw->clipcount = 0;
-		vw->width = se401->cwidth;
-		vw->height = se401->cheight;
-		return 0;
-	}
-	case VIDIOCGMBUF:
-	{
-		struct video_mbuf *vm = arg;
-		int i;
-
-		memset(vm, 0, sizeof(*vm));
-		vm->size = SE401_NUMFRAMES * se401->maxframesize;
-		vm->frames = SE401_NUMFRAMES;
-		for (i = 0; i < SE401_NUMFRAMES; i++)
-			vm->offsets[i] = se401->maxframesize * i;
-		return 0;
-	}
-	case VIDIOCMCAPTURE:
-	{
-		struct video_mmap *vm = arg;
-
-		if (vm->format != VIDEO_PALETTE_RGB24)
-			return -EINVAL;
-		if (vm->frame >= SE401_NUMFRAMES)
-			return -EINVAL;
-		if (se401->frame[vm->frame].grabstate != FRAME_UNUSED)
-			return -EBUSY;
-
-		/* Is this according to the v4l spec??? */
-		if (se401_set_size(se401, vm->width, vm->height))
-			return -EINVAL;
-		se401->frame[vm->frame].grabstate = FRAME_READY;
-
-		if (!se401->streaming)
-			se401_start_stream(se401);
-
-		/* Set the picture properties */
-		if (se401->framecount == 0)
-			se401_send_pict(se401);
-		/* Calibrate the reset level after a few frames. */
-		if (se401->framecount % 20 == 1)
-			se401_auto_resetlevel(se401);
-
-		return 0;
-	}
-	case VIDIOCSYNC:
-	{
-		int *frame = arg;
-		int ret = 0;
-
-		if (*frame < 0 || *frame >= SE401_NUMFRAMES)
-			return -EINVAL;
-
-		ret = se401_newframe(se401, *frame);
-		se401->frame[*frame].grabstate = FRAME_UNUSED;
-		return ret;
-	}
-	case VIDIOCGFBUF:
-	{
-		struct video_buffer *vb = arg;
-
-		memset(vb, 0, sizeof(*vb));
-		return 0;
-	}
-	case VIDIOCKEY:
-		return 0;
-	case VIDIOCCAPTURE:
-		return -EINVAL;
-	case VIDIOCSFBUF:
-		return -EINVAL;
-	case VIDIOCGTUNER:
-	case VIDIOCSTUNER:
-		return -EINVAL;
-	case VIDIOCGFREQ:
-	case VIDIOCSFREQ:
-		return -EINVAL;
-	case VIDIOCGAUDIO:
-	case VIDIOCSAUDIO:
-		return -EINVAL;
-	default:
-		return -ENOIOCTLCMD;
-	} /* end switch */
-
-	return 0;
-}
-
-static long se401_ioctl(struct file *file,
-		       unsigned int cmd, unsigned long arg)
-{
-	return video_usercopy(file, cmd, arg, se401_do_ioctl);
-}
-
-static ssize_t se401_read(struct file *file, char __user *buf,
-		     size_t count, loff_t *ppos)
-{
-	int realcount = count, ret = 0;
-	struct video_device *dev = file->private_data;
-	struct usb_se401 *se401 = (struct usb_se401 *)dev;
-
-
-	if (se401->dev ==  NULL)
-		return -EIO;
-	if (realcount > se401->cwidth*se401->cheight*3)
-		realcount = se401->cwidth*se401->cheight*3;
-
-	/* Shouldn't happen: */
-	if (se401->frame[0].grabstate == FRAME_GRABBING)
-		return -EBUSY;
-	se401->frame[0].grabstate = FRAME_READY;
-	se401->frame[1].grabstate = FRAME_UNUSED;
-	se401->curframe = 0;
-
-	if (!se401->streaming)
-		se401_start_stream(se401);
-
-	/* Set the picture properties */
-	if (se401->framecount == 0)
-		se401_send_pict(se401);
-	/* Calibrate the reset level after a few frames. */
-	if (se401->framecount%20 == 1)
-		se401_auto_resetlevel(se401);
-
-	ret = se401_newframe(se401, 0);
-
-	se401->frame[0].grabstate = FRAME_UNUSED;
-	if (ret)
-		return ret;
-	if (copy_to_user(buf, se401->frame[0].data, realcount))
-		return -EFAULT;
-
-	return realcount;
-}
-
-static int se401_mmap(struct file *file, struct vm_area_struct *vma)
-{
-	struct video_device *dev = file->private_data;
-	struct usb_se401 *se401 = (struct usb_se401 *)dev;
-	unsigned long start = vma->vm_start;
-	unsigned long size  = vma->vm_end-vma->vm_start;
-	unsigned long page, pos;
-
-	mutex_lock(&se401->lock);
-
-	if (se401->dev ==  NULL) {
-		mutex_unlock(&se401->lock);
-		return -EIO;
-	}
-	if (size > (((SE401_NUMFRAMES * se401->maxframesize) + PAGE_SIZE - 1)
-							& ~(PAGE_SIZE - 1))) {
-		mutex_unlock(&se401->lock);
-		return -EINVAL;
-	}
-	pos = (unsigned long)se401->fbuf;
-	while (size > 0) {
-		page = vmalloc_to_pfn((void *)pos);
-		if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) {
-			mutex_unlock(&se401->lock);
-			return -EAGAIN;
-		}
-		start +=  PAGE_SIZE;
-		pos +=  PAGE_SIZE;
-		if (size > PAGE_SIZE)
-			size -=  PAGE_SIZE;
-		else
-			size = 0;
-	}
-	mutex_unlock(&se401->lock);
-
-	return 0;
-}
-
-static const struct v4l2_file_operations se401_fops = {
-	.owner  = 	THIS_MODULE,
-	.open =         se401_open,
-	.release =      se401_close,
-	.read =         se401_read,
-	.mmap =         se401_mmap,
-	.ioctl =        se401_ioctl,
-};
-static struct video_device se401_template = {
-	.name =         "se401 USB camera",
-	.fops =         &se401_fops,
-	.release = video_device_release_empty,
-};
-
-
-
-/***************************/
-static int se401_init(struct usb_se401 *se401, int button)
-{
-	int i = 0, rc;
-	unsigned char cp[0x40];
-	char temp[200];
-	int slen;
-
-	/* led on */
-	se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 1, NULL, 0);
-
-	/* get camera descriptor */
-	rc = se401_sndctrl(0, se401, SE401_REQ_GET_CAMERA_DESCRIPTOR, 0,
-							cp, sizeof(cp));
-	if (cp[1] != 0x41) {
-		err("Wrong descriptor type");
-		return 1;
-	}
-	slen = snprintf(temp, 200, "ExtraFeatures: %d", cp[3]);
-
-	se401->sizes = cp[4] + cp[5] * 256;
-	se401->width = kmalloc(se401->sizes*sizeof(int), GFP_KERNEL);
-	if (!se401->width)
-		return 1;
-	se401->height = kmalloc(se401->sizes*sizeof(int), GFP_KERNEL);
-	if (!se401->height) {
-		kfree(se401->width);
-		return 1;
-	}
-	for (i = 0; i < se401->sizes; i++) {
-		se401->width[i] = cp[6 + i * 4 + 0] + cp[6 + i*4 + 1] * 256;
-		se401->height[i] = cp[6 + i * 4 + 2] + cp[6 + i * 4 + 3] * 256;
-	}
-	slen += snprintf(temp + slen, 200 - slen, " Sizes:");
-	for (i = 0; i < se401->sizes; i++) {
-		slen +=  snprintf(temp + slen, 200 - slen,
-			" %dx%d", se401->width[i], se401->height[i]);
-	}
-	dev_info(&se401->dev->dev, "%s\n", temp);
-	se401->maxframesize = se401->width[se401->sizes-1] *
-					se401->height[se401->sizes - 1] * 3;
-
-	rc = se401_sndctrl(0, se401, SE401_REQ_GET_WIDTH, 0, cp, sizeof(cp));
-	se401->cwidth = cp[0]+cp[1]*256;
-	rc = se401_sndctrl(0, se401, SE401_REQ_GET_HEIGHT, 0, cp, sizeof(cp));
-	se401->cheight = cp[0]+cp[1]*256;
-
-	if (!(cp[2] & SE401_FORMAT_BAYER)) {
-		err("Bayer format not supported!");
-		return 1;
-	}
-	/* set output mode (BAYER) */
-	se401_sndctrl(1, se401, SE401_REQ_SET_OUTPUT_MODE,
-						SE401_FORMAT_BAYER, NULL, 0);
-
-	rc = se401_sndctrl(0, se401, SE401_REQ_GET_BRT, 0, cp, sizeof(cp));
-	se401->brightness = cp[0]+cp[1]*256;
-	/* some default values */
-	se401->resetlevel = 0x2d;
-	se401->rgain = 0x20;
-	se401->ggain = 0x20;
-	se401->bgain = 0x20;
-	se401_set_exposure(se401, 20000);
-	se401->palette = VIDEO_PALETTE_RGB24;
-	se401->enhance = 1;
-	se401->dropped = 0;
-	se401->error = 0;
-	se401->framecount = 0;
-	se401->readcount = 0;
-
-	/* Start interrupt transfers for snapshot button */
-	if (button) {
-		se401->inturb = usb_alloc_urb(0, GFP_KERNEL);
-		if (!se401->inturb) {
-			dev_info(&se401->dev->dev,
-				 "Allocation of inturb failed\n");
-			return 1;
-		}
-		usb_fill_int_urb(se401->inturb, se401->dev,
-		    usb_rcvintpipe(se401->dev, SE401_BUTTON_ENDPOINT),
-		    &se401->button, sizeof(se401->button),
-		    se401_button_irq,
-		    se401,
-		    8
-		);
-		if (usb_submit_urb(se401->inturb, GFP_KERNEL)) {
-			dev_info(&se401->dev->dev, "int urb burned down\n");
-			return 1;
-		}
-	} else
-		se401->inturb = NULL;
-
-	/* Flash the led */
-	se401_sndctrl(1, se401, SE401_REQ_CAMERA_POWER, 1, NULL, 0);
-	se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 1, NULL, 0);
-	se401_sndctrl(1, se401, SE401_REQ_CAMERA_POWER, 0, NULL, 0);
-	se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 0, NULL, 0);
-
-	return 0;
-}
-
-static int se401_probe(struct usb_interface *intf,
-	const struct usb_device_id *id)
-{
-	struct usb_device *dev = interface_to_usbdev(intf);
-	struct usb_interface_descriptor *interface;
-	struct usb_se401 *se401;
-	char *camera_name = NULL;
-	int button = 1;
-
-	/* We don't handle multi-config cameras */
-	if (dev->descriptor.bNumConfigurations != 1)
-		return -ENODEV;
-
-	interface = &intf->cur_altsetting->desc;
-
-	/* Is it an se401? */
-	if (le16_to_cpu(dev->descriptor.idVendor) ==  0x03e8 &&
-	    le16_to_cpu(dev->descriptor.idProduct) ==  0x0004) {
-		camera_name = "Endpoints/Aox SE401";
-	} else if (le16_to_cpu(dev->descriptor.idVendor) ==  0x0471 &&
-	    le16_to_cpu(dev->descriptor.idProduct) ==  0x030b) {
-		camera_name = "Philips PCVC665K";
-	} else if (le16_to_cpu(dev->descriptor.idVendor) ==  0x047d &&
-	    le16_to_cpu(dev->descriptor.idProduct) ==  0x5001) {
-		camera_name = "Kensington VideoCAM 67014";
-	} else if (le16_to_cpu(dev->descriptor.idVendor) ==  0x047d &&
-	    le16_to_cpu(dev->descriptor.idProduct) ==  0x5002) {
-		camera_name = "Kensington VideoCAM 6701(5/7)";
-	} else if (le16_to_cpu(dev->descriptor.idVendor) ==  0x047d &&
-	    le16_to_cpu(dev->descriptor.idProduct) ==  0x5003) {
-		camera_name = "Kensington VideoCAM 67016";
-		button = 0;
-	} else
-		return -ENODEV;
-
-	/* Checking vendor/product should be enough, but what the hell */
-	if (interface->bInterfaceClass != 0x00)
-		return -ENODEV;
-	if (interface->bInterfaceSubClass != 0x00)
-		return -ENODEV;
-
-	/* We found one */
-	dev_info(&intf->dev, "SE401 camera found: %s\n", camera_name);
-
-	se401 = kzalloc(sizeof(*se401), GFP_KERNEL);
-	if (se401 ==  NULL) {
-		err("couldn't kmalloc se401 struct");
-		return -ENOMEM;
-	}
-
-	se401->dev = dev;
-	se401->iface = interface->bInterfaceNumber;
-	se401->camera_name = camera_name;
-
-	dev_info(&intf->dev, "firmware version: %02x\n",
-		 le16_to_cpu(dev->descriptor.bcdDevice) & 255);
-
-	if (se401_init(se401, button)) {
-		kfree(se401);
-		return -EIO;
-	}
-
-	memcpy(&se401->vdev, &se401_template, sizeof(se401_template));
-	memcpy(se401->vdev.name, se401->camera_name,
-					strlen(se401->camera_name));
-	init_waitqueue_head(&se401->wq);
-	mutex_init(&se401->lock);
-	wmb();
-
-	if (video_register_device(&se401->vdev,
-					VFL_TYPE_GRABBER, video_nr) < 0) {
-		kfree(se401);
-		err("video_register_device failed");
-		return -EIO;
-	}
-	dev_info(&intf->dev, "registered new video device: %s\n",
-		 video_device_node_name(&se401->vdev));
-
-	usb_set_intfdata(intf, se401);
-	return 0;
-}
-
-static void se401_disconnect(struct usb_interface *intf)
-{
-	struct usb_se401 *se401 = usb_get_intfdata(intf);
-
-	usb_set_intfdata(intf, NULL);
-	if (se401) {
-		video_unregister_device(&se401->vdev);
-		if (!se401->user)
-			usb_se401_remove_disconnected(se401);
-		else {
-			se401->frame[0].grabstate = FRAME_ERROR;
-			se401->frame[0].grabstate = FRAME_ERROR;
-
-			se401->streaming = 0;
-
-			wake_up_interruptible(&se401->wq);
-			se401->removed = 1;
-		}
-	}
-}
-
-static struct usb_driver se401_driver = {
-	.name		 =  "se401",
-	.id_table	 =  device_table,
-	.probe		 =  se401_probe,
-	.disconnect	 =  se401_disconnect,
-};
-
-
-
-/****************************************************************************
- *
- *  Module routines
- *
- ***************************************************************************/
-
-static int __init usb_se401_init(void)
-{
-	printk(KERN_INFO "SE401 usb camera driver version %s registering\n",
-								version);
-	if (flickerless)
-		if (flickerless != 50 && flickerless != 60) {
-			printk(KERN_ERR "Invallid flickerless value, use 0, 50 or 60.\n");
-			return -1;
-	}
-	return usb_register(&se401_driver);
-}
-
-static void __exit usb_se401_exit(void)
-{
-	usb_deregister(&se401_driver);
-	printk(KERN_INFO "SE401 driver deregistered\frame");
-}
-
-module_init(usb_se401_init);
-module_exit(usb_se401_exit);
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/se401.h linux-libre-2.6.38-gnu1/drivers/media/video/se401.h
--- linux-libre-2.6.37-gnu1/drivers/media/video/se401.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/se401.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,236 +0,0 @@
-
-#ifndef __LINUX_se401_H
-#define __LINUX_se401_H
-
-#include <linux/uaccess.h>
-#include <linux/videodev.h>
-#include <media/v4l2-common.h>
-#include <media/v4l2-ioctl.h>
-#include <linux/mutex.h>
-
-#define se401_DEBUG	/* Turn on debug messages */
-
-#ifdef se401_DEBUG
-#  define PDEBUG(level, fmt, args...) \
-if (debug >= level) \
-	info("[" __PRETTY_FUNCTION__ ":%d] " fmt, __LINE__ , ## args)
-#else
-#  define PDEBUG(level, fmt, args...) do {} while (0)
-#endif
-
-/* An almost drop-in replacement for sleep_on_interruptible */
-#define wait_interruptible(test, queue, wait) \
-{ \
-	add_wait_queue(queue, wait); \
-	set_current_state(TASK_INTERRUPTIBLE); \
-	if (test) \
-		schedule(); \
-	remove_wait_queue(queue, wait); \
-	set_current_state(TASK_RUNNING); \
-	if (signal_pending(current)) \
-		break; \
-}
-
-#define SE401_REQ_GET_CAMERA_DESCRIPTOR		0x06
-#define SE401_REQ_START_CONTINUOUS_CAPTURE	0x41
-#define SE401_REQ_STOP_CONTINUOUS_CAPTURE	0x42
-#define SE401_REQ_CAPTURE_FRAME			0x43
-#define SE401_REQ_GET_BRT			0x44
-#define SE401_REQ_SET_BRT			0x45
-#define SE401_REQ_GET_WIDTH			0x4c
-#define SE401_REQ_SET_WIDTH			0x4d
-#define SE401_REQ_GET_HEIGHT			0x4e
-#define SE401_REQ_SET_HEIGHT			0x4f
-#define SE401_REQ_GET_OUTPUT_MODE		0x50
-#define SE401_REQ_SET_OUTPUT_MODE		0x51
-#define SE401_REQ_GET_EXT_FEATURE		0x52
-#define SE401_REQ_SET_EXT_FEATURE		0x53
-#define SE401_REQ_CAMERA_POWER			0x56
-#define SE401_REQ_LED_CONTROL			0x57
-#define SE401_REQ_BIOS				0xff
-
-#define SE401_BIOS_READ				0x07
-
-#define SE401_FORMAT_BAYER	0x40
-
-/* Hyundai hv7131b registers
-   7121 and 7141 should be the same (haven't really checked...) */
-/* Mode registers: */
-#define HV7131_REG_MODE_A		0x00
-#define HV7131_REG_MODE_B		0x01
-#define HV7131_REG_MODE_C		0x02
-/* Frame registers: */
-#define HV7131_REG_FRSU		0x10
-#define HV7131_REG_FRSL		0x11
-#define HV7131_REG_FCSU		0x12
-#define HV7131_REG_FCSL		0x13
-#define HV7131_REG_FWHU		0x14
-#define HV7131_REG_FWHL		0x15
-#define HV7131_REG_FWWU		0x16
-#define HV7131_REG_FWWL		0x17
-/* Timing registers: */
-#define HV7131_REG_THBU		0x20
-#define HV7131_REG_THBL		0x21
-#define HV7131_REG_TVBU		0x22
-#define HV7131_REG_TVBL		0x23
-#define HV7131_REG_TITU		0x25
-#define HV7131_REG_TITM		0x26
-#define HV7131_REG_TITL		0x27
-#define HV7131_REG_TMCD		0x28
-/* Adjust Registers: */
-#define HV7131_REG_ARLV		0x30
-#define HV7131_REG_ARCG		0x31
-#define HV7131_REG_AGCG		0x32
-#define HV7131_REG_ABCG		0x33
-#define HV7131_REG_APBV		0x34
-#define HV7131_REG_ASLP		0x54
-/* Offset Registers: */
-#define HV7131_REG_OFSR		0x50
-#define HV7131_REG_OFSG		0x51
-#define HV7131_REG_OFSB		0x52
-/* REset level statistics registers: */
-#define HV7131_REG_LOREFNOH	0x57
-#define HV7131_REG_LOREFNOL	0x58
-#define HV7131_REG_HIREFNOH	0x59
-#define HV7131_REG_HIREFNOL	0x5a
-
-/* se401 registers */
-#define SE401_OPERATINGMODE	0x2000
-
-
-/* size of usb transfers */
-#define SE401_PACKETSIZE	4096
-/* number of queued bulk transfers to use, should be about 8 */
-#define SE401_NUMSBUF		1
-/* read the usb specs for this one :) */
-#define SE401_VIDEO_ENDPOINT	1
-#define SE401_BUTTON_ENDPOINT	2
-/* number of frames supported by the v4l part */
-#define SE401_NUMFRAMES		2
-/* scratch buffers for passing data to the decoders */
-#define SE401_NUMSCRATCH	32
-/* maximum amount of data in a JangGu packet */
-#define SE401_VLCDATALEN	1024
-/* number of nul sized packets to receive before kicking the camera */
-#define SE401_MAX_NULLPACKETS	4000
-/* number of decoding errors before kicking the camera */
-#define SE401_MAX_ERRORS	200
-
-struct usb_device;
-
-struct se401_sbuf {
-	unsigned char *data;
-};
-
-enum {
-	FRAME_UNUSED,		/* Unused (no MCAPTURE) */
-	FRAME_READY,		/* Ready to start grabbing */
-	FRAME_GRABBING,		/* In the process of being grabbed into */
-	FRAME_DONE,		/* Finished grabbing, but not been synced yet */
-	FRAME_ERROR,		/* Something bad happened while processing */
-};
-
-enum {
-	FMT_BAYER,
-	FMT_JANGGU,
-};
-
-enum {
-	BUFFER_UNUSED,
-	BUFFER_READY,
-	BUFFER_BUSY,
-	BUFFER_DONE,
-};
-
-struct se401_scratch {
-	unsigned char *data;
-	volatile int state;
-	int offset;
-	int length;
-};
-
-struct se401_frame {
-	unsigned char *data;		/* Frame buffer */
-
-	volatile int grabstate;	/* State of grabbing */
-
-	unsigned char *curline;
-	int curlinepix;
-	int curpix;
-};
-
-struct usb_se401 {
-	struct video_device vdev;
-
-	/* Device structure */
-	struct usb_device *dev;
-
-	unsigned char iface;
-
-	char *camera_name;
-
-	int change;
-	int brightness;
-	int hue;
-	int rgain;
-	int ggain;
-	int bgain;
-	int expose_h;
-	int expose_m;
-	int expose_l;
-	int resetlevel;
-
-	int enhance;
-
-	int format;
-	int sizes;
-	int *width;
-	int *height;
-	int cwidth;		/* current width */
-	int cheight;		/* current height */
-	int palette;
-	int maxframesize;
-	int cframesize;		/* current framesize */
-
-	struct mutex lock;
-	int user;		/* user count for exclusive use */
-	int removed;		/* device disconnected */
-
-	int streaming;		/* Are we streaming video? */
-
-	char *fbuf;		/* Videodev buffer area */
-
-	struct urb *urb[SE401_NUMSBUF];
-	struct urb *inturb;
-
-	int button;
-	int buttonpressed;
-
-	int curframe;		/* Current receiving frame */
-	struct se401_frame frame[SE401_NUMFRAMES];
-	int readcount;
-	int framecount;
-	int error;
-	int dropped;
-
-	int scratch_next;
-	int scratch_use;
-	int scratch_overflow;
-	struct se401_scratch scratch[SE401_NUMSCRATCH];
-
-	/* Decoder specific data: */
-	unsigned char vlcdata[SE401_VLCDATALEN];
-	int vlcdatapos;
-	int bayeroffset;
-
-	struct se401_sbuf sbuf[SE401_NUMSBUF];
-
-	wait_queue_head_t wq;	/* Processes waiting */
-
-	int nullpackets;
-};
-
-
-
-#endif
-
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/sh_mobile_ceu_camera.c linux-libre-2.6.38-gnu1/drivers/media/video/sh_mobile_ceu_camera.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/sh_mobile_ceu_camera.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/sh_mobile_ceu_camera.c	2011-03-14 21:20:32.000000000 -0400
@@ -1786,7 +1786,7 @@ static void sh_mobile_ceu_init_videobuf(
 				       V4L2_BUF_TYPE_VIDEO_CAPTURE,
 				       pcdev->field,
 				       sizeof(struct sh_mobile_ceu_buffer),
-				       icd, NULL);
+				       icd, &icd->video_lock);
 }
 
 static int sh_mobile_ceu_get_ctrl(struct soc_camera_device *icd,
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/sn9c102/sn9c102_core.c linux-libre-2.6.38-gnu1/drivers/media/video/sn9c102/sn9c102_core.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/sn9c102/sn9c102_core.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/sn9c102/sn9c102_core.c	2011-03-14 21:20:32.000000000 -0400
@@ -2189,6 +2189,7 @@ sn9c102_vidioc_enuminput(struct sn9c102_
 	memset(&i, 0, sizeof(i));
 	strcpy(i.name, "Camera");
 	i.type = V4L2_INPUT_TYPE_CAMERA;
+	i.capabilities = V4L2_IN_CAP_STD;
 
 	if (copy_to_user(arg, &i, sizeof(i)))
 		return -EFAULT;
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/sn9c102/sn9c102_devtable.h linux-libre-2.6.38-gnu1/drivers/media/video/sn9c102/sn9c102_devtable.h
--- linux-libre-2.6.37-gnu1/drivers/media/video/sn9c102/sn9c102_devtable.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/sn9c102/sn9c102_devtable.h	2011-03-14 21:20:32.000000000 -0400
@@ -43,93 +43,81 @@ static const struct usb_device_id sn9c10
 #if !defined CONFIG_USB_GSPCA_SONIXB && !defined CONFIG_USB_GSPCA_SONIXB_MODULE
 	{ SN9C102_USB_DEVICE(0x0c45, 0x6001, BRIDGE_SN9C102), },
 	{ SN9C102_USB_DEVICE(0x0c45, 0x6005, BRIDGE_SN9C102), },
-#endif
 	{ SN9C102_USB_DEVICE(0x0c45, 0x6007, BRIDGE_SN9C102), },
-#if !defined CONFIG_USB_GSPCA_SONIXB && !defined CONFIG_USB_GSPCA_SONIXB_MODULE
 	{ SN9C102_USB_DEVICE(0x0c45, 0x6009, BRIDGE_SN9C102), },
 	{ SN9C102_USB_DEVICE(0x0c45, 0x600d, BRIDGE_SN9C102), },
 /*	{ SN9C102_USB_DEVICE(0x0c45, 0x6011, BRIDGE_SN9C102), }, OV6650 */
-#endif
 	{ SN9C102_USB_DEVICE(0x0c45, 0x6019, BRIDGE_SN9C102), },
+#endif
 	{ SN9C102_USB_DEVICE(0x0c45, 0x6024, BRIDGE_SN9C102), },
 	{ SN9C102_USB_DEVICE(0x0c45, 0x6025, BRIDGE_SN9C102), },
 #if !defined CONFIG_USB_GSPCA_SONIXB && !defined CONFIG_USB_GSPCA_SONIXB_MODULE
 	{ SN9C102_USB_DEVICE(0x0c45, 0x6028, BRIDGE_SN9C102), },
 	{ SN9C102_USB_DEVICE(0x0c45, 0x6029, BRIDGE_SN9C102), },
-#endif
 	{ SN9C102_USB_DEVICE(0x0c45, 0x602a, BRIDGE_SN9C102), },
-	{ SN9C102_USB_DEVICE(0x0c45, 0x602b, BRIDGE_SN9C102), },
+#endif
+	{ SN9C102_USB_DEVICE(0x0c45, 0x602b, BRIDGE_SN9C102), }, /* not in sonixb */
 #if !defined CONFIG_USB_GSPCA_SONIXB && !defined CONFIG_USB_GSPCA_SONIXB_MODULE
 	{ SN9C102_USB_DEVICE(0x0c45, 0x602c, BRIDGE_SN9C102), },
 /*	{ SN9C102_USB_DEVICE(0x0c45, 0x602d, BRIDGE_SN9C102), }, HV7131R */
 	{ SN9C102_USB_DEVICE(0x0c45, 0x602e, BRIDGE_SN9C102), },
 #endif
-	{ SN9C102_USB_DEVICE(0x0c45, 0x6030, BRIDGE_SN9C102), },
+	{ SN9C102_USB_DEVICE(0x0c45, 0x6030, BRIDGE_SN9C102), }, /* not in sonixb */
 	/* SN9C103 */
-	{ SN9C102_USB_DEVICE(0x0c45, 0x6080, BRIDGE_SN9C103), },
-	{ SN9C102_USB_DEVICE(0x0c45, 0x6082, BRIDGE_SN9C103), },
+/*	{ SN9C102_USB_DEVICE(0x0c45, 0x6080, BRIDGE_SN9C103), }, non existent ? */
+	{ SN9C102_USB_DEVICE(0x0c45, 0x6082, BRIDGE_SN9C103), }, /* not in sonixb */
+#if !defined CONFIG_USB_GSPCA_SONIXB && !defined CONFIG_USB_GSPCA_SONIXB_MODULE
 /*	{ SN9C102_USB_DEVICE(0x0c45, 0x6083, BRIDGE_SN9C103), }, HY7131D/E */
-	{ SN9C102_USB_DEVICE(0x0c45, 0x6088, BRIDGE_SN9C103), },
-	{ SN9C102_USB_DEVICE(0x0c45, 0x608a, BRIDGE_SN9C103), },
-	{ SN9C102_USB_DEVICE(0x0c45, 0x608b, BRIDGE_SN9C103), },
+/*	{ SN9C102_USB_DEVICE(0x0c45, 0x6088, BRIDGE_SN9C103), }, non existent ? */
+/*	{ SN9C102_USB_DEVICE(0x0c45, 0x608a, BRIDGE_SN9C103), }, non existent ? */
+/*	{ SN9C102_USB_DEVICE(0x0c45, 0x608b, BRIDGE_SN9C103), }, non existent ? */
 	{ SN9C102_USB_DEVICE(0x0c45, 0x608c, BRIDGE_SN9C103), },
 /*	{ SN9C102_USB_DEVICE(0x0c45, 0x608e, BRIDGE_SN9C103), }, CISVF10 */
-#if !defined CONFIG_USB_GSPCA_SONIXB && !defined CONFIG_USB_GSPCA_SONIXB_MODULE
 	{ SN9C102_USB_DEVICE(0x0c45, 0x608f, BRIDGE_SN9C103), },
-#endif
-	{ SN9C102_USB_DEVICE(0x0c45, 0x60a0, BRIDGE_SN9C103), },
-	{ SN9C102_USB_DEVICE(0x0c45, 0x60a2, BRIDGE_SN9C103), },
-	{ SN9C102_USB_DEVICE(0x0c45, 0x60a3, BRIDGE_SN9C103), },
+/*	{ SN9C102_USB_DEVICE(0x0c45, 0x60a0, BRIDGE_SN9C103), }, non existent ? */
+/*	{ SN9C102_USB_DEVICE(0x0c45, 0x60a2, BRIDGE_SN9C103), }, non existent ? */
+/*	{ SN9C102_USB_DEVICE(0x0c45, 0x60a3, BRIDGE_SN9C103), }, non existent ? */
 /*	{ SN9C102_USB_DEVICE(0x0c45, 0x60a8, BRIDGE_SN9C103), }, PAS106 */
 /*	{ SN9C102_USB_DEVICE(0x0c45, 0x60aa, BRIDGE_SN9C103), }, TAS5130 */
-/*	{ SN9C102_USB_DEVICE(0x0c45, 0x60ab, BRIDGE_SN9C103), }, TAS5130 */
-	{ SN9C102_USB_DEVICE(0x0c45, 0x60ac, BRIDGE_SN9C103), },
-	{ SN9C102_USB_DEVICE(0x0c45, 0x60ae, BRIDGE_SN9C103), },
+/*	{ SN9C102_USB_DEVICE(0x0c45, 0x60ab, BRIDGE_SN9C103), }, TAS5110, non existent */
+/*	{ SN9C102_USB_DEVICE(0x0c45, 0x60ac, BRIDGE_SN9C103), }, non existent ? */
+/*	{ SN9C102_USB_DEVICE(0x0c45, 0x60ae, BRIDGE_SN9C103), }, non existent ? */
 	{ SN9C102_USB_DEVICE(0x0c45, 0x60af, BRIDGE_SN9C103), },
-#if !defined CONFIG_USB_GSPCA_SONIXB && !defined CONFIG_USB_GSPCA_SONIXB_MODULE
 	{ SN9C102_USB_DEVICE(0x0c45, 0x60b0, BRIDGE_SN9C103), },
+/*	{ SN9C102_USB_DEVICE(0x0c45, 0x60b2, BRIDGE_SN9C103), }, non existent ? */
+/*	{ SN9C102_USB_DEVICE(0x0c45, 0x60b3, BRIDGE_SN9C103), }, non existent ? */
+/*	{ SN9C102_USB_DEVICE(0x0c45, 0x60b8, BRIDGE_SN9C103), }, non existent ? */
+/*	{ SN9C102_USB_DEVICE(0x0c45, 0x60ba, BRIDGE_SN9C103), }, non existent ? */
+/*	{ SN9C102_USB_DEVICE(0x0c45, 0x60bb, BRIDGE_SN9C103), }, non existent ? */
+/*	{ SN9C102_USB_DEVICE(0x0c45, 0x60bc, BRIDGE_SN9C103), }, non existent ? */
+/*	{ SN9C102_USB_DEVICE(0x0c45, 0x60be, BRIDGE_SN9C103), }, non existent ? */
 #endif
-	{ SN9C102_USB_DEVICE(0x0c45, 0x60b2, BRIDGE_SN9C103), },
-	{ SN9C102_USB_DEVICE(0x0c45, 0x60b3, BRIDGE_SN9C103), },
-	{ SN9C102_USB_DEVICE(0x0c45, 0x60b8, BRIDGE_SN9C103), },
-	{ SN9C102_USB_DEVICE(0x0c45, 0x60ba, BRIDGE_SN9C103), },
-	{ SN9C102_USB_DEVICE(0x0c45, 0x60bb, BRIDGE_SN9C103), },
-	{ SN9C102_USB_DEVICE(0x0c45, 0x60bc, BRIDGE_SN9C103), },
-	{ SN9C102_USB_DEVICE(0x0c45, 0x60be, BRIDGE_SN9C103), },
 	/* SN9C105 */
 #if !defined CONFIG_USB_GSPCA_SONIXJ && !defined CONFIG_USB_GSPCA_SONIXJ_MODULE
 	{ SN9C102_USB_DEVICE(0x045e, 0x00f5, BRIDGE_SN9C105), },
 	{ SN9C102_USB_DEVICE(0x045e, 0x00f7, BRIDGE_SN9C105), },
 	{ SN9C102_USB_DEVICE(0x0471, 0x0327, BRIDGE_SN9C105), },
 	{ SN9C102_USB_DEVICE(0x0471, 0x0328, BRIDGE_SN9C105), },
-#endif
 	{ SN9C102_USB_DEVICE(0x0c45, 0x60c0, BRIDGE_SN9C105), },
-	{ SN9C102_USB_DEVICE(0x0c45, 0x60c2, BRIDGE_SN9C105), },
-	{ SN9C102_USB_DEVICE(0x0c45, 0x60c8, BRIDGE_SN9C105), },
-	{ SN9C102_USB_DEVICE(0x0c45, 0x60cc, BRIDGE_SN9C105), },
-	{ SN9C102_USB_DEVICE(0x0c45, 0x60ea, BRIDGE_SN9C105), },
-	{ SN9C102_USB_DEVICE(0x0c45, 0x60ec, BRIDGE_SN9C105), },
-	{ SN9C102_USB_DEVICE(0x0c45, 0x60ef, BRIDGE_SN9C105), },
-	{ SN9C102_USB_DEVICE(0x0c45, 0x60fa, BRIDGE_SN9C105), },
+/*	{ SN9C102_USB_DEVICE(0x0c45, 0x60c2, BRIDGE_SN9C105), }, PO1030 */
+/*	{ SN9C102_USB_DEVICE(0x0c45, 0x60c8, BRIDGE_SN9C105), }, OM6801 */
+/*	{ SN9C102_USB_DEVICE(0x0c45, 0x60cc, BRIDGE_SN9C105), }, HV7131GP */
+/*	{ SN9C102_USB_DEVICE(0x0c45, 0x60ea, BRIDGE_SN9C105), }, non existent ? */
+/*	{ SN9C102_USB_DEVICE(0x0c45, 0x60ec, BRIDGE_SN9C105), }, MO4000 */
+/*	{ SN9C102_USB_DEVICE(0x0c45, 0x60ef, BRIDGE_SN9C105), }, ICM105C */
+/*	{ SN9C102_USB_DEVICE(0x0c45, 0x60fa, BRIDGE_SN9C105), }, OV7648 */
 	{ SN9C102_USB_DEVICE(0x0c45, 0x60fb, BRIDGE_SN9C105), },
 	{ SN9C102_USB_DEVICE(0x0c45, 0x60fc, BRIDGE_SN9C105), },
 	{ SN9C102_USB_DEVICE(0x0c45, 0x60fe, BRIDGE_SN9C105), },
 	/* SN9C120 */
 	{ SN9C102_USB_DEVICE(0x0458, 0x7025, BRIDGE_SN9C120), },
-#if !defined CONFIG_USB_GSPCA_SONIXJ && !defined CONFIG_USB_GSPCA_SONIXJ_MODULE
-	{ SN9C102_USB_DEVICE(0x0c45, 0x6102, BRIDGE_SN9C120), },
-#endif
-	{ SN9C102_USB_DEVICE(0x0c45, 0x6108, BRIDGE_SN9C120), },
-	{ SN9C102_USB_DEVICE(0x0c45, 0x610f, BRIDGE_SN9C120), },
-#if !defined CONFIG_USB_GSPCA_SONIXJ && !defined CONFIG_USB_GSPCA_SONIXJ_MODULE
+/*	{ SN9C102_USB_DEVICE(0x0c45, 0x6102, BRIDGE_SN9C120), }, po2030 */
+/*	{ SN9C102_USB_DEVICE(0x0c45, 0x6108, BRIDGE_SN9C120), }, om6801 */
+/*	{ SN9C102_USB_DEVICE(0x0c45, 0x610f, BRIDGE_SN9C120), }, S5K53BEB */
 	{ SN9C102_USB_DEVICE(0x0c45, 0x6130, BRIDGE_SN9C120), },
-#endif
 /*	{ SN9C102_USB_DEVICE(0x0c45, 0x6138, BRIDGE_SN9C120), }, MO8000 */
-#if !defined CONFIG_USB_GSPCA_SONIXJ && !defined CONFIG_USB_GSPCA_SONIXJ_MODULE
 	{ SN9C102_USB_DEVICE(0x0c45, 0x613a, BRIDGE_SN9C120), },
-#endif
 	{ SN9C102_USB_DEVICE(0x0c45, 0x613b, BRIDGE_SN9C120), },
-#if !defined CONFIG_USB_GSPCA_SONIXJ && !defined CONFIG_USB_GSPCA_SONIXJ_MODULE
 	{ SN9C102_USB_DEVICE(0x0c45, 0x613c, BRIDGE_SN9C120), },
 	{ SN9C102_USB_DEVICE(0x0c45, 0x613e, BRIDGE_SN9C120), },
 #endif
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/sn9c102/sn9c102_sensor.h linux-libre-2.6.38-gnu1/drivers/media/video/sn9c102/sn9c102_sensor.h
--- linux-libre-2.6.37-gnu1/drivers/media/video/sn9c102/sn9c102_sensor.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/sn9c102/sn9c102_sensor.h	2011-03-14 21:20:32.000000000 -0400
@@ -147,7 +147,7 @@ enum sn9c102_i2c_interface {
 
 struct sn9c102_sensor {
 	char name[32], /* sensor name */
-	     maintainer[64]; /* name of the mantainer <email> */
+	     maintainer[64]; /* name of the maintainer <email> */
 
 	enum sn9c102_bridge supported_bridge; /* supported SN9C1xx bridges */
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/soc_camera.c linux-libre-2.6.38-gnu1/drivers/media/video/soc_camera.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/soc_camera.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/soc_camera.c	2011-03-14 21:20:32.000000000 -0400
@@ -24,6 +24,7 @@
 #include <linux/mutex.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
 #include <linux/slab.h>
 #include <linux/pm_runtime.h>
 #include <linux/vmalloc.h>
@@ -43,6 +44,51 @@ static LIST_HEAD(hosts);
 static LIST_HEAD(devices);
 static DEFINE_MUTEX(list_lock);		/* Protects the list of hosts */
 
+static int soc_camera_power_set(struct soc_camera_device *icd,
+				struct soc_camera_link *icl,
+				int power_on)
+{
+	int ret;
+
+	if (power_on) {
+		ret = regulator_bulk_enable(icl->num_regulators,
+					    icl->regulators);
+		if (ret < 0) {
+			dev_err(&icd->dev, "Cannot enable regulators\n");
+			return ret;
+		}
+
+		if (icl->power)
+			ret = icl->power(icd->pdev, power_on);
+		if (ret < 0) {
+			dev_err(&icd->dev,
+				"Platform failed to power-on the camera.\n");
+
+			regulator_bulk_disable(icl->num_regulators,
+					       icl->regulators);
+			return ret;
+		}
+	} else {
+		ret = 0;
+		if (icl->power)
+			ret = icl->power(icd->pdev, 0);
+		if (ret < 0) {
+			dev_err(&icd->dev,
+				"Platform failed to power-off the camera.\n");
+			return ret;
+		}
+
+		ret = regulator_bulk_disable(icl->num_regulators,
+					     icl->regulators);
+		if (ret < 0) {
+			dev_err(&icd->dev, "Cannot disable regulators\n");
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
 const struct soc_camera_format_xlate *soc_camera_xlate_by_fourcc(
 	struct soc_camera_device *icd, unsigned int fourcc)
 {
@@ -352,12 +398,6 @@ static int soc_camera_open(struct file *
 		return -EINVAL;
 	}
 
-	/*
-	 * Protect against icd->ops->remove() until we module_get() both
-	 * drivers.
-	 */
-	mutex_lock(&icd->video_lock);
-
 	icd->use_count++;
 
 	/* Now we really have to activate the camera */
@@ -375,11 +415,9 @@ static int soc_camera_open(struct file *
 			},
 		};
 
-		if (icl->power) {
-			ret = icl->power(icd->pdev, 1);
-			if (ret < 0)
-				goto epower;
-		}
+		ret = soc_camera_power_set(icd, icl, 1);
+		if (ret < 0)
+			goto epower;
 
 		/* The camera could have been already on, try to reset */
 		if (icl->reset)
@@ -412,8 +450,6 @@ static int soc_camera_open(struct file *
 	file->private_data = icd;
 	dev_dbg(&icd->dev, "camera device open\n");
 
-	mutex_unlock(&icd->video_lock);
-
 	return 0;
 
 	/*
@@ -425,11 +461,9 @@ esfmt:
 eresume:
 	ici->ops->remove(icd);
 eiciadd:
-	if (icl->power)
-		icl->power(icd->pdev, 0);
+	soc_camera_power_set(icd, icl, 0);
 epower:
 	icd->use_count--;
-	mutex_unlock(&icd->video_lock);
 	module_put(ici->ops->owner);
 
 	return ret;
@@ -440,7 +474,6 @@ static int soc_camera_close(struct file
 	struct soc_camera_device *icd = file->private_data;
 	struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
 
-	mutex_lock(&icd->video_lock);
 	icd->use_count--;
 	if (!icd->use_count) {
 		struct soc_camera_link *icl = to_soc_camera_link(icd);
@@ -450,15 +483,12 @@ static int soc_camera_close(struct file
 
 		ici->ops->remove(icd);
 
-		if (icl->power)
-			icl->power(icd->pdev, 0);
+		soc_camera_power_set(icd, icl, 0);
 	}
 
 	if (icd->streamer == file)
 		icd->streamer = NULL;
 
-	mutex_unlock(&icd->video_lock);
-
 	module_put(ici->ops->owner);
 
 	dev_dbg(&icd->dev, "camera device close\n");
@@ -517,7 +547,7 @@ static struct v4l2_file_operations soc_c
 	.owner		= THIS_MODULE,
 	.open		= soc_camera_open,
 	.release	= soc_camera_close,
-	.ioctl		= video_ioctl2,
+	.unlocked_ioctl	= video_ioctl2,
 	.read		= soc_camera_read,
 	.mmap		= soc_camera_mmap,
 	.poll		= soc_camera_poll,
@@ -534,12 +564,9 @@ static int soc_camera_s_fmt_vid_cap(stru
 	if (icd->streamer && icd->streamer != file)
 		return -EBUSY;
 
-	mutex_lock(&icd->vb_vidq.vb_lock);
-
 	if (icd->vb_vidq.bufs[0]) {
 		dev_err(&icd->dev, "S_FMT denied: queue initialised\n");
-		ret = -EBUSY;
-		goto unlock;
+		return -EBUSY;
 	}
 
 	ret = soc_camera_set_fmt(icd, f);
@@ -547,9 +574,6 @@ static int soc_camera_s_fmt_vid_cap(stru
 	if (!ret && !icd->streamer)
 		icd->streamer = file;
 
-unlock:
-	mutex_unlock(&icd->vb_vidq.vb_lock);
-
 	return ret;
 }
 
@@ -622,15 +646,11 @@ static int soc_camera_streamon(struct fi
 	if (icd->streamer != file)
 		return -EBUSY;
 
-	mutex_lock(&icd->video_lock);
-
 	v4l2_subdev_call(sd, video, s_stream, 1);
 
 	/* This calls buf_queue from host driver's videobuf_queue_ops */
 	ret = videobuf_streamon(&icd->vb_vidq);
 
-	mutex_unlock(&icd->video_lock);
-
 	return ret;
 }
 
@@ -648,8 +668,6 @@ static int soc_camera_streamoff(struct f
 	if (icd->streamer != file)
 		return -EBUSY;
 
-	mutex_lock(&icd->video_lock);
-
 	/*
 	 * This calls buf_release from host driver's videobuf_queue_ops for all
 	 * remaining buffers. When the last buffer is freed, stop capture
@@ -658,8 +676,6 @@ static int soc_camera_streamoff(struct f
 
 	v4l2_subdev_call(sd, video, s_stream, 0);
 
-	mutex_unlock(&icd->video_lock);
-
 	return 0;
 }
 
@@ -748,9 +764,7 @@ static int soc_camera_g_crop(struct file
 	struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
 	int ret;
 
-	mutex_lock(&icd->vb_vidq.vb_lock);
 	ret = ici->ops->get_crop(icd, a);
-	mutex_unlock(&icd->vb_vidq.vb_lock);
 
 	return ret;
 }
@@ -775,9 +789,6 @@ static int soc_camera_s_crop(struct file
 	dev_dbg(&icd->dev, "S_CROP(%ux%u@%u:%u)\n",
 		rect->width, rect->height, rect->left, rect->top);
 
-	/* Cropping is allowed during a running capture, guard consistency */
-	mutex_lock(&icd->vb_vidq.vb_lock);
-
 	/* If get_crop fails, we'll let host and / or client drivers decide */
 	ret = ici->ops->get_crop(icd, &current_crop);
 
@@ -795,8 +806,6 @@ static int soc_camera_s_crop(struct file
 		ret = ici->ops->set_crop(icd, a);
 	}
 
-	mutex_unlock(&icd->vb_vidq.vb_lock);
-
 	return ret;
 }
 
@@ -941,14 +950,14 @@ static int soc_camera_probe(struct devic
 
 	dev_info(dev, "Probing %s\n", dev_name(dev));
 
-	if (icl->power) {
-		ret = icl->power(icd->pdev, 1);
-		if (ret < 0) {
-			dev_err(dev,
-				"Platform failed to power-on the camera.\n");
-			goto epower;
-		}
-	}
+	ret = regulator_bulk_get(icd->pdev, icl->num_regulators,
+				 icl->regulators);
+	if (ret < 0)
+		goto ereg;
+
+	ret = soc_camera_power_set(icd, icl, 1);
+	if (ret < 0)
+		goto epower;
 
 	/* The camera could have been already on, try to reset */
 	if (icl->reset)
@@ -998,7 +1007,13 @@ static int soc_camera_probe(struct devic
 
 	icd->field = V4L2_FIELD_ANY;
 
-	/* ..._video_start() will create a device node, so we have to protect */
+	icd->vdev->lock = &icd->video_lock;
+
+	/*
+	 * ..._video_start() will create a device node, video_register_device()
+	 * itself is protected against concurrent open() calls, but we also have
+	 * to protect our data.
+	 */
 	mutex_lock(&icd->video_lock);
 
 	ret = soc_camera_video_start(icd);
@@ -1021,8 +1036,7 @@ static int soc_camera_probe(struct devic
 
 	ici->ops->remove(icd);
 
-	if (icl->power)
-		icl->power(icd->pdev, 0);
+	soc_camera_power_set(icd, icl, 0);
 
 	mutex_unlock(&icd->video_lock);
 
@@ -1044,9 +1058,10 @@ eadddev:
 evdc:
 	ici->ops->remove(icd);
 eadd:
-	if (icl->power)
-		icl->power(icd->pdev, 0);
+	soc_camera_power_set(icd, icl, 0);
 epower:
+	regulator_bulk_free(icl->num_regulators, icl->regulators);
+ereg:
 	return ret;
 }
 
@@ -1063,10 +1078,8 @@ static int soc_camera_remove(struct devi
 	BUG_ON(!dev->parent);
 
 	if (vdev) {
-		mutex_lock(&icd->video_lock);
 		video_unregister_device(vdev);
 		icd->vdev = NULL;
-		mutex_unlock(&icd->video_lock);
 	}
 
 	if (icl->board_info) {
@@ -1081,6 +1094,8 @@ static int soc_camera_remove(struct devi
 	}
 	soc_camera_free_user_formats(icd);
 
+	regulator_bulk_free(icl->num_regulators, icl->regulators);
+
 	return 0;
 }
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/sr030pc30.c linux-libre-2.6.38-gnu1/drivers/media/video/sr030pc30.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/sr030pc30.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/sr030pc30.c	2011-03-14 21:20:32.000000000 -0400
@@ -714,15 +714,6 @@ static int sr030pc30_base_config(struct
 	return ret;
 }
 
-static int sr030pc30_s_config(struct v4l2_subdev *sd,
-			      int irq, void *platform_data)
-{
-	struct sr030pc30_info *info = to_sr030pc30(sd);
-
-	info->pdata = platform_data;
-	return 0;
-}
-
 static int sr030pc30_s_stream(struct v4l2_subdev *sd, int enable)
 {
 	return 0;
@@ -735,7 +726,7 @@ static int sr030pc30_s_power(struct v4l2
 	const struct sr030pc30_platform_data *pdata = info->pdata;
 	int ret;
 
-	if (WARN(pdata == NULL, "No platform data!"))
+	if (WARN(pdata == NULL, "No platform data!\n"))
 		return -ENOMEM;
 
 	/*
@@ -763,7 +754,6 @@ static int sr030pc30_s_power(struct v4l2
 }
 
 static const struct v4l2_subdev_core_ops sr030pc30_core_ops = {
-	.s_config	= sr030pc30_s_config,
 	.s_power	= sr030pc30_s_power,
 	.queryctrl	= sr030pc30_queryctrl,
 	.s_ctrl		= sr030pc30_s_ctrl,
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/stk-webcam.c linux-libre-2.6.38-gnu1/drivers/media/video/stk-webcam.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/stk-webcam.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/stk-webcam.c	2011-03-14 21:20:32.000000000 -0400
@@ -230,120 +230,6 @@ static int stk_initialise(struct stk_cam
 		return -1;
 }
 
-#ifdef CONFIG_VIDEO_V4L1_COMPAT
-
-/* sysfs functions */
-/*FIXME cleanup this */
-
-static ssize_t show_brightness(struct device *class,
-			struct device_attribute *attr, char *buf)
-{
-	struct video_device *vdev = to_video_device(class);
-	struct stk_camera *dev = vdev_to_camera(vdev);
-
-	return sprintf(buf, "%X\n", dev->vsettings.brightness);
-}
-
-static ssize_t store_brightness(struct device *class,
-		struct device_attribute *attr, const char *buf, size_t count)
-{
-	char *endp;
-	unsigned long value;
-	int ret;
-
-	struct video_device *vdev = to_video_device(class);
-	struct stk_camera *dev = vdev_to_camera(vdev);
-
-	value = simple_strtoul(buf, &endp, 16);
-
-	dev->vsettings.brightness = (int) value;
-
-	ret = stk_sensor_set_brightness(dev, value >> 8);
-	if (ret)
-		return ret;
-	else
-		return count;
-}
-
-static ssize_t show_hflip(struct device *class,
-		struct device_attribute *attr, char *buf)
-{
-	struct video_device *vdev = to_video_device(class);
-	struct stk_camera *dev = vdev_to_camera(vdev);
-
-	return sprintf(buf, "%d\n", dev->vsettings.hflip);
-}
-
-static ssize_t store_hflip(struct device *class,
-		struct device_attribute *attr, const char *buf, size_t count)
-{
-	struct video_device *vdev = to_video_device(class);
-	struct stk_camera *dev = vdev_to_camera(vdev);
-
-	if (strncmp(buf, "1", 1) == 0)
-		dev->vsettings.hflip = 1;
-	else if (strncmp(buf, "0", 1) == 0)
-		dev->vsettings.hflip = 0;
-	else
-		return -EINVAL;
-
-	return strlen(buf);
-}
-
-static ssize_t show_vflip(struct device *class,
-		struct device_attribute *attr, char *buf)
-{
-	struct video_device *vdev = to_video_device(class);
-	struct stk_camera *dev = vdev_to_camera(vdev);
-
-	return sprintf(buf, "%d\n", dev->vsettings.vflip);
-}
-
-static ssize_t store_vflip(struct device *class,
-		struct device_attribute *attr, const char *buf, size_t count)
-{
-	struct video_device *vdev = to_video_device(class);
-	struct stk_camera *dev = vdev_to_camera(vdev);
-
-	if (strncmp(buf, "1", 1) == 0)
-		dev->vsettings.vflip = 1;
-	else if (strncmp(buf, "0", 1) == 0)
-		dev->vsettings.vflip = 0;
-	else
-		return -EINVAL;
-
-	return strlen(buf);
-}
-
-static DEVICE_ATTR(brightness, S_IRUGO | S_IWUGO,
-			show_brightness, store_brightness);
-static DEVICE_ATTR(hflip, S_IRUGO | S_IWUGO, show_hflip, store_hflip);
-static DEVICE_ATTR(vflip, S_IRUGO | S_IWUGO, show_vflip, store_vflip);
-
-static int stk_create_sysfs_files(struct video_device *vdev)
-{
-	int ret;
-
-	ret = device_create_file(&vdev->dev, &dev_attr_brightness);
-	ret += device_create_file(&vdev->dev, &dev_attr_hflip);
-	ret += device_create_file(&vdev->dev, &dev_attr_vflip);
-	if (ret)
-		STK_WARNING("Could not create sysfs files\n");
-	return ret;
-}
-
-static void stk_remove_sysfs_files(struct video_device *vdev)
-{
-	device_remove_file(&vdev->dev, &dev_attr_brightness);
-	device_remove_file(&vdev->dev, &dev_attr_hflip);
-	device_remove_file(&vdev->dev, &dev_attr_vflip);
-}
-
-#else
-#define stk_create_sysfs_files(a)
-#define stk_remove_sysfs_files(a)
-#endif
-
 /* *********************************************** */
 /*
  * This function is called as an URB transfert is complete (Isochronous pipe).
@@ -878,7 +764,24 @@ static struct v4l2_queryctrl stk_control
 		.step    = 0x0100,
 		.default_value = 0x6000,
 	},
-	/*TODO: get more controls to work */
+	{
+		.id      = V4L2_CID_HFLIP,
+		.type    = V4L2_CTRL_TYPE_BOOLEAN,
+		.name    = "Horizontal Flip",
+		.minimum = 0,
+		.maximum = 1,
+		.step    = 1,
+		.default_value = 1,
+	},
+	{
+		.id      = V4L2_CID_VFLIP,
+		.type    = V4L2_CTRL_TYPE_BOOLEAN,
+		.name    = "Vertical Flip",
+		.minimum = 0,
+		.maximum = 1,
+		.step    = 1,
+		.default_value = 1,
+	},
 };
 
 static int stk_vidioc_queryctrl(struct file *filp,
@@ -906,6 +809,12 @@ static int stk_vidioc_g_ctrl(struct file
 	case V4L2_CID_BRIGHTNESS:
 		c->value = dev->vsettings.brightness;
 		break;
+	case V4L2_CID_HFLIP:
+		c->value = dev->vsettings.hflip;
+		break;
+	case V4L2_CID_VFLIP:
+		c->value = dev->vsettings.vflip;
+		break;
 	default:
 		return -EINVAL;
 	}
@@ -920,6 +829,12 @@ static int stk_vidioc_s_ctrl(struct file
 	case V4L2_CID_BRIGHTNESS:
 		dev->vsettings.brightness = c->value;
 		return stk_sensor_set_brightness(dev, c->value >> 8);
+	case V4L2_CID_HFLIP:
+		dev->vsettings.hflip = c->value;
+		return 0;
+	case V4L2_CID_VFLIP:
+		dev->vsettings.vflip = c->value;
+		return 0;
 	default:
 		return -EINVAL;
 	}
@@ -1394,8 +1309,6 @@ static int stk_camera_probe(struct usb_i
 		goto error;
 	}
 
-	stk_create_sysfs_files(&dev->vdev);
-
 	return 0;
 
 error:
@@ -1411,7 +1324,6 @@ static void stk_camera_disconnect(struct
 	unset_present(dev);
 
 	wake_up_interruptible(&dev->wait_frame);
-	stk_remove_sysfs_files(&dev->vdev);
 
 	STK_INFO("Syntek USB2.0 Camera release resources device %s\n",
 		 video_device_node_name(&dev->vdev));
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/tda9875.c linux-libre-2.6.38-gnu1/drivers/media/video/tda9875.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/tda9875.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/tda9875.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,411 +0,0 @@
-/*
- * For the TDA9875 chip
- * (The TDA9875 is used on the Diamond DTV2000 french version
- * Other cards probably use these chips as well.)
- * This driver will not complain if used with any
- * other i2c device with the same address.
- *
- * Copyright (c) 2000 Guillaume Delvit based on Gerd Knorr source and
- * Eric Sandeen
- * Copyright (c) 2006 Mauro Carvalho Chehab <mchehab@infradead.org>
- * This code is placed under the terms of the GNU General Public License
- * Based on tda9855.c by Steve VanDeBogart (vandebo@uclink.berkeley.edu)
- * Which was based on tda8425.c by Greg Alexander (c) 1998
- *
- * OPTIONS:
- * debug   - set to 1 if you'd like to see debug messages
- *
- *  Revision: 0.1 - original version
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/timer.h>
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
-#include <linux/i2c.h>
-#include <linux/videodev2.h>
-#include <media/v4l2-device.h>
-#include <media/i2c-addr.h>
-
-static int debug; /* insmod parameter */
-module_param(debug, int, S_IRUGO | S_IWUSR);
-MODULE_LICENSE("GPL");
-
-
-/* This is a superset of the TDA9875 */
-struct tda9875 {
-	struct v4l2_subdev sd;
-	int rvol, lvol;
-	int bass, treble;
-};
-
-static inline struct tda9875 *to_state(struct v4l2_subdev *sd)
-{
-	return container_of(sd, struct tda9875, sd);
-}
-
-#define dprintk  if (debug) printk
-
-/* The TDA9875 is made by Philips Semiconductor
- * http://www.semiconductors.philips.com
- * TDA9875: I2C-bus controlled DSP audio processor, FM demodulator
- *
- */
-
-		/* subaddresses for TDA9875 */
-#define TDA9875_MUT         0x12  /*General mute  (value --> 0b11001100*/
-#define TDA9875_CFG         0x01  /* Config register (value --> 0b00000000 */
-#define TDA9875_DACOS       0x13  /*DAC i/o select (ADC) 0b0000100*/
-#define TDA9875_LOSR        0x16  /*Line output select regirter 0b0100 0001*/
-
-#define TDA9875_CH1V        0x0c  /*Channel 1 volume (mute)*/
-#define TDA9875_CH2V        0x0d  /*Channel 2 volume (mute)*/
-#define TDA9875_SC1         0x14  /*SCART 1 in (mono)*/
-#define TDA9875_SC2         0x15  /*SCART 2 in (mono)*/
-
-#define TDA9875_ADCIS       0x17  /*ADC input select (mono) 0b0110 000*/
-#define TDA9875_AER         0x19  /*Audio effect (AVL+Pseudo) 0b0000 0110*/
-#define TDA9875_MCS         0x18  /*Main channel select (DAC) 0b0000100*/
-#define TDA9875_MVL         0x1a  /* Main volume gauche */
-#define TDA9875_MVR         0x1b  /* Main volume droite */
-#define TDA9875_MBA         0x1d  /* Main Basse */
-#define TDA9875_MTR         0x1e  /* Main treble */
-#define TDA9875_ACS         0x1f  /* Auxilary channel select (FM) 0b0000000*/
-#define TDA9875_AVL         0x20  /* Auxilary volume gauche */
-#define TDA9875_AVR         0x21  /* Auxilary volume droite */
-#define TDA9875_ABA         0x22  /* Auxilary Basse */
-#define TDA9875_ATR         0x23  /* Auxilary treble */
-
-#define TDA9875_MSR         0x02  /* Monitor select register */
-#define TDA9875_C1MSB       0x03  /* Carrier 1 (FM) frequency register MSB */
-#define TDA9875_C1MIB       0x04  /* Carrier 1 (FM) frequency register (16-8]b */
-#define TDA9875_C1LSB       0x05  /* Carrier 1 (FM) frequency register LSB */
-#define TDA9875_C2MSB       0x06  /* Carrier 2 (nicam) frequency register MSB */
-#define TDA9875_C2MIB       0x07  /* Carrier 2 (nicam) frequency register (16-8]b */
-#define TDA9875_C2LSB       0x08  /* Carrier 2 (nicam) frequency register LSB */
-#define TDA9875_DCR         0x09  /* Demodulateur configuration regirter*/
-#define TDA9875_DEEM        0x0a  /* FM de-emphasis regirter*/
-#define TDA9875_FMAT        0x0b  /* FM Matrix regirter*/
-
-/* values */
-#define TDA9875_MUTE_ON	    0xff /* general mute */
-#define TDA9875_MUTE_OFF    0xcc /* general no mute */
-
-
-
-/* Begin code */
-
-static int tda9875_write(struct v4l2_subdev *sd, int subaddr, unsigned char val)
-{
-	struct i2c_client *client = v4l2_get_subdevdata(sd);
-	unsigned char buffer[2];
-
-	v4l2_dbg(1, debug, sd, "Writing %d 0x%x\n", subaddr, val);
-	buffer[0] = subaddr;
-	buffer[1] = val;
-	if (2 != i2c_master_send(client, buffer, 2)) {
-		v4l2_warn(sd, "I/O error, trying (write %d 0x%x)\n",
-		       subaddr, val);
-		return -1;
-	}
-	return 0;
-}
-
-
-static int i2c_read_register(struct i2c_client *client, int addr, int reg)
-{
-	unsigned char write[1];
-	unsigned char read[1];
-	struct i2c_msg msgs[2] = {
-		{ addr, 0,        1, write },
-		{ addr, I2C_M_RD, 1, read  }
-	};
-
-	write[0] = reg;
-
-	if (2 != i2c_transfer(client->adapter, msgs, 2)) {
-		v4l_warn(client, "I/O error (read2)\n");
-		return -1;
-	}
-	v4l_dbg(1, debug, client, "chip_read2: reg%d=0x%x\n", reg, read[0]);
-	return read[0];
-}
-
-static void tda9875_set(struct v4l2_subdev *sd)
-{
-	struct tda9875 *tda = to_state(sd);
-	unsigned char a;
-
-	v4l2_dbg(1, debug, sd, "tda9875_set(%04x,%04x,%04x,%04x)\n",
-		tda->lvol, tda->rvol, tda->bass, tda->treble);
-
-	a = tda->lvol & 0xff;
-	tda9875_write(sd, TDA9875_MVL, a);
-	a =tda->rvol & 0xff;
-	tda9875_write(sd, TDA9875_MVR, a);
-	a =tda->bass & 0xff;
-	tda9875_write(sd, TDA9875_MBA, a);
-	a =tda->treble  & 0xff;
-	tda9875_write(sd, TDA9875_MTR, a);
-}
-
-static void do_tda9875_init(struct v4l2_subdev *sd)
-{
-	struct tda9875 *t = to_state(sd);
-
-	v4l2_dbg(1, debug, sd, "In tda9875_init\n");
-	tda9875_write(sd, TDA9875_CFG, 0xd0); /*reg de config 0 (reset)*/
-	tda9875_write(sd, TDA9875_MSR, 0x03);    /* Monitor 0b00000XXX*/
-	tda9875_write(sd, TDA9875_C1MSB, 0x00);  /*Car1(FM) MSB XMHz*/
-	tda9875_write(sd, TDA9875_C1MIB, 0x00);  /*Car1(FM) MIB XMHz*/
-	tda9875_write(sd, TDA9875_C1LSB, 0x00);  /*Car1(FM) LSB XMHz*/
-	tda9875_write(sd, TDA9875_C2MSB, 0x00);  /*Car2(NICAM) MSB XMHz*/
-	tda9875_write(sd, TDA9875_C2MIB, 0x00);  /*Car2(NICAM) MIB XMHz*/
-	tda9875_write(sd, TDA9875_C2LSB, 0x00);  /*Car2(NICAM) LSB XMHz*/
-	tda9875_write(sd, TDA9875_DCR, 0x00);    /*Demod config 0x00*/
-	tda9875_write(sd, TDA9875_DEEM, 0x44);   /*DE-Emph 0b0100 0100*/
-	tda9875_write(sd, TDA9875_FMAT, 0x00);   /*FM Matrix reg 0x00*/
-	tda9875_write(sd, TDA9875_SC1, 0x00);    /* SCART 1 (SC1)*/
-	tda9875_write(sd, TDA9875_SC2, 0x01);    /* SCART 2 (sc2)*/
-
-	tda9875_write(sd, TDA9875_CH1V, 0x10);  /* Channel volume 1 mute*/
-	tda9875_write(sd, TDA9875_CH2V, 0x10);  /* Channel volume 2 mute */
-	tda9875_write(sd, TDA9875_DACOS, 0x02); /* sig DAC i/o(in:nicam)*/
-	tda9875_write(sd, TDA9875_ADCIS, 0x6f); /* sig ADC input(in:mono)*/
-	tda9875_write(sd, TDA9875_LOSR, 0x00);  /* line out (in:mono)*/
-	tda9875_write(sd, TDA9875_AER, 0x00);   /*06 Effect (AVL+PSEUDO) */
-	tda9875_write(sd, TDA9875_MCS, 0x44);   /* Main ch select (DAC) */
-	tda9875_write(sd, TDA9875_MVL, 0x03);   /* Vol Main left 10dB */
-	tda9875_write(sd, TDA9875_MVR, 0x03);   /* Vol Main right 10dB*/
-	tda9875_write(sd, TDA9875_MBA, 0x00);   /* Main Bass Main 0dB*/
-	tda9875_write(sd, TDA9875_MTR, 0x00);   /* Main Treble Main 0dB*/
-	tda9875_write(sd, TDA9875_ACS, 0x44);   /* Aux chan select (dac)*/
-	tda9875_write(sd, TDA9875_AVL, 0x00);   /* Vol Aux left 0dB*/
-	tda9875_write(sd, TDA9875_AVR, 0x00);   /* Vol Aux right 0dB*/
-	tda9875_write(sd, TDA9875_ABA, 0x00);   /* Aux Bass Main 0dB*/
-	tda9875_write(sd, TDA9875_ATR, 0x00);   /* Aux Aigus Main 0dB*/
-
-	tda9875_write(sd, TDA9875_MUT, 0xcc);   /* General mute  */
-
-	t->lvol = t->rvol = 0;  	/* 0dB */
-	t->bass = 0; 			/* 0dB */
-	t->treble = 0;  		/* 0dB */
-	tda9875_set(sd);
-}
-
-
-static int tda9875_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
-{
-	struct tda9875 *t = to_state(sd);
-
-	switch (ctrl->id) {
-	case V4L2_CID_AUDIO_VOLUME:
-	{
-		int left = (t->lvol+84)*606;
-		int right = (t->rvol+84)*606;
-
-		ctrl->value=max(left,right);
-		return 0;
-	}
-	case V4L2_CID_AUDIO_BALANCE:
-	{
-		int left = (t->lvol+84)*606;
-		int right = (t->rvol+84)*606;
-		int volume = max(left,right);
-		int balance = (32768*min(left,right))/
-			      (volume ? volume : 1);
-		ctrl->value=(left<right)?
-			(65535-balance) : balance;
-		return 0;
-	}
-	case V4L2_CID_AUDIO_BASS:
-		ctrl->value = (t->bass+12)*2427;    /* min -12 max +15 */
-		return 0;
-	case V4L2_CID_AUDIO_TREBLE:
-		ctrl->value = (t->treble+12)*2730;/* min -12 max +12 */
-		return 0;
-	}
-	return -EINVAL;
-}
-
-static int tda9875_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
-{
-	struct tda9875 *t = to_state(sd);
-	int chvol = 0, volume = 0, balance = 0, left, right;
-
-	switch (ctrl->id) {
-	case V4L2_CID_AUDIO_VOLUME:
-		left = (t->lvol+84)*606;
-		right = (t->rvol+84)*606;
-
-		volume = max(left,right);
-		balance = (32768*min(left,right))/
-			      (volume ? volume : 1);
-		balance =(left<right)?
-			(65535-balance) : balance;
-
-		volume = ctrl->value;
-
-		chvol=1;
-		break;
-	case V4L2_CID_AUDIO_BALANCE:
-		left = (t->lvol+84)*606;
-		right = (t->rvol+84)*606;
-
-		volume=max(left,right);
-
-		balance = ctrl->value;
-
-		chvol=1;
-		break;
-	case V4L2_CID_AUDIO_BASS:
-		t->bass = ((ctrl->value/2400)-12) & 0xff;
-		if (t->bass > 15)
-			t->bass = 15;
-		if (t->bass < -12)
-			t->bass = -12 & 0xff;
-		break;
-	case V4L2_CID_AUDIO_TREBLE:
-		t->treble = ((ctrl->value/2700)-12) & 0xff;
-		if (t->treble > 12)
-			t->treble = 12;
-		if (t->treble < -12)
-			t->treble = -12 & 0xff;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	if (chvol) {
-		left = (min(65536 - balance,32768) *
-			volume) / 32768;
-		right = (min(balance,32768) *
-				volume) / 32768;
-		t->lvol = ((left/606)-84) & 0xff;
-		if (t->lvol > 24)
-			t->lvol = 24;
-		if (t->lvol < -84)
-			t->lvol = -84 & 0xff;
-
-		t->rvol = ((right/606)-84) & 0xff;
-		if (t->rvol > 24)
-			t->rvol = 24;
-		if (t->rvol < -84)
-			t->rvol = -84 & 0xff;
-	}
-
-	tda9875_set(sd);
-	return 0;
-}
-
-static int tda9875_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc)
-{
-	switch (qc->id) {
-	case V4L2_CID_AUDIO_VOLUME:
-		return v4l2_ctrl_query_fill(qc, 0, 65535, 65535 / 100, 58880);
-	case V4L2_CID_AUDIO_BASS:
-	case V4L2_CID_AUDIO_TREBLE:
-		return v4l2_ctrl_query_fill(qc, 0, 65535, 65535 / 100, 32768);
-	}
-	return -EINVAL;
-}
-
-/* ----------------------------------------------------------------------- */
-
-static const struct v4l2_subdev_core_ops tda9875_core_ops = {
-	.queryctrl = tda9875_queryctrl,
-	.g_ctrl = tda9875_g_ctrl,
-	.s_ctrl = tda9875_s_ctrl,
-};
-
-static const struct v4l2_subdev_ops tda9875_ops = {
-	.core = &tda9875_core_ops,
-};
-
-/* ----------------------------------------------------------------------- */
-
-
-/* *********************** *
- * i2c interface functions *
- * *********************** */
-
-static int tda9875_checkit(struct i2c_client *client, int addr)
-{
-	int dic, rev;
-
-	dic = i2c_read_register(client, addr, 254);
-	rev = i2c_read_register(client, addr, 255);
-
-	if (dic == 0 || dic == 2) { /* tda9875 and tda9875A */
-		v4l_info(client, "tda9875%s rev. %d detected at 0x%02x\n",
-			dic == 0 ? "" : "A", rev, addr << 1);
-		return 1;
-	}
-	v4l_info(client, "no such chip at 0x%02x (dic=0x%x rev=0x%x)\n",
-			addr << 1, dic, rev);
-	return 0;
-}
-
-static int tda9875_probe(struct i2c_client *client,
-			const struct i2c_device_id *id)
-{
-	struct tda9875 *t;
-	struct v4l2_subdev *sd;
-
-	v4l_info(client, "chip found @ 0x%02x (%s)\n",
-			client->addr << 1, client->adapter->name);
-
-	if (!tda9875_checkit(client, client->addr))
-		return -ENODEV;
-
-	t = kzalloc(sizeof(*t), GFP_KERNEL);
-	if (!t)
-		return -ENOMEM;
-	sd = &t->sd;
-	v4l2_i2c_subdev_init(sd, client, &tda9875_ops);
-
-	do_tda9875_init(sd);
-	return 0;
-}
-
-static int tda9875_remove(struct i2c_client *client)
-{
-	struct v4l2_subdev *sd = i2c_get_clientdata(client);
-
-	do_tda9875_init(sd);
-	v4l2_device_unregister_subdev(sd);
-	kfree(to_state(sd));
-	return 0;
-}
-
-static const struct i2c_device_id tda9875_id[] = {
-	{ "tda9875", 0 },
-	{ }
-};
-MODULE_DEVICE_TABLE(i2c, tda9875_id);
-
-static struct i2c_driver tda9875_driver = {
-	.driver = {
-		.owner	= THIS_MODULE,
-		.name	= "tda9875",
-	},
-	.probe		= tda9875_probe,
-	.remove		= tda9875_remove,
-	.id_table	= tda9875_id,
-};
-
-static __init int init_tda9875(void)
-{
-	return i2c_add_driver(&tda9875_driver);
-}
-
-static __exit void exit_tda9875(void)
-{
-	i2c_del_driver(&tda9875_driver);
-}
-
-module_init(init_tda9875);
-module_exit(exit_tda9875);
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/tea6415c.c linux-libre-2.6.38-gnu1/drivers/media/video/tea6415c.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/tea6415c.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/tea6415c.c	2011-03-14 21:20:32.000000000 -0400
@@ -148,7 +148,7 @@ static int tea6415c_probe(struct i2c_cli
 
 	/* let's see whether this adapter can support what we need */
 	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WRITE_BYTE))
-		return 0;
+		return -EIO;
 
 	v4l_info(client, "chip found @ 0x%x (%s)\n",
 			client->addr << 1, client->adapter->name);
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/timblogiw.c linux-libre-2.6.38-gnu1/drivers/media/video/timblogiw.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/timblogiw.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/timblogiw.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,893 @@
+/*
+ * timblogiw.c timberdale FPGA LogiWin Video In driver
+ * Copyright (c) 2009-2010 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.
+ *
+ * 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.
+ */
+
+/* Supports:
+ * Timberdale FPGA LogiWin Video In
+ */
+
+#include <linux/version.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/dmaengine.h>
+#include <linux/scatterlist.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/i2c.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-device.h>
+#include <media/videobuf-dma-contig.h>
+#include <media/timb_video.h>
+
+#define DRIVER_NAME			"timb-video"
+
+#define TIMBLOGIWIN_NAME		"Timberdale Video-In"
+#define TIMBLOGIW_VERSION_CODE		0x04
+
+#define TIMBLOGIW_LINES_PER_DESC	44
+#define TIMBLOGIW_MAX_VIDEO_MEM		16
+
+#define TIMBLOGIW_HAS_DECODER(lw)	(lw->pdata.encoder.module_name)
+
+
+struct timblogiw {
+	struct video_device		video_dev;
+	struct v4l2_device		v4l2_dev; /* mutual exclusion */
+	struct mutex			lock;
+	struct device			*dev;
+	struct timb_video_platform_data pdata;
+	struct v4l2_subdev		*sd_enc;	/* encoder */
+	bool				opened;
+};
+
+struct timblogiw_tvnorm {
+	v4l2_std_id std;
+	u16     width;
+	u16     height;
+	u8	fps;
+};
+
+struct timblogiw_fh {
+	struct videobuf_queue		vb_vidq;
+	struct timblogiw_tvnorm const	*cur_norm;
+	struct list_head		capture;
+	struct dma_chan			*chan;
+	spinlock_t			queue_lock; /* mutual exclusion */
+	unsigned int			frame_count;
+};
+
+struct timblogiw_buffer {
+	/* common v4l buffer stuff -- must be first */
+	struct videobuf_buffer	vb;
+	struct scatterlist	sg[16];
+	dma_cookie_t		cookie;
+	struct timblogiw_fh	*fh;
+};
+
+const struct timblogiw_tvnorm timblogiw_tvnorms[] = {
+	{
+		.std			= V4L2_STD_PAL,
+		.width			= 720,
+		.height			= 576,
+		.fps			= 25
+	},
+	{
+		.std			= V4L2_STD_NTSC,
+		.width			= 720,
+		.height			= 480,
+		.fps			= 30
+	}
+};
+
+static int timblogiw_bytes_per_line(const struct timblogiw_tvnorm *norm)
+{
+	return norm->width * 2;
+}
+
+
+static int timblogiw_frame_size(const struct timblogiw_tvnorm *norm)
+{
+	return norm->height * timblogiw_bytes_per_line(norm);
+}
+
+static const struct timblogiw_tvnorm *timblogiw_get_norm(const v4l2_std_id std)
+{
+	int i;
+	for (i = 0; i < ARRAY_SIZE(timblogiw_tvnorms); i++)
+		if (timblogiw_tvnorms[i].std & std)
+			return timblogiw_tvnorms + i;
+
+	/* default to first element */
+	return timblogiw_tvnorms;
+}
+
+static void timblogiw_dma_cb(void *data)
+{
+	struct timblogiw_buffer *buf = data;
+	struct timblogiw_fh *fh = buf->fh;
+	struct videobuf_buffer *vb = &buf->vb;
+
+	spin_lock(&fh->queue_lock);
+
+	/* mark the transfer done */
+	buf->cookie = -1;
+
+	fh->frame_count++;
+
+	if (vb->state != VIDEOBUF_ERROR) {
+		list_del(&vb->queue);
+		do_gettimeofday(&vb->ts);
+		vb->field_count = fh->frame_count * 2;
+		vb->state = VIDEOBUF_DONE;
+
+		wake_up(&vb->done);
+	}
+
+	if (!list_empty(&fh->capture)) {
+		vb = list_entry(fh->capture.next, struct videobuf_buffer,
+			queue);
+		vb->state = VIDEOBUF_ACTIVE;
+	}
+
+	spin_unlock(&fh->queue_lock);
+}
+
+static bool timblogiw_dma_filter_fn(struct dma_chan *chan, void *filter_param)
+{
+	return chan->chan_id == (uintptr_t)filter_param;
+}
+
+/* IOCTL functions */
+
+static int timblogiw_g_fmt(struct file *file, void  *priv,
+	struct v4l2_format *format)
+{
+	struct video_device *vdev = video_devdata(file);
+	struct timblogiw *lw = video_get_drvdata(vdev);
+	struct timblogiw_fh *fh = priv;
+
+	dev_dbg(&vdev->dev, "%s entry\n", __func__);
+
+	if (format->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return -EINVAL;
+
+	mutex_lock(&lw->lock);
+
+	format->fmt.pix.width = fh->cur_norm->width;
+	format->fmt.pix.height = fh->cur_norm->height;
+	format->fmt.pix.pixelformat = V4L2_PIX_FMT_UYVY;
+	format->fmt.pix.bytesperline = timblogiw_bytes_per_line(fh->cur_norm);
+	format->fmt.pix.sizeimage = timblogiw_frame_size(fh->cur_norm);
+	format->fmt.pix.field = V4L2_FIELD_NONE;
+
+	mutex_unlock(&lw->lock);
+
+	return 0;
+}
+
+static int timblogiw_try_fmt(struct file *file, void  *priv,
+	struct v4l2_format *format)
+{
+	struct video_device *vdev = video_devdata(file);
+	struct v4l2_pix_format *pix = &format->fmt.pix;
+
+	dev_dbg(&vdev->dev,
+		"%s - width=%d, height=%d, pixelformat=%d, field=%d\n"
+		"bytes per line %d, size image: %d, colorspace: %d\n",
+		__func__,
+		pix->width, pix->height, pix->pixelformat, pix->field,
+		pix->bytesperline, pix->sizeimage, pix->colorspace);
+
+	if (format->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return -EINVAL;
+
+	if (pix->field != V4L2_FIELD_NONE)
+		return -EINVAL;
+
+	if (pix->pixelformat != V4L2_PIX_FMT_UYVY)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int timblogiw_s_fmt(struct file *file, void  *priv,
+	struct v4l2_format *format)
+{
+	struct video_device *vdev = video_devdata(file);
+	struct timblogiw *lw = video_get_drvdata(vdev);
+	struct timblogiw_fh *fh = priv;
+	struct v4l2_pix_format *pix = &format->fmt.pix;
+	int err;
+
+	mutex_lock(&lw->lock);
+
+	err = timblogiw_try_fmt(file, priv, format);
+	if (err)
+		goto out;
+
+	if (videobuf_queue_is_busy(&fh->vb_vidq)) {
+		dev_err(&vdev->dev, "%s queue busy\n", __func__);
+		err = -EBUSY;
+		goto out;
+	}
+
+	pix->width = fh->cur_norm->width;
+	pix->height = fh->cur_norm->height;
+
+out:
+	mutex_unlock(&lw->lock);
+	return err;
+}
+
+static int timblogiw_querycap(struct file *file, void  *priv,
+	struct v4l2_capability *cap)
+{
+	struct video_device *vdev = video_devdata(file);
+
+	dev_dbg(&vdev->dev, "%s: Entry\n",  __func__);
+	memset(cap, 0, sizeof(*cap));
+	strncpy(cap->card, TIMBLOGIWIN_NAME, sizeof(cap->card)-1);
+	strncpy(cap->driver, DRIVER_NAME, sizeof(cap->driver) - 1);
+	strlcpy(cap->bus_info, vdev->name, sizeof(cap->bus_info));
+	cap->version = TIMBLOGIW_VERSION_CODE;
+	cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING |
+		V4L2_CAP_READWRITE;
+
+	return 0;
+}
+
+static int timblogiw_enum_fmt(struct file *file, void  *priv,
+	struct v4l2_fmtdesc *fmt)
+{
+	struct video_device *vdev = video_devdata(file);
+
+	dev_dbg(&vdev->dev, "%s, index: %d\n",  __func__, fmt->index);
+
+	if (fmt->index != 0)
+		return -EINVAL;
+	memset(fmt, 0, sizeof(*fmt));
+	fmt->index = 0;
+	fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	strncpy(fmt->description, "4:2:2, packed, YUYV",
+		sizeof(fmt->description)-1);
+	fmt->pixelformat = V4L2_PIX_FMT_UYVY;
+
+	return 0;
+}
+
+static int timblogiw_g_parm(struct file *file, void *priv,
+	struct v4l2_streamparm *sp)
+{
+	struct timblogiw_fh *fh = priv;
+	struct v4l2_captureparm *cp = &sp->parm.capture;
+
+	cp->capability = V4L2_CAP_TIMEPERFRAME;
+	cp->timeperframe.numerator = 1;
+	cp->timeperframe.denominator = fh->cur_norm->fps;
+
+	return 0;
+}
+
+static int timblogiw_reqbufs(struct file *file, void  *priv,
+	struct v4l2_requestbuffers *rb)
+{
+	struct video_device *vdev = video_devdata(file);
+	struct timblogiw_fh *fh = priv;
+
+	dev_dbg(&vdev->dev, "%s: entry\n",  __func__);
+
+	return videobuf_reqbufs(&fh->vb_vidq, rb);
+}
+
+static int timblogiw_querybuf(struct file *file, void  *priv,
+	struct v4l2_buffer *b)
+{
+	struct video_device *vdev = video_devdata(file);
+	struct timblogiw_fh *fh = priv;
+
+	dev_dbg(&vdev->dev, "%s: entry\n",  __func__);
+
+	return videobuf_querybuf(&fh->vb_vidq, b);
+}
+
+static int timblogiw_qbuf(struct file *file, void  *priv, struct v4l2_buffer *b)
+{
+	struct video_device *vdev = video_devdata(file);
+	struct timblogiw_fh *fh = priv;
+
+	dev_dbg(&vdev->dev, "%s: entry\n",  __func__);
+
+	return videobuf_qbuf(&fh->vb_vidq, b);
+}
+
+static int timblogiw_dqbuf(struct file *file, void  *priv,
+	struct v4l2_buffer *b)
+{
+	struct video_device *vdev = video_devdata(file);
+	struct timblogiw_fh *fh = priv;
+
+	dev_dbg(&vdev->dev, "%s: entry\n",  __func__);
+
+	return videobuf_dqbuf(&fh->vb_vidq, b, file->f_flags & O_NONBLOCK);
+}
+
+static int timblogiw_g_std(struct file *file, void  *priv, v4l2_std_id *std)
+{
+	struct video_device *vdev = video_devdata(file);
+	struct timblogiw_fh *fh = priv;
+
+	dev_dbg(&vdev->dev, "%s: entry\n",  __func__);
+
+	*std = fh->cur_norm->std;
+	return 0;
+}
+
+static int timblogiw_s_std(struct file *file, void  *priv, v4l2_std_id *std)
+{
+	struct video_device *vdev = video_devdata(file);
+	struct timblogiw *lw = video_get_drvdata(vdev);
+	struct timblogiw_fh *fh = priv;
+	int err = 0;
+
+	dev_dbg(&vdev->dev, "%s: entry\n",  __func__);
+
+	mutex_lock(&lw->lock);
+
+	if (TIMBLOGIW_HAS_DECODER(lw))
+		err = v4l2_subdev_call(lw->sd_enc, core, s_std, *std);
+
+	if (!err)
+		fh->cur_norm = timblogiw_get_norm(*std);
+
+	mutex_unlock(&lw->lock);
+
+	return err;
+}
+
+static int timblogiw_enuminput(struct file *file, void  *priv,
+	struct v4l2_input *inp)
+{
+	struct video_device *vdev = video_devdata(file);
+	int i;
+
+	dev_dbg(&vdev->dev, "%s: Entry\n",  __func__);
+
+	if (inp->index != 0)
+		return -EINVAL;
+
+	inp->index = 0;
+
+	strncpy(inp->name, "Timb input 1", sizeof(inp->name) - 1);
+	inp->type = V4L2_INPUT_TYPE_CAMERA;
+
+	inp->std = 0;
+	for (i = 0; i < ARRAY_SIZE(timblogiw_tvnorms); i++)
+		inp->std |= timblogiw_tvnorms[i].std;
+
+	return 0;
+}
+
+static int timblogiw_g_input(struct file *file, void  *priv,
+	unsigned int *input)
+{
+	struct video_device *vdev = video_devdata(file);
+
+	dev_dbg(&vdev->dev, "%s: Entry\n",  __func__);
+
+	*input = 0;
+
+	return 0;
+}
+
+static int timblogiw_s_input(struct file *file, void  *priv, unsigned int input)
+{
+	struct video_device *vdev = video_devdata(file);
+
+	dev_dbg(&vdev->dev, "%s: Entry\n",  __func__);
+
+	if (input != 0)
+		return -EINVAL;
+	return 0;
+}
+
+static int timblogiw_streamon(struct file *file, void  *priv, unsigned int type)
+{
+	struct video_device *vdev = video_devdata(file);
+	struct timblogiw_fh *fh = priv;
+
+	dev_dbg(&vdev->dev, "%s: entry\n",  __func__);
+
+	if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+		dev_dbg(&vdev->dev, "%s - No capture device\n", __func__);
+		return -EINVAL;
+	}
+
+	fh->frame_count = 0;
+	return videobuf_streamon(&fh->vb_vidq);
+}
+
+static int timblogiw_streamoff(struct file *file, void  *priv,
+	unsigned int type)
+{
+	struct video_device *vdev = video_devdata(file);
+	struct timblogiw_fh *fh = priv;
+
+	dev_dbg(&vdev->dev, "%s entry\n",  __func__);
+
+	if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return -EINVAL;
+
+	return videobuf_streamoff(&fh->vb_vidq);
+}
+
+static int timblogiw_querystd(struct file *file, void  *priv, v4l2_std_id *std)
+{
+	struct video_device *vdev = video_devdata(file);
+	struct timblogiw *lw = video_get_drvdata(vdev);
+	struct timblogiw_fh *fh = priv;
+
+	dev_dbg(&vdev->dev, "%s entry\n",  __func__);
+
+	if (TIMBLOGIW_HAS_DECODER(lw))
+		return v4l2_subdev_call(lw->sd_enc, video, querystd, std);
+	else {
+		*std = fh->cur_norm->std;
+		return 0;
+	}
+}
+
+static int timblogiw_enum_framesizes(struct file *file, void  *priv,
+	struct v4l2_frmsizeenum *fsize)
+{
+	struct video_device *vdev = video_devdata(file);
+	struct timblogiw_fh *fh = priv;
+
+	dev_dbg(&vdev->dev, "%s - index: %d, format: %d\n",  __func__,
+		fsize->index, fsize->pixel_format);
+
+	if ((fsize->index != 0) ||
+		(fsize->pixel_format != V4L2_PIX_FMT_UYVY))
+		return -EINVAL;
+
+	fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
+	fsize->discrete.width = fh->cur_norm->width;
+	fsize->discrete.height = fh->cur_norm->height;
+
+	return 0;
+}
+
+/* Video buffer functions */
+
+static int buffer_setup(struct videobuf_queue *vq, unsigned int *count,
+	unsigned int *size)
+{
+	struct timblogiw_fh *fh = vq->priv_data;
+
+	*size = timblogiw_frame_size(fh->cur_norm);
+
+	if (!*count)
+		*count = 32;
+
+	while (*size * *count > TIMBLOGIW_MAX_VIDEO_MEM * 1024 * 1024)
+		(*count)--;
+
+	return 0;
+}
+
+static int buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb,
+	enum v4l2_field field)
+{
+	struct timblogiw_fh *fh = vq->priv_data;
+	struct timblogiw_buffer *buf = container_of(vb, struct timblogiw_buffer,
+		vb);
+	unsigned int data_size = timblogiw_frame_size(fh->cur_norm);
+	int err = 0;
+
+	if (vb->baddr && vb->bsize < data_size)
+		/* User provided buffer, but it is too small */
+		return -ENOMEM;
+
+	vb->size = data_size;
+	vb->width = fh->cur_norm->width;
+	vb->height = fh->cur_norm->height;
+	vb->field = field;
+
+	if (vb->state == VIDEOBUF_NEEDS_INIT) {
+		int i;
+		unsigned int size;
+		unsigned int bytes_per_desc = TIMBLOGIW_LINES_PER_DESC *
+			timblogiw_bytes_per_line(fh->cur_norm);
+		dma_addr_t addr;
+
+		sg_init_table(buf->sg, ARRAY_SIZE(buf->sg));
+
+		err = videobuf_iolock(vq, vb, NULL);
+		if (err)
+			goto err;
+
+		addr = videobuf_to_dma_contig(vb);
+		for (i = 0, size = 0; size < data_size; i++) {
+			sg_dma_address(buf->sg + i) = addr + size;
+			size += bytes_per_desc;
+			sg_dma_len(buf->sg + i) = (size > data_size) ?
+				(bytes_per_desc - (size - data_size)) :
+				bytes_per_desc;
+		}
+
+		vb->state = VIDEOBUF_PREPARED;
+		buf->cookie = -1;
+		buf->fh = fh;
+	}
+
+	return 0;
+
+err:
+	videobuf_dma_contig_free(vq, vb);
+	vb->state = VIDEOBUF_NEEDS_INIT;
+	return err;
+}
+
+static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
+{
+	struct timblogiw_fh *fh = vq->priv_data;
+	struct timblogiw_buffer *buf = container_of(vb, struct timblogiw_buffer,
+		vb);
+	struct dma_async_tx_descriptor *desc;
+	int sg_elems;
+	int bytes_per_desc = TIMBLOGIW_LINES_PER_DESC *
+		timblogiw_bytes_per_line(fh->cur_norm);
+
+	sg_elems = timblogiw_frame_size(fh->cur_norm) / bytes_per_desc;
+	sg_elems +=
+		(timblogiw_frame_size(fh->cur_norm) % bytes_per_desc) ? 1 : 0;
+
+	if (list_empty(&fh->capture))
+		vb->state = VIDEOBUF_ACTIVE;
+	else
+		vb->state = VIDEOBUF_QUEUED;
+
+	list_add_tail(&vb->queue, &fh->capture);
+
+	spin_unlock_irq(&fh->queue_lock);
+
+	desc = fh->chan->device->device_prep_slave_sg(fh->chan,
+		buf->sg, sg_elems, DMA_FROM_DEVICE,
+		DMA_PREP_INTERRUPT | DMA_COMPL_SKIP_SRC_UNMAP);
+	if (!desc) {
+		spin_lock_irq(&fh->queue_lock);
+		list_del_init(&vb->queue);
+		vb->state = VIDEOBUF_PREPARED;
+		return;
+	}
+
+	desc->callback_param = buf;
+	desc->callback = timblogiw_dma_cb;
+
+	buf->cookie = desc->tx_submit(desc);
+
+	spin_lock_irq(&fh->queue_lock);
+}
+
+static void buffer_release(struct videobuf_queue *vq,
+	struct videobuf_buffer *vb)
+{
+	struct timblogiw_fh *fh = vq->priv_data;
+	struct timblogiw_buffer *buf = container_of(vb, struct timblogiw_buffer,
+		vb);
+
+	videobuf_waiton(vq, vb, 0, 0);
+	if (buf->cookie >= 0)
+		dma_sync_wait(fh->chan, buf->cookie);
+
+	videobuf_dma_contig_free(vq, vb);
+	vb->state = VIDEOBUF_NEEDS_INIT;
+}
+
+static struct videobuf_queue_ops timblogiw_video_qops = {
+	.buf_setup      = buffer_setup,
+	.buf_prepare    = buffer_prepare,
+	.buf_queue      = buffer_queue,
+	.buf_release    = buffer_release,
+};
+
+/* Device Operations functions */
+
+static int timblogiw_open(struct file *file)
+{
+	struct video_device *vdev = video_devdata(file);
+	struct timblogiw *lw = video_get_drvdata(vdev);
+	struct timblogiw_fh *fh;
+	v4l2_std_id std;
+	dma_cap_mask_t mask;
+	int err = 0;
+
+	dev_dbg(&vdev->dev, "%s: entry\n", __func__);
+
+	mutex_lock(&lw->lock);
+	if (lw->opened) {
+		err = -EBUSY;
+		goto out;
+	}
+
+	if (TIMBLOGIW_HAS_DECODER(lw) && !lw->sd_enc) {
+		struct i2c_adapter *adapt;
+
+		/* find the video decoder */
+		adapt = i2c_get_adapter(lw->pdata.i2c_adapter);
+		if (!adapt) {
+			dev_err(&vdev->dev, "No I2C bus #%d\n",
+				lw->pdata.i2c_adapter);
+			err = -ENODEV;
+			goto out;
+		}
+
+		/* now find the encoder */
+		lw->sd_enc = v4l2_i2c_new_subdev_board(&lw->v4l2_dev, adapt,
+			lw->pdata.encoder.info, NULL);
+
+		i2c_put_adapter(adapt);
+
+		if (!lw->sd_enc) {
+			dev_err(&vdev->dev, "Failed to get encoder: %s\n",
+				lw->pdata.encoder.module_name);
+			err = -ENODEV;
+			goto out;
+		}
+	}
+
+	fh = kzalloc(sizeof(*fh), GFP_KERNEL);
+	if (!fh) {
+		err = -ENOMEM;
+		goto out;
+	}
+
+	fh->cur_norm = timblogiw_tvnorms;
+	timblogiw_querystd(file, fh, &std);
+	fh->cur_norm = timblogiw_get_norm(std);
+
+	INIT_LIST_HEAD(&fh->capture);
+	spin_lock_init(&fh->queue_lock);
+
+	dma_cap_zero(mask);
+	dma_cap_set(DMA_SLAVE, mask);
+	dma_cap_set(DMA_PRIVATE, mask);
+
+	/* find the DMA channel */
+	fh->chan = dma_request_channel(mask, timblogiw_dma_filter_fn,
+			(void *)(uintptr_t)lw->pdata.dma_channel);
+	if (!fh->chan) {
+		dev_err(&vdev->dev, "Failed to get DMA channel\n");
+		kfree(fh);
+		err = -ENODEV;
+		goto out;
+	}
+
+	file->private_data = fh;
+	videobuf_queue_dma_contig_init(&fh->vb_vidq,
+		&timblogiw_video_qops, lw->dev, &fh->queue_lock,
+		V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_NONE,
+		sizeof(struct timblogiw_buffer), fh, NULL);
+
+	lw->opened = true;
+out:
+	mutex_unlock(&lw->lock);
+
+	return err;
+}
+
+static int timblogiw_close(struct file *file)
+{
+	struct video_device *vdev = video_devdata(file);
+	struct timblogiw *lw = video_get_drvdata(vdev);
+	struct timblogiw_fh *fh = file->private_data;
+
+	dev_dbg(&vdev->dev, "%s: Entry\n",  __func__);
+
+	videobuf_stop(&fh->vb_vidq);
+	videobuf_mmap_free(&fh->vb_vidq);
+
+	dma_release_channel(fh->chan);
+
+	kfree(fh);
+
+	mutex_lock(&lw->lock);
+	lw->opened = false;
+	mutex_unlock(&lw->lock);
+	return 0;
+}
+
+static ssize_t timblogiw_read(struct file *file, char __user *data,
+	size_t count, loff_t *ppos)
+{
+	struct video_device *vdev = video_devdata(file);
+	struct timblogiw_fh *fh = file->private_data;
+
+	dev_dbg(&vdev->dev, "%s: entry\n",  __func__);
+
+	return videobuf_read_stream(&fh->vb_vidq, data, count, ppos, 0,
+		file->f_flags & O_NONBLOCK);
+}
+
+static unsigned int timblogiw_poll(struct file *file,
+	struct poll_table_struct *wait)
+{
+	struct video_device *vdev = video_devdata(file);
+	struct timblogiw_fh *fh = file->private_data;
+
+	dev_dbg(&vdev->dev, "%s: entry\n",  __func__);
+
+	return videobuf_poll_stream(file, &fh->vb_vidq, wait);
+}
+
+static int timblogiw_mmap(struct file *file, struct vm_area_struct *vma)
+{
+	struct video_device *vdev = video_devdata(file);
+	struct timblogiw_fh *fh = file->private_data;
+
+	dev_dbg(&vdev->dev, "%s: entry\n", __func__);
+
+	return videobuf_mmap_mapper(&fh->vb_vidq, vma);
+}
+
+/* Platform device functions */
+
+static __devinitconst struct v4l2_ioctl_ops timblogiw_ioctl_ops = {
+	.vidioc_querycap		= timblogiw_querycap,
+	.vidioc_enum_fmt_vid_cap	= timblogiw_enum_fmt,
+	.vidioc_g_fmt_vid_cap		= timblogiw_g_fmt,
+	.vidioc_try_fmt_vid_cap		= timblogiw_try_fmt,
+	.vidioc_s_fmt_vid_cap		= timblogiw_s_fmt,
+	.vidioc_g_parm			= timblogiw_g_parm,
+	.vidioc_reqbufs			= timblogiw_reqbufs,
+	.vidioc_querybuf		= timblogiw_querybuf,
+	.vidioc_qbuf			= timblogiw_qbuf,
+	.vidioc_dqbuf			= timblogiw_dqbuf,
+	.vidioc_g_std			= timblogiw_g_std,
+	.vidioc_s_std			= timblogiw_s_std,
+	.vidioc_enum_input		= timblogiw_enuminput,
+	.vidioc_g_input			= timblogiw_g_input,
+	.vidioc_s_input			= timblogiw_s_input,
+	.vidioc_streamon		= timblogiw_streamon,
+	.vidioc_streamoff		= timblogiw_streamoff,
+	.vidioc_querystd		= timblogiw_querystd,
+	.vidioc_enum_framesizes		= timblogiw_enum_framesizes,
+};
+
+static __devinitconst struct v4l2_file_operations timblogiw_fops = {
+	.owner		= THIS_MODULE,
+	.open		= timblogiw_open,
+	.release	= timblogiw_close,
+	.unlocked_ioctl		= video_ioctl2, /* V4L2 ioctl handler */
+	.mmap		= timblogiw_mmap,
+	.read		= timblogiw_read,
+	.poll		= timblogiw_poll,
+};
+
+static __devinitconst struct video_device timblogiw_template = {
+	.name		= TIMBLOGIWIN_NAME,
+	.fops		= &timblogiw_fops,
+	.ioctl_ops	= &timblogiw_ioctl_ops,
+	.release	= video_device_release_empty,
+	.minor		= -1,
+	.tvnorms	= V4L2_STD_PAL | V4L2_STD_NTSC
+};
+
+static int __devinit timblogiw_probe(struct platform_device *pdev)
+{
+	int err;
+	struct timblogiw *lw = NULL;
+	struct timb_video_platform_data *pdata = pdev->dev.platform_data;
+
+	if (!pdata) {
+		dev_err(&pdev->dev, "No platform data\n");
+		err = -EINVAL;
+		goto err;
+	}
+
+	if (!pdata->encoder.module_name)
+		dev_info(&pdev->dev, "Running without decoder\n");
+
+	lw = kzalloc(sizeof(*lw), GFP_KERNEL);
+	if (!lw) {
+		err = -ENOMEM;
+		goto err;
+	}
+
+	if (pdev->dev.parent)
+		lw->dev = pdev->dev.parent;
+	else
+		lw->dev = &pdev->dev;
+
+	memcpy(&lw->pdata, pdata, sizeof(lw->pdata));
+
+	mutex_init(&lw->lock);
+
+	lw->video_dev = timblogiw_template;
+
+	strlcpy(lw->v4l2_dev.name, DRIVER_NAME, sizeof(lw->v4l2_dev.name));
+	err = v4l2_device_register(NULL, &lw->v4l2_dev);
+	if (err)
+		goto err_register;
+
+	lw->video_dev.v4l2_dev = &lw->v4l2_dev;
+
+	platform_set_drvdata(pdev, lw);
+	video_set_drvdata(&lw->video_dev, lw);
+
+	err = video_register_device(&lw->video_dev, VFL_TYPE_GRABBER, 0);
+	if (err) {
+		dev_err(&pdev->dev, "Error reg video: %d\n", err);
+		goto err_request;
+	}
+
+
+	return 0;
+
+err_request:
+	platform_set_drvdata(pdev, NULL);
+	v4l2_device_unregister(&lw->v4l2_dev);
+err_register:
+	kfree(lw);
+err:
+	dev_err(&pdev->dev, "Failed to register: %d\n", err);
+
+	return err;
+}
+
+static int __devexit timblogiw_remove(struct platform_device *pdev)
+{
+	struct timblogiw *lw = platform_get_drvdata(pdev);
+
+	video_unregister_device(&lw->video_dev);
+
+	v4l2_device_unregister(&lw->v4l2_dev);
+
+	kfree(lw);
+
+	platform_set_drvdata(pdev, NULL);
+
+	return 0;
+}
+
+static struct platform_driver timblogiw_platform_driver = {
+	.driver = {
+		.name	= DRIVER_NAME,
+		.owner	= THIS_MODULE,
+	},
+	.probe		= timblogiw_probe,
+	.remove		= __devexit_p(timblogiw_remove),
+};
+
+/* Module functions */
+
+static int __init timblogiw_init(void)
+{
+	return platform_driver_register(&timblogiw_platform_driver);
+}
+
+static void __exit timblogiw_exit(void)
+{
+	platform_driver_unregister(&timblogiw_platform_driver);
+}
+
+module_init(timblogiw_init);
+module_exit(timblogiw_exit);
+
+MODULE_DESCRIPTION(TIMBLOGIWIN_NAME);
+MODULE_AUTHOR("Pelagicore AB <info@pelagicore.com>");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:"DRIVER_NAME);
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/tlg2300/Kconfig linux-libre-2.6.38-gnu1/drivers/media/video/tlg2300/Kconfig
--- linux-libre-2.6.37-gnu1/drivers/media/video/tlg2300/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/tlg2300/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -1,9 +1,9 @@
 config VIDEO_TLG2300
 	tristate "Telegent TLG2300 USB video capture support"
-	depends on VIDEO_DEV && I2C && INPUT && SND && DVB_CORE
+	depends on VIDEO_DEV && I2C && SND && DVB_CORE
 	select VIDEO_TUNER
 	select VIDEO_TVEEPROM
-	depends on VIDEO_IR
+	depends on RC_CORE
 	select VIDEOBUF_VMALLOC
 	select SND_PCM
 	select VIDEOBUF_DVB
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/tlg2300/pd-main.c linux-libre-2.6.38-gnu1/drivers/media/video/tlg2300/pd-main.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/tlg2300/pd-main.c	2013-05-03 03:57:24.000000000 -0400
+++ linux-libre-2.6.38-gnu1/drivers/media/video/tlg2300/pd-main.c	2013-05-03 01:57:13.000000000 -0400
@@ -452,7 +452,8 @@ static int poseidon_probe(struct usb_int
 
 	device_init_wakeup(&udev->dev, 1);
 #ifdef CONFIG_PM
-	pd->udev->autosuspend_delay = HZ * PM_SUSPEND_DELAY;
+	pm_runtime_set_autosuspend_delay(&pd->udev->dev,
+			1000 * PM_SUSPEND_DELAY);
 	usb_enable_autosuspend(pd->udev);
 
 	if (in_hibernation(pd)) {
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/tlg2300/pd-video.c linux-libre-2.6.38-gnu1/drivers/media/video/tlg2300/pd-video.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/tlg2300/pd-video.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/tlg2300/pd-video.c	2011-03-14 21:20:32.000000000 -0400
@@ -512,19 +512,20 @@ int alloc_bulk_urbs_generic(struct urb *
 			int buf_size, gfp_t gfp_flags,
 			usb_complete_t complete_fn, void *context)
 {
-	struct urb *urb;
-	void *mem;
-	int i;
+	int i = 0;
 
-	for (i = 0; i < num; i++) {
-		urb = usb_alloc_urb(0, gfp_flags);
+	for (; i < num; i++) {
+		void *mem;
+		struct urb *urb = usb_alloc_urb(0, gfp_flags);
 		if (urb == NULL)
 			return i;
 
 		mem = usb_alloc_coherent(udev, buf_size, gfp_flags,
 					 &urb->transfer_dma);
-		if (mem == NULL)
+		if (mem == NULL) {
+			usb_free_urb(urb);
 			return i;
+		}
 
 		usb_fill_bulk_urb(urb, udev, usb_rcvbulkpipe(udev, ep_addr),
 				mem, buf_size, complete_fn, context);
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/tvp7002.c linux-libre-2.6.38-gnu1/drivers/media/video/tvp7002.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/tvp7002.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/tvp7002.c	2011-03-14 21:20:32.000000000 -0400
@@ -789,7 +789,7 @@ static int tvp7002_query_dv_preset(struc
  * Get the value of a TVP7002 decoder device register.
  * Returns zero when successful, -EINVAL if register read fails or
  * access to I2C client fails, -EPERM if the call is not allowed
- * by diabled CAP_SYS_ADMIN.
+ * by disabled CAP_SYS_ADMIN.
  */
 static int tvp7002_g_register(struct v4l2_subdev *sd,
 						struct v4l2_dbg_register *reg)
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/usbvideo/ibmcam.c linux-libre-2.6.38-gnu1/drivers/media/video/usbvideo/ibmcam.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/usbvideo/ibmcam.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/usbvideo/ibmcam.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,3977 +0,0 @@
-/*
- * USB IBM C-It Video Camera driver
- *
- * Supports Xirlink C-It Video Camera, IBM PC Camera,
- * IBM NetCamera and Veo Stingray.
- *
- * This driver is based on earlier work of:
- *
- * (C) Copyright 1999 Johannes Erdfelt
- * (C) Copyright 1999 Randy Dunlap
- *
- * 5/24/00 Removed optional (and unnecessary) locking of the driver while
- * the device remains plugged in. Corrected race conditions in ibmcam_open
- * and ibmcam_probe() routines using this as a guideline:
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-
-#include "usbvideo.h"
-
-#define IBMCAM_VENDOR_ID	0x0545
-#define IBMCAM_PRODUCT_ID	0x8080
-#define NETCAM_PRODUCT_ID	0x8002	/* IBM NetCamera, close to model 2 */
-#define VEO_800C_PRODUCT_ID	0x800C	/* Veo Stingray, repackaged Model 2 */
-#define VEO_800D_PRODUCT_ID	0x800D	/* Veo Stingray, repackaged Model 4 */
-
-#define MAX_IBMCAM		4	/* How many devices we allow to connect */
-#define USES_IBMCAM_PUTPIXEL    0       /* 0=Fast/oops 1=Slow/secure */
-
-/* Header signatures */
-
-/* Model 1 header: 00 FF 00 xx */
-#define HDRSIG_MODEL1_128x96	0x06	/* U Y V Y ... */
-#define HDRSIG_MODEL1_176x144	0x0e	/* U Y V Y ... */
-#define HDRSIG_MODEL1_352x288	0x00	/* V Y U Y ... */
-
-#define	IBMCAM_MODEL_1	1	/* XVP-501, 3 interfaces, rev. 0.02 */
-#define IBMCAM_MODEL_2	2	/* KSX-X9903, 2 interfaces, rev. 3.0a */
-#define IBMCAM_MODEL_3	3	/* KSX-X9902, 2 interfaces, rev. 3.01 */
-#define	IBMCAM_MODEL_4	4	/* IBM NetCamera, 0545/8002/3.0a */
-
-/* Video sizes supported */
-#define	VIDEOSIZE_128x96	VIDEOSIZE(128, 96)
-#define	VIDEOSIZE_176x144	VIDEOSIZE(176,144)
-#define	VIDEOSIZE_352x288	VIDEOSIZE(352,288)
-#define	VIDEOSIZE_320x240	VIDEOSIZE(320,240)
-#define	VIDEOSIZE_352x240	VIDEOSIZE(352,240)
-#define	VIDEOSIZE_640x480	VIDEOSIZE(640,480)
-#define	VIDEOSIZE_160x120	VIDEOSIZE(160,120)
-
-/* Video sizes supported */
-enum {
-	SIZE_128x96 = 0,
-	SIZE_160x120,
-	SIZE_176x144,
-	SIZE_320x240,
-	SIZE_352x240,
-	SIZE_352x288,
-	SIZE_640x480,
-	/* Add/remove/rearrange items before this line */
-	SIZE_LastItem
-};
-
-/*
- * This structure lives in uvd->user field.
- */
-typedef struct {
-	int initialized;	/* Had we already sent init sequence? */
-	int camera_model;	/* What type of IBM camera we got? */
-	int has_hdr;
-} ibmcam_t;
-#define	IBMCAM_T(uvd)	((ibmcam_t *)((uvd)->user_data))
-
-static struct usbvideo *cams;
-
-static int debug;
-
-static int flags; /* = FLAGS_DISPLAY_HINTS | FLAGS_OVERLAY_STATS; */
-
-static const int min_canvasWidth  = 8;
-static const int min_canvasHeight = 4;
-
-static int lighting = 1; /* Medium */
-
-#define SHARPNESS_MIN	0
-#define SHARPNESS_MAX	6
-static int sharpness = 4; /* Low noise, good details */
-
-#define FRAMERATE_MIN	0
-#define FRAMERATE_MAX	6
-static int framerate = -1;
-
-static int size = SIZE_352x288;
-
-/*
- * Here we define several initialization variables. They may
- * be used to automatically set color, hue, brightness and
- * contrast to desired values. This is particularly useful in
- * case of webcams (which have no controls and no on-screen
- * output) and also when a client V4L software is used that
- * does not have some of those controls. In any case it's
- * good to have startup values as options.
- *
- * These values are all in [0..255] range. This simplifies
- * operation. Note that actual values of V4L variables may
- * be scaled up (as much as << 8). User can see that only
- * on overlay output, however, or through a V4L client.
- */
-static int init_brightness = 128;
-static int init_contrast = 192;
-static int init_color = 128;
-static int init_hue = 128;
-static int hue_correction = 128;
-
-/* Settings for camera model 2 */
-static int init_model2_rg2 = -1;
-static int init_model2_sat = -1;
-static int init_model2_yb = -1;
-
-/* 01.01.08 - Added for RCA video in support -LO */
-/* Settings for camera model 3 */
-static int init_model3_input;
-
-module_param(debug, int, 0);
-MODULE_PARM_DESC(debug, "Debug level: 0-9 (default=0)");
-module_param(flags, int, 0);
-MODULE_PARM_DESC(flags, "Bitfield: 0=VIDIOCSYNC, 1=B/W, 2=show hints, 3=show stats, 4=test pattern, 5=separate frames, 6=clean frames");
-module_param(framerate, int, 0);
-MODULE_PARM_DESC(framerate, "Framerate setting: 0=slowest, 6=fastest (default=2)");
-module_param(lighting, int, 0);
-MODULE_PARM_DESC(lighting, "Photosensitivity: 0=bright, 1=medium (default), 2=low light");
-module_param(sharpness, int, 0);
-MODULE_PARM_DESC(sharpness, "Model1 noise reduction: 0=smooth, 6=sharp (default=4)");
-module_param(size, int, 0);
-MODULE_PARM_DESC(size, "Image size: 0=128x96 1=160x120 2=176x144 3=320x240 4=352x240 5=352x288 6=640x480  (default=5)");
-module_param(init_brightness, int, 0);
-MODULE_PARM_DESC(init_brightness, "Brightness preconfiguration: 0-255 (default=128)");
-module_param(init_contrast, int, 0);
-MODULE_PARM_DESC(init_contrast, "Contrast preconfiguration: 0-255 (default=192)");
-module_param(init_color, int, 0);
-MODULE_PARM_DESC(init_color, "Color preconfiguration: 0-255 (default=128)");
-module_param(init_hue, int, 0);
-MODULE_PARM_DESC(init_hue, "Hue preconfiguration: 0-255 (default=128)");
-module_param(hue_correction, int, 0);
-MODULE_PARM_DESC(hue_correction, "YUV colorspace regulation: 0-255 (default=128)");
-
-module_param(init_model2_rg2, int, 0);
-MODULE_PARM_DESC(init_model2_rg2, "Model2 preconfiguration: 0-255 (default=47)");
-module_param(init_model2_sat, int, 0);
-MODULE_PARM_DESC(init_model2_sat, "Model2 preconfiguration: 0-255 (default=52)");
-module_param(init_model2_yb, int, 0);
-MODULE_PARM_DESC(init_model2_yb, "Model2 preconfiguration: 0-255 (default=160)");
-
-/* 01.01.08 - Added for RCA video in support -LO */
-module_param(init_model3_input, int, 0);
-MODULE_PARM_DESC(init_model3_input, "Model3 input: 0=CCD 1=RCA");
-
-MODULE_AUTHOR ("Dmitri");
-MODULE_DESCRIPTION ("IBM/Xirlink C-it USB Camera Driver for Linux (c) 2000");
-MODULE_LICENSE("GPL");
-
-/* Still mysterious i2c commands */
-static const unsigned short unknown_88 = 0x0088;
-static const unsigned short unknown_89 = 0x0089;
-static const unsigned short bright_3x[3] = { 0x0031, 0x0032, 0x0033 };
-static const unsigned short contrast_14 = 0x0014;
-static const unsigned short light_27 = 0x0027;
-static const unsigned short sharp_13 = 0x0013;
-
-/* i2c commands for Model 2 cameras */
-static const unsigned short mod2_brightness = 0x001a;		/* $5b .. $ee; default=$5a */
-static const unsigned short mod2_set_framerate = 0x001c;	/* 0 (fast).. $1F (slow) */
-static const unsigned short mod2_color_balance_rg2 = 0x001e;	/* 0 (red) .. $7F (green) */
-static const unsigned short mod2_saturation = 0x0020;		/* 0 (b/w) - $7F (full color) */
-static const unsigned short mod2_color_balance_yb = 0x0022;	/* 0..$7F, $50 is about right */
-static const unsigned short mod2_hue = 0x0024;			/* 0..$7F, $70 is about right */
-static const unsigned short mod2_sensitivity = 0x0028;		/* 0 (min) .. $1F (max) */
-
-struct struct_initData {
-	unsigned char req;
-	unsigned short value;
-	unsigned short index;
-};
-
-/*
- * ibmcam_size_to_videosize()
- *
- * This procedure converts module option 'size' into the actual
- * videosize_t that defines the image size in pixels. We need
- * simplified 'size' because user wants a simple enumerated list
- * of choices, not an infinite set of possibilities.
- */
-static videosize_t ibmcam_size_to_videosize(int size)
-{
-	videosize_t vs = VIDEOSIZE_352x288;
-	RESTRICT_TO_RANGE(size, 0, (SIZE_LastItem-1));
-	switch (size) {
-	case SIZE_128x96:
-		vs = VIDEOSIZE_128x96;
-		break;
-	case SIZE_160x120:
-		vs = VIDEOSIZE_160x120;
-		break;
-	case SIZE_176x144:
-		vs = VIDEOSIZE_176x144;
-		break;
-	case SIZE_320x240:
-		vs = VIDEOSIZE_320x240;
-		break;
-	case SIZE_352x240:
-		vs = VIDEOSIZE_352x240;
-		break;
-	case SIZE_352x288:
-		vs = VIDEOSIZE_352x288;
-		break;
-	case SIZE_640x480:
-		vs = VIDEOSIZE_640x480;
-		break;
-	default:
-		err("size=%d. is not valid", size);
-		break;
-	}
-	return vs;
-}
-
-/*
- * ibmcam_find_header()
- *
- * Locate one of supported header markers in the queue.
- * Once found, remove all preceding bytes AND the marker (4 bytes)
- * from the data pump queue. Whatever follows must be video lines.
- *
- * History:
- * 1/21/00  Created.
- */
-static enum ParseState ibmcam_find_header(struct uvd *uvd) /* FIXME: Add frame here */
-{
-	struct usbvideo_frame *frame;
-	ibmcam_t *icam;
-
-	if ((uvd->curframe) < 0 || (uvd->curframe >= USBVIDEO_NUMFRAMES)) {
-		err("ibmcam_find_header: Illegal frame %d.", uvd->curframe);
-		return scan_EndParse;
-	}
-	icam = IBMCAM_T(uvd);
-	assert(icam != NULL);
-	frame = &uvd->frame[uvd->curframe];
-	icam->has_hdr = 0;
-	switch (icam->camera_model) {
-	case IBMCAM_MODEL_1:
-	{
-		const int marker_len = 4;
-		while (RingQueue_GetLength(&uvd->dp) >= marker_len) {
-			if ((RING_QUEUE_PEEK(&uvd->dp, 0) == 0x00) &&
-			    (RING_QUEUE_PEEK(&uvd->dp, 1) == 0xFF) &&
-			    (RING_QUEUE_PEEK(&uvd->dp, 2) == 0x00))
-			{
-#if 0				/* This code helps to detect new frame markers */
-				dev_info(&uvd->dev->dev,
-					 "Header sig: 00 FF 00 %02X\n",
-					 RING_QUEUE_PEEK(&uvd->dp, 3));
-#endif
-				frame->header = RING_QUEUE_PEEK(&uvd->dp, 3);
-				if ((frame->header == HDRSIG_MODEL1_128x96) ||
-				    (frame->header == HDRSIG_MODEL1_176x144) ||
-				    (frame->header == HDRSIG_MODEL1_352x288))
-				{
-#if 0
-					dev_info(&uvd->dev->dev,
-						 "Header found.\n");
-#endif
-					RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, marker_len);
-					icam->has_hdr = 1;
-					break;
-				}
-			}
-			/* If we are still here then this doesn't look like a header */
-			RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, 1);
-		}
-		break;
-	}
-	case IBMCAM_MODEL_2:
-case IBMCAM_MODEL_4:
-	{
-		int marker_len = 0;
-		switch (uvd->videosize) {
-		case VIDEOSIZE_176x144:
-			marker_len = 10;
-			break;
-		default:
-			marker_len = 2;
-			break;
-		}
-		while (RingQueue_GetLength(&uvd->dp) >= marker_len) {
-			if ((RING_QUEUE_PEEK(&uvd->dp, 0) == 0x00) &&
-			    (RING_QUEUE_PEEK(&uvd->dp, 1) == 0xFF))
-			{
-#if 0
-				dev_info(&uvd->dev->dev, "Header found.\n");
-#endif
-				RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, marker_len);
-				icam->has_hdr = 1;
-				frame->header = HDRSIG_MODEL1_176x144;
-				break;
-			}
-			/* If we are still here then this doesn't look like a header */
-			RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, 1);
-		}
-		break;
-	}
-	case IBMCAM_MODEL_3:
-	{	/*
-		 * Headers: (one precedes every frame). nc=no compression,
-		 * bq=best quality bf=best frame rate.
-		 *
-		 * 176x144: 00 FF 02 { 0A=nc CA=bq EA=bf }
-		 * 320x240: 00 FF 02 { 08=nc 28=bq 68=bf }
-		 * 640x480: 00 FF 03 { 08=nc 28=bq 68=bf }
-		 *
-		 * Bytes '00 FF' seem to indicate header. Other two bytes
-		 * encode the frame type. This is a set of bit fields that
-		 * encode image size, compression type etc. These fields
-		 * do NOT contain frame number because all frames carry
-		 * the same header.
-		 */
-		const int marker_len = 4;
-		while (RingQueue_GetLength(&uvd->dp) >= marker_len) {
-			if ((RING_QUEUE_PEEK(&uvd->dp, 0) == 0x00) &&
-			    (RING_QUEUE_PEEK(&uvd->dp, 1) == 0xFF) &&
-			    (RING_QUEUE_PEEK(&uvd->dp, 2) != 0xFF))
-			{
-				/*
-				 * Combine 2 bytes of frame type into one
-				 * easy to use value
-				 */
-				unsigned long byte3, byte4;
-
-				byte3 = RING_QUEUE_PEEK(&uvd->dp, 2);
-				byte4 = RING_QUEUE_PEEK(&uvd->dp, 3);
-				frame->header = (byte3 << 8) | byte4;
-#if 0
-				dev_info(&uvd->dev->dev, "Header found.\n");
-#endif
-				RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, marker_len);
-				icam->has_hdr = 1;
-				break;
-			}
-			/* If we are still here then this doesn't look like a header */
-			RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, 1);
-		}
-		break;
-	}
-	default:
-		break;
-	}
-	if (!icam->has_hdr) {
-		if (uvd->debug > 2)
-			dev_info(&uvd->dev->dev,
-				 "Skipping frame, no header\n");
-		return scan_EndParse;
-	}
-
-	/* Header found */
-	icam->has_hdr = 1;
-	uvd->stats.header_count++;
-	frame->scanstate = ScanState_Lines;
-	frame->curline = 0;
-
-	if (flags & FLAGS_FORCE_TESTPATTERN) {
-		usbvideo_TestPattern(uvd, 1, 1);
-		return scan_NextFrame;
-	}
-	return scan_Continue;
-}
-
-/*
- * ibmcam_parse_lines()
- *
- * Parse one line (interlaced) from the buffer, put
- * decoded RGB value into the current frame buffer
- * and add the written number of bytes (RGB) to
- * the *pcopylen.
- *
- * History:
- * 21-Jan-2000 Created.
- * 12-Oct-2000 Reworked to reflect interlaced nature of the data.
- */
-static enum ParseState ibmcam_parse_lines(
-	struct uvd *uvd,
-	struct usbvideo_frame *frame,
-	long *pcopylen)
-{
-	unsigned char *f;
-	ibmcam_t *icam;
-	unsigned int len, scanLength, scanHeight, order_uv, order_yc;
-	int v4l_linesize; /* V4L line offset */
-	const int hue_corr  = (uvd->vpic.hue - 0x8000) >> 10;	/* -32..+31 */
-	const int hue2_corr = (hue_correction - 128) / 4;		/* -32..+31 */
-	const int ccm = 128; /* Color correction median - see below */
-	int y, u, v, i, frame_done=0, color_corr;
-	static unsigned char lineBuffer[640*3];
-	unsigned const char *chromaLine, *lumaLine;
-
-	assert(uvd != NULL);
-	assert(frame != NULL);
-	icam = IBMCAM_T(uvd);
-	assert(icam != NULL);
-	color_corr = (uvd->vpic.colour - 0x8000) >> 8; /* -128..+127 = -ccm..+(ccm-1)*/
-	RESTRICT_TO_RANGE(color_corr, -ccm, ccm+1);
-
-	v4l_linesize = VIDEOSIZE_X(frame->request) * V4L_BYTES_PER_PIXEL;
-
-	if (IBMCAM_T(uvd)->camera_model == IBMCAM_MODEL_4) {
-		/* Model 4 frame markers do not carry image size identification */
-		switch (uvd->videosize) {
-		case VIDEOSIZE_128x96:
-		case VIDEOSIZE_160x120:
-		case VIDEOSIZE_176x144:
-			scanLength = VIDEOSIZE_X(uvd->videosize);
-			scanHeight = VIDEOSIZE_Y(uvd->videosize);
-			break;
-		default:
-			err("ibmcam_parse_lines: Wrong mode.");
-			return scan_Out;
-		}
-		order_yc = 1;	/* order_yc: true=Yc false=cY ('c'=either U or V) */
-		order_uv = 1;	/* Always true in this algorithm */
-	} else {
-		switch (frame->header) {
-		case HDRSIG_MODEL1_128x96:
-			scanLength = 128;
-			scanHeight = 96;
-			order_uv = 1;	/* U Y V Y ... */
-			break;
-		case HDRSIG_MODEL1_176x144:
-			scanLength = 176;
-			scanHeight = 144;
-			order_uv = 1;	/* U Y V Y ... */
-			break;
-		case HDRSIG_MODEL1_352x288:
-			scanLength = 352;
-			scanHeight = 288;
-			order_uv = 0;	/* Y V Y V ... */
-			break;
-		default:
-			err("Unknown header signature 00 FF 00 %02lX", frame->header);
-			return scan_NextFrame;
-		}
-		/* order_yc: true=Yc false=cY ('c'=either U or V) */
-		order_yc = (IBMCAM_T(uvd)->camera_model == IBMCAM_MODEL_2);
-	}
-
-	len = scanLength * 3;
-	assert(len <= sizeof(lineBuffer));
-
-	/*
-	 * Lines are organized this way:
-	 *
-	 * I420:
-	 * ~~~~
-	 * <scanLength->
-	 * ___________________________________
-	 * |-----Y-----|---UVUVUV...UVUV-----| \
-	 * |-----------+---------------------|  \
-	 * |<-- 176 -->|<------ 176*2 ------>|  Total 72. lines (interlaced)
-	 * |...	   ... |        ...          |  /
-	 * |<-- 352 -->|<------ 352*2 ------>|  Total 144. lines (interlaced)
-	 * |___________|_____________________| /
-	 *  \           \
-	 *   lumaLine    chromaLine
-	 */
-
-	/* Make sure there's enough data for the entire line */
-	if (RingQueue_GetLength(&uvd->dp) < len)
-		return scan_Out;
-
-	/* Suck one line out of the ring queue */
-	RingQueue_Dequeue(&uvd->dp, lineBuffer, len);
-
-	/*
-	 * Make sure that our writing into output buffer
-	 * will not exceed the buffer. Mind that we may write
-	 * not into current output scanline but in several after
-	 * it as well (if we enlarge image vertically.)
-	 */
-	if ((frame->curline + 2) >= VIDEOSIZE_Y(frame->request))
-		return scan_NextFrame;
-
-	/*
-	 * Now we are sure that entire line (representing all 'scanLength'
-	 * pixels from the camera) is available in the buffer. We
-	 * start copying the line left-aligned to the V4L buffer.
-	 * If the camera line is shorter then we should pad the V4L
-	 * buffer with something (black) to complete the line.
-	 */
-	assert(frame->data != NULL);
-	f = frame->data + (v4l_linesize * frame->curline);
-
-	/*
-	 * To obtain chrominance data from the 'chromaLine' use this:
-	 *   v = chromaLine[0]; // 0-1:[0], 2-3:[4], 4-5:[8]...
-	 *   u = chromaLine[2]; // 0-1:[2], 2-3:[6], 4-5:[10]...
-	 *
-	 * Indices must be calculated this way:
-	 * v_index = (i >> 1) << 2;
-	 * u_index = (i >> 1) << 2 + 2;
-	 *
-	 * where 'i' is the column number [0..VIDEOSIZE_X(frame->request)-1]
-	 */
-	lumaLine = lineBuffer;
-	chromaLine = lineBuffer + scanLength;
-	for (i = 0; i < VIDEOSIZE_X(frame->request); i++)
-	{
-		unsigned char rv, gv, bv;	/* RGB components */
-
-		/* Check for various visual debugging hints (colorized pixels) */
-		if ((flags & FLAGS_DISPLAY_HINTS) && (icam->has_hdr)) {
-			/*
-			 * This is bad and should not happen. This means that
-			 * we somehow overshoot the line and encountered new
-			 * frame! Obviously our camera/V4L frame size is out
-			 * of whack. This cyan dot will help you to figure
-			 * out where exactly the new frame arrived.
-			 */
-			if (icam->has_hdr == 1) {
-				bv = 0; /* Yellow marker */
-				gv = 0xFF;
-				rv = 0xFF;
-			} else {
-				bv = 0xFF; /* Cyan marker */
-				gv = 0xFF;
-				rv = 0;
-			}
-			icam->has_hdr = 0;
-			goto make_pixel;
-		}
-
-		/*
-		 * Check if we are still in range. We may be out of range if our
-		 * V4L canvas is wider or taller than the camera "native" image.
-		 * Then we quickly fill the remainder of the line with zeros to
-		 * make black color and quit the horizontal scanning loop.
-		 */
-		if (((frame->curline + 2) >= scanHeight) || (i >= scanLength)) {
-			const int j = i * V4L_BYTES_PER_PIXEL;
-#if USES_IBMCAM_PUTPIXEL
-			/* Refresh 'f' because we don't use it much with PUTPIXEL */
-			f = frame->data + (v4l_linesize * frame->curline) + j;
-#endif
-			memset(f, 0, v4l_linesize - j);
-			break;
-		}
-
-		y = lumaLine[i];
-		if (flags & FLAGS_MONOCHROME) /* Use monochrome for debugging */
-			rv = gv = bv = y;
-		else {
-			int off_0, off_2;
-
-			off_0 = (i >> 1) << 2;
-			off_2 = off_0 + 2;
-
-			if (order_yc) {
-				off_0++;
-				off_2++;
-			}
-			if (!order_uv) {
-				off_0 += 2;
-				off_2 -= 2;
-			}
-			u = chromaLine[off_0] + hue_corr;
-			v = chromaLine[off_2] + hue2_corr;
-
-			/* Apply color correction */
-			if (color_corr != 0) {
-				/* Magnify up to 2 times, reduce down to zero saturation */
-				u = 128 + ((ccm + color_corr) * (u - 128)) / ccm;
-				v = 128 + ((ccm + color_corr) * (v - 128)) / ccm;
-			}
-			YUV_TO_RGB_BY_THE_BOOK(y, u, v, rv, gv, bv);
-		}
-
-	make_pixel:
-		/*
-		 * The purpose of creating the pixel here, in one,
-		 * dedicated place is that we may need to make the
-		 * pixel wider and taller than it actually is. This
-		 * may be used if camera generates small frames for
-		 * sake of frame rate (or any other reason.)
-		 *
-		 * The output data consists of B, G, R bytes
-		 * (in this order).
-		 */
-#if USES_IBMCAM_PUTPIXEL
-		RGB24_PUTPIXEL(frame, i, frame->curline, rv, gv, bv);
-#else
-		*f++ = bv;
-		*f++ = gv;
-		*f++ = rv;
-#endif
-		/*
-		 * Typically we do not decide within a legitimate frame
-		 * that we want to end the frame. However debugging code
-		 * may detect marker of new frame within the data. Then
-		 * this condition activates. The 'data' pointer is already
-		 * pointing at the new marker, so we'd better leave it as is.
-		 */
-		if (frame_done)
-			break;	/* End scanning of lines */
-	}
-	/*
-	 * Account for number of bytes that we wrote into output V4L frame.
-	 * We do it here, after we are done with the scanline, because we
-	 * may fill more than one output scanline if we do vertical
-	 * enlargement.
-	 */
-	frame->curline += 2;
-	if (pcopylen != NULL)
-		*pcopylen += 2 * v4l_linesize;
-	frame->deinterlace = Deinterlace_FillOddLines;
-
-	if (frame_done || (frame->curline >= VIDEOSIZE_Y(frame->request)))
-		return scan_NextFrame;
-	else
-		return scan_Continue;
-}
-
-/*
- * ibmcam_model2_320x240_parse_lines()
- *
- * This procedure deals with a weird RGB format that is produced by IBM
- * camera model 2 in modes 320x240 and above; 'x' below is 159 or 175,
- * depending on horizontal size of the picture:
- *
- * <--- 160 or 176 pairs of RA,RB bytes ----->
- * *-----------------------------------------* \
- * | RA0 | RB0 | RA1 | RB1 | ... | RAx | RBx |  \   This is pair of horizontal lines,
- * |-----+-----+-----+-----+ ... +-----+-----|   *- or one interlaced line, total
- * | B0  | G0  | B1  | G1  | ... | Bx  | Gx  |  /   120 or 144 such pairs which yield
- * |=====+=====+=====+=====+ ... +=====+=====| /    240 or 288 lines after deinterlacing.
- *
- * Each group of FOUR bytes (RAi, RBi, Bi, Gi) where i=0..frame_width/2-1
- * defines ONE pixel. Therefore this format yields 176x144 "decoded"
- * resolution at best. I do not know why camera sends such format - the
- * previous model (1) just used interlaced I420 and everyone was happy.
- *
- * I do not know what is the difference between RAi and RBi bytes. Both
- * seemingly represent R component, but slightly vary in value (so that
- * the picture looks a bit colored if one or another is used). I use
- * them both as R component in attempt to at least partially recover the
- * lost resolution.
- */
-static enum ParseState ibmcam_model2_320x240_parse_lines(
-	struct uvd *uvd,
-	struct usbvideo_frame *frame,
-	long *pcopylen)
-{
-	unsigned char *f, *la, *lb;
-	unsigned int len;
-	int v4l_linesize; /* V4L line offset */
-	int i, j, frame_done=0, color_corr;
-	int scanLength, scanHeight;
-	static unsigned char lineBuffer[352*2];
-
-	switch (uvd->videosize) {
-	case VIDEOSIZE_320x240:
-	case VIDEOSIZE_352x240:
-	case VIDEOSIZE_352x288:
-		scanLength = VIDEOSIZE_X(uvd->videosize);
-		scanHeight = VIDEOSIZE_Y(uvd->videosize);
-		break;
-	default:
-		err("ibmcam_model2_320x240_parse_lines: Wrong mode.");
-		return scan_Out;
-	}
-
-	color_corr = (uvd->vpic.colour) >> 8; /* 0..+255 */
-	v4l_linesize = VIDEOSIZE_X(frame->request) * V4L_BYTES_PER_PIXEL;
-
-	len = scanLength * 2; /* See explanation above */
-	assert(len <= sizeof(lineBuffer));
-
-	/* Make sure there's enough data for the entire line */
-	if (RingQueue_GetLength(&uvd->dp) < len)
-		return scan_Out;
-
-	/* Suck one line out of the ring queue */
-	RingQueue_Dequeue(&uvd->dp, lineBuffer, len);
-
-	/*
-	 * Make sure that our writing into output buffer
-	 * will not exceed the buffer. Mind that we may write
-	 * not into current output scanline but in several after
-	 * it as well (if we enlarge image vertically.)
-	 */
-	if ((frame->curline + 2) >= VIDEOSIZE_Y(frame->request))
-		return scan_NextFrame;
-
-	la = lineBuffer;
-	lb = lineBuffer + scanLength;
-
-	/*
-	 * Now we are sure that entire line (representing all
-	 *         VIDEOSIZE_X(frame->request)
-	 * pixels from the camera) is available in the scratch buffer. We
-	 * start copying the line left-aligned to the V4L buffer (which
-	 * might be larger - not smaller, hopefully). If the camera
-	 * line is shorter then we should pad the V4L buffer with something
-	 * (black in this case) to complete the line.
-	 */
-	f = frame->data + (v4l_linesize * frame->curline);
-
-	/* Fill the 2-line strip */
-	for (i = 0; i < VIDEOSIZE_X(frame->request); i++) {
-		int y, rv, gv, bv;	/* RGB components */
-
-		j = i & (~1);
-
-		/* Check for various visual debugging hints (colorized pixels) */
-		if ((flags & FLAGS_DISPLAY_HINTS) && (IBMCAM_T(uvd)->has_hdr)) {
-			if (IBMCAM_T(uvd)->has_hdr == 1) {
-				bv = 0; /* Yellow marker */
-				gv = 0xFF;
-				rv = 0xFF;
-			} else {
-				bv = 0xFF; /* Cyan marker */
-				gv = 0xFF;
-				rv = 0;
-			}
-			IBMCAM_T(uvd)->has_hdr = 0;
-			goto make_pixel;
-		}
-
-		/*
-		 * Check if we are still in range. We may be out of range if our
-		 * V4L canvas is wider or taller than the camera "native" image.
-		 * Then we quickly fill the remainder of the line with zeros to
-		 * make black color and quit the horizontal scanning loop.
-		 */
-		if (((frame->curline + 2) >= scanHeight) || (i >= scanLength)) {
-			const int offset = i * V4L_BYTES_PER_PIXEL;
-#if USES_IBMCAM_PUTPIXEL
-			/* Refresh 'f' because we don't use it much with PUTPIXEL */
-			f = frame->data + (v4l_linesize * frame->curline) + offset;
-#endif
-			memset(f, 0, v4l_linesize - offset);
-			break;
-		}
-
-		/*
-		 * Here I use RA and RB components, one per physical pixel.
-		 * This causes fine vertical grid on the picture but may improve
-		 * horizontal resolution. If you prefer replicating, use this:
-		 *   rv = la[j + 0];   ... or ... rv = la[j + 1];
-		 * then the pixel will be replicated.
-		 */
-		rv = la[i];
-		gv = lb[j + 1];
-		bv = lb[j + 0];
-
-		y = (rv + gv + bv) / 3; /* Brightness (badly calculated) */
-
-		if (flags & FLAGS_MONOCHROME) /* Use monochrome for debugging */
-			rv = gv = bv = y;
-		else if (color_corr != 128) {
-
-			/* Calculate difference between color and brightness */
-			rv -= y;
-			gv -= y;
-			bv -= y;
-
-			/* Scale differences */
-			rv = (rv * color_corr) / 128;
-			gv = (gv * color_corr) / 128;
-			bv = (bv * color_corr) / 128;
-
-			/* Reapply brightness */
-			rv += y;
-			gv += y;
-			bv += y;
-
-			/* Watch for overflows */
-			RESTRICT_TO_RANGE(rv, 0, 255);
-			RESTRICT_TO_RANGE(gv, 0, 255);
-			RESTRICT_TO_RANGE(bv, 0, 255);
-		}
-
-	make_pixel:
-		RGB24_PUTPIXEL(frame, i, frame->curline, rv, gv, bv);
-	}
-	/*
-	 * Account for number of bytes that we wrote into output V4L frame.
-	 * We do it here, after we are done with the scanline, because we
-	 * may fill more than one output scanline if we do vertical
-	 * enlargement.
-	 */
-	frame->curline += 2;
-	*pcopylen += v4l_linesize * 2;
-	frame->deinterlace = Deinterlace_FillOddLines;
-
-	if (frame_done || (frame->curline >= VIDEOSIZE_Y(frame->request)))
-		return scan_NextFrame;
-	else
-		return scan_Continue;
-}
-
-/*
- * ibmcam_model3_parse_lines()
- *
- * | Even lines |     Odd Lines       |
- * -----------------------------------|
- * |YYY........Y|UYVYUYVY.........UYVY|
- * |YYY........Y|UYVYUYVY.........UYVY|
- * |............|.....................|
- * |YYY........Y|UYVYUYVY.........UYVY|
- * |------------+---------------------|
- *
- * There is one (U, V) chroma pair for every four luma (Y) values.  This
- * function reads a pair of lines at a time and obtains missing chroma values
- * from adjacent pixels.
- */
-static enum ParseState ibmcam_model3_parse_lines(
-	struct uvd *uvd,
-	struct usbvideo_frame *frame,
-	long *pcopylen)
-{
-	unsigned char *data;
-	const unsigned char *color;
-	unsigned int len;
-	int v4l_linesize; /* V4L line offset */
-	const int hue_corr  = (uvd->vpic.hue - 0x8000) >> 10;	/* -32..+31 */
-	const int hue2_corr = (hue_correction - 128) / 4;		/* -32..+31 */
-	const int ccm = 128; /* Color correction median - see below */
-	int i, u, v, rw, data_w=0, data_h=0, color_corr;
-	static unsigned char lineBuffer[640*3];
-	int line;
-
-	color_corr = (uvd->vpic.colour - 0x8000) >> 8; /* -128..+127 = -ccm..+(ccm-1)*/
-	RESTRICT_TO_RANGE(color_corr, -ccm, ccm+1);
-
-	v4l_linesize = VIDEOSIZE_X(frame->request) * V4L_BYTES_PER_PIXEL;
-
-	/* The header tells us what sort of data is in this frame */
-	switch (frame->header) {
-		/*
-		 * Uncompressed modes (that are easy to decode).
-		 */
-	case 0x0308:
-		data_w = 640;
-		data_h = 480;
-		break;
-	case 0x0208:
-		data_w = 320;
-		data_h = 240;
-		break;
-	case 0x020A:
-		data_w = 160;
-		data_h = 120;
-		break;
-		/*
-		 * Compressed modes (ViCE - that I don't know how to decode).
-		 */
-	case 0x0328:	/* 640x480, best quality compression */
-	case 0x0368:	/* 640x480, best frame rate compression */
-	case 0x0228:	/* 320x240, best quality compression */
-	case 0x0268:	/* 320x240, best frame rate compression */
-	case 0x02CA:	/* 160x120, best quality compression */
-	case 0x02EA:	/* 160x120, best frame rate compression */
-		/* Do nothing with this - not supported */
-		err("Unsupported mode $%04lx", frame->header);
-		return scan_NextFrame;
-	default:
-		/* Catch unknown headers, may help in learning new headers */
-		err("Strange frame->header=$%08lx", frame->header);
-		return scan_NextFrame;
-	}
-
-	/*
-	 * Make sure that our writing into output buffer
-	 * will not exceed the buffer. Note that we may write
-	 * not into current output scanline but in several after
-	 * it as well (if we enlarge image vertically.)
-	 */
-	if ((frame->curline + 1) >= data_h) {
-		if (uvd->debug >= 3)
-			dev_info(&uvd->dev->dev,
-				 "Reached line %d. (frame is done)\n",
-				 frame->curline);
-		return scan_NextFrame;
-	}
-
-	/* Make sure that lineBuffer can store two lines of data */
-	len = 3 * data_w; /* <y-data> <uyvy-data> */
-	assert(len <= sizeof(lineBuffer));
-
-	/* Make sure there's enough data for two lines */
-	if (RingQueue_GetLength(&uvd->dp) < len)
-		return scan_Out;
-
-	/* Suck two lines of data out of the ring queue */
-	RingQueue_Dequeue(&uvd->dp, lineBuffer, len);
-
-	data = lineBuffer;
-	color = data + data_w;		/* Point to where color planes begin */
-
-	/* Bottom-to-top scanning */
-	rw = (int)VIDEOSIZE_Y(frame->request) - (int)(frame->curline) - 1;
-	RESTRICT_TO_RANGE(rw, 0, VIDEOSIZE_Y(frame->request)-1);
-
-	/* Iterate over two lines. */
-	for (line = 0; line < 2; line++) {
-		for (i = 0; i < VIDEOSIZE_X(frame->request); i++) {
-			int y;
-			int rv, gv, bv;	/* RGB components */
-
-			if (i >= data_w) {
-				RGB24_PUTPIXEL(frame, i, rw, 0, 0, 0);
-				continue;
-			}
-
-			/* first line is YYY...Y; second is UYVY...UYVY */
-			y = data[(line == 0) ? i : (i*2 + 1)];
-
-			/* Apply static color correction */
-			u = color[(i/2)*4] + hue_corr;
-			v = color[(i/2)*4 + 2] + hue2_corr;
-
-			/* Apply color correction */
-			if (color_corr != 0) {
-				/* Magnify up to 2 times, reduce down to zero saturation */
-				u = 128 + ((ccm + color_corr) * (u - 128)) / ccm;
-				v = 128 + ((ccm + color_corr) * (v - 128)) / ccm;
-			}
-
-
-			YUV_TO_RGB_BY_THE_BOOK(y, u, v, rv, gv, bv);
-			RGB24_PUTPIXEL(frame, i, rw, rv, gv, bv);  /* No deinterlacing */
-		}
-
-		/* Check for the end of requested data */
-		if (rw == 0)
-			break;
-
-		/* Prepare for the second line */
-		rw--;
-		data = lineBuffer + data_w;
-	}
-	frame->deinterlace = Deinterlace_None;
-
-	/*
-	 * Account for number of bytes that we wrote into output V4L frame.
-	 * We do it here, after we are done with the scanline, because we
-	 * may fill more than one output scanline if we do vertical
-	 * enlargement.
-	 */
-	frame->curline += 2;
-	*pcopylen += 2 * v4l_linesize;
-
-	if (frame->curline >= VIDEOSIZE_Y(frame->request)) {
-		if (uvd->debug >= 3) {
-			dev_info(&uvd->dev->dev,
-				 "All requested lines (%ld.) done.\n",
-				 VIDEOSIZE_Y(frame->request));
-		}
-		return scan_NextFrame;
-	} else
-		return scan_Continue;
-}
-
-/*
- * ibmcam_model4_128x96_parse_lines()
- *
- * This decoder is for one strange data format that is produced by Model 4
- * camera only in 128x96 mode. This is RGB format and here is its description.
- * First of all, this is non-interlaced stream, meaning that all scan lines
- * are present in the datastream. There are 96 consecutive blocks of data
- * that describe all 96 lines of the image. Each block is 5*128 bytes long
- * and carries R, G, B components. The format of the block is shown in the
- * code below. First 128*2 bytes are interleaved R and G components. Then
- * we have a gap (junk data) 64 bytes long. Then follow B and something
- * else, also interleaved (this makes another 128*2 bytes). After that
- * probably another 64 bytes of junk follow.
- *
- * History:
- * 10-Feb-2001 Created.
- */
-static enum ParseState ibmcam_model4_128x96_parse_lines(
-	struct uvd *uvd,
-	struct usbvideo_frame *frame,
-	long *pcopylen)
-{
-	const unsigned char *data_rv, *data_gv, *data_bv;
-	unsigned int len;
-	int i, v4l_linesize; /* V4L line offset */
-	const int data_w=128, data_h=96;
-	static unsigned char lineBuffer[128*5];
-
-	v4l_linesize = VIDEOSIZE_X(frame->request) * V4L_BYTES_PER_PIXEL;
-
-	/*
-	 * Make sure that our writing into output buffer
-	 * will not exceed the buffer. Note that we may write
-	 * not into current output scanline but in several after
-	 * it as well (if we enlarge image vertically.)
-	 */
-	if ((frame->curline + 1) >= data_h) {
-		if (uvd->debug >= 3)
-			dev_info(&uvd->dev->dev,
-				 "Reached line %d. (frame is done)\n",
-				 frame->curline);
-		return scan_NextFrame;
-	}
-
-	/*
-	 * RGRGRG .... RGRG_____________B?B?B? ... B?B?____________
-	 * <---- 128*2 ---><---- 64 ---><--- 128*2 ---><--- 64 --->
-	 */
-
-	/* Make sure there's enough data for the entire line */
-	len = 5 * data_w;
-	assert(len <= sizeof(lineBuffer));
-
-	/* Make sure there's enough data for the entire line */
-	if (RingQueue_GetLength(&uvd->dp) < len)
-		return scan_Out;
-
-	/* Suck one line out of the ring queue */
-	RingQueue_Dequeue(&uvd->dp, lineBuffer, len);
-
-	data_rv = lineBuffer;
-	data_gv = lineBuffer + 1;
-	data_bv = lineBuffer + data_w*2 + data_w/2;
-	for (i = 0; i < VIDEOSIZE_X(frame->request); i++) {
-		int rv, gv, bv;	/* RGB components */
-		if (i < data_w) {
-			const int j = i * 2;
-			gv = data_rv[j];
-			rv = data_gv[j];
-			bv = data_bv[j];
-			if (flags & FLAGS_MONOCHROME) {
-				unsigned long y;
-				y = rv + gv + bv;
-				y /= 3;
-				if (y > 0xFF)
-					y = 0xFF;
-				rv = gv = bv = (unsigned char) y;
-			}
-		} else {
-			rv = gv = bv = 0;
-		}
-		RGB24_PUTPIXEL(frame, i, frame->curline, rv, gv, bv);
-	}
-	frame->deinterlace = Deinterlace_None;
-	frame->curline++;
-	*pcopylen += v4l_linesize;
-
-	if (frame->curline >= VIDEOSIZE_Y(frame->request)) {
-		if (uvd->debug >= 3) {
-			dev_info(&uvd->dev->dev,
-				 "All requested lines (%ld.) done.\n",
-				 VIDEOSIZE_Y(frame->request));
-		}
-		return scan_NextFrame;
-	} else
-		return scan_Continue;
-}
-
-/*
- * ibmcam_ProcessIsocData()
- *
- * Generic routine to parse the ring queue data. It employs either
- * ibmcam_find_header() or ibmcam_parse_lines() to do most
- * of work.
- *
- * History:
- * 1/21/00  Created.
- */
-static void ibmcam_ProcessIsocData(struct uvd *uvd,
-				   struct usbvideo_frame *frame)
-{
-	enum ParseState newstate;
-	long copylen = 0;
-	int mod = IBMCAM_T(uvd)->camera_model;
-
-	while (1) {
-		newstate = scan_Out;
-		if (RingQueue_GetLength(&uvd->dp) > 0) {
-			if (frame->scanstate == ScanState_Scanning) {
-				newstate = ibmcam_find_header(uvd);
-			} else if (frame->scanstate == ScanState_Lines) {
-				if ((mod == IBMCAM_MODEL_2) &&
-				    ((uvd->videosize == VIDEOSIZE_352x288) ||
-				     (uvd->videosize == VIDEOSIZE_320x240) ||
-				     (uvd->videosize == VIDEOSIZE_352x240)))
-				{
-					newstate = ibmcam_model2_320x240_parse_lines(
-						uvd, frame, &copylen);
-				} else if (mod == IBMCAM_MODEL_4) {
-					/*
-					 * Model 4 cameras (IBM NetCamera) use Model 2 decoder (RGB)
-					 * for 320x240 and above; 160x120 and 176x144 uses Model 1
-					 * decoder (YUV), and 128x96 mode uses ???
-					 */
-					if ((uvd->videosize == VIDEOSIZE_352x288) ||
-					    (uvd->videosize == VIDEOSIZE_320x240) ||
-					    (uvd->videosize == VIDEOSIZE_352x240))
-					{
-						newstate = ibmcam_model2_320x240_parse_lines(uvd, frame, &copylen);
-					} else if (uvd->videosize == VIDEOSIZE_128x96) {
-						newstate = ibmcam_model4_128x96_parse_lines(uvd, frame, &copylen);
-					} else {
-						newstate = ibmcam_parse_lines(uvd, frame, &copylen);
-					}
-				} else if (mod == IBMCAM_MODEL_3) {
-					newstate = ibmcam_model3_parse_lines(uvd, frame, &copylen);
-				} else {
-					newstate = ibmcam_parse_lines(uvd, frame, &copylen);
-				}
-			}
-		}
-		if (newstate == scan_Continue)
-			continue;
-		else if ((newstate == scan_NextFrame) || (newstate == scan_Out))
-			break;
-		else
-			return; /* scan_EndParse */
-	}
-
-	if (newstate == scan_NextFrame) {
-		frame->frameState = FrameState_Done;
-		uvd->curframe = -1;
-		uvd->stats.frame_num++;
-		if ((mod == IBMCAM_MODEL_2) || (mod == IBMCAM_MODEL_4)) {
-			/* Need software contrast adjustment for those cameras */
-			frame->flags |= USBVIDEO_FRAME_FLAG_SOFTWARE_CONTRAST;
-		}
-	}
-
-	/* Update the frame's uncompressed length. */
-	frame->seqRead_Length += copylen;
-
-#if 0
-	{
-		static unsigned char j=0;
-		memset(frame->data, j++, uvd->max_frame_size);
-		frame->frameState = FrameState_Ready;
-	}
-#endif
-}
-
-/*
- * ibmcam_veio()
- *
- * History:
- * 1/27/00  Added check for dev == NULL; this happens if camera is unplugged.
- */
-static int ibmcam_veio(
-	struct uvd *uvd,
-	unsigned char req,
-	unsigned short value,
-	unsigned short index)
-{
-	static const char proc[] = "ibmcam_veio";
-	unsigned char cp[8] /* = { 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef } */;
-	int i;
-
-	if (!CAMERA_IS_OPERATIONAL(uvd))
-		return 0;
-
-	if (req == 1) {
-		i = usb_control_msg(
-			uvd->dev,
-			usb_rcvctrlpipe(uvd->dev, 0),
-			req,
-			USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT,
-			value,
-			index,
-			cp,
-			sizeof(cp),
-			1000);
-#if 0
-		dev_info(&uvd->dev->dev,
-			 "USB => %02x%02x%02x%02x%02x%02x%02x%02x "
-			 "(req=$%02x val=$%04x ind=$%04x)\n",
-			 cp[0],cp[1],cp[2],cp[3],cp[4],cp[5],cp[6],cp[7],
-			 req, value, index);
-#endif
-	} else {
-		i = usb_control_msg(
-			uvd->dev,
-			usb_sndctrlpipe(uvd->dev, 0),
-			req,
-			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT,
-			value,
-			index,
-			NULL,
-			0,
-			1000);
-	}
-	if (i < 0) {
-		err("%s: ERROR=%d. Camera stopped; Reconnect or reload driver.",
-		    proc, i);
-		uvd->last_error = i;
-	}
-	return i;
-}
-
-/*
- * ibmcam_calculate_fps()
- *
- * This procedure roughly calculates the real frame rate based
- * on FPS code (framerate=NNN option). Actual FPS differs
- * slightly depending on lighting conditions, so that actual frame
- * rate is determined by the camera. Since I don't know how to ask
- * the camera what FPS is now I have to use the FPS code instead.
- *
- * The FPS code is in range [0..6], 0 is slowest, 6 is fastest.
- * Corresponding real FPS should be in range [3..30] frames per second.
- * The conversion formula is obvious:
- *
- * real_fps = 3 + (fps_code * 4.5)
- *
- * History:
- * 1/18/00  Created.
- */
-static int ibmcam_calculate_fps(struct uvd *uvd)
-{
-	return 3 + framerate*4 + framerate/2;
-}
-
-/*
- * ibmcam_send_FF_04_02()
- *
- * This procedure sends magic 3-command prefix to the camera.
- * The purpose of this prefix is not known.
- *
- * History:
- * 1/2/00   Created.
- */
-static void ibmcam_send_FF_04_02(struct uvd *uvd)
-{
-	ibmcam_veio(uvd, 0, 0x00FF, 0x0127);
-	ibmcam_veio(uvd, 0, 0x0004, 0x0124);
-	ibmcam_veio(uvd, 0, 0x0002, 0x0124);
-}
-
-static void ibmcam_send_00_04_06(struct uvd *uvd)
-{
-	ibmcam_veio(uvd, 0, 0x0000, 0x0127);
-	ibmcam_veio(uvd, 0, 0x0004, 0x0124);
-	ibmcam_veio(uvd, 0, 0x0006, 0x0124);
-}
-
-static void ibmcam_send_x_00(struct uvd *uvd, unsigned short x)
-{
-	ibmcam_veio(uvd, 0, x,      0x0127);
-	ibmcam_veio(uvd, 0, 0x0000, 0x0124);
-}
-
-static void ibmcam_send_x_00_05(struct uvd *uvd, unsigned short x)
-{
-	ibmcam_send_x_00(uvd, x);
-	ibmcam_veio(uvd, 0, 0x0005, 0x0124);
-}
-
-static void ibmcam_send_x_00_05_02(struct uvd *uvd, unsigned short x)
-{
-	ibmcam_veio(uvd, 0, x,      0x0127);
-	ibmcam_veio(uvd, 0, 0x0000, 0x0124);
-	ibmcam_veio(uvd, 0, 0x0005, 0x0124);
-	ibmcam_veio(uvd, 0, 0x0002, 0x0124);
-}
-
-static void ibmcam_send_x_01_00_05(struct uvd *uvd, unsigned short x)
-{
-	ibmcam_veio(uvd, 0, x,      0x0127);
-	ibmcam_veio(uvd, 0, 0x0001, 0x0124);
-	ibmcam_veio(uvd, 0, 0x0000, 0x0124);
-	ibmcam_veio(uvd, 0, 0x0005, 0x0124);
-}
-
-static void ibmcam_send_x_00_05_02_01(struct uvd *uvd, unsigned short x)
-{
-	ibmcam_veio(uvd, 0, x,      0x0127);
-	ibmcam_veio(uvd, 0, 0x0000, 0x0124);
-	ibmcam_veio(uvd, 0, 0x0005, 0x0124);
-	ibmcam_veio(uvd, 0, 0x0002, 0x0124);
-	ibmcam_veio(uvd, 0, 0x0001, 0x0124);
-}
-
-static void ibmcam_send_x_00_05_02_08_01(struct uvd *uvd, unsigned short x)
-{
-	ibmcam_veio(uvd, 0, x,      0x0127);
-	ibmcam_veio(uvd, 0, 0x0000, 0x0124);
-	ibmcam_veio(uvd, 0, 0x0005, 0x0124);
-	ibmcam_veio(uvd, 0, 0x0002, 0x0124);
-	ibmcam_veio(uvd, 0, 0x0008, 0x0124);
-	ibmcam_veio(uvd, 0, 0x0001, 0x0124);
-}
-
-static void ibmcam_Packet_Format1(struct uvd *uvd, unsigned char fkey, unsigned char val)
-{
-	ibmcam_send_x_01_00_05(uvd, unknown_88);
-	ibmcam_send_x_00_05(uvd, fkey);
-	ibmcam_send_x_00_05_02_08_01(uvd, val);
-	ibmcam_send_x_00_05(uvd, unknown_88);
-	ibmcam_send_x_00_05_02_01(uvd, fkey);
-	ibmcam_send_x_00_05(uvd, unknown_89);
-	ibmcam_send_x_00(uvd, fkey);
-	ibmcam_send_00_04_06(uvd);
-	ibmcam_veio(uvd, 1, 0x0000, 0x0126);
-	ibmcam_send_FF_04_02(uvd);
-}
-
-static void ibmcam_PacketFormat2(struct uvd *uvd, unsigned char fkey, unsigned char val)
-{
-	ibmcam_send_x_01_00_05	(uvd, unknown_88);
-	ibmcam_send_x_00_05	(uvd, fkey);
-	ibmcam_send_x_00_05_02	(uvd, val);
-}
-
-static void ibmcam_model2_Packet2(struct uvd *uvd)
-{
-	ibmcam_veio(uvd, 0, 0x00ff, 0x012d);
-	ibmcam_veio(uvd, 0, 0xfea3, 0x0124);
-}
-
-static void ibmcam_model2_Packet1(struct uvd *uvd, unsigned short v1, unsigned short v2)
-{
-	ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
-	ibmcam_veio(uvd, 0, 0x00ff, 0x012e);
-	ibmcam_veio(uvd, 0, v1,     0x012f);
-	ibmcam_veio(uvd, 0, 0x00ff, 0x0130);
-	ibmcam_veio(uvd, 0, 0xc719, 0x0124);
-	ibmcam_veio(uvd, 0, v2,     0x0127);
-
-	ibmcam_model2_Packet2(uvd);
-}
-
-/*
- * ibmcam_model3_Packet1()
- *
- * 00_0078_012d
- * 00_0097_012f
- * 00_d141_0124
- * 00_0096_0127
- * 00_fea8_0124
-*/
-static void ibmcam_model3_Packet1(struct uvd *uvd, unsigned short v1, unsigned short v2)
-{
-	ibmcam_veio(uvd, 0, 0x0078, 0x012d);
-	ibmcam_veio(uvd, 0, v1,     0x012f);
-	ibmcam_veio(uvd, 0, 0xd141, 0x0124);
-	ibmcam_veio(uvd, 0, v2,     0x0127);
-	ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
-}
-
-static void ibmcam_model4_BrightnessPacket(struct uvd *uvd, int i)
-{
-	ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
-	ibmcam_veio(uvd, 0, 0x0026, 0x012f);
-	ibmcam_veio(uvd, 0, 0xd141, 0x0124);
-	ibmcam_veio(uvd, 0, i,      0x0127);
-	ibmcam_veio(uvd, 0, 0x00aa, 0x0130);
-	ibmcam_veio(uvd, 0, 0x82a8, 0x0124);
-	ibmcam_veio(uvd, 0, 0x0038, 0x012d);
-	ibmcam_veio(uvd, 0, 0x0004, 0x012f);
-	ibmcam_veio(uvd, 0, 0xd145, 0x0124);
-	ibmcam_veio(uvd, 0, 0xfffa, 0x0124);
-}
-
-/*
- * ibmcam_adjust_contrast()
- *
- * The contrast value changes from 0 (high contrast) to 15 (low contrast).
- * This is in reverse to usual order of things (such as TV controls), so
- * we reverse it again here.
- *
- * TODO: we probably don't need to send the setup 5 times...
- *
- * History:
- * 1/2/00   Created.
- */
-static void ibmcam_adjust_contrast(struct uvd *uvd)
-{
-	unsigned char a_contrast = uvd->vpic.contrast >> 12;
-	unsigned char new_contrast;
-
-	if (a_contrast >= 16)
-		a_contrast = 15;
-	new_contrast = 15 - a_contrast;
-	if (new_contrast == uvd->vpic_old.contrast)
-		return;
-	uvd->vpic_old.contrast = new_contrast;
-	switch (IBMCAM_T(uvd)->camera_model) {
-	case IBMCAM_MODEL_1:
-	{
-		const int ntries = 5;
-		int i;
-		for (i=0; i < ntries; i++) {
-			ibmcam_Packet_Format1(uvd, contrast_14, new_contrast);
-			ibmcam_send_FF_04_02(uvd);
-		}
-		break;
-	}
-	case IBMCAM_MODEL_2:
-	case IBMCAM_MODEL_4:
-		/* Models 2, 4 do not have this control; implemented in software. */
-		break;
-	case IBMCAM_MODEL_3:
-	{	/* Preset hardware values */
-		static const struct {
-			unsigned short cv1;
-			unsigned short cv2;
-			unsigned short cv3;
-		} cv[7] = {
-			{ 0x05, 0x05, 0x0f },	/* Minimum */
-			{ 0x04, 0x04, 0x16 },
-			{ 0x02, 0x03, 0x16 },
-			{ 0x02, 0x08, 0x16 },
-			{ 0x01, 0x0c, 0x16 },
-			{ 0x01, 0x0e, 0x16 },
-			{ 0x01, 0x10, 0x16 }	/* Maximum */
-		};
-		int i = a_contrast / 2;
-		RESTRICT_TO_RANGE(i, 0, 6);
-		ibmcam_veio(uvd, 0, 0x0000, 0x010c);	/* Stop */
-		ibmcam_model3_Packet1(uvd, 0x0067, cv[i].cv1);
-		ibmcam_model3_Packet1(uvd, 0x005b, cv[i].cv2);
-		ibmcam_model3_Packet1(uvd, 0x005c, cv[i].cv3);
-		ibmcam_veio(uvd, 0, 0x0001, 0x0114);
-		ibmcam_veio(uvd, 0, 0x00c0, 0x010c);	/* Go! */
-		usb_clear_halt(uvd->dev, usb_rcvisocpipe(uvd->dev, uvd->video_endp));
-		break;
-	}
-	default:
-		break;
-	}
-}
-
-/*
- * ibmcam_change_lighting_conditions()
- *
- * Camera model 1:
- * We have 3 levels of lighting conditions: 0=Bright, 1=Medium, 2=Low.
- *
- * Camera model 2:
- * We have 16 levels of lighting, 0 for bright light and up to 15 for
- * low light. But values above 5 or so are useless because camera is
- * not really capable to produce anything worth viewing at such light.
- * This setting may be altered only in certain camera state.
- *
- * Low lighting forces slower FPS. Lighting is set as a module parameter.
- *
- * History:
- * 1/5/00   Created.
- * 2/20/00  Added support for Model 2 cameras.
- */
-static void ibmcam_change_lighting_conditions(struct uvd *uvd)
-{
-	if (debug > 0)
-		dev_info(&uvd->dev->dev,
-			 "%s: Set lighting to %hu.\n", __func__, lighting);
-
-	switch (IBMCAM_T(uvd)->camera_model) {
-	case IBMCAM_MODEL_1:
-	{
-		const int ntries = 5;
-		int i;
-		for (i=0; i < ntries; i++)
-			ibmcam_Packet_Format1(uvd, light_27, (unsigned short) lighting);
-		break;
-	}
-	case IBMCAM_MODEL_2:
-#if 0
-		/*
-		 * This command apparently requires camera to be stopped. My
-		 * experiments showed that it -is- possible to alter the lighting
-		 * conditions setting "on the fly", but why bother? This setting does
-		 * not work reliably in all cases, so I decided simply to leave the
-		 * setting where Xirlink put it - in the camera setup phase. This code
-		 * is commented out because it does not work at -any- moment, so its
-		 * presence makes no sense. You may use it for experiments.
-		 */
-		ibmcam_veio(uvd, 0, 0x0000, 0x010c);	/* Stop camera */
-		ibmcam_model2_Packet1(uvd, mod2_sensitivity, lighting);
-		ibmcam_veio(uvd, 0, 0x00c0, 0x010c);	/* Start camera */
-#endif
-		break;
-	case IBMCAM_MODEL_3:
-	case IBMCAM_MODEL_4:
-	default:
-		break;
-	}
-}
-
-/*
- * ibmcam_set_sharpness()
- *
- * Cameras model 1 have internal smoothing feature. It is controlled by value in
- * range [0..6], where 0 is most smooth and 6 is most sharp (raw image, I guess).
- * Recommended value is 4. Cameras model 2 do not have this feature at all.
- */
-static void ibmcam_set_sharpness(struct uvd *uvd)
-{
-	switch (IBMCAM_T(uvd)->camera_model) {
-	case IBMCAM_MODEL_1:
-	{
-		static const unsigned short sa[] = { 0x11, 0x13, 0x16, 0x18, 0x1a, 0x8, 0x0a };
-		unsigned short i, sv;
-
-		RESTRICT_TO_RANGE(sharpness, SHARPNESS_MIN, SHARPNESS_MAX);
-		if (debug > 0)
-			dev_info(&uvd->dev->dev, "%s: Set sharpness to %hu.\n",
-				 __func__, sharpness);
-
-		sv = sa[sharpness - SHARPNESS_MIN];
-		for (i=0; i < 2; i++) {
-			ibmcam_send_x_01_00_05	(uvd, unknown_88);
-			ibmcam_send_x_00_05		(uvd, sharp_13);
-			ibmcam_send_x_00_05_02	(uvd, sv);
-		}
-		break;
-	}
-	case IBMCAM_MODEL_2:
-	case IBMCAM_MODEL_4:
-		/* Models 2, 4 do not have this control */
-		break;
-	case IBMCAM_MODEL_3:
-	{	/*
-		 * "Use a table of magic numbers.
-		 *  This setting doesn't really change much.
-		 *  But that's how Windows does it."
-		 */
-		static const struct {
-			unsigned short sv1;
-			unsigned short sv2;
-			unsigned short sv3;
-			unsigned short sv4;
-		} sv[7] = {
-			{ 0x00, 0x00, 0x05, 0x14 },	/* Smoothest */
-			{ 0x01, 0x04, 0x05, 0x14 },
-			{ 0x02, 0x04, 0x05, 0x14 },
-			{ 0x03, 0x04, 0x05, 0x14 },
-			{ 0x03, 0x05, 0x05, 0x14 },
-			{ 0x03, 0x06, 0x05, 0x14 },
-			{ 0x03, 0x07, 0x05, 0x14 }	/* Sharpest */
-		};
-		RESTRICT_TO_RANGE(sharpness, SHARPNESS_MIN, SHARPNESS_MAX);
-		RESTRICT_TO_RANGE(sharpness, 0, 6);
-		ibmcam_veio(uvd, 0, 0x0000, 0x010c);	/* Stop */
-		ibmcam_model3_Packet1(uvd, 0x0060, sv[sharpness].sv1);
-		ibmcam_model3_Packet1(uvd, 0x0061, sv[sharpness].sv2);
-		ibmcam_model3_Packet1(uvd, 0x0062, sv[sharpness].sv3);
-		ibmcam_model3_Packet1(uvd, 0x0063, sv[sharpness].sv4);
-		ibmcam_veio(uvd, 0, 0x0001, 0x0114);
-		ibmcam_veio(uvd, 0, 0x00c0, 0x010c);	/* Go! */
-		usb_clear_halt(uvd->dev, usb_rcvisocpipe(uvd->dev, uvd->video_endp));
-		ibmcam_veio(uvd, 0, 0x0001, 0x0113);
-		break;
-	}
-	default:
-		break;
-	}
-}
-
-/*
- * ibmcam_set_brightness()
- *
- * This procedure changes brightness of the picture.
- */
-static void ibmcam_set_brightness(struct uvd *uvd)
-{
-	static const unsigned short n = 1;
-
-	if (debug > 0)
-		dev_info(&uvd->dev->dev, "%s: Set brightness to %hu.\n",
-			 __func__, uvd->vpic.brightness);
-
-	switch (IBMCAM_T(uvd)->camera_model) {
-	case IBMCAM_MODEL_1:
-	{
-		unsigned short i, j, bv[3];
-		bv[0] = bv[1] = bv[2] = uvd->vpic.brightness >> 10;
-		if (bv[0] == (uvd->vpic_old.brightness >> 10))
-			return;
-		uvd->vpic_old.brightness = bv[0];
-		for (j=0; j < 3; j++)
-			for (i=0; i < n; i++)
-				ibmcam_Packet_Format1(uvd, bright_3x[j], bv[j]);
-		break;
-	}
-	case IBMCAM_MODEL_2:
-	{
-		unsigned short i, j;
-		i = uvd->vpic.brightness >> 12;	/* 0 .. 15 */
-		j = 0x60 + i * ((0xee - 0x60) / 16);	/* 0x60 .. 0xee or so */
-		if (uvd->vpic_old.brightness == j)
-			break;
-		uvd->vpic_old.brightness = j;
-		ibmcam_model2_Packet1(uvd, mod2_brightness, j);
-		break;
-	}
-	case IBMCAM_MODEL_3:
-	{
-		/* Model 3: Brightness range 'i' in [0x0C..0x3F] */
-		unsigned short i =
-			0x0C + (uvd->vpic.brightness / (0xFFFF / (0x3F - 0x0C + 1)));
-		RESTRICT_TO_RANGE(i, 0x0C, 0x3F);
-		if (uvd->vpic_old.brightness == i)
-			break;
-		uvd->vpic_old.brightness = i;
-		ibmcam_veio(uvd, 0, 0x0000, 0x010c);	/* Stop */
-		ibmcam_model3_Packet1(uvd, 0x0036, i);
-		ibmcam_veio(uvd, 0, 0x0001, 0x0114);
-		ibmcam_veio(uvd, 0, 0x00c0, 0x010c);	/* Go! */
-		usb_clear_halt(uvd->dev, usb_rcvisocpipe(uvd->dev, uvd->video_endp));
-		ibmcam_veio(uvd, 0, 0x0001, 0x0113);
-		break;
-	}
-	case IBMCAM_MODEL_4:
-	{
-		/* Model 4: Brightness range 'i' in [0x04..0xb4] */
-		unsigned short i = 0x04 + (uvd->vpic.brightness / (0xFFFF / (0xb4 - 0x04 + 1)));
-		RESTRICT_TO_RANGE(i, 0x04, 0xb4);
-		if (uvd->vpic_old.brightness == i)
-			break;
-		uvd->vpic_old.brightness = i;
-		ibmcam_model4_BrightnessPacket(uvd, i);
-		break;
-	}
-	default:
-		break;
-	}
-}
-
-static void ibmcam_set_hue(struct uvd *uvd)
-{
-	switch (IBMCAM_T(uvd)->camera_model) {
-	case IBMCAM_MODEL_2:
-	{
-		unsigned short hue = uvd->vpic.hue >> 9; /* 0 .. 7F */
-		if (uvd->vpic_old.hue == hue)
-			return;
-		uvd->vpic_old.hue = hue;
-		ibmcam_model2_Packet1(uvd, mod2_hue, hue);
-		/* ibmcam_model2_Packet1(uvd, mod2_saturation, sat); */
-		break;
-	}
-	case IBMCAM_MODEL_3:
-	{
-#if 0 /* This seems not to work. No problem, will fix programmatically */
-		unsigned short hue = 0x05 + (uvd->vpic.hue / (0xFFFF / (0x37 - 0x05 + 1)));
-		RESTRICT_TO_RANGE(hue, 0x05, 0x37);
-		if (uvd->vpic_old.hue == hue)
-			return;
-		uvd->vpic_old.hue = hue;
-		ibmcam_veio(uvd, 0, 0x0000, 0x010c);	/* Stop */
-		ibmcam_model3_Packet1(uvd, 0x007e, hue);
-		ibmcam_veio(uvd, 0, 0x0001, 0x0114);
-		ibmcam_veio(uvd, 0, 0x00c0, 0x010c);	/* Go! */
-		usb_clear_halt(uvd->dev, usb_rcvisocpipe(uvd->dev, uvd->video_endp));
-		ibmcam_veio(uvd, 0, 0x0001, 0x0113);
-#endif
-		break;
-	}
-	case IBMCAM_MODEL_4:
-	{
-		unsigned short r_gain, g_gain, b_gain, hue;
-
-		/*
-		 * I am not sure r/g/b_gain variables exactly control gain
-		 * of those channels. Most likely they subtly change some
-		 * very internal image processing settings in the camera.
-		 * In any case, here is what they do, and feel free to tweak:
-		 *
-		 * r_gain: seriously affects red gain
-		 * g_gain: seriously affects green gain
-		 * b_gain: seriously affects blue gain
-		 * hue: changes average color from violet (0) to red (0xFF)
-		 *
-		 * These settings are preset for a decent white balance in
-		 * 320x240, 352x288 modes. Low-res modes exhibit higher contrast
-		 * and therefore may need different values here.
-		 */
-		hue = 20 + (uvd->vpic.hue >> 9);
-		switch (uvd->videosize) {
-		case VIDEOSIZE_128x96:
-			r_gain = 90;
-			g_gain = 166;
-			b_gain = 175;
-			break;
-		case VIDEOSIZE_160x120:
-			r_gain = 70;
-			g_gain = 166;
-			b_gain = 185;
-			break;
-		case VIDEOSIZE_176x144:
-			r_gain = 160;
-			g_gain = 175;
-			b_gain = 185;
-			break;
-		default:
-			r_gain = 120;
-			g_gain = 166;
-			b_gain = 175;
-			break;
-		}
-		RESTRICT_TO_RANGE(hue, 1, 0x7f);
-
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
-		ibmcam_veio(uvd, 0, 0x001e, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
-		ibmcam_veio(uvd, 0, g_gain, 0x0127);	/* Green gain */
-		ibmcam_veio(uvd, 0, r_gain, 0x012e);	/* Red gain */
-		ibmcam_veio(uvd, 0, b_gain, 0x0130);	/* Blue gain */
-		ibmcam_veio(uvd, 0, 0x8a28, 0x0124);
-		ibmcam_veio(uvd, 0, hue,    0x012d);	/* Hue */
-		ibmcam_veio(uvd, 0, 0xf545, 0x0124);
-		break;
-	}
-	default:
-		break;
-	}
-}
-
-/*
- * ibmcam_adjust_picture()
- *
- * This procedure gets called from V4L interface to update picture settings.
- * Here we change brightness and contrast.
- */
-static void ibmcam_adjust_picture(struct uvd *uvd)
-{
-	ibmcam_adjust_contrast(uvd);
-	ibmcam_set_brightness(uvd);
-	ibmcam_set_hue(uvd);
-}
-
-static int ibmcam_model1_setup(struct uvd *uvd)
-{
-	const int ntries = 5;
-	int i;
-
-	ibmcam_veio(uvd, 1, 0x00, 0x0128);
-	ibmcam_veio(uvd, 1, 0x00, 0x0100);
-	ibmcam_veio(uvd, 0, 0x01, 0x0100);	/* LED On  */
-	ibmcam_veio(uvd, 1, 0x00, 0x0100);
-	ibmcam_veio(uvd, 0, 0x81, 0x0100);	/* LED Off */
-	ibmcam_veio(uvd, 1, 0x00, 0x0100);
-	ibmcam_veio(uvd, 0, 0x01, 0x0100);	/* LED On  */
-	ibmcam_veio(uvd, 0, 0x01, 0x0108);
-
-	ibmcam_veio(uvd, 0, 0x03, 0x0112);
-	ibmcam_veio(uvd, 1, 0x00, 0x0115);
-	ibmcam_veio(uvd, 0, 0x06, 0x0115);
-	ibmcam_veio(uvd, 1, 0x00, 0x0116);
-	ibmcam_veio(uvd, 0, 0x44, 0x0116);
-	ibmcam_veio(uvd, 1, 0x00, 0x0116);
-	ibmcam_veio(uvd, 0, 0x40, 0x0116);
-	ibmcam_veio(uvd, 1, 0x00, 0x0115);
-	ibmcam_veio(uvd, 0, 0x0e, 0x0115);
-	ibmcam_veio(uvd, 0, 0x19, 0x012c);
-
-	ibmcam_Packet_Format1(uvd, 0x00, 0x1e);
-	ibmcam_Packet_Format1(uvd, 0x39, 0x0d);
-	ibmcam_Packet_Format1(uvd, 0x39, 0x09);
-	ibmcam_Packet_Format1(uvd, 0x3b, 0x00);
-	ibmcam_Packet_Format1(uvd, 0x28, 0x22);
-	ibmcam_Packet_Format1(uvd, light_27, 0);
-	ibmcam_Packet_Format1(uvd, 0x2b, 0x1f);
-	ibmcam_Packet_Format1(uvd, 0x39, 0x08);
-
-	for (i=0; i < ntries; i++)
-		ibmcam_Packet_Format1(uvd, 0x2c, 0x00);
-
-	for (i=0; i < ntries; i++)
-		ibmcam_Packet_Format1(uvd, 0x30, 0x14);
-
-	ibmcam_PacketFormat2(uvd, 0x39, 0x02);
-	ibmcam_PacketFormat2(uvd, 0x01, 0xe1);
-	ibmcam_PacketFormat2(uvd, 0x02, 0xcd);
-	ibmcam_PacketFormat2(uvd, 0x03, 0xcd);
-	ibmcam_PacketFormat2(uvd, 0x04, 0xfa);
-	ibmcam_PacketFormat2(uvd, 0x3f, 0xff);
-	ibmcam_PacketFormat2(uvd, 0x39, 0x00);
-
-	ibmcam_PacketFormat2(uvd, 0x39, 0x02);
-	ibmcam_PacketFormat2(uvd, 0x0a, 0x37);
-	ibmcam_PacketFormat2(uvd, 0x0b, 0xb8);
-	ibmcam_PacketFormat2(uvd, 0x0c, 0xf3);
-	ibmcam_PacketFormat2(uvd, 0x0d, 0xe3);
-	ibmcam_PacketFormat2(uvd, 0x0e, 0x0d);
-	ibmcam_PacketFormat2(uvd, 0x0f, 0xf2);
-	ibmcam_PacketFormat2(uvd, 0x10, 0xd5);
-	ibmcam_PacketFormat2(uvd, 0x11, 0xba);
-	ibmcam_PacketFormat2(uvd, 0x12, 0x53);
-	ibmcam_PacketFormat2(uvd, 0x3f, 0xff);
-	ibmcam_PacketFormat2(uvd, 0x39, 0x00);
-
-	ibmcam_PacketFormat2(uvd, 0x39, 0x02);
-	ibmcam_PacketFormat2(uvd, 0x16, 0x00);
-	ibmcam_PacketFormat2(uvd, 0x17, 0x28);
-	ibmcam_PacketFormat2(uvd, 0x18, 0x7d);
-	ibmcam_PacketFormat2(uvd, 0x19, 0xbe);
-	ibmcam_PacketFormat2(uvd, 0x3f, 0xff);
-	ibmcam_PacketFormat2(uvd, 0x39, 0x00);
-
-	for (i=0; i < ntries; i++)
-		ibmcam_Packet_Format1(uvd, 0x00, 0x18);
-	for (i=0; i < ntries; i++)
-		ibmcam_Packet_Format1(uvd, 0x13, 0x18);
-	for (i=0; i < ntries; i++)
-		ibmcam_Packet_Format1(uvd, 0x14, 0x06);
-
-	/* This is default brightness */
-	for (i=0; i < ntries; i++)
-		ibmcam_Packet_Format1(uvd, 0x31, 0x37);
-	for (i=0; i < ntries; i++)
-		ibmcam_Packet_Format1(uvd, 0x32, 0x46);
-	for (i=0; i < ntries; i++)
-		ibmcam_Packet_Format1(uvd, 0x33, 0x55);
-
-	ibmcam_Packet_Format1(uvd, 0x2e, 0x04);
-	for (i=0; i < ntries; i++)
-		ibmcam_Packet_Format1(uvd, 0x2d, 0x04);
-	for (i=0; i < ntries; i++)
-		ibmcam_Packet_Format1(uvd, 0x29, 0x80);
-	ibmcam_Packet_Format1(uvd, 0x2c, 0x01);
-	ibmcam_Packet_Format1(uvd, 0x30, 0x17);
-	ibmcam_Packet_Format1(uvd, 0x39, 0x08);
-	for (i=0; i < ntries; i++)
-		ibmcam_Packet_Format1(uvd, 0x34, 0x00);
-
-	ibmcam_veio(uvd, 0, 0x00, 0x0101);
-	ibmcam_veio(uvd, 0, 0x00, 0x010a);
-
-	switch (uvd->videosize) {
-	case VIDEOSIZE_128x96:
-		ibmcam_veio(uvd, 0, 0x80, 0x0103);
-		ibmcam_veio(uvd, 0, 0x60, 0x0105);
-		ibmcam_veio(uvd, 0, 0x0c, 0x010b);
-		ibmcam_veio(uvd, 0, 0x04, 0x011b);	/* Same everywhere */
-		ibmcam_veio(uvd, 0, 0x0b, 0x011d);
-		ibmcam_veio(uvd, 0, 0x00, 0x011e);	/* Same everywhere */
-		ibmcam_veio(uvd, 0, 0x00, 0x0129);
-		break;
-	case VIDEOSIZE_176x144:
-		ibmcam_veio(uvd, 0, 0xb0, 0x0103);
-		ibmcam_veio(uvd, 0, 0x8f, 0x0105);
-		ibmcam_veio(uvd, 0, 0x06, 0x010b);
-		ibmcam_veio(uvd, 0, 0x04, 0x011b);	/* Same everywhere */
-		ibmcam_veio(uvd, 0, 0x0d, 0x011d);
-		ibmcam_veio(uvd, 0, 0x00, 0x011e);	/* Same everywhere */
-		ibmcam_veio(uvd, 0, 0x03, 0x0129);
-		break;
-	case VIDEOSIZE_352x288:
-		ibmcam_veio(uvd, 0, 0xb0, 0x0103);
-		ibmcam_veio(uvd, 0, 0x90, 0x0105);
-		ibmcam_veio(uvd, 0, 0x02, 0x010b);
-		ibmcam_veio(uvd, 0, 0x04, 0x011b);	/* Same everywhere */
-		ibmcam_veio(uvd, 0, 0x05, 0x011d);
-		ibmcam_veio(uvd, 0, 0x00, 0x011e);	/* Same everywhere */
-		ibmcam_veio(uvd, 0, 0x00, 0x0129);
-		break;
-	}
-
-	ibmcam_veio(uvd, 0, 0xff, 0x012b);
-
-	/* This is another brightness - don't know why */
-	for (i=0; i < ntries; i++)
-		ibmcam_Packet_Format1(uvd, 0x31, 0xc3);
-	for (i=0; i < ntries; i++)
-		ibmcam_Packet_Format1(uvd, 0x32, 0xd2);
-	for (i=0; i < ntries; i++)
-		ibmcam_Packet_Format1(uvd, 0x33, 0xe1);
-
-	/* Default contrast */
-	for (i=0; i < ntries; i++)
-		ibmcam_Packet_Format1(uvd, contrast_14, 0x0a);
-
-	/* Default sharpness */
-	for (i=0; i < 2; i++)
-		ibmcam_PacketFormat2(uvd, sharp_13, 0x1a);	/* Level 4 FIXME */
-
-	/* Default lighting conditions */
-	ibmcam_Packet_Format1(uvd, light_27, lighting); /* 0=Bright 2=Low */
-
-	/* Assorted init */
-
-	switch (uvd->videosize) {
-	case VIDEOSIZE_128x96:
-		ibmcam_Packet_Format1(uvd, 0x2b, 0x1e);
-		ibmcam_veio(uvd, 0, 0xc9, 0x0119);	/* Same everywhere */
-		ibmcam_veio(uvd, 0, 0x80, 0x0109);	/* Same everywhere */
-		ibmcam_veio(uvd, 0, 0x36, 0x0102);
-		ibmcam_veio(uvd, 0, 0x1a, 0x0104);
-		ibmcam_veio(uvd, 0, 0x04, 0x011a);	/* Same everywhere */
-		ibmcam_veio(uvd, 0, 0x2b, 0x011c);
-		ibmcam_veio(uvd, 0, 0x23, 0x012a);	/* Same everywhere */
-#if 0
-		ibmcam_veio(uvd, 0, 0x00, 0x0106);
-		ibmcam_veio(uvd, 0, 0x38, 0x0107);
-#else
-		ibmcam_veio(uvd, 0, 0x02, 0x0106);
-		ibmcam_veio(uvd, 0, 0x2a, 0x0107);
-#endif
-		break;
-	case VIDEOSIZE_176x144:
-		ibmcam_Packet_Format1(uvd, 0x2b, 0x1e);
-		ibmcam_veio(uvd, 0, 0xc9, 0x0119);	/* Same everywhere */
-		ibmcam_veio(uvd, 0, 0x80, 0x0109);	/* Same everywhere */
-		ibmcam_veio(uvd, 0, 0x04, 0x0102);
-		ibmcam_veio(uvd, 0, 0x02, 0x0104);
-		ibmcam_veio(uvd, 0, 0x04, 0x011a);	/* Same everywhere */
-		ibmcam_veio(uvd, 0, 0x2b, 0x011c);
-		ibmcam_veio(uvd, 0, 0x23, 0x012a);	/* Same everywhere */
-		ibmcam_veio(uvd, 0, 0x01, 0x0106);
-		ibmcam_veio(uvd, 0, 0xca, 0x0107);
-		break;
-	case VIDEOSIZE_352x288:
-		ibmcam_Packet_Format1(uvd, 0x2b, 0x1f);
-		ibmcam_veio(uvd, 0, 0xc9, 0x0119);	/* Same everywhere */
-		ibmcam_veio(uvd, 0, 0x80, 0x0109);	/* Same everywhere */
-		ibmcam_veio(uvd, 0, 0x08, 0x0102);
-		ibmcam_veio(uvd, 0, 0x01, 0x0104);
-		ibmcam_veio(uvd, 0, 0x04, 0x011a);	/* Same everywhere */
-		ibmcam_veio(uvd, 0, 0x2f, 0x011c);
-		ibmcam_veio(uvd, 0, 0x23, 0x012a);	/* Same everywhere */
-		ibmcam_veio(uvd, 0, 0x03, 0x0106);
-		ibmcam_veio(uvd, 0, 0xf6, 0x0107);
-		break;
-	}
-	return (CAMERA_IS_OPERATIONAL(uvd) ? 0 : -EFAULT);
-}
-
-static int ibmcam_model2_setup(struct uvd *uvd)
-{
-	ibmcam_veio(uvd, 0, 0x0000, 0x0100);	/* LED on */
-	ibmcam_veio(uvd, 1, 0x0000, 0x0116);
-	ibmcam_veio(uvd, 0, 0x0060, 0x0116);
-	ibmcam_veio(uvd, 0, 0x0002, 0x0112);
-	ibmcam_veio(uvd, 0, 0x00bc, 0x012c);
-	ibmcam_veio(uvd, 0, 0x0008, 0x012b);
-	ibmcam_veio(uvd, 0, 0x0000, 0x0108);
-	ibmcam_veio(uvd, 0, 0x0001, 0x0133);
-	ibmcam_veio(uvd, 0, 0x0001, 0x0102);
-	switch (uvd->videosize) {
-	case VIDEOSIZE_176x144:
-		ibmcam_veio(uvd, 0, 0x002c, 0x0103);	/* All except 320x240 */
-		ibmcam_veio(uvd, 0, 0x0000, 0x0104);	/* Same */
-		ibmcam_veio(uvd, 0, 0x0024, 0x0105);	/* 176x144, 352x288 */
-		ibmcam_veio(uvd, 0, 0x00b9, 0x010a);	/* Unique to this mode */
-		ibmcam_veio(uvd, 0, 0x0038, 0x0119);	/* Unique to this mode */
-		ibmcam_veio(uvd, 0, 0x0003, 0x0106);	/* Same */
-		ibmcam_veio(uvd, 0, 0x0090, 0x0107);	/* Unique to every mode*/
-		break;
-	case VIDEOSIZE_320x240:
-		ibmcam_veio(uvd, 0, 0x0028, 0x0103);	/* Unique to this mode */
-		ibmcam_veio(uvd, 0, 0x0000, 0x0104);	/* Same */
-		ibmcam_veio(uvd, 0, 0x001e, 0x0105);	/* 320x240, 352x240 */
-		ibmcam_veio(uvd, 0, 0x0039, 0x010a);	/* All except 176x144 */
-		ibmcam_veio(uvd, 0, 0x0070, 0x0119);	/* All except 176x144 */
-		ibmcam_veio(uvd, 0, 0x0003, 0x0106);	/* Same */
-		ibmcam_veio(uvd, 0, 0x0098, 0x0107);	/* Unique to every mode*/
-		break;
-	case VIDEOSIZE_352x240:
-		ibmcam_veio(uvd, 0, 0x002c, 0x0103);	/* All except 320x240 */
-		ibmcam_veio(uvd, 0, 0x0000, 0x0104);	/* Same */
-		ibmcam_veio(uvd, 0, 0x001e, 0x0105);	/* 320x240, 352x240 */
-		ibmcam_veio(uvd, 0, 0x0039, 0x010a);	/* All except 176x144 */
-		ibmcam_veio(uvd, 0, 0x0070, 0x0119);	/* All except 176x144 */
-		ibmcam_veio(uvd, 0, 0x0003, 0x0106);	/* Same */
-		ibmcam_veio(uvd, 0, 0x00da, 0x0107);	/* Unique to every mode*/
-		break;
-	case VIDEOSIZE_352x288:
-		ibmcam_veio(uvd, 0, 0x002c, 0x0103);	/* All except 320x240 */
-		ibmcam_veio(uvd, 0, 0x0000, 0x0104);	/* Same */
-		ibmcam_veio(uvd, 0, 0x0024, 0x0105);	/* 176x144, 352x288 */
-		ibmcam_veio(uvd, 0, 0x0039, 0x010a);	/* All except 176x144 */
-		ibmcam_veio(uvd, 0, 0x0070, 0x0119);	/* All except 176x144 */
-		ibmcam_veio(uvd, 0, 0x0003, 0x0106);	/* Same */
-		ibmcam_veio(uvd, 0, 0x00fe, 0x0107);	/* Unique to every mode*/
-		break;
-	}
-	return (CAMERA_IS_OPERATIONAL(uvd) ? 0 : -EFAULT);
-}
-
-/*
- * ibmcam_model1_setup_after_video_if()
- *
- * This code adds finishing touches to the video data interface.
- * Here we configure the frame rate and turn on the LED.
- */
-static void ibmcam_model1_setup_after_video_if(struct uvd *uvd)
-{
-	unsigned short internal_frame_rate;
-
-	RESTRICT_TO_RANGE(framerate, FRAMERATE_MIN, FRAMERATE_MAX);
-	internal_frame_rate = FRAMERATE_MAX - framerate; /* 0=Fast 6=Slow */
-	ibmcam_veio(uvd, 0, 0x01, 0x0100);	/* LED On  */
-	ibmcam_veio(uvd, 0, internal_frame_rate, 0x0111);
-	ibmcam_veio(uvd, 0, 0x01, 0x0114);
-	ibmcam_veio(uvd, 0, 0xc0, 0x010c);
-}
-
-static void ibmcam_model2_setup_after_video_if(struct uvd *uvd)
-{
-	unsigned short setup_model2_rg2, setup_model2_sat, setup_model2_yb;
-
-	ibmcam_veio(uvd, 0, 0x0000, 0x0100);	/* LED on */
-
-	switch (uvd->videosize) {
-	case VIDEOSIZE_176x144:
-		ibmcam_veio(uvd, 0, 0x0050, 0x0111);
-		ibmcam_veio(uvd, 0, 0x00d0, 0x0111);
-		break;
-	case VIDEOSIZE_320x240:
-	case VIDEOSIZE_352x240:
-	case VIDEOSIZE_352x288:
-		ibmcam_veio(uvd, 0, 0x0040, 0x0111);
-		ibmcam_veio(uvd, 0, 0x00c0, 0x0111);
-		break;
-	}
-	ibmcam_veio(uvd, 0, 0x009b, 0x010f);
-	ibmcam_veio(uvd, 0, 0x00bb, 0x010f);
-
-	/*
-	 * Hardware settings, may affect CMOS sensor; not user controls!
-	 * -------------------------------------------------------------
-	 * 0x0004: no effect
-	 * 0x0006: hardware effect
-	 * 0x0008: no effect
-	 * 0x000a: stops video stream, probably important h/w setting
-	 * 0x000c: changes color in hardware manner (not user setting)
-	 * 0x0012: changes number of colors (does not affect speed)
-	 * 0x002a: no effect
-	 * 0x002c: hardware setting (related to scan lines)
-	 * 0x002e: stops video stream, probably important h/w setting
-	 */
-	ibmcam_model2_Packet1(uvd, 0x000a, 0x005c);
-	ibmcam_model2_Packet1(uvd, 0x0004, 0x0000);
-	ibmcam_model2_Packet1(uvd, 0x0006, 0x00fb);
-	ibmcam_model2_Packet1(uvd, 0x0008, 0x0000);
-	ibmcam_model2_Packet1(uvd, 0x000c, 0x0009);
-	ibmcam_model2_Packet1(uvd, 0x0012, 0x000a);
-	ibmcam_model2_Packet1(uvd, 0x002a, 0x0000);
-	ibmcam_model2_Packet1(uvd, 0x002c, 0x0000);
-	ibmcam_model2_Packet1(uvd, 0x002e, 0x0008);
-
-	/*
-	 * Function 0x0030 pops up all over the place. Apparently
-	 * it is a hardware control register, with every bit assigned to
-	 * do something.
-	 */
-	ibmcam_model2_Packet1(uvd, 0x0030, 0x0000);
-
-	/*
-	 * Magic control of CMOS sensor. Only lower values like
-	 * 0-3 work, and picture shifts left or right. Don't change.
-	 */
-	switch (uvd->videosize) {
-	case VIDEOSIZE_176x144:
-		ibmcam_model2_Packet1(uvd, 0x0014, 0x0002);
-		ibmcam_model2_Packet1(uvd, 0x0016, 0x0002); /* Horizontal shift */
-		ibmcam_model2_Packet1(uvd, 0x0018, 0x004a); /* Another hardware setting */
-		break;
-	case VIDEOSIZE_320x240:
-		ibmcam_model2_Packet1(uvd, 0x0014, 0x0009);
-		ibmcam_model2_Packet1(uvd, 0x0016, 0x0005); /* Horizontal shift */
-		ibmcam_model2_Packet1(uvd, 0x0018, 0x0044); /* Another hardware setting */
-		break;
-	case VIDEOSIZE_352x240:
-		/* This mode doesn't work as Windows programs it; changed to work */
-		ibmcam_model2_Packet1(uvd, 0x0014, 0x0009); /* Windows sets this to 8 */
-		ibmcam_model2_Packet1(uvd, 0x0016, 0x0003); /* Horizontal shift */
-		ibmcam_model2_Packet1(uvd, 0x0018, 0x0044); /* Windows sets this to 0x0045 */
-		break;
-	case VIDEOSIZE_352x288:
-		ibmcam_model2_Packet1(uvd, 0x0014, 0x0003);
-		ibmcam_model2_Packet1(uvd, 0x0016, 0x0002); /* Horizontal shift */
-		ibmcam_model2_Packet1(uvd, 0x0018, 0x004a); /* Another hardware setting */
-		break;
-	}
-
-	ibmcam_model2_Packet1(uvd, mod2_brightness, 0x005a);
-
-	/*
-	 * We have our own frame rate setting varying from 0 (slowest) to 6 (fastest).
-	 * The camera model 2 allows frame rate in range [0..0x1F] where 0 is also the
-	 * slowest setting. However for all practical reasons high settings make no
-	 * sense because USB is not fast enough to support high FPS. Be aware that
-	 * the picture datastream will be severely disrupted if you ask for
-	 * frame rate faster than allowed for the video size - see below:
-	 *
-	 * Allowable ranges (obtained experimentally on OHCI, K6-3, 450 MHz):
-	 * -----------------------------------------------------------------
-	 * 176x144: [6..31]
-	 * 320x240: [8..31]
-	 * 352x240: [10..31]
-	 * 352x288: [16..31] I have to raise lower threshold for stability...
-	 *
-	 * As usual, slower FPS provides better sensitivity.
-	 */
-	{
-		short hw_fps=31, i_framerate;
-
-		RESTRICT_TO_RANGE(framerate, FRAMERATE_MIN, FRAMERATE_MAX);
-		i_framerate = FRAMERATE_MAX - framerate + FRAMERATE_MIN;
-		switch (uvd->videosize) {
-		case VIDEOSIZE_176x144:
-			hw_fps = 6 + i_framerate*4;
-			break;
-		case VIDEOSIZE_320x240:
-			hw_fps = 8 + i_framerate*3;
-			break;
-		case VIDEOSIZE_352x240:
-			hw_fps = 10 + i_framerate*2;
-			break;
-		case VIDEOSIZE_352x288:
-			hw_fps = 28 + i_framerate/2;
-			break;
-		}
-		if (uvd->debug > 0)
-			dev_info(&uvd->dev->dev, "Framerate (hardware): %hd.\n",
-				 hw_fps);
-		RESTRICT_TO_RANGE(hw_fps, 0, 31);
-		ibmcam_model2_Packet1(uvd, mod2_set_framerate, hw_fps);
-	}
-
-	/*
-	 * This setting does not visibly affect pictures; left it here
-	 * because it was present in Windows USB data stream. This function
-	 * does not allow arbitrary values and apparently is a bit mask, to
-	 * be activated only at appropriate time. Don't change it randomly!
-	 */
-	switch (uvd->videosize) {
-	case VIDEOSIZE_176x144:
-		ibmcam_model2_Packet1(uvd, 0x0026, 0x00c2);
-		break;
-	case VIDEOSIZE_320x240:
-		ibmcam_model2_Packet1(uvd, 0x0026, 0x0044);
-		break;
-	case VIDEOSIZE_352x240:
-		ibmcam_model2_Packet1(uvd, 0x0026, 0x0046);
-		break;
-	case VIDEOSIZE_352x288:
-		ibmcam_model2_Packet1(uvd, 0x0026, 0x0048);
-		break;
-	}
-
-	ibmcam_model2_Packet1(uvd, mod2_sensitivity, lighting);
-
-	if (init_model2_rg2 >= 0) {
-		RESTRICT_TO_RANGE(init_model2_rg2, 0, 255);
-		setup_model2_rg2 = init_model2_rg2;
-	} else
-		setup_model2_rg2 = 0x002f;
-
-	if (init_model2_sat >= 0) {
-		RESTRICT_TO_RANGE(init_model2_sat, 0, 255);
-		setup_model2_sat = init_model2_sat;
-	} else
-		setup_model2_sat = 0x0034;
-
-	if (init_model2_yb >= 0) {
-		RESTRICT_TO_RANGE(init_model2_yb, 0, 255);
-		setup_model2_yb = init_model2_yb;
-	} else
-		setup_model2_yb = 0x00a0;
-
-	ibmcam_model2_Packet1(uvd, mod2_color_balance_rg2, setup_model2_rg2);
-	ibmcam_model2_Packet1(uvd, mod2_saturation, setup_model2_sat);
-	ibmcam_model2_Packet1(uvd, mod2_color_balance_yb, setup_model2_yb);
-	ibmcam_model2_Packet1(uvd, mod2_hue, uvd->vpic.hue >> 9); /* 0 .. 7F */;
-
-	/* Hardware control command */
-	ibmcam_model2_Packet1(uvd, 0x0030, 0x0004);
-
-	ibmcam_veio(uvd, 0, 0x00c0, 0x010c);	/* Go camera, go! */
-	usb_clear_halt(uvd->dev, usb_rcvisocpipe(uvd->dev, uvd->video_endp));
-}
-
-static void ibmcam_model4_setup_after_video_if(struct uvd *uvd)
-{
-	switch (uvd->videosize) {
-	case VIDEOSIZE_128x96:
-		ibmcam_veio(uvd, 0, 0x0000, 0x0100);
-		ibmcam_veio(uvd, 0, 0x00c0, 0x0111);
-		ibmcam_veio(uvd, 0, 0x00bc, 0x012c);
-		ibmcam_veio(uvd, 0, 0x0080, 0x012b);
-		ibmcam_veio(uvd, 0, 0x0000, 0x0108);
-		ibmcam_veio(uvd, 0, 0x0001, 0x0133);
-		ibmcam_veio(uvd, 0, 0x009b, 0x010f);
-		ibmcam_veio(uvd, 0, 0x00bb, 0x010f);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0038, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0000, 0x0127);
-		ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
-		ibmcam_veio(uvd, 0, 0x000a, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
-		ibmcam_veio(uvd, 0, 0x005c, 0x0127);
-		ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0004, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0000, 0x0127);
-		ibmcam_veio(uvd, 0, 0x00fb, 0x012e);
-		ibmcam_veio(uvd, 0, 0x0000, 0x0130);
-		ibmcam_veio(uvd, 0, 0x8a28, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd055, 0x0124);
-		ibmcam_veio(uvd, 0, 0x000c, 0x0127);
-		ibmcam_veio(uvd, 0, 0x0009, 0x012e);
-		ibmcam_veio(uvd, 0, 0xaa28, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0012, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0008, 0x0127);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x0130);
-		ibmcam_veio(uvd, 0, 0x82a8, 0x0124);
-		ibmcam_veio(uvd, 0, 0x002a, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0000, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd145, 0x0124);
-		ibmcam_veio(uvd, 0, 0xfffa, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0034, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0000, 0x0127);
-		ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0070, 0x0119);
-		ibmcam_veio(uvd, 0, 0x00d2, 0x0107);
-		ibmcam_veio(uvd, 0, 0x0003, 0x0106);
-		ibmcam_veio(uvd, 0, 0x005e, 0x0107);
-		ibmcam_veio(uvd, 0, 0x0003, 0x0106);
-		ibmcam_veio(uvd, 0, 0x00d0, 0x0111);
-		ibmcam_veio(uvd, 0, 0x0039, 0x010a);
-		ibmcam_veio(uvd, 0, 0x0001, 0x0102);
-		ibmcam_veio(uvd, 0, 0x0028, 0x0103);
-		ibmcam_veio(uvd, 0, 0x0000, 0x0104);
-		ibmcam_veio(uvd, 0, 0x001e, 0x0105);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0016, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
-		ibmcam_veio(uvd, 0, 0x000a, 0x0127);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x0130);
-		ibmcam_veio(uvd, 0, 0x82a8, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0014, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0008, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd145, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012e);
-		ibmcam_veio(uvd, 0, 0x001a, 0x0130);
-		ibmcam_veio(uvd, 0, 0x8a0a, 0x0124);
-		ibmcam_veio(uvd, 0, 0x005a, 0x012d);
-		ibmcam_veio(uvd, 0, 0x9545, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x0127);
-		ibmcam_veio(uvd, 0, 0x0018, 0x012e);
-		ibmcam_veio(uvd, 0, 0x0043, 0x0130);
-		ibmcam_veio(uvd, 0, 0x8a28, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd055, 0x0124);
-		ibmcam_veio(uvd, 0, 0x001c, 0x0127);
-		ibmcam_veio(uvd, 0, 0x00eb, 0x012e);
-		ibmcam_veio(uvd, 0, 0xaa28, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0032, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0000, 0x0127);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x0130);
-		ibmcam_veio(uvd, 0, 0x82a8, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0036, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0008, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd145, 0x0124);
-		ibmcam_veio(uvd, 0, 0xfffa, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
-		ibmcam_veio(uvd, 0, 0x001e, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0017, 0x0127);
-		ibmcam_veio(uvd, 0, 0x0013, 0x012e);
-		ibmcam_veio(uvd, 0, 0x0031, 0x0130);
-		ibmcam_veio(uvd, 0, 0x8a28, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0017, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0078, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd145, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0000, 0x0127);
-		ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0038, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0004, 0x0127);
-		ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00c0, 0x010c);
-		break;
-	case VIDEOSIZE_160x120:
-		ibmcam_veio(uvd, 0, 0x0000, 0x0100);
-		ibmcam_veio(uvd, 0, 0x00c0, 0x0111);
-		ibmcam_veio(uvd, 0, 0x00bc, 0x012c);
-		ibmcam_veio(uvd, 0, 0x0080, 0x012b);
-		ibmcam_veio(uvd, 0, 0x0000, 0x0108);
-		ibmcam_veio(uvd, 0, 0x0001, 0x0133);
-		ibmcam_veio(uvd, 0, 0x009b, 0x010f);
-		ibmcam_veio(uvd, 0, 0x00bb, 0x010f);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0038, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0000, 0x0127);
-		ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
-		ibmcam_veio(uvd, 0, 0x000a, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
-		ibmcam_veio(uvd, 0, 0x005c, 0x0127);
-		ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0004, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0000, 0x0127);
-		ibmcam_veio(uvd, 0, 0x00fb, 0x012e);
-		ibmcam_veio(uvd, 0, 0x0000, 0x0130);
-		ibmcam_veio(uvd, 0, 0x8a28, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd055, 0x0124);
-		ibmcam_veio(uvd, 0, 0x000c, 0x0127);
-		ibmcam_veio(uvd, 0, 0x0009, 0x012e);
-		ibmcam_veio(uvd, 0, 0xaa28, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0012, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0008, 0x0127);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x0130);
-		ibmcam_veio(uvd, 0, 0x82a8, 0x0124);
-		ibmcam_veio(uvd, 0, 0x002a, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0000, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd145, 0x0124);
-		ibmcam_veio(uvd, 0, 0xfffa, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0034, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0000, 0x0127);
-		ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0038, 0x0119);
-		ibmcam_veio(uvd, 0, 0x00d8, 0x0107);
-		ibmcam_veio(uvd, 0, 0x0002, 0x0106);
-		ibmcam_veio(uvd, 0, 0x00d0, 0x0111);
-		ibmcam_veio(uvd, 0, 0x00b9, 0x010a);
-		ibmcam_veio(uvd, 0, 0x0001, 0x0102);
-		ibmcam_veio(uvd, 0, 0x0028, 0x0103);
-		ibmcam_veio(uvd, 0, 0x0000, 0x0104);
-		ibmcam_veio(uvd, 0, 0x001e, 0x0105);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0016, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
-		ibmcam_veio(uvd, 0, 0x000b, 0x0127);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x0130);
-		ibmcam_veio(uvd, 0, 0x82a8, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0014, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0008, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd145, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012e);
-		ibmcam_veio(uvd, 0, 0x001a, 0x0130);
-		ibmcam_veio(uvd, 0, 0x8a0a, 0x0124);
-		ibmcam_veio(uvd, 0, 0x005a, 0x012d);
-		ibmcam_veio(uvd, 0, 0x9545, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x0127);
-		ibmcam_veio(uvd, 0, 0x0018, 0x012e);
-		ibmcam_veio(uvd, 0, 0x0043, 0x0130);
-		ibmcam_veio(uvd, 0, 0x8a28, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd055, 0x0124);
-		ibmcam_veio(uvd, 0, 0x001c, 0x0127);
-		ibmcam_veio(uvd, 0, 0x00c7, 0x012e);
-		ibmcam_veio(uvd, 0, 0xaa28, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0032, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0025, 0x0127);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x0130);
-		ibmcam_veio(uvd, 0, 0x82a8, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0036, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0008, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd145, 0x0124);
-		ibmcam_veio(uvd, 0, 0xfffa, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
-		ibmcam_veio(uvd, 0, 0x001e, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0048, 0x0127);
-		ibmcam_veio(uvd, 0, 0x0035, 0x012e);
-		ibmcam_veio(uvd, 0, 0x00d0, 0x0130);
-		ibmcam_veio(uvd, 0, 0x8a28, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0048, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0090, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd145, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0001, 0x0127);
-		ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0038, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0004, 0x0127);
-		ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00c0, 0x010c);
-		break;
-	case VIDEOSIZE_176x144:
-		ibmcam_veio(uvd, 0, 0x0000, 0x0100);
-		ibmcam_veio(uvd, 0, 0x00c0, 0x0111);
-		ibmcam_veio(uvd, 0, 0x00bc, 0x012c);
-		ibmcam_veio(uvd, 0, 0x0080, 0x012b);
-		ibmcam_veio(uvd, 0, 0x0000, 0x0108);
-		ibmcam_veio(uvd, 0, 0x0001, 0x0133);
-		ibmcam_veio(uvd, 0, 0x009b, 0x010f);
-		ibmcam_veio(uvd, 0, 0x00bb, 0x010f);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0038, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0000, 0x0127);
-		ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
-		ibmcam_veio(uvd, 0, 0x000a, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
-		ibmcam_veio(uvd, 0, 0x005c, 0x0127);
-		ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0004, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0000, 0x0127);
-		ibmcam_veio(uvd, 0, 0x00fb, 0x012e);
-		ibmcam_veio(uvd, 0, 0x0000, 0x0130);
-		ibmcam_veio(uvd, 0, 0x8a28, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd055, 0x0124);
-		ibmcam_veio(uvd, 0, 0x000c, 0x0127);
-		ibmcam_veio(uvd, 0, 0x0009, 0x012e);
-		ibmcam_veio(uvd, 0, 0xaa28, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0012, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0008, 0x0127);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x0130);
-		ibmcam_veio(uvd, 0, 0x82a8, 0x0124);
-		ibmcam_veio(uvd, 0, 0x002a, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0000, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd145, 0x0124);
-		ibmcam_veio(uvd, 0, 0xfffa, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0034, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0000, 0x0127);
-		ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0038, 0x0119);
-		ibmcam_veio(uvd, 0, 0x00d6, 0x0107);
-		ibmcam_veio(uvd, 0, 0x0003, 0x0106);
-		ibmcam_veio(uvd, 0, 0x0018, 0x0107);
-		ibmcam_veio(uvd, 0, 0x0003, 0x0106);
-		ibmcam_veio(uvd, 0, 0x00d0, 0x0111);
-		ibmcam_veio(uvd, 0, 0x00b9, 0x010a);
-		ibmcam_veio(uvd, 0, 0x0001, 0x0102);
-		ibmcam_veio(uvd, 0, 0x002c, 0x0103);
-		ibmcam_veio(uvd, 0, 0x0000, 0x0104);
-		ibmcam_veio(uvd, 0, 0x0024, 0x0105);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0016, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0007, 0x0127);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x0130);
-		ibmcam_veio(uvd, 0, 0x82a8, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0014, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0001, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd145, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012e);
-		ibmcam_veio(uvd, 0, 0x001a, 0x0130);
-		ibmcam_veio(uvd, 0, 0x8a0a, 0x0124);
-		ibmcam_veio(uvd, 0, 0x005e, 0x012d);
-		ibmcam_veio(uvd, 0, 0x9545, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x0127);
-		ibmcam_veio(uvd, 0, 0x0018, 0x012e);
-		ibmcam_veio(uvd, 0, 0x0049, 0x0130);
-		ibmcam_veio(uvd, 0, 0x8a28, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd055, 0x0124);
-		ibmcam_veio(uvd, 0, 0x001c, 0x0127);
-		ibmcam_veio(uvd, 0, 0x00c7, 0x012e);
-		ibmcam_veio(uvd, 0, 0xaa28, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0032, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0028, 0x0127);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x0130);
-		ibmcam_veio(uvd, 0, 0x82a8, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0036, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0008, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd145, 0x0124);
-		ibmcam_veio(uvd, 0, 0xfffa, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
-		ibmcam_veio(uvd, 0, 0x001e, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0010, 0x0127);
-		ibmcam_veio(uvd, 0, 0x0013, 0x012e);
-		ibmcam_veio(uvd, 0, 0x002a, 0x0130);
-		ibmcam_veio(uvd, 0, 0x8a28, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0010, 0x012d);
-		ibmcam_veio(uvd, 0, 0x006d, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd145, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0001, 0x0127);
-		ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0038, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0004, 0x0127);
-		ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00c0, 0x010c);
-		break;
-	case VIDEOSIZE_320x240:
-		ibmcam_veio(uvd, 0, 0x0000, 0x0100);
-		ibmcam_veio(uvd, 0, 0x00c0, 0x0111);
-		ibmcam_veio(uvd, 0, 0x00bc, 0x012c);
-		ibmcam_veio(uvd, 0, 0x0080, 0x012b);
-		ibmcam_veio(uvd, 0, 0x0000, 0x0108);
-		ibmcam_veio(uvd, 0, 0x0001, 0x0133);
-		ibmcam_veio(uvd, 0, 0x009b, 0x010f);
-		ibmcam_veio(uvd, 0, 0x00bb, 0x010f);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0038, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0000, 0x0127);
-		ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
-		ibmcam_veio(uvd, 0, 0x000a, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
-		ibmcam_veio(uvd, 0, 0x005c, 0x0127);
-		ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0004, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0000, 0x0127);
-		ibmcam_veio(uvd, 0, 0x00fb, 0x012e);
-		ibmcam_veio(uvd, 0, 0x0000, 0x0130);
-		ibmcam_veio(uvd, 0, 0x8a28, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd055, 0x0124);
-		ibmcam_veio(uvd, 0, 0x000c, 0x0127);
-		ibmcam_veio(uvd, 0, 0x0009, 0x012e);
-		ibmcam_veio(uvd, 0, 0xaa28, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0012, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0008, 0x0127);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x0130);
-		ibmcam_veio(uvd, 0, 0x82a8, 0x0124);
-		ibmcam_veio(uvd, 0, 0x002a, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0000, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd145, 0x0124);
-		ibmcam_veio(uvd, 0, 0xfffa, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0034, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0000, 0x0127);
-		ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0070, 0x0119);
-		ibmcam_veio(uvd, 0, 0x00d2, 0x0107);
-		ibmcam_veio(uvd, 0, 0x0003, 0x0106);
-		ibmcam_veio(uvd, 0, 0x005e, 0x0107);
-		ibmcam_veio(uvd, 0, 0x0003, 0x0106);
-		ibmcam_veio(uvd, 0, 0x00d0, 0x0111);
-		ibmcam_veio(uvd, 0, 0x0039, 0x010a);
-		ibmcam_veio(uvd, 0, 0x0001, 0x0102);
-		ibmcam_veio(uvd, 0, 0x0028, 0x0103);
-		ibmcam_veio(uvd, 0, 0x0000, 0x0104);
-		ibmcam_veio(uvd, 0, 0x001e, 0x0105);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0016, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
-		ibmcam_veio(uvd, 0, 0x000a, 0x0127);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x0130);
-		ibmcam_veio(uvd, 0, 0x82a8, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0014, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0008, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd145, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012e);
-		ibmcam_veio(uvd, 0, 0x001a, 0x0130);
-		ibmcam_veio(uvd, 0, 0x8a0a, 0x0124);
-		ibmcam_veio(uvd, 0, 0x005a, 0x012d);
-		ibmcam_veio(uvd, 0, 0x9545, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x0127);
-		ibmcam_veio(uvd, 0, 0x0018, 0x012e);
-		ibmcam_veio(uvd, 0, 0x0043, 0x0130);
-		ibmcam_veio(uvd, 0, 0x8a28, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd055, 0x0124);
-		ibmcam_veio(uvd, 0, 0x001c, 0x0127);
-		ibmcam_veio(uvd, 0, 0x00eb, 0x012e);
-		ibmcam_veio(uvd, 0, 0xaa28, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0032, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0000, 0x0127);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x0130);
-		ibmcam_veio(uvd, 0, 0x82a8, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0036, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0008, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd145, 0x0124);
-		ibmcam_veio(uvd, 0, 0xfffa, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
-		ibmcam_veio(uvd, 0, 0x001e, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0017, 0x0127);
-		ibmcam_veio(uvd, 0, 0x0013, 0x012e);
-		ibmcam_veio(uvd, 0, 0x0031, 0x0130);
-		ibmcam_veio(uvd, 0, 0x8a28, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0017, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0078, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd145, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0000, 0x0127);
-		ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0038, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0004, 0x0127);
-		ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00c0, 0x010c);
-		break;
-	case VIDEOSIZE_352x288:
-		ibmcam_veio(uvd, 0, 0x0000, 0x0100);
-		ibmcam_veio(uvd, 0, 0x00c0, 0x0111);
-		ibmcam_veio(uvd, 0, 0x00bc, 0x012c);
-		ibmcam_veio(uvd, 0, 0x0080, 0x012b);
-		ibmcam_veio(uvd, 0, 0x0000, 0x0108);
-		ibmcam_veio(uvd, 0, 0x0001, 0x0133);
-		ibmcam_veio(uvd, 0, 0x009b, 0x010f);
-		ibmcam_veio(uvd, 0, 0x00bb, 0x010f);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0038, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0000, 0x0127);
-		ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
-		ibmcam_veio(uvd, 0, 0x000a, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
-		ibmcam_veio(uvd, 0, 0x005c, 0x0127);
-		ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0004, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0000, 0x0127);
-		ibmcam_veio(uvd, 0, 0x00fb, 0x012e);
-		ibmcam_veio(uvd, 0, 0x0000, 0x0130);
-		ibmcam_veio(uvd, 0, 0x8a28, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd055, 0x0124);
-		ibmcam_veio(uvd, 0, 0x000c, 0x0127);
-		ibmcam_veio(uvd, 0, 0x0009, 0x012e);
-		ibmcam_veio(uvd, 0, 0xaa28, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0012, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0008, 0x0127);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x0130);
-		ibmcam_veio(uvd, 0, 0x82a8, 0x0124);
-		ibmcam_veio(uvd, 0, 0x002a, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0000, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd145, 0x0124);
-		ibmcam_veio(uvd, 0, 0xfffa, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0034, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0000, 0x0127);
-		ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0070, 0x0119);
-		ibmcam_veio(uvd, 0, 0x00f2, 0x0107);
-		ibmcam_veio(uvd, 0, 0x0003, 0x0106);
-		ibmcam_veio(uvd, 0, 0x008c, 0x0107);
-		ibmcam_veio(uvd, 0, 0x0003, 0x0106);
-		ibmcam_veio(uvd, 0, 0x00c0, 0x0111);
-		ibmcam_veio(uvd, 0, 0x0039, 0x010a);
-		ibmcam_veio(uvd, 0, 0x0001, 0x0102);
-		ibmcam_veio(uvd, 0, 0x002c, 0x0103);
-		ibmcam_veio(uvd, 0, 0x0000, 0x0104);
-		ibmcam_veio(uvd, 0, 0x0024, 0x0105);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0016, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0006, 0x0127);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x0130);
-		ibmcam_veio(uvd, 0, 0x82a8, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0014, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0002, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd145, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012e);
-		ibmcam_veio(uvd, 0, 0x001a, 0x0130);
-		ibmcam_veio(uvd, 0, 0x8a0a, 0x0124);
-		ibmcam_veio(uvd, 0, 0x005e, 0x012d);
-		ibmcam_veio(uvd, 0, 0x9545, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x0127);
-		ibmcam_veio(uvd, 0, 0x0018, 0x012e);
-		ibmcam_veio(uvd, 0, 0x0049, 0x0130);
-		ibmcam_veio(uvd, 0, 0x8a28, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd055, 0x0124);
-		ibmcam_veio(uvd, 0, 0x001c, 0x0127);
-		ibmcam_veio(uvd, 0, 0x00cf, 0x012e);
-		ibmcam_veio(uvd, 0, 0xaa28, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0032, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0000, 0x0127);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x0130);
-		ibmcam_veio(uvd, 0, 0x82a8, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0036, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0008, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd145, 0x0124);
-		ibmcam_veio(uvd, 0, 0xfffa, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
-		ibmcam_veio(uvd, 0, 0x001e, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0010, 0x0127);
-		ibmcam_veio(uvd, 0, 0x0013, 0x012e);
-		ibmcam_veio(uvd, 0, 0x0025, 0x0130);
-		ibmcam_veio(uvd, 0, 0x8a28, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0010, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0048, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd145, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0000, 0x0127);
-		ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0038, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0004, 0x0127);
-		ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00c0, 0x010c);
-		break;
-	}
-	usb_clear_halt(uvd->dev, usb_rcvisocpipe(uvd->dev, uvd->video_endp));
-}
-
-static void ibmcam_model3_setup_after_video_if(struct uvd *uvd)
-{
-	int i;
-	/*
-	 * 01.01.08 - Added for RCA video in support -LO
-	 * This struct is used to init the Model3 cam to use the RCA video in port
-	 * instead of the CCD sensor.
-	 */
-	static const struct struct_initData initData[] = {
-		{0, 0x0000, 0x010c},
-		{0, 0x0006, 0x012c},
-		{0, 0x0078, 0x012d},
-		{0, 0x0046, 0x012f},
-		{0, 0xd141, 0x0124},
-		{0, 0x0000, 0x0127},
-		{0, 0xfea8, 0x0124},
-		{1, 0x0000, 0x0116},
-		{0, 0x0064, 0x0116},
-		{1, 0x0000, 0x0115},
-		{0, 0x0003, 0x0115},
-		{0, 0x0008, 0x0123},
-		{0, 0x0000, 0x0117},
-		{0, 0x0000, 0x0112},
-		{0, 0x0080, 0x0100},
-		{0, 0x0000, 0x0100},
-		{1, 0x0000, 0x0116},
-		{0, 0x0060, 0x0116},
-		{0, 0x0002, 0x0112},
-		{0, 0x0000, 0x0123},
-		{0, 0x0001, 0x0117},
-		{0, 0x0040, 0x0108},
-		{0, 0x0019, 0x012c},
-		{0, 0x0040, 0x0116},
-		{0, 0x000a, 0x0115},
-		{0, 0x000b, 0x0115},
-		{0, 0x0078, 0x012d},
-		{0, 0x0046, 0x012f},
-		{0, 0xd141, 0x0124},
-		{0, 0x0000, 0x0127},
-		{0, 0xfea8, 0x0124},
-		{0, 0x0064, 0x0116},
-		{0, 0x0000, 0x0115},
-		{0, 0x0001, 0x0115},
-		{0, 0xffff, 0x0124},
-		{0, 0xfff9, 0x0124},
-		{0, 0x0086, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x00aa, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0000, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0xfffa, 0x0124},
-		{0, 0xffff, 0x0124},
-		{0, 0xfff9, 0x0124},
-		{0, 0x0086, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x00f2, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x000f, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0xfffa, 0x0124},
-		{0, 0xffff, 0x0124},
-		{0, 0xfff9, 0x0124},
-		{0, 0x0086, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x00f8, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x00fc, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0xfffa, 0x0124},
-		{0, 0xffff, 0x0124},
-		{0, 0xfff9, 0x0124},
-		{0, 0x0086, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x00f9, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x003c, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0xfffa, 0x0124},
-		{0, 0xffff, 0x0124},
-		{0, 0xfff9, 0x0124},
-		{0, 0x0086, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0027, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0019, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0xfffa, 0x0124},
-		{0, 0xfff9, 0x0124},
-		{0, 0x0086, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0037, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0000, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0021, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0xfffa, 0x0124},
-		{0, 0xfff9, 0x0124},
-		{0, 0x0086, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0038, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0006, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0045, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0xfffa, 0x0124},
-		{0, 0xfff9, 0x0124},
-		{0, 0x0086, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0037, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0001, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x002a, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0xfffa, 0x0124},
-		{0, 0xfff9, 0x0124},
-		{0, 0x0086, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0038, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0000, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x000e, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0xfffa, 0x0124},
-		{0, 0xfff9, 0x0124},
-		{0, 0x0086, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0037, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0001, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x002b, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0xfffa, 0x0124},
-		{0, 0xfff9, 0x0124},
-		{0, 0x0086, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0038, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0001, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x00f4, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0xfffa, 0x0124},
-		{0, 0xfff9, 0x0124},
-		{0, 0x0086, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0037, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0001, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x002c, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0xfffa, 0x0124},
-		{0, 0xfff9, 0x0124},
-		{0, 0x0086, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0038, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0001, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0004, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0xfffa, 0x0124},
-		{0, 0xfff9, 0x0124},
-		{0, 0x0086, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0037, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0001, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x002d, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0xfffa, 0x0124},
-		{0, 0xfff9, 0x0124},
-		{0, 0x0086, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0038, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0000, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0014, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0xfffa, 0x0124},
-		{0, 0xfff9, 0x0124},
-		{0, 0x0086, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0037, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0001, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x002e, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0xfffa, 0x0124},
-		{0, 0xfff9, 0x0124},
-		{0, 0x0086, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0038, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0003, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0000, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0xfffa, 0x0124},
-		{0, 0xfff9, 0x0124},
-		{0, 0x0086, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0037, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0001, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x002f, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0xfffa, 0x0124},
-		{0, 0xfff9, 0x0124},
-		{0, 0x0086, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0038, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0003, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0014, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0xfffa, 0x0124},
-		{0, 0xfff9, 0x0124},
-		{0, 0x0086, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0037, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0001, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0040, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0xfffa, 0x0124},
-		{0, 0xfff9, 0x0124},
-		{0, 0x0086, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0038, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0000, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0040, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0xfffa, 0x0124},
-		{0, 0xfff9, 0x0124},
-		{0, 0x0086, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0037, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0001, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0053, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0xfffa, 0x0124},
-		{0, 0xfff9, 0x0124},
-		{0, 0x0086, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0038, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0000, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0038, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0xfffa, 0x0124},
-		{0, 0x0000, 0x0101},
-		{0, 0x00a0, 0x0103},
-		{0, 0x0078, 0x0105},
-		{0, 0x0000, 0x010a},
-		{0, 0x0024, 0x010b},
-		{0, 0x0028, 0x0119},
-		{0, 0x0088, 0x011b},
-		{0, 0x0002, 0x011d},
-		{0, 0x0003, 0x011e},
-		{0, 0x0000, 0x0129},
-		{0, 0x00fc, 0x012b},
-		{0, 0x0008, 0x0102},
-		{0, 0x0000, 0x0104},
-		{0, 0x0008, 0x011a},
-		{0, 0x0028, 0x011c},
-		{0, 0x0021, 0x012a},
-		{0, 0x0000, 0x0118},
-		{0, 0x0000, 0x0132},
-		{0, 0x0000, 0x0109},
-		{0, 0xfff9, 0x0124},
-		{0, 0x0086, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0037, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0001, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0031, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0xfffa, 0x0124},
-		{0, 0xfff9, 0x0124},
-		{0, 0x0086, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0038, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0000, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0000, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0xfffa, 0x0124},
-		{0, 0xfff9, 0x0124},
-		{0, 0x0086, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0037, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0001, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0040, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0xfffa, 0x0124},
-		{0, 0xfff9, 0x0124},
-		{0, 0x0086, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0038, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0000, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0040, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0xfffa, 0x0124},
-		{0, 0xfff9, 0x0124},
-		{0, 0x0086, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0037, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0000, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x00dc, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0xfffa, 0x0124},
-		{0, 0xfff9, 0x0124},
-		{0, 0x0086, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0038, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0000, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0000, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0xfffa, 0x0124},
-		{0, 0xfff9, 0x0124},
-		{0, 0x0086, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0037, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0001, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0032, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0xfffa, 0x0124},
-		{0, 0xfff9, 0x0124},
-		{0, 0x0086, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0038, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0001, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0020, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0xfffa, 0x0124},
-		{0, 0xfff9, 0x0124},
-		{0, 0x0086, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0037, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0001, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0040, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0xfffa, 0x0124},
-		{0, 0xfff9, 0x0124},
-		{0, 0x0086, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0038, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0000, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0040, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0xfffa, 0x0124},
-		{0, 0xfff9, 0x0124},
-		{0, 0x0086, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0037, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0000, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0030, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0xfffa, 0x0124},
-		{0, 0xfff9, 0x0124},
-		{0, 0x0086, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0038, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0008, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0000, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0xfffa, 0x0124},
-		{0, 0x0003, 0x0106},
-		{0, 0x0062, 0x0107},
-		{0, 0x0003, 0x0111},
-	};
-#define NUM_INIT_DATA
-
-	unsigned short compression = 0;	/* 0=none, 7=best frame rate  */
-	int f_rate; /* 0=Fastest 7=slowest */
-
-	if (IBMCAM_T(uvd)->initialized)
-		return;
-
-	/* Internal frame rate is controlled by f_rate value */
-	f_rate = 7 - framerate;
-	RESTRICT_TO_RANGE(f_rate, 0, 7);
-
-	ibmcam_veio(uvd, 0, 0x0000, 0x0100);
-	ibmcam_veio(uvd, 1, 0x0000, 0x0116);
-	ibmcam_veio(uvd, 0, 0x0060, 0x0116);
-	ibmcam_veio(uvd, 0, 0x0002, 0x0112);
-	ibmcam_veio(uvd, 0, 0x0000, 0x0123);
-	ibmcam_veio(uvd, 0, 0x0001, 0x0117);
-	ibmcam_veio(uvd, 0, 0x0040, 0x0108);
-	ibmcam_veio(uvd, 0, 0x0019, 0x012c);
-	ibmcam_veio(uvd, 0, 0x0060, 0x0116);
-	ibmcam_veio(uvd, 0, 0x0002, 0x0115);
-	ibmcam_veio(uvd, 0, 0x0003, 0x0115);
-	ibmcam_veio(uvd, 1, 0x0000, 0x0115);
-	ibmcam_veio(uvd, 0, 0x000b, 0x0115);
-	ibmcam_model3_Packet1(uvd, 0x000a, 0x0040);
-	ibmcam_model3_Packet1(uvd, 0x000b, 0x00f6);
-	ibmcam_model3_Packet1(uvd, 0x000c, 0x0002);
-	ibmcam_model3_Packet1(uvd, 0x000d, 0x0020);
-	ibmcam_model3_Packet1(uvd, 0x000e, 0x0033);
-	ibmcam_model3_Packet1(uvd, 0x000f, 0x0007);
-	ibmcam_model3_Packet1(uvd, 0x0010, 0x0000);
-	ibmcam_model3_Packet1(uvd, 0x0011, 0x0070);
-	ibmcam_model3_Packet1(uvd, 0x0012, 0x0030);
-	ibmcam_model3_Packet1(uvd, 0x0013, 0x0000);
-	ibmcam_model3_Packet1(uvd, 0x0014, 0x0001);
-	ibmcam_model3_Packet1(uvd, 0x0015, 0x0001);
-	ibmcam_model3_Packet1(uvd, 0x0016, 0x0001);
-	ibmcam_model3_Packet1(uvd, 0x0017, 0x0001);
-	ibmcam_model3_Packet1(uvd, 0x0018, 0x0000);
-	ibmcam_model3_Packet1(uvd, 0x001e, 0x00c3);
-	ibmcam_model3_Packet1(uvd, 0x0020, 0x0000);
-	ibmcam_model3_Packet1(uvd, 0x0028, 0x0010);
-	ibmcam_model3_Packet1(uvd, 0x0029, 0x0054);
-	ibmcam_model3_Packet1(uvd, 0x002a, 0x0013);
-	ibmcam_model3_Packet1(uvd, 0x002b, 0x0007);
-	ibmcam_model3_Packet1(uvd, 0x002d, 0x0028);
-	ibmcam_model3_Packet1(uvd, 0x002e, 0x0000);
-	ibmcam_model3_Packet1(uvd, 0x0031, 0x0000);
-	ibmcam_model3_Packet1(uvd, 0x0032, 0x0000);
-	ibmcam_model3_Packet1(uvd, 0x0033, 0x0000);
-	ibmcam_model3_Packet1(uvd, 0x0034, 0x0000);
-	ibmcam_model3_Packet1(uvd, 0x0035, 0x0038);
-	ibmcam_model3_Packet1(uvd, 0x003a, 0x0001);
-	ibmcam_model3_Packet1(uvd, 0x003c, 0x001e);
-	ibmcam_model3_Packet1(uvd, 0x003f, 0x000a);
-	ibmcam_model3_Packet1(uvd, 0x0041, 0x0000);
-	ibmcam_model3_Packet1(uvd, 0x0046, 0x003f);
-	ibmcam_model3_Packet1(uvd, 0x0047, 0x0000);
-	ibmcam_model3_Packet1(uvd, 0x0050, 0x0005);
-	ibmcam_model3_Packet1(uvd, 0x0052, 0x001a);
-	ibmcam_model3_Packet1(uvd, 0x0053, 0x0003);
-	ibmcam_model3_Packet1(uvd, 0x005a, 0x006b);
-	ibmcam_model3_Packet1(uvd, 0x005d, 0x001e);
-	ibmcam_model3_Packet1(uvd, 0x005e, 0x0030);
-	ibmcam_model3_Packet1(uvd, 0x005f, 0x0041);
-	ibmcam_model3_Packet1(uvd, 0x0064, 0x0008);
-	ibmcam_model3_Packet1(uvd, 0x0065, 0x0015);
-	ibmcam_model3_Packet1(uvd, 0x0068, 0x000f);
-	ibmcam_model3_Packet1(uvd, 0x0079, 0x0000);
-	ibmcam_model3_Packet1(uvd, 0x007a, 0x0000);
-	ibmcam_model3_Packet1(uvd, 0x007c, 0x003f);
-	ibmcam_model3_Packet1(uvd, 0x0082, 0x000f);
-	ibmcam_model3_Packet1(uvd, 0x0085, 0x0000);
-	ibmcam_model3_Packet1(uvd, 0x0099, 0x0000);
-	ibmcam_model3_Packet1(uvd, 0x009b, 0x0023);
-	ibmcam_model3_Packet1(uvd, 0x009c, 0x0022);
-	ibmcam_model3_Packet1(uvd, 0x009d, 0x0096);
-	ibmcam_model3_Packet1(uvd, 0x009e, 0x0096);
-	ibmcam_model3_Packet1(uvd, 0x009f, 0x000a);
-
-	switch (uvd->videosize) {
-	case VIDEOSIZE_160x120:
-		ibmcam_veio(uvd, 0, 0x0000, 0x0101); /* Same on 176x144, 320x240 */
-		ibmcam_veio(uvd, 0, 0x00a0, 0x0103); /* Same on 176x144, 320x240 */
-		ibmcam_veio(uvd, 0, 0x0078, 0x0105); /* Same on 176x144, 320x240 */
-		ibmcam_veio(uvd, 0, 0x0000, 0x010a); /* Same */
-		ibmcam_veio(uvd, 0, 0x0024, 0x010b); /* Differs everywhere */
-		ibmcam_veio(uvd, 0, 0x00a9, 0x0119);
-		ibmcam_veio(uvd, 0, 0x0016, 0x011b);
-		ibmcam_veio(uvd, 0, 0x0002, 0x011d); /* Same on 176x144, 320x240 */
-		ibmcam_veio(uvd, 0, 0x0003, 0x011e); /* Same on 176x144, 640x480 */
-		ibmcam_veio(uvd, 0, 0x0000, 0x0129); /* Same */
-		ibmcam_veio(uvd, 0, 0x00fc, 0x012b); /* Same */
-		ibmcam_veio(uvd, 0, 0x0018, 0x0102);
-		ibmcam_veio(uvd, 0, 0x0004, 0x0104);
-		ibmcam_veio(uvd, 0, 0x0004, 0x011a);
-		ibmcam_veio(uvd, 0, 0x0028, 0x011c);
-		ibmcam_veio(uvd, 0, 0x0022, 0x012a); /* Same */
-		ibmcam_veio(uvd, 0, 0x0000, 0x0118);
-		ibmcam_veio(uvd, 0, 0x0000, 0x0132);
-		ibmcam_model3_Packet1(uvd, 0x0021, 0x0001); /* Same */
-		ibmcam_veio(uvd, 0, compression, 0x0109);
-		break;
-	case VIDEOSIZE_320x240:
-		ibmcam_veio(uvd, 0, 0x0000, 0x0101); /* Same on 176x144, 320x240 */
-		ibmcam_veio(uvd, 0, 0x00a0, 0x0103); /* Same on 176x144, 320x240 */
-		ibmcam_veio(uvd, 0, 0x0078, 0x0105); /* Same on 176x144, 320x240 */
-		ibmcam_veio(uvd, 0, 0x0000, 0x010a); /* Same */
-		ibmcam_veio(uvd, 0, 0x0028, 0x010b); /* Differs everywhere */
-		ibmcam_veio(uvd, 0, 0x0002, 0x011d); /* Same */
-		ibmcam_veio(uvd, 0, 0x0000, 0x011e);
-		ibmcam_veio(uvd, 0, 0x0000, 0x0129); /* Same */
-		ibmcam_veio(uvd, 0, 0x00fc, 0x012b); /* Same */
-		/* 4 commands from 160x120 skipped */
-		ibmcam_veio(uvd, 0, 0x0022, 0x012a); /* Same */
-		ibmcam_model3_Packet1(uvd, 0x0021, 0x0001); /* Same */
-		ibmcam_veio(uvd, 0, compression, 0x0109);
-		ibmcam_veio(uvd, 0, 0x00d9, 0x0119);
-		ibmcam_veio(uvd, 0, 0x0006, 0x011b);
-		ibmcam_veio(uvd, 0, 0x0021, 0x0102); /* Same on 320x240, 640x480 */
-		ibmcam_veio(uvd, 0, 0x0010, 0x0104);
-		ibmcam_veio(uvd, 0, 0x0004, 0x011a);
-		ibmcam_veio(uvd, 0, 0x003f, 0x011c);
-		ibmcam_veio(uvd, 0, 0x001c, 0x0118);
-		ibmcam_veio(uvd, 0, 0x0000, 0x0132);
-		break;
-	case VIDEOSIZE_640x480:
-		ibmcam_veio(uvd, 0, 0x00f0, 0x0105);
-		ibmcam_veio(uvd, 0, 0x0000, 0x010a); /* Same */
-		ibmcam_veio(uvd, 0, 0x0038, 0x010b); /* Differs everywhere */
-		ibmcam_veio(uvd, 0, 0x00d9, 0x0119); /* Same on 320x240, 640x480 */
-		ibmcam_veio(uvd, 0, 0x0006, 0x011b); /* Same on 320x240, 640x480 */
-		ibmcam_veio(uvd, 0, 0x0004, 0x011d); /* NC */
-		ibmcam_veio(uvd, 0, 0x0003, 0x011e); /* Same on 176x144, 640x480 */
-		ibmcam_veio(uvd, 0, 0x0000, 0x0129); /* Same */
-		ibmcam_veio(uvd, 0, 0x00fc, 0x012b); /* Same */
-		ibmcam_veio(uvd, 0, 0x0021, 0x0102); /* Same on 320x240, 640x480 */
-		ibmcam_veio(uvd, 0, 0x0016, 0x0104); /* NC */
-		ibmcam_veio(uvd, 0, 0x0004, 0x011a); /* Same on 320x240, 640x480 */
-		ibmcam_veio(uvd, 0, 0x003f, 0x011c); /* Same on 320x240, 640x480 */
-		ibmcam_veio(uvd, 0, 0x0022, 0x012a); /* Same */
-		ibmcam_veio(uvd, 0, 0x001c, 0x0118); /* Same on 320x240, 640x480 */
-		ibmcam_model3_Packet1(uvd, 0x0021, 0x0001); /* Same */
-		ibmcam_veio(uvd, 0, compression, 0x0109);
-		ibmcam_veio(uvd, 0, 0x0040, 0x0101);
-		ibmcam_veio(uvd, 0, 0x0040, 0x0103);
-		ibmcam_veio(uvd, 0, 0x0000, 0x0132); /* Same on 320x240, 640x480 */
-		break;
-	}
-	ibmcam_model3_Packet1(uvd, 0x007e, 0x000e);	/* Hue */
-	ibmcam_model3_Packet1(uvd, 0x0036, 0x0011);	/* Brightness */
-	ibmcam_model3_Packet1(uvd, 0x0060, 0x0002);	/* Sharpness */
-	ibmcam_model3_Packet1(uvd, 0x0061, 0x0004);	/* Sharpness */
-	ibmcam_model3_Packet1(uvd, 0x0062, 0x0005);	/* Sharpness */
-	ibmcam_model3_Packet1(uvd, 0x0063, 0x0014);	/* Sharpness */
-	ibmcam_model3_Packet1(uvd, 0x0096, 0x00a0);	/* Red gain */
-	ibmcam_model3_Packet1(uvd, 0x0097, 0x0096);	/* Blue gain */
-	ibmcam_model3_Packet1(uvd, 0x0067, 0x0001);	/* Contrast */
-	ibmcam_model3_Packet1(uvd, 0x005b, 0x000c);	/* Contrast */
-	ibmcam_model3_Packet1(uvd, 0x005c, 0x0016);	/* Contrast */
-	ibmcam_model3_Packet1(uvd, 0x0098, 0x000b);
-	ibmcam_model3_Packet1(uvd, 0x002c, 0x0003);	/* Was 1, broke 640x480 */
-	ibmcam_model3_Packet1(uvd, 0x002f, 0x002a);
-	ibmcam_model3_Packet1(uvd, 0x0030, 0x0029);
-	ibmcam_model3_Packet1(uvd, 0x0037, 0x0002);
-	ibmcam_model3_Packet1(uvd, 0x0038, 0x0059);
-	ibmcam_model3_Packet1(uvd, 0x003d, 0x002e);
-	ibmcam_model3_Packet1(uvd, 0x003e, 0x0028);
-	ibmcam_model3_Packet1(uvd, 0x0078, 0x0005);
-	ibmcam_model3_Packet1(uvd, 0x007b, 0x0011);
-	ibmcam_model3_Packet1(uvd, 0x007d, 0x004b);
-	ibmcam_model3_Packet1(uvd, 0x007f, 0x0022);
-	ibmcam_model3_Packet1(uvd, 0x0080, 0x000c);
-	ibmcam_model3_Packet1(uvd, 0x0081, 0x000b);
-	ibmcam_model3_Packet1(uvd, 0x0083, 0x00fd);
-	ibmcam_model3_Packet1(uvd, 0x0086, 0x000b);
-	ibmcam_model3_Packet1(uvd, 0x0087, 0x000b);
-	ibmcam_model3_Packet1(uvd, 0x007e, 0x000e);
-	ibmcam_model3_Packet1(uvd, 0x0096, 0x00a0);	/* Red gain */
-	ibmcam_model3_Packet1(uvd, 0x0097, 0x0096);	/* Blue gain */
-	ibmcam_model3_Packet1(uvd, 0x0098, 0x000b);
-
-	switch (uvd->videosize) {
-	case VIDEOSIZE_160x120:
-		ibmcam_veio(uvd, 0, 0x0002, 0x0106);
-		ibmcam_veio(uvd, 0, 0x0008, 0x0107);
-		ibmcam_veio(uvd, 0, f_rate, 0x0111);	/* Frame rate */
-		ibmcam_model3_Packet1(uvd, 0x001f, 0x0000); /* Same */
-		ibmcam_model3_Packet1(uvd, 0x0039, 0x001f); /* Same */
-		ibmcam_model3_Packet1(uvd, 0x003b, 0x003c); /* Same */
-		ibmcam_model3_Packet1(uvd, 0x0040, 0x000a);
-		ibmcam_model3_Packet1(uvd, 0x0051, 0x000a);
-		break;
-	case VIDEOSIZE_320x240:
-		ibmcam_veio(uvd, 0, 0x0003, 0x0106);
-		ibmcam_veio(uvd, 0, 0x0062, 0x0107);
-		ibmcam_veio(uvd, 0, f_rate, 0x0111);	/* Frame rate */
-		ibmcam_model3_Packet1(uvd, 0x001f, 0x0000); /* Same */
-		ibmcam_model3_Packet1(uvd, 0x0039, 0x001f); /* Same */
-		ibmcam_model3_Packet1(uvd, 0x003b, 0x003c); /* Same */
-		ibmcam_model3_Packet1(uvd, 0x0040, 0x0008);
-		ibmcam_model3_Packet1(uvd, 0x0051, 0x000b);
-		break;
-	case VIDEOSIZE_640x480:
-		ibmcam_veio(uvd, 0, 0x0002, 0x0106);	/* Adjustments */
-		ibmcam_veio(uvd, 0, 0x00b4, 0x0107);	/* Adjustments */
-		ibmcam_veio(uvd, 0, f_rate, 0x0111);	/* Frame rate */
-		ibmcam_model3_Packet1(uvd, 0x001f, 0x0002); /* !Same */
-		ibmcam_model3_Packet1(uvd, 0x0039, 0x003e); /* !Same */
-		ibmcam_model3_Packet1(uvd, 0x0040, 0x0008);
-		ibmcam_model3_Packet1(uvd, 0x0051, 0x000a);
-		break;
-	}
-
-	/* 01.01.08 - Added for RCA video in support -LO */
-	if(init_model3_input) {
-		if (debug > 0)
-			dev_info(&uvd->dev->dev, "Setting input to RCA.\n");
-		for (i=0; i < ARRAY_SIZE(initData); i++) {
-			ibmcam_veio(uvd, initData[i].req, initData[i].value, initData[i].index);
-		}
-	}
-
-	ibmcam_veio(uvd, 0, 0x0001, 0x0114);
-	ibmcam_veio(uvd, 0, 0x00c0, 0x010c);
-	usb_clear_halt(uvd->dev, usb_rcvisocpipe(uvd->dev, uvd->video_endp));
-}
-
-/*
- * ibmcam_video_stop()
- *
- * This code tells camera to stop streaming. The interface remains
- * configured and bandwidth - claimed.
- */
-static void ibmcam_video_stop(struct uvd *uvd)
-{
-	switch (IBMCAM_T(uvd)->camera_model) {
-	case IBMCAM_MODEL_1:
-		ibmcam_veio(uvd, 0, 0x00, 0x010c);
-		ibmcam_veio(uvd, 0, 0x00, 0x010c);
-		ibmcam_veio(uvd, 0, 0x01, 0x0114);
-		ibmcam_veio(uvd, 0, 0xc0, 0x010c);
-		ibmcam_veio(uvd, 0, 0x00, 0x010c);
-		ibmcam_send_FF_04_02(uvd);
-		ibmcam_veio(uvd, 1, 0x00, 0x0100);
-		ibmcam_veio(uvd, 0, 0x81, 0x0100);	/* LED Off */
-		break;
-	case IBMCAM_MODEL_2:
-case IBMCAM_MODEL_4:
-		ibmcam_veio(uvd, 0, 0x0000, 0x010c);	/* Stop the camera */
-
-		ibmcam_model2_Packet1(uvd, 0x0030, 0x0004);
-
-		ibmcam_veio(uvd, 0, 0x0080, 0x0100);	/* LED Off */
-		ibmcam_veio(uvd, 0, 0x0020, 0x0111);
-		ibmcam_veio(uvd, 0, 0x00a0, 0x0111);
-
-		ibmcam_model2_Packet1(uvd, 0x0030, 0x0002);
-
-		ibmcam_veio(uvd, 0, 0x0020, 0x0111);
-		ibmcam_veio(uvd, 0, 0x0000, 0x0112);
-		break;
-	case IBMCAM_MODEL_3:
-#if 1
-		ibmcam_veio(uvd, 0, 0x0000, 0x010c);
-
-		/* Here we are supposed to select video interface alt. setting 0 */
-		ibmcam_veio(uvd, 0, 0x0006, 0x012c);
-
-		ibmcam_model3_Packet1(uvd, 0x0046, 0x0000);
-
-		ibmcam_veio(uvd, 1, 0x0000, 0x0116);
-		ibmcam_veio(uvd, 0, 0x0064, 0x0116);
-		ibmcam_veio(uvd, 1, 0x0000, 0x0115);
-		ibmcam_veio(uvd, 0, 0x0003, 0x0115);
-		ibmcam_veio(uvd, 0, 0x0008, 0x0123);
-		ibmcam_veio(uvd, 0, 0x0000, 0x0117);
-		ibmcam_veio(uvd, 0, 0x0000, 0x0112);
-		ibmcam_veio(uvd, 0, 0x0080, 0x0100);
-		IBMCAM_T(uvd)->initialized = 0;
-#endif
-		break;
-	} /* switch */
-}
-
-/*
- * ibmcam_reinit_iso()
- *
- * This procedure sends couple of commands to the camera and then
- * resets the video pipe. This sequence was observed to reinit the
- * camera or, at least, to initiate ISO data stream.
- *
- * History:
- * 1/2/00   Created.
- */
-static void ibmcam_reinit_iso(struct uvd *uvd, int do_stop)
-{
-	switch (IBMCAM_T(uvd)->camera_model) {
-	case IBMCAM_MODEL_1:
-		if (do_stop)
-			ibmcam_video_stop(uvd);
-		ibmcam_veio(uvd, 0, 0x0001, 0x0114);
-		ibmcam_veio(uvd, 0, 0x00c0, 0x010c);
-		usb_clear_halt(uvd->dev, usb_rcvisocpipe(uvd->dev, uvd->video_endp));
-		ibmcam_model1_setup_after_video_if(uvd);
-		break;
-	case IBMCAM_MODEL_2:
-		ibmcam_model2_setup_after_video_if(uvd);
-		break;
-	case IBMCAM_MODEL_3:
-		ibmcam_video_stop(uvd);
-		ibmcam_model3_setup_after_video_if(uvd);
-		break;
-	case IBMCAM_MODEL_4:
-		ibmcam_model4_setup_after_video_if(uvd);
-		break;
-	}
-}
-
-static void ibmcam_video_start(struct uvd *uvd)
-{
-	ibmcam_change_lighting_conditions(uvd);
-	ibmcam_set_sharpness(uvd);
-	ibmcam_reinit_iso(uvd, 0);
-}
-
-/*
- * Return negative code on failure, 0 on success.
- */
-static int ibmcam_setup_on_open(struct uvd *uvd)
-{
-	int setup_ok = 0; /* Success by default */
-	/* Send init sequence only once, it's large! */
-	if (!IBMCAM_T(uvd)->initialized) { /* FIXME rename */
-		switch (IBMCAM_T(uvd)->camera_model) {
-		case IBMCAM_MODEL_1:
-			setup_ok = ibmcam_model1_setup(uvd);
-			break;
-		case IBMCAM_MODEL_2:
-			setup_ok = ibmcam_model2_setup(uvd);
-			break;
-		case IBMCAM_MODEL_3:
-		case IBMCAM_MODEL_4:
-			/* We do all setup when Isoc stream is requested */
-			break;
-		}
-		IBMCAM_T(uvd)->initialized = (setup_ok != 0);
-	}
-	return setup_ok;
-}
-
-static void ibmcam_configure_video(struct uvd *uvd)
-{
-	if (uvd == NULL)
-		return;
-
-	RESTRICT_TO_RANGE(init_brightness, 0, 255);
-	RESTRICT_TO_RANGE(init_contrast, 0, 255);
-	RESTRICT_TO_RANGE(init_color, 0, 255);
-	RESTRICT_TO_RANGE(init_hue, 0, 255);
-	RESTRICT_TO_RANGE(hue_correction, 0, 255);
-
-	memset(&uvd->vpic, 0, sizeof(uvd->vpic));
-	memset(&uvd->vpic_old, 0x55, sizeof(uvd->vpic_old));
-
-	uvd->vpic.colour = init_color << 8;
-	uvd->vpic.hue = init_hue << 8;
-	uvd->vpic.brightness = init_brightness << 8;
-	uvd->vpic.contrast = init_contrast << 8;
-	uvd->vpic.whiteness = 105 << 8; /* This one isn't used */
-	uvd->vpic.depth = 24;
-	uvd->vpic.palette = VIDEO_PALETTE_RGB24;
-
-	memset(&uvd->vcap, 0, sizeof(uvd->vcap));
-	strcpy(uvd->vcap.name, "IBM USB Camera");
-	uvd->vcap.type = VID_TYPE_CAPTURE;
-	uvd->vcap.channels = 1;
-	uvd->vcap.audios = 0;
-	uvd->vcap.maxwidth = VIDEOSIZE_X(uvd->canvas);
-	uvd->vcap.maxheight = VIDEOSIZE_Y(uvd->canvas);
-	uvd->vcap.minwidth = min_canvasWidth;
-	uvd->vcap.minheight = min_canvasHeight;
-
-	memset(&uvd->vchan, 0, sizeof(uvd->vchan));
-	uvd->vchan.flags = 0;
-	uvd->vchan.tuners = 0;
-	uvd->vchan.channel = 0;
-	uvd->vchan.type = VIDEO_TYPE_CAMERA;
-	strcpy(uvd->vchan.name, "Camera");
-}
-
-/*
- * ibmcam_probe()
- *
- * This procedure queries device descriptor and accepts the interface
- * if it looks like IBM C-it camera.
- *
- * History:
- * 22-Jan-2000 Moved camera init code to ibmcam_open()
- * 27=Jan-2000 Changed to use static structures, added locking.
- * 24-May-2000 Corrected to prevent race condition (MOD_xxx_USE_COUNT).
- * 03-Jul-2000 Fixed endianness bug.
- * 12-Nov-2000 Reworked to comply with new probe() signature.
- * 23-Jan-2001 Added compatibility with 2.2.x kernels.
- */
-static int ibmcam_probe(struct usb_interface *intf, const struct usb_device_id *devid)
-{
-	struct usb_device *dev = interface_to_usbdev(intf);
-	struct uvd *uvd = NULL;
-	int ix, i, nas, model=0, canvasX=0, canvasY=0;
-	int actInterface=-1, inactInterface=-1, maxPS=0;
-	__u8 ifnum = intf->altsetting->desc.bInterfaceNumber;
-	unsigned char video_ep = 0;
-
-	if (debug >= 1)
-		dev_info(&dev->dev, "ibmcam_probe(%p,%u.)\n", intf, ifnum);
-
-	/* We don't handle multi-config cameras */
-	if (dev->descriptor.bNumConfigurations != 1)
-		return -ENODEV;
-
-	/* Check the version/revision */
-	switch (le16_to_cpu(dev->descriptor.bcdDevice)) {
-	case 0x0002:
-		if (ifnum != 2)
-			return -ENODEV;
-		model = IBMCAM_MODEL_1;
-		break;
-	case 0x030A:
-		if (ifnum != 0)
-			return -ENODEV;
-		if ((le16_to_cpu(dev->descriptor.idProduct) == NETCAM_PRODUCT_ID) ||
-		    (le16_to_cpu(dev->descriptor.idProduct) == VEO_800D_PRODUCT_ID))
-			model = IBMCAM_MODEL_4;
-		else
-			model = IBMCAM_MODEL_2;
-		break;
-	case 0x0301:
-		if (ifnum != 0)
-			return -ENODEV;
-		model = IBMCAM_MODEL_3;
-		break;
-	default:
-		err("IBM camera with revision 0x%04x is not supported.",
-			le16_to_cpu(dev->descriptor.bcdDevice));
-		return -ENODEV;
-	}
-
-	/* Print detailed info on what we found so far */
-	do {
-		char *brand = NULL;
-		switch (le16_to_cpu(dev->descriptor.idProduct)) {
-		case NETCAM_PRODUCT_ID:
-			brand = "IBM NetCamera";
-			break;
-		case VEO_800C_PRODUCT_ID:
-			brand = "Veo Stingray [800C]";
-			break;
-		case VEO_800D_PRODUCT_ID:
-			brand = "Veo Stingray [800D]";
-			break;
-		case IBMCAM_PRODUCT_ID:
-		default:
-			brand = "IBM PC Camera"; /* a.k.a. Xirlink C-It */
-			break;
-		}
-		dev_info(&dev->dev,
-			 "%s USB camera found (model %d, rev. 0x%04x)\n",
-			 brand, model, le16_to_cpu(dev->descriptor.bcdDevice));
-	} while (0);
-
-	/* Validate found interface: must have one ISO endpoint */
-	nas = intf->num_altsetting;
-	if (debug > 0)
-		dev_info(&dev->dev, "Number of alternate settings=%d.\n",
-			 nas);
-	if (nas < 2) {
-		err("Too few alternate settings for this camera!");
-		return -ENODEV;
-	}
-	/* Validate all alternate settings */
-	for (ix=0; ix < nas; ix++) {
-		const struct usb_host_interface *interface;
-		const struct usb_endpoint_descriptor *endpoint;
-
-		interface = &intf->altsetting[ix];
-		i = interface->desc.bAlternateSetting;
-		if (interface->desc.bNumEndpoints != 1) {
-			err("Interface %d. has %u. endpoints!",
-			    ifnum, (unsigned)(interface->desc.bNumEndpoints));
-			return -ENODEV;
-		}
-		endpoint = &interface->endpoint[0].desc;
-		if (video_ep == 0)
-			video_ep = endpoint->bEndpointAddress;
-		else if (video_ep != endpoint->bEndpointAddress) {
-			err("Alternate settings have different endpoint addresses!");
-			return -ENODEV;
-		}
-		if (!usb_endpoint_xfer_isoc(endpoint)) {
-			err("Interface %d. has non-ISO endpoint!", ifnum);
-			return -ENODEV;
-		}
-		if (usb_endpoint_dir_out(endpoint)) {
-			err("Interface %d. has ISO OUT endpoint!", ifnum);
-			return -ENODEV;
-		}
-		if (le16_to_cpu(endpoint->wMaxPacketSize) == 0) {
-			if (inactInterface < 0)
-				inactInterface = i;
-			else {
-				err("More than one inactive alt. setting!");
-				return -ENODEV;
-			}
-		} else {
-			if (actInterface < 0) {
-				actInterface = i;
-				maxPS = le16_to_cpu(endpoint->wMaxPacketSize);
-				if (debug > 0)
-					dev_info(&dev->dev,
-						 "Active setting=%d. "
-						 "maxPS=%d.\n", i, maxPS);
-			} else
-				err("More than one active alt. setting! Ignoring #%d.", i);
-		}
-	}
-	if ((maxPS <= 0) || (actInterface < 0) || (inactInterface < 0)) {
-		err("Failed to recognize the camera!");
-		return -ENODEV;
-	}
-
-	/* Validate options */
-	switch (model) {
-	case IBMCAM_MODEL_1:
-		RESTRICT_TO_RANGE(lighting, 0, 2);
-		RESTRICT_TO_RANGE(size, SIZE_128x96, SIZE_352x288);
-		if (framerate < 0)
-			framerate = 2;
-		canvasX = 352;
-		canvasY = 288;
-		break;
-	case IBMCAM_MODEL_2:
-		RESTRICT_TO_RANGE(lighting, 0, 15);
-		RESTRICT_TO_RANGE(size, SIZE_176x144, SIZE_352x240);
-		if (framerate < 0)
-			framerate = 2;
-		canvasX = 352;
-		canvasY = 240;
-		break;
-	case IBMCAM_MODEL_3:
-		RESTRICT_TO_RANGE(lighting, 0, 15); /* FIXME */
-		switch (size) {
-		case SIZE_160x120:
-			canvasX = 160;
-			canvasY = 120;
-			if (framerate < 0)
-				framerate = 2;
-			RESTRICT_TO_RANGE(framerate, 0, 5);
-			break;
-		default:
-			dev_info(&dev->dev, "IBM camera: using 320x240\n");
-			size = SIZE_320x240;
-			/* No break here */
-		case SIZE_320x240:
-			canvasX = 320;
-			canvasY = 240;
-			if (framerate < 0)
-				framerate = 3;
-			RESTRICT_TO_RANGE(framerate, 0, 5);
-			break;
-		case SIZE_640x480:
-			canvasX = 640;
-			canvasY = 480;
-			framerate = 0;	/* Slowest, and maybe even that is too fast */
-			break;
-		}
-		break;
-	case IBMCAM_MODEL_4:
-		RESTRICT_TO_RANGE(lighting, 0, 2);
-		switch (size) {
-		case SIZE_128x96:
-			canvasX = 128;
-			canvasY = 96;
-			break;
-		case SIZE_160x120:
-			canvasX = 160;
-			canvasY = 120;
-			break;
-		default:
-			dev_info(&dev->dev, "IBM NetCamera: using 176x144\n");
-			size = SIZE_176x144;
-			/* No break here */
-		case SIZE_176x144:
-			canvasX = 176;
-			canvasY = 144;
-			break;
-		case SIZE_320x240:
-			canvasX = 320;
-			canvasY = 240;
-			break;
-		case SIZE_352x288:
-			canvasX = 352;
-			canvasY = 288;
-			break;
-		}
-		break;
-	default:
-		err("IBM camera: Model %d. not supported!", model);
-		return -ENODEV;
-	}
-
-	uvd = usbvideo_AllocateDevice(cams);
-	if (uvd != NULL) {
-		/* Here uvd is a fully allocated uvd object */
-		uvd->flags = flags;
-		uvd->debug = debug;
-		uvd->dev = dev;
-		uvd->iface = ifnum;
-		uvd->ifaceAltInactive = inactInterface;
-		uvd->ifaceAltActive = actInterface;
-		uvd->video_endp = video_ep;
-		uvd->iso_packet_len = maxPS;
-		uvd->paletteBits = 1L << VIDEO_PALETTE_RGB24;
-		uvd->defaultPalette = VIDEO_PALETTE_RGB24;
-		uvd->canvas = VIDEOSIZE(canvasX, canvasY);
-		uvd->videosize = ibmcam_size_to_videosize(size);
-
-		/* Initialize ibmcam-specific data */
-		assert(IBMCAM_T(uvd) != NULL);
-		IBMCAM_T(uvd)->camera_model = model;
-		IBMCAM_T(uvd)->initialized = 0;
-
-		ibmcam_configure_video(uvd);
-
-		i = usbvideo_RegisterVideoDevice(uvd);
-		if (i != 0) {
-			err("usbvideo_RegisterVideoDevice() failed.");
-			uvd = NULL;
-		}
-	}
-	usb_set_intfdata (intf, uvd);
-	return 0;
-}
-
-
-static struct usb_device_id id_table[] = {
-	{ USB_DEVICE_VER(IBMCAM_VENDOR_ID, IBMCAM_PRODUCT_ID, 0x0002, 0x0002) },	/* Model 1 */
-	{ USB_DEVICE_VER(IBMCAM_VENDOR_ID, IBMCAM_PRODUCT_ID, 0x030a, 0x030a) },	/* Model 2 */
-	{ USB_DEVICE_VER(IBMCAM_VENDOR_ID, IBMCAM_PRODUCT_ID, 0x0301, 0x0301) },	/* Model 3 */
-	{ USB_DEVICE_VER(IBMCAM_VENDOR_ID, NETCAM_PRODUCT_ID, 0x030a, 0x030a) },	/* Model 4 */
-	{ USB_DEVICE_VER(IBMCAM_VENDOR_ID, VEO_800C_PRODUCT_ID, 0x030a, 0x030a) },	/* Model 2 */
-	{ USB_DEVICE_VER(IBMCAM_VENDOR_ID, VEO_800D_PRODUCT_ID, 0x030a, 0x030a) },	/* Model 4 */
-	{ }  /* Terminating entry */
-};
-
-/*
- * ibmcam_init()
- *
- * This code is run to initialize the driver.
- *
- * History:
- * 1/27/00  Reworked to use statically allocated ibmcam structures.
- * 21/10/00 Completely redesigned to use usbvideo services.
- */
-static int __init ibmcam_init(void)
-{
-	struct usbvideo_cb cbTbl;
-	memset(&cbTbl, 0, sizeof(cbTbl));
-	cbTbl.probe = ibmcam_probe;
-	cbTbl.setupOnOpen = ibmcam_setup_on_open;
-	cbTbl.videoStart = ibmcam_video_start;
-	cbTbl.videoStop = ibmcam_video_stop;
-	cbTbl.processData = ibmcam_ProcessIsocData;
-	cbTbl.postProcess = usbvideo_DeinterlaceFrame;
-	cbTbl.adjustPicture = ibmcam_adjust_picture;
-	cbTbl.getFPS = ibmcam_calculate_fps;
-	return usbvideo_register(
-		&cams,
-		MAX_IBMCAM,
-		sizeof(ibmcam_t),
-		"ibmcam",
-		&cbTbl,
-		THIS_MODULE,
-		id_table);
-}
-
-static void __exit ibmcam_cleanup(void)
-{
-	usbvideo_Deregister(&cams);
-}
-
-MODULE_DEVICE_TABLE(usb, id_table);
-
-module_init(ibmcam_init);
-module_exit(ibmcam_cleanup);
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/usbvideo/Kconfig linux-libre-2.6.38-gnu1/drivers/media/video/usbvideo/Kconfig
--- linux-libre-2.6.37-gnu1/drivers/media/video/usbvideo/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/usbvideo/Kconfig	1969-12-31 19:00:00.000000000 -0500
@@ -1,45 +0,0 @@
-config VIDEO_USBVIDEO
-	tristate
-
-config USB_VICAM
-	tristate "USB 3com HomeConnect (aka vicam) support (EXPERIMENTAL)"
-	depends on VIDEO_V4L1 && EXPERIMENTAL
-	select VIDEO_USBVIDEO
-	---help---
-	  Say Y here if you have 3com homeconnect camera (vicam).
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called vicam.
-
-config USB_IBMCAM
-	tristate "USB IBM (Xirlink) C-it Camera support (DEPRECATED)"
-	depends on VIDEO_V4L1
-	select VIDEO_USBVIDEO
-	---help---
-	  This driver is DEPRECATED please use the gspca xirlink_cit module
-	  instead.
-
-	  Say Y here if you want to connect a IBM "C-It" camera, also known as
-	  "Xirlink PC Camera" to your computer's USB port.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called ibmcam.
-
-	  This camera has several configuration options which
-	  can be specified when you load the module. Read
-	  <file:Documentation/video4linux/ibmcam.txt> to learn more.
-
-config USB_KONICAWC
-	tristate "USB Konica Webcam support (DEPRECATED)"
-	depends on VIDEO_V4L1
-	select VIDEO_USBVIDEO
-	---help---
-	  This driver is DEPRECATED (and known to crash) please use the
-	  gspca konica module instead.
-
-	  Say Y here if you want support for webcams based on a Konica
-	  chipset. This is known to work with the Intel YC76 webcam.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called konicawc.
-
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/usbvideo/konicawc.c linux-libre-2.6.38-gnu1/drivers/media/video/usbvideo/konicawc.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/usbvideo/konicawc.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/usbvideo/konicawc.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,992 +0,0 @@
-/*
- * konicawc.c - konica webcam driver
- *
- * Author: Simon Evans <spse@secret.org.uk>
- *
- * Copyright (C) 2002 Simon Evans
- *
- * Licence: GPL
- *
- * Driver for USB webcams based on Konica chipset. This
- * chipset is used in Intel YC76 camera.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/usb/input.h>
-#include <linux/gfp.h>
-
-#include "usbvideo.h"
-
-#define MAX_BRIGHTNESS	108
-#define MAX_CONTRAST	108
-#define MAX_SATURATION	108
-#define MAX_SHARPNESS	108
-#define MAX_WHITEBAL	372
-#define MAX_SPEED	6
-
-
-#define MAX_CAMERAS	1
-
-#define DRIVER_VERSION	"v1.4"
-#define DRIVER_DESC	"Konica Webcam driver"
-
-enum ctrl_req {
-	SetWhitebal	= 0x01,
-	SetBrightness	= 0x02,
-	SetSharpness	= 0x03,
-	SetContrast	= 0x04,
-	SetSaturation	= 0x05,
-};
-
-
-enum frame_sizes {
-	SIZE_160X120	= 0,
-	SIZE_160X136	= 1,
-	SIZE_176X144	= 2,
-	SIZE_320X240	= 3,
-
-};
-
-#define MAX_FRAME_SIZE	SIZE_320X240
-
-static struct usbvideo *cams;
-
-#ifdef CONFIG_USB_DEBUG
-static int debug;
-#define DEBUG(n, format, arg...) \
-	if (n <= debug) {	 \
-		printk(KERN_DEBUG __FILE__ ":%s(): " format "\n", __func__ , ## arg); \
-	}
-#else
-#define DEBUG(n, arg...)
-static const int debug;
-#endif
-
-
-/* Some default values for initial camera settings,
-   can be set by modprobe */
-
-static int size;
-static int speed = 6;		/* Speed (fps) 0 (slowest) to 6 (fastest) */
-static int brightness =	MAX_BRIGHTNESS/2;
-static int contrast =	MAX_CONTRAST/2;
-static int saturation =	MAX_SATURATION/2;
-static int sharpness =	MAX_SHARPNESS/2;
-static int whitebal =	3*(MAX_WHITEBAL/4);
-
-static const int spd_to_iface[] = { 1, 0, 3, 2, 4, 5, 6 };
-
-/* These FPS speeds are from the windows config box. They are
- * indexed on size (0-2) and speed (0-6). Divide by 3 to get the
- * real fps.
- */
-
-static const int spd_to_fps[][7] = { { 24, 40, 48, 60, 72, 80, 100 },
-			       { 24, 40, 48, 60, 72, 80, 100 },
-			       { 18, 30, 36, 45, 54, 60, 75  },
-			       { 6,  10, 12, 15, 18, 21, 25  } };
-
-struct cam_size {
-	u16	width;
-	u16	height;
-	u8	cmd;
-};
-
-static const struct cam_size camera_sizes[] = { { 160, 120, 0x7 },
-					  { 160, 136, 0xa },
-					  { 176, 144, 0x4 },
-					  { 320, 240, 0x5 } };
-
-struct konicawc {
-	u8 brightness;		/* camera uses 0 - 9, x11 for real value */
-	u8 contrast;		/* as above */
-	u8 saturation;		/* as above */
-	u8 sharpness;		/* as above */
-	u8 white_bal;		/* 0 - 33, x11 for real value */
-	u8 speed;		/* Stored as 0 - 6, used as index in spd_to_* (above) */
-	u8 size;		/* Frame Size */
-	int height;
-	int width;
-	struct urb *sts_urb[USBVIDEO_NUMSBUF];
-	u8 sts_buf[USBVIDEO_NUMSBUF][FRAMES_PER_DESC];
-	struct urb *last_data_urb;
-	int lastframe;
-	int cur_frame_size;	/* number of bytes in current frame size */
-	int maxline;		/* number of lines per frame */
-	int yplanesz;		/* Number of bytes in the Y plane */
-	unsigned int buttonsts:1;
-#ifdef CONFIG_INPUT
-	struct input_dev *input;
-	char input_physname[64];
-#endif
-};
-
-
-#define konicawc_set_misc(uvd, req, value, index)		konicawc_ctrl_msg(uvd, USB_DIR_OUT, req, value, index, NULL, 0)
-#define konicawc_get_misc(uvd, req, value, index, buf, sz)	konicawc_ctrl_msg(uvd, USB_DIR_IN, req, value, index, buf, sz)
-#define konicawc_set_value(uvd, value, index)			konicawc_ctrl_msg(uvd, USB_DIR_OUT, 2, value, index, NULL, 0)
-
-
-static int konicawc_ctrl_msg(struct uvd *uvd, u8 dir, u8 request, u16 value, u16 index, void *buf, int len)
-{
-	int retval = usb_control_msg(uvd->dev,
-		dir ? usb_rcvctrlpipe(uvd->dev, 0) : usb_sndctrlpipe(uvd->dev, 0),
-		    request, 0x40 | dir, value, index, buf, len, 1000);
-	return retval < 0 ? retval : 0;
-}
-
-
-static inline void konicawc_camera_on(struct uvd *uvd)
-{
-	DEBUG(0, "camera on");
-	konicawc_set_misc(uvd, 0x2, 1, 0x0b);
-}
-
-
-static inline void konicawc_camera_off(struct uvd *uvd)
-{
-	DEBUG(0, "camera off");
-	konicawc_set_misc(uvd, 0x2, 0, 0x0b);
-}
-
-
-static void konicawc_set_camera_size(struct uvd *uvd)
-{
-	struct konicawc *cam = (struct konicawc *)uvd->user_data;
-
-	konicawc_set_misc(uvd, 0x2, camera_sizes[cam->size].cmd, 0x08);
-	cam->width = camera_sizes[cam->size].width;
-	cam->height = camera_sizes[cam->size].height;
-	cam->yplanesz = cam->height * cam->width;
-	cam->cur_frame_size = (cam->yplanesz * 3) / 2;
-	cam->maxline = cam->yplanesz / 256;
-	uvd->videosize = VIDEOSIZE(cam->width, cam->height);
-}
-
-
-static int konicawc_setup_on_open(struct uvd *uvd)
-{
-	struct konicawc *cam = (struct konicawc *)uvd->user_data;
-
-	DEBUG(1, "setting brightness to %d (%d)", cam->brightness,
-	    cam->brightness * 11);
-	konicawc_set_value(uvd, cam->brightness, SetBrightness);
-	DEBUG(1, "setting white balance to %d (%d)", cam->white_bal,
-	    cam->white_bal * 11);
-	konicawc_set_value(uvd, cam->white_bal, SetWhitebal);
-	DEBUG(1, "setting contrast to %d (%d)", cam->contrast,
-	    cam->contrast * 11);
-	konicawc_set_value(uvd, cam->contrast, SetContrast);
-	DEBUG(1, "setting saturation to %d (%d)", cam->saturation,
-	    cam->saturation * 11);
-	konicawc_set_value(uvd, cam->saturation, SetSaturation);
-	DEBUG(1, "setting sharpness to %d (%d)", cam->sharpness,
-	    cam->sharpness * 11);
-	konicawc_set_value(uvd, cam->sharpness, SetSharpness);
-	konicawc_set_camera_size(uvd);
-	cam->lastframe = -2;
-	cam->buttonsts = 0;
-	return 0;
-}
-
-
-static void konicawc_adjust_picture(struct uvd *uvd)
-{
-	struct konicawc *cam = (struct konicawc *)uvd->user_data;
-
-	konicawc_camera_off(uvd);
-	DEBUG(1, "new brightness: %d", uvd->vpic.brightness);
-	uvd->vpic.brightness = (uvd->vpic.brightness > MAX_BRIGHTNESS) ? MAX_BRIGHTNESS : uvd->vpic.brightness;
-	if(cam->brightness != uvd->vpic.brightness / 11) {
-	   cam->brightness = uvd->vpic.brightness / 11;
-	   DEBUG(1, "setting brightness to %d (%d)", cam->brightness,
-	       cam->brightness * 11);
-	   konicawc_set_value(uvd, cam->brightness, SetBrightness);
-	}
-
-	DEBUG(1, "new contrast: %d", uvd->vpic.contrast);
-	uvd->vpic.contrast = (uvd->vpic.contrast > MAX_CONTRAST) ? MAX_CONTRAST : uvd->vpic.contrast;
-	if(cam->contrast != uvd->vpic.contrast / 11) {
-		cam->contrast = uvd->vpic.contrast / 11;
-		DEBUG(1, "setting contrast to %d (%d)", cam->contrast,
-		    cam->contrast * 11);
-		konicawc_set_value(uvd, cam->contrast, SetContrast);
-	}
-	konicawc_camera_on(uvd);
-}
-
-#ifdef CONFIG_INPUT
-
-static void konicawc_register_input(struct konicawc *cam, struct usb_device *dev)
-{
-	struct input_dev *input_dev;
-	int error;
-
-	usb_make_path(dev, cam->input_physname, sizeof(cam->input_physname));
-	strlcat(cam->input_physname, "/input0", sizeof(cam->input_physname));
-
-	cam->input = input_dev = input_allocate_device();
-	if (!input_dev) {
-		dev_warn(&dev->dev,
-			 "Not enough memory for camera's input device\n");
-		return;
-	}
-
-	input_dev->name = "Konicawc snapshot button";
-	input_dev->phys = cam->input_physname;
-	usb_to_input_id(dev, &input_dev->id);
-	input_dev->dev.parent = &dev->dev;
-
-	input_dev->evbit[0] = BIT_MASK(EV_KEY);
-	input_dev->keybit[BIT_WORD(KEY_CAMERA)] = BIT_MASK(KEY_CAMERA);
-
-	error = input_register_device(cam->input);
-	if (error) {
-		dev_warn(&dev->dev,
-			 "Failed to register camera's input device, err: %d\n",
-			 error);
-		input_free_device(cam->input);
-		cam->input = NULL;
-	}
-}
-
-static void konicawc_unregister_input(struct konicawc *cam)
-{
-	if (cam->input) {
-		input_unregister_device(cam->input);
-		cam->input = NULL;
-	}
-}
-
-static void konicawc_report_buttonstat(struct konicawc *cam)
-{
-	if (cam->input) {
-		input_report_key(cam->input, KEY_CAMERA, cam->buttonsts);
-		input_sync(cam->input);
-	}
-}
-
-#else
-
-static inline void konicawc_register_input(struct konicawc *cam, struct usb_device *dev) { }
-static inline void konicawc_unregister_input(struct konicawc *cam) { }
-static inline void konicawc_report_buttonstat(struct konicawc *cam) { }
-
-#endif /* CONFIG_INPUT */
-
-static int konicawc_compress_iso(struct uvd *uvd, struct urb *dataurb, struct urb *stsurb)
-{
-	char *cdata;
-	int i, totlen = 0;
-	unsigned char *status = stsurb->transfer_buffer;
-	int keep = 0, discard = 0, bad = 0;
-	struct konicawc *cam = (struct konicawc *)uvd->user_data;
-
-	for (i = 0; i < dataurb->number_of_packets; i++) {
-		int button = cam->buttonsts;
-		unsigned char sts;
-		int n = dataurb->iso_frame_desc[i].actual_length;
-		int st = dataurb->iso_frame_desc[i].status;
-		cdata = dataurb->transfer_buffer +
-			dataurb->iso_frame_desc[i].offset;
-
-		/* Detect and ignore errored packets */
-		if (st < 0) {
-			DEBUG(1, "Data error: packet=%d. len=%d. status=%d.",
-			      i, n, st);
-			uvd->stats.iso_err_count++;
-			continue;
-		}
-
-		/* Detect and ignore empty packets */
-		if (n <= 0) {
-			uvd->stats.iso_skip_count++;
-			continue;
-		}
-
-		/* See what the status data said about the packet */
-		sts = *(status+stsurb->iso_frame_desc[i].offset);
-
-		/* sts: 0x80-0xff: frame start with frame number (ie 0-7f)
-		 * otherwise:
-		 * bit 0 0: keep packet
-		 *	 1: drop packet (padding data)
-		 *
-		 * bit 4 0 button not clicked
-		 *       1 button clicked
-		 * button is used to `take a picture' (in software)
-		 */
-
-		if(sts < 0x80) {
-			button = !!(sts & 0x40);
-			sts &= ~0x40;
-		}
-
-		/* work out the button status, but don't do
-		   anything with it for now */
-
-		if(button != cam->buttonsts) {
-			DEBUG(2, "button: %sclicked", button ? "" : "un");
-			cam->buttonsts = button;
-			konicawc_report_buttonstat(cam);
-		}
-
-		if(sts == 0x01) { /* drop frame */
-			discard++;
-			continue;
-		}
-
-		if((sts > 0x01) && (sts < 0x80)) {
-			dev_info(&uvd->dev->dev, "unknown status %2.2x\n",
-				 sts);
-			bad++;
-			continue;
-		}
-		if(!sts && cam->lastframe == -2) {
-			DEBUG(2, "dropping frame looking for image start");
-			continue;
-		}
-
-		keep++;
-		if(sts & 0x80) { /* frame start */
-			unsigned char marker[] = { 0, 0xff, 0, 0x00 };
-
-			if(cam->lastframe == -2) {
-				DEBUG(2, "found initial image");
-				cam->lastframe = -1;
-			}
-
-			marker[3] = sts & 0x7F;
-			RingQueue_Enqueue(&uvd->dp, marker, 4);
-			totlen += 4;
-		}
-
-		totlen += n;	/* Little local accounting */
-		RingQueue_Enqueue(&uvd->dp, cdata, n);
-	}
-	DEBUG(8, "finished: keep = %d discard = %d bad = %d added %d bytes",
-		    keep, discard, bad, totlen);
-	return totlen;
-}
-
-
-static void resubmit_urb(struct uvd *uvd, struct urb *urb)
-{
-	int i, ret;
-	for (i = 0; i < FRAMES_PER_DESC; i++) {
-		urb->iso_frame_desc[i].status = 0;
-	}
-	urb->dev = uvd->dev;
-	urb->status = 0;
-	ret = usb_submit_urb(urb, GFP_ATOMIC);
-	DEBUG(3, "submitting urb of length %d", urb->transfer_buffer_length);
-	if(ret)
-		err("usb_submit_urb error (%d)", ret);
-
-}
-
-
-static void konicawc_isoc_irq(struct urb *urb)
-{
-	struct uvd *uvd = urb->context;
-	struct konicawc *cam = (struct konicawc *)uvd->user_data;
-
-	/* We don't want to do anything if we are about to be removed! */
-	if (!CAMERA_IS_OPERATIONAL(uvd))
-		return;
-
-	if (!uvd->streaming) {
-		DEBUG(1, "Not streaming, but interrupt!");
-		return;
-	}
-
-	DEBUG(3, "got frame %d len = %d buflen =%d", urb->start_frame, urb->actual_length, urb->transfer_buffer_length);
-
-	uvd->stats.urb_count++;
-
-	if (urb->transfer_buffer_length > 32) {
-		cam->last_data_urb = urb;
-		return;
-	}
-	/* Copy the data received into ring queue */
-	if(cam->last_data_urb) {
-		int len = 0;
-		if(urb->start_frame != cam->last_data_urb->start_frame)
-			err("Lost sync on frames");
-		else if (!urb->status && !cam->last_data_urb->status)
-			len = konicawc_compress_iso(uvd, cam->last_data_urb, urb);
-
-		resubmit_urb(uvd, cam->last_data_urb);
-		resubmit_urb(uvd, urb);
-		cam->last_data_urb = NULL;
-		uvd->stats.urb_length = len;
-		uvd->stats.data_count += len;
-		if(len)
-			RingQueue_WakeUpInterruptible(&uvd->dp);
-		return;
-	}
-	return;
-}
-
-
-static int konicawc_start_data(struct uvd *uvd)
-{
-	struct usb_device *dev = uvd->dev;
-	int i, errFlag;
-	struct konicawc *cam = (struct konicawc *)uvd->user_data;
-	int pktsz;
-	struct usb_interface *intf;
-	struct usb_host_interface *interface = NULL;
-
-	intf = usb_ifnum_to_if(dev, uvd->iface);
-	if (intf)
-		interface = usb_altnum_to_altsetting(intf,
-				spd_to_iface[cam->speed]);
-	if (!interface)
-		return -ENXIO;
-	pktsz = le16_to_cpu(interface->endpoint[1].desc.wMaxPacketSize);
-	DEBUG(1, "pktsz = %d", pktsz);
-	if (!CAMERA_IS_OPERATIONAL(uvd)) {
-		err("Camera is not operational");
-		return -EFAULT;
-	}
-	uvd->curframe = -1;
-	konicawc_camera_on(uvd);
-	/* Alternate interface 1 is is the biggest frame size */
-	i = usb_set_interface(dev, uvd->iface, uvd->ifaceAltActive);
-	if (i < 0) {
-		err("usb_set_interface error");
-		uvd->last_error = i;
-		return -EBUSY;
-	}
-
-	/* We double buffer the Iso lists */
-	for (i=0; i < USBVIDEO_NUMSBUF; i++) {
-		int j, k;
-		struct urb *urb = uvd->sbuf[i].urb;
-		urb->dev = dev;
-		urb->context = uvd;
-		urb->pipe = usb_rcvisocpipe(dev, uvd->video_endp);
-		urb->interval = 1;
-		urb->transfer_flags = URB_ISO_ASAP;
-		urb->transfer_buffer = uvd->sbuf[i].data;
-		urb->complete = konicawc_isoc_irq;
-		urb->number_of_packets = FRAMES_PER_DESC;
-		urb->transfer_buffer_length = pktsz * FRAMES_PER_DESC;
-		for (j=k=0; j < FRAMES_PER_DESC; j++, k += pktsz) {
-			urb->iso_frame_desc[j].offset = k;
-			urb->iso_frame_desc[j].length = pktsz;
-		}
-
-		urb = cam->sts_urb[i];
-		urb->dev = dev;
-		urb->context = uvd;
-		urb->pipe = usb_rcvisocpipe(dev, uvd->video_endp-1);
-		urb->interval = 1;
-		urb->transfer_flags = URB_ISO_ASAP;
-		urb->transfer_buffer = cam->sts_buf[i];
-		urb->complete = konicawc_isoc_irq;
-		urb->number_of_packets = FRAMES_PER_DESC;
-		urb->transfer_buffer_length = FRAMES_PER_DESC;
-		for (j=0; j < FRAMES_PER_DESC; j++) {
-			urb->iso_frame_desc[j].offset = j;
-			urb->iso_frame_desc[j].length = 1;
-		}
-	}
-
-	cam->last_data_urb = NULL;
-
-	/* Submit all URBs */
-	for (i=0; i < USBVIDEO_NUMSBUF; i++) {
-		errFlag = usb_submit_urb(cam->sts_urb[i], GFP_KERNEL);
-		if (errFlag)
-			err("usb_submit_isoc(%d) ret %d", i, errFlag);
-
-		errFlag = usb_submit_urb(uvd->sbuf[i].urb, GFP_KERNEL);
-		if (errFlag)
-			err ("usb_submit_isoc(%d) ret %d", i, errFlag);
-	}
-
-	uvd->streaming = 1;
-	DEBUG(1, "streaming=1 video_endp=$%02x", uvd->video_endp);
-	return 0;
-}
-
-
-static void konicawc_stop_data(struct uvd *uvd)
-{
-	int i, j;
-	struct konicawc *cam;
-
-	if ((uvd == NULL) || (!uvd->streaming) || (uvd->dev == NULL))
-		return;
-
-	konicawc_camera_off(uvd);
-	uvd->streaming = 0;
-	cam = (struct konicawc *)uvd->user_data;
-	cam->last_data_urb = NULL;
-
-	/* Unschedule all of the iso td's */
-	for (i=0; i < USBVIDEO_NUMSBUF; i++) {
-		usb_kill_urb(uvd->sbuf[i].urb);
-		usb_kill_urb(cam->sts_urb[i]);
-	}
-
-	if (!uvd->remove_pending) {
-		/* Set packet size to 0 */
-		j = usb_set_interface(uvd->dev, uvd->iface, uvd->ifaceAltInactive);
-		if (j < 0) {
-			err("usb_set_interface() error %d.", j);
-			uvd->last_error = j;
-		}
-	}
-}
-
-
-static void konicawc_process_isoc(struct uvd *uvd, struct usbvideo_frame *frame)
-{
-	struct konicawc *cam = (struct konicawc *)uvd->user_data;
-	int maxline = cam->maxline;
-	int yplanesz = cam->yplanesz;
-
-	assert(frame != NULL);
-
-	DEBUG(5, "maxline = %d yplanesz = %d", maxline, yplanesz);
-	DEBUG(3, "Frame state = %d", frame->scanstate);
-
-	if(frame->scanstate == ScanState_Scanning) {
-		int drop = 0;
-		int curframe;
-		int fdrops = 0;
-		DEBUG(3, "Searching for marker, queue len = %d", RingQueue_GetLength(&uvd->dp));
-		while(RingQueue_GetLength(&uvd->dp) >= 4) {
-			if ((RING_QUEUE_PEEK(&uvd->dp, 0) == 0x00) &&
-			    (RING_QUEUE_PEEK(&uvd->dp, 1) == 0xff) &&
-			    (RING_QUEUE_PEEK(&uvd->dp, 2) == 0x00) &&
-			    (RING_QUEUE_PEEK(&uvd->dp, 3) < 0x80)) {
-				curframe = RING_QUEUE_PEEK(&uvd->dp, 3);
-				if(cam->lastframe >= 0) {
-					fdrops = (0x80 + curframe - cam->lastframe) & 0x7F;
-					fdrops--;
-					if(fdrops) {
-						dev_info(&uvd->dev->dev,
-							 "Dropped %d frames "
-							 "(%d -> %d)\n",
-							 fdrops,
-							 cam->lastframe,
-							 curframe);
-					}
-				}
-				cam->lastframe = curframe;
-				frame->curline = 0;
-				frame->scanstate = ScanState_Lines;
-				RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, 4);
-				break;
-			}
-			RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, 1);
-			drop++;
-		}
-		if(drop)
-			DEBUG(2, "dropped %d bytes looking for new frame", drop);
-	}
-
-	if(frame->scanstate == ScanState_Scanning)
-		return;
-
-	/* Try to move data from queue into frame buffer
-	 * We get data in blocks of 384 bytes made up of:
-	 * 256 Y, 64 U, 64 V.
-	 * This needs to be written out as a Y plane, a U plane and a V plane.
-	 */
-
-	while ( frame->curline < maxline && (RingQueue_GetLength(&uvd->dp) >= 384)) {
-		/* Y */
-		RingQueue_Dequeue(&uvd->dp, frame->data + (frame->curline * 256), 256);
-		/* U */
-		RingQueue_Dequeue(&uvd->dp, frame->data + yplanesz + (frame->curline * 64), 64);
-		/* V */
-		RingQueue_Dequeue(&uvd->dp, frame->data + (5 * yplanesz)/4 + (frame->curline * 64), 64);
-		frame->seqRead_Length += 384;
-		frame->curline++;
-	}
-	/* See if we filled the frame */
-	if (frame->curline == maxline) {
-		DEBUG(5, "got whole frame");
-
-		frame->frameState = FrameState_Done_Hold;
-		frame->curline = 0;
-		uvd->curframe = -1;
-		uvd->stats.frame_num++;
-	}
-}
-
-
-static int konicawc_find_fps(int size, int fps)
-{
-	int i;
-
-	fps *= 3;
-	DEBUG(1, "konica_find_fps: size = %d fps = %d", size, fps);
-	if(fps <= spd_to_fps[size][0])
-		return 0;
-
-	if(fps >= spd_to_fps[size][MAX_SPEED])
-		return MAX_SPEED;
-
-	for(i = 0; i < MAX_SPEED; i++) {
-		if((fps >= spd_to_fps[size][i]) && (fps <= spd_to_fps[size][i+1])) {
-			DEBUG(2, "fps %d between %d and %d", fps, i, i+1);
-			if( (fps - spd_to_fps[size][i]) < (spd_to_fps[size][i+1] - fps))
-				return i;
-			else
-				return i+1;
-		}
-	}
-	return MAX_SPEED+1;
-}
-
-
-static int konicawc_set_video_mode(struct uvd *uvd, struct video_window *vw)
-{
-	struct konicawc *cam = (struct konicawc *)uvd->user_data;
-	int newspeed = cam->speed;
-	int newsize;
-	int x = vw->width;
-	int y = vw->height;
-	int fps = vw->flags;
-
-	if(x > 0 && y > 0) {
-		DEBUG(2, "trying to find size %d,%d", x, y);
-		for(newsize = 0; newsize <= MAX_FRAME_SIZE; newsize++) {
-			if((camera_sizes[newsize].width == x) && (camera_sizes[newsize].height == y))
-				break;
-		}
-	} else {
-		newsize = cam->size;
-	}
-
-	if(newsize > MAX_FRAME_SIZE) {
-		DEBUG(1, "couldn't find size %d,%d", x, y);
-		return -EINVAL;
-	}
-
-	if(fps > 0) {
-		DEBUG(1, "trying to set fps to %d", fps);
-		newspeed = konicawc_find_fps(newsize, fps);
-		DEBUG(1, "find_fps returned %d (%d)", newspeed, spd_to_fps[newsize][newspeed]);
-	}
-
-	if(newspeed > MAX_SPEED)
-		return -EINVAL;
-
-	DEBUG(1, "setting size to %d speed to %d", newsize, newspeed);
-	if((newsize == cam->size) && (newspeed == cam->speed)) {
-		DEBUG(1, "Nothing to do");
-		return 0;
-	}
-	DEBUG(0, "setting to  %dx%d @ %d fps", camera_sizes[newsize].width,
-	     camera_sizes[newsize].height, spd_to_fps[newsize][newspeed]/3);
-
-	konicawc_stop_data(uvd);
-	uvd->ifaceAltActive = spd_to_iface[newspeed];
-	DEBUG(1, "new interface = %d", uvd->ifaceAltActive);
-	cam->speed = newspeed;
-
-	if(cam->size != newsize) {
-		cam->size = newsize;
-		konicawc_set_camera_size(uvd);
-	}
-
-	/* Flush the input queue and clear any current frame in progress */
-
-	RingQueue_Flush(&uvd->dp);
-	cam->lastframe = -2;
-	if(uvd->curframe != -1) {
-		uvd->frame[uvd->curframe].curline = 0;
-		uvd->frame[uvd->curframe].seqRead_Length = 0;
-		uvd->frame[uvd->curframe].seqRead_Index = 0;
-	}
-
-	konicawc_start_data(uvd);
-	return 0;
-}
-
-
-static int konicawc_calculate_fps(struct uvd *uvd)
-{
-	struct konicawc *cam = uvd->user_data;
-	return spd_to_fps[cam->size][cam->speed]/3;
-}
-
-
-static void konicawc_configure_video(struct uvd *uvd)
-{
-	struct konicawc *cam = (struct konicawc *)uvd->user_data;
-	u8 buf[2];
-
-	memset(&uvd->vpic, 0, sizeof(uvd->vpic));
-	memset(&uvd->vpic_old, 0x55, sizeof(uvd->vpic_old));
-
-	RESTRICT_TO_RANGE(brightness, 0, MAX_BRIGHTNESS);
-	RESTRICT_TO_RANGE(contrast, 0, MAX_CONTRAST);
-	RESTRICT_TO_RANGE(saturation, 0, MAX_SATURATION);
-	RESTRICT_TO_RANGE(sharpness, 0, MAX_SHARPNESS);
-	RESTRICT_TO_RANGE(whitebal, 0, MAX_WHITEBAL);
-
-	cam->brightness = brightness / 11;
-	cam->contrast = contrast / 11;
-	cam->saturation = saturation / 11;
-	cam->sharpness = sharpness / 11;
-	cam->white_bal = whitebal / 11;
-
-	uvd->vpic.colour = 108;
-	uvd->vpic.hue = 108;
-	uvd->vpic.brightness = brightness;
-	uvd->vpic.contrast = contrast;
-	uvd->vpic.whiteness = whitebal;
-	uvd->vpic.depth = 6;
-	uvd->vpic.palette = VIDEO_PALETTE_YUV420P;
-
-	memset(&uvd->vcap, 0, sizeof(uvd->vcap));
-	strcpy(uvd->vcap.name, "Konica Webcam");
-	uvd->vcap.type = VID_TYPE_CAPTURE;
-	uvd->vcap.channels = 1;
-	uvd->vcap.audios = 0;
-	uvd->vcap.minwidth = camera_sizes[SIZE_160X120].width;
-	uvd->vcap.minheight = camera_sizes[SIZE_160X120].height;
-	uvd->vcap.maxwidth = camera_sizes[SIZE_320X240].width;
-	uvd->vcap.maxheight = camera_sizes[SIZE_320X240].height;
-
-	memset(&uvd->vchan, 0, sizeof(uvd->vchan));
-	uvd->vchan.flags = 0 ;
-	uvd->vchan.tuners = 0;
-	uvd->vchan.channel = 0;
-	uvd->vchan.type = VIDEO_TYPE_CAMERA;
-	strcpy(uvd->vchan.name, "Camera");
-
-	/* Talk to device */
-	DEBUG(1, "device init");
-	if(!konicawc_get_misc(uvd, 0x3, 0, 0x10, buf, 2))
-		DEBUG(2, "3,10 -> %2.2x %2.2x", buf[0], buf[1]);
-	if(!konicawc_get_misc(uvd, 0x3, 0, 0x10, buf, 2))
-		DEBUG(2, "3,10 -> %2.2x %2.2x", buf[0], buf[1]);
-	if(konicawc_set_misc(uvd, 0x2, 0, 0xd))
-		DEBUG(2, "2,0,d failed");
-	DEBUG(1, "setting initial values");
-}
-
-static int konicawc_probe(struct usb_interface *intf, const struct usb_device_id *devid)
-{
-	struct usb_device *dev = interface_to_usbdev(intf);
-	struct uvd *uvd = NULL;
-	int ix, i, nas;
-	int actInterface=-1, inactInterface=-1, maxPS=0;
-	unsigned char video_ep = 0;
-
-	DEBUG(1, "konicawc_probe(%p)", intf);
-
-	/* We don't handle multi-config cameras */
-	if (dev->descriptor.bNumConfigurations != 1)
-		return -ENODEV;
-
-	dev_info(&intf->dev, "Konica Webcam (rev. 0x%04x)\n",
-		 le16_to_cpu(dev->descriptor.bcdDevice));
-	RESTRICT_TO_RANGE(speed, 0, MAX_SPEED);
-
-	/* Validate found interface: must have one ISO endpoint */
-	nas = intf->num_altsetting;
-	if (nas != 8) {
-		err("Incorrect number of alternate settings (%d) for this camera!", nas);
-		return -ENODEV;
-	}
-	/* Validate all alternate settings */
-	for (ix=0; ix < nas; ix++) {
-		const struct usb_host_interface *interface;
-		const struct usb_endpoint_descriptor *endpoint;
-
-		interface = &intf->altsetting[ix];
-		i = interface->desc.bAlternateSetting;
-		if (interface->desc.bNumEndpoints != 2) {
-			err("Interface %d. has %u. endpoints!",
-			    interface->desc.bInterfaceNumber,
-			    (unsigned)(interface->desc.bNumEndpoints));
-			return -ENODEV;
-		}
-		endpoint = &interface->endpoint[1].desc;
-		DEBUG(1, "found endpoint: addr: 0x%2.2x maxps = 0x%4.4x",
-		    endpoint->bEndpointAddress, le16_to_cpu(endpoint->wMaxPacketSize));
-		if (video_ep == 0)
-			video_ep = endpoint->bEndpointAddress;
-		else if (video_ep != endpoint->bEndpointAddress) {
-			err("Alternate settings have different endpoint addresses!");
-			return -ENODEV;
-		}
-		if (!usb_endpoint_xfer_isoc(endpoint)) {
-			err("Interface %d. has non-ISO endpoint!",
-			    interface->desc.bInterfaceNumber);
-			return -ENODEV;
-		}
-		if (usb_endpoint_dir_out(endpoint)) {
-			err("Interface %d. has ISO OUT endpoint!",
-			    interface->desc.bInterfaceNumber);
-			return -ENODEV;
-		}
-		if (le16_to_cpu(endpoint->wMaxPacketSize) == 0) {
-			if (inactInterface < 0)
-				inactInterface = i;
-			else {
-				err("More than one inactive alt. setting!");
-				return -ENODEV;
-			}
-		} else {
-			if (i == spd_to_iface[speed]) {
-				/* This one is the requested one */
-				actInterface = i;
-			}
-		}
-		if (le16_to_cpu(endpoint->wMaxPacketSize) > maxPS)
-			maxPS = le16_to_cpu(endpoint->wMaxPacketSize);
-	}
-	if(actInterface == -1) {
-		err("Cant find required endpoint");
-		return -ENODEV;
-	}
-
-	DEBUG(1, "Selecting requested active setting=%d. maxPS=%d.", actInterface, maxPS);
-
-	uvd = usbvideo_AllocateDevice(cams);
-	if (uvd != NULL) {
-		struct konicawc *cam = (struct konicawc *)(uvd->user_data);
-		/* Here uvd is a fully allocated uvd object */
-		for(i = 0; i < USBVIDEO_NUMSBUF; i++) {
-			cam->sts_urb[i] = usb_alloc_urb(FRAMES_PER_DESC, GFP_KERNEL);
-			if(cam->sts_urb[i] == NULL) {
-				while(i--) {
-					usb_free_urb(cam->sts_urb[i]);
-				}
-				err("can't allocate urbs");
-				return -ENOMEM;
-			}
-		}
-		cam->speed = speed;
-		RESTRICT_TO_RANGE(size, SIZE_160X120, SIZE_320X240);
-		cam->width = camera_sizes[size].width;
-		cam->height = camera_sizes[size].height;
-		cam->size = size;
-
-		uvd->flags = 0;
-		uvd->debug = debug;
-		uvd->dev = dev;
-		uvd->iface = intf->altsetting->desc.bInterfaceNumber;
-		uvd->ifaceAltInactive = inactInterface;
-		uvd->ifaceAltActive = actInterface;
-		uvd->video_endp = video_ep;
-		uvd->iso_packet_len = maxPS;
-		uvd->paletteBits = 1L << VIDEO_PALETTE_YUV420P;
-		uvd->defaultPalette = VIDEO_PALETTE_YUV420P;
-		uvd->canvas = VIDEOSIZE(320, 240);
-		uvd->videosize = VIDEOSIZE(cam->width, cam->height);
-
-		/* Initialize konicawc specific data */
-		konicawc_configure_video(uvd);
-
-		i = usbvideo_RegisterVideoDevice(uvd);
-		uvd->max_frame_size = (320 * 240 * 3)/2;
-		if (i != 0) {
-			err("usbvideo_RegisterVideoDevice() failed.");
-			uvd = NULL;
-		}
-
-		konicawc_register_input(cam, dev);
-	}
-
-	if (uvd) {
-		usb_set_intfdata (intf, uvd);
-		return 0;
-	}
-	return -EIO;
-}
-
-
-static void konicawc_free_uvd(struct uvd *uvd)
-{
-	int i;
-	struct konicawc *cam = (struct konicawc *)uvd->user_data;
-
-	konicawc_unregister_input(cam);
-
-	for (i = 0; i < USBVIDEO_NUMSBUF; i++) {
-		usb_free_urb(cam->sts_urb[i]);
-		cam->sts_urb[i] = NULL;
-	}
-}
-
-
-static struct usb_device_id id_table[] = {
-	{ USB_DEVICE(0x04c8, 0x0720) }, /* Intel YC 76 */
-	{ }  /* Terminating entry */
-};
-
-
-static int __init konicawc_init(void)
-{
-	struct usbvideo_cb cbTbl;
-	printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
-	       DRIVER_DESC "\n");
-	memset(&cbTbl, 0, sizeof(cbTbl));
-	cbTbl.probe = konicawc_probe;
-	cbTbl.setupOnOpen = konicawc_setup_on_open;
-	cbTbl.processData = konicawc_process_isoc;
-	cbTbl.getFPS = konicawc_calculate_fps;
-	cbTbl.setVideoMode = konicawc_set_video_mode;
-	cbTbl.startDataPump = konicawc_start_data;
-	cbTbl.stopDataPump = konicawc_stop_data;
-	cbTbl.adjustPicture = konicawc_adjust_picture;
-	cbTbl.userFree = konicawc_free_uvd;
-	return usbvideo_register(
-		&cams,
-		MAX_CAMERAS,
-		sizeof(struct konicawc),
-		"konicawc",
-		&cbTbl,
-		THIS_MODULE,
-		id_table);
-}
-
-
-static void __exit konicawc_cleanup(void)
-{
-	usbvideo_Deregister(&cams);
-}
-
-
-MODULE_DEVICE_TABLE(usb, id_table);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Simon Evans <spse@secret.org.uk>");
-MODULE_DESCRIPTION(DRIVER_DESC);
-module_param(speed, int, 0);
-MODULE_PARM_DESC(speed, "Initial speed: 0 (slowest) - 6 (fastest)");
-module_param(size, int, 0);
-MODULE_PARM_DESC(size, "Initial Size 0: 160x120 1: 160x136 2: 176x144 3: 320x240");
-module_param(brightness, int, 0);
-MODULE_PARM_DESC(brightness, "Initial brightness 0 - 108");
-module_param(contrast, int, 0);
-MODULE_PARM_DESC(contrast, "Initial contrast 0 - 108");
-module_param(saturation, int, 0);
-MODULE_PARM_DESC(saturation, "Initial saturation 0 - 108");
-module_param(sharpness, int, 0);
-MODULE_PARM_DESC(sharpness, "Initial brightness 0 - 108");
-module_param(whitebal, int, 0);
-MODULE_PARM_DESC(whitebal, "Initial white balance 0 - 363");
-
-#ifdef CONFIG_USB_DEBUG
-module_param(debug, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(debug, "Debug level: 0-9 (default=0)");
-#endif
-
-module_init(konicawc_init);
-module_exit(konicawc_cleanup);
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/usbvideo/Makefile linux-libre-2.6.38-gnu1/drivers/media/video/usbvideo/Makefile
--- linux-libre-2.6.37-gnu1/drivers/media/video/usbvideo/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/usbvideo/Makefile	1969-12-31 19:00:00.000000000 -0500
@@ -1,4 +0,0 @@
-obj-$(CONFIG_VIDEO_USBVIDEO)    += usbvideo.o
-obj-$(CONFIG_USB_IBMCAM)        += ibmcam.o ultracam.o
-obj-$(CONFIG_USB_KONICAWC)      += konicawc.o
-obj-$(CONFIG_USB_VICAM)         += vicam.o
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/usbvideo/ultracam.c linux-libre-2.6.38-gnu1/drivers/media/video/usbvideo/ultracam.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/usbvideo/ultracam.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/usbvideo/ultracam.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,685 +0,0 @@
-/*
- * USB NB Camera driver
- *
- * HISTORY:
- * 25-Dec-2002 Dmitri      Removed lighting, sharpness parameters, methods.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-
-#include "usbvideo.h"
-
-#define	ULTRACAM_VENDOR_ID	0x0461
-#define	ULTRACAM_PRODUCT_ID	0x0813
-
-#define MAX_CAMERAS		4	/* How many devices we allow to connect */
-
-/*
- * This structure lives in uvd_t->user field.
- */
-typedef struct {
-	int initialized;	/* Had we already sent init sequence? */
-	int camera_model;	/* What type of IBM camera we got? */
-	int has_hdr;
-} ultracam_t;
-#define	ULTRACAM_T(uvd)	((ultracam_t *)((uvd)->user_data))
-
-static struct usbvideo *cams = NULL;
-
-static int debug;
-
-static int flags; /* FLAGS_DISPLAY_HINTS | FLAGS_OVERLAY_STATS; */
-
-static const int min_canvasWidth  = 8;
-static const int min_canvasHeight = 4;
-
-#define FRAMERATE_MIN	0
-#define FRAMERATE_MAX	6
-static int framerate = -1;
-
-/*
- * Here we define several initialization variables. They may
- * be used to automatically set color, hue, brightness and
- * contrast to desired values. This is particularly useful in
- * case of webcams (which have no controls and no on-screen
- * output) and also when a client V4L software is used that
- * does not have some of those controls. In any case it's
- * good to have startup values as options.
- *
- * These values are all in [0..255] range. This simplifies
- * operation. Note that actual values of V4L variables may
- * be scaled up (as much as << 8). User can see that only
- * on overlay output, however, or through a V4L client.
- */
-static int init_brightness = 128;
-static int init_contrast = 192;
-static int init_color = 128;
-static int init_hue = 128;
-static int hue_correction = 128;
-
-module_param(debug, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(debug, "Debug level: 0-9 (default=0)");
-module_param(flags, int, 0);
-MODULE_PARM_DESC(flags,
-		"Bitfield: 0=VIDIOCSYNC, "
-		"1=B/W, "
-		"2=show hints, "
-		"3=show stats, "
-		"4=test pattern, "
-		"5=separate frames, "
-		"6=clean frames");
-module_param(framerate, int, 0);
-MODULE_PARM_DESC(framerate, "Framerate setting: 0=slowest, 6=fastest (default=2)");
-
-module_param(init_brightness, int, 0);
-MODULE_PARM_DESC(init_brightness, "Brightness preconfiguration: 0-255 (default=128)");
-module_param(init_contrast, int, 0);
-MODULE_PARM_DESC(init_contrast, "Contrast preconfiguration: 0-255 (default=192)");
-module_param(init_color, int, 0);
-MODULE_PARM_DESC(init_color, "Color preconfiguration: 0-255 (default=128)");
-module_param(init_hue, int, 0);
-MODULE_PARM_DESC(init_hue, "Hue preconfiguration: 0-255 (default=128)");
-module_param(hue_correction, int, 0);
-MODULE_PARM_DESC(hue_correction, "YUV colorspace regulation: 0-255 (default=128)");
-
-/*
- * ultracam_ProcessIsocData()
- *
- * Generic routine to parse the ring queue data. It employs either
- * ultracam_find_header() or ultracam_parse_lines() to do most
- * of work.
- *
- * 02-Nov-2000 First (mostly dummy) version.
- * 06-Nov-2000 Rewrote to dump all data into frame.
- */
-static void ultracam_ProcessIsocData(struct uvd *uvd, struct usbvideo_frame *frame)
-{
-	int n;
-
-	assert(uvd != NULL);
-	assert(frame != NULL);
-
-	/* Try to move data from queue into frame buffer */
-	n = RingQueue_GetLength(&uvd->dp);
-	if (n > 0) {
-		int m;
-		/* See how much spare we have left */
-		m = uvd->max_frame_size - frame->seqRead_Length;
-		if (n > m)
-			n = m;
-		/* Now move that much data into frame buffer */
-		RingQueue_Dequeue(
-			&uvd->dp,
-			frame->data + frame->seqRead_Length,
-			m);
-		frame->seqRead_Length += m;
-	}
-	/* See if we filled the frame */
-	if (frame->seqRead_Length >= uvd->max_frame_size) {
-		frame->frameState = FrameState_Done;
-		uvd->curframe = -1;
-		uvd->stats.frame_num++;
-	}
-}
-
-/*
- * ultracam_veio()
- *
- * History:
- * 1/27/00  Added check for dev == NULL; this happens if camera is unplugged.
- */
-static int ultracam_veio(
-	struct uvd *uvd,
-	unsigned char req,
-	unsigned short value,
-	unsigned short index,
-	int is_out)
-{
-	static const char proc[] = "ultracam_veio";
-	unsigned char cp[8] /* = { 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef } */;
-	int i;
-
-	if (!CAMERA_IS_OPERATIONAL(uvd))
-		return 0;
-
-	if (!is_out) {
-		i = usb_control_msg(
-			uvd->dev,
-			usb_rcvctrlpipe(uvd->dev, 0),
-			req,
-			USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-			value,
-			index,
-			cp,
-			sizeof(cp),
-			1000);
-#if 1
-		dev_info(&uvd->dev->dev,
-			 "USB => %02x%02x%02x%02x%02x%02x%02x%02x "
-			 "(req=$%02x val=$%04x ind=$%04x)\n",
-			 cp[0],cp[1],cp[2],cp[3],cp[4],cp[5],cp[6],cp[7],
-			 req, value, index);
-#endif
-	} else {
-		i = usb_control_msg(
-			uvd->dev,
-			usb_sndctrlpipe(uvd->dev, 0),
-			req,
-			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-			value,
-			index,
-			NULL,
-			0,
-			1000);
-	}
-	if (i < 0) {
-		err("%s: ERROR=%d. Camera stopped; Reconnect or reload driver.",
-		    proc, i);
-		uvd->last_error = i;
-	}
-	return i;
-}
-
-/*
- * ultracam_calculate_fps()
- */
-static int ultracam_calculate_fps(struct uvd *uvd)
-{
-	return 3 + framerate*4 + framerate/2;
-}
-
-/*
- * ultracam_adjust_contrast()
- */
-static void ultracam_adjust_contrast(struct uvd *uvd)
-{
-}
-
-/*
- * ultracam_set_brightness()
- *
- * This procedure changes brightness of the picture.
- */
-static void ultracam_set_brightness(struct uvd *uvd)
-{
-}
-
-static void ultracam_set_hue(struct uvd *uvd)
-{
-}
-
-/*
- * ultracam_adjust_picture()
- *
- * This procedure gets called from V4L interface to update picture settings.
- * Here we change brightness and contrast.
- */
-static void ultracam_adjust_picture(struct uvd *uvd)
-{
-	ultracam_adjust_contrast(uvd);
-	ultracam_set_brightness(uvd);
-	ultracam_set_hue(uvd);
-}
-
-/*
- * ultracam_video_stop()
- *
- * This code tells camera to stop streaming. The interface remains
- * configured and bandwidth - claimed.
- */
-static void ultracam_video_stop(struct uvd *uvd)
-{
-}
-
-/*
- * ultracam_reinit_iso()
- *
- * This procedure sends couple of commands to the camera and then
- * resets the video pipe. This sequence was observed to reinit the
- * camera or, at least, to initiate ISO data stream.
- */
-static void ultracam_reinit_iso(struct uvd *uvd, int do_stop)
-{
-}
-
-static void ultracam_video_start(struct uvd *uvd)
-{
-	ultracam_reinit_iso(uvd, 0);
-}
-
-static int ultracam_resetPipe(struct uvd *uvd)
-{
-	usb_clear_halt(uvd->dev, uvd->video_endp);
-	return 0;
-}
-
-static int ultracam_alternateSetting(struct uvd *uvd, int setting)
-{
-	static const char proc[] = "ultracam_alternateSetting";
-	int i;
-	i = usb_set_interface(uvd->dev, uvd->iface, setting);
-	if (i < 0) {
-		err("%s: usb_set_interface error", proc);
-		uvd->last_error = i;
-		return -EBUSY;
-	}
-	return 0;
-}
-
-/*
- * Return negative code on failure, 0 on success.
- */
-static int ultracam_setup_on_open(struct uvd *uvd)
-{
-	int setup_ok = 0; /* Success by default */
-	/* Send init sequence only once, it's large! */
-	if (!ULTRACAM_T(uvd)->initialized) {
-		ultracam_alternateSetting(uvd, 0x04);
-		ultracam_alternateSetting(uvd, 0x00);
-		ultracam_veio(uvd, 0x02, 0x0004, 0x000b, 1);
-		ultracam_veio(uvd, 0x02, 0x0001, 0x0005, 1);
-		ultracam_veio(uvd, 0x02, 0x8000, 0x0000, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x0000, 1);
-		ultracam_veio(uvd, 0x00, 0x00b0, 0x0001, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x0002, 1);
-		ultracam_veio(uvd, 0x00, 0x000c, 0x0003, 1);
-		ultracam_veio(uvd, 0x00, 0x000b, 0x0004, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x0005, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x0006, 1);
-		ultracam_veio(uvd, 0x00, 0x0079, 0x0007, 1);
-		ultracam_veio(uvd, 0x00, 0x003b, 0x0008, 1);
-		ultracam_veio(uvd, 0x00, 0x0002, 0x000f, 1);
-		ultracam_veio(uvd, 0x00, 0x0001, 0x0010, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x0011, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00bf, 1);
-		ultracam_veio(uvd, 0x00, 0x0001, 0x00c0, 1);
-		ultracam_veio(uvd, 0x00, 0x0010, 0x00cb, 1);
-		ultracam_veio(uvd, 0x01, 0x00a4, 0x0001, 1);
-		ultracam_veio(uvd, 0x01, 0x0010, 0x0002, 1);
-		ultracam_veio(uvd, 0x01, 0x0066, 0x0007, 1);
-		ultracam_veio(uvd, 0x01, 0x000b, 0x0008, 1);
-		ultracam_veio(uvd, 0x01, 0x0034, 0x0009, 1);
-		ultracam_veio(uvd, 0x01, 0x0000, 0x000a, 1);
-		ultracam_veio(uvd, 0x01, 0x002e, 0x000b, 1);
-		ultracam_veio(uvd, 0x01, 0x00d6, 0x000c, 1);
-		ultracam_veio(uvd, 0x01, 0x00fc, 0x000d, 1);
-		ultracam_veio(uvd, 0x01, 0x00f1, 0x000e, 1);
-		ultracam_veio(uvd, 0x01, 0x00da, 0x000f, 1);
-		ultracam_veio(uvd, 0x01, 0x0036, 0x0010, 1);
-		ultracam_veio(uvd, 0x01, 0x000b, 0x0011, 1);
-		ultracam_veio(uvd, 0x01, 0x0001, 0x0012, 1);
-		ultracam_veio(uvd, 0x01, 0x0000, 0x0013, 1);
-		ultracam_veio(uvd, 0x01, 0x0000, 0x0014, 1);
-		ultracam_veio(uvd, 0x01, 0x0087, 0x0051, 1);
-		ultracam_veio(uvd, 0x01, 0x0040, 0x0052, 1);
-		ultracam_veio(uvd, 0x01, 0x0058, 0x0053, 1);
-		ultracam_veio(uvd, 0x01, 0x0040, 0x0054, 1);
-		ultracam_veio(uvd, 0x01, 0x0000, 0x0040, 1);
-		ultracam_veio(uvd, 0x01, 0x0010, 0x0041, 1);
-		ultracam_veio(uvd, 0x01, 0x0020, 0x0042, 1);
-		ultracam_veio(uvd, 0x01, 0x0030, 0x0043, 1);
-		ultracam_veio(uvd, 0x01, 0x0040, 0x0044, 1);
-		ultracam_veio(uvd, 0x01, 0x0050, 0x0045, 1);
-		ultracam_veio(uvd, 0x01, 0x0060, 0x0046, 1);
-		ultracam_veio(uvd, 0x01, 0x0070, 0x0047, 1);
-		ultracam_veio(uvd, 0x01, 0x0080, 0x0048, 1);
-		ultracam_veio(uvd, 0x01, 0x0090, 0x0049, 1);
-		ultracam_veio(uvd, 0x01, 0x00a0, 0x004a, 1);
-		ultracam_veio(uvd, 0x01, 0x00b0, 0x004b, 1);
-		ultracam_veio(uvd, 0x01, 0x00c0, 0x004c, 1);
-		ultracam_veio(uvd, 0x01, 0x00d0, 0x004d, 1);
-		ultracam_veio(uvd, 0x01, 0x00e0, 0x004e, 1);
-		ultracam_veio(uvd, 0x01, 0x00f0, 0x004f, 1);
-		ultracam_veio(uvd, 0x01, 0x00ff, 0x0050, 1);
-		ultracam_veio(uvd, 0x01, 0x0000, 0x0056, 1);
-		ultracam_veio(uvd, 0x00, 0x0080, 0x00c1, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c2, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00ca, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
-		ultracam_veio(uvd, 0x00, 0x0080, 0x00c1, 1);
-		ultracam_veio(uvd, 0x00, 0x0004, 0x00c2, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00ca, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
-		ultracam_veio(uvd, 0x00, 0x0002, 0x00c1, 1);
-		ultracam_veio(uvd, 0x00, 0x0020, 0x00c2, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00ca, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c3, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c4, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c5, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c6, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c7, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c8, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c3, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c4, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c5, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c6, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c7, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c8, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
-		ultracam_veio(uvd, 0x00, 0x0040, 0x00c1, 1);
-		ultracam_veio(uvd, 0x00, 0x0017, 0x00c2, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00ca, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c3, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c4, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c5, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c6, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c7, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c8, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c3, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c4, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c5, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c6, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c7, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c8, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
-		ultracam_veio(uvd, 0x00, 0x00c0, 0x00c1, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c2, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00ca, 1);
-		ultracam_veio(uvd, 0x02, 0xc040, 0x0001, 1);
-		ultracam_veio(uvd, 0x01, 0x0000, 0x0008, 0);
-		ultracam_veio(uvd, 0x01, 0x0000, 0x0009, 0);
-		ultracam_veio(uvd, 0x01, 0x0000, 0x000a, 0);
-		ultracam_veio(uvd, 0x01, 0x0000, 0x000b, 0);
-		ultracam_veio(uvd, 0x01, 0x0000, 0x000c, 0);
-		ultracam_veio(uvd, 0x01, 0x0000, 0x000d, 0);
-		ultracam_veio(uvd, 0x01, 0x0000, 0x000e, 0);
-		ultracam_veio(uvd, 0x01, 0x0000, 0x000f, 0);
-		ultracam_veio(uvd, 0x01, 0x0000, 0x0010, 0);
-		ultracam_veio(uvd, 0x01, 0x000b, 0x0008, 1);
-		ultracam_veio(uvd, 0x01, 0x0034, 0x0009, 1);
-		ultracam_veio(uvd, 0x01, 0x0000, 0x000a, 1);
-		ultracam_veio(uvd, 0x01, 0x002e, 0x000b, 1);
-		ultracam_veio(uvd, 0x01, 0x00d6, 0x000c, 1);
-		ultracam_veio(uvd, 0x01, 0x00fc, 0x000d, 1);
-		ultracam_veio(uvd, 0x01, 0x00f1, 0x000e, 1);
-		ultracam_veio(uvd, 0x01, 0x00da, 0x000f, 1);
-		ultracam_veio(uvd, 0x01, 0x0036, 0x0010, 1);
-		ultracam_veio(uvd, 0x01, 0x0000, 0x0001, 0);
-		ultracam_veio(uvd, 0x01, 0x0064, 0x0001, 1);
-		ultracam_veio(uvd, 0x01, 0x0059, 0x0051, 1);
-		ultracam_veio(uvd, 0x01, 0x003f, 0x0052, 1);
-		ultracam_veio(uvd, 0x01, 0x0094, 0x0053, 1);
-		ultracam_veio(uvd, 0x01, 0x00ff, 0x0011, 1);
-		ultracam_veio(uvd, 0x01, 0x0003, 0x0012, 1);
-		ultracam_veio(uvd, 0x01, 0x00f7, 0x0013, 1);
-		ultracam_veio(uvd, 0x00, 0x0009, 0x0011, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x0001, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x0000, 1);
-		ultracam_veio(uvd, 0x00, 0x0020, 0x00c1, 1);
-		ultracam_veio(uvd, 0x00, 0x0010, 0x00c2, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00ca, 1);
-		ultracam_alternateSetting(uvd, 0x04);
-		ultracam_veio(uvd, 0x02, 0x0000, 0x0001, 1);
-		ultracam_veio(uvd, 0x02, 0x0000, 0x0001, 1);
-		ultracam_veio(uvd, 0x02, 0x0000, 0x0006, 1);
-		ultracam_veio(uvd, 0x02, 0x9000, 0x0007, 1);
-		ultracam_veio(uvd, 0x02, 0x0042, 0x0001, 1);
-		ultracam_veio(uvd, 0x02, 0x0000, 0x000b, 0);
-		ultracam_resetPipe(uvd);
-		ULTRACAM_T(uvd)->initialized = (setup_ok != 0);
-	}
-	return setup_ok;
-}
-
-static void ultracam_configure_video(struct uvd *uvd)
-{
-	if (uvd == NULL)
-		return;
-
-	RESTRICT_TO_RANGE(init_brightness, 0, 255);
-	RESTRICT_TO_RANGE(init_contrast, 0, 255);
-	RESTRICT_TO_RANGE(init_color, 0, 255);
-	RESTRICT_TO_RANGE(init_hue, 0, 255);
-	RESTRICT_TO_RANGE(hue_correction, 0, 255);
-
-	memset(&uvd->vpic, 0, sizeof(uvd->vpic));
-	memset(&uvd->vpic_old, 0x55, sizeof(uvd->vpic_old));
-
-	uvd->vpic.colour = init_color << 8;
-	uvd->vpic.hue = init_hue << 8;
-	uvd->vpic.brightness = init_brightness << 8;
-	uvd->vpic.contrast = init_contrast << 8;
-	uvd->vpic.whiteness = 105 << 8; /* This one isn't used */
-	uvd->vpic.depth = 24;
-	uvd->vpic.palette = VIDEO_PALETTE_RGB24;
-
-	memset(&uvd->vcap, 0, sizeof(uvd->vcap));
-	strcpy(uvd->vcap.name, "IBM Ultra Camera");
-	uvd->vcap.type = VID_TYPE_CAPTURE;
-	uvd->vcap.channels = 1;
-	uvd->vcap.audios = 0;
-	uvd->vcap.maxwidth = VIDEOSIZE_X(uvd->canvas);
-	uvd->vcap.maxheight = VIDEOSIZE_Y(uvd->canvas);
-	uvd->vcap.minwidth = min_canvasWidth;
-	uvd->vcap.minheight = min_canvasHeight;
-
-	memset(&uvd->vchan, 0, sizeof(uvd->vchan));
-	uvd->vchan.flags = 0;
-	uvd->vchan.tuners = 0;
-	uvd->vchan.channel = 0;
-	uvd->vchan.type = VIDEO_TYPE_CAMERA;
-	strcpy(uvd->vchan.name, "Camera");
-}
-
-/*
- * ultracam_probe()
- *
- * This procedure queries device descriptor and accepts the interface
- * if it looks like our camera.
- *
- * History:
- * 12-Nov-2000 Reworked to comply with new probe() signature.
- * 23-Jan-2001 Added compatibility with 2.2.x kernels.
- */
-static int ultracam_probe(struct usb_interface *intf, const struct usb_device_id *devid)
-{
-	struct usb_device *dev = interface_to_usbdev(intf);
-	struct uvd *uvd = NULL;
-	int ix, i, nas;
-	int actInterface=-1, inactInterface=-1, maxPS=0;
-	unsigned char video_ep = 0;
-
-	if (debug >= 1)
-		dev_info(&intf->dev, "ultracam_probe\n");
-
-	/* We don't handle multi-config cameras */
-	if (dev->descriptor.bNumConfigurations != 1)
-		return -ENODEV;
-
-	dev_info(&intf->dev, "IBM Ultra camera found (rev. 0x%04x)\n",
-		 le16_to_cpu(dev->descriptor.bcdDevice));
-
-	/* Validate found interface: must have one ISO endpoint */
-	nas = intf->num_altsetting;
-	if (debug > 0)
-		dev_info(&intf->dev, "Number of alternate settings=%d.\n",
-			 nas);
-	if (nas < 8) {
-		err("Too few alternate settings for this camera!");
-		return -ENODEV;
-	}
-	/* Validate all alternate settings */
-	for (ix=0; ix < nas; ix++) {
-		const struct usb_host_interface *interface;
-		const struct usb_endpoint_descriptor *endpoint;
-
-		interface = &intf->altsetting[ix];
-		i = interface->desc.bAlternateSetting;
-		if (interface->desc.bNumEndpoints != 1) {
-			err("Interface %d. has %u. endpoints!",
-			    interface->desc.bInterfaceNumber,
-			    (unsigned)(interface->desc.bNumEndpoints));
-			return -ENODEV;
-		}
-		endpoint = &interface->endpoint[0].desc;
-		if (video_ep == 0)
-			video_ep = endpoint->bEndpointAddress;
-		else if (video_ep != endpoint->bEndpointAddress) {
-			err("Alternate settings have different endpoint addresses!");
-			return -ENODEV;
-		}
-		if (!usb_endpoint_xfer_isoc(endpoint)) {
-			err("Interface %d. has non-ISO endpoint!",
-			    interface->desc.bInterfaceNumber);
-			return -ENODEV;
-		}
-		if (usb_endpoint_dir_out(endpoint)) {
-			err("Interface %d. has ISO OUT endpoint!",
-			    interface->desc.bInterfaceNumber);
-			return -ENODEV;
-		}
-		if (le16_to_cpu(endpoint->wMaxPacketSize) == 0) {
-			if (inactInterface < 0)
-				inactInterface = i;
-			else {
-				err("More than one inactive alt. setting!");
-				return -ENODEV;
-			}
-		} else {
-			if (actInterface < 0) {
-				actInterface = i;
-				maxPS = le16_to_cpu(endpoint->wMaxPacketSize);
-				if (debug > 0)
-					dev_info(&intf->dev,
-						 "Active setting=%d. "
-						 "maxPS=%d.\n", i, maxPS);
-			} else {
-				/* Got another active alt. setting */
-				if (maxPS < le16_to_cpu(endpoint->wMaxPacketSize)) {
-					/* This one is better! */
-					actInterface = i;
-					maxPS = le16_to_cpu(endpoint->wMaxPacketSize);
-					if (debug > 0) {
-						dev_info(&intf->dev,
-							 "Even better ctive "
-							 "setting=%d. "
-							 "maxPS=%d.\n",
-							 i, maxPS);
-					}
-				}
-			}
-		}
-	}
-	if ((maxPS <= 0) || (actInterface < 0) || (inactInterface < 0)) {
-		err("Failed to recognize the camera!");
-		return -ENODEV;
-	}
-
-	uvd = usbvideo_AllocateDevice(cams);
-	if (uvd != NULL) {
-		/* Here uvd is a fully allocated uvd object */
-		uvd->flags = flags;
-		uvd->debug = debug;
-		uvd->dev = dev;
-		uvd->iface = intf->altsetting->desc.bInterfaceNumber;
-		uvd->ifaceAltInactive = inactInterface;
-		uvd->ifaceAltActive = actInterface;
-		uvd->video_endp = video_ep;
-		uvd->iso_packet_len = maxPS;
-		uvd->paletteBits = 1L << VIDEO_PALETTE_RGB24;
-		uvd->defaultPalette = VIDEO_PALETTE_RGB24;
-		uvd->canvas = VIDEOSIZE(640, 480);	/* FIXME */
-		uvd->videosize = uvd->canvas; /* ultracam_size_to_videosize(size);*/
-
-		/* Initialize ibmcam-specific data */
-		assert(ULTRACAM_T(uvd) != NULL);
-		ULTRACAM_T(uvd)->camera_model = 0; /* Not used yet */
-		ULTRACAM_T(uvd)->initialized = 0;
-
-		ultracam_configure_video(uvd);
-
-		i = usbvideo_RegisterVideoDevice(uvd);
-		if (i != 0) {
-			err("usbvideo_RegisterVideoDevice() failed.");
-			uvd = NULL;
-		}
-	}
-
-	if (uvd) {
-		usb_set_intfdata (intf, uvd);
-		return 0;
-	}
-	return -EIO;
-}
-
-
-static struct usb_device_id id_table[] = {
-	{ USB_DEVICE(ULTRACAM_VENDOR_ID, ULTRACAM_PRODUCT_ID) },
-	{ }  /* Terminating entry */
-};
-
-/*
- * ultracam_init()
- *
- * This code is run to initialize the driver.
- */
-static int __init ultracam_init(void)
-{
-	struct usbvideo_cb cbTbl;
-	memset(&cbTbl, 0, sizeof(cbTbl));
-	cbTbl.probe = ultracam_probe;
-	cbTbl.setupOnOpen = ultracam_setup_on_open;
-	cbTbl.videoStart = ultracam_video_start;
-	cbTbl.videoStop = ultracam_video_stop;
-	cbTbl.processData = ultracam_ProcessIsocData;
-	cbTbl.postProcess = usbvideo_DeinterlaceFrame;
-	cbTbl.adjustPicture = ultracam_adjust_picture;
-	cbTbl.getFPS = ultracam_calculate_fps;
-	return usbvideo_register(
-		&cams,
-		MAX_CAMERAS,
-		sizeof(ultracam_t),
-		"ultracam",
-		&cbTbl,
-		THIS_MODULE,
-		id_table);
-}
-
-static void __exit ultracam_cleanup(void)
-{
-	usbvideo_Deregister(&cams);
-}
-
-MODULE_DEVICE_TABLE(usb, id_table);
-MODULE_LICENSE("GPL");
-
-module_init(ultracam_init);
-module_exit(ultracam_cleanup);
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/usbvideo/usbvideo.c linux-libre-2.6.38-gnu1/drivers/media/video/usbvideo/usbvideo.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/usbvideo/usbvideo.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/usbvideo/usbvideo.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,2230 +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, 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/sched.h>
-#include <linux/list.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/mm.h>
-#include <linux/vmalloc.h>
-#include <linux/init.h>
-#include <linux/spinlock.h>
-
-#include <asm/io.h>
-
-#include "usbvideo.h"
-
-#if defined(MAP_NR)
-#define	virt_to_page(v)	MAP_NR(v)	/* Kernels 2.2.x */
-#endif
-
-static int video_nr = -1;
-module_param(video_nr, int, 0);
-
-/*
- * Local prototypes.
- */
-static void usbvideo_Disconnect(struct usb_interface *intf);
-static void usbvideo_CameraRelease(struct uvd *uvd);
-
-static long usbvideo_v4l_ioctl(struct file *file,
-			      unsigned int cmd, unsigned long arg);
-static int usbvideo_v4l_mmap(struct file *file, struct vm_area_struct *vma);
-static int usbvideo_v4l_open(struct file *file);
-static ssize_t usbvideo_v4l_read(struct file *file, char __user *buf,
-			     size_t count, loff_t *ppos);
-static int usbvideo_v4l_close(struct file *file);
-
-static int usbvideo_StartDataPump(struct uvd *uvd);
-static void usbvideo_StopDataPump(struct uvd *uvd);
-static int usbvideo_GetFrame(struct uvd *uvd, int frameNum);
-static int usbvideo_NewFrame(struct uvd *uvd, int framenum);
-static void usbvideo_SoftwareContrastAdjustment(struct uvd *uvd,
-						struct usbvideo_frame *frame);
-
-/*******************************/
-/* Memory management functions */
-/*******************************/
-static void *usbvideo_rvmalloc(unsigned long size)
-{
-	void *mem;
-	unsigned long adr;
-
-	size = PAGE_ALIGN(size);
-	mem = vmalloc_32(size);
-	if (!mem)
-		return NULL;
-
-	memset(mem, 0, size); /* Clear the ram out, no junk to the user */
-	adr = (unsigned long) mem;
-	while (size > 0) {
-		SetPageReserved(vmalloc_to_page((void *)adr));
-		adr += PAGE_SIZE;
-		size -= PAGE_SIZE;
-	}
-
-	return mem;
-}
-
-static void usbvideo_rvfree(void *mem, unsigned long size)
-{
-	unsigned long adr;
-
-	if (!mem)
-		return;
-
-	adr = (unsigned long) mem;
-	while ((long) size > 0) {
-		ClearPageReserved(vmalloc_to_page((void *)adr));
-		adr += PAGE_SIZE;
-		size -= PAGE_SIZE;
-	}
-	vfree(mem);
-}
-
-static void RingQueue_Initialize(struct RingQueue *rq)
-{
-	assert(rq != NULL);
-	init_waitqueue_head(&rq->wqh);
-}
-
-static void RingQueue_Allocate(struct RingQueue *rq, int rqLen)
-{
-	/* Make sure the requested size is a power of 2 and
-	   round up if necessary. This allows index wrapping
-	   using masks rather than modulo */
-
-	int i = 1;
-	assert(rq != NULL);
-	assert(rqLen > 0);
-
-	while(rqLen >> i)
-		i++;
-	if(rqLen != 1 << (i-1))
-		rqLen = 1 << i;
-
-	rq->length = rqLen;
-	rq->ri = rq->wi = 0;
-	rq->queue = usbvideo_rvmalloc(rq->length);
-	assert(rq->queue != NULL);
-}
-
-static int RingQueue_IsAllocated(const struct RingQueue *rq)
-{
-	if (rq == NULL)
-		return 0;
-	return (rq->queue != NULL) && (rq->length > 0);
-}
-
-static void RingQueue_Free(struct RingQueue *rq)
-{
-	assert(rq != NULL);
-	if (RingQueue_IsAllocated(rq)) {
-		usbvideo_rvfree(rq->queue, rq->length);
-		rq->queue = NULL;
-		rq->length = 0;
-	}
-}
-
-int RingQueue_Dequeue(struct RingQueue *rq, unsigned char *dst, int len)
-{
-	int rql, toread;
-
-	assert(rq != NULL);
-	assert(dst != NULL);
-
-	rql = RingQueue_GetLength(rq);
-	if(!rql)
-		return 0;
-
-	/* Clip requested length to available data */
-	if(len > rql)
-		len = rql;
-
-	toread = len;
-	if(rq->ri > rq->wi) {
-		/* Read data from tail */
-		int read = (toread < (rq->length - rq->ri)) ? toread : rq->length - rq->ri;
-		memcpy(dst, rq->queue + rq->ri, read);
-		toread -= read;
-		dst += read;
-		rq->ri = (rq->ri + read) & (rq->length-1);
-	}
-	if(toread) {
-		/* Read data from head */
-		memcpy(dst, rq->queue + rq->ri, toread);
-		rq->ri = (rq->ri + toread) & (rq->length-1);
-	}
-	return len;
-}
-
-EXPORT_SYMBOL(RingQueue_Dequeue);
-
-int RingQueue_Enqueue(struct RingQueue *rq, const unsigned char *cdata, int n)
-{
-	int enqueued = 0;
-
-	assert(rq != NULL);
-	assert(cdata != NULL);
-	assert(rq->length > 0);
-	while (n > 0) {
-		int m, q_avail;
-
-		/* Calculate the largest chunk that fits the tail of the ring */
-		q_avail = rq->length - rq->wi;
-		if (q_avail <= 0) {
-			rq->wi = 0;
-			q_avail = rq->length;
-		}
-		m = n;
-		assert(q_avail > 0);
-		if (m > q_avail)
-			m = q_avail;
-
-		memcpy(rq->queue + rq->wi, cdata, m);
-		RING_QUEUE_ADVANCE_INDEX(rq, wi, m);
-		cdata += m;
-		enqueued += m;
-		n -= m;
-	}
-	return enqueued;
-}
-
-EXPORT_SYMBOL(RingQueue_Enqueue);
-
-static void RingQueue_InterruptibleSleepOn(struct RingQueue *rq)
-{
-	assert(rq != NULL);
-	interruptible_sleep_on(&rq->wqh);
-}
-
-void RingQueue_WakeUpInterruptible(struct RingQueue *rq)
-{
-	assert(rq != NULL);
-	if (waitqueue_active(&rq->wqh))
-		wake_up_interruptible(&rq->wqh);
-}
-
-EXPORT_SYMBOL(RingQueue_WakeUpInterruptible);
-
-void RingQueue_Flush(struct RingQueue *rq)
-{
-	assert(rq != NULL);
-	rq->ri = 0;
-	rq->wi = 0;
-}
-
-EXPORT_SYMBOL(RingQueue_Flush);
-
-
-/*
- * usbvideo_VideosizeToString()
- *
- * This procedure converts given videosize value to readable string.
- *
- * History:
- * 07-Aug-2000 Created.
- * 19-Oct-2000 Reworked for usbvideo module.
- */
-static void usbvideo_VideosizeToString(char *buf, int bufLen, videosize_t vs)
-{
-	char tmp[40];
-	int n;
-
-	n = 1 + sprintf(tmp, "%ldx%ld", VIDEOSIZE_X(vs), VIDEOSIZE_Y(vs));
-	assert(n < sizeof(tmp));
-	if ((buf == NULL) || (bufLen < n))
-		err("usbvideo_VideosizeToString: buffer is too small.");
-	else
-		memmove(buf, tmp, n);
-}
-
-/*
- * usbvideo_OverlayChar()
- *
- * History:
- * 01-Feb-2000 Created.
- */
-static void usbvideo_OverlayChar(struct uvd *uvd, struct usbvideo_frame *frame,
-				 int x, int y, int ch)
-{
-	static const unsigned short digits[16] = {
-		0xF6DE, /* 0 */
-		0x2492, /* 1 */
-		0xE7CE, /* 2 */
-		0xE79E, /* 3 */
-		0xB792, /* 4 */
-		0xF39E, /* 5 */
-		0xF3DE, /* 6 */
-		0xF492, /* 7 */
-		0xF7DE, /* 8 */
-		0xF79E, /* 9 */
-		0x77DA, /* a */
-		0xD75C, /* b */
-		0xF24E, /* c */
-		0xD6DC, /* d */
-		0xF34E, /* e */
-		0xF348  /* f */
-	};
-	unsigned short digit;
-	int ix, iy;
-	int value;
-
-	if ((uvd == NULL) || (frame == NULL))
-		return;
-
-	value = hex_to_bin(ch);
-	if (value < 0)
-		return;
-	digit = digits[value];
-
-	for (iy=0; iy < 5; iy++) {
-		for (ix=0; ix < 3; ix++) {
-			if (digit & 0x8000) {
-				if (uvd->paletteBits & (1L << VIDEO_PALETTE_RGB24)) {
-/* TODO */				RGB24_PUTPIXEL(frame, x+ix, y+iy, 0xFF, 0xFF, 0xFF);
-				}
-			}
-			digit = digit << 1;
-		}
-	}
-}
-
-/*
- * usbvideo_OverlayString()
- *
- * History:
- * 01-Feb-2000 Created.
- */
-static void usbvideo_OverlayString(struct uvd *uvd, struct usbvideo_frame *frame,
-				   int x, int y, const char *str)
-{
-	while (*str) {
-		usbvideo_OverlayChar(uvd, frame, x, y, *str);
-		str++;
-		x += 4; /* 3 pixels character + 1 space */
-	}
-}
-
-/*
- * usbvideo_OverlayStats()
- *
- * Overlays important debugging information.
- *
- * History:
- * 01-Feb-2000 Created.
- */
-static void usbvideo_OverlayStats(struct uvd *uvd, struct usbvideo_frame *frame)
-{
-	const int y_diff = 8;
-	char tmp[16];
-	int x = 10, y=10;
-	long i, j, barLength;
-	const int qi_x1 = 60, qi_y1 = 10;
-	const int qi_x2 = VIDEOSIZE_X(frame->request) - 10, qi_h = 10;
-
-	/* Call the user callback, see if we may proceed after that */
-	if (VALID_CALLBACK(uvd, overlayHook)) {
-		if (GET_CALLBACK(uvd, overlayHook)(uvd, frame) < 0)
-			return;
-	}
-
-	/*
-	 * We draw a (mostly) hollow rectangle with qi_xxx coordinates.
-	 * Left edge symbolizes the queue index 0; right edge symbolizes
-	 * the full capacity of the queue.
-	 */
-	barLength = qi_x2 - qi_x1 - 2;
-	if ((barLength > 10) && (uvd->paletteBits & (1L << VIDEO_PALETTE_RGB24))) {
-/* TODO */	long u_lo, u_hi, q_used;
-		long m_ri, m_wi, m_lo, m_hi;
-
-		/*
-		 * Determine fill zones (used areas of the queue):
-		 * 0 xxxxxxx u_lo ...... uvd->dp.ri xxxxxxxx u_hi ..... uvd->dp.length
-		 *
-		 * if u_lo < 0 then there is no first filler.
-		 */
-
-		q_used = RingQueue_GetLength(&uvd->dp);
-		if ((uvd->dp.ri + q_used) >= uvd->dp.length) {
-			u_hi = uvd->dp.length;
-			u_lo = (q_used + uvd->dp.ri) & (uvd->dp.length-1);
-		} else {
-			u_hi = (q_used + uvd->dp.ri);
-			u_lo = -1;
-		}
-
-		/* Convert byte indices into screen units */
-		m_ri = qi_x1 + ((barLength * uvd->dp.ri) / uvd->dp.length);
-		m_wi = qi_x1 + ((barLength * uvd->dp.wi) / uvd->dp.length);
-		m_lo = (u_lo > 0) ? (qi_x1 + ((barLength * u_lo) / uvd->dp.length)) : -1;
-		m_hi = qi_x1 + ((barLength * u_hi) / uvd->dp.length);
-
-		for (j=qi_y1; j < (qi_y1 + qi_h); j++) {
-			for (i=qi_x1; i < qi_x2; i++) {
-				/* Draw border lines */
-				if ((j == qi_y1) || (j == (qi_y1 + qi_h - 1)) ||
-				    (i == qi_x1) || (i == (qi_x2 - 1))) {
-					RGB24_PUTPIXEL(frame, i, j, 0xFF, 0xFF, 0xFF);
-					continue;
-				}
-				/* For all other points the Y coordinate does not matter */
-				if ((i >= m_ri) && (i <= (m_ri + 3))) {
-					RGB24_PUTPIXEL(frame, i, j, 0x00, 0xFF, 0x00);
-				} else if ((i >= m_wi) && (i <= (m_wi + 3))) {
-					RGB24_PUTPIXEL(frame, i, j, 0xFF, 0x00, 0x00);
-				} else if ((i < m_lo) || ((i > m_ri) && (i < m_hi)))
-					RGB24_PUTPIXEL(frame, i, j, 0x00, 0x00, 0xFF);
-			}
-		}
-	}
-
-	sprintf(tmp, "%8lx", uvd->stats.frame_num);
-	usbvideo_OverlayString(uvd, frame, x, y, tmp);
-	y += y_diff;
-
-	sprintf(tmp, "%8lx", uvd->stats.urb_count);
-	usbvideo_OverlayString(uvd, frame, x, y, tmp);
-	y += y_diff;
-
-	sprintf(tmp, "%8lx", uvd->stats.urb_length);
-	usbvideo_OverlayString(uvd, frame, x, y, tmp);
-	y += y_diff;
-
-	sprintf(tmp, "%8lx", uvd->stats.data_count);
-	usbvideo_OverlayString(uvd, frame, x, y, tmp);
-	y += y_diff;
-
-	sprintf(tmp, "%8lx", uvd->stats.header_count);
-	usbvideo_OverlayString(uvd, frame, x, y, tmp);
-	y += y_diff;
-
-	sprintf(tmp, "%8lx", uvd->stats.iso_skip_count);
-	usbvideo_OverlayString(uvd, frame, x, y, tmp);
-	y += y_diff;
-
-	sprintf(tmp, "%8lx", uvd->stats.iso_err_count);
-	usbvideo_OverlayString(uvd, frame, x, y, tmp);
-	y += y_diff;
-
-	sprintf(tmp, "%8x", uvd->vpic.colour);
-	usbvideo_OverlayString(uvd, frame, x, y, tmp);
-	y += y_diff;
-
-	sprintf(tmp, "%8x", uvd->vpic.hue);
-	usbvideo_OverlayString(uvd, frame, x, y, tmp);
-	y += y_diff;
-
-	sprintf(tmp, "%8x", uvd->vpic.brightness >> 8);
-	usbvideo_OverlayString(uvd, frame, x, y, tmp);
-	y += y_diff;
-
-	sprintf(tmp, "%8x", uvd->vpic.contrast >> 12);
-	usbvideo_OverlayString(uvd, frame, x, y, tmp);
-	y += y_diff;
-
-	sprintf(tmp, "%8d", uvd->vpic.whiteness >> 8);
-	usbvideo_OverlayString(uvd, frame, x, y, tmp);
-	y += y_diff;
-}
-
-/*
- * usbvideo_ReportStatistics()
- *
- * This procedure prints packet and transfer statistics.
- *
- * History:
- * 14-Jan-2000 Corrected default multiplier.
- */
-static void usbvideo_ReportStatistics(const struct uvd *uvd)
-{
-	if ((uvd != NULL) && (uvd->stats.urb_count > 0)) {
-		unsigned long allPackets, badPackets, goodPackets, percent;
-		allPackets = uvd->stats.urb_count * CAMERA_URB_FRAMES;
-		badPackets = uvd->stats.iso_skip_count + uvd->stats.iso_err_count;
-		goodPackets = allPackets - badPackets;
-		/* Calculate percentage wisely, remember integer limits */
-		assert(allPackets != 0);
-		if (goodPackets < (((unsigned long)-1)/100))
-			percent = (100 * goodPackets) / allPackets;
-		else
-			percent = goodPackets / (allPackets / 100);
-		dev_info(&uvd->dev->dev,
-			 "Packet Statistics: Total=%lu. Empty=%lu. Usage=%lu%%\n",
-			 allPackets, badPackets, percent);
-		if (uvd->iso_packet_len > 0) {
-			unsigned long allBytes, xferBytes;
-			char multiplier = ' ';
-			allBytes = allPackets * uvd->iso_packet_len;
-			xferBytes = uvd->stats.data_count;
-			assert(allBytes != 0);
-			if (xferBytes < (((unsigned long)-1)/100))
-				percent = (100 * xferBytes) / allBytes;
-			else
-				percent = xferBytes / (allBytes / 100);
-			/* Scale xferBytes for easy reading */
-			if (xferBytes > 10*1024) {
-				xferBytes /= 1024;
-				multiplier = 'K';
-				if (xferBytes > 10*1024) {
-					xferBytes /= 1024;
-					multiplier = 'M';
-					if (xferBytes > 10*1024) {
-						xferBytes /= 1024;
-						multiplier = 'G';
-						if (xferBytes > 10*1024) {
-							xferBytes /= 1024;
-							multiplier = 'T';
-						}
-					}
-				}
-			}
-			dev_info(&uvd->dev->dev,
-				 "Transfer Statistics: Transferred=%lu%cB Usage=%lu%%\n",
-				 xferBytes, multiplier, percent);
-		}
-	}
-}
-
-/*
- * usbvideo_TestPattern()
- *
- * Procedure forms a test pattern (yellow grid on blue background).
- *
- * Parameters:
- * fullframe: if TRUE then entire frame is filled, otherwise the procedure
- *	      continues from the current scanline.
- * pmode      0: fill the frame with solid blue color (like on VCR or TV)
- *	      1: Draw a colored grid
- *
- * History:
- * 01-Feb-2000 Created.
- */
-void usbvideo_TestPattern(struct uvd *uvd, int fullframe, int pmode)
-{
-	struct usbvideo_frame *frame;
-	int num_cell = 0;
-	int scan_length = 0;
-	static int num_pass;
-
-	if (uvd == NULL) {
-		err("%s: uvd == NULL", __func__);
-		return;
-	}
-	if ((uvd->curframe < 0) || (uvd->curframe >= USBVIDEO_NUMFRAMES)) {
-		err("%s: uvd->curframe=%d.", __func__, uvd->curframe);
-		return;
-	}
-
-	/* Grab the current frame */
-	frame = &uvd->frame[uvd->curframe];
-
-	/* Optionally start at the beginning */
-	if (fullframe) {
-		frame->curline = 0;
-		frame->seqRead_Length = 0;
-	}
-#if 0
-	{	/* For debugging purposes only */
-		char tmp[20];
-		usbvideo_VideosizeToString(tmp, sizeof(tmp), frame->request);
-		dev_info(&uvd->dev->dev, "testpattern: frame=%s\n", tmp);
-	}
-#endif
-	/* Form every scan line */
-	for (; frame->curline < VIDEOSIZE_Y(frame->request); frame->curline++) {
-		int i;
-		unsigned char *f = frame->data +
-			(VIDEOSIZE_X(frame->request) * V4L_BYTES_PER_PIXEL * frame->curline);
-		for (i=0; i < VIDEOSIZE_X(frame->request); i++) {
-			unsigned char cb=0x80;
-			unsigned char cg = 0;
-			unsigned char cr = 0;
-
-			if (pmode == 1) {
-				if (frame->curline % 32 == 0)
-					cb = 0, cg = cr = 0xFF;
-				else if (i % 32 == 0) {
-					if (frame->curline % 32 == 1)
-						num_cell++;
-					cb = 0, cg = cr = 0xFF;
-				} else {
-					cb = ((num_cell*7) + num_pass) & 0xFF;
-					cg = ((num_cell*5) + num_pass*2) & 0xFF;
-					cr = ((num_cell*3) + num_pass*3) & 0xFF;
-				}
-			} else {
-				/* Just the blue screen */
-			}
-
-			*f++ = cb;
-			*f++ = cg;
-			*f++ = cr;
-			scan_length += 3;
-		}
-	}
-
-	frame->frameState = FrameState_Done;
-	frame->seqRead_Length += scan_length;
-	++num_pass;
-
-	/* We do this unconditionally, regardless of FLAGS_OVERLAY_STATS */
-	usbvideo_OverlayStats(uvd, frame);
-}
-
-EXPORT_SYMBOL(usbvideo_TestPattern);
-
-
-#ifdef DEBUG
-/*
- * usbvideo_HexDump()
- *
- * A debugging tool. Prints hex dumps.
- *
- * History:
- * 29-Jul-2000 Added printing of offsets.
- */
-void usbvideo_HexDump(const unsigned char *data, int len)
-{
-	const int bytes_per_line = 32;
-	char tmp[128]; /* 32*3 + 5 */
-	int i, k;
-
-	for (i=k=0; len > 0; i++, len--) {
-		if (i > 0 && ((i % bytes_per_line) == 0)) {
-			printk("%s\n", tmp);
-			k=0;
-		}
-		if ((i % bytes_per_line) == 0)
-			k += sprintf(&tmp[k], "%04x: ", i);
-		k += sprintf(&tmp[k], "%02x ", data[i]);
-	}
-	if (k > 0)
-		printk("%s\n", tmp);
-}
-
-EXPORT_SYMBOL(usbvideo_HexDump);
-
-#endif
-
-/* ******************************************************************** */
-
-/* XXX: this piece of crap really wants some error handling.. */
-static int usbvideo_ClientIncModCount(struct uvd *uvd)
-{
-	if (uvd == NULL) {
-		err("%s: uvd == NULL", __func__);
-		return -EINVAL;
-	}
-	if (uvd->handle == NULL) {
-		err("%s: uvd->handle == NULL", __func__);
-		return -EINVAL;
-	}
-	if (!try_module_get(uvd->handle->md_module)) {
-		err("%s: try_module_get() == 0", __func__);
-		return -ENODEV;
-	}
-	return 0;
-}
-
-static void usbvideo_ClientDecModCount(struct uvd *uvd)
-{
-	if (uvd == NULL) {
-		err("%s: uvd == NULL", __func__);
-		return;
-	}
-	if (uvd->handle == NULL) {
-		err("%s: uvd->handle == NULL", __func__);
-		return;
-	}
-	if (uvd->handle->md_module == NULL) {
-		err("%s: uvd->handle->md_module == NULL", __func__);
-		return;
-	}
-	module_put(uvd->handle->md_module);
-}
-
-int usbvideo_register(
-	struct usbvideo **pCams,
-	const int num_cams,
-	const int num_extra,
-	const char *driverName,
-	const struct usbvideo_cb *cbTbl,
-	struct module *md,
-	const struct usb_device_id *id_table)
-{
-	struct usbvideo *cams;
-	int i, base_size, result;
-
-	/* Check parameters for sanity */
-	if ((num_cams <= 0) || (pCams == NULL) || (cbTbl == NULL)) {
-		err("%s: Illegal call", __func__);
-		return -EINVAL;
-	}
-
-	/* Check registration callback - must be set! */
-	if (cbTbl->probe == NULL) {
-		err("%s: probe() is required!", __func__);
-		return -EINVAL;
-	}
-
-	base_size = num_cams * sizeof(struct uvd) + sizeof(struct usbvideo);
-	cams = kzalloc(base_size, GFP_KERNEL);
-	if (cams == NULL) {
-		err("Failed to allocate %d. bytes for usbvideo struct", base_size);
-		return -ENOMEM;
-	}
-	dbg("%s: Allocated $%p (%d. bytes) for %d. cameras",
-	    __func__, cams, base_size, num_cams);
-
-	/* Copy callbacks, apply defaults for those that are not set */
-	memmove(&cams->cb, cbTbl, sizeof(cams->cb));
-	if (cams->cb.getFrame == NULL)
-		cams->cb.getFrame = usbvideo_GetFrame;
-	if (cams->cb.disconnect == NULL)
-		cams->cb.disconnect = usbvideo_Disconnect;
-	if (cams->cb.startDataPump == NULL)
-		cams->cb.startDataPump = usbvideo_StartDataPump;
-	if (cams->cb.stopDataPump == NULL)
-		cams->cb.stopDataPump = usbvideo_StopDataPump;
-
-	cams->num_cameras = num_cams;
-	cams->cam = (struct uvd *) &cams[1];
-	cams->md_module = md;
-	mutex_init(&cams->lock);	/* to 1 == available */
-
-	for (i = 0; i < num_cams; i++) {
-		struct uvd *up = &cams->cam[i];
-
-		up->handle = cams;
-
-		/* Allocate user_data separately because of kmalloc's limits */
-		if (num_extra > 0) {
-			up->user_size = num_cams * num_extra;
-			up->user_data = kmalloc(up->user_size, GFP_KERNEL);
-			if (up->user_data == NULL) {
-				err("%s: Failed to allocate user_data (%d. bytes)",
-				    __func__, up->user_size);
-				while (i) {
-					up = &cams->cam[--i];
-					kfree(up->user_data);
-				}
-				kfree(cams);
-				return -ENOMEM;
-			}
-			dbg("%s: Allocated cams[%d].user_data=$%p (%d. bytes)",
-			     __func__, i, up->user_data, up->user_size);
-		}
-	}
-
-	/*
-	 * Register ourselves with USB stack.
-	 */
-	strcpy(cams->drvName, (driverName != NULL) ? driverName : "Unknown");
-	cams->usbdrv.name = cams->drvName;
-	cams->usbdrv.probe = cams->cb.probe;
-	cams->usbdrv.disconnect = cams->cb.disconnect;
-	cams->usbdrv.id_table = id_table;
-
-	/*
-	 * Update global handle to usbvideo. This is very important
-	 * because probe() can be called before usb_register() returns.
-	 * If the handle is not yet updated then the probe() will fail.
-	 */
-	*pCams = cams;
-	result = usb_register(&cams->usbdrv);
-	if (result) {
-		for (i = 0; i < num_cams; i++) {
-			struct uvd *up = &cams->cam[i];
-			kfree(up->user_data);
-		}
-		kfree(cams);
-	}
-
-	return result;
-}
-
-EXPORT_SYMBOL(usbvideo_register);
-
-/*
- * usbvideo_Deregister()
- *
- * Procedure frees all usbvideo and user data structures. Be warned that
- * if you had some dynamically allocated components in ->user field then
- * you should free them before calling here.
- */
-void usbvideo_Deregister(struct usbvideo **pCams)
-{
-	struct usbvideo *cams;
-	int i;
-
-	if (pCams == NULL) {
-		err("%s: pCams == NULL", __func__);
-		return;
-	}
-	cams = *pCams;
-	if (cams == NULL) {
-		err("%s: cams == NULL", __func__);
-		return;
-	}
-
-	dbg("%s: Deregistering %s driver.", __func__, cams->drvName);
-	usb_deregister(&cams->usbdrv);
-
-	dbg("%s: Deallocating cams=$%p (%d. cameras)", __func__, cams, cams->num_cameras);
-	for (i=0; i < cams->num_cameras; i++) {
-		struct uvd *up = &cams->cam[i];
-		int warning = 0;
-
-		if (up->user_data != NULL) {
-			if (up->user_size <= 0)
-				++warning;
-		} else {
-			if (up->user_size > 0)
-				++warning;
-		}
-		if (warning) {
-			err("%s: Warning: user_data=$%p user_size=%d.",
-			    __func__, up->user_data, up->user_size);
-		} else {
-			dbg("%s: Freeing %d. $%p->user_data=$%p",
-			    __func__, i, up, up->user_data);
-			kfree(up->user_data);
-		}
-	}
-	/* Whole array was allocated in one chunk */
-	dbg("%s: Freed %d uvd structures",
-	    __func__, cams->num_cameras);
-	kfree(cams);
-	*pCams = NULL;
-}
-
-EXPORT_SYMBOL(usbvideo_Deregister);
-
-/*
- * usbvideo_Disconnect()
- *
- * This procedure stops all driver activity. Deallocation of
- * the interface-private structure (pointed by 'ptr') is done now
- * (if we don't have any open files) or later, when those files
- * are closed. After that driver should be removable.
- *
- * This code handles surprise removal. The uvd->user is a counter which
- * increments on open() and decrements on close(). If we see here that
- * this counter is not 0 then we have a client who still has us opened.
- * We set uvd->remove_pending flag as early as possible, and after that
- * all access to the camera will gracefully fail. These failures should
- * prompt client to (eventually) close the video device, and then - in
- * usbvideo_v4l_close() - we decrement uvd->uvd_used and usage counter.
- *
- * History:
- * 22-Jan-2000 Added polling of MOD_IN_USE to delay removal until all users gone.
- * 27-Jan-2000 Reworked to allow pending disconnects; see xxx_close()
- * 24-May-2000 Corrected to prevent race condition (MOD_xxx_USE_COUNT).
- * 19-Oct-2000 Moved to usbvideo module.
- */
-static void usbvideo_Disconnect(struct usb_interface *intf)
-{
-	struct uvd *uvd = usb_get_intfdata (intf);
-	int i;
-
-	if (uvd == NULL) {
-		err("%s($%p): Illegal call.", __func__, intf);
-		return;
-	}
-
-	usb_set_intfdata (intf, NULL);
-
-	usbvideo_ClientIncModCount(uvd);
-	if (uvd->debug > 0)
-		dev_info(&intf->dev, "%s(%p.)\n", __func__, intf);
-
-	mutex_lock(&uvd->lock);
-	uvd->remove_pending = 1; /* Now all ISO data will be ignored */
-
-	/* At this time we ask to cancel outstanding URBs */
-	GET_CALLBACK(uvd, stopDataPump)(uvd);
-
-	for (i=0; i < USBVIDEO_NUMSBUF; i++)
-		usb_free_urb(uvd->sbuf[i].urb);
-
-	usb_put_dev(uvd->dev);
-	uvd->dev = NULL;    	    /* USB device is no more */
-
-	video_unregister_device(&uvd->vdev);
-	if (uvd->debug > 0)
-		dev_info(&intf->dev, "%s: Video unregistered.\n", __func__);
-
-	if (uvd->user)
-		dev_info(&intf->dev, "%s: In use, disconnect pending.\n",
-			 __func__);
-	else
-		usbvideo_CameraRelease(uvd);
-	mutex_unlock(&uvd->lock);
-	dev_info(&intf->dev, "USB camera disconnected.\n");
-
-	usbvideo_ClientDecModCount(uvd);
-}
-
-/*
- * usbvideo_CameraRelease()
- *
- * This code does final release of uvd. This happens
- * after the device is disconnected -and- all clients
- * closed their files.
- *
- * History:
- * 27-Jan-2000 Created.
- */
-static void usbvideo_CameraRelease(struct uvd *uvd)
-{
-	if (uvd == NULL) {
-		err("%s: Illegal call", __func__);
-		return;
-	}
-
-	RingQueue_Free(&uvd->dp);
-	if (VALID_CALLBACK(uvd, userFree))
-		GET_CALLBACK(uvd, userFree)(uvd);
-	uvd->uvd_used = 0;	/* This is atomic, no need to take mutex */
-}
-
-/*
- * usbvideo_find_struct()
- *
- * This code searches the array of preallocated (static) structures
- * and returns index of the first one that isn't in use. Returns -1
- * if there are no free structures.
- *
- * History:
- * 27-Jan-2000 Created.
- */
-static int usbvideo_find_struct(struct usbvideo *cams)
-{
-	int u, rv = -1;
-
-	if (cams == NULL) {
-		err("No usbvideo handle?");
-		return -1;
-	}
-	mutex_lock(&cams->lock);
-	for (u = 0; u < cams->num_cameras; u++) {
-		struct uvd *uvd = &cams->cam[u];
-		if (!uvd->uvd_used) /* This one is free */
-		{
-			uvd->uvd_used = 1;	/* In use now */
-			mutex_init(&uvd->lock);	/* to 1 == available */
-			uvd->dev = NULL;
-			rv = u;
-			break;
-		}
-	}
-	mutex_unlock(&cams->lock);
-	return rv;
-}
-
-static const struct v4l2_file_operations usbvideo_fops = {
-	.owner =  THIS_MODULE,
-	.open =   usbvideo_v4l_open,
-	.release =usbvideo_v4l_close,
-	.read =   usbvideo_v4l_read,
-	.mmap =   usbvideo_v4l_mmap,
-	.ioctl =  usbvideo_v4l_ioctl,
-};
-static const struct video_device usbvideo_template = {
-	.fops =       &usbvideo_fops,
-};
-
-struct uvd *usbvideo_AllocateDevice(struct usbvideo *cams)
-{
-	int i, devnum;
-	struct uvd *uvd = NULL;
-
-	if (cams == NULL) {
-		err("No usbvideo handle?");
-		return NULL;
-	}
-
-	devnum = usbvideo_find_struct(cams);
-	if (devnum == -1) {
-		err("IBM USB camera driver: Too many devices!");
-		return NULL;
-	}
-	uvd = &cams->cam[devnum];
-	dbg("Device entry #%d. at $%p", devnum, uvd);
-
-	/* Not relying upon caller we increase module counter ourselves */
-	usbvideo_ClientIncModCount(uvd);
-
-	mutex_lock(&uvd->lock);
-	for (i=0; i < USBVIDEO_NUMSBUF; i++) {
-		uvd->sbuf[i].urb = usb_alloc_urb(FRAMES_PER_DESC, GFP_KERNEL);
-		if (uvd->sbuf[i].urb == NULL) {
-			err("usb_alloc_urb(%d.) failed.", FRAMES_PER_DESC);
-			uvd->uvd_used = 0;
-			uvd = NULL;
-			goto allocate_done;
-		}
-	}
-	uvd->user=0;
-	uvd->remove_pending = 0;
-	uvd->last_error = 0;
-	RingQueue_Initialize(&uvd->dp);
-
-	/* Initialize video device structure */
-	uvd->vdev = usbvideo_template;
-	sprintf(uvd->vdev.name, "%.20s USB Camera", cams->drvName);
-	/*
-	 * The client is free to overwrite those because we
-	 * return control to the client's probe function right now.
-	 */
-allocate_done:
-	mutex_unlock(&uvd->lock);
-	usbvideo_ClientDecModCount(uvd);
-	return uvd;
-}
-
-EXPORT_SYMBOL(usbvideo_AllocateDevice);
-
-int usbvideo_RegisterVideoDevice(struct uvd *uvd)
-{
-	char tmp1[20], tmp2[20];	/* Buffers for printing */
-
-	if (uvd == NULL) {
-		err("%s: Illegal call.", __func__);
-		return -EINVAL;
-	}
-	if (uvd->video_endp == 0) {
-		dev_info(&uvd->dev->dev,
-			 "%s: No video endpoint specified; data pump disabled.\n",
-			 __func__);
-	}
-	if (uvd->paletteBits == 0) {
-		err("%s: No palettes specified!", __func__);
-		return -EINVAL;
-	}
-	if (uvd->defaultPalette == 0) {
-		dev_info(&uvd->dev->dev, "%s: No default palette!\n",
-			 __func__);
-	}
-
-	uvd->max_frame_size = VIDEOSIZE_X(uvd->canvas) *
-		VIDEOSIZE_Y(uvd->canvas) * V4L_BYTES_PER_PIXEL;
-	usbvideo_VideosizeToString(tmp1, sizeof(tmp1), uvd->videosize);
-	usbvideo_VideosizeToString(tmp2, sizeof(tmp2), uvd->canvas);
-
-	if (uvd->debug > 0) {
-		dev_info(&uvd->dev->dev,
-			 "%s: iface=%d. endpoint=$%02x paletteBits=$%08lx\n",
-			 __func__, uvd->iface, uvd->video_endp,
-			 uvd->paletteBits);
-	}
-	if (uvd->dev == NULL) {
-		err("%s: uvd->dev == NULL", __func__);
-		return -EINVAL;
-	}
-	uvd->vdev.parent = &uvd->dev->dev;
-	uvd->vdev.release = video_device_release_empty;
-	if (video_register_device(&uvd->vdev, VFL_TYPE_GRABBER, video_nr) < 0) {
-		err("%s: video_register_device failed", __func__);
-		return -EPIPE;
-	}
-	if (uvd->debug > 1) {
-		dev_info(&uvd->dev->dev,
-			 "%s: video_register_device() successful\n", __func__);
-	}
-
-	dev_info(&uvd->dev->dev, "%s on %s: canvas=%s videosize=%s\n",
-		 (uvd->handle != NULL) ? uvd->handle->drvName : "???",
-		 video_device_node_name(&uvd->vdev), tmp2, tmp1);
-
-	usb_get_dev(uvd->dev);
-	return 0;
-}
-
-EXPORT_SYMBOL(usbvideo_RegisterVideoDevice);
-
-/* ******************************************************************** */
-
-static int usbvideo_v4l_mmap(struct file *file, struct vm_area_struct *vma)
-{
-	struct uvd *uvd = file->private_data;
-	unsigned long start = vma->vm_start;
-	unsigned long size  = vma->vm_end-vma->vm_start;
-	unsigned long page, pos;
-
-	if (!CAMERA_IS_OPERATIONAL(uvd))
-		return -EFAULT;
-
-	if (size > (((USBVIDEO_NUMFRAMES * uvd->max_frame_size) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1)))
-		return -EINVAL;
-
-	pos = (unsigned long) uvd->fbuf;
-	while (size > 0) {
-		page = vmalloc_to_pfn((void *)pos);
-		if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED))
-			return -EAGAIN;
-
-		start += PAGE_SIZE;
-		pos += PAGE_SIZE;
-		if (size > PAGE_SIZE)
-			size -= PAGE_SIZE;
-		else
-			size = 0;
-	}
-
-	return 0;
-}
-
-/*
- * usbvideo_v4l_open()
- *
- * This is part of Video 4 Linux API. The driver can be opened by one
- * client only (checks internal counter 'uvdser'). The procedure
- * then allocates buffers needed for video processing.
- *
- * History:
- * 22-Jan-2000 Rewrote, moved scratch buffer allocation here. Now the
- *             camera is also initialized here (once per connect), at
- *             expense of V4L client (it waits on open() call).
- * 27-Jan-2000 Used USBVIDEO_NUMSBUF as number of URB buffers.
- * 24-May-2000 Corrected to prevent race condition (MOD_xxx_USE_COUNT).
- */
-static int usbvideo_v4l_open(struct file *file)
-{
-	struct video_device *dev = video_devdata(file);
-	struct uvd *uvd = (struct uvd *) dev;
-	const int sb_size = FRAMES_PER_DESC * uvd->iso_packet_len;
-	int i, errCode = 0;
-
-	if (uvd->debug > 1)
-		dev_info(&uvd->dev->dev, "%s($%p)\n", __func__, dev);
-
-	if (usbvideo_ClientIncModCount(uvd) < 0)
-		return -ENODEV;
-	mutex_lock(&uvd->lock);
-
-	if (uvd->user) {
-		err("%s: Someone tried to open an already opened device!", __func__);
-		errCode = -EBUSY;
-	} else {
-		/* Clear statistics */
-		memset(&uvd->stats, 0, sizeof(uvd->stats));
-
-		/* Clean pointers so we know if we allocated something */
-		for (i=0; i < USBVIDEO_NUMSBUF; i++)
-			uvd->sbuf[i].data = NULL;
-
-		/* Allocate memory for the frame buffers */
-		uvd->fbuf_size = USBVIDEO_NUMFRAMES * uvd->max_frame_size;
-		uvd->fbuf = usbvideo_rvmalloc(uvd->fbuf_size);
-		RingQueue_Allocate(&uvd->dp, RING_QUEUE_SIZE);
-		if ((uvd->fbuf == NULL) ||
-		    (!RingQueue_IsAllocated(&uvd->dp))) {
-			err("%s: Failed to allocate fbuf or dp", __func__);
-			errCode = -ENOMEM;
-		} else {
-			/* Allocate all buffers */
-			for (i=0; i < USBVIDEO_NUMFRAMES; i++) {
-				uvd->frame[i].frameState = FrameState_Unused;
-				uvd->frame[i].data = uvd->fbuf + i*(uvd->max_frame_size);
-				/*
-				 * Set default sizes in case IOCTL (VIDIOCMCAPTURE)
-				 * is not used (using read() instead).
-				 */
-				uvd->frame[i].canvas = uvd->canvas;
-				uvd->frame[i].seqRead_Index = 0;
-			}
-			for (i=0; i < USBVIDEO_NUMSBUF; i++) {
-				uvd->sbuf[i].data = kmalloc(sb_size, GFP_KERNEL);
-				if (uvd->sbuf[i].data == NULL) {
-					errCode = -ENOMEM;
-					break;
-				}
-			}
-		}
-		if (errCode != 0) {
-			/* Have to free all that memory */
-			if (uvd->fbuf != NULL) {
-				usbvideo_rvfree(uvd->fbuf, uvd->fbuf_size);
-				uvd->fbuf = NULL;
-			}
-			RingQueue_Free(&uvd->dp);
-			for (i=0; i < USBVIDEO_NUMSBUF; i++) {
-				kfree(uvd->sbuf[i].data);
-				uvd->sbuf[i].data = NULL;
-			}
-		}
-	}
-
-	/* If so far no errors then we shall start the camera */
-	if (errCode == 0) {
-		/* Start data pump if we have valid endpoint */
-		if (uvd->video_endp != 0)
-			errCode = GET_CALLBACK(uvd, startDataPump)(uvd);
-		if (errCode == 0) {
-			if (VALID_CALLBACK(uvd, setupOnOpen)) {
-				if (uvd->debug > 1)
-					dev_info(&uvd->dev->dev,
-						 "%s: setupOnOpen callback\n",
-						 __func__);
-				errCode = GET_CALLBACK(uvd, setupOnOpen)(uvd);
-				if (errCode < 0) {
-					err("%s: setupOnOpen callback failed (%d.).",
-					    __func__, errCode);
-				} else if (uvd->debug > 1) {
-					dev_info(&uvd->dev->dev,
-						 "%s: setupOnOpen callback successful\n",
-						 __func__);
-				}
-			}
-			if (errCode == 0) {
-				uvd->settingsAdjusted = 0;
-				if (uvd->debug > 1)
-					dev_info(&uvd->dev->dev,
-						 "%s: Open succeeded.\n",
-						 __func__);
-				uvd->user++;
-				file->private_data = uvd;
-			}
-		}
-	}
-	mutex_unlock(&uvd->lock);
-	if (errCode != 0)
-		usbvideo_ClientDecModCount(uvd);
-	if (uvd->debug > 0)
-		dev_info(&uvd->dev->dev, "%s: Returning %d.\n", __func__,
-			 errCode);
-	return errCode;
-}
-
-/*
- * usbvideo_v4l_close()
- *
- * This is part of Video 4 Linux API. The procedure
- * stops streaming and deallocates all buffers that were earlier
- * allocated in usbvideo_v4l_open().
- *
- * History:
- * 22-Jan-2000 Moved scratch buffer deallocation here.
- * 27-Jan-2000 Used USBVIDEO_NUMSBUF as number of URB buffers.
- * 24-May-2000 Moved MOD_DEC_USE_COUNT outside of code that can sleep.
- */
-static int usbvideo_v4l_close(struct file *file)
-{
-	struct video_device *dev = file->private_data;
-	struct uvd *uvd = (struct uvd *) dev;
-	int i;
-
-	if (uvd->debug > 1)
-		dev_info(&uvd->dev->dev, "%s($%p)\n", __func__, dev);
-
-	mutex_lock(&uvd->lock);
-	GET_CALLBACK(uvd, stopDataPump)(uvd);
-	usbvideo_rvfree(uvd->fbuf, uvd->fbuf_size);
-	uvd->fbuf = NULL;
-	RingQueue_Free(&uvd->dp);
-
-	for (i=0; i < USBVIDEO_NUMSBUF; i++) {
-		kfree(uvd->sbuf[i].data);
-		uvd->sbuf[i].data = NULL;
-	}
-
-#if USBVIDEO_REPORT_STATS
-	usbvideo_ReportStatistics(uvd);
-#endif
-
-	uvd->user--;
-	if (uvd->remove_pending) {
-		if (uvd->debug > 0)
-			dev_info(&uvd->dev->dev, "%s: Final disconnect.\n",
-				 __func__);
-		usbvideo_CameraRelease(uvd);
-	}
-	mutex_unlock(&uvd->lock);
-	usbvideo_ClientDecModCount(uvd);
-
-	if (uvd->debug > 1)
-		dev_info(&uvd->dev->dev, "%s: Completed.\n", __func__);
-	file->private_data = NULL;
-	return 0;
-}
-
-/*
- * usbvideo_v4l_ioctl()
- *
- * This is part of Video 4 Linux API. The procedure handles ioctl() calls.
- *
- * History:
- * 22-Jan-2000 Corrected VIDIOCSPICT to reject unsupported settings.
- */
-static long usbvideo_v4l_do_ioctl(struct file *file, unsigned int cmd, void *arg)
-{
-	struct uvd *uvd = file->private_data;
-
-	if (!CAMERA_IS_OPERATIONAL(uvd))
-		return -EIO;
-
-	switch (cmd) {
-		case VIDIOCGCAP:
-		{
-			struct video_capability *b = arg;
-			*b = uvd->vcap;
-			return 0;
-		}
-		case VIDIOCGCHAN:
-		{
-			struct video_channel *v = arg;
-			*v = uvd->vchan;
-			return 0;
-		}
-		case VIDIOCSCHAN:
-		{
-			struct video_channel *v = arg;
-			if (v->channel != 0)
-				return -EINVAL;
-			return 0;
-		}
-		case VIDIOCGPICT:
-		{
-			struct video_picture *pic = arg;
-			*pic = uvd->vpic;
-			return 0;
-		}
-		case VIDIOCSPICT:
-		{
-			struct video_picture *pic = arg;
-			/*
-			 * Use temporary 'video_picture' structure to preserve our
-			 * own settings (such as color depth, palette) that we
-			 * aren't allowing everyone (V4L client) to change.
-			 */
-			uvd->vpic.brightness = pic->brightness;
-			uvd->vpic.hue = pic->hue;
-			uvd->vpic.colour = pic->colour;
-			uvd->vpic.contrast = pic->contrast;
-			uvd->settingsAdjusted = 0;	/* Will force new settings */
-			return 0;
-		}
-		case VIDIOCSWIN:
-		{
-			struct video_window *vw = arg;
-
-			if(VALID_CALLBACK(uvd, setVideoMode)) {
-				return GET_CALLBACK(uvd, setVideoMode)(uvd, vw);
-			}
-
-			if (vw->flags)
-				return -EINVAL;
-			if (vw->clipcount)
-				return -EINVAL;
-			if (vw->width != VIDEOSIZE_X(uvd->canvas))
-				return -EINVAL;
-			if (vw->height != VIDEOSIZE_Y(uvd->canvas))
-				return -EINVAL;
-
-			return 0;
-		}
-		case VIDIOCGWIN:
-		{
-			struct video_window *vw = arg;
-
-			vw->x = 0;
-			vw->y = 0;
-			vw->width = VIDEOSIZE_X(uvd->videosize);
-			vw->height = VIDEOSIZE_Y(uvd->videosize);
-			vw->chromakey = 0;
-			if (VALID_CALLBACK(uvd, getFPS))
-				vw->flags = GET_CALLBACK(uvd, getFPS)(uvd);
-			else
-				vw->flags = 10; /* FIXME: do better! */
-			return 0;
-		}
-		case VIDIOCGMBUF:
-		{
-			struct video_mbuf *vm = arg;
-			int i;
-
-			memset(vm, 0, sizeof(*vm));
-			vm->size = uvd->max_frame_size * USBVIDEO_NUMFRAMES;
-			vm->frames = USBVIDEO_NUMFRAMES;
-			for(i = 0; i < USBVIDEO_NUMFRAMES; i++)
-			  vm->offsets[i] = i * uvd->max_frame_size;
-
-			return 0;
-		}
-		case VIDIOCMCAPTURE:
-		{
-			struct video_mmap *vm = arg;
-
-			if (uvd->debug >= 1) {
-				dev_info(&uvd->dev->dev,
-					 "VIDIOCMCAPTURE: frame=%d. size=%dx%d, format=%d.\n",
-					 vm->frame, vm->width, vm->height, vm->format);
-			}
-			/*
-			 * Check if the requested size is supported. If the requestor
-			 * requests too big a frame then we may be tricked into accessing
-			 * outside of own preallocated frame buffer (in uvd->frame).
-			 * This will cause oops or a security hole. Theoretically, we
-			 * could only clamp the size down to acceptable bounds, but then
-			 * we'd need to figure out how to insert our smaller buffer into
-			 * larger caller's buffer... this is not an easy question. So we
-			 * here just flatly reject too large requests, assuming that the
-			 * caller will resubmit with smaller size. Callers should know
-			 * what size we support (returned by VIDIOCGCAP). However vidcat,
-			 * for one, does not care and allows to ask for any size.
-			 */
-			if ((vm->width > VIDEOSIZE_X(uvd->canvas)) ||
-			    (vm->height > VIDEOSIZE_Y(uvd->canvas))) {
-				if (uvd->debug > 0) {
-					dev_info(&uvd->dev->dev,
-						 "VIDIOCMCAPTURE: Size=%dx%d "
-						 "too large; allowed only up "
-						 "to %ldx%ld\n", vm->width,
-						 vm->height,
-						 VIDEOSIZE_X(uvd->canvas),
-						 VIDEOSIZE_Y(uvd->canvas));
-				}
-				return -EINVAL;
-			}
-			/* Check if the palette is supported */
-			if (((1L << vm->format) & uvd->paletteBits) == 0) {
-				if (uvd->debug > 0) {
-					dev_info(&uvd->dev->dev,
-						 "VIDIOCMCAPTURE: format=%d. "
-						 "not supported "
-						 "(paletteBits=$%08lx)\n",
-						 vm->format, uvd->paletteBits);
-				}
-				return -EINVAL;
-			}
-			if ((vm->frame < 0) || (vm->frame >= USBVIDEO_NUMFRAMES)) {
-				err("VIDIOCMCAPTURE: vm.frame=%d. !E [0-%d]", vm->frame, USBVIDEO_NUMFRAMES-1);
-				return -EINVAL;
-			}
-			if (uvd->frame[vm->frame].frameState == FrameState_Grabbing) {
-				/* Not an error - can happen */
-			}
-			uvd->frame[vm->frame].request = VIDEOSIZE(vm->width, vm->height);
-			uvd->frame[vm->frame].palette = vm->format;
-
-			/* Mark it as ready */
-			uvd->frame[vm->frame].frameState = FrameState_Ready;
-
-			return usbvideo_NewFrame(uvd, vm->frame);
-		}
-		case VIDIOCSYNC:
-		{
-			int *frameNum = arg;
-			int ret;
-
-			if (*frameNum < 0 || *frameNum >= USBVIDEO_NUMFRAMES)
-				return -EINVAL;
-
-			if (uvd->debug >= 1)
-				dev_info(&uvd->dev->dev,
-					 "VIDIOCSYNC: syncing to frame %d.\n",
-					 *frameNum);
-			if (uvd->flags & FLAGS_NO_DECODING)
-				ret = usbvideo_GetFrame(uvd, *frameNum);
-			else if (VALID_CALLBACK(uvd, getFrame)) {
-				ret = GET_CALLBACK(uvd, getFrame)(uvd, *frameNum);
-				if ((ret < 0) && (uvd->debug >= 1)) {
-					err("VIDIOCSYNC: getFrame() returned %d.", ret);
-				}
-			} else {
-				err("VIDIOCSYNC: getFrame is not set");
-				ret = -EFAULT;
-			}
-
-			/*
-			 * The frame is in FrameState_Done_Hold state. Release it
-			 * right now because its data is already mapped into
-			 * the user space and it's up to the application to
-			 * make use of it until it asks for another frame.
-			 */
-			uvd->frame[*frameNum].frameState = FrameState_Unused;
-			return ret;
-		}
-		case VIDIOCGFBUF:
-		{
-			struct video_buffer *vb = arg;
-
-			memset(vb, 0, sizeof(*vb));
-			return 0;
-		}
-		case VIDIOCKEY:
-			return 0;
-
-		case VIDIOCCAPTURE:
-			return -EINVAL;
-
-		case VIDIOCSFBUF:
-
-		case VIDIOCGTUNER:
-		case VIDIOCSTUNER:
-
-		case VIDIOCGFREQ:
-		case VIDIOCSFREQ:
-
-		case VIDIOCGAUDIO:
-		case VIDIOCSAUDIO:
-			return -EINVAL;
-
-		default:
-			return -ENOIOCTLCMD;
-	}
-	return 0;
-}
-
-static long usbvideo_v4l_ioctl(struct file *file,
-		       unsigned int cmd, unsigned long arg)
-{
-	return video_usercopy(file, cmd, arg, usbvideo_v4l_do_ioctl);
-}
-
-/*
- * usbvideo_v4l_read()
- *
- * This is mostly boring stuff. We simply ask for a frame and when it
- * arrives copy all the video data from it into user space. There is
- * no obvious need to override this method.
- *
- * History:
- * 20-Oct-2000 Created.
- * 01-Nov-2000 Added mutex (uvd->lock).
- */
-static ssize_t usbvideo_v4l_read(struct file *file, char __user *buf,
-		      size_t count, loff_t *ppos)
-{
-	struct uvd *uvd = file->private_data;
-	int noblock = file->f_flags & O_NONBLOCK;
-	int frmx = -1, i;
-	struct usbvideo_frame *frame;
-
-	if (!CAMERA_IS_OPERATIONAL(uvd) || (buf == NULL))
-		return -EFAULT;
-
-	if (uvd->debug >= 1)
-		dev_info(&uvd->dev->dev,
-			 "%s: %Zd. bytes, noblock=%d.\n",
-			 __func__, count, noblock);
-
-	mutex_lock(&uvd->lock);
-
-	/* See if a frame is completed, then use it. */
-	for(i = 0; i < USBVIDEO_NUMFRAMES; i++) {
-		if ((uvd->frame[i].frameState == FrameState_Done) ||
-		    (uvd->frame[i].frameState == FrameState_Done_Hold) ||
-		    (uvd->frame[i].frameState == FrameState_Error)) {
-			frmx = i;
-			break;
-		}
-	}
-
-	/* FIXME: If we don't start a frame here then who ever does? */
-	if (noblock && (frmx == -1)) {
-		count = -EAGAIN;
-		goto read_done;
-	}
-
-	/*
-	 * If no FrameState_Done, look for a FrameState_Grabbing state.
-	 * See if a frame is in process (grabbing), then use it.
-	 * We will need to wait until it becomes cooked, of course.
-	 */
-	if (frmx == -1) {
-		for(i = 0; i < USBVIDEO_NUMFRAMES; i++) {
-			if (uvd->frame[i].frameState == FrameState_Grabbing) {
-				frmx = i;
-				break;
-			}
-		}
-	}
-
-	/*
-	 * If no frame is active, start one. We don't care which one
-	 * it will be, so #0 is as good as any.
-	 * In read access mode we don't have convenience of VIDIOCMCAPTURE
-	 * to specify the requested palette (video format) on per-frame
-	 * basis. This means that we have to return data in -some- format
-	 * and just hope that the client knows what to do with it.
-	 * The default format is configured in uvd->defaultPalette field
-	 * as one of VIDEO_PALETTE_xxx values. We stuff it into the new
-	 * frame and initiate the frame filling process.
-	 */
-	if (frmx == -1) {
-		if (uvd->defaultPalette == 0) {
-			err("%s: No default palette; don't know what to do!", __func__);
-			count = -EFAULT;
-			goto read_done;
-		}
-		frmx = 0;
-		/*
-		 * We have no per-frame control over video size.
-		 * Therefore we only can use whatever size was
-		 * specified as default.
-		 */
-		uvd->frame[frmx].request = uvd->videosize;
-		uvd->frame[frmx].palette = uvd->defaultPalette;
-		uvd->frame[frmx].frameState = FrameState_Ready;
-		usbvideo_NewFrame(uvd, frmx);
-		/* Now frame 0 is supposed to start filling... */
-	}
-
-	/*
-	 * Get a pointer to the active frame. It is either previously
-	 * completed frame or frame in progress but not completed yet.
-	 */
-	frame = &uvd->frame[frmx];
-
-	/*
-	 * Sit back & wait until the frame gets filled and postprocessed.
-	 * If we fail to get the picture [in time] then return the error.
-	 * In this call we specify that we want the frame to be waited for,
-	 * postprocessed and switched into FrameState_Done_Hold state. This
-	 * state is used to hold the frame as "fully completed" between
-	 * subsequent partial reads of the same frame.
-	 */
-	if (frame->frameState != FrameState_Done_Hold) {
-		long rv = -EFAULT;
-		if (uvd->flags & FLAGS_NO_DECODING)
-			rv = usbvideo_GetFrame(uvd, frmx);
-		else if (VALID_CALLBACK(uvd, getFrame))
-			rv = GET_CALLBACK(uvd, getFrame)(uvd, frmx);
-		else
-			err("getFrame is not set");
-		if ((rv != 0) || (frame->frameState != FrameState_Done_Hold)) {
-			count = rv;
-			goto read_done;
-		}
-	}
-
-	/*
-	 * Copy bytes to user space. We allow for partial reads, which
-	 * means that the user application can request read less than
-	 * the full frame size. It is up to the application to issue
-	 * subsequent calls until entire frame is read.
-	 *
-	 * First things first, make sure we don't copy more than we
-	 * have - even if the application wants more. That would be
-	 * a big security embarassment!
-	 */
-	if ((count + frame->seqRead_Index) > frame->seqRead_Length)
-		count = frame->seqRead_Length - frame->seqRead_Index;
-
-	/*
-	 * Copy requested amount of data to user space. We start
-	 * copying from the position where we last left it, which
-	 * will be zero for a new frame (not read before).
-	 */
-	if (copy_to_user(buf, frame->data + frame->seqRead_Index, count)) {
-		count = -EFAULT;
-		goto read_done;
-	}
-
-	/* Update last read position */
-	frame->seqRead_Index += count;
-	if (uvd->debug >= 1) {
-		err("%s: {copy} count used=%Zd, new seqRead_Index=%ld",
-			__func__, count, frame->seqRead_Index);
-	}
-
-	/* Finally check if the frame is done with and "release" it */
-	if (frame->seqRead_Index >= frame->seqRead_Length) {
-		/* All data has been read */
-		frame->seqRead_Index = 0;
-
-		/* Mark it as available to be used again. */
-		uvd->frame[frmx].frameState = FrameState_Unused;
-		if (usbvideo_NewFrame(uvd, (frmx + 1) % USBVIDEO_NUMFRAMES)) {
-			err("%s: usbvideo_NewFrame failed.", __func__);
-		}
-	}
-read_done:
-	mutex_unlock(&uvd->lock);
-	return count;
-}
-
-/*
- * Make all of the blocks of data contiguous
- */
-static int usbvideo_CompressIsochronous(struct uvd *uvd, struct urb *urb)
-{
-	char *cdata;
-	int i, totlen = 0;
-
-	for (i = 0; i < urb->number_of_packets; i++) {
-		int n = urb->iso_frame_desc[i].actual_length;
-		int st = urb->iso_frame_desc[i].status;
-
-		cdata = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
-
-		/* Detect and ignore errored packets */
-		if (st < 0) {
-			if (uvd->debug >= 1)
-				err("Data error: packet=%d. len=%d. status=%d.", i, n, st);
-			uvd->stats.iso_err_count++;
-			continue;
-		}
-
-		/* Detect and ignore empty packets */
-		if (n <= 0) {
-			uvd->stats.iso_skip_count++;
-			continue;
-		}
-		totlen += n;	/* Little local accounting */
-		RingQueue_Enqueue(&uvd->dp, cdata, n);
-	}
-	return totlen;
-}
-
-static void usbvideo_IsocIrq(struct urb *urb)
-{
-	int i, ret, len;
-	struct uvd *uvd = urb->context;
-
-	/* We don't want to do anything if we are about to be removed! */
-	if (!CAMERA_IS_OPERATIONAL(uvd))
-		return;
-#if 0
-	if (urb->actual_length > 0) {
-		dev_info(&uvd->dev->dev,
-			 "urb=$%p status=%d. errcount=%d. length=%d.\n",
-			 urb, urb->status, urb->error_count,
-			 urb->actual_length);
-	} else {
-		static int c = 0;
-		if (c++ % 100 == 0)
-			dev_info(&uvd->dev->dev, "No Isoc data\n");
-	}
-#endif
-
-	if (!uvd->streaming) {
-		if (uvd->debug >= 1)
-			dev_info(&uvd->dev->dev,
-				 "Not streaming, but interrupt!\n");
-		return;
-	}
-
-	uvd->stats.urb_count++;
-	if (urb->actual_length <= 0)
-		goto urb_done_with;
-
-	/* Copy the data received into ring queue */
-	len = usbvideo_CompressIsochronous(uvd, urb);
-	uvd->stats.urb_length = len;
-	if (len <= 0)
-		goto urb_done_with;
-
-	/* Here we got some data */
-	uvd->stats.data_count += len;
-	RingQueue_WakeUpInterruptible(&uvd->dp);
-
-urb_done_with:
-	for (i = 0; i < FRAMES_PER_DESC; i++) {
-		urb->iso_frame_desc[i].status = 0;
-		urb->iso_frame_desc[i].actual_length = 0;
-	}
-	urb->status = 0;
-	urb->dev = uvd->dev;
-	ret = usb_submit_urb (urb, GFP_KERNEL);
-	if(ret)
-		err("usb_submit_urb error (%d)", ret);
-	return;
-}
-
-/*
- * usbvideo_StartDataPump()
- *
- * History:
- * 27-Jan-2000 Used ibmcam->iface, ibmcam->ifaceAltActive instead
- *             of hardcoded values. Simplified by using for loop,
- *             allowed any number of URBs.
- */
-static int usbvideo_StartDataPump(struct uvd *uvd)
-{
-	struct usb_device *dev = uvd->dev;
-	int i, errFlag;
-
-	if (uvd->debug > 1)
-		dev_info(&uvd->dev->dev, "%s($%p)\n", __func__, uvd);
-
-	if (!CAMERA_IS_OPERATIONAL(uvd)) {
-		err("%s: Camera is not operational", __func__);
-		return -EFAULT;
-	}
-	uvd->curframe = -1;
-
-	/* Alternate interface 1 is is the biggest frame size */
-	i = usb_set_interface(dev, uvd->iface, uvd->ifaceAltActive);
-	if (i < 0) {
-		err("%s: usb_set_interface error", __func__);
-		uvd->last_error = i;
-		return -EBUSY;
-	}
-	if (VALID_CALLBACK(uvd, videoStart))
-		GET_CALLBACK(uvd, videoStart)(uvd);
-	else
-		err("%s: videoStart not set", __func__);
-
-	/* We double buffer the Iso lists */
-	for (i=0; i < USBVIDEO_NUMSBUF; i++) {
-		int j, k;
-		struct urb *urb = uvd->sbuf[i].urb;
-		urb->dev = dev;
-		urb->context = uvd;
-		urb->pipe = usb_rcvisocpipe(dev, uvd->video_endp);
-		urb->interval = 1;
-		urb->transfer_flags = URB_ISO_ASAP;
-		urb->transfer_buffer = uvd->sbuf[i].data;
-		urb->complete = usbvideo_IsocIrq;
-		urb->number_of_packets = FRAMES_PER_DESC;
-		urb->transfer_buffer_length = uvd->iso_packet_len * FRAMES_PER_DESC;
-		for (j=k=0; j < FRAMES_PER_DESC; j++, k += uvd->iso_packet_len) {
-			urb->iso_frame_desc[j].offset = k;
-			urb->iso_frame_desc[j].length = uvd->iso_packet_len;
-		}
-	}
-
-	/* Submit all URBs */
-	for (i=0; i < USBVIDEO_NUMSBUF; i++) {
-		errFlag = usb_submit_urb(uvd->sbuf[i].urb, GFP_KERNEL);
-		if (errFlag)
-			err("%s: usb_submit_isoc(%d) ret %d", __func__, i, errFlag);
-	}
-
-	uvd->streaming = 1;
-	if (uvd->debug > 1)
-		dev_info(&uvd->dev->dev,
-			 "%s: streaming=1 video_endp=$%02x\n", __func__,
-			 uvd->video_endp);
-	return 0;
-}
-
-/*
- * usbvideo_StopDataPump()
- *
- * This procedure stops streaming and deallocates URBs. Then it
- * activates zero-bandwidth alt. setting of the video interface.
- *
- * History:
- * 22-Jan-2000 Corrected order of actions to work after surprise removal.
- * 27-Jan-2000 Used uvd->iface, uvd->ifaceAltInactive instead of hardcoded values.
- */
-static void usbvideo_StopDataPump(struct uvd *uvd)
-{
-	int i, j;
-
-	if ((uvd == NULL) || (!uvd->streaming) || (uvd->dev == NULL))
-		return;
-
-	if (uvd->debug > 1)
-		dev_info(&uvd->dev->dev, "%s($%p)\n", __func__, uvd);
-
-	/* Unschedule all of the iso td's */
-	for (i=0; i < USBVIDEO_NUMSBUF; i++) {
-		usb_kill_urb(uvd->sbuf[i].urb);
-	}
-	if (uvd->debug > 1)
-		dev_info(&uvd->dev->dev, "%s: streaming=0\n", __func__);
-	uvd->streaming = 0;
-
-	if (!uvd->remove_pending) {
-		/* Invoke minidriver's magic to stop the camera */
-		if (VALID_CALLBACK(uvd, videoStop))
-			GET_CALLBACK(uvd, videoStop)(uvd);
-		else
-			err("%s: videoStop not set", __func__);
-
-		/* Set packet size to 0 */
-		j = usb_set_interface(uvd->dev, uvd->iface, uvd->ifaceAltInactive);
-		if (j < 0) {
-			err("%s: usb_set_interface() error %d.", __func__, j);
-			uvd->last_error = j;
-		}
-	}
-}
-
-/*
- * usbvideo_NewFrame()
- *
- * History:
- * 29-Mar-00 Added copying of previous frame into the current one.
- * 6-Aug-00  Added model 3 video sizes, removed redundant width, height.
- */
-static int usbvideo_NewFrame(struct uvd *uvd, int framenum)
-{
-	struct usbvideo_frame *frame;
-	int n;
-
-	if (uvd->debug > 1)
-		dev_info(&uvd->dev->dev, "usbvideo_NewFrame($%p,%d.)\n", uvd,
-			 framenum);
-
-	/* If we're not grabbing a frame right now and the other frame is */
-	/*  ready to be grabbed into, then use it instead */
-	if (uvd->curframe != -1)
-		return 0;
-
-	/* If necessary we adjust picture settings between frames */
-	if (!uvd->settingsAdjusted) {
-		if (VALID_CALLBACK(uvd, adjustPicture))
-			GET_CALLBACK(uvd, adjustPicture)(uvd);
-		uvd->settingsAdjusted = 1;
-	}
-
-	n = (framenum + 1) % USBVIDEO_NUMFRAMES;
-	if (uvd->frame[n].frameState == FrameState_Ready)
-		framenum = n;
-
-	frame = &uvd->frame[framenum];
-
-	frame->frameState = FrameState_Grabbing;
-	frame->scanstate = ScanState_Scanning;
-	frame->seqRead_Length = 0;	/* Accumulated in xxx_parse_data() */
-	frame->deinterlace = Deinterlace_None;
-	frame->flags = 0; /* No flags yet, up to minidriver (or us) to set them */
-	uvd->curframe = framenum;
-
-	/*
-	 * Normally we would want to copy previous frame into the current one
-	 * before we even start filling it with data; this allows us to stop
-	 * filling at any moment; top portion of the frame will be new and
-	 * bottom portion will stay as it was in previous frame. If we don't
-	 * do that then missing chunks of video stream will result in flickering
-	 * portions of old data whatever it was before.
-	 *
-	 * If we choose not to copy previous frame (to, for example, save few
-	 * bus cycles - the frame can be pretty large!) then we have an option
-	 * to clear the frame before using. If we experience losses in this
-	 * mode then missing picture will be black (no flickering).
-	 *
-	 * Finally, if user chooses not to clean the current frame before
-	 * filling it with data then the old data will be visible if we fail
-	 * to refill entire frame with new data.
-	 */
-	if (!(uvd->flags & FLAGS_SEPARATE_FRAMES)) {
-		/* This copies previous frame into this one to mask losses */
-		int prev = (framenum - 1 + USBVIDEO_NUMFRAMES) % USBVIDEO_NUMFRAMES;
-		memmove(frame->data, uvd->frame[prev].data, uvd->max_frame_size);
-	} else {
-		if (uvd->flags & FLAGS_CLEAN_FRAMES) {
-			/* This provides a "clean" frame but slows things down */
-			memset(frame->data, 0, uvd->max_frame_size);
-		}
-	}
-	return 0;
-}
-
-/*
- * usbvideo_CollectRawData()
- *
- * This procedure can be used instead of 'processData' callback if you
- * only want to dump the raw data from the camera into the output
- * device (frame buffer). You can look at it with V4L client, but the
- * image will be unwatchable. The main purpose of this code and of the
- * mode FLAGS_NO_DECODING is debugging and capturing of datastreams from
- * new, unknown cameras. This procedure will be automatically invoked
- * instead of the specified callback handler when uvd->flags has bit
- * FLAGS_NO_DECODING set. Therefore, any regular build of any driver
- * based on usbvideo can use this feature at any time.
- */
-static void usbvideo_CollectRawData(struct uvd *uvd, struct usbvideo_frame *frame)
-{
-	int n;
-
-	assert(uvd != NULL);
-	assert(frame != NULL);
-
-	/* Try to move data from queue into frame buffer */
-	n = RingQueue_GetLength(&uvd->dp);
-	if (n > 0) {
-		int m;
-		/* See how much space we have left */
-		m = uvd->max_frame_size - frame->seqRead_Length;
-		if (n > m)
-			n = m;
-		/* Now move that much data into frame buffer */
-		RingQueue_Dequeue(
-			&uvd->dp,
-			frame->data + frame->seqRead_Length,
-			m);
-		frame->seqRead_Length += m;
-	}
-	/* See if we filled the frame */
-	if (frame->seqRead_Length >= uvd->max_frame_size) {
-		frame->frameState = FrameState_Done;
-		uvd->curframe = -1;
-		uvd->stats.frame_num++;
-	}
-}
-
-static int usbvideo_GetFrame(struct uvd *uvd, int frameNum)
-{
-	struct usbvideo_frame *frame = &uvd->frame[frameNum];
-
-	if (uvd->debug >= 2)
-		dev_info(&uvd->dev->dev, "%s($%p,%d.)\n", __func__, uvd,
-			 frameNum);
-
-	switch (frame->frameState) {
-	case FrameState_Unused:
-		if (uvd->debug >= 2)
-			dev_info(&uvd->dev->dev, "%s: FrameState_Unused\n",
-				 __func__);
-		return -EINVAL;
-	case FrameState_Ready:
-	case FrameState_Grabbing:
-	case FrameState_Error:
-	{
-		int ntries, signalPending;
-	redo:
-		if (!CAMERA_IS_OPERATIONAL(uvd)) {
-			if (uvd->debug >= 2)
-				dev_info(&uvd->dev->dev,
-					 "%s: Camera is not operational (1)\n",
-					 __func__);
-			return -EIO;
-		}
-		ntries = 0;
-		do {
-			RingQueue_InterruptibleSleepOn(&uvd->dp);
-			signalPending = signal_pending(current);
-			if (!CAMERA_IS_OPERATIONAL(uvd)) {
-				if (uvd->debug >= 2)
-					dev_info(&uvd->dev->dev,
-						 "%s: Camera is not "
-						 "operational (2)\n", __func__);
-				return -EIO;
-			}
-			assert(uvd->fbuf != NULL);
-			if (signalPending) {
-				if (uvd->debug >= 2)
-					dev_info(&uvd->dev->dev,
-					"%s: Signal=$%08x\n", __func__,
-					signalPending);
-				if (uvd->flags & FLAGS_RETRY_VIDIOCSYNC) {
-					usbvideo_TestPattern(uvd, 1, 0);
-					uvd->curframe = -1;
-					uvd->stats.frame_num++;
-					if (uvd->debug >= 2)
-						dev_info(&uvd->dev->dev,
-							 "%s: Forced test "
-							 "pattern screen\n",
-							 __func__);
-					return 0;
-				} else {
-					/* Standard answer: Interrupted! */
-					if (uvd->debug >= 2)
-						dev_info(&uvd->dev->dev,
-							 "%s: Interrupted!\n",
-							 __func__);
-					return -EINTR;
-				}
-			} else {
-				/* No signals - we just got new data in dp queue */
-				if (uvd->flags & FLAGS_NO_DECODING)
-					usbvideo_CollectRawData(uvd, frame);
-				else if (VALID_CALLBACK(uvd, processData))
-					GET_CALLBACK(uvd, processData)(uvd, frame);
-				else
-					err("%s: processData not set", __func__);
-			}
-		} while (frame->frameState == FrameState_Grabbing);
-		if (uvd->debug >= 2) {
-			dev_info(&uvd->dev->dev,
-				 "%s: Grabbing done; state=%d. (%lu. bytes)\n",
-				 __func__, frame->frameState,
-				 frame->seqRead_Length);
-		}
-		if (frame->frameState == FrameState_Error) {
-			int ret = usbvideo_NewFrame(uvd, frameNum);
-			if (ret < 0) {
-				err("%s: usbvideo_NewFrame() failed (%d.)", __func__, ret);
-				return ret;
-			}
-			goto redo;
-		}
-		/* Note that we fall through to meet our destiny below */
-	}
-	case FrameState_Done:
-		/*
-		 * Do all necessary postprocessing of data prepared in
-		 * "interrupt" code and the collecting code above. The
-		 * frame gets marked as FrameState_Done by queue parsing code.
-		 * This status means that we collected enough data and
-		 * most likely processed it as we went through. However
-		 * the data may need postprocessing, such as deinterlacing
-		 * or picture adjustments implemented in software (horror!)
-		 *
-		 * As soon as the frame becomes "final" it gets promoted to
-		 * FrameState_Done_Hold status where it will remain until the
-		 * caller consumed all the video data from the frame. Then
-		 * the empty shell of ex-frame is thrown out for dogs to eat.
-		 * But we, worried about pets, will recycle the frame!
-		 */
-		uvd->stats.frame_num++;
-		if ((uvd->flags & FLAGS_NO_DECODING) == 0) {
-			if (VALID_CALLBACK(uvd, postProcess))
-				GET_CALLBACK(uvd, postProcess)(uvd, frame);
-			if (frame->flags & USBVIDEO_FRAME_FLAG_SOFTWARE_CONTRAST)
-				usbvideo_SoftwareContrastAdjustment(uvd, frame);
-		}
-		frame->frameState = FrameState_Done_Hold;
-		if (uvd->debug >= 2)
-			dev_info(&uvd->dev->dev,
-				 "%s: Entered FrameState_Done_Hold state.\n",
-				 __func__);
-		return 0;
-
-	case FrameState_Done_Hold:
-		/*
-		 * We stay in this state indefinitely until someone external,
-		 * like ioctl() or read() call finishes digesting the frame
-		 * data. Then it will mark the frame as FrameState_Unused and
-		 * it will be released back into the wild to roam freely.
-		 */
-		if (uvd->debug >= 2)
-			dev_info(&uvd->dev->dev,
-				 "%s: FrameState_Done_Hold state.\n",
-				 __func__);
-		return 0;
-	}
-
-	/* Catch-all for other cases. We shall not be here. */
-	err("%s: Invalid state %d.", __func__, frame->frameState);
-	frame->frameState = FrameState_Unused;
-	return 0;
-}
-
-/*
- * usbvideo_DeinterlaceFrame()
- *
- * This procedure deinterlaces the given frame. Some cameras produce
- * only half of scanlines - sometimes only even lines, sometimes only
- * odd lines. The deinterlacing method is stored in frame->deinterlace
- * variable.
- *
- * Here we scan the frame vertically and replace missing scanlines with
- * average between surrounding ones - before and after. If we have no
- * line above then we just copy next line. Similarly, if we need to
- * create a last line then preceding line is used.
- */
-void usbvideo_DeinterlaceFrame(struct uvd *uvd, struct usbvideo_frame *frame)
-{
-	if ((uvd == NULL) || (frame == NULL))
-		return;
-
-	if ((frame->deinterlace == Deinterlace_FillEvenLines) ||
-	    (frame->deinterlace == Deinterlace_FillOddLines))
-	{
-		const int v4l_linesize = VIDEOSIZE_X(frame->request) * V4L_BYTES_PER_PIXEL;
-		int i = (frame->deinterlace == Deinterlace_FillEvenLines) ? 0 : 1;
-
-		for (; i < VIDEOSIZE_Y(frame->request); i += 2) {
-			const unsigned char *fs1, *fs2;
-			unsigned char *fd;
-			int ip, in, j;	/* Previous and next lines */
-
-			/*
-			 * Need to average lines before and after 'i'.
-			 * If we go out of bounds seeking those lines then
-			 * we point back to existing line.
-			 */
-			ip = i - 1;	/* First, get rough numbers */
-			in = i + 1;
-
-			/* Now validate */
-			if (ip < 0)
-				ip = in;
-			if (in >= VIDEOSIZE_Y(frame->request))
-				in = ip;
-
-			/* Sanity check */
-			if ((ip < 0) || (in < 0) ||
-			    (ip >= VIDEOSIZE_Y(frame->request)) ||
-			    (in >= VIDEOSIZE_Y(frame->request)))
-			{
-				err("Error: ip=%d. in=%d. req.height=%ld.",
-				    ip, in, VIDEOSIZE_Y(frame->request));
-				break;
-			}
-
-			/* Now we need to average lines 'ip' and 'in' to produce line 'i' */
-			fs1 = frame->data + (v4l_linesize * ip);
-			fs2 = frame->data + (v4l_linesize * in);
-			fd = frame->data + (v4l_linesize * i);
-
-			/* Average lines around destination */
-			for (j=0; j < v4l_linesize; j++) {
-				fd[j] = (unsigned char)((((unsigned) fs1[j]) +
-							 ((unsigned)fs2[j])) >> 1);
-			}
-		}
-	}
-
-	/* Optionally display statistics on the screen */
-	if (uvd->flags & FLAGS_OVERLAY_STATS)
-		usbvideo_OverlayStats(uvd, frame);
-}
-
-EXPORT_SYMBOL(usbvideo_DeinterlaceFrame);
-
-/*
- * usbvideo_SoftwareContrastAdjustment()
- *
- * This code adjusts the contrast of the frame, assuming RGB24 format.
- * As most software image processing, this job is CPU-intensive.
- * Get a camera that supports hardware adjustment!
- *
- * History:
- * 09-Feb-2001  Created.
- */
-static void usbvideo_SoftwareContrastAdjustment(struct uvd *uvd,
-						struct usbvideo_frame *frame)
-{
-	int i, j, v4l_linesize;
-	signed long adj;
-	const int ccm = 128; /* Color correction median - see below */
-
-	if ((uvd == NULL) || (frame == NULL)) {
-		err("%s: Illegal call.", __func__);
-		return;
-	}
-	adj = (uvd->vpic.contrast - 0x8000) >> 8; /* -128..+127 = -ccm..+(ccm-1)*/
-	RESTRICT_TO_RANGE(adj, -ccm, ccm+1);
-	if (adj == 0) {
-		/* In rare case of no adjustment */
-		return;
-	}
-	v4l_linesize = VIDEOSIZE_X(frame->request) * V4L_BYTES_PER_PIXEL;
-	for (i=0; i < VIDEOSIZE_Y(frame->request); i++) {
-		unsigned char *fd = frame->data + (v4l_linesize * i);
-		for (j=0; j < v4l_linesize; j++) {
-			signed long v = (signed long) fd[j];
-			/* Magnify up to 2 times, reduce down to zero */
-			v = 128 + ((ccm + adj) * (v - 128)) / ccm;
-			RESTRICT_TO_RANGE(v, 0, 0xFF); /* Must flatten tails */
-			fd[j] = (unsigned char) v;
-		}
-	}
-}
-
-MODULE_LICENSE("GPL");
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/usbvideo/usbvideo.h linux-libre-2.6.38-gnu1/drivers/media/video/usbvideo/usbvideo.h
--- linux-libre-2.6.37-gnu1/drivers/media/video/usbvideo/usbvideo.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/usbvideo/usbvideo.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,395 +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, 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 usbvideo_h
-#define	usbvideo_h
-
-#include <linux/videodev.h>
-#include <media/v4l2-common.h>
-#include <media/v4l2-ioctl.h>
-#include <linux/usb.h>
-#include <linux/mutex.h>
-
-/* Most helpful debugging aid */
-#define assert(expr) ((void) ((expr) ? 0 : (err("assert failed at line %d",__LINE__))))
-
-#define USBVIDEO_REPORT_STATS	1	/* Set to 0 to block statistics on close */
-
-/* Bit flags (options) */
-#define FLAGS_RETRY_VIDIOCSYNC		(1 << 0)
-#define	FLAGS_MONOCHROME		(1 << 1)
-#define FLAGS_DISPLAY_HINTS		(1 << 2)
-#define FLAGS_OVERLAY_STATS		(1 << 3)
-#define FLAGS_FORCE_TESTPATTERN		(1 << 4)
-#define FLAGS_SEPARATE_FRAMES		(1 << 5)
-#define FLAGS_CLEAN_FRAMES		(1 << 6)
-#define	FLAGS_NO_DECODING		(1 << 7)
-
-/* Bit flags for frames (apply to the frame where they are specified) */
-#define USBVIDEO_FRAME_FLAG_SOFTWARE_CONTRAST	(1 << 0)
-
-/* Camera capabilities (maximum) */
-#define CAMERA_URB_FRAMES       32
-#define CAMERA_MAX_ISO_PACKET   1023 /* 1022 actually sent by camera */
-#define FRAMES_PER_DESC		(CAMERA_URB_FRAMES)
-#define FRAME_SIZE_PER_DESC	(CAMERA_MAX_ISO_PACKET)
-
-/* This macro restricts an int variable to an inclusive range */
-#define RESTRICT_TO_RANGE(v,mi,ma) { if ((v) < (mi)) (v) = (mi); else if ((v) > (ma)) (v) = (ma); }
-
-#define V4L_BYTES_PER_PIXEL     3	/* Because we produce RGB24 */
-
-/*
- * Use this macro to construct constants for different video sizes.
- * We have to deal with different video sizes that have to be
- * configured in the device or compared against when we receive
- * a data. Normally one would define a bunch of VIDEOSIZE_x_by_y
- * #defines and that's the end of story. However this solution
- * does not allow to convert between real pixel sizes and the
- * constant (integer) value that may be used to tag a frame or
- * whatever. The set of macros below constructs videosize constants
- * from the pixel size and allows to reconstruct the pixel size
- * from the combined value later.
- */
-#define	VIDEOSIZE(x,y)	(((x) & 0xFFFFL) | (((y) & 0xFFFFL) << 16))
-#define	VIDEOSIZE_X(vs)	((vs) & 0xFFFFL)
-#define	VIDEOSIZE_Y(vs)	(((vs) >> 16) & 0xFFFFL)
-typedef unsigned long videosize_t;
-
-/*
- * This macro checks if the camera is still operational. The 'uvd'
- * pointer must be valid, uvd->dev must be valid, we are not
- * removing the device and the device has not erred on us.
- */
-#define CAMERA_IS_OPERATIONAL(uvd) (\
-	(uvd != NULL) && \
-	((uvd)->dev != NULL) && \
-	((uvd)->last_error == 0) && \
-	(!(uvd)->remove_pending))
-
-/*
- * We use macros to do YUV -> RGB conversion because this is
- * very important for speed and totally unimportant for size.
- *
- * YUV -> RGB Conversion
- * ---------------------
- *
- * B = 1.164*(Y-16)		    + 2.018*(V-128)
- * G = 1.164*(Y-16) - 0.813*(U-128) - 0.391*(V-128)
- * R = 1.164*(Y-16) + 1.596*(U-128)
- *
- * If you fancy integer arithmetics (as you should), hear this:
- *
- * 65536*B = 76284*(Y-16)		  + 132252*(V-128)
- * 65536*G = 76284*(Y-16) -  53281*(U-128) -  25625*(V-128)
- * 65536*R = 76284*(Y-16) + 104595*(U-128)
- *
- * Make sure the output values are within [0..255] range.
- */
-#define LIMIT_RGB(x) (((x) < 0) ? 0 : (((x) > 255) ? 255 : (x)))
-#define YUV_TO_RGB_BY_THE_BOOK(my,mu,mv,mr,mg,mb) { \
-    int mm_y, mm_yc, mm_u, mm_v, mm_r, mm_g, mm_b; \
-    mm_y = (my) - 16;  \
-    mm_u = (mu) - 128; \
-    mm_v = (mv) - 128; \
-    mm_yc= mm_y * 76284; \
-    mm_b = (mm_yc		+ 132252*mm_v	) >> 16; \
-    mm_g = (mm_yc -  53281*mm_u -  25625*mm_v	) >> 16; \
-    mm_r = (mm_yc + 104595*mm_u			) >> 16; \
-    mb = LIMIT_RGB(mm_b); \
-    mg = LIMIT_RGB(mm_g); \
-    mr = LIMIT_RGB(mm_r); \
-}
-
-#define	RING_QUEUE_SIZE		(128*1024)	/* Must be a power of 2 */
-#define	RING_QUEUE_ADVANCE_INDEX(rq,ind,n) (rq)->ind = ((rq)->ind + (n)) & ((rq)->length-1)
-#define	RING_QUEUE_DEQUEUE_BYTES(rq,n) RING_QUEUE_ADVANCE_INDEX(rq,ri,n)
-#define	RING_QUEUE_PEEK(rq,ofs) ((rq)->queue[((ofs) + (rq)->ri) & ((rq)->length-1)])
-
-struct RingQueue {
-	unsigned char *queue;	/* Data from the Isoc data pump */
-	int length;		/* How many bytes allocated for the queue */
-	int wi;			/* That's where we write */
-	int ri;			/* Read from here until you hit write index */
-	wait_queue_head_t wqh;	/* Processes waiting */
-};
-
-enum ScanState {
-	ScanState_Scanning,	/* Scanning for header */
-	ScanState_Lines		/* Parsing lines */
-};
-
-/* Completion states of the data parser */
-enum ParseState {
-	scan_Continue,		/* Just parse next item */
-	scan_NextFrame,		/* Frame done, send it to V4L */
-	scan_Out,		/* Not enough data for frame */
-	scan_EndParse		/* End parsing */
-};
-
-enum FrameState {
-	FrameState_Unused,	/* Unused (no MCAPTURE) */
-	FrameState_Ready,	/* Ready to start grabbing */
-	FrameState_Grabbing,	/* In the process of being grabbed into */
-	FrameState_Done,	/* Finished grabbing, but not been synced yet */
-	FrameState_Done_Hold,	/* Are syncing or reading */
-	FrameState_Error,	/* Something bad happened while processing */
-};
-
-/*
- * Some frames may contain only even or odd lines. This type
- * specifies what type of deinterlacing is required.
- */
-enum Deinterlace {
-	Deinterlace_None=0,
-	Deinterlace_FillOddLines,
-	Deinterlace_FillEvenLines
-};
-
-#define USBVIDEO_NUMFRAMES	2	/* How many frames we work with */
-#define USBVIDEO_NUMSBUF	2	/* How many URBs linked in a ring */
-
-/* This structure represents one Isoc request - URB and buffer */
-struct usbvideo_sbuf {
-	char *data;
-	struct urb *urb;
-};
-
-struct usbvideo_frame {
-	char *data;		/* Frame buffer */
-	unsigned long header;	/* Significant bits from the header */
-
-	videosize_t canvas;	/* The canvas (max. image) allocated */
-	videosize_t request;	/* That's what the application asked for */
-	unsigned short palette;	/* The desired format */
-
-	enum FrameState frameState;/* State of grabbing */
-	enum ScanState scanstate;	/* State of scanning */
-	enum Deinterlace deinterlace;
-	int flags;		/* USBVIDEO_FRAME_FLAG_xxx bit flags */
-
-	int curline;		/* Line of frame we're working on */
-
-	long seqRead_Length;	/* Raw data length of frame */
-	long seqRead_Index;	/* Amount of data that has been already read */
-
-	void *user;		/* Additional data that user may need */
-};
-
-/* Statistics that can be overlaid on screen */
-struct usbvideo_statistics {
-	unsigned long frame_num;	/* Sequential number of the frame */
-	unsigned long urb_count;        /* How many URBs we received so far */
-	unsigned long urb_length;       /* Length of last URB */
-	unsigned long data_count;       /* How many bytes we received */
-	unsigned long header_count;     /* How many frame headers we found */
-	unsigned long iso_skip_count;	/* How many empty ISO packets received */
-	unsigned long iso_err_count;	/* How many bad ISO packets received */
-};
-
-struct usbvideo;
-
-struct uvd {
-	struct video_device vdev;	/* Must be the first field! */
-	struct usb_device *dev;
-	struct usbvideo *handle;	/* Points back to the struct usbvideo */
-	void *user_data;		/* Camera-dependent data */
-	int user_size;			/* Size of that camera-dependent data */
-	int debug;			/* Debug level for usbvideo */
-	unsigned char iface;		/* Video interface number */
-	unsigned char video_endp;
-	unsigned char ifaceAltActive;
-	unsigned char ifaceAltInactive; /* Alt settings */
-	unsigned long flags;		/* FLAGS_USBVIDEO_xxx */
-	unsigned long paletteBits;	/* Which palettes we accept? */
-	unsigned short defaultPalette;	/* What palette to use for read() */
-	struct mutex lock;
-	int user;		/* user count for exclusive use */
-
-	videosize_t videosize;	/* Current setting */
-	videosize_t canvas;	/* This is the width,height of the V4L canvas */
-	int max_frame_size;	/* Bytes in one video frame */
-
-	int uvd_used;        	/* Is this structure in use? */
-	int streaming;		/* Are we streaming Isochronous? */
-	int grabbing;		/* Are we grabbing? */
-	int settingsAdjusted;	/* Have we adjusted contrast etc.? */
-	int last_error;		/* What calamity struck us? */
-
-	char *fbuf;		/* Videodev buffer area */
-	int fbuf_size;		/* Videodev buffer size */
-
-	int curframe;
-	int iso_packet_len;	/* Videomode-dependent, saves bus bandwidth */
-
-	struct RingQueue dp;	/* Isoc data pump */
-	struct usbvideo_frame frame[USBVIDEO_NUMFRAMES];
-	struct usbvideo_sbuf sbuf[USBVIDEO_NUMSBUF];
-
-	volatile int remove_pending;	/* If set then about to exit */
-
-	struct video_picture vpic, vpic_old;	/* Picture settings */
-	struct video_capability vcap;		/* Video capabilities */
-	struct video_channel vchan;	/* May be used for tuner support */
-	struct usbvideo_statistics stats;
-	char videoName[32];		/* Holds name like "video7" */
-};
-
-/*
- * usbvideo callbacks (virtual methods). They are set when usbvideo
- * services are registered. All of these default to NULL, except those
- * that default to usbvideo-provided methods.
- */
-struct usbvideo_cb {
-	int (*probe)(struct usb_interface *, const struct usb_device_id *);
-	void (*userFree)(struct uvd *);
-	void (*disconnect)(struct usb_interface *);
-	int (*setupOnOpen)(struct uvd *);
-	void (*videoStart)(struct uvd *);
-	void (*videoStop)(struct uvd *);
-	void (*processData)(struct uvd *, struct usbvideo_frame *);
-	void (*postProcess)(struct uvd *, struct usbvideo_frame *);
-	void (*adjustPicture)(struct uvd *);
-	int (*getFPS)(struct uvd *);
-	int (*overlayHook)(struct uvd *, struct usbvideo_frame *);
-	int (*getFrame)(struct uvd *, int);
-	int (*startDataPump)(struct uvd *uvd);
-	void (*stopDataPump)(struct uvd *uvd);
-	int (*setVideoMode)(struct uvd *uvd, struct video_window *vw);
-};
-
-struct usbvideo {
-	int num_cameras;		/* As allocated */
-	struct usb_driver usbdrv;	/* Interface to the USB stack */
-	char drvName[80];		/* Driver name */
-	struct mutex lock;		/* Mutex protecting camera structures */
-	struct usbvideo_cb cb;		/* Table of callbacks (virtual methods) */
-	struct video_device vdt;	/* Video device template */
-	struct uvd *cam;			/* Array of camera structures */
-	struct module *md_module;	/* Minidriver module */
-};
-
-
-/*
- * This macro retrieves callback address from the struct uvd object.
- * No validity checks are done here, so be sure to check the
- * callback beforehand with VALID_CALLBACK.
- */
-#define	GET_CALLBACK(uvd,cbName) ((uvd)->handle->cb.cbName)
-
-/*
- * This macro returns either callback pointer or NULL. This is safe
- * macro, meaning that most of components of data structures involved
- * may be NULL - this only results in NULL being returned. You may
- * wish to use this macro to make sure that the callback is callable.
- * However keep in mind that those checks take time.
- */
-#define	VALID_CALLBACK(uvd,cbName) ((((uvd) != NULL) && \
-		((uvd)->handle != NULL)) ? GET_CALLBACK(uvd,cbName) : NULL)
-
-int  RingQueue_Dequeue(struct RingQueue *rq, unsigned char *dst, int len);
-int  RingQueue_Enqueue(struct RingQueue *rq, const unsigned char *cdata, int n);
-void RingQueue_WakeUpInterruptible(struct RingQueue *rq);
-void RingQueue_Flush(struct RingQueue *rq);
-
-static inline int RingQueue_GetLength(const struct RingQueue *rq)
-{
-	return (rq->wi - rq->ri + rq->length) & (rq->length-1);
-}
-
-static inline int RingQueue_GetFreeSpace(const struct RingQueue *rq)
-{
-	return rq->length - RingQueue_GetLength(rq);
-}
-
-void usbvideo_DrawLine(
-	struct usbvideo_frame *frame,
-	int x1, int y1,
-	int x2, int y2,
-	unsigned char cr, unsigned char cg, unsigned char cb);
-void usbvideo_HexDump(const unsigned char *data, int len);
-void usbvideo_SayAndWait(const char *what);
-void usbvideo_TestPattern(struct uvd *uvd, int fullframe, int pmode);
-
-/* Memory allocation routines */
-unsigned long usbvideo_kvirt_to_pa(unsigned long adr);
-
-int usbvideo_register(
-	struct usbvideo **pCams,
-	const int num_cams,
-	const int num_extra,
-	const char *driverName,
-	const struct usbvideo_cb *cbTable,
-	struct module *md,
-	const struct usb_device_id *id_table);
-struct uvd *usbvideo_AllocateDevice(struct usbvideo *cams);
-int usbvideo_RegisterVideoDevice(struct uvd *uvd);
-void usbvideo_Deregister(struct usbvideo **uvt);
-
-int usbvideo_v4l_initialize(struct video_device *dev);
-
-void usbvideo_DeinterlaceFrame(struct uvd *uvd, struct usbvideo_frame *frame);
-
-/*
- * This code performs bounds checking - use it when working with
- * new formats, or else you may get oopses all over the place.
- * If pixel falls out of bounds then it gets shoved back (as close
- * to place of offence as possible) and is painted bright red.
- *
- * There are two important concepts: frame width, height and
- * V4L canvas width, height. The former is the area requested by
- * the application -for this very frame-. The latter is the largest
- * possible frame that we can serve (we advertise that via V4L ioctl).
- * The frame data is expected to be formatted as lines of length
- * VIDEOSIZE_X(fr->request), total VIDEOSIZE_Y(frame->request) lines.
- */
-static inline void RGB24_PUTPIXEL(
-	struct usbvideo_frame *fr,
-	int ix, int iy,
-	unsigned char vr,
-	unsigned char vg,
-	unsigned char vb)
-{
-	register unsigned char *pf;
-	int limiter = 0, mx, my;
-	mx = ix;
-	my = iy;
-	if (mx < 0) {
-		mx=0;
-		limiter++;
-	} else if (mx >= VIDEOSIZE_X((fr)->request)) {
-		mx= VIDEOSIZE_X((fr)->request) - 1;
-		limiter++;
-	}
-	if (my < 0) {
-		my = 0;
-		limiter++;
-	} else if (my >= VIDEOSIZE_Y((fr)->request)) {
-		my = VIDEOSIZE_Y((fr)->request) - 1;
-		limiter++;
-	}
-	pf = (fr)->data + V4L_BYTES_PER_PIXEL*((iy)*VIDEOSIZE_X((fr)->request) + (ix));
-	if (limiter) {
-		*pf++ = 0;
-		*pf++ = 0;
-		*pf++ = 0xFF;
-	} else {
-		*pf++ = (vb);
-		*pf++ = (vg);
-		*pf++ = (vr);
-	}
-}
-
-#endif /* usbvideo_h */
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/usbvideo/vicam.c linux-libre-2.6.38-gnu1/drivers/media/video/usbvideo/vicam.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/usbvideo/vicam.c	2013-05-03 03:57:36.000000000 -0400
+++ linux-libre-2.6.38-gnu1/drivers/media/video/usbvideo/vicam.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,952 +0,0 @@
-/*
- * USB ViCam WebCam driver
- * Copyright (c) 2002 Joe Burks (jburks@wavicle.org),
- *                    Christopher L Cheney (ccheney@cheney.cx),
- *                    Pavel Machek (pavel@ucw.cz),
- *                    John Tyner (jtyner@cs.ucr.edu),
- *                    Monroe Williams (monroe@pobox.com)
- *
- * Supports 3COM HomeConnect PC Digital WebCam
- * Supports Compro PS39U WebCam
- *
- * 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.
- *
- * This source code is based heavily on the CPiA webcam driver which was
- * written by Peter Pregler, Scott J. Bertin and Johannes Erdfelt
- *
- * Portions of this code were also copied from usbvideo.c
- *
- * Special thanks to the whole team at Sourceforge for help making
- * this driver become a reality.  Notably:
- * Andy Armstrong who reverse engineered the color encoding and
- * Pavel Machek and Chris Cheney who worked on reverse engineering the
- *    camera controls and wrote the first generation driver.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/videodev.h>
-#include <linux/usb.h>
-#include <linux/vmalloc.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/mutex.h>
-#include <linux/firmware.h>
-#include <linux/ihex.h>
-#include "usbvideo.h"
-
-// #define VICAM_DEBUG
-
-#ifdef VICAM_DEBUG
-#define ADBG(lineno,fmt,args...) printk(fmt, jiffies, __func__, lineno, ##args)
-#define DBG(fmt,args...) ADBG((__LINE__),KERN_DEBUG __FILE__"(%ld):%s (%d):"fmt,##args)
-#else
-#define DBG(fmn,args...) do {} while(0)
-#endif
-
-#define DRIVER_AUTHOR           "Joe Burks, jburks@wavicle.org"
-#define DRIVER_DESC             "ViCam WebCam Driver"
-
-/* Define these values to match your device */
-#define USB_VICAM_VENDOR_ID	0x04c1
-#define USB_VICAM_PRODUCT_ID	0x009d
-#define USB_COMPRO_VENDOR_ID	0x0602
-#define USB_COMPRO_PRODUCT_ID	0x1001
-
-#define VICAM_BYTES_PER_PIXEL   3
-#define VICAM_MAX_READ_SIZE     (512*242+128)
-#define VICAM_MAX_FRAME_SIZE    (VICAM_BYTES_PER_PIXEL*320*240)
-#define VICAM_FRAMES            2
-
-#define VICAM_HEADER_SIZE       64
-
-/* rvmalloc / rvfree copied from usbvideo.c
- *
- * Not sure why these are not yet non-statics which I can reference through
- * usbvideo.h the same as it is in 2.4.20.  I bet this will get fixed sometime
- * in the future.
- *
-*/
-static void *rvmalloc(unsigned long size)
-{
-	void *mem;
-	unsigned long adr;
-
-	size = PAGE_ALIGN(size);
-	mem = vmalloc_32(size);
-	if (!mem)
-		return NULL;
-
-	memset(mem, 0, size); /* Clear the ram out, no junk to the user */
-	adr = (unsigned long) mem;
-	while (size > 0) {
-		SetPageReserved(vmalloc_to_page((void *)adr));
-		adr += PAGE_SIZE;
-		size -= PAGE_SIZE;
-	}
-
-	return mem;
-}
-
-static void rvfree(void *mem, unsigned long size)
-{
-	unsigned long adr;
-
-	if (!mem)
-		return;
-
-	adr = (unsigned long) mem;
-	while ((long) size > 0) {
-		ClearPageReserved(vmalloc_to_page((void *)adr));
-		adr += PAGE_SIZE;
-		size -= PAGE_SIZE;
-	}
-	vfree(mem);
-}
-
-struct vicam_camera {
-	u16 shutter_speed;	// capture shutter speed
-	u16 gain;		// capture gain
-
-	u8 *raw_image;		// raw data captured from the camera
-	u8 *framebuf;		// processed data in RGB24 format
-	u8 *cntrlbuf;		// area used to send control msgs
-
-	struct video_device vdev;	// v4l video device
-	struct usb_device *udev;	// usb device
-
-	/* guard against simultaneous accesses to the camera */
-	struct mutex cam_lock;
-
-	int is_initialized;
-	u8 open_count;
-	u8 bulkEndpoint;
-	int needsDummyRead;
-};
-
-static int vicam_probe( struct usb_interface *intf, const struct usb_device_id *id);
-static void vicam_disconnect(struct usb_interface *intf);
-static void read_frame(struct vicam_camera *cam, int framenum);
-static void vicam_decode_color(const u8 *, u8 *);
-
-static int __send_control_msg(struct vicam_camera *cam,
-			      u8 request,
-			      u16 value,
-			      u16 index,
-			      unsigned char *cp,
-			      u16 size)
-{
-	int status;
-
-	/* cp must be memory that has been allocated by kmalloc */
-
-	status = usb_control_msg(cam->udev,
-				 usb_sndctrlpipe(cam->udev, 0),
-				 request,
-				 USB_DIR_OUT | USB_TYPE_VENDOR |
-				 USB_RECIP_DEVICE, value, index,
-				 cp, size, 1000);
-
-	status = min(status, 0);
-
-	if (status < 0) {
-		printk(KERN_INFO "Failed sending control message, error %d.\n",
-		       status);
-	}
-
-	return status;
-}
-
-static int send_control_msg(struct vicam_camera *cam,
-			    u8 request,
-			    u16 value,
-			    u16 index,
-			    unsigned char *cp,
-			    u16 size)
-{
-	int status = -ENODEV;
-	mutex_lock(&cam->cam_lock);
-	if (cam->udev) {
-		status = __send_control_msg(cam, request, value,
-					    index, cp, size);
-	}
-	mutex_unlock(&cam->cam_lock);
-	return status;
-}
-static int
-initialize_camera(struct vicam_camera *cam)
-{
-	int err;
-	const struct ihex_binrec *rec;
-	const struct firmware *uninitialized_var(fw);
-
-	err = reject_firmware(&fw, "/*(DEBLOBBED)*/", &cam->udev->dev);
-	if (err) {
-		printk(KERN_ERR "Failed to load \"/*(DEBLOBBED)*/\": %d\n",
-		       err);
-		return err;
-	}
-
-	for (rec = (void *)fw->data; rec; rec = ihex_next_binrec(rec)) {
-		memcpy(cam->cntrlbuf, rec->data, be16_to_cpu(rec->len));
-
-		err = send_control_msg(cam, 0xff, 0, 0,
-				       cam->cntrlbuf, be16_to_cpu(rec->len));
-		if (err)
-			break;
-	}
-
-	release_firmware(fw);
-
-	return err;
-}
-
-static int
-set_camera_power(struct vicam_camera *cam, int state)
-{
-	int status;
-
-	if ((status = send_control_msg(cam, 0x50, state, 0, NULL, 0)) < 0)
-		return status;
-
-	if (state) {
-		send_control_msg(cam, 0x55, 1, 0, NULL, 0);
-	}
-
-	return 0;
-}
-
-static long
-vicam_ioctl(struct file *file, unsigned int ioctlnr, unsigned long arg)
-{
-	void __user *user_arg = (void __user *)arg;
-	struct vicam_camera *cam = file->private_data;
-	long retval = 0;
-
-	if (!cam)
-		return -ENODEV;
-
-	switch (ioctlnr) {
-		/* query capabilities */
-	case VIDIOCGCAP:
-		{
-			struct video_capability b;
-
-			DBG("VIDIOCGCAP\n");
-			memset(&b, 0, sizeof(b));
-			strcpy(b.name, "ViCam-based Camera");
-			b.type = VID_TYPE_CAPTURE;
-			b.channels = 1;
-			b.audios = 0;
-			b.maxwidth = 320;	/* VIDEOSIZE_CIF */
-			b.maxheight = 240;
-			b.minwidth = 320;	/* VIDEOSIZE_48_48 */
-			b.minheight = 240;
-
-			if (copy_to_user(user_arg, &b, sizeof(b)))
-				retval = -EFAULT;
-
-			break;
-		}
-		/* get/set video source - we are a camera and nothing else */
-	case VIDIOCGCHAN:
-		{
-			struct video_channel v;
-
-			DBG("VIDIOCGCHAN\n");
-			if (copy_from_user(&v, user_arg, sizeof(v))) {
-				retval = -EFAULT;
-				break;
-			}
-			if (v.channel != 0) {
-				retval = -EINVAL;
-				break;
-			}
-
-			v.channel = 0;
-			strcpy(v.name, "Camera");
-			v.tuners = 0;
-			v.flags = 0;
-			v.type = VIDEO_TYPE_CAMERA;
-			v.norm = 0;
-
-			if (copy_to_user(user_arg, &v, sizeof(v)))
-				retval = -EFAULT;
-			break;
-		}
-
-	case VIDIOCSCHAN:
-		{
-			int v;
-
-			if (copy_from_user(&v, user_arg, sizeof(v)))
-				retval = -EFAULT;
-			DBG("VIDIOCSCHAN %d\n", v);
-
-			if (retval == 0 && v != 0)
-				retval = -EINVAL;
-
-			break;
-		}
-
-		/* image properties */
-	case VIDIOCGPICT:
-		{
-			struct video_picture vp;
-			DBG("VIDIOCGPICT\n");
-			memset(&vp, 0, sizeof (struct video_picture));
-			vp.brightness = cam->gain << 8;
-			vp.depth = 24;
-			vp.palette = VIDEO_PALETTE_RGB24;
-			if (copy_to_user(user_arg, &vp, sizeof (struct video_picture)))
-				retval = -EFAULT;
-			break;
-		}
-
-	case VIDIOCSPICT:
-		{
-			struct video_picture vp;
-
-			if (copy_from_user(&vp, user_arg, sizeof(vp))) {
-				retval = -EFAULT;
-				break;
-			}
-
-			DBG("VIDIOCSPICT depth = %d, pal = %d\n", vp.depth,
-			    vp.palette);
-
-			cam->gain = vp.brightness >> 8;
-
-			if (vp.depth != 24
-			    || vp.palette != VIDEO_PALETTE_RGB24)
-				retval = -EINVAL;
-
-			break;
-		}
-
-		/* get/set capture window */
-	case VIDIOCGWIN:
-		{
-			struct video_window vw;
-			vw.x = 0;
-			vw.y = 0;
-			vw.width = 320;
-			vw.height = 240;
-			vw.chromakey = 0;
-			vw.flags = 0;
-			vw.clips = NULL;
-			vw.clipcount = 0;
-
-			DBG("VIDIOCGWIN\n");
-
-			if (copy_to_user(user_arg, (void *)&vw, sizeof(vw)))
-				retval = -EFAULT;
-
-			// I'm not sure what the deal with a capture window is, it is very poorly described
-			// in the doc.  So I won't support it now.
-			break;
-		}
-
-	case VIDIOCSWIN:
-		{
-
-			struct video_window vw;
-
-			if (copy_from_user(&vw, user_arg, sizeof(vw))) {
-				retval = -EFAULT;
-				break;
-			}
-
-			DBG("VIDIOCSWIN %d x %d\n", vw.width, vw.height);
-
-			if ( vw.width != 320 || vw.height != 240 )
-				retval = -EFAULT;
-
-			break;
-		}
-
-		/* mmap interface */
-	case VIDIOCGMBUF:
-		{
-			struct video_mbuf vm;
-			int i;
-
-			DBG("VIDIOCGMBUF\n");
-			memset(&vm, 0, sizeof (vm));
-			vm.size =
-			    VICAM_MAX_FRAME_SIZE * VICAM_FRAMES;
-			vm.frames = VICAM_FRAMES;
-			for (i = 0; i < VICAM_FRAMES; i++)
-				vm.offsets[i] = VICAM_MAX_FRAME_SIZE * i;
-
-			if (copy_to_user(user_arg, (void *)&vm, sizeof(vm)))
-				retval = -EFAULT;
-
-			break;
-		}
-
-	case VIDIOCMCAPTURE:
-		{
-			struct video_mmap vm;
-			// int video_size;
-
-			if (copy_from_user((void *)&vm, user_arg, sizeof(vm))) {
-				retval = -EFAULT;
-				break;
-			}
-
-			DBG("VIDIOCMCAPTURE frame=%d, height=%d, width=%d, format=%d.\n",vm.frame,vm.width,vm.height,vm.format);
-
-			if ( vm.frame >= VICAM_FRAMES || vm.format != VIDEO_PALETTE_RGB24 )
-				retval = -EINVAL;
-
-			// in theory right here we'd start the image capturing
-			// (fill in a bulk urb and submit it asynchronously)
-			//
-			// Instead we're going to do a total hack job for now and
-			// retrieve the frame in VIDIOCSYNC
-
-			break;
-		}
-
-	case VIDIOCSYNC:
-		{
-			int frame;
-
-			if (copy_from_user((void *)&frame, user_arg, sizeof(int))) {
-				retval = -EFAULT;
-				break;
-			}
-			DBG("VIDIOCSYNC: %d\n", frame);
-
-			read_frame(cam, frame);
-			vicam_decode_color(cam->raw_image,
-					   cam->framebuf +
-					   frame * VICAM_MAX_FRAME_SIZE );
-
-			break;
-		}
-
-		/* pointless to implement overlay with this camera */
-	case VIDIOCCAPTURE:
-	case VIDIOCGFBUF:
-	case VIDIOCSFBUF:
-	case VIDIOCKEY:
-		retval = -EINVAL;
-		break;
-
-		/* tuner interface - we have none */
-	case VIDIOCGTUNER:
-	case VIDIOCSTUNER:
-	case VIDIOCGFREQ:
-	case VIDIOCSFREQ:
-		retval = -EINVAL;
-		break;
-
-		/* audio interface - we have none */
-	case VIDIOCGAUDIO:
-	case VIDIOCSAUDIO:
-		retval = -EINVAL;
-		break;
-	default:
-		retval = -ENOIOCTLCMD;
-		break;
-	}
-
-	return retval;
-}
-
-static int
-vicam_open(struct file *file)
-{
-	struct vicam_camera *cam = video_drvdata(file);
-
-	DBG("open\n");
-
-	if (!cam) {
-		printk(KERN_ERR
-		       "vicam video_device improperly initialized");
-		return -EINVAL;
-	}
-
-	/* cam_lock/open_count protects us from simultaneous opens
-	 * ... for now. we probably shouldn't rely on this fact forever.
-	 */
-
-	mutex_lock(&cam->cam_lock);
-	if (cam->open_count > 0) {
-		printk(KERN_INFO
-		       "vicam_open called on already opened camera");
-		mutex_unlock(&cam->cam_lock);
-		return -EBUSY;
-	}
-
-	cam->raw_image = kmalloc(VICAM_MAX_READ_SIZE, GFP_KERNEL);
-	if (!cam->raw_image) {
-		mutex_unlock(&cam->cam_lock);
-		return -ENOMEM;
-	}
-
-	cam->framebuf = rvmalloc(VICAM_MAX_FRAME_SIZE * VICAM_FRAMES);
-	if (!cam->framebuf) {
-		kfree(cam->raw_image);
-		mutex_unlock(&cam->cam_lock);
-		return -ENOMEM;
-	}
-
-	cam->cntrlbuf = kmalloc(PAGE_SIZE, GFP_KERNEL);
-	if (!cam->cntrlbuf) {
-		kfree(cam->raw_image);
-		rvfree(cam->framebuf, VICAM_MAX_FRAME_SIZE * VICAM_FRAMES);
-		mutex_unlock(&cam->cam_lock);
-		return -ENOMEM;
-	}
-
-	cam->needsDummyRead = 1;
-	cam->open_count++;
-
-	file->private_data = cam;
-	mutex_unlock(&cam->cam_lock);
-
-
-	// First upload firmware, then turn the camera on
-
-	if (!cam->is_initialized) {
-		initialize_camera(cam);
-
-		cam->is_initialized = 1;
-	}
-
-	set_camera_power(cam, 1);
-
-	return 0;
-}
-
-static int
-vicam_close(struct file *file)
-{
-	struct vicam_camera *cam = file->private_data;
-	int open_count;
-	struct usb_device *udev;
-
-	DBG("close\n");
-
-	/* it's not the end of the world if
-	 * we fail to turn the camera off.
-	 */
-
-	set_camera_power(cam, 0);
-
-	kfree(cam->raw_image);
-	rvfree(cam->framebuf, VICAM_MAX_FRAME_SIZE * VICAM_FRAMES);
-	kfree(cam->cntrlbuf);
-
-	mutex_lock(&cam->cam_lock);
-
-	cam->open_count--;
-	open_count = cam->open_count;
-	udev = cam->udev;
-
-	mutex_unlock(&cam->cam_lock);
-
-	if (!open_count && !udev) {
-		kfree(cam);
-	}
-
-	return 0;
-}
-
-static void vicam_decode_color(const u8 *data, u8 *rgb)
-{
-	/* vicam_decode_color - Convert from Vicam Y-Cr-Cb to RGB
-	 * Copyright (C) 2002 Monroe Williams (monroe@pobox.com)
-	 */
-
-	int i, prevY, nextY;
-
-	prevY = 512;
-	nextY = 512;
-
-	data += VICAM_HEADER_SIZE;
-
-	for( i = 0; i < 240; i++, data += 512 ) {
-		const int y = ( i * 242 ) / 240;
-
-		int j, prevX, nextX;
-		int Y, Cr, Cb;
-
-		if ( y == 242 - 1 ) {
-			nextY = -512;
-		}
-
-		prevX = 1;
-		nextX = 1;
-
-		for ( j = 0; j < 320; j++, rgb += 3 ) {
-			const int x = ( j * 512 ) / 320;
-			const u8 * const src = &data[x];
-
-			if ( x == 512 - 1 ) {
-				nextX = -1;
-			}
-
-			Cr = ( src[prevX] - src[0] ) +
-				( src[nextX] - src[0] );
-			Cr /= 2;
-
-			Cb = ( src[prevY] - src[prevX + prevY] ) +
-				( src[prevY] - src[nextX + prevY] ) +
-				( src[nextY] - src[prevX + nextY] ) +
-				( src[nextY] - src[nextX + nextY] );
-			Cb /= 4;
-
-			Y = 1160 * ( src[0] + ( Cr / 2 ) - 16 );
-
-			if ( i & 1 ) {
-				int Ct = Cr;
-				Cr = Cb;
-				Cb = Ct;
-			}
-
-			if ( ( x ^ i ) & 1 ) {
-				Cr = -Cr;
-				Cb = -Cb;
-			}
-
-			rgb[0] = clamp( ( ( Y + ( 2017 * Cb ) ) +
-					500 ) / 900, 0, 255 );
-			rgb[1] = clamp( ( ( Y - ( 392 * Cb ) -
-					  ( 813 * Cr ) ) +
-					  500 ) / 1000, 0, 255 );
-			rgb[2] = clamp( ( ( Y + ( 1594 * Cr ) ) +
-					500 ) / 1300, 0, 255 );
-
-			prevX = -1;
-		}
-
-		prevY = -512;
-	}
-}
-
-static void
-read_frame(struct vicam_camera *cam, int framenum)
-{
-	unsigned char *request = cam->cntrlbuf;
-	int realShutter;
-	int n;
-	int actual_length;
-
-	if (cam->needsDummyRead) {
-		cam->needsDummyRead = 0;
-		read_frame(cam, framenum);
-	}
-
-	memset(request, 0, 16);
-	request[0] = cam->gain;	// 0 = 0% gain, FF = 100% gain
-
-	request[1] = 0;	// 512x242 capture
-
-	request[2] = 0x90;	// the function of these two bytes
-	request[3] = 0x07;	// is not yet understood
-
-	if (cam->shutter_speed > 60) {
-		// Short exposure
-		realShutter =
-		    ((-15631900 / cam->shutter_speed) + 260533) / 1000;
-		request[4] = realShutter & 0xFF;
-		request[5] = (realShutter >> 8) & 0xFF;
-		request[6] = 0x03;
-		request[7] = 0x01;
-	} else {
-		// Long exposure
-		realShutter = 15600 / cam->shutter_speed - 1;
-		request[4] = 0;
-		request[5] = 0;
-		request[6] = realShutter & 0xFF;
-		request[7] = realShutter >> 8;
-	}
-
-	// Per John Markus Bjørndalen, byte at index 8 causes problems if it isn't 0
-	request[8] = 0;
-	// bytes 9-15 do not seem to affect exposure or image quality
-
-	mutex_lock(&cam->cam_lock);
-
-	if (!cam->udev) {
-		goto done;
-	}
-
-	n = __send_control_msg(cam, 0x51, 0x80, 0, request, 16);
-
-	if (n < 0) {
-		printk(KERN_ERR
-		       " Problem sending frame capture control message");
-		goto done;
-	}
-
-	n = usb_bulk_msg(cam->udev,
-			 usb_rcvbulkpipe(cam->udev, cam->bulkEndpoint),
-			 cam->raw_image,
-			 512 * 242 + 128, &actual_length, 10000);
-
-	if (n < 0) {
-		printk(KERN_ERR "Problem during bulk read of frame data: %d\n",
-		       n);
-	}
-
- done:
-	mutex_unlock(&cam->cam_lock);
-}
-
-static ssize_t
-vicam_read( struct file *file, char __user *buf, size_t count, loff_t *ppos )
-{
-	struct vicam_camera *cam = file->private_data;
-
-	DBG("read %d bytes.\n", (int) count);
-
-	if (*ppos >= VICAM_MAX_FRAME_SIZE) {
-		*ppos = 0;
-		return 0;
-	}
-
-	if (*ppos == 0) {
-		read_frame(cam, 0);
-		vicam_decode_color(cam->raw_image,
-				   cam->framebuf +
-				   0 * VICAM_MAX_FRAME_SIZE);
-	}
-
-	count = min_t(size_t, count, VICAM_MAX_FRAME_SIZE - *ppos);
-
-	if (copy_to_user(buf, &cam->framebuf[*ppos], count)) {
-		count = -EFAULT;
-	} else {
-		*ppos += count;
-	}
-
-	if (count == VICAM_MAX_FRAME_SIZE) {
-		*ppos = 0;
-	}
-
-	return count;
-}
-
-
-static int
-vicam_mmap(struct file *file, struct vm_area_struct *vma)
-{
-	// TODO: allocate the raw frame buffer if necessary
-	unsigned long page, pos;
-	unsigned long start = vma->vm_start;
-	unsigned long size  = vma->vm_end-vma->vm_start;
-	struct vicam_camera *cam = file->private_data;
-
-	if (!cam)
-		return -ENODEV;
-
-	DBG("vicam_mmap: %ld\n", size);
-
-	/* We let mmap allocate as much as it wants because Linux was adding 2048 bytes
-	 * to the size the application requested for mmap and it was screwing apps up.
-	 if (size > VICAM_FRAMES*VICAM_MAX_FRAME_SIZE)
-	 return -EINVAL;
-	 */
-
-	pos = (unsigned long)cam->framebuf;
-	while (size > 0) {
-		page = vmalloc_to_pfn((void *)pos);
-		if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED))
-			return -EAGAIN;
-
-		start += PAGE_SIZE;
-		pos += PAGE_SIZE;
-		if (size > PAGE_SIZE)
-			size -= PAGE_SIZE;
-		else
-			size = 0;
-	}
-
-	return 0;
-}
-
-static const struct v4l2_file_operations vicam_fops = {
-	.owner		= THIS_MODULE,
-	.open		= vicam_open,
-	.release	= vicam_close,
-	.read		= vicam_read,
-	.mmap		= vicam_mmap,
-	.ioctl		= vicam_ioctl,
-};
-
-static struct video_device vicam_template = {
-	.name 		= "ViCam-based USB Camera",
-	.fops 		= &vicam_fops,
-	.release 	= video_device_release_empty,
-};
-
-/* table of devices that work with this driver */
-static struct usb_device_id vicam_table[] = {
-	{USB_DEVICE(USB_VICAM_VENDOR_ID, USB_VICAM_PRODUCT_ID)},
-	{USB_DEVICE(USB_COMPRO_VENDOR_ID, USB_COMPRO_PRODUCT_ID)},
-	{}			/* Terminating entry */
-};
-
-MODULE_DEVICE_TABLE(usb, vicam_table);
-
-static struct usb_driver vicam_driver = {
-	.name		= "vicam",
-	.probe		= vicam_probe,
-	.disconnect	= vicam_disconnect,
-	.id_table	= vicam_table
-};
-
-/**
- *	vicam_probe
- *	@intf: the interface
- *	@id: the device id
- *
- *	Called by the usb core when a new device is connected that it thinks
- *	this driver might be interested in.
- */
-static int
-vicam_probe( struct usb_interface *intf, const struct usb_device_id *id)
-{
-	struct usb_device *dev = interface_to_usbdev(intf);
-	int bulkEndpoint = 0;
-	const struct usb_host_interface *interface;
-	const struct usb_endpoint_descriptor *endpoint;
-	struct vicam_camera *cam;
-
-	printk(KERN_INFO "ViCam based webcam connected\n");
-
-	interface = intf->cur_altsetting;
-
-	DBG(KERN_DEBUG "Interface %d. has %u. endpoints!\n",
-	       interface->desc.bInterfaceNumber, (unsigned) (interface->desc.bNumEndpoints));
-	endpoint = &interface->endpoint[0].desc;
-
-	if (usb_endpoint_is_bulk_in(endpoint)) {
-		/* we found a bulk in endpoint */
-		bulkEndpoint = endpoint->bEndpointAddress;
-	} else {
-		printk(KERN_ERR
-		       "No bulk in endpoint was found ?! (this is bad)\n");
-	}
-
-	if ((cam =
-	     kzalloc(sizeof (struct vicam_camera), GFP_KERNEL)) == NULL) {
-		printk(KERN_WARNING
-		       "could not allocate kernel memory for vicam_camera struct\n");
-		return -ENOMEM;
-	}
-
-
-	cam->shutter_speed = 15;
-
-	mutex_init(&cam->cam_lock);
-
-	memcpy(&cam->vdev, &vicam_template, sizeof(vicam_template));
-	video_set_drvdata(&cam->vdev, cam);
-
-	cam->udev = dev;
-	cam->bulkEndpoint = bulkEndpoint;
-
-	if (video_register_device(&cam->vdev, VFL_TYPE_GRABBER, -1) < 0) {
-		kfree(cam);
-		printk(KERN_WARNING "video_register_device failed\n");
-		return -EIO;
-	}
-
-	printk(KERN_INFO "ViCam webcam driver now controlling device %s\n",
-		video_device_node_name(&cam->vdev));
-
-	usb_set_intfdata (intf, cam);
-
-	return 0;
-}
-
-static void
-vicam_disconnect(struct usb_interface *intf)
-{
-	int open_count;
-	struct vicam_camera *cam = usb_get_intfdata (intf);
-	usb_set_intfdata (intf, NULL);
-
-	/* we must unregister the device before taking its
-	 * cam_lock. This is because the video open call
-	 * holds the same lock as video unregister. if we
-	 * unregister inside of the cam_lock and open also
-	 * uses the cam_lock, we get deadlock.
-	 */
-
-	video_unregister_device(&cam->vdev);
-
-	/* stop the camera from being used */
-
-	mutex_lock(&cam->cam_lock);
-
-	/* mark the camera as gone */
-
-	cam->udev = NULL;
-
-	/* the only thing left to do is synchronize with
-	 * our close/release function on who should release
-	 * the camera memory. if there are any users using the
-	 * camera, it's their job. if there are no users,
-	 * it's ours.
-	 */
-
-	open_count = cam->open_count;
-
-	mutex_unlock(&cam->cam_lock);
-
-	if (!open_count) {
-		kfree(cam);
-	}
-
-	printk(KERN_DEBUG "ViCam-based WebCam disconnected\n");
-}
-
-/*
- */
-static int __init
-usb_vicam_init(void)
-{
-	int retval;
-	DBG(KERN_INFO "ViCam-based WebCam driver startup\n");
-	retval = usb_register(&vicam_driver);
-	if (retval)
-		printk(KERN_WARNING "usb_register failed!\n");
-	return retval;
-}
-
-static void __exit
-usb_vicam_exit(void)
-{
-	DBG(KERN_INFO
-	       "ViCam-based WebCam driver shutdown\n");
-
-	usb_deregister(&vicam_driver);
-}
-
-module_init(usb_vicam_init);
-module_exit(usb_vicam_exit);
-
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE("GPL");
-/*(DEBLOBBED)*/
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/usbvision/usbvision-cards.c linux-libre-2.6.38-gnu1/drivers/media/video/usbvision/usbvision-cards.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/usbvision/usbvision-cards.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/usbvision/usbvision-cards.c	2011-03-14 21:20:32.000000000 -0400
@@ -32,1072 +32,1072 @@
 /* Supported Devices: A table for usbvision.c*/
 struct usbvision_device_data_st  usbvision_device_data[] = {
 	[XANBOO] = {
-		.Interface     = -1,
-		.Codec         = CODEC_SAA7113,
-		.VideoChannels = 4,
-		.VideoNorm     = V4L2_STD_NTSC,
-		.AudioChannels = 1,
-		.Radio         = 0,
-		.vbi           = 1,
-		.Tuner         = 0,
-		.TunerType     = 0,
-		.X_Offset      = -1,
-		.Y_Offset      = -1,
-		.ModelString   = "Xanboo",
+		.interface      = -1,
+		.codec          = CODEC_SAA7113,
+		.video_channels = 4,
+		.video_norm     = V4L2_STD_NTSC,
+		.audio_channels = 1,
+		.radio          = 0,
+		.vbi            = 1,
+		.tuner          = 0,
+		.tuner_type     = 0,
+		.x_offset       = -1,
+		.y_offset       = -1,
+		.model_string   = "Xanboo",
 	},
 	[BELKIN_VIDEOBUS_II] = {
-		.Interface     = -1,
-		.Codec         = CODEC_SAA7113,
-		.VideoChannels = 2,
-		.VideoNorm     = V4L2_STD_PAL,
-		.AudioChannels = 1,
-		.Radio         = 0,
-		.vbi           = 1,
-		.Tuner         = 0,
-		.TunerType     = 0,
-		.X_Offset      = 0,
-		.Y_Offset      = 3,
-		.Dvi_yuv_override = 1,
-		.Dvi_yuv       = 7,
-		.ModelString   = "Belkin USB VideoBus II Adapter",
+		.interface      = -1,
+		.codec          = CODEC_SAA7113,
+		.video_channels = 2,
+		.video_norm     = V4L2_STD_PAL,
+		.audio_channels = 1,
+		.radio          = 0,
+		.vbi            = 1,
+		.tuner          = 0,
+		.tuner_type     = 0,
+		.x_offset       = 0,
+		.y_offset       = 3,
+		.dvi_yuv_override = 1,
+		.dvi_yuv        = 7,
+		.model_string   = "Belkin USB VideoBus II Adapter",
 	},
 	[BELKIN_VIDEOBUS] = {
-		.Interface     = -1,
-		.Codec         = CODEC_SAA7111,
-		.VideoChannels = 2,
-		.VideoNorm     = V4L2_STD_NTSC,
-		.AudioChannels = 1,
-		.Radio         = 0,
-		.vbi           = 1,
-		.Tuner         = 0,
-		.TunerType     = 0,
-		.X_Offset      = -1,
-		.Y_Offset      = -1,
-		.ModelString   = "Belkin Components USB VideoBus",
+		.interface      = -1,
+		.codec          = CODEC_SAA7111,
+		.video_channels = 2,
+		.video_norm     = V4L2_STD_NTSC,
+		.audio_channels = 1,
+		.radio          = 0,
+		.vbi            = 1,
+		.tuner          = 0,
+		.tuner_type     = 0,
+		.x_offset       = -1,
+		.y_offset       = -1,
+		.model_string   = "Belkin Components USB VideoBus",
 	},
 	[BELKIN_USB_VIDEOBUS_II] = {
-		.Interface     = -1,
-		.Codec         = CODEC_SAA7113,
-		.VideoChannels = 2,
-		.VideoNorm     = V4L2_STD_NTSC,
-		.AudioChannels = 1,
-		.Radio         = 0,
-		.vbi           = 1,
-		.Tuner         = 0,
-		.TunerType     = 0,
-		.X_Offset      = 0,
-		.Y_Offset      = 3,
-		.Dvi_yuv_override = 1,
-		.Dvi_yuv       = 7,
-		.ModelString   = "Belkin USB VideoBus II",
+		.interface      = -1,
+		.codec          = CODEC_SAA7113,
+		.video_channels = 2,
+		.video_norm     = V4L2_STD_NTSC,
+		.audio_channels = 1,
+		.radio          = 0,
+		.vbi            = 1,
+		.tuner          = 0,
+		.tuner_type     = 0,
+		.x_offset       = 0,
+		.y_offset       = 3,
+		.dvi_yuv_override = 1,
+		.dvi_yuv        = 7,
+		.model_string   = "Belkin USB VideoBus II",
 	},
 	[ECHOFX_INTERVIEW_LITE] = {
-		.Interface     = 0,
-		.Codec         = CODEC_SAA7111,
-		.VideoChannels = 2,
-		.VideoNorm     = V4L2_STD_PAL,
-		.AudioChannels = 0,
-		.Radio         = 0,
-		.vbi           = 1,
-		.Tuner         = 0,
-		.TunerType     = 0,
-		.X_Offset      = -1,
-		.Y_Offset      = -1,
-		.Dvi_yuv_override = 1,
-		.Dvi_yuv       = 7,
-		.ModelString   = "echoFX InterView Lite",
+		.interface      = 0,
+		.codec          = CODEC_SAA7111,
+		.video_channels = 2,
+		.video_norm     = V4L2_STD_PAL,
+		.audio_channels = 0,
+		.radio          = 0,
+		.vbi            = 1,
+		.tuner          = 0,
+		.tuner_type     = 0,
+		.x_offset       = -1,
+		.y_offset       = -1,
+		.dvi_yuv_override = 1,
+		.dvi_yuv        = 7,
+		.model_string   = "echoFX InterView Lite",
 	},
 	[USBGEAR_USBG_V1] = {
-		.Interface     = -1,
-		.Codec         = CODEC_SAA7111,
-		.VideoChannels = 2,
-		.VideoNorm     = V4L2_STD_NTSC,
-		.AudioChannels = 1,
-		.Radio         = 0,
-		.vbi           = 1,
-		.Tuner         = 0,
-		.TunerType     = 0,
-		.X_Offset      = -1,
-		.Y_Offset      = -1,
-		.ModelString   = "USBGear USBG-V1 resp. HAMA USB",
+		.interface      = -1,
+		.codec          = CODEC_SAA7111,
+		.video_channels = 2,
+		.video_norm     = V4L2_STD_NTSC,
+		.audio_channels = 1,
+		.radio          = 0,
+		.vbi            = 1,
+		.tuner          = 0,
+		.tuner_type     = 0,
+		.x_offset       = -1,
+		.y_offset       = -1,
+		.model_string   = "USBGear USBG-V1 resp. HAMA USB",
 	},
 	[D_LINK_V100] = {
-		.Interface     = -1,
-		.Codec         = CODEC_SAA7113,
-		.VideoChannels = 4,
-		.VideoNorm     = V4L2_STD_NTSC,
-		.AudioChannels = 0,
-		.Radio         = 0,
-		.vbi           = 1,
-		.Tuner         = 0,
-		.TunerType     = 0,
-		.X_Offset      = 0,
-		.Y_Offset      = 3,
-		.Dvi_yuv_override = 1,
-		.Dvi_yuv       = 7,
-		.ModelString   = "D-Link V100",
+		.interface      = -1,
+		.codec          = CODEC_SAA7113,
+		.video_channels = 4,
+		.video_norm     = V4L2_STD_NTSC,
+		.audio_channels = 0,
+		.radio          = 0,
+		.vbi            = 1,
+		.tuner          = 0,
+		.tuner_type     = 0,
+		.x_offset       = 0,
+		.y_offset       = 3,
+		.dvi_yuv_override = 1,
+		.dvi_yuv        = 7,
+		.model_string   = "D-Link V100",
 	},
 	[X10_USB_CAMERA] = {
-		.Interface     = -1,
-		.Codec         = CODEC_SAA7111,
-		.VideoChannels = 2,
-		.VideoNorm     = V4L2_STD_NTSC,
-		.AudioChannels = 1,
-		.Radio         = 0,
-		.vbi           = 1,
-		.Tuner         = 0,
-		.TunerType     = 0,
-		.X_Offset      = -1,
-		.Y_Offset      = -1,
-		.ModelString   = "X10 USB Camera",
+		.interface      = -1,
+		.codec          = CODEC_SAA7111,
+		.video_channels = 2,
+		.video_norm     = V4L2_STD_NTSC,
+		.audio_channels = 1,
+		.radio          = 0,
+		.vbi            = 1,
+		.tuner          = 0,
+		.tuner_type     = 0,
+		.x_offset       = -1,
+		.y_offset       = -1,
+		.model_string   = "X10 USB Camera",
 	},
 	[HPG_WINTV_LIVE_PAL_BG] = {
-		.Interface     = -1,
-		.Codec         = CODEC_SAA7111,
-		.VideoChannels = 2,
-		.VideoNorm     = V4L2_STD_PAL,
-		.AudioChannels = 1,
-		.Radio         = 0,
-		.vbi           = 1,
-		.Tuner         = 0,
-		.TunerType     = 0,
-		.X_Offset      = -1,
-		.Y_Offset      = 3,
-		.Dvi_yuv_override = 1,
-		.Dvi_yuv       = 7,
-		.ModelString   = "Hauppauge WinTV USB Live (PAL B/G)",
+		.interface      = -1,
+		.codec          = CODEC_SAA7111,
+		.video_channels = 2,
+		.video_norm     = V4L2_STD_PAL,
+		.audio_channels = 1,
+		.radio          = 0,
+		.vbi            = 1,
+		.tuner          = 0,
+		.tuner_type     = 0,
+		.x_offset       = -1,
+		.y_offset       = 3,
+		.dvi_yuv_override = 1,
+		.dvi_yuv        = 7,
+		.model_string   = "Hauppauge WinTV USB Live (PAL B/G)",
 	},
 	[HPG_WINTV_LIVE_PRO_NTSC_MN] = {
-		.Interface     = -1,
-		.Codec         = CODEC_SAA7113,
-		.VideoChannels = 2,
-		.VideoNorm     = V4L2_STD_NTSC,
-		.AudioChannels = 0,
-		.Radio         = 0,
-		.vbi           = 1,
-		.Tuner         = 0,
-		.TunerType     = 0,
-		.X_Offset      = 0,
-		.Y_Offset      = 3,
-		.Dvi_yuv_override = 1,
-		.Dvi_yuv       = 7,
-		.ModelString   = "Hauppauge WinTV USB Live Pro (NTSC M/N)",
+		.interface      = -1,
+		.codec          = CODEC_SAA7113,
+		.video_channels = 2,
+		.video_norm     = V4L2_STD_NTSC,
+		.audio_channels = 0,
+		.radio          = 0,
+		.vbi            = 1,
+		.tuner          = 0,
+		.tuner_type     = 0,
+		.x_offset       = 0,
+		.y_offset       = 3,
+		.dvi_yuv_override = 1,
+		.dvi_yuv        = 7,
+		.model_string   = "Hauppauge WinTV USB Live Pro (NTSC M/N)",
 	},
 	[ZORAN_PMD_NOGATECH] = {
-		.Interface     = -1,
-		.Codec         = CODEC_SAA7113,
-		.VideoChannels = 2,
-		.VideoNorm     = V4L2_STD_PAL,
-		.AudioChannels = 2,
-		.Radio         = 0,
-		.vbi           = 1,
-		.Tuner         = 0,
-		.TunerType     = 0,
-		.X_Offset      = 0,
-		.Y_Offset      = 3,
-		.Dvi_yuv_override = 1,
-		.Dvi_yuv       = 7,
-		.ModelString   = "Zoran Co. PMD (Nogatech) AV-grabber Manhattan",
+		.interface      = -1,
+		.codec          = CODEC_SAA7113,
+		.video_channels = 2,
+		.video_norm     = V4L2_STD_PAL,
+		.audio_channels = 2,
+		.radio          = 0,
+		.vbi            = 1,
+		.tuner          = 0,
+		.tuner_type     = 0,
+		.x_offset       = 0,
+		.y_offset       = 3,
+		.dvi_yuv_override = 1,
+		.dvi_yuv        = 7,
+		.model_string   = "Zoran Co. PMD (Nogatech) AV-grabber Manhattan",
 	},
 	[NOGATECH_USB_TV_NTSC_FM] = {
-		.Interface     = -1,
-		.Codec         = CODEC_SAA7111,
-		.VideoChannels = 3,
-		.VideoNorm     = V4L2_STD_NTSC,
-		.AudioChannels = 1,
-		.Radio         = 1,
-		.vbi           = 1,
-		.Tuner         = 1,
-		.TunerType     = TUNER_PHILIPS_NTSC_M,
-		.X_Offset      = -1,
-		.Y_Offset      = 20,
-		.ModelString   = "Nogatech USB-TV (NTSC) FM",
+		.interface      = -1,
+		.codec          = CODEC_SAA7111,
+		.video_channels = 3,
+		.video_norm     = V4L2_STD_NTSC,
+		.audio_channels = 1,
+		.radio          = 1,
+		.vbi            = 1,
+		.tuner          = 1,
+		.tuner_type     = TUNER_PHILIPS_NTSC_M,
+		.x_offset       = -1,
+		.y_offset       = 20,
+		.model_string   = "Nogatech USB-TV (NTSC) FM",
 	},
 	[PNY_USB_TV_NTSC_FM] = {
-		.Interface     = -1,
-		.Codec         = CODEC_SAA7111,
-		.VideoChannels = 3,
-		.VideoNorm     = V4L2_STD_NTSC,
-		.AudioChannels = 1,
-		.Radio         = 1,
-		.vbi           = 1,
-		.Tuner         = 1,
-		.TunerType     = TUNER_PHILIPS_NTSC_M,
-		.X_Offset      = -1,
-		.Y_Offset      = 20,
-		.ModelString   = "PNY USB-TV (NTSC) FM",
+		.interface      = -1,
+		.codec          = CODEC_SAA7111,
+		.video_channels = 3,
+		.video_norm     = V4L2_STD_NTSC,
+		.audio_channels = 1,
+		.radio          = 1,
+		.vbi            = 1,
+		.tuner          = 1,
+		.tuner_type     = TUNER_PHILIPS_NTSC_M,
+		.x_offset       = -1,
+		.y_offset       = 20,
+		.model_string   = "PNY USB-TV (NTSC) FM",
 	},
 	[PV_PLAYTV_USB_PRO_PAL_FM] = {
-		.Interface     = 0,
-		.Codec         = CODEC_SAA7113,
-		.VideoChannels = 3,
-		.VideoNorm     = V4L2_STD_PAL,
-		.AudioChannels = 1,
-		.Radio         = 1,
-		.vbi           = 1,
-		.Tuner         = 1,
-		.TunerType     = TUNER_PHILIPS_PAL,
-		.X_Offset      = 0,
-		.Y_Offset      = 3,
-		.Dvi_yuv_override = 1,
-		.Dvi_yuv       = 7,
-		.ModelString   = "PixelView PlayTv-USB PRO (PAL) FM",
+		.interface      = 0,
+		.codec          = CODEC_SAA7113,
+		.video_channels = 3,
+		.video_norm     = V4L2_STD_PAL,
+		.audio_channels = 1,
+		.radio          = 1,
+		.vbi            = 1,
+		.tuner          = 1,
+		.tuner_type     = TUNER_PHILIPS_PAL,
+		.x_offset       = 0,
+		.y_offset       = 3,
+		.dvi_yuv_override = 1,
+		.dvi_yuv        = 7,
+		.model_string   = "PixelView PlayTv-USB PRO (PAL) FM",
 	},
 	[ZT_721] = {
-		.Interface     = 0,
-		.Codec         = CODEC_SAA7113,
-		.VideoChannels = 3,
-		.VideoNorm     = V4L2_STD_PAL,
-		.AudioChannels = 1,
-		.Radio         = 1,
-		.vbi           = 1,
-		.Tuner         = 1,
-		.TunerType     = TUNER_PHILIPS_PAL,
-		.X_Offset      = 0,
-		.Y_Offset      = 3,
-		.Dvi_yuv_override = 1,
-		.Dvi_yuv       = 7,
-		.ModelString   = "ZTV ZT-721 2.4GHz USB A/V Receiver",
+		.interface      = 0,
+		.codec          = CODEC_SAA7113,
+		.video_channels = 3,
+		.video_norm     = V4L2_STD_PAL,
+		.audio_channels = 1,
+		.radio          = 1,
+		.vbi            = 1,
+		.tuner          = 1,
+		.tuner_type     = TUNER_PHILIPS_PAL,
+		.x_offset       = 0,
+		.y_offset       = 3,
+		.dvi_yuv_override = 1,
+		.dvi_yuv        = 7,
+		.model_string   = "ZTV ZT-721 2.4GHz USB A/V Receiver",
 	},
 	[HPG_WINTV_NTSC_MN] = {
-		.Interface     = -1,
-		.Codec         = CODEC_SAA7111,
-		.VideoChannels = 3,
-		.VideoNorm     = V4L2_STD_NTSC,
-		.AudioChannels = 1,
-		.Radio         = 0,
-		.vbi           = 1,
-		.Tuner         = 1,
-		.TunerType     = TUNER_PHILIPS_NTSC_M,
-		.X_Offset      = -1,
-		.Y_Offset      = 20,
-		.ModelString   = "Hauppauge WinTV USB (NTSC M/N)",
+		.interface      = -1,
+		.codec          = CODEC_SAA7111,
+		.video_channels = 3,
+		.video_norm     = V4L2_STD_NTSC,
+		.audio_channels = 1,
+		.radio          = 0,
+		.vbi            = 1,
+		.tuner          = 1,
+		.tuner_type     = TUNER_PHILIPS_NTSC_M,
+		.x_offset       = -1,
+		.y_offset       = 20,
+		.model_string   = "Hauppauge WinTV USB (NTSC M/N)",
 	},
 	[HPG_WINTV_PAL_BG] = {
-		.Interface     = -1,
-		.Codec         = CODEC_SAA7111,
-		.VideoChannels = 3,
-		.VideoNorm     = V4L2_STD_PAL,
-		.AudioChannels = 1,
-		.Radio         = 0,
-		.vbi           = 1,
-		.Tuner         = 1,
-		.TunerType     = TUNER_PHILIPS_PAL,
-		.X_Offset      = -1,
-		.Y_Offset      = -1,
-		.ModelString   = "Hauppauge WinTV USB (PAL B/G)",
+		.interface      = -1,
+		.codec          = CODEC_SAA7111,
+		.video_channels = 3,
+		.video_norm     = V4L2_STD_PAL,
+		.audio_channels = 1,
+		.radio          = 0,
+		.vbi            = 1,
+		.tuner          = 1,
+		.tuner_type     = TUNER_PHILIPS_PAL,
+		.x_offset       = -1,
+		.y_offset       = -1,
+		.model_string   = "Hauppauge WinTV USB (PAL B/G)",
 	},
 	[HPG_WINTV_PAL_I] = {
-		.Interface     = -1,
-		.Codec         = CODEC_SAA7111,
-		.VideoChannels = 3,
-		.VideoNorm     = V4L2_STD_PAL,
-		.AudioChannels = 1,
-		.Radio         = 0,
-		.vbi           = 1,
-		.Tuner         = 1,
-		.TunerType     = TUNER_PHILIPS_PAL,
-		.X_Offset      = -1,
-		.Y_Offset      = -1,
-		.ModelString   = "Hauppauge WinTV USB (PAL I)",
+		.interface      = -1,
+		.codec          = CODEC_SAA7111,
+		.video_channels = 3,
+		.video_norm     = V4L2_STD_PAL,
+		.audio_channels = 1,
+		.radio          = 0,
+		.vbi            = 1,
+		.tuner          = 1,
+		.tuner_type     = TUNER_PHILIPS_PAL,
+		.x_offset       = -1,
+		.y_offset       = -1,
+		.model_string   = "Hauppauge WinTV USB (PAL I)",
 	},
 	[HPG_WINTV_PAL_SECAM_L] = {
-		.Interface     = -1,
-		.Codec         = CODEC_SAA7111,
-		.VideoChannels = 3,
-		.VideoNorm     = V4L2_STD_SECAM,
-		.AudioChannels = 1,
-		.Radio         = 0,
-		.vbi           = 1,
-		.Tuner         = 1,
-		.TunerType     = TUNER_PHILIPS_SECAM,
-		.X_Offset      = 0x80,
-		.Y_Offset      = 0x16,
-		.ModelString   = "Hauppauge WinTV USB (PAL/SECAM L)",
+		.interface      = -1,
+		.codec          = CODEC_SAA7111,
+		.video_channels = 3,
+		.video_norm     = V4L2_STD_SECAM,
+		.audio_channels = 1,
+		.radio          = 0,
+		.vbi            = 1,
+		.tuner          = 1,
+		.tuner_type     = TUNER_PHILIPS_SECAM,
+		.x_offset       = 0x80,
+		.y_offset       = 0x16,
+		.model_string   = "Hauppauge WinTV USB (PAL/SECAM L)",
 	},
 	[HPG_WINTV_PAL_D_K] = {
-		.Interface     = -1,
-		.Codec         = CODEC_SAA7111,
-		.VideoChannels = 3,
-		.VideoNorm     = V4L2_STD_PAL,
-		.AudioChannels = 1,
-		.Radio         = 0,
-		.vbi           = 1,
-		.Tuner         = 1,
-		.TunerType     = TUNER_PHILIPS_PAL,
-		.X_Offset      = -1,
-		.Y_Offset      = -1,
-		.ModelString   = "Hauppauge WinTV USB (PAL D/K)",
+		.interface      = -1,
+		.codec          = CODEC_SAA7111,
+		.video_channels = 3,
+		.video_norm     = V4L2_STD_PAL,
+		.audio_channels = 1,
+		.radio          = 0,
+		.vbi            = 1,
+		.tuner          = 1,
+		.tuner_type     = TUNER_PHILIPS_PAL,
+		.x_offset       = -1,
+		.y_offset       = -1,
+		.model_string   = "Hauppauge WinTV USB (PAL D/K)",
 	},
 	[HPG_WINTV_NTSC_FM] = {
-		.Interface     = -1,
-		.Codec         = CODEC_SAA7111,
-		.VideoChannels = 3,
-		.VideoNorm     = V4L2_STD_NTSC,
-		.AudioChannels = 1,
-		.Radio         = 1,
-		.vbi           = 1,
-		.Tuner         = 1,
-		.TunerType     = TUNER_PHILIPS_NTSC_M,
-		.X_Offset      = -1,
-		.Y_Offset      = -1,
-		.ModelString   = "Hauppauge WinTV USB (NTSC FM)",
+		.interface      = -1,
+		.codec          = CODEC_SAA7111,
+		.video_channels = 3,
+		.video_norm     = V4L2_STD_NTSC,
+		.audio_channels = 1,
+		.radio          = 1,
+		.vbi            = 1,
+		.tuner          = 1,
+		.tuner_type     = TUNER_PHILIPS_NTSC_M,
+		.x_offset       = -1,
+		.y_offset       = -1,
+		.model_string   = "Hauppauge WinTV USB (NTSC FM)",
 	},
 	[HPG_WINTV_PAL_BG_FM] = {
-		.Interface     = -1,
-		.Codec         = CODEC_SAA7111,
-		.VideoChannels = 3,
-		.VideoNorm     = V4L2_STD_PAL,
-		.AudioChannels = 1,
-		.Radio         = 1,
-		.vbi           = 1,
-		.Tuner         = 1,
-		.TunerType     = TUNER_PHILIPS_PAL,
-		.X_Offset      = -1,
-		.Y_Offset      = -1,
-		.ModelString   = "Hauppauge WinTV USB (PAL B/G FM)",
+		.interface      = -1,
+		.codec          = CODEC_SAA7111,
+		.video_channels = 3,
+		.video_norm     = V4L2_STD_PAL,
+		.audio_channels = 1,
+		.radio          = 1,
+		.vbi            = 1,
+		.tuner          = 1,
+		.tuner_type     = TUNER_PHILIPS_PAL,
+		.x_offset       = -1,
+		.y_offset       = -1,
+		.model_string   = "Hauppauge WinTV USB (PAL B/G FM)",
 	},
 	[HPG_WINTV_PAL_I_FM] = {
-		.Interface     = -1,
-		.Codec         = CODEC_SAA7111,
-		.VideoChannels = 3,
-		.VideoNorm     = V4L2_STD_PAL,
-		.AudioChannels = 1,
-		.Radio         = 1,
-		.vbi           = 1,
-		.Tuner         = 1,
-		.TunerType     = TUNER_PHILIPS_PAL,
-		.X_Offset      = -1,
-		.Y_Offset      = -1,
-		.ModelString   = "Hauppauge WinTV USB (PAL I FM)",
+		.interface      = -1,
+		.codec          = CODEC_SAA7111,
+		.video_channels = 3,
+		.video_norm     = V4L2_STD_PAL,
+		.audio_channels = 1,
+		.radio          = 1,
+		.vbi            = 1,
+		.tuner          = 1,
+		.tuner_type     = TUNER_PHILIPS_PAL,
+		.x_offset       = -1,
+		.y_offset       = -1,
+		.model_string   = "Hauppauge WinTV USB (PAL I FM)",
 	},
 	[HPG_WINTV_PAL_D_K_FM] = {
-		.Interface     = -1,
-		.Codec         = CODEC_SAA7111,
-		.VideoChannels = 3,
-		.VideoNorm     = V4L2_STD_PAL,
-		.AudioChannels = 1,
-		.Radio         = 1,
-		.vbi           = 1,
-		.Tuner         = 1,
-		.TunerType     = TUNER_PHILIPS_PAL,
-		.X_Offset      = -1,
-		.Y_Offset      = -1,
-		.ModelString   = "Hauppauge WinTV USB (PAL D/K FM)",
+		.interface      = -1,
+		.codec          = CODEC_SAA7111,
+		.video_channels = 3,
+		.video_norm     = V4L2_STD_PAL,
+		.audio_channels = 1,
+		.radio          = 1,
+		.vbi            = 1,
+		.tuner          = 1,
+		.tuner_type     = TUNER_PHILIPS_PAL,
+		.x_offset       = -1,
+		.y_offset       = -1,
+		.model_string   = "Hauppauge WinTV USB (PAL D/K FM)",
 	},
 	[HPG_WINTV_PRO_NTSC_MN] = {
-		.Interface     = 0,
-		.Codec         = CODEC_SAA7113,
-		.VideoChannels = 3,
-		.VideoNorm     = V4L2_STD_NTSC,
-		.AudioChannels = 1,
-		.Radio         = 1,
-		.vbi           = 1,
-		.Tuner         = 1,
-		.TunerType     = TUNER_MICROTUNE_4049FM5,
-		.X_Offset      = 0,
-		.Y_Offset      = 3,
-		.Dvi_yuv_override = 1,
-		.Dvi_yuv       = 7,
-		.ModelString   = "Hauppauge WinTV USB Pro (NTSC M/N)",
+		.interface      = 0,
+		.codec          = CODEC_SAA7113,
+		.video_channels = 3,
+		.video_norm     = V4L2_STD_NTSC,
+		.audio_channels = 1,
+		.radio          = 1,
+		.vbi            = 1,
+		.tuner          = 1,
+		.tuner_type     = TUNER_MICROTUNE_4049FM5,
+		.x_offset       = 0,
+		.y_offset       = 3,
+		.dvi_yuv_override = 1,
+		.dvi_yuv        = 7,
+		.model_string   = "Hauppauge WinTV USB Pro (NTSC M/N)",
 	},
 	[HPG_WINTV_PRO_NTSC_MN_V2] = {
-		.Interface     = 0,
-		.Codec         = CODEC_SAA7113,
-		.VideoChannels = 3,
-		.VideoNorm     = V4L2_STD_NTSC,
-		.AudioChannels = 1,
-		.Radio         = 1,
-		.vbi           = 1,
-		.Tuner         = 1,
-		.TunerType     = TUNER_MICROTUNE_4049FM5,
-		.X_Offset      = 0,
-		.Y_Offset      = 3,
-		.Dvi_yuv_override = 1,
-		.Dvi_yuv       = 7,
-		.ModelString   = "Hauppauge WinTV USB Pro (NTSC M/N) V2",
+		.interface      = 0,
+		.codec          = CODEC_SAA7113,
+		.video_channels = 3,
+		.video_norm     = V4L2_STD_NTSC,
+		.audio_channels = 1,
+		.radio          = 1,
+		.vbi            = 1,
+		.tuner          = 1,
+		.tuner_type     = TUNER_MICROTUNE_4049FM5,
+		.x_offset       = 0,
+		.y_offset       = 3,
+		.dvi_yuv_override = 1,
+		.dvi_yuv        = 7,
+		.model_string   = "Hauppauge WinTV USB Pro (NTSC M/N) V2",
 	},
 	[HPG_WINTV_PRO_PAL] = {
-		.Interface     = 0,
-		.Codec         = CODEC_SAA7113,
-		.VideoChannels = 3,
-		.VideoNorm     = V4L2_STD_PAL,
-		.AudioChannels = 1,
-		.Radio         = 0,
-		.vbi           = 1,
-		.Tuner         = 1,
-		.TunerType     = TUNER_PHILIPS_FM1216ME_MK3,
-		.X_Offset      = 0,
-		.Y_Offset      = 3,
-		.Dvi_yuv_override = 1,
-		.Dvi_yuv       = 7,
-		.ModelString   = "Hauppauge WinTV USB Pro (PAL/SECAM B/G/I/D/K/L)",
+		.interface      = 0,
+		.codec          = CODEC_SAA7113,
+		.video_channels = 3,
+		.video_norm     = V4L2_STD_PAL,
+		.audio_channels = 1,
+		.radio          = 0,
+		.vbi            = 1,
+		.tuner          = 1,
+		.tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
+		.x_offset       = 0,
+		.y_offset       = 3,
+		.dvi_yuv_override = 1,
+		.dvi_yuv        = 7,
+		.model_string   = "Hauppauge WinTV USB Pro (PAL/SECAM B/G/I/D/K/L)",
 	},
 	[HPG_WINTV_PRO_NTSC_MN_V3] = {
-		.Interface     = 0,
-		.Codec         = CODEC_SAA7113,
-		.VideoChannels = 3,
-		.VideoNorm     = V4L2_STD_NTSC,
-		.AudioChannels = 1,
-		.Radio         = 1,
-		.vbi           = 1,
-		.Tuner         = 1,
-		.TunerType     = TUNER_PHILIPS_NTSC_M,
-		.X_Offset      = 0,
-		.Y_Offset      = 3,
-		.Dvi_yuv_override = 1,
-		.Dvi_yuv       = 7,
-		.ModelString   = "Hauppauge WinTV USB Pro (NTSC M/N) V3",
+		.interface      = 0,
+		.codec          = CODEC_SAA7113,
+		.video_channels = 3,
+		.video_norm     = V4L2_STD_NTSC,
+		.audio_channels = 1,
+		.radio          = 1,
+		.vbi            = 1,
+		.tuner          = 1,
+		.tuner_type     = TUNER_PHILIPS_NTSC_M,
+		.x_offset       = 0,
+		.y_offset       = 3,
+		.dvi_yuv_override = 1,
+		.dvi_yuv        = 7,
+		.model_string   = "Hauppauge WinTV USB Pro (NTSC M/N) V3",
 	},
 	[HPG_WINTV_PRO_PAL_BG] = {
-		.Interface     = 0,
-		.Codec         = CODEC_SAA7113,
-		.VideoChannels = 3,
-		.VideoNorm     = V4L2_STD_PAL,
-		.AudioChannels = 1,
-		.Radio         = 0,
-		.vbi           = 1,
-		.Tuner         = 1,
-		.TunerType     = TUNER_PHILIPS_PAL,
-		.X_Offset      = 0,
-		.Y_Offset      = 3,
-		.Dvi_yuv_override = 1,
-		.Dvi_yuv       = 7,
-		.ModelString   = "Hauppauge WinTV USB Pro (PAL B/G)",
+		.interface      = 0,
+		.codec          = CODEC_SAA7113,
+		.video_channels = 3,
+		.video_norm     = V4L2_STD_PAL,
+		.audio_channels = 1,
+		.radio          = 0,
+		.vbi            = 1,
+		.tuner          = 1,
+		.tuner_type     = TUNER_PHILIPS_PAL,
+		.x_offset       = 0,
+		.y_offset       = 3,
+		.dvi_yuv_override = 1,
+		.dvi_yuv        = 7,
+		.model_string   = "Hauppauge WinTV USB Pro (PAL B/G)",
 	},
 	[HPG_WINTV_PRO_PAL_I] = {
-		.Interface     = 0,
-		.Codec         = CODEC_SAA7113,
-		.VideoChannels = 3,
-		.VideoNorm     = V4L2_STD_PAL,
-		.AudioChannels = 1,
-		.Radio         = 0,
-		.vbi           = 1,
-		.Tuner         = 1,
-		.TunerType     = TUNER_PHILIPS_PAL,
-		.X_Offset      = 0,
-		.Y_Offset      = 3,
-		.Dvi_yuv_override = 1,
-		.Dvi_yuv       = 7,
-		.ModelString   = "Hauppauge WinTV USB Pro (PAL I)",
+		.interface      = 0,
+		.codec          = CODEC_SAA7113,
+		.video_channels = 3,
+		.video_norm     = V4L2_STD_PAL,
+		.audio_channels = 1,
+		.radio          = 0,
+		.vbi            = 1,
+		.tuner          = 1,
+		.tuner_type     = TUNER_PHILIPS_PAL,
+		.x_offset       = 0,
+		.y_offset       = 3,
+		.dvi_yuv_override = 1,
+		.dvi_yuv        = 7,
+		.model_string   = "Hauppauge WinTV USB Pro (PAL I)",
 	},
 	[HPG_WINTV_PRO_PAL_SECAM_L] = {
-		.Interface     = -1,
-		.Codec         = CODEC_SAA7113,
-		.VideoChannels = 3,
-		.VideoNorm     = V4L2_STD_SECAM,
-		.AudioChannels = 1,
-		.Radio         = 0,
-		.vbi           = 1,
-		.Tuner         = 1,
-		.TunerType     = TUNER_PHILIPS_SECAM,
-		.X_Offset      = 0,
-		.Y_Offset      = 3,
-		.Dvi_yuv_override = 1,
-		.Dvi_yuv       = 7,
-		.ModelString   = "Hauppauge WinTV USB Pro (PAL/SECAM L)",
+		.interface      = -1,
+		.codec          = CODEC_SAA7113,
+		.video_channels = 3,
+		.video_norm     = V4L2_STD_SECAM,
+		.audio_channels = 1,
+		.radio          = 0,
+		.vbi            = 1,
+		.tuner          = 1,
+		.tuner_type     = TUNER_PHILIPS_SECAM,
+		.x_offset       = 0,
+		.y_offset       = 3,
+		.dvi_yuv_override = 1,
+		.dvi_yuv        = 7,
+		.model_string   = "Hauppauge WinTV USB Pro (PAL/SECAM L)",
 	},
 	[HPG_WINTV_PRO_PAL_D_K] = {
-		.Interface     = -1,
-		.Codec         = CODEC_SAA7113,
-		.VideoChannels = 3,
-		.VideoNorm     = V4L2_STD_PAL,
-		.AudioChannels = 1,
-		.Radio         = 0,
-		.vbi           = 1,
-		.Tuner         = 1,
-		.TunerType     = TUNER_PHILIPS_PAL,
-		.X_Offset      = 0,
-		.Y_Offset      = 3,
-		.Dvi_yuv_override = 1,
-		.Dvi_yuv       = 7,
-		.ModelString   = "Hauppauge WinTV USB Pro (PAL D/K)",
+		.interface      = -1,
+		.codec          = CODEC_SAA7113,
+		.video_channels = 3,
+		.video_norm     = V4L2_STD_PAL,
+		.audio_channels = 1,
+		.radio          = 0,
+		.vbi            = 1,
+		.tuner          = 1,
+		.tuner_type     = TUNER_PHILIPS_PAL,
+		.x_offset       = 0,
+		.y_offset       = 3,
+		.dvi_yuv_override = 1,
+		.dvi_yuv        = 7,
+		.model_string   = "Hauppauge WinTV USB Pro (PAL D/K)",
 	},
 	[HPG_WINTV_PRO_PAL_SECAM] = {
-		.Interface     = -1,
-		.Codec         = CODEC_SAA7113,
-		.VideoChannels = 3,
-		.VideoNorm     = V4L2_STD_SECAM,
-		.AudioChannels = 1,
-		.Radio         = 0,
-		.vbi           = 1,
-		.Tuner         = 1,
-		.TunerType     = TUNER_PHILIPS_SECAM,
-		.X_Offset      = 0,
-		.Y_Offset      = 3,
-		.Dvi_yuv_override = 1,
-		.Dvi_yuv       = 7,
-		.ModelString   = "Hauppauge WinTV USB Pro (PAL/SECAM BGDK/I/L)",
+		.interface      = -1,
+		.codec          = CODEC_SAA7113,
+		.video_channels = 3,
+		.video_norm     = V4L2_STD_SECAM,
+		.audio_channels = 1,
+		.radio          = 0,
+		.vbi            = 1,
+		.tuner          = 1,
+		.tuner_type     = TUNER_PHILIPS_SECAM,
+		.x_offset       = 0,
+		.y_offset       = 3,
+		.dvi_yuv_override = 1,
+		.dvi_yuv        = 7,
+		.model_string   = "Hauppauge WinTV USB Pro (PAL/SECAM BGDK/I/L)",
 	},
 	[HPG_WINTV_PRO_PAL_SECAM_V2] = {
-		.Interface     = -1,
-		.Codec         = CODEC_SAA7113,
-		.VideoChannels = 3,
-		.VideoNorm     = V4L2_STD_SECAM,
-		.AudioChannels = 1,
-		.Radio         = 0,
-		.vbi           = 1,
-		.Tuner         = 1,
-		.TunerType     = TUNER_PHILIPS_SECAM,
-		.X_Offset      = 0,
-		.Y_Offset      = 3,
-		.Dvi_yuv_override = 1,
-		.Dvi_yuv       = 7,
-		.ModelString   = "Hauppauge WinTV USB Pro (PAL/SECAM BGDK/I/L) V2",
+		.interface      = -1,
+		.codec          = CODEC_SAA7113,
+		.video_channels = 3,
+		.video_norm     = V4L2_STD_SECAM,
+		.audio_channels = 1,
+		.radio          = 0,
+		.vbi            = 1,
+		.tuner          = 1,
+		.tuner_type     = TUNER_PHILIPS_SECAM,
+		.x_offset       = 0,
+		.y_offset       = 3,
+		.dvi_yuv_override = 1,
+		.dvi_yuv        = 7,
+		.model_string   = "Hauppauge WinTV USB Pro (PAL/SECAM BGDK/I/L) V2",
 	},
 	[HPG_WINTV_PRO_PAL_BG_V2] = {
-		.Interface     = -1,
-		.Codec         = CODEC_SAA7113,
-		.VideoChannels = 3,
-		.VideoNorm     = V4L2_STD_PAL,
-		.AudioChannels = 1,
-		.Radio         = 0,
-		.vbi           = 1,
-		.Tuner         = 1,
-		.TunerType     = TUNER_ALPS_TSBE1_PAL,
-		.X_Offset      = 0,
-		.Y_Offset      = 3,
-		.Dvi_yuv_override = 1,
-		.Dvi_yuv       = 7,
-		.ModelString   = "Hauppauge WinTV USB Pro (PAL B/G) V2",
+		.interface      = -1,
+		.codec          = CODEC_SAA7113,
+		.video_channels = 3,
+		.video_norm     = V4L2_STD_PAL,
+		.audio_channels = 1,
+		.radio          = 0,
+		.vbi            = 1,
+		.tuner          = 1,
+		.tuner_type     = TUNER_ALPS_TSBE1_PAL,
+		.x_offset       = 0,
+		.y_offset       = 3,
+		.dvi_yuv_override = 1,
+		.dvi_yuv        = 7,
+		.model_string   = "Hauppauge WinTV USB Pro (PAL B/G) V2",
 	},
 	[HPG_WINTV_PRO_PAL_BG_D_K] = {
-		.Interface     = -1,
-		.Codec         = CODEC_SAA7113,
-		.VideoChannels = 3,
-		.VideoNorm     = V4L2_STD_PAL,
-		.AudioChannels = 1,
-		.Radio         = 0,
-		.vbi           = 1,
-		.Tuner         = 1,
-		.TunerType     = TUNER_ALPS_TSBE1_PAL,
-		.X_Offset      = 0,
-		.Y_Offset      = 3,
-		.Dvi_yuv_override = 1,
-		.Dvi_yuv       = 7,
-		.ModelString   = "Hauppauge WinTV USB Pro (PAL B/G,D/K)",
+		.interface      = -1,
+		.codec          = CODEC_SAA7113,
+		.video_channels = 3,
+		.video_norm     = V4L2_STD_PAL,
+		.audio_channels = 1,
+		.radio          = 0,
+		.vbi            = 1,
+		.tuner          = 1,
+		.tuner_type     = TUNER_ALPS_TSBE1_PAL,
+		.x_offset       = 0,
+		.y_offset       = 3,
+		.dvi_yuv_override = 1,
+		.dvi_yuv        = 7,
+		.model_string   = "Hauppauge WinTV USB Pro (PAL B/G,D/K)",
 	},
 	[HPG_WINTV_PRO_PAL_I_D_K] = {
-		.Interface     = -1,
-		.Codec         = CODEC_SAA7113,
-		.VideoChannels = 3,
-		.VideoNorm     = V4L2_STD_PAL,
-		.AudioChannels = 1,
-		.Radio         = 0,
-		.vbi           = 1,
-		.Tuner         = 1,
-		.TunerType     = TUNER_LG_PAL_NEW_TAPC,
-		.X_Offset      = 0,
-		.Y_Offset      = 3,
-		.Dvi_yuv_override = 1,
-		.Dvi_yuv       = 7,
-		.ModelString   = "Hauppauge WinTV USB Pro (PAL I,D/K)",
+		.interface      = -1,
+		.codec          = CODEC_SAA7113,
+		.video_channels = 3,
+		.video_norm     = V4L2_STD_PAL,
+		.audio_channels = 1,
+		.radio          = 0,
+		.vbi            = 1,
+		.tuner          = 1,
+		.tuner_type     = TUNER_LG_PAL_NEW_TAPC,
+		.x_offset       = 0,
+		.y_offset       = 3,
+		.dvi_yuv_override = 1,
+		.dvi_yuv        = 7,
+		.model_string   = "Hauppauge WinTV USB Pro (PAL I,D/K)",
 	},
 	[HPG_WINTV_PRO_NTSC_MN_FM] = {
-		.Interface     = -1,
-		.Codec         = CODEC_SAA7113,
-		.VideoChannels = 3,
-		.VideoNorm     = V4L2_STD_NTSC,
-		.AudioChannels = 1,
-		.Radio         = 1,
-		.vbi           = 1,
-		.Tuner         = 1,
-		.TunerType     = TUNER_PHILIPS_NTSC_M,
-		.X_Offset      = 0,
-		.Y_Offset      = 3,
-		.Dvi_yuv_override = 1,
-		.Dvi_yuv       = 7,
-		.ModelString   = "Hauppauge WinTV USB Pro (NTSC M/N FM)",
+		.interface      = -1,
+		.codec          = CODEC_SAA7113,
+		.video_channels = 3,
+		.video_norm     = V4L2_STD_NTSC,
+		.audio_channels = 1,
+		.radio          = 1,
+		.vbi            = 1,
+		.tuner          = 1,
+		.tuner_type     = TUNER_PHILIPS_NTSC_M,
+		.x_offset       = 0,
+		.y_offset       = 3,
+		.dvi_yuv_override = 1,
+		.dvi_yuv        = 7,
+		.model_string   = "Hauppauge WinTV USB Pro (NTSC M/N FM)",
 	},
 	[HPG_WINTV_PRO_PAL_BG_FM] = {
-		.Interface     = 0,
-		.Codec         = CODEC_SAA7113,
-		.VideoChannels = 3,
-		.VideoNorm     = V4L2_STD_PAL,
-		.AudioChannels = 1,
-		.Radio         = 1,
-		.vbi           = 1,
-		.Tuner         = 1,
-		.TunerType     = TUNER_PHILIPS_PAL,
-		.X_Offset      = 0,
-		.Y_Offset      = 3,
-		.Dvi_yuv_override = 1,
-		.Dvi_yuv       = 7,
-		.ModelString   = "Hauppauge WinTV USB Pro (PAL B/G FM)",
+		.interface      = 0,
+		.codec          = CODEC_SAA7113,
+		.video_channels = 3,
+		.video_norm     = V4L2_STD_PAL,
+		.audio_channels = 1,
+		.radio          = 1,
+		.vbi            = 1,
+		.tuner          = 1,
+		.tuner_type     = TUNER_PHILIPS_PAL,
+		.x_offset       = 0,
+		.y_offset       = 3,
+		.dvi_yuv_override = 1,
+		.dvi_yuv        = 7,
+		.model_string   = "Hauppauge WinTV USB Pro (PAL B/G FM)",
 	},
 	[HPG_WINTV_PRO_PAL_I_FM] = {
-		.Interface     = 0,
-		.Codec         = CODEC_SAA7113,
-		.VideoChannels = 3,
-		.VideoNorm     = V4L2_STD_PAL,
-		.AudioChannels = 1,
-		.Radio         = 1,
-		.vbi           = 1,
-		.Tuner         = 1,
-		.TunerType     = TUNER_PHILIPS_PAL,
-		.X_Offset      = 0,
-		.Y_Offset      = 3,
-		.Dvi_yuv_override = 1,
-		.Dvi_yuv       = 7,
-		.ModelString   = "Hauppauge WinTV USB Pro (PAL I FM)",
+		.interface      = 0,
+		.codec          = CODEC_SAA7113,
+		.video_channels = 3,
+		.video_norm     = V4L2_STD_PAL,
+		.audio_channels = 1,
+		.radio          = 1,
+		.vbi            = 1,
+		.tuner          = 1,
+		.tuner_type     = TUNER_PHILIPS_PAL,
+		.x_offset       = 0,
+		.y_offset       = 3,
+		.dvi_yuv_override = 1,
+		.dvi_yuv        = 7,
+		.model_string   = "Hauppauge WinTV USB Pro (PAL I FM)",
 	},
 	[HPG_WINTV_PRO_PAL_D_K_FM] = {
-		.Interface     = 0,
-		.Codec         = CODEC_SAA7113,
-		.VideoChannels = 3,
-		.VideoNorm     = V4L2_STD_PAL,
-		.AudioChannels = 1,
-		.Radio         = 1,
-		.vbi           = 1,
-		.Tuner         = 1,
-		.TunerType     = TUNER_PHILIPS_PAL,
-		.X_Offset      = 0,
-		.Y_Offset      = 3,
-		.Dvi_yuv_override = 1,
-		.Dvi_yuv       = 7,
-		.ModelString   = "Hauppauge WinTV USB Pro (PAL D/K FM)",
+		.interface      = 0,
+		.codec          = CODEC_SAA7113,
+		.video_channels = 3,
+		.video_norm     = V4L2_STD_PAL,
+		.audio_channels = 1,
+		.radio          = 1,
+		.vbi            = 1,
+		.tuner          = 1,
+		.tuner_type     = TUNER_PHILIPS_PAL,
+		.x_offset       = 0,
+		.y_offset       = 3,
+		.dvi_yuv_override = 1,
+		.dvi_yuv        = 7,
+		.model_string   = "Hauppauge WinTV USB Pro (PAL D/K FM)",
 	},
 	[HPG_WINTV_PRO_TEMIC_PAL_FM] = {
-		.Interface     = 0,
-		.Codec         = CODEC_SAA7113,
-		.VideoChannels = 3,
-		.VideoNorm     = V4L2_STD_PAL,
-		.AudioChannels = 1,
-		.Radio         = 1,
-		.vbi           = 1,
-		.Tuner         = 1,
-		.TunerType     = TUNER_MICROTUNE_4049FM5,
-		.X_Offset      = 0,
-		.Y_Offset      = 3,
-		.Dvi_yuv_override = 1,
-		.Dvi_yuv       = 7,
-		.ModelString   = "Hauppauge WinTV USB Pro (Temic PAL/SECAM B/G/I/D/K/L FM)",
+		.interface      = 0,
+		.codec          = CODEC_SAA7113,
+		.video_channels = 3,
+		.video_norm     = V4L2_STD_PAL,
+		.audio_channels = 1,
+		.radio          = 1,
+		.vbi            = 1,
+		.tuner          = 1,
+		.tuner_type     = TUNER_MICROTUNE_4049FM5,
+		.x_offset       = 0,
+		.y_offset       = 3,
+		.dvi_yuv_override = 1,
+		.dvi_yuv        = 7,
+		.model_string   = "Hauppauge WinTV USB Pro (Temic PAL/SECAM B/G/I/D/K/L FM)",
 	},
 	[HPG_WINTV_PRO_TEMIC_PAL_BG_FM] = {
-		.Interface     = 0,
-		.Codec         = CODEC_SAA7113,
-		.VideoChannels = 3,
-		.VideoNorm     = V4L2_STD_PAL,
-		.AudioChannels = 1,
-		.Radio         = 1,
-		.vbi           = 1,
-		.Tuner         = 1,
-		.TunerType     = TUNER_MICROTUNE_4049FM5,
-		.X_Offset      = 0,
-		.Y_Offset      = 3,
-		.Dvi_yuv_override = 1,
-		.Dvi_yuv       = 7,
-		.ModelString   = "Hauppauge WinTV USB Pro (Temic PAL B/G FM)",
+		.interface      = 0,
+		.codec          = CODEC_SAA7113,
+		.video_channels = 3,
+		.video_norm     = V4L2_STD_PAL,
+		.audio_channels = 1,
+		.radio          = 1,
+		.vbi            = 1,
+		.tuner          = 1,
+		.tuner_type     = TUNER_MICROTUNE_4049FM5,
+		.x_offset       = 0,
+		.y_offset       = 3,
+		.dvi_yuv_override = 1,
+		.dvi_yuv        = 7,
+		.model_string   = "Hauppauge WinTV USB Pro (Temic PAL B/G FM)",
 	},
 	[HPG_WINTV_PRO_PAL_FM] = {
-		.Interface     = 0,
-		.Codec         = CODEC_SAA7113,
-		.VideoChannels = 3,
-		.VideoNorm     = V4L2_STD_PAL,
-		.AudioChannels = 1,
-		.Radio         = 1,
-		.vbi           = 1,
-		.Tuner         = 1,
-		.TunerType     = TUNER_PHILIPS_FM1216ME_MK3,
-		.X_Offset      = 0,
-		.Y_Offset      = 3,
-		.Dvi_yuv_override = 1,
-		.Dvi_yuv       = 7,
-		.ModelString   = "Hauppauge WinTV USB Pro (PAL/SECAM B/G/I/D/K/L FM)",
+		.interface      = 0,
+		.codec          = CODEC_SAA7113,
+		.video_channels = 3,
+		.video_norm     = V4L2_STD_PAL,
+		.audio_channels = 1,
+		.radio          = 1,
+		.vbi            = 1,
+		.tuner          = 1,
+		.tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
+		.x_offset       = 0,
+		.y_offset       = 3,
+		.dvi_yuv_override = 1,
+		.dvi_yuv        = 7,
+		.model_string   = "Hauppauge WinTV USB Pro (PAL/SECAM B/G/I/D/K/L FM)",
 	},
 	[HPG_WINTV_PRO_NTSC_MN_FM_V2] = {
-		.Interface     = 0,
-		.Codec         = CODEC_SAA7113,
-		.VideoChannels = 3,
-		.VideoNorm     = V4L2_STD_NTSC,
-		.AudioChannels = 1,
-		.Radio         = 1,
-		.vbi           = 1,
-		.Tuner         = 1,
-		.TunerType     = TUNER_PHILIPS_NTSC_M,
-		.X_Offset      = 0,
-		.Y_Offset      = 3,
-		.Dvi_yuv_override = 1,
-		.Dvi_yuv       = 7,
-		.ModelString   = "Hauppauge WinTV USB Pro (NTSC M/N FM) V2",
+		.interface      = 0,
+		.codec          = CODEC_SAA7113,
+		.video_channels = 3,
+		.video_norm     = V4L2_STD_NTSC,
+		.audio_channels = 1,
+		.radio          = 1,
+		.vbi            = 1,
+		.tuner          = 1,
+		.tuner_type     = TUNER_PHILIPS_NTSC_M,
+		.x_offset       = 0,
+		.y_offset       = 3,
+		.dvi_yuv_override = 1,
+		.dvi_yuv        = 7,
+		.model_string   = "Hauppauge WinTV USB Pro (NTSC M/N FM) V2",
 	},
 	[CAMTEL_TVB330] = {
-		.Interface     = -1,
-		.Codec         = CODEC_SAA7113,
-		.VideoChannels = 3,
-		.VideoNorm     = V4L2_STD_NTSC,
-		.AudioChannels = 1,
-		.Radio         = 1,
-		.vbi           = 1,
-		.Tuner         = 1,
-		.TunerType     = TUNER_PHILIPS_NTSC_M,
-		.X_Offset      = 5,
-		.Y_Offset      = 5,
-		.ModelString   = "Camtel Technology USB TV Genie Pro FM Model TVB330",
+		.interface      = -1,
+		.codec          = CODEC_SAA7113,
+		.video_channels = 3,
+		.video_norm     = V4L2_STD_NTSC,
+		.audio_channels = 1,
+		.radio          = 1,
+		.vbi            = 1,
+		.tuner          = 1,
+		.tuner_type     = TUNER_PHILIPS_NTSC_M,
+		.x_offset       = 5,
+		.y_offset       = 5,
+		.model_string   = "Camtel Technology USB TV Genie Pro FM Model TVB330",
 	},
 	[DIGITAL_VIDEO_CREATOR_I] = {
-		.Interface     = -1,
-		.Codec         = CODEC_SAA7113,
-		.VideoChannels = 2,
-		.VideoNorm     = V4L2_STD_PAL,
-		.AudioChannels = 0,
-		.Radio         = 0,
-		.vbi           = 1,
-		.Tuner         = 0,
-		.TunerType     = 0,
-		.X_Offset      = 0,
-		.Y_Offset      = 3,
-		.Dvi_yuv_override = 1,
-		.Dvi_yuv       = 7,
-		.ModelString   = "Digital Video Creator I",
+		.interface      = -1,
+		.codec          = CODEC_SAA7113,
+		.video_channels = 2,
+		.video_norm     = V4L2_STD_PAL,
+		.audio_channels = 0,
+		.radio          = 0,
+		.vbi            = 1,
+		.tuner          = 0,
+		.tuner_type     = 0,
+		.x_offset       = 0,
+		.y_offset       = 3,
+		.dvi_yuv_override = 1,
+		.dvi_yuv        = 7,
+		.model_string   = "Digital Video Creator I",
 	},
 	[GLOBAL_VILLAGE_GV_007_NTSC] = {
-		.Interface     = -1,
-		.Codec         = CODEC_SAA7111,
-		.VideoChannels = 2,
-		.VideoNorm     = V4L2_STD_NTSC,
-		.AudioChannels = 0,
-		.Radio         = 0,
-		.vbi           = 1,
-		.Tuner         = 0,
-		.TunerType     = 0,
-		.X_Offset      = 82,
-		.Y_Offset      = 20,
-		.Dvi_yuv_override = 1,
-		.Dvi_yuv       = 7,
-		.ModelString   = "Global Village GV-007 (NTSC)",
+		.interface      = -1,
+		.codec          = CODEC_SAA7111,
+		.video_channels = 2,
+		.video_norm     = V4L2_STD_NTSC,
+		.audio_channels = 0,
+		.radio          = 0,
+		.vbi            = 1,
+		.tuner          = 0,
+		.tuner_type     = 0,
+		.x_offset       = 82,
+		.y_offset       = 20,
+		.dvi_yuv_override = 1,
+		.dvi_yuv        = 7,
+		.model_string   = "Global Village GV-007 (NTSC)",
 	},
 	[DAZZLE_DVC_50_REV_1_NTSC] = {
-		.Interface     = 0,
-		.Codec         = CODEC_SAA7113,
-		.VideoChannels = 2,
-		.VideoNorm     = V4L2_STD_NTSC,
-		.AudioChannels = 0,
-		.Radio         = 0,
-		.vbi           = 1,
-		.Tuner         = 0,
-		.TunerType     = 0,
-		.X_Offset      = 0,
-		.Y_Offset      = 3,
-		.Dvi_yuv_override = 1,
-		.Dvi_yuv       = 7,
-		.ModelString   = "Dazzle Fusion Model DVC-50 Rev 1 (NTSC)",
+		.interface      = 0,
+		.codec          = CODEC_SAA7113,
+		.video_channels = 2,
+		.video_norm     = V4L2_STD_NTSC,
+		.audio_channels = 0,
+		.radio          = 0,
+		.vbi            = 1,
+		.tuner          = 0,
+		.tuner_type     = 0,
+		.x_offset       = 0,
+		.y_offset       = 3,
+		.dvi_yuv_override = 1,
+		.dvi_yuv        = 7,
+		.model_string   = "Dazzle Fusion Model DVC-50 Rev 1 (NTSC)",
 	},
 	[DAZZLE_DVC_80_REV_1_PAL] = {
-		.Interface     = 0,
-		.Codec         = CODEC_SAA7113,
-		.VideoChannels = 2,
-		.VideoNorm     = V4L2_STD_PAL,
-		.AudioChannels = 0,
-		.Radio         = 0,
-		.vbi           = 1,
-		.Tuner         = 0,
-		.TunerType     = 0,
-		.X_Offset      = 0,
-		.Y_Offset      = 3,
-		.Dvi_yuv_override = 1,
-		.Dvi_yuv       = 7,
-		.ModelString   = "Dazzle Fusion Model DVC-80 Rev 1 (PAL)",
+		.interface      = 0,
+		.codec          = CODEC_SAA7113,
+		.video_channels = 2,
+		.video_norm     = V4L2_STD_PAL,
+		.audio_channels = 0,
+		.radio          = 0,
+		.vbi            = 1,
+		.tuner          = 0,
+		.tuner_type     = 0,
+		.x_offset       = 0,
+		.y_offset       = 3,
+		.dvi_yuv_override = 1,
+		.dvi_yuv        = 7,
+		.model_string   = "Dazzle Fusion Model DVC-80 Rev 1 (PAL)",
 	},
 	[DAZZLE_DVC_90_REV_1_SECAM] = {
-		.Interface     = 0,
-		.Codec         = CODEC_SAA7113,
-		.VideoChannels = 2,
-		.VideoNorm     = V4L2_STD_SECAM,
-		.AudioChannels = 0,
-		.Radio         = 0,
-		.vbi           = 1,
-		.Tuner         = 0,
-		.TunerType     = 0,
-		.X_Offset      = 0,
-		.Y_Offset      = 3,
-		.Dvi_yuv_override = 1,
-		.Dvi_yuv       = 7,
-		.ModelString   = "Dazzle Fusion Model DVC-90 Rev 1 (SECAM)",
+		.interface      = 0,
+		.codec          = CODEC_SAA7113,
+		.video_channels = 2,
+		.video_norm     = V4L2_STD_SECAM,
+		.audio_channels = 0,
+		.radio          = 0,
+		.vbi            = 1,
+		.tuner          = 0,
+		.tuner_type     = 0,
+		.x_offset       = 0,
+		.y_offset       = 3,
+		.dvi_yuv_override = 1,
+		.dvi_yuv        = 7,
+		.model_string   = "Dazzle Fusion Model DVC-90 Rev 1 (SECAM)",
 	},
 	[ESKAPE_LABS_MYTV2GO] = {
-		.Interface     = 0,
-		.Codec         = CODEC_SAA7113,
-		.VideoChannels = 2,
-		.VideoNorm     = V4L2_STD_PAL,
-		.AudioChannels = 1,
-		.Radio         = 1,
-		.vbi           = 1,
-		.Tuner         = 1,
-		.TunerType     = TUNER_PHILIPS_FM1216ME_MK3,
-		.X_Offset      = 0,
-		.Y_Offset      = 3,
-		.Dvi_yuv_override = 1,
-		.Dvi_yuv       = 7,
-		.ModelString   = "Eskape Labs MyTV2Go",
+		.interface      = 0,
+		.codec          = CODEC_SAA7113,
+		.video_channels = 2,
+		.video_norm     = V4L2_STD_PAL,
+		.audio_channels = 1,
+		.radio          = 1,
+		.vbi            = 1,
+		.tuner          = 1,
+		.tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
+		.x_offset       = 0,
+		.y_offset       = 3,
+		.dvi_yuv_override = 1,
+		.dvi_yuv        = 7,
+		.model_string   = "Eskape Labs MyTV2Go",
 	},
 	[PINNA_PCTV_USB_PAL] = {
-		.Interface     = -1,
-		.Codec         = CODEC_SAA7111,
-		.VideoChannels = 3,
-		.VideoNorm     = V4L2_STD_PAL,
-		.AudioChannels = 1,
-		.Radio         = 0,
-		.vbi           = 0,
-		.Tuner         = 1,
-		.TunerType     = TUNER_TEMIC_4066FY5_PAL_I,
-		.X_Offset      = -1,
-		.Y_Offset      = -1,
-		.ModelString   = "Pinnacle Studio PCTV USB (PAL)",
+		.interface      = -1,
+		.codec          = CODEC_SAA7111,
+		.video_channels = 3,
+		.video_norm     = V4L2_STD_PAL,
+		.audio_channels = 1,
+		.radio          = 0,
+		.vbi            = 0,
+		.tuner          = 1,
+		.tuner_type     = TUNER_TEMIC_4066FY5_PAL_I,
+		.x_offset       = -1,
+		.y_offset       = -1,
+		.model_string   = "Pinnacle Studio PCTV USB (PAL)",
 	},
 	[PINNA_PCTV_USB_SECAM] = {
-		.Interface     = -1,
-		.Codec         = CODEC_SAA7111,
-		.VideoChannels = 3,
-		.VideoNorm     = V4L2_STD_SECAM,
-		.AudioChannels = 1,
-		.Radio         = 0,
-		.vbi           = 1,
-		.Tuner         = 1,
-		.TunerType     = TUNER_PHILIPS_SECAM,
-		.X_Offset      = -1,
-		.Y_Offset      = -1,
-		.ModelString   = "Pinnacle Studio PCTV USB (SECAM)",
+		.interface      = -1,
+		.codec          = CODEC_SAA7111,
+		.video_channels = 3,
+		.video_norm     = V4L2_STD_SECAM,
+		.audio_channels = 1,
+		.radio          = 0,
+		.vbi            = 1,
+		.tuner          = 1,
+		.tuner_type     = TUNER_PHILIPS_SECAM,
+		.x_offset       = -1,
+		.y_offset       = -1,
+		.model_string   = "Pinnacle Studio PCTV USB (SECAM)",
 	},
 	[PINNA_PCTV_USB_PAL_FM] = {
-		.Interface     = -1,
-		.Codec         = CODEC_SAA7111,
-		.VideoChannels = 3,
-		.VideoNorm     = V4L2_STD_PAL,
-		.AudioChannels = 1,
-		.Radio         = 1,
-		.vbi           = 1,
-		.Tuner         = 1,
-		.TunerType     = TUNER_PHILIPS_PAL,
-		.X_Offset      = 128,
-		.Y_Offset      = 23,
-		.ModelString   = "Pinnacle Studio PCTV USB (PAL) FM",
+		.interface      = -1,
+		.codec          = CODEC_SAA7111,
+		.video_channels = 3,
+		.video_norm     = V4L2_STD_PAL,
+		.audio_channels = 1,
+		.radio          = 1,
+		.vbi            = 1,
+		.tuner          = 1,
+		.tuner_type     = TUNER_PHILIPS_PAL,
+		.x_offset       = 128,
+		.y_offset       = 23,
+		.model_string   = "Pinnacle Studio PCTV USB (PAL) FM",
 	},
 	[MIRO_PCTV_USB] = {
-		.Interface     = -1,
-		.Codec         = CODEC_SAA7111,
-		.VideoChannels = 3,
-		.VideoNorm     = V4L2_STD_PAL,
-		.AudioChannels = 1,
-		.Radio         = 0,
-		.vbi           = 1,
-		.Tuner         = 1,
-		.TunerType     = TUNER_PHILIPS_PAL,
-		.X_Offset      = -1,
-		.Y_Offset      = -1,
-		.ModelString   = "Miro PCTV USB",
+		.interface      = -1,
+		.codec          = CODEC_SAA7111,
+		.video_channels = 3,
+		.video_norm     = V4L2_STD_PAL,
+		.audio_channels = 1,
+		.radio          = 0,
+		.vbi            = 1,
+		.tuner          = 1,
+		.tuner_type     = TUNER_PHILIPS_PAL,
+		.x_offset       = -1,
+		.y_offset       = -1,
+		.model_string   = "Miro PCTV USB",
 	},
 	[PINNA_PCTV_USB_NTSC_FM] = {
-		.Interface     = -1,
-		.Codec         = CODEC_SAA7111,
-		.VideoChannels = 3,
-		.VideoNorm     = V4L2_STD_NTSC,
-		.AudioChannels = 1,
-		.Radio         = 1,
-		.vbi           = 1,
-		.Tuner         = 1,
-		.TunerType     = TUNER_PHILIPS_NTSC_M,
-		.X_Offset      = -1,
-		.Y_Offset      = -1,
-		.ModelString   = "Pinnacle Studio PCTV USB (NTSC) FM",
+		.interface      = -1,
+		.codec          = CODEC_SAA7111,
+		.video_channels = 3,
+		.video_norm     = V4L2_STD_NTSC,
+		.audio_channels = 1,
+		.radio          = 1,
+		.vbi            = 1,
+		.tuner          = 1,
+		.tuner_type     = TUNER_PHILIPS_NTSC_M,
+		.x_offset       = -1,
+		.y_offset       = -1,
+		.model_string   = "Pinnacle Studio PCTV USB (NTSC) FM",
 	},
 	[PINNA_PCTV_USB_NTSC_FM_V3] = {
-		.Interface     = -1,
-		.Codec         = CODEC_SAA7111,
-		.VideoChannels = 3,
-		.VideoNorm     = V4L2_STD_NTSC,
-		.AudioChannels = 1,
-		.Radio         = 1,
-		.vbi           = 1,
-		.Tuner         = 1,
-		.TunerType     = TUNER_PHILIPS_NTSC_M,
-		.X_Offset      = -1,
-		.Y_Offset      = -1,
-		.ModelString   = "Pinnacle Studio PCTV USB (NTSC) FM V3",
+		.interface      = -1,
+		.codec          = CODEC_SAA7111,
+		.video_channels = 3,
+		.video_norm     = V4L2_STD_NTSC,
+		.audio_channels = 1,
+		.radio          = 1,
+		.vbi            = 1,
+		.tuner          = 1,
+		.tuner_type     = TUNER_PHILIPS_NTSC_M,
+		.x_offset       = -1,
+		.y_offset       = -1,
+		.model_string   = "Pinnacle Studio PCTV USB (NTSC) FM V3",
 	},
 	[PINNA_PCTV_USB_PAL_FM_V2] = {
-		.Interface     = -1,
-		.Codec         = CODEC_SAA7113,
-		.VideoChannels = 3,
-		.VideoNorm     = V4L2_STD_PAL,
-		.AudioChannels = 1,
-		.Radio         = 1,
-		.vbi           = 1,
-		.Tuner         = 1,
-		.TunerType     = TUNER_TEMIC_4009FR5_PAL,
-		.X_Offset      = 0,
-		.Y_Offset      = 3,
-		.Dvi_yuv_override = 1,
-		.Dvi_yuv       = 7,
-		.ModelString   = "Pinnacle Studio PCTV USB (PAL) FM V2",
+		.interface      = -1,
+		.codec          = CODEC_SAA7113,
+		.video_channels = 3,
+		.video_norm     = V4L2_STD_PAL,
+		.audio_channels = 1,
+		.radio          = 1,
+		.vbi            = 1,
+		.tuner          = 1,
+		.tuner_type     = TUNER_TEMIC_4009FR5_PAL,
+		.x_offset       = 0,
+		.y_offset       = 3,
+		.dvi_yuv_override = 1,
+		.dvi_yuv        = 7,
+		.model_string   = "Pinnacle Studio PCTV USB (PAL) FM V2",
 	},
 	[PINNA_PCTV_USB_NTSC_FM_V2] = {
-		.Interface     = -1,
-		.Codec         = CODEC_SAA7111,
-		.VideoChannels = 3,
-		.VideoNorm     = V4L2_STD_NTSC,
-		.AudioChannels = 1,
-		.Radio         = 1,
-		.vbi           = 1,
-		.Tuner         = 1,
-		.TunerType     = TUNER_TEMIC_4039FR5_NTSC,
-		.X_Offset      = 0,
-		.Y_Offset      = 3,
-		.Dvi_yuv_override = 1,
-		.Dvi_yuv       = 7,
-		.ModelString   = "Pinnacle Studio PCTV USB (NTSC) FM V2",
+		.interface      = -1,
+		.codec          = CODEC_SAA7111,
+		.video_channels = 3,
+		.video_norm     = V4L2_STD_NTSC,
+		.audio_channels = 1,
+		.radio          = 1,
+		.vbi            = 1,
+		.tuner          = 1,
+		.tuner_type     = TUNER_TEMIC_4039FR5_NTSC,
+		.x_offset       = 0,
+		.y_offset       = 3,
+		.dvi_yuv_override = 1,
+		.dvi_yuv        = 7,
+		.model_string   = "Pinnacle Studio PCTV USB (NTSC) FM V2",
 	},
 	[PINNA_PCTV_USB_PAL_FM_V3] = {
-		.Interface     = -1,
-		.Codec         = CODEC_SAA7113,
-		.VideoChannels = 3,
-		.VideoNorm     = V4L2_STD_PAL,
-		.AudioChannels = 1,
-		.Radio         = 1,
-		.vbi           = 1,
-		.Tuner         = 1,
-		.TunerType     = TUNER_TEMIC_4009FR5_PAL,
-		.X_Offset      = 0,
-		.Y_Offset      = 3,
-		.Dvi_yuv_override = 1,
-		.Dvi_yuv       = 7,
-		.ModelString   = "Pinnacle Studio PCTV USB (PAL) FM V3",
+		.interface      = -1,
+		.codec          = CODEC_SAA7113,
+		.video_channels = 3,
+		.video_norm     = V4L2_STD_PAL,
+		.audio_channels = 1,
+		.radio          = 1,
+		.vbi            = 1,
+		.tuner          = 1,
+		.tuner_type     = TUNER_TEMIC_4009FR5_PAL,
+		.x_offset       = 0,
+		.y_offset       = 3,
+		.dvi_yuv_override = 1,
+		.dvi_yuv        = 7,
+		.model_string   = "Pinnacle Studio PCTV USB (PAL) FM V3",
 	},
 	[PINNA_LINX_VD_IN_CAB_NTSC] = {
-		.Interface     = -1,
-		.Codec         = CODEC_SAA7113,
-		.VideoChannels = 2,
-		.VideoNorm     = V4L2_STD_NTSC,
-		.AudioChannels = 1,
-		.Radio         = 0,
-		.vbi           = 1,
-		.Tuner         = 0,
-		.TunerType     = 0,
-		.X_Offset      = 0,
-		.Y_Offset      = 3,
-		.Dvi_yuv_override = 1,
-		.Dvi_yuv       = 7,
-		.ModelString   = "Pinnacle Studio Linx Video input cable (NTSC)",
+		.interface      = -1,
+		.codec          = CODEC_SAA7113,
+		.video_channels = 2,
+		.video_norm     = V4L2_STD_NTSC,
+		.audio_channels = 1,
+		.radio          = 0,
+		.vbi            = 1,
+		.tuner          = 0,
+		.tuner_type     = 0,
+		.x_offset       = 0,
+		.y_offset       = 3,
+		.dvi_yuv_override = 1,
+		.dvi_yuv        = 7,
+		.model_string   = "Pinnacle Studio Linx Video input cable (NTSC)",
 	},
 	[PINNA_LINX_VD_IN_CAB_PAL] = {
-		.Interface     = -1,
-		.Codec         = CODEC_SAA7113,
-		.VideoChannels = 2,
-		.VideoNorm     = V4L2_STD_PAL,
-		.AudioChannels = 1,
-		.Radio         = 0,
-		.vbi           = 1,
-		.Tuner         = 0,
-		.TunerType     = 0,
-		.X_Offset      = 0,
-		.Y_Offset      = 3,
-		.Dvi_yuv_override = 1,
-		.Dvi_yuv       = 7,
-		.ModelString   = "Pinnacle Studio Linx Video input cable (PAL)",
+		.interface      = -1,
+		.codec          = CODEC_SAA7113,
+		.video_channels = 2,
+		.video_norm     = V4L2_STD_PAL,
+		.audio_channels = 1,
+		.radio          = 0,
+		.vbi            = 1,
+		.tuner          = 0,
+		.tuner_type     = 0,
+		.x_offset       = 0,
+		.y_offset       = 3,
+		.dvi_yuv_override = 1,
+		.dvi_yuv        = 7,
+		.model_string   = "Pinnacle Studio Linx Video input cable (PAL)",
 	},
 	[PINNA_PCTV_BUNGEE_PAL_FM] = {
-		.Interface     = -1,
-		.Codec         = CODEC_SAA7113,
-		.VideoChannels = 3,
-		.VideoNorm     = V4L2_STD_PAL,
-		.AudioChannels = 1,
-		.Radio         = 1,
-		.vbi           = 1,
-		.Tuner         = 1,
-		.TunerType     = TUNER_TEMIC_4009FR5_PAL,
-		.X_Offset      = 0,
-		.Y_Offset      = 3,
-		.Dvi_yuv_override = 1,
-		.Dvi_yuv       = 7,
-		.ModelString   = "Pinnacle PCTV Bungee USB (PAL) FM",
+		.interface      = -1,
+		.codec          = CODEC_SAA7113,
+		.video_channels = 3,
+		.video_norm     = V4L2_STD_PAL,
+		.audio_channels = 1,
+		.radio          = 1,
+		.vbi            = 1,
+		.tuner          = 1,
+		.tuner_type     = TUNER_TEMIC_4009FR5_PAL,
+		.x_offset       = 0,
+		.y_offset       = 3,
+		.dvi_yuv_override = 1,
+		.dvi_yuv        = 7,
+		.model_string   = "Pinnacle PCTV Bungee USB (PAL) FM",
 	},
 	[HPG_WINTV] = {
-		.Interface     = -1,
-		.Codec         = CODEC_SAA7111,
-		.VideoChannels = 3,
-		.VideoNorm     = V4L2_STD_NTSC,
-		.AudioChannels = 1,
-		.Radio         = 0,
-		.vbi           = 1,
-		.Tuner         = 1,
-		.TunerType     = TUNER_PHILIPS_NTSC_M,
-		.X_Offset      = -1,
-		.Y_Offset      = -1,
-		.ModelString   = "Hauppauge WinTv-USB",
+		.interface      = -1,
+		.codec          = CODEC_SAA7111,
+		.video_channels = 3,
+		.video_norm     = V4L2_STD_NTSC,
+		.audio_channels = 1,
+		.radio          = 0,
+		.vbi            = 1,
+		.tuner          = 1,
+		.tuner_type     = TUNER_PHILIPS_NTSC_M,
+		.x_offset       = -1,
+		.y_offset       = -1,
+		.model_string   = "Hauppauge WinTv-USB",
 	},
 };
-const int usbvision_device_data_size=ARRAY_SIZE(usbvision_device_data);
+const int usbvision_device_data_size = ARRAY_SIZE(usbvision_device_data);
 
 /* Supported Devices */
 
-struct usb_device_id usbvision_table [] = {
-	{ USB_DEVICE(0x0a6f, 0x0400), .driver_info=XANBOO },
-	{ USB_DEVICE(0x050d, 0x0106), .driver_info=BELKIN_VIDEOBUS_II },
-	{ USB_DEVICE(0x050d, 0x0207), .driver_info=BELKIN_VIDEOBUS },
-	{ USB_DEVICE(0x050d, 0x0208), .driver_info=BELKIN_USB_VIDEOBUS_II },
-	{ USB_DEVICE(0x0571, 0x0002), .driver_info=ECHOFX_INTERVIEW_LITE },
-	{ USB_DEVICE(0x0573, 0x0003), .driver_info=USBGEAR_USBG_V1 },
-	{ USB_DEVICE(0x0573, 0x0400), .driver_info=D_LINK_V100 },
-	{ USB_DEVICE(0x0573, 0x2000), .driver_info=X10_USB_CAMERA },
-	{ USB_DEVICE(0x0573, 0x2d00), .driver_info=HPG_WINTV_LIVE_PAL_BG },
-	{ USB_DEVICE(0x0573, 0x2d01), .driver_info=HPG_WINTV_LIVE_PRO_NTSC_MN },
-	{ USB_DEVICE(0x0573, 0x2101), .driver_info=ZORAN_PMD_NOGATECH },
-	{ USB_DEVICE(0x0573, 0x4100), .driver_info=NOGATECH_USB_TV_NTSC_FM },
-	{ USB_DEVICE(0x0573, 0x4110), .driver_info=PNY_USB_TV_NTSC_FM },
-	{ USB_DEVICE(0x0573, 0x4450), .driver_info=PV_PLAYTV_USB_PRO_PAL_FM },
-	{ USB_DEVICE(0x0573, 0x4550), .driver_info=ZT_721 },
-	{ USB_DEVICE(0x0573, 0x4d00), .driver_info=HPG_WINTV_NTSC_MN },
-	{ USB_DEVICE(0x0573, 0x4d01), .driver_info=HPG_WINTV_PAL_BG },
-	{ USB_DEVICE(0x0573, 0x4d02), .driver_info=HPG_WINTV_PAL_I },
-	{ USB_DEVICE(0x0573, 0x4d03), .driver_info=HPG_WINTV_PAL_SECAM_L },
-	{ USB_DEVICE(0x0573, 0x4d04), .driver_info=HPG_WINTV_PAL_D_K },
-	{ USB_DEVICE(0x0573, 0x4d10), .driver_info=HPG_WINTV_NTSC_FM },
-	{ USB_DEVICE(0x0573, 0x4d11), .driver_info=HPG_WINTV_PAL_BG_FM },
-	{ USB_DEVICE(0x0573, 0x4d12), .driver_info=HPG_WINTV_PAL_I_FM },
-	{ USB_DEVICE(0x0573, 0x4d14), .driver_info=HPG_WINTV_PAL_D_K_FM },
-	{ USB_DEVICE(0x0573, 0x4d2a), .driver_info=HPG_WINTV_PRO_NTSC_MN },
-	{ USB_DEVICE(0x0573, 0x4d2b), .driver_info=HPG_WINTV_PRO_NTSC_MN_V2 },
-	{ USB_DEVICE(0x0573, 0x4d2c), .driver_info=HPG_WINTV_PRO_PAL },
+struct usb_device_id usbvision_table[] = {
+	{ USB_DEVICE(0x0a6f, 0x0400), .driver_info = XANBOO },
+	{ USB_DEVICE(0x050d, 0x0106), .driver_info = BELKIN_VIDEOBUS_II },
+	{ USB_DEVICE(0x050d, 0x0207), .driver_info = BELKIN_VIDEOBUS },
+	{ USB_DEVICE(0x050d, 0x0208), .driver_info = BELKIN_USB_VIDEOBUS_II },
+	{ USB_DEVICE(0x0571, 0x0002), .driver_info = ECHOFX_INTERVIEW_LITE },
+	{ USB_DEVICE(0x0573, 0x0003), .driver_info = USBGEAR_USBG_V1 },
+	{ USB_DEVICE(0x0573, 0x0400), .driver_info = D_LINK_V100 },
+	{ USB_DEVICE(0x0573, 0x2000), .driver_info = X10_USB_CAMERA },
+	{ USB_DEVICE(0x0573, 0x2d00), .driver_info = HPG_WINTV_LIVE_PAL_BG },
+	{ USB_DEVICE(0x0573, 0x2d01), .driver_info = HPG_WINTV_LIVE_PRO_NTSC_MN },
+	{ USB_DEVICE(0x0573, 0x2101), .driver_info = ZORAN_PMD_NOGATECH },
+	{ USB_DEVICE(0x0573, 0x4100), .driver_info = NOGATECH_USB_TV_NTSC_FM },
+	{ USB_DEVICE(0x0573, 0x4110), .driver_info = PNY_USB_TV_NTSC_FM },
+	{ USB_DEVICE(0x0573, 0x4450), .driver_info = PV_PLAYTV_USB_PRO_PAL_FM },
+	{ USB_DEVICE(0x0573, 0x4550), .driver_info = ZT_721 },
+	{ USB_DEVICE(0x0573, 0x4d00), .driver_info = HPG_WINTV_NTSC_MN },
+	{ USB_DEVICE(0x0573, 0x4d01), .driver_info = HPG_WINTV_PAL_BG },
+	{ USB_DEVICE(0x0573, 0x4d02), .driver_info = HPG_WINTV_PAL_I },
+	{ USB_DEVICE(0x0573, 0x4d03), .driver_info = HPG_WINTV_PAL_SECAM_L },
+	{ USB_DEVICE(0x0573, 0x4d04), .driver_info = HPG_WINTV_PAL_D_K },
+	{ USB_DEVICE(0x0573, 0x4d10), .driver_info = HPG_WINTV_NTSC_FM },
+	{ USB_DEVICE(0x0573, 0x4d11), .driver_info = HPG_WINTV_PAL_BG_FM },
+	{ USB_DEVICE(0x0573, 0x4d12), .driver_info = HPG_WINTV_PAL_I_FM },
+	{ USB_DEVICE(0x0573, 0x4d14), .driver_info = HPG_WINTV_PAL_D_K_FM },
+	{ USB_DEVICE(0x0573, 0x4d2a), .driver_info = HPG_WINTV_PRO_NTSC_MN },
+	{ USB_DEVICE(0x0573, 0x4d2b), .driver_info = HPG_WINTV_PRO_NTSC_MN_V2 },
+	{ USB_DEVICE(0x0573, 0x4d2c), .driver_info = HPG_WINTV_PRO_PAL },
 	{ USB_DEVICE(0x0573, 0x4d20), .driver_info = HPG_WINTV_PRO_NTSC_MN_V3 },
-	{ USB_DEVICE(0x0573, 0x4d21), .driver_info=HPG_WINTV_PRO_PAL_BG },
-	{ USB_DEVICE(0x0573, 0x4d22), .driver_info=HPG_WINTV_PRO_PAL_I },
-	{ USB_DEVICE(0x0573, 0x4d23), .driver_info=HPG_WINTV_PRO_PAL_SECAM_L },
-	{ USB_DEVICE(0x0573, 0x4d24), .driver_info=HPG_WINTV_PRO_PAL_D_K },
-	{ USB_DEVICE(0x0573, 0x4d25), .driver_info=HPG_WINTV_PRO_PAL_SECAM },
-	{ USB_DEVICE(0x0573, 0x4d26), .driver_info=HPG_WINTV_PRO_PAL_SECAM_V2 },
-	{ USB_DEVICE(0x0573, 0x4d27), .driver_info=HPG_WINTV_PRO_PAL_BG_V2 },
-	{ USB_DEVICE(0x0573, 0x4d28), .driver_info=HPG_WINTV_PRO_PAL_BG_D_K },
-	{ USB_DEVICE(0x0573, 0x4d29), .driver_info=HPG_WINTV_PRO_PAL_I_D_K },
-	{ USB_DEVICE(0x0573, 0x4d30), .driver_info=HPG_WINTV_PRO_NTSC_MN_FM },
-	{ USB_DEVICE(0x0573, 0x4d31), .driver_info=HPG_WINTV_PRO_PAL_BG_FM },
-	{ USB_DEVICE(0x0573, 0x4d32), .driver_info=HPG_WINTV_PRO_PAL_I_FM },
-	{ USB_DEVICE(0x0573, 0x4d34), .driver_info=HPG_WINTV_PRO_PAL_D_K_FM },
-	{ USB_DEVICE(0x0573, 0x4d35), .driver_info=HPG_WINTV_PRO_TEMIC_PAL_FM },
-	{ USB_DEVICE(0x0573, 0x4d36), .driver_info=HPG_WINTV_PRO_TEMIC_PAL_BG_FM },
-	{ USB_DEVICE(0x0573, 0x4d37), .driver_info=HPG_WINTV_PRO_PAL_FM },
-	{ USB_DEVICE(0x0573, 0x4d38), .driver_info=HPG_WINTV_PRO_NTSC_MN_FM_V2 },
-	{ USB_DEVICE(0x0768, 0x0006), .driver_info=CAMTEL_TVB330 },
-	{ USB_DEVICE(0x07d0, 0x0001), .driver_info=DIGITAL_VIDEO_CREATOR_I },
-	{ USB_DEVICE(0x07d0, 0x0002), .driver_info=GLOBAL_VILLAGE_GV_007_NTSC },
-	{ USB_DEVICE(0x07d0, 0x0003), .driver_info=DAZZLE_DVC_50_REV_1_NTSC },
-	{ USB_DEVICE(0x07d0, 0x0004), .driver_info=DAZZLE_DVC_80_REV_1_PAL },
-	{ USB_DEVICE(0x07d0, 0x0005), .driver_info=DAZZLE_DVC_90_REV_1_SECAM },
-	{ USB_DEVICE(0x07f8, 0x9104), .driver_info=ESKAPE_LABS_MYTV2GO },
-	{ USB_DEVICE(0x2304, 0x010d), .driver_info=PINNA_PCTV_USB_PAL },
-	{ USB_DEVICE(0x2304, 0x0109), .driver_info=PINNA_PCTV_USB_SECAM },
-	{ USB_DEVICE(0x2304, 0x0110), .driver_info=PINNA_PCTV_USB_PAL_FM },
-	{ USB_DEVICE(0x2304, 0x0111), .driver_info=MIRO_PCTV_USB },
-	{ USB_DEVICE(0x2304, 0x0112), .driver_info=PINNA_PCTV_USB_NTSC_FM },
+	{ USB_DEVICE(0x0573, 0x4d21), .driver_info = HPG_WINTV_PRO_PAL_BG },
+	{ USB_DEVICE(0x0573, 0x4d22), .driver_info = HPG_WINTV_PRO_PAL_I },
+	{ USB_DEVICE(0x0573, 0x4d23), .driver_info = HPG_WINTV_PRO_PAL_SECAM_L },
+	{ USB_DEVICE(0x0573, 0x4d24), .driver_info = HPG_WINTV_PRO_PAL_D_K },
+	{ USB_DEVICE(0x0573, 0x4d25), .driver_info = HPG_WINTV_PRO_PAL_SECAM },
+	{ USB_DEVICE(0x0573, 0x4d26), .driver_info = HPG_WINTV_PRO_PAL_SECAM_V2 },
+	{ USB_DEVICE(0x0573, 0x4d27), .driver_info = HPG_WINTV_PRO_PAL_BG_V2 },
+	{ USB_DEVICE(0x0573, 0x4d28), .driver_info = HPG_WINTV_PRO_PAL_BG_D_K },
+	{ USB_DEVICE(0x0573, 0x4d29), .driver_info = HPG_WINTV_PRO_PAL_I_D_K },
+	{ USB_DEVICE(0x0573, 0x4d30), .driver_info = HPG_WINTV_PRO_NTSC_MN_FM },
+	{ USB_DEVICE(0x0573, 0x4d31), .driver_info = HPG_WINTV_PRO_PAL_BG_FM },
+	{ USB_DEVICE(0x0573, 0x4d32), .driver_info = HPG_WINTV_PRO_PAL_I_FM },
+	{ USB_DEVICE(0x0573, 0x4d34), .driver_info = HPG_WINTV_PRO_PAL_D_K_FM },
+	{ USB_DEVICE(0x0573, 0x4d35), .driver_info = HPG_WINTV_PRO_TEMIC_PAL_FM },
+	{ USB_DEVICE(0x0573, 0x4d36), .driver_info = HPG_WINTV_PRO_TEMIC_PAL_BG_FM },
+	{ USB_DEVICE(0x0573, 0x4d37), .driver_info = HPG_WINTV_PRO_PAL_FM },
+	{ USB_DEVICE(0x0573, 0x4d38), .driver_info = HPG_WINTV_PRO_NTSC_MN_FM_V2 },
+	{ USB_DEVICE(0x0768, 0x0006), .driver_info = CAMTEL_TVB330 },
+	{ USB_DEVICE(0x07d0, 0x0001), .driver_info = DIGITAL_VIDEO_CREATOR_I },
+	{ USB_DEVICE(0x07d0, 0x0002), .driver_info = GLOBAL_VILLAGE_GV_007_NTSC },
+	{ USB_DEVICE(0x07d0, 0x0003), .driver_info = DAZZLE_DVC_50_REV_1_NTSC },
+	{ USB_DEVICE(0x07d0, 0x0004), .driver_info = DAZZLE_DVC_80_REV_1_PAL },
+	{ USB_DEVICE(0x07d0, 0x0005), .driver_info = DAZZLE_DVC_90_REV_1_SECAM },
+	{ USB_DEVICE(0x07f8, 0x9104), .driver_info = ESKAPE_LABS_MYTV2GO },
+	{ USB_DEVICE(0x2304, 0x010d), .driver_info = PINNA_PCTV_USB_PAL },
+	{ USB_DEVICE(0x2304, 0x0109), .driver_info = PINNA_PCTV_USB_SECAM },
+	{ USB_DEVICE(0x2304, 0x0110), .driver_info = PINNA_PCTV_USB_PAL_FM },
+	{ USB_DEVICE(0x2304, 0x0111), .driver_info = MIRO_PCTV_USB },
+	{ USB_DEVICE(0x2304, 0x0112), .driver_info = PINNA_PCTV_USB_NTSC_FM },
 	{ USB_DEVICE(0x2304, 0x0113),
 	  .driver_info = PINNA_PCTV_USB_NTSC_FM_V3 },
-	{ USB_DEVICE(0x2304, 0x0210), .driver_info=PINNA_PCTV_USB_PAL_FM_V2 },
-	{ USB_DEVICE(0x2304, 0x0212), .driver_info=PINNA_PCTV_USB_NTSC_FM_V2 },
-	{ USB_DEVICE(0x2304, 0x0214), .driver_info=PINNA_PCTV_USB_PAL_FM_V3 },
-	{ USB_DEVICE(0x2304, 0x0300), .driver_info=PINNA_LINX_VD_IN_CAB_NTSC },
-	{ USB_DEVICE(0x2304, 0x0301), .driver_info=PINNA_LINX_VD_IN_CAB_PAL },
-	{ USB_DEVICE(0x2304, 0x0419), .driver_info=PINNA_PCTV_BUNGEE_PAL_FM },
-	{ USB_DEVICE(0x2400, 0x4200), .driver_info=HPG_WINTV },
+	{ USB_DEVICE(0x2304, 0x0210), .driver_info = PINNA_PCTV_USB_PAL_FM_V2 },
+	{ USB_DEVICE(0x2304, 0x0212), .driver_info = PINNA_PCTV_USB_NTSC_FM_V2 },
+	{ USB_DEVICE(0x2304, 0x0214), .driver_info = PINNA_PCTV_USB_PAL_FM_V3 },
+	{ USB_DEVICE(0x2304, 0x0300), .driver_info = PINNA_LINX_VD_IN_CAB_NTSC },
+	{ USB_DEVICE(0x2304, 0x0301), .driver_info = PINNA_LINX_VD_IN_CAB_PAL },
+	{ USB_DEVICE(0x2304, 0x0419), .driver_info = PINNA_PCTV_BUNGEE_PAL_FM },
+	{ USB_DEVICE(0x2400, 0x4200), .driver_info = HPG_WINTV },
 	{ },    /* terminate list */
 };
 
-MODULE_DEVICE_TABLE (usb, usbvision_table);
+MODULE_DEVICE_TABLE(usb, usbvision_table);
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/usbvision/usbvision-core.c linux-libre-2.6.38-gnu1/drivers/media/video/usbvision/usbvision-core.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/usbvision/usbvision-core.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/usbvision/usbvision-core.c	2011-03-14 21:20:32.000000000 -0400
@@ -33,7 +33,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/spinlock.h>
-#include <asm/io.h>
+#include <linux/io.h>
 #include <linux/videodev2.h>
 #include <linux/i2c.h>
 
@@ -46,30 +46,30 @@
 #include "usbvision.h"
 
 static unsigned int core_debug;
-module_param(core_debug,int,0644);
-MODULE_PARM_DESC(core_debug,"enable debug messages [core]");
+module_param(core_debug, int, 0644);
+MODULE_PARM_DESC(core_debug, "enable debug messages [core]");
 
 static unsigned int force_testpattern;
-module_param(force_testpattern,int,0644);
-MODULE_PARM_DESC(force_testpattern,"enable test pattern display [core]");
+module_param(force_testpattern, int, 0644);
+MODULE_PARM_DESC(force_testpattern, "enable test pattern display [core]");
 
-static int adjustCompression = 1;	/* Set the compression to be adaptive */
-module_param(adjustCompression, int, 0444);
-MODULE_PARM_DESC(adjustCompression, " Set the ADPCM compression for the device.  Default: 1 (On)");
+static int adjust_compression = 1;	/* Set the compression to be adaptive */
+module_param(adjust_compression, int, 0444);
+MODULE_PARM_DESC(adjust_compression, " Set the ADPCM compression for the device.  Default: 1 (On)");
 
 /* To help people with Black and White output with using s-video input.
  * Some cables and input device are wired differently. */
-static int SwitchSVideoInput;
-module_param(SwitchSVideoInput, int, 0444);
-MODULE_PARM_DESC(SwitchSVideoInput, " Set the S-Video input.  Some cables and input device are wired differently. Default: 0 (Off)");
+static int switch_svideo_input;
+module_param(switch_svideo_input, int, 0444);
+MODULE_PARM_DESC(switch_svideo_input, " Set the S-Video input.  Some cables and input device are wired differently. Default: 0 (Off)");
 
-static unsigned int adjust_X_Offset = -1;
-module_param(adjust_X_Offset, int, 0644);
-MODULE_PARM_DESC(adjust_X_Offset, "adjust X offset display [core]");
+static unsigned int adjust_x_offset = -1;
+module_param(adjust_x_offset, int, 0644);
+MODULE_PARM_DESC(adjust_x_offset, "adjust X offset display [core]");
 
-static unsigned int adjust_Y_Offset = -1;
-module_param(adjust_Y_Offset, int, 0644);
-MODULE_PARM_DESC(adjust_Y_Offset, "adjust Y offset display [core]");
+static unsigned int adjust_y_offset = -1;
+module_param(adjust_y_offset, int, 0644);
+MODULE_PARM_DESC(adjust_y_offset, "adjust Y offset display [core]");
 
 
 #define	ENABLE_HEXDUMP	0	/* Enable if you need it */
@@ -82,15 +82,15 @@ MODULE_PARM_DESC(adjust_Y_Offset, "adjus
 				__func__, __LINE__ , ## args); \
 	}
 #else
-	#define PDEBUG(level, fmt, args...) do {} while(0)
+	#define PDEBUG(level, fmt, args...) do {} while (0)
 #endif
 
-#define DBG_HEADER	1<<0
-#define DBG_IRQ		1<<1
-#define DBG_ISOC	1<<2
-#define DBG_PARSE	1<<3
-#define DBG_SCRATCH	1<<4
-#define DBG_FUNC	1<<5
+#define DBG_HEADER	(1 << 0)
+#define DBG_IRQ		(1 << 1)
+#define DBG_ISOC	(1 << 2)
+#define DBG_PARSE	(1 << 3)
+#define DBG_SCRATCH	(1 << 4)
+#define DBG_FUNC	(1 << 5)
 
 static const int max_imgwidth = MAX_FRAME_WIDTH;
 static const int max_imgheight = MAX_FRAME_HEIGHT;
@@ -103,14 +103,14 @@ static const int min_imgheight = MIN_FRA
  * to work with. This setting can be adjusted, but the default value
  * should be OK for most desktop users.
  */
-#define DEFAULT_SCRATCH_BUF_SIZE	(0x20000)		// 128kB memory scratch buffer
+#define DEFAULT_SCRATCH_BUF_SIZE	(0x20000)		/* 128kB memory scratch buffer */
 static const int scratch_buf_size = DEFAULT_SCRATCH_BUF_SIZE;
 
-// Function prototypes
-static int usbvision_request_intra (struct usb_usbvision *usbvision);
-static int usbvision_unrequest_intra (struct usb_usbvision *usbvision);
-static int usbvision_adjust_compression (struct usb_usbvision *usbvision);
-static int usbvision_measure_bandwidth (struct usb_usbvision *usbvision);
+/* Function prototypes */
+static int usbvision_request_intra(struct usb_usbvision *usbvision);
+static int usbvision_unrequest_intra(struct usb_usbvision *usbvision);
+static int usbvision_adjust_compression(struct usb_usbvision *usbvision);
+static int usbvision_measure_bandwidth(struct usb_usbvision *usbvision);
 
 /*******************************/
 /* Memory management functions */
@@ -176,19 +176,19 @@ static void usbvision_hexdump(const unsi
 		k += sprintf(&tmp[k], "%02x ", data[i]);
 	}
 	if (k > 0)
-		printk("%s\n", tmp);
+		printk(KERN_CONT "%s\n", tmp);
 }
 #endif
 
 /********************************
  * scratch ring buffer handling
  ********************************/
-static int scratch_len(struct usb_usbvision *usbvision)    /*This returns the amount of data actually in the buffer */
+static int scratch_len(struct usb_usbvision *usbvision)    /* This returns the amount of data actually in the buffer */
 {
 	int len = usbvision->scratch_write_ptr - usbvision->scratch_read_ptr;
-	if (len < 0) {
+
+	if (len < 0)
 		len += scratch_buf_size;
-	}
 	PDEBUG(DBG_SCRATCH, "scratch_len() = %d\n", len);
 
 	return len;
@@ -199,9 +199,8 @@ static int scratch_len(struct usb_usbvis
 static int scratch_free(struct usb_usbvision *usbvision)
 {
 	int free = usbvision->scratch_read_ptr - usbvision->scratch_write_ptr;
-	if (free <= 0) {
+	if (free <= 0)
 		free += scratch_buf_size;
-	}
 	if (free) {
 		free -= 1;							/* at least one byte in the buffer must */
 										/* left blank, otherwise there is no chance to differ between full and empty */
@@ -221,14 +220,12 @@ static int scratch_put(struct usb_usbvis
 	if (usbvision->scratch_write_ptr + len < scratch_buf_size) {
 		memcpy(usbvision->scratch + usbvision->scratch_write_ptr, data, len);
 		usbvision->scratch_write_ptr += len;
-	}
-	else {
+	} else {
 		len_part = scratch_buf_size - usbvision->scratch_write_ptr;
 		memcpy(usbvision->scratch + usbvision->scratch_write_ptr, data, len_part);
 		if (len == len_part) {
 			usbvision->scratch_write_ptr = 0;			/* just set write_ptr to zero */
-		}
-		else {
+		} else {
 			memcpy(usbvision->scratch, data + len_part, len - len_part);
 			usbvision->scratch_write_ptr = len - len_part;
 		}
@@ -255,17 +252,16 @@ static int scratch_get_extra(struct usb_
 			     unsigned char *data, int *ptr, int len)
 {
 	int len_part;
+
 	if (*ptr + len < scratch_buf_size) {
 		memcpy(data, usbvision->scratch + *ptr, len);
 		*ptr += len;
-	}
-	else {
+	} else {
 		len_part = scratch_buf_size - *ptr;
 		memcpy(data, usbvision->scratch + *ptr, len_part);
 		if (len == len_part) {
 			*ptr = 0;							/* just set the y_ptr to zero */
-		}
-		else {
+		} else {
 			memcpy(data + len_part, usbvision->scratch, len - len_part);
 			*ptr = len - len_part;
 		}
@@ -281,13 +277,13 @@ static int scratch_get_extra(struct usb_
 static void scratch_set_extra_ptr(struct usb_usbvision *usbvision, int *ptr,
 				  int len)
 {
-	*ptr = (usbvision->scratch_read_ptr + len)%scratch_buf_size;
+	*ptr = (usbvision->scratch_read_ptr + len) % scratch_buf_size;
 
 	PDEBUG(DBG_SCRATCH, "ptr=%d\n", *ptr);
 }
 
 
-/*This increments the scratch extra read pointer */
+/* This increments the scratch extra read pointer */
 static void scratch_inc_extra_ptr(int *ptr, int len)
 {
 	*ptr = (*ptr + len) % scratch_buf_size;
@@ -301,17 +297,16 @@ static int scratch_get(struct usb_usbvis
 		       int len)
 {
 	int len_part;
+
 	if (usbvision->scratch_read_ptr + len < scratch_buf_size) {
 		memcpy(data, usbvision->scratch + usbvision->scratch_read_ptr, len);
 		usbvision->scratch_read_ptr += len;
-	}
-	else {
+	} else {
 		len_part = scratch_buf_size - usbvision->scratch_read_ptr;
 		memcpy(data, usbvision->scratch + usbvision->scratch_read_ptr, len_part);
 		if (len == len_part) {
 			usbvision->scratch_read_ptr = 0;				/* just set the read_ptr to zero */
-		}
-		else {
+		} else {
 			memcpy(data + len_part, usbvision->scratch, len - len_part);
 			usbvision->scratch_read_ptr = len - len_part;
 		}
@@ -327,7 +322,7 @@ static int scratch_get(struct usb_usbvis
 static int scratch_get_header(struct usb_usbvision *usbvision,
 			      struct usbvision_frame_header *header)
 {
-	int errCode = 0;
+	int err_code = 0;
 
 	PDEBUG(DBG_SCRATCH, "from read_ptr=%d", usbvision->scratch_headermarker_read_ptr);
 
@@ -340,29 +335,28 @@ static int scratch_get_header(struct usb
 		scratch_get(usbvision, (unsigned char *)header, USBVISION_HEADER_LENGTH);
 		if ((header->magic_1 == USBVISION_MAGIC_1)
 			 && (header->magic_2 == USBVISION_MAGIC_2)
-			 && (header->headerLength == USBVISION_HEADER_LENGTH)) {
-			errCode = USBVISION_HEADER_LENGTH;
-			header->frameWidth  = header->frameWidthLo  + (header->frameWidthHi << 8);
-			header->frameHeight = header->frameHeightLo + (header->frameHeightHi << 8);
+			 && (header->header_length == USBVISION_HEADER_LENGTH)) {
+			err_code = USBVISION_HEADER_LENGTH;
+			header->frame_width  = header->frame_width_lo  + (header->frame_width_hi << 8);
+			header->frame_height = header->frame_height_lo + (header->frame_height_hi << 8);
 			break;
 		}
 	}
 
-	return errCode;
+	return err_code;
 }
 
 
-/*This removes len bytes of old data from the buffer */
+/* This removes len bytes of old data from the buffer */
 static void scratch_rm_old(struct usb_usbvision *usbvision, int len)
 {
-
 	usbvision->scratch_read_ptr += len;
 	usbvision->scratch_read_ptr %= scratch_buf_size;
 	PDEBUG(DBG_SCRATCH, "read_ptr is now %d\n", usbvision->scratch_read_ptr);
 }
 
 
-/*This resets the buffer - kills all data in it too */
+/* This resets the buffer - kills all data in it too */
 static void scratch_reset(struct usb_usbvision *usbvision)
 {
 	PDEBUG(DBG_SCRATCH, "\n");
@@ -371,14 +365,14 @@ static void scratch_reset(struct usb_usb
 	usbvision->scratch_write_ptr = 0;
 	usbvision->scratch_headermarker_read_ptr = 0;
 	usbvision->scratch_headermarker_write_ptr = 0;
-	usbvision->isocstate = IsocState_NoFrame;
+	usbvision->isocstate = isoc_state_no_frame;
 }
 
 int usbvision_scratch_alloc(struct usb_usbvision *usbvision)
 {
 	usbvision->scratch = vmalloc_32(scratch_buf_size);
 	scratch_reset(usbvision);
-	if(usbvision->scratch == NULL) {
+	if (usbvision->scratch == NULL) {
 		dev_err(&usbvision->dev->dev,
 			"%s: unable to allocate %d bytes for scratch\n",
 				__func__, scratch_buf_size);
@@ -391,7 +385,6 @@ void usbvision_scratch_free(struct usb_u
 {
 	vfree(usbvision->scratch);
 	usbvision->scratch = NULL;
-
 }
 
 /*
@@ -420,13 +413,13 @@ static void usbvision_testpattern(struct
 		printk(KERN_ERR "%s: usbvision == NULL\n", proc);
 		return;
 	}
-	if (usbvision->curFrame == NULL) {
-		printk(KERN_ERR "%s: usbvision->curFrame is NULL.\n", proc);
+	if (usbvision->cur_frame == NULL) {
+		printk(KERN_ERR "%s: usbvision->cur_frame is NULL.\n", proc);
 		return;
 	}
 
 	/* Grab the current frame */
-	frame = usbvision->curFrame;
+	frame = usbvision->cur_frame;
 
 	/* Optionally start at the beginning */
 	if (fullframe) {
@@ -473,10 +466,9 @@ static void usbvision_testpattern(struct
 		}
 	}
 
-	frame->grabstate = FrameState_Done;
+	frame->grabstate = frame_state_done;
 	frame->scanlength += scan_length;
 	++num_pass;
-
 }
 
 /*
@@ -487,8 +479,9 @@ static void usbvision_testpattern(struct
 int usbvision_decompress_alloc(struct usb_usbvision *usbvision)
 {
 	int IFB_size = MAX_FRAME_WIDTH * MAX_FRAME_HEIGHT * 3 / 2;
-	usbvision->IntraFrameBuffer = vmalloc_32(IFB_size);
-	if (usbvision->IntraFrameBuffer == NULL) {
+
+	usbvision->intra_frame_buffer = vmalloc_32(IFB_size);
+	if (usbvision->intra_frame_buffer == NULL) {
 		dev_err(&usbvision->dev->dev,
 			"%s: unable to allocate %d for compr. frame buffer\n",
 				__func__, IFB_size);
@@ -504,8 +497,8 @@ int usbvision_decompress_alloc(struct us
  */
 void usbvision_decompress_free(struct usb_usbvision *usbvision)
 {
-	vfree(usbvision->IntraFrameBuffer);
-	usbvision->IntraFrameBuffer = NULL;
+	vfree(usbvision->intra_frame_buffer);
+	usbvision->intra_frame_buffer = NULL;
 
 }
 
@@ -517,117 +510,111 @@ void usbvision_decompress_free(struct us
  *
  * Locate one of supported header markers in the scratch buffer.
  */
-static enum ParseState usbvision_find_header(struct usb_usbvision *usbvision)
+static enum parse_state usbvision_find_header(struct usb_usbvision *usbvision)
 {
 	struct usbvision_frame *frame;
-	int foundHeader = 0;
+	int found_header = 0;
 
-	frame = usbvision->curFrame;
+	frame = usbvision->cur_frame;
 
-	while (scratch_get_header(usbvision, &frame->isocHeader) == USBVISION_HEADER_LENGTH) {
-		// found header in scratch
+	while (scratch_get_header(usbvision, &frame->isoc_header) == USBVISION_HEADER_LENGTH) {
+		/* found header in scratch */
 		PDEBUG(DBG_HEADER, "found header: 0x%02x%02x %d %d %d %d %#x 0x%02x %u %u",
-				frame->isocHeader.magic_2,
-				frame->isocHeader.magic_1,
-				frame->isocHeader.headerLength,
-				frame->isocHeader.frameNum,
-				frame->isocHeader.framePhase,
-				frame->isocHeader.frameLatency,
-				frame->isocHeader.dataFormat,
-				frame->isocHeader.formatParam,
-				frame->isocHeader.frameWidth,
-				frame->isocHeader.frameHeight);
+				frame->isoc_header.magic_2,
+				frame->isoc_header.magic_1,
+				frame->isoc_header.header_length,
+				frame->isoc_header.frame_num,
+				frame->isoc_header.frame_phase,
+				frame->isoc_header.frame_latency,
+				frame->isoc_header.data_format,
+				frame->isoc_header.format_param,
+				frame->isoc_header.frame_width,
+				frame->isoc_header.frame_height);
 
-		if (usbvision->requestIntra) {
-			if (frame->isocHeader.formatParam & 0x80) {
-				foundHeader = 1;
-				usbvision->lastIsocFrameNum = -1; // do not check for lost frames this time
+		if (usbvision->request_intra) {
+			if (frame->isoc_header.format_param & 0x80) {
+				found_header = 1;
+				usbvision->last_isoc_frame_num = -1; /* do not check for lost frames this time */
 				usbvision_unrequest_intra(usbvision);
 				break;
 			}
-		}
-		else {
-			foundHeader = 1;
+		} else {
+			found_header = 1;
 			break;
 		}
 	}
 
-	if (foundHeader) {
-		frame->frmwidth = frame->isocHeader.frameWidth * usbvision->stretch_width;
-		frame->frmheight = frame->isocHeader.frameHeight * usbvision->stretch_height;
-		frame->v4l2_linesize = (frame->frmwidth * frame->v4l2_format.depth)>> 3;
-	}
-	else { // no header found
+	if (found_header) {
+		frame->frmwidth = frame->isoc_header.frame_width * usbvision->stretch_width;
+		frame->frmheight = frame->isoc_header.frame_height * usbvision->stretch_height;
+		frame->v4l2_linesize = (frame->frmwidth * frame->v4l2_format.depth) >> 3;
+	} else { /* no header found */
 		PDEBUG(DBG_HEADER, "skipping scratch data, no header");
 		scratch_reset(usbvision);
-		return ParseState_EndParse;
+		return parse_state_end_parse;
 	}
 
-	// found header
-	if (frame->isocHeader.dataFormat==ISOC_MODE_COMPRESS) {
-		//check isocHeader.frameNum for lost frames
-		if (usbvision->lastIsocFrameNum >= 0) {
-			if (((usbvision->lastIsocFrameNum + 1) % 32) != frame->isocHeader.frameNum) {
-				// unexpected frame drop: need to request new intra frame
-				PDEBUG(DBG_HEADER, "Lost frame before %d on USB", frame->isocHeader.frameNum);
+	/* found header */
+	if (frame->isoc_header.data_format == ISOC_MODE_COMPRESS) {
+		/* check isoc_header.frame_num for lost frames */
+		if (usbvision->last_isoc_frame_num >= 0) {
+			if (((usbvision->last_isoc_frame_num + 1) % 32) != frame->isoc_header.frame_num) {
+				/* unexpected frame drop: need to request new intra frame */
+				PDEBUG(DBG_HEADER, "Lost frame before %d on USB", frame->isoc_header.frame_num);
 				usbvision_request_intra(usbvision);
-				return ParseState_NextFrame;
+				return parse_state_next_frame;
 			}
 		}
-		usbvision->lastIsocFrameNum = frame->isocHeader.frameNum;
+		usbvision->last_isoc_frame_num = frame->isoc_header.frame_num;
 	}
 	usbvision->header_count++;
-	frame->scanstate = ScanState_Lines;
+	frame->scanstate = scan_state_lines;
 	frame->curline = 0;
 
 	if (force_testpattern) {
 		usbvision_testpattern(usbvision, 1, 1);
-		return ParseState_NextFrame;
+		return parse_state_next_frame;
 	}
-	return ParseState_Continue;
+	return parse_state_continue;
 }
 
-static enum ParseState usbvision_parse_lines_422(struct usb_usbvision *usbvision,
+static enum parse_state usbvision_parse_lines_422(struct usb_usbvision *usbvision,
 					   long *pcopylen)
 {
 	volatile struct usbvision_frame *frame;
 	unsigned char *f;
 	int len;
 	int i;
-	unsigned char yuyv[4]={180, 128, 10, 128}; // YUV components
-	unsigned char rv, gv, bv;	// RGB components
+	unsigned char yuyv[4] = { 180, 128, 10, 128 }; /* YUV components */
+	unsigned char rv, gv, bv;	/* RGB components */
 	int clipmask_index, bytes_per_pixel;
 	int stretch_bytes, clipmask_add;
 
-	frame  = usbvision->curFrame;
+	frame  = usbvision->cur_frame;
 	f = frame->data + (frame->v4l2_linesize * frame->curline);
 
 	/* Make sure there's enough data for the entire line */
-	len = (frame->isocHeader.frameWidth * 2)+5;
+	len = (frame->isoc_header.frame_width * 2) + 5;
 	if (scratch_len(usbvision) < len) {
 		PDEBUG(DBG_PARSE, "out of data in line %d, need %u.\n", frame->curline, len);
-		return ParseState_Out;
+		return parse_state_out;
 	}
 
-	if ((frame->curline + 1) >= frame->frmheight) {
-		return ParseState_NextFrame;
-	}
+	if ((frame->curline + 1) >= frame->frmheight)
+		return parse_state_next_frame;
 
 	bytes_per_pixel = frame->v4l2_format.bytes_per_pixel;
 	stretch_bytes = (usbvision->stretch_width - 1) * bytes_per_pixel;
 	clipmask_index = frame->curline * MAX_FRAME_WIDTH;
 	clipmask_add = usbvision->stretch_width;
 
-	for (i = 0; i < frame->frmwidth; i+=(2 * usbvision->stretch_width)) {
-
+	for (i = 0; i < frame->frmwidth; i += (2 * usbvision->stretch_width)) {
 		scratch_get(usbvision, &yuyv[0], 4);
 
 		if (frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) {
-			*f++ = yuyv[0]; // Y
-			*f++ = yuyv[3]; // U
-		}
-		else {
-
+			*f++ = yuyv[0]; /* Y */
+			*f++ = yuyv[3]; /* U */
+		} else {
 			YUV_TO_RGB_BY_THE_BOOK(yuyv[0], yuyv[1], yuyv[3], rv, gv, bv);
 			switch (frame->v4l2_format.format) {
 			case V4L2_PIX_FMT_RGB565:
@@ -659,11 +646,9 @@ static enum ParseState usbvision_parse_l
 		f += stretch_bytes;
 
 		if (frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) {
-			*f++ = yuyv[2]; // Y
-			*f++ = yuyv[1]; // V
-		}
-		else {
-
+			*f++ = yuyv[2]; /* Y */
+			*f++ = yuyv[1]; /* V */
+		} else {
 			YUV_TO_RGB_BY_THE_BOOK(yuyv[2], yuyv[1], yuyv[3], rv, gv, bv);
 			switch (frame->v4l2_format.format) {
 			case V4L2_PIX_FMT_RGB565:
@@ -698,100 +683,94 @@ static enum ParseState usbvision_parse_l
 	frame->curline += usbvision->stretch_height;
 	*pcopylen += frame->v4l2_linesize * usbvision->stretch_height;
 
-	if (frame->curline >= frame->frmheight) {
-		return ParseState_NextFrame;
-	}
-	else {
-		return ParseState_Continue;
-	}
+	if (frame->curline >= frame->frmheight)
+		return parse_state_next_frame;
+	return parse_state_continue;
 }
 
 /* The decompression routine  */
-static int usbvision_decompress(struct usb_usbvision *usbvision,unsigned char *Compressed,
-								unsigned char *Decompressed, int *StartPos,
-								int *BlockTypeStartPos, int Len)
+static int usbvision_decompress(struct usb_usbvision *usbvision, unsigned char *compressed,
+								unsigned char *decompressed, int *start_pos,
+								int *block_typestart_pos, int len)
 {
-	int RestPixel, Idx, MaxPos, Pos, ExtraPos, BlockLen, BlockTypePos, BlockTypeLen;
-	unsigned char BlockByte, BlockCode, BlockType, BlockTypeByte, Integrator;
-
-	Integrator = 0;
-	Pos = *StartPos;
-	BlockTypePos = *BlockTypeStartPos;
-	MaxPos = 396; //Pos + Len;
-	ExtraPos = Pos;
-	BlockLen = 0;
-	BlockByte = 0;
-	BlockCode = 0;
-	BlockType = 0;
-	BlockTypeByte = 0;
-	BlockTypeLen = 0;
-	RestPixel = Len;
+	int rest_pixel, idx, max_pos, pos, extra_pos, block_len, block_type_pos, block_type_len;
+	unsigned char block_byte, block_code, block_type, block_type_byte, integrator;
 
-	for (Idx = 0; Idx < Len; Idx++) {
+	integrator = 0;
+	pos = *start_pos;
+	block_type_pos = *block_typestart_pos;
+	max_pos = 396; /* pos + len; */
+	extra_pos = pos;
+	block_len = 0;
+	block_byte = 0;
+	block_code = 0;
+	block_type = 0;
+	block_type_byte = 0;
+	block_type_len = 0;
+	rest_pixel = len;
 
-		if (BlockLen == 0) {
-			if (BlockTypeLen==0) {
-				BlockTypeByte = Compressed[BlockTypePos];
-				BlockTypePos++;
-				BlockTypeLen = 4;
+	for (idx = 0; idx < len; idx++) {
+		if (block_len == 0) {
+			if (block_type_len == 0) {
+				block_type_byte = compressed[block_type_pos];
+				block_type_pos++;
+				block_type_len = 4;
 			}
-			BlockType = (BlockTypeByte & 0xC0) >> 6;
+			block_type = (block_type_byte & 0xC0) >> 6;
 
-			//statistic:
-			usbvision->ComprBlockTypes[BlockType]++;
+			/* statistic: */
+			usbvision->compr_block_types[block_type]++;
 
-			Pos = ExtraPos;
-			if (BlockType == 0) {
-				if(RestPixel >= 24) {
-					Idx += 23;
-					RestPixel -= 24;
-					Integrator = Decompressed[Idx];
+			pos = extra_pos;
+			if (block_type == 0) {
+				if (rest_pixel >= 24) {
+					idx += 23;
+					rest_pixel -= 24;
+					integrator = decompressed[idx];
 				} else {
-					Idx += RestPixel - 1;
-					RestPixel = 0;
+					idx += rest_pixel - 1;
+					rest_pixel = 0;
 				}
 			} else {
-				BlockCode = Compressed[Pos];
-				Pos++;
-				if (RestPixel >= 24) {
-					BlockLen  = 24;
-				} else {
-					BlockLen = RestPixel;
-				}
-				RestPixel -= BlockLen;
-				ExtraPos = Pos + (BlockLen / 4);
+				block_code = compressed[pos];
+				pos++;
+				if (rest_pixel >= 24)
+					block_len  = 24;
+				else
+					block_len = rest_pixel;
+				rest_pixel -= block_len;
+				extra_pos = pos + (block_len / 4);
 			}
-			BlockTypeByte <<= 2;
-			BlockTypeLen -= 1;
+			block_type_byte <<= 2;
+			block_type_len -= 1;
 		}
-		if (BlockLen > 0) {
-			if ((BlockLen%4) == 0) {
-				BlockByte = Compressed[Pos];
-				Pos++;
-			}
-			if (BlockType == 1) { //inter Block
-				Integrator = Decompressed[Idx];
+		if (block_len > 0) {
+			if ((block_len % 4) == 0) {
+				block_byte = compressed[pos];
+				pos++;
 			}
-			switch (BlockByte & 0xC0) {
-				case 0x03<<6:
-					Integrator += Compressed[ExtraPos];
-					ExtraPos++;
-					break;
-				case 0x02<<6:
-					Integrator += BlockCode;
-					break;
-				case 0x00:
-					Integrator -= BlockCode;
-					break;
+			if (block_type == 1) /* inter Block */
+				integrator = decompressed[idx];
+			switch (block_byte & 0xC0) {
+			case 0x03 << 6:
+				integrator += compressed[extra_pos];
+				extra_pos++;
+				break;
+			case 0x02 << 6:
+				integrator += block_code;
+				break;
+			case 0x00:
+				integrator -= block_code;
+				break;
 			}
-			Decompressed[Idx] = Integrator;
-			BlockByte <<= 2;
-			BlockLen -= 1;
+			decompressed[idx] = integrator;
+			block_byte <<= 2;
+			block_len -= 1;
 		}
 	}
-	*StartPos = ExtraPos;
-	*BlockTypeStartPos = BlockTypePos;
-	return Idx;
+	*start_pos = extra_pos;
+	*block_typestart_pos = block_type_pos;
+	return idx;
 }
 
 
@@ -803,7 +782,7 @@ static int usbvision_decompress(struct u
  * number of bytes (RGB) to the *pcopylen.
  *
  */
-static enum ParseState usbvision_parse_compress(struct usb_usbvision *usbvision,
+static enum parse_state usbvision_parse_compress(struct usb_usbvision *usbvision,
 					   long *pcopylen)
 {
 #define USBVISION_STRIP_MAGIC		0x5A
@@ -811,191 +790,165 @@ static enum ParseState usbvision_parse_c
 #define USBVISION_STRIP_HEADER_LEN	3
 
 	struct usbvision_frame *frame;
-	unsigned char *f,*u = NULL ,*v = NULL;
-	unsigned char StripData[USBVISION_STRIP_LEN_MAX];
-	unsigned char StripHeader[USBVISION_STRIP_HEADER_LEN];
-	int Idx, IdxEnd, StripLen, StripPtr, StartBlockPos, BlockPos, BlockTypePos;
+	unsigned char *f, *u = NULL, *v = NULL;
+	unsigned char strip_data[USBVISION_STRIP_LEN_MAX];
+	unsigned char strip_header[USBVISION_STRIP_HEADER_LEN];
+	int idx, idx_end, strip_len, strip_ptr, startblock_pos, block_pos, block_type_pos;
 	int clipmask_index, bytes_per_pixel, rc;
-	int imageSize;
+	int image_size;
 	unsigned char rv, gv, bv;
 	static unsigned char *Y, *U, *V;
 
-	frame  = usbvision->curFrame;
-	imageSize = frame->frmwidth * frame->frmheight;
-	if ( (frame->v4l2_format.format == V4L2_PIX_FMT_YUV422P) ||
-	     (frame->v4l2_format.format == V4L2_PIX_FMT_YVU420) ) {       // this is a planar format
-		//... v4l2_linesize not used here.
+	frame = usbvision->cur_frame;
+	image_size = frame->frmwidth * frame->frmheight;
+	if ((frame->v4l2_format.format == V4L2_PIX_FMT_YUV422P) ||
+	    (frame->v4l2_format.format == V4L2_PIX_FMT_YVU420)) {       /* this is a planar format */
+		/* ... v4l2_linesize not used here. */
 		f = frame->data + (frame->width * frame->curline);
 	} else
 		f = frame->data + (frame->v4l2_linesize * frame->curline);
 
-	if (frame->v4l2_format.format == V4L2_PIX_FMT_YUYV){ //initialise u and v pointers
-		// get base of u and b planes add halfoffset
-
+	if (frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) { /* initialise u and v pointers */
+		/* get base of u and b planes add halfoffset */
 		u = frame->data
-			+ imageSize
-			+ (frame->frmwidth >>1) * frame->curline ;
-		v = u + (imageSize >>1 );
-
-	} else if (frame->v4l2_format.format == V4L2_PIX_FMT_YVU420){
-
-		v = frame->data + imageSize + ((frame->curline* (frame->width))>>2) ;
-		u = v + (imageSize >>2) ;
+			+ image_size
+			+ (frame->frmwidth >> 1) * frame->curline;
+		v = u + (image_size >> 1);
+	} else if (frame->v4l2_format.format == V4L2_PIX_FMT_YVU420) {
+		v = frame->data + image_size + ((frame->curline * (frame->width)) >> 2);
+		u = v + (image_size >> 2);
 	}
 
-	if (frame->curline == 0) {
+	if (frame->curline == 0)
 		usbvision_adjust_compression(usbvision);
-	}
 
-	if (scratch_len(usbvision) < USBVISION_STRIP_HEADER_LEN) {
-		return ParseState_Out;
-	}
+	if (scratch_len(usbvision) < USBVISION_STRIP_HEADER_LEN)
+		return parse_state_out;
 
-	//get strip header without changing the scratch_read_ptr
-	scratch_set_extra_ptr(usbvision, &StripPtr, 0);
-	scratch_get_extra(usbvision, &StripHeader[0], &StripPtr,
+	/* get strip header without changing the scratch_read_ptr */
+	scratch_set_extra_ptr(usbvision, &strip_ptr, 0);
+	scratch_get_extra(usbvision, &strip_header[0], &strip_ptr,
 				USBVISION_STRIP_HEADER_LEN);
 
-	if (StripHeader[0] != USBVISION_STRIP_MAGIC) {
-		// wrong strip magic
-		usbvision->stripMagicErrors++;
-		return ParseState_NextFrame;
+	if (strip_header[0] != USBVISION_STRIP_MAGIC) {
+		/* wrong strip magic */
+		usbvision->strip_magic_errors++;
+		return parse_state_next_frame;
 	}
 
-	if (frame->curline != (int)StripHeader[2]) {
-		//line number missmatch error
-		usbvision->stripLineNumberErrors++;
+	if (frame->curline != (int)strip_header[2]) {
+		/* line number mismatch error */
+		usbvision->strip_line_number_errors++;
 	}
 
-	StripLen = 2 * (unsigned int)StripHeader[1];
-	if (StripLen > USBVISION_STRIP_LEN_MAX) {
-		// strip overrun
-		// I think this never happens
+	strip_len = 2 * (unsigned int)strip_header[1];
+	if (strip_len > USBVISION_STRIP_LEN_MAX) {
+		/* strip overrun */
+		/* I think this never happens */
 		usbvision_request_intra(usbvision);
 	}
 
-	if (scratch_len(usbvision) < StripLen) {
-		//there is not enough data for the strip
-		return ParseState_Out;
+	if (scratch_len(usbvision) < strip_len) {
+		/* there is not enough data for the strip */
+		return parse_state_out;
 	}
 
-	if (usbvision->IntraFrameBuffer) {
-		Y = usbvision->IntraFrameBuffer + frame->frmwidth * frame->curline;
-		U = usbvision->IntraFrameBuffer + imageSize + (frame->frmwidth / 2) * (frame->curline / 2);
-		V = usbvision->IntraFrameBuffer + imageSize / 4 * 5 + (frame->frmwidth / 2) * (frame->curline / 2);
-	}
-	else {
-		return ParseState_NextFrame;
+	if (usbvision->intra_frame_buffer) {
+		Y = usbvision->intra_frame_buffer + frame->frmwidth * frame->curline;
+		U = usbvision->intra_frame_buffer + image_size + (frame->frmwidth / 2) * (frame->curline / 2);
+		V = usbvision->intra_frame_buffer + image_size / 4 * 5 + (frame->frmwidth / 2) * (frame->curline / 2);
+	} else {
+		return parse_state_next_frame;
 	}
 
 	bytes_per_pixel = frame->v4l2_format.bytes_per_pixel;
 	clipmask_index = frame->curline * MAX_FRAME_WIDTH;
 
-	scratch_get(usbvision, StripData, StripLen);
+	scratch_get(usbvision, strip_data, strip_len);
 
-	IdxEnd = frame->frmwidth;
-	BlockTypePos = USBVISION_STRIP_HEADER_LEN;
-	StartBlockPos = BlockTypePos + (IdxEnd - 1) / 96 + (IdxEnd / 2 - 1) / 96 + 2;
-	BlockPos = StartBlockPos;
+	idx_end = frame->frmwidth;
+	block_type_pos = USBVISION_STRIP_HEADER_LEN;
+	startblock_pos = block_type_pos + (idx_end - 1) / 96 + (idx_end / 2 - 1) / 96 + 2;
+	block_pos = startblock_pos;
 
-	usbvision->BlockPos = BlockPos;
+	usbvision->block_pos = block_pos;
 
-	if ((rc = usbvision_decompress(usbvision, StripData, Y, &BlockPos, &BlockTypePos, IdxEnd)) != IdxEnd) {
-		//return ParseState_Continue;
-	}
-	if (StripLen > usbvision->maxStripLen) {
-		usbvision->maxStripLen = StripLen;
-	}
+	rc = usbvision_decompress(usbvision, strip_data, Y, &block_pos, &block_type_pos, idx_end);
+	if (strip_len > usbvision->max_strip_len)
+		usbvision->max_strip_len = strip_len;
 
-	if (frame->curline%2) {
-		if ((rc = usbvision_decompress(usbvision, StripData, V, &BlockPos, &BlockTypePos, IdxEnd/2)) != IdxEnd/2) {
-		//return ParseState_Continue;
-		}
-	}
-	else {
-		if ((rc = usbvision_decompress(usbvision, StripData, U, &BlockPos, &BlockTypePos, IdxEnd/2)) != IdxEnd/2) {
-			//return ParseState_Continue;
-		}
-	}
+	if (frame->curline % 2)
+		rc = usbvision_decompress(usbvision, strip_data, V, &block_pos, &block_type_pos, idx_end / 2);
+	else
+		rc = usbvision_decompress(usbvision, strip_data, U, &block_pos, &block_type_pos, idx_end / 2);
 
-	if (BlockPos > usbvision->comprBlockPos) {
-		usbvision->comprBlockPos = BlockPos;
-	}
-	if (BlockPos > StripLen) {
-		usbvision->stripLenErrors++;
-	}
+	if (block_pos > usbvision->comprblock_pos)
+		usbvision->comprblock_pos = block_pos;
+	if (block_pos > strip_len)
+		usbvision->strip_len_errors++;
 
-	for (Idx = 0; Idx < IdxEnd; Idx++) {
-		if(frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) {
-			*f++ = Y[Idx];
-			*f++ = Idx & 0x01 ? U[Idx/2] : V[Idx/2];
-		}
-		else if(frame->v4l2_format.format == V4L2_PIX_FMT_YUV422P) {
-			*f++ = Y[Idx];
-			if ( Idx & 0x01)
-				*u++ = U[Idx>>1] ;
+	for (idx = 0; idx < idx_end; idx++) {
+		if (frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) {
+			*f++ = Y[idx];
+			*f++ = idx & 0x01 ? U[idx / 2] : V[idx / 2];
+		} else if (frame->v4l2_format.format == V4L2_PIX_FMT_YUV422P) {
+			*f++ = Y[idx];
+			if (idx & 0x01)
+				*u++ = U[idx >> 1];
 			else
-				*v++ = V[Idx>>1];
-		}
-		else if (frame->v4l2_format.format == V4L2_PIX_FMT_YVU420) {
-			*f++ = Y [Idx];
-			if ( !((  Idx & 0x01  ) | (  frame->curline & 0x01  )) ){
-
-/* 				 only need do this for 1 in 4 pixels */
-/* 				 intraframe buffer is YUV420 format */
-
-				*u++ = U[Idx >>1];
-				*v++ = V[Idx >>1];
+				*v++ = V[idx >> 1];
+		} else if (frame->v4l2_format.format == V4L2_PIX_FMT_YVU420) {
+			*f++ = Y[idx];
+			if (!((idx & 0x01) | (frame->curline & 0x01))) {
+				/* only need do this for 1 in 4 pixels */
+				/* intraframe buffer is YUV420 format */
+				*u++ = U[idx >> 1];
+				*v++ = V[idx >> 1];
 			}
-
-		}
-		else {
-			YUV_TO_RGB_BY_THE_BOOK(Y[Idx], U[Idx/2], V[Idx/2], rv, gv, bv);
+		} else {
+			YUV_TO_RGB_BY_THE_BOOK(Y[idx], U[idx / 2], V[idx / 2], rv, gv, bv);
 			switch (frame->v4l2_format.format) {
-				case V4L2_PIX_FMT_GREY:
-					*f++ = Y[Idx];
-					break;
-				case V4L2_PIX_FMT_RGB555:
-					*f++ = (0x1F & rv) |
-						(0xE0 & (gv << 5));
-					*f++ = (0x03 & (gv >> 3)) |
-						(0x7C & (bv << 2));
-					break;
-				case V4L2_PIX_FMT_RGB565:
-					*f++ = (0x1F & rv) |
-						(0xE0 & (gv << 5));
-					*f++ = (0x07 & (gv >> 3)) |
-						(0xF8 &  bv);
-					break;
-				case V4L2_PIX_FMT_RGB24:
-					*f++ = rv;
-					*f++ = gv;
-					*f++ = bv;
-					break;
-				case V4L2_PIX_FMT_RGB32:
-					*f++ = rv;
-					*f++ = gv;
-					*f++ = bv;
-					f++;
-					break;
+			case V4L2_PIX_FMT_GREY:
+				*f++ = Y[idx];
+				break;
+			case V4L2_PIX_FMT_RGB555:
+				*f++ = (0x1F & rv) |
+					(0xE0 & (gv << 5));
+				*f++ = (0x03 & (gv >> 3)) |
+					(0x7C & (bv << 2));
+				break;
+			case V4L2_PIX_FMT_RGB565:
+				*f++ = (0x1F & rv) |
+					(0xE0 & (gv << 5));
+				*f++ = (0x07 & (gv >> 3)) |
+					(0xF8 & bv);
+				break;
+			case V4L2_PIX_FMT_RGB24:
+				*f++ = rv;
+				*f++ = gv;
+				*f++ = bv;
+				break;
+			case V4L2_PIX_FMT_RGB32:
+				*f++ = rv;
+				*f++ = gv;
+				*f++ = bv;
+				f++;
+				break;
 			}
 		}
 		clipmask_index++;
 	}
 	/* Deal with non-integer no. of bytes for YUV420P */
-	if (frame->v4l2_format.format != V4L2_PIX_FMT_YVU420 )
+	if (frame->v4l2_format.format != V4L2_PIX_FMT_YVU420)
 		*pcopylen += frame->v4l2_linesize;
 	else
 		*pcopylen += frame->curline & 0x01 ? frame->v4l2_linesize : frame->v4l2_linesize << 1;
 
 	frame->curline += 1;
 
-	if (frame->curline >= frame->frmheight) {
-		return ParseState_NextFrame;
-	}
-	else {
-		return ParseState_Continue;
-	}
+	if (frame->curline >= frame->frmheight)
+		return parse_state_next_frame;
+	return parse_state_continue;
 
 }
 
@@ -1008,7 +961,7 @@ static enum ParseState usbvision_parse_c
  * number of bytes (RGB) to the *pcopylen.
  *
  */
-static enum ParseState usbvision_parse_lines_420(struct usb_usbvision *usbvision,
+static enum parse_state usbvision_parse_lines_420(struct usb_usbvision *usbvision,
 					   long *pcopylen)
 {
 	struct usbvision_frame *frame;
@@ -1016,11 +969,11 @@ static enum ParseState usbvision_parse_l
 	unsigned int pixel_per_line, block;
 	int pixel, block_split;
 	int y_ptr, u_ptr, v_ptr, y_odd_offset;
-	const int   y_block_size = 128;
-	const int  uv_block_size = 64;
+	const int y_block_size = 128;
+	const int uv_block_size = 64;
 	const int sub_block_size = 32;
-	const int y_step[] = { 0, 0, 0, 2 },  y_step_size = 4;
-	const int uv_step[]= { 0, 0, 0, 4 }, uv_step_size = 4;
+	const int y_step[] = { 0, 0, 0, 2 }, y_step_size = 4;
+	const int uv_step[] = { 0, 0, 0, 4 }, uv_step_size = 4;
 	unsigned char y[2], u, v;	/* YUV components */
 	int y_, u_, v_, vb, uvg, ur;
 	int r_, g_, b_;			/* RGB components */
@@ -1028,7 +981,7 @@ static enum ParseState usbvision_parse_l
 	int clipmask_even_index, clipmask_odd_index, bytes_per_pixel;
 	int clipmask_add, stretch_bytes;
 
-	frame  = usbvision->curFrame;
+	frame  = usbvision->cur_frame;
 	f_even = frame->data + (frame->v4l2_linesize * frame->curline);
 	f_odd  = f_even + frame->v4l2_linesize * usbvision->stretch_height;
 
@@ -1040,18 +993,17 @@ static enum ParseState usbvision_parse_l
 	clipmask_even_index = frame->curline * MAX_FRAME_WIDTH;
 	clipmask_odd_index  = clipmask_even_index + MAX_FRAME_WIDTH;
 	clipmask_add = usbvision->stretch_width;
-	pixel_per_line = frame->isocHeader.frameWidth;
+	pixel_per_line = frame->isoc_header.frame_width;
 
 	if (scratch_len(usbvision) < (int)pixel_per_line * 3) {
-		//printk(KERN_DEBUG "out of data, need %d\n", len);
-		return ParseState_Out;
+		/* printk(KERN_DEBUG "out of data, need %d\n", len); */
+		return parse_state_out;
 	}
 
-	if ((frame->curline + 1) >= frame->frmheight) {
-		return ParseState_NextFrame;
-	}
+	if ((frame->curline + 1) >= frame->frmheight)
+		return parse_state_next_frame;
 
-	block_split = (pixel_per_line%y_block_size) ? 1 : 0;	//are some blocks splitted into different lines?
+	block_split = (pixel_per_line%y_block_size) ? 1 : 0;	/* are some blocks splitted into different lines? */
 
 	y_odd_offset = (pixel_per_line / y_block_size) * (y_block_size + uv_block_size)
 			+ block_split * uv_block_size;
@@ -1061,31 +1013,27 @@ static enum ParseState usbvision_parse_l
 	scratch_set_extra_ptr(usbvision, &v_ptr, y_odd_offset
 			+ (4 - block_split) * sub_block_size);
 
-	for (block = 0; block < (pixel_per_line / sub_block_size);
-	     block++) {
-
-
-		for (pixel = 0; pixel < sub_block_size; pixel +=2) {
+	for (block = 0; block < (pixel_per_line / sub_block_size); block++) {
+		for (pixel = 0; pixel < sub_block_size; pixel += 2) {
 			scratch_get(usbvision, &y[0], 2);
 			scratch_get_extra(usbvision, &u, &u_ptr, 1);
 			scratch_get_extra(usbvision, &v, &v_ptr, 1);
 
-			//I don't use the YUV_TO_RGB macro for better performance
+			/* I don't use the YUV_TO_RGB macro for better performance */
 			v_ = v - 128;
 			u_ = u - 128;
-			vb =              132252 * v_;
-			uvg= -53281 * u_ - 25625 * v_;
+			vb = 132252 * v_;
+			uvg = -53281 * u_ - 25625 * v_;
 			ur = 104595 * u_;
 
-			if(frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) {
+			if (frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) {
 				*f_even++ = y[0];
 				*f_even++ = v;
-			}
-			else {
+			} else {
 				y_ = 76284 * (y[0] - 16);
 
 				b_ = (y_ + vb) >> 16;
-				g_ = (y_ + uvg)>> 16;
+				g_ = (y_ + uvg) >> 16;
 				r_ = (y_ + ur) >> 16;
 
 				switch (frame->v4l2_format.format) {
@@ -1121,15 +1069,14 @@ static enum ParseState usbvision_parse_l
 			clipmask_even_index += clipmask_add;
 			f_even += stretch_bytes;
 
-			if(frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) {
+			if (frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) {
 				*f_even++ = y[1];
 				*f_even++ = u;
-			}
-			else {
+			} else {
 				y_ = 76284 * (y[1] - 16);
 
 				b_ = (y_ + vb) >> 16;
-				g_ = (y_ + uvg)>> 16;
+				g_ = (y_ + uvg) >> 16;
 				r_ = (y_ + ur) >> 16;
 
 				switch (frame->v4l2_format.format) {
@@ -1167,15 +1114,14 @@ static enum ParseState usbvision_parse_l
 
 			scratch_get_extra(usbvision, &y[0], &y_ptr, 2);
 
-			if(frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) {
+			if (frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) {
 				*f_odd++ = y[0];
 				*f_odd++ = v;
-			}
-			else {
+			} else {
 				y_ = 76284 * (y[0] - 16);
 
 				b_ = (y_ + vb) >> 16;
-				g_ = (y_ + uvg)>> 16;
+				g_ = (y_ + uvg) >> 16;
 				r_ = (y_ + ur) >> 16;
 
 				switch (frame->v4l2_format.format) {
@@ -1211,15 +1157,14 @@ static enum ParseState usbvision_parse_l
 			clipmask_odd_index += clipmask_add;
 			f_odd += stretch_bytes;
 
-			if(frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) {
+			if (frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) {
 				*f_odd++ = y[1];
 				*f_odd++ = u;
-			}
-			else {
+			} else {
 				y_ = 76284 * (y[1] - 16);
 
 				b_ = (y_ + vb) >> 16;
-				g_ = (y_ + uvg)>> 16;
+				g_ = (y_ + uvg) >> 16;
 				r_ = (y_ + ur) >> 16;
 
 				switch (frame->v4l2_format.format) {
@@ -1256,7 +1201,7 @@ static enum ParseState usbvision_parse_l
 			f_odd += stretch_bytes;
 		}
 
-		scratch_rm_old(usbvision,y_step[block % y_step_size] * sub_block_size);
+		scratch_rm_old(usbvision, y_step[block % y_step_size] * sub_block_size);
 		scratch_inc_extra_ptr(&y_ptr, y_step[(block + 2 * block_split) % y_step_size]
 				* sub_block_size);
 		scratch_inc_extra_ptr(&u_ptr, uv_step[block % uv_step_size]
@@ -1272,9 +1217,8 @@ static enum ParseState usbvision_parse_l
 	*pcopylen += frame->v4l2_linesize * 2 * usbvision->stretch_height;
 
 	if (frame->curline >= frame->frmheight)
-		return ParseState_NextFrame;
-	else
-		return ParseState_Continue;
+		return parse_state_next_frame;
+	return parse_state_continue;
 }
 
 /*
@@ -1288,53 +1232,43 @@ static enum ParseState usbvision_parse_l
 static void usbvision_parse_data(struct usb_usbvision *usbvision)
 {
 	struct usbvision_frame *frame;
-	enum ParseState newstate;
+	enum parse_state newstate;
 	long copylen = 0;
 	unsigned long lock_flags;
 
-	frame = usbvision->curFrame;
+	frame = usbvision->cur_frame;
 
 	PDEBUG(DBG_PARSE, "parsing len=%d\n", scratch_len(usbvision));
 
 	while (1) {
-
-		newstate = ParseState_Out;
+		newstate = parse_state_out;
 		if (scratch_len(usbvision)) {
-			if (frame->scanstate == ScanState_Scanning) {
+			if (frame->scanstate == scan_state_scanning) {
 				newstate = usbvision_find_header(usbvision);
-			}
-			else if (frame->scanstate == ScanState_Lines) {
-				if (usbvision->isocMode == ISOC_MODE_YUV420) {
+			} else if (frame->scanstate == scan_state_lines) {
+				if (usbvision->isoc_mode == ISOC_MODE_YUV420)
 					newstate = usbvision_parse_lines_420(usbvision, &copylen);
-				}
-				else if (usbvision->isocMode == ISOC_MODE_YUV422) {
+				else if (usbvision->isoc_mode == ISOC_MODE_YUV422)
 					newstate = usbvision_parse_lines_422(usbvision, &copylen);
-				}
-				else if (usbvision->isocMode == ISOC_MODE_COMPRESS) {
+				else if (usbvision->isoc_mode == ISOC_MODE_COMPRESS)
 					newstate = usbvision_parse_compress(usbvision, &copylen);
-				}
-
 			}
 		}
-		if (newstate == ParseState_Continue) {
+		if (newstate == parse_state_continue)
 			continue;
-		}
-		else if ((newstate == ParseState_NextFrame) || (newstate == ParseState_Out)) {
+		if ((newstate == parse_state_next_frame) || (newstate == parse_state_out))
 			break;
-		}
-		else {
-			return;	/* ParseState_EndParse */
-		}
+		return;	/* parse_state_end_parse */
 	}
 
-	if (newstate == ParseState_NextFrame) {
-		frame->grabstate = FrameState_Done;
+	if (newstate == parse_state_next_frame) {
+		frame->grabstate = frame_state_done;
 		do_gettimeofday(&(frame->timestamp));
 		frame->sequence = usbvision->frame_num;
 
 		spin_lock_irqsave(&usbvision->queue_lock, lock_flags);
 		list_move_tail(&(frame->frame), &usbvision->outqueue);
-		usbvision->curFrame = NULL;
+		usbvision->cur_frame = NULL;
 		spin_unlock_irqrestore(&usbvision->queue_lock, lock_flags);
 
 		usbvision->frame_num++;
@@ -1344,10 +1278,9 @@ static void usbvision_parse_data(struct
 			PDEBUG(DBG_PARSE, "Wake up !");
 			wake_up_interruptible(&usbvision->wait_frame);
 		}
+	} else {
+		frame->grabstate = frame_state_grabbing;
 	}
-	else
-		frame->grabstate = FrameState_Grabbing;
-
 
 	/* Update the frame's uncompressed length. */
 	frame->scanlength += copylen;
@@ -1370,34 +1303,32 @@ static int usbvision_compress_isochronou
 		packet_data = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
 
 		/* Detect and ignore errored packets */
-		if (packet_stat) {	// packet_stat != 0 ?????????????
+		if (packet_stat) {	/* packet_stat != 0 ????????????? */
 			PDEBUG(DBG_ISOC, "data error: [%d] len=%d, status=%X", i, packet_len, packet_stat);
-			usbvision->isocErrCount++;
+			usbvision->isoc_err_count++;
 			continue;
 		}
 
 		/* Detect and ignore empty packets */
 		if (packet_len < 0) {
 			PDEBUG(DBG_ISOC, "error packet [%d]", i);
-			usbvision->isocSkipCount++;
+			usbvision->isoc_skip_count++;
 			continue;
-		}
-		else if (packet_len == 0) {	/* Frame end ????? */
+		} else if (packet_len == 0) {	/* Frame end ????? */
 			PDEBUG(DBG_ISOC, "null packet [%d]", i);
-			usbvision->isocstate=IsocState_NoFrame;
-			usbvision->isocSkipCount++;
+			usbvision->isocstate = isoc_state_no_frame;
+			usbvision->isoc_skip_count++;
 			continue;
-		}
-		else if (packet_len > usbvision->isocPacketSize) {
-			PDEBUG(DBG_ISOC, "packet[%d] > isocPacketSize", i);
-			usbvision->isocSkipCount++;
+		} else if (packet_len > usbvision->isoc_packet_size) {
+			PDEBUG(DBG_ISOC, "packet[%d] > isoc_packet_size", i);
+			usbvision->isoc_skip_count++;
 			continue;
 		}
 
 		PDEBUG(DBG_ISOC, "packet ok [%d] len=%d", i, packet_len);
 
-		if (usbvision->isocstate==IsocState_NoFrame) { //new frame begins
-			usbvision->isocstate=IsocState_InFrame;
+		if (usbvision->isocstate == isoc_state_no_frame) { /* new frame begins */
+			usbvision->isocstate = isoc_state_in_frame;
 			scratch_mark_header(usbvision);
 			usbvision_measure_bandwidth(usbvision);
 			PDEBUG(DBG_ISOC, "packet with header");
@@ -1412,7 +1343,6 @@ static int usbvision_compress_isochronou
 		 * your favorite evil here.
 		 */
 		if (scratch_free(usbvision) < packet_len) {
-
 			usbvision->scratch_ovf_count++;
 			PDEBUG(DBG_ISOC, "scratch buf overflow! scr_len: %d, n: %d",
 			       scratch_len(usbvision), packet_len);
@@ -1422,12 +1352,13 @@ static int usbvision_compress_isochronou
 		/* Now we know that there is enough room in scratch buffer */
 		scratch_put(usbvision, packet_data, packet_len);
 		totlen += packet_len;
-		usbvision->isocDataCount += packet_len;
-		usbvision->isocPacketCount++;
+		usbvision->isoc_data_count += packet_len;
+		usbvision->isoc_packet_count++;
 	}
 #if ENABLE_HEXDUMP
 	if (totlen > 0) {
 		static int foo;
+
 		if (foo < 1) {
 			printk(KERN_DEBUG "+%d.\n", usbvision->scratchlen);
 			usbvision_hexdump(data0, (totlen > 64) ? 64 : totlen);
@@ -1435,16 +1366,16 @@ static int usbvision_compress_isochronou
 		}
 	}
 #endif
- return totlen;
+	return totlen;
 }
 
-static void usbvision_isocIrq(struct urb *urb)
+static void usbvision_isoc_irq(struct urb *urb)
 {
-	int errCode = 0;
+	int err_code = 0;
 	int len;
 	struct usb_usbvision *usbvision = urb->context;
 	int i;
-	unsigned long startTime = jiffies;
+	unsigned long start_time = jiffies;
 	struct usbvision_frame **f;
 
 	/* We don't want to do anything if we are about to be removed! */
@@ -1452,18 +1383,17 @@ static void usbvision_isocIrq(struct urb
 		return;
 
 	/* any urb with wrong status is ignored without acknowledgement */
-	if (urb->status == -ENOENT) {
+	if (urb->status == -ENOENT)
 		return;
-	}
 
-	f = &usbvision->curFrame;
+	f = &usbvision->cur_frame;
 
 	/* Manage streaming interruption */
-	if (usbvision->streaming == Stream_Interrupt) {
-		usbvision->streaming = Stream_Idle;
+	if (usbvision->streaming == stream_interrupt) {
+		usbvision->streaming = stream_idle;
 		if ((*f)) {
-			(*f)->grabstate = FrameState_Ready;
-			(*f)->scanstate = ScanState_Scanning;
+			(*f)->grabstate = frame_state_ready;
+			(*f)->scanstate = scan_state_scanning;
 		}
 		PDEBUG(DBG_IRQ, "stream interrupted");
 		wake_up_interruptible(&usbvision->wait_stream);
@@ -1472,35 +1402,32 @@ static void usbvision_isocIrq(struct urb
 	/* Copy the data received into our scratch buffer */
 	len = usbvision_compress_isochronous(usbvision, urb);
 
-	usbvision->isocUrbCount++;
+	usbvision->isoc_urb_count++;
 	usbvision->urb_length = len;
 
-	if (usbvision->streaming == Stream_On) {
-
+	if (usbvision->streaming == stream_on) {
 		/* If we collected enough data let's parse! */
-		if ((scratch_len(usbvision) > USBVISION_HEADER_LENGTH) &&
-		    (!list_empty(&(usbvision->inqueue))) ) {
+		if (scratch_len(usbvision) > USBVISION_HEADER_LENGTH &&
+		    !list_empty(&(usbvision->inqueue))) {
 			if (!(*f)) {
 				(*f) = list_entry(usbvision->inqueue.next,
 						  struct usbvision_frame,
 						  frame);
 			}
 			usbvision_parse_data(usbvision);
-		}
-		else {
-			/*If we don't have a frame
+		} else {
+			/* If we don't have a frame
 			  we're current working on, complain */
 			PDEBUG(DBG_IRQ,
 			       "received data, but no one needs it");
 			scratch_reset(usbvision);
 		}
-	}
-	else {
+	} else {
 		PDEBUG(DBG_IRQ, "received data, but no one needs it");
 		scratch_reset(usbvision);
 	}
 
-	usbvision->timeInIrq += jiffies - startTime;
+	usbvision->time_in_irq += jiffies - start_time;
 
 	for (i = 0; i < USBVISION_URB_FRAMES; i++) {
 		urb->iso_frame_desc[i].status = 0;
@@ -1509,12 +1436,12 @@ static void usbvision_isocIrq(struct urb
 
 	urb->status = 0;
 	urb->dev = usbvision->dev;
-	errCode = usb_submit_urb (urb, GFP_ATOMIC);
+	err_code = usb_submit_urb(urb, GFP_ATOMIC);
 
-	if(errCode) {
+	if (err_code) {
 		dev_err(&usbvision->dev->dev,
 			"%s: usb_submit_urb failed: error %d\n",
-				__func__, errCode);
+				__func__, err_code);
 	}
 
 	return;
@@ -1533,21 +1460,21 @@ static void usbvision_isocIrq(struct urb
 
 int usbvision_read_reg(struct usb_usbvision *usbvision, unsigned char reg)
 {
-	int errCode = 0;
+	int err_code = 0;
 	unsigned char buffer[1];
 
 	if (!USBVISION_IS_OPERATIONAL(usbvision))
 		return -1;
 
-	errCode = usb_control_msg(usbvision->dev, usb_rcvctrlpipe(usbvision->dev, 1),
+	err_code = usb_control_msg(usbvision->dev, usb_rcvctrlpipe(usbvision->dev, 1),
 				USBVISION_OP_CODE,
 				USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT,
 				0, (__u16) reg, buffer, 1, HZ);
 
-	if (errCode < 0) {
+	if (err_code < 0) {
 		dev_err(&usbvision->dev->dev,
-			"%s: failed: error %d\n", __func__, errCode);
-		return errCode;
+			"%s: failed: error %d\n", __func__, err_code);
+		return err_code;
 	}
 	return buffer[0];
 }
@@ -1563,179 +1490,176 @@ int usbvision_read_reg(struct usb_usbvis
 int usbvision_write_reg(struct usb_usbvision *usbvision, unsigned char reg,
 			    unsigned char value)
 {
-	int errCode = 0;
+	int err_code = 0;
 
 	if (!USBVISION_IS_OPERATIONAL(usbvision))
 		return 0;
 
-	errCode = usb_control_msg(usbvision->dev, usb_sndctrlpipe(usbvision->dev, 1),
+	err_code = usb_control_msg(usbvision->dev, usb_sndctrlpipe(usbvision->dev, 1),
 				USBVISION_OP_CODE,
 				USB_DIR_OUT | USB_TYPE_VENDOR |
 				USB_RECIP_ENDPOINT, 0, (__u16) reg, &value, 1, HZ);
 
-	if (errCode < 0) {
+	if (err_code < 0) {
 		dev_err(&usbvision->dev->dev,
-			"%s: failed: error %d\n", __func__, errCode);
+			"%s: failed: error %d\n", __func__, err_code);
 	}
-	return errCode;
+	return err_code;
 }
 
 
-static void usbvision_ctrlUrb_complete(struct urb *urb)
+static void usbvision_ctrl_urb_complete(struct urb *urb)
 {
 	struct usb_usbvision *usbvision = (struct usb_usbvision *)urb->context;
 
 	PDEBUG(DBG_IRQ, "");
-	usbvision->ctrlUrbBusy = 0;
-	if (waitqueue_active(&usbvision->ctrlUrb_wq)) {
-		wake_up_interruptible(&usbvision->ctrlUrb_wq);
-	}
+	usbvision->ctrl_urb_busy = 0;
+	if (waitqueue_active(&usbvision->ctrl_urb_wq))
+		wake_up_interruptible(&usbvision->ctrl_urb_wq);
 }
 
 
-static int usbvision_write_reg_irq(struct usb_usbvision *usbvision,int address,
-									unsigned char *data, int len)
+static int usbvision_write_reg_irq(struct usb_usbvision *usbvision, int address,
+				unsigned char *data, int len)
 {
-	int errCode = 0;
+	int err_code = 0;
 
 	PDEBUG(DBG_IRQ, "");
-	if (len > 8) {
+	if (len > 8)
 		return -EFAULT;
-	}
-	if (usbvision->ctrlUrbBusy) {
+	if (usbvision->ctrl_urb_busy)
 		return -EBUSY;
-	}
-	usbvision->ctrlUrbBusy = 1;
+	usbvision->ctrl_urb_busy = 1;
 
-	usbvision->ctrlUrbSetup.bRequestType = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT;
-	usbvision->ctrlUrbSetup.bRequest     = USBVISION_OP_CODE;
-	usbvision->ctrlUrbSetup.wValue       = 0;
-	usbvision->ctrlUrbSetup.wIndex       = cpu_to_le16(address);
-	usbvision->ctrlUrbSetup.wLength      = cpu_to_le16(len);
-	usb_fill_control_urb (usbvision->ctrlUrb, usbvision->dev,
+	usbvision->ctrl_urb_setup.bRequestType = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT;
+	usbvision->ctrl_urb_setup.bRequest     = USBVISION_OP_CODE;
+	usbvision->ctrl_urb_setup.wValue       = 0;
+	usbvision->ctrl_urb_setup.wIndex       = cpu_to_le16(address);
+	usbvision->ctrl_urb_setup.wLength      = cpu_to_le16(len);
+	usb_fill_control_urb(usbvision->ctrl_urb, usbvision->dev,
 							usb_sndctrlpipe(usbvision->dev, 1),
-							(unsigned char *)&usbvision->ctrlUrbSetup,
-							(void *)usbvision->ctrlUrbBuffer, len,
-							usbvision_ctrlUrb_complete,
+							(unsigned char *)&usbvision->ctrl_urb_setup,
+							(void *)usbvision->ctrl_urb_buffer, len,
+							usbvision_ctrl_urb_complete,
 							(void *)usbvision);
 
-	memcpy(usbvision->ctrlUrbBuffer, data, len);
+	memcpy(usbvision->ctrl_urb_buffer, data, len);
 
-	errCode = usb_submit_urb(usbvision->ctrlUrb, GFP_ATOMIC);
-	if (errCode < 0) {
-		// error in usb_submit_urb()
-		usbvision->ctrlUrbBusy = 0;
+	err_code = usb_submit_urb(usbvision->ctrl_urb, GFP_ATOMIC);
+	if (err_code < 0) {
+		/* error in usb_submit_urb() */
+		usbvision->ctrl_urb_busy = 0;
 	}
-	PDEBUG(DBG_IRQ, "submit %d byte: error %d", len, errCode);
-	return errCode;
+	PDEBUG(DBG_IRQ, "submit %d byte: error %d", len, err_code);
+	return err_code;
 }
 
 
 static int usbvision_init_compression(struct usb_usbvision *usbvision)
 {
-	int errCode = 0;
+	int err_code = 0;
 
-	usbvision->lastIsocFrameNum = -1;
-	usbvision->isocDataCount = 0;
-	usbvision->isocPacketCount = 0;
-	usbvision->isocSkipCount = 0;
-	usbvision->comprLevel = 50;
-	usbvision->lastComprLevel = -1;
-	usbvision->isocUrbCount = 0;
-	usbvision->requestIntra = 1;
-	usbvision->isocMeasureBandwidthCount = 0;
+	usbvision->last_isoc_frame_num = -1;
+	usbvision->isoc_data_count = 0;
+	usbvision->isoc_packet_count = 0;
+	usbvision->isoc_skip_count = 0;
+	usbvision->compr_level = 50;
+	usbvision->last_compr_level = -1;
+	usbvision->isoc_urb_count = 0;
+	usbvision->request_intra = 1;
+	usbvision->isoc_measure_bandwidth_count = 0;
 
-	return errCode;
+	return err_code;
 }
 
 /* this function measures the used bandwidth since last call
  * return:    0 : no error
- * sets usedBandwidth to 1-100 : 1-100% of full bandwidth resp. to isocPacketSize
+ * sets used_bandwidth to 1-100 : 1-100% of full bandwidth resp. to isoc_packet_size
  */
-static int usbvision_measure_bandwidth (struct usb_usbvision *usbvision)
+static int usbvision_measure_bandwidth(struct usb_usbvision *usbvision)
 {
-	int errCode = 0;
+	int err_code = 0;
 
-	if (usbvision->isocMeasureBandwidthCount < 2) { // this gives an average bandwidth of 3 frames
-		usbvision->isocMeasureBandwidthCount++;
-		return errCode;
+	if (usbvision->isoc_measure_bandwidth_count < 2) { /* this gives an average bandwidth of 3 frames */
+		usbvision->isoc_measure_bandwidth_count++;
+		return err_code;
 	}
-	if ((usbvision->isocPacketSize > 0) && (usbvision->isocPacketCount > 0)) {
-		usbvision->usedBandwidth = usbvision->isocDataCount /
-					(usbvision->isocPacketCount + usbvision->isocSkipCount) *
-					100 / usbvision->isocPacketSize;
+	if ((usbvision->isoc_packet_size > 0) && (usbvision->isoc_packet_count > 0)) {
+		usbvision->used_bandwidth = usbvision->isoc_data_count /
+					(usbvision->isoc_packet_count + usbvision->isoc_skip_count) *
+					100 / usbvision->isoc_packet_size;
 	}
-	usbvision->isocMeasureBandwidthCount = 0;
-	usbvision->isocDataCount = 0;
-	usbvision->isocPacketCount = 0;
-	usbvision->isocSkipCount = 0;
-	return errCode;
+	usbvision->isoc_measure_bandwidth_count = 0;
+	usbvision->isoc_data_count = 0;
+	usbvision->isoc_packet_count = 0;
+	usbvision->isoc_skip_count = 0;
+	return err_code;
 }
 
-static int usbvision_adjust_compression (struct usb_usbvision *usbvision)
+static int usbvision_adjust_compression(struct usb_usbvision *usbvision)
 {
-	int errCode = 0;
+	int err_code = 0;
 	unsigned char buffer[6];
 
 	PDEBUG(DBG_IRQ, "");
-	if ((adjustCompression) && (usbvision->usedBandwidth > 0)) {
-		usbvision->comprLevel += (usbvision->usedBandwidth - 90) / 2;
-		RESTRICT_TO_RANGE(usbvision->comprLevel, 0, 100);
-		if (usbvision->comprLevel != usbvision->lastComprLevel) {
-			int distorsion;
-			if (usbvision->bridgeType == BRIDGE_NT1004 || usbvision->bridgeType == BRIDGE_NT1005) {
-				buffer[0] = (unsigned char)(4 + 16 * usbvision->comprLevel / 100);	// PCM Threshold 1
-				buffer[1] = (unsigned char)(4 + 8 * usbvision->comprLevel / 100);	// PCM Threshold 2
-				distorsion = 7 + 248 * usbvision->comprLevel / 100;
-				buffer[2] = (unsigned char)(distorsion & 0xFF);				// Average distorsion Threshold (inter)
-				buffer[3] = (unsigned char)(distorsion & 0xFF);				// Average distorsion Threshold (intra)
-				distorsion = 1 + 42 * usbvision->comprLevel / 100;
-				buffer[4] = (unsigned char)(distorsion & 0xFF);				// Maximum distorsion Threshold (inter)
-				buffer[5] = (unsigned char)(distorsion & 0xFF);				// Maximum distorsion Threshold (intra)
-			}
-			else { //BRIDGE_NT1003
-				buffer[0] = (unsigned char)(4 + 16 * usbvision->comprLevel / 100);	// PCM threshold 1
-				buffer[1] = (unsigned char)(4 + 8 * usbvision->comprLevel / 100);	// PCM threshold 2
-				distorsion = 2 + 253 * usbvision->comprLevel / 100;
-				buffer[2] = (unsigned char)(distorsion & 0xFF);				// distorsion threshold bit0-7
-				buffer[3] = 0; 	//(unsigned char)((distorsion >> 8) & 0x0F);		// distorsion threshold bit 8-11
-				distorsion = 0 + 43 * usbvision->comprLevel / 100;
-				buffer[4] = (unsigned char)(distorsion & 0xFF);				// maximum distorsion bit0-7
-				buffer[5] = 0; //(unsigned char)((distorsion >> 8) & 0x01);		// maximum distorsion bit 8
+	if ((adjust_compression) && (usbvision->used_bandwidth > 0)) {
+		usbvision->compr_level += (usbvision->used_bandwidth - 90) / 2;
+		RESTRICT_TO_RANGE(usbvision->compr_level, 0, 100);
+		if (usbvision->compr_level != usbvision->last_compr_level) {
+			int distortion;
+
+			if (usbvision->bridge_type == BRIDGE_NT1004 || usbvision->bridge_type == BRIDGE_NT1005) {
+				buffer[0] = (unsigned char)(4 + 16 * usbvision->compr_level / 100);	/* PCM Threshold 1 */
+				buffer[1] = (unsigned char)(4 + 8 * usbvision->compr_level / 100);	/* PCM Threshold 2 */
+				distortion = 7 + 248 * usbvision->compr_level / 100;
+				buffer[2] = (unsigned char)(distortion & 0xFF);				/* Average distortion Threshold (inter) */
+				buffer[3] = (unsigned char)(distortion & 0xFF);				/* Average distortion Threshold (intra) */
+				distortion = 1 + 42 * usbvision->compr_level / 100;
+				buffer[4] = (unsigned char)(distortion & 0xFF);				/* Maximum distortion Threshold (inter) */
+				buffer[5] = (unsigned char)(distortion & 0xFF);				/* Maximum distortion Threshold (intra) */
+			} else { /* BRIDGE_NT1003 */
+				buffer[0] = (unsigned char)(4 + 16 * usbvision->compr_level / 100);	/* PCM threshold 1 */
+				buffer[1] = (unsigned char)(4 + 8 * usbvision->compr_level / 100);	/* PCM threshold 2 */
+				distortion = 2 + 253 * usbvision->compr_level / 100;
+				buffer[2] = (unsigned char)(distortion & 0xFF);				/* distortion threshold bit0-7 */
+				buffer[3] = 0;	/* (unsigned char)((distortion >> 8) & 0x0F);		distortion threshold bit 8-11 */
+				distortion = 0 + 43 * usbvision->compr_level / 100;
+				buffer[4] = (unsigned char)(distortion & 0xFF);				/* maximum distortion bit0-7 */
+				buffer[5] = 0; /* (unsigned char)((distortion >> 8) & 0x01);		maximum distortion bit 8 */
 			}
-			errCode = usbvision_write_reg_irq(usbvision, USBVISION_PCM_THR1, buffer, 6);
-			if (errCode == 0){
+			err_code = usbvision_write_reg_irq(usbvision, USBVISION_PCM_THR1, buffer, 6);
+			if (err_code == 0) {
 				PDEBUG(DBG_IRQ, "new compr params %#02x %#02x %#02x %#02x %#02x %#02x", buffer[0],
 								buffer[1], buffer[2], buffer[3], buffer[4], buffer[5]);
-				usbvision->lastComprLevel = usbvision->comprLevel;
+				usbvision->last_compr_level = usbvision->compr_level;
 			}
 		}
 	}
-	return errCode;
+	return err_code;
 }
 
-static int usbvision_request_intra (struct usb_usbvision *usbvision)
+static int usbvision_request_intra(struct usb_usbvision *usbvision)
 {
-	int errCode = 0;
+	int err_code = 0;
 	unsigned char buffer[1];
 
 	PDEBUG(DBG_IRQ, "");
-	usbvision->requestIntra = 1;
+	usbvision->request_intra = 1;
 	buffer[0] = 1;
 	usbvision_write_reg_irq(usbvision, USBVISION_FORCE_INTRA, buffer, 1);
-	return errCode;
+	return err_code;
 }
 
-static int usbvision_unrequest_intra (struct usb_usbvision *usbvision)
+static int usbvision_unrequest_intra(struct usb_usbvision *usbvision)
 {
-	int errCode = 0;
+	int err_code = 0;
 	unsigned char buffer[1];
 
 	PDEBUG(DBG_IRQ, "");
-	usbvision->requestIntra = 0;
+	usbvision->request_intra = 0;
 	buffer[0] = 0;
 	usbvision_write_reg_irq(usbvision, USBVISION_FORCE_INTRA, buffer, 1);
-	return errCode;
+	return err_code;
 }
 
 /*******************************
@@ -1744,16 +1668,15 @@ static int usbvision_unrequest_intra (st
 
 int usbvision_power_off(struct usb_usbvision *usbvision)
 {
-	int errCode = 0;
+	int err_code = 0;
 
 	PDEBUG(DBG_FUNC, "");
 
-	errCode = usbvision_write_reg(usbvision, USBVISION_PWR_REG, USBVISION_SSPND_EN);
-	if (errCode == 1) {
+	err_code = usbvision_write_reg(usbvision, USBVISION_PWR_REG, USBVISION_SSPND_EN);
+	if (err_code == 1)
 		usbvision->power = 0;
-	}
-	PDEBUG(DBG_FUNC, "%s: errCode %d", (errCode!=1)?"ERROR":"power is off", errCode);
-	return errCode;
+	PDEBUG(DBG_FUNC, "%s: err_code %d", (err_code != 1) ? "ERROR" : "power is off", err_code);
+	return err_code;
 }
 
 /*
@@ -1769,7 +1692,7 @@ static int usbvision_set_video_format(st
 	if (!USBVISION_IS_OPERATIONAL(usbvision))
 		return 0;
 
-	PDEBUG(DBG_FUNC, "isocMode %#02x", format);
+	PDEBUG(DBG_FUNC, "isoc_mode %#02x", format);
 
 	if ((format != ISOC_MODE_YUV422)
 	    && (format != ISOC_MODE_YUV420)
@@ -1778,8 +1701,8 @@ static int usbvision_set_video_format(st
 		       format);
 		format = ISOC_MODE_YUV420;
 	}
-	value[0] = 0x0A;  //TODO: See the effect of the filter
-	value[1] = format; // Sets the VO_MODE register which follows FILT_CONT
+	value[0] = 0x0A;  /* TODO: See the effect of the filter */
+	value[1] = format; /* Sets the VO_MODE register which follows FILT_CONT */
 	rc = usb_control_msg(usbvision->dev, usb_sndctrlpipe(usbvision->dev, 1),
 			     USBVISION_OP_CODE,
 			     USB_DIR_OUT | USB_TYPE_VENDOR |
@@ -1790,7 +1713,7 @@ static int usbvision_set_video_format(st
 		printk(KERN_ERR "%s: ERROR=%d. USBVISION stopped - "
 		       "reconnect or reload driver.\n", proc, rc);
 	}
-	usbvision->isocMode = format;
+	usbvision->isoc_mode = format;
 	return rc;
 }
 
@@ -1802,96 +1725,88 @@ static int usbvision_set_video_format(st
 int usbvision_set_output(struct usb_usbvision *usbvision, int width,
 			 int height)
 {
-	int errCode = 0;
-	int UsbWidth, UsbHeight;
-	unsigned int frameRate=0, frameDrop=0;
+	int err_code = 0;
+	int usb_width, usb_height;
+	unsigned int frame_rate = 0, frame_drop = 0;
 	unsigned char value[4];
 
-	if (!USBVISION_IS_OPERATIONAL(usbvision)) {
+	if (!USBVISION_IS_OPERATIONAL(usbvision))
 		return 0;
-	}
 
 	if (width > MAX_USB_WIDTH) {
-		UsbWidth = width / 2;
+		usb_width = width / 2;
 		usbvision->stretch_width = 2;
-	}
-	else {
-		UsbWidth = width;
+	} else {
+		usb_width = width;
 		usbvision->stretch_width = 1;
 	}
 
 	if (height > MAX_USB_HEIGHT) {
-		UsbHeight = height / 2;
+		usb_height = height / 2;
 		usbvision->stretch_height = 2;
-	}
-	else {
-		UsbHeight = height;
+	} else {
+		usb_height = height;
 		usbvision->stretch_height = 1;
 	}
 
-	RESTRICT_TO_RANGE(UsbWidth, MIN_FRAME_WIDTH, MAX_USB_WIDTH);
-	UsbWidth &= ~(MIN_FRAME_WIDTH-1);
-	RESTRICT_TO_RANGE(UsbHeight, MIN_FRAME_HEIGHT, MAX_USB_HEIGHT);
-	UsbHeight &= ~(1);
+	RESTRICT_TO_RANGE(usb_width, MIN_FRAME_WIDTH, MAX_USB_WIDTH);
+	usb_width &= ~(MIN_FRAME_WIDTH-1);
+	RESTRICT_TO_RANGE(usb_height, MIN_FRAME_HEIGHT, MAX_USB_HEIGHT);
+	usb_height &= ~(1);
 
 	PDEBUG(DBG_FUNC, "usb %dx%d; screen %dx%d; stretch %dx%d",
-						UsbWidth, UsbHeight, width, height,
+						usb_width, usb_height, width, height,
 						usbvision->stretch_width, usbvision->stretch_height);
 
 	/* I'll not rewrite the same values */
-	if ((UsbWidth != usbvision->curwidth) || (UsbHeight != usbvision->curheight)) {
-		value[0] = UsbWidth & 0xff;		//LSB
-		value[1] = (UsbWidth >> 8) & 0x03;	//MSB
-		value[2] = UsbHeight & 0xff;		//LSB
-		value[3] = (UsbHeight >> 8) & 0x03;	//MSB
+	if ((usb_width != usbvision->curwidth) || (usb_height != usbvision->curheight)) {
+		value[0] = usb_width & 0xff;		/* LSB */
+		value[1] = (usb_width >> 8) & 0x03;	/* MSB */
+		value[2] = usb_height & 0xff;		/* LSB */
+		value[3] = (usb_height >> 8) & 0x03;	/* MSB */
 
-		errCode = usb_control_msg(usbvision->dev, usb_sndctrlpipe(usbvision->dev, 1),
+		err_code = usb_control_msg(usbvision->dev, usb_sndctrlpipe(usbvision->dev, 1),
 			     USBVISION_OP_CODE,
 			     USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT,
 				 0, (__u16) USBVISION_LXSIZE_O, value, 4, HZ);
 
-		if (errCode < 0) {
+		if (err_code < 0) {
 			dev_err(&usbvision->dev->dev,
-				"%s failed: error %d\n", __func__, errCode);
-			return errCode;
+				"%s failed: error %d\n", __func__, err_code);
+			return err_code;
 		}
-		usbvision->curwidth = usbvision->stretch_width * UsbWidth;
-		usbvision->curheight = usbvision->stretch_height * UsbHeight;
+		usbvision->curwidth = usbvision->stretch_width * usb_width;
+		usbvision->curheight = usbvision->stretch_height * usb_height;
 	}
 
-	if (usbvision->isocMode == ISOC_MODE_YUV422) {
-		frameRate = (usbvision->isocPacketSize * 1000) / (UsbWidth * UsbHeight * 2);
-	}
-	else if (usbvision->isocMode == ISOC_MODE_YUV420) {
-		frameRate = (usbvision->isocPacketSize * 1000) / ((UsbWidth * UsbHeight * 12) / 8);
-	}
-	else {
-		frameRate = FRAMERATE_MAX;
-	}
+	if (usbvision->isoc_mode == ISOC_MODE_YUV422)
+		frame_rate = (usbvision->isoc_packet_size * 1000) / (usb_width * usb_height * 2);
+	else if (usbvision->isoc_mode == ISOC_MODE_YUV420)
+		frame_rate = (usbvision->isoc_packet_size * 1000) / ((usb_width * usb_height * 12) / 8);
+	else
+		frame_rate = FRAMERATE_MAX;
 
-	if (usbvision->tvnormId & V4L2_STD_625_50) {
-		frameDrop = frameRate * 32 / 25 - 1;
-	}
-	else if (usbvision->tvnormId & V4L2_STD_525_60) {
-		frameDrop = frameRate * 32 / 30 - 1;
-	}
+	if (usbvision->tvnorm_id & V4L2_STD_625_50)
+		frame_drop = frame_rate * 32 / 25 - 1;
+	else if (usbvision->tvnorm_id & V4L2_STD_525_60)
+		frame_drop = frame_rate * 32 / 30 - 1;
 
-	RESTRICT_TO_RANGE(frameDrop, FRAMERATE_MIN, FRAMERATE_MAX);
+	RESTRICT_TO_RANGE(frame_drop, FRAMERATE_MIN, FRAMERATE_MAX);
 
-	PDEBUG(DBG_FUNC, "frameRate %d fps, frameDrop %d", frameRate, frameDrop);
+	PDEBUG(DBG_FUNC, "frame_rate %d fps, frame_drop %d", frame_rate, frame_drop);
 
-	frameDrop = FRAMERATE_MAX; 	// We can allow the maximum here, because dropping is controlled
+	frame_drop = FRAMERATE_MAX;	/* We can allow the maximum here, because dropping is controlled */
 
-	/* frameDrop = 7; => framePhase = 1, 5, 9, 13, 17, 21, 25, 0, 4, 8, ...
-		=> frameSkip = 4;
-		=> frameRate = (7 + 1) * 25 / 32 = 200 / 32 = 6.25;
+	/* frame_drop = 7; => frame_phase = 1, 5, 9, 13, 17, 21, 25, 0, 4, 8, ...
+		=> frame_skip = 4;
+		=> frame_rate = (7 + 1) * 25 / 32 = 200 / 32 = 6.25;
 
-	   frameDrop = 9; => framePhase = 1, 5, 8, 11, 14, 17, 21, 24, 27, 1, 4, 8, ...
-	    => frameSkip = 4, 3, 3, 3, 3, 4, 3, 3, 3, 3, 4, ...
-		=> frameRate = (9 + 1) * 25 / 32 = 250 / 32 = 7.8125;
+	   frame_drop = 9; => frame_phase = 1, 5, 8, 11, 14, 17, 21, 24, 27, 1, 4, 8, ...
+	    => frame_skip = 4, 3, 3, 3, 3, 4, 3, 3, 3, 3, 4, ...
+		=> frame_rate = (9 + 1) * 25 / 32 = 250 / 32 = 7.8125;
 	*/
-	errCode = usbvision_write_reg(usbvision, USBVISION_FRM_RATE, frameDrop);
-	return errCode;
+	err_code = usbvision_write_reg(usbvision, USBVISION_FRM_RATE, frame_drop);
+	return err_code;
 }
 
 
@@ -1903,8 +1818,8 @@ int usbvision_frames_alloc(struct usb_us
 {
 	int i;
 
-	/*needs to be page aligned cause the buffers can be mapped individually! */
-	usbvision->max_frame_size =  PAGE_ALIGN(usbvision->curwidth *
+	/* needs to be page aligned cause the buffers can be mapped individually! */
+	usbvision->max_frame_size = PAGE_ALIGN(usbvision->curwidth *
 						usbvision->curheight *
 						usbvision->palette.bytes_per_pixel);
 
@@ -1912,9 +1827,9 @@ int usbvision_frames_alloc(struct usb_us
 	usbvision->num_frames = number_of_frames;
 	while (usbvision->num_frames > 0) {
 		usbvision->fbuf_size = usbvision->num_frames * usbvision->max_frame_size;
-		if((usbvision->fbuf = usbvision_rvmalloc(usbvision->fbuf_size))) {
+		usbvision->fbuf = usbvision_rvmalloc(usbvision->fbuf_size);
+		if (usbvision->fbuf)
 			break;
-		}
 		usbvision->num_frames--;
 	}
 
@@ -1925,7 +1840,7 @@ int usbvision_frames_alloc(struct usb_us
 	/* Allocate all buffers */
 	for (i = 0; i < usbvision->num_frames; i++) {
 		usbvision->frame[i].index = i;
-		usbvision->frame[i].grabstate = FrameState_Unused;
+		usbvision->frame[i].grabstate = frame_state_unused;
 		usbvision->frame[i].data = usbvision->fbuf +
 			i * usbvision->max_frame_size;
 		/*
@@ -1937,7 +1852,8 @@ int usbvision_frames_alloc(struct usb_us
 		usbvision->frame[i].height = usbvision->curheight;
 		usbvision->frame[i].bytes_read = 0;
 	}
-	PDEBUG(DBG_FUNC, "allocated %d frames (%d bytes per frame)",usbvision->num_frames,usbvision->max_frame_size);
+	PDEBUG(DBG_FUNC, "allocated %d frames (%d bytes per frame)",
+			usbvision->num_frames, usbvision->max_frame_size);
 	return usbvision->num_frames;
 }
 
@@ -1948,7 +1864,7 @@ int usbvision_frames_alloc(struct usb_us
 void usbvision_frames_free(struct usb_usbvision *usbvision)
 {
 	/* Have to free all that memory */
-	PDEBUG(DBG_FUNC, "free %d frames",usbvision->num_frames);
+	PDEBUG(DBG_FUNC, "free %d frames", usbvision->num_frames);
 
 	if (usbvision->fbuf != NULL) {
 		usbvision_rvfree(usbvision->fbuf, usbvision->fbuf_size);
@@ -1969,7 +1885,7 @@ void usbvision_empty_framequeues(struct
 	INIT_LIST_HEAD(&(usbvision->outqueue));
 
 	for (i = 0; i < USBVISION_NUMFRAMES; i++) {
-		usbvision->frame[i].grabstate = FrameState_Unused;
+		usbvision->frame[i].grabstate = frame_state_unused;
 		usbvision->frame[i].bytes_read = 0;
 	}
 }
@@ -1984,9 +1900,9 @@ int usbvision_stream_interrupt(struct us
 
 	/* stop reading from the device */
 
-	usbvision->streaming = Stream_Interrupt;
+	usbvision->streaming = stream_interrupt;
 	ret = wait_event_timeout(usbvision->wait_stream,
-				 (usbvision->streaming == Stream_Idle),
+				 (usbvision->streaming == stream_idle),
 				 msecs_to_jiffies(USBVISION_NUMSBUF*USBVISION_URB_FRAMES));
 	return ret;
 }
@@ -2002,19 +1918,19 @@ static int usbvision_set_compress_params
 	int rc;
 	unsigned char value[6];
 
-	value[0] = 0x0F;    // Intra-Compression cycle
-	value[1] = 0x01;    // Reg.45 one line per strip
-	value[2] = 0x00;    // Reg.46 Force intra mode on all new frames
-	value[3] = 0x00;    // Reg.47 FORCE_UP <- 0 normal operation (not force)
-	value[4] = 0xA2;    // Reg.48 BUF_THR I'm not sure if this does something in not compressed mode.
-	value[5] = 0x00;    // Reg.49 DVI_YUV This has nothing to do with compression
+	value[0] = 0x0F;    /* Intra-Compression cycle */
+	value[1] = 0x01;    /* Reg.45 one line per strip */
+	value[2] = 0x00;    /* Reg.46 Force intra mode on all new frames */
+	value[3] = 0x00;    /* Reg.47 FORCE_UP <- 0 normal operation (not force) */
+	value[4] = 0xA2;    /* Reg.48 BUF_THR I'm not sure if this does something in not compressed mode. */
+	value[5] = 0x00;    /* Reg.49 DVI_YUV This has nothing to do with compression */
 
-	//catched values for NT1004
-	// value[0] = 0xFF; // Never apply intra mode automatically
-	// value[1] = 0xF1; // Use full frame height for virtual strip width; One line per strip
-	// value[2] = 0x01; // Force intra mode on all new frames
-	// value[3] = 0x00; // Strip size 400 Bytes; do not force up
-	// value[4] = 0xA2; //
+	/* catched values for NT1004 */
+	/* value[0] = 0xFF; Never apply intra mode automatically */
+	/* value[1] = 0xF1; Use full frame height for virtual strip width; One line per strip */
+	/* value[2] = 0x01; Force intra mode on all new frames */
+	/* value[3] = 0x00; Strip size 400 Bytes; do not force up */
+	/* value[4] = 0xA2; */
 	if (!USBVISION_IS_OPERATIONAL(usbvision))
 		return 0;
 
@@ -2030,21 +1946,20 @@ static int usbvision_set_compress_params
 		return rc;
 	}
 
-	if (usbvision->bridgeType == BRIDGE_NT1004) {
-		value[0] =  20; // PCM Threshold 1
-		value[1] =  12; // PCM Threshold 2
-		value[2] = 255; // Distorsion Threshold inter
-		value[3] = 255; // Distorsion Threshold intra
-		value[4] =  43; // Max Distorsion inter
-		value[5] =  43; // Max Distorsion intra
-	}
-	else {
-		value[0] =  20; // PCM Threshold 1
-		value[1] =  12; // PCM Threshold 2
-		value[2] = 255; // Distorsion Threshold d7-d0
-		value[3] =   0; // Distorsion Threshold d11-d8
-		value[4] =  43; // Max Distorsion d7-d0
-		value[5] =   0; // Max Distorsion d8
+	if (usbvision->bridge_type == BRIDGE_NT1004) {
+		value[0] =  20; /* PCM Threshold 1 */
+		value[1] =  12; /* PCM Threshold 2 */
+		value[2] = 255; /* Distortion Threshold inter */
+		value[3] = 255; /* Distortion Threshold intra */
+		value[4] =  43; /* Max Distortion inter */
+		value[5] =  43; /* Max Distortion intra */
+	} else {
+		value[0] =  20; /* PCM Threshold 1 */
+		value[1] =  12; /* PCM Threshold 2 */
+		value[2] = 255; /* Distortion Threshold d7-d0 */
+		value[3] =   0; /* Distortion Threshold d11-d8 */
+		value[4] =  43; /* Max Distortion d7-d0 */
+		value[5] =   0; /* Max Distortion d8 */
 	}
 
 	if (!USBVISION_IS_OPERATIONAL(usbvision))
@@ -2059,10 +1974,7 @@ static int usbvision_set_compress_params
 	if (rc < 0) {
 		printk(KERN_ERR "%sERROR=%d. USBVISION stopped - "
 		       "reconnect or reload driver.\n", proc, rc);
-		return rc;
 	}
-
-
 	return rc;
 }
 
@@ -2085,9 +1997,9 @@ int usbvision_set_input(struct usb_usbvi
 		return 0;
 
 	/* Set input format expected from decoder*/
-	if (usbvision_device_data[usbvision->DevModel].Vin_Reg1_override) {
-		value[0] = usbvision_device_data[usbvision->DevModel].Vin_Reg1;
-	} else if(usbvision_device_data[usbvision->DevModel].Codec == CODEC_SAA7113) {
+	if (usbvision_device_data[usbvision->dev_model].vin_reg1_override) {
+		value[0] = usbvision_device_data[usbvision->dev_model].vin_reg1;
+	} else if (usbvision_device_data[usbvision->dev_model].codec == CODEC_SAA7113) {
 		/* SAA7113 uses 8 bit output */
 		value[0] = USBVISION_8_422_SYNC;
 	} else {
@@ -2105,53 +2017,53 @@ int usbvision_set_input(struct usb_usbvi
 	}
 
 
-	if (usbvision->tvnormId & V4L2_STD_PAL) {
+	if (usbvision->tvnorm_id & V4L2_STD_PAL) {
 		value[0] = 0xC0;
-		value[1] = 0x02;	//0x02C0 -> 704 Input video line length
+		value[1] = 0x02;	/* 0x02C0 -> 704 Input video line length */
 		value[2] = 0x20;
-		value[3] = 0x01;	//0x0120 -> 288 Input video n. of lines
+		value[3] = 0x01;	/* 0x0120 -> 288 Input video n. of lines */
 		value[4] = 0x60;
-		value[5] = 0x00;	//0x0060 -> 96 Input video h offset
+		value[5] = 0x00;	/* 0x0060 -> 96 Input video h offset */
 		value[6] = 0x16;
-		value[7] = 0x00;	//0x0016 -> 22 Input video v offset
-	} else if (usbvision->tvnormId & V4L2_STD_SECAM) {
+		value[7] = 0x00;	/* 0x0016 -> 22 Input video v offset */
+	} else if (usbvision->tvnorm_id & V4L2_STD_SECAM) {
 		value[0] = 0xC0;
-		value[1] = 0x02;	//0x02C0 -> 704 Input video line length
+		value[1] = 0x02;	/* 0x02C0 -> 704 Input video line length */
 		value[2] = 0x20;
-		value[3] = 0x01;	//0x0120 -> 288 Input video n. of lines
+		value[3] = 0x01;	/* 0x0120 -> 288 Input video n. of lines */
 		value[4] = 0x01;
-		value[5] = 0x00;	//0x0001 -> 01 Input video h offset
+		value[5] = 0x00;	/* 0x0001 -> 01 Input video h offset */
 		value[6] = 0x01;
-		value[7] = 0x00;	//0x0001 -> 01 Input video v offset
+		value[7] = 0x00;	/* 0x0001 -> 01 Input video v offset */
 	} else {	/* V4L2_STD_NTSC */
 		value[0] = 0xD0;
-		value[1] = 0x02;	//0x02D0 -> 720 Input video line length
+		value[1] = 0x02;	/* 0x02D0 -> 720 Input video line length */
 		value[2] = 0xF0;
-		value[3] = 0x00;	//0x00F0 -> 240 Input video number of lines
+		value[3] = 0x00;	/* 0x00F0 -> 240 Input video number of lines */
 		value[4] = 0x50;
-		value[5] = 0x00;	//0x0050 -> 80 Input video h offset
+		value[5] = 0x00;	/* 0x0050 -> 80 Input video h offset */
 		value[6] = 0x10;
-		value[7] = 0x00;	//0x0010 -> 16 Input video v offset
+		value[7] = 0x00;	/* 0x0010 -> 16 Input video v offset */
 	}
 
-	if (usbvision_device_data[usbvision->DevModel].X_Offset >= 0) {
-		value[4]=usbvision_device_data[usbvision->DevModel].X_Offset & 0xff;
-		value[5]=(usbvision_device_data[usbvision->DevModel].X_Offset & 0x0300) >> 8;
+	if (usbvision_device_data[usbvision->dev_model].x_offset >= 0) {
+		value[4] = usbvision_device_data[usbvision->dev_model].x_offset & 0xff;
+		value[5] = (usbvision_device_data[usbvision->dev_model].x_offset & 0x0300) >> 8;
 	}
 
-	if (adjust_X_Offset != -1) {
-		value[4] = adjust_X_Offset & 0xff;
-		value[5] = (adjust_X_Offset & 0x0300) >> 8;
+	if (adjust_x_offset != -1) {
+		value[4] = adjust_x_offset & 0xff;
+		value[5] = (adjust_x_offset & 0x0300) >> 8;
 	}
 
-	if (usbvision_device_data[usbvision->DevModel].Y_Offset >= 0) {
-		value[6]=usbvision_device_data[usbvision->DevModel].Y_Offset & 0xff;
-		value[7]=(usbvision_device_data[usbvision->DevModel].Y_Offset & 0x0300) >> 8;
+	if (usbvision_device_data[usbvision->dev_model].y_offset >= 0) {
+		value[6] = usbvision_device_data[usbvision->dev_model].y_offset & 0xff;
+		value[7] = (usbvision_device_data[usbvision->dev_model].y_offset & 0x0300) >> 8;
 	}
 
-	if (adjust_Y_Offset != -1) {
-		value[6] = adjust_Y_Offset & 0xff;
-		value[7] = (adjust_Y_Offset & 0x0300) >> 8;
+	if (adjust_y_offset != -1) {
+		value[6] = adjust_y_offset & 0xff;
+		value[7] = (adjust_y_offset & 0x0300) >> 8;
 	}
 
 	rc = usb_control_msg(usbvision->dev, usb_sndctrlpipe(usbvision->dev, 1),
@@ -2167,15 +2079,14 @@ int usbvision_set_input(struct usb_usbvi
 
 	dvi_yuv_value = 0x00;	/* U comes after V, Ya comes after U/V, Yb comes after Yb */
 
-	if(usbvision_device_data[usbvision->DevModel].Dvi_yuv_override){
-		dvi_yuv_value = usbvision_device_data[usbvision->DevModel].Dvi_yuv;
-	}
-	else if(usbvision_device_data[usbvision->DevModel].Codec == CODEC_SAA7113) {
-	/* This changes as the fine sync control changes. Further investigation necessary */
+	if (usbvision_device_data[usbvision->dev_model].dvi_yuv_override) {
+		dvi_yuv_value = usbvision_device_data[usbvision->dev_model].dvi_yuv;
+	} else if (usbvision_device_data[usbvision->dev_model].codec == CODEC_SAA7113) {
+		/* This changes as the fine sync control changes. Further investigation necessary */
 		dvi_yuv_value = 0x06;
 	}
 
-	return (usbvision_write_reg(usbvision, USBVISION_DVI_YUV, dvi_yuv_value));
+	return usbvision_write_reg(usbvision, USBVISION_DVI_YUV, dvi_yuv_value);
 }
 
 
@@ -2192,7 +2103,7 @@ static int usbvision_set_dram_settings(s
 	int rc;
 	unsigned char value[8];
 
-	if (usbvision->isocMode == ISOC_MODE_COMPRESS) {
+	if (usbvision->isoc_mode == ISOC_MODE_COMPRESS) {
 		value[0] = 0x42;
 		value[1] = 0x71;
 		value[2] = 0xff;
@@ -2201,11 +2112,10 @@ static int usbvision_set_dram_settings(s
 		value[5] = 0xe0;
 		value[6] = 0x71;
 		value[7] = 0xff;
-		// UR:  0x0E200-0x3FFFF = 204288 Words (1 Word = 2 Byte)
-		// FDL: 0x00000-0x0E099 =  57498 Words
-		// VDW: 0x0E3FF-0x3FFFF
-	}
-	else {
+		/* UR:  0x0E200-0x3FFFF = 204288 Words (1 Word = 2 Byte) */
+		/* FDL: 0x00000-0x0E099 =  57498 Words */
+		/* VDW: 0x0E3FF-0x3FFFF */
+	} else {
 		value[0] = 0x42;
 		value[1] = 0x00;
 		value[2] = 0xff;
@@ -2218,14 +2128,14 @@ static int usbvision_set_dram_settings(s
 	/* These are the values of the address of the video buffer,
 	 * they have to be loaded into the USBVISION_DRM_PRM1-8
 	 *
-	 * Start address of video output buffer for read: 	drm_prm1-2 -> 0x00000
-	 * End address of video output buffer for read: 	drm_prm1-3 -> 0x1ffff
-	 * Start address of video frame delay buffer: 		drm_prm1-4 -> 0x20000
+	 * Start address of video output buffer for read:	drm_prm1-2 -> 0x00000
+	 * End address of video output buffer for read:		drm_prm1-3 -> 0x1ffff
+	 * Start address of video frame delay buffer:		drm_prm1-4 -> 0x20000
 	 *    Only used in compressed mode
-	 * End address of video frame delay buffer: 		drm_prm1-5-6 -> 0x3ffff
+	 * End address of video frame delay buffer:		drm_prm1-5-6 -> 0x3ffff
 	 *    Only used in compressed mode
-	 * Start address of video output buffer for write: 	drm_prm1-7 -> 0x00000
-	 * End address of video output buffer for write: 	drm_prm1-8 -> 0x1ffff
+	 * Start address of video output buffer for write:	drm_prm1-7 -> 0x00000
+	 * End address of video output buffer for write:	drm_prm1-8 -> 0x1ffff
 	 */
 
 	if (!USBVISION_IS_OPERATIONAL(usbvision))
@@ -2243,8 +2153,9 @@ static int usbvision_set_dram_settings(s
 	}
 
 	/* Restart the video buffer logic */
-	if ((rc = usbvision_write_reg(usbvision, USBVISION_DRM_CONT, USBVISION_RES_UR |
-				   USBVISION_RES_FDL | USBVISION_RES_VDW)) < 0)
+	rc = usbvision_write_reg(usbvision, USBVISION_DRM_CONT, USBVISION_RES_UR |
+				   USBVISION_RES_FDL | USBVISION_RES_VDW);
+	if (rc < 0)
 		return rc;
 	rc = usbvision_write_reg(usbvision, USBVISION_DRM_CONT, 0x00);
 
@@ -2261,23 +2172,22 @@ static int usbvision_set_dram_settings(s
 
 int usbvision_power_on(struct usb_usbvision *usbvision)
 {
-	int errCode = 0;
+	int err_code = 0;
 
 	PDEBUG(DBG_FUNC, "");
 
 	usbvision_write_reg(usbvision, USBVISION_PWR_REG, USBVISION_SSPND_EN);
 	usbvision_write_reg(usbvision, USBVISION_PWR_REG,
-			 USBVISION_SSPND_EN | USBVISION_RES2);
+			USBVISION_SSPND_EN | USBVISION_RES2);
 
 	usbvision_write_reg(usbvision, USBVISION_PWR_REG,
-			 USBVISION_SSPND_EN | USBVISION_PWR_VID);
-	errCode = usbvision_write_reg(usbvision, USBVISION_PWR_REG,
-						USBVISION_SSPND_EN | USBVISION_PWR_VID | USBVISION_RES2);
-	if (errCode == 1) {
+			USBVISION_SSPND_EN | USBVISION_PWR_VID);
+	err_code = usbvision_write_reg(usbvision, USBVISION_PWR_REG,
+			USBVISION_SSPND_EN | USBVISION_PWR_VID | USBVISION_RES2);
+	if (err_code == 1)
 		usbvision->power = 1;
-	}
-	PDEBUG(DBG_FUNC, "%s: errCode %d", (errCode<0)?"ERROR":"power is on", errCode);
-	return errCode;
+	PDEBUG(DBG_FUNC, "%s: err_code %d", (err_code < 0) ? "ERROR" : "power is on", err_code);
+	return err_code;
 }
 
 
@@ -2285,53 +2195,50 @@ int usbvision_power_on(struct usb_usbvis
  * usbvision timer stuff
  */
 
-// to call usbvision_power_off from task queue
+/* to call usbvision_power_off from task queue */
 static void call_usbvision_power_off(struct work_struct *work)
 {
-	struct usb_usbvision *usbvision = container_of(work, struct usb_usbvision, powerOffWork);
+	struct usb_usbvision *usbvision = container_of(work, struct usb_usbvision, power_off_work);
 
 	PDEBUG(DBG_FUNC, "");
-	if(mutex_lock_interruptible(&usbvision->lock)) {
+	if (mutex_lock_interruptible(&usbvision->v4l2_lock))
 		return;
-	}
 
-
-	if(usbvision->user == 0) {
+	if (usbvision->user == 0) {
 		usbvision_i2c_unregister(usbvision);
 
 		usbvision_power_off(usbvision);
 		usbvision->initialized = 0;
 	}
-	mutex_unlock(&usbvision->lock);
+	mutex_unlock(&usbvision->v4l2_lock);
 }
 
-static void usbvision_powerOffTimer(unsigned long data)
+static void usbvision_power_off_timer(unsigned long data)
 {
-	struct usb_usbvision *usbvision = (void *) data;
+	struct usb_usbvision *usbvision = (void *)data;
 
 	PDEBUG(DBG_FUNC, "");
-	del_timer(&usbvision->powerOffTimer);
-	INIT_WORK(&usbvision->powerOffWork, call_usbvision_power_off);
-	(void) schedule_work(&usbvision->powerOffWork);
+	del_timer(&usbvision->power_off_timer);
+	INIT_WORK(&usbvision->power_off_work, call_usbvision_power_off);
+	(void) schedule_work(&usbvision->power_off_work);
 }
 
-void usbvision_init_powerOffTimer(struct usb_usbvision *usbvision)
+void usbvision_init_power_off_timer(struct usb_usbvision *usbvision)
 {
-	init_timer(&usbvision->powerOffTimer);
-	usbvision->powerOffTimer.data = (long) usbvision;
-	usbvision->powerOffTimer.function = usbvision_powerOffTimer;
+	init_timer(&usbvision->power_off_timer);
+	usbvision->power_off_timer.data = (long)usbvision;
+	usbvision->power_off_timer.function = usbvision_power_off_timer;
 }
 
-void usbvision_set_powerOffTimer(struct usb_usbvision *usbvision)
+void usbvision_set_power_off_timer(struct usb_usbvision *usbvision)
 {
-	mod_timer(&usbvision->powerOffTimer, jiffies + USBVISION_POWEROFF_TIME);
+	mod_timer(&usbvision->power_off_timer, jiffies + USBVISION_POWEROFF_TIME);
 }
 
-void usbvision_reset_powerOffTimer(struct usb_usbvision *usbvision)
+void usbvision_reset_power_off_timer(struct usb_usbvision *usbvision)
 {
-	if (timer_pending(&usbvision->powerOffTimer)) {
-		del_timer(&usbvision->powerOffTimer);
-	}
+	if (timer_pending(&usbvision->power_off_timer))
+		del_timer(&usbvision->power_off_timer);
 }
 
 /*
@@ -2341,14 +2248,10 @@ void usbvision_reset_powerOffTimer(struc
  */
 int usbvision_begin_streaming(struct usb_usbvision *usbvision)
 {
-	int errCode = 0;
-
-	if (usbvision->isocMode == ISOC_MODE_COMPRESS) {
+	if (usbvision->isoc_mode == ISOC_MODE_COMPRESS)
 		usbvision_init_compression(usbvision);
-	}
-	errCode = usbvision_write_reg(usbvision, USBVISION_VIN_REG2, USBVISION_NOHVALID |
-										usbvision->Vin_Reg2_Preset);
-	return errCode;
+	return usbvision_write_reg(usbvision, USBVISION_VIN_REG2,
+		USBVISION_NOHVALID | usbvision->vin_reg2_preset);
 }
 
 /*
@@ -2360,25 +2263,24 @@ int usbvision_restart_isoc(struct usb_us
 {
 	int ret;
 
-	if (
-	    (ret =
-	     usbvision_write_reg(usbvision, USBVISION_PWR_REG,
-			      USBVISION_SSPND_EN | USBVISION_PWR_VID)) < 0)
+	ret = usbvision_write_reg(usbvision, USBVISION_PWR_REG,
+			      USBVISION_SSPND_EN | USBVISION_PWR_VID);
+	if (ret < 0)
 		return ret;
-	if (
-	    (ret =
-	     usbvision_write_reg(usbvision, USBVISION_PWR_REG,
+	ret = usbvision_write_reg(usbvision, USBVISION_PWR_REG,
 			      USBVISION_SSPND_EN | USBVISION_PWR_VID |
-			      USBVISION_RES2)) < 0)
+			      USBVISION_RES2);
+	if (ret < 0)
 		return ret;
-	if (
-	    (ret =
-	     usbvision_write_reg(usbvision, USBVISION_VIN_REG2,
+	ret = usbvision_write_reg(usbvision, USBVISION_VIN_REG2,
 			      USBVISION_KEEP_BLANK | USBVISION_NOHVALID |
-				  usbvision->Vin_Reg2_Preset)) < 0) return ret;
+				  usbvision->vin_reg2_preset);
+	if (ret < 0)
+		return ret;
 
 	/* TODO: schedule timeout */
-	while ((usbvision_read_reg(usbvision, USBVISION_STATUS_REG) & 0x01) != 1);
+	while ((usbvision_read_reg(usbvision, USBVISION_STATUS_REG) & 0x01) != 1)
+		;
 
 	return 0;
 }
@@ -2386,27 +2288,27 @@ int usbvision_restart_isoc(struct usb_us
 int usbvision_audio_off(struct usb_usbvision *usbvision)
 {
 	if (usbvision_write_reg(usbvision, USBVISION_IOPIN_REG, USBVISION_AUDIO_MUTE) < 0) {
-		printk(KERN_ERR "usbvision_audio_off: can't wirte reg\n");
+		printk(KERN_ERR "usbvision_audio_off: can't write reg\n");
 		return -1;
 	}
-	usbvision->AudioMute = 0;
-	usbvision->AudioChannel = USBVISION_AUDIO_MUTE;
+	usbvision->audio_mute = 0;
+	usbvision->audio_channel = USBVISION_AUDIO_MUTE;
 	return 0;
 }
 
-int usbvision_set_audio(struct usb_usbvision *usbvision, int AudioChannel)
+int usbvision_set_audio(struct usb_usbvision *usbvision, int audio_channel)
 {
-	if (!usbvision->AudioMute) {
-		if (usbvision_write_reg(usbvision, USBVISION_IOPIN_REG, AudioChannel) < 0) {
+	if (!usbvision->audio_mute) {
+		if (usbvision_write_reg(usbvision, USBVISION_IOPIN_REG, audio_channel) < 0) {
 			printk(KERN_ERR "usbvision_set_audio: can't write iopin register for audio switching\n");
 			return -1;
 		}
 	}
-	usbvision->AudioChannel = AudioChannel;
+	usbvision->audio_channel = audio_channel;
 	return 0;
 }
 
-int usbvision_setup(struct usb_usbvision *usbvision,int format)
+int usbvision_setup(struct usb_usbvision *usbvision, int format)
 {
 	usbvision_set_video_format(usbvision, format);
 	usbvision_set_dram_settings(usbvision);
@@ -2421,27 +2323,28 @@ int usbvision_setup(struct usb_usbvision
 
 int usbvision_set_alternate(struct usb_usbvision *dev)
 {
-	int errCode, prev_alt = dev->ifaceAlt;
+	int err_code, prev_alt = dev->iface_alt;
 	int i;
 
-	dev->ifaceAlt=0;
-	for(i=0;i< dev->num_alt; i++)
-		if(dev->alt_max_pkt_size[i]>dev->alt_max_pkt_size[dev->ifaceAlt])
-			dev->ifaceAlt=i;
+	dev->iface_alt = 0;
+	for (i = 0; i < dev->num_alt; i++)
+		if (dev->alt_max_pkt_size[i] > dev->alt_max_pkt_size[dev->iface_alt])
+			dev->iface_alt = i;
 
-	if (dev->ifaceAlt != prev_alt) {
-		dev->isocPacketSize = dev->alt_max_pkt_size[dev->ifaceAlt];
-		PDEBUG(DBG_FUNC,"setting alternate %d with wMaxPacketSize=%u", dev->ifaceAlt,dev->isocPacketSize);
-		errCode = usb_set_interface(dev->dev, dev->iface, dev->ifaceAlt);
-		if (errCode < 0) {
+	if (dev->iface_alt != prev_alt) {
+		dev->isoc_packet_size = dev->alt_max_pkt_size[dev->iface_alt];
+		PDEBUG(DBG_FUNC, "setting alternate %d with max_packet_size=%u",
+				dev->iface_alt, dev->isoc_packet_size);
+		err_code = usb_set_interface(dev->dev, dev->iface, dev->iface_alt);
+		if (err_code < 0) {
 			dev_err(&dev->dev->dev,
 				"cannot change alternate number to %d (error=%i)\n",
-					dev->ifaceAlt, errCode);
-			return errCode;
+					dev->iface_alt, err_code);
+			return err_code;
 		}
 	}
 
-	PDEBUG(DBG_ISOC, "ISO Packet Length:%d", dev->isocPacketSize);
+	PDEBUG(DBG_ISOC, "ISO Packet Length:%d", dev->isoc_packet_size);
 
 	return 0;
 }
@@ -2453,27 +2356,27 @@ int usbvision_set_alternate(struct usb_u
 int usbvision_init_isoc(struct usb_usbvision *usbvision)
 {
 	struct usb_device *dev = usbvision->dev;
-	int bufIdx, errCode, regValue;
+	int buf_idx, err_code, reg_value;
 	int sb_size;
 
 	if (!USBVISION_IS_OPERATIONAL(usbvision))
 		return -EFAULT;
 
-	usbvision->curFrame = NULL;
+	usbvision->cur_frame = NULL;
 	scratch_reset(usbvision);
 
 	/* Alternate interface 1 is is the biggest frame size */
-	errCode = usbvision_set_alternate(usbvision);
-	if (errCode < 0) {
-		usbvision->last_error = errCode;
+	err_code = usbvision_set_alternate(usbvision);
+	if (err_code < 0) {
+		usbvision->last_error = err_code;
 		return -EBUSY;
 	}
-	sb_size = USBVISION_URB_FRAMES * usbvision->isocPacketSize;
+	sb_size = USBVISION_URB_FRAMES * usbvision->isoc_packet_size;
 
-	regValue = (16 - usbvision_read_reg(usbvision,
+	reg_value = (16 - usbvision_read_reg(usbvision,
 					    USBVISION_ALTER_REG)) & 0x0F;
 
-	usbvision->usb_bandwidth = regValue >> 1;
+	usbvision->usb_bandwidth = reg_value >> 1;
 	PDEBUG(DBG_ISOC, "USB Bandwidth Usage: %dMbit/Sec",
 	       usbvision->usb_bandwidth);
 
@@ -2481,7 +2384,7 @@ int usbvision_init_isoc(struct usb_usbvi
 
 	/* We double buffer the Iso lists */
 
-	for (bufIdx = 0; bufIdx < USBVISION_NUMSBUF; bufIdx++) {
+	for (buf_idx = 0; buf_idx < USBVISION_NUMSBUF; buf_idx++) {
 		int j, k;
 		struct urb *urb;
 
@@ -2491,8 +2394,8 @@ int usbvision_init_isoc(struct usb_usbvi
 				"%s: usb_alloc_urb() failed\n", __func__);
 			return -ENOMEM;
 		}
-		usbvision->sbuf[bufIdx].urb = urb;
-		usbvision->sbuf[bufIdx].data =
+		usbvision->sbuf[buf_idx].urb = urb;
+		usbvision->sbuf[buf_idx].data =
 			usb_alloc_coherent(usbvision->dev,
 					   sb_size,
 					   GFP_KERNEL,
@@ -2502,31 +2405,31 @@ int usbvision_init_isoc(struct usb_usbvi
 		urb->pipe = usb_rcvisocpipe(dev, usbvision->video_endp);
 		urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
 		urb->interval = 1;
-		urb->transfer_buffer = usbvision->sbuf[bufIdx].data;
-		urb->complete = usbvision_isocIrq;
+		urb->transfer_buffer = usbvision->sbuf[buf_idx].data;
+		urb->complete = usbvision_isoc_irq;
 		urb->number_of_packets = USBVISION_URB_FRAMES;
 		urb->transfer_buffer_length =
-		    usbvision->isocPacketSize * USBVISION_URB_FRAMES;
+		    usbvision->isoc_packet_size * USBVISION_URB_FRAMES;
 		for (j = k = 0; j < USBVISION_URB_FRAMES; j++,
-		     k += usbvision->isocPacketSize) {
+		     k += usbvision->isoc_packet_size) {
 			urb->iso_frame_desc[j].offset = k;
 			urb->iso_frame_desc[j].length =
-				usbvision->isocPacketSize;
+				usbvision->isoc_packet_size;
 		}
 	}
 
 	/* Submit all URBs */
-	for (bufIdx = 0; bufIdx < USBVISION_NUMSBUF; bufIdx++) {
-			errCode = usb_submit_urb(usbvision->sbuf[bufIdx].urb,
+	for (buf_idx = 0; buf_idx < USBVISION_NUMSBUF; buf_idx++) {
+			err_code = usb_submit_urb(usbvision->sbuf[buf_idx].urb,
 						 GFP_KERNEL);
-		if (errCode) {
+		if (err_code) {
 			dev_err(&usbvision->dev->dev,
 				"%s: usb_submit_urb(%d) failed: error %d\n",
-					__func__, bufIdx, errCode);
+					__func__, buf_idx, err_code);
 		}
 	}
 
-	usbvision->streaming = Stream_Idle;
+	usbvision->streaming = stream_idle;
 	PDEBUG(DBG_ISOC, "%s: streaming=1 usbvision->video_endp=$%02x",
 	       __func__,
 	       usbvision->video_endp);
@@ -2542,47 +2445,46 @@ int usbvision_init_isoc(struct usb_usbvi
  */
 void usbvision_stop_isoc(struct usb_usbvision *usbvision)
 {
-	int bufIdx, errCode, regValue;
-	int sb_size = USBVISION_URB_FRAMES * usbvision->isocPacketSize;
+	int buf_idx, err_code, reg_value;
+	int sb_size = USBVISION_URB_FRAMES * usbvision->isoc_packet_size;
 
-	if ((usbvision->streaming == Stream_Off) || (usbvision->dev == NULL))
+	if ((usbvision->streaming == stream_off) || (usbvision->dev == NULL))
 		return;
 
 	/* Unschedule all of the iso td's */
-	for (bufIdx = 0; bufIdx < USBVISION_NUMSBUF; bufIdx++) {
-		usb_kill_urb(usbvision->sbuf[bufIdx].urb);
-		if (usbvision->sbuf[bufIdx].data){
+	for (buf_idx = 0; buf_idx < USBVISION_NUMSBUF; buf_idx++) {
+		usb_kill_urb(usbvision->sbuf[buf_idx].urb);
+		if (usbvision->sbuf[buf_idx].data) {
 			usb_free_coherent(usbvision->dev,
 					  sb_size,
-					  usbvision->sbuf[bufIdx].data,
-					  usbvision->sbuf[bufIdx].urb->transfer_dma);
+					  usbvision->sbuf[buf_idx].data,
+					  usbvision->sbuf[buf_idx].urb->transfer_dma);
 		}
-		usb_free_urb(usbvision->sbuf[bufIdx].urb);
-		usbvision->sbuf[bufIdx].urb = NULL;
+		usb_free_urb(usbvision->sbuf[buf_idx].urb);
+		usbvision->sbuf[buf_idx].urb = NULL;
 	}
 
-	PDEBUG(DBG_ISOC, "%s: streaming=Stream_Off\n", __func__);
-	usbvision->streaming = Stream_Off;
+	PDEBUG(DBG_ISOC, "%s: streaming=stream_off\n", __func__);
+	usbvision->streaming = stream_off;
 
 	if (!usbvision->remove_pending) {
-
 		/* Set packet size to 0 */
-		usbvision->ifaceAlt=0;
-		errCode = usb_set_interface(usbvision->dev, usbvision->iface,
-					    usbvision->ifaceAlt);
-		if (errCode < 0) {
+		usbvision->iface_alt = 0;
+		err_code = usb_set_interface(usbvision->dev, usbvision->iface,
+					    usbvision->iface_alt);
+		if (err_code < 0) {
 			dev_err(&usbvision->dev->dev,
 				"%s: usb_set_interface() failed: error %d\n",
-					__func__, errCode);
-			usbvision->last_error = errCode;
+					__func__, err_code);
+			usbvision->last_error = err_code;
 		}
-		regValue = (16-usbvision_read_reg(usbvision, USBVISION_ALTER_REG)) & 0x0F;
-		usbvision->isocPacketSize =
-			(regValue == 0) ? 0 : (regValue * 64) - 1;
+		reg_value = (16-usbvision_read_reg(usbvision, USBVISION_ALTER_REG)) & 0x0F;
+		usbvision->isoc_packet_size =
+			(reg_value == 0) ? 0 : (reg_value * 64) - 1;
 		PDEBUG(DBG_ISOC, "ISO Packet Length:%d",
-		       usbvision->isocPacketSize);
+		       usbvision->isoc_packet_size);
 
-		usbvision->usb_bandwidth = regValue >> 1;
+		usbvision->usb_bandwidth = reg_value >> 1;
 		PDEBUG(DBG_ISOC, "USB Bandwidth Usage: %dMbit/Sec",
 		       usbvision->usb_bandwidth);
 	}
@@ -2592,39 +2494,38 @@ int usbvision_muxsel(struct usb_usbvisio
 {
 	/* inputs #0 and #3 are constant for every SAA711x. */
 	/* inputs #1 and #2 are variable for SAA7111 and SAA7113 */
-	int mode[4]= {SAA7115_COMPOSITE0, 0, 0, SAA7115_COMPOSITE3};
-	int audio[]= {1, 0, 0, 0};
-	//channel 0 is TV with audiochannel 1 (tuner mono)
-	//channel 1 is Composite with audio channel 0 (line in)
-	//channel 2 is S-Video with audio channel 0 (line in)
-	//channel 3 is additional video inputs to the device with audio channel 0 (line in)
+	int mode[4] = { SAA7115_COMPOSITE0, 0, 0, SAA7115_COMPOSITE3 };
+	int audio[] = { 1, 0, 0, 0 };
+	/* channel 0 is TV with audiochannel 1 (tuner mono) */
+	/* channel 1 is Composite with audio channel 0 (line in) */
+	/* channel 2 is S-Video with audio channel 0 (line in) */
+	/* channel 3 is additional video inputs to the device with audio channel 0 (line in) */
 
 	RESTRICT_TO_RANGE(channel, 0, usbvision->video_inputs);
 	usbvision->ctl_input = channel;
 
-	// set the new channel
-	// Regular USB TV Tuners -> channel: 0 = Television, 1 = Composite, 2 = S-Video
-	// Four video input devices -> channel: 0 = Chan White, 1 = Chan Green, 2 = Chan Yellow, 3 = Chan Red
+	/* set the new channel */
+	/* Regular USB TV Tuners -> channel: 0 = Television, 1 = Composite, 2 = S-Video */
+	/* Four video input devices -> channel: 0 = Chan White, 1 = Chan Green, 2 = Chan Yellow, 3 = Chan Red */
 
-	switch (usbvision_device_data[usbvision->DevModel].Codec) {
-		case CODEC_SAA7113:
-			mode[1] = SAA7115_COMPOSITE2;
-			if (SwitchSVideoInput) {
-				/* To handle problems with S-Video Input for
-				 * some devices.  Use SwitchSVideoInput
-				 * parameter when loading the module.*/
-				mode[2] = SAA7115_COMPOSITE1;
-			}
-			else {
-				mode[2] = SAA7115_SVIDEO1;
-			}
-			break;
-		case CODEC_SAA7111:
-		default:
-			/* modes for saa7111 */
-			mode[1] = SAA7115_COMPOSITE1;
+	switch (usbvision_device_data[usbvision->dev_model].codec) {
+	case CODEC_SAA7113:
+		mode[1] = SAA7115_COMPOSITE2;
+		if (switch_svideo_input) {
+			/* To handle problems with S-Video Input for
+			 * some devices.  Use switch_svideo_input
+			 * parameter when loading the module.*/
+			mode[2] = SAA7115_COMPOSITE1;
+		} else {
 			mode[2] = SAA7115_SVIDEO1;
-			break;
+		}
+		break;
+	case CODEC_SAA7111:
+	default:
+		/* modes for saa7111 */
+		mode[1] = SAA7115_COMPOSITE1;
+		mode[2] = SAA7115_SVIDEO1;
+		break;
 	}
 	call_all(usbvision, video, s_routing, mode[channel], 0, 0);
 	usbvision_set_audio(usbvision, audio[channel]);
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/usbvision/usbvision.h linux-libre-2.6.38-gnu1/drivers/media/video/usbvision/usbvision.h
--- linux-libre-2.6.37-gnu1/drivers/media/video/usbvision/usbvision.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/usbvision/usbvision.h	2011-03-14 21:20:32.000000000 -0400
@@ -132,15 +132,15 @@
 #define MAX_BYTES_PER_PIXEL		4
 
 #define MIN_FRAME_WIDTH			64
-#define MAX_USB_WIDTH			320  //384
-#define MAX_FRAME_WIDTH			320  //384			/*streching sometimes causes crashes*/
+#define MAX_USB_WIDTH			320  /* 384 */
+#define MAX_FRAME_WIDTH			320  /* 384 */			/* streching sometimes causes crashes*/
 
 #define MIN_FRAME_HEIGHT		48
-#define MAX_USB_HEIGHT			240  //288
-#define MAX_FRAME_HEIGHT		240  //288			/*Streching sometimes causes crashes*/
+#define MAX_USB_HEIGHT			240  /* 288 */
+#define MAX_FRAME_HEIGHT		240  /* 288 */			/* Streching sometimes causes crashes*/
 
-#define MAX_FRAME_SIZE     		(MAX_FRAME_WIDTH * MAX_FRAME_HEIGHT * MAX_BYTES_PER_PIXEL)
-#define USBVISION_CLIPMASK_SIZE		(MAX_FRAME_WIDTH * MAX_FRAME_HEIGHT / 8) //bytesize of clipmask
+#define MAX_FRAME_SIZE			(MAX_FRAME_WIDTH * MAX_FRAME_HEIGHT * MAX_BYTES_PER_PIXEL)
+#define USBVISION_CLIPMASK_SIZE		(MAX_FRAME_WIDTH * MAX_FRAME_HEIGHT / 8) /* bytesize of clipmask */
 
 #define USBVISION_URB_FRAMES		32
 
@@ -148,7 +148,7 @@
 #define USBVISION_NUMFRAMES		3  /* Maximum number of frames an application can get */
 #define USBVISION_NUMSBUF		2 /* Dimensioning the USB S buffering */
 
-#define USBVISION_POWEROFF_TIME		3 * (HZ)		// 3 seconds
+#define USBVISION_POWEROFF_TIME		(3 * HZ)		/* 3 seconds */
 
 
 #define FRAMERATE_MIN	0
@@ -161,7 +161,8 @@ enum {
 };
 
 /* This macro restricts an int variable to an inclusive range */
-#define RESTRICT_TO_RANGE(v,mi,ma) { if ((v) < (mi)) (v) = (mi); else if ((v) > (ma)) (v) = (ma); }
+#define RESTRICT_TO_RANGE(v, mi, ma) \
+	{ if ((v) < (mi)) (v) = (mi); else if ((v) > (ma)) (v) = (ma); }
 
 /*
  * We use macros to do YUV -> RGB conversion because this is
@@ -183,18 +184,18 @@ enum {
  * Make sure the output values are within [0..255] range.
  */
 #define LIMIT_RGB(x) (((x) < 0) ? 0 : (((x) > 255) ? 255 : (x)))
-#define YUV_TO_RGB_BY_THE_BOOK(my,mu,mv,mr,mg,mb) { \
-    int mm_y, mm_yc, mm_u, mm_v, mm_r, mm_g, mm_b; \
-    mm_y = (my) - 16;  \
-    mm_u = (mu) - 128; \
-    mm_v = (mv) - 128; \
-    mm_yc= mm_y * 76284; \
-    mm_b = (mm_yc		+ 132252*mm_v	) >> 16; \
-    mm_g = (mm_yc -  53281*mm_u -  25625*mm_v	) >> 16; \
-    mm_r = (mm_yc + 104595*mm_u			) >> 16; \
-    mb = LIMIT_RGB(mm_b); \
-    mg = LIMIT_RGB(mm_g); \
-    mr = LIMIT_RGB(mm_r); \
+#define YUV_TO_RGB_BY_THE_BOOK(my, mu, mv, mr, mg, mb) { \
+	int mm_y, mm_yc, mm_u, mm_v, mm_r, mm_g, mm_b; \
+	mm_y = (my) - 16; \
+	mm_u = (mu) - 128; \
+	mm_v = (mv) - 128; \
+	mm_yc = mm_y * 76284; \
+	mm_b = (mm_yc + 132252 * mm_v) >> 16; \
+	mm_g = (mm_yc - 53281 * mm_u - 25625 * mm_v) >> 16; \
+	mm_r = (mm_yc + 104595 * mm_u) >> 16; \
+	mb = LIMIT_RGB(mm_b); \
+	mg = LIMIT_RGB(mm_g); \
+	mr = LIMIT_RGB(mm_r); \
 }
 
 /* Debugging aid */
@@ -202,7 +203,7 @@ enum {
 	wait_queue_head_t wq; \
 	init_waitqueue_head(&wq); \
 	printk(KERN_INFO "Say: %s\n", what); \
-	interruptible_sleep_on_timeout (&wq, HZ*3); \
+	interruptible_sleep_on_timeout(&wq, HZ * 3); \
 }
 
 /*
@@ -223,39 +224,39 @@ enum {
 /* ----------------------------------------------------------------- */
 /* usbvision video structures                                        */
 /* ----------------------------------------------------------------- */
-enum ScanState {
-	ScanState_Scanning,	/* Scanning for header */
-	ScanState_Lines		/* Parsing lines */
+enum scan_state {
+	scan_state_scanning,	/* Scanning for header */
+	scan_state_lines	/* Parsing lines */
 };
 
 /* Completion states of the data parser */
-enum ParseState {
-	ParseState_Continue,	/* Just parse next item */
-	ParseState_NextFrame,	/* Frame done, send it to V4L */
-	ParseState_Out,		/* Not enough data for frame */
-	ParseState_EndParse	/* End parsing */
+enum parse_state {
+	parse_state_continue,	/* Just parse next item */
+	parse_state_next_frame,	/* Frame done, send it to V4L */
+	parse_state_out,	/* Not enough data for frame */
+	parse_state_end_parse	/* End parsing */
 };
 
-enum FrameState {
-	FrameState_Unused,	/* Unused (no MCAPTURE) */
-	FrameState_Ready,	/* Ready to start grabbing */
-	FrameState_Grabbing,	/* In the process of being grabbed into */
-	FrameState_Done,	/* Finished grabbing, but not been synced yet */
-	FrameState_DoneHold,	/* Are syncing or reading */
-	FrameState_Error,	/* Something bad happened while processing */
+enum frame_state {
+	frame_state_unused,	/* Unused (no MCAPTURE) */
+	frame_state_ready,	/* Ready to start grabbing */
+	frame_state_grabbing,	/* In the process of being grabbed into */
+	frame_state_done,	/* Finished grabbing, but not been synced yet */
+	frame_state_done_hold,	/* Are syncing or reading */
+	frame_state_error,	/* Something bad happened while processing */
 };
 
 /* stream states */
-enum StreamState {
-	Stream_Off,		/* Driver streaming is completely OFF */
-	Stream_Idle,		/* Driver streaming is ready to be put ON by the application */
-	Stream_Interrupt,	/* Driver streaming must be interrupted */
-	Stream_On,		/* Driver streaming is put ON by the application */
+enum stream_state {
+	stream_off,		/* Driver streaming is completely OFF */
+	stream_idle,		/* Driver streaming is ready to be put ON by the application */
+	stream_interrupt,	/* Driver streaming must be interrupted */
+	stream_on,		/* Driver streaming is put ON by the application */
 };
 
-enum IsocState {
-	IsocState_InFrame,	/* Isoc packet is member of frame */
-	IsocState_NoFrame,	/* Isoc packet is not member of any frame */
+enum isoc_state {
+	isoc_state_in_frame,	/* Isoc packet is member of frame */
+	isoc_state_no_frame,	/* Isoc packet is not member of any frame */
 };
 
 struct usb_device;
@@ -265,8 +266,8 @@ struct usbvision_sbuf {
 	struct urb *urb;
 };
 
-#define USBVISION_MAGIC_1      			0x55
-#define USBVISION_MAGIC_2      			0xAA
+#define USBVISION_MAGIC_1			0x55
+#define USBVISION_MAGIC_2			0xAA
 #define USBVISION_HEADER_LENGTH			0x0c
 #define USBVISION_SAA7111_ADDR			0x48
 #define USBVISION_SAA7113_ADDR			0x4a
@@ -286,23 +287,23 @@ struct usbvision_v4l2_format_st {
 struct usbvision_frame_header {
 	unsigned char magic_1;				/* 0 magic */
 	unsigned char magic_2;				/* 1  magic */
-	unsigned char headerLength;			/* 2 */
-	unsigned char frameNum;				/* 3 */
-	unsigned char framePhase;			/* 4 */
-	unsigned char frameLatency;			/* 5 */
-	unsigned char dataFormat;			/* 6 */
-	unsigned char formatParam;			/* 7 */
-	unsigned char frameWidthLo;			/* 8 */
-	unsigned char frameWidthHi;			/* 9 */
-	unsigned char frameHeightLo;			/* 10 */
-	unsigned char frameHeightHi;			/* 11 */
-	__u16 frameWidth;				/* 8 - 9 after endian correction*/
-	__u16 frameHeight;				/* 10 - 11 after endian correction*/
+	unsigned char header_length;			/* 2 */
+	unsigned char frame_num;			/* 3 */
+	unsigned char frame_phase;			/* 4 */
+	unsigned char frame_latency;			/* 5 */
+	unsigned char data_format;			/* 6 */
+	unsigned char format_param;			/* 7 */
+	unsigned char frame_width_lo;			/* 8 */
+	unsigned char frame_width_hi;			/* 9 */
+	unsigned char frame_height_lo;			/* 10 */
+	unsigned char frame_height_hi;			/* 11 */
+	__u16 frame_width;				/* 8 - 9 after endian correction*/
+	__u16 frame_height;				/* 10 - 11 after endian correction*/
 };
 
 struct usbvision_frame {
 	char *data;					/* Frame buffer */
-	struct usbvision_frame_header isocHeader;	/* Header from stream */
+	struct usbvision_frame_header isoc_header;	/* Header from stream */
 
 	int width;					/* Width application is expecting */
 	int height;					/* Height */
@@ -322,7 +323,7 @@ struct usbvision_frame {
 	struct usbvision_v4l2_format_st v4l2_format;	/* format the user needs*/
 	int v4l2_linesize;				/* bytes for one videoline*/
 	struct timeval timestamp;
-	int sequence;					// How many video frames we send to user
+	int sequence;					/* How many video frames we send to user */
 };
 
 #define CODEC_SAA7113	7113
@@ -332,24 +333,24 @@ struct usbvision_frame {
 #define BRIDGE_NT1005   1005
 
 struct usbvision_device_data_st {
-	__u64 VideoNorm;
-	const char *ModelString;
-	int Interface; /* to handle special interface number like BELKIN and Hauppauge WinTV-USB II */
-	__u16 Codec;
-	unsigned VideoChannels:3;
-	unsigned AudioChannels:2;
-	unsigned Radio:1;
+	__u64 video_norm;
+	const char *model_string;
+	int interface; /* to handle special interface number like BELKIN and Hauppauge WinTV-USB II */
+	__u16 codec;
+	unsigned video_channels:3;
+	unsigned audio_channels:2;
+	unsigned radio:1;
 	unsigned vbi:1;
-	unsigned Tuner:1;
-	unsigned Vin_Reg1_override:1;	/* Override default value with */
-	unsigned Vin_Reg2_override:1;   /* Vin_Reg1, Vin_Reg2, etc. */
-	unsigned Dvi_yuv_override:1;
-	__u8 Vin_Reg1;
-	__u8 Vin_Reg2;
-	__u8 Dvi_yuv;
-	__u8 TunerType;
-	__s16 X_Offset;
-	__s16 Y_Offset;
+	unsigned tuner:1;
+	unsigned vin_reg1_override:1;	/* Override default value with */
+	unsigned vin_reg2_override:1;   /* vin_reg1, vin_reg2, etc. */
+	unsigned dvi_yuv_override:1;
+	__u8 vin_reg1;
+	__u8 vin_reg2;
+	__u8 dvi_yuv;
+	__u8 tuner_type;
+	__s16 x_offset;
+	__s16 y_offset;
 };
 
 /* Declared on usbvision-cards.c */
@@ -358,50 +359,50 @@ extern struct usb_device_id usbvision_ta
 
 struct usb_usbvision {
 	struct v4l2_device v4l2_dev;
-	struct video_device *vdev;         				/* Video Device */
-	struct video_device *rdev;               			/* Radio Device */
+	struct video_device *vdev;					/* Video Device */
+	struct video_device *rdev;					/* Radio Device */
 
 	/* i2c Declaration Section*/
 	struct i2c_adapter i2c_adap;
 	int registered_i2c;
 
-	struct urb *ctrlUrb;
-	unsigned char ctrlUrbBuffer[8];
-	int ctrlUrbBusy;
-	struct usb_ctrlrequest ctrlUrbSetup;
-	wait_queue_head_t ctrlUrb_wq;					// Processes waiting
+	struct urb *ctrl_urb;
+	unsigned char ctrl_urb_buffer[8];
+	int ctrl_urb_busy;
+	struct usb_ctrlrequest ctrl_urb_setup;
+	wait_queue_head_t ctrl_urb_wq;					/* Processes waiting */
 
 	/* configuration part */
 	int have_tuner;
 	int tuner_type;
-	int bridgeType;							// NT1003, NT1004, NT1005
+	int bridge_type;						/* NT1003, NT1004, NT1005 */
 	int radio;
-	int video_inputs;						// # of inputs
+	int video_inputs;						/* # of inputs */
 	unsigned long freq;
-	int AudioMute;
-	int AudioChannel;
-	int isocMode;							// format of video data for the usb isoc-transfer
-	unsigned int nr;						// Number of the device
+	int audio_mute;
+	int audio_channel;
+	int isoc_mode;							/* format of video data for the usb isoc-transfer */
+	unsigned int nr;						/* Number of the device */
 
 	/* Device structure */
 	struct usb_device *dev;
 	/* usb transfer */
 	int num_alt;		/* Number of alternative settings */
-	unsigned int *alt_max_pkt_size;	/* array of wMaxPacketSize */
+	unsigned int *alt_max_pkt_size;	/* array of max_packet_size */
 	unsigned char iface;						/* Video interface number */
-	unsigned char ifaceAlt;			/* Alt settings */
-	unsigned char Vin_Reg2_Preset;
-	struct mutex               lock;
-	struct timer_list powerOffTimer;
-	struct work_struct powerOffWork;
+	unsigned char iface_alt;					/* Alt settings */
+	unsigned char vin_reg2_preset;
+	struct mutex v4l2_lock;
+	struct timer_list power_off_timer;
+	struct work_struct power_off_work;
 	int power;							/* is the device powered on? */
 	int user;							/* user count for exclusive use */
 	int initialized;						/* Had we already sent init sequence? */
-	int DevModel;							/* What type of USBVISION device we got? */
-	enum StreamState streaming;					/* Are we streaming Isochronous? */
+	int dev_model;							/* What type of USBVISION device we got? */
+	enum stream_state streaming;					/* Are we streaming Isochronous? */
 	int last_error;							/* What calamity struck us? */
 	int curwidth;							/* width of the frame the device is currently set to*/
-	int curheight;      						/* height of the frame the device is currently set to*/
+	int curheight;							/* height of the frame the device is currently set to*/
 	int stretch_width;						/* stretch-factor for frame width (from usb to screen)*/
 	int stretch_height;						/* stretch-factor for frame height (from usb to screen)*/
 	char *fbuf;							/* Videodev buffer area for mmap*/
@@ -411,10 +412,10 @@ struct usb_usbvision {
 	struct list_head inqueue, outqueue;                             /* queued frame list and ready to dequeue frame list */
 	wait_queue_head_t wait_frame;					/* Processes waiting */
 	wait_queue_head_t wait_stream;					/* Processes waiting */
-	struct usbvision_frame *curFrame;				// pointer to current frame, set by usbvision_find_header
-	struct usbvision_frame frame[USBVISION_NUMFRAMES];		// frame buffer
-	int num_frames;							// number of frames allocated
-	struct usbvision_sbuf sbuf[USBVISION_NUMSBUF];			// S buffering
+	struct usbvision_frame *cur_frame;				/* pointer to current frame, set by usbvision_find_header */
+	struct usbvision_frame frame[USBVISION_NUMFRAMES];		/* frame buffer */
+	int num_frames;							/* number of frames allocated */
+	struct usbvision_sbuf sbuf[USBVISION_NUMSBUF];			/* S buffering */
 	volatile int remove_pending;					/* If set then about to exit */
 
 	/* Scratch space from the Isochronous Pipe.*/
@@ -424,43 +425,43 @@ struct usb_usbvision {
 	int scratch_headermarker[USBVISION_NUM_HEADERMARKER];
 	int scratch_headermarker_read_ptr;
 	int scratch_headermarker_write_ptr;
-	enum IsocState isocstate;
+	enum isoc_state isocstate;
 	struct usbvision_v4l2_format_st palette;
 
 	struct v4l2_capability vcap;					/* Video capabilities */
 	unsigned int ctl_input;						/* selected input */
-	v4l2_std_id tvnormId;						/* selected tv norm */
+	v4l2_std_id tvnorm_id;						/* selected tv norm */
 	unsigned char video_endp;					/* 0x82 for USBVISION devices based */
 
-	// Decompression stuff:
-	unsigned char *IntraFrameBuffer;				/* Buffer for reference frame */
-	int BlockPos; 							//for test only
-	int requestIntra;						// 0 = normal; 1 = intra frame is requested;
-	int lastIsocFrameNum;						// check for lost isoc frames
-	int isocPacketSize;						// need to calculate usedBandwidth
-	int usedBandwidth;						// used bandwidth 0-100%, need to set comprLevel
-	int comprLevel;							// How strong (100) or weak (0) is compression
-	int lastComprLevel;						// How strong (100) or weak (0) was compression
+	/* Decompression stuff: */
+	unsigned char *intra_frame_buffer;				/* Buffer for reference frame */
+	int block_pos;							/* for test only */
+	int request_intra;						/* 0 = normal; 1 = intra frame is requested; */
+	int last_isoc_frame_num;					/* check for lost isoc frames */
+	int isoc_packet_size;						/* need to calculate used_bandwidth */
+	int used_bandwidth;						/* used bandwidth 0-100%, need to set compr_level */
+	int compr_level;						/* How strong (100) or weak (0) is compression */
+	int last_compr_level;						/* How strong (100) or weak (0) was compression */
 	int usb_bandwidth;						/* Mbit/s */
 
 	/* Statistics that can be overlayed on the screen */
-	unsigned long isocUrbCount;			// How many URBs we received so far
+	unsigned long isoc_urb_count;			/* How many URBs we received so far */
 	unsigned long urb_length;			/* Length of last URB */
-	unsigned long isocDataCount;			/* How many bytes we received */
+	unsigned long isoc_data_count;			/* How many bytes we received */
 	unsigned long header_count;			/* How many frame headers we found */
 	unsigned long scratch_ovf_count;		/* How many times we overflowed scratch */
-	unsigned long isocSkipCount;			/* How many empty ISO packets received */
-	unsigned long isocErrCount;			/* How many bad ISO packets received */
-	unsigned long isocPacketCount;			// How many packets we totally got
-	unsigned long timeInIrq;			// How long do we need for interrupt
-	int isocMeasureBandwidthCount;
-	int frame_num;					// How many video frames we send to user
-	int maxStripLen;				// How big is the biggest strip
-	int comprBlockPos;
-	int stripLenErrors;				// How many times was BlockPos greater than StripLen
-	int stripMagicErrors;
-	int stripLineNumberErrors;
-	int ComprBlockTypes[4];
+	unsigned long isoc_skip_count;			/* How many empty ISO packets received */
+	unsigned long isoc_err_count;			/* How many bad ISO packets received */
+	unsigned long isoc_packet_count;		/* How many packets we totally got */
+	unsigned long time_in_irq;			/* How long do we need for interrupt */
+	int isoc_measure_bandwidth_count;
+	int frame_num;					/* How many video frames we send to user */
+	int max_strip_len;				/* How big is the biggest strip */
+	int comprblock_pos;
+	int strip_len_errors;				/* How many times was block_pos greater than strip_len */
+	int strip_magic_errors;
+	int strip_line_number_errors;
+	int compr_block_types[4];
 };
 
 static inline struct usb_usbvision *to_usbvision(struct v4l2_device *v4l2_dev)
@@ -494,13 +495,13 @@ void usbvision_scratch_free(struct usb_u
 int usbvision_decompress_alloc(struct usb_usbvision *usbvision);
 void usbvision_decompress_free(struct usb_usbvision *usbvision);
 
-int usbvision_setup(struct usb_usbvision *usbvision,int format);
+int usbvision_setup(struct usb_usbvision *usbvision, int format);
 int usbvision_init_isoc(struct usb_usbvision *usbvision);
 int usbvision_restart_isoc(struct usb_usbvision *usbvision);
 void usbvision_stop_isoc(struct usb_usbvision *usbvision);
 int usbvision_set_alternate(struct usb_usbvision *dev);
 
-int usbvision_set_audio(struct usb_usbvision *usbvision, int AudioChannel);
+int usbvision_set_audio(struct usb_usbvision *usbvision, int audio_channel);
 int usbvision_audio_off(struct usb_usbvision *usbvision);
 
 int usbvision_begin_streaming(struct usb_usbvision *usbvision);
@@ -511,9 +512,9 @@ int usbvision_muxsel(struct usb_usbvisio
 int usbvision_set_input(struct usb_usbvision *usbvision);
 int usbvision_set_output(struct usb_usbvision *usbvision, int width, int height);
 
-void usbvision_init_powerOffTimer(struct usb_usbvision *usbvision);
-void usbvision_set_powerOffTimer(struct usb_usbvision *usbvision);
-void usbvision_reset_powerOffTimer(struct usb_usbvision *usbvision);
+void usbvision_init_power_off_timer(struct usb_usbvision *usbvision);
+void usbvision_set_power_off_timer(struct usb_usbvision *usbvision);
+void usbvision_reset_power_off_timer(struct usb_usbvision *usbvision);
 int usbvision_power_off(struct usb_usbvision *usbvision);
 int usbvision_power_on(struct usb_usbvision *usbvision);
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/usbvision/usbvision-i2c.c linux-libre-2.6.38-gnu1/drivers/media/video/usbvision/usbvision-i2c.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/usbvision/usbvision-i2c.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/usbvision/usbvision-i2c.c	2011-03-14 21:20:32.000000000 -0400
@@ -28,18 +28,18 @@
 #include <linux/module.h>
 #include <linux/delay.h>
 #include <linux/init.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <linux/ioport.h>
 #include <linux/errno.h>
 #include <linux/usb.h>
 #include <linux/i2c.h>
 #include "usbvision.h"
 
-#define DBG_I2C		1<<0
+#define DBG_I2C		(1 << 0)
 
 static int i2c_debug;
 
-module_param (i2c_debug, int, 0644);			// debug_i2c_usb mode of the device driver
+module_param(i2c_debug, int, 0644);			/* debug_i2c_usb mode of the device driver */
 MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]");
 
 #define PDEBUG(level, fmt, args...) { \
@@ -72,8 +72,8 @@ static inline int try_write_address(stru
 		udelay(10);
 	}
 	if (i) {
-		PDEBUG(DBG_I2C,"Needed %d retries for address %#2x", i, addr);
-		PDEBUG(DBG_I2C,"Maybe there's no device at this address");
+		PDEBUG(DBG_I2C, "Needed %d retries for address %#2x", i, addr);
+		PDEBUG(DBG_I2C, "Maybe there's no device at this address");
 	}
 	return ret;
 }
@@ -96,8 +96,8 @@ static inline int try_read_address(struc
 		udelay(10);
 	}
 	if (i) {
-		PDEBUG(DBG_I2C,"Needed %d retries for address %#2x", i, addr);
-		PDEBUG(DBG_I2C,"Maybe there's no device at this address");
+		PDEBUG(DBG_I2C, "Needed %d retries for address %#2x", i, addr);
+		PDEBUG(DBG_I2C, "Maybe there's no device at this address");
 	}
 	return ret;
 }
@@ -143,9 +143,8 @@ static inline int usb_find_address(struc
 		else
 			ret = try_write_address(i2c_adap, addr, retries);
 
-		if (ret != 1) {
+		if (ret != 1)
 			return -EREMOTEIO;
-		}
 	}
 	return 0;
 }
@@ -164,22 +163,20 @@ usbvision_i2c_xfer(struct i2c_adapter *i
 		pmsg = &msgs[i];
 		ret = usb_find_address(i2c_adap, pmsg, i2c_adap->retries, &addr);
 		if (ret != 0) {
-			PDEBUG(DBG_I2C,"got NAK from device, message #%d", i);
+			PDEBUG(DBG_I2C, "got NAK from device, message #%d", i);
 			return (ret < 0) ? ret : -EREMOTEIO;
 		}
 
 		if (pmsg->flags & I2C_M_RD) {
 			/* read bytes into buffer */
 			ret = (usbvision_i2c_read(usbvision, addr, pmsg->buf, pmsg->len));
-			if (ret < pmsg->len) {
+			if (ret < pmsg->len)
 				return (ret < 0) ? ret : -EREMOTEIO;
-			}
 		} else {
 			/* write bytes from buffer */
 			ret = (usbvision_i2c_write(usbvision, addr, pmsg->buf, pmsg->len));
-			if (ret < pmsg->len) {
+			if (ret < pmsg->len)
 				return (ret < 0) ? ret : -EREMOTEIO;
-			}
 		}
 	}
 	return num;
@@ -219,7 +216,7 @@ int usbvision_i2c_register(struct usb_us
 
 	sprintf(usbvision->i2c_adap.name, "%s-%d-%s", i2c_adap_template.name,
 		usbvision->dev->bus->busnum, usbvision->dev->devpath);
-	PDEBUG(DBG_I2C,"Adaptername: %s", usbvision->i2c_adap.name);
+	PDEBUG(DBG_I2C, "Adaptername: %s", usbvision->i2c_adap.name);
 	usbvision->i2c_adap.dev.parent = &usbvision->dev->dev;
 
 	i2c_set_adapdata(&usbvision->i2c_adap, &usbvision->v4l2_dev);
@@ -244,7 +241,7 @@ int usbvision_i2c_register(struct usb_us
 	PDEBUG(DBG_I2C, "i2c bus for %s registered", usbvision->i2c_adap.name);
 
 	/* Request the load of the i2c modules we need */
-	switch (usbvision_device_data[usbvision->DevModel].Codec) {
+	switch (usbvision_device_data[usbvision->dev_model].codec) {
 	case CODEC_SAA7113:
 	case CODEC_SAA7111:
 		/* Without this delay the detection of the saa711x is
@@ -255,7 +252,7 @@ int usbvision_i2c_register(struct usb_us
 				"saa7115_auto", 0, saa711x_addrs);
 		break;
 	}
-	if (usbvision_device_data[usbvision->DevModel].Tuner == 1) {
+	if (usbvision_device_data[usbvision->dev_model].tuner == 1) {
 		struct v4l2_subdev *sd;
 		enum v4l2_i2c_tuner_type type;
 		struct tuner_setup tun_setup;
@@ -293,7 +290,7 @@ int usbvision_i2c_unregister(struct usb_
 	i2c_del_adapter(&(usbvision->i2c_adap));
 	usbvision->registered_i2c = 0;
 
-	PDEBUG(DBG_I2C,"i2c bus for %s unregistered", usbvision->i2c_adap.name);
+	PDEBUG(DBG_I2C, "i2c bus for %s unregistered", usbvision->i2c_adap.name);
 
 	return 0;
 }
@@ -355,9 +352,9 @@ usbvision_i2c_read_max4(struct usb_usbvi
 
 	if (i2c_debug & DBG_I2C) {
 		int idx;
-		for (idx = 0; idx < len; idx++) {
-			PDEBUG(DBG_I2C,"read %x from address %x", (unsigned char)buf[idx], addr);
-		}
+
+		for (idx = 0; idx < len; idx++)
+			PDEBUG(DBG_I2C, "read %x from address %x", (unsigned char)buf[idx], addr);
 	}
 	return len;
 }
@@ -416,9 +413,9 @@ static int usbvision_i2c_write_max4(stru
 
 	if (i2c_debug & DBG_I2C) {
 		int idx;
-		for (idx = 0; idx < len; idx++) {
-			PDEBUG(DBG_I2C,"wrote %x at address %x", (unsigned char)buf[idx], addr);
-		}
+
+		for (idx = 0; idx < len; idx++)
+			PDEBUG(DBG_I2C, "wrote %x at address %x", (unsigned char)buf[idx], addr);
 	}
 	return len;
 }
@@ -426,18 +423,18 @@ static int usbvision_i2c_write_max4(stru
 static int usbvision_i2c_write(struct usb_usbvision *usbvision, unsigned char addr, char *buf,
 			    short len)
 {
-	char *bufPtr = buf;
+	char *buf_ptr = buf;
 	int retval;
 	int wrcount = 0;
 	int count;
-	int maxLen = 4;
+	int max_len = 4;
 
 	while (len > 0) {
-		count = (len > maxLen) ? maxLen : len;
-		retval = usbvision_i2c_write_max4(usbvision, addr, bufPtr, count);
+		count = (len > max_len) ? max_len : len;
+		retval = usbvision_i2c_write_max4(usbvision, addr, buf_ptr, count);
 		if (retval > 0) {
 			len -= count;
-			bufPtr += count;
+			buf_ptr += count;
 			wrcount += count;
 		} else
 			return (retval < 0) ? retval : -EFAULT;
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/usbvision/usbvision-video.c linux-libre-2.6.38-gnu1/drivers/media/video/usbvision/usbvision-video.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/usbvision/usbvision-video.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/usbvision/usbvision-video.c	2011-03-14 21:20:32.000000000 -0400
@@ -56,7 +56,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/spinlock.h>
-#include <asm/io.h>
+#include <linux/io.h>
 #include <linux/videodev2.h>
 #include <linux/i2c.h>
 
@@ -70,8 +70,8 @@
 #include "usbvision.h"
 #include "usbvision-cards.h"
 
-#define DRIVER_AUTHOR "Joerg Heckenbach <joerg@heckenbach-aw.de>,\
- Dwaine Garden <DwaineGarden@rogers.com>"
+#define DRIVER_AUTHOR "Joerg Heckenbach <joerg@heckenbach-aw.de>, \
+Dwaine Garden <DwaineGarden@rogers.com>"
 #define DRIVER_NAME "usbvision"
 #define DRIVER_ALIAS "USBVision"
 #define DRIVER_DESC "USBVision USB Video Device Driver for Linux"
@@ -82,9 +82,9 @@
 #define USBVISION_DRIVER_VERSION KERNEL_VERSION(USBVISION_DRIVER_VERSION_MAJOR,\
 USBVISION_DRIVER_VERSION_MINOR,\
 USBVISION_DRIVER_VERSION_PATCHLEVEL)
-#define USBVISION_VERSION_STRING __stringify(USBVISION_DRIVER_VERSION_MAJOR)\
- "." __stringify(USBVISION_DRIVER_VERSION_MINOR)\
- "." __stringify(USBVISION_DRIVER_VERSION_PATCHLEVEL)
+#define USBVISION_VERSION_STRING __stringify(USBVISION_DRIVER_VERSION_MAJOR) \
+"." __stringify(USBVISION_DRIVER_VERSION_MINOR) \
+"." __stringify(USBVISION_DRIVER_VERSION_PATCHLEVEL)
 
 #define	ENABLE_HEXDUMP	0	/* Enable if you need it */
 
@@ -96,16 +96,16 @@ USBVISION_DRIVER_VERSION_PATCHLEVEL)
 				__func__, __LINE__ , ## args); \
 	}
 #else
-	#define PDEBUG(level, fmt, args...) do {} while(0)
+	#define PDEBUG(level, fmt, args...) do {} while (0)
 #endif
 
-#define DBG_IO		1<<1
-#define DBG_PROBE	1<<2
-#define DBG_MMAP	1<<3
+#define DBG_IO		(1 << 1)
+#define DBG_PROBE	(1 << 2)
+#define DBG_MMAP	(1 << 3)
 
-//String operations
-#define rmspace(str)	while(*str==' ') str++;
-#define goto2next(str)	while(*str!=' ') str++; while(*str==' ') str++;
+/* String operations */
+#define rmspace(str)	while (*str == ' ') str++;
+#define goto2next(str)	while (*str != ' ') str++; while (*str == ' ') str++;
 
 
 /* sequential number of usbvision device */
@@ -118,7 +118,7 @@ static struct usbvision_v4l2_format_st u
 	{ 1, 4, 32, V4L2_PIX_FMT_RGB32   , "RGB32" },
 	{ 1, 2, 16, V4L2_PIX_FMT_RGB555  , "RGB555" },
 	{ 1, 2, 16, V4L2_PIX_FMT_YUYV    , "YUV422" },
-	{ 1, 2, 12, V4L2_PIX_FMT_YVU420  , "YUV420P" }, // 1.5 !
+	{ 1, 2, 12, V4L2_PIX_FMT_YVU420  , "YUV420P" }, /* 1.5 ! */
 	{ 1, 2, 16, V4L2_PIX_FMT_YUV422P , "YUV422P" }
 };
 
@@ -127,11 +127,11 @@ static void usbvision_release(struct usb
 
 /* Default initialization of device driver parameters */
 /* Set the default format for ISOC endpoint */
-static int isocMode = ISOC_MODE_COMPRESS;
+static int isoc_mode = ISOC_MODE_COMPRESS;
 /* Set the default Debug Mode of the device driver */
 static int video_debug;
 /* Set the default device to power on at startup */
-static int PowerOnAtOpen = 1;
+static int power_on_at_open = 1;
 /* Sequential Number of Video Device */
 static int video_nr = -1;
 /* Sequential Number of Radio Device */
@@ -140,20 +140,20 @@ static int radio_nr = -1;
 /* Grab parameters for the device driver */
 
 /* Showing parameters under SYSFS */
-module_param(isocMode, int, 0444);
+module_param(isoc_mode, int, 0444);
 module_param(video_debug, int, 0444);
-module_param(PowerOnAtOpen, int, 0444);
+module_param(power_on_at_open, int, 0444);
 module_param(video_nr, int, 0444);
 module_param(radio_nr, int, 0444);
 
-MODULE_PARM_DESC(isocMode, " Set the default format for ISOC endpoint.  Default: 0x60 (Compression On)");
+MODULE_PARM_DESC(isoc_mode, " Set the default format for ISOC endpoint.  Default: 0x60 (Compression On)");
 MODULE_PARM_DESC(video_debug, " Set the default Debug Mode of the device driver.  Default: 0 (Off)");
-MODULE_PARM_DESC(PowerOnAtOpen, " Set the default device to power on when device is opened.  Default: 1 (On)");
+MODULE_PARM_DESC(power_on_at_open, " Set the default device to power on when device is opened.  Default: 1 (On)");
 MODULE_PARM_DESC(video_nr, "Set video device number (/dev/videoX).  Default: -1 (autodetect)");
 MODULE_PARM_DESC(radio_nr, "Set radio device number (/dev/radioX).  Default: -1 (autodetect)");
 
 
-// Misc stuff
+/* Misc stuff */
 MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE(DRIVER_LICENSE);
@@ -192,7 +192,7 @@ static ssize_t show_model(struct device
 		container_of(cd, struct video_device, dev);
 	struct usb_usbvision *usbvision = video_get_drvdata(vdev);
 	return sprintf(buf, "%s\n",
-		       usbvision_device_data[usbvision->DevModel].ModelString);
+		       usbvision_device_data[usbvision->dev_model].model_string);
 }
 static DEVICE_ATTR(model, S_IRUGO, show_model, NULL);
 
@@ -205,7 +205,7 @@ static ssize_t show_hue(struct device *c
 	struct v4l2_control ctrl;
 	ctrl.id = V4L2_CID_HUE;
 	ctrl.value = 0;
-	if(usbvision->user)
+	if (usbvision->user)
 		call_all(usbvision, core, g_ctrl, &ctrl);
 	return sprintf(buf, "%d\n", ctrl.value);
 }
@@ -220,7 +220,7 @@ static ssize_t show_contrast(struct devi
 	struct v4l2_control ctrl;
 	ctrl.id = V4L2_CID_CONTRAST;
 	ctrl.value = 0;
-	if(usbvision->user)
+	if (usbvision->user)
 		call_all(usbvision, core, g_ctrl, &ctrl);
 	return sprintf(buf, "%d\n", ctrl.value);
 }
@@ -235,7 +235,7 @@ static ssize_t show_brightness(struct de
 	struct v4l2_control ctrl;
 	ctrl.id = V4L2_CID_BRIGHTNESS;
 	ctrl.value = 0;
-	if(usbvision->user)
+	if (usbvision->user)
 		call_all(usbvision, core, g_ctrl, &ctrl);
 	return sprintf(buf, "%d\n", ctrl.value);
 }
@@ -250,7 +250,7 @@ static ssize_t show_saturation(struct de
 	struct v4l2_control ctrl;
 	ctrl.id = V4L2_CID_SATURATION;
 	ctrl.value = 0;
-	if(usbvision->user)
+	if (usbvision->user)
 		call_all(usbvision, core, g_ctrl, &ctrl);
 	return sprintf(buf, "%d\n", ctrl.value);
 }
@@ -263,7 +263,7 @@ static ssize_t show_streaming(struct dev
 		container_of(cd, struct video_device, dev);
 	struct usb_usbvision *usbvision = video_get_drvdata(vdev);
 	return sprintf(buf, "%s\n",
-		       YES_NO(usbvision->streaming==Stream_On?1:0));
+		       YES_NO(usbvision->streaming == stream_on ? 1 : 0));
 }
 static DEVICE_ATTR(streaming, S_IRUGO, show_streaming, NULL);
 
@@ -274,7 +274,7 @@ static ssize_t show_compression(struct d
 		container_of(cd, struct video_device, dev);
 	struct usb_usbvision *usbvision = video_get_drvdata(vdev);
 	return sprintf(buf, "%s\n",
-		       YES_NO(usbvision->isocMode==ISOC_MODE_COMPRESS));
+		       YES_NO(usbvision->isoc_mode == ISOC_MODE_COMPRESS));
 }
 static DEVICE_ATTR(compression, S_IRUGO, show_compression, NULL);
 
@@ -284,42 +284,43 @@ static ssize_t show_device_bridge(struct
 	struct video_device *vdev =
 		container_of(cd, struct video_device, dev);
 	struct usb_usbvision *usbvision = video_get_drvdata(vdev);
-	return sprintf(buf, "%d\n", usbvision->bridgeType);
+	return sprintf(buf, "%d\n", usbvision->bridge_type);
 }
 static DEVICE_ATTR(bridge, S_IRUGO, show_device_bridge, NULL);
 
 static void usbvision_create_sysfs(struct video_device *vdev)
 {
 	int res;
+
 	if (!vdev)
 		return;
 	do {
 		res = device_create_file(&vdev->dev, &dev_attr_version);
-		if (res<0)
+		if (res < 0)
 			break;
 		res = device_create_file(&vdev->dev, &dev_attr_model);
-		if (res<0)
+		if (res < 0)
 			break;
 		res = device_create_file(&vdev->dev, &dev_attr_hue);
-		if (res<0)
+		if (res < 0)
 			break;
 		res = device_create_file(&vdev->dev, &dev_attr_contrast);
-		if (res<0)
+		if (res < 0)
 			break;
 		res = device_create_file(&vdev->dev, &dev_attr_brightness);
-		if (res<0)
+		if (res < 0)
 			break;
 		res = device_create_file(&vdev->dev, &dev_attr_saturation);
-		if (res<0)
+		if (res < 0)
 			break;
 		res = device_create_file(&vdev->dev, &dev_attr_streaming);
-		if (res<0)
+		if (res < 0)
 			break;
 		res = device_create_file(&vdev->dev, &dev_attr_compression);
-		if (res<0)
+		if (res < 0)
 			break;
 		res = device_create_file(&vdev->dev, &dev_attr_bridge);
-		if (res>=0)
+		if (res >= 0)
 			return;
 	} while (0);
 
@@ -352,24 +353,23 @@ static void usbvision_remove_sysfs(struc
 static int usbvision_v4l2_open(struct file *file)
 {
 	struct usb_usbvision *usbvision = video_drvdata(file);
-	int errCode = 0;
+	int err_code = 0;
 
 	PDEBUG(DBG_IO, "open");
 
-	mutex_lock(&usbvision->lock);
-	usbvision_reset_powerOffTimer(usbvision);
+	usbvision_reset_power_off_timer(usbvision);
 
 	if (usbvision->user)
-		errCode = -EBUSY;
+		err_code = -EBUSY;
 	else {
 		/* Allocate memory for the scratch ring buffer */
-		errCode = usbvision_scratch_alloc(usbvision);
-		if (isocMode==ISOC_MODE_COMPRESS) {
+		err_code = usbvision_scratch_alloc(usbvision);
+		if (isoc_mode == ISOC_MODE_COMPRESS) {
 			/* Allocate intermediate decompression buffers
 			   only if needed */
-			errCode = usbvision_decompress_alloc(usbvision);
+			err_code = usbvision_decompress_alloc(usbvision);
 		}
-		if (errCode) {
+		if (err_code) {
 			/* Deallocate all buffers if trouble */
 			usbvision_scratch_free(usbvision);
 			usbvision_decompress_free(usbvision);
@@ -377,7 +377,7 @@ static int usbvision_v4l2_open(struct fi
 	}
 
 	/* If so far no errors then we shall start the camera */
-	if (!errCode) {
+	if (!err_code) {
 		if (usbvision->power == 0) {
 			usbvision_power_on(usbvision);
 			usbvision_i2c_register(usbvision);
@@ -386,21 +386,21 @@ static int usbvision_v4l2_open(struct fi
 		/* Send init sequence only once, it's large! */
 		if (!usbvision->initialized) {
 			int setup_ok = 0;
-			setup_ok = usbvision_setup(usbvision,isocMode);
+			setup_ok = usbvision_setup(usbvision, isoc_mode);
 			if (setup_ok)
 				usbvision->initialized = 1;
 			else
-				errCode = -EBUSY;
+				err_code = -EBUSY;
 		}
 
-		if (!errCode) {
+		if (!err_code) {
 			usbvision_begin_streaming(usbvision);
-			errCode = usbvision_init_isoc(usbvision);
+			err_code = usbvision_init_isoc(usbvision);
 			/* device must be initialized before isoc transfer */
-			usbvision_muxsel(usbvision,0);
+			usbvision_muxsel(usbvision, 0);
 			usbvision->user++;
 		} else {
-			if (PowerOnAtOpen) {
+			if (power_on_at_open) {
 				usbvision_i2c_unregister(usbvision);
 				usbvision_power_off(usbvision);
 				usbvision->initialized = 0;
@@ -412,8 +412,7 @@ static int usbvision_v4l2_open(struct fi
 	usbvision_empty_framequeues(usbvision);
 
 	PDEBUG(DBG_IO, "success");
-	mutex_unlock(&usbvision->lock);
-	return errCode;
+	return err_code;
 }
 
 /*
@@ -429,7 +428,6 @@ static int usbvision_v4l2_close(struct f
 	struct usb_usbvision *usbvision = video_drvdata(file);
 
 	PDEBUG(DBG_IO, "close");
-	mutex_lock(&usbvision->lock);
 
 	usbvision_audio_off(usbvision);
 	usbvision_restart_isoc(usbvision);
@@ -442,15 +440,13 @@ static int usbvision_v4l2_close(struct f
 
 	usbvision->user--;
 
-	if (PowerOnAtOpen) {
+	if (power_on_at_open) {
 		/* power off in a little while
 		   to avoid off/on every close/open short sequences */
-		usbvision_set_powerOffTimer(usbvision);
+		usbvision_set_power_off_timer(usbvision);
 		usbvision->initialized = 0;
 	}
 
-	mutex_unlock(&usbvision->lock);
-
 	if (usbvision->remove_pending) {
 		printk(KERN_INFO "%s: Final disconnect\n", __func__);
 		usbvision_release(usbvision);
@@ -468,55 +464,55 @@ static int usbvision_v4l2_close(struct f
  *
  */
 #ifdef CONFIG_VIDEO_ADV_DEBUG
-static int vidioc_g_register (struct file *file, void *priv,
+static int vidioc_g_register(struct file *file, void *priv,
 				struct v4l2_dbg_register *reg)
 {
 	struct usb_usbvision *usbvision = video_drvdata(file);
-	int errCode;
+	int err_code;
 
 	if (!v4l2_chip_match_host(&reg->match))
 		return -EINVAL;
 	/* NT100x has a 8-bit register space */
-	errCode = usbvision_read_reg(usbvision, reg->reg&0xff);
-	if (errCode < 0) {
+	err_code = usbvision_read_reg(usbvision, reg->reg&0xff);
+	if (err_code < 0) {
 		dev_err(&usbvision->vdev->dev,
 			"%s: VIDIOC_DBG_G_REGISTER failed: error %d\n",
-				__func__, errCode);
-		return errCode;
+				__func__, err_code);
+		return err_code;
 	}
-	reg->val = errCode;
+	reg->val = err_code;
 	reg->size = 1;
 	return 0;
 }
 
-static int vidioc_s_register (struct file *file, void *priv,
+static int vidioc_s_register(struct file *file, void *priv,
 				struct v4l2_dbg_register *reg)
 {
 	struct usb_usbvision *usbvision = video_drvdata(file);
-	int errCode;
+	int err_code;
 
 	if (!v4l2_chip_match_host(&reg->match))
 		return -EINVAL;
 	/* NT100x has a 8-bit register space */
-	errCode = usbvision_write_reg(usbvision, reg->reg&0xff, reg->val);
-	if (errCode < 0) {
+	err_code = usbvision_write_reg(usbvision, reg->reg & 0xff, reg->val);
+	if (err_code < 0) {
 		dev_err(&usbvision->vdev->dev,
 			"%s: VIDIOC_DBG_S_REGISTER failed: error %d\n",
-				__func__, errCode);
-		return errCode;
+				__func__, err_code);
+		return err_code;
 	}
 	return 0;
 }
 #endif
 
-static int vidioc_querycap (struct file *file, void  *priv,
+static int vidioc_querycap(struct file *file, void  *priv,
 					struct v4l2_capability *vc)
 {
 	struct usb_usbvision *usbvision = video_drvdata(file);
 
 	strlcpy(vc->driver, "USBVision", sizeof(vc->driver));
 	strlcpy(vc->card,
-		usbvision_device_data[usbvision->DevModel].ModelString,
+		usbvision_device_data[usbvision->dev_model].model_string,
 		sizeof(vc->card));
 	usb_make_path(usbvision->dev, vc->bus_info, sizeof(vc->bus_info));
 	vc->version = USBVISION_DRIVER_VERSION;
@@ -528,7 +524,7 @@ static int vidioc_querycap (struct file
 	return 0;
 }
 
-static int vidioc_enum_input (struct file *file, void *priv,
+static int vidioc_enum_input(struct file *file, void *priv,
 				struct v4l2_input *vi)
 {
 	struct usb_usbvision *usbvision = video_drvdata(file);
@@ -536,16 +532,16 @@ static int vidioc_enum_input (struct fil
 
 	if (vi->index >= usbvision->video_inputs)
 		return -EINVAL;
-	if (usbvision->have_tuner) {
+	if (usbvision->have_tuner)
 		chan = vi->index;
-	} else {
-		chan = vi->index + 1; /*skip Television string*/
-	}
+	else
+		chan = vi->index + 1; /* skip Television string*/
+
 	/* Determine the requested input characteristics
 	   specific for each usbvision card model */
-	switch(chan) {
+	switch (chan) {
 	case 0:
-		if (usbvision_device_data[usbvision->DevModel].VideoChannels == 4) {
+		if (usbvision_device_data[usbvision->dev_model].video_channels == 4) {
 			strcpy(vi->name, "White Video Input");
 		} else {
 			strcpy(vi->name, "Television");
@@ -557,20 +553,18 @@ static int vidioc_enum_input (struct fil
 		break;
 	case 1:
 		vi->type = V4L2_INPUT_TYPE_CAMERA;
-		if (usbvision_device_data[usbvision->DevModel].VideoChannels == 4) {
+		if (usbvision_device_data[usbvision->dev_model].video_channels == 4)
 			strcpy(vi->name, "Green Video Input");
-		} else {
+		else
 			strcpy(vi->name, "Composite Video Input");
-		}
 		vi->std = V4L2_STD_PAL;
 		break;
 	case 2:
 		vi->type = V4L2_INPUT_TYPE_CAMERA;
-		if (usbvision_device_data[usbvision->DevModel].VideoChannels == 4) {
+		if (usbvision_device_data[usbvision->dev_model].video_channels == 4)
 			strcpy(vi->name, "Yellow Video Input");
-		} else {
+		else
 			strcpy(vi->name, "S-Video Input");
-		}
 		vi->std = V4L2_STD_PAL;
 		break;
 	case 3:
@@ -582,7 +576,7 @@ static int vidioc_enum_input (struct fil
 	return 0;
 }
 
-static int vidioc_g_input (struct file *file, void *priv, unsigned int *input)
+static int vidioc_g_input(struct file *file, void *priv, unsigned int *input)
 {
 	struct usb_usbvision *usbvision = video_drvdata(file);
 
@@ -590,46 +584,42 @@ static int vidioc_g_input (struct file *
 	return 0;
 }
 
-static int vidioc_s_input (struct file *file, void *priv, unsigned int input)
+static int vidioc_s_input(struct file *file, void *priv, unsigned int input)
 {
 	struct usb_usbvision *usbvision = video_drvdata(file);
 
 	if (input >= usbvision->video_inputs)
 		return -EINVAL;
 
-	mutex_lock(&usbvision->lock);
 	usbvision_muxsel(usbvision, input);
 	usbvision_set_input(usbvision);
 	usbvision_set_output(usbvision,
 			     usbvision->curwidth,
 			     usbvision->curheight);
-	mutex_unlock(&usbvision->lock);
 	return 0;
 }
 
-static int vidioc_s_std (struct file *file, void *priv, v4l2_std_id *id)
+static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *id)
 {
 	struct usb_usbvision *usbvision = video_drvdata(file);
 
-	usbvision->tvnormId=*id;
+	usbvision->tvnorm_id = *id;
 
-	mutex_lock(&usbvision->lock);
-	call_all(usbvision, core, s_std, usbvision->tvnormId);
-	mutex_unlock(&usbvision->lock);
+	call_all(usbvision, core, s_std, usbvision->tvnorm_id);
 	/* propagate the change to the decoder */
 	usbvision_muxsel(usbvision, usbvision->ctl_input);
 
 	return 0;
 }
 
-static int vidioc_g_tuner (struct file *file, void *priv,
+static int vidioc_g_tuner(struct file *file, void *priv,
 				struct v4l2_tuner *vt)
 {
 	struct usb_usbvision *usbvision = video_drvdata(file);
 
-	if (!usbvision->have_tuner || vt->index)	// Only tuner 0
+	if (!usbvision->have_tuner || vt->index)	/* Only tuner 0 */
 		return -EINVAL;
-	if(usbvision->radio) {
+	if (usbvision->radio) {
 		strcpy(vt->name, "Radio");
 		vt->type = V4L2_TUNER_RADIO;
 	} else {
@@ -641,12 +631,12 @@ static int vidioc_g_tuner (struct file *
 	return 0;
 }
 
-static int vidioc_s_tuner (struct file *file, void *priv,
+static int vidioc_s_tuner(struct file *file, void *priv,
 				struct v4l2_tuner *vt)
 {
 	struct usb_usbvision *usbvision = video_drvdata(file);
 
-	// Only no or one tuner for now
+	/* Only no or one tuner for now */
 	if (!usbvision->have_tuner || vt->index)
 		return -EINVAL;
 	/* let clients handle this */
@@ -655,28 +645,27 @@ static int vidioc_s_tuner (struct file *
 	return 0;
 }
 
-static int vidioc_g_frequency (struct file *file, void *priv,
+static int vidioc_g_frequency(struct file *file, void *priv,
 				struct v4l2_frequency *freq)
 {
 	struct usb_usbvision *usbvision = video_drvdata(file);
 
-	freq->tuner = 0; // Only one tuner
-	if(usbvision->radio) {
+	freq->tuner = 0; /* Only one tuner */
+	if (usbvision->radio)
 		freq->type = V4L2_TUNER_RADIO;
-	} else {
+	else
 		freq->type = V4L2_TUNER_ANALOG_TV;
-	}
 	freq->frequency = usbvision->freq;
 
 	return 0;
 }
 
-static int vidioc_s_frequency (struct file *file, void *priv,
+static int vidioc_s_frequency(struct file *file, void *priv,
 				struct v4l2_frequency *freq)
 {
 	struct usb_usbvision *usbvision = video_drvdata(file);
 
-	// Only no or one tuner for now
+	/* Only no or one tuner for now */
 	if (!usbvision->have_tuner || freq->tuner)
 		return -EINVAL;
 
@@ -686,30 +675,27 @@ static int vidioc_s_frequency (struct fi
 	return 0;
 }
 
-static int vidioc_g_audio (struct file *file, void *priv, struct v4l2_audio *a)
+static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
 {
 	struct usb_usbvision *usbvision = video_drvdata(file);
 
-	if(usbvision->radio) {
-		strcpy(a->name,"Radio");
-	} else {
+	if (usbvision->radio)
+		strcpy(a->name, "Radio");
+	else
 		strcpy(a->name, "TV");
-	}
 
 	return 0;
 }
 
-static int vidioc_s_audio (struct file *file, void *fh,
+static int vidioc_s_audio(struct file *file, void *fh,
 			  struct v4l2_audio *a)
 {
-	if(a->index) {
+	if (a->index)
 		return -EINVAL;
-	}
-
 	return 0;
 }
 
-static int vidioc_queryctrl (struct file *file, void *priv,
+static int vidioc_queryctrl(struct file *file, void *priv,
 			    struct v4l2_queryctrl *ctrl)
 {
 	struct usb_usbvision *usbvision = video_drvdata(file);
@@ -722,52 +708,53 @@ static int vidioc_queryctrl (struct file
 	return 0;
 }
 
-static int vidioc_g_ctrl (struct file *file, void *priv,
+static int vidioc_g_ctrl(struct file *file, void *priv,
 				struct v4l2_control *ctrl)
 {
 	struct usb_usbvision *usbvision = video_drvdata(file);
-	call_all(usbvision, core, g_ctrl, ctrl);
 
+	call_all(usbvision, core, g_ctrl, ctrl);
 	return 0;
 }
 
-static int vidioc_s_ctrl (struct file *file, void *priv,
+static int vidioc_s_ctrl(struct file *file, void *priv,
 				struct v4l2_control *ctrl)
 {
 	struct usb_usbvision *usbvision = video_drvdata(file);
-	call_all(usbvision, core, s_ctrl, ctrl);
 
+	call_all(usbvision, core, s_ctrl, ctrl);
 	return 0;
 }
 
-static int vidioc_reqbufs (struct file *file,
+static int vidioc_reqbufs(struct file *file,
 			   void *priv, struct v4l2_requestbuffers *vr)
 {
 	struct usb_usbvision *usbvision = video_drvdata(file);
 	int ret;
 
-	RESTRICT_TO_RANGE(vr->count,1,USBVISION_NUMFRAMES);
+	RESTRICT_TO_RANGE(vr->count, 1, USBVISION_NUMFRAMES);
 
 	/* Check input validity:
 	   the user must do a VIDEO CAPTURE and MMAP method. */
 	if (vr->memory != V4L2_MEMORY_MMAP)
 		return -EINVAL;
 
-	if(usbvision->streaming == Stream_On) {
-		if ((ret = usbvision_stream_interrupt(usbvision)))
+	if (usbvision->streaming == stream_on) {
+		ret = usbvision_stream_interrupt(usbvision);
+		if (ret)
 			return ret;
 	}
 
 	usbvision_frames_free(usbvision);
 	usbvision_empty_framequeues(usbvision);
-	vr->count = usbvision_frames_alloc(usbvision,vr->count);
+	vr->count = usbvision_frames_alloc(usbvision, vr->count);
 
-	usbvision->curFrame = NULL;
+	usbvision->cur_frame = NULL;
 
 	return 0;
 }
 
-static int vidioc_querybuf (struct file *file,
+static int vidioc_querybuf(struct file *file,
 			    void *priv, struct v4l2_buffer *vb)
 {
 	struct usb_usbvision *usbvision = video_drvdata(file);
@@ -775,52 +762,49 @@ static int vidioc_querybuf (struct file
 
 	/* FIXME : must control
 	   that buffers are mapped (VIDIOC_REQBUFS has been called) */
-	if(vb->index>=usbvision->num_frames)  {
+	if (vb->index >= usbvision->num_frames)
 		return -EINVAL;
-	}
 	/* Updating the corresponding frame state */
 	vb->flags = 0;
 	frame = &usbvision->frame[vb->index];
-	if(frame->grabstate >= FrameState_Ready)
+	if (frame->grabstate >= frame_state_ready)
 		vb->flags |= V4L2_BUF_FLAG_QUEUED;
-	if(frame->grabstate >= FrameState_Done)
+	if (frame->grabstate >= frame_state_done)
 		vb->flags |= V4L2_BUF_FLAG_DONE;
-	if(frame->grabstate == FrameState_Unused)
+	if (frame->grabstate == frame_state_unused)
 		vb->flags |= V4L2_BUF_FLAG_MAPPED;
 	vb->memory = V4L2_MEMORY_MMAP;
 
-	vb->m.offset = vb->index*PAGE_ALIGN(usbvision->max_frame_size);
+	vb->m.offset = vb->index * PAGE_ALIGN(usbvision->max_frame_size);
 
 	vb->memory = V4L2_MEMORY_MMAP;
 	vb->field = V4L2_FIELD_NONE;
-	vb->length = usbvision->curwidth*
-		usbvision->curheight*
+	vb->length = usbvision->curwidth *
+		usbvision->curheight *
 		usbvision->palette.bytes_per_pixel;
 	vb->timestamp = usbvision->frame[vb->index].timestamp;
 	vb->sequence = usbvision->frame[vb->index].sequence;
 	return 0;
 }
 
-static int vidioc_qbuf (struct file *file, void *priv, struct v4l2_buffer *vb)
+static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *vb)
 {
 	struct usb_usbvision *usbvision = video_drvdata(file);
 	struct usbvision_frame *frame;
 	unsigned long lock_flags;
 
 	/* FIXME : works only on VIDEO_CAPTURE MODE, MMAP. */
-	if(vb->index>=usbvision->num_frames)  {
+	if (vb->index >= usbvision->num_frames)
 		return -EINVAL;
-	}
 
 	frame = &usbvision->frame[vb->index];
 
-	if (frame->grabstate != FrameState_Unused) {
+	if (frame->grabstate != frame_state_unused)
 		return -EAGAIN;
-	}
 
 	/* Mark it as ready and enqueue frame */
-	frame->grabstate = FrameState_Ready;
-	frame->scanstate = ScanState_Scanning;
+	frame->grabstate = frame_state_ready;
+	frame->scanstate = scan_state_scanning;
 	frame->scanlength = 0;	/* Accumulated in usbvision_parse_data() */
 
 	vb->flags &= ~V4L2_BUF_FLAG_DONE;
@@ -835,7 +819,7 @@ static int vidioc_qbuf (struct file *fil
 	return 0;
 }
 
-static int vidioc_dqbuf (struct file *file, void *priv, struct v4l2_buffer *vb)
+static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *vb)
 {
 	struct usb_usbvision *usbvision = video_drvdata(file);
 	int ret;
@@ -843,7 +827,7 @@ static int vidioc_dqbuf (struct file *fi
 	unsigned long lock_flags;
 
 	if (list_empty(&(usbvision->outqueue))) {
-		if (usbvision->streaming == Stream_Idle)
+		if (usbvision->streaming == stream_idle)
 			return -EINVAL;
 		ret = wait_event_interruptible
 			(usbvision->wait_frame,
@@ -858,7 +842,7 @@ static int vidioc_dqbuf (struct file *fi
 	list_del(usbvision->outqueue.next);
 	spin_unlock_irqrestore(&usbvision->queue_lock, lock_flags);
 
-	f->grabstate = FrameState_Unused;
+	f->grabstate = frame_state_unused;
 
 	vb->memory = V4L2_MEMORY_MMAP;
 	vb->flags = V4L2_BUF_FLAG_MAPPED |
@@ -877,7 +861,7 @@ static int vidioc_streamon(struct file *
 {
 	struct usb_usbvision *usbvision = video_drvdata(file);
 
-	usbvision->streaming = Stream_On;
+	usbvision->streaming = stream_on;
 	call_all(usbvision, video, s_stream, 1);
 
 	return 0;
@@ -891,7 +875,7 @@ static int vidioc_streamoff(struct file
 	if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
 		return -EINVAL;
 
-	if(usbvision->streaming == Stream_On) {
+	if (usbvision->streaming == stream_on) {
 		usbvision_stream_interrupt(usbvision);
 		/* Stop all video streamings */
 		call_all(usbvision, video, s_stream, 0);
@@ -901,18 +885,17 @@ static int vidioc_streamoff(struct file
 	return 0;
 }
 
-static int vidioc_enum_fmt_vid_cap (struct file *file, void  *priv,
+static int vidioc_enum_fmt_vid_cap(struct file *file, void  *priv,
 					struct v4l2_fmtdesc *vfd)
 {
-	if(vfd->index>=USBVISION_SUPPORTED_PALETTES-1) {
+	if (vfd->index >= USBVISION_SUPPORTED_PALETTES - 1)
 		return -EINVAL;
-	}
-	strcpy(vfd->description,usbvision_v4l2_format[vfd->index].desc);
+	strcpy(vfd->description, usbvision_v4l2_format[vfd->index].desc);
 	vfd->pixelformat = usbvision_v4l2_format[vfd->index].format;
 	return 0;
 }
 
-static int vidioc_g_fmt_vid_cap (struct file *file, void *priv,
+static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
 					struct v4l2_format *vf)
 {
 	struct usb_usbvision *usbvision = video_drvdata(file);
@@ -920,32 +903,31 @@ static int vidioc_g_fmt_vid_cap (struct
 	vf->fmt.pix.height = usbvision->curheight;
 	vf->fmt.pix.pixelformat = usbvision->palette.format;
 	vf->fmt.pix.bytesperline =
-		usbvision->curwidth*usbvision->palette.bytes_per_pixel;
-	vf->fmt.pix.sizeimage = vf->fmt.pix.bytesperline*usbvision->curheight;
+		usbvision->curwidth * usbvision->palette.bytes_per_pixel;
+	vf->fmt.pix.sizeimage = vf->fmt.pix.bytesperline * usbvision->curheight;
 	vf->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
 	vf->fmt.pix.field = V4L2_FIELD_NONE; /* Always progressive image */
 
 	return 0;
 }
 
-static int vidioc_try_fmt_vid_cap (struct file *file, void *priv,
+static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
 			       struct v4l2_format *vf)
 {
 	struct usb_usbvision *usbvision = video_drvdata(file);
-	int formatIdx;
+	int format_idx;
 
 	/* Find requested format in available ones */
-	for(formatIdx=0;formatIdx<USBVISION_SUPPORTED_PALETTES;formatIdx++) {
-		if(vf->fmt.pix.pixelformat ==
-		   usbvision_v4l2_format[formatIdx].format) {
-			usbvision->palette = usbvision_v4l2_format[formatIdx];
+	for (format_idx = 0; format_idx < USBVISION_SUPPORTED_PALETTES; format_idx++) {
+		if (vf->fmt.pix.pixelformat ==
+		   usbvision_v4l2_format[format_idx].format) {
+			usbvision->palette = usbvision_v4l2_format[format_idx];
 			break;
 		}
 	}
 	/* robustness */
-	if(formatIdx == USBVISION_SUPPORTED_PALETTES) {
+	if (format_idx == USBVISION_SUPPORTED_PALETTES)
 		return -EINVAL;
-	}
 	RESTRICT_TO_RANGE(vf->fmt.pix.width, MIN_FRAME_WIDTH, MAX_FRAME_WIDTH);
 	RESTRICT_TO_RANGE(vf->fmt.pix.height, MIN_FRAME_HEIGHT, MAX_FRAME_HEIGHT);
 
@@ -962,24 +944,23 @@ static int vidioc_s_fmt_vid_cap(struct f
 	struct usb_usbvision *usbvision = video_drvdata(file);
 	int ret;
 
-	if( 0 != (ret=vidioc_try_fmt_vid_cap (file, priv, vf)) ) {
+	ret = vidioc_try_fmt_vid_cap(file, priv, vf);
+	if (ret)
 		return ret;
-	}
 
 	/* stop io in case it is already in progress */
-	if(usbvision->streaming == Stream_On) {
-		if ((ret = usbvision_stream_interrupt(usbvision)))
+	if (usbvision->streaming == stream_on) {
+		ret = usbvision_stream_interrupt(usbvision);
+		if (ret)
 			return ret;
 	}
 	usbvision_frames_free(usbvision);
 	usbvision_empty_framequeues(usbvision);
 
-	usbvision->curFrame = NULL;
+	usbvision->cur_frame = NULL;
 
 	/* by now we are committed to the new data... */
-	mutex_lock(&usbvision->lock);
 	usbvision_set_output(usbvision, vf->fmt.pix.width, vf->fmt.pix.height);
-	mutex_unlock(&usbvision->lock);
 
 	return 0;
 }
@@ -990,8 +971,7 @@ static ssize_t usbvision_v4l2_read(struc
 	struct usb_usbvision *usbvision = video_drvdata(file);
 	int noblock = file->f_flags & O_NONBLOCK;
 	unsigned long lock_flags;
-
-	int ret,i;
+	int ret, i;
 	struct usbvision_frame *frame;
 
 	PDEBUG(DBG_IO, "%s: %ld bytes, noblock=%d", __func__,
@@ -1003,28 +983,28 @@ static ssize_t usbvision_v4l2_read(struc
 	/* This entry point is compatible with the mmap routines
 	   so that a user can do either VIDIOC_QBUF/VIDIOC_DQBUF
 	   to get frames or call read on the device. */
-	if(!usbvision->num_frames) {
+	if (!usbvision->num_frames) {
 		/* First, allocate some frames to work with
 		   if this has not been done with VIDIOC_REQBUF */
 		usbvision_frames_free(usbvision);
 		usbvision_empty_framequeues(usbvision);
-		usbvision_frames_alloc(usbvision,USBVISION_NUMFRAMES);
+		usbvision_frames_alloc(usbvision, USBVISION_NUMFRAMES);
 	}
 
-	if(usbvision->streaming != Stream_On) {
+	if (usbvision->streaming != stream_on) {
 		/* no stream is running, make it running ! */
-		usbvision->streaming = Stream_On;
+		usbvision->streaming = stream_on;
 		call_all(usbvision, video, s_stream, 1);
 	}
 
 	/* Then, enqueue as many frames as possible
 	   (like a user of VIDIOC_QBUF would do) */
-	for(i=0;i<usbvision->num_frames;i++) {
+	for (i = 0; i < usbvision->num_frames; i++) {
 		frame = &usbvision->frame[i];
-		if(frame->grabstate == FrameState_Unused) {
+		if (frame->grabstate == frame_state_unused) {
 			/* Mark it as ready and enqueue frame */
-			frame->grabstate = FrameState_Ready;
-			frame->scanstate = ScanState_Scanning;
+			frame->grabstate = frame_state_ready;
+			frame->scanstate = scan_state_scanning;
 			/* Accumulated in usbvision_parse_data() */
 			frame->scanlength = 0;
 
@@ -1040,7 +1020,7 @@ static ssize_t usbvision_v4l2_read(struc
 
 	/* Then try to steal a frame (like a VIDIOC_DQBUF would do) */
 	if (list_empty(&(usbvision->outqueue))) {
-		if(noblock)
+		if (noblock)
 			return -EAGAIN;
 
 		ret = wait_event_interruptible
@@ -1057,7 +1037,7 @@ static ssize_t usbvision_v4l2_read(struc
 	spin_unlock_irqrestore(&usbvision->queue_lock, lock_flags);
 
 	/* An error returns an empty frame */
-	if (frame->grabstate == FrameState_Error) {
+	if (frame->grabstate == frame_state_error) {
 		frame->bytes_read = 0;
 		return 0;
 	}
@@ -1070,9 +1050,8 @@ static ssize_t usbvision_v4l2_read(struc
 	if ((count + frame->bytes_read) > (unsigned long)frame->scanlength)
 		count = frame->scanlength - frame->bytes_read;
 
-	if (copy_to_user(buf, frame->data + frame->bytes_read, count)) {
+	if (copy_to_user(buf, frame->data + frame->bytes_read, count))
 		return -EFAULT;
-	}
 
 	frame->bytes_read += count;
 	PDEBUG(DBG_IO, "%s: {copy} count used=%ld, new bytes_read=%ld",
@@ -1080,12 +1059,12 @@ static ssize_t usbvision_v4l2_read(struc
 	       (unsigned long)count, frame->bytes_read);
 
 	/* For now, forget the frame if it has not been read in one shot. */
-/* 	if (frame->bytes_read >= frame->scanlength) {// All data has been read */
+/*	if (frame->bytes_read >= frame->scanlength) {*/ /* All data has been read */
 		frame->bytes_read = 0;
 
 		/* Mark it as available to be used again. */
-		frame->grabstate = FrameState_Unused;
-/* 	} */
+		frame->grabstate = frame_state_unused;
+/*	} */
 
 	return count;
 }
@@ -1100,16 +1079,11 @@ static int usbvision_v4l2_mmap(struct fi
 
 	PDEBUG(DBG_MMAP, "mmap");
 
-	mutex_lock(&usbvision->lock);
-
-	if (!USBVISION_IS_OPERATIONAL(usbvision)) {
-		mutex_unlock(&usbvision->lock);
+	if (!USBVISION_IS_OPERATIONAL(usbvision))
 		return -EFAULT;
-	}
 
 	if (!(vma->vm_flags & VM_WRITE) ||
 	    size != PAGE_ALIGN(usbvision->max_frame_size)) {
-		mutex_unlock(&usbvision->lock);
 		return -EINVAL;
 	}
 
@@ -1121,7 +1095,6 @@ static int usbvision_v4l2_mmap(struct fi
 	if (i == usbvision->num_frames) {
 		PDEBUG(DBG_MMAP,
 		       "mmap: user supplied mapping address is out of range");
-		mutex_unlock(&usbvision->lock);
 		return -EINVAL;
 	}
 
@@ -1131,10 +1104,8 @@ static int usbvision_v4l2_mmap(struct fi
 
 	pos = usbvision->frame[i].data;
 	while (size > 0) {
-
 		if (vm_insert_page(vma, start, vmalloc_to_page(pos))) {
 			PDEBUG(DBG_MMAP, "mmap: vm_insert_page failed");
-			mutex_unlock(&usbvision->lock);
 			return -EAGAIN;
 		}
 		start += PAGE_SIZE;
@@ -1142,7 +1113,6 @@ static int usbvision_v4l2_mmap(struct fi
 		size -= PAGE_SIZE;
 	}
 
-	mutex_unlock(&usbvision->lock);
 	return 0;
 }
 
@@ -1154,21 +1124,18 @@ static int usbvision_v4l2_mmap(struct fi
 static int usbvision_radio_open(struct file *file)
 {
 	struct usb_usbvision *usbvision = video_drvdata(file);
-	int errCode = 0;
+	int err_code = 0;
 
 	PDEBUG(DBG_IO, "%s:", __func__);
 
-	mutex_lock(&usbvision->lock);
-
 	if (usbvision->user) {
 		dev_err(&usbvision->rdev->dev,
 			"%s: Someone tried to open an already opened USBVision Radio!\n",
 				__func__);
-		errCode = -EBUSY;
-	}
-	else {
-		if(PowerOnAtOpen) {
-			usbvision_reset_powerOffTimer(usbvision);
+		err_code = -EBUSY;
+	} else {
+		if (power_on_at_open) {
+			usbvision_reset_power_off_timer(usbvision);
 			if (usbvision->power == 0) {
 				usbvision_power_on(usbvision);
 				usbvision_i2c_register(usbvision);
@@ -1176,80 +1143,73 @@ static int usbvision_radio_open(struct f
 		}
 
 		/* Alternate interface 1 is is the biggest frame size */
-		errCode = usbvision_set_alternate(usbvision);
-		if (errCode < 0) {
-			usbvision->last_error = errCode;
-			errCode = -EBUSY;
+		err_code = usbvision_set_alternate(usbvision);
+		if (err_code < 0) {
+			usbvision->last_error = err_code;
+			err_code = -EBUSY;
 			goto out;
 		}
 
-		// If so far no errors then we shall start the radio
+		/* If so far no errors then we shall start the radio */
 		usbvision->radio = 1;
 		call_all(usbvision, tuner, s_radio);
 		usbvision_set_audio(usbvision, USBVISION_AUDIO_RADIO);
 		usbvision->user++;
 	}
 
-	if (errCode) {
-		if (PowerOnAtOpen) {
+	if (err_code) {
+		if (power_on_at_open) {
 			usbvision_i2c_unregister(usbvision);
 			usbvision_power_off(usbvision);
 			usbvision->initialized = 0;
 		}
 	}
 out:
-	mutex_unlock(&usbvision->lock);
-	return errCode;
+	return err_code;
 }
 
 
 static int usbvision_radio_close(struct file *file)
 {
 	struct usb_usbvision *usbvision = video_drvdata(file);
-	int errCode = 0;
+	int err_code = 0;
 
 	PDEBUG(DBG_IO, "");
 
-	mutex_lock(&usbvision->lock);
-
 	/* Set packet size to 0 */
-	usbvision->ifaceAlt=0;
-	errCode = usb_set_interface(usbvision->dev, usbvision->iface,
-				    usbvision->ifaceAlt);
+	usbvision->iface_alt = 0;
+	err_code = usb_set_interface(usbvision->dev, usbvision->iface,
+				    usbvision->iface_alt);
 
 	usbvision_audio_off(usbvision);
-	usbvision->radio=0;
+	usbvision->radio = 0;
 	usbvision->user--;
 
-	if (PowerOnAtOpen) {
-		usbvision_set_powerOffTimer(usbvision);
+	if (power_on_at_open) {
+		usbvision_set_power_off_timer(usbvision);
 		usbvision->initialized = 0;
 	}
 
-	mutex_unlock(&usbvision->lock);
-
 	if (usbvision->remove_pending) {
 		printk(KERN_INFO "%s: Final disconnect\n", __func__);
 		usbvision_release(usbvision);
 	}
 
 	PDEBUG(DBG_IO, "success");
-	return errCode;
+	return err_code;
 }
 
-//
-// Video registration stuff
-//
+/* Video registration stuff */
 
-// Video template
+/* Video template */
 static const struct v4l2_file_operations usbvision_fops = {
 	.owner             = THIS_MODULE,
 	.open		= usbvision_v4l2_open,
 	.release	= usbvision_v4l2_close,
 	.read		= usbvision_v4l2_read,
 	.mmap		= usbvision_v4l2_mmap,
-	.ioctl		= video_ioctl2,
-/* 	.poll          = video_poll, */
+	.unlocked_ioctl	= video_ioctl2,
+/*	.poll		= video_poll, */
 };
 
 static const struct v4l2_ioctl_ops usbvision_ioctl_ops = {
@@ -1273,9 +1233,6 @@ static const struct v4l2_ioctl_ops usbvi
 	.vidioc_s_ctrl        = vidioc_s_ctrl,
 	.vidioc_streamon      = vidioc_streamon,
 	.vidioc_streamoff     = vidioc_streamoff,
-#ifdef CONFIG_VIDEO_V4L1_COMPAT
-/*  	.vidiocgmbuf          = vidiocgmbuf, */
-#endif
 	.vidioc_g_tuner       = vidioc_g_tuner,
 	.vidioc_s_tuner       = vidioc_s_tuner,
 	.vidioc_g_frequency   = vidioc_g_frequency,
@@ -1288,20 +1245,20 @@ static const struct v4l2_ioctl_ops usbvi
 
 static struct video_device usbvision_video_template = {
 	.fops		= &usbvision_fops,
-	.ioctl_ops 	= &usbvision_ioctl_ops,
+	.ioctl_ops	= &usbvision_ioctl_ops,
 	.name           = "usbvision-video",
 	.release	= video_device_release,
-	.tvnorms              = USBVISION_NORMS,
-	.current_norm         = V4L2_STD_PAL
+	.tvnorms        = USBVISION_NORMS,
+	.current_norm   = V4L2_STD_PAL
 };
 
 
-// Radio template
+/* Radio template */
 static const struct v4l2_file_operations usbvision_radio_fops = {
 	.owner             = THIS_MODULE,
 	.open		= usbvision_radio_open,
 	.release	= usbvision_radio_close,
-	.ioctl		= video_ioctl2,
+	.unlocked_ioctl	= video_ioctl2,
 };
 
 static const struct v4l2_ioctl_ops usbvision_radio_ioctl_ops = {
@@ -1322,9 +1279,9 @@ static const struct v4l2_ioctl_ops usbvi
 
 static struct video_device usbvision_radio_template = {
 	.fops		= &usbvision_radio_fops,
-	.name           = "usbvision-radio",
+	.name		= "usbvision-radio",
 	.release	= video_device_release,
-	.ioctl_ops 	= &usbvision_radio_ioctl_ops,
+	.ioctl_ops	= &usbvision_radio_ioctl_ops,
 
 	.tvnorms              = USBVISION_NORMS,
 	.current_norm         = V4L2_STD_PAL
@@ -1345,80 +1302,70 @@ static struct video_device *usbvision_vd
 	}
 
 	vdev = video_device_alloc();
-	if (NULL == vdev) {
+	if (NULL == vdev)
 		return NULL;
-	}
 	*vdev = *vdev_template;
+	vdev->lock = &usbvision->v4l2_lock;
 	vdev->v4l2_dev = &usbvision->v4l2_dev;
 	snprintf(vdev->name, sizeof(vdev->name), "%s", name);
 	video_set_drvdata(vdev, usbvision);
 	return vdev;
 }
 
-// unregister video4linux devices
+/* unregister video4linux devices */
 static void usbvision_unregister_video(struct usb_usbvision *usbvision)
 {
-	// Radio Device:
+	/* Radio Device: */
 	if (usbvision->rdev) {
 		PDEBUG(DBG_PROBE, "unregister %s [v4l2]",
 		       video_device_node_name(usbvision->rdev));
-		if (video_is_registered(usbvision->rdev)) {
+		if (video_is_registered(usbvision->rdev))
 			video_unregister_device(usbvision->rdev);
-		} else {
+		else
 			video_device_release(usbvision->rdev);
-		}
 		usbvision->rdev = NULL;
 	}
 
-	// Video Device:
+	/* Video Device: */
 	if (usbvision->vdev) {
 		PDEBUG(DBG_PROBE, "unregister %s [v4l2]",
 		       video_device_node_name(usbvision->vdev));
-		if (video_is_registered(usbvision->vdev)) {
+		if (video_is_registered(usbvision->vdev))
 			video_unregister_device(usbvision->vdev);
-		} else {
+		else
 			video_device_release(usbvision->vdev);
-		}
 		usbvision->vdev = NULL;
 	}
 }
 
-// register video4linux devices
+/* register video4linux devices */
 static int __devinit usbvision_register_video(struct usb_usbvision *usbvision)
 {
-	// Video Device:
+	/* Video Device: */
 	usbvision->vdev = usbvision_vdev_init(usbvision,
 					      &usbvision_video_template,
 					      "USBVision Video");
-	if (usbvision->vdev == NULL) {
+	if (usbvision->vdev == NULL)
 		goto err_exit;
-	}
-	if (video_register_device(usbvision->vdev,
-				  VFL_TYPE_GRABBER,
-				  video_nr)<0) {
+	if (video_register_device(usbvision->vdev, VFL_TYPE_GRABBER, video_nr) < 0)
 		goto err_exit;
-	}
 	printk(KERN_INFO "USBVision[%d]: registered USBVision Video device %s [v4l2]\n",
 	       usbvision->nr, video_device_node_name(usbvision->vdev));
 
-	// Radio Device:
-	if (usbvision_device_data[usbvision->DevModel].Radio) {
-		// usbvision has radio
+	/* Radio Device: */
+	if (usbvision_device_data[usbvision->dev_model].radio) {
+		/* usbvision has radio */
 		usbvision->rdev = usbvision_vdev_init(usbvision,
 						      &usbvision_radio_template,
 						      "USBVision Radio");
-		if (usbvision->rdev == NULL) {
+		if (usbvision->rdev == NULL)
 			goto err_exit;
-		}
-		if (video_register_device(usbvision->rdev,
-					  VFL_TYPE_RADIO,
-					  radio_nr)<0) {
+		if (video_register_device(usbvision->rdev, VFL_TYPE_RADIO, radio_nr) < 0)
 			goto err_exit;
-		}
 		printk(KERN_INFO "USBVision[%d]: registered USBVision Radio device %s [v4l2]\n",
 		       usbvision->nr, video_device_node_name(usbvision->rdev));
 	}
-	// all done
+	/* all done */
 	return 0;
 
  err_exit:
@@ -1451,15 +1398,15 @@ static struct usb_usbvision *usbvision_a
 	if (v4l2_device_register(&intf->dev, &usbvision->v4l2_dev))
 		goto err_free;
 
-	mutex_init(&usbvision->lock);	/* available */
+	mutex_init(&usbvision->v4l2_lock);
 
-	// prepare control urb for control messages during interrupts
-	usbvision->ctrlUrb = usb_alloc_urb(USBVISION_URB_FRAMES, GFP_KERNEL);
-	if (usbvision->ctrlUrb == NULL)
+	/* prepare control urb for control messages during interrupts */
+	usbvision->ctrl_urb = usb_alloc_urb(USBVISION_URB_FRAMES, GFP_KERNEL);
+	if (usbvision->ctrl_urb == NULL)
 		goto err_unreg;
-	init_waitqueue_head(&usbvision->ctrlUrb_wq);
+	init_waitqueue_head(&usbvision->ctrl_urb_wq);
 
-	usbvision_init_powerOffTimer(usbvision);
+	usbvision_init_power_off_timer(usbvision);
 
 	return usbvision;
 
@@ -1481,20 +1428,14 @@ static void usbvision_release(struct usb
 {
 	PDEBUG(DBG_PROBE, "");
 
-	mutex_lock(&usbvision->lock);
-
-	usbvision_reset_powerOffTimer(usbvision);
+	usbvision_reset_power_off_timer(usbvision);
 
 	usbvision->initialized = 0;
 
-	mutex_unlock(&usbvision->lock);
-
 	usbvision_remove_sysfs(usbvision->vdev);
 	usbvision_unregister_video(usbvision);
 
-	if (usbvision->ctrlUrb) {
-		usb_free_urb(usbvision->ctrlUrb);
-	}
+	usb_free_urb(usbvision->ctrl_urb);
 
 	v4l2_device_unregister(&usbvision->v4l2_dev);
 	kfree(usbvision);
@@ -1512,25 +1453,25 @@ static void usbvision_configure_video(st
 	if (usbvision == NULL)
 		return;
 
-	model = usbvision->DevModel;
-	usbvision->palette = usbvision_v4l2_format[2]; // V4L2_PIX_FMT_RGB24;
+	model = usbvision->dev_model;
+	usbvision->palette = usbvision_v4l2_format[2]; /* V4L2_PIX_FMT_RGB24; */
 
-	if (usbvision_device_data[usbvision->DevModel].Vin_Reg2_override) {
-		usbvision->Vin_Reg2_Preset =
-			usbvision_device_data[usbvision->DevModel].Vin_Reg2;
+	if (usbvision_device_data[usbvision->dev_model].vin_reg2_override) {
+		usbvision->vin_reg2_preset =
+			usbvision_device_data[usbvision->dev_model].vin_reg2;
 	} else {
-		usbvision->Vin_Reg2_Preset = 0;
+		usbvision->vin_reg2_preset = 0;
 	}
 
-	usbvision->tvnormId = usbvision_device_data[model].VideoNorm;
+	usbvision->tvnorm_id = usbvision_device_data[model].video_norm;
 
-	usbvision->video_inputs = usbvision_device_data[model].VideoChannels;
+	usbvision->video_inputs = usbvision_device_data[model].video_channels;
 	usbvision->ctl_input = 0;
 
 	/* This should be here to make i2c clients to be able to register */
 	/* first switch off audio */
 	usbvision_audio_off(usbvision);
-	if (!PowerOnAtOpen) {
+	if (!power_on_at_open) {
 		/* and then power up the noisy tuner */
 		usbvision_power_on(usbvision);
 		usbvision_i2c_register(usbvision);
@@ -1553,25 +1494,24 @@ static int __devinit usbvision_probe(str
 	const struct usb_host_interface *interface;
 	struct usb_usbvision *usbvision = NULL;
 	const struct usb_endpoint_descriptor *endpoint;
-	int model,i;
+	int model, i;
 
 	PDEBUG(DBG_PROBE, "VID=%#04x, PID=%#04x, ifnum=%u",
 				dev->descriptor.idVendor,
 				dev->descriptor.idProduct, ifnum);
 
 	model = devid->driver_info;
-	if ( (model<0) || (model>=usbvision_device_data_size) ) {
-		PDEBUG(DBG_PROBE, "model out of bounds %d",model);
+	if (model < 0 || model >= usbvision_device_data_size) {
+		PDEBUG(DBG_PROBE, "model out of bounds %d", model);
 		return -ENODEV;
 	}
 	printk(KERN_INFO "%s: %s found\n", __func__,
-				usbvision_device_data[model].ModelString);
+				usbvision_device_data[model].model_string);
 
-	if (usbvision_device_data[model].Interface >= 0) {
-		interface = &dev->actconfig->interface[usbvision_device_data[model].Interface]->altsetting[0];
-	} else {
+	if (usbvision_device_data[model].interface >= 0)
+		interface = &dev->actconfig->interface[usbvision_device_data[model].interface]->altsetting[0];
+	else
 		interface = &dev->actconfig->interface[ifnum]->altsetting[0];
-	}
 	endpoint = &interface->endpoint[1].desc;
 	if (!usb_endpoint_xfer_isoc(endpoint)) {
 		dev_err(&intf->dev, "%s: interface %d. has non-ISO endpoint!\n",
@@ -1592,59 +1532,52 @@ static int __devinit usbvision_probe(str
 		return -ENOMEM;
 	}
 
-	if (dev->descriptor.bNumConfigurations > 1) {
-		usbvision->bridgeType = BRIDGE_NT1004;
-	} else if (model == DAZZLE_DVC_90_REV_1_SECAM) {
-		usbvision->bridgeType = BRIDGE_NT1005;
-	} else {
-		usbvision->bridgeType = BRIDGE_NT1003;
-	}
-	PDEBUG(DBG_PROBE, "bridgeType %d", usbvision->bridgeType);
-
-	mutex_lock(&usbvision->lock);
+	if (dev->descriptor.bNumConfigurations > 1)
+		usbvision->bridge_type = BRIDGE_NT1004;
+	else if (model == DAZZLE_DVC_90_REV_1_SECAM)
+		usbvision->bridge_type = BRIDGE_NT1005;
+	else
+		usbvision->bridge_type = BRIDGE_NT1003;
+	PDEBUG(DBG_PROBE, "bridge_type %d", usbvision->bridge_type);
 
 	/* compute alternate max packet sizes */
 	uif = dev->actconfig->interface[0];
 
-	usbvision->num_alt=uif->num_altsetting;
-	PDEBUG(DBG_PROBE, "Alternate settings: %i",usbvision->num_alt);
-	usbvision->alt_max_pkt_size = kmalloc(32*
-					      usbvision->num_alt,GFP_KERNEL);
+	usbvision->num_alt = uif->num_altsetting;
+	PDEBUG(DBG_PROBE, "Alternate settings: %i", usbvision->num_alt);
+	usbvision->alt_max_pkt_size = kmalloc(32 * usbvision->num_alt, GFP_KERNEL);
 	if (usbvision->alt_max_pkt_size == NULL) {
 		dev_err(&intf->dev, "usbvision: out of memory!\n");
-		mutex_unlock(&usbvision->lock);
 		return -ENOMEM;
 	}
 
-	for (i = 0; i < usbvision->num_alt ; i++) {
+	for (i = 0; i < usbvision->num_alt; i++) {
 		u16 tmp = le16_to_cpu(uif->altsetting[i].endpoint[1].desc.
 				      wMaxPacketSize);
 		usbvision->alt_max_pkt_size[i] =
 			(tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1);
-		PDEBUG(DBG_PROBE, "Alternate setting %i, max size= %i",i,
+		PDEBUG(DBG_PROBE, "Alternate setting %i, max size= %i", i,
 		       usbvision->alt_max_pkt_size[i]);
 	}
 
 
 	usbvision->nr = usbvision_nr++;
 
-	usbvision->have_tuner = usbvision_device_data[model].Tuner;
-	if (usbvision->have_tuner) {
-		usbvision->tuner_type = usbvision_device_data[model].TunerType;
-	}
+	usbvision->have_tuner = usbvision_device_data[model].tuner;
+	if (usbvision->have_tuner)
+		usbvision->tuner_type = usbvision_device_data[model].tuner_type;
 
-	usbvision->DevModel = model;
+	usbvision->dev_model = model;
 	usbvision->remove_pending = 0;
 	usbvision->iface = ifnum;
-	usbvision->ifaceAlt = 0;
+	usbvision->iface_alt = 0;
 	usbvision->video_endp = endpoint->bEndpointAddress;
-	usbvision->isocPacketSize = 0;
+	usbvision->isoc_packet_size = 0;
 	usbvision->usb_bandwidth = 0;
 	usbvision->user = 0;
-	usbvision->streaming = Stream_Off;
+	usbvision->streaming = stream_off;
 	usbvision_configure_video(usbvision);
 	usbvision_register_video(usbvision);
-	mutex_unlock(&usbvision->lock);
 
 	usbvision_create_sysfs(usbvision->vdev);
 
@@ -1672,9 +1605,9 @@ static void __devexit usbvision_disconne
 		return;
 	}
 
-	mutex_lock(&usbvision->lock);
+	mutex_lock(&usbvision->v4l2_lock);
 
-	// At this time we ask to cancel outstanding URBs
+	/* At this time we ask to cancel outstanding URBs */
 	usbvision_stop_isoc(usbvision);
 
 	v4l2_device_disconnect(&usbvision->v4l2_dev);
@@ -1683,12 +1616,12 @@ static void __devexit usbvision_disconne
 		usbvision_i2c_unregister(usbvision);
 		usbvision_power_off(usbvision);
 	}
-	usbvision->remove_pending = 1;	// Now all ISO data will be ignored
+	usbvision->remove_pending = 1;	/* Now all ISO data will be ignored */
 
 	usb_put_dev(usbvision->dev);
-	usbvision->dev = NULL;	// USB device is no more
+	usbvision->dev = NULL;	/* USB device is no more */
 
-	mutex_unlock(&usbvision->lock);
+	mutex_unlock(&usbvision->v4l2_lock);
 
 	if (usbvision->user) {
 		printk(KERN_INFO "%s: In use, disconnect pending\n",
@@ -1717,7 +1650,7 @@ static struct usb_driver usbvision_drive
  */
 static int __init usbvision_init(void)
 {
-	int errCode;
+	int err_code;
 
 	PDEBUG(DBG_PROBE, "");
 
@@ -1726,27 +1659,27 @@ static int __init usbvision_init(void)
 	PDEBUG(DBG_MMAP, "MMAP    debugging is enabled [video]");
 
 	/* disable planar mode support unless compression enabled */
-	if (isocMode != ISOC_MODE_COMPRESS ) {
-		// FIXME : not the right way to set supported flag
-		usbvision_v4l2_format[6].supported = 0; // V4L2_PIX_FMT_YVU420
-		usbvision_v4l2_format[7].supported = 0; // V4L2_PIX_FMT_YUV422P
+	if (isoc_mode != ISOC_MODE_COMPRESS) {
+		/* FIXME : not the right way to set supported flag */
+		usbvision_v4l2_format[6].supported = 0; /* V4L2_PIX_FMT_YVU420 */
+		usbvision_v4l2_format[7].supported = 0; /* V4L2_PIX_FMT_YUV422P */
 	}
 
-	errCode = usb_register(&usbvision_driver);
+	err_code = usb_register(&usbvision_driver);
 
-	if (errCode == 0) {
+	if (err_code == 0) {
 		printk(KERN_INFO DRIVER_DESC " : " USBVISION_VERSION_STRING "\n");
 		PDEBUG(DBG_PROBE, "success");
 	}
-	return errCode;
+	return err_code;
 }
 
 static void __exit usbvision_exit(void)
 {
- PDEBUG(DBG_PROBE, "");
+	PDEBUG(DBG_PROBE, "");
 
- usb_deregister(&usbvision_driver);
- PDEBUG(DBG_PROBE, "success");
+	usb_deregister(&usbvision_driver);
+	PDEBUG(DBG_PROBE, "success");
 }
 
 module_init(usbvision_init);
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/uvc/uvc_v4l2.c linux-libre-2.6.38-gnu1/drivers/media/video/uvc/uvc_v4l2.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/uvc/uvc_v4l2.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/uvc/uvc_v4l2.c	2011-03-14 21:20:32.000000000 -0400
@@ -1035,11 +1035,8 @@ static long uvc_v4l2_do_ioctl(struct fil
 		return uvc_xu_ctrl_query(chain, arg, 1);
 
 	default:
-		if ((ret = v4l_compat_translate_ioctl(file, cmd, arg,
-			uvc_v4l2_do_ioctl)) == -ENOIOCTLCMD)
-			uvc_trace(UVC_TRACE_IOCTL, "Unknown ioctl 0x%08x\n",
-				  cmd);
-		return ret;
+		uvc_trace(UVC_TRACE_IOCTL, "Unknown ioctl 0x%08x\n", cmd);
+		return -EINVAL;
 	}
 
 	return ret;
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/v4l1-compat.c linux-libre-2.6.38-gnu1/drivers/media/video/v4l1-compat.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/v4l1-compat.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/v4l1-compat.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1277 +0,0 @@
-/*
- *
- *	Video for Linux Two
- *	Backward Compatibility Layer
- *
- *	Support subroutines for providing V4L2 drivers with backward
- *	compatibility with applications using the old API.
- *
- *	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.
- *
- * Author:	Bill Dirks <bill@thedirks.org>
- *		et al.
- *
- */
-
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <linux/fs.h>
-#include <linux/file.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
-#include <linux/videodev.h>
-#include <media/v4l2-common.h>
-#include <media/v4l2-ioctl.h>
-
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <asm/pgtable.h>
-
-static unsigned int debug;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "enable debug messages");
-MODULE_AUTHOR("Bill Dirks");
-MODULE_DESCRIPTION("v4l(1) compatibility layer for v4l2 drivers.");
-MODULE_LICENSE("GPL");
-
-#define dprintk(fmt, arg...) \
-	do { \
-		if (debug) \
-			printk(KERN_DEBUG "v4l1-compat: " fmt , ## arg);\
-	} while (0)
-
-/*
- *	I O C T L   T R A N S L A T I O N
- *
- *	From here on down is the code for translating the numerous
- *	ioctl commands from the old API to the new API.
- */
-
-static int
-get_v4l_control(struct file             *file,
-		int			cid,
-		v4l2_kioctl             drv)
-{
-	struct v4l2_queryctrl	qctrl2;
-	struct v4l2_control	ctrl2;
-	int			err;
-
-	qctrl2.id = cid;
-	err = drv(file, VIDIOC_QUERYCTRL, &qctrl2);
-	if (err < 0)
-		dprintk("VIDIOC_QUERYCTRL: %d\n", err);
-	if (err == 0 && !(qctrl2.flags & V4L2_CTRL_FLAG_DISABLED)) {
-		ctrl2.id = qctrl2.id;
-		err = drv(file, VIDIOC_G_CTRL, &ctrl2);
-		if (err < 0) {
-			dprintk("VIDIOC_G_CTRL: %d\n", err);
-			return 0;
-		}
-		return DIV_ROUND_CLOSEST((ctrl2.value-qctrl2.minimum) * 65535,
-					 qctrl2.maximum - qctrl2.minimum);
-	}
-	return 0;
-}
-
-static int
-set_v4l_control(struct file             *file,
-		int			cid,
-		int			value,
-		v4l2_kioctl             drv)
-{
-	struct v4l2_queryctrl	qctrl2;
-	struct v4l2_control	ctrl2;
-	int			err;
-
-	qctrl2.id = cid;
-	err = drv(file, VIDIOC_QUERYCTRL, &qctrl2);
-	if (err < 0)
-		dprintk("VIDIOC_QUERYCTRL: %d\n", err);
-	if (err == 0 &&
-	    !(qctrl2.flags & V4L2_CTRL_FLAG_DISABLED) &&
-	    !(qctrl2.flags & V4L2_CTRL_FLAG_GRABBED)) {
-		if (value < 0)
-			value = 0;
-		if (value > 65535)
-			value = 65535;
-		if (value && qctrl2.type == V4L2_CTRL_TYPE_BOOLEAN)
-			value = 65535;
-		ctrl2.id = qctrl2.id;
-		ctrl2.value =
-			(value * (qctrl2.maximum - qctrl2.minimum)
-			 + 32767)
-			/ 65535;
-		ctrl2.value += qctrl2.minimum;
-		err = drv(file, VIDIOC_S_CTRL, &ctrl2);
-		if (err < 0)
-			dprintk("VIDIOC_S_CTRL: %d\n", err);
-	}
-	return 0;
-}
-
-/* ----------------------------------------------------------------- */
-
-static const unsigned int palette2pixelformat[] = {
-	[VIDEO_PALETTE_GREY]    = V4L2_PIX_FMT_GREY,
-	[VIDEO_PALETTE_RGB555]  = V4L2_PIX_FMT_RGB555,
-	[VIDEO_PALETTE_RGB565]  = V4L2_PIX_FMT_RGB565,
-	[VIDEO_PALETTE_RGB24]   = V4L2_PIX_FMT_BGR24,
-	[VIDEO_PALETTE_RGB32]   = V4L2_PIX_FMT_BGR32,
-	/* yuv packed pixel */
-	[VIDEO_PALETTE_YUYV]    = V4L2_PIX_FMT_YUYV,
-	[VIDEO_PALETTE_YUV422]  = V4L2_PIX_FMT_YUYV,
-	[VIDEO_PALETTE_UYVY]    = V4L2_PIX_FMT_UYVY,
-	/* yuv planar */
-	[VIDEO_PALETTE_YUV410P] = V4L2_PIX_FMT_YUV410,
-	[VIDEO_PALETTE_YUV420]  = V4L2_PIX_FMT_YUV420,
-	[VIDEO_PALETTE_YUV420P] = V4L2_PIX_FMT_YUV420,
-	[VIDEO_PALETTE_YUV411P] = V4L2_PIX_FMT_YUV411P,
-	[VIDEO_PALETTE_YUV422P] = V4L2_PIX_FMT_YUV422P,
-};
-
-static unsigned int __pure
-palette_to_pixelformat(unsigned int palette)
-{
-	if (palette < ARRAY_SIZE(palette2pixelformat))
-		return palette2pixelformat[palette];
-	else
-		return 0;
-}
-
-static unsigned int __attribute_const__
-pixelformat_to_palette(unsigned int pixelformat)
-{
-	int	palette = 0;
-	switch (pixelformat) {
-	case V4L2_PIX_FMT_GREY:
-		palette = VIDEO_PALETTE_GREY;
-		break;
-	case V4L2_PIX_FMT_RGB555:
-		palette = VIDEO_PALETTE_RGB555;
-		break;
-	case V4L2_PIX_FMT_RGB565:
-		palette = VIDEO_PALETTE_RGB565;
-		break;
-	case V4L2_PIX_FMT_BGR24:
-		palette = VIDEO_PALETTE_RGB24;
-		break;
-	case V4L2_PIX_FMT_BGR32:
-		palette = VIDEO_PALETTE_RGB32;
-		break;
-	/* yuv packed pixel */
-	case V4L2_PIX_FMT_YUYV:
-		palette = VIDEO_PALETTE_YUYV;
-		break;
-	case V4L2_PIX_FMT_UYVY:
-		palette = VIDEO_PALETTE_UYVY;
-		break;
-	/* yuv planar */
-	case V4L2_PIX_FMT_YUV410:
-		palette = VIDEO_PALETTE_YUV420;
-		break;
-	case V4L2_PIX_FMT_YUV420:
-		palette = VIDEO_PALETTE_YUV420;
-		break;
-	case V4L2_PIX_FMT_YUV411P:
-		palette = VIDEO_PALETTE_YUV411P;
-		break;
-	case V4L2_PIX_FMT_YUV422P:
-		palette = VIDEO_PALETTE_YUV422P;
-		break;
-	}
-	return palette;
-}
-
-/* ----------------------------------------------------------------- */
-
-static int poll_one(struct file *file, struct poll_wqueues *pwq)
-{
-	int retval = 1;
-	poll_table *table;
-
-	poll_initwait(pwq);
-	table = &pwq->pt;
-	for (;;) {
-		int mask;
-		mask = file->f_op->poll(file, table);
-		if (mask & POLLIN)
-			break;
-		table = NULL;
-		if (signal_pending(current)) {
-			retval = -ERESTARTSYS;
-			break;
-		}
-		poll_schedule(pwq, TASK_INTERRUPTIBLE);
-	}
-	poll_freewait(pwq);
-	return retval;
-}
-
-static int count_inputs(
-			struct file *file,
-			v4l2_kioctl drv)
-{
-	struct v4l2_input input2;
-	int i;
-
-	for (i = 0;; i++) {
-		memset(&input2, 0, sizeof(input2));
-		input2.index = i;
-		if (0 != drv(file, VIDIOC_ENUMINPUT, &input2))
-			break;
-	}
-	return i;
-}
-
-static int check_size(
-		struct file *file,
-		v4l2_kioctl drv,
-		int *maxw,
-		int *maxh)
-{
-	struct v4l2_fmtdesc desc2;
-	struct v4l2_format  fmt2;
-
-	memset(&desc2, 0, sizeof(desc2));
-	memset(&fmt2, 0, sizeof(fmt2));
-
-	desc2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-	if (0 != drv(file, VIDIOC_ENUM_FMT, &desc2))
-		goto done;
-
-	fmt2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-	fmt2.fmt.pix.width       = 10000;
-	fmt2.fmt.pix.height      = 10000;
-	fmt2.fmt.pix.pixelformat = desc2.pixelformat;
-	if (0 != drv(file, VIDIOC_TRY_FMT, &fmt2))
-		goto done;
-
-	*maxw = fmt2.fmt.pix.width;
-	*maxh = fmt2.fmt.pix.height;
-
-done:
-	return 0;
-}
-
-/* ----------------------------------------------------------------- */
-
-static noinline long v4l1_compat_get_capabilities(
-					struct video_capability *cap,
-					struct file *file,
-					v4l2_kioctl drv)
-{
-	long err;
-	struct v4l2_framebuffer fbuf;
-	struct v4l2_capability *cap2;
-
-	cap2 = kzalloc(sizeof(*cap2), GFP_KERNEL);
-	if (!cap2) {
-		err = -ENOMEM;
-		return err;
-	}
-	memset(cap, 0, sizeof(*cap));
-	memset(&fbuf, 0, sizeof(fbuf));
-
-	err = drv(file, VIDIOC_QUERYCAP, cap2);
-	if (err < 0) {
-		dprintk("VIDIOCGCAP / VIDIOC_QUERYCAP: %ld\n", err);
-		goto done;
-	}
-	if (cap2->capabilities & V4L2_CAP_VIDEO_OVERLAY) {
-		err = drv(file, VIDIOC_G_FBUF, &fbuf);
-		if (err < 0) {
-			dprintk("VIDIOCGCAP / VIDIOC_G_FBUF: %ld\n", err);
-			memset(&fbuf, 0, sizeof(fbuf));
-		}
-		err = 0;
-	}
-
-	memcpy(cap->name, cap2->card,
-	       min(sizeof(cap->name), sizeof(cap2->card)));
-	cap->name[sizeof(cap->name) - 1] = 0;
-	if (cap2->capabilities & V4L2_CAP_VIDEO_CAPTURE)
-		cap->type |= VID_TYPE_CAPTURE;
-	if (cap2->capabilities & V4L2_CAP_TUNER)
-		cap->type |= VID_TYPE_TUNER;
-	if (cap2->capabilities & V4L2_CAP_VBI_CAPTURE)
-		cap->type |= VID_TYPE_TELETEXT;
-	if (cap2->capabilities & V4L2_CAP_VIDEO_OVERLAY)
-		cap->type |= VID_TYPE_OVERLAY;
-	if (fbuf.capability & V4L2_FBUF_CAP_LIST_CLIPPING)
-		cap->type |= VID_TYPE_CLIPPING;
-
-	cap->channels  = count_inputs(file, drv);
-	check_size(file, drv,
-		   &cap->maxwidth, &cap->maxheight);
-	cap->audios    =  0; /* FIXME */
-	cap->minwidth  = 48; /* FIXME */
-	cap->minheight = 32; /* FIXME */
-
-done:
-	kfree(cap2);
-	return err;
-}
-
-static noinline long v4l1_compat_get_frame_buffer(
-					struct video_buffer *buffer,
-					struct file *file,
-					v4l2_kioctl drv)
-{
-	long err;
-	struct v4l2_framebuffer fbuf;
-
-	memset(buffer, 0, sizeof(*buffer));
-	memset(&fbuf, 0, sizeof(fbuf));
-
-	err = drv(file, VIDIOC_G_FBUF, &fbuf);
-	if (err < 0) {
-		dprintk("VIDIOCGFBUF / VIDIOC_G_FBUF: %ld\n", err);
-		goto done;
-	}
-	buffer->base   = fbuf.base;
-	buffer->height = fbuf.fmt.height;
-	buffer->width  = fbuf.fmt.width;
-
-	switch (fbuf.fmt.pixelformat) {
-	case V4L2_PIX_FMT_RGB332:
-		buffer->depth = 8;
-		break;
-	case V4L2_PIX_FMT_RGB555:
-		buffer->depth = 15;
-		break;
-	case V4L2_PIX_FMT_RGB565:
-		buffer->depth = 16;
-		break;
-	case V4L2_PIX_FMT_BGR24:
-		buffer->depth = 24;
-		break;
-	case V4L2_PIX_FMT_BGR32:
-		buffer->depth = 32;
-		break;
-	default:
-		buffer->depth = 0;
-	}
-	if (fbuf.fmt.bytesperline) {
-		buffer->bytesperline = fbuf.fmt.bytesperline;
-		if (!buffer->depth && buffer->width)
-			buffer->depth   = ((fbuf.fmt.bytesperline<<3)
-					  + (buffer->width-1))
-					  / buffer->width;
-	} else {
-		buffer->bytesperline =
-			(buffer->width * buffer->depth + 7) & 7;
-		buffer->bytesperline >>= 3;
-	}
-done:
-	return err;
-}
-
-static noinline long v4l1_compat_set_frame_buffer(
-					struct video_buffer *buffer,
-					struct file *file,
-					v4l2_kioctl drv)
-{
-	long err;
-	struct v4l2_framebuffer fbuf;
-
-	memset(&fbuf, 0, sizeof(fbuf));
-	fbuf.base       = buffer->base;
-	fbuf.fmt.height = buffer->height;
-	fbuf.fmt.width  = buffer->width;
-	switch (buffer->depth) {
-	case 8:
-		fbuf.fmt.pixelformat = V4L2_PIX_FMT_RGB332;
-		break;
-	case 15:
-		fbuf.fmt.pixelformat = V4L2_PIX_FMT_RGB555;
-		break;
-	case 16:
-		fbuf.fmt.pixelformat = V4L2_PIX_FMT_RGB565;
-		break;
-	case 24:
-		fbuf.fmt.pixelformat = V4L2_PIX_FMT_BGR24;
-		break;
-	case 32:
-		fbuf.fmt.pixelformat = V4L2_PIX_FMT_BGR32;
-		break;
-	}
-	fbuf.fmt.bytesperline = buffer->bytesperline;
-	err = drv(file, VIDIOC_S_FBUF, &fbuf);
-	if (err < 0)
-		dprintk("VIDIOCSFBUF / VIDIOC_S_FBUF: %ld\n", err);
-	return err;
-}
-
-static noinline long v4l1_compat_get_win_cap_dimensions(
-					struct video_window *win,
-					struct file *file,
-					v4l2_kioctl drv)
-{
-	long err;
-	struct v4l2_format *fmt;
-
-	fmt = kzalloc(sizeof(*fmt), GFP_KERNEL);
-	if (!fmt) {
-		err = -ENOMEM;
-		return err;
-	}
-	memset(win, 0, sizeof(*win));
-
-	fmt->type = V4L2_BUF_TYPE_VIDEO_OVERLAY;
-	err = drv(file, VIDIOC_G_FMT, fmt);
-	if (err < 0)
-		dprintk("VIDIOCGWIN / VIDIOC_G_WIN: %ld\n", err);
-	if (err == 0) {
-		win->x         = fmt->fmt.win.w.left;
-		win->y         = fmt->fmt.win.w.top;
-		win->width     = fmt->fmt.win.w.width;
-		win->height    = fmt->fmt.win.w.height;
-		win->chromakey = fmt->fmt.win.chromakey;
-		win->clips     = NULL;
-		win->clipcount = 0;
-		goto done;
-	}
-
-	fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-	err = drv(file, VIDIOC_G_FMT, fmt);
-	if (err < 0) {
-		dprintk("VIDIOCGWIN / VIDIOC_G_FMT: %ld\n", err);
-		goto done;
-	}
-	win->x         = 0;
-	win->y         = 0;
-	win->width     = fmt->fmt.pix.width;
-	win->height    = fmt->fmt.pix.height;
-	win->chromakey = 0;
-	win->clips     = NULL;
-	win->clipcount = 0;
-done:
-	kfree(fmt);
-	return err;
-}
-
-static noinline long v4l1_compat_set_win_cap_dimensions(
-					struct video_window *win,
-					struct file *file,
-					v4l2_kioctl drv)
-{
-	long err, err1, err2;
-	struct v4l2_format *fmt;
-
-	fmt = kzalloc(sizeof(*fmt), GFP_KERNEL);
-	if (!fmt) {
-		err = -ENOMEM;
-		return err;
-	}
-	fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-	drv(file, VIDIOC_STREAMOFF, &fmt->type);
-	err1 = drv(file, VIDIOC_G_FMT, fmt);
-	if (err1 < 0)
-		dprintk("VIDIOCSWIN / VIDIOC_G_FMT: %ld\n", err1);
-	if (err1 == 0) {
-		fmt->fmt.pix.width  = win->width;
-		fmt->fmt.pix.height = win->height;
-		fmt->fmt.pix.field  = V4L2_FIELD_ANY;
-		fmt->fmt.pix.bytesperline = 0;
-		err = drv(file, VIDIOC_S_FMT, fmt);
-		if (err < 0)
-			dprintk("VIDIOCSWIN / VIDIOC_S_FMT #1: %ld\n",
-				err);
-		win->width  = fmt->fmt.pix.width;
-		win->height = fmt->fmt.pix.height;
-	}
-
-	memset(fmt, 0, sizeof(*fmt));
-	fmt->type = V4L2_BUF_TYPE_VIDEO_OVERLAY;
-	fmt->fmt.win.w.left    = win->x;
-	fmt->fmt.win.w.top     = win->y;
-	fmt->fmt.win.w.width   = win->width;
-	fmt->fmt.win.w.height  = win->height;
-	fmt->fmt.win.chromakey = win->chromakey;
-	fmt->fmt.win.clips     = (void __user *)win->clips;
-	fmt->fmt.win.clipcount = win->clipcount;
-	err2 = drv(file, VIDIOC_S_FMT, fmt);
-	if (err2 < 0)
-		dprintk("VIDIOCSWIN / VIDIOC_S_FMT #2: %ld\n", err2);
-
-	if (err1 != 0 && err2 != 0)
-		err = err1;
-	else
-		err = 0;
-	kfree(fmt);
-	return err;
-}
-
-static noinline long v4l1_compat_turn_preview_on_off(
-					int *on,
-					struct file *file,
-					v4l2_kioctl drv)
-{
-	long err;
-	enum v4l2_buf_type captype = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-
-	if (0 == *on) {
-		/* dirty hack time.  But v4l1 has no STREAMOFF
-		 * equivalent in the API, and this one at
-		 * least comes close ... */
-		drv(file, VIDIOC_STREAMOFF, &captype);
-	}
-	err = drv(file, VIDIOC_OVERLAY, on);
-	if (err < 0)
-		dprintk("VIDIOCCAPTURE / VIDIOC_PREVIEW: %ld\n", err);
-	return err;
-}
-
-static noinline long v4l1_compat_get_input_info(
-					struct video_channel *chan,
-					struct file *file,
-					v4l2_kioctl drv)
-{
-	long err;
-	struct v4l2_input	input2;
-	v4l2_std_id    		sid;
-
-	memset(&input2, 0, sizeof(input2));
-	input2.index = chan->channel;
-	err = drv(file, VIDIOC_ENUMINPUT, &input2);
-	if (err < 0) {
-		dprintk("VIDIOCGCHAN / VIDIOC_ENUMINPUT: "
-			"channel=%d err=%ld\n", chan->channel, err);
-		goto done;
-	}
-	chan->channel = input2.index;
-	memcpy(chan->name, input2.name,
-	       min(sizeof(chan->name), sizeof(input2.name)));
-	chan->name[sizeof(chan->name) - 1] = 0;
-	chan->tuners = (input2.type == V4L2_INPUT_TYPE_TUNER) ? 1 : 0;
-	chan->flags = (chan->tuners) ? VIDEO_VC_TUNER : 0;
-	switch (input2.type) {
-	case V4L2_INPUT_TYPE_TUNER:
-		chan->type = VIDEO_TYPE_TV;
-		break;
-	default:
-	case V4L2_INPUT_TYPE_CAMERA:
-		chan->type = VIDEO_TYPE_CAMERA;
-		break;
-	}
-	chan->norm = 0;
-	/* Note: G_STD might not be present for radio receivers,
-	 * so we should ignore any errors. */
-	if (drv(file, VIDIOC_G_STD, &sid) == 0) {
-		if (sid & V4L2_STD_PAL)
-			chan->norm = VIDEO_MODE_PAL;
-		if (sid & V4L2_STD_NTSC)
-			chan->norm = VIDEO_MODE_NTSC;
-		if (sid & V4L2_STD_SECAM)
-			chan->norm = VIDEO_MODE_SECAM;
-		if (sid == V4L2_STD_ALL)
-			chan->norm = VIDEO_MODE_AUTO;
-	}
-done:
-	return err;
-}
-
-static noinline long v4l1_compat_set_input(
-					struct video_channel *chan,
-					struct file *file,
-					v4l2_kioctl drv)
-{
-	long err;
-	v4l2_std_id sid = 0;
-
-	err = drv(file, VIDIOC_S_INPUT, &chan->channel);
-	if (err < 0)
-		dprintk("VIDIOCSCHAN / VIDIOC_S_INPUT: %ld\n", err);
-	switch (chan->norm) {
-	case VIDEO_MODE_PAL:
-		sid = V4L2_STD_PAL;
-		break;
-	case VIDEO_MODE_NTSC:
-		sid = V4L2_STD_NTSC;
-		break;
-	case VIDEO_MODE_SECAM:
-		sid = V4L2_STD_SECAM;
-		break;
-	case VIDEO_MODE_AUTO:
-		sid = V4L2_STD_ALL;
-		break;
-	}
-	if (0 != sid) {
-		err = drv(file, VIDIOC_S_STD, &sid);
-		if (err < 0)
-			dprintk("VIDIOCSCHAN / VIDIOC_S_STD: %ld\n", err);
-	}
-	return err;
-}
-
-static noinline long v4l1_compat_get_picture(
-					struct video_picture *pict,
-					struct file *file,
-					v4l2_kioctl drv)
-{
-	long err;
-	struct v4l2_format *fmt;
-
-	fmt = kzalloc(sizeof(*fmt), GFP_KERNEL);
-	if (!fmt) {
-		err = -ENOMEM;
-		return err;
-	}
-
-	pict->brightness = get_v4l_control(file,
-					   V4L2_CID_BRIGHTNESS, drv);
-	pict->hue = get_v4l_control(file,
-				    V4L2_CID_HUE, drv);
-	pict->contrast = get_v4l_control(file,
-					 V4L2_CID_CONTRAST, drv);
-	pict->colour = get_v4l_control(file,
-				       V4L2_CID_SATURATION, drv);
-	pict->whiteness = get_v4l_control(file,
-					  V4L2_CID_WHITENESS, drv);
-
-	fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-	err = drv(file, VIDIOC_G_FMT, fmt);
-	if (err < 0) {
-		dprintk("VIDIOCGPICT / VIDIOC_G_FMT: %ld\n", err);
-		goto done;
-	}
-
-	if (fmt->fmt.pix.width)
-	{
-		pict->depth   = ((fmt->fmt.pix.bytesperline << 3)
-				 + (fmt->fmt.pix.width - 1))
-				 / fmt->fmt.pix.width;
-	} else {
-		err = -EINVAL;
-		goto done;
-	}
-
-	pict->palette = pixelformat_to_palette(
-		fmt->fmt.pix.pixelformat);
-done:
-	kfree(fmt);
-	return err;
-}
-
-static noinline long v4l1_compat_set_picture(
-					struct video_picture *pict,
-					struct file *file,
-					v4l2_kioctl drv)
-{
-	long err;
-	struct v4l2_framebuffer fbuf;
-	int mem_err = 0, ovl_err = 0;
-	struct v4l2_format *fmt;
-
-	fmt = kzalloc(sizeof(*fmt), GFP_KERNEL);
-	if (!fmt) {
-		err = -ENOMEM;
-		return err;
-	}
-	memset(&fbuf, 0, sizeof(fbuf));
-
-	set_v4l_control(file,
-			V4L2_CID_BRIGHTNESS, pict->brightness, drv);
-	set_v4l_control(file,
-			V4L2_CID_HUE, pict->hue, drv);
-	set_v4l_control(file,
-			V4L2_CID_CONTRAST, pict->contrast, drv);
-	set_v4l_control(file,
-			V4L2_CID_SATURATION, pict->colour, drv);
-	set_v4l_control(file,
-			V4L2_CID_WHITENESS, pict->whiteness, drv);
-	/*
-	 * V4L1 uses this ioctl to set both memory capture and overlay
-	 * pixel format, while V4L2 has two different ioctls for this.
-	 * Some cards may not support one or the other, and may support
-	 * different pixel formats for memory vs overlay.
-	 */
-
-	fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-	err = drv(file, VIDIOC_G_FMT, fmt);
-	/* If VIDIOC_G_FMT failed, then the driver likely doesn't
-	   support memory capture.  Trying to set the memory capture
-	   parameters would be pointless.  */
-	if (err < 0) {
-		dprintk("VIDIOCSPICT / VIDIOC_G_FMT: %ld\n", err);
-		mem_err = -1000;  /* didn't even try */
-	} else if (fmt->fmt.pix.pixelformat !=
-		 palette_to_pixelformat(pict->palette)) {
-		fmt->fmt.pix.pixelformat = palette_to_pixelformat(
-			pict->palette);
-		mem_err = drv(file, VIDIOC_S_FMT, fmt);
-		if (mem_err < 0)
-			dprintk("VIDIOCSPICT / VIDIOC_S_FMT: %d\n",
-				mem_err);
-	}
-
-	err = drv(file, VIDIOC_G_FBUF, &fbuf);
-	/* If VIDIOC_G_FBUF failed, then the driver likely doesn't
-	   support overlay.  Trying to set the overlay parameters
-	   would be quite pointless.  */
-	if (err < 0) {
-		dprintk("VIDIOCSPICT / VIDIOC_G_FBUF: %ld\n", err);
-		ovl_err = -1000;  /* didn't even try */
-	} else if (fbuf.fmt.pixelformat !=
-		 palette_to_pixelformat(pict->palette)) {
-		fbuf.fmt.pixelformat = palette_to_pixelformat(
-			pict->palette);
-		ovl_err = drv(file, VIDIOC_S_FBUF, &fbuf);
-		if (ovl_err < 0)
-			dprintk("VIDIOCSPICT / VIDIOC_S_FBUF: %d\n",
-				ovl_err);
-	}
-	if (ovl_err < 0 && mem_err < 0) {
-		/* ioctl failed, couldn't set either parameter */
-		if (mem_err != -1000)
-			err = mem_err;
-		else if (ovl_err == -EPERM)
-			err = 0;
-		else
-			err = ovl_err;
-	} else
-		err = 0;
-	kfree(fmt);
-	return err;
-}
-
-static noinline long v4l1_compat_get_tuner(
-					struct video_tuner *tun,
-					struct file *file,
-					v4l2_kioctl drv)
-{
-	long err;
-	int i;
-	struct v4l2_tuner	tun2;
-	struct v4l2_standard	std2;
-	v4l2_std_id    		sid;
-
-	memset(&tun2, 0, sizeof(tun2));
-	err = drv(file, VIDIOC_G_TUNER, &tun2);
-	if (err < 0) {
-		dprintk("VIDIOCGTUNER / VIDIOC_G_TUNER: %ld\n", err);
-		goto done;
-	}
-	memcpy(tun->name, tun2.name,
-	       min(sizeof(tun->name), sizeof(tun2.name)));
-	tun->name[sizeof(tun->name) - 1] = 0;
-	tun->rangelow = tun2.rangelow;
-	tun->rangehigh = tun2.rangehigh;
-	tun->flags = 0;
-	tun->mode = VIDEO_MODE_AUTO;
-
-	for (i = 0; i < 64; i++) {
-		memset(&std2, 0, sizeof(std2));
-		std2.index = i;
-		if (0 != drv(file, VIDIOC_ENUMSTD, &std2))
-			break;
-		if (std2.id & V4L2_STD_PAL)
-			tun->flags |= VIDEO_TUNER_PAL;
-		if (std2.id & V4L2_STD_NTSC)
-			tun->flags |= VIDEO_TUNER_NTSC;
-		if (std2.id & V4L2_STD_SECAM)
-			tun->flags |= VIDEO_TUNER_SECAM;
-	}
-
-	/* Note: G_STD might not be present for radio receivers,
-	 * so we should ignore any errors. */
-	if (drv(file, VIDIOC_G_STD, &sid) == 0) {
-		if (sid & V4L2_STD_PAL)
-			tun->mode = VIDEO_MODE_PAL;
-		if (sid & V4L2_STD_NTSC)
-			tun->mode = VIDEO_MODE_NTSC;
-		if (sid & V4L2_STD_SECAM)
-			tun->mode = VIDEO_MODE_SECAM;
-	}
-
-	if (tun2.capability & V4L2_TUNER_CAP_LOW)
-		tun->flags |= VIDEO_TUNER_LOW;
-	if (tun2.rxsubchans & V4L2_TUNER_SUB_STEREO)
-		tun->flags |= VIDEO_TUNER_STEREO_ON;
-	tun->signal = tun2.signal;
-done:
-	return err;
-}
-
-static noinline long v4l1_compat_select_tuner(
-					struct video_tuner *tun,
-					struct file *file,
-					v4l2_kioctl drv)
-{
-	long err;
-	struct v4l2_tuner	t;/*84 bytes on x86_64*/
-	memset(&t, 0, sizeof(t));
-
-	t.index = tun->tuner;
-
-	err = drv(file, VIDIOC_S_TUNER, &t);
-	if (err < 0)
-		dprintk("VIDIOCSTUNER / VIDIOC_S_TUNER: %ld\n", err);
-	return err;
-}
-
-static noinline long v4l1_compat_get_frequency(
-					unsigned long *freq,
-					struct file *file,
-					v4l2_kioctl drv)
-{
-	long err;
-	struct v4l2_frequency   freq2;
-	memset(&freq2, 0, sizeof(freq2));
-
-	freq2.tuner = 0;
-	err = drv(file, VIDIOC_G_FREQUENCY, &freq2);
-	if (err < 0)
-		dprintk("VIDIOCGFREQ / VIDIOC_G_FREQUENCY: %ld\n", err);
-	if (0 == err)
-		*freq = freq2.frequency;
-	return err;
-}
-
-static noinline long v4l1_compat_set_frequency(
-					unsigned long *freq,
-					struct file *file,
-					v4l2_kioctl drv)
-{
-	long err;
-	struct v4l2_frequency   freq2;
-	memset(&freq2, 0, sizeof(freq2));
-
-	drv(file, VIDIOC_G_FREQUENCY, &freq2);
-	freq2.frequency = *freq;
-	err = drv(file, VIDIOC_S_FREQUENCY, &freq2);
-	if (err < 0)
-		dprintk("VIDIOCSFREQ / VIDIOC_S_FREQUENCY: %ld\n", err);
-	return err;
-}
-
-static noinline long v4l1_compat_get_audio(
-					struct video_audio *aud,
-					struct file *file,
-					v4l2_kioctl drv)
-{
-	long err;
-	int i;
-	struct v4l2_queryctrl	qctrl2;
-	struct v4l2_audio	aud2;
-	struct v4l2_tuner	tun2;
-	memset(&aud2, 0, sizeof(aud2));
-
-	err = drv(file, VIDIOC_G_AUDIO, &aud2);
-	if (err < 0) {
-		dprintk("VIDIOCGAUDIO / VIDIOC_G_AUDIO: %ld\n", err);
-		goto done;
-	}
-	memcpy(aud->name, aud2.name,
-	       min(sizeof(aud->name), sizeof(aud2.name)));
-	aud->name[sizeof(aud->name) - 1] = 0;
-	aud->audio = aud2.index;
-	aud->flags = 0;
-	i = get_v4l_control(file, V4L2_CID_AUDIO_VOLUME, drv);
-	if (i >= 0) {
-		aud->volume = i;
-		aud->flags |= VIDEO_AUDIO_VOLUME;
-	}
-	i = get_v4l_control(file, V4L2_CID_AUDIO_BASS, drv);
-	if (i >= 0) {
-		aud->bass = i;
-		aud->flags |= VIDEO_AUDIO_BASS;
-	}
-	i = get_v4l_control(file, V4L2_CID_AUDIO_TREBLE, drv);
-	if (i >= 0) {
-		aud->treble = i;
-		aud->flags |= VIDEO_AUDIO_TREBLE;
-	}
-	i = get_v4l_control(file, V4L2_CID_AUDIO_BALANCE, drv);
-	if (i >= 0) {
-		aud->balance = i;
-		aud->flags |= VIDEO_AUDIO_BALANCE;
-	}
-	i = get_v4l_control(file, V4L2_CID_AUDIO_MUTE, drv);
-	if (i >= 0) {
-		if (i)
-			aud->flags |= VIDEO_AUDIO_MUTE;
-		aud->flags |= VIDEO_AUDIO_MUTABLE;
-	}
-	aud->step = 1;
-	qctrl2.id = V4L2_CID_AUDIO_VOLUME;
-	if (drv(file, VIDIOC_QUERYCTRL, &qctrl2) == 0 &&
-	    !(qctrl2.flags & V4L2_CTRL_FLAG_DISABLED))
-		aud->step = qctrl2.step;
-	aud->mode = 0;
-
-	memset(&tun2, 0, sizeof(tun2));
-	err = drv(file, VIDIOC_G_TUNER, &tun2);
-	if (err < 0) {
-		dprintk("VIDIOCGAUDIO / VIDIOC_G_TUNER: %ld\n", err);
-		err = 0;
-		goto done;
-	}
-
-	if (tun2.rxsubchans & V4L2_TUNER_SUB_LANG2)
-		aud->mode = VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2;
-	else if (tun2.rxsubchans & V4L2_TUNER_SUB_STEREO)
-		aud->mode = VIDEO_SOUND_STEREO;
-	else if (tun2.rxsubchans & V4L2_TUNER_SUB_MONO)
-		aud->mode = VIDEO_SOUND_MONO;
-done:
-	return err;
-}
-
-static noinline long v4l1_compat_set_audio(
-					struct video_audio *aud,
-					struct file *file,
-					v4l2_kioctl drv)
-{
-	long err;
-	struct v4l2_audio	aud2;
-	struct v4l2_tuner	tun2;
-
-	memset(&aud2, 0, sizeof(aud2));
-	memset(&tun2, 0, sizeof(tun2));
-
-	aud2.index = aud->audio;
-	err = drv(file, VIDIOC_S_AUDIO, &aud2);
-	if (err < 0) {
-		dprintk("VIDIOCSAUDIO / VIDIOC_S_AUDIO: %ld\n", err);
-		goto done;
-	}
-
-	set_v4l_control(file, V4L2_CID_AUDIO_VOLUME,
-			aud->volume, drv);
-	set_v4l_control(file, V4L2_CID_AUDIO_BASS,
-			aud->bass, drv);
-	set_v4l_control(file, V4L2_CID_AUDIO_TREBLE,
-			aud->treble, drv);
-	set_v4l_control(file, V4L2_CID_AUDIO_BALANCE,
-			aud->balance, drv);
-	set_v4l_control(file, V4L2_CID_AUDIO_MUTE,
-			!!(aud->flags & VIDEO_AUDIO_MUTE), drv);
-
-	err = drv(file, VIDIOC_G_TUNER, &tun2);
-	if (err < 0)
-		dprintk("VIDIOCSAUDIO / VIDIOC_G_TUNER: %ld\n", err);
-	if (err == 0) {
-		switch (aud->mode) {
-		default:
-		case VIDEO_SOUND_MONO:
-		case VIDEO_SOUND_LANG1:
-			tun2.audmode = V4L2_TUNER_MODE_MONO;
-			break;
-		case VIDEO_SOUND_STEREO:
-			tun2.audmode = V4L2_TUNER_MODE_STEREO;
-			break;
-		case VIDEO_SOUND_LANG2:
-			tun2.audmode = V4L2_TUNER_MODE_LANG2;
-			break;
-		}
-		err = drv(file, VIDIOC_S_TUNER, &tun2);
-		if (err < 0)
-			dprintk("VIDIOCSAUDIO / VIDIOC_S_TUNER: %ld\n", err);
-	}
-	err = 0;
-done:
-	return err;
-}
-
-static noinline long v4l1_compat_capture_frame(
-					struct video_mmap *mm,
-					struct file *file,
-					v4l2_kioctl drv)
-{
-	long err;
-	enum v4l2_buf_type      captype = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-	struct v4l2_buffer	buf;
-	struct v4l2_format	*fmt;
-
-	fmt = kzalloc(sizeof(*fmt), GFP_KERNEL);
-	if (!fmt) {
-		err = -ENOMEM;
-		return err;
-	}
-	memset(&buf, 0, sizeof(buf));
-
-	fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-	err = drv(file, VIDIOC_G_FMT, fmt);
-	if (err < 0) {
-		dprintk("VIDIOCMCAPTURE / VIDIOC_G_FMT: %ld\n", err);
-		goto done;
-	}
-	if (mm->width   != fmt->fmt.pix.width  ||
-	    mm->height  != fmt->fmt.pix.height ||
-	    palette_to_pixelformat(mm->format) !=
-	    fmt->fmt.pix.pixelformat) {
-		/* New capture format...  */
-		fmt->fmt.pix.width = mm->width;
-		fmt->fmt.pix.height = mm->height;
-		fmt->fmt.pix.pixelformat =
-			palette_to_pixelformat(mm->format);
-		fmt->fmt.pix.field = V4L2_FIELD_ANY;
-		fmt->fmt.pix.bytesperline = 0;
-		err = drv(file, VIDIOC_S_FMT, fmt);
-		if (err < 0) {
-			dprintk("VIDIOCMCAPTURE / VIDIOC_S_FMT: %ld\n", err);
-			goto done;
-		}
-	}
-	buf.index = mm->frame;
-	buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-	err = drv(file, VIDIOC_QUERYBUF, &buf);
-	if (err < 0) {
-		dprintk("VIDIOCMCAPTURE / VIDIOC_QUERYBUF: %ld\n", err);
-		goto done;
-	}
-	err = drv(file, VIDIOC_QBUF, &buf);
-	if (err < 0) {
-		dprintk("VIDIOCMCAPTURE / VIDIOC_QBUF: %ld\n", err);
-		goto done;
-	}
-	err = drv(file, VIDIOC_STREAMON, &captype);
-	if (err < 0)
-		dprintk("VIDIOCMCAPTURE / VIDIOC_STREAMON: %ld\n", err);
-done:
-	kfree(fmt);
-	return err;
-}
-
-static noinline long v4l1_compat_sync(
-				int *i,
-				struct file *file,
-				v4l2_kioctl drv)
-{
-	long err;
-	enum v4l2_buf_type captype = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-	struct v4l2_buffer buf;
-	struct poll_wqueues *pwq;
-
-	memset(&buf, 0, sizeof(buf));
-	buf.index = *i;
-	buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-	err = drv(file, VIDIOC_QUERYBUF, &buf);
-	if (err < 0) {
-		/*  No such buffer */
-		dprintk("VIDIOCSYNC / VIDIOC_QUERYBUF: %ld\n", err);
-		goto done;
-	}
-	if (!(buf.flags & V4L2_BUF_FLAG_MAPPED)) {
-		/* Buffer is not mapped  */
-		err = -EINVAL;
-		goto done;
-	}
-
-	/* make sure capture actually runs so we don't block forever */
-	err = drv(file, VIDIOC_STREAMON, &captype);
-	if (err < 0) {
-		dprintk("VIDIOCSYNC / VIDIOC_STREAMON: %ld\n", err);
-		goto done;
-	}
-
-	pwq = kmalloc(sizeof(*pwq), GFP_KERNEL);
-	/*  Loop as long as the buffer is queued, but not done  */
-	while ((buf.flags & (V4L2_BUF_FLAG_QUEUED | V4L2_BUF_FLAG_DONE))
-						== V4L2_BUF_FLAG_QUEUED) {
-		err = poll_one(file, pwq);
-		if (err < 0 ||	/* error or sleep was interrupted  */
-		    err == 0)	/* timeout? Shouldn't occur.  */
-			break;
-		err = drv(file, VIDIOC_QUERYBUF, &buf);
-		if (err < 0)
-			dprintk("VIDIOCSYNC / VIDIOC_QUERYBUF: %ld\n", err);
-	}
-	kfree(pwq);
-	if (!(buf.flags & V4L2_BUF_FLAG_DONE)) /* not done */
-		goto done;
-	do {
-		err = drv(file, VIDIOC_DQBUF, &buf);
-		if (err < 0)
-			dprintk("VIDIOCSYNC / VIDIOC_DQBUF: %ld\n", err);
-	} while (err == 0 && buf.index != *i);
-done:
-	return err;
-}
-
-static noinline long v4l1_compat_get_vbi_format(
-				struct vbi_format *fmt,
-				struct file *file,
-				v4l2_kioctl drv)
-{
-	long err;
-	struct v4l2_format *fmt2;
-
-	fmt2 = kzalloc(sizeof(*fmt2), GFP_KERNEL);
-	if (!fmt2) {
-		err = -ENOMEM;
-		return err;
-	}
-	fmt2->type = V4L2_BUF_TYPE_VBI_CAPTURE;
-
-	err = drv(file, VIDIOC_G_FMT, fmt2);
-	if (err < 0) {
-		dprintk("VIDIOCGVBIFMT / VIDIOC_G_FMT: %ld\n", err);
-		goto done;
-	}
-	if (fmt2->fmt.vbi.sample_format != V4L2_PIX_FMT_GREY) {
-		err = -EINVAL;
-		goto done;
-	}
-	memset(fmt, 0, sizeof(*fmt));
-	fmt->samples_per_line = fmt2->fmt.vbi.samples_per_line;
-	fmt->sampling_rate    = fmt2->fmt.vbi.sampling_rate;
-	fmt->sample_format    = VIDEO_PALETTE_RAW;
-	fmt->start[0]         = fmt2->fmt.vbi.start[0];
-	fmt->count[0]         = fmt2->fmt.vbi.count[0];
-	fmt->start[1]         = fmt2->fmt.vbi.start[1];
-	fmt->count[1]         = fmt2->fmt.vbi.count[1];
-	fmt->flags            = fmt2->fmt.vbi.flags & 0x03;
-done:
-	kfree(fmt2);
-	return err;
-}
-
-static noinline long v4l1_compat_set_vbi_format(
-				struct vbi_format *fmt,
-				struct file *file,
-				v4l2_kioctl drv)
-{
-	long err;
-	struct v4l2_format	*fmt2 = NULL;
-
-	if (VIDEO_PALETTE_RAW != fmt->sample_format) {
-		err = -EINVAL;
-		return err;
-	}
-
-	fmt2 = kzalloc(sizeof(*fmt2), GFP_KERNEL);
-	if (!fmt2) {
-		err = -ENOMEM;
-		return err;
-	}
-	fmt2->type = V4L2_BUF_TYPE_VBI_CAPTURE;
-	fmt2->fmt.vbi.samples_per_line = fmt->samples_per_line;
-	fmt2->fmt.vbi.sampling_rate    = fmt->sampling_rate;
-	fmt2->fmt.vbi.sample_format    = V4L2_PIX_FMT_GREY;
-	fmt2->fmt.vbi.start[0]         = fmt->start[0];
-	fmt2->fmt.vbi.count[0]         = fmt->count[0];
-	fmt2->fmt.vbi.start[1]         = fmt->start[1];
-	fmt2->fmt.vbi.count[1]         = fmt->count[1];
-	fmt2->fmt.vbi.flags            = fmt->flags;
-	err = drv(file, VIDIOC_TRY_FMT, fmt2);
-	if (err < 0) {
-		dprintk("VIDIOCSVBIFMT / VIDIOC_TRY_FMT: %ld\n", err);
-		goto done;
-	}
-
-	if (fmt2->fmt.vbi.samples_per_line != fmt->samples_per_line ||
-	    fmt2->fmt.vbi.sampling_rate    != fmt->sampling_rate    ||
-	    fmt2->fmt.vbi.sample_format    != V4L2_PIX_FMT_GREY     ||
-	    fmt2->fmt.vbi.start[0]         != fmt->start[0]         ||
-	    fmt2->fmt.vbi.count[0]         != fmt->count[0]         ||
-	    fmt2->fmt.vbi.start[1]         != fmt->start[1]         ||
-	    fmt2->fmt.vbi.count[1]         != fmt->count[1]         ||
-	    fmt2->fmt.vbi.flags            != fmt->flags) {
-		err = -EINVAL;
-		goto done;
-	}
-	err = drv(file, VIDIOC_S_FMT, fmt2);
-	if (err < 0)
-		dprintk("VIDIOCSVBIFMT / VIDIOC_S_FMT: %ld\n", err);
-done:
-	kfree(fmt2);
-	return err;
-}
-
-/*
- *	This function is exported.
- */
-long
-v4l_compat_translate_ioctl(struct file		*file,
-			   int			cmd,
-			   void			*arg,
-			   v4l2_kioctl          drv)
-{
-	long err;
-
-	switch (cmd) {
-	case VIDIOCGCAP:	/* capability */
-		err = v4l1_compat_get_capabilities(arg, file, drv);
-		break;
-	case VIDIOCGFBUF: /*  get frame buffer  */
-		err = v4l1_compat_get_frame_buffer(arg, file, drv);
-		break;
-	case VIDIOCSFBUF: /*  set frame buffer  */
-		err = v4l1_compat_set_frame_buffer(arg, file, drv);
-		break;
-	case VIDIOCGWIN: /*  get window or capture dimensions  */
-		err = v4l1_compat_get_win_cap_dimensions(arg, file, drv);
-		break;
-	case VIDIOCSWIN: /*  set window and/or capture dimensions  */
-		err = v4l1_compat_set_win_cap_dimensions(arg, file, drv);
-		break;
-	case VIDIOCCAPTURE: /*  turn on/off preview  */
-		err = v4l1_compat_turn_preview_on_off(arg, file, drv);
-		break;
-	case VIDIOCGCHAN: /*  get input information  */
-		err = v4l1_compat_get_input_info(arg, file, drv);
-		break;
-	case VIDIOCSCHAN: /*  set input  */
-		err = v4l1_compat_set_input(arg, file, drv);
-		break;
-	case VIDIOCGPICT: /*  get tone controls & partial capture format  */
-		err = v4l1_compat_get_picture(arg, file, drv);
-		break;
-	case VIDIOCSPICT: /*  set tone controls & partial capture format  */
-		err = v4l1_compat_set_picture(arg, file, drv);
-		break;
-	case VIDIOCGTUNER: /*  get tuner information  */
-		err = v4l1_compat_get_tuner(arg, file, drv);
-		break;
-	case VIDIOCSTUNER: /*  select a tuner input  */
-		err = v4l1_compat_select_tuner(arg, file, drv);
-		break;
-	case VIDIOCGFREQ: /*  get frequency  */
-		err = v4l1_compat_get_frequency(arg, file, drv);
-		break;
-	case VIDIOCSFREQ: /*  set frequency  */
-		err = v4l1_compat_set_frequency(arg, file, drv);
-		break;
-	case VIDIOCGAUDIO: /*  get audio properties/controls  */
-		err = v4l1_compat_get_audio(arg, file, drv);
-		break;
-	case VIDIOCSAUDIO: /*  set audio controls  */
-		err = v4l1_compat_set_audio(arg, file, drv);
-		break;
-	case VIDIOCMCAPTURE: /*  capture a frame  */
-		err = v4l1_compat_capture_frame(arg, file, drv);
-		break;
-	case VIDIOCSYNC: /*  wait for a frame  */
-		err = v4l1_compat_sync(arg, file, drv);
-		break;
-	case VIDIOCGVBIFMT: /* query VBI data capture format */
-		err = v4l1_compat_get_vbi_format(arg, file, drv);
-		break;
-	case VIDIOCSVBIFMT:
-		err = v4l1_compat_set_vbi_format(arg, file, drv);
-		break;
-	default:
-		err = -ENOIOCTLCMD;
-		break;
-	}
-
-	return err;
-}
-EXPORT_SYMBOL(v4l_compat_translate_ioctl);
-
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/v4l2-common.c linux-libre-2.6.38-gnu1/drivers/media/video/v4l2-common.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/v4l2-common.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/v4l2-common.c	2011-03-14 21:20:32.000000000 -0400
@@ -150,7 +150,7 @@ EXPORT_SYMBOL(v4l2_prio_check);
    struct v4l2_queryctrl and the available menu items. Note that
    menu_items may be NULL, in that case it is ignored. */
 int v4l2_ctrl_check(struct v4l2_ext_control *ctrl, struct v4l2_queryctrl *qctrl,
-		const char **menu_items)
+		const char * const *menu_items)
 {
 	if (qctrl->flags & V4L2_CTRL_FLAG_DISABLED)
 		return -EINVAL;
@@ -199,7 +199,7 @@ EXPORT_SYMBOL(v4l2_ctrl_query_fill);
    If menu_items is NULL, then the menu items are retrieved using
    v4l2_ctrl_get_menu. */
 int v4l2_ctrl_query_menu(struct v4l2_querymenu *qmenu, struct v4l2_queryctrl *qctrl,
-	       const char **menu_items)
+	       const char * const *menu_items)
 {
 	int i;
 
@@ -222,7 +222,7 @@ EXPORT_SYMBOL(v4l2_ctrl_query_menu);
    Use this if there are 'holes' in the list of valid menu items. */
 int v4l2_ctrl_query_menu_valid_items(struct v4l2_querymenu *qmenu, const u32 *ids)
 {
-	const char **menu_items = v4l2_ctrl_get_menu(qmenu->id);
+	const char * const *menu_items = v4l2_ctrl_get_menu(qmenu->id);
 
 	qmenu->reserved = 0;
 	if (menu_items == NULL || ids == NULL)
@@ -407,18 +407,6 @@ struct v4l2_subdev *v4l2_i2c_new_subdev_
 	/* Decrease the module use count to match the first try_module_get. */
 	module_put(client->driver->driver.owner);
 
-	if (sd) {
-		/* We return errors from v4l2_subdev_call only if we have the
-		   callback as the .s_config is not mandatory */
-		int err = v4l2_subdev_call(sd, core, s_config,
-				info->irq, info->platform_data);
-
-		if (err && err != -ENOIOCTLCMD) {
-			v4l2_device_unregister_subdev(sd);
-			sd = NULL;
-		}
-	}
-
 error:
 	/* If we have a client but no subdev, then something went wrong and
 	   we must unregister the client. */
@@ -428,9 +416,8 @@ error:
 }
 EXPORT_SYMBOL_GPL(v4l2_i2c_new_subdev_board);
 
-struct v4l2_subdev *v4l2_i2c_new_subdev_cfg(struct v4l2_device *v4l2_dev,
+struct v4l2_subdev *v4l2_i2c_new_subdev(struct v4l2_device *v4l2_dev,
 		struct i2c_adapter *adapter, const char *client_type,
-		int irq, void *platform_data,
 		u8 addr, const unsigned short *probe_addrs)
 {
 	struct i2c_board_info info;
@@ -440,12 +427,10 @@ struct v4l2_subdev *v4l2_i2c_new_subdev_
 	memset(&info, 0, sizeof(info));
 	strlcpy(info.type, client_type, sizeof(info.type));
 	info.addr = addr;
-	info.irq = irq;
-	info.platform_data = platform_data;
 
 	return v4l2_i2c_new_subdev_board(v4l2_dev, adapter, &info, probe_addrs);
 }
-EXPORT_SYMBOL_GPL(v4l2_i2c_new_subdev_cfg);
+EXPORT_SYMBOL_GPL(v4l2_i2c_new_subdev);
 
 /* Return i2c client address of v4l2_subdev. */
 unsigned short v4l2_i2c_subdev_addr(struct v4l2_subdev *sd)
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/v4l2-compat-ioctl32.c linux-libre-2.6.38-gnu1/drivers/media/video/v4l2-compat-ioctl32.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/v4l2-compat-ioctl32.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/v4l2-compat-ioctl32.c	2011-03-14 21:20:32.000000000 -0400
@@ -15,219 +15,12 @@
 
 #include <linux/compat.h>
 #define __OLD_VIDIOC_ /* To allow fixing old calls*/
-#include <linux/videodev.h>
 #include <linux/videodev2.h>
 #include <linux/module.h>
 #include <media/v4l2-ioctl.h>
 
 #ifdef CONFIG_COMPAT
 
-#ifdef CONFIG_VIDEO_V4L1_COMPAT
-struct video_tuner32 {
-	compat_int_t tuner;
-	char name[32];
-	compat_ulong_t rangelow, rangehigh;
-	u32 flags;	/* It is really u32 in videodev.h */
-	u16 mode, signal;
-};
-
-static int get_video_tuner32(struct video_tuner *kp, struct video_tuner32 __user *up)
-{
-	if (!access_ok(VERIFY_READ, up, sizeof(struct video_tuner32)) ||
-		get_user(kp->tuner, &up->tuner) ||
-		copy_from_user(kp->name, up->name, 32) ||
-		get_user(kp->rangelow, &up->rangelow) ||
-		get_user(kp->rangehigh, &up->rangehigh) ||
-		get_user(kp->flags, &up->flags) ||
-		get_user(kp->mode, &up->mode) ||
-		get_user(kp->signal, &up->signal))
-		return -EFAULT;
-	return 0;
-}
-
-static int put_video_tuner32(struct video_tuner *kp, struct video_tuner32 __user *up)
-{
-	if (!access_ok(VERIFY_WRITE, up, sizeof(struct video_tuner32)) ||
-		put_user(kp->tuner, &up->tuner) ||
-		copy_to_user(up->name, kp->name, 32) ||
-		put_user(kp->rangelow, &up->rangelow) ||
-		put_user(kp->rangehigh, &up->rangehigh) ||
-		put_user(kp->flags, &up->flags) ||
-		put_user(kp->mode, &up->mode) ||
-		put_user(kp->signal, &up->signal))
-			return -EFAULT;
-	return 0;
-}
-
-struct video_buffer32 {
-	compat_caddr_t base;
-	compat_int_t height, width, depth, bytesperline;
-};
-
-static int get_video_buffer32(struct video_buffer *kp, struct video_buffer32 __user *up)
-{
-	u32 tmp;
-
-	if (!access_ok(VERIFY_READ, up, sizeof(struct video_buffer32)) ||
-		get_user(tmp, &up->base) ||
-		get_user(kp->height, &up->height) ||
-		get_user(kp->width, &up->width) ||
-		get_user(kp->depth, &up->depth) ||
-		get_user(kp->bytesperline, &up->bytesperline))
-			return -EFAULT;
-
-	/* This is actually a physical address stored
-	 * as a void pointer.
-	 */
-	kp->base = (void *)(unsigned long) tmp;
-
-	return 0;
-}
-
-static int put_video_buffer32(struct video_buffer *kp, struct video_buffer32 __user *up)
-{
-	u32 tmp = (u32)((unsigned long)kp->base);
-
-	if (!access_ok(VERIFY_WRITE, up, sizeof(struct video_buffer32)) ||
-		put_user(tmp, &up->base) ||
-		put_user(kp->height, &up->height) ||
-		put_user(kp->width, &up->width) ||
-		put_user(kp->depth, &up->depth) ||
-		put_user(kp->bytesperline, &up->bytesperline))
-			return -EFAULT;
-	return 0;
-}
-
-struct video_clip32 {
-	s32 x, y, width, height;	/* It's really s32 in videodev.h */
-	compat_caddr_t next;
-};
-
-struct video_window32 {
-	u32 x, y, width, height, chromakey, flags;
-	compat_caddr_t clips;
-	compat_int_t clipcount;
-};
-
-static int get_video_window32(struct video_window *kp, struct video_window32 __user *up)
-{
-	struct video_clip __user *uclips;
-	struct video_clip __user *kclips;
-	compat_caddr_t p;
-	int nclips;
-
-	if (!access_ok(VERIFY_READ, up, sizeof(struct video_window32)))
-		return -EFAULT;
-
-	if (get_user(nclips, &up->clipcount))
-		return -EFAULT;
-
-	if (!access_ok(VERIFY_READ, up, sizeof(struct video_window32)) ||
-	    get_user(kp->x, &up->x) ||
-	    get_user(kp->y, &up->y) ||
-	    get_user(kp->width, &up->width) ||
-	    get_user(kp->height, &up->height) ||
-	    get_user(kp->chromakey, &up->chromakey) ||
-	    get_user(kp->flags, &up->flags) ||
-	    get_user(kp->clipcount, &up->clipcount))
-		return -EFAULT;
-
-	nclips = kp->clipcount;
-	kp->clips = NULL;
-
-	if (nclips == 0)
-		return 0;
-	if (get_user(p, &up->clips))
-		return -EFAULT;
-	uclips = compat_ptr(p);
-
-	/* If nclips < 0, then it is a clipping bitmap of size
-	   VIDEO_CLIPMAP_SIZE */
-	if (nclips < 0) {
-		if (!access_ok(VERIFY_READ, uclips, VIDEO_CLIPMAP_SIZE))
-			return -EFAULT;
-		kp->clips = compat_alloc_user_space(VIDEO_CLIPMAP_SIZE);
-		if (copy_in_user(kp->clips, uclips, VIDEO_CLIPMAP_SIZE))
-			return -EFAULT;
-		return 0;
-	}
-
-	/* Otherwise it is an array of video_clip structs. */
-	if (!access_ok(VERIFY_READ, uclips, nclips * sizeof(struct video_clip)))
-		return -EFAULT;
-
-	kp->clips = compat_alloc_user_space(nclips * sizeof(struct video_clip));
-	kclips = kp->clips;
-	while (nclips--) {
-		int err;
-
-		err = copy_in_user(&kclips->x, &uclips->x, sizeof(kclips->x));
-		err |= copy_in_user(&kclips->y, &uclips->y, sizeof(kclips->y));
-		err |= copy_in_user(&kclips->width, &uclips->width, sizeof(kclips->width));
-		err |= copy_in_user(&kclips->height, &uclips->height, sizeof(kclips->height));
-		kclips->next = NULL;
-		if (err)
-			return -EFAULT;
-		kclips++;
-		uclips++;
-	}
-	return 0;
-}
-
-/* You get back everything except the clips... */
-static int put_video_window32(struct video_window *kp, struct video_window32 __user *up)
-{
-	if (!access_ok(VERIFY_WRITE, up, sizeof(struct video_window32)) ||
-		put_user(kp->x, &up->x) ||
-		put_user(kp->y, &up->y) ||
-		put_user(kp->width, &up->width) ||
-		put_user(kp->height, &up->height) ||
-		put_user(kp->chromakey, &up->chromakey) ||
-		put_user(kp->flags, &up->flags) ||
-		put_user(kp->clipcount, &up->clipcount))
-			return -EFAULT;
-	return 0;
-}
-
-struct video_code32 {
-	char		loadwhat[16];	/* name or tag of file being passed */
-	compat_int_t	datasize;
-	compat_uptr_t	data;
-};
-
-static struct video_code __user *get_microcode32(struct video_code32 *kp)
-{
-	struct video_code __user *up;
-
-	up = compat_alloc_user_space(sizeof(*up));
-
-	/*
-	 * NOTE! We don't actually care if these fail. If the
-	 * user address is invalid, the native ioctl will do
-	 * the error handling for us
-	 */
-	(void) copy_to_user(up->loadwhat, kp->loadwhat, sizeof(up->loadwhat));
-	(void) put_user(kp->datasize, &up->datasize);
-	(void) put_user(compat_ptr(kp->data), &up->data);
-	return up;
-}
-
-#define VIDIOCGTUNER32		_IOWR('v', 4, struct video_tuner32)
-#define VIDIOCSTUNER32		_IOW('v', 5, struct video_tuner32)
-#define VIDIOCGWIN32		_IOR('v', 9, struct video_window32)
-#define VIDIOCSWIN32		_IOW('v', 10, struct video_window32)
-#define VIDIOCGFBUF32		_IOR('v', 11, struct video_buffer32)
-#define VIDIOCSFBUF32		_IOW('v', 12, struct video_buffer32)
-#define VIDIOCGFREQ32		_IOR('v', 14, u32)
-#define VIDIOCSFREQ32		_IOW('v', 15, u32)
-#define VIDIOCSMICROCODE32	_IOW('v', 27, struct video_code32)
-
-#define VIDIOCCAPTURE32		_IOW('v', 8, s32)
-#define VIDIOCSYNC32		_IOW('v', 18, s32)
-#define VIDIOCSWRITEMODE32	_IOW('v', 25, s32)
-
-#endif
-
 static long native_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
 	long ret = -ENOIOCTLCMD;
@@ -372,8 +165,6 @@ static int get_v4l2_format32(struct v4l2
 		if (copy_from_user(kp, up, sizeof(kp->fmt.raw_data)))
 			return -EFAULT;
 		return 0;
-	case 0:
-		return -EINVAL;
 	default:
 		printk(KERN_INFO "compat_ioctl32: unexpected VIDIOC_FMT type %d\n",
 								kp->type);
@@ -403,8 +194,6 @@ static int put_v4l2_format32(struct v4l2
 		if (copy_to_user(up, kp, sizeof(up->fmt.raw_data)))
 			return -EFAULT;
 		return 0;
-	case 0:
-		return -EINVAL;
 	default:
 		printk(KERN_INFO "compat_ioctl32: unexpected VIDIOC_FMT type %d\n",
 								kp->type);
@@ -741,13 +530,6 @@ static int put_v4l2_ext_controls32(struc
 static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
 	union {
-#ifdef CONFIG_VIDEO_V4L1_COMPAT
-		struct video_tuner vt;
-		struct video_buffer vb;
-		struct video_window vw;
-		struct video_code32 vc;
-		struct video_audio va;
-#endif
 		struct v4l2_format v2f;
 		struct v4l2_buffer v2b;
 		struct v4l2_framebuffer v2fb;
@@ -763,17 +545,6 @@ static long do_video_ioctl(struct file *
 
 	/* First, convert the command. */
 	switch (cmd) {
-#ifdef CONFIG_VIDEO_V4L1_COMPAT
-	case VIDIOCGTUNER32: cmd = VIDIOCGTUNER; break;
-	case VIDIOCSTUNER32: cmd = VIDIOCSTUNER; break;
-	case VIDIOCGWIN32: cmd = VIDIOCGWIN; break;
-	case VIDIOCSWIN32: cmd = VIDIOCSWIN; break;
-	case VIDIOCGFBUF32: cmd = VIDIOCGFBUF; break;
-	case VIDIOCSFBUF32: cmd = VIDIOCSFBUF; break;
-	case VIDIOCGFREQ32: cmd = VIDIOCGFREQ; break;
-	case VIDIOCSFREQ32: cmd = VIDIOCSFREQ; break;
-	case VIDIOCSMICROCODE32: cmd = VIDIOCSMICROCODE; break;
-#endif
 	case VIDIOC_G_FMT32: cmd = VIDIOC_G_FMT; break;
 	case VIDIOC_S_FMT32: cmd = VIDIOC_S_FMT; break;
 	case VIDIOC_QUERYBUF32: cmd = VIDIOC_QUERYBUF; break;
@@ -800,46 +571,6 @@ static long do_video_ioctl(struct file *
 	}
 
 	switch (cmd) {
-#ifdef CONFIG_VIDEO_V4L1_COMPAT
-	case VIDIOCSTUNER:
-	case VIDIOCGTUNER:
-		err = get_video_tuner32(&karg.vt, up);
-		compatible_arg = 0;
-		break;
-
-	case VIDIOCSFBUF:
-		err = get_video_buffer32(&karg.vb, up);
-		compatible_arg = 0;
-		break;
-
-	case VIDIOCSWIN:
-		err = get_video_window32(&karg.vw, up);
-		compatible_arg = 0;
-		break;
-
-	case VIDIOCGWIN:
-	case VIDIOCGFBUF:
-	case VIDIOCGFREQ:
-		compatible_arg = 0;
-		break;
-
-	case VIDIOCSMICROCODE:
-		/* Copy the 32-bit "video_code32" to kernel space */
-		if (copy_from_user(&karg.vc, up, sizeof(karg.vc)))
-			return -EFAULT;
-		/* Convert the 32-bit version to a 64-bit version in user space */
-		up = get_microcode32(&karg.vc);
-		break;
-
-	case VIDIOCSFREQ:
-		err = get_user(karg.vx, (u32 __user *)up);
-		compatible_arg = 0;
-		break;
-
-	case VIDIOCCAPTURE:
-	case VIDIOCSYNC:
-	case VIDIOCSWRITEMODE:
-#endif
 	case VIDIOC_OVERLAY:
 	case VIDIOC_STREAMON:
 	case VIDIOC_STREAMOFF:
@@ -922,23 +653,6 @@ static long do_video_ioctl(struct file *
 		return err;
 
 	switch (cmd) {
-#ifdef CONFIG_VIDEO_V4L1_COMPAT
-	case VIDIOCGTUNER:
-		err = put_video_tuner32(&karg.vt, up);
-		break;
-
-	case VIDIOCGWIN:
-		err = put_video_window32(&karg.vw, up);
-		break;
-
-	case VIDIOCGFBUF:
-		err = put_video_buffer32(&karg.vb, up);
-		break;
-
-	case VIDIOCGFREQ:
-		err = put_user(((u32)karg.vx), (u32 __user *)up);
-		break;
-#endif
 	case VIDIOC_S_INPUT:
 	case VIDIOC_S_OUTPUT:
 	case VIDIOC_G_INPUT:
@@ -981,37 +695,6 @@ long v4l2_compat_ioctl32(struct file *fi
 		return ret;
 
 	switch (cmd) {
-#ifdef CONFIG_VIDEO_V4L1_COMPAT
-	case VIDIOCGCAP:
-	case VIDIOCGCHAN:
-	case VIDIOCSCHAN:
-	case VIDIOCGTUNER32:
-	case VIDIOCSTUNER32:
-	case VIDIOCGPICT:
-	case VIDIOCSPICT:
-	case VIDIOCCAPTURE32:
-	case VIDIOCGWIN32:
-	case VIDIOCSWIN32:
-	case VIDIOCGFBUF32:
-	case VIDIOCSFBUF32:
-	case VIDIOCKEY:
-	case VIDIOCGFREQ32:
-	case VIDIOCSFREQ32:
-	case VIDIOCGAUDIO:
-	case VIDIOCSAUDIO:
-	case VIDIOCSYNC32:
-	case VIDIOCMCAPTURE:
-	case VIDIOCGMBUF:
-	case VIDIOCGUNIT:
-	case VIDIOCGCAPTURE:
-	case VIDIOCSCAPTURE:
-	case VIDIOCSPLAYMODE:
-	case VIDIOCSWRITEMODE32:
-	case VIDIOCGPLAYINFO:
-	case VIDIOCSMICROCODE32:
-	case VIDIOCGVBIFMT:
-	case VIDIOCSVBIFMT:
-#endif
 #ifdef __OLD_VIDIOC_
 	case VIDIOC_OVERLAY32_OLD:
 	case VIDIOC_S_PARM_OLD:
@@ -1096,19 +779,6 @@ long v4l2_compat_ioctl32(struct file *fi
 		ret = do_video_ioctl(file, cmd, arg);
 		break;
 
-#ifdef CONFIG_VIDEO_V4L1_COMPAT
-	/* BTTV specific... */
-	case _IOW('v',  BASE_VIDIOCPRIVATE+0, char [256]):
-	case _IOR('v',  BASE_VIDIOCPRIVATE+1, char [256]):
-	case _IOR('v' , BASE_VIDIOCPRIVATE+2, unsigned int):
-	case _IOW('v' , BASE_VIDIOCPRIVATE+3, char [16]): /* struct bttv_pll_info */
-	case _IOR('v' , BASE_VIDIOCPRIVATE+4, int):
-	case _IOR('v' , BASE_VIDIOCPRIVATE+5, int):
-	case _IOR('v' , BASE_VIDIOCPRIVATE+6, int):
-	case _IOR('v' , BASE_VIDIOCPRIVATE+7, int):
-		ret = native_ioctl(file, cmd, (unsigned long)compat_ptr(arg));
-		break;
-#endif
 	default:
 		printk(KERN_WARNING "compat_ioctl32: "
 			"unknown ioctl '%c', dir=%d, #%d (0x%08x)\n",
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/v4l2-ctrls.c linux-libre-2.6.38-gnu1/drivers/media/video/v4l2-ctrls.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/v4l2-ctrls.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/v4l2-ctrls.c	2011-03-14 21:20:32.000000000 -0400
@@ -38,15 +38,15 @@ struct ctrl_helper {
    the given control ID. The pointer array ends with a NULL pointer.
    An empty string signifies a menu entry that is invalid. This allows
    drivers to disable certain options if it is not supported. */
-const char **v4l2_ctrl_get_menu(u32 id)
+const char * const *v4l2_ctrl_get_menu(u32 id)
 {
-	static const char *mpeg_audio_sampling_freq[] = {
+	static const char * const mpeg_audio_sampling_freq[] = {
 		"44.1 kHz",
 		"48 kHz",
 		"32 kHz",
 		NULL
 	};
-	static const char *mpeg_audio_encoding[] = {
+	static const char * const mpeg_audio_encoding[] = {
 		"MPEG-1/2 Layer I",
 		"MPEG-1/2 Layer II",
 		"MPEG-1/2 Layer III",
@@ -54,7 +54,7 @@ const char **v4l2_ctrl_get_menu(u32 id)
 		"AC-3",
 		NULL
 	};
-	static const char *mpeg_audio_l1_bitrate[] = {
+	static const char * const mpeg_audio_l1_bitrate[] = {
 		"32 kbps",
 		"64 kbps",
 		"96 kbps",
@@ -71,7 +71,7 @@ const char **v4l2_ctrl_get_menu(u32 id)
 		"448 kbps",
 		NULL
 	};
-	static const char *mpeg_audio_l2_bitrate[] = {
+	static const char * const mpeg_audio_l2_bitrate[] = {
 		"32 kbps",
 		"48 kbps",
 		"56 kbps",
@@ -88,7 +88,7 @@ const char **v4l2_ctrl_get_menu(u32 id)
 		"384 kbps",
 		NULL
 	};
-	static const char *mpeg_audio_l3_bitrate[] = {
+	static const char * const mpeg_audio_l3_bitrate[] = {
 		"32 kbps",
 		"40 kbps",
 		"48 kbps",
@@ -105,7 +105,7 @@ const char **v4l2_ctrl_get_menu(u32 id)
 		"320 kbps",
 		NULL
 	};
-	static const char *mpeg_audio_ac3_bitrate[] = {
+	static const char * const mpeg_audio_ac3_bitrate[] = {
 		"32 kbps",
 		"40 kbps",
 		"48 kbps",
@@ -127,50 +127,50 @@ const char **v4l2_ctrl_get_menu(u32 id)
 		"640 kbps",
 		NULL
 	};
-	static const char *mpeg_audio_mode[] = {
+	static const char * const mpeg_audio_mode[] = {
 		"Stereo",
 		"Joint Stereo",
 		"Dual",
 		"Mono",
 		NULL
 	};
-	static const char *mpeg_audio_mode_extension[] = {
+	static const char * const mpeg_audio_mode_extension[] = {
 		"Bound 4",
 		"Bound 8",
 		"Bound 12",
 		"Bound 16",
 		NULL
 	};
-	static const char *mpeg_audio_emphasis[] = {
+	static const char * const mpeg_audio_emphasis[] = {
 		"No Emphasis",
 		"50/15 us",
 		"CCITT J17",
 		NULL
 	};
-	static const char *mpeg_audio_crc[] = {
+	static const char * const mpeg_audio_crc[] = {
 		"No CRC",
 		"16-bit CRC",
 		NULL
 	};
-	static const char *mpeg_video_encoding[] = {
+	static const char * const mpeg_video_encoding[] = {
 		"MPEG-1",
 		"MPEG-2",
 		"MPEG-4 AVC",
 		NULL
 	};
-	static const char *mpeg_video_aspect[] = {
+	static const char * const mpeg_video_aspect[] = {
 		"1x1",
 		"4x3",
 		"16x9",
 		"2.21x1",
 		NULL
 	};
-	static const char *mpeg_video_bitrate_mode[] = {
+	static const char * const mpeg_video_bitrate_mode[] = {
 		"Variable Bitrate",
 		"Constant Bitrate",
 		NULL
 	};
-	static const char *mpeg_stream_type[] = {
+	static const char * const mpeg_stream_type[] = {
 		"MPEG-2 Program Stream",
 		"MPEG-2 Transport Stream",
 		"MPEG-1 System Stream",
@@ -179,25 +179,25 @@ const char **v4l2_ctrl_get_menu(u32 id)
 		"MPEG-2 SVCD-compatible Stream",
 		NULL
 	};
-	static const char *mpeg_stream_vbi_fmt[] = {
+	static const char * const mpeg_stream_vbi_fmt[] = {
 		"No VBI",
 		"Private packet, IVTV format",
 		NULL
 	};
-	static const char *camera_power_line_frequency[] = {
+	static const char * const camera_power_line_frequency[] = {
 		"Disabled",
 		"50 Hz",
 		"60 Hz",
 		NULL
 	};
-	static const char *camera_exposure_auto[] = {
+	static const char * const camera_exposure_auto[] = {
 		"Auto Mode",
 		"Manual Mode",
 		"Shutter Priority Mode",
 		"Aperture Priority Mode",
 		NULL
 	};
-	static const char *colorfx[] = {
+	static const char * const colorfx[] = {
 		"None",
 		"Black & White",
 		"Sepia",
@@ -210,7 +210,7 @@ const char **v4l2_ctrl_get_menu(u32 id)
 		"Vivid",
 		NULL
 	};
-	static const char *tune_preemphasis[] = {
+	static const char * const tune_preemphasis[] = {
 		"No preemphasis",
 		"50 useconds",
 		"75 useconds",
@@ -569,7 +569,7 @@ static int user_to_new(struct v4l2_ext_c
 	int ret;
 	u32 size;
 
-	ctrl->has_new = 1;
+	ctrl->is_new = 1;
 	switch (ctrl->type) {
 	case V4L2_CTRL_TYPE_INTEGER64:
 		ctrl->val64 = c->value64;
@@ -952,7 +952,7 @@ static struct v4l2_ctrl *v4l2_ctrl_new(s
 			const struct v4l2_ctrl_ops *ops,
 			u32 id, const char *name, enum v4l2_ctrl_type type,
 			s32 min, s32 max, u32 step, s32 def,
-			u32 flags, const char **qmenu, void *priv)
+			u32 flags, const char * const *qmenu, void *priv)
 {
 	struct v4l2_ctrl *ctrl;
 	unsigned sz_extra = 0;
@@ -962,13 +962,20 @@ static struct v4l2_ctrl *v4l2_ctrl_new(s
 
 	/* Sanity checks */
 	if (id == 0 || name == NULL || id >= V4L2_CID_PRIVATE_BASE ||
-	    def < min || def > max || max < min ||
+	    max < min ||
 	    (type == V4L2_CTRL_TYPE_INTEGER && step == 0) ||
 	    (type == V4L2_CTRL_TYPE_MENU && qmenu == NULL) ||
 	    (type == V4L2_CTRL_TYPE_STRING && max == 0)) {
 		handler_set_err(hdl, -ERANGE);
 		return NULL;
 	}
+	if ((type == V4L2_CTRL_TYPE_INTEGER ||
+	     type == V4L2_CTRL_TYPE_MENU ||
+	     type == V4L2_CTRL_TYPE_BOOLEAN) &&
+	    (def < min || def > max)) {
+		handler_set_err(hdl, -ERANGE);
+		return NULL;
+	}
 
 	if (type == V4L2_CTRL_TYPE_BUTTON)
 		flags |= V4L2_CTRL_FLAG_WRITE_ONLY;
@@ -1019,7 +1026,7 @@ struct v4l2_ctrl *v4l2_ctrl_new_custom(s
 	bool is_menu;
 	struct v4l2_ctrl *ctrl;
 	const char *name = cfg->name;
-	const char **qmenu = cfg->qmenu;
+	const char * const *qmenu = cfg->qmenu;
 	enum v4l2_ctrl_type type = cfg->type;
 	u32 flags = cfg->flags;
 	s32 min = cfg->min;
@@ -1075,7 +1082,7 @@ struct v4l2_ctrl *v4l2_ctrl_new_std_menu
 			const struct v4l2_ctrl_ops *ops,
 			u32 id, s32 max, s32 mask, s32 def)
 {
-	const char **qmenu = v4l2_ctrl_get_menu(id);
+	const char * const *qmenu = v4l2_ctrl_get_menu(id);
 	const char *name;
 	enum v4l2_ctrl_type type;
 	s32 min;
@@ -1273,8 +1280,12 @@ int v4l2_ctrl_handler_setup(struct v4l2_
 		if (ctrl->done)
 			continue;
 
-		for (i = 0; i < master->ncontrols; i++)
-			cur_to_new(master->cluster[i]);
+		for (i = 0; i < master->ncontrols; i++) {
+			if (master->cluster[i]) {
+				cur_to_new(master->cluster[i]);
+				master->cluster[i]->is_new = 1;
+			}
+		}
 
 		/* Skip button controls and read-only controls. */
 		if (ctrl->type == V4L2_CTRL_TYPE_BUTTON ||
@@ -1333,12 +1344,15 @@ int v4l2_queryctrl(struct v4l2_ctrl_hand
 
 	ctrl = ref->ctrl;
 	memset(qc, 0, sizeof(*qc));
-	qc->id = ctrl->id;
+	if (id >= V4L2_CID_PRIVATE_BASE)
+		qc->id = id;
+	else
+		qc->id = ctrl->id;
 	strlcpy(qc->name, ctrl->name, sizeof(qc->name));
 	qc->minimum = ctrl->minimum;
 	qc->maximum = ctrl->maximum;
 	qc->default_value = ctrl->default_value;
-	if (qc->type == V4L2_CTRL_TYPE_MENU)
+	if (ctrl->type == V4L2_CTRL_TYPE_MENU)
 		qc->step = 1;
 	else
 		qc->step = ctrl->step;
@@ -1638,7 +1652,7 @@ static int try_or_set_control_cluster(st
 		if (ctrl == NULL)
 			continue;
 
-		if (ctrl->has_new) {
+		if (ctrl->is_new) {
 			/* Double check this: it may have changed since the
 			   last check in try_or_set_ext_ctrls(). */
 			if (set && (ctrl->flags & V4L2_CTRL_FLAG_GRABBED))
@@ -1712,13 +1726,13 @@ static int try_or_set_ext_ctrls(struct v
 
 		v4l2_ctrl_lock(ctrl);
 
-		/* Reset the 'has_new' flags of the cluster */
+		/* Reset the 'is_new' flags of the cluster */
 		for (j = 0; j < master->ncontrols; j++)
 			if (master->cluster[j])
-				master->cluster[j]->has_new = 0;
+				master->cluster[j]->is_new = 0;
 
 		/* Copy the new caller-supplied control values.
-		   user_to_new() sets 'has_new' to 1. */
+		   user_to_new() sets 'is_new' to 1. */
 		ret = cluster_walk(i, cs, helpers, user_to_new);
 
 		if (!ret)
@@ -1813,15 +1827,18 @@ static int set_ctrl(struct v4l2_ctrl *ct
 	int ret;
 	int i;
 
+	if (ctrl->flags & V4L2_CTRL_FLAG_READ_ONLY)
+		return -EACCES;
+
 	v4l2_ctrl_lock(ctrl);
 
-	/* Reset the 'has_new' flags of the cluster */
+	/* Reset the 'is_new' flags of the cluster */
 	for (i = 0; i < master->ncontrols; i++)
 		if (master->cluster[i])
-			master->cluster[i]->has_new = 0;
+			master->cluster[i]->is_new = 0;
 
 	ctrl->val = *val;
-	ctrl->has_new = 1;
+	ctrl->is_new = 1;
 	ret = try_or_set_control_cluster(master, false);
 	if (!ret)
 		ret = try_or_set_control_cluster(master, true);
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/v4l2-dev.c linux-libre-2.6.38-gnu1/drivers/media/video/v4l2-dev.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/v4l2-dev.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/v4l2-dev.c	2011-03-14 21:20:32.000000000 -0400
@@ -419,6 +419,10 @@ static int get_index(struct video_device
  *	The registration code assigns minor numbers and device node numbers
  *	based on the requested type and registers the new device node with
  *	the kernel.
+ *
+ *	This function assumes that struct video_device was zeroed when it
+ *	was allocated and does not contain any stale date.
+ *
  *	An error is returned if no free minor or device node number could be
  *	found, or if the registration of the device node failed.
  *
@@ -440,7 +444,6 @@ static int __video_register_device(struc
 	int minor_offset = 0;
 	int minor_cnt = VIDEO_NUM_DEVICES;
 	const char *name_base;
-	void *priv = vdev->dev.p;
 
 	/* A minor value of -1 marks this video device as never
 	   having been registered */
@@ -559,10 +562,6 @@ static int __video_register_device(struc
 	}
 
 	/* Part 4: register the device with sysfs */
-	memset(&vdev->dev, 0, sizeof(vdev->dev));
-	/* The memset above cleared the device's device_private, so
-	   put back the copy we made earlier. */
-	vdev->dev.p = priv;
 	vdev->dev.class = &video_class;
 	vdev->dev.devt = MKDEV(VIDEO_MAJOR, vdev->minor);
 	if (vdev->parent)
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/v4l2-device.c linux-libre-2.6.38-gnu1/drivers/media/video/v4l2-device.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/v4l2-device.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/v4l2-device.c	2011-03-14 21:20:32.000000000 -0400
@@ -100,6 +100,7 @@ void v4l2_device_unregister(struct v4l2_
 			   is a platform bus, then it is never deleted. */
 			if (client)
 				i2c_unregister_device(client);
+			continue;
 		}
 #endif
 #if defined(CONFIG_SPI)
@@ -108,6 +109,7 @@ void v4l2_device_unregister(struct v4l2_
 
 			if (spi)
 				spi_unregister_device(spi);
+			continue;
 		}
 #endif
 	}
@@ -126,11 +128,19 @@ int v4l2_device_register_subdev(struct v
 	WARN_ON(sd->v4l2_dev != NULL);
 	if (!try_module_get(sd->owner))
 		return -ENODEV;
+	sd->v4l2_dev = v4l2_dev;
+	if (sd->internal_ops && sd->internal_ops->registered) {
+		err = sd->internal_ops->registered(sd);
+		if (err)
+			return err;
+	}
 	/* This just returns 0 if either of the two args is NULL */
 	err = v4l2_ctrl_add_handler(v4l2_dev->ctrl_handler, sd->ctrl_handler);
-	if (err)
+	if (err) {
+		if (sd->internal_ops && sd->internal_ops->unregistered)
+			sd->internal_ops->unregistered(sd);
 		return err;
-	sd->v4l2_dev = v4l2_dev;
+	}
 	spin_lock(&v4l2_dev->lock);
 	list_add_tail(&sd->list, &v4l2_dev->subdevs);
 	spin_unlock(&v4l2_dev->lock);
@@ -146,6 +156,8 @@ void v4l2_device_unregister_subdev(struc
 	spin_lock(&sd->v4l2_dev->lock);
 	list_del(&sd->list);
 	spin_unlock(&sd->v4l2_dev->lock);
+	if (sd->internal_ops && sd->internal_ops->unregistered)
+		sd->internal_ops->unregistered(sd);
 	sd->v4l2_dev = NULL;
 	module_put(sd->owner);
 }
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/v4l2-ioctl.c linux-libre-2.6.38-gnu1/drivers/media/video/v4l2-ioctl.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/v4l2-ioctl.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/v4l2-ioctl.c	2011-03-14 21:20:32.000000000 -0400
@@ -18,12 +18,8 @@
 #include <linux/kernel.h>
 
 #define __OLD_VIDIOC_ /* To allow fixing old calls */
-#include <linux/videodev.h>
 #include <linux/videodev2.h>
 
-#ifdef CONFIG_VIDEO_V4L1
-#include <linux/videodev.h>
-#endif
 #include <media/v4l2-common.h>
 #include <media/v4l2-ioctl.h>
 #include <media/v4l2-ctrls.h>
@@ -183,42 +179,6 @@ static const char *v4l2_memory_names[] =
 
 /* ------------------------------------------------------------------ */
 /* debug help functions                                               */
-
-#ifdef CONFIG_VIDEO_V4L1_COMPAT
-static const char *v4l1_ioctls[] = {
-	[_IOC_NR(VIDIOCGCAP)]       = "VIDIOCGCAP",
-	[_IOC_NR(VIDIOCGCHAN)]      = "VIDIOCGCHAN",
-	[_IOC_NR(VIDIOCSCHAN)]      = "VIDIOCSCHAN",
-	[_IOC_NR(VIDIOCGTUNER)]     = "VIDIOCGTUNER",
-	[_IOC_NR(VIDIOCSTUNER)]     = "VIDIOCSTUNER",
-	[_IOC_NR(VIDIOCGPICT)]      = "VIDIOCGPICT",
-	[_IOC_NR(VIDIOCSPICT)]      = "VIDIOCSPICT",
-	[_IOC_NR(VIDIOCCAPTURE)]    = "VIDIOCCAPTURE",
-	[_IOC_NR(VIDIOCGWIN)]       = "VIDIOCGWIN",
-	[_IOC_NR(VIDIOCSWIN)]       = "VIDIOCSWIN",
-	[_IOC_NR(VIDIOCGFBUF)]      = "VIDIOCGFBUF",
-	[_IOC_NR(VIDIOCSFBUF)]      = "VIDIOCSFBUF",
-	[_IOC_NR(VIDIOCKEY)]        = "VIDIOCKEY",
-	[_IOC_NR(VIDIOCGFREQ)]      = "VIDIOCGFREQ",
-	[_IOC_NR(VIDIOCSFREQ)]      = "VIDIOCSFREQ",
-	[_IOC_NR(VIDIOCGAUDIO)]     = "VIDIOCGAUDIO",
-	[_IOC_NR(VIDIOCSAUDIO)]     = "VIDIOCSAUDIO",
-	[_IOC_NR(VIDIOCSYNC)]       = "VIDIOCSYNC",
-	[_IOC_NR(VIDIOCMCAPTURE)]   = "VIDIOCMCAPTURE",
-	[_IOC_NR(VIDIOCGMBUF)]      = "VIDIOCGMBUF",
-	[_IOC_NR(VIDIOCGUNIT)]      = "VIDIOCGUNIT",
-	[_IOC_NR(VIDIOCGCAPTURE)]   = "VIDIOCGCAPTURE",
-	[_IOC_NR(VIDIOCSCAPTURE)]   = "VIDIOCSCAPTURE",
-	[_IOC_NR(VIDIOCSPLAYMODE)]  = "VIDIOCSPLAYMODE",
-	[_IOC_NR(VIDIOCSWRITEMODE)] = "VIDIOCSWRITEMODE",
-	[_IOC_NR(VIDIOCGPLAYINFO)]  = "VIDIOCGPLAYINFO",
-	[_IOC_NR(VIDIOCSMICROCODE)] = "VIDIOCSMICROCODE",
-	[_IOC_NR(VIDIOCGVBIFMT)]    = "VIDIOCGVBIFMT",
-	[_IOC_NR(VIDIOCSVBIFMT)]    = "VIDIOCSVBIFMT"
-};
-#define V4L1_IOCTLS ARRAY_SIZE(v4l1_ioctls)
-#endif
-
 static const char *v4l2_ioctls[] = {
 	[_IOC_NR(VIDIOC_QUERYCAP)]         = "VIDIOC_QUERYCAP",
 	[_IOC_NR(VIDIOC_RESERVED)]         = "VIDIOC_RESERVED",
@@ -310,15 +270,6 @@ void v4l_printk_ioctl(unsigned int cmd)
 	case 'd':
 		type = "v4l2_int";
 		break;
-#ifdef CONFIG_VIDEO_V4L1_COMPAT
-	case 'v':
-		if (_IOC_NR(cmd) >= V4L1_IOCTLS) {
-			type = "v4l1";
-			break;
-		}
-		printk("%s", v4l1_ioctls[_IOC_NR(cmd)]);
-		return;
-#endif
 	case 'V':
 		if (_IOC_NR(cmd) >= V4L2_IOCTLS) {
 			type = "v4l2";
@@ -622,20 +573,6 @@ static long __video_do_ioctl(struct file
 		return -EINVAL;
 	}
 
-#ifdef CONFIG_VIDEO_V4L1_COMPAT
-	/********************************************************
-	 All other V4L1 calls are handled by v4l1_compat module.
-	 Those calls will be translated into V4L2 calls, and
-	 __video_do_ioctl will be called again, with one or more
-	 V4L2 ioctls.
-	 ********************************************************/
-	if (_IOC_TYPE(cmd) == 'v' && cmd != VIDIOCGMBUF &&
-				_IOC_NR(cmd) < BASE_VIDIOCPRIVATE) {
-		return v4l_compat_translate_ioctl(file, cmd, arg,
-						__video_do_ioctl);
-	}
-#endif
-
 	if ((vfd->debug & V4L2_DEBUG_IOCTL) &&
 				!(vfd->debug & V4L2_DEBUG_IOCTL_ARG)) {
 		v4l_print_ioctl(vfd->name, cmd);
@@ -644,29 +581,6 @@ static long __video_do_ioctl(struct file
 
 	switch (cmd) {
 
-#ifdef CONFIG_VIDEO_V4L1_COMPAT
-	/***********************************************************
-	 Handles calls to the obsoleted V4L1 API
-	 Due to the nature of VIDIOCGMBUF, each driver that supports
-	 V4L1 should implement its own handler for this ioctl.
-	 ***********************************************************/
-
-	/* --- streaming capture ------------------------------------- */
-	case VIDIOCGMBUF:
-	{
-		struct video_mbuf *p = arg;
-
-		if (!ops->vidiocgmbuf)
-			break;
-		ret = ops->vidiocgmbuf(file, fh, p);
-		if (!ret)
-			dbgarg(cmd, "size=%d, frames=%d, offsets=0x%08lx\n",
-						p->size, p->frames,
-						(unsigned long)p->offsets);
-		break;
-	}
-#endif
-
 	/* --- capabilities ------------------------------------------ */
 	case VIDIOC_QUERYCAP:
 	{
@@ -1745,20 +1659,24 @@ static long __video_do_ioctl(struct file
 	{
 		struct v4l2_dbg_register *p = arg;
 
-		if (!capable(CAP_SYS_ADMIN))
-			ret = -EPERM;
-		else if (ops->vidioc_g_register)
-			ret = ops->vidioc_g_register(file, fh, p);
+		if (ops->vidioc_g_register) {
+			if (!capable(CAP_SYS_ADMIN))
+				ret = -EPERM;
+			else
+				ret = ops->vidioc_g_register(file, fh, p);
+		}
 		break;
 	}
 	case VIDIOC_DBG_S_REGISTER:
 	{
 		struct v4l2_dbg_register *p = arg;
 
-		if (!capable(CAP_SYS_ADMIN))
-			ret = -EPERM;
-		else if (ops->vidioc_s_register)
-			ret = ops->vidioc_s_register(file, fh, p);
+		if (ops->vidioc_s_register) {
+			if (!capable(CAP_SYS_ADMIN))
+				ret = -EPERM;
+			else
+				ret = ops->vidioc_s_register(file, fh, p);
+		}
 		break;
 	}
 #endif
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/via-camera.c linux-libre-2.6.38-gnu1/drivers/media/video/via-camera.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/via-camera.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/via-camera.c	2011-03-14 21:20:32.000000000 -0400
@@ -13,14 +13,12 @@
 #include <linux/pci.h>
 #include <linux/gpio.h>
 #include <linux/interrupt.h>
-#include <linux/pci.h>
 #include <linux/platform_device.h>
 #include <linux/videodev2.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-ioctl.h>
 #include <media/v4l2-chip-ident.h>
 #include <media/videobuf-dma-sg.h>
-#include <linux/device.h>
 #include <linux/delay.h>
 #include <linux/dma-mapping.h>
 #include <linux/pm_qos_params.h>
@@ -1161,16 +1159,6 @@ out:
 	return ret;
 }
 
-#ifdef CONFIG_VIDEO_V4L1_COMPAT
-static int viacam_vidiocgmbuf(struct file *filp, void *priv,
-		struct video_mbuf *mbuf)
-{
-	struct via_camera *cam = priv;
-
-	return videobuf_cgmbuf(&cam->vb_queue, mbuf, 6);
-}
-#endif
-
 /* G/S_PARM */
 
 static int viacam_g_parm(struct file *filp, void *priv,
@@ -1251,9 +1239,6 @@ static const struct v4l2_ioctl_ops viaca
 	.vidioc_s_parm		= viacam_s_parm,
 	.vidioc_enum_framesizes = viacam_enum_framesizes,
 	.vidioc_enum_frameintervals = viacam_enum_frameintervals,
-#ifdef CONFIG_VIDEO_V4L1_COMPAT
-	.vidiocgmbuf		= viacam_vidiocgmbuf,
-#endif
 };
 
 /*----------------------------------------------------------------------------*/
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/videobuf-core.c linux-libre-2.6.38-gnu1/drivers/media/video/videobuf-core.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/videobuf-core.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/videobuf-core.c	2011-03-14 21:20:32.000000000 -0400
@@ -1202,33 +1202,3 @@ int videobuf_mmap_mapper(struct videobuf
 	return rc;
 }
 EXPORT_SYMBOL_GPL(videobuf_mmap_mapper);
-
-#ifdef CONFIG_VIDEO_V4L1_COMPAT
-int videobuf_cgmbuf(struct videobuf_queue *q,
-		    struct video_mbuf *mbuf, int count)
-{
-	struct v4l2_requestbuffers req;
-	int rc, i;
-
-	MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS);
-
-	memset(&req, 0, sizeof(req));
-	req.type   = q->type;
-	req.count  = count;
-	req.memory = V4L2_MEMORY_MMAP;
-	rc = videobuf_reqbufs(q, &req);
-	if (rc < 0)
-		return rc;
-
-	mbuf->frames = req.count;
-	mbuf->size   = 0;
-	for (i = 0; i < mbuf->frames; i++) {
-		mbuf->offsets[i]  = q->bufs[i]->boff;
-		mbuf->size       += PAGE_ALIGN(q->bufs[i]->bsize);
-	}
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(videobuf_cgmbuf);
-#endif
-
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/videobuf-dma-sg.c linux-libre-2.6.38-gnu1/drivers/media/video/videobuf-dma-sg.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/videobuf-dma-sg.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/videobuf-dma-sg.c	2011-03-14 21:20:32.000000000 -0400
@@ -69,10 +69,9 @@ static struct scatterlist *videobuf_vmal
 	struct page *pg;
 	int i;
 
-	sglist = vmalloc(nr_pages * sizeof(*sglist));
+	sglist = vzalloc(nr_pages * sizeof(*sglist));
 	if (NULL == sglist)
 		return NULL;
-	memset(sglist, 0, nr_pages * sizeof(*sglist));
 	sg_init_table(sglist, nr_pages);
 	for (i = 0; i < nr_pages; i++, virt += PAGE_SIZE) {
 		pg = vmalloc_to_page(virt);
@@ -544,14 +543,6 @@ static int __videobuf_mmap_mapper(struct
 
 	retval = -EINVAL;
 
-	/* This function maintains backwards compatibility with V4L1 and will
-	 * map more than one buffer if the vma length is equal to the combined
-	 * size of multiple buffers than it will map them together.  See
-	 * VIDIOCGMBUF in the v4l spec
-	 *
-	 * TODO: Allow drivers to specify if they support this mode
-	 */
-
 	BUG_ON(!mem);
 	MAGIC_CHECK(mem->magic, MAGIC_SG_MEM);
 
@@ -571,29 +562,6 @@ static int __videobuf_mmap_mapper(struct
 	}
 
 	last = first;
-#ifdef CONFIG_VIDEO_V4L1_COMPAT
-	if (size != (vma->vm_end - vma->vm_start)) {
-		/* look for last buffer to map */
-		for (last = first + 1; last < VIDEO_MAX_FRAME; last++) {
-			if (NULL == q->bufs[last])
-				continue;
-			if (V4L2_MEMORY_MMAP != q->bufs[last]->memory)
-				continue;
-			if (q->bufs[last]->map) {
-				retval = -EBUSY;
-				goto done;
-			}
-			size += PAGE_ALIGN(q->bufs[last]->bsize);
-			if (size == (vma->vm_end - vma->vm_start))
-				break;
-		}
-		if (VIDEO_MAX_FRAME == last) {
-			dprintk(1, "mmap app bug: size invalid [size=0x%lx]\n",
-					(vma->vm_end - vma->vm_start));
-			goto done;
-		}
-	}
-#endif
 
 	/* create mapping + update buffer list */
 	retval = -ENOMEM;
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/vino.c linux-libre-2.6.38-gnu1/drivers/media/video/vino.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/vino.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/vino.c	2011-03-14 21:20:32.000000000 -0400
@@ -2954,9 +2954,6 @@ static int vino_enum_input(struct file *
 	if (input == VINO_INPUT_NONE)
 		return -EINVAL;
 
-	memset(i, 0, sizeof(struct v4l2_input));
-
-	i->index = index;
 	i->type = V4L2_INPUT_TYPE_CAMERA;
 	i->std = vino_inputs[input].std;
 	strcpy(i->name, vino_inputs[input].name);
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/vivi.c linux-libre-2.6.38-gnu1/drivers/media/video/vivi.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/vivi.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/vivi.c	2011-03-14 21:20:32.000000000 -0400
@@ -870,15 +870,6 @@ static int vidioc_dqbuf(struct file *fil
 				file->f_flags & O_NONBLOCK);
 }
 
-#ifdef CONFIG_VIDEO_V4L1_COMPAT
-static int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf)
-{
-	struct vivi_dev *dev = video_drvdata(file);
-
-	return videobuf_cgmbuf(&dev->vb_vidq, mbuf, 8);
-}
-#endif
-
 static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
 {
 	struct vivi_dev *dev = video_drvdata(file);
@@ -1105,9 +1096,6 @@ static const struct v4l2_ioctl_ops vivi_
 	.vidioc_queryctrl     = vidioc_queryctrl,
 	.vidioc_g_ctrl        = vidioc_g_ctrl,
 	.vidioc_s_ctrl        = vidioc_s_ctrl,
-#ifdef CONFIG_VIDEO_V4L1_COMPAT
-	.vidiocgmbuf          = vidiocgmbuf,
-#endif
 };
 
 static struct video_device vivi_template = {
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/w9966.c linux-libre-2.6.38-gnu1/drivers/media/video/w9966.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/w9966.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/w9966.c	2011-03-14 21:20:32.000000000 -0400
@@ -937,6 +937,7 @@ static void w9966_term(struct w9966 *cam
 		parport_unregister_device(cam->pdev);
 		w9966_set_state(cam, W9966_STATE_PDEV, 0);
 	}
+	memset(cam, 0, sizeof(*cam));
 }
 
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/zoran/zoran_card.c linux-libre-2.6.38-gnu1/drivers/media/video/zoran/zoran_card.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/zoran/zoran_card.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/zoran/zoran_card.c	2011-03-14 21:20:32.000000000 -0400
@@ -943,7 +943,7 @@ zoran_open_init_params (struct zoran *zr
 	memset(zr->jpg_settings.jpg_comp.COM_data, 0,
 	       sizeof(zr->jpg_settings.jpg_comp.COM_data));
 	zr->jpg_settings.jpg_comp.jpeg_markers =
-	    JPEG_MARKER_DHT | JPEG_MARKER_DQT;
+	    V4L2_JPEG_MARKER_DHT | V4L2_JPEG_MARKER_DQT;
 	i = zoran_check_jpg_settings(zr, &zr->jpg_settings, 0);
 	if (i)
 		dprintk(1, KERN_ERR "%s: %s internal error\n",
@@ -1041,7 +1041,7 @@ zr36057_init (struct zoran *zr)
 	/* allocate memory *before* doing anything to the hardware
 	 * in case allocation fails */
 	zr->stat_com = kzalloc(BUZ_NUM_STAT_COM * 4, GFP_KERNEL);
-	zr->video_dev = kmalloc(sizeof(struct video_device), GFP_KERNEL);
+	zr->video_dev = video_device_alloc();
 	if (!zr->stat_com || !zr->video_dev) {
 		dprintk(1,
 			KERN_ERR
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/zoran/zoran_device.c linux-libre-2.6.38-gnu1/drivers/media/video/zoran/zoran_device.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/zoran/zoran_device.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/zoran/zoran_device.c	2011-03-14 21:20:32.000000000 -0400
@@ -1523,7 +1523,7 @@ zoran_irq (int             irq,
 		    zr->JPEG_missed > 25 ||
 		    zr->JPEG_error == 1	||
 		    ((zr->codec_mode == BUZ_MODE_MOTION_DECOMPRESS) &&
-		     (zr->frame_num & (zr->JPEG_missed > zr->jpg_settings.field_per_buff)))) {
+		     (zr->frame_num && (zr->JPEG_missed > zr->jpg_settings.field_per_buff)))) {
 			error_handler(zr, astat, stat);
 		}
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/zoran/zoran_driver.c linux-libre-2.6.38-gnu1/drivers/media/video/zoran/zoran_driver.c
--- linux-libre-2.6.37-gnu1/drivers/media/video/zoran/zoran_driver.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/zoran/zoran_driver.c	2011-03-14 21:20:32.000000000 -0400
@@ -1528,323 +1528,6 @@ zoran_set_input (struct zoran *zr,
  *   ioctl routine
  */
 
-#ifdef CONFIG_VIDEO_V4L1_COMPAT
-static long zoran_default(struct file *file, void *__fh, int cmd, void *arg)
-{
-	struct zoran_fh *fh = __fh;
-	struct zoran *zr = fh->zr;
-	struct zoran_jpg_settings settings;
-
-	switch (cmd) {
-	case BUZIOC_G_PARAMS:
-	{
-		struct zoran_params *bparams = arg;
-
-		dprintk(3, KERN_DEBUG "%s: BUZIOC_G_PARAMS\n", ZR_DEVNAME(zr));
-
-		memset(bparams, 0, sizeof(struct zoran_params));
-		bparams->major_version = MAJOR_VERSION;
-		bparams->minor_version = MINOR_VERSION;
-
-		mutex_lock(&zr->resource_lock);
-
-		if (zr->norm & V4L2_STD_NTSC)
-			bparams->norm = ZORAN_VIDMODE_NTSC;
-		else if (zr->norm & V4L2_STD_SECAM)
-			bparams->norm = ZORAN_VIDMODE_SECAM;
-		else
-			bparams->norm = ZORAN_VIDMODE_PAL;
-
-		bparams->input = zr->input;
-
-		bparams->decimation = fh->jpg_settings.decimation;
-		bparams->HorDcm = fh->jpg_settings.HorDcm;
-		bparams->VerDcm = fh->jpg_settings.VerDcm;
-		bparams->TmpDcm = fh->jpg_settings.TmpDcm;
-		bparams->field_per_buff = fh->jpg_settings.field_per_buff;
-		bparams->img_x = fh->jpg_settings.img_x;
-		bparams->img_y = fh->jpg_settings.img_y;
-		bparams->img_width = fh->jpg_settings.img_width;
-		bparams->img_height = fh->jpg_settings.img_height;
-		bparams->odd_even = fh->jpg_settings.odd_even;
-
-		bparams->quality = fh->jpg_settings.jpg_comp.quality;
-		bparams->APPn = fh->jpg_settings.jpg_comp.APPn;
-		bparams->APP_len = fh->jpg_settings.jpg_comp.APP_len;
-		memcpy(bparams->APP_data,
-		       fh->jpg_settings.jpg_comp.APP_data,
-		       sizeof(bparams->APP_data));
-		bparams->COM_len = zr->jpg_settings.jpg_comp.COM_len;
-		memcpy(bparams->COM_data,
-		       fh->jpg_settings.jpg_comp.COM_data,
-		       sizeof(bparams->COM_data));
-		bparams->jpeg_markers =
-		    fh->jpg_settings.jpg_comp.jpeg_markers;
-
-		mutex_unlock(&zr->resource_lock);
-
-		bparams->VFIFO_FB = 0;
-
-		return 0;
-	}
-
-	case BUZIOC_S_PARAMS:
-	{
-		struct zoran_params *bparams = arg;
-		int res = 0;
-
-		dprintk(3, KERN_DEBUG "%s: BUZIOC_S_PARAMS\n", ZR_DEVNAME(zr));
-
-		settings.decimation = bparams->decimation;
-		settings.HorDcm = bparams->HorDcm;
-		settings.VerDcm = bparams->VerDcm;
-		settings.TmpDcm = bparams->TmpDcm;
-		settings.field_per_buff = bparams->field_per_buff;
-		settings.img_x = bparams->img_x;
-		settings.img_y = bparams->img_y;
-		settings.img_width = bparams->img_width;
-		settings.img_height = bparams->img_height;
-		settings.odd_even = bparams->odd_even;
-
-		settings.jpg_comp.quality = bparams->quality;
-		settings.jpg_comp.APPn = bparams->APPn;
-		settings.jpg_comp.APP_len = bparams->APP_len;
-		memcpy(settings.jpg_comp.APP_data, bparams->APP_data,
-		       sizeof(bparams->APP_data));
-		settings.jpg_comp.COM_len = bparams->COM_len;
-		memcpy(settings.jpg_comp.COM_data, bparams->COM_data,
-		       sizeof(bparams->COM_data));
-		settings.jpg_comp.jpeg_markers = bparams->jpeg_markers;
-
-		mutex_lock(&zr->resource_lock);
-
-		if (zr->codec_mode != BUZ_MODE_IDLE) {
-			dprintk(1,
-				KERN_ERR
-				"%s: BUZIOC_S_PARAMS called, but Buz in capture/playback mode\n",
-				ZR_DEVNAME(zr));
-			res = -EINVAL;
-			goto sparams_unlock_and_return;
-		}
-
-		/* Check the params first before overwriting our
-		 * nternal values */
-		if (zoran_check_jpg_settings(zr, &settings, 0)) {
-			res = -EINVAL;
-			goto sparams_unlock_and_return;
-		}
-
-		fh->jpg_settings = settings;
-sparams_unlock_and_return:
-		mutex_unlock(&zr->resource_lock);
-
-		return res;
-	}
-
-	case BUZIOC_REQBUFS:
-	{
-		struct zoran_requestbuffers *breq = arg;
-		int res = 0;
-
-		dprintk(3,
-			KERN_DEBUG
-			"%s: BUZIOC_REQBUFS - count=%lu, size=%lu\n",
-			ZR_DEVNAME(zr), breq->count, breq->size);
-
-		/* Enforce reasonable lower and upper limits */
-		if (breq->count < 4)
-			breq->count = 4;	/* Could be choosen smaller */
-		if (breq->count > jpg_nbufs)
-			breq->count = jpg_nbufs;
-		breq->size = PAGE_ALIGN(breq->size);
-		if (breq->size < 8192)
-			breq->size = 8192;	/* Arbitrary */
-		/* breq->size is limited by 1 page for the stat_com
-		 * tables to a Maximum of 2 MB */
-		if (breq->size > jpg_bufsize)
-			breq->size = jpg_bufsize;
-
-		mutex_lock(&zr->resource_lock);
-
-		if (fh->buffers.allocated) {
-			dprintk(1,
-				KERN_ERR
-				"%s: BUZIOC_REQBUFS - buffers already allocated\n",
-				ZR_DEVNAME(zr));
-			res = -EBUSY;
-			goto jpgreqbuf_unlock_and_return;
-		}
-
-		/* The next mmap will map the MJPEG buffers - could
-		 * also be *_PLAY, but it doesn't matter here */
-		map_mode_jpg(fh, 0);
-		fh->buffers.num_buffers = breq->count;
-		fh->buffers.buffer_size = breq->size;
-
-		if (jpg_fbuffer_alloc(fh)) {
-			res = -ENOMEM;
-			goto jpgreqbuf_unlock_and_return;
-		}
-
-jpgreqbuf_unlock_and_return:
-		mutex_unlock(&zr->resource_lock);
-
-		return res;
-	}
-
-	case BUZIOC_QBUF_CAPT:
-	{
-		int *frame = arg, res;
-
-		dprintk(3, KERN_DEBUG "%s: BUZIOC_QBUF_CAPT - frame=%d\n",
-			ZR_DEVNAME(zr), *frame);
-
-		mutex_lock(&zr->resource_lock);
-		res = jpg_qbuf(fh, *frame, BUZ_MODE_MOTION_COMPRESS);
-		mutex_unlock(&zr->resource_lock);
-
-		return res;
-	}
-
-	case BUZIOC_QBUF_PLAY:
-	{
-		int *frame = arg, res;
-
-		dprintk(3, KERN_DEBUG "%s: BUZIOC_QBUF_PLAY - frame=%d\n",
-			ZR_DEVNAME(zr), *frame);
-
-		mutex_lock(&zr->resource_lock);
-		res = jpg_qbuf(fh, *frame, BUZ_MODE_MOTION_DECOMPRESS);
-		mutex_unlock(&zr->resource_lock);
-
-		return res;
-	}
-
-	case BUZIOC_SYNC:
-	{
-		struct zoran_sync *bsync = arg;
-		int res;
-
-		dprintk(3, KERN_DEBUG "%s: BUZIOC_SYNC\n", ZR_DEVNAME(zr));
-
-		mutex_lock(&zr->resource_lock);
-
-		if (fh->map_mode == ZORAN_MAP_MODE_RAW) {
-			dprintk(2, KERN_WARNING
-				"%s: %s - not in jpg capture mode\n",
-				ZR_DEVNAME(zr), __func__);
-			res = -EINVAL;
-		} else {
-			res = jpg_sync(fh, bsync);
-		}
-		mutex_unlock(&zr->resource_lock);
-
-		return res;
-	}
-
-	case BUZIOC_G_STATUS:
-	{
-		struct zoran_status *bstat = arg;
-		int status = 0, res = 0;
-		v4l2_std_id norm;
-
-		dprintk(3, KERN_DEBUG "%s: BUZIOC_G_STATUS\n", ZR_DEVNAME(zr));
-
-		if (zr->codec_mode != BUZ_MODE_IDLE) {
-			dprintk(1,
-				KERN_ERR
-				"%s: BUZIOC_G_STATUS called but Buz in capture/playback mode\n",
-				ZR_DEVNAME(zr));
-			return -EINVAL;
-		}
-
-		mutex_lock(&zr->resource_lock);
-
-		if (zr->codec_mode != BUZ_MODE_IDLE) {
-			dprintk(1,
-				KERN_ERR
-				"%s: BUZIOC_G_STATUS called, but Buz in capture/playback mode\n",
-				ZR_DEVNAME(zr));
-			res = -EINVAL;
-			goto gstat_unlock_and_return;
-		}
-
-		decoder_call(zr, video, s_routing,
-				zr->card.input[bstat->input].muxsel, 0, 0);
-
-		/* sleep 1 second */
-		ssleep(1);
-
-		/* Get status of video decoder */
-		decoder_call(zr, video, querystd, &norm);
-		decoder_call(zr, video, g_input_status, &status);
-
-		/* restore previous input and norm */
-		decoder_call(zr, video, s_routing,
-				zr->card.input[zr->input].muxsel, 0, 0);
-gstat_unlock_and_return:
-		mutex_unlock(&zr->resource_lock);
-
-		if (!res) {
-			bstat->signal =
-			    (status & V4L2_IN_ST_NO_SIGNAL) ? 0 : 1;
-			if (norm & V4L2_STD_NTSC)
-				bstat->norm = ZORAN_VIDMODE_NTSC;
-			else if (norm & V4L2_STD_SECAM)
-				bstat->norm = ZORAN_VIDMODE_SECAM;
-			else
-				bstat->norm = ZORAN_VIDMODE_PAL;
-
-			bstat->color =
-			    (status & V4L2_IN_ST_NO_COLOR) ? 0 : 1;
-		}
-
-		return res;
-	}
-
-	default:
-		return -EINVAL;
-	}
-}
-
-static int zoran_vidiocgmbuf(struct file *file, void *__fh, struct video_mbuf *vmbuf)
-{
-	struct zoran_fh *fh = __fh;
-	struct zoran *zr = fh->zr;
-	int i, res = 0;
-
-
-	mutex_lock(&zr->resource_lock);
-
-	if (fh->buffers.allocated) {
-		dprintk(1,
-			KERN_ERR
-			"%s: VIDIOCGMBUF - buffers already allocated\n",
-			ZR_DEVNAME(zr));
-		res = -EINVAL;
-		goto v4l1reqbuf_unlock_and_return;
-	}
-
-	/* The next mmap will map the V4L buffers */
-	map_mode_raw(fh);
-
-	if (v4l_fbuffer_alloc(fh)) {
-		res = -ENOMEM;
-		goto v4l1reqbuf_unlock_and_return;
-	}
-
-	vmbuf->size = fh->buffers.num_buffers * fh->buffers.buffer_size;
-	vmbuf->frames = fh->buffers.num_buffers;
-	for (i = 0; i < vmbuf->frames; i++)
-		vmbuf->offsets[i] = i * fh->buffers.buffer_size;
-
-v4l1reqbuf_unlock_and_return:
-	mutex_unlock(&zr->resource_lock);
-
-	return res;
-}
-#endif
-
 static int zoran_querycap(struct file *file, void *__fh, struct v4l2_capability *cap)
 {
 	struct zoran_fh *fh = __fh;
@@ -2533,6 +2216,7 @@ static int zoran_dqbuf(struct file *file
 			res = -EAGAIN;
 			goto dqbuf_unlock_and_return;
 		}
+		bs.frame = 0; /* suppress compiler warning */
 		res = jpg_sync(fh, &bs);
 		if (res)
 			goto dqbuf_unlock_and_return;
@@ -2766,11 +2450,6 @@ static int zoran_enum_input(struct file
 
 	if (inp->index >= zr->card.inputs)
 		return -EINVAL;
-	else {
-		int id = inp->index;
-		memset(inp, 0, sizeof(*inp));
-		inp->index = id;
-	}
 
 	strncpy(inp->name, zr->card.input[inp->index].name,
 		sizeof(inp->name) - 1);
@@ -2820,7 +2499,6 @@ static int zoran_enum_output(struct file
 	if (outp->index != 0)
 		return -EINVAL;
 
-	memset(outp, 0, sizeof(*outp));
 	outp->index = 0;
 	outp->type = V4L2_OUTPUT_TYPE_ANALOGVGAOVERLAY;
 	strncpy(outp->name, "Autodetect", sizeof(outp->name)-1);
@@ -3364,10 +3042,6 @@ static const struct v4l2_ioctl_ops zoran
 	.vidioc_queryctrl 		    = zoran_queryctrl,
 	.vidioc_s_ctrl       		    = zoran_s_ctrl,
 	.vidioc_g_ctrl       		    = zoran_g_ctrl,
-#ifdef CONFIG_VIDEO_V4L1_COMPAT
-	.vidioc_default 		    = zoran_default,
-	.vidiocgmbuf 			    = zoran_vidiocgmbuf,
-#endif
 };
 
 /* please use zr->resource_lock consistently and kill this wrapper */
diff -druNp linux-libre-2.6.37-gnu1/drivers/media/video/zoran/zoran.h linux-libre-2.6.38-gnu1/drivers/media/video/zoran/zoran.h
--- linux-libre-2.6.37-gnu1/drivers/media/video/zoran/zoran.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/media/video/zoran/zoran.h	2011-03-14 21:20:32.000000000 -0400
@@ -33,15 +33,6 @@
 
 #include <media/v4l2-device.h>
 
-#define ZORAN_VIDMODE_PAL	0
-#define ZORAN_VIDMODE_NTSC	1
-#define ZORAN_VIDMODE_SECAM	2
-
-struct zoran_requestbuffers {
-	unsigned long count;	/* Number of buffers for MJPEG grabbing */
-	unsigned long size;	/* Size PER BUFFER in bytes */
-};
-
 struct zoran_sync {
 	unsigned long frame;	/* number of buffer that has been free'd */
 	unsigned long length;	/* number of code bytes in buffer (capture only) */
@@ -49,102 +40,6 @@ struct zoran_sync {
 	struct timeval timestamp;	/* timestamp */
 };
 
-struct zoran_status {
-	int input;		/* Input channel, has to be set prior to BUZIOC_G_STATUS */
-	int signal;		/* Returned: 1 if valid video signal detected */
-	int norm;		/* Returned: ZORAN_VIDMODE_PAL or ZORAN_VIDMODE_NTSC */
-	int color;		/* Returned: 1 if color signal detected */
-};
-
-struct zoran_params {
-
-	/* The following parameters can only be queried */
-
-	int major_version;	/* Major version number of driver */
-	int minor_version;	/* Minor version number of driver */
-
-	/* Main control parameters */
-
-	int input;		/* Input channel: 0 = Composite, 1 = S-VHS */
-	int norm;		/* Norm: ZORAN_VIDMODE_PAL or ZORAN_VIDMODE_NTSC */
-	int decimation;		/* decimation of captured video,
-				 * enlargement of video played back.
-				 * Valid values are 1, 2, 4 or 0.
-				 * 0 is a special value where the user
-				 * has full control over video scaling */
-
-	/* The following parameters only have to be set if decimation==0,
-	 * for other values of decimation they provide the data how the image is captured */
-
-	int HorDcm;		/* Horizontal decimation: 1, 2 or 4 */
-	int VerDcm;		/* Vertical decimation: 1 or 2 */
-	int TmpDcm;		/* Temporal decimation: 1 or 2,
-				 * if TmpDcm==2 in capture every second frame is dropped,
-				 * in playback every frame is played twice */
-	int field_per_buff;	/* Number of fields per buffer: 1 or 2 */
-	int img_x;		/* start of image in x direction */
-	int img_y;		/* start of image in y direction */
-	int img_width;		/* image width BEFORE decimation,
-				 * must be a multiple of HorDcm*16 */
-	int img_height;		/* image height BEFORE decimation,
-				 * must be a multiple of VerDcm*8 */
-
-	/* --- End of parameters for decimation==0 only --- */
-
-	/* JPEG control parameters */
-
-	int quality;		/* Measure for quality of compressed images.
-				 * Scales linearly with the size of the compressed images.
-				 * Must be beetween 0 and 100, 100 is a compression
-				 * ratio of 1:4 */
-
-	int odd_even;		/* Which field should come first ??? */
-
-	int APPn;		/* Number of APP segment to be written, must be 0..15 */
-	int APP_len;		/* Length of data in JPEG APPn segment */
-	char APP_data[60];	/* Data in the JPEG APPn segment. */
-
-	int COM_len;		/* Length of data in JPEG COM segment */
-	char COM_data[60];	/* Data in JPEG COM segment */
-
-	unsigned long jpeg_markers;	/* Which markers should go into the JPEG output.
-					 * Unless you exactly know what you do, leave them untouched.
-					 * Inluding less markers will make the resulting code
-					 * smaller, but there will be fewer applications
-					 * which can read it.
-					 * The presence of the APP and COM marker is
-					 * influenced by APP0_len and COM_len ONLY! */
-#define JPEG_MARKER_DHT (1<<3)	/* Define Huffman Tables */
-#define JPEG_MARKER_DQT (1<<4)	/* Define Quantization Tables */
-#define JPEG_MARKER_DRI (1<<5)	/* Define Restart Interval */
-#define JPEG_MARKER_COM (1<<6)	/* Comment segment */
-#define JPEG_MARKER_APP (1<<7)	/* App segment, driver will allways use APP0 */
-
-	int VFIFO_FB;		/* Flag for enabling Video Fifo Feedback.
-				 * If this flag is turned on and JPEG decompressing
-				 * is going to the screen, the decompress process
-				 * is stopped every time the Video Fifo is full.
-				 * This enables a smooth decompress to the screen
-				 * but the video output signal will get scrambled */
-
-	/* Misc */
-
-	char reserved[312];	/* Makes 512 bytes for this structure */
-};
-
-/*
-Private IOCTL to set up for displaying MJPEG
-*/
-#define BUZIOC_G_PARAMS       _IOR ('v', BASE_VIDIOC_PRIVATE+0,  struct zoran_params)
-#define BUZIOC_S_PARAMS       _IOWR('v', BASE_VIDIOC_PRIVATE+1,  struct zoran_params)
-#define BUZIOC_REQBUFS        _IOWR('v', BASE_VIDIOC_PRIVATE+2,  struct zoran_requestbuffers)
-#define BUZIOC_QBUF_CAPT      _IOW ('v', BASE_VIDIOC_PRIVATE+3,  int)
-#define BUZIOC_QBUF_PLAY      _IOW ('v', BASE_VIDIOC_PRIVATE+4,  int)
-#define BUZIOC_SYNC           _IOR ('v', BASE_VIDIOC_PRIVATE+5,  struct zoran_sync)
-#define BUZIOC_G_STATUS       _IOWR('v', BASE_VIDIOC_PRIVATE+6,  struct zoran_status)
-
-
-#ifdef __KERNEL__
 
 #define MAJOR_VERSION 0		/* driver major version */
 #define MINOR_VERSION 10	/* driver minor version */
@@ -507,6 +402,4 @@ static inline struct zoran *to_zoran(str
 #define btor(dat,adr)       btwrite((dat) | btread(adr), adr)
 #define btaor(dat,mask,adr) btwrite((dat) | ((mask) & btread(adr)), adr)
 
-#endif				/* __kernel__ */
-
 #endif
diff -druNp linux-libre-2.6.37-gnu1/drivers/memstick/core/memstick.c linux-libre-2.6.38-gnu1/drivers/memstick/core/memstick.c
--- linux-libre-2.6.37-gnu1/drivers/memstick/core/memstick.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/memstick/core/memstick.c	2011-03-14 21:20:32.000000000 -0400
@@ -465,6 +465,7 @@ static void memstick_check(struct work_s
 		if (!host->card) {
 			host->card = card;
 			if (device_register(&card->dev)) {
+				put_device(&card->dev);
 				kfree(host->card);
 				host->card = NULL;
 			}
@@ -510,14 +511,18 @@ int memstick_add_host(struct memstick_ho
 {
 	int rc;
 
-	if (!idr_pre_get(&memstick_host_idr, GFP_KERNEL))
-		return -ENOMEM;
+	while (1) {
+		if (!idr_pre_get(&memstick_host_idr, GFP_KERNEL))
+			return -ENOMEM;
 
-	spin_lock(&memstick_host_lock);
-	rc = idr_get_new(&memstick_host_idr, host, &host->id);
-	spin_unlock(&memstick_host_lock);
-	if (rc)
-		return rc;
+		spin_lock(&memstick_host_lock);
+		rc = idr_get_new(&memstick_host_idr, host, &host->id);
+		spin_unlock(&memstick_host_lock);
+		if (!rc)
+			break;
+		else if (rc != -EAGAIN)
+			return rc;
+	}
 
 	dev_set_name(&host->dev, "memstick%u", host->id);
 
@@ -616,7 +621,7 @@ static int __init memstick_init(void)
 {
 	int rc;
 
-	workqueue = create_freezeable_workqueue("kmemstick");
+	workqueue = create_freezable_workqueue("kmemstick");
 	if (!workqueue)
 		return -ENOMEM;
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/memstick/core/mspro_block.c linux-libre-2.6.38-gnu1/drivers/memstick/core/mspro_block.c
--- linux-libre-2.6.37-gnu1/drivers/memstick/core/mspro_block.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/memstick/core/mspro_block.c	2011-03-14 21:20:32.000000000 -0400
@@ -23,7 +23,6 @@
 
 #define DRIVER_NAME "mspro_block"
 
-static DEFINE_MUTEX(mspro_block_mutex);
 static int major;
 module_param(major, int, 0644);
 
@@ -160,6 +159,13 @@ struct mspro_block_data {
 	int                   (*mrq_handler)(struct memstick_dev *card,
 					     struct memstick_request **mrq);
 
+
+	/* Default request setup function for data access method preferred by
+	 * this host instance.
+	 */
+	void                  (*setup_transfer)(struct memstick_dev *card,
+						u64 offset, size_t length);
+
 	struct attribute_group attr_group;
 
 	struct scatterlist    req_sg[MSPRO_BLOCK_MAX_SEGS];
@@ -181,7 +187,6 @@ static int mspro_block_bd_open(struct bl
 	struct mspro_block_data *msb = disk->private_data;
 	int rc = -ENXIO;
 
-	mutex_lock(&mspro_block_mutex);
 	mutex_lock(&mspro_block_disk_lock);
 
 	if (msb && msb->card) {
@@ -193,7 +198,6 @@ static int mspro_block_bd_open(struct bl
 	}
 
 	mutex_unlock(&mspro_block_disk_lock);
-	mutex_unlock(&mspro_block_mutex);
 
 	return rc;
 }
@@ -225,11 +229,7 @@ static int mspro_block_disk_release(stru
 
 static int mspro_block_bd_release(struct gendisk *disk, fmode_t mode)
 {
-	int ret;
-	mutex_lock(&mspro_block_mutex);
-	ret = mspro_block_disk_release(disk);
-	mutex_unlock(&mspro_block_mutex);
-	return ret;
+	return mspro_block_disk_release(disk);
 }
 
 static int mspro_block_bd_getgeo(struct block_device *bdev,
@@ -663,14 +663,43 @@ has_int_reg:
 	}
 }
 
+/*** Transfer setup functions for different access methods. ***/
+
+/** Setup data transfer request for SET_CMD TPC with arguments in card
+ *  registers.
+ *
+ *  @card    Current media instance
+ *  @offset  Target data offset in bytes
+ *  @length  Required transfer length in bytes.
+ */
+static void h_mspro_block_setup_cmd(struct memstick_dev *card, u64 offset,
+				    size_t length)
+{
+	struct mspro_block_data *msb = memstick_get_drvdata(card);
+	struct mspro_param_register param = {
+		.system = msb->system,
+		.data_count = cpu_to_be16((uint16_t)(length / msb->page_size)),
+		/* ISO C90 warning precludes direct initialization for now. */
+		.data_address = 0,
+		.tpc_param = 0
+	};
+
+	do_div(offset, msb->page_size);
+	param.data_address = cpu_to_be32((uint32_t)offset);
+
+	card->next_request = h_mspro_block_req_init;
+	msb->mrq_handler = h_mspro_block_transfer_data;
+	memstick_init_req(&card->current_mrq, MS_TPC_WRITE_REG,
+			  &param, sizeof(param));
+}
+
 /*** Data transfer ***/
 
 static int mspro_block_issue_req(struct memstick_dev *card, int chunk)
 {
 	struct mspro_block_data *msb = memstick_get_drvdata(card);
-	sector_t t_sec;
+	u64 t_off;
 	unsigned int count;
-	struct mspro_param_register param;
 
 try_again:
 	while (chunk) {
@@ -685,30 +714,17 @@ try_again:
 			continue;
 		}
 
-		t_sec = blk_rq_pos(msb->block_req) << 9;
-		sector_div(t_sec, msb->page_size);
-
+		t_off = blk_rq_pos(msb->block_req);
+		t_off <<= 9;
 		count = blk_rq_bytes(msb->block_req);
-		count /= msb->page_size;
 
-		param.system = msb->system;
-		param.data_count = cpu_to_be16(count);
-		param.data_address = cpu_to_be32((uint32_t)t_sec);
-		param.tpc_param = 0;
+		msb->setup_transfer(card, t_off, count);
 
 		msb->data_dir = rq_data_dir(msb->block_req);
 		msb->transfer_cmd = msb->data_dir == READ
 				    ? MSPRO_CMD_READ_DATA
 				    : MSPRO_CMD_WRITE_DATA;
 
-		dev_dbg(&card->dev, "data transfer: cmd %x, "
-			"lba %x, count %x\n", msb->transfer_cmd,
-			be32_to_cpu(param.data_address), count);
-
-		card->next_request = h_mspro_block_req_init;
-		msb->mrq_handler = h_mspro_block_transfer_data;
-		memstick_init_req(&card->current_mrq, MS_TPC_WRITE_REG,
-				  &param, sizeof(param));
 		memstick_new_req(card->host);
 		return 0;
 	}
@@ -963,18 +979,16 @@ try_again:
 static int mspro_block_read_attributes(struct memstick_dev *card)
 {
 	struct mspro_block_data *msb = memstick_get_drvdata(card);
-	struct mspro_param_register param = {
-		.system = msb->system,
-		.data_count = cpu_to_be16(1),
-		.data_address = 0,
-		.tpc_param = 0
-	};
 	struct mspro_attribute *attr = NULL;
 	struct mspro_sys_attr *s_attr = NULL;
 	unsigned char *buffer = NULL;
 	int cnt, rc, attr_count;
-	unsigned int addr;
-	unsigned short page_count;
+	/* While normally physical device offsets, represented here by
+	 * attr_offset and attr_len will be of large numeric types, we can be
+	 * sure, that attributes are close enough to the beginning of the
+	 * device, to save ourselves some trouble.
+	 */
+	unsigned int addr, attr_offset = 0, attr_len = msb->page_size;
 
 	attr = kmalloc(msb->page_size, GFP_KERNEL);
 	if (!attr)
@@ -987,10 +1001,8 @@ static int mspro_block_read_attributes(s
 	msb->data_dir = READ;
 	msb->transfer_cmd = MSPRO_CMD_READ_ATRB;
 
-	card->next_request = h_mspro_block_req_init;
-	msb->mrq_handler = h_mspro_block_transfer_data;
-	memstick_init_req(&card->current_mrq, MS_TPC_WRITE_REG, &param,
-			  sizeof(param));
+	msb->setup_transfer(card, attr_offset, attr_len);
+
 	memstick_new_req(card->host);
 	wait_for_completion(&card->mrq_complete);
 	if (card->current_mrq.error) {
@@ -1021,13 +1033,12 @@ static int mspro_block_read_attributes(s
 	}
 	msb->attr_group.name = "media_attributes";
 
-	buffer = kmalloc(msb->page_size, GFP_KERNEL);
+	buffer = kmalloc(attr_len, GFP_KERNEL);
 	if (!buffer) {
 		rc = -ENOMEM;
 		goto out_free_attr;
 	}
-	memcpy(buffer, (char *)attr, msb->page_size);
-	page_count = 1;
+	memcpy(buffer, (char *)attr, attr_len);
 
 	for (cnt = 0; cnt < attr_count; ++cnt) {
 		s_attr = kzalloc(sizeof(struct mspro_sys_attr), GFP_KERNEL);
@@ -1038,9 +1049,10 @@ static int mspro_block_read_attributes(s
 
 		msb->attr_group.attrs[cnt] = &s_attr->dev_attr.attr;
 		addr = be32_to_cpu(attr->entries[cnt].address);
-		rc = be32_to_cpu(attr->entries[cnt].size);
+		s_attr->size = be32_to_cpu(attr->entries[cnt].size);
 		dev_dbg(&card->dev, "adding attribute %d: id %x, address %x, "
-			"size %x\n", cnt, attr->entries[cnt].id, addr, rc);
+			"size %zx\n", cnt, attr->entries[cnt].id, addr,
+			s_attr->size);
 		s_attr->id = attr->entries[cnt].id;
 		if (mspro_block_attr_name(s_attr->id))
 			snprintf(s_attr->name, sizeof(s_attr->name), "%s",
@@ -1054,57 +1066,47 @@ static int mspro_block_read_attributes(s
 		s_attr->dev_attr.attr.mode = S_IRUGO;
 		s_attr->dev_attr.show = mspro_block_attr_show(s_attr->id);
 
-		if (!rc)
+		if (!s_attr->size)
 			continue;
 
-		s_attr->size = rc;
-		s_attr->data = kmalloc(rc, GFP_KERNEL);
+		s_attr->data = kmalloc(s_attr->size, GFP_KERNEL);
 		if (!s_attr->data) {
 			rc = -ENOMEM;
 			goto out_free_buffer;
 		}
 
-		if (((addr / msb->page_size)
-		     == be32_to_cpu(param.data_address))
-		    && (((addr + rc - 1) / msb->page_size)
-			== be32_to_cpu(param.data_address))) {
+		if (((addr / msb->page_size) == (attr_offset / msb->page_size))
+		    && (((addr + s_attr->size - 1) / msb->page_size)
+			== (attr_offset / msb->page_size))) {
 			memcpy(s_attr->data, buffer + addr % msb->page_size,
-			       rc);
+			       s_attr->size);
 			continue;
 		}
 
-		if (page_count <= (rc / msb->page_size)) {
+		attr_offset = (addr / msb->page_size) * msb->page_size;
+
+		if ((attr_offset + attr_len) < (addr + s_attr->size)) {
 			kfree(buffer);
-			page_count = (rc / msb->page_size) + 1;
-			buffer = kmalloc(page_count * msb->page_size,
-					 GFP_KERNEL);
+			attr_len = (((addr + s_attr->size) / msb->page_size)
+				    + 1 ) * msb->page_size - attr_offset;
+			buffer = kmalloc(attr_len, GFP_KERNEL);
 			if (!buffer) {
 				rc = -ENOMEM;
 				goto out_free_attr;
 			}
 		}
 
-		param.system = msb->system;
-		param.data_count = cpu_to_be16((rc / msb->page_size) + 1);
-		param.data_address = cpu_to_be32(addr / msb->page_size);
-		param.tpc_param = 0;
-
-		sg_init_one(&msb->req_sg[0], buffer,
-			    be16_to_cpu(param.data_count) * msb->page_size);
+		sg_init_one(&msb->req_sg[0], buffer, attr_len);
 		msb->seg_count = 1;
 		msb->current_seg = 0;
 		msb->current_page = 0;
 		msb->data_dir = READ;
 		msb->transfer_cmd = MSPRO_CMD_READ_ATRB;
 
-		dev_dbg(&card->dev, "reading attribute pages %x, %x\n",
-			be32_to_cpu(param.data_address),
-			be16_to_cpu(param.data_count));
+		dev_dbg(&card->dev, "reading attribute range %x, %x\n",
+			attr_offset, attr_len);
 
-		card->next_request = h_mspro_block_req_init;
-		msb->mrq_handler = h_mspro_block_transfer_data;
-		memstick_init_req(&card->current_mrq, MS_TPC_WRITE_REG,
-				  (char *)&param, sizeof(param));
+		msb->setup_transfer(card, attr_offset, attr_len);
 		memstick_new_req(card->host);
 		wait_for_completion(&card->mrq_complete);
 		if (card->current_mrq.error) {
@@ -1112,7 +1114,8 @@ static int mspro_block_read_attributes(s
 			goto out_free_buffer;
 		}
 
-		memcpy(s_attr->data, buffer + addr % msb->page_size, rc);
+		memcpy(s_attr->data, buffer + addr % msb->page_size,
+		       s_attr->size);
 	}
 
 	rc = 0;
@@ -1130,6 +1133,8 @@ static int mspro_block_init_card(struct
 	int rc = 0;
 
 	msb->system = MEMSTICK_SYS_SERIAL;
+	msb->setup_transfer = h_mspro_block_setup_cmd;
+
 	card->reg_addr.r_offset = offsetof(struct mspro_register, status);
 	card->reg_addr.r_length = sizeof(struct ms_status_register);
 	card->reg_addr.w_offset = offsetof(struct mspro_register, param);
@@ -1206,10 +1211,12 @@ static int mspro_block_init_disk(struct
 
 	msb->page_size = be16_to_cpu(sys_info->unit_size);
 
-	if (!idr_pre_get(&mspro_block_disk_idr, GFP_KERNEL))
+	mutex_lock(&mspro_block_disk_lock);
+	if (!idr_pre_get(&mspro_block_disk_idr, GFP_KERNEL)) {
+		mutex_unlock(&mspro_block_disk_lock);
 		return -ENOMEM;
+	}
 
-	mutex_lock(&mspro_block_disk_lock);
 	rc = idr_get_new(&mspro_block_disk_idr, card, &disk_id);
 	mutex_unlock(&mspro_block_disk_lock);
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/memstick/host/jmb38x_ms.c linux-libre-2.6.38-gnu1/drivers/memstick/host/jmb38x_ms.c
--- linux-libre-2.6.37-gnu1/drivers/memstick/host/jmb38x_ms.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/memstick/host/jmb38x_ms.c	2011-03-14 21:20:32.000000000 -0400
@@ -61,6 +61,7 @@ struct jmb38x_ms_host {
 	struct memstick_request *req;
 	unsigned char           cmd_flags;
 	unsigned char           io_pos;
+	unsigned char           ifmode;
 	unsigned int            io_word[2];
 };
 
@@ -136,15 +137,14 @@ struct jmb38x_ms {
 #define PAD_PU_PD_ON_MS_SOCK0 0x5f8f0000
 #define PAD_PU_PD_ON_MS_SOCK1 0x0f0f0000
 
+#define CLOCK_CONTROL_BY_MMIO 0x00000008
 #define CLOCK_CONTROL_40MHZ   0x00000001
-#define CLOCK_CONTROL_50MHZ   0x0000000a
-#define CLOCK_CONTROL_60MHZ   0x00000008
-#define CLOCK_CONTROL_62_5MHZ 0x0000000c
+#define CLOCK_CONTROL_50MHZ   0x00000002
+#define CLOCK_CONTROL_60MHZ   0x00000010
+#define CLOCK_CONTROL_62_5MHZ 0x00000004
 #define CLOCK_CONTROL_OFF     0x00000000
 
 #define PCI_CTL_CLOCK_DLY_ADDR   0x000000b0
-#define PCI_CTL_CLOCK_DLY_MASK_A 0x00000f00
-#define PCI_CTL_CLOCK_DLY_MASK_B 0x0000f000
 
 enum {
 	CMD_READY    = 0x01,
@@ -390,8 +390,13 @@ static int jmb38x_ms_issue_cmd(struct me
 
 	if (host->req->data_dir == READ)
 		cmd |= TPC_DIR;
-	if (host->req->need_card_int)
-		cmd |= TPC_WAIT_INT;
+
+	if (host->req->need_card_int) {
+		if (host->ifmode == MEMSTICK_SERIAL)
+			cmd |= TPC_GET_INT;
+		else
+			cmd |= TPC_WAIT_INT;
+	}
 
 	data = host->req->data;
 
@@ -529,7 +534,10 @@ static irqreturn_t jmb38x_ms_isr(int irq
 		if (irq_status & INT_STATUS_ANY_ERR) {
 			if (irq_status & INT_STATUS_CRC_ERR)
 				host->req->error = -EILSEQ;
-			else
+			else if (irq_status & INT_STATUS_TPC_ERR) {
+				dev_dbg(&host->chip->pdev->dev, "TPC_ERR\n");
+				jmb38x_ms_complete_cmd(msh, 0);
+			} else
 				host->req->error = -ETIME;
 		} else {
 			if (host->cmd_flags & DMA_DATA) {
@@ -644,7 +652,6 @@ static int jmb38x_ms_reset(struct jmb38x
 		ndelay(20);
 	}
 	dev_dbg(&host->chip->pdev->dev, "reset_req timeout\n");
-	/* return -EIO; */
 
 reset_next:
 	writel(HOST_CONTROL_RESET | HOST_CONTROL_CLOCK_EN
@@ -675,7 +682,7 @@ static int jmb38x_ms_set_param(struct me
 {
 	struct jmb38x_ms_host *host = memstick_priv(msh);
 	unsigned int host_ctl = readl(host->addr + HOST_CONTROL);
-	unsigned int clock_ctl = CLOCK_CONTROL_40MHZ, clock_delay = 0;
+	unsigned int clock_ctl = CLOCK_CONTROL_BY_MMIO, clock_delay = 0;
 	int rc = 0;
 
 	switch (param) {
@@ -687,9 +694,7 @@ static int jmb38x_ms_set_param(struct me
 
 			host_ctl = 7;
 			host_ctl |= HOST_CONTROL_POWER_EN
-				    | HOST_CONTROL_CLOCK_EN
-				    | HOST_CONTROL_HW_OC_P
-				    | HOST_CONTROL_TDELAY_EN;
+				 | HOST_CONTROL_CLOCK_EN;
 			writel(host_ctl, host->addr + HOST_CONTROL);
 
 			writel(host->id ? PAD_PU_PD_ON_MS_SOCK1
@@ -712,46 +717,88 @@ static int jmb38x_ms_set_param(struct me
 			return -EINVAL;
 		break;
 	case MEMSTICK_INTERFACE:
+		dev_dbg(&host->chip->pdev->dev,
+			"Set Host Interface Mode to %d\n", value);
+		host_ctl &= ~(HOST_CONTROL_FAST_CLK | HOST_CONTROL_REI |
+			      HOST_CONTROL_REO);
+		host_ctl |= HOST_CONTROL_TDELAY_EN | HOST_CONTROL_HW_OC_P;
 		host_ctl &= ~(3 << HOST_CONTROL_IF_SHIFT);
-		pci_read_config_dword(host->chip->pdev,
-				      PCI_CTL_CLOCK_DLY_ADDR,
-				      &clock_delay);
-		clock_delay &= host->id ? ~PCI_CTL_CLOCK_DLY_MASK_B
-					: ~PCI_CTL_CLOCK_DLY_MASK_A;
 
 		if (value == MEMSTICK_SERIAL) {
-			host_ctl &= ~HOST_CONTROL_FAST_CLK;
-			host_ctl &= ~HOST_CONTROL_REO;
 			host_ctl |= HOST_CONTROL_IF_SERIAL
 				    << HOST_CONTROL_IF_SHIFT;
 			host_ctl |= HOST_CONTROL_REI;
-			clock_ctl = CLOCK_CONTROL_40MHZ;
+			clock_ctl |= CLOCK_CONTROL_40MHZ;
+			clock_delay = 0;
 		} else if (value == MEMSTICK_PAR4) {
-			host_ctl |= HOST_CONTROL_FAST_CLK | HOST_CONTROL_REO;
+			host_ctl |= HOST_CONTROL_FAST_CLK;
 			host_ctl |= HOST_CONTROL_IF_PAR4
 				    << HOST_CONTROL_IF_SHIFT;
-			host_ctl &= ~HOST_CONTROL_REI;
-			clock_ctl = CLOCK_CONTROL_40MHZ;
-			clock_delay |= host->id ? (4 << 12) : (4 << 8);
+			host_ctl |= HOST_CONTROL_REO;
+			clock_ctl |= CLOCK_CONTROL_40MHZ;
+			clock_delay = 4;
 		} else if (value == MEMSTICK_PAR8) {
 			host_ctl |= HOST_CONTROL_FAST_CLK;
 			host_ctl |= HOST_CONTROL_IF_PAR8
 				    << HOST_CONTROL_IF_SHIFT;
-			host_ctl &= ~(HOST_CONTROL_REI | HOST_CONTROL_REO);
-			clock_ctl = CLOCK_CONTROL_50MHZ;
+			clock_ctl |= CLOCK_CONTROL_50MHZ;
+			clock_delay = 0;
 		} else
 			return -EINVAL;
 
 		writel(host_ctl, host->addr + HOST_CONTROL);
+		writel(CLOCK_CONTROL_OFF, host->addr + CLOCK_CONTROL);
 		writel(clock_ctl, host->addr + CLOCK_CONTROL);
-		pci_write_config_dword(host->chip->pdev,
-				       PCI_CTL_CLOCK_DLY_ADDR,
-				       clock_delay);
+		pci_write_config_byte(host->chip->pdev,
+				      PCI_CTL_CLOCK_DLY_ADDR + 1,
+				      clock_delay);
+		host->ifmode = value;
 		break;
 	};
 	return 0;
 }
 
+#define PCI_PMOS0_CONTROL		0xae
+#define  PMOS0_ENABLE			0x01
+#define  PMOS0_OVERCURRENT_LEVEL_2_4V	0x06
+#define  PMOS0_EN_OVERCURRENT_DEBOUNCE	0x40
+#define  PMOS0_SW_LED_POLARITY_ENABLE	0x80
+#define  PMOS0_ACTIVE_BITS (PMOS0_ENABLE | PMOS0_EN_OVERCURRENT_DEBOUNCE | \
+			    PMOS0_OVERCURRENT_LEVEL_2_4V)
+#define PCI_PMOS1_CONTROL		0xbd
+#define  PMOS1_ACTIVE_BITS		0x4a
+#define PCI_CLOCK_CTL			0xb9
+
+static int jmb38x_ms_pmos(struct pci_dev *pdev, int flag)
+{
+	unsigned char val;
+
+	pci_read_config_byte(pdev, PCI_PMOS0_CONTROL, &val);
+	if (flag)
+		val |= PMOS0_ACTIVE_BITS;
+	else
+		val &= ~PMOS0_ACTIVE_BITS;
+	pci_write_config_byte(pdev, PCI_PMOS0_CONTROL, val);
+	dev_dbg(&pdev->dev, "JMB38x: set PMOS0 val 0x%x\n", val);
+
+	if (pci_resource_flags(pdev, 1)) {
+		pci_read_config_byte(pdev, PCI_PMOS1_CONTROL, &val);
+		if (flag)
+			val |= PMOS1_ACTIVE_BITS;
+		else
+			val &= ~PMOS1_ACTIVE_BITS;
+		pci_write_config_byte(pdev, PCI_PMOS1_CONTROL, val);
+		dev_dbg(&pdev->dev, "JMB38x: set PMOS1 val 0x%x\n", val);
+	}
+
+	pci_read_config_byte(pdev, PCI_CLOCK_CTL, &val);
+	pci_write_config_byte(pdev, PCI_CLOCK_CTL, val & ~0x0f);
+	pci_write_config_byte(pdev, PCI_CLOCK_CTL, val | 0x01);
+	dev_dbg(&pdev->dev, "Clock Control by PCI config is disabled!\n");
+
+        return 0;
+}
+
 #ifdef CONFIG_PM
 
 static int jmb38x_ms_suspend(struct pci_dev *dev, pm_message_t state)
@@ -784,8 +831,7 @@ static int jmb38x_ms_resume(struct pci_d
 		return rc;
 	pci_set_master(dev);
 
-	pci_read_config_dword(dev, 0xac, &rc);
-	pci_write_config_dword(dev, 0xac, rc | 0x00470000);
+	jmb38x_ms_pmos(dev, 1);
 
 	for (rc = 0; rc < jm->host_cnt; ++rc) {
 		if (!jm->hosts[rc])
@@ -894,8 +940,7 @@ static int jmb38x_ms_probe(struct pci_de
 		goto err_out;
 	}
 
-	pci_read_config_dword(pdev, 0xac, &rc);
-	pci_write_config_dword(pdev, 0xac, rc | 0x00470000);
+	jmb38x_ms_pmos(pdev, 1);
 
 	cnt = jmb38x_ms_count_slots(pdev);
 	if (!cnt) {
@@ -976,6 +1021,8 @@ static void jmb38x_ms_remove(struct pci_
 		jmb38x_ms_free_host(jm->hosts[cnt]);
 	}
 
+	jmb38x_ms_pmos(dev, 0);
+
 	pci_set_drvdata(dev, NULL);
 	pci_release_regions(dev);
 	pci_disable_device(dev);
@@ -983,8 +1030,9 @@ static void jmb38x_ms_remove(struct pci_
 }
 
 static struct pci_device_id jmb38x_ms_id_tbl [] = {
-	{ PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB38X_MS, PCI_ANY_ID,
-	  PCI_ANY_ID, 0, 0, 0 },
+	{ PCI_VDEVICE(JMICRON, PCI_DEVICE_ID_JMICRON_JMB38X_MS) },
+	{ PCI_VDEVICE(JMICRON, PCI_DEVICE_ID_JMICRON_JMB385_MS) },
+	{ PCI_VDEVICE(JMICRON, PCI_DEVICE_ID_JMICRON_JMB390_MS) },
 	{ }
 };
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/message/fusion/lsi/mpi_log_sas.h linux-libre-2.6.38-gnu1/drivers/message/fusion/lsi/mpi_log_sas.h
--- linux-libre-2.6.37-gnu1/drivers/message/fusion/lsi/mpi_log_sas.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/message/fusion/lsi/mpi_log_sas.h	2011-03-14 21:20:32.000000000 -0400
@@ -268,7 +268,7 @@
 
 /* Compatibility Error : IR Disabled */
 #define IR_LOGINFO_COMPAT_ERROR_RAID_DISABLED                  (0x00010030)
-/* Compatibility Error : Inquiry Comand failed */
+/* Compatibility Error : Inquiry Command failed */
 #define IR_LOGINFO_COMPAT_ERROR_INQUIRY_FAILED                 (0x00010031)
 /* Compatibility Error : Device not direct access device */
 #define IR_LOGINFO_COMPAT_ERROR_NOT_DIRECT_ACCESS              (0x00010032)
diff -druNp linux-libre-2.6.37-gnu1/drivers/message/fusion/mptbase.c linux-libre-2.6.38-gnu1/drivers/message/fusion/mptbase.c
--- linux-libre-2.6.37-gnu1/drivers/message/fusion/mptbase.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/message/fusion/mptbase.c	2011-03-14 21:20:32.000000000 -0400
@@ -7977,7 +7977,7 @@ mpt_spi_log_info(MPT_ADAPTER *ioc, u32 l
 		NULL,						/* 2Eh */
 		NULL,						/* 2Fh */
 		"Compatibility Error: IR Disabled",		/* 30h */
-		"Compatibility Error: Inquiry Comand Failed",	/* 31h */
+		"Compatibility Error: Inquiry Command Failed",	/* 31h */
 		"Compatibility Error: Device not Direct Access "
 		    "Device ",					/* 32h */
 		"Compatibility Error: Removable Device Found",	/* 33h */
diff -druNp linux-libre-2.6.37-gnu1/drivers/message/fusion/mptbase.h linux-libre-2.6.38-gnu1/drivers/message/fusion/mptbase.h
--- linux-libre-2.6.37-gnu1/drivers/message/fusion/mptbase.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/message/fusion/mptbase.h	2011-03-14 21:20:32.000000000 -0400
@@ -76,8 +76,8 @@
 #define COPYRIGHT	"Copyright (c) 1999-2008 " MODULEAUTHOR
 #endif
 
-#define MPT_LINUX_VERSION_COMMON	"3.04.17"
-#define MPT_LINUX_PACKAGE_NAME		"@(#)mptlinux-3.04.17"
+#define MPT_LINUX_VERSION_COMMON	"3.04.18"
+#define MPT_LINUX_PACKAGE_NAME		"@(#)mptlinux-3.04.18"
 #define WHAT_MAGIC_STRING		"@" "(" "#" ")"
 
 #define show_mptmod_ver(s,ver)  \
diff -druNp linux-libre-2.6.37-gnu1/drivers/message/fusion/mptctl.c linux-libre-2.6.38-gnu1/drivers/message/fusion/mptctl.c
--- linux-libre-2.6.37-gnu1/drivers/message/fusion/mptctl.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/message/fusion/mptctl.c	2011-03-14 21:20:32.000000000 -0400
@@ -597,6 +597,13 @@ mptctl_event_process(MPT_ADAPTER *ioc, E
 }
 
 static int
+mptctl_release(struct inode *inode, struct file *filep)
+{
+	fasync_helper(-1, filep, 0, &async_queue);
+	return 0;
+}
+
+static int
 mptctl_fasync(int fd, struct file *filep, int mode)
 {
 	MPT_ADAPTER	*ioc;
@@ -2815,6 +2822,7 @@ static const struct file_operations mptc
 	.llseek =	no_llseek,
 	.fasync = 	mptctl_fasync,
 	.unlocked_ioctl = mptctl_ioctl,
+	.release =	mptctl_release,
 #ifdef CONFIG_COMPAT
 	.compat_ioctl = compat_mpctl_ioctl,
 #endif
diff -druNp linux-libre-2.6.37-gnu1/drivers/message/fusion/mptsas.c linux-libre-2.6.38-gnu1/drivers/message/fusion/mptsas.c
--- linux-libre-2.6.37-gnu1/drivers/message/fusion/mptsas.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/message/fusion/mptsas.c	2011-03-14 21:20:32.000000000 -0400
@@ -1146,7 +1146,7 @@ mptsas_target_reset_queue(MPT_ADAPTER *i
  *
  * This function will delete scheduled target reset from the list and
  * try to send next target reset. This will be called from completion
- * context of any Task managment command.
+ * context of any Task management command.
  */
 
 void
diff -druNp linux-libre-2.6.37-gnu1/drivers/message/fusion/mptscsih.c linux-libre-2.6.38-gnu1/drivers/message/fusion/mptscsih.c
--- linux-libre-2.6.37-gnu1/drivers/message/fusion/mptscsih.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/message/fusion/mptscsih.c	2011-03-14 21:20:32.000000000 -0400
@@ -1873,8 +1873,9 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
 	}
 
  out:
-	printk(MYIOC_s_INFO_FMT "task abort: %s (sc=%p)\n",
-	    ioc->name, ((retval == SUCCESS) ? "SUCCESS" : "FAILED"), SCpnt);
+	printk(MYIOC_s_INFO_FMT "task abort: %s (rv=%04x) (sc=%p) (sn=%ld)\n",
+	    ioc->name, ((retval == SUCCESS) ? "SUCCESS" : "FAILED"), retval,
+	    SCpnt, SCpnt->serial_number);
 
 	return retval;
 }
@@ -1911,7 +1912,7 @@ mptscsih_dev_reset(struct scsi_cmnd * SC
 
 	vdevice = SCpnt->device->hostdata;
 	if (!vdevice || !vdevice->vtarget) {
-		retval = SUCCESS;
+		retval = 0;
 		goto out;
 	}
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/message/i2o/i2o_block.c linux-libre-2.6.38-gnu1/drivers/message/i2o/i2o_block.c
--- linux-libre-2.6.37-gnu1/drivers/message/i2o/i2o_block.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/message/i2o/i2o_block.c	2011-03-14 21:20:32.000000000 -0400
@@ -309,7 +309,7 @@ static inline void i2o_block_request_fre
  *	@ireq: I2O block request
  *	@mptr: message body pointer
  *
- *	Builds the SG list and map it to be accessable by the controller.
+ *	Builds the SG list and map it to be accessible by the controller.
  *
  *	Returns 0 on failure or 1 on success.
  */
diff -druNp linux-libre-2.6.37-gnu1/drivers/mfd/88pm860x-core.c linux-libre-2.6.38-gnu1/drivers/mfd/88pm860x-core.c
--- linux-libre-2.6.37-gnu1/drivers/mfd/88pm860x-core.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mfd/88pm860x-core.c	2011-03-14 21:20:32.000000000 -0400
@@ -361,12 +361,6 @@ static struct pm860x_irq_data pm860x_irq
 	},
 };
 
-static inline struct pm860x_irq_data *irq_to_pm860x(struct pm860x_chip *chip,
-						    int irq)
-{
-	return &pm860x_irqs[irq - chip->irq_base];
-}
-
 static irqreturn_t pm860x_irq(int irq, void *data)
 {
 	struct pm860x_chip *chip = data;
@@ -388,16 +382,16 @@ static irqreturn_t pm860x_irq(int irq, v
 	return IRQ_HANDLED;
 }
 
-static void pm860x_irq_lock(unsigned int irq)
+static void pm860x_irq_lock(struct irq_data *data)
 {
-	struct pm860x_chip *chip = get_irq_chip_data(irq);
+	struct pm860x_chip *chip = irq_data_get_irq_chip_data(data);
 
 	mutex_lock(&chip->irq_lock);
 }
 
-static void pm860x_irq_sync_unlock(unsigned int irq)
+static void pm860x_irq_sync_unlock(struct irq_data *data)
 {
-	struct pm860x_chip *chip = get_irq_chip_data(irq);
+	struct pm860x_chip *chip = irq_data_get_irq_chip_data(data);
 	struct pm860x_irq_data *irq_data;
 	struct i2c_client *i2c;
 	static unsigned char cached[3] = {0x0, 0x0, 0x0};
@@ -439,25 +433,25 @@ static void pm860x_irq_sync_unlock(unsig
 	mutex_unlock(&chip->irq_lock);
 }
 
-static void pm860x_irq_enable(unsigned int irq)
+static void pm860x_irq_enable(struct irq_data *data)
 {
-	struct pm860x_chip *chip = get_irq_chip_data(irq);
-	pm860x_irqs[irq - chip->irq_base].enable
-		= pm860x_irqs[irq - chip->irq_base].offs;
+	struct pm860x_chip *chip = irq_data_get_irq_chip_data(data);
+	pm860x_irqs[data->irq - chip->irq_base].enable
+		= pm860x_irqs[data->irq - chip->irq_base].offs;
 }
 
-static void pm860x_irq_disable(unsigned int irq)
+static void pm860x_irq_disable(struct irq_data *data)
 {
-	struct pm860x_chip *chip = get_irq_chip_data(irq);
-	pm860x_irqs[irq - chip->irq_base].enable = 0;
+	struct pm860x_chip *chip = irq_data_get_irq_chip_data(data);
+	pm860x_irqs[data->irq - chip->irq_base].enable = 0;
 }
 
 static struct irq_chip pm860x_irq_chip = {
 	.name		= "88pm860x",
-	.bus_lock	= pm860x_irq_lock,
-	.bus_sync_unlock = pm860x_irq_sync_unlock,
-	.enable		= pm860x_irq_enable,
-	.disable	= pm860x_irq_disable,
+	.irq_bus_lock	= pm860x_irq_lock,
+	.irq_bus_sync_unlock = pm860x_irq_sync_unlock,
+	.irq_enable	= pm860x_irq_enable,
+	.irq_disable	= pm860x_irq_disable,
 };
 
 static int __devinit device_gpadc_init(struct pm860x_chip *chip,
diff -druNp linux-libre-2.6.37-gnu1/drivers/mfd/ab3550-core.c linux-libre-2.6.38-gnu1/drivers/mfd/ab3550-core.c
--- linux-libre-2.6.37-gnu1/drivers/mfd/ab3550-core.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mfd/ab3550-core.c	2011-03-14 21:20:32.000000000 -0400
@@ -1159,15 +1159,16 @@ static void ab3550_mask_work(struct work
 	}
 }
 
-static void ab3550_mask(unsigned int irq)
+static void ab3550_mask(struct irq_data *data)
 {
 	unsigned long flags;
 	struct ab3550 *ab;
 	struct ab3550_platform_data *plf_data;
+	int irq;
 
-	ab = get_irq_chip_data(irq);
+	ab = irq_data_get_irq_chip_data(data);
 	plf_data = ab->i2c_client[0]->dev.platform_data;
-	irq -= plf_data->irq.base;
+	irq = data->irq - plf_data->irq.base;
 
 	spin_lock_irqsave(&ab->event_lock, flags);
 	ab->event_mask[irq / 8] |= BIT(irq % 8);
@@ -1176,15 +1177,16 @@ static void ab3550_mask(unsigned int irq
 	schedule_work(&ab->mask_work);
 }
 
-static void ab3550_unmask(unsigned int irq)
+static void ab3550_unmask(struct irq_data *data)
 {
 	unsigned long flags;
 	struct ab3550 *ab;
 	struct ab3550_platform_data *plf_data;
+	int irq;
 
-	ab = get_irq_chip_data(irq);
+	ab = irq_data_get_irq_chip_data(data);
 	plf_data = ab->i2c_client[0]->dev.platform_data;
-	irq -= plf_data->irq.base;
+	irq = data->irq - plf_data->irq.base;
 
 	spin_lock_irqsave(&ab->event_lock, flags);
 	ab->event_mask[irq / 8] &= ~BIT(irq % 8);
@@ -1193,20 +1195,16 @@ static void ab3550_unmask(unsigned int i
 	schedule_work(&ab->mask_work);
 }
 
-static void noop(unsigned int irq)
+static void noop(struct irq_data *data)
 {
 }
 
 static struct irq_chip ab3550_irq_chip = {
 	.name		= "ab3550-core", /* Keep the same name as the request */
-	.startup	= NULL, /* defaults to enable */
-	.shutdown	= NULL, /* defaults to disable */
-	.enable		= NULL, /* defaults to unmask */
-	.disable	= ab3550_mask, /* No default to mask in chip.c */
-	.ack		= noop,
-	.mask		= ab3550_mask,
-	.unmask		= ab3550_unmask,
-	.end		= NULL,
+	.irq_disable	= ab3550_mask, /* No default to mask in chip.c */
+	.irq_ack	= noop,
+	.irq_mask	= ab3550_mask,
+	.irq_unmask	= ab3550_unmask,
 };
 
 struct ab_family_id {
diff -druNp linux-libre-2.6.37-gnu1/drivers/mfd/ab8500-core.c linux-libre-2.6.38-gnu1/drivers/mfd/ab8500-core.c
--- linux-libre-2.6.37-gnu1/drivers/mfd/ab8500-core.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mfd/ab8500-core.c	2011-03-14 21:20:32.000000000 -0400
@@ -52,6 +52,7 @@
 #define AB8500_IT_LATCH8_REG		0x27
 #define AB8500_IT_LATCH9_REG		0x28
 #define AB8500_IT_LATCH10_REG		0x29
+#define AB8500_IT_LATCH12_REG		0x2B
 #define AB8500_IT_LATCH19_REG		0x32
 #define AB8500_IT_LATCH20_REG		0x33
 #define AB8500_IT_LATCH21_REG		0x34
@@ -98,13 +99,17 @@
  * offset 0.
  */
 static const int ab8500_irq_regoffset[AB8500_NUM_IRQ_REGS] = {
-	0, 1, 2, 3, 4, 6, 7, 8, 9, 18, 19, 20, 21,
+	0, 1, 2, 3, 4, 6, 7, 8, 9, 11, 18, 19, 20, 21,
 };
 
 static int ab8500_get_chip_id(struct device *dev)
 {
-	struct ab8500 *ab8500 = dev_get_drvdata(dev->parent);
-	return (int)ab8500->chip_id;
+	struct ab8500 *ab8500;
+
+	if (!dev)
+		return -EINVAL;
+	ab8500 = dev_get_drvdata(dev->parent);
+	return ab8500 ? (int)ab8500->chip_id : -EINVAL;
 }
 
 static int set_register_interruptible(struct ab8500 *ab8500, u8 bank,
@@ -228,16 +233,16 @@ static struct abx500_ops ab8500_ops = {
 	.startup_irq_enabled = NULL,
 };
 
-static void ab8500_irq_lock(unsigned int irq)
+static void ab8500_irq_lock(struct irq_data *data)
 {
-	struct ab8500 *ab8500 = get_irq_chip_data(irq);
+	struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data);
 
 	mutex_lock(&ab8500->irq_lock);
 }
 
-static void ab8500_irq_sync_unlock(unsigned int irq)
+static void ab8500_irq_sync_unlock(struct irq_data *data)
 {
-	struct ab8500 *ab8500 = get_irq_chip_data(irq);
+	struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data);
 	int i;
 
 	for (i = 0; i < AB8500_NUM_IRQ_REGS; i++) {
@@ -248,6 +253,10 @@ static void ab8500_irq_sync_unlock(unsig
 		if (new == old)
 			continue;
 
+		/* Interrupt register 12 does'nt exist prior to version 0x20 */
+		if (ab8500_irq_regoffset[i] == 11 && ab8500->chip_id < 0x20)
+			continue;
+
 		ab8500->oldmask[i] = new;
 
 		reg = AB8500_IT_MASK1_REG + ab8500_irq_regoffset[i];
@@ -257,20 +266,20 @@ static void ab8500_irq_sync_unlock(unsig
 	mutex_unlock(&ab8500->irq_lock);
 }
 
-static void ab8500_irq_mask(unsigned int irq)
+static void ab8500_irq_mask(struct irq_data *data)
 {
-	struct ab8500 *ab8500 = get_irq_chip_data(irq);
-	int offset = irq - ab8500->irq_base;
+	struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data);
+	int offset = data->irq - ab8500->irq_base;
 	int index = offset / 8;
 	int mask = 1 << (offset % 8);
 
 	ab8500->mask[index] |= mask;
 }
 
-static void ab8500_irq_unmask(unsigned int irq)
+static void ab8500_irq_unmask(struct irq_data *data)
 {
-	struct ab8500 *ab8500 = get_irq_chip_data(irq);
-	int offset = irq - ab8500->irq_base;
+	struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data);
+	int offset = data->irq - ab8500->irq_base;
 	int index = offset / 8;
 	int mask = 1 << (offset % 8);
 
@@ -279,10 +288,10 @@ static void ab8500_irq_unmask(unsigned i
 
 static struct irq_chip ab8500_irq_chip = {
 	.name			= "ab8500",
-	.bus_lock		= ab8500_irq_lock,
-	.bus_sync_unlock	= ab8500_irq_sync_unlock,
-	.mask			= ab8500_irq_mask,
-	.unmask			= ab8500_irq_unmask,
+	.irq_bus_lock		= ab8500_irq_lock,
+	.irq_bus_sync_unlock	= ab8500_irq_sync_unlock,
+	.irq_mask		= ab8500_irq_mask,
+	.irq_unmask		= ab8500_irq_unmask,
 };
 
 static irqreturn_t ab8500_irq(int irq, void *dev)
@@ -297,6 +306,10 @@ static irqreturn_t ab8500_irq(int irq, v
 		int status;
 		u8 value;
 
+		/* Interrupt register 12 does'nt exist prior to version 0x20 */
+		if (regoffset == 11 && ab8500->chip_id < 0x20)
+			continue;
+
 		status = get_register_interruptible(ab8500, AB8500_INTERRUPT,
 			AB8500_IT_LATCH1_REG + regoffset, &value);
 		if (status < 0 || value == 0)
@@ -393,13 +406,195 @@ static struct resource ab8500_poweronkey
 	},
 };
 
+static struct resource ab8500_bm_resources[] = {
+	{
+		.name = "MAIN_EXT_CH_NOT_OK",
+		.start = AB8500_INT_MAIN_EXT_CH_NOT_OK,
+		.end = AB8500_INT_MAIN_EXT_CH_NOT_OK,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
+		.name = "BATT_OVV",
+		.start = AB8500_INT_BATT_OVV,
+		.end = AB8500_INT_BATT_OVV,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
+		.name = "MAIN_CH_UNPLUG_DET",
+		.start = AB8500_INT_MAIN_CH_UNPLUG_DET,
+		.end = AB8500_INT_MAIN_CH_UNPLUG_DET,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
+		.name = "MAIN_CHARGE_PLUG_DET",
+		.start = AB8500_INT_MAIN_CH_PLUG_DET,
+		.end = AB8500_INT_MAIN_CH_PLUG_DET,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
+		.name = "VBUS_DET_F",
+		.start = AB8500_INT_VBUS_DET_F,
+		.end = AB8500_INT_VBUS_DET_F,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
+		.name = "VBUS_DET_R",
+		.start = AB8500_INT_VBUS_DET_R,
+		.end = AB8500_INT_VBUS_DET_R,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
+		.name = "BAT_CTRL_INDB",
+		.start = AB8500_INT_BAT_CTRL_INDB,
+		.end = AB8500_INT_BAT_CTRL_INDB,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
+		.name = "CH_WD_EXP",
+		.start = AB8500_INT_CH_WD_EXP,
+		.end = AB8500_INT_CH_WD_EXP,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
+		.name = "VBUS_OVV",
+		.start = AB8500_INT_VBUS_OVV,
+		.end = AB8500_INT_VBUS_OVV,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
+		.name = "NCONV_ACCU",
+		.start = AB8500_INT_CCN_CONV_ACC,
+		.end = AB8500_INT_CCN_CONV_ACC,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
+		.name = "LOW_BAT_F",
+		.start = AB8500_INT_LOW_BAT_F,
+		.end = AB8500_INT_LOW_BAT_F,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
+		.name = "LOW_BAT_R",
+		.start = AB8500_INT_LOW_BAT_R,
+		.end = AB8500_INT_LOW_BAT_R,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
+		.name = "BTEMP_LOW",
+		.start = AB8500_INT_BTEMP_LOW,
+		.end = AB8500_INT_BTEMP_LOW,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
+		.name = "BTEMP_HIGH",
+		.start = AB8500_INT_BTEMP_HIGH,
+		.end = AB8500_INT_BTEMP_HIGH,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
+		.name = "USB_CHARGER_NOT_OKR",
+		.start = AB8500_INT_USB_CHARGER_NOT_OK,
+		.end = AB8500_INT_USB_CHARGER_NOT_OK,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
+		.name = "USB_CHARGE_DET_DONE",
+		.start = AB8500_INT_USB_CHG_DET_DONE,
+		.end = AB8500_INT_USB_CHG_DET_DONE,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
+		.name = "USB_CH_TH_PROT_R",
+		.start = AB8500_INT_USB_CH_TH_PROT_R,
+		.end = AB8500_INT_USB_CH_TH_PROT_R,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
+		.name = "MAIN_CH_TH_PROT_R",
+		.start = AB8500_INT_MAIN_CH_TH_PROT_R,
+		.end = AB8500_INT_MAIN_CH_TH_PROT_R,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
+		.name = "USB_CHARGER_NOT_OKF",
+		.start = AB8500_INT_USB_CHARGER_NOT_OKF,
+		.end = AB8500_INT_USB_CHARGER_NOT_OKF,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+static struct resource ab8500_debug_resources[] = {
+	{
+		.name	= "IRQ_FIRST",
+		.start	= AB8500_INT_MAIN_EXT_CH_NOT_OK,
+		.end	= AB8500_INT_MAIN_EXT_CH_NOT_OK,
+		.flags	= IORESOURCE_IRQ,
+	},
+	{
+		.name	= "IRQ_LAST",
+		.start	= AB8500_INT_USB_CHARGER_NOT_OKF,
+		.end	= AB8500_INT_USB_CHARGER_NOT_OKF,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct resource ab8500_usb_resources[] = {
+	{
+		.name = "ID_WAKEUP_R",
+		.start = AB8500_INT_ID_WAKEUP_R,
+		.end = AB8500_INT_ID_WAKEUP_R,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
+		.name = "ID_WAKEUP_F",
+		.start = AB8500_INT_ID_WAKEUP_F,
+		.end = AB8500_INT_ID_WAKEUP_F,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
+		.name = "VBUS_DET_F",
+		.start = AB8500_INT_VBUS_DET_F,
+		.end = AB8500_INT_VBUS_DET_F,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
+		.name = "VBUS_DET_R",
+		.start = AB8500_INT_VBUS_DET_R,
+		.end = AB8500_INT_VBUS_DET_R,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
+		.name = "USB_LINK_STATUS",
+		.start = AB8500_INT_USB_LINK_STATUS,
+		.end = AB8500_INT_USB_LINK_STATUS,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+static struct resource ab8500_temp_resources[] = {
+	{
+		.name  = "AB8500_TEMP_WARM",
+		.start = AB8500_INT_TEMP_WARM,
+		.end   = AB8500_INT_TEMP_WARM,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
 static struct mfd_cell ab8500_devs[] = {
 #ifdef CONFIG_DEBUG_FS
 	{
 		.name = "ab8500-debug",
+		.num_resources = ARRAY_SIZE(ab8500_debug_resources),
+		.resources = ab8500_debug_resources,
 	},
 #endif
 	{
+		.name = "ab8500-sysctrl",
+	},
+	{
+		.name = "ab8500-regulator",
+	},
+	{
 		.name = "ab8500-gpadc",
 		.num_resources = ARRAY_SIZE(ab8500_gpadc_resources),
 		.resources = ab8500_gpadc_resources,
@@ -410,6 +605,22 @@ static struct mfd_cell ab8500_devs[] = {
 		.resources = ab8500_rtc_resources,
 	},
 	{
+		.name = "ab8500-bm",
+		.num_resources = ARRAY_SIZE(ab8500_bm_resources),
+		.resources = ab8500_bm_resources,
+	},
+	{ .name = "ab8500-codec", },
+	{
+		.name = "ab8500-usb",
+		.num_resources = ARRAY_SIZE(ab8500_usb_resources),
+		.resources = ab8500_usb_resources,
+	},
+	{
+		.name = "ab8500-poweron-key",
+		.num_resources = ARRAY_SIZE(ab8500_poweronkey_db_resources),
+		.resources = ab8500_poweronkey_db_resources,
+	},
+	{
 		.name = "ab8500-pwm",
 		.id = 1,
 	},
@@ -421,17 +632,37 @@ static struct mfd_cell ab8500_devs[] = {
 		.name = "ab8500-pwm",
 		.id = 3,
 	},
-	{ .name = "ab8500-charger", },
-	{ .name = "ab8500-audio", },
-	{ .name = "ab8500-usb", },
-	{ .name = "ab8500-regulator", },
+	{ .name = "ab8500-leds", },
 	{
-		.name = "ab8500-poweron-key",
-		.num_resources = ARRAY_SIZE(ab8500_poweronkey_db_resources),
-		.resources = ab8500_poweronkey_db_resources,
+		.name = "ab8500-denc",
+	},
+	{
+		.name = "ab8500-temp",
+		.num_resources = ARRAY_SIZE(ab8500_temp_resources),
+		.resources = ab8500_temp_resources,
 	},
 };
 
+static ssize_t show_chip_id(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct ab8500 *ab8500;
+
+	ab8500 = dev_get_drvdata(dev);
+	return sprintf(buf, "%#x\n", ab8500 ? ab8500->chip_id : -EINVAL);
+}
+
+static DEVICE_ATTR(chip_id, S_IRUGO, show_chip_id, NULL);
+
+static struct attribute *ab8500_sysfs_entries[] = {
+	&dev_attr_chip_id.attr,
+	NULL,
+};
+
+static struct attribute_group ab8500_attr_group = {
+	.attrs	= ab8500_sysfs_entries,
+};
+
 int __devinit ab8500_init(struct ab8500 *ab8500)
 {
 	struct ab8500_platform_data *plat = dev_get_platdata(ab8500->dev);
@@ -454,8 +685,9 @@ int __devinit ab8500_init(struct ab8500
 	 * 0x0 - Early Drop
 	 * 0x10 - Cut 1.0
 	 * 0x11 - Cut 1.1
+	 * 0x20 - Cut 2.0
 	 */
-	if (value == 0x0 || value == 0x10 || value == 0x11) {
+	if (value == 0x0 || value == 0x10 || value == 0x11 || value == 0x20) {
 		ab8500->revision = value;
 		dev_info(ab8500->dev, "detected chip, revision: %#x\n", value);
 	} else {
@@ -468,18 +700,16 @@ int __devinit ab8500_init(struct ab8500
 		plat->init(ab8500);
 
 	/* Clear and mask all interrupts */
-	for (i = 0; i < 10; i++) {
-		get_register_interruptible(ab8500, AB8500_INTERRUPT,
-			AB8500_IT_LATCH1_REG + i, &value);
-		set_register_interruptible(ab8500, AB8500_INTERRUPT,
-			AB8500_IT_MASK1_REG + i, 0xff);
-	}
+	for (i = 0; i < AB8500_NUM_IRQ_REGS; i++) {
+		/* Interrupt register 12 does'nt exist prior to version 0x20 */
+		if (ab8500_irq_regoffset[i] == 11 && ab8500->chip_id < 0x20)
+			continue;
 
-	for (i = 18; i < 24; i++) {
 		get_register_interruptible(ab8500, AB8500_INTERRUPT,
-			AB8500_IT_LATCH1_REG + i, &value);
+			AB8500_IT_LATCH1_REG + ab8500_irq_regoffset[i],
+			&value);
 		set_register_interruptible(ab8500, AB8500_INTERRUPT,
-			AB8500_IT_MASK1_REG + i, 0xff);
+			AB8500_IT_MASK1_REG + ab8500_irq_regoffset[i], 0xff);
 	}
 
 	ret = abx500_register_ops(ab8500->dev, &ab8500_ops);
@@ -495,7 +725,8 @@ int __devinit ab8500_init(struct ab8500
 			return ret;
 
 		ret = request_threaded_irq(ab8500->irq, NULL, ab8500_irq,
-					   IRQF_ONESHOT, "ab8500", ab8500);
+					   IRQF_ONESHOT | IRQF_NO_SUSPEND,
+					   "ab8500", ab8500);
 		if (ret)
 			goto out_removeirq;
 	}
@@ -506,6 +737,10 @@ int __devinit ab8500_init(struct ab8500
 	if (ret)
 		goto out_freeirq;
 
+	ret = sysfs_create_group(&ab8500->dev->kobj, &ab8500_attr_group);
+	if (ret)
+		dev_err(ab8500->dev, "error creating sysfs entries\n");
+
 	return ret;
 
 out_freeirq:
@@ -519,6 +754,7 @@ out_removeirq:
 
 int __devexit ab8500_exit(struct ab8500 *ab8500)
 {
+	sysfs_remove_group(&ab8500->dev->kobj, &ab8500_attr_group);
 	mfd_remove_devices(ab8500->dev);
 	if (ab8500->irq_base) {
 		free_irq(ab8500->irq, ab8500);
diff -druNp linux-libre-2.6.37-gnu1/drivers/mfd/ab8500-debugfs.c linux-libre-2.6.38-gnu1/drivers/mfd/ab8500-debugfs.c
--- linux-libre-2.6.37-gnu1/drivers/mfd/ab8500-debugfs.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mfd/ab8500-debugfs.c	2011-03-14 21:20:32.000000000 -0400
@@ -24,9 +24,9 @@ static u32 debug_address;
  * @perm: access permissions for the range
  */
 struct ab8500_reg_range {
-       u8 first;
-       u8 last;
-       u8 perm;
+	u8 first;
+	u8 last;
+	u8 perm;
 };
 
 /**
@@ -36,9 +36,9 @@ struct ab8500_reg_range {
  * @range: the list of register ranges
  */
 struct ab8500_i2c_ranges {
-       u8 num_ranges;
-       u8 bankid;
-       const struct ab8500_reg_range *range;
+	u8 num_ranges;
+	u8 bankid;
+	const struct ab8500_reg_range *range;
 };
 
 #define AB8500_NAME_STRING "ab8500"
@@ -47,521 +47,521 @@ struct ab8500_i2c_ranges {
 #define AB8500_REV_REG 0x80
 
 static struct ab8500_i2c_ranges debug_ranges[AB8500_NUM_BANKS] = {
-       [0x0] = {
-               .num_ranges = 0,
-               .range = 0,
-       },
-       [AB8500_SYS_CTRL1_BLOCK] = {
-               .num_ranges = 3,
-               .range = (struct ab8500_reg_range[]) {
-                       {
-                               .first = 0x00,
-                               .last = 0x02,
-                       },
-                       {
-                               .first = 0x42,
-                               .last = 0x42,
-                       },
-                       {
-                               .first = 0x80,
-                               .last = 0x81,
-                       },
-               },
-       },
-       [AB8500_SYS_CTRL2_BLOCK] = {
-               .num_ranges = 4,
-               .range = (struct ab8500_reg_range[]) {
-                       {
-                               .first = 0x00,
-                               .last = 0x0D,
-                       },
-                       {
-                               .first = 0x0F,
-                               .last = 0x17,
-                       },
-                       {
-                               .first = 0x30,
-                               .last = 0x30,
-                       },
-                       {
-                               .first = 0x32,
-                               .last = 0x33,
-                       },
-               },
-       },
-       [AB8500_REGU_CTRL1] = {
-               .num_ranges = 3,
-               .range = (struct ab8500_reg_range[]) {
-                       {
-                               .first = 0x00,
-                               .last = 0x00,
-                       },
-                       {
-                               .first = 0x03,
-                               .last = 0x10,
-                       },
-                       {
-                               .first = 0x80,
-                               .last = 0x84,
-                       },
-               },
-       },
-       [AB8500_REGU_CTRL2] = {
-               .num_ranges = 5,
-               .range = (struct ab8500_reg_range[]) {
-                       {
-                               .first = 0x00,
-                               .last = 0x15,
-                       },
-                       {
-                               .first = 0x17,
-                               .last = 0x19,
-                       },
-                       {
-                               .first = 0x1B,
-                               .last = 0x1D,
-                       },
-                       {
-                               .first = 0x1F,
-                               .last = 0x22,
-                       },
-                       {
-                               .first = 0x40,
-                               .last = 0x44,
-                       },
-                       /* 0x80-0x8B is SIM registers and should
-                        * not be accessed from here */
-               },
-       },
-       [AB8500_USB] = {
-               .num_ranges = 2,
-               .range = (struct ab8500_reg_range[]) {
-                       {
-                               .first = 0x80,
-                               .last = 0x83,
-                       },
-                       {
-                               .first = 0x87,
-                               .last = 0x8A,
-                       },
-               },
-       },
-       [AB8500_TVOUT] = {
-               .num_ranges = 9,
-               .range = (struct ab8500_reg_range[]) {
-                       {
-                               .first = 0x00,
-                               .last = 0x12,
-                       },
-                       {
-                               .first = 0x15,
-                               .last = 0x17,
-                       },
-                       {
-                               .first = 0x19,
-                               .last = 0x21,
-                       },
-                       {
-                               .first = 0x27,
-                               .last = 0x2C,
-                       },
-                       {
-                               .first = 0x41,
-                               .last = 0x41,
-                       },
-                       {
-                               .first = 0x45,
-                               .last = 0x5B,
-                       },
-                       {
-                               .first = 0x5D,
-                               .last = 0x5D,
-                       },
-                       {
-                               .first = 0x69,
-                               .last = 0x69,
-                       },
-                       {
-                               .first = 0x80,
-                               .last = 0x81,
-                       },
-               },
-       },
-       [AB8500_DBI] = {
-               .num_ranges = 0,
-               .range = 0,
-       },
-       [AB8500_ECI_AV_ACC] = {
-               .num_ranges = 1,
-               .range = (struct ab8500_reg_range[]) {
-                       {
-                               .first = 0x80,
-                               .last = 0x82,
-                       },
-               },
-       },
-       [0x9] = {
-               .num_ranges = 0,
-               .range = 0,
-       },
-       [AB8500_GPADC] = {
-               .num_ranges = 1,
-               .range = (struct ab8500_reg_range[]) {
-                       {
-                               .first = 0x00,
-                               .last = 0x08,
-                       },
-               },
-       },
-       [AB8500_CHARGER] = {
-               .num_ranges = 8,
-               .range = (struct ab8500_reg_range[]) {
-                       {
-                               .first = 0x00,
-                               .last = 0x03,
-                       },
-                       {
-                               .first = 0x05,
-                               .last = 0x05,
-                       },
-                       {
-                               .first = 0x40,
-                               .last = 0x40,
-                       },
-                       {
-                               .first = 0x42,
-                               .last = 0x42,
-                       },
-                       {
-                               .first = 0x44,
-                               .last = 0x44,
-                       },
-                       {
-                               .first = 0x50,
-                               .last = 0x55,
-                       },
-                       {
-                               .first = 0x80,
-                               .last = 0x82,
-                       },
-                       {
-                               .first = 0xC0,
-                               .last = 0xC2,
-                       },
-               },
-       },
-       [AB8500_GAS_GAUGE] = {
-               .num_ranges = 3,
-               .range = (struct ab8500_reg_range[]) {
-                       {
-                               .first = 0x00,
-                               .last = 0x00,
-                       },
-                       {
-                               .first = 0x07,
-                               .last = 0x0A,
-                       },
-                       {
-                               .first = 0x10,
-                               .last = 0x14,
-                       },
-               },
-       },
-       [AB8500_AUDIO] = {
-               .num_ranges = 1,
-               .range = (struct ab8500_reg_range[]) {
-                       {
-                               .first = 0x00,
-                               .last = 0x6F,
-                       },
-               },
-       },
-       [AB8500_INTERRUPT] = {
-               .num_ranges = 0,
-               .range = 0,
-       },
-       [AB8500_RTC] = {
-               .num_ranges = 1,
-               .range = (struct ab8500_reg_range[]) {
-                       {
-                               .first = 0x00,
-                               .last = 0x0F,
-                       },
-               },
-       },
-       [AB8500_MISC] = {
-               .num_ranges = 8,
-               .range = (struct ab8500_reg_range[]) {
-                       {
-                               .first = 0x00,
-                               .last = 0x05,
-                       },
-                       {
-                               .first = 0x10,
-                               .last = 0x15,
-                       },
-                       {
-                               .first = 0x20,
-                               .last = 0x25,
-                       },
-                       {
-                               .first = 0x30,
-                               .last = 0x35,
-                       },
-                       {
-                               .first = 0x40,
-                               .last = 0x45,
-                       },
-                       {
-                               .first = 0x50,
-                               .last = 0x50,
-                       },
-                       {
-                               .first = 0x60,
-                               .last = 0x67,
-                       },
-                       {
-                               .first = 0x80,
-                               .last = 0x80,
-                       },
-               },
-       },
-       [0x11] = {
-               .num_ranges = 0,
-               .range = 0,
-       },
-       [0x12] = {
-               .num_ranges = 0,
-               .range = 0,
-       },
-       [0x13] = {
-               .num_ranges = 0,
-               .range = 0,
-       },
-       [0x14] = {
-               .num_ranges = 0,
-               .range = 0,
-       },
-       [AB8500_OTP_EMUL] = {
-               .num_ranges = 1,
-               .range = (struct ab8500_reg_range[]) {
-                       {
-                               .first = 0x01,
-                               .last = 0x0F,
-                       },
-               },
-       },
+	[0x0] = {
+		.num_ranges = 0,
+		.range = 0,
+	},
+	[AB8500_SYS_CTRL1_BLOCK] = {
+		.num_ranges = 3,
+		.range = (struct ab8500_reg_range[]) {
+			{
+				.first = 0x00,
+				.last = 0x02,
+			},
+			{
+				.first = 0x42,
+				.last = 0x42,
+			},
+			{
+				.first = 0x80,
+				.last = 0x81,
+			},
+		},
+	},
+	[AB8500_SYS_CTRL2_BLOCK] = {
+		.num_ranges = 4,
+		.range = (struct ab8500_reg_range[]) {
+			{
+				.first = 0x00,
+				.last = 0x0D,
+			},
+			{
+				.first = 0x0F,
+				.last = 0x17,
+			},
+			{
+				.first = 0x30,
+				.last = 0x30,
+			},
+			{
+				.first = 0x32,
+				.last = 0x33,
+			},
+		},
+	},
+	[AB8500_REGU_CTRL1] = {
+		.num_ranges = 3,
+		.range = (struct ab8500_reg_range[]) {
+			{
+				.first = 0x00,
+				.last = 0x00,
+			},
+			{
+				.first = 0x03,
+				.last = 0x10,
+			},
+			{
+				.first = 0x80,
+				.last = 0x84,
+			},
+		},
+	},
+	[AB8500_REGU_CTRL2] = {
+		.num_ranges = 5,
+		.range = (struct ab8500_reg_range[]) {
+			{
+				.first = 0x00,
+				.last = 0x15,
+			},
+			{
+				.first = 0x17,
+				.last = 0x19,
+			},
+			{
+				.first = 0x1B,
+				.last = 0x1D,
+			},
+			{
+				.first = 0x1F,
+				.last = 0x22,
+			},
+			{
+				.first = 0x40,
+				.last = 0x44,
+			},
+			/* 0x80-0x8B is SIM registers and should
+			 * not be accessed from here */
+		},
+	},
+	[AB8500_USB] = {
+		.num_ranges = 2,
+		.range = (struct ab8500_reg_range[]) {
+			{
+				.first = 0x80,
+				.last = 0x83,
+			},
+			{
+				.first = 0x87,
+				.last = 0x8A,
+			},
+		},
+	},
+	[AB8500_TVOUT] = {
+		.num_ranges = 9,
+		.range = (struct ab8500_reg_range[]) {
+			{
+				.first = 0x00,
+				.last = 0x12,
+			},
+			{
+				.first = 0x15,
+				.last = 0x17,
+			},
+			{
+				.first = 0x19,
+				.last = 0x21,
+			},
+			{
+				.first = 0x27,
+				.last = 0x2C,
+			},
+			{
+				.first = 0x41,
+				.last = 0x41,
+			},
+			{
+				.first = 0x45,
+				.last = 0x5B,
+			},
+			{
+				.first = 0x5D,
+				.last = 0x5D,
+			},
+			{
+				.first = 0x69,
+				.last = 0x69,
+			},
+			{
+				.first = 0x80,
+				.last = 0x81,
+			},
+		},
+	},
+	[AB8500_DBI] = {
+		.num_ranges = 0,
+		.range = NULL,
+	},
+	[AB8500_ECI_AV_ACC] = {
+		.num_ranges = 1,
+		.range = (struct ab8500_reg_range[]) {
+			{
+				.first = 0x80,
+				.last = 0x82,
+			},
+		},
+	},
+	[0x9] = {
+		.num_ranges = 0,
+		.range = NULL,
+	},
+	[AB8500_GPADC] = {
+		.num_ranges = 1,
+		.range = (struct ab8500_reg_range[]) {
+			{
+				.first = 0x00,
+				.last = 0x08,
+			},
+		},
+	},
+	[AB8500_CHARGER] = {
+		.num_ranges = 8,
+		.range = (struct ab8500_reg_range[]) {
+			{
+				.first = 0x00,
+				.last = 0x03,
+			},
+			{
+				.first = 0x05,
+				.last = 0x05,
+			},
+			{
+				.first = 0x40,
+				.last = 0x40,
+			},
+			{
+				.first = 0x42,
+				.last = 0x42,
+			},
+			{
+				.first = 0x44,
+				.last = 0x44,
+			},
+			{
+				.first = 0x50,
+				.last = 0x55,
+			},
+			{
+				.first = 0x80,
+				.last = 0x82,
+			},
+			{
+				.first = 0xC0,
+				.last = 0xC2,
+			},
+		},
+	},
+	[AB8500_GAS_GAUGE] = {
+		.num_ranges = 3,
+		.range = (struct ab8500_reg_range[]) {
+			{
+				.first = 0x00,
+				.last = 0x00,
+			},
+			{
+				.first = 0x07,
+				.last = 0x0A,
+			},
+			{
+				.first = 0x10,
+				.last = 0x14,
+			},
+		},
+	},
+	[AB8500_AUDIO] = {
+		.num_ranges = 1,
+		.range = (struct ab8500_reg_range[]) {
+			{
+				.first = 0x00,
+				.last = 0x6F,
+			},
+		},
+	},
+	[AB8500_INTERRUPT] = {
+		.num_ranges = 0,
+		.range = NULL,
+	},
+	[AB8500_RTC] = {
+		.num_ranges = 1,
+		.range = (struct ab8500_reg_range[]) {
+			{
+				.first = 0x00,
+				.last = 0x0F,
+			},
+		},
+	},
+	[AB8500_MISC] = {
+		.num_ranges = 8,
+		.range = (struct ab8500_reg_range[]) {
+			{
+				.first = 0x00,
+				.last = 0x05,
+			},
+			{
+				.first = 0x10,
+				.last = 0x15,
+			},
+			{
+				.first = 0x20,
+				.last = 0x25,
+			},
+			{
+				.first = 0x30,
+				.last = 0x35,
+			},
+			{
+				.first = 0x40,
+				.last = 0x45,
+			},
+			{
+				.first = 0x50,
+				.last = 0x50,
+			},
+			{
+				.first = 0x60,
+				.last = 0x67,
+			},
+			{
+				.first = 0x80,
+				.last = 0x80,
+			},
+		},
+	},
+	[0x11] = {
+		.num_ranges = 0,
+		.range = NULL,
+	},
+	[0x12] = {
+		.num_ranges = 0,
+		.range = NULL,
+	},
+	[0x13] = {
+		.num_ranges = 0,
+		.range = NULL,
+	},
+	[0x14] = {
+		.num_ranges = 0,
+		.range = NULL,
+	},
+	[AB8500_OTP_EMUL] = {
+		.num_ranges = 1,
+		.range = (struct ab8500_reg_range[]) {
+			{
+				.first = 0x01,
+				.last = 0x0F,
+			},
+		},
+	},
 };
 
 static int ab8500_registers_print(struct seq_file *s, void *p)
 {
-       struct device *dev = s->private;
-       unsigned int i;
-       u32 bank = debug_bank;
+	struct device *dev = s->private;
+	unsigned int i;
+	u32 bank = debug_bank;
 
-       seq_printf(s, AB8500_NAME_STRING " register values:\n");
+	seq_printf(s, AB8500_NAME_STRING " register values:\n");
 
-       seq_printf(s, " bank %u:\n", bank);
-       for (i = 0; i < debug_ranges[bank].num_ranges; i++) {
-               u32 reg;
+	seq_printf(s, " bank %u:\n", bank);
+	for (i = 0; i < debug_ranges[bank].num_ranges; i++) {
+		u32 reg;
 
-               for (reg = debug_ranges[bank].range[i].first;
-                       reg <= debug_ranges[bank].range[i].last;
-                       reg++) {
-                       u8 value;
-                       int err;
+		for (reg = debug_ranges[bank].range[i].first;
+			reg <= debug_ranges[bank].range[i].last;
+			reg++) {
+			u8 value;
+			int err;
 
-                       err = abx500_get_register_interruptible(dev,
-                               (u8)bank, (u8)reg, &value);
-                       if (err < 0) {
-                               dev_err(dev, "ab->read fail %d\n", err);
-                               return err;
-                       }
+			err = abx500_get_register_interruptible(dev,
+				(u8)bank, (u8)reg, &value);
+			if (err < 0) {
+				dev_err(dev, "ab->read fail %d\n", err);
+				return err;
+			}
 
-                       err = seq_printf(s, "  [%u/0x%02X]: 0x%02X\n", bank,
-                               reg, value);
-                       if (err < 0) {
-                               dev_err(dev, "seq_printf overflow\n");
-                               /* Error is not returned here since
-                                * the output is wanted in any case */
-                               return 0;
-                       }
-               }
-       }
-       return 0;
+			err = seq_printf(s, "  [%u/0x%02X]: 0x%02X\n", bank,
+				reg, value);
+			if (err < 0) {
+				dev_err(dev, "seq_printf overflow\n");
+				/* Error is not returned here since
+				 * the output is wanted in any case */
+				return 0;
+			}
+		}
+	}
+	return 0;
 }
 
 static int ab8500_registers_open(struct inode *inode, struct file *file)
 {
-       return single_open(file, ab8500_registers_print, inode->i_private);
+	return single_open(file, ab8500_registers_print, inode->i_private);
 }
 
 static const struct file_operations ab8500_registers_fops = {
-       .open = ab8500_registers_open,
-       .read = seq_read,
-       .llseek = seq_lseek,
-       .release = single_release,
-       .owner = THIS_MODULE,
+	.open = ab8500_registers_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+	.owner = THIS_MODULE,
 };
 
 static int ab8500_bank_print(struct seq_file *s, void *p)
 {
-       return seq_printf(s, "%d\n", debug_bank);
+	return seq_printf(s, "%d\n", debug_bank);
 }
 
 static int ab8500_bank_open(struct inode *inode, struct file *file)
 {
-       return single_open(file, ab8500_bank_print, inode->i_private);
+	return single_open(file, ab8500_bank_print, inode->i_private);
 }
 
 static ssize_t ab8500_bank_write(struct file *file,
-       const char __user *user_buf,
-       size_t count, loff_t *ppos)
+	const char __user *user_buf,
+	size_t count, loff_t *ppos)
 {
-       struct device *dev = ((struct seq_file *)(file->private_data))->private;
-       char buf[32];
-       int buf_size;
-       unsigned long user_bank;
-       int err;
+	struct device *dev = ((struct seq_file *)(file->private_data))->private;
+	char buf[32];
+	int buf_size;
+	unsigned long user_bank;
+	int err;
 
-       /* Get userspace string and assure termination */
-       buf_size = min(count, (sizeof(buf) - 1));
-       if (copy_from_user(buf, user_buf, buf_size))
-               return -EFAULT;
-       buf[buf_size] = 0;
+	/* Get userspace string and assure termination */
+	buf_size = min(count, (sizeof(buf) - 1));
+	if (copy_from_user(buf, user_buf, buf_size))
+		return -EFAULT;
+	buf[buf_size] = 0;
 
-       err = strict_strtoul(buf, 0, &user_bank);
-       if (err)
-               return -EINVAL;
+	err = strict_strtoul(buf, 0, &user_bank);
+	if (err)
+		return -EINVAL;
 
-       if (user_bank >= AB8500_NUM_BANKS) {
-               dev_err(dev, "debugfs error input > number of banks\n");
-               return -EINVAL;
-       }
+	if (user_bank >= AB8500_NUM_BANKS) {
+		dev_err(dev, "debugfs error input > number of banks\n");
+		return -EINVAL;
+	}
 
-       debug_bank = user_bank;
+	debug_bank = user_bank;
 
-       return buf_size;
+	return buf_size;
 }
 
 static int ab8500_address_print(struct seq_file *s, void *p)
 {
-       return seq_printf(s, "0x%02X\n", debug_address);
+	return seq_printf(s, "0x%02X\n", debug_address);
 }
 
 static int ab8500_address_open(struct inode *inode, struct file *file)
 {
-       return single_open(file, ab8500_address_print, inode->i_private);
+	return single_open(file, ab8500_address_print, inode->i_private);
 }
 
 static ssize_t ab8500_address_write(struct file *file,
-       const char __user *user_buf,
-       size_t count, loff_t *ppos)
+	const char __user *user_buf,
+	size_t count, loff_t *ppos)
 {
-       struct device *dev = ((struct seq_file *)(file->private_data))->private;
-       char buf[32];
-       int buf_size;
-       unsigned long user_address;
-       int err;
+	struct device *dev = ((struct seq_file *)(file->private_data))->private;
+	char buf[32];
+	int buf_size;
+	unsigned long user_address;
+	int err;
 
-       /* Get userspace string and assure termination */
-       buf_size = min(count, (sizeof(buf) - 1));
-       if (copy_from_user(buf, user_buf, buf_size))
-               return -EFAULT;
-       buf[buf_size] = 0;
+	/* Get userspace string and assure termination */
+	buf_size = min(count, (sizeof(buf) - 1));
+	if (copy_from_user(buf, user_buf, buf_size))
+		return -EFAULT;
+	buf[buf_size] = 0;
 
-       err = strict_strtoul(buf, 0, &user_address);
-       if (err)
-               return -EINVAL;
-       if (user_address > 0xff) {
-               dev_err(dev, "debugfs error input > 0xff\n");
-               return -EINVAL;
-       }
-       debug_address = user_address;
-       return buf_size;
+	err = strict_strtoul(buf, 0, &user_address);
+	if (err)
+		return -EINVAL;
+	if (user_address > 0xff) {
+		dev_err(dev, "debugfs error input > 0xff\n");
+		return -EINVAL;
+	}
+	debug_address = user_address;
+	return buf_size;
 }
 
 static int ab8500_val_print(struct seq_file *s, void *p)
 {
-       struct device *dev = s->private;
-       int ret;
-       u8 regvalue;
+	struct device *dev = s->private;
+	int ret;
+	u8 regvalue;
 
-       ret = abx500_get_register_interruptible(dev,
-               (u8)debug_bank, (u8)debug_address, &regvalue);
-       if (ret < 0) {
-               dev_err(dev, "abx500_get_reg fail %d, %d\n",
-                       ret, __LINE__);
-               return -EINVAL;
-       }
-       seq_printf(s, "0x%02X\n", regvalue);
+	ret = abx500_get_register_interruptible(dev,
+		(u8)debug_bank, (u8)debug_address, &regvalue);
+	if (ret < 0) {
+		dev_err(dev, "abx500_get_reg fail %d, %d\n",
+			ret, __LINE__);
+		return -EINVAL;
+	}
+	seq_printf(s, "0x%02X\n", regvalue);
 
-       return 0;
+	return 0;
 }
 
 static int ab8500_val_open(struct inode *inode, struct file *file)
 {
-       return single_open(file, ab8500_val_print, inode->i_private);
+	return single_open(file, ab8500_val_print, inode->i_private);
 }
 
 static ssize_t ab8500_val_write(struct file *file,
-       const char __user *user_buf,
-       size_t count, loff_t *ppos)
+	const char __user *user_buf,
+	size_t count, loff_t *ppos)
 {
-       struct device *dev = ((struct seq_file *)(file->private_data))->private;
-       char buf[32];
-       int buf_size;
-       unsigned long user_val;
-       int err;
+	struct device *dev = ((struct seq_file *)(file->private_data))->private;
+	char buf[32];
+	int buf_size;
+	unsigned long user_val;
+	int err;
 
-       /* Get userspace string and assure termination */
-       buf_size = min(count, (sizeof(buf)-1));
-       if (copy_from_user(buf, user_buf, buf_size))
-               return -EFAULT;
-       buf[buf_size] = 0;
+	/* Get userspace string and assure termination */
+	buf_size = min(count, (sizeof(buf)-1));
+	if (copy_from_user(buf, user_buf, buf_size))
+		return -EFAULT;
+	buf[buf_size] = 0;
 
-       err = strict_strtoul(buf, 0, &user_val);
-       if (err)
-               return -EINVAL;
-       if (user_val > 0xff) {
-               dev_err(dev, "debugfs error input > 0xff\n");
-               return -EINVAL;
-       }
-       err = abx500_set_register_interruptible(dev,
-               (u8)debug_bank, debug_address, (u8)user_val);
-       if (err < 0) {
-               printk(KERN_ERR "abx500_set_reg failed %d, %d", err, __LINE__);
-               return -EINVAL;
-       }
+	err = strict_strtoul(buf, 0, &user_val);
+	if (err)
+		return -EINVAL;
+	if (user_val > 0xff) {
+		dev_err(dev, "debugfs error input > 0xff\n");
+		return -EINVAL;
+	}
+	err = abx500_set_register_interruptible(dev,
+		(u8)debug_bank, debug_address, (u8)user_val);
+	if (err < 0) {
+		printk(KERN_ERR "abx500_set_reg failed %d, %d", err, __LINE__);
+		return -EINVAL;
+	}
 
-       return buf_size;
+	return buf_size;
 }
 
 static const struct file_operations ab8500_bank_fops = {
-       .open = ab8500_bank_open,
-       .write = ab8500_bank_write,
-       .read = seq_read,
-       .llseek = seq_lseek,
-       .release = single_release,
-       .owner = THIS_MODULE,
+	.open = ab8500_bank_open,
+	.write = ab8500_bank_write,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+	.owner = THIS_MODULE,
 };
 
 static const struct file_operations ab8500_address_fops = {
-       .open = ab8500_address_open,
-       .write = ab8500_address_write,
-       .read = seq_read,
-       .llseek = seq_lseek,
-       .release = single_release,
-       .owner = THIS_MODULE,
+	.open = ab8500_address_open,
+	.write = ab8500_address_write,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+	.owner = THIS_MODULE,
 };
 
 static const struct file_operations ab8500_val_fops = {
-       .open = ab8500_val_open,
-       .write = ab8500_val_write,
-       .read = seq_read,
-       .llseek = seq_lseek,
-       .release = single_release,
-       .owner = THIS_MODULE,
+	.open = ab8500_val_open,
+	.write = ab8500_val_write,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+	.owner = THIS_MODULE,
 };
 
 static struct dentry *ab8500_dir;
@@ -572,77 +572,77 @@ static struct dentry *ab8500_val_file;
 
 static int __devinit ab8500_debug_probe(struct platform_device *plf)
 {
-       debug_bank = AB8500_MISC;
-       debug_address = AB8500_REV_REG & 0x00FF;
+	debug_bank = AB8500_MISC;
+	debug_address = AB8500_REV_REG & 0x00FF;
 
-       ab8500_dir = debugfs_create_dir(AB8500_NAME_STRING, NULL);
-       if (!ab8500_dir)
-               goto exit_no_debugfs;
+	ab8500_dir = debugfs_create_dir(AB8500_NAME_STRING, NULL);
+	if (!ab8500_dir)
+		goto exit_no_debugfs;
 
-       ab8500_reg_file = debugfs_create_file("all-bank-registers",
-               S_IRUGO, ab8500_dir, &plf->dev, &ab8500_registers_fops);
-       if (!ab8500_reg_file)
-               goto exit_destroy_dir;
+	ab8500_reg_file = debugfs_create_file("all-bank-registers",
+		S_IRUGO, ab8500_dir, &plf->dev, &ab8500_registers_fops);
+	if (!ab8500_reg_file)
+		goto exit_destroy_dir;
 
-       ab8500_bank_file = debugfs_create_file("register-bank",
-               (S_IRUGO | S_IWUGO), ab8500_dir, &plf->dev, &ab8500_bank_fops);
-       if (!ab8500_bank_file)
-               goto exit_destroy_reg;
+	ab8500_bank_file = debugfs_create_file("register-bank",
+		(S_IRUGO | S_IWUGO), ab8500_dir, &plf->dev, &ab8500_bank_fops);
+	if (!ab8500_bank_file)
+		goto exit_destroy_reg;
 
-       ab8500_address_file = debugfs_create_file("register-address",
-               (S_IRUGO | S_IWUGO), ab8500_dir, &plf->dev,
-               &ab8500_address_fops);
-       if (!ab8500_address_file)
-               goto exit_destroy_bank;
+	ab8500_address_file = debugfs_create_file("register-address",
+		(S_IRUGO | S_IWUGO), ab8500_dir, &plf->dev,
+		&ab8500_address_fops);
+	if (!ab8500_address_file)
+		goto exit_destroy_bank;
 
-       ab8500_val_file = debugfs_create_file("register-value",
-               (S_IRUGO | S_IWUGO), ab8500_dir, &plf->dev, &ab8500_val_fops);
-       if (!ab8500_val_file)
-               goto exit_destroy_address;
+	ab8500_val_file = debugfs_create_file("register-value",
+		(S_IRUGO | S_IWUGO), ab8500_dir, &plf->dev, &ab8500_val_fops);
+	if (!ab8500_val_file)
+		goto exit_destroy_address;
 
-       return 0;
+	return 0;
 
 exit_destroy_address:
-       debugfs_remove(ab8500_address_file);
+	debugfs_remove(ab8500_address_file);
 exit_destroy_bank:
-       debugfs_remove(ab8500_bank_file);
+	debugfs_remove(ab8500_bank_file);
 exit_destroy_reg:
-       debugfs_remove(ab8500_reg_file);
+	debugfs_remove(ab8500_reg_file);
 exit_destroy_dir:
-       debugfs_remove(ab8500_dir);
+	debugfs_remove(ab8500_dir);
 exit_no_debugfs:
-       dev_err(&plf->dev, "failed to create debugfs entries.\n");
-       return -ENOMEM;
+	dev_err(&plf->dev, "failed to create debugfs entries.\n");
+	return -ENOMEM;
 }
 
 static int __devexit ab8500_debug_remove(struct platform_device *plf)
 {
-       debugfs_remove(ab8500_val_file);
-       debugfs_remove(ab8500_address_file);
-       debugfs_remove(ab8500_bank_file);
-       debugfs_remove(ab8500_reg_file);
-       debugfs_remove(ab8500_dir);
+	debugfs_remove(ab8500_val_file);
+	debugfs_remove(ab8500_address_file);
+	debugfs_remove(ab8500_bank_file);
+	debugfs_remove(ab8500_reg_file);
+	debugfs_remove(ab8500_dir);
 
-       return 0;
+	return 0;
 }
 
 static struct platform_driver ab8500_debug_driver = {
-       .driver = {
-               .name = "ab8500-debug",
-               .owner = THIS_MODULE,
-       },
-       .probe  = ab8500_debug_probe,
-       .remove = __devexit_p(ab8500_debug_remove)
+	.driver = {
+		.name = "ab8500-debug",
+		.owner = THIS_MODULE,
+	},
+	.probe  = ab8500_debug_probe,
+	.remove = __devexit_p(ab8500_debug_remove)
 };
 
 static int __init ab8500_debug_init(void)
 {
-       return platform_driver_register(&ab8500_debug_driver);
+	return platform_driver_register(&ab8500_debug_driver);
 }
 
 static void __exit ab8500_debug_exit(void)
 {
-       platform_driver_unregister(&ab8500_debug_driver);
+	platform_driver_unregister(&ab8500_debug_driver);
 }
 subsys_initcall(ab8500_debug_init);
 module_exit(ab8500_debug_exit);
diff -druNp linux-libre-2.6.37-gnu1/drivers/mfd/ab8500-spi.c linux-libre-2.6.38-gnu1/drivers/mfd/ab8500-spi.c
--- linux-libre-2.6.37-gnu1/drivers/mfd/ab8500-spi.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mfd/ab8500-spi.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,143 +0,0 @@
-/*
- * Copyright (C) ST-Ericsson SA 2010
- *
- * License Terms: GNU General Public License v2
- * Author: Srinidhi Kasagar <srinidhi.kasagar@stericsson.com>
- */
-
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/spi/spi.h>
-#include <linux/mfd/ab8500.h>
-
-/*
- * This funtion writes to any AB8500 registers using
- * SPI protocol &  before it writes it packs the data
- * in the below 24 bit frame format
- *
- *	 *|------------------------------------|
- *	 *| 23|22...18|17.......10|9|8|7......0|
- *	 *| r/w  bank       adr          data  |
- *	 * ------------------------------------
- *
- * This function shouldn't be called from interrupt
- * context
- */
-static int ab8500_spi_write(struct ab8500 *ab8500, u16 addr, u8 data)
-{
-	struct spi_device *spi = container_of(ab8500->dev, struct spi_device,
-					      dev);
-	unsigned long spi_data = addr << 10 | data;
-	struct spi_transfer xfer;
-	struct spi_message msg;
-
-	ab8500->tx_buf[0] = spi_data;
-	ab8500->rx_buf[0] = 0;
-
-	xfer.tx_buf	= ab8500->tx_buf;
-	xfer.rx_buf	= NULL;
-	xfer.len	= sizeof(unsigned long);
-
-	spi_message_init(&msg);
-	spi_message_add_tail(&xfer, &msg);
-
-	return spi_sync(spi, &msg);
-}
-
-static int ab8500_spi_read(struct ab8500 *ab8500, u16 addr)
-{
-	struct spi_device *spi = container_of(ab8500->dev, struct spi_device,
-					      dev);
-	unsigned long spi_data = 1 << 23 | addr << 10;
-	struct spi_transfer xfer;
-	struct spi_message msg;
-	int ret;
-
-	ab8500->tx_buf[0] = spi_data;
-	ab8500->rx_buf[0] = 0;
-
-	xfer.tx_buf	= ab8500->tx_buf;
-	xfer.rx_buf	= ab8500->rx_buf;
-	xfer.len	= sizeof(unsigned long);
-
-	spi_message_init(&msg);
-	spi_message_add_tail(&xfer, &msg);
-
-	ret = spi_sync(spi, &msg);
-	if (!ret)
-		/*
-		 * Only the 8 lowermost bytes are
-		 * defined with value, the rest may
-		 * vary depending on chip/board noise.
-		 */
-		ret = ab8500->rx_buf[0] & 0xFFU;
-
-	return ret;
-}
-
-static int __devinit ab8500_spi_probe(struct spi_device *spi)
-{
-	struct ab8500 *ab8500;
-	int ret;
-
-	spi->bits_per_word = 24;
-	ret = spi_setup(spi);
-	if (ret < 0)
-		return ret;
-
-	ab8500 = kzalloc(sizeof *ab8500, GFP_KERNEL);
-	if (!ab8500)
-		return -ENOMEM;
-
-	ab8500->dev = &spi->dev;
-	ab8500->irq = spi->irq;
-
-	ab8500->read = ab8500_spi_read;
-	ab8500->write = ab8500_spi_write;
-
-	spi_set_drvdata(spi, ab8500);
-
-	ret = ab8500_init(ab8500);
-	if (ret)
-		kfree(ab8500);
-
-	return ret;
-}
-
-static int __devexit ab8500_spi_remove(struct spi_device *spi)
-{
-	struct ab8500 *ab8500 = spi_get_drvdata(spi);
-
-	ab8500_exit(ab8500);
-	kfree(ab8500);
-
-	return 0;
-}
-
-static struct spi_driver ab8500_spi_driver = {
-	.driver = {
-		.name = "ab8500-spi",
-		.owner = THIS_MODULE,
-	},
-	.probe	= ab8500_spi_probe,
-	.remove	= __devexit_p(ab8500_spi_remove)
-};
-
-static int __init ab8500_spi_init(void)
-{
-	return spi_register_driver(&ab8500_spi_driver);
-}
-subsys_initcall(ab8500_spi_init);
-
-static void __exit ab8500_spi_exit(void)
-{
-	spi_unregister_driver(&ab8500_spi_driver);
-}
-module_exit(ab8500_spi_exit);
-
-MODULE_AUTHOR("Srinidhi KASAGAR <srinidhi.kasagar@stericsson.com");
-MODULE_DESCRIPTION("AB8500 SPI");
-MODULE_LICENSE("GPL v2");
diff -druNp linux-libre-2.6.37-gnu1/drivers/mfd/asic3.c linux-libre-2.6.38-gnu1/drivers/mfd/asic3.c
--- linux-libre-2.6.37-gnu1/drivers/mfd/asic3.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mfd/asic3.c	2011-03-14 21:20:32.000000000 -0400
@@ -57,7 +57,7 @@ struct asic3_clk {
 		.rate = _rate,			\
 	}
 
-struct asic3_clk asic3_clk_init[] __initdata = {
+static struct asic3_clk asic3_clk_init[] __initdata = {
 	INIT_CDEX(SPI, 0),
 	INIT_CDEX(OWM, 5000000),
 	INIT_CDEX(PWM0, 0),
@@ -102,7 +102,7 @@ static inline u32 asic3_read_register(st
 			(reg >> asic->bus_shift));
 }
 
-void asic3_set_register(struct asic3 *asic, u32 reg, u32 bits, bool set)
+static void asic3_set_register(struct asic3 *asic, u32 reg, u32 bits, bool set)
 {
 	unsigned long flags;
 	u32 val;
@@ -143,9 +143,9 @@ static void asic3_irq_demux(unsigned int
 	unsigned long flags;
 	struct asic3 *asic;
 
-	desc->chip->ack(irq);
+	desc->irq_data.chip->irq_ack(&desc->irq_data);
 
-	asic = desc->handler_data;
+	asic = get_irq_data(irq);
 
 	for (iter = 0 ; iter < MAX_ASIC_ISR_LOOPS; iter++) {
 		u32 status;
@@ -226,14 +226,14 @@ static inline int asic3_irq_to_index(str
 	return (irq - asic->irq_base) & 0xf;
 }
 
-static void asic3_mask_gpio_irq(unsigned int irq)
+static void asic3_mask_gpio_irq(struct irq_data *data)
 {
-	struct asic3 *asic = get_irq_chip_data(irq);
+	struct asic3 *asic = irq_data_get_irq_chip_data(data);
 	u32 val, bank, index;
 	unsigned long flags;
 
-	bank = asic3_irq_to_bank(asic, irq);
-	index = asic3_irq_to_index(asic, irq);
+	bank = asic3_irq_to_bank(asic, data->irq);
+	index = asic3_irq_to_index(asic, data->irq);
 
 	spin_lock_irqsave(&asic->lock, flags);
 	val = asic3_read_register(asic, bank + ASIC3_GPIO_MASK);
@@ -242,9 +242,9 @@ static void asic3_mask_gpio_irq(unsigned
 	spin_unlock_irqrestore(&asic->lock, flags);
 }
 
-static void asic3_mask_irq(unsigned int irq)
+static void asic3_mask_irq(struct irq_data *data)
 {
-	struct asic3 *asic = get_irq_chip_data(irq);
+	struct asic3 *asic = irq_data_get_irq_chip_data(data);
 	int regval;
 	unsigned long flags;
 
@@ -254,7 +254,7 @@ static void asic3_mask_irq(unsigned int
 				     ASIC3_INTR_INT_MASK);
 
 	regval &= ~(ASIC3_INTMASK_MASK0 <<
-		    (irq - (asic->irq_base + ASIC3_NUM_GPIOS)));
+		    (data->irq - (asic->irq_base + ASIC3_NUM_GPIOS)));
 
 	asic3_write_register(asic,
 			     ASIC3_INTR_BASE +
@@ -263,14 +263,14 @@ static void asic3_mask_irq(unsigned int
 	spin_unlock_irqrestore(&asic->lock, flags);
 }
 
-static void asic3_unmask_gpio_irq(unsigned int irq)
+static void asic3_unmask_gpio_irq(struct irq_data *data)
 {
-	struct asic3 *asic = get_irq_chip_data(irq);
+	struct asic3 *asic = irq_data_get_irq_chip_data(data);
 	u32 val, bank, index;
 	unsigned long flags;
 
-	bank = asic3_irq_to_bank(asic, irq);
-	index = asic3_irq_to_index(asic, irq);
+	bank = asic3_irq_to_bank(asic, data->irq);
+	index = asic3_irq_to_index(asic, data->irq);
 
 	spin_lock_irqsave(&asic->lock, flags);
 	val = asic3_read_register(asic, bank + ASIC3_GPIO_MASK);
@@ -279,9 +279,9 @@ static void asic3_unmask_gpio_irq(unsign
 	spin_unlock_irqrestore(&asic->lock, flags);
 }
 
-static void asic3_unmask_irq(unsigned int irq)
+static void asic3_unmask_irq(struct irq_data *data)
 {
-	struct asic3 *asic = get_irq_chip_data(irq);
+	struct asic3 *asic = irq_data_get_irq_chip_data(data);
 	int regval;
 	unsigned long flags;
 
@@ -291,7 +291,7 @@ static void asic3_unmask_irq(unsigned in
 				     ASIC3_INTR_INT_MASK);
 
 	regval |= (ASIC3_INTMASK_MASK0 <<
-		   (irq - (asic->irq_base + ASIC3_NUM_GPIOS)));
+		   (data->irq - (asic->irq_base + ASIC3_NUM_GPIOS)));
 
 	asic3_write_register(asic,
 			     ASIC3_INTR_BASE +
@@ -300,15 +300,15 @@ static void asic3_unmask_irq(unsigned in
 	spin_unlock_irqrestore(&asic->lock, flags);
 }
 
-static int asic3_gpio_irq_type(unsigned int irq, unsigned int type)
+static int asic3_gpio_irq_type(struct irq_data *data, unsigned int type)
 {
-	struct asic3 *asic = get_irq_chip_data(irq);
+	struct asic3 *asic = irq_data_get_irq_chip_data(data);
 	u32 bank, index;
 	u16 trigger, level, edge, bit;
 	unsigned long flags;
 
-	bank = asic3_irq_to_bank(asic, irq);
-	index = asic3_irq_to_index(asic, irq);
+	bank = asic3_irq_to_bank(asic, data->irq);
+	index = asic3_irq_to_index(asic, data->irq);
 	bit = 1<<index;
 
 	spin_lock_irqsave(&asic->lock, flags);
@@ -318,7 +318,7 @@ static int asic3_gpio_irq_type(unsigned
 				   bank + ASIC3_GPIO_EDGE_TRIGGER);
 	trigger = asic3_read_register(asic,
 				      bank + ASIC3_GPIO_TRIGGER_TYPE);
-	asic->irq_bothedge[(irq - asic->irq_base) >> 4] &= ~bit;
+	asic->irq_bothedge[(data->irq - asic->irq_base) >> 4] &= ~bit;
 
 	if (type == IRQ_TYPE_EDGE_RISING) {
 		trigger |= bit;
@@ -328,11 +328,11 @@ static int asic3_gpio_irq_type(unsigned
 		edge &= ~bit;
 	} else if (type == IRQ_TYPE_EDGE_BOTH) {
 		trigger |= bit;
-		if (asic3_gpio_get(&asic->gpio, irq - asic->irq_base))
+		if (asic3_gpio_get(&asic->gpio, data->irq - asic->irq_base))
 			edge &= ~bit;
 		else
 			edge |= bit;
-		asic->irq_bothedge[(irq - asic->irq_base) >> 4] |= bit;
+		asic->irq_bothedge[(data->irq - asic->irq_base) >> 4] |= bit;
 	} else if (type == IRQ_TYPE_LEVEL_LOW) {
 		trigger &= ~bit;
 		level &= ~bit;
@@ -359,17 +359,17 @@ static int asic3_gpio_irq_type(unsigned
 
 static struct irq_chip asic3_gpio_irq_chip = {
 	.name		= "ASIC3-GPIO",
-	.ack		= asic3_mask_gpio_irq,
-	.mask		= asic3_mask_gpio_irq,
-	.unmask		= asic3_unmask_gpio_irq,
-	.set_type	= asic3_gpio_irq_type,
+	.irq_ack	= asic3_mask_gpio_irq,
+	.irq_mask	= asic3_mask_gpio_irq,
+	.irq_unmask	= asic3_unmask_gpio_irq,
+	.irq_set_type	= asic3_gpio_irq_type,
 };
 
 static struct irq_chip asic3_irq_chip = {
 	.name		= "ASIC3",
-	.ack		= asic3_mask_irq,
-	.mask		= asic3_mask_irq,
-	.unmask		= asic3_unmask_irq,
+	.irq_ack	= asic3_mask_irq,
+	.irq_mask	= asic3_mask_irq,
+	.irq_unmask	= asic3_unmask_irq,
 };
 
 static int __init asic3_irq_probe(struct platform_device *pdev)
@@ -635,7 +635,7 @@ static struct resource ds1wm_resources[]
 	},
 	{
 		.start = ASIC3_IRQ_OWM,
-		.start = ASIC3_IRQ_OWM,
+		.end   = ASIC3_IRQ_OWM,
 		.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE,
 	},
 };
diff -druNp linux-libre-2.6.37-gnu1/drivers/mfd/cs5535-mfd.c linux-libre-2.6.38-gnu1/drivers/mfd/cs5535-mfd.c
--- linux-libre-2.6.37-gnu1/drivers/mfd/cs5535-mfd.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mfd/cs5535-mfd.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,151 @@
+/*
+ * cs5535-mfd.c - core MFD driver for CS5535/CS5536 southbridges
+ *
+ * The CS5535 and CS5536 has an ISA bridge on the PCI bus that is
+ * used for accessing GPIOs, MFGPTs, ACPI, etc.  Each subdevice has
+ * an IO range that's specified in a single BAR.  The BAR order is
+ * hardcoded in the CS553x specifications.
+ *
+ * Copyright (c) 2010  Andres Salomon <dilinger@queued.net>
+ *
+ * This program is free software; you can 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/mfd/core.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+
+#define DRV_NAME "cs5535-mfd"
+
+enum cs5535_mfd_bars {
+	SMB_BAR = 0,
+	GPIO_BAR = 1,
+	MFGPT_BAR = 2,
+	PMS_BAR = 4,
+	ACPI_BAR = 5,
+	NR_BARS,
+};
+
+static __devinitdata struct resource cs5535_mfd_resources[NR_BARS];
+
+static __devinitdata struct mfd_cell cs5535_mfd_cells[] = {
+	{
+		.id = SMB_BAR,
+		.name = "cs5535-smb",
+		.num_resources = 1,
+		.resources = &cs5535_mfd_resources[SMB_BAR],
+	},
+	{
+		.id = GPIO_BAR,
+		.name = "cs5535-gpio",
+		.num_resources = 1,
+		.resources = &cs5535_mfd_resources[GPIO_BAR],
+	},
+	{
+		.id = MFGPT_BAR,
+		.name = "cs5535-mfgpt",
+		.num_resources = 1,
+		.resources = &cs5535_mfd_resources[MFGPT_BAR],
+	},
+	{
+		.id = PMS_BAR,
+		.name = "cs5535-pms",
+		.num_resources = 1,
+		.resources = &cs5535_mfd_resources[PMS_BAR],
+	},
+	{
+		.id = ACPI_BAR,
+		.name = "cs5535-acpi",
+		.num_resources = 1,
+		.resources = &cs5535_mfd_resources[ACPI_BAR],
+	},
+};
+
+static int __devinit cs5535_mfd_probe(struct pci_dev *pdev,
+		const struct pci_device_id *id)
+{
+	int err, i;
+
+	err = pci_enable_device(pdev);
+	if (err)
+		return err;
+
+	/* fill in IO range for each cell; subdrivers handle the region */
+	for (i = 0; i < ARRAY_SIZE(cs5535_mfd_cells); i++) {
+		int bar = cs5535_mfd_cells[i].id;
+		struct resource *r = &cs5535_mfd_resources[bar];
+
+		r->flags = IORESOURCE_IO;
+		r->start = pci_resource_start(pdev, bar);
+		r->end = pci_resource_end(pdev, bar);
+
+		/* id is used for temporarily storing BAR; unset it now */
+		cs5535_mfd_cells[i].id = 0;
+	}
+
+	err = mfd_add_devices(&pdev->dev, -1, cs5535_mfd_cells,
+			ARRAY_SIZE(cs5535_mfd_cells), NULL, 0);
+	if (err) {
+		dev_err(&pdev->dev, "MFD add devices failed: %d\n", err);
+		goto err_disable;
+	}
+
+	dev_info(&pdev->dev, "%zu devices registered.\n",
+			ARRAY_SIZE(cs5535_mfd_cells));
+
+	return 0;
+
+err_disable:
+	pci_disable_device(pdev);
+	return err;
+}
+
+static void __devexit cs5535_mfd_remove(struct pci_dev *pdev)
+{
+	mfd_remove_devices(&pdev->dev);
+	pci_disable_device(pdev);
+}
+
+static struct pci_device_id cs5535_mfd_pci_tbl[] = {
+	{ PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_CS5535_ISA) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA) },
+	{ 0, }
+};
+MODULE_DEVICE_TABLE(pci, cs5535_mfd_pci_tbl);
+
+static struct pci_driver cs5535_mfd_drv = {
+	.name = DRV_NAME,
+	.id_table = cs5535_mfd_pci_tbl,
+	.probe = cs5535_mfd_probe,
+	.remove = __devexit_p(cs5535_mfd_remove),
+};
+
+static int __init cs5535_mfd_init(void)
+{
+	return pci_register_driver(&cs5535_mfd_drv);
+}
+
+static void __exit cs5535_mfd_exit(void)
+{
+	pci_unregister_driver(&cs5535_mfd_drv);
+}
+
+module_init(cs5535_mfd_init);
+module_exit(cs5535_mfd_exit);
+
+MODULE_AUTHOR("Andres Salomon <dilinger@queued.net>");
+MODULE_DESCRIPTION("MFD driver for CS5535/CS5536 southbridge's ISA PCI device");
+MODULE_LICENSE("GPL");
diff -druNp linux-libre-2.6.37-gnu1/drivers/mfd/davinci_voicecodec.c linux-libre-2.6.38-gnu1/drivers/mfd/davinci_voicecodec.c
--- linux-libre-2.6.37-gnu1/drivers/mfd/davinci_voicecodec.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mfd/davinci_voicecodec.c	2011-03-14 21:20:32.000000000 -0400
@@ -118,12 +118,12 @@ static int __init davinci_vc_probe(struc
 
 	/* Voice codec interface client */
 	cell = &davinci_vc->cells[DAVINCI_VC_VCIF_CELL];
-	cell->name = "davinci_vcif";
+	cell->name = "davinci-vcif";
 	cell->driver_data = davinci_vc;
 
 	/* Voice codec CQ93VC client */
 	cell = &davinci_vc->cells[DAVINCI_VC_CQ93VC_CELL];
-	cell->name = "cq93vc";
+	cell->name = "cq93vc-codec";
 	cell->driver_data = davinci_vc;
 
 	ret = mfd_add_devices(&pdev->dev, pdev->id, davinci_vc->cells,
diff -druNp linux-libre-2.6.37-gnu1/drivers/mfd/ezx-pcap.c linux-libre-2.6.38-gnu1/drivers/mfd/ezx-pcap.c
--- linux-libre-2.6.37-gnu1/drivers/mfd/ezx-pcap.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mfd/ezx-pcap.c	2011-03-14 21:20:32.000000000 -0400
@@ -144,26 +144,26 @@ int pcap_to_irq(struct pcap_chip *pcap,
 }
 EXPORT_SYMBOL_GPL(pcap_to_irq);
 
-static void pcap_mask_irq(unsigned int irq)
+static void pcap_mask_irq(struct irq_data *d)
 {
-	struct pcap_chip *pcap = get_irq_chip_data(irq);
+	struct pcap_chip *pcap = irq_data_get_irq_chip_data(d);
 
-	pcap->msr |= 1 << irq_to_pcap(pcap, irq);
+	pcap->msr |= 1 << irq_to_pcap(pcap, d->irq);
 	queue_work(pcap->workqueue, &pcap->msr_work);
 }
 
-static void pcap_unmask_irq(unsigned int irq)
+static void pcap_unmask_irq(struct irq_data *d)
 {
-	struct pcap_chip *pcap = get_irq_chip_data(irq);
+	struct pcap_chip *pcap = irq_data_get_irq_chip_data(d);
 
-	pcap->msr &= ~(1 << irq_to_pcap(pcap, irq));
+	pcap->msr &= ~(1 << irq_to_pcap(pcap, d->irq));
 	queue_work(pcap->workqueue, &pcap->msr_work);
 }
 
 static struct irq_chip pcap_irq_chip = {
-	.name	= "pcap",
-	.mask	= pcap_mask_irq,
-	.unmask	= pcap_unmask_irq,
+	.name		= "pcap",
+	.irq_mask	= pcap_mask_irq,
+	.irq_unmask	= pcap_unmask_irq,
 };
 
 static void pcap_msr_work(struct work_struct *work)
@@ -199,8 +199,7 @@ static void pcap_isr_work(struct work_st
 			if (service & 1) {
 				struct irq_desc *desc = irq_to_desc(irq);
 
-				if (WARN(!desc, KERN_WARNING
-						"Invalid PCAP IRQ %d\n", irq))
+				if (WARN(!desc, "Invalid PCAP IRQ %d\n", irq))
 					break;
 
 				if (desc->status & IRQ_DISABLED)
@@ -218,7 +217,7 @@ static void pcap_irq_handler(unsigned in
 {
 	struct pcap_chip *pcap = get_irq_data(irq);
 
-	desc->chip->ack(irq);
+	desc->irq_data.chip->irq_ack(&desc->irq_data);
 	queue_work(pcap->workqueue, &pcap->isr_work);
 	return;
 }
@@ -282,7 +281,7 @@ static irqreturn_t pcap_adc_irq(int irq,
 	mutex_lock(&pcap->adc_mutex);
 	req = pcap->adc_queue[pcap->adc_head];
 
-	if (WARN(!req, KERN_WARNING "adc irq without pending request\n")) {
+	if (WARN(!req, "adc irq without pending request\n")) {
 		mutex_unlock(&pcap->adc_mutex);
 		return IRQ_HANDLED;
 	}
diff -druNp linux-libre-2.6.37-gnu1/drivers/mfd/htc-egpio.c linux-libre-2.6.38-gnu1/drivers/mfd/htc-egpio.c
--- linux-libre-2.6.37-gnu1/drivers/mfd/htc-egpio.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mfd/htc-egpio.c	2011-03-14 21:20:32.000000000 -0400
@@ -70,31 +70,32 @@ static inline void ack_irqs(struct egpio
 			ei->ack_write, ei->ack_register << ei->bus_shift);
 }
 
-static void egpio_ack(unsigned int irq)
+static void egpio_ack(struct irq_data *data)
 {
 }
 
 /* There does not appear to be a way to proactively mask interrupts
  * on the egpio chip itself.  So, we simply ignore interrupts that
  * aren't desired. */
-static void egpio_mask(unsigned int irq)
+static void egpio_mask(struct irq_data *data)
 {
-	struct egpio_info *ei = get_irq_chip_data(irq);
-	ei->irqs_enabled &= ~(1 << (irq - ei->irq_start));
-	pr_debug("EGPIO mask %d %04x\n", irq, ei->irqs_enabled);
+	struct egpio_info *ei = irq_data_get_irq_chip_data(data);
+	ei->irqs_enabled &= ~(1 << (data->irq - ei->irq_start));
+	pr_debug("EGPIO mask %d %04x\n", data->irq, ei->irqs_enabled);
 }
-static void egpio_unmask(unsigned int irq)
+
+static void egpio_unmask(struct irq_data *data)
 {
-	struct egpio_info *ei = get_irq_chip_data(irq);
-	ei->irqs_enabled |= 1 << (irq - ei->irq_start);
-	pr_debug("EGPIO unmask %d %04x\n", irq, ei->irqs_enabled);
+	struct egpio_info *ei = irq_data_get_irq_chip_data(data);
+	ei->irqs_enabled |= 1 << (data->irq - ei->irq_start);
+	pr_debug("EGPIO unmask %d %04x\n", data->irq, ei->irqs_enabled);
 }
 
 static struct irq_chip egpio_muxed_chip = {
-	.name   = "htc-egpio",
-	.ack	= egpio_ack,
-	.mask   = egpio_mask,
-	.unmask = egpio_unmask,
+	.name		= "htc-egpio",
+	.irq_ack	= egpio_ack,
+	.irq_mask	= egpio_mask,
+	.irq_unmask	= egpio_unmask,
 };
 
 static void egpio_handler(unsigned int irq, struct irq_desc *desc)
diff -druNp linux-libre-2.6.37-gnu1/drivers/mfd/htc-i2cpld.c linux-libre-2.6.38-gnu1/drivers/mfd/htc-i2cpld.c
--- linux-libre-2.6.37-gnu1/drivers/mfd/htc-i2cpld.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mfd/htc-i2cpld.c	2011-03-14 21:20:32.000000000 -0400
@@ -82,25 +82,25 @@ struct htcpld_data {
 /* There does not appear to be a way to proactively mask interrupts
  * on the htcpld chip itself.  So, we simply ignore interrupts that
  * aren't desired. */
-static void htcpld_mask(unsigned int irq)
+static void htcpld_mask(struct irq_data *data)
 {
-	struct htcpld_chip *chip = get_irq_chip_data(irq);
-	chip->irqs_enabled &= ~(1 << (irq - chip->irq_start));
-	pr_debug("HTCPLD mask %d %04x\n", irq, chip->irqs_enabled);
+	struct htcpld_chip *chip = irq_data_get_irq_chip_data(data);
+	chip->irqs_enabled &= ~(1 << (data->irq - chip->irq_start));
+	pr_debug("HTCPLD mask %d %04x\n", data->irq, chip->irqs_enabled);
 }
-static void htcpld_unmask(unsigned int irq)
+static void htcpld_unmask(struct irq_data *data)
 {
-	struct htcpld_chip *chip = get_irq_chip_data(irq);
-	chip->irqs_enabled |= 1 << (irq - chip->irq_start);
-	pr_debug("HTCPLD unmask %d %04x\n", irq, chip->irqs_enabled);
+	struct htcpld_chip *chip = irq_data_get_irq_chip_data(data);
+	chip->irqs_enabled |= 1 << (data->irq - chip->irq_start);
+	pr_debug("HTCPLD unmask %d %04x\n", data->irq, chip->irqs_enabled);
 }
 
-static int htcpld_set_type(unsigned int irq, unsigned int flags)
+static int htcpld_set_type(struct irq_data *data, unsigned int flags)
 {
-	struct irq_desc *d = irq_to_desc(irq);
+	struct irq_desc *d = irq_to_desc(data->irq);
 
 	if (!d) {
-		pr_err("HTCPLD invalid IRQ: %d\n", irq);
+		pr_err("HTCPLD invalid IRQ: %d\n", data->irq);
 		return -EINVAL;
 	}
 
@@ -118,10 +118,10 @@ static int htcpld_set_type(unsigned int
 }
 
 static struct irq_chip htcpld_muxed_chip = {
-	.name     = "htcpld",
-	.mask     = htcpld_mask,
-	.unmask   = htcpld_unmask,
-	.set_type = htcpld_set_type,
+	.name         = "htcpld",
+	.irq_mask     = htcpld_mask,
+	.irq_unmask   = htcpld_unmask,
+	.irq_set_type = htcpld_set_type,
 };
 
 /* To properly dispatch IRQ events, we need to read from the
@@ -235,7 +235,7 @@ static irqreturn_t htcpld_handler(int ir
  * and that work is scheduled in the set routine.  The kernel can then run
  * the I2C functions, which will sleep, in process context.
  */
-void htcpld_chip_set(struct gpio_chip *chip, unsigned offset, int val)
+static void htcpld_chip_set(struct gpio_chip *chip, unsigned offset, int val)
 {
 	struct i2c_client *client;
 	struct htcpld_chip *chip_data;
@@ -259,7 +259,7 @@ void htcpld_chip_set(struct gpio_chip *c
 	schedule_work(&(chip_data->set_val_work));
 }
 
-void htcpld_chip_set_ni(struct work_struct *work)
+static void htcpld_chip_set_ni(struct work_struct *work)
 {
 	struct htcpld_chip *chip_data;
 	struct i2c_client *client;
@@ -269,7 +269,7 @@ void htcpld_chip_set_ni(struct work_stru
 	i2c_smbus_read_byte_data(client, chip_data->cache_out);
 }
 
-int htcpld_chip_get(struct gpio_chip *chip, unsigned offset)
+static int htcpld_chip_get(struct gpio_chip *chip, unsigned offset)
 {
 	struct htcpld_chip *chip_data;
 	int val = 0;
@@ -316,7 +316,7 @@ static int htcpld_direction_input(struct
 	return (offset < chip->ngpio) ? 0 : -EINVAL;
 }
 
-int htcpld_chip_to_irq(struct gpio_chip *chip, unsigned offset)
+static int htcpld_chip_to_irq(struct gpio_chip *chip, unsigned offset)
 {
 	struct htcpld_chip *chip_data;
 
@@ -328,7 +328,7 @@ int htcpld_chip_to_irq(struct gpio_chip
 		return -EINVAL;
 }
 
-void htcpld_chip_reset(struct i2c_client *client)
+static void htcpld_chip_reset(struct i2c_client *client)
 {
 	struct htcpld_chip *chip_data = i2c_get_clientdata(client);
 	if (!chip_data)
diff -druNp linux-libre-2.6.37-gnu1/drivers/mfd/jz4740-adc.c linux-libre-2.6.38-gnu1/drivers/mfd/jz4740-adc.c
--- linux-libre-2.6.37-gnu1/drivers/mfd/jz4740-adc.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mfd/jz4740-adc.c	2011-03-14 21:20:32.000000000 -0400
@@ -84,31 +84,30 @@ static inline void jz4740_adc_irq_set_ma
 	spin_unlock_irqrestore(&adc->lock, flags);
 }
 
-static void jz4740_adc_irq_mask(unsigned int irq)
+static void jz4740_adc_irq_mask(struct irq_data *data)
 {
-	struct jz4740_adc *adc = get_irq_chip_data(irq);
-	jz4740_adc_irq_set_masked(adc, irq, true);
+	struct jz4740_adc *adc = irq_data_get_irq_chip_data(data);
+	jz4740_adc_irq_set_masked(adc, data->irq, true);
 }
 
-static void jz4740_adc_irq_unmask(unsigned int irq)
+static void jz4740_adc_irq_unmask(struct irq_data *data)
 {
-	struct jz4740_adc *adc = get_irq_chip_data(irq);
-	jz4740_adc_irq_set_masked(adc, irq, false);
+	struct jz4740_adc *adc = irq_data_get_irq_chip_data(data);
+	jz4740_adc_irq_set_masked(adc, data->irq, false);
 }
 
-static void jz4740_adc_irq_ack(unsigned int irq)
+static void jz4740_adc_irq_ack(struct irq_data *data)
 {
-	struct jz4740_adc *adc = get_irq_chip_data(irq);
-
-	irq -= adc->irq_base;
+	struct jz4740_adc *adc = irq_data_get_irq_chip_data(data);
+	unsigned int irq = data->irq - adc->irq_base;
 	writeb(BIT(irq), adc->base + JZ_REG_ADC_STATUS);
 }
 
 static struct irq_chip jz4740_adc_irq_chip = {
 	.name = "jz4740-adc",
-	.mask = jz4740_adc_irq_mask,
-	.unmask = jz4740_adc_irq_unmask,
-	.ack = jz4740_adc_irq_ack,
+	.irq_mask = jz4740_adc_irq_mask,
+	.irq_unmask = jz4740_adc_irq_unmask,
+	.irq_ack = jz4740_adc_irq_ack,
 };
 
 static void jz4740_adc_irq_demux(unsigned int irq, struct irq_desc *desc)
diff -druNp linux-libre-2.6.37-gnu1/drivers/mfd/Kconfig linux-libre-2.6.38-gnu1/drivers/mfd/Kconfig
--- linux-libre-2.6.37-gnu1/drivers/mfd/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mfd/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -218,12 +218,12 @@ config MFD_STMPE
 		Keypad: stmpe-keypad
 		Touchscreen: stmpe-ts
 
-config MFD_TC35892
-	bool "Support Toshiba TC35892"
+config MFD_TC3589X
+	bool "Support Toshiba TC35892 and variants"
 	depends on I2C=y && GENERIC_HARDIRQS
 	select MFD_CORE
 	help
-	  Support for the Toshiba TC35892 I/O Expander.
+	  Support for the Toshiba TC35892 and variants I/O Expander.
 
 	  This driver provides common support for accessing the device,
 	  additional drivers must be enabled in order to use the
@@ -496,13 +496,13 @@ config EZX_PCAP
 
 config AB8500_CORE
 	bool "ST-Ericsson AB8500 Mixed Signal Power Management chip"
-	depends on GENERIC_HARDIRQS && ABX500_CORE && SPI_MASTER && ARCH_U8500
+	depends on GENERIC_HARDIRQS && ABX500_CORE
 	select MFD_CORE
 	help
 	  Select this option to enable access to AB8500 power management
-	  chip. This connects to U8500 either on the SSP/SPI bus
-	  or the I2C bus via PRCMU. It also adds the irq_chip
-	  parts for handling the Mixed Signal chip events.
+	  chip. This connects to U8500 either on the SSP/SPI bus (deprecated
+	  since hardware version v1.0) or the I2C bus via PRCMU. It also adds
+	  the irq_chip parts for handling the Mixed Signal chip events.
 	  This chip embeds various other multimedia funtionalities as well.
 
 config AB8500_I2C_CORE
@@ -537,6 +537,14 @@ config AB3550_CORE
 	  LEDs, vibrator, system power and temperature, power management
 	  and ALSA sound.
 
+config MFD_CS5535
+	tristate "Support for CS5535 and CS5536 southbridge core functions"
+	select MFD_CORE
+	depends on PCI
+	---help---
+	  This is the core driver for CS5535/CS5536 MFD functions.  This is
+          necessary for using the board's GPIO and MFGPT functionality.
+
 config MFD_TIMBERDALE
 	tristate "Support for the Timberdale FPGA"
 	select MFD_CORE
@@ -606,6 +614,16 @@ config MFD_VX855
 	  VIA VX855/VX875 south bridge. You will need to enable the vx855_spi
 	  and/or vx855_gpio drivers for this to do anything useful.
 
+config MFD_WL1273_CORE
+	tristate
+	depends on I2C
+	select MFD_CORE
+	default n
+	help
+	  This is the core driver for the TI WL1273 FM radio. This MFD
+	  driver connects the radio-wl1273 V4L2 module and the wl1273
+	  audio codec.
+
 endif # MFD_SUPPORT
 
 menu "Multimedia Capabilities Port drivers"
diff -druNp linux-libre-2.6.37-gnu1/drivers/mfd/Makefile linux-libre-2.6.38-gnu1/drivers/mfd/Makefile
--- linux-libre-2.6.37-gnu1/drivers/mfd/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mfd/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -16,7 +16,7 @@ obj-$(CONFIG_MFD_DAVINCI_VOICECODEC)	+=
 obj-$(CONFIG_MFD_DM355EVM_MSP)	+= dm355evm_msp.o
 
 obj-$(CONFIG_MFD_STMPE)		+= stmpe.o
-obj-$(CONFIG_MFD_TC35892)	+= tc35892.o
+obj-$(CONFIG_MFD_TC3589X)	+= tc3589x.o
 obj-$(CONFIG_MFD_T7L66XB)	+= t7l66xb.o tmio_core.o
 obj-$(CONFIG_MFD_TC6387XB)	+= tc6387xb.o tmio_core.o
 obj-$(CONFIG_MFD_TC6393XB)	+= tc6393xb.o tmio_core.o
@@ -70,7 +70,7 @@ obj-$(CONFIG_ABX500_CORE)	+= abx500-core
 obj-$(CONFIG_AB3100_CORE)	+= ab3100-core.o
 obj-$(CONFIG_AB3100_OTP)	+= ab3100-otp.o
 obj-$(CONFIG_AB3550_CORE)	+= ab3550-core.o
-obj-$(CONFIG_AB8500_CORE)	+= ab8500-core.o ab8500-spi.o
+obj-$(CONFIG_AB8500_CORE)	+= ab8500-core.o
 obj-$(CONFIG_AB8500_I2C_CORE)	+= ab8500-i2c.o
 obj-$(CONFIG_AB8500_DEBUG)	+= ab8500-debugfs.o
 obj-$(CONFIG_MFD_TIMBERDALE)    += timberdale.o
@@ -81,3 +81,5 @@ obj-$(CONFIG_MFD_JANZ_CMODIO)	+= janz-cm
 obj-$(CONFIG_MFD_JZ4740_ADC)	+= jz4740-adc.o
 obj-$(CONFIG_MFD_TPS6586X)	+= tps6586x.o
 obj-$(CONFIG_MFD_VX855)		+= vx855.o
+obj-$(CONFIG_MFD_WL1273_CORE)	+= wl1273-core.o
+obj-$(CONFIG_MFD_CS5535)	+= cs5535-mfd.o
diff -druNp linux-libre-2.6.37-gnu1/drivers/mfd/max8925-core.c linux-libre-2.6.38-gnu1/drivers/mfd/max8925-core.c
--- linux-libre-2.6.37-gnu1/drivers/mfd/max8925-core.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mfd/max8925-core.c	2011-03-14 21:20:32.000000000 -0400
@@ -407,16 +407,16 @@ static irqreturn_t max8925_tsc_irq(int i
 	return IRQ_HANDLED;
 }
 
-static void max8925_irq_lock(unsigned int irq)
+static void max8925_irq_lock(struct irq_data *data)
 {
-	struct max8925_chip *chip = get_irq_chip_data(irq);
+	struct max8925_chip *chip = irq_data_get_irq_chip_data(data);
 
 	mutex_lock(&chip->irq_lock);
 }
 
-static void max8925_irq_sync_unlock(unsigned int irq)
+static void max8925_irq_sync_unlock(struct irq_data *data)
 {
-	struct max8925_chip *chip = get_irq_chip_data(irq);
+	struct max8925_chip *chip = irq_data_get_irq_chip_data(data);
 	struct max8925_irq_data *irq_data;
 	static unsigned char cache_chg[2] = {0xff, 0xff};
 	static unsigned char cache_on[2] = {0xff, 0xff};
@@ -492,25 +492,25 @@ static void max8925_irq_sync_unlock(unsi
 	mutex_unlock(&chip->irq_lock);
 }
 
-static void max8925_irq_enable(unsigned int irq)
+static void max8925_irq_enable(struct irq_data *data)
 {
-	struct max8925_chip *chip = get_irq_chip_data(irq);
-	max8925_irqs[irq - chip->irq_base].enable
-		= max8925_irqs[irq - chip->irq_base].offs;
+	struct max8925_chip *chip = irq_data_get_irq_chip_data(data);
+	max8925_irqs[data->irq - chip->irq_base].enable
+		= max8925_irqs[data->irq - chip->irq_base].offs;
 }
 
-static void max8925_irq_disable(unsigned int irq)
+static void max8925_irq_disable(struct irq_data *data)
 {
-	struct max8925_chip *chip = get_irq_chip_data(irq);
-	max8925_irqs[irq - chip->irq_base].enable = 0;
+	struct max8925_chip *chip = irq_data_get_irq_chip_data(data);
+	max8925_irqs[data->irq - chip->irq_base].enable = 0;
 }
 
 static struct irq_chip max8925_irq_chip = {
 	.name		= "max8925",
-	.bus_lock	= max8925_irq_lock,
-	.bus_sync_unlock = max8925_irq_sync_unlock,
-	.enable		= max8925_irq_enable,
-	.disable	= max8925_irq_disable,
+	.irq_bus_lock	= max8925_irq_lock,
+	.irq_bus_sync_unlock = max8925_irq_sync_unlock,
+	.irq_enable	= max8925_irq_enable,
+	.irq_disable	= max8925_irq_disable,
 };
 
 static int max8925_irq_init(struct max8925_chip *chip, int irq,
diff -druNp linux-libre-2.6.37-gnu1/drivers/mfd/max8998.c linux-libre-2.6.38-gnu1/drivers/mfd/max8998.c
--- linux-libre-2.6.37-gnu1/drivers/mfd/max8998.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mfd/max8998.c	2011-03-14 21:20:32.000000000 -0400
@@ -25,6 +25,8 @@
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/pm_runtime.h>
 #include <linux/mutex.h>
 #include <linux/mfd/core.h>
 #include <linux/mfd/max8998.h>
@@ -40,6 +42,14 @@ static struct mfd_cell max8998_devs[] =
 	},
 };
 
+static struct mfd_cell lp3974_devs[] = {
+	{
+		.name = "lp3974-pmic",
+	}, {
+		.name = "lp3974-rtc",
+	},
+};
+
 int max8998_read_reg(struct i2c_client *i2c, u8 reg, u8 *dest)
 {
 	struct max8998_dev *max8998 = i2c_get_clientdata(i2c);
@@ -135,6 +145,7 @@ static int max8998_i2c_probe(struct i2c_
 	if (pdata) {
 		max8998->ono = pdata->ono;
 		max8998->irq_base = pdata->irq_base;
+		max8998->wakeup = pdata->wakeup;
 	}
 	mutex_init(&max8998->iolock);
 
@@ -143,9 +154,23 @@ static int max8998_i2c_probe(struct i2c_
 
 	max8998_irq_init(max8998);
 
-	ret = mfd_add_devices(max8998->dev, -1,
-			      max8998_devs, ARRAY_SIZE(max8998_devs),
-			      NULL, 0);
+	pm_runtime_set_active(max8998->dev);
+
+	switch (id->driver_data) {
+	case TYPE_LP3974:
+		ret = mfd_add_devices(max8998->dev, -1,
+				lp3974_devs, ARRAY_SIZE(lp3974_devs),
+				NULL, 0);
+		break;
+	case TYPE_MAX8998:
+		ret = mfd_add_devices(max8998->dev, -1,
+				max8998_devs, ARRAY_SIZE(max8998_devs),
+				NULL, 0);
+		break;
+	default:
+		ret = -EINVAL;
+	}
+
 	if (ret < 0)
 		goto err;
 
@@ -178,10 +203,113 @@ static const struct i2c_device_id max899
 };
 MODULE_DEVICE_TABLE(i2c, max8998_i2c_id);
 
+static int max8998_suspend(struct device *dev)
+{
+	struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
+	struct max8998_dev *max8998 = i2c_get_clientdata(i2c);
+
+	if (max8998->wakeup)
+		set_irq_wake(max8998->irq, 1);
+	return 0;
+}
+
+static int max8998_resume(struct device *dev)
+{
+	struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
+	struct max8998_dev *max8998 = i2c_get_clientdata(i2c);
+
+	if (max8998->wakeup)
+		set_irq_wake(max8998->irq, 0);
+	/*
+	 * In LP3974, if IRQ registers are not "read & clear"
+	 * when it's set during sleep, the interrupt becomes
+	 * disabled.
+	 */
+	return max8998_irq_resume(i2c_get_clientdata(i2c));
+}
+
+struct max8998_reg_dump {
+	u8	addr;
+	u8	val;
+};
+#define SAVE_ITEM(x)	{ .addr = (x), .val = 0x0, }
+struct max8998_reg_dump max8998_dump[] = {
+	SAVE_ITEM(MAX8998_REG_IRQM1),
+	SAVE_ITEM(MAX8998_REG_IRQM2),
+	SAVE_ITEM(MAX8998_REG_IRQM3),
+	SAVE_ITEM(MAX8998_REG_IRQM4),
+	SAVE_ITEM(MAX8998_REG_STATUSM1),
+	SAVE_ITEM(MAX8998_REG_STATUSM2),
+	SAVE_ITEM(MAX8998_REG_CHGR1),
+	SAVE_ITEM(MAX8998_REG_CHGR2),
+	SAVE_ITEM(MAX8998_REG_LDO_ACTIVE_DISCHARGE1),
+	SAVE_ITEM(MAX8998_REG_LDO_ACTIVE_DISCHARGE1),
+	SAVE_ITEM(MAX8998_REG_BUCK_ACTIVE_DISCHARGE3),
+	SAVE_ITEM(MAX8998_REG_ONOFF1),
+	SAVE_ITEM(MAX8998_REG_ONOFF2),
+	SAVE_ITEM(MAX8998_REG_ONOFF3),
+	SAVE_ITEM(MAX8998_REG_ONOFF4),
+	SAVE_ITEM(MAX8998_REG_BUCK1_VOLTAGE1),
+	SAVE_ITEM(MAX8998_REG_BUCK1_VOLTAGE2),
+	SAVE_ITEM(MAX8998_REG_BUCK1_VOLTAGE3),
+	SAVE_ITEM(MAX8998_REG_BUCK1_VOLTAGE4),
+	SAVE_ITEM(MAX8998_REG_BUCK2_VOLTAGE1),
+	SAVE_ITEM(MAX8998_REG_BUCK2_VOLTAGE2),
+	SAVE_ITEM(MAX8998_REG_LDO2_LDO3),
+	SAVE_ITEM(MAX8998_REG_LDO4),
+	SAVE_ITEM(MAX8998_REG_LDO5),
+	SAVE_ITEM(MAX8998_REG_LDO6),
+	SAVE_ITEM(MAX8998_REG_LDO7),
+	SAVE_ITEM(MAX8998_REG_LDO8_LDO9),
+	SAVE_ITEM(MAX8998_REG_LDO10_LDO11),
+	SAVE_ITEM(MAX8998_REG_LDO12),
+	SAVE_ITEM(MAX8998_REG_LDO13),
+	SAVE_ITEM(MAX8998_REG_LDO14),
+	SAVE_ITEM(MAX8998_REG_LDO15),
+	SAVE_ITEM(MAX8998_REG_LDO16),
+	SAVE_ITEM(MAX8998_REG_LDO17),
+	SAVE_ITEM(MAX8998_REG_BKCHR),
+	SAVE_ITEM(MAX8998_REG_LBCNFG1),
+	SAVE_ITEM(MAX8998_REG_LBCNFG2),
+};
+/* Save registers before hibernation */
+static int max8998_freeze(struct device *dev)
+{
+	struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(max8998_dump); i++)
+		max8998_read_reg(i2c, max8998_dump[i].addr,
+				&max8998_dump[i].val);
+
+	return 0;
+}
+
+/* Restore registers after hibernation */
+static int max8998_restore(struct device *dev)
+{
+	struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(max8998_dump); i++)
+		max8998_write_reg(i2c, max8998_dump[i].addr,
+				max8998_dump[i].val);
+
+	return 0;
+}
+
+const struct dev_pm_ops max8998_pm = {
+	.suspend = max8998_suspend,
+	.resume = max8998_resume,
+	.freeze = max8998_freeze,
+	.restore = max8998_restore,
+};
+
 static struct i2c_driver max8998_i2c_driver = {
 	.driver = {
 		   .name = "max8998",
 		   .owner = THIS_MODULE,
+		   .pm = &max8998_pm,
 	},
 	.probe = max8998_i2c_probe,
 	.remove = max8998_i2c_remove,
diff -druNp linux-libre-2.6.37-gnu1/drivers/mfd/max8998-irq.c linux-libre-2.6.38-gnu1/drivers/mfd/max8998-irq.c
--- linux-libre-2.6.37-gnu1/drivers/mfd/max8998-irq.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mfd/max8998-irq.c	2011-03-14 21:20:32.000000000 -0400
@@ -102,16 +102,16 @@ irq_to_max8998_irq(struct max8998_dev *m
 	return &max8998_irqs[irq - max8998->irq_base];
 }
 
-static void max8998_irq_lock(unsigned int irq)
+static void max8998_irq_lock(struct irq_data *data)
 {
-	struct max8998_dev *max8998 = get_irq_chip_data(irq);
+	struct max8998_dev *max8998 = irq_data_get_irq_chip_data(data);
 
 	mutex_lock(&max8998->irqlock);
 }
 
-static void max8998_irq_sync_unlock(unsigned int irq)
+static void max8998_irq_sync_unlock(struct irq_data *data)
 {
-	struct max8998_dev *max8998 = get_irq_chip_data(irq);
+	struct max8998_dev *max8998 = irq_data_get_irq_chip_data(data);
 	int i;
 
 	for (i = 0; i < ARRAY_SIZE(max8998->irq_masks_cur); i++) {
@@ -129,28 +129,30 @@ static void max8998_irq_sync_unlock(unsi
 	mutex_unlock(&max8998->irqlock);
 }
 
-static void max8998_irq_unmask(unsigned int irq)
+static void max8998_irq_unmask(struct irq_data *data)
 {
-	struct max8998_dev *max8998 = get_irq_chip_data(irq);
-	struct max8998_irq_data *irq_data = irq_to_max8998_irq(max8998, irq);
+	struct max8998_dev *max8998 = irq_data_get_irq_chip_data(data);
+	struct max8998_irq_data *irq_data = irq_to_max8998_irq(max8998,
+							       data->irq);
 
 	max8998->irq_masks_cur[irq_data->reg - 1] &= ~irq_data->mask;
 }
 
-static void max8998_irq_mask(unsigned int irq)
+static void max8998_irq_mask(struct irq_data *data)
 {
-	struct max8998_dev *max8998 = get_irq_chip_data(irq);
-	struct max8998_irq_data *irq_data = irq_to_max8998_irq(max8998, irq);
+	struct max8998_dev *max8998 = irq_data_get_irq_chip_data(data);
+	struct max8998_irq_data *irq_data = irq_to_max8998_irq(max8998,
+							       data->irq);
 
 	max8998->irq_masks_cur[irq_data->reg - 1] |= irq_data->mask;
 }
 
 static struct irq_chip max8998_irq_chip = {
 	.name = "max8998",
-	.bus_lock = max8998_irq_lock,
-	.bus_sync_unlock = max8998_irq_sync_unlock,
-	.mask = max8998_irq_mask,
-	.unmask = max8998_irq_unmask,
+	.irq_bus_lock = max8998_irq_lock,
+	.irq_bus_sync_unlock = max8998_irq_sync_unlock,
+	.irq_mask = max8998_irq_mask,
+	.irq_unmask = max8998_irq_unmask,
 };
 
 static irqreturn_t max8998_irq_thread(int irq, void *data)
@@ -181,6 +183,13 @@ static irqreturn_t max8998_irq_thread(in
 	return IRQ_HANDLED;
 }
 
+int max8998_irq_resume(struct max8998_dev *max8998)
+{
+	if (max8998->irq && max8998->irq_base)
+		max8998_irq_thread(max8998->irq_base, max8998);
+	return 0;
+}
+
 int max8998_irq_init(struct max8998_dev *max8998)
 {
 	int i;
diff -druNp linux-libre-2.6.37-gnu1/drivers/mfd/mc13xxx-core.c linux-libre-2.6.38-gnu1/drivers/mfd/mc13xxx-core.c
--- linux-libre-2.6.37-gnu1/drivers/mfd/mc13xxx-core.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mfd/mc13xxx-core.c	2011-03-14 21:20:32.000000000 -0400
@@ -749,7 +749,7 @@ static int mc13xxx_probe(struct spi_devi
 	if (ret) {
 err_mask:
 err_revision:
-		mutex_unlock(&mc13xxx->lock);
+		mc13xxx_unlock(mc13xxx);
 		dev_set_drvdata(&spi->dev, NULL);
 		kfree(mc13xxx);
 		return ret;
diff -druNp linux-libre-2.6.37-gnu1/drivers/mfd/menelaus.c linux-libre-2.6.38-gnu1/drivers/mfd/menelaus.c
--- linux-libre-2.6.37-gnu1/drivers/mfd/menelaus.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mfd/menelaus.c	2011-03-14 21:20:32.000000000 -0400
@@ -1259,7 +1259,7 @@ static int menelaus_probe(struct i2c_cli
 	return 0;
 fail2:
 	free_irq(client->irq, menelaus);
-	flush_scheduled_work();
+	flush_work_sync(&menelaus->work);
 fail1:
 	kfree(menelaus);
 	return err;
@@ -1270,6 +1270,7 @@ static int __exit menelaus_remove(struct
 	struct menelaus_chip	*menelaus = i2c_get_clientdata(client);
 
 	free_irq(client->irq, menelaus);
+	flush_work_sync(&menelaus->work);
 	kfree(menelaus);
 	the_menelaus = NULL;
 	return 0;
diff -druNp linux-libre-2.6.37-gnu1/drivers/mfd/mfd-core.c linux-libre-2.6.38-gnu1/drivers/mfd/mfd-core.c
--- linux-libre-2.6.37-gnu1/drivers/mfd/mfd-core.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mfd/mfd-core.c	2011-03-14 21:20:32.000000000 -0400
@@ -15,6 +15,7 @@
 #include <linux/platform_device.h>
 #include <linux/acpi.h>
 #include <linux/mfd/core.h>
+#include <linux/pm_runtime.h>
 #include <linux/slab.h>
 
 static int mfd_add_device(struct device *parent, int id,
@@ -82,6 +83,9 @@ static int mfd_add_device(struct device
 	if (ret)
 		goto fail_res;
 
+	if (cell->pm_runtime_no_callbacks)
+		pm_runtime_no_callbacks(&pdev->dev);
+
 	kfree(res);
 
 	return 0;
diff -druNp linux-libre-2.6.37-gnu1/drivers/mfd/sh_mobile_sdhi.c linux-libre-2.6.38-gnu1/drivers/mfd/sh_mobile_sdhi.c
--- linux-libre-2.6.37-gnu1/drivers/mfd/sh_mobile_sdhi.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mfd/sh_mobile_sdhi.c	2011-03-14 21:20:32.000000000 -0400
@@ -131,11 +131,17 @@ static int __devinit sh_mobile_sdhi_prob
 	 */
 	mmc_data->flags |= TMIO_MMC_BLKSZ_2BYTES;
 
+	/*
+	 * All SDHI blocks support SDIO IRQ signalling.
+	 */
+	mmc_data->flags |= TMIO_MMC_SDIO_IRQ;
+
 	if (p && p->dma_slave_tx >= 0 && p->dma_slave_rx >= 0) {
 		priv->param_tx.slave_id = p->dma_slave_tx;
 		priv->param_rx.slave_id = p->dma_slave_rx;
 		priv->dma_priv.chan_priv_tx = &priv->param_tx;
 		priv->dma_priv.chan_priv_rx = &priv->param_rx;
+		priv->dma_priv.alignment_shift = 1; /* 2-byte alignment */
 		mmc_data->dma = &priv->dma_priv;
 	}
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/mfd/sm501.c linux-libre-2.6.38-gnu1/drivers/mfd/sm501.c
--- linux-libre-2.6.37-gnu1/drivers/mfd/sm501.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mfd/sm501.c	2011-03-14 21:20:32.000000000 -0400
@@ -26,7 +26,7 @@
 #include <linux/sm501-regs.h>
 #include <linux/serial_8250.h>
 
-#include <asm/io.h>
+#include <linux/io.h>
 
 struct sm501_device {
 	struct list_head		list;
@@ -745,11 +745,8 @@ static int sm501_register_device(struct
 	int ret;
 
 	for (ptr = 0; ptr < pdev->num_resources; ptr++) {
-		printk(KERN_DEBUG "%s[%d] flags %08lx: %08llx..%08llx\n",
-		       pdev->name, ptr,
-		       pdev->resource[ptr].flags,
-		       (unsigned long long)pdev->resource[ptr].start,
-		       (unsigned long long)pdev->resource[ptr].end);
+		printk(KERN_DEBUG "%s[%d] %pR\n",
+		       pdev->name, ptr, &pdev->resource[ptr]);
 	}
 
 	ret = platform_device_register(pdev);
diff -druNp linux-libre-2.6.37-gnu1/drivers/mfd/stmpe.c linux-libre-2.6.38-gnu1/drivers/mfd/stmpe.c
--- linux-libre-2.6.37-gnu1/drivers/mfd/stmpe.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mfd/stmpe.c	2011-03-14 21:20:32.000000000 -0400
@@ -699,16 +699,16 @@ static irqreturn_t stmpe_irq(int irq, vo
 	return IRQ_HANDLED;
 }
 
-static void stmpe_irq_lock(unsigned int irq)
+static void stmpe_irq_lock(struct irq_data *data)
 {
-	struct stmpe *stmpe = get_irq_chip_data(irq);
+	struct stmpe *stmpe = irq_data_get_irq_chip_data(data);
 
 	mutex_lock(&stmpe->irq_lock);
 }
 
-static void stmpe_irq_sync_unlock(unsigned int irq)
+static void stmpe_irq_sync_unlock(struct irq_data *data)
 {
-	struct stmpe *stmpe = get_irq_chip_data(irq);
+	struct stmpe *stmpe = irq_data_get_irq_chip_data(data);
 	struct stmpe_variant_info *variant = stmpe->variant;
 	int num = DIV_ROUND_UP(variant->num_irqs, 8);
 	int i;
@@ -727,20 +727,20 @@ static void stmpe_irq_sync_unlock(unsign
 	mutex_unlock(&stmpe->irq_lock);
 }
 
-static void stmpe_irq_mask(unsigned int irq)
+static void stmpe_irq_mask(struct irq_data *data)
 {
-	struct stmpe *stmpe = get_irq_chip_data(irq);
-	int offset = irq - stmpe->irq_base;
+	struct stmpe *stmpe = irq_data_get_irq_chip_data(data);
+	int offset = data->irq - stmpe->irq_base;
 	int regoffset = offset / 8;
 	int mask = 1 << (offset % 8);
 
 	stmpe->ier[regoffset] &= ~mask;
 }
 
-static void stmpe_irq_unmask(unsigned int irq)
+static void stmpe_irq_unmask(struct irq_data *data)
 {
-	struct stmpe *stmpe = get_irq_chip_data(irq);
-	int offset = irq - stmpe->irq_base;
+	struct stmpe *stmpe = irq_data_get_irq_chip_data(data);
+	int offset = data->irq - stmpe->irq_base;
 	int regoffset = offset / 8;
 	int mask = 1 << (offset % 8);
 
@@ -749,10 +749,10 @@ static void stmpe_irq_unmask(unsigned in
 
 static struct irq_chip stmpe_irq_chip = {
 	.name			= "stmpe",
-	.bus_lock		= stmpe_irq_lock,
-	.bus_sync_unlock	= stmpe_irq_sync_unlock,
-	.mask			= stmpe_irq_mask,
-	.unmask			= stmpe_irq_unmask,
+	.irq_bus_lock		= stmpe_irq_lock,
+	.irq_bus_sync_unlock	= stmpe_irq_sync_unlock,
+	.irq_mask		= stmpe_irq_mask,
+	.irq_unmask		= stmpe_irq_unmask,
 };
 
 static int __devinit stmpe_irq_init(struct stmpe *stmpe)
diff -druNp linux-libre-2.6.37-gnu1/drivers/mfd/t7l66xb.c linux-libre-2.6.38-gnu1/drivers/mfd/t7l66xb.c
--- linux-libre-2.6.37-gnu1/drivers/mfd/t7l66xb.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mfd/t7l66xb.c	2011-03-14 21:20:32.000000000 -0400
@@ -199,37 +199,37 @@ static void t7l66xb_irq(unsigned int irq
 				generic_handle_irq(irq_base + i);
 }
 
-static void t7l66xb_irq_mask(unsigned int irq)
+static void t7l66xb_irq_mask(struct irq_data *data)
 {
-	struct t7l66xb *t7l66xb = get_irq_chip_data(irq);
+	struct t7l66xb *t7l66xb = irq_data_get_irq_chip_data(data);
 	unsigned long			flags;
 	u8 imr;
 
 	spin_lock_irqsave(&t7l66xb->lock, flags);
 	imr = tmio_ioread8(t7l66xb->scr + SCR_IMR);
-	imr |= 1 << (irq - t7l66xb->irq_base);
+	imr |= 1 << (data->irq - t7l66xb->irq_base);
 	tmio_iowrite8(imr, t7l66xb->scr + SCR_IMR);
 	spin_unlock_irqrestore(&t7l66xb->lock, flags);
 }
 
-static void t7l66xb_irq_unmask(unsigned int irq)
+static void t7l66xb_irq_unmask(struct irq_data *data)
 {
-	struct t7l66xb *t7l66xb = get_irq_chip_data(irq);
+	struct t7l66xb *t7l66xb = irq_data_get_irq_chip_data(data);
 	unsigned long flags;
 	u8 imr;
 
 	spin_lock_irqsave(&t7l66xb->lock, flags);
 	imr = tmio_ioread8(t7l66xb->scr + SCR_IMR);
-	imr &= ~(1 << (irq - t7l66xb->irq_base));
+	imr &= ~(1 << (data->irq - t7l66xb->irq_base));
 	tmio_iowrite8(imr, t7l66xb->scr + SCR_IMR);
 	spin_unlock_irqrestore(&t7l66xb->lock, flags);
 }
 
 static struct irq_chip t7l66xb_chip = {
-	.name	= "t7l66xb",
-	.ack	= t7l66xb_irq_mask,
-	.mask	= t7l66xb_irq_mask,
-	.unmask	= t7l66xb_irq_unmask,
+	.name		= "t7l66xb",
+	.irq_ack	= t7l66xb_irq_mask,
+	.irq_mask	= t7l66xb_irq_mask,
+	.irq_unmask	= t7l66xb_irq_unmask,
 };
 
 /*--------------------------------------------------------------------------*/
diff -druNp linux-libre-2.6.37-gnu1/drivers/mfd/tc35892.c linux-libre-2.6.38-gnu1/drivers/mfd/tc35892.c
--- linux-libre-2.6.37-gnu1/drivers/mfd/tc35892.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mfd/tc35892.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,345 +0,0 @@
-/*
- * Copyright (C) ST-Ericsson SA 2010
- *
- * License Terms: GNU General Public License, version 2
- * Author: Hanumath Prasad <hanumath.prasad@stericsson.com> for ST-Ericsson
- * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson
- */
-
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/slab.h>
-#include <linux/i2c.h>
-#include <linux/mfd/core.h>
-#include <linux/mfd/tc35892.h>
-
-/**
- * tc35892_reg_read() - read a single TC35892 register
- * @tc35892:	Device to read from
- * @reg:	Register to read
- */
-int tc35892_reg_read(struct tc35892 *tc35892, u8 reg)
-{
-	int ret;
-
-	ret = i2c_smbus_read_byte_data(tc35892->i2c, reg);
-	if (ret < 0)
-		dev_err(tc35892->dev, "failed to read reg %#x: %d\n",
-			reg, ret);
-
-	return ret;
-}
-EXPORT_SYMBOL_GPL(tc35892_reg_read);
-
-/**
- * tc35892_reg_read() - write a single TC35892 register
- * @tc35892:	Device to write to
- * @reg:	Register to read
- * @data:	Value to write
- */
-int tc35892_reg_write(struct tc35892 *tc35892, u8 reg, u8 data)
-{
-	int ret;
-
-	ret = i2c_smbus_write_byte_data(tc35892->i2c, reg, data);
-	if (ret < 0)
-		dev_err(tc35892->dev, "failed to write reg %#x: %d\n",
-			reg, ret);
-
-	return ret;
-}
-EXPORT_SYMBOL_GPL(tc35892_reg_write);
-
-/**
- * tc35892_block_read() - read multiple TC35892 registers
- * @tc35892:	Device to read from
- * @reg:	First register
- * @length:	Number of registers
- * @values:	Buffer to write to
- */
-int tc35892_block_read(struct tc35892 *tc35892, u8 reg, u8 length, u8 *values)
-{
-	int ret;
-
-	ret = i2c_smbus_read_i2c_block_data(tc35892->i2c, reg, length, values);
-	if (ret < 0)
-		dev_err(tc35892->dev, "failed to read regs %#x: %d\n",
-			reg, ret);
-
-	return ret;
-}
-EXPORT_SYMBOL_GPL(tc35892_block_read);
-
-/**
- * tc35892_block_write() - write multiple TC35892 registers
- * @tc35892:	Device to write to
- * @reg:	First register
- * @length:	Number of registers
- * @values:	Values to write
- */
-int tc35892_block_write(struct tc35892 *tc35892, u8 reg, u8 length,
-			const u8 *values)
-{
-	int ret;
-
-	ret = i2c_smbus_write_i2c_block_data(tc35892->i2c, reg, length,
-					     values);
-	if (ret < 0)
-		dev_err(tc35892->dev, "failed to write regs %#x: %d\n",
-			reg, ret);
-
-	return ret;
-}
-EXPORT_SYMBOL_GPL(tc35892_block_write);
-
-/**
- * tc35892_set_bits() - set the value of a bitfield in a TC35892 register
- * @tc35892:	Device to write to
- * @reg:	Register to write
- * @mask:	Mask of bits to set
- * @values:	Value to set
- */
-int tc35892_set_bits(struct tc35892 *tc35892, u8 reg, u8 mask, u8 val)
-{
-	int ret;
-
-	mutex_lock(&tc35892->lock);
-
-	ret = tc35892_reg_read(tc35892, reg);
-	if (ret < 0)
-		goto out;
-
-	ret &= ~mask;
-	ret |= val;
-
-	ret = tc35892_reg_write(tc35892, reg, ret);
-
-out:
-	mutex_unlock(&tc35892->lock);
-	return ret;
-}
-EXPORT_SYMBOL_GPL(tc35892_set_bits);
-
-static struct resource gpio_resources[] = {
-	{
-		.start	= TC35892_INT_GPIIRQ,
-		.end	= TC35892_INT_GPIIRQ,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct mfd_cell tc35892_devs[] = {
-	{
-		.name		= "tc35892-gpio",
-		.num_resources	= ARRAY_SIZE(gpio_resources),
-		.resources	= &gpio_resources[0],
-	},
-};
-
-static irqreturn_t tc35892_irq(int irq, void *data)
-{
-	struct tc35892 *tc35892 = data;
-	int status;
-
-	status = tc35892_reg_read(tc35892, TC35892_IRQST);
-	if (status < 0)
-		return IRQ_NONE;
-
-	while (status) {
-		int bit = __ffs(status);
-
-		handle_nested_irq(tc35892->irq_base + bit);
-		status &= ~(1 << bit);
-	}
-
-	/*
-	 * A dummy read or write (to any register) appears to be necessary to
-	 * have the last interrupt clear (for example, GPIO IC write) take
-	 * effect.
-	 */
-	tc35892_reg_read(tc35892, TC35892_IRQST);
-
-	return IRQ_HANDLED;
-}
-
-static void tc35892_irq_dummy(unsigned int irq)
-{
-	/* No mask/unmask at this level */
-}
-
-static struct irq_chip tc35892_irq_chip = {
-	.name	= "tc35892",
-	.mask	= tc35892_irq_dummy,
-	.unmask	= tc35892_irq_dummy,
-};
-
-static int tc35892_irq_init(struct tc35892 *tc35892)
-{
-	int base = tc35892->irq_base;
-	int irq;
-
-	for (irq = base; irq < base + TC35892_NR_INTERNAL_IRQS; irq++) {
-		set_irq_chip_data(irq, tc35892);
-		set_irq_chip_and_handler(irq, &tc35892_irq_chip,
-					 handle_edge_irq);
-		set_irq_nested_thread(irq, 1);
-#ifdef CONFIG_ARM
-		set_irq_flags(irq, IRQF_VALID);
-#else
-		set_irq_noprobe(irq);
-#endif
-	}
-
-	return 0;
-}
-
-static void tc35892_irq_remove(struct tc35892 *tc35892)
-{
-	int base = tc35892->irq_base;
-	int irq;
-
-	for (irq = base; irq < base + TC35892_NR_INTERNAL_IRQS; irq++) {
-#ifdef CONFIG_ARM
-		set_irq_flags(irq, 0);
-#endif
-		set_irq_chip_and_handler(irq, NULL, NULL);
-		set_irq_chip_data(irq, NULL);
-	}
-}
-
-static int tc35892_chip_init(struct tc35892 *tc35892)
-{
-	int manf, ver, ret;
-
-	manf = tc35892_reg_read(tc35892, TC35892_MANFCODE);
-	if (manf < 0)
-		return manf;
-
-	ver = tc35892_reg_read(tc35892, TC35892_VERSION);
-	if (ver < 0)
-		return ver;
-
-	if (manf != TC35892_MANFCODE_MAGIC) {
-		dev_err(tc35892->dev, "unknown manufacturer: %#x\n", manf);
-		return -EINVAL;
-	}
-
-	dev_info(tc35892->dev, "manufacturer: %#x, version: %#x\n", manf, ver);
-
-	/* Put everything except the IRQ module into reset */
-	ret = tc35892_reg_write(tc35892, TC35892_RSTCTRL,
-				TC35892_RSTCTRL_TIMRST
-				| TC35892_RSTCTRL_ROTRST
-				| TC35892_RSTCTRL_KBDRST
-				| TC35892_RSTCTRL_GPIRST);
-	if (ret < 0)
-		return ret;
-
-	/* Clear the reset interrupt. */
-	return tc35892_reg_write(tc35892, TC35892_RSTINTCLR, 0x1);
-}
-
-static int __devinit tc35892_probe(struct i2c_client *i2c,
-				   const struct i2c_device_id *id)
-{
-	struct tc35892_platform_data *pdata = i2c->dev.platform_data;
-	struct tc35892 *tc35892;
-	int ret;
-
-	if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA
-				     | I2C_FUNC_SMBUS_I2C_BLOCK))
-		return -EIO;
-
-	tc35892 = kzalloc(sizeof(struct tc35892), GFP_KERNEL);
-	if (!tc35892)
-		return -ENOMEM;
-
-	mutex_init(&tc35892->lock);
-
-	tc35892->dev = &i2c->dev;
-	tc35892->i2c = i2c;
-	tc35892->pdata = pdata;
-	tc35892->irq_base = pdata->irq_base;
-	tc35892->num_gpio = id->driver_data;
-
-	i2c_set_clientdata(i2c, tc35892);
-
-	ret = tc35892_chip_init(tc35892);
-	if (ret)
-		goto out_free;
-
-	ret = tc35892_irq_init(tc35892);
-	if (ret)
-		goto out_free;
-
-	ret = request_threaded_irq(tc35892->i2c->irq, NULL, tc35892_irq,
-				   IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
-				   "tc35892", tc35892);
-	if (ret) {
-		dev_err(tc35892->dev, "failed to request IRQ: %d\n", ret);
-		goto out_removeirq;
-	}
-
-	ret = mfd_add_devices(tc35892->dev, -1, tc35892_devs,
-			      ARRAY_SIZE(tc35892_devs), NULL,
-			      tc35892->irq_base);
-	if (ret) {
-		dev_err(tc35892->dev, "failed to add children\n");
-		goto out_freeirq;
-	}
-
-	return 0;
-
-out_freeirq:
-	free_irq(tc35892->i2c->irq, tc35892);
-out_removeirq:
-	tc35892_irq_remove(tc35892);
-out_free:
-	kfree(tc35892);
-	return ret;
-}
-
-static int __devexit tc35892_remove(struct i2c_client *client)
-{
-	struct tc35892 *tc35892 = i2c_get_clientdata(client);
-
-	mfd_remove_devices(tc35892->dev);
-
-	free_irq(tc35892->i2c->irq, tc35892);
-	tc35892_irq_remove(tc35892);
-
-	kfree(tc35892);
-
-	return 0;
-}
-
-static const struct i2c_device_id tc35892_id[] = {
-	{ "tc35892", 24 },
-	{ }
-};
-MODULE_DEVICE_TABLE(i2c, tc35892_id);
-
-static struct i2c_driver tc35892_driver = {
-	.driver.name	= "tc35892",
-	.driver.owner	= THIS_MODULE,
-	.probe		= tc35892_probe,
-	.remove		= __devexit_p(tc35892_remove),
-	.id_table	= tc35892_id,
-};
-
-static int __init tc35892_init(void)
-{
-	return i2c_add_driver(&tc35892_driver);
-}
-subsys_initcall(tc35892_init);
-
-static void __exit tc35892_exit(void)
-{
-	i2c_del_driver(&tc35892_driver);
-}
-module_exit(tc35892_exit);
-
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("TC35892 MFD core driver");
-MODULE_AUTHOR("Hanumath Prasad, Rabin Vincent");
diff -druNp linux-libre-2.6.37-gnu1/drivers/mfd/tc3589x.c linux-libre-2.6.38-gnu1/drivers/mfd/tc3589x.c
--- linux-libre-2.6.37-gnu1/drivers/mfd/tc3589x.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mfd/tc3589x.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,422 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * License Terms: GNU General Public License, version 2
+ * Author: Hanumath Prasad <hanumath.prasad@stericsson.com> for ST-Ericsson
+ * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson
+ */
+
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/tc3589x.h>
+
+#define TC3589x_CLKMODE_MODCTL_SLEEP		0x0
+#define TC3589x_CLKMODE_MODCTL_OPERATION	(1 << 0)
+
+/**
+ * tc3589x_reg_read() - read a single TC3589x register
+ * @tc3589x:	Device to read from
+ * @reg:	Register to read
+ */
+int tc3589x_reg_read(struct tc3589x *tc3589x, u8 reg)
+{
+	int ret;
+
+	ret = i2c_smbus_read_byte_data(tc3589x->i2c, reg);
+	if (ret < 0)
+		dev_err(tc3589x->dev, "failed to read reg %#x: %d\n",
+			reg, ret);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(tc3589x_reg_read);
+
+/**
+ * tc3589x_reg_read() - write a single TC3589x register
+ * @tc3589x:	Device to write to
+ * @reg:	Register to read
+ * @data:	Value to write
+ */
+int tc3589x_reg_write(struct tc3589x *tc3589x, u8 reg, u8 data)
+{
+	int ret;
+
+	ret = i2c_smbus_write_byte_data(tc3589x->i2c, reg, data);
+	if (ret < 0)
+		dev_err(tc3589x->dev, "failed to write reg %#x: %d\n",
+			reg, ret);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(tc3589x_reg_write);
+
+/**
+ * tc3589x_block_read() - read multiple TC3589x registers
+ * @tc3589x:	Device to read from
+ * @reg:	First register
+ * @length:	Number of registers
+ * @values:	Buffer to write to
+ */
+int tc3589x_block_read(struct tc3589x *tc3589x, u8 reg, u8 length, u8 *values)
+{
+	int ret;
+
+	ret = i2c_smbus_read_i2c_block_data(tc3589x->i2c, reg, length, values);
+	if (ret < 0)
+		dev_err(tc3589x->dev, "failed to read regs %#x: %d\n",
+			reg, ret);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(tc3589x_block_read);
+
+/**
+ * tc3589x_block_write() - write multiple TC3589x registers
+ * @tc3589x:	Device to write to
+ * @reg:	First register
+ * @length:	Number of registers
+ * @values:	Values to write
+ */
+int tc3589x_block_write(struct tc3589x *tc3589x, u8 reg, u8 length,
+			const u8 *values)
+{
+	int ret;
+
+	ret = i2c_smbus_write_i2c_block_data(tc3589x->i2c, reg, length,
+					     values);
+	if (ret < 0)
+		dev_err(tc3589x->dev, "failed to write regs %#x: %d\n",
+			reg, ret);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(tc3589x_block_write);
+
+/**
+ * tc3589x_set_bits() - set the value of a bitfield in a TC3589x register
+ * @tc3589x:	Device to write to
+ * @reg:	Register to write
+ * @mask:	Mask of bits to set
+ * @values:	Value to set
+ */
+int tc3589x_set_bits(struct tc3589x *tc3589x, u8 reg, u8 mask, u8 val)
+{
+	int ret;
+
+	mutex_lock(&tc3589x->lock);
+
+	ret = tc3589x_reg_read(tc3589x, reg);
+	if (ret < 0)
+		goto out;
+
+	ret &= ~mask;
+	ret |= val;
+
+	ret = tc3589x_reg_write(tc3589x, reg, ret);
+
+out:
+	mutex_unlock(&tc3589x->lock);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(tc3589x_set_bits);
+
+static struct resource gpio_resources[] = {
+	{
+		.start	= TC3589x_INT_GPIIRQ,
+		.end	= TC3589x_INT_GPIIRQ,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct resource keypad_resources[] = {
+	{
+		.start  = TC3589x_INT_KBDIRQ,
+		.end    = TC3589x_INT_KBDIRQ,
+		.flags  = IORESOURCE_IRQ,
+	},
+};
+
+static struct mfd_cell tc3589x_dev_gpio[] = {
+	{
+		.name		= "tc3589x-gpio",
+		.num_resources	= ARRAY_SIZE(gpio_resources),
+		.resources	= &gpio_resources[0],
+	},
+};
+
+static struct mfd_cell tc3589x_dev_keypad[] = {
+	{
+		.name           = "tc3589x-keypad",
+		.num_resources  = ARRAY_SIZE(keypad_resources),
+		.resources      = &keypad_resources[0],
+	},
+};
+
+static irqreturn_t tc3589x_irq(int irq, void *data)
+{
+	struct tc3589x *tc3589x = data;
+	int status;
+
+again:
+	status = tc3589x_reg_read(tc3589x, TC3589x_IRQST);
+	if (status < 0)
+		return IRQ_NONE;
+
+	while (status) {
+		int bit = __ffs(status);
+
+		handle_nested_irq(tc3589x->irq_base + bit);
+		status &= ~(1 << bit);
+	}
+
+	/*
+	 * A dummy read or write (to any register) appears to be necessary to
+	 * have the last interrupt clear (for example, GPIO IC write) take
+	 * effect. In such a case, recheck for any interrupt which is still
+	 * pending.
+	 */
+	status = tc3589x_reg_read(tc3589x, TC3589x_IRQST);
+	if (status)
+		goto again;
+
+	return IRQ_HANDLED;
+}
+
+static int tc3589x_irq_init(struct tc3589x *tc3589x)
+{
+	int base = tc3589x->irq_base;
+	int irq;
+
+	for (irq = base; irq < base + TC3589x_NR_INTERNAL_IRQS; irq++) {
+		set_irq_chip_data(irq, tc3589x);
+		set_irq_chip_and_handler(irq, &dummy_irq_chip,
+					 handle_edge_irq);
+		set_irq_nested_thread(irq, 1);
+#ifdef CONFIG_ARM
+		set_irq_flags(irq, IRQF_VALID);
+#else
+		set_irq_noprobe(irq);
+#endif
+	}
+
+	return 0;
+}
+
+static void tc3589x_irq_remove(struct tc3589x *tc3589x)
+{
+	int base = tc3589x->irq_base;
+	int irq;
+
+	for (irq = base; irq < base + TC3589x_NR_INTERNAL_IRQS; irq++) {
+#ifdef CONFIG_ARM
+		set_irq_flags(irq, 0);
+#endif
+		set_irq_chip_and_handler(irq, NULL, NULL);
+		set_irq_chip_data(irq, NULL);
+	}
+}
+
+static int tc3589x_chip_init(struct tc3589x *tc3589x)
+{
+	int manf, ver, ret;
+
+	manf = tc3589x_reg_read(tc3589x, TC3589x_MANFCODE);
+	if (manf < 0)
+		return manf;
+
+	ver = tc3589x_reg_read(tc3589x, TC3589x_VERSION);
+	if (ver < 0)
+		return ver;
+
+	if (manf != TC3589x_MANFCODE_MAGIC) {
+		dev_err(tc3589x->dev, "unknown manufacturer: %#x\n", manf);
+		return -EINVAL;
+	}
+
+	dev_info(tc3589x->dev, "manufacturer: %#x, version: %#x\n", manf, ver);
+
+	/*
+	 * Put everything except the IRQ module into reset;
+	 * also spare the GPIO module for any pin initialization
+	 * done during pre-kernel boot
+	 */
+	ret = tc3589x_reg_write(tc3589x, TC3589x_RSTCTRL,
+				TC3589x_RSTCTRL_TIMRST
+				| TC3589x_RSTCTRL_ROTRST
+				| TC3589x_RSTCTRL_KBDRST);
+	if (ret < 0)
+		return ret;
+
+	/* Clear the reset interrupt. */
+	return tc3589x_reg_write(tc3589x, TC3589x_RSTINTCLR, 0x1);
+}
+
+static int __devinit tc3589x_device_init(struct tc3589x *tc3589x)
+{
+	int ret = 0;
+	unsigned int blocks = tc3589x->pdata->block;
+
+	if (blocks & TC3589x_BLOCK_GPIO) {
+		ret = mfd_add_devices(tc3589x->dev, -1, tc3589x_dev_gpio,
+				ARRAY_SIZE(tc3589x_dev_gpio), NULL,
+				tc3589x->irq_base);
+		if (ret) {
+			dev_err(tc3589x->dev, "failed to add gpio child\n");
+			return ret;
+		}
+		dev_info(tc3589x->dev, "added gpio block\n");
+	}
+
+	if (blocks & TC3589x_BLOCK_KEYPAD) {
+		ret = mfd_add_devices(tc3589x->dev, -1, tc3589x_dev_keypad,
+				ARRAY_SIZE(tc3589x_dev_keypad), NULL,
+				tc3589x->irq_base);
+		if (ret) {
+			dev_err(tc3589x->dev, "failed to keypad child\n");
+			return ret;
+		}
+		dev_info(tc3589x->dev, "added keypad block\n");
+	}
+
+	return ret;
+}
+
+static int __devinit tc3589x_probe(struct i2c_client *i2c,
+				   const struct i2c_device_id *id)
+{
+	struct tc3589x_platform_data *pdata = i2c->dev.platform_data;
+	struct tc3589x *tc3589x;
+	int ret;
+
+	if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA
+				     | I2C_FUNC_SMBUS_I2C_BLOCK))
+		return -EIO;
+
+	tc3589x = kzalloc(sizeof(struct tc3589x), GFP_KERNEL);
+	if (!tc3589x)
+		return -ENOMEM;
+
+	mutex_init(&tc3589x->lock);
+
+	tc3589x->dev = &i2c->dev;
+	tc3589x->i2c = i2c;
+	tc3589x->pdata = pdata;
+	tc3589x->irq_base = pdata->irq_base;
+	tc3589x->num_gpio = id->driver_data;
+
+	i2c_set_clientdata(i2c, tc3589x);
+
+	ret = tc3589x_chip_init(tc3589x);
+	if (ret)
+		goto out_free;
+
+	ret = tc3589x_irq_init(tc3589x);
+	if (ret)
+		goto out_free;
+
+	ret = request_threaded_irq(tc3589x->i2c->irq, NULL, tc3589x_irq,
+				   IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+				   "tc3589x", tc3589x);
+	if (ret) {
+		dev_err(tc3589x->dev, "failed to request IRQ: %d\n", ret);
+		goto out_removeirq;
+	}
+
+	ret = tc3589x_device_init(tc3589x);
+	if (ret) {
+		dev_err(tc3589x->dev, "failed to add child devices\n");
+		goto out_freeirq;
+	}
+
+	return 0;
+
+out_freeirq:
+	free_irq(tc3589x->i2c->irq, tc3589x);
+out_removeirq:
+	tc3589x_irq_remove(tc3589x);
+out_free:
+	kfree(tc3589x);
+	return ret;
+}
+
+static int __devexit tc3589x_remove(struct i2c_client *client)
+{
+	struct tc3589x *tc3589x = i2c_get_clientdata(client);
+
+	mfd_remove_devices(tc3589x->dev);
+
+	free_irq(tc3589x->i2c->irq, tc3589x);
+	tc3589x_irq_remove(tc3589x);
+
+	kfree(tc3589x);
+
+	return 0;
+}
+
+static int tc3589x_suspend(struct device *dev)
+{
+	struct tc3589x *tc3589x = dev_get_drvdata(dev);
+	struct i2c_client *client = tc3589x->i2c;
+	int ret = 0;
+
+	/* put the system to sleep mode */
+	if (!device_may_wakeup(&client->dev))
+		ret = tc3589x_reg_write(tc3589x, TC3589x_CLKMODE,
+				TC3589x_CLKMODE_MODCTL_SLEEP);
+
+	return ret;
+}
+
+static int tc3589x_resume(struct device *dev)
+{
+	struct tc3589x *tc3589x = dev_get_drvdata(dev);
+	struct i2c_client *client = tc3589x->i2c;
+	int ret = 0;
+
+	/* enable the system into operation */
+	if (!device_may_wakeup(&client->dev))
+		ret = tc3589x_reg_write(tc3589x, TC3589x_CLKMODE,
+				TC3589x_CLKMODE_MODCTL_OPERATION);
+
+	return ret;
+}
+
+static const SIMPLE_DEV_PM_OPS(tc3589x_dev_pm_ops, tc3589x_suspend,
+						tc3589x_resume);
+
+static const struct i2c_device_id tc3589x_id[] = {
+	{ "tc3589x", 24 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, tc3589x_id);
+
+static struct i2c_driver tc3589x_driver = {
+	.driver.name	= "tc3589x",
+	.driver.owner	= THIS_MODULE,
+#ifdef CONFIG_PM
+	.driver.pm	= &tc3589x_dev_pm_ops,
+#endif
+	.probe		= tc3589x_probe,
+	.remove		= __devexit_p(tc3589x_remove),
+	.id_table	= tc3589x_id,
+};
+
+static int __init tc3589x_init(void)
+{
+	return i2c_add_driver(&tc3589x_driver);
+}
+subsys_initcall(tc3589x_init);
+
+static void __exit tc3589x_exit(void)
+{
+	i2c_del_driver(&tc3589x_driver);
+}
+module_exit(tc3589x_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("TC3589x MFD core driver");
+MODULE_AUTHOR("Hanumath Prasad, Rabin Vincent");
diff -druNp linux-libre-2.6.37-gnu1/drivers/mfd/tc6393xb.c linux-libre-2.6.38-gnu1/drivers/mfd/tc6393xb.c
--- linux-libre-2.6.37-gnu1/drivers/mfd/tc6393xb.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mfd/tc6393xb.c	2011-03-14 21:20:32.000000000 -0400
@@ -527,41 +527,41 @@ tc6393xb_irq(unsigned int irq, struct ir
 		}
 }
 
-static void tc6393xb_irq_ack(unsigned int irq)
+static void tc6393xb_irq_ack(struct irq_data *data)
 {
 }
 
-static void tc6393xb_irq_mask(unsigned int irq)
+static void tc6393xb_irq_mask(struct irq_data *data)
 {
-	struct tc6393xb *tc6393xb = get_irq_chip_data(irq);
+	struct tc6393xb *tc6393xb = irq_data_get_irq_chip_data(data);
 	unsigned long flags;
 	u8 imr;
 
 	spin_lock_irqsave(&tc6393xb->lock, flags);
 	imr = tmio_ioread8(tc6393xb->scr + SCR_IMR);
-	imr |= 1 << (irq - tc6393xb->irq_base);
+	imr |= 1 << (data->irq - tc6393xb->irq_base);
 	tmio_iowrite8(imr, tc6393xb->scr + SCR_IMR);
 	spin_unlock_irqrestore(&tc6393xb->lock, flags);
 }
 
-static void tc6393xb_irq_unmask(unsigned int irq)
+static void tc6393xb_irq_unmask(struct irq_data *data)
 {
-	struct tc6393xb *tc6393xb = get_irq_chip_data(irq);
+	struct tc6393xb *tc6393xb = irq_data_get_irq_chip_data(data);
 	unsigned long flags;
 	u8 imr;
 
 	spin_lock_irqsave(&tc6393xb->lock, flags);
 	imr = tmio_ioread8(tc6393xb->scr + SCR_IMR);
-	imr &= ~(1 << (irq - tc6393xb->irq_base));
+	imr &= ~(1 << (data->irq - tc6393xb->irq_base));
 	tmio_iowrite8(imr, tc6393xb->scr + SCR_IMR);
 	spin_unlock_irqrestore(&tc6393xb->lock, flags);
 }
 
 static struct irq_chip tc6393xb_chip = {
-	.name	= "tc6393xb",
-	.ack	= tc6393xb_irq_ack,
-	.mask	= tc6393xb_irq_mask,
-	.unmask	= tc6393xb_irq_unmask,
+	.name		= "tc6393xb",
+	.irq_ack	= tc6393xb_irq_ack,
+	.irq_mask	= tc6393xb_irq_mask,
+	.irq_unmask	= tc6393xb_irq_unmask,
 };
 
 static void tc6393xb_attach_irq(struct platform_device *dev)
diff -druNp linux-libre-2.6.37-gnu1/drivers/mfd/timberdale.c linux-libre-2.6.38-gnu1/drivers/mfd/timberdale.c
--- linux-libre-2.6.37-gnu1/drivers/mfd/timberdale.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mfd/timberdale.c	2011-03-14 21:20:32.000000000 -0400
@@ -40,6 +40,7 @@
 #include <linux/spi/mc33880.h>
 
 #include <media/timb_radio.h>
+#include <media/timb_video.h>
 
 #include <linux/timb_dma.h>
 
@@ -246,7 +247,23 @@ static const __devinitconst struct resou
 	},
 };
 
-static const __devinitconst struct resource timberdale_radio_resources[] = {
+static __devinitdata struct i2c_board_info timberdale_adv7180_i2c_board_info = {
+	/* Requires jumper JP9 to be off */
+	I2C_BOARD_INFO("adv7180", 0x42 >> 1),
+	.irq = IRQ_TIMBERDALE_ADV7180
+};
+
+static __devinitdata struct timb_video_platform_data
+	timberdale_video_platform_data = {
+	.dma_channel = DMA_VIDEO_RX,
+	.i2c_adapter = 0,
+	.encoder = {
+		.info = &timberdale_adv7180_i2c_board_info
+	}
+};
+
+static const __devinitconst struct resource
+timberdale_radio_resources[] = {
 	{
 		.start	= RDSOFFSET,
 		.end	= RDSEND,
@@ -271,15 +288,25 @@ static __devinitdata struct timb_radio_p
 	timberdale_radio_platform_data = {
 	.i2c_adapter = 0,
 	.tuner = {
-		.module_name = "tef6862",
 		.info = &timberdale_tef6868_i2c_board_info
 	},
 	.dsp = {
-		.module_name = "saa7706h",
 		.info = &timberdale_saa7706_i2c_board_info
 	}
 };
 
+static const __devinitconst struct resource timberdale_video_resources[] = {
+	{
+		.start	= LOGIWOFFSET,
+		.end	= LOGIWEND,
+		.flags	= IORESOURCE_MEM,
+	},
+	/*
+	note that the "frame buffer" is located in DMA area
+	starting at 0x1200000
+	*/
+};
+
 static __devinitdata struct timb_dma_platform_data timb_dma_platform_data = {
 	.nr_channels = 10,
 	.channels = {
@@ -380,6 +407,13 @@ static __devinitdata struct mfd_cell tim
 		.data_size = sizeof(timberdale_gpio_platform_data),
 	},
 	{
+		.name = "timb-video",
+		.num_resources = ARRAY_SIZE(timberdale_video_resources),
+		.resources = timberdale_video_resources,
+		.platform_data = &timberdale_video_platform_data,
+		.data_size = sizeof(timberdale_video_platform_data),
+	},
+	{
 		.name = "timb-radio",
 		.num_resources = ARRAY_SIZE(timberdale_radio_resources),
 		.resources = timberdale_radio_resources,
@@ -440,6 +474,13 @@ static __devinitdata struct mfd_cell tim
 		.resources = timberdale_mlogicore_resources,
 	},
 	{
+		.name = "timb-video",
+		.num_resources = ARRAY_SIZE(timberdale_video_resources),
+		.resources = timberdale_video_resources,
+		.platform_data = &timberdale_video_platform_data,
+		.data_size = sizeof(timberdale_video_platform_data),
+	},
+	{
 		.name = "timb-radio",
 		.num_resources = ARRAY_SIZE(timberdale_radio_resources),
 		.resources = timberdale_radio_resources,
@@ -490,6 +531,13 @@ static __devinitdata struct mfd_cell tim
 		.data_size = sizeof(timberdale_gpio_platform_data),
 	},
 	{
+		.name = "timb-video",
+		.num_resources = ARRAY_SIZE(timberdale_video_resources),
+		.resources = timberdale_video_resources,
+		.platform_data = &timberdale_video_platform_data,
+		.data_size = sizeof(timberdale_video_platform_data),
+	},
+	{
 		.name = "timb-radio",
 		.num_resources = ARRAY_SIZE(timberdale_radio_resources),
 		.resources = timberdale_radio_resources,
@@ -533,6 +581,13 @@ static __devinitdata struct mfd_cell tim
 		.data_size = sizeof(timberdale_gpio_platform_data),
 	},
 	{
+		.name = "timb-video",
+		.num_resources = ARRAY_SIZE(timberdale_video_resources),
+		.resources = timberdale_video_resources,
+		.platform_data = &timberdale_video_platform_data,
+		.data_size = sizeof(timberdale_video_platform_data),
+	},
+	{
 		.name = "timb-radio",
 		.num_resources = ARRAY_SIZE(timberdale_radio_resources),
 		.resources = timberdale_radio_resources,
diff -druNp linux-libre-2.6.37-gnu1/drivers/mfd/timberdale.h linux-libre-2.6.38-gnu1/drivers/mfd/timberdale.h
--- linux-libre-2.6.37-gnu1/drivers/mfd/timberdale.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mfd/timberdale.h	2011-03-14 21:20:32.000000000 -0400
@@ -23,7 +23,7 @@
 #ifndef MFD_TIMBERDALE_H
 #define MFD_TIMBERDALE_H
 
-#define DRV_VERSION		"0.2"
+#define DRV_VERSION		"0.3"
 
 /* This driver only support versions >= 3.8 and < 4.0  */
 #define TIMB_SUPPORTED_MAJOR	3
diff -druNp linux-libre-2.6.37-gnu1/drivers/mfd/tps65010.c linux-libre-2.6.38-gnu1/drivers/mfd/tps65010.c
--- linux-libre-2.6.37-gnu1/drivers/mfd/tps65010.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mfd/tps65010.c	2011-03-14 21:20:32.000000000 -0400
@@ -34,7 +34,7 @@
 
 #include <linux/i2c/tps65010.h>
 
-#include <asm/gpio.h>
+#include <linux/gpio.h>
 
 
 /*-------------------------------------------------------------------------*/
@@ -242,7 +242,7 @@ static int dbg_show(struct seq_file *s,
 	seq_printf(s, "mask2     %s\n", buf);
 	/* ignore ackint2 */
 
-	(void) schedule_delayed_work(&tps->work, POWER_POLL_DELAY);
+	schedule_delayed_work(&tps->work, POWER_POLL_DELAY);
 
 
 	/* VMAIN voltage, enable lowpower, etc */
@@ -400,7 +400,7 @@ static void tps65010_interrupt(struct tp
 			&& (tps->chgstatus & (TPS_CHG_USB|TPS_CHG_AC)))
 		poll = 1;
 	if (poll)
-		(void) schedule_delayed_work(&tps->work, POWER_POLL_DELAY);
+		schedule_delayed_work(&tps->work, POWER_POLL_DELAY);
 
 	/* also potentially gpio-in rise or fall */
 }
@@ -410,7 +410,7 @@ static void tps65010_work(struct work_st
 {
 	struct tps65010		*tps;
 
-	tps = container_of(work, struct tps65010, work.work);
+	tps = container_of(to_delayed_work(work), struct tps65010, work);
 	mutex_lock(&tps->lock);
 
 	tps65010_interrupt(tps);
@@ -448,7 +448,7 @@ static irqreturn_t tps65010_irq(int irq,
 
 	disable_irq_nosync(irq);
 	set_bit(FLAG_IRQ_ENABLE, &tps->flags);
-	(void) schedule_work(&tps->work.work);
+	schedule_delayed_work(&tps->work, 0);
 	return IRQ_HANDLED;
 }
 
@@ -527,8 +527,7 @@ static int __exit tps65010_remove(struct
 	}
 	if (client->irq > 0)
 		free_irq(client->irq, tps);
-	cancel_delayed_work(&tps->work);
-	flush_scheduled_work();
+	cancel_delayed_work_sync(&tps->work);
 	debugfs_remove(tps->file);
 	kfree(tps);
 	the_tps = NULL;
@@ -720,7 +719,7 @@ int tps65010_set_vbus_draw(unsigned mA)
 			&& test_and_set_bit(
 				FLAG_VBUS_CHANGED, &the_tps->flags)) {
 		/* gadget drivers call this in_irq() */
-		(void) schedule_work(&the_tps->work.work);
+		schedule_delayed_work(&the_tps->work, 0);
 	}
 	local_irq_restore(flags);
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/mfd/tps6586x.c linux-libre-2.6.38-gnu1/drivers/mfd/tps6586x.c
--- linux-libre-2.6.37-gnu1/drivers/mfd/tps6586x.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mfd/tps6586x.c	2011-03-14 21:20:32.000000000 -0400
@@ -46,8 +46,6 @@
 
 /* device id */
 #define TPS6586X_VERSIONCRC	0xcd
-#define TPS658621A_VERSIONCRC	0x15
-#define TPS658621C_VERSIONCRC	0x2c
 
 struct tps6586x_irq_data {
 	u8	mask_reg;
@@ -152,12 +150,12 @@ static inline int __tps6586x_write(struc
 static inline int __tps6586x_writes(struct i2c_client *client, int reg,
 				  int len, uint8_t *val)
 {
-	int ret;
+	int ret, i;
 
-	ret = i2c_smbus_write_i2c_block_data(client, reg, len, val);
-	if (ret < 0) {
-		dev_err(&client->dev, "failed writings to 0x%02x\n", reg);
-		return ret;
+	for (i = 0; i < len; i++) {
+		ret = __tps6586x_write(client, reg + i, *(val + i));
+		if (ret < 0)
+			return ret;
 	}
 
 	return 0;
@@ -325,37 +323,37 @@ static int tps6586x_remove_subdevs(struc
 	return device_for_each_child(tps6586x->dev, NULL, __remove_subdev);
 }
 
-static void tps6586x_irq_lock(unsigned int irq)
+static void tps6586x_irq_lock(struct irq_data *data)
 {
-	struct tps6586x *tps6586x = get_irq_chip_data(irq);
+	struct tps6586x *tps6586x = irq_data_get_irq_chip_data(data);
 
 	mutex_lock(&tps6586x->irq_lock);
 }
 
-static void tps6586x_irq_enable(unsigned int irq)
+static void tps6586x_irq_enable(struct irq_data *irq_data)
 {
-	struct tps6586x *tps6586x = get_irq_chip_data(irq);
-	unsigned int __irq = irq - tps6586x->irq_base;
+	struct tps6586x *tps6586x = irq_data_get_irq_chip_data(irq_data);
+	unsigned int __irq = irq_data->irq - tps6586x->irq_base;
 	const struct tps6586x_irq_data *data = &tps6586x_irqs[__irq];
 
 	tps6586x->mask_reg[data->mask_reg] &= ~data->mask_mask;
 	tps6586x->irq_en |= (1 << __irq);
 }
 
-static void tps6586x_irq_disable(unsigned int irq)
+static void tps6586x_irq_disable(struct irq_data *irq_data)
 {
-	struct tps6586x *tps6586x = get_irq_chip_data(irq);
+	struct tps6586x *tps6586x = irq_data_get_irq_chip_data(irq_data);
 
-	unsigned int __irq = irq - tps6586x->irq_base;
+	unsigned int __irq = irq_data->irq - tps6586x->irq_base;
 	const struct tps6586x_irq_data *data = &tps6586x_irqs[__irq];
 
 	tps6586x->mask_reg[data->mask_reg] |= data->mask_mask;
 	tps6586x->irq_en &= ~(1 << __irq);
 }
 
-static void tps6586x_irq_sync_unlock(unsigned int irq)
+static void tps6586x_irq_sync_unlock(struct irq_data *data)
 {
-	struct tps6586x *tps6586x = get_irq_chip_data(irq);
+	struct tps6586x *tps6586x = irq_data_get_irq_chip_data(data);
 	int i;
 
 	for (i = 0; i < ARRAY_SIZE(tps6586x->mask_reg); i++) {
@@ -421,10 +419,10 @@ static int __devinit tps6586x_irq_init(s
 	tps6586x->irq_base = irq_base;
 
 	tps6586x->irq_chip.name = "tps6586x";
-	tps6586x->irq_chip.enable = tps6586x_irq_enable;
-	tps6586x->irq_chip.disable = tps6586x_irq_disable;
-	tps6586x->irq_chip.bus_lock = tps6586x_irq_lock;
-	tps6586x->irq_chip.bus_sync_unlock = tps6586x_irq_sync_unlock;
+	tps6586x->irq_chip.irq_enable = tps6586x_irq_enable;
+	tps6586x->irq_chip.irq_disable = tps6586x_irq_disable;
+	tps6586x->irq_chip.irq_bus_lock = tps6586x_irq_lock;
+	tps6586x->irq_chip.irq_bus_sync_unlock = tps6586x_irq_sync_unlock;
 
 	for (i = 0; i < ARRAY_SIZE(tps6586x_irqs); i++) {
 		int __irq = i + tps6586x->irq_base;
@@ -498,11 +496,7 @@ static int __devinit tps6586x_i2c_probe(
 		return -EIO;
 	}
 
-	if ((ret != TPS658621A_VERSIONCRC) &&
-	    (ret != TPS658621C_VERSIONCRC)) {
-		dev_err(&client->dev, "Unsupported chip ID: %x\n", ret);
-		return -ENODEV;
-	}
+	dev_info(&client->dev, "VERSIONCRC is %02x\n", ret);
 
 	tps6586x = kzalloc(sizeof(struct tps6586x), GFP_KERNEL);
 	if (tps6586x == NULL)
diff -druNp linux-libre-2.6.37-gnu1/drivers/mfd/twl4030-irq.c linux-libre-2.6.38-gnu1/drivers/mfd/twl4030-irq.c
--- linux-libre-2.6.37-gnu1/drivers/mfd/twl4030-irq.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mfd/twl4030-irq.c	2011-03-14 21:20:32.000000000 -0400
@@ -599,38 +599,38 @@ static void twl4030_sih_do_edge(struct w
  * completion, potentially including some re-ordering, of these requests.
  */
 
-static void twl4030_sih_mask(unsigned irq)
+static void twl4030_sih_mask(struct irq_data *data)
 {
-	struct sih_agent *sih = get_irq_chip_data(irq);
+	struct sih_agent *sih = irq_data_get_irq_chip_data(data);
 	unsigned long flags;
 
 	spin_lock_irqsave(&sih_agent_lock, flags);
-	sih->imr |= BIT(irq - sih->irq_base);
+	sih->imr |= BIT(data->irq - sih->irq_base);
 	sih->imr_change_pending = true;
 	queue_work(wq, &sih->mask_work);
 	spin_unlock_irqrestore(&sih_agent_lock, flags);
 }
 
-static void twl4030_sih_unmask(unsigned irq)
+static void twl4030_sih_unmask(struct irq_data *data)
 {
-	struct sih_agent *sih = get_irq_chip_data(irq);
+	struct sih_agent *sih = irq_data_get_irq_chip_data(data);
 	unsigned long flags;
 
 	spin_lock_irqsave(&sih_agent_lock, flags);
-	sih->imr &= ~BIT(irq - sih->irq_base);
+	sih->imr &= ~BIT(data->irq - sih->irq_base);
 	sih->imr_change_pending = true;
 	queue_work(wq, &sih->mask_work);
 	spin_unlock_irqrestore(&sih_agent_lock, flags);
 }
 
-static int twl4030_sih_set_type(unsigned irq, unsigned trigger)
+static int twl4030_sih_set_type(struct irq_data *data, unsigned trigger)
 {
-	struct sih_agent *sih = get_irq_chip_data(irq);
-	struct irq_desc *desc = irq_to_desc(irq);
+	struct sih_agent *sih = irq_data_get_irq_chip_data(data);
+	struct irq_desc *desc = irq_to_desc(data->irq);
 	unsigned long flags;
 
 	if (!desc) {
-		pr_err("twl4030: Invalid IRQ: %d\n", irq);
+		pr_err("twl4030: Invalid IRQ: %d\n", data->irq);
 		return -EINVAL;
 	}
 
@@ -641,7 +641,7 @@ static int twl4030_sih_set_type(unsigned
 	if ((desc->status & IRQ_TYPE_SENSE_MASK) != trigger) {
 		desc->status &= ~IRQ_TYPE_SENSE_MASK;
 		desc->status |= trigger;
-		sih->edge_change |= BIT(irq - sih->irq_base);
+		sih->edge_change |= BIT(data->irq - sih->irq_base);
 		queue_work(wq, &sih->edge_work);
 	}
 	spin_unlock_irqrestore(&sih_agent_lock, flags);
@@ -650,9 +650,9 @@ static int twl4030_sih_set_type(unsigned
 
 static struct irq_chip twl4030_sih_irq_chip = {
 	.name		= "twl4030",
-	.mask		= twl4030_sih_mask,
-	.unmask		= twl4030_sih_unmask,
-	.set_type	= twl4030_sih_set_type,
+	.irq_mask      	= twl4030_sih_mask,
+	.irq_unmask	= twl4030_sih_unmask,
+	.irq_set_type	= twl4030_sih_set_type,
 };
 
 /*----------------------------------------------------------------------*/
diff -druNp linux-libre-2.6.37-gnu1/drivers/mfd/twl6030-irq.c linux-libre-2.6.38-gnu1/drivers/mfd/twl6030-irq.c
--- linux-libre-2.6.37-gnu1/drivers/mfd/twl6030-irq.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mfd/twl6030-irq.c	2011-03-14 21:20:32.000000000 -0400
@@ -74,7 +74,7 @@ static int twl6030_interrupt_mapping[24]
 	USBOTG_INTR_OFFSET,	/* Bit 16	ID_WKUP			*/
 	USBOTG_INTR_OFFSET,	/* Bit 17	VBUS_WKUP		*/
 	USBOTG_INTR_OFFSET,	/* Bit 18	ID			*/
-	USBOTG_INTR_OFFSET,	/* Bit 19	VBUS			*/
+	USB_PRES_INTR_OFFSET,	/* Bit 19	VBUS			*/
 	CHARGER_INTR_OFFSET,	/* Bit 20	CHRG_CTRL		*/
 	CHARGER_INTR_OFFSET,	/* Bit 21	EXT_CHRG		*/
 	CHARGER_INTR_OFFSET,	/* Bit 22	INT_CHRG		*/
@@ -128,6 +128,13 @@ static int twl6030_irq_thread(void *data
 
 		sts.bytes[3] = 0; /* Only 24 bits are valid*/
 
+		/*
+		 * Since VBUS status bit is not reliable for VBUS disconnect
+		 * use CHARGER VBUS detection status bit instead.
+		 */
+		if (sts.bytes[2] & 0x10)
+			sts.bytes[2] |= 0x08;
+
 		for (i = 0; sts.int_sts; sts.int_sts >>= 1, i++) {
 			local_irq_disable();
 			if (sts.int_sts & 0x1) {
@@ -325,7 +332,7 @@ int twl6030_init_irq(int irq_num, unsign
 	 */
 	twl6030_irq_chip = dummy_irq_chip;
 	twl6030_irq_chip.name = "twl6030";
-	twl6030_irq_chip.set_type = NULL;
+	twl6030_irq_chip.irq_set_type = NULL;
 
 	for (i = irq_base; i < irq_end; i++) {
 		set_irq_chip_and_handler(i, &twl6030_irq_chip,
diff -druNp linux-libre-2.6.37-gnu1/drivers/mfd/twl-core.c linux-libre-2.6.38-gnu1/drivers/mfd/twl-core.c
--- linux-libre-2.6.37-gnu1/drivers/mfd/twl-core.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mfd/twl-core.c	2011-03-14 21:20:32.000000000 -0400
@@ -95,7 +95,8 @@
 #define twl_has_rtc()	false
 #endif
 
-#if defined(CONFIG_TWL4030_USB) || defined(CONFIG_TWL4030_USB_MODULE)
+#if defined(CONFIG_TWL4030_USB) || defined(CONFIG_TWL4030_USB_MODULE) ||\
+	defined(CONFIG_TWL6030_USB) || defined(CONFIG_TWL6030_USB_MODULE)
 #define twl_has_usb()	true
 #else
 #define twl_has_usb()	false
@@ -682,6 +683,43 @@ add_children(struct twl4030_platform_dat
 			usb3v1.dev = child;
 		}
 	}
+	if (twl_has_usb() && pdata->usb && twl_class_is_6030()) {
+
+		static struct regulator_consumer_supply usb3v3 = {
+			.supply =	"vusb",
+		};
+
+		if (twl_has_regulator()) {
+			/* this is a template that gets copied */
+			struct regulator_init_data usb_fixed = {
+				.constraints.valid_modes_mask =
+					REGULATOR_MODE_NORMAL
+					| REGULATOR_MODE_STANDBY,
+				.constraints.valid_ops_mask =
+					REGULATOR_CHANGE_MODE
+					| REGULATOR_CHANGE_STATUS,
+			};
+
+			child = add_regulator_linked(TWL6030_REG_VUSB,
+						      &usb_fixed, &usb3v3, 1);
+			if (IS_ERR(child))
+				return PTR_ERR(child);
+		}
+
+		child = add_child(0, "twl6030_usb",
+			pdata->usb, sizeof(*pdata->usb),
+			true,
+			/* irq1 = VBUS_PRES, irq0 = USB ID */
+			pdata->irq_base + USBOTG_INTR_OFFSET,
+			pdata->irq_base + USB_PRES_INTR_OFFSET);
+
+		if (IS_ERR(child))
+			return PTR_ERR(child);
+		/* we need to connect regulators to this transceiver */
+		if (twl_has_regulator() && child)
+			usb3v3.dev = child;
+
+	}
 
 	if (twl_has_watchdog()) {
 		child = add_child(0, "twl4030_wdt", NULL, 0, false, 0, 0);
@@ -815,10 +853,6 @@ add_children(struct twl4030_platform_dat
 		if (IS_ERR(child))
 			return PTR_ERR(child);
 
-		child = add_regulator(TWL6030_REG_VUSB, pdata->vusb);
-		if (IS_ERR(child))
-			return PTR_ERR(child);
-
 		child = add_regulator(TWL6030_REG_VAUX1_6030, pdata->vaux1);
 		if (IS_ERR(child))
 			return PTR_ERR(child);
@@ -969,7 +1003,7 @@ static int twl_remove(struct i2c_client
 }
 
 /* NOTE:  this driver only handles a single twl4030/tps659x0 chip */
-static int __init
+static int __devinit
 twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
 {
 	int				status;
diff -druNp linux-libre-2.6.37-gnu1/drivers/mfd/ucb1x00-ts.c linux-libre-2.6.38-gnu1/drivers/mfd/ucb1x00-ts.c
--- linux-libre-2.6.37-gnu1/drivers/mfd/ucb1x00-ts.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mfd/ucb1x00-ts.c	2011-03-14 21:20:32.000000000 -0400
@@ -385,12 +385,18 @@ static int ucb1x00_ts_add(struct ucb1x00
 	idev->close      = ucb1x00_ts_close;
 
 	__set_bit(EV_ABS, idev->evbit);
-	__set_bit(ABS_X, idev->absbit);
-	__set_bit(ABS_Y, idev->absbit);
-	__set_bit(ABS_PRESSURE, idev->absbit);
 
 	input_set_drvdata(idev, ts);
 
+	ucb1x00_adc_enable(ts->ucb);
+	ts->x_res = ucb1x00_ts_read_xres(ts);
+	ts->y_res = ucb1x00_ts_read_yres(ts);
+	ucb1x00_adc_disable(ts->ucb);
+
+	input_set_abs_params(idev, ABS_X, 0, ts->x_res, 0, 0);
+	input_set_abs_params(idev, ABS_Y, 0, ts->y_res, 0, 0);
+	input_set_abs_params(idev, ABS_PRESSURE, 0, 0, 0, 0);
+
 	err = input_register_device(idev);
 	if (err)
 		goto fail;
diff -druNp linux-libre-2.6.37-gnu1/drivers/mfd/vx855.c linux-libre-2.6.38-gnu1/drivers/mfd/vx855.c
--- linux-libre-2.6.37-gnu1/drivers/mfd/vx855.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mfd/vx855.c	2011-03-14 21:20:32.000000000 -0400
@@ -112,7 +112,7 @@ out:
 	return ret;
 }
 
-static void vx855_remove(struct pci_dev *pdev)
+static void __devexit vx855_remove(struct pci_dev *pdev)
 {
 	mfd_remove_devices(&pdev->dev);
 	pci_disable_device(pdev);
diff -druNp linux-libre-2.6.37-gnu1/drivers/mfd/wl1273-core.c linux-libre-2.6.38-gnu1/drivers/mfd/wl1273-core.c
--- linux-libre-2.6.37-gnu1/drivers/mfd/wl1273-core.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mfd/wl1273-core.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,148 @@
+/*
+ * MFD driver for wl1273 FM radio and audio codec submodules.
+ *
+ * Copyright (C) 2010 Nokia Corporation
+ * Author: Matti Aaltonen <matti.j.aaltonen@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.
+ *
+ * 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/mfd/wl1273-core.h>
+#include <linux/slab.h>
+
+#define DRIVER_DESC "WL1273 FM Radio Core"
+
+static struct i2c_device_id wl1273_driver_id_table[] = {
+	{ WL1273_FM_DRIVER_NAME, 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, wl1273_driver_id_table);
+
+static int wl1273_core_remove(struct i2c_client *client)
+{
+	struct wl1273_core *core = i2c_get_clientdata(client);
+
+	dev_dbg(&client->dev, "%s\n", __func__);
+
+	mfd_remove_devices(&client->dev);
+	i2c_set_clientdata(client, NULL);
+	kfree(core);
+
+	return 0;
+}
+
+static int __devinit wl1273_core_probe(struct i2c_client *client,
+				       const struct i2c_device_id *id)
+{
+	struct wl1273_fm_platform_data *pdata = client->dev.platform_data;
+	struct wl1273_core *core;
+	struct mfd_cell *cell;
+	int children = 0;
+	int r = 0;
+
+	dev_dbg(&client->dev, "%s\n", __func__);
+
+	if (!pdata) {
+		dev_err(&client->dev, "No platform data.\n");
+		return -EINVAL;
+	}
+
+	if (!(pdata->children & WL1273_RADIO_CHILD)) {
+		dev_err(&client->dev, "Cannot function without radio child.\n");
+		return -EINVAL;
+	}
+
+	core = kzalloc(sizeof(*core), GFP_KERNEL);
+	if (!core)
+		return -ENOMEM;
+
+	core->pdata = pdata;
+	core->client = client;
+	mutex_init(&core->lock);
+
+	i2c_set_clientdata(client, core);
+
+	dev_dbg(&client->dev, "%s: Have V4L2.\n", __func__);
+
+	cell = &core->cells[children];
+	cell->name = "wl1273_fm_radio";
+	cell->platform_data = &core;
+	cell->data_size = sizeof(core);
+	children++;
+
+	if (pdata->children & WL1273_CODEC_CHILD) {
+		cell = &core->cells[children];
+
+		dev_dbg(&client->dev, "%s: Have codec.\n", __func__);
+		cell->name = "wl1273-codec";
+		cell->platform_data = &core;
+		cell->data_size = sizeof(core);
+		children++;
+	}
+
+	dev_dbg(&client->dev, "%s: number of children: %d.\n",
+		__func__, children);
+
+	r = mfd_add_devices(&client->dev, -1, core->cells,
+			    children, NULL, 0);
+	if (r)
+		goto err;
+
+	return 0;
+
+err:
+	i2c_set_clientdata(client, NULL);
+	pdata->free_resources();
+	kfree(core);
+
+	dev_dbg(&client->dev, "%s\n", __func__);
+
+	return r;
+}
+
+static struct i2c_driver wl1273_core_driver = {
+	.driver = {
+		.name = WL1273_FM_DRIVER_NAME,
+	},
+	.probe = wl1273_core_probe,
+	.id_table = wl1273_driver_id_table,
+	.remove = __devexit_p(wl1273_core_remove),
+};
+
+static int __init wl1273_core_init(void)
+{
+	int r;
+
+	r = i2c_add_driver(&wl1273_core_driver);
+	if (r) {
+		pr_err(WL1273_FM_DRIVER_NAME
+		       ": driver registration failed\n");
+		return r;
+	}
+
+	return r;
+}
+
+static void __exit wl1273_core_exit(void)
+{
+	i2c_del_driver(&wl1273_core_driver);
+}
+late_initcall(wl1273_core_init);
+module_exit(wl1273_core_exit);
+
+MODULE_AUTHOR("Matti Aaltonen <matti.j.aaltonen@nokia.com>");
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
diff -druNp linux-libre-2.6.37-gnu1/drivers/mfd/wm831x-core.c linux-libre-2.6.38-gnu1/drivers/mfd/wm831x-core.c
--- linux-libre-2.6.37-gnu1/drivers/mfd/wm831x-core.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mfd/wm831x-core.c	2011-03-14 21:20:32.000000000 -0400
@@ -1541,6 +1541,12 @@ int wm831x_device_init(struct wm831x *wm
 		dev_info(wm831x->dev, "WM8325 revision %c\n", 'A' + rev);
 		break;
 
+	case WM8326:
+		parent = WM8326;
+		wm831x->num_gpio = 12;
+		dev_info(wm831x->dev, "WM8326 revision %c\n", 'A' + rev);
+		break;
+
 	default:
 		dev_err(wm831x->dev, "Unknown WM831x device %04x\n", ret);
 		ret = -EINVAL;
@@ -1610,18 +1616,9 @@ int wm831x_device_init(struct wm831x *wm
 		break;
 
 	case WM8320:
-		ret = mfd_add_devices(wm831x->dev, -1,
-				      wm8320_devs, ARRAY_SIZE(wm8320_devs),
-				      NULL, 0);
-		break;
-
 	case WM8321:
-		ret = mfd_add_devices(wm831x->dev, -1,
-				      wm8320_devs, ARRAY_SIZE(wm8320_devs),
-				      NULL, 0);
-		break;
-
 	case WM8325:
+	case WM8326:
 		ret = mfd_add_devices(wm831x->dev, -1,
 				      wm8320_devs, ARRAY_SIZE(wm8320_devs),
 				      NULL, wm831x->irq_base);
diff -druNp linux-libre-2.6.37-gnu1/drivers/mfd/wm831x-i2c.c linux-libre-2.6.38-gnu1/drivers/mfd/wm831x-i2c.c
--- linux-libre-2.6.37-gnu1/drivers/mfd/wm831x-i2c.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mfd/wm831x-i2c.c	2011-03-14 21:20:32.000000000 -0400
@@ -94,9 +94,9 @@ static int wm831x_i2c_remove(struct i2c_
 	return 0;
 }
 
-static int wm831x_i2c_suspend(struct i2c_client *i2c, pm_message_t mesg)
+static int wm831x_i2c_suspend(struct device *dev)
 {
-	struct wm831x *wm831x = i2c_get_clientdata(i2c);
+	struct wm831x *wm831x = dev_get_drvdata(dev);
 
 	return wm831x_device_suspend(wm831x);
 }
@@ -108,19 +108,23 @@ static const struct i2c_device_id wm831x
 	{ "wm8320", WM8320 },
 	{ "wm8321", WM8321 },
 	{ "wm8325", WM8325 },
+	{ "wm8326", WM8326 },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, wm831x_i2c_id);
 
+static const struct dev_pm_ops wm831x_pm_ops = {
+	.suspend = wm831x_i2c_suspend,
+};
 
 static struct i2c_driver wm831x_i2c_driver = {
 	.driver = {
-		   .name = "wm831x",
-		   .owner = THIS_MODULE,
+		.name = "wm831x",
+		.owner = THIS_MODULE,
+		.pm = &wm831x_pm_ops,
 	},
 	.probe = wm831x_i2c_probe,
 	.remove = wm831x_i2c_remove,
-	.suspend = wm831x_i2c_suspend,
 	.id_table = wm831x_i2c_id,
 };
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/mfd/wm831x-irq.c linux-libre-2.6.38-gnu1/drivers/mfd/wm831x-irq.c
--- linux-libre-2.6.37-gnu1/drivers/mfd/wm831x-irq.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mfd/wm831x-irq.c	2011-03-14 21:20:32.000000000 -0400
@@ -345,16 +345,16 @@ static inline struct wm831x_irq_data *ir
 	return &wm831x_irqs[irq - wm831x->irq_base];
 }
 
-static void wm831x_irq_lock(unsigned int irq)
+static void wm831x_irq_lock(struct irq_data *data)
 {
-	struct wm831x *wm831x = get_irq_chip_data(irq);
+	struct wm831x *wm831x = irq_data_get_irq_chip_data(data);
 
 	mutex_lock(&wm831x->irq_lock);
 }
 
-static void wm831x_irq_sync_unlock(unsigned int irq)
+static void wm831x_irq_sync_unlock(struct irq_data *data)
 {
-	struct wm831x *wm831x = get_irq_chip_data(irq);
+	struct wm831x *wm831x = irq_data_get_irq_chip_data(data);
 	int i;
 
 	for (i = 0; i < ARRAY_SIZE(wm831x->irq_masks_cur); i++) {
@@ -371,28 +371,30 @@ static void wm831x_irq_sync_unlock(unsig
 	mutex_unlock(&wm831x->irq_lock);
 }
 
-static void wm831x_irq_unmask(unsigned int irq)
+static void wm831x_irq_unmask(struct irq_data *data)
 {
-	struct wm831x *wm831x = get_irq_chip_data(irq);
-	struct wm831x_irq_data *irq_data = irq_to_wm831x_irq(wm831x, irq);
+	struct wm831x *wm831x = irq_data_get_irq_chip_data(data);
+	struct wm831x_irq_data *irq_data = irq_to_wm831x_irq(wm831x,
+							     data->irq);
 
 	wm831x->irq_masks_cur[irq_data->reg - 1] &= ~irq_data->mask;
 }
 
-static void wm831x_irq_mask(unsigned int irq)
+static void wm831x_irq_mask(struct irq_data *data)
 {
-	struct wm831x *wm831x = get_irq_chip_data(irq);
-	struct wm831x_irq_data *irq_data = irq_to_wm831x_irq(wm831x, irq);
+	struct wm831x *wm831x = irq_data_get_irq_chip_data(data);
+	struct wm831x_irq_data *irq_data = irq_to_wm831x_irq(wm831x,
+							     data->irq);
 
 	wm831x->irq_masks_cur[irq_data->reg - 1] |= irq_data->mask;
 }
 
-static int wm831x_irq_set_type(unsigned int irq, unsigned int type)
+static int wm831x_irq_set_type(struct irq_data *data, unsigned int type)
 {
-	struct wm831x *wm831x = get_irq_chip_data(irq);
-	int val;
+	struct wm831x *wm831x = irq_data_get_irq_chip_data(data);
+	int val, irq;
 
-	irq = irq - wm831x->irq_base;
+	irq = data->irq - wm831x->irq_base;
 
 	if (irq < WM831X_IRQ_GPIO_1 || irq > WM831X_IRQ_GPIO_11) {
 		/* Ignore internal-only IRQs */
@@ -421,12 +423,12 @@ static int wm831x_irq_set_type(unsigned
 }
 
 static struct irq_chip wm831x_irq_chip = {
-	.name = "wm831x",
-	.bus_lock = wm831x_irq_lock,
-	.bus_sync_unlock = wm831x_irq_sync_unlock,
-	.mask = wm831x_irq_mask,
-	.unmask = wm831x_irq_unmask,
-	.set_type = wm831x_irq_set_type,
+	.name			= "wm831x",
+	.irq_bus_lock		= wm831x_irq_lock,
+	.irq_bus_sync_unlock	= wm831x_irq_sync_unlock,
+	.irq_mask		= wm831x_irq_mask,
+	.irq_unmask		= wm831x_irq_unmask,
+	.irq_set_type		= wm831x_irq_set_type,
 };
 
 /* The processing of the primary interrupt occurs in a thread so that
@@ -515,6 +517,17 @@ int wm831x_irq_init(struct wm831x *wm831
 		return 0;
 	}
 
+	/* Try to flag /IRQ as a wake source; there are a number of
+	 * unconditional wake sources in the PMIC so this isn't
+	 * conditional but we don't actually care *too* much if it
+	 * fails.
+	 */
+	ret = enable_irq_wake(irq);
+	if (ret != 0) {
+		dev_warn(wm831x->dev, "Can't enable IRQ as wake source: %d\n",
+			 ret);
+	}
+
 	wm831x->irq = irq;
 	wm831x->irq_base = pdata->irq_base;
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/mfd/wm831x-spi.c linux-libre-2.6.38-gnu1/drivers/mfd/wm831x-spi.c
--- linux-libre-2.6.37-gnu1/drivers/mfd/wm831x-spi.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mfd/wm831x-spi.c	2011-03-14 21:20:32.000000000 -0400
@@ -81,6 +81,8 @@ static int __devinit wm831x_spi_probe(st
 		type = WM8321;
 	else if (strcmp(spi->modalias, "wm8325") == 0)
 		type = WM8325;
+	else if (strcmp(spi->modalias, "wm8326") == 0)
+		type = WM8326;
 	else {
 		dev_err(&spi->dev, "Unknown device type\n");
 		return -EINVAL;
@@ -184,6 +186,17 @@ static struct spi_driver wm8325_spi_driv
 	.suspend	= wm831x_spi_suspend,
 };
 
+static struct spi_driver wm8326_spi_driver = {
+	.driver = {
+		.name	= "wm8326",
+		.bus	= &spi_bus_type,
+		.owner	= THIS_MODULE,
+	},
+	.probe		= wm831x_spi_probe,
+	.remove		= __devexit_p(wm831x_spi_remove),
+	.suspend	= wm831x_spi_suspend,
+};
+
 static int __init wm831x_spi_init(void)
 {
 	int ret;
@@ -212,12 +225,17 @@ static int __init wm831x_spi_init(void)
 	if (ret != 0)
 		pr_err("Failed to register WM8325 SPI driver: %d\n", ret);
 
+	ret = spi_register_driver(&wm8326_spi_driver);
+	if (ret != 0)
+		pr_err("Failed to register WM8326 SPI driver: %d\n", ret);
+
 	return 0;
 }
 subsys_initcall(wm831x_spi_init);
 
 static void __exit wm831x_spi_exit(void)
 {
+	spi_unregister_driver(&wm8326_spi_driver);
 	spi_unregister_driver(&wm8325_spi_driver);
 	spi_unregister_driver(&wm8321_spi_driver);
 	spi_unregister_driver(&wm8320_spi_driver);
diff -druNp linux-libre-2.6.37-gnu1/drivers/mfd/wm8350-irq.c linux-libre-2.6.38-gnu1/drivers/mfd/wm8350-irq.c
--- linux-libre-2.6.37-gnu1/drivers/mfd/wm8350-irq.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mfd/wm8350-irq.c	2011-03-14 21:20:32.000000000 -0400
@@ -417,16 +417,16 @@ static irqreturn_t wm8350_irq(int irq, v
 	return IRQ_HANDLED;
 }
 
-static void wm8350_irq_lock(unsigned int irq)
+static void wm8350_irq_lock(struct irq_data *data)
 {
-	struct wm8350 *wm8350 = get_irq_chip_data(irq);
+	struct wm8350 *wm8350 = irq_data_get_irq_chip_data(data);
 
 	mutex_lock(&wm8350->irq_lock);
 }
 
-static void wm8350_irq_sync_unlock(unsigned int irq)
+static void wm8350_irq_sync_unlock(struct irq_data *data)
 {
-	struct wm8350 *wm8350 = get_irq_chip_data(irq);
+	struct wm8350 *wm8350 = irq_data_get_irq_chip_data(data);
 	int i;
 
 	for (i = 0; i < ARRAY_SIZE(wm8350->irq_masks); i++) {
@@ -442,28 +442,30 @@ static void wm8350_irq_sync_unlock(unsig
 	mutex_unlock(&wm8350->irq_lock);
 }
 
-static void wm8350_irq_enable(unsigned int irq)
+static void wm8350_irq_enable(struct irq_data *data)
 {
-	struct wm8350 *wm8350 = get_irq_chip_data(irq);
-	struct wm8350_irq_data *irq_data = irq_to_wm8350_irq(wm8350, irq);
+	struct wm8350 *wm8350 = irq_data_get_irq_chip_data(data);
+	struct wm8350_irq_data *irq_data = irq_to_wm8350_irq(wm8350,
+							     data->irq);
 
 	wm8350->irq_masks[irq_data->reg] &= ~irq_data->mask;
 }
 
-static void wm8350_irq_disable(unsigned int irq)
+static void wm8350_irq_disable(struct irq_data *data)
 {
-	struct wm8350 *wm8350 = get_irq_chip_data(irq);
-	struct wm8350_irq_data *irq_data = irq_to_wm8350_irq(wm8350, irq);
+	struct wm8350 *wm8350 = irq_data_get_irq_chip_data(data);
+	struct wm8350_irq_data *irq_data = irq_to_wm8350_irq(wm8350,
+							     data->irq);
 
 	wm8350->irq_masks[irq_data->reg] |= irq_data->mask;
 }
 
 static struct irq_chip wm8350_irq_chip = {
-	.name = "wm8350",
-	.bus_lock = wm8350_irq_lock,
-	.bus_sync_unlock = wm8350_irq_sync_unlock,
-	.disable = wm8350_irq_disable,
-	.enable = wm8350_irq_enable,
+	.name			= "wm8350",
+	.irq_bus_lock		= wm8350_irq_lock,
+	.irq_bus_sync_unlock	= wm8350_irq_sync_unlock,
+	.irq_disable		= wm8350_irq_disable,
+	.irq_enable		= wm8350_irq_enable,
 };
 
 int wm8350_irq_init(struct wm8350 *wm8350, int irq,
diff -druNp linux-libre-2.6.37-gnu1/drivers/mfd/wm8994-core.c linux-libre-2.6.38-gnu1/drivers/mfd/wm8994-core.c
--- linux-libre-2.6.37-gnu1/drivers/mfd/wm8994-core.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mfd/wm8994-core.c	2011-03-14 21:20:32.000000000 -0400
@@ -18,6 +18,7 @@
 #include <linux/i2c.h>
 #include <linux/delay.h>
 #include <linux/mfd/core.h>
+#include <linux/pm_runtime.h>
 #include <linux/regulator/consumer.h>
 #include <linux/regulator/machine.h>
 
@@ -169,8 +170,16 @@ out:
 EXPORT_SYMBOL_GPL(wm8994_set_bits);
 
 static struct mfd_cell wm8994_regulator_devs[] = {
-	{ .name = "wm8994-ldo", .id = 1 },
-	{ .name = "wm8994-ldo", .id = 2 },
+	{
+		.name = "wm8994-ldo",
+		.id = 1,
+		.pm_runtime_no_callbacks = true,
+	},
+	{
+		.name = "wm8994-ldo",
+		.id = 2,
+		.pm_runtime_no_callbacks = true,
+	},
 };
 
 static struct resource wm8994_codec_resources[] = {
@@ -200,6 +209,7 @@ static struct mfd_cell wm8994_devs[] = {
 		.name = "wm8994-gpio",
 		.num_resources = ARRAY_SIZE(wm8994_gpio_resources),
 		.resources = wm8994_gpio_resources,
+		.pm_runtime_no_callbacks = true,
 	},
 };
 
@@ -218,12 +228,34 @@ static const char *wm8994_main_supplies[
 	"SPKVDD2",
 };
 
+static const char *wm8958_main_supplies[] = {
+	"DBVDD1",
+	"DBVDD2",
+	"DBVDD3",
+	"DCVDD",
+	"AVDD1",
+	"AVDD2",
+	"CPVDD",
+	"SPKVDD1",
+	"SPKVDD2",
+};
+
 #ifdef CONFIG_PM
-static int wm8994_device_suspend(struct device *dev)
+static int wm8994_suspend(struct device *dev)
 {
 	struct wm8994 *wm8994 = dev_get_drvdata(dev);
 	int ret;
 
+	/* Don't actually go through with the suspend if the CODEC is
+	 * still active (eg, for audio passthrough from CP. */
+	ret = wm8994_reg_read(wm8994, WM8994_POWER_MANAGEMENT_1);
+	if (ret < 0) {
+		dev_err(dev, "Failed to read power status: %d\n", ret);
+	} else if (ret & WM8994_VMID_SEL_MASK) {
+		dev_dbg(dev, "CODEC still active, ignoring suspend\n");
+		return 0;
+	}
+
 	/* GPIO configuration state is saved here since we may be configuring
 	 * the GPIO alternate functions even if we're not using the gpiolib
 	 * driver for them.
@@ -239,7 +271,9 @@ static int wm8994_device_suspend(struct
 	if (ret < 0)
 		dev_err(dev, "Failed to save LDO registers: %d\n", ret);
 
-	ret = regulator_bulk_disable(ARRAY_SIZE(wm8994_main_supplies),
+	wm8994->suspended = true;
+
+	ret = regulator_bulk_disable(wm8994->num_supplies,
 				     wm8994->supplies);
 	if (ret != 0) {
 		dev_err(dev, "Failed to disable supplies: %d\n", ret);
@@ -249,12 +283,16 @@ static int wm8994_device_suspend(struct
 	return 0;
 }
 
-static int wm8994_device_resume(struct device *dev)
+static int wm8994_resume(struct device *dev)
 {
 	struct wm8994 *wm8994 = dev_get_drvdata(dev);
 	int ret;
 
-	ret = regulator_bulk_enable(ARRAY_SIZE(wm8994_main_supplies),
+	/* We may have lied to the PM core about suspending */
+	if (!wm8994->suspended)
+		return 0;
+
+	ret = regulator_bulk_enable(wm8994->num_supplies,
 				    wm8994->supplies);
 	if (ret != 0) {
 		dev_err(dev, "Failed to enable supplies: %d\n", ret);
@@ -276,6 +314,8 @@ static int wm8994_device_resume(struct d
 	if (ret < 0)
 		dev_err(dev, "Failed to restore GPIO registers: %d\n", ret);
 
+	wm8994->suspended = false;
+
 	return 0;
 }
 #endif
@@ -305,9 +345,10 @@ static int wm8994_ldo_in_use(struct wm89
 /*
  * Instantiate the generic non-control parts of the device.
  */
-static int wm8994_device_init(struct wm8994 *wm8994, unsigned long id, int irq)
+static int wm8994_device_init(struct wm8994 *wm8994, int irq)
 {
 	struct wm8994_pdata *pdata = wm8994->dev->platform_data;
+	const char *devname;
 	int ret, i;
 
 	mutex_init(&wm8994->io_lock);
@@ -323,25 +364,48 @@ static int wm8994_device_init(struct wm8
 		goto err;
 	}
 
+	switch (wm8994->type) {
+	case WM8994:
+		wm8994->num_supplies = ARRAY_SIZE(wm8994_main_supplies);
+		break;
+	case WM8958:
+		wm8994->num_supplies = ARRAY_SIZE(wm8958_main_supplies);
+		break;
+	default:
+		BUG();
+		return -EINVAL;
+	}
+
 	wm8994->supplies = kzalloc(sizeof(struct regulator_bulk_data) *
-				   ARRAY_SIZE(wm8994_main_supplies),
+				   wm8994->num_supplies,
 				   GFP_KERNEL);
 	if (!wm8994->supplies) {
 		ret = -ENOMEM;
 		goto err;
 	}
 
-	for (i = 0; i < ARRAY_SIZE(wm8994_main_supplies); i++)
-		wm8994->supplies[i].supply = wm8994_main_supplies[i];
-
-	ret = regulator_bulk_get(wm8994->dev, ARRAY_SIZE(wm8994_main_supplies),
+	switch (wm8994->type) {
+	case WM8994:
+		for (i = 0; i < ARRAY_SIZE(wm8994_main_supplies); i++)
+			wm8994->supplies[i].supply = wm8994_main_supplies[i];
+		break;
+	case WM8958:
+		for (i = 0; i < ARRAY_SIZE(wm8958_main_supplies); i++)
+			wm8994->supplies[i].supply = wm8958_main_supplies[i];
+		break;
+	default:
+		BUG();
+		return -EINVAL;
+	}
+		
+	ret = regulator_bulk_get(wm8994->dev, wm8994->num_supplies,
 				 wm8994->supplies);
 	if (ret != 0) {
 		dev_err(wm8994->dev, "Failed to get supplies: %d\n", ret);
 		goto err_supplies;
 	}
 
-	ret = regulator_bulk_enable(ARRAY_SIZE(wm8994_main_supplies),
+	ret = regulator_bulk_enable(wm8994->num_supplies,
 				    wm8994->supplies);
 	if (ret != 0) {
 		dev_err(wm8994->dev, "Failed to enable supplies: %d\n", ret);
@@ -353,7 +417,22 @@ static int wm8994_device_init(struct wm8
 		dev_err(wm8994->dev, "Failed to read ID register\n");
 		goto err_enable;
 	}
-	if (ret != 0x8994) {
+	switch (ret) {
+	case 0x8994:
+		devname = "WM8994";
+		if (wm8994->type != WM8994)
+			dev_warn(wm8994->dev, "Device registered as type %d\n",
+				 wm8994->type);
+		wm8994->type = WM8994;
+		break;
+	case 0x8958:
+		devname = "WM8958";
+		if (wm8994->type != WM8958)
+			dev_warn(wm8994->dev, "Device registered as type %d\n",
+				 wm8994->type);
+		wm8994->type = WM8958;
+		break;
+	default:
 		dev_err(wm8994->dev, "Device is not a WM8994, ID is %x\n",
 			ret);
 		ret = -EINVAL;
@@ -370,14 +449,16 @@ static int wm8994_device_init(struct wm8
 	switch (ret) {
 	case 0:
 	case 1:
-		dev_warn(wm8994->dev, "revision %c not fully supported\n",
-			'A' + ret);
+		if (wm8994->type == WM8994)
+			dev_warn(wm8994->dev,
+				 "revision %c not fully supported\n",
+				 'A' + ret);
 		break;
 	default:
-		dev_info(wm8994->dev, "revision %c\n", 'A' + ret);
 		break;
 	}
 
+	dev_info(wm8994->dev, "%s revision %c\n", devname, 'A' + ret);
 
 	if (pdata) {
 		wm8994->irq_base = pdata->irq_base;
@@ -418,15 +499,18 @@ static int wm8994_device_init(struct wm8
 		goto err_irq;
 	}
 
+	pm_runtime_enable(wm8994->dev);
+	pm_runtime_resume(wm8994->dev);
+
 	return 0;
 
 err_irq:
 	wm8994_irq_exit(wm8994);
 err_enable:
-	regulator_bulk_disable(ARRAY_SIZE(wm8994_main_supplies),
+	regulator_bulk_disable(wm8994->num_supplies,
 			       wm8994->supplies);
 err_get:
-	regulator_bulk_free(ARRAY_SIZE(wm8994_main_supplies), wm8994->supplies);
+	regulator_bulk_free(wm8994->num_supplies, wm8994->supplies);
 err_supplies:
 	kfree(wm8994->supplies);
 err:
@@ -437,11 +521,12 @@ err:
 
 static void wm8994_device_exit(struct wm8994 *wm8994)
 {
+	pm_runtime_disable(wm8994->dev);
 	mfd_remove_devices(wm8994->dev);
 	wm8994_irq_exit(wm8994);
-	regulator_bulk_disable(ARRAY_SIZE(wm8994_main_supplies),
+	regulator_bulk_disable(wm8994->num_supplies,
 			       wm8994->supplies);
-	regulator_bulk_free(ARRAY_SIZE(wm8994_main_supplies), wm8994->supplies);
+	regulator_bulk_free(wm8994->num_supplies, wm8994->supplies);
 	kfree(wm8994->supplies);
 	kfree(wm8994);
 }
@@ -506,8 +591,9 @@ static int wm8994_i2c_probe(struct i2c_c
 	wm8994->read_dev = wm8994_i2c_read_device;
 	wm8994->write_dev = wm8994_i2c_write_device;
 	wm8994->irq = i2c->irq;
+	wm8994->type = id->driver_data;
 
-	return wm8994_device_init(wm8994, id->driver_data, i2c->irq);
+	return wm8994_device_init(wm8994, i2c->irq);
 }
 
 static int wm8994_i2c_remove(struct i2c_client *i2c)
@@ -519,36 +605,23 @@ static int wm8994_i2c_remove(struct i2c_
 	return 0;
 }
 
-#ifdef CONFIG_PM
-static int wm8994_i2c_suspend(struct i2c_client *i2c, pm_message_t state)
-{
-	return wm8994_device_suspend(&i2c->dev);
-}
-
-static int wm8994_i2c_resume(struct i2c_client *i2c)
-{
-	return wm8994_device_resume(&i2c->dev);
-}
-#else
-#define wm8994_i2c_suspend NULL
-#define wm8994_i2c_resume NULL
-#endif
-
 static const struct i2c_device_id wm8994_i2c_id[] = {
-	{ "wm8994", 0 },
+	{ "wm8994", WM8994 },
+	{ "wm8958", WM8958 },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, wm8994_i2c_id);
 
+UNIVERSAL_DEV_PM_OPS(wm8994_pm_ops, wm8994_suspend, wm8994_resume, NULL);
+
 static struct i2c_driver wm8994_i2c_driver = {
 	.driver = {
-		   .name = "wm8994",
-		   .owner = THIS_MODULE,
+		.name = "wm8994",
+		.owner = THIS_MODULE,
+		.pm = &wm8994_pm_ops,
 	},
 	.probe = wm8994_i2c_probe,
 	.remove = wm8994_i2c_remove,
-	.suspend = wm8994_i2c_suspend,
-	.resume = wm8994_i2c_resume,
 	.id_table = wm8994_i2c_id,
 };
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/mfd/wm8994-irq.c linux-libre-2.6.38-gnu1/drivers/mfd/wm8994-irq.c
--- linux-libre-2.6.37-gnu1/drivers/mfd/wm8994-irq.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mfd/wm8994-irq.c	2011-03-14 21:20:32.000000000 -0400
@@ -156,16 +156,16 @@ static inline struct wm8994_irq_data *ir
 	return &wm8994_irqs[irq - wm8994->irq_base];
 }
 
-static void wm8994_irq_lock(unsigned int irq)
+static void wm8994_irq_lock(struct irq_data *data)
 {
-	struct wm8994 *wm8994 = get_irq_chip_data(irq);
+	struct wm8994 *wm8994 = irq_data_get_irq_chip_data(data);
 
 	mutex_lock(&wm8994->irq_lock);
 }
 
-static void wm8994_irq_sync_unlock(unsigned int irq)
+static void wm8994_irq_sync_unlock(struct irq_data *data)
 {
-	struct wm8994 *wm8994 = get_irq_chip_data(irq);
+	struct wm8994 *wm8994 = irq_data_get_irq_chip_data(data);
 	int i;
 
 	for (i = 0; i < ARRAY_SIZE(wm8994->irq_masks_cur); i++) {
@@ -182,28 +182,30 @@ static void wm8994_irq_sync_unlock(unsig
 	mutex_unlock(&wm8994->irq_lock);
 }
 
-static void wm8994_irq_unmask(unsigned int irq)
+static void wm8994_irq_unmask(struct irq_data *data)
 {
-	struct wm8994 *wm8994 = get_irq_chip_data(irq);
-	struct wm8994_irq_data *irq_data = irq_to_wm8994_irq(wm8994, irq);
+	struct wm8994 *wm8994 = irq_data_get_irq_chip_data(data);
+	struct wm8994_irq_data *irq_data = irq_to_wm8994_irq(wm8994,
+							     data->irq);
 
 	wm8994->irq_masks_cur[irq_data->reg - 1] &= ~irq_data->mask;
 }
 
-static void wm8994_irq_mask(unsigned int irq)
+static void wm8994_irq_mask(struct irq_data *data)
 {
-	struct wm8994 *wm8994 = get_irq_chip_data(irq);
-	struct wm8994_irq_data *irq_data = irq_to_wm8994_irq(wm8994, irq);
+	struct wm8994 *wm8994 = irq_data_get_irq_chip_data(data);
+	struct wm8994_irq_data *irq_data = irq_to_wm8994_irq(wm8994,
+							     data->irq);
 
 	wm8994->irq_masks_cur[irq_data->reg - 1] |= irq_data->mask;
 }
 
 static struct irq_chip wm8994_irq_chip = {
-	.name = "wm8994",
-	.bus_lock = wm8994_irq_lock,
-	.bus_sync_unlock = wm8994_irq_sync_unlock,
-	.mask = wm8994_irq_mask,
-	.unmask = wm8994_irq_unmask,
+	.name			= "wm8994",
+	.irq_bus_lock		= wm8994_irq_lock,
+	.irq_bus_sync_unlock	= wm8994_irq_sync_unlock,
+	.irq_mask		= wm8994_irq_mask,
+	.irq_unmask		= wm8994_irq_unmask,
 };
 
 /* The processing of the primary interrupt occurs in a thread so that
diff -druNp linux-libre-2.6.37-gnu1/drivers/misc/arm-charlcd.c linux-libre-2.6.38-gnu1/drivers/misc/arm-charlcd.c
--- linux-libre-2.6.37-gnu1/drivers/misc/arm-charlcd.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/misc/arm-charlcd.c	2011-03-14 21:20:32.000000000 -0400
@@ -313,7 +313,7 @@ static int __init charlcd_probe(struct p
 	INIT_DELAYED_WORK(&lcd->init_work, charlcd_init_work);
 	schedule_delayed_work(&lcd->init_work, 0);
 
-	dev_info(&pdev->dev, "initalized ARM character LCD at %08x\n",
+	dev_info(&pdev->dev, "initialized ARM character LCD at %08x\n",
 		lcd->phybase);
 
 	return 0;
diff -druNp linux-libre-2.6.37-gnu1/drivers/misc/bmp085.c linux-libre-2.6.38-gnu1/drivers/misc/bmp085.c
--- linux-libre-2.6.37-gnu1/drivers/misc/bmp085.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/misc/bmp085.c	2011-03-14 21:20:32.000000000 -0400
@@ -449,6 +449,7 @@ static const struct i2c_device_id bmp085
 	{ "bmp085", 0 },
 	{ }
 };
+MODULE_DEVICE_TABLE(i2c, bmp085_id);
 
 static struct i2c_driver bmp085_driver = {
 	.driver = {
diff -druNp linux-libre-2.6.37-gnu1/drivers/misc/cs5535-mfgpt.c linux-libre-2.6.38-gnu1/drivers/misc/cs5535-mfgpt.c
--- linux-libre-2.6.37-gnu1/drivers/misc/cs5535-mfgpt.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/misc/cs5535-mfgpt.c	2011-03-14 21:20:32.000000000 -0400
@@ -16,12 +16,11 @@
 #include <linux/spinlock.h>
 #include <linux/interrupt.h>
 #include <linux/module.h>
-#include <linux/pci.h>
+#include <linux/platform_device.h>
 #include <linux/cs5535.h>
 #include <linux/slab.h>
 
 #define DRV_NAME "cs5535-mfgpt"
-#define MFGPT_BAR 2
 
 static int mfgpt_reset_timers;
 module_param_named(mfgptfix, mfgpt_reset_timers, int, 0644);
@@ -37,7 +36,7 @@ static struct cs5535_mfgpt_chip {
 	DECLARE_BITMAP(avail, MFGPT_MAX_TIMERS);
 	resource_size_t base;
 
-	struct pci_dev *pdev;
+	struct platform_device *pdev;
 	spinlock_t lock;
 	int initialized;
 } cs5535_mfgpt_chip;
@@ -290,10 +289,10 @@ static int __init scan_timers(struct cs5
 	return timers;
 }
 
-static int __init cs5535_mfgpt_probe(struct pci_dev *pdev,
-		const struct pci_device_id *pci_id)
+static int __devinit cs5535_mfgpt_probe(struct platform_device *pdev)
 {
-	int err, t;
+	struct resource *res;
+	int err = -EIO, t;
 
 	/* There are two ways to get the MFGPT base address; one is by
 	 * fetching it from MSR_LBAR_MFGPT, the other is by reading the
@@ -302,29 +301,27 @@ static int __init cs5535_mfgpt_probe(str
 	 * it turns out to be unreliable in the face of crappy BIOSes, we
 	 * can always go back to using MSRs.. */
 
-	err = pci_enable_device_io(pdev);
-	if (err) {
-		dev_err(&pdev->dev, "can't enable device IO\n");
+	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+	if (!res) {
+		dev_err(&pdev->dev, "can't fetch device resource info\n");
 		goto done;
 	}
 
-	err = pci_request_region(pdev, MFGPT_BAR, DRV_NAME);
-	if (err) {
-		dev_err(&pdev->dev, "can't alloc PCI BAR #%d\n", MFGPT_BAR);
+	if (!request_region(res->start, resource_size(res), pdev->name)) {
+		dev_err(&pdev->dev, "can't request region\n");
 		goto done;
 	}
 
 	/* set up the driver-specific struct */
-	cs5535_mfgpt_chip.base = pci_resource_start(pdev, MFGPT_BAR);
+	cs5535_mfgpt_chip.base = res->start;
 	cs5535_mfgpt_chip.pdev = pdev;
 	spin_lock_init(&cs5535_mfgpt_chip.lock);
 
-	dev_info(&pdev->dev, "allocated PCI BAR #%d: base 0x%llx\n", MFGPT_BAR,
-			(unsigned long long) cs5535_mfgpt_chip.base);
+	dev_info(&pdev->dev, "reserved resource region %pR\n", res);
 
 	/* detect the available timers */
 	t = scan_timers(&cs5535_mfgpt_chip);
-	dev_info(&pdev->dev, DRV_NAME ": %d MFGPT timers available\n", t);
+	dev_info(&pdev->dev, "%d MFGPT timers available\n", t);
 	cs5535_mfgpt_chip.initialized = 1;
 	return 0;
 
@@ -332,47 +329,18 @@ done:
 	return err;
 }
 
-static struct pci_device_id cs5535_mfgpt_pci_tbl[] = {
-	{ PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_CS5535_ISA) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA) },
-	{ 0, },
+static struct platform_driver cs5535_mfgpt_drv = {
+	.driver = {
+		.name = DRV_NAME,
+		.owner = THIS_MODULE,
+	},
+	.probe = cs5535_mfgpt_probe,
 };
-MODULE_DEVICE_TABLE(pci, cs5535_mfgpt_pci_tbl);
-
-/*
- * Just like with the cs5535-gpio driver, we can't use the standard PCI driver
- * registration stuff.  It only allows only one driver to bind to each PCI
- * device, and we want the GPIO and MFGPT drivers to be able to share a PCI
- * device.  Instead, we manually scan for the PCI device, request a single
- * region, and keep track of the devices that we're using.
- */
-
-static int __init cs5535_mfgpt_scan_pci(void)
-{
-	struct pci_dev *pdev;
-	int err = -ENODEV;
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(cs5535_mfgpt_pci_tbl); i++) {
-		pdev = pci_get_device(cs5535_mfgpt_pci_tbl[i].vendor,
-				cs5535_mfgpt_pci_tbl[i].device, NULL);
-		if (pdev) {
-			err = cs5535_mfgpt_probe(pdev,
-					&cs5535_mfgpt_pci_tbl[i]);
-			if (err)
-				pci_dev_put(pdev);
-
-			/* we only support a single CS5535/6 southbridge */
-			break;
-		}
-	}
 
-	return err;
-}
 
 static int __init cs5535_mfgpt_init(void)
 {
-	return cs5535_mfgpt_scan_pci();
+	return platform_driver_register(&cs5535_mfgpt_drv);
 }
 
 module_init(cs5535_mfgpt_init);
@@ -380,3 +348,4 @@ module_init(cs5535_mfgpt_init);
 MODULE_AUTHOR("Andres Salomon <dilinger@queued.net>");
 MODULE_DESCRIPTION("CS5535/CS5536 MFGPT timer driver");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" DRV_NAME);
diff -druNp linux-libre-2.6.37-gnu1/drivers/misc/eeprom/at24.c linux-libre-2.6.38-gnu1/drivers/misc/eeprom/at24.c
--- linux-libre-2.6.37-gnu1/drivers/misc/eeprom/at24.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/misc/eeprom/at24.c	2011-03-14 21:20:32.000000000 -0400
@@ -20,6 +20,7 @@
 #include <linux/log2.h>
 #include <linux/bitops.h>
 #include <linux/jiffies.h>
+#include <linux/of.h>
 #include <linux/i2c.h>
 #include <linux/i2c/at24.h>
 
@@ -457,6 +458,27 @@ static ssize_t at24_macc_write(struct me
 
 /*-------------------------------------------------------------------------*/
 
+#ifdef CONFIG_OF
+static void at24_get_ofdata(struct i2c_client *client,
+		struct at24_platform_data *chip)
+{
+	const __be32 *val;
+	struct device_node *node = client->dev.of_node;
+
+	if (node) {
+		if (of_get_property(node, "read-only", NULL))
+			chip->flags |= AT24_FLAG_READONLY;
+		val = of_get_property(node, "pagesize", NULL);
+		if (val)
+			chip->page_size = be32_to_cpup(val);
+	}
+}
+#else
+static void at24_get_ofdata(struct i2c_client *client,
+		struct at24_platform_data *chip)
+{ }
+#endif /* CONFIG_OF */
+
 static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
 {
 	struct at24_platform_data chip;
@@ -485,6 +507,9 @@ static int at24_probe(struct i2c_client
 		 */
 		chip.page_size = 1;
 
+		/* update chipdata if OF is present */
+		at24_get_ofdata(client, &chip);
+
 		chip.setup = NULL;
 		chip.context = NULL;
 	}
@@ -492,6 +517,11 @@ static int at24_probe(struct i2c_client
 	if (!is_power_of_2(chip.byte_len))
 		dev_warn(&client->dev,
 			"byte_len looks suspicious (no power of 2)!\n");
+	if (!chip.page_size) {
+		dev_err(&client->dev, "page_size must not be 0!\n");
+		err = -EINVAL;
+		goto err_out;
+	}
 	if (!is_power_of_2(chip.page_size))
 		dev_warn(&client->dev,
 			"page_size looks suspicious (no power of 2)!\n");
@@ -597,19 +627,15 @@ static int at24_probe(struct i2c_client
 
 	i2c_set_clientdata(client, at24);
 
-	dev_info(&client->dev, "%zu byte %s EEPROM %s\n",
+	dev_info(&client->dev, "%zu byte %s EEPROM, %s, %u bytes/write\n",
 		at24->bin.size, client->name,
-		writable ? "(writable)" : "(read-only)");
+		writable ? "writable" : "read-only", at24->write_max);
 	if (use_smbus == I2C_SMBUS_WORD_DATA ||
 	    use_smbus == I2C_SMBUS_BYTE_DATA) {
 		dev_notice(&client->dev, "Falling back to %s reads, "
 			   "performance will suffer\n", use_smbus ==
 			   I2C_SMBUS_WORD_DATA ? "word" : "byte");
 	}
-	dev_dbg(&client->dev,
-		"page_size %d, num_addresses %d, write_max %d, use_smbus %d\n",
-		chip.page_size, num_addresses,
-		at24->write_max, use_smbus);
 
 	/* export data to kernel code */
 	if (chip.setup)
@@ -660,6 +686,11 @@ static struct i2c_driver at24_driver = {
 
 static int __init at24_init(void)
 {
+	if (!io_limit) {
+		pr_err("at24: io_limit must not be 0!\n");
+		return -EINVAL;
+	}
+
 	io_limit = rounddown_pow_of_two(io_limit);
 	return i2c_add_driver(&at24_driver);
 }
diff -druNp linux-libre-2.6.37-gnu1/drivers/misc/ioc4.c linux-libre-2.6.38-gnu1/drivers/misc/ioc4.c
--- linux-libre-2.6.37-gnu1/drivers/misc/ioc4.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/misc/ioc4.c	2011-03-14 21:20:32.000000000 -0400
@@ -273,13 +273,11 @@ ioc4_variant(struct ioc4_driver_data *id
 static void __devinit
 ioc4_load_modules(struct work_struct *work)
 {
-	/* arg just has to be freed */
-
 	request_module("sgiioc4");
-
-	kfree(work);
 }
 
+static DECLARE_WORK(ioc4_load_modules_work, ioc4_load_modules);
+
 /* Adds a new instance of an IOC4 card */
 static int __devinit
 ioc4_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id)
@@ -396,21 +394,12 @@ ioc4_probe(struct pci_dev *pdev, const s
 	 * PCI device.
 	 */
 	if (idd->idd_variant != IOC4_VARIANT_PCI_RT) {
-		struct work_struct *work;
-		work = kzalloc(sizeof(struct work_struct), GFP_KERNEL);
-		if (!work) {
-			printk(KERN_WARNING
-			       "%s: IOC4 unable to allocate memory for "
-			       "load of sub-modules.\n", __func__);
-		} else {
-			/* Request the module from a work procedure as the
-			 * modprobe goes out to a userland helper and that
-			 * will hang if done directly from ioc4_probe().
-			 */
-			printk(KERN_INFO "IOC4 loading sgiioc4 submodule\n");
-			INIT_WORK(work, ioc4_load_modules);
-			schedule_work(work);
-		}
+		/* Request the module from a work procedure as the modprobe
+		 * goes out to a userland helper and that will hang if done
+		 * directly from ioc4_probe().
+		 */
+		printk(KERN_INFO "IOC4 loading sgiioc4 submodule\n");
+		schedule_work(&ioc4_load_modules_work);
 	}
 
 	return 0;
@@ -498,7 +487,7 @@ static void __exit
 ioc4_exit(void)
 {
 	/* Ensure ioc4_load_modules() has completed before exiting */
-	flush_scheduled_work();
+	flush_work_sync(&ioc4_load_modules_work);
 	pci_unregister_driver(&ioc4_driver);
 }
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/misc/Kconfig linux-libre-2.6.38-gnu1/drivers/misc/Kconfig
--- linux-libre-2.6.37-gnu1/drivers/misc/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/misc/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -64,7 +64,7 @@ config ATMEL_PWM
 
 config AB8500_PWM
 	bool "AB8500 PWM support"
-	depends on AB8500_CORE
+	depends on AB8500_CORE && ARCH_U8500
 	select HAVE_PWM
 	help
 	  This driver exports functions to enable/disble/config/free Pulse
@@ -402,7 +402,7 @@ config TI_DAC7512
 	  DAC7512 16-bit digital-to-analog converter.
 
 	  This driver can also be built as a module. If so, the module
-	  will be calles ti_dac7512.
+	  will be called ti_dac7512.
 
 config VMWARE_BALLOON
 	tristate "VMware Balloon Driver"
diff -druNp linux-libre-2.6.37-gnu1/drivers/misc/tifm_core.c linux-libre-2.6.38-gnu1/drivers/misc/tifm_core.c
--- linux-libre-2.6.37-gnu1/drivers/misc/tifm_core.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/misc/tifm_core.c	2011-03-14 21:20:32.000000000 -0400
@@ -329,7 +329,7 @@ static int __init tifm_init(void)
 {
 	int rc;
 
-	workqueue = create_freezeable_workqueue("tifm");
+	workqueue = create_freezable_workqueue("tifm");
 	if (!workqueue)
 		return -ENOMEM;
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/misc/vmw_balloon.c linux-libre-2.6.38-gnu1/drivers/misc/vmw_balloon.c
--- linux-libre-2.6.37-gnu1/drivers/misc/vmw_balloon.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/misc/vmw_balloon.c	2011-03-14 21:20:32.000000000 -0400
@@ -45,7 +45,7 @@
 
 MODULE_AUTHOR("VMware, Inc.");
 MODULE_DESCRIPTION("VMware Memory Control (Balloon) Driver");
-MODULE_VERSION("1.2.1.1-k");
+MODULE_VERSION("1.2.1.2-k");
 MODULE_ALIAS("dmi:*:svnVMware*:*");
 MODULE_ALIAS("vmware_vmmemctl");
 MODULE_LICENSE("GPL");
@@ -315,7 +315,8 @@ static bool vmballoon_send_get_target(st
  * fear that guest will need it. Host may reject some pages, we need to
  * check the return value and maybe submit a different page.
  */
-static bool vmballoon_send_lock_page(struct vmballoon *b, unsigned long pfn)
+static bool vmballoon_send_lock_page(struct vmballoon *b, unsigned long pfn,
+				     unsigned int *hv_status)
 {
 	unsigned long status, dummy;
 	u32 pfn32;
@@ -326,7 +327,7 @@ static bool vmballoon_send_lock_page(str
 
 	STATS_INC(b->stats.lock);
 
-	status = VMWARE_BALLOON_CMD(LOCK, pfn, dummy);
+	*hv_status = status = VMWARE_BALLOON_CMD(LOCK, pfn, dummy);
 	if (vmballoon_check_status(b, status))
 		return true;
 
@@ -410,6 +411,7 @@ static int vmballoon_reserve_page(struct
 {
 	struct page *page;
 	gfp_t flags;
+	unsigned int hv_status;
 	bool locked = false;
 
 	do {
@@ -429,11 +431,12 @@ static int vmballoon_reserve_page(struct
 		}
 
 		/* inform monitor */
-		locked = vmballoon_send_lock_page(b, page_to_pfn(page));
+		locked = vmballoon_send_lock_page(b, page_to_pfn(page), &hv_status);
 		if (!locked) {
 			STATS_INC(b->stats.refused_alloc);
 
-			if (b->reset_required) {
+			if (hv_status == VMW_BALLOON_ERROR_RESET ||
+			    hv_status == VMW_BALLOON_ERROR_PPN_NOTNEEDED) {
 				__free_page(page);
 				return -EIO;
 			}
@@ -782,7 +785,7 @@ static int __init vmballoon_init(void)
 	if (x86_hyper != &x86_hyper_vmware)
 		return -ENODEV;
 
-	vmballoon_wq = create_freezeable_workqueue("vmmemctl");
+	vmballoon_wq = create_freezable_workqueue("vmmemctl");
 	if (!vmballoon_wq) {
 		pr_err("failed to create workqueue\n");
 		return -ENOMEM;
diff -druNp linux-libre-2.6.37-gnu1/drivers/mmc/card/block.c linux-libre-2.6.38-gnu1/drivers/mmc/card/block.c
--- linux-libre-2.6.37-gnu1/drivers/mmc/card/block.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mmc/card/block.c	2011-03-14 21:20:32.000000000 -0400
@@ -257,7 +257,7 @@ static u32 get_card_status(struct mmc_ca
 	cmd.flags = MMC_RSP_SPI_R2 | MMC_RSP_R1 | MMC_CMD_AC;
 	err = mmc_wait_for_cmd(card->host, &cmd, 0);
 	if (err)
-		printk(KERN_ERR "%s: error %d sending status comand",
+		printk(KERN_ERR "%s: error %d sending status command",
 		       req->rq_disk->disk_name, err);
 	return cmd.resp[0];
 }
diff -druNp linux-libre-2.6.37-gnu1/drivers/mmc/card/Kconfig linux-libre-2.6.38-gnu1/drivers/mmc/card/Kconfig
--- linux-libre-2.6.37-gnu1/drivers/mmc/card/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mmc/card/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -16,6 +16,7 @@ config MMC_BLOCK
 
 config MMC_BLOCK_MINORS
 	int "Number of minors per block device"
+	depends on MMC_BLOCK
 	range 4 256
 	default 8
 	help
diff -druNp linux-libre-2.6.37-gnu1/drivers/mmc/core/bus.c linux-libre-2.6.38-gnu1/drivers/mmc/core/bus.c
--- linux-libre-2.6.37-gnu1/drivers/mmc/core/bus.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mmc/core/bus.c	2011-03-14 21:20:32.000000000 -0400
@@ -303,14 +303,14 @@ int mmc_add_card(struct mmc_card *card)
 			type, card->rca);
 	}
 
-	ret = device_add(&card->dev);
-	if (ret)
-		return ret;
-
 #ifdef CONFIG_DEBUG_FS
 	mmc_add_card_debugfs(card);
 #endif
 
+	ret = device_add(&card->dev);
+	if (ret)
+		return ret;
+
 	mmc_card_set_present(card);
 
 	return 0;
diff -druNp linux-libre-2.6.37-gnu1/drivers/mmc/core/core.c linux-libre-2.6.38-gnu1/drivers/mmc/core/core.c
--- linux-libre-2.6.37-gnu1/drivers/mmc/core/core.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mmc/core/core.c	2011-03-14 21:20:32.000000000 -0400
@@ -22,6 +22,7 @@
 #include <linux/scatterlist.h>
 #include <linux/log2.h>
 #include <linux/regulator/consumer.h>
+#include <linux/pm_runtime.h>
 
 #include <linux/mmc/card.h>
 #include <linux/mmc/host.h>
@@ -130,6 +131,8 @@ void mmc_request_done(struct mmc_host *h
 
 		if (mrq->done)
 			mrq->done(mrq);
+
+		mmc_host_clk_gate(host);
 	}
 }
 
@@ -190,6 +193,7 @@ mmc_start_request(struct mmc_host *host,
 			mrq->stop->mrq = mrq;
 		}
 	}
+	mmc_host_clk_ungate(host);
 	host->ops->request(host, mrq);
 }
 
@@ -295,8 +299,9 @@ void mmc_set_data_timeout(struct mmc_dat
 		unsigned int timeout_us, limit_us;
 
 		timeout_us = data->timeout_ns / 1000;
-		timeout_us += data->timeout_clks * 1000 /
-			(card->host->ios.clock / 1000);
+		if (mmc_host_clk_rate(card->host))
+			timeout_us += data->timeout_clks * 1000 /
+				(mmc_host_clk_rate(card->host) / 1000);
 
 		if (data->flags & MMC_DATA_WRITE)
 			/*
@@ -614,6 +619,8 @@ static inline void mmc_set_ios(struct mm
 		 ios->power_mode, ios->chip_select, ios->vdd,
 		 ios->bus_width, ios->timing);
 
+	if (ios->clock > 0)
+		mmc_set_ungated(host);
 	host->ops->set_ios(host, ios);
 }
 
@@ -641,6 +648,61 @@ void mmc_set_clock(struct mmc_host *host
 	mmc_set_ios(host);
 }
 
+#ifdef CONFIG_MMC_CLKGATE
+/*
+ * This gates the clock by setting it to 0 Hz.
+ */
+void mmc_gate_clock(struct mmc_host *host)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&host->clk_lock, flags);
+	host->clk_old = host->ios.clock;
+	host->ios.clock = 0;
+	host->clk_gated = true;
+	spin_unlock_irqrestore(&host->clk_lock, flags);
+	mmc_set_ios(host);
+}
+
+/*
+ * This restores the clock from gating by using the cached
+ * clock value.
+ */
+void mmc_ungate_clock(struct mmc_host *host)
+{
+	/*
+	 * We should previously have gated the clock, so the clock shall
+	 * be 0 here! The clock may however be 0 during initialization,
+	 * when some request operations are performed before setting
+	 * the frequency. When ungate is requested in that situation
+	 * we just ignore the call.
+	 */
+	if (host->clk_old) {
+		BUG_ON(host->ios.clock);
+		/* This call will also set host->clk_gated to false */
+		mmc_set_clock(host, host->clk_old);
+	}
+}
+
+void mmc_set_ungated(struct mmc_host *host)
+{
+	unsigned long flags;
+
+	/*
+	 * We've been given a new frequency while the clock is gated,
+	 * so make sure we regard this as ungating it.
+	 */
+	spin_lock_irqsave(&host->clk_lock, flags);
+	host->clk_gated = false;
+	spin_unlock_irqrestore(&host->clk_lock, flags);
+}
+
+#else
+void mmc_set_ungated(struct mmc_host *host)
+{
+}
+#endif
+
 /*
  * Change the bus mode (open drain/push-pull) of a host.
  */
@@ -1424,35 +1486,57 @@ int mmc_set_blocklen(struct mmc_card *ca
 }
 EXPORT_SYMBOL(mmc_set_blocklen);
 
+static int mmc_rescan_try_freq(struct mmc_host *host, unsigned freq)
+{
+	host->f_init = freq;
+
+#ifdef CONFIG_MMC_DEBUG
+	pr_info("%s: %s: trying to init card at %u Hz\n",
+		mmc_hostname(host), __func__, host->f_init);
+#endif
+	mmc_power_up(host);
+	sdio_reset(host);
+	mmc_go_idle(host);
+
+	mmc_send_if_cond(host, host->ocr_avail);
+
+	/* Order's important: probe SDIO, then SD, then MMC */
+	if (!mmc_attach_sdio(host))
+		return 0;
+	if (!mmc_attach_sd(host))
+		return 0;
+	if (!mmc_attach_mmc(host))
+		return 0;
+
+	mmc_power_off(host);
+	return -EIO;
+}
+
 void mmc_rescan(struct work_struct *work)
 {
+	static const unsigned freqs[] = { 400000, 300000, 200000, 100000 };
 	struct mmc_host *host =
 		container_of(work, struct mmc_host, detect.work);
-	u32 ocr;
-	int err;
-	unsigned long flags;
 	int i;
-	const unsigned freqs[] = { 400000, 300000, 200000, 100000 };
 
-	spin_lock_irqsave(&host->lock, flags);
-
-	if (host->rescan_disable) {
-		spin_unlock_irqrestore(&host->lock, flags);
+	if (host->rescan_disable)
 		return;
-	}
-
-	spin_unlock_irqrestore(&host->lock, flags);
-
 
 	mmc_bus_get(host);
 
-	/* if there is a card registered, check whether it is still present */
-	if ((host->bus_ops != NULL) && host->bus_ops->detect && !host->bus_dead)
+	/*
+	 * if there is a _removable_ card registered, check whether it is
+	 * still present
+	 */
+	if (host->bus_ops && host->bus_ops->detect && !host->bus_dead
+	    && !(host->caps & MMC_CAP_NONREMOVABLE))
 		host->bus_ops->detect(host);
 
+	/*
+	 * Let mmc_bus_put() free the bus/bus_ops if we've found that
+	 * the card is no longer present.
+	 */
 	mmc_bus_put(host);
-
-
 	mmc_bus_get(host);
 
 	/* if there still is a card present, stop here */
@@ -1461,8 +1545,6 @@ void mmc_rescan(struct work_struct *work
 		goto out;
 	}
 
-	/* detect a newly inserted card */
-
 	/*
 	 * Only we can add a new handler, so it's safe to
 	 * release the lock here.
@@ -1472,72 +1554,16 @@ void mmc_rescan(struct work_struct *work
 	if (host->ops->get_cd && host->ops->get_cd(host) == 0)
 		goto out;
 
+	mmc_claim_host(host);
 	for (i = 0; i < ARRAY_SIZE(freqs); i++) {
-		mmc_claim_host(host);
-
-		if (freqs[i] >= host->f_min)
-			host->f_init = freqs[i];
-		else if (!i || freqs[i-1] > host->f_min)
-			host->f_init = host->f_min;
-		else {
-			mmc_release_host(host);
-			goto out;
-		}
-#ifdef CONFIG_MMC_DEBUG
-		pr_info("%s: %s: trying to init card at %u Hz\n",
-			mmc_hostname(host), __func__, host->f_init);
-#endif
-		mmc_power_up(host);
-		sdio_reset(host);
-		mmc_go_idle(host);
-
-		mmc_send_if_cond(host, host->ocr_avail);
-
-		/*
-		 * First we search for SDIO...
-		 */
-		err = mmc_send_io_op_cond(host, 0, &ocr);
-		if (!err) {
-			if (mmc_attach_sdio(host, ocr)) {
-				mmc_claim_host(host);
-				/*
-				 * Try SDMEM (but not MMC) even if SDIO
-				 * is broken.
-				 */
-				if (mmc_send_app_op_cond(host, 0, &ocr))
-					goto out_fail;
-
-				if (mmc_attach_sd(host, ocr))
-					mmc_power_off(host);
-			}
-			goto out;
-		}
-
-		/*
-		 * ...then normal SD...
-		 */
-		err = mmc_send_app_op_cond(host, 0, &ocr);
-		if (!err) {
-			if (mmc_attach_sd(host, ocr))
-				mmc_power_off(host);
-			goto out;
-		}
-
-		/*
-		 * ...and finally MMC.
-		 */
-		err = mmc_send_op_cond(host, 0, &ocr);
-		if (!err) {
-			if (mmc_attach_mmc(host, ocr))
-				mmc_power_off(host);
-			goto out;
-		}
-
-out_fail:
-		mmc_release_host(host);
-		mmc_power_off(host);
+		if (!mmc_rescan_try_freq(host, max(freqs[i], host->f_min)))
+			break;
+		if (freqs[i] < host->f_min)
+			break;
 	}
-out:
+	mmc_release_host(host);
+
+ out:
 	if (host->caps & MMC_CAP_NEEDS_POLL)
 		mmc_schedule_delayed_work(&host->detect, HZ);
 }
@@ -1721,6 +1747,18 @@ int mmc_resume_host(struct mmc_host *hos
 		if (!(host->pm_flags & MMC_PM_KEEP_POWER)) {
 			mmc_power_up(host);
 			mmc_select_voltage(host, host->ocr);
+			/*
+			 * Tell runtime PM core we just powered up the card,
+			 * since it still believes the card is powered off.
+			 * Note that currently runtime PM is only enabled
+			 * for SDIO cards that are MMC_CAP_POWER_OFF_CARD
+			 */
+			if (mmc_card_sdio(host->card) &&
+			    (host->caps & MMC_CAP_POWER_OFF_CARD)) {
+				pm_runtime_disable(&host->card->dev);
+				pm_runtime_set_active(&host->card->dev);
+				pm_runtime_enable(&host->card->dev);
+			}
 		}
 		BUG_ON(!host->bus_ops->resume);
 		err = host->bus_ops->resume(host);
@@ -1790,7 +1828,7 @@ static int __init mmc_init(void)
 {
 	int ret;
 
-	workqueue = create_singlethread_workqueue("kmmcd");
+	workqueue = alloc_ordered_workqueue("kmmcd", 0);
 	if (!workqueue)
 		return -ENOMEM;
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/mmc/core/core.h linux-libre-2.6.38-gnu1/drivers/mmc/core/core.h
--- linux-libre-2.6.37-gnu1/drivers/mmc/core/core.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mmc/core/core.h	2011-03-14 21:20:32.000000000 -0400
@@ -33,6 +33,9 @@ void mmc_init_erase(struct mmc_card *car
 
 void mmc_set_chip_select(struct mmc_host *host, int mode);
 void mmc_set_clock(struct mmc_host *host, unsigned int hz);
+void mmc_gate_clock(struct mmc_host *host);
+void mmc_ungate_clock(struct mmc_host *host);
+void mmc_set_ungated(struct mmc_host *host);
 void mmc_set_bus_mode(struct mmc_host *host, unsigned int mode);
 void mmc_set_bus_width(struct mmc_host *host, unsigned int width);
 void mmc_set_bus_width_ddr(struct mmc_host *host, unsigned int width,
@@ -54,9 +57,9 @@ void mmc_rescan(struct work_struct *work
 void mmc_start_host(struct mmc_host *host);
 void mmc_stop_host(struct mmc_host *host);
 
-int mmc_attach_mmc(struct mmc_host *host, u32 ocr);
-int mmc_attach_sd(struct mmc_host *host, u32 ocr);
-int mmc_attach_sdio(struct mmc_host *host, u32 ocr);
+int mmc_attach_mmc(struct mmc_host *host);
+int mmc_attach_sd(struct mmc_host *host);
+int mmc_attach_sdio(struct mmc_host *host);
 
 /* Module parameters */
 extern int use_spi_crc;
diff -druNp linux-libre-2.6.37-gnu1/drivers/mmc/core/debugfs.c linux-libre-2.6.38-gnu1/drivers/mmc/core/debugfs.c
--- linux-libre-2.6.37-gnu1/drivers/mmc/core/debugfs.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mmc/core/debugfs.c	2011-03-14 21:20:32.000000000 -0400
@@ -183,6 +183,11 @@ void mmc_add_host_debugfs(struct mmc_hos
 			&mmc_clock_fops))
 		goto err_node;
 
+#ifdef CONFIG_MMC_CLKGATE
+	if (!debugfs_create_u32("clk_delay", (S_IRUSR | S_IWUSR),
+				root, &host->clk_delay))
+		goto err_node;
+#endif
 	return;
 
 err_node:
diff -druNp linux-libre-2.6.37-gnu1/drivers/mmc/core/host.c linux-libre-2.6.38-gnu1/drivers/mmc/core/host.c
--- linux-libre-2.6.37-gnu1/drivers/mmc/core/host.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mmc/core/host.c	2011-03-14 21:20:32.000000000 -0400
@@ -3,6 +3,7 @@
  *
  *  Copyright (C) 2003 Russell King, All Rights Reserved.
  *  Copyright (C) 2007-2008 Pierre Ossman
+ *  Copyright (C) 2010 Linus Walleij
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -20,6 +21,7 @@
 #include <linux/suspend.h>
 
 #include <linux/mmc/host.h>
+#include <linux/mmc/card.h>
 
 #include "core.h"
 #include "host.h"
@@ -50,6 +52,205 @@ void mmc_unregister_host_class(void)
 static DEFINE_IDR(mmc_host_idr);
 static DEFINE_SPINLOCK(mmc_host_lock);
 
+#ifdef CONFIG_MMC_CLKGATE
+
+/*
+ * Enabling clock gating will make the core call out to the host
+ * once up and once down when it performs a request or card operation
+ * intermingled in any fashion. The driver will see this through
+ * set_ios() operations with ios.clock field set to 0 to gate (disable)
+ * the block clock, and to the old frequency to enable it again.
+ */
+static void mmc_host_clk_gate_delayed(struct mmc_host *host)
+{
+	unsigned long tick_ns;
+	unsigned long freq = host->ios.clock;
+	unsigned long flags;
+
+	if (!freq) {
+		pr_debug("%s: frequency set to 0 in disable function, "
+			 "this means the clock is already disabled.\n",
+			 mmc_hostname(host));
+		return;
+	}
+	/*
+	 * New requests may have appeared while we were scheduling,
+	 * then there is no reason to delay the check before
+	 * clk_disable().
+	 */
+	spin_lock_irqsave(&host->clk_lock, flags);
+
+	/*
+	 * Delay n bus cycles (at least 8 from MMC spec) before attempting
+	 * to disable the MCI block clock. The reference count may have
+	 * gone up again after this delay due to rescheduling!
+	 */
+	if (!host->clk_requests) {
+		spin_unlock_irqrestore(&host->clk_lock, flags);
+		tick_ns = DIV_ROUND_UP(1000000000, freq);
+		ndelay(host->clk_delay * tick_ns);
+	} else {
+		/* New users appeared while waiting for this work */
+		spin_unlock_irqrestore(&host->clk_lock, flags);
+		return;
+	}
+	mutex_lock(&host->clk_gate_mutex);
+	spin_lock_irqsave(&host->clk_lock, flags);
+	if (!host->clk_requests) {
+		spin_unlock_irqrestore(&host->clk_lock, flags);
+		/* This will set host->ios.clock to 0 */
+		mmc_gate_clock(host);
+		spin_lock_irqsave(&host->clk_lock, flags);
+		pr_debug("%s: gated MCI clock\n", mmc_hostname(host));
+	}
+	spin_unlock_irqrestore(&host->clk_lock, flags);
+	mutex_unlock(&host->clk_gate_mutex);
+}
+
+/*
+ * Internal work. Work to disable the clock at some later point.
+ */
+static void mmc_host_clk_gate_work(struct work_struct *work)
+{
+	struct mmc_host *host = container_of(work, struct mmc_host,
+					      clk_gate_work);
+
+	mmc_host_clk_gate_delayed(host);
+}
+
+/**
+ *	mmc_host_clk_ungate - ungate hardware MCI clocks
+ *	@host: host to ungate.
+ *
+ *	Makes sure the host ios.clock is restored to a non-zero value
+ *	past this call.	Increase clock reference count and ungate clock
+ *	if we're the first user.
+ */
+void mmc_host_clk_ungate(struct mmc_host *host)
+{
+	unsigned long flags;
+
+	mutex_lock(&host->clk_gate_mutex);
+	spin_lock_irqsave(&host->clk_lock, flags);
+	if (host->clk_gated) {
+		spin_unlock_irqrestore(&host->clk_lock, flags);
+		mmc_ungate_clock(host);
+		spin_lock_irqsave(&host->clk_lock, flags);
+		pr_debug("%s: ungated MCI clock\n", mmc_hostname(host));
+	}
+	host->clk_requests++;
+	spin_unlock_irqrestore(&host->clk_lock, flags);
+	mutex_unlock(&host->clk_gate_mutex);
+}
+
+/**
+ *	mmc_host_may_gate_card - check if this card may be gated
+ *	@card: card to check.
+ */
+static bool mmc_host_may_gate_card(struct mmc_card *card)
+{
+	/* If there is no card we may gate it */
+	if (!card)
+		return true;
+	/*
+	 * Don't gate SDIO cards! These need to be clocked at all times
+	 * since they may be independent systems generating interrupts
+	 * and other events. The clock requests counter from the core will
+	 * go down to zero since the core does not need it, but we will not
+	 * gate the clock, because there is somebody out there that may still
+	 * be using it.
+	 */
+	if (mmc_card_sdio(card))
+		return false;
+
+	return true;
+}
+
+/**
+ *	mmc_host_clk_gate - gate off hardware MCI clocks
+ *	@host: host to gate.
+ *
+ *	Calls the host driver with ios.clock set to zero as often as possible
+ *	in order to gate off hardware MCI clocks. Decrease clock reference
+ *	count and schedule disabling of clock.
+ */
+void mmc_host_clk_gate(struct mmc_host *host)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&host->clk_lock, flags);
+	host->clk_requests--;
+	if (mmc_host_may_gate_card(host->card) &&
+	    !host->clk_requests)
+		schedule_work(&host->clk_gate_work);
+	spin_unlock_irqrestore(&host->clk_lock, flags);
+}
+
+/**
+ *	mmc_host_clk_rate - get current clock frequency setting
+ *	@host: host to get the clock frequency for.
+ *
+ *	Returns current clock frequency regardless of gating.
+ */
+unsigned int mmc_host_clk_rate(struct mmc_host *host)
+{
+	unsigned long freq;
+	unsigned long flags;
+
+	spin_lock_irqsave(&host->clk_lock, flags);
+	if (host->clk_gated)
+		freq = host->clk_old;
+	else
+		freq = host->ios.clock;
+	spin_unlock_irqrestore(&host->clk_lock, flags);
+	return freq;
+}
+
+/**
+ *	mmc_host_clk_init - set up clock gating code
+ *	@host: host with potential clock to control
+ */
+static inline void mmc_host_clk_init(struct mmc_host *host)
+{
+	host->clk_requests = 0;
+	/* Hold MCI clock for 8 cycles by default */
+	host->clk_delay = 8;
+	host->clk_gated = false;
+	INIT_WORK(&host->clk_gate_work, mmc_host_clk_gate_work);
+	spin_lock_init(&host->clk_lock);
+	mutex_init(&host->clk_gate_mutex);
+}
+
+/**
+ *	mmc_host_clk_exit - shut down clock gating code
+ *	@host: host with potential clock to control
+ */
+static inline void mmc_host_clk_exit(struct mmc_host *host)
+{
+	/*
+	 * Wait for any outstanding gate and then make sure we're
+	 * ungated before exiting.
+	 */
+	if (cancel_work_sync(&host->clk_gate_work))
+		mmc_host_clk_gate_delayed(host);
+	if (host->clk_gated)
+		mmc_host_clk_ungate(host);
+	/* There should be only one user now */
+	WARN_ON(host->clk_requests > 1);
+}
+
+#else
+
+static inline void mmc_host_clk_init(struct mmc_host *host)
+{
+}
+
+static inline void mmc_host_clk_exit(struct mmc_host *host)
+{
+}
+
+#endif
+
 /**
  *	mmc_alloc_host - initialise the per-host structure.
  *	@extra: sizeof private data structure
@@ -82,6 +283,8 @@ struct mmc_host *mmc_alloc_host(int extr
 	host->class_dev.class = &mmc_host_class;
 	device_initialize(&host->class_dev);
 
+	mmc_host_clk_init(host);
+
 	spin_lock_init(&host->lock);
 	init_waitqueue_head(&host->wq);
 	INIT_DELAYED_WORK(&host->detect, mmc_rescan);
@@ -163,6 +366,8 @@ void mmc_remove_host(struct mmc_host *ho
 	device_del(&host->class_dev);
 
 	led_trigger_unregister_simple(host->led);
+
+	mmc_host_clk_exit(host);
 }
 
 EXPORT_SYMBOL(mmc_remove_host);
@@ -183,4 +388,3 @@ void mmc_free_host(struct mmc_host *host
 }
 
 EXPORT_SYMBOL(mmc_free_host);
-
diff -druNp linux-libre-2.6.37-gnu1/drivers/mmc/core/host.h linux-libre-2.6.38-gnu1/drivers/mmc/core/host.h
--- linux-libre-2.6.37-gnu1/drivers/mmc/core/host.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mmc/core/host.h	2011-03-14 21:20:32.000000000 -0400
@@ -10,10 +10,31 @@
  */
 #ifndef _MMC_CORE_HOST_H
 #define _MMC_CORE_HOST_H
+#include <linux/mmc/host.h>
 
 int mmc_register_host_class(void);
 void mmc_unregister_host_class(void);
 
+#ifdef CONFIG_MMC_CLKGATE
+void mmc_host_clk_ungate(struct mmc_host *host);
+void mmc_host_clk_gate(struct mmc_host *host);
+unsigned int mmc_host_clk_rate(struct mmc_host *host);
+
+#else
+static inline void mmc_host_clk_ungate(struct mmc_host *host)
+{
+}
+
+static inline void mmc_host_clk_gate(struct mmc_host *host)
+{
+}
+
+static inline unsigned int mmc_host_clk_rate(struct mmc_host *host)
+{
+	return host->ios.clock;
+}
+#endif
+
 void mmc_host_deeper_disable(struct work_struct *work);
 
 #endif
diff -druNp linux-libre-2.6.37-gnu1/drivers/mmc/core/Kconfig linux-libre-2.6.38-gnu1/drivers/mmc/core/Kconfig
--- linux-libre-2.6.37-gnu1/drivers/mmc/core/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mmc/core/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -16,3 +16,14 @@ config MMC_UNSAFE_RESUME
 
 	  This option sets a default which can be overridden by the
 	  module parameter "removable=0" or "removable=1".
+
+config MMC_CLKGATE
+	bool "MMC host clock gating (EXPERIMENTAL)"
+	depends on EXPERIMENTAL
+	help
+	  This will attempt to aggressively gate the clock to the MMC card.
+	  This is done to save power due to gating off the logic and bus
+	  noise when the MMC card is not in use. Your host driver has to
+	  support handling this in order for it to be of any use.
+
+	  If unsure, say N.
diff -druNp linux-libre-2.6.37-gnu1/drivers/mmc/core/mmc.c linux-libre-2.6.38-gnu1/drivers/mmc/core/mmc.c
--- linux-libre-2.6.37-gnu1/drivers/mmc/core/mmc.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mmc/core/mmc.c	2011-03-14 21:20:32.000000000 -0400
@@ -534,39 +534,57 @@ static int mmc_init_card(struct mmc_host
 	 */
 	if ((card->csd.mmca_vsn >= CSD_SPEC_VER_4) &&
 	    (host->caps & (MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA))) {
-		unsigned ext_csd_bit, bus_width;
+		static unsigned ext_csd_bits[][2] = {
+			{ EXT_CSD_BUS_WIDTH_8, EXT_CSD_DDR_BUS_WIDTH_8 },
+			{ EXT_CSD_BUS_WIDTH_4, EXT_CSD_DDR_BUS_WIDTH_4 },
+			{ EXT_CSD_BUS_WIDTH_1, EXT_CSD_BUS_WIDTH_1 },
+		};
+		static unsigned bus_widths[] = {
+			MMC_BUS_WIDTH_8,
+			MMC_BUS_WIDTH_4,
+			MMC_BUS_WIDTH_1
+		};
+		unsigned idx, bus_width = 0;
 
-		if (host->caps & MMC_CAP_8_BIT_DATA) {
-			if (ddr)
-				ext_csd_bit = EXT_CSD_DDR_BUS_WIDTH_8;
-			else
-				ext_csd_bit = EXT_CSD_BUS_WIDTH_8;
-			bus_width = MMC_BUS_WIDTH_8;
-		} else {
-			if (ddr)
-				ext_csd_bit = EXT_CSD_DDR_BUS_WIDTH_4;
-			else
-				ext_csd_bit = EXT_CSD_BUS_WIDTH_4;
-			bus_width = MMC_BUS_WIDTH_4;
+		if (host->caps & MMC_CAP_8_BIT_DATA)
+			idx = 0;
+		else
+			idx = 1;
+		for (; idx < ARRAY_SIZE(bus_widths); idx++) {
+			bus_width = bus_widths[idx];
+			if (bus_width == MMC_BUS_WIDTH_1)
+				ddr = 0; /* no DDR for 1-bit width */
+			err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+					 EXT_CSD_BUS_WIDTH,
+					 ext_csd_bits[idx][0]);
+			if (!err) {
+				mmc_set_bus_width_ddr(card->host,
+						      bus_width, MMC_SDR_MODE);
+				/*
+				 * If controller can't handle bus width test,
+				 * use the highest bus width to maintain
+				 * compatibility with previous MMC behavior.
+				 */
+				if (!(host->caps & MMC_CAP_BUS_WIDTH_TEST))
+					break;
+				err = mmc_bus_test(card, bus_width);
+				if (!err)
+					break;
+			}
 		}
 
-		err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
-				 EXT_CSD_BUS_WIDTH, ext_csd_bit);
-
-		if (err && err != -EBADMSG)
-			goto free_card;
-
+		if (!err && ddr) {
+			err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+					EXT_CSD_BUS_WIDTH,
+					ext_csd_bits[idx][1]);
+		}
 		if (err) {
 			printk(KERN_WARNING "%s: switch to bus width %d ddr %d "
-			       "failed\n", mmc_hostname(card->host),
-			       1 << bus_width, ddr);
-			err = 0;
-		} else {
-			if (ddr)
-				mmc_card_set_ddr_mode(card);
-			else
-				ddr = MMC_SDR_MODE;
-
+				"failed\n", mmc_hostname(card->host),
+				1 << bus_width, ddr);
+			goto free_card;
+		} else if (ddr) {
+			mmc_card_set_ddr_mode(card);
 			mmc_set_bus_width_ddr(card->host, bus_width, ddr);
 		}
 	}
@@ -737,14 +755,21 @@ static void mmc_attach_bus_ops(struct mm
 /*
  * Starting point for MMC card init.
  */
-int mmc_attach_mmc(struct mmc_host *host, u32 ocr)
+int mmc_attach_mmc(struct mmc_host *host)
 {
 	int err;
+	u32 ocr;
 
 	BUG_ON(!host);
 	WARN_ON(!host->claimed);
 
+	err = mmc_send_op_cond(host, 0, &ocr);
+	if (err)
+		return err;
+
 	mmc_attach_bus_ops(host);
+	if (host->ocr_avail_mmc)
+		host->ocr_avail = host->ocr_avail_mmc;
 
 	/*
 	 * We need to get OCR a different way for SPI.
@@ -784,20 +809,20 @@ int mmc_attach_mmc(struct mmc_host *host
 		goto err;
 
 	mmc_release_host(host);
-
 	err = mmc_add_card(host->card);
+	mmc_claim_host(host);
 	if (err)
 		goto remove_card;
 
 	return 0;
 
 remove_card:
+	mmc_release_host(host);
 	mmc_remove_card(host->card);
-	host->card = NULL;
 	mmc_claim_host(host);
+	host->card = NULL;
 err:
 	mmc_detach_bus(host);
-	mmc_release_host(host);
 
 	printk(KERN_ERR "%s: error %d whilst initialising MMC card\n",
 		mmc_hostname(host), err);
diff -druNp linux-libre-2.6.37-gnu1/drivers/mmc/core/mmc_ops.c linux-libre-2.6.38-gnu1/drivers/mmc/core/mmc_ops.c
--- linux-libre-2.6.37-gnu1/drivers/mmc/core/mmc_ops.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mmc/core/mmc_ops.c	2011-03-14 21:20:32.000000000 -0400
@@ -462,3 +462,104 @@ int mmc_send_status(struct mmc_card *car
 	return 0;
 }
 
+static int
+mmc_send_bus_test(struct mmc_card *card, struct mmc_host *host, u8 opcode,
+		  u8 len)
+{
+	struct mmc_request mrq;
+	struct mmc_command cmd;
+	struct mmc_data data;
+	struct scatterlist sg;
+	u8 *data_buf;
+	u8 *test_buf;
+	int i, err;
+	static u8 testdata_8bit[8] = { 0x55, 0xaa, 0, 0, 0, 0, 0, 0 };
+	static u8 testdata_4bit[4] = { 0x5a, 0, 0, 0 };
+
+	/* dma onto stack is unsafe/nonportable, but callers to this
+	 * routine normally provide temporary on-stack buffers ...
+	 */
+	data_buf = kmalloc(len, GFP_KERNEL);
+	if (!data_buf)
+		return -ENOMEM;
+
+	if (len == 8)
+		test_buf = testdata_8bit;
+	else if (len == 4)
+		test_buf = testdata_4bit;
+	else {
+		printk(KERN_ERR "%s: Invalid bus_width %d\n",
+		       mmc_hostname(host), len);
+		kfree(data_buf);
+		return -EINVAL;
+	}
+
+	if (opcode == MMC_BUS_TEST_W)
+		memcpy(data_buf, test_buf, len);
+
+	memset(&mrq, 0, sizeof(struct mmc_request));
+	memset(&cmd, 0, sizeof(struct mmc_command));
+	memset(&data, 0, sizeof(struct mmc_data));
+
+	mrq.cmd = &cmd;
+	mrq.data = &data;
+	cmd.opcode = opcode;
+	cmd.arg = 0;
+
+	/* NOTE HACK:  the MMC_RSP_SPI_R1 is always correct here, but we
+	 * rely on callers to never use this with "native" calls for reading
+	 * CSD or CID.  Native versions of those commands use the R2 type,
+	 * not R1 plus a data block.
+	 */
+	cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC;
+
+	data.blksz = len;
+	data.blocks = 1;
+	if (opcode == MMC_BUS_TEST_R)
+		data.flags = MMC_DATA_READ;
+	else
+		data.flags = MMC_DATA_WRITE;
+
+	data.sg = &sg;
+	data.sg_len = 1;
+	sg_init_one(&sg, data_buf, len);
+	mmc_wait_for_req(host, &mrq);
+	err = 0;
+	if (opcode == MMC_BUS_TEST_R) {
+		for (i = 0; i < len / 4; i++)
+			if ((test_buf[i] ^ data_buf[i]) != 0xff) {
+				err = -EIO;
+				break;
+			}
+	}
+	kfree(data_buf);
+
+	if (cmd.error)
+		return cmd.error;
+	if (data.error)
+		return data.error;
+
+	return err;
+}
+
+int mmc_bus_test(struct mmc_card *card, u8 bus_width)
+{
+	int err, width;
+
+	if (bus_width == MMC_BUS_WIDTH_8)
+		width = 8;
+	else if (bus_width == MMC_BUS_WIDTH_4)
+		width = 4;
+	else if (bus_width == MMC_BUS_WIDTH_1)
+		return 0; /* no need for test */
+	else
+		return -EINVAL;
+
+	/*
+	 * Ignore errors from BUS_TEST_W.  BUS_TEST_R will fail if there
+	 * is a problem.  This improves chances that the test will work.
+	 */
+	mmc_send_bus_test(card, card->host, MMC_BUS_TEST_W, width);
+	err = mmc_send_bus_test(card, card->host, MMC_BUS_TEST_R, width);
+	return err;
+}
diff -druNp linux-libre-2.6.37-gnu1/drivers/mmc/core/mmc_ops.h linux-libre-2.6.38-gnu1/drivers/mmc/core/mmc_ops.h
--- linux-libre-2.6.37-gnu1/drivers/mmc/core/mmc_ops.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mmc/core/mmc_ops.h	2011-03-14 21:20:32.000000000 -0400
@@ -26,6 +26,7 @@ int mmc_send_cid(struct mmc_host *host,
 int mmc_spi_read_ocr(struct mmc_host *host, int highcap, u32 *ocrp);
 int mmc_spi_set_crc(struct mmc_host *host, int use_crc);
 int mmc_card_sleepawake(struct mmc_host *host, int sleep);
+int mmc_bus_test(struct mmc_card *card, u8 bus_width);
 
 #endif
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/mmc/core/sd.c linux-libre-2.6.38-gnu1/drivers/mmc/core/sd.c
--- linux-libre-2.6.37-gnu1/drivers/mmc/core/sd.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mmc/core/sd.c	2011-03-14 21:20:32.000000000 -0400
@@ -764,14 +764,21 @@ static void mmc_sd_attach_bus_ops(struct
 /*
  * Starting point for SD card init.
  */
-int mmc_attach_sd(struct mmc_host *host, u32 ocr)
+int mmc_attach_sd(struct mmc_host *host)
 {
 	int err;
+	u32 ocr;
 
 	BUG_ON(!host);
 	WARN_ON(!host->claimed);
 
+	err = mmc_send_app_op_cond(host, 0, &ocr);
+	if (err)
+		return err;
+
 	mmc_sd_attach_bus_ops(host);
+	if (host->ocr_avail_sd)
+		host->ocr_avail = host->ocr_avail_sd;
 
 	/*
 	 * We need to get OCR a different way for SPI.
@@ -795,7 +802,8 @@ int mmc_attach_sd(struct mmc_host *host,
 		ocr &= ~0x7F;
 	}
 
-	if (ocr & MMC_VDD_165_195) {
+	if ((ocr & MMC_VDD_165_195) &&
+	    !(host->ocr_avail_sd & MMC_VDD_165_195)) {
 		printk(KERN_WARNING "%s: SD card claims to support the "
 		       "incompletely defined 'low voltage range'. This "
 		       "will be ignored.\n", mmc_hostname(host));
@@ -820,20 +828,20 @@ int mmc_attach_sd(struct mmc_host *host,
 		goto err;
 
 	mmc_release_host(host);
-
 	err = mmc_add_card(host->card);
+	mmc_claim_host(host);
 	if (err)
 		goto remove_card;
 
 	return 0;
 
 remove_card:
+	mmc_release_host(host);
 	mmc_remove_card(host->card);
 	host->card = NULL;
 	mmc_claim_host(host);
 err:
 	mmc_detach_bus(host);
-	mmc_release_host(host);
 
 	printk(KERN_ERR "%s: error %d whilst initialising SD card\n",
 		mmc_hostname(host), err);
diff -druNp linux-libre-2.6.37-gnu1/drivers/mmc/core/sdio_bus.c linux-libre-2.6.38-gnu1/drivers/mmc/core/sdio_bus.c
--- linux-libre-2.6.37-gnu1/drivers/mmc/core/sdio_bus.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mmc/core/sdio_bus.c	2011-03-14 21:20:32.000000000 -0400
@@ -197,44 +197,12 @@ out:
 
 #ifdef CONFIG_PM_RUNTIME
 
-static int sdio_bus_pm_prepare(struct device *dev)
-{
-	struct sdio_func *func = dev_to_sdio_func(dev);
-
-	/*
-	 * Resume an SDIO device which was suspended at run time at this
-	 * point, in order to allow standard SDIO suspend/resume paths
-	 * to keep working as usual.
-	 *
-	 * Ultimately, the SDIO driver itself will decide (in its
-	 * suspend handler, or lack thereof) whether the card should be
-	 * removed or kept, and if kept, at what power state.
-	 *
-	 * At this point, PM core have increased our use count, so it's
-	 * safe to directly resume the device. After system is resumed
-	 * again, PM core will drop back its runtime PM use count, and if
-	 * needed device will be suspended again.
-	 *
-	 * The end result is guaranteed to be a power state that is
-	 * coherent with the device's runtime PM use count.
-	 *
-	 * The return value of pm_runtime_resume is deliberately unchecked
-	 * since there is little point in failing system suspend if a
-	 * device can't be resumed.
-	 */
-	if (func->card->host->caps & MMC_CAP_POWER_OFF_CARD)
-		pm_runtime_resume(dev);
-
-	return 0;
-}
-
 static const struct dev_pm_ops sdio_bus_pm_ops = {
 	SET_RUNTIME_PM_OPS(
 		pm_generic_runtime_suspend,
 		pm_generic_runtime_resume,
 		pm_generic_runtime_idle
 	)
-	.prepare = sdio_bus_pm_prepare,
 };
 
 #define SDIO_PM_OPS_PTR	(&sdio_bus_pm_ops)
diff -druNp linux-libre-2.6.37-gnu1/drivers/mmc/core/sdio.c linux-libre-2.6.38-gnu1/drivers/mmc/core/sdio.c
--- linux-libre-2.6.37-gnu1/drivers/mmc/core/sdio.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mmc/core/sdio.c	2011-03-14 21:20:32.000000000 -0400
@@ -627,15 +627,27 @@ static int mmc_sdio_suspend(struct mmc_h
 
 static int mmc_sdio_resume(struct mmc_host *host)
 {
-	int i, err;
+	int i, err = 0;
 
 	BUG_ON(!host);
 	BUG_ON(!host->card);
 
 	/* Basic card reinitialization. */
 	mmc_claim_host(host);
-	err = mmc_sdio_init_card(host, host->ocr, host->card,
+
+	/* No need to reinitialize powered-resumed nonremovable cards */
+	if (mmc_card_is_removable(host) || !mmc_card_is_powered_resumed(host))
+		err = mmc_sdio_init_card(host, host->ocr, host->card,
 				 (host->pm_flags & MMC_PM_KEEP_POWER));
+	else if (mmc_card_is_powered_resumed(host)) {
+		/* We may have switched to 1-bit mode during suspend */
+		err = sdio_enable_4bit_bus(host->card);
+		if (err > 0) {
+			mmc_set_bus_width(host, MMC_BUS_WIDTH_4);
+			err = 0;
+		}
+	}
+
 	if (!err && host->sdio_irqs)
 		mmc_signal_sdio_irq(host);
 	mmc_release_host(host);
@@ -690,16 +702,22 @@ static const struct mmc_bus_ops mmc_sdio
 /*
  * Starting point for SDIO card init.
  */
-int mmc_attach_sdio(struct mmc_host *host, u32 ocr)
+int mmc_attach_sdio(struct mmc_host *host)
 {
-	int err;
-	int i, funcs;
+	int err, i, funcs;
+	u32 ocr;
 	struct mmc_card *card;
 
 	BUG_ON(!host);
 	WARN_ON(!host->claimed);
 
+	err = mmc_send_io_op_cond(host, 0, &ocr);
+	if (err)
+		return err;
+
 	mmc_attach_bus(host, &mmc_sdio_ops);
+	if (host->ocr_avail_sdio)
+		host->ocr_avail = host->ocr_avail_sdio;
 
 	/*
 	 * Sanity check the voltages that the card claims to
@@ -769,11 +787,10 @@ int mmc_attach_sdio(struct mmc_host *hos
 			pm_runtime_enable(&card->sdio_func[i]->dev);
 	}
 
-	mmc_release_host(host);
-
 	/*
 	 * First add the card to the driver model...
 	 */
+	mmc_release_host(host);
 	err = mmc_add_card(host->card);
 	if (err)
 		goto remove_added;
@@ -787,6 +804,7 @@ int mmc_attach_sdio(struct mmc_host *hos
 			goto remove_added;
 	}
 
+	mmc_claim_host(host);
 	return 0;
 
 
@@ -796,11 +814,12 @@ remove_added:
 	mmc_claim_host(host);
 remove:
 	/* And with lock if it hasn't been added. */
+	mmc_release_host(host);
 	if (host->card)
 		mmc_sdio_remove(host);
+	mmc_claim_host(host);
 err:
 	mmc_detach_bus(host);
-	mmc_release_host(host);
 
 	printk(KERN_ERR "%s: error %d whilst initialising SDIO card\n",
 		mmc_hostname(host), err);
diff -druNp linux-libre-2.6.37-gnu1/drivers/mmc/host/au1xmmc.c linux-libre-2.6.38-gnu1/drivers/mmc/host/au1xmmc.c
--- linux-libre-2.6.37-gnu1/drivers/mmc/host/au1xmmc.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mmc/host/au1xmmc.c	2011-03-14 21:20:32.000000000 -0400
@@ -192,7 +192,7 @@ static inline void SEND_STOP(struct au1x
 	au_writel(config2 | SD_CONFIG2_DF, HOST_CONFIG2(host));
 	au_sync();
 
-	/* Send the stop commmand */
+	/* Send the stop command */
 	au_writel(STOP_CMD, HOST_CMD(host));
 }
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/mmc/host/bfin_sdh.c linux-libre-2.6.38-gnu1/drivers/mmc/host/bfin_sdh.c
--- linux-libre-2.6.37-gnu1/drivers/mmc/host/bfin_sdh.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mmc/host/bfin_sdh.c	2011-03-14 21:20:32.000000000 -0400
@@ -462,7 +462,7 @@ static int __devinit sdh_probe(struct pl
 		goto out;
 	}
 
-	mmc = mmc_alloc_host(sizeof(*mmc), &pdev->dev);
+	mmc = mmc_alloc_host(sizeof(struct sdh_host), &pdev->dev);
 	if (!mmc) {
 		ret = -ENOMEM;
 		goto out;
diff -druNp linux-libre-2.6.37-gnu1/drivers/mmc/host/davinci_mmc.c linux-libre-2.6.38-gnu1/drivers/mmc/host/davinci_mmc.c
--- linux-libre-2.6.37-gnu1/drivers/mmc/host/davinci_mmc.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mmc/host/davinci_mmc.c	2011-03-14 21:20:32.000000000 -0400
@@ -66,8 +66,8 @@
 #define DAVINCI_MMCBLNC      0x60
 #define DAVINCI_SDIOCTL      0x64
 #define DAVINCI_SDIOST0      0x68
-#define DAVINCI_SDIOEN       0x6C
-#define DAVINCI_SDIOST       0x70
+#define DAVINCI_SDIOIEN      0x6C
+#define DAVINCI_SDIOIST      0x70
 #define DAVINCI_MMCFIFOCTL   0x74 /* FIFO Control Register             */
 
 /* DAVINCI_MMCCTL definitions */
@@ -131,6 +131,14 @@
 #define MMCFIFOCTL_ACCWD_2    (2 << 3) /* access width of 2 bytes    */
 #define MMCFIFOCTL_ACCWD_1    (3 << 3) /* access width of 1 byte     */
 
+/* DAVINCI_SDIOST0 definitions */
+#define SDIOST0_DAT1_HI       BIT(0)
+
+/* DAVINCI_SDIOIEN definitions */
+#define SDIOIEN_IOINTEN       BIT(0)
+
+/* DAVINCI_SDIOIST definitions */
+#define SDIOIST_IOINT         BIT(0)
 
 /* MMCSD Init clock in Hz in opendrain mode */
 #define MMCSD_INIT_CLOCK		200000
@@ -164,7 +172,7 @@ struct mmc_davinci_host {
 	unsigned int mmc_input_clk;
 	void __iomem *base;
 	struct resource *mem_res;
-	int irq;
+	int mmc_irq, sdio_irq;
 	unsigned char bus_mode;
 
 #define DAVINCI_MMC_DATADIR_NONE	0
@@ -184,6 +192,7 @@ struct mmc_davinci_host {
 	u32 rxdma, txdma;
 	bool use_dma;
 	bool do_dma;
+	bool sdio_int;
 
 	/* Scatterlist DMA uses one or more parameter RAM entries:
 	 * the main one (associated with rxdma or txdma) plus zero or
@@ -480,7 +489,7 @@ static void mmc_davinci_send_dma_request
 	struct scatterlist	*sg;
 	unsigned		sg_len;
 	unsigned		bytes_left = host->bytes_left;
-	const unsigned		shift = ffs(rw_threshold) - 1;;
+	const unsigned		shift = ffs(rw_threshold) - 1;
 
 	if (host->data_dir == DAVINCI_MMC_DATADIR_WRITE) {
 		template = &host->tx_template;
@@ -866,6 +875,19 @@ mmc_davinci_xfer_done(struct mmc_davinci
 {
 	host->data = NULL;
 
+	if (host->mmc->caps & MMC_CAP_SDIO_IRQ) {
+		/*
+		 * SDIO Interrupt Detection work-around as suggested by
+		 * Davinci Errata (TMS320DM355 Silicon Revision 1.1 Errata
+		 * 2.1.6): Signal SDIO interrupt only if it is enabled by core
+		 */
+		if (host->sdio_int && !(readl(host->base + DAVINCI_SDIOST0) &
+					SDIOST0_DAT1_HI)) {
+			writel(SDIOIST_IOINT, host->base + DAVINCI_SDIOIST);
+			mmc_signal_sdio_irq(host->mmc);
+		}
+	}
+
 	if (host->do_dma) {
 		davinci_abort_dma(host);
 
@@ -932,6 +954,21 @@ davinci_abort_data(struct mmc_davinci_ho
 	mmc_davinci_reset_ctrl(host, 0);
 }
 
+static irqreturn_t mmc_davinci_sdio_irq(int irq, void *dev_id)
+{
+	struct mmc_davinci_host *host = dev_id;
+	unsigned int status;
+
+	status = readl(host->base + DAVINCI_SDIOIST);
+	if (status & SDIOIST_IOINT) {
+		dev_dbg(mmc_dev(host->mmc),
+			"SDIO interrupt status %x\n", status);
+		writel(status | SDIOIST_IOINT, host->base + DAVINCI_SDIOIST);
+		mmc_signal_sdio_irq(host->mmc);
+	}
+	return IRQ_HANDLED;
+}
+
 static irqreturn_t mmc_davinci_irq(int irq, void *dev_id)
 {
 	struct mmc_davinci_host *host = (struct mmc_davinci_host *)dev_id;
@@ -1076,11 +1113,32 @@ static int mmc_davinci_get_ro(struct mmc
 	return config->get_ro(pdev->id);
 }
 
+static void mmc_davinci_enable_sdio_irq(struct mmc_host *mmc, int enable)
+{
+	struct mmc_davinci_host *host = mmc_priv(mmc);
+
+	if (enable) {
+		if (!(readl(host->base + DAVINCI_SDIOST0) & SDIOST0_DAT1_HI)) {
+			writel(SDIOIST_IOINT, host->base + DAVINCI_SDIOIST);
+			mmc_signal_sdio_irq(host->mmc);
+		} else {
+			host->sdio_int = true;
+			writel(readl(host->base + DAVINCI_SDIOIEN) |
+			       SDIOIEN_IOINTEN, host->base + DAVINCI_SDIOIEN);
+		}
+	} else {
+		host->sdio_int = false;
+		writel(readl(host->base + DAVINCI_SDIOIEN) & ~SDIOIEN_IOINTEN,
+		       host->base + DAVINCI_SDIOIEN);
+	}
+}
+
 static struct mmc_host_ops mmc_davinci_ops = {
 	.request	= mmc_davinci_request,
 	.set_ios	= mmc_davinci_set_ios,
 	.get_cd		= mmc_davinci_get_cd,
 	.get_ro		= mmc_davinci_get_ro,
+	.enable_sdio_irq = mmc_davinci_enable_sdio_irq,
 };
 
 /*----------------------------------------------------------------------*/
@@ -1209,7 +1267,8 @@ static int __init davinci_mmcsd_probe(st
 		host->nr_sg = MAX_NR_SG;
 
 	host->use_dma = use_dma;
-	host->irq = irq;
+	host->mmc_irq = irq;
+	host->sdio_irq = platform_get_irq(pdev, 1);
 
 	if (host->use_dma && davinci_acquire_dma_channels(host) != 0)
 		host->use_dma = 0;
@@ -1270,6 +1329,13 @@ static int __init davinci_mmcsd_probe(st
 	if (ret)
 		goto out;
 
+	if (host->sdio_irq >= 0) {
+		ret = request_irq(host->sdio_irq, mmc_davinci_sdio_irq, 0,
+				  mmc_hostname(mmc), host);
+		if (!ret)
+			mmc->caps |= MMC_CAP_SDIO_IRQ;
+	}
+
 	rename_region(mem, mmc_hostname(mmc));
 
 	dev_info(mmc_dev(host->mmc), "Using %s, %d-bit mode\n",
@@ -1313,7 +1379,9 @@ static int __exit davinci_mmcsd_remove(s
 		mmc_davinci_cpufreq_deregister(host);
 
 		mmc_remove_host(host->mmc);
-		free_irq(host->irq, host);
+		free_irq(host->mmc_irq, host);
+		if (host->mmc->caps & MMC_CAP_SDIO_IRQ)
+			free_irq(host->sdio_irq, host);
 
 		davinci_release_dma_channels(host);
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/mmc/host/dw_mmc.c linux-libre-2.6.38-gnu1/drivers/mmc/host/dw_mmc.c
--- linux-libre-2.6.37-gnu1/drivers/mmc/host/dw_mmc.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mmc/host/dw_mmc.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,1796 @@
+/*
+ * Synopsys DesignWare Multimedia Card Interface driver
+ *  (Based on NXP driver for lpc 31xx)
+ *
+ * Copyright (C) 2009 NXP Semiconductors
+ * Copyright (C) 2009, 2010 Imagination Technologies 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.
+ */
+
+#include <linux/blkdev.h>
+#include <linux/clk.h>
+#include <linux/debugfs.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/scatterlist.h>
+#include <linux/seq_file.h>
+#include <linux/slab.h>
+#include <linux/stat.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/mmc.h>
+#include <linux/mmc/dw_mmc.h>
+#include <linux/bitops.h>
+
+#include "dw_mmc.h"
+
+/* Common flag combinations */
+#define DW_MCI_DATA_ERROR_FLAGS	(SDMMC_INT_DTO | SDMMC_INT_DCRC | \
+				 SDMMC_INT_HTO | SDMMC_INT_SBE  | \
+				 SDMMC_INT_EBE)
+#define DW_MCI_CMD_ERROR_FLAGS	(SDMMC_INT_RTO | SDMMC_INT_RCRC | \
+				 SDMMC_INT_RESP_ERR)
+#define DW_MCI_ERROR_FLAGS	(DW_MCI_DATA_ERROR_FLAGS | \
+				 DW_MCI_CMD_ERROR_FLAGS  | SDMMC_INT_HLE)
+#define DW_MCI_SEND_STATUS	1
+#define DW_MCI_RECV_STATUS	2
+#define DW_MCI_DMA_THRESHOLD	16
+
+#ifdef CONFIG_MMC_DW_IDMAC
+struct idmac_desc {
+	u32		des0;	/* Control Descriptor */
+#define IDMAC_DES0_DIC	BIT(1)
+#define IDMAC_DES0_LD	BIT(2)
+#define IDMAC_DES0_FD	BIT(3)
+#define IDMAC_DES0_CH	BIT(4)
+#define IDMAC_DES0_ER	BIT(5)
+#define IDMAC_DES0_CES	BIT(30)
+#define IDMAC_DES0_OWN	BIT(31)
+
+	u32		des1;	/* Buffer sizes */
+#define IDMAC_SET_BUFFER1_SIZE(d, s) \
+	((d)->des1 = ((d)->des1 & 0x03ffc000) | ((s) & 0x3fff))
+
+	u32		des2;	/* buffer 1 physical address */
+
+	u32		des3;	/* buffer 2 physical address */
+};
+#endif /* CONFIG_MMC_DW_IDMAC */
+
+/**
+ * struct dw_mci_slot - MMC slot state
+ * @mmc: The mmc_host representing this slot.
+ * @host: The MMC controller this slot is using.
+ * @ctype: Card type for this slot.
+ * @mrq: mmc_request currently being processed or waiting to be
+ *	processed, or NULL when the slot is idle.
+ * @queue_node: List node for placing this node in the @queue list of
+ *	&struct dw_mci.
+ * @clock: Clock rate configured by set_ios(). Protected by host->lock.
+ * @flags: Random state bits associated with the slot.
+ * @id: Number of this slot.
+ * @last_detect_state: Most recently observed card detect state.
+ */
+struct dw_mci_slot {
+	struct mmc_host		*mmc;
+	struct dw_mci		*host;
+
+	u32			ctype;
+
+	struct mmc_request	*mrq;
+	struct list_head	queue_node;
+
+	unsigned int		clock;
+	unsigned long		flags;
+#define DW_MMC_CARD_PRESENT	0
+#define DW_MMC_CARD_NEED_INIT	1
+	int			id;
+	int			last_detect_state;
+};
+
+#if defined(CONFIG_DEBUG_FS)
+static int dw_mci_req_show(struct seq_file *s, void *v)
+{
+	struct dw_mci_slot *slot = s->private;
+	struct mmc_request *mrq;
+	struct mmc_command *cmd;
+	struct mmc_command *stop;
+	struct mmc_data	*data;
+
+	/* Make sure we get a consistent snapshot */
+	spin_lock_bh(&slot->host->lock);
+	mrq = slot->mrq;
+
+	if (mrq) {
+		cmd = mrq->cmd;
+		data = mrq->data;
+		stop = mrq->stop;
+
+		if (cmd)
+			seq_printf(s,
+				   "CMD%u(0x%x) flg %x rsp %x %x %x %x err %d\n",
+				   cmd->opcode, cmd->arg, cmd->flags,
+				   cmd->resp[0], cmd->resp[1], cmd->resp[2],
+				   cmd->resp[2], cmd->error);
+		if (data)
+			seq_printf(s, "DATA %u / %u * %u flg %x err %d\n",
+				   data->bytes_xfered, data->blocks,
+				   data->blksz, data->flags, data->error);
+		if (stop)
+			seq_printf(s,
+				   "CMD%u(0x%x) flg %x rsp %x %x %x %x err %d\n",
+				   stop->opcode, stop->arg, stop->flags,
+				   stop->resp[0], stop->resp[1], stop->resp[2],
+				   stop->resp[2], stop->error);
+	}
+
+	spin_unlock_bh(&slot->host->lock);
+
+	return 0;
+}
+
+static int dw_mci_req_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, dw_mci_req_show, inode->i_private);
+}
+
+static const struct file_operations dw_mci_req_fops = {
+	.owner		= THIS_MODULE,
+	.open		= dw_mci_req_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+static int dw_mci_regs_show(struct seq_file *s, void *v)
+{
+	seq_printf(s, "STATUS:\t0x%08x\n", SDMMC_STATUS);
+	seq_printf(s, "RINTSTS:\t0x%08x\n", SDMMC_RINTSTS);
+	seq_printf(s, "CMD:\t0x%08x\n", SDMMC_CMD);
+	seq_printf(s, "CTRL:\t0x%08x\n", SDMMC_CTRL);
+	seq_printf(s, "INTMASK:\t0x%08x\n", SDMMC_INTMASK);
+	seq_printf(s, "CLKENA:\t0x%08x\n", SDMMC_CLKENA);
+
+	return 0;
+}
+
+static int dw_mci_regs_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, dw_mci_regs_show, inode->i_private);
+}
+
+static const struct file_operations dw_mci_regs_fops = {
+	.owner		= THIS_MODULE,
+	.open		= dw_mci_regs_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+static void dw_mci_init_debugfs(struct dw_mci_slot *slot)
+{
+	struct mmc_host	*mmc = slot->mmc;
+	struct dw_mci *host = slot->host;
+	struct dentry *root;
+	struct dentry *node;
+
+	root = mmc->debugfs_root;
+	if (!root)
+		return;
+
+	node = debugfs_create_file("regs", S_IRUSR, root, host,
+				   &dw_mci_regs_fops);
+	if (!node)
+		goto err;
+
+	node = debugfs_create_file("req", S_IRUSR, root, slot,
+				   &dw_mci_req_fops);
+	if (!node)
+		goto err;
+
+	node = debugfs_create_u32("state", S_IRUSR, root, (u32 *)&host->state);
+	if (!node)
+		goto err;
+
+	node = debugfs_create_x32("pending_events", S_IRUSR, root,
+				  (u32 *)&host->pending_events);
+	if (!node)
+		goto err;
+
+	node = debugfs_create_x32("completed_events", S_IRUSR, root,
+				  (u32 *)&host->completed_events);
+	if (!node)
+		goto err;
+
+	return;
+
+err:
+	dev_err(&mmc->class_dev, "failed to initialize debugfs for slot\n");
+}
+#endif /* defined(CONFIG_DEBUG_FS) */
+
+static void dw_mci_set_timeout(struct dw_mci *host)
+{
+	/* timeout (maximum) */
+	mci_writel(host, TMOUT, 0xffffffff);
+}
+
+static u32 dw_mci_prepare_command(struct mmc_host *mmc, struct mmc_command *cmd)
+{
+	struct mmc_data	*data;
+	u32 cmdr;
+	cmd->error = -EINPROGRESS;
+
+	cmdr = cmd->opcode;
+
+	if (cmdr == MMC_STOP_TRANSMISSION)
+		cmdr |= SDMMC_CMD_STOP;
+	else
+		cmdr |= SDMMC_CMD_PRV_DAT_WAIT;
+
+	if (cmd->flags & MMC_RSP_PRESENT) {
+		/* We expect a response, so set this bit */
+		cmdr |= SDMMC_CMD_RESP_EXP;
+		if (cmd->flags & MMC_RSP_136)
+			cmdr |= SDMMC_CMD_RESP_LONG;
+	}
+
+	if (cmd->flags & MMC_RSP_CRC)
+		cmdr |= SDMMC_CMD_RESP_CRC;
+
+	data = cmd->data;
+	if (data) {
+		cmdr |= SDMMC_CMD_DAT_EXP;
+		if (data->flags & MMC_DATA_STREAM)
+			cmdr |= SDMMC_CMD_STRM_MODE;
+		if (data->flags & MMC_DATA_WRITE)
+			cmdr |= SDMMC_CMD_DAT_WR;
+	}
+
+	return cmdr;
+}
+
+static void dw_mci_start_command(struct dw_mci *host,
+				 struct mmc_command *cmd, u32 cmd_flags)
+{
+	host->cmd = cmd;
+	dev_vdbg(&host->pdev->dev,
+		 "start command: ARGR=0x%08x CMDR=0x%08x\n",
+		 cmd->arg, cmd_flags);
+
+	mci_writel(host, CMDARG, cmd->arg);
+	wmb();
+
+	mci_writel(host, CMD, cmd_flags | SDMMC_CMD_START);
+}
+
+static void send_stop_cmd(struct dw_mci *host, struct mmc_data *data)
+{
+	dw_mci_start_command(host, data->stop, host->stop_cmdr);
+}
+
+/* DMA interface functions */
+static void dw_mci_stop_dma(struct dw_mci *host)
+{
+	if (host->use_dma) {
+		host->dma_ops->stop(host);
+		host->dma_ops->cleanup(host);
+	} else {
+		/* Data transfer was stopped by the interrupt handler */
+		set_bit(EVENT_XFER_COMPLETE, &host->pending_events);
+	}
+}
+
+#ifdef CONFIG_MMC_DW_IDMAC
+static void dw_mci_dma_cleanup(struct dw_mci *host)
+{
+	struct mmc_data *data = host->data;
+
+	if (data)
+		dma_unmap_sg(&host->pdev->dev, data->sg, data->sg_len,
+			     ((data->flags & MMC_DATA_WRITE)
+			      ? DMA_TO_DEVICE : DMA_FROM_DEVICE));
+}
+
+static void dw_mci_idmac_stop_dma(struct dw_mci *host)
+{
+	u32 temp;
+
+	/* Disable and reset the IDMAC interface */
+	temp = mci_readl(host, CTRL);
+	temp &= ~SDMMC_CTRL_USE_IDMAC;
+	temp |= SDMMC_CTRL_DMA_RESET;
+	mci_writel(host, CTRL, temp);
+
+	/* Stop the IDMAC running */
+	temp = mci_readl(host, BMOD);
+	temp &= ~SDMMC_IDMAC_ENABLE;
+	mci_writel(host, BMOD, temp);
+}
+
+static void dw_mci_idmac_complete_dma(struct dw_mci *host)
+{
+	struct mmc_data *data = host->data;
+
+	dev_vdbg(&host->pdev->dev, "DMA complete\n");
+
+	host->dma_ops->cleanup(host);
+
+	/*
+	 * If the card was removed, data will be NULL. No point in trying to
+	 * send the stop command or waiting for NBUSY in this case.
+	 */
+	if (data) {
+		set_bit(EVENT_XFER_COMPLETE, &host->pending_events);
+		tasklet_schedule(&host->tasklet);
+	}
+}
+
+static void dw_mci_translate_sglist(struct dw_mci *host, struct mmc_data *data,
+				    unsigned int sg_len)
+{
+	int i;
+	struct idmac_desc *desc = host->sg_cpu;
+
+	for (i = 0; i < sg_len; i++, desc++) {
+		unsigned int length = sg_dma_len(&data->sg[i]);
+		u32 mem_addr = sg_dma_address(&data->sg[i]);
+
+		/* Set the OWN bit and disable interrupts for this descriptor */
+		desc->des0 = IDMAC_DES0_OWN | IDMAC_DES0_DIC | IDMAC_DES0_CH;
+
+		/* Buffer length */
+		IDMAC_SET_BUFFER1_SIZE(desc, length);
+
+		/* Physical address to DMA to/from */
+		desc->des2 = mem_addr;
+	}
+
+	/* Set first descriptor */
+	desc = host->sg_cpu;
+	desc->des0 |= IDMAC_DES0_FD;
+
+	/* Set last descriptor */
+	desc = host->sg_cpu + (i - 1) * sizeof(struct idmac_desc);
+	desc->des0 &= ~(IDMAC_DES0_CH | IDMAC_DES0_DIC);
+	desc->des0 |= IDMAC_DES0_LD;
+
+	wmb();
+}
+
+static void dw_mci_idmac_start_dma(struct dw_mci *host, unsigned int sg_len)
+{
+	u32 temp;
+
+	dw_mci_translate_sglist(host, host->data, sg_len);
+
+	/* Select IDMAC interface */
+	temp = mci_readl(host, CTRL);
+	temp |= SDMMC_CTRL_USE_IDMAC;
+	mci_writel(host, CTRL, temp);
+
+	wmb();
+
+	/* Enable the IDMAC */
+	temp = mci_readl(host, BMOD);
+	temp |= SDMMC_IDMAC_ENABLE;
+	mci_writel(host, BMOD, temp);
+
+	/* Start it running */
+	mci_writel(host, PLDMND, 1);
+}
+
+static int dw_mci_idmac_init(struct dw_mci *host)
+{
+	struct idmac_desc *p;
+	int i;
+
+	/* Number of descriptors in the ring buffer */
+	host->ring_size = PAGE_SIZE / sizeof(struct idmac_desc);
+
+	/* Forward link the descriptor list */
+	for (i = 0, p = host->sg_cpu; i < host->ring_size - 1; i++, p++)
+		p->des3 = host->sg_dma + (sizeof(struct idmac_desc) * (i + 1));
+
+	/* Set the last descriptor as the end-of-ring descriptor */
+	p->des3 = host->sg_dma;
+	p->des0 = IDMAC_DES0_ER;
+
+	/* Mask out interrupts - get Tx & Rx complete only */
+	mci_writel(host, IDINTEN, SDMMC_IDMAC_INT_NI | SDMMC_IDMAC_INT_RI |
+		   SDMMC_IDMAC_INT_TI);
+
+	/* Set the descriptor base address */
+	mci_writel(host, DBADDR, host->sg_dma);
+	return 0;
+}
+
+static struct dw_mci_dma_ops dw_mci_idmac_ops = {
+	.init = dw_mci_idmac_init,
+	.start = dw_mci_idmac_start_dma,
+	.stop = dw_mci_idmac_stop_dma,
+	.complete = dw_mci_idmac_complete_dma,
+	.cleanup = dw_mci_dma_cleanup,
+};
+#endif /* CONFIG_MMC_DW_IDMAC */
+
+static int dw_mci_submit_data_dma(struct dw_mci *host, struct mmc_data *data)
+{
+	struct scatterlist *sg;
+	unsigned int i, direction, sg_len;
+	u32 temp;
+
+	/* If we don't have a channel, we can't do DMA */
+	if (!host->use_dma)
+		return -ENODEV;
+
+	/*
+	 * We don't do DMA on "complex" transfers, i.e. with
+	 * non-word-aligned buffers or lengths. Also, we don't bother
+	 * with all the DMA setup overhead for short transfers.
+	 */
+	if (data->blocks * data->blksz < DW_MCI_DMA_THRESHOLD)
+		return -EINVAL;
+	if (data->blksz & 3)
+		return -EINVAL;
+
+	for_each_sg(data->sg, sg, data->sg_len, i) {
+		if (sg->offset & 3 || sg->length & 3)
+			return -EINVAL;
+	}
+
+	if (data->flags & MMC_DATA_READ)
+		direction = DMA_FROM_DEVICE;
+	else
+		direction = DMA_TO_DEVICE;
+
+	sg_len = dma_map_sg(&host->pdev->dev, data->sg, data->sg_len,
+			    direction);
+
+	dev_vdbg(&host->pdev->dev,
+		 "sd sg_cpu: %#lx sg_dma: %#lx sg_len: %d\n",
+		 (unsigned long)host->sg_cpu, (unsigned long)host->sg_dma,
+		 sg_len);
+
+	/* Enable the DMA interface */
+	temp = mci_readl(host, CTRL);
+	temp |= SDMMC_CTRL_DMA_ENABLE;
+	mci_writel(host, CTRL, temp);
+
+	/* Disable RX/TX IRQs, let DMA handle it */
+	temp = mci_readl(host, INTMASK);
+	temp  &= ~(SDMMC_INT_RXDR | SDMMC_INT_TXDR);
+	mci_writel(host, INTMASK, temp);
+
+	host->dma_ops->start(host, sg_len);
+
+	return 0;
+}
+
+static void dw_mci_submit_data(struct dw_mci *host, struct mmc_data *data)
+{
+	u32 temp;
+
+	data->error = -EINPROGRESS;
+
+	WARN_ON(host->data);
+	host->sg = NULL;
+	host->data = data;
+
+	if (dw_mci_submit_data_dma(host, data)) {
+		host->sg = data->sg;
+		host->pio_offset = 0;
+		if (data->flags & MMC_DATA_READ)
+			host->dir_status = DW_MCI_RECV_STATUS;
+		else
+			host->dir_status = DW_MCI_SEND_STATUS;
+
+		temp = mci_readl(host, INTMASK);
+		temp |= SDMMC_INT_TXDR | SDMMC_INT_RXDR;
+		mci_writel(host, INTMASK, temp);
+
+		temp = mci_readl(host, CTRL);
+		temp &= ~SDMMC_CTRL_DMA_ENABLE;
+		mci_writel(host, CTRL, temp);
+	}
+}
+
+static void mci_send_cmd(struct dw_mci_slot *slot, u32 cmd, u32 arg)
+{
+	struct dw_mci *host = slot->host;
+	unsigned long timeout = jiffies + msecs_to_jiffies(500);
+	unsigned int cmd_status = 0;
+
+	mci_writel(host, CMDARG, arg);
+	wmb();
+	mci_writel(host, CMD, SDMMC_CMD_START | cmd);
+
+	while (time_before(jiffies, timeout)) {
+		cmd_status = mci_readl(host, CMD);
+		if (!(cmd_status & SDMMC_CMD_START))
+			return;
+	}
+	dev_err(&slot->mmc->class_dev,
+		"Timeout sending command (cmd %#x arg %#x status %#x)\n",
+		cmd, arg, cmd_status);
+}
+
+static void dw_mci_setup_bus(struct dw_mci_slot *slot)
+{
+	struct dw_mci *host = slot->host;
+	u32 div;
+
+	if (slot->clock != host->current_speed) {
+		if (host->bus_hz % slot->clock)
+			/*
+			 * move the + 1 after the divide to prevent
+			 * over-clocking the card.
+			 */
+			div = ((host->bus_hz / slot->clock) >> 1) + 1;
+		else
+			div = (host->bus_hz  / slot->clock) >> 1;
+
+		dev_info(&slot->mmc->class_dev,
+			 "Bus speed (slot %d) = %dHz (slot req %dHz, actual %dHZ"
+			 " div = %d)\n", slot->id, host->bus_hz, slot->clock,
+			 div ? ((host->bus_hz / div) >> 1) : host->bus_hz, div);
+
+		/* disable clock */
+		mci_writel(host, CLKENA, 0);
+		mci_writel(host, CLKSRC, 0);
+
+		/* inform CIU */
+		mci_send_cmd(slot,
+			     SDMMC_CMD_UPD_CLK | SDMMC_CMD_PRV_DAT_WAIT, 0);
+
+		/* set clock to desired speed */
+		mci_writel(host, CLKDIV, div);
+
+		/* inform CIU */
+		mci_send_cmd(slot,
+			     SDMMC_CMD_UPD_CLK | SDMMC_CMD_PRV_DAT_WAIT, 0);
+
+		/* enable clock */
+		mci_writel(host, CLKENA, SDMMC_CLKEN_ENABLE);
+
+		/* inform CIU */
+		mci_send_cmd(slot,
+			     SDMMC_CMD_UPD_CLK | SDMMC_CMD_PRV_DAT_WAIT, 0);
+
+		host->current_speed = slot->clock;
+	}
+
+	/* Set the current slot bus width */
+	mci_writel(host, CTYPE, slot->ctype);
+}
+
+static void dw_mci_start_request(struct dw_mci *host,
+				 struct dw_mci_slot *slot)
+{
+	struct mmc_request *mrq;
+	struct mmc_command *cmd;
+	struct mmc_data	*data;
+	u32 cmdflags;
+
+	mrq = slot->mrq;
+	if (host->pdata->select_slot)
+		host->pdata->select_slot(slot->id);
+
+	/* Slot specific timing and width adjustment */
+	dw_mci_setup_bus(slot);
+
+	host->cur_slot = slot;
+	host->mrq = mrq;
+
+	host->pending_events = 0;
+	host->completed_events = 0;
+	host->data_status = 0;
+
+	data = mrq->data;
+	if (data) {
+		dw_mci_set_timeout(host);
+		mci_writel(host, BYTCNT, data->blksz*data->blocks);
+		mci_writel(host, BLKSIZ, data->blksz);
+	}
+
+	cmd = mrq->cmd;
+	cmdflags = dw_mci_prepare_command(slot->mmc, cmd);
+
+	/* this is the first command, send the initialization clock */
+	if (test_and_clear_bit(DW_MMC_CARD_NEED_INIT, &slot->flags))
+		cmdflags |= SDMMC_CMD_INIT;
+
+	if (data) {
+		dw_mci_submit_data(host, data);
+		wmb();
+	}
+
+	dw_mci_start_command(host, cmd, cmdflags);
+
+	if (mrq->stop)
+		host->stop_cmdr = dw_mci_prepare_command(slot->mmc, mrq->stop);
+}
+
+static void dw_mci_queue_request(struct dw_mci *host, struct dw_mci_slot *slot,
+				 struct mmc_request *mrq)
+{
+	dev_vdbg(&slot->mmc->class_dev, "queue request: state=%d\n",
+		 host->state);
+
+	spin_lock_bh(&host->lock);
+	slot->mrq = mrq;
+
+	if (host->state == STATE_IDLE) {
+		host->state = STATE_SENDING_CMD;
+		dw_mci_start_request(host, slot);
+	} else {
+		list_add_tail(&slot->queue_node, &host->queue);
+	}
+
+	spin_unlock_bh(&host->lock);
+}
+
+static void dw_mci_request(struct mmc_host *mmc, struct mmc_request *mrq)
+{
+	struct dw_mci_slot *slot = mmc_priv(mmc);
+	struct dw_mci *host = slot->host;
+
+	WARN_ON(slot->mrq);
+
+	if (!test_bit(DW_MMC_CARD_PRESENT, &slot->flags)) {
+		mrq->cmd->error = -ENOMEDIUM;
+		mmc_request_done(mmc, mrq);
+		return;
+	}
+
+	/* We don't support multiple blocks of weird lengths. */
+	dw_mci_queue_request(host, slot, mrq);
+}
+
+static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
+{
+	struct dw_mci_slot *slot = mmc_priv(mmc);
+
+	/* set default 1 bit mode */
+	slot->ctype = SDMMC_CTYPE_1BIT;
+
+	switch (ios->bus_width) {
+	case MMC_BUS_WIDTH_1:
+		slot->ctype = SDMMC_CTYPE_1BIT;
+		break;
+	case MMC_BUS_WIDTH_4:
+		slot->ctype = SDMMC_CTYPE_4BIT;
+		break;
+	}
+
+	if (ios->clock) {
+		/*
+		 * Use mirror of ios->clock to prevent race with mmc
+		 * core ios update when finding the minimum.
+		 */
+		slot->clock = ios->clock;
+	}
+
+	switch (ios->power_mode) {
+	case MMC_POWER_UP:
+		set_bit(DW_MMC_CARD_NEED_INIT, &slot->flags);
+		break;
+	default:
+		break;
+	}
+}
+
+static int dw_mci_get_ro(struct mmc_host *mmc)
+{
+	int read_only;
+	struct dw_mci_slot *slot = mmc_priv(mmc);
+	struct dw_mci_board *brd = slot->host->pdata;
+
+	/* Use platform get_ro function, else try on board write protect */
+	if (brd->get_ro)
+		read_only = brd->get_ro(slot->id);
+	else
+		read_only =
+			mci_readl(slot->host, WRTPRT) & (1 << slot->id) ? 1 : 0;
+
+	dev_dbg(&mmc->class_dev, "card is %s\n",
+		read_only ? "read-only" : "read-write");
+
+	return read_only;
+}
+
+static int dw_mci_get_cd(struct mmc_host *mmc)
+{
+	int present;
+	struct dw_mci_slot *slot = mmc_priv(mmc);
+	struct dw_mci_board *brd = slot->host->pdata;
+
+	/* Use platform get_cd function, else try onboard card detect */
+	if (brd->get_cd)
+		present = !brd->get_cd(slot->id);
+	else
+		present = (mci_readl(slot->host, CDETECT) & (1 << slot->id))
+			== 0 ? 1 : 0;
+
+	if (present)
+		dev_dbg(&mmc->class_dev, "card is present\n");
+	else
+		dev_dbg(&mmc->class_dev, "card is not present\n");
+
+	return present;
+}
+
+static const struct mmc_host_ops dw_mci_ops = {
+	.request	= dw_mci_request,
+	.set_ios	= dw_mci_set_ios,
+	.get_ro		= dw_mci_get_ro,
+	.get_cd		= dw_mci_get_cd,
+};
+
+static void dw_mci_request_end(struct dw_mci *host, struct mmc_request *mrq)
+	__releases(&host->lock)
+	__acquires(&host->lock)
+{
+	struct dw_mci_slot *slot;
+	struct mmc_host	*prev_mmc = host->cur_slot->mmc;
+
+	WARN_ON(host->cmd || host->data);
+
+	host->cur_slot->mrq = NULL;
+	host->mrq = NULL;
+	if (!list_empty(&host->queue)) {
+		slot = list_entry(host->queue.next,
+				  struct dw_mci_slot, queue_node);
+		list_del(&slot->queue_node);
+		dev_vdbg(&host->pdev->dev, "list not empty: %s is next\n",
+			 mmc_hostname(slot->mmc));
+		host->state = STATE_SENDING_CMD;
+		dw_mci_start_request(host, slot);
+	} else {
+		dev_vdbg(&host->pdev->dev, "list empty\n");
+		host->state = STATE_IDLE;
+	}
+
+	spin_unlock(&host->lock);
+	mmc_request_done(prev_mmc, mrq);
+	spin_lock(&host->lock);
+}
+
+static void dw_mci_command_complete(struct dw_mci *host, struct mmc_command *cmd)
+{
+	u32 status = host->cmd_status;
+
+	host->cmd_status = 0;
+
+	/* Read the response from the card (up to 16 bytes) */
+	if (cmd->flags & MMC_RSP_PRESENT) {
+		if (cmd->flags & MMC_RSP_136) {
+			cmd->resp[3] = mci_readl(host, RESP0);
+			cmd->resp[2] = mci_readl(host, RESP1);
+			cmd->resp[1] = mci_readl(host, RESP2);
+			cmd->resp[0] = mci_readl(host, RESP3);
+		} else {
+			cmd->resp[0] = mci_readl(host, RESP0);
+			cmd->resp[1] = 0;
+			cmd->resp[2] = 0;
+			cmd->resp[3] = 0;
+		}
+	}
+
+	if (status & SDMMC_INT_RTO)
+		cmd->error = -ETIMEDOUT;
+	else if ((cmd->flags & MMC_RSP_CRC) && (status & SDMMC_INT_RCRC))
+		cmd->error = -EILSEQ;
+	else if (status & SDMMC_INT_RESP_ERR)
+		cmd->error = -EIO;
+	else
+		cmd->error = 0;
+
+	if (cmd->error) {
+		/* newer ip versions need a delay between retries */
+		if (host->quirks & DW_MCI_QUIRK_RETRY_DELAY)
+			mdelay(20);
+
+		if (cmd->data) {
+			host->data = NULL;
+			dw_mci_stop_dma(host);
+		}
+	}
+}
+
+static void dw_mci_tasklet_func(unsigned long priv)
+{
+	struct dw_mci *host = (struct dw_mci *)priv;
+	struct mmc_data	*data;
+	struct mmc_command *cmd;
+	enum dw_mci_state state;
+	enum dw_mci_state prev_state;
+	u32 status;
+
+	spin_lock(&host->lock);
+
+	state = host->state;
+	data = host->data;
+
+	do {
+		prev_state = state;
+
+		switch (state) {
+		case STATE_IDLE:
+			break;
+
+		case STATE_SENDING_CMD:
+			if (!test_and_clear_bit(EVENT_CMD_COMPLETE,
+						&host->pending_events))
+				break;
+
+			cmd = host->cmd;
+			host->cmd = NULL;
+			set_bit(EVENT_CMD_COMPLETE, &host->completed_events);
+			dw_mci_command_complete(host, host->mrq->cmd);
+			if (!host->mrq->data || cmd->error) {
+				dw_mci_request_end(host, host->mrq);
+				goto unlock;
+			}
+
+			prev_state = state = STATE_SENDING_DATA;
+			/* fall through */
+
+		case STATE_SENDING_DATA:
+			if (test_and_clear_bit(EVENT_DATA_ERROR,
+					       &host->pending_events)) {
+				dw_mci_stop_dma(host);
+				if (data->stop)
+					send_stop_cmd(host, data);
+				state = STATE_DATA_ERROR;
+				break;
+			}
+
+			if (!test_and_clear_bit(EVENT_XFER_COMPLETE,
+						&host->pending_events))
+				break;
+
+			set_bit(EVENT_XFER_COMPLETE, &host->completed_events);
+			prev_state = state = STATE_DATA_BUSY;
+			/* fall through */
+
+		case STATE_DATA_BUSY:
+			if (!test_and_clear_bit(EVENT_DATA_COMPLETE,
+						&host->pending_events))
+				break;
+
+			host->data = NULL;
+			set_bit(EVENT_DATA_COMPLETE, &host->completed_events);
+			status = host->data_status;
+
+			if (status & DW_MCI_DATA_ERROR_FLAGS) {
+				if (status & SDMMC_INT_DTO) {
+					dev_err(&host->pdev->dev,
+						"data timeout error\n");
+					data->error = -ETIMEDOUT;
+				} else if (status & SDMMC_INT_DCRC) {
+					dev_err(&host->pdev->dev,
+						"data CRC error\n");
+					data->error = -EILSEQ;
+				} else {
+					dev_err(&host->pdev->dev,
+						"data FIFO error "
+						"(status=%08x)\n",
+						status);
+					data->error = -EIO;
+				}
+			} else {
+				data->bytes_xfered = data->blocks * data->blksz;
+				data->error = 0;
+			}
+
+			if (!data->stop) {
+				dw_mci_request_end(host, host->mrq);
+				goto unlock;
+			}
+
+			prev_state = state = STATE_SENDING_STOP;
+			if (!data->error)
+				send_stop_cmd(host, data);
+			/* fall through */
+
+		case STATE_SENDING_STOP:
+			if (!test_and_clear_bit(EVENT_CMD_COMPLETE,
+						&host->pending_events))
+				break;
+
+			host->cmd = NULL;
+			dw_mci_command_complete(host, host->mrq->stop);
+			dw_mci_request_end(host, host->mrq);
+			goto unlock;
+
+		case STATE_DATA_ERROR:
+			if (!test_and_clear_bit(EVENT_XFER_COMPLETE,
+						&host->pending_events))
+				break;
+
+			state = STATE_DATA_BUSY;
+			break;
+		}
+	} while (state != prev_state);
+
+	host->state = state;
+unlock:
+	spin_unlock(&host->lock);
+
+}
+
+static void dw_mci_push_data16(struct dw_mci *host, void *buf, int cnt)
+{
+	u16 *pdata = (u16 *)buf;
+
+	WARN_ON(cnt % 2 != 0);
+
+	cnt = cnt >> 1;
+	while (cnt > 0) {
+		mci_writew(host, DATA, *pdata++);
+		cnt--;
+	}
+}
+
+static void dw_mci_pull_data16(struct dw_mci *host, void *buf, int cnt)
+{
+	u16 *pdata = (u16 *)buf;
+
+	WARN_ON(cnt % 2 != 0);
+
+	cnt = cnt >> 1;
+	while (cnt > 0) {
+		*pdata++ = mci_readw(host, DATA);
+		cnt--;
+	}
+}
+
+static void dw_mci_push_data32(struct dw_mci *host, void *buf, int cnt)
+{
+	u32 *pdata = (u32 *)buf;
+
+	WARN_ON(cnt % 4 != 0);
+	WARN_ON((unsigned long)pdata & 0x3);
+
+	cnt = cnt >> 2;
+	while (cnt > 0) {
+		mci_writel(host, DATA, *pdata++);
+		cnt--;
+	}
+}
+
+static void dw_mci_pull_data32(struct dw_mci *host, void *buf, int cnt)
+{
+	u32 *pdata = (u32 *)buf;
+
+	WARN_ON(cnt % 4 != 0);
+	WARN_ON((unsigned long)pdata & 0x3);
+
+	cnt = cnt >> 2;
+	while (cnt > 0) {
+		*pdata++ = mci_readl(host, DATA);
+		cnt--;
+	}
+}
+
+static void dw_mci_push_data64(struct dw_mci *host, void *buf, int cnt)
+{
+	u64 *pdata = (u64 *)buf;
+
+	WARN_ON(cnt % 8 != 0);
+
+	cnt = cnt >> 3;
+	while (cnt > 0) {
+		mci_writeq(host, DATA, *pdata++);
+		cnt--;
+	}
+}
+
+static void dw_mci_pull_data64(struct dw_mci *host, void *buf, int cnt)
+{
+	u64 *pdata = (u64 *)buf;
+
+	WARN_ON(cnt % 8 != 0);
+
+	cnt = cnt >> 3;
+	while (cnt > 0) {
+		*pdata++ = mci_readq(host, DATA);
+		cnt--;
+	}
+}
+
+static void dw_mci_read_data_pio(struct dw_mci *host)
+{
+	struct scatterlist *sg = host->sg;
+	void *buf = sg_virt(sg);
+	unsigned int offset = host->pio_offset;
+	struct mmc_data	*data = host->data;
+	int shift = host->data_shift;
+	u32 status;
+	unsigned int nbytes = 0, len, old_len, count = 0;
+
+	do {
+		len = SDMMC_GET_FCNT(mci_readl(host, STATUS)) << shift;
+		if (count == 0)
+			old_len = len;
+
+		if (offset + len <= sg->length) {
+			host->pull_data(host, (void *)(buf + offset), len);
+
+			offset += len;
+			nbytes += len;
+
+			if (offset == sg->length) {
+				flush_dcache_page(sg_page(sg));
+				host->sg = sg = sg_next(sg);
+				if (!sg)
+					goto done;
+
+				offset = 0;
+				buf = sg_virt(sg);
+			}
+		} else {
+			unsigned int remaining = sg->length - offset;
+			host->pull_data(host, (void *)(buf + offset),
+					remaining);
+			nbytes += remaining;
+
+			flush_dcache_page(sg_page(sg));
+			host->sg = sg = sg_next(sg);
+			if (!sg)
+				goto done;
+
+			offset = len - remaining;
+			buf = sg_virt(sg);
+			host->pull_data(host, buf, offset);
+			nbytes += offset;
+		}
+
+		status = mci_readl(host, MINTSTS);
+		mci_writel(host, RINTSTS, SDMMC_INT_RXDR);
+		if (status & DW_MCI_DATA_ERROR_FLAGS) {
+			host->data_status = status;
+			data->bytes_xfered += nbytes;
+			smp_wmb();
+
+			set_bit(EVENT_DATA_ERROR, &host->pending_events);
+
+			tasklet_schedule(&host->tasklet);
+			return;
+		}
+		count++;
+	} while (status & SDMMC_INT_RXDR); /*if the RXDR is ready read again*/
+	len = SDMMC_GET_FCNT(mci_readl(host, STATUS));
+	host->pio_offset = offset;
+	data->bytes_xfered += nbytes;
+	return;
+
+done:
+	data->bytes_xfered += nbytes;
+	smp_wmb();
+	set_bit(EVENT_XFER_COMPLETE, &host->pending_events);
+}
+
+static void dw_mci_write_data_pio(struct dw_mci *host)
+{
+	struct scatterlist *sg = host->sg;
+	void *buf = sg_virt(sg);
+	unsigned int offset = host->pio_offset;
+	struct mmc_data	*data = host->data;
+	int shift = host->data_shift;
+	u32 status;
+	unsigned int nbytes = 0, len;
+
+	do {
+		len = SDMMC_FIFO_SZ -
+			(SDMMC_GET_FCNT(mci_readl(host, STATUS)) << shift);
+		if (offset + len <= sg->length) {
+			host->push_data(host, (void *)(buf + offset), len);
+
+			offset += len;
+			nbytes += len;
+			if (offset == sg->length) {
+				host->sg = sg = sg_next(sg);
+				if (!sg)
+					goto done;
+
+				offset = 0;
+				buf = sg_virt(sg);
+			}
+		} else {
+			unsigned int remaining = sg->length - offset;
+
+			host->push_data(host, (void *)(buf + offset),
+					remaining);
+			nbytes += remaining;
+
+			host->sg = sg = sg_next(sg);
+			if (!sg)
+				goto done;
+
+			offset = len - remaining;
+			buf = sg_virt(sg);
+			host->push_data(host, (void *)buf, offset);
+			nbytes += offset;
+		}
+
+		status = mci_readl(host, MINTSTS);
+		mci_writel(host, RINTSTS, SDMMC_INT_TXDR);
+		if (status & DW_MCI_DATA_ERROR_FLAGS) {
+			host->data_status = status;
+			data->bytes_xfered += nbytes;
+
+			smp_wmb();
+
+			set_bit(EVENT_DATA_ERROR, &host->pending_events);
+
+			tasklet_schedule(&host->tasklet);
+			return;
+		}
+	} while (status & SDMMC_INT_TXDR); /* if TXDR write again */
+
+	host->pio_offset = offset;
+	data->bytes_xfered += nbytes;
+
+	return;
+
+done:
+	data->bytes_xfered += nbytes;
+	smp_wmb();
+	set_bit(EVENT_XFER_COMPLETE, &host->pending_events);
+}
+
+static void dw_mci_cmd_interrupt(struct dw_mci *host, u32 status)
+{
+	if (!host->cmd_status)
+		host->cmd_status = status;
+
+	smp_wmb();
+
+	set_bit(EVENT_CMD_COMPLETE, &host->pending_events);
+	tasklet_schedule(&host->tasklet);
+}
+
+static irqreturn_t dw_mci_interrupt(int irq, void *dev_id)
+{
+	struct dw_mci *host = dev_id;
+	u32 status, pending;
+	unsigned int pass_count = 0;
+
+	do {
+		status = mci_readl(host, RINTSTS);
+		pending = mci_readl(host, MINTSTS); /* read-only mask reg */
+
+		/*
+		 * DTO fix - version 2.10a and below, and only if internal DMA
+		 * is configured.
+		 */
+		if (host->quirks & DW_MCI_QUIRK_IDMAC_DTO) {
+			if (!pending &&
+			    ((mci_readl(host, STATUS) >> 17) & 0x1fff))
+				pending |= SDMMC_INT_DATA_OVER;
+		}
+
+		if (!pending)
+			break;
+
+		if (pending & DW_MCI_CMD_ERROR_FLAGS) {
+			mci_writel(host, RINTSTS, DW_MCI_CMD_ERROR_FLAGS);
+			host->cmd_status = status;
+			smp_wmb();
+			set_bit(EVENT_CMD_COMPLETE, &host->pending_events);
+			tasklet_schedule(&host->tasklet);
+		}
+
+		if (pending & DW_MCI_DATA_ERROR_FLAGS) {
+			/* if there is an error report DATA_ERROR */
+			mci_writel(host, RINTSTS, DW_MCI_DATA_ERROR_FLAGS);
+			host->data_status = status;
+			smp_wmb();
+			set_bit(EVENT_DATA_ERROR, &host->pending_events);
+			tasklet_schedule(&host->tasklet);
+		}
+
+		if (pending & SDMMC_INT_DATA_OVER) {
+			mci_writel(host, RINTSTS, SDMMC_INT_DATA_OVER);
+			if (!host->data_status)
+				host->data_status = status;
+			smp_wmb();
+			if (host->dir_status == DW_MCI_RECV_STATUS) {
+				if (host->sg != NULL)
+					dw_mci_read_data_pio(host);
+			}
+			set_bit(EVENT_DATA_COMPLETE, &host->pending_events);
+			tasklet_schedule(&host->tasklet);
+		}
+
+		if (pending & SDMMC_INT_RXDR) {
+			mci_writel(host, RINTSTS, SDMMC_INT_RXDR);
+			if (host->sg)
+				dw_mci_read_data_pio(host);
+		}
+
+		if (pending & SDMMC_INT_TXDR) {
+			mci_writel(host, RINTSTS, SDMMC_INT_TXDR);
+			if (host->sg)
+				dw_mci_write_data_pio(host);
+		}
+
+		if (pending & SDMMC_INT_CMD_DONE) {
+			mci_writel(host, RINTSTS, SDMMC_INT_CMD_DONE);
+			dw_mci_cmd_interrupt(host, status);
+		}
+
+		if (pending & SDMMC_INT_CD) {
+			mci_writel(host, RINTSTS, SDMMC_INT_CD);
+			tasklet_schedule(&host->card_tasklet);
+		}
+
+	} while (pass_count++ < 5);
+
+#ifdef CONFIG_MMC_DW_IDMAC
+	/* Handle DMA interrupts */
+	pending = mci_readl(host, IDSTS);
+	if (pending & (SDMMC_IDMAC_INT_TI | SDMMC_IDMAC_INT_RI)) {
+		mci_writel(host, IDSTS, SDMMC_IDMAC_INT_TI | SDMMC_IDMAC_INT_RI);
+		mci_writel(host, IDSTS, SDMMC_IDMAC_INT_NI);
+		set_bit(EVENT_DATA_COMPLETE, &host->pending_events);
+		host->dma_ops->complete(host);
+	}
+#endif
+
+	return IRQ_HANDLED;
+}
+
+static void dw_mci_tasklet_card(unsigned long data)
+{
+	struct dw_mci *host = (struct dw_mci *)data;
+	int i;
+
+	for (i = 0; i < host->num_slots; i++) {
+		struct dw_mci_slot *slot = host->slot[i];
+		struct mmc_host *mmc = slot->mmc;
+		struct mmc_request *mrq;
+		int present;
+		u32 ctrl;
+
+		present = dw_mci_get_cd(mmc);
+		while (present != slot->last_detect_state) {
+			spin_lock(&host->lock);
+
+			dev_dbg(&slot->mmc->class_dev, "card %s\n",
+				present ? "inserted" : "removed");
+
+			/* Card change detected */
+			slot->last_detect_state = present;
+
+			/* Power up slot */
+			if (present != 0) {
+				if (host->pdata->setpower)
+					host->pdata->setpower(slot->id,
+							      mmc->ocr_avail);
+
+				set_bit(DW_MMC_CARD_PRESENT, &slot->flags);
+			}
+
+			/* Clean up queue if present */
+			mrq = slot->mrq;
+			if (mrq) {
+				if (mrq == host->mrq) {
+					host->data = NULL;
+					host->cmd = NULL;
+
+					switch (host->state) {
+					case STATE_IDLE:
+						break;
+					case STATE_SENDING_CMD:
+						mrq->cmd->error = -ENOMEDIUM;
+						if (!mrq->data)
+							break;
+						/* fall through */
+					case STATE_SENDING_DATA:
+						mrq->data->error = -ENOMEDIUM;
+						dw_mci_stop_dma(host);
+						break;
+					case STATE_DATA_BUSY:
+					case STATE_DATA_ERROR:
+						if (mrq->data->error == -EINPROGRESS)
+							mrq->data->error = -ENOMEDIUM;
+						if (!mrq->stop)
+							break;
+						/* fall through */
+					case STATE_SENDING_STOP:
+						mrq->stop->error = -ENOMEDIUM;
+						break;
+					}
+
+					dw_mci_request_end(host, mrq);
+				} else {
+					list_del(&slot->queue_node);
+					mrq->cmd->error = -ENOMEDIUM;
+					if (mrq->data)
+						mrq->data->error = -ENOMEDIUM;
+					if (mrq->stop)
+						mrq->stop->error = -ENOMEDIUM;
+
+					spin_unlock(&host->lock);
+					mmc_request_done(slot->mmc, mrq);
+					spin_lock(&host->lock);
+				}
+			}
+
+			/* Power down slot */
+			if (present == 0) {
+				if (host->pdata->setpower)
+					host->pdata->setpower(slot->id, 0);
+				clear_bit(DW_MMC_CARD_PRESENT, &slot->flags);
+
+				/*
+				 * Clear down the FIFO - doing so generates a
+				 * block interrupt, hence setting the
+				 * scatter-gather pointer to NULL.
+				 */
+				host->sg = NULL;
+
+				ctrl = mci_readl(host, CTRL);
+				ctrl |= SDMMC_CTRL_FIFO_RESET;
+				mci_writel(host, CTRL, ctrl);
+
+#ifdef CONFIG_MMC_DW_IDMAC
+				ctrl = mci_readl(host, BMOD);
+				ctrl |= 0x01; /* Software reset of DMA */
+				mci_writel(host, BMOD, ctrl);
+#endif
+
+			}
+
+			spin_unlock(&host->lock);
+			present = dw_mci_get_cd(mmc);
+		}
+
+		mmc_detect_change(slot->mmc,
+			msecs_to_jiffies(host->pdata->detect_delay_ms));
+	}
+}
+
+static int __init dw_mci_init_slot(struct dw_mci *host, unsigned int id)
+{
+	struct mmc_host *mmc;
+	struct dw_mci_slot *slot;
+
+	mmc = mmc_alloc_host(sizeof(struct dw_mci_slot), &host->pdev->dev);
+	if (!mmc)
+		return -ENOMEM;
+
+	slot = mmc_priv(mmc);
+	slot->id = id;
+	slot->mmc = mmc;
+	slot->host = host;
+
+	mmc->ops = &dw_mci_ops;
+	mmc->f_min = DIV_ROUND_UP(host->bus_hz, 510);
+	mmc->f_max = host->bus_hz;
+
+	if (host->pdata->get_ocr)
+		mmc->ocr_avail = host->pdata->get_ocr(id);
+	else
+		mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
+
+	/*
+	 * Start with slot power disabled, it will be enabled when a card
+	 * is detected.
+	 */
+	if (host->pdata->setpower)
+		host->pdata->setpower(id, 0);
+
+	mmc->caps = 0;
+	if (host->pdata->get_bus_wd)
+		if (host->pdata->get_bus_wd(slot->id) >= 4)
+			mmc->caps |= MMC_CAP_4_BIT_DATA;
+
+	if (host->pdata->quirks & DW_MCI_QUIRK_HIGHSPEED)
+		mmc->caps |= MMC_CAP_SD_HIGHSPEED;
+
+#ifdef CONFIG_MMC_DW_IDMAC
+	mmc->max_segs = host->ring_size;
+	mmc->max_blk_size = 65536;
+	mmc->max_blk_count = host->ring_size;
+	mmc->max_seg_size = 0x1000;
+	mmc->max_req_size = mmc->max_seg_size * mmc->max_blk_count;
+#else
+	if (host->pdata->blk_settings) {
+		mmc->max_segs = host->pdata->blk_settings->max_segs;
+		mmc->max_blk_size = host->pdata->blk_settings->max_blk_size;
+		mmc->max_blk_count = host->pdata->blk_settings->max_blk_count;
+		mmc->max_req_size = host->pdata->blk_settings->max_req_size;
+		mmc->max_seg_size = host->pdata->blk_settings->max_seg_size;
+	} else {
+		/* Useful defaults if platform data is unset. */
+		mmc->max_segs = 64;
+		mmc->max_blk_size = 65536; /* BLKSIZ is 16 bits */
+		mmc->max_blk_count = 512;
+		mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count;
+		mmc->max_seg_size = mmc->max_req_size;
+	}
+#endif /* CONFIG_MMC_DW_IDMAC */
+
+	if (dw_mci_get_cd(mmc))
+		set_bit(DW_MMC_CARD_PRESENT, &slot->flags);
+	else
+		clear_bit(DW_MMC_CARD_PRESENT, &slot->flags);
+
+	host->slot[id] = slot;
+	mmc_add_host(mmc);
+
+#if defined(CONFIG_DEBUG_FS)
+	dw_mci_init_debugfs(slot);
+#endif
+
+	/* Card initially undetected */
+	slot->last_detect_state = 0;
+
+	return 0;
+}
+
+static void dw_mci_cleanup_slot(struct dw_mci_slot *slot, unsigned int id)
+{
+	/* Shutdown detect IRQ */
+	if (slot->host->pdata->exit)
+		slot->host->pdata->exit(id);
+
+	/* Debugfs stuff is cleaned up by mmc core */
+	mmc_remove_host(slot->mmc);
+	slot->host->slot[id] = NULL;
+	mmc_free_host(slot->mmc);
+}
+
+static void dw_mci_init_dma(struct dw_mci *host)
+{
+	/* Alloc memory for sg translation */
+	host->sg_cpu = dma_alloc_coherent(&host->pdev->dev, PAGE_SIZE,
+					  &host->sg_dma, GFP_KERNEL);
+	if (!host->sg_cpu) {
+		dev_err(&host->pdev->dev, "%s: could not alloc DMA memory\n",
+			__func__);
+		goto no_dma;
+	}
+
+	/* Determine which DMA interface to use */
+#ifdef CONFIG_MMC_DW_IDMAC
+	host->dma_ops = &dw_mci_idmac_ops;
+	dev_info(&host->pdev->dev, "Using internal DMA controller.\n");
+#endif
+
+	if (!host->dma_ops)
+		goto no_dma;
+
+	if (host->dma_ops->init) {
+		if (host->dma_ops->init(host)) {
+			dev_err(&host->pdev->dev, "%s: Unable to initialize "
+				"DMA Controller.\n", __func__);
+			goto no_dma;
+		}
+	} else {
+		dev_err(&host->pdev->dev, "DMA initialization not found.\n");
+		goto no_dma;
+	}
+
+	host->use_dma = 1;
+	return;
+
+no_dma:
+	dev_info(&host->pdev->dev, "Using PIO mode.\n");
+	host->use_dma = 0;
+	return;
+}
+
+static bool mci_wait_reset(struct device *dev, struct dw_mci *host)
+{
+	unsigned long timeout = jiffies + msecs_to_jiffies(500);
+	unsigned int ctrl;
+
+	mci_writel(host, CTRL, (SDMMC_CTRL_RESET | SDMMC_CTRL_FIFO_RESET |
+				SDMMC_CTRL_DMA_RESET));
+
+	/* wait till resets clear */
+	do {
+		ctrl = mci_readl(host, CTRL);
+		if (!(ctrl & (SDMMC_CTRL_RESET | SDMMC_CTRL_FIFO_RESET |
+			      SDMMC_CTRL_DMA_RESET)))
+			return true;
+	} while (time_before(jiffies, timeout));
+
+	dev_err(dev, "Timeout resetting block (ctrl %#x)\n", ctrl);
+
+	return false;
+}
+
+static int dw_mci_probe(struct platform_device *pdev)
+{
+	struct dw_mci *host;
+	struct resource	*regs;
+	struct dw_mci_board *pdata;
+	int irq, ret, i, width;
+	u32 fifo_size;
+
+	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!regs)
+		return -ENXIO;
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0)
+		return irq;
+
+	host = kzalloc(sizeof(struct dw_mci), GFP_KERNEL);
+	if (!host)
+		return -ENOMEM;
+
+	host->pdev = pdev;
+	host->pdata = pdata = pdev->dev.platform_data;
+	if (!pdata || !pdata->init) {
+		dev_err(&pdev->dev,
+			"Platform data must supply init function\n");
+		ret = -ENODEV;
+		goto err_freehost;
+	}
+
+	if (!pdata->select_slot && pdata->num_slots > 1) {
+		dev_err(&pdev->dev,
+			"Platform data must supply select_slot function\n");
+		ret = -ENODEV;
+		goto err_freehost;
+	}
+
+	if (!pdata->bus_hz) {
+		dev_err(&pdev->dev,
+			"Platform data must supply bus speed\n");
+		ret = -ENODEV;
+		goto err_freehost;
+	}
+
+	host->bus_hz = pdata->bus_hz;
+	host->quirks = pdata->quirks;
+
+	spin_lock_init(&host->lock);
+	INIT_LIST_HEAD(&host->queue);
+
+	ret = -ENOMEM;
+	host->regs = ioremap(regs->start, regs->end - regs->start + 1);
+	if (!host->regs)
+		goto err_freehost;
+
+	host->dma_ops = pdata->dma_ops;
+	dw_mci_init_dma(host);
+
+	/*
+	 * Get the host data width - this assumes that HCON has been set with
+	 * the correct values.
+	 */
+	i = (mci_readl(host, HCON) >> 7) & 0x7;
+	if (!i) {
+		host->push_data = dw_mci_push_data16;
+		host->pull_data = dw_mci_pull_data16;
+		width = 16;
+		host->data_shift = 1;
+	} else if (i == 2) {
+		host->push_data = dw_mci_push_data64;
+		host->pull_data = dw_mci_pull_data64;
+		width = 64;
+		host->data_shift = 3;
+	} else {
+		/* Check for a reserved value, and warn if it is */
+		WARN((i != 1),
+		     "HCON reports a reserved host data width!\n"
+		     "Defaulting to 32-bit access.\n");
+		host->push_data = dw_mci_push_data32;
+		host->pull_data = dw_mci_pull_data32;
+		width = 32;
+		host->data_shift = 2;
+	}
+
+	/* Reset all blocks */
+	if (!mci_wait_reset(&pdev->dev, host)) {
+		ret = -ENODEV;
+		goto err_dmaunmap;
+	}
+
+	/* Clear the interrupts for the host controller */
+	mci_writel(host, RINTSTS, 0xFFFFFFFF);
+	mci_writel(host, INTMASK, 0); /* disable all mmc interrupt first */
+
+	/* Put in max timeout */
+	mci_writel(host, TMOUT, 0xFFFFFFFF);
+
+	/*
+	 * FIFO threshold settings  RxMark  = fifo_size / 2 - 1,
+	 *                          Tx Mark = fifo_size / 2 DMA Size = 8
+	 */
+	fifo_size = mci_readl(host, FIFOTH);
+	fifo_size = (fifo_size >> 16) & 0x7ff;
+	mci_writel(host, FIFOTH, ((0x2 << 28) | ((fifo_size/2 - 1) << 16) |
+				  ((fifo_size/2) << 0)));
+
+	/* disable clock to CIU */
+	mci_writel(host, CLKENA, 0);
+	mci_writel(host, CLKSRC, 0);
+
+	tasklet_init(&host->tasklet, dw_mci_tasklet_func, (unsigned long)host);
+	tasklet_init(&host->card_tasklet,
+		     dw_mci_tasklet_card, (unsigned long)host);
+
+	ret = request_irq(irq, dw_mci_interrupt, 0, "dw-mci", host);
+	if (ret)
+		goto err_dmaunmap;
+
+	platform_set_drvdata(pdev, host);
+
+	if (host->pdata->num_slots)
+		host->num_slots = host->pdata->num_slots;
+	else
+		host->num_slots = ((mci_readl(host, HCON) >> 1) & 0x1F) + 1;
+
+	/* We need at least one slot to succeed */
+	for (i = 0; i < host->num_slots; i++) {
+		ret = dw_mci_init_slot(host, i);
+		if (ret) {
+			ret = -ENODEV;
+			goto err_init_slot;
+		}
+	}
+
+	/*
+	 * Enable interrupts for command done, data over, data empty, card det,
+	 * receive ready and error such as transmit, receive timeout, crc error
+	 */
+	mci_writel(host, RINTSTS, 0xFFFFFFFF);
+	mci_writel(host, INTMASK, SDMMC_INT_CMD_DONE | SDMMC_INT_DATA_OVER |
+		   SDMMC_INT_TXDR | SDMMC_INT_RXDR |
+		   DW_MCI_ERROR_FLAGS | SDMMC_INT_CD);
+	mci_writel(host, CTRL, SDMMC_CTRL_INT_ENABLE); /* Enable mci interrupt */
+
+	dev_info(&pdev->dev, "DW MMC controller at irq %d, "
+		 "%d bit host data width\n", irq, width);
+	if (host->quirks & DW_MCI_QUIRK_IDMAC_DTO)
+		dev_info(&pdev->dev, "Internal DMAC interrupt fix enabled.\n");
+
+	return 0;
+
+err_init_slot:
+	/* De-init any initialized slots */
+	while (i > 0) {
+		if (host->slot[i])
+			dw_mci_cleanup_slot(host->slot[i], i);
+		i--;
+	}
+	free_irq(irq, host);
+
+err_dmaunmap:
+	if (host->use_dma && host->dma_ops->exit)
+		host->dma_ops->exit(host);
+	dma_free_coherent(&host->pdev->dev, PAGE_SIZE,
+			  host->sg_cpu, host->sg_dma);
+	iounmap(host->regs);
+
+err_freehost:
+	kfree(host);
+	return ret;
+}
+
+static int __exit dw_mci_remove(struct platform_device *pdev)
+{
+	struct dw_mci *host = platform_get_drvdata(pdev);
+	int i;
+
+	mci_writel(host, RINTSTS, 0xFFFFFFFF);
+	mci_writel(host, INTMASK, 0); /* disable all mmc interrupt first */
+
+	platform_set_drvdata(pdev, NULL);
+
+	for (i = 0; i < host->num_slots; i++) {
+		dev_dbg(&pdev->dev, "remove slot %d\n", i);
+		if (host->slot[i])
+			dw_mci_cleanup_slot(host->slot[i], i);
+	}
+
+	/* disable clock to CIU */
+	mci_writel(host, CLKENA, 0);
+	mci_writel(host, CLKSRC, 0);
+
+	free_irq(platform_get_irq(pdev, 0), host);
+	dma_free_coherent(&pdev->dev, PAGE_SIZE, host->sg_cpu, host->sg_dma);
+
+	if (host->use_dma && host->dma_ops->exit)
+		host->dma_ops->exit(host);
+
+	iounmap(host->regs);
+
+	kfree(host);
+	return 0;
+}
+
+#ifdef CONFIG_PM
+/*
+ * TODO: we should probably disable the clock to the card in the suspend path.
+ */
+static int dw_mci_suspend(struct platform_device *pdev, pm_message_t mesg)
+{
+	int i, ret;
+	struct dw_mci *host = platform_get_drvdata(pdev);
+
+	for (i = 0; i < host->num_slots; i++) {
+		struct dw_mci_slot *slot = host->slot[i];
+		if (!slot)
+			continue;
+		ret = mmc_suspend_host(slot->mmc);
+		if (ret < 0) {
+			while (--i >= 0) {
+				slot = host->slot[i];
+				if (slot)
+					mmc_resume_host(host->slot[i]->mmc);
+			}
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+static int dw_mci_resume(struct platform_device *pdev)
+{
+	int i, ret;
+	struct dw_mci *host = platform_get_drvdata(pdev);
+
+	for (i = 0; i < host->num_slots; i++) {
+		struct dw_mci_slot *slot = host->slot[i];
+		if (!slot)
+			continue;
+		ret = mmc_resume_host(host->slot[i]->mmc);
+		if (ret < 0)
+			return ret;
+	}
+
+	return 0;
+}
+#else
+#define dw_mci_suspend	NULL
+#define dw_mci_resume	NULL
+#endif /* CONFIG_PM */
+
+static struct platform_driver dw_mci_driver = {
+	.remove		= __exit_p(dw_mci_remove),
+	.suspend	= dw_mci_suspend,
+	.resume		= dw_mci_resume,
+	.driver		= {
+		.name		= "dw_mmc",
+	},
+};
+
+static int __init dw_mci_init(void)
+{
+	return platform_driver_probe(&dw_mci_driver, dw_mci_probe);
+}
+
+static void __exit dw_mci_exit(void)
+{
+	platform_driver_unregister(&dw_mci_driver);
+}
+
+module_init(dw_mci_init);
+module_exit(dw_mci_exit);
+
+MODULE_DESCRIPTION("DW Multimedia Card Interface driver");
+MODULE_AUTHOR("NXP Semiconductor VietNam");
+MODULE_AUTHOR("Imagination Technologies Ltd");
+MODULE_LICENSE("GPL v2");
diff -druNp linux-libre-2.6.37-gnu1/drivers/mmc/host/dw_mmc.h linux-libre-2.6.38-gnu1/drivers/mmc/host/dw_mmc.h
--- linux-libre-2.6.37-gnu1/drivers/mmc/host/dw_mmc.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mmc/host/dw_mmc.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,168 @@
+/*
+ * Synopsys DesignWare Multimedia Card Interface driver
+ *  (Based on NXP driver for lpc 31xx)
+ *
+ * Copyright (C) 2009 NXP Semiconductors
+ * Copyright (C) 2009, 2010 Imagination Technologies 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 _DW_MMC_H_
+#define _DW_MMC_H_
+
+#define SDMMC_CTRL		0x000
+#define SDMMC_PWREN		0x004
+#define SDMMC_CLKDIV		0x008
+#define SDMMC_CLKSRC		0x00c
+#define SDMMC_CLKENA		0x010
+#define SDMMC_TMOUT		0x014
+#define SDMMC_CTYPE		0x018
+#define SDMMC_BLKSIZ		0x01c
+#define SDMMC_BYTCNT		0x020
+#define SDMMC_INTMASK		0x024
+#define SDMMC_CMDARG		0x028
+#define SDMMC_CMD		0x02c
+#define SDMMC_RESP0		0x030
+#define SDMMC_RESP1		0x034
+#define SDMMC_RESP2		0x038
+#define SDMMC_RESP3		0x03c
+#define SDMMC_MINTSTS		0x040
+#define SDMMC_RINTSTS		0x044
+#define SDMMC_STATUS		0x048
+#define SDMMC_FIFOTH		0x04c
+#define SDMMC_CDETECT		0x050
+#define SDMMC_WRTPRT		0x054
+#define SDMMC_GPIO		0x058
+#define SDMMC_TCBCNT		0x05c
+#define SDMMC_TBBCNT		0x060
+#define SDMMC_DEBNCE		0x064
+#define SDMMC_USRID		0x068
+#define SDMMC_VERID		0x06c
+#define SDMMC_HCON		0x070
+#define SDMMC_BMOD		0x080
+#define SDMMC_PLDMND		0x084
+#define SDMMC_DBADDR		0x088
+#define SDMMC_IDSTS		0x08c
+#define SDMMC_IDINTEN		0x090
+#define SDMMC_DSCADDR		0x094
+#define SDMMC_BUFADDR		0x098
+#define SDMMC_DATA		0x100
+#define SDMMC_DATA_ADR		0x100
+
+/* shift bit field */
+#define _SBF(f, v)		((v) << (f))
+
+/* Control register defines */
+#define SDMMC_CTRL_USE_IDMAC		BIT(25)
+#define SDMMC_CTRL_CEATA_INT_EN		BIT(11)
+#define SDMMC_CTRL_SEND_AS_CCSD		BIT(10)
+#define SDMMC_CTRL_SEND_CCSD		BIT(9)
+#define SDMMC_CTRL_ABRT_READ_DATA	BIT(8)
+#define SDMMC_CTRL_SEND_IRQ_RESP	BIT(7)
+#define SDMMC_CTRL_READ_WAIT		BIT(6)
+#define SDMMC_CTRL_DMA_ENABLE		BIT(5)
+#define SDMMC_CTRL_INT_ENABLE		BIT(4)
+#define SDMMC_CTRL_DMA_RESET		BIT(2)
+#define SDMMC_CTRL_FIFO_RESET		BIT(1)
+#define SDMMC_CTRL_RESET		BIT(0)
+/* Clock Enable register defines */
+#define SDMMC_CLKEN_LOW_PWR		BIT(16)
+#define SDMMC_CLKEN_ENABLE		BIT(0)
+/* time-out register defines */
+#define SDMMC_TMOUT_DATA(n)		_SBF(8, (n))
+#define SDMMC_TMOUT_DATA_MSK		0xFFFFFF00
+#define SDMMC_TMOUT_RESP(n)		((n) & 0xFF)
+#define SDMMC_TMOUT_RESP_MSK		0xFF
+/* card-type register defines */
+#define SDMMC_CTYPE_8BIT		BIT(16)
+#define SDMMC_CTYPE_4BIT		BIT(0)
+#define SDMMC_CTYPE_1BIT		0
+/* Interrupt status & mask register defines */
+#define SDMMC_INT_SDIO			BIT(16)
+#define SDMMC_INT_EBE			BIT(15)
+#define SDMMC_INT_ACD			BIT(14)
+#define SDMMC_INT_SBE			BIT(13)
+#define SDMMC_INT_HLE			BIT(12)
+#define SDMMC_INT_FRUN			BIT(11)
+#define SDMMC_INT_HTO			BIT(10)
+#define SDMMC_INT_DTO			BIT(9)
+#define SDMMC_INT_RTO			BIT(8)
+#define SDMMC_INT_DCRC			BIT(7)
+#define SDMMC_INT_RCRC			BIT(6)
+#define SDMMC_INT_RXDR			BIT(5)
+#define SDMMC_INT_TXDR			BIT(4)
+#define SDMMC_INT_DATA_OVER		BIT(3)
+#define SDMMC_INT_CMD_DONE		BIT(2)
+#define SDMMC_INT_RESP_ERR		BIT(1)
+#define SDMMC_INT_CD			BIT(0)
+#define SDMMC_INT_ERROR			0xbfc2
+/* Command register defines */
+#define SDMMC_CMD_START			BIT(31)
+#define SDMMC_CMD_CCS_EXP		BIT(23)
+#define SDMMC_CMD_CEATA_RD		BIT(22)
+#define SDMMC_CMD_UPD_CLK		BIT(21)
+#define SDMMC_CMD_INIT			BIT(15)
+#define SDMMC_CMD_STOP			BIT(14)
+#define SDMMC_CMD_PRV_DAT_WAIT		BIT(13)
+#define SDMMC_CMD_SEND_STOP		BIT(12)
+#define SDMMC_CMD_STRM_MODE		BIT(11)
+#define SDMMC_CMD_DAT_WR		BIT(10)
+#define SDMMC_CMD_DAT_EXP		BIT(9)
+#define SDMMC_CMD_RESP_CRC		BIT(8)
+#define SDMMC_CMD_RESP_LONG		BIT(7)
+#define SDMMC_CMD_RESP_EXP		BIT(6)
+#define SDMMC_CMD_INDX(n)		((n) & 0x1F)
+/* Status register defines */
+#define SDMMC_GET_FCNT(x)		(((x)>>17) & 0x1FF)
+#define SDMMC_FIFO_SZ			32
+/* Internal DMAC interrupt defines */
+#define SDMMC_IDMAC_INT_AI		BIT(9)
+#define SDMMC_IDMAC_INT_NI		BIT(8)
+#define SDMMC_IDMAC_INT_CES		BIT(5)
+#define SDMMC_IDMAC_INT_DU		BIT(4)
+#define SDMMC_IDMAC_INT_FBE		BIT(2)
+#define SDMMC_IDMAC_INT_RI		BIT(1)
+#define SDMMC_IDMAC_INT_TI		BIT(0)
+/* Internal DMAC bus mode bits */
+#define SDMMC_IDMAC_ENABLE		BIT(7)
+#define SDMMC_IDMAC_FB			BIT(1)
+#define SDMMC_IDMAC_SWRESET		BIT(0)
+
+/* Register access macros */
+#define mci_readl(dev, reg)			\
+	__raw_readl(dev->regs + SDMMC_##reg)
+#define mci_writel(dev, reg, value)			\
+	__raw_writel((value), dev->regs + SDMMC_##reg)
+
+/* 16-bit FIFO access macros */
+#define mci_readw(dev, reg)			\
+	__raw_readw(dev->regs + SDMMC_##reg)
+#define mci_writew(dev, reg, value)			\
+	__raw_writew((value), dev->regs + SDMMC_##reg)
+
+/* 64-bit FIFO access macros */
+#ifdef readq
+#define mci_readq(dev, reg)			\
+	__raw_readq(dev->regs + SDMMC_##reg)
+#define mci_writeq(dev, reg, value)			\
+	__raw_writeq((value), dev->regs + SDMMC_##reg)
+#else
+/*
+ * Dummy readq implementation for architectures that don't define it.
+ *
+ * We would assume that none of these architectures would configure
+ * the IP block with a 64bit FIFO width, so this code will never be
+ * executed on those machines. Defining these macros here keeps the
+ * rest of the code free from ifdefs.
+ */
+#define mci_readq(dev, reg)			\
+	(*(volatile u64 __force *)(dev->regs + SDMMC_##reg))
+#define mci_writeq(dev, reg, value)			\
+	(*(volatile u64 __force *)(dev->regs + SDMMC_##reg) = value)
+#endif
+
+#endif /* _DW_MMC_H_ */
diff -druNp linux-libre-2.6.37-gnu1/drivers/mmc/host/jz4740_mmc.c linux-libre-2.6.38-gnu1/drivers/mmc/host/jz4740_mmc.c
--- linux-libre-2.6.37-gnu1/drivers/mmc/host/jz4740_mmc.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mmc/host/jz4740_mmc.c	2011-03-14 21:20:32.000000000 -0400
@@ -14,6 +14,7 @@
  */
 
 #include <linux/mmc/host.h>
+#include <linux/err.h>
 #include <linux/io.h>
 #include <linux/irq.h>
 #include <linux/interrupt.h>
@@ -827,8 +828,8 @@ static int __devinit jz4740_mmc_probe(st
 	}
 
 	host->clk = clk_get(&pdev->dev, "mmc");
-	if (!host->clk) {
-		ret = -ENOENT;
+	if (IS_ERR(host->clk)) {
+		ret = PTR_ERR(host->clk);
 		dev_err(&pdev->dev, "Failed to get mmc clock\n");
 		goto err_free_host;
 	}
diff -druNp linux-libre-2.6.37-gnu1/drivers/mmc/host/Kconfig linux-libre-2.6.38-gnu1/drivers/mmc/host/Kconfig
--- linux-libre-2.6.37-gnu1/drivers/mmc/host/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mmc/host/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -83,7 +83,7 @@ config MMC_RICOH_MMC
 
 config MMC_SDHCI_OF
 	tristate "SDHCI support on OpenFirmware platforms"
-	depends on MMC_SDHCI && PPC_OF
+	depends on MMC_SDHCI && OF
 	help
 	  This selects the OF support for Secure Digital Host Controller
 	  Interfaces.
@@ -93,6 +93,7 @@ config MMC_SDHCI_OF
 config MMC_SDHCI_OF_ESDHC
 	bool "SDHCI OF support for the Freescale eSDHC controller"
 	depends on MMC_SDHCI_OF
+	depends on PPC_OF
 	select MMC_SDHCI_BIG_ENDIAN_32BIT_BYTE_SWAPPER
 	help
 	  This selects the Freescale eSDHC controller support.
@@ -102,6 +103,7 @@ config MMC_SDHCI_OF_ESDHC
 config MMC_SDHCI_OF_HLWD
 	bool "SDHCI OF support for the Nintendo Wii SDHCI controllers"
 	depends on MMC_SDHCI_OF
+	depends on PPC_OF
 	select MMC_SDHCI_BIG_ENDIAN_32BIT_BYTE_SWAPPER
 	help
 	  This selects the Secure Digital Host Controller Interface (SDHCI)
@@ -140,6 +142,27 @@ config MMC_SDHCI_ESDHC_IMX
 
 	  If unsure, say N.
 
+config MMC_SDHCI_DOVE
+	bool "SDHCI support on Marvell's Dove SoC"
+	depends on ARCH_DOVE
+	depends on MMC_SDHCI_PLTFM
+	select MMC_SDHCI_IO_ACCESSORS
+	help
+	  This selects the Secure Digital Host Controller Interface in
+	  Marvell's Dove SoC.
+
+	  If unsure, say N.
+
+config MMC_SDHCI_TEGRA
+	tristate "SDHCI platform support for the Tegra SD/MMC Controller"
+	depends on MMC_SDHCI_PLTFM && ARCH_TEGRA
+	select MMC_SDHCI_IO_ACCESSORS
+	help
+	  This selects the Tegra SD/MMC controller. If you have a Tegra
+	  platform with SD or MMC devices, say Y or M here.
+
+	  If unsure, say N.
+
 config MMC_SDHCI_S3C
 	tristate "SDHCI support on Samsung S3C SoC"
 	depends on MMC_SDHCI && PLAT_SAMSUNG
@@ -458,11 +481,27 @@ config SDH_BFIN_MISSING_CMD_PULLUP_WORKA
 	help
 	  If you say yes here SD-Cards may work on the EZkit.
 
+config MMC_DW
+	tristate "Synopsys DesignWare Memory Card Interface"
+	depends on ARM
+	help
+	  This selects support for the Synopsys DesignWare Mobile Storage IP
+	  block, this provides host support for SD and MMC interfaces, in both
+	  PIO and external DMA modes.
+
+config MMC_DW_IDMAC
+	bool "Internal DMAC interface"
+	depends on MMC_DW
+	help
+	  This selects support for the internal DMAC block within the Synopsys
+	  Designware Mobile Storage IP block. This disables the external DMA
+	  interface.
+
 config MMC_SH_MMCIF
 	tristate "SuperH Internal MMCIF support"
 	depends on MMC_BLOCK && (SUPERH || ARCH_SHMOBILE)
 	help
-	  This selects the MMC Host Interface controler (MMCIF).
+	  This selects the MMC Host Interface controller (MMCIF).
 
 	  This driver supports MMCIF in sh7724/sh7757/sh7372.
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/mmc/host/Makefile linux-libre-2.6.38-gnu1/drivers/mmc/host/Makefile
--- linux-libre-2.6.37-gnu1/drivers/mmc/host/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mmc/host/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -31,6 +31,7 @@ obj-$(CONFIG_MMC_TMIO)		+= tmio_mmc.o
 obj-$(CONFIG_MMC_CB710)	+= cb710-mmc.o
 obj-$(CONFIG_MMC_VIA_SDMMC)	+= via-sdmmc.o
 obj-$(CONFIG_SDH_BFIN)		+= bfin_sdh.o
+obj-$(CONFIG_MMC_DW)		+= dw_mmc.o
 obj-$(CONFIG_MMC_SH_MMCIF)	+= sh_mmcif.o
 obj-$(CONFIG_MMC_JZ4740)	+= jz4740_mmc.o
 obj-$(CONFIG_MMC_USHC)		+= ushc.o
@@ -39,6 +40,8 @@ obj-$(CONFIG_MMC_SDHCI_PLTFM)			+= sdhci
 sdhci-platform-y				:= sdhci-pltfm.o
 sdhci-platform-$(CONFIG_MMC_SDHCI_CNS3XXX)	+= sdhci-cns3xxx.o
 sdhci-platform-$(CONFIG_MMC_SDHCI_ESDHC_IMX)	+= sdhci-esdhc-imx.o
+sdhci-platform-$(CONFIG_MMC_SDHCI_DOVE)		+= sdhci-dove.o
+sdhci-platform-$(CONFIG_MMC_SDHCI_TEGRA)	+= sdhci-tegra.o
 
 obj-$(CONFIG_MMC_SDHCI_OF)	+= sdhci-of.o
 sdhci-of-y				:= sdhci-of-core.o
diff -druNp linux-libre-2.6.37-gnu1/drivers/mmc/host/mmci.c linux-libre-2.6.38-gnu1/drivers/mmc/host/mmci.c
--- linux-libre-2.6.37-gnu1/drivers/mmc/host/mmci.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mmc/host/mmci.c	2011-03-14 21:20:32.000000000 -0400
@@ -14,11 +14,13 @@
 #include <linux/ioport.h>
 #include <linux/device.h>
 #include <linux/interrupt.h>
+#include <linux/kernel.h>
 #include <linux/delay.h>
 #include <linux/err.h>
 #include <linux/highmem.h>
 #include <linux/log2.h>
 #include <linux/mmc/host.h>
+#include <linux/mmc/card.h>
 #include <linux/amba/bus.h>
 #include <linux/clk.h>
 #include <linux/scatterlist.h>
@@ -45,6 +47,8 @@ static unsigned int fmax = 515633;
  *	      is asserted (likewise for RX)
  * @fifohalfsize: number of bytes that can be written when MCI_TXFIFOHALFEMPTY
  *		  is asserted (likewise for RX)
+ * @sdio: variant supports SDIO
+ * @st_clkdiv: true if using a ST-specific clock divider algorithm
  */
 struct variant_data {
 	unsigned int		clkreg;
@@ -52,6 +56,8 @@ struct variant_data {
 	unsigned int		datalength_bits;
 	unsigned int		fifosize;
 	unsigned int		fifohalfsize;
+	bool			sdio;
+	bool			st_clkdiv;
 };
 
 static struct variant_data variant_arm = {
@@ -65,6 +71,7 @@ static struct variant_data variant_u300
 	.fifohalfsize		= 8 * 4,
 	.clkreg_enable		= 1 << 13, /* HWFCEN */
 	.datalength_bits	= 16,
+	.sdio			= true,
 };
 
 static struct variant_data variant_ux500 = {
@@ -73,7 +80,10 @@ static struct variant_data variant_ux500
 	.clkreg			= MCI_CLK_ENABLE,
 	.clkreg_enable		= 1 << 14, /* HWFCEN */
 	.datalength_bits	= 24,
+	.sdio			= true,
+	.st_clkdiv		= true,
 };
+
 /*
  * This must be called with host->lock held
  */
@@ -86,7 +96,22 @@ static void mmci_set_clkreg(struct mmci_
 		if (desired >= host->mclk) {
 			clk = MCI_CLK_BYPASS;
 			host->cclk = host->mclk;
+		} else if (variant->st_clkdiv) {
+			/*
+			 * DB8500 TRM says f = mclk / (clkdiv + 2)
+			 * => clkdiv = (mclk / f) - 2
+			 * Round the divider up so we don't exceed the max
+			 * frequency
+			 */
+			clk = DIV_ROUND_UP(host->mclk, desired) - 2;
+			if (clk >= 256)
+				clk = 255;
+			host->cclk = host->mclk / (clk + 2);
 		} else {
+			/*
+			 * PL180 TRM says f = mclk / (2 * (clkdiv + 1))
+			 * => clkdiv = mclk / (2 * f) - 1
+			 */
 			clk = host->mclk / (2 * desired) - 1;
 			if (clk >= 256)
 				clk = 255;
@@ -129,10 +154,26 @@ mmci_request_end(struct mmci_host *host,
 	spin_lock(&host->lock);
 }
 
+static void mmci_set_mask1(struct mmci_host *host, unsigned int mask)
+{
+	void __iomem *base = host->base;
+
+	if (host->singleirq) {
+		unsigned int mask0 = readl(base + MMCIMASK0);
+
+		mask0 &= ~MCI_IRQ1MASK;
+		mask0 |= mask;
+
+		writel(mask0, base + MMCIMASK0);
+	}
+
+	writel(mask, base + MMCIMASK1);
+}
+
 static void mmci_stop_data(struct mmci_host *host)
 {
 	writel(0, host->base + MMCIDATACTRL);
-	writel(0, host->base + MMCIMASK1);
+	mmci_set_mask1(host, 0);
 	host->data = NULL;
 }
 
@@ -196,9 +237,14 @@ static void mmci_start_data(struct mmci_
 		irqmask = MCI_TXFIFOHALFEMPTYMASK;
 	}
 
+	/* The ST Micro variants has a special bit to enable SDIO */
+	if (variant->sdio && host->mmc->card)
+		if (mmc_card_sdio(host->mmc->card))
+			datactrl |= MCI_ST_DPSM_SDIOEN;
+
 	writel(datactrl, base + MMCIDATACTRL);
 	writel(readl(base + MMCIMASK0) & ~MCI_DATAENDMASK, base + MMCIMASK0);
-	writel(irqmask, base + MMCIMASK1);
+	mmci_set_mask1(host, irqmask);
 }
 
 static void
@@ -233,29 +279,26 @@ static void
 mmci_data_irq(struct mmci_host *host, struct mmc_data *data,
 	      unsigned int status)
 {
-	if (status & MCI_DATABLOCKEND) {
-		host->data_xfered += data->blksz;
-#ifdef CONFIG_ARCH_U300
-		/*
-		 * On the U300 some signal or other is
-		 * badly routed so that a data write does
-		 * not properly terminate with a MCI_DATAEND
-		 * status flag. This quirk will make writes
-		 * work again.
-		 */
-		if (data->flags & MMC_DATA_WRITE)
-			status |= MCI_DATAEND;
-#endif
-	}
+	/* First check for errors */
 	if (status & (MCI_DATACRCFAIL|MCI_DATATIMEOUT|MCI_TXUNDERRUN|MCI_RXOVERRUN)) {
+		u32 remain, success;
+
+		/* Calculate how far we are into the transfer */
+		remain = readl(host->base + MMCIDATACNT);
+		success = data->blksz * data->blocks - remain;
+
 		dev_dbg(mmc_dev(host->mmc), "MCI ERROR IRQ (status %08x)\n", status);
-		if (status & MCI_DATACRCFAIL)
+		if (status & MCI_DATACRCFAIL) {
+			/* Last block was not successful */
+			host->data_xfered = round_down(success - 1, data->blksz);
 			data->error = -EILSEQ;
-		else if (status & MCI_DATATIMEOUT)
+		} else if (status & MCI_DATATIMEOUT) {
+			host->data_xfered = round_down(success, data->blksz);
 			data->error = -ETIMEDOUT;
-		else if (status & (MCI_TXUNDERRUN|MCI_RXOVERRUN))
+		} else if (status & (MCI_TXUNDERRUN|MCI_RXOVERRUN)) {
+			host->data_xfered = round_down(success, data->blksz);
 			data->error = -EIO;
-		status |= MCI_DATAEND;
+		}
 
 		/*
 		 * We hit an error condition.  Ensure that any data
@@ -273,9 +316,17 @@ mmci_data_irq(struct mmci_host *host, st
 			local_irq_restore(flags);
 		}
 	}
-	if (status & MCI_DATAEND) {
+
+	if (status & MCI_DATABLOCKEND)
+		dev_err(mmc_dev(host->mmc), "stray MCI_DATABLOCKEND interrupt\n");
+
+	if (status & MCI_DATAEND || data->error) {
 		mmci_stop_data(host);
 
+		if (!data->error)
+			/* The error clause is handled above, success! */
+			host->data_xfered += data->blksz * data->blocks;
+
 		if (!data->stop) {
 			mmci_request_end(host, data->mrq);
 		} else {
@@ -292,15 +343,15 @@ mmci_cmd_irq(struct mmci_host *host, str
 
 	host->cmd = NULL;
 
-	cmd->resp[0] = readl(base + MMCIRESPONSE0);
-	cmd->resp[1] = readl(base + MMCIRESPONSE1);
-	cmd->resp[2] = readl(base + MMCIRESPONSE2);
-	cmd->resp[3] = readl(base + MMCIRESPONSE3);
-
 	if (status & MCI_CMDTIMEOUT) {
 		cmd->error = -ETIMEDOUT;
 	} else if (status & MCI_CMDCRCFAIL && cmd->flags & MMC_RSP_CRC) {
 		cmd->error = -EILSEQ;
+	} else {
+		cmd->resp[0] = readl(base + MMCIRESPONSE0);
+		cmd->resp[1] = readl(base + MMCIRESPONSE1);
+		cmd->resp[2] = readl(base + MMCIRESPONSE2);
+		cmd->resp[3] = readl(base + MMCIRESPONSE3);
 	}
 
 	if (!cmd->data || cmd->error) {
@@ -356,7 +407,32 @@ static int mmci_pio_write(struct mmci_ho
 			 variant->fifosize : variant->fifohalfsize;
 		count = min(remain, maxcnt);
 
-		writesl(base + MMCIFIFO, ptr, count >> 2);
+		/*
+		 * The ST Micro variant for SDIO transfer sizes
+		 * less then 8 bytes should have clock H/W flow
+		 * control disabled.
+		 */
+		if (variant->sdio &&
+		    mmc_card_sdio(host->mmc->card)) {
+			if (count < 8)
+				writel(readl(host->base + MMCICLOCK) &
+					~variant->clkreg_enable,
+					host->base + MMCICLOCK);
+			else
+				writel(readl(host->base + MMCICLOCK) |
+					variant->clkreg_enable,
+					host->base + MMCICLOCK);
+		}
+
+		/*
+		 * SDIO especially may want to send something that is
+		 * not divisible by 4 (as opposed to card sectors
+		 * etc), and the FIFO only accept full 32-bit writes.
+		 * So compensate by adding +3 on the count, a single
+		 * byte become a 32bit write, 7 bytes will be two
+		 * 32bit writes etc.
+		 */
+		writesl(base + MMCIFIFO, ptr, (count + 3) >> 2);
 
 		ptr += count;
 		remain -= count;
@@ -437,7 +513,7 @@ static irqreturn_t mmci_pio_irq(int irq,
 	 * "any data available" mode.
 	 */
 	if (status & MCI_RXACTIVE && host->size < variant->fifosize)
-		writel(MCI_RXDATAAVLBLMASK, base + MMCIMASK1);
+		mmci_set_mask1(host, MCI_RXDATAAVLBLMASK);
 
 	/*
 	 * If we run out of data, disable the data IRQs; this
@@ -446,7 +522,7 @@ static irqreturn_t mmci_pio_irq(int irq,
 	 * stops us racing with our data end IRQ.
 	 */
 	if (host->size == 0) {
-		writel(0, base + MMCIMASK1);
+		mmci_set_mask1(host, 0);
 		writel(readl(base + MMCIMASK0) | MCI_DATAENDMASK, base + MMCIMASK0);
 	}
 
@@ -469,6 +545,14 @@ static irqreturn_t mmci_irq(int irq, voi
 		struct mmc_data *data;
 
 		status = readl(host->base + MMCISTATUS);
+
+		if (host->singleirq) {
+			if (status & readl(host->base + MMCIMASK1))
+				mmci_pio_irq(irq, dev_id);
+
+			status &= ~MCI_IRQ1MASK;
+		}
+
 		status &= readl(host->base + MMCIMASK0);
 		writel(status, host->base + MMCICLEAR);
 
@@ -806,20 +890,25 @@ static int __devinit mmci_probe(struct a
 	if (ret)
 		goto unmap;
 
-	ret = request_irq(dev->irq[1], mmci_pio_irq, IRQF_SHARED, DRIVER_NAME " (pio)", host);
-	if (ret)
-		goto irq0_free;
+	if (dev->irq[1] == NO_IRQ)
+		host->singleirq = true;
+	else {
+		ret = request_irq(dev->irq[1], mmci_pio_irq, IRQF_SHARED,
+				  DRIVER_NAME " (pio)", host);
+		if (ret)
+			goto irq0_free;
+	}
 
 	writel(MCI_IRQENABLE, host->base + MMCIMASK0);
 
 	amba_set_drvdata(dev, mmc);
 
-	mmc_add_host(mmc);
-
-	dev_info(&dev->dev, "%s: MMCI rev %x cfg %02x at 0x%016llx irq %d,%d\n",
-		mmc_hostname(mmc), amba_rev(dev), amba_config(dev),
+	dev_info(&dev->dev, "%s: PL%03x rev%u at 0x%08llx irq %d,%d\n",
+		mmc_hostname(mmc), amba_part(dev), amba_rev(dev),
 		(unsigned long long)dev->res.start, dev->irq[0], dev->irq[1]);
 
+	mmc_add_host(mmc);
+
 	return 0;
 
  irq0_free:
@@ -864,7 +953,8 @@ static int __devexit mmci_remove(struct
 		writel(0, host->base + MMCIDATACTRL);
 
 		free_irq(dev->irq[0], host);
-		free_irq(dev->irq[1], host);
+		if (!host->singleirq)
+			free_irq(dev->irq[1], host);
 
 		if (host->gpio_wp != -ENOSYS)
 			gpio_free(host->gpio_wp);
diff -druNp linux-libre-2.6.37-gnu1/drivers/mmc/host/mmci.h linux-libre-2.6.38-gnu1/drivers/mmc/host/mmci.h
--- linux-libre-2.6.37-gnu1/drivers/mmc/host/mmci.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mmc/host/mmci.h	2011-03-14 21:20:32.000000000 -0400
@@ -137,7 +137,12 @@
 #define MCI_IRQENABLE	\
 	(MCI_CMDCRCFAILMASK|MCI_DATACRCFAILMASK|MCI_CMDTIMEOUTMASK|	\
 	MCI_DATATIMEOUTMASK|MCI_TXUNDERRUNMASK|MCI_RXOVERRUNMASK|	\
-	MCI_CMDRESPENDMASK|MCI_CMDSENTMASK|MCI_DATABLOCKENDMASK)
+	MCI_CMDRESPENDMASK|MCI_CMDSENTMASK)
+
+/* These interrupts are directed to IRQ1 when two IRQ lines are available */
+#define MCI_IRQ1MASK \
+	(MCI_RXFIFOHALFFULLMASK | MCI_RXDATAAVLBLMASK | \
+	 MCI_TXFIFOHALFEMPTYMASK)
 
 #define NR_SG		16
 
@@ -154,6 +159,7 @@ struct mmci_host {
 	int			gpio_cd;
 	int			gpio_wp;
 	int			gpio_cd_irq;
+	bool			singleirq;
 
 	unsigned int		data_xfered;
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/mmc/host/msm_sdcc.c linux-libre-2.6.38-gnu1/drivers/mmc/host/msm_sdcc.c
--- linux-libre-2.6.37-gnu1/drivers/mmc/host/msm_sdcc.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mmc/host/msm_sdcc.c	2011-03-14 21:20:32.000000000 -0400
@@ -44,6 +44,7 @@
 #include <mach/mmc.h>
 #include <mach/msm_iomap.h>
 #include <mach/dma.h>
+#include <mach/clk.h>
 
 #include "msm_sdcc.h"
 
@@ -126,6 +127,40 @@ static void
 msmsdcc_start_command(struct msmsdcc_host *host, struct mmc_command *cmd,
 		      u32 c);
 
+static void msmsdcc_reset_and_restore(struct msmsdcc_host *host)
+{
+	u32	mci_clk = 0;
+	u32	mci_mask0 = 0;
+	int	ret = 0;
+
+	/* Save the controller state */
+	mci_clk = readl(host->base + MMCICLOCK);
+	mci_mask0 = readl(host->base + MMCIMASK0);
+
+	/* Reset the controller */
+	ret = clk_reset(host->clk, CLK_RESET_ASSERT);
+	if (ret)
+		pr_err("%s: Clock assert failed at %u Hz with err %d\n",
+				mmc_hostname(host->mmc), host->clk_rate, ret);
+
+	ret = clk_reset(host->clk, CLK_RESET_DEASSERT);
+	if (ret)
+		pr_err("%s: Clock deassert failed at %u Hz with err %d\n",
+				mmc_hostname(host->mmc), host->clk_rate, ret);
+
+	pr_info("%s: Controller has been re-initialiazed\n",
+			mmc_hostname(host->mmc));
+
+	/* Restore the contoller state */
+	writel(host->pwr, host->base + MMCIPOWER);
+	writel(mci_clk, host->base + MMCICLOCK);
+	writel(mci_mask0, host->base + MMCIMASK0);
+	ret = clk_set_rate(host->clk, host->clk_rate);
+	if (ret)
+		pr_err("%s: Failed to set clk rate %u Hz (%d)\n",
+				mmc_hostname(host->mmc), host->clk_rate, ret);
+}
+
 static void
 msmsdcc_request_end(struct msmsdcc_host *host, struct mmc_request *mrq)
 {
@@ -155,7 +190,7 @@ static void
 msmsdcc_stop_data(struct msmsdcc_host *host)
 {
 	host->curr.data = NULL;
-	host->curr.got_dataend = host->curr.got_datablkend = 0;
+	host->curr.got_dataend = 0;
 }
 
 uint32_t msmsdcc_fifo_addr(struct msmsdcc_host *host)
@@ -189,42 +224,42 @@ msmsdcc_dma_exec_func(struct msm_dmov_cm
 }
 
 static void
-msmsdcc_dma_complete_func(struct msm_dmov_cmd *cmd,
-			  unsigned int result,
-			  struct msm_dmov_errdata *err)
+msmsdcc_dma_complete_tlet(unsigned long data)
 {
-	struct msmsdcc_dma_data	*dma_data =
-		container_of(cmd, struct msmsdcc_dma_data, hdr);
-	struct msmsdcc_host	*host = dma_data->host;
+	struct msmsdcc_host *host = (struct msmsdcc_host *)data;
 	unsigned long		flags;
 	struct mmc_request	*mrq;
+	struct msm_dmov_errdata err;
 
 	spin_lock_irqsave(&host->lock, flags);
 	host->dma.active = 0;
 
+	err = host->dma.err;
 	mrq = host->curr.mrq;
 	BUG_ON(!mrq);
 	WARN_ON(!mrq->data);
 
-	if (!(result & DMOV_RSLT_VALID)) {
+	if (!(host->dma.result & DMOV_RSLT_VALID)) {
 		pr_err("msmsdcc: Invalid DataMover result\n");
 		goto out;
 	}
 
-	if (result & DMOV_RSLT_DONE) {
+	if (host->dma.result & DMOV_RSLT_DONE) {
 		host->curr.data_xfered = host->curr.xfer_size;
 	} else {
 		/* Error or flush  */
-		if (result & DMOV_RSLT_ERROR)
+		if (host->dma.result & DMOV_RSLT_ERROR)
 			pr_err("%s: DMA error (0x%.8x)\n",
-			       mmc_hostname(host->mmc), result);
-		if (result & DMOV_RSLT_FLUSH)
+			       mmc_hostname(host->mmc), host->dma.result);
+		if (host->dma.result & DMOV_RSLT_FLUSH)
 			pr_err("%s: DMA channel flushed (0x%.8x)\n",
-			       mmc_hostname(host->mmc), result);
-		if (err)
-			pr_err("Flush data: %.8x %.8x %.8x %.8x %.8x %.8x\n",
-			       err->flush[0], err->flush[1], err->flush[2],
-			       err->flush[3], err->flush[4], err->flush[5]);
+			       mmc_hostname(host->mmc), host->dma.result);
+
+		pr_err("Flush data: %.8x %.8x %.8x %.8x %.8x %.8x\n",
+		       err.flush[0], err.flush[1], err.flush[2],
+		       err.flush[3], err.flush[4], err.flush[5]);
+
+		msmsdcc_reset_and_restore(host);
 		if (!mrq->data->error)
 			mrq->data->error = -EIO;
 	}
@@ -242,8 +277,7 @@ msmsdcc_dma_complete_func(struct msm_dmo
 	host->dma.sg = NULL;
 	host->dma.busy = 0;
 
-	if ((host->curr.got_dataend && host->curr.got_datablkend)
-	     || mrq->data->error) {
+	if (host->curr.got_dataend || mrq->data->error) {
 
 		/*
 		 * If we've already gotten our DATAEND / DATABLKEND
@@ -273,6 +307,22 @@ out:
 	return;
 }
 
+static void
+msmsdcc_dma_complete_func(struct msm_dmov_cmd *cmd,
+			  unsigned int result,
+			  struct msm_dmov_errdata *err)
+{
+	struct msmsdcc_dma_data	*dma_data =
+		container_of(cmd, struct msmsdcc_dma_data, hdr);
+	struct msmsdcc_host *host = dma_data->host;
+
+	dma_data->result = result;
+	if (err)
+		memcpy(&dma_data->err, err, sizeof(struct msm_dmov_errdata));
+
+	tasklet_schedule(&host->dma_tlet);
+}
+
 static int validate_dma(struct msmsdcc_host *host, struct mmc_data *data)
 {
 	if (host->dma.channel == -1)
@@ -333,14 +383,30 @@ static int msmsdcc_config_dma(struct msm
 	host->curr.user_pages = 0;
 
 	box = &nc->cmd[0];
-	for (i = 0; i < host->dma.num_ents; i++) {
-		box->cmd = CMD_MODE_BOX;
 
-	/* Initialize sg dma address */
-	sg->dma_address = page_to_dma(mmc_dev(host->mmc), sg_page(sg))
-				+ sg->offset;
+	/* location of command block must be 64 bit aligned */
+	BUG_ON(host->dma.cmd_busaddr & 0x07);
 
-	if (i == (host->dma.num_ents - 1))
+	nc->cmdptr = (host->dma.cmd_busaddr >> 3) | CMD_PTR_LP;
+	host->dma.hdr.cmdptr = DMOV_CMD_PTR_LIST |
+			       DMOV_CMD_ADDR(host->dma.cmdptr_busaddr);
+	host->dma.hdr.complete_func = msmsdcc_dma_complete_func;
+
+	n = dma_map_sg(mmc_dev(host->mmc), host->dma.sg,
+			host->dma.num_ents, host->dma.dir);
+	if (n == 0) {
+		printk(KERN_ERR "%s: Unable to map in all sg elements\n",
+			mmc_hostname(host->mmc));
+		host->dma.sg = NULL;
+		host->dma.num_ents = 0;
+		return -ENOMEM;
+	}
+
+	for_each_sg(host->dma.sg, sg, n, i) {
+
+		box->cmd = CMD_MODE_BOX;
+
+		if (i == n - 1)
 			box->cmd |= CMD_LC;
 		rows = (sg_dma_len(sg) % MCI_FIFOSIZE) ?
 			(sg_dma_len(sg) / MCI_FIFOSIZE) + 1 :
@@ -368,27 +434,6 @@ static int msmsdcc_config_dma(struct msm
 			box->cmd |= CMD_DST_CRCI(crci);
 		}
 		box++;
-		sg++;
-	}
-
-	/* location of command block must be 64 bit aligned */
-	BUG_ON(host->dma.cmd_busaddr & 0x07);
-
-	nc->cmdptr = (host->dma.cmd_busaddr >> 3) | CMD_PTR_LP;
-	host->dma.hdr.cmdptr = DMOV_CMD_PTR_LIST |
-			       DMOV_CMD_ADDR(host->dma.cmdptr_busaddr);
-	host->dma.hdr.complete_func = msmsdcc_dma_complete_func;
-
-	n = dma_map_sg(mmc_dev(host->mmc), host->dma.sg,
-			host->dma.num_ents, host->dma.dir);
-/* dsb inside dma_map_sg will write nc out to mem as well */
-
-	if (n != host->dma.num_ents) {
-		printk(KERN_ERR "%s: Unable to map in all sg elements\n",
-			mmc_hostname(host->mmc));
-		host->dma.sg = NULL;
-		host->dma.num_ents = 0;
-		return -ENOMEM;
 	}
 
 	return 0;
@@ -424,6 +469,11 @@ msmsdcc_start_command_deferred(struct ms
 	      (cmd->opcode == 53))
 		*c |= MCI_CSPM_DATCMD;
 
+	if (host->prog_scan && (cmd->opcode == 12)) {
+		*c |= MCI_CPSM_PROGENA;
+		host->prog_enable = true;
+	}
+
 	if (cmd == cmd->mrq->stop)
 		*c |= MCI_CSPM_MCIABORT;
 
@@ -450,7 +500,6 @@ msmsdcc_start_data(struct msmsdcc_host *
 	host->curr.xfer_remain = host->curr.xfer_size;
 	host->curr.data_xfered = 0;
 	host->curr.got_dataend = 0;
-	host->curr.got_datablkend = 0;
 
 	memset(&host->pio, 0, sizeof(host->pio));
 
@@ -494,6 +543,8 @@ msmsdcc_start_data(struct msmsdcc_host *
 			host->cmd_c = c;
 		}
 		msm_dmov_enqueue_cmd(host->dma.channel, &host->dma.hdr);
+		if (data->flags & MMC_DATA_WRITE)
+			host->prog_scan = true;
 	} else {
 		msmsdcc_writel(host, timeout, MMCIDATATIMER);
 
@@ -555,6 +606,9 @@ msmsdcc_pio_read(struct msmsdcc_host *ho
 	uint32_t	*ptr = (uint32_t *) buffer;
 	int		count = 0;
 
+	if (remain % 4)
+		remain = ((remain >> 2) + 1) << 2;
+
 	while (msmsdcc_readl(host, MMCISTATUS) & MCI_RXDATAAVLBL) {
 		*ptr = msmsdcc_readl(host, MMCIFIFO + (count % MCI_FIFOSIZE));
 		ptr++;
@@ -575,13 +629,14 @@ msmsdcc_pio_write(struct msmsdcc_host *h
 	char *ptr = buffer;
 
 	do {
-		unsigned int count, maxcnt;
+		unsigned int count, maxcnt, sz;
 
 		maxcnt = status & MCI_TXFIFOEMPTY ? MCI_FIFOSIZE :
 						    MCI_FIFOHALFSIZE;
 		count = min(remain, maxcnt);
 
-		writesl(base + MMCIFIFO, ptr, count >> 2);
+		sz = count % 4 ? (count >> 2) + 1 : (count >> 2);
+		writesl(base + MMCIFIFO, ptr, sz);
 		ptr += count;
 		remain -= count;
 
@@ -702,10 +757,26 @@ static void msmsdcc_do_cmdirq(struct msm
 			msm_dmov_stop_cmd(host->dma.channel,
 					  &host->dma.hdr, 0);
 		else if (host->curr.data) { /* Non DMA */
+			msmsdcc_reset_and_restore(host);
 			msmsdcc_stop_data(host);
 			msmsdcc_request_end(host, cmd->mrq);
-		} else /* host->data == NULL */
-			msmsdcc_request_end(host, cmd->mrq);
+		} else { /* host->data == NULL */
+			if (!cmd->error && host->prog_enable) {
+				if (status & MCI_PROGDONE) {
+					host->prog_scan = false;
+					host->prog_enable = false;
+					msmsdcc_request_end(host, cmd->mrq);
+				} else {
+					host->curr.cmd = cmd;
+				}
+			} else {
+				if (host->prog_enable) {
+					host->prog_scan = false;
+					host->prog_enable = false;
+				}
+				msmsdcc_request_end(host, cmd->mrq);
+			}
+		}
 	} else if (cmd->data)
 		if (!(cmd->data->flags & MMC_DATA_READ))
 			msmsdcc_start_data(host, cmd->data,
@@ -719,7 +790,7 @@ msmsdcc_handle_irq_data(struct msmsdcc_h
 	struct mmc_data *data = host->curr.data;
 
 	if (status & (MCI_CMDSENT | MCI_CMDRESPEND | MCI_CMDCRCFAIL |
-	              MCI_CMDTIMEOUT) && host->curr.cmd) {
+			MCI_CMDTIMEOUT | MCI_PROGDONE) && host->curr.cmd) {
 		msmsdcc_do_cmdirq(host, status);
 	}
 
@@ -735,6 +806,7 @@ msmsdcc_handle_irq_data(struct msmsdcc_h
 			msm_dmov_stop_cmd(host->dma.channel,
 					  &host->dma.hdr, 0);
 		else {
+			msmsdcc_reset_and_restore(host);
 			if (host->curr.data)
 				msmsdcc_stop_data(host);
 			if (!data->stop)
@@ -748,14 +820,10 @@ msmsdcc_handle_irq_data(struct msmsdcc_h
 	if (!host->curr.got_dataend && (status & MCI_DATAEND))
 		host->curr.got_dataend = 1;
 
-	if (!host->curr.got_datablkend && (status & MCI_DATABLOCKEND))
-		host->curr.got_datablkend = 1;
-
 	/*
 	 * If DMA is still in progress, we complete via the completion handler
 	 */
-	if (host->curr.got_dataend && host->curr.got_datablkend &&
-	    !host->dma.busy) {
+	if (host->curr.got_dataend && !host->dma.busy) {
 		/*
 		 * There appears to be an issue in the controller where
 		 * if you request a small block transfer (< fifo size),
@@ -792,8 +860,7 @@ msmsdcc_irq(int irq, void *dev_id)
 
 	do {
 		status = msmsdcc_readl(host, MMCISTATUS);
-		status &= (msmsdcc_readl(host, MMCIMASK0) |
-					      MCI_DATABLOCKENDMASK);
+		status &= msmsdcc_readl(host, MMCIMASK0);
 		msmsdcc_writel(host, status, MMCICLEAR);
 
 		if (status & MCI_SDIOINTR)
@@ -1118,6 +1185,9 @@ msmsdcc_probe(struct platform_device *pd
 	host->dmares = dmares;
 	spin_lock_init(&host->lock);
 
+	tasklet_init(&host->dma_tlet, msmsdcc_dma_complete_tlet,
+			(unsigned long)host);
+
 	/*
 	 * Setup DMA
 	 */
@@ -1256,9 +1326,6 @@ msmsdcc_probe(struct platform_device *pd
 	if (host->timer.function)
 		pr_info("%s: Polling status mode enabled\n", mmc_hostname(mmc));
 
-#if BUSCLK_PWRSAVE
-	msmsdcc_disable_clocks(host, 1);
-#endif
 	return 0;
  cmd_irq_free:
 	free_irq(cmd_irqres->start, host);
diff -druNp linux-libre-2.6.37-gnu1/drivers/mmc/host/msm_sdcc.h linux-libre-2.6.38-gnu1/drivers/mmc/host/msm_sdcc.h
--- linux-libre-2.6.37-gnu1/drivers/mmc/host/msm_sdcc.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mmc/host/msm_sdcc.h	2011-03-14 21:20:32.000000000 -0400
@@ -138,7 +138,7 @@
 #define MCI_IRQENABLE	\
 	(MCI_CMDCRCFAILMASK|MCI_DATACRCFAILMASK|MCI_CMDTIMEOUTMASK|	\
 	MCI_DATATIMEOUTMASK|MCI_TXUNDERRUNMASK|MCI_RXOVERRUNMASK|	\
-	MCI_CMDRESPENDMASK|MCI_CMDSENTMASK|MCI_DATAENDMASK)
+	MCI_CMDRESPENDMASK|MCI_CMDSENTMASK|MCI_DATAENDMASK|MCI_PROGDONEMASK)
 
 /*
  * The size of the FIFO in bytes.
@@ -172,6 +172,8 @@ struct msmsdcc_dma_data {
 	struct msmsdcc_host		*host;
 	int				busy; /* Set if DM is busy */
 	int				active;
+	unsigned int			result;
+	struct msm_dmov_errdata		err;
 };
 
 struct msmsdcc_pio_data {
@@ -188,7 +190,6 @@ struct msmsdcc_curr_req {
 	unsigned int		xfer_remain;	/* Bytes remaining to send */
 	unsigned int		data_xfered;	/* Bytes acked by BLKEND irq */
 	int			got_dataend;
-	int			got_datablkend;
 	int			user_pages;
 };
 
@@ -235,6 +236,7 @@ struct msmsdcc_host {
 	int			cmdpoll;
 	struct msmsdcc_stats	stats;
 
+	struct tasklet_struct	dma_tlet;
 	/* Command parameters */
 	unsigned int		cmd_timeout;
 	unsigned int		cmd_pio_irqmask;
@@ -242,6 +244,8 @@ struct msmsdcc_host {
 	struct mmc_command	*cmd_cmd;
 	u32			cmd_c;
 
+	bool prog_scan;
+	bool prog_enable;
 };
 
 #endif
diff -druNp linux-libre-2.6.37-gnu1/drivers/mmc/host/mxcmmc.c linux-libre-2.6.38-gnu1/drivers/mmc/host/mxcmmc.c
--- linux-libre-2.6.37-gnu1/drivers/mmc/host/mxcmmc.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mmc/host/mxcmmc.c	2011-03-14 21:20:32.000000000 -0400
@@ -31,6 +31,7 @@
 #include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/gpio.h>
+#include <linux/regulator/consumer.h>
 
 #include <asm/dma.h>
 #include <asm/irq.h>
@@ -141,10 +142,49 @@ struct mxcmci_host {
 
 	struct work_struct	datawork;
 	spinlock_t		lock;
+
+	struct regulator	*vcc;
 };
 
 static void mxcmci_set_clk_rate(struct mxcmci_host *host, unsigned int clk_ios);
 
+static inline void mxcmci_init_ocr(struct mxcmci_host *host)
+{
+	host->vcc = regulator_get(mmc_dev(host->mmc), "vmmc");
+
+	if (IS_ERR(host->vcc)) {
+		host->vcc = NULL;
+	} else {
+		host->mmc->ocr_avail = mmc_regulator_get_ocrmask(host->vcc);
+		if (host->pdata && host->pdata->ocr_avail)
+			dev_warn(mmc_dev(host->mmc),
+				"pdata->ocr_avail will not be used\n");
+	}
+
+	if (host->vcc == NULL) {
+		/* fall-back to platform data */
+		if (host->pdata && host->pdata->ocr_avail)
+			host->mmc->ocr_avail = host->pdata->ocr_avail;
+		else
+			host->mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
+	}
+}
+
+static inline void mxcmci_set_power(struct mxcmci_host *host,
+				    unsigned char power_mode,
+				    unsigned int vdd)
+{
+	if (host->vcc) {
+		if (power_mode == MMC_POWER_UP)
+			mmc_regulator_set_ocr(host->mmc, host->vcc, vdd);
+		else if (power_mode == MMC_POWER_OFF)
+			mmc_regulator_set_ocr(host->mmc, host->vcc, 0);
+	}
+
+	if (host->pdata && host->pdata->setpower)
+		host->pdata->setpower(mmc_dev(host->mmc), vdd);
+}
+
 static inline int mxcmci_use_dma(struct mxcmci_host *host)
 {
 	return host->do_dma;
@@ -680,9 +720,9 @@ static void mxcmci_set_ios(struct mmc_ho
 		host->cmdat &= ~CMD_DAT_CONT_BUS_WIDTH_4;
 
 	if (host->power_mode != ios->power_mode) {
-		if (host->pdata && host->pdata->setpower)
-			host->pdata->setpower(mmc_dev(mmc), ios->vdd);
+		mxcmci_set_power(host, ios->power_mode, ios->vdd);
 		host->power_mode = ios->power_mode;
+
 		if (ios->power_mode == MMC_POWER_ON)
 			host->cmdat |= CMD_DAT_CONT_INIT;
 	}
@@ -807,10 +847,7 @@ static int mxcmci_probe(struct platform_
 	host->pdata = pdev->dev.platform_data;
 	spin_lock_init(&host->lock);
 
-	if (host->pdata && host->pdata->ocr_avail)
-		mmc->ocr_avail = host->pdata->ocr_avail;
-	else
-		mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
+	mxcmci_init_ocr(host);
 
 	if (host->pdata && host->pdata->dat3_card_detect)
 		host->default_irq_mask =
@@ -915,6 +952,9 @@ static int mxcmci_remove(struct platform
 
 	mmc_remove_host(mmc);
 
+	if (host->vcc)
+		regulator_put(host->vcc);
+
 	if (host->pdata && host->pdata->exit)
 		host->pdata->exit(&pdev->dev, mmc);
 
@@ -927,7 +967,6 @@ static int mxcmci_remove(struct platform
 	clk_put(host->clk);
 
 	release_mem_region(host->res->start, resource_size(host->res));
-	release_resource(host->res);
 
 	mmc_free_host(mmc);
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/mmc/host/omap.c linux-libre-2.6.38-gnu1/drivers/mmc/host/omap.c
--- linux-libre-2.6.37-gnu1/drivers/mmc/host/omap.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mmc/host/omap.c	2011-03-14 21:20:32.000000000 -0400
@@ -173,6 +173,8 @@ struct mmc_omap_host {
 	struct omap_mmc_platform_data *pdata;
 };
 
+static struct workqueue_struct *mmc_omap_wq;
+
 static void mmc_omap_fclk_offdelay(struct mmc_omap_slot *slot)
 {
 	unsigned long tick_ns;
@@ -289,7 +291,7 @@ static void mmc_omap_release_slot(struct
 		host->next_slot = new_slot;
 		host->mmc = new_slot->mmc;
 		spin_unlock_irqrestore(&host->slot_lock, flags);
-		schedule_work(&host->slot_release_work);
+		queue_work(mmc_omap_wq, &host->slot_release_work);
 		return;
 	}
 
@@ -457,7 +459,7 @@ mmc_omap_xfer_done(struct mmc_omap_host
 	}
 
 	host->stop_data = data;
-	schedule_work(&host->send_stop_work);
+	queue_work(mmc_omap_wq, &host->send_stop_work);
 }
 
 static void
@@ -637,7 +639,7 @@ mmc_omap_cmd_timer(unsigned long data)
 		OMAP_MMC_WRITE(host, IE, 0);
 		disable_irq(host->irq);
 		host->abort = 1;
-		schedule_work(&host->cmd_abort_work);
+		queue_work(mmc_omap_wq, &host->cmd_abort_work);
 	}
 	spin_unlock_irqrestore(&host->slot_lock, flags);
 }
@@ -826,7 +828,7 @@ static irqreturn_t mmc_omap_irq(int irq,
 		host->abort = 1;
 		OMAP_MMC_WRITE(host, IE, 0);
 		disable_irq_nosync(host->irq);
-		schedule_work(&host->cmd_abort_work);
+		queue_work(mmc_omap_wq, &host->cmd_abort_work);
 		return IRQ_HANDLED;
 	}
 
@@ -1387,7 +1389,7 @@ static void mmc_omap_remove_slot(struct
 
 	tasklet_kill(&slot->cover_tasklet);
 	del_timer_sync(&slot->cover_timer);
-	flush_scheduled_work();
+	flush_workqueue(mmc_omap_wq);
 
 	mmc_remove_host(mmc);
 	mmc_free_host(mmc);
@@ -1608,12 +1610,22 @@ static struct platform_driver mmc_omap_d
 
 static int __init mmc_omap_init(void)
 {
-	return platform_driver_probe(&mmc_omap_driver, mmc_omap_probe);
+	int ret;
+
+	mmc_omap_wq = alloc_workqueue("mmc_omap", 0, 0);
+	if (!mmc_omap_wq)
+		return -ENOMEM;
+
+	ret = platform_driver_probe(&mmc_omap_driver, mmc_omap_probe);
+	if (ret)
+		destroy_workqueue(mmc_omap_wq);
+	return ret;
 }
 
 static void __exit mmc_omap_exit(void)
 {
 	platform_driver_unregister(&mmc_omap_driver);
+	destroy_workqueue(mmc_omap_wq);
 }
 
 module_init(mmc_omap_init);
diff -druNp linux-libre-2.6.37-gnu1/drivers/mmc/host/omap_hsmmc.c linux-libre-2.6.38-gnu1/drivers/mmc/host/omap_hsmmc.c
--- linux-libre-2.6.37-gnu1/drivers/mmc/host/omap_hsmmc.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mmc/host/omap_hsmmc.c	2011-03-14 21:20:32.000000000 -0400
@@ -2290,7 +2290,7 @@ static int omap_hsmmc_remove(struct plat
 		free_irq(host->irq, host);
 		if (mmc_slot(host).card_detect_irq)
 			free_irq(mmc_slot(host).card_detect_irq, host);
-		flush_scheduled_work();
+		flush_work_sync(&host->mmc_carddetect_work);
 
 		mmc_host_disable(host->mmc);
 		clk_disable(host->iclk);
diff -druNp linux-libre-2.6.37-gnu1/drivers/mmc/host/sdhci.c linux-libre-2.6.38-gnu1/drivers/mmc/host/sdhci.c
--- linux-libre-2.6.37-gnu1/drivers/mmc/host/sdhci.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mmc/host/sdhci.c	2011-03-14 21:20:32.000000000 -0400
@@ -23,6 +23,7 @@
 
 #include <linux/leds.h>
 
+#include <linux/mmc/mmc.h>
 #include <linux/mmc/host.h>
 
 #include "sdhci.h"
@@ -77,8 +78,11 @@ static void sdhci_dumpregs(struct sdhci_
 	printk(KERN_DEBUG DRIVER_NAME ": AC12 err: 0x%08x | Slot int: 0x%08x\n",
 		sdhci_readw(host, SDHCI_ACMD12_ERR),
 		sdhci_readw(host, SDHCI_SLOT_INT_STATUS));
-	printk(KERN_DEBUG DRIVER_NAME ": Caps:     0x%08x | Max curr: 0x%08x\n",
+	printk(KERN_DEBUG DRIVER_NAME ": Caps:     0x%08x | Caps_1:   0x%08x\n",
 		sdhci_readl(host, SDHCI_CAPABILITIES),
+		sdhci_readl(host, SDHCI_CAPABILITIES_1));
+	printk(KERN_DEBUG DRIVER_NAME ": Cmd:      0x%08x | Max curr: 0x%08x\n",
+		sdhci_readw(host, SDHCI_COMMAND),
 		sdhci_readl(host, SDHCI_MAX_CURRENT));
 
 	if (host->flags & SDHCI_USE_ADMA)
@@ -1518,7 +1522,11 @@ static void sdhci_data_irq(struct sdhci_
 
 	if (intmask & SDHCI_INT_DATA_TIMEOUT)
 		host->data->error = -ETIMEDOUT;
-	else if (intmask & (SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_END_BIT))
+	else if (intmask & SDHCI_INT_DATA_END_BIT)
+		host->data->error = -EILSEQ;
+	else if ((intmask & SDHCI_INT_DATA_CRC) &&
+		SDHCI_GET_CMD(sdhci_readw(host, SDHCI_COMMAND))
+			!= MMC_BUS_TEST_R)
 		host->data->error = -EILSEQ;
 	else if (intmask & SDHCI_INT_ADMA_ERROR) {
 		printk(KERN_ERR "%s: ADMA error\n", mmc_hostname(host->mmc));
@@ -1736,7 +1744,7 @@ EXPORT_SYMBOL_GPL(sdhci_alloc_host);
 int sdhci_add_host(struct sdhci_host *host)
 {
 	struct mmc_host *mmc;
-	unsigned int caps;
+	unsigned int caps, ocr_avail;
 	int ret;
 
 	WARN_ON(host == NULL);
@@ -1890,13 +1898,26 @@ int sdhci_add_host(struct sdhci_host *ho
 	    mmc_card_is_removable(mmc))
 		mmc->caps |= MMC_CAP_NEEDS_POLL;
 
-	mmc->ocr_avail = 0;
+	ocr_avail = 0;
 	if (caps & SDHCI_CAN_VDD_330)
-		mmc->ocr_avail |= MMC_VDD_32_33|MMC_VDD_33_34;
+		ocr_avail |= MMC_VDD_32_33 | MMC_VDD_33_34;
 	if (caps & SDHCI_CAN_VDD_300)
-		mmc->ocr_avail |= MMC_VDD_29_30|MMC_VDD_30_31;
+		ocr_avail |= MMC_VDD_29_30 | MMC_VDD_30_31;
 	if (caps & SDHCI_CAN_VDD_180)
-		mmc->ocr_avail |= MMC_VDD_165_195;
+		ocr_avail |= MMC_VDD_165_195;
+
+	mmc->ocr_avail = ocr_avail;
+	mmc->ocr_avail_sdio = ocr_avail;
+	if (host->ocr_avail_sdio)
+		mmc->ocr_avail_sdio &= host->ocr_avail_sdio;
+	mmc->ocr_avail_sd = ocr_avail;
+	if (host->ocr_avail_sd)
+		mmc->ocr_avail_sd &= host->ocr_avail_sd;
+	else /* normal SD controllers don't support 1.8V */
+		mmc->ocr_avail_sd &= ~MMC_VDD_165_195;
+	mmc->ocr_avail_mmc = ocr_avail;
+	if (host->ocr_avail_mmc)
+		mmc->ocr_avail_mmc &= host->ocr_avail_mmc;
 
 	if (mmc->ocr_avail == 0) {
 		printk(KERN_ERR "%s: Hardware doesn't report any "
@@ -1928,10 +1949,14 @@ int sdhci_add_host(struct sdhci_host *ho
 	 * of bytes. When doing hardware scatter/gather, each entry cannot
 	 * be larger than 64 KiB though.
 	 */
-	if (host->flags & SDHCI_USE_ADMA)
-		mmc->max_seg_size = 65536;
-	else
+	if (host->flags & SDHCI_USE_ADMA) {
+		if (host->quirks & SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC)
+			mmc->max_seg_size = 65535;
+		else
+			mmc->max_seg_size = 65536;
+	} else {
 		mmc->max_seg_size = mmc->max_req_size;
+	}
 
 	/*
 	 * Maximum block size. This varies from controller to controller and
diff -druNp linux-libre-2.6.37-gnu1/drivers/mmc/host/sdhci-dove.c linux-libre-2.6.38-gnu1/drivers/mmc/host/sdhci-dove.c
--- linux-libre-2.6.37-gnu1/drivers/mmc/host/sdhci-dove.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mmc/host/sdhci-dove.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,70 @@
+/*
+ * sdhci-dove.c Support for SDHCI on Marvell's Dove SoC
+ *
+ * Author: Saeed Bishara <saeed@marvell.com>
+ *	   Mike Rapoport <mike@compulab.co.il>
+ * Based on sdhci-cns3xxx.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.
+ *
+ * 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/io.h>
+#include <linux/mmc/host.h>
+
+#include "sdhci.h"
+#include "sdhci-pltfm.h"
+
+static u16 sdhci_dove_readw(struct sdhci_host *host, int reg)
+{
+	u16 ret;
+
+	switch (reg) {
+	case SDHCI_HOST_VERSION:
+	case SDHCI_SLOT_INT_STATUS:
+		/* those registers don't exist */
+		return 0;
+	default:
+		ret = readw(host->ioaddr + reg);
+	}
+	return ret;
+}
+
+static u32 sdhci_dove_readl(struct sdhci_host *host, int reg)
+{
+	u32 ret;
+
+	switch (reg) {
+	case SDHCI_CAPABILITIES:
+		ret = readl(host->ioaddr + reg);
+		/* Mask the support for 3.0V */
+		ret &= ~SDHCI_CAN_VDD_300;
+		break;
+	default:
+		ret = readl(host->ioaddr + reg);
+	}
+	return ret;
+}
+
+static struct sdhci_ops sdhci_dove_ops = {
+	.read_w	= sdhci_dove_readw,
+	.read_l	= sdhci_dove_readl,
+};
+
+struct sdhci_pltfm_data sdhci_dove_pdata = {
+	.ops	= &sdhci_dove_ops,
+	.quirks	= SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER |
+		  SDHCI_QUIRK_NO_BUSY_IRQ |
+		  SDHCI_QUIRK_BROKEN_TIMEOUT_VAL |
+		  SDHCI_QUIRK_FORCE_DMA,
+};
diff -druNp linux-libre-2.6.37-gnu1/drivers/mmc/host/sdhci.h linux-libre-2.6.38-gnu1/drivers/mmc/host/sdhci.h
--- linux-libre-2.6.37-gnu1/drivers/mmc/host/sdhci.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mmc/host/sdhci.h	2011-03-14 21:20:32.000000000 -0400
@@ -52,6 +52,7 @@
 #define  SDHCI_CMD_RESP_SHORT_BUSY 0x03
 
 #define SDHCI_MAKE_CMD(c, f) (((c & 0xff) << 8) | (f & 0xff))
+#define SDHCI_GET_CMD(c) ((c>>8) & 0x3f)
 
 #define SDHCI_RESPONSE		0x10
 
@@ -165,7 +166,7 @@
 #define  SDHCI_CAN_VDD_180	0x04000000
 #define  SDHCI_CAN_64BIT	0x10000000
 
-/* 44-47 reserved for more caps */
+#define SDHCI_CAPABILITIES_1	0x44
 
 #define SDHCI_MAX_CURRENT	0x48
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/mmc/host/sdhci-of-core.c linux-libre-2.6.38-gnu1/drivers/mmc/host/sdhci-of-core.c
--- linux-libre-2.6.37-gnu1/drivers/mmc/host/sdhci-of-core.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mmc/host/sdhci-of-core.c	2011-03-14 21:20:32.000000000 -0400
@@ -13,6 +13,7 @@
  * your option) any later version.
  */
 
+#include <linux/err.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/io.h>
@@ -20,8 +21,12 @@
 #include <linux/delay.h>
 #include <linux/of.h>
 #include <linux/of_platform.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
 #include <linux/mmc/host.h>
+#ifdef CONFIG_PPC
 #include <asm/machdep.h>
+#endif
 #include "sdhci-of.h"
 #include "sdhci.h"
 
@@ -112,7 +117,11 @@ static bool __devinit sdhci_of_wp_invert
 		return true;
 
 	/* Old device trees don't have the wp-inverted property. */
+#ifdef CONFIG_PPC
 	return machine_is(mpc837x_rdb) || machine_is(mpc837x_mds);
+#else
+	return false;
+#endif
 }
 
 static int __devinit sdhci_of_probe(struct platform_device *ofdev,
@@ -122,7 +131,7 @@ static int __devinit sdhci_of_probe(stru
 	struct sdhci_of_data *sdhci_of_data = match->data;
 	struct sdhci_host *host;
 	struct sdhci_of_host *of_host;
-	const u32 *clk;
+	const __be32 *clk;
 	int size;
 	int ret;
 
@@ -166,7 +175,7 @@ static int __devinit sdhci_of_probe(stru
 
 	clk = of_get_property(np, "clock-frequency", &size);
 	if (clk && size == sizeof(*clk) && *clk)
-		of_host->clock = *clk;
+		of_host->clock = be32_to_cpup(clk);
 
 	ret = sdhci_add_host(host);
 	if (ret)
diff -druNp linux-libre-2.6.37-gnu1/drivers/mmc/host/sdhci-pci.c linux-libre-2.6.38-gnu1/drivers/mmc/host/sdhci-pci.c
--- linux-libre-2.6.37-gnu1/drivers/mmc/host/sdhci-pci.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mmc/host/sdhci-pci.c	2011-03-14 21:20:32.000000000 -0400
@@ -176,6 +176,74 @@ static const struct sdhci_pci_fixes sdhc
 	.quirks		= SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC,
 };
 
+/* O2Micro extra registers */
+#define O2_SD_LOCK_WP		0xD3
+#define O2_SD_MULTI_VCC3V	0xEE
+#define O2_SD_CLKREQ		0xEC
+#define O2_SD_CAPS		0xE0
+#define O2_SD_ADMA1		0xE2
+#define O2_SD_ADMA2		0xE7
+#define O2_SD_INF_MOD		0xF1
+
+static int o2_probe(struct sdhci_pci_chip *chip)
+{
+	int ret;
+	u8 scratch;
+
+	switch (chip->pdev->device) {
+	case PCI_DEVICE_ID_O2_8220:
+	case PCI_DEVICE_ID_O2_8221:
+	case PCI_DEVICE_ID_O2_8320:
+	case PCI_DEVICE_ID_O2_8321:
+		/* This extra setup is required due to broken ADMA. */
+		ret = pci_read_config_byte(chip->pdev, O2_SD_LOCK_WP, &scratch);
+		if (ret)
+			return ret;
+		scratch &= 0x7f;
+		pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch);
+
+		/* Set Multi 3 to VCC3V# */
+		pci_write_config_byte(chip->pdev, O2_SD_MULTI_VCC3V, 0x08);
+
+		/* Disable CLK_REQ# support after media DET */
+		ret = pci_read_config_byte(chip->pdev, O2_SD_CLKREQ, &scratch);
+		if (ret)
+			return ret;
+		scratch |= 0x20;
+		pci_write_config_byte(chip->pdev, O2_SD_CLKREQ, scratch);
+
+		/* Choose capabilities, enable SDMA.  We have to write 0x01
+		 * to the capabilities register first to unlock it.
+		 */
+		ret = pci_read_config_byte(chip->pdev, O2_SD_CAPS, &scratch);
+		if (ret)
+			return ret;
+		scratch |= 0x01;
+		pci_write_config_byte(chip->pdev, O2_SD_CAPS, scratch);
+		pci_write_config_byte(chip->pdev, O2_SD_CAPS, 0x73);
+
+		/* Disable ADMA1/2 */
+		pci_write_config_byte(chip->pdev, O2_SD_ADMA1, 0x39);
+		pci_write_config_byte(chip->pdev, O2_SD_ADMA2, 0x08);
+
+		/* Disable the infinite transfer mode */
+		ret = pci_read_config_byte(chip->pdev, O2_SD_INF_MOD, &scratch);
+		if (ret)
+			return ret;
+		scratch |= 0x08;
+		pci_write_config_byte(chip->pdev, O2_SD_INF_MOD, scratch);
+
+		/* Lock WP */
+		ret = pci_read_config_byte(chip->pdev, O2_SD_LOCK_WP, &scratch);
+		if (ret)
+			return ret;
+		scratch |= 0x80;
+		pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch);
+	}
+
+	return 0;
+}
+
 static int jmicron_pmos(struct sdhci_pci_chip *chip, int on)
 {
 	u8 scratch;
@@ -204,6 +272,7 @@ static int jmicron_pmos(struct sdhci_pci
 static int jmicron_probe(struct sdhci_pci_chip *chip)
 {
 	int ret;
+	u16 mmcdev = 0;
 
 	if (chip->pdev->revision == 0) {
 		chip->quirks |= SDHCI_QUIRK_32BIT_DMA_ADDR |
@@ -225,12 +294,17 @@ static int jmicron_probe(struct sdhci_pc
 	 * 2. The MMC interface has a lower subfunction number
 	 *    than the SD interface.
 	 */
-	if (chip->pdev->device == PCI_DEVICE_ID_JMICRON_JMB38X_SD) {
+	if (chip->pdev->device == PCI_DEVICE_ID_JMICRON_JMB38X_SD)
+		mmcdev = PCI_DEVICE_ID_JMICRON_JMB38X_MMC;
+	else if (chip->pdev->device == PCI_DEVICE_ID_JMICRON_JMB388_SD)
+		mmcdev = PCI_DEVICE_ID_JMICRON_JMB388_ESD;
+
+	if (mmcdev) {
 		struct pci_dev *sd_dev;
 
 		sd_dev = NULL;
 		while ((sd_dev = pci_get_device(PCI_VENDOR_ID_JMICRON,
-			PCI_DEVICE_ID_JMICRON_JMB38X_MMC, sd_dev)) != NULL) {
+						mmcdev, sd_dev)) != NULL) {
 			if ((PCI_SLOT(chip->pdev->devfn) ==
 				PCI_SLOT(sd_dev->devfn)) &&
 				(chip->pdev->bus == sd_dev->bus))
@@ -290,13 +364,25 @@ static int jmicron_probe_slot(struct sdh
 			slot->host->quirks |= SDHCI_QUIRK_BROKEN_ADMA;
 	}
 
+	/* JM388 MMC doesn't support 1.8V while SD supports it */
+	if (slot->chip->pdev->device == PCI_DEVICE_ID_JMICRON_JMB388_ESD) {
+		slot->host->ocr_avail_sd = MMC_VDD_32_33 | MMC_VDD_33_34 |
+			MMC_VDD_29_30 | MMC_VDD_30_31 |
+			MMC_VDD_165_195; /* allow 1.8V */
+		slot->host->ocr_avail_mmc = MMC_VDD_32_33 | MMC_VDD_33_34 |
+			MMC_VDD_29_30 | MMC_VDD_30_31; /* no 1.8V for MMC */
+	}
+
 	/*
 	 * The secondary interface requires a bit set to get the
 	 * interrupts.
 	 */
-	if (slot->chip->pdev->device == PCI_DEVICE_ID_JMICRON_JMB38X_MMC)
+	if (slot->chip->pdev->device == PCI_DEVICE_ID_JMICRON_JMB38X_MMC ||
+	    slot->chip->pdev->device == PCI_DEVICE_ID_JMICRON_JMB388_ESD)
 		jmicron_enable_mmc(slot->host, 1);
 
+	slot->host->mmc->caps |= MMC_CAP_BUS_WIDTH_TEST;
+
 	return 0;
 }
 
@@ -305,7 +391,8 @@ static void jmicron_remove_slot(struct s
 	if (dead)
 		return;
 
-	if (slot->chip->pdev->device == PCI_DEVICE_ID_JMICRON_JMB38X_MMC)
+	if (slot->chip->pdev->device == PCI_DEVICE_ID_JMICRON_JMB38X_MMC ||
+	    slot->chip->pdev->device == PCI_DEVICE_ID_JMICRON_JMB388_ESD)
 		jmicron_enable_mmc(slot->host, 0);
 }
 
@@ -313,7 +400,8 @@ static int jmicron_suspend(struct sdhci_
 {
 	int i;
 
-	if (chip->pdev->device == PCI_DEVICE_ID_JMICRON_JMB38X_MMC) {
+	if (chip->pdev->device == PCI_DEVICE_ID_JMICRON_JMB38X_MMC ||
+	    chip->pdev->device == PCI_DEVICE_ID_JMICRON_JMB388_ESD) {
 		for (i = 0;i < chip->num_slots;i++)
 			jmicron_enable_mmc(chip->slots[i]->host, 0);
 	}
@@ -325,7 +413,8 @@ static int jmicron_resume(struct sdhci_p
 {
 	int ret, i;
 
-	if (chip->pdev->device == PCI_DEVICE_ID_JMICRON_JMB38X_MMC) {
+	if (chip->pdev->device == PCI_DEVICE_ID_JMICRON_JMB38X_MMC ||
+	    chip->pdev->device == PCI_DEVICE_ID_JMICRON_JMB388_ESD) {
 		for (i = 0;i < chip->num_slots;i++)
 			jmicron_enable_mmc(chip->slots[i]->host, 1);
 	}
@@ -339,6 +428,10 @@ static int jmicron_resume(struct sdhci_p
 	return 0;
 }
 
+static const struct sdhci_pci_fixes sdhci_o2 = {
+	.probe		= o2_probe,
+};
+
 static const struct sdhci_pci_fixes sdhci_jmicron = {
 	.probe		= jmicron_probe,
 
@@ -510,6 +603,22 @@ static const struct pci_device_id pci_id
 	},
 
 	{
+		.vendor		= PCI_VENDOR_ID_JMICRON,
+		.device		= PCI_DEVICE_ID_JMICRON_JMB388_SD,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+		.driver_data	= (kernel_ulong_t)&sdhci_jmicron,
+	},
+
+	{
+		.vendor		= PCI_VENDOR_ID_JMICRON,
+		.device		= PCI_DEVICE_ID_JMICRON_JMB388_ESD,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+		.driver_data	= (kernel_ulong_t)&sdhci_jmicron,
+	},
+
+	{
 		.vendor		= PCI_VENDOR_ID_SYSKONNECT,
 		.device		= 0x8000,
 		.subvendor	= PCI_ANY_ID,
@@ -589,6 +698,46 @@ static const struct pci_device_id pci_id
 		.driver_data	= (kernel_ulong_t)&sdhci_intel_mfd_emmc_sdio,
 	},
 
+	{
+		.vendor		= PCI_VENDOR_ID_O2,
+		.device		= PCI_DEVICE_ID_O2_8120,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+		.driver_data	= (kernel_ulong_t)&sdhci_o2,
+	},
+
+	{
+		.vendor		= PCI_VENDOR_ID_O2,
+		.device		= PCI_DEVICE_ID_O2_8220,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+		.driver_data	= (kernel_ulong_t)&sdhci_o2,
+	},
+
+	{
+		.vendor		= PCI_VENDOR_ID_O2,
+		.device		= PCI_DEVICE_ID_O2_8221,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+		.driver_data	= (kernel_ulong_t)&sdhci_o2,
+	},
+
+	{
+		.vendor		= PCI_VENDOR_ID_O2,
+		.device		= PCI_DEVICE_ID_O2_8320,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+		.driver_data	= (kernel_ulong_t)&sdhci_o2,
+	},
+
+	{
+		.vendor		= PCI_VENDOR_ID_O2,
+		.device		= PCI_DEVICE_ID_O2_8321,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+		.driver_data	= (kernel_ulong_t)&sdhci_o2,
+	},
+
 	{	/* Generic SD host controller */
 		PCI_DEVICE_CLASS((PCI_CLASS_SYSTEM_SDHCI << 8), 0xFFFF00)
 	},
diff -druNp linux-libre-2.6.37-gnu1/drivers/mmc/host/sdhci-pltfm.c linux-libre-2.6.38-gnu1/drivers/mmc/host/sdhci-pltfm.c
--- linux-libre-2.6.37-gnu1/drivers/mmc/host/sdhci-pltfm.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mmc/host/sdhci-pltfm.c	2011-03-14 21:20:32.000000000 -0400
@@ -170,6 +170,12 @@ static const struct platform_device_id s
 #ifdef CONFIG_MMC_SDHCI_ESDHC_IMX
 	{ "sdhci-esdhc-imx", (kernel_ulong_t)&sdhci_esdhc_imx_pdata },
 #endif
+#ifdef CONFIG_MMC_SDHCI_DOVE
+	{ "sdhci-dove", (kernel_ulong_t)&sdhci_dove_pdata },
+#endif
+#ifdef CONFIG_MMC_SDHCI_TEGRA
+	{ "sdhci-tegra", (kernel_ulong_t)&sdhci_tegra_pdata },
+#endif
 	{ },
 };
 MODULE_DEVICE_TABLE(platform, sdhci_pltfm_ids);
diff -druNp linux-libre-2.6.37-gnu1/drivers/mmc/host/sdhci-pltfm.h linux-libre-2.6.38-gnu1/drivers/mmc/host/sdhci-pltfm.h
--- linux-libre-2.6.37-gnu1/drivers/mmc/host/sdhci-pltfm.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mmc/host/sdhci-pltfm.h	2011-03-14 21:20:32.000000000 -0400
@@ -22,5 +22,7 @@ struct sdhci_pltfm_host {
 
 extern struct sdhci_pltfm_data sdhci_cns3xxx_pdata;
 extern struct sdhci_pltfm_data sdhci_esdhc_imx_pdata;
+extern struct sdhci_pltfm_data sdhci_dove_pdata;
+extern struct sdhci_pltfm_data sdhci_tegra_pdata;
 
 #endif /* _DRIVERS_MMC_SDHCI_PLTFM_H */
diff -druNp linux-libre-2.6.37-gnu1/drivers/mmc/host/sdhci-s3c.c linux-libre-2.6.38-gnu1/drivers/mmc/host/sdhci-s3c.c
--- linux-libre-2.6.37-gnu1/drivers/mmc/host/sdhci-s3c.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mmc/host/sdhci-s3c.c	2011-03-14 21:20:32.000000000 -0400
@@ -130,6 +130,15 @@ static unsigned int sdhci_s3c_consider_c
 	if (!clksrc)
 		return UINT_MAX;
 
+	/*
+	 * Clock divider's step is different as 1 from that of host controller
+	 * when 'clk_type' is S3C_SDHCI_CLK_DIV_EXTERNAL.
+	 */
+	if (ourhost->pdata->clk_type) {
+		rate = clk_round_rate(clksrc, wanted);
+		return wanted - rate;
+	}
+
 	rate = clk_get_rate(clksrc);
 
 	for (div = 1; div < 256; div *= 2) {
@@ -232,10 +241,79 @@ static unsigned int sdhci_s3c_get_min_cl
 	return min;
 }
 
+/* sdhci_cmu_get_max_clk - callback to get maximum clock frequency.*/
+static unsigned int sdhci_cmu_get_max_clock(struct sdhci_host *host)
+{
+	struct sdhci_s3c *ourhost = to_s3c(host);
+
+	return clk_round_rate(ourhost->clk_bus[ourhost->cur_clk], UINT_MAX);
+}
+
+/* sdhci_cmu_get_min_clock - callback to get minimal supported clock value. */
+static unsigned int sdhci_cmu_get_min_clock(struct sdhci_host *host)
+{
+	struct sdhci_s3c *ourhost = to_s3c(host);
+
+	/*
+	 * initial clock can be in the frequency range of
+	 * 100KHz-400KHz, so we set it as max value.
+	 */
+	return clk_round_rate(ourhost->clk_bus[ourhost->cur_clk], 400000);
+}
+
+/* sdhci_cmu_set_clock - callback on clock change.*/
+static void sdhci_cmu_set_clock(struct sdhci_host *host, unsigned int clock)
+{
+	struct sdhci_s3c *ourhost = to_s3c(host);
+
+	/* don't bother if the clock is going off */
+	if (clock == 0)
+		return;
+
+	sdhci_s3c_set_clock(host, clock);
+
+	clk_set_rate(ourhost->clk_bus[ourhost->cur_clk], clock);
+
+	host->clock = clock;
+}
+
+/**
+ * sdhci_s3c_platform_8bit_width - support 8bit buswidth
+ * @host: The SDHCI host being queried
+ * @width: MMC_BUS_WIDTH_ macro for the bus width being requested
+ *
+ * We have 8-bit width support but is not a v3 controller.
+ * So we add platform_8bit_width() and support 8bit width.
+ */
+static int sdhci_s3c_platform_8bit_width(struct sdhci_host *host, int width)
+{
+	u8 ctrl;
+
+	ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
+
+	switch (width) {
+	case MMC_BUS_WIDTH_8:
+		ctrl |= SDHCI_CTRL_8BITBUS;
+		ctrl &= ~SDHCI_CTRL_4BITBUS;
+		break;
+	case MMC_BUS_WIDTH_4:
+		ctrl |= SDHCI_CTRL_4BITBUS;
+		ctrl &= ~SDHCI_CTRL_8BITBUS;
+		break;
+	default:
+		break;
+	}
+
+	sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
+
+	return 0;
+}
+
 static struct sdhci_ops sdhci_s3c_ops = {
 	.get_max_clock		= sdhci_s3c_get_max_clk,
 	.set_clock		= sdhci_s3c_set_clock,
 	.get_min_clock		= sdhci_s3c_get_min_clock,
+	.platform_8bit_width	= sdhci_s3c_platform_8bit_width,
 };
 
 static void sdhci_s3c_notify_change(struct platform_device *dev, int state)
@@ -361,6 +439,13 @@ static int __devinit sdhci_s3c_probe(str
 
 		clks++;
 		sc->clk_bus[ptr] = clk;
+
+		/*
+		 * save current clock index to know which clock bus
+		 * is used later in overriding functions.
+		 */
+		sc->cur_clk = ptr;
+
 		clk_enable(clk);
 
 		dev_info(dev, "clock source %d: %s (%ld Hz)\n",
@@ -421,12 +506,29 @@ static int __devinit sdhci_s3c_probe(str
 	if (pdata->cd_type == S3C_SDHCI_CD_PERMANENT)
 		host->mmc->caps = MMC_CAP_NONREMOVABLE;
 
+	if (pdata->host_caps)
+		host->mmc->caps |= pdata->host_caps;
+
 	host->quirks |= (SDHCI_QUIRK_32BIT_DMA_ADDR |
 			 SDHCI_QUIRK_32BIT_DMA_SIZE);
 
 	/* HSMMC on Samsung SoCs uses SDCLK as timeout clock */
 	host->quirks |= SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK;
 
+	/*
+	 * If controller does not have internal clock divider,
+	 * we can use overriding functions instead of default.
+	 */
+	if (pdata->clk_type) {
+		sdhci_s3c_ops.set_clock = sdhci_cmu_set_clock;
+		sdhci_s3c_ops.get_min_clock = sdhci_cmu_get_min_clock;
+		sdhci_s3c_ops.get_max_clock = sdhci_cmu_get_max_clock;
+	}
+
+	/* It supports additional host capabilities if needed */
+	if (pdata->host_caps)
+		host->mmc->caps |= pdata->host_caps;
+
 	ret = sdhci_add_host(host);
 	if (ret) {
 		dev_err(dev, "sdhci_add_host() failed\n");
diff -druNp linux-libre-2.6.37-gnu1/drivers/mmc/host/sdhci-tegra.c linux-libre-2.6.38-gnu1/drivers/mmc/host/sdhci-tegra.c
--- linux-libre-2.6.37-gnu1/drivers/mmc/host/sdhci-tegra.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mmc/host/sdhci-tegra.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,257 @@
+/*
+ * Copyright (C) 2010 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.
+ *
+ */
+
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+#include <linux/mmc/card.h>
+#include <linux/mmc/host.h>
+
+#include <mach/gpio.h>
+#include <mach/sdhci.h>
+
+#include "sdhci.h"
+#include "sdhci-pltfm.h"
+
+static u32 tegra_sdhci_readl(struct sdhci_host *host, int reg)
+{
+	u32 val;
+
+	if (unlikely(reg == SDHCI_PRESENT_STATE)) {
+		/* Use wp_gpio here instead? */
+		val = readl(host->ioaddr + reg);
+		return val | SDHCI_WRITE_PROTECT;
+	}
+
+	return readl(host->ioaddr + reg);
+}
+
+static u16 tegra_sdhci_readw(struct sdhci_host *host, int reg)
+{
+	if (unlikely(reg == SDHCI_HOST_VERSION)) {
+		/* Erratum: Version register is invalid in HW. */
+		return SDHCI_SPEC_200;
+	}
+
+	return readw(host->ioaddr + reg);
+}
+
+static void tegra_sdhci_writel(struct sdhci_host *host, u32 val, int reg)
+{
+	/* Seems like we're getting spurious timeout and crc errors, so
+	 * disable signalling of them. In case of real errors software
+	 * timers should take care of eventually detecting them.
+	 */
+	if (unlikely(reg == SDHCI_SIGNAL_ENABLE))
+		val &= ~(SDHCI_INT_TIMEOUT|SDHCI_INT_CRC);
+
+	writel(val, host->ioaddr + reg);
+
+	if (unlikely(reg == SDHCI_INT_ENABLE)) {
+		/* Erratum: Must enable block gap interrupt detection */
+		u8 gap_ctrl = readb(host->ioaddr + SDHCI_BLOCK_GAP_CONTROL);
+		if (val & SDHCI_INT_CARD_INT)
+			gap_ctrl |= 0x8;
+		else
+			gap_ctrl &= ~0x8;
+		writeb(gap_ctrl, host->ioaddr + SDHCI_BLOCK_GAP_CONTROL);
+	}
+}
+
+static unsigned int tegra_sdhci_get_ro(struct sdhci_host *sdhci)
+{
+	struct platform_device *pdev = to_platform_device(mmc_dev(sdhci->mmc));
+	struct tegra_sdhci_platform_data *plat;
+
+	plat = pdev->dev.platform_data;
+
+	if (!gpio_is_valid(plat->wp_gpio))
+		return -1;
+
+	return gpio_get_value(plat->wp_gpio);
+}
+
+static irqreturn_t carddetect_irq(int irq, void *data)
+{
+	struct sdhci_host *sdhost = (struct sdhci_host *)data;
+
+	tasklet_schedule(&sdhost->card_tasklet);
+	return IRQ_HANDLED;
+};
+
+static int tegra_sdhci_8bit(struct sdhci_host *host, int bus_width)
+{
+	struct platform_device *pdev = to_platform_device(mmc_dev(host->mmc));
+	struct tegra_sdhci_platform_data *plat;
+	u32 ctrl;
+
+	plat = pdev->dev.platform_data;
+
+	ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
+	if (plat->is_8bit && bus_width == MMC_BUS_WIDTH_8) {
+		ctrl &= ~SDHCI_CTRL_4BITBUS;
+		ctrl |= SDHCI_CTRL_8BITBUS;
+	} else {
+		ctrl &= ~SDHCI_CTRL_8BITBUS;
+		if (bus_width == MMC_BUS_WIDTH_4)
+			ctrl |= SDHCI_CTRL_4BITBUS;
+		else
+			ctrl &= ~SDHCI_CTRL_4BITBUS;
+	}
+	sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
+	return 0;
+}
+
+
+static int tegra_sdhci_pltfm_init(struct sdhci_host *host,
+				  struct sdhci_pltfm_data *pdata)
+{
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct platform_device *pdev = to_platform_device(mmc_dev(host->mmc));
+	struct tegra_sdhci_platform_data *plat;
+	struct clk *clk;
+	int rc;
+
+	plat = pdev->dev.platform_data;
+	if (plat == NULL) {
+		dev_err(mmc_dev(host->mmc), "missing platform data\n");
+		return -ENXIO;
+	}
+
+	if (gpio_is_valid(plat->power_gpio)) {
+		rc = gpio_request(plat->power_gpio, "sdhci_power");
+		if (rc) {
+			dev_err(mmc_dev(host->mmc),
+				"failed to allocate power gpio\n");
+			goto out;
+		}
+		tegra_gpio_enable(plat->power_gpio);
+		gpio_direction_output(plat->power_gpio, 1);
+	}
+
+	if (gpio_is_valid(plat->cd_gpio)) {
+		rc = gpio_request(plat->cd_gpio, "sdhci_cd");
+		if (rc) {
+			dev_err(mmc_dev(host->mmc),
+				"failed to allocate cd gpio\n");
+			goto out_power;
+		}
+		tegra_gpio_enable(plat->cd_gpio);
+		gpio_direction_input(plat->cd_gpio);
+
+		rc = request_irq(gpio_to_irq(plat->cd_gpio), carddetect_irq,
+				 IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
+				 mmc_hostname(host->mmc), host);
+
+		if (rc)	{
+			dev_err(mmc_dev(host->mmc), "request irq error\n");
+			goto out_cd;
+		}
+
+	}
+
+	if (gpio_is_valid(plat->wp_gpio)) {
+		rc = gpio_request(plat->wp_gpio, "sdhci_wp");
+		if (rc) {
+			dev_err(mmc_dev(host->mmc),
+				"failed to allocate wp gpio\n");
+			goto out_cd;
+		}
+		tegra_gpio_enable(plat->wp_gpio);
+		gpio_direction_input(plat->wp_gpio);
+	}
+
+	clk = clk_get(mmc_dev(host->mmc), NULL);
+	if (IS_ERR(clk)) {
+		dev_err(mmc_dev(host->mmc), "clk err\n");
+		rc = PTR_ERR(clk);
+		goto out_wp;
+	}
+	clk_enable(clk);
+	pltfm_host->clk = clk;
+
+	if (plat->is_8bit)
+		host->mmc->caps |= MMC_CAP_8_BIT_DATA;
+
+	return 0;
+
+out_wp:
+	if (gpio_is_valid(plat->wp_gpio)) {
+		tegra_gpio_disable(plat->wp_gpio);
+		gpio_free(plat->wp_gpio);
+	}
+
+out_cd:
+	if (gpio_is_valid(plat->cd_gpio)) {
+		tegra_gpio_disable(plat->cd_gpio);
+		gpio_free(plat->cd_gpio);
+	}
+
+out_power:
+	if (gpio_is_valid(plat->power_gpio)) {
+		tegra_gpio_disable(plat->power_gpio);
+		gpio_free(plat->power_gpio);
+	}
+
+out:
+	return rc;
+}
+
+static void tegra_sdhci_pltfm_exit(struct sdhci_host *host)
+{
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct platform_device *pdev = to_platform_device(mmc_dev(host->mmc));
+	struct tegra_sdhci_platform_data *plat;
+
+	plat = pdev->dev.platform_data;
+
+	if (gpio_is_valid(plat->wp_gpio)) {
+		tegra_gpio_disable(plat->wp_gpio);
+		gpio_free(plat->wp_gpio);
+	}
+
+	if (gpio_is_valid(plat->cd_gpio)) {
+		tegra_gpio_disable(plat->cd_gpio);
+		gpio_free(plat->cd_gpio);
+	}
+
+	if (gpio_is_valid(plat->power_gpio)) {
+		tegra_gpio_disable(plat->power_gpio);
+		gpio_free(plat->power_gpio);
+	}
+
+	clk_disable(pltfm_host->clk);
+	clk_put(pltfm_host->clk);
+}
+
+static struct sdhci_ops tegra_sdhci_ops = {
+	.get_ro     = tegra_sdhci_get_ro,
+	.read_l     = tegra_sdhci_readl,
+	.read_w     = tegra_sdhci_readw,
+	.write_l    = tegra_sdhci_writel,
+	.platform_8bit_width = tegra_sdhci_8bit,
+};
+
+struct sdhci_pltfm_data sdhci_tegra_pdata = {
+	.quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL |
+		  SDHCI_QUIRK_SINGLE_POWER_WRITE |
+		  SDHCI_QUIRK_NO_HISPD_BIT |
+		  SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC,
+	.ops  = &tegra_sdhci_ops,
+	.init = tegra_sdhci_pltfm_init,
+	.exit = tegra_sdhci_pltfm_exit,
+};
diff -druNp linux-libre-2.6.37-gnu1/drivers/mmc/host/sdricoh_cs.c linux-libre-2.6.38-gnu1/drivers/mmc/host/sdricoh_cs.c
--- linux-libre-2.6.37-gnu1/drivers/mmc/host/sdricoh_cs.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mmc/host/sdricoh_cs.c	2011-03-14 21:20:32.000000000 -0400
@@ -446,7 +446,7 @@ static int sdricoh_init_mmc(struct pci_d
 	mmc->max_seg_size = 1024 * 512;
 	mmc->max_blk_size = 512;
 
-	/* reset the controler */
+	/* reset the controller */
 	if (sdricoh_reset(host)) {
 		dev_dbg(dev, "could not reset\n");
 		result = -EIO;
@@ -478,7 +478,7 @@ static int sdricoh_pcmcia_probe(struct p
 	dev_info(&pcmcia_dev->dev, "Searching MMC controller for pcmcia device"
 		" %s %s ...\n", pcmcia_dev->prod_id[0], pcmcia_dev->prod_id[1]);
 
-	/* search pci cardbus bridge that contains the mmc controler */
+	/* search pci cardbus bridge that contains the mmc controller */
 	/* the io region is already claimed by yenta_socket... */
 	while ((pci_dev =
 		pci_get_device(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_RL5C476,
diff -druNp linux-libre-2.6.37-gnu1/drivers/mmc/host/sh_mmcif.c linux-libre-2.6.38-gnu1/drivers/mmc/host/sh_mmcif.c
--- linux-libre-2.6.37-gnu1/drivers/mmc/host/sh_mmcif.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mmc/host/sh_mmcif.c	2011-03-14 21:20:32.000000000 -0400
@@ -16,16 +16,19 @@
  *
  */
 
+#include <linux/clk.h>
+#include <linux/completion.h>
+#include <linux/delay.h>
 #include <linux/dma-mapping.h>
-#include <linux/mmc/host.h>
+#include <linux/dmaengine.h>
 #include <linux/mmc/card.h>
 #include <linux/mmc/core.h>
+#include <linux/mmc/host.h>
 #include <linux/mmc/mmc.h>
 #include <linux/mmc/sdio.h>
-#include <linux/delay.h>
-#include <linux/platform_device.h>
-#include <linux/clk.h>
 #include <linux/mmc/sh_mmcif.h>
+#include <linux/pagemap.h>
+#include <linux/platform_device.h>
 
 #define DRIVER_NAME	"sh_mmcif"
 #define DRIVER_VERSION	"2010-04-28"
@@ -62,25 +65,6 @@
 /* CE_BLOCK_SET */
 #define BLOCK_SIZE_MASK		0x0000ffff
 
-/* CE_CLK_CTRL */
-#define CLK_ENABLE		(1 << 24) /* 1: output mmc clock */
-#define CLK_CLEAR		((1 << 19) | (1 << 18) | (1 << 17) | (1 << 16))
-#define CLK_SUP_PCLK		((1 << 19) | (1 << 18) | (1 << 17) | (1 << 16))
-#define SRSPTO_256		((1 << 13) | (0 << 12)) /* resp timeout */
-#define SRBSYTO_29		((1 << 11) | (1 << 10) |	\
-				 (1 << 9) | (1 << 8)) /* resp busy timeout */
-#define SRWDTO_29		((1 << 7) | (1 << 6) |		\
-				 (1 << 5) | (1 << 4)) /* read/write timeout */
-#define SCCSTO_29		((1 << 3) | (1 << 2) |		\
-				 (1 << 1) | (1 << 0)) /* ccs timeout */
-
-/* CE_BUF_ACC */
-#define BUF_ACC_DMAWEN		(1 << 25)
-#define BUF_ACC_DMAREN		(1 << 24)
-#define BUF_ACC_BUSW_32		(0 << 17)
-#define BUF_ACC_BUSW_16		(1 << 17)
-#define BUF_ACC_ATYP		(1 << 16)
-
 /* CE_INT */
 #define INT_CCSDE		(1 << 29)
 #define INT_CMD12DRE		(1 << 26)
@@ -165,10 +149,6 @@
 				 STS2_AC12BSYTO | STS2_RSPBSYTO |	\
 				 STS2_AC12RSPTO | STS2_RSPTO)
 
-/* CE_VERSION */
-#define SOFT_RST_ON		(1 << 31)
-#define SOFT_RST_OFF		(0 << 31)
-
 #define CLKDEV_EMMC_DATA	52000000 /* 52MHz */
 #define CLKDEV_MMC_DATA		20000000 /* 20MHz */
 #define CLKDEV_INIT		400000   /* 400 KHz */
@@ -176,18 +156,21 @@
 struct sh_mmcif_host {
 	struct mmc_host *mmc;
 	struct mmc_data *data;
-	struct mmc_command *cmd;
 	struct platform_device *pd;
 	struct clk *hclk;
 	unsigned int clk;
 	int bus_width;
-	u16 wait_int;
-	u16 sd_error;
+	bool sd_error;
 	long timeout;
 	void __iomem *addr;
-	wait_queue_head_t intr_wait;
-};
+	struct completion intr_wait;
 
+	/* DMA support */
+	struct dma_chan		*chan_rx;
+	struct dma_chan		*chan_tx;
+	struct completion	dma_complete;
+	unsigned int            dma_sglen;
+};
 
 static inline void sh_mmcif_bitset(struct sh_mmcif_host *host,
 					unsigned int reg, u32 val)
@@ -201,6 +184,188 @@ static inline void sh_mmcif_bitclr(struc
 	writel(~val & readl(host->addr + reg), host->addr + reg);
 }
 
+static void mmcif_dma_complete(void *arg)
+{
+	struct sh_mmcif_host *host = arg;
+	dev_dbg(&host->pd->dev, "Command completed\n");
+
+	if (WARN(!host->data, "%s: NULL data in DMA completion!\n",
+		 dev_name(&host->pd->dev)))
+		return;
+
+	if (host->data->flags & MMC_DATA_READ)
+		dma_unmap_sg(&host->pd->dev, host->data->sg, host->dma_sglen,
+			     DMA_FROM_DEVICE);
+	else
+		dma_unmap_sg(&host->pd->dev, host->data->sg, host->dma_sglen,
+			     DMA_TO_DEVICE);
+
+	complete(&host->dma_complete);
+}
+
+static void sh_mmcif_start_dma_rx(struct sh_mmcif_host *host)
+{
+	struct scatterlist *sg = host->data->sg;
+	struct dma_async_tx_descriptor *desc = NULL;
+	struct dma_chan *chan = host->chan_rx;
+	dma_cookie_t cookie = -EINVAL;
+	int ret;
+
+	ret = dma_map_sg(&host->pd->dev, sg, host->data->sg_len, DMA_FROM_DEVICE);
+	if (ret > 0) {
+		host->dma_sglen = ret;
+		desc = chan->device->device_prep_slave_sg(chan, sg, ret,
+			DMA_FROM_DEVICE, DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+	}
+
+	if (desc) {
+		desc->callback = mmcif_dma_complete;
+		desc->callback_param = host;
+		cookie = desc->tx_submit(desc);
+		if (cookie < 0) {
+			desc = NULL;
+			ret = cookie;
+		} else {
+			sh_mmcif_bitset(host, MMCIF_CE_BUF_ACC, BUF_ACC_DMAREN);
+			chan->device->device_issue_pending(chan);
+		}
+	}
+	dev_dbg(&host->pd->dev, "%s(): mapped %d -> %d, cookie %d\n",
+		__func__, host->data->sg_len, ret, cookie);
+
+	if (!desc) {
+		/* DMA failed, fall back to PIO */
+		if (ret >= 0)
+			ret = -EIO;
+		host->chan_rx = NULL;
+		host->dma_sglen = 0;
+		dma_release_channel(chan);
+		/* Free the Tx channel too */
+		chan = host->chan_tx;
+		if (chan) {
+			host->chan_tx = NULL;
+			dma_release_channel(chan);
+		}
+		dev_warn(&host->pd->dev,
+			 "DMA failed: %d, falling back to PIO\n", ret);
+		sh_mmcif_bitclr(host, MMCIF_CE_BUF_ACC, BUF_ACC_DMAREN | BUF_ACC_DMAWEN);
+	}
+
+	dev_dbg(&host->pd->dev, "%s(): desc %p, cookie %d, sg[%d]\n", __func__,
+		desc, cookie, host->data->sg_len);
+}
+
+static void sh_mmcif_start_dma_tx(struct sh_mmcif_host *host)
+{
+	struct scatterlist *sg = host->data->sg;
+	struct dma_async_tx_descriptor *desc = NULL;
+	struct dma_chan *chan = host->chan_tx;
+	dma_cookie_t cookie = -EINVAL;
+	int ret;
+
+	ret = dma_map_sg(&host->pd->dev, sg, host->data->sg_len, DMA_TO_DEVICE);
+	if (ret > 0) {
+		host->dma_sglen = ret;
+		desc = chan->device->device_prep_slave_sg(chan, sg, ret,
+			DMA_TO_DEVICE, DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+	}
+
+	if (desc) {
+		desc->callback = mmcif_dma_complete;
+		desc->callback_param = host;
+		cookie = desc->tx_submit(desc);
+		if (cookie < 0) {
+			desc = NULL;
+			ret = cookie;
+		} else {
+			sh_mmcif_bitset(host, MMCIF_CE_BUF_ACC, BUF_ACC_DMAWEN);
+			chan->device->device_issue_pending(chan);
+		}
+	}
+	dev_dbg(&host->pd->dev, "%s(): mapped %d -> %d, cookie %d\n",
+		__func__, host->data->sg_len, ret, cookie);
+
+	if (!desc) {
+		/* DMA failed, fall back to PIO */
+		if (ret >= 0)
+			ret = -EIO;
+		host->chan_tx = NULL;
+		host->dma_sglen = 0;
+		dma_release_channel(chan);
+		/* Free the Rx channel too */
+		chan = host->chan_rx;
+		if (chan) {
+			host->chan_rx = NULL;
+			dma_release_channel(chan);
+		}
+		dev_warn(&host->pd->dev,
+			 "DMA failed: %d, falling back to PIO\n", ret);
+		sh_mmcif_bitclr(host, MMCIF_CE_BUF_ACC, BUF_ACC_DMAREN | BUF_ACC_DMAWEN);
+	}
+
+	dev_dbg(&host->pd->dev, "%s(): desc %p, cookie %d\n", __func__,
+		desc, cookie);
+}
+
+static bool sh_mmcif_filter(struct dma_chan *chan, void *arg)
+{
+	dev_dbg(chan->device->dev, "%s: slave data %p\n", __func__, arg);
+	chan->private = arg;
+	return true;
+}
+
+static void sh_mmcif_request_dma(struct sh_mmcif_host *host,
+				 struct sh_mmcif_plat_data *pdata)
+{
+	host->dma_sglen = 0;
+
+	/* We can only either use DMA for both Tx and Rx or not use it at all */
+	if (pdata->dma) {
+		dma_cap_mask_t mask;
+
+		dma_cap_zero(mask);
+		dma_cap_set(DMA_SLAVE, mask);
+
+		host->chan_tx = dma_request_channel(mask, sh_mmcif_filter,
+						    &pdata->dma->chan_priv_tx);
+		dev_dbg(&host->pd->dev, "%s: TX: got channel %p\n", __func__,
+			host->chan_tx);
+
+		if (!host->chan_tx)
+			return;
+
+		host->chan_rx = dma_request_channel(mask, sh_mmcif_filter,
+						    &pdata->dma->chan_priv_rx);
+		dev_dbg(&host->pd->dev, "%s: RX: got channel %p\n", __func__,
+			host->chan_rx);
+
+		if (!host->chan_rx) {
+			dma_release_channel(host->chan_tx);
+			host->chan_tx = NULL;
+			return;
+		}
+
+		init_completion(&host->dma_complete);
+	}
+}
+
+static void sh_mmcif_release_dma(struct sh_mmcif_host *host)
+{
+	sh_mmcif_bitclr(host, MMCIF_CE_BUF_ACC, BUF_ACC_DMAREN | BUF_ACC_DMAWEN);
+	/* Descriptors are freed automatically */
+	if (host->chan_tx) {
+		struct dma_chan *chan = host->chan_tx;
+		host->chan_tx = NULL;
+		dma_release_channel(chan);
+	}
+	if (host->chan_rx) {
+		struct dma_chan *chan = host->chan_rx;
+		host->chan_rx = NULL;
+		dma_release_channel(chan);
+	}
+
+	host->dma_sglen = 0;
+}
 
 static void sh_mmcif_clock_control(struct sh_mmcif_host *host, unsigned int clk)
 {
@@ -239,13 +404,12 @@ static int sh_mmcif_error_manage(struct
 	u32 state1, state2;
 	int ret, timeout = 10000000;
 
-	host->sd_error = 0;
-	host->wait_int = 0;
+	host->sd_error = false;
 
 	state1 = sh_mmcif_readl(host->addr, MMCIF_CE_HOST_STS1);
 	state2 = sh_mmcif_readl(host->addr, MMCIF_CE_HOST_STS2);
-	pr_debug("%s: ERR HOST_STS1 = %08x\n", DRIVER_NAME, state1);
-	pr_debug("%s: ERR HOST_STS2 = %08x\n", DRIVER_NAME, state2);
+	dev_dbg(&host->pd->dev, "ERR HOST_STS1 = %08x\n", state1);
+	dev_dbg(&host->pd->dev, "ERR HOST_STS2 = %08x\n", state2);
 
 	if (state1 & STS1_CMDSEQ) {
 		sh_mmcif_bitset(host, MMCIF_CE_CMD_CTRL, CMD_CTRL_BREAK);
@@ -253,8 +417,8 @@ static int sh_mmcif_error_manage(struct
 		while (1) {
 			timeout--;
 			if (timeout < 0) {
-				pr_err(DRIVER_NAME": Forceed end of " \
-					"command sequence timeout err\n");
+				dev_err(&host->pd->dev,
+					"Forceed end of command sequence timeout err\n");
 				return -EIO;
 			}
 			if (!(sh_mmcif_readl(host->addr, MMCIF_CE_HOST_STS1)
@@ -263,18 +427,18 @@ static int sh_mmcif_error_manage(struct
 			mdelay(1);
 		}
 		sh_mmcif_sync_reset(host);
-		pr_debug(DRIVER_NAME": Forced end of command sequence\n");
+		dev_dbg(&host->pd->dev, "Forced end of command sequence\n");
 		return -EIO;
 	}
 
 	if (state2 & STS2_CRC_ERR) {
-		pr_debug(DRIVER_NAME": Happened CRC error\n");
+		dev_dbg(&host->pd->dev, ": Happened CRC error\n");
 		ret = -EIO;
 	} else if (state2 & STS2_TIMEOUT_ERR) {
-		pr_debug(DRIVER_NAME": Happened Timeout error\n");
+		dev_dbg(&host->pd->dev, ": Happened Timeout error\n");
 		ret = -ETIMEDOUT;
 	} else {
-		pr_debug(DRIVER_NAME": Happened End/Index error\n");
+		dev_dbg(&host->pd->dev, ": Happened End/Index error\n");
 		ret = -EIO;
 	}
 	return ret;
@@ -287,17 +451,13 @@ static int sh_mmcif_single_read(struct s
 	long time;
 	u32 blocksize, i, *p = sg_virt(data->sg);
 
-	host->wait_int = 0;
-
 	/* buf read enable */
 	sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFREN);
-	time = wait_event_interruptible_timeout(host->intr_wait,
-			host->wait_int == 1 ||
-			host->sd_error == 1, host->timeout);
-	if (host->wait_int != 1 && (time == 0 || host->sd_error != 0))
+	time = wait_for_completion_interruptible_timeout(&host->intr_wait,
+			host->timeout);
+	if (time <= 0 || host->sd_error)
 		return sh_mmcif_error_manage(host);
 
-	host->wait_int = 0;
 	blocksize = (BLOCK_SIZE_MASK &
 			sh_mmcif_readl(host->addr, MMCIF_CE_BLOCK_SET)) + 3;
 	for (i = 0; i < blocksize / 4; i++)
@@ -305,13 +465,11 @@ static int sh_mmcif_single_read(struct s
 
 	/* buffer read end */
 	sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFRE);
-	time = wait_event_interruptible_timeout(host->intr_wait,
-			host->wait_int == 1 ||
-			host->sd_error == 1, host->timeout);
-	if (host->wait_int != 1 && (time == 0 || host->sd_error != 0))
+	time = wait_for_completion_interruptible_timeout(&host->intr_wait,
+			host->timeout);
+	if (time <= 0 || host->sd_error)
 		return sh_mmcif_error_manage(host);
 
-	host->wait_int = 0;
 	return 0;
 }
 
@@ -326,19 +484,15 @@ static int sh_mmcif_multi_read(struct sh
 						     MMCIF_CE_BLOCK_SET);
 	for (j = 0; j < data->sg_len; j++) {
 		p = sg_virt(data->sg);
-		host->wait_int = 0;
 		for (sec = 0; sec < data->sg->length / blocksize; sec++) {
 			sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFREN);
 			/* buf read enable */
-			time = wait_event_interruptible_timeout(host->intr_wait,
-				host->wait_int == 1 ||
-				host->sd_error == 1, host->timeout);
+			time = wait_for_completion_interruptible_timeout(&host->intr_wait,
+				host->timeout);
 
-			if (host->wait_int != 1 &&
-			    (time == 0 || host->sd_error != 0))
+			if (time <= 0 || host->sd_error)
 				return sh_mmcif_error_manage(host);
 
-			host->wait_int = 0;
 			for (i = 0; i < blocksize / 4; i++)
 				*p++ = sh_mmcif_readl(host->addr,
 						      MMCIF_CE_DATA);
@@ -356,17 +510,14 @@ static int sh_mmcif_single_write(struct
 	long time;
 	u32 blocksize, i, *p = sg_virt(data->sg);
 
-	host->wait_int = 0;
 	sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFWEN);
 
 	/* buf write enable */
-	time = wait_event_interruptible_timeout(host->intr_wait,
-			host->wait_int == 1 ||
-			host->sd_error == 1, host->timeout);
-	if (host->wait_int != 1 && (time == 0 || host->sd_error != 0))
+	time = wait_for_completion_interruptible_timeout(&host->intr_wait,
+			host->timeout);
+	if (time <= 0 || host->sd_error)
 		return sh_mmcif_error_manage(host);
 
-	host->wait_int = 0;
 	blocksize = (BLOCK_SIZE_MASK &
 			sh_mmcif_readl(host->addr, MMCIF_CE_BLOCK_SET)) + 3;
 	for (i = 0; i < blocksize / 4; i++)
@@ -375,13 +526,11 @@ static int sh_mmcif_single_write(struct
 	/* buffer write end */
 	sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MDTRANE);
 
-	time = wait_event_interruptible_timeout(host->intr_wait,
-			host->wait_int == 1 ||
-			host->sd_error == 1, host->timeout);
-	if (host->wait_int != 1 && (time == 0 || host->sd_error != 0))
+	time = wait_for_completion_interruptible_timeout(&host->intr_wait,
+			host->timeout);
+	if (time <= 0 || host->sd_error)
 		return sh_mmcif_error_manage(host);
 
-	host->wait_int = 0;
 	return 0;
 }
 
@@ -397,19 +546,15 @@ static int sh_mmcif_multi_write(struct s
 
 	for (j = 0; j < data->sg_len; j++) {
 		p = sg_virt(data->sg);
-		host->wait_int = 0;
 		for (sec = 0; sec < data->sg->length / blocksize; sec++) {
 			sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFWEN);
 			/* buf write enable*/
-			time = wait_event_interruptible_timeout(host->intr_wait,
-				host->wait_int == 1 ||
-				host->sd_error == 1, host->timeout);
+			time = wait_for_completion_interruptible_timeout(&host->intr_wait,
+				host->timeout);
 
-			if (host->wait_int != 1 &&
-			    (time == 0 || host->sd_error != 0))
+			if (time <= 0 || host->sd_error)
 				return sh_mmcif_error_manage(host);
 
-			host->wait_int = 0;
 			for (i = 0; i < blocksize / 4; i++)
 				sh_mmcif_writel(host->addr,
 						MMCIF_CE_DATA, *p++);
@@ -457,7 +602,7 @@ static u32 sh_mmcif_set_cmd(struct sh_mm
 		tmp |= CMD_SET_RTYP_17B;
 		break;
 	default:
-		pr_err(DRIVER_NAME": Not support type response.\n");
+		dev_err(&host->pd->dev, "Unsupported response type.\n");
 		break;
 	}
 	switch (opc) {
@@ -485,7 +630,7 @@ static u32 sh_mmcif_set_cmd(struct sh_mm
 			tmp |= CMD_SET_DATW_8;
 			break;
 		default:
-			pr_err(DRIVER_NAME": Not support bus width.\n");
+			dev_err(&host->pd->dev, "Unsupported bus width.\n");
 			break;
 		}
 	}
@@ -513,10 +658,10 @@ static u32 sh_mmcif_set_cmd(struct sh_mm
 	return opc = ((opc << 24) | tmp);
 }
 
-static u32 sh_mmcif_data_trans(struct sh_mmcif_host *host,
+static int sh_mmcif_data_trans(struct sh_mmcif_host *host,
 				struct mmc_request *mrq, u32 opc)
 {
-	u32 ret;
+	int ret;
 
 	switch (opc) {
 	case MMC_READ_MULTIPLE_BLOCK:
@@ -533,7 +678,7 @@ static u32 sh_mmcif_data_trans(struct sh
 		ret = sh_mmcif_single_read(host, mrq);
 		break;
 	default:
-		pr_err(DRIVER_NAME": NOT SUPPORT CMD = d'%08d\n", opc);
+		dev_err(&host->pd->dev, "UNSUPPORTED CMD = d'%08d\n", opc);
 		ret = -EINVAL;
 		break;
 	}
@@ -547,8 +692,6 @@ static void sh_mmcif_start_cmd(struct sh
 	int ret = 0, mask = 0;
 	u32 opc = cmd->opcode;
 
-	host->cmd = cmd;
-
 	switch (opc) {
 	/* respons busy check */
 	case MMC_SWITCH:
@@ -579,13 +722,12 @@ static void sh_mmcif_start_cmd(struct sh
 	sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, mask);
 	/* set arg */
 	sh_mmcif_writel(host->addr, MMCIF_CE_ARG, cmd->arg);
-	host->wait_int = 0;
 	/* set cmd */
 	sh_mmcif_writel(host->addr, MMCIF_CE_CMD_SET, opc);
 
-	time = wait_event_interruptible_timeout(host->intr_wait,
-		host->wait_int == 1 || host->sd_error == 1, host->timeout);
-	if (host->wait_int != 1 && time == 0) {
+	time = wait_for_completion_interruptible_timeout(&host->intr_wait,
+		host->timeout);
+	if (time <= 0) {
 		cmd->error = sh_mmcif_error_manage(host);
 		return;
 	}
@@ -597,26 +739,34 @@ static void sh_mmcif_start_cmd(struct sh
 			cmd->error = -ETIMEDOUT;
 			break;
 		default:
-			pr_debug("%s: Cmd(d'%d) err\n",
-					DRIVER_NAME, cmd->opcode);
+			dev_dbg(&host->pd->dev, "Cmd(d'%d) err\n",
+					cmd->opcode);
 			cmd->error = sh_mmcif_error_manage(host);
 			break;
 		}
-		host->sd_error = 0;
-		host->wait_int = 0;
+		host->sd_error = false;
 		return;
 	}
 	if (!(cmd->flags & MMC_RSP_PRESENT)) {
-		cmd->error = ret;
-		host->wait_int = 0;
+		cmd->error = 0;
 		return;
 	}
-	if (host->wait_int == 1) {
-		sh_mmcif_get_response(host, cmd);
-		host->wait_int = 0;
-	}
+	sh_mmcif_get_response(host, cmd);
 	if (host->data) {
-		ret = sh_mmcif_data_trans(host, mrq, cmd->opcode);
+		if (!host->dma_sglen) {
+			ret = sh_mmcif_data_trans(host, mrq, cmd->opcode);
+		} else {
+			long time =
+				wait_for_completion_interruptible_timeout(&host->dma_complete,
+									  host->timeout);
+			if (!time)
+				ret = -ETIMEDOUT;
+			else if (time < 0)
+				ret = time;
+			sh_mmcif_bitclr(host, MMCIF_CE_BUF_ACC,
+					BUF_ACC_DMAREN | BUF_ACC_DMAWEN);
+			host->dma_sglen = 0;
+		}
 		if (ret < 0)
 			mrq->data->bytes_xfered = 0;
 		else
@@ -636,20 +786,18 @@ static void sh_mmcif_stop_cmd(struct sh_
 	else if (mrq->cmd->opcode == MMC_WRITE_MULTIPLE_BLOCK)
 		sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MCMD12RBE);
 	else {
-		pr_err(DRIVER_NAME": not support stop cmd\n");
+		dev_err(&host->pd->dev, "unsupported stop cmd\n");
 		cmd->error = sh_mmcif_error_manage(host);
 		return;
 	}
 
-	time = wait_event_interruptible_timeout(host->intr_wait,
-			host->wait_int == 1 ||
-			host->sd_error == 1, host->timeout);
-	if (host->wait_int != 1 && (time == 0 || host->sd_error != 0)) {
+	time = wait_for_completion_interruptible_timeout(&host->intr_wait,
+			host->timeout);
+	if (time <= 0 || host->sd_error) {
 		cmd->error = sh_mmcif_error_manage(host);
 		return;
 	}
 	sh_mmcif_get_cmd12response(host, cmd);
-	host->wait_int = 0;
 	cmd->error = 0;
 }
 
@@ -676,6 +824,15 @@ static void sh_mmcif_request(struct mmc_
 		break;
 	}
 	host->data = mrq->data;
+	if (mrq->data) {
+		if (mrq->data->flags & MMC_DATA_READ) {
+			if (host->chan_rx)
+				sh_mmcif_start_dma_rx(host);
+		} else {
+			if (host->chan_tx)
+				sh_mmcif_start_dma_tx(host);
+		}
+	}
 	sh_mmcif_start_cmd(host, mrq, mrq->cmd);
 	host->data = NULL;
 
@@ -735,7 +892,7 @@ static void sh_mmcif_detect(struct mmc_h
 static irqreturn_t sh_mmcif_intr(int irq, void *dev_id)
 {
 	struct sh_mmcif_host *host = dev_id;
-	u32 state = 0;
+	u32 state;
 	int err = 0;
 
 	state = sh_mmcif_readl(host->addr, MMCIF_CE_INT);
@@ -774,17 +931,19 @@ static irqreturn_t sh_mmcif_intr(int irq
 		sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, state);
 		err = 1;
 	} else {
-		pr_debug("%s: Not support int\n", DRIVER_NAME);
+		dev_dbg(&host->pd->dev, "Not support int\n");
 		sh_mmcif_writel(host->addr, MMCIF_CE_INT, ~state);
 		sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, state);
 		err = 1;
 	}
 	if (err) {
-		host->sd_error = 1;
-		pr_debug("%s: int err state = %08x\n", DRIVER_NAME, state);
+		host->sd_error = true;
+		dev_dbg(&host->pd->dev, "int err state = %08x\n", state);
 	}
-	host->wait_int = 1;
-	wake_up(&host->intr_wait);
+	if (state & ~(INT_CMD12RBE | INT_CMD12CRE))
+		complete(&host->intr_wait);
+	else
+		dev_dbg(&host->pd->dev, "Unexpected IRQ 0x%x\n", state);
 
 	return IRQ_HANDLED;
 }
@@ -793,8 +952,8 @@ static int __devinit sh_mmcif_probe(stru
 {
 	int ret = 0, irq[2];
 	struct mmc_host *mmc;
-	struct sh_mmcif_host *host = NULL;
-	struct sh_mmcif_plat_data *pd = NULL;
+	struct sh_mmcif_host *host;
+	struct sh_mmcif_plat_data *pd;
 	struct resource *res;
 	void __iomem *reg;
 	char clk_name[8];
@@ -802,7 +961,7 @@ static int __devinit sh_mmcif_probe(stru
 	irq[0] = platform_get_irq(pdev, 0);
 	irq[1] = platform_get_irq(pdev, 1);
 	if (irq[0] < 0 || irq[1] < 0) {
-		pr_err(DRIVER_NAME": Get irq error\n");
+		dev_err(&pdev->dev, "Get irq error\n");
 		return -ENXIO;
 	}
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -815,7 +974,7 @@ static int __devinit sh_mmcif_probe(stru
 		dev_err(&pdev->dev, "ioremap error.\n");
 		return -ENOMEM;
 	}
-	pd = (struct sh_mmcif_plat_data *)(pdev->dev.platform_data);
+	pd = pdev->dev.platform_data;
 	if (!pd) {
 		dev_err(&pdev->dev, "sh_mmcif plat data error.\n");
 		ret = -ENXIO;
@@ -842,7 +1001,7 @@ static int __devinit sh_mmcif_probe(stru
 	host->clk = clk_get_rate(host->hclk);
 	host->pd = pdev;
 
-	init_waitqueue_head(&host->intr_wait);
+	init_completion(&host->intr_wait);
 
 	mmc->ops = &sh_mmcif_ops;
 	mmc->f_max = host->clk;
@@ -858,33 +1017,37 @@ static int __devinit sh_mmcif_probe(stru
 	mmc->caps = MMC_CAP_MMC_HIGHSPEED;
 	if (pd->caps)
 		mmc->caps |= pd->caps;
-	mmc->max_segs = 128;
+	mmc->max_segs = 32;
 	mmc->max_blk_size = 512;
-	mmc->max_blk_count = 65535;
-	mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count;
+	mmc->max_req_size = PAGE_CACHE_SIZE * mmc->max_segs;
+	mmc->max_blk_count = mmc->max_req_size / mmc->max_blk_size;
 	mmc->max_seg_size = mmc->max_req_size;
 
 	sh_mmcif_sync_reset(host);
 	platform_set_drvdata(pdev, host);
+
+	/* See if we also get DMA */
+	sh_mmcif_request_dma(host, pd);
+
 	mmc_add_host(mmc);
 
 	ret = request_irq(irq[0], sh_mmcif_intr, 0, "sh_mmc:error", host);
 	if (ret) {
-		pr_err(DRIVER_NAME": request_irq error (sh_mmc:error)\n");
+		dev_err(&pdev->dev, "request_irq error (sh_mmc:error)\n");
 		goto clean_up2;
 	}
 	ret = request_irq(irq[1], sh_mmcif_intr, 0, "sh_mmc:int", host);
 	if (ret) {
 		free_irq(irq[0], host);
-		pr_err(DRIVER_NAME": request_irq error (sh_mmc:int)\n");
+		dev_err(&pdev->dev, "request_irq error (sh_mmc:int)\n");
 		goto clean_up2;
 	}
 
 	sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, MASK_ALL);
 	sh_mmcif_detect(host->mmc);
 
-	pr_info("%s: driver version %s\n", DRIVER_NAME, DRIVER_VERSION);
-	pr_debug("%s: chip ver H'%04x\n", DRIVER_NAME,
+	dev_info(&pdev->dev, "driver version %s\n", DRIVER_VERSION);
+	dev_dbg(&pdev->dev, "chip ver H'%04x\n",
 		sh_mmcif_readl(host->addr, MMCIF_CE_VERSION) & 0x0000ffff);
 	return ret;
 
@@ -903,20 +1066,22 @@ static int __devexit sh_mmcif_remove(str
 	struct sh_mmcif_host *host = platform_get_drvdata(pdev);
 	int irq[2];
 
-	sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, MASK_ALL);
-
-	irq[0] = platform_get_irq(pdev, 0);
-	irq[1] = platform_get_irq(pdev, 1);
+	mmc_remove_host(host->mmc);
+	sh_mmcif_release_dma(host);
 
 	if (host->addr)
 		iounmap(host->addr);
 
-	platform_set_drvdata(pdev, NULL);
-	mmc_remove_host(host->mmc);
+	sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, MASK_ALL);
+
+	irq[0] = platform_get_irq(pdev, 0);
+	irq[1] = platform_get_irq(pdev, 1);
 
 	free_irq(irq[0], host);
 	free_irq(irq[1], host);
 
+	platform_set_drvdata(pdev, NULL);
+
 	clk_disable(host->hclk);
 	mmc_free_host(host->mmc);
 
@@ -947,5 +1112,5 @@ module_exit(sh_mmcif_exit);
 
 MODULE_DESCRIPTION("SuperH on-chip MMC/eMMC interface driver");
 MODULE_LICENSE("GPL");
-MODULE_ALIAS(DRIVER_NAME);
+MODULE_ALIAS("platform:" DRIVER_NAME);
 MODULE_AUTHOR("Yusuke Goda <yusuke.goda.sx@renesas.com>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/mmc/host/tmio_mmc.c linux-libre-2.6.38-gnu1/drivers/mmc/host/tmio_mmc.c
--- linux-libre-2.6.37-gnu1/drivers/mmc/host/tmio_mmc.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mmc/host/tmio_mmc.c	2011-03-14 21:20:32.000000000 -0400
@@ -25,16 +25,261 @@
  *   double buffer support
  *
  */
-#include <linux/module.h>
-#include <linux/irq.h>
-#include <linux/device.h>
+
 #include <linux/delay.h>
+#include <linux/device.h>
 #include <linux/dmaengine.h>
-#include <linux/mmc/host.h>
+#include <linux/highmem.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
 #include <linux/mfd/core.h>
 #include <linux/mfd/tmio.h>
+#include <linux/mmc/host.h>
+#include <linux/module.h>
+#include <linux/pagemap.h>
+#include <linux/scatterlist.h>
+#include <linux/workqueue.h>
+#include <linux/spinlock.h>
 
-#include "tmio_mmc.h"
+#define CTL_SD_CMD 0x00
+#define CTL_ARG_REG 0x04
+#define CTL_STOP_INTERNAL_ACTION 0x08
+#define CTL_XFER_BLK_COUNT 0xa
+#define CTL_RESPONSE 0x0c
+#define CTL_STATUS 0x1c
+#define CTL_IRQ_MASK 0x20
+#define CTL_SD_CARD_CLK_CTL 0x24
+#define CTL_SD_XFER_LEN 0x26
+#define CTL_SD_MEM_CARD_OPT 0x28
+#define CTL_SD_ERROR_DETAIL_STATUS 0x2c
+#define CTL_SD_DATA_PORT 0x30
+#define CTL_TRANSACTION_CTL 0x34
+#define CTL_SDIO_STATUS 0x36
+#define CTL_SDIO_IRQ_MASK 0x38
+#define CTL_RESET_SD 0xe0
+#define CTL_SDIO_REGS 0x100
+#define CTL_CLK_AND_WAIT_CTL 0x138
+#define CTL_RESET_SDIO 0x1e0
+
+/* Definitions for values the CTRL_STATUS register can take. */
+#define TMIO_STAT_CMDRESPEND    0x00000001
+#define TMIO_STAT_DATAEND       0x00000004
+#define TMIO_STAT_CARD_REMOVE   0x00000008
+#define TMIO_STAT_CARD_INSERT   0x00000010
+#define TMIO_STAT_SIGSTATE      0x00000020
+#define TMIO_STAT_WRPROTECT     0x00000080
+#define TMIO_STAT_CARD_REMOVE_A 0x00000100
+#define TMIO_STAT_CARD_INSERT_A 0x00000200
+#define TMIO_STAT_SIGSTATE_A    0x00000400
+#define TMIO_STAT_CMD_IDX_ERR   0x00010000
+#define TMIO_STAT_CRCFAIL       0x00020000
+#define TMIO_STAT_STOPBIT_ERR   0x00040000
+#define TMIO_STAT_DATATIMEOUT   0x00080000
+#define TMIO_STAT_RXOVERFLOW    0x00100000
+#define TMIO_STAT_TXUNDERRUN    0x00200000
+#define TMIO_STAT_CMDTIMEOUT    0x00400000
+#define TMIO_STAT_RXRDY         0x01000000
+#define TMIO_STAT_TXRQ          0x02000000
+#define TMIO_STAT_ILL_FUNC      0x20000000
+#define TMIO_STAT_CMD_BUSY      0x40000000
+#define TMIO_STAT_ILL_ACCESS    0x80000000
+
+/* Definitions for values the CTRL_SDIO_STATUS register can take. */
+#define TMIO_SDIO_STAT_IOIRQ	0x0001
+#define TMIO_SDIO_STAT_EXPUB52	0x4000
+#define TMIO_SDIO_STAT_EXWT	0x8000
+#define TMIO_SDIO_MASK_ALL	0xc007
+
+/* Define some IRQ masks */
+/* This is the mask used at reset by the chip */
+#define TMIO_MASK_ALL           0x837f031d
+#define TMIO_MASK_READOP  (TMIO_STAT_RXRDY | TMIO_STAT_DATAEND)
+#define TMIO_MASK_WRITEOP (TMIO_STAT_TXRQ | TMIO_STAT_DATAEND)
+#define TMIO_MASK_CMD     (TMIO_STAT_CMDRESPEND | TMIO_STAT_CMDTIMEOUT | \
+		TMIO_STAT_CARD_REMOVE | TMIO_STAT_CARD_INSERT)
+#define TMIO_MASK_IRQ     (TMIO_MASK_READOP | TMIO_MASK_WRITEOP | TMIO_MASK_CMD)
+
+#define enable_mmc_irqs(host, i) \
+	do { \
+		u32 mask;\
+		mask  = sd_ctrl_read32((host), CTL_IRQ_MASK); \
+		mask &= ~((i) & TMIO_MASK_IRQ); \
+		sd_ctrl_write32((host), CTL_IRQ_MASK, mask); \
+	} while (0)
+
+#define disable_mmc_irqs(host, i) \
+	do { \
+		u32 mask;\
+		mask  = sd_ctrl_read32((host), CTL_IRQ_MASK); \
+		mask |= ((i) & TMIO_MASK_IRQ); \
+		sd_ctrl_write32((host), CTL_IRQ_MASK, mask); \
+	} while (0)
+
+#define ack_mmc_irqs(host, i) \
+	do { \
+		sd_ctrl_write32((host), CTL_STATUS, ~(i)); \
+	} while (0)
+
+/* This is arbitrary, just noone needed any higher alignment yet */
+#define MAX_ALIGN 4
+
+struct tmio_mmc_host {
+	void __iomem *ctl;
+	unsigned long bus_shift;
+	struct mmc_command      *cmd;
+	struct mmc_request      *mrq;
+	struct mmc_data         *data;
+	struct mmc_host         *mmc;
+	int                     irq;
+	unsigned int		sdio_irq_enabled;
+
+	/* Callbacks for clock / power control */
+	void (*set_pwr)(struct platform_device *host, int state);
+	void (*set_clk_div)(struct platform_device *host, int state);
+
+	/* pio related stuff */
+	struct scatterlist      *sg_ptr;
+	struct scatterlist      *sg_orig;
+	unsigned int            sg_len;
+	unsigned int            sg_off;
+
+	struct platform_device *pdev;
+
+	/* DMA support */
+	struct dma_chan		*chan_rx;
+	struct dma_chan		*chan_tx;
+	struct tasklet_struct	dma_complete;
+	struct tasklet_struct	dma_issue;
+#ifdef CONFIG_TMIO_MMC_DMA
+	unsigned int            dma_sglen;
+	u8			bounce_buf[PAGE_CACHE_SIZE] __attribute__((aligned(MAX_ALIGN)));
+	struct scatterlist	bounce_sg;
+#endif
+
+	/* Track lost interrupts */
+	struct delayed_work	delayed_reset_work;
+	spinlock_t		lock;
+	unsigned long		last_req_ts;
+};
+
+static void tmio_check_bounce_buffer(struct tmio_mmc_host *host);
+
+static u16 sd_ctrl_read16(struct tmio_mmc_host *host, int addr)
+{
+	return readw(host->ctl + (addr << host->bus_shift));
+}
+
+static void sd_ctrl_read16_rep(struct tmio_mmc_host *host, int addr,
+		u16 *buf, int count)
+{
+	readsw(host->ctl + (addr << host->bus_shift), buf, count);
+}
+
+static u32 sd_ctrl_read32(struct tmio_mmc_host *host, int addr)
+{
+	return readw(host->ctl + (addr << host->bus_shift)) |
+	       readw(host->ctl + ((addr + 2) << host->bus_shift)) << 16;
+}
+
+static void sd_ctrl_write16(struct tmio_mmc_host *host, int addr, u16 val)
+{
+	writew(val, host->ctl + (addr << host->bus_shift));
+}
+
+static void sd_ctrl_write16_rep(struct tmio_mmc_host *host, int addr,
+		u16 *buf, int count)
+{
+	writesw(host->ctl + (addr << host->bus_shift), buf, count);
+}
+
+static void sd_ctrl_write32(struct tmio_mmc_host *host, int addr, u32 val)
+{
+	writew(val, host->ctl + (addr << host->bus_shift));
+	writew(val >> 16, host->ctl + ((addr + 2) << host->bus_shift));
+}
+
+static void tmio_mmc_init_sg(struct tmio_mmc_host *host, struct mmc_data *data)
+{
+	host->sg_len = data->sg_len;
+	host->sg_ptr = data->sg;
+	host->sg_orig = data->sg;
+	host->sg_off = 0;
+}
+
+static int tmio_mmc_next_sg(struct tmio_mmc_host *host)
+{
+	host->sg_ptr = sg_next(host->sg_ptr);
+	host->sg_off = 0;
+	return --host->sg_len;
+}
+
+static char *tmio_mmc_kmap_atomic(struct scatterlist *sg, unsigned long *flags)
+{
+	local_irq_save(*flags);
+	return kmap_atomic(sg_page(sg), KM_BIO_SRC_IRQ) + sg->offset;
+}
+
+static void tmio_mmc_kunmap_atomic(void *virt, unsigned long *flags)
+{
+	kunmap_atomic(virt, KM_BIO_SRC_IRQ);
+	local_irq_restore(*flags);
+}
+
+#ifdef CONFIG_MMC_DEBUG
+
+#define STATUS_TO_TEXT(a) \
+	do { \
+		if (status & TMIO_STAT_##a) \
+			printk(#a); \
+	} while (0)
+
+void pr_debug_status(u32 status)
+{
+	printk(KERN_DEBUG "status: %08x = ", status);
+	STATUS_TO_TEXT(CARD_REMOVE);
+	STATUS_TO_TEXT(CARD_INSERT);
+	STATUS_TO_TEXT(SIGSTATE);
+	STATUS_TO_TEXT(WRPROTECT);
+	STATUS_TO_TEXT(CARD_REMOVE_A);
+	STATUS_TO_TEXT(CARD_INSERT_A);
+	STATUS_TO_TEXT(SIGSTATE_A);
+	STATUS_TO_TEXT(CMD_IDX_ERR);
+	STATUS_TO_TEXT(STOPBIT_ERR);
+	STATUS_TO_TEXT(ILL_FUNC);
+	STATUS_TO_TEXT(CMD_BUSY);
+	STATUS_TO_TEXT(CMDRESPEND);
+	STATUS_TO_TEXT(DATAEND);
+	STATUS_TO_TEXT(CRCFAIL);
+	STATUS_TO_TEXT(DATATIMEOUT);
+	STATUS_TO_TEXT(CMDTIMEOUT);
+	STATUS_TO_TEXT(RXOVERFLOW);
+	STATUS_TO_TEXT(TXUNDERRUN);
+	STATUS_TO_TEXT(RXRDY);
+	STATUS_TO_TEXT(TXRQ);
+	STATUS_TO_TEXT(ILL_ACCESS);
+	printk("\n");
+}
+
+#else
+#define pr_debug_status(s)  do { } while (0)
+#endif
+
+static void tmio_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable)
+{
+	struct tmio_mmc_host *host = mmc_priv(mmc);
+
+	if (enable) {
+		host->sdio_irq_enabled = 1;
+		sd_ctrl_write16(host, CTL_TRANSACTION_CTL, 0x0001);
+		sd_ctrl_write16(host, CTL_SDIO_IRQ_MASK,
+			(TMIO_SDIO_MASK_ALL & ~TMIO_SDIO_STAT_IOIRQ));
+	} else {
+		sd_ctrl_write16(host, CTL_SDIO_IRQ_MASK, TMIO_SDIO_MASK_ALL);
+		sd_ctrl_write16(host, CTL_TRANSACTION_CTL, 0x0000);
+		host->sdio_irq_enabled = 0;
+	}
+}
 
 static void tmio_mmc_set_clock(struct tmio_mmc_host *host, int new_clock)
 {
@@ -55,8 +300,23 @@ static void tmio_mmc_set_clock(struct tm
 
 static void tmio_mmc_clk_stop(struct tmio_mmc_host *host)
 {
+	struct mfd_cell *cell = host->pdev->dev.platform_data;
+	struct tmio_mmc_data *pdata = cell->driver_data;
+
+	/*
+	 * Testing on sh-mobile showed that SDIO IRQs are unmasked when
+	 * CTL_CLK_AND_WAIT_CTL gets written, so we have to disable the
+	 * device IRQ here and restore the SDIO IRQ mask before
+	 * re-enabling the device IRQ.
+	 */
+	if (pdata->flags & TMIO_MMC_SDIO_IRQ)
+		disable_irq(host->irq);
 	sd_ctrl_write16(host, CTL_CLK_AND_WAIT_CTL, 0x0000);
 	msleep(10);
+	if (pdata->flags & TMIO_MMC_SDIO_IRQ) {
+		tmio_mmc_enable_sdio_irq(host->mmc, host->sdio_irq_enabled);
+		enable_irq(host->irq);
+	}
 	sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, ~0x0100 &
 		sd_ctrl_read16(host, CTL_SD_CARD_CLK_CTL));
 	msleep(10);
@@ -64,11 +324,21 @@ static void tmio_mmc_clk_stop(struct tmi
 
 static void tmio_mmc_clk_start(struct tmio_mmc_host *host)
 {
+	struct mfd_cell *cell = host->pdev->dev.platform_data;
+	struct tmio_mmc_data *pdata = cell->driver_data;
+
 	sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, 0x0100 |
 		sd_ctrl_read16(host, CTL_SD_CARD_CLK_CTL));
 	msleep(10);
+	/* see comment in tmio_mmc_clk_stop above */
+	if (pdata->flags & TMIO_MMC_SDIO_IRQ)
+		disable_irq(host->irq);
 	sd_ctrl_write16(host, CTL_CLK_AND_WAIT_CTL, 0x0100);
 	msleep(10);
+	if (pdata->flags & TMIO_MMC_SDIO_IRQ) {
+		tmio_mmc_enable_sdio_irq(host->mmc, host->sdio_irq_enabled);
+		enable_irq(host->irq);
+	}
 }
 
 static void reset(struct tmio_mmc_host *host)
@@ -82,15 +352,60 @@ static void reset(struct tmio_mmc_host *
 	msleep(10);
 }
 
+static void tmio_mmc_reset_work(struct work_struct *work)
+{
+	struct tmio_mmc_host *host = container_of(work, struct tmio_mmc_host,
+						  delayed_reset_work.work);
+	struct mmc_request *mrq;
+	unsigned long flags;
+
+	spin_lock_irqsave(&host->lock, flags);
+	mrq = host->mrq;
+
+	/* request already finished */
+	if (!mrq
+	    || time_is_after_jiffies(host->last_req_ts +
+		msecs_to_jiffies(2000))) {
+		spin_unlock_irqrestore(&host->lock, flags);
+		return;
+	}
+
+	dev_warn(&host->pdev->dev,
+		"timeout waiting for hardware interrupt (CMD%u)\n",
+		mrq->cmd->opcode);
+
+	if (host->data)
+		host->data->error = -ETIMEDOUT;
+	else if (host->cmd)
+		host->cmd->error = -ETIMEDOUT;
+	else
+		mrq->cmd->error = -ETIMEDOUT;
+
+	host->cmd = NULL;
+	host->data = NULL;
+	host->mrq = NULL;
+
+	spin_unlock_irqrestore(&host->lock, flags);
+
+	reset(host);
+
+	mmc_request_done(host->mmc, mrq);
+}
+
 static void
 tmio_mmc_finish_request(struct tmio_mmc_host *host)
 {
 	struct mmc_request *mrq = host->mrq;
 
+	if (!mrq)
+		return;
+
 	host->mrq = NULL;
 	host->cmd = NULL;
 	host->data = NULL;
 
+	cancel_delayed_work(&host->delayed_reset_work);
+
 	mmc_request_done(host->mmc, mrq);
 }
 
@@ -200,6 +515,7 @@ static void tmio_mmc_pio_irq(struct tmio
 	return;
 }
 
+/* needs to be called with host->lock held */
 static void tmio_mmc_do_data_irq(struct tmio_mmc_host *host)
 {
 	struct mmc_data *data = host->data;
@@ -233,6 +549,8 @@ static void tmio_mmc_do_data_irq(struct
 	if (data->flags & MMC_DATA_READ) {
 		if (!host->chan_rx)
 			disable_mmc_irqs(host, TMIO_MASK_READOP);
+		else
+			tmio_check_bounce_buffer(host);
 		dev_dbg(&host->pdev->dev, "Complete Rx request %p\n",
 			host->mrq);
 	} else {
@@ -254,10 +572,12 @@ static void tmio_mmc_do_data_irq(struct
 
 static void tmio_mmc_data_irq(struct tmio_mmc_host *host)
 {
-	struct mmc_data *data = host->data;
+	struct mmc_data *data;
+	spin_lock(&host->lock);
+	data = host->data;
 
 	if (!data)
-		return;
+		goto out;
 
 	if (host->chan_tx && (data->flags & MMC_DATA_WRITE)) {
 		/*
@@ -278,6 +598,8 @@ static void tmio_mmc_data_irq(struct tmi
 	} else {
 		tmio_mmc_do_data_irq(host);
 	}
+out:
+	spin_unlock(&host->lock);
 }
 
 static void tmio_mmc_cmd_irq(struct tmio_mmc_host *host,
@@ -286,9 +608,11 @@ static void tmio_mmc_cmd_irq(struct tmio
 	struct mmc_command *cmd = host->cmd;
 	int i, addr;
 
+	spin_lock(&host->lock);
+
 	if (!host->cmd) {
 		pr_debug("Spurious CMD irq\n");
-		return;
+		goto out;
 	}
 
 	host->cmd = NULL;
@@ -324,8 +648,7 @@ static void tmio_mmc_cmd_irq(struct tmio
 			if (!host->chan_rx)
 				enable_mmc_irqs(host, TMIO_MASK_READOP);
 		} else {
-			struct dma_chan *chan = host->chan_tx;
-			if (!chan)
+			if (!host->chan_tx)
 				enable_mmc_irqs(host, TMIO_MASK_WRITEOP);
 			else
 				tasklet_schedule(&host->dma_issue);
@@ -334,13 +657,19 @@ static void tmio_mmc_cmd_irq(struct tmio
 		tmio_mmc_finish_request(host);
 	}
 
+out:
+	spin_unlock(&host->lock);
+
 	return;
 }
 
 static irqreturn_t tmio_mmc_irq(int irq, void *devid)
 {
 	struct tmio_mmc_host *host = devid;
+	struct mfd_cell	*cell = host->pdev->dev.platform_data;
+	struct tmio_mmc_data *pdata = cell->driver_data;
 	unsigned int ireg, irq_mask, status;
+	unsigned int sdio_ireg, sdio_irq_mask, sdio_status;
 
 	pr_debug("MMC IRQ begin\n");
 
@@ -348,6 +677,29 @@ static irqreturn_t tmio_mmc_irq(int irq,
 	irq_mask = sd_ctrl_read32(host, CTL_IRQ_MASK);
 	ireg = status & TMIO_MASK_IRQ & ~irq_mask;
 
+	sdio_ireg = 0;
+	if (!ireg && pdata->flags & TMIO_MMC_SDIO_IRQ) {
+		sdio_status = sd_ctrl_read16(host, CTL_SDIO_STATUS);
+		sdio_irq_mask = sd_ctrl_read16(host, CTL_SDIO_IRQ_MASK);
+		sdio_ireg = sdio_status & TMIO_SDIO_MASK_ALL & ~sdio_irq_mask;
+
+		sd_ctrl_write16(host, CTL_SDIO_STATUS, sdio_status & ~TMIO_SDIO_MASK_ALL);
+
+		if (sdio_ireg && !host->sdio_irq_enabled) {
+			pr_warning("tmio_mmc: Spurious SDIO IRQ, disabling! 0x%04x 0x%04x 0x%04x\n",
+				   sdio_status, sdio_irq_mask, sdio_ireg);
+			tmio_mmc_enable_sdio_irq(host->mmc, 0);
+			goto out;
+		}
+
+		if (host->mmc->caps & MMC_CAP_SDIO_IRQ &&
+			sdio_ireg & TMIO_SDIO_STAT_IOIRQ)
+			mmc_signal_sdio_irq(host->mmc);
+
+		if (sdio_ireg)
+			goto out;
+	}
+
 	pr_debug_status(status);
 	pr_debug_status(ireg);
 
@@ -375,8 +727,10 @@ static irqreturn_t tmio_mmc_irq(int irq,
  */
 
 		/* Command completion */
-		if (ireg & TMIO_MASK_CMD) {
-			ack_mmc_irqs(host, TMIO_MASK_CMD);
+		if (ireg & (TMIO_STAT_CMDRESPEND | TMIO_STAT_CMDTIMEOUT)) {
+			ack_mmc_irqs(host,
+				     TMIO_STAT_CMDRESPEND |
+				     TMIO_STAT_CMDTIMEOUT);
 			tmio_mmc_cmd_irq(host, status);
 		}
 
@@ -407,6 +761,16 @@ out:
 }
 
 #ifdef CONFIG_TMIO_MMC_DMA
+static void tmio_check_bounce_buffer(struct tmio_mmc_host *host)
+{
+	if (host->sg_ptr == &host->bounce_sg) {
+		unsigned long flags;
+		void *sg_vaddr = tmio_mmc_kmap_atomic(host->sg_orig, &flags);
+		memcpy(sg_vaddr, host->bounce_buf, host->bounce_sg.length);
+		tmio_mmc_kunmap_atomic(sg_vaddr, &flags);
+	}
+}
+
 static void tmio_mmc_enable_dma(struct tmio_mmc_host *host, bool enable)
 {
 #if defined(CONFIG_SUPERH) || defined(CONFIG_ARCH_SHMOBILE)
@@ -427,12 +791,39 @@ static void tmio_dma_complete(void *arg)
 		enable_mmc_irqs(host, TMIO_STAT_DATAEND);
 }
 
-static int tmio_mmc_start_dma_rx(struct tmio_mmc_host *host)
+static void tmio_mmc_start_dma_rx(struct tmio_mmc_host *host)
 {
-	struct scatterlist *sg = host->sg_ptr;
+	struct scatterlist *sg = host->sg_ptr, *sg_tmp;
 	struct dma_async_tx_descriptor *desc = NULL;
 	struct dma_chan *chan = host->chan_rx;
-	int ret;
+	struct mfd_cell	*cell = host->pdev->dev.platform_data;
+	struct tmio_mmc_data *pdata = cell->driver_data;
+	dma_cookie_t cookie;
+	int ret, i;
+	bool aligned = true, multiple = true;
+	unsigned int align = (1 << pdata->dma->alignment_shift) - 1;
+
+	for_each_sg(sg, sg_tmp, host->sg_len, i) {
+		if (sg_tmp->offset & align)
+			aligned = false;
+		if (sg_tmp->length & align) {
+			multiple = false;
+			break;
+		}
+	}
+
+	if ((!aligned && (host->sg_len > 1 || sg->length > PAGE_CACHE_SIZE ||
+			  align >= MAX_ALIGN)) || !multiple) {
+		ret = -EINVAL;
+		goto pio;
+	}
+
+	/* The only sg element can be unaligned, use our bounce buffer then */
+	if (!aligned) {
+		sg_init_one(&host->bounce_sg, host->bounce_buf, sg->length);
+		host->sg_ptr = &host->bounce_sg;
+		sg = host->sg_ptr;
+	}
 
 	ret = dma_map_sg(&host->pdev->dev, sg, host->sg_len, DMA_FROM_DEVICE);
 	if (ret > 0) {
@@ -442,21 +833,21 @@ static int tmio_mmc_start_dma_rx(struct
 	}
 
 	if (desc) {
-		host->desc = desc;
 		desc->callback = tmio_dma_complete;
 		desc->callback_param = host;
-		host->cookie = desc->tx_submit(desc);
-		if (host->cookie < 0) {
-			host->desc = NULL;
-			ret = host->cookie;
+		cookie = desc->tx_submit(desc);
+		if (cookie < 0) {
+			desc = NULL;
+			ret = cookie;
 		} else {
 			chan->device->device_issue_pending(chan);
 		}
 	}
 	dev_dbg(&host->pdev->dev, "%s(): mapped %d -> %d, cookie %d, rq %p\n",
-		__func__, host->sg_len, ret, host->cookie, host->mrq);
+		__func__, host->sg_len, ret, cookie, host->mrq);
 
-	if (!host->desc) {
+pio:
+	if (!desc) {
 		/* DMA failed, fall back to PIO */
 		if (ret >= 0)
 			ret = -EIO;
@@ -471,24 +862,49 @@ static int tmio_mmc_start_dma_rx(struct
 		dev_warn(&host->pdev->dev,
 			 "DMA failed: %d, falling back to PIO\n", ret);
 		tmio_mmc_enable_dma(host, false);
-		reset(host);
-		/* Fail this request, let above layers recover */
-		host->mrq->cmd->error = ret;
-		tmio_mmc_finish_request(host);
 	}
 
 	dev_dbg(&host->pdev->dev, "%s(): desc %p, cookie %d, sg[%d]\n", __func__,
-		desc, host->cookie, host->sg_len);
-
-	return ret > 0 ? 0 : ret;
+		desc, cookie, host->sg_len);
 }
 
-static int tmio_mmc_start_dma_tx(struct tmio_mmc_host *host)
+static void tmio_mmc_start_dma_tx(struct tmio_mmc_host *host)
 {
-	struct scatterlist *sg = host->sg_ptr;
+	struct scatterlist *sg = host->sg_ptr, *sg_tmp;
 	struct dma_async_tx_descriptor *desc = NULL;
 	struct dma_chan *chan = host->chan_tx;
-	int ret;
+	struct mfd_cell	*cell = host->pdev->dev.platform_data;
+	struct tmio_mmc_data *pdata = cell->driver_data;
+	dma_cookie_t cookie;
+	int ret, i;
+	bool aligned = true, multiple = true;
+	unsigned int align = (1 << pdata->dma->alignment_shift) - 1;
+
+	for_each_sg(sg, sg_tmp, host->sg_len, i) {
+		if (sg_tmp->offset & align)
+			aligned = false;
+		if (sg_tmp->length & align) {
+			multiple = false;
+			break;
+		}
+	}
+
+	if ((!aligned && (host->sg_len > 1 || sg->length > PAGE_CACHE_SIZE ||
+			  align >= MAX_ALIGN)) || !multiple) {
+		ret = -EINVAL;
+		goto pio;
+	}
+
+	/* The only sg element can be unaligned, use our bounce buffer then */
+	if (!aligned) {
+		unsigned long flags;
+		void *sg_vaddr = tmio_mmc_kmap_atomic(sg, &flags);
+		sg_init_one(&host->bounce_sg, host->bounce_buf, sg->length);
+		memcpy(host->bounce_buf, sg_vaddr, host->bounce_sg.length);
+		tmio_mmc_kunmap_atomic(sg_vaddr, &flags);
+		host->sg_ptr = &host->bounce_sg;
+		sg = host->sg_ptr;
+	}
 
 	ret = dma_map_sg(&host->pdev->dev, sg, host->sg_len, DMA_TO_DEVICE);
 	if (ret > 0) {
@@ -498,19 +914,19 @@ static int tmio_mmc_start_dma_tx(struct
 	}
 
 	if (desc) {
-		host->desc = desc;
 		desc->callback = tmio_dma_complete;
 		desc->callback_param = host;
-		host->cookie = desc->tx_submit(desc);
-		if (host->cookie < 0) {
-			host->desc = NULL;
-			ret = host->cookie;
+		cookie = desc->tx_submit(desc);
+		if (cookie < 0) {
+			desc = NULL;
+			ret = cookie;
 		}
 	}
 	dev_dbg(&host->pdev->dev, "%s(): mapped %d -> %d, cookie %d, rq %p\n",
-		__func__, host->sg_len, ret, host->cookie, host->mrq);
+		__func__, host->sg_len, ret, cookie, host->mrq);
 
-	if (!host->desc) {
+pio:
+	if (!desc) {
 		/* DMA failed, fall back to PIO */
 		if (ret >= 0)
 			ret = -EIO;
@@ -525,30 +941,22 @@ static int tmio_mmc_start_dma_tx(struct
 		dev_warn(&host->pdev->dev,
 			 "DMA failed: %d, falling back to PIO\n", ret);
 		tmio_mmc_enable_dma(host, false);
-		reset(host);
-		/* Fail this request, let above layers recover */
-		host->mrq->cmd->error = ret;
-		tmio_mmc_finish_request(host);
 	}
 
 	dev_dbg(&host->pdev->dev, "%s(): desc %p, cookie %d\n", __func__,
-		desc, host->cookie);
-
-	return ret > 0 ? 0 : ret;
+		desc, cookie);
 }
 
-static int tmio_mmc_start_dma(struct tmio_mmc_host *host,
+static void tmio_mmc_start_dma(struct tmio_mmc_host *host,
 			       struct mmc_data *data)
 {
 	if (data->flags & MMC_DATA_READ) {
 		if (host->chan_rx)
-			return tmio_mmc_start_dma_rx(host);
+			tmio_mmc_start_dma_rx(host);
 	} else {
 		if (host->chan_tx)
-			return tmio_mmc_start_dma_tx(host);
+			tmio_mmc_start_dma_tx(host);
 	}
-
-	return 0;
 }
 
 static void tmio_issue_tasklet_fn(unsigned long priv)
@@ -562,6 +970,12 @@ static void tmio_issue_tasklet_fn(unsign
 static void tmio_tasklet_fn(unsigned long arg)
 {
 	struct tmio_mmc_host *host = (struct tmio_mmc_host *)arg;
+	unsigned long flags;
+
+	spin_lock_irqsave(&host->lock, flags);
+
+	if (!host->data)
+		goto out;
 
 	if (host->data->flags & MMC_DATA_READ)
 		dma_unmap_sg(&host->pdev->dev, host->sg_ptr, host->dma_sglen,
@@ -571,6 +985,8 @@ static void tmio_tasklet_fn(unsigned lon
 			     DMA_TO_DEVICE);
 
 	tmio_mmc_do_data_irq(host);
+out:
+	spin_unlock_irqrestore(&host->lock, flags);
 }
 
 /* It might be necessary to make filter MFD specific */
@@ -584,9 +1000,6 @@ static bool tmio_mmc_filter(struct dma_c
 static void tmio_mmc_request_dma(struct tmio_mmc_host *host,
 				 struct tmio_mmc_data *pdata)
 {
-	host->cookie = -EINVAL;
-	host->desc = NULL;
-
 	/* We can only either use DMA for both Tx and Rx or not use it at all */
 	if (pdata->dma) {
 		dma_cap_mask_t mask;
@@ -632,15 +1045,15 @@ static void tmio_mmc_release_dma(struct
 		host->chan_rx = NULL;
 		dma_release_channel(chan);
 	}
-
-	host->cookie = -EINVAL;
-	host->desc = NULL;
 }
 #else
-static int tmio_mmc_start_dma(struct tmio_mmc_host *host,
+static void tmio_check_bounce_buffer(struct tmio_mmc_host *host)
+{
+}
+
+static void tmio_mmc_start_dma(struct tmio_mmc_host *host,
 			       struct mmc_data *data)
 {
-	return 0;
 }
 
 static void tmio_mmc_request_dma(struct tmio_mmc_host *host,
@@ -682,7 +1095,9 @@ static int tmio_mmc_start_data(struct tm
 	sd_ctrl_write16(host, CTL_SD_XFER_LEN, data->blksz);
 	sd_ctrl_write16(host, CTL_XFER_BLK_COUNT, data->blocks);
 
-	return tmio_mmc_start_dma(host, data);
+	tmio_mmc_start_dma(host, data);
+
+	return 0;
 }
 
 /* Process requests from the MMC layer */
@@ -694,6 +1109,8 @@ static void tmio_mmc_request(struct mmc_
 	if (host->mrq)
 		pr_debug("request not null\n");
 
+	host->last_req_ts = jiffies;
+	wmb();
 	host->mrq = mrq;
 
 	if (mrq->data) {
@@ -703,10 +1120,14 @@ static void tmio_mmc_request(struct mmc_
 	}
 
 	ret = tmio_mmc_start_command(host, mrq->cmd);
-	if (!ret)
+	if (!ret) {
+		schedule_delayed_work(&host->delayed_reset_work,
+				      msecs_to_jiffies(2000));
 		return;
+	}
 
 fail:
+	host->mrq = NULL;
 	mrq->cmd->error = ret;
 	mmc_request_done(mmc, mrq);
 }
@@ -780,6 +1201,7 @@ static const struct mmc_host_ops tmio_mm
 	.set_ios	= tmio_mmc_set_ios,
 	.get_ro         = tmio_mmc_get_ro,
 	.get_cd		= tmio_mmc_get_cd,
+	.enable_sdio_irq = tmio_mmc_enable_sdio_irq,
 };
 
 #ifdef CONFIG_PM
@@ -864,10 +1286,15 @@ static int __devinit tmio_mmc_probe(stru
 		goto host_free;
 
 	mmc->ops = &tmio_mmc_ops;
-	mmc->caps = MMC_CAP_4_BIT_DATA;
-	mmc->caps |= pdata->capabilities;
+	mmc->caps = MMC_CAP_4_BIT_DATA | pdata->capabilities;
 	mmc->f_max = pdata->hclk;
 	mmc->f_min = mmc->f_max / 512;
+	mmc->max_segs = 32;
+	mmc->max_blk_size = 512;
+	mmc->max_blk_count = (PAGE_CACHE_SIZE / mmc->max_blk_size) *
+		mmc->max_segs;
+	mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count;
+	mmc->max_seg_size = mmc->max_req_size;
 	if (pdata->ocr_mask)
 		mmc->ocr_avail = pdata->ocr_mask;
 	else
@@ -890,12 +1317,19 @@ static int __devinit tmio_mmc_probe(stru
 		goto cell_disable;
 
 	disable_mmc_irqs(host, TMIO_MASK_ALL);
+	if (pdata->flags & TMIO_MMC_SDIO_IRQ)
+		tmio_mmc_enable_sdio_irq(mmc, 0);
 
 	ret = request_irq(host->irq, tmio_mmc_irq, IRQF_DISABLED |
 		IRQF_TRIGGER_FALLING, dev_name(&dev->dev), host);
 	if (ret)
 		goto cell_disable;
 
+	spin_lock_init(&host->lock);
+
+	/* Init delayed work for request timeouts */
+	INIT_DELAYED_WORK(&host->delayed_reset_work, tmio_mmc_reset_work);
+
 	/* See if we also get DMA */
 	tmio_mmc_request_dma(host, pdata);
 
@@ -934,6 +1368,7 @@ static int __devexit tmio_mmc_remove(str
 	if (mmc) {
 		struct tmio_mmc_host *host = mmc_priv(mmc);
 		mmc_remove_host(mmc);
+		cancel_delayed_work_sync(&host->delayed_reset_work);
 		tmio_mmc_release_dma(host);
 		free_irq(host->irq, host);
 		if (cell->disable)
diff -druNp linux-libre-2.6.37-gnu1/drivers/mmc/host/tmio_mmc.h linux-libre-2.6.38-gnu1/drivers/mmc/host/tmio_mmc.h
--- linux-libre-2.6.37-gnu1/drivers/mmc/host/tmio_mmc.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mmc/host/tmio_mmc.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,228 +0,0 @@
-/* Definitons for use with the tmio_mmc.c
- *
- * (c) 2004 Ian Molton <spyro@f2s.com>
- * (c) 2007 Ian Molton <spyro@f2s.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/highmem.h>
-#include <linux/interrupt.h>
-#include <linux/dmaengine.h>
-
-#define CTL_SD_CMD 0x00
-#define CTL_ARG_REG 0x04
-#define CTL_STOP_INTERNAL_ACTION 0x08
-#define CTL_XFER_BLK_COUNT 0xa
-#define CTL_RESPONSE 0x0c
-#define CTL_STATUS 0x1c
-#define CTL_IRQ_MASK 0x20
-#define CTL_SD_CARD_CLK_CTL 0x24
-#define CTL_SD_XFER_LEN 0x26
-#define CTL_SD_MEM_CARD_OPT 0x28
-#define CTL_SD_ERROR_DETAIL_STATUS 0x2c
-#define CTL_SD_DATA_PORT 0x30
-#define CTL_TRANSACTION_CTL 0x34
-#define CTL_RESET_SD 0xe0
-#define CTL_SDIO_REGS 0x100
-#define CTL_CLK_AND_WAIT_CTL 0x138
-#define CTL_RESET_SDIO 0x1e0
-
-/* Definitions for values the CTRL_STATUS register can take. */
-#define TMIO_STAT_CMDRESPEND    0x00000001
-#define TMIO_STAT_DATAEND       0x00000004
-#define TMIO_STAT_CARD_REMOVE   0x00000008
-#define TMIO_STAT_CARD_INSERT   0x00000010
-#define TMIO_STAT_SIGSTATE      0x00000020
-#define TMIO_STAT_WRPROTECT     0x00000080
-#define TMIO_STAT_CARD_REMOVE_A 0x00000100
-#define TMIO_STAT_CARD_INSERT_A 0x00000200
-#define TMIO_STAT_SIGSTATE_A    0x00000400
-#define TMIO_STAT_CMD_IDX_ERR   0x00010000
-#define TMIO_STAT_CRCFAIL       0x00020000
-#define TMIO_STAT_STOPBIT_ERR   0x00040000
-#define TMIO_STAT_DATATIMEOUT   0x00080000
-#define TMIO_STAT_RXOVERFLOW    0x00100000
-#define TMIO_STAT_TXUNDERRUN    0x00200000
-#define TMIO_STAT_CMDTIMEOUT    0x00400000
-#define TMIO_STAT_RXRDY         0x01000000
-#define TMIO_STAT_TXRQ          0x02000000
-#define TMIO_STAT_ILL_FUNC      0x20000000
-#define TMIO_STAT_CMD_BUSY      0x40000000
-#define TMIO_STAT_ILL_ACCESS    0x80000000
-
-/* Define some IRQ masks */
-/* This is the mask used at reset by the chip */
-#define TMIO_MASK_ALL           0x837f031d
-#define TMIO_MASK_READOP  (TMIO_STAT_RXRDY | TMIO_STAT_DATAEND)
-#define TMIO_MASK_WRITEOP (TMIO_STAT_TXRQ | TMIO_STAT_DATAEND)
-#define TMIO_MASK_CMD     (TMIO_STAT_CMDRESPEND | TMIO_STAT_CMDTIMEOUT | \
-		TMIO_STAT_CARD_REMOVE | TMIO_STAT_CARD_INSERT)
-#define TMIO_MASK_IRQ     (TMIO_MASK_READOP | TMIO_MASK_WRITEOP | TMIO_MASK_CMD)
-
-
-#define enable_mmc_irqs(host, i) \
-	do { \
-		u32 mask;\
-		mask  = sd_ctrl_read32((host), CTL_IRQ_MASK); \
-		mask &= ~((i) & TMIO_MASK_IRQ); \
-		sd_ctrl_write32((host), CTL_IRQ_MASK, mask); \
-	} while (0)
-
-#define disable_mmc_irqs(host, i) \
-	do { \
-		u32 mask;\
-		mask  = sd_ctrl_read32((host), CTL_IRQ_MASK); \
-		mask |= ((i) & TMIO_MASK_IRQ); \
-		sd_ctrl_write32((host), CTL_IRQ_MASK, mask); \
-	} while (0)
-
-#define ack_mmc_irqs(host, i) \
-	do { \
-		sd_ctrl_write32((host), CTL_STATUS, ~(i)); \
-	} while (0)
-
-
-struct tmio_mmc_host {
-	void __iomem *ctl;
-	unsigned long bus_shift;
-	struct mmc_command      *cmd;
-	struct mmc_request      *mrq;
-	struct mmc_data         *data;
-	struct mmc_host         *mmc;
-	int                     irq;
-
-	/* Callbacks for clock / power control */
-	void (*set_pwr)(struct platform_device *host, int state);
-	void (*set_clk_div)(struct platform_device *host, int state);
-
-	/* pio related stuff */
-	struct scatterlist      *sg_ptr;
-	unsigned int            sg_len;
-	unsigned int            sg_off;
-
-	struct platform_device *pdev;
-
-	/* DMA support */
-	struct dma_chan		*chan_rx;
-	struct dma_chan		*chan_tx;
-	struct tasklet_struct	dma_complete;
-	struct tasklet_struct	dma_issue;
-#ifdef CONFIG_TMIO_MMC_DMA
-	struct dma_async_tx_descriptor *desc;
-	unsigned int            dma_sglen;
-	dma_cookie_t		cookie;
-#endif
-};
-
-#include <linux/io.h>
-
-static inline u16 sd_ctrl_read16(struct tmio_mmc_host *host, int addr)
-{
-	return readw(host->ctl + (addr << host->bus_shift));
-}
-
-static inline void sd_ctrl_read16_rep(struct tmio_mmc_host *host, int addr,
-		u16 *buf, int count)
-{
-	readsw(host->ctl + (addr << host->bus_shift), buf, count);
-}
-
-static inline u32 sd_ctrl_read32(struct tmio_mmc_host *host, int addr)
-{
-	return readw(host->ctl + (addr << host->bus_shift)) |
-	       readw(host->ctl + ((addr + 2) << host->bus_shift)) << 16;
-}
-
-static inline void sd_ctrl_write16(struct tmio_mmc_host *host, int addr,
-		u16 val)
-{
-	writew(val, host->ctl + (addr << host->bus_shift));
-}
-
-static inline void sd_ctrl_write16_rep(struct tmio_mmc_host *host, int addr,
-		u16 *buf, int count)
-{
-	writesw(host->ctl + (addr << host->bus_shift), buf, count);
-}
-
-static inline void sd_ctrl_write32(struct tmio_mmc_host *host, int addr,
-		u32 val)
-{
-	writew(val, host->ctl + (addr << host->bus_shift));
-	writew(val >> 16, host->ctl + ((addr + 2) << host->bus_shift));
-}
-
-#include <linux/scatterlist.h>
-#include <linux/blkdev.h>
-
-static inline void tmio_mmc_init_sg(struct tmio_mmc_host *host,
-	struct mmc_data *data)
-{
-	host->sg_len = data->sg_len;
-	host->sg_ptr = data->sg;
-	host->sg_off = 0;
-}
-
-static inline int tmio_mmc_next_sg(struct tmio_mmc_host *host)
-{
-	host->sg_ptr = sg_next(host->sg_ptr);
-	host->sg_off = 0;
-	return --host->sg_len;
-}
-
-static inline char *tmio_mmc_kmap_atomic(struct scatterlist *sg,
-	unsigned long *flags)
-{
-	local_irq_save(*flags);
-	return kmap_atomic(sg_page(sg), KM_BIO_SRC_IRQ) + sg->offset;
-}
-
-static inline void tmio_mmc_kunmap_atomic(void *virt,
-	unsigned long *flags)
-{
-	kunmap_atomic(virt, KM_BIO_SRC_IRQ);
-	local_irq_restore(*flags);
-}
-
-#ifdef CONFIG_MMC_DEBUG
-
-#define STATUS_TO_TEXT(a) \
-	do { \
-		if (status & TMIO_STAT_##a) \
-			printk(#a); \
-	} while (0)
-
-void pr_debug_status(u32 status)
-{
-	printk(KERN_DEBUG "status: %08x = ", status);
-	STATUS_TO_TEXT(CARD_REMOVE);
-	STATUS_TO_TEXT(CARD_INSERT);
-	STATUS_TO_TEXT(SIGSTATE);
-	STATUS_TO_TEXT(WRPROTECT);
-	STATUS_TO_TEXT(CARD_REMOVE_A);
-	STATUS_TO_TEXT(CARD_INSERT_A);
-	STATUS_TO_TEXT(SIGSTATE_A);
-	STATUS_TO_TEXT(CMD_IDX_ERR);
-	STATUS_TO_TEXT(STOPBIT_ERR);
-	STATUS_TO_TEXT(ILL_FUNC);
-	STATUS_TO_TEXT(CMD_BUSY);
-	STATUS_TO_TEXT(CMDRESPEND);
-	STATUS_TO_TEXT(DATAEND);
-	STATUS_TO_TEXT(CRCFAIL);
-	STATUS_TO_TEXT(DATATIMEOUT);
-	STATUS_TO_TEXT(CMDTIMEOUT);
-	STATUS_TO_TEXT(RXOVERFLOW);
-	STATUS_TO_TEXT(TXUNDERRUN);
-	STATUS_TO_TEXT(RXRDY);
-	STATUS_TO_TEXT(TXRQ);
-	STATUS_TO_TEXT(ILL_ACCESS);
-	printk("\n");
-}
-
-#else
-#define pr_debug_status(s)  do { } while (0)
-#endif
diff -druNp linux-libre-2.6.37-gnu1/drivers/mmc/host/ushc.c linux-libre-2.6.38-gnu1/drivers/mmc/host/ushc.c
--- linux-libre-2.6.37-gnu1/drivers/mmc/host/ushc.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mmc/host/ushc.c	2011-03-14 21:20:32.000000000 -0400
@@ -19,7 +19,6 @@
 #include <linux/module.h>
 #include <linux/usb.h>
 #include <linux/kernel.h>
-#include <linux/usb.h>
 #include <linux/slab.h>
 #include <linux/dma-mapping.h>
 #include <linux/mmc/host.h>
diff -druNp linux-libre-2.6.37-gnu1/drivers/mtd/chips/cfi_cmdset_0001.c linux-libre-2.6.38-gnu1/drivers/mtd/chips/cfi_cmdset_0001.c
--- linux-libre-2.6.37-gnu1/drivers/mtd/chips/cfi_cmdset_0001.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mtd/chips/cfi_cmdset_0001.c	2011-03-14 21:20:32.000000000 -0400
@@ -162,7 +162,7 @@ static void cfi_tell_features(struct cfi
 #endif
 
 /* Atmel chips don't use the same PRI format as Intel chips */
-static void fixup_convert_atmel_pri(struct mtd_info *mtd, void *param)
+static void fixup_convert_atmel_pri(struct mtd_info *mtd)
 {
 	struct map_info *map = mtd->priv;
 	struct cfi_private *cfi = map->fldrv_priv;
@@ -202,7 +202,7 @@ static void fixup_convert_atmel_pri(stru
 	cfi->cfiq->BufWriteTimeoutMax = 0;
 }
 
-static void fixup_at49bv640dx_lock(struct mtd_info *mtd, void *param)
+static void fixup_at49bv640dx_lock(struct mtd_info *mtd)
 {
 	struct map_info *map = mtd->priv;
 	struct cfi_private *cfi = map->fldrv_priv;
@@ -214,7 +214,7 @@ static void fixup_at49bv640dx_lock(struc
 
 #ifdef CMDSET0001_DISABLE_ERASE_SUSPEND_ON_WRITE
 /* Some Intel Strata Flash prior to FPO revision C has bugs in this area */
-static void fixup_intel_strataflash(struct mtd_info *mtd, void* param)
+static void fixup_intel_strataflash(struct mtd_info *mtd)
 {
 	struct map_info *map = mtd->priv;
 	struct cfi_private *cfi = map->fldrv_priv;
@@ -227,7 +227,7 @@ static void fixup_intel_strataflash(stru
 #endif
 
 #ifdef CMDSET0001_DISABLE_WRITE_SUSPEND
-static void fixup_no_write_suspend(struct mtd_info *mtd, void* param)
+static void fixup_no_write_suspend(struct mtd_info *mtd)
 {
 	struct map_info *map = mtd->priv;
 	struct cfi_private *cfi = map->fldrv_priv;
@@ -240,7 +240,7 @@ static void fixup_no_write_suspend(struc
 }
 #endif
 
-static void fixup_st_m28w320ct(struct mtd_info *mtd, void* param)
+static void fixup_st_m28w320ct(struct mtd_info *mtd)
 {
 	struct map_info *map = mtd->priv;
 	struct cfi_private *cfi = map->fldrv_priv;
@@ -249,7 +249,7 @@ static void fixup_st_m28w320ct(struct mt
 	cfi->cfiq->BufWriteTimeoutMax = 0;	/* Not supported */
 }
 
-static void fixup_st_m28w320cb(struct mtd_info *mtd, void* param)
+static void fixup_st_m28w320cb(struct mtd_info *mtd)
 {
 	struct map_info *map = mtd->priv;
 	struct cfi_private *cfi = map->fldrv_priv;
@@ -259,7 +259,7 @@ static void fixup_st_m28w320cb(struct mt
 		(cfi->cfiq->EraseRegionInfo[1] & 0xffff0000) | 0x3e;
 };
 
-static void fixup_use_point(struct mtd_info *mtd, void *param)
+static void fixup_use_point(struct mtd_info *mtd)
 {
 	struct map_info *map = mtd->priv;
 	if (!mtd->point && map_is_linear(map)) {
@@ -268,7 +268,7 @@ static void fixup_use_point(struct mtd_i
 	}
 }
 
-static void fixup_use_write_buffers(struct mtd_info *mtd, void *param)
+static void fixup_use_write_buffers(struct mtd_info *mtd)
 {
 	struct map_info *map = mtd->priv;
 	struct cfi_private *cfi = map->fldrv_priv;
@@ -282,7 +282,7 @@ static void fixup_use_write_buffers(stru
 /*
  * Some chips power-up with all sectors locked by default.
  */
-static void fixup_unlock_powerup_lock(struct mtd_info *mtd, void *param)
+static void fixup_unlock_powerup_lock(struct mtd_info *mtd)
 {
 	struct map_info *map = mtd->priv;
 	struct cfi_private *cfi = map->fldrv_priv;
@@ -295,31 +295,31 @@ static void fixup_unlock_powerup_lock(st
 }
 
 static struct cfi_fixup cfi_fixup_table[] = {
-	{ CFI_MFR_ATMEL, CFI_ID_ANY, fixup_convert_atmel_pri, NULL },
-	{ CFI_MFR_ATMEL, AT49BV640D, fixup_at49bv640dx_lock, NULL },
-	{ CFI_MFR_ATMEL, AT49BV640DT, fixup_at49bv640dx_lock, NULL },
+	{ CFI_MFR_ATMEL, CFI_ID_ANY, fixup_convert_atmel_pri },
+	{ CFI_MFR_ATMEL, AT49BV640D, fixup_at49bv640dx_lock },
+	{ CFI_MFR_ATMEL, AT49BV640DT, fixup_at49bv640dx_lock },
 #ifdef CMDSET0001_DISABLE_ERASE_SUSPEND_ON_WRITE
-	{ CFI_MFR_ANY, CFI_ID_ANY, fixup_intel_strataflash, NULL },
+	{ CFI_MFR_ANY, CFI_ID_ANY, fixup_intel_strataflash },
 #endif
 #ifdef CMDSET0001_DISABLE_WRITE_SUSPEND
-	{ CFI_MFR_ANY, CFI_ID_ANY, fixup_no_write_suspend, NULL },
+	{ CFI_MFR_ANY, CFI_ID_ANY, fixup_no_write_suspend },
 #endif
 #if !FORCE_WORD_WRITE
-	{ CFI_MFR_ANY, CFI_ID_ANY, fixup_use_write_buffers, NULL },
+	{ CFI_MFR_ANY, CFI_ID_ANY, fixup_use_write_buffers },
 #endif
-	{ CFI_MFR_ST, 0x00ba, /* M28W320CT */ fixup_st_m28w320ct, NULL },
-	{ CFI_MFR_ST, 0x00bb, /* M28W320CB */ fixup_st_m28w320cb, NULL },
-	{ CFI_MFR_INTEL, CFI_ID_ANY, fixup_unlock_powerup_lock, NULL, },
-	{ 0, 0, NULL, NULL }
+	{ CFI_MFR_ST, 0x00ba, /* M28W320CT */ fixup_st_m28w320ct },
+	{ CFI_MFR_ST, 0x00bb, /* M28W320CB */ fixup_st_m28w320cb },
+	{ CFI_MFR_INTEL, CFI_ID_ANY, fixup_unlock_powerup_lock },
+	{ 0, 0, NULL }
 };
 
 static struct cfi_fixup jedec_fixup_table[] = {
-	{ CFI_MFR_INTEL, I82802AB,   fixup_use_fwh_lock, NULL, },
-	{ CFI_MFR_INTEL, I82802AC,   fixup_use_fwh_lock, NULL, },
-	{ CFI_MFR_ST,    M50LPW080,  fixup_use_fwh_lock, NULL, },
-	{ CFI_MFR_ST,    M50FLW080A, fixup_use_fwh_lock, NULL, },
-	{ CFI_MFR_ST,    M50FLW080B, fixup_use_fwh_lock, NULL, },
-	{ 0, 0, NULL, NULL }
+	{ CFI_MFR_INTEL, I82802AB,   fixup_use_fwh_lock },
+	{ CFI_MFR_INTEL, I82802AC,   fixup_use_fwh_lock },
+	{ CFI_MFR_ST,    M50LPW080,  fixup_use_fwh_lock },
+	{ CFI_MFR_ST,    M50FLW080A, fixup_use_fwh_lock },
+	{ CFI_MFR_ST,    M50FLW080B, fixup_use_fwh_lock },
+	{ 0, 0, NULL }
 };
 static struct cfi_fixup fixup_table[] = {
 	/* The CFI vendor ids and the JEDEC vendor IDs appear
@@ -327,8 +327,8 @@ static struct cfi_fixup fixup_table[] =
 	 * well.  This table is to pick all cases where
 	 * we know that is the case.
 	 */
-	{ CFI_MFR_ANY, CFI_ID_ANY, fixup_use_point, NULL },
-	{ 0, 0, NULL, NULL }
+	{ CFI_MFR_ANY, CFI_ID_ANY, fixup_use_point },
+	{ 0, 0, NULL }
 };
 
 static void cfi_fixup_major_minor(struct cfi_private *cfi,
@@ -455,6 +455,7 @@ struct mtd_info *cfi_cmdset_0001(struct
 	mtd->flags   = MTD_CAP_NORFLASH;
 	mtd->name    = map->name;
 	mtd->writesize = 1;
+	mtd->writebufsize = 1 << cfi->cfiq->MaxBufWriteSize;
 
 	mtd->reboot_notifier.notifier_call = cfi_intelext_reboot;
 
@@ -1229,10 +1230,32 @@ static int inval_cache_and_wait_for_oper
 	sleep_time = chip_op_time / 2;
 
 	for (;;) {
+		if (chip->state != chip_state) {
+			/* Someone's suspended the operation: sleep */
+			DECLARE_WAITQUEUE(wait, current);
+			set_current_state(TASK_UNINTERRUPTIBLE);
+			add_wait_queue(&chip->wq, &wait);
+			mutex_unlock(&chip->mutex);
+			schedule();
+			remove_wait_queue(&chip->wq, &wait);
+			mutex_lock(&chip->mutex);
+			continue;
+		}
+
 		status = map_read(map, cmd_adr);
 		if (map_word_andequal(map, status, status_OK, status_OK))
 			break;
 
+		if (chip->erase_suspended && chip_state == FL_ERASING)  {
+			/* Erase suspend occured while sleep: reset timeout */
+			timeo = reset_timeo;
+			chip->erase_suspended = 0;
+		}
+		if (chip->write_suspended && chip_state == FL_WRITING)  {
+			/* Write suspend occured while sleep: reset timeout */
+			timeo = reset_timeo;
+			chip->write_suspended = 0;
+		}
 		if (!timeo) {
 			map_write(map, CMD(0x70), cmd_adr);
 			chip->state = FL_STATUS;
@@ -1256,27 +1279,6 @@ static int inval_cache_and_wait_for_oper
 			timeo--;
 		}
 		mutex_lock(&chip->mutex);
-
-		while (chip->state != chip_state) {
-			/* Someone's suspended the operation: sleep */
-			DECLARE_WAITQUEUE(wait, current);
-			set_current_state(TASK_UNINTERRUPTIBLE);
-			add_wait_queue(&chip->wq, &wait);
-			mutex_unlock(&chip->mutex);
-			schedule();
-			remove_wait_queue(&chip->wq, &wait);
-			mutex_lock(&chip->mutex);
-		}
-		if (chip->erase_suspended && chip_state == FL_ERASING)  {
-			/* Erase suspend occured while sleep: reset timeout */
-			timeo = reset_timeo;
-			chip->erase_suspended = 0;
-		}
-		if (chip->write_suspended && chip_state == FL_WRITING)  {
-			/* Write suspend occured while sleep: reset timeout */
-			timeo = reset_timeo;
-			chip->write_suspended = 0;
-		}
 	}
 
 	/* Done and happy. */
diff -druNp linux-libre-2.6.37-gnu1/drivers/mtd/chips/cfi_cmdset_0002.c linux-libre-2.6.38-gnu1/drivers/mtd/chips/cfi_cmdset_0002.c
--- linux-libre-2.6.37-gnu1/drivers/mtd/chips/cfi_cmdset_0002.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mtd/chips/cfi_cmdset_0002.c	2011-03-14 21:20:32.000000000 -0400
@@ -134,7 +134,7 @@ static void cfi_tell_features(struct cfi
 
 #ifdef AMD_BOOTLOC_BUG
 /* Wheee. Bring me the head of someone at AMD. */
-static void fixup_amd_bootblock(struct mtd_info *mtd, void* param)
+static void fixup_amd_bootblock(struct mtd_info *mtd)
 {
 	struct map_info *map = mtd->priv;
 	struct cfi_private *cfi = map->fldrv_priv;
@@ -186,7 +186,7 @@ static void fixup_amd_bootblock(struct m
 }
 #endif
 
-static void fixup_use_write_buffers(struct mtd_info *mtd, void *param)
+static void fixup_use_write_buffers(struct mtd_info *mtd)
 {
 	struct map_info *map = mtd->priv;
 	struct cfi_private *cfi = map->fldrv_priv;
@@ -197,7 +197,7 @@ static void fixup_use_write_buffers(stru
 }
 
 /* Atmel chips don't use the same PRI format as AMD chips */
-static void fixup_convert_atmel_pri(struct mtd_info *mtd, void *param)
+static void fixup_convert_atmel_pri(struct mtd_info *mtd)
 {
 	struct map_info *map = mtd->priv;
 	struct cfi_private *cfi = map->fldrv_priv;
@@ -228,14 +228,14 @@ static void fixup_convert_atmel_pri(stru
 	cfi->cfiq->BufWriteTimeoutMax = 0;
 }
 
-static void fixup_use_secsi(struct mtd_info *mtd, void *param)
+static void fixup_use_secsi(struct mtd_info *mtd)
 {
 	/* Setup for chips with a secsi area */
 	mtd->read_user_prot_reg = cfi_amdstd_secsi_read;
 	mtd->read_fact_prot_reg = cfi_amdstd_secsi_read;
 }
 
-static void fixup_use_erase_chip(struct mtd_info *mtd, void *param)
+static void fixup_use_erase_chip(struct mtd_info *mtd)
 {
 	struct map_info *map = mtd->priv;
 	struct cfi_private *cfi = map->fldrv_priv;
@@ -250,7 +250,7 @@ static void fixup_use_erase_chip(struct
  * Some Atmel chips (e.g. the AT49BV6416) power-up with all sectors
  * locked by default.
  */
-static void fixup_use_atmel_lock(struct mtd_info *mtd, void *param)
+static void fixup_use_atmel_lock(struct mtd_info *mtd)
 {
 	mtd->lock = cfi_atmel_lock;
 	mtd->unlock = cfi_atmel_unlock;
@@ -271,7 +271,7 @@ static void fixup_old_sst_eraseregion(st
 	cfi->cfiq->NumEraseRegions = 1;
 }
 
-static void fixup_sst39vf(struct mtd_info *mtd, void *param)
+static void fixup_sst39vf(struct mtd_info *mtd)
 {
 	struct map_info *map = mtd->priv;
 	struct cfi_private *cfi = map->fldrv_priv;
@@ -282,7 +282,7 @@ static void fixup_sst39vf(struct mtd_inf
 	cfi->addr_unlock2 = 0x2AAA;
 }
 
-static void fixup_sst39vf_rev_b(struct mtd_info *mtd, void *param)
+static void fixup_sst39vf_rev_b(struct mtd_info *mtd)
 {
 	struct map_info *map = mtd->priv;
 	struct cfi_private *cfi = map->fldrv_priv;
@@ -295,12 +295,12 @@ static void fixup_sst39vf_rev_b(struct m
 	cfi->sector_erase_cmd = CMD(0x50);
 }
 
-static void fixup_sst38vf640x_sectorsize(struct mtd_info *mtd, void *param)
+static void fixup_sst38vf640x_sectorsize(struct mtd_info *mtd)
 {
 	struct map_info *map = mtd->priv;
 	struct cfi_private *cfi = map->fldrv_priv;
 
-	fixup_sst39vf_rev_b(mtd, param);
+	fixup_sst39vf_rev_b(mtd);
 
 	/*
 	 * CFI reports 1024 sectors (0x03ff+1) of 64KBytes (0x0100*256) where
@@ -310,7 +310,7 @@ static void fixup_sst38vf640x_sectorsize
 	pr_warning("%s: Bad 38VF640x CFI data; adjusting sector size from 64 to 8KiB\n", mtd->name);
 }
 
-static void fixup_s29gl064n_sectors(struct mtd_info *mtd, void *param)
+static void fixup_s29gl064n_sectors(struct mtd_info *mtd)
 {
 	struct map_info *map = mtd->priv;
 	struct cfi_private *cfi = map->fldrv_priv;
@@ -321,7 +321,7 @@ static void fixup_s29gl064n_sectors(stru
 	}
 }
 
-static void fixup_s29gl032n_sectors(struct mtd_info *mtd, void *param)
+static void fixup_s29gl032n_sectors(struct mtd_info *mtd)
 {
 	struct map_info *map = mtd->priv;
 	struct cfi_private *cfi = map->fldrv_priv;
@@ -334,47 +334,47 @@ static void fixup_s29gl032n_sectors(stru
 
 /* Used to fix CFI-Tables of chips without Extended Query Tables */
 static struct cfi_fixup cfi_nopri_fixup_table[] = {
-	{ CFI_MFR_SST, 0x234A, fixup_sst39vf, NULL, }, /* SST39VF1602 */
-	{ CFI_MFR_SST, 0x234B, fixup_sst39vf, NULL, }, /* SST39VF1601 */
-	{ CFI_MFR_SST, 0x235A, fixup_sst39vf, NULL, }, /* SST39VF3202 */
-	{ CFI_MFR_SST, 0x235B, fixup_sst39vf, NULL, }, /* SST39VF3201 */
-	{ CFI_MFR_SST, 0x235C, fixup_sst39vf_rev_b, NULL, }, /* SST39VF3202B */
-	{ CFI_MFR_SST, 0x235D, fixup_sst39vf_rev_b, NULL, }, /* SST39VF3201B */
-	{ CFI_MFR_SST, 0x236C, fixup_sst39vf_rev_b, NULL, }, /* SST39VF6402B */
-	{ CFI_MFR_SST, 0x236D, fixup_sst39vf_rev_b, NULL, }, /* SST39VF6401B */
-	{ 0, 0, NULL, NULL }
+	{ CFI_MFR_SST, 0x234a, fixup_sst39vf }, /* SST39VF1602 */
+	{ CFI_MFR_SST, 0x234b, fixup_sst39vf }, /* SST39VF1601 */
+	{ CFI_MFR_SST, 0x235a, fixup_sst39vf }, /* SST39VF3202 */
+	{ CFI_MFR_SST, 0x235b, fixup_sst39vf }, /* SST39VF3201 */
+	{ CFI_MFR_SST, 0x235c, fixup_sst39vf_rev_b }, /* SST39VF3202B */
+	{ CFI_MFR_SST, 0x235d, fixup_sst39vf_rev_b }, /* SST39VF3201B */
+	{ CFI_MFR_SST, 0x236c, fixup_sst39vf_rev_b }, /* SST39VF6402B */
+	{ CFI_MFR_SST, 0x236d, fixup_sst39vf_rev_b }, /* SST39VF6401B */
+	{ 0, 0, NULL }
 };
 
 static struct cfi_fixup cfi_fixup_table[] = {
-	{ CFI_MFR_ATMEL, CFI_ID_ANY, fixup_convert_atmel_pri, NULL },
+	{ CFI_MFR_ATMEL, CFI_ID_ANY, fixup_convert_atmel_pri },
 #ifdef AMD_BOOTLOC_BUG
-	{ CFI_MFR_AMD, CFI_ID_ANY, fixup_amd_bootblock, NULL },
-	{ CFI_MFR_MACRONIX, CFI_ID_ANY, fixup_amd_bootblock, NULL },
+	{ CFI_MFR_AMD, CFI_ID_ANY, fixup_amd_bootblock },
+	{ CFI_MFR_MACRONIX, CFI_ID_ANY, fixup_amd_bootblock },
 #endif
-	{ CFI_MFR_AMD, 0x0050, fixup_use_secsi, NULL, },
-	{ CFI_MFR_AMD, 0x0053, fixup_use_secsi, NULL, },
-	{ CFI_MFR_AMD, 0x0055, fixup_use_secsi, NULL, },
-	{ CFI_MFR_AMD, 0x0056, fixup_use_secsi, NULL, },
-	{ CFI_MFR_AMD, 0x005C, fixup_use_secsi, NULL, },
-	{ CFI_MFR_AMD, 0x005F, fixup_use_secsi, NULL, },
-	{ CFI_MFR_AMD, 0x0c01, fixup_s29gl064n_sectors, NULL, },
-	{ CFI_MFR_AMD, 0x1301, fixup_s29gl064n_sectors, NULL, },
-	{ CFI_MFR_AMD, 0x1a00, fixup_s29gl032n_sectors, NULL, },
-	{ CFI_MFR_AMD, 0x1a01, fixup_s29gl032n_sectors, NULL, },
-	{ CFI_MFR_SST, 0x536A, fixup_sst38vf640x_sectorsize, NULL, }, /* SST38VF6402 */
-	{ CFI_MFR_SST, 0x536B, fixup_sst38vf640x_sectorsize, NULL, }, /* SST38VF6401 */
-	{ CFI_MFR_SST, 0x536C, fixup_sst38vf640x_sectorsize, NULL, }, /* SST38VF6404 */
-	{ CFI_MFR_SST, 0x536D, fixup_sst38vf640x_sectorsize, NULL, }, /* SST38VF6403 */
+	{ CFI_MFR_AMD, 0x0050, fixup_use_secsi },
+	{ CFI_MFR_AMD, 0x0053, fixup_use_secsi },
+	{ CFI_MFR_AMD, 0x0055, fixup_use_secsi },
+	{ CFI_MFR_AMD, 0x0056, fixup_use_secsi },
+	{ CFI_MFR_AMD, 0x005C, fixup_use_secsi },
+	{ CFI_MFR_AMD, 0x005F, fixup_use_secsi },
+	{ CFI_MFR_AMD, 0x0c01, fixup_s29gl064n_sectors },
+	{ CFI_MFR_AMD, 0x1301, fixup_s29gl064n_sectors },
+	{ CFI_MFR_AMD, 0x1a00, fixup_s29gl032n_sectors },
+	{ CFI_MFR_AMD, 0x1a01, fixup_s29gl032n_sectors },
+	{ CFI_MFR_SST, 0x536a, fixup_sst38vf640x_sectorsize }, /* SST38VF6402 */
+	{ CFI_MFR_SST, 0x536b, fixup_sst38vf640x_sectorsize }, /* SST38VF6401 */
+	{ CFI_MFR_SST, 0x536c, fixup_sst38vf640x_sectorsize }, /* SST38VF6404 */
+	{ CFI_MFR_SST, 0x536d, fixup_sst38vf640x_sectorsize }, /* SST38VF6403 */
 #if !FORCE_WORD_WRITE
-	{ CFI_MFR_ANY, CFI_ID_ANY, fixup_use_write_buffers, NULL, },
+	{ CFI_MFR_ANY, CFI_ID_ANY, fixup_use_write_buffers },
 #endif
-	{ 0, 0, NULL, NULL }
+	{ 0, 0, NULL }
 };
 static struct cfi_fixup jedec_fixup_table[] = {
-	{ CFI_MFR_SST, SST49LF004B, fixup_use_fwh_lock, NULL, },
-	{ CFI_MFR_SST, SST49LF040B, fixup_use_fwh_lock, NULL, },
-	{ CFI_MFR_SST, SST49LF008A, fixup_use_fwh_lock, NULL, },
-	{ 0, 0, NULL, NULL }
+	{ CFI_MFR_SST, SST49LF004B, fixup_use_fwh_lock },
+	{ CFI_MFR_SST, SST49LF040B, fixup_use_fwh_lock },
+	{ CFI_MFR_SST, SST49LF008A, fixup_use_fwh_lock },
+	{ 0, 0, NULL }
 };
 
 static struct cfi_fixup fixup_table[] = {
@@ -383,18 +383,30 @@ static struct cfi_fixup fixup_table[] =
 	 * well.  This table is to pick all cases where
 	 * we know that is the case.
 	 */
-	{ CFI_MFR_ANY, CFI_ID_ANY, fixup_use_erase_chip, NULL },
-	{ CFI_MFR_ATMEL, AT49BV6416, fixup_use_atmel_lock, NULL },
-	{ 0, 0, NULL, NULL }
+	{ CFI_MFR_ANY, CFI_ID_ANY, fixup_use_erase_chip },
+	{ CFI_MFR_ATMEL, AT49BV6416, fixup_use_atmel_lock },
+	{ 0, 0, NULL }
 };
 
 
 static void cfi_fixup_major_minor(struct cfi_private *cfi,
 				  struct cfi_pri_amdstd *extp)
 {
-	if (cfi->mfr == CFI_MFR_SAMSUNG && cfi->id == 0x257e &&
-	    extp->MajorVersion == '0')
-		extp->MajorVersion = '1';
+	if (cfi->mfr == CFI_MFR_SAMSUNG) {
+		if ((extp->MajorVersion == '0' && extp->MinorVersion == '0') ||
+		    (extp->MajorVersion == '3' && extp->MinorVersion == '3')) {
+			/*
+			 * Samsung K8P2815UQB and K8D6x16UxM chips
+			 * report major=0 / minor=0.
+			 * K8D3x16UxC chips report major=3 / minor=3.
+			 */
+			printk(KERN_NOTICE "  Fixing Samsung's Amd/Fujitsu"
+			       " Extended Query version to 1.%c\n",
+			       extp->MinorVersion);
+			extp->MajorVersion = '1';
+		}
+	}
+
 	/*
 	 * SST 38VF640x chips report major=0xFF / minor=0xFF.
 	 */
@@ -428,6 +440,10 @@ struct mtd_info *cfi_cmdset_0002(struct
 	mtd->flags   = MTD_CAP_NORFLASH;
 	mtd->name    = map->name;
 	mtd->writesize = 1;
+	mtd->writebufsize = 1 << cfi->cfiq->MaxBufWriteSize;
+
+	DEBUG(MTD_DEBUG_LEVEL3, "MTD %s(): write buffer size %d\n",
+		__func__, mtd->writebufsize);
 
 	mtd->reboot_notifier.notifier_call = cfi_amdstd_reboot;
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/mtd/chips/cfi_cmdset_0020.c linux-libre-2.6.38-gnu1/drivers/mtd/chips/cfi_cmdset_0020.c
--- linux-libre-2.6.37-gnu1/drivers/mtd/chips/cfi_cmdset_0020.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mtd/chips/cfi_cmdset_0020.c	2011-03-14 21:20:32.000000000 -0400
@@ -238,6 +238,7 @@ static struct mtd_info *cfi_staa_setup(s
 	mtd->resume = cfi_staa_resume;
 	mtd->flags = MTD_CAP_NORFLASH & ~MTD_BIT_WRITEABLE;
 	mtd->writesize = 8; /* FIXME: Should be 0 for STMicro flashes w/out ECC */
+	mtd->writebufsize = 1 << cfi->cfiq->MaxBufWriteSize;
 	map->fldrv = &cfi_staa_chipdrv;
 	__module_get(THIS_MODULE);
 	mtd->name = map->name;
diff -druNp linux-libre-2.6.37-gnu1/drivers/mtd/chips/cfi_util.c linux-libre-2.6.38-gnu1/drivers/mtd/chips/cfi_util.c
--- linux-libre-2.6.37-gnu1/drivers/mtd/chips/cfi_util.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mtd/chips/cfi_util.c	2011-03-14 21:20:32.000000000 -0400
@@ -156,7 +156,7 @@ void cfi_fixup(struct mtd_info *mtd, str
 	for (f=fixups; f->fixup; f++) {
 		if (((f->mfr == CFI_MFR_ANY) || (f->mfr == cfi->mfr)) &&
 		    ((f->id  == CFI_ID_ANY)  || (f->id  == cfi->id))) {
-			f->fixup(mtd, f->param);
+			f->fixup(mtd);
 		}
 	}
 }
diff -druNp linux-libre-2.6.37-gnu1/drivers/mtd/chips/fwh_lock.h linux-libre-2.6.38-gnu1/drivers/mtd/chips/fwh_lock.h
--- linux-libre-2.6.37-gnu1/drivers/mtd/chips/fwh_lock.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mtd/chips/fwh_lock.h	2011-03-14 21:20:32.000000000 -0400
@@ -98,7 +98,7 @@ static int fwh_unlock_varsize(struct mtd
 	return ret;
 }
 
-static void fixup_use_fwh_lock(struct mtd_info *mtd, void *param)
+static void fixup_use_fwh_lock(struct mtd_info *mtd)
 {
 	printk(KERN_NOTICE "using fwh lock/unlock method\n");
 	/* Setup for the chips with the fwh lock method */
diff -druNp linux-libre-2.6.37-gnu1/drivers/mtd/chips/jedec_probe.c linux-libre-2.6.38-gnu1/drivers/mtd/chips/jedec_probe.c
--- linux-libre-2.6.37-gnu1/drivers/mtd/chips/jedec_probe.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mtd/chips/jedec_probe.c	2011-03-14 21:20:32.000000000 -0400
@@ -1935,14 +1935,14 @@ static void jedec_reset(u32 base, struct
 }
 
 
-static int cfi_jedec_setup(struct cfi_private *p_cfi, int index)
+static int cfi_jedec_setup(struct map_info *map, struct cfi_private *cfi, int index)
 {
 	int i,num_erase_regions;
 	uint8_t uaddr;
 
-	if (! (jedec_table[index].devtypes & p_cfi->device_type)) {
+	if (!(jedec_table[index].devtypes & cfi->device_type)) {
 		DEBUG(MTD_DEBUG_LEVEL1, "Rejecting potential %s with incompatible %d-bit device type\n",
-		      jedec_table[index].name, 4 * (1<<p_cfi->device_type));
+		      jedec_table[index].name, 4 * (1<<cfi->device_type));
 		return 0;
 	}
 
@@ -1950,27 +1950,28 @@ static int cfi_jedec_setup(struct cfi_pr
 
 	num_erase_regions = jedec_table[index].nr_regions;
 
-	p_cfi->cfiq = kmalloc(sizeof(struct cfi_ident) + num_erase_regions * 4, GFP_KERNEL);
-	if (!p_cfi->cfiq) {
+	cfi->cfiq = kmalloc(sizeof(struct cfi_ident) + num_erase_regions * 4, GFP_KERNEL);
+	if (!cfi->cfiq) {
 		//xx printk(KERN_WARNING "%s: kmalloc failed for CFI ident structure\n", map->name);
 		return 0;
 	}
 
-	memset(p_cfi->cfiq,0,sizeof(struct cfi_ident));
+	memset(cfi->cfiq, 0, sizeof(struct cfi_ident));
 
-	p_cfi->cfiq->P_ID = jedec_table[index].cmd_set;
-	p_cfi->cfiq->NumEraseRegions = jedec_table[index].nr_regions;
-	p_cfi->cfiq->DevSize = jedec_table[index].dev_size;
-	p_cfi->cfi_mode = CFI_MODE_JEDEC;
+	cfi->cfiq->P_ID = jedec_table[index].cmd_set;
+	cfi->cfiq->NumEraseRegions = jedec_table[index].nr_regions;
+	cfi->cfiq->DevSize = jedec_table[index].dev_size;
+	cfi->cfi_mode = CFI_MODE_JEDEC;
+	cfi->sector_erase_cmd = CMD(0x30);
 
 	for (i=0; i<num_erase_regions; i++){
-		p_cfi->cfiq->EraseRegionInfo[i] = jedec_table[index].regions[i];
+		cfi->cfiq->EraseRegionInfo[i] = jedec_table[index].regions[i];
 	}
-	p_cfi->cmdset_priv = NULL;
+	cfi->cmdset_priv = NULL;
 
 	/* This may be redundant for some cases, but it doesn't hurt */
-	p_cfi->mfr = jedec_table[index].mfr_id;
-	p_cfi->id = jedec_table[index].dev_id;
+	cfi->mfr = jedec_table[index].mfr_id;
+	cfi->id = jedec_table[index].dev_id;
 
 	uaddr = jedec_table[index].uaddr;
 
@@ -1978,8 +1979,8 @@ static int cfi_jedec_setup(struct cfi_pr
 	   our brains explode when we see the datasheets talking about address
 	   lines numbered from A-1 to A18. The CFI table has unlock addresses
 	   in device-words according to the mode the device is connected in */
-	p_cfi->addr_unlock1 = unlock_addrs[uaddr].addr1 / p_cfi->device_type;
-	p_cfi->addr_unlock2 = unlock_addrs[uaddr].addr2 / p_cfi->device_type;
+	cfi->addr_unlock1 = unlock_addrs[uaddr].addr1 / cfi->device_type;
+	cfi->addr_unlock2 = unlock_addrs[uaddr].addr2 / cfi->device_type;
 
 	return 1;	/* ok */
 }
@@ -2175,7 +2176,7 @@ static int jedec_probe_chip(struct map_i
 				       "MTD %s(): matched device 0x%x,0x%x unlock_addrs: 0x%.4x 0x%.4x\n",
 				       __func__, cfi->mfr, cfi->id,
 				       cfi->addr_unlock1, cfi->addr_unlock2 );
-				if (!cfi_jedec_setup(cfi, i))
+				if (!cfi_jedec_setup(map, cfi, i))
 					return 0;
 				goto ok_out;
 			}
diff -druNp linux-libre-2.6.37-gnu1/drivers/mtd/devices/block2mtd.c linux-libre-2.6.38-gnu1/drivers/mtd/devices/block2mtd.c
--- linux-libre-2.6.37-gnu1/drivers/mtd/devices/block2mtd.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mtd/devices/block2mtd.c	2011-03-14 21:20:32.000000000 -0400
@@ -224,7 +224,7 @@ static void block2mtd_free_device(struct
 	if (dev->blkdev) {
 		invalidate_mapping_pages(dev->blkdev->bd_inode->i_mapping,
 					0, -1);
-		close_bdev_exclusive(dev->blkdev, FMODE_READ|FMODE_WRITE);
+		blkdev_put(dev->blkdev, FMODE_READ|FMODE_WRITE|FMODE_EXCL);
 	}
 
 	kfree(dev);
@@ -234,6 +234,7 @@ static void block2mtd_free_device(struct
 /* FIXME: ensure that mtd->size % erase_size == 0 */
 static struct block2mtd_dev *add_device(char *devname, int erase_size)
 {
+	const fmode_t mode = FMODE_READ | FMODE_WRITE | FMODE_EXCL;
 	struct block_device *bdev;
 	struct block2mtd_dev *dev;
 	char *name;
@@ -246,7 +247,7 @@ static struct block2mtd_dev *add_device(
 		return NULL;
 
 	/* Get a handle on the device */
-	bdev = open_bdev_exclusive(devname, FMODE_READ|FMODE_WRITE, NULL);
+	bdev = blkdev_get_by_path(devname, mode, dev);
 #ifndef MODULE
 	if (IS_ERR(bdev)) {
 
@@ -254,9 +255,8 @@ static struct block2mtd_dev *add_device(
 		   to resolve the device name by other means. */
 
 		dev_t devt = name_to_dev_t(devname);
-		if (devt) {
-			bdev = open_by_devnum(devt, FMODE_WRITE | FMODE_READ);
-		}
+		if (devt)
+			bdev = blkdev_get_by_dev(devt, mode, dev);
 	}
 #endif
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/mtd/devices/m25p80.c linux-libre-2.6.38-gnu1/drivers/mtd/devices/m25p80.c
--- linux-libre-2.6.37-gnu1/drivers/mtd/devices/m25p80.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mtd/devices/m25p80.c	2011-03-14 21:20:32.000000000 -0400
@@ -51,6 +51,10 @@
 #define	OPCODE_WRDI		0x04	/* Write disable */
 #define	OPCODE_AAI_WP		0xad	/* Auto address increment word program */
 
+/* Used for Macronix flashes only. */
+#define	OPCODE_EN4B		0xb7	/* Enter 4-byte mode */
+#define	OPCODE_EX4B		0xe9	/* Exit 4-byte mode */
+
 /* Status Register bits. */
 #define	SR_WIP			1	/* Write in progress */
 #define	SR_WEL			2	/* Write enable latch */
@@ -62,7 +66,7 @@
 
 /* Define max times to check status register before we give up. */
 #define	MAX_READY_WAIT_JIFFIES	(40 * HZ)	/* M25P16 specs 40s max chip erase */
-#define	MAX_CMD_SIZE		4
+#define	MAX_CMD_SIZE		5
 
 #ifdef CONFIG_M25PXX_USE_FAST_READ
 #define OPCODE_READ 	OPCODE_FAST_READ
@@ -152,6 +156,16 @@ static inline int write_disable(struct m
 }
 
 /*
+ * Enable/disable 4-byte addressing mode.
+ */
+static inline int set_4byte(struct m25p *flash, int enable)
+{
+	u8	code = enable ? OPCODE_EN4B : OPCODE_EX4B;
+
+	return spi_write_then_read(flash->spi, &code, 1, NULL, 0);
+}
+
+/*
  * Service routine to read status register until ready, or timeout occurs.
  * Returns non-zero if error.
  */
@@ -207,6 +221,7 @@ static void m25p_addr2cmd(struct m25p *f
 	cmd[1] = addr >> (flash->addr_width * 8 -  8);
 	cmd[2] = addr >> (flash->addr_width * 8 - 16);
 	cmd[3] = addr >> (flash->addr_width * 8 - 24);
+	cmd[4] = addr >> (flash->addr_width * 8 - 32);
 }
 
 static int m25p_cmdsz(struct m25p *flash)
@@ -482,6 +497,10 @@ static int sst_write(struct mtd_info *mt
 	size_t actual;
 	int cmd_sz, ret;
 
+	DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %zd\n",
+			dev_name(&flash->spi->dev), __func__, "to",
+			(u32)to, len);
+
 	*retlen = 0;
 
 	/* sanity checks */
@@ -607,7 +626,6 @@ struct flash_info {
 		.sector_size = (_sector_size),				\
 		.n_sectors = (_n_sectors),				\
 		.page_size = 256,					\
-		.addr_width = 3,					\
 		.flags = (_flags),					\
 	})
 
@@ -635,7 +653,7 @@ static const struct spi_device_id m25p_i
 	{ "at26f004",   INFO(0x1f0400, 0, 64 * 1024,  8, SECT_4K) },
 	{ "at26df081a", INFO(0x1f4501, 0, 64 * 1024, 16, SECT_4K) },
 	{ "at26df161a", INFO(0x1f4601, 0, 64 * 1024, 32, SECT_4K) },
-	{ "at26df321",  INFO(0x1f4701, 0, 64 * 1024, 64, SECT_4K) },
+	{ "at26df321",  INFO(0x1f4700, 0, 64 * 1024, 64, SECT_4K) },
 
 	/* EON -- en25pxx */
 	{ "en25p32", INFO(0x1c2016, 0, 64 * 1024,  64, 0) },
@@ -653,6 +671,8 @@ static const struct spi_device_id m25p_i
 	{ "mx25l6405d",  INFO(0xc22017, 0, 64 * 1024, 128, 0) },
 	{ "mx25l12805d", INFO(0xc22018, 0, 64 * 1024, 256, 0) },
 	{ "mx25l12855e", INFO(0xc22618, 0, 64 * 1024, 256, 0) },
+	{ "mx25l25635e", INFO(0xc22019, 0, 64 * 1024, 512, 0) },
+	{ "mx25l25655e", INFO(0xc22619, 0, 64 * 1024, 512, 0) },
 
 	/* Spansion -- single (large) sector size only, at least
 	 * for the chips listed here (without boot sectors).
@@ -764,6 +784,7 @@ static const struct spi_device_id *__dev
 			return &m25p_ids[tmp];
 		}
 	}
+	dev_err(&spi->dev, "unrecognized JEDEC id %06x\n", jedec);
 	return ERR_PTR(-ENODEV);
 }
 
@@ -883,7 +904,17 @@ static int __devinit m25p_probe(struct s
 
 	flash->mtd.dev.parent = &spi->dev;
 	flash->page_size = info->page_size;
-	flash->addr_width = info->addr_width;
+
+	if (info->addr_width)
+		flash->addr_width = info->addr_width;
+	else {
+		/* enable 4-byte addressing if the device exceeds 16MiB */
+		if (flash->mtd.size > 0x1000000) {
+			flash->addr_width = 4;
+			set_4byte(flash, 1);
+		} else
+			flash->addr_width = 3;
+	}
 
 	dev_info(&spi->dev, "%s (%lld Kbytes)\n", id->name,
 			(long long)flash->mtd.size >> 10);
diff -druNp linux-libre-2.6.37-gnu1/drivers/mtd/devices/sst25l.c linux-libre-2.6.38-gnu1/drivers/mtd/devices/sst25l.c
--- linux-libre-2.6.37-gnu1/drivers/mtd/devices/sst25l.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mtd/devices/sst25l.c	2011-03-14 21:20:32.000000000 -0400
@@ -335,7 +335,7 @@ out:
 	return ret;
 }
 
-static struct flash_info *__init sst25l_match_device(struct spi_device *spi)
+static struct flash_info *__devinit sst25l_match_device(struct spi_device *spi)
 {
 	struct flash_info *flash_info = NULL;
 	struct spi_message m;
@@ -375,7 +375,7 @@ static struct flash_info *__init sst25l_
 	return flash_info;
 }
 
-static int __init sst25l_probe(struct spi_device *spi)
+static int __devinit sst25l_probe(struct spi_device *spi)
 {
 	struct flash_info *flash_info;
 	struct sst25l_flash *flash;
diff -druNp linux-libre-2.6.37-gnu1/drivers/mtd/Kconfig linux-libre-2.6.38-gnu1/drivers/mtd/Kconfig
--- linux-libre-2.6.37-gnu1/drivers/mtd/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mtd/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -53,9 +53,10 @@ config MTD_PARTITIONS
 	  devices. Partitioning on NFTL 'devices' is a different - that's the
 	  'normal' form of partitioning used on a block device.
 
+if MTD_PARTITIONS
+
 config MTD_REDBOOT_PARTS
 	tristate "RedBoot partition table parsing"
-	depends on MTD_PARTITIONS
 	---help---
 	  RedBoot is a ROM monitor and bootloader which deals with multiple
 	  'images' in flash devices by putting a table one of the erase
@@ -72,9 +73,10 @@ config MTD_REDBOOT_PARTS
 	  SA1100 map driver (CONFIG_MTD_SA1100) has an option for this, for
 	  example.
 
+if MTD_REDBOOT_PARTS
+
 config MTD_REDBOOT_DIRECTORY_BLOCK
 	int "Location of RedBoot partition table"
-	depends on MTD_REDBOOT_PARTS
 	default "-1"
 	---help---
 	  This option is the Linux counterpart to the
@@ -91,18 +93,18 @@ config MTD_REDBOOT_DIRECTORY_BLOCK
 
 config MTD_REDBOOT_PARTS_UNALLOCATED
 	bool "Include unallocated flash regions"
-	depends on MTD_REDBOOT_PARTS
 	help
 	  If you need to register each unallocated flash region as a MTD
 	  'partition', enable this option.
 
 config MTD_REDBOOT_PARTS_READONLY
 	bool "Force read-only for RedBoot system images"
-	depends on MTD_REDBOOT_PARTS
 	help
 	  If you need to force read-only for 'RedBoot', 'RedBoot Config' and
 	  'FIS directory' images, enable this option.
 
+endif # MTD_REDBOOT_PARTS
+
 config MTD_CMDLINE_PARTS
 	bool "Command line partition table parsing"
 	depends on MTD_PARTITIONS = "y" && MTD = "y"
@@ -142,7 +144,7 @@ config MTD_CMDLINE_PARTS
 
 config MTD_AFS_PARTS
 	tristate "ARM Firmware Suite partition parsing"
-	depends on ARM && MTD_PARTITIONS
+	depends on ARM
 	---help---
 	  The ARM Firmware Suite allows the user to divide flash devices into
 	  multiple 'images'. Each such image has a header containing its name
@@ -158,8 +160,8 @@ config MTD_AFS_PARTS
 	  example.
 
 config MTD_OF_PARTS
-	tristate "Flash partition map based on OF description"
-	depends on (MICROBLAZE || PPC_OF) && MTD_PARTITIONS
+	def_bool y
+	depends on OF
 	help
 	  This provides a partition parsing function which derives
 	  the partition map from the children of the flash node,
@@ -167,10 +169,11 @@ config MTD_OF_PARTS
 
 config MTD_AR7_PARTS
 	tristate "TI AR7 partitioning support"
-	depends on MTD_PARTITIONS
 	---help---
 	  TI AR7 partitioning support
 
+endif # MTD_PARTITIONS
+
 comment "User Modules And Translation Layers"
 
 config MTD_CHAR
diff -druNp linux-libre-2.6.37-gnu1/drivers/mtd/Makefile linux-libre-2.6.38-gnu1/drivers/mtd/Makefile
--- linux-libre-2.6.37-gnu1/drivers/mtd/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mtd/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -6,13 +6,13 @@
 obj-$(CONFIG_MTD)		+= mtd.o
 mtd-y				:= mtdcore.o mtdsuper.o
 mtd-$(CONFIG_MTD_PARTITIONS)	+= mtdpart.o
+mtd-$(CONFIG_MTD_OF_PARTS)	+= ofpart.o
 
 obj-$(CONFIG_MTD_CONCAT)	+= mtdconcat.o
 obj-$(CONFIG_MTD_REDBOOT_PARTS) += redboot.o
 obj-$(CONFIG_MTD_CMDLINE_PARTS) += cmdlinepart.o
 obj-$(CONFIG_MTD_AFS_PARTS)	+= afs.o
 obj-$(CONFIG_MTD_AR7_PARTS)	+= ar7part.o
-obj-$(CONFIG_MTD_OF_PARTS)      += ofpart.o
 
 # 'Users' - code which presents functionality to userspace.
 obj-$(CONFIG_MTD_CHAR)		+= mtdchar.o
diff -druNp linux-libre-2.6.37-gnu1/drivers/mtd/maps/amd76xrom.c linux-libre-2.6.38-gnu1/drivers/mtd/maps/amd76xrom.c
--- linux-libre-2.6.37-gnu1/drivers/mtd/maps/amd76xrom.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mtd/maps/amd76xrom.c	2011-03-14 21:20:32.000000000 -0400
@@ -149,11 +149,9 @@ static int __devinit amd76xrom_init_one
 	if (request_resource(&iomem_resource, &window->rsrc)) {
 		window->rsrc.parent = NULL;
 		printk(KERN_ERR MOD_NAME
-			" %s(): Unable to register resource"
-			" 0x%.16llx-0x%.16llx - kernel bug?\n",
-			__func__,
-			(unsigned long long)window->rsrc.start,
-			(unsigned long long)window->rsrc.end);
+		       " %s(): Unable to register resource %pR - kernel bug?\n",
+		       __func__, &window->rsrc);
+		return -EBUSY;
 	}
 
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/mtd/maps/bcm963xx-flash.c linux-libre-2.6.38-gnu1/drivers/mtd/maps/bcm963xx-flash.c
--- linux-libre-2.6.37-gnu1/drivers/mtd/maps/bcm963xx-flash.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mtd/maps/bcm963xx-flash.c	2011-03-14 21:20:32.000000000 -0400
@@ -196,10 +196,15 @@ static int bcm963xx_probe(struct platfor
 	bcm963xx_mtd_info = do_map_probe("cfi_probe", &bcm963xx_map);
 	if (!bcm963xx_mtd_info) {
 		dev_err(&pdev->dev, "failed to probe using CFI\n");
+		bcm963xx_mtd_info = do_map_probe("jedec_probe", &bcm963xx_map);
+		if (bcm963xx_mtd_info)
+			goto probe_ok;
+		dev_err(&pdev->dev, "failed to probe using JEDEC\n");
 		err = -EIO;
 		goto err_probe;
 	}
 
+probe_ok:
 	bcm963xx_mtd_info->owner = THIS_MODULE;
 
 	/* This is mutually exclusive */
diff -druNp linux-libre-2.6.37-gnu1/drivers/mtd/maps/ck804xrom.c linux-libre-2.6.38-gnu1/drivers/mtd/maps/ck804xrom.c
--- linux-libre-2.6.37-gnu1/drivers/mtd/maps/ck804xrom.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mtd/maps/ck804xrom.c	2011-03-14 21:20:32.000000000 -0400
@@ -178,11 +178,8 @@ static int __devinit ck804xrom_init_one
 	if (request_resource(&iomem_resource, &window->rsrc)) {
 		window->rsrc.parent = NULL;
 		printk(KERN_ERR MOD_NAME
-			" %s(): Unable to register resource"
-			" 0x%.016llx-0x%.016llx - kernel bug?\n",
-			__func__,
-			(unsigned long long)window->rsrc.start,
-			(unsigned long long)window->rsrc.end);
+		       " %s(): Unable to register resource %pR - kernel bug?\n",
+			__func__, &window->rsrc);
 	}
 
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/mtd/maps/esb2rom.c linux-libre-2.6.38-gnu1/drivers/mtd/maps/esb2rom.c
--- linux-libre-2.6.37-gnu1/drivers/mtd/maps/esb2rom.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mtd/maps/esb2rom.c	2011-03-14 21:20:32.000000000 -0400
@@ -242,12 +242,9 @@ static int __devinit esb2rom_init_one(st
 	window->rsrc.flags = IORESOURCE_MEM | IORESOURCE_BUSY;
 	if (request_resource(&iomem_resource, &window->rsrc)) {
 		window->rsrc.parent = NULL;
-		printk(KERN_DEBUG MOD_NAME
-			": %s(): Unable to register resource"
-			" 0x%.08llx-0x%.08llx - kernel bug?\n",
-			__func__,
-			(unsigned long long)window->rsrc.start,
-			(unsigned long long)window->rsrc.end);
+		printk(KERN_DEBUG MOD_NAME ": "
+		       "%s(): Unable to register resource %pR - kernel bug?\n",
+			__func__, &window->rsrc);
 	}
 
 	/* Map the firmware hub into my address space. */
diff -druNp linux-libre-2.6.37-gnu1/drivers/mtd/maps/ichxrom.c linux-libre-2.6.38-gnu1/drivers/mtd/maps/ichxrom.c
--- linux-libre-2.6.37-gnu1/drivers/mtd/maps/ichxrom.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mtd/maps/ichxrom.c	2011-03-14 21:20:32.000000000 -0400
@@ -175,12 +175,9 @@ static int __devinit ichxrom_init_one (s
 	window->rsrc.flags = IORESOURCE_MEM | IORESOURCE_BUSY;
 	if (request_resource(&iomem_resource, &window->rsrc)) {
 		window->rsrc.parent = NULL;
-		printk(KERN_DEBUG MOD_NAME
-			": %s(): Unable to register resource"
-			" 0x%.16llx-0x%.16llx - kernel bug?\n",
-			__func__,
-			(unsigned long long)window->rsrc.start,
-			(unsigned long long)window->rsrc.end);
+		printk(KERN_DEBUG MOD_NAME ": "
+		       "%s(): Unable to register resource %pR - kernel bug?\n",
+		       __func__, &window->rsrc);
 	}
 
 	/* Map the firmware hub into my address space. */
diff -druNp linux-libre-2.6.37-gnu1/drivers/mtd/maps/Kconfig linux-libre-2.6.38-gnu1/drivers/mtd/maps/Kconfig
--- linux-libre-2.6.37-gnu1/drivers/mtd/maps/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mtd/maps/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -72,7 +72,7 @@ config MTD_PHYSMAP_BANKWIDTH
 
 config MTD_PHYSMAP_OF
 	tristate "Flash device in physical memory map based on OF description"
-	depends on (MICROBLAZE || PPC_OF) && (MTD_CFI || MTD_JEDECPROBE || MTD_ROM)
+	depends on OF && (MTD_CFI || MTD_JEDECPROBE || MTD_ROM)
 	help
 	  This provides a 'mapping' driver which allows the NOR Flash and
 	  ROM driver code to communicate with chips which are mapped
diff -druNp linux-libre-2.6.37-gnu1/drivers/mtd/maps/physmap_of.c linux-libre-2.6.38-gnu1/drivers/mtd/maps/physmap_of.c
--- linux-libre-2.6.37-gnu1/drivers/mtd/maps/physmap_of.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mtd/maps/physmap_of.c	2011-03-14 21:20:32.000000000 -0400
@@ -274,9 +274,7 @@ static int __devinit of_flash_probe(stru
 			continue;
 		}
 
-		dev_dbg(&dev->dev, "of_flash device: %.8llx-%.8llx\n",
-			(unsigned long long)res.start,
-			(unsigned long long)res.end);
+		dev_dbg(&dev->dev, "of_flash device: %pR\n", &res);
 
 		err = -EBUSY;
 		res_size = resource_size(&res);
diff -druNp linux-libre-2.6.37-gnu1/drivers/mtd/maps/scx200_docflash.c linux-libre-2.6.38-gnu1/drivers/mtd/maps/scx200_docflash.c
--- linux-libre-2.6.37-gnu1/drivers/mtd/maps/scx200_docflash.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mtd/maps/scx200_docflash.c	2011-03-14 21:20:32.000000000 -0400
@@ -166,9 +166,8 @@ static int __init init_scx200_docflash(v
 		outl(pmr, scx200_cb_base + SCx200_PMR);
 	}
 
-       	printk(KERN_INFO NAME ": DOCCS mapped at 0x%llx-0x%llx, width %d\n",
-			(unsigned long long)docmem.start,
-			(unsigned long long)docmem.end, width);
+	printk(KERN_INFO NAME ": DOCCS mapped at %pR, width %d\n",
+	       &docmem, width);
 
 	scx200_docflash_map.size = size;
 	if (width == 8)
diff -druNp linux-libre-2.6.37-gnu1/drivers/mtd/maps/tqm8xxl.c linux-libre-2.6.38-gnu1/drivers/mtd/maps/tqm8xxl.c
--- linux-libre-2.6.37-gnu1/drivers/mtd/maps/tqm8xxl.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mtd/maps/tqm8xxl.c	2011-03-14 21:20:32.000000000 -0400
@@ -139,7 +139,7 @@ static int __init init_tqm_mtd(void)
 			goto error_mem;
 		}
 
-		map_banks[idx]->name = (char *)kmalloc(16, GFP_KERNEL);
+		map_banks[idx]->name = kmalloc(16, GFP_KERNEL);
 
 		if (!map_banks[idx]->name) {
 			ret = -ENOMEM;
diff -druNp linux-libre-2.6.37-gnu1/drivers/mtd/mtd_blkdevs.c linux-libre-2.6.38-gnu1/drivers/mtd/mtd_blkdevs.c
--- linux-libre-2.6.37-gnu1/drivers/mtd/mtd_blkdevs.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mtd/mtd_blkdevs.c	2011-03-14 21:20:32.000000000 -0400
@@ -413,7 +413,6 @@ error3:
 error2:
 	list_del(&new->list);
 error1:
-	kfree(new);
 	return ret;
 }
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/mtd/mtdchar.c linux-libre-2.6.38-gnu1/drivers/mtd/mtdchar.c
--- linux-libre-2.6.37-gnu1/drivers/mtd/mtdchar.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mtd/mtdchar.c	2011-03-14 21:20:32.000000000 -0400
@@ -522,10 +522,6 @@ static int mtd_blkpg_ioctl(struct mtd_in
 	if (!capable(CAP_SYS_ADMIN))
 		return -EPERM;
 
-	/* Only master mtd device must be used to control partitions */
-	if (!mtd_is_master(mtd))
-		return -EINVAL;
-
 	if (copy_from_user(&a, arg, sizeof(struct blkpg_ioctl_arg)))
 		return -EFAULT;
 
@@ -535,6 +531,10 @@ static int mtd_blkpg_ioctl(struct mtd_in
 	switch (a.op) {
 	case BLKPG_ADD_PARTITION:
 
+		/* Only master mtd device must be used to add partitions */
+		if (mtd_is_partition(mtd))
+			return -EINVAL;
+
 		return mtd_add_partition(mtd, p.devname, p.start, p.length);
 
 	case BLKPG_DEL_PARTITION:
@@ -601,6 +601,7 @@ static int mtd_ioctl(struct file *file,
 	}
 
 	case MEMGETINFO:
+		memset(&info, 0, sizeof(info));
 		info.type	= mtd->type;
 		info.flags	= mtd->flags;
 		info.size	= mtd->size;
@@ -609,7 +610,6 @@ static int mtd_ioctl(struct file *file,
 		info.oobsize	= mtd->oobsize;
 		/* The below fields are obsolete */
 		info.ecctype	= -1;
-		info.eccsize	= 0;
 		if (copy_to_user(argp, &info, sizeof(struct mtd_info_user)))
 			return -EFAULT;
 		break;
@@ -1134,7 +1134,7 @@ static const struct file_operations mtd_
 static struct dentry *mtd_inodefs_mount(struct file_system_type *fs_type,
 				int flags, const char *dev_name, void *data)
 {
-	return mount_pseudo(fs_type, "mtd_inode:", NULL, MTD_INODE_FS_MAGIC);
+	return mount_pseudo(fs_type, "mtd_inode:", NULL, NULL, MTD_INODE_FS_MAGIC);
 }
 
 static struct file_system_type mtd_inodefs_type = {
diff -druNp linux-libre-2.6.37-gnu1/drivers/mtd/mtdconcat.c linux-libre-2.6.38-gnu1/drivers/mtd/mtdconcat.c
--- linux-libre-2.6.37-gnu1/drivers/mtd/mtdconcat.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mtd/mtdconcat.c	2011-03-14 21:20:32.000000000 -0400
@@ -776,6 +776,7 @@ struct mtd_info *mtd_concat_create(struc
 	concat->mtd.size = subdev[0]->size;
 	concat->mtd.erasesize = subdev[0]->erasesize;
 	concat->mtd.writesize = subdev[0]->writesize;
+	concat->mtd.writebufsize = subdev[0]->writebufsize;
 	concat->mtd.subpage_sft = subdev[0]->subpage_sft;
 	concat->mtd.oobsize = subdev[0]->oobsize;
 	concat->mtd.oobavail = subdev[0]->oobavail;
diff -druNp linux-libre-2.6.37-gnu1/drivers/mtd/mtdoops.c linux-libre-2.6.38-gnu1/drivers/mtd/mtdoops.c
--- linux-libre-2.6.37-gnu1/drivers/mtd/mtdoops.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mtd/mtdoops.c	2011-03-14 21:20:32.000000000 -0400
@@ -307,6 +307,11 @@ static void mtdoops_do_dump(struct kmsg_
 	unsigned long l1_cpy, l2_cpy;
 	char *dst;
 
+	if (reason != KMSG_DUMP_OOPS &&
+	    reason != KMSG_DUMP_PANIC &&
+	    reason != KMSG_DUMP_KEXEC)
+		return;
+
 	/* Only dump oopses if dump_oops is set */
 	if (reason == KMSG_DUMP_OOPS && !dump_oops)
 		return;
@@ -396,7 +401,8 @@ static void mtdoops_notify_remove(struct
 		printk(KERN_WARNING "mtdoops: could not unregister kmsg_dumper\n");
 
 	cxt->mtd = NULL;
-	flush_scheduled_work();
+	flush_work_sync(&cxt->work_erase);
+	flush_work_sync(&cxt->work_write);
 }
 
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/mtd/mtdpart.c linux-libre-2.6.38-gnu1/drivers/mtd/mtdpart.c
--- linux-libre-2.6.37-gnu1/drivers/mtd/mtdpart.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mtd/mtdpart.c	2011-03-14 21:20:32.000000000 -0400
@@ -120,8 +120,25 @@ static int part_read_oob(struct mtd_info
 		return -EINVAL;
 	if (ops->datbuf && from + ops->len > mtd->size)
 		return -EINVAL;
-	res = part->master->read_oob(part->master, from + part->offset, ops);
 
+	/*
+	 * If OOB is also requested, make sure that we do not read past the end
+	 * of this partition.
+	 */
+	if (ops->oobbuf) {
+		size_t len, pages;
+
+		if (ops->mode == MTD_OOB_AUTO)
+			len = mtd->oobavail;
+		else
+			len = mtd->oobsize;
+		pages = mtd_div_by_ws(mtd->size, mtd);
+		pages -= mtd_div_by_ws(from, mtd);
+		if (ops->ooboffs + ops->ooblen > pages * len)
+			return -EINVAL;
+	}
+
+	res = part->master->read_oob(part->master, from + part->offset, ops);
 	if (unlikely(res)) {
 		if (res == -EUCLEAN)
 			mtd->ecc_stats.corrected++;
@@ -384,6 +401,7 @@ static struct mtd_part *allocate_partiti
 	slave->mtd.flags = master->flags & ~part->mask_flags;
 	slave->mtd.size = part->size;
 	slave->mtd.writesize = master->writesize;
+	slave->mtd.writebufsize = master->writebufsize;
 	slave->mtd.oobsize = master->oobsize;
 	slave->mtd.oobavail = master->oobavail;
 	slave->mtd.subpage_sft = master->subpage_sft;
@@ -720,19 +738,19 @@ int parse_mtd_partitions(struct mtd_info
 }
 EXPORT_SYMBOL_GPL(parse_mtd_partitions);
 
-int mtd_is_master(struct mtd_info *mtd)
+int mtd_is_partition(struct mtd_info *mtd)
 {
 	struct mtd_part *part;
-	int nopart = 0;
+	int ispart = 0;
 
 	mutex_lock(&mtd_partitions_mutex);
 	list_for_each_entry(part, &mtd_partitions, list)
 		if (&part->mtd == mtd) {
-			nopart = 1;
+			ispart = 1;
 			break;
 		}
 	mutex_unlock(&mtd_partitions_mutex);
 
-	return nopart;
+	return ispart;
 }
-EXPORT_SYMBOL_GPL(mtd_is_master);
+EXPORT_SYMBOL_GPL(mtd_is_partition);
diff -druNp linux-libre-2.6.37-gnu1/drivers/mtd/nand/ams-delta.c linux-libre-2.6.38-gnu1/drivers/mtd/nand/ams-delta.c
--- linux-libre-2.6.37-gnu1/drivers/mtd/nand/ams-delta.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mtd/nand/ams-delta.c	2011-03-14 21:20:32.000000000 -0400
@@ -4,6 +4,8 @@
  *  Copyright (C) 2006 Jonathan McDowell <noodles@earth.li>
  *
  *  Derived from drivers/mtd/toto.c
+ *  Converted to platform driver by Janusz Krzysztofik <jkrzyszt@tis.icnet.pl>
+ *  Partially stolen from drivers/mtd/nand/plat_nand.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
@@ -62,9 +64,10 @@ static struct mtd_partition partition_in
 static void ams_delta_write_byte(struct mtd_info *mtd, u_char byte)
 {
 	struct nand_chip *this = mtd->priv;
+	void __iomem *io_base = this->priv;
 
-	omap_writew(0, (OMAP1_MPUIO_BASE + OMAP_MPUIO_IO_CNTL));
-	omap_writew(byte, this->IO_ADDR_W);
+	writew(0, io_base + OMAP_MPUIO_IO_CNTL);
+	writew(byte, this->IO_ADDR_W);
 	ams_delta_latch2_write(AMS_DELTA_LATCH2_NAND_NWE, 0);
 	ndelay(40);
 	ams_delta_latch2_write(AMS_DELTA_LATCH2_NAND_NWE,
@@ -75,11 +78,12 @@ static u_char ams_delta_read_byte(struct
 {
 	u_char res;
 	struct nand_chip *this = mtd->priv;
+	void __iomem *io_base = this->priv;
 
 	ams_delta_latch2_write(AMS_DELTA_LATCH2_NAND_NRE, 0);
 	ndelay(40);
-	omap_writew(~0, (OMAP1_MPUIO_BASE + OMAP_MPUIO_IO_CNTL));
-	res = omap_readw(this->IO_ADDR_R);
+	writew(~0, io_base + OMAP_MPUIO_IO_CNTL);
+	res = readw(this->IO_ADDR_R);
 	ams_delta_latch2_write(AMS_DELTA_LATCH2_NAND_NRE,
 			       AMS_DELTA_LATCH2_NAND_NRE);
 
@@ -151,11 +155,16 @@ static int ams_delta_nand_ready(struct m
 /*
  * Main initialization routine
  */
-static int __init ams_delta_init(void)
+static int __devinit ams_delta_init(struct platform_device *pdev)
 {
 	struct nand_chip *this;
+	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	void __iomem *io_base;
 	int err = 0;
 
+	if (!res)
+		return -ENXIO;
+
 	/* Allocate memory for MTD device structure and private data */
 	ams_delta_mtd = kmalloc(sizeof(struct mtd_info) +
 				sizeof(struct nand_chip), GFP_KERNEL);
@@ -177,9 +186,25 @@ static int __init ams_delta_init(void)
 	/* Link the private data with the MTD structure */
 	ams_delta_mtd->priv = this;
 
+	if (!request_mem_region(res->start, resource_size(res),
+			dev_name(&pdev->dev))) {
+		dev_err(&pdev->dev, "request_mem_region failed\n");
+		err = -EBUSY;
+		goto out_free;
+	}
+
+	io_base = ioremap(res->start, resource_size(res));
+	if (io_base == NULL) {
+		dev_err(&pdev->dev, "ioremap failed\n");
+		err = -EIO;
+		goto out_release_io;
+	}
+
+	this->priv = io_base;
+
 	/* Set address of NAND IO lines */
-	this->IO_ADDR_R = (OMAP1_MPUIO_BASE + OMAP_MPUIO_INPUT_LATCH);
-	this->IO_ADDR_W = (OMAP1_MPUIO_BASE + OMAP_MPUIO_OUTPUT);
+	this->IO_ADDR_R = io_base + OMAP_MPUIO_INPUT_LATCH;
+	this->IO_ADDR_W = io_base + OMAP_MPUIO_OUTPUT;
 	this->read_byte = ams_delta_read_byte;
 	this->write_buf = ams_delta_write_buf;
 	this->read_buf = ams_delta_read_buf;
@@ -195,6 +220,8 @@ static int __init ams_delta_init(void)
 	this->chip_delay = 30;
 	this->ecc.mode = NAND_ECC_SOFT;
 
+	platform_set_drvdata(pdev, io_base);
+
 	/* Set chip enabled, but  */
 	ams_delta_latch2_write(NAND_MASK, AMS_DELTA_LATCH2_NAND_NRE |
 					  AMS_DELTA_LATCH2_NAND_NWE |
@@ -214,25 +241,56 @@ static int __init ams_delta_init(void)
 	goto out;
 
  out_mtd:
+	platform_set_drvdata(pdev, NULL);
+	iounmap(io_base);
+out_release_io:
+	release_mem_region(res->start, resource_size(res));
+out_free:
 	kfree(ams_delta_mtd);
  out:
 	return err;
 }
 
-module_init(ams_delta_init);
-
 /*
  * Clean up routine
  */
-static void __exit ams_delta_cleanup(void)
+static int __devexit ams_delta_cleanup(struct platform_device *pdev)
 {
+	void __iomem *io_base = platform_get_drvdata(pdev);
+	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
 	/* Release resources, unregister device */
 	nand_release(ams_delta_mtd);
 
+	iounmap(io_base);
+	release_mem_region(res->start, resource_size(res));
+
 	/* Free the MTD device structure */
 	kfree(ams_delta_mtd);
+
+	return 0;
 }
-module_exit(ams_delta_cleanup);
+
+static struct platform_driver ams_delta_nand_driver = {
+	.probe		= ams_delta_init,
+	.remove		= __devexit_p(ams_delta_cleanup),
+	.driver		= {
+		.name	= "ams-delta-nand",
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init ams_delta_nand_init(void)
+{
+	return platform_driver_register(&ams_delta_nand_driver);
+}
+module_init(ams_delta_nand_init);
+
+static void __exit ams_delta_nand_exit(void)
+{
+	platform_driver_unregister(&ams_delta_nand_driver);
+}
+module_exit(ams_delta_nand_exit);
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Jonathan McDowell <noodles@earth.li>");
diff -druNp linux-libre-2.6.37-gnu1/drivers/mtd/nand/fsl_elbc_nand.c linux-libre-2.6.38-gnu1/drivers/mtd/nand/fsl_elbc_nand.c
--- linux-libre-2.6.37-gnu1/drivers/mtd/nand/fsl_elbc_nand.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mtd/nand/fsl_elbc_nand.c	2011-03-14 21:20:32.000000000 -0400
@@ -388,6 +388,8 @@ static void fsl_elbc_cmdfunc(struct mtd_
 		         "page_addr: 0x%x, column: 0x%x.\n",
 		         page_addr, column);
 
+		elbc_fcm_ctrl->column = column;
+		elbc_fcm_ctrl->oob = 0;
 		elbc_fcm_ctrl->use_mdr = 1;
 
 		fcr = (NAND_CMD_STATUS   << FCR_CMD1_SHIFT) |
diff -druNp linux-libre-2.6.37-gnu1/drivers/mtd/nand/fsmc_nand.c linux-libre-2.6.38-gnu1/drivers/mtd/nand/fsmc_nand.c
--- linux-libre-2.6.37-gnu1/drivers/mtd/nand/fsmc_nand.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mtd/nand/fsmc_nand.c	2011-03-14 21:20:32.000000000 -0400
@@ -31,6 +31,7 @@
 #include <linux/io.h>
 #include <linux/slab.h>
 #include <linux/mtd/fsmc.h>
+#include <linux/amba/bus.h>
 #include <mtd/mtd-abi.h>
 
 static struct nand_ecclayout fsmc_ecc1_layout = {
@@ -119,21 +120,36 @@ static struct fsmc_eccplace fsmc_ecc4_sp
 	}
 };
 
-/*
- * Default partition tables to be used if the partition information not
- * provided through platform data
- */
-#define PARTITION(n, off, sz)	{.name = n, .offset = off, .size = sz}
 
+#ifdef CONFIG_MTD_PARTITIONS
 /*
+ * Default partition tables to be used if the partition information not
+ * provided through platform data.
+ *
  * Default partition layout for small page(= 512 bytes) devices
  * Size for "Root file system" is updated in driver based on actual device size
  */
 static struct mtd_partition partition_info_16KB_blk[] = {
-	PARTITION("X-loader", 0, 4 * 0x4000),
-	PARTITION("U-Boot", 0x10000, 20 * 0x4000),
-	PARTITION("Kernel", 0x60000, 256 * 0x4000),
-	PARTITION("Root File System", 0x460000, 0),
+	{
+		.name = "X-loader",
+		.offset = 0,
+		.size = 4*0x4000,
+	},
+	{
+		.name = "U-Boot",
+		.offset = 0x10000,
+		.size = 20*0x4000,
+	},
+	{
+		.name = "Kernel",
+		.offset = 0x60000,
+		.size = 256*0x4000,
+	},
+	{
+		.name = "Root File System",
+		.offset = 0x460000,
+		.size = 0,
+	},
 };
 
 /*
@@ -141,19 +157,37 @@ static struct mtd_partition partition_in
  * Size for "Root file system" is updated in driver based on actual device size
  */
 static struct mtd_partition partition_info_128KB_blk[] = {
-	PARTITION("X-loader", 0, 4 * 0x20000),
-	PARTITION("U-Boot", 0x80000, 12 * 0x20000),
-	PARTITION("Kernel", 0x200000, 48 * 0x20000),
-	PARTITION("Root File System", 0x800000, 0),
+	{
+		.name = "X-loader",
+		.offset = 0,
+		.size = 4*0x20000,
+	},
+	{
+		.name = "U-Boot",
+		.offset = 0x80000,
+		.size = 12*0x20000,
+	},
+	{
+		.name = "Kernel",
+		.offset = 0x200000,
+		.size = 48*0x20000,
+	},
+	{
+		.name = "Root File System",
+		.offset = 0x800000,
+		.size = 0,
+	},
 };
 
 #ifdef CONFIG_MTD_CMDLINE_PARTS
 const char *part_probes[] = { "cmdlinepart", NULL };
 #endif
+#endif
 
 /**
- * struct fsmc_nand_data - atructure for FSMC NAND device state
+ * struct fsmc_nand_data - structure for FSMC NAND device state
  *
+ * @pid:		Part ID on the AMBA PrimeCell format
  * @mtd:		MTD info for a NAND flash.
  * @nand:		Chip related info for a NAND flash.
  * @partitions:		Partition info for a NAND Flash.
@@ -169,6 +203,7 @@ const char *part_probes[] = { "cmdlinepa
  * @regs_va:		FSMC regs base address.
  */
 struct fsmc_nand_data {
+	u32			pid;
 	struct mtd_info		mtd;
 	struct nand_chip	nand;
 	struct mtd_partition	*partitions;
@@ -508,7 +543,9 @@ static int __init fsmc_nand_probe(struct
 	struct nand_chip *nand;
 	struct fsmc_regs *regs;
 	struct resource *res;
-	int nr_parts, ret = 0;
+	int ret = 0;
+	u32 pid;
+	int i;
 
 	if (!pdata) {
 		dev_err(&pdev->dev, "platform data is NULL\n");
@@ -598,6 +635,18 @@ static int __init fsmc_nand_probe(struct
 	if (ret)
 		goto err_probe1;
 
+	/*
+	 * This device ID is actually a common AMBA ID as used on the
+	 * AMBA PrimeCell bus. However it is not a PrimeCell.
+	 */
+	for (pid = 0, i = 0; i < 4; i++)
+		pid |= (readl(host->regs_va + resource_size(res) - 0x20 + 4 * i) & 255) << (i * 8);
+	host->pid = pid;
+	dev_info(&pdev->dev, "FSMC device partno %03x, manufacturer %02x, "
+		 "revision %02x, config %02x\n",
+		 AMBA_PART_BITS(pid), AMBA_MANF_BITS(pid),
+		 AMBA_REV_BITS(pid), AMBA_CONFIG_BITS(pid));
+
 	host->bank = pdata->bank;
 	host->select_chip = pdata->select_bank;
 	regs = host->regs_va;
@@ -625,7 +674,7 @@ static int __init fsmc_nand_probe(struct
 
 	fsmc_nand_setup(regs, host->bank, nand->options & NAND_BUSWIDTH_16);
 
-	if (get_fsmc_version(host->regs_va) == FSMC_VER8) {
+	if (AMBA_REV_BITS(host->pid) >= 8) {
 		nand->ecc.read_page = fsmc_read_page_hwecc;
 		nand->ecc.calculate = fsmc_read_hwecc_ecc4;
 		nand->ecc.correct = fsmc_correct_data;
@@ -645,7 +694,7 @@ static int __init fsmc_nand_probe(struct
 		goto err_probe;
 	}
 
-	if (get_fsmc_version(host->regs_va) == FSMC_VER8) {
+	if (AMBA_REV_BITS(host->pid) >= 8) {
 		if (host->mtd.writesize == 512) {
 			nand->ecc.layout = &fsmc_ecc4_sp_layout;
 			host->ecc_place = &fsmc_ecc4_sp_place;
@@ -676,11 +725,9 @@ static int __init fsmc_nand_probe(struct
 	 * Check if partition info passed via command line
 	 */
 	host->mtd.name = "nand";
-	nr_parts = parse_mtd_partitions(&host->mtd, part_probes,
+	host->nr_partitions = parse_mtd_partitions(&host->mtd, part_probes,
 			&host->partitions, 0);
-	if (nr_parts > 0) {
-		host->nr_partitions = nr_parts;
-	} else {
+	if (host->nr_partitions <= 0) {
 #endif
 		/*
 		 * Check if partition info passed via command line
diff -druNp linux-libre-2.6.37-gnu1/drivers/mtd/nand/jz4740_nand.c linux-libre-2.6.38-gnu1/drivers/mtd/nand/jz4740_nand.c
--- linux-libre-2.6.37-gnu1/drivers/mtd/nand/jz4740_nand.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mtd/nand/jz4740_nand.c	2011-03-14 21:20:32.000000000 -0400
@@ -251,58 +251,6 @@ static int jz_nand_correct_ecc_rs(struct
 	return 0;
 }
 
-
-/* Copy paste of nand_read_page_hwecc_oob_first except for different eccpos
- * handling. The ecc area is for 4k chips 72 bytes long and thus does not fit
- * into the eccpos array. */
-static int jz_nand_read_page_hwecc_oob_first(struct mtd_info *mtd,
-	struct nand_chip *chip, uint8_t *buf, int page)
-{
-	int i, eccsize = chip->ecc.size;
-	int eccbytes = chip->ecc.bytes;
-	int eccsteps = chip->ecc.steps;
-	uint8_t *p = buf;
-	unsigned int ecc_offset = chip->page_shift;
-
-	/* Read the OOB area first */
-	chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page);
-	chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
-	chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page);
-
-	for (i = ecc_offset; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
-		int stat;
-
-		chip->ecc.hwctl(mtd, NAND_ECC_READ);
-		chip->read_buf(mtd, p, eccsize);
-
-		stat = chip->ecc.correct(mtd, p, &chip->oob_poi[i], NULL);
-		if (stat < 0)
-			mtd->ecc_stats.failed++;
-		else
-			mtd->ecc_stats.corrected += stat;
-	}
-	return 0;
-}
-
-/* Copy-and-paste of nand_write_page_hwecc with different eccpos handling. */
-static void jz_nand_write_page_hwecc(struct mtd_info *mtd,
-	struct nand_chip *chip, const uint8_t *buf)
-{
-	int i, eccsize = chip->ecc.size;
-	int eccbytes = chip->ecc.bytes;
-	int eccsteps = chip->ecc.steps;
-	const uint8_t *p = buf;
-	unsigned int ecc_offset = chip->page_shift;
-
-	for (i = ecc_offset; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
-		chip->ecc.hwctl(mtd, NAND_ECC_WRITE);
-		chip->write_buf(mtd, p, eccsize);
-		chip->ecc.calculate(mtd, p, &chip->oob_poi[i]);
-	}
-
-	chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
-}
-
 #ifdef CONFIG_MTD_CMDLINE_PARTS
 static const char *part_probes[] = {"cmdline", NULL};
 #endif
@@ -393,9 +341,6 @@ static int __devinit jz_nand_probe(struc
 	chip->ecc.size		= 512;
 	chip->ecc.bytes		= 9;
 
-	chip->ecc.read_page	= jz_nand_read_page_hwecc_oob_first;
-	chip->ecc.write_page	= jz_nand_write_page_hwecc;
-
 	if (pdata)
 		chip->ecc.layout = pdata->ecc_layout;
 
@@ -489,7 +434,7 @@ static int __devexit jz_nand_remove(stru
 	return 0;
 }
 
-struct platform_driver jz_nand_driver = {
+static struct platform_driver jz_nand_driver = {
 	.probe = jz_nand_probe,
 	.remove = __devexit_p(jz_nand_remove),
 	.driver = {
diff -druNp linux-libre-2.6.37-gnu1/drivers/mtd/nand/Kconfig linux-libre-2.6.38-gnu1/drivers/mtd/nand/Kconfig
--- linux-libre-2.6.37-gnu1/drivers/mtd/nand/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mtd/nand/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -96,6 +96,7 @@ config MTD_NAND_SPIA
 config MTD_NAND_AMS_DELTA
 	tristate "NAND Flash device on Amstrad E3"
 	depends on MACH_AMS_DELTA
+	default y
 	help
 	  Support for NAND flash on Amstrad E3 (Delta).
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/mtd/nand/mxc_nand.c linux-libre-2.6.38-gnu1/drivers/mtd/nand/mxc_nand.c
--- linux-libre-2.6.37-gnu1/drivers/mtd/nand/mxc_nand.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mtd/nand/mxc_nand.c	2011-03-14 21:20:32.000000000 -0400
@@ -1009,7 +1009,7 @@ static int __init mxcnd_probe(struct pla
 	struct mxc_nand_platform_data *pdata = pdev->dev.platform_data;
 	struct mxc_nand_host *host;
 	struct resource *res;
-	int err = 0, nr_parts = 0;
+	int err = 0, __maybe_unused nr_parts = 0;
 	struct nand_ecclayout *oob_smallpage, *oob_largepage;
 
 	/* Allocate memory for MTD device structure and private data */
diff -druNp linux-libre-2.6.37-gnu1/drivers/mtd/nand/nand_base.c linux-libre-2.6.38-gnu1/drivers/mtd/nand/nand_base.c
--- linux-libre-2.6.37-gnu1/drivers/mtd/nand/nand_base.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mtd/nand/nand_base.c	2011-03-14 21:20:32.000000000 -0400
@@ -821,7 +821,7 @@ retry:
  *
  * Wait for command done. This is a helper function for nand_wait used when
  * we are in interrupt context. May happen when in panic and trying to write
- * an oops trough mtdoops.
+ * an oops through mtdoops.
  */
 static void panic_nand_wait(struct mtd_info *mtd, struct nand_chip *chip,
 			    unsigned long timeo)
@@ -2865,20 +2865,24 @@ static int nand_flash_detect_onfi(struct
 
 	/* check version */
 	val = le16_to_cpu(p->revision);
-	if (val == 1 || val > (1 << 4)) {
-		printk(KERN_INFO "%s: unsupported ONFI version: %d\n",
-								__func__, val);
-		return 0;
-	}
-
-	if (val & (1 << 4))
+	if (val & (1 << 5))
+		chip->onfi_version = 23;
+	else if (val & (1 << 4))
 		chip->onfi_version = 22;
 	else if (val & (1 << 3))
 		chip->onfi_version = 21;
 	else if (val & (1 << 2))
 		chip->onfi_version = 20;
-	else
+	else if (val & (1 << 1))
 		chip->onfi_version = 10;
+	else
+		chip->onfi_version = 0;
+
+	if (!chip->onfi_version) {
+		printk(KERN_INFO "%s: unsupported ONFI version: %d\n",
+								__func__, val);
+		return 0;
+	}
 
 	sanitize_string(p->manufacturer, sizeof(p->manufacturer));
 	sanitize_string(p->model, sizeof(p->model));
@@ -2887,7 +2891,7 @@ static int nand_flash_detect_onfi(struct
 	mtd->writesize = le32_to_cpu(p->byte_per_page);
 	mtd->erasesize = le32_to_cpu(p->pages_per_block) * mtd->writesize;
 	mtd->oobsize = le16_to_cpu(p->spare_bytes_per_page);
-	chip->chipsize = le32_to_cpu(p->blocks_per_lun) * mtd->erasesize;
+	chip->chipsize = (uint64_t)le32_to_cpu(p->blocks_per_lun) * mtd->erasesize;
 	busw = 0;
 	if (le16_to_cpu(p->features) & 1)
 		busw = NAND_BUSWIDTH_16;
@@ -3157,7 +3161,7 @@ ident_done:
 	printk(KERN_INFO "NAND device: Manufacturer ID:"
 		" 0x%02x, Chip ID: 0x%02x (%s %s)\n", *maf_id, *dev_id,
 		nand_manuf_ids[maf_idx].name,
-	chip->onfi_version ? type->name : chip->onfi_params.model);
+		chip->onfi_version ? chip->onfi_params.model : type->name);
 
 	return type;
 }
@@ -3435,6 +3439,7 @@ int nand_scan_tail(struct mtd_info *mtd)
 	mtd->resume = nand_resume;
 	mtd->block_isbad = nand_block_isbad;
 	mtd->block_markbad = nand_block_markbad;
+	mtd->writebufsize = mtd->writesize;
 
 	/* propagate ecc.layout to mtd_info */
 	mtd->ecclayout = chip->ecc.layout;
diff -druNp linux-libre-2.6.37-gnu1/drivers/mtd/nand/nand_bbt.c linux-libre-2.6.38-gnu1/drivers/mtd/nand/nand_bbt.c
--- linux-libre-2.6.37-gnu1/drivers/mtd/nand/nand_bbt.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mtd/nand/nand_bbt.c	2011-03-14 21:20:32.000000000 -0400
@@ -1092,7 +1092,8 @@ static void mark_bbt_region(struct mtd_i
 
 /**
  * verify_bbt_descr - verify the bad block description
- * @bd:			the table to verify
+ * @mtd:	MTD device structure
+ * @bd:		the table to verify
  *
  * This functions performs a few sanity checks on the bad block description
  * table.
diff -druNp linux-libre-2.6.37-gnu1/drivers/mtd/nand/nandsim.c linux-libre-2.6.38-gnu1/drivers/mtd/nand/nandsim.c
--- linux-libre-2.6.37-gnu1/drivers/mtd/nand/nandsim.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mtd/nand/nandsim.c	2011-03-14 21:20:32.000000000 -0400
@@ -210,12 +210,12 @@ MODULE_PARM_DESC(bbt,		 "0 OOB, 1 BBT wi
 #define STATE_CMD_READ0        0x00000001 /* read data from the beginning of page */
 #define STATE_CMD_READ1        0x00000002 /* read data from the second half of page */
 #define STATE_CMD_READSTART    0x00000003 /* read data second command (large page devices) */
-#define STATE_CMD_PAGEPROG     0x00000004 /* start page programm */
+#define STATE_CMD_PAGEPROG     0x00000004 /* start page program */
 #define STATE_CMD_READOOB      0x00000005 /* read OOB area */
 #define STATE_CMD_ERASE1       0x00000006 /* sector erase first command */
 #define STATE_CMD_STATUS       0x00000007 /* read status */
 #define STATE_CMD_STATUS_M     0x00000008 /* read multi-plane status (isn't implemented) */
-#define STATE_CMD_SEQIN        0x00000009 /* sequential data imput */
+#define STATE_CMD_SEQIN        0x00000009 /* sequential data input */
 #define STATE_CMD_READID       0x0000000A /* read ID */
 #define STATE_CMD_ERASE2       0x0000000B /* sector erase second command */
 #define STATE_CMD_RESET        0x0000000C /* reset */
@@ -230,7 +230,7 @@ MODULE_PARM_DESC(bbt,		 "0 OOB, 1 BBT wi
 #define STATE_ADDR_ZERO        0x00000040 /* one byte zero address was accepted */
 #define STATE_ADDR_MASK        0x00000070 /* address states mask */
 
-/* Durind data input/output the simulator is in these states */
+/* During data input/output the simulator is in these states */
 #define STATE_DATAIN           0x00000100 /* waiting for data input */
 #define STATE_DATAIN_MASK      0x00000100 /* data input states mask */
 
@@ -248,7 +248,7 @@ MODULE_PARM_DESC(bbt,		 "0 OOB, 1 BBT wi
 
 /* Simulator's actions bit masks */
 #define ACTION_CPY       0x00100000 /* copy page/OOB to the internal buffer */
-#define ACTION_PRGPAGE   0x00200000 /* programm the internal buffer to flash */
+#define ACTION_PRGPAGE   0x00200000 /* program the internal buffer to flash */
 #define ACTION_SECERASE  0x00300000 /* erase sector */
 #define ACTION_ZEROOFF   0x00400000 /* don't add any offset to address */
 #define ACTION_HALFOFF   0x00500000 /* add to address half of page */
@@ -263,18 +263,18 @@ MODULE_PARM_DESC(bbt,		 "0 OOB, 1 BBT wi
 #define OPT_PAGE512      0x00000002 /* 512-byte  page chips */
 #define OPT_PAGE2048     0x00000008 /* 2048-byte page chips */
 #define OPT_SMARTMEDIA   0x00000010 /* SmartMedia technology chips */
-#define OPT_AUTOINCR     0x00000020 /* page number auto inctimentation is possible */
+#define OPT_AUTOINCR     0x00000020 /* page number auto incrementation is possible */
 #define OPT_PAGE512_8BIT 0x00000040 /* 512-byte page chips with 8-bit bus width */
 #define OPT_PAGE4096     0x00000080 /* 4096-byte page chips */
 #define OPT_LARGEPAGE    (OPT_PAGE2048 | OPT_PAGE4096) /* 2048 & 4096-byte page chips */
 #define OPT_SMALLPAGE    (OPT_PAGE256  | OPT_PAGE512)  /* 256 and 512-byte page chips */
 
-/* Remove action bits ftom state */
+/* Remove action bits from state */
 #define NS_STATE(x) ((x) & ~ACTION_MASK)
 
 /*
  * Maximum previous states which need to be saved. Currently saving is
- * only needed for page programm operation with preceeded read command
+ * only needed for page program operation with preceded read command
  * (which is only valid for 512-byte pages).
  */
 #define NS_MAX_PREVSTATES 1
@@ -380,16 +380,16 @@ static struct nandsim_operations {
 	/* Read OOB */
 	{OPT_SMALLPAGE, {STATE_CMD_READOOB | ACTION_OOBOFF, STATE_ADDR_PAGE | ACTION_CPY,
 			STATE_DATAOUT, STATE_READY}},
-	/* Programm page starting from the beginning */
+	/* Program page starting from the beginning */
 	{OPT_ANY, {STATE_CMD_SEQIN, STATE_ADDR_PAGE, STATE_DATAIN,
 			STATE_CMD_PAGEPROG | ACTION_PRGPAGE, STATE_READY}},
-	/* Programm page starting from the beginning */
+	/* Program page starting from the beginning */
 	{OPT_SMALLPAGE, {STATE_CMD_READ0, STATE_CMD_SEQIN | ACTION_ZEROOFF, STATE_ADDR_PAGE,
 			      STATE_DATAIN, STATE_CMD_PAGEPROG | ACTION_PRGPAGE, STATE_READY}},
-	/* Programm page starting from the second half */
+	/* Program page starting from the second half */
 	{OPT_PAGE512, {STATE_CMD_READ1, STATE_CMD_SEQIN | ACTION_HALFOFF, STATE_ADDR_PAGE,
 			      STATE_DATAIN, STATE_CMD_PAGEPROG | ACTION_PRGPAGE, STATE_READY}},
-	/* Programm OOB */
+	/* Program OOB */
 	{OPT_SMALLPAGE, {STATE_CMD_READOOB, STATE_CMD_SEQIN | ACTION_OOBOFF, STATE_ADDR_PAGE,
 			      STATE_DATAIN, STATE_CMD_PAGEPROG | ACTION_PRGPAGE, STATE_READY}},
 	/* Erase sector */
@@ -470,7 +470,7 @@ static int alloc_device(struct nandsim *
 			err = -EINVAL;
 			goto err_close;
 		}
-		ns->pages_written = vmalloc(ns->geom.pgnum);
+		ns->pages_written = vzalloc(ns->geom.pgnum);
 		if (!ns->pages_written) {
 			NS_ERR("alloc_device: unable to allocate pages written array\n");
 			err = -ENOMEM;
@@ -483,7 +483,6 @@ static int alloc_device(struct nandsim *
 			goto err_free;
 		}
 		ns->cfile = cfile;
-		memset(ns->pages_written, 0, ns->geom.pgnum);
 		return 0;
 	}
 
@@ -1171,9 +1170,9 @@ static inline void switch_to_ready_state
  * of supported operations.
  *
  * Operation can be unknown because of the following.
- *   1. New command was accepted and this is the firs call to find the
+ *   1. New command was accepted and this is the first call to find the
  *      correspondent states chain. In this case ns->npstates = 0;
- *   2. There is several operations which begin with the same command(s)
+ *   2. There are several operations which begin with the same command(s)
  *      (for example program from the second half and read from the
  *      second half operations both begin with the READ1 command). In this
  *      case the ns->pstates[] array contains previous states.
@@ -1186,7 +1185,7 @@ static inline void switch_to_ready_state
  * ns->ops, ns->state, ns->nxstate are initialized, ns->npstate is
  * zeroed).
  *
- * If there are several maches, the current state is pushed to the
+ * If there are several matches, the current state is pushed to the
  * ns->pstates.
  *
  * The operation can be unknown only while commands are input to the chip.
@@ -1195,10 +1194,10 @@ static inline void switch_to_ready_state
  * operation is searched using the following pattern:
  *     ns->pstates[0], ... ns->pstates[ns->npstates], <address input>
  *
- * It is supposed that this pattern must either match one operation on
+ * It is supposed that this pattern must either match one operation or
  * none. There can't be ambiguity in that case.
  *
- * If no matches found, the functions does the following:
+ * If no matches found, the function does the following:
  *   1. if there are saved states present, try to ignore them and search
  *      again only using the last command. If nothing was found, switch
  *      to the STATE_READY state.
@@ -1668,7 +1667,7 @@ static int do_state_action(struct nandsi
 
 	case ACTION_PRGPAGE:
 		/*
-		 * Programm page - move internal buffer data to the page.
+		 * Program page - move internal buffer data to the page.
 		 */
 
 		if (ns->lines.wp) {
@@ -1933,7 +1932,7 @@ static u_char ns_nand_read_byte(struct m
 		NS_DBG("read_byte: all bytes were read\n");
 
 		/*
-		 * The OPT_AUTOINCR allows to read next conseqitive pages without
+		 * The OPT_AUTOINCR allows to read next consecutive pages without
 		 * new read operation cycle.
 		 */
 		if ((ns->options & OPT_AUTOINCR) && NS_STATE(ns->state) == STATE_DATAOUT) {
diff -druNp linux-libre-2.6.37-gnu1/drivers/mtd/nand/omap2.c linux-libre-2.6.38-gnu1/drivers/mtd/nand/omap2.c
--- linux-libre-2.6.37-gnu1/drivers/mtd/nand/omap2.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mtd/nand/omap2.c	2011-03-14 21:20:32.000000000 -0400
@@ -968,6 +968,6 @@ static void __exit omap_nand_exit(void)
 module_init(omap_nand_init);
 module_exit(omap_nand_exit);
 
-MODULE_ALIAS(DRIVER_NAME);
+MODULE_ALIAS("platform:" DRIVER_NAME);
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Glue layer for NAND flash on TI OMAP boards");
diff -druNp linux-libre-2.6.37-gnu1/drivers/mtd/nand/pasemi_nand.c linux-libre-2.6.38-gnu1/drivers/mtd/nand/pasemi_nand.c
--- linux-libre-2.6.37-gnu1/drivers/mtd/nand/pasemi_nand.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mtd/nand/pasemi_nand.c	2011-03-14 21:20:32.000000000 -0400
@@ -107,7 +107,7 @@ static int __devinit pasemi_nand_probe(s
 	if (pasemi_nand_mtd)
 		return -ENODEV;
 
-	pr_debug("pasemi_nand at %llx-%llx\n", res.start, res.end);
+	pr_debug("pasemi_nand at %pR\n", &res);
 
 	/* Allocate memory for MTD device structure and private data */
 	pasemi_nand_mtd = kzalloc(sizeof(struct mtd_info) +
diff -druNp linux-libre-2.6.37-gnu1/drivers/mtd/nand/pxa3xx_nand.c linux-libre-2.6.38-gnu1/drivers/mtd/nand/pxa3xx_nand.c
--- linux-libre-2.6.37-gnu1/drivers/mtd/nand/pxa3xx_nand.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mtd/nand/pxa3xx_nand.c	2011-03-14 21:20:32.000000000 -0400
@@ -885,6 +885,7 @@ static int pxa3xx_nand_detect_config(str
 	/* set info fields needed to __readid */
 	info->read_id_bytes = (info->page_size == 2048) ? 4 : 2;
 	info->reg_ndcr = ndcr;
+	info->cmdset = &default_cmdset;
 
 	if (__readid(info, &id))
 		return -ENODEV;
@@ -915,7 +916,6 @@ static int pxa3xx_nand_detect_config(str
 
 	info->ndtr0cs0 = nand_readl(info, NDTR0CS0);
 	info->ndtr1cs0 = nand_readl(info, NDTR1CS0);
-	info->cmdset = &default_cmdset;
 
 	return 0;
 }
diff -druNp linux-libre-2.6.37-gnu1/drivers/mtd/nand/r852.c linux-libre-2.6.38-gnu1/drivers/mtd/nand/r852.c
--- linux-libre-2.6.37-gnu1/drivers/mtd/nand/r852.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mtd/nand/r852.c	2011-03-14 21:20:32.000000000 -0400
@@ -930,7 +930,7 @@ int  r852_probe(struct pci_dev *pci_dev,
 
 	init_completion(&dev->dma_done);
 
-	dev->card_workqueue = create_freezeable_workqueue(DRV_NAME);
+	dev->card_workqueue = create_freezable_workqueue(DRV_NAME);
 
 	if (!dev->card_workqueue)
 		goto error9;
diff -druNp linux-libre-2.6.37-gnu1/drivers/mtd/nand/txx9ndfmc.c linux-libre-2.6.38-gnu1/drivers/mtd/nand/txx9ndfmc.c
--- linux-libre-2.6.37-gnu1/drivers/mtd/nand/txx9ndfmc.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mtd/nand/txx9ndfmc.c	2011-03-14 21:20:32.000000000 -0400
@@ -277,8 +277,9 @@ static int txx9ndfmc_nand_scan(struct mt
 	ret = nand_scan_ident(mtd, 1, NULL);
 	if (!ret) {
 		if (mtd->writesize >= 512) {
-			chip->ecc.size = mtd->writesize;
-			chip->ecc.bytes = 3 * (mtd->writesize / 256);
+			/* Hardware ECC 6 byte ECC per 512 Byte data */
+			chip->ecc.size = 512;
+			chip->ecc.bytes = 6;
 		}
 		ret = nand_scan_tail(mtd);
 	}
diff -druNp linux-libre-2.6.37-gnu1/drivers/mtd/onenand/generic.c linux-libre-2.6.38-gnu1/drivers/mtd/onenand/generic.c
--- linux-libre-2.6.37-gnu1/drivers/mtd/onenand/generic.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mtd/onenand/generic.c	2011-03-14 21:20:32.000000000 -0400
@@ -131,7 +131,7 @@ static struct platform_driver generic_on
 	.remove		= __devexit_p(generic_onenand_remove),
 };
 
-MODULE_ALIAS(DRIVER_NAME);
+MODULE_ALIAS("platform:" DRIVER_NAME);
 
 static int __init generic_onenand_init(void)
 {
diff -druNp linux-libre-2.6.37-gnu1/drivers/mtd/onenand/omap2.c linux-libre-2.6.38-gnu1/drivers/mtd/onenand/omap2.c
--- linux-libre-2.6.37-gnu1/drivers/mtd/onenand/omap2.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mtd/onenand/omap2.c	2011-03-14 21:20:32.000000000 -0400
@@ -35,6 +35,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/io.h>
 #include <linux/slab.h>
+#include <linux/regulator/consumer.h>
 
 #include <asm/mach/flash.h>
 #include <plat/gpmc.h>
@@ -63,8 +64,13 @@ struct omap2_onenand {
 	int dma_channel;
 	int freq;
 	int (*setup)(void __iomem *base, int freq);
+	struct regulator *regulator;
 };
 
+#ifdef CONFIG_MTD_PARTITIONS
+static const char *part_probes[] = { "cmdlinepart", NULL,  };
+#endif
+
 static void omap2_onenand_dma_cb(int lch, u16 ch_status, void *data)
 {
 	struct omap2_onenand *c = data;
@@ -108,8 +114,9 @@ static void wait_warn(char *msg, int sta
 static int omap2_onenand_wait(struct mtd_info *mtd, int state)
 {
 	struct omap2_onenand *c = container_of(mtd, struct omap2_onenand, mtd);
+	struct onenand_chip *this = mtd->priv;
 	unsigned int intr = 0;
-	unsigned int ctrl;
+	unsigned int ctrl, ctrl_mask;
 	unsigned long timeout;
 	u32 syscfg;
 
@@ -180,7 +187,8 @@ retry:
 			if (result == 0) {
 				/* Timeout after 20ms */
 				ctrl = read_reg(c, ONENAND_REG_CTRL_STATUS);
-				if (ctrl & ONENAND_CTRL_ONGO) {
+				if (ctrl & ONENAND_CTRL_ONGO &&
+				    !this->ongoing) {
 					/*
 					 * The operation seems to be still going
 					 * so give it some more time.
@@ -269,7 +277,11 @@ retry:
 		return -EIO;
 	}
 
-	if (ctrl & 0xFE9F)
+	ctrl_mask = 0xFE9F;
+	if (this->ongoing)
+		ctrl_mask &= ~0x8000;
+
+	if (ctrl & ctrl_mask)
 		wait_warn("unexpected controller status", state, ctrl, intr);
 
 	return 0;
@@ -591,6 +603,30 @@ static void omap2_onenand_shutdown(struc
 	memset((__force void *)c->onenand.base, 0, ONENAND_BUFRAM_SIZE);
 }
 
+static int omap2_onenand_enable(struct mtd_info *mtd)
+{
+	int ret;
+	struct omap2_onenand *c = container_of(mtd, struct omap2_onenand, mtd);
+
+	ret = regulator_enable(c->regulator);
+	if (ret != 0)
+		dev_err(&c->pdev->dev, "cant enable regulator\n");
+
+	return ret;
+}
+
+static int omap2_onenand_disable(struct mtd_info *mtd)
+{
+	int ret;
+	struct omap2_onenand *c = container_of(mtd, struct omap2_onenand, mtd);
+
+	ret = regulator_disable(c->regulator);
+	if (ret != 0)
+		dev_err(&c->pdev->dev, "cant disable regulator\n");
+
+	return ret;
+}
+
 static int __devinit omap2_onenand_probe(struct platform_device *pdev)
 {
 	struct omap_onenand_platform_data *pdata;
@@ -705,8 +741,18 @@ static int __devinit omap2_onenand_probe
 		}
 	}
 
+	if (pdata->regulator_can_sleep) {
+		c->regulator = regulator_get(&pdev->dev, "vonenand");
+		if (IS_ERR(c->regulator)) {
+			dev_err(&pdev->dev,  "Failed to get regulator\n");
+			goto err_release_dma;
+		}
+		c->onenand.enable = omap2_onenand_enable;
+		c->onenand.disable = omap2_onenand_disable;
+	}
+
 	if ((r = onenand_scan(&c->mtd, 1)) < 0)
-		goto err_release_dma;
+		goto err_release_regulator;
 
 	switch ((c->onenand.version_id >> 4) & 0xf) {
 	case 0:
@@ -721,16 +767,21 @@ static int __devinit omap2_onenand_probe
 	case 3:
 		c->freq = 83;
 		break;
+	case 4:
+		c->freq = 104;
+		break;
 	}
 
 #ifdef CONFIG_MTD_PARTITIONS
-	if (pdata->parts != NULL)
-		r = add_mtd_partitions(&c->mtd, pdata->parts,
-				       pdata->nr_parts);
+	r = parse_mtd_partitions(&c->mtd, part_probes, &c->parts, 0);
+	if (r > 0)
+		r = add_mtd_partitions(&c->mtd, c->parts, r);
+	else if (pdata->parts != NULL)
+		r = add_mtd_partitions(&c->mtd, pdata->parts, pdata->nr_parts);
 	else
 #endif
 		r = add_mtd_device(&c->mtd);
-	if (r < 0)
+	if (r)
 		goto err_release_onenand;
 
 	platform_set_drvdata(pdev, c);
@@ -739,6 +790,8 @@ static int __devinit omap2_onenand_probe
 
 err_release_onenand:
 	onenand_release(&c->mtd);
+err_release_regulator:
+	regulator_put(c->regulator);
 err_release_dma:
 	if (c->dma_channel != -1)
 		omap_free_dma(c->dma_channel);
@@ -754,6 +807,7 @@ err_release_mem_region:
 err_free_cs:
 	gpmc_cs_free(c->gpmc_cs);
 err_kfree:
+	kfree(c->parts);
 	kfree(c);
 
 	return r;
@@ -763,18 +817,8 @@ static int __devexit omap2_onenand_remov
 {
 	struct omap2_onenand *c = dev_get_drvdata(&pdev->dev);
 
-	BUG_ON(c == NULL);
-
-#ifdef CONFIG_MTD_PARTITIONS
-	if (c->parts)
-		del_mtd_partitions(&c->mtd);
-	else
-		del_mtd_device(&c->mtd);
-#else
-	del_mtd_device(&c->mtd);
-#endif
-
 	onenand_release(&c->mtd);
+	regulator_put(c->regulator);
 	if (c->dma_channel != -1)
 		omap_free_dma(c->dma_channel);
 	omap2_onenand_shutdown(pdev);
@@ -786,6 +830,7 @@ static int __devexit omap2_onenand_remov
 	iounmap(c->onenand.base);
 	release_mem_region(c->phys_base, ONENAND_IO_SIZE);
 	gpmc_cs_free(c->gpmc_cs);
+	kfree(c->parts);
 	kfree(c);
 
 	return 0;
@@ -815,7 +860,7 @@ static void __exit omap2_onenand_exit(vo
 module_init(omap2_onenand_init);
 module_exit(omap2_onenand_exit);
 
-MODULE_ALIAS(DRIVER_NAME);
+MODULE_ALIAS("platform:" DRIVER_NAME);
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Jarkko Lavinen <jarkko.lavinen@nokia.com>");
 MODULE_DESCRIPTION("Glue layer for OneNAND flash on OMAP2 / OMAP3");
diff -druNp linux-libre-2.6.37-gnu1/drivers/mtd/onenand/onenand_base.c linux-libre-2.6.38-gnu1/drivers/mtd/onenand/onenand_base.c
--- linux-libre-2.6.37-gnu1/drivers/mtd/onenand/onenand_base.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mtd/onenand/onenand_base.c	2011-03-14 21:20:32.000000000 -0400
@@ -400,8 +400,7 @@ static int onenand_command(struct mtd_in
 		value = onenand_bufferram_address(this, block);
 		this->write_word(value, this->base + ONENAND_REG_START_ADDRESS2);
 
-		if (ONENAND_IS_MLC(this) || ONENAND_IS_2PLANE(this) ||
-		    ONENAND_IS_4KB_PAGE(this))
+		if (ONENAND_IS_2PLANE(this) || ONENAND_IS_4KB_PAGE(this))
 			/* It is always BufferRAM0 */
 			ONENAND_SET_BUFFERRAM0(this);
 		else
@@ -430,7 +429,7 @@ static int onenand_command(struct mtd_in
 		case FLEXONENAND_CMD_RECOVER_LSB:
 		case ONENAND_CMD_READ:
 		case ONENAND_CMD_READOOB:
-			if (ONENAND_IS_MLC(this) || ONENAND_IS_4KB_PAGE(this))
+			if (ONENAND_IS_4KB_PAGE(this))
 				/* It is always BufferRAM0 */
 				dataram = ONENAND_SET_BUFFERRAM0(this);
 			else
@@ -949,6 +948,8 @@ static int onenand_get_device(struct mtd
 		if (this->state == FL_READY) {
 			this->state = new_state;
 			spin_unlock(&this->chip_lock);
+			if (new_state != FL_PM_SUSPENDED && this->enable)
+				this->enable(mtd);
 			break;
 		}
 		if (new_state == FL_PM_SUSPENDED) {
@@ -975,6 +976,8 @@ static void onenand_release_device(struc
 {
 	struct onenand_chip *this = mtd->priv;
 
+	if (this->state != FL_PM_SUSPENDED && this->disable)
+		this->disable(mtd);
 	/* Release the chip */
 	spin_lock(&this->chip_lock);
 	this->state = FL_READY;
@@ -1353,7 +1356,7 @@ static int onenand_read_oob_nolock(struc
 
 	stats = mtd->ecc_stats;
 
-	readcmd = ONENAND_IS_MLC(this) ? ONENAND_CMD_READ : ONENAND_CMD_READOOB;
+	readcmd = ONENAND_IS_4KB_PAGE(this) ? ONENAND_CMD_READ : ONENAND_CMD_READOOB;
 
 	while (read < len) {
 		cond_resched();
@@ -1429,7 +1432,7 @@ static int onenand_read(struct mtd_info
 	int ret;
 
 	onenand_get_device(mtd, FL_READING);
-	ret = ONENAND_IS_MLC(this) || ONENAND_IS_4KB_PAGE(this) ?
+	ret = ONENAND_IS_4KB_PAGE(this) ?
 		onenand_mlc_read_ops_nolock(mtd, from, &ops) :
 		onenand_read_ops_nolock(mtd, from, &ops);
 	onenand_release_device(mtd);
@@ -1464,7 +1467,7 @@ static int onenand_read_oob(struct mtd_i
 
 	onenand_get_device(mtd, FL_READING);
 	if (ops->datbuf)
-		ret = ONENAND_IS_MLC(this) || ONENAND_IS_4KB_PAGE(this) ?
+		ret = ONENAND_IS_4KB_PAGE(this) ?
 			onenand_mlc_read_ops_nolock(mtd, from, ops) :
 			onenand_read_ops_nolock(mtd, from, ops);
 	else
@@ -1485,8 +1488,7 @@ static int onenand_bbt_wait(struct mtd_i
 {
 	struct onenand_chip *this = mtd->priv;
 	unsigned long timeout;
-	unsigned int interrupt;
-	unsigned int ctrl;
+	unsigned int interrupt, ctrl, ecc, addr1, addr8;
 
 	/* The 20 msec is enough */
 	timeout = jiffies + msecs_to_jiffies(20);
@@ -1498,25 +1500,28 @@ static int onenand_bbt_wait(struct mtd_i
 	/* To get correct interrupt status in timeout case */
 	interrupt = this->read_word(this->base + ONENAND_REG_INTERRUPT);
 	ctrl = this->read_word(this->base + ONENAND_REG_CTRL_STATUS);
+	addr1 = this->read_word(this->base + ONENAND_REG_START_ADDRESS1);
+	addr8 = this->read_word(this->base + ONENAND_REG_START_ADDRESS8);
 
 	if (interrupt & ONENAND_INT_READ) {
-		int ecc = onenand_read_ecc(this);
+		ecc = onenand_read_ecc(this);
 		if (ecc & ONENAND_ECC_2BIT_ALL) {
-			printk(KERN_WARNING "%s: ecc error = 0x%04x, "
-				"controller error 0x%04x\n",
-				__func__, ecc, ctrl);
+			printk(KERN_DEBUG "%s: ecc 0x%04x ctrl 0x%04x "
+			       "intr 0x%04x addr1 %#x addr8 %#x\n",
+			       __func__, ecc, ctrl, interrupt, addr1, addr8);
 			return ONENAND_BBT_READ_ECC_ERROR;
 		}
 	} else {
-		printk(KERN_ERR "%s: read timeout! ctrl=0x%04x intr=0x%04x\n",
-			__func__, ctrl, interrupt);
+		printk(KERN_ERR "%s: read timeout! ctrl 0x%04x "
+		       "intr 0x%04x addr1 %#x addr8 %#x\n",
+		       __func__, ctrl, interrupt, addr1, addr8);
 		return ONENAND_BBT_READ_FATAL_ERROR;
 	}
 
 	/* Initial bad block case: 0x2400 or 0x0400 */
 	if (ctrl & ONENAND_CTRL_ERROR) {
-		printk(KERN_DEBUG "%s: controller error = 0x%04x\n",
-			__func__, ctrl);
+		printk(KERN_DEBUG "%s: ctrl 0x%04x intr 0x%04x addr1 %#x "
+		       "addr8 %#x\n", __func__, ctrl, interrupt, addr1, addr8);
 		return ONENAND_BBT_READ_ERROR;
 	}
 
@@ -1558,7 +1563,7 @@ int onenand_bbt_read_oob(struct mtd_info
 
 	column = from & (mtd->oobsize - 1);
 
-	readcmd = ONENAND_IS_MLC(this) ? ONENAND_CMD_READ : ONENAND_CMD_READOOB;
+	readcmd = ONENAND_IS_4KB_PAGE(this) ? ONENAND_CMD_READ : ONENAND_CMD_READOOB;
 
 	while (read < len) {
 		cond_resched();
@@ -1612,7 +1617,7 @@ static int onenand_verify_oob(struct mtd
 	u_char *oob_buf = this->oob_buf;
 	int status, i, readcmd;
 
-	readcmd = ONENAND_IS_MLC(this) ? ONENAND_CMD_READ : ONENAND_CMD_READOOB;
+	readcmd = ONENAND_IS_4KB_PAGE(this) ? ONENAND_CMD_READ : ONENAND_CMD_READOOB;
 
 	this->command(mtd, readcmd, to, mtd->oobsize);
 	onenand_update_bufferram(mtd, to, 0);
@@ -1845,7 +1850,7 @@ static int onenand_write_ops_nolock(stru
 	const u_char *buf = ops->datbuf;
 	const u_char *oob = ops->oobbuf;
 	u_char *oobbuf;
-	int ret = 0;
+	int ret = 0, cmd;
 
 	DEBUG(MTD_DEBUG_LEVEL3, "%s: to = 0x%08x, len = %i\n",
 		__func__, (unsigned int) to, (int) len);
@@ -1954,7 +1959,19 @@ static int onenand_write_ops_nolock(stru
 			ONENAND_SET_NEXT_BUFFERRAM(this);
 		}
 
-		this->command(mtd, ONENAND_CMD_PROG, to, mtd->writesize);
+		this->ongoing = 0;
+		cmd = ONENAND_CMD_PROG;
+
+		/* Exclude 1st OTP and OTP blocks for cache program feature */
+		if (ONENAND_IS_CACHE_PROGRAM(this) &&
+		    likely(onenand_block(this, to) != 0) &&
+		    ONENAND_IS_4KB_PAGE(this) &&
+		    ((written + thislen) < len)) {
+			cmd = ONENAND_CMD_2X_CACHE_PROG;
+			this->ongoing = 1;
+		}
+
+		this->command(mtd, cmd, to, mtd->writesize);
 
 		/*
 		 * 2 PLANE, MLC, and Flex-OneNAND wait here
@@ -2067,7 +2084,7 @@ static int onenand_write_oob_nolock(stru
 
 	oobbuf = this->oob_buf;
 
-	oobcmd = ONENAND_IS_MLC(this) ? ONENAND_CMD_PROG : ONENAND_CMD_PROGOOB;
+	oobcmd = ONENAND_IS_4KB_PAGE(this) ? ONENAND_CMD_PROG : ONENAND_CMD_PROGOOB;
 
 	/* Loop until all data write */
 	while (written < len) {
@@ -2086,7 +2103,7 @@ static int onenand_write_oob_nolock(stru
 			memcpy(oobbuf + column, buf, thislen);
 		this->write_bufferram(mtd, ONENAND_SPARERAM, oobbuf, 0, mtd->oobsize);
 
-		if (ONENAND_IS_MLC(this) || ONENAND_IS_4KB_PAGE(this)) {
+		if (ONENAND_IS_4KB_PAGE(this)) {
 			/* Set main area of DataRAM to 0xff*/
 			memset(this->page_buf, 0xff, mtd->writesize);
 			this->write_bufferram(mtd, ONENAND_DATARAM,
@@ -2481,7 +2498,8 @@ static int onenand_erase(struct mtd_info
 	/* Grab the lock and see if the device is available */
 	onenand_get_device(mtd, FL_ERASING);
 
-	if (region || instr->len < MB_ERASE_MIN_BLK_COUNT * block_size) {
+	if (ONENAND_IS_4KB_PAGE(this) || region ||
+	    instr->len < MB_ERASE_MIN_BLK_COUNT * block_size) {
 		/* region is set for Flex-OneNAND (no mb erase) */
 		ret = onenand_block_by_block_erase(mtd, instr,
 						   region, block_size);
@@ -3029,7 +3047,7 @@ static int do_otp_read(struct mtd_info *
 	this->command(mtd, ONENAND_CMD_OTP_ACCESS, 0, 0);
 	this->wait(mtd, FL_OTPING);
 
-	ret = ONENAND_IS_MLC(this) || ONENAND_IS_4KB_PAGE(this) ?
+	ret = ONENAND_IS_4KB_PAGE(this) ?
 		onenand_mlc_read_ops_nolock(mtd, from, &ops) :
 		onenand_read_ops_nolock(mtd, from, &ops);
 
@@ -3377,8 +3395,10 @@ static void onenand_check_features(struc
 	case ONENAND_DEVICE_DENSITY_4Gb:
 		if (ONENAND_IS_DDP(this))
 			this->options |= ONENAND_HAS_2PLANE;
-		else if (numbufs == 1)
+		else if (numbufs == 1) {
 			this->options |= ONENAND_HAS_4KB_PAGE;
+			this->options |= ONENAND_HAS_CACHE_PROGRAM;
+		}
 
 	case ONENAND_DEVICE_DENSITY_2Gb:
 		/* 2Gb DDP does not have 2 plane */
@@ -3399,7 +3419,11 @@ static void onenand_check_features(struc
 		break;
 	}
 
-	if (ONENAND_IS_MLC(this) || ONENAND_IS_4KB_PAGE(this))
+	/* The MLC has 4KiB pagesize. */
+	if (ONENAND_IS_MLC(this))
+		this->options |= ONENAND_HAS_4KB_PAGE;
+
+	if (ONENAND_IS_4KB_PAGE(this))
 		this->options &= ~ONENAND_HAS_2PLANE;
 
 	if (FLEXONENAND(this)) {
@@ -3415,6 +3439,8 @@ static void onenand_check_features(struc
 		printk(KERN_DEBUG "Chip has 2 plane\n");
 	if (this->options & ONENAND_HAS_4KB_PAGE)
 		printk(KERN_DEBUG "Chip has 4KiB pagesize\n");
+	if (this->options & ONENAND_HAS_CACHE_PROGRAM)
+		printk(KERN_DEBUG "Chip has cache program feature\n");
 }
 
 /**
@@ -3831,7 +3857,7 @@ static int onenand_probe(struct mtd_info
 	/* The data buffer size is equal to page size */
 	mtd->writesize = this->read_word(this->base + ONENAND_REG_DATA_BUFFER_SIZE);
 	/* We use the full BufferRAM */
-	if (ONENAND_IS_MLC(this) || ONENAND_IS_4KB_PAGE(this))
+	if (ONENAND_IS_4KB_PAGE(this))
 		mtd->writesize <<= 1;
 
 	mtd->oobsize = mtd->writesize >> 5;
@@ -4054,6 +4080,7 @@ int onenand_scan(struct mtd_info *mtd, i
 	mtd->block_isbad = onenand_block_isbad;
 	mtd->block_markbad = onenand_block_markbad;
 	mtd->owner = THIS_MODULE;
+	mtd->writebufsize = mtd->writesize;
 
 	/* Unlock whole block */
 	this->unlock_all(mtd);
diff -druNp linux-libre-2.6.37-gnu1/drivers/mtd/onenand/onenand_bbt.c linux-libre-2.6.38-gnu1/drivers/mtd/onenand/onenand_bbt.c
--- linux-libre-2.6.37-gnu1/drivers/mtd/onenand/onenand_bbt.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mtd/onenand/onenand_bbt.c	2011-03-14 21:20:32.000000000 -0400
@@ -91,16 +91,18 @@ static int create_bbt(struct mtd_info *m
 		for (j = 0; j < len; j++) {
 			/* No need to read pages fully,
 			 * just read required OOB bytes */
-			ret = onenand_bbt_read_oob(mtd, from + j * mtd->writesize + bd->offs, &ops);
+			ret = onenand_bbt_read_oob(mtd,
+				from + j * this->writesize + bd->offs, &ops);
 
 			/* If it is a initial bad block, just ignore it */
 			if (ret == ONENAND_BBT_READ_FATAL_ERROR)
 				return -EIO;
 
-			if (ret || check_short_pattern(&buf[j * scanlen], scanlen, mtd->writesize, bd)) {
+			if (ret || check_short_pattern(&buf[j * scanlen],
+					       scanlen, this->writesize, bd)) {
 				bbm->bbt[i >> 3] |= 0x03 << (i & 0x6);
-				printk(KERN_WARNING "Bad eraseblock %d at 0x%08x\n",
-					i >> 1, (unsigned int) from);
+				printk(KERN_INFO "OneNAND eraseblock %d is an "
+					"initial bad block\n", i >> 1);
 				mtd->ecc_stats.badblocks++;
 				break;
 			}
diff -druNp linux-libre-2.6.37-gnu1/drivers/mtd/onenand/samsung.c linux-libre-2.6.38-gnu1/drivers/mtd/onenand/samsung.c
--- linux-libre-2.6.37-gnu1/drivers/mtd/onenand/samsung.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mtd/onenand/samsung.c	2011-03-14 21:20:32.000000000 -0400
@@ -651,7 +651,7 @@ static int s5pc110_read_bufferram(struct
 	void __iomem *p;
 	void *buf = (void *) buffer;
 	dma_addr_t dma_src, dma_dst;
-	int err, page_dma = 0;
+	int err, ofs, page_dma = 0;
 	struct device *dev = &onenand->pdev->dev;
 
 	p = this->base + area;
@@ -677,10 +677,13 @@ static int s5pc110_read_bufferram(struct
 		if (!page)
 			goto normal;
 
+		/* Page offset */
+		ofs = ((size_t) buf & ~PAGE_MASK);
 		page_dma = 1;
+
 		/* DMA routine */
 		dma_src = onenand->phys_base + (p - this->base);
-		dma_dst = dma_map_page(dev, page, 0, count, DMA_FROM_DEVICE);
+		dma_dst = dma_map_page(dev, page, ofs, count, DMA_FROM_DEVICE);
 	} else {
 		/* DMA routine */
 		dma_src = onenand->phys_base + (p - this->base);
diff -druNp linux-libre-2.6.37-gnu1/drivers/mtd/sm_ftl.c linux-libre-2.6.38-gnu1/drivers/mtd/sm_ftl.c
--- linux-libre-2.6.37-gnu1/drivers/mtd/sm_ftl.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mtd/sm_ftl.c	2011-03-14 21:20:32.000000000 -0400
@@ -1258,7 +1258,7 @@ static struct mtd_blktrans_ops sm_ftl_op
 static __init int sm_module_init(void)
 {
 	int error = 0;
-	cache_flush_workqueue = create_freezeable_workqueue("smflush");
+	cache_flush_workqueue = create_freezable_workqueue("smflush");
 
 	if (IS_ERR(cache_flush_workqueue))
 		return PTR_ERR(cache_flush_workqueue);
diff -druNp linux-libre-2.6.37-gnu1/drivers/mtd/ubi/vtbl.c linux-libre-2.6.38-gnu1/drivers/mtd/ubi/vtbl.c
--- linux-libre-2.6.37-gnu1/drivers/mtd/ubi/vtbl.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/mtd/ubi/vtbl.c	2011-03-14 21:20:32.000000000 -0400
@@ -425,12 +425,11 @@ static struct ubi_vtbl_record *process_l
 
 	/* Read both LEB 0 and LEB 1 into memory */
 	ubi_rb_for_each_entry(rb, seb, &sv->root, u.rb) {
-		leb[seb->lnum] = vmalloc(ubi->vtbl_size);
+		leb[seb->lnum] = vzalloc(ubi->vtbl_size);
 		if (!leb[seb->lnum]) {
 			err = -ENOMEM;
 			goto out_free;
 		}
-		memset(leb[seb->lnum], 0, ubi->vtbl_size);
 
 		err = ubi_io_read_data(ubi, leb[seb->lnum], seb->pnum, 0,
 				       ubi->vtbl_size);
@@ -516,10 +515,9 @@ static struct ubi_vtbl_record *create_em
 	int i;
 	struct ubi_vtbl_record *vtbl;
 
-	vtbl = vmalloc(ubi->vtbl_size);
+	vtbl = vzalloc(ubi->vtbl_size);
 	if (!vtbl)
 		return ERR_PTR(-ENOMEM);
-	memset(vtbl, 0, ubi->vtbl_size);
 
 	for (i = 0; i < ubi->vtbl_slots; i++)
 		memcpy(&vtbl[i], &empty_vtbl_record, UBI_VTBL_RECORD_SIZE);
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/3c501.c linux-libre-2.6.38-gnu1/drivers/net/3c501.c
--- linux-libre-2.6.37-gnu1/drivers/net/3c501.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/3c501.c	2011-03-14 21:20:32.000000000 -0400
@@ -158,8 +158,8 @@ static int mem_start;
 struct net_device * __init el1_probe(int unit)
 {
 	struct net_device *dev = alloc_etherdev(sizeof(struct net_local));
-	static unsigned ports[] = { 0x280, 0x300, 0};
-	unsigned *port;
+	static const unsigned ports[] = { 0x280, 0x300, 0};
+	const unsigned *port;
 	int err = 0;
 
 	if (!dev)
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/3c503.c linux-libre-2.6.38-gnu1/drivers/net/3c503.c
--- linux-libre-2.6.37-gnu1/drivers/net/3c503.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/3c503.c	2011-03-14 21:20:32.000000000 -0400
@@ -392,8 +392,8 @@ el2_open(struct net_device *dev)
     int retval;
 
     if (dev->irq < 2) {
-	int irqlist[] = {5, 9, 3, 4, 0};
-	int *irqp = irqlist;
+	static const int irqlist[] = {5, 9, 3, 4, 0};
+	const int *irqp = irqlist;
 
 	outb(EGACFR_NORM, E33G_GACFR);	/* Enable RAM and interrupts. */
 	do {
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/3c507.c linux-libre-2.6.38-gnu1/drivers/net/3c507.c
--- linux-libre-2.6.37-gnu1/drivers/net/3c507.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/3c507.c	2011-03-14 21:20:32.000000000 -0400
@@ -201,7 +201,7 @@ struct net_local {
 #define RX_BUF_SIZE 	(1518+14+18)	/* packet+header+RBD */
 #define RX_BUF_END		(dev->mem_end - dev->mem_start)
 
-#define TX_TIMEOUT 5
+#define TX_TIMEOUT (HZ/20)
 
 /*
   That's it: only 86 bytes to set up the beast, including every extra
@@ -311,8 +311,8 @@ static int mem_start;
 struct net_device * __init el16_probe(int unit)
 {
 	struct net_device *dev = alloc_etherdev(sizeof(struct net_local));
-	static unsigned ports[] = { 0x300, 0x320, 0x340, 0x280, 0};
-	unsigned *port;
+	static const unsigned ports[] = { 0x300, 0x320, 0x340, 0x280, 0};
+	const unsigned *port;
 	int err = -ENODEV;
 
 	if (!dev)
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/3c515.c linux-libre-2.6.38-gnu1/drivers/net/3c515.c
--- linux-libre-2.6.37-gnu1/drivers/net/3c515.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/3c515.c	2011-03-14 21:20:32.000000000 -0400
@@ -98,7 +98,7 @@ static int rx_nocopy, rx_copy, queued_pa
 #define WAIT_TX_AVAIL 200
 
 /* Operational parameter that usually are not changed. */
-#define TX_TIMEOUT  40		/* Time in jiffies before concluding Tx hung */
+#define TX_TIMEOUT  ((4*HZ)/10)	/* Time in jiffies before concluding Tx hung */
 
 /* The size here is somewhat misleading: the Corkscrew also uses the ISA
    aliased registers at <base>+0x400.
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/3c527.c linux-libre-2.6.38-gnu1/drivers/net/3c527.c
--- linux-libre-2.6.37-gnu1/drivers/net/3c527.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/3c527.c	2011-03-14 21:20:32.000000000 -0400
@@ -317,13 +317,13 @@ static int __init mc32_probe1(struct net
 	u8 POS;
 	u32 base;
 	struct mc32_local *lp = netdev_priv(dev);
-	static u16 mca_io_bases[]={
+	static const u16 mca_io_bases[] = {
 		0x7280,0x7290,
 		0x7680,0x7690,
 		0x7A80,0x7A90,
 		0x7E80,0x7E90
 	};
-	static u32 mca_mem_bases[]={
+	static const u32 mca_mem_bases[] = {
 		0x00C0000,
 		0x00C4000,
 		0x00C8000,
@@ -333,7 +333,7 @@ static int __init mc32_probe1(struct net
 		0x00D8000,
 		0x00DC000
 	};
-	static char *failures[]={
+	static const char * const failures[] = {
 		"Processor instruction",
 		"Processor data bus",
 		"Processor data bus",
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/8139too.c linux-libre-2.6.38-gnu1/drivers/net/8139too.c
--- linux-libre-2.6.37-gnu1/drivers/net/8139too.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/8139too.c	2011-03-14 21:20:32.000000000 -0400
@@ -1092,10 +1092,11 @@ err_out:
 static void __devexit rtl8139_remove_one (struct pci_dev *pdev)
 {
 	struct net_device *dev = pci_get_drvdata (pdev);
+	struct rtl8139_private *tp = netdev_priv(dev);
 
 	assert (dev != NULL);
 
-	flush_scheduled_work();
+	cancel_delayed_work_sync(&tp->thread);
 
 	unregister_netdev (dev);
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/82596.c linux-libre-2.6.38-gnu1/drivers/net/82596.c
--- linux-libre-2.6.37-gnu1/drivers/net/82596.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/82596.c	2011-03-14 21:20:32.000000000 -0400
@@ -191,7 +191,7 @@ enum commands {
 #define	 RX_SUSPEND	0x0030
 #define	 RX_ABORT	0x0040
 
-#define TX_TIMEOUT	5
+#define TX_TIMEOUT	(HZ/20)
 
 
 struct i596_reg {
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/ariadne.c linux-libre-2.6.38-gnu1/drivers/net/ariadne.c
--- linux-libre-2.6.37-gnu1/drivers/net/ariadne.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/ariadne.c	2011-03-14 21:20:32.000000000 -0400
@@ -425,11 +425,6 @@ static irqreturn_t ariadne_interrupt(int
     int csr0, boguscnt;
     int handled = 0;
 
-    if (dev == NULL) {
-	printk(KERN_WARNING "ariadne_interrupt(): irq for unknown device.\n");
-	return IRQ_NONE;
-    }
-
     lance->RAP = CSR0;			/* PCnet-ISA Controller Status */
 
     if (!(lance->RDP & INTR))		/* Check if any interrupt has been */
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/arm/am79c961a.c linux-libre-2.6.38-gnu1/drivers/net/arm/am79c961a.c
--- linux-libre-2.6.37-gnu1/drivers/net/arm/am79c961a.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/arm/am79c961a.c	2011-03-14 21:20:32.000000000 -0400
@@ -340,14 +340,6 @@ am79c961_close(struct net_device *dev)
 	return 0;
 }
 
-/*
- * Get the current statistics.
- */
-static struct net_device_stats *am79c961_getstats (struct net_device *dev)
-{
-	return &dev->stats;
-}
-
 static void am79c961_mc_hash(char *addr, unsigned short *hash)
 {
 	if (addr[0] & 0x01) {
@@ -665,7 +657,6 @@ static const struct net_device_ops am79c
 	.ndo_open		= am79c961_open,
 	.ndo_stop		= am79c961_close,
 	.ndo_start_xmit		= am79c961_sendpacket,
-	.ndo_get_stats		= am79c961_getstats,
 	.ndo_set_multicast_list	= am79c961_setmulticastlist,
 	.ndo_tx_timeout		= am79c961_timeout,
 	.ndo_validate_addr	= eth_validate_addr,
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/arm/ixp4xx_eth.c linux-libre-2.6.38-gnu1/drivers/net/arm/ixp4xx_eth.c
--- linux-libre-2.6.37-gnu1/drivers/net/arm/ixp4xx_eth.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/arm/ixp4xx_eth.c	2011-03-14 21:20:32.000000000 -0400
@@ -1229,8 +1229,10 @@ static int __devinit eth_init_one(struct
 	snprintf(phy_id, MII_BUS_ID_SIZE + 3, PHY_ID_FMT, "0", plat->phy);
 	port->phydev = phy_connect(dev, phy_id, &ixp4xx_adjust_link, 0,
 				   PHY_INTERFACE_MODE_MII);
-	if ((err = IS_ERR(port->phydev)))
+	if (IS_ERR(port->phydev)) {
+		err = PTR_ERR(port->phydev);
 		goto err_free_mem;
+	}
 
 	port->phydev->irq = PHY_POLL;
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/arm/ks8695net.c linux-libre-2.6.38-gnu1/drivers/net/arm/ks8695net.c
--- linux-libre-2.6.37-gnu1/drivers/net/arm/ks8695net.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/arm/ks8695net.c	2011-03-14 21:20:32.000000000 -0400
@@ -854,12 +854,12 @@ ks8695_set_msglevel(struct net_device *n
 }
 
 /**
- *	ks8695_get_settings - Get device-specific settings.
+ *	ks8695_wan_get_settings - Get device-specific settings.
  *	@ndev: The network device to read settings from
  *	@cmd: The ethtool structure to read into
  */
 static int
-ks8695_get_settings(struct net_device *ndev, struct ethtool_cmd *cmd)
+ks8695_wan_get_settings(struct net_device *ndev, struct ethtool_cmd *cmd)
 {
 	struct ks8695_priv *ksp = netdev_priv(ndev);
 	u32 ctrl;
@@ -870,69 +870,50 @@ ks8695_get_settings(struct net_device *n
 			  SUPPORTED_TP | SUPPORTED_MII);
 	cmd->transceiver = XCVR_INTERNAL;
 
-	/* Port specific extras */
-	switch (ksp->dtype) {
-	case KS8695_DTYPE_HPNA:
-		cmd->phy_address = 0;
-		/* not supported for HPNA */
-		cmd->autoneg = AUTONEG_DISABLE;
-
-		/* BUG: Erm, dtype hpna implies no phy regs */
-		/*
-		ctrl = readl(KS8695_MISC_VA + KS8695_HMC);
-		cmd->speed = (ctrl & HMC_HSS) ? SPEED_100 : SPEED_10;
-		cmd->duplex = (ctrl & HMC_HDS) ? DUPLEX_FULL : DUPLEX_HALF;
-		*/
-		return -EOPNOTSUPP;
-	case KS8695_DTYPE_WAN:
-		cmd->advertising = ADVERTISED_TP | ADVERTISED_MII;
-		cmd->port = PORT_MII;
-		cmd->supported |= (SUPPORTED_Autoneg | SUPPORTED_Pause);
-		cmd->phy_address = 0;
+	cmd->advertising = ADVERTISED_TP | ADVERTISED_MII;
+	cmd->port = PORT_MII;
+	cmd->supported |= (SUPPORTED_Autoneg | SUPPORTED_Pause);
+	cmd->phy_address = 0;
 
-		ctrl = readl(ksp->phyiface_regs + KS8695_WMC);
-		if ((ctrl & WMC_WAND) == 0) {
-			/* auto-negotiation is enabled */
-			cmd->advertising |= ADVERTISED_Autoneg;
-			if (ctrl & WMC_WANA100F)
-				cmd->advertising |= ADVERTISED_100baseT_Full;
-			if (ctrl & WMC_WANA100H)
-				cmd->advertising |= ADVERTISED_100baseT_Half;
-			if (ctrl & WMC_WANA10F)
-				cmd->advertising |= ADVERTISED_10baseT_Full;
-			if (ctrl & WMC_WANA10H)
-				cmd->advertising |= ADVERTISED_10baseT_Half;
-			if (ctrl & WMC_WANAP)
-				cmd->advertising |= ADVERTISED_Pause;
-			cmd->autoneg = AUTONEG_ENABLE;
+	ctrl = readl(ksp->phyiface_regs + KS8695_WMC);
+	if ((ctrl & WMC_WAND) == 0) {
+		/* auto-negotiation is enabled */
+		cmd->advertising |= ADVERTISED_Autoneg;
+		if (ctrl & WMC_WANA100F)
+			cmd->advertising |= ADVERTISED_100baseT_Full;
+		if (ctrl & WMC_WANA100H)
+			cmd->advertising |= ADVERTISED_100baseT_Half;
+		if (ctrl & WMC_WANA10F)
+			cmd->advertising |= ADVERTISED_10baseT_Full;
+		if (ctrl & WMC_WANA10H)
+			cmd->advertising |= ADVERTISED_10baseT_Half;
+		if (ctrl & WMC_WANAP)
+			cmd->advertising |= ADVERTISED_Pause;
+		cmd->autoneg = AUTONEG_ENABLE;
 
-			cmd->speed = (ctrl & WMC_WSS) ? SPEED_100 : SPEED_10;
-			cmd->duplex = (ctrl & WMC_WDS) ?
-				DUPLEX_FULL : DUPLEX_HALF;
-		} else {
-			/* auto-negotiation is disabled */
-			cmd->autoneg = AUTONEG_DISABLE;
+		cmd->speed = (ctrl & WMC_WSS) ? SPEED_100 : SPEED_10;
+		cmd->duplex = (ctrl & WMC_WDS) ?
+			DUPLEX_FULL : DUPLEX_HALF;
+	} else {
+		/* auto-negotiation is disabled */
+		cmd->autoneg = AUTONEG_DISABLE;
 
-			cmd->speed = (ctrl & WMC_WANF100) ?
-				SPEED_100 : SPEED_10;
-			cmd->duplex = (ctrl & WMC_WANFF) ?
-				DUPLEX_FULL : DUPLEX_HALF;
-		}
-		break;
-	case KS8695_DTYPE_LAN:
-		return -EOPNOTSUPP;
+		cmd->speed = (ctrl & WMC_WANF100) ?
+			SPEED_100 : SPEED_10;
+		cmd->duplex = (ctrl & WMC_WANFF) ?
+			DUPLEX_FULL : DUPLEX_HALF;
 	}
 
 	return 0;
 }
 
 /**
- *	ks8695_set_settings - Set device-specific settings.
+ *	ks8695_wan_set_settings - Set device-specific settings.
  *	@ndev: The network device to configure
  *	@cmd: The settings to configure
  */
 static int
-ks8695_set_settings(struct net_device *ndev, struct ethtool_cmd *cmd)
+ks8695_wan_set_settings(struct net_device *ndev, struct ethtool_cmd *cmd)
 {
 	struct ks8695_priv *ksp = netdev_priv(ndev);
 	u32 ctrl;
@@ -956,171 +937,85 @@ ks8695_set_settings(struct net_device *n
 				ADVERTISED_100baseT_Full)) == 0)
 			return -EINVAL;
 
-		switch (ksp->dtype) {
-		case KS8695_DTYPE_HPNA:
-			/* HPNA does not support auto-negotiation. */
-			return -EINVAL;
-		case KS8695_DTYPE_WAN:
-			ctrl = readl(ksp->phyiface_regs + KS8695_WMC);
-
-			ctrl &= ~(WMC_WAND | WMC_WANA100F | WMC_WANA100H |
-				  WMC_WANA10F | WMC_WANA10H);
-			if (cmd->advertising & ADVERTISED_100baseT_Full)
-				ctrl |= WMC_WANA100F;
-			if (cmd->advertising & ADVERTISED_100baseT_Half)
-				ctrl |= WMC_WANA100H;
-			if (cmd->advertising & ADVERTISED_10baseT_Full)
-				ctrl |= WMC_WANA10F;
-			if (cmd->advertising & ADVERTISED_10baseT_Half)
-				ctrl |= WMC_WANA10H;
+		ctrl = readl(ksp->phyiface_regs + KS8695_WMC);
 
-			/* force a re-negotiation */
-			ctrl |= WMC_WANR;
-			writel(ctrl, ksp->phyiface_regs + KS8695_WMC);
-			break;
-		case KS8695_DTYPE_LAN:
-			return -EOPNOTSUPP;
-		}
+		ctrl &= ~(WMC_WAND | WMC_WANA100F | WMC_WANA100H |
+			  WMC_WANA10F | WMC_WANA10H);
+		if (cmd->advertising & ADVERTISED_100baseT_Full)
+			ctrl |= WMC_WANA100F;
+		if (cmd->advertising & ADVERTISED_100baseT_Half)
+			ctrl |= WMC_WANA100H;
+		if (cmd->advertising & ADVERTISED_10baseT_Full)
+			ctrl |= WMC_WANA10F;
+		if (cmd->advertising & ADVERTISED_10baseT_Half)
+			ctrl |= WMC_WANA10H;
 
+		/* force a re-negotiation */
+		ctrl |= WMC_WANR;
+		writel(ctrl, ksp->phyiface_regs + KS8695_WMC);
 	} else {
-		switch (ksp->dtype) {
-		case KS8695_DTYPE_HPNA:
-			/* BUG: dtype_hpna implies no phy registers */
-			/*
-			ctrl = __raw_readl(KS8695_MISC_VA + KS8695_HMC);
-
-			ctrl &= ~(HMC_HSS | HMC_HDS);
-			if (cmd->speed == SPEED_100)
-				ctrl |= HMC_HSS;
-			if (cmd->duplex == DUPLEX_FULL)
-				ctrl |= HMC_HDS;
-
-			__raw_writel(ctrl, KS8695_MISC_VA + KS8695_HMC);
-			*/
-			return -EOPNOTSUPP;
-		case KS8695_DTYPE_WAN:
-			ctrl = readl(ksp->phyiface_regs + KS8695_WMC);
+		ctrl = readl(ksp->phyiface_regs + KS8695_WMC);
 
-			/* disable auto-negotiation */
-			ctrl |= WMC_WAND;
-			ctrl &= ~(WMC_WANF100 | WMC_WANFF);
+		/* disable auto-negotiation */
+		ctrl |= WMC_WAND;
+		ctrl &= ~(WMC_WANF100 | WMC_WANFF);
 
-			if (cmd->speed == SPEED_100)
-				ctrl |= WMC_WANF100;
-			if (cmd->duplex == DUPLEX_FULL)
-				ctrl |= WMC_WANFF;
+		if (cmd->speed == SPEED_100)
+			ctrl |= WMC_WANF100;
+		if (cmd->duplex == DUPLEX_FULL)
+			ctrl |= WMC_WANFF;
 
-			writel(ctrl, ksp->phyiface_regs + KS8695_WMC);
-			break;
-		case KS8695_DTYPE_LAN:
-			return -EOPNOTSUPP;
-		}
+		writel(ctrl, ksp->phyiface_regs + KS8695_WMC);
 	}
 
 	return 0;
 }
 
 /**
- *	ks8695_nwayreset - Restart the autonegotiation on the port.
+ *	ks8695_wan_nwayreset - Restart the autonegotiation on the port.
  *	@ndev: The network device to restart autoneotiation on
  */
 static int
-ks8695_nwayreset(struct net_device *ndev)
+ks8695_wan_nwayreset(struct net_device *ndev)
 {
 	struct ks8695_priv *ksp = netdev_priv(ndev);
 	u32 ctrl;
 
-	switch (ksp->dtype) {
-	case KS8695_DTYPE_HPNA:
-		/* No phy means no autonegotiation on hpna */
-		return -EINVAL;
-	case KS8695_DTYPE_WAN:
-		ctrl = readl(ksp->phyiface_regs + KS8695_WMC);
-
-		if ((ctrl & WMC_WAND) == 0)
-			writel(ctrl | WMC_WANR,
-			       ksp->phyiface_regs + KS8695_WMC);
-		else
-			/* auto-negotiation not enabled */
-			return -EINVAL;
-		break;
-	case KS8695_DTYPE_LAN:
-		return -EOPNOTSUPP;
-	}
-
-	return 0;
-}
+	ctrl = readl(ksp->phyiface_regs + KS8695_WMC);
 
-/**
- *	ks8695_get_link - Retrieve link status of network interface
- *	@ndev: The network interface to retrive the link status of.
- */
-static u32
-ks8695_get_link(struct net_device *ndev)
-{
-	struct ks8695_priv *ksp = netdev_priv(ndev);
-	u32 ctrl;
+	if ((ctrl & WMC_WAND) == 0)
+		writel(ctrl | WMC_WANR,
+		       ksp->phyiface_regs + KS8695_WMC);
+	else
+		/* auto-negotiation not enabled */
+		return -EINVAL;
 
-	switch (ksp->dtype) {
-	case KS8695_DTYPE_HPNA:
-		/* HPNA always has link */
-		return 1;
-	case KS8695_DTYPE_WAN:
-		/* WAN we can read the PHY for */
-		ctrl = readl(ksp->phyiface_regs + KS8695_WMC);
-		return ctrl & WMC_WLS;
-	case KS8695_DTYPE_LAN:
-		return -EOPNOTSUPP;
-	}
 	return 0;
 }
 
 /**
- *	ks8695_get_pause - Retrieve network pause/flow-control advertising
+ *	ks8695_wan_get_pause - Retrieve network pause/flow-control advertising
  *	@ndev: The device to retrieve settings from
  *	@param: The structure to fill out with the information
  */
 static void
-ks8695_get_pause(struct net_device *ndev, struct ethtool_pauseparam *param)
+ks8695_wan_get_pause(struct net_device *ndev, struct ethtool_pauseparam *param)
 {
 	struct ks8695_priv *ksp = netdev_priv(ndev);
 	u32 ctrl;
 
-	switch (ksp->dtype) {
-	case KS8695_DTYPE_HPNA:
-		/* No phy link on hpna to configure */
-		return;
-	case KS8695_DTYPE_WAN:
-		ctrl = readl(ksp->phyiface_regs + KS8695_WMC);
-
-		/* advertise Pause */
-		param->autoneg = (ctrl & WMC_WANAP);
+	ctrl = readl(ksp->phyiface_regs + KS8695_WMC);
 
-		/* current Rx Flow-control */
-		ctrl = ks8695_readreg(ksp, KS8695_DRXC);
-		param->rx_pause = (ctrl & DRXC_RFCE);
+	/* advertise Pause */
+	param->autoneg = (ctrl & WMC_WANAP);
 
-		/* current Tx Flow-control */
-		ctrl = ks8695_readreg(ksp, KS8695_DTXC);
-		param->tx_pause = (ctrl & DTXC_TFCE);
-		break;
-	case KS8695_DTYPE_LAN:
-		/* The LAN's "phy" is a direct-attached switch */
-		return;
-	}
-}
+	/* current Rx Flow-control */
+	ctrl = ks8695_readreg(ksp, KS8695_DRXC);
+	param->rx_pause = (ctrl & DRXC_RFCE);
 
-/**
- *	ks8695_set_pause - Configure pause/flow-control
- *	@ndev: The device to configure
- *	@param: The pause parameters to set
- *
- *	TODO: Implement this
- */
-static int
-ks8695_set_pause(struct net_device *ndev, struct ethtool_pauseparam *param)
-{
-	return -EOPNOTSUPP;
+	/* current Tx Flow-control */
+	ctrl = ks8695_readreg(ksp, KS8695_DTXC);
+	param->tx_pause = (ctrl & DTXC_TFCE);
 }
 
 /**
@@ -1140,12 +1035,17 @@ ks8695_get_drvinfo(struct net_device *nd
 static const struct ethtool_ops ks8695_ethtool_ops = {
 	.get_msglevel	= ks8695_get_msglevel,
 	.set_msglevel	= ks8695_set_msglevel,
-	.get_settings	= ks8695_get_settings,
-	.set_settings	= ks8695_set_settings,
-	.nway_reset	= ks8695_nwayreset,
-	.get_link	= ks8695_get_link,
-	.get_pauseparam = ks8695_get_pause,
-	.set_pauseparam = ks8695_set_pause,
+	.get_drvinfo	= ks8695_get_drvinfo,
+};
+
+static const struct ethtool_ops ks8695_wan_ethtool_ops = {
+	.get_msglevel	= ks8695_get_msglevel,
+	.set_msglevel	= ks8695_set_msglevel,
+	.get_settings	= ks8695_wan_get_settings,
+	.set_settings	= ks8695_wan_set_settings,
+	.nway_reset	= ks8695_wan_nwayreset,
+	.get_link	= ethtool_op_get_link,
+	.get_pauseparam = ks8695_wan_get_pause,
 	.get_drvinfo	= ks8695_get_drvinfo,
 };
 
@@ -1541,7 +1441,6 @@ ks8695_probe(struct platform_device *pde
 
 	/* driver system setup */
 	ndev->netdev_ops = &ks8695_netdev_ops;
-	SET_ETHTOOL_OPS(ndev, &ks8695_ethtool_ops);
 	ndev->watchdog_timeo	 = msecs_to_jiffies(watchdog);
 
 	netif_napi_add(ndev, &ksp->napi, ks8695_poll, NAPI_WEIGHT);
@@ -1608,12 +1507,15 @@ ks8695_probe(struct platform_device *pde
 	if (ksp->phyiface_regs && ksp->link_irq == -1) {
 		ks8695_init_switch(ksp);
 		ksp->dtype = KS8695_DTYPE_LAN;
+		SET_ETHTOOL_OPS(ndev, &ks8695_ethtool_ops);
 	} else if (ksp->phyiface_regs && ksp->link_irq != -1) {
 		ks8695_init_wan_phy(ksp);
 		ksp->dtype = KS8695_DTYPE_WAN;
+		SET_ETHTOOL_OPS(ndev, &ks8695_wan_ethtool_ops);
 	} else {
 		/* No initialisation since HPNA does not have a PHY */
 		ksp->dtype = KS8695_DTYPE_HPNA;
+		SET_ETHTOOL_OPS(ndev, &ks8695_ethtool_ops);
 	}
 
 	/* And bring up the net_device with the net core */
@@ -1742,7 +1644,7 @@ ks8695_cleanup(void)
 module_init(ks8695_init);
 module_exit(ks8695_cleanup);
 
-MODULE_AUTHOR("Simtec Electronics")
+MODULE_AUTHOR("Simtec Electronics");
 MODULE_DESCRIPTION("Micrel KS8695 (Centaur) Ethernet driver");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("platform:" MODULENAME);
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/arm/w90p910_ether.c linux-libre-2.6.38-gnu1/drivers/net/arm/w90p910_ether.c
--- linux-libre-2.6.37-gnu1/drivers/net/arm/w90p910_ether.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/arm/w90p910_ether.c	2011-03-14 21:20:32.000000000 -0400
@@ -117,7 +117,7 @@
 #define TX_DESC_SIZE		10
 #define MAX_RBUFF_SZ		0x600
 #define MAX_TBUFF_SZ		0x600
-#define TX_TIMEOUT		50
+#define TX_TIMEOUT		(HZ/2)
 #define DELAY			1000
 #define CAM0			0x0
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/at1700.c linux-libre-2.6.38-gnu1/drivers/net/at1700.c
--- linux-libre-2.6.37-gnu1/drivers/net/at1700.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/at1700.c	2011-03-14 21:20:32.000000000 -0400
@@ -150,7 +150,7 @@ struct net_local {
 #define PORT_OFFSET(o) (o)
 
 
-#define TX_TIMEOUT		10
+#define TX_TIMEOUT		(HZ/10)
 
 
 /* Index to functions, as function prototypes. */
@@ -270,9 +270,9 @@ static const struct net_device_ops at170
 
 static int __init at1700_probe1(struct net_device *dev, int ioaddr)
 {
-	char fmv_irqmap[4] = {3, 7, 10, 15};
-	char fmv_irqmap_pnp[8] = {3, 4, 5, 7, 9, 10, 11, 15};
-	char at1700_irqmap[8] = {3, 4, 5, 9, 10, 11, 14, 15};
+	static const char fmv_irqmap[4] = {3, 7, 10, 15};
+	static const char fmv_irqmap_pnp[8] = {3, 4, 5, 7, 9, 10, 11, 15};
+	static const char at1700_irqmap[8] = {3, 4, 5, 9, 10, 11, 14, 15};
 	unsigned int i, irq, is_fmv18x = 0, is_at1700 = 0;
 	int slot, ret = -ENODEV;
 	struct net_local *lp = netdev_priv(dev);
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/atarilance.c linux-libre-2.6.38-gnu1/drivers/net/atarilance.c
--- linux-libre-2.6.37-gnu1/drivers/net/atarilance.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/atarilance.c	2011-03-14 21:20:32.000000000 -0400
@@ -116,7 +116,7 @@ MODULE_LICENSE("GPL");
 #define RX_RING_LEN_BITS		(RX_LOG_RING_SIZE << 5)
 #define	RX_RING_MOD_MASK		(RX_RING_SIZE - 1)
 
-#define TX_TIMEOUT	20
+#define TX_TIMEOUT	(HZ/5)
 
 /* The LANCE Rx and Tx ring descriptors. */
 struct lance_rx_head {
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/atl1c/atl1c_main.c linux-libre-2.6.38-gnu1/drivers/net/atl1c/atl1c_main.c
--- linux-libre-2.6.37-gnu1/drivers/net/atl1c/atl1c_main.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/atl1c/atl1c_main.c	2011-03-14 21:20:32.000000000 -0400
@@ -48,6 +48,7 @@ static DEFINE_PCI_DEVICE_TABLE(atl1c_pci
 	{PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, PCI_DEVICE_ID_ATHEROS_L2C_B)},
 	{PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, PCI_DEVICE_ID_ATHEROS_L2C_B2)},
 	{PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, PCI_DEVICE_ID_ATHEROS_L1D)},
+	{PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, PCI_DEVICE_ID_ATHEROS_L1D_2_0)},
 	/* required last entry */
 	{ 0 }
 };
@@ -2079,7 +2080,7 @@ static int atl1c_tso_csum(struct atl1c_a
 check_sum:
 	if (likely(skb->ip_summed == CHECKSUM_PARTIAL)) {
 		u8 css, cso;
-		cso = skb_transport_offset(skb);
+		cso = skb_checksum_start_offset(skb);
 
 		if (unlikely(cso & 0x1)) {
 			if (netif_msg_tx_err(adapter))
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/atl1e/atl1e_main.c linux-libre-2.6.38-gnu1/drivers/net/atl1e/atl1e_main.c
--- linux-libre-2.6.37-gnu1/drivers/net/atl1e/atl1e_main.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/atl1e/atl1e_main.c	2011-03-14 21:20:32.000000000 -0400
@@ -1649,7 +1649,7 @@ check_sum:
 	if (likely(skb->ip_summed == CHECKSUM_PARTIAL)) {
 		u8 css, cso;
 
-		cso = skb_transport_offset(skb);
+		cso = skb_checksum_start_offset(skb);
 		if (unlikely(cso & 0x1)) {
 			netdev_err(adapter->netdev,
 				   "payload offset should not ant event number\n");
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/atlx/atl1.c linux-libre-2.6.38-gnu1/drivers/net/atlx/atl1.c
--- linux-libre-2.6.37-gnu1/drivers/net/atlx/atl1.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/atlx/atl1.c	2011-03-14 21:20:32.000000000 -0400
@@ -2174,7 +2174,7 @@ static int atl1_tx_csum(struct atl1_adap
 	u8 css, cso;
 
 	if (likely(skb->ip_summed == CHECKSUM_PARTIAL)) {
-		css = (u8) (skb->csum_start - skb_headroom(skb));
+		css = skb_checksum_start_offset(skb);
 		cso = css + (u8) skb->csum_offset;
 		if (unlikely(css & 0x1)) {
 			/* L1 hardware requires an even number here */
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/atlx/atl2.c linux-libre-2.6.38-gnu1/drivers/net/atlx/atl2.c
--- linux-libre-2.6.37-gnu1/drivers/net/atlx/atl2.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/atlx/atl2.c	2011-03-14 21:20:32.000000000 -0400
@@ -1504,8 +1504,8 @@ static void __devexit atl2_remove(struct
 
 	del_timer_sync(&adapter->watchdog_timer);
 	del_timer_sync(&adapter->phy_config_timer);
-
-	flush_scheduled_work();
+	cancel_work_sync(&adapter->reset_task);
+	cancel_work_sync(&adapter->link_chg_task);
 
 	unregister_netdev(netdev);
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/au1000_eth.c linux-libre-2.6.38-gnu1/drivers/net/au1000_eth.c
--- linux-libre-2.6.37-gnu1/drivers/net/au1000_eth.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/au1000_eth.c	2011-03-14 21:20:32.000000000 -0400
@@ -106,8 +106,6 @@ MODULE_VERSION(DRV_VERSION);
  * complete immediately.
  */
 
-struct au1000_private *au_macs[NUM_ETH_INTERFACES];
-
 /*
  * board-specific configurations
  *
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/ax88796.c linux-libre-2.6.38-gnu1/drivers/net/ax88796.c
--- linux-libre-2.6.37-gnu1/drivers/net/ax88796.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/ax88796.c	2011-03-14 21:20:32.000000000 -0400
@@ -325,7 +325,7 @@ static void ax_block_output(struct net_d
 static void
 ax_mii_ei_outbits(struct net_device *dev, unsigned int bits, int len)
 {
-	struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev);
+	struct ei_device *ei_local = netdev_priv(dev);
 	void __iomem *memr_addr = (void __iomem *)dev->base_addr + AX_MEMR;
 	unsigned int memr;
 
@@ -364,7 +364,7 @@ ax_mii_ei_outbits(struct net_device *dev
 static unsigned int
 ax_phy_ei_inbits(struct net_device *dev, int no)
 {
-	struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev);
+	struct ei_device *ei_local = netdev_priv(dev);
 	void __iomem *memr_addr = (void __iomem *)dev->base_addr + AX_MEMR;
 	unsigned int memr;
 	unsigned int result = 0;
@@ -412,7 +412,7 @@ ax_phy_issueaddr(struct net_device *dev,
 static int
 ax_phy_read(struct net_device *dev, int phy_addr, int reg)
 {
-	struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev);
+	struct ei_device *ei_local = netdev_priv(dev);
 	unsigned long flags;
  	unsigned int result;
 
@@ -435,7 +435,7 @@ ax_phy_read(struct net_device *dev, int
 static void
 ax_phy_write(struct net_device *dev, int phy_addr, int reg, int value)
 {
-	struct ei_device *ei = (struct ei_device *) netdev_priv(dev);
+	struct ei_device *ei = netdev_priv(dev);
 	struct ax_device  *ax = to_ax_dev(dev);
 	unsigned long flags;
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/bcm63xx_enet.c linux-libre-2.6.38-gnu1/drivers/net/bcm63xx_enet.c
--- linux-libre-2.6.37-gnu1/drivers/net/bcm63xx_enet.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/bcm63xx_enet.c	2011-03-14 21:20:32.000000000 -0400
@@ -1097,7 +1097,7 @@ static int bcm_enet_stop(struct net_devi
 	enet_dma_writel(priv, 0, ENETDMA_IRMASK_REG(priv->tx_chan));
 
 	/* make sure no mib update is scheduled */
-	flush_scheduled_work();
+	cancel_work_sync(&priv->mib_update_task);
 
 	/* disable dma & mac */
 	bcm_enet_disable_dma(priv, priv->tx_chan);
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/benet/be_cmds.c linux-libre-2.6.38-gnu1/drivers/net/benet/be_cmds.c
--- linux-libre-2.6.37-gnu1/drivers/net/benet/be_cmds.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/benet/be_cmds.c	2011-03-14 21:20:32.000000000 -0400
@@ -323,7 +323,12 @@ static int be_mbox_notify_wait(struct be
 
 static int be_POST_stage_get(struct be_adapter *adapter, u16 *stage)
 {
-	u32 sem = ioread32(adapter->csr + MPU_EP_SEMAPHORE_OFFSET);
+	u32 sem;
+
+	if (lancer_chip(adapter))
+		sem  = ioread32(adapter->db + MPU_EP_SEMAPHORE_IF_TYPE2_OFFSET);
+	else
+		sem  = ioread32(adapter->csr + MPU_EP_SEMAPHORE_OFFSET);
 
 	*stage = sem & EP_SEMAPHORE_POST_STAGE_MASK;
 	if ((sem >> EP_SEMAPHORE_POST_ERR_SHIFT) & EP_SEMAPHORE_POST_ERR_MASK)
@@ -685,16 +690,36 @@ int be_cmd_cq_create(struct be_adapter *
 		OPCODE_COMMON_CQ_CREATE, sizeof(*req));
 
 	req->num_pages =  cpu_to_le16(PAGES_4K_SPANNED(q_mem->va, q_mem->size));
+	if (lancer_chip(adapter)) {
+		req->hdr.version = 1;
+		req->page_size = 1; /* 1 for 4K */
+		AMAP_SET_BITS(struct amap_cq_context_lancer, coalescwm, ctxt,
+								coalesce_wm);
+		AMAP_SET_BITS(struct amap_cq_context_lancer, nodelay, ctxt,
+								no_delay);
+		AMAP_SET_BITS(struct amap_cq_context_lancer, count, ctxt,
+						__ilog2_u32(cq->len/256));
+		AMAP_SET_BITS(struct amap_cq_context_lancer, valid, ctxt, 1);
+		AMAP_SET_BITS(struct amap_cq_context_lancer, eventable,
+								ctxt, 1);
+		AMAP_SET_BITS(struct amap_cq_context_lancer, eqid,
+								ctxt, eq->id);
+		AMAP_SET_BITS(struct amap_cq_context_lancer, armed, ctxt, 1);
+	} else {
+		AMAP_SET_BITS(struct amap_cq_context_be, coalescwm, ctxt,
+								coalesce_wm);
+		AMAP_SET_BITS(struct amap_cq_context_be, nodelay,
+								ctxt, no_delay);
+		AMAP_SET_BITS(struct amap_cq_context_be, count, ctxt,
+						__ilog2_u32(cq->len/256));
+		AMAP_SET_BITS(struct amap_cq_context_be, valid, ctxt, 1);
+		AMAP_SET_BITS(struct amap_cq_context_be, solevent,
+								ctxt, sol_evts);
+		AMAP_SET_BITS(struct amap_cq_context_be, eventable, ctxt, 1);
+		AMAP_SET_BITS(struct amap_cq_context_be, eqid, ctxt, eq->id);
+		AMAP_SET_BITS(struct amap_cq_context_be, armed, ctxt, 1);
+	}
 
-	AMAP_SET_BITS(struct amap_cq_context, coalescwm, ctxt, coalesce_wm);
-	AMAP_SET_BITS(struct amap_cq_context, nodelay, ctxt, no_delay);
-	AMAP_SET_BITS(struct amap_cq_context, count, ctxt,
-			__ilog2_u32(cq->len/256));
-	AMAP_SET_BITS(struct amap_cq_context, valid, ctxt, 1);
-	AMAP_SET_BITS(struct amap_cq_context, solevent, ctxt, sol_evts);
-	AMAP_SET_BITS(struct amap_cq_context, eventable, ctxt, 1);
-	AMAP_SET_BITS(struct amap_cq_context, eqid, ctxt, eq->id);
-	AMAP_SET_BITS(struct amap_cq_context, armed, ctxt, 1);
 	be_dws_cpu_to_le(ctxt, sizeof(req->context));
 
 	be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem);
@@ -743,13 +768,27 @@ int be_cmd_mccq_create(struct be_adapter
 			OPCODE_COMMON_MCC_CREATE_EXT, sizeof(*req));
 
 	req->num_pages = cpu_to_le16(PAGES_4K_SPANNED(q_mem->va, q_mem->size));
+	if (lancer_chip(adapter)) {
+		req->hdr.version = 1;
+		req->cq_id = cpu_to_le16(cq->id);
+
+		AMAP_SET_BITS(struct amap_mcc_context_lancer, ring_size, ctxt,
+						be_encoded_q_len(mccq->len));
+		AMAP_SET_BITS(struct amap_mcc_context_lancer, valid, ctxt, 1);
+		AMAP_SET_BITS(struct amap_mcc_context_lancer, async_cq_id,
+								ctxt, cq->id);
+		AMAP_SET_BITS(struct amap_mcc_context_lancer, async_cq_valid,
+								 ctxt, 1);
+
+	} else {
+		AMAP_SET_BITS(struct amap_mcc_context_be, valid, ctxt, 1);
+		AMAP_SET_BITS(struct amap_mcc_context_be, ring_size, ctxt,
+						be_encoded_q_len(mccq->len));
+		AMAP_SET_BITS(struct amap_mcc_context_be, cq_id, ctxt, cq->id);
+	}
 
-	AMAP_SET_BITS(struct amap_mcc_context, valid, ctxt, 1);
-	AMAP_SET_BITS(struct amap_mcc_context, ring_size, ctxt,
-		be_encoded_q_len(mccq->len));
-	AMAP_SET_BITS(struct amap_mcc_context, cq_id, ctxt, cq->id);
 	/* Subscribe to Link State and Group 5 Events(bits 1 and 5 set) */
-	req->async_event_bitmap[0] |= 0x00000022;
+	req->async_event_bitmap[0] = cpu_to_le32(0x00000022);
 	be_dws_cpu_to_le(ctxt, sizeof(req->context));
 
 	be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem);
@@ -1747,6 +1786,10 @@ int be_cmd_get_seeprom_data(struct be_ad
 	spin_lock_bh(&adapter->mcc_lock);
 
 	wrb = wrb_from_mccq(adapter);
+	if (!wrb) {
+		status = -EBUSY;
+		goto err;
+	}
 	req = nonemb_cmd->va;
 	sge = nonembedded_sgl(wrb);
 
@@ -1762,6 +1805,7 @@ int be_cmd_get_seeprom_data(struct be_ad
 
 	status = be_mcc_notify_wait(adapter);
 
+err:
 	spin_unlock_bh(&adapter->mcc_lock);
 	return status;
 }
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/benet/be_cmds.h linux-libre-2.6.38-gnu1/drivers/net/benet/be_cmds.h
--- linux-libre-2.6.37-gnu1/drivers/net/benet/be_cmds.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/benet/be_cmds.h	2011-03-14 21:20:32.000000000 -0400
@@ -309,7 +309,7 @@ struct be_cmd_req_pmac_del {
 /******************** Create CQ ***************************/
 /* Pseudo amap definition in which each bit of the actual structure is defined
  * as a byte: used to calculate offset/shift/mask of each field */
-struct amap_cq_context {
+struct amap_cq_context_be {
 	u8 cidx[11];		/* dword 0*/
 	u8 rsvd0;		/* dword 0*/
 	u8 coalescwm[2];	/* dword 0*/
@@ -332,14 +332,32 @@ struct amap_cq_context {
 	u8 rsvd5[32];		/* dword 3*/
 } __packed;
 
+struct amap_cq_context_lancer {
+	u8 rsvd0[12];		/* dword 0*/
+	u8 coalescwm[2];	/* dword 0*/
+	u8 nodelay;		/* dword 0*/
+	u8 rsvd1[12];		/* dword 0*/
+	u8 count[2];		/* dword 0*/
+	u8 valid;		/* dword 0*/
+	u8 rsvd2;		/* dword 0*/
+	u8 eventable;		/* dword 0*/
+	u8 eqid[16];		/* dword 1*/
+	u8 rsvd3[15];		/* dword 1*/
+	u8 armed;		/* dword 1*/
+	u8 rsvd4[32];		/* dword 2*/
+	u8 rsvd5[32];		/* dword 3*/
+} __packed;
+
 struct be_cmd_req_cq_create {
 	struct be_cmd_req_hdr hdr;
 	u16 num_pages;
-	u16 rsvd0;
-	u8 context[sizeof(struct amap_cq_context) / 8];
+	u8 page_size;
+	u8 rsvd0;
+	u8 context[sizeof(struct amap_cq_context_be) / 8];
 	struct phys_addr pages[8];
 } __packed;
 
+
 struct be_cmd_resp_cq_create {
 	struct be_cmd_resp_hdr hdr;
 	u16 cq_id;
@@ -349,7 +367,7 @@ struct be_cmd_resp_cq_create {
 /******************** Create MCCQ ***************************/
 /* Pseudo amap definition in which each bit of the actual structure is defined
  * as a byte: used to calculate offset/shift/mask of each field */
-struct amap_mcc_context {
+struct amap_mcc_context_be {
 	u8 con_index[14];
 	u8 rsvd0[2];
 	u8 ring_size[4];
@@ -364,12 +382,23 @@ struct amap_mcc_context {
 	u8 rsvd2[32];
 } __packed;
 
+struct amap_mcc_context_lancer {
+	u8 async_cq_id[16];
+	u8 ring_size[4];
+	u8 rsvd0[12];
+	u8 rsvd1[31];
+	u8 valid;
+	u8 async_cq_valid[1];
+	u8 rsvd2[31];
+	u8 rsvd3[32];
+} __packed;
+
 struct be_cmd_req_mcc_create {
 	struct be_cmd_req_hdr hdr;
 	u16 num_pages;
-	u16 rsvd0;
+	u16 cq_id;
 	u32 async_event_bitmap[1];
-	u8 context[sizeof(struct amap_mcc_context) / 8];
+	u8 context[sizeof(struct amap_mcc_context_be) / 8];
 	struct phys_addr pages[8];
 } __packed;
 
@@ -605,6 +634,7 @@ struct be_hw_stats {
 	struct be_rxf_stats rxf;
 	u32 rsvd[48];
 	struct be_erx_stats erx;
+	u32 rsvd1[6];
 };
 
 struct be_cmd_req_get_stats {
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/benet/be_ethtool.c linux-libre-2.6.38-gnu1/drivers/net/benet/be_ethtool.c
--- linux-libre-2.6.37-gnu1/drivers/net/benet/be_ethtool.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/benet/be_ethtool.c	2011-03-14 21:20:32.000000000 -0400
@@ -549,7 +549,9 @@ be_test_ddr_dma(struct be_adapter *adapt
 {
 	int ret, i;
 	struct be_dma_mem ddrdma_cmd;
-	u64 pattern[2] = {0x5a5a5a5a5a5a5a5aULL, 0xa5a5a5a5a5a5a5a5ULL};
+	static const u64 pattern[2] = {
+		0x5a5a5a5a5a5a5a5aULL, 0xa5a5a5a5a5a5a5a5ULL
+	};
 
 	ddrdma_cmd.size = sizeof(struct be_cmd_req_ddrdma_test);
 	ddrdma_cmd.va = pci_alloc_consistent(adapter->pdev, ddrdma_cmd.size,
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/benet/be.h linux-libre-2.6.38-gnu1/drivers/net/benet/be.h
--- linux-libre-2.6.37-gnu1/drivers/net/benet/be.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/benet/be.h	2011-03-14 21:20:32.000000000 -0400
@@ -38,14 +38,17 @@
 #define BE_NAME			"ServerEngines BladeEngine2 10Gbps NIC"
 #define BE3_NAME		"ServerEngines BladeEngine3 10Gbps NIC"
 #define OC_NAME			"Emulex OneConnect 10Gbps NIC"
-#define OC_NAME1		"Emulex OneConnect 10Gbps NIC (be3)"
+#define OC_NAME_BE		OC_NAME	"(be3)"
+#define OC_NAME_LANCER		OC_NAME "(Lancer)"
 #define DRV_DESC		"ServerEngines BladeEngine 10Gbps NIC Driver"
 
 #define BE_VENDOR_ID 		0x19a2
+#define EMULEX_VENDOR_ID	0x10df
 #define BE_DEVICE_ID1		0x211
 #define BE_DEVICE_ID2		0x221
-#define OC_DEVICE_ID1		0x700
-#define OC_DEVICE_ID2		0x710
+#define OC_DEVICE_ID1		0x700	/* Device Id for BE2 cards */
+#define OC_DEVICE_ID2		0x710	/* Device Id for BE3 cards */
+#define OC_DEVICE_ID3		0xe220	/* Device id for Lancer cards */
 
 static inline char *nic_name(struct pci_dev *pdev)
 {
@@ -53,7 +56,9 @@ static inline char *nic_name(struct pci_
 	case OC_DEVICE_ID1:
 		return OC_NAME;
 	case OC_DEVICE_ID2:
-		return OC_NAME1;
+		return OC_NAME_BE;
+	case OC_DEVICE_ID3:
+		return OC_NAME_LANCER;
 	case BE_DEVICE_ID2:
 		return BE3_NAME;
 	default:
@@ -149,6 +154,7 @@ struct be_eq_obj {
 	u16 min_eqd;		/* in usecs */
 	u16 max_eqd;		/* in usecs */
 	u16 cur_eqd;		/* in usecs */
+	u8  msix_vec_idx;
 
 	struct napi_struct napi;
 };
@@ -214,7 +220,9 @@ struct be_rx_obj {
 	struct be_rx_stats stats;
 	u8 rss_id;
 	bool rx_post_starved;	/* Zero rx frags have been posted to BE */
-	u32 cache_line_barrier[16];
+	u16 last_frag_index;
+	u16 rsvd;
+	u32 cache_line_barrier[15];
 };
 
 struct be_vf_cfg {
@@ -260,6 +268,8 @@ struct be_adapter {
 	u32 num_rx_qs;
 	u32 big_page_size;	/* Compounded page size shared by rx wrbs */
 
+	u8 msix_vec_next_idx;
+
 	struct vlan_group *vlan_grp;
 	u16 vlans_added;
 	u16 max_vlans;	/* Number of vlans supported */
@@ -299,8 +309,8 @@ struct be_adapter {
 
 	bool sriov_enabled;
 	struct be_vf_cfg vf_cfg[BE_MAX_VF];
-	u8 base_eq_id;
 	u8 is_virtfn;
+	u32 sli_family;
 };
 
 #define be_physfn(adapter) (!adapter->is_virtfn)
@@ -309,6 +319,8 @@ struct be_adapter {
 #define BE_GEN2 2
 #define BE_GEN3 3
 
+#define lancer_chip(adapter)		(adapter->pdev->device == OC_DEVICE_ID3)
+
 extern const struct ethtool_ops be_ethtool_ops;
 
 #define tx_stats(adapter)		(&adapter->tx_stats)
@@ -416,10 +428,17 @@ static inline u8 is_udp_pkt(struct sk_bu
 static inline void be_check_sriov_fn_type(struct be_adapter *adapter)
 {
 	u8 data;
+	u32 sli_intf;
 
-	pci_write_config_byte(adapter->pdev, 0xFE, 0xAA);
-	pci_read_config_byte(adapter->pdev, 0xFE, &data);
-	adapter->is_virtfn = (data != 0xAA);
+	if (lancer_chip(adapter)) {
+		pci_read_config_dword(adapter->pdev, SLI_INTF_REG_OFFSET,
+								&sli_intf);
+		adapter->is_virtfn = (sli_intf & SLI_INTF_FT_MASK) ? 1 : 0;
+	} else {
+		pci_write_config_byte(adapter->pdev, 0xFE, 0xAA);
+		pci_read_config_byte(adapter->pdev, 0xFE, &data);
+		adapter->is_virtfn = (data != 0xAA);
+	}
 }
 
 static inline void be_vf_eth_addr_generate(struct be_adapter *adapter, u8 *mac)
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/benet/be_hw.h linux-libre-2.6.38-gnu1/drivers/net/benet/be_hw.h
--- linux-libre-2.6.37-gnu1/drivers/net/benet/be_hw.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/benet/be_hw.h	2011-03-14 21:20:32.000000000 -0400
@@ -32,10 +32,12 @@
 #define MPU_EP_CONTROL 		0
 
 /********** MPU semphore ******************/
-#define MPU_EP_SEMAPHORE_OFFSET 	0xac
-#define EP_SEMAPHORE_POST_STAGE_MASK	0x0000FFFF
-#define EP_SEMAPHORE_POST_ERR_MASK	0x1
-#define EP_SEMAPHORE_POST_ERR_SHIFT	31
+#define MPU_EP_SEMAPHORE_OFFSET		0xac
+#define MPU_EP_SEMAPHORE_IF_TYPE2_OFFSET	0x400
+#define EP_SEMAPHORE_POST_STAGE_MASK		0x0000FFFF
+#define EP_SEMAPHORE_POST_ERR_MASK		0x1
+#define EP_SEMAPHORE_POST_ERR_SHIFT		31
+
 /* MPU semphore POST stage values */
 #define POST_STAGE_AWAITING_HOST_RDY 	0x1 /* FW awaiting goahead from host */
 #define POST_STAGE_HOST_RDY 		0x2 /* Host has given go-ahed to FW */
@@ -66,6 +68,28 @@
 #define PCICFG_UE_STATUS_LOW_MASK		0xA8
 #define PCICFG_UE_STATUS_HI_MASK		0xAC
 
+/******** SLI_INTF ***********************/
+#define SLI_INTF_REG_OFFSET			0x58
+#define SLI_INTF_VALID_MASK			0xE0000000
+#define SLI_INTF_VALID				0xC0000000
+#define SLI_INTF_HINT2_MASK			0x1F000000
+#define SLI_INTF_HINT2_SHIFT			24
+#define SLI_INTF_HINT1_MASK			0x00FF0000
+#define SLI_INTF_HINT1_SHIFT			16
+#define SLI_INTF_FAMILY_MASK			0x00000F00
+#define SLI_INTF_FAMILY_SHIFT			8
+#define SLI_INTF_IF_TYPE_MASK			0x0000F000
+#define SLI_INTF_IF_TYPE_SHIFT			12
+#define SLI_INTF_REV_MASK			0x000000F0
+#define SLI_INTF_REV_SHIFT			4
+#define SLI_INTF_FT_MASK			0x00000001
+
+
+/* SLI family */
+#define BE_SLI_FAMILY		0x0
+#define LANCER_A0_SLI_FAMILY	0xA
+
+
 /********* ISR0 Register offset **********/
 #define CEV_ISR0_OFFSET 			0xC18
 #define CEV_ISR_SIZE				4
@@ -73,6 +97,9 @@
 /********* Event Q door bell *************/
 #define DB_EQ_OFFSET			DB_CQ_OFFSET
 #define DB_EQ_RING_ID_MASK		0x1FF	/* bits 0 - 8 */
+#define DB_EQ_RING_ID_EXT_MASK		0x3e00  /* bits 9-13 */
+#define DB_EQ_RING_ID_EXT_MASK_SHIFT	(2) /* qid bits 9-13 placing at 11-15 */
+
 /* Clear the interrupt for this eq */
 #define DB_EQ_CLR_SHIFT			(9)	/* bit 9 */
 /* Must be 1 */
@@ -85,6 +112,10 @@
 /********* Compl Q door bell *************/
 #define DB_CQ_OFFSET 			0x120
 #define DB_CQ_RING_ID_MASK		0x3FF	/* bits 0 - 9 */
+#define DB_CQ_RING_ID_EXT_MASK		0x7C00	/* bits 10-14 */
+#define DB_CQ_RING_ID_EXT_MASK_SHIFT	(1)	/* qid bits 10-14
+						 placing at 11-15 */
+
 /* Number of event entries processed */
 #define DB_CQ_NUM_POPPED_SHIFT		(16) 	/* bits 16 - 28 */
 /* Rearm bit */
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/benet/be_main.c linux-libre-2.6.38-gnu1/drivers/net/benet/be_main.c
--- linux-libre-2.6.37-gnu1/drivers/net/benet/be_main.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/benet/be_main.c	2011-03-14 21:20:32.000000000 -0400
@@ -41,6 +41,7 @@ static DEFINE_PCI_DEVICE_TABLE(be_dev_id
 	{ PCI_DEVICE(BE_VENDOR_ID, BE_DEVICE_ID2) },
 	{ PCI_DEVICE(BE_VENDOR_ID, OC_DEVICE_ID1) },
 	{ PCI_DEVICE(BE_VENDOR_ID, OC_DEVICE_ID2) },
+	{ PCI_DEVICE(EMULEX_VENDOR_ID, OC_DEVICE_ID3)},
 	{ 0 }
 };
 MODULE_DEVICE_TABLE(pci, be_dev_ids);
@@ -188,6 +189,8 @@ static void be_eq_notify(struct be_adapt
 {
 	u32 val = 0;
 	val |= qid & DB_EQ_RING_ID_MASK;
+	val |= ((qid & DB_EQ_RING_ID_EXT_MASK) <<
+			DB_EQ_RING_ID_EXT_MASK_SHIFT);
 
 	if (adapter->eeh_err)
 		return;
@@ -205,6 +208,8 @@ void be_cq_notify(struct be_adapter *ada
 {
 	u32 val = 0;
 	val |= qid & DB_CQ_RING_ID_MASK;
+	val |= ((qid & DB_CQ_RING_ID_EXT_MASK) <<
+			DB_CQ_RING_ID_EXT_MASK_SHIFT);
 
 	if (adapter->eeh_err)
 		return;
@@ -307,11 +312,9 @@ void be_link_status_update(struct be_ada
 	if (adapter->link_up != link_up) {
 		adapter->link_speed = -1;
 		if (link_up) {
-			netif_start_queue(netdev);
 			netif_carrier_on(netdev);
 			printk(KERN_INFO "%s: Link up\n", netdev->name);
 		} else {
-			netif_stop_queue(netdev);
 			netif_carrier_off(netdev);
 			printk(KERN_INFO "%s: Link down\n", netdev->name);
 		}
@@ -404,7 +407,8 @@ static void be_tx_stats_update(struct be
 }
 
 /* Determine number of WRB entries needed to xmit data in an skb */
-static u32 wrb_cnt_for_skb(struct sk_buff *skb, bool *dummy)
+static u32 wrb_cnt_for_skb(struct be_adapter *adapter, struct sk_buff *skb,
+								bool *dummy)
 {
 	int cnt = (skb->len > skb->data_len);
 
@@ -412,12 +416,13 @@ static u32 wrb_cnt_for_skb(struct sk_buf
 
 	/* to account for hdr wrb */
 	cnt++;
-	if (cnt & 1) {
+	if (lancer_chip(adapter) || !(cnt & 1)) {
+		*dummy = false;
+	} else {
 		/* add a dummy to make it an even num */
 		cnt++;
 		*dummy = true;
-	} else
-		*dummy = false;
+	}
 	BUG_ON(cnt > BE_MAX_TX_FRAG_COUNT);
 	return cnt;
 }
@@ -443,8 +448,18 @@ static void wrb_fill_hdr(struct be_adapt
 		AMAP_SET_BITS(struct amap_eth_hdr_wrb, lso, hdr, 1);
 		AMAP_SET_BITS(struct amap_eth_hdr_wrb, lso_mss,
 			hdr, skb_shinfo(skb)->gso_size);
-		if (skb_is_gso_v6(skb))
+		if (skb_is_gso_v6(skb) && !lancer_chip(adapter))
 			AMAP_SET_BITS(struct amap_eth_hdr_wrb, lso6, hdr, 1);
+		if (lancer_chip(adapter) && adapter->sli_family  ==
+							LANCER_A0_SLI_FAMILY) {
+			AMAP_SET_BITS(struct amap_eth_hdr_wrb, ipcs, hdr, 1);
+			if (is_tcp_pkt(skb))
+				AMAP_SET_BITS(struct amap_eth_hdr_wrb,
+								tcpcs, hdr, 1);
+			else if (is_udp_pkt(skb))
+				AMAP_SET_BITS(struct amap_eth_hdr_wrb,
+								udpcs, hdr, 1);
+		}
 	} else if (skb->ip_summed == CHECKSUM_PARTIAL) {
 		if (is_tcp_pkt(skb))
 			AMAP_SET_BITS(struct amap_eth_hdr_wrb, tcpcs, hdr, 1);
@@ -566,7 +581,7 @@ static netdev_tx_t be_xmit(struct sk_buf
 	u32 start = txq->head;
 	bool dummy_wrb, stopped = false;
 
-	wrb_cnt = wrb_cnt_for_skb(skb, &dummy_wrb);
+	wrb_cnt = wrb_cnt_for_skb(adapter, skb, &dummy_wrb);
 
 	copied = make_tx_wrbs(adapter, skb, wrb_cnt, dummy_wrb);
 	if (copied) {
@@ -894,11 +909,17 @@ static void be_rx_compl_discard(struct b
 	rxq_idx = AMAP_GET_BITS(struct amap_eth_rx_compl, fragndx, rxcp);
 	num_rcvd = AMAP_GET_BITS(struct amap_eth_rx_compl, numfrags, rxcp);
 
-	for (i = 0; i < num_rcvd; i++) {
-		page_info = get_rx_page_info(adapter, rxo, rxq_idx);
-		put_page(page_info->page);
-		memset(page_info, 0, sizeof(*page_info));
-		index_inc(&rxq_idx, rxq->len);
+	 /* Skip out-of-buffer compl(lancer) or flush compl(BE) */
+	if (likely(rxq_idx != rxo->last_frag_index && num_rcvd != 0)) {
+
+		rxo->last_frag_index = rxq_idx;
+
+		for (i = 0; i < num_rcvd; i++) {
+			page_info = get_rx_page_info(adapter, rxo, rxq_idx);
+			put_page(page_info->page);
+			memset(page_info, 0, sizeof(*page_info));
+			index_inc(&rxq_idx, rxq->len);
+		}
 	}
 }
 
@@ -999,9 +1020,6 @@ static void be_rx_compl_process(struct b
 	u8 vtm;
 
 	num_rcvd = AMAP_GET_BITS(struct amap_eth_rx_compl, numfrags, rxcp);
-	/* Is it a flush compl that has no data */
-	if (unlikely(num_rcvd == 0))
-		return;
 
 	skb = netdev_alloc_skb_ip_align(adapter->netdev, BE_HDR_LEN);
 	if (unlikely(!skb)) {
@@ -1035,7 +1053,8 @@ static void be_rx_compl_process(struct b
 			return;
 		}
 		vid = AMAP_GET_BITS(struct amap_eth_rx_compl, vlan_tag, rxcp);
-		vid = swab16(vid);
+		if (!lancer_chip(adapter))
+			vid = swab16(vid);
 		vlan_hwaccel_receive_skb(skb, adapter->vlan_grp, vid);
 	} else {
 		netif_receive_skb(skb);
@@ -1057,10 +1076,6 @@ static void be_rx_compl_process_gro(stru
 	u8 pkt_type;
 
 	num_rcvd = AMAP_GET_BITS(struct amap_eth_rx_compl, numfrags, rxcp);
-	/* Is it a flush compl that has no data */
-	if (unlikely(num_rcvd == 0))
-		return;
-
 	pkt_size = AMAP_GET_BITS(struct amap_eth_rx_compl, pktsize, rxcp);
 	vlanf = AMAP_GET_BITS(struct amap_eth_rx_compl, vtp, rxcp);
 	rxq_idx = AMAP_GET_BITS(struct amap_eth_rx_compl, fragndx, rxcp);
@@ -1113,7 +1128,8 @@ static void be_rx_compl_process_gro(stru
 		napi_gro_frags(&eq_obj->napi);
 	} else {
 		vid = AMAP_GET_BITS(struct amap_eth_rx_compl, vlan_tag, rxcp);
-		vid = swab16(vid);
+		if (!lancer_chip(adapter))
+			vid = swab16(vid);
 
 		if (!adapter->vlan_grp || adapter->vlans_added == 0)
 			return;
@@ -1330,7 +1346,7 @@ static void be_rx_q_clean(struct be_adap
 	while ((rxcp = be_rx_compl_get(rxo)) != NULL) {
 		be_rx_compl_discard(adapter, rxo, rxcp);
 		be_rx_compl_reset(rxcp);
-		be_cq_notify(adapter, rx_cq->id, true, 1);
+		be_cq_notify(adapter, rx_cq->id, false, 1);
 	}
 
 	/* Then free posted rx buffer that were not used */
@@ -1381,7 +1397,8 @@ static void be_tx_compl_clean(struct be_
 		sent_skb = sent_skbs[txq->tail];
 		end_idx = txq->tail;
 		index_adv(&end_idx,
-			wrb_cnt_for_skb(sent_skb, &dummy_wrb) - 1, txq->len);
+			wrb_cnt_for_skb(adapter, sent_skb, &dummy_wrb) - 1,
+			txq->len);
 		be_tx_compl_process(adapter, end_idx);
 	}
 }
@@ -1476,7 +1493,9 @@ static int be_tx_queues_create(struct be
 	/* Ask BE to create Tx Event queue */
 	if (be_cmd_eq_create(adapter, eq, adapter->tx_eq.cur_eqd))
 		goto tx_eq_free;
-	adapter->base_eq_id = adapter->tx_eq.q.id;
+
+	adapter->tx_eq.msix_vec_idx = adapter->msix_vec_next_idx++;
+
 
 	/* Alloc TX eth compl queue */
 	cq = &adapter->tx_obj.cq;
@@ -1554,6 +1573,9 @@ static int be_rx_queues_create(struct be
 	adapter->big_page_size = (1 << get_order(rx_frag_size)) * PAGE_SIZE;
 	for_all_rx_queues(adapter, rxo, i) {
 		rxo->adapter = adapter;
+		/* Init last_frag_index so that the frag index in the first
+		 * completion will never match */
+		rxo->last_frag_index = 0xffff;
 		rxo->rx_eq.max_eqd = BE_MAX_EQD;
 		rxo->rx_eq.enable_aic = true;
 
@@ -1568,6 +1590,8 @@ static int be_rx_queues_create(struct be
 		if (rc)
 			goto err;
 
+		rxo->rx_eq.msix_vec_idx = adapter->msix_vec_next_idx++;
+
 		/* CQ */
 		cq = &rxo->cq;
 		rc = be_queue_alloc(adapter, cq, RX_CQ_LEN,
@@ -1578,7 +1602,6 @@ static int be_rx_queues_create(struct be
 		rc = be_cmd_cq_create(adapter, cq, eq, false, false, 3);
 		if (rc)
 			goto err;
-
 		/* Rx Q */
 		q = &rxo->q;
 		rc = be_queue_alloc(adapter, q, RX_Q_LEN,
@@ -1611,29 +1634,45 @@ err:
 	return -1;
 }
 
-/* There are 8 evt ids per func. Retruns the evt id's bit number */
-static inline int be_evt_bit_get(struct be_adapter *adapter, u32 eq_id)
+static bool event_peek(struct be_eq_obj *eq_obj)
 {
-	return eq_id - adapter->base_eq_id;
+	struct be_eq_entry *eqe = queue_tail_node(&eq_obj->q);
+	if (!eqe->evt)
+		return false;
+	else
+		return true;
 }
 
 static irqreturn_t be_intx(int irq, void *dev)
 {
 	struct be_adapter *adapter = dev;
 	struct be_rx_obj *rxo;
-	int isr, i;
+	int isr, i, tx = 0 , rx = 0;
 
-	isr = ioread32(adapter->csr + CEV_ISR0_OFFSET +
-		(adapter->tx_eq.q.id/ 8) * CEV_ISR_SIZE);
-	if (!isr)
-		return IRQ_NONE;
+	if (lancer_chip(adapter)) {
+		if (event_peek(&adapter->tx_eq))
+			tx = event_handle(adapter, &adapter->tx_eq);
+		for_all_rx_queues(adapter, rxo, i) {
+			if (event_peek(&rxo->rx_eq))
+				rx |= event_handle(adapter, &rxo->rx_eq);
+		}
 
-	if ((1 << be_evt_bit_get(adapter, adapter->tx_eq.q.id) & isr))
-		event_handle(adapter, &adapter->tx_eq);
+		if (!(tx || rx))
+			return IRQ_NONE;
 
-	for_all_rx_queues(adapter, rxo, i) {
-		if ((1 << be_evt_bit_get(adapter, rxo->rx_eq.q.id) & isr))
-			event_handle(adapter, &rxo->rx_eq);
+	} else {
+		isr = ioread32(adapter->csr + CEV_ISR0_OFFSET +
+			(adapter->tx_eq.q.id / 8) * CEV_ISR_SIZE);
+		if (!isr)
+			return IRQ_NONE;
+
+		if ((1 << adapter->tx_eq.msix_vec_idx & isr))
+			event_handle(adapter, &adapter->tx_eq);
+
+		for_all_rx_queues(adapter, rxo, i) {
+			if ((1 << rxo->rx_eq.msix_vec_idx & isr))
+				event_handle(adapter, &rxo->rx_eq);
+		}
 	}
 
 	return IRQ_HANDLED;
@@ -1658,10 +1697,9 @@ static irqreturn_t be_msix_tx_mcc(int ir
 	return IRQ_HANDLED;
 }
 
-static inline bool do_gro(struct be_adapter *adapter, struct be_rx_obj *rxo,
-			struct be_eth_rx_compl *rxcp)
+static inline bool do_gro(struct be_rx_obj *rxo,
+			struct be_eth_rx_compl *rxcp, u8 err)
 {
-	int err = AMAP_GET_BITS(struct amap_eth_rx_compl, err, rxcp);
 	int tcp_frame = AMAP_GET_BITS(struct amap_eth_rx_compl, tcpf, rxcp);
 
 	if (err)
@@ -1678,6 +1716,8 @@ static int be_poll_rx(struct napi_struct
 	struct be_queue_info *rx_cq = &rxo->cq;
 	struct be_eth_rx_compl *rxcp;
 	u32 work_done;
+	u16 frag_index, num_rcvd;
+	u8 err;
 
 	rxo->stats.rx_polls++;
 	for (work_done = 0; work_done < budget; work_done++) {
@@ -1685,10 +1725,22 @@ static int be_poll_rx(struct napi_struct
 		if (!rxcp)
 			break;
 
-		if (do_gro(adapter, rxo, rxcp))
-			be_rx_compl_process_gro(adapter, rxo, rxcp);
-		else
-			be_rx_compl_process(adapter, rxo, rxcp);
+		err = AMAP_GET_BITS(struct amap_eth_rx_compl, err, rxcp);
+		frag_index = AMAP_GET_BITS(struct amap_eth_rx_compl, fragndx,
+								rxcp);
+		num_rcvd = AMAP_GET_BITS(struct amap_eth_rx_compl, numfrags,
+								rxcp);
+
+		/* Skip out-of-buffer compl(lancer) or flush compl(BE) */
+		if (likely(frag_index != rxo->last_frag_index &&
+				num_rcvd != 0)) {
+			rxo->last_frag_index = frag_index;
+
+			if (do_gro(rxo, rxcp, err))
+				be_rx_compl_process_gro(adapter, rxo, rxcp);
+			else
+				be_rx_compl_process(adapter, rxo, rxcp);
+		}
 
 		be_rx_compl_reset(rxcp);
 	}
@@ -1830,8 +1882,7 @@ static void be_worker(struct work_struct
 			be_post_rx_frags(rxo);
 		}
 	}
-
-	if (!adapter->ue_detected)
+	if (!adapter->ue_detected && !lancer_chip(adapter))
 		be_detect_dump_ue(adapter);
 
 reschedule:
@@ -1910,10 +1961,10 @@ static void be_sriov_disable(struct be_a
 #endif
 }
 
-static inline int be_msix_vec_get(struct be_adapter *adapter, u32 eq_id)
+static inline int be_msix_vec_get(struct be_adapter *adapter,
+					struct be_eq_obj *eq_obj)
 {
-	return adapter->msix_entries[
-			be_evt_bit_get(adapter, eq_id)].vector;
+	return adapter->msix_entries[eq_obj->msix_vec_idx].vector;
 }
 
 static int be_request_irq(struct be_adapter *adapter,
@@ -1924,14 +1975,14 @@ static int be_request_irq(struct be_adap
 	int vec;
 
 	sprintf(eq_obj->desc, "%s-%s", netdev->name, desc);
-	vec = be_msix_vec_get(adapter, eq_obj->q.id);
+	vec = be_msix_vec_get(adapter, eq_obj);
 	return request_irq(vec, handler, 0, eq_obj->desc, context);
 }
 
 static void be_free_irq(struct be_adapter *adapter, struct be_eq_obj *eq_obj,
 			void *context)
 {
-	int vec = be_msix_vec_get(adapter, eq_obj->q.id);
+	int vec = be_msix_vec_get(adapter, eq_obj);
 	free_irq(vec, context);
 }
 
@@ -2036,14 +2087,15 @@ static int be_close(struct net_device *n
 	netif_carrier_off(netdev);
 	adapter->link_up = false;
 
-	be_intr_set(adapter, false);
+	if (!lancer_chip(adapter))
+		be_intr_set(adapter, false);
 
 	if (adapter->msix_enabled) {
-		vec = be_msix_vec_get(adapter, tx_eq->q.id);
+		vec = be_msix_vec_get(adapter, tx_eq);
 		synchronize_irq(vec);
 
 		for_all_rx_queues(adapter, rxo, i) {
-			vec = be_msix_vec_get(adapter, rxo->rx_eq.q.id);
+			vec = be_msix_vec_get(adapter, &rxo->rx_eq);
 			synchronize_irq(vec);
 		}
 	} else {
@@ -2082,7 +2134,8 @@ static int be_open(struct net_device *ne
 
 	be_irq_register(adapter);
 
-	be_intr_set(adapter, true);
+	if (!lancer_chip(adapter))
+		be_intr_set(adapter, true);
 
 	/* The evt queues are created in unarmed state; arm them */
 	for_all_rx_queues(adapter, rxo, i) {
@@ -2343,10 +2396,10 @@ static int be_flash_data(struct be_adapt
 	int num_bytes;
 	const u8 *p = fw->data;
 	struct be_cmd_write_flashrom *req = flash_cmd->va;
-	struct flash_comp *pflashcomp;
+	const struct flash_comp *pflashcomp;
 	int num_comp;
 
-	struct flash_comp gen3_flash_types[9] = {
+	static const struct flash_comp gen3_flash_types[9] = {
 		{ FLASH_iSCSI_PRIMARY_IMAGE_START_g3, IMG_TYPE_ISCSI_ACTIVE,
 			FLASH_IMAGE_MAX_SIZE_g3},
 		{ FLASH_REDBOOT_START_g3, IMG_TYPE_REDBOOT,
@@ -2366,7 +2419,7 @@ static int be_flash_data(struct be_adapt
 		{ FLASH_NCSI_START_g3, IMG_TYPE_NCSI_FW,
 			FLASH_NCSI_IMAGE_MAX_SIZE_g3}
 	};
-	struct flash_comp gen2_flash_types[8] = {
+	static const struct flash_comp gen2_flash_types[8] = {
 		{ FLASH_iSCSI_PRIMARY_IMAGE_START_g2, IMG_TYPE_ISCSI_ACTIVE,
 			FLASH_IMAGE_MAX_SIZE_g2},
 		{ FLASH_REDBOOT_START_g2, IMG_TYPE_REDBOOT,
@@ -2388,11 +2441,11 @@ static int be_flash_data(struct be_adapt
 	if (adapter->generation == BE_GEN3) {
 		pflashcomp = gen3_flash_types;
 		filehdr_size = sizeof(struct flash_file_hdr_g3);
-		num_comp = 9;
+		num_comp = ARRAY_SIZE(gen3_flash_types);
 	} else {
 		pflashcomp = gen2_flash_types;
 		filehdr_size = sizeof(struct flash_file_hdr_g2);
-		num_comp = 8;
+		num_comp = ARRAY_SIZE(gen2_flash_types);
 	}
 	for (i = 0; i < num_comp; i++) {
 		if ((pflashcomp[i].optype == IMG_TYPE_NCSI_FW) &&
@@ -2543,10 +2596,15 @@ static void be_netdev_init(struct net_de
 	int i;
 
 	netdev->features |= NETIF_F_SG | NETIF_F_HW_VLAN_RX | NETIF_F_TSO |
-		NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_FILTER | NETIF_F_HW_CSUM |
+		NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_FILTER |
+		NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
 		NETIF_F_GRO | NETIF_F_TSO6;
 
-	netdev->vlan_features |= NETIF_F_SG | NETIF_F_TSO | NETIF_F_HW_CSUM;
+	netdev->vlan_features |= NETIF_F_SG | NETIF_F_TSO |
+		NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
+
+	if (lancer_chip(adapter))
+		netdev->vlan_features |= NETIF_F_TSO6;
 
 	netdev->flags |= IFF_MULTICAST;
 
@@ -2568,8 +2626,6 @@ static void be_netdev_init(struct net_de
 
 	netif_napi_add(netdev, &adapter->tx_eq.napi, be_poll_tx_mcc,
 		BE_NAPI_WEIGHT);
-
-	netif_stop_queue(netdev);
 }
 
 static void be_unmap_pci_bars(struct be_adapter *adapter)
@@ -2587,6 +2643,15 @@ static int be_map_pci_bars(struct be_ada
 	u8 __iomem *addr;
 	int pcicfg_reg, db_reg;
 
+	if (lancer_chip(adapter)) {
+		addr = ioremap_nocache(pci_resource_start(adapter->pdev, 0),
+			pci_resource_len(adapter->pdev, 0));
+		if (addr == NULL)
+			return -ENOMEM;
+		adapter->db = addr;
+		return 0;
+	}
+
 	if (be_physfn(adapter)) {
 		addr = ioremap_nocache(pci_resource_start(adapter->pdev, 2),
 				pci_resource_len(adapter->pdev, 2));
@@ -2783,6 +2848,44 @@ static int be_get_config(struct be_adapt
 	return 0;
 }
 
+static int be_dev_family_check(struct be_adapter *adapter)
+{
+	struct pci_dev *pdev = adapter->pdev;
+	u32 sli_intf = 0, if_type;
+
+	switch (pdev->device) {
+	case BE_DEVICE_ID1:
+	case OC_DEVICE_ID1:
+		adapter->generation = BE_GEN2;
+		break;
+	case BE_DEVICE_ID2:
+	case OC_DEVICE_ID2:
+		adapter->generation = BE_GEN3;
+		break;
+	case OC_DEVICE_ID3:
+		pci_read_config_dword(pdev, SLI_INTF_REG_OFFSET, &sli_intf);
+		if_type = (sli_intf & SLI_INTF_IF_TYPE_MASK) >>
+						SLI_INTF_IF_TYPE_SHIFT;
+
+		if (((sli_intf & SLI_INTF_VALID_MASK) != SLI_INTF_VALID) ||
+			if_type != 0x02) {
+			dev_err(&pdev->dev, "SLI_INTF reg val is not valid\n");
+			return -EINVAL;
+		}
+		if (num_vfs > 0) {
+			dev_err(&pdev->dev, "VFs not supported\n");
+			return -EINVAL;
+		}
+		adapter->sli_family = ((sli_intf & SLI_INTF_FAMILY_MASK) >>
+					 SLI_INTF_FAMILY_SHIFT);
+		adapter->generation = BE_GEN3;
+		break;
+	default:
+		adapter->generation = 0;
+	}
+	return 0;
+}
+
 static int __devinit be_probe(struct pci_dev *pdev,
 			const struct pci_device_id *pdev_id)
 {
@@ -2805,22 +2908,13 @@ static int __devinit be_probe(struct pci
 		goto rel_reg;
 	}
 	adapter = netdev_priv(netdev);
-
-	switch (pdev->device) {
-	case BE_DEVICE_ID1:
-	case OC_DEVICE_ID1:
-		adapter->generation = BE_GEN2;
-		break;
-	case BE_DEVICE_ID2:
-	case OC_DEVICE_ID2:
-		adapter->generation = BE_GEN3;
-		break;
-	default:
-		adapter->generation = 0;
-	}
-
 	adapter->pdev = pdev;
 	pci_set_drvdata(pdev, adapter);
+
+	status = be_dev_family_check(adapter);
+	if (status)
+		goto free_netdev;
+
 	adapter->netdev = netdev;
 	SET_NETDEV_DEV(netdev, &pdev->dev);
 
@@ -2895,7 +2989,7 @@ ctrl_clean:
 	be_ctrl_cleanup(adapter);
 free_netdev:
 	be_sriov_disable(adapter);
-	free_netdev(adapter->netdev);
+	free_netdev(netdev);
 	pci_set_drvdata(pdev, NULL);
 rel_reg:
 	pci_release_regions(pdev);
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/bfin_mac.c linux-libre-2.6.38-gnu1/drivers/net/bfin_mac.c
--- linux-libre-2.6.37-gnu1/drivers/net/bfin_mac.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/bfin_mac.c	2011-03-14 21:20:32.000000000 -0400
@@ -8,6 +8,11 @@
  * Licensed under the GPL-2 or later.
  */
 
+#define DRV_VERSION	"1.1"
+#define DRV_DESC	"Blackfin on-chip Ethernet MAC driver"
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
@@ -41,12 +46,7 @@
 
 #include "bfin_mac.h"
 
-#define DRV_NAME	"bfin_mac"
-#define DRV_VERSION	"1.1"
-#define DRV_AUTHOR	"Bryan Wu, Luke Yang"
-#define DRV_DESC	"Blackfin on-chip Ethernet MAC driver"
-
-MODULE_AUTHOR(DRV_AUTHOR);
+MODULE_AUTHOR("Bryan Wu, Luke Yang");
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION(DRV_DESC);
 MODULE_ALIAS("platform:bfin_mac");
@@ -189,8 +189,7 @@ static int desc_list_init(void)
 		/* allocate a new skb for next time receive */
 		new_skb = dev_alloc_skb(PKT_BUF_SZ + NET_IP_ALIGN);
 		if (!new_skb) {
-			printk(KERN_NOTICE DRV_NAME
-			       ": init: low on mem - packet dropped\n");
+			pr_notice("init: low on mem - packet dropped\n");
 			goto init_error;
 		}
 		skb_reserve(new_skb, NET_IP_ALIGN);
@@ -240,7 +239,7 @@ static int desc_list_init(void)
 
 init_error:
 	desc_list_free();
-	printk(KERN_ERR DRV_NAME ": kmalloc failed\n");
+	pr_err("kmalloc failed\n");
 	return -ENOMEM;
 }
 
@@ -259,8 +258,7 @@ static int bfin_mdio_poll(void)
 	while ((bfin_read_EMAC_STAADD()) & STABUSY) {
 		udelay(1);
 		if (timeout_cnt-- < 0) {
-			printk(KERN_ERR DRV_NAME
-			": wait MDC/MDIO transaction to complete timeout\n");
+			pr_err("wait MDC/MDIO transaction to complete timeout\n");
 			return -ETIMEDOUT;
 		}
 	}
@@ -350,9 +348,9 @@ static void bfin_mac_adjust_link(struct
 					opmode &= ~RMII_10;
 					break;
 				default:
-					printk(KERN_WARNING
-						"%s: Ack!  Speed (%d) is not 10/100!\n",
-						DRV_NAME, phydev->speed);
+					netdev_warn(dev,
+						"Ack! Speed (%d) is not 10/100!\n",
+						phydev->speed);
 					break;
 				}
 				bfin_write_EMAC_OPMODE(opmode);
@@ -417,14 +415,13 @@ static int mii_probe(struct net_device *
 
 	/* now we are supposed to have a proper phydev, to attach to... */
 	if (!phydev) {
-		printk(KERN_INFO "%s: Don't found any phy device at all\n",
-			dev->name);
+		netdev_err(dev, "no phy device found\n");
 		return -ENODEV;
 	}
 
 	if (phy_mode != PHY_INTERFACE_MODE_RMII &&
 		phy_mode != PHY_INTERFACE_MODE_MII) {
-		printk(KERN_INFO "%s: Invalid phy interface mode\n", dev->name);
+		netdev_err(dev, "invalid phy interface mode\n");
 		return -EINVAL;
 	}
 
@@ -432,7 +429,7 @@ static int mii_probe(struct net_device *
 			0, phy_mode);
 
 	if (IS_ERR(phydev)) {
-		printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name);
+		netdev_err(dev, "could not attach PHY\n");
 		return PTR_ERR(phydev);
 	}
 
@@ -453,11 +450,10 @@ static int mii_probe(struct net_device *
 	lp->old_duplex = -1;
 	lp->phydev = phydev;
 
-	printk(KERN_INFO "%s: attached PHY driver [%s] "
-	       "(mii_bus:phy_addr=%s, irq=%d, mdc_clk=%dHz(mdc_div=%d)"
-	       "@sclk=%dMHz)\n",
-	       DRV_NAME, phydev->drv->name, dev_name(&phydev->dev), phydev->irq,
-	       MDC_CLK, mdc_div, sclk/1000000);
+	pr_info("attached PHY driver [%s] "
+	        "(mii_bus:phy_addr=%s, irq=%d, mdc_clk=%dHz(mdc_div=%d)@sclk=%dMHz)\n",
+	        phydev->drv->name, dev_name(&phydev->dev), phydev->irq,
+	        MDC_CLK, mdc_div, sclk/1000000);
 
 	return 0;
 }
@@ -502,7 +498,7 @@ bfin_mac_ethtool_setsettings(struct net_
 static void bfin_mac_ethtool_getdrvinfo(struct net_device *dev,
 					struct ethtool_drvinfo *info)
 {
-	strcpy(info->driver, DRV_NAME);
+	strcpy(info->driver, KBUILD_MODNAME);
 	strcpy(info->version, DRV_VERSION);
 	strcpy(info->fw_version, "N/A");
 	strcpy(info->bus_info, dev_name(&dev->dev));
@@ -562,7 +558,7 @@ static const struct ethtool_ops bfin_mac
 };
 
 /**************************************************************************/
-void setup_system_regs(struct net_device *dev)
+static void setup_system_regs(struct net_device *dev)
 {
 	struct bfin_mac_local *lp = netdev_priv(dev);
 	int i;
@@ -592,6 +588,10 @@ void setup_system_regs(struct net_device
 
 	bfin_write_EMAC_MMC_CTL(RSTC | CROLL);
 
+	/* Set vlan regs to let 1522 bytes long packets pass through */
+	bfin_write_EMAC_VLAN1(lp->vlan1_mask);
+	bfin_write_EMAC_VLAN2(lp->vlan2_mask);
+
 	/* Initialize the TX DMA channel registers */
 	bfin_write_DMA2_X_COUNT(0);
 	bfin_write_DMA2_X_MODIFY(4);
@@ -827,8 +827,7 @@ static void bfin_tx_hwtstamp(struct net_
 		while ((!(bfin_read_EMAC_PTP_ISTAT() & TXTL)) && (--timeout_cnt))
 			udelay(1);
 		if (timeout_cnt == 0)
-			printk(KERN_ERR DRV_NAME
-					": fails to timestamp the TX packet\n");
+			netdev_err(netdev, "timestamp the TX packet failed\n");
 		else {
 			struct skb_shared_hwtstamps shhwtstamps;
 			u64 ns;
@@ -1083,8 +1082,7 @@ static void bfin_mac_rx(struct net_devic
 	 * we which case we simply drop the packet
 	 */
 	if (current_rx_ptr->status.status_word & RX_ERROR_MASK) {
-		printk(KERN_NOTICE DRV_NAME
-		       ": rx: receive error - packet dropped\n");
+		netdev_notice(dev, "rx: receive error - packet dropped\n");
 		dev->stats.rx_dropped++;
 		goto out;
 	}
@@ -1094,8 +1092,7 @@ static void bfin_mac_rx(struct net_devic
 
 	new_skb = dev_alloc_skb(PKT_BUF_SZ + NET_IP_ALIGN);
 	if (!new_skb) {
-		printk(KERN_NOTICE DRV_NAME
-		       ": rx: low on mem - packet dropped\n");
+		netdev_notice(dev, "rx: low on mem - packet dropped\n");
 		dev->stats.rx_dropped++;
 		goto out;
 	}
@@ -1213,7 +1210,7 @@ static int bfin_mac_enable(struct phy_de
 	int ret;
 	u32 opmode;
 
-	pr_debug("%s: %s\n", DRV_NAME, __func__);
+	pr_debug("%s\n", __func__);
 
 	/* Set RX DMA */
 	bfin_write_DMA1_NEXT_DESC_PTR(&(rx_list_head->desc_a));
@@ -1287,19 +1284,12 @@ static void bfin_mac_multicast_hash(stru
 {
 	u32 emac_hashhi, emac_hashlo;
 	struct netdev_hw_addr *ha;
-	char *addrs;
 	u32 crc;
 
 	emac_hashhi = emac_hashlo = 0;
 
 	netdev_for_each_mc_addr(ha, dev) {
-		addrs = ha->addr;
-
-		/* skip non-multicast addresses */
-		if (!(*addrs & 1))
-			continue;
-
-		crc = ether_crc(ETH_ALEN, addrs);
+		crc = ether_crc(ETH_ALEN, ha->addr);
 		crc >>= 26;
 
 		if (crc & 0x20)
@@ -1323,7 +1313,7 @@ static void bfin_mac_set_multicast_list(
 	u32 sysctl;
 
 	if (dev->flags & IFF_PROMISC) {
-		printk(KERN_INFO "%s: set to promisc mode\n", dev->name);
+		netdev_info(dev, "set promisc mode\n");
 		sysctl = bfin_read_EMAC_OPMODE();
 		sysctl |= PR;
 		bfin_write_EMAC_OPMODE(sysctl);
@@ -1393,7 +1383,7 @@ static int bfin_mac_open(struct net_devi
 	 * address using ifconfig eth0 hw ether xx:xx:xx:xx:xx:xx
 	 */
 	if (!is_valid_ether_addr(dev->dev_addr)) {
-		printk(KERN_WARNING DRV_NAME ": no valid ethernet hw addr\n");
+		netdev_warn(dev, "no valid ethernet hw addr\n");
 		return -EINVAL;
 	}
 
@@ -1527,6 +1517,9 @@ static int __devinit bfin_mac_probe(stru
 		goto out_err_mii_probe;
 	}
 
+	lp->vlan1_mask = ETH_P_8021Q | mii_bus_data->vlan1_mask;
+	lp->vlan2_mask = ETH_P_8021Q | mii_bus_data->vlan2_mask;
+
 	/* Fill in the fields of the device structure with ethernet values. */
 	ether_setup(ndev);
 
@@ -1558,7 +1551,7 @@ static int __devinit bfin_mac_probe(stru
 	bfin_mac_hwtstamp_init(ndev);
 
 	/* now, print out the card info, in a short format.. */
-	dev_info(&pdev->dev, "%s, Version %s\n", DRV_DESC, DRV_VERSION);
+	netdev_info(ndev, "%s, Version %s\n", DRV_DESC, DRV_VERSION);
 
 	return 0;
 
@@ -1650,7 +1643,7 @@ static int __devinit bfin_mii_bus_probe(
 	 * so set the GPIO pins to Ethernet mode
 	 */
 	pin_req = mii_bus_pd->mac_peripherals;
-	rc = peripheral_request_list(pin_req, DRV_NAME);
+	rc = peripheral_request_list(pin_req, KBUILD_MODNAME);
 	if (rc) {
 		dev_err(&pdev->dev, "Requesting peripherals failed!\n");
 		return rc;
@@ -1739,7 +1732,7 @@ static struct platform_driver bfin_mac_d
 	.resume = bfin_mac_resume,
 	.suspend = bfin_mac_suspend,
 	.driver = {
-		.name = DRV_NAME,
+		.name = KBUILD_MODNAME,
 		.owner	= THIS_MODULE,
 	},
 };
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/bfin_mac.h linux-libre-2.6.38-gnu1/drivers/net/bfin_mac.h
--- linux-libre-2.6.37-gnu1/drivers/net/bfin_mac.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/bfin_mac.h	2011-03-14 21:20:32.000000000 -0400
@@ -17,7 +17,14 @@
 #include <linux/etherdevice.h>
 #include <linux/bfin_mac.h>
 
+/*
+ * Disable hardware checksum for bug #5600 if writeback cache is
+ * enabled. Otherwize, corrupted RX packet will be sent up stack
+ * without error mark.
+ */
+#ifndef CONFIG_BFIN_EXTMEM_WRITEBACK
 #define BFIN_MAC_CSUM_OFFLOAD
+#endif
 
 #define TX_RECLAIM_JIFFIES (HZ / 5)
 
@@ -68,7 +75,6 @@ struct bfin_mac_local {
 	 */
 	struct net_device_stats stats;
 
-	unsigned char Mac[6];	/* MAC address of the board */
 	spinlock_t lock;
 
 	int wol;		/* Wake On Lan */
@@ -76,6 +82,9 @@ struct bfin_mac_local {
 	struct timer_list tx_reclaim_timer;
 	struct net_device *ndev;
 
+	/* Data for EMAC_VLAN1 regs */
+	u16 vlan1_mask, vlan2_mask;
+
 	/* MII and PHY stuffs */
 	int old_link;          /* used by bf537_adjust_link */
 	int old_speed;
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/bna/bfa_defs.h linux-libre-2.6.38-gnu1/drivers/net/bna/bfa_defs.h
--- linux-libre-2.6.37-gnu1/drivers/net/bna/bfa_defs.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/bna/bfa_defs.h	2011-03-14 21:20:32.000000000 -0400
@@ -112,16 +112,18 @@ struct bfa_ioc_pci_attr {
  * IOC states
  */
 enum bfa_ioc_state {
-	BFA_IOC_RESET		= 1,	/*!< IOC is in reset state */
-	BFA_IOC_SEMWAIT		= 2,	/*!< Waiting for IOC h/w semaphore */
-	BFA_IOC_HWINIT		= 3,	/*!< IOC h/w is being initialized */
-	BFA_IOC_GETATTR		= 4,	/*!< IOC is being configured */
-	BFA_IOC_OPERATIONAL	= 5,	/*!< IOC is operational */
-	BFA_IOC_INITFAIL	= 6,	/*!< IOC hardware failure */
-	BFA_IOC_HBFAIL		= 7,	/*!< IOC heart-beat failure */
-	BFA_IOC_DISABLING	= 8,	/*!< IOC is being disabled */
-	BFA_IOC_DISABLED	= 9,	/*!< IOC is disabled */
-	BFA_IOC_FWMISMATCH	= 10,	/*!< IOC f/w different from drivers */
+	BFA_IOC_UNINIT		= 1,	/*!< IOC is in uninit state */
+	BFA_IOC_RESET		= 2,	/*!< IOC is in reset state */
+	BFA_IOC_SEMWAIT		= 3,	/*!< Waiting for IOC h/w semaphore */
+	BFA_IOC_HWINIT		= 4,	/*!< IOC h/w is being initialized */
+	BFA_IOC_GETATTR		= 5,	/*!< IOC is being configured */
+	BFA_IOC_OPERATIONAL	= 6,	/*!< IOC is operational */
+	BFA_IOC_INITFAIL	= 7,	/*!< IOC hardware failure */
+	BFA_IOC_FAIL		= 8,	/*!< IOC heart-beat failure */
+	BFA_IOC_DISABLING	= 9,	/*!< IOC is being disabled */
+	BFA_IOC_DISABLED	= 10,	/*!< IOC is disabled */
+	BFA_IOC_FWMISMATCH	= 11,	/*!< IOC f/w different from drivers */
+	BFA_IOC_ENABLING	= 12,	/*!< IOC is being enabled */
 };
 
 /**
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/bna/bfa_defs_mfg_comm.h linux-libre-2.6.38-gnu1/drivers/net/bna/bfa_defs_mfg_comm.h
--- linux-libre-2.6.37-gnu1/drivers/net/bna/bfa_defs_mfg_comm.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/bna/bfa_defs_mfg_comm.h	2011-03-14 21:20:32.000000000 -0400
@@ -95,28 +95,6 @@ enum {
 	(type) == BFA_MFG_TYPE_CNA10P1 || \
 	bfa_mfg_is_mezz(type)))
 
-/**
- * Check if the card having old wwn/mac handling
- */
-#define bfa_mfg_is_old_wwn_mac_model(type) (( \
-	(type) == BFA_MFG_TYPE_FC8P2 || \
-	(type) == BFA_MFG_TYPE_FC8P1 || \
-	(type) == BFA_MFG_TYPE_FC4P2 || \
-	(type) == BFA_MFG_TYPE_FC4P1 || \
-	(type) == BFA_MFG_TYPE_CNA10P2 || \
-	(type) == BFA_MFG_TYPE_CNA10P1 || \
-	(type) == BFA_MFG_TYPE_JAYHAWK || \
-	(type) == BFA_MFG_TYPE_WANCHESE))
-
-#define bfa_mfg_increment_wwn_mac(m, i)				\
-do {								\
-	u32 t = ((m)[0] << 16) | ((m)[1] << 8) | (m)[2];	\
-	t += (i);						\
-	(m)[0] = (t >> 16) & 0xFF;				\
-	(m)[1] = (t >> 8) & 0xFF;				\
-	(m)[2] = t & 0xFF;					\
-} while (0)
-
 #define bfa_mfg_adapter_prop_init_flash(card_type, prop)	\
 do {								\
 	switch ((card_type)) {					\
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/bna/bfa_ioc.c linux-libre-2.6.38-gnu1/drivers/net/bna/bfa_ioc.c
--- linux-libre-2.6.37-gnu1/drivers/net/bna/bfa_ioc.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/bna/bfa_ioc.c	2011-03-14 21:20:32.000000000 -0400
@@ -26,25 +26,6 @@
  * IOC local definitions
  */
 
-#define bfa_ioc_timer_start(__ioc)					\
-	mod_timer(&(__ioc)->ioc_timer, jiffies +	\
-			msecs_to_jiffies(BFA_IOC_TOV))
-#define bfa_ioc_timer_stop(__ioc)   del_timer(&(__ioc)->ioc_timer)
-
-#define bfa_ioc_recovery_timer_start(__ioc)				\
-	mod_timer(&(__ioc)->ioc_timer, jiffies +	\
-			msecs_to_jiffies(BFA_IOC_TOV_RECOVER))
-
-#define bfa_sem_timer_start(__ioc)					\
-	mod_timer(&(__ioc)->sem_timer, jiffies +	\
-			msecs_to_jiffies(BFA_IOC_HWSEM_TOV))
-#define bfa_sem_timer_stop(__ioc)	del_timer(&(__ioc)->sem_timer)
-
-#define bfa_hb_timer_start(__ioc)					\
-	mod_timer(&(__ioc)->hb_timer, jiffies +		\
-			msecs_to_jiffies(BFA_IOC_HB_TOV))
-#define bfa_hb_timer_stop(__ioc)	del_timer(&(__ioc)->hb_timer)
-
 /**
  * Asic specific macros : see bfa_hw_cb.c and bfa_hw_ct.c for details.
  */
@@ -55,11 +36,16 @@
 			((__ioc)->ioc_hwif->ioc_firmware_unlock(__ioc))
 #define bfa_ioc_reg_init(__ioc) ((__ioc)->ioc_hwif->ioc_reg_init(__ioc))
 #define bfa_ioc_map_port(__ioc) ((__ioc)->ioc_hwif->ioc_map_port(__ioc))
-#define bfa_ioc_notify_hbfail(__ioc)			\
-			((__ioc)->ioc_hwif->ioc_notify_hbfail(__ioc))
-
-#define bfa_ioc_is_optrom(__ioc)	\
-	(bfa_cb_image_get_size(BFA_IOC_FWIMG_TYPE(__ioc)) < BFA_IOC_FWIMG_MINSZ)
+#define bfa_ioc_notify_fail(__ioc)			\
+			((__ioc)->ioc_hwif->ioc_notify_fail(__ioc))
+#define bfa_ioc_sync_join(__ioc)			\
+			((__ioc)->ioc_hwif->ioc_sync_join(__ioc))
+#define bfa_ioc_sync_leave(__ioc)			\
+			((__ioc)->ioc_hwif->ioc_sync_leave(__ioc))
+#define bfa_ioc_sync_ack(__ioc)				\
+			((__ioc)->ioc_hwif->ioc_sync_ack(__ioc))
+#define bfa_ioc_sync_complete(__ioc)			\
+			((__ioc)->ioc_hwif->ioc_sync_complete(__ioc))
 
 #define bfa_ioc_mbox_cmd_pending(__ioc)		\
 			(!list_empty(&((__ioc)->mbox_mod.cmd_q)) || \
@@ -85,6 +71,12 @@ static void bfa_ioc_recover(struct bfa_i
 static void bfa_ioc_check_attr_wwns(struct bfa_ioc *ioc);
 static void bfa_ioc_disable_comp(struct bfa_ioc *ioc);
 static void bfa_ioc_lpu_stop(struct bfa_ioc *ioc);
+static void bfa_ioc_fail_notify(struct bfa_ioc *ioc);
+static void bfa_ioc_pf_enabled(struct bfa_ioc *ioc);
+static void bfa_ioc_pf_disabled(struct bfa_ioc *ioc);
+static void bfa_ioc_pf_initfailed(struct bfa_ioc *ioc);
+static void bfa_ioc_pf_failed(struct bfa_ioc *ioc);
+static void bfa_ioc_pf_fwmismatch(struct bfa_ioc *ioc);
 static void bfa_ioc_boot(struct bfa_ioc *ioc, u32 boot_type,
 			 u32 boot_param);
 static u32 bfa_ioc_smem_pgnum(struct bfa_ioc *ioc, u32 fmaddr);
@@ -101,72 +93,173 @@ static void bfa_ioc_get_adapter_manufact
 						char *manufacturer);
 static void bfa_ioc_get_adapter_model(struct bfa_ioc *ioc, char *model);
 static u64 bfa_ioc_get_pwwn(struct bfa_ioc *ioc);
-static mac_t bfa_ioc_get_mfg_mac(struct bfa_ioc *ioc);
 
 /**
- * IOC state machine events
+ * IOC state machine definitions/declarations
  */
 enum ioc_event {
-	IOC_E_ENABLE		= 1,	/*!< IOC enable request		*/
-	IOC_E_DISABLE		= 2,	/*!< IOC disable request	*/
-	IOC_E_TIMEOUT		= 3,	/*!< f/w response timeout	*/
-	IOC_E_FWREADY		= 4,	/*!< f/w initialization done	*/
-	IOC_E_FWRSP_GETATTR	= 5,	/*!< IOC get attribute response	*/
-	IOC_E_FWRSP_ENABLE	= 6,	/*!< enable f/w response	*/
-	IOC_E_FWRSP_DISABLE	= 7,	/*!< disable f/w response	*/
-	IOC_E_HBFAIL		= 8,	/*!< heartbeat failure		*/
-	IOC_E_HWERROR		= 9,	/*!< hardware error interrupt	*/
-	IOC_E_SEMLOCKED		= 10,	/*!< h/w semaphore is locked	*/
-	IOC_E_DETACH		= 11,	/*!< driver detach cleanup	*/
+	IOC_E_RESET		= 1,	/*!< IOC reset request		*/
+	IOC_E_ENABLE		= 2,	/*!< IOC enable request		*/
+	IOC_E_DISABLE		= 3,	/*!< IOC disable request	*/
+	IOC_E_DETACH		= 4,	/*!< driver detach cleanup	*/
+	IOC_E_ENABLED		= 5,	/*!< f/w enabled		*/
+	IOC_E_FWRSP_GETATTR	= 6,	/*!< IOC get attribute response	*/
+	IOC_E_DISABLED		= 7,	/*!< f/w disabled		*/
+	IOC_E_INITFAILED	= 8,	/*!< failure notice by iocpf sm	*/
+	IOC_E_PFAILED		= 9,	/*!< failure notice by iocpf sm	*/
+	IOC_E_HBFAIL		= 10,	/*!< heartbeat failure		*/
+	IOC_E_HWERROR		= 11,	/*!< hardware error interrupt	*/
+	IOC_E_TIMEOUT		= 12,	/*!< timeout			*/
 };
 
+bfa_fsm_state_decl(bfa_ioc, uninit, struct bfa_ioc, enum ioc_event);
 bfa_fsm_state_decl(bfa_ioc, reset, struct bfa_ioc, enum ioc_event);
-bfa_fsm_state_decl(bfa_ioc, fwcheck, struct bfa_ioc, enum ioc_event);
-bfa_fsm_state_decl(bfa_ioc, mismatch, struct bfa_ioc, enum ioc_event);
-bfa_fsm_state_decl(bfa_ioc, semwait, struct bfa_ioc, enum ioc_event);
-bfa_fsm_state_decl(bfa_ioc, hwinit, struct bfa_ioc, enum ioc_event);
 bfa_fsm_state_decl(bfa_ioc, enabling, struct bfa_ioc, enum ioc_event);
 bfa_fsm_state_decl(bfa_ioc, getattr, struct bfa_ioc, enum ioc_event);
 bfa_fsm_state_decl(bfa_ioc, op, struct bfa_ioc, enum ioc_event);
-bfa_fsm_state_decl(bfa_ioc, initfail, struct bfa_ioc, enum ioc_event);
-bfa_fsm_state_decl(bfa_ioc, hbfail, struct bfa_ioc, enum ioc_event);
+bfa_fsm_state_decl(bfa_ioc, fail_retry, struct bfa_ioc, enum ioc_event);
+bfa_fsm_state_decl(bfa_ioc, fail, struct bfa_ioc, enum ioc_event);
 bfa_fsm_state_decl(bfa_ioc, disabling, struct bfa_ioc, enum ioc_event);
 bfa_fsm_state_decl(bfa_ioc, disabled, struct bfa_ioc, enum ioc_event);
 
 static struct bfa_sm_table ioc_sm_table[] = {
+	{BFA_SM(bfa_ioc_sm_uninit), BFA_IOC_UNINIT},
 	{BFA_SM(bfa_ioc_sm_reset), BFA_IOC_RESET},
-	{BFA_SM(bfa_ioc_sm_fwcheck), BFA_IOC_FWMISMATCH},
-	{BFA_SM(bfa_ioc_sm_mismatch), BFA_IOC_FWMISMATCH},
-	{BFA_SM(bfa_ioc_sm_semwait), BFA_IOC_SEMWAIT},
-	{BFA_SM(bfa_ioc_sm_hwinit), BFA_IOC_HWINIT},
-	{BFA_SM(bfa_ioc_sm_enabling), BFA_IOC_HWINIT},
+	{BFA_SM(bfa_ioc_sm_enabling), BFA_IOC_ENABLING},
 	{BFA_SM(bfa_ioc_sm_getattr), BFA_IOC_GETATTR},
 	{BFA_SM(bfa_ioc_sm_op), BFA_IOC_OPERATIONAL},
-	{BFA_SM(bfa_ioc_sm_initfail), BFA_IOC_INITFAIL},
-	{BFA_SM(bfa_ioc_sm_hbfail), BFA_IOC_HBFAIL},
+	{BFA_SM(bfa_ioc_sm_fail_retry), BFA_IOC_INITFAIL},
+	{BFA_SM(bfa_ioc_sm_fail), BFA_IOC_FAIL},
 	{BFA_SM(bfa_ioc_sm_disabling), BFA_IOC_DISABLING},
 	{BFA_SM(bfa_ioc_sm_disabled), BFA_IOC_DISABLED},
 };
 
 /**
+ * IOCPF state machine definitions/declarations
+ */
+
+/*
+ * Forward declareations for iocpf state machine
+ */
+static void bfa_iocpf_enable(struct bfa_ioc *ioc);
+static void bfa_iocpf_disable(struct bfa_ioc *ioc);
+static void bfa_iocpf_fail(struct bfa_ioc *ioc);
+static void bfa_iocpf_initfail(struct bfa_ioc *ioc);
+static void bfa_iocpf_getattrfail(struct bfa_ioc *ioc);
+static void bfa_iocpf_stop(struct bfa_ioc *ioc);
+
+/**
+ * IOCPF state machine events
+ */
+enum iocpf_event {
+	IOCPF_E_ENABLE		= 1,	/*!< IOCPF enable request	*/
+	IOCPF_E_DISABLE		= 2,	/*!< IOCPF disable request	*/
+	IOCPF_E_STOP		= 3,	/*!< stop on driver detach	*/
+	IOCPF_E_FWREADY	 	= 4,	/*!< f/w initialization done	*/
+	IOCPF_E_FWRSP_ENABLE	= 5,	/*!< enable f/w response	*/
+	IOCPF_E_FWRSP_DISABLE	= 6,	/*!< disable f/w response	*/
+	IOCPF_E_FAIL		= 7,	/*!< failure notice by ioc sm	*/
+	IOCPF_E_INITFAIL	= 8,	/*!< init fail notice by ioc sm	*/
+	IOCPF_E_GETATTRFAIL	= 9,	/*!< init fail notice by ioc sm	*/
+	IOCPF_E_SEMLOCKED	= 10,   /*!< h/w semaphore is locked	*/
+	IOCPF_E_TIMEOUT		= 11,   /*!< f/w response timeout	*/
+};
+
+/**
+ * IOCPF states
+ */
+enum bfa_iocpf_state {
+	BFA_IOCPF_RESET		= 1,	/*!< IOC is in reset state */
+	BFA_IOCPF_SEMWAIT	= 2,	/*!< Waiting for IOC h/w semaphore */
+	BFA_IOCPF_HWINIT	= 3,	/*!< IOC h/w is being initialized */
+	BFA_IOCPF_READY		= 4,	/*!< IOCPF is initialized */
+	BFA_IOCPF_INITFAIL	= 5,	/*!< IOCPF failed */
+	BFA_IOCPF_FAIL		= 6,	/*!< IOCPF failed */
+	BFA_IOCPF_DISABLING	= 7,	/*!< IOCPF is being disabled */
+	BFA_IOCPF_DISABLED	= 8,	/*!< IOCPF is disabled */
+	BFA_IOCPF_FWMISMATCH	= 9,	/*!< IOC f/w different from drivers */
+};
+
+bfa_fsm_state_decl(bfa_iocpf, reset, struct bfa_iocpf, enum iocpf_event);
+bfa_fsm_state_decl(bfa_iocpf, fwcheck, struct bfa_iocpf, enum iocpf_event);
+bfa_fsm_state_decl(bfa_iocpf, mismatch, struct bfa_iocpf, enum iocpf_event);
+bfa_fsm_state_decl(bfa_iocpf, semwait, struct bfa_iocpf, enum iocpf_event);
+bfa_fsm_state_decl(bfa_iocpf, hwinit, struct bfa_iocpf, enum iocpf_event);
+bfa_fsm_state_decl(bfa_iocpf, enabling, struct bfa_iocpf, enum iocpf_event);
+bfa_fsm_state_decl(bfa_iocpf, ready, struct bfa_iocpf, enum iocpf_event);
+bfa_fsm_state_decl(bfa_iocpf, initfail_sync, struct bfa_iocpf,
+						enum iocpf_event);
+bfa_fsm_state_decl(bfa_iocpf, initfail, struct bfa_iocpf, enum iocpf_event);
+bfa_fsm_state_decl(bfa_iocpf, fail_sync, struct bfa_iocpf, enum iocpf_event);
+bfa_fsm_state_decl(bfa_iocpf, fail, struct bfa_iocpf, enum iocpf_event);
+bfa_fsm_state_decl(bfa_iocpf, disabling, struct bfa_iocpf, enum iocpf_event);
+bfa_fsm_state_decl(bfa_iocpf, disabling_sync, struct bfa_iocpf,
+						enum iocpf_event);
+bfa_fsm_state_decl(bfa_iocpf, disabled, struct bfa_iocpf, enum iocpf_event);
+
+static struct bfa_sm_table iocpf_sm_table[] = {
+	{BFA_SM(bfa_iocpf_sm_reset), BFA_IOCPF_RESET},
+	{BFA_SM(bfa_iocpf_sm_fwcheck), BFA_IOCPF_FWMISMATCH},
+	{BFA_SM(bfa_iocpf_sm_mismatch), BFA_IOCPF_FWMISMATCH},
+	{BFA_SM(bfa_iocpf_sm_semwait), BFA_IOCPF_SEMWAIT},
+	{BFA_SM(bfa_iocpf_sm_hwinit), BFA_IOCPF_HWINIT},
+	{BFA_SM(bfa_iocpf_sm_enabling), BFA_IOCPF_HWINIT},
+	{BFA_SM(bfa_iocpf_sm_ready), BFA_IOCPF_READY},
+	{BFA_SM(bfa_iocpf_sm_initfail_sync), BFA_IOCPF_INITFAIL},
+	{BFA_SM(bfa_iocpf_sm_initfail), BFA_IOCPF_INITFAIL},
+	{BFA_SM(bfa_iocpf_sm_fail_sync), BFA_IOCPF_FAIL},
+	{BFA_SM(bfa_iocpf_sm_fail), BFA_IOCPF_FAIL},
+	{BFA_SM(bfa_iocpf_sm_disabling), BFA_IOCPF_DISABLING},
+	{BFA_SM(bfa_iocpf_sm_disabling_sync), BFA_IOCPF_DISABLING},
+	{BFA_SM(bfa_iocpf_sm_disabled), BFA_IOCPF_DISABLED},
+};
+
+/**
+ * IOC State Machine
+ */
+
+/**
+ * Beginning state. IOC uninit state.
+ */
+static void
+bfa_ioc_sm_uninit_entry(struct bfa_ioc *ioc)
+{
+}
+
+/**
+ * IOC is in uninit state.
+ */
+static void
+bfa_ioc_sm_uninit(struct bfa_ioc *ioc, enum ioc_event event)
+{
+	switch (event) {
+	case IOC_E_RESET:
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_reset);
+		break;
+
+	default:
+		bfa_sm_fault(ioc, event);
+	}
+}
+
+/**
  * Reset entry actions -- initialize state machine
  */
 static void
 bfa_ioc_sm_reset_entry(struct bfa_ioc *ioc)
 {
-	ioc->retry_count = 0;
-	ioc->auto_recover = bfa_nw_auto_recover;
+	bfa_fsm_set_state(&ioc->iocpf, bfa_iocpf_sm_reset);
 }
 
 /**
- * Beginning state. IOC is in reset state.
+ * IOC is in reset state.
  */
 static void
 bfa_ioc_sm_reset(struct bfa_ioc *ioc, enum ioc_event event)
 {
 	switch (event) {
 	case IOC_E_ENABLE:
-		bfa_fsm_set_state(ioc, bfa_ioc_sm_fwcheck);
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_enabling);
 		break;
 
 	case IOC_E_DISABLE:
@@ -174,6 +267,7 @@ bfa_ioc_sm_reset(struct bfa_ioc *ioc, en
 		break;
 
 	case IOC_E_DETACH:
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);
 		break;
 
 	default:
@@ -181,42 +275,43 @@ bfa_ioc_sm_reset(struct bfa_ioc *ioc, en
 	}
 }
 
-/**
- * Semaphore should be acquired for version check.
- */
 static void
-bfa_ioc_sm_fwcheck_entry(struct bfa_ioc *ioc)
+bfa_ioc_sm_enabling_entry(struct bfa_ioc *ioc)
 {
-	bfa_ioc_hw_sem_get(ioc);
+	bfa_iocpf_enable(ioc);
 }
 
 /**
- * Awaiting h/w semaphore to continue with version check.
+ * Host IOC function is being enabled, awaiting response from firmware.
+ * Semaphore is acquired.
  */
 static void
-bfa_ioc_sm_fwcheck(struct bfa_ioc *ioc, enum ioc_event event)
+bfa_ioc_sm_enabling(struct bfa_ioc *ioc, enum ioc_event event)
 {
 	switch (event) {
-	case IOC_E_SEMLOCKED:
-		if (bfa_ioc_firmware_lock(ioc)) {
-			ioc->retry_count = 0;
-			bfa_fsm_set_state(ioc, bfa_ioc_sm_hwinit);
-		} else {
-			bfa_nw_ioc_hw_sem_release(ioc);
-			bfa_fsm_set_state(ioc, bfa_ioc_sm_mismatch);
-		}
+	case IOC_E_ENABLED:
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_getattr);
+		break;
+
+	case IOC_E_PFAILED:
+		/* !!! fall through !!! */
+	case IOC_E_HWERROR:
+		ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_fail_retry);
+		if (event != IOC_E_PFAILED)
+			bfa_iocpf_initfail(ioc);
 		break;
 
 	case IOC_E_DISABLE:
-		bfa_ioc_disable_comp(ioc);
-		/* fall through */
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);
+		break;
 
 	case IOC_E_DETACH:
-		bfa_ioc_hw_sem_get_cancel(ioc);
-		bfa_fsm_set_state(ioc, bfa_ioc_sm_reset);
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);
+		bfa_iocpf_stop(ioc);
 		break;
 
-	case IOC_E_FWREADY:
+	case IOC_E_ENABLE:
 		break;
 
 	default:
@@ -225,41 +320,85 @@ bfa_ioc_sm_fwcheck(struct bfa_ioc *ioc,
 }
 
 /**
- * Notify enable completion callback and generate mismatch AEN.
+ * Semaphore should be acquired for version check.
  */
 static void
-bfa_ioc_sm_mismatch_entry(struct bfa_ioc *ioc)
+bfa_ioc_sm_getattr_entry(struct bfa_ioc *ioc)
 {
-	/**
-	 * Provide enable completion callback and AEN notification only once.
-	 */
-	if (ioc->retry_count == 0)
-		ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
-	ioc->retry_count++;
-	bfa_ioc_timer_start(ioc);
+	mod_timer(&ioc->ioc_timer, jiffies +
+		msecs_to_jiffies(BFA_IOC_TOV));
+	bfa_ioc_send_getattr(ioc);
 }
 
 /**
- * Awaiting firmware version match.
+ * IOC configuration in progress. Timer is active.
  */
 static void
-bfa_ioc_sm_mismatch(struct bfa_ioc *ioc, enum ioc_event event)
+bfa_ioc_sm_getattr(struct bfa_ioc *ioc, enum ioc_event event)
 {
 	switch (event) {
+	case IOC_E_FWRSP_GETATTR:
+		del_timer(&ioc->ioc_timer);
+		bfa_ioc_check_attr_wwns(ioc);
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_op);
+		break;
+
+	case IOC_E_PFAILED:
+	case IOC_E_HWERROR:
+		del_timer(&ioc->ioc_timer);
+		/* fall through */
 	case IOC_E_TIMEOUT:
-		bfa_fsm_set_state(ioc, bfa_ioc_sm_fwcheck);
+		ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_fail_retry);
+		if (event != IOC_E_PFAILED)
+			bfa_iocpf_getattrfail(ioc);
 		break;
 
 	case IOC_E_DISABLE:
-		bfa_ioc_disable_comp(ioc);
-		/* fall through */
+		del_timer(&ioc->ioc_timer);
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);
+		break;
 
-	case IOC_E_DETACH:
-		bfa_ioc_timer_stop(ioc);
-		bfa_fsm_set_state(ioc, bfa_ioc_sm_reset);
+	case IOC_E_ENABLE:
 		break;
 
-	case IOC_E_FWREADY:
+	default:
+		bfa_sm_fault(ioc, event);
+	}
+}
+
+static void
+bfa_ioc_sm_op_entry(struct bfa_ioc *ioc)
+{
+	ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_OK);
+	bfa_ioc_hb_monitor(ioc);
+}
+
+static void
+bfa_ioc_sm_op(struct bfa_ioc *ioc, enum ioc_event event)
+{
+	switch (event) {
+	case IOC_E_ENABLE:
+		break;
+
+	case IOC_E_DISABLE:
+		bfa_ioc_hb_stop(ioc);
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);
+		break;
+
+	case IOC_E_PFAILED:
+	case IOC_E_HWERROR:
+		bfa_ioc_hb_stop(ioc);
+		/* !!! fall through !!! */
+	case IOC_E_HBFAIL:
+		bfa_ioc_fail_notify(ioc);
+		if (ioc->iocpf.auto_recover)
+			bfa_fsm_set_state(ioc, bfa_ioc_sm_fail_retry);
+		else
+			bfa_fsm_set_state(ioc, bfa_ioc_sm_fail);
+
+		if (event != IOC_E_PFAILED)
+			bfa_iocpf_fail(ioc);
 		break;
 
 	default:
@@ -267,30 +406,61 @@ bfa_ioc_sm_mismatch(struct bfa_ioc *ioc,
 	}
 }
 
+static void
+bfa_ioc_sm_disabling_entry(struct bfa_ioc *ioc)
+{
+	bfa_iocpf_disable(ioc);
+}
+
 /**
- * Request for semaphore.
+ * IOC is being desabled
  */
 static void
-bfa_ioc_sm_semwait_entry(struct bfa_ioc *ioc)
+bfa_ioc_sm_disabling(struct bfa_ioc *ioc, enum ioc_event event)
 {
-	bfa_ioc_hw_sem_get(ioc);
+	switch (event) {
+	case IOC_E_DISABLED:
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled);
+		break;
+
+	case IOC_E_HWERROR:
+		/*
+		 * No state change.  Will move to disabled state
+		 * after iocpf sm completes failure processing and
+		 * moves to disabled state.
+		 */
+		bfa_iocpf_fail(ioc);
+		break;
+
+	default:
+		bfa_sm_fault(ioc, event);
+	}
 }
 
 /**
- * Awaiting semaphore for h/w initialzation.
+ * IOC desable completion entry.
  */
 static void
-bfa_ioc_sm_semwait(struct bfa_ioc *ioc, enum ioc_event event)
+bfa_ioc_sm_disabled_entry(struct bfa_ioc *ioc)
+{
+	bfa_ioc_disable_comp(ioc);
+}
+
+static void
+bfa_ioc_sm_disabled(struct bfa_ioc *ioc, enum ioc_event event)
 {
 	switch (event) {
-	case IOC_E_SEMLOCKED:
-		ioc->retry_count = 0;
-		bfa_fsm_set_state(ioc, bfa_ioc_sm_hwinit);
+	case IOC_E_ENABLE:
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_enabling);
 		break;
 
 	case IOC_E_DISABLE:
-		bfa_ioc_hw_sem_get_cancel(ioc);
-		bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled);
+		ioc->cbfn->disable_cbfn(ioc->bfa);
+		break;
+
+	case IOC_E_DETACH:
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);
+		bfa_iocpf_stop(ioc);
 		break;
 
 	default:
@@ -299,46 +469,45 @@ bfa_ioc_sm_semwait(struct bfa_ioc *ioc,
 }
 
 static void
-bfa_ioc_sm_hwinit_entry(struct bfa_ioc *ioc)
+bfa_ioc_sm_fail_retry_entry(struct bfa_ioc *ioc)
 {
-	bfa_ioc_timer_start(ioc);
-	bfa_ioc_reset(ioc, false);
 }
 
 /**
- * @brief
- * Hardware is being initialized. Interrupts are enabled.
- * Holding hardware semaphore lock.
+ * Hardware initialization retry.
  */
 static void
-bfa_ioc_sm_hwinit(struct bfa_ioc *ioc, enum ioc_event event)
+bfa_ioc_sm_fail_retry(struct bfa_ioc *ioc, enum ioc_event event)
 {
 	switch (event) {
-	case IOC_E_FWREADY:
-		bfa_ioc_timer_stop(ioc);
-		bfa_fsm_set_state(ioc, bfa_ioc_sm_enabling);
+	case IOC_E_ENABLED:
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_getattr);
 		break;
 
+	case IOC_E_PFAILED:
 	case IOC_E_HWERROR:
-		bfa_ioc_timer_stop(ioc);
-		/* fall through */
+		/**
+		 * Initialization retry failed.
+		 */
+		ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
+		if (event != IOC_E_PFAILED)
+			bfa_iocpf_initfail(ioc);
+		break;
 
-	case IOC_E_TIMEOUT:
-		ioc->retry_count++;
-		if (ioc->retry_count < BFA_IOC_HWINIT_MAX) {
-			bfa_ioc_timer_start(ioc);
-			bfa_ioc_reset(ioc, true);
-			break;
-		}
+	case IOC_E_INITFAILED:
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_fail);
+		break;
 
-		bfa_nw_ioc_hw_sem_release(ioc);
-		bfa_fsm_set_state(ioc, bfa_ioc_sm_initfail);
+	case IOC_E_ENABLE:
 		break;
 
 	case IOC_E_DISABLE:
-		bfa_nw_ioc_hw_sem_release(ioc);
-		bfa_ioc_timer_stop(ioc);
-		bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled);
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);
+		break;
+
+	case IOC_E_DETACH:
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);
+		bfa_iocpf_stop(ioc);
 		break;
 
 	default:
@@ -347,51 +516,248 @@ bfa_ioc_sm_hwinit(struct bfa_ioc *ioc, e
 }
 
 static void
-bfa_ioc_sm_enabling_entry(struct bfa_ioc *ioc)
+bfa_ioc_sm_fail_entry(struct bfa_ioc *ioc)
 {
-	bfa_ioc_timer_start(ioc);
-	bfa_ioc_send_enable(ioc);
 }
 
 /**
- * Host IOC function is being enabled, awaiting response from firmware.
- * Semaphore is acquired.
+ * IOC failure.
  */
 static void
-bfa_ioc_sm_enabling(struct bfa_ioc *ioc, enum ioc_event event)
+bfa_ioc_sm_fail(struct bfa_ioc *ioc, enum ioc_event event)
 {
 	switch (event) {
-	case IOC_E_FWRSP_ENABLE:
-		bfa_ioc_timer_stop(ioc);
-		bfa_nw_ioc_hw_sem_release(ioc);
-		bfa_fsm_set_state(ioc, bfa_ioc_sm_getattr);
+	case IOC_E_ENABLE:
+		ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
+		break;
+
+	case IOC_E_DISABLE:
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);
+		break;
+
+	case IOC_E_DETACH:
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);
+		bfa_iocpf_stop(ioc);
 		break;
 
 	case IOC_E_HWERROR:
-		bfa_ioc_timer_stop(ioc);
-		/* fall through */
+		/* HB failure notification, ignore. */
+		break;
 
-	case IOC_E_TIMEOUT:
-		ioc->retry_count++;
-		if (ioc->retry_count < BFA_IOC_HWINIT_MAX) {
-			writel(BFI_IOC_UNINIT,
-				      ioc->ioc_regs.ioc_fwstate);
-			bfa_fsm_set_state(ioc, bfa_ioc_sm_hwinit);
-			break;
+	default:
+		bfa_sm_fault(ioc, event);
+	}
+}
+
+/**
+ * IOCPF State Machine
+ */
+
+/**
+ * Reset entry actions -- initialize state machine
+ */
+static void
+bfa_iocpf_sm_reset_entry(struct bfa_iocpf *iocpf)
+{
+	iocpf->retry_count = 0;
+	iocpf->auto_recover = bfa_nw_auto_recover;
+}
+
+/**
+ * Beginning state. IOC is in reset state.
+ */
+static void
+bfa_iocpf_sm_reset(struct bfa_iocpf *iocpf, enum iocpf_event event)
+{
+	switch (event) {
+	case IOCPF_E_ENABLE:
+		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fwcheck);
+		break;
+
+	case IOCPF_E_STOP:
+		break;
+
+	default:
+		bfa_sm_fault(iocpf->ioc, event);
+	}
+}
+
+/**
+ * Semaphore should be acquired for version check.
+ */
+static void
+bfa_iocpf_sm_fwcheck_entry(struct bfa_iocpf *iocpf)
+{
+	bfa_ioc_hw_sem_get(iocpf->ioc);
+}
+
+/**
+ * Awaiting h/w semaphore to continue with version check.
+ */
+static void
+bfa_iocpf_sm_fwcheck(struct bfa_iocpf *iocpf, enum iocpf_event event)
+{
+	struct bfa_ioc *ioc = iocpf->ioc;
+
+	switch (event) {
+	case IOCPF_E_SEMLOCKED:
+		if (bfa_ioc_firmware_lock(ioc)) {
+			if (bfa_ioc_sync_complete(ioc)) {
+				iocpf->retry_count = 0;
+				bfa_ioc_sync_join(ioc);
+				bfa_fsm_set_state(iocpf, bfa_iocpf_sm_hwinit);
+			} else {
+				bfa_ioc_firmware_unlock(ioc);
+				bfa_nw_ioc_hw_sem_release(ioc);
+				mod_timer(&ioc->sem_timer, jiffies +
+					msecs_to_jiffies(BFA_IOC_HWSEM_TOV));
+			}
+		} else {
+			bfa_nw_ioc_hw_sem_release(ioc);
+			bfa_fsm_set_state(iocpf, bfa_iocpf_sm_mismatch);
 		}
+		break;
 
-		bfa_nw_ioc_hw_sem_release(ioc);
-		bfa_fsm_set_state(ioc, bfa_ioc_sm_initfail);
+	case IOCPF_E_DISABLE:
+		bfa_ioc_hw_sem_get_cancel(ioc);
+		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);
+		bfa_ioc_pf_disabled(ioc);
 		break;
 
-	case IOC_E_DISABLE:
-		bfa_ioc_timer_stop(ioc);
+	case IOCPF_E_STOP:
+		bfa_ioc_hw_sem_get_cancel(ioc);
+		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);
+		break;
+
+	default:
+		bfa_sm_fault(ioc, event);
+	}
+}
+
+/**
+ * Notify enable completion callback
+ */
+static void
+bfa_iocpf_sm_mismatch_entry(struct bfa_iocpf *iocpf)
+{
+	/* Call only the first time sm enters fwmismatch state. */
+	if (iocpf->retry_count == 0)
+		bfa_ioc_pf_fwmismatch(iocpf->ioc);
+
+	iocpf->retry_count++;
+	mod_timer(&(iocpf->ioc)->iocpf_timer, jiffies +
+		msecs_to_jiffies(BFA_IOC_TOV));
+}
+
+/**
+ * Awaiting firmware version match.
+ */
+static void
+bfa_iocpf_sm_mismatch(struct bfa_iocpf *iocpf, enum iocpf_event event)
+{
+	struct bfa_ioc *ioc = iocpf->ioc;
+
+	switch (event) {
+	case IOCPF_E_TIMEOUT:
+		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fwcheck);
+		break;
+
+	case IOCPF_E_DISABLE:
+		del_timer(&ioc->iocpf_timer);
+		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);
+		bfa_ioc_pf_disabled(ioc);
+		break;
+
+	case IOCPF_E_STOP:
+		del_timer(&ioc->iocpf_timer);
+		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);
+		break;
+
+	default:
+		bfa_sm_fault(ioc, event);
+	}
+}
+
+/**
+ * Request for semaphore.
+ */
+static void
+bfa_iocpf_sm_semwait_entry(struct bfa_iocpf *iocpf)
+{
+	bfa_ioc_hw_sem_get(iocpf->ioc);
+}
+
+/**
+ * Awaiting semaphore for h/w initialzation.
+ */
+static void
+bfa_iocpf_sm_semwait(struct bfa_iocpf *iocpf, enum iocpf_event event)
+{
+	struct bfa_ioc *ioc = iocpf->ioc;
+
+	switch (event) {
+	case IOCPF_E_SEMLOCKED:
+		if (bfa_ioc_sync_complete(ioc)) {
+			bfa_ioc_sync_join(ioc);
+			bfa_fsm_set_state(iocpf, bfa_iocpf_sm_hwinit);
+		} else {
+			bfa_nw_ioc_hw_sem_release(ioc);
+			mod_timer(&ioc->sem_timer, jiffies +
+				msecs_to_jiffies(BFA_IOC_HWSEM_TOV));
+		}
+		break;
+
+	case IOCPF_E_DISABLE:
+		bfa_ioc_hw_sem_get_cancel(ioc);
+		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling_sync);
+		break;
+
+	default:
+		bfa_sm_fault(ioc, event);
+	}
+}
+
+static void
+bfa_iocpf_sm_hwinit_entry(struct bfa_iocpf *iocpf)
+{
+	mod_timer(&(iocpf->ioc)->iocpf_timer, jiffies +
+		msecs_to_jiffies(BFA_IOC_TOV));
+	bfa_ioc_reset(iocpf->ioc, 0);
+}
+
+/**
+ * Hardware is being initialized. Interrupts are enabled.
+ * Holding hardware semaphore lock.
+ */
+static void
+bfa_iocpf_sm_hwinit(struct bfa_iocpf *iocpf, enum iocpf_event event)
+{
+	struct bfa_ioc *ioc = iocpf->ioc;
+
+	switch (event) {
+	case IOCPF_E_FWREADY:
+		del_timer(&ioc->iocpf_timer);
+		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_enabling);
+		break;
+
+	case IOCPF_E_INITFAIL:
+		del_timer(&ioc->iocpf_timer);
+		/*
+		 * !!! fall through !!!
+		 */
+
+	case IOCPF_E_TIMEOUT:
 		bfa_nw_ioc_hw_sem_release(ioc);
-		bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled);
+		if (event == IOCPF_E_TIMEOUT)
+			bfa_ioc_pf_failed(ioc);
+		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail_sync);
 		break;
 
-	case IOC_E_FWREADY:
-		bfa_ioc_send_enable(ioc);
+	case IOCPF_E_DISABLE:
+		del_timer(&ioc->iocpf_timer);
+		bfa_ioc_sync_leave(ioc);
+		bfa_nw_ioc_hw_sem_release(ioc);
+		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled);
 		break;
 
 	default:
@@ -400,37 +766,49 @@ bfa_ioc_sm_enabling(struct bfa_ioc *ioc,
 }
 
 static void
-bfa_ioc_sm_getattr_entry(struct bfa_ioc *ioc)
+bfa_iocpf_sm_enabling_entry(struct bfa_iocpf *iocpf)
 {
-	bfa_ioc_timer_start(ioc);
-	bfa_ioc_send_getattr(ioc);
+	mod_timer(&(iocpf->ioc)->iocpf_timer, jiffies +
+		msecs_to_jiffies(BFA_IOC_TOV));
+	bfa_ioc_send_enable(iocpf->ioc);
 }
 
 /**
- * @brief
- * IOC configuration in progress. Timer is active.
+ * Host IOC function is being enabled, awaiting response from firmware.
+ * Semaphore is acquired.
  */
 static void
-bfa_ioc_sm_getattr(struct bfa_ioc *ioc, enum ioc_event event)
+bfa_iocpf_sm_enabling(struct bfa_iocpf *iocpf, enum iocpf_event event)
 {
+	struct bfa_ioc *ioc = iocpf->ioc;
+
 	switch (event) {
-	case IOC_E_FWRSP_GETATTR:
-		bfa_ioc_timer_stop(ioc);
-		bfa_ioc_check_attr_wwns(ioc);
-		bfa_fsm_set_state(ioc, bfa_ioc_sm_op);
+	case IOCPF_E_FWRSP_ENABLE:
+		del_timer(&ioc->iocpf_timer);
+		bfa_nw_ioc_hw_sem_release(ioc);
+		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_ready);
 		break;
 
-	case IOC_E_HWERROR:
-		bfa_ioc_timer_stop(ioc);
-		/* fall through */
+	case IOCPF_E_INITFAIL:
+		del_timer(&ioc->iocpf_timer);
+		/*
+		 * !!! fall through !!!
+		 */
+	case IOCPF_E_TIMEOUT:
+		bfa_nw_ioc_hw_sem_release(ioc);
+		if (event == IOCPF_E_TIMEOUT)
+			bfa_ioc_pf_failed(ioc);
+		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail_sync);
+		break;
 
-	case IOC_E_TIMEOUT:
-		bfa_fsm_set_state(ioc, bfa_ioc_sm_initfail);
+	case IOCPF_E_DISABLE:
+		del_timer(&ioc->iocpf_timer);
+		bfa_nw_ioc_hw_sem_release(ioc);
+		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling);
 		break;
 
-	case IOC_E_DISABLE:
-		bfa_ioc_timer_stop(ioc);
-		bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled);
+	case IOCPF_E_FWREADY:
+		bfa_ioc_send_enable(ioc);
 		break;
 
 	default:
@@ -438,36 +816,42 @@ bfa_ioc_sm_getattr(struct bfa_ioc *ioc,
 	}
 }
 
+static bool
+bfa_nw_ioc_is_operational(struct bfa_ioc *ioc)
+{
+	return bfa_fsm_cmp_state(ioc, bfa_ioc_sm_op);
+}
+
 static void
-bfa_ioc_sm_op_entry(struct bfa_ioc *ioc)
+bfa_iocpf_sm_ready_entry(struct bfa_iocpf *iocpf)
 {
-	ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_OK);
-	bfa_ioc_hb_monitor(ioc);
+	bfa_ioc_pf_enabled(iocpf->ioc);
 }
 
 static void
-bfa_ioc_sm_op(struct bfa_ioc *ioc, enum ioc_event event)
+bfa_iocpf_sm_ready(struct bfa_iocpf *iocpf, enum iocpf_event event)
 {
+	struct bfa_ioc *ioc = iocpf->ioc;
+
 	switch (event) {
-	case IOC_E_ENABLE:
+	case IOCPF_E_DISABLE:
+		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling);
 		break;
 
-	case IOC_E_DISABLE:
-		bfa_ioc_hb_stop(ioc);
-		bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);
+	case IOCPF_E_GETATTRFAIL:
+		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail_sync);
 		break;
 
-	case IOC_E_HWERROR:
-	case IOC_E_FWREADY:
-		/**
-		 * Hard error or IOC recovery by other function.
-		 * Treat it same as heartbeat failure.
-		 */
-		bfa_ioc_hb_stop(ioc);
-		/* !!! fall through !!! */
+	case IOCPF_E_FAIL:
+		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail_sync);
+		break;
 
-	case IOC_E_HBFAIL:
-		bfa_fsm_set_state(ioc, bfa_ioc_sm_hbfail);
+	case IOCPF_E_FWREADY:
+		bfa_ioc_pf_failed(ioc);
+		if (bfa_nw_ioc_is_operational(ioc))
+			bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail_sync);
+		else
+			bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail_sync);
 		break;
 
 	default:
@@ -476,33 +860,40 @@ bfa_ioc_sm_op(struct bfa_ioc *ioc, enum
 }
 
 static void
-bfa_ioc_sm_disabling_entry(struct bfa_ioc *ioc)
+bfa_iocpf_sm_disabling_entry(struct bfa_iocpf *iocpf)
 {
-	bfa_ioc_timer_start(ioc);
-	bfa_ioc_send_disable(ioc);
+	mod_timer(&(iocpf->ioc)->iocpf_timer, jiffies +
+		msecs_to_jiffies(BFA_IOC_TOV));
+	bfa_ioc_send_disable(iocpf->ioc);
 }
 
 /**
  * IOC is being disabled
  */
 static void
-bfa_ioc_sm_disabling(struct bfa_ioc *ioc, enum ioc_event event)
+bfa_iocpf_sm_disabling(struct bfa_iocpf *iocpf, enum iocpf_event event)
 {
+	struct bfa_ioc *ioc = iocpf->ioc;
+
 	switch (event) {
-	case IOC_E_FWRSP_DISABLE:
-		bfa_ioc_timer_stop(ioc);
-		bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled);
+	case IOCPF_E_FWRSP_DISABLE:
+	case IOCPF_E_FWREADY:
+		del_timer(&ioc->iocpf_timer);
+		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling_sync);
 		break;
 
-	case IOC_E_HWERROR:
-		bfa_ioc_timer_stop(ioc);
+	case IOCPF_E_FAIL:
+		del_timer(&ioc->iocpf_timer);
 		/*
 		 * !!! fall through !!!
 		 */
 
-	case IOC_E_TIMEOUT:
+	case IOCPF_E_TIMEOUT:
 		writel(BFI_IOC_FAIL, ioc->ioc_regs.ioc_fwstate);
-		bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled);
+		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling_sync);
+		break;
+
+	case IOCPF_E_FWRSP_ENABLE:
 		break;
 
 	default:
@@ -510,33 +901,58 @@ bfa_ioc_sm_disabling(struct bfa_ioc *ioc
 	}
 }
 
-/**
- * IOC disable completion entry.
- */
 static void
-bfa_ioc_sm_disabled_entry(struct bfa_ioc *ioc)
+bfa_iocpf_sm_disabling_sync_entry(struct bfa_iocpf *iocpf)
 {
-	bfa_ioc_disable_comp(ioc);
+	bfa_ioc_hw_sem_get(iocpf->ioc);
 }
 
+/**
+ * IOC hb ack request is being removed.
+ */
 static void
-bfa_ioc_sm_disabled(struct bfa_ioc *ioc, enum ioc_event event)
+bfa_iocpf_sm_disabling_sync(struct bfa_iocpf *iocpf, enum iocpf_event event)
 {
+	struct bfa_ioc *ioc = iocpf->ioc;
+
 	switch (event) {
-	case IOC_E_ENABLE:
-		bfa_fsm_set_state(ioc, bfa_ioc_sm_semwait);
+	case IOCPF_E_SEMLOCKED:
+		bfa_ioc_sync_leave(ioc);
+		bfa_nw_ioc_hw_sem_release(ioc);
+		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled);
 		break;
 
-	case IOC_E_DISABLE:
-		ioc->cbfn->disable_cbfn(ioc->bfa);
+	case IOCPF_E_FAIL:
 		break;
 
-	case IOC_E_FWREADY:
+	default:
+		bfa_sm_fault(ioc, event);
+	}
+}
+
+/**
+ * IOC disable completion entry.
+ */
+static void
+bfa_iocpf_sm_disabled_entry(struct bfa_iocpf *iocpf)
+{
+	bfa_ioc_pf_disabled(iocpf->ioc);
+}
+
+static void
+bfa_iocpf_sm_disabled(struct bfa_iocpf *iocpf, enum iocpf_event event)
+{
+	struct bfa_ioc *ioc = iocpf->ioc;
+
+	switch (event) {
+	case IOCPF_E_ENABLE:
+		iocpf->retry_count = 0;
+		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_semwait);
 		break;
 
-	case IOC_E_DETACH:
+	case IOCPF_E_STOP:
 		bfa_ioc_firmware_unlock(ioc);
-		bfa_fsm_set_state(ioc, bfa_ioc_sm_reset);
+		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);
 		break;
 
 	default:
@@ -545,33 +961,50 @@ bfa_ioc_sm_disabled(struct bfa_ioc *ioc,
 }
 
 static void
-bfa_ioc_sm_initfail_entry(struct bfa_ioc *ioc)
+bfa_iocpf_sm_initfail_sync_entry(struct bfa_iocpf *iocpf)
 {
-	ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
-	bfa_ioc_timer_start(ioc);
+	bfa_ioc_hw_sem_get(iocpf->ioc);
 }
 
 /**
- * @brief
  * Hardware initialization failed.
  */
 static void
-bfa_ioc_sm_initfail(struct bfa_ioc *ioc, enum ioc_event event)
+bfa_iocpf_sm_initfail_sync(struct bfa_iocpf *iocpf, enum iocpf_event event)
 {
+	struct bfa_ioc *ioc = iocpf->ioc;
+
 	switch (event) {
-	case IOC_E_DISABLE:
-		bfa_ioc_timer_stop(ioc);
-		bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled);
+	case IOCPF_E_SEMLOCKED:
+		bfa_ioc_notify_fail(ioc);
+		bfa_ioc_sync_ack(ioc);
+		iocpf->retry_count++;
+		if (iocpf->retry_count >= BFA_IOC_HWINIT_MAX) {
+			bfa_ioc_sync_leave(ioc);
+			bfa_nw_ioc_hw_sem_release(ioc);
+			bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail);
+		} else {
+			if (bfa_ioc_sync_complete(ioc))
+				bfa_fsm_set_state(iocpf, bfa_iocpf_sm_hwinit);
+			else {
+				bfa_nw_ioc_hw_sem_release(ioc);
+				bfa_fsm_set_state(iocpf, bfa_iocpf_sm_semwait);
+			}
+		}
 		break;
 
-	case IOC_E_DETACH:
-		bfa_ioc_timer_stop(ioc);
+	case IOCPF_E_DISABLE:
+		bfa_ioc_hw_sem_get_cancel(ioc);
+		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling_sync);
+		break;
+
+	case IOCPF_E_STOP:
+		bfa_ioc_hw_sem_get_cancel(ioc);
 		bfa_ioc_firmware_unlock(ioc);
-		bfa_fsm_set_state(ioc, bfa_ioc_sm_reset);
+		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);
 		break;
 
-	case IOC_E_TIMEOUT:
-		bfa_fsm_set_state(ioc, bfa_ioc_sm_semwait);
+	case IOCPF_E_FAIL:
 		break;
 
 	default:
@@ -580,80 +1013,108 @@ bfa_ioc_sm_initfail(struct bfa_ioc *ioc,
 }
 
 static void
-bfa_ioc_sm_hbfail_entry(struct bfa_ioc *ioc)
+bfa_iocpf_sm_initfail_entry(struct bfa_iocpf *iocpf)
 {
-	struct list_head			*qe;
-	struct bfa_ioc_hbfail_notify *notify;
+	bfa_ioc_pf_initfailed(iocpf->ioc);
+}
 
-	/**
-	 * Mark IOC as failed in hardware and stop firmware.
-	 */
-	bfa_ioc_lpu_stop(ioc);
-	writel(BFI_IOC_FAIL, ioc->ioc_regs.ioc_fwstate);
+/**
+ * Hardware initialization failed.
+ */
+static void
+bfa_iocpf_sm_initfail(struct bfa_iocpf *iocpf, enum iocpf_event event)
+{
+	struct bfa_ioc *ioc = iocpf->ioc;
 
-	/**
-	 * Notify other functions on HB failure.
-	 */
-	bfa_ioc_notify_hbfail(ioc);
+	switch (event) {
+	case IOCPF_E_DISABLE:
+		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled);
+		break;
 
-	/**
-	 * Notify driver and common modules registered for notification.
-	 */
-	ioc->cbfn->hbfail_cbfn(ioc->bfa);
-	list_for_each(qe, &ioc->hb_notify_q) {
-		notify = (struct bfa_ioc_hbfail_notify *) qe;
-		notify->cbfn(notify->cbarg);
+	case IOCPF_E_STOP:
+		bfa_ioc_firmware_unlock(ioc);
+		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);
+		break;
+
+	default:
+		bfa_sm_fault(ioc, event);
 	}
+}
 
+static void
+bfa_iocpf_sm_fail_sync_entry(struct bfa_iocpf *iocpf)
+{
 	/**
-	 * Flush any queued up mailbox requests.
+	 * Mark IOC as failed in hardware and stop firmware.
 	 */
-	bfa_ioc_mbox_hbfail(ioc);
+	bfa_ioc_lpu_stop(iocpf->ioc);
 
 	/**
-	 * Trigger auto-recovery after a delay.
+	 * Flush any queued up mailbox requests.
 	 */
-	if (ioc->auto_recover)
-		mod_timer(&ioc->ioc_timer, jiffies +
-			msecs_to_jiffies(BFA_IOC_TOV_RECOVER));
+	bfa_ioc_mbox_hbfail(iocpf->ioc);
+	bfa_ioc_hw_sem_get(iocpf->ioc);
 }
 
 /**
- * @brief
- * IOC heartbeat failure.
+ * IOC is in failed state.
  */
 static void
-bfa_ioc_sm_hbfail(struct bfa_ioc *ioc, enum ioc_event event)
+bfa_iocpf_sm_fail_sync(struct bfa_iocpf *iocpf, enum iocpf_event event)
 {
-	switch (event) {
+	struct bfa_ioc *ioc = iocpf->ioc;
 
-	case IOC_E_ENABLE:
-		ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
+	switch (event) {
+	case IOCPF_E_SEMLOCKED:
+		iocpf->retry_count = 0;
+		bfa_ioc_sync_ack(ioc);
+		bfa_ioc_notify_fail(ioc);
+		if (!iocpf->auto_recover) {
+			bfa_ioc_sync_leave(ioc);
+			bfa_nw_ioc_hw_sem_release(ioc);
+			bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail);
+		} else {
+			if (bfa_ioc_sync_complete(ioc))
+				bfa_fsm_set_state(iocpf, bfa_iocpf_sm_hwinit);
+			else {
+				bfa_nw_ioc_hw_sem_release(ioc);
+				bfa_fsm_set_state(iocpf, bfa_iocpf_sm_semwait);
+			}
+		}
 		break;
 
-	case IOC_E_DISABLE:
-		if (ioc->auto_recover)
-			bfa_ioc_timer_stop(ioc);
-		bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled);
+	case IOCPF_E_DISABLE:
+		bfa_ioc_hw_sem_get_cancel(ioc);
+		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling_sync);
 		break;
 
-	case IOC_E_TIMEOUT:
-		bfa_fsm_set_state(ioc, bfa_ioc_sm_semwait);
+	case IOCPF_E_FAIL:
 		break;
 
-	case IOC_E_FWREADY:
-		/**
-		 * Recovery is already initiated by other function.
-		 */
-		break;
+	default:
+		bfa_sm_fault(ioc, event);
+	}
+}
 
-	case IOC_E_HWERROR:
-		/*
-		 * HB failure notification, ignore.
-		 */
+static void
+bfa_iocpf_sm_fail_entry(struct bfa_iocpf *iocpf)
+{
+}
+
+/**
+ * @brief
+ * IOC is in failed state.
+ */
+static void
+bfa_iocpf_sm_fail(struct bfa_iocpf *iocpf, enum iocpf_event event)
+{
+	switch (event) {
+	case IOCPF_E_DISABLE:
+		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled);
 		break;
+
 	default:
-		bfa_sm_fault(ioc, event);
+		bfa_sm_fault(iocpf->ioc, event);
 	}
 }
 
@@ -678,14 +1139,6 @@ bfa_ioc_disable_comp(struct bfa_ioc *ioc
 	}
 }
 
-void
-bfa_nw_ioc_sem_timeout(void *ioc_arg)
-{
-	struct bfa_ioc *ioc = (struct bfa_ioc *) ioc_arg;
-
-	bfa_ioc_hw_sem_get(ioc);
-}
-
 bool
 bfa_nw_ioc_sem_get(void __iomem *sem_reg)
 {
@@ -725,7 +1178,7 @@ bfa_ioc_hw_sem_get(struct bfa_ioc *ioc)
 	 */
 	r32 = readl(ioc->ioc_regs.ioc_sem_reg);
 	if (r32 == 0) {
-		bfa_fsm_send_event(ioc, IOC_E_SEMLOCKED);
+		bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_SEMLOCKED);
 		return;
 	}
 
@@ -865,12 +1318,6 @@ bfa_ioc_fwver_valid(struct bfa_ioc *ioc)
 {
 	struct bfi_ioc_image_hdr fwhdr, *drv_fwhdr;
 
-	/**
-	 * If bios/efi boot (flash based) -- return true
-	 */
-	if (bfa_ioc_is_optrom(ioc))
-		return true;
-
 	bfa_nw_ioc_fwver_get(ioc, &fwhdr);
 	drv_fwhdr = (struct bfi_ioc_image_hdr *)
 		bfa_cb_image_get_chunk(BFA_IOC_FWIMG_TYPE(ioc), 0);
@@ -934,20 +1381,15 @@ bfa_ioc_hwinit(struct bfa_ioc *ioc, bool
 	/**
 	 * If IOC function is disabled and firmware version is same,
 	 * just re-enable IOC.
-	 *
-	 * If option rom, IOC must not be in operational state. With
-	 * convergence, IOC will be in operational state when 2nd driver
-	 * is loaded.
 	 */
-	if (ioc_fwstate == BFI_IOC_DISABLED ||
-	    (!bfa_ioc_is_optrom(ioc) && ioc_fwstate == BFI_IOC_OP)) {
+	if (ioc_fwstate == BFI_IOC_DISABLED || ioc_fwstate == BFI_IOC_OP) {
 		/**
 		 * When using MSI-X any pending firmware ready event should
 		 * be flushed. Otherwise MSI-X interrupts are not delivered.
 		 */
 		bfa_ioc_msgflush(ioc);
 		ioc->cbfn->reset_cbfn(ioc->bfa);
-		bfa_fsm_send_event(ioc, IOC_E_FWREADY);
+		bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_FWREADY);
 		return;
 	}
 
@@ -1033,7 +1475,6 @@ bfa_nw_ioc_hb_check(void *cbarg)
 
 	hb_count = readl(ioc->ioc_regs.heartbeat);
 	if (ioc->hb_count == hb_count) {
-		pr_crit("Firmware heartbeat failure at %d", hb_count);
 		bfa_ioc_recover(ioc);
 		return;
 	} else {
@@ -1078,11 +1519,6 @@ bfa_ioc_download_fw(struct bfa_ioc *ioc,
 	 */
 	bfa_ioc_lmem_init(ioc);
 
-	/**
-	 * Flash based firmware boot
-	 */
-	if (bfa_ioc_is_optrom(ioc))
-		boot_type = BFI_BOOT_TYPE_FLASH;
 	fwimg = bfa_cb_image_get_chunk(BFA_IOC_FWIMG_TYPE(ioc), chunkno);
 
 	pgnum = bfa_ioc_smem_pgnum(ioc, loff);
@@ -1209,6 +1645,55 @@ bfa_ioc_mbox_hbfail(struct bfa_ioc *ioc)
 		bfa_q_deq(&mod->cmd_q, &cmd);
 }
 
+static void
+bfa_ioc_fail_notify(struct bfa_ioc *ioc)
+{
+	struct list_head		*qe;
+	struct bfa_ioc_hbfail_notify	*notify;
+
+	/**
+	 * Notify driver and common modules registered for notification.
+	 */
+	ioc->cbfn->hbfail_cbfn(ioc->bfa);
+	list_for_each(qe, &ioc->hb_notify_q) {
+		notify = (struct bfa_ioc_hbfail_notify *) qe;
+		notify->cbfn(notify->cbarg);
+	}
+}
+
+static void
+bfa_ioc_pf_enabled(struct bfa_ioc *ioc)
+{
+	bfa_fsm_send_event(ioc, IOC_E_ENABLED);
+}
+
+static void
+bfa_ioc_pf_disabled(struct bfa_ioc *ioc)
+{
+	bfa_fsm_send_event(ioc, IOC_E_DISABLED);
+}
+
+static void
+bfa_ioc_pf_initfailed(struct bfa_ioc *ioc)
+{
+	bfa_fsm_send_event(ioc, IOC_E_INITFAILED);
+}
+
+static void
+bfa_ioc_pf_failed(struct bfa_ioc *ioc)
+{
+	bfa_fsm_send_event(ioc, IOC_E_PFAILED);
+}
+
+static void
+bfa_ioc_pf_fwmismatch(struct bfa_ioc *ioc)
+{
+	/**
+	 * Provide enable completion callback and AEN notification.
+	 */
+	ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
+}
+
 /**
  * IOC public
  */
@@ -1304,6 +1789,7 @@ static void
 bfa_ioc_isr(struct bfa_ioc *ioc, struct bfi_mbmsg *m)
 {
 	union bfi_ioc_i2h_msg_u	*msg;
+	struct bfa_iocpf *iocpf = &ioc->iocpf;
 
 	msg = (union bfi_ioc_i2h_msg_u *) m;
 
@@ -1314,15 +1800,15 @@ bfa_ioc_isr(struct bfa_ioc *ioc, struct
 		break;
 
 	case BFI_IOC_I2H_READY_EVENT:
-		bfa_fsm_send_event(ioc, IOC_E_FWREADY);
+		bfa_fsm_send_event(iocpf, IOCPF_E_FWREADY);
 		break;
 
 	case BFI_IOC_I2H_ENABLE_REPLY:
-		bfa_fsm_send_event(ioc, IOC_E_FWRSP_ENABLE);
+		bfa_fsm_send_event(iocpf, IOCPF_E_FWRSP_ENABLE);
 		break;
 
 	case BFI_IOC_I2H_DISABLE_REPLY:
-		bfa_fsm_send_event(ioc, IOC_E_FWRSP_DISABLE);
+		bfa_fsm_send_event(iocpf, IOCPF_E_FWRSP_DISABLE);
 		break;
 
 	case BFI_IOC_I2H_GETATTR_REPLY:
@@ -1348,11 +1834,13 @@ bfa_nw_ioc_attach(struct bfa_ioc *ioc, v
 	ioc->fcmode	= false;
 	ioc->pllinit	= false;
 	ioc->dbg_fwsave_once = true;
+	ioc->iocpf.ioc  = ioc;
 
 	bfa_ioc_mbox_attach(ioc);
 	INIT_LIST_HEAD(&ioc->hb_notify_q);
 
-	bfa_fsm_set_state(ioc, bfa_ioc_sm_reset);
+	bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);
+	bfa_fsm_send_event(ioc, IOC_E_RESET);
 }
 
 /**
@@ -1657,7 +2145,40 @@ bfa_ioc_get_adapter_model(struct bfa_ioc
 static enum bfa_ioc_state
 bfa_ioc_get_state(struct bfa_ioc *ioc)
 {
-	return bfa_sm_to_state(ioc_sm_table, ioc->fsm);
+	enum bfa_iocpf_state iocpf_st;
+	enum bfa_ioc_state ioc_st = bfa_sm_to_state(ioc_sm_table, ioc->fsm);
+
+	if (ioc_st == BFA_IOC_ENABLING ||
+		ioc_st == BFA_IOC_FAIL || ioc_st == BFA_IOC_INITFAIL) {
+
+		iocpf_st = bfa_sm_to_state(iocpf_sm_table, ioc->iocpf.fsm);
+
+		switch (iocpf_st) {
+		case BFA_IOCPF_SEMWAIT:
+			ioc_st = BFA_IOC_SEMWAIT;
+			break;
+
+		case BFA_IOCPF_HWINIT:
+			ioc_st = BFA_IOC_HWINIT;
+			break;
+
+		case BFA_IOCPF_FWMISMATCH:
+			ioc_st = BFA_IOC_FWMISMATCH;
+			break;
+
+		case BFA_IOCPF_FAIL:
+			ioc_st = BFA_IOC_FAIL;
+			break;
+
+		case BFA_IOCPF_INITFAIL:
+			ioc_st = BFA_IOC_INITFAIL;
+			break;
+
+		default:
+			break;
+		}
+	}
+	return ioc_st;
 }
 
 void
@@ -1689,28 +2210,7 @@ bfa_ioc_get_pwwn(struct bfa_ioc *ioc)
 mac_t
 bfa_nw_ioc_get_mac(struct bfa_ioc *ioc)
 {
-	/*
-	 * Currently mfg mac is used as FCoE enode mac (not configured by PBC)
-	 */
-	if (bfa_ioc_get_type(ioc) == BFA_IOC_TYPE_FCoE)
-		return bfa_ioc_get_mfg_mac(ioc);
-	else
-		return ioc->attr->mac;
-}
-
-static mac_t
-bfa_ioc_get_mfg_mac(struct bfa_ioc *ioc)
-{
-	mac_t	m;
-
-	m = ioc->attr->mfg_mac;
-	if (bfa_mfg_is_old_wwn_mac_model(ioc->attr->card_type))
-		m.mac[MAC_ADDRLEN - 1] += bfa_ioc_pcifn(ioc);
-	else
-		bfa_mfg_increment_wwn_mac(&(m.mac[MAC_ADDRLEN-3]),
-			bfa_ioc_pcifn(ioc));
-
-	return m;
+	return ioc->attr->mac;
 }
 
 /**
@@ -1719,8 +2219,13 @@ bfa_ioc_get_mfg_mac(struct bfa_ioc *ioc)
 static void
 bfa_ioc_recover(struct bfa_ioc *ioc)
 {
-	bfa_ioc_stats(ioc, ioc_hbfails);
-	bfa_fsm_send_event(ioc, IOC_E_HBFAIL);
+	u16 bdf;
+
+	bdf = (ioc->pcidev.pci_slot << 8 | ioc->pcidev.pci_func << 3 |
+					ioc->pcidev.device_id);
+
+	pr_crit("Firmware heartbeat failure at %d", bdf);
+	BUG_ON(1);
 }
 
 static void
@@ -1728,5 +2233,61 @@ bfa_ioc_check_attr_wwns(struct bfa_ioc *
 {
 	if (bfa_ioc_get_type(ioc) == BFA_IOC_TYPE_LL)
 		return;
+}
+
+/**
+ * @dg hal_iocpf_pvt BFA IOC PF private functions
+ * @{
+ */
+
+static void
+bfa_iocpf_enable(struct bfa_ioc *ioc)
+{
+	bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_ENABLE);
+}
+
+static void
+bfa_iocpf_disable(struct bfa_ioc *ioc)
+{
+	bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_DISABLE);
+}
 
+static void
+bfa_iocpf_fail(struct bfa_ioc *ioc)
+{
+	bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_FAIL);
+}
+
+static void
+bfa_iocpf_initfail(struct bfa_ioc *ioc)
+{
+	bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_INITFAIL);
+}
+
+static void
+bfa_iocpf_getattrfail(struct bfa_ioc *ioc)
+{
+	bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_GETATTRFAIL);
+}
+
+static void
+bfa_iocpf_stop(struct bfa_ioc *ioc)
+{
+	bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_STOP);
+}
+
+void
+bfa_nw_iocpf_timeout(void *ioc_arg)
+{
+	struct bfa_ioc  *ioc = (struct bfa_ioc *) ioc_arg;
+
+	bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_TIMEOUT);
+}
+
+void
+bfa_nw_iocpf_sem_timeout(void *ioc_arg)
+{
+	struct bfa_ioc  *ioc = (struct bfa_ioc *) ioc_arg;
+
+	bfa_ioc_hw_sem_get(ioc);
 }
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/bna/bfa_ioc_ct.c linux-libre-2.6.38-gnu1/drivers/net/bna/bfa_ioc_ct.c
--- linux-libre-2.6.37-gnu1/drivers/net/bna/bfa_ioc_ct.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/bna/bfa_ioc_ct.c	2011-03-14 21:20:32.000000000 -0400
@@ -22,6 +22,15 @@
 #include "bfi_ctreg.h"
 #include "bfa_defs.h"
 
+#define bfa_ioc_ct_sync_pos(__ioc)	\
+		((u32) (1 << bfa_ioc_pcifn(__ioc)))
+#define BFA_IOC_SYNC_REQD_SH		16
+#define bfa_ioc_ct_get_sync_ackd(__val) (__val & 0x0000ffff)
+#define bfa_ioc_ct_clear_sync_ackd(__val) (__val & 0xffff0000)
+#define bfa_ioc_ct_get_sync_reqd(__val) (__val >> BFA_IOC_SYNC_REQD_SH)
+#define bfa_ioc_ct_sync_reqd_pos(__ioc) \
+		(bfa_ioc_ct_sync_pos(__ioc) << BFA_IOC_SYNC_REQD_SH)
+
 /*
  * forward declarations
  */
@@ -30,8 +39,12 @@ static void bfa_ioc_ct_firmware_unlock(s
 static void bfa_ioc_ct_reg_init(struct bfa_ioc *ioc);
 static void bfa_ioc_ct_map_port(struct bfa_ioc *ioc);
 static void bfa_ioc_ct_isr_mode_set(struct bfa_ioc *ioc, bool msix);
-static void bfa_ioc_ct_notify_hbfail(struct bfa_ioc *ioc);
+static void bfa_ioc_ct_notify_fail(struct bfa_ioc *ioc);
 static void bfa_ioc_ct_ownership_reset(struct bfa_ioc *ioc);
+static void bfa_ioc_ct_sync_join(struct bfa_ioc *ioc);
+static void bfa_ioc_ct_sync_leave(struct bfa_ioc *ioc);
+static void bfa_ioc_ct_sync_ack(struct bfa_ioc *ioc);
+static bool bfa_ioc_ct_sync_complete(struct bfa_ioc *ioc);
 static enum bfa_status bfa_ioc_ct_pll_init(void __iomem *rb, bool fcmode);
 
 static struct bfa_ioc_hwif nw_hwif_ct;
@@ -48,8 +61,12 @@ bfa_nw_ioc_set_ct_hwif(struct bfa_ioc *i
 	nw_hwif_ct.ioc_reg_init = bfa_ioc_ct_reg_init;
 	nw_hwif_ct.ioc_map_port = bfa_ioc_ct_map_port;
 	nw_hwif_ct.ioc_isr_mode_set = bfa_ioc_ct_isr_mode_set;
-	nw_hwif_ct.ioc_notify_hbfail = bfa_ioc_ct_notify_hbfail;
+	nw_hwif_ct.ioc_notify_fail = bfa_ioc_ct_notify_fail;
 	nw_hwif_ct.ioc_ownership_reset = bfa_ioc_ct_ownership_reset;
+	nw_hwif_ct.ioc_sync_join = bfa_ioc_ct_sync_join;
+	nw_hwif_ct.ioc_sync_leave = bfa_ioc_ct_sync_leave;
+	nw_hwif_ct.ioc_sync_ack = bfa_ioc_ct_sync_ack;
+	nw_hwif_ct.ioc_sync_complete = bfa_ioc_ct_sync_complete;
 
 	ioc->ioc_hwif = &nw_hwif_ct;
 }
@@ -86,6 +103,7 @@ bfa_ioc_ct_firmware_lock(struct bfa_ioc
 	if (usecnt == 0) {
 		writel(1, ioc->ioc_regs.ioc_usage_reg);
 		bfa_nw_ioc_sem_release(ioc->ioc_regs.ioc_usage_sem_reg);
+		writel(0, ioc->ioc_regs.ioc_fail_sync);
 		return true;
 	}
 
@@ -149,12 +167,14 @@ bfa_ioc_ct_firmware_unlock(struct bfa_io
  * Notify other functions on HB failure.
  */
 static void
-bfa_ioc_ct_notify_hbfail(struct bfa_ioc *ioc)
+bfa_ioc_ct_notify_fail(struct bfa_ioc *ioc)
 {
 	if (ioc->cna) {
 		writel(__FW_INIT_HALT_P, ioc->ioc_regs.ll_halt);
+		writel(__FW_INIT_HALT_P, ioc->ioc_regs.alt_ll_halt);
 		/* Wait for halt to take effect */
 		readl(ioc->ioc_regs.ll_halt);
+		readl(ioc->ioc_regs.alt_ll_halt);
 	} else {
 		writel(__PSS_ERR_STATUS_SET, ioc->ioc_regs.err_set);
 		readl(ioc->ioc_regs.err_set);
@@ -206,15 +226,19 @@ bfa_ioc_ct_reg_init(struct bfa_ioc *ioc)
 	if (ioc->port_id == 0) {
 		ioc->ioc_regs.heartbeat = rb + BFA_IOC0_HBEAT_REG;
 		ioc->ioc_regs.ioc_fwstate = rb + BFA_IOC0_STATE_REG;
+		ioc->ioc_regs.alt_ioc_fwstate = rb + BFA_IOC1_STATE_REG;
 		ioc->ioc_regs.hfn_mbox_cmd = rb + iocreg_mbcmd_p0[pcifn].hfn;
 		ioc->ioc_regs.lpu_mbox_cmd = rb + iocreg_mbcmd_p0[pcifn].lpu;
 		ioc->ioc_regs.ll_halt = rb + FW_INIT_HALT_P0;
+		ioc->ioc_regs.alt_ll_halt = rb + FW_INIT_HALT_P1;
 	} else {
 		ioc->ioc_regs.heartbeat = (rb + BFA_IOC1_HBEAT_REG);
 		ioc->ioc_regs.ioc_fwstate = (rb + BFA_IOC1_STATE_REG);
+		ioc->ioc_regs.alt_ioc_fwstate = rb + BFA_IOC0_STATE_REG;
 		ioc->ioc_regs.hfn_mbox_cmd = rb + iocreg_mbcmd_p1[pcifn].hfn;
 		ioc->ioc_regs.lpu_mbox_cmd = rb + iocreg_mbcmd_p1[pcifn].lpu;
 		ioc->ioc_regs.ll_halt = rb + FW_INIT_HALT_P1;
+		ioc->ioc_regs.alt_ll_halt = rb + FW_INIT_HALT_P0;
 	}
 
 	/*
@@ -232,6 +256,7 @@ bfa_ioc_ct_reg_init(struct bfa_ioc *ioc)
 	ioc->ioc_regs.ioc_usage_sem_reg = (rb + HOST_SEM1_REG);
 	ioc->ioc_regs.ioc_init_sem_reg = (rb + HOST_SEM2_REG);
 	ioc->ioc_regs.ioc_usage_reg = (rb + BFA_FW_USE_COUNT);
+	ioc->ioc_regs.ioc_fail_sync = (rb + BFA_IOC_FAIL_SYNC);
 
 	/**
 	 * sram memory access
@@ -317,6 +342,77 @@ bfa_ioc_ct_ownership_reset(struct bfa_io
 	bfa_nw_ioc_hw_sem_release(ioc);
 }
 
+/**
+ * Synchronized IOC failure processing routines
+ */
+static void
+bfa_ioc_ct_sync_join(struct bfa_ioc *ioc)
+{
+	u32 r32 = readl(ioc->ioc_regs.ioc_fail_sync);
+	u32 sync_pos = bfa_ioc_ct_sync_reqd_pos(ioc);
+
+	writel((r32 | sync_pos), ioc->ioc_regs.ioc_fail_sync);
+}
+
+static void
+bfa_ioc_ct_sync_leave(struct bfa_ioc *ioc)
+{
+	u32 r32 = readl(ioc->ioc_regs.ioc_fail_sync);
+	u32 sync_msk = bfa_ioc_ct_sync_reqd_pos(ioc) |
+					bfa_ioc_ct_sync_pos(ioc);
+
+	writel((r32 & ~sync_msk), ioc->ioc_regs.ioc_fail_sync);
+}
+
+static void
+bfa_ioc_ct_sync_ack(struct bfa_ioc *ioc)
+{
+	u32 r32 = readl(ioc->ioc_regs.ioc_fail_sync);
+
+	writel((r32 | bfa_ioc_ct_sync_pos(ioc)), ioc->ioc_regs.ioc_fail_sync);
+}
+
+static bool
+bfa_ioc_ct_sync_complete(struct bfa_ioc *ioc)
+{
+	u32 r32 = readl(ioc->ioc_regs.ioc_fail_sync);
+	u32 sync_reqd = bfa_ioc_ct_get_sync_reqd(r32);
+	u32 sync_ackd = bfa_ioc_ct_get_sync_ackd(r32);
+	u32 tmp_ackd;
+
+	if (sync_ackd == 0)
+		return true;
+
+	/**
+	 * The check below is to see whether any other PCI fn
+	 * has reinitialized the ASIC (reset sync_ackd bits)
+	 * and failed again while this IOC was waiting for hw
+	 * semaphore (in bfa_iocpf_sm_semwait()).
+	 */
+	tmp_ackd = sync_ackd;
+	if ((sync_reqd &  bfa_ioc_ct_sync_pos(ioc)) &&
+			!(sync_ackd & bfa_ioc_ct_sync_pos(ioc)))
+		sync_ackd |= bfa_ioc_ct_sync_pos(ioc);
+
+	if (sync_reqd == sync_ackd) {
+		writel(bfa_ioc_ct_clear_sync_ackd(r32),
+				ioc->ioc_regs.ioc_fail_sync);
+		writel(BFI_IOC_FAIL, ioc->ioc_regs.ioc_fwstate);
+		writel(BFI_IOC_FAIL, ioc->ioc_regs.alt_ioc_fwstate);
+		return true;
+	}
+
+	/**
+	 * If another PCI fn reinitialized and failed again while
+	 * this IOC was waiting for hw sem, the sync_ackd bit for
+	 * this IOC need to be set again to allow reinitialization.
+	 */
+	if (tmp_ackd != sync_ackd)
+		writel((r32 | sync_ackd), ioc->ioc_regs.ioc_fail_sync);
+
+	return false;
+}
+
 static enum bfa_status
 bfa_ioc_ct_pll_init(void __iomem *rb, bool fcmode)
 {
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/bna/bfa_ioc.h linux-libre-2.6.38-gnu1/drivers/net/bna/bfa_ioc.h
--- linux-libre-2.6.37-gnu1/drivers/net/bna/bfa_ioc.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/bna/bfa_ioc.h	2011-03-14 21:20:32.000000000 -0400
@@ -26,16 +26,7 @@
 #define BFA_IOC_TOV		3000	/* msecs */
 #define BFA_IOC_HWSEM_TOV	500	/* msecs */
 #define BFA_IOC_HB_TOV		500	/* msecs */
-#define BFA_IOC_HWINIT_MAX	2
-#define BFA_IOC_TOV_RECOVER	BFA_IOC_HB_TOV
-
-/**
- * Generic Scatter Gather Element used by driver
- */
-struct bfa_sge {
-	u32	sg_len;
-	void	*sg_addr;
-};
+#define BFA_IOC_HWINIT_MAX	5
 
 /**
  * PCI device information required by IOC
@@ -65,19 +56,6 @@ struct bfa_dma {
 #define BFI_SMEM_CT_SIZE	0x280000U	/* ! 2.5MB for catapult	*/
 
 /**
- * @brief BFA dma address assignment macro
- */
-#define bfa_dma_addr_set(dma_addr, pa)	\
-		__bfa_dma_addr_set(&dma_addr, (u64)pa)
-
-static inline void
-__bfa_dma_addr_set(union bfi_addr_u *dma_addr, u64 pa)
-{
-	dma_addr->a32.addr_lo = (u32) pa;
-	dma_addr->a32.addr_hi = (u32) (upper_32_bits(pa));
-}
-
-/**
  * @brief BFA dma address assignment macro. (big endian format)
  */
 #define bfa_dma_be_addr_set(dma_addr, pa)	\
@@ -105,8 +83,11 @@ struct bfa_ioc_regs {
 	void __iomem *host_page_num_fn;
 	void __iomem *heartbeat;
 	void __iomem *ioc_fwstate;
+	void __iomem *alt_ioc_fwstate;
 	void __iomem *ll_halt;
+	void __iomem *alt_ll_halt;
 	void __iomem *err_set;
+	void __iomem *ioc_fail_sync;
 	void __iomem *shirq_isr_next;
 	void __iomem *shirq_msk_next;
 	void __iomem *smem_page_start;
@@ -165,16 +146,22 @@ struct bfa_ioc_hbfail_notify {
 	(__notify)->cbarg = (__cbarg);				\
 } while (0)
 
+struct bfa_iocpf {
+	bfa_fsm_t		fsm;
+	struct bfa_ioc		*ioc;
+	u32			retry_count;
+	bool			auto_recover;
+};
+
 struct bfa_ioc {
 	bfa_fsm_t		fsm;
 	struct bfa 		*bfa;
 	struct bfa_pcidev 	pcidev;
-	struct bfa_timer_mod	*timer_mod;
 	struct timer_list 	ioc_timer;
+	struct timer_list 	iocpf_timer;
 	struct timer_list 	sem_timer;
 	struct timer_list	hb_timer;
 	u32			hb_count;
-	u32			retry_count;
 	struct list_head	hb_notify_q;
 	void			*dbg_fwsave;
 	int			dbg_fwsave_len;
@@ -182,7 +169,6 @@ struct bfa_ioc {
 	enum bfi_mclass		ioc_mc;
 	struct bfa_ioc_regs 	ioc_regs;
 	struct bfa_ioc_drv_stats stats;
-	bool			auto_recover;
 	bool			fcmode;
 	bool			ctdev;
 	bool			cna;
@@ -195,6 +181,7 @@ struct bfa_ioc {
 	struct bfa_ioc_cbfn	*cbfn;
 	struct bfa_ioc_mbox_mod	mbox_mod;
 	struct bfa_ioc_hwif	*ioc_hwif;
+	struct bfa_iocpf	iocpf;
 };
 
 struct bfa_ioc_hwif {
@@ -205,8 +192,12 @@ struct bfa_ioc_hwif {
 	void		(*ioc_map_port)	(struct bfa_ioc *ioc);
 	void		(*ioc_isr_mode_set)	(struct bfa_ioc *ioc,
 					bool msix);
-	void		(*ioc_notify_hbfail)	(struct bfa_ioc *ioc);
+	void		(*ioc_notify_fail)	(struct bfa_ioc *ioc);
 	void		(*ioc_ownership_reset)	(struct bfa_ioc *ioc);
+	void		(*ioc_sync_join)	(struct bfa_ioc *ioc);
+	void		(*ioc_sync_leave)	(struct bfa_ioc *ioc);
+	void		(*ioc_sync_ack)		(struct bfa_ioc *ioc);
+	bool		(*ioc_sync_complete)	(struct bfa_ioc *ioc);
 };
 
 #define bfa_ioc_pcifn(__ioc)		((__ioc)->pcidev.pci_func)
@@ -271,7 +262,6 @@ void bfa_nw_ioc_enable(struct bfa_ioc *i
 void bfa_nw_ioc_disable(struct bfa_ioc *ioc);
 
 void bfa_nw_ioc_error_isr(struct bfa_ioc *ioc);
-
 void bfa_nw_ioc_get_attr(struct bfa_ioc *ioc, struct bfa_ioc_attr *ioc_attr);
 void bfa_nw_ioc_hbfail_register(struct bfa_ioc *ioc,
 	struct bfa_ioc_hbfail_notify *notify);
@@ -289,7 +279,8 @@ mac_t bfa_nw_ioc_get_mac(struct bfa_ioc
  */
 void bfa_nw_ioc_timeout(void *ioc);
 void bfa_nw_ioc_hb_check(void *ioc);
-void bfa_nw_ioc_sem_timeout(void *ioc);
+void bfa_nw_iocpf_timeout(void *ioc);
+void bfa_nw_iocpf_sem_timeout(void *ioc);
 
 /*
  * F/W Image Size & Chunk
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/bna/bfi_ctreg.h linux-libre-2.6.38-gnu1/drivers/net/bna/bfi_ctreg.h
--- linux-libre-2.6.37-gnu1/drivers/net/bna/bfi_ctreg.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/bna/bfi_ctreg.h	2011-03-14 21:20:32.000000000 -0400
@@ -535,6 +535,7 @@ enum {
 #define BFA_IOC1_HBEAT_REG		HOST_SEM2_INFO_REG
 #define BFA_IOC1_STATE_REG		HOST_SEM3_INFO_REG
 #define BFA_FW_USE_COUNT		 HOST_SEM4_INFO_REG
+#define BFA_IOC_FAIL_SYNC		HOST_SEM5_INFO_REG
 
 #define CPE_DEPTH_Q(__n) \
 	(CPE_DEPTH_Q0 + (__n) * (CPE_DEPTH_Q1 - CPE_DEPTH_Q0))
@@ -552,22 +553,30 @@ enum {
 	(RME_PI_PTR_Q0 + (__n) * (RME_PI_PTR_Q1 - RME_PI_PTR_Q0))
 #define RME_CI_PTR_Q(__n) \
 	(RME_CI_PTR_Q0 + (__n) * (RME_CI_PTR_Q1 - RME_CI_PTR_Q0))
-#define HQM_QSET_RXQ_DRBL_P0(__n) (HQM_QSET0_RXQ_DRBL_P0 + (__n) \
-	* (HQM_QSET1_RXQ_DRBL_P0 - HQM_QSET0_RXQ_DRBL_P0))
-#define HQM_QSET_TXQ_DRBL_P0(__n) (HQM_QSET0_TXQ_DRBL_P0 + (__n) \
-	* (HQM_QSET1_TXQ_DRBL_P0 - HQM_QSET0_TXQ_DRBL_P0))
-#define HQM_QSET_IB_DRBL_1_P0(__n) (HQM_QSET0_IB_DRBL_1_P0 + (__n) \
-	* (HQM_QSET1_IB_DRBL_1_P0 - HQM_QSET0_IB_DRBL_1_P0))
-#define HQM_QSET_IB_DRBL_2_P0(__n) (HQM_QSET0_IB_DRBL_2_P0 + (__n) \
-	* (HQM_QSET1_IB_DRBL_2_P0 - HQM_QSET0_IB_DRBL_2_P0))
-#define HQM_QSET_RXQ_DRBL_P1(__n) (HQM_QSET0_RXQ_DRBL_P1 + (__n) \
-	* (HQM_QSET1_RXQ_DRBL_P1 - HQM_QSET0_RXQ_DRBL_P1))
-#define HQM_QSET_TXQ_DRBL_P1(__n) (HQM_QSET0_TXQ_DRBL_P1 + (__n) \
-	* (HQM_QSET1_TXQ_DRBL_P1 - HQM_QSET0_TXQ_DRBL_P1))
-#define HQM_QSET_IB_DRBL_1_P1(__n) (HQM_QSET0_IB_DRBL_1_P1 + (__n) \
-	* (HQM_QSET1_IB_DRBL_1_P1 - HQM_QSET0_IB_DRBL_1_P1))
-#define HQM_QSET_IB_DRBL_2_P1(__n) (HQM_QSET0_IB_DRBL_2_P1 + (__n) \
-	* (HQM_QSET1_IB_DRBL_2_P1 - HQM_QSET0_IB_DRBL_2_P1))
+#define HQM_QSET_RXQ_DRBL_P0(__n) \
+	(HQM_QSET0_RXQ_DRBL_P0 + (__n) * \
+		(HQM_QSET1_RXQ_DRBL_P0 - HQM_QSET0_RXQ_DRBL_P0))
+#define HQM_QSET_TXQ_DRBL_P0(__n) \
+	(HQM_QSET0_TXQ_DRBL_P0 + (__n) * \
+		(HQM_QSET1_TXQ_DRBL_P0 - HQM_QSET0_TXQ_DRBL_P0))
+#define HQM_QSET_IB_DRBL_1_P0(__n) \
+	(HQM_QSET0_IB_DRBL_1_P0 + (__n) * \
+		(HQM_QSET1_IB_DRBL_1_P0 - HQM_QSET0_IB_DRBL_1_P0))
+#define HQM_QSET_IB_DRBL_2_P0(__n) \
+	(HQM_QSET0_IB_DRBL_2_P0 + (__n) * \
+		(HQM_QSET1_IB_DRBL_2_P0 - HQM_QSET0_IB_DRBL_2_P0))
+#define HQM_QSET_RXQ_DRBL_P1(__n) \
+	(HQM_QSET0_RXQ_DRBL_P1 + (__n) * \
+		(HQM_QSET1_RXQ_DRBL_P1 - HQM_QSET0_RXQ_DRBL_P1))
+#define HQM_QSET_TXQ_DRBL_P1(__n) \
+	(HQM_QSET0_TXQ_DRBL_P1 + (__n) * \
+		(HQM_QSET1_TXQ_DRBL_P1 - HQM_QSET0_TXQ_DRBL_P1))
+#define HQM_QSET_IB_DRBL_1_P1(__n) \
+	(HQM_QSET0_IB_DRBL_1_P1 + (__n) * \
+		(HQM_QSET1_IB_DRBL_1_P1 - HQM_QSET0_IB_DRBL_1_P1))
+#define HQM_QSET_IB_DRBL_2_P1(__n) \
+	(HQM_QSET0_IB_DRBL_2_P1 + (__n) * \
+		(HQM_QSET1_IB_DRBL_2_P1 - HQM_QSET0_IB_DRBL_2_P1))
 
 #define CPE_Q_NUM(__fn, __q) (((__fn) << 2) + (__q))
 #define RME_Q_NUM(__fn, __q) (((__fn) << 2) + (__q))
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/bna/bna_ctrl.c linux-libre-2.6.38-gnu1/drivers/net/bna/bna_ctrl.c
--- linux-libre-2.6.37-gnu1/drivers/net/bna/bna_ctrl.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/bna/bna_ctrl.c	2011-03-14 21:20:32.000000000 -0400
@@ -59,14 +59,70 @@ bna_port_cb_link_down(struct bna_port *p
 	port->link_cbfn(port->bna->bnad, BNA_LINK_DOWN);
 }
 
+static inline int
+llport_can_be_up(struct bna_llport *llport)
+{
+	int ready = 0;
+	if (llport->type == BNA_PORT_T_REGULAR)
+		ready = ((llport->flags & BNA_LLPORT_F_ADMIN_UP) &&
+			 (llport->flags & BNA_LLPORT_F_RX_STARTED) &&
+			 (llport->flags & BNA_LLPORT_F_PORT_ENABLED));
+	else
+		ready = ((llport->flags & BNA_LLPORT_F_ADMIN_UP) &&
+			 (llport->flags & BNA_LLPORT_F_RX_STARTED) &&
+			 !(llport->flags & BNA_LLPORT_F_PORT_ENABLED));
+	return ready;
+}
+
+#define llport_is_up llport_can_be_up
+
+enum bna_llport_event {
+	LLPORT_E_START			= 1,
+	LLPORT_E_STOP			= 2,
+	LLPORT_E_FAIL			= 3,
+	LLPORT_E_UP			= 4,
+	LLPORT_E_DOWN			= 5,
+	LLPORT_E_FWRESP_UP_OK		= 6,
+	LLPORT_E_FWRESP_UP_FAIL		= 7,
+	LLPORT_E_FWRESP_DOWN		= 8
+};
+
+static void
+bna_llport_cb_port_enabled(struct bna_llport *llport)
+{
+	llport->flags |= BNA_LLPORT_F_PORT_ENABLED;
+
+	if (llport_can_be_up(llport))
+		bfa_fsm_send_event(llport, LLPORT_E_UP);
+}
+
+static void
+bna_llport_cb_port_disabled(struct bna_llport *llport)
+{
+	int llport_up = llport_is_up(llport);
+
+	llport->flags &= ~BNA_LLPORT_F_PORT_ENABLED;
+
+	if (llport_up)
+		bfa_fsm_send_event(llport, LLPORT_E_DOWN);
+}
+
 /**
  * MBOX
  */
 static int
 bna_is_aen(u8 msg_id)
 {
-	return msg_id == BFI_LL_I2H_LINK_DOWN_AEN ||
-	       msg_id == BFI_LL_I2H_LINK_UP_AEN;
+	switch (msg_id) {
+	case BFI_LL_I2H_LINK_DOWN_AEN:
+	case BFI_LL_I2H_LINK_UP_AEN:
+	case BFI_LL_I2H_PORT_ENABLE_AEN:
+	case BFI_LL_I2H_PORT_DISABLE_AEN:
+		return 1;
+
+	default:
+		return 0;
+	}
 }
 
 static void
@@ -81,6 +137,12 @@ bna_mbox_aen_callback(struct bna *bna, s
 	case BFI_LL_I2H_LINK_DOWN_AEN:
 		bna_port_cb_link_down(&bna->port, aen->reason);
 		break;
+	case BFI_LL_I2H_PORT_ENABLE_AEN:
+		bna_llport_cb_port_enabled(&bna->port.llport);
+		break;
+	case BFI_LL_I2H_PORT_DISABLE_AEN:
+		bna_llport_cb_port_disabled(&bna->port.llport);
+		break;
 	default:
 		break;
 	}
@@ -251,16 +313,6 @@ static void bna_llport_start(struct bna_
 static void bna_llport_stop(struct bna_llport *llport);
 static void bna_llport_fail(struct bna_llport *llport);
 
-enum bna_llport_event {
-	LLPORT_E_START			= 1,
-	LLPORT_E_STOP			= 2,
-	LLPORT_E_FAIL			= 3,
-	LLPORT_E_UP			= 4,
-	LLPORT_E_DOWN			= 5,
-	LLPORT_E_FWRESP_UP		= 6,
-	LLPORT_E_FWRESP_DOWN		= 7
-};
-
 enum bna_llport_state {
 	BNA_LLPORT_STOPPED		= 1,
 	BNA_LLPORT_DOWN			= 2,
@@ -320,7 +372,7 @@ bna_llport_sm_stopped(struct bna_llport
 		/* No-op */
 		break;
 
-	case LLPORT_E_FWRESP_UP:
+	case LLPORT_E_FWRESP_UP_OK:
 	case LLPORT_E_FWRESP_DOWN:
 		/**
 		 * These events are received due to flushing of mbox when
@@ -366,6 +418,7 @@ bna_llport_sm_down(struct bna_llport *ll
 static void
 bna_llport_sm_up_resp_wait_entry(struct bna_llport *llport)
 {
+	BUG_ON(!llport_can_be_up(llport));
 	/**
 	 * NOTE: Do not call bna_fw_llport_up() here. That will over step
 	 * mbox due to down_resp_wait -> up_resp_wait transition on event
@@ -390,10 +443,14 @@ bna_llport_sm_up_resp_wait(struct bna_ll
 		bfa_fsm_set_state(llport, bna_llport_sm_down_resp_wait);
 		break;
 
-	case LLPORT_E_FWRESP_UP:
+	case LLPORT_E_FWRESP_UP_OK:
 		bfa_fsm_set_state(llport, bna_llport_sm_up);
 		break;
 
+	case LLPORT_E_FWRESP_UP_FAIL:
+		bfa_fsm_set_state(llport, bna_llport_sm_down);
+		break;
+
 	case LLPORT_E_FWRESP_DOWN:
 		/* down_resp_wait -> up_resp_wait transition on LLPORT_E_UP */
 		bna_fw_llport_up(llport);
@@ -431,11 +488,12 @@ bna_llport_sm_down_resp_wait(struct bna_
 		bfa_fsm_set_state(llport, bna_llport_sm_up_resp_wait);
 		break;
 
-	case LLPORT_E_FWRESP_UP:
+	case LLPORT_E_FWRESP_UP_OK:
 		/* up_resp_wait->down_resp_wait transition on LLPORT_E_DOWN */
 		bna_fw_llport_down(llport);
 		break;
 
+	case LLPORT_E_FWRESP_UP_FAIL:
 	case LLPORT_E_FWRESP_DOWN:
 		bfa_fsm_set_state(llport, bna_llport_sm_down);
 		break;
@@ -496,11 +554,12 @@ bna_llport_sm_last_resp_wait(struct bna_
 		/* No-op */
 		break;
 
-	case LLPORT_E_FWRESP_UP:
+	case LLPORT_E_FWRESP_UP_OK:
 		/* up_resp_wait->last_resp_wait transition on LLPORT_T_STOP */
 		bna_fw_llport_down(llport);
 		break;
 
+	case LLPORT_E_FWRESP_UP_FAIL:
 	case LLPORT_E_FWRESP_DOWN:
 		bfa_fsm_set_state(llport, bna_llport_sm_stopped);
 		break;
@@ -541,7 +600,14 @@ bna_fw_cb_llport_up(void *arg, int statu
 	struct bna_llport *llport = (struct bna_llport *)arg;
 
 	bfa_q_qe_init(&llport->mbox_qe.qe);
-	bfa_fsm_send_event(llport, LLPORT_E_FWRESP_UP);
+	if (status == BFI_LL_CMD_FAIL) {
+		if (llport->type == BNA_PORT_T_REGULAR)
+			llport->flags &= ~BNA_LLPORT_F_PORT_ENABLED;
+		else
+			llport->flags &= ~BNA_LLPORT_F_ADMIN_UP;
+		bfa_fsm_send_event(llport, LLPORT_E_FWRESP_UP_FAIL);
+	} else
+		bfa_fsm_send_event(llport, LLPORT_E_FWRESP_UP_OK);
 }
 
 static void
@@ -588,13 +654,14 @@ bna_port_cb_llport_stopped(struct bna_po
 static void
 bna_llport_init(struct bna_llport *llport, struct bna *bna)
 {
-	llport->flags |= BNA_LLPORT_F_ENABLED;
+	llport->flags |= BNA_LLPORT_F_ADMIN_UP;
+	llport->flags |= BNA_LLPORT_F_PORT_ENABLED;
 	llport->type = BNA_PORT_T_REGULAR;
 	llport->bna = bna;
 
 	llport->link_status = BNA_LINK_DOWN;
 
-	llport->admin_up_count = 0;
+	llport->rx_started_count = 0;
 
 	llport->stop_cbfn = NULL;
 
@@ -606,7 +673,8 @@ bna_llport_init(struct bna_llport *llpor
 static void
 bna_llport_uninit(struct bna_llport *llport)
 {
-	llport->flags &= ~BNA_LLPORT_F_ENABLED;
+	llport->flags &= ~BNA_LLPORT_F_ADMIN_UP;
+	llport->flags &= ~BNA_LLPORT_F_PORT_ENABLED;
 
 	llport->bna = NULL;
 }
@@ -628,6 +696,8 @@ bna_llport_stop(struct bna_llport *llpor
 static void
 bna_llport_fail(struct bna_llport *llport)
 {
+	/* Reset the physical port status to enabled */
+	llport->flags |= BNA_LLPORT_F_PORT_ENABLED;
 	bfa_fsm_send_event(llport, LLPORT_E_FAIL);
 }
 
@@ -638,25 +708,31 @@ bna_llport_state_get(struct bna_llport *
 }
 
 void
-bna_llport_admin_up(struct bna_llport *llport)
+bna_llport_rx_started(struct bna_llport *llport)
 {
-	llport->admin_up_count++;
+	llport->rx_started_count++;
 
-	if (llport->admin_up_count == 1) {
-		llport->flags |= BNA_LLPORT_F_RX_ENABLED;
-		if (llport->flags & BNA_LLPORT_F_ENABLED)
+	if (llport->rx_started_count == 1) {
+
+		llport->flags |= BNA_LLPORT_F_RX_STARTED;
+
+		if (llport_can_be_up(llport))
 			bfa_fsm_send_event(llport, LLPORT_E_UP);
 	}
 }
 
 void
-bna_llport_admin_down(struct bna_llport *llport)
+bna_llport_rx_stopped(struct bna_llport *llport)
 {
-	llport->admin_up_count--;
+	int llport_up = llport_is_up(llport);
 
-	if (llport->admin_up_count == 0) {
-		llport->flags &= ~BNA_LLPORT_F_RX_ENABLED;
-		if (llport->flags & BNA_LLPORT_F_ENABLED)
+	llport->rx_started_count--;
+
+	if (llport->rx_started_count == 0) {
+
+		llport->flags &= ~BNA_LLPORT_F_RX_STARTED;
+
+		if (llport_up)
 			bfa_fsm_send_event(llport, LLPORT_E_DOWN);
 	}
 }
@@ -2056,37 +2132,6 @@ rxf_fltr_mbox_cmd(struct bna_rxf *rxf, u
 	bna_mbox_send(rxf->rx->bna, &rxf->mbox_qe);
 }
 
-static void
-__rxf_default_function_config(struct bna_rxf *rxf, enum bna_status status)
-{
-	struct bna_rx_fndb_ram *rx_fndb_ram;
-	u32 ctrl_flags;
-	int i;
-
-	rx_fndb_ram = (struct bna_rx_fndb_ram *)
-			BNA_GET_MEM_BASE_ADDR(rxf->rx->bna->pcidev.pci_bar_kva,
-			RX_FNDB_RAM_BASE_OFFSET);
-
-	for (i = 0; i < BFI_MAX_RXF; i++) {
-		if (status == BNA_STATUS_T_ENABLED) {
-			if (i == rxf->rxf_id)
-				continue;
-
-			ctrl_flags =
-				readl(&rx_fndb_ram[i].control_flags);
-			ctrl_flags |= BNA_RXF_CF_DEFAULT_FUNCTION_ENABLE;
-			writel(ctrl_flags,
-						&rx_fndb_ram[i].control_flags);
-		} else {
-			ctrl_flags =
-				readl(&rx_fndb_ram[i].control_flags);
-			ctrl_flags &= ~BNA_RXF_CF_DEFAULT_FUNCTION_ENABLE;
-			writel(ctrl_flags,
-						&rx_fndb_ram[i].control_flags);
-		}
-	}
-}
-
 int
 rxf_process_packet_filter_ucast(struct bna_rxf *rxf)
 {
@@ -2153,46 +2198,6 @@ rxf_process_packet_filter_promisc(struct
 }
 
 int
-rxf_process_packet_filter_default(struct bna_rxf *rxf)
-{
-	struct bna *bna = rxf->rx->bna;
-
-	/* Enable/disable default mode */
-	if (is_default_enable(rxf->rxmode_pending,
-				rxf->rxmode_pending_bitmask)) {
-		/* move default configuration from pending -> active */
-		default_inactive(rxf->rxmode_pending,
-				rxf->rxmode_pending_bitmask);
-		rxf->rxmode_active |= BNA_RXMODE_DEFAULT;
-
-		/* Disable VLAN filter to allow all VLANs */
-		__rxf_vlan_filter_set(rxf, BNA_STATUS_T_DISABLED);
-		/* Redirect all other RxF vlan filtering to this one */
-		__rxf_default_function_config(rxf, BNA_STATUS_T_ENABLED);
-		rxf_fltr_mbox_cmd(rxf, BFI_LL_H2I_RXF_DEFAULT_SET_REQ,
-				BNA_STATUS_T_ENABLED);
-		return 1;
-	} else if (is_default_disable(rxf->rxmode_pending,
-				rxf->rxmode_pending_bitmask)) {
-		/* move default configuration from pending -> active */
-		default_inactive(rxf->rxmode_pending,
-				rxf->rxmode_pending_bitmask);
-		rxf->rxmode_active &= ~BNA_RXMODE_DEFAULT;
-		bna->rxf_default_id = BFI_MAX_RXF;
-
-		/* Revert VLAN filter */
-		__rxf_vlan_filter_set(rxf, rxf->vlan_filter_status);
-		/* Stop RxF vlan filter table redirection */
-		__rxf_default_function_config(rxf, BNA_STATUS_T_DISABLED);
-		rxf_fltr_mbox_cmd(rxf, BFI_LL_H2I_RXF_DEFAULT_SET_REQ,
-				BNA_STATUS_T_DISABLED);
-		return 1;
-	}
-
-	return 0;
-}
-
-int
 rxf_process_packet_filter_allmulti(struct bna_rxf *rxf)
 {
 	/* Enable/disable allmulti mode */
@@ -2289,48 +2294,6 @@ rxf_clear_packet_filter_promisc(struct b
 }
 
 int
-rxf_clear_packet_filter_default(struct bna_rxf *rxf)
-{
-	struct bna *bna = rxf->rx->bna;
-
-	/* 8. Execute pending default mode disable command */
-	if (is_default_disable(rxf->rxmode_pending,
-				rxf->rxmode_pending_bitmask)) {
-		/* move default configuration from pending -> active */
-		default_inactive(rxf->rxmode_pending,
-				rxf->rxmode_pending_bitmask);
-		rxf->rxmode_active &= ~BNA_RXMODE_DEFAULT;
-		bna->rxf_default_id = BFI_MAX_RXF;
-
-		/* Revert VLAN filter */
-		__rxf_vlan_filter_set(rxf, rxf->vlan_filter_status);
-		/* Stop RxF vlan filter table redirection */
-		__rxf_default_function_config(rxf, BNA_STATUS_T_DISABLED);
-		rxf_fltr_mbox_cmd(rxf, BFI_LL_H2I_RXF_DEFAULT_SET_REQ,
-				BNA_STATUS_T_DISABLED);
-		return 1;
-	}
-
-	/* 9. Clear active default mode; move it to pending enable */
-	if (rxf->rxmode_active & BNA_RXMODE_DEFAULT) {
-		/* move default configuration from active -> pending */
-		default_enable(rxf->rxmode_pending,
-				rxf->rxmode_pending_bitmask);
-		rxf->rxmode_active &= ~BNA_RXMODE_DEFAULT;
-
-		/* Revert VLAN filter */
-		__rxf_vlan_filter_set(rxf, rxf->vlan_filter_status);
-		/* Stop RxF vlan filter table redirection */
-		__rxf_default_function_config(rxf, BNA_STATUS_T_DISABLED);
-		rxf_fltr_mbox_cmd(rxf, BFI_LL_H2I_RXF_DEFAULT_SET_REQ,
-				BNA_STATUS_T_DISABLED);
-		return 1;
-	}
-
-	return 0;
-}
-
-int
 rxf_clear_packet_filter_allmulti(struct bna_rxf *rxf)
 {
 	/* 10. Execute pending allmulti mode disable command */
@@ -2405,28 +2368,6 @@ rxf_reset_packet_filter_promisc(struct b
 }
 
 void
-rxf_reset_packet_filter_default(struct bna_rxf *rxf)
-{
-	struct bna *bna = rxf->rx->bna;
-
-	/* 8. Clear pending default mode disable */
-	if (is_default_disable(rxf->rxmode_pending,
-				rxf->rxmode_pending_bitmask)) {
-		default_inactive(rxf->rxmode_pending,
-				rxf->rxmode_pending_bitmask);
-		rxf->rxmode_active &= ~BNA_RXMODE_DEFAULT;
-		bna->rxf_default_id = BFI_MAX_RXF;
-	}
-
-	/* 9. Move default mode config from active -> pending */
-	if (rxf->rxmode_active & BNA_RXMODE_DEFAULT) {
-		default_enable(rxf->rxmode_pending,
-				rxf->rxmode_pending_bitmask);
-		rxf->rxmode_active &= ~BNA_RXMODE_DEFAULT;
-	}
-}
-
-void
 rxf_reset_packet_filter_allmulti(struct bna_rxf *rxf)
 {
 	/* 10. Clear pending allmulti mode disable */
@@ -2523,76 +2464,6 @@ rxf_promisc_disable(struct bna_rxf *rxf)
  *	1 = need h/w change
  */
 static int
-rxf_default_enable(struct bna_rxf *rxf)
-{
-	struct bna *bna = rxf->rx->bna;
-	int ret = 0;
-
-	/* There can not be any pending disable command */
-
-	/* Do nothing if pending enable or already enabled */
-	if (is_default_enable(rxf->rxmode_pending,
-		rxf->rxmode_pending_bitmask) ||
-		(rxf->rxmode_active & BNA_RXMODE_DEFAULT)) {
-		/* Schedule enable */
-	} else {
-		/* Default mode should not be active in the system */
-		default_enable(rxf->rxmode_pending,
-				rxf->rxmode_pending_bitmask);
-		bna->rxf_default_id = rxf->rxf_id;
-		ret = 1;
-	}
-
-	return ret;
-}
-
-/**
- * Should only be called by bna_rxf_mode_set.
- * Helps deciding if h/w configuration is needed or not.
- *  Returns:
- *	0 = no h/w change
- *	1 = need h/w change
- */
-static int
-rxf_default_disable(struct bna_rxf *rxf)
-{
-	struct bna *bna = rxf->rx->bna;
-	int ret = 0;
-
-	/* There can not be any pending disable */
-
-	/* Turn off pending enable command , if any */
-	if (is_default_enable(rxf->rxmode_pending,
-				rxf->rxmode_pending_bitmask)) {
-		/* Promisc mode should not be active */
-		/* system default state should be pending */
-		default_inactive(rxf->rxmode_pending,
-				rxf->rxmode_pending_bitmask);
-		/* Remove the default state from the system */
-		bna->rxf_default_id = BFI_MAX_RXF;
-
-	/* Schedule disable */
-	} else if (rxf->rxmode_active & BNA_RXMODE_DEFAULT) {
-		/* Default mode should be active in the system */
-		default_disable(rxf->rxmode_pending,
-				rxf->rxmode_pending_bitmask);
-		ret = 1;
-
-	/* Do nothing if already disabled */
-	} else {
-	}
-
-	return ret;
-}
-
-/**
- * Should only be called by bna_rxf_mode_set.
- * Helps deciding if h/w configuration is needed or not.
- *  Returns:
- *	0 = no h/w change
- *	1 = need h/w change
- */
-static int
 rxf_allmulti_enable(struct bna_rxf *rxf)
 {
 	int ret = 0;
@@ -2654,38 +2525,13 @@ bna_rx_mode_set(struct bna_rx *rx, enum
 	struct bna_rxf *rxf = &rx->rxf;
 	int need_hw_config = 0;
 
-	/* Error checks */
+	/* Process the commands */
 
 	if (is_promisc_enable(new_mode, bitmask)) {
 		/* If promisc mode is already enabled elsewhere in the system */
 		if ((rx->bna->rxf_promisc_id != BFI_MAX_RXF) &&
 			(rx->bna->rxf_promisc_id != rxf->rxf_id))
 			goto err_return;
-
-		/* If default mode is already enabled in the system */
-		if (rx->bna->rxf_default_id != BFI_MAX_RXF)
-			goto err_return;
-
-		/* Trying to enable promiscuous and default mode together */
-		if (is_default_enable(new_mode, bitmask))
-			goto err_return;
-	}
-
-	if (is_default_enable(new_mode, bitmask)) {
-		/* If default mode is already enabled elsewhere in the system */
-		if ((rx->bna->rxf_default_id != BFI_MAX_RXF) &&
-			(rx->bna->rxf_default_id != rxf->rxf_id)) {
-				goto err_return;
-		}
-
-		/* If promiscuous mode is already enabled in the system */
-		if (rx->bna->rxf_promisc_id != BFI_MAX_RXF)
-			goto err_return;
-	}
-
-	/* Process the commands */
-
-	if (is_promisc_enable(new_mode, bitmask)) {
 		if (rxf_promisc_enable(rxf))
 			need_hw_config = 1;
 	} else if (is_promisc_disable(new_mode, bitmask)) {
@@ -2693,14 +2539,6 @@ bna_rx_mode_set(struct bna_rx *rx, enum
 			need_hw_config = 1;
 	}
 
-	if (is_default_enable(new_mode, bitmask)) {
-		if (rxf_default_enable(rxf))
-			need_hw_config = 1;
-	} else if (is_default_disable(new_mode, bitmask)) {
-		if (rxf_default_disable(rxf))
-			need_hw_config = 1;
-	}
-
 	if (is_allmulti_enable(new_mode, bitmask)) {
 		if (rxf_allmulti_enable(rxf))
 			need_hw_config = 1;
@@ -3126,7 +2964,6 @@ bna_init(struct bna *bna, struct bnad *b
 
 	bna_mcam_mod_init(&bna->mcam_mod, bna, res_info);
 
-	bna->rxf_default_id = BFI_MAX_RXF;
 	bna->rxf_promisc_id = BFI_MAX_RXF;
 
 	/* Mbox q element for posting stat request to f/w */
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/bna/bnad.c linux-libre-2.6.38-gnu1/drivers/net/bna/bnad.c
--- linux-libre-2.6.37-gnu1/drivers/net/bna/bnad.c	2013-05-03 03:57:49.000000000 -0400
+++ linux-libre-2.6.38-gnu1/drivers/net/bna/bnad.c	2013-05-03 01:57:47.000000000 -0400
@@ -70,6 +70,8 @@ do {								\
 	(sizeof(struct bnad_skb_unmap) * ((_depth) - 1));	\
 } while (0)
 
+#define BNAD_TXRX_SYNC_MDELAY	250	/* 250 msecs */
+
 /*
  * Reinitialize completions in CQ, once Rx is taken down
  */
@@ -107,7 +109,7 @@ static void
 bnad_free_all_txbufs(struct bnad *bnad,
 		 struct bna_tcb *tcb)
 {
-	u16 		unmap_cons;
+	u32 		unmap_cons;
 	struct bnad_unmap_q *unmap_q = tcb->unmap_q;
 	struct bnad_skb_unmap *unmap_array;
 	struct sk_buff 		*skb = NULL;
@@ -130,7 +132,9 @@ bnad_free_all_txbufs(struct bnad *bnad,
 						PCI_DMA_TODEVICE);
 
 		pci_unmap_addr_set(&unmap_array[unmap_cons], dma_addr, 0);
-		unmap_cons++;
+		if (++unmap_cons >= unmap_q->q_depth)
+			break;
+
 		for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
 			pci_unmap_page(bnad->pcidev,
 				       pci_unmap_addr(&unmap_array[unmap_cons],
@@ -139,7 +143,8 @@ bnad_free_all_txbufs(struct bnad *bnad,
 				       PCI_DMA_TODEVICE);
 			pci_unmap_addr_set(&unmap_array[unmap_cons], dma_addr,
 					   0);
-			unmap_cons++;
+			if (++unmap_cons >= unmap_q->q_depth)
+				break;
 		}
 		dev_kfree_skb_any(skb);
 	}
@@ -167,11 +172,11 @@ bnad_free_txbufs(struct bnad *bnad,
 	/*
 	 * Just return if TX is stopped. This check is useful
 	 * when bnad_free_txbufs() runs out of a tasklet scheduled
-	 * before bnad_cb_tx_cleanup() cleared BNAD_RF_TX_STARTED bit
+	 * before bnad_cb_tx_cleanup() cleared BNAD_TXQ_TX_STARTED bit
 	 * but this routine runs actually after the cleanup has been
 	 * executed.
 	 */
-	if (!test_bit(BNAD_RF_TX_STARTED, &bnad->run_flags))
+	if (!test_bit(BNAD_TXQ_TX_STARTED, &tcb->flags))
 		return 0;
 
 	updated_hw_cons = *(tcb->hw_consumer_index);
@@ -239,7 +244,7 @@ bnad_tx_free_tasklet(unsigned long bnad_
 {
 	struct bnad *bnad = (struct bnad *)bnad_ptr;
 	struct bna_tcb *tcb;
-	u32 		acked;
+	u32 		acked = 0;
 	int			i, j;
 
 	for (i = 0; i < bnad->num_tx; i++) {
@@ -252,10 +257,26 @@ bnad_tx_free_tasklet(unsigned long bnad_
 				(!test_and_set_bit(BNAD_TXQ_FREE_SENT,
 						  &tcb->flags))) {
 				acked = bnad_free_txbufs(bnad, tcb);
-				bna_ib_ack(tcb->i_dbell, acked);
+				if (likely(test_bit(BNAD_TXQ_TX_STARTED,
+					&tcb->flags)))
+					bna_ib_ack(tcb->i_dbell, acked);
 				smp_mb__before_clear_bit();
 				clear_bit(BNAD_TXQ_FREE_SENT, &tcb->flags);
 			}
+			if (unlikely(!test_bit(BNAD_TXQ_TX_STARTED,
+						&tcb->flags)))
+				continue;
+			if (netif_queue_stopped(bnad->netdev)) {
+				if (acked && netif_carrier_ok(bnad->netdev) &&
+					BNA_QE_FREE_CNT(tcb, tcb->q_depth) >=
+						BNAD_NETIF_WAKE_THRESHOLD) {
+					netif_wake_queue(bnad->netdev);
+					/* TODO */
+					/* Counters for individual TxQs? */
+					BNAD_UPDATE_CTR(bnad,
+						netif_queue_wakeup);
+				}
+			}
 		}
 	}
 }
@@ -264,7 +285,7 @@ static u32
 bnad_tx(struct bnad *bnad, struct bna_tcb *tcb)
 {
 	struct net_device *netdev = bnad->netdev;
-	u32 sent;
+	u32 sent = 0;
 
 	if (test_and_set_bit(BNAD_TXQ_FREE_SENT, &tcb->flags))
 		return 0;
@@ -275,12 +296,15 @@ bnad_tx(struct bnad *bnad, struct bna_tc
 		    netif_carrier_ok(netdev) &&
 		    BNA_QE_FREE_CNT(tcb, tcb->q_depth) >=
 				    BNAD_NETIF_WAKE_THRESHOLD) {
-			netif_wake_queue(netdev);
-			BNAD_UPDATE_CTR(bnad, netif_queue_wakeup);
+			if (test_bit(BNAD_TXQ_TX_STARTED, &tcb->flags)) {
+				netif_wake_queue(netdev);
+				BNAD_UPDATE_CTR(bnad, netif_queue_wakeup);
+			}
 		}
+	}
+
+	if (likely(test_bit(BNAD_TXQ_TX_STARTED, &tcb->flags)))
 		bna_ib_ack(tcb->i_dbell, sent);
-	} else
-		bna_ib_ack(tcb->i_dbell, 0);
 
 	smp_mb__before_clear_bit();
 	clear_bit(BNAD_TXQ_FREE_SENT, &tcb->flags);
@@ -313,25 +337,24 @@ bnad_reset_rcb(struct bnad *bnad, struct
 }
 
 static void
-bnad_free_rxbufs(struct bnad *bnad, struct bna_rcb *rcb)
+bnad_free_all_rxbufs(struct bnad *bnad, struct bna_rcb *rcb)
 {
 	struct bnad_unmap_q *unmap_q;
 	struct sk_buff *skb;
+	int unmap_cons;
 
 	unmap_q = rcb->unmap_q;
-	while (BNA_QE_IN_USE_CNT(unmap_q, unmap_q->q_depth)) {
-		skb = unmap_q->unmap_array[unmap_q->consumer_index].skb;
-		BUG_ON(!(skb));
-		unmap_q->unmap_array[unmap_q->consumer_index].skb = NULL;
+	for (unmap_cons = 0; unmap_cons < unmap_q->q_depth; unmap_cons++) {
+		skb = unmap_q->unmap_array[unmap_cons].skb;
+		if (!skb)
+			continue;
+		unmap_q->unmap_array[unmap_cons].skb = NULL;
 		pci_unmap_single(bnad->pcidev, pci_unmap_addr(&unmap_q->
-					unmap_array[unmap_q->consumer_index],
-					dma_addr), rcb->rxq->buffer_size +
-					NET_IP_ALIGN, PCI_DMA_FROMDEVICE);
+					unmap_array[unmap_cons],
+					dma_addr), rcb->rxq->buffer_size,
+					PCI_DMA_FROMDEVICE);
 		dev_kfree_skb(skb);
-		BNA_QE_INDX_ADD(unmap_q->consumer_index, 1, unmap_q->q_depth);
-		BNA_QE_INDX_ADD(rcb->consumer_index, 1, rcb->q_depth);
 	}
-
 	bnad_reset_rcb(bnad, rcb);
 }
 
@@ -385,41 +408,9 @@ finishing:
 		unmap_q->producer_index = unmap_prod;
 		rcb->producer_index = unmap_prod;
 		smp_mb();
-		bna_rxq_prod_indx_doorbell(rcb);
-	}
-}
-
-/*
- * Locking is required in the enable path
- * because it is called from a napi poll
- * context, where the bna_lock is not held
- * unlike the IRQ context.
- */
-static void
-bnad_enable_txrx_irqs(struct bnad *bnad)
-{
-	struct bna_tcb *tcb;
-	struct bna_ccb *ccb;
-	int i, j;
-	unsigned long flags;
-
-	spin_lock_irqsave(&bnad->bna_lock, flags);
-	for (i = 0; i < bnad->num_tx; i++) {
-		for (j = 0; j < bnad->num_txq_per_tx; j++) {
-			tcb = bnad->tx_info[i].tcb[j];
-			bna_ib_coalescing_timer_set(tcb->i_dbell,
-				tcb->txq->ib->ib_config.coalescing_timeo);
-			bna_ib_ack(tcb->i_dbell, 0);
-		}
-	}
-
-	for (i = 0; i < bnad->num_rx; i++) {
-		for (j = 0; j < bnad->num_rxp_per_rx; j++) {
-			ccb = bnad->rx_info[i].rx_ctrl[j].ccb;
-			bnad_enable_rx_irq_unsafe(ccb);
-		}
+		if (likely(test_bit(BNAD_RXQ_STARTED, &rcb->flags)))
+			bna_rxq_prod_indx_doorbell(rcb);
 	}
-	spin_unlock_irqrestore(&bnad->bna_lock, flags);
 }
 
 static inline void
@@ -448,6 +439,9 @@ bnad_poll_cq(struct bnad *bnad, struct b
 	u32 qid0 = ccb->rcb[0]->rxq->rxq_id;
 	struct bna_pkt_rate *pkt_rt = &ccb->pkt_rate;
 
+	if (!test_bit(BNAD_RXQ_STARTED, &ccb->rcb[0]->flags))
+		return 0;
+
 	prefetch(bnad->netdev);
 	BNA_CQ_QPGE_PTR_GET(ccb->producer_index, ccb->sw_qpt, cmpl,
 			    wi_range);
@@ -544,12 +538,15 @@ next:
 	BNA_QE_INDX_ADD(ccb->producer_index, wis, ccb->q_depth);
 
 	if (likely(ccb)) {
-		bna_ib_ack(ccb->i_dbell, packets);
+		if (likely(test_bit(BNAD_RXQ_STARTED, &ccb->rcb[0]->flags)))
+			bna_ib_ack(ccb->i_dbell, packets);
 		bnad_refill_rxq(bnad, ccb->rcb[0]);
 		if (ccb->rcb[1])
 			bnad_refill_rxq(bnad, ccb->rcb[1]);
-	} else
-		bna_ib_ack(ccb->i_dbell, 0);
+	} else {
+		if (likely(test_bit(BNAD_RXQ_STARTED, &ccb->rcb[0]->flags)))
+			bna_ib_ack(ccb->i_dbell, 0);
+	}
 
 	return packets;
 }
@@ -557,6 +554,9 @@ next:
 static void
 bnad_disable_rx_irq(struct bnad *bnad, struct bna_ccb *ccb)
 {
+	if (unlikely(!test_bit(BNAD_RXQ_STARTED, &ccb->rcb[0]->flags)))
+		return;
+
 	bna_ib_coalescing_timer_set(ccb->i_dbell, 0);
 	bna_ib_ack(ccb->i_dbell, 0);
 }
@@ -566,7 +566,8 @@ bnad_enable_rx_irq(struct bnad *bnad, st
 {
 	unsigned long flags;
 
-	spin_lock_irqsave(&bnad->bna_lock, flags); /* Because of polling context */
+	/* Because of polling context */
+	spin_lock_irqsave(&bnad->bna_lock, flags);
 	bnad_enable_rx_irq_unsafe(ccb);
 	spin_unlock_irqrestore(&bnad->bna_lock, flags);
 }
@@ -575,9 +576,11 @@ static void
 bnad_netif_rx_schedule_poll(struct bnad *bnad, struct bna_ccb *ccb)
 {
 	struct bnad_rx_ctrl *rx_ctrl = (struct bnad_rx_ctrl *)(ccb->ctrl);
-	if (likely(napi_schedule_prep((&rx_ctrl->napi)))) {
+	struct napi_struct *napi = &rx_ctrl->napi;
+
+	if (likely(napi_schedule_prep(napi))) {
 		bnad_disable_rx_irq(bnad, ccb);
-		__napi_schedule((&rx_ctrl->napi));
+		__napi_schedule(napi);
 	}
 	BNAD_UPDATE_CTR(bnad, netif_rx_schedule);
 }
@@ -602,12 +605,11 @@ bnad_msix_mbox_handler(int irq, void *da
 {
 	u32 intr_status;
 	unsigned long flags;
-	struct net_device *netdev = data;
-	struct bnad *bnad;
+	struct bnad *bnad = (struct bnad *)data;
 
-	bnad = netdev_priv(netdev);
+	if (unlikely(test_bit(BNAD_RF_MBOX_IRQ_DISABLED, &bnad->run_flags)))
+		return IRQ_HANDLED;
 
-	/* BNA_ISR_GET(bnad); Inc Ref count */
 	spin_lock_irqsave(&bnad->bna_lock, flags);
 
 	bna_intr_status_get(&bnad->bna, intr_status);
@@ -617,7 +619,6 @@ bnad_msix_mbox_handler(int irq, void *da
 
 	spin_unlock_irqrestore(&bnad->bna_lock, flags);
 
-	/* BNAD_ISR_PUT(bnad); Dec Ref count */
 	return IRQ_HANDLED;
 }
 
@@ -627,8 +628,7 @@ bnad_isr(int irq, void *data)
 	int i, j;
 	u32 intr_status;
 	unsigned long flags;
-	struct net_device *netdev = data;
-	struct bnad *bnad = netdev_priv(netdev);
+	struct bnad *bnad = (struct bnad *)data;
 	struct bnad_rx_info *rx_info;
 	struct bnad_rx_ctrl *rx_ctrl;
 
@@ -642,16 +642,21 @@ bnad_isr(int irq, void *data)
 
 	spin_lock_irqsave(&bnad->bna_lock, flags);
 
-	if (BNA_IS_MBOX_ERR_INTR(intr_status)) {
+	if (BNA_IS_MBOX_ERR_INTR(intr_status))
 		bna_mbox_handler(&bnad->bna, intr_status);
-		if (!BNA_IS_INTX_DATA_INTR(intr_status)) {
-			spin_unlock_irqrestore(&bnad->bna_lock, flags);
-			goto done;
-		}
-	}
+
 	spin_unlock_irqrestore(&bnad->bna_lock, flags);
 
+	if (!BNA_IS_INTX_DATA_INTR(intr_status))
+		return IRQ_HANDLED;
+
 	/* Process data interrupts */
+	/* Tx processing */
+	for (i = 0; i < bnad->num_tx; i++) {
+		for (j = 0; j < bnad->num_txq_per_tx; j++)
+			bnad_tx(bnad, bnad->tx_info[i].tcb[j]);
+	}
+	/* Rx processing */
 	for (i = 0; i < bnad->num_rx; i++) {
 		rx_info = &bnad->rx_info[i];
 		if (!rx_info->rx)
@@ -663,7 +668,6 @@ bnad_isr(int irq, void *data)
 							    rx_ctrl->ccb);
 		}
 	}
-done:
 	return IRQ_HANDLED;
 }
 
@@ -674,11 +678,7 @@ done:
 static void
 bnad_enable_mbox_irq(struct bnad *bnad)
 {
-	int irq = BNAD_GET_MBOX_IRQ(bnad);
-
-	if (test_and_clear_bit(BNAD_RF_MBOX_IRQ_DISABLED, &bnad->run_flags))
-		if (bnad->cfg_flags & BNAD_CF_MSIX)
-			enable_irq(irq);
+	clear_bit(BNAD_RF_MBOX_IRQ_DISABLED, &bnad->run_flags);
 
 	BNAD_UPDATE_CTR(bnad, mbox_intr_enabled);
 }
@@ -690,14 +690,19 @@ bnad_enable_mbox_irq(struct bnad *bnad)
 static void
 bnad_disable_mbox_irq(struct bnad *bnad)
 {
-	int irq = BNAD_GET_MBOX_IRQ(bnad);
+	set_bit(BNAD_RF_MBOX_IRQ_DISABLED, &bnad->run_flags);
 
+	BNAD_UPDATE_CTR(bnad, mbox_intr_disabled);
+}
 
-	if (!test_and_set_bit(BNAD_RF_MBOX_IRQ_DISABLED, &bnad->run_flags))
-		if (bnad->cfg_flags & BNAD_CF_MSIX)
-			disable_irq_nosync(irq);
+static void
+bnad_set_netdev_perm_addr(struct bnad *bnad)
+{
+	struct net_device *netdev = bnad->netdev;
 
-	BNAD_UPDATE_CTR(bnad, mbox_intr_disabled);
+	memcpy(netdev->perm_addr, &bnad->perm_addr, netdev->addr_len);
+	if (is_zero_ether_addr(netdev->dev_addr))
+		memcpy(netdev->dev_addr, &bnad->perm_addr, netdev->addr_len);
 }
 
 /* Control Path Handlers */
@@ -755,11 +760,14 @@ bnad_cb_port_link_status(struct bnad *bn
 
 	if (link_up) {
 		if (!netif_carrier_ok(bnad->netdev)) {
+			struct bna_tcb *tcb = bnad->tx_info[0].tcb[0];
+			if (!tcb)
+				return;
 			pr_warn("bna: %s link up\n",
 				bnad->netdev->name);
 			netif_carrier_on(bnad->netdev);
 			BNAD_UPDATE_CTR(bnad, link_toggle);
-			if (test_bit(BNAD_RF_TX_STARTED, &bnad->run_flags)) {
+			if (test_bit(BNAD_TXQ_TX_STARTED, &tcb->flags)) {
 				/* Force an immediate Transmit Schedule */
 				pr_info("bna: %s TX_STARTED\n",
 					bnad->netdev->name);
@@ -807,6 +815,18 @@ bnad_cb_tcb_destroy(struct bnad *bnad, s
 {
 	struct bnad_tx_info *tx_info =
 			(struct bnad_tx_info *)tcb->txq->tx->priv;
+	struct bnad_unmap_q *unmap_q = tcb->unmap_q;
+
+	while (test_and_set_bit(BNAD_TXQ_FREE_SENT, &tcb->flags))
+		cpu_relax();
+
+	bnad_free_all_txbufs(bnad, tcb);
+
+	unmap_q->producer_index = 0;
+	unmap_q->consumer_index = 0;
+
+	smp_mb__before_clear_bit();
+	clear_bit(BNAD_TXQ_FREE_SENT, &tcb->flags);
 
 	tx_info->tcb[tcb->id] = NULL;
 }
@@ -822,6 +842,12 @@ bnad_cb_rcb_setup(struct bnad *bnad, str
 }
 
 static void
+bnad_cb_rcb_destroy(struct bnad *bnad, struct bna_rcb *rcb)
+{
+	bnad_free_all_rxbufs(bnad, rcb);
+}
+
+static void
 bnad_cb_ccb_setup(struct bnad *bnad, struct bna_ccb *ccb)
 {
 	struct bnad_rx_info *rx_info =
@@ -849,7 +875,7 @@ bnad_cb_tx_stall(struct bnad *bnad, stru
 	if (tx_info != &bnad->tx_info[0])
 		return;
 
-	clear_bit(BNAD_RF_TX_STARTED, &bnad->run_flags);
+	clear_bit(BNAD_TXQ_TX_STARTED, &tcb->flags);
 	netif_stop_queue(bnad->netdev);
 	pr_info("bna: %s TX_STOPPED\n", bnad->netdev->name);
 }
@@ -857,30 +883,15 @@ bnad_cb_tx_stall(struct bnad *bnad, stru
 static void
 bnad_cb_tx_resume(struct bnad *bnad, struct bna_tcb *tcb)
 {
-	if (test_and_set_bit(BNAD_RF_TX_STARTED, &bnad->run_flags))
-		return;
-
-	if (netif_carrier_ok(bnad->netdev)) {
-		pr_info("bna: %s TX_STARTED\n", bnad->netdev->name);
-		netif_wake_queue(bnad->netdev);
-		BNAD_UPDATE_CTR(bnad, netif_queue_wakeup);
-	}
-}
-
-static void
-bnad_cb_tx_cleanup(struct bnad *bnad, struct bna_tcb *tcb)
-{
-	struct bnad_unmap_q *unmap_q;
+	struct bnad_unmap_q *unmap_q = tcb->unmap_q;
 
-	if (!tcb || (!tcb->unmap_q))
+	if (test_bit(BNAD_TXQ_TX_STARTED, &tcb->flags))
 		return;
 
-	unmap_q = tcb->unmap_q;
-	if (!unmap_q->unmap_array)
-		return;
+	clear_bit(BNAD_RF_TX_SHUTDOWN_DELAYED, &bnad->run_flags);
 
-	if (test_and_set_bit(BNAD_TXQ_FREE_SENT, &tcb->flags))
-		return;
+	while (test_and_set_bit(BNAD_TXQ_FREE_SENT, &tcb->flags))
+		cpu_relax();
 
 	bnad_free_all_txbufs(bnad, tcb);
 
@@ -889,21 +900,45 @@ bnad_cb_tx_cleanup(struct bnad *bnad, st
 
 	smp_mb__before_clear_bit();
 	clear_bit(BNAD_TXQ_FREE_SENT, &tcb->flags);
+
+	/*
+	 * Workaround for first device enable failure & we
+	 * get a 0 MAC address. We try to get the MAC address
+	 * again here.
+	 */
+	if (is_zero_ether_addr(&bnad->perm_addr.mac[0])) {
+		bna_port_mac_get(&bnad->bna.port, &bnad->perm_addr);
+		bnad_set_netdev_perm_addr(bnad);
+	}
+
+	set_bit(BNAD_TXQ_TX_STARTED, &tcb->flags);
+
+	if (netif_carrier_ok(bnad->netdev)) {
+		pr_info("bna: %s TX_STARTED\n", bnad->netdev->name);
+		netif_wake_queue(bnad->netdev);
+		BNAD_UPDATE_CTR(bnad, netif_queue_wakeup);
+	}
+}
+
+static void
+bnad_cb_tx_cleanup(struct bnad *bnad, struct bna_tcb *tcb)
+{
+	/* Delay only once for the whole Tx Path Shutdown */
+	if (!test_and_set_bit(BNAD_RF_TX_SHUTDOWN_DELAYED, &bnad->run_flags))
+		mdelay(BNAD_TXRX_SYNC_MDELAY);
 }
 
 static void
 bnad_cb_rx_cleanup(struct bnad *bnad,
 			struct bna_ccb *ccb)
 {
-	bnad_cq_cmpl_init(bnad, ccb);
-
-	bnad_free_rxbufs(bnad, ccb->rcb[0]);
 	clear_bit(BNAD_RXQ_STARTED, &ccb->rcb[0]->flags);
 
-	if (ccb->rcb[1]) {
-		bnad_free_rxbufs(bnad, ccb->rcb[1]);
+	if (ccb->rcb[1])
 		clear_bit(BNAD_RXQ_STARTED, &ccb->rcb[1]->flags);
-	}
+
+	if (!test_and_set_bit(BNAD_RF_RX_SHUTDOWN_DELAYED, &bnad->run_flags))
+		mdelay(BNAD_TXRX_SYNC_MDELAY);
 }
 
 static void
@@ -911,6 +946,13 @@ bnad_cb_rx_post(struct bnad *bnad, struc
 {
 	struct bnad_unmap_q *unmap_q = rcb->unmap_q;
 
+	clear_bit(BNAD_RF_RX_SHUTDOWN_DELAYED, &bnad->run_flags);
+
+	if (rcb == rcb->cq->ccb->rcb[0])
+		bnad_cq_cmpl_init(bnad, rcb->cq->ccb);
+
+	bnad_free_all_rxbufs(bnad, rcb);
+
 	set_bit(BNAD_RXQ_STARTED, &rcb->flags);
 
 	/* Now allocate & post buffers for this RCB */
@@ -1047,7 +1089,7 @@ bnad_mbox_irq_free(struct bnad *bnad,
 	spin_unlock_irqrestore(&bnad->bna_lock, flags);
 
 	irq = BNAD_GET_MBOX_IRQ(bnad);
-	free_irq(irq, bnad->netdev);
+	free_irq(irq, bnad);
 
 	kfree(intr_info->idl);
 }
@@ -1061,7 +1103,7 @@ static int
 bnad_mbox_irq_alloc(struct bnad *bnad,
 		    struct bna_intr_info *intr_info)
 {
-	int 		err;
+	int 		err = 0;
 	unsigned long 	flags;
 	u32	irq;
 	irq_handler_t 	irq_handler;
@@ -1096,22 +1138,17 @@ bnad_mbox_irq_alloc(struct bnad *bnad,
 	 */
 	set_bit(BNAD_RF_MBOX_IRQ_DISABLED, &bnad->run_flags);
 
+	BNAD_UPDATE_CTR(bnad, mbox_intr_disabled);
+
 	err = request_irq(irq, irq_handler, flags,
-			  bnad->mbox_irq_name, bnad->netdev);
+			  bnad->mbox_irq_name, bnad);
 
 	if (err) {
 		kfree(intr_info->idl);
 		intr_info->idl = NULL;
-		return err;
 	}
 
-	spin_lock_irqsave(&bnad->bna_lock, flags);
-
-	if (bnad->cfg_flags & BNAD_CF_MSIX)
-		disable_irq_nosync(irq);
-
-	spin_unlock_irqrestore(&bnad->bna_lock, flags);
-	return 0;
+	return err;
 }
 
 static void
@@ -1388,13 +1425,24 @@ bnad_ioc_hb_check(unsigned long data)
 }
 
 static void
-bnad_ioc_sem_timeout(unsigned long data)
+bnad_iocpf_timeout(unsigned long data)
 {
 	struct bnad *bnad = (struct bnad *)data;
 	unsigned long flags;
 
 	spin_lock_irqsave(&bnad->bna_lock, flags);
-	bfa_nw_ioc_sem_timeout((void *) &bnad->bna.device.ioc);
+	bfa_nw_iocpf_timeout((void *) &bnad->bna.device.ioc);
+	spin_unlock_irqrestore(&bnad->bna_lock, flags);
+}
+
+static void
+bnad_iocpf_sem_timeout(unsigned long data)
+{
+	struct bnad *bnad = (struct bnad *)data;
+	unsigned long flags;
+
+	spin_lock_irqsave(&bnad->bna_lock, flags);
+	bfa_nw_iocpf_sem_timeout((void *) &bnad->bna.device.ioc);
 	spin_unlock_irqrestore(&bnad->bna_lock, flags);
 }
 
@@ -1555,62 +1603,19 @@ poll_exit:
 	return rcvd;
 }
 
-static int
-bnad_napi_poll_txrx(struct napi_struct *napi, int budget)
-{
-	struct bnad_rx_ctrl *rx_ctrl =
-		container_of(napi, struct bnad_rx_ctrl, napi);
-	struct bna_ccb *ccb;
-	struct bnad *bnad;
-	int 			rcvd = 0;
-	int			i, j;
-
-	ccb = rx_ctrl->ccb;
-
-	bnad = ccb->bnad;
-
-	if (!netif_carrier_ok(bnad->netdev))
-		goto poll_exit;
-
-	/* Handle Tx Completions, if any */
-	for (i = 0; i < bnad->num_tx; i++) {
-		for (j = 0; j < bnad->num_txq_per_tx; j++)
-			bnad_tx(bnad, bnad->tx_info[i].tcb[j]);
-	}
-
-	/* Handle Rx Completions */
-	rcvd = bnad_poll_cq(bnad, ccb, budget);
-	if (rcvd == budget)
-		return rcvd;
-poll_exit:
-	napi_complete((napi));
-
-	BNAD_UPDATE_CTR(bnad, netif_rx_complete);
-
-	bnad_enable_txrx_irqs(bnad);
-	return rcvd;
-}
-
 static void
 bnad_napi_enable(struct bnad *bnad, u32 rx_id)
 {
-	int (*napi_poll) (struct napi_struct *, int);
 	struct bnad_rx_ctrl *rx_ctrl;
 	int i;
-	unsigned long flags;
-
-	spin_lock_irqsave(&bnad->bna_lock, flags);
-	if (bnad->cfg_flags & BNAD_CF_MSIX)
-		napi_poll = bnad_napi_poll_rx;
-	else
-		napi_poll = bnad_napi_poll_txrx;
-	spin_unlock_irqrestore(&bnad->bna_lock, flags);
 
 	/* Initialize & enable NAPI */
 	for (i = 0; i <	bnad->num_rxp_per_rx; i++) {
 		rx_ctrl = &bnad->rx_info[rx_id].rx_ctrl[i];
+
 		netif_napi_add(bnad->netdev, &rx_ctrl->napi,
-			       napi_poll, 64);
+			       bnad_napi_poll_rx, 64);
+
 		napi_enable(&rx_ctrl->napi);
 	}
 }
@@ -1825,6 +1830,7 @@ bnad_setup_rx(struct bnad *bnad, uint rx
 
 	/* Initialize the Rx event handlers */
 	rx_cbfn.rcb_setup_cbfn = bnad_cb_rcb_setup;
+	rx_cbfn.rcb_destroy_cbfn = bnad_cb_rcb_destroy;
 	rx_cbfn.rcb_destroy_cbfn = NULL;
 	rx_cbfn.ccb_setup_cbfn = bnad_cb_ccb_setup;
 	rx_cbfn.ccb_destroy_cbfn = bnad_cb_ccb_destroy;
@@ -1968,6 +1974,27 @@ bnad_enable_default_bcast(struct bnad *b
 	return 0;
 }
 
+/* Called with bnad_conf_lock() held */
+static void
+bnad_restore_vlans(struct bnad *bnad, u32 rx_id)
+{
+	u16 vlan_id;
+	unsigned long flags;
+
+	if (!bnad->vlan_grp)
+		return;
+
+	BUG_ON(!(VLAN_N_VID == (BFI_MAX_VLAN + 1)));
+
+	for (vlan_id = 0; vlan_id < VLAN_N_VID; vlan_id++) {
+		if (!vlan_group_get_device(bnad->vlan_grp, vlan_id))
+			continue;
+		spin_lock_irqsave(&bnad->bna_lock, flags);
+		bna_rx_vlan_add(bnad->rx_info[rx_id].rx, vlan_id);
+		spin_unlock_irqrestore(&bnad->bna_lock, flags);
+	}
+}
+
 /* Statistics utilities */
 void
 bnad_netdev_qstats_fill(struct bnad *bnad, struct rtnl_link_stats64 *stats)
@@ -2152,16 +2179,6 @@ bnad_q_num_adjust(struct bnad *bnad, int
 		bnad->num_rxp_per_rx = 1;
 }
 
-static void
-bnad_set_netdev_perm_addr(struct bnad *bnad)
-{
-	struct net_device *netdev = bnad->netdev;
-
-	memcpy(netdev->perm_addr, &bnad->perm_addr, netdev->addr_len);
-	if (is_zero_ether_addr(netdev->dev_addr))
-		memcpy(netdev->dev_addr, &bnad->perm_addr, netdev->addr_len);
-}
-
 /* Enable / disable device */
 static void
 bnad_device_disable(struct bnad *bnad)
@@ -2353,6 +2370,9 @@ bnad_open(struct net_device *netdev)
 	/* Enable broadcast */
 	bnad_enable_default_bcast(bnad);
 
+	/* Restore VLANs, if any */
+	bnad_restore_vlans(bnad, 0);
+
 	/* Set the UCAST address */
 	spin_lock_irqsave(&bnad->bna_lock, flags);
 	bnad_mac_addr_set_locked(bnad, netdev->dev_addr);
@@ -2433,21 +2453,21 @@ bnad_start_xmit(struct sk_buff *skb, str
 		return NETDEV_TX_OK;
 	}
 
+	tx_id = 0;
+
+	tx_info = &bnad->tx_info[tx_id];
+	tcb = tx_info->tcb[tx_id];
+	unmap_q = tcb->unmap_q;
+
 	/*
 	 * Takes care of the Tx that is scheduled between clearing the flag
 	 * and the netif_stop_queue() call.
 	 */
-	if (unlikely(!test_bit(BNAD_RF_TX_STARTED, &bnad->run_flags))) {
+	if (unlikely(!test_bit(BNAD_TXQ_TX_STARTED, &tcb->flags))) {
 		dev_kfree_skb(skb);
 		return NETDEV_TX_OK;
 	}
 
-	tx_id = 0;
-
-	tx_info = &bnad->tx_info[tx_id];
-	tcb = tx_info->tcb[tx_id];
-	unmap_q = tcb->unmap_q;
-
 	vectors = 1 + skb_shinfo(skb)->nr_frags;
 	if (vectors > BFI_TX_MAX_VECTORS_PER_PKT) {
 		dev_kfree_skb(skb);
@@ -2462,7 +2482,8 @@ bnad_start_xmit(struct sk_buff *skb, str
 		    tcb->consumer_index &&
 		    !test_and_set_bit(BNAD_TXQ_FREE_SENT, &tcb->flags)) {
 			acked = bnad_free_txbufs(bnad, tcb);
-			bna_ib_ack(tcb->i_dbell, acked);
+			if (likely(test_bit(BNAD_TXQ_TX_STARTED, &tcb->flags)))
+				bna_ib_ack(tcb->i_dbell, acked);
 			smp_mb__before_clear_bit();
 			clear_bit(BNAD_TXQ_FREE_SENT, &tcb->flags);
 		} else {
@@ -2624,6 +2645,10 @@ bnad_start_xmit(struct sk_buff *skb, str
 	tcb->producer_index = txq_prod;
 
 	smp_mb();
+
+	if (unlikely(!test_bit(BNAD_TXQ_TX_STARTED, &tcb->flags)))
+		return NETDEV_TX_OK;
+
 	bna_txq_prod_indx_doorbell(tcb);
 
 	if ((u16) (*tcb->hw_consumer_index) != tcb->consumer_index)
@@ -3032,7 +3057,7 @@ static int __devinit
 bnad_pci_probe(struct pci_dev *pdev,
 		const struct pci_device_id *pcidev_id)
 {
-	bool 	using_dac;
+	bool 	using_dac = false;
 	int 	err;
 	struct bnad *bnad;
 	struct bna *bna;
@@ -3066,7 +3091,7 @@ bnad_pci_probe(struct pci_dev *pdev,
 	/*
 	 * PCI initialization
 	 * 	Output : using_dac = 1 for 64 bit DMA
-	 *		           = 0 for 32 bit DMA
+	 *			   = 0 for 32 bit DMA
 	 */
 	err = bnad_pci_init(bnad, pdev, &using_dac);
 	if (err)
@@ -3084,6 +3109,9 @@ bnad_pci_probe(struct pci_dev *pdev,
 	/* Initialize netdev structure, set up ethtool ops */
 	bnad_netdev_init(bnad, using_dac);
 
+	/* Set link to down state */
+	netif_carrier_off(netdev);
+
 	bnad_enable_msix(bnad);
 
 	/* Get resource requirement form bna */
@@ -3115,11 +3143,13 @@ bnad_pci_probe(struct pci_dev *pdev,
 				((unsigned long)bnad));
 	setup_timer(&bnad->bna.device.ioc.hb_timer, bnad_ioc_hb_check,
 				((unsigned long)bnad));
-	setup_timer(&bnad->bna.device.ioc.sem_timer, bnad_ioc_sem_timeout,
+	setup_timer(&bnad->bna.device.ioc.iocpf_timer, bnad_iocpf_timeout,
+				((unsigned long)bnad));
+	setup_timer(&bnad->bna.device.ioc.sem_timer, bnad_iocpf_sem_timeout,
 				((unsigned long)bnad));
 
 	/* Now start the timer before calling IOC */
-	mod_timer(&bnad->bna.device.ioc.ioc_timer,
+	mod_timer(&bnad->bna.device.ioc.iocpf_timer,
 		  jiffies + msecs_to_jiffies(BNA_IOC_TIMER_FREQ));
 
 	/*
@@ -3137,11 +3167,6 @@ bnad_pci_probe(struct pci_dev *pdev,
 
 	mutex_unlock(&bnad->conf_mutex);
 
-	/*
-	 * Make sure the link appears down to the stack
-	 */
-	netif_carrier_off(netdev);
-
 	/* Finally, reguister with net_device layer */
 	err = register_netdev(netdev);
 	if (err) {
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/bna/bnad_ethtool.c linux-libre-2.6.38-gnu1/drivers/net/bna/bnad_ethtool.c
--- linux-libre-2.6.37-gnu1/drivers/net/bna/bnad_ethtool.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/bna/bnad_ethtool.c	2011-03-14 21:20:32.000000000 -0400
@@ -68,6 +68,7 @@ static char *bnad_net_stats_strings[BNAD
 
 	"netif_queue_stop",
 	"netif_queue_wakeup",
+	"netif_queue_stopped",
 	"tso4",
 	"tso6",
 	"tso_err",
@@ -274,7 +275,6 @@ bnad_get_drvinfo(struct net_device *netd
 
 	ioc_attr = kzalloc(sizeof(*ioc_attr), GFP_KERNEL);
 	if (ioc_attr) {
-		memset(ioc_attr, 0, sizeof(*ioc_attr));
 		spin_lock_irqsave(&bnad->bna_lock, flags);
 		bfa_nw_ioc_get_attr(&bnad->bna.device.ioc, ioc_attr);
 		spin_unlock_irqrestore(&bnad->bna_lock, flags);
@@ -330,10 +330,6 @@ do {								\
 
 	BNAD_GET_REG(PCIE_MISC_REG);
 
-	BNAD_GET_REG(HOST_SEM0_REG);
-	BNAD_GET_REG(HOST_SEM1_REG);
-	BNAD_GET_REG(HOST_SEM2_REG);
-	BNAD_GET_REG(HOST_SEM3_REG);
 	BNAD_GET_REG(HOST_SEM0_INFO_REG);
 	BNAD_GET_REG(HOST_SEM1_INFO_REG);
 	BNAD_GET_REG(HOST_SEM2_INFO_REG);
@@ -1184,6 +1180,9 @@ bnad_get_ethtool_stats(struct net_device
 
 	bi = sizeof(*net_stats64) / sizeof(u64);
 
+	/* Get netif_queue_stopped from stack */
+	bnad->stats.drv_stats.netif_queue_stopped = netif_queue_stopped(netdev);
+
 	/* Fill driver stats into ethtool buffers */
 	stats64 = (u64 *)&bnad->stats.drv_stats;
 	for (i = 0; i < sizeof(struct bnad_drv_stats) / sizeof(u64); i++)
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/bna/bnad.h linux-libre-2.6.38-gnu1/drivers/net/bna/bnad.h
--- linux-libre-2.6.37-gnu1/drivers/net/bna/bnad.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/bna/bnad.h	2011-03-14 21:20:32.000000000 -0400
@@ -51,6 +51,7 @@
  */
 struct bnad_rx_ctrl {
 	struct bna_ccb *ccb;
+	unsigned long  flags;
 	struct napi_struct	napi;
 };
 
@@ -64,7 +65,7 @@ struct bnad_rx_ctrl {
 #define BNAD_NAME			"bna"
 #define BNAD_NAME_LEN			64
 
-#define BNAD_VERSION			"2.3.2.0"
+#define BNAD_VERSION			"2.3.2.3"
 
 #define BNAD_MAILBOX_MSIX_VECTORS	1
 
@@ -82,6 +83,7 @@ struct bnad_rx_ctrl {
 
 /* Bit positions for tcb->flags */
 #define BNAD_TXQ_FREE_SENT		0
+#define BNAD_TXQ_TX_STARTED		1
 
 /* Bit positions for rcb->flags */
 #define BNAD_RXQ_REFILL			0
@@ -124,6 +126,7 @@ struct bnad_completion {
 struct bnad_drv_stats {
 	u64 		netif_queue_stop;
 	u64		netif_queue_wakeup;
+	u64		netif_queue_stopped;
 	u64		tso4;
 	u64		tso6;
 	u64		tso_err;
@@ -199,12 +202,12 @@ struct bnad_unmap_q {
 /* Set, tested & cleared using xxx_bit() functions */
 /* Values indicated bit positions */
 #define	BNAD_RF_CEE_RUNNING		1
-#define BNAD_RF_HW_ERROR 		2
-#define BNAD_RF_MBOX_IRQ_DISABLED	3
-#define BNAD_RF_TX_STARTED		4
-#define BNAD_RF_RX_STARTED		5
-#define BNAD_RF_DIM_TIMER_RUNNING	6
-#define BNAD_RF_STATS_TIMER_RUNNING	7
+#define BNAD_RF_MBOX_IRQ_DISABLED	2
+#define BNAD_RF_RX_STARTED		3
+#define BNAD_RF_DIM_TIMER_RUNNING	4
+#define BNAD_RF_STATS_TIMER_RUNNING	5
+#define BNAD_RF_TX_SHUTDOWN_DELAYED	6
+#define BNAD_RF_RX_SHUTDOWN_DELAYED	7
 
 struct bnad {
 	struct net_device 	*netdev;
@@ -306,8 +309,10 @@ extern void bnad_cleanup_rx(struct bnad
 extern void bnad_dim_timer_start(struct bnad *bnad);
 
 /* Statistics */
-extern void bnad_netdev_qstats_fill(struct bnad *bnad, struct rtnl_link_stats64 *stats);
-extern void bnad_netdev_hwstats_fill(struct bnad *bnad, struct rtnl_link_stats64 *stats);
+extern void bnad_netdev_qstats_fill(struct bnad *bnad,
+		struct rtnl_link_stats64 *stats);
+extern void bnad_netdev_hwstats_fill(struct bnad *bnad,
+		struct rtnl_link_stats64 *stats);
 
 /**
  * MACROS
@@ -320,9 +325,11 @@ extern void bnad_netdev_hwstats_fill(str
 
 #define bnad_enable_rx_irq_unsafe(_ccb)			\
 {							\
-	bna_ib_coalescing_timer_set((_ccb)->i_dbell,	\
-		(_ccb)->rx_coalescing_timeo);		\
-	bna_ib_ack((_ccb)->i_dbell, 0);			\
+	if (likely(test_bit(BNAD_RXQ_STARTED, &ccb->rcb[0]->flags))) {\
+		bna_ib_coalescing_timer_set((_ccb)->i_dbell,	\
+			(_ccb)->rx_coalescing_timeo);		\
+		bna_ib_ack((_ccb)->i_dbell, 0);			\
+	}							\
 }
 
 #define bnad_dim_timer_running(_bnad)				\
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/bna/bna.h linux-libre-2.6.38-gnu1/drivers/net/bna/bna.h
--- linux-libre-2.6.37-gnu1/drivers/net/bna/bna.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/bna/bna.h	2011-03-14 21:20:32.000000000 -0400
@@ -32,8 +32,6 @@ extern const u32 bna_napi_dim_vector[][B
 /* Log string size */
 #define BNA_MESSAGE_SIZE		256
 
-#define bna_device_timer(_dev)		bfa_timer_beat(&((_dev)->timer_mod))
-
 /* MBOX API for PORT, TX, RX */
 #define bna_mbox_qe_fill(_qe, _cmd, _cmd_len, _cbfn, _cbarg)		\
 do {									\
@@ -390,8 +388,8 @@ void bna_mbox_send(struct bna *bna, stru
 
 /* API for RX */
 int bna_port_mtu_get(struct bna_port *port);
-void bna_llport_admin_up(struct bna_llport *llport);
-void bna_llport_admin_down(struct bna_llport *llport);
+void bna_llport_rx_started(struct bna_llport *llport);
+void bna_llport_rx_stopped(struct bna_llport *llport);
 
 /* API for BNAD */
 void bna_port_enable(struct bna_port *port);
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/bna/bna_txrx.c linux-libre-2.6.38-gnu1/drivers/net/bna/bna_txrx.c
--- linux-libre-2.6.37-gnu1/drivers/net/bna/bna_txrx.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/bna/bna_txrx.c	2011-03-14 21:20:32.000000000 -0400
@@ -1226,8 +1226,7 @@ rxf_process_packet_filter_vlan(struct bn
 	/* Apply the VLAN filter */
 	if (rxf->rxf_flags & BNA_RXF_FL_VLAN_CONFIG_PENDING) {
 		rxf->rxf_flags &= ~BNA_RXF_FL_VLAN_CONFIG_PENDING;
-		if (!(rxf->rxmode_active & BNA_RXMODE_PROMISC) &&
-			!(rxf->rxmode_active & BNA_RXMODE_DEFAULT))
+		if (!(rxf->rxmode_active & BNA_RXMODE_PROMISC))
 			__rxf_vlan_filter_set(rxf, rxf->vlan_filter_status);
 	}
 
@@ -1276,9 +1275,6 @@ rxf_process_packet_filter(struct bna_rxf
 	if (rxf_process_packet_filter_promisc(rxf))
 		return 1;
 
-	if (rxf_process_packet_filter_default(rxf))
-		return 1;
-
 	if (rxf_process_packet_filter_allmulti(rxf))
 		return 1;
 
@@ -1340,9 +1336,6 @@ rxf_clear_packet_filter(struct bna_rxf *
 	if (rxf_clear_packet_filter_promisc(rxf))
 		return 1;
 
-	if (rxf_clear_packet_filter_default(rxf))
-		return 1;
-
 	if (rxf_clear_packet_filter_allmulti(rxf))
 		return 1;
 
@@ -1389,8 +1382,6 @@ rxf_reset_packet_filter(struct bna_rxf *
 
 	rxf_reset_packet_filter_promisc(rxf);
 
-	rxf_reset_packet_filter_default(rxf);
-
 	rxf_reset_packet_filter_allmulti(rxf);
 }
 
@@ -1441,12 +1432,16 @@ bna_rxf_init(struct bna_rxf *rxf,
 	memset(rxf->vlan_filter_table, 0,
 			(sizeof(u32) * ((BFI_MAX_VLAN + 1) / 32)));
 
+	/* Set up VLAN 0 for pure priority tagged packets */
+	rxf->vlan_filter_table[0] |= 1;
+
 	bfa_fsm_set_state(rxf, bna_rxf_sm_stopped);
 }
 
 static void
 bna_rxf_uninit(struct bna_rxf *rxf)
 {
+	struct bna *bna = rxf->rx->bna;
 	struct bna_mac *mac;
 
 	bna_rit_mod_seg_put(&rxf->rx->bna->rit_mod, rxf->rit_segment);
@@ -1473,6 +1468,27 @@ bna_rxf_uninit(struct bna_rxf *rxf)
 		bna_mcam_mod_mac_put(&rxf->rx->bna->mcam_mod, mac);
 	}
 
+	/* Turn off pending promisc mode */
+	if (is_promisc_enable(rxf->rxmode_pending,
+				rxf->rxmode_pending_bitmask)) {
+		/* system promisc state should be pending */
+		BUG_ON(!(bna->rxf_promisc_id == rxf->rxf_id));
+		promisc_inactive(rxf->rxmode_pending,
+				rxf->rxmode_pending_bitmask);
+		 bna->rxf_promisc_id = BFI_MAX_RXF;
+	}
+	/* Promisc mode should not be active */
+	BUG_ON(rxf->rxmode_active & BNA_RXMODE_PROMISC);
+
+	/* Turn off pending all-multi mode */
+	if (is_allmulti_enable(rxf->rxmode_pending,
+				rxf->rxmode_pending_bitmask)) {
+		allmulti_inactive(rxf->rxmode_pending,
+				rxf->rxmode_pending_bitmask);
+	}
+	/* Allmulti mode should not be active */
+	BUG_ON(rxf->rxmode_active & BNA_RXMODE_ALLMULTI);
+
 	rxf->rx = NULL;
 }
 
@@ -1947,7 +1963,7 @@ bna_rx_sm_started_entry(struct bna_rx *r
 		bna_ib_ack(&rxp->cq.ib->door_bell, 0);
 	}
 
-	bna_llport_admin_up(&rx->bna->port.llport);
+	bna_llport_rx_started(&rx->bna->port.llport);
 }
 
 void
@@ -1955,13 +1971,13 @@ bna_rx_sm_started(struct bna_rx *rx, enu
 {
 	switch (event) {
 	case RX_E_FAIL:
-		bna_llport_admin_down(&rx->bna->port.llport);
+		bna_llport_rx_stopped(&rx->bna->port.llport);
 		bfa_fsm_set_state(rx, bna_rx_sm_stopped);
 		rx_ib_fail(rx);
 		bna_rxf_fail(&rx->rxf);
 		break;
 	case RX_E_STOP:
-		bna_llport_admin_down(&rx->bna->port.llport);
+		bna_llport_rx_stopped(&rx->bna->port.llport);
 		bfa_fsm_set_state(rx, bna_rx_sm_rxf_stop_wait);
 		break;
 	default:
@@ -3373,7 +3389,7 @@ __bna_txq_start(struct bna_tx *tx, struc
 
 	txq_cfg.cns_ptr2_n_q_state = BNA_Q_IDLE_STATE;
 	txq_cfg.nxt_qid_n_fid_n_pri = (((tx->txf.txf_id & 0x3f) << 3) |
-			(txq->priority & 0x3));
+			(txq->priority & 0x7));
 	txq_cfg.wvc_n_cquota_n_rquota =
 			((((u32)BFI_TX_MAX_WRR_QUOTA & 0xfff) << 12) |
 			(BFI_TX_MAX_WRR_QUOTA & 0xfff));
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/bna/bna_types.h linux-libre-2.6.38-gnu1/drivers/net/bna/bna_types.h
--- linux-libre-2.6.37-gnu1/drivers/net/bna/bna_types.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/bna/bna_types.h	2011-03-14 21:20:32.000000000 -0400
@@ -165,8 +165,7 @@ enum bna_rxp_type {
 
 enum bna_rxmode {
 	BNA_RXMODE_PROMISC 	= 1,
-	BNA_RXMODE_DEFAULT 	= 2,
-	BNA_RXMODE_ALLMULTI 	= 4
+	BNA_RXMODE_ALLMULTI 	= 2
 };
 
 enum bna_rx_event {
@@ -249,8 +248,9 @@ enum bna_link_status {
 };
 
 enum bna_llport_flags {
-	BNA_LLPORT_F_ENABLED 	= 1,
-	BNA_LLPORT_F_RX_ENABLED	= 2
+	BNA_LLPORT_F_ADMIN_UP	 	= 1,
+	BNA_LLPORT_F_PORT_ENABLED	= 2,
+	BNA_LLPORT_F_RX_STARTED		= 4
 };
 
 enum bna_port_flags {
@@ -405,7 +405,7 @@ struct bna_llport {
 
 	enum bna_link_status link_status;
 
-	int			admin_up_count;
+	int			rx_started_count;
 
 	void (*stop_cbfn)(struct bna_port *, enum bna_cb_status);
 
@@ -1117,7 +1117,6 @@ struct bna {
 
 	struct bna_rit_mod rit_mod;
 
-	int			rxf_default_id;
 	int			rxf_promisc_id;
 
 	struct bna_mbox_qe mbox_qe;
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/bnx2.c linux-libre-2.6.38-gnu1/drivers/net/bnx2.c
--- linux-libre-2.6.37-gnu1/drivers/net/bnx2.c	2013-05-03 03:57:56.000000000 -0400
+++ linux-libre-2.6.38-gnu1/drivers/net/bnx2.c	2013-05-03 01:57:58.000000000 -0400
@@ -56,8 +56,8 @@
 #include "bnx2_fw.h"
 
 #define DRV_MODULE_NAME		"bnx2"
-#define DRV_MODULE_VERSION	"2.0.18"
-#define DRV_MODULE_RELDATE	"Oct 7, 2010"
+#define DRV_MODULE_VERSION	"2.0.21"
+#define DRV_MODULE_RELDATE	"Dec 23, 2010"
 #define FW_MIPS_FILE_06		"/*(DEBLOBBED)*/"
 #define FW_RV2P_FILE_06		"/*(DEBLOBBED)*/"
 #define FW_MIPS_FILE_09		"/*(DEBLOBBED)*/"
@@ -762,13 +762,10 @@ bnx2_alloc_rx_mem(struct bnx2 *bp)
 		int j;
 
 		rxr->rx_buf_ring =
-			vmalloc(SW_RXBD_RING_SIZE * bp->rx_max_ring);
+			vzalloc(SW_RXBD_RING_SIZE * bp->rx_max_ring);
 		if (rxr->rx_buf_ring == NULL)
 			return -ENOMEM;
 
-		memset(rxr->rx_buf_ring, 0,
-		       SW_RXBD_RING_SIZE * bp->rx_max_ring);
-
 		for (j = 0; j < bp->rx_max_ring; j++) {
 			rxr->rx_desc_ring[j] =
 				dma_alloc_coherent(&bp->pdev->dev,
@@ -781,13 +778,11 @@ bnx2_alloc_rx_mem(struct bnx2 *bp)
 		}
 
 		if (bp->rx_pg_ring_size) {
-			rxr->rx_pg_ring = vmalloc(SW_RXPG_RING_SIZE *
+			rxr->rx_pg_ring = vzalloc(SW_RXPG_RING_SIZE *
 						  bp->rx_max_pg_ring);
 			if (rxr->rx_pg_ring == NULL)
 				return -ENOMEM;
 
-			memset(rxr->rx_pg_ring, 0, SW_RXPG_RING_SIZE *
-			       bp->rx_max_pg_ring);
 		}
 
 		for (j = 0; j < bp->rx_max_pg_ring; j++) {
@@ -4641,13 +4636,28 @@ bnx2_reset_chip(struct bnx2 *bp, u32 res
 
 	/* Wait for the current PCI transaction to complete before
 	 * issuing a reset. */
-	REG_WR(bp, BNX2_MISC_ENABLE_CLR_BITS,
-	       BNX2_MISC_ENABLE_CLR_BITS_TX_DMA_ENABLE |
-	       BNX2_MISC_ENABLE_CLR_BITS_DMA_ENGINE_ENABLE |
-	       BNX2_MISC_ENABLE_CLR_BITS_RX_DMA_ENABLE |
-	       BNX2_MISC_ENABLE_CLR_BITS_HOST_COALESCE_ENABLE);
-	val = REG_RD(bp, BNX2_MISC_ENABLE_CLR_BITS);
-	udelay(5);
+	if ((CHIP_NUM(bp) == CHIP_NUM_5706) ||
+	    (CHIP_NUM(bp) == CHIP_NUM_5708)) {
+		REG_WR(bp, BNX2_MISC_ENABLE_CLR_BITS,
+		       BNX2_MISC_ENABLE_CLR_BITS_TX_DMA_ENABLE |
+		       BNX2_MISC_ENABLE_CLR_BITS_DMA_ENGINE_ENABLE |
+		       BNX2_MISC_ENABLE_CLR_BITS_RX_DMA_ENABLE |
+		       BNX2_MISC_ENABLE_CLR_BITS_HOST_COALESCE_ENABLE);
+		val = REG_RD(bp, BNX2_MISC_ENABLE_CLR_BITS);
+		udelay(5);
+	} else {  /* 5709 */
+		val = REG_RD(bp, BNX2_MISC_NEW_CORE_CTL);
+		val &= ~BNX2_MISC_NEW_CORE_CTL_DMA_ENABLE;
+		REG_WR(bp, BNX2_MISC_NEW_CORE_CTL, val);
+		val = REG_RD(bp, BNX2_MISC_NEW_CORE_CTL);
+
+		for (i = 0; i < 100; i++) {
+			msleep(1);
+			val = REG_RD(bp, BNX2_PCICFG_DEVICE_CONTROL);
+			if (!(val & BNX2_PCICFG_DEVICE_STATUS_NO_PEND))
+				break;
+		}
+	}
 
 	/* Wait for the firmware to tell us it is ok to issue a reset. */
 	bnx2_fw_sync(bp, BNX2_DRV_MSG_DATA_WAIT0 | reset_code, 1, 1);
@@ -4669,7 +4679,7 @@ bnx2_reset_chip(struct bnx2 *bp, u32 res
 		val = BNX2_PCICFG_MISC_CONFIG_REG_WINDOW_ENA |
 		      BNX2_PCICFG_MISC_CONFIG_TARGET_MB_WORD_SWAP;
 
-		pci_write_config_dword(bp->pdev, BNX2_PCICFG_MISC_CONFIG, val);
+		REG_WR(bp, BNX2_PCICFG_MISC_CONFIG, val);
 
 	} else {
 		val = BNX2_PCICFG_MISC_CONFIG_CORE_RST_REQ |
@@ -6082,7 +6092,7 @@ bnx2_request_irq(struct bnx2 *bp)
 }
 
 static void
-bnx2_free_irq(struct bnx2 *bp)
+__bnx2_free_irq(struct bnx2 *bp)
 {
 	struct bnx2_irq *irq;
 	int i;
@@ -6093,6 +6103,13 @@ bnx2_free_irq(struct bnx2 *bp)
 			free_irq(irq->vector, &bp->bnx2_napi[i]);
 		irq->requested = 0;
 	}
+}
+
+static void
+bnx2_free_irq(struct bnx2 *bp)
+{
+
+	__bnx2_free_irq(bp);
 	if (bp->flags & BNX2_FLAG_USING_MSI)
 		pci_disable_msi(bp->pdev);
 	else if (bp->flags & BNX2_FLAG_USING_MSIX)
@@ -6797,28 +6814,30 @@ bnx2_get_regs(struct net_device *dev, st
 	u32 *p = _p, i, offset;
 	u8 *orig_p = _p;
 	struct bnx2 *bp = netdev_priv(dev);
-	u32 reg_boundaries[] = { 0x0000, 0x0098, 0x0400, 0x045c,
-				 0x0800, 0x0880, 0x0c00, 0x0c10,
-				 0x0c30, 0x0d08, 0x1000, 0x101c,
-				 0x1040, 0x1048, 0x1080, 0x10a4,
-				 0x1400, 0x1490, 0x1498, 0x14f0,
-				 0x1500, 0x155c, 0x1580, 0x15dc,
-				 0x1600, 0x1658, 0x1680, 0x16d8,
-				 0x1800, 0x1820, 0x1840, 0x1854,
-				 0x1880, 0x1894, 0x1900, 0x1984,
-				 0x1c00, 0x1c0c, 0x1c40, 0x1c54,
-				 0x1c80, 0x1c94, 0x1d00, 0x1d84,
-				 0x2000, 0x2030, 0x23c0, 0x2400,
-				 0x2800, 0x2820, 0x2830, 0x2850,
-				 0x2b40, 0x2c10, 0x2fc0, 0x3058,
-				 0x3c00, 0x3c94, 0x4000, 0x4010,
-				 0x4080, 0x4090, 0x43c0, 0x4458,
-				 0x4c00, 0x4c18, 0x4c40, 0x4c54,
-				 0x4fc0, 0x5010, 0x53c0, 0x5444,
-				 0x5c00, 0x5c18, 0x5c80, 0x5c90,
-				 0x5fc0, 0x6000, 0x6400, 0x6428,
-				 0x6800, 0x6848, 0x684c, 0x6860,
-				 0x6888, 0x6910, 0x8000 };
+	static const u32 reg_boundaries[] = {
+		0x0000, 0x0098, 0x0400, 0x045c,
+		0x0800, 0x0880, 0x0c00, 0x0c10,
+		0x0c30, 0x0d08, 0x1000, 0x101c,
+		0x1040, 0x1048, 0x1080, 0x10a4,
+		0x1400, 0x1490, 0x1498, 0x14f0,
+		0x1500, 0x155c, 0x1580, 0x15dc,
+		0x1600, 0x1658, 0x1680, 0x16d8,
+		0x1800, 0x1820, 0x1840, 0x1854,
+		0x1880, 0x1894, 0x1900, 0x1984,
+		0x1c00, 0x1c0c, 0x1c40, 0x1c54,
+		0x1c80, 0x1c94, 0x1d00, 0x1d84,
+		0x2000, 0x2030, 0x23c0, 0x2400,
+		0x2800, 0x2820, 0x2830, 0x2850,
+		0x2b40, 0x2c10, 0x2fc0, 0x3058,
+		0x3c00, 0x3c94, 0x4000, 0x4010,
+		0x4080, 0x4090, 0x43c0, 0x4458,
+		0x4c00, 0x4c18, 0x4c40, 0x4c54,
+		0x4fc0, 0x5010, 0x53c0, 0x5444,
+		0x5c00, 0x5c18, 0x5c80, 0x5c90,
+		0x5fc0, 0x6000, 0x6400, 0x6428,
+		0x6800, 0x6848, 0x684c, 0x6860,
+		0x6888, 0x6910, 0x8000
+	};
 
 	regs->version = 0;
 
@@ -7076,6 +7095,7 @@ bnx2_change_ring_size(struct bnx2 *bp, u
 
 		bnx2_netif_stop(bp, true);
 		bnx2_reset_chip(bp, BNX2_DRV_MSG_CODE_RESET);
+		__bnx2_free_irq(bp);
 		bnx2_free_skbs(bp);
 		bnx2_free_mem(bp);
 	}
@@ -7088,6 +7108,9 @@ bnx2_change_ring_size(struct bnx2 *bp, u
 
 		rc = bnx2_alloc_mem(bp);
 		if (!rc)
+			rc = bnx2_request_irq(bp);
+
+		if (!rc)
 			rc = bnx2_init_nic(bp, 0);
 
 		if (rc) {
@@ -7526,6 +7549,10 @@ bnx2_set_flags(struct net_device *dev, u
 	    !(data & ETH_FLAG_RXVLAN))
 		return -EINVAL;
 
+	/* TSO with VLAN tag won't work with current firmware */
+	if (!(data & ETH_FLAG_TXVLAN))
+		return -EINVAL;
+
 	rc = ethtool_op_set_flags(dev, data, ETH_FLAG_RXHASH | ETH_FLAG_RXVLAN |
 				  ETH_FLAG_TXVLAN);
 	if (rc)
@@ -7910,15 +7937,15 @@ bnx2_init_board(struct pci_dev *pdev, st
 		goto err_out_release;
 	}
 
+	bnx2_set_power_state(bp, PCI_D0);
+
 	/* Configure byte swap and enable write to the reg_window registers.
 	 * Rely on CPU to do target byte swapping on big endian systems
 	 * The chip's target access swapping will not swap all accesses
 	 */
-	pci_write_config_dword(bp->pdev, BNX2_PCICFG_MISC_CONFIG,
-			       BNX2_PCICFG_MISC_CONFIG_REG_WINDOW_ENA |
-			       BNX2_PCICFG_MISC_CONFIG_TARGET_MB_WORD_SWAP);
-
-	bnx2_set_power_state(bp, PCI_D0);
+	REG_WR(bp, BNX2_PCICFG_MISC_CONFIG,
+		   BNX2_PCICFG_MISC_CONFIG_REG_WINDOW_ENA |
+		   BNX2_PCICFG_MISC_CONFIG_TARGET_MB_WORD_SWAP);
 
 	bp->chip_id = REG_RD(bp, BNX2_MISC_ID);
 
@@ -7935,11 +7962,8 @@ bnx2_init_board(struct pci_dev *pdev, st
 
 		/* AER (Advanced Error Reporting) hooks */
 		err = pci_enable_pcie_error_reporting(pdev);
-		if (err) {
-			dev_err(&pdev->dev, "pci_enable_pcie_error_reporting "
-					    "failed 0x%x\n", err);
-			/* non-fatal, continue */
-		}
+		if (!err)
+			bp->flags |= BNX2_FLAG_AER_ENABLED;
 
 	} else {
 		bp->pcix_cap = pci_find_capability(pdev, PCI_CAP_ID_PCIX);
@@ -8202,8 +8226,10 @@ bnx2_init_board(struct pci_dev *pdev, st
 	return 0;
 
 err_out_unmap:
-	if (bp->flags & BNX2_FLAG_PCIE)
+	if (bp->flags & BNX2_FLAG_AER_ENABLED) {
 		pci_disable_pcie_error_reporting(pdev);
+		bp->flags &= ~BNX2_FLAG_AER_ENABLED;
+	}
 
 	if (bp->regview) {
 		iounmap(bp->regview);
@@ -8379,8 +8405,6 @@ bnx2_remove_one(struct pci_dev *pdev)
 	struct net_device *dev = pci_get_drvdata(pdev);
 	struct bnx2 *bp = netdev_priv(dev);
 
-	flush_scheduled_work();
-
 	unregister_netdev(dev);
 
 	if (bp->mips_firmware)
@@ -8393,8 +8417,10 @@ bnx2_remove_one(struct pci_dev *pdev)
 
 	kfree(bp->temp_stats_blk);
 
-	if (bp->flags & BNX2_FLAG_PCIE)
+	if (bp->flags & BNX2_FLAG_AER_ENABLED) {
 		pci_disable_pcie_error_reporting(pdev);
+		bp->flags &= ~BNX2_FLAG_AER_ENABLED;
+	}
 
 	free_netdev(dev);
 
@@ -8417,7 +8443,7 @@ bnx2_suspend(struct pci_dev *pdev, pm_me
 	if (!netif_running(dev))
 		return 0;
 
-	flush_scheduled_work();
+	cancel_work_sync(&bp->reset_task);
 	bnx2_netif_stop(bp, true);
 	netif_device_detach(dev);
 	del_timer_sync(&bp->timer);
@@ -8510,7 +8536,7 @@ static pci_ers_result_t bnx2_io_slot_res
 	}
 	rtnl_unlock();
 
-	if (!(bp->flags & BNX2_FLAG_PCIE))
+	if (!(bp->flags & BNX2_FLAG_AER_ENABLED))
 		return result;
 
 	err = pci_cleanup_aer_uncorrect_error_status(pdev);
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/bnx2.h linux-libre-2.6.38-gnu1/drivers/net/bnx2.h
--- linux-libre-2.6.37-gnu1/drivers/net/bnx2.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/bnx2.h	2011-03-14 21:20:32.000000000 -0400
@@ -461,6 +461,8 @@ struct l2_fhdr {
 #define BNX2_PCICFG_MAILBOX_QUEUE_ADDR			0x00000090
 #define BNX2_PCICFG_MAILBOX_QUEUE_DATA			0x00000094
 
+#define BNX2_PCICFG_DEVICE_CONTROL			0x000000b4
+#define BNX2_PCICFG_DEVICE_STATUS_NO_PEND		 ((1L<<5)<<16)
 
 /*
  *  pci_reg definition
@@ -6739,6 +6741,7 @@ struct bnx2 {
 #define BNX2_FLAG_JUMBO_BROKEN		0x00000800
 #define BNX2_FLAG_CAN_KEEP_VLAN		0x00001000
 #define BNX2_FLAG_BROKEN_STATS		0x00002000
+#define BNX2_FLAG_AER_ENABLED		0x00004000
 
 	struct bnx2_napi	bnx2_napi[BNX2_MAX_MSIX_VEC];
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/bnx2x/bnx2x_cmn.c linux-libre-2.6.38-gnu1/drivers/net/bnx2x/bnx2x_cmn.c
--- linux-libre-2.6.37-gnu1/drivers/net/bnx2x/bnx2x_cmn.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/bnx2x/bnx2x_cmn.c	2011-03-14 21:20:32.000000000 -0400
@@ -259,10 +259,44 @@ static void bnx2x_tpa_start(struct bnx2x
 #endif
 }
 
+/* Timestamp option length allowed for TPA aggregation:
+ *
+ *		nop nop kind length echo val
+ */
+#define TPA_TSTAMP_OPT_LEN	12
+/**
+ * Calculate the approximate value of the MSS for this
+ * aggregation using the first packet of it.
+ *
+ * @param bp
+ * @param parsing_flags Parsing flags from the START CQE
+ * @param len_on_bd Total length of the first packet for the
+ *		     aggregation.
+ */
+static inline u16 bnx2x_set_lro_mss(struct bnx2x *bp, u16 parsing_flags,
+				    u16 len_on_bd)
+{
+	/* TPA arrgregation won't have an IP options and TCP options
+	 * other than timestamp.
+	 */
+	u16 hdrs_len = ETH_HLEN + sizeof(struct iphdr) + sizeof(struct tcphdr);
+
+
+	/* Check if there was a TCP timestamp, if there is it's will
+	 * always be 12 bytes length: nop nop kind length echo val.
+	 *
+	 * Otherwise FW would close the aggregation.
+	 */
+	if (parsing_flags & PARSING_FLAGS_TIME_STAMP_EXIST_FLAG)
+		hdrs_len += TPA_TSTAMP_OPT_LEN;
+
+	return len_on_bd - hdrs_len;
+}
+
 static int bnx2x_fill_frag_skb(struct bnx2x *bp, struct bnx2x_fastpath *fp,
 			       struct sk_buff *skb,
 			       struct eth_fast_path_rx_cqe *fp_cqe,
-			       u16 cqe_idx)
+			       u16 cqe_idx, u16 parsing_flags)
 {
 	struct sw_rx_page *rx_pg, old_rx_pg;
 	u16 len_on_bd = le16_to_cpu(fp_cqe->len_on_bd);
@@ -275,8 +309,8 @@ static int bnx2x_fill_frag_skb(struct bn
 
 	/* This is needed in order to enable forwarding support */
 	if (frag_size)
-		skb_shinfo(skb)->gso_size = min((u32)SGE_PAGE_SIZE,
-					       max(frag_size, (u32)len_on_bd));
+		skb_shinfo(skb)->gso_size = bnx2x_set_lro_mss(bp, parsing_flags,
+							      len_on_bd);
 
 #ifdef BNX2X_STOP_ON_ERROR
 	if (pages > min_t(u32, 8, MAX_SKB_FRAGS)*SGE_PAGE_SIZE*PAGES_PER_SGE) {
@@ -344,6 +378,8 @@ static void bnx2x_tpa_stop(struct bnx2x
 	if (likely(new_skb)) {
 		/* fix ip xsum and give it to the stack */
 		/* (no need to map the new skb) */
+		u16 parsing_flags =
+			le16_to_cpu(cqe->fast_path_cqe.pars_flags.flags);
 
 		prefetch(skb);
 		prefetch(((char *)(skb)) + L1_CACHE_BYTES);
@@ -373,9 +409,9 @@ static void bnx2x_tpa_stop(struct bnx2x
 		}
 
 		if (!bnx2x_fill_frag_skb(bp, fp, skb,
-					 &cqe->fast_path_cqe, cqe_idx)) {
-			if ((le16_to_cpu(cqe->fast_path_cqe.
-			    pars_flags.flags) & PARSING_FLAGS_VLAN))
+					 &cqe->fast_path_cqe, cqe_idx,
+					 parsing_flags)) {
+			if (parsing_flags & PARSING_FLAGS_VLAN)
 				__vlan_hwaccel_put_tag(skb,
 						 le16_to_cpu(cqe->fast_path_cqe.
 							     vlan_tag));
@@ -698,6 +734,30 @@ void bnx2x_release_phy_lock(struct bnx2x
 	mutex_unlock(&bp->port.phy_mutex);
 }
 
+/* calculates MF speed according to current linespeed and MF configuration */
+u16 bnx2x_get_mf_speed(struct bnx2x *bp)
+{
+	u16 line_speed = bp->link_vars.line_speed;
+	if (IS_MF(bp)) {
+		u16 maxCfg = bnx2x_extract_max_cfg(bp,
+						   bp->mf_config[BP_VN(bp)]);
+
+		/* Calculate the current MAX line speed limit for the MF
+		 * devices
+		 */
+		if (IS_MF_SI(bp))
+			line_speed = (line_speed * maxCfg) / 100;
+		else { /* SD mode */
+			u16 vn_max_rate = maxCfg * 100;
+
+			if (vn_max_rate < line_speed)
+				line_speed = vn_max_rate;
+		}
+	}
+
+	return line_speed;
+}
+
 void bnx2x_link_report(struct bnx2x *bp)
 {
 	if (bp->flags & MF_FUNC_DIS) {
@@ -713,17 +773,8 @@ void bnx2x_link_report(struct bnx2x *bp)
 			netif_carrier_on(bp->dev);
 		netdev_info(bp->dev, "NIC Link is Up, ");
 
-		line_speed = bp->link_vars.line_speed;
-		if (IS_MF(bp)) {
-			u16 vn_max_rate;
+		line_speed = bnx2x_get_mf_speed(bp);
 
-			vn_max_rate =
-				((bp->mf_config[BP_VN(bp)] &
-				  FUNC_MF_CFG_MAX_BW_MASK) >>
-						FUNC_MF_CFG_MAX_BW_SHIFT) * 100;
-			if (vn_max_rate < line_speed)
-				line_speed = vn_max_rate;
-		}
 		pr_cont("%d Mbps ", line_speed);
 
 		if (bp->link_vars.duplex == DUPLEX_FULL)
@@ -813,7 +864,7 @@ void bnx2x_init_rx_rings(struct bnx2x *b
 	DP(NETIF_MSG_IFUP,
 	   "mtu %d  rx_buf_size %d\n", bp->dev->mtu, bp->rx_buf_size);
 
-	for_each_queue(bp, j) {
+	for_each_rx_queue(bp, j) {
 		struct bnx2x_fastpath *fp = &bp->fp[j];
 
 		if (!fp->disable_tpa) {
@@ -866,7 +917,7 @@ void bnx2x_init_rx_rings(struct bnx2x *b
 		}
 	}
 
-	for_each_queue(bp, j) {
+	for_each_rx_queue(bp, j) {
 		struct bnx2x_fastpath *fp = &bp->fp[j];
 
 		fp->rx_bd_cons = 0;
@@ -897,7 +948,7 @@ static void bnx2x_free_tx_skbs(struct bn
 {
 	int i;
 
-	for_each_queue(bp, i) {
+	for_each_tx_queue(bp, i) {
 		struct bnx2x_fastpath *fp = &bp->fp[i];
 
 		u16 bd_cons = fp->tx_bd_cons;
@@ -915,7 +966,7 @@ static void bnx2x_free_rx_skbs(struct bn
 {
 	int i, j;
 
-	for_each_queue(bp, j) {
+	for_each_rx_queue(bp, j) {
 		struct bnx2x_fastpath *fp = &bp->fp[j];
 
 		for (i = 0; i < NUM_RX_BD; i++) {
@@ -945,6 +996,23 @@ void bnx2x_free_skbs(struct bnx2x *bp)
 	bnx2x_free_rx_skbs(bp);
 }
 
+void bnx2x_update_max_mf_config(struct bnx2x *bp, u32 value)
+{
+	/* load old values */
+	u32 mf_cfg = bp->mf_config[BP_VN(bp)];
+
+	if (value != bnx2x_extract_max_cfg(bp, mf_cfg)) {
+		/* leave all but MAX value */
+		mf_cfg &= ~FUNC_MF_CFG_MAX_BW_MASK;
+
+		/* set new MAX value */
+		mf_cfg |= (value << FUNC_MF_CFG_MAX_BW_SHIFT)
+				& FUNC_MF_CFG_MAX_BW_MASK;
+
+		bnx2x_fw_command(bp, DRV_MSG_CODE_SET_MF_BW, mf_cfg);
+	}
+}
+
 static void bnx2x_free_msix_irqs(struct bnx2x *bp)
 {
 	int i, offset = 1;
@@ -956,7 +1024,7 @@ static void bnx2x_free_msix_irqs(struct
 #ifdef BCM_CNIC
 	offset++;
 #endif
-	for_each_queue(bp, i) {
+	for_each_eth_queue(bp, i) {
 		DP(NETIF_MSG_IFDOWN, "about to release fp #%d->%d irq  "
 		   "state %x\n", i, bp->msix_table[i + offset].vector,
 		   bnx2x_fp(bp, i, state));
@@ -990,14 +1058,14 @@ int bnx2x_enable_msix(struct bnx2x *bp)
 	   bp->msix_table[msix_vec].entry, bp->msix_table[msix_vec].entry);
 	msix_vec++;
 #endif
-	for_each_queue(bp, i) {
+	for_each_eth_queue(bp, i) {
 		bp->msix_table[msix_vec].entry = msix_vec;
 		DP(NETIF_MSG_IFUP, "msix_table[%d].entry = %d "
 		   "(fastpath #%u)\n", msix_vec, msix_vec, i);
 		msix_vec++;
 	}
 
-	req_cnt = BNX2X_NUM_QUEUES(bp) + CNIC_CONTEXT_USE + 1;
+	req_cnt = BNX2X_NUM_ETH_QUEUES(bp) + CNIC_CONTEXT_USE + 1;
 
 	rc = pci_enable_msix(bp->pdev, &bp->msix_table[0], req_cnt);
 
@@ -1053,7 +1121,7 @@ static int bnx2x_req_msix_irqs(struct bn
 #ifdef BCM_CNIC
 	offset++;
 #endif
-	for_each_queue(bp, i) {
+	for_each_eth_queue(bp, i) {
 		struct bnx2x_fastpath *fp = &bp->fp[i];
 		snprintf(fp->name, sizeof(fp->name), "%s-fp-%d",
 			 bp->dev->name, i);
@@ -1070,7 +1138,7 @@ static int bnx2x_req_msix_irqs(struct bn
 		fp->state = BNX2X_FP_STATE_IRQ;
 	}
 
-	i = BNX2X_NUM_QUEUES(bp);
+	i = BNX2X_NUM_ETH_QUEUES(bp);
 	offset = 1 + CNIC_CONTEXT_USE;
 	netdev_info(bp->dev, "using MSI-X  IRQs: sp %d  fp[%d] %d"
 	       " ... fp[%d] %d\n",
@@ -1117,7 +1185,7 @@ static void bnx2x_napi_enable(struct bnx
 {
 	int i;
 
-	for_each_queue(bp, i)
+	for_each_napi_queue(bp, i)
 		napi_enable(&bnx2x_fp(bp, i, napi));
 }
 
@@ -1125,7 +1193,7 @@ static void bnx2x_napi_disable(struct bn
 {
 	int i;
 
-	for_each_queue(bp, i)
+	for_each_napi_queue(bp, i)
 		napi_disable(&bnx2x_fp(bp, i, napi));
 }
 
@@ -1153,6 +1221,35 @@ void bnx2x_netif_stop(struct bnx2x *bp,
 	netif_tx_disable(bp->dev);
 }
 
+u16 bnx2x_select_queue(struct net_device *dev, struct sk_buff *skb)
+{
+#ifdef BCM_CNIC
+	struct bnx2x *bp = netdev_priv(dev);
+	if (NO_FCOE(bp))
+		return skb_tx_hash(dev, skb);
+	else {
+		struct ethhdr *hdr = (struct ethhdr *)skb->data;
+		u16 ether_type = ntohs(hdr->h_proto);
+
+		/* Skip VLAN tag if present */
+		if (ether_type == ETH_P_8021Q) {
+			struct vlan_ethhdr *vhdr =
+				(struct vlan_ethhdr *)skb->data;
+
+			ether_type = ntohs(vhdr->h_vlan_encapsulated_proto);
+		}
+
+		/* If ethertype is FCoE or FIP - use FCoE ring */
+		if ((ether_type == ETH_P_FCOE) || (ether_type == ETH_P_FIP))
+			return bnx2x_fcoe(bp, index);
+	}
+#endif
+	/* Select a none-FCoE queue:  if FCoE is enabled, exclude FCoE L2 ring
+	 */
+	return __skb_tx_hash(dev, skb,
+			dev->real_num_tx_queues - FCOE_CONTEXT_USE);
+}
+
 void bnx2x_set_num_queues(struct bnx2x *bp)
 {
 	switch (bp->multi_mode) {
@@ -1167,7 +1264,22 @@ void bnx2x_set_num_queues(struct bnx2x *
 		bp->num_queues = 1;
 		break;
 	}
+
+	/* Add special queues */
+	bp->num_queues += NONE_ETH_CONTEXT_USE;
+}
+
+#ifdef BCM_CNIC
+static inline void bnx2x_set_fcoe_eth_macs(struct bnx2x *bp)
+{
+	if (!NO_FCOE(bp)) {
+		if (!IS_MF_SD(bp))
+			bnx2x_set_fip_eth_mac_addr(bp, 1);
+		bnx2x_set_all_enode_macs(bp, 1);
+		bp->flags |= FCOE_MACS_SET;
+	}
 }
+#endif
 
 static void bnx2x_release_firmware(struct bnx2x *bp)
 {
@@ -1177,6 +1289,20 @@ static void bnx2x_release_firmware(struc
 	release_firmware(bp->firmware);
 }
 
+static inline int bnx2x_set_real_num_queues(struct bnx2x *bp)
+{
+	int rc, num = bp->num_queues;
+
+#ifdef BCM_CNIC
+	if (NO_FCOE(bp))
+		num -= FCOE_CONTEXT_USE;
+
+#endif
+	netif_set_real_num_tx_queues(bp->dev, num);
+	rc = netif_set_real_num_rx_queues(bp->dev, num);
+	return rc;
+}
+
 /* must be called with rtnl_lock */
 int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
 {
@@ -1203,10 +1329,9 @@ int bnx2x_nic_load(struct bnx2x *bp, int
 	if (bnx2x_alloc_mem(bp))
 		return -ENOMEM;
 
-	netif_set_real_num_tx_queues(bp->dev, bp->num_queues);
-	rc = netif_set_real_num_rx_queues(bp->dev, bp->num_queues);
+	rc = bnx2x_set_real_num_queues(bp);
 	if (rc) {
-		BNX2X_ERR("Unable to update real_num_rx_queues\n");
+		BNX2X_ERR("Unable to set real_num_queues\n");
 		goto load_error0;
 	}
 
@@ -1214,6 +1339,10 @@ int bnx2x_nic_load(struct bnx2x *bp, int
 		bnx2x_fp(bp, i, disable_tpa) =
 					((bp->flags & TPA_ENABLE_FLAG) == 0);
 
+#ifdef BCM_CNIC
+	/* We don't want TPA on FCoE L2 ring */
+	bnx2x_fcoe(bp, disable_tpa) = 1;
+#endif
 	bnx2x_napi_enable(bp);
 
 	/* Send LOAD_REQUEST command to MCP
@@ -1296,6 +1425,8 @@ int bnx2x_nic_load(struct bnx2x *bp, int
 		}
 	}
 
+	bnx2x_dcbx_init(bp);
+
 	bp->state = BNX2X_STATE_OPENING_WAIT4_PORT;
 
 	rc = bnx2x_func_start(bp);
@@ -1344,8 +1475,17 @@ int bnx2x_nic_load(struct bnx2x *bp, int
 	/* Now when Clients are configured we are ready to work */
 	bp->state = BNX2X_STATE_OPEN;
 
+#ifdef BCM_CNIC
+	bnx2x_set_fcoe_eth_macs(bp);
+#endif
+
 	bnx2x_set_eth_mac(bp, 1);
 
+	if (bp->pending_max) {
+		bnx2x_update_max_mf_config(bp, bp->pending_max);
+		bp->pending_max = 0;
+	}
+
 	if (bp->port.pmf)
 		bnx2x_initial_phy_init(bp, load_mode);
 
@@ -1402,7 +1542,7 @@ load_error3:
 
 	/* Free SKBs, SGEs, TPA pool and driver internals */
 	bnx2x_free_skbs(bp);
-	for_each_queue(bp, i)
+	for_each_rx_queue(bp, i)
 		bnx2x_free_rx_sge_range(bp, bp->fp + i, NUM_RX_SGE);
 
 	/* Release IRQs */
@@ -1473,7 +1613,7 @@ int bnx2x_nic_unload(struct bnx2x *bp, i
 
 	/* Free SKBs, SGEs, TPA pool and driver internals */
 	bnx2x_free_skbs(bp);
-	for_each_queue(bp, i)
+	for_each_rx_queue(bp, i)
 		bnx2x_free_rx_sge_range(bp, bp->fp + i, NUM_RX_SGE);
 
 	bnx2x_free_mem(bp);
@@ -1577,6 +1717,17 @@ int bnx2x_poll(struct napi_struct *napi,
 
 		/* Fall out from the NAPI loop if needed */
 		if (!(bnx2x_has_rx_work(fp) || bnx2x_has_tx_work(fp))) {
+#ifdef BCM_CNIC
+			/* No need to update SB for FCoE L2 ring as long as
+			 * it's connected to the default SB and the SB
+			 * has been updated when NAPI was scheduled.
+			 */
+			if (IS_FCOE_FP(fp)) {
+				napi_complete(napi);
+				break;
+			}
+#endif
+
 			bnx2x_update_fpsb_idx(fp);
 			/* bnx2x_has_rx_work() reads the status block,
 			 * thus we need to ensure that status block indices
@@ -1692,11 +1843,10 @@ static inline u32 bnx2x_xmit_type(struct
 		}
 	}
 
-	if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV4)
-		rc |= (XMIT_GSO_V4 | XMIT_CSUM_V4 | XMIT_CSUM_TCP);
-
-	else if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6)
-		rc |= (XMIT_GSO_V6 | XMIT_CSUM_TCP | XMIT_CSUM_V6);
+	if (skb_is_gso_v6(skb))
+		rc |= XMIT_GSO_V6 | XMIT_CSUM_TCP | XMIT_CSUM_V6;
+	else if (skb_is_gso(skb))
+		rc |= XMIT_GSO_V4 | XMIT_CSUM_V4 | XMIT_CSUM_TCP;
 
 	return rc;
 }
@@ -2242,7 +2392,7 @@ int __devinit bnx2x_alloc_mem_bp(struct
 	bp->fp = fp;
 
 	/* msix table */
-	tbl = kzalloc((bp->l2_cid_count + 1) * sizeof(*tbl),
+	tbl = kzalloc((FP_SB_COUNT(bp->l2_cid_count) + 1) * sizeof(*tbl),
 				  GFP_KERNEL);
 	if (!tbl)
 		goto alloc_err;
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/bnx2x/bnx2x_cmn.h linux-libre-2.6.38-gnu1/drivers/net/bnx2x/bnx2x_cmn.h
--- linux-libre-2.6.37-gnu1/drivers/net/bnx2x/bnx2x_cmn.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/bnx2x/bnx2x_cmn.h	2011-03-14 21:20:32.000000000 -0400
@@ -73,6 +73,16 @@ void bnx2x__link_status_update(struct bn
 void bnx2x_link_report(struct bnx2x *bp);
 
 /**
+ * calculates MF speed according to current linespeed and MF
+ * configuration
+ *
+ * @param bp
+ *
+ * @return u16
+ */
+u16 bnx2x_get_mf_speed(struct bnx2x *bp);
+
+/**
  * MSI-X slowpath interrupt handler
  *
  * @param irq
@@ -232,6 +242,30 @@ int bnx2x_release_hw_lock(struct bnx2x *
  */
 void bnx2x_set_eth_mac(struct bnx2x *bp, int set);
 
+#ifdef BCM_CNIC
+/**
+ * Set/Clear FIP MAC(s) at the next enties in the CAM after the ETH
+ * MAC(s). This function will wait until the ramdord completion
+ * returns.
+ *
+ * @param bp driver handle
+ * @param set set or clear the CAM entry
+ *
+ * @return 0 if cussess, -ENODEV if ramrod doesn't return.
+ */
+int bnx2x_set_fip_eth_mac_addr(struct bnx2x *bp, int set);
+
+/**
+ * Set/Clear ALL_ENODE mcast MAC.
+ *
+ * @param bp
+ * @param set
+ *
+ * @return int
+ */
+int bnx2x_set_all_enode_macs(struct bnx2x *bp, int set);
+#endif
+
 /**
  * Set MAC filtering configurations.
  *
@@ -290,6 +324,13 @@ int bnx2x_func_start(struct bnx2x *bp);
 void bnx2x_ilt_set_info(struct bnx2x *bp);
 
 /**
+ * Inintialize dcbx protocol
+ *
+ * @param bp
+ */
+void bnx2x_dcbx_init(struct bnx2x *bp);
+
+/**
  * Set power state to the requested value. Currently only D0 and
  * D3hot are supported.
  *
@@ -300,6 +341,15 @@ void bnx2x_ilt_set_info(struct bnx2x *bp
  */
 int bnx2x_set_power_state(struct bnx2x *bp, pci_power_t state);
 
+/**
+ * Updates MAX part of MF configuration in HW
+ * (if required)
+ *
+ * @param bp
+ * @param value
+ */
+void bnx2x_update_max_mf_config(struct bnx2x *bp, u32 value);
+
 /* dev_close main block */
 int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode);
 
@@ -309,6 +359,9 @@ int bnx2x_nic_load(struct bnx2x *bp, int
 /* hard_xmit callback */
 netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev);
 
+/* select_queue callback */
+u16 bnx2x_select_queue(struct net_device *dev, struct sk_buff *skb);
+
 int bnx2x_change_mac_addr(struct net_device *dev, void *p);
 
 /* NAPI poll Rx part */
@@ -685,7 +738,7 @@ static inline void bnx2x_add_all_napi(st
 	int i;
 
 	/* Add NAPI objects */
-	for_each_queue(bp, i)
+	for_each_napi_queue(bp, i)
 		netif_napi_add(bp->dev, &bnx2x_fp(bp, i, napi),
 			       bnx2x_poll, BNX2X_NAPI_WEIGHT);
 }
@@ -694,7 +747,7 @@ static inline void bnx2x_del_all_napi(st
 {
 	int i;
 
-	for_each_queue(bp, i)
+	for_each_napi_queue(bp, i)
 		netif_napi_del(&bnx2x_fp(bp, i, napi));
 }
 
@@ -860,7 +913,7 @@ static inline void bnx2x_init_tx_rings(s
 {
 	int i, j;
 
-	for_each_queue(bp, j) {
+	for_each_tx_queue(bp, j) {
 		struct bnx2x_fastpath *fp = &bp->fp[j];
 
 		for (i = 1; i <= NUM_TX_RINGS; i++) {
@@ -939,7 +992,30 @@ static inline void bnx2x_set_next_page_r
 	}
 }
 
+#ifdef BCM_CNIC
+static inline void bnx2x_init_fcoe_fp(struct bnx2x *bp)
+{
+	bnx2x_fcoe(bp, cl_id) = BNX2X_FCOE_ETH_CL_ID +
+		BP_E1HVN(bp) * NONE_ETH_CONTEXT_USE;
+	bnx2x_fcoe(bp, cid) = BNX2X_FCOE_ETH_CID;
+	bnx2x_fcoe(bp, fw_sb_id) = DEF_SB_ID;
+	bnx2x_fcoe(bp, igu_sb_id) = bp->igu_dsb_id;
+	bnx2x_fcoe(bp, bp) = bp;
+	bnx2x_fcoe(bp, state) = BNX2X_FP_STATE_CLOSED;
+	bnx2x_fcoe(bp, index) = FCOE_IDX;
+	bnx2x_fcoe(bp, rx_cons_sb) = BNX2X_FCOE_L2_RX_INDEX;
+	bnx2x_fcoe(bp, tx_cons_sb) = BNX2X_FCOE_L2_TX_INDEX;
+	/* qZone id equals to FW (per path) client id */
+	bnx2x_fcoe(bp, cl_qzone_id) = bnx2x_fcoe(bp, cl_id) +
+		BP_PORT(bp)*(CHIP_IS_E2(bp) ? ETH_MAX_RX_CLIENTS_E2 :
+				ETH_MAX_RX_CLIENTS_E1H);
+	/* init shortcut */
+	bnx2x_fcoe(bp, ustorm_rx_prods_offset) = CHIP_IS_E2(bp) ?
+	    USTORM_RX_PRODS_E2_OFFSET(bnx2x_fcoe(bp, cl_qzone_id)) :
+	    USTORM_RX_PRODS_E1X_OFFSET(BP_PORT(bp), bnx2x_fcoe_fp(bp)->cl_id);
 
+}
+#endif
 
 static inline void __storm_memset_struct(struct bnx2x *bp,
 					 u32 addr, size_t size, u32 *data)
@@ -977,4 +1053,24 @@ static inline void storm_memset_cmng(str
 void bnx2x_acquire_phy_lock(struct bnx2x *bp);
 void bnx2x_release_phy_lock(struct bnx2x *bp);
 
+/**
+ * Extracts MAX BW part from MF configuration.
+ *
+ * @param bp
+ * @param mf_cfg
+ *
+ * @return u16
+ */
+static inline u16 bnx2x_extract_max_cfg(struct bnx2x *bp, u32 mf_cfg)
+{
+	u16 max_cfg = (mf_cfg & FUNC_MF_CFG_MAX_BW_MASK) >>
+			      FUNC_MF_CFG_MAX_BW_SHIFT;
+	if (!max_cfg) {
+		BNX2X_ERR("Illegal configuration detected for Max BW - "
+			  "using 100 instead\n");
+		max_cfg = 100;
+	}
+	return max_cfg;
+}
+
 #endif /* BNX2X_CMN_H */
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/bnx2x/bnx2x_dcb.c linux-libre-2.6.38-gnu1/drivers/net/bnx2x/bnx2x_dcb.c
--- linux-libre-2.6.37-gnu1/drivers/net/bnx2x/bnx2x_dcb.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/bnx2x/bnx2x_dcb.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,2118 @@
+/* bnx2x_dcb.c: Broadcom Everest network driver.
+ *
+ * Copyright 2009-2010 Broadcom Corporation
+ *
+ * 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.gnu.org/licenses/old-licenses/gpl-2.0.html (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.
+ *
+ * Maintained by: Eilon Greenstein <eilong@broadcom.com>
+ * Written by: Dmitry Kravkov
+ *
+ */
+#include <linux/netdevice.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+
+#include "bnx2x.h"
+#include "bnx2x_cmn.h"
+#include "bnx2x_dcb.h"
+
+
+/* forward declarations of dcbx related functions */
+static void bnx2x_dcbx_stop_hw_tx(struct bnx2x *bp);
+static void bnx2x_pfc_set_pfc(struct bnx2x *bp);
+static void bnx2x_dcbx_update_ets_params(struct bnx2x *bp);
+static void bnx2x_dcbx_resume_hw_tx(struct bnx2x *bp);
+static void bnx2x_dcbx_get_ets_pri_pg_tbl(struct bnx2x *bp,
+					  u32 *set_configuration_ets_pg,
+					  u32 *pri_pg_tbl);
+static void bnx2x_dcbx_get_num_pg_traf_type(struct bnx2x *bp,
+					    u32 *pg_pri_orginal_spread,
+					    struct pg_help_data *help_data);
+static void bnx2x_dcbx_fill_cos_params(struct bnx2x *bp,
+				       struct pg_help_data *help_data,
+				       struct dcbx_ets_feature *ets,
+				       u32 *pg_pri_orginal_spread);
+static void bnx2x_dcbx_separate_pauseable_from_non(struct bnx2x *bp,
+				struct cos_help_data *cos_data,
+				u32 *pg_pri_orginal_spread,
+				struct dcbx_ets_feature *ets);
+static void bnx2x_pfc_fw_struct_e2(struct bnx2x *bp);
+
+
+static void bnx2x_pfc_set(struct bnx2x *bp)
+{
+	struct bnx2x_nig_brb_pfc_port_params pfc_params = {0};
+	u32 pri_bit, val = 0;
+	u8 pri;
+
+	/* Tx COS configuration */
+	if (bp->dcbx_port_params.ets.cos_params[0].pauseable)
+		pfc_params.rx_cos0_priority_mask =
+			bp->dcbx_port_params.ets.cos_params[0].pri_bitmask;
+	if (bp->dcbx_port_params.ets.cos_params[1].pauseable)
+		pfc_params.rx_cos1_priority_mask =
+			bp->dcbx_port_params.ets.cos_params[1].pri_bitmask;
+
+
+	/**
+	 * Rx COS configuration
+	 * Changing PFC RX configuration .
+	 * In RX COS0 will always be configured to lossy and COS1 to lossless
+	 */
+	for (pri = 0 ; pri < MAX_PFC_PRIORITIES ; pri++) {
+		pri_bit = 1 << pri;
+
+		if (pri_bit & DCBX_PFC_PRI_PAUSE_MASK(bp))
+			val |= 1 << (pri * 4);
+	}
+
+	pfc_params.pkt_priority_to_cos = val;
+
+	/* RX COS0 */
+	pfc_params.llfc_low_priority_classes = 0;
+	/* RX COS1 */
+	pfc_params.llfc_high_priority_classes = DCBX_PFC_PRI_PAUSE_MASK(bp);
+
+	/* BRB configuration */
+	pfc_params.cos0_pauseable = false;
+	pfc_params.cos1_pauseable = true;
+
+	bnx2x_acquire_phy_lock(bp);
+	bp->link_params.feature_config_flags |= FEATURE_CONFIG_PFC_ENABLED;
+	bnx2x_update_pfc(&bp->link_params, &bp->link_vars, &pfc_params);
+	bnx2x_release_phy_lock(bp);
+}
+
+static void bnx2x_pfc_clear(struct bnx2x *bp)
+{
+	struct bnx2x_nig_brb_pfc_port_params nig_params = {0};
+	nig_params.pause_enable = 1;
+#ifdef BNX2X_SAFC
+	if (bp->flags & SAFC_TX_FLAG) {
+		u32 high = 0, low = 0;
+		int i;
+
+		for (i = 0; i < BNX2X_MAX_PRIORITY; i++) {
+			if (bp->pri_map[i] == 1)
+				high |= (1 << i);
+			if (bp->pri_map[i] == 0)
+				low |= (1 << i);
+		}
+
+		nig_params.llfc_low_priority_classes = high;
+		nig_params.llfc_low_priority_classes = low;
+
+		nig_params.pause_enable = 0;
+		nig_params.llfc_enable = 1;
+		nig_params.llfc_out_en = 1;
+	}
+#endif /* BNX2X_SAFC */
+	bnx2x_acquire_phy_lock(bp);
+	bp->link_params.feature_config_flags &= ~FEATURE_CONFIG_PFC_ENABLED;
+	bnx2x_update_pfc(&bp->link_params, &bp->link_vars, &nig_params);
+	bnx2x_release_phy_lock(bp);
+}
+
+static void  bnx2x_dump_dcbx_drv_param(struct bnx2x *bp,
+				       struct dcbx_features *features,
+				       u32 error)
+{
+	u8 i = 0;
+	DP(NETIF_MSG_LINK, "local_mib.error %x\n", error);
+
+	/* PG */
+	DP(NETIF_MSG_LINK,
+	   "local_mib.features.ets.enabled %x\n", features->ets.enabled);
+	for (i = 0; i < DCBX_MAX_NUM_PG_BW_ENTRIES; i++)
+		DP(NETIF_MSG_LINK,
+		   "local_mib.features.ets.pg_bw_tbl[%d] %d\n", i,
+		   DCBX_PG_BW_GET(features->ets.pg_bw_tbl, i));
+	for (i = 0; i < DCBX_MAX_NUM_PRI_PG_ENTRIES; i++)
+		DP(NETIF_MSG_LINK,
+		   "local_mib.features.ets.pri_pg_tbl[%d] %d\n", i,
+		   DCBX_PRI_PG_GET(features->ets.pri_pg_tbl, i));
+
+	/* pfc */
+	DP(NETIF_MSG_LINK, "dcbx_features.pfc.pri_en_bitmap %x\n",
+					features->pfc.pri_en_bitmap);
+	DP(NETIF_MSG_LINK, "dcbx_features.pfc.pfc_caps %x\n",
+					features->pfc.pfc_caps);
+	DP(NETIF_MSG_LINK, "dcbx_features.pfc.enabled %x\n",
+					features->pfc.enabled);
+
+	DP(NETIF_MSG_LINK, "dcbx_features.app.default_pri %x\n",
+					features->app.default_pri);
+	DP(NETIF_MSG_LINK, "dcbx_features.app.tc_supported %x\n",
+					features->app.tc_supported);
+	DP(NETIF_MSG_LINK, "dcbx_features.app.enabled %x\n",
+					features->app.enabled);
+	for (i = 0; i < DCBX_MAX_APP_PROTOCOL; i++) {
+		DP(NETIF_MSG_LINK,
+		   "dcbx_features.app.app_pri_tbl[%x].app_id %x\n",
+		   i, features->app.app_pri_tbl[i].app_id);
+		DP(NETIF_MSG_LINK,
+		   "dcbx_features.app.app_pri_tbl[%x].pri_bitmap %x\n",
+		   i, features->app.app_pri_tbl[i].pri_bitmap);
+		DP(NETIF_MSG_LINK,
+		   "dcbx_features.app.app_pri_tbl[%x].appBitfield %x\n",
+		   i, features->app.app_pri_tbl[i].appBitfield);
+	}
+}
+
+static void bnx2x_dcbx_get_ap_priority(struct bnx2x *bp,
+				       u8 pri_bitmap,
+				       u8 llfc_traf_type)
+{
+	u32 pri = MAX_PFC_PRIORITIES;
+	u32 index = MAX_PFC_PRIORITIES - 1;
+	u32 pri_mask;
+	u32 *ttp = bp->dcbx_port_params.app.traffic_type_priority;
+
+	/* Choose the highest priority */
+	while ((MAX_PFC_PRIORITIES == pri) && (0 != index)) {
+		pri_mask = 1 << index;
+		if (GET_FLAGS(pri_bitmap, pri_mask))
+			pri = index ;
+		index--;
+	}
+
+	if (pri < MAX_PFC_PRIORITIES)
+		ttp[llfc_traf_type] = max_t(u32, ttp[llfc_traf_type], pri);
+}
+
+static void bnx2x_dcbx_get_ap_feature(struct bnx2x *bp,
+				   struct dcbx_app_priority_feature *app,
+				   u32 error) {
+	u8 index;
+	u32 *ttp = bp->dcbx_port_params.app.traffic_type_priority;
+
+	if (GET_FLAGS(error, DCBX_LOCAL_APP_ERROR))
+		DP(NETIF_MSG_LINK, "DCBX_LOCAL_APP_ERROR\n");
+
+	if (app->enabled && !GET_FLAGS(error, DCBX_LOCAL_APP_ERROR)) {
+
+		bp->dcbx_port_params.app.enabled = true;
+
+		for (index = 0 ; index < LLFC_DRIVER_TRAFFIC_TYPE_MAX; index++)
+			ttp[index] = 0;
+
+		if (app->default_pri < MAX_PFC_PRIORITIES)
+			ttp[LLFC_TRAFFIC_TYPE_NW] = app->default_pri;
+
+		for (index = 0 ; index < DCBX_MAX_APP_PROTOCOL; index++) {
+			struct dcbx_app_priority_entry *entry =
+							app->app_pri_tbl;
+
+			if (GET_FLAGS(entry[index].appBitfield,
+				     DCBX_APP_SF_ETH_TYPE) &&
+			   ETH_TYPE_FCOE == entry[index].app_id)
+				bnx2x_dcbx_get_ap_priority(bp,
+						entry[index].pri_bitmap,
+						LLFC_TRAFFIC_TYPE_FCOE);
+
+			if (GET_FLAGS(entry[index].appBitfield,
+				     DCBX_APP_SF_PORT) &&
+			   TCP_PORT_ISCSI == entry[index].app_id)
+				bnx2x_dcbx_get_ap_priority(bp,
+						entry[index].pri_bitmap,
+						LLFC_TRAFFIC_TYPE_ISCSI);
+		}
+	} else {
+		DP(NETIF_MSG_LINK, "DCBX_LOCAL_APP_DISABLED\n");
+		bp->dcbx_port_params.app.enabled = false;
+		for (index = 0 ; index < LLFC_DRIVER_TRAFFIC_TYPE_MAX; index++)
+			ttp[index] = INVALID_TRAFFIC_TYPE_PRIORITY;
+	}
+}
+
+static void bnx2x_dcbx_get_ets_feature(struct bnx2x *bp,
+				       struct dcbx_ets_feature *ets,
+				       u32 error) {
+	int i = 0;
+	u32 pg_pri_orginal_spread[DCBX_MAX_NUM_PG_BW_ENTRIES] = {0};
+	struct pg_help_data pg_help_data;
+	struct bnx2x_dcbx_cos_params *cos_params =
+			bp->dcbx_port_params.ets.cos_params;
+
+	memset(&pg_help_data, 0, sizeof(struct pg_help_data));
+
+
+	if (GET_FLAGS(error, DCBX_LOCAL_ETS_ERROR))
+		DP(NETIF_MSG_LINK, "DCBX_LOCAL_ETS_ERROR\n");
+
+
+	/* Clean up old settings of ets on COS */
+	for (i = 0; i < E2_NUM_OF_COS ; i++) {
+
+		cos_params[i].pauseable = false;
+		cos_params[i].strict = BNX2X_DCBX_COS_NOT_STRICT;
+		cos_params[i].bw_tbl = DCBX_INVALID_COS_BW;
+		cos_params[i].pri_bitmask = DCBX_PFC_PRI_GET_NON_PAUSE(bp, 0);
+	}
+
+	if (bp->dcbx_port_params.app.enabled &&
+	   !GET_FLAGS(error, DCBX_LOCAL_ETS_ERROR) &&
+	   ets->enabled) {
+		DP(NETIF_MSG_LINK, "DCBX_LOCAL_ETS_ENABLE\n");
+		bp->dcbx_port_params.ets.enabled = true;
+
+		bnx2x_dcbx_get_ets_pri_pg_tbl(bp,
+					      pg_pri_orginal_spread,
+					      ets->pri_pg_tbl);
+
+		bnx2x_dcbx_get_num_pg_traf_type(bp,
+						pg_pri_orginal_spread,
+						&pg_help_data);
+
+		bnx2x_dcbx_fill_cos_params(bp, &pg_help_data,
+					   ets, pg_pri_orginal_spread);
+
+	} else {
+		DP(NETIF_MSG_LINK, "DCBX_LOCAL_ETS_DISABLED\n");
+		bp->dcbx_port_params.ets.enabled = false;
+		ets->pri_pg_tbl[0] = 0;
+
+		for (i = 0; i < DCBX_MAX_NUM_PRI_PG_ENTRIES ; i++)
+			DCBX_PG_BW_SET(ets->pg_bw_tbl, i, 1);
+	}
+}
+
+static void  bnx2x_dcbx_get_pfc_feature(struct bnx2x *bp,
+					struct dcbx_pfc_feature *pfc, u32 error)
+{
+
+	if (GET_FLAGS(error, DCBX_LOCAL_PFC_ERROR))
+		DP(NETIF_MSG_LINK, "DCBX_LOCAL_PFC_ERROR\n");
+
+	if (bp->dcbx_port_params.app.enabled &&
+	   !GET_FLAGS(error, DCBX_LOCAL_PFC_ERROR) &&
+	   pfc->enabled) {
+		bp->dcbx_port_params.pfc.enabled = true;
+		bp->dcbx_port_params.pfc.priority_non_pauseable_mask =
+			~(pfc->pri_en_bitmap);
+	} else {
+		DP(NETIF_MSG_LINK, "DCBX_LOCAL_PFC_DISABLED\n");
+		bp->dcbx_port_params.pfc.enabled = false;
+		bp->dcbx_port_params.pfc.priority_non_pauseable_mask = 0;
+	}
+}
+
+static void bnx2x_get_dcbx_drv_param(struct bnx2x *bp,
+				     struct dcbx_features *features,
+				     u32 error)
+{
+	bnx2x_dcbx_get_ap_feature(bp, &features->app, error);
+
+	bnx2x_dcbx_get_pfc_feature(bp, &features->pfc, error);
+
+	bnx2x_dcbx_get_ets_feature(bp, &features->ets, error);
+}
+
+#define DCBX_LOCAL_MIB_MAX_TRY_READ		(100)
+static int bnx2x_dcbx_read_mib(struct bnx2x *bp,
+			       u32 *base_mib_addr,
+			       u32 offset,
+			       int read_mib_type)
+{
+	int max_try_read = 0, i;
+	u32 *buff, mib_size, prefix_seq_num, suffix_seq_num;
+	struct lldp_remote_mib *remote_mib ;
+	struct lldp_local_mib  *local_mib;
+
+
+	switch (read_mib_type) {
+	case DCBX_READ_LOCAL_MIB:
+		mib_size = sizeof(struct lldp_local_mib);
+		break;
+	case DCBX_READ_REMOTE_MIB:
+		mib_size = sizeof(struct lldp_remote_mib);
+		break;
+	default:
+		return 1; /*error*/
+	}
+
+	offset += BP_PORT(bp) * mib_size;
+
+	do {
+		buff = base_mib_addr;
+		for (i = 0; i < mib_size; i += 4, buff++)
+			*buff = REG_RD(bp, offset + i);
+
+		max_try_read++;
+
+		switch (read_mib_type) {
+		case DCBX_READ_LOCAL_MIB:
+			local_mib = (struct lldp_local_mib *) base_mib_addr;
+			prefix_seq_num = local_mib->prefix_seq_num;
+			suffix_seq_num = local_mib->suffix_seq_num;
+			break;
+		case DCBX_READ_REMOTE_MIB:
+			remote_mib = (struct lldp_remote_mib *) base_mib_addr;
+			prefix_seq_num = remote_mib->prefix_seq_num;
+			suffix_seq_num = remote_mib->suffix_seq_num;
+			break;
+		default:
+			return 1; /*error*/
+		}
+	} while ((prefix_seq_num != suffix_seq_num) &&
+	       (max_try_read < DCBX_LOCAL_MIB_MAX_TRY_READ));
+
+	if (max_try_read >= DCBX_LOCAL_MIB_MAX_TRY_READ) {
+		BNX2X_ERR("MIB could not be read\n");
+		return 1;
+	}
+
+	return 0;
+}
+
+static void bnx2x_pfc_set_pfc(struct bnx2x *bp)
+{
+	if (CHIP_IS_E2(bp)) {
+		if (BP_PORT(bp)) {
+			BNX2X_ERR("4 port mode is not supported");
+			return;
+		}
+
+		if (bp->dcbx_port_params.pfc.enabled)
+
+			/* 1. Fills up common PFC structures if required.*/
+			/* 2. Configure NIG, MAC and BRB via the elink:
+			 *    elink must first check if BMAC is not in reset
+			 *    and only then configures the BMAC
+			 *    Or, configure EMAC.
+			 */
+			bnx2x_pfc_set(bp);
+
+		else
+			bnx2x_pfc_clear(bp);
+	}
+}
+
+static void bnx2x_dcbx_stop_hw_tx(struct bnx2x *bp)
+{
+	DP(NETIF_MSG_LINK, "sending STOP TRAFFIC\n");
+	bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_STOP_TRAFFIC,
+		      0 /* connectionless */,
+		      0 /* dataHi is zero */,
+		      0 /* dataLo is zero */,
+		      1 /* common */);
+}
+
+static void bnx2x_dcbx_resume_hw_tx(struct bnx2x *bp)
+{
+	bnx2x_pfc_fw_struct_e2(bp);
+	DP(NETIF_MSG_LINK, "sending START TRAFFIC\n");
+	bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_START_TRAFFIC,
+		      0, /* connectionless */
+		      U64_HI(bnx2x_sp_mapping(bp, pfc_config)),
+		      U64_LO(bnx2x_sp_mapping(bp, pfc_config)),
+		      1  /* commmon */);
+}
+
+static void bnx2x_dcbx_update_ets_params(struct bnx2x *bp)
+{
+	struct bnx2x_dcbx_pg_params *ets = &(bp->dcbx_port_params.ets);
+	u8	status = 0;
+
+	bnx2x_ets_disabled(&bp->link_params);
+
+	if (!ets->enabled)
+		return;
+
+	if ((ets->num_of_cos == 0) || (ets->num_of_cos > E2_NUM_OF_COS)) {
+		BNX2X_ERR("illegal num of cos= %x", ets->num_of_cos);
+		return;
+	}
+
+	/* valid COS entries */
+	if (ets->num_of_cos == 1)   /* no ETS */
+		return;
+
+	/* sanity */
+	if (((BNX2X_DCBX_COS_NOT_STRICT == ets->cos_params[0].strict) &&
+	     (DCBX_INVALID_COS_BW == ets->cos_params[0].bw_tbl)) ||
+	    ((BNX2X_DCBX_COS_NOT_STRICT == ets->cos_params[1].strict) &&
+	     (DCBX_INVALID_COS_BW == ets->cos_params[1].bw_tbl))) {
+		BNX2X_ERR("all COS should have at least bw_limit or strict"
+			    "ets->cos_params[0].strict= %x"
+			    "ets->cos_params[0].bw_tbl= %x"
+			    "ets->cos_params[1].strict= %x"
+			    "ets->cos_params[1].bw_tbl= %x",
+			  ets->cos_params[0].strict,
+			  ets->cos_params[0].bw_tbl,
+			  ets->cos_params[1].strict,
+			  ets->cos_params[1].bw_tbl);
+		return;
+	}
+	/* If we join a group and there is bw_tbl and strict then bw rules */
+	if ((DCBX_INVALID_COS_BW != ets->cos_params[0].bw_tbl) &&
+	    (DCBX_INVALID_COS_BW != ets->cos_params[1].bw_tbl)) {
+		u32 bw_tbl_0 = ets->cos_params[0].bw_tbl;
+		u32 bw_tbl_1 = ets->cos_params[1].bw_tbl;
+		/* Do not allow 0-100 configuration
+		 * since PBF does not support it
+		 * force 1-99 instead
+		 */
+		if (bw_tbl_0 == 0) {
+			bw_tbl_0 = 1;
+			bw_tbl_1 = 99;
+		} else if (bw_tbl_1 == 0) {
+			bw_tbl_1 = 1;
+			bw_tbl_0 = 99;
+		}
+
+		bnx2x_ets_bw_limit(&bp->link_params, bw_tbl_0, bw_tbl_1);
+	} else {
+		if (ets->cos_params[0].strict == BNX2X_DCBX_COS_HIGH_STRICT)
+			status = bnx2x_ets_strict(&bp->link_params, 0);
+		else if (ets->cos_params[1].strict
+						== BNX2X_DCBX_COS_HIGH_STRICT)
+			status = bnx2x_ets_strict(&bp->link_params, 1);
+
+		if (status)
+			BNX2X_ERR("update_ets_params failed\n");
+	}
+}
+
+static int bnx2x_dcbx_read_shmem_neg_results(struct bnx2x *bp)
+{
+	struct lldp_local_mib local_mib = {0};
+	u32 dcbx_neg_res_offset = SHMEM2_RD(bp, dcbx_neg_res_offset);
+	int rc;
+
+	DP(NETIF_MSG_LINK, "dcbx_neg_res_offset 0x%x\n", dcbx_neg_res_offset);
+
+	if (SHMEM_DCBX_NEG_RES_NONE == dcbx_neg_res_offset) {
+		BNX2X_ERR("FW doesn't support dcbx_neg_res_offset\n");
+		return -EINVAL;
+	}
+	rc = bnx2x_dcbx_read_mib(bp, (u32 *)&local_mib, dcbx_neg_res_offset,
+				 DCBX_READ_LOCAL_MIB);
+
+	if (rc) {
+		BNX2X_ERR("Faild to read local mib from FW\n");
+		return rc;
+	}
+
+	/* save features and error */
+	bp->dcbx_local_feat = local_mib.features;
+	bp->dcbx_error = local_mib.error;
+	return 0;
+}
+
+void bnx2x_dcbx_set_params(struct bnx2x *bp, u32 state)
+{
+	switch (state) {
+	case BNX2X_DCBX_STATE_NEG_RECEIVED:
+		{
+			DP(NETIF_MSG_LINK, "BNX2X_DCBX_STATE_NEG_RECEIVED\n");
+
+			/* Read neg results if dcbx is in the FW */
+			if (bnx2x_dcbx_read_shmem_neg_results(bp))
+				return;
+
+			bnx2x_dump_dcbx_drv_param(bp, &bp->dcbx_local_feat,
+						  bp->dcbx_error);
+
+			bnx2x_get_dcbx_drv_param(bp, &bp->dcbx_local_feat,
+						 bp->dcbx_error);
+
+			if (bp->state != BNX2X_STATE_OPENING_WAIT4_LOAD) {
+				bnx2x_dcbx_stop_hw_tx(bp);
+				return;
+			}
+			/* fall through */
+		}
+	case BNX2X_DCBX_STATE_TX_PAUSED:
+		DP(NETIF_MSG_LINK, "BNX2X_DCBX_STATE_TX_PAUSED\n");
+		bnx2x_pfc_set_pfc(bp);
+
+		bnx2x_dcbx_update_ets_params(bp);
+		if (bp->state != BNX2X_STATE_OPENING_WAIT4_LOAD) {
+			bnx2x_dcbx_resume_hw_tx(bp);
+			return;
+		}
+		/* fall through */
+	case BNX2X_DCBX_STATE_TX_RELEASED:
+		DP(NETIF_MSG_LINK, "BNX2X_DCBX_STATE_TX_RELEASED\n");
+		if (bp->state != BNX2X_STATE_OPENING_WAIT4_LOAD)
+			bnx2x_fw_command(bp, DRV_MSG_CODE_DCBX_PMF_DRV_OK, 0);
+
+		return;
+	default:
+		BNX2X_ERR("Unknown DCBX_STATE\n");
+	}
+}
+
+
+#define LLDP_STATS_OFFSET(bp)		(BP_PORT(bp)*\
+					sizeof(struct lldp_dcbx_stat))
+
+/* calculate struct offset in array according to chip information */
+#define LLDP_PARAMS_OFFSET(bp)		(BP_PORT(bp)*sizeof(struct lldp_params))
+
+#define LLDP_ADMIN_MIB_OFFSET(bp)	(PORT_MAX*sizeof(struct lldp_params) + \
+				      BP_PORT(bp)*sizeof(struct lldp_admin_mib))
+
+static void bnx2x_dcbx_lldp_updated_params(struct bnx2x *bp,
+					   u32 dcbx_lldp_params_offset)
+{
+	struct lldp_params lldp_params = {0};
+	u32 i = 0, *buff = NULL;
+	u32 offset = dcbx_lldp_params_offset + LLDP_PARAMS_OFFSET(bp);
+
+	DP(NETIF_MSG_LINK, "lldp_offset 0x%x\n", offset);
+
+	if ((bp->lldp_config_params.overwrite_settings ==
+				BNX2X_DCBX_OVERWRITE_SETTINGS_ENABLE)) {
+		/* Read the data first */
+		buff = (u32 *)&lldp_params;
+		for (i = 0; i < sizeof(struct lldp_params); i += 4,  buff++)
+			*buff = REG_RD(bp, (offset + i));
+
+		lldp_params.msg_tx_hold =
+			(u8)bp->lldp_config_params.msg_tx_hold;
+		lldp_params.msg_fast_tx_interval =
+			(u8)bp->lldp_config_params.msg_fast_tx;
+		lldp_params.tx_crd_max =
+			(u8)bp->lldp_config_params.tx_credit_max;
+		lldp_params.msg_tx_interval =
+			(u8)bp->lldp_config_params.msg_tx_interval;
+		lldp_params.tx_fast =
+			(u8)bp->lldp_config_params.tx_fast;
+
+		/* Write the data.*/
+		buff = (u32 *)&lldp_params;
+		for (i = 0; i < sizeof(struct lldp_params); i += 4, buff++)
+			REG_WR(bp, (offset + i) , *buff);
+
+
+	} else if (BNX2X_DCBX_OVERWRITE_SETTINGS_ENABLE ==
+				bp->lldp_config_params.overwrite_settings)
+		bp->lldp_config_params.overwrite_settings =
+				BNX2X_DCBX_OVERWRITE_SETTINGS_INVALID;
+}
+
+static void bnx2x_dcbx_admin_mib_updated_params(struct bnx2x *bp,
+				u32 dcbx_lldp_params_offset)
+{
+	struct lldp_admin_mib admin_mib;
+	u32 i, other_traf_type = PREDEFINED_APP_IDX_MAX, traf_type = 0;
+	u32 *buff;
+	u32 offset = dcbx_lldp_params_offset + LLDP_ADMIN_MIB_OFFSET(bp);
+
+	/*shortcuts*/
+	struct dcbx_features *af = &admin_mib.features;
+	struct bnx2x_config_dcbx_params *dp = &bp->dcbx_config_params;
+
+	memset(&admin_mib, 0, sizeof(struct lldp_admin_mib));
+	buff = (u32 *)&admin_mib;
+	/* Read the data first */
+	for (i = 0; i < sizeof(struct lldp_admin_mib); i += 4, buff++)
+		*buff = REG_RD(bp, (offset + i));
+
+	if (bp->dcbx_enabled == BNX2X_DCBX_ENABLED_ON_NEG_ON)
+		SET_FLAGS(admin_mib.ver_cfg_flags, DCBX_DCBX_ENABLED);
+	else
+		RESET_FLAGS(admin_mib.ver_cfg_flags, DCBX_DCBX_ENABLED);
+
+	if ((BNX2X_DCBX_OVERWRITE_SETTINGS_ENABLE ==
+				dp->overwrite_settings)) {
+		RESET_FLAGS(admin_mib.ver_cfg_flags, DCBX_CEE_VERSION_MASK);
+		admin_mib.ver_cfg_flags |=
+			(dp->admin_dcbx_version << DCBX_CEE_VERSION_SHIFT) &
+			 DCBX_CEE_VERSION_MASK;
+
+		af->ets.enabled = (u8)dp->admin_ets_enable;
+
+		af->pfc.enabled = (u8)dp->admin_pfc_enable;
+
+		/* FOR IEEE dp->admin_tc_supported_tx_enable */
+		if (dp->admin_ets_configuration_tx_enable)
+			SET_FLAGS(admin_mib.ver_cfg_flags,
+				  DCBX_ETS_CONFIG_TX_ENABLED);
+		else
+			RESET_FLAGS(admin_mib.ver_cfg_flags,
+				    DCBX_ETS_CONFIG_TX_ENABLED);
+		/* For IEEE admin_ets_recommendation_tx_enable */
+		if (dp->admin_pfc_tx_enable)
+			SET_FLAGS(admin_mib.ver_cfg_flags,
+				  DCBX_PFC_CONFIG_TX_ENABLED);
+		else
+			RESET_FLAGS(admin_mib.ver_cfg_flags,
+				  DCBX_PFC_CONFIG_TX_ENABLED);
+
+		if (dp->admin_application_priority_tx_enable)
+			SET_FLAGS(admin_mib.ver_cfg_flags,
+				  DCBX_APP_CONFIG_TX_ENABLED);
+		else
+			RESET_FLAGS(admin_mib.ver_cfg_flags,
+				  DCBX_APP_CONFIG_TX_ENABLED);
+
+		if (dp->admin_ets_willing)
+			SET_FLAGS(admin_mib.ver_cfg_flags, DCBX_ETS_WILLING);
+		else
+			RESET_FLAGS(admin_mib.ver_cfg_flags, DCBX_ETS_WILLING);
+		/* For IEEE admin_ets_reco_valid */
+		if (dp->admin_pfc_willing)
+			SET_FLAGS(admin_mib.ver_cfg_flags, DCBX_PFC_WILLING);
+		else
+			RESET_FLAGS(admin_mib.ver_cfg_flags, DCBX_PFC_WILLING);
+
+		if (dp->admin_app_priority_willing)
+			SET_FLAGS(admin_mib.ver_cfg_flags, DCBX_APP_WILLING);
+		else
+			RESET_FLAGS(admin_mib.ver_cfg_flags, DCBX_APP_WILLING);
+
+		for (i = 0 ; i < DCBX_MAX_NUM_PG_BW_ENTRIES; i++) {
+			DCBX_PG_BW_SET(af->ets.pg_bw_tbl, i,
+				(u8)dp->admin_configuration_bw_precentage[i]);
+
+			DP(NETIF_MSG_LINK, "pg_bw_tbl[%d] = %02x\n",
+			   i, DCBX_PG_BW_GET(af->ets.pg_bw_tbl, i));
+		}
+
+		for (i = 0; i < DCBX_MAX_NUM_PRI_PG_ENTRIES; i++) {
+			DCBX_PRI_PG_SET(af->ets.pri_pg_tbl, i,
+					(u8)dp->admin_configuration_ets_pg[i]);
+
+			DP(NETIF_MSG_LINK, "pri_pg_tbl[%d] = %02x\n",
+			   i, DCBX_PRI_PG_GET(af->ets.pri_pg_tbl, i));
+		}
+
+		/*For IEEE admin_recommendation_bw_precentage
+		 *For IEEE admin_recommendation_ets_pg */
+		af->pfc.pri_en_bitmap = (u8)dp->admin_pfc_bitmap;
+		for (i = 0; i < 4; i++) {
+			if (dp->admin_priority_app_table[i].valid) {
+				struct bnx2x_admin_priority_app_table *table =
+					dp->admin_priority_app_table;
+				if ((ETH_TYPE_FCOE == table[i].app_id) &&
+				   (TRAFFIC_TYPE_ETH == table[i].traffic_type))
+					traf_type = FCOE_APP_IDX;
+				else if ((TCP_PORT_ISCSI == table[i].app_id) &&
+				   (TRAFFIC_TYPE_PORT == table[i].traffic_type))
+					traf_type = ISCSI_APP_IDX;
+				else
+					traf_type = other_traf_type++;
+
+				af->app.app_pri_tbl[traf_type].app_id =
+					table[i].app_id;
+
+				af->app.app_pri_tbl[traf_type].pri_bitmap =
+					(u8)(1 << table[i].priority);
+
+				af->app.app_pri_tbl[traf_type].appBitfield =
+				    (DCBX_APP_ENTRY_VALID);
+
+				af->app.app_pri_tbl[traf_type].appBitfield |=
+				   (TRAFFIC_TYPE_ETH == table[i].traffic_type) ?
+					DCBX_APP_SF_ETH_TYPE : DCBX_APP_SF_PORT;
+			}
+		}
+
+		af->app.default_pri = (u8)dp->admin_default_priority;
+
+	} else if (BNX2X_DCBX_OVERWRITE_SETTINGS_ENABLE ==
+						dp->overwrite_settings)
+		dp->overwrite_settings = BNX2X_DCBX_OVERWRITE_SETTINGS_INVALID;
+
+	/* Write the data. */
+	buff = (u32 *)&admin_mib;
+	for (i = 0; i < sizeof(struct lldp_admin_mib); i += 4, buff++)
+		REG_WR(bp, (offset + i), *buff);
+}
+
+void bnx2x_dcbx_set_state(struct bnx2x *bp, bool dcb_on, u32 dcbx_enabled)
+{
+	if (CHIP_IS_E2(bp) && !CHIP_MODE_IS_4_PORT(bp)) {
+		bp->dcb_state = dcb_on;
+		bp->dcbx_enabled = dcbx_enabled;
+	} else {
+		bp->dcb_state = false;
+		bp->dcbx_enabled = BNX2X_DCBX_ENABLED_INVALID;
+	}
+	DP(NETIF_MSG_LINK, "DCB state [%s:%s]\n",
+	   dcb_on ? "ON" : "OFF",
+	   dcbx_enabled == BNX2X_DCBX_ENABLED_OFF ? "user-mode" :
+	   dcbx_enabled == BNX2X_DCBX_ENABLED_ON_NEG_OFF ? "on-chip static" :
+	   dcbx_enabled == BNX2X_DCBX_ENABLED_ON_NEG_ON ?
+	   "on-chip with negotiation" : "invalid");
+}
+
+void bnx2x_dcbx_init_params(struct bnx2x *bp)
+{
+	bp->dcbx_config_params.admin_dcbx_version = 0x0; /* 0 - CEE; 1 - IEEE */
+	bp->dcbx_config_params.admin_ets_willing = 1;
+	bp->dcbx_config_params.admin_pfc_willing = 1;
+	bp->dcbx_config_params.overwrite_settings = 1;
+	bp->dcbx_config_params.admin_ets_enable = 1;
+	bp->dcbx_config_params.admin_pfc_enable = 1;
+	bp->dcbx_config_params.admin_tc_supported_tx_enable = 1;
+	bp->dcbx_config_params.admin_ets_configuration_tx_enable = 1;
+	bp->dcbx_config_params.admin_pfc_tx_enable = 1;
+	bp->dcbx_config_params.admin_application_priority_tx_enable = 1;
+	bp->dcbx_config_params.admin_ets_reco_valid = 1;
+	bp->dcbx_config_params.admin_app_priority_willing = 1;
+	bp->dcbx_config_params.admin_configuration_bw_precentage[0] = 00;
+	bp->dcbx_config_params.admin_configuration_bw_precentage[1] = 50;
+	bp->dcbx_config_params.admin_configuration_bw_precentage[2] = 50;
+	bp->dcbx_config_params.admin_configuration_bw_precentage[3] = 0;
+	bp->dcbx_config_params.admin_configuration_bw_precentage[4] = 0;
+	bp->dcbx_config_params.admin_configuration_bw_precentage[5] = 0;
+	bp->dcbx_config_params.admin_configuration_bw_precentage[6] = 0;
+	bp->dcbx_config_params.admin_configuration_bw_precentage[7] = 0;
+	bp->dcbx_config_params.admin_configuration_ets_pg[0] = 1;
+	bp->dcbx_config_params.admin_configuration_ets_pg[1] = 0;
+	bp->dcbx_config_params.admin_configuration_ets_pg[2] = 0;
+	bp->dcbx_config_params.admin_configuration_ets_pg[3] = 2;
+	bp->dcbx_config_params.admin_configuration_ets_pg[4] = 0;
+	bp->dcbx_config_params.admin_configuration_ets_pg[5] = 0;
+	bp->dcbx_config_params.admin_configuration_ets_pg[6] = 0;
+	bp->dcbx_config_params.admin_configuration_ets_pg[7] = 0;
+	bp->dcbx_config_params.admin_recommendation_bw_precentage[0] = 0;
+	bp->dcbx_config_params.admin_recommendation_bw_precentage[1] = 1;
+	bp->dcbx_config_params.admin_recommendation_bw_precentage[2] = 2;
+	bp->dcbx_config_params.admin_recommendation_bw_precentage[3] = 0;
+	bp->dcbx_config_params.admin_recommendation_bw_precentage[4] = 7;
+	bp->dcbx_config_params.admin_recommendation_bw_precentage[5] = 5;
+	bp->dcbx_config_params.admin_recommendation_bw_precentage[6] = 6;
+	bp->dcbx_config_params.admin_recommendation_bw_precentage[7] = 7;
+	bp->dcbx_config_params.admin_recommendation_ets_pg[0] = 0;
+	bp->dcbx_config_params.admin_recommendation_ets_pg[1] = 1;
+	bp->dcbx_config_params.admin_recommendation_ets_pg[2] = 2;
+	bp->dcbx_config_params.admin_recommendation_ets_pg[3] = 3;
+	bp->dcbx_config_params.admin_recommendation_ets_pg[4] = 4;
+	bp->dcbx_config_params.admin_recommendation_ets_pg[5] = 5;
+	bp->dcbx_config_params.admin_recommendation_ets_pg[6] = 6;
+	bp->dcbx_config_params.admin_recommendation_ets_pg[7] = 7;
+	bp->dcbx_config_params.admin_pfc_bitmap = 0x8; /* FCoE(3) enable */
+	bp->dcbx_config_params.admin_priority_app_table[0].valid = 1;
+	bp->dcbx_config_params.admin_priority_app_table[1].valid = 1;
+	bp->dcbx_config_params.admin_priority_app_table[2].valid = 0;
+	bp->dcbx_config_params.admin_priority_app_table[3].valid = 0;
+	bp->dcbx_config_params.admin_priority_app_table[0].priority = 3;
+	bp->dcbx_config_params.admin_priority_app_table[1].priority = 0;
+	bp->dcbx_config_params.admin_priority_app_table[2].priority = 0;
+	bp->dcbx_config_params.admin_priority_app_table[3].priority = 0;
+	bp->dcbx_config_params.admin_priority_app_table[0].traffic_type = 0;
+	bp->dcbx_config_params.admin_priority_app_table[1].traffic_type = 1;
+	bp->dcbx_config_params.admin_priority_app_table[2].traffic_type = 0;
+	bp->dcbx_config_params.admin_priority_app_table[3].traffic_type = 0;
+	bp->dcbx_config_params.admin_priority_app_table[0].app_id = 0x8906;
+	bp->dcbx_config_params.admin_priority_app_table[1].app_id = 3260;
+	bp->dcbx_config_params.admin_priority_app_table[2].app_id = 0;
+	bp->dcbx_config_params.admin_priority_app_table[3].app_id = 0;
+	bp->dcbx_config_params.admin_default_priority =
+		bp->dcbx_config_params.admin_priority_app_table[1].priority;
+}
+
+void bnx2x_dcbx_init(struct bnx2x *bp)
+{
+	u32 dcbx_lldp_params_offset = SHMEM_LLDP_DCBX_PARAMS_NONE;
+
+	if (bp->dcbx_enabled <= 0)
+		return;
+
+	/* validate:
+	 * chip of good for dcbx version,
+	 * dcb is wanted
+	 * the function is pmf
+	 * shmem2 contains DCBX support fields
+	 */
+	DP(NETIF_MSG_LINK, "dcb_state %d bp->port.pmf %d\n",
+	   bp->dcb_state, bp->port.pmf);
+
+	if (bp->dcb_state ==  BNX2X_DCB_STATE_ON && bp->port.pmf &&
+	    SHMEM2_HAS(bp, dcbx_lldp_params_offset)) {
+		dcbx_lldp_params_offset =
+			SHMEM2_RD(bp, dcbx_lldp_params_offset);
+
+		DP(NETIF_MSG_LINK, "dcbx_lldp_params_offset 0x%x\n",
+		   dcbx_lldp_params_offset);
+
+		if (SHMEM_LLDP_DCBX_PARAMS_NONE != dcbx_lldp_params_offset) {
+			bnx2x_dcbx_lldp_updated_params(bp,
+						       dcbx_lldp_params_offset);
+
+			bnx2x_dcbx_admin_mib_updated_params(bp,
+				dcbx_lldp_params_offset);
+
+			/* set default configuration BC has */
+			bnx2x_dcbx_set_params(bp,
+					      BNX2X_DCBX_STATE_NEG_RECEIVED);
+
+			bnx2x_fw_command(bp,
+					 DRV_MSG_CODE_DCBX_ADMIN_PMF_MSG, 0);
+		}
+	}
+}
+
+void bnx2x_dcb_init_intmem_pfc(struct bnx2x *bp)
+{
+	struct priority_cos pricos[MAX_PFC_TRAFFIC_TYPES];
+	u32 i = 0, addr;
+	memset(pricos, 0, sizeof(pricos));
+	/* Default initialization */
+	for (i = 0; i < MAX_PFC_TRAFFIC_TYPES; i++)
+		pricos[i].priority = LLFC_TRAFFIC_TYPE_TO_PRIORITY_UNMAPPED;
+
+	/* Store per port struct to internal memory */
+	addr = BAR_XSTRORM_INTMEM +
+			XSTORM_CMNG_PER_PORT_VARS_OFFSET(BP_PORT(bp)) +
+			offsetof(struct cmng_struct_per_port,
+				 traffic_type_to_priority_cos);
+	__storm_memset_struct(bp, addr, sizeof(pricos), (u32 *)pricos);
+
+
+	/* LLFC disabled.*/
+	REG_WR8(bp , BAR_XSTRORM_INTMEM +
+		    XSTORM_CMNG_PER_PORT_VARS_OFFSET(BP_PORT(bp)) +
+		    offsetof(struct cmng_struct_per_port, llfc_mode),
+			LLFC_MODE_NONE);
+
+	/* DCBX disabled.*/
+	REG_WR8(bp , BAR_XSTRORM_INTMEM +
+		    XSTORM_CMNG_PER_PORT_VARS_OFFSET(BP_PORT(bp)) +
+		    offsetof(struct cmng_struct_per_port, dcb_enabled),
+			DCB_DISABLED);
+}
+
+static void
+bnx2x_dcbx_print_cos_params(struct bnx2x *bp,
+			    struct flow_control_configuration *pfc_fw_cfg)
+{
+	u8 pri = 0;
+	u8 cos = 0;
+
+	DP(NETIF_MSG_LINK,
+	   "pfc_fw_cfg->dcb_version %x\n", pfc_fw_cfg->dcb_version);
+	DP(NETIF_MSG_LINK,
+	   "pdev->params.dcbx_port_params.pfc."
+	   "priority_non_pauseable_mask %x\n",
+	   bp->dcbx_port_params.pfc.priority_non_pauseable_mask);
+
+	for (cos = 0 ; cos < bp->dcbx_port_params.ets.num_of_cos ; cos++) {
+		DP(NETIF_MSG_LINK, "pdev->params.dcbx_port_params.ets."
+		   "cos_params[%d].pri_bitmask %x\n", cos,
+		   bp->dcbx_port_params.ets.cos_params[cos].pri_bitmask);
+
+		DP(NETIF_MSG_LINK, "pdev->params.dcbx_port_params.ets."
+		   "cos_params[%d].bw_tbl %x\n", cos,
+		   bp->dcbx_port_params.ets.cos_params[cos].bw_tbl);
+
+		DP(NETIF_MSG_LINK, "pdev->params.dcbx_port_params.ets."
+		   "cos_params[%d].strict %x\n", cos,
+		   bp->dcbx_port_params.ets.cos_params[cos].strict);
+
+		DP(NETIF_MSG_LINK, "pdev->params.dcbx_port_params.ets."
+		   "cos_params[%d].pauseable %x\n", cos,
+		   bp->dcbx_port_params.ets.cos_params[cos].pauseable);
+	}
+
+	for (pri = 0; pri < LLFC_DRIVER_TRAFFIC_TYPE_MAX; pri++) {
+		DP(NETIF_MSG_LINK,
+		   "pfc_fw_cfg->traffic_type_to_priority_cos[%d]."
+		   "priority %x\n", pri,
+		   pfc_fw_cfg->traffic_type_to_priority_cos[pri].priority);
+
+		DP(NETIF_MSG_LINK,
+		   "pfc_fw_cfg->traffic_type_to_priority_cos[%d].cos %x\n",
+		   pri, pfc_fw_cfg->traffic_type_to_priority_cos[pri].cos);
+	}
+}
+
+/* fills help_data according to pg_info */
+static void bnx2x_dcbx_get_num_pg_traf_type(struct bnx2x *bp,
+					    u32 *pg_pri_orginal_spread,
+					    struct pg_help_data *help_data)
+{
+	bool pg_found  = false;
+	u32 i, traf_type, add_traf_type, add_pg;
+	u32 *ttp = bp->dcbx_port_params.app.traffic_type_priority;
+	struct pg_entry_help_data *data = help_data->data; /*shotcut*/
+
+	/* Set to invalid */
+	for (i = 0; i < LLFC_DRIVER_TRAFFIC_TYPE_MAX; i++)
+		data[i].pg = DCBX_ILLEGAL_PG;
+
+	for (add_traf_type = 0;
+	     add_traf_type < LLFC_DRIVER_TRAFFIC_TYPE_MAX; add_traf_type++) {
+		pg_found = false;
+		if (ttp[add_traf_type] < MAX_PFC_PRIORITIES) {
+			add_pg = (u8)pg_pri_orginal_spread[ttp[add_traf_type]];
+			for (traf_type = 0;
+			     traf_type < LLFC_DRIVER_TRAFFIC_TYPE_MAX;
+			     traf_type++) {
+				if (data[traf_type].pg == add_pg) {
+					if (!(data[traf_type].pg_priority &
+					     (1 << ttp[add_traf_type])))
+						data[traf_type].
+							num_of_dif_pri++;
+					data[traf_type].pg_priority |=
+						(1 << ttp[add_traf_type]);
+					pg_found = true;
+					break;
+				}
+			}
+			if (false == pg_found) {
+				data[help_data->num_of_pg].pg = add_pg;
+				data[help_data->num_of_pg].pg_priority =
+						(1 << ttp[add_traf_type]);
+				data[help_data->num_of_pg].num_of_dif_pri = 1;
+				help_data->num_of_pg++;
+			}
+		}
+		DP(NETIF_MSG_LINK,
+		   "add_traf_type %d pg_found %s num_of_pg %d\n",
+		   add_traf_type, (false == pg_found) ? "NO" : "YES",
+		   help_data->num_of_pg);
+	}
+}
+
+
+/*******************************************************************************
+ * Description: single priority group
+ *
+ * Return:
+ ******************************************************************************/
+static void bnx2x_dcbx_ets_disabled_entry_data(struct bnx2x *bp,
+					       struct cos_help_data *cos_data,
+					       u32 pri_join_mask)
+{
+	/* Only one priority than only one COS */
+	cos_data->data[0].pausable =
+		IS_DCBX_PFC_PRI_ONLY_PAUSE(bp, pri_join_mask);
+	cos_data->data[0].pri_join_mask = pri_join_mask;
+	cos_data->data[0].cos_bw = 100;
+	cos_data->num_of_cos = 1;
+}
+
+/*******************************************************************************
+ * Description: updating the cos bw
+ *
+ * Return:
+ ******************************************************************************/
+static inline void bnx2x_dcbx_add_to_cos_bw(struct bnx2x *bp,
+					    struct cos_entry_help_data *data,
+					    u8 pg_bw)
+{
+	if (data->cos_bw == DCBX_INVALID_COS_BW)
+		data->cos_bw = pg_bw;
+	else
+		data->cos_bw += pg_bw;
+}
+
+/*******************************************************************************
+ * Description: single priority group
+ *
+ * Return:
+ ******************************************************************************/
+static void bnx2x_dcbx_separate_pauseable_from_non(struct bnx2x *bp,
+			struct cos_help_data *cos_data,
+			u32 *pg_pri_orginal_spread,
+			struct dcbx_ets_feature *ets)
+{
+	u32	pri_tested	= 0;
+	u8	i		= 0;
+	u8	entry		= 0;
+	u8	pg_entry	= 0;
+	u8	num_of_pri	= LLFC_DRIVER_TRAFFIC_TYPE_MAX;
+
+	cos_data->data[0].pausable = true;
+	cos_data->data[1].pausable = false;
+	cos_data->data[0].pri_join_mask = cos_data->data[1].pri_join_mask = 0;
+
+	for (i = 0 ; i < num_of_pri ; i++) {
+		pri_tested = 1 << bp->dcbx_port_params.
+					app.traffic_type_priority[i];
+
+		if (pri_tested & DCBX_PFC_PRI_NON_PAUSE_MASK(bp)) {
+			cos_data->data[1].pri_join_mask |= pri_tested;
+			entry = 1;
+		} else {
+			cos_data->data[0].pri_join_mask |= pri_tested;
+			entry = 0;
+		}
+		pg_entry = (u8)pg_pri_orginal_spread[bp->dcbx_port_params.
+						app.traffic_type_priority[i]];
+		/* There can be only one strict pg */
+		if (pg_entry < DCBX_MAX_NUM_PG_BW_ENTRIES)
+			bnx2x_dcbx_add_to_cos_bw(bp, &cos_data->data[entry],
+				DCBX_PG_BW_GET(ets->pg_bw_tbl, pg_entry));
+		else
+			/* If we join a group and one is strict
+			 * than the bw rulls */
+			cos_data->data[entry].strict =
+						BNX2X_DCBX_COS_HIGH_STRICT;
+	}
+	if ((0 == cos_data->data[0].pri_join_mask) &&
+	    (0 == cos_data->data[1].pri_join_mask))
+		BNX2X_ERR("dcbx error: Both groups must have priorities\n");
+}
+
+
+#ifndef POWER_OF_2
+#define POWER_OF_2(x)	((0 != x) && (0 == (x & (x-1))))
+#endif
+
+static void bxn2x_dcbx_single_pg_to_cos_params(struct bnx2x *bp,
+					      struct pg_help_data *pg_help_data,
+					      struct cos_help_data *cos_data,
+					      u32 pri_join_mask,
+					      u8 num_of_dif_pri)
+{
+	u8 i = 0;
+	u32 pri_tested = 0;
+	u32 pri_mask_without_pri = 0;
+	u32 *ttp = bp->dcbx_port_params.app.traffic_type_priority;
+	/*debug*/
+	if (num_of_dif_pri == 1) {
+		bnx2x_dcbx_ets_disabled_entry_data(bp, cos_data, pri_join_mask);
+		return;
+	}
+	/* single priority group */
+	if (pg_help_data->data[0].pg < DCBX_MAX_NUM_PG_BW_ENTRIES) {
+		/* If there are both pauseable and non-pauseable priorities,
+		 * the pauseable priorities go to the first queue and
+		 * the non-pauseable priorities go to the second queue.
+		 */
+		if (IS_DCBX_PFC_PRI_MIX_PAUSE(bp, pri_join_mask)) {
+			/* Pauseable */
+			cos_data->data[0].pausable = true;
+			/* Non pauseable.*/
+			cos_data->data[1].pausable = false;
+
+			if (2 == num_of_dif_pri) {
+				cos_data->data[0].cos_bw = 50;
+				cos_data->data[1].cos_bw = 50;
+			}
+
+			if (3 == num_of_dif_pri) {
+				if (POWER_OF_2(DCBX_PFC_PRI_GET_PAUSE(bp,
+							pri_join_mask))) {
+					cos_data->data[0].cos_bw = 33;
+					cos_data->data[1].cos_bw = 67;
+				} else {
+					cos_data->data[0].cos_bw = 67;
+					cos_data->data[1].cos_bw = 33;
+				}
+			}
+
+		} else if (IS_DCBX_PFC_PRI_ONLY_PAUSE(bp, pri_join_mask)) {
+			/* If there are only pauseable priorities,
+			 * then one/two priorities go to the first queue
+			 * and one priority goes to the second queue.
+			 */
+			if (2 == num_of_dif_pri) {
+				cos_data->data[0].cos_bw = 50;
+				cos_data->data[1].cos_bw = 50;
+			} else {
+				cos_data->data[0].cos_bw = 67;
+				cos_data->data[1].cos_bw = 33;
+			}
+			cos_data->data[1].pausable = true;
+			cos_data->data[0].pausable = true;
+			/* All priorities except FCOE */
+			cos_data->data[0].pri_join_mask = (pri_join_mask &
+				((u8)~(1 << ttp[LLFC_TRAFFIC_TYPE_FCOE])));
+			/* Only FCOE priority.*/
+			cos_data->data[1].pri_join_mask =
+				(1 << ttp[LLFC_TRAFFIC_TYPE_FCOE]);
+		} else
+			/* If there are only non-pauseable priorities,
+			 * they will all go to the same queue.
+			 */
+			bnx2x_dcbx_ets_disabled_entry_data(bp,
+						cos_data, pri_join_mask);
+	} else {
+		/* priority group which is not BW limited (PG#15):*/
+		if (IS_DCBX_PFC_PRI_MIX_PAUSE(bp, pri_join_mask)) {
+			/* If there are both pauseable and non-pauseable
+			 * priorities, the pauseable priorities go to the first
+			 * queue and the non-pauseable priorities
+			 * go to the second queue.
+			 */
+			if (DCBX_PFC_PRI_GET_PAUSE(bp, pri_join_mask) >
+			    DCBX_PFC_PRI_GET_NON_PAUSE(bp, pri_join_mask)) {
+				cos_data->data[0].strict =
+					BNX2X_DCBX_COS_HIGH_STRICT;
+				cos_data->data[1].strict =
+					BNX2X_DCBX_COS_LOW_STRICT;
+			} else {
+				cos_data->data[0].strict =
+					BNX2X_DCBX_COS_LOW_STRICT;
+				cos_data->data[1].strict =
+					BNX2X_DCBX_COS_HIGH_STRICT;
+			}
+			/* Pauseable */
+			cos_data->data[0].pausable = true;
+			/* Non pause-able.*/
+			cos_data->data[1].pausable = false;
+		} else {
+			/* If there are only pauseable priorities or
+			 * only non-pauseable,* the lower priorities go
+			 * to the first queue and the higherpriorities go
+			 * to the second queue.
+			 */
+			cos_data->data[0].pausable =
+				cos_data->data[1].pausable =
+				IS_DCBX_PFC_PRI_ONLY_PAUSE(bp, pri_join_mask);
+
+			for (i = 0 ; i < LLFC_DRIVER_TRAFFIC_TYPE_MAX; i++) {
+				pri_tested = 1 << bp->dcbx_port_params.
+					app.traffic_type_priority[i];
+				/* Remove priority tested */
+				pri_mask_without_pri =
+					(pri_join_mask & ((u8)(~pri_tested)));
+				if (pri_mask_without_pri < pri_tested)
+					break;
+			}
+
+			if (i == LLFC_DRIVER_TRAFFIC_TYPE_MAX)
+				BNX2X_ERR("Invalid value for pri_join_mask -"
+					  " could not find a priority\n");
+
+			cos_data->data[0].pri_join_mask = pri_mask_without_pri;
+			cos_data->data[1].pri_join_mask = pri_tested;
+			/* Both queues are strict priority,
+			 * and that with the highest priority
+			 * gets the highest strict priority in the arbiter.
+			 */
+			cos_data->data[0].strict = BNX2X_DCBX_COS_LOW_STRICT;
+			cos_data->data[1].strict = BNX2X_DCBX_COS_HIGH_STRICT;
+		}
+	}
+}
+
+static void bnx2x_dcbx_two_pg_to_cos_params(
+			    struct bnx2x		*bp,
+			    struct  pg_help_data	*pg_help_data,
+			    struct dcbx_ets_feature	*ets,
+			    struct cos_help_data	*cos_data,
+			    u32			*pg_pri_orginal_spread,
+			    u32				pri_join_mask,
+			    u8				num_of_dif_pri)
+{
+	u8 i = 0;
+	u8 pg[E2_NUM_OF_COS] = {0};
+
+	/* If there are both pauseable and non-pauseable priorities,
+	 * the pauseable priorities go to the first queue and
+	 * the non-pauseable priorities go to the second queue.
+	 */
+	if (IS_DCBX_PFC_PRI_MIX_PAUSE(bp, pri_join_mask)) {
+		if (IS_DCBX_PFC_PRI_MIX_PAUSE(bp,
+					 pg_help_data->data[0].pg_priority) ||
+		    IS_DCBX_PFC_PRI_MIX_PAUSE(bp,
+					 pg_help_data->data[1].pg_priority)) {
+			/* If one PG contains both pauseable and
+			 * non-pauseable priorities then ETS is disabled.
+			 */
+			bnx2x_dcbx_separate_pauseable_from_non(bp, cos_data,
+					pg_pri_orginal_spread, ets);
+			bp->dcbx_port_params.ets.enabled = false;
+			return;
+		}
+
+		/* Pauseable */
+		cos_data->data[0].pausable = true;
+		/* Non pauseable. */
+		cos_data->data[1].pausable = false;
+		if (IS_DCBX_PFC_PRI_ONLY_PAUSE(bp,
+				pg_help_data->data[0].pg_priority)) {
+			/* 0 is pauseable */
+			cos_data->data[0].pri_join_mask =
+				pg_help_data->data[0].pg_priority;
+			pg[0] = pg_help_data->data[0].pg;
+			cos_data->data[1].pri_join_mask =
+				pg_help_data->data[1].pg_priority;
+			pg[1] = pg_help_data->data[1].pg;
+		} else {/* 1 is pauseable */
+			cos_data->data[0].pri_join_mask =
+				pg_help_data->data[1].pg_priority;
+			pg[0] = pg_help_data->data[1].pg;
+			cos_data->data[1].pri_join_mask =
+				pg_help_data->data[0].pg_priority;
+			pg[1] = pg_help_data->data[0].pg;
+		}
+	} else {
+		/* If there are only pauseable priorities or
+		 * only non-pauseable, each PG goes to a queue.
+		 */
+		cos_data->data[0].pausable = cos_data->data[1].pausable =
+			IS_DCBX_PFC_PRI_ONLY_PAUSE(bp, pri_join_mask);
+		cos_data->data[0].pri_join_mask =
+			pg_help_data->data[0].pg_priority;
+		pg[0] = pg_help_data->data[0].pg;
+		cos_data->data[1].pri_join_mask =
+			pg_help_data->data[1].pg_priority;
+		pg[1] = pg_help_data->data[1].pg;
+	}
+
+	/* There can be only one strict pg */
+	for (i = 0 ; i < E2_NUM_OF_COS; i++) {
+		if (pg[i] < DCBX_MAX_NUM_PG_BW_ENTRIES)
+			cos_data->data[i].cos_bw =
+				DCBX_PG_BW_GET(ets->pg_bw_tbl, pg[i]);
+		else
+			cos_data->data[i].strict = BNX2X_DCBX_COS_HIGH_STRICT;
+	}
+}
+
+/*******************************************************************************
+ * Description: Still
+ *
+ * Return:
+ ******************************************************************************/
+static void bnx2x_dcbx_three_pg_to_cos_params(
+			      struct bnx2x		*bp,
+			      struct pg_help_data	*pg_help_data,
+			      struct dcbx_ets_feature	*ets,
+			      struct cos_help_data	*cos_data,
+			      u32			*pg_pri_orginal_spread,
+			      u32			pri_join_mask,
+			      u8			num_of_dif_pri)
+{
+	u8 i = 0;
+	u32 pri_tested = 0;
+	u8 entry = 0;
+	u8 pg_entry = 0;
+	bool b_found_strict = false;
+	u8 num_of_pri = LLFC_DRIVER_TRAFFIC_TYPE_MAX;
+
+	cos_data->data[0].pri_join_mask = cos_data->data[1].pri_join_mask = 0;
+	/* If there are both pauseable and non-pauseable priorities,
+	 * the pauseable priorities go to the first queue and the
+	 * non-pauseable priorities go to the second queue.
+	 */
+	if (IS_DCBX_PFC_PRI_MIX_PAUSE(bp, pri_join_mask))
+		bnx2x_dcbx_separate_pauseable_from_non(bp,
+				cos_data, pg_pri_orginal_spread, ets);
+	else {
+		/* If two BW-limited PG-s were combined to one queue,
+		 * the BW is their sum.
+		 *
+		 * If there are only pauseable priorities or only non-pauseable,
+		 * and there are both BW-limited and non-BW-limited PG-s,
+		 * the BW-limited PG/s go to one queue and the non-BW-limited
+		 * PG/s go to the second queue.
+		 *
+		 * If there are only pauseable priorities or only non-pauseable
+		 * and all are BW limited, then	two priorities go to the first
+		 * queue and one priority goes to the second queue.
+		 *
+		 * We will join this two cases:
+		 * if one is BW limited it will go to the secoend queue
+		 * otherwise the last priority will get it
+		 */
+
+		cos_data->data[0].pausable = cos_data->data[1].pausable =
+			IS_DCBX_PFC_PRI_ONLY_PAUSE(bp, pri_join_mask);
+
+		for (i = 0 ; i < num_of_pri; i++) {
+			pri_tested = 1 << bp->dcbx_port_params.
+				app.traffic_type_priority[i];
+			pg_entry = (u8)pg_pri_orginal_spread[bp->
+				dcbx_port_params.app.traffic_type_priority[i]];
+
+			if (pg_entry < DCBX_MAX_NUM_PG_BW_ENTRIES) {
+				entry = 0;
+
+				if (i == (num_of_pri-1) &&
+				    false == b_found_strict)
+					/* last entry will be handled separately
+					 * If no priority is strict than last
+					 * enty goes to last queue.*/
+					entry = 1;
+				cos_data->data[entry].pri_join_mask |=
+								pri_tested;
+				bnx2x_dcbx_add_to_cos_bw(bp,
+					&cos_data->data[entry],
+					DCBX_PG_BW_GET(ets->pg_bw_tbl,
+						       pg_entry));
+			} else {
+				b_found_strict = true;
+				cos_data->data[1].pri_join_mask |= pri_tested;
+				/* If we join a group and one is strict
+				 * than the bw rulls */
+				cos_data->data[1].strict =
+					BNX2X_DCBX_COS_HIGH_STRICT;
+			}
+		}
+	}
+}
+
+
+static void bnx2x_dcbx_fill_cos_params(struct bnx2x *bp,
+				       struct pg_help_data *help_data,
+				       struct dcbx_ets_feature *ets,
+				       u32 *pg_pri_orginal_spread)
+{
+	struct cos_help_data         cos_data ;
+	u8                    i                           = 0;
+	u32                   pri_join_mask               = 0;
+	u8                    num_of_dif_pri              = 0;
+
+	memset(&cos_data, 0, sizeof(cos_data));
+	/* Validate the pg value */
+	for (i = 0; i < help_data->num_of_pg ; i++) {
+		if (DCBX_STRICT_PRIORITY != help_data->data[i].pg &&
+		    DCBX_MAX_NUM_PG_BW_ENTRIES <= help_data->data[i].pg)
+			BNX2X_ERR("Invalid pg[%d] data %x\n", i,
+				  help_data->data[i].pg);
+		pri_join_mask   |=  help_data->data[i].pg_priority;
+		num_of_dif_pri  += help_data->data[i].num_of_dif_pri;
+	}
+
+	/* default settings */
+	cos_data.num_of_cos = 2;
+	for (i = 0; i < E2_NUM_OF_COS ; i++) {
+		cos_data.data[i].pri_join_mask    = pri_join_mask;
+		cos_data.data[i].pausable         = false;
+		cos_data.data[i].strict           = BNX2X_DCBX_COS_NOT_STRICT;
+		cos_data.data[i].cos_bw           = DCBX_INVALID_COS_BW;
+	}
+
+	switch (help_data->num_of_pg) {
+	case 1:
+
+		bxn2x_dcbx_single_pg_to_cos_params(
+					       bp,
+					       help_data,
+					       &cos_data,
+					       pri_join_mask,
+					       num_of_dif_pri);
+		break;
+	case 2:
+		bnx2x_dcbx_two_pg_to_cos_params(
+					    bp,
+					    help_data,
+					    ets,
+					    &cos_data,
+					    pg_pri_orginal_spread,
+					    pri_join_mask,
+					    num_of_dif_pri);
+		break;
+
+	case 3:
+		bnx2x_dcbx_three_pg_to_cos_params(
+					      bp,
+					      help_data,
+					      ets,
+					      &cos_data,
+					      pg_pri_orginal_spread,
+					      pri_join_mask,
+					      num_of_dif_pri);
+
+		break;
+	default:
+		BNX2X_ERR("Wrong pg_help_data.num_of_pg\n");
+		bnx2x_dcbx_ets_disabled_entry_data(bp,
+						   &cos_data, pri_join_mask);
+	}
+
+	for (i = 0; i < cos_data.num_of_cos ; i++) {
+		struct bnx2x_dcbx_cos_params *params =
+			&bp->dcbx_port_params.ets.cos_params[i];
+
+		params->pauseable = cos_data.data[i].pausable;
+		params->strict = cos_data.data[i].strict;
+		params->bw_tbl = cos_data.data[i].cos_bw;
+		if (params->pauseable) {
+			params->pri_bitmask =
+			DCBX_PFC_PRI_GET_PAUSE(bp,
+					cos_data.data[i].pri_join_mask);
+			DP(NETIF_MSG_LINK, "COS %d PAUSABLE prijoinmask 0x%x\n",
+				  i, cos_data.data[i].pri_join_mask);
+		} else {
+			params->pri_bitmask =
+			DCBX_PFC_PRI_GET_NON_PAUSE(bp,
+					cos_data.data[i].pri_join_mask);
+			DP(NETIF_MSG_LINK, "COS %d NONPAUSABLE prijoinmask "
+					  "0x%x\n",
+				  i, cos_data.data[i].pri_join_mask);
+		}
+	}
+
+	bp->dcbx_port_params.ets.num_of_cos = cos_data.num_of_cos ;
+}
+
+static void bnx2x_dcbx_get_ets_pri_pg_tbl(struct bnx2x *bp,
+				u32 *set_configuration_ets_pg,
+				u32 *pri_pg_tbl)
+{
+	int i;
+
+	for (i = 0; i < DCBX_MAX_NUM_PRI_PG_ENTRIES; i++) {
+		set_configuration_ets_pg[i] = DCBX_PRI_PG_GET(pri_pg_tbl, i);
+
+		DP(NETIF_MSG_LINK, "set_configuration_ets_pg[%d] = 0x%x\n",
+		   i, set_configuration_ets_pg[i]);
+	}
+}
+
+/*******************************************************************************
+ * Description: Fill pfc_config struct that will be sent in DCBX start ramrod
+ *
+ * Return:
+ ******************************************************************************/
+static void bnx2x_pfc_fw_struct_e2(struct bnx2x *bp)
+{
+	struct flow_control_configuration   *pfc_fw_cfg = NULL;
+	u16 pri_bit = 0;
+	u8 cos = 0, pri = 0;
+	struct priority_cos *tt2cos;
+	u32 *ttp = bp->dcbx_port_params.app.traffic_type_priority;
+
+	pfc_fw_cfg = (struct flow_control_configuration *)
+					bnx2x_sp(bp, pfc_config);
+	memset(pfc_fw_cfg, 0, sizeof(struct flow_control_configuration));
+
+	/*shortcut*/
+	tt2cos = pfc_fw_cfg->traffic_type_to_priority_cos;
+
+	/* Fw version should be incremented each update */
+	pfc_fw_cfg->dcb_version = ++bp->dcb_version;
+	pfc_fw_cfg->dcb_enabled = DCB_ENABLED;
+
+	/* Default initialization */
+	for (pri = 0; pri < MAX_PFC_TRAFFIC_TYPES ; pri++) {
+		tt2cos[pri].priority = LLFC_TRAFFIC_TYPE_TO_PRIORITY_UNMAPPED;
+		tt2cos[pri].cos = 0;
+	}
+
+	/* Fill priority parameters */
+	for (pri = 0; pri < LLFC_DRIVER_TRAFFIC_TYPE_MAX; pri++) {
+		tt2cos[pri].priority = ttp[pri];
+		pri_bit = 1 << tt2cos[pri].priority;
+
+		/* Fill COS parameters based on COS calculated to
+		 * make it more generally for future use */
+		for (cos = 0; cos < bp->dcbx_port_params.ets.num_of_cos; cos++)
+			if (bp->dcbx_port_params.ets.cos_params[cos].
+						pri_bitmask & pri_bit)
+					tt2cos[pri].cos = cos;
+	}
+	bnx2x_dcbx_print_cos_params(bp,	pfc_fw_cfg);
+}
+/* DCB netlink */
+#ifdef BCM_DCB
+#include <linux/dcbnl.h>
+
+#define BNX2X_DCBX_CAPS		(DCB_CAP_DCBX_LLD_MANAGED | \
+				DCB_CAP_DCBX_VER_CEE | DCB_CAP_DCBX_STATIC)
+
+static inline bool bnx2x_dcbnl_set_valid(struct bnx2x *bp)
+{
+	/* validate dcbnl call that may change HW state:
+	 * DCB is on and DCBX mode was SUCCESSFULLY set by the user.
+	 */
+	return bp->dcb_state && bp->dcbx_mode_uset;
+}
+
+static u8 bnx2x_dcbnl_get_state(struct net_device *netdev)
+{
+	struct bnx2x *bp = netdev_priv(netdev);
+	DP(NETIF_MSG_LINK, "state = %d\n", bp->dcb_state);
+	return bp->dcb_state;
+}
+
+static u8 bnx2x_dcbnl_set_state(struct net_device *netdev, u8 state)
+{
+	struct bnx2x *bp = netdev_priv(netdev);
+	DP(NETIF_MSG_LINK, "state = %s\n", state ? "on" : "off");
+
+	bnx2x_dcbx_set_state(bp, (state ? true : false), bp->dcbx_enabled);
+	return 0;
+}
+
+static void bnx2x_dcbnl_get_perm_hw_addr(struct net_device *netdev,
+					 u8 *perm_addr)
+{
+	struct bnx2x *bp = netdev_priv(netdev);
+	DP(NETIF_MSG_LINK, "GET-PERM-ADDR\n");
+
+	/* first the HW mac address */
+	memcpy(perm_addr, netdev->dev_addr, netdev->addr_len);
+
+#ifdef BCM_CNIC
+	/* second SAN address */
+	memcpy(perm_addr+netdev->addr_len, bp->fip_mac, netdev->addr_len);
+#endif
+}
+
+static void bnx2x_dcbnl_set_pg_tccfg_tx(struct net_device *netdev, int prio,
+					u8 prio_type, u8 pgid, u8 bw_pct,
+					u8 up_map)
+{
+	struct bnx2x *bp = netdev_priv(netdev);
+
+	DP(NETIF_MSG_LINK, "prio[%d] = %d\n", prio, pgid);
+	if (!bnx2x_dcbnl_set_valid(bp) || prio >= DCBX_MAX_NUM_PRI_PG_ENTRIES)
+		return;
+
+	/**
+	 * bw_pct ingnored -	band-width percentage devision between user
+	 *			priorities within the same group is not
+	 *			standard and hence not supported
+	 *
+	 * prio_type igonred -	priority levels within the same group are not
+	 *			standard and hence are not supported. According
+	 *			to the standard pgid 15 is dedicated to strict
+	 *			prioirty traffic (on the port level).
+	 *
+	 * up_map ignored
+	 */
+
+	bp->dcbx_config_params.admin_configuration_ets_pg[prio] = pgid;
+	bp->dcbx_config_params.admin_ets_configuration_tx_enable = 1;
+}
+
+static void bnx2x_dcbnl_set_pg_bwgcfg_tx(struct net_device *netdev,
+					 int pgid, u8 bw_pct)
+{
+	struct bnx2x *bp = netdev_priv(netdev);
+	DP(NETIF_MSG_LINK, "pgid[%d] = %d\n", pgid, bw_pct);
+
+	if (!bnx2x_dcbnl_set_valid(bp) || pgid >= DCBX_MAX_NUM_PG_BW_ENTRIES)
+		return;
+
+	bp->dcbx_config_params.admin_configuration_bw_precentage[pgid] = bw_pct;
+	bp->dcbx_config_params.admin_ets_configuration_tx_enable = 1;
+}
+
+static void bnx2x_dcbnl_set_pg_tccfg_rx(struct net_device *netdev, int prio,
+					u8 prio_type, u8 pgid, u8 bw_pct,
+					u8 up_map)
+{
+	struct bnx2x *bp = netdev_priv(netdev);
+	DP(NETIF_MSG_LINK, "Nothing to set; No RX support\n");
+}
+
+static void bnx2x_dcbnl_set_pg_bwgcfg_rx(struct net_device *netdev,
+					 int pgid, u8 bw_pct)
+{
+	struct bnx2x *bp = netdev_priv(netdev);
+	DP(NETIF_MSG_LINK, "Nothing to set; No RX support\n");
+}
+
+static void bnx2x_dcbnl_get_pg_tccfg_tx(struct net_device *netdev, int prio,
+					u8 *prio_type, u8 *pgid, u8 *bw_pct,
+					u8 *up_map)
+{
+	struct bnx2x *bp = netdev_priv(netdev);
+	DP(NETIF_MSG_LINK, "prio = %d\n", prio);
+
+	/**
+	 * bw_pct ingnored -	band-width percentage devision between user
+	 *			priorities within the same group is not
+	 *			standard and hence not supported
+	 *
+	 * prio_type igonred -	priority levels within the same group are not
+	 *			standard and hence are not supported. According
+	 *			to the standard pgid 15 is dedicated to strict
+	 *			prioirty traffic (on the port level).
+	 *
+	 * up_map ignored
+	 */
+	*up_map = *bw_pct = *prio_type = *pgid = 0;
+
+	if (!bp->dcb_state || prio >= DCBX_MAX_NUM_PRI_PG_ENTRIES)
+		return;
+
+	*pgid = DCBX_PRI_PG_GET(bp->dcbx_local_feat.ets.pri_pg_tbl, prio);
+}
+
+static void bnx2x_dcbnl_get_pg_bwgcfg_tx(struct net_device *netdev,
+					 int pgid, u8 *bw_pct)
+{
+	struct bnx2x *bp = netdev_priv(netdev);
+	DP(NETIF_MSG_LINK, "pgid = %d\n", pgid);
+
+	*bw_pct = 0;
+
+	if (!bp->dcb_state || pgid >= DCBX_MAX_NUM_PG_BW_ENTRIES)
+		return;
+
+	*bw_pct = DCBX_PG_BW_GET(bp->dcbx_local_feat.ets.pg_bw_tbl, pgid);
+}
+
+static void bnx2x_dcbnl_get_pg_tccfg_rx(struct net_device *netdev, int prio,
+					u8 *prio_type, u8 *pgid, u8 *bw_pct,
+					u8 *up_map)
+{
+	struct bnx2x *bp = netdev_priv(netdev);
+	DP(NETIF_MSG_LINK, "Nothing to get; No RX support\n");
+
+	*prio_type = *pgid = *bw_pct = *up_map = 0;
+}
+
+static void bnx2x_dcbnl_get_pg_bwgcfg_rx(struct net_device *netdev,
+					 int pgid, u8 *bw_pct)
+{
+	struct bnx2x *bp = netdev_priv(netdev);
+	DP(NETIF_MSG_LINK, "Nothing to get; No RX support\n");
+
+	*bw_pct = 0;
+}
+
+static void bnx2x_dcbnl_set_pfc_cfg(struct net_device *netdev, int prio,
+				    u8 setting)
+{
+	struct bnx2x *bp = netdev_priv(netdev);
+	DP(NETIF_MSG_LINK, "prio[%d] = %d\n", prio, setting);
+
+	if (!bnx2x_dcbnl_set_valid(bp) || prio >= MAX_PFC_PRIORITIES)
+		return;
+
+	bp->dcbx_config_params.admin_pfc_bitmap |= ((setting ? 1 : 0) << prio);
+
+	if (setting)
+		bp->dcbx_config_params.admin_pfc_tx_enable = 1;
+}
+
+static void bnx2x_dcbnl_get_pfc_cfg(struct net_device *netdev, int prio,
+				    u8 *setting)
+{
+	struct bnx2x *bp = netdev_priv(netdev);
+	DP(NETIF_MSG_LINK, "prio = %d\n", prio);
+
+	*setting = 0;
+
+	if (!bp->dcb_state || prio >= MAX_PFC_PRIORITIES)
+		return;
+
+	*setting = (bp->dcbx_local_feat.pfc.pri_en_bitmap >> prio) & 0x1;
+}
+
+static u8 bnx2x_dcbnl_set_all(struct net_device *netdev)
+{
+	struct bnx2x *bp = netdev_priv(netdev);
+	int rc = 0;
+
+	DP(NETIF_MSG_LINK, "SET-ALL\n");
+
+	if (!bnx2x_dcbnl_set_valid(bp))
+		return 1;
+
+	if (bp->recovery_state != BNX2X_RECOVERY_DONE) {
+		netdev_err(bp->dev, "Handling parity error recovery. "
+				"Try again later\n");
+		return 1;
+	}
+	if (netif_running(bp->dev)) {
+		bnx2x_nic_unload(bp, UNLOAD_NORMAL);
+		rc = bnx2x_nic_load(bp, LOAD_NORMAL);
+	}
+	DP(NETIF_MSG_LINK, "set_dcbx_params done (%d)\n", rc);
+	if (rc)
+		return 1;
+
+	return 0;
+}
+
+static u8 bnx2x_dcbnl_get_cap(struct net_device *netdev, int capid, u8 *cap)
+{
+	struct bnx2x *bp = netdev_priv(netdev);
+	u8 rval = 0;
+
+	if (bp->dcb_state) {
+		switch (capid) {
+		case DCB_CAP_ATTR_PG:
+			*cap = true;
+			break;
+		case DCB_CAP_ATTR_PFC:
+			*cap = true;
+			break;
+		case DCB_CAP_ATTR_UP2TC:
+			*cap = false;
+			break;
+		case DCB_CAP_ATTR_PG_TCS:
+			*cap = 0x80;	/* 8 priorities for PGs */
+			break;
+		case DCB_CAP_ATTR_PFC_TCS:
+			*cap = 0x80;	/* 8 priorities for PFC */
+			break;
+		case DCB_CAP_ATTR_GSP:
+			*cap = true;
+			break;
+		case DCB_CAP_ATTR_BCN:
+			*cap = false;
+			break;
+		case DCB_CAP_ATTR_DCBX:
+			*cap = BNX2X_DCBX_CAPS;
+		default:
+			rval = -EINVAL;
+			break;
+		}
+	} else
+		rval = -EINVAL;
+
+	DP(NETIF_MSG_LINK, "capid %d:%x\n", capid, *cap);
+	return rval;
+}
+
+static u8 bnx2x_dcbnl_get_numtcs(struct net_device *netdev, int tcid, u8 *num)
+{
+	struct bnx2x *bp = netdev_priv(netdev);
+	u8 rval = 0;
+
+	DP(NETIF_MSG_LINK, "tcid %d\n", tcid);
+
+	if (bp->dcb_state) {
+		switch (tcid) {
+		case DCB_NUMTCS_ATTR_PG:
+			*num = E2_NUM_OF_COS;
+			break;
+		case DCB_NUMTCS_ATTR_PFC:
+			*num = E2_NUM_OF_COS;
+			break;
+		default:
+			rval = -EINVAL;
+			break;
+		}
+	} else
+		rval = -EINVAL;
+
+	return rval;
+}
+
+static u8 bnx2x_dcbnl_set_numtcs(struct net_device *netdev, int tcid, u8 num)
+{
+	struct bnx2x *bp = netdev_priv(netdev);
+	DP(NETIF_MSG_LINK, "num tcs = %d; Not supported\n", num);
+	return -EINVAL;
+}
+
+static u8  bnx2x_dcbnl_get_pfc_state(struct net_device *netdev)
+{
+	struct bnx2x *bp = netdev_priv(netdev);
+	DP(NETIF_MSG_LINK, "state = %d\n", bp->dcbx_local_feat.pfc.enabled);
+
+	if (!bp->dcb_state)
+		return 0;
+
+	return bp->dcbx_local_feat.pfc.enabled;
+}
+
+static void bnx2x_dcbnl_set_pfc_state(struct net_device *netdev, u8 state)
+{
+	struct bnx2x *bp = netdev_priv(netdev);
+	DP(NETIF_MSG_LINK, "state = %s\n", state ? "on" : "off");
+
+	if (!bnx2x_dcbnl_set_valid(bp))
+		return;
+
+	bp->dcbx_config_params.admin_pfc_tx_enable =
+	bp->dcbx_config_params.admin_pfc_enable = (state ? 1 : 0);
+}
+
+static bool bnx2x_app_is_equal(struct dcbx_app_priority_entry *app_ent,
+			       u8 idtype, u16 idval)
+{
+	if (!(app_ent->appBitfield & DCBX_APP_ENTRY_VALID))
+		return false;
+
+	switch (idtype) {
+	case DCB_APP_IDTYPE_ETHTYPE:
+		if ((app_ent->appBitfield & DCBX_APP_ENTRY_SF_MASK) !=
+			DCBX_APP_SF_ETH_TYPE)
+			return false;
+		break;
+	case DCB_APP_IDTYPE_PORTNUM:
+		if ((app_ent->appBitfield & DCBX_APP_ENTRY_SF_MASK) !=
+			DCBX_APP_SF_PORT)
+			return false;
+		break;
+	default:
+		return false;
+	}
+	if (app_ent->app_id != idval)
+		return false;
+
+	return true;
+}
+
+static void bnx2x_admin_app_set_ent(
+	struct bnx2x_admin_priority_app_table *app_ent,
+	u8 idtype, u16 idval, u8 up)
+{
+	app_ent->valid = 1;
+
+	switch (idtype) {
+	case DCB_APP_IDTYPE_ETHTYPE:
+		app_ent->traffic_type = TRAFFIC_TYPE_ETH;
+		break;
+	case DCB_APP_IDTYPE_PORTNUM:
+		app_ent->traffic_type = TRAFFIC_TYPE_PORT;
+		break;
+	default:
+		break; /* never gets here */
+	}
+	app_ent->app_id = idval;
+	app_ent->priority = up;
+}
+
+static bool bnx2x_admin_app_is_equal(
+	struct bnx2x_admin_priority_app_table *app_ent,
+	u8 idtype, u16 idval)
+{
+	if (!app_ent->valid)
+		return false;
+
+	switch (idtype) {
+	case DCB_APP_IDTYPE_ETHTYPE:
+		if (app_ent->traffic_type != TRAFFIC_TYPE_ETH)
+			return false;
+		break;
+	case DCB_APP_IDTYPE_PORTNUM:
+		if (app_ent->traffic_type != TRAFFIC_TYPE_PORT)
+			return false;
+		break;
+	default:
+		return false;
+	}
+	if (app_ent->app_id != idval)
+		return false;
+
+	return true;
+}
+
+static int bnx2x_set_admin_app_up(struct bnx2x *bp, u8 idtype, u16 idval, u8 up)
+{
+	int i, ff;
+
+	/* iterate over the app entries looking for idtype and idval */
+	for (i = 0, ff = -1; i < 4; i++) {
+		struct bnx2x_admin_priority_app_table *app_ent =
+			&bp->dcbx_config_params.admin_priority_app_table[i];
+		if (bnx2x_admin_app_is_equal(app_ent, idtype, idval))
+			break;
+
+		if (ff < 0 && !app_ent->valid)
+			ff = i;
+	}
+	if (i < 4)
+		/* if found overwrite up */
+		bp->dcbx_config_params.
+			admin_priority_app_table[i].priority = up;
+	else if (ff >= 0)
+		/* not found use first-free */
+		bnx2x_admin_app_set_ent(
+			&bp->dcbx_config_params.admin_priority_app_table[ff],
+			idtype, idval, up);
+	else
+		/* app table is full */
+		return -EBUSY;
+
+	/* up configured, if not 0 make sure feature is enabled */
+	if (up)
+		bp->dcbx_config_params.admin_application_priority_tx_enable = 1;
+
+	return 0;
+}
+
+static u8 bnx2x_dcbnl_set_app_up(struct net_device *netdev, u8 idtype,
+				 u16 idval, u8 up)
+{
+	struct bnx2x *bp = netdev_priv(netdev);
+
+	DP(NETIF_MSG_LINK, "app_type %d, app_id %x, prio bitmap %d\n",
+	   idtype, idval, up);
+
+	if (!bnx2x_dcbnl_set_valid(bp))
+		return -EINVAL;
+
+	/* verify idtype */
+	switch (idtype) {
+	case DCB_APP_IDTYPE_ETHTYPE:
+	case DCB_APP_IDTYPE_PORTNUM:
+		break;
+	default:
+		return -EINVAL;
+	}
+	return bnx2x_set_admin_app_up(bp, idtype, idval, up);
+}
+
+static u8 bnx2x_dcbnl_get_app_up(struct net_device *netdev, u8 idtype,
+				 u16 idval)
+{
+	int i;
+	u8 up = 0;
+
+	struct bnx2x *bp = netdev_priv(netdev);
+	DP(NETIF_MSG_LINK, "app_type %d, app_id 0x%x\n", idtype, idval);
+
+	/* iterate over the app entries looking for idtype and idval */
+	for (i = 0; i < DCBX_MAX_APP_PROTOCOL; i++)
+		if (bnx2x_app_is_equal(&bp->dcbx_local_feat.app.app_pri_tbl[i],
+				       idtype, idval))
+			break;
+
+	if (i < DCBX_MAX_APP_PROTOCOL)
+		/* if found return up */
+		up = bp->dcbx_local_feat.app.app_pri_tbl[i].pri_bitmap;
+	else
+		DP(NETIF_MSG_LINK, "app not found\n");
+
+	return up;
+}
+
+static u8 bnx2x_dcbnl_get_dcbx(struct net_device *netdev)
+{
+	struct bnx2x *bp = netdev_priv(netdev);
+	u8 state;
+
+	state = DCB_CAP_DCBX_LLD_MANAGED | DCB_CAP_DCBX_VER_CEE;
+
+	if (bp->dcbx_enabled == BNX2X_DCBX_ENABLED_ON_NEG_OFF)
+		state |= DCB_CAP_DCBX_STATIC;
+
+	return state;
+}
+
+static u8 bnx2x_dcbnl_set_dcbx(struct net_device *netdev, u8 state)
+{
+	struct bnx2x *bp = netdev_priv(netdev);
+	DP(NETIF_MSG_LINK, "state = %02x\n", state);
+
+	/* set dcbx mode */
+
+	if ((state & BNX2X_DCBX_CAPS) != state) {
+		BNX2X_ERR("Requested DCBX mode %x is beyond advertised "
+			  "capabilities\n", state);
+		return 1;
+	}
+
+	if (bp->dcb_state != BNX2X_DCB_STATE_ON) {
+		BNX2X_ERR("DCB turned off, DCBX configuration is invalid\n");
+		return 1;
+	}
+
+	if (state & DCB_CAP_DCBX_STATIC)
+		bp->dcbx_enabled = BNX2X_DCBX_ENABLED_ON_NEG_OFF;
+	else
+		bp->dcbx_enabled = BNX2X_DCBX_ENABLED_ON_NEG_ON;
+
+	bp->dcbx_mode_uset = true;
+	return 0;
+}
+
+
+static u8 bnx2x_dcbnl_get_featcfg(struct net_device *netdev, int featid,
+				  u8 *flags)
+{
+	struct bnx2x *bp = netdev_priv(netdev);
+	u8 rval = 0;
+
+	DP(NETIF_MSG_LINK, "featid %d\n", featid);
+
+	if (bp->dcb_state) {
+		*flags = 0;
+		switch (featid) {
+		case DCB_FEATCFG_ATTR_PG:
+			if (bp->dcbx_local_feat.ets.enabled)
+				*flags |= DCB_FEATCFG_ENABLE;
+			if (bp->dcbx_error & DCBX_LOCAL_ETS_ERROR)
+				*flags |= DCB_FEATCFG_ERROR;
+			break;
+		case DCB_FEATCFG_ATTR_PFC:
+			if (bp->dcbx_local_feat.pfc.enabled)
+				*flags |= DCB_FEATCFG_ENABLE;
+			if (bp->dcbx_error & (DCBX_LOCAL_PFC_ERROR |
+			    DCBX_LOCAL_PFC_MISMATCH))
+				*flags |= DCB_FEATCFG_ERROR;
+			break;
+		case DCB_FEATCFG_ATTR_APP:
+			if (bp->dcbx_local_feat.app.enabled)
+				*flags |= DCB_FEATCFG_ENABLE;
+			if (bp->dcbx_error & (DCBX_LOCAL_APP_ERROR |
+			    DCBX_LOCAL_APP_MISMATCH))
+				*flags |= DCB_FEATCFG_ERROR;
+			break;
+		default:
+			rval = -EINVAL;
+			break;
+		}
+	} else
+		rval = -EINVAL;
+
+	return rval;
+}
+
+static u8 bnx2x_dcbnl_set_featcfg(struct net_device *netdev, int featid,
+				  u8 flags)
+{
+	struct bnx2x *bp = netdev_priv(netdev);
+	u8 rval = 0;
+
+	DP(NETIF_MSG_LINK, "featid = %d flags = %02x\n", featid, flags);
+
+	/* ignore the 'advertise' flag */
+	if (bnx2x_dcbnl_set_valid(bp)) {
+		switch (featid) {
+		case DCB_FEATCFG_ATTR_PG:
+			bp->dcbx_config_params.admin_ets_enable =
+				flags & DCB_FEATCFG_ENABLE ? 1 : 0;
+			bp->dcbx_config_params.admin_ets_willing =
+				flags & DCB_FEATCFG_WILLING ? 1 : 0;
+			break;
+		case DCB_FEATCFG_ATTR_PFC:
+			bp->dcbx_config_params.admin_pfc_enable =
+				flags & DCB_FEATCFG_ENABLE ? 1 : 0;
+			bp->dcbx_config_params.admin_pfc_willing =
+				flags & DCB_FEATCFG_WILLING ? 1 : 0;
+			break;
+		case DCB_FEATCFG_ATTR_APP:
+			/* ignore enable, always enabled */
+			bp->dcbx_config_params.admin_app_priority_willing =
+				flags & DCB_FEATCFG_WILLING ? 1 : 0;
+			break;
+		default:
+			rval = -EINVAL;
+			break;
+		}
+	} else
+		rval = -EINVAL;
+
+	return rval;
+}
+
+const struct dcbnl_rtnl_ops bnx2x_dcbnl_ops = {
+	.getstate       = bnx2x_dcbnl_get_state,
+	.setstate       = bnx2x_dcbnl_set_state,
+	.getpermhwaddr  = bnx2x_dcbnl_get_perm_hw_addr,
+	.setpgtccfgtx   = bnx2x_dcbnl_set_pg_tccfg_tx,
+	.setpgbwgcfgtx  = bnx2x_dcbnl_set_pg_bwgcfg_tx,
+	.setpgtccfgrx   = bnx2x_dcbnl_set_pg_tccfg_rx,
+	.setpgbwgcfgrx  = bnx2x_dcbnl_set_pg_bwgcfg_rx,
+	.getpgtccfgtx   = bnx2x_dcbnl_get_pg_tccfg_tx,
+	.getpgbwgcfgtx  = bnx2x_dcbnl_get_pg_bwgcfg_tx,
+	.getpgtccfgrx   = bnx2x_dcbnl_get_pg_tccfg_rx,
+	.getpgbwgcfgrx  = bnx2x_dcbnl_get_pg_bwgcfg_rx,
+	.setpfccfg      = bnx2x_dcbnl_set_pfc_cfg,
+	.getpfccfg      = bnx2x_dcbnl_get_pfc_cfg,
+	.setall         = bnx2x_dcbnl_set_all,
+	.getcap         = bnx2x_dcbnl_get_cap,
+	.getnumtcs      = bnx2x_dcbnl_get_numtcs,
+	.setnumtcs      = bnx2x_dcbnl_set_numtcs,
+	.getpfcstate    = bnx2x_dcbnl_get_pfc_state,
+	.setpfcstate    = bnx2x_dcbnl_set_pfc_state,
+	.getapp         = bnx2x_dcbnl_get_app_up,
+	.setapp         = bnx2x_dcbnl_set_app_up,
+	.getdcbx        = bnx2x_dcbnl_get_dcbx,
+	.setdcbx        = bnx2x_dcbnl_set_dcbx,
+	.getfeatcfg     = bnx2x_dcbnl_get_featcfg,
+	.setfeatcfg     = bnx2x_dcbnl_set_featcfg,
+};
+
+#endif /* BCM_DCB */
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/bnx2x/bnx2x_dcb.h linux-libre-2.6.38-gnu1/drivers/net/bnx2x/bnx2x_dcb.h
--- linux-libre-2.6.37-gnu1/drivers/net/bnx2x/bnx2x_dcb.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/bnx2x/bnx2x_dcb.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,196 @@
+/* bnx2x_dcb.h: Broadcom Everest network driver.
+ *
+ * Copyright 2009-2010 Broadcom Corporation
+ *
+ * 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.gnu.org/licenses/old-licenses/gpl-2.0.html (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.
+ *
+ * Maintained by: Eilon Greenstein <eilong@broadcom.com>
+ * Written by: Dmitry Kravkov
+ *
+ */
+#ifndef BNX2X_DCB_H
+#define BNX2X_DCB_H
+
+#include "bnx2x_hsi.h"
+
+#define LLFC_DRIVER_TRAFFIC_TYPE_MAX 3 /* NW, iSCSI, FCoE */
+struct bnx2x_dcbx_app_params {
+	u32 enabled;
+	u32 traffic_type_priority[LLFC_DRIVER_TRAFFIC_TYPE_MAX];
+};
+
+#define E2_NUM_OF_COS			2
+#define BNX2X_DCBX_COS_NOT_STRICT	0
+#define BNX2X_DCBX_COS_LOW_STRICT	1
+#define BNX2X_DCBX_COS_HIGH_STRICT	2
+
+struct bnx2x_dcbx_cos_params {
+	u32	bw_tbl;
+	u32	pri_bitmask;
+	u8	strict;
+	u8	pauseable;
+};
+
+struct bnx2x_dcbx_pg_params {
+	u32 enabled;
+	u8 num_of_cos; /* valid COS entries */
+	struct bnx2x_dcbx_cos_params	cos_params[E2_NUM_OF_COS];
+};
+
+struct bnx2x_dcbx_pfc_params {
+	u32 enabled;
+	u32 priority_non_pauseable_mask;
+};
+
+struct bnx2x_dcbx_port_params {
+	struct bnx2x_dcbx_pfc_params pfc;
+	struct bnx2x_dcbx_pg_params  ets;
+	struct bnx2x_dcbx_app_params app;
+};
+
+#define BNX2X_DCBX_CONFIG_INV_VALUE			(0xFFFFFFFF)
+#define BNX2X_DCBX_OVERWRITE_SETTINGS_DISABLE		0
+#define BNX2X_DCBX_OVERWRITE_SETTINGS_ENABLE		1
+#define BNX2X_DCBX_OVERWRITE_SETTINGS_INVALID	(BNX2X_DCBX_CONFIG_INV_VALUE)
+
+/*******************************************************************************
+ * LLDP protocol configuration parameters.
+ ******************************************************************************/
+struct bnx2x_config_lldp_params {
+	u32 overwrite_settings;
+	u32 msg_tx_hold;
+	u32 msg_fast_tx;
+	u32 tx_credit_max;
+	u32 msg_tx_interval;
+	u32 tx_fast;
+};
+
+struct bnx2x_admin_priority_app_table {
+		u32 valid;
+		u32 priority;
+#define INVALID_TRAFFIC_TYPE_PRIORITY	(0xFFFFFFFF)
+		u32 traffic_type;
+#define TRAFFIC_TYPE_ETH		0
+#define TRAFFIC_TYPE_PORT		1
+		u32 app_id;
+};
+
+/*******************************************************************************
+ * DCBX protocol configuration parameters.
+ ******************************************************************************/
+struct bnx2x_config_dcbx_params {
+	u32 overwrite_settings;
+	u32 admin_dcbx_version;
+	u32 admin_ets_enable;
+	u32 admin_pfc_enable;
+	u32 admin_tc_supported_tx_enable;
+	u32 admin_ets_configuration_tx_enable;
+	u32 admin_ets_recommendation_tx_enable;
+	u32 admin_pfc_tx_enable;
+	u32 admin_application_priority_tx_enable;
+	u32 admin_ets_willing;
+	u32 admin_ets_reco_valid;
+	u32 admin_pfc_willing;
+	u32 admin_app_priority_willing;
+	u32 admin_configuration_bw_precentage[8];
+	u32 admin_configuration_ets_pg[8];
+	u32 admin_recommendation_bw_precentage[8];
+	u32 admin_recommendation_ets_pg[8];
+	u32 admin_pfc_bitmap;
+	struct bnx2x_admin_priority_app_table admin_priority_app_table[4];
+	u32 admin_default_priority;
+};
+
+#define GET_FLAGS(flags, bits)		((flags) & (bits))
+#define SET_FLAGS(flags, bits)		((flags) |= (bits))
+#define RESET_FLAGS(flags, bits)	((flags) &= ~(bits))
+
+enum {
+	DCBX_READ_LOCAL_MIB,
+	DCBX_READ_REMOTE_MIB
+};
+
+#define ETH_TYPE_FCOE		(0x8906)
+#define TCP_PORT_ISCSI		(0xCBC)
+
+#define PFC_VALUE_FRAME_SIZE				(512)
+#define PFC_QUANTA_IN_NANOSEC_FROM_SPEED_MEGA(mega_speed)  \
+				((1000 * PFC_VALUE_FRAME_SIZE)/(mega_speed))
+
+#define PFC_BRB1_REG_HIGH_LLFC_LOW_THRESHOLD			130
+#define PFC_BRB1_REG_HIGH_LLFC_HIGH_THRESHOLD			170
+
+
+
+struct cos_entry_help_data {
+	u32			pri_join_mask;
+	u32			cos_bw;
+	u8			strict;
+	bool			pausable;
+};
+
+struct cos_help_data {
+	struct cos_entry_help_data	data[E2_NUM_OF_COS];
+	u8				num_of_cos;
+};
+
+#define DCBX_ILLEGAL_PG				(0xFF)
+#define DCBX_PFC_PRI_MASK			(0xFF)
+#define DCBX_STRICT_PRIORITY			(15)
+#define DCBX_INVALID_COS_BW			(0xFFFFFFFF)
+#define DCBX_PFC_PRI_NON_PAUSE_MASK(bp)		\
+			((bp)->dcbx_port_params.pfc.priority_non_pauseable_mask)
+#define DCBX_PFC_PRI_PAUSE_MASK(bp)		\
+					((u8)~DCBX_PFC_PRI_NON_PAUSE_MASK(bp))
+#define DCBX_PFC_PRI_GET_PAUSE(bp, pg_pri)	\
+				((pg_pri) & (DCBX_PFC_PRI_PAUSE_MASK(bp)))
+#define DCBX_PFC_PRI_GET_NON_PAUSE(bp, pg_pri)	\
+			(DCBX_PFC_PRI_NON_PAUSE_MASK(bp) & (pg_pri))
+#define IS_DCBX_PFC_PRI_ONLY_PAUSE(bp, pg_pri)	\
+			(pg_pri == DCBX_PFC_PRI_GET_PAUSE((bp), (pg_pri)))
+#define IS_DCBX_PFC_PRI_ONLY_NON_PAUSE(bp, pg_pri)\
+			((pg_pri) == DCBX_PFC_PRI_GET_NON_PAUSE((bp), (pg_pri)))
+#define IS_DCBX_PFC_PRI_MIX_PAUSE(bp, pg_pri)	\
+			(!(IS_DCBX_PFC_PRI_ONLY_NON_PAUSE((bp), (pg_pri)) || \
+			 IS_DCBX_PFC_PRI_ONLY_PAUSE((bp), (pg_pri))))
+
+
+struct pg_entry_help_data {
+	u8	num_of_dif_pri;
+	u8	pg;
+	u32	pg_priority;
+};
+
+struct pg_help_data {
+	struct pg_entry_help_data	data[LLFC_DRIVER_TRAFFIC_TYPE_MAX];
+	u8				num_of_pg;
+};
+
+/* forward DCB/PFC related declarations */
+struct bnx2x;
+void bnx2x_dcb_init_intmem_pfc(struct bnx2x *bp);
+void bnx2x_dcbx_update(struct work_struct *work);
+void bnx2x_dcbx_init_params(struct bnx2x *bp);
+void bnx2x_dcbx_set_state(struct bnx2x *bp, bool dcb_on, u32 dcbx_enabled);
+
+enum {
+	BNX2X_DCBX_STATE_NEG_RECEIVED = 0x1,
+	BNX2X_DCBX_STATE_TX_PAUSED = 0x2,
+	BNX2X_DCBX_STATE_TX_RELEASED = 0x4
+};
+void bnx2x_dcbx_set_params(struct bnx2x *bp, u32 state);
+
+/* DCB netlink */
+#ifdef BCM_DCB
+extern const struct dcbnl_rtnl_ops bnx2x_dcbnl_ops;
+#endif /* BCM_DCB */
+
+#endif /* BNX2X_DCB_H */
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/bnx2x/bnx2x_dump.h linux-libre-2.6.38-gnu1/drivers/net/bnx2x/bnx2x_dump.h
--- linux-libre-2.6.37-gnu1/drivers/net/bnx2x/bnx2x_dump.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/bnx2x/bnx2x_dump.h	2011-03-14 21:20:32.000000000 -0400
@@ -1,10 +1,16 @@
 /* bnx2x_dump.h: Broadcom Everest network driver.
  *
- * Copyright (c) 2009 Broadcom Corporation
+ * Copyright (c) 2011 Broadcom 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.
+ * 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.gnu.org/licenses/old-licenses/gpl-2.0.html (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.
  */
 
 
@@ -17,53 +23,53 @@
 #define BNX2X_DUMP_H
 
 
-struct dump_sign {
-	u32 time_stamp;
-	u32 diag_ver;
-	u32 grc_dump_ver;
-};
 
-#define TSTORM_WAITP_ADDR		0x1b8a80
-#define CSTORM_WAITP_ADDR		0x238a80
-#define XSTORM_WAITP_ADDR		0x2b8a80
-#define USTORM_WAITP_ADDR		0x338a80
-#define TSTORM_CAM_MODE			0x1b1440
+/*definitions */
+#define XSTORM_WAITP_ADDR    0x2b8a80
+#define TSTORM_WAITP_ADDR    0x1b8a80
+#define USTORM_WAITP_ADDR    0x338a80
+#define CSTORM_WAITP_ADDR    0x238a80
+#define TSTORM_CAM_MODE         0x1B1440
 
-#define RI_E1				0x1
-#define RI_E1H				0x2
+#define MAX_TIMER_PENDING      200
+#define TIMER_SCAN_DONT_CARE   0xFF
+#define RI_E1			0x1
+#define RI_E1H			0x2
 #define RI_E2			0x4
-#define RI_ONLINE			0x100
+#define RI_ONLINE		0x100
 #define RI_PATH0_DUMP		0x200
 #define RI_PATH1_DUMP		0x400
-#define RI_E1_OFFLINE			(RI_E1)
-#define RI_E1_ONLINE			(RI_E1 | RI_ONLINE)
-#define RI_E1H_OFFLINE			(RI_E1H)
-#define RI_E1H_ONLINE			(RI_E1H | RI_ONLINE)
-#define RI_E2_OFFLINE			(RI_E2)
-#define RI_E2_ONLINE			(RI_E2 | RI_ONLINE)
-#define RI_E1E1H_OFFLINE		(RI_E1 | RI_E1H)
-#define RI_E1E1H_ONLINE			(RI_E1 | RI_E1H | RI_ONLINE)
-#define RI_E1HE2_OFFLINE		(RI_E2 | RI_E1H)
-#define RI_E1HE2_ONLINE			(RI_E2 | RI_E1H | RI_ONLINE)
-#define RI_E1E2_OFFLINE			(RI_E2 | RI_E1)
-#define RI_E1E2_ONLINE			(RI_E2 | RI_E1 | RI_ONLINE)
-#define RI_ALL_OFFLINE			(RI_E1 | RI_E1H | RI_E2)
-#define RI_ALL_ONLINE			(RI_E1 | RI_E1H | RI_E2 | RI_ONLINE)
-
-#define MAX_TIMER_PENDING		200
-#define TIMER_SCAN_DONT_CARE		0xFF
+#define RI_E1_OFFLINE		(RI_E1)
+#define RI_E1_ONLINE		(RI_E1 | RI_ONLINE)
+#define RI_E1H_OFFLINE		(RI_E1H)
+#define RI_E1H_ONLINE		(RI_E1H | RI_ONLINE)
+#define RI_E2_OFFLINE		(RI_E2)
+#define RI_E2_ONLINE		(RI_E2 | RI_ONLINE)
+#define RI_E1E1H_OFFLINE	(RI_E1 | RI_E1H)
+#define RI_E1E1H_ONLINE		(RI_E1 | RI_E1H | RI_ONLINE)
+#define RI_E1HE2_OFFLINE	(RI_E2 | RI_E1H)
+#define RI_E1HE2_ONLINE		(RI_E2 | RI_E1H | RI_ONLINE)
+#define RI_E1E2_OFFLINE		(RI_E2 | RI_E1)
+#define RI_E1E2_ONLINE		(RI_E2 | RI_E1 | RI_ONLINE)
+#define RI_ALL_OFFLINE         (RI_E1 | RI_E1H | RI_E2)
+#define RI_ALL_ONLINE          (RI_E1 | RI_E1H | RI_E2 | RI_ONLINE)
 
+struct dump_sign {
+	u32 time_stamp;
+	u32 diag_ver;
+	u32 grc_dump_ver;
+};
 
 struct dump_hdr {
-	u32		 hdr_size;	/* in dwords, excluding this field */
-	struct dump_sign dump_sign;
-	u32		 xstorm_waitp;
-	u32		 tstorm_waitp;
-	u32		 ustorm_waitp;
-	u32		 cstorm_waitp;
-	u16		 info;
-	u8		 idle_chk;
-	u8		 reserved;
+	u32  hdr_size;	/* in dwords, excluding this field */
+	struct dump_sign	dump_sign;
+	u32  xstorm_waitp;
+	u32  tstorm_waitp;
+	u32  ustorm_waitp;
+	u32  cstorm_waitp;
+	u16  info;
+	u8   idle_chk;
+	u8   reserved;
 };
 
 struct reg_addr {
@@ -80,202 +86,185 @@ struct wreg_addr {
 	u16 info;
 };
 
-
-#define REGS_COUNT			558
+#define REGS_COUNT			834
 static const struct reg_addr reg_addrs[REGS_COUNT] = {
 	{ 0x2000, 341, RI_ALL_ONLINE }, { 0x2800, 103, RI_ALL_ONLINE },
 	{ 0x3000, 287, RI_ALL_ONLINE }, { 0x3800, 331, RI_ALL_ONLINE },
-	{ 0x8800, 6, RI_E1_ONLINE }, { 0xa000, 223, RI_ALL_ONLINE },
-	{ 0xa388, 1, RI_ALL_ONLINE }, { 0xa398, 1, RI_ALL_ONLINE },
-	{ 0xa39c, 7, RI_E1H_ONLINE }, { 0xa3c0, 3, RI_E1H_ONLINE },
-	{ 0xa3d0, 1, RI_E1H_ONLINE }, { 0xa3d8, 1, RI_E1H_ONLINE },
-	{ 0xa3e0, 1, RI_E1H_ONLINE }, { 0xa3e8, 1, RI_E1H_ONLINE },
-	{ 0xa3f0, 1, RI_E1H_ONLINE }, { 0xa3f8, 1, RI_E1H_ONLINE },
-	{ 0xa400, 69, RI_ALL_ONLINE }, { 0xa518, 1, RI_ALL_ONLINE },
-	{ 0xa520, 1, RI_ALL_ONLINE }, { 0xa528, 1, RI_ALL_ONLINE },
-	{ 0xa530, 1, RI_ALL_ONLINE }, { 0xa538, 1, RI_ALL_ONLINE },
-	{ 0xa540, 1, RI_ALL_ONLINE }, { 0xa548, 1, RI_ALL_ONLINE },
-	{ 0xa550, 1, RI_ALL_ONLINE }, { 0xa558, 1, RI_ALL_ONLINE },
-	{ 0xa560, 1, RI_ALL_ONLINE }, { 0xa568, 1, RI_ALL_ONLINE },
-	{ 0xa570, 1, RI_ALL_ONLINE }, { 0xa580, 1, RI_ALL_ONLINE },
-	{ 0xa590, 1, RI_ALL_ONLINE }, { 0xa5a0, 1, RI_ALL_ONLINE },
-	{ 0xa5c0, 1, RI_ALL_ONLINE }, { 0xa5e0, 1, RI_E1H_ONLINE },
-	{ 0xa5e8, 1, RI_E1H_ONLINE }, { 0xa5f0, 1, RI_E1H_ONLINE },
-	{ 0xa5f8, 10, RI_E1H_ONLINE }, { 0x10000, 236, RI_ALL_ONLINE },
-	{ 0x103bc, 1, RI_ALL_ONLINE }, { 0x103cc, 1, RI_ALL_ONLINE },
-	{ 0x103dc, 1, RI_ALL_ONLINE }, { 0x10400, 57, RI_ALL_ONLINE },
-	{ 0x104e8, 2, RI_ALL_ONLINE }, { 0x104f4, 2, RI_ALL_ONLINE },
-	{ 0x10500, 146, RI_ALL_ONLINE }, { 0x10750, 2, RI_ALL_ONLINE },
-	{ 0x10760, 2, RI_ALL_ONLINE }, { 0x10770, 2, RI_ALL_ONLINE },
-	{ 0x10780, 2, RI_ALL_ONLINE }, { 0x10790, 2, RI_ALL_ONLINE },
-	{ 0x107a0, 2, RI_ALL_ONLINE }, { 0x107b0, 2, RI_ALL_ONLINE },
-	{ 0x107c0, 2, RI_ALL_ONLINE }, { 0x107d0, 2, RI_ALL_ONLINE },
-	{ 0x107e0, 2, RI_ALL_ONLINE }, { 0x10880, 2, RI_ALL_ONLINE },
-	{ 0x10900, 2, RI_ALL_ONLINE }, { 0x12000, 1, RI_ALL_ONLINE },
-	{ 0x14000, 1, RI_ALL_ONLINE }, { 0x16000, 26, RI_E1H_ONLINE },
-	{ 0x16070, 18, RI_E1H_ONLINE }, { 0x160c0, 27, RI_E1H_ONLINE },
-	{ 0x16140, 1, RI_E1H_ONLINE }, { 0x16160, 1, RI_E1H_ONLINE },
-	{ 0x16180, 2, RI_E1H_ONLINE }, { 0x161c0, 2, RI_E1H_ONLINE },
-	{ 0x16204, 5, RI_E1H_ONLINE }, { 0x18000, 1, RI_E1H_ONLINE },
-	{ 0x18008, 1, RI_E1H_ONLINE }, { 0x20000, 24, RI_ALL_ONLINE },
-	{ 0x20060, 8, RI_ALL_ONLINE }, { 0x20080, 138, RI_ALL_ONLINE },
-	{ 0x202b4, 1, RI_ALL_ONLINE }, { 0x202c4, 1, RI_ALL_ONLINE },
-	{ 0x20400, 2, RI_ALL_ONLINE }, { 0x2040c, 8, RI_ALL_ONLINE },
-	{ 0x2042c, 18, RI_E1H_ONLINE }, { 0x20480, 1, RI_ALL_ONLINE },
-	{ 0x20500, 1, RI_ALL_ONLINE }, { 0x20600, 1, RI_ALL_ONLINE },
-	{ 0x28000, 1, RI_ALL_ONLINE }, { 0x28004, 8191, RI_ALL_OFFLINE },
-	{ 0x30000, 1, RI_ALL_ONLINE }, { 0x30004, 16383, RI_ALL_OFFLINE },
-	{ 0x40000, 98, RI_ALL_ONLINE }, { 0x40194, 1, RI_ALL_ONLINE },
-	{ 0x401a4, 1, RI_ALL_ONLINE }, { 0x401a8, 11, RI_E1H_ONLINE },
-	{ 0x40200, 4, RI_ALL_ONLINE }, { 0x40400, 43, RI_ALL_ONLINE },
-	{ 0x404b8, 1, RI_ALL_ONLINE }, { 0x404c8, 1, RI_ALL_ONLINE },
-	{ 0x404cc, 3, RI_E1H_ONLINE }, { 0x40500, 2, RI_ALL_ONLINE },
+	{ 0x8800, 6, RI_ALL_ONLINE }, { 0x8818, 1, RI_E1HE2_ONLINE },
+	{ 0x9000, 164, RI_E2_ONLINE }, { 0x9400, 33, RI_E2_ONLINE },
+	{ 0xa000, 27, RI_ALL_ONLINE }, { 0xa06c, 1, RI_E1E1H_ONLINE },
+	{ 0xa070, 71, RI_ALL_ONLINE }, { 0xa18c, 4, RI_E1E1H_ONLINE },
+	{ 0xa19c, 62, RI_ALL_ONLINE }, { 0xa294, 2, RI_E1E1H_ONLINE },
+	{ 0xa29c, 56, RI_ALL_ONLINE }, { 0xa39c, 7, RI_E1HE2_ONLINE },
+	{ 0xa3c0, 3, RI_E1HE2_ONLINE }, { 0xa3d0, 1, RI_E1HE2_ONLINE },
+	{ 0xa3d8, 1, RI_E1HE2_ONLINE }, { 0xa3e0, 1, RI_E1HE2_ONLINE },
+	{ 0xa3e8, 1, RI_E1HE2_ONLINE }, { 0xa3f0, 1, RI_E1HE2_ONLINE },
+	{ 0xa3f8, 1, RI_E1HE2_ONLINE }, { 0xa400, 43, RI_ALL_ONLINE },
+	{ 0xa4ac, 2, RI_E1E1H_ONLINE }, { 0xa4b4, 1, RI_ALL_ONLINE },
+	{ 0xa4b8, 2, RI_E1E1H_ONLINE }, { 0xa4c0, 3, RI_ALL_ONLINE },
+	{ 0xa4cc, 5, RI_E1E1H_ONLINE }, { 0xa4e0, 9, RI_ALL_ONLINE },
+	{ 0xa504, 1, RI_E1E1H_ONLINE }, { 0xa508, 3, RI_ALL_ONLINE },
+	{ 0xa518, 1, RI_ALL_ONLINE }, { 0xa520, 1, RI_ALL_ONLINE },
+	{ 0xa528, 1, RI_ALL_ONLINE }, { 0xa530, 1, RI_ALL_ONLINE },
+	{ 0xa538, 1, RI_ALL_ONLINE }, { 0xa540, 1, RI_ALL_ONLINE },
+	{ 0xa548, 1, RI_E1E1H_ONLINE }, { 0xa550, 1, RI_E1E1H_ONLINE },
+	{ 0xa558, 1, RI_E1E1H_ONLINE }, { 0xa560, 1, RI_E1E1H_ONLINE },
+	{ 0xa568, 1, RI_E1E1H_ONLINE }, { 0xa570, 1, RI_ALL_ONLINE },
+	{ 0xa580, 1, RI_ALL_ONLINE }, { 0xa590, 1, RI_ALL_ONLINE },
+	{ 0xa5a0, 1, RI_ALL_ONLINE }, { 0xa5c0, 1, RI_ALL_ONLINE },
+	{ 0xa5e0, 1, RI_E1HE2_ONLINE }, { 0xa5e8, 1, RI_E1HE2_ONLINE },
+	{ 0xa5f0, 1, RI_E1HE2_ONLINE }, { 0xa5f8, 10, RI_E1HE2_ONLINE },
+	{ 0xa620, 111, RI_E2_ONLINE }, { 0xa800, 51, RI_E2_ONLINE },
+	{ 0xa8d4, 4, RI_E2_ONLINE }, { 0xa8e8, 1, RI_E2_ONLINE },
+	{ 0xa8f0, 1, RI_E2_ONLINE }, { 0x10000, 236, RI_ALL_ONLINE },
+	{ 0x10400, 57, RI_ALL_ONLINE }, { 0x104e8, 2, RI_ALL_ONLINE },
+	{ 0x104f4, 2, RI_ALL_ONLINE }, { 0x10500, 146, RI_ALL_ONLINE },
+	{ 0x10750, 2, RI_ALL_ONLINE }, { 0x10760, 2, RI_ALL_ONLINE },
+	{ 0x10770, 2, RI_ALL_ONLINE }, { 0x10780, 2, RI_ALL_ONLINE },
+	{ 0x10790, 2, RI_ALL_ONLINE }, { 0x107a0, 2, RI_ALL_ONLINE },
+	{ 0x107b0, 2, RI_ALL_ONLINE }, { 0x107c0, 2, RI_ALL_ONLINE },
+	{ 0x107d0, 2, RI_ALL_ONLINE }, { 0x107e0, 2, RI_ALL_ONLINE },
+	{ 0x10880, 2, RI_ALL_ONLINE }, { 0x10900, 2, RI_ALL_ONLINE },
+	{ 0x16000, 26, RI_E1HE2_ONLINE }, { 0x16070, 18, RI_E1HE2_ONLINE },
+	{ 0x160c0, 27, RI_E1HE2_ONLINE }, { 0x16140, 1, RI_E1HE2_ONLINE },
+	{ 0x16160, 1, RI_E1HE2_ONLINE }, { 0x16180, 2, RI_E1HE2_ONLINE },
+	{ 0x161c0, 2, RI_E1HE2_ONLINE }, { 0x16204, 5, RI_E1HE2_ONLINE },
+	{ 0x18000, 1, RI_E1HE2_ONLINE }, { 0x18008, 1, RI_E1HE2_ONLINE },
+	{ 0x18010, 35, RI_E2_ONLINE }, { 0x180a4, 2, RI_E2_ONLINE },
+	{ 0x180c0, 191, RI_E2_ONLINE }, { 0x18440, 1, RI_E2_ONLINE },
+	{ 0x18460, 1, RI_E2_ONLINE }, { 0x18480, 2, RI_E2_ONLINE },
+	{ 0x184c0, 2, RI_E2_ONLINE }, { 0x18500, 15, RI_E2_ONLINE },
+	{ 0x20000, 24, RI_ALL_ONLINE }, { 0x20060, 8, RI_ALL_ONLINE },
+	{ 0x20080, 94, RI_ALL_ONLINE }, { 0x201f8, 1, RI_E1E1H_ONLINE },
+	{ 0x201fc, 1, RI_ALL_ONLINE }, { 0x20200, 1, RI_E1E1H_ONLINE },
+	{ 0x20204, 1, RI_ALL_ONLINE }, { 0x20208, 1, RI_E1E1H_ONLINE },
+	{ 0x2020c, 39, RI_ALL_ONLINE }, { 0x202c8, 1, RI_E2_ONLINE },
+	{ 0x202d8, 4, RI_E2_ONLINE }, { 0x20400, 2, RI_ALL_ONLINE },
+	{ 0x2040c, 8, RI_ALL_ONLINE }, { 0x2042c, 18, RI_E1HE2_ONLINE },
+	{ 0x20480, 1, RI_ALL_ONLINE }, { 0x20500, 1, RI_ALL_ONLINE },
+	{ 0x20600, 1, RI_ALL_ONLINE }, { 0x28000, 1, RI_ALL_ONLINE },
+	{ 0x28004, 8191, RI_ALL_OFFLINE }, { 0x30000, 1, RI_ALL_ONLINE },
+	{ 0x30004, 16383, RI_ALL_OFFLINE }, { 0x40000, 98, RI_ALL_ONLINE },
+	{ 0x401a8, 8, RI_E1HE2_ONLINE }, { 0x401c8, 1, RI_E1H_ONLINE },
+	{ 0x401cc, 2, RI_E1HE2_ONLINE }, { 0x401d4, 2, RI_E2_ONLINE },
+	{ 0x40200, 4, RI_ALL_ONLINE }, { 0x40220, 18, RI_E2_ONLINE },
+	{ 0x40400, 43, RI_ALL_ONLINE }, { 0x404cc, 3, RI_E1HE2_ONLINE },
+	{ 0x404e0, 1, RI_E2_ONLINE }, { 0x40500, 2, RI_ALL_ONLINE },
 	{ 0x40510, 2, RI_ALL_ONLINE }, { 0x40520, 2, RI_ALL_ONLINE },
 	{ 0x40530, 2, RI_ALL_ONLINE }, { 0x40540, 2, RI_ALL_ONLINE },
-	{ 0x42000, 164, RI_ALL_ONLINE }, { 0x4229c, 1, RI_ALL_ONLINE },
-	{ 0x422ac, 1, RI_ALL_ONLINE }, { 0x422bc, 1, RI_ALL_ONLINE },
-	{ 0x422d4, 5, RI_E1H_ONLINE }, { 0x42400, 49, RI_ALL_ONLINE },
-	{ 0x424c8, 38, RI_ALL_ONLINE }, { 0x42568, 2, RI_ALL_ONLINE },
-	{ 0x42800, 1, RI_ALL_ONLINE }, { 0x50000, 20, RI_ALL_ONLINE },
-	{ 0x50050, 8, RI_ALL_ONLINE }, { 0x50070, 88, RI_ALL_ONLINE },
-	{ 0x501dc, 1, RI_ALL_ONLINE }, { 0x501ec, 1, RI_ALL_ONLINE },
-	{ 0x501f0, 4, RI_E1H_ONLINE }, { 0x50200, 2, RI_ALL_ONLINE },
-	{ 0x5020c, 7, RI_ALL_ONLINE }, { 0x50228, 6, RI_E1H_ONLINE },
-	{ 0x50240, 1, RI_ALL_ONLINE }, { 0x50280, 1, RI_ALL_ONLINE },
+	{ 0x40550, 10, RI_E2_ONLINE }, { 0x40610, 2, RI_E2_ONLINE },
+	{ 0x42000, 164, RI_ALL_ONLINE }, { 0x422c0, 4, RI_E2_ONLINE },
+	{ 0x422d4, 5, RI_E1HE2_ONLINE }, { 0x422e8, 1, RI_E2_ONLINE },
+	{ 0x42400, 49, RI_ALL_ONLINE }, { 0x424c8, 38, RI_ALL_ONLINE },
+	{ 0x42568, 2, RI_ALL_ONLINE }, { 0x42640, 5, RI_E2_ONLINE },
+	{ 0x42800, 1, RI_ALL_ONLINE }, { 0x50000, 1, RI_ALL_ONLINE },
+	{ 0x50004, 19, RI_ALL_ONLINE }, { 0x50050, 8, RI_ALL_ONLINE },
+	{ 0x50070, 88, RI_ALL_ONLINE }, { 0x501f0, 4, RI_E1HE2_ONLINE },
+	{ 0x50200, 2, RI_ALL_ONLINE }, { 0x5020c, 7, RI_ALL_ONLINE },
+	{ 0x50228, 6, RI_E1HE2_ONLINE }, { 0x50240, 1, RI_ALL_ONLINE },
+	{ 0x50280, 1, RI_ALL_ONLINE }, { 0x50300, 1, RI_E2_ONLINE },
+	{ 0x5030c, 1, RI_E2_ONLINE }, { 0x50318, 1, RI_E2_ONLINE },
+	{ 0x5031c, 1, RI_E2_ONLINE }, { 0x50320, 2, RI_E2_ONLINE },
 	{ 0x52000, 1, RI_ALL_ONLINE }, { 0x54000, 1, RI_ALL_ONLINE },
 	{ 0x54004, 3327, RI_ALL_OFFLINE }, { 0x58000, 1, RI_ALL_ONLINE },
-	{ 0x58004, 8191, RI_ALL_OFFLINE }, { 0x60000, 71, RI_ALL_ONLINE },
-	{ 0x60128, 1, RI_ALL_ONLINE }, { 0x60138, 1, RI_ALL_ONLINE },
-	{ 0x6013c, 24, RI_E1H_ONLINE }, { 0x60200, 1, RI_ALL_ONLINE },
+	{ 0x58004, 8191, RI_E1E1H_OFFLINE }, { 0x60000, 26, RI_ALL_ONLINE },
+	{ 0x60068, 8, RI_E1E1H_ONLINE }, { 0x60088, 12, RI_ALL_ONLINE },
+	{ 0x600b8, 9, RI_E1E1H_ONLINE }, { 0x600dc, 1, RI_ALL_ONLINE },
+	{ 0x600e0, 5, RI_E1E1H_ONLINE }, { 0x600f4, 1, RI_ALL_ONLINE },
+	{ 0x600f8, 1, RI_E1E1H_ONLINE }, { 0x600fc, 8, RI_ALL_ONLINE },
+	{ 0x6013c, 24, RI_E1H_ONLINE }, { 0x6019c, 2, RI_E2_ONLINE },
+	{ 0x601ac, 18, RI_E2_ONLINE }, { 0x60200, 1, RI_ALL_ONLINE },
+	{ 0x60204, 2, RI_ALL_OFFLINE }, { 0x60210, 13, RI_E2_ONLINE },
 	{ 0x61000, 1, RI_ALL_ONLINE }, { 0x61004, 511, RI_ALL_OFFLINE },
-	{ 0x70000, 8, RI_ALL_ONLINE }, { 0x70020, 21496, RI_ALL_OFFLINE },
-	{ 0x85000, 3, RI_ALL_ONLINE }, { 0x8500c, 4, RI_ALL_OFFLINE },
-	{ 0x8501c, 7, RI_ALL_ONLINE }, { 0x85038, 4, RI_ALL_OFFLINE },
-	{ 0x85048, 1, RI_ALL_ONLINE }, { 0x8504c, 109, RI_ALL_OFFLINE },
-	{ 0x85200, 32, RI_ALL_ONLINE }, { 0x85280, 11104, RI_ALL_OFFLINE },
-	{ 0xa0000, 16384, RI_ALL_ONLINE }, { 0xb0000, 16384, RI_E1H_ONLINE },
-	{ 0xc1000, 7, RI_ALL_ONLINE }, { 0xc1028, 1, RI_ALL_ONLINE },
-	{ 0xc1038, 1, RI_ALL_ONLINE }, { 0xc1800, 2, RI_ALL_ONLINE },
-	{ 0xc2000, 164, RI_ALL_ONLINE }, { 0xc229c, 1, RI_ALL_ONLINE },
-	{ 0xc22ac, 1, RI_ALL_ONLINE }, { 0xc22bc, 1, RI_ALL_ONLINE },
+	{ 0x70000, 8, RI_ALL_ONLINE }, { 0x70020, 8184, RI_ALL_OFFLINE },
+	{ 0x85000, 3, RI_ALL_ONLINE }, { 0x8501c, 7, RI_ALL_ONLINE },
+	{ 0x85048, 1, RI_ALL_ONLINE }, { 0x85200, 32, RI_ALL_ONLINE },
+	{ 0xc1000, 7, RI_ALL_ONLINE }, { 0xc103c, 2, RI_E2_ONLINE },
+	{ 0xc1800, 2, RI_ALL_ONLINE }, { 0xc2000, 164, RI_ALL_ONLINE },
+	{ 0xc22c0, 5, RI_E2_ONLINE }, { 0xc22d8, 4, RI_E2_ONLINE },
 	{ 0xc2400, 49, RI_ALL_ONLINE }, { 0xc24c8, 38, RI_ALL_ONLINE },
 	{ 0xc2568, 2, RI_ALL_ONLINE }, { 0xc2600, 1, RI_ALL_ONLINE },
-	{ 0xc4000, 165, RI_ALL_ONLINE }, { 0xc42a0, 1, RI_ALL_ONLINE },
-	{ 0xc42b0, 1, RI_ALL_ONLINE }, { 0xc42c0, 1, RI_ALL_ONLINE },
-	{ 0xc42e0, 7, RI_E1H_ONLINE }, { 0xc4400, 51, RI_ALL_ONLINE },
-	{ 0xc44d0, 38, RI_ALL_ONLINE }, { 0xc4570, 2, RI_ALL_ONLINE },
+	{ 0xc4000, 165, RI_ALL_ONLINE }, { 0xc42d8, 2, RI_E2_ONLINE },
+	{ 0xc42e0, 7, RI_E1HE2_ONLINE }, { 0xc42fc, 1, RI_E2_ONLINE },
+	{ 0xc4400, 51, RI_ALL_ONLINE }, { 0xc44d0, 38, RI_ALL_ONLINE },
+	{ 0xc4570, 2, RI_ALL_ONLINE }, { 0xc4578, 5, RI_E2_ONLINE },
 	{ 0xc4600, 1, RI_ALL_ONLINE }, { 0xd0000, 19, RI_ALL_ONLINE },
 	{ 0xd004c, 8, RI_ALL_ONLINE }, { 0xd006c, 91, RI_ALL_ONLINE },
-	{ 0xd01e4, 1, RI_ALL_ONLINE }, { 0xd01f4, 1, RI_ALL_ONLINE },
-	{ 0xd0200, 2, RI_ALL_ONLINE }, { 0xd020c, 7, RI_ALL_ONLINE },
-	{ 0xd0228, 18, RI_E1H_ONLINE }, { 0xd0280, 1, RI_ALL_ONLINE },
-	{ 0xd0300, 1, RI_ALL_ONLINE }, { 0xd0400, 1, RI_ALL_ONLINE },
-	{ 0xd4000, 1, RI_ALL_ONLINE }, { 0xd4004, 2559, RI_ALL_OFFLINE },
-	{ 0xd8000, 1, RI_ALL_ONLINE }, { 0xd8004, 8191, RI_ALL_OFFLINE },
-	{ 0xe0000, 21, RI_ALL_ONLINE }, { 0xe0054, 8, RI_ALL_ONLINE },
-	{ 0xe0074, 85, RI_ALL_ONLINE }, { 0xe01d4, 1, RI_ALL_ONLINE },
-	{ 0xe01e4, 1, RI_ALL_ONLINE }, { 0xe0200, 2, RI_ALL_ONLINE },
-	{ 0xe020c, 8, RI_ALL_ONLINE }, { 0xe022c, 18, RI_E1H_ONLINE },
+	{ 0xd01fc, 1, RI_E2_ONLINE }, { 0xd0200, 2, RI_ALL_ONLINE },
+	{ 0xd020c, 7, RI_ALL_ONLINE }, { 0xd0228, 18, RI_E1HE2_ONLINE },
+	{ 0xd0280, 1, RI_ALL_ONLINE }, { 0xd0300, 1, RI_ALL_ONLINE },
+	{ 0xd0400, 1, RI_ALL_ONLINE }, { 0xd4000, 1, RI_ALL_ONLINE },
+	{ 0xd4004, 2559, RI_ALL_OFFLINE }, { 0xd8000, 1, RI_ALL_ONLINE },
+	{ 0xd8004, 8191, RI_ALL_OFFLINE }, { 0xe0000, 21, RI_ALL_ONLINE },
+	{ 0xe0054, 8, RI_ALL_ONLINE }, { 0xe0074, 49, RI_ALL_ONLINE },
+	{ 0xe0138, 1, RI_E1E1H_ONLINE }, { 0xe013c, 35, RI_ALL_ONLINE },
+	{ 0xe01f4, 2, RI_E2_ONLINE }, { 0xe0200, 2, RI_ALL_ONLINE },
+	{ 0xe020c, 8, RI_ALL_ONLINE }, { 0xe022c, 18, RI_E1HE2_ONLINE },
 	{ 0xe0280, 1, RI_ALL_ONLINE }, { 0xe0300, 1, RI_ALL_ONLINE },
 	{ 0xe1000, 1, RI_ALL_ONLINE }, { 0xe2000, 1, RI_ALL_ONLINE },
 	{ 0xe2004, 2047, RI_ALL_OFFLINE }, { 0xf0000, 1, RI_ALL_ONLINE },
 	{ 0xf0004, 16383, RI_ALL_OFFLINE }, { 0x101000, 12, RI_ALL_ONLINE },
-	{ 0x10103c, 1, RI_ALL_ONLINE }, { 0x10104c, 1, RI_ALL_ONLINE },
-	{ 0x101050, 1, RI_E1H_ONLINE }, { 0x101100, 1, RI_ALL_ONLINE },
-	{ 0x101800, 8, RI_ALL_ONLINE }, { 0x102000, 18, RI_ALL_ONLINE },
-	{ 0x102054, 1, RI_ALL_ONLINE }, { 0x102064, 1, RI_ALL_ONLINE },
+	{ 0x101050, 1, RI_E1HE2_ONLINE }, { 0x101054, 3, RI_E2_ONLINE },
+	{ 0x101100, 1, RI_ALL_ONLINE }, { 0x101800, 8, RI_ALL_ONLINE },
+	{ 0x102000, 18, RI_ALL_ONLINE }, { 0x102068, 6, RI_E2_ONLINE },
 	{ 0x102080, 17, RI_ALL_ONLINE }, { 0x1020c8, 8, RI_E1H_ONLINE },
-	{ 0x102400, 1, RI_ALL_ONLINE }, { 0x103000, 26, RI_ALL_ONLINE },
-	{ 0x103074, 1, RI_ALL_ONLINE }, { 0x103084, 1, RI_ALL_ONLINE },
-	{ 0x103094, 1, RI_ALL_ONLINE }, { 0x103098, 5, RI_E1H_ONLINE },
+	{ 0x1020e8, 9, RI_E2_ONLINE }, { 0x102400, 1, RI_ALL_ONLINE },
+	{ 0x103000, 26, RI_ALL_ONLINE }, { 0x103098, 5, RI_E1HE2_ONLINE },
+	{ 0x1030ac, 10, RI_E2_ONLINE }, { 0x1030d8, 8, RI_E2_ONLINE },
+	{ 0x103400, 1, RI_E2_ONLINE }, { 0x103404, 135, RI_E2_OFFLINE },
 	{ 0x103800, 8, RI_ALL_ONLINE }, { 0x104000, 63, RI_ALL_ONLINE },
-	{ 0x104108, 1, RI_ALL_ONLINE }, { 0x104118, 1, RI_ALL_ONLINE },
-	{ 0x104200, 17, RI_ALL_ONLINE }, { 0x104400, 64, RI_ALL_ONLINE },
-	{ 0x104500, 192, RI_ALL_OFFLINE }, { 0x104800, 64, RI_ALL_ONLINE },
-	{ 0x104900, 192, RI_ALL_OFFLINE }, { 0x105000, 7, RI_ALL_ONLINE },
-	{ 0x10501c, 1, RI_ALL_OFFLINE }, { 0x105020, 3, RI_ALL_ONLINE },
-	{ 0x10502c, 1, RI_ALL_OFFLINE }, { 0x105030, 3, RI_ALL_ONLINE },
-	{ 0x10503c, 1, RI_ALL_OFFLINE }, { 0x105040, 3, RI_ALL_ONLINE },
-	{ 0x10504c, 1, RI_ALL_OFFLINE }, { 0x105050, 3, RI_ALL_ONLINE },
-	{ 0x10505c, 1, RI_ALL_OFFLINE }, { 0x105060, 3, RI_ALL_ONLINE },
-	{ 0x10506c, 1, RI_ALL_OFFLINE }, { 0x105070, 3, RI_ALL_ONLINE },
-	{ 0x10507c, 1, RI_ALL_OFFLINE }, { 0x105080, 3, RI_ALL_ONLINE },
-	{ 0x10508c, 1, RI_ALL_OFFLINE }, { 0x105090, 3, RI_ALL_ONLINE },
-	{ 0x10509c, 1, RI_ALL_OFFLINE }, { 0x1050a0, 3, RI_ALL_ONLINE },
-	{ 0x1050ac, 1, RI_ALL_OFFLINE }, { 0x1050b0, 3, RI_ALL_ONLINE },
-	{ 0x1050bc, 1, RI_ALL_OFFLINE }, { 0x1050c0, 3, RI_ALL_ONLINE },
-	{ 0x1050cc, 1, RI_ALL_OFFLINE }, { 0x1050d0, 3, RI_ALL_ONLINE },
-	{ 0x1050dc, 1, RI_ALL_OFFLINE }, { 0x1050e0, 3, RI_ALL_ONLINE },
-	{ 0x1050ec, 1, RI_ALL_OFFLINE }, { 0x1050f0, 3, RI_ALL_ONLINE },
-	{ 0x1050fc, 1, RI_ALL_OFFLINE }, { 0x105100, 3, RI_ALL_ONLINE },
-	{ 0x10510c, 1, RI_ALL_OFFLINE }, { 0x105110, 3, RI_ALL_ONLINE },
-	{ 0x10511c, 1, RI_ALL_OFFLINE }, { 0x105120, 3, RI_ALL_ONLINE },
-	{ 0x10512c, 1, RI_ALL_OFFLINE }, { 0x105130, 3, RI_ALL_ONLINE },
-	{ 0x10513c, 1, RI_ALL_OFFLINE }, { 0x105140, 3, RI_ALL_ONLINE },
-	{ 0x10514c, 1, RI_ALL_OFFLINE }, { 0x105150, 3, RI_ALL_ONLINE },
-	{ 0x10515c, 1, RI_ALL_OFFLINE }, { 0x105160, 3, RI_ALL_ONLINE },
-	{ 0x10516c, 1, RI_ALL_OFFLINE }, { 0x105170, 3, RI_ALL_ONLINE },
-	{ 0x10517c, 1, RI_ALL_OFFLINE }, { 0x105180, 3, RI_ALL_ONLINE },
-	{ 0x10518c, 1, RI_ALL_OFFLINE }, { 0x105190, 3, RI_ALL_ONLINE },
-	{ 0x10519c, 1, RI_ALL_OFFLINE }, { 0x1051a0, 3, RI_ALL_ONLINE },
-	{ 0x1051ac, 1, RI_ALL_OFFLINE }, { 0x1051b0, 3, RI_ALL_ONLINE },
-	{ 0x1051bc, 1, RI_ALL_OFFLINE }, { 0x1051c0, 3, RI_ALL_ONLINE },
-	{ 0x1051cc, 1, RI_ALL_OFFLINE }, { 0x1051d0, 3, RI_ALL_ONLINE },
-	{ 0x1051dc, 1, RI_ALL_OFFLINE }, { 0x1051e0, 3, RI_ALL_ONLINE },
-	{ 0x1051ec, 1, RI_ALL_OFFLINE }, { 0x1051f0, 3, RI_ALL_ONLINE },
-	{ 0x1051fc, 1, RI_ALL_OFFLINE }, { 0x105200, 3, RI_ALL_ONLINE },
-	{ 0x10520c, 1, RI_ALL_OFFLINE }, { 0x105210, 3, RI_ALL_ONLINE },
-	{ 0x10521c, 1, RI_ALL_OFFLINE }, { 0x105220, 3, RI_ALL_ONLINE },
-	{ 0x10522c, 1, RI_ALL_OFFLINE }, { 0x105230, 3, RI_ALL_ONLINE },
-	{ 0x10523c, 1, RI_ALL_OFFLINE }, { 0x105240, 3, RI_ALL_ONLINE },
-	{ 0x10524c, 1, RI_ALL_OFFLINE }, { 0x105250, 3, RI_ALL_ONLINE },
-	{ 0x10525c, 1, RI_ALL_OFFLINE }, { 0x105260, 3, RI_ALL_ONLINE },
-	{ 0x10526c, 1, RI_ALL_OFFLINE }, { 0x105270, 3, RI_ALL_ONLINE },
-	{ 0x10527c, 1, RI_ALL_OFFLINE }, { 0x105280, 3, RI_ALL_ONLINE },
-	{ 0x10528c, 1, RI_ALL_OFFLINE }, { 0x105290, 3, RI_ALL_ONLINE },
-	{ 0x10529c, 1, RI_ALL_OFFLINE }, { 0x1052a0, 3, RI_ALL_ONLINE },
-	{ 0x1052ac, 1, RI_ALL_OFFLINE }, { 0x1052b0, 3, RI_ALL_ONLINE },
-	{ 0x1052bc, 1, RI_ALL_OFFLINE }, { 0x1052c0, 3, RI_ALL_ONLINE },
-	{ 0x1052cc, 1, RI_ALL_OFFLINE }, { 0x1052d0, 3, RI_ALL_ONLINE },
-	{ 0x1052dc, 1, RI_ALL_OFFLINE }, { 0x1052e0, 3, RI_ALL_ONLINE },
-	{ 0x1052ec, 1, RI_ALL_OFFLINE }, { 0x1052f0, 3, RI_ALL_ONLINE },
-	{ 0x1052fc, 1, RI_ALL_OFFLINE }, { 0x105300, 3, RI_ALL_ONLINE },
-	{ 0x10530c, 1, RI_ALL_OFFLINE }, { 0x105310, 3, RI_ALL_ONLINE },
-	{ 0x10531c, 1, RI_ALL_OFFLINE }, { 0x105320, 3, RI_ALL_ONLINE },
-	{ 0x10532c, 1, RI_ALL_OFFLINE }, { 0x105330, 3, RI_ALL_ONLINE },
-	{ 0x10533c, 1, RI_ALL_OFFLINE }, { 0x105340, 3, RI_ALL_ONLINE },
-	{ 0x10534c, 1, RI_ALL_OFFLINE }, { 0x105350, 3, RI_ALL_ONLINE },
-	{ 0x10535c, 1, RI_ALL_OFFLINE }, { 0x105360, 3, RI_ALL_ONLINE },
-	{ 0x10536c, 1, RI_ALL_OFFLINE }, { 0x105370, 3, RI_ALL_ONLINE },
-	{ 0x10537c, 1, RI_ALL_OFFLINE }, { 0x105380, 3, RI_ALL_ONLINE },
-	{ 0x10538c, 1, RI_ALL_OFFLINE }, { 0x105390, 3, RI_ALL_ONLINE },
-	{ 0x10539c, 1, RI_ALL_OFFLINE }, { 0x1053a0, 3, RI_ALL_ONLINE },
-	{ 0x1053ac, 1, RI_ALL_OFFLINE }, { 0x1053b0, 3, RI_ALL_ONLINE },
-	{ 0x1053bc, 1, RI_ALL_OFFLINE }, { 0x1053c0, 3, RI_ALL_ONLINE },
-	{ 0x1053cc, 1, RI_ALL_OFFLINE }, { 0x1053d0, 3, RI_ALL_ONLINE },
-	{ 0x1053dc, 1, RI_ALL_OFFLINE }, { 0x1053e0, 3, RI_ALL_ONLINE },
-	{ 0x1053ec, 1, RI_ALL_OFFLINE }, { 0x1053f0, 3, RI_ALL_ONLINE },
-	{ 0x1053fc, 769, RI_ALL_OFFLINE }, { 0x108000, 33, RI_ALL_ONLINE },
-	{ 0x108090, 1, RI_ALL_ONLINE }, { 0x1080a0, 1, RI_ALL_ONLINE },
-	{ 0x1080ac, 5, RI_E1H_ONLINE }, { 0x108100, 5, RI_ALL_ONLINE },
-	{ 0x108120, 5, RI_ALL_ONLINE }, { 0x108200, 74, RI_ALL_ONLINE },
-	{ 0x108400, 74, RI_ALL_ONLINE }, { 0x108800, 152, RI_ALL_ONLINE },
-	{ 0x109000, 1, RI_ALL_ONLINE }, { 0x120000, 347, RI_ALL_ONLINE },
-	{ 0x120578, 1, RI_ALL_ONLINE }, { 0x120588, 1, RI_ALL_ONLINE },
-	{ 0x120598, 1, RI_ALL_ONLINE }, { 0x12059c, 23, RI_E1H_ONLINE },
-	{ 0x120614, 1, RI_E1H_ONLINE }, { 0x12061c, 30, RI_E1H_ONLINE },
-	{ 0x12080c, 65, RI_ALL_ONLINE }, { 0x120a00, 2, RI_ALL_ONLINE },
-	{ 0x122000, 2, RI_ALL_ONLINE }, { 0x128000, 2, RI_E1H_ONLINE },
-	{ 0x140000, 114, RI_ALL_ONLINE }, { 0x1401d4, 1, RI_ALL_ONLINE },
-	{ 0x1401e4, 1, RI_ALL_ONLINE }, { 0x140200, 6, RI_ALL_ONLINE },
-	{ 0x144000, 4, RI_ALL_ONLINE }, { 0x148000, 4, RI_ALL_ONLINE },
-	{ 0x14c000, 4, RI_ALL_ONLINE }, { 0x150000, 4, RI_ALL_ONLINE },
-	{ 0x154000, 4, RI_ALL_ONLINE }, { 0x158000, 4, RI_ALL_ONLINE },
-	{ 0x15c000, 7, RI_E1H_ONLINE }, { 0x161000, 7, RI_ALL_ONLINE },
-	{ 0x161028, 1, RI_ALL_ONLINE }, { 0x161038, 1, RI_ALL_ONLINE },
-	{ 0x161800, 2, RI_ALL_ONLINE }, { 0x164000, 60, RI_ALL_ONLINE },
-	{ 0x1640fc, 1, RI_ALL_ONLINE }, { 0x16410c, 1, RI_ALL_ONLINE },
-	{ 0x164110, 2, RI_E1H_ONLINE }, { 0x164200, 1, RI_ALL_ONLINE },
+	{ 0x10411c, 16, RI_E2_ONLINE }, { 0x104200, 17, RI_ALL_ONLINE },
+	{ 0x104400, 64, RI_ALL_ONLINE }, { 0x104500, 192, RI_ALL_OFFLINE },
+	{ 0x104800, 64, RI_ALL_ONLINE }, { 0x104900, 192, RI_ALL_OFFLINE },
+	{ 0x105000, 256, RI_ALL_ONLINE }, { 0x105400, 768, RI_ALL_OFFLINE },
+	{ 0x107000, 7, RI_E2_ONLINE }, { 0x108000, 33, RI_E1E1H_ONLINE },
+	{ 0x1080ac, 5, RI_E1H_ONLINE }, { 0x108100, 5, RI_E1E1H_ONLINE },
+	{ 0x108120, 5, RI_E1E1H_ONLINE }, { 0x108200, 74, RI_E1E1H_ONLINE },
+	{ 0x108400, 74, RI_E1E1H_ONLINE }, { 0x108800, 152, RI_E1E1H_ONLINE },
+	{ 0x110000, 111, RI_E2_ONLINE }, { 0x110200, 4, RI_E2_ONLINE },
+	{ 0x120000, 2, RI_ALL_ONLINE }, { 0x120008, 4, RI_ALL_ONLINE },
+	{ 0x120018, 3, RI_ALL_ONLINE }, { 0x120024, 4, RI_ALL_ONLINE },
+	{ 0x120034, 3, RI_ALL_ONLINE }, { 0x120040, 4, RI_ALL_ONLINE },
+	{ 0x120050, 3, RI_ALL_ONLINE }, { 0x12005c, 4, RI_ALL_ONLINE },
+	{ 0x12006c, 3, RI_ALL_ONLINE }, { 0x120078, 4, RI_ALL_ONLINE },
+	{ 0x120088, 3, RI_ALL_ONLINE }, { 0x120094, 4, RI_ALL_ONLINE },
+	{ 0x1200a4, 3, RI_ALL_ONLINE }, { 0x1200b0, 4, RI_ALL_ONLINE },
+	{ 0x1200c0, 3, RI_ALL_ONLINE }, { 0x1200cc, 4, RI_ALL_ONLINE },
+	{ 0x1200dc, 3, RI_ALL_ONLINE }, { 0x1200e8, 4, RI_ALL_ONLINE },
+	{ 0x1200f8, 3, RI_ALL_ONLINE }, { 0x120104, 4, RI_ALL_ONLINE },
+	{ 0x120114, 1, RI_ALL_ONLINE }, { 0x120118, 22, RI_ALL_ONLINE },
+	{ 0x120170, 2, RI_E1E1H_ONLINE }, { 0x120178, 243, RI_ALL_ONLINE },
+	{ 0x120544, 4, RI_E1E1H_ONLINE }, { 0x120554, 7, RI_ALL_ONLINE },
+	{ 0x12059c, 6, RI_E1HE2_ONLINE }, { 0x1205b4, 1, RI_E1HE2_ONLINE },
+	{ 0x1205b8, 16, RI_E1HE2_ONLINE }, { 0x1205f8, 4, RI_E2_ONLINE },
+	{ 0x120618, 1, RI_E2_ONLINE }, { 0x12061c, 20, RI_E1HE2_ONLINE },
+	{ 0x12066c, 11, RI_E1HE2_ONLINE }, { 0x120698, 5, RI_E2_ONLINE },
+	{ 0x1206b0, 76, RI_E2_ONLINE }, { 0x1207fc, 1, RI_E2_ONLINE },
+	{ 0x120808, 66, RI_ALL_ONLINE }, { 0x120910, 7, RI_E2_ONLINE },
+	{ 0x120930, 9, RI_E2_ONLINE }, { 0x120a00, 2, RI_ALL_ONLINE },
+	{ 0x122000, 2, RI_ALL_ONLINE }, { 0x122008, 2046, RI_E1_OFFLINE },
+	{ 0x128000, 2, RI_E1HE2_ONLINE }, { 0x128008, 6142, RI_E1HE2_OFFLINE },
+	{ 0x130000, 35, RI_E2_ONLINE }, { 0x130100, 29, RI_E2_ONLINE },
+	{ 0x130180, 1, RI_E2_ONLINE }, { 0x130200, 1, RI_E2_ONLINE },
+	{ 0x130280, 1, RI_E2_ONLINE }, { 0x130300, 5, RI_E2_ONLINE },
+	{ 0x130380, 1, RI_E2_ONLINE }, { 0x130400, 1, RI_E2_ONLINE },
+	{ 0x130480, 5, RI_E2_ONLINE }, { 0x130800, 72, RI_E2_ONLINE },
+	{ 0x131000, 136, RI_E2_ONLINE }, { 0x132000, 148, RI_E2_ONLINE },
+	{ 0x134000, 544, RI_E2_ONLINE }, { 0x140000, 64, RI_ALL_ONLINE },
+	{ 0x140100, 5, RI_E1E1H_ONLINE }, { 0x140114, 45, RI_ALL_ONLINE },
+	{ 0x140200, 6, RI_ALL_ONLINE }, { 0x140220, 4, RI_E2_ONLINE },
+	{ 0x140240, 4, RI_E2_ONLINE }, { 0x140260, 4, RI_E2_ONLINE },
+	{ 0x140280, 4, RI_E2_ONLINE }, { 0x1402a0, 4, RI_E2_ONLINE },
+	{ 0x1402c0, 4, RI_E2_ONLINE }, { 0x1402e0, 13, RI_E2_ONLINE },
+	{ 0x144000, 4, RI_E1E1H_ONLINE }, { 0x148000, 4, RI_E1E1H_ONLINE },
+	{ 0x14c000, 4, RI_E1E1H_ONLINE }, { 0x150000, 4, RI_E1E1H_ONLINE },
+	{ 0x154000, 4, RI_E1E1H_ONLINE }, { 0x158000, 4, RI_E1E1H_ONLINE },
+	{ 0x15c000, 2, RI_E1HE2_ONLINE }, { 0x15c008, 5, RI_E1H_ONLINE },
+	{ 0x15c020, 27, RI_E2_ONLINE }, { 0x15c090, 13, RI_E2_ONLINE },
+	{ 0x15c0c8, 34, RI_E2_ONLINE }, { 0x161000, 7, RI_ALL_ONLINE },
+	{ 0x16103c, 2, RI_E2_ONLINE }, { 0x161800, 2, RI_ALL_ONLINE },
+	{ 0x164000, 60, RI_ALL_ONLINE }, { 0x164110, 2, RI_E1HE2_ONLINE },
+	{ 0x164118, 15, RI_E2_ONLINE }, { 0x164200, 1, RI_ALL_ONLINE },
 	{ 0x164208, 1, RI_ALL_ONLINE }, { 0x164210, 1, RI_ALL_ONLINE },
 	{ 0x164218, 1, RI_ALL_ONLINE }, { 0x164220, 1, RI_ALL_ONLINE },
 	{ 0x164228, 1, RI_ALL_ONLINE }, { 0x164230, 1, RI_ALL_ONLINE },
@@ -284,169 +273,298 @@ static const struct reg_addr reg_addrs[R
 	{ 0x164258, 1, RI_ALL_ONLINE }, { 0x164260, 1, RI_ALL_ONLINE },
 	{ 0x164270, 2, RI_ALL_ONLINE }, { 0x164280, 2, RI_ALL_ONLINE },
 	{ 0x164800, 2, RI_ALL_ONLINE }, { 0x165000, 2, RI_ALL_ONLINE },
-	{ 0x166000, 164, RI_ALL_ONLINE }, { 0x16629c, 1, RI_ALL_ONLINE },
-	{ 0x1662ac, 1, RI_ALL_ONLINE }, { 0x1662bc, 1, RI_ALL_ONLINE },
+	{ 0x166000, 164, RI_ALL_ONLINE }, { 0x1662cc, 7, RI_E2_ONLINE },
 	{ 0x166400, 49, RI_ALL_ONLINE }, { 0x1664c8, 38, RI_ALL_ONLINE },
-	{ 0x166568, 2, RI_ALL_ONLINE }, { 0x166800, 1, RI_ALL_ONLINE },
-	{ 0x168000, 270, RI_ALL_ONLINE }, { 0x168444, 1, RI_ALL_ONLINE },
-	{ 0x168454, 1, RI_ALL_ONLINE }, { 0x168800, 19, RI_ALL_ONLINE },
-	{ 0x168900, 1, RI_ALL_ONLINE }, { 0x168a00, 128, RI_ALL_ONLINE },
-	{ 0x16a000, 1, RI_ALL_ONLINE }, { 0x16a004, 1535, RI_ALL_OFFLINE },
-	{ 0x16c000, 1, RI_ALL_ONLINE }, { 0x16c004, 1535, RI_ALL_OFFLINE },
-	{ 0x16e000, 16, RI_E1H_ONLINE }, { 0x16e100, 1, RI_E1H_ONLINE },
-	{ 0x16e200, 2, RI_E1H_ONLINE }, { 0x16e400, 183, RI_E1H_ONLINE },
-	{ 0x170000, 93, RI_ALL_ONLINE }, { 0x170180, 1, RI_ALL_ONLINE },
-	{ 0x170190, 1, RI_ALL_ONLINE }, { 0x170200, 4, RI_ALL_ONLINE },
-	{ 0x170214, 1, RI_ALL_ONLINE }, { 0x178000, 1, RI_ALL_ONLINE },
-	{ 0x180000, 61, RI_ALL_ONLINE }, { 0x180100, 1, RI_ALL_ONLINE },
-	{ 0x180110, 1, RI_ALL_ONLINE }, { 0x180120, 1, RI_ALL_ONLINE },
-	{ 0x180130, 1, RI_ALL_ONLINE }, { 0x18013c, 2, RI_E1H_ONLINE },
-	{ 0x180200, 58, RI_ALL_ONLINE }, { 0x180340, 4, RI_ALL_ONLINE },
-	{ 0x180400, 1, RI_ALL_ONLINE }, { 0x180404, 255, RI_ALL_OFFLINE },
+	{ 0x166568, 2, RI_ALL_ONLINE }, { 0x166570, 5, RI_E2_ONLINE },
+	{ 0x166800, 1, RI_ALL_ONLINE }, { 0x168000, 137, RI_ALL_ONLINE },
+	{ 0x168224, 2, RI_E1E1H_ONLINE }, { 0x16822c, 29, RI_ALL_ONLINE },
+	{ 0x1682a0, 12, RI_E1E1H_ONLINE }, { 0x1682d0, 12, RI_ALL_ONLINE },
+	{ 0x168300, 2, RI_E1E1H_ONLINE }, { 0x168308, 68, RI_ALL_ONLINE },
+	{ 0x168418, 2, RI_E1E1H_ONLINE }, { 0x168420, 6, RI_ALL_ONLINE },
+	{ 0x168800, 19, RI_ALL_ONLINE }, { 0x168900, 1, RI_ALL_ONLINE },
+	{ 0x168a00, 128, RI_ALL_ONLINE }, { 0x16a000, 1, RI_ALL_ONLINE },
+	{ 0x16a004, 1535, RI_ALL_OFFLINE }, { 0x16c000, 1, RI_ALL_ONLINE },
+	{ 0x16c004, 1535, RI_ALL_OFFLINE }, { 0x16e000, 16, RI_E1H_ONLINE },
+	{ 0x16e040, 8, RI_E2_ONLINE }, { 0x16e100, 1, RI_E1H_ONLINE },
+	{ 0x16e200, 2, RI_E1H_ONLINE }, { 0x16e400, 161, RI_E1H_ONLINE },
+	{ 0x16e684, 2, RI_E1HE2_ONLINE }, { 0x16e68c, 12, RI_E1H_ONLINE },
+	{ 0x16e6bc, 4, RI_E1HE2_ONLINE }, { 0x16e6cc, 4, RI_E1H_ONLINE },
+	{ 0x16e6e0, 12, RI_E2_ONLINE }, { 0x16e768, 17, RI_E2_ONLINE },
+	{ 0x170000, 24, RI_ALL_ONLINE }, { 0x170060, 4, RI_E1E1H_ONLINE },
+	{ 0x170070, 65, RI_ALL_ONLINE }, { 0x170194, 11, RI_E2_ONLINE },
+	{ 0x1701c4, 1, RI_E2_ONLINE }, { 0x1701cc, 7, RI_E2_ONLINE },
+	{ 0x1701ec, 1, RI_E2_ONLINE }, { 0x1701f4, 1, RI_E2_ONLINE },
+	{ 0x170200, 4, RI_ALL_ONLINE }, { 0x170214, 1, RI_ALL_ONLINE },
+	{ 0x170218, 77, RI_E2_ONLINE }, { 0x170400, 64, RI_E2_ONLINE },
+	{ 0x178000, 1, RI_ALL_ONLINE }, { 0x180000, 61, RI_ALL_ONLINE },
+	{ 0x18013c, 2, RI_E1HE2_ONLINE }, { 0x180200, 58, RI_ALL_ONLINE },
+	{ 0x180340, 4, RI_ALL_ONLINE }, { 0x180380, 1, RI_E2_ONLINE },
+	{ 0x180388, 1, RI_E2_ONLINE }, { 0x180390, 1, RI_E2_ONLINE },
+	{ 0x180398, 1, RI_E2_ONLINE }, { 0x1803a0, 5, RI_E2_ONLINE },
+	{ 0x180400, 1, RI_ALL_ONLINE }, { 0x180404, 255, RI_E1E1H_OFFLINE },
 	{ 0x181000, 4, RI_ALL_ONLINE }, { 0x181010, 1020, RI_ALL_OFFLINE },
-	{ 0x1a0000, 1, RI_ALL_ONLINE }, { 0x1a0004, 1023, RI_ALL_OFFLINE },
-	{ 0x1a1000, 1, RI_ALL_ONLINE }, { 0x1a1004, 4607, RI_ALL_OFFLINE },
-	{ 0x1a5800, 2560, RI_E1H_OFFLINE }, { 0x1a8000, 64, RI_ALL_OFFLINE },
-	{ 0x1a8100, 1984, RI_E1H_OFFLINE }, { 0x1aa000, 1, RI_E1H_ONLINE },
-	{ 0x1aa004, 6655, RI_E1H_OFFLINE }, { 0x1b1800, 128, RI_ALL_OFFLINE },
-	{ 0x1b1c00, 128, RI_ALL_OFFLINE }, { 0x1b2000, 1, RI_ALL_OFFLINE },
-	{ 0x1b2400, 64, RI_E1H_OFFLINE }, { 0x1b8200, 1, RI_ALL_ONLINE },
+	{ 0x1a0000, 1, RI_ALL_ONLINE }, { 0x1a0004, 5631, RI_ALL_OFFLINE },
+	{ 0x1a5800, 2560, RI_E1HE2_OFFLINE }, { 0x1a8000, 1, RI_ALL_ONLINE },
+	{ 0x1a8004, 8191, RI_E1HE2_OFFLINE }, { 0x1b0000, 1, RI_ALL_ONLINE },
+	{ 0x1b0004, 15, RI_E1H_OFFLINE }, { 0x1b0040, 1, RI_E1HE2_ONLINE },
+	{ 0x1b0044, 239, RI_E1H_OFFLINE }, { 0x1b0400, 1, RI_ALL_ONLINE },
+	{ 0x1b0404, 255, RI_E1H_OFFLINE }, { 0x1b0800, 1, RI_ALL_ONLINE },
+	{ 0x1b0840, 1, RI_E1HE2_ONLINE }, { 0x1b0c00, 1, RI_ALL_ONLINE },
+	{ 0x1b1000, 1, RI_ALL_ONLINE }, { 0x1b1040, 1, RI_E1HE2_ONLINE },
+	{ 0x1b1400, 1, RI_ALL_ONLINE }, { 0x1b1440, 1, RI_E1HE2_ONLINE },
+	{ 0x1b1480, 1, RI_E1HE2_ONLINE }, { 0x1b14c0, 1, RI_E1HE2_ONLINE },
+	{ 0x1b1800, 128, RI_ALL_OFFLINE }, { 0x1b1c00, 128, RI_ALL_OFFLINE },
+	{ 0x1b2000, 1, RI_ALL_ONLINE }, { 0x1b2400, 1, RI_E1HE2_ONLINE },
+	{ 0x1b2404, 5631, RI_E2_OFFLINE }, { 0x1b8000, 1, RI_ALL_ONLINE },
+	{ 0x1b8040, 1, RI_ALL_ONLINE }, { 0x1b8080, 1, RI_ALL_ONLINE },
+	{ 0x1b80c0, 1, RI_ALL_ONLINE }, { 0x1b8100, 1, RI_ALL_ONLINE },
+	{ 0x1b8140, 1, RI_ALL_ONLINE }, { 0x1b8180, 1, RI_ALL_ONLINE },
+	{ 0x1b81c0, 1, RI_ALL_ONLINE }, { 0x1b8200, 1, RI_ALL_ONLINE },
 	{ 0x1b8240, 1, RI_ALL_ONLINE }, { 0x1b8280, 1, RI_ALL_ONLINE },
-	{ 0x1b82c0, 1, RI_ALL_ONLINE }, { 0x1b8a00, 1, RI_ALL_ONLINE },
-	{ 0x1b8a80, 1, RI_ALL_ONLINE }, { 0x1c0000, 2, RI_ALL_ONLINE },
-	{ 0x200000, 65, RI_ALL_ONLINE }, { 0x200110, 1, RI_ALL_ONLINE },
-	{ 0x200120, 1, RI_ALL_ONLINE }, { 0x200130, 1, RI_ALL_ONLINE },
-	{ 0x200140, 1, RI_ALL_ONLINE }, { 0x20014c, 2, RI_E1H_ONLINE },
-	{ 0x200200, 58, RI_ALL_ONLINE }, { 0x200340, 4, RI_ALL_ONLINE },
-	{ 0x200400, 1, RI_ALL_ONLINE }, { 0x200404, 255, RI_ALL_OFFLINE },
-	{ 0x202000, 4, RI_ALL_ONLINE }, { 0x202010, 2044, RI_ALL_OFFLINE },
-	{ 0x220000, 1, RI_ALL_ONLINE }, { 0x220004, 1023, RI_ALL_OFFLINE },
-	{ 0x221000, 1, RI_ALL_ONLINE }, { 0x221004, 4607, RI_ALL_OFFLINE },
-	{ 0x225800, 1536, RI_E1H_OFFLINE }, { 0x227000, 1, RI_E1H_ONLINE },
-	{ 0x227004, 1023, RI_E1H_OFFLINE }, { 0x228000, 64, RI_ALL_OFFLINE },
-	{ 0x228100, 8640, RI_E1H_OFFLINE }, { 0x231800, 128, RI_ALL_OFFLINE },
-	{ 0x231c00, 128, RI_ALL_OFFLINE }, { 0x232000, 1, RI_ALL_OFFLINE },
-	{ 0x232400, 64, RI_E1H_OFFLINE }, { 0x238200, 1, RI_ALL_ONLINE },
-	{ 0x238240, 1, RI_ALL_ONLINE }, { 0x238280, 1, RI_ALL_ONLINE },
-	{ 0x2382c0, 1, RI_ALL_ONLINE }, { 0x238a00, 1, RI_ALL_ONLINE },
-	{ 0x238a80, 1, RI_ALL_ONLINE }, { 0x240000, 2, RI_ALL_ONLINE },
-	{ 0x280000, 65, RI_ALL_ONLINE }, { 0x280110, 1, RI_ALL_ONLINE },
-	{ 0x280120, 1, RI_ALL_ONLINE }, { 0x280130, 1, RI_ALL_ONLINE },
-	{ 0x280140, 1, RI_ALL_ONLINE }, { 0x28014c, 2, RI_E1H_ONLINE },
-	{ 0x280200, 58, RI_ALL_ONLINE }, { 0x280340, 4, RI_ALL_ONLINE },
-	{ 0x280400, 1, RI_ALL_ONLINE }, { 0x280404, 255, RI_ALL_OFFLINE },
-	{ 0x282000, 4, RI_ALL_ONLINE }, { 0x282010, 2044, RI_ALL_OFFLINE },
-	{ 0x2a0000, 1, RI_ALL_ONLINE }, { 0x2a0004, 1023, RI_ALL_OFFLINE },
-	{ 0x2a1000, 1, RI_ALL_ONLINE }, { 0x2a1004, 4607, RI_ALL_OFFLINE },
-	{ 0x2a5800, 2560, RI_E1H_OFFLINE }, { 0x2a8000, 64, RI_ALL_OFFLINE },
-	{ 0x2a8100, 960, RI_E1H_OFFLINE }, { 0x2a9000, 1, RI_E1H_ONLINE },
-	{ 0x2a9004, 7679, RI_E1H_OFFLINE }, { 0x2b1800, 128, RI_ALL_OFFLINE },
-	{ 0x2b1c00, 128, RI_ALL_OFFLINE }, { 0x2b2000, 1, RI_ALL_OFFLINE },
-	{ 0x2b2400, 64, RI_E1H_OFFLINE }, { 0x2b8200, 1, RI_ALL_ONLINE },
-	{ 0x2b8240, 1, RI_ALL_ONLINE }, { 0x2b8280, 1, RI_ALL_ONLINE },
-	{ 0x2b82c0, 1, RI_ALL_ONLINE }, { 0x2b8a00, 1, RI_ALL_ONLINE },
-	{ 0x2b8a80, 1, RI_ALL_ONLINE }, { 0x2c0000, 2, RI_ALL_ONLINE },
-	{ 0x300000, 65, RI_ALL_ONLINE }, { 0x300110, 1, RI_ALL_ONLINE },
-	{ 0x300120, 1, RI_ALL_ONLINE }, { 0x300130, 1, RI_ALL_ONLINE },
-	{ 0x300140, 1, RI_ALL_ONLINE }, { 0x30014c, 2, RI_E1H_ONLINE },
+	{ 0x1b82c0, 1, RI_ALL_ONLINE }, { 0x1b8300, 1, RI_ALL_ONLINE },
+	{ 0x1b8340, 1, RI_ALL_ONLINE }, { 0x1b8380, 1, RI_ALL_ONLINE },
+	{ 0x1b83c0, 1, RI_ALL_ONLINE }, { 0x1b8400, 1, RI_ALL_ONLINE },
+	{ 0x1b8440, 1, RI_ALL_ONLINE }, { 0x1b8480, 1, RI_ALL_ONLINE },
+	{ 0x1b84c0, 1, RI_ALL_ONLINE }, { 0x1b8500, 1, RI_ALL_ONLINE },
+	{ 0x1b8540, 1, RI_ALL_ONLINE }, { 0x1b8580, 1, RI_ALL_ONLINE },
+	{ 0x1b85c0, 19, RI_E2_ONLINE }, { 0x1b8800, 1, RI_ALL_ONLINE },
+	{ 0x1b8840, 1, RI_ALL_ONLINE }, { 0x1b8880, 1, RI_ALL_ONLINE },
+	{ 0x1b88c0, 1, RI_ALL_ONLINE }, { 0x1b8900, 1, RI_ALL_ONLINE },
+	{ 0x1b8940, 1, RI_ALL_ONLINE }, { 0x1b8980, 1, RI_ALL_ONLINE },
+	{ 0x1b89c0, 1, RI_ALL_ONLINE }, { 0x1b8a00, 1, RI_ALL_ONLINE },
+	{ 0x1b8a40, 1, RI_ALL_ONLINE }, { 0x1b8a80, 1, RI_ALL_ONLINE },
+	{ 0x1b8ac0, 1, RI_ALL_ONLINE }, { 0x1b8b00, 1, RI_ALL_ONLINE },
+	{ 0x1b8b40, 1, RI_ALL_ONLINE }, { 0x1b8b80, 1, RI_ALL_ONLINE },
+	{ 0x1b8bc0, 1, RI_ALL_ONLINE }, { 0x1b8c00, 1, RI_ALL_ONLINE },
+	{ 0x1b8c40, 1, RI_ALL_ONLINE }, { 0x1b8c80, 1, RI_ALL_ONLINE },
+	{ 0x1b8cc0, 1, RI_ALL_ONLINE }, { 0x1b8cc4, 1, RI_E2_ONLINE },
+	{ 0x1b8d00, 1, RI_ALL_ONLINE }, { 0x1b8d40, 1, RI_ALL_ONLINE },
+	{ 0x1b8d80, 1, RI_ALL_ONLINE }, { 0x1b8dc0, 1, RI_ALL_ONLINE },
+	{ 0x1b8e00, 1, RI_ALL_ONLINE }, { 0x1b8e40, 1, RI_ALL_ONLINE },
+	{ 0x1b8e80, 1, RI_ALL_ONLINE }, { 0x1b8e84, 1, RI_E2_ONLINE },
+	{ 0x1b8ec0, 1, RI_E1HE2_ONLINE }, { 0x1b8f00, 1, RI_E1HE2_ONLINE },
+	{ 0x1b8f40, 1, RI_E1HE2_ONLINE }, { 0x1b8f80, 1, RI_E1HE2_ONLINE },
+	{ 0x1b8fc0, 1, RI_E1HE2_ONLINE }, { 0x1b8fc4, 2, RI_E2_ONLINE },
+	{ 0x1b8fd0, 6, RI_E2_ONLINE }, { 0x1b9000, 1, RI_E2_ONLINE },
+	{ 0x1b9040, 3, RI_E2_ONLINE }, { 0x1b9400, 14, RI_E2_ONLINE },
+	{ 0x1b943c, 19, RI_E2_ONLINE }, { 0x1b9490, 10, RI_E2_ONLINE },
+	{ 0x1c0000, 2, RI_ALL_ONLINE }, { 0x200000, 65, RI_ALL_ONLINE },
+	{ 0x20014c, 2, RI_E1HE2_ONLINE }, { 0x200200, 58, RI_ALL_ONLINE },
+	{ 0x200340, 4, RI_ALL_ONLINE }, { 0x200380, 1, RI_E2_ONLINE },
+	{ 0x200388, 1, RI_E2_ONLINE }, { 0x200390, 1, RI_E2_ONLINE },
+	{ 0x200398, 1, RI_E2_ONLINE }, { 0x2003a0, 1, RI_E2_ONLINE },
+	{ 0x2003a8, 2, RI_E2_ONLINE }, { 0x200400, 1, RI_ALL_ONLINE },
+	{ 0x200404, 255, RI_E1E1H_OFFLINE }, { 0x202000, 4, RI_ALL_ONLINE },
+	{ 0x202010, 2044, RI_ALL_OFFLINE }, { 0x220000, 1, RI_ALL_ONLINE },
+	{ 0x220004, 5631, RI_ALL_OFFLINE }, { 0x225800, 2560, RI_E1HE2_OFFLINE},
+	{ 0x228000, 1, RI_ALL_ONLINE }, { 0x228004, 8191, RI_E1HE2_OFFLINE },
+	{ 0x230000, 1, RI_ALL_ONLINE }, { 0x230004, 15, RI_E1H_OFFLINE },
+	{ 0x230040, 1, RI_E1HE2_ONLINE }, { 0x230044, 239, RI_E1H_OFFLINE },
+	{ 0x230400, 1, RI_ALL_ONLINE }, { 0x230404, 255, RI_E1H_OFFLINE },
+	{ 0x230800, 1, RI_ALL_ONLINE }, { 0x230840, 1, RI_E1HE2_ONLINE },
+	{ 0x230c00, 1, RI_ALL_ONLINE }, { 0x231000, 1, RI_ALL_ONLINE },
+	{ 0x231040, 1, RI_E1HE2_ONLINE }, { 0x231400, 1, RI_ALL_ONLINE },
+	{ 0x231440, 1, RI_E1HE2_ONLINE }, { 0x231480, 1, RI_E1HE2_ONLINE },
+	{ 0x2314c0, 1, RI_E1HE2_ONLINE }, { 0x231800, 128, RI_ALL_OFFLINE },
+	{ 0x231c00, 128, RI_ALL_OFFLINE }, { 0x232000, 1, RI_ALL_ONLINE },
+	{ 0x232400, 1, RI_E1HE2_ONLINE }, { 0x232404, 5631, RI_E2_OFFLINE },
+	{ 0x238000, 1, RI_ALL_ONLINE }, { 0x238040, 1, RI_ALL_ONLINE },
+	{ 0x238080, 1, RI_ALL_ONLINE }, { 0x2380c0, 1, RI_ALL_ONLINE },
+	{ 0x238100, 1, RI_ALL_ONLINE }, { 0x238140, 1, RI_ALL_ONLINE },
+	{ 0x238180, 1, RI_ALL_ONLINE }, { 0x2381c0, 1, RI_ALL_ONLINE },
+	{ 0x238200, 1, RI_ALL_ONLINE }, { 0x238240, 1, RI_ALL_ONLINE },
+	{ 0x238280, 1, RI_ALL_ONLINE }, { 0x2382c0, 1, RI_ALL_ONLINE },
+	{ 0x238300, 1, RI_ALL_ONLINE }, { 0x238340, 1, RI_ALL_ONLINE },
+	{ 0x238380, 1, RI_ALL_ONLINE }, { 0x2383c0, 1, RI_ALL_ONLINE },
+	{ 0x238400, 1, RI_ALL_ONLINE }, { 0x238440, 1, RI_ALL_ONLINE },
+	{ 0x238480, 1, RI_ALL_ONLINE }, { 0x2384c0, 1, RI_ALL_ONLINE },
+	{ 0x238500, 1, RI_ALL_ONLINE }, { 0x238540, 1, RI_ALL_ONLINE },
+	{ 0x238580, 1, RI_ALL_ONLINE }, { 0x2385c0, 19, RI_E2_ONLINE },
+	{ 0x238800, 1, RI_ALL_ONLINE }, { 0x238840, 1, RI_ALL_ONLINE },
+	{ 0x238880, 1, RI_ALL_ONLINE }, { 0x2388c0, 1, RI_ALL_ONLINE },
+	{ 0x238900, 1, RI_ALL_ONLINE }, { 0x238940, 1, RI_ALL_ONLINE },
+	{ 0x238980, 1, RI_ALL_ONLINE }, { 0x2389c0, 1, RI_ALL_ONLINE },
+	{ 0x238a00, 1, RI_ALL_ONLINE }, { 0x238a40, 1, RI_ALL_ONLINE },
+	{ 0x238a80, 1, RI_ALL_ONLINE }, { 0x238ac0, 1, RI_ALL_ONLINE },
+	{ 0x238b00, 1, RI_ALL_ONLINE }, { 0x238b40, 1, RI_ALL_ONLINE },
+	{ 0x238b80, 1, RI_ALL_ONLINE }, { 0x238bc0, 1, RI_ALL_ONLINE },
+	{ 0x238c00, 1, RI_ALL_ONLINE }, { 0x238c40, 1, RI_ALL_ONLINE },
+	{ 0x238c80, 1, RI_ALL_ONLINE }, { 0x238cc0, 1, RI_ALL_ONLINE },
+	{ 0x238cc4, 1, RI_E2_ONLINE }, { 0x238d00, 1, RI_ALL_ONLINE },
+	{ 0x238d40, 1, RI_ALL_ONLINE }, { 0x238d80, 1, RI_ALL_ONLINE },
+	{ 0x238dc0, 1, RI_ALL_ONLINE }, { 0x238e00, 1, RI_ALL_ONLINE },
+	{ 0x238e40, 1, RI_ALL_ONLINE }, { 0x238e80, 1, RI_ALL_ONLINE },
+	{ 0x238e84, 1, RI_E2_ONLINE }, { 0x238ec0, 1, RI_E1HE2_ONLINE },
+	{ 0x238f00, 1, RI_E1HE2_ONLINE }, { 0x238f40, 1, RI_E1HE2_ONLINE },
+	{ 0x238f80, 1, RI_E1HE2_ONLINE }, { 0x238fc0, 1, RI_E1HE2_ONLINE },
+	{ 0x238fc4, 2, RI_E2_ONLINE }, { 0x238fd0, 6, RI_E2_ONLINE },
+	{ 0x239000, 1, RI_E2_ONLINE }, { 0x239040, 3, RI_E2_ONLINE },
+	{ 0x240000, 2, RI_ALL_ONLINE }, { 0x280000, 65, RI_ALL_ONLINE },
+	{ 0x28014c, 2, RI_E1HE2_ONLINE }, { 0x280200, 58, RI_ALL_ONLINE },
+	{ 0x280340, 4, RI_ALL_ONLINE }, { 0x280380, 1, RI_E2_ONLINE },
+	{ 0x280388, 1, RI_E2_ONLINE }, { 0x280390, 1, RI_E2_ONLINE },
+	{ 0x280398, 1, RI_E2_ONLINE }, { 0x2803a0, 1, RI_E2_ONLINE },
+	{ 0x2803a8, 2, RI_E2_ONLINE }, { 0x280400, 1, RI_ALL_ONLINE },
+	{ 0x280404, 255, RI_E1E1H_OFFLINE }, { 0x282000, 4, RI_ALL_ONLINE },
+	{ 0x282010, 2044, RI_ALL_OFFLINE }, { 0x2a0000, 1, RI_ALL_ONLINE },
+	{ 0x2a0004, 5631, RI_ALL_OFFLINE }, { 0x2a5800, 2560, RI_E1HE2_OFFLINE},
+	{ 0x2a8000, 1, RI_ALL_ONLINE }, { 0x2a8004, 8191, RI_E1HE2_OFFLINE },
+	{ 0x2b0000, 1, RI_ALL_ONLINE }, { 0x2b0004, 15, RI_E1H_OFFLINE },
+	{ 0x2b0040, 1, RI_E1HE2_ONLINE }, { 0x2b0044, 239, RI_E1H_OFFLINE },
+	{ 0x2b0400, 1, RI_ALL_ONLINE }, { 0x2b0404, 255, RI_E1H_OFFLINE },
+	{ 0x2b0800, 1, RI_ALL_ONLINE }, { 0x2b0840, 1, RI_E1HE2_ONLINE },
+	{ 0x2b0c00, 1, RI_ALL_ONLINE }, { 0x2b1000, 1, RI_ALL_ONLINE },
+	{ 0x2b1040, 1, RI_E1HE2_ONLINE }, { 0x2b1400, 1, RI_ALL_ONLINE },
+	{ 0x2b1440, 1, RI_E1HE2_ONLINE }, { 0x2b1480, 1, RI_E1HE2_ONLINE },
+	{ 0x2b14c0, 1, RI_E1HE2_ONLINE }, { 0x2b1800, 128, RI_ALL_OFFLINE },
+	{ 0x2b1c00, 128, RI_ALL_OFFLINE }, { 0x2b2000, 1, RI_ALL_ONLINE },
+	{ 0x2b2400, 1, RI_E1HE2_ONLINE }, { 0x2b2404, 5631, RI_E2_OFFLINE },
+	{ 0x2b8000, 1, RI_ALL_ONLINE }, { 0x2b8040, 1, RI_ALL_ONLINE },
+	{ 0x2b8080, 1, RI_ALL_ONLINE }, { 0x2b80c0, 1, RI_ALL_ONLINE },
+	{ 0x2b8100, 1, RI_ALL_ONLINE }, { 0x2b8140, 1, RI_ALL_ONLINE },
+	{ 0x2b8180, 1, RI_ALL_ONLINE }, { 0x2b81c0, 1, RI_ALL_ONLINE },
+	{ 0x2b8200, 1, RI_ALL_ONLINE }, { 0x2b8240, 1, RI_ALL_ONLINE },
+	{ 0x2b8280, 1, RI_ALL_ONLINE }, { 0x2b82c0, 1, RI_ALL_ONLINE },
+	{ 0x2b8300, 1, RI_ALL_ONLINE }, { 0x2b8340, 1, RI_ALL_ONLINE },
+	{ 0x2b8380, 1, RI_ALL_ONLINE }, { 0x2b83c0, 1, RI_ALL_ONLINE },
+	{ 0x2b8400, 1, RI_ALL_ONLINE }, { 0x2b8440, 1, RI_ALL_ONLINE },
+	{ 0x2b8480, 1, RI_ALL_ONLINE }, { 0x2b84c0, 1, RI_ALL_ONLINE },
+	{ 0x2b8500, 1, RI_ALL_ONLINE }, { 0x2b8540, 1, RI_ALL_ONLINE },
+	{ 0x2b8580, 1, RI_ALL_ONLINE }, { 0x2b85c0, 19, RI_E2_ONLINE },
+	{ 0x2b8800, 1, RI_ALL_ONLINE }, { 0x2b8840, 1, RI_ALL_ONLINE },
+	{ 0x2b8880, 1, RI_ALL_ONLINE }, { 0x2b88c0, 1, RI_ALL_ONLINE },
+	{ 0x2b8900, 1, RI_ALL_ONLINE }, { 0x2b8940, 1, RI_ALL_ONLINE },
+	{ 0x2b8980, 1, RI_ALL_ONLINE }, { 0x2b89c0, 1, RI_ALL_ONLINE },
+	{ 0x2b8a00, 1, RI_ALL_ONLINE }, { 0x2b8a40, 1, RI_ALL_ONLINE },
+	{ 0x2b8a80, 1, RI_ALL_ONLINE }, { 0x2b8ac0, 1, RI_ALL_ONLINE },
+	{ 0x2b8b00, 1, RI_ALL_ONLINE }, { 0x2b8b40, 1, RI_ALL_ONLINE },
+	{ 0x2b8b80, 1, RI_ALL_ONLINE }, { 0x2b8bc0, 1, RI_ALL_ONLINE },
+	{ 0x2b8c00, 1, RI_ALL_ONLINE }, { 0x2b8c40, 1, RI_ALL_ONLINE },
+	{ 0x2b8c80, 1, RI_ALL_ONLINE }, { 0x2b8cc0, 1, RI_ALL_ONLINE },
+	{ 0x2b8cc4, 1, RI_E2_ONLINE }, { 0x2b8d00, 1, RI_ALL_ONLINE },
+	{ 0x2b8d40, 1, RI_ALL_ONLINE }, { 0x2b8d80, 1, RI_ALL_ONLINE },
+	{ 0x2b8dc0, 1, RI_ALL_ONLINE }, { 0x2b8e00, 1, RI_ALL_ONLINE },
+	{ 0x2b8e40, 1, RI_ALL_ONLINE }, { 0x2b8e80, 1, RI_ALL_ONLINE },
+	{ 0x2b8e84, 1, RI_E2_ONLINE }, { 0x2b8ec0, 1, RI_E1HE2_ONLINE },
+	{ 0x2b8f00, 1, RI_E1HE2_ONLINE }, { 0x2b8f40, 1, RI_E1HE2_ONLINE },
+	{ 0x2b8f80, 1, RI_E1HE2_ONLINE }, { 0x2b8fc0, 1, RI_E1HE2_ONLINE },
+	{ 0x2b8fc4, 2, RI_E2_ONLINE }, { 0x2b8fd0, 6, RI_E2_ONLINE },
+	{ 0x2b9000, 1, RI_E2_ONLINE }, { 0x2b9040, 3, RI_E2_ONLINE },
+	{ 0x2b9400, 14, RI_E2_ONLINE }, { 0x2b943c, 19, RI_E2_ONLINE },
+	{ 0x2b9490, 10, RI_E2_ONLINE }, { 0x2c0000, 2, RI_ALL_ONLINE },
+	{ 0x300000, 65, RI_ALL_ONLINE }, { 0x30014c, 2, RI_E1HE2_ONLINE },
 	{ 0x300200, 58, RI_ALL_ONLINE }, { 0x300340, 4, RI_ALL_ONLINE },
-	{ 0x300400, 1, RI_ALL_ONLINE }, { 0x300404, 255, RI_ALL_OFFLINE },
+	{ 0x300380, 1, RI_E2_ONLINE }, { 0x300388, 1, RI_E2_ONLINE },
+	{ 0x300390, 1, RI_E2_ONLINE }, { 0x300398, 1, RI_E2_ONLINE },
+	{ 0x3003a0, 1, RI_E2_ONLINE }, { 0x3003a8, 2, RI_E2_ONLINE },
+	{ 0x300400, 1, RI_ALL_ONLINE }, { 0x300404, 255, RI_E1E1H_OFFLINE },
 	{ 0x302000, 4, RI_ALL_ONLINE }, { 0x302010, 2044, RI_ALL_OFFLINE },
-	{ 0x320000, 1, RI_ALL_ONLINE }, { 0x320004, 1023, RI_ALL_OFFLINE },
-	{ 0x321000, 1, RI_ALL_ONLINE }, { 0x321004, 4607, RI_ALL_OFFLINE },
-	{ 0x325800, 2560, RI_E1H_OFFLINE }, { 0x328000, 64, RI_ALL_OFFLINE },
-	{ 0x328100, 536, RI_E1H_OFFLINE }, { 0x328960, 1, RI_E1H_ONLINE },
-	{ 0x328964, 8103, RI_E1H_OFFLINE }, { 0x331800, 128, RI_ALL_OFFLINE },
-	{ 0x331c00, 128, RI_ALL_OFFLINE }, { 0x332000, 1, RI_ALL_OFFLINE },
-	{ 0x332400, 64, RI_E1H_OFFLINE }, { 0x338200, 1, RI_ALL_ONLINE },
+	{ 0x320000, 1, RI_ALL_ONLINE }, { 0x320004, 5631, RI_ALL_OFFLINE },
+	{ 0x325800, 2560, RI_E1HE2_OFFLINE }, { 0x328000, 1, RI_ALL_ONLINE },
+	{ 0x328004, 8191, RI_E1HE2_OFFLINE }, { 0x330000, 1, RI_ALL_ONLINE },
+	{ 0x330004, 15, RI_E1H_OFFLINE }, { 0x330040, 1, RI_E1HE2_ONLINE },
+	{ 0x330044, 239, RI_E1H_OFFLINE }, { 0x330400, 1, RI_ALL_ONLINE },
+	{ 0x330404, 255, RI_E1H_OFFLINE }, { 0x330800, 1, RI_ALL_ONLINE },
+	{ 0x330840, 1, RI_E1HE2_ONLINE }, { 0x330c00, 1, RI_ALL_ONLINE },
+	{ 0x331000, 1, RI_ALL_ONLINE }, { 0x331040, 1, RI_E1HE2_ONLINE },
+	{ 0x331400, 1, RI_ALL_ONLINE }, { 0x331440, 1, RI_E1HE2_ONLINE },
+	{ 0x331480, 1, RI_E1HE2_ONLINE }, { 0x3314c0, 1, RI_E1HE2_ONLINE },
+	{ 0x331800, 128, RI_ALL_OFFLINE }, { 0x331c00, 128, RI_ALL_OFFLINE },
+	{ 0x332000, 1, RI_ALL_ONLINE }, { 0x332400, 1, RI_E1HE2_ONLINE },
+	{ 0x332404, 5631, RI_E2_OFFLINE }, { 0x338000, 1, RI_ALL_ONLINE },
+	{ 0x338040, 1, RI_ALL_ONLINE }, { 0x338080, 1, RI_ALL_ONLINE },
+	{ 0x3380c0, 1, RI_ALL_ONLINE }, { 0x338100, 1, RI_ALL_ONLINE },
+	{ 0x338140, 1, RI_ALL_ONLINE }, { 0x338180, 1, RI_ALL_ONLINE },
+	{ 0x3381c0, 1, RI_ALL_ONLINE }, { 0x338200, 1, RI_ALL_ONLINE },
 	{ 0x338240, 1, RI_ALL_ONLINE }, { 0x338280, 1, RI_ALL_ONLINE },
-	{ 0x3382c0, 1, RI_ALL_ONLINE }, { 0x338a00, 1, RI_ALL_ONLINE },
-	{ 0x338a80, 1, RI_ALL_ONLINE }, { 0x340000, 2, RI_ALL_ONLINE }
+	{ 0x3382c0, 1, RI_ALL_ONLINE }, { 0x338300, 1, RI_ALL_ONLINE },
+	{ 0x338340, 1, RI_ALL_ONLINE }, { 0x338380, 1, RI_ALL_ONLINE },
+	{ 0x3383c0, 1, RI_ALL_ONLINE }, { 0x338400, 1, RI_ALL_ONLINE },
+	{ 0x338440, 1, RI_ALL_ONLINE }, { 0x338480, 1, RI_ALL_ONLINE },
+	{ 0x3384c0, 1, RI_ALL_ONLINE }, { 0x338500, 1, RI_ALL_ONLINE },
+	{ 0x338540, 1, RI_ALL_ONLINE }, { 0x338580, 1, RI_ALL_ONLINE },
+	{ 0x3385c0, 19, RI_E2_ONLINE }, { 0x338800, 1, RI_ALL_ONLINE },
+	{ 0x338840, 1, RI_ALL_ONLINE }, { 0x338880, 1, RI_ALL_ONLINE },
+	{ 0x3388c0, 1, RI_ALL_ONLINE }, { 0x338900, 1, RI_ALL_ONLINE },
+	{ 0x338940, 1, RI_ALL_ONLINE }, { 0x338980, 1, RI_ALL_ONLINE },
+	{ 0x3389c0, 1, RI_ALL_ONLINE }, { 0x338a00, 1, RI_ALL_ONLINE },
+	{ 0x338a40, 1, RI_ALL_ONLINE }, { 0x338a80, 1, RI_ALL_ONLINE },
+	{ 0x338ac0, 1, RI_ALL_ONLINE }, { 0x338b00, 1, RI_ALL_ONLINE },
+	{ 0x338b40, 1, RI_ALL_ONLINE }, { 0x338b80, 1, RI_ALL_ONLINE },
+	{ 0x338bc0, 1, RI_ALL_ONLINE }, { 0x338c00, 1, RI_ALL_ONLINE },
+	{ 0x338c40, 1, RI_ALL_ONLINE }, { 0x338c80, 1, RI_ALL_ONLINE },
+	{ 0x338cc0, 1, RI_ALL_ONLINE }, { 0x338cc4, 1, RI_E2_ONLINE },
+	{ 0x338d00, 1, RI_ALL_ONLINE }, { 0x338d40, 1, RI_ALL_ONLINE },
+	{ 0x338d80, 1, RI_ALL_ONLINE }, { 0x338dc0, 1, RI_ALL_ONLINE },
+	{ 0x338e00, 1, RI_ALL_ONLINE }, { 0x338e40, 1, RI_ALL_ONLINE },
+	{ 0x338e80, 1, RI_ALL_ONLINE }, { 0x338e84, 1, RI_E2_ONLINE },
+	{ 0x338ec0, 1, RI_E1HE2_ONLINE }, { 0x338f00, 1, RI_E1HE2_ONLINE },
+	{ 0x338f40, 1, RI_E1HE2_ONLINE }, { 0x338f80, 1, RI_E1HE2_ONLINE },
+	{ 0x338fc0, 1, RI_E1HE2_ONLINE }, { 0x338fc4, 2, RI_E2_ONLINE },
+	{ 0x338fd0, 6, RI_E2_ONLINE }, { 0x339000, 1, RI_E2_ONLINE },
+	{ 0x339040, 3, RI_E2_ONLINE }, { 0x340000, 2, RI_ALL_ONLINE },
 };
 
-
-#define IDLE_REGS_COUNT			277
+#define IDLE_REGS_COUNT			237
 static const struct reg_addr idle_addrs[IDLE_REGS_COUNT] = {
-	{ 0x2114, 1, RI_ALL_ONLINE }, { 0x2120, 1, RI_ALL_ONLINE },
-	{ 0x212c, 4, RI_ALL_ONLINE }, { 0x2814, 1, RI_ALL_ONLINE },
-	{ 0x281c, 2, RI_ALL_ONLINE }, { 0xa38c, 1, RI_ALL_ONLINE },
+	{ 0x2104, 1, RI_ALL_ONLINE }, { 0x2110, 2, RI_ALL_ONLINE },
+	{ 0x211c, 8, RI_ALL_ONLINE }, { 0x2814, 1, RI_ALL_ONLINE },
+	{ 0x281c, 2, RI_ALL_ONLINE }, { 0x2854, 1, RI_ALL_ONLINE },
+	{ 0x285c, 1, RI_ALL_ONLINE }, { 0x9010, 7, RI_E2_ONLINE },
+	{ 0x9030, 1, RI_E2_ONLINE }, { 0x9068, 16, RI_E2_ONLINE },
+	{ 0x9230, 2, RI_E2_ONLINE }, { 0x9244, 1, RI_E2_ONLINE },
+	{ 0x9298, 1, RI_E2_ONLINE }, { 0x92a8, 1, RI_E2_ONLINE },
+	{ 0xa38c, 1, RI_ALL_ONLINE }, { 0xa3c4, 1, RI_E1HE2_ONLINE },
 	{ 0xa408, 1, RI_ALL_ONLINE }, { 0xa42c, 12, RI_ALL_ONLINE },
-	{ 0xa600, 5, RI_E1H_ONLINE }, { 0xa618, 1, RI_E1H_ONLINE },
-	{ 0xc09c, 1, RI_ALL_ONLINE }, { 0x103b0, 1, RI_ALL_ONLINE },
-	{ 0x103c0, 1, RI_ALL_ONLINE }, { 0x103d0, 1, RI_E1H_ONLINE },
-	{ 0x2021c, 11, RI_ALL_ONLINE }, { 0x202a8, 1, RI_ALL_ONLINE },
-	{ 0x202b8, 1, RI_ALL_ONLINE }, { 0x20404, 1, RI_ALL_ONLINE },
-	{ 0x2040c, 2, RI_ALL_ONLINE }, { 0x2041c, 2, RI_ALL_ONLINE },
-	{ 0x40154, 14, RI_ALL_ONLINE }, { 0x40198, 1, RI_ALL_ONLINE },
-	{ 0x404ac, 1, RI_ALL_ONLINE }, { 0x404bc, 1, RI_ALL_ONLINE },
-	{ 0x42290, 1, RI_ALL_ONLINE }, { 0x422a0, 1, RI_ALL_ONLINE },
-	{ 0x422b0, 1, RI_ALL_ONLINE }, { 0x42548, 1, RI_ALL_ONLINE },
-	{ 0x42550, 1, RI_ALL_ONLINE }, { 0x42558, 1, RI_ALL_ONLINE },
-	{ 0x50160, 8, RI_ALL_ONLINE }, { 0x501d0, 1, RI_ALL_ONLINE },
-	{ 0x501e0, 1, RI_ALL_ONLINE }, { 0x50204, 1, RI_ALL_ONLINE },
-	{ 0x5020c, 2, RI_ALL_ONLINE }, { 0x5021c, 1, RI_ALL_ONLINE },
-	{ 0x60090, 1, RI_ALL_ONLINE }, { 0x6011c, 1, RI_ALL_ONLINE },
-	{ 0x6012c, 1, RI_ALL_ONLINE }, { 0xc101c, 1, RI_ALL_ONLINE },
-	{ 0xc102c, 1, RI_ALL_ONLINE }, { 0xc2290, 1, RI_ALL_ONLINE },
-	{ 0xc22a0, 1, RI_ALL_ONLINE }, { 0xc22b0, 1, RI_ALL_ONLINE },
-	{ 0xc2548, 1, RI_ALL_ONLINE }, { 0xc2550, 1, RI_ALL_ONLINE },
-	{ 0xc2558, 1, RI_ALL_ONLINE }, { 0xc4294, 1, RI_ALL_ONLINE },
-	{ 0xc42a4, 1, RI_ALL_ONLINE }, { 0xc42b4, 1, RI_ALL_ONLINE },
-	{ 0xc4550, 1, RI_ALL_ONLINE }, { 0xc4558, 1, RI_ALL_ONLINE },
-	{ 0xc4560, 1, RI_ALL_ONLINE }, { 0xd016c, 8, RI_ALL_ONLINE },
-	{ 0xd01d8, 1, RI_ALL_ONLINE }, { 0xd01e8, 1, RI_ALL_ONLINE },
-	{ 0xd0204, 1, RI_ALL_ONLINE }, { 0xd020c, 3, RI_ALL_ONLINE },
-	{ 0xe0154, 8, RI_ALL_ONLINE }, { 0xe01c8, 1, RI_ALL_ONLINE },
-	{ 0xe01d8, 1, RI_ALL_ONLINE }, { 0xe0204, 1, RI_ALL_ONLINE },
-	{ 0xe020c, 2, RI_ALL_ONLINE }, { 0xe021c, 2, RI_ALL_ONLINE },
-	{ 0x101014, 1, RI_ALL_ONLINE }, { 0x101030, 1, RI_ALL_ONLINE },
-	{ 0x101040, 1, RI_ALL_ONLINE }, { 0x102058, 1, RI_ALL_ONLINE },
-	{ 0x102080, 16, RI_ALL_ONLINE }, { 0x103004, 2, RI_ALL_ONLINE },
-	{ 0x103068, 1, RI_ALL_ONLINE }, { 0x103078, 1, RI_ALL_ONLINE },
-	{ 0x103088, 1, RI_ALL_ONLINE }, { 0x10309c, 2, RI_E1H_ONLINE },
+	{ 0xa600, 5, RI_E1HE2_ONLINE }, { 0xa618, 1, RI_E1HE2_ONLINE },
+	{ 0xa714, 1, RI_E2_ONLINE }, { 0xa720, 1, RI_E2_ONLINE },
+	{ 0xa750, 1, RI_E2_ONLINE }, { 0xc09c, 1, RI_E1E1H_ONLINE },
+	{ 0x103b0, 1, RI_ALL_ONLINE }, { 0x103c0, 1, RI_ALL_ONLINE },
+	{ 0x103d0, 1, RI_E1H_ONLINE }, { 0x183bc, 1, RI_E2_ONLINE },
+	{ 0x183cc, 1, RI_E2_ONLINE }, { 0x2021c, 11, RI_ALL_ONLINE },
+	{ 0x202a8, 1, RI_ALL_ONLINE }, { 0x202b8, 1, RI_ALL_ONLINE },
+	{ 0x20404, 1, RI_ALL_ONLINE }, { 0x2040c, 2, RI_ALL_ONLINE },
+	{ 0x2041c, 2, RI_ALL_ONLINE }, { 0x40154, 14, RI_ALL_ONLINE },
+	{ 0x40198, 1, RI_ALL_ONLINE }, { 0x404ac, 1, RI_ALL_ONLINE },
+	{ 0x404bc, 1, RI_ALL_ONLINE }, { 0x42290, 1, RI_ALL_ONLINE },
+	{ 0x422a0, 1, RI_ALL_ONLINE }, { 0x422b0, 1, RI_ALL_ONLINE },
+	{ 0x42548, 1, RI_ALL_ONLINE }, { 0x42550, 1, RI_ALL_ONLINE },
+	{ 0x42558, 1, RI_ALL_ONLINE }, { 0x50160, 8, RI_ALL_ONLINE },
+	{ 0x501d0, 1, RI_ALL_ONLINE }, { 0x501e0, 1, RI_ALL_ONLINE },
+	{ 0x50204, 1, RI_ALL_ONLINE }, { 0x5020c, 2, RI_ALL_ONLINE },
+	{ 0x5021c, 1, RI_ALL_ONLINE }, { 0x60090, 1, RI_ALL_ONLINE },
+	{ 0x6011c, 1, RI_ALL_ONLINE }, { 0x6012c, 1, RI_ALL_ONLINE },
+	{ 0xc101c, 1, RI_ALL_ONLINE }, { 0xc102c, 1, RI_ALL_ONLINE },
+	{ 0xc2290, 1, RI_ALL_ONLINE }, { 0xc22a0, 1, RI_ALL_ONLINE },
+	{ 0xc22b0, 1, RI_ALL_ONLINE }, { 0xc2548, 1, RI_ALL_ONLINE },
+	{ 0xc2550, 1, RI_ALL_ONLINE }, { 0xc2558, 1, RI_ALL_ONLINE },
+	{ 0xc4294, 1, RI_ALL_ONLINE }, { 0xc42a4, 1, RI_ALL_ONLINE },
+	{ 0xc42b4, 1, RI_ALL_ONLINE }, { 0xc4550, 1, RI_ALL_ONLINE },
+	{ 0xc4558, 1, RI_ALL_ONLINE }, { 0xc4560, 1, RI_ALL_ONLINE },
+	{ 0xd016c, 8, RI_ALL_ONLINE }, { 0xd01d8, 1, RI_ALL_ONLINE },
+	{ 0xd01e8, 1, RI_ALL_ONLINE }, { 0xd0204, 1, RI_ALL_ONLINE },
+	{ 0xd020c, 3, RI_ALL_ONLINE }, { 0xe0154, 8, RI_ALL_ONLINE },
+	{ 0xe01c8, 1, RI_ALL_ONLINE }, { 0xe01d8, 1, RI_ALL_ONLINE },
+	{ 0xe0204, 1, RI_ALL_ONLINE }, { 0xe020c, 2, RI_ALL_ONLINE },
+	{ 0xe021c, 2, RI_ALL_ONLINE }, { 0x101014, 1, RI_ALL_ONLINE },
+	{ 0x101030, 1, RI_ALL_ONLINE }, { 0x101040, 1, RI_ALL_ONLINE },
+	{ 0x102058, 1, RI_ALL_ONLINE }, { 0x102080, 16, RI_ALL_ONLINE },
+	{ 0x103004, 2, RI_ALL_ONLINE }, { 0x103068, 1, RI_ALL_ONLINE },
+	{ 0x103078, 1, RI_ALL_ONLINE }, { 0x103088, 1, RI_ALL_ONLINE },
+	{ 0x10309c, 2, RI_E1HE2_ONLINE }, { 0x1030b8, 2, RI_E2_ONLINE },
+	{ 0x1030cc, 1, RI_E2_ONLINE }, { 0x1030e0, 1, RI_E2_ONLINE },
 	{ 0x104004, 1, RI_ALL_ONLINE }, { 0x104018, 1, RI_ALL_ONLINE },
 	{ 0x104020, 1, RI_ALL_ONLINE }, { 0x10403c, 1, RI_ALL_ONLINE },
 	{ 0x1040fc, 1, RI_ALL_ONLINE }, { 0x10410c, 1, RI_ALL_ONLINE },
 	{ 0x104400, 64, RI_ALL_ONLINE }, { 0x104800, 64, RI_ALL_ONLINE },
-	{ 0x105000, 3, RI_ALL_ONLINE }, { 0x105010, 3, RI_ALL_ONLINE },
-	{ 0x105020, 3, RI_ALL_ONLINE }, { 0x105030, 3, RI_ALL_ONLINE },
-	{ 0x105040, 3, RI_ALL_ONLINE }, { 0x105050, 3, RI_ALL_ONLINE },
-	{ 0x105060, 3, RI_ALL_ONLINE }, { 0x105070, 3, RI_ALL_ONLINE },
-	{ 0x105080, 3, RI_ALL_ONLINE }, { 0x105090, 3, RI_ALL_ONLINE },
-	{ 0x1050a0, 3, RI_ALL_ONLINE }, { 0x1050b0, 3, RI_ALL_ONLINE },
-	{ 0x1050c0, 3, RI_ALL_ONLINE }, { 0x1050d0, 3, RI_ALL_ONLINE },
-	{ 0x1050e0, 3, RI_ALL_ONLINE }, { 0x1050f0, 3, RI_ALL_ONLINE },
-	{ 0x105100, 3, RI_ALL_ONLINE }, { 0x105110, 3, RI_ALL_ONLINE },
-	{ 0x105120, 3, RI_ALL_ONLINE }, { 0x105130, 3, RI_ALL_ONLINE },
-	{ 0x105140, 3, RI_ALL_ONLINE }, { 0x105150, 3, RI_ALL_ONLINE },
-	{ 0x105160, 3, RI_ALL_ONLINE }, { 0x105170, 3, RI_ALL_ONLINE },
-	{ 0x105180, 3, RI_ALL_ONLINE }, { 0x105190, 3, RI_ALL_ONLINE },
-	{ 0x1051a0, 3, RI_ALL_ONLINE }, { 0x1051b0, 3, RI_ALL_ONLINE },
-	{ 0x1051c0, 3, RI_ALL_ONLINE }, { 0x1051d0, 3, RI_ALL_ONLINE },
-	{ 0x1051e0, 3, RI_ALL_ONLINE }, { 0x1051f0, 3, RI_ALL_ONLINE },
-	{ 0x105200, 3, RI_ALL_ONLINE }, { 0x105210, 3, RI_ALL_ONLINE },
-	{ 0x105220, 3, RI_ALL_ONLINE }, { 0x105230, 3, RI_ALL_ONLINE },
-	{ 0x105240, 3, RI_ALL_ONLINE }, { 0x105250, 3, RI_ALL_ONLINE },
-	{ 0x105260, 3, RI_ALL_ONLINE }, { 0x105270, 3, RI_ALL_ONLINE },
-	{ 0x105280, 3, RI_ALL_ONLINE }, { 0x105290, 3, RI_ALL_ONLINE },
-	{ 0x1052a0, 3, RI_ALL_ONLINE }, { 0x1052b0, 3, RI_ALL_ONLINE },
-	{ 0x1052c0, 3, RI_ALL_ONLINE }, { 0x1052d0, 3, RI_ALL_ONLINE },
-	{ 0x1052e0, 3, RI_ALL_ONLINE }, { 0x1052f0, 3, RI_ALL_ONLINE },
-	{ 0x105300, 3, RI_ALL_ONLINE }, { 0x105310, 3, RI_ALL_ONLINE },
-	{ 0x105320, 3, RI_ALL_ONLINE }, { 0x105330, 3, RI_ALL_ONLINE },
-	{ 0x105340, 3, RI_ALL_ONLINE }, { 0x105350, 3, RI_ALL_ONLINE },
-	{ 0x105360, 3, RI_ALL_ONLINE }, { 0x105370, 3, RI_ALL_ONLINE },
-	{ 0x105380, 3, RI_ALL_ONLINE }, { 0x105390, 3, RI_ALL_ONLINE },
-	{ 0x1053a0, 3, RI_ALL_ONLINE }, { 0x1053b0, 3, RI_ALL_ONLINE },
-	{ 0x1053c0, 3, RI_ALL_ONLINE }, { 0x1053d0, 3, RI_ALL_ONLINE },
-	{ 0x1053e0, 3, RI_ALL_ONLINE }, { 0x1053f0, 3, RI_ALL_ONLINE },
-	{ 0x108094, 1, RI_ALL_ONLINE }, { 0x1201b0, 2, RI_ALL_ONLINE },
-	{ 0x12032c, 1, RI_ALL_ONLINE }, { 0x12036c, 3, RI_ALL_ONLINE },
-	{ 0x120408, 2, RI_ALL_ONLINE }, { 0x120414, 15, RI_ALL_ONLINE },
-	{ 0x120478, 2, RI_ALL_ONLINE }, { 0x12052c, 1, RI_ALL_ONLINE },
-	{ 0x120564, 3, RI_ALL_ONLINE }, { 0x12057c, 1, RI_ALL_ONLINE },
-	{ 0x12058c, 1, RI_ALL_ONLINE }, { 0x120608, 1, RI_E1H_ONLINE },
-	{ 0x120808, 1, RI_E1_ONLINE }, { 0x12080c, 2, RI_ALL_ONLINE },
+	{ 0x105000, 256, RI_ALL_ONLINE }, { 0x108094, 1, RI_E1E1H_ONLINE },
+	{ 0x1201b0, 2, RI_ALL_ONLINE }, { 0x12032c, 1, RI_ALL_ONLINE },
+	{ 0x12036c, 3, RI_ALL_ONLINE }, { 0x120408, 2, RI_ALL_ONLINE },
+	{ 0x120414, 15, RI_ALL_ONLINE }, { 0x120478, 2, RI_ALL_ONLINE },
+	{ 0x12052c, 1, RI_ALL_ONLINE }, { 0x120564, 3, RI_ALL_ONLINE },
+	{ 0x12057c, 1, RI_ALL_ONLINE }, { 0x12058c, 1, RI_ALL_ONLINE },
+	{ 0x120608, 1, RI_E1HE2_ONLINE }, { 0x120738, 1, RI_E2_ONLINE },
+	{ 0x120778, 2, RI_E2_ONLINE }, { 0x120808, 3, RI_ALL_ONLINE },
 	{ 0x120818, 1, RI_ALL_ONLINE }, { 0x120820, 1, RI_ALL_ONLINE },
 	{ 0x120828, 1, RI_ALL_ONLINE }, { 0x120830, 1, RI_ALL_ONLINE },
 	{ 0x120838, 1, RI_ALL_ONLINE }, { 0x120840, 1, RI_ALL_ONLINE },
@@ -462,48 +580,50 @@ static const struct reg_addr idle_addrs[
 	{ 0x1208d8, 1, RI_ALL_ONLINE }, { 0x1208e0, 1, RI_ALL_ONLINE },
 	{ 0x1208e8, 1, RI_ALL_ONLINE }, { 0x1208f0, 1, RI_ALL_ONLINE },
 	{ 0x1208f8, 1, RI_ALL_ONLINE }, { 0x120900, 1, RI_ALL_ONLINE },
-	{ 0x120908, 1, RI_ALL_ONLINE }, { 0x14005c, 2, RI_ALL_ONLINE },
-	{ 0x1400d0, 2, RI_ALL_ONLINE }, { 0x1400e0, 1, RI_ALL_ONLINE },
-	{ 0x1401c8, 1, RI_ALL_ONLINE }, { 0x140200, 6, RI_ALL_ONLINE },
-	{ 0x16101c, 1, RI_ALL_ONLINE }, { 0x16102c, 1, RI_ALL_ONLINE },
-	{ 0x164014, 2, RI_ALL_ONLINE }, { 0x1640f0, 1, RI_ALL_ONLINE },
-	{ 0x166290, 1, RI_ALL_ONLINE }, { 0x1662a0, 1, RI_ALL_ONLINE },
-	{ 0x1662b0, 1, RI_ALL_ONLINE }, { 0x166548, 1, RI_ALL_ONLINE },
-	{ 0x166550, 1, RI_ALL_ONLINE }, { 0x166558, 1, RI_ALL_ONLINE },
-	{ 0x168000, 1, RI_ALL_ONLINE }, { 0x168008, 1, RI_ALL_ONLINE },
-	{ 0x168010, 1, RI_ALL_ONLINE }, { 0x168018, 1, RI_ALL_ONLINE },
-	{ 0x168028, 2, RI_ALL_ONLINE }, { 0x168058, 4, RI_ALL_ONLINE },
-	{ 0x168070, 1, RI_ALL_ONLINE }, { 0x168238, 1, RI_ALL_ONLINE },
-	{ 0x1682d0, 2, RI_ALL_ONLINE }, { 0x1682e0, 1, RI_ALL_ONLINE },
-	{ 0x168300, 67, RI_ALL_ONLINE }, { 0x168410, 2, RI_ALL_ONLINE },
+	{ 0x120908, 1, RI_ALL_ONLINE }, { 0x120940, 5, RI_E2_ONLINE },
+	{ 0x130030, 1, RI_E2_ONLINE }, { 0x13004c, 3, RI_E2_ONLINE },
+	{ 0x130064, 2, RI_E2_ONLINE }, { 0x13009c, 1, RI_E2_ONLINE },
+	{ 0x130130, 1, RI_E2_ONLINE }, { 0x13016c, 1, RI_E2_ONLINE },
+	{ 0x130300, 1, RI_E2_ONLINE }, { 0x130480, 1, RI_E2_ONLINE },
+	{ 0x14005c, 2, RI_ALL_ONLINE }, { 0x1400d0, 2, RI_ALL_ONLINE },
+	{ 0x1400e0, 1, RI_ALL_ONLINE }, { 0x1401c8, 1, RI_ALL_ONLINE },
+	{ 0x140200, 6, RI_ALL_ONLINE }, { 0x16101c, 1, RI_ALL_ONLINE },
+	{ 0x16102c, 1, RI_ALL_ONLINE }, { 0x164014, 2, RI_ALL_ONLINE },
+	{ 0x1640f0, 1, RI_ALL_ONLINE }, { 0x166290, 1, RI_ALL_ONLINE },
+	{ 0x1662a0, 1, RI_ALL_ONLINE }, { 0x1662b0, 1, RI_ALL_ONLINE },
+	{ 0x166548, 1, RI_ALL_ONLINE }, { 0x166550, 1, RI_ALL_ONLINE },
+	{ 0x166558, 1, RI_ALL_ONLINE }, { 0x168000, 1, RI_ALL_ONLINE },
+	{ 0x168008, 1, RI_ALL_ONLINE }, { 0x168010, 1, RI_ALL_ONLINE },
+	{ 0x168018, 1, RI_ALL_ONLINE }, { 0x168028, 2, RI_ALL_ONLINE },
+	{ 0x168058, 4, RI_ALL_ONLINE }, { 0x168070, 1, RI_ALL_ONLINE },
+	{ 0x168238, 1, RI_ALL_ONLINE }, { 0x1682d0, 2, RI_ALL_ONLINE },
+	{ 0x1682e0, 1, RI_ALL_ONLINE }, { 0x168300, 2, RI_E1E1H_ONLINE },
+	{ 0x168308, 65, RI_ALL_ONLINE }, { 0x168410, 2, RI_ALL_ONLINE },
 	{ 0x168438, 1, RI_ALL_ONLINE }, { 0x168448, 1, RI_ALL_ONLINE },
 	{ 0x168a00, 128, RI_ALL_ONLINE }, { 0x16e200, 128, RI_E1H_ONLINE },
-	{ 0x16e404, 2, RI_E1H_ONLINE }, { 0x16e584, 70, RI_E1H_ONLINE },
-	{ 0x1700a4, 1, RI_ALL_ONLINE }, { 0x1700ac, 2, RI_ALL_ONLINE },
-	{ 0x1700c0, 1, RI_ALL_ONLINE }, { 0x170174, 1, RI_ALL_ONLINE },
-	{ 0x170184, 1, RI_ALL_ONLINE }, { 0x1800f4, 1, RI_ALL_ONLINE },
-	{ 0x180104, 1, RI_ALL_ONLINE }, { 0x180114, 1, RI_ALL_ONLINE },
-	{ 0x180124, 1, RI_ALL_ONLINE }, { 0x18026c, 1, RI_ALL_ONLINE },
-	{ 0x1802a0, 1, RI_ALL_ONLINE }, { 0x1a1000, 1, RI_ALL_ONLINE },
-	{ 0x1aa000, 1, RI_E1H_ONLINE }, { 0x1b8000, 1, RI_ALL_ONLINE },
-	{ 0x1b8040, 1, RI_ALL_ONLINE }, { 0x1b8080, 1, RI_ALL_ONLINE },
-	{ 0x1b80c0, 1, RI_ALL_ONLINE }, { 0x200104, 1, RI_ALL_ONLINE },
-	{ 0x200114, 1, RI_ALL_ONLINE }, { 0x200124, 1, RI_ALL_ONLINE },
-	{ 0x200134, 1, RI_ALL_ONLINE }, { 0x20026c, 1, RI_ALL_ONLINE },
-	{ 0x2002a0, 1, RI_ALL_ONLINE }, { 0x221000, 1, RI_ALL_ONLINE },
-	{ 0x227000, 1, RI_E1H_ONLINE }, { 0x238000, 1, RI_ALL_ONLINE },
-	{ 0x238040, 1, RI_ALL_ONLINE }, { 0x238080, 1, RI_ALL_ONLINE },
-	{ 0x2380c0, 1, RI_ALL_ONLINE }, { 0x280104, 1, RI_ALL_ONLINE },
-	{ 0x280114, 1, RI_ALL_ONLINE }, { 0x280124, 1, RI_ALL_ONLINE },
-	{ 0x280134, 1, RI_ALL_ONLINE }, { 0x28026c, 1, RI_ALL_ONLINE },
-	{ 0x2802a0, 1, RI_ALL_ONLINE }, { 0x2a1000, 1, RI_ALL_ONLINE },
-	{ 0x2a9000, 1, RI_E1H_ONLINE }, { 0x2b8000, 1, RI_ALL_ONLINE },
-	{ 0x2b8040, 1, RI_ALL_ONLINE }, { 0x2b8080, 1, RI_ALL_ONLINE },
-	{ 0x2b80c0, 1, RI_ALL_ONLINE }, { 0x300104, 1, RI_ALL_ONLINE },
+	{ 0x16e404, 2, RI_E1H_ONLINE }, { 0x16e584, 64, RI_E1H_ONLINE },
+	{ 0x16e684, 2, RI_E1HE2_ONLINE }, { 0x16e68c, 4, RI_E1H_ONLINE },
+	{ 0x16e6fc, 4, RI_E2_ONLINE }, { 0x1700a4, 1, RI_ALL_ONLINE },
+	{ 0x1700ac, 2, RI_ALL_ONLINE }, { 0x1700c0, 1, RI_ALL_ONLINE },
+	{ 0x170174, 1, RI_ALL_ONLINE }, { 0x170184, 1, RI_ALL_ONLINE },
+	{ 0x1800f4, 1, RI_ALL_ONLINE }, { 0x180104, 1, RI_ALL_ONLINE },
+	{ 0x180114, 1, RI_ALL_ONLINE }, { 0x180124, 1, RI_ALL_ONLINE },
+	{ 0x18026c, 1, RI_ALL_ONLINE }, { 0x1802a0, 1, RI_ALL_ONLINE },
+	{ 0x1b8000, 1, RI_ALL_ONLINE }, { 0x1b8040, 1, RI_ALL_ONLINE },
+	{ 0x1b8080, 1, RI_ALL_ONLINE }, { 0x1b80c0, 1, RI_ALL_ONLINE },
+	{ 0x200104, 1, RI_ALL_ONLINE }, { 0x200114, 1, RI_ALL_ONLINE },
+	{ 0x200124, 1, RI_ALL_ONLINE }, { 0x200134, 1, RI_ALL_ONLINE },
+	{ 0x20026c, 1, RI_ALL_ONLINE }, { 0x2002a0, 1, RI_ALL_ONLINE },
+	{ 0x238000, 1, RI_ALL_ONLINE }, { 0x238040, 1, RI_ALL_ONLINE },
+	{ 0x238080, 1, RI_ALL_ONLINE }, { 0x2380c0, 1, RI_ALL_ONLINE },
+	{ 0x280104, 1, RI_ALL_ONLINE }, { 0x280114, 1, RI_ALL_ONLINE },
+	{ 0x280124, 1, RI_ALL_ONLINE }, { 0x280134, 1, RI_ALL_ONLINE },
+	{ 0x28026c, 1, RI_ALL_ONLINE }, { 0x2802a0, 1, RI_ALL_ONLINE },
+	{ 0x2b8000, 1, RI_ALL_ONLINE }, { 0x2b8040, 1, RI_ALL_ONLINE },
+	{ 0x2b8080, 1, RI_ALL_ONLINE }, { 0x300104, 1, RI_ALL_ONLINE },
 	{ 0x300114, 1, RI_ALL_ONLINE }, { 0x300124, 1, RI_ALL_ONLINE },
 	{ 0x300134, 1, RI_ALL_ONLINE }, { 0x30026c, 1, RI_ALL_ONLINE },
-	{ 0x3002a0, 1, RI_ALL_ONLINE }, { 0x321000, 1, RI_ALL_ONLINE },
-	{ 0x328960, 1, RI_E1H_ONLINE }, { 0x338000, 1, RI_ALL_ONLINE },
+	{ 0x3002a0, 1, RI_ALL_ONLINE }, { 0x338000, 1, RI_ALL_ONLINE },
 	{ 0x338040, 1, RI_ALL_ONLINE }, { 0x338080, 1, RI_ALL_ONLINE },
 	{ 0x3380c0, 1, RI_ALL_ONLINE }
 };
@@ -515,7 +635,6 @@ static const struct wreg_addr wreg_addrs
 	{ 0x1b0c00, 192, 1, read_reg_e1_0, RI_E1_OFFLINE }
 };
 
-
 #define WREGS_COUNT_E1H			1
 static const u32 read_reg_e1h_0[] = { 0x1b1040, 0x1b1000 };
 
@@ -530,22 +649,53 @@ static const struct wreg_addr wreg_addrs
 	{ 0x1b0c00, 128, 2, read_reg_e2_0, RI_E2_OFFLINE }
 };
 
-static const struct dump_sign dump_sign_all = { 0x49aa93ee, 0x40835, 0x22 };
-
+static const struct dump_sign dump_sign_all = { 0x4d18b0a4, 0x60010, 0x3a };
 
 #define TIMER_REGS_COUNT_E1		2
-static const u32 timer_status_regs_e1[TIMER_REGS_COUNT_E1] =
-	{ 0x164014, 0x164018 };
-static const u32 timer_scan_regs_e1[TIMER_REGS_COUNT_E1] =
-	{ 0x1640d0, 0x1640d4 };
 
+static const u32 timer_status_regs_e1[TIMER_REGS_COUNT_E1] = {
+	0x164014, 0x164018 };
+static const u32 timer_scan_regs_e1[TIMER_REGS_COUNT_E1] = {
+	0x1640d0, 0x1640d4 };
 
 #define TIMER_REGS_COUNT_E1H		2
-static const u32 timer_status_regs_e1h[TIMER_REGS_COUNT_E1H] =
-	{ 0x164014, 0x164018 };
-static const u32 timer_scan_regs_e1h[TIMER_REGS_COUNT_E1H] =
-	{ 0x1640d0, 0x1640d4 };
 
+static const u32 timer_status_regs_e1h[TIMER_REGS_COUNT_E1H] = {
+	0x164014, 0x164018 };
+static const u32 timer_scan_regs_e1h[TIMER_REGS_COUNT_E1H] = {
+	0x1640d0, 0x1640d4 };
+
+#define TIMER_REGS_COUNT_E2		2
+
+static const u32 timer_status_regs_e2[TIMER_REGS_COUNT_E2] = {
+	0x164014, 0x164018 };
+static const u32 timer_scan_regs_e2[TIMER_REGS_COUNT_E2] = {
+	0x1640d0, 0x1640d4 };
+
+#define PAGE_MODE_VALUES_E1 0
+
+#define PAGE_READ_REGS_E1 0
+
+#define PAGE_WRITE_REGS_E1 0
+
+static const u32 page_vals_e1[] = { 0 };
+
+static const u32 page_write_regs_e1[] = { 0 };
+
+static const struct reg_addr page_read_regs_e1[] = { { 0x0, 0, RI_E1_ONLINE } };
+
+#define PAGE_MODE_VALUES_E1H 0
+
+#define PAGE_READ_REGS_E1H 0
+
+#define PAGE_WRITE_REGS_E1H 0
+
+static const u32 page_vals_e1h[] = { 0 };
+
+static const u32 page_write_regs_e1h[] = { 0 };
+
+static const struct reg_addr page_read_regs_e1h[] = {
+	{ 0x0, 0, RI_E1H_ONLINE } };
 
 #define PAGE_MODE_VALUES_E2 2
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/bnx2x/bnx2x_ethtool.c linux-libre-2.6.38-gnu1/drivers/net/bnx2x/bnx2x_ethtool.c
--- linux-libre-2.6.37-gnu1/drivers/net/bnx2x/bnx2x_ethtool.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/bnx2x/bnx2x_ethtool.c	2011-03-14 21:20:32.000000000 -0400
@@ -24,6 +24,144 @@
 #include "bnx2x.h"
 #include "bnx2x_cmn.h"
 #include "bnx2x_dump.h"
+#include "bnx2x_init.h"
+
+/* Note: in the format strings below %s is replaced by the queue-name which is
+ * either its index or 'fcoe' for the fcoe queue. Make sure the format string
+ * length does not exceed ETH_GSTRING_LEN - MAX_QUEUE_NAME_LEN + 2
+ */
+#define MAX_QUEUE_NAME_LEN	4
+static const struct {
+	long offset;
+	int size;
+	char string[ETH_GSTRING_LEN];
+} bnx2x_q_stats_arr[] = {
+/* 1 */	{ Q_STATS_OFFSET32(total_bytes_received_hi), 8, "[%s]: rx_bytes" },
+	{ Q_STATS_OFFSET32(error_bytes_received_hi),
+						8, "[%s]: rx_error_bytes" },
+	{ Q_STATS_OFFSET32(total_unicast_packets_received_hi),
+						8, "[%s]: rx_ucast_packets" },
+	{ Q_STATS_OFFSET32(total_multicast_packets_received_hi),
+						8, "[%s]: rx_mcast_packets" },
+	{ Q_STATS_OFFSET32(total_broadcast_packets_received_hi),
+						8, "[%s]: rx_bcast_packets" },
+	{ Q_STATS_OFFSET32(no_buff_discard_hi),	8, "[%s]: rx_discards" },
+	{ Q_STATS_OFFSET32(rx_err_discard_pkt),
+					 4, "[%s]: rx_phy_ip_err_discards"},
+	{ Q_STATS_OFFSET32(rx_skb_alloc_failed),
+					 4, "[%s]: rx_skb_alloc_discard" },
+	{ Q_STATS_OFFSET32(hw_csum_err), 4, "[%s]: rx_csum_offload_errors" },
+
+/* 10 */{ Q_STATS_OFFSET32(total_bytes_transmitted_hi),	8, "[%s]: tx_bytes" },
+	{ Q_STATS_OFFSET32(total_unicast_packets_transmitted_hi),
+						8, "[%s]: tx_ucast_packets" },
+	{ Q_STATS_OFFSET32(total_multicast_packets_transmitted_hi),
+						8, "[%s]: tx_mcast_packets" },
+	{ Q_STATS_OFFSET32(total_broadcast_packets_transmitted_hi),
+						8, "[%s]: tx_bcast_packets" }
+};
+
+#define BNX2X_NUM_Q_STATS ARRAY_SIZE(bnx2x_q_stats_arr)
+
+static const struct {
+	long offset;
+	int size;
+	u32 flags;
+#define STATS_FLAGS_PORT		1
+#define STATS_FLAGS_FUNC		2
+#define STATS_FLAGS_BOTH		(STATS_FLAGS_FUNC | STATS_FLAGS_PORT)
+	char string[ETH_GSTRING_LEN];
+} bnx2x_stats_arr[] = {
+/* 1 */	{ STATS_OFFSET32(total_bytes_received_hi),
+				8, STATS_FLAGS_BOTH, "rx_bytes" },
+	{ STATS_OFFSET32(error_bytes_received_hi),
+				8, STATS_FLAGS_BOTH, "rx_error_bytes" },
+	{ STATS_OFFSET32(total_unicast_packets_received_hi),
+				8, STATS_FLAGS_BOTH, "rx_ucast_packets" },
+	{ STATS_OFFSET32(total_multicast_packets_received_hi),
+				8, STATS_FLAGS_BOTH, "rx_mcast_packets" },
+	{ STATS_OFFSET32(total_broadcast_packets_received_hi),
+				8, STATS_FLAGS_BOTH, "rx_bcast_packets" },
+	{ STATS_OFFSET32(rx_stat_dot3statsfcserrors_hi),
+				8, STATS_FLAGS_PORT, "rx_crc_errors" },
+	{ STATS_OFFSET32(rx_stat_dot3statsalignmenterrors_hi),
+				8, STATS_FLAGS_PORT, "rx_align_errors" },
+	{ STATS_OFFSET32(rx_stat_etherstatsundersizepkts_hi),
+				8, STATS_FLAGS_PORT, "rx_undersize_packets" },
+	{ STATS_OFFSET32(etherstatsoverrsizepkts_hi),
+				8, STATS_FLAGS_PORT, "rx_oversize_packets" },
+/* 10 */{ STATS_OFFSET32(rx_stat_etherstatsfragments_hi),
+				8, STATS_FLAGS_PORT, "rx_fragments" },
+	{ STATS_OFFSET32(rx_stat_etherstatsjabbers_hi),
+				8, STATS_FLAGS_PORT, "rx_jabbers" },
+	{ STATS_OFFSET32(no_buff_discard_hi),
+				8, STATS_FLAGS_BOTH, "rx_discards" },
+	{ STATS_OFFSET32(mac_filter_discard),
+				4, STATS_FLAGS_PORT, "rx_filtered_packets" },
+	{ STATS_OFFSET32(xxoverflow_discard),
+				4, STATS_FLAGS_PORT, "rx_fw_discards" },
+	{ STATS_OFFSET32(brb_drop_hi),
+				8, STATS_FLAGS_PORT, "rx_brb_discard" },
+	{ STATS_OFFSET32(brb_truncate_hi),
+				8, STATS_FLAGS_PORT, "rx_brb_truncate" },
+	{ STATS_OFFSET32(pause_frames_received_hi),
+				8, STATS_FLAGS_PORT, "rx_pause_frames" },
+	{ STATS_OFFSET32(rx_stat_maccontrolframesreceived_hi),
+				8, STATS_FLAGS_PORT, "rx_mac_ctrl_frames" },
+	{ STATS_OFFSET32(nig_timer_max),
+			4, STATS_FLAGS_PORT, "rx_constant_pause_events" },
+/* 20 */{ STATS_OFFSET32(rx_err_discard_pkt),
+				4, STATS_FLAGS_BOTH, "rx_phy_ip_err_discards"},
+	{ STATS_OFFSET32(rx_skb_alloc_failed),
+				4, STATS_FLAGS_BOTH, "rx_skb_alloc_discard" },
+	{ STATS_OFFSET32(hw_csum_err),
+				4, STATS_FLAGS_BOTH, "rx_csum_offload_errors" },
+
+	{ STATS_OFFSET32(total_bytes_transmitted_hi),
+				8, STATS_FLAGS_BOTH, "tx_bytes" },
+	{ STATS_OFFSET32(tx_stat_ifhcoutbadoctets_hi),
+				8, STATS_FLAGS_PORT, "tx_error_bytes" },
+	{ STATS_OFFSET32(total_unicast_packets_transmitted_hi),
+				8, STATS_FLAGS_BOTH, "tx_ucast_packets" },
+	{ STATS_OFFSET32(total_multicast_packets_transmitted_hi),
+				8, STATS_FLAGS_BOTH, "tx_mcast_packets" },
+	{ STATS_OFFSET32(total_broadcast_packets_transmitted_hi),
+				8, STATS_FLAGS_BOTH, "tx_bcast_packets" },
+	{ STATS_OFFSET32(tx_stat_dot3statsinternalmactransmiterrors_hi),
+				8, STATS_FLAGS_PORT, "tx_mac_errors" },
+	{ STATS_OFFSET32(rx_stat_dot3statscarriersenseerrors_hi),
+				8, STATS_FLAGS_PORT, "tx_carrier_errors" },
+/* 30 */{ STATS_OFFSET32(tx_stat_dot3statssinglecollisionframes_hi),
+				8, STATS_FLAGS_PORT, "tx_single_collisions" },
+	{ STATS_OFFSET32(tx_stat_dot3statsmultiplecollisionframes_hi),
+				8, STATS_FLAGS_PORT, "tx_multi_collisions" },
+	{ STATS_OFFSET32(tx_stat_dot3statsdeferredtransmissions_hi),
+				8, STATS_FLAGS_PORT, "tx_deferred" },
+	{ STATS_OFFSET32(tx_stat_dot3statsexcessivecollisions_hi),
+				8, STATS_FLAGS_PORT, "tx_excess_collisions" },
+	{ STATS_OFFSET32(tx_stat_dot3statslatecollisions_hi),
+				8, STATS_FLAGS_PORT, "tx_late_collisions" },
+	{ STATS_OFFSET32(tx_stat_etherstatscollisions_hi),
+				8, STATS_FLAGS_PORT, "tx_total_collisions" },
+	{ STATS_OFFSET32(tx_stat_etherstatspkts64octets_hi),
+				8, STATS_FLAGS_PORT, "tx_64_byte_packets" },
+	{ STATS_OFFSET32(tx_stat_etherstatspkts65octetsto127octets_hi),
+			8, STATS_FLAGS_PORT, "tx_65_to_127_byte_packets" },
+	{ STATS_OFFSET32(tx_stat_etherstatspkts128octetsto255octets_hi),
+			8, STATS_FLAGS_PORT, "tx_128_to_255_byte_packets" },
+	{ STATS_OFFSET32(tx_stat_etherstatspkts256octetsto511octets_hi),
+			8, STATS_FLAGS_PORT, "tx_256_to_511_byte_packets" },
+/* 40 */{ STATS_OFFSET32(tx_stat_etherstatspkts512octetsto1023octets_hi),
+			8, STATS_FLAGS_PORT, "tx_512_to_1023_byte_packets" },
+	{ STATS_OFFSET32(etherstatspkts1024octetsto1522octets_hi),
+			8, STATS_FLAGS_PORT, "tx_1024_to_1522_byte_packets" },
+	{ STATS_OFFSET32(etherstatspktsover1522octets_hi),
+			8, STATS_FLAGS_PORT, "tx_1523_to_9022_byte_packets" },
+	{ STATS_OFFSET32(pause_frames_sent_hi),
+				8, STATS_FLAGS_PORT, "tx_pause_frames" }
+};
+
+#define BNX2X_NUM_STATS		ARRAY_SIZE(bnx2x_stats_arr)
 
 static int bnx2x_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 {
@@ -45,14 +183,9 @@ static int bnx2x_get_settings(struct net
 		cmd->speed = bp->link_params.req_line_speed[cfg_idx];
 		cmd->duplex = bp->link_params.req_duplex[cfg_idx];
 	}
-	if (IS_MF(bp)) {
-		u16 vn_max_rate = ((bp->mf_config[BP_VN(bp)] &
-			FUNC_MF_CFG_MAX_BW_MASK) >> FUNC_MF_CFG_MAX_BW_SHIFT) *
-			100;
 
-		if (vn_max_rate < cmd->speed)
-			cmd->speed = vn_max_rate;
-	}
+	if (IS_MF(bp))
+		cmd->speed = bnx2x_get_mf_speed(bp);
 
 	if (bp->port.supported[cfg_idx] & SUPPORTED_TP)
 		cmd->port = PORT_TP;
@@ -87,18 +220,56 @@ static int bnx2x_set_settings(struct net
 {
 	struct bnx2x *bp = netdev_priv(dev);
 	u32 advertising, cfg_idx, old_multi_phy_config, new_multi_phy_config;
+	u32 speed;
 
-	if (IS_MF(bp))
+	if (IS_MF_SD(bp))
 		return 0;
 
 	DP(NETIF_MSG_LINK, "ethtool_cmd: cmd %d\n"
-	   DP_LEVEL "  supported 0x%x  advertising 0x%x  speed %d\n"
-	   DP_LEVEL "  duplex %d  port %d  phy_address %d  transceiver %d\n"
-	   DP_LEVEL "  autoneg %d  maxtxpkt %d  maxrxpkt %d\n",
+	   "  supported 0x%x  advertising 0x%x  speed %d speed_hi %d\n"
+	   "  duplex %d  port %d  phy_address %d  transceiver %d\n"
+	   "  autoneg %d  maxtxpkt %d  maxrxpkt %d\n",
 	   cmd->cmd, cmd->supported, cmd->advertising, cmd->speed,
+	   cmd->speed_hi,
 	   cmd->duplex, cmd->port, cmd->phy_address, cmd->transceiver,
 	   cmd->autoneg, cmd->maxtxpkt, cmd->maxrxpkt);
 
+	speed = cmd->speed;
+	speed |= (cmd->speed_hi << 16);
+
+	if (IS_MF_SI(bp)) {
+		u32 part;
+		u32 line_speed = bp->link_vars.line_speed;
+
+		/* use 10G if no link detected */
+		if (!line_speed)
+			line_speed = 10000;
+
+		if (bp->common.bc_ver < REQ_BC_VER_4_SET_MF_BW) {
+			BNX2X_DEV_INFO("To set speed BC %X or higher "
+				       "is required, please upgrade BC\n",
+				       REQ_BC_VER_4_SET_MF_BW);
+			return -EINVAL;
+		}
+
+		part = (speed * 100) / line_speed;
+
+		if (line_speed < speed || !part) {
+			BNX2X_DEV_INFO("Speed setting should be in a range "
+				       "from 1%% to 100%% "
+				       "of actual line speed\n");
+			return -EINVAL;
+		}
+
+		if (bp->state != BNX2X_STATE_OPEN)
+			/* store value for following "load" */
+			bp->pending_max = part;
+		else
+			bnx2x_update_max_mf_config(bp, part);
+
+		return 0;
+	}
+
 	cfg_idx = bnx2x_get_link_cfg_idx(bp);
 	old_multi_phy_config = bp->link_params.multi_phy_config;
 	switch (cmd->port) {
@@ -168,8 +339,6 @@ static int bnx2x_set_settings(struct net
 
 	} else { /* forced speed */
 		/* advertise the requested speed and duplex if supported */
-		u32 speed = cmd->speed;
-		speed |= (cmd->speed_hi << 16);
 		switch (speed) {
 		case SPEED_10:
 			if (cmd->duplex == DUPLEX_FULL) {
@@ -303,7 +472,7 @@ static int bnx2x_get_regs_len(struct net
 {
 	struct bnx2x *bp = netdev_priv(dev);
 	int regdump_len = 0;
-	int i;
+	int i, j, k;
 
 	if (CHIP_IS_E1(bp)) {
 		for (i = 0; i < REGS_COUNT; i++)
@@ -333,6 +502,15 @@ static int bnx2x_get_regs_len(struct net
 			if (IS_E2_ONLINE(wreg_addrs_e2[i].info))
 				regdump_len += wreg_addrs_e2[i].size *
 					(1 + wreg_addrs_e2[i].read_regs_count);
+
+		for (i = 0; i < PAGE_MODE_VALUES_E2; i++)
+			for (j = 0; j < PAGE_WRITE_REGS_E2; j++) {
+				for (k = 0; k < PAGE_READ_REGS_E2; k++)
+					if (IS_E2_ONLINE(page_read_regs_e2[k].
+							 info))
+						regdump_len +=
+						page_read_regs_e2[k].size;
+			}
 	}
 	regdump_len *= 4;
 	regdump_len += sizeof(struct dump_hdr);
@@ -370,6 +548,12 @@ static void bnx2x_get_regs(struct net_de
 	if (!netif_running(bp->dev))
 		return;
 
+	/* Disable parity attentions as long as following dump may
+	 * cause false alarms by reading never written registers. We
+	 * will re-enable parity attentions right after the dump.
+	 */
+	bnx2x_disable_blocks_parity(bp);
+
 	dump_hdr.hdr_size = (sizeof(struct dump_hdr) / 4) - 1;
 	dump_hdr.dump_sign = dump_sign_all;
 	dump_hdr.xstorm_waitp = REG_RD(bp, XSTORM_WAITP_ADDR);
@@ -411,6 +595,10 @@ static void bnx2x_get_regs(struct net_de
 
 		bnx2x_read_pages_regs_e2(bp, p);
 	}
+	/* Re-enable parity attentions */
+	bnx2x_clear_blocks_parity(bp);
+	if (CHIP_PARITY_ENABLED(bp))
+		bnx2x_enable_blocks_parity(bp);
 }
 
 #define PHY_FW_VER_LEN			20
@@ -1286,7 +1474,7 @@ static int bnx2x_test_registers(struct b
 
 			save_val = REG_RD(bp, offset);
 
-			REG_WR(bp, offset, (wr_val & mask));
+			REG_WR(bp, offset, wr_val & mask);
 
 			val = REG_RD(bp, offset);
 
@@ -1499,8 +1687,15 @@ static int bnx2x_run_loopback(struct bnx
 	 * updates that have been performed while interrupts were
 	 * disabled.
 	 */
-	if (bp->common.int_block == INT_BLOCK_IGU)
+	if (bp->common.int_block == INT_BLOCK_IGU) {
+		/* Disable local BHes to prevent a dead-lock situation between
+		 * sch_direct_xmit() and bnx2x_run_loopback() (calling
+		 * bnx2x_tx_int()), as both are taking netif_tx_lock().
+		 */
+		local_bh_disable();
 		bnx2x_tx_int(fp_tx);
+		local_bh_enable();
+	}
 
 	rx_idx = le16_to_cpu(*fp_rx->rx_cons_sb);
 	if (rx_idx != rx_start_idx + num_pkts)
@@ -1585,9 +1780,7 @@ static int bnx2x_test_nvram(struct bnx2x
 		{ 0x100, 0x350 }, /* manuf_info */
 		{ 0x450,  0xf0 }, /* feature_info */
 		{ 0x640,  0x64 }, /* upgrade_key_info */
-		{ 0x6a4,  0x64 },
 		{ 0x708,  0x70 }, /* manuf_key_info */
-		{ 0x778,  0x70 },
 		{     0,     0 }
 	};
 	__be32 buf[0x350 / 4];
@@ -1650,7 +1843,7 @@ static int bnx2x_test_intr(struct bnx2x
 	config->hdr.client_id = bp->fp->cl_id;
 	config->hdr.reserved1 = 0;
 
-	bp->set_mac_pending++;
+	bp->set_mac_pending = 1;
 	smp_wmb();
 	rc = bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_SET_MAC, 0,
 			   U64_HI(bnx2x_sp_mapping(bp, mac_config)),
@@ -1737,145 +1930,17 @@ static void bnx2x_self_test(struct net_d
 		buf[4] = 1;
 		etest->flags |= ETH_TEST_FL_FAILED;
 	}
-	if (bp->port.pmf)
-		if (bnx2x_link_test(bp, is_serdes) != 0) {
-			buf[5] = 1;
-			etest->flags |= ETH_TEST_FL_FAILED;
-		}
+
+	if (bnx2x_link_test(bp, is_serdes) != 0) {
+		buf[5] = 1;
+		etest->flags |= ETH_TEST_FL_FAILED;
+	}
 
 #ifdef BNX2X_EXTRA_DEBUG
 	bnx2x_panic_dump(bp);
 #endif
 }
 
-static const struct {
-	long offset;
-	int size;
-	u8 string[ETH_GSTRING_LEN];
-} bnx2x_q_stats_arr[BNX2X_NUM_Q_STATS] = {
-/* 1 */	{ Q_STATS_OFFSET32(total_bytes_received_hi), 8, "[%d]: rx_bytes" },
-	{ Q_STATS_OFFSET32(error_bytes_received_hi),
-						8, "[%d]: rx_error_bytes" },
-	{ Q_STATS_OFFSET32(total_unicast_packets_received_hi),
-						8, "[%d]: rx_ucast_packets" },
-	{ Q_STATS_OFFSET32(total_multicast_packets_received_hi),
-						8, "[%d]: rx_mcast_packets" },
-	{ Q_STATS_OFFSET32(total_broadcast_packets_received_hi),
-						8, "[%d]: rx_bcast_packets" },
-	{ Q_STATS_OFFSET32(no_buff_discard_hi),	8, "[%d]: rx_discards" },
-	{ Q_STATS_OFFSET32(rx_err_discard_pkt),
-					 4, "[%d]: rx_phy_ip_err_discards"},
-	{ Q_STATS_OFFSET32(rx_skb_alloc_failed),
-					 4, "[%d]: rx_skb_alloc_discard" },
-	{ Q_STATS_OFFSET32(hw_csum_err), 4, "[%d]: rx_csum_offload_errors" },
-
-/* 10 */{ Q_STATS_OFFSET32(total_bytes_transmitted_hi),	8, "[%d]: tx_bytes" },
-	{ Q_STATS_OFFSET32(total_unicast_packets_transmitted_hi),
-						8, "[%d]: tx_ucast_packets" },
-	{ Q_STATS_OFFSET32(total_multicast_packets_transmitted_hi),
-						8, "[%d]: tx_mcast_packets" },
-	{ Q_STATS_OFFSET32(total_broadcast_packets_transmitted_hi),
-						8, "[%d]: tx_bcast_packets" }
-};
-
-static const struct {
-	long offset;
-	int size;
-	u32 flags;
-#define STATS_FLAGS_PORT		1
-#define STATS_FLAGS_FUNC		2
-#define STATS_FLAGS_BOTH		(STATS_FLAGS_FUNC | STATS_FLAGS_PORT)
-	u8 string[ETH_GSTRING_LEN];
-} bnx2x_stats_arr[BNX2X_NUM_STATS] = {
-/* 1 */	{ STATS_OFFSET32(total_bytes_received_hi),
-				8, STATS_FLAGS_BOTH, "rx_bytes" },
-	{ STATS_OFFSET32(error_bytes_received_hi),
-				8, STATS_FLAGS_BOTH, "rx_error_bytes" },
-	{ STATS_OFFSET32(total_unicast_packets_received_hi),
-				8, STATS_FLAGS_BOTH, "rx_ucast_packets" },
-	{ STATS_OFFSET32(total_multicast_packets_received_hi),
-				8, STATS_FLAGS_BOTH, "rx_mcast_packets" },
-	{ STATS_OFFSET32(total_broadcast_packets_received_hi),
-				8, STATS_FLAGS_BOTH, "rx_bcast_packets" },
-	{ STATS_OFFSET32(rx_stat_dot3statsfcserrors_hi),
-				8, STATS_FLAGS_PORT, "rx_crc_errors" },
-	{ STATS_OFFSET32(rx_stat_dot3statsalignmenterrors_hi),
-				8, STATS_FLAGS_PORT, "rx_align_errors" },
-	{ STATS_OFFSET32(rx_stat_etherstatsundersizepkts_hi),
-				8, STATS_FLAGS_PORT, "rx_undersize_packets" },
-	{ STATS_OFFSET32(etherstatsoverrsizepkts_hi),
-				8, STATS_FLAGS_PORT, "rx_oversize_packets" },
-/* 10 */{ STATS_OFFSET32(rx_stat_etherstatsfragments_hi),
-				8, STATS_FLAGS_PORT, "rx_fragments" },
-	{ STATS_OFFSET32(rx_stat_etherstatsjabbers_hi),
-				8, STATS_FLAGS_PORT, "rx_jabbers" },
-	{ STATS_OFFSET32(no_buff_discard_hi),
-				8, STATS_FLAGS_BOTH, "rx_discards" },
-	{ STATS_OFFSET32(mac_filter_discard),
-				4, STATS_FLAGS_PORT, "rx_filtered_packets" },
-	{ STATS_OFFSET32(xxoverflow_discard),
-				4, STATS_FLAGS_PORT, "rx_fw_discards" },
-	{ STATS_OFFSET32(brb_drop_hi),
-				8, STATS_FLAGS_PORT, "rx_brb_discard" },
-	{ STATS_OFFSET32(brb_truncate_hi),
-				8, STATS_FLAGS_PORT, "rx_brb_truncate" },
-	{ STATS_OFFSET32(pause_frames_received_hi),
-				8, STATS_FLAGS_PORT, "rx_pause_frames" },
-	{ STATS_OFFSET32(rx_stat_maccontrolframesreceived_hi),
-				8, STATS_FLAGS_PORT, "rx_mac_ctrl_frames" },
-	{ STATS_OFFSET32(nig_timer_max),
-			4, STATS_FLAGS_PORT, "rx_constant_pause_events" },
-/* 20 */{ STATS_OFFSET32(rx_err_discard_pkt),
-				4, STATS_FLAGS_BOTH, "rx_phy_ip_err_discards"},
-	{ STATS_OFFSET32(rx_skb_alloc_failed),
-				4, STATS_FLAGS_BOTH, "rx_skb_alloc_discard" },
-	{ STATS_OFFSET32(hw_csum_err),
-				4, STATS_FLAGS_BOTH, "rx_csum_offload_errors" },
-
-	{ STATS_OFFSET32(total_bytes_transmitted_hi),
-				8, STATS_FLAGS_BOTH, "tx_bytes" },
-	{ STATS_OFFSET32(tx_stat_ifhcoutbadoctets_hi),
-				8, STATS_FLAGS_PORT, "tx_error_bytes" },
-	{ STATS_OFFSET32(total_unicast_packets_transmitted_hi),
-				8, STATS_FLAGS_BOTH, "tx_ucast_packets" },
-	{ STATS_OFFSET32(total_multicast_packets_transmitted_hi),
-				8, STATS_FLAGS_BOTH, "tx_mcast_packets" },
-	{ STATS_OFFSET32(total_broadcast_packets_transmitted_hi),
-				8, STATS_FLAGS_BOTH, "tx_bcast_packets" },
-	{ STATS_OFFSET32(tx_stat_dot3statsinternalmactransmiterrors_hi),
-				8, STATS_FLAGS_PORT, "tx_mac_errors" },
-	{ STATS_OFFSET32(rx_stat_dot3statscarriersenseerrors_hi),
-				8, STATS_FLAGS_PORT, "tx_carrier_errors" },
-/* 30 */{ STATS_OFFSET32(tx_stat_dot3statssinglecollisionframes_hi),
-				8, STATS_FLAGS_PORT, "tx_single_collisions" },
-	{ STATS_OFFSET32(tx_stat_dot3statsmultiplecollisionframes_hi),
-				8, STATS_FLAGS_PORT, "tx_multi_collisions" },
-	{ STATS_OFFSET32(tx_stat_dot3statsdeferredtransmissions_hi),
-				8, STATS_FLAGS_PORT, "tx_deferred" },
-	{ STATS_OFFSET32(tx_stat_dot3statsexcessivecollisions_hi),
-				8, STATS_FLAGS_PORT, "tx_excess_collisions" },
-	{ STATS_OFFSET32(tx_stat_dot3statslatecollisions_hi),
-				8, STATS_FLAGS_PORT, "tx_late_collisions" },
-	{ STATS_OFFSET32(tx_stat_etherstatscollisions_hi),
-				8, STATS_FLAGS_PORT, "tx_total_collisions" },
-	{ STATS_OFFSET32(tx_stat_etherstatspkts64octets_hi),
-				8, STATS_FLAGS_PORT, "tx_64_byte_packets" },
-	{ STATS_OFFSET32(tx_stat_etherstatspkts65octetsto127octets_hi),
-			8, STATS_FLAGS_PORT, "tx_65_to_127_byte_packets" },
-	{ STATS_OFFSET32(tx_stat_etherstatspkts128octetsto255octets_hi),
-			8, STATS_FLAGS_PORT, "tx_128_to_255_byte_packets" },
-	{ STATS_OFFSET32(tx_stat_etherstatspkts256octetsto511octets_hi),
-			8, STATS_FLAGS_PORT, "tx_256_to_511_byte_packets" },
-/* 40 */{ STATS_OFFSET32(tx_stat_etherstatspkts512octetsto1023octets_hi),
-			8, STATS_FLAGS_PORT, "tx_512_to_1023_byte_packets" },
-	{ STATS_OFFSET32(etherstatspkts1024octetsto1522octets_hi),
-			8, STATS_FLAGS_PORT, "tx_1024_to_1522_byte_packets" },
-	{ STATS_OFFSET32(etherstatspktsover1522octets_hi),
-			8, STATS_FLAGS_PORT, "tx_1523_to_9022_byte_packets" },
-	{ STATS_OFFSET32(pause_frames_sent_hi),
-				8, STATS_FLAGS_PORT, "tx_pause_frames" }
-};
-
 #define IS_PORT_STAT(i) \
 	((bnx2x_stats_arr[i].flags & STATS_FLAGS_BOTH) == STATS_FLAGS_PORT)
 #define IS_FUNC_STAT(i)		(bnx2x_stats_arr[i].flags & STATS_FLAGS_FUNC)
@@ -1890,7 +1955,8 @@ static int bnx2x_get_sset_count(struct n
 	switch (stringset) {
 	case ETH_SS_STATS:
 		if (is_multi(bp)) {
-			num_stats = BNX2X_NUM_Q_STATS * bp->num_queues;
+			num_stats = BNX2X_NUM_STAT_QUEUES(bp) *
+				BNX2X_NUM_Q_STATS;
 			if (!IS_MF_MODE_STAT(bp))
 				num_stats += BNX2X_NUM_STATS;
 		} else {
@@ -1916,15 +1982,25 @@ static void bnx2x_get_strings(struct net
 {
 	struct bnx2x *bp = netdev_priv(dev);
 	int i, j, k;
+	char queue_name[MAX_QUEUE_NAME_LEN+1];
 
 	switch (stringset) {
 	case ETH_SS_STATS:
 		if (is_multi(bp)) {
 			k = 0;
-			for_each_queue(bp, i) {
+			for_each_napi_queue(bp, i) {
+				memset(queue_name, 0, sizeof(queue_name));
+
+				if (IS_FCOE_IDX(i))
+					sprintf(queue_name, "fcoe");
+				else
+					sprintf(queue_name, "%d", i);
+
 				for (j = 0; j < BNX2X_NUM_Q_STATS; j++)
-					sprintf(buf + (k + j)*ETH_GSTRING_LEN,
-						bnx2x_q_stats_arr[j].string, i);
+					snprintf(buf + (k + j)*ETH_GSTRING_LEN,
+						ETH_GSTRING_LEN,
+						bnx2x_q_stats_arr[j].string,
+						queue_name);
 				k += BNX2X_NUM_Q_STATS;
 			}
 			if (IS_MF_MODE_STAT(bp))
@@ -1958,7 +2034,7 @@ static void bnx2x_get_ethtool_stats(stru
 
 	if (is_multi(bp)) {
 		k = 0;
-		for_each_queue(bp, i) {
+		for_each_napi_queue(bp, i) {
 			hw_stats = (u32 *)&bp->fp[i].eth_q_stats;
 			for (j = 0; j < BNX2X_NUM_Q_STATS; j++) {
 				if (bnx2x_q_stats_arr[j].size == 0) {
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/bnx2x/bnx2x.h linux-libre-2.6.38-gnu1/drivers/net/bnx2x/bnx2x.h
--- linux-libre-2.6.37-gnu1/drivers/net/bnx2x/bnx2x.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/bnx2x/bnx2x.h	2011-03-14 21:20:32.000000000 -0400
@@ -13,6 +13,8 @@
 
 #ifndef BNX2X_H
 #define BNX2X_H
+#include <linux/netdevice.h>
+#include <linux/types.h>
 
 /* compilation time flags */
 
@@ -20,15 +22,17 @@
  * (you will need to reboot afterwards) */
 /* #define BNX2X_STOP_ON_ERROR */
 
-#define DRV_MODULE_VERSION      "1.60.01-0"
-#define DRV_MODULE_RELDATE      "2010/11/12"
+#define DRV_MODULE_VERSION      "1.62.00-6"
+#define DRV_MODULE_RELDATE      "2011/01/30"
 #define BNX2X_BC_VER            0x040200
 
 #define BNX2X_MULTI_QUEUE
 
 #define BNX2X_NEW_NAPI
 
-
+#if defined(CONFIG_DCB)
+#define BCM_DCB
+#endif
 #if defined(CONFIG_CNIC) || defined(CONFIG_CNIC_MODULE)
 #define BCM_CNIC 1
 #include "../cnic_if.h"
@@ -48,6 +52,7 @@
 #include "bnx2x_fw_defs.h"
 #include "bnx2x_hsi.h"
 #include "bnx2x_link.h"
+#include "bnx2x_dcb.h"
 #include "bnx2x_stats.h"
 
 /* error/debug prints */
@@ -199,10 +204,25 @@ void bnx2x_panic_dump(struct bnx2x *bp);
 /* EQ completions */
 #define HC_SP_INDEX_EQ_CONS			7
 
+/* FCoE L2 connection completions */
+#define HC_SP_INDEX_ETH_FCOE_TX_CQ_CONS		6
+#define HC_SP_INDEX_ETH_FCOE_RX_CQ_CONS		4
 /* iSCSI L2 */
 #define HC_SP_INDEX_ETH_ISCSI_CQ_CONS		5
 #define HC_SP_INDEX_ETH_ISCSI_RX_CQ_CONS	1
 
+/* Special clients parameters */
+
+/* SB indices */
+/* FCoE L2 */
+#define BNX2X_FCOE_L2_RX_INDEX \
+	(&bp->def_status_blk->sp_sb.\
+	index_values[HC_SP_INDEX_ETH_FCOE_RX_CQ_CONS])
+
+#define BNX2X_FCOE_L2_TX_INDEX \
+	(&bp->def_status_blk->sp_sb.\
+	index_values[HC_SP_INDEX_ETH_FCOE_TX_CQ_CONS])
+
 /**
  *  CIDs and CLIDs:
  *  CLIDs below is a CLID for func 0, then the CLID for other
@@ -215,12 +235,19 @@ void bnx2x_panic_dump(struct bnx2x *bp);
 #define BNX2X_ISCSI_ETH_CL_ID		17
 #define BNX2X_ISCSI_ETH_CID		17
 
+/* FCoE L2 */
+#define BNX2X_FCOE_ETH_CL_ID		18
+#define BNX2X_FCOE_ETH_CID		18
+
 /** Additional rings budgeting */
 #ifdef BCM_CNIC
 #define CNIC_CONTEXT_USE		1
+#define FCOE_CONTEXT_USE		1
 #else
 #define CNIC_CONTEXT_USE		0
+#define FCOE_CONTEXT_USE		0
 #endif /* BCM_CNIC */
+#define NONE_ETH_CONTEXT_USE	(FCOE_CONTEXT_USE)
 
 #define AEU_IN_ATTN_BITS_PXPPCICLOCKCLIENT_PARITY_ERROR \
 	AEU_INPUTS_ATTN_BITS_PXPPCICLOCKCLIENT_PARITY_ERROR
@@ -401,6 +428,17 @@ struct bnx2x_fastpath {
 };
 
 #define bnx2x_fp(bp, nr, var)		(bp->fp[nr].var)
+#ifdef BCM_CNIC
+/* FCoE L2 `fastpath' is right after the eth entries */
+#define FCOE_IDX			BNX2X_NUM_ETH_QUEUES(bp)
+#define bnx2x_fcoe_fp(bp)		(&bp->fp[FCOE_IDX])
+#define bnx2x_fcoe(bp, var)		(bnx2x_fcoe_fp(bp)->var)
+#define IS_FCOE_FP(fp)			(fp->index == FCOE_IDX)
+#define IS_FCOE_IDX(idx)		((idx) == FCOE_IDX)
+#else
+#define IS_FCOE_FP(fp)		false
+#define IS_FCOE_IDX(idx)	false
+#endif
 
 
 /* MC hsi */
@@ -598,6 +636,7 @@ struct bnx2x_common {
 
 #define CHIP_METAL(bp)			(bp->common.chip_id & 0x00000ff0)
 #define CHIP_BOND_ID(bp)		(bp->common.chip_id & 0x0000000f)
+#define CHIP_PARITY_ENABLED(bp)	(CHIP_IS_E1(bp) || CHIP_IS_E1H(bp))
 
 	int			flash_size;
 #define NVRAM_1MB_SIZE			0x20000	/* 1M bit in bytes */
@@ -669,8 +708,14 @@ struct bnx2x_port {
 enum {
 	CAM_ETH_LINE = 0,
 	CAM_ISCSI_ETH_LINE,
-	CAM_MAX_PF_LINE = CAM_ISCSI_ETH_LINE
+	CAM_FIP_ETH_LINE,
+	CAM_FIP_MCAST_LINE,
+	CAM_MAX_PF_LINE = CAM_FIP_MCAST_LINE
 };
+/* number of MACs per function in NIG memory - used for SI mode */
+#define NIG_LLH_FUNC_MEM_SIZE		16
+/* number of entries in NIG_REG_LLHX_FUNC_MEM */
+#define NIG_LLH_FUNC_MEM_MAX_OFFSET	8
 
 #define BNX2X_VF_ID_INVALID	0xFF
 
@@ -710,6 +755,14 @@ enum {
  */
 #define L2_FP_COUNT(cid_cnt)	((cid_cnt) - CNIC_CONTEXT_USE)
 
+/*
+ * The number of FP-SB allocated by the driver == max number of regular L2
+ * queues + 1 for the CNIC which also consumes an FP-SB
+ */
+#define FP_SB_COUNT(cid_cnt)	((cid_cnt) - FCOE_CONTEXT_USE)
+#define NUM_IGU_SB_REQUIRED(cid_cnt) \
+				(FP_SB_COUNT(cid_cnt) - NONE_ETH_CONTEXT_USE)
+
 union cdu_context {
 	struct eth_context eth;
 	char pad[1024];
@@ -722,7 +775,8 @@ union cdu_context {
 
 #ifdef BCM_CNIC
 #define CNIC_ISCSI_CID_MAX	256
-#define CNIC_CID_MAX		(CNIC_ISCSI_CID_MAX)
+#define CNIC_FCOE_CID_MAX	2048
+#define CNIC_CID_MAX		(CNIC_ISCSI_CID_MAX + CNIC_FCOE_CID_MAX)
 #define CNIC_ILT_LINES		DIV_ROUND_UP(CNIC_CID_MAX, ILT_PAGE_CIDS)
 #endif
 
@@ -770,6 +824,8 @@ struct bnx2x_slowpath {
 
 	u32				wb_comp;
 	u32				wb_data[4];
+	/* pfc configuration for DCBX ramrod */
+	struct flow_control_configuration pfc_config;
 };
 
 #define bnx2x_sp(bp, var)		(&bp->slowpath->var)
@@ -918,6 +974,10 @@ struct bnx2x {
 #define DISABLE_MSI_FLAG		0x200
 #define BP_NOMCP(bp)			(bp->flags & NO_MCP_FLAG)
 #define MF_FUNC_DIS			0x1000
+#define FCOE_MACS_SET			0x2000
+#define NO_FCOE_FLAG			0x4000
+
+#define NO_FCOE(bp)		((bp)->flags & NO_FCOE_FLAG)
 
 	int			pf_num;	/* absolute PF number */
 	int			pfid;	/* per-path PF number */
@@ -967,6 +1027,8 @@ struct bnx2x {
 	u16			mf_ov;
 	u8			mf_mode;
 #define IS_MF(bp)		(bp->mf_mode != 0)
+#define IS_MF_SI(bp)		(bp->mf_mode == MULTI_FUNCTION_SI)
+#define IS_MF_SD(bp)		(bp->mf_mode == MULTI_FUNCTION_SD)
 
 	u8			wol;
 
@@ -1010,6 +1072,7 @@ struct bnx2x {
 #define BNX2X_ACCEPT_ALL_UNICAST	0x0004
 #define BNX2X_ACCEPT_ALL_MULTICAST	0x0008
 #define BNX2X_ACCEPT_BROADCAST		0x0010
+#define BNX2X_ACCEPT_UNMATCHED_UCAST	0x0020
 #define BNX2X_PROMISCUOUS_MODE		0x10000
 
 	u32			rx_mode;
@@ -1062,7 +1125,8 @@ struct bnx2x {
 	u16			cnic_kwq_pending;
 	u16			cnic_spq_pending;
 	struct mutex		cnic_mutex;
-	u8			iscsi_mac[6];
+	u8			iscsi_mac[ETH_ALEN];
+	u8			fip_mac[ETH_ALEN];
 #endif
 
 	int			dmae_ready;
@@ -1122,6 +1186,32 @@ struct bnx2x {
 
 	char			fw_ver[32];
 	const struct firmware	*firmware;
+	/* LLDP params */
+	struct bnx2x_config_lldp_params		lldp_config_params;
+
+	/* DCB support on/off */
+	u16 dcb_state;
+#define BNX2X_DCB_STATE_OFF			0
+#define BNX2X_DCB_STATE_ON			1
+
+	/* DCBX engine mode */
+	int dcbx_enabled;
+#define BNX2X_DCBX_ENABLED_OFF			0
+#define BNX2X_DCBX_ENABLED_ON_NEG_OFF		1
+#define BNX2X_DCBX_ENABLED_ON_NEG_ON		2
+#define BNX2X_DCBX_ENABLED_INVALID		(-1)
+
+	bool dcbx_mode_uset;
+
+	struct bnx2x_config_dcbx_params		dcbx_config_params;
+
+	struct bnx2x_dcbx_port_params		dcbx_port_params;
+	int					dcb_version;
+
+	/* DCBX Negotation results */
+	struct dcbx_features			dcbx_local_feat;
+	u32					dcbx_error;
+	u32					pending_max;
 };
 
 /**
@@ -1152,10 +1242,17 @@ struct bnx2x {
 #define RSS_IPV6_TCP_CAP	0x0008
 
 #define BNX2X_NUM_QUEUES(bp)	(bp->num_queues)
+#define BNX2X_NUM_ETH_QUEUES(bp) (BNX2X_NUM_QUEUES(bp) - NONE_ETH_CONTEXT_USE)
+
+/* ethtool statistics are displayed for all regular ethernet queues and the
+ * fcoe L2 queue if not disabled
+ */
+#define BNX2X_NUM_STAT_QUEUES(bp) (NO_FCOE(bp) ? BNX2X_NUM_ETH_QUEUES(bp) : \
+			   (BNX2X_NUM_ETH_QUEUES(bp) + FCOE_CONTEXT_USE))
+
 #define is_multi(bp)		(BNX2X_NUM_QUEUES(bp) > 1)
 
 #define BNX2X_MAX_QUEUES(bp)	(bp->igu_sb_cnt - CNIC_CONTEXT_USE)
-#define is_eth_multi(bp)	(BNX2X_NUM_ETH_QUEUES(bp) > 1)
 
 #define RSS_IPV4_CAP_MASK						\
 	TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV4_CAPABILITY
@@ -1248,6 +1345,7 @@ struct bnx2x_client_ramrod_params {
 	u16 cl_id;
 	u32 cid;
 	u8 poll;
+#define CLIENT_IS_FCOE			0x01
 #define CLIENT_IS_LEADING_RSS		0x02
 	u8 flags;
 };
@@ -1280,11 +1378,54 @@ struct bnx2x_func_init_params {
 	u16		spq_prod;	/* valid iff FUNC_FLG_SPQ */
 };
 
+#define for_each_eth_queue(bp, var) \
+			for (var = 0; var < BNX2X_NUM_ETH_QUEUES(bp); var++)
+
+#define for_each_nondefault_eth_queue(bp, var) \
+			for (var = 1; var < BNX2X_NUM_ETH_QUEUES(bp); var++)
+
+#define for_each_napi_queue(bp, var) \
+	for (var = 0; \
+		var < BNX2X_NUM_ETH_QUEUES(bp) + FCOE_CONTEXT_USE; var++) \
+		if (skip_queue(bp, var))	\
+			continue;		\
+		else
+
 #define for_each_queue(bp, var) \
-			for (var = 0; var < BNX2X_NUM_QUEUES(bp); var++)
+	for (var = 0; var < BNX2X_NUM_QUEUES(bp); var++) \
+		if (skip_queue(bp, var))	\
+			continue;		\
+		else
+
+#define for_each_rx_queue(bp, var) \
+	for (var = 0; var < BNX2X_NUM_QUEUES(bp); var++) \
+		if (skip_rx_queue(bp, var))	\
+			continue;		\
+		else
+
+#define for_each_tx_queue(bp, var) \
+	for (var = 0; var < BNX2X_NUM_QUEUES(bp); var++) \
+		if (skip_tx_queue(bp, var))	\
+			continue;		\
+		else
+
 #define for_each_nondefault_queue(bp, var) \
-			for (var = 1; var < BNX2X_NUM_QUEUES(bp); var++)
+	for (var = 1; var < BNX2X_NUM_QUEUES(bp); var++) \
+		if (skip_queue(bp, var))	\
+			continue;		\
+		else
+
+/* skip rx queue
+ * if FCOE l2 support is disabled and this is the fcoe L2 queue
+ */
+#define skip_rx_queue(bp, idx)	(NO_FCOE(bp) && IS_FCOE_IDX(idx))
 
+/* skip tx queue
+ * if FCOE l2 support is disabled and this is the fcoe L2 queue
+ */
+#define skip_tx_queue(bp, idx)	(NO_FCOE(bp) && IS_FCOE_IDX(idx))
+
+#define skip_queue(bp, idx)	(NO_FCOE(bp) && IS_FCOE_IDX(idx))
 
 #define WAIT_RAMROD_POLL	0x01
 #define WAIT_RAMROD_COMMON	0x02
@@ -1329,7 +1470,7 @@ static inline u32 reg_poll(struct bnx2x
 
 #define BNX2X_ILT_ZALLOC(x, y, size) \
 	do { \
-		x = pci_alloc_consistent(bp->pdev, size, y); \
+		x = dma_alloc_coherent(&bp->pdev->dev, size, y, GFP_KERNEL); \
 		if (x) \
 			memset(x, 0, size); \
 	} while (0)
@@ -1337,7 +1478,7 @@ static inline u32 reg_poll(struct bnx2x
 #define BNX2X_ILT_FREE(x, y, size) \
 	do { \
 		if (x) { \
-			pci_free_consistent(bp->pdev, size, x, y); \
+			dma_free_coherent(&bp->pdev->dev, size, x, y); \
 			x = NULL; \
 			y = 0; \
 		} \
@@ -1473,19 +1614,23 @@ static inline u32 reg_poll(struct bnx2x
 #define BNX2X_BTR			4
 #define MAX_SPQ_PENDING			8
 
-
-/* CMNG constants
-   derived from lab experiments, and not from system spec calculations !!! */
-#define DEF_MIN_RATE			100
-/* resolution of the rate shaping timer - 100 usec */
-#define RS_PERIODIC_TIMEOUT_USEC	100
-/* resolution of fairness algorithm in usecs -
-   coefficient for calculating the actual t fair */
-#define T_FAIR_COEF			10000000
+/* CMNG constants, as derived from system spec calculations */
+/* default MIN rate in case VNIC min rate is configured to zero - 100Mbps */
+#define DEF_MIN_RATE					100
+/* resolution of the rate shaping timer - 400 usec */
+#define RS_PERIODIC_TIMEOUT_USEC			400
 /* number of bytes in single QM arbitration cycle -
-   coefficient for calculating the fairness timer */
-#define QM_ARB_BYTES			40000
-#define FAIR_MEM			2
+ * coefficient for calculating the fairness timer */
+#define QM_ARB_BYTES					160000
+/* resolution of Min algorithm 1:100 */
+#define MIN_RES						100
+/* how many bytes above threshold for the minimal credit of Min algorithm*/
+#define MIN_ABOVE_THRESH				32768
+/* Fairness algorithm integration time coefficient -
+ * for calculating the actual Tfair */
+#define T_FAIR_COEF	((MIN_ABOVE_THRESH +  QM_ARB_BYTES) * 8 * MIN_RES)
+/* Memory of fairness algorithm . 2 cycles */
+#define FAIR_MEM					2
 
 
 #define ATTN_NIG_FOR_FUNC		(1L << 8)
@@ -1608,10 +1753,6 @@ static inline u32 reg_poll(struct bnx2x
 	MAC_CONFIGURATION_ENTRY_ACTION_TYPE) == \
 	(T_ETH_MAC_COMMAND_INVALIDATE))
 
-#define CAM_INVALIDATE(x) \
-	(x.target_table_entry.flags = TSTORM_CAM_TARGET_TABLE_ENTRY_ACTION_TYPE)
-
-
 /* Number of u32 elements in MC hash array */
 #define MC_HASH_SIZE			8
 #define MC_HASH_OFFSET(bp, i)		(BAR_TSTRORM_INTMEM + \
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/bnx2x/bnx2x_hsi.h linux-libre-2.6.38-gnu1/drivers/net/bnx2x/bnx2x_hsi.h
--- linux-libre-2.6.37-gnu1/drivers/net/bnx2x/bnx2x_hsi.h	2013-05-03 03:58:06.000000000 -0400
+++ linux-libre-2.6.38-gnu1/drivers/net/bnx2x/bnx2x_hsi.h	2013-05-03 01:58:10.000000000 -0400
@@ -352,6 +352,10 @@ struct port_hw_cfg {			    /* port 0: 0x
 #define PORT_HW_CFG_LANE_SWAP_CFG_31203120	    0x0000d8d8
 	/* forced only */
 #define PORT_HW_CFG_LANE_SWAP_CFG_32103210	    0x0000e4e4
+    /*	Indicate whether to swap the external phy polarity */
+#define PORT_HW_CFG_SWAP_PHY_POLARITY_MASK	       0x00010000
+#define PORT_HW_CFG_SWAP_PHY_POLARITY_DISABLED	    0x00000000
+#define PORT_HW_CFG_SWAP_PHY_POLARITY_ENABLED	    0x00010000
 
 	u32 external_phy_config;
 #define PORT_HW_CFG_SERDES_EXT_PHY_TYPE_MASK	    0xff000000
@@ -434,7 +438,12 @@ struct shared_feat_cfg {				 /* NVRAM Of
 #define SHARED_FEAT_CFG_OVERRIDE_PREEMPHASIS_CFG_DISABLED     0x00000000
 #define SHARED_FEAT_CFG_OVERRIDE_PREEMPHASIS_CFG_ENABLED      0x00000002
 
-#define SHARED_FEATURE_MF_MODE_DISABLED 	    0x00000100
+#define SHARED_FEAT_CFG_FORCE_SF_MODE_MASK		      0x00000700
+#define SHARED_FEAT_CFG_FORCE_SF_MODE_SHIFT		      8
+#define SHARED_FEAT_CFG_FORCE_SF_MODE_MF_ALLOWED	      0x00000000
+#define SHARED_FEAT_CFG_FORCE_SF_MODE_FORCED_SF		      0x00000100
+#define SHARED_FEAT_CFG_FORCE_SF_MODE_SPIO4		      0x00000200
+#define SHARED_FEAT_CFG_FORCE_SF_MODE_SWITCH_INDEPT	      0x00000300
 
 };
 
@@ -679,7 +688,7 @@ struct shm_dev_info {						    /* size *
 #define E1VN_MAX			1
 #define E1HVN_MAX			4
 
-
+#define E2_VF_MAX			64
 /* This value (in milliseconds) determines the frequency of the driver
  * issuing the PULSE message code.  The firmware monitors this periodic
  * pulse to determine when to switch to an OS-absent mode. */
@@ -815,6 +824,11 @@ struct drv_func_mb {
 #define DRV_MSG_CODE_VRFY_SPECIFIC_PHY_OPT_MDL	    0xa1000000
 #define REQ_BC_VER_4_VRFY_SPECIFIC_PHY_OPT_MDL	    0x00050234
 
+#define DRV_MSG_CODE_DCBX_ADMIN_PMF_MSG			0xb0000000
+#define DRV_MSG_CODE_DCBX_PMF_DRV_OK			0xb2000000
+#define DRV_MSG_CODE_SET_MF_BW				0xe0000000
+#define REQ_BC_VER_4_SET_MF_BW				0x00060202
+#define DRV_MSG_CODE_SET_MF_BW_ACK			0xe1000000
 #define BIOS_MSG_CODE_LIC_CHALLENGE			0xff010000
 #define BIOS_MSG_CODE_LIC_RESPONSE			0xff020000
 #define BIOS_MSG_CODE_VIRT_MAC_PRIM			0xff030000
@@ -888,6 +902,7 @@ struct drv_func_mb {
 
 	u32 drv_status;
 #define DRV_STATUS_PMF					0x00000001
+#define DRV_STATUS_SET_MF_BW				0x00000004
 
 #define DRV_STATUS_DCC_EVENT_MASK			0x0000ff00
 #define DRV_STATUS_DCC_DISABLE_ENABLE_PF		0x00000100
@@ -896,6 +911,8 @@ struct drv_func_mb {
 #define DRV_STATUS_DCC_RESERVED1			0x00000800
 #define DRV_STATUS_DCC_SET_PROTOCOL			0x00001000
 #define DRV_STATUS_DCC_SET_PRIORITY			0x00002000
+#define DRV_STATUS_DCBX_EVENT_MASK			0x000f0000
+#define DRV_STATUS_DCBX_NEGOTIATION_RESULTS		0x00010000
 
 	u32 virt_mac_upper;
 #define VIRT_MAC_SIGN_MASK				0xffff0000
@@ -988,12 +1005,43 @@ struct func_mf_cfg {
 
 };
 
+/* This structure is not applicable and should not be accessed on 57711 */
+struct func_ext_cfg {
+	u32 func_cfg;
+#define MACP_FUNC_CFG_FLAGS_MASK			      0x000000FF
+#define MACP_FUNC_CFG_FLAGS_SHIFT			      0
+#define MACP_FUNC_CFG_FLAGS_ENABLED			      0x00000001
+#define MACP_FUNC_CFG_FLAGS_ETHERNET			      0x00000002
+#define MACP_FUNC_CFG_FLAGS_ISCSI_OFFLOAD		      0x00000004
+#define MACP_FUNC_CFG_FLAGS_FCOE_OFFLOAD		      0x00000008
+
+	u32 iscsi_mac_addr_upper;
+	u32 iscsi_mac_addr_lower;
+
+	u32 fcoe_mac_addr_upper;
+	u32 fcoe_mac_addr_lower;
+
+	u32 fcoe_wwn_port_name_upper;
+	u32 fcoe_wwn_port_name_lower;
+
+	u32 fcoe_wwn_node_name_upper;
+	u32 fcoe_wwn_node_name_lower;
+
+	u32 preserve_data;
+#define MF_FUNC_CFG_PRESERVE_L2_MAC			     (1<<0)
+#define MF_FUNC_CFG_PRESERVE_ISCSI_MAC			     (1<<1)
+#define MF_FUNC_CFG_PRESERVE_FCOE_MAC			     (1<<2)
+#define MF_FUNC_CFG_PRESERVE_FCOE_WWN_P			     (1<<3)
+#define MF_FUNC_CFG_PRESERVE_FCOE_WWN_N			     (1<<4)
+};
+
 struct mf_cfg {
 
 	struct shared_mf_cfg	shared_mf_config;
 	struct port_mf_cfg	port_mf_config[PORT_MAX];
 	struct func_mf_cfg	func_mf_config[E1H_FUNC_MAX];
 
+	struct func_ext_cfg func_ext_config[E1H_FUNC_MAX];
 };
 
 
@@ -1049,6 +1097,251 @@ struct fw_flr_mb {
 	struct	fw_flr_ack ack;
 };
 
+/**** SUPPORT FOR SHMEM ARRRAYS ***
+ * The SHMEM HSI is aligned on 32 bit boundaries which makes it difficult to
+ * define arrays with storage types smaller then unsigned dwords.
+ * The macros below add generic support for SHMEM arrays with numeric elements
+ * that can span 2,4,8 or 16 bits. The array underlying type is a 32 bit dword
+ * array with individual bit-filed elements accessed using shifts and masks.
+ *
+ */
+
+/* eb is the bitwidth of a single element */
+#define SHMEM_ARRAY_MASK(eb)		((1<<(eb))-1)
+#define SHMEM_ARRAY_ENTRY(i, eb)	((i)/(32/(eb)))
+
+/* the bit-position macro allows the used to flip the order of the arrays
+ * elements on a per byte or word boundary.
+ *
+ * example: an array with 8 entries each 4 bit wide. This array will fit into
+ * a single dword. The diagrmas below show the array order of the nibbles.
+ *
+ * SHMEM_ARRAY_BITPOS(i, 4, 4) defines the stadard ordering:
+ *
+ *		|		|		|		|
+ *   0	|   1	|   2	|   3	|   4	|   5	|   6	|   7	|
+ *		|		|		|		|
+ *
+ * SHMEM_ARRAY_BITPOS(i, 4, 8) defines a flip ordering per byte:
+ *
+ *		|		|		|		|
+ *   1	|   0	|   3	|   2	|   5	|   4	|   7	|   6	|
+ *		|		|		|		|
+ *
+ * SHMEM_ARRAY_BITPOS(i, 4, 16) defines a flip ordering per word:
+ *
+ *		|		|		|		|
+ *   3	|   2	|   1	|   0	|   7	|   6	|   5	|   4	|
+ *		|		|		|		|
+ */
+#define SHMEM_ARRAY_BITPOS(i, eb, fb)	\
+	((((32/(fb)) - 1 - ((i)/((fb)/(eb))) % (32/(fb))) * (fb)) + \
+	(((i)%((fb)/(eb))) * (eb)))
+
+#define SHMEM_ARRAY_GET(a, i, eb, fb)					   \
+	((a[SHMEM_ARRAY_ENTRY(i, eb)] >> SHMEM_ARRAY_BITPOS(i, eb, fb)) &  \
+	SHMEM_ARRAY_MASK(eb))
+
+#define SHMEM_ARRAY_SET(a, i, eb, fb, val)				   \
+do {									   \
+	a[SHMEM_ARRAY_ENTRY(i, eb)] &= ~(SHMEM_ARRAY_MASK(eb) <<	   \
+	SHMEM_ARRAY_BITPOS(i, eb, fb));				   \
+	a[SHMEM_ARRAY_ENTRY(i, eb)] |= (((val) & SHMEM_ARRAY_MASK(eb)) <<  \
+	SHMEM_ARRAY_BITPOS(i, eb, fb));				   \
+} while (0)
+
+
+/****START OF DCBX STRUCTURES DECLARATIONS****/
+#define DCBX_MAX_NUM_PRI_PG_ENTRIES	8
+#define DCBX_PRI_PG_BITWIDTH		4
+#define DCBX_PRI_PG_FBITS		8
+#define DCBX_PRI_PG_GET(a, i)		\
+	SHMEM_ARRAY_GET(a, i, DCBX_PRI_PG_BITWIDTH, DCBX_PRI_PG_FBITS)
+#define DCBX_PRI_PG_SET(a, i, val)	\
+	SHMEM_ARRAY_SET(a, i, DCBX_PRI_PG_BITWIDTH, DCBX_PRI_PG_FBITS, val)
+#define DCBX_MAX_NUM_PG_BW_ENTRIES	8
+#define DCBX_BW_PG_BITWIDTH		8
+#define DCBX_PG_BW_GET(a, i)		\
+	SHMEM_ARRAY_GET(a, i, DCBX_BW_PG_BITWIDTH, DCBX_BW_PG_BITWIDTH)
+#define DCBX_PG_BW_SET(a, i, val)	\
+	SHMEM_ARRAY_SET(a, i, DCBX_BW_PG_BITWIDTH, DCBX_BW_PG_BITWIDTH, val)
+#define DCBX_STRICT_PRI_PG		15
+#define DCBX_MAX_APP_PROTOCOL		16
+#define FCOE_APP_IDX			0
+#define ISCSI_APP_IDX			1
+#define PREDEFINED_APP_IDX_MAX		2
+
+struct dcbx_ets_feature {
+	u32 enabled;
+	u32  pg_bw_tbl[2];
+	u32  pri_pg_tbl[1];
+};
+
+struct dcbx_pfc_feature {
+#ifdef __BIG_ENDIAN
+	u8 pri_en_bitmap;
+#define DCBX_PFC_PRI_0 0x01
+#define DCBX_PFC_PRI_1 0x02
+#define DCBX_PFC_PRI_2 0x04
+#define DCBX_PFC_PRI_3 0x08
+#define DCBX_PFC_PRI_4 0x10
+#define DCBX_PFC_PRI_5 0x20
+#define DCBX_PFC_PRI_6 0x40
+#define DCBX_PFC_PRI_7 0x80
+	u8 pfc_caps;
+	u8 reserved;
+	u8 enabled;
+#elif defined(__LITTLE_ENDIAN)
+	u8 enabled;
+	u8 reserved;
+	u8 pfc_caps;
+	u8 pri_en_bitmap;
+#define DCBX_PFC_PRI_0 0x01
+#define DCBX_PFC_PRI_1 0x02
+#define DCBX_PFC_PRI_2 0x04
+#define DCBX_PFC_PRI_3 0x08
+#define DCBX_PFC_PRI_4 0x10
+#define DCBX_PFC_PRI_5 0x20
+#define DCBX_PFC_PRI_6 0x40
+#define DCBX_PFC_PRI_7 0x80
+#endif
+};
+
+struct dcbx_app_priority_entry {
+#ifdef __BIG_ENDIAN
+	u16	app_id;
+	u8	pri_bitmap;
+	u8	appBitfield;
+#define DCBX_APP_ENTRY_VALID	     0x01
+#define DCBX_APP_ENTRY_SF_MASK	     0x30
+#define DCBX_APP_ENTRY_SF_SHIFT	     4
+#define DCBX_APP_SF_ETH_TYPE	     0x10
+#define DCBX_APP_SF_PORT	     0x20
+#elif defined(__LITTLE_ENDIAN)
+	u8 appBitfield;
+#define DCBX_APP_ENTRY_VALID	     0x01
+#define DCBX_APP_ENTRY_SF_MASK	     0x30
+#define DCBX_APP_ENTRY_SF_SHIFT	     4
+#define DCBX_APP_SF_ETH_TYPE	     0x10
+#define DCBX_APP_SF_PORT	     0x20
+	u8	pri_bitmap;
+	u16	app_id;
+#endif
+};
+
+struct dcbx_app_priority_feature {
+#ifdef __BIG_ENDIAN
+	u8 reserved;
+	u8 default_pri;
+	u8 tc_supported;
+	u8 enabled;
+#elif defined(__LITTLE_ENDIAN)
+	u8 enabled;
+	u8 tc_supported;
+	u8 default_pri;
+	u8 reserved;
+#endif
+	struct dcbx_app_priority_entry  app_pri_tbl[DCBX_MAX_APP_PROTOCOL];
+};
+
+struct dcbx_features {
+	struct dcbx_ets_feature ets;
+	struct dcbx_pfc_feature pfc;
+	struct dcbx_app_priority_feature app;
+};
+
+struct lldp_params {
+#ifdef __BIG_ENDIAN
+	u8	msg_fast_tx_interval;
+	u8	msg_tx_hold;
+	u8	msg_tx_interval;
+	u8	admin_status;
+#define LLDP_TX_ONLY  0x01
+#define LLDP_RX_ONLY  0x02
+#define LLDP_TX_RX    0x03
+#define LLDP_DISABLED 0x04
+	u8	reserved1;
+	u8	tx_fast;
+	u8	tx_crd_max;
+	u8	tx_crd;
+#elif defined(__LITTLE_ENDIAN)
+	u8	admin_status;
+#define LLDP_TX_ONLY  0x01
+#define LLDP_RX_ONLY  0x02
+#define LLDP_TX_RX    0x03
+#define LLDP_DISABLED 0x04
+	u8	msg_tx_interval;
+	u8	msg_tx_hold;
+	u8	msg_fast_tx_interval;
+	u8	tx_crd;
+	u8	tx_crd_max;
+	u8	tx_fast;
+	u8	reserved1;
+#endif
+#define REM_CHASSIS_ID_STAT_LEN	4
+#define REM_PORT_ID_STAT_LEN 4
+	u32 peer_chassis_id[REM_CHASSIS_ID_STAT_LEN];
+	u32 peer_port_id[REM_PORT_ID_STAT_LEN];
+};
+
+struct lldp_dcbx_stat {
+#define LOCAL_CHASSIS_ID_STAT_LEN 2
+#define LOCAL_PORT_ID_STAT_LEN 2
+	u32 local_chassis_id[LOCAL_CHASSIS_ID_STAT_LEN];
+	u32 local_port_id[LOCAL_PORT_ID_STAT_LEN];
+	u32 num_tx_dcbx_pkts;
+	u32 num_rx_dcbx_pkts;
+};
+
+struct lldp_admin_mib {
+	u32	ver_cfg_flags;
+#define DCBX_ETS_CONFIG_TX_ENABLED	0x00000001
+#define DCBX_PFC_CONFIG_TX_ENABLED	0x00000002
+#define DCBX_APP_CONFIG_TX_ENABLED	0x00000004
+#define DCBX_ETS_RECO_TX_ENABLED	0x00000008
+#define DCBX_ETS_RECO_VALID		0x00000010
+#define DCBX_ETS_WILLING		0x00000020
+#define DCBX_PFC_WILLING		0x00000040
+#define DCBX_APP_WILLING		0x00000080
+#define DCBX_VERSION_CEE		0x00000100
+#define DCBX_VERSION_IEEE		0x00000200
+#define DCBX_DCBX_ENABLED		0x00000400
+#define DCBX_CEE_VERSION_MASK		0x0000f000
+#define DCBX_CEE_VERSION_SHIFT		12
+#define DCBX_CEE_MAX_VERSION_MASK	0x000f0000
+#define DCBX_CEE_MAX_VERSION_SHIFT	16
+	struct dcbx_features	features;
+};
+
+struct lldp_remote_mib {
+	u32 prefix_seq_num;
+	u32 flags;
+#define DCBX_ETS_TLV_RX	    0x00000001
+#define DCBX_PFC_TLV_RX	    0x00000002
+#define DCBX_APP_TLV_RX	    0x00000004
+#define DCBX_ETS_RX_ERROR   0x00000010
+#define DCBX_PFC_RX_ERROR   0x00000020
+#define DCBX_APP_RX_ERROR   0x00000040
+#define DCBX_ETS_REM_WILLING	0x00000100
+#define DCBX_PFC_REM_WILLING	0x00000200
+#define DCBX_APP_REM_WILLING	0x00000400
+#define DCBX_REMOTE_ETS_RECO_VALID  0x00001000
+	struct dcbx_features features;
+	u32 suffix_seq_num;
+};
+
+struct lldp_local_mib {
+	u32 prefix_seq_num;
+	u32 error;
+#define DCBX_LOCAL_ETS_ERROR	 0x00000001
+#define DCBX_LOCAL_PFC_ERROR	 0x00000002
+#define DCBX_LOCAL_APP_ERROR	 0x00000004
+#define DCBX_LOCAL_PFC_MISMATCH	 0x00000010
+#define DCBX_LOCAL_APP_MISMATCH	 0x00000020
+	struct dcbx_features   features;
+	u32 suffix_seq_num;
+};
+/***END OF DCBX STRUCTURES DECLARATIONS***/
 
 struct shmem2_region {
 
@@ -1072,7 +1365,12 @@ struct shmem2_region {
 #define SHMEM_MF_CFG_ADDR_NONE			    0x00000000
 
 	struct fw_flr_mb flr_mb;
-	u32	reserved[3];
+	u32	dcbx_lldp_params_offset;
+#define SHMEM_LLDP_DCBX_PARAMS_NONE		    0x00000000
+	u32	dcbx_neg_res_offset;
+#define SHMEM_DCBX_NEG_RES_NONE			    0x00000000
+	u32	dcbx_remote_mib_offset;
+#define SHMEM_DCBX_REMOTE_MIB_NONE		    0x00000000
 	/*
 	 * The other shmemX_base_addr holds the other path's shmem address
 	 * required for example in case of common phy init, or for path1 to know
@@ -1081,6 +1379,10 @@ struct shmem2_region {
 	 */
 	u32 other_shmem_base_addr;
 	u32 other_shmem2_base_addr;
+	u32	reserved1[E2_VF_MAX / 32];
+	u32	reserved2[E2_FUNC_MAX][E2_VF_MAX / 32];
+	u32	dcbx_lldp_dcbx_stat_offset;
+#define SHMEM_LLDP_DCBX_STAT_NONE		   0x00000000
 };
 
 
@@ -2978,6 +3280,25 @@ struct fairness_vars_per_vn {
 };
 
 
+/*
+ * The data for flow control configuration
+ */
+struct flow_control_configuration {
+	struct priority_cos
+		traffic_type_to_priority_cos[MAX_PFC_TRAFFIC_TYPES];
+#if defined(__BIG_ENDIAN)
+	u16 reserved1;
+	u8 dcb_version;
+	u8 dcb_enabled;
+#elif defined(__LITTLE_ENDIAN)
+	u8 dcb_enabled;
+	u8 dcb_version;
+	u16 reserved1;
+#endif
+	u32 reserved2;
+};
+
+
 /*
  * FW version stored in the Xstorm RAM
  */
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/bnx2x/bnx2x_init.h linux-libre-2.6.38-gnu1/drivers/net/bnx2x/bnx2x_init.h
--- linux-libre-2.6.37-gnu1/drivers/net/bnx2x/bnx2x_init.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/bnx2x/bnx2x_init.h	2011-03-14 21:20:32.000000000 -0400
@@ -192,5 +192,225 @@ struct src_ent {
 	u64 next;
 };
 
+/****************************************************************************
+* Parity configuration
+****************************************************************************/
+#define BLOCK_PRTY_INFO(block, en_mask, m1, m1h, m2) \
+{ \
+	block##_REG_##block##_PRTY_MASK, \
+	block##_REG_##block##_PRTY_STS_CLR, \
+	en_mask, {m1, m1h, m2}, #block \
+}
+
+#define BLOCK_PRTY_INFO_0(block, en_mask, m1, m1h, m2) \
+{ \
+	block##_REG_##block##_PRTY_MASK_0, \
+	block##_REG_##block##_PRTY_STS_CLR_0, \
+	en_mask, {m1, m1h, m2}, #block"_0" \
+}
+
+#define BLOCK_PRTY_INFO_1(block, en_mask, m1, m1h, m2) \
+{ \
+	block##_REG_##block##_PRTY_MASK_1, \
+	block##_REG_##block##_PRTY_STS_CLR_1, \
+	en_mask, {m1, m1h, m2}, #block"_1" \
+}
+
+static const struct {
+	u32 mask_addr;
+	u32 sts_clr_addr;
+	u32 en_mask;		/* Mask to enable parity attentions */
+	struct {
+		u32 e1;		/* 57710 */
+		u32 e1h;	/* 57711 */
+		u32 e2;		/* 57712 */
+	} reg_mask;		/* Register mask (all valid bits) */
+	char name[7];		/* Block's longest name is 6 characters long
+				 * (name + suffix)
+				 */
+} bnx2x_blocks_parity_data[] = {
+	/* bit 19 masked */
+	/* REG_WR(bp, PXP_REG_PXP_PRTY_MASK, 0x80000); */
+	/* bit 5,18,20-31 */
+	/* REG_WR(bp, PXP2_REG_PXP2_PRTY_MASK_0, 0xfff40020); */
+	/* bit 5 */
+	/* REG_WR(bp, PXP2_REG_PXP2_PRTY_MASK_1, 0x20);	*/
+	/* REG_WR(bp, HC_REG_HC_PRTY_MASK, 0x0); */
+	/* REG_WR(bp, MISC_REG_MISC_PRTY_MASK, 0x0); */
+
+	/* Block IGU, MISC, PXP and PXP2 parity errors as long as we don't
+	 * want to handle "system kill" flow at the moment.
+	 */
+	BLOCK_PRTY_INFO(PXP, 0x7ffffff, 0x3ffffff, 0x3ffffff, 0x7ffffff),
+	BLOCK_PRTY_INFO_0(PXP2,	0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff),
+	BLOCK_PRTY_INFO_1(PXP2,	0x7ff, 0x7f, 0x7f, 0x7ff),
+	BLOCK_PRTY_INFO(HC, 0x7, 0x7, 0x7, 0),
+	BLOCK_PRTY_INFO(IGU, 0x7ff, 0, 0, 0x7ff),
+	BLOCK_PRTY_INFO(MISC, 0x1, 0x1, 0x1, 0x1),
+	BLOCK_PRTY_INFO(QM, 0, 0x1ff, 0xfff, 0xfff),
+	BLOCK_PRTY_INFO(DORQ, 0, 0x3, 0x3, 0x3),
+	{GRCBASE_UPB + PB_REG_PB_PRTY_MASK,
+		GRCBASE_UPB + PB_REG_PB_PRTY_STS_CLR, 0,
+		{0xf, 0xf, 0xf}, "UPB"},
+	{GRCBASE_XPB + PB_REG_PB_PRTY_MASK,
+		GRCBASE_XPB + PB_REG_PB_PRTY_STS_CLR, 0,
+		{0xf, 0xf, 0xf}, "XPB"},
+	BLOCK_PRTY_INFO(SRC, 0x4, 0x7, 0x7, 0x7),
+	BLOCK_PRTY_INFO(CDU, 0, 0x1f, 0x1f, 0x1f),
+	BLOCK_PRTY_INFO(CFC, 0, 0xf, 0xf, 0xf),
+	BLOCK_PRTY_INFO(DBG, 0, 0x1, 0x1, 0x1),
+	BLOCK_PRTY_INFO(DMAE, 0, 0xf, 0xf, 0xf),
+	BLOCK_PRTY_INFO(BRB1, 0, 0xf, 0xf, 0xf),
+	BLOCK_PRTY_INFO(PRS, (1<<6), 0xff, 0xff, 0xff),
+	BLOCK_PRTY_INFO(TSDM, 0x18, 0x7ff, 0x7ff, 0x7ff),
+	BLOCK_PRTY_INFO(CSDM, 0x8, 0x7ff, 0x7ff, 0x7ff),
+	BLOCK_PRTY_INFO(USDM, 0x38, 0x7ff, 0x7ff, 0x7ff),
+	BLOCK_PRTY_INFO(XSDM, 0x8, 0x7ff, 0x7ff, 0x7ff),
+	BLOCK_PRTY_INFO_0(TSEM, 0, 0xffffffff, 0xffffffff, 0xffffffff),
+	BLOCK_PRTY_INFO_1(TSEM, 0, 0x3, 0x1f, 0x3f),
+	BLOCK_PRTY_INFO_0(USEM, 0, 0xffffffff, 0xffffffff, 0xffffffff),
+	BLOCK_PRTY_INFO_1(USEM, 0, 0x3, 0x1f, 0x1f),
+	BLOCK_PRTY_INFO_0(CSEM, 0, 0xffffffff, 0xffffffff, 0xffffffff),
+	BLOCK_PRTY_INFO_1(CSEM, 0, 0x3, 0x1f, 0x1f),
+	BLOCK_PRTY_INFO_0(XSEM, 0, 0xffffffff, 0xffffffff, 0xffffffff),
+	BLOCK_PRTY_INFO_1(XSEM, 0, 0x3, 0x1f, 0x3f),
+};
+
+
+/* [28] MCP Latched rom_parity
+ * [29] MCP Latched ump_rx_parity
+ * [30] MCP Latched ump_tx_parity
+ * [31] MCP Latched scpad_parity
+ */
+#define MISC_AEU_ENABLE_MCP_PRTY_BITS	\
+	(AEU_INPUTS_ATTN_BITS_MCP_LATCHED_ROM_PARITY | \
+	 AEU_INPUTS_ATTN_BITS_MCP_LATCHED_UMP_RX_PARITY | \
+	 AEU_INPUTS_ATTN_BITS_MCP_LATCHED_UMP_TX_PARITY | \
+	 AEU_INPUTS_ATTN_BITS_MCP_LATCHED_SCPAD_PARITY)
+
+/* Below registers control the MCP parity attention output. When
+ * MISC_AEU_ENABLE_MCP_PRTY_BITS are set - attentions are
+ * enabled, when cleared - disabled.
+ */
+static const u32 mcp_attn_ctl_regs[] = {
+	MISC_REG_AEU_ENABLE4_FUNC_0_OUT_0,
+	MISC_REG_AEU_ENABLE4_NIG_0,
+	MISC_REG_AEU_ENABLE4_PXP_0,
+	MISC_REG_AEU_ENABLE4_FUNC_1_OUT_0,
+	MISC_REG_AEU_ENABLE4_NIG_1,
+	MISC_REG_AEU_ENABLE4_PXP_1
+};
+
+static inline void bnx2x_set_mcp_parity(struct bnx2x *bp, u8 enable)
+{
+	int i;
+	u32 reg_val;
+
+	for (i = 0; i < ARRAY_SIZE(mcp_attn_ctl_regs); i++) {
+		reg_val = REG_RD(bp, mcp_attn_ctl_regs[i]);
+
+		if (enable)
+			reg_val |= MISC_AEU_ENABLE_MCP_PRTY_BITS;
+		else
+			reg_val &= ~MISC_AEU_ENABLE_MCP_PRTY_BITS;
+
+		REG_WR(bp, mcp_attn_ctl_regs[i], reg_val);
+	}
+}
+
+static inline u32 bnx2x_parity_reg_mask(struct bnx2x *bp, int idx)
+{
+	if (CHIP_IS_E1(bp))
+		return bnx2x_blocks_parity_data[idx].reg_mask.e1;
+	else if (CHIP_IS_E1H(bp))
+		return bnx2x_blocks_parity_data[idx].reg_mask.e1h;
+	else
+		return bnx2x_blocks_parity_data[idx].reg_mask.e2;
+}
+
+static inline void bnx2x_disable_blocks_parity(struct bnx2x *bp)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(bnx2x_blocks_parity_data); i++) {
+		u32 dis_mask = bnx2x_parity_reg_mask(bp, i);
+
+		if (dis_mask) {
+			REG_WR(bp, bnx2x_blocks_parity_data[i].mask_addr,
+			       dis_mask);
+			DP(NETIF_MSG_HW, "Setting parity mask "
+						 "for %s to\t\t0x%x\n",
+				    bnx2x_blocks_parity_data[i].name, dis_mask);
+		}
+	}
+
+	/* Disable MCP parity attentions */
+	bnx2x_set_mcp_parity(bp, false);
+}
+
+/**
+ * Clear the parity error status registers.
+ */
+static inline void bnx2x_clear_blocks_parity(struct bnx2x *bp)
+{
+	int i;
+	u32 reg_val, mcp_aeu_bits =
+		AEU_INPUTS_ATTN_BITS_MCP_LATCHED_ROM_PARITY |
+		AEU_INPUTS_ATTN_BITS_MCP_LATCHED_SCPAD_PARITY |
+		AEU_INPUTS_ATTN_BITS_MCP_LATCHED_UMP_RX_PARITY |
+		AEU_INPUTS_ATTN_BITS_MCP_LATCHED_UMP_TX_PARITY;
+
+	/* Clear SEM_FAST parities */
+	REG_WR(bp, XSEM_REG_FAST_MEMORY + SEM_FAST_REG_PARITY_RST, 0x1);
+	REG_WR(bp, TSEM_REG_FAST_MEMORY + SEM_FAST_REG_PARITY_RST, 0x1);
+	REG_WR(bp, USEM_REG_FAST_MEMORY + SEM_FAST_REG_PARITY_RST, 0x1);
+	REG_WR(bp, CSEM_REG_FAST_MEMORY + SEM_FAST_REG_PARITY_RST, 0x1);
+
+	for (i = 0; i < ARRAY_SIZE(bnx2x_blocks_parity_data); i++) {
+		u32 reg_mask = bnx2x_parity_reg_mask(bp, i);
+
+		if (reg_mask) {
+			reg_val = REG_RD(bp, bnx2x_blocks_parity_data[i].
+					 sts_clr_addr);
+			if (reg_val & reg_mask)
+				DP(NETIF_MSG_HW,
+					    "Parity errors in %s: 0x%x\n",
+					    bnx2x_blocks_parity_data[i].name,
+					    reg_val & reg_mask);
+		}
+	}
+
+	/* Check if there were parity attentions in MCP */
+	reg_val = REG_RD(bp, MISC_REG_AEU_AFTER_INVERT_4_MCP);
+	if (reg_val & mcp_aeu_bits)
+		DP(NETIF_MSG_HW, "Parity error in MCP: 0x%x\n",
+		   reg_val & mcp_aeu_bits);
+
+	/* Clear parity attentions in MCP:
+	 * [7]  clears Latched rom_parity
+	 * [8]  clears Latched ump_rx_parity
+	 * [9]  clears Latched ump_tx_parity
+	 * [10] clears Latched scpad_parity (both ports)
+	 */
+	REG_WR(bp, MISC_REG_AEU_CLR_LATCH_SIGNAL, 0x780);
+}
+
+static inline void bnx2x_enable_blocks_parity(struct bnx2x *bp)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(bnx2x_blocks_parity_data); i++) {
+		u32 reg_mask = bnx2x_parity_reg_mask(bp, i);
+
+		if (reg_mask)
+			REG_WR(bp, bnx2x_blocks_parity_data[i].mask_addr,
+				bnx2x_blocks_parity_data[i].en_mask & reg_mask);
+	}
+
+	/* Enable MCP parity attentions */
+	bnx2x_set_mcp_parity(bp, true);
+}
+
+
 #endif /* BNX2X_INIT_H */
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/bnx2x/bnx2x_link.c linux-libre-2.6.38-gnu1/drivers/net/bnx2x/bnx2x_link.c
--- linux-libre-2.6.37-gnu1/drivers/net/bnx2x/bnx2x_link.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/bnx2x/bnx2x_link.c	2011-03-14 21:20:32.000000000 -0400
@@ -164,7 +164,8 @@
 #define EDC_MODE_PASSIVE_DAC 			0x0055
 
 
-
+#define ETS_BW_LIMIT_CREDIT_UPPER_BOUND		(0x5000)
+#define ETS_BW_LIMIT_CREDIT_WEIGHT		(0x5000)
 /**********************************************************/
 /*                     INTERFACE                          */
 /**********************************************************/
@@ -205,6 +206,270 @@ static u32 bnx2x_bits_dis(struct bnx2x *
 	return val;
 }
 
+/******************************************************************/
+/*				ETS section			  */
+/******************************************************************/
+void bnx2x_ets_disabled(struct link_params *params)
+{
+	/* ETS disabled configuration*/
+	struct bnx2x *bp = params->bp;
+
+	DP(NETIF_MSG_LINK, "ETS disabled configuration\n");
+
+	/**
+	 * mapping between entry  priority to client number (0,1,2 -debug and
+	 * management clients, 3 - COS0 client, 4 - COS client)(HIGHEST)
+	 * 3bits client num.
+	 *   PRI4    |    PRI3    |    PRI2    |    PRI1    |    PRI0
+	 * cos1-100     cos0-011     dbg1-010     dbg0-001     MCP-000
+	 */
+
+	REG_WR(bp, NIG_REG_P0_TX_ARB_PRIORITY_CLIENT, 0x4688);
+	/**
+	 * Bitmap of 5bits length. Each bit specifies whether the entry behaves
+	 * as strict.  Bits 0,1,2 - debug and management entries, 3 -
+	 * COS0 entry, 4 - COS1 entry.
+	 * COS1 | COS0 | DEBUG1 | DEBUG0 | MGMT
+	 * bit4   bit3	  bit2   bit1	  bit0
+	 * MCP and debug are strict
+	 */
+
+	REG_WR(bp, NIG_REG_P0_TX_ARB_CLIENT_IS_STRICT, 0x7);
+	/* defines which entries (clients) are subjected to WFQ arbitration */
+	REG_WR(bp, NIG_REG_P0_TX_ARB_CLIENT_IS_SUBJECT2WFQ, 0);
+	/**
+	* For strict priority entries defines the number of consecutive
+	* slots for the highest priority.
+	*/
+	REG_WR(bp, NIG_REG_P0_TX_ARB_NUM_STRICT_ARB_SLOTS, 0x100);
+	/**
+	 * mapping between the CREDIT_WEIGHT registers and actual client
+	 * numbers
+	 */
+	REG_WR(bp, NIG_REG_P0_TX_ARB_CLIENT_CREDIT_MAP, 0);
+	REG_WR(bp, NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_0, 0);
+	REG_WR(bp, NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_1, 0);
+
+	REG_WR(bp, NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_0, 0);
+	REG_WR(bp, NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_1, 0);
+	REG_WR(bp, PBF_REG_HIGH_PRIORITY_COS_NUM, 0);
+	/* ETS mode disable */
+	REG_WR(bp, PBF_REG_ETS_ENABLED, 0);
+	/**
+	 * If ETS mode is enabled (there is no strict priority) defines a WFQ
+	 * weight for COS0/COS1.
+	 */
+	REG_WR(bp, PBF_REG_COS0_WEIGHT, 0x2710);
+	REG_WR(bp, PBF_REG_COS1_WEIGHT, 0x2710);
+	/* Upper bound that COS0_WEIGHT can reach in the WFQ arbiter */
+	REG_WR(bp, PBF_REG_COS0_UPPER_BOUND, 0x989680);
+	REG_WR(bp, PBF_REG_COS1_UPPER_BOUND, 0x989680);
+	/* Defines the number of consecutive slots for the strict priority */
+	REG_WR(bp, PBF_REG_NUM_STRICT_ARB_SLOTS, 0);
+}
+
+void bnx2x_ets_bw_limit_common(const struct link_params *params)
+{
+	/* ETS disabled configuration */
+	struct bnx2x *bp = params->bp;
+	DP(NETIF_MSG_LINK, "ETS enabled BW limit configuration\n");
+	/**
+	* defines which entries (clients) are subjected to WFQ arbitration
+	* COS0 0x8
+	* COS1 0x10
+	*/
+	REG_WR(bp, NIG_REG_P0_TX_ARB_CLIENT_IS_SUBJECT2WFQ, 0x18);
+	/**
+	* mapping between the ARB_CREDIT_WEIGHT registers and actual
+	* client numbers (WEIGHT_0 does not actually have to represent
+	* client 0)
+	*    PRI4    |    PRI3    |    PRI2    |    PRI1    |    PRI0
+	*  cos1-001     cos0-000     dbg1-100     dbg0-011     MCP-010
+	*/
+	REG_WR(bp, NIG_REG_P0_TX_ARB_CLIENT_CREDIT_MAP, 0x111A);
+
+	REG_WR(bp, NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_0,
+	       ETS_BW_LIMIT_CREDIT_UPPER_BOUND);
+	REG_WR(bp, NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_1,
+	       ETS_BW_LIMIT_CREDIT_UPPER_BOUND);
+
+	/* ETS mode enabled*/
+	REG_WR(bp, PBF_REG_ETS_ENABLED, 1);
+
+	/* Defines the number of consecutive slots for the strict priority */
+	REG_WR(bp, PBF_REG_NUM_STRICT_ARB_SLOTS, 0);
+	/**
+	* Bitmap of 5bits length. Each bit specifies whether the entry behaves
+	* as strict.  Bits 0,1,2 - debug and management entries, 3 - COS0
+	* entry, 4 - COS1 entry.
+	* COS1 | COS0 | DEBUG21 | DEBUG0 | MGMT
+	* bit4   bit3	  bit2     bit1	   bit0
+	* MCP and debug are strict
+	*/
+	REG_WR(bp, NIG_REG_P0_TX_ARB_CLIENT_IS_STRICT, 0x7);
+
+	/* Upper bound that COS0_WEIGHT can reach in the WFQ arbiter.*/
+	REG_WR(bp, PBF_REG_COS0_UPPER_BOUND,
+	       ETS_BW_LIMIT_CREDIT_UPPER_BOUND);
+	REG_WR(bp, PBF_REG_COS1_UPPER_BOUND,
+	       ETS_BW_LIMIT_CREDIT_UPPER_BOUND);
+}
+
+void bnx2x_ets_bw_limit(const struct link_params *params, const u32 cos0_bw,
+			const u32 cos1_bw)
+{
+	/* ETS disabled configuration*/
+	struct bnx2x *bp = params->bp;
+	const u32 total_bw = cos0_bw + cos1_bw;
+	u32 cos0_credit_weight = 0;
+	u32 cos1_credit_weight = 0;
+
+	DP(NETIF_MSG_LINK, "ETS enabled BW limit configuration\n");
+
+	if ((0 == total_bw) ||
+	    (0 == cos0_bw) ||
+	    (0 == cos1_bw)) {
+		DP(NETIF_MSG_LINK,
+		   "bnx2x_ets_bw_limit: Total BW can't be zero\n");
+		return;
+	}
+
+	cos0_credit_weight = (cos0_bw * ETS_BW_LIMIT_CREDIT_WEIGHT)/
+		total_bw;
+	cos1_credit_weight = (cos1_bw * ETS_BW_LIMIT_CREDIT_WEIGHT)/
+		total_bw;
+
+	bnx2x_ets_bw_limit_common(params);
+
+	REG_WR(bp, NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_0, cos0_credit_weight);
+	REG_WR(bp, NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_1, cos1_credit_weight);
+
+	REG_WR(bp, PBF_REG_COS0_WEIGHT, cos0_credit_weight);
+	REG_WR(bp, PBF_REG_COS1_WEIGHT, cos1_credit_weight);
+}
+
+u8 bnx2x_ets_strict(const struct link_params *params, const u8 strict_cos)
+{
+	/* ETS disabled configuration*/
+	struct bnx2x *bp = params->bp;
+	u32 val	= 0;
+
+	DP(NETIF_MSG_LINK, "ETS enabled strict configuration\n");
+	/**
+	 * Bitmap of 5bits length. Each bit specifies whether the entry behaves
+	 * as strict.  Bits 0,1,2 - debug and management entries,
+	 * 3 - COS0 entry, 4 - COS1 entry.
+	 *  COS1 | COS0 | DEBUG21 | DEBUG0 | MGMT
+	 *  bit4   bit3	  bit2      bit1     bit0
+	 * MCP and debug are strict
+	 */
+	REG_WR(bp, NIG_REG_P0_TX_ARB_CLIENT_IS_STRICT, 0x1F);
+	/**
+	 * For strict priority entries defines the number of consecutive slots
+	 * for the highest priority.
+	 */
+	REG_WR(bp, NIG_REG_P0_TX_ARB_NUM_STRICT_ARB_SLOTS, 0x100);
+	/* ETS mode disable */
+	REG_WR(bp, PBF_REG_ETS_ENABLED, 0);
+	/* Defines the number of consecutive slots for the strict priority */
+	REG_WR(bp, PBF_REG_NUM_STRICT_ARB_SLOTS, 0x100);
+
+	/* Defines the number of consecutive slots for the strict priority */
+	REG_WR(bp, PBF_REG_HIGH_PRIORITY_COS_NUM, strict_cos);
+
+	/**
+	* mapping between entry  priority to client number (0,1,2 -debug and
+	* management clients, 3 - COS0 client, 4 - COS client)(HIGHEST)
+	* 3bits client num.
+	*   PRI4    |    PRI3    |    PRI2    |    PRI1    |    PRI0
+	* dbg0-010     dbg1-001     cos1-100     cos0-011     MCP-000
+	* dbg0-010     dbg1-001     cos0-011     cos1-100     MCP-000
+	*/
+	val = (0 == strict_cos) ? 0x2318 : 0x22E0;
+	REG_WR(bp, NIG_REG_P0_TX_ARB_PRIORITY_CLIENT, val);
+
+	return 0;
+}
+/******************************************************************/
+/*			ETS section				  */
+/******************************************************************/
+
+static void bnx2x_bmac2_get_pfc_stat(struct link_params *params,
+				     u32 pfc_frames_sent[2],
+				     u32 pfc_frames_received[2])
+{
+	/* Read pfc statistic */
+	struct bnx2x *bp = params->bp;
+	u32 bmac_addr = params->port ? NIG_REG_INGRESS_BMAC1_MEM :
+		NIG_REG_INGRESS_BMAC0_MEM;
+
+	DP(NETIF_MSG_LINK, "pfc statistic read from BMAC\n");
+
+	REG_RD_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_TX_STAT_GTPP,
+					pfc_frames_sent, 2);
+
+	REG_RD_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_RX_STAT_GRPP,
+					pfc_frames_received, 2);
+
+}
+static void bnx2x_emac_get_pfc_stat(struct link_params *params,
+				    u32 pfc_frames_sent[2],
+				    u32 pfc_frames_received[2])
+{
+	/* Read pfc statistic */
+	struct bnx2x *bp = params->bp;
+	u32 emac_base = params->port ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
+	u32 val_xon = 0;
+	u32 val_xoff = 0;
+
+	DP(NETIF_MSG_LINK, "pfc statistic read from EMAC\n");
+
+	/* PFC received frames */
+	val_xoff = REG_RD(bp, emac_base +
+				EMAC_REG_RX_PFC_STATS_XOFF_RCVD);
+	val_xoff &= EMAC_REG_RX_PFC_STATS_XOFF_RCVD_COUNT;
+	val_xon = REG_RD(bp, emac_base + EMAC_REG_RX_PFC_STATS_XON_RCVD);
+	val_xon &= EMAC_REG_RX_PFC_STATS_XON_RCVD_COUNT;
+
+	pfc_frames_received[0] = val_xon + val_xoff;
+
+	/* PFC received sent */
+	val_xoff = REG_RD(bp, emac_base +
+				EMAC_REG_RX_PFC_STATS_XOFF_SENT);
+	val_xoff &= EMAC_REG_RX_PFC_STATS_XOFF_SENT_COUNT;
+	val_xon = REG_RD(bp, emac_base + EMAC_REG_RX_PFC_STATS_XON_SENT);
+	val_xon &= EMAC_REG_RX_PFC_STATS_XON_SENT_COUNT;
+
+	pfc_frames_sent[0] = val_xon + val_xoff;
+}
+
+void bnx2x_pfc_statistic(struct link_params *params, struct link_vars *vars,
+			 u32 pfc_frames_sent[2],
+			 u32 pfc_frames_received[2])
+{
+	/* Read pfc statistic */
+	struct bnx2x *bp = params->bp;
+	u32 val	= 0;
+	DP(NETIF_MSG_LINK, "pfc statistic\n");
+
+	if (!vars->link_up)
+		return;
+
+	val = REG_RD(bp, MISC_REG_RESET_REG_2);
+	if ((val & (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << params->port))
+	    == 0) {
+		DP(NETIF_MSG_LINK, "About to read stats from EMAC\n");
+		bnx2x_emac_get_pfc_stat(params, pfc_frames_sent,
+					pfc_frames_received);
+	} else {
+		DP(NETIF_MSG_LINK, "About to read stats from BMAC\n");
+		bnx2x_bmac2_get_pfc_stat(params, pfc_frames_sent,
+					 pfc_frames_received);
+	}
+}
+/******************************************************************/
+/*			MAC/PBF section				  */
+/******************************************************************/
 static void bnx2x_emac_init(struct link_params *params,
 			   struct link_vars *vars)
 {
@@ -315,24 +580,55 @@ static u8 bnx2x_emac_enable(struct link_
 		/* pause enable/disable */
 		bnx2x_bits_dis(bp, emac_base + EMAC_REG_EMAC_RX_MODE,
 			       EMAC_RX_MODE_FLOW_EN);
-		if (vars->flow_ctrl & BNX2X_FLOW_CTRL_RX)
-			bnx2x_bits_en(bp, emac_base +
-				    EMAC_REG_EMAC_RX_MODE,
-				    EMAC_RX_MODE_FLOW_EN);
 
 		bnx2x_bits_dis(bp,  emac_base + EMAC_REG_EMAC_TX_MODE,
-			     (EMAC_TX_MODE_EXT_PAUSE_EN |
-			      EMAC_TX_MODE_FLOW_EN));
-		if (vars->flow_ctrl & BNX2X_FLOW_CTRL_TX)
-			bnx2x_bits_en(bp, emac_base +
-				    EMAC_REG_EMAC_TX_MODE,
-				   (EMAC_TX_MODE_EXT_PAUSE_EN |
-				    EMAC_TX_MODE_FLOW_EN));
+			       (EMAC_TX_MODE_EXT_PAUSE_EN |
+				EMAC_TX_MODE_FLOW_EN));
+		if (!(params->feature_config_flags &
+		      FEATURE_CONFIG_PFC_ENABLED)) {
+			if (vars->flow_ctrl & BNX2X_FLOW_CTRL_RX)
+				bnx2x_bits_en(bp, emac_base +
+					      EMAC_REG_EMAC_RX_MODE,
+					      EMAC_RX_MODE_FLOW_EN);
+
+			if (vars->flow_ctrl & BNX2X_FLOW_CTRL_TX)
+				bnx2x_bits_en(bp, emac_base +
+					      EMAC_REG_EMAC_TX_MODE,
+					      (EMAC_TX_MODE_EXT_PAUSE_EN |
+					       EMAC_TX_MODE_FLOW_EN));
+		} else
+			bnx2x_bits_en(bp, emac_base + EMAC_REG_EMAC_TX_MODE,
+				      EMAC_TX_MODE_FLOW_EN);
 	}
 
 	/* KEEP_VLAN_TAG, promiscuous */
 	val = REG_RD(bp, emac_base + EMAC_REG_EMAC_RX_MODE);
 	val |= EMAC_RX_MODE_KEEP_VLAN_TAG | EMAC_RX_MODE_PROMISCUOUS;
+
+	/**
+	* Setting this bit causes MAC control frames (except for pause
+	* frames) to be passed on for processing. This setting has no
+	* affect on the operation of the pause frames. This bit effects
+	* all packets regardless of RX Parser packet sorting logic.
+	* Turn the PFC off to make sure we are in Xon state before
+	* enabling it.
+	*/
+	EMAC_WR(bp, EMAC_REG_RX_PFC_MODE, 0);
+	if (params->feature_config_flags & FEATURE_CONFIG_PFC_ENABLED) {
+		DP(NETIF_MSG_LINK, "PFC is enabled\n");
+		/* Enable PFC again */
+		EMAC_WR(bp, EMAC_REG_RX_PFC_MODE,
+			EMAC_REG_RX_PFC_MODE_RX_EN |
+			EMAC_REG_RX_PFC_MODE_TX_EN |
+			EMAC_REG_RX_PFC_MODE_PRIORITIES);
+
+		EMAC_WR(bp, EMAC_REG_RX_PFC_PARAM,
+			((0x0101 <<
+			  EMAC_REG_RX_PFC_PARAM_OPCODE_BITSHIFT) |
+			 (0x00ff <<
+			  EMAC_REG_RX_PFC_PARAM_PRIORITY_EN_BITSHIFT)));
+		val |= EMAC_RX_MODE_KEEP_MAC_CONTROL;
+	}
 	EMAC_WR(bp, EMAC_REG_EMAC_RX_MODE, val);
 
 	/* Set Loopback */
@@ -362,7 +658,9 @@ static u8 bnx2x_emac_enable(struct link_
 	/* enable the NIG in/out to the emac */
 	REG_WR(bp, NIG_REG_EMAC0_IN_EN + port*4, 0x1);
 	val = 0;
-	if (vars->flow_ctrl & BNX2X_FLOW_CTRL_TX)
+	if ((params->feature_config_flags &
+	      FEATURE_CONFIG_PFC_ENABLED) ||
+	    (vars->flow_ctrl & BNX2X_FLOW_CTRL_TX))
 		val = 1;
 
 	REG_WR(bp, NIG_REG_EMAC0_PAUSE_OUT_EN + port*4, val);
@@ -383,9 +681,38 @@ static u8 bnx2x_emac_enable(struct link_
 	return 0;
 }
 
-static void bnx2x_update_bmac2(struct link_params *params,
-			       struct link_vars *vars,
-			       u8 is_lb)
+static void bnx2x_update_pfc_bmac1(struct link_params *params,
+				   struct link_vars *vars)
+{
+	u32 wb_data[2];
+	struct bnx2x *bp = params->bp;
+	u32 bmac_addr =  params->port ? NIG_REG_INGRESS_BMAC1_MEM :
+		NIG_REG_INGRESS_BMAC0_MEM;
+
+	u32 val = 0x14;
+	if ((!(params->feature_config_flags &
+	      FEATURE_CONFIG_PFC_ENABLED)) &&
+		(vars->flow_ctrl & BNX2X_FLOW_CTRL_RX))
+		/* Enable BigMAC to react on received Pause packets */
+		val |= (1<<5);
+	wb_data[0] = val;
+	wb_data[1] = 0;
+	REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_RX_CONTROL, wb_data, 2);
+
+	/* tx control */
+	val = 0xc0;
+	if (!(params->feature_config_flags &
+	      FEATURE_CONFIG_PFC_ENABLED) &&
+		(vars->flow_ctrl & BNX2X_FLOW_CTRL_TX))
+		val |= 0x800000;
+	wb_data[0] = val;
+	wb_data[1] = 0;
+	REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_TX_CONTROL, wb_data, 2);
+}
+
+static void bnx2x_update_pfc_bmac2(struct link_params *params,
+				   struct link_vars *vars,
+				   u8 is_lb)
 {
 	/*
 	 * Set rx control: Strip CRC and enable BigMAC to relay
@@ -397,7 +724,9 @@ static void bnx2x_update_bmac2(struct li
 		NIG_REG_INGRESS_BMAC0_MEM;
 	u32 val = 0x14;
 
-	if (vars->flow_ctrl & BNX2X_FLOW_CTRL_RX)
+	if ((!(params->feature_config_flags &
+	      FEATURE_CONFIG_PFC_ENABLED)) &&
+		(vars->flow_ctrl & BNX2X_FLOW_CTRL_RX))
 		/* Enable BigMAC to react on received Pause packets */
 		val |= (1<<5);
 	wb_data[0] = val;
@@ -408,14 +737,47 @@ static void bnx2x_update_bmac2(struct li
 
 	/* Tx control */
 	val = 0xc0;
-	if (vars->flow_ctrl & BNX2X_FLOW_CTRL_TX)
+	if (!(params->feature_config_flags &
+				FEATURE_CONFIG_PFC_ENABLED) &&
+	    (vars->flow_ctrl & BNX2X_FLOW_CTRL_TX))
 		val |= 0x800000;
 	wb_data[0] = val;
 	wb_data[1] = 0;
-	REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_TX_CONTROL,
-			wb_data, 2);
+	REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_TX_CONTROL, wb_data, 2);
+
+	if (params->feature_config_flags & FEATURE_CONFIG_PFC_ENABLED) {
+		DP(NETIF_MSG_LINK, "PFC is enabled\n");
+		/* Enable PFC RX & TX & STATS and set 8 COS  */
+		wb_data[0] = 0x0;
+		wb_data[0] |= (1<<0);  /* RX */
+		wb_data[0] |= (1<<1);  /* TX */
+		wb_data[0] |= (1<<2);  /* Force initial Xon */
+		wb_data[0] |= (1<<3);  /* 8 cos */
+		wb_data[0] |= (1<<5);  /* STATS */
+		wb_data[1] = 0;
+		REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_PFC_CONTROL,
+			    wb_data, 2);
+		/* Clear the force Xon */
+		wb_data[0] &= ~(1<<2);
+	} else {
+		DP(NETIF_MSG_LINK, "PFC is disabled\n");
+		/* disable PFC RX & TX & STATS and set 8 COS */
+		wb_data[0] = 0x8;
+		wb_data[1] = 0;
+	}
 
+	REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_PFC_CONTROL, wb_data, 2);
+
+	/**
+	* Set Time (based unit is 512 bit time) between automatic
+	* re-sending of PP packets amd enable automatic re-send of
+	* Per-Priroity Packet as long as pp_gen is asserted and
+	* pp_disable is low.
+	*/
 	val = 0x8000;
+	if (params->feature_config_flags & FEATURE_CONFIG_PFC_ENABLED)
+		val |= (1<<16); /* enable automatic re-send */
+
 	wb_data[0] = val;
 	wb_data[1] = 0;
 	REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_TX_PAUSE_CONTROL,
@@ -427,6 +789,9 @@ static void bnx2x_update_bmac2(struct li
 		val |= 0x4; /* Local loopback */
 		DP(NETIF_MSG_LINK, "enable bmac loopback\n");
 	}
+	/* When PFC enabled, Pass pause frames towards the NIG. */
+	if (params->feature_config_flags & FEATURE_CONFIG_PFC_ENABLED)
+		val |= ((1<<6)|(1<<5));
 
 	wb_data[0] = val;
 	wb_data[1] = 0;
@@ -434,6 +799,239 @@ static void bnx2x_update_bmac2(struct li
 			wb_data, 2);
 }
 
+static void bnx2x_update_pfc_brb(struct link_params *params,
+		struct link_vars *vars,
+		struct bnx2x_nig_brb_pfc_port_params *pfc_params)
+{
+	struct bnx2x *bp = params->bp;
+	int set_pfc = params->feature_config_flags &
+		FEATURE_CONFIG_PFC_ENABLED;
+
+	/* default - pause configuration */
+	u32 pause_xoff_th = PFC_BRB_MAC_PAUSE_XOFF_THRESHOLD_PAUSEABLE;
+	u32 pause_xon_th = PFC_BRB_MAC_PAUSE_XON_THRESHOLD_PAUSEABLE;
+	u32 full_xoff_th = PFC_BRB_MAC_FULL_XOFF_THRESHOLD_PAUSEABLE;
+	u32 full_xon_th = PFC_BRB_MAC_FULL_XON_THRESHOLD_PAUSEABLE;
+
+	if (set_pfc && pfc_params)
+		/* First COS */
+		if (!pfc_params->cos0_pauseable) {
+			pause_xoff_th =
+			  PFC_BRB_MAC_PAUSE_XOFF_THRESHOLD_NON_PAUSEABLE;
+			pause_xon_th =
+			  PFC_BRB_MAC_PAUSE_XON_THRESHOLD_NON_PAUSEABLE;
+			full_xoff_th =
+			  PFC_BRB_MAC_FULL_XOFF_THRESHOLD_NON_PAUSEABLE;
+			full_xon_th =
+			  PFC_BRB_MAC_FULL_XON_THRESHOLD_NON_PAUSEABLE;
+		}
+	/* The number of free blocks below which the pause signal to class 0
+	   of MAC #n is asserted. n=0,1 */
+	REG_WR(bp, BRB1_REG_PAUSE_0_XOFF_THRESHOLD_0 , pause_xoff_th);
+	/* The number of free blocks above which the pause signal to class 0
+	   of MAC #n is de-asserted. n=0,1 */
+	REG_WR(bp, BRB1_REG_PAUSE_0_XON_THRESHOLD_0 , pause_xon_th);
+	/* The number of free blocks below which the full signal to class 0
+	   of MAC #n is asserted. n=0,1 */
+	REG_WR(bp, BRB1_REG_FULL_0_XOFF_THRESHOLD_0 , full_xoff_th);
+	/* The number of free blocks above which the full signal to class 0
+	   of MAC #n is de-asserted. n=0,1 */
+	REG_WR(bp, BRB1_REG_FULL_0_XON_THRESHOLD_0 , full_xon_th);
+
+	if (set_pfc && pfc_params) {
+		/* Second COS */
+		if (pfc_params->cos1_pauseable) {
+			pause_xoff_th =
+			  PFC_BRB_MAC_PAUSE_XOFF_THRESHOLD_PAUSEABLE;
+			pause_xon_th =
+			  PFC_BRB_MAC_PAUSE_XON_THRESHOLD_PAUSEABLE;
+			full_xoff_th =
+			  PFC_BRB_MAC_FULL_XOFF_THRESHOLD_PAUSEABLE;
+			full_xon_th =
+			  PFC_BRB_MAC_FULL_XON_THRESHOLD_PAUSEABLE;
+		} else {
+			pause_xoff_th =
+			  PFC_BRB_MAC_PAUSE_XOFF_THRESHOLD_NON_PAUSEABLE;
+			pause_xon_th =
+			  PFC_BRB_MAC_PAUSE_XON_THRESHOLD_NON_PAUSEABLE;
+			full_xoff_th =
+			  PFC_BRB_MAC_FULL_XOFF_THRESHOLD_NON_PAUSEABLE;
+			full_xon_th =
+			  PFC_BRB_MAC_FULL_XON_THRESHOLD_NON_PAUSEABLE;
+		}
+		/**
+		 * The number of free blocks below which the pause signal to
+		 * class 1 of MAC #n is asserted. n=0,1
+		 **/
+		REG_WR(bp, BRB1_REG_PAUSE_1_XOFF_THRESHOLD_0, pause_xoff_th);
+		/**
+		 * The number of free blocks above which the pause signal to
+		 * class 1 of MAC #n is de-asserted. n=0,1
+		 **/
+		REG_WR(bp, BRB1_REG_PAUSE_1_XON_THRESHOLD_0, pause_xon_th);
+		/**
+		 * The number of free blocks below which the full signal to
+		 * class 1 of MAC #n is asserted. n=0,1
+		 **/
+		REG_WR(bp, BRB1_REG_FULL_1_XOFF_THRESHOLD_0, full_xoff_th);
+		/**
+		 * The number of free blocks above which the full signal to
+		 * class 1 of MAC #n is de-asserted. n=0,1
+		 **/
+		REG_WR(bp, BRB1_REG_FULL_1_XON_THRESHOLD_0, full_xon_th);
+	}
+}
+
+static void bnx2x_update_pfc_nig(struct link_params *params,
+		struct link_vars *vars,
+		struct bnx2x_nig_brb_pfc_port_params *nig_params)
+{
+	u32 xcm_mask = 0, ppp_enable = 0, pause_enable = 0, llfc_out_en = 0;
+	u32 llfc_enable = 0, xcm0_out_en = 0, p0_hwpfc_enable = 0;
+	u32 pkt_priority_to_cos = 0;
+	u32 val;
+	struct bnx2x *bp = params->bp;
+	int port = params->port;
+	int set_pfc = params->feature_config_flags &
+		FEATURE_CONFIG_PFC_ENABLED;
+	DP(NETIF_MSG_LINK, "updating pfc nig parameters\n");
+
+	/**
+	 * When NIG_LLH0_XCM_MASK_REG_LLHX_XCM_MASK_BCN bit is set
+	 * MAC control frames (that are not pause packets)
+	 * will be forwarded to the XCM.
+	 */
+	xcm_mask = REG_RD(bp,
+				port ? NIG_REG_LLH1_XCM_MASK :
+				NIG_REG_LLH0_XCM_MASK);
+	/**
+	 * nig params will override non PFC params, since it's possible to
+	 * do transition from PFC to SAFC
+	 */
+	if (set_pfc) {
+		pause_enable = 0;
+		llfc_out_en = 0;
+		llfc_enable = 0;
+		ppp_enable = 1;
+		xcm_mask &= ~(port ? NIG_LLH1_XCM_MASK_REG_LLH1_XCM_MASK_BCN :
+				     NIG_LLH0_XCM_MASK_REG_LLH0_XCM_MASK_BCN);
+		xcm0_out_en = 0;
+		p0_hwpfc_enable = 1;
+	} else  {
+		if (nig_params) {
+			llfc_out_en = nig_params->llfc_out_en;
+			llfc_enable = nig_params->llfc_enable;
+			pause_enable = nig_params->pause_enable;
+		} else  /*defaul non PFC mode - PAUSE */
+			pause_enable = 1;
+
+		xcm_mask |= (port ? NIG_LLH1_XCM_MASK_REG_LLH1_XCM_MASK_BCN :
+			NIG_LLH0_XCM_MASK_REG_LLH0_XCM_MASK_BCN);
+		xcm0_out_en = 1;
+	}
+
+	REG_WR(bp, port ? NIG_REG_LLFC_OUT_EN_1 :
+	       NIG_REG_LLFC_OUT_EN_0, llfc_out_en);
+	REG_WR(bp, port ? NIG_REG_LLFC_ENABLE_1 :
+	       NIG_REG_LLFC_ENABLE_0, llfc_enable);
+	REG_WR(bp, port ? NIG_REG_PAUSE_ENABLE_1 :
+	       NIG_REG_PAUSE_ENABLE_0, pause_enable);
+
+	REG_WR(bp, port ? NIG_REG_PPP_ENABLE_1 :
+	       NIG_REG_PPP_ENABLE_0, ppp_enable);
+
+	REG_WR(bp, port ? NIG_REG_LLH1_XCM_MASK :
+	       NIG_REG_LLH0_XCM_MASK, xcm_mask);
+
+	REG_WR(bp,  NIG_REG_LLFC_EGRESS_SRC_ENABLE_0, 0x7);
+
+	/* output enable for RX_XCM # IF */
+	REG_WR(bp, NIG_REG_XCM0_OUT_EN, xcm0_out_en);
+
+	/* HW PFC TX enable */
+	REG_WR(bp, NIG_REG_P0_HWPFC_ENABLE, p0_hwpfc_enable);
+
+	/* 0x2 = BMAC, 0x1= EMAC */
+	switch (vars->mac_type) {
+	case MAC_TYPE_EMAC:
+		val = 1;
+		break;
+	case MAC_TYPE_BMAC:
+		val = 0;
+		break;
+	default:
+		val = 0;
+		break;
+	}
+	REG_WR(bp, NIG_REG_EGRESS_EMAC0_PORT, val);
+
+	if (nig_params) {
+		pkt_priority_to_cos = nig_params->pkt_priority_to_cos;
+
+		REG_WR(bp, port ? NIG_REG_P1_RX_COS0_PRIORITY_MASK :
+		       NIG_REG_P0_RX_COS0_PRIORITY_MASK,
+		       nig_params->rx_cos0_priority_mask);
+
+		REG_WR(bp, port ? NIG_REG_P1_RX_COS1_PRIORITY_MASK :
+		       NIG_REG_P0_RX_COS1_PRIORITY_MASK,
+		       nig_params->rx_cos1_priority_mask);
+
+		REG_WR(bp, port ? NIG_REG_LLFC_HIGH_PRIORITY_CLASSES_1 :
+		       NIG_REG_LLFC_HIGH_PRIORITY_CLASSES_0,
+		       nig_params->llfc_high_priority_classes);
+
+		REG_WR(bp, port ? NIG_REG_LLFC_LOW_PRIORITY_CLASSES_1 :
+		       NIG_REG_LLFC_LOW_PRIORITY_CLASSES_0,
+		       nig_params->llfc_low_priority_classes);
+	}
+	REG_WR(bp, port ? NIG_REG_P1_PKT_PRIORITY_TO_COS :
+	       NIG_REG_P0_PKT_PRIORITY_TO_COS,
+	       pkt_priority_to_cos);
+}
+
+
+void bnx2x_update_pfc(struct link_params *params,
+		      struct link_vars *vars,
+		      struct bnx2x_nig_brb_pfc_port_params *pfc_params)
+{
+	/**
+	 * The PFC and pause are orthogonal to one another, meaning when
+	 * PFC is enabled, the pause are disabled, and when PFC is
+	 * disabled, pause are set according to the pause result.
+	 */
+	u32 val;
+	struct bnx2x *bp = params->bp;
+
+	/* update NIG params */
+	bnx2x_update_pfc_nig(params, vars, pfc_params);
+
+	/* update BRB params */
+	bnx2x_update_pfc_brb(params, vars, pfc_params);
+
+	if (!vars->link_up)
+		return;
+
+	val = REG_RD(bp, MISC_REG_RESET_REG_2);
+	if ((val & (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << params->port))
+	    == 0) {
+		DP(NETIF_MSG_LINK, "About to update PFC in EMAC\n");
+		bnx2x_emac_enable(params, vars, 0);
+		return;
+	}
+
+	DP(NETIF_MSG_LINK, "About to update PFC in BMAC\n");
+	if (CHIP_IS_E2(bp))
+		bnx2x_update_pfc_bmac2(params, vars, 0);
+	else
+		bnx2x_update_pfc_bmac1(params, vars);
+
+	val = 0;
+	if ((params->feature_config_flags &
+	      FEATURE_CONFIG_PFC_ENABLED) ||
+	    (vars->flow_ctrl & BNX2X_FLOW_CTRL_TX))
+		val = 1;
+	REG_WR(bp, NIG_REG_BMAC0_PAUSE_OUT_EN + params->port*4, val);
+}
 
 static u8 bnx2x_bmac1_enable(struct link_params *params,
 			     struct link_vars *vars,
@@ -465,15 +1063,6 @@ static u8 bnx2x_bmac1_enable(struct link
 	REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_TX_SOURCE_ADDR,
 		    wb_data, 2);
 
-	/* tx control */
-	val = 0xc0;
-	if (vars->flow_ctrl & BNX2X_FLOW_CTRL_TX)
-		val |= 0x800000;
-	wb_data[0] = val;
-	wb_data[1] = 0;
-	REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_TX_CONTROL,
-			wb_data, 2);
-
 	/* mac control */
 	val = 0x3;
 	if (is_lb) {
@@ -491,14 +1080,7 @@ static u8 bnx2x_bmac1_enable(struct link
 	REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_RX_MAX_SIZE,
 			wb_data, 2);
 
-	/* rx control set to don't strip crc */
-	val = 0x14;
-	if (vars->flow_ctrl & BNX2X_FLOW_CTRL_RX)
-		val |= 0x20;
-	wb_data[0] = val;
-	wb_data[1] = 0;
-	REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_RX_CONTROL,
-			wb_data, 2);
+	bnx2x_update_pfc_bmac1(params, vars);
 
 	/* set tx mtu */
 	wb_data[0] = ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVREHEAD;
@@ -595,7 +1177,7 @@ static u8 bnx2x_bmac2_enable(struct link
 	REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_CNT_MAX_SIZE,
 			wb_data, 2);
 	udelay(30);
-	bnx2x_update_bmac2(params, vars, is_lb);
+	bnx2x_update_pfc_bmac2(params, vars, is_lb);
 
 	return 0;
 }
@@ -627,7 +1209,9 @@ static u8 bnx2x_bmac_enable(struct link_
 	REG_WR(bp, NIG_REG_XGXS_LANE_SEL_P0 + port*4, 0x0);
 	REG_WR(bp, NIG_REG_EGRESS_EMAC0_PORT + port*4, 0x0);
 	val = 0;
-	if (vars->flow_ctrl & BNX2X_FLOW_CTRL_TX)
+	if ((params->feature_config_flags &
+	      FEATURE_CONFIG_PFC_ENABLED) ||
+	    (vars->flow_ctrl & BNX2X_FLOW_CTRL_TX))
 		val = 1;
 	REG_WR(bp, NIG_REG_BMAC0_PAUSE_OUT_EN + port*4, val);
 	REG_WR(bp, NIG_REG_EGRESS_EMAC0_OUT_EN + port*4, 0x0);
@@ -989,7 +1573,7 @@ static void bnx2x_set_aer_mmd_xgxs(struc
 
 	offset = phy->addr + ser_lane;
 	if (CHIP_IS_E2(bp))
-		aer_val = 0x2800 + offset - 1;
+		aer_val = 0x3800 + offset - 1;
 	else
 		aer_val = 0x3800 + offset;
 	CL45_WR_OVER_CL22(bp, phy,
@@ -2582,7 +3166,23 @@ u8 bnx2x_set_led(struct link_params *par
 		if (!vars->link_up)
 			break;
 	case LED_MODE_ON:
-		if (SINGLE_MEDIA_DIRECT(params)) {
+		if (params->phy[EXT_PHY1].type ==
+		    PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727 &&
+		    CHIP_IS_E2(bp) && params->num_phys == 2) {
+			/**
+			* This is a work-around for E2+8727 Configurations
+			*/
+			if (mode == LED_MODE_ON ||
+				speed == SPEED_10000){
+				REG_WR(bp, NIG_REG_LED_MODE_P0 + port*4, 0);
+				REG_WR(bp, NIG_REG_LED_10G_P0 + port*4, 1);
+
+				tmp = EMAC_RD(bp, EMAC_REG_EMAC_LED);
+				EMAC_WR(bp, EMAC_REG_EMAC_LED,
+					(tmp | EMAC_LED_OVERRIDE));
+				return rc;
+			}
+		} else if (SINGLE_MEDIA_DIRECT(params)) {
 			/**
 			* This is a work-around for HW issue found when link
 			* is up in CL73
@@ -3270,11 +3870,14 @@ static void bnx2x_8073_resolve_fc(struct
 			   pause_result);
 	}
 }
-
-static void bnx2x_8073_8727_external_rom_boot(struct bnx2x *bp,
+static u8 bnx2x_8073_8727_external_rom_boot(struct bnx2x *bp,
 					      struct bnx2x_phy *phy,
 					      u8 port)
 {
+	u32 count = 0;
+	u16 fw_ver1, fw_msgout;
+	u8 rc = 0;
+
 	/* Boot port from external ROM  */
 	/* EDC grst */
 	bnx2x_cl45_write(bp, phy,
@@ -3304,56 +3907,45 @@ static void bnx2x_8073_8727_external_rom
 		       MDIO_PMA_REG_GEN_CTRL,
 		       MDIO_PMA_REG_GEN_CTRL_ROM_RESET_INTERNAL_MP);
 
-	/* wait for 120ms for code download via SPI port */
-	msleep(120);
+	/* Delay 100ms per the PHY specifications */
+	msleep(100);
+
+	/* 8073 sometimes taking longer to download */
+	do {
+		count++;
+		if (count > 300) {
+			DP(NETIF_MSG_LINK,
+				 "bnx2x_8073_8727_external_rom_boot port %x:"
+				 "Download failed. fw version = 0x%x\n",
+				 port, fw_ver1);
+			rc = -EINVAL;
+			break;
+		}
+
+		bnx2x_cl45_read(bp, phy,
+				MDIO_PMA_DEVAD,
+				MDIO_PMA_REG_ROM_VER1, &fw_ver1);
+		bnx2x_cl45_read(bp, phy,
+				MDIO_PMA_DEVAD,
+				MDIO_PMA_REG_M8051_MSGOUT_REG, &fw_msgout);
+
+		msleep(1);
+	} while (fw_ver1 == 0 || fw_ver1 == 0x4321 ||
+			((fw_msgout & 0xff) != 0x03 && (phy->type ==
+			PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073)));
 
 	/* Clear ser_boot_ctl bit */
 	bnx2x_cl45_write(bp, phy,
 		       MDIO_PMA_DEVAD,
 		       MDIO_PMA_REG_MISC_CTRL1, 0x0000);
 	bnx2x_save_bcm_spirom_ver(bp, phy, port);
-}
 
-static void bnx2x_8073_set_xaui_low_power_mode(struct bnx2x *bp,
-					       struct bnx2x_phy *phy)
-{
-	u16 val;
-	bnx2x_cl45_read(bp, phy,
-			MDIO_PMA_DEVAD, MDIO_PMA_REG_8073_CHIP_REV, &val);
-
-	if (val == 0) {
-		/* Mustn't set low power mode in 8073 A0 */
-		return;
-	}
-
-	/* Disable PLL sequencer (use read-modify-write to clear bit 13) */
-	bnx2x_cl45_read(bp, phy,
-			MDIO_XS_DEVAD, MDIO_XS_PLL_SEQUENCER, &val);
-	val &= ~(1<<13);
-	bnx2x_cl45_write(bp, phy,
-		       MDIO_XS_DEVAD, MDIO_XS_PLL_SEQUENCER, val);
-
-	/* PLL controls */
-	bnx2x_cl45_write(bp, phy, MDIO_XS_DEVAD, 0x805E, 0x1077);
-	bnx2x_cl45_write(bp, phy, MDIO_XS_DEVAD, 0x805D, 0x0000);
-	bnx2x_cl45_write(bp, phy, MDIO_XS_DEVAD, 0x805C, 0x030B);
-	bnx2x_cl45_write(bp, phy, MDIO_XS_DEVAD, 0x805B, 0x1240);
-	bnx2x_cl45_write(bp, phy, MDIO_XS_DEVAD, 0x805A, 0x2490);
-
-	/* Tx Controls */
-	bnx2x_cl45_write(bp, phy, MDIO_XS_DEVAD, 0x80A7, 0x0C74);
-	bnx2x_cl45_write(bp, phy, MDIO_XS_DEVAD, 0x80A6, 0x9041);
-	bnx2x_cl45_write(bp, phy, MDIO_XS_DEVAD, 0x80A5, 0x4640);
-
-	/* Rx Controls */
-	bnx2x_cl45_write(bp, phy, MDIO_XS_DEVAD, 0x80FE, 0x01C4);
-	bnx2x_cl45_write(bp, phy, MDIO_XS_DEVAD, 0x80FD, 0x9249);
-	bnx2x_cl45_write(bp, phy, MDIO_XS_DEVAD, 0x80FC, 0x2015);
+	DP(NETIF_MSG_LINK,
+		 "bnx2x_8073_8727_external_rom_boot port %x:"
+		 "Download complete. fw version = 0x%x\n",
+		 port, fw_ver1);
 
-	/* Enable PLL sequencer  (use read-modify-write to set bit 13) */
-	bnx2x_cl45_read(bp, phy, MDIO_XS_DEVAD, MDIO_XS_PLL_SEQUENCER, &val);
-	val |= (1<<13);
-	bnx2x_cl45_write(bp, phy, MDIO_XS_DEVAD, MDIO_XS_PLL_SEQUENCER, val);
+	return rc;
 }
 
 /******************************************************************/
@@ -3514,8 +4106,6 @@ static u8 bnx2x_8073_config_init(struct
 
 	bnx2x_8073_set_pause_cl37(params, phy, vars);
 
-	bnx2x_8073_set_xaui_low_power_mode(bp, phy);
-
 	bnx2x_cl45_read(bp, phy,
 			MDIO_PMA_DEVAD, MDIO_PMA_REG_M8051_MSGOUT_REG, &tmp1);
 
@@ -3524,6 +4114,25 @@ static u8 bnx2x_8073_config_init(struct
 
 	DP(NETIF_MSG_LINK, "Before rom RX_ALARM(port1): 0x%x\n", tmp1);
 
+	/**
+	 * If this is forced speed, set to KR or KX (all other are not
+	 * supported)
+	 */
+	/* Swap polarity if required - Must be done only in non-1G mode */
+	if (params->lane_config & PORT_HW_CFG_SWAP_PHY_POLARITY_ENABLED) {
+		/* Configure the 8073 to swap _P and _N of the KR lines */
+		DP(NETIF_MSG_LINK, "Swapping polarity for the 8073\n");
+		/* 10G Rx/Tx and 1G Tx signal polarity swap */
+		bnx2x_cl45_read(bp, phy,
+				MDIO_PMA_DEVAD,
+				MDIO_PMA_REG_8073_OPT_DIGITAL_CTRL, &val);
+		bnx2x_cl45_write(bp, phy,
+				 MDIO_PMA_DEVAD,
+				 MDIO_PMA_REG_8073_OPT_DIGITAL_CTRL,
+				 (val | (3<<9)));
+	}
+
+
 	/* Enable CL37 BAM */
 	if (REG_RD(bp, params->shmem_base +
 			 offsetof(struct shmem_region, dev_info.
@@ -3730,8 +4339,32 @@ static u8 bnx2x_8073_read_status(struct
 	}
 
 	if (link_up) {
+		/* Swap polarity if required */
+		if (params->lane_config &
+		    PORT_HW_CFG_SWAP_PHY_POLARITY_ENABLED) {
+			/* Configure the 8073 to swap P and N of the KR lines */
+			bnx2x_cl45_read(bp, phy,
+					MDIO_XS_DEVAD,
+					MDIO_XS_REG_8073_RX_CTRL_PCIE, &val1);
+			/**
+			* Set bit 3 to invert Rx in 1G mode and clear this bit
+			* when it`s in 10G mode.
+			*/
+			if (vars->line_speed == SPEED_1000) {
+				DP(NETIF_MSG_LINK, "Swapping 1G polarity for"
+					      "the 8073\n");
+				val1 |= (1<<3);
+			} else
+				val1 &= ~(1<<3);
+
+			bnx2x_cl45_write(bp, phy,
+					 MDIO_XS_DEVAD,
+					 MDIO_XS_REG_8073_RX_CTRL_PCIE,
+					 val1);
+		}
 		bnx2x_ext_phy_10G_an_resolve(bp, phy, vars);
 		bnx2x_8073_resolve_fc(phy, params, vars);
+		vars->duplex = DUPLEX_FULL;
 	}
 	return link_up;
 }
@@ -3904,7 +4537,7 @@ static u8 bnx2x_8726_read_sfp_module_eep
 			      MDIO_PMA_REG_SFP_TWO_WIRE_CTRL, &val);
 		if ((val & MDIO_PMA_REG_SFP_TWO_WIRE_CTRL_STATUS_MASK) ==
 		    MDIO_PMA_REG_SFP_TWO_WIRE_STATUS_IDLE)
-			return 0;;
+			return 0;
 		msleep(1);
 	}
 	return -EINVAL;
@@ -3988,7 +4621,7 @@ static u8 bnx2x_8727_read_sfp_module_eep
 			      MDIO_PMA_REG_SFP_TWO_WIRE_CTRL, &val);
 		if ((val & MDIO_PMA_REG_SFP_TWO_WIRE_CTRL_STATUS_MASK) ==
 		    MDIO_PMA_REG_SFP_TWO_WIRE_STATUS_IDLE)
-			return 0;;
+			return 0;
 		msleep(1);
 	}
 
@@ -4478,6 +5111,7 @@ static u8 bnx2x_8706_8726_read_status(st
 		else
 			vars->line_speed = SPEED_10000;
 		bnx2x_ext_phy_resolve_fc(phy, params, vars);
+		vars->duplex = DUPLEX_FULL;
 	}
 	return link_up;
 }
@@ -5174,8 +5808,11 @@ static u8 bnx2x_8727_read_status(struct
 		DP(NETIF_MSG_LINK, "port %x: External link is down\n",
 			   params->port);
 	}
-	if (link_up)
+	if (link_up) {
 		bnx2x_ext_phy_resolve_fc(phy, params, vars);
+		vars->duplex = DUPLEX_FULL;
+		DP(NETIF_MSG_LINK, "duplex = 0x%x\n", vars->duplex);
+	}
 
 	if ((DUAL_MEDIA(params)) &&
 	    (phy->req_line_speed == SPEED_1000)) {
@@ -5291,10 +5928,26 @@ static void bnx2x_848xx_set_led(struct b
 			 MDIO_PMA_REG_8481_LED2_MASK,
 			 0x18);
 
+	/* Select activity source by Tx and Rx, as suggested by PHY AE */
 	bnx2x_cl45_write(bp, phy,
 			 MDIO_PMA_DEVAD,
 			 MDIO_PMA_REG_8481_LED3_MASK,
-			 0x0040);
+			 0x0006);
+
+	/* Select the closest activity blink rate to that in 10/100/1000 */
+	bnx2x_cl45_write(bp, phy,
+			MDIO_PMA_DEVAD,
+			MDIO_PMA_REG_8481_LED3_BLINK,
+			0);
+
+	bnx2x_cl45_read(bp, phy,
+			MDIO_PMA_DEVAD,
+			MDIO_PMA_REG_84823_CTL_LED_CTL_1, &val);
+	val |= MDIO_PMA_REG_84823_LED3_STRETCH_EN; /* stretch_en for LED3*/
+
+	bnx2x_cl45_write(bp, phy,
+			 MDIO_PMA_DEVAD,
+			 MDIO_PMA_REG_84823_CTL_LED_CTL_1, val);
 
 	/* 'Interrupt Mask' */
 	bnx2x_cl45_write(bp, phy,
@@ -5542,6 +6195,7 @@ static u8 bnx2x_848xx_read_status(struct
 	/* Check link 10G */
 	if (val2 & (1<<11)) {
 		vars->line_speed = SPEED_10000;
+		vars->duplex = DUPLEX_FULL;
 		link_up = 1;
 		bnx2x_ext_phy_10G_an_resolve(bp, phy, vars);
 	} else { /* Check Legacy speed link */
@@ -5821,6 +6475,18 @@ static void bnx2x_848xx_set_link_led(str
 					 MDIO_PMA_DEVAD,
 					 MDIO_PMA_REG_8481_LED1_MASK,
 					 0x80);
+
+			/* Tell LED3 to blink on source */
+			bnx2x_cl45_read(bp, phy,
+					MDIO_PMA_DEVAD,
+					MDIO_PMA_REG_8481_LINK_SIGNAL,
+					&val);
+			val &= ~(7<<6);
+			val |= (1<<6); /* A83B[8:6]= 1 */
+			bnx2x_cl45_write(bp, phy,
+					 MDIO_PMA_DEVAD,
+					 MDIO_PMA_REG_8481_LINK_SIGNAL,
+					 val);
 		}
 		break;
 	}
@@ -5905,6 +6571,7 @@ static u8 bnx2x_7101_read_status(struct
 				MDIO_AN_DEVAD, MDIO_AN_REG_MASTER_STATUS,
 				&val2);
 		vars->line_speed = SPEED_10000;
+		vars->duplex = DUPLEX_FULL;
 		DP(NETIF_MSG_LINK, "SFX7101 AN status 0x%x->Master=%x\n",
 			   val2, (val2 & (1<<14)));
 		bnx2x_ext_phy_10G_an_resolve(bp, phy, vars);
@@ -7021,10 +7688,13 @@ static u8 bnx2x_8073_common_init_phy(str
 	struct bnx2x_phy phy[PORT_MAX];
 	struct bnx2x_phy *phy_blk[PORT_MAX];
 	u16 val;
-	s8 port;
+	s8 port = 0;
 	s8 port_of_path = 0;
-
-	bnx2x_ext_phy_hw_reset(bp, 0);
+	u32 swap_val, swap_override;
+	swap_val = REG_RD(bp,  NIG_REG_PORT_SWAP);
+	swap_override = REG_RD(bp,  NIG_REG_STRAP_OVERRIDE);
+	port ^= (swap_val && swap_override);
+	bnx2x_ext_phy_hw_reset(bp, port);
 	/* PART1 - Reset both phys */
 	for (port = PORT_MAX - 1; port >= PORT_0; port--) {
 		u32 shmem_base, shmem2_base;
@@ -7079,7 +7749,6 @@ static u8 bnx2x_8073_common_init_phy(str
 
 	/* PART2 - Download firmware to both phys */
 	for (port = PORT_MAX - 1; port >= PORT_0; port--) {
-		u16 fw_ver1;
 		if (CHIP_IS_E2(bp))
 			port_of_path = 0;
 		else
@@ -7087,19 +7756,9 @@ static u8 bnx2x_8073_common_init_phy(str
 
 		DP(NETIF_MSG_LINK, "Loading spirom for phy address 0x%x\n",
 			   phy_blk[port]->addr);
-		bnx2x_8073_8727_external_rom_boot(bp, phy_blk[port],
-						  port_of_path);
-
-		bnx2x_cl45_read(bp, phy_blk[port],
-			      MDIO_PMA_DEVAD,
-			      MDIO_PMA_REG_ROM_VER1, &fw_ver1);
-		if (fw_ver1 == 0 || fw_ver1 == 0x4321) {
-			DP(NETIF_MSG_LINK,
-				 "bnx2x_8073_common_init_phy port %x:"
-				 "Download failed. fw version = 0x%x\n",
-				 port, fw_ver1);
+		if (bnx2x_8073_8727_external_rom_boot(bp, phy_blk[port],
+						      port_of_path))
 			return -EINVAL;
-		}
 
 		/* Only set bit 10 = 1 (Tx power down) */
 		bnx2x_cl45_read(bp, phy_blk[port],
@@ -7264,27 +7923,17 @@ static u8 bnx2x_8727_common_init_phy(str
 	}
 	/* PART2 - Download firmware to both phys */
 	for (port = PORT_MAX - 1; port >= PORT_0; port--) {
-		u16 fw_ver1;
 		 if (CHIP_IS_E2(bp))
 			port_of_path = 0;
 		else
 			port_of_path = port;
 		DP(NETIF_MSG_LINK, "Loading spirom for phy address 0x%x\n",
 			   phy_blk[port]->addr);
-		bnx2x_8073_8727_external_rom_boot(bp, phy_blk[port],
-						  port_of_path);
-		bnx2x_cl45_read(bp, phy_blk[port],
-			      MDIO_PMA_DEVAD,
-			      MDIO_PMA_REG_ROM_VER1, &fw_ver1);
-		if (fw_ver1 == 0 || fw_ver1 == 0x4321) {
-			DP(NETIF_MSG_LINK,
-				 "bnx2x_8727_common_init_phy port %x:"
-				 "Download failed. fw version = 0x%x\n",
-				 port, fw_ver1);
+		if (bnx2x_8073_8727_external_rom_boot(bp, phy_blk[port],
+						      port_of_path))
 			return -EINVAL;
-		}
-	}
 
+	}
 	return 0;
 }
 
@@ -7332,6 +7981,7 @@ u8 bnx2x_common_init_phy(struct bnx2x *b
 			 u32 shmem2_base_path[], u32 chip_id)
 {
 	u8 rc = 0;
+	u32 phy_ver;
 	u8 phy_index;
 	u32 ext_phy_type, ext_phy_config;
 	DP(NETIF_MSG_LINK, "Begin common phy init\n");
@@ -7339,6 +7989,16 @@ u8 bnx2x_common_init_phy(struct bnx2x *b
 	if (CHIP_REV_IS_EMUL(bp))
 		return 0;
 
+	/* Check if common init was already done */
+	phy_ver = REG_RD(bp, shmem_base_path[0] +
+			 offsetof(struct shmem_region,
+				  port_mb[PORT_0].ext_phy_fw_version));
+	if (phy_ver) {
+		DP(NETIF_MSG_LINK, "Not doing common init; phy ver is 0x%x\n",
+			       phy_ver);
+		return 0;
+	}
+
 	/* Read the ext_phy_type for arbitrary port(0) */
 	for (phy_index = EXT_PHY1; phy_index < MAX_PHYS;
 	      phy_index++) {
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/bnx2x/bnx2x_link.h linux-libre-2.6.38-gnu1/drivers/net/bnx2x/bnx2x_link.h
--- linux-libre-2.6.37-gnu1/drivers/net/bnx2x/bnx2x_link.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/bnx2x/bnx2x_link.h	2011-03-14 21:20:32.000000000 -0400
@@ -65,6 +65,22 @@
 #define FW_PARAM_MDIO_CTRL_OFFSET 16
 #define FW_PARAM_SET(phy_addr, phy_type, mdio_access) \
 	(phy_addr | phy_type | mdio_access << FW_PARAM_MDIO_CTRL_OFFSET)
+
+#define PFC_BRB_MAC_PAUSE_XOFF_THRESHOLD_PAUSEABLE		170
+#define PFC_BRB_MAC_PAUSE_XOFF_THRESHOLD_NON_PAUSEABLE		0
+
+#define PFC_BRB_MAC_PAUSE_XON_THRESHOLD_PAUSEABLE			250
+#define PFC_BRB_MAC_PAUSE_XON_THRESHOLD_NON_PAUSEABLE		0
+
+#define PFC_BRB_MAC_FULL_XOFF_THRESHOLD_PAUSEABLE			10
+#define PFC_BRB_MAC_FULL_XOFF_THRESHOLD_NON_PAUSEABLE		90
+
+#define PFC_BRB_MAC_FULL_XON_THRESHOLD_PAUSEABLE			50
+#define PFC_BRB_MAC_FULL_XON_THRESHOLD_NON_PAUSEABLE		250
+
+#define PFC_BRB_FULL_LB_XOFF_THRESHOLD				170
+#define PFC_BRB_FULL_LB_XON_THRESHOLD				250
+
 /***********************************************************/
 /*                         Structs                         */
 /***********************************************************/
@@ -216,6 +232,7 @@ struct link_params {
 
 	u32 feature_config_flags;
 #define FEATURE_CONFIG_OVERRIDE_PREEMPHASIS_ENABLED (1<<0)
+#define FEATURE_CONFIG_PFC_ENABLED		(1<<1)
 #define FEATURE_CONFIG_BC_SUPPORTS_OPT_MDL_VRFY	(1<<2)
 #define FEATURE_CONFIG_BC_SUPPORTS_DUAL_PHY_OPT_MDL_VRFY	(1<<3)
 	/* Will be populated during common init */
@@ -332,4 +349,43 @@ u8 bnx2x_phy_probe(struct link_params *p
 u8 bnx2x_fan_failure_det_req(struct bnx2x *bp, u32 shmem_base,
 			     u32 shmem2_base, u8 port);
 
+/* PFC port configuration params */
+struct bnx2x_nig_brb_pfc_port_params {
+	/* NIG */
+	u32 pause_enable;
+	u32 llfc_out_en;
+	u32 llfc_enable;
+	u32 pkt_priority_to_cos;
+	u32 rx_cos0_priority_mask;
+	u32 rx_cos1_priority_mask;
+	u32 llfc_high_priority_classes;
+	u32 llfc_low_priority_classes;
+	/* BRB */
+	u32 cos0_pauseable;
+	u32 cos1_pauseable;
+};
+
+/**
+ * Used to update the PFC attributes in EMAC, BMAC, NIG and BRB
+ * when link is already up
+ */
+void bnx2x_update_pfc(struct link_params *params,
+		      struct link_vars *vars,
+		      struct bnx2x_nig_brb_pfc_port_params *pfc_params);
+
+
+/* Used to configure the ETS to disable */
+void bnx2x_ets_disabled(struct link_params *params);
+
+/* Used to configure the ETS to BW limited */
+void bnx2x_ets_bw_limit(const struct link_params *params, const u32 cos0_bw,
+						const u32 cos1_bw);
+
+/* Used to configure the ETS to strict */
+u8 bnx2x_ets_strict(const struct link_params *params, const u8 strict_cos);
+
+/* Read pfc statistic*/
+void bnx2x_pfc_statistic(struct link_params *params, struct link_vars *vars,
+						 u32 pfc_frames_sent[2],
+						 u32 pfc_frames_received[2]);
 #endif /* BNX2X_LINK_H */
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/bnx2x/bnx2x_main.c linux-libre-2.6.38-gnu1/drivers/net/bnx2x/bnx2x_main.c
--- linux-libre-2.6.37-gnu1/drivers/net/bnx2x/bnx2x_main.c	2013-05-03 03:58:03.000000000 -0400
+++ linux-libre-2.6.38-gnu1/drivers/net/bnx2x/bnx2x_main.c	2013-05-03 01:58:06.000000000 -0400
@@ -55,6 +55,7 @@
 #include "bnx2x_init.h"
 #include "bnx2x_init_ops.h"
 #include "bnx2x_cmn.h"
+#include "bnx2x_dcb.h"
 #define bnx2x_init_block(bp, start, end) \
   return (printk(KERN_ERR "%s: Missing Free firmware\n", bp->dev->name),\
 	  -EINVAL)
@@ -118,6 +119,10 @@ MODULE_PARM_DESC(debug, " Default debug
 
 static struct workqueue_struct *bnx2x_wq;
 
+#ifdef BCM_CNIC
+static u8 ALL_ENODE_MACS[] = {0x01, 0x10, 0x18, 0x01, 0x00, 0x01};
+#endif
+
 enum bnx2x_board_type {
 	BCM57710 = 0,
 	BCM57711 = 1,
@@ -918,7 +923,7 @@ void bnx2x_panic_dump(struct bnx2x *bp)
 	       sp_sb_data.p_func.vf_valid);
 
 
-	for_each_queue(bp, i) {
+	for_each_eth_queue(bp, i) {
 		struct bnx2x_fastpath *fp = &bp->fp[i];
 		int loop;
 		struct hc_status_block_data_e2 sb_data_e2;
@@ -958,6 +963,10 @@ void bnx2x_panic_dump(struct bnx2x *bp)
 
 		/* host sb data */
 
+#ifdef BCM_CNIC
+		if (IS_FCOE_FP(fp))
+			continue;
+#endif
 		BNX2X_ERR("     run indexes (");
 		for (j = 0; j < HC_SB_MAX_SM; j++)
 			pr_cont("0x%x%s",
@@ -1026,7 +1035,7 @@ void bnx2x_panic_dump(struct bnx2x *bp)
 #ifdef BNX2X_STOP_ON_ERROR
 	/* Rings */
 	/* Rx */
-	for_each_queue(bp, i) {
+	for_each_rx_queue(bp, i) {
 		struct bnx2x_fastpath *fp = &bp->fp[i];
 
 		start = RX_BD(le16_to_cpu(*fp->rx_cons_sb) - 10);
@@ -1060,7 +1069,7 @@ void bnx2x_panic_dump(struct bnx2x *bp)
 	}
 
 	/* Tx */
-	for_each_queue(bp, i) {
+	for_each_tx_queue(bp, i) {
 		struct bnx2x_fastpath *fp = &bp->fp[i];
 
 		start = TX_BD(le16_to_cpu(*fp->tx_cons_sb) - 10);
@@ -1295,7 +1304,7 @@ void bnx2x_int_disable_sync(struct bnx2x
 #ifdef BCM_CNIC
 		offset++;
 #endif
-		for_each_queue(bp, i)
+		for_each_eth_queue(bp, i)
 			synchronize_irq(bp->msix_table[i + offset].vector);
 	} else
 		synchronize_irq(bp->pdev->irq);
@@ -1417,7 +1426,7 @@ irqreturn_t bnx2x_interrupt(int irq, voi
 		return IRQ_HANDLED;
 #endif
 
-	for_each_queue(bp, i) {
+	for_each_eth_queue(bp, i) {
 		struct bnx2x_fastpath *fp = &bp->fp[i];
 
 		mask = 0x2 << (fp->index + CNIC_CONTEXT_USE);
@@ -1962,13 +1971,22 @@ static void bnx2x_init_vn_minmax(struct
 		vn_max_rate = 0;
 
 	} else {
+		u32 maxCfg = bnx2x_extract_max_cfg(bp, vn_cfg);
+
 		vn_min_rate = ((vn_cfg & FUNC_MF_CFG_MIN_BW_MASK) >>
 				FUNC_MF_CFG_MIN_BW_SHIFT) * 100;
-		/* If min rate is zero - set it to 1 */
+		/* If fairness is enabled (not all min rates are zeroes) and
+		   if current min rate is zero - set it to 1.
+		   This is a requirement of the algorithm. */
 		if (bp->vn_weight_sum && (vn_min_rate == 0))
 			vn_min_rate = DEF_MIN_RATE;
-		vn_max_rate = ((vn_cfg & FUNC_MF_CFG_MAX_BW_MASK) >>
-				FUNC_MF_CFG_MAX_BW_SHIFT) * 100;
+
+		if (IS_MF_SI(bp))
+			/* maxCfg in percents of linkspeed */
+			vn_max_rate = (bp->link_vars.line_speed * maxCfg) / 100;
+		else
+			/* maxCfg is absolute in 100Mb units */
+			vn_max_rate = maxCfg * 100;
 	}
 
 	DP(NETIF_MSG_IFUP,
@@ -1994,7 +2012,8 @@ static void bnx2x_init_vn_minmax(struct
 		m_fair_vn.vn_credit_delta =
 			max_t(u32, (vn_min_rate * (T_FAIR_COEF /
 						   (8 * bp->vn_weight_sum))),
-			      (bp->cmng.fair_vars.fair_threshold * 2));
+			      (bp->cmng.fair_vars.fair_threshold +
+							MIN_ABOVE_THRESH));
 		DP(NETIF_MSG_IFUP, "m_fair_vn.vn_credit_delta %d\n",
 		   m_fair_vn.vn_credit_delta);
 	}
@@ -2023,13 +2042,28 @@ static int bnx2x_get_cmng_fns_mode(struc
 
 static void bnx2x_read_mf_cfg(struct bnx2x *bp)
 {
-	int vn;
+	int vn, n = (CHIP_MODE_IS_4_PORT(bp) ? 2 : 1);
 
 	if (BP_NOMCP(bp))
 		return; /* what should be the default bvalue in this case */
 
+	/* For 2 port configuration the absolute function number formula
+	 * is:
+	 *      abs_func = 2 * vn + BP_PORT + BP_PATH
+	 *
+	 *      and there are 4 functions per port
+	 *
+	 * For 4 port configuration it is
+	 *      abs_func = 4 * vn + 2 * BP_PORT + BP_PATH
+	 *
+	 *      and there are 2 functions per port
+	 */
 	for (vn = VN_0; vn < E1HVN_MAX; vn++) {
-		int /*abs*/func = 2*vn + BP_PORT(bp);
+		int /*abs*/func = n * (2 * vn + BP_PORT(bp)) + BP_PATH(bp);
+
+		if (func >= E1H_FUNC_MAX)
+			break;
+
 		bp->mf_config[vn] =
 			MF_CFG_RD(bp, func_mf_config[func].config);
 	}
@@ -2055,8 +2089,9 @@ static void bnx2x_cmng_fns_init(struct b
 		bnx2x_calc_vn_weight_sum(bp);
 
 		/* calculate and set min-max rate for each vn */
-		for (vn = VN_0; vn < E1HVN_MAX; vn++)
-			bnx2x_init_vn_minmax(bp, vn);
+		if (bp->port.pmf)
+			for (vn = VN_0; vn < E1HVN_MAX; vn++)
+				bnx2x_init_vn_minmax(bp, vn);
 
 		/* always enable rate shaping and fairness */
 		bp->cmng.flags.cmng_enables |=
@@ -2125,13 +2160,6 @@ static void bnx2x_link_attn(struct bnx2x
 			bnx2x_stats_handle(bp, STATS_EVENT_LINK_UP);
 	}
 
-	/* indicate link status only if link status actually changed */
-	if (prev_link_status != bp->link_vars.link_status)
-		bnx2x_link_report(bp);
-
-	if (IS_MF(bp))
-		bnx2x_link_sync_notify(bp);
-
 	if (bp->link_vars.link_up && bp->link_vars.line_speed) {
 		int cmng_fns = bnx2x_get_cmng_fns_mode(bp);
 
@@ -2143,6 +2171,13 @@ static void bnx2x_link_attn(struct bnx2x
 			DP(NETIF_MSG_IFUP,
 			   "single function mode without fairness\n");
 	}
+
+	if (IS_MF(bp))
+		bnx2x_link_sync_notify(bp);
+
+	/* indicate link status only if link status actually changed */
+	if (prev_link_status != bp->link_vars.link_status)
+		bnx2x_link_report(bp);
 }
 
 void bnx2x__link_status_update(struct bnx2x *bp)
@@ -2235,6 +2270,15 @@ u32 bnx2x_fw_command(struct bnx2x *bp, u
 	return rc;
 }
 
+static u8 stat_counter_valid(struct bnx2x *bp, struct bnx2x_fastpath *fp)
+{
+#ifdef BCM_CNIC
+	if (IS_FCOE_FP(fp) && IS_MF(bp))
+		return false;
+#endif
+	return true;
+}
+
 /* must be called under rtnl_lock */
 static void bnx2x_rxq_set_mac_filters(struct bnx2x *bp, u16 cl_id, u32 filters)
 {
@@ -2245,19 +2289,30 @@ static void bnx2x_rxq_set_mac_filters(st
 	u8 accp_all_ucast = 0, accp_all_bcast = 0, accp_all_mcast = 0;
 	u8 unmatched_unicast = 0;
 
+	if (filters & BNX2X_ACCEPT_UNMATCHED_UCAST)
+		unmatched_unicast = 1;
+
 	if (filters & BNX2X_PROMISCUOUS_MODE) {
 		/* promiscious - accept all, drop none */
 		drop_all_ucast = drop_all_bcast = drop_all_mcast = 0;
 		accp_all_ucast = accp_all_bcast = accp_all_mcast = 1;
+		if (IS_MF_SI(bp)) {
+			/*
+			 * SI mode defines to accept in promiscuos mode
+			 * only unmatched packets
+			 */
+			unmatched_unicast = 1;
+			accp_all_ucast = 0;
+		}
 	}
 	if (filters & BNX2X_ACCEPT_UNICAST) {
 		/* accept matched ucast */
 		drop_all_ucast = 0;
 	}
-	if (filters & BNX2X_ACCEPT_MULTICAST) {
+	if (filters & BNX2X_ACCEPT_MULTICAST)
 		/* accept matched mcast */
 		drop_all_mcast = 0;
-	}
+
 	if (filters & BNX2X_ACCEPT_ALL_UNICAST) {
 		/* accept all mcast */
 		drop_all_ucast = 0;
@@ -2369,7 +2424,7 @@ static inline u16 bnx2x_get_cl_flags(str
 	/* calculate queue flags */
 	flags |= QUEUE_FLG_CACHE_ALIGN;
 	flags |= QUEUE_FLG_HC;
-	flags |= IS_MF(bp) ? QUEUE_FLG_OV : 0;
+	flags |= IS_MF_SD(bp) ? QUEUE_FLG_OV : 0;
 
 	flags |= QUEUE_FLG_VLAN;
 	DP(NETIF_MSG_IFUP, "vlan removal enabled\n");
@@ -2377,7 +2432,8 @@ static inline u16 bnx2x_get_cl_flags(str
 	if (!fp->disable_tpa)
 		flags |= QUEUE_FLG_TPA;
 
-	flags |= QUEUE_FLG_STATS;
+	flags = stat_counter_valid(bp, fp) ?
+			(flags | QUEUE_FLG_STATS) : (flags & ~QUEUE_FLG_STATS);
 
 	return flags;
 }
@@ -2437,7 +2493,10 @@ static void bnx2x_pf_rx_cl_prep(struct b
 	rxq_init->cache_line_log = BNX2X_RX_ALIGN_SHIFT;
 	rxq_init->fw_sb_id = fp->fw_sb_id;
 
-	rxq_init->sb_cq_index = U_SB_ETH_RX_CQ_INDEX;
+	if (IS_FCOE_FP(fp))
+		rxq_init->sb_cq_index = HC_SP_INDEX_ETH_FCOE_RX_CQ_CONS;
+	else
+		rxq_init->sb_cq_index = U_SB_ETH_RX_CQ_INDEX;
 
 	rxq_init->cid = HW_CID(bp, fp->cid);
 
@@ -2457,6 +2516,12 @@ static void bnx2x_pf_tx_cl_prep(struct b
 	txq_init->sb_cq_index = C_SB_ETH_TX_CQ_INDEX;
 	txq_init->traffic_type = LLFC_TRAFFIC_TYPE_NW;
 	txq_init->fw_sb_id = fp->fw_sb_id;
+
+	if (IS_FCOE_FP(fp)) {
+		txq_init->sb_cq_index = HC_SP_INDEX_ETH_FCOE_TX_CQ_CONS;
+		txq_init->traffic_type = LLFC_TRAFFIC_TYPE_FCOE;
+	}
+
 	txq_init->hc_rate = bp->tx_ticks ? (1000000 / bp->tx_ticks) : 0;
 }
 
@@ -2570,6 +2635,26 @@ static void bnx2x_e1h_enable(struct bnx2
 	 */
 }
 
+/* called due to MCP event (on pmf):
+ *	reread new bandwidth configuration
+ *	configure FW
+ *	notify others function about the change
+ */
+static inline void bnx2x_config_mf_bw(struct bnx2x *bp)
+{
+	if (bp->link_vars.link_up) {
+		bnx2x_cmng_fns_init(bp, true, CMNG_FNS_MINMAX);
+		bnx2x_link_sync_notify(bp);
+	}
+	storm_memset_cmng(bp, &bp->cmng, BP_PORT(bp));
+}
+
+static inline void bnx2x_set_mf_bw(struct bnx2x *bp)
+{
+	bnx2x_config_mf_bw(bp);
+	bnx2x_fw_command(bp, DRV_MSG_CODE_SET_MF_BW_ACK, 0);
+}
+
 static void bnx2x_dcc_event(struct bnx2x *bp, u32 dcc_event)
 {
 	DP(BNX2X_MSG_MCP, "dcc_event 0x%x\n", dcc_event);
@@ -2595,10 +2680,7 @@ static void bnx2x_dcc_event(struct bnx2x
 		dcc_event &= ~DRV_STATUS_DCC_DISABLE_ENABLE_PF;
 	}
 	if (dcc_event & DRV_STATUS_DCC_BANDWIDTH_ALLOCATION) {
-
-		bnx2x_cmng_fns_init(bp, true, CMNG_FNS_MINMAX);
-		bnx2x_link_sync_notify(bp);
-		storm_memset_cmng(bp, &bp->cmng, BP_PORT(bp));
+		bnx2x_config_mf_bw(bp);
 		dcc_event &= ~DRV_STATUS_DCC_BANDWIDTH_ALLOCATION;
 	}
 
@@ -3019,10 +3101,20 @@ static inline void bnx2x_attn_int_deasse
 			if (val & DRV_STATUS_DCC_EVENT_MASK)
 				bnx2x_dcc_event(bp,
 					    (val & DRV_STATUS_DCC_EVENT_MASK));
+
+			if (val & DRV_STATUS_SET_MF_BW)
+				bnx2x_set_mf_bw(bp);
+
 			bnx2x__link_status_update(bp);
 			if ((bp->port.pmf == 0) && (val & DRV_STATUS_PMF))
 				bnx2x_pmf_update(bp);
 
+			if (bp->port.pmf &&
+			    (val & DRV_STATUS_DCBX_NEGOTIATION_RESULTS) &&
+				bp->dcbx_enabled > 0)
+				/* start dcbx state machine */
+				bnx2x_dcbx_set_params(bp,
+					BNX2X_DCBX_STATE_NEG_RECEIVED);
 		} else if (attn & BNX2X_MC_ASSERT_BITS) {
 
 			BNX2X_ERR("MC assert!\n");
@@ -3063,7 +3155,6 @@ static inline void bnx2x_attn_int_deasse
 #define LOAD_COUNTER_MASK	(((u32)0x1 << LOAD_COUNTER_BITS) - 1)
 #define RESET_DONE_FLAG_MASK	(~LOAD_COUNTER_MASK)
 #define RESET_DONE_FLAG_SHIFT	LOAD_COUNTER_BITS
-#define CHIP_PARITY_SUPPORTED(bp)   (CHIP_IS_E1(bp) || CHIP_IS_E1H(bp))
 
 /*
  * should be run under rtnl lock
@@ -3438,7 +3529,7 @@ static void bnx2x_attn_int_deasserted(st
 	   try to handle this event */
 	bnx2x_acquire_alr(bp);
 
-	if (bnx2x_chk_parity_attn(bp)) {
+	if (CHIP_PARITY_ENABLED(bp) && bnx2x_chk_parity_attn(bp)) {
 		bp->recovery_state = BNX2X_RECOVERY_INIT;
 		bnx2x_set_reset_in_progress(bp);
 		schedule_delayed_work(&bp->reset_task, 0);
@@ -3634,11 +3725,23 @@ static void bnx2x_eq_int(struct bnx2x *b
 #ifdef BCM_CNIC
 			if (!bnx2x_cnic_handle_cfc_del(bp, cid, elem))
 				goto next_spqe;
+			if (cid == BNX2X_FCOE_ETH_CID)
+				bnx2x_fcoe(bp, state) = BNX2X_FP_STATE_CLOSED;
+			else
 #endif
-			bnx2x_fp(bp, cid, state) =
+				bnx2x_fp(bp, cid, state) =
 						BNX2X_FP_STATE_CLOSED;
 
 			goto next_spqe;
+
+		case EVENT_RING_OPCODE_STOP_TRAFFIC:
+			DP(NETIF_MSG_IFUP, "got STOP TRAFFIC\n");
+			bnx2x_dcbx_set_params(bp, BNX2X_DCBX_STATE_TX_PAUSED);
+			goto next_spqe;
+		case EVENT_RING_OPCODE_START_TRAFFIC:
+			DP(NETIF_MSG_IFUP, "got START TRAFFIC\n");
+			bnx2x_dcbx_set_params(bp, BNX2X_DCBX_STATE_TX_RELEASED);
+			goto next_spqe;
 		}
 
 		switch (opcode | bp->state) {
@@ -3711,7 +3814,13 @@ static void bnx2x_sp_task(struct work_st
 
 	/* SP events: STAT_QUERY and others */
 	if (status & BNX2X_DEF_SB_IDX) {
+#ifdef BCM_CNIC
+		struct bnx2x_fastpath *fp = bnx2x_fcoe_fp(bp);
 
+		if ((!NO_FCOE(bp)) &&
+			(bnx2x_has_rx_work(fp) || bnx2x_has_tx_work(fp)))
+			napi_schedule(&bnx2x_fcoe(bp, napi));
+#endif
 		/* Handle EQ completions */
 		bnx2x_eq_int(bp);
 
@@ -4094,7 +4203,7 @@ void bnx2x_update_coalesce(struct bnx2x
 {
 	int i;
 
-	for_each_queue(bp, i)
+	for_each_eth_queue(bp, i)
 		bnx2x_update_coalesce_sb(bp, bp->fp[i].fw_sb_id,
 					 bp->rx_ticks, bp->tx_ticks);
 }
@@ -4142,13 +4251,16 @@ static void bnx2x_init_ind_table(struct
 	for (i = 0; i < TSTORM_INDIRECTION_TABLE_SIZE; i++)
 		REG_WR8(bp, BAR_TSTRORM_INTMEM +
 			TSTORM_INDIRECTION_TABLE_OFFSET(func) + i,
-			bp->fp->cl_id + (i % bp->num_queues));
+			bp->fp->cl_id + (i % (bp->num_queues -
+				NONE_ETH_CONTEXT_USE)));
 }
 
 void bnx2x_set_storm_rx_mode(struct bnx2x *bp)
 {
 	int mode = bp->rx_mode;
+	int port = BP_PORT(bp);
 	u16 cl_id;
+	u32 def_q_filters = 0;
 
 	/* All but management unicast packets should pass to the host as well */
 	u32 llh_mask =
@@ -4159,30 +4271,56 @@ void bnx2x_set_storm_rx_mode(struct bnx2
 
 	switch (mode) {
 	case BNX2X_RX_MODE_NONE: /* no Rx */
-		cl_id = BP_L_ID(bp);
-		bnx2x_rxq_set_mac_filters(bp, cl_id, BNX2X_ACCEPT_NONE);
+		def_q_filters = BNX2X_ACCEPT_NONE;
+#ifdef BCM_CNIC
+		if (!NO_FCOE(bp)) {
+			cl_id = bnx2x_fcoe(bp, cl_id);
+			bnx2x_rxq_set_mac_filters(bp, cl_id, BNX2X_ACCEPT_NONE);
+		}
+#endif
 		break;
 
 	case BNX2X_RX_MODE_NORMAL:
-		cl_id = BP_L_ID(bp);
-		bnx2x_rxq_set_mac_filters(bp, cl_id,
-			BNX2X_ACCEPT_UNICAST |
-			BNX2X_ACCEPT_BROADCAST |
-			BNX2X_ACCEPT_MULTICAST);
+		def_q_filters |= BNX2X_ACCEPT_UNICAST | BNX2X_ACCEPT_BROADCAST |
+				BNX2X_ACCEPT_MULTICAST;
+#ifdef BCM_CNIC
+		if (!NO_FCOE(bp)) {
+			cl_id = bnx2x_fcoe(bp, cl_id);
+			bnx2x_rxq_set_mac_filters(bp, cl_id,
+						  BNX2X_ACCEPT_UNICAST |
+						  BNX2X_ACCEPT_MULTICAST);
+		}
+#endif
 		break;
 
 	case BNX2X_RX_MODE_ALLMULTI:
-		cl_id = BP_L_ID(bp);
-		bnx2x_rxq_set_mac_filters(bp, cl_id,
-			BNX2X_ACCEPT_UNICAST |
-			BNX2X_ACCEPT_BROADCAST |
-			BNX2X_ACCEPT_ALL_MULTICAST);
+		def_q_filters |= BNX2X_ACCEPT_UNICAST | BNX2X_ACCEPT_BROADCAST |
+				BNX2X_ACCEPT_ALL_MULTICAST;
+#ifdef BCM_CNIC
+		/*
+		 *  Prevent duplication of multicast packets by configuring FCoE
+		 *  L2 Client to receive only matched unicast frames.
+		 */
+		if (!NO_FCOE(bp)) {
+			cl_id = bnx2x_fcoe(bp, cl_id);
+			bnx2x_rxq_set_mac_filters(bp, cl_id,
+						  BNX2X_ACCEPT_UNICAST);
+		}
+#endif
 		break;
 
 	case BNX2X_RX_MODE_PROMISC:
-		cl_id = BP_L_ID(bp);
-		bnx2x_rxq_set_mac_filters(bp, cl_id, BNX2X_PROMISCUOUS_MODE);
-
+		def_q_filters |= BNX2X_PROMISCUOUS_MODE;
+#ifdef BCM_CNIC
+		/*
+		 *  Prevent packets duplication by configuring DROP_ALL for FCoE
+		 *  L2 Client.
+		 */
+		if (!NO_FCOE(bp)) {
+			cl_id = bnx2x_fcoe(bp, cl_id);
+			bnx2x_rxq_set_mac_filters(bp, cl_id, BNX2X_ACCEPT_NONE);
+		}
+#endif
 		/* pass management unicast packets as well */
 		llh_mask |= NIG_LLH0_BRB1_DRV_MASK_REG_LLH0_BRB1_DRV_MASK_UNCST;
 		break;
@@ -4192,20 +4330,24 @@ void bnx2x_set_storm_rx_mode(struct bnx2
 		break;
 	}
 
+	cl_id = BP_L_ID(bp);
+	bnx2x_rxq_set_mac_filters(bp, cl_id, def_q_filters);
+
 	REG_WR(bp,
-	       BP_PORT(bp) ? NIG_REG_LLH1_BRB1_DRV_MASK :
-			     NIG_REG_LLH0_BRB1_DRV_MASK,
-	       llh_mask);
+	       (port ? NIG_REG_LLH1_BRB1_DRV_MASK :
+		       NIG_REG_LLH0_BRB1_DRV_MASK), llh_mask);
 
 	DP(NETIF_MSG_IFUP, "rx mode %d\n"
 		"drop_ucast 0x%x\ndrop_mcast 0x%x\ndrop_bcast 0x%x\n"
-		"accp_ucast 0x%x\naccp_mcast 0x%x\naccp_bcast 0x%x\n", mode,
+		"accp_ucast 0x%x\naccp_mcast 0x%x\naccp_bcast 0x%x\n"
+		"unmatched_ucast 0x%x\n", mode,
 		bp->mac_filters.ucast_drop_all,
 		bp->mac_filters.mcast_drop_all,
 		bp->mac_filters.bcast_drop_all,
 		bp->mac_filters.ucast_accept_all,
 		bp->mac_filters.mcast_accept_all,
-		bp->mac_filters.bcast_accept_all
+		bp->mac_filters.bcast_accept_all,
+		bp->mac_filters.unmatched_unicast
 	);
 
 	storm_memset_mac_filters(bp, &bp->mac_filters, BP_FUNC(bp));
@@ -4229,6 +4371,15 @@ static void bnx2x_init_internal_common(s
 			bp->mf_mode);
 	}
 
+	if (IS_MF_SI(bp))
+		/*
+		 * In switch independent mode, the TSTORM needs to accept
+		 * packets that failed classification, since approximate match
+		 * mac addresses aren't written to NIG LLH
+		 */
+		REG_WR8(bp, BAR_TSTRORM_INTMEM +
+			    TSTORM_ACCEPT_CLASSIFY_FAILED_OFFSET, 2);
+
 	/* Zero this manually as its initialization is
 	   currently missing in the initTool */
 	for (i = 0; i < (USTORM_AGG_DATA_SIZE >> 2); i++)
@@ -4244,6 +4395,7 @@ static void bnx2x_init_internal_common(s
 static void bnx2x_init_internal_port(struct bnx2x *bp)
 {
 	/* port */
+	bnx2x_dcb_init_intmem_pfc(bp);
 }
 
 static void bnx2x_init_internal(struct bnx2x *bp, u32 load_code)
@@ -4305,9 +4457,11 @@ void bnx2x_nic_init(struct bnx2x *bp, u3
 {
 	int i;
 
-	for_each_queue(bp, i)
+	for_each_eth_queue(bp, i)
 		bnx2x_init_fp_sb(bp, i);
 #ifdef BCM_CNIC
+	if (!NO_FCOE(bp))
+		bnx2x_init_fcoe_fp(bp);
 
 	bnx2x_init_sb(bp, bp->cnic_sb_mapping,
 		      BNX2X_VF_ID_INVALID, false,
@@ -4616,7 +4770,7 @@ static int bnx2x_int_mem_test(struct bnx
 	return 0; /* OK */
 }
 
-static void enable_blocks_attention(struct bnx2x *bp)
+static void bnx2x_enable_blocks_attention(struct bnx2x *bp)
 {
 	REG_WR(bp, PXP_REG_PXP_INT_MASK_0, 0);
 	if (CHIP_IS_E2(bp))
@@ -4670,53 +4824,9 @@ static void enable_blocks_attention(stru
 	REG_WR(bp, CDU_REG_CDU_INT_MASK, 0);
 	REG_WR(bp, DMAE_REG_DMAE_INT_MASK, 0);
 /*	REG_WR(bp, MISC_REG_MISC_INT_MASK, 0); */
-	REG_WR(bp, PBF_REG_PBF_INT_MASK, 0X18);		/* bit 3,4 masked */
-}
-
-static const struct {
-	u32 addr;
-	u32 mask;
-} bnx2x_parity_mask[] = {
-	{PXP_REG_PXP_PRTY_MASK,		0x3ffffff},
-	{PXP2_REG_PXP2_PRTY_MASK_0,	0xffffffff},
-	{PXP2_REG_PXP2_PRTY_MASK_1,	0x7f},
-	{HC_REG_HC_PRTY_MASK,		0x7},
-	{MISC_REG_MISC_PRTY_MASK,	0x1},
-	{QM_REG_QM_PRTY_MASK,		0x0},
-	{DORQ_REG_DORQ_PRTY_MASK,	0x0},
-	{GRCBASE_UPB + PB_REG_PB_PRTY_MASK, 0x0},
-	{GRCBASE_XPB + PB_REG_PB_PRTY_MASK, 0x0},
-	{SRC_REG_SRC_PRTY_MASK,		0x4}, /* bit 2 */
-	{CDU_REG_CDU_PRTY_MASK,		0x0},
-	{CFC_REG_CFC_PRTY_MASK,		0x0},
-	{DBG_REG_DBG_PRTY_MASK,		0x0},
-	{DMAE_REG_DMAE_PRTY_MASK,	0x0},
-	{BRB1_REG_BRB1_PRTY_MASK,	0x0},
-	{PRS_REG_PRS_PRTY_MASK,		(1<<6)},/* bit 6 */
-	{TSDM_REG_TSDM_PRTY_MASK,	0x18},	/* bit 3,4 */
-	{CSDM_REG_CSDM_PRTY_MASK,	0x8},	/* bit 3 */
-	{USDM_REG_USDM_PRTY_MASK,	0x38},  /* bit 3,4,5 */
-	{XSDM_REG_XSDM_PRTY_MASK,	0x8},	/* bit 3 */
-	{TSEM_REG_TSEM_PRTY_MASK_0,	0x0},
-	{TSEM_REG_TSEM_PRTY_MASK_1,	0x0},
-	{USEM_REG_USEM_PRTY_MASK_0,	0x0},
-	{USEM_REG_USEM_PRTY_MASK_1,	0x0},
-	{CSEM_REG_CSEM_PRTY_MASK_0,	0x0},
-	{CSEM_REG_CSEM_PRTY_MASK_1,	0x0},
-	{XSEM_REG_XSEM_PRTY_MASK_0,	0x0},
-	{XSEM_REG_XSEM_PRTY_MASK_1,	0x0}
-};
-
-static void enable_blocks_parity(struct bnx2x *bp)
-{
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(bnx2x_parity_mask); i++)
-		REG_WR(bp, bnx2x_parity_mask[i].addr,
-			bnx2x_parity_mask[i].mask);
+	REG_WR(bp, PBF_REG_PBF_INT_MASK, 0x18);		/* bit 3,4 masked */
 }
 
-
 static void bnx2x_reset_common(struct bnx2x *bp)
 {
 	/* reset_common */
@@ -4944,7 +5054,7 @@ static int bnx2x_init_hw_common(struct b
 		memset(&ilt_cli, 0, sizeof(struct ilt_client_info));
 		memset(&ilt, 0, sizeof(struct bnx2x_ilt));
 
-		/* initalize dummy TM client */
+		/* initialize dummy TM client */
 		ilt_cli.start = 0;
 		ilt_cli.end = ILT_NUM_PAGE_ENTRIES - 1;
 		ilt_cli.client_num = ILT_CLIENT_TM;
@@ -5045,12 +5155,12 @@ static int bnx2x_init_hw_common(struct b
 	REG_WR(bp, PRS_REG_NIC_MODE, 1);
 #endif
 	if (!CHIP_IS_E1(bp))
-		REG_WR(bp, PRS_REG_E1HOV_MODE, IS_MF(bp));
+		REG_WR(bp, PRS_REG_E1HOV_MODE, IS_MF_SD(bp));
 
 	if (CHIP_IS_E2(bp)) {
 		/* Bit-map indicating which L2 hdrs may appear after the
 		   basic Ethernet header */
-		int has_ovlan = IS_MF(bp);
+		int has_ovlan = IS_MF_SD(bp);
 		REG_WR(bp, PRS_REG_HDRS_AFTER_BASIC, (has_ovlan ? 7 : 6));
 		REG_WR(bp, PRS_REG_MUST_HAVE_HDRS, (has_ovlan ? 1 : 0));
 	}
@@ -5084,7 +5194,7 @@ static int bnx2x_init_hw_common(struct b
 	bnx2x_init_block(bp, PBF_BLOCK, COMMON_STAGE);
 
 	if (CHIP_IS_E2(bp)) {
-		int has_ovlan = IS_MF(bp);
+		int has_ovlan = IS_MF_SD(bp);
 		REG_WR(bp, PBF_REG_HDRS_AFTER_BASIC, (has_ovlan ? 7 : 6));
 		REG_WR(bp, PBF_REG_MUST_HAVE_HDRS, (has_ovlan ? 1 : 0));
 	}
@@ -5161,12 +5271,12 @@ static int bnx2x_init_hw_common(struct b
 	bnx2x_init_block(bp, NIG_BLOCK, COMMON_STAGE);
 	if (!CHIP_IS_E1(bp)) {
 		REG_WR(bp, NIG_REG_LLH_MF_MODE, IS_MF(bp));
-		REG_WR(bp, NIG_REG_LLH_E1HOV_MODE, IS_MF(bp));
+		REG_WR(bp, NIG_REG_LLH_E1HOV_MODE, IS_MF_SD(bp));
 	}
 	if (CHIP_IS_E2(bp)) {
 		/* Bit-map indicating which L2 hdrs may appear after the
 		   basic Ethernet header */
-		REG_WR(bp, NIG_REG_P0_HDRS_AFTER_BASIC, (IS_MF(bp) ? 7 : 6));
+		REG_WR(bp, NIG_REG_P0_HDRS_AFTER_BASIC, (IS_MF_SD(bp) ? 7 : 6));
 	}
 
 	if (CHIP_REV_IS_SLOW(bp))
@@ -5203,18 +5313,14 @@ static int bnx2x_init_hw_common(struct b
 		}
 	}
 
-	bp->port.need_hw_lock = bnx2x_hw_lock_required(bp,
-						       bp->common.shmem_base,
-						       bp->common.shmem2_base);
-
 	bnx2x_setup_fan_failure_detection(bp);
 
 	/* clear PXP2 attentions */
 	REG_RD(bp, PXP2_REG_PXP2_INT_STS_CLR_0);
 
-	enable_blocks_attention(bp);
-	if (CHIP_PARITY_SUPPORTED(bp))
-		enable_blocks_parity(bp);
+	bnx2x_enable_blocks_attention(bp);
+	if (CHIP_PARITY_ENABLED(bp))
+		bnx2x_enable_blocks_parity(bp);
 
 	if (!BP_NOMCP(bp)) {
 		/* In E2 2-PORT mode, same ext phy is used for the two paths */
@@ -5367,8 +5473,10 @@ static int bnx2x_init_hw_port(struct bnx
 	 *  - SF mode: bits 3-7 are masked. only bits 0-2 are in use
 	 *  - MF mode: bit 3 is masked. bits 0-2 are in use as in SF
 	 *             bits 4-7 are used for "per vn group attention" */
-	REG_WR(bp, MISC_REG_AEU_MASK_ATTN_FUNC_0 + port*4,
-	       (IS_MF(bp) ? 0xF7 : 0x7));
+	val = IS_MF(bp) ? 0xF7 : 0x7;
+	/* Enable DCBX attention for all but E1 */
+	val |= CHIP_IS_E1(bp) ? 0 : 0x10;
+	REG_WR(bp, MISC_REG_AEU_MASK_ATTN_FUNC_0 + port*4, val);
 
 	bnx2x_init_block(bp, PXPCS_BLOCK, init_stage);
 	bnx2x_init_block(bp, EMAC0_BLOCK, init_stage);
@@ -5383,7 +5491,7 @@ static int bnx2x_init_hw_port(struct bnx
 	if (!CHIP_IS_E1(bp)) {
 		/* 0x2 disable mf_ov, 0x1 enable */
 		REG_WR(bp, NIG_REG_LLH0_BRB1_DRV_MASK_MF + port*4,
-		       (IS_MF(bp) ? 0x1 : 0x2));
+		       (IS_MF_SD(bp) ? 0x1 : 0x2));
 
 		if (CHIP_IS_E2(bp)) {
 			val = 0;
@@ -5408,9 +5516,6 @@ static int bnx2x_init_hw_port(struct bnx
 
 	bnx2x_init_block(bp, MCP_BLOCK, init_stage);
 	bnx2x_init_block(bp, DMAE_BLOCK, init_stage);
-	bp->port.need_hw_lock = bnx2x_hw_lock_required(bp,
-						       bp->common.shmem_base,
-						       bp->common.shmem2_base);
 	if (bnx2x_fan_failure_det_req(bp, bp->common.shmem_base,
 				      bp->common.shmem2_base, port)) {
 		u32 reg_addr = (port ? MISC_REG_AEU_ENABLE1_FUNC_1_OUT_0 :
@@ -5813,6 +5918,15 @@ void bnx2x_free_mem(struct bnx2x *bp)
 	/* fastpath */
 	/* Common */
 	for_each_queue(bp, i) {
+#ifdef BCM_CNIC
+		/* FCoE client uses default status block */
+		if (IS_FCOE_IDX(i)) {
+			union host_hc_status_block *sb =
+				&bnx2x_fp(bp, i, status_blk);
+			memset(sb, 0, sizeof(union host_hc_status_block));
+			bnx2x_fp(bp, i, status_blk_mapping) = 0;
+		} else {
+#endif
 		/* status blocks */
 		if (CHIP_IS_E2(bp))
 			BNX2X_PCI_FREE(bnx2x_fp(bp, i, status_blk.e2_sb),
@@ -5822,9 +5936,12 @@ void bnx2x_free_mem(struct bnx2x *bp)
 			BNX2X_PCI_FREE(bnx2x_fp(bp, i, status_blk.e1x_sb),
 				       bnx2x_fp(bp, i, status_blk_mapping),
 				       sizeof(struct host_hc_status_block_e1x));
+#ifdef BCM_CNIC
+		}
+#endif
 	}
 	/* Rx */
-	for_each_queue(bp, i) {
+	for_each_rx_queue(bp, i) {
 
 		/* fastpath rx rings: rx_buf rx_desc rx_comp */
 		BNX2X_FREE(bnx2x_fp(bp, i, rx_buf_ring));
@@ -5844,7 +5961,7 @@ void bnx2x_free_mem(struct bnx2x *bp)
 			       BCM_PAGE_SIZE * NUM_RX_SGE_PAGES);
 	}
 	/* Tx */
-	for_each_queue(bp, i) {
+	for_each_tx_queue(bp, i) {
 
 		/* fastpath tx rings: tx_buf tx_desc */
 		BNX2X_FREE(bnx2x_fp(bp, i, tx_buf_ring));
@@ -5928,15 +6045,20 @@ int bnx2x_alloc_mem(struct bnx2x *bp)
 		union host_hc_status_block *sb = &bnx2x_fp(bp, i, status_blk);
 		bnx2x_fp(bp, i, bp) = bp;
 		/* status blocks */
-		if (CHIP_IS_E2(bp))
-			BNX2X_PCI_ALLOC(sb->e2_sb,
-				&bnx2x_fp(bp, i, status_blk_mapping),
-				sizeof(struct host_hc_status_block_e2));
-		else
-			BNX2X_PCI_ALLOC(sb->e1x_sb,
-				&bnx2x_fp(bp, i, status_blk_mapping),
-				sizeof(struct host_hc_status_block_e1x));
-
+#ifdef BCM_CNIC
+		if (!IS_FCOE_IDX(i)) {
+#endif
+			if (CHIP_IS_E2(bp))
+				BNX2X_PCI_ALLOC(sb->e2_sb,
+				    &bnx2x_fp(bp, i, status_blk_mapping),
+				    sizeof(struct host_hc_status_block_e2));
+			else
+				BNX2X_PCI_ALLOC(sb->e1x_sb,
+				    &bnx2x_fp(bp, i, status_blk_mapping),
+				    sizeof(struct host_hc_status_block_e1x));
+#ifdef BCM_CNIC
+		}
+#endif
 		set_sb_shortcuts(bp, i);
 	}
 	/* Rx */
@@ -6052,7 +6174,7 @@ static int bnx2x_func_stop(struct bnx2x
  * @param cam_offset offset in a CAM to use
  * @param is_bcast is the set MAC a broadcast address (for E1 only)
  */
-static void bnx2x_set_mac_addr_gen(struct bnx2x *bp, int set, u8 *mac,
+static void bnx2x_set_mac_addr_gen(struct bnx2x *bp, int set, const u8 *mac,
 				   u32 cl_bit_vec, u8 cam_offset,
 				   u8 is_bcast)
 {
@@ -6167,6 +6289,70 @@ static u8 bnx2x_e1h_cam_offset(struct bn
 		return BP_VN(bp) * 32  + rel_offset;
 }
 
+/**
+ *  LLH CAM line allocations: currently only iSCSI and ETH macs are
+ *  relevant. In addition, current implementation is tuned for a
+ *  single ETH MAC.
+ *
+ *  When multiple unicast ETH MACs PF configuration in switch
+ *  independent mode is required (NetQ, multiple netdev MACs,
+ *  etc.), consider better utilisation of 16 per function MAC
+ *  entries in the LLH memory.
+ */
+enum {
+	LLH_CAM_ISCSI_ETH_LINE = 0,
+	LLH_CAM_ETH_LINE,
+	LLH_CAM_MAX_PF_LINE = NIG_REG_LLH1_FUNC_MEM_SIZE
+};
+
+static void bnx2x_set_mac_in_nig(struct bnx2x *bp,
+			  int set,
+			  unsigned char *dev_addr,
+			  int index)
+{
+	u32 wb_data[2];
+	u32 mem_offset, ena_offset, mem_index;
+	/**
+	 * indexes mapping:
+	 * 0..7 - goes to MEM
+	 * 8..15 - goes to MEM2
+	 */
+
+	if (!IS_MF_SI(bp) || index > LLH_CAM_MAX_PF_LINE)
+		return;
+
+	/* calculate memory start offset according to the mapping
+	 * and index in the memory */
+	if (index < NIG_LLH_FUNC_MEM_MAX_OFFSET) {
+		mem_offset = BP_PORT(bp) ? NIG_REG_LLH1_FUNC_MEM :
+					   NIG_REG_LLH0_FUNC_MEM;
+		ena_offset = BP_PORT(bp) ? NIG_REG_LLH1_FUNC_MEM_ENABLE :
+					   NIG_REG_LLH0_FUNC_MEM_ENABLE;
+		mem_index = index;
+	} else {
+		mem_offset = BP_PORT(bp) ? NIG_REG_P1_LLH_FUNC_MEM2 :
+					   NIG_REG_P0_LLH_FUNC_MEM2;
+		ena_offset = BP_PORT(bp) ? NIG_REG_P1_LLH_FUNC_MEM2_ENABLE :
+					   NIG_REG_P0_LLH_FUNC_MEM2_ENABLE;
+		mem_index = index - NIG_LLH_FUNC_MEM_MAX_OFFSET;
+	}
+
+	if (set) {
+		/* LLH_FUNC_MEM is a u64 WB register */
+		mem_offset += 8*mem_index;
+
+		wb_data[0] = ((dev_addr[2] << 24) | (dev_addr[3] << 16) |
+			      (dev_addr[4] <<  8) |  dev_addr[5]);
+		wb_data[1] = ((dev_addr[0] <<  8) |  dev_addr[1]);
+
+		REG_WR_DMAE(bp, mem_offset, wb_data, 2);
+	}
+
+	/* enable/disable the entry */
+	REG_WR(bp, ena_offset + 4*mem_index, set);
+
+}
+
 void bnx2x_set_eth_mac(struct bnx2x *bp, int set)
 {
 	u8 cam_offset = (CHIP_IS_E1(bp) ? (BP_PORT(bp) ? 32 : 0) :
@@ -6176,9 +6362,13 @@ void bnx2x_set_eth_mac(struct bnx2x *bp,
 	bnx2x_set_mac_addr_gen(bp, set, bp->dev->dev_addr,
 			       (1 << bp->fp->cl_id), cam_offset , 0);
 
+	bnx2x_set_mac_in_nig(bp, set, bp->dev->dev_addr, LLH_CAM_ETH_LINE);
+
 	if (CHIP_IS_E1(bp)) {
 		/* broadcast MAC */
-		u8 bcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+		static const u8 bcast[ETH_ALEN] = {
+			0xff, 0xff, 0xff, 0xff, 0xff, 0xff
+		};
 		bnx2x_set_mac_addr_gen(bp, set, bcast, 0, cam_offset + 1, 1);
 	}
 }
@@ -6280,12 +6470,59 @@ static int bnx2x_set_iscsi_eth_mac_addr(
 {
 	u8 cam_offset = (CHIP_IS_E1(bp) ? ((BP_PORT(bp) ? 32 : 0) + 2) :
 			 bnx2x_e1h_cam_offset(bp, CAM_ISCSI_ETH_LINE));
-	u32 iscsi_l2_cl_id = BNX2X_ISCSI_ETH_CL_ID;
+	u32 iscsi_l2_cl_id = BNX2X_ISCSI_ETH_CL_ID +
+		BP_E1HVN(bp) * NONE_ETH_CONTEXT_USE;
 	u32 cl_bit_vec = (1 << iscsi_l2_cl_id);
 
 	/* Send a SET_MAC ramrod */
 	bnx2x_set_mac_addr_gen(bp, set, bp->iscsi_mac, cl_bit_vec,
 			       cam_offset, 0);
+
+	bnx2x_set_mac_in_nig(bp, set, bp->iscsi_mac, LLH_CAM_ISCSI_ETH_LINE);
+
+	return 0;
+}
+
+/**
+ * Set FCoE L2 MAC(s) at the next enties in the CAM after the
+ * ETH MAC(s). This function will wait until the ramdord
+ * completion returns.
+ *
+ * @param bp driver handle
+ * @param set set or clear the CAM entry
+ *
+ * @return 0 if cussess, -ENODEV if ramrod doesn't return.
+ */
+int bnx2x_set_fip_eth_mac_addr(struct bnx2x *bp, int set)
+{
+	u32 cl_bit_vec = (1 << bnx2x_fcoe(bp, cl_id));
+	/**
+	 * CAM allocation for E1H
+	 * eth unicasts: by func number
+	 * iscsi: by func number
+	 * fip unicast: by func number
+	 * fip multicast: by func number
+	 */
+	bnx2x_set_mac_addr_gen(bp, set, bp->fip_mac,
+		cl_bit_vec, bnx2x_e1h_cam_offset(bp, CAM_FIP_ETH_LINE), 0);
+
+	return 0;
+}
+
+int bnx2x_set_all_enode_macs(struct bnx2x *bp, int set)
+{
+	u32 cl_bit_vec = (1 << bnx2x_fcoe(bp, cl_id));
+
+	/**
+	 * CAM allocation for E1H
+	 * eth unicasts: by func number
+	 * iscsi: by func number
+	 * fip unicast: by func number
+	 * fip multicast: by func number
+	 */
+	bnx2x_set_mac_addr_gen(bp, set, ALL_ENODE_MACS,	cl_bit_vec,
+		bnx2x_e1h_cam_offset(bp, CAM_FIP_MCAST_LINE), 0);
+
 	return 0;
 }
 #endif
@@ -6303,6 +6540,8 @@ static void bnx2x_fill_cl_init_data(stru
 	data->general.statistics_counter_id = params->rxq_params.stat_id;
 	data->general.statistics_en_flg =
 		(params->rxq_params.flags & QUEUE_FLG_STATS) ? 1 : 0;
+	data->general.is_fcoe_flg =
+		(params->ramrod_params.flags & CLIENT_IS_FCOE) ? 1 : 0;
 	data->general.activate_flg = activate;
 	data->general.sp_client_id = params->rxq_params.spcl_id;
 
@@ -6371,7 +6610,9 @@ static void bnx2x_fill_cl_init_data(stru
 	data->fc.safc_group_num = params->txq_params.cos;
 	data->fc.safc_group_en_flg =
 		(params->txq_params.flags & QUEUE_FLG_COS) ? 1 : 0;
-	data->fc.traffic_type = LLFC_TRAFFIC_TYPE_NW;
+	data->fc.traffic_type =
+		(params->ramrod_params.flags & CLIENT_IS_FCOE) ?
+		LLFC_TRAFFIC_TYPE_FCOE : LLFC_TRAFFIC_TYPE_NW;
 }
 
 static inline void bnx2x_set_ctx_validation(struct eth_context *cxt, u32 cid)
@@ -6470,7 +6711,7 @@ static int __devinit bnx2x_set_int_mode(
 		bnx2x_enable_msi(bp);
 		/* falling through... */
 	case INT_MODE_INTx:
-		bp->num_queues = 1;
+		bp->num_queues = 1 + NONE_ETH_CONTEXT_USE;
 		DP(NETIF_MSG_IFUP, "set number of queues to 1\n");
 		break;
 	default:
@@ -6493,8 +6734,8 @@ static int __devinit bnx2x_set_int_mode(
 					  "enable MSI-X (%d), "
 					  "set number of queues to %d\n",
 				   bp->num_queues,
-				   1);
-			bp->num_queues = 1;
+				   1 + NONE_ETH_CONTEXT_USE);
+			bp->num_queues = 1 + NONE_ETH_CONTEXT_USE;
 
 			if (!(bp->flags & DISABLE_MSI_FLAG))
 				bnx2x_enable_msi(bp);
@@ -6615,7 +6856,9 @@ int bnx2x_setup_client(struct bnx2x *bp,
 	struct bnx2x_client_init_params params = { {0} };
 	int rc;
 
-	bnx2x_ack_sb(bp, fp->igu_sb_id, USTORM_ID, 0,
+	/* reset IGU state skip FCoE L2 queue */
+	if (!IS_FCOE_FP(fp))
+		bnx2x_ack_sb(bp, fp->igu_sb_id, USTORM_ID, 0,
 			     IGU_INT_ENABLE, 0);
 
 	params.ramrod_params.pstate = &fp->state;
@@ -6623,6 +6866,12 @@ int bnx2x_setup_client(struct bnx2x *bp,
 	params.ramrod_params.index = fp->index;
 	params.ramrod_params.cid = fp->cid;
 
+#ifdef BCM_CNIC
+	if (IS_FCOE_FP(fp))
+		params.ramrod_params.flags |= CLIENT_IS_FCOE;
+
+#endif
+
 	if (is_leading)
 		params.ramrod_params.flags |= CLIENT_IS_LEADING_RSS;
 
@@ -6707,7 +6956,7 @@ static void bnx2x_reset_func(struct bnx2
 	REG_WR8(bp, BAR_USTRORM_INTMEM + USTORM_FUNC_EN_OFFSET(func), 0);
 
 	/* FP SBs */
-	for_each_queue(bp, i) {
+	for_each_eth_queue(bp, i) {
 		struct bnx2x_fastpath *fp = &bp->fp[i];
 		REG_WR8(bp,
 			BAR_CSTRORM_INTMEM +
@@ -6827,6 +7076,20 @@ static void bnx2x_reset_chip(struct bnx2
 	}
 }
 
+#ifdef BCM_CNIC
+static inline void bnx2x_del_fcoe_eth_macs(struct bnx2x *bp)
+{
+	if (bp->flags & FCOE_MACS_SET) {
+		if (!IS_MF_SD(bp))
+			bnx2x_set_fip_eth_mac_addr(bp, 0);
+
+		bnx2x_set_all_enode_macs(bp, 0);
+
+		bp->flags &= ~FCOE_MACS_SET;
+	}
+}
+#endif
+
 void bnx2x_chip_cleanup(struct bnx2x *bp, int unload_mode)
 {
 	int port = BP_PORT(bp);
@@ -6834,7 +7097,7 @@ void bnx2x_chip_cleanup(struct bnx2x *bp
 	int i, cnt, rc;
 
 	/* Wait until tx fastpath tasks complete */
-	for_each_queue(bp, i) {
+	for_each_tx_queue(bp, i) {
 		struct bnx2x_fastpath *fp = &bp->fp[i];
 
 		cnt = 1000;
@@ -6874,13 +7137,7 @@ void bnx2x_chip_cleanup(struct bnx2x *bp
 	}
 
 #ifdef BCM_CNIC
-	/* Clear iSCSI L2 MAC */
-	mutex_lock(&bp->cnic_mutex);
-	if (bp->cnic_flags & BNX2X_CNIC_FLAG_MAC_SET) {
-		bnx2x_set_iscsi_eth_mac_addr(bp, 0);
-		bp->cnic_flags &= ~BNX2X_CNIC_FLAG_MAC_SET;
-	}
-	mutex_unlock(&bp->cnic_mutex);
+	bnx2x_del_fcoe_eth_macs(bp);
 #endif
 
 	if (unload_mode == UNLOAD_NORMAL)
@@ -7733,7 +7990,7 @@ static void __devinit bnx2x_get_igu_cam_
 	bp->igu_sb_cnt = 0;
 	if (CHIP_INT_MODE_IS_BC(bp)) {
 		bp->igu_sb_cnt = min_t(u8, FP_SB_MAX_E1x,
-				       bp->l2_cid_count);
+				       NUM_IGU_SB_REQUIRED(bp->l2_cid_count));
 
 		bp->igu_base_sb = (CHIP_MODE_IS_4_PORT(bp) ? pfid : vn) *
 			FP_SB_MAX_E1x;
@@ -7764,7 +8021,8 @@ static void __devinit bnx2x_get_igu_cam_
 			}
 		}
 	}
-	bp->igu_sb_cnt = min_t(u8, bp->igu_sb_cnt, bp->l2_cid_count);
+	bp->igu_sb_cnt = min_t(u8, bp->igu_sb_cnt,
+				   NUM_IGU_SB_REQUIRED(bp->l2_cid_count));
 	if (bp->igu_sb_cnt == 0)
 		BNX2X_ERR("CAM configuration error\n");
 }
@@ -8073,9 +8331,8 @@ static void __devinit bnx2x_set_mac_buf(
 static void __devinit bnx2x_get_port_hwinfo(struct bnx2x *bp)
 {
 	int port = BP_PORT(bp);
-	u32 val, val2;
 	u32 config;
-	u32 ext_phy_type, ext_phy_config;;
+	u32 ext_phy_type, ext_phy_config;
 
 	bp->link_params.bp = bp;
 	bp->link_params.port = port;
@@ -8133,24 +8390,83 @@ static void __devinit bnx2x_get_port_hwi
 		bp->mdio.prtad =
 			XGXS_EXT_PHY_ADDR(ext_phy_config);
 
-	val2 = SHMEM_RD(bp, dev_info.port_hw_config[port].mac_upper);
-	val = SHMEM_RD(bp, dev_info.port_hw_config[port].mac_lower);
-	bnx2x_set_mac_buf(bp->dev->dev_addr, val, val2);
+	/*
+	 * Check if hw lock is required to access MDC/MDIO bus to the PHY(s)
+	 * In MF mode, it is set to cover self test cases
+	 */
+	if (IS_MF(bp))
+		bp->port.need_hw_lock = 1;
+	else
+		bp->port.need_hw_lock = bnx2x_hw_lock_required(bp,
+							bp->common.shmem_base,
+							bp->common.shmem2_base);
+}
+
+static void __devinit bnx2x_get_mac_hwinfo(struct bnx2x *bp)
+{
+	u32 val, val2;
+	int func = BP_ABS_FUNC(bp);
+	int port = BP_PORT(bp);
+
+	if (BP_NOMCP(bp)) {
+		BNX2X_ERROR("warning: random MAC workaround active\n");
+		random_ether_addr(bp->dev->dev_addr);
+	} else if (IS_MF(bp)) {
+		val2 = MF_CFG_RD(bp, func_mf_config[func].mac_upper);
+		val = MF_CFG_RD(bp, func_mf_config[func].mac_lower);
+		if ((val2 != FUNC_MF_CFG_UPPERMAC_DEFAULT) &&
+		    (val != FUNC_MF_CFG_LOWERMAC_DEFAULT))
+			bnx2x_set_mac_buf(bp->dev->dev_addr, val, val2);
+
+#ifdef BCM_CNIC
+		/* iSCSI NPAR MAC */
+		if (IS_MF_SI(bp)) {
+			u32 cfg = MF_CFG_RD(bp, func_ext_config[func].func_cfg);
+			if (cfg & MACP_FUNC_CFG_FLAGS_ISCSI_OFFLOAD) {
+				val2 = MF_CFG_RD(bp, func_ext_config[func].
+						     iscsi_mac_addr_upper);
+				val = MF_CFG_RD(bp, func_ext_config[func].
+						    iscsi_mac_addr_lower);
+				bnx2x_set_mac_buf(bp->iscsi_mac, val, val2);
+			}
+		}
+#endif
+	} else {
+		/* in SF read MACs from port configuration */
+		val2 = SHMEM_RD(bp, dev_info.port_hw_config[port].mac_upper);
+		val = SHMEM_RD(bp, dev_info.port_hw_config[port].mac_lower);
+		bnx2x_set_mac_buf(bp->dev->dev_addr, val, val2);
+
+#ifdef BCM_CNIC
+		val2 = SHMEM_RD(bp, dev_info.port_hw_config[port].
+				    iscsi_mac_upper);
+		val = SHMEM_RD(bp, dev_info.port_hw_config[port].
+				   iscsi_mac_lower);
+		bnx2x_set_mac_buf(bp->iscsi_mac, val, val2);
+#endif
+	}
+
 	memcpy(bp->link_params.mac_addr, bp->dev->dev_addr, ETH_ALEN);
 	memcpy(bp->dev->perm_addr, bp->dev->dev_addr, ETH_ALEN);
 
 #ifdef BCM_CNIC
-	val2 = SHMEM_RD(bp, dev_info.port_hw_config[port].iscsi_mac_upper);
-	val = SHMEM_RD(bp, dev_info.port_hw_config[port].iscsi_mac_lower);
-	bnx2x_set_mac_buf(bp->iscsi_mac, val, val2);
+	/* Inform the upper layers about FCoE MAC */
+	if (!CHIP_IS_E1x(bp)) {
+		if (IS_MF_SD(bp))
+			memcpy(bp->fip_mac, bp->dev->dev_addr,
+			       sizeof(bp->fip_mac));
+		else
+			memcpy(bp->fip_mac, bp->iscsi_mac,
+			       sizeof(bp->fip_mac));
+	}
 #endif
 }
 
 static int __devinit bnx2x_get_hwinfo(struct bnx2x *bp)
 {
-	int func = BP_ABS_FUNC(bp);
-	int vn;
-	u32 val, val2;
+	int /*abs*/func = BP_ABS_FUNC(bp);
+	int vn, port;
+	u32 val = 0;
 	int rc = 0;
 
 	bnx2x_get_common_hwinfo(bp);
@@ -8160,7 +8476,8 @@ static int __devinit bnx2x_get_hwinfo(st
 
 		bp->igu_dsb_id = DEF_SB_IGU_ID;
 		bp->igu_base_sb = 0;
-		bp->igu_sb_cnt = min_t(u8, FP_SB_MAX_E1x, bp->l2_cid_count);
+		bp->igu_sb_cnt = min_t(u8, FP_SB_MAX_E1x,
+				       NUM_IGU_SB_REQUIRED(bp->l2_cid_count));
 	} else {
 		bp->common.int_block = INT_BLOCK_IGU;
 		val = REG_RD(bp, IGU_REG_BLOCK_CONFIGURATION);
@@ -8183,44 +8500,99 @@ static int __devinit bnx2x_get_hwinfo(st
 	bp->mf_ov = 0;
 	bp->mf_mode = 0;
 	vn = BP_E1HVN(bp);
+	port = BP_PORT(bp);
+
 	if (!CHIP_IS_E1(bp) && !BP_NOMCP(bp)) {
+		DP(NETIF_MSG_PROBE,
+			    "shmem2base 0x%x, size %d, mfcfg offset %d\n",
+			    bp->common.shmem2_base, SHMEM2_RD(bp, size),
+			    (u32)offsetof(struct shmem2_region, mf_cfg_addr));
 		if (SHMEM2_HAS(bp, mf_cfg_addr))
 			bp->common.mf_cfg_base = SHMEM2_RD(bp, mf_cfg_addr);
 		else
 			bp->common.mf_cfg_base = bp->common.shmem_base +
 				offsetof(struct shmem_region, func_mb) +
 				E1H_FUNC_MAX * sizeof(struct drv_func_mb);
-		bp->mf_config[vn] =
-			MF_CFG_RD(bp, func_mf_config[func].config);
+		/*
+		 * get mf configuration:
+		 * 1. existance of MF configuration
+		 * 2. MAC address must be legal (check only upper bytes)
+		 *    for  Switch-Independent mode;
+		 *    OVLAN must be legal for Switch-Dependent mode
+		 * 3. SF_MODE configures specific MF mode
+		 */
+		if (bp->common.mf_cfg_base != SHMEM_MF_CFG_ADDR_NONE) {
+			/* get mf configuration */
+			val = SHMEM_RD(bp,
+				       dev_info.shared_feature_config.config);
+			val &= SHARED_FEAT_CFG_FORCE_SF_MODE_MASK;
+
+			switch (val) {
+			case SHARED_FEAT_CFG_FORCE_SF_MODE_SWITCH_INDEPT:
+				val = MF_CFG_RD(bp, func_mf_config[func].
+						mac_upper);
+				/* check for legal mac (upper bytes)*/
+				if (val != 0xffff) {
+					bp->mf_mode = MULTI_FUNCTION_SI;
+					bp->mf_config[vn] = MF_CFG_RD(bp,
+						   func_mf_config[func].config);
+				} else
+					DP(NETIF_MSG_PROBE, "illegal MAC "
+							    "address for SI\n");
+				break;
+			case SHARED_FEAT_CFG_FORCE_SF_MODE_MF_ALLOWED:
+				/* get OV configuration */
+				val = MF_CFG_RD(bp,
+					func_mf_config[FUNC_0].e1hov_tag);
+				val &= FUNC_MF_CFG_E1HOV_TAG_MASK;
+
+				if (val != FUNC_MF_CFG_E1HOV_TAG_DEFAULT) {
+					bp->mf_mode = MULTI_FUNCTION_SD;
+					bp->mf_config[vn] = MF_CFG_RD(bp,
+						func_mf_config[func].config);
+				} else
+					DP(NETIF_MSG_PROBE, "illegal OV for "
+							    "SD\n");
+				break;
+			default:
+				/* Unknown configuration: reset mf_config */
+				bp->mf_config[vn] = 0;
+				DP(NETIF_MSG_PROBE, "Unkown MF mode 0x%x\n",
+				   val);
+			}
+		}
 
-		val = (MF_CFG_RD(bp, func_mf_config[FUNC_0].e1hov_tag) &
-		       FUNC_MF_CFG_E1HOV_TAG_MASK);
-		if (val != FUNC_MF_CFG_E1HOV_TAG_DEFAULT)
-			bp->mf_mode = 1;
 		BNX2X_DEV_INFO("%s function mode\n",
 			       IS_MF(bp) ? "multi" : "single");
 
-		if (IS_MF(bp)) {
-			val = (MF_CFG_RD(bp, func_mf_config[func].
-								e1hov_tag) &
-			       FUNC_MF_CFG_E1HOV_TAG_MASK);
+		switch (bp->mf_mode) {
+		case MULTI_FUNCTION_SD:
+			val = MF_CFG_RD(bp, func_mf_config[func].e1hov_tag) &
+			      FUNC_MF_CFG_E1HOV_TAG_MASK;
 			if (val != FUNC_MF_CFG_E1HOV_TAG_DEFAULT) {
 				bp->mf_ov = val;
-				BNX2X_DEV_INFO("MF OV for func %d is %d "
-					       "(0x%04x)\n",
-					       func, bp->mf_ov, bp->mf_ov);
+				BNX2X_DEV_INFO("MF OV for func %d is %d"
+					       " (0x%04x)\n", func,
+					       bp->mf_ov, bp->mf_ov);
 			} else {
-				BNX2X_ERROR("No valid MF OV for func %d,"
-					    "  aborting\n", func);
+				BNX2X_ERR("No valid MF OV for func %d,"
+					  "  aborting\n", func);
 				rc = -EPERM;
 			}
-		} else {
-			if (BP_VN(bp)) {
-				BNX2X_ERROR("VN %d in single function mode,"
-					    "  aborting\n", BP_E1HVN(bp));
+			break;
+		case MULTI_FUNCTION_SI:
+			BNX2X_DEV_INFO("func %d is in MF "
+				       "switch-independent mode\n", func);
+			break;
+		default:
+			if (vn) {
+				BNX2X_ERR("VN %d in single function mode,"
+					  "  aborting\n", vn);
 				rc = -EPERM;
 			}
+			break;
 		}
+
 	}
 
 	/* adjust igu_sb_cnt to MF for E1x */
@@ -8245,32 +8617,8 @@ static int __devinit bnx2x_get_hwinfo(st
 		BNX2X_DEV_INFO("fw_seq 0x%08x\n", bp->fw_seq);
 	}
 
-	if (IS_MF(bp)) {
-		val2 = MF_CFG_RD(bp, func_mf_config[func].mac_upper);
-		val = MF_CFG_RD(bp,  func_mf_config[func].mac_lower);
-		if ((val2 != FUNC_MF_CFG_UPPERMAC_DEFAULT) &&
-		    (val != FUNC_MF_CFG_LOWERMAC_DEFAULT)) {
-			bp->dev->dev_addr[0] = (u8)(val2 >> 8 & 0xff);
-			bp->dev->dev_addr[1] = (u8)(val2 & 0xff);
-			bp->dev->dev_addr[2] = (u8)(val >> 24 & 0xff);
-			bp->dev->dev_addr[3] = (u8)(val >> 16 & 0xff);
-			bp->dev->dev_addr[4] = (u8)(val >> 8  & 0xff);
-			bp->dev->dev_addr[5] = (u8)(val & 0xff);
-			memcpy(bp->link_params.mac_addr, bp->dev->dev_addr,
-			       ETH_ALEN);
-			memcpy(bp->dev->perm_addr, bp->dev->dev_addr,
-			       ETH_ALEN);
-		}
-
-		return rc;
-	}
-
-	if (BP_NOMCP(bp)) {
-		/* only supposed to happen on emulation/FPGA */
-		BNX2X_ERROR("warning: random MAC workaround active\n");
-		random_ether_addr(bp->dev->dev_addr);
-		memcpy(bp->dev->perm_addr, bp->dev->dev_addr, ETH_ALEN);
-	}
+	/* Get MAC addresses */
+	bnx2x_get_mac_hwinfo(bp);
 
 	return rc;
 }
@@ -8379,13 +8727,6 @@ static int __devinit bnx2x_init_bp(struc
 		dev_err(&bp->pdev->dev, "MCP disabled, "
 					"must load devices in order!\n");
 
-	/* Set multi queue mode */
-	if ((multi_mode != ETH_RSS_MODE_DISABLED) &&
-	    ((int_mode == INT_MODE_INTx) || (int_mode == INT_MODE_MSI))) {
-		dev_err(&bp->pdev->dev, "Multi disabled since int_mode "
-					"requested is not MSI-X\n");
-		multi_mode = ETH_RSS_MODE_DISABLED;
-	}
 	bp->multi_mode = multi_mode;
 	bp->int_mode = int_mode;
 
@@ -8424,6 +8765,9 @@ static int __devinit bnx2x_init_bp(struc
 	bp->timer.data = (unsigned long) bp;
 	bp->timer.function = bnx2x_timer;
 
+	bnx2x_dcbx_set_state(bp, true, BNX2X_DCBX_ENABLED_ON_NEG_ON);
+	bnx2x_dcbx_init_params(bp);
+
 	return rc;
 }
 
@@ -8626,6 +8970,7 @@ static const struct net_device_ops bnx2x
 	.ndo_open		= bnx2x_open,
 	.ndo_stop		= bnx2x_close,
 	.ndo_start_xmit		= bnx2x_start_xmit,
+	.ndo_select_queue	= bnx2x_select_queue,
 	.ndo_set_multicast_list	= bnx2x_set_rx_mode,
 	.ndo_set_mac_address	= bnx2x_change_mac_addr,
 	.ndo_validate_addr	= eth_validate_addr,
@@ -8758,7 +9103,7 @@ static int __devinit bnx2x_init_dev(stru
 	dev->netdev_ops = &bnx2x_netdev_ops;
 	bnx2x_set_ethtool_ops(dev);
 	dev->features |= NETIF_F_SG;
-	dev->features |= NETIF_F_HW_CSUM;
+	dev->features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
 	if (bp->flags & USING_DAC_FLAG)
 		dev->features |= NETIF_F_HIGHDMA;
 	dev->features |= (NETIF_F_TSO | NETIF_F_TSO_ECN);
@@ -8766,12 +9111,16 @@ static int __devinit bnx2x_init_dev(stru
 	dev->features |= (NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX);
 
 	dev->vlan_features |= NETIF_F_SG;
-	dev->vlan_features |= NETIF_F_HW_CSUM;
+	dev->vlan_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
 	if (bp->flags & USING_DAC_FLAG)
 		dev->vlan_features |= NETIF_F_HIGHDMA;
 	dev->vlan_features |= (NETIF_F_TSO | NETIF_F_TSO_ECN);
 	dev->vlan_features |= NETIF_F_TSO6;
 
+#ifdef BCM_DCB
+	dev->dcbnl_ops = &bnx2x_dcbnl_ops;
+#endif
+
 	/* get_port_hwinfo() will set prtad and mmds properly */
 	bp->mdio.prtad = MDIO_PRTAD_NONE;
 	bp->mdio.mmds = 0;
@@ -9005,7 +9354,7 @@ static int __devinit bnx2x_init_one(stru
 		return -ENODEV;
 	}
 
-	cid_count += CNIC_CONTEXT_USE;
+	cid_count += NONE_ETH_CONTEXT_USE + CNIC_CONTEXT_USE;
 
 	/* dev zeroed in init_etherdev */
 	dev = alloc_etherdev_mq(sizeof(*bp), cid_count);
@@ -9034,11 +9383,12 @@ static int __devinit bnx2x_init_one(stru
 	/* calc qm_cid_count */
 	bp->qm_cid_count = bnx2x_set_qm_cid_count(bp, cid_count);
 
-	rc = register_netdev(dev);
-	if (rc) {
-		dev_err(&pdev->dev, "Cannot register net device\n");
-		goto init_one_exit;
-	}
+#ifdef BCM_CNIC
+	/* disable FCOE L2 queue for E1x*/
+	if (CHIP_IS_E1x(bp))
+		bp->flags |= NO_FCOE_FLAG;
+
+#endif
 
 	/* Configure interupt mode: try to enable MSI-X/MSI if
 	 * needed, set bp->num_queues appropriately.
@@ -9048,6 +9398,21 @@ static int __devinit bnx2x_init_one(stru
 	/* Add all NAPI objects */
 	bnx2x_add_all_napi(bp);
 
+	rc = register_netdev(dev);
+	if (rc) {
+		dev_err(&pdev->dev, "Cannot register net device\n");
+		goto init_one_exit;
+	}
+
+#ifdef BCM_CNIC
+	if (!NO_FCOE(bp)) {
+		/* Add storage MAC address */
+		rtnl_lock();
+		dev_addr_add(bp->dev, bp->fip_mac, NETDEV_HW_ADDR_T_SAN);
+		rtnl_unlock();
+	}
+#endif
+
 	bnx2x_get_pcie_width_speed(bp, &pcie_width, &pcie_speed);
 
 	netdev_info(dev, "%s (%c%d) PCI-E x%d %s found at mem %lx,"
@@ -9091,14 +9456,29 @@ static void __devexit bnx2x_remove_one(s
 	}
 	bp = netdev_priv(dev);
 
+#ifdef BCM_CNIC
+	/* Delete storage MAC address */
+	if (!NO_FCOE(bp)) {
+		rtnl_lock();
+		dev_addr_del(bp->dev, bp->fip_mac, NETDEV_HW_ADDR_T_SAN);
+		rtnl_unlock();
+	}
+#endif
+
 	unregister_netdev(dev);
 
 	/* Delete all NAPI objects */
 	bnx2x_del_all_napi(bp);
 
+	/* Power on: we can't let PCI layer write to us while we are in D3 */
+	bnx2x_set_power_state(bp, PCI_D0);
+
 	/* Disable MSI/MSI-X */
 	bnx2x_disable_msi(bp);
 
+	/* Power off */
+	bnx2x_set_power_state(bp, PCI_D3hot);
+
 	/* Make sure RESET task is not scheduled before continuing */
 	cancel_delayed_work_sync(&bp->reset_task);
 
@@ -9140,7 +9520,7 @@ static int bnx2x_eeh_nic_unload(struct b
 	/* Free SKBs, SGEs, TPA pool and driver internals */
 	bnx2x_free_skbs(bp);
 
-	for_each_queue(bp, i)
+	for_each_rx_queue(bp, i)
 		bnx2x_free_rx_sge_range(bp, bp->fp + i, NUM_RX_SGE);
 
 	bnx2x_free_mem(bp);
@@ -9367,7 +9747,8 @@ static void bnx2x_cnic_sp_post(struct bn
 				break;
 			else
 				atomic_dec(&bp->spq_left);
-		} else if (type == ISCSI_CONNECTION_TYPE) {
+		} else if ((type == ISCSI_CONNECTION_TYPE) ||
+			   (type == FCOE_CONNECTION_TYPE)) {
 			if (bp->cnic_spq_pending >=
 			    bp->cnic_eth_dev.max_kwqe_pending)
 				break;
@@ -9514,6 +9895,9 @@ static int bnx2x_drv_ctl(struct net_devi
 	case DRV_CTL_START_L2_CMD: {
 		u32 cli = ctl->data.ring.client_id;
 
+		/* Clear FCoE FIP and ALL ENODE MACs addresses first */
+		bnx2x_del_fcoe_eth_macs(bp);
+
 		/* Set iSCSI MAC address */
 		bnx2x_set_iscsi_eth_mac_addr(bp, 1);
 
@@ -9635,10 +10019,6 @@ static int bnx2x_unregister_cnic(struct
 	struct cnic_eth_dev *cp = &bp->cnic_eth_dev;
 
 	mutex_lock(&bp->cnic_mutex);
-	if (bp->cnic_flags & BNX2X_CNIC_FLAG_MAC_SET) {
-		bp->cnic_flags &= ~BNX2X_CNIC_FLAG_MAC_SET;
-		bnx2x_set_iscsi_eth_mac_addr(bp, 0);
-	}
 	cp->drv_state = 0;
 	rcu_assign_pointer(bp->cnic_ops, NULL);
 	mutex_unlock(&bp->cnic_mutex);
@@ -9669,7 +10049,9 @@ struct cnic_eth_dev *bnx2x_cnic_probe(st
 	cp->drv_ctl = bnx2x_drv_ctl;
 	cp->drv_register_cnic = bnx2x_register_cnic;
 	cp->drv_unregister_cnic = bnx2x_unregister_cnic;
-	cp->iscsi_l2_client_id = BNX2X_ISCSI_ETH_CL_ID;
+	cp->fcoe_init_cid = BNX2X_FCOE_ETH_CID;
+	cp->iscsi_l2_client_id = BNX2X_ISCSI_ETH_CL_ID +
+		BP_E1HVN(bp) * NONE_ETH_CONTEXT_USE;
 	cp->iscsi_l2_cid = BNX2X_ISCSI_ETH_CID;
 
 	DP(BNX2X_MSG_SP, "page_size %d, tbl_offset %d, tbl_lines %d, "
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/bnx2x/bnx2x_reg.h linux-libre-2.6.38-gnu1/drivers/net/bnx2x/bnx2x_reg.h
--- linux-libre-2.6.37-gnu1/drivers/net/bnx2x/bnx2x_reg.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/bnx2x/bnx2x_reg.h	2011-03-14 21:20:32.000000000 -0400
@@ -18,6 +18,8 @@
  * WR - Write Clear (write 1 to clear the bit)
  *
  */
+#ifndef BNX2X_REG_H
+#define BNX2X_REG_H
 
 #define ATC_ATC_INT_STS_REG_ADDRESS_ERROR			 (0x1<<0)
 #define ATC_ATC_INT_STS_REG_ATC_GPA_MULTIPLE_HITS		 (0x1<<2)
@@ -39,6 +41,8 @@
 #define BRB1_REG_BRB1_PRTY_MASK 				 0x60138
 /* [R 4] Parity register #0 read */
 #define BRB1_REG_BRB1_PRTY_STS					 0x6012c
+/* [RC 4] Parity register #0 read clear */
+#define BRB1_REG_BRB1_PRTY_STS_CLR				 0x60130
 /* [RW 10] At address BRB1_IND_FREE_LIST_PRS_CRDT initialize free head. At
  * address BRB1_IND_FREE_LIST_PRS_CRDT+1 initialize free tail. At address
  * BRB1_IND_FREE_LIST_PRS_CRDT+2 initialize parser initial credit. Warning -
@@ -132,8 +136,12 @@
 #define CCM_REG_CCM_INT_MASK					 0xd01e4
 /* [R 11] Interrupt register #0 read */
 #define CCM_REG_CCM_INT_STS					 0xd01d8
+/* [RW 27] Parity mask register #0 read/write */
+#define CCM_REG_CCM_PRTY_MASK					 0xd01f4
 /* [R 27] Parity register #0 read */
 #define CCM_REG_CCM_PRTY_STS					 0xd01e8
+/* [RC 27] Parity register #0 read clear */
+#define CCM_REG_CCM_PRTY_STS_CLR				 0xd01ec
 /* [RW 3] The size of AG context region 0 in REG-pairs. Designates the MS
    REG-pair number (e.g. if region 0 is 6 REG-pairs; the value should be 5).
    Is used to determine the number of the AG context REG-pairs written back;
@@ -350,6 +358,8 @@
 #define CDU_REG_CDU_PRTY_MASK					 0x10104c
 /* [R 5] Parity register #0 read */
 #define CDU_REG_CDU_PRTY_STS					 0x101040
+/* [RC 5] Parity register #0 read clear */
+#define CDU_REG_CDU_PRTY_STS_CLR				 0x101044
 /* [RC 32] logging of error data in case of a CDU load error:
    {expected_cid[15:0]; xpected_type[2:0]; xpected_region[2:0]; ctive_error;
    ype_error; ctual_active; ctual_compressed_context}; */
@@ -381,6 +391,8 @@
 #define CFC_REG_CFC_PRTY_MASK					 0x104118
 /* [R 4] Parity register #0 read */
 #define CFC_REG_CFC_PRTY_STS					 0x10410c
+/* [RC 4] Parity register #0 read clear */
+#define CFC_REG_CFC_PRTY_STS_CLR				 0x104110
 /* [RW 21] CID cam access (21:1 - Data; alid - 0) */
 #define CFC_REG_CID_CAM 					 0x104800
 #define CFC_REG_CONTROL0					 0x104028
@@ -466,6 +478,8 @@
 #define CSDM_REG_CSDM_PRTY_MASK 				 0xc22bc
 /* [R 11] Parity register #0 read */
 #define CSDM_REG_CSDM_PRTY_STS					 0xc22b0
+/* [RC 11] Parity register #0 read clear */
+#define CSDM_REG_CSDM_PRTY_STS_CLR				 0xc22b4
 #define CSDM_REG_ENABLE_IN1					 0xc2238
 #define CSDM_REG_ENABLE_IN2					 0xc223c
 #define CSDM_REG_ENABLE_OUT1					 0xc2240
@@ -556,6 +570,9 @@
 /* [R 32] Parity register #0 read */
 #define CSEM_REG_CSEM_PRTY_STS_0				 0x200124
 #define CSEM_REG_CSEM_PRTY_STS_1				 0x200134
+/* [RC 32] Parity register #0 read clear */
+#define CSEM_REG_CSEM_PRTY_STS_CLR_0				 0x200128
+#define CSEM_REG_CSEM_PRTY_STS_CLR_1				 0x200138
 #define CSEM_REG_ENABLE_IN					 0x2000a4
 #define CSEM_REG_ENABLE_OUT					 0x2000a8
 /* [RW 32] This address space contains all registers and memories that are
@@ -648,6 +665,8 @@
 #define DBG_REG_DBG_PRTY_MASK					 0xc0a8
 /* [R 1] Parity register #0 read */
 #define DBG_REG_DBG_PRTY_STS					 0xc09c
+/* [RC 1] Parity register #0 read clear */
+#define DBG_REG_DBG_PRTY_STS_CLR				 0xc0a0
 /* [RW 1] When set the DMAE will process the commands as in E1.5. 1.The
  * function that is used is always SRC-PCI; 2.VF_Valid = 0; 3.VFID=0;
  * 4.Completion function=0; 5.Error handling=0 */
@@ -668,6 +687,8 @@
 #define DMAE_REG_DMAE_PRTY_MASK 				 0x102064
 /* [R 4] Parity register #0 read */
 #define DMAE_REG_DMAE_PRTY_STS					 0x102058
+/* [RC 4] Parity register #0 read clear */
+#define DMAE_REG_DMAE_PRTY_STS_CLR				 0x10205c
 /* [RW 1] Command 0 go. */
 #define DMAE_REG_GO_C0						 0x102080
 /* [RW 1] Command 1 go. */
@@ -734,6 +755,8 @@
 #define DORQ_REG_DORQ_PRTY_MASK 				 0x170190
 /* [R 2] Parity register #0 read */
 #define DORQ_REG_DORQ_PRTY_STS					 0x170184
+/* [RC 2] Parity register #0 read clear */
+#define DORQ_REG_DORQ_PRTY_STS_CLR				 0x170188
 /* [RW 8] The address to write the DPM CID to STORM. */
 #define DORQ_REG_DPM_CID_ADDR					 0x170044
 /* [RW 5] The DPM mode CID extraction offset. */
@@ -842,8 +865,12 @@
 /* [R 1] data availble for error memory. If this bit is clear do not red
  * from error_handling_memory. */
 #define IGU_REG_ERROR_HANDLING_DATA_VALID			 0x130130
+/* [RW 11] Parity mask register #0 read/write */
+#define IGU_REG_IGU_PRTY_MASK					 0x1300a8
 /* [R 11] Parity register #0 read */
 #define IGU_REG_IGU_PRTY_STS					 0x13009c
+/* [RC 11] Parity register #0 read clear */
+#define IGU_REG_IGU_PRTY_STS_CLR				 0x1300a0
 /* [R 4] Debug: int_handle_fsm */
 #define IGU_REG_INT_HANDLE_FSM					 0x130050
 #define IGU_REG_LEADING_EDGE_LATCH				 0x130134
@@ -1501,6 +1528,8 @@
 #define MISC_REG_MISC_PRTY_MASK 				 0xa398
 /* [R 1] Parity register #0 read */
 #define MISC_REG_MISC_PRTY_STS					 0xa38c
+/* [RC 1] Parity register #0 read clear */
+#define MISC_REG_MISC_PRTY_STS_CLR				 0xa390
 #define MISC_REG_NIG_WOL_P0					 0xa270
 #define MISC_REG_NIG_WOL_P1					 0xa274
 /* [R 1] If set indicate that the pcie_rst_b was asserted without perst
@@ -1604,7 +1633,7 @@
    (~misc_registers_sw_timer_cfg_4.sw_timer_cfg_4[1] ) is set */
 #define MISC_REG_SW_TIMER_RELOAD_VAL_4				 0xa2fc
 /* [RW 32] the value of the counter for sw timers1-8. there are 8 addresses
-   in this register. addres 0 - timer 1; address 1 - timer 2, ...  address 7 -
+   in this register. address 0 - timer 1; address 1 - timer 2, ...  address 7 -
    timer 8 */
 #define MISC_REG_SW_TIMER_VAL					 0xa5c0
 /* [RW 1] Set by the MCP to remember if one or more of the drivers is/are
@@ -1615,6 +1644,8 @@
 #define NIG_LLH0_BRB1_DRV_MASK_REG_LLH0_BRB1_DRV_MASK_NO_VLAN	 (0x1<<4)
 #define NIG_LLH0_BRB1_DRV_MASK_REG_LLH0_BRB1_DRV_MASK_UNCST	 (0x1<<2)
 #define NIG_LLH0_BRB1_DRV_MASK_REG_LLH0_BRB1_DRV_MASK_VLAN	 (0x1<<3)
+#define NIG_LLH0_XCM_MASK_REG_LLH0_XCM_MASK_BCN			 (0x1<<0)
+#define NIG_LLH1_XCM_MASK_REG_LLH1_XCM_MASK_BCN			 (0x1<<0)
 #define NIG_MASK_INTERRUPT_PORT0_REG_MASK_EMAC0_MISC_MI_INT	 (0x1<<0)
 #define NIG_MASK_INTERRUPT_PORT0_REG_MASK_SERDES0_LINK_STATUS	 (0x1<<9)
 #define NIG_MASK_INTERRUPT_PORT0_REG_MASK_XGXS0_LINK10G 	 (0x1<<15)
@@ -1744,12 +1775,16 @@
    ~ppp_enable.ppp_enable = 0 and pause_enable.pause_enable =0 for the same
    port */
 #define NIG_REG_LLFC_ENABLE_0					 0x16208
+#define NIG_REG_LLFC_ENABLE_1					 0x1620c
 /* [RW 16] classes are high-priority for port0 */
 #define NIG_REG_LLFC_HIGH_PRIORITY_CLASSES_0			 0x16058
+#define NIG_REG_LLFC_HIGH_PRIORITY_CLASSES_1			 0x1605c
 /* [RW 16] classes are low-priority for port0 */
 #define NIG_REG_LLFC_LOW_PRIORITY_CLASSES_0			 0x16060
+#define NIG_REG_LLFC_LOW_PRIORITY_CLASSES_1			 0x16064
 /* [RW 1] Output enable of message to LLFC BMAC IF for port0 */
 #define NIG_REG_LLFC_OUT_EN_0					 0x160c8
+#define NIG_REG_LLFC_OUT_EN_1					 0x160cc
 #define NIG_REG_LLH0_ACPI_PAT_0_CRC				 0x1015c
 #define NIG_REG_LLH0_ACPI_PAT_6_LEN				 0x10154
 #define NIG_REG_LLH0_BRB1_DRV_MASK				 0x10244
@@ -1774,6 +1809,8 @@
 /* [RW 8] event id for llh0 */
 #define NIG_REG_LLH0_EVENT_ID					 0x10084
 #define NIG_REG_LLH0_FUNC_EN					 0x160fc
+#define NIG_REG_LLH0_FUNC_MEM					 0x16180
+#define NIG_REG_LLH0_FUNC_MEM_ENABLE				 0x16140
 #define NIG_REG_LLH0_FUNC_VLAN_ID				 0x16100
 /* [RW 1] Determine the IP version to look for in
    ~nig_registers_llh0_dest_ip_0.llh0_dest_ip_0. 0 - IPv6; 1-IPv4 */
@@ -1797,6 +1834,9 @@
 #define NIG_REG_LLH1_ERROR_MASK 				 0x10090
 /* [RW 8] event id for llh1 */
 #define NIG_REG_LLH1_EVENT_ID					 0x10088
+#define NIG_REG_LLH1_FUNC_MEM					 0x161c0
+#define NIG_REG_LLH1_FUNC_MEM_ENABLE				 0x16160
+#define NIG_REG_LLH1_FUNC_MEM_SIZE				 16
 /* [RW 8] init credit counter for port1 in LLH */
 #define NIG_REG_LLH1_XCM_INIT_CREDIT				 0x10564
 #define NIG_REG_LLH1_XCM_MASK					 0x10134
@@ -1907,11 +1947,17 @@
    ~safc_enable.safc_enable = 0 and ppp_enable.ppp_enable =0 for the same
    port */
 #define NIG_REG_PAUSE_ENABLE_0					 0x160c0
+#define NIG_REG_PAUSE_ENABLE_1					 0x160c4
 /* [RW 1] Input enable for RX PBF LP IF */
 #define NIG_REG_PBF_LB_IN_EN					 0x100b4
 /* [RW 1] Value of this register will be transmitted to port swap when
    ~nig_registers_strap_override.strap_override =1 */
 #define NIG_REG_PORT_SWAP					 0x10394
+/* [RW 1] PPP enable for port0. This register may get 1 only when
+ * ~safc_enable.safc_enable = 0 and pause_enable.pause_enable =0 for the
+ * same port */
+#define NIG_REG_PPP_ENABLE_0					 0x160b0
+#define NIG_REG_PPP_ENABLE_1					 0x160b4
 /* [RW 1] output enable for RX parser descriptor IF */
 #define NIG_REG_PRS_EOP_OUT_EN					 0x10104
 /* [RW 1] Input enable for RX parser request IF */
@@ -1978,6 +2024,14 @@
 #define NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_XGXS0_LINK10G	 (0x1<<15)
 #define NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_XGXS0_LINK_STATUS  (0xf<<18)
 #define NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_XGXS0_LINK_STATUS_SIZE 18
+/* [RW 31] The upper bound of the weight of COS0 in the ETS command arbiter. */
+#define PBF_REG_COS0_UPPER_BOUND				 0x15c05c
+/* [RW 31] The weight of COS0 in the ETS command arbiter. */
+#define PBF_REG_COS0_WEIGHT					 0x15c054
+/* [RW 31] The upper bound of the weight of COS1 in the ETS command arbiter. */
+#define PBF_REG_COS1_UPPER_BOUND				 0x15c060
+/* [RW 31] The weight of COS1 in the ETS command arbiter. */
+#define PBF_REG_COS1_WEIGHT					 0x15c058
 /* [RW 1] Disable processing further tasks from port 0 (after ending the
    current task in process). */
 #define PBF_REG_DISABLE_NEW_TASK_PROC_P0			 0x14005c
@@ -1988,9 +2042,16 @@
    current task in process). */
 #define PBF_REG_DISABLE_NEW_TASK_PROC_P4			 0x14006c
 #define PBF_REG_DISABLE_PF					 0x1402e8
+/* [RW 1] Indicates that ETS is performed between the COSes in the command
+ * arbiter. If reset strict priority w/ anti-starvation will be performed
+ * w/o WFQ. */
+#define PBF_REG_ETS_ENABLED					 0x15c050
 /* [RW 6] Bit-map indicating which L2 hdrs may appear after the basic
  * Ethernet header. */
 #define PBF_REG_HDRS_AFTER_BASIC				 0x15c0a8
+/* [RW 1] Indicates which COS is conncted to the highest priority in the
+ * command arbiter. */
+#define PBF_REG_HIGH_PRIORITY_COS_NUM				 0x15c04c
 #define PBF_REG_IF_ENABLE_REG					 0x140044
 /* [RW 1] Init bit. When set the initial credits are copied to the credit
    registers (except the port credits). Should be set and then reset after
@@ -2016,6 +2077,10 @@
 #define PBF_REG_MAC_LB_ENABLE					 0x140040
 /* [RW 6] Bit-map indicating which headers must appear in the packet */
 #define PBF_REG_MUST_HAVE_HDRS					 0x15c0c4
+/* [RW 16] The number of strict priority arbitration slots between 2 RR
+ * arbitration slots. A value of 0 means no strict priority cycles; i.e. the
+ * strict-priority w/ anti-starvation arbiter is a RR arbiter. */
+#define PBF_REG_NUM_STRICT_ARB_SLOTS				 0x15c064
 /* [RW 10] Port 0 threshold used by arbiter in 16 byte lines used when pause
    not suppoterd. */
 #define PBF_REG_P0_ARB_THRSH					 0x1400e4
@@ -2046,6 +2111,10 @@
 #define PBF_REG_PBF_INT_MASK					 0x1401d4
 /* [R 5] Interrupt register #0 read */
 #define PBF_REG_PBF_INT_STS					 0x1401c8
+/* [RW 20] Parity mask register #0 read/write */
+#define PBF_REG_PBF_PRTY_MASK					 0x1401e4
+/* [RC 20] Parity register #0 read clear */
+#define PBF_REG_PBF_PRTY_STS_CLR				 0x1401dc
 #define PB_REG_CONTROL						 0
 /* [RW 2] Interrupt mask register #0 read/write */
 #define PB_REG_PB_INT_MASK					 0x28
@@ -2055,6 +2124,8 @@
 #define PB_REG_PB_PRTY_MASK					 0x38
 /* [R 4] Parity register #0 read */
 #define PB_REG_PB_PRTY_STS					 0x2c
+/* [RC 4] Parity register #0 read clear */
+#define PB_REG_PB_PRTY_STS_CLR					 0x30
 #define PGLUE_B_PGLUE_B_INT_STS_REG_ADDRESS_ERROR		 (0x1<<0)
 #define PGLUE_B_PGLUE_B_INT_STS_REG_CSSNOOP_FIFO_OVERFLOW	 (0x1<<8)
 #define PGLUE_B_PGLUE_B_INT_STS_REG_INCORRECT_RCV_BEHAVIOR	 (0x1<<1)
@@ -2410,6 +2481,8 @@
 #define PRS_REG_PRS_PRTY_MASK					 0x401a4
 /* [R 8] Parity register #0 read */
 #define PRS_REG_PRS_PRTY_STS					 0x40198
+/* [RC 8] Parity register #0 read clear */
+#define PRS_REG_PRS_PRTY_STS_CLR				 0x4019c
 /* [RW 8] Context region for pure acknowledge packets. Used in CFC load
    request message */
 #define PRS_REG_PURE_REGIONS					 0x40024
@@ -2563,6 +2636,9 @@
 /* [R 32] Parity register #0 read */
 #define PXP2_REG_PXP2_PRTY_STS_0				 0x12057c
 #define PXP2_REG_PXP2_PRTY_STS_1				 0x12058c
+/* [RC 32] Parity register #0 read clear */
+#define PXP2_REG_PXP2_PRTY_STS_CLR_0				 0x120580
+#define PXP2_REG_PXP2_PRTY_STS_CLR_1				 0x120590
 /* [R 1] Debug only: The 'almost full' indication from each fifo (gives
    indication about backpressure) */
 #define PXP2_REG_RD_ALMOST_FULL_0				 0x120424
@@ -2965,6 +3041,8 @@
 #define PXP_REG_PXP_PRTY_MASK					 0x103094
 /* [R 26] Parity register #0 read */
 #define PXP_REG_PXP_PRTY_STS					 0x103088
+/* [RC 27] Parity register #0 read clear */
+#define PXP_REG_PXP_PRTY_STS_CLR				 0x10308c
 /* [RW 4] The activity counter initial increment value sent in the load
    request */
 #define QM_REG_ACTCTRINITVAL_0					 0x168040
@@ -3121,6 +3199,8 @@
 #define QM_REG_QM_PRTY_MASK					 0x168454
 /* [R 12] Parity register #0 read */
 #define QM_REG_QM_PRTY_STS					 0x168448
+/* [RC 12] Parity register #0 read clear */
+#define QM_REG_QM_PRTY_STS_CLR					 0x16844c
 /* [R 32] Current queues in pipeline: Queues from 32 to 63 */
 #define QM_REG_QSTATUS_HIGH					 0x16802c
 /* [R 32] Current queues in pipeline: Queues from 96 to 127 */
@@ -3406,6 +3486,8 @@
 #define QM_REG_WRRWEIGHTS_9					 0x168848
 /* [R 6] Keep the fill level of the fifo from write client 1 */
 #define QM_REG_XQM_WRC_FIFOLVL					 0x168000
+/* [W 1] reset to parity interrupt */
+#define SEM_FAST_REG_PARITY_RST					 0x18840
 #define SRC_REG_COUNTFREE0					 0x40500
 /* [RW 1] If clr the searcher is compatible to E1 A0 - support only two
    ports. If set the searcher support 8 functions. */
@@ -3434,6 +3516,8 @@
 #define SRC_REG_SRC_PRTY_MASK					 0x404c8
 /* [R 3] Parity register #0 read */
 #define SRC_REG_SRC_PRTY_STS					 0x404bc
+/* [RC 3] Parity register #0 read clear */
+#define SRC_REG_SRC_PRTY_STS_CLR				 0x404c0
 /* [R 4] Used to read the value of the XX protection CAM occupancy counter. */
 #define TCM_REG_CAM_OCCUP					 0x5017c
 /* [RW 1] CDU AG read Interface enable. If 0 - the request input is
@@ -3560,8 +3644,12 @@
 #define TCM_REG_TCM_INT_MASK					 0x501dc
 /* [R 11] Interrupt register #0 read */
 #define TCM_REG_TCM_INT_STS					 0x501d0
+/* [RW 27] Parity mask register #0 read/write */
+#define TCM_REG_TCM_PRTY_MASK					 0x501ec
 /* [R 27] Parity register #0 read */
 #define TCM_REG_TCM_PRTY_STS					 0x501e0
+/* [RC 27] Parity register #0 read clear */
+#define TCM_REG_TCM_PRTY_STS_CLR				 0x501e4
 /* [RW 3] The size of AG context region 0 in REG-pairs. Designates the MS
    REG-pair number (e.g. if region 0 is 6 REG-pairs; the value should be 5).
    Is used to determine the number of the AG context REG-pairs written back;
@@ -3719,6 +3807,10 @@
 #define TM_REG_TM_INT_MASK					 0x1640fc
 /* [R 1] Interrupt register #0 read */
 #define TM_REG_TM_INT_STS					 0x1640f0
+/* [RW 7] Parity mask register #0 read/write */
+#define TM_REG_TM_PRTY_MASK					 0x16410c
+/* [RC 7] Parity register #0 read clear */
+#define TM_REG_TM_PRTY_STS_CLR					 0x164104
 /* [RW 8] The event id for aggregated interrupt 0 */
 #define TSDM_REG_AGG_INT_EVENT_0				 0x42038
 #define TSDM_REG_AGG_INT_EVENT_1				 0x4203c
@@ -3799,6 +3891,8 @@
 #define TSDM_REG_TSDM_PRTY_MASK 				 0x422bc
 /* [R 11] Parity register #0 read */
 #define TSDM_REG_TSDM_PRTY_STS					 0x422b0
+/* [RC 11] Parity register #0 read clear */
+#define TSDM_REG_TSDM_PRTY_STS_CLR				 0x422b4
 /* [RW 5] The number of time_slots in the arbitration cycle */
 #define TSEM_REG_ARB_CYCLE_SIZE 				 0x180034
 /* [RW 3] The source that is associated with arbitration element 0. Source
@@ -3878,6 +3972,9 @@
 #define TSEM_REG_SLOW_EXT_STORE_EMPTY				 0x1802a0
 /* [RW 8] List of free threads . There is a bit per thread. */
 #define TSEM_REG_THREADS_LIST					 0x1802e4
+/* [RC 32] Parity register #0 read clear */
+#define TSEM_REG_TSEM_PRTY_STS_CLR_0				 0x180118
+#define TSEM_REG_TSEM_PRTY_STS_CLR_1				 0x180128
 /* [RW 3] The arbitration scheme of time_slot 0 */
 #define TSEM_REG_TS_0_AS					 0x180038
 /* [RW 3] The arbitration scheme of time_slot 10 */
@@ -4080,6 +4177,8 @@
 #define UCM_REG_UCM_INT_STS					 0xe01c8
 /* [R 27] Parity register #0 read */
 #define UCM_REG_UCM_PRTY_STS					 0xe01d8
+/* [RC 27] Parity register #0 read clear */
+#define UCM_REG_UCM_PRTY_STS_CLR				 0xe01dc
 /* [RW 2] The size of AG context region 0 in REG-pairs. Designates the MS
    REG-pair number (e.g. if region 0 is 6 REG-pairs; the value should be 5).
    Is used to determine the number of the AG context REG-pairs written back;
@@ -4256,6 +4355,8 @@
 #define USDM_REG_USDM_PRTY_MASK 				 0xc42c0
 /* [R 11] Parity register #0 read */
 #define USDM_REG_USDM_PRTY_STS					 0xc42b4
+/* [RC 11] Parity register #0 read clear */
+#define USDM_REG_USDM_PRTY_STS_CLR				 0xc42b8
 /* [RW 5] The number of time_slots in the arbitration cycle */
 #define USEM_REG_ARB_CYCLE_SIZE 				 0x300034
 /* [RW 3] The source that is associated with arbitration element 0. Source
@@ -4385,6 +4486,9 @@
 /* [R 32] Parity register #0 read */
 #define USEM_REG_USEM_PRTY_STS_0				 0x300124
 #define USEM_REG_USEM_PRTY_STS_1				 0x300134
+/* [RC 32] Parity register #0 read clear */
+#define USEM_REG_USEM_PRTY_STS_CLR_0				 0x300128
+#define USEM_REG_USEM_PRTY_STS_CLR_1				 0x300138
 /* [W 7] VF or PF ID for reset error bit. Values 0-63 reset error bit for 64
  * VF; values 64-67 reset error for 4 PF; values 68-127 are not valid. */
 #define USEM_REG_VFPF_ERR_NUM					 0x300380
@@ -4761,6 +4865,8 @@
 #define XSDM_REG_XSDM_PRTY_MASK 				 0x1662bc
 /* [R 11] Parity register #0 read */
 #define XSDM_REG_XSDM_PRTY_STS					 0x1662b0
+/* [RC 11] Parity register #0 read clear */
+#define XSDM_REG_XSDM_PRTY_STS_CLR				 0x1662b4
 /* [RW 5] The number of time_slots in the arbitration cycle */
 #define XSEM_REG_ARB_CYCLE_SIZE 				 0x280034
 /* [RW 3] The source that is associated with arbitration element 0. Source
@@ -4893,6 +4999,9 @@
 /* [R 32] Parity register #0 read */
 #define XSEM_REG_XSEM_PRTY_STS_0				 0x280124
 #define XSEM_REG_XSEM_PRTY_STS_1				 0x280134
+/* [RC 32] Parity register #0 read clear */
+#define XSEM_REG_XSEM_PRTY_STS_CLR_0				 0x280128
+#define XSEM_REG_XSEM_PRTY_STS_CLR_1				 0x280138
 #define MCPR_NVM_ACCESS_ENABLE_EN				 (1L<<0)
 #define MCPR_NVM_ACCESS_ENABLE_WR_EN				 (1L<<1)
 #define MCPR_NVM_ADDR_NVM_ADDR_VALUE				 (0xffffffL<<0)
@@ -4970,7 +5079,23 @@
 #define EMAC_REG_EMAC_TX_MODE					 0xbc
 #define EMAC_REG_EMAC_TX_STAT_AC				 0x280
 #define EMAC_REG_EMAC_TX_STAT_AC_COUNT				 22
+#define EMAC_REG_RX_PFC_MODE					 0x320
+#define EMAC_REG_RX_PFC_MODE_PRIORITIES				 (1L<<2)
+#define EMAC_REG_RX_PFC_MODE_RX_EN				 (1L<<1)
+#define EMAC_REG_RX_PFC_MODE_TX_EN				 (1L<<0)
+#define EMAC_REG_RX_PFC_PARAM					 0x324
+#define EMAC_REG_RX_PFC_PARAM_OPCODE_BITSHIFT			 0
+#define EMAC_REG_RX_PFC_PARAM_PRIORITY_EN_BITSHIFT		 16
+#define EMAC_REG_RX_PFC_STATS_XOFF_RCVD				 0x328
+#define EMAC_REG_RX_PFC_STATS_XOFF_RCVD_COUNT			 (0xffff<<0)
+#define EMAC_REG_RX_PFC_STATS_XOFF_SENT				 0x330
+#define EMAC_REG_RX_PFC_STATS_XOFF_SENT_COUNT			 (0xffff<<0)
+#define EMAC_REG_RX_PFC_STATS_XON_RCVD				 0x32c
+#define EMAC_REG_RX_PFC_STATS_XON_RCVD_COUNT			 (0xffff<<0)
+#define EMAC_REG_RX_PFC_STATS_XON_SENT				 0x334
+#define EMAC_REG_RX_PFC_STATS_XON_SENT_COUNT			 (0xffff<<0)
 #define EMAC_RX_MODE_FLOW_EN					 (1L<<2)
+#define EMAC_RX_MODE_KEEP_MAC_CONTROL				 (1L<<3)
 #define EMAC_RX_MODE_KEEP_VLAN_TAG				 (1L<<10)
 #define EMAC_RX_MODE_PROMISCUOUS				 (1L<<8)
 #define EMAC_RX_MODE_RESET					 (1L<<0)
@@ -6069,7 +6194,11 @@ Theotherbitsarereservedandshouldbezero*/
 #define MDIO_CTL_REG_84823_MEDIA_PRIORITY_COPPER	0x0000
 #define MDIO_CTL_REG_84823_MEDIA_PRIORITY_FIBER		0x0100
 #define MDIO_CTL_REG_84823_MEDIA_FIBER_1G			0x1000
+#define MDIO_CTL_REG_84823_USER_CTRL_REG		0x4005
+#define MDIO_CTL_REG_84823_USER_CTRL_CMS		0x0080
 
+#define MDIO_PMA_REG_84823_CTL_LED_CTL_1		0xa8e3
+#define MDIO_PMA_REG_84823_LED3_STRETCH_EN		0x0080
 
 #define IGU_FUNC_BASE			0x0400
 
@@ -6264,3 +6393,4 @@ static inline u8 calc_crc8(u32 data, u8
 }
 
 
+#endif /* BNX2X_REG_H */
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/bnx2x/bnx2x_stats.c linux-libre-2.6.38-gnu1/drivers/net/bnx2x/bnx2x_stats.c
--- linux-libre-2.6.37-gnu1/drivers/net/bnx2x/bnx2x_stats.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/bnx2x/bnx2x_stats.c	2011-03-14 21:20:32.000000000 -0400
@@ -158,9 +158,14 @@ static void bnx2x_storm_stats_post(struc
 
 		spin_lock_bh(&bp->stats_lock);
 
+		if (bp->stats_pending) {
+			spin_unlock_bh(&bp->stats_lock);
+			return;
+		}
+
 		ramrod_data.drv_counter = bp->stats_counter++;
 		ramrod_data.collect_port = bp->port.pmf ? 1 : 0;
-		for_each_queue(bp, i)
+		for_each_eth_queue(bp, i)
 			ramrod_data.ctr_id_vector |= (1 << bp->fp[i].cl_id);
 
 		rc = bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_STAT_QUERY, 0,
@@ -766,7 +771,7 @@ static int bnx2x_storm_stats_update(stru
 	estats->no_buff_discard_hi = 0;
 	estats->no_buff_discard_lo = 0;
 
-	for_each_queue(bp, i) {
+	for_each_eth_queue(bp, i) {
 		struct bnx2x_fastpath *fp = &bp->fp[i];
 		int cl_id = fp->cl_id;
 		struct tstorm_per_client_stats *tclient =
@@ -996,7 +1001,7 @@ static void bnx2x_net_stats_update(struc
 	nstats->tx_bytes = bnx2x_hilo(&estats->total_bytes_transmitted_hi);
 
 	tmp = estats->mac_discard;
-	for_each_queue(bp, i)
+	for_each_rx_queue(bp, i)
 		tmp += le32_to_cpu(bp->fp[i].old_tclient.checksum_discard);
 	nstats->rx_dropped = tmp;
 
@@ -1087,7 +1092,7 @@ static void bnx2x_stats_update(struct bn
 		       bp->dev->name,
 		       estats->brb_drop_lo, estats->brb_truncate_lo);
 
-		for_each_queue(bp, i) {
+		for_each_eth_queue(bp, i) {
 			struct bnx2x_fastpath *fp = &bp->fp[i];
 			struct bnx2x_eth_q_stats *qstats = &fp->eth_q_stats;
 
@@ -1101,7 +1106,7 @@ static void bnx2x_stats_update(struct bn
 			       fp->rx_calls, fp->rx_pkt);
 		}
 
-		for_each_queue(bp, i) {
+		for_each_eth_queue(bp, i) {
 			struct bnx2x_fastpath *fp = &bp->fp[i];
 			struct bnx2x_eth_q_stats *qstats = &fp->eth_q_stats;
 			struct netdev_queue *txq =
@@ -1234,14 +1239,14 @@ void bnx2x_stats_handle(struct bnx2x *bp
 	if (unlikely(bp->panic))
 		return;
 
+	bnx2x_stats_stm[bp->stats_state][event].action(bp);
+
 	/* Protect a state change flow */
 	spin_lock_bh(&bp->stats_lock);
 	state = bp->stats_state;
 	bp->stats_state = bnx2x_stats_stm[state][event].next_state;
 	spin_unlock_bh(&bp->stats_lock);
 
-	bnx2x_stats_stm[state][event].action(bp);
-
 	if ((event != STATS_EVENT_UPDATE) || netif_msg_timer(bp))
 		DP(BNX2X_MSG_STATS, "state %d -> event %d -> state %d\n",
 		   state, event, bp->stats_state);
@@ -1381,7 +1386,8 @@ void bnx2x_stats_init(struct bnx2x *bp)
 		memset(&fp->eth_q_stats, 0, sizeof(struct bnx2x_eth_q_stats));
 	}
 
-	for_each_queue(bp, i) {
+	/* FW stats are currently collected for ETH clients only */
+	for_each_eth_queue(bp, i) {
 		/* Set initial stats counter in the stats ramrod data to -1 */
 		int cl_id = bp->fp[i].cl_id;
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/bnx2x/bnx2x_stats.h linux-libre-2.6.38-gnu1/drivers/net/bnx2x/bnx2x_stats.h
--- linux-libre-2.6.37-gnu1/drivers/net/bnx2x/bnx2x_stats.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/bnx2x/bnx2x_stats.h	2011-03-14 21:20:32.000000000 -0400
@@ -53,7 +53,6 @@ struct bnx2x_eth_q_stats {
 	u32 hw_csum_err;
 };
 
-#define BNX2X_NUM_Q_STATS		13
 #define Q_STATS_OFFSET32(stat_name) \
 			(offsetof(struct bnx2x_eth_q_stats, stat_name) / 4)
 
@@ -225,7 +224,6 @@ struct bnx2x_eth_stats {
 	u32 nig_timer_max;
 };
 
-#define BNX2X_NUM_STATS			43
 #define STATS_OFFSET32(stat_name) \
 			(offsetof(struct bnx2x_eth_stats, stat_name) / 4)
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/bnx2x/Makefile linux-libre-2.6.38-gnu1/drivers/net/bnx2x/Makefile
--- linux-libre-2.6.37-gnu1/drivers/net/bnx2x/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/bnx2x/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -4,4 +4,4 @@
 
 obj-$(CONFIG_BNX2X) += bnx2x.o
 
-bnx2x-objs := bnx2x_main.o bnx2x_link.o bnx2x_cmn.o bnx2x_ethtool.o bnx2x_stats.o
+bnx2x-objs := bnx2x_main.o bnx2x_link.o bnx2x_cmn.o bnx2x_ethtool.o bnx2x_stats.o bnx2x_dcb.o
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/bonding/bond_3ad.c linux-libre-2.6.38-gnu1/drivers/net/bonding/bond_3ad.c
--- linux-libre-2.6.37-gnu1/drivers/net/bonding/bond_3ad.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/bonding/bond_3ad.c	2011-03-14 21:20:32.000000000 -0400
@@ -281,23 +281,23 @@ static inline int __check_agg_selection_
 }
 
 /**
- * __get_rx_machine_lock - lock the port's RX machine
+ * __get_state_machine_lock - lock the port's state machines
  * @port: the port we're looking at
  *
  */
-static inline void __get_rx_machine_lock(struct port *port)
+static inline void __get_state_machine_lock(struct port *port)
 {
-	spin_lock_bh(&(SLAVE_AD_INFO(port->slave).rx_machine_lock));
+	spin_lock_bh(&(SLAVE_AD_INFO(port->slave).state_machine_lock));
 }
 
 /**
- * __release_rx_machine_lock - unlock the port's RX machine
+ * __release_state_machine_lock - unlock the port's state machines
  * @port: the port we're looking at
  *
  */
-static inline void __release_rx_machine_lock(struct port *port)
+static inline void __release_state_machine_lock(struct port *port)
 {
-	spin_unlock_bh(&(SLAVE_AD_INFO(port->slave).rx_machine_lock));
+	spin_unlock_bh(&(SLAVE_AD_INFO(port->slave).state_machine_lock));
 }
 
 /**
@@ -388,14 +388,14 @@ static u8 __get_duplex(struct port *port
 }
 
 /**
- * __initialize_port_locks - initialize a port's RX machine spinlock
+ * __initialize_port_locks - initialize a port's STATE machine spinlock
  * @port: the port we're looking at
  *
  */
 static inline void __initialize_port_locks(struct port *port)
 {
 	// make sure it isn't called twice
-	spin_lock_init(&(SLAVE_AD_INFO(port->slave).rx_machine_lock));
+	spin_lock_init(&(SLAVE_AD_INFO(port->slave).state_machine_lock));
 }
 
 //conversions
@@ -840,7 +840,7 @@ static int ad_lacpdu_send(struct port *p
 	lacpdu_header = (struct lacpdu_header *)skb_put(skb, length);
 
 	memcpy(lacpdu_header->hdr.h_dest, lacpdu_mcast_addr, ETH_ALEN);
-	/* Note: source addres is set to be the member's PERMANENT address,
+	/* Note: source address is set to be the member's PERMANENT address,
 	   because we use it to identify loopback lacpdus in receive. */
 	memcpy(lacpdu_header->hdr.h_source, slave->perm_hwaddr, ETH_ALEN);
 	lacpdu_header->hdr.h_proto = PKT_TYPE_LACPDU;
@@ -881,7 +881,7 @@ static int ad_marker_send(struct port *p
 	marker_header = (struct bond_marker_header *)skb_put(skb, length);
 
 	memcpy(marker_header->hdr.h_dest, lacpdu_mcast_addr, ETH_ALEN);
-	/* Note: source addres is set to be the member's PERMANENT address,
+	/* Note: source address is set to be the member's PERMANENT address,
 	   because we use it to identify loopback MARKERs in receive. */
 	memcpy(marker_header->hdr.h_source, slave->perm_hwaddr, ETH_ALEN);
 	marker_header->hdr.h_proto = PKT_TYPE_LACPDU;
@@ -1025,9 +1025,6 @@ static void ad_rx_machine(struct lacpdu
 {
 	rx_states_t last_state;
 
-	// Lock to prevent 2 instances of this function to run simultaneously(rx interrupt and periodic machine callback)
-	__get_rx_machine_lock(port);
-
 	// keep current State Machine state to compare later if it was changed
 	last_state = port->sm_rx_state;
 
@@ -1133,7 +1130,6 @@ static void ad_rx_machine(struct lacpdu
 				pr_err("%s: An illegal loopback occurred on adapter (%s).\n"
 				       "Check the configuration to verify that all adapters are connected to 802.3ad compliant switch ports\n",
 				       port->slave->dev->master->name, port->slave->dev->name);
-				__release_rx_machine_lock(port);
 				return;
 			}
 			__update_selected(lacpdu, port);
@@ -1153,7 +1149,6 @@ static void ad_rx_machine(struct lacpdu
 			break;
 		}
 	}
-	__release_rx_machine_lock(port);
 }
 
 /**
@@ -1916,7 +1911,7 @@ int bond_3ad_bind_slave(struct slave *sl
 		return -1;
 	}
 
-	//check that the slave has not been intialized yet.
+	//check that the slave has not been initialized yet.
 	if (SLAVE_AD_INFO(slave).port.slave != slave) {
 
 		// port initialization
@@ -2155,6 +2150,12 @@ void bond_3ad_state_machine_handler(stru
 			goto re_arm;
 		}
 
+		/* Lock around state machines to protect data accessed
+		 * by all (e.g., port->sm_vars).  ad_rx_machine may run
+		 * concurrently due to incoming LACPDU.
+		 */
+		__get_state_machine_lock(port);
+
 		ad_rx_machine(NULL, port);
 		ad_periodic_machine(port);
 		ad_port_selection_logic(port);
@@ -2164,6 +2165,8 @@ void bond_3ad_state_machine_handler(stru
 		// turn off the BEGIN bit, since we already handled it
 		if (port->sm_vars & AD_PORT_BEGIN)
 			port->sm_vars &= ~AD_PORT_BEGIN;
+
+		__release_state_machine_lock(port);
 	}
 
 re_arm:
@@ -2200,7 +2203,10 @@ static void bond_3ad_rx_indication(struc
 		case AD_TYPE_LACPDU:
 			pr_debug("Received LACPDU on port %d\n",
 				 port->actor_port_number);
+			/* Protect against concurrent state machines */
+			__get_state_machine_lock(port);
 			ad_rx_machine(lacpdu, port);
+			__release_state_machine_lock(port);
 			break;
 
 		case AD_TYPE_MARKER:
@@ -2470,12 +2476,15 @@ int bond_3ad_lacpdu_recv(struct sk_buff
 	if (!(dev->flags & IFF_MASTER))
 		goto out;
 
+	skb = skb_share_check(skb, GFP_ATOMIC);
+	if (!skb)
+		goto out;
+
 	if (!pskb_may_pull(skb, sizeof(struct lacpdu)))
 		goto out;
 
 	read_lock(&bond->lock);
-	slave = bond_get_slave_by_dev((struct bonding *)netdev_priv(dev),
-					orig_dev);
+	slave = bond_get_slave_by_dev(netdev_priv(dev), orig_dev);
 	if (!slave)
 		goto out_unlock;
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/bonding/bond_3ad.h linux-libre-2.6.38-gnu1/drivers/net/bonding/bond_3ad.h
--- linux-libre-2.6.37-gnu1/drivers/net/bonding/bond_3ad.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/bonding/bond_3ad.h	2011-03-14 21:20:32.000000000 -0400
@@ -264,7 +264,8 @@ struct ad_bond_info {
 struct ad_slave_info {
 	struct aggregator aggregator;	    // 802.3ad aggregator structure
 	struct port port;		    // 802.3ad port structure
-	spinlock_t rx_machine_lock; // To avoid race condition between callback and receive interrupt
+	spinlock_t state_machine_lock; /* mutex state machines vs.
+					  incoming LACPDU */
 	u16 id;
 };
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/bonding/bond_alb.c linux-libre-2.6.38-gnu1/drivers/net/bonding/bond_alb.c
--- linux-libre-2.6.37-gnu1/drivers/net/bonding/bond_alb.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/bonding/bond_alb.c	2011-03-14 21:20:32.000000000 -0400
@@ -44,42 +44,6 @@
 #include "bond_alb.h"
 
 
-#define ALB_TIMER_TICKS_PER_SEC	    10	/* should be a divisor of HZ */
-#define BOND_TLB_REBALANCE_INTERVAL 10	/* In seconds, periodic re-balancing.
-					 * Used for division - never set
-					 * to zero !!!
-					 */
-#define BOND_ALB_LP_INTERVAL	    1	/* In seconds, periodic send of
-					 * learning packets to the switch
-					 */
-
-#define BOND_TLB_REBALANCE_TICKS (BOND_TLB_REBALANCE_INTERVAL \
-				  * ALB_TIMER_TICKS_PER_SEC)
-
-#define BOND_ALB_LP_TICKS (BOND_ALB_LP_INTERVAL \
-			   * ALB_TIMER_TICKS_PER_SEC)
-
-#define TLB_HASH_TABLE_SIZE 256	/* The size of the clients hash table.
-				 * Note that this value MUST NOT be smaller
-				 * because the key hash table is BYTE wide !
-				 */
-
-
-#define TLB_NULL_INDEX		0xffffffff
-#define MAX_LP_BURST		3
-
-/* rlb defs */
-#define RLB_HASH_TABLE_SIZE	256
-#define RLB_NULL_INDEX		0xffffffff
-#define RLB_UPDATE_DELAY	2*ALB_TIMER_TICKS_PER_SEC /* 2 seconds */
-#define RLB_ARP_BURST_SIZE	2
-#define RLB_UPDATE_RETRY	3	/* 3-ticks - must be smaller than the rlb
-					 * rebalance interval (5 min).
-					 */
-/* RLB_PROMISC_TIMEOUT = 10 sec equals the time that the current slave is
- * promiscuous after failover
- */
-#define RLB_PROMISC_TIMEOUT	10*ALB_TIMER_TICKS_PER_SEC
 
 #ifndef __long_aligned
 #define __long_aligned __attribute__((aligned((sizeof(long)))))
@@ -362,6 +326,10 @@ static int rlb_arp_recv(struct sk_buff *
 		goto out;
 	}
 
+	skb = skb_share_check(skb, GFP_ATOMIC);
+	if (!skb)
+		goto out;
+
 	if (!pskb_may_pull(skb, arp_hdr_len(bond_dev)))
 		goto out;
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/bonding/bond_alb.h linux-libre-2.6.38-gnu1/drivers/net/bonding/bond_alb.h
--- linux-libre-2.6.37-gnu1/drivers/net/bonding/bond_alb.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/bonding/bond_alb.h	2011-03-14 21:20:32.000000000 -0400
@@ -31,6 +31,44 @@ struct slave;
 #define BOND_ALB_INFO(bond)   ((bond)->alb_info)
 #define SLAVE_TLB_INFO(slave) ((slave)->tlb_info)
 
+#define ALB_TIMER_TICKS_PER_SEC	    10	/* should be a divisor of HZ */
+#define BOND_TLB_REBALANCE_INTERVAL 10	/* In seconds, periodic re-balancing.
+					 * Used for division - never set
+					 * to zero !!!
+					 */
+#define BOND_ALB_LP_INTERVAL	    1	/* In seconds, periodic send of
+					 * learning packets to the switch
+					 */
+
+#define BOND_TLB_REBALANCE_TICKS (BOND_TLB_REBALANCE_INTERVAL \
+				  * ALB_TIMER_TICKS_PER_SEC)
+
+#define BOND_ALB_LP_TICKS (BOND_ALB_LP_INTERVAL \
+			   * ALB_TIMER_TICKS_PER_SEC)
+
+#define TLB_HASH_TABLE_SIZE 256	/* The size of the clients hash table.
+				 * Note that this value MUST NOT be smaller
+				 * because the key hash table is BYTE wide !
+				 */
+
+
+#define TLB_NULL_INDEX		0xffffffff
+#define MAX_LP_BURST		3
+
+/* rlb defs */
+#define RLB_HASH_TABLE_SIZE	256
+#define RLB_NULL_INDEX		0xffffffff
+#define RLB_UPDATE_DELAY	(2*ALB_TIMER_TICKS_PER_SEC) /* 2 seconds */
+#define RLB_ARP_BURST_SIZE	2
+#define RLB_UPDATE_RETRY	3 /* 3-ticks - must be smaller than the rlb
+				   * rebalance interval (5 min).
+				   */
+/* RLB_PROMISC_TIMEOUT = 10 sec equals the time that the current slave is
+ * promiscuous after failover
+ */
+#define RLB_PROMISC_TIMEOUT	(10*ALB_TIMER_TICKS_PER_SEC)
+
+
 struct tlb_client_info {
 	struct slave *tx_slave;	/* A pointer to slave used for transmiting
 				 * packets to a Client that the Hash function
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/bonding/bond_debugfs.c linux-libre-2.6.38-gnu1/drivers/net/bonding/bond_debugfs.c
--- linux-libre-2.6.37-gnu1/drivers/net/bonding/bond_debugfs.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/bonding/bond_debugfs.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,146 @@
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/netdevice.h>
+
+#include "bonding.h"
+#include "bond_alb.h"
+
+#ifdef CONFIG_DEBUG_FS
+
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+
+static struct dentry *bonding_debug_root;
+
+/*
+ *  Show RLB hash table
+ */
+static int bond_debug_rlb_hash_show(struct seq_file *m, void *v)
+{
+	struct bonding *bond = m->private;
+	struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
+	struct rlb_client_info *client_info;
+	u32 hash_index;
+
+	if (bond->params.mode != BOND_MODE_ALB)
+		return 0;
+
+	seq_printf(m, "SourceIP        DestinationIP   "
+			"Destination MAC   DEV\n");
+
+	spin_lock_bh(&(BOND_ALB_INFO(bond).rx_hashtbl_lock));
+
+	hash_index = bond_info->rx_hashtbl_head;
+	for (; hash_index != RLB_NULL_INDEX; hash_index = client_info->next) {
+		client_info = &(bond_info->rx_hashtbl[hash_index]);
+		seq_printf(m, "%-15pI4 %-15pI4 %-17pM %s\n",
+			&client_info->ip_src,
+			&client_info->ip_dst,
+			&client_info->mac_dst,
+			client_info->slave->dev->name);
+	}
+
+	spin_unlock_bh(&(BOND_ALB_INFO(bond).rx_hashtbl_lock));
+
+	return 0;
+}
+
+static int bond_debug_rlb_hash_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, bond_debug_rlb_hash_show, inode->i_private);
+}
+
+static const struct file_operations bond_debug_rlb_hash_fops = {
+	.owner		= THIS_MODULE,
+	.open		= bond_debug_rlb_hash_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+void bond_debug_register(struct bonding *bond)
+{
+	if (!bonding_debug_root)
+		return;
+
+	bond->debug_dir =
+		debugfs_create_dir(bond->dev->name, bonding_debug_root);
+
+	if (!bond->debug_dir) {
+		pr_warning("%s: Warning: failed to register to debugfs\n",
+			bond->dev->name);
+		return;
+	}
+
+	debugfs_create_file("rlb_hash_table", 0400, bond->debug_dir,
+				bond, &bond_debug_rlb_hash_fops);
+}
+
+void bond_debug_unregister(struct bonding *bond)
+{
+	if (!bonding_debug_root)
+		return;
+
+	debugfs_remove_recursive(bond->debug_dir);
+}
+
+void bond_debug_reregister(struct bonding *bond)
+{
+	struct dentry *d;
+
+	if (!bonding_debug_root)
+		return;
+
+	d = debugfs_rename(bonding_debug_root, bond->debug_dir,
+			   bonding_debug_root, bond->dev->name);
+	if (d) {
+		bond->debug_dir = d;
+	} else {
+		pr_warning("%s: Warning: failed to reregister, "
+				"so just unregister old one\n",
+				bond->dev->name);
+		bond_debug_unregister(bond);
+	}
+}
+
+void bond_create_debugfs(void)
+{
+	bonding_debug_root = debugfs_create_dir("bonding", NULL);
+
+	if (!bonding_debug_root) {
+		pr_warning("Warning: Cannot create bonding directory"
+				" in debugfs\n");
+	}
+}
+
+void bond_destroy_debugfs(void)
+{
+	debugfs_remove_recursive(bonding_debug_root);
+	bonding_debug_root = NULL;
+}
+
+
+#else /* !CONFIG_DEBUG_FS */
+
+void bond_debug_register(struct bonding *bond)
+{
+}
+
+void bond_debug_unregister(struct bonding *bond)
+{
+}
+
+void bond_debug_reregister(struct bonding *bond)
+{
+}
+
+void bond_create_debugfs(void)
+{
+}
+
+void bond_destroy_debugfs(void)
+{
+}
+
+#endif /* CONFIG_DEBUG_FS */
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/bonding/bonding.h linux-libre-2.6.38-gnu1/drivers/net/bonding/bonding.h
--- linux-libre-2.6.37-gnu1/drivers/net/bonding/bonding.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/bonding/bonding.h	2011-03-14 21:20:32.000000000 -0400
@@ -18,7 +18,6 @@
 #include <linux/timer.h>
 #include <linux/proc_fs.h>
 #include <linux/if_bonding.h>
-#include <linux/kobject.h>
 #include <linux/cpumask.h>
 #include <linux/in6.h>
 #include "bond_3ad.h"
@@ -255,6 +254,10 @@ struct bonding {
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 	struct   in6_addr master_ipv6;
 #endif
+#ifdef CONFIG_DEBUG_FS
+	/* debugging suport via debugfs */
+	struct	 dentry *debug_dir;
+#endif /* CONFIG_DEBUG_FS */
 };
 
 /**
@@ -282,7 +285,7 @@ static inline struct bonding *bond_get_b
 		return NULL;
 	}
 
-	return (struct bonding *)netdev_priv(slave->dev->master);
+	return netdev_priv(slave->dev->master);
 }
 
 static inline bool bond_is_lb(const struct bonding *bond)
@@ -376,6 +379,11 @@ void bond_select_active_slave(struct bon
 void bond_change_active_slave(struct bonding *bond, struct slave *new_active);
 void bond_register_arp(struct bonding *);
 void bond_unregister_arp(struct bonding *);
+void bond_create_debugfs(void);
+void bond_destroy_debugfs(void);
+void bond_debug_register(struct bonding *bond);
+void bond_debug_unregister(struct bonding *bond);
+void bond_debug_reregister(struct bonding *bond);
 
 struct bond_net {
 	struct net *		net;	/* Associated network namespace */
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/bonding/bond_main.c linux-libre-2.6.38-gnu1/drivers/net/bonding/bond_main.c
--- linux-libre-2.6.37-gnu1/drivers/net/bonding/bond_main.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/bonding/bond_main.c	2011-03-14 21:20:32.000000000 -0400
@@ -848,17 +848,11 @@ static void bond_mc_del(struct bonding *
 static void __bond_resend_igmp_join_requests(struct net_device *dev)
 {
 	struct in_device *in_dev;
-	struct ip_mc_list *im;
 
 	rcu_read_lock();
 	in_dev = __in_dev_get_rcu(dev);
-	if (in_dev) {
-		read_lock(&in_dev->mc_list_lock);
-		for (im = in_dev->mc_list; im; im = im->next)
-			ip_mc_rejoin_group(im);
-		read_unlock(&in_dev->mc_list_lock);
-	}
-
+	if (in_dev)
+		ip_mc_rejoin_groups(in_dev);
 	rcu_read_unlock();
 }
 
@@ -2739,6 +2733,10 @@ static int bond_arp_rcv(struct sk_buff *
 	if (!slave || !slave_do_arp_validate(bond, slave))
 		goto out_unlock;
 
+	skb = skb_share_check(skb, GFP_ATOMIC);
+	if (!skb)
+		goto out_unlock;
+
 	if (!pskb_may_pull(skb, arp_hdr_len(dev)))
 		goto out_unlock;
 
@@ -3189,7 +3187,7 @@ out:
 #ifdef CONFIG_PROC_FS
 
 static void *bond_info_seq_start(struct seq_file *seq, loff_t *pos)
-	__acquires(&dev_base_lock)
+	__acquires(RCU)
 	__acquires(&bond->lock)
 {
 	struct bonding *bond = seq->private;
@@ -3198,7 +3196,7 @@ static void *bond_info_seq_start(struct
 	int i;
 
 	/* make sure the bond won't be taken away */
-	read_lock(&dev_base_lock);
+	rcu_read_lock();
 	read_lock(&bond->lock);
 
 	if (*pos == 0)
@@ -3228,12 +3226,12 @@ static void *bond_info_seq_next(struct s
 
 static void bond_info_seq_stop(struct seq_file *seq, void *v)
 	__releases(&bond->lock)
-	__releases(&dev_base_lock)
+	__releases(RCU)
 {
 	struct bonding *bond = seq->private;
 
 	read_unlock(&bond->lock);
-	read_unlock(&dev_base_lock);
+	rcu_read_unlock();
 }
 
 static void bond_info_show_master(struct seq_file *seq)
@@ -3487,6 +3485,8 @@ static int bond_event_changename(struct
 	bond_remove_proc_entry(bond);
 	bond_create_proc_entry(bond);
 
+	bond_debug_reregister(bond);
+
 	return NOTIFY_DONE;
 }
 
@@ -4769,6 +4769,8 @@ static void bond_uninit(struct net_devic
 
 	bond_remove_proc_entry(bond);
 
+	bond_debug_unregister(bond);
+
 	__hw_addr_flush(&bond->mc_list);
 
 	list_for_each_entry_safe(vlan, tmp, &bond->vlan_list, vlan_list) {
@@ -5171,6 +5173,8 @@ static int bond_init(struct net_device *
 
 	bond_prepare_sysfs_group(bond);
 
+	bond_debug_register(bond);
+
 	__hw_addr_init(&bond->mc_list);
 	return 0;
 }
@@ -5285,6 +5289,8 @@ static int __init bonding_init(void)
 	if (res)
 		goto err_link;
 
+	bond_create_debugfs();
+
 	for (i = 0; i < max_bonds; i++) {
 		res = bond_create(&init_net, NULL);
 		if (res)
@@ -5295,7 +5301,6 @@ static int __init bonding_init(void)
 	if (res)
 		goto err;
 
-
 	register_netdevice_notifier(&bond_netdev_notifier);
 	register_inetaddr_notifier(&bond_inetaddr_notifier);
 	bond_register_ipv6_notifier();
@@ -5316,6 +5321,7 @@ static void __exit bonding_exit(void)
 	bond_unregister_ipv6_notifier();
 
 	bond_destroy_sysfs();
+	bond_destroy_debugfs();
 
 	rtnl_link_unregister(&bond_link_ops);
 	unregister_pernet_subsys(&bond_net_ops);
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/bonding/Makefile linux-libre-2.6.38-gnu1/drivers/net/bonding/Makefile
--- linux-libre-2.6.37-gnu1/drivers/net/bonding/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/bonding/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -4,7 +4,7 @@
 
 obj-$(CONFIG_BONDING) += bonding.o
 
-bonding-objs := bond_main.o bond_3ad.o bond_alb.o bond_sysfs.o
+bonding-objs := bond_main.o bond_3ad.o bond_alb.o bond_sysfs.o bond_debugfs.o
 
 ipv6-$(subst m,y,$(CONFIG_IPV6)) += bond_ipv6.o
 bonding-objs += $(ipv6-y)
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/caif/caif_shm_u5500.c linux-libre-2.6.38-gnu1/drivers/net/caif/caif_shm_u5500.c
--- linux-libre-2.6.37-gnu1/drivers/net/caif/caif_shm_u5500.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/caif/caif_shm_u5500.c	2011-03-14 21:20:32.000000000 -0400
@@ -11,7 +11,7 @@
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/netdevice.h>
-#include <mach/mbox.h>
+#include <mach/mbox-db5500.h>
 #include <net/caif/caif_shm.h>
 
 MODULE_LICENSE("GPL");
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/can/at91_can.c linux-libre-2.6.38-gnu1/drivers/net/can/at91_can.c
--- linux-libre-2.6.37-gnu1/drivers/net/can/at91_can.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/can/at91_can.c	2011-03-14 21:20:32.000000000 -0400
@@ -2,7 +2,7 @@
  * at91_can.c - CAN network driver for AT91 SoC CAN controller
  *
  * (C) 2007 by Hans J. Koch <hjk@hansjkoch.de>
- * (C) 2008, 2009, 2010 by Marc Kleine-Budde <kernel@pengutronix.de>
+ * (C) 2008, 2009, 2010, 2011 by Marc Kleine-Budde <kernel@pengutronix.de>
  *
  * This software may be distributed under the terms of the GNU General
  * Public License ("GPL") version 2 as distributed in the 'COPYING'
@@ -30,6 +30,7 @@
 #include <linux/module.h>
 #include <linux/netdevice.h>
 #include <linux/platform_device.h>
+#include <linux/rtnetlink.h>
 #include <linux/skbuff.h>
 #include <linux/spinlock.h>
 #include <linux/string.h>
@@ -40,22 +41,23 @@
 
 #include <mach/board.h>
 
-#define AT91_NAPI_WEIGHT	12
+#define AT91_NAPI_WEIGHT	11
 
 /*
  * RX/TX Mailbox split
  * don't dare to touch
  */
-#define AT91_MB_RX_NUM		12
+#define AT91_MB_RX_NUM		11
 #define AT91_MB_TX_SHIFT	2
 
-#define AT91_MB_RX_FIRST	0
+#define AT91_MB_RX_FIRST	1
 #define AT91_MB_RX_LAST		(AT91_MB_RX_FIRST + AT91_MB_RX_NUM - 1)
 
 #define AT91_MB_RX_MASK(i)	((1 << (i)) - 1)
 #define AT91_MB_RX_SPLIT	8
 #define AT91_MB_RX_LOW_LAST	(AT91_MB_RX_SPLIT - 1)
-#define AT91_MB_RX_LOW_MASK	(AT91_MB_RX_MASK(AT91_MB_RX_SPLIT))
+#define AT91_MB_RX_LOW_MASK	(AT91_MB_RX_MASK(AT91_MB_RX_SPLIT) & \
+				 ~AT91_MB_RX_MASK(AT91_MB_RX_FIRST))
 
 #define AT91_MB_TX_NUM		(1 << AT91_MB_TX_SHIFT)
 #define AT91_MB_TX_FIRST	(AT91_MB_RX_LAST + 1)
@@ -168,6 +170,8 @@ struct at91_priv {
 
 	struct clk		*clk;
 	struct at91_can_data	*pdata;
+
+	canid_t			mb0_id;
 };
 
 static struct can_bittiming_const at91_bittiming_const = {
@@ -220,6 +224,18 @@ static inline void set_mb_mode(const str
 	set_mb_mode_prio(priv, mb, mode, 0);
 }
 
+static inline u32 at91_can_id_to_reg_mid(canid_t can_id)
+{
+	u32 reg_mid;
+
+	if (can_id & CAN_EFF_FLAG)
+		reg_mid = (can_id & CAN_EFF_MASK) | AT91_MID_MIDE;
+	else
+		reg_mid = (can_id & CAN_SFF_MASK) << 18;
+
+	return reg_mid;
+}
+
 /*
  * Swtich transceiver on or off
  */
@@ -233,12 +249,22 @@ static void at91_setup_mailboxes(struct
 {
 	struct at91_priv *priv = netdev_priv(dev);
 	unsigned int i;
+	u32 reg_mid;
 
 	/*
-	 * The first 12 mailboxes are used as a reception FIFO. The
-	 * last mailbox is configured with overwrite option. The
-	 * overwrite flag indicates a FIFO overflow.
+	 * Due to a chip bug (errata 50.2.6.3 & 50.3.5.3) the first
+	 * mailbox is disabled. The next 11 mailboxes are used as a
+	 * reception FIFO. The last mailbox is configured with
+	 * overwrite option. The overwrite flag indicates a FIFO
+	 * overflow.
 	 */
+	reg_mid = at91_can_id_to_reg_mid(priv->mb0_id);
+	for (i = 0; i < AT91_MB_RX_FIRST; i++) {
+		set_mb_mode(priv, i, AT91_MB_MODE_DISABLED);
+		at91_write(priv, AT91_MID(i), reg_mid);
+		at91_write(priv, AT91_MCR(i), 0x0);	/* clear dlc */
+	}
+
 	for (i = AT91_MB_RX_FIRST; i < AT91_MB_RX_LAST; i++)
 		set_mb_mode(priv, i, AT91_MB_MODE_RX);
 	set_mb_mode(priv, AT91_MB_RX_LAST, AT91_MB_MODE_RX_OVRWR);
@@ -254,7 +280,8 @@ static void at91_setup_mailboxes(struct
 		set_mb_mode_prio(priv, i, AT91_MB_MODE_TX, 0);
 
 	/* Reset tx and rx helper pointers */
-	priv->tx_next = priv->tx_echo = priv->rx_next = 0;
+	priv->tx_next = priv->tx_echo = 0;
+	priv->rx_next = AT91_MB_RX_FIRST;
 }
 
 static int at91_set_bittiming(struct net_device *dev)
@@ -372,12 +399,7 @@ static netdev_tx_t at91_start_xmit(struc
 		netdev_err(dev, "BUG! TX buffer full when queue awake!\n");
 		return NETDEV_TX_BUSY;
 	}
-
-	if (cf->can_id & CAN_EFF_FLAG)
-		reg_mid = (cf->can_id & CAN_EFF_MASK) | AT91_MID_MIDE;
-	else
-		reg_mid = (cf->can_id & CAN_SFF_MASK) << 18;
-
+	reg_mid = at91_can_id_to_reg_mid(cf->can_id);
 	reg_mcr = ((cf->can_id & CAN_RTR_FLAG) ? AT91_MCR_MRTR : 0) |
 		(cf->can_dlc << 16) | AT91_MCR_MTCR;
 
@@ -539,27 +561,31 @@ static void at91_read_msg(struct net_dev
  *
  * Theory of Operation:
  *
- * 12 of the 16 mailboxes on the chip are reserved for RX. we split
- * them into 2 groups. The lower group holds 8 and upper 4 mailboxes.
+ * 11 of the 16 mailboxes on the chip are reserved for RX. we split
+ * them into 2 groups. The lower group holds 7 and upper 4 mailboxes.
  *
  * Like it or not, but the chip always saves a received CAN message
  * into the first free mailbox it finds (starting with the
  * lowest). This makes it very difficult to read the messages in the
  * right order from the chip. This is how we work around that problem:
  *
- * The first message goes into mb nr. 0 and issues an interrupt. All
+ * The first message goes into mb nr. 1 and issues an interrupt. All
  * rx ints are disabled in the interrupt handler and a napi poll is
  * scheduled. We read the mailbox, but do _not_ reenable the mb (to
  * receive another message).
  *
  *    lower mbxs      upper
- *   ______^______    __^__
- *  /             \  /     \
+ *     ____^______    __^__
+ *    /           \  /     \
  * +-+-+-+-+-+-+-+-++-+-+-+-+
- * |x|x|x|x|x|x|x|x|| | | | |
+ * | |x|x|x|x|x|x|x|| | | | |
  * +-+-+-+-+-+-+-+-++-+-+-+-+
  *  0 0 0 0 0 0  0 0 0 0 1 1  \ mail
  *  0 1 2 3 4 5  6 7 8 9 0 1  / box
+ *  ^
+ *  |
+ *   \
+ *     unused, due to chip bug
  *
  * The variable priv->rx_next points to the next mailbox to read a
  * message from. As long we're in the lower mailboxes we just read the
@@ -590,10 +616,10 @@ static int at91_poll_rx(struct net_devic
 			"order of incoming frames cannot be guaranteed\n");
 
  again:
-	for (mb = find_next_bit(addr, AT91_MB_RX_NUM, priv->rx_next);
-	     mb < AT91_MB_RX_NUM && quota > 0;
+	for (mb = find_next_bit(addr, AT91_MB_RX_LAST + 1, priv->rx_next);
+	     mb < AT91_MB_RX_LAST + 1 && quota > 0;
 	     reg_sr = at91_read(priv, AT91_SR),
-	     mb = find_next_bit(addr, AT91_MB_RX_NUM, ++priv->rx_next)) {
+	     mb = find_next_bit(addr, AT91_MB_RX_LAST + 1, ++priv->rx_next)) {
 		at91_read_msg(dev, mb);
 
 		/* reactivate mailboxes */
@@ -610,8 +636,8 @@ static int at91_poll_rx(struct net_devic
 
 	/* upper group completed, look again in lower */
 	if (priv->rx_next > AT91_MB_RX_LOW_LAST &&
-	    quota > 0 && mb >= AT91_MB_RX_NUM) {
-		priv->rx_next = 0;
+	    quota > 0 && mb > AT91_MB_RX_LAST) {
+		priv->rx_next = AT91_MB_RX_FIRST;
 		goto again;
 	}
 
@@ -1037,6 +1063,64 @@ static const struct net_device_ops at91_
 	.ndo_start_xmit	= at91_start_xmit,
 };
 
+static ssize_t at91_sysfs_show_mb0_id(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct at91_priv *priv = netdev_priv(to_net_dev(dev));
+
+	if (priv->mb0_id & CAN_EFF_FLAG)
+		return snprintf(buf, PAGE_SIZE, "0x%08x\n", priv->mb0_id);
+	else
+		return snprintf(buf, PAGE_SIZE, "0x%03x\n", priv->mb0_id);
+}
+
+static ssize_t at91_sysfs_set_mb0_id(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct net_device *ndev = to_net_dev(dev);
+	struct at91_priv *priv = netdev_priv(ndev);
+	unsigned long can_id;
+	ssize_t ret;
+	int err;
+
+	rtnl_lock();
+
+	if (ndev->flags & IFF_UP) {
+		ret = -EBUSY;
+		goto out;
+	}
+
+	err = strict_strtoul(buf, 0, &can_id);
+	if (err) {
+		ret = err;
+		goto out;
+	}
+
+	if (can_id & CAN_EFF_FLAG)
+		can_id &= CAN_EFF_MASK | CAN_EFF_FLAG;
+	else
+		can_id &= CAN_SFF_MASK;
+
+	priv->mb0_id = can_id;
+	ret = count;
+
+ out:
+	rtnl_unlock();
+	return ret;
+}
+
+static DEVICE_ATTR(mb0_id, S_IWUSR | S_IRUGO,
+	at91_sysfs_show_mb0_id, at91_sysfs_set_mb0_id);
+
+static struct attribute *at91_sysfs_attrs[] = {
+	&dev_attr_mb0_id.attr,
+	NULL,
+};
+
+static struct attribute_group at91_sysfs_attr_group = {
+	.attrs = at91_sysfs_attrs,
+};
+
 static int __devinit at91_can_probe(struct platform_device *pdev)
 {
 	struct net_device *dev;
@@ -1082,6 +1166,7 @@ static int __devinit at91_can_probe(stru
 	dev->netdev_ops	= &at91_netdev_ops;
 	dev->irq = irq;
 	dev->flags |= IFF_ECHO;
+	dev->sysfs_groups[0] = &at91_sysfs_attr_group;
 
 	priv = netdev_priv(dev);
 	priv->can.clock.freq = clk_get_rate(clk);
@@ -1093,6 +1178,7 @@ static int __devinit at91_can_probe(stru
 	priv->dev = dev;
 	priv->clk = clk;
 	priv->pdata = pdev->dev.platform_data;
+	priv->mb0_id = 0x7ff;
 
 	netif_napi_add(dev, &priv->napi, at91_poll, AT91_NAPI_WEIGHT);
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/can/janz-ican3.c linux-libre-2.6.38-gnu1/drivers/net/can/janz-ican3.c
--- linux-libre-2.6.37-gnu1/drivers/net/can/janz-ican3.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/can/janz-ican3.c	2011-03-14 21:20:32.000000000 -0400
@@ -1114,11 +1114,6 @@ static bool ican3_txok(struct ican3_dev
 /*
  * Recieve one CAN frame from the hardware
  *
- * This works like the core of a NAPI function, but is intended to be called
- * from workqueue context instead. This driver already needs a workqueue to
- * process control messages, so we use the workqueue instead of using NAPI.
- * This was done to simplify locking.
- *
  * CONTEXT: must be called from user context
  */
 static int ican3_recv_skb(struct ican3_dev *mod)
@@ -1251,7 +1246,6 @@ static irqreturn_t ican3_irq(int irq, vo
  * Reset an ICAN module to its power-on state
  *
  * CONTEXT: no network device registered
- * LOCKING: work function disabled
  */
 static int ican3_reset_module(struct ican3_dev *mod)
 {
@@ -1262,9 +1256,6 @@ static int ican3_reset_module(struct ica
 	/* disable interrupts so no more work is scheduled */
 	iowrite8(1 << mod->num, &mod->ctrl->int_disable);
 
-	/* flush any pending work */
-	flush_scheduled_work();
-
 	/* the first unallocated page in the DPM is #9 */
 	mod->free_page = DPM_FREE_START;
 
@@ -1627,7 +1618,7 @@ static ssize_t ican3_sysfs_set_term(stru
 	return count;
 }
 
-static DEVICE_ATTR(termination, S_IWUGO | S_IRUGO, ican3_sysfs_show_term,
+static DEVICE_ATTR(termination, S_IWUSR | S_IRUGO, ican3_sysfs_show_term,
 						   ican3_sysfs_set_term);
 
 static struct attribute *ican3_sysfs_attrs[] = {
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/can/Kconfig linux-libre-2.6.38-gnu1/drivers/net/can/Kconfig
--- linux-libre-2.6.37-gnu1/drivers/net/can/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/can/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -12,6 +12,27 @@ config CAN_VCAN
 	  This driver can also be built as a module.  If so, the module
 	  will be called vcan.
 
+config CAN_SLCAN
+	tristate "Serial / USB serial CAN Adaptors (slcan)"
+	depends on CAN
+	default N
+	---help---
+	  CAN driver for several 'low cost' CAN interfaces that are attached
+	  via serial lines or via USB-to-serial adapters using the LAWICEL
+	  ASCII protocol. The driver implements the tty linediscipline N_SLCAN.
+
+	  As only the sending and receiving of CAN frames is implemented, this
+	  driver should work with the (serial/USB) CAN hardware from:
+	  www.canusb.com / www.can232.com / www.mictronics.de / www.canhack.de
+
+	  Userspace tools to attach the SLCAN line discipline (slcan_attach,
+	  slcand) can be found in the can-utils at the SocketCAN SVN, see
+	  http://developer.berlios.de/projects/socketcan for details.
+
+	  The slcan driver supports up to 10 CAN netdevices by default which
+	  can be changed by the 'maxdev=xx' module option. This driver can
+	  also be built as a module. If so, the module will be called slcan.
+
 config CAN_DEV
 	tristate "Platform CAN drivers with Netlink support"
 	depends on CAN
@@ -96,6 +117,8 @@ source "drivers/net/can/sja1000/Kconfig"
 
 source "drivers/net/can/usb/Kconfig"
 
+source "drivers/net/can/softing/Kconfig"
+
 config CAN_DEBUG_DEVICES
 	bool "CAN devices debugging messages"
 	depends on CAN
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/can/Makefile linux-libre-2.6.38-gnu1/drivers/net/can/Makefile
--- linux-libre-2.6.37-gnu1/drivers/net/can/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/can/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -3,11 +3,13 @@
 #
 
 obj-$(CONFIG_CAN_VCAN)		+= vcan.o
+obj-$(CONFIG_CAN_SLCAN)		+= slcan.o
 
 obj-$(CONFIG_CAN_DEV)		+= can-dev.o
 can-dev-y			:= dev.o
 
 obj-y				+= usb/
+obj-y				+= softing/
 
 obj-$(CONFIG_CAN_SJA1000)	+= sja1000/
 obj-$(CONFIG_CAN_MSCAN)		+= mscan/
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/can/mcp251x.c linux-libre-2.6.38-gnu1/drivers/net/can/mcp251x.c
--- linux-libre-2.6.37-gnu1/drivers/net/can/mcp251x.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/can/mcp251x.c	2011-03-14 21:20:32.000000000 -0400
@@ -940,7 +940,7 @@ static int mcp251x_open(struct net_devic
 		goto open_unlock;
 	}
 
-	priv->wq = create_freezeable_workqueue("mcp251x_wq");
+	priv->wq = create_freezable_workqueue("mcp251x_wq");
 	INIT_WORK(&priv->tx_work, mcp251x_tx_work_handler);
 	INIT_WORK(&priv->restart_work, mcp251x_restart_work_handler);
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/can/mscan/Kconfig linux-libre-2.6.38-gnu1/drivers/net/can/mscan/Kconfig
--- linux-libre-2.6.37-gnu1/drivers/net/can/mscan/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/can/mscan/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -1,5 +1,5 @@
 config CAN_MSCAN
-	depends on CAN_DEV && (PPC || M68K || M68KNOMMU)
+	depends on CAN_DEV && (PPC || M68K)
 	tristate "Support for Freescale MSCAN based chips"
 	---help---
 	  The Motorola Scalable Controller Area Network (MSCAN) definition
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/can/mscan/mscan.c linux-libre-2.6.38-gnu1/drivers/net/can/mscan/mscan.c
--- linux-libre-2.6.37-gnu1/drivers/net/can/mscan/mscan.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/can/mscan/mscan.c	2011-03-14 21:20:32.000000000 -0400
@@ -182,7 +182,7 @@ static int mscan_restart(struct net_devi
 
 		priv->can.state = CAN_STATE_ERROR_ACTIVE;
 		WARN(!(in_8(&regs->canmisc) & MSCAN_BOHOLD),
-		     "bus-off state expected");
+		     "bus-off state expected\n");
 		out_8(&regs->canmisc, MSCAN_BOHOLD);
 		/* Re-enable receive interrupts. */
 		out_8(&regs->canrier, MSCAN_RX_INTS_ENABLE);
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/can/pch_can.c linux-libre-2.6.38-gnu1/drivers/net/can/pch_can.c
--- linux-libre-2.6.37-gnu1/drivers/net/can/pch_can.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/can/pch_can.c	2011-03-14 21:20:32.000000000 -0400
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 1999 - 2010 Intel Corporation.
- * Copyright (C) 2010 OKI SEMICONDUCTOR Co., LTD.
+ * Copyright (C) 2010 OKI SEMICONDUCTOR 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
@@ -32,106 +32,115 @@
 #include <linux/can/dev.h>
 #include <linux/can/error.h>
 
-#define MAX_MSG_OBJ		32
-#define MSG_OBJ_RX		0 /* The receive message object flag. */
-#define MSG_OBJ_TX		1 /* The transmit message object flag. */
-
-#define ENABLE			1 /* The enable flag */
-#define DISABLE			0 /* The disable flag */
-#define CAN_CTRL_INIT		0x0001 /* The INIT bit of CANCONT register. */
-#define CAN_CTRL_IE		0x0002 /* The IE bit of CAN control register */
-#define CAN_CTRL_IE_SIE_EIE	0x000e
-#define CAN_CTRL_CCE		0x0040
-#define CAN_CTRL_OPT		0x0080 /* The OPT bit of CANCONT register. */
-#define CAN_OPT_SILENT		0x0008 /* The Silent bit of CANOPT reg. */
-#define CAN_OPT_LBACK		0x0010 /* The LoopBack bit of CANOPT reg. */
-#define CAN_CMASK_RX_TX_SET	0x00f3
-#define CAN_CMASK_RX_TX_GET	0x0073
-#define CAN_CMASK_ALL		0xff
-#define CAN_CMASK_RDWR		0x80
-#define CAN_CMASK_ARB		0x20
-#define CAN_CMASK_CTRL		0x10
-#define CAN_CMASK_MASK		0x40
-#define CAN_CMASK_NEWDAT	0x04
-#define CAN_CMASK_CLRINTPND	0x08
-
-#define CAN_IF_MCONT_NEWDAT	0x8000
-#define CAN_IF_MCONT_INTPND	0x2000
-#define CAN_IF_MCONT_UMASK	0x1000
-#define CAN_IF_MCONT_TXIE	0x0800
-#define CAN_IF_MCONT_RXIE	0x0400
-#define CAN_IF_MCONT_RMTEN	0x0200
-#define CAN_IF_MCONT_TXRQXT	0x0100
-#define CAN_IF_MCONT_EOB	0x0080
-#define CAN_IF_MCONT_DLC	0x000f
-#define CAN_IF_MCONT_MSGLOST	0x4000
-#define CAN_MASK2_MDIR_MXTD	0xc000
-#define CAN_ID2_DIR		0x2000
-#define CAN_ID_MSGVAL		0x8000
+#define PCH_CTRL_INIT		BIT(0) /* The INIT bit of CANCONT register. */
+#define PCH_CTRL_IE		BIT(1) /* The IE bit of CAN control register */
+#define PCH_CTRL_IE_SIE_EIE	(BIT(3) | BIT(2) | BIT(1))
+#define PCH_CTRL_CCE		BIT(6)
+#define PCH_CTRL_OPT		BIT(7) /* The OPT bit of CANCONT register. */
+#define PCH_OPT_SILENT		BIT(3) /* The Silent bit of CANOPT reg. */
+#define PCH_OPT_LBACK		BIT(4) /* The LoopBack bit of CANOPT reg. */
 
-#define CAN_STATUS_INT		0x8000
-#define CAN_IF_CREQ_BUSY	0x8000
-#define CAN_ID2_XTD		0x4000
+#define PCH_CMASK_RX_TX_SET	0x00f3
+#define PCH_CMASK_RX_TX_GET	0x0073
+#define PCH_CMASK_ALL		0xff
+#define PCH_CMASK_NEWDAT	BIT(2)
+#define PCH_CMASK_CLRINTPND	BIT(3)
+#define PCH_CMASK_CTRL		BIT(4)
+#define PCH_CMASK_ARB		BIT(5)
+#define PCH_CMASK_MASK		BIT(6)
+#define PCH_CMASK_RDWR		BIT(7)
+#define PCH_IF_MCONT_NEWDAT	BIT(15)
+#define PCH_IF_MCONT_MSGLOST	BIT(14)
+#define PCH_IF_MCONT_INTPND	BIT(13)
+#define PCH_IF_MCONT_UMASK	BIT(12)
+#define PCH_IF_MCONT_TXIE	BIT(11)
+#define PCH_IF_MCONT_RXIE	BIT(10)
+#define PCH_IF_MCONT_RMTEN	BIT(9)
+#define PCH_IF_MCONT_TXRQXT	BIT(8)
+#define PCH_IF_MCONT_EOB	BIT(7)
+#define PCH_IF_MCONT_DLC	(BIT(0) | BIT(1) | BIT(2) | BIT(3))
+#define PCH_MASK2_MDIR_MXTD	(BIT(14) | BIT(15))
+#define PCH_ID2_DIR		BIT(13)
+#define PCH_ID2_XTD		BIT(14)
+#define PCH_ID_MSGVAL		BIT(15)
+#define PCH_IF_CREQ_BUSY	BIT(15)
 
-#define CAN_REC			0x00007f00
-#define CAN_TEC			0x000000ff
+#define PCH_STATUS_INT		0x8000
+#define PCH_REC			0x00007f00
+#define PCH_TEC			0x000000ff
 
-#define PCH_RX_OK		0x00000010
-#define PCH_TX_OK		0x00000008
-#define PCH_BUS_OFF		0x00000080
-#define PCH_EWARN		0x00000040
-#define PCH_EPASSIV		0x00000020
-#define PCH_LEC0		0x00000001
-#define PCH_LEC1		0x00000002
-#define PCH_LEC2		0x00000004
-#define PCH_LEC_ALL		(PCH_LEC0 | PCH_LEC1 | PCH_LEC2)
-#define PCH_STUF_ERR		PCH_LEC0
-#define PCH_FORM_ERR		PCH_LEC1
-#define PCH_ACK_ERR		(PCH_LEC0 | PCH_LEC1)
-#define PCH_BIT1_ERR		PCH_LEC2
-#define PCH_BIT0_ERR		(PCH_LEC0 | PCH_LEC2)
-#define PCH_CRC_ERR		(PCH_LEC1 | PCH_LEC2)
+#define PCH_TX_OK		BIT(3)
+#define PCH_RX_OK		BIT(4)
+#define PCH_EPASSIV		BIT(5)
+#define PCH_EWARN		BIT(6)
+#define PCH_BUS_OFF		BIT(7)
 
 /* bit position of certain controller bits. */
-#define BIT_BITT_BRP		0
-#define BIT_BITT_SJW		6
-#define BIT_BITT_TSEG1		8
-#define BIT_BITT_TSEG2		12
-#define BIT_IF1_MCONT_RXIE	10
-#define BIT_IF2_MCONT_TXIE	11
-#define BIT_BRPE_BRPE		6
-#define BIT_ES_TXERRCNT		0
-#define BIT_ES_RXERRCNT		8
-#define MSK_BITT_BRP		0x3f
-#define MSK_BITT_SJW		0xc0
-#define MSK_BITT_TSEG1		0xf00
-#define MSK_BITT_TSEG2		0x7000
-#define MSK_BRPE_BRPE		0x3c0
-#define MSK_BRPE_GET		0x0f
-#define MSK_CTRL_IE_SIE_EIE	0x07
-#define MSK_MCONT_TXIE		0x08
-#define MSK_MCONT_RXIE		0x10
-#define PCH_CAN_NO_TX_BUFF	1
-#define COUNTER_LIMIT		10
+#define PCH_BIT_BRP_SHIFT	0
+#define PCH_BIT_SJW_SHIFT	6
+#define PCH_BIT_TSEG1_SHIFT	8
+#define PCH_BIT_TSEG2_SHIFT	12
+#define PCH_BIT_BRPE_BRPE_SHIFT	6
+
+#define PCH_MSK_BITT_BRP	0x3f
+#define PCH_MSK_BRPE_BRPE	0x3c0
+#define PCH_MSK_CTRL_IE_SIE_EIE	0x07
+#define PCH_COUNTER_LIMIT	10
 
 #define PCH_CAN_CLK		50000000	/* 50MHz */
 
-/* Define the number of message object.
+/*
+ * Define the number of message object.
  * PCH CAN communications are done via Message RAM.
- * The Message RAM consists of 32 message objects. */
-#define PCH_RX_OBJ_NUM		26  /* 1~ PCH_RX_OBJ_NUM is Rx*/
-#define PCH_TX_OBJ_NUM		6  /* PCH_RX_OBJ_NUM is RX ~ Tx*/
-#define PCH_OBJ_NUM		(PCH_TX_OBJ_NUM + PCH_RX_OBJ_NUM)
+ * The Message RAM consists of 32 message objects.
+ */
+#define PCH_RX_OBJ_NUM		26
+#define PCH_TX_OBJ_NUM		6
+#define PCH_RX_OBJ_START	1
+#define PCH_RX_OBJ_END		PCH_RX_OBJ_NUM
+#define PCH_TX_OBJ_START	(PCH_RX_OBJ_END + 1)
+#define PCH_TX_OBJ_END		(PCH_RX_OBJ_NUM + PCH_TX_OBJ_NUM)
 
 #define PCH_FIFO_THRESH		16
 
+/* TxRqst2 show status of MsgObjNo.17~32 */
+#define PCH_TREQ2_TX_MASK	(((1 << PCH_TX_OBJ_NUM) - 1) <<\
+							(PCH_RX_OBJ_END - 16))
+
+enum pch_ifreg {
+	PCH_RX_IFREG,
+	PCH_TX_IFREG,
+};
+
+enum pch_can_err {
+	PCH_STUF_ERR = 1,
+	PCH_FORM_ERR,
+	PCH_ACK_ERR,
+	PCH_BIT1_ERR,
+	PCH_BIT0_ERR,
+	PCH_CRC_ERR,
+	PCH_LEC_ALL,
+};
+
 enum pch_can_mode {
 	PCH_CAN_ENABLE,
 	PCH_CAN_DISABLE,
 	PCH_CAN_ALL,
 	PCH_CAN_NONE,
 	PCH_CAN_STOP,
-	PCH_CAN_RUN
+	PCH_CAN_RUN,
+};
+
+struct pch_can_if_regs {
+	u32 creq;
+	u32 cmask;
+	u32 mask1;
+	u32 mask2;
+	u32 id1;
+	u32 id2;
+	u32 mcont;
+	u32 data[4];
+	u32 rsv[13];
 };
 
 struct pch_can_regs {
@@ -142,62 +151,41 @@ struct pch_can_regs {
 	u32 intr;
 	u32 opt;
 	u32 brpe;
-	u32 reserve1;
-	u32 if1_creq;
-	u32 if1_cmask;
-	u32 if1_mask1;
-	u32 if1_mask2;
-	u32 if1_id1;
-	u32 if1_id2;
-	u32 if1_mcont;
-	u32 if1_dataa1;
-	u32 if1_dataa2;
-	u32 if1_datab1;
-	u32 if1_datab2;
-	u32 reserve2;
-	u32 reserve3[12];
-	u32 if2_creq;
-	u32 if2_cmask;
-	u32 if2_mask1;
-	u32 if2_mask2;
-	u32 if2_id1;
-	u32 if2_id2;
-	u32 if2_mcont;
-	u32 if2_dataa1;
-	u32 if2_dataa2;
-	u32 if2_datab1;
-	u32 if2_datab2;
-	u32 reserve4;
-	u32 reserve5[20];
+	u32 reserve;
+	struct pch_can_if_regs ifregs[2]; /* [0]=if1  [1]=if2 */
+	u32 reserve1[8];
 	u32 treq1;
 	u32 treq2;
-	u32 reserve6[2];
-	u32 reserve7[56];
-	u32 reserve8[3];
+	u32 reserve2[6];
+	u32 data1;
+	u32 data2;
+	u32 reserve3[6];
+	u32 canipend1;
+	u32 canipend2;
+	u32 reserve4[6];
+	u32 canmval1;
+	u32 canmval2;
+	u32 reserve5[37];
 	u32 srst;
 };
 
 struct pch_can_priv {
 	struct can_priv can;
-	unsigned int can_num;
 	struct pci_dev *dev;
-	unsigned int tx_enable[MAX_MSG_OBJ];
-	unsigned int rx_enable[MAX_MSG_OBJ];
-	unsigned int rx_link[MAX_MSG_OBJ];
-	unsigned int int_enables;
-	unsigned int int_stat;
+	u32 tx_enable[PCH_TX_OBJ_END];
+	u32 rx_enable[PCH_TX_OBJ_END];
+	u32 rx_link[PCH_TX_OBJ_END];
+	u32 int_enables;
 	struct net_device *ndev;
-	spinlock_t msgif_reg_lock; /* Message Interface Registers Access Lock*/
-	unsigned int msg_obj[MAX_MSG_OBJ];
 	struct pch_can_regs __iomem *regs;
 	struct napi_struct napi;
-	unsigned int tx_obj;	/* Point next Tx Obj index */
-	unsigned int use_msi;
+	int tx_obj;	/* Point next Tx Obj index */
+	int use_msi;
 };
 
 static struct can_bittiming_const pch_can_bittiming_const = {
 	.name = KBUILD_MODNAME,
-	.tseg1_min = 1,
+	.tseg1_min = 2,
 	.tseg1_max = 16,
 	.tseg2_min = 1,
 	.tseg2_max = 8,
@@ -228,15 +216,15 @@ static void pch_can_set_run_mode(struct
 {
 	switch (mode) {
 	case PCH_CAN_RUN:
-		pch_can_bit_clear(&priv->regs->cont, CAN_CTRL_INIT);
+		pch_can_bit_clear(&priv->regs->cont, PCH_CTRL_INIT);
 		break;
 
 	case PCH_CAN_STOP:
-		pch_can_bit_set(&priv->regs->cont, CAN_CTRL_INIT);
+		pch_can_bit_set(&priv->regs->cont, PCH_CTRL_INIT);
 		break;
 
 	default:
-		dev_err(&priv->ndev->dev, "%s -> Invalid Mode.\n", __func__);
+		netdev_err(priv->ndev, "%s -> Invalid Mode.\n", __func__);
 		break;
 	}
 }
@@ -246,357 +234,184 @@ static void pch_can_set_optmode(struct p
 	u32 reg_val = ioread32(&priv->regs->opt);
 
 	if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY)
-		reg_val |= CAN_OPT_SILENT;
+		reg_val |= PCH_OPT_SILENT;
 
 	if (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK)
-		reg_val |= CAN_OPT_LBACK;
+		reg_val |= PCH_OPT_LBACK;
 
-	pch_can_bit_set(&priv->regs->cont, CAN_CTRL_OPT);
+	pch_can_bit_set(&priv->regs->cont, PCH_CTRL_OPT);
 	iowrite32(reg_val, &priv->regs->opt);
 }
 
-static void pch_can_set_int_custom(struct pch_can_priv *priv)
+static void pch_can_rw_msg_obj(void __iomem *creq_addr, u32 num)
 {
-	/* Clearing the IE, SIE and EIE bits of Can control register. */
-	pch_can_bit_clear(&priv->regs->cont, CAN_CTRL_IE_SIE_EIE);
-
-	/* Appropriately setting them. */
-	pch_can_bit_set(&priv->regs->cont,
-			((priv->int_enables & MSK_CTRL_IE_SIE_EIE) << 1));
-}
+	int counter = PCH_COUNTER_LIMIT;
+	u32 ifx_creq;
 
-/* This function retrieves interrupt enabled for the CAN device. */
-static void pch_can_get_int_enables(struct pch_can_priv *priv, u32 *enables)
-{
-	/* Obtaining the status of IE, SIE and EIE interrupt bits. */
-	*enables = ((ioread32(&priv->regs->cont) & CAN_CTRL_IE_SIE_EIE) >> 1);
+	iowrite32(num, creq_addr);
+	while (counter) {
+		ifx_creq = ioread32(creq_addr) & PCH_IF_CREQ_BUSY;
+		if (!ifx_creq)
+			break;
+		counter--;
+		udelay(1);
+	}
+	if (!counter)
+		pr_err("%s:IF1 BUSY Flag is set forever.\n", __func__);
 }
 
 static void pch_can_set_int_enables(struct pch_can_priv *priv,
 				    enum pch_can_mode interrupt_no)
 {
 	switch (interrupt_no) {
-	case PCH_CAN_ENABLE:
-		pch_can_bit_set(&priv->regs->cont, CAN_CTRL_IE);
-		break;
-
 	case PCH_CAN_DISABLE:
-		pch_can_bit_clear(&priv->regs->cont, CAN_CTRL_IE);
+		pch_can_bit_clear(&priv->regs->cont, PCH_CTRL_IE);
 		break;
 
 	case PCH_CAN_ALL:
-		pch_can_bit_set(&priv->regs->cont, CAN_CTRL_IE_SIE_EIE);
+		pch_can_bit_set(&priv->regs->cont, PCH_CTRL_IE_SIE_EIE);
 		break;
 
 	case PCH_CAN_NONE:
-		pch_can_bit_clear(&priv->regs->cont, CAN_CTRL_IE_SIE_EIE);
+		pch_can_bit_clear(&priv->regs->cont, PCH_CTRL_IE_SIE_EIE);
 		break;
 
 	default:
-		dev_err(&priv->ndev->dev, "Invalid interrupt number.\n");
+		netdev_err(priv->ndev, "Invalid interrupt number.\n");
 		break;
 	}
 }
 
-static void pch_can_check_if_busy(u32 __iomem *creq_addr, u32 num)
-{
-	u32 counter = COUNTER_LIMIT;
-	u32 ifx_creq;
-
-	iowrite32(num, creq_addr);
-	while (counter) {
-		ifx_creq = ioread32(creq_addr) & CAN_IF_CREQ_BUSY;
-		if (!ifx_creq)
-			break;
-		counter--;
-		udelay(1);
-	}
-	if (!counter)
-		pr_err("%s:IF1 BUSY Flag is set forever.\n", __func__);
-}
-
-static void pch_can_set_rx_enable(struct pch_can_priv *priv, u32 buff_num,
-				  u32 set)
+static void pch_can_set_rxtx(struct pch_can_priv *priv, u32 buff_num,
+			     int set, enum pch_ifreg dir)
 {
-	unsigned long flags;
+	u32 ie;
 
-	spin_lock_irqsave(&priv->msgif_reg_lock, flags);
-	/* Reading the receive buffer data from RAM to Interface1 registers */
-	iowrite32(CAN_CMASK_RX_TX_GET, &priv->regs->if1_cmask);
-	pch_can_check_if_busy(&priv->regs->if1_creq, buff_num);
+	if (dir)
+		ie = PCH_IF_MCONT_TXIE;
+	else
+		ie = PCH_IF_MCONT_RXIE;
 
-	/* Setting the IF1MASK1 register to access MsgVal and RxIE bits */
-	iowrite32(CAN_CMASK_RDWR | CAN_CMASK_ARB | CAN_CMASK_CTRL,
-		  &priv->regs->if1_cmask);
+	/* Reading the Msg buffer from Message RAM to IF1/2 registers. */
+	iowrite32(PCH_CMASK_RX_TX_GET, &priv->regs->ifregs[dir].cmask);
+	pch_can_rw_msg_obj(&priv->regs->ifregs[dir].creq, buff_num);
 
-	if (set == ENABLE) {
-		/* Setting the MsgVal and RxIE bits */
-		pch_can_bit_set(&priv->regs->if1_mcont, CAN_IF_MCONT_RXIE);
-		pch_can_bit_set(&priv->regs->if1_id2, CAN_ID_MSGVAL);
+	/* Setting the IF1/2MASK1 register to access MsgVal and RxIE bits */
+	iowrite32(PCH_CMASK_RDWR | PCH_CMASK_ARB | PCH_CMASK_CTRL,
+		  &priv->regs->ifregs[dir].cmask);
 
-	} else if (set == DISABLE) {
-		/* Resetting the MsgVal and RxIE bits */
-		pch_can_bit_clear(&priv->regs->if1_mcont, CAN_IF_MCONT_RXIE);
-		pch_can_bit_clear(&priv->regs->if1_id2, CAN_ID_MSGVAL);
+	if (set) {
+		/* Setting the MsgVal and RxIE/TxIE bits */
+		pch_can_bit_set(&priv->regs->ifregs[dir].mcont, ie);
+		pch_can_bit_set(&priv->regs->ifregs[dir].id2, PCH_ID_MSGVAL);
+	} else {
+		/* Clearing the MsgVal and RxIE/TxIE bits */
+		pch_can_bit_clear(&priv->regs->ifregs[dir].mcont, ie);
+		pch_can_bit_clear(&priv->regs->ifregs[dir].id2, PCH_ID_MSGVAL);
 	}
 
-	pch_can_check_if_busy(&priv->regs->if1_creq, buff_num);
-	spin_unlock_irqrestore(&priv->msgif_reg_lock, flags);
-}
-
-static void pch_can_rx_enable_all(struct pch_can_priv *priv)
-{
-	int i;
-
-	/* Traversing to obtain the object configured as receivers. */
-	for (i = 0; i < PCH_OBJ_NUM; i++) {
-		if (priv->msg_obj[i] == MSG_OBJ_RX)
-			pch_can_set_rx_enable(priv, i + 1, ENABLE);
-	}
+	pch_can_rw_msg_obj(&priv->regs->ifregs[dir].creq, buff_num);
 }
 
-static void pch_can_rx_disable_all(struct pch_can_priv *priv)
+static void pch_can_set_rx_all(struct pch_can_priv *priv, int set)
 {
 	int i;
 
 	/* Traversing to obtain the object configured as receivers. */
-	for (i = 0; i < PCH_OBJ_NUM; i++) {
-		if (priv->msg_obj[i] == MSG_OBJ_RX)
-			pch_can_set_rx_enable(priv, i + 1, DISABLE);
-	}
-}
-
-static void pch_can_set_tx_enable(struct pch_can_priv *priv, u32 buff_num,
-				 u32 set)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&priv->msgif_reg_lock, flags);
-	/* Reading the Msg buffer from Message RAM to Interface2 registers. */
-	iowrite32(CAN_CMASK_RX_TX_GET, &priv->regs->if2_cmask);
-	pch_can_check_if_busy(&priv->regs->if2_creq, buff_num);
-
-	/* Setting the IF2CMASK register for accessing the
-		MsgVal and TxIE bits */
-	iowrite32(CAN_CMASK_RDWR | CAN_CMASK_ARB | CAN_CMASK_CTRL,
-		 &priv->regs->if2_cmask);
-
-	if (set == ENABLE) {
-		/* Setting the MsgVal and TxIE bits */
-		pch_can_bit_set(&priv->regs->if2_mcont, CAN_IF_MCONT_TXIE);
-		pch_can_bit_set(&priv->regs->if2_id2, CAN_ID_MSGVAL);
-	} else if (set == DISABLE) {
-		/* Resetting the MsgVal and TxIE bits. */
-		pch_can_bit_clear(&priv->regs->if2_mcont, CAN_IF_MCONT_TXIE);
-		pch_can_bit_clear(&priv->regs->if2_id2, CAN_ID_MSGVAL);
-	}
-
-	pch_can_check_if_busy(&priv->regs->if2_creq, buff_num);
-	spin_unlock_irqrestore(&priv->msgif_reg_lock, flags);
-}
-
-static void pch_can_tx_enable_all(struct pch_can_priv *priv)
-{
-	int i;
-
-	/* Traversing to obtain the object configured as transmit object. */
-	for (i = 0; i < PCH_OBJ_NUM; i++) {
-		if (priv->msg_obj[i] == MSG_OBJ_TX)
-			pch_can_set_tx_enable(priv, i + 1, ENABLE);
-	}
+	for (i = PCH_RX_OBJ_START; i <= PCH_RX_OBJ_END; i++)
+		pch_can_set_rxtx(priv, i, set, PCH_RX_IFREG);
 }
 
-static void pch_can_tx_disable_all(struct pch_can_priv *priv)
+static void pch_can_set_tx_all(struct pch_can_priv *priv, int set)
 {
 	int i;
 
 	/* Traversing to obtain the object configured as transmit object. */
-	for (i = 0; i < PCH_OBJ_NUM; i++) {
-		if (priv->msg_obj[i] == MSG_OBJ_TX)
-			pch_can_set_tx_enable(priv, i + 1, DISABLE);
-	}
-}
-
-static void pch_can_get_rx_enable(struct pch_can_priv *priv, u32 buff_num,
-				 u32 *enable)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&priv->msgif_reg_lock, flags);
-	iowrite32(CAN_CMASK_RX_TX_GET, &priv->regs->if1_cmask);
-	pch_can_check_if_busy(&priv->regs->if1_creq, buff_num);
-
-	if (((ioread32(&priv->regs->if1_id2)) & CAN_ID_MSGVAL) &&
-			((ioread32(&priv->regs->if1_mcont)) &
-			CAN_IF_MCONT_RXIE))
-		*enable = ENABLE;
-	else
-		*enable = DISABLE;
-	spin_unlock_irqrestore(&priv->msgif_reg_lock, flags);
-}
-
-static void pch_can_get_tx_enable(struct pch_can_priv *priv, u32 buff_num,
-				 u32 *enable)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&priv->msgif_reg_lock, flags);
-	iowrite32(CAN_CMASK_RX_TX_GET, &priv->regs->if2_cmask);
-	pch_can_check_if_busy(&priv->regs->if2_creq, buff_num);
-
-	if (((ioread32(&priv->regs->if2_id2)) & CAN_ID_MSGVAL) &&
-			((ioread32(&priv->regs->if2_mcont)) &
-			CAN_IF_MCONT_TXIE)) {
-		*enable = ENABLE;
-	} else {
-		*enable = DISABLE;
-	}
-	spin_unlock_irqrestore(&priv->msgif_reg_lock, flags);
+	for (i = PCH_TX_OBJ_START; i <= PCH_TX_OBJ_END; i++)
+		pch_can_set_rxtx(priv, i, set, PCH_TX_IFREG);
 }
 
-static int pch_can_int_pending(struct pch_can_priv *priv)
+static u32 pch_can_int_pending(struct pch_can_priv *priv)
 {
 	return ioread32(&priv->regs->intr) & 0xffff;
 }
 
-static void pch_can_set_rx_buffer_link(struct pch_can_priv *priv,
-				       u32 buffer_num, u32 set)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&priv->msgif_reg_lock, flags);
-	iowrite32(CAN_CMASK_RX_TX_GET, &priv->regs->if1_cmask);
-	pch_can_check_if_busy(&priv->regs->if1_creq, buffer_num);
-	iowrite32(CAN_CMASK_RDWR | CAN_CMASK_CTRL, &priv->regs->if1_cmask);
-	if (set == ENABLE)
-		pch_can_bit_clear(&priv->regs->if1_mcont, CAN_IF_MCONT_EOB);
-	else
-		pch_can_bit_set(&priv->regs->if1_mcont, CAN_IF_MCONT_EOB);
-
-	pch_can_check_if_busy(&priv->regs->if1_creq, buffer_num);
-	spin_unlock_irqrestore(&priv->msgif_reg_lock, flags);
-}
-
-static void pch_can_get_rx_buffer_link(struct pch_can_priv *priv,
-				       u32 buffer_num, u32 *link)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&priv->msgif_reg_lock, flags);
-	iowrite32(CAN_CMASK_RX_TX_GET, &priv->regs->if1_cmask);
-	pch_can_check_if_busy(&priv->regs->if1_creq, buffer_num);
-
-	if (ioread32(&priv->regs->if1_mcont) & CAN_IF_MCONT_EOB)
-		*link = DISABLE;
-	else
-		*link = ENABLE;
-	spin_unlock_irqrestore(&priv->msgif_reg_lock, flags);
-}
-
-static void pch_can_clear_buffers(struct pch_can_priv *priv)
+static void pch_can_clear_if_buffers(struct pch_can_priv *priv)
 {
-	int i;
-
-	for (i = 0; i < PCH_RX_OBJ_NUM; i++) {
-		iowrite32(CAN_CMASK_RX_TX_SET, &priv->regs->if1_cmask);
-		iowrite32(0xffff, &priv->regs->if1_mask1);
-		iowrite32(0xffff, &priv->regs->if1_mask2);
-		iowrite32(0x0, &priv->regs->if1_id1);
-		iowrite32(0x0, &priv->regs->if1_id2);
-		iowrite32(0x0, &priv->regs->if1_mcont);
-		iowrite32(0x0, &priv->regs->if1_dataa1);
-		iowrite32(0x0, &priv->regs->if1_dataa2);
-		iowrite32(0x0, &priv->regs->if1_datab1);
-		iowrite32(0x0, &priv->regs->if1_datab2);
-		iowrite32(CAN_CMASK_RDWR | CAN_CMASK_MASK |
-			  CAN_CMASK_ARB | CAN_CMASK_CTRL,
-			  &priv->regs->if1_cmask);
-		pch_can_check_if_busy(&priv->regs->if1_creq, i+1);
-	}
+	int i; /* Msg Obj ID (1~32) */
 
-	for (i = i;  i < PCH_OBJ_NUM; i++) {
-		iowrite32(CAN_CMASK_RX_TX_SET, &priv->regs->if2_cmask);
-		iowrite32(0xffff, &priv->regs->if2_mask1);
-		iowrite32(0xffff, &priv->regs->if2_mask2);
-		iowrite32(0x0, &priv->regs->if2_id1);
-		iowrite32(0x0, &priv->regs->if2_id2);
-		iowrite32(0x0, &priv->regs->if2_mcont);
-		iowrite32(0x0, &priv->regs->if2_dataa1);
-		iowrite32(0x0, &priv->regs->if2_dataa2);
-		iowrite32(0x0, &priv->regs->if2_datab1);
-		iowrite32(0x0, &priv->regs->if2_datab2);
-		iowrite32(CAN_CMASK_RDWR | CAN_CMASK_MASK |
-			  CAN_CMASK_ARB | CAN_CMASK_CTRL,
-			  &priv->regs->if2_cmask);
-		pch_can_check_if_busy(&priv->regs->if2_creq, i+1);
+	for (i = PCH_RX_OBJ_START; i <= PCH_TX_OBJ_END; i++) {
+		iowrite32(PCH_CMASK_RX_TX_SET, &priv->regs->ifregs[0].cmask);
+		iowrite32(0xffff, &priv->regs->ifregs[0].mask1);
+		iowrite32(0xffff, &priv->regs->ifregs[0].mask2);
+		iowrite32(0x0, &priv->regs->ifregs[0].id1);
+		iowrite32(0x0, &priv->regs->ifregs[0].id2);
+		iowrite32(0x0, &priv->regs->ifregs[0].mcont);
+		iowrite32(0x0, &priv->regs->ifregs[0].data[0]);
+		iowrite32(0x0, &priv->regs->ifregs[0].data[1]);
+		iowrite32(0x0, &priv->regs->ifregs[0].data[2]);
+		iowrite32(0x0, &priv->regs->ifregs[0].data[3]);
+		iowrite32(PCH_CMASK_RDWR | PCH_CMASK_MASK |
+			  PCH_CMASK_ARB | PCH_CMASK_CTRL,
+			  &priv->regs->ifregs[0].cmask);
+		pch_can_rw_msg_obj(&priv->regs->ifregs[0].creq, i);
 	}
 }
 
 static void pch_can_config_rx_tx_buffers(struct pch_can_priv *priv)
 {
 	int i;
-	unsigned long flags;
-
-	spin_lock_irqsave(&priv->msgif_reg_lock, flags);
 
-	for (i = 0; i < PCH_OBJ_NUM; i++) {
-		if (priv->msg_obj[i] == MSG_OBJ_RX) {
-			iowrite32(CAN_CMASK_RX_TX_GET,
-				&priv->regs->if1_cmask);
-			pch_can_check_if_busy(&priv->regs->if1_creq, i+1);
+	for (i = PCH_RX_OBJ_START; i <= PCH_RX_OBJ_END; i++) {
+		iowrite32(PCH_CMASK_RX_TX_GET, &priv->regs->ifregs[0].cmask);
+		pch_can_rw_msg_obj(&priv->regs->ifregs[0].creq, i);
 
-			iowrite32(0x0, &priv->regs->if1_id1);
-			iowrite32(0x0, &priv->regs->if1_id2);
+		iowrite32(0x0, &priv->regs->ifregs[0].id1);
+		iowrite32(0x0, &priv->regs->ifregs[0].id2);
 
-			pch_can_bit_set(&priv->regs->if1_mcont,
-					CAN_IF_MCONT_UMASK);
+		pch_can_bit_set(&priv->regs->ifregs[0].mcont,
+				PCH_IF_MCONT_UMASK);
 
-			/* Set FIFO mode set to 0 except last Rx Obj*/
-			pch_can_bit_clear(&priv->regs->if1_mcont,
-					  CAN_IF_MCONT_EOB);
-			/* In case FIFO mode, Last EoB of Rx Obj must be 1 */
-			if (i == (PCH_RX_OBJ_NUM - 1))
-				pch_can_bit_set(&priv->regs->if1_mcont,
-						  CAN_IF_MCONT_EOB);
+		/* In case FIFO mode, Last EoB of Rx Obj must be 1 */
+		if (i == PCH_RX_OBJ_END)
+			pch_can_bit_set(&priv->regs->ifregs[0].mcont,
+					PCH_IF_MCONT_EOB);
+		else
+			pch_can_bit_clear(&priv->regs->ifregs[0].mcont,
+					  PCH_IF_MCONT_EOB);
 
-			iowrite32(0, &priv->regs->if1_mask1);
-			pch_can_bit_clear(&priv->regs->if1_mask2,
-					  0x1fff | CAN_MASK2_MDIR_MXTD);
+		iowrite32(0, &priv->regs->ifregs[0].mask1);
+		pch_can_bit_clear(&priv->regs->ifregs[0].mask2,
+				  0x1fff | PCH_MASK2_MDIR_MXTD);
 
-			/* Setting CMASK for writing */
-			iowrite32(CAN_CMASK_RDWR | CAN_CMASK_MASK |
-				  CAN_CMASK_ARB | CAN_CMASK_CTRL,
-				  &priv->regs->if1_cmask);
+		/* Setting CMASK for writing */
+		iowrite32(PCH_CMASK_RDWR | PCH_CMASK_MASK | PCH_CMASK_ARB |
+			  PCH_CMASK_CTRL, &priv->regs->ifregs[0].cmask);
 
-			pch_can_check_if_busy(&priv->regs->if1_creq, i+1);
-		} else if (priv->msg_obj[i] == MSG_OBJ_TX) {
-			iowrite32(CAN_CMASK_RX_TX_GET,
-				&priv->regs->if2_cmask);
-			pch_can_check_if_busy(&priv->regs->if2_creq, i+1);
+		pch_can_rw_msg_obj(&priv->regs->ifregs[0].creq, i);
+	}
 
-			/* Resetting DIR bit for reception */
-			iowrite32(0x0, &priv->regs->if2_id1);
-			iowrite32(0x0, &priv->regs->if2_id2);
-			pch_can_bit_set(&priv->regs->if2_id2, CAN_ID2_DIR);
+	for (i = PCH_TX_OBJ_START; i <= PCH_TX_OBJ_END; i++) {
+		iowrite32(PCH_CMASK_RX_TX_GET, &priv->regs->ifregs[1].cmask);
+		pch_can_rw_msg_obj(&priv->regs->ifregs[1].creq, i);
 
-			/* Setting EOB bit for transmitter */
-			iowrite32(CAN_IF_MCONT_EOB, &priv->regs->if2_mcont);
+		/* Resetting DIR bit for reception */
+		iowrite32(0x0, &priv->regs->ifregs[1].id1);
+		iowrite32(PCH_ID2_DIR, &priv->regs->ifregs[1].id2);
 
-			pch_can_bit_set(&priv->regs->if2_mcont,
-					CAN_IF_MCONT_UMASK);
+		/* Setting EOB bit for transmitter */
+		iowrite32(PCH_IF_MCONT_EOB | PCH_IF_MCONT_UMASK,
+			  &priv->regs->ifregs[1].mcont);
 
-			iowrite32(0, &priv->regs->if2_mask1);
-			pch_can_bit_clear(&priv->regs->if2_mask2, 0x1fff);
+		iowrite32(0, &priv->regs->ifregs[1].mask1);
+		pch_can_bit_clear(&priv->regs->ifregs[1].mask2, 0x1fff);
 
-			/* Setting CMASK for writing */
-			iowrite32(CAN_CMASK_RDWR | CAN_CMASK_MASK |
-				  CAN_CMASK_ARB | CAN_CMASK_CTRL,
-				  &priv->regs->if2_cmask);
+		/* Setting CMASK for writing */
+		iowrite32(PCH_CMASK_RDWR | PCH_CMASK_MASK | PCH_CMASK_ARB |
+			  PCH_CMASK_CTRL, &priv->regs->ifregs[1].cmask);
 
-			pch_can_check_if_busy(&priv->regs->if2_creq, i+1);
-		}
+		pch_can_rw_msg_obj(&priv->regs->ifregs[1].creq, i);
 	}
-	spin_unlock_irqrestore(&priv->msgif_reg_lock, flags);
 }
 
 static void pch_can_init(struct pch_can_priv *priv)
@@ -605,7 +420,7 @@ static void pch_can_init(struct pch_can_
 	pch_can_set_run_mode(priv, PCH_CAN_STOP);
 
 	/* Clearing all the message object buffers. */
-	pch_can_clear_buffers(priv);
+	pch_can_clear_if_buffers(priv);
 
 	/* Configuring the respective message object as either rx/tx object. */
 	pch_can_config_rx_tx_buffers(priv);
@@ -623,57 +438,47 @@ static void pch_can_release(struct pch_c
 	pch_can_set_int_enables(priv, PCH_CAN_NONE);
 
 	/* Disabling all the receive object. */
-	pch_can_rx_disable_all(priv);
+	pch_can_set_rx_all(priv, 0);
 
 	/* Disabling all the transmit object. */
-	pch_can_tx_disable_all(priv);
+	pch_can_set_tx_all(priv, 0);
 }
 
 /* This function clears interrupt(s) from the CAN device. */
 static void pch_can_int_clr(struct pch_can_priv *priv, u32 mask)
 {
-	if (mask == CAN_STATUS_INT) {
-		ioread32(&priv->regs->stat);
-		return;
-	}
-
 	/* Clear interrupt for transmit object */
-	if (priv->msg_obj[mask - 1] == MSG_OBJ_TX) {
-		/* Setting CMASK for clearing interrupts for
-					 frame transmission. */
-		iowrite32(CAN_CMASK_RDWR | CAN_CMASK_CTRL | CAN_CMASK_ARB,
-			  &priv->regs->if2_cmask);
-
-		/* Resetting the ID registers. */
-		pch_can_bit_set(&priv->regs->if2_id2,
-			       CAN_ID2_DIR | (0x7ff << 2));
-		iowrite32(0x0, &priv->regs->if2_id1);
-
-		/* Claring NewDat, TxRqst & IntPnd */
-		pch_can_bit_clear(&priv->regs->if2_mcont,
-				  CAN_IF_MCONT_NEWDAT | CAN_IF_MCONT_INTPND |
-				  CAN_IF_MCONT_TXRQXT);
-		pch_can_check_if_busy(&priv->regs->if2_creq, mask);
-	} else if (priv->msg_obj[mask - 1] == MSG_OBJ_RX) {
+	if ((mask >= PCH_RX_OBJ_START) && (mask <= PCH_RX_OBJ_END)) {
 		/* Setting CMASK for clearing the reception interrupts. */
-		iowrite32(CAN_CMASK_RDWR | CAN_CMASK_CTRL | CAN_CMASK_ARB,
-			  &priv->regs->if1_cmask);
+		iowrite32(PCH_CMASK_RDWR | PCH_CMASK_CTRL | PCH_CMASK_ARB,
+			  &priv->regs->ifregs[0].cmask);
 
 		/* Clearing the Dir bit. */
-		pch_can_bit_clear(&priv->regs->if1_id2, CAN_ID2_DIR);
+		pch_can_bit_clear(&priv->regs->ifregs[0].id2, PCH_ID2_DIR);
 
 		/* Clearing NewDat & IntPnd */
-		pch_can_bit_clear(&priv->regs->if1_mcont,
-				  CAN_IF_MCONT_NEWDAT | CAN_IF_MCONT_INTPND);
+		pch_can_bit_clear(&priv->regs->ifregs[0].mcont,
+				  PCH_IF_MCONT_NEWDAT | PCH_IF_MCONT_INTPND);
 
-		pch_can_check_if_busy(&priv->regs->if1_creq, mask);
-	}
-}
+		pch_can_rw_msg_obj(&priv->regs->ifregs[0].creq, mask);
+	} else if ((mask >= PCH_TX_OBJ_START) && (mask <= PCH_TX_OBJ_END)) {
+		/*
+		 * Setting CMASK for clearing interrupts for frame transmission.
+		 */
+		iowrite32(PCH_CMASK_RDWR | PCH_CMASK_CTRL | PCH_CMASK_ARB,
+			  &priv->regs->ifregs[1].cmask);
 
-static int pch_can_get_buffer_status(struct pch_can_priv *priv)
-{
-	return (ioread32(&priv->regs->treq1) & 0xffff) |
-	       ((ioread32(&priv->regs->treq2) & 0xffff) << 16);
+		/* Resetting the ID registers. */
+		pch_can_bit_set(&priv->regs->ifregs[1].id2,
+			       PCH_ID2_DIR | (0x7ff << 2));
+		iowrite32(0x0, &priv->regs->ifregs[1].id1);
+
+		/* Claring NewDat, TxRqst & IntPnd */
+		pch_can_bit_clear(&priv->regs->ifregs[1].mcont,
+				  PCH_IF_MCONT_NEWDAT | PCH_IF_MCONT_INTPND |
+				  PCH_IF_MCONT_TXRQXT);
+		pch_can_rw_msg_obj(&priv->regs->ifregs[1].creq, mask);
+	}
 }
 
 static void pch_can_reset(struct pch_can_priv *priv)
@@ -688,7 +493,7 @@ static void pch_can_error(struct net_dev
 	struct sk_buff *skb;
 	struct pch_can_priv *priv = netdev_priv(ndev);
 	struct can_frame *cf;
-	u32 errc;
+	u32 errc, lec;
 	struct net_device_stats *stats = &(priv->ndev->stats);
 	enum can_state state = priv->can.state;
 
@@ -697,26 +502,24 @@ static void pch_can_error(struct net_dev
 		return;
 
 	if (status & PCH_BUS_OFF) {
-		pch_can_tx_disable_all(priv);
-		pch_can_rx_disable_all(priv);
+		pch_can_set_tx_all(priv, 0);
+		pch_can_set_rx_all(priv, 0);
 		state = CAN_STATE_BUS_OFF;
 		cf->can_id |= CAN_ERR_BUSOFF;
 		can_bus_off(ndev);
-		pch_can_set_run_mode(priv, PCH_CAN_RUN);
-		dev_err(&ndev->dev, "%s -> Bus Off occurres.\n", __func__);
 	}
 
+	errc = ioread32(&priv->regs->errc);
 	/* Warning interrupt. */
 	if (status & PCH_EWARN) {
 		state = CAN_STATE_ERROR_WARNING;
 		priv->can.can_stats.error_warning++;
 		cf->can_id |= CAN_ERR_CRTL;
-		errc = ioread32(&priv->regs->errc);
-		if (((errc & CAN_REC) >> 8) > 96)
+		if (((errc & PCH_REC) >> 8) > 96)
 			cf->data[1] |= CAN_ERR_CRTL_RX_WARNING;
-		if ((errc & CAN_TEC) > 96)
+		if ((errc & PCH_TEC) > 96)
 			cf->data[1] |= CAN_ERR_CRTL_TX_WARNING;
-		dev_warn(&ndev->dev,
+		netdev_dbg(ndev,
 			"%s -> Error Counter is more than 96.\n", __func__);
 	}
 	/* Error passive interrupt. */
@@ -724,46 +527,52 @@ static void pch_can_error(struct net_dev
 		priv->can.can_stats.error_passive++;
 		state = CAN_STATE_ERROR_PASSIVE;
 		cf->can_id |= CAN_ERR_CRTL;
-		errc = ioread32(&priv->regs->errc);
-		if (((errc & CAN_REC) >> 8) > 127)
+		if (((errc & PCH_REC) >> 8) > 127)
 			cf->data[1] |= CAN_ERR_CRTL_RX_PASSIVE;
-		if ((errc & CAN_TEC) > 127)
+		if ((errc & PCH_TEC) > 127)
 			cf->data[1] |= CAN_ERR_CRTL_TX_PASSIVE;
-		dev_err(&ndev->dev,
+		netdev_dbg(ndev,
 			"%s -> CAN controller is ERROR PASSIVE .\n", __func__);
 	}
 
-	if (status & PCH_LEC_ALL) {
+	lec = status & PCH_LEC_ALL;
+	switch (lec) {
+	case PCH_STUF_ERR:
+		cf->data[2] |= CAN_ERR_PROT_STUFF;
 		priv->can.can_stats.bus_error++;
 		stats->rx_errors++;
-		switch (status & PCH_LEC_ALL) {
-		case PCH_STUF_ERR:
-			cf->data[2] |= CAN_ERR_PROT_STUFF;
-			break;
-		case PCH_FORM_ERR:
-			cf->data[2] |= CAN_ERR_PROT_FORM;
-			break;
-		case PCH_ACK_ERR:
-			cf->data[2] |= CAN_ERR_PROT_LOC_ACK |
-				       CAN_ERR_PROT_LOC_ACK_DEL;
-			break;
-		case PCH_BIT1_ERR:
-		case PCH_BIT0_ERR:
-			cf->data[2] |= CAN_ERR_PROT_BIT;
-			break;
-		case PCH_CRC_ERR:
-			cf->data[2] |= CAN_ERR_PROT_LOC_CRC_SEQ |
-				       CAN_ERR_PROT_LOC_CRC_DEL;
-			break;
-		default:
-			iowrite32(status | PCH_LEC_ALL, &priv->regs->stat);
-			break;
-		}
-
+		break;
+	case PCH_FORM_ERR:
+		cf->data[2] |= CAN_ERR_PROT_FORM;
+		priv->can.can_stats.bus_error++;
+		stats->rx_errors++;
+		break;
+	case PCH_ACK_ERR:
+		cf->can_id |= CAN_ERR_ACK;
+		priv->can.can_stats.bus_error++;
+		stats->rx_errors++;
+		break;
+	case PCH_BIT1_ERR:
+	case PCH_BIT0_ERR:
+		cf->data[2] |= CAN_ERR_PROT_BIT;
+		priv->can.can_stats.bus_error++;
+		stats->rx_errors++;
+		break;
+	case PCH_CRC_ERR:
+		cf->data[2] |= CAN_ERR_PROT_LOC_CRC_SEQ |
+			       CAN_ERR_PROT_LOC_CRC_DEL;
+		priv->can.can_stats.bus_error++;
+		stats->rx_errors++;
+		break;
+	case PCH_LEC_ALL: /* Written by CPU. No error status */
+		break;
 	}
 
+	cf->data[6] = errc & PCH_TEC;
+	cf->data[7] = (errc & PCH_REC) >> 8;
+
 	priv->can.state = state;
-	netif_rx(skb);
+	netif_receive_skb(skb);
 
 	stats->rx_packets++;
 	stats->rx_bytes += cf->can_dlc;
@@ -774,204 +583,202 @@ static irqreturn_t pch_can_interrupt(int
 	struct net_device *ndev = (struct net_device *)dev_id;
 	struct pch_can_priv *priv = netdev_priv(ndev);
 
-	pch_can_set_int_enables(priv, PCH_CAN_NONE);
+	if (!pch_can_int_pending(priv))
+		return IRQ_NONE;
 
+	pch_can_set_int_enables(priv, PCH_CAN_NONE);
 	napi_schedule(&priv->napi);
-
 	return IRQ_HANDLED;
 }
 
-static int pch_can_rx_normal(struct net_device *ndev, u32 int_stat)
+static void pch_fifo_thresh(struct pch_can_priv *priv, int obj_id)
+{
+	if (obj_id < PCH_FIFO_THRESH) {
+		iowrite32(PCH_CMASK_RDWR | PCH_CMASK_CTRL |
+			  PCH_CMASK_ARB, &priv->regs->ifregs[0].cmask);
+
+		/* Clearing the Dir bit. */
+		pch_can_bit_clear(&priv->regs->ifregs[0].id2, PCH_ID2_DIR);
+
+		/* Clearing NewDat & IntPnd */
+		pch_can_bit_clear(&priv->regs->ifregs[0].mcont,
+				  PCH_IF_MCONT_INTPND);
+		pch_can_rw_msg_obj(&priv->regs->ifregs[0].creq, obj_id);
+	} else if (obj_id > PCH_FIFO_THRESH) {
+		pch_can_int_clr(priv, obj_id);
+	} else if (obj_id == PCH_FIFO_THRESH) {
+		int cnt;
+		for (cnt = 0; cnt < PCH_FIFO_THRESH; cnt++)
+			pch_can_int_clr(priv, cnt + 1);
+	}
+}
+
+static void pch_can_rx_msg_lost(struct net_device *ndev, int obj_id)
+{
+	struct pch_can_priv *priv = netdev_priv(ndev);
+	struct net_device_stats *stats = &(priv->ndev->stats);
+	struct sk_buff *skb;
+	struct can_frame *cf;
+
+	netdev_dbg(priv->ndev, "Msg Obj is overwritten.\n");
+	pch_can_bit_clear(&priv->regs->ifregs[0].mcont,
+			  PCH_IF_MCONT_MSGLOST);
+	iowrite32(PCH_CMASK_RDWR | PCH_CMASK_CTRL,
+		  &priv->regs->ifregs[0].cmask);
+	pch_can_rw_msg_obj(&priv->regs->ifregs[0].creq, obj_id);
+
+	skb = alloc_can_err_skb(ndev, &cf);
+	if (!skb)
+		return;
+
+	cf->can_id |= CAN_ERR_CRTL;
+	cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW;
+	stats->rx_over_errors++;
+	stats->rx_errors++;
+
+	netif_receive_skb(skb);
+}
+
+static int pch_can_rx_normal(struct net_device *ndev, u32 obj_num, int quota)
 {
 	u32 reg;
 	canid_t id;
-	u32 ide;
-	u32 rtr;
-	int i, j, k;
 	int rcv_pkts = 0;
 	struct sk_buff *skb;
 	struct can_frame *cf;
 	struct pch_can_priv *priv = netdev_priv(ndev);
 	struct net_device_stats *stats = &(priv->ndev->stats);
+	int i;
+	u32 id2;
+	u16 data_reg;
 
-	/* Reading the messsage object from the Message RAM */
-	iowrite32(CAN_CMASK_RX_TX_GET, &priv->regs->if1_cmask);
-	pch_can_check_if_busy(&priv->regs->if1_creq, int_stat);
-
-	/* Reading the MCONT register. */
-	reg = ioread32(&priv->regs->if1_mcont);
-	reg &= 0xffff;
-
-	for (k = int_stat; !(reg & CAN_IF_MCONT_EOB); k++) {
-		/* If MsgLost bit set. */
-		if (reg & CAN_IF_MCONT_MSGLOST) {
-			dev_err(&priv->ndev->dev, "Msg Obj is overwritten.\n");
-			pch_can_bit_clear(&priv->regs->if1_mcont,
-					  CAN_IF_MCONT_MSGLOST);
-			iowrite32(CAN_CMASK_RDWR | CAN_CMASK_CTRL,
-				  &priv->regs->if1_cmask);
-			pch_can_check_if_busy(&priv->regs->if1_creq, k);
+	do {
+		/* Reading the messsage object from the Message RAM */
+		iowrite32(PCH_CMASK_RX_TX_GET, &priv->regs->ifregs[0].cmask);
+		pch_can_rw_msg_obj(&priv->regs->ifregs[0].creq, obj_num);
 
-			skb = alloc_can_err_skb(ndev, &cf);
-			if (!skb)
-				return -ENOMEM;
+		/* Reading the MCONT register. */
+		reg = ioread32(&priv->regs->ifregs[0].mcont);
 
-			priv->can.can_stats.error_passive++;
-			priv->can.state = CAN_STATE_ERROR_PASSIVE;
-			cf->can_id |= CAN_ERR_CRTL;
-			cf->data[1] |= CAN_ERR_CRTL_RX_OVERFLOW;
-			cf->data[2] |= CAN_ERR_PROT_OVERLOAD;
-			stats->rx_packets++;
-			stats->rx_bytes += cf->can_dlc;
+		if (reg & PCH_IF_MCONT_EOB)
+			break;
 
-			netif_receive_skb(skb);
+		/* If MsgLost bit set. */
+		if (reg & PCH_IF_MCONT_MSGLOST) {
+			pch_can_rx_msg_lost(ndev, obj_num);
 			rcv_pkts++;
-			goto RX_NEXT;
+			quota--;
+			obj_num++;
+			continue;
+		} else if (!(reg & PCH_IF_MCONT_NEWDAT)) {
+			obj_num++;
+			continue;
 		}
-		if (!(reg & CAN_IF_MCONT_NEWDAT))
-			goto RX_NEXT;
 
 		skb = alloc_can_skb(priv->ndev, &cf);
-		if (!skb)
-			return -ENOMEM;
+		if (!skb) {
+			netdev_err(ndev, "alloc_can_skb Failed\n");
+			return rcv_pkts;
+		}
 
 		/* Get Received data */
-		ide = ((ioread32(&priv->regs->if1_id2)) & CAN_ID2_XTD) >> 14;
-		if (ide) {
-			id = (ioread32(&priv->regs->if1_id1) & 0xffff);
-			id |= (((ioread32(&priv->regs->if1_id2)) &
-					    0x1fff) << 16);
-			cf->can_id = (id & CAN_EFF_MASK) | CAN_EFF_FLAG;
+		id2 = ioread32(&priv->regs->ifregs[0].id2);
+		if (id2 & PCH_ID2_XTD) {
+			id = (ioread32(&priv->regs->ifregs[0].id1) & 0xffff);
+			id |= (((id2) & 0x1fff) << 16);
+			cf->can_id = id | CAN_EFF_FLAG;
 		} else {
-			id = (((ioread32(&priv->regs->if1_id2)) &
-					  (CAN_SFF_MASK << 2)) >> 2);
-			cf->can_id = (id & CAN_SFF_MASK);
+			id = (id2 >> 2) & CAN_SFF_MASK;
+			cf->can_id = id;
 		}
 
-		rtr = (ioread32(&priv->regs->if1_id2) &  CAN_ID2_DIR);
-		if (rtr) {
-			cf->can_dlc = 0;
+		if (id2 & PCH_ID2_DIR)
 			cf->can_id |= CAN_RTR_FLAG;
-		} else {
-			cf->can_dlc = ((ioread32(&priv->regs->if1_mcont)) &
-						   0x0f);
-		}
 
-		for (i = 0, j = 0; i < cf->can_dlc; j++) {
-			reg = ioread32(&priv->regs->if1_dataa1 + j*4);
-			cf->data[i++] = cpu_to_le32(reg & 0xff);
-			if (i == cf->can_dlc)
-				break;
-			cf->data[i++] = cpu_to_le32((reg >> 8) & 0xff);
+		cf->can_dlc = get_can_dlc((ioread32(&priv->regs->
+						    ifregs[0].mcont)) & 0xF);
+
+		for (i = 0; i < cf->can_dlc; i += 2) {
+			data_reg = ioread16(&priv->regs->ifregs[0].data[i / 2]);
+			cf->data[i] = data_reg;
+			cf->data[i + 1] = data_reg >> 8;
 		}
 
 		netif_receive_skb(skb);
 		rcv_pkts++;
 		stats->rx_packets++;
+		quota--;
 		stats->rx_bytes += cf->can_dlc;
 
-		if (k < PCH_FIFO_THRESH) {
-			iowrite32(CAN_CMASK_RDWR | CAN_CMASK_CTRL |
-				  CAN_CMASK_ARB, &priv->regs->if1_cmask);
-
-			/* Clearing the Dir bit. */
-			pch_can_bit_clear(&priv->regs->if1_id2, CAN_ID2_DIR);
-
-			/* Clearing NewDat & IntPnd */
-			pch_can_bit_clear(&priv->regs->if1_mcont,
-					  CAN_IF_MCONT_INTPND);
-			pch_can_check_if_busy(&priv->regs->if1_creq, k);
-		} else if (k > PCH_FIFO_THRESH) {
-			pch_can_int_clr(priv, k);
-		} else if (k == PCH_FIFO_THRESH) {
-			int cnt;
-			for (cnt = 0; cnt < PCH_FIFO_THRESH; cnt++)
-				pch_can_int_clr(priv, cnt+1);
-		}
-RX_NEXT:
-		/* Reading the messsage object from the Message RAM */
-		iowrite32(CAN_CMASK_RX_TX_GET, &priv->regs->if1_cmask);
-		pch_can_check_if_busy(&priv->regs->if1_creq, k + 1);
-		reg = ioread32(&priv->regs->if1_mcont);
-	}
+		pch_fifo_thresh(priv, obj_num);
+		obj_num++;
+	} while (quota > 0);
 
 	return rcv_pkts;
 }
-static int pch_can_rx_poll(struct napi_struct *napi, int quota)
+
+static void pch_can_tx_complete(struct net_device *ndev, u32 int_stat)
 {
-	struct net_device *ndev = napi->dev;
 	struct pch_can_priv *priv = netdev_priv(ndev);
 	struct net_device_stats *stats = &(priv->ndev->stats);
 	u32 dlc;
+
+	can_get_echo_skb(ndev, int_stat - PCH_RX_OBJ_END - 1);
+	iowrite32(PCH_CMASK_RX_TX_GET | PCH_CMASK_CLRINTPND,
+		  &priv->regs->ifregs[1].cmask);
+	pch_can_rw_msg_obj(&priv->regs->ifregs[1].creq, int_stat);
+	dlc = get_can_dlc(ioread32(&priv->regs->ifregs[1].mcont) &
+			  PCH_IF_MCONT_DLC);
+	stats->tx_bytes += dlc;
+	stats->tx_packets++;
+	if (int_stat == PCH_TX_OBJ_END)
+		netif_wake_queue(ndev);
+}
+
+static int pch_can_poll(struct napi_struct *napi, int quota)
+{
+	struct net_device *ndev = napi->dev;
+	struct pch_can_priv *priv = netdev_priv(ndev);
 	u32 int_stat;
-	int rcv_pkts = 0;
 	u32 reg_stat;
-	unsigned long flags;
+	int quota_save = quota;
 
 	int_stat = pch_can_int_pending(priv);
 	if (!int_stat)
-		return 0;
+		goto end;
 
-INT_STAT:
-	if (int_stat == CAN_STATUS_INT) {
+	if (int_stat == PCH_STATUS_INT) {
 		reg_stat = ioread32(&priv->regs->stat);
-		if (reg_stat & (PCH_BUS_OFF | PCH_LEC_ALL)) {
-			if ((reg_stat & PCH_LEC_ALL) != PCH_LEC_ALL)
-				pch_can_error(ndev, reg_stat);
-		}
 
-		if (reg_stat & PCH_TX_OK) {
-			spin_lock_irqsave(&priv->msgif_reg_lock, flags);
-			iowrite32(CAN_CMASK_RX_TX_GET, &priv->regs->if2_cmask);
-			pch_can_check_if_busy(&priv->regs->if2_creq,
-					       ioread32(&priv->regs->intr));
-			spin_unlock_irqrestore(&priv->msgif_reg_lock, flags);
-			pch_can_bit_clear(&priv->regs->stat, PCH_TX_OK);
+		if ((reg_stat & (PCH_BUS_OFF | PCH_LEC_ALL)) &&
+		   ((reg_stat & PCH_LEC_ALL) != PCH_LEC_ALL)) {
+			pch_can_error(ndev, reg_stat);
+			quota--;
 		}
 
-		if (reg_stat & PCH_RX_OK)
-			pch_can_bit_clear(&priv->regs->stat, PCH_RX_OK);
+		if (reg_stat & (PCH_TX_OK | PCH_RX_OK))
+			pch_can_bit_clear(&priv->regs->stat,
+					  reg_stat & (PCH_TX_OK | PCH_RX_OK));
 
 		int_stat = pch_can_int_pending(priv);
-		if (int_stat == CAN_STATUS_INT)
-			goto INT_STAT;
 	}
 
-MSG_OBJ:
-	if ((int_stat >= 1) && (int_stat <= PCH_RX_OBJ_NUM)) {
-		spin_lock_irqsave(&priv->msgif_reg_lock, flags);
-		rcv_pkts = pch_can_rx_normal(ndev, int_stat);
-		spin_unlock_irqrestore(&priv->msgif_reg_lock, flags);
-		if (rcv_pkts < 0)
-			return 0;
-	} else if ((int_stat > PCH_RX_OBJ_NUM) && (int_stat <= PCH_OBJ_NUM)) {
-		if (priv->msg_obj[int_stat - 1] == MSG_OBJ_TX) {
-			/* Handle transmission interrupt */
-			can_get_echo_skb(ndev, int_stat - PCH_RX_OBJ_NUM - 1);
-			spin_lock_irqsave(&priv->msgif_reg_lock, flags);
-			iowrite32(CAN_CMASK_RX_TX_GET | CAN_CMASK_CLRINTPND,
-				  &priv->regs->if2_cmask);
-			dlc = ioread32(&priv->regs->if2_mcont) &
-				       CAN_IF_MCONT_DLC;
-			pch_can_check_if_busy(&priv->regs->if2_creq, int_stat);
-			spin_unlock_irqrestore(&priv->msgif_reg_lock, flags);
-			if (dlc > 8)
-				dlc = 8;
-			stats->tx_bytes += dlc;
-			stats->tx_packets++;
-		}
-	}
+	if (quota == 0)
+		goto end;
 
-	int_stat = pch_can_int_pending(priv);
-	if (int_stat == CAN_STATUS_INT)
-		goto INT_STAT;
-	else if (int_stat >= 1 && int_stat <= 32)
-		goto MSG_OBJ;
+	if ((int_stat >= PCH_RX_OBJ_START) && (int_stat <= PCH_RX_OBJ_END)) {
+		quota -= pch_can_rx_normal(ndev, int_stat, quota);
+	} else if ((int_stat >= PCH_TX_OBJ_START) &&
+		   (int_stat <= PCH_TX_OBJ_END)) {
+		/* Handle transmission interrupt */
+		pch_can_tx_complete(ndev, int_stat);
+	}
 
+end:
 	napi_complete(napi);
 	pch_can_set_int_enables(priv, PCH_CAN_ALL);
 
-	return rcv_pkts;
+	return quota_save - quota;
 }
 
 static int pch_set_bittiming(struct net_device *ndev)
@@ -980,20 +787,18 @@ static int pch_set_bittiming(struct net_
 	const struct can_bittiming *bt = &priv->can.bittiming;
 	u32 canbit;
 	u32 bepe;
-	u32 brp;
 
 	/* Setting the CCE bit for accessing the Can Timing register. */
-	pch_can_bit_set(&priv->regs->cont, CAN_CTRL_CCE);
+	pch_can_bit_set(&priv->regs->cont, PCH_CTRL_CCE);
 
-	brp = (bt->tq) / (1000000000/PCH_CAN_CLK) - 1;
-	canbit = brp & MSK_BITT_BRP;
-	canbit |= (bt->sjw - 1) << BIT_BITT_SJW;
-	canbit |= (bt->phase_seg1 + bt->prop_seg - 1) << BIT_BITT_TSEG1;
-	canbit |= (bt->phase_seg2 - 1) << BIT_BITT_TSEG2;
-	bepe = (brp & MSK_BRPE_BRPE) >> BIT_BRPE_BRPE;
+	canbit = (bt->brp - 1) & PCH_MSK_BITT_BRP;
+	canbit |= (bt->sjw - 1) << PCH_BIT_SJW_SHIFT;
+	canbit |= (bt->phase_seg1 + bt->prop_seg - 1) << PCH_BIT_TSEG1_SHIFT;
+	canbit |= (bt->phase_seg2 - 1) << PCH_BIT_TSEG2_SHIFT;
+	bepe = ((bt->brp - 1) & PCH_MSK_BRPE_BRPE) >> PCH_BIT_BRPE_BRPE_SHIFT;
 	iowrite32(canbit, &priv->regs->bitt);
 	iowrite32(bepe, &priv->regs->brpe);
-	pch_can_bit_clear(&priv->regs->cont, CAN_CTRL_CCE);
+	pch_can_bit_clear(&priv->regs->cont, PCH_CTRL_CCE);
 
 	return 0;
 }
@@ -1008,8 +813,8 @@ static void pch_can_start(struct net_dev
 	pch_set_bittiming(ndev);
 	pch_can_set_optmode(priv);
 
-	pch_can_tx_enable_all(priv);
-	pch_can_rx_enable_all(priv);
+	pch_can_set_tx_all(priv, 1);
+	pch_can_set_rx_all(priv, 1);
 
 	/* Setting the CAN to run mode. */
 	pch_can_set_run_mode(priv, PCH_CAN_RUN);
@@ -1041,27 +846,18 @@ static int pch_can_open(struct net_devic
 	struct pch_can_priv *priv = netdev_priv(ndev);
 	int retval;
 
-	retval = pci_enable_msi(priv->dev);
-	if (retval) {
-		dev_info(&ndev->dev, "PCH CAN opened without MSI\n");
-		priv->use_msi = 0;
-	} else {
-		dev_info(&ndev->dev, "PCH CAN opened with MSI\n");
-		priv->use_msi = 1;
-	}
-
-	/* Regsitering the interrupt. */
+	/* Regstering the interrupt. */
 	retval = request_irq(priv->dev->irq, pch_can_interrupt, IRQF_SHARED,
 			     ndev->name, ndev);
 	if (retval) {
-		dev_err(&ndev->dev, "request_irq failed.\n");
+		netdev_err(ndev, "request_irq failed.\n");
 		goto req_irq_err;
 	}
 
 	/* Open common can device */
 	retval = open_candev(ndev);
 	if (retval) {
-		dev_err(ndev->dev.parent, "open_candev() failed %d\n", retval);
+		netdev_err(ndev, "open_candev() failed %d\n", retval);
 		goto err_open_candev;
 	}
 
@@ -1075,9 +871,6 @@ static int pch_can_open(struct net_devic
 err_open_candev:
 	free_irq(priv->dev->irq, ndev);
 req_irq_err:
-	if (priv->use_msi)
-		pci_disable_msi(priv->dev);
-
 	pch_can_release(priv);
 
 	return retval;
@@ -1091,102 +884,65 @@ static int pch_close(struct net_device *
 	napi_disable(&priv->napi);
 	pch_can_release(priv);
 	free_irq(priv->dev->irq, ndev);
-	if (priv->use_msi)
-		pci_disable_msi(priv->dev);
 	close_candev(ndev);
 	priv->can.state = CAN_STATE_STOPPED;
 	return 0;
 }
 
-static int pch_get_msg_obj_sts(struct net_device *ndev, u32 obj_id)
-{
-	u32 buffer_status = 0;
-	struct pch_can_priv *priv = netdev_priv(ndev);
-
-	/* Getting the message object status. */
-	buffer_status = (u32) pch_can_get_buffer_status(priv);
-
-	return buffer_status & obj_id;
-}
-
-
 static netdev_tx_t pch_xmit(struct sk_buff *skb, struct net_device *ndev)
 {
-	int i, j;
-	unsigned long flags;
 	struct pch_can_priv *priv = netdev_priv(ndev);
 	struct can_frame *cf = (struct can_frame *)skb->data;
-	int tx_buffer_avail = 0;
+	int tx_obj_no;
+	int i;
+	u32 id2;
 
 	if (can_dropped_invalid_skb(ndev, skb))
 		return NETDEV_TX_OK;
 
-	if (priv->tx_obj == (PCH_OBJ_NUM + 1)) { /* Point tail Obj */
-		while (pch_get_msg_obj_sts(ndev, (((1 << PCH_TX_OBJ_NUM)-1) <<
-					   PCH_RX_OBJ_NUM)))
-			udelay(500);
+	tx_obj_no = priv->tx_obj;
+	if (priv->tx_obj == PCH_TX_OBJ_END) {
+		if (ioread32(&priv->regs->treq2) & PCH_TREQ2_TX_MASK)
+			netif_stop_queue(ndev);
 
-		priv->tx_obj = PCH_RX_OBJ_NUM + 1; /* Point head of Tx Obj ID */
-		tx_buffer_avail = priv->tx_obj; /* Point Tail of Tx Obj */
+		priv->tx_obj = PCH_TX_OBJ_START;
 	} else {
-		tx_buffer_avail = priv->tx_obj;
+		priv->tx_obj++;
 	}
-	priv->tx_obj++;
-
-	/* Attaining the lock. */
-	spin_lock_irqsave(&priv->msgif_reg_lock, flags);
-
-	/* Reading the Msg Obj from the Msg RAM to the Interface register. */
-	iowrite32(CAN_CMASK_RX_TX_GET, &priv->regs->if2_cmask);
-	pch_can_check_if_busy(&priv->regs->if2_creq, tx_buffer_avail);
 
 	/* Setting the CMASK register. */
-	pch_can_bit_set(&priv->regs->if2_cmask, CAN_CMASK_ALL);
+	pch_can_bit_set(&priv->regs->ifregs[1].cmask, PCH_CMASK_ALL);
 
 	/* If ID extended is set. */
-	pch_can_bit_clear(&priv->regs->if2_id1, 0xffff);
-	pch_can_bit_clear(&priv->regs->if2_id2, 0x1fff | CAN_ID2_XTD);
 	if (cf->can_id & CAN_EFF_FLAG) {
-		pch_can_bit_set(&priv->regs->if2_id1, cf->can_id & 0xffff);
-		pch_can_bit_set(&priv->regs->if2_id2,
-				((cf->can_id >> 16) & 0x1fff) | CAN_ID2_XTD);
+		iowrite32(cf->can_id & 0xffff, &priv->regs->ifregs[1].id1);
+		id2 = ((cf->can_id >> 16) & 0x1fff) | PCH_ID2_XTD;
 	} else {
-		pch_can_bit_set(&priv->regs->if2_id1, 0);
-		pch_can_bit_set(&priv->regs->if2_id2,
-				(cf->can_id & CAN_SFF_MASK) << 2);
+		iowrite32(0, &priv->regs->ifregs[1].id1);
+		id2 = (cf->can_id & CAN_SFF_MASK) << 2;
 	}
 
-	/* If remote frame has to be transmitted.. */
-	if (cf->can_id & CAN_RTR_FLAG)
-		pch_can_bit_clear(&priv->regs->if2_id2, CAN_ID2_DIR);
-
-	for (i = 0, j = 0; i < cf->can_dlc; j++) {
-		iowrite32(le32_to_cpu(cf->data[i++]),
-			 (&priv->regs->if2_dataa1) + j*4);
-		if (i == cf->can_dlc)
-			break;
-		iowrite32(le32_to_cpu(cf->data[i++] << 8),
-			 (&priv->regs->if2_dataa1) + j*4);
-	}
+	id2 |= PCH_ID_MSGVAL;
 
-	can_put_echo_skb(skb, ndev, tx_buffer_avail - PCH_RX_OBJ_NUM - 1);
+	/* If remote frame has to be transmitted.. */
+	if (!(cf->can_id & CAN_RTR_FLAG))
+		id2 |= PCH_ID2_DIR;
 
-	/* Updating the size of the data. */
-	pch_can_bit_clear(&priv->regs->if2_mcont, 0x0f);
-	pch_can_bit_set(&priv->regs->if2_mcont, cf->can_dlc);
+	iowrite32(id2, &priv->regs->ifregs[1].id2);
 
-	/* Clearing IntPend, NewDat & TxRqst */
-	pch_can_bit_clear(&priv->regs->if2_mcont,
-			  CAN_IF_MCONT_NEWDAT | CAN_IF_MCONT_INTPND |
-			  CAN_IF_MCONT_TXRQXT);
+	/* Copy data to register */
+	for (i = 0; i < cf->can_dlc; i += 2) {
+		iowrite16(cf->data[i] | (cf->data[i + 1] << 8),
+			  &priv->regs->ifregs[1].data[i / 2]);
+	}
 
-	/* Setting NewDat, TxRqst bits */
-	pch_can_bit_set(&priv->regs->if2_mcont,
-			CAN_IF_MCONT_NEWDAT | CAN_IF_MCONT_TXRQXT);
+	can_put_echo_skb(skb, ndev, tx_obj_no - PCH_RX_OBJ_END - 1);
 
-	pch_can_check_if_busy(&priv->regs->if2_creq, tx_buffer_avail);
+	/* Set the size of the data. Update if2_mcont */
+	iowrite32(cf->can_dlc | PCH_IF_MCONT_NEWDAT | PCH_IF_MCONT_TXRQXT |
+		  PCH_IF_MCONT_TXIE, &priv->regs->ifregs[1].mcont);
 
-	spin_unlock_irqrestore(&priv->msgif_reg_lock, flags);
+	pch_can_rw_msg_obj(&priv->regs->ifregs[1].creq, tx_obj_no);
 
 	return NETDEV_TX_OK;
 }
@@ -1203,21 +959,98 @@ static void __devexit pch_can_remove(str
 	struct pch_can_priv *priv = netdev_priv(ndev);
 
 	unregister_candev(priv->ndev);
-	free_candev(priv->ndev);
-	pci_iounmap(pdev, priv->regs);
+	if (priv->use_msi)
+		pci_disable_msi(priv->dev);
 	pci_release_regions(pdev);
 	pci_disable_device(pdev);
 	pci_set_drvdata(pdev, NULL);
 	pch_can_reset(priv);
+	pci_iounmap(pdev, priv->regs);
+	free_candev(priv->ndev);
 }
 
 #ifdef CONFIG_PM
+static void pch_can_set_int_custom(struct pch_can_priv *priv)
+{
+	/* Clearing the IE, SIE and EIE bits of Can control register. */
+	pch_can_bit_clear(&priv->regs->cont, PCH_CTRL_IE_SIE_EIE);
+
+	/* Appropriately setting them. */
+	pch_can_bit_set(&priv->regs->cont,
+			((priv->int_enables & PCH_MSK_CTRL_IE_SIE_EIE) << 1));
+}
+
+/* This function retrieves interrupt enabled for the CAN device. */
+static u32 pch_can_get_int_enables(struct pch_can_priv *priv)
+{
+	/* Obtaining the status of IE, SIE and EIE interrupt bits. */
+	return (ioread32(&priv->regs->cont) & PCH_CTRL_IE_SIE_EIE) >> 1;
+}
+
+static u32 pch_can_get_rxtx_ir(struct pch_can_priv *priv, u32 buff_num,
+			       enum pch_ifreg dir)
+{
+	u32 ie, enable;
+
+	if (dir)
+		ie = PCH_IF_MCONT_RXIE;
+	else
+		ie = PCH_IF_MCONT_TXIE;
+
+	iowrite32(PCH_CMASK_RX_TX_GET, &priv->regs->ifregs[dir].cmask);
+	pch_can_rw_msg_obj(&priv->regs->ifregs[dir].creq, buff_num);
+
+	if (((ioread32(&priv->regs->ifregs[dir].id2)) & PCH_ID_MSGVAL) &&
+			((ioread32(&priv->regs->ifregs[dir].mcont)) & ie))
+		enable = 1;
+	else
+		enable = 0;
+
+	return enable;
+}
+
+static void pch_can_set_rx_buffer_link(struct pch_can_priv *priv,
+				       u32 buffer_num, int set)
+{
+	iowrite32(PCH_CMASK_RX_TX_GET, &priv->regs->ifregs[0].cmask);
+	pch_can_rw_msg_obj(&priv->regs->ifregs[0].creq, buffer_num);
+	iowrite32(PCH_CMASK_RDWR | PCH_CMASK_CTRL,
+		  &priv->regs->ifregs[0].cmask);
+	if (set)
+		pch_can_bit_clear(&priv->regs->ifregs[0].mcont,
+				  PCH_IF_MCONT_EOB);
+	else
+		pch_can_bit_set(&priv->regs->ifregs[0].mcont, PCH_IF_MCONT_EOB);
+
+	pch_can_rw_msg_obj(&priv->regs->ifregs[0].creq, buffer_num);
+}
+
+static u32 pch_can_get_rx_buffer_link(struct pch_can_priv *priv, u32 buffer_num)
+{
+	u32 link;
+
+	iowrite32(PCH_CMASK_RX_TX_GET, &priv->regs->ifregs[0].cmask);
+	pch_can_rw_msg_obj(&priv->regs->ifregs[0].creq, buffer_num);
+
+	if (ioread32(&priv->regs->ifregs[0].mcont) & PCH_IF_MCONT_EOB)
+		link = 0;
+	else
+		link = 1;
+	return link;
+}
+
+static int pch_can_get_buffer_status(struct pch_can_priv *priv)
+{
+	return (ioread32(&priv->regs->treq1) & 0xffff) |
+	       (ioread32(&priv->regs->treq2) << 16);
+}
+
 static int pch_can_suspend(struct pci_dev *pdev, pm_message_t state)
 {
-	int i;			/* Counter variable. */
-	int retval;		/* Return value. */
+	int i;
+	int retval;
 	u32 buf_stat;	/* Variable for reading the transmit buffer status. */
-	u32 counter = 0xFFFFFF;
+	int counter = PCH_COUNTER_LIMIT;
 
 	struct net_device *dev = pci_get_drvdata(pdev);
 	struct pch_can_priv *priv = netdev_priv(dev);
@@ -1226,7 +1059,7 @@ static int pch_can_suspend(struct pci_de
 	pch_can_set_run_mode(priv, PCH_CAN_STOP);
 
 	/* Indicate that we are aboutto/in suspend */
-	priv->can.state = CAN_STATE_SLEEPING;
+	priv->can.state = CAN_STATE_STOPPED;
 
 	/* Waiting for all transmission to complete. */
 	while (counter) {
@@ -1240,31 +1073,26 @@ static int pch_can_suspend(struct pci_de
 		dev_err(&pdev->dev, "%s -> Transmission time out.\n", __func__);
 
 	/* Save interrupt configuration and then disable them */
-	pch_can_get_int_enables(priv, &(priv->int_enables));
+	priv->int_enables = pch_can_get_int_enables(priv);
 	pch_can_set_int_enables(priv, PCH_CAN_DISABLE);
 
 	/* Save Tx buffer enable state */
-	for (i = 0; i < PCH_OBJ_NUM; i++) {
-		if (priv->msg_obj[i] == MSG_OBJ_TX)
-			pch_can_get_tx_enable(priv, i + 1,
-					      &(priv->tx_enable[i]));
-	}
+	for (i = PCH_TX_OBJ_START; i <= PCH_TX_OBJ_END; i++)
+		priv->tx_enable[i - 1] = pch_can_get_rxtx_ir(priv, i,
+							     PCH_TX_IFREG);
 
 	/* Disable all Transmit buffers */
-	pch_can_tx_disable_all(priv);
+	pch_can_set_tx_all(priv, 0);
 
 	/* Save Rx buffer enable state */
-	for (i = 0; i < PCH_OBJ_NUM; i++) {
-		if (priv->msg_obj[i] == MSG_OBJ_RX) {
-			pch_can_get_rx_enable(priv, i + 1,
-						&(priv->rx_enable[i]));
-			pch_can_get_rx_buffer_link(priv, i + 1,
-						&(priv->rx_link[i]));
-		}
+	for (i = PCH_RX_OBJ_START; i <= PCH_RX_OBJ_END; i++) {
+		priv->rx_enable[i - 1] = pch_can_get_rxtx_ir(priv, i,
+							     PCH_RX_IFREG);
+		priv->rx_link[i - 1] = pch_can_get_rx_buffer_link(priv, i);
 	}
 
 	/* Disable all Receive buffers */
-	pch_can_rx_disable_all(priv);
+	pch_can_set_rx_all(priv, 0);
 	retval = pci_save_state(pdev);
 	if (retval) {
 		dev_err(&pdev->dev, "pci_save_state failed.\n");
@@ -1279,8 +1107,8 @@ static int pch_can_suspend(struct pci_de
 
 static int pch_can_resume(struct pci_dev *pdev)
 {
-	int i;			/* Counter variable. */
-	int retval;		/* Return variable. */
+	int i;
+	int retval;
 	struct net_device *dev = pci_get_drvdata(pdev);
 	struct pch_can_priv *priv = netdev_priv(dev);
 
@@ -1312,23 +1140,16 @@ static int pch_can_resume(struct pci_dev
 	pch_can_set_optmode(priv);
 
 	/* Enabling the transmit buffer. */
-	for (i = 0; i < PCH_OBJ_NUM; i++) {
-		if (priv->msg_obj[i] == MSG_OBJ_TX) {
-			pch_can_set_tx_enable(priv, i + 1,
-					      priv->tx_enable[i]);
-		}
-	}
+	for (i = PCH_TX_OBJ_START; i <= PCH_TX_OBJ_END; i++)
+		pch_can_set_rxtx(priv, i, priv->tx_enable[i - 1], PCH_TX_IFREG);
 
 	/* Configuring the receive buffer and enabling them. */
-	for (i = 0; i < PCH_OBJ_NUM; i++) {
-		if (priv->msg_obj[i] == MSG_OBJ_RX) {
-			/* Restore buffer link */
-			pch_can_set_rx_buffer_link(priv, i + 1,
-						   priv->rx_link[i]);
+	for (i = PCH_RX_OBJ_START; i <= PCH_RX_OBJ_END; i++) {
+		/* Restore buffer link */
+		pch_can_set_rx_buffer_link(priv, i, priv->rx_link[i - 1]);
 
-			/* Restore buffer enables */
-			pch_can_set_rx_enable(priv, i + 1, priv->rx_enable[i]);
-		}
+		/* Restore buffer enables */
+		pch_can_set_rxtx(priv, i, priv->rx_enable[i - 1], PCH_RX_IFREG);
 	}
 
 	/* Enable CAN Interrupts */
@@ -1348,9 +1169,10 @@ static int pch_can_get_berr_counter(cons
 				    struct can_berr_counter *bec)
 {
 	struct pch_can_priv *priv = netdev_priv(dev);
+	u32 errc = ioread32(&priv->regs->errc);
 
-	bec->txerr = ioread32(&priv->regs->errc) & CAN_TEC;
-	bec->rxerr = (ioread32(&priv->regs->errc) & CAN_REC) >> 8;
+	bec->txerr = errc & PCH_TEC;
+	bec->rxerr = (errc & PCH_REC) >> 8;
 
 	return 0;
 }
@@ -1361,7 +1183,6 @@ static int __devinit pch_can_probe(struc
 	struct net_device *ndev;
 	struct pch_can_priv *priv;
 	int rc;
-	int index;
 	void __iomem *addr;
 
 	rc = pci_enable_device(pdev);
@@ -1383,7 +1204,7 @@ static int __devinit pch_can_probe(struc
 		goto probe_exit_ipmap;
 	}
 
-	ndev = alloc_candev(sizeof(struct pch_can_priv), PCH_TX_OBJ_NUM);
+	ndev = alloc_candev(sizeof(struct pch_can_priv), PCH_TX_OBJ_END);
 	if (!ndev) {
 		rc = -ENOMEM;
 		dev_err(&pdev->dev, "Failed alloc_candev\n");
@@ -1399,7 +1220,7 @@ static int __devinit pch_can_probe(struc
 	priv->can.do_get_berr_counter = pch_can_get_berr_counter;
 	priv->can.ctrlmode_supported = CAN_CTRLMODE_LISTENONLY |
 				       CAN_CTRLMODE_LOOPBACK;
-	priv->tx_obj = PCH_RX_OBJ_NUM + 1; /* Point head of Tx Obj */
+	priv->tx_obj = PCH_TX_OBJ_START; /* Point head of Tx Obj */
 
 	ndev->irq = pdev->irq;
 	ndev->flags |= IFF_ECHO;
@@ -1407,15 +1228,19 @@ static int __devinit pch_can_probe(struc
 	pci_set_drvdata(pdev, ndev);
 	SET_NETDEV_DEV(ndev, &pdev->dev);
 	ndev->netdev_ops = &pch_can_netdev_ops;
-
 	priv->can.clock.freq = PCH_CAN_CLK; /* Hz */
-	for (index = 0; index < PCH_RX_OBJ_NUM;)
-		priv->msg_obj[index++] = MSG_OBJ_RX;
 
-	for (index = index;  index < PCH_OBJ_NUM;)
-		priv->msg_obj[index++] = MSG_OBJ_TX;
+	netif_napi_add(ndev, &priv->napi, pch_can_poll, PCH_RX_OBJ_END);
 
-	netif_napi_add(ndev, &priv->napi, pch_can_rx_poll, PCH_RX_OBJ_NUM);
+	rc = pci_enable_msi(priv->dev);
+	if (rc) {
+		netdev_err(ndev, "PCH CAN opened without MSI\n");
+		priv->use_msi = 0;
+	} else {
+		netdev_err(ndev, "PCH CAN opened with MSI\n");
+		pci_set_master(pdev);
+		priv->use_msi = 1;
+	}
 
 	rc = register_candev(ndev);
 	if (rc) {
@@ -1426,6 +1251,8 @@ static int __devinit pch_can_probe(struc
 	return 0;
 
 probe_exit_reg_candev:
+	if (priv->use_msi)
+		pci_disable_msi(priv->dev);
 	free_candev(ndev);
 probe_exit_alloc_candev:
 	pci_iounmap(pdev, addr);
@@ -1458,6 +1285,6 @@ static void __exit pch_can_pci_exit(void
 }
 module_exit(pch_can_pci_exit);
 
-MODULE_DESCRIPTION("Controller Area Network Driver");
+MODULE_DESCRIPTION("Intel EG20T PCH CAN(Controller Area Network) Driver");
 MODULE_LICENSE("GPL v2");
 MODULE_VERSION("0.94");
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/can/sja1000/plx_pci.c linux-libre-2.6.38-gnu1/drivers/net/can/sja1000/plx_pci.c
--- linux-libre-2.6.37-gnu1/drivers/net/can/sja1000/plx_pci.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/can/sja1000/plx_pci.c	2011-03-14 21:20:32.000000000 -0400
@@ -383,7 +383,7 @@ static void plx_pci_reset_marathon(struc
 {
 	void __iomem *reset_addr;
 	int i;
-	int reset_bar[2] = {3, 5};
+	static const int reset_bar[2] = {3, 5};
 
 	plx_pci_reset_common(pdev);
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/can/sja1000/sja1000_of_platform.c linux-libre-2.6.38-gnu1/drivers/net/can/sja1000/sja1000_of_platform.c
--- linux-libre-2.6.37-gnu1/drivers/net/can/sja1000/sja1000_of_platform.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/can/sja1000/sja1000_of_platform.c	2011-03-14 21:20:32.000000000 -0400
@@ -107,17 +107,13 @@ static int __devinit sja1000_ofp_probe(s
 	res_size = resource_size(&res);
 
 	if (!request_mem_region(res.start, res_size, DRV_NAME)) {
-		dev_err(&ofdev->dev, "couldn't request %#llx..%#llx\n",
-			(unsigned long long)res.start,
-			(unsigned long long)res.end);
+		dev_err(&ofdev->dev, "couldn't request %pR\n", &res);
 		return -EBUSY;
 	}
 
 	base = ioremap_nocache(res.start, res_size);
 	if (!base) {
-		dev_err(&ofdev->dev, "couldn't ioremap %#llx..%#llx\n",
-			(unsigned long long)res.start,
-			(unsigned long long)res.end);
+		dev_err(&ofdev->dev, "couldn't ioremap %pR\n", &res);
 		err = -ENOMEM;
 		goto exit_release_mem;
 	}
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/can/slcan.c linux-libre-2.6.38-gnu1/drivers/net/can/slcan.c
--- linux-libre-2.6.37-gnu1/drivers/net/can/slcan.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/can/slcan.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,756 @@
+/*
+ * slcan.c - serial line CAN interface driver (using tty line discipline)
+ *
+ * This file is derived from linux/drivers/net/slip.c
+ *
+ * slip.c Authors  : Laurence Culhane <loz@holmes.demon.co.uk>
+ *                   Fred N. van Kempen <waltje@uwalt.nl.mugnet.org>
+ * slcan.c Author  : Oliver Hartkopp <socketcan@hartkopp.net>
+ *
+ * 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. You can also get it
+ * at http://www.gnu.org/licenses/gpl.html
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "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 COPYRIGHT
+ * OWNER OR CONTRIBUTORS 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.
+ *
+ * Send feedback to <socketcan-users@lists.berlios.de>
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+
+#include <asm/system.h>
+#include <linux/uaccess.h>
+#include <linux/bitops.h>
+#include <linux/string.h>
+#include <linux/tty.h>
+#include <linux/errno.h>
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+#include <linux/rtnetlink.h>
+#include <linux/if_arp.h>
+#include <linux/if_ether.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/can.h>
+
+static __initdata const char banner[] =
+	KERN_INFO "slcan: serial line CAN interface driver\n";
+
+MODULE_ALIAS_LDISC(N_SLCAN);
+MODULE_DESCRIPTION("serial line CAN interface");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Oliver Hartkopp <socketcan@hartkopp.net>");
+
+#define SLCAN_MAGIC 0x53CA
+
+static int maxdev = 10;		/* MAX number of SLCAN channels;
+				   This can be overridden with
+				   insmod slcan.ko maxdev=nnn	*/
+module_param(maxdev, int, 0);
+MODULE_PARM_DESC(maxdev, "Maximum number of slcan interfaces");
+
+/* maximum rx buffer len: extended CAN frame with timestamp */
+#define SLC_MTU (sizeof("T1111222281122334455667788EA5F\r")+1)
+
+struct slcan {
+	int			magic;
+
+	/* Various fields. */
+	struct tty_struct	*tty;		/* ptr to TTY structure	     */
+	struct net_device	*dev;		/* easy for intr handling    */
+	spinlock_t		lock;
+
+	/* These are pointers to the malloc()ed frame buffers. */
+	unsigned char		rbuff[SLC_MTU];	/* receiver buffer	     */
+	int			rcount;         /* received chars counter    */
+	unsigned char		xbuff[SLC_MTU];	/* transmitter buffer	     */
+	unsigned char		*xhead;         /* pointer to next XMIT byte */
+	int			xleft;          /* bytes left in XMIT queue  */
+
+	unsigned long		flags;		/* Flag values/ mode etc     */
+#define SLF_INUSE		0		/* Channel in use            */
+#define SLF_ERROR		1               /* Parity, etc. error        */
+
+	unsigned char		leased;
+	dev_t			line;
+	pid_t			pid;
+};
+
+static struct net_device **slcan_devs;
+
+ /************************************************************************
+  *			SLCAN ENCAPSULATION FORMAT			 *
+  ************************************************************************/
+
+/*
+ * A CAN frame has a can_id (11 bit standard frame format OR 29 bit extended
+ * frame format) a data length code (can_dlc) which can be from 0 to 8
+ * and up to <can_dlc> data bytes as payload.
+ * Additionally a CAN frame may become a remote transmission frame if the
+ * RTR-bit is set. This causes another ECU to send a CAN frame with the
+ * given can_id.
+ *
+ * The SLCAN ASCII representation of these different frame types is:
+ * <type> <id> <dlc> <data>*
+ *
+ * Extended frames (29 bit) are defined by capital characters in the type.
+ * RTR frames are defined as 'r' types - normal frames have 't' type:
+ * t => 11 bit data frame
+ * r => 11 bit RTR frame
+ * T => 29 bit data frame
+ * R => 29 bit RTR frame
+ *
+ * The <id> is 3 (standard) or 8 (extended) bytes in ASCII Hex (base64).
+ * The <dlc> is a one byte ASCII number ('0' - '8')
+ * The <data> section has at much ASCII Hex bytes as defined by the <dlc>
+ *
+ * Examples:
+ *
+ * t1230 : can_id 0x123, can_dlc 0, no data
+ * t4563112233 : can_id 0x456, can_dlc 3, data 0x11 0x22 0x33
+ * T12ABCDEF2AA55 : extended can_id 0x12ABCDEF, can_dlc 2, data 0xAA 0x55
+ * r1230 : can_id 0x123, can_dlc 0, no data, remote transmission request
+ *
+ */
+
+ /************************************************************************
+  *			STANDARD SLCAN DECAPSULATION			 *
+  ************************************************************************/
+
+static int asc2nibble(char c)
+{
+
+	if ((c >= '0') && (c <= '9'))
+		return c - '0';
+
+	if ((c >= 'A') && (c <= 'F'))
+		return c - 'A' + 10;
+
+	if ((c >= 'a') && (c <= 'f'))
+		return c - 'a' + 10;
+
+	return 16; /* error */
+}
+
+/* Send one completely decapsulated can_frame to the network layer */
+static void slc_bump(struct slcan *sl)
+{
+	struct sk_buff *skb;
+	struct can_frame cf;
+	int i, dlc_pos, tmp;
+	unsigned long ultmp;
+	char cmd = sl->rbuff[0];
+
+	if ((cmd != 't') && (cmd != 'T') && (cmd != 'r') && (cmd != 'R'))
+		return;
+
+	if (cmd & 0x20) /* tiny chars 'r' 't' => standard frame format */
+		dlc_pos = 4; /* dlc position tiiid */
+	else
+		dlc_pos = 9; /* dlc position Tiiiiiiiid */
+
+	if (!((sl->rbuff[dlc_pos] >= '0') && (sl->rbuff[dlc_pos] < '9')))
+		return;
+
+	cf.can_dlc = sl->rbuff[dlc_pos] - '0'; /* get can_dlc from ASCII val */
+
+	sl->rbuff[dlc_pos] = 0; /* terminate can_id string */
+
+	if (strict_strtoul(sl->rbuff+1, 16, &ultmp))
+		return;
+
+	cf.can_id = ultmp;
+
+	if (!(cmd & 0x20)) /* NO tiny chars => extended frame format */
+		cf.can_id |= CAN_EFF_FLAG;
+
+	if ((cmd | 0x20) == 'r') /* RTR frame */
+		cf.can_id |= CAN_RTR_FLAG;
+
+	*(u64 *) (&cf.data) = 0; /* clear payload */
+
+	for (i = 0, dlc_pos++; i < cf.can_dlc; i++) {
+
+		tmp = asc2nibble(sl->rbuff[dlc_pos++]);
+		if (tmp > 0x0F)
+			return;
+		cf.data[i] = (tmp << 4);
+		tmp = asc2nibble(sl->rbuff[dlc_pos++]);
+		if (tmp > 0x0F)
+			return;
+		cf.data[i] |= tmp;
+	}
+
+
+	skb = dev_alloc_skb(sizeof(struct can_frame));
+	if (!skb)
+		return;
+
+	skb->dev = sl->dev;
+	skb->protocol = htons(ETH_P_CAN);
+	skb->pkt_type = PACKET_BROADCAST;
+	skb->ip_summed = CHECKSUM_UNNECESSARY;
+	memcpy(skb_put(skb, sizeof(struct can_frame)),
+	       &cf, sizeof(struct can_frame));
+	netif_rx(skb);
+
+	sl->dev->stats.rx_packets++;
+	sl->dev->stats.rx_bytes += cf.can_dlc;
+}
+
+/* parse tty input stream */
+static void slcan_unesc(struct slcan *sl, unsigned char s)
+{
+
+	if ((s == '\r') || (s == '\a')) { /* CR or BEL ends the pdu */
+		if (!test_and_clear_bit(SLF_ERROR, &sl->flags) &&
+		    (sl->rcount > 4))  {
+			slc_bump(sl);
+		}
+		sl->rcount = 0;
+	} else {
+		if (!test_bit(SLF_ERROR, &sl->flags))  {
+			if (sl->rcount < SLC_MTU)  {
+				sl->rbuff[sl->rcount++] = s;
+				return;
+			} else {
+				sl->dev->stats.rx_over_errors++;
+				set_bit(SLF_ERROR, &sl->flags);
+			}
+		}
+	}
+}
+
+ /************************************************************************
+  *			STANDARD SLCAN ENCAPSULATION			 *
+  ************************************************************************/
+
+/* Encapsulate one can_frame and stuff into a TTY queue. */
+static void slc_encaps(struct slcan *sl, struct can_frame *cf)
+{
+	int actual, idx, i;
+	char cmd;
+
+	if (cf->can_id & CAN_RTR_FLAG)
+		cmd = 'R'; /* becomes 'r' in standard frame format */
+	else
+		cmd = 'T'; /* becomes 't' in standard frame format */
+
+	if (cf->can_id & CAN_EFF_FLAG)
+		sprintf(sl->xbuff, "%c%08X%d", cmd,
+			cf->can_id & CAN_EFF_MASK, cf->can_dlc);
+	else
+		sprintf(sl->xbuff, "%c%03X%d", cmd | 0x20,
+			cf->can_id & CAN_SFF_MASK, cf->can_dlc);
+
+	idx = strlen(sl->xbuff);
+
+	for (i = 0; i < cf->can_dlc; i++)
+		sprintf(&sl->xbuff[idx + 2*i], "%02X", cf->data[i]);
+
+	strcat(sl->xbuff, "\r"); /* add terminating character */
+
+	/* Order of next two lines is *very* important.
+	 * When we are sending a little amount of data,
+	 * the transfer may be completed inside the ops->write()
+	 * routine, because it's running with interrupts enabled.
+	 * In this case we *never* got WRITE_WAKEUP event,
+	 * if we did not request it before write operation.
+	 *       14 Oct 1994  Dmitry Gorodchanin.
+	 */
+	set_bit(TTY_DO_WRITE_WAKEUP, &sl->tty->flags);
+	actual = sl->tty->ops->write(sl->tty, sl->xbuff, strlen(sl->xbuff));
+	sl->xleft = strlen(sl->xbuff) - actual;
+	sl->xhead = sl->xbuff + actual;
+	sl->dev->stats.tx_bytes += cf->can_dlc;
+}
+
+/*
+ * Called by the driver when there's room for more data.  If we have
+ * more packets to send, we send them here.
+ */
+static void slcan_write_wakeup(struct tty_struct *tty)
+{
+	int actual;
+	struct slcan *sl = (struct slcan *) tty->disc_data;
+
+	/* First make sure we're connected. */
+	if (!sl || sl->magic != SLCAN_MAGIC || !netif_running(sl->dev))
+		return;
+
+	if (sl->xleft <= 0)  {
+		/* Now serial buffer is almost free & we can start
+		 * transmission of another packet */
+		sl->dev->stats.tx_packets++;
+		clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
+		netif_wake_queue(sl->dev);
+		return;
+	}
+
+	actual = tty->ops->write(tty, sl->xhead, sl->xleft);
+	sl->xleft -= actual;
+	sl->xhead += actual;
+}
+
+/* Send a can_frame to a TTY queue. */
+static netdev_tx_t slc_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	struct slcan *sl = netdev_priv(dev);
+
+	if (skb->len != sizeof(struct can_frame))
+		goto out;
+
+	spin_lock(&sl->lock);
+	if (!netif_running(dev))  {
+		spin_unlock(&sl->lock);
+		printk(KERN_WARNING "%s: xmit: iface is down\n", dev->name);
+		goto out;
+	}
+	if (sl->tty == NULL) {
+		spin_unlock(&sl->lock);
+		goto out;
+	}
+
+	netif_stop_queue(sl->dev);
+	slc_encaps(sl, (struct can_frame *) skb->data); /* encaps & send */
+	spin_unlock(&sl->lock);
+
+out:
+	kfree_skb(skb);
+	return NETDEV_TX_OK;
+}
+
+
+/******************************************
+ *   Routines looking at netdevice side.
+ ******************************************/
+
+/* Netdevice UP -> DOWN routine */
+static int slc_close(struct net_device *dev)
+{
+	struct slcan *sl = netdev_priv(dev);
+
+	spin_lock_bh(&sl->lock);
+	if (sl->tty) {
+		/* TTY discipline is running. */
+		clear_bit(TTY_DO_WRITE_WAKEUP, &sl->tty->flags);
+	}
+	netif_stop_queue(dev);
+	sl->rcount   = 0;
+	sl->xleft    = 0;
+	spin_unlock_bh(&sl->lock);
+
+	return 0;
+}
+
+/* Netdevice DOWN -> UP routine */
+static int slc_open(struct net_device *dev)
+{
+	struct slcan *sl = netdev_priv(dev);
+
+	if (sl->tty == NULL)
+		return -ENODEV;
+
+	sl->flags &= (1 << SLF_INUSE);
+	netif_start_queue(dev);
+	return 0;
+}
+
+/* Hook the destructor so we can free slcan devs at the right point in time */
+static void slc_free_netdev(struct net_device *dev)
+{
+	int i = dev->base_addr;
+	free_netdev(dev);
+	slcan_devs[i] = NULL;
+}
+
+static const struct net_device_ops slc_netdev_ops = {
+	.ndo_open               = slc_open,
+	.ndo_stop               = slc_close,
+	.ndo_start_xmit         = slc_xmit,
+};
+
+static void slc_setup(struct net_device *dev)
+{
+	dev->netdev_ops		= &slc_netdev_ops;
+	dev->destructor		= slc_free_netdev;
+
+	dev->hard_header_len	= 0;
+	dev->addr_len		= 0;
+	dev->tx_queue_len	= 10;
+
+	dev->mtu		= sizeof(struct can_frame);
+	dev->type		= ARPHRD_CAN;
+
+	/* New-style flags. */
+	dev->flags		= IFF_NOARP;
+	dev->features           = NETIF_F_NO_CSUM;
+}
+
+/******************************************
+  Routines looking at TTY side.
+ ******************************************/
+
+/*
+ * Handle the 'receiver data ready' interrupt.
+ * This function is called by the 'tty_io' module in the kernel when
+ * a block of SLCAN data has been received, which can now be decapsulated
+ * and sent on to some IP layer for further processing. This will not
+ * be re-entered while running but other ldisc functions may be called
+ * in parallel
+ */
+
+static void slcan_receive_buf(struct tty_struct *tty,
+			      const unsigned char *cp, char *fp, int count)
+{
+	struct slcan *sl = (struct slcan *) tty->disc_data;
+
+	if (!sl || sl->magic != SLCAN_MAGIC || !netif_running(sl->dev))
+		return;
+
+	/* Read the characters out of the buffer */
+	while (count--) {
+		if (fp && *fp++) {
+			if (!test_and_set_bit(SLF_ERROR, &sl->flags))
+				sl->dev->stats.rx_errors++;
+			cp++;
+			continue;
+		}
+		slcan_unesc(sl, *cp++);
+	}
+}
+
+/************************************
+ *  slcan_open helper routines.
+ ************************************/
+
+/* Collect hanged up channels */
+static void slc_sync(void)
+{
+	int i;
+	struct net_device *dev;
+	struct slcan	  *sl;
+
+	for (i = 0; i < maxdev; i++) {
+		dev = slcan_devs[i];
+		if (dev == NULL)
+			break;
+
+		sl = netdev_priv(dev);
+		if (sl->tty || sl->leased)
+			continue;
+		if (dev->flags & IFF_UP)
+			dev_close(dev);
+	}
+}
+
+/* Find a free SLCAN channel, and link in this `tty' line. */
+static struct slcan *slc_alloc(dev_t line)
+{
+	int i;
+	struct net_device *dev = NULL;
+	struct slcan       *sl;
+
+	if (slcan_devs == NULL)
+		return NULL;	/* Master array missing ! */
+
+	for (i = 0; i < maxdev; i++) {
+		dev = slcan_devs[i];
+		if (dev == NULL)
+			break;
+
+	}
+
+	/* Sorry, too many, all slots in use */
+	if (i >= maxdev)
+		return NULL;
+
+	if (dev) {
+		sl = netdev_priv(dev);
+		if (test_bit(SLF_INUSE, &sl->flags)) {
+			unregister_netdevice(dev);
+			dev = NULL;
+			slcan_devs[i] = NULL;
+		}
+	}
+
+	if (!dev) {
+		char name[IFNAMSIZ];
+		sprintf(name, "slcan%d", i);
+
+		dev = alloc_netdev(sizeof(*sl), name, slc_setup);
+		if (!dev)
+			return NULL;
+		dev->base_addr  = i;
+	}
+
+	sl = netdev_priv(dev);
+
+	/* Initialize channel control data */
+	sl->magic = SLCAN_MAGIC;
+	sl->dev	= dev;
+	spin_lock_init(&sl->lock);
+	slcan_devs[i] = dev;
+
+	return sl;
+}
+
+/*
+ * Open the high-level part of the SLCAN channel.
+ * This function is called by the TTY module when the
+ * SLCAN line discipline is called for.  Because we are
+ * sure the tty line exists, we only have to link it to
+ * a free SLCAN channel...
+ *
+ * Called in process context serialized from other ldisc calls.
+ */
+
+static int slcan_open(struct tty_struct *tty)
+{
+	struct slcan *sl;
+	int err;
+
+	if (!capable(CAP_NET_ADMIN))
+		return -EPERM;
+
+	if (tty->ops->write == NULL)
+		return -EOPNOTSUPP;
+
+	/* RTnetlink lock is misused here to serialize concurrent
+	   opens of slcan channels. There are better ways, but it is
+	   the simplest one.
+	 */
+	rtnl_lock();
+
+	/* Collect hanged up channels. */
+	slc_sync();
+
+	sl = tty->disc_data;
+
+	err = -EEXIST;
+	/* First make sure we're not already connected. */
+	if (sl && sl->magic == SLCAN_MAGIC)
+		goto err_exit;
+
+	/* OK.  Find a free SLCAN channel to use. */
+	err = -ENFILE;
+	sl = slc_alloc(tty_devnum(tty));
+	if (sl == NULL)
+		goto err_exit;
+
+	sl->tty = tty;
+	tty->disc_data = sl;
+	sl->line = tty_devnum(tty);
+	sl->pid = current->pid;
+
+	if (!test_bit(SLF_INUSE, &sl->flags)) {
+		/* Perform the low-level SLCAN initialization. */
+		sl->rcount   = 0;
+		sl->xleft    = 0;
+
+		set_bit(SLF_INUSE, &sl->flags);
+
+		err = register_netdevice(sl->dev);
+		if (err)
+			goto err_free_chan;
+	}
+
+	/* Done.  We have linked the TTY line to a channel. */
+	rtnl_unlock();
+	tty->receive_room = 65536;	/* We don't flow control */
+	return sl->dev->base_addr;
+
+err_free_chan:
+	sl->tty = NULL;
+	tty->disc_data = NULL;
+	clear_bit(SLF_INUSE, &sl->flags);
+
+err_exit:
+	rtnl_unlock();
+
+	/* Count references from TTY module */
+	return err;
+}
+
+/*
+ * Close down a SLCAN channel.
+ * This means flushing out any pending queues, and then returning. This
+ * call is serialized against other ldisc functions.
+ *
+ * We also use this method for a hangup event.
+ */
+
+static void slcan_close(struct tty_struct *tty)
+{
+	struct slcan *sl = (struct slcan *) tty->disc_data;
+
+	/* First make sure we're connected. */
+	if (!sl || sl->magic != SLCAN_MAGIC || sl->tty != tty)
+		return;
+
+	tty->disc_data = NULL;
+	sl->tty = NULL;
+	if (!sl->leased)
+		sl->line = 0;
+
+	/* Flush network side */
+	unregister_netdev(sl->dev);
+	/* This will complete via sl_free_netdev */
+}
+
+static int slcan_hangup(struct tty_struct *tty)
+{
+	slcan_close(tty);
+	return 0;
+}
+
+/* Perform I/O control on an active SLCAN channel. */
+static int slcan_ioctl(struct tty_struct *tty, struct file *file,
+		       unsigned int cmd, unsigned long arg)
+{
+	struct slcan *sl = (struct slcan *) tty->disc_data;
+	unsigned int tmp;
+
+	/* First make sure we're connected. */
+	if (!sl || sl->magic != SLCAN_MAGIC)
+		return -EINVAL;
+
+	switch (cmd) {
+	case SIOCGIFNAME:
+		tmp = strlen(sl->dev->name) + 1;
+		if (copy_to_user((void __user *)arg, sl->dev->name, tmp))
+			return -EFAULT;
+		return 0;
+
+	case SIOCSIFHWADDR:
+		return -EINVAL;
+
+	default:
+		return tty_mode_ioctl(tty, file, cmd, arg);
+	}
+}
+
+static struct tty_ldisc_ops slc_ldisc = {
+	.owner		= THIS_MODULE,
+	.magic		= TTY_LDISC_MAGIC,
+	.name		= "slcan",
+	.open		= slcan_open,
+	.close		= slcan_close,
+	.hangup		= slcan_hangup,
+	.ioctl		= slcan_ioctl,
+	.receive_buf	= slcan_receive_buf,
+	.write_wakeup	= slcan_write_wakeup,
+};
+
+static int __init slcan_init(void)
+{
+	int status;
+
+	if (maxdev < 4)
+		maxdev = 4; /* Sanity */
+
+	printk(banner);
+	printk(KERN_INFO "slcan: %d dynamic interface channels.\n", maxdev);
+
+	slcan_devs = kzalloc(sizeof(struct net_device *)*maxdev, GFP_KERNEL);
+	if (!slcan_devs) {
+		printk(KERN_ERR "slcan: can't allocate slcan device array!\n");
+		return -ENOMEM;
+	}
+
+	/* Fill in our line protocol discipline, and register it */
+	status = tty_register_ldisc(N_SLCAN, &slc_ldisc);
+	if (status)  {
+		printk(KERN_ERR "slcan: can't register line discipline\n");
+		kfree(slcan_devs);
+	}
+	return status;
+}
+
+static void __exit slcan_exit(void)
+{
+	int i;
+	struct net_device *dev;
+	struct slcan *sl;
+	unsigned long timeout = jiffies + HZ;
+	int busy = 0;
+
+	if (slcan_devs == NULL)
+		return;
+
+	/* First of all: check for active disciplines and hangup them.
+	 */
+	do {
+		if (busy)
+			msleep_interruptible(100);
+
+		busy = 0;
+		for (i = 0; i < maxdev; i++) {
+			dev = slcan_devs[i];
+			if (!dev)
+				continue;
+			sl = netdev_priv(dev);
+			spin_lock_bh(&sl->lock);
+			if (sl->tty) {
+				busy++;
+				tty_hangup(sl->tty);
+			}
+			spin_unlock_bh(&sl->lock);
+		}
+	} while (busy && time_before(jiffies, timeout));
+
+	/* FIXME: hangup is async so we should wait when doing this second
+	   phase */
+
+	for (i = 0; i < maxdev; i++) {
+		dev = slcan_devs[i];
+		if (!dev)
+			continue;
+		slcan_devs[i] = NULL;
+
+		sl = netdev_priv(dev);
+		if (sl->tty) {
+			printk(KERN_ERR "%s: tty discipline still running\n",
+			       dev->name);
+			/* Intentionally leak the control block. */
+			dev->destructor = NULL;
+		}
+
+		unregister_netdev(dev);
+	}
+
+	kfree(slcan_devs);
+	slcan_devs = NULL;
+
+	i = tty_unregister_ldisc(N_SLCAN);
+	if (i)
+		printk(KERN_ERR "slcan: can't unregister ldisc (err %d)\n", i);
+}
+
+module_init(slcan_init);
+module_exit(slcan_exit);
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/can/softing/Kconfig linux-libre-2.6.38-gnu1/drivers/net/can/softing/Kconfig
--- linux-libre-2.6.37-gnu1/drivers/net/can/softing/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/can/softing/Kconfig	2013-05-03 02:04:16.000000000 -0400
@@ -0,0 +1,27 @@
+config CAN_SOFTING
+	tristate "Softing Gmbh CAN generic support"
+	depends on CAN_DEV && HAS_IOMEM
+	---help---
+	  Support for CAN cards from Softing Gmbh & some cards
+	  from Vector Gmbh.
+	  Softing Gmbh CAN cards come with 1 or 2 physical busses.
+	  Those cards typically use Dual Port RAM to communicate
+	  with the host CPU. The interface is then identical for PCI
+	  and PCMCIA cards. This driver operates on a platform device,
+	  which has been created by softing_cs or softing_pci driver.
+	  Warning:
+	  The API of the card does not allow fine control per bus, but
+	  controls the 2 busses on the card together.
+	  As such, some actions (start/stop/busoff recovery) on 1 bus
+	  must bring down the other bus too temporarily.
+
+config CAN_SOFTING_CS
+	tristate "Softing Gmbh CAN pcmcia cards"
+	depends on PCMCIA
+	depends on CAN_SOFTING
+	---help---
+	  Support for PCMCIA cards from Softing Gmbh & some cards
+	  from Vector Gmbh.
+	  /*(DEBLOBBED)*/
+	  In order to use the card as CAN device, you need the Softing generic
+	  support too.
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/can/softing/Makefile linux-libre-2.6.38-gnu1/drivers/net/can/softing/Makefile
--- linux-libre-2.6.37-gnu1/drivers/net/can/softing/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/can/softing/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,6 @@
+
+softing-y := softing_main.o softing_fw.o
+obj-$(CONFIG_CAN_SOFTING) += softing.o
+obj-$(CONFIG_CAN_SOFTING_CS) += softing_cs.o
+
+ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/can/softing/softing_cs.c linux-libre-2.6.38-gnu1/drivers/net/can/softing/softing_cs.c
--- linux-libre-2.6.37-gnu1/drivers/net/can/softing/softing_cs.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/can/softing/softing_cs.c	2013-05-03 02:04:11.000000000 -0400
@@ -0,0 +1,353 @@
+/*
+ * Copyright (C) 2008-2010
+ *
+ * - Kurt Van Dijck, EIA Electronics
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the version 2 of the GNU General Public License
+ * 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/module.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+
+#include <pcmcia/cistpl.h>
+#include <pcmcia/ds.h>
+
+#include "softing_platform.h"
+
+static int softingcs_index;
+static spinlock_t softingcs_index_lock;
+
+static int softingcs_reset(struct platform_device *pdev, int v);
+static int softingcs_enable_irq(struct platform_device *pdev, int v);
+
+/*
+ * platform_data descriptions
+ */
+#define MHZ (1000*1000)
+static const struct softing_platform_data softingcs_platform_data[] = {
+{
+	.name = "CANcard",
+	.manf = 0x0168, .prod = 0x001,
+	.generation = 1,
+	.nbus = 2,
+	.freq = 16 * MHZ, .max_brp = 32, .max_sjw = 4,
+	.dpram_size = 0x0800,
+	.boot = {0x0000, 0x000000, fw_dir "/*(DEBLOBBED)*/",},
+	.load = {0x0120, 0x00f600, fw_dir "/*(DEBLOBBED)*/",},
+	.app = {0x0010, 0x0d0000, fw_dir "/*(DEBLOBBED)*/",},
+	.reset = softingcs_reset,
+	.enable_irq = softingcs_enable_irq,
+}, {
+	.name = "CANcard-NEC",
+	.manf = 0x0168, .prod = 0x002,
+	.generation = 1,
+	.nbus = 2,
+	.freq = 16 * MHZ, .max_brp = 32, .max_sjw = 4,
+	.dpram_size = 0x0800,
+	.boot = {0x0000, 0x000000, fw_dir "/*(DEBLOBBED)*/",},
+	.load = {0x0120, 0x00f600, fw_dir "/*(DEBLOBBED)*/",},
+	.app = {0x0010, 0x0d0000, fw_dir "/*(DEBLOBBED)*/",},
+	.reset = softingcs_reset,
+	.enable_irq = softingcs_enable_irq,
+}, {
+	.name = "CANcard-SJA",
+	.manf = 0x0168, .prod = 0x004,
+	.generation = 1,
+	.nbus = 2,
+	.freq = 20 * MHZ, .max_brp = 32, .max_sjw = 4,
+	.dpram_size = 0x0800,
+	.boot = {0x0000, 0x000000, fw_dir "/*(DEBLOBBED)*/",},
+	.load = {0x0120, 0x00f600, fw_dir "/*(DEBLOBBED)*/",},
+	.app = {0x0010, 0x0d0000, fw_dir "/*(DEBLOBBED)*/",},
+	.reset = softingcs_reset,
+	.enable_irq = softingcs_enable_irq,
+}, {
+	.name = "CANcard-2",
+	.manf = 0x0168, .prod = 0x005,
+	.generation = 2,
+	.nbus = 2,
+	.freq = 24 * MHZ, .max_brp = 64, .max_sjw = 4,
+	.dpram_size = 0x1000,
+	.boot = {0x0000, 0x000000, fw_dir "/*(DEBLOBBED)*/",},
+	.load = {0x0120, 0x00f600, fw_dir "/*(DEBLOBBED)*/",},
+	.app = {0x0010, 0x0d0000, fw_dir "/*(DEBLOBBED)*/",},
+	.reset = softingcs_reset,
+	.enable_irq = NULL,
+}, {
+	.name = "Vector-CANcard",
+	.manf = 0x0168, .prod = 0x081,
+	.generation = 1,
+	.nbus = 2,
+	.freq = 16 * MHZ, .max_brp = 64, .max_sjw = 4,
+	.dpram_size = 0x0800,
+	.boot = {0x0000, 0x000000, fw_dir "/*(DEBLOBBED)*/",},
+	.load = {0x0120, 0x00f600, fw_dir "/*(DEBLOBBED)*/",},
+	.app = {0x0010, 0x0d0000, fw_dir "/*(DEBLOBBED)*/",},
+	.reset = softingcs_reset,
+	.enable_irq = softingcs_enable_irq,
+}, {
+	.name = "Vector-CANcard-SJA",
+	.manf = 0x0168, .prod = 0x084,
+	.generation = 1,
+	.nbus = 2,
+	.freq = 20 * MHZ, .max_brp = 32, .max_sjw = 4,
+	.dpram_size = 0x0800,
+	.boot = {0x0000, 0x000000, fw_dir "/*(DEBLOBBED)*/",},
+	.load = {0x0120, 0x00f600, fw_dir "/*(DEBLOBBED)*/",},
+	.app = {0x0010, 0x0d0000, fw_dir "/*(DEBLOBBED)*/",},
+	.reset = softingcs_reset,
+	.enable_irq = softingcs_enable_irq,
+}, {
+	.name = "Vector-CANcard-2",
+	.manf = 0x0168, .prod = 0x085,
+	.generation = 2,
+	.nbus = 2,
+	.freq = 24 * MHZ, .max_brp = 64, .max_sjw = 4,
+	.dpram_size = 0x1000,
+	.boot = {0x0000, 0x000000, fw_dir "/*(DEBLOBBED)*/",},
+	.load = {0x0120, 0x00f600, fw_dir "/*(DEBLOBBED)*/",},
+	.app = {0x0010, 0x0d0000, fw_dir "/*(DEBLOBBED)*/",},
+	.reset = softingcs_reset,
+	.enable_irq = NULL,
+}, {
+	.name = "EDICcard-NEC",
+	.manf = 0x0168, .prod = 0x102,
+	.generation = 1,
+	.nbus = 2,
+	.freq = 16 * MHZ, .max_brp = 64, .max_sjw = 4,
+	.dpram_size = 0x0800,
+	.boot = {0x0000, 0x000000, fw_dir "/*(DEBLOBBED)*/",},
+	.load = {0x0120, 0x00f600, fw_dir "/*(DEBLOBBED)*/",},
+	.app = {0x0010, 0x0d0000, fw_dir "/*(DEBLOBBED)*/",},
+	.reset = softingcs_reset,
+	.enable_irq = softingcs_enable_irq,
+}, {
+	.name = "EDICcard-2",
+	.manf = 0x0168, .prod = 0x105,
+	.generation = 2,
+	.nbus = 2,
+	.freq = 24 * MHZ, .max_brp = 64, .max_sjw = 4,
+	.dpram_size = 0x1000,
+	.boot = {0x0000, 0x000000, fw_dir "/*(DEBLOBBED)*/",},
+	.load = {0x0120, 0x00f600, fw_dir "/*(DEBLOBBED)*/",},
+	.app = {0x0010, 0x0d0000, fw_dir "/*(DEBLOBBED)*/",},
+	.reset = softingcs_reset,
+	.enable_irq = NULL,
+}, {
+	0, 0,
+},
+};
+
+/*(DEBLOBBED)*/
+
+static __devinit const struct softing_platform_data
+*softingcs_find_platform_data(unsigned int manf, unsigned int prod)
+{
+	const struct softing_platform_data *lp;
+
+	for (lp = softingcs_platform_data; lp->manf; ++lp) {
+		if ((lp->manf == manf) && (lp->prod == prod))
+			return lp;
+	}
+	return NULL;
+}
+
+/*
+ * platformdata callbacks
+ */
+static int softingcs_reset(struct platform_device *pdev, int v)
+{
+	struct pcmcia_device *pcmcia = to_pcmcia_dev(pdev->dev.parent);
+
+	dev_dbg(&pdev->dev, "pcmcia config [2] %02x\n", v ? 0 : 0x20);
+	return pcmcia_write_config_byte(pcmcia, 2, v ? 0 : 0x20);
+}
+
+static int softingcs_enable_irq(struct platform_device *pdev, int v)
+{
+	struct pcmcia_device *pcmcia = to_pcmcia_dev(pdev->dev.parent);
+
+	dev_dbg(&pdev->dev, "pcmcia config [0] %02x\n", v ? 0x60 : 0);
+	return pcmcia_write_config_byte(pcmcia, 0, v ? 0x60 : 0);
+}
+
+/*
+ * pcmcia check
+ */
+static __devinit int softingcs_probe_config(struct pcmcia_device *pcmcia,
+		void *priv_data)
+{
+	struct softing_platform_data *pdat = priv_data;
+	struct resource *pres;
+	int memspeed = 0;
+
+	WARN_ON(!pdat);
+	pres = pcmcia->resource[PCMCIA_IOMEM_0];
+	if (resource_size(pres) < 0x1000)
+		return -ERANGE;
+
+	pres->flags |= WIN_MEMORY_TYPE_CM | WIN_ENABLE;
+	if (pdat->generation < 2) {
+		pres->flags |= WIN_USE_WAIT | WIN_DATA_WIDTH_8;
+		memspeed = 3;
+	} else {
+		pres->flags |= WIN_DATA_WIDTH_16;
+	}
+	return pcmcia_request_window(pcmcia, pres, memspeed);
+}
+
+static __devexit void softingcs_remove(struct pcmcia_device *pcmcia)
+{
+	struct platform_device *pdev = pcmcia->priv;
+
+	/* free bits */
+	platform_device_unregister(pdev);
+	/* release pcmcia stuff */
+	pcmcia_disable_device(pcmcia);
+}
+
+/*
+ * platform_device wrapper
+ * pdev->resource has 2 entries: io & irq
+ */
+static void softingcs_pdev_release(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	kfree(pdev);
+}
+
+static __devinit int softingcs_probe(struct pcmcia_device *pcmcia)
+{
+	int ret;
+	struct platform_device *pdev;
+	const struct softing_platform_data *pdat;
+	struct resource *pres;
+	struct dev {
+		struct platform_device pdev;
+		struct resource res[2];
+	} *dev;
+
+	/* find matching platform_data */
+	pdat = softingcs_find_platform_data(pcmcia->manf_id, pcmcia->card_id);
+	if (!pdat)
+		return -ENOTTY;
+
+	/* setup pcmcia device */
+	pcmcia->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IOMEM |
+		CONF_AUTO_SET_VPP | CONF_AUTO_CHECK_VCC;
+	ret = pcmcia_loop_config(pcmcia, softingcs_probe_config, (void *)pdat);
+	if (ret)
+		goto pcmcia_failed;
+
+	ret = pcmcia_enable_device(pcmcia);
+	if (ret < 0)
+		goto pcmcia_failed;
+
+	pres = pcmcia->resource[PCMCIA_IOMEM_0];
+	if (!pres) {
+		ret = -EBADF;
+		goto pcmcia_bad;
+	}
+
+	/* create softing platform device */
+	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+	if (!dev) {
+		ret = -ENOMEM;
+		goto mem_failed;
+	}
+	dev->pdev.resource = dev->res;
+	dev->pdev.num_resources = ARRAY_SIZE(dev->res);
+	dev->pdev.dev.release = softingcs_pdev_release;
+
+	pdev = &dev->pdev;
+	pdev->dev.platform_data = (void *)pdat;
+	pdev->dev.parent = &pcmcia->dev;
+	pcmcia->priv = pdev;
+
+	/* platform device resources */
+	pdev->resource[0].flags = IORESOURCE_MEM;
+	pdev->resource[0].start = pres->start;
+	pdev->resource[0].end = pres->end;
+
+	pdev->resource[1].flags = IORESOURCE_IRQ;
+	pdev->resource[1].start = pcmcia->irq;
+	pdev->resource[1].end = pdev->resource[1].start;
+
+	/* platform device setup */
+	spin_lock(&softingcs_index_lock);
+	pdev->id = softingcs_index++;
+	spin_unlock(&softingcs_index_lock);
+	pdev->name = "softing";
+	dev_set_name(&pdev->dev, "softingcs.%i", pdev->id);
+	ret = platform_device_register(pdev);
+	if (ret < 0)
+		goto platform_failed;
+
+	dev_info(&pcmcia->dev, "created %s\n", dev_name(&pdev->dev));
+	return 0;
+
+platform_failed:
+	kfree(dev);
+mem_failed:
+pcmcia_bad:
+pcmcia_failed:
+	pcmcia_disable_device(pcmcia);
+	pcmcia->priv = NULL;
+	return ret ?: -ENODEV;
+}
+
+static /*const*/ struct pcmcia_device_id softingcs_ids[] = {
+	/* softing */
+	PCMCIA_DEVICE_MANF_CARD(0x0168, 0x0001),
+	PCMCIA_DEVICE_MANF_CARD(0x0168, 0x0002),
+	PCMCIA_DEVICE_MANF_CARD(0x0168, 0x0004),
+	PCMCIA_DEVICE_MANF_CARD(0x0168, 0x0005),
+	/* vector, manufacturer? */
+	PCMCIA_DEVICE_MANF_CARD(0x0168, 0x0081),
+	PCMCIA_DEVICE_MANF_CARD(0x0168, 0x0084),
+	PCMCIA_DEVICE_MANF_CARD(0x0168, 0x0085),
+	/* EDIC */
+	PCMCIA_DEVICE_MANF_CARD(0x0168, 0x0102),
+	PCMCIA_DEVICE_MANF_CARD(0x0168, 0x0105),
+	PCMCIA_DEVICE_NULL,
+};
+
+MODULE_DEVICE_TABLE(pcmcia, softingcs_ids);
+
+static struct pcmcia_driver softingcs_driver = {
+	.owner		= THIS_MODULE,
+	.name		= "softingcs",
+	.id_table	= softingcs_ids,
+	.probe		= softingcs_probe,
+	.remove		= __devexit_p(softingcs_remove),
+};
+
+static int __init softingcs_start(void)
+{
+	spin_lock_init(&softingcs_index_lock);
+	return pcmcia_register_driver(&softingcs_driver);
+}
+
+static void __exit softingcs_stop(void)
+{
+	pcmcia_unregister_driver(&softingcs_driver);
+}
+
+module_init(softingcs_start);
+module_exit(softingcs_stop);
+
+MODULE_DESCRIPTION("softing CANcard driver"
+		", links PCMCIA card to softing driver");
+MODULE_LICENSE("GPL v2");
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/can/softing/softing_fw.c linux-libre-2.6.38-gnu1/drivers/net/can/softing/softing_fw.c
--- linux-libre-2.6.37-gnu1/drivers/net/can/softing/softing_fw.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/can/softing/softing_fw.c	2013-05-03 02:04:08.000000000 -0400
@@ -0,0 +1,691 @@
+/*
+ * Copyright (C) 2008-2010
+ *
+ * - Kurt Van Dijck, EIA Electronics
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the version 2 of the GNU General Public License
+ * 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/firmware.h>
+#include <linux/sched.h>
+#include <asm/div64.h>
+
+#include "softing.h"
+
+/*
+ * low level DPRAM command.
+ * Make sure that card->dpram[DPRAM_FCT_HOST] is preset
+ */
+static int _softing_fct_cmd(struct softing *card, int16_t cmd, uint16_t vector,
+		const char *msg)
+{
+	int ret;
+	unsigned long stamp;
+
+	iowrite16(cmd, &card->dpram[DPRAM_FCT_PARAM]);
+	iowrite8(vector >> 8, &card->dpram[DPRAM_FCT_HOST + 1]);
+	iowrite8(vector, &card->dpram[DPRAM_FCT_HOST]);
+	/* be sure to flush this to the card */
+	wmb();
+	stamp = jiffies + 1 * HZ;
+	/* wait for card */
+	do {
+		/* DPRAM_FCT_HOST is _not_ aligned */
+		ret = ioread8(&card->dpram[DPRAM_FCT_HOST]) +
+			(ioread8(&card->dpram[DPRAM_FCT_HOST + 1]) << 8);
+		/* don't have any cached variables */
+		rmb();
+		if (ret == RES_OK)
+			/* read return-value now */
+			return ioread16(&card->dpram[DPRAM_FCT_RESULT]);
+
+		if ((ret != vector) || time_after(jiffies, stamp))
+			break;
+		/* process context => relax */
+		usleep_range(500, 10000);
+	} while (1);
+
+	ret = (ret == RES_NONE) ? -ETIMEDOUT : -ECANCELED;
+	dev_alert(&card->pdev->dev, "firmware %s failed (%i)\n", msg, ret);
+	return ret;
+}
+
+static int softing_fct_cmd(struct softing *card, int16_t cmd, const char *msg)
+{
+	int ret;
+
+	ret = _softing_fct_cmd(card, cmd, 0, msg);
+	if (ret > 0) {
+		dev_alert(&card->pdev->dev, "%s returned %u\n", msg, ret);
+		ret = -EIO;
+	}
+	return ret;
+}
+
+int softing_bootloader_command(struct softing *card, int16_t cmd,
+		const char *msg)
+{
+	int ret;
+	unsigned long stamp;
+
+	iowrite16(RES_NONE, &card->dpram[DPRAM_RECEIPT]);
+	iowrite16(cmd, &card->dpram[DPRAM_COMMAND]);
+	/* be sure to flush this to the card */
+	wmb();
+	stamp = jiffies + 3 * HZ;
+	/* wait for card */
+	do {
+		ret = ioread16(&card->dpram[DPRAM_RECEIPT]);
+		/* don't have any cached variables */
+		rmb();
+		if (ret == RES_OK)
+			return 0;
+		if (time_after(jiffies, stamp))
+			break;
+		/* process context => relax */
+		usleep_range(500, 10000);
+	} while (!signal_pending(current));
+
+	ret = (ret == RES_NONE) ? -ETIMEDOUT : -ECANCELED;
+	dev_alert(&card->pdev->dev, "bootloader %s failed (%i)\n", msg, ret);
+	return ret;
+}
+
+static int fw_parse(const uint8_t **pmem, uint16_t *ptype, uint32_t *paddr,
+		uint16_t *plen, const uint8_t **pdat)
+{
+	uint16_t checksum[2];
+	const uint8_t *mem;
+	const uint8_t *end;
+
+	/*
+	 * firmware records are a binary, unaligned stream composed of:
+	 * uint16_t type;
+	 * uint32_t addr;
+	 * uint16_t len;
+	 * uint8_t dat[len];
+	 * uint16_t checksum;
+	 * all values in little endian.
+	 * We could define a struct for this, with __attribute__((packed)),
+	 * but would that solve the alignment in _all_ cases (cfr. the
+	 * struct itself may be an odd address)?
+	 *
+	 * I chose to use leXX_to_cpup() since this solves both
+	 * endianness & alignment.
+	 */
+	mem = *pmem;
+	*ptype = le16_to_cpup((void *)&mem[0]);
+	*paddr = le32_to_cpup((void *)&mem[2]);
+	*plen = le16_to_cpup((void *)&mem[6]);
+	*pdat = &mem[8];
+	/* verify checksum */
+	end = &mem[8 + *plen];
+	checksum[0] = le16_to_cpup((void *)end);
+	for (checksum[1] = 0; mem < end; ++mem)
+		checksum[1] += *mem;
+	if (checksum[0] != checksum[1])
+		return -EINVAL;
+	/* increment */
+	*pmem += 10 + *plen;
+	return 0;
+}
+
+int softing_load_fw(const char *file, struct softing *card,
+		__iomem uint8_t *dpram, unsigned int size, int offset)
+{
+	const struct firmware *fw;
+	int ret;
+	const uint8_t *mem, *end, *dat;
+	uint16_t type, len;
+	uint32_t addr;
+	uint8_t *buf = NULL;
+	int buflen = 0;
+	int8_t type_end = 0;
+
+	ret = reject_firmware(&fw, file, &card->pdev->dev);
+	if (ret < 0)
+		return ret;
+	dev_dbg(&card->pdev->dev, "%s, firmware(%s) got %u bytes"
+		", offset %c0x%04x\n",
+		card->pdat->name, file, (unsigned int)fw->size,
+		(offset >= 0) ? '+' : '-', (unsigned int)abs(offset));
+	/* parse the firmware */
+	mem = fw->data;
+	end = &mem[fw->size];
+	/* look for header record */
+	ret = fw_parse(&mem, &type, &addr, &len, &dat);
+	if (ret < 0)
+		goto failed;
+	if (type != 0xffff)
+		goto failed;
+	if (strncmp("Structured Binary Format, Softing GmbH" , dat, len)) {
+		ret = -EINVAL;
+		goto failed;
+	}
+	/* ok, we had a header */
+	while (mem < end) {
+		ret = fw_parse(&mem, &type, &addr, &len, &dat);
+		if (ret < 0)
+			goto failed;
+		if (type == 3) {
+			/* start address, not used here */
+			continue;
+		} else if (type == 1) {
+			/* eof */
+			type_end = 1;
+			break;
+		} else if (type != 0) {
+			ret = -EINVAL;
+			goto failed;
+		}
+
+		if ((addr + len + offset) > size)
+			goto failed;
+		memcpy_toio(&dpram[addr + offset], dat, len);
+		/* be sure to flush caches from IO space */
+		mb();
+		if (len > buflen) {
+			/* align buflen */
+			buflen = (len + (1024-1)) & ~(1024-1);
+			buf = krealloc(buf, buflen, GFP_KERNEL);
+			if (!buf) {
+				ret = -ENOMEM;
+				goto failed;
+			}
+		}
+		/* verify record data */
+		memcpy_fromio(buf, &dpram[addr + offset], len);
+		if (memcmp(buf, dat, len)) {
+			/* is not ok */
+			dev_alert(&card->pdev->dev, "DPRAM readback failed\n");
+			ret = -EIO;
+			goto failed;
+		}
+	}
+	if (!type_end)
+		/* no end record seen */
+		goto failed;
+	ret = 0;
+failed:
+	kfree(buf);
+	release_firmware(fw);
+	if (ret < 0)
+		dev_info(&card->pdev->dev, "firmware %s failed\n", file);
+	return ret;
+}
+
+int softing_load_app_fw(const char *file, struct softing *card)
+{
+	const struct firmware *fw;
+	const uint8_t *mem, *end, *dat;
+	int ret, j;
+	uint16_t type, len;
+	uint32_t addr, start_addr = 0;
+	unsigned int sum, rx_sum;
+	int8_t type_end = 0, type_entrypoint = 0;
+
+	ret = reject_firmware(&fw, file, &card->pdev->dev);
+	if (ret) {
+		dev_alert(&card->pdev->dev, "reject_firmware(%s) got %i\n",
+			file, ret);
+		return ret;
+	}
+	dev_dbg(&card->pdev->dev, "firmware(%s) got %lu bytes\n",
+		file, (unsigned long)fw->size);
+	/* parse the firmware */
+	mem = fw->data;
+	end = &mem[fw->size];
+	/* look for header record */
+	ret = fw_parse(&mem, &type, &addr, &len, &dat);
+	if (ret)
+		goto failed;
+	ret = -EINVAL;
+	if (type != 0xffff) {
+		dev_alert(&card->pdev->dev, "firmware starts with type 0x%x\n",
+			type);
+		goto failed;
+	}
+	if (strncmp("Structured Binary Format, Softing GmbH", dat, len)) {
+		dev_alert(&card->pdev->dev, "firmware string '%.*s' fault\n",
+				len, dat);
+		goto failed;
+	}
+	/* ok, we had a header */
+	while (mem < end) {
+		ret = fw_parse(&mem, &type, &addr, &len, &dat);
+		if (ret)
+			goto failed;
+
+		if (type == 3) {
+			/* start address */
+			start_addr = addr;
+			type_entrypoint = 1;
+			continue;
+		} else if (type == 1) {
+			/* eof */
+			type_end = 1;
+			break;
+		} else if (type != 0) {
+			dev_alert(&card->pdev->dev,
+					"unknown record type 0x%04x\n", type);
+			ret = -EINVAL;
+			goto failed;
+		}
+
+		/* regualar data */
+		for (sum = 0, j = 0; j < len; ++j)
+			sum += dat[j];
+		/* work in 16bit (target) */
+		sum &= 0xffff;
+
+		memcpy_toio(&card->dpram[card->pdat->app.offs], dat, len);
+		iowrite32(card->pdat->app.offs + card->pdat->app.addr,
+				&card->dpram[DPRAM_COMMAND + 2]);
+		iowrite32(addr, &card->dpram[DPRAM_COMMAND + 6]);
+		iowrite16(len, &card->dpram[DPRAM_COMMAND + 10]);
+		iowrite8(1, &card->dpram[DPRAM_COMMAND + 12]);
+		ret = softing_bootloader_command(card, 1, "loading app.");
+		if (ret < 0)
+			goto failed;
+		/* verify checksum */
+		rx_sum = ioread16(&card->dpram[DPRAM_RECEIPT + 2]);
+		if (rx_sum != sum) {
+			dev_alert(&card->pdev->dev, "SRAM seems to be damaged"
+				", wanted 0x%04x, got 0x%04x\n", sum, rx_sum);
+			ret = -EIO;
+			goto failed;
+		}
+	}
+	if (!type_end || !type_entrypoint)
+		goto failed;
+	/* start application in card */
+	iowrite32(start_addr, &card->dpram[DPRAM_COMMAND + 2]);
+	iowrite8(1, &card->dpram[DPRAM_COMMAND + 6]);
+	ret = softing_bootloader_command(card, 3, "start app.");
+	if (ret < 0)
+		goto failed;
+	ret = 0;
+failed:
+	release_firmware(fw);
+	if (ret < 0)
+		dev_info(&card->pdev->dev, "firmware %s failed\n", file);
+	return ret;
+}
+
+static int softing_reset_chip(struct softing *card)
+{
+	int ret;
+
+	do {
+		/* reset chip */
+		iowrite8(0, &card->dpram[DPRAM_RESET_RX_FIFO]);
+		iowrite8(0, &card->dpram[DPRAM_RESET_RX_FIFO+1]);
+		iowrite8(1, &card->dpram[DPRAM_RESET]);
+		iowrite8(0, &card->dpram[DPRAM_RESET+1]);
+
+		ret = softing_fct_cmd(card, 0, "reset_can");
+		if (!ret)
+			break;
+		if (signal_pending(current))
+			/* don't wait any longer */
+			break;
+	} while (1);
+	card->tx.pending = 0;
+	return ret;
+}
+
+int softing_chip_poweron(struct softing *card)
+{
+	int ret;
+	/* sync */
+	ret = _softing_fct_cmd(card, 99, 0x55, "sync-a");
+	if (ret < 0)
+		goto failed;
+
+	ret = _softing_fct_cmd(card, 99, 0xaa, "sync-b");
+	if (ret < 0)
+		goto failed;
+
+	ret = softing_reset_chip(card);
+	if (ret < 0)
+		goto failed;
+	/* get_serial */
+	ret = softing_fct_cmd(card, 43, "get_serial_number");
+	if (ret < 0)
+		goto failed;
+	card->id.serial = ioread32(&card->dpram[DPRAM_FCT_PARAM]);
+	/* get_version */
+	ret = softing_fct_cmd(card, 12, "get_version");
+	if (ret < 0)
+		goto failed;
+	card->id.fw_version = ioread16(&card->dpram[DPRAM_FCT_PARAM + 2]);
+	card->id.hw_version = ioread16(&card->dpram[DPRAM_FCT_PARAM + 4]);
+	card->id.license = ioread16(&card->dpram[DPRAM_FCT_PARAM + 6]);
+	card->id.chip[0] = ioread16(&card->dpram[DPRAM_FCT_PARAM + 8]);
+	card->id.chip[1] = ioread16(&card->dpram[DPRAM_FCT_PARAM + 10]);
+	return 0;
+failed:
+	return ret;
+}
+
+static void softing_initialize_timestamp(struct softing *card)
+{
+	uint64_t ovf;
+
+	card->ts_ref = ktime_get();
+
+	/* 16MHz is the reference */
+	ovf = 0x100000000ULL * 16;
+	do_div(ovf, card->pdat->freq ?: 16);
+
+	card->ts_overflow = ktime_add_us(ktime_set(0, 0), ovf);
+}
+
+ktime_t softing_raw2ktime(struct softing *card, u32 raw)
+{
+	uint64_t rawl;
+	ktime_t now, real_offset;
+	ktime_t target;
+	ktime_t tmp;
+
+	now = ktime_get();
+	real_offset = ktime_sub(ktime_get_real(), now);
+
+	/* find nsec from card */
+	rawl = raw * 16;
+	do_div(rawl, card->pdat->freq ?: 16);
+	target = ktime_add_us(card->ts_ref, rawl);
+	/* test for overflows */
+	tmp = ktime_add(target, card->ts_overflow);
+	while (unlikely(ktime_to_ns(tmp) > ktime_to_ns(now))) {
+		card->ts_ref = ktime_add(card->ts_ref, card->ts_overflow);
+		target = tmp;
+		tmp = ktime_add(target, card->ts_overflow);
+	}
+	return ktime_add(target, real_offset);
+}
+
+static inline int softing_error_reporting(struct net_device *netdev)
+{
+	struct softing_priv *priv = netdev_priv(netdev);
+
+	return (priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING)
+		? 1 : 0;
+}
+
+int softing_startstop(struct net_device *dev, int up)
+{
+	int ret;
+	struct softing *card;
+	struct softing_priv *priv;
+	struct net_device *netdev;
+	int bus_bitmask_start;
+	int j, error_reporting;
+	struct can_frame msg;
+	const struct can_bittiming *bt;
+
+	priv = netdev_priv(dev);
+	card = priv->card;
+
+	if (!card->fw.up)
+		return -EIO;
+
+	ret = mutex_lock_interruptible(&card->fw.lock);
+	if (ret)
+		return ret;
+
+	bus_bitmask_start = 0;
+	if (dev && up)
+		/* prepare to start this bus as well */
+		bus_bitmask_start |= (1 << priv->index);
+	/* bring netdevs down */
+	for (j = 0; j < ARRAY_SIZE(card->net); ++j) {
+		netdev = card->net[j];
+		if (!netdev)
+			continue;
+		priv = netdev_priv(netdev);
+
+		if (dev != netdev)
+			netif_stop_queue(netdev);
+
+		if (netif_running(netdev)) {
+			if (dev != netdev)
+				bus_bitmask_start |= (1 << j);
+			priv->tx.pending = 0;
+			priv->tx.echo_put = 0;
+			priv->tx.echo_get = 0;
+			/*
+			 * this bus' may just have called open_candev()
+			 * which is rather stupid to call close_candev()
+			 * already
+			 * but we may come here from busoff recovery too
+			 * in which case the echo_skb _needs_ flushing too.
+			 * just be sure to call open_candev() again
+			 */
+			close_candev(netdev);
+		}
+		priv->can.state = CAN_STATE_STOPPED;
+	}
+	card->tx.pending = 0;
+
+	softing_enable_irq(card, 0);
+	ret = softing_reset_chip(card);
+	if (ret)
+		goto failed;
+	if (!bus_bitmask_start)
+		/* no busses to be brought up */
+		goto card_done;
+
+	if ((bus_bitmask_start & 1) && (bus_bitmask_start & 2)
+			&& (softing_error_reporting(card->net[0])
+				!= softing_error_reporting(card->net[1]))) {
+		dev_alert(&card->pdev->dev,
+				"err_reporting flag differs for busses\n");
+		goto invalid;
+	}
+	error_reporting = 0;
+	if (bus_bitmask_start & 1) {
+		netdev = card->net[0];
+		priv = netdev_priv(netdev);
+		error_reporting += softing_error_reporting(netdev);
+		/* init chip 1 */
+		bt = &priv->can.bittiming;
+		iowrite16(bt->brp, &card->dpram[DPRAM_FCT_PARAM + 2]);
+		iowrite16(bt->sjw, &card->dpram[DPRAM_FCT_PARAM + 4]);
+		iowrite16(bt->phase_seg1 + bt->prop_seg,
+				&card->dpram[DPRAM_FCT_PARAM + 6]);
+		iowrite16(bt->phase_seg2, &card->dpram[DPRAM_FCT_PARAM + 8]);
+		iowrite16((priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES) ? 1 : 0,
+				&card->dpram[DPRAM_FCT_PARAM + 10]);
+		ret = softing_fct_cmd(card, 1, "initialize_chip[0]");
+		if (ret < 0)
+			goto failed;
+		/* set mode */
+		iowrite16(0, &card->dpram[DPRAM_FCT_PARAM + 2]);
+		iowrite16(0, &card->dpram[DPRAM_FCT_PARAM + 4]);
+		ret = softing_fct_cmd(card, 3, "set_mode[0]");
+		if (ret < 0)
+			goto failed;
+		/* set filter */
+		/* 11bit id & mask */
+		iowrite16(0x0000, &card->dpram[DPRAM_FCT_PARAM + 2]);
+		iowrite16(0x07ff, &card->dpram[DPRAM_FCT_PARAM + 4]);
+		/* 29bit id.lo & mask.lo & id.hi & mask.hi */
+		iowrite16(0x0000, &card->dpram[DPRAM_FCT_PARAM + 6]);
+		iowrite16(0xffff, &card->dpram[DPRAM_FCT_PARAM + 8]);
+		iowrite16(0x0000, &card->dpram[DPRAM_FCT_PARAM + 10]);
+		iowrite16(0x1fff, &card->dpram[DPRAM_FCT_PARAM + 12]);
+		ret = softing_fct_cmd(card, 7, "set_filter[0]");
+		if (ret < 0)
+			goto failed;
+		/* set output control */
+		iowrite16(priv->output, &card->dpram[DPRAM_FCT_PARAM + 2]);
+		ret = softing_fct_cmd(card, 5, "set_output[0]");
+		if (ret < 0)
+			goto failed;
+	}
+	if (bus_bitmask_start & 2) {
+		netdev = card->net[1];
+		priv = netdev_priv(netdev);
+		error_reporting += softing_error_reporting(netdev);
+		/* init chip2 */
+		bt = &priv->can.bittiming;
+		iowrite16(bt->brp, &card->dpram[DPRAM_FCT_PARAM + 2]);
+		iowrite16(bt->sjw, &card->dpram[DPRAM_FCT_PARAM + 4]);
+		iowrite16(bt->phase_seg1 + bt->prop_seg,
+				&card->dpram[DPRAM_FCT_PARAM + 6]);
+		iowrite16(bt->phase_seg2, &card->dpram[DPRAM_FCT_PARAM + 8]);
+		iowrite16((priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES) ? 1 : 0,
+				&card->dpram[DPRAM_FCT_PARAM + 10]);
+		ret = softing_fct_cmd(card, 2, "initialize_chip[1]");
+		if (ret < 0)
+			goto failed;
+		/* set mode2 */
+		iowrite16(0, &card->dpram[DPRAM_FCT_PARAM + 2]);
+		iowrite16(0, &card->dpram[DPRAM_FCT_PARAM + 4]);
+		ret = softing_fct_cmd(card, 4, "set_mode[1]");
+		if (ret < 0)
+			goto failed;
+		/* set filter2 */
+		/* 11bit id & mask */
+		iowrite16(0x0000, &card->dpram[DPRAM_FCT_PARAM + 2]);
+		iowrite16(0x07ff, &card->dpram[DPRAM_FCT_PARAM + 4]);
+		/* 29bit id.lo & mask.lo & id.hi & mask.hi */
+		iowrite16(0x0000, &card->dpram[DPRAM_FCT_PARAM + 6]);
+		iowrite16(0xffff, &card->dpram[DPRAM_FCT_PARAM + 8]);
+		iowrite16(0x0000, &card->dpram[DPRAM_FCT_PARAM + 10]);
+		iowrite16(0x1fff, &card->dpram[DPRAM_FCT_PARAM + 12]);
+		ret = softing_fct_cmd(card, 8, "set_filter[1]");
+		if (ret < 0)
+			goto failed;
+		/* set output control2 */
+		iowrite16(priv->output, &card->dpram[DPRAM_FCT_PARAM + 2]);
+		ret = softing_fct_cmd(card, 6, "set_output[1]");
+		if (ret < 0)
+			goto failed;
+	}
+	/* enable_error_frame */
+	/*
+	 * Error reporting is switched off at the moment since
+	 * the receiving of them is not yet 100% verified
+	 * This should be enabled sooner or later
+	 *
+	if (error_reporting) {
+		ret = softing_fct_cmd(card, 51, "enable_error_frame");
+		if (ret < 0)
+			goto failed;
+	}
+	*/
+	/* initialize interface */
+	iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 2]);
+	iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 4]);
+	iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 6]);
+	iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 8]);
+	iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 10]);
+	iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 12]);
+	iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 14]);
+	iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 16]);
+	iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 18]);
+	iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 20]);
+	ret = softing_fct_cmd(card, 17, "initialize_interface");
+	if (ret < 0)
+		goto failed;
+	/* enable_fifo */
+	ret = softing_fct_cmd(card, 36, "enable_fifo");
+	if (ret < 0)
+		goto failed;
+	/* enable fifo tx ack */
+	ret = softing_fct_cmd(card, 13, "fifo_tx_ack[0]");
+	if (ret < 0)
+		goto failed;
+	/* enable fifo tx ack2 */
+	ret = softing_fct_cmd(card, 14, "fifo_tx_ack[1]");
+	if (ret < 0)
+		goto failed;
+	/* start_chip */
+	ret = softing_fct_cmd(card, 11, "start_chip");
+	if (ret < 0)
+		goto failed;
+	iowrite8(0, &card->dpram[DPRAM_INFO_BUSSTATE]);
+	iowrite8(0, &card->dpram[DPRAM_INFO_BUSSTATE2]);
+	if (card->pdat->generation < 2) {
+		iowrite8(0, &card->dpram[DPRAM_V2_IRQ_TOHOST]);
+		/* flush the DPRAM caches */
+		wmb();
+	}
+
+	softing_initialize_timestamp(card);
+
+	/*
+	 * do socketcan notifications/status changes
+	 * from here, no errors should occur, or the failed: part
+	 * must be reviewed
+	 */
+	memset(&msg, 0, sizeof(msg));
+	msg.can_id = CAN_ERR_FLAG | CAN_ERR_RESTARTED;
+	msg.can_dlc = CAN_ERR_DLC;
+	for (j = 0; j < ARRAY_SIZE(card->net); ++j) {
+		if (!(bus_bitmask_start & (1 << j)))
+			continue;
+		netdev = card->net[j];
+		if (!netdev)
+			continue;
+		priv = netdev_priv(netdev);
+		priv->can.state = CAN_STATE_ERROR_ACTIVE;
+		open_candev(netdev);
+		if (dev != netdev) {
+			/* notify other busses on the restart */
+			softing_netdev_rx(netdev, &msg, ktime_set(0, 0));
+			++priv->can.can_stats.restarts;
+		}
+		netif_wake_queue(netdev);
+	}
+
+	/* enable interrupts */
+	ret = softing_enable_irq(card, 1);
+	if (ret)
+		goto failed;
+card_done:
+	mutex_unlock(&card->fw.lock);
+	return 0;
+invalid:
+	ret = -EINVAL;
+failed:
+	softing_enable_irq(card, 0);
+	softing_reset_chip(card);
+	mutex_unlock(&card->fw.lock);
+	/* bring all other interfaces down */
+	for (j = 0; j < ARRAY_SIZE(card->net); ++j) {
+		netdev = card->net[j];
+		if (!netdev)
+			continue;
+		dev_close(netdev);
+	}
+	return ret;
+}
+
+int softing_default_output(struct net_device *netdev)
+{
+	struct softing_priv *priv = netdev_priv(netdev);
+	struct softing *card = priv->card;
+
+	switch (priv->chip) {
+	case 1000:
+		return (card->pdat->generation < 2) ? 0xfb : 0xfa;
+	case 5:
+		return 0x60;
+	default:
+		return 0x40;
+	}
+}
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/can/softing/softing.h linux-libre-2.6.38-gnu1/drivers/net/can/softing/softing.h
--- linux-libre-2.6.37-gnu1/drivers/net/can/softing/softing.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/can/softing/softing.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,167 @@
+/*
+ * softing common interfaces
+ *
+ * by Kurt Van Dijck, 2008-2010
+ */
+
+#include <linux/atomic.h>
+#include <linux/netdevice.h>
+#include <linux/ktime.h>
+#include <linux/mutex.h>
+#include <linux/spinlock.h>
+#include <linux/can.h>
+#include <linux/can/dev.h>
+
+#include "softing_platform.h"
+
+struct softing;
+
+struct softing_priv {
+	struct can_priv can; /* must be the first member! */
+	struct net_device *netdev;
+	struct softing *card;
+	struct {
+		int pending;
+		/* variables wich hold the circular buffer */
+		int echo_put;
+		int echo_get;
+	} tx;
+	struct can_bittiming_const btr_const;
+	int index;
+	uint8_t output;
+	uint16_t chip;
+};
+#define netdev2softing(netdev)	((struct softing_priv *)netdev_priv(netdev))
+
+struct softing {
+	const struct softing_platform_data *pdat;
+	struct platform_device *pdev;
+	struct net_device *net[2];
+	spinlock_t spin; /* protect this structure & DPRAM access */
+	ktime_t ts_ref;
+	ktime_t ts_overflow; /* timestamp overflow value, in ktime */
+
+	struct {
+		/* indication of firmware status */
+		int up;
+		/* protection of the 'up' variable */
+		struct mutex lock;
+	} fw;
+	struct {
+		int nr;
+		int requested;
+		int svc_count;
+		unsigned int dpram_position;
+	} irq;
+	struct {
+		int pending;
+		int last_bus;
+		/*
+		 * keep the bus that last tx'd a message,
+		 * in order to let every netdev queue resume
+		 */
+	} tx;
+	__iomem uint8_t *dpram;
+	unsigned long dpram_phys;
+	unsigned long dpram_size;
+	struct {
+		uint16_t fw_version, hw_version, license, serial;
+		uint16_t chip[2];
+		unsigned int freq; /* remote cpu's operating frequency */
+	} id;
+};
+
+extern int softing_default_output(struct net_device *netdev);
+
+extern ktime_t softing_raw2ktime(struct softing *card, u32 raw);
+
+extern int softing_chip_poweron(struct softing *card);
+
+extern int softing_bootloader_command(struct softing *card, int16_t cmd,
+		const char *msg);
+
+/* Load firmware after reset */
+extern int softing_load_fw(const char *file, struct softing *card,
+			__iomem uint8_t *virt, unsigned int size, int offset);
+
+/* Load final application firmware after bootloader */
+extern int softing_load_app_fw(const char *file, struct softing *card);
+
+/*
+ * enable or disable irq
+ * only called with fw.lock locked
+ */
+extern int softing_enable_irq(struct softing *card, int enable);
+
+/* start/stop 1 bus on card */
+extern int softing_startstop(struct net_device *netdev, int up);
+
+/* netif_rx() */
+extern int softing_netdev_rx(struct net_device *netdev,
+		const struct can_frame *msg, ktime_t ktime);
+
+/* SOFTING DPRAM mappings */
+#define DPRAM_RX		0x0000
+	#define DPRAM_RX_SIZE	32
+	#define DPRAM_RX_CNT	16
+#define DPRAM_RX_RD		0x0201	/* uint8_t */
+#define DPRAM_RX_WR		0x0205	/* uint8_t */
+#define DPRAM_RX_LOST		0x0207	/* uint8_t */
+
+#define DPRAM_FCT_PARAM		0x0300	/* int16_t [20] */
+#define DPRAM_FCT_RESULT	0x0328	/* int16_t */
+#define DPRAM_FCT_HOST		0x032b	/* uint16_t */
+
+#define DPRAM_INFO_BUSSTATE	0x0331	/* uint16_t */
+#define DPRAM_INFO_BUSSTATE2	0x0335	/* uint16_t */
+#define DPRAM_INFO_ERRSTATE	0x0339	/* uint16_t */
+#define DPRAM_INFO_ERRSTATE2	0x033d	/* uint16_t */
+#define DPRAM_RESET		0x0341	/* uint16_t */
+#define DPRAM_CLR_RECV_FIFO	0x0345	/* uint16_t */
+#define DPRAM_RESET_TIME	0x034d	/* uint16_t */
+#define DPRAM_TIME		0x0350	/* uint64_t */
+#define DPRAM_WR_START		0x0358	/* uint8_t */
+#define DPRAM_WR_END		0x0359	/* uint8_t */
+#define DPRAM_RESET_RX_FIFO	0x0361	/* uint16_t */
+#define DPRAM_RESET_TX_FIFO	0x0364	/* uint8_t */
+#define DPRAM_READ_FIFO_LEVEL	0x0365	/* uint8_t */
+#define DPRAM_RX_FIFO_LEVEL	0x0366	/* uint16_t */
+#define DPRAM_TX_FIFO_LEVEL	0x0366	/* uint16_t */
+
+#define DPRAM_TX		0x0400	/* uint16_t */
+	#define DPRAM_TX_SIZE	16
+	#define DPRAM_TX_CNT	32
+#define DPRAM_TX_RD		0x0601	/* uint8_t */
+#define DPRAM_TX_WR		0x0605	/* uint8_t */
+
+#define DPRAM_COMMAND		0x07e0	/* uint16_t */
+#define DPRAM_RECEIPT		0x07f0	/* uint16_t */
+#define DPRAM_IRQ_TOHOST	0x07fe	/* uint8_t */
+#define DPRAM_IRQ_TOCARD	0x07ff	/* uint8_t */
+
+#define DPRAM_V2_RESET		0x0e00	/* uint8_t */
+#define DPRAM_V2_IRQ_TOHOST	0x0e02	/* uint8_t */
+
+#define TXMAX	(DPRAM_TX_CNT - 1)
+
+/* DPRAM return codes */
+#define RES_NONE	0
+#define RES_OK		1
+#define RES_NOK		2
+#define RES_UNKNOWN	3
+/* DPRAM flags */
+#define CMD_TX		0x01
+#define CMD_ACK		0x02
+#define CMD_XTD		0x04
+#define CMD_RTR		0x08
+#define CMD_ERR		0x10
+#define CMD_BUS2	0x80
+
+/* returned fifo entry bus state masks */
+#define SF_MASK_BUSOFF		0x80
+#define SF_MASK_EPASSIVE	0x60
+
+/* bus states */
+#define STATE_BUSOFF	2
+#define STATE_EPASSIVE	1
+#define STATE_EACTIVE	0
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/can/softing/softing_main.c linux-libre-2.6.38-gnu1/drivers/net/can/softing/softing_main.c
--- linux-libre-2.6.37-gnu1/drivers/net/can/softing/softing_main.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/can/softing/softing_main.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,894 @@
+/*
+ * Copyright (C) 2008-2010
+ *
+ * - Kurt Van Dijck, EIA Electronics
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the version 2 of the GNU General Public License
+ * 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/version.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+
+#include "softing.h"
+
+#define TX_ECHO_SKB_MAX (((TXMAX+1)/2)-1)
+
+/*
+ * test is a specific CAN netdev
+ * is online (ie. up 'n running, not sleeping, not busoff
+ */
+static inline int canif_is_active(struct net_device *netdev)
+{
+	struct can_priv *can = netdev_priv(netdev);
+
+	if (!netif_running(netdev))
+		return 0;
+	return (can->state <= CAN_STATE_ERROR_PASSIVE);
+}
+
+/* reset DPRAM */
+static inline void softing_set_reset_dpram(struct softing *card)
+{
+	if (card->pdat->generation >= 2) {
+		spin_lock_bh(&card->spin);
+		iowrite8(ioread8(&card->dpram[DPRAM_V2_RESET]) & ~1,
+				&card->dpram[DPRAM_V2_RESET]);
+		spin_unlock_bh(&card->spin);
+	}
+}
+
+static inline void softing_clr_reset_dpram(struct softing *card)
+{
+	if (card->pdat->generation >= 2) {
+		spin_lock_bh(&card->spin);
+		iowrite8(ioread8(&card->dpram[DPRAM_V2_RESET]) | 1,
+				&card->dpram[DPRAM_V2_RESET]);
+		spin_unlock_bh(&card->spin);
+	}
+}
+
+/* trigger the tx queue-ing */
+static netdev_tx_t softing_netdev_start_xmit(struct sk_buff *skb,
+		struct net_device *dev)
+{
+	struct softing_priv *priv = netdev_priv(dev);
+	struct softing *card = priv->card;
+	int ret;
+	uint8_t *ptr;
+	uint8_t fifo_wr, fifo_rd;
+	struct can_frame *cf = (struct can_frame *)skb->data;
+	uint8_t buf[DPRAM_TX_SIZE];
+
+	if (can_dropped_invalid_skb(dev, skb))
+		return NETDEV_TX_OK;
+
+	spin_lock(&card->spin);
+
+	ret = NETDEV_TX_BUSY;
+	if (!card->fw.up ||
+			(card->tx.pending >= TXMAX) ||
+			(priv->tx.pending >= TX_ECHO_SKB_MAX))
+		goto xmit_done;
+	fifo_wr = ioread8(&card->dpram[DPRAM_TX_WR]);
+	fifo_rd = ioread8(&card->dpram[DPRAM_TX_RD]);
+	if (fifo_wr == fifo_rd)
+		/* fifo full */
+		goto xmit_done;
+	memset(buf, 0, sizeof(buf));
+	ptr = buf;
+	*ptr = CMD_TX;
+	if (cf->can_id & CAN_RTR_FLAG)
+		*ptr |= CMD_RTR;
+	if (cf->can_id & CAN_EFF_FLAG)
+		*ptr |= CMD_XTD;
+	if (priv->index)
+		*ptr |= CMD_BUS2;
+	++ptr;
+	*ptr++ = cf->can_dlc;
+	*ptr++ = (cf->can_id >> 0);
+	*ptr++ = (cf->can_id >> 8);
+	if (cf->can_id & CAN_EFF_FLAG) {
+		*ptr++ = (cf->can_id >> 16);
+		*ptr++ = (cf->can_id >> 24);
+	} else {
+		/* increment 1, not 2 as you might think */
+		ptr += 1;
+	}
+	if (!(cf->can_id & CAN_RTR_FLAG))
+		memcpy(ptr, &cf->data[0], cf->can_dlc);
+	memcpy_toio(&card->dpram[DPRAM_TX + DPRAM_TX_SIZE * fifo_wr],
+			buf, DPRAM_TX_SIZE);
+	if (++fifo_wr >= DPRAM_TX_CNT)
+		fifo_wr = 0;
+	iowrite8(fifo_wr, &card->dpram[DPRAM_TX_WR]);
+	card->tx.last_bus = priv->index;
+	++card->tx.pending;
+	++priv->tx.pending;
+	can_put_echo_skb(skb, dev, priv->tx.echo_put);
+	++priv->tx.echo_put;
+	if (priv->tx.echo_put >= TX_ECHO_SKB_MAX)
+		priv->tx.echo_put = 0;
+	/* can_put_echo_skb() saves the skb, safe to return TX_OK */
+	ret = NETDEV_TX_OK;
+xmit_done:
+	spin_unlock(&card->spin);
+	if (card->tx.pending >= TXMAX) {
+		int j;
+		for (j = 0; j < ARRAY_SIZE(card->net); ++j) {
+			if (card->net[j])
+				netif_stop_queue(card->net[j]);
+		}
+	}
+	if (ret != NETDEV_TX_OK)
+		netif_stop_queue(dev);
+
+	return ret;
+}
+
+/*
+ * shortcut for skb delivery
+ */
+int softing_netdev_rx(struct net_device *netdev, const struct can_frame *msg,
+		ktime_t ktime)
+{
+	struct sk_buff *skb;
+	struct can_frame *cf;
+
+	skb = alloc_can_skb(netdev, &cf);
+	if (!skb)
+		return -ENOMEM;
+	memcpy(cf, msg, sizeof(*msg));
+	skb->tstamp = ktime;
+	return netif_rx(skb);
+}
+
+/*
+ * softing_handle_1
+ * pop 1 entry from the DPRAM queue, and process
+ */
+static int softing_handle_1(struct softing *card)
+{
+	struct net_device *netdev;
+	struct softing_priv *priv;
+	ktime_t ktime;
+	struct can_frame msg;
+	int cnt = 0, lost_msg;
+	uint8_t fifo_rd, fifo_wr, cmd;
+	uint8_t *ptr;
+	uint32_t tmp_u32;
+	uint8_t buf[DPRAM_RX_SIZE];
+
+	memset(&msg, 0, sizeof(msg));
+	/* test for lost msgs */
+	lost_msg = ioread8(&card->dpram[DPRAM_RX_LOST]);
+	if (lost_msg) {
+		int j;
+		/* reset condition */
+		iowrite8(0, &card->dpram[DPRAM_RX_LOST]);
+		/* prepare msg */
+		msg.can_id = CAN_ERR_FLAG | CAN_ERR_CRTL;
+		msg.can_dlc = CAN_ERR_DLC;
+		msg.data[1] = CAN_ERR_CRTL_RX_OVERFLOW;
+		/*
+		 * service to all busses, we don't know which it was applicable
+		 * but only service busses that are online
+		 */
+		for (j = 0; j < ARRAY_SIZE(card->net); ++j) {
+			netdev = card->net[j];
+			if (!netdev)
+				continue;
+			if (!canif_is_active(netdev))
+				/* a dead bus has no overflows */
+				continue;
+			++netdev->stats.rx_over_errors;
+			softing_netdev_rx(netdev, &msg, ktime_set(0, 0));
+		}
+		/* prepare for other use */
+		memset(&msg, 0, sizeof(msg));
+		++cnt;
+	}
+
+	fifo_rd = ioread8(&card->dpram[DPRAM_RX_RD]);
+	fifo_wr = ioread8(&card->dpram[DPRAM_RX_WR]);
+
+	if (++fifo_rd >= DPRAM_RX_CNT)
+		fifo_rd = 0;
+	if (fifo_wr == fifo_rd)
+		return cnt;
+
+	memcpy_fromio(buf, &card->dpram[DPRAM_RX + DPRAM_RX_SIZE*fifo_rd],
+			DPRAM_RX_SIZE);
+	mb();
+	/* trigger dual port RAM */
+	iowrite8(fifo_rd, &card->dpram[DPRAM_RX_RD]);
+
+	ptr = buf;
+	cmd = *ptr++;
+	if (cmd == 0xff)
+		/* not quite usefull, probably the card has got out */
+		return 0;
+	netdev = card->net[0];
+	if (cmd & CMD_BUS2)
+		netdev = card->net[1];
+	priv = netdev_priv(netdev);
+
+	if (cmd & CMD_ERR) {
+		uint8_t can_state, state;
+
+		state = *ptr++;
+
+		msg.can_id = CAN_ERR_FLAG;
+		msg.can_dlc = CAN_ERR_DLC;
+
+		if (state & SF_MASK_BUSOFF) {
+			can_state = CAN_STATE_BUS_OFF;
+			msg.can_id |= CAN_ERR_BUSOFF;
+			state = STATE_BUSOFF;
+		} else if (state & SF_MASK_EPASSIVE) {
+			can_state = CAN_STATE_ERROR_PASSIVE;
+			msg.can_id |= CAN_ERR_CRTL;
+			msg.data[1] = CAN_ERR_CRTL_TX_PASSIVE;
+			state = STATE_EPASSIVE;
+		} else {
+			can_state = CAN_STATE_ERROR_ACTIVE;
+			msg.can_id |= CAN_ERR_CRTL;
+			state = STATE_EACTIVE;
+		}
+		/* update DPRAM */
+		iowrite8(state, &card->dpram[priv->index ?
+				DPRAM_INFO_BUSSTATE2 : DPRAM_INFO_BUSSTATE]);
+		/* timestamp */
+		tmp_u32 = le32_to_cpup((void *)ptr);
+		ptr += 4;
+		ktime = softing_raw2ktime(card, tmp_u32);
+
+		++netdev->stats.rx_errors;
+		/* update internal status */
+		if (can_state != priv->can.state) {
+			priv->can.state = can_state;
+			if (can_state == CAN_STATE_ERROR_PASSIVE)
+				++priv->can.can_stats.error_passive;
+			else if (can_state == CAN_STATE_BUS_OFF) {
+				/* this calls can_close_cleanup() */
+				can_bus_off(netdev);
+				netif_stop_queue(netdev);
+			}
+			/* trigger socketcan */
+			softing_netdev_rx(netdev, &msg, ktime);
+		}
+
+	} else {
+		if (cmd & CMD_RTR)
+			msg.can_id |= CAN_RTR_FLAG;
+		msg.can_dlc = get_can_dlc(*ptr++);
+		if (cmd & CMD_XTD) {
+			msg.can_id |= CAN_EFF_FLAG;
+			msg.can_id |= le32_to_cpup((void *)ptr);
+			ptr += 4;
+		} else {
+			msg.can_id |= le16_to_cpup((void *)ptr);
+			ptr += 2;
+		}
+		/* timestamp */
+		tmp_u32 = le32_to_cpup((void *)ptr);
+		ptr += 4;
+		ktime = softing_raw2ktime(card, tmp_u32);
+		if (!(msg.can_id & CAN_RTR_FLAG))
+			memcpy(&msg.data[0], ptr, 8);
+		ptr += 8;
+		/* update socket */
+		if (cmd & CMD_ACK) {
+			/* acknowledge, was tx msg */
+			struct sk_buff *skb;
+			skb = priv->can.echo_skb[priv->tx.echo_get];
+			if (skb)
+				skb->tstamp = ktime;
+			can_get_echo_skb(netdev, priv->tx.echo_get);
+			++priv->tx.echo_get;
+			if (priv->tx.echo_get >= TX_ECHO_SKB_MAX)
+				priv->tx.echo_get = 0;
+			if (priv->tx.pending)
+				--priv->tx.pending;
+			if (card->tx.pending)
+				--card->tx.pending;
+			++netdev->stats.tx_packets;
+			if (!(msg.can_id & CAN_RTR_FLAG))
+				netdev->stats.tx_bytes += msg.can_dlc;
+		} else {
+			int ret;
+
+			ret = softing_netdev_rx(netdev, &msg, ktime);
+			if (ret == NET_RX_SUCCESS) {
+				++netdev->stats.rx_packets;
+				if (!(msg.can_id & CAN_RTR_FLAG))
+					netdev->stats.rx_bytes += msg.can_dlc;
+			} else {
+				++netdev->stats.rx_dropped;
+			}
+		}
+	}
+	++cnt;
+	return cnt;
+}
+
+/*
+ * real interrupt handler
+ */
+static irqreturn_t softing_irq_thread(int irq, void *dev_id)
+{
+	struct softing *card = (struct softing *)dev_id;
+	struct net_device *netdev;
+	struct softing_priv *priv;
+	int j, offset, work_done;
+
+	work_done = 0;
+	spin_lock_bh(&card->spin);
+	while (softing_handle_1(card) > 0) {
+		++card->irq.svc_count;
+		++work_done;
+	}
+	spin_unlock_bh(&card->spin);
+	/* resume tx queue's */
+	offset = card->tx.last_bus;
+	for (j = 0; j < ARRAY_SIZE(card->net); ++j) {
+		if (card->tx.pending >= TXMAX)
+			break;
+		netdev = card->net[(j + offset + 1) % card->pdat->nbus];
+		if (!netdev)
+			continue;
+		priv = netdev_priv(netdev);
+		if (!canif_is_active(netdev))
+			/* it makes no sense to wake dead busses */
+			continue;
+		if (priv->tx.pending >= TX_ECHO_SKB_MAX)
+			continue;
+		++work_done;
+		netif_wake_queue(netdev);
+	}
+	return work_done ? IRQ_HANDLED : IRQ_NONE;
+}
+
+/*
+ * interrupt routines:
+ * schedule the 'real interrupt handler'
+ */
+static irqreturn_t softing_irq_v2(int irq, void *dev_id)
+{
+	struct softing *card = (struct softing *)dev_id;
+	uint8_t ir;
+
+	ir = ioread8(&card->dpram[DPRAM_V2_IRQ_TOHOST]);
+	iowrite8(0, &card->dpram[DPRAM_V2_IRQ_TOHOST]);
+	return (1 == ir) ? IRQ_WAKE_THREAD : IRQ_NONE;
+}
+
+static irqreturn_t softing_irq_v1(int irq, void *dev_id)
+{
+	struct softing *card = (struct softing *)dev_id;
+	uint8_t ir;
+
+	ir = ioread8(&card->dpram[DPRAM_IRQ_TOHOST]);
+	iowrite8(0, &card->dpram[DPRAM_IRQ_TOHOST]);
+	return ir ? IRQ_WAKE_THREAD : IRQ_NONE;
+}
+
+/*
+ * netdev/candev inter-operability
+ */
+static int softing_netdev_open(struct net_device *ndev)
+{
+	int ret;
+
+	/* check or determine and set bittime */
+	ret = open_candev(ndev);
+	if (!ret)
+		ret = softing_startstop(ndev, 1);
+	return ret;
+}
+
+static int softing_netdev_stop(struct net_device *ndev)
+{
+	int ret;
+
+	netif_stop_queue(ndev);
+
+	/* softing cycle does close_candev() */
+	ret = softing_startstop(ndev, 0);
+	return ret;
+}
+
+static int softing_candev_set_mode(struct net_device *ndev, enum can_mode mode)
+{
+	int ret;
+
+	switch (mode) {
+	case CAN_MODE_START:
+		/* softing_startstop does close_candev() */
+		ret = softing_startstop(ndev, 1);
+		return ret;
+	case CAN_MODE_STOP:
+	case CAN_MODE_SLEEP:
+		return -EOPNOTSUPP;
+	}
+	return 0;
+}
+
+/*
+ * Softing device management helpers
+ */
+int softing_enable_irq(struct softing *card, int enable)
+{
+	int ret;
+
+	if (!card->irq.nr) {
+		return 0;
+	} else if (card->irq.requested && !enable) {
+		free_irq(card->irq.nr, card);
+		card->irq.requested = 0;
+	} else if (!card->irq.requested && enable) {
+		ret = request_threaded_irq(card->irq.nr,
+				(card->pdat->generation >= 2) ?
+					softing_irq_v2 : softing_irq_v1,
+				softing_irq_thread, IRQF_SHARED,
+				dev_name(&card->pdev->dev), card);
+		if (ret) {
+			dev_alert(&card->pdev->dev,
+					"request_threaded_irq(%u) failed\n",
+					card->irq.nr);
+			return ret;
+		}
+		card->irq.requested = 1;
+	}
+	return 0;
+}
+
+static void softing_card_shutdown(struct softing *card)
+{
+	int fw_up = 0;
+
+	if (mutex_lock_interruptible(&card->fw.lock))
+		/* return -ERESTARTSYS */;
+	fw_up = card->fw.up;
+	card->fw.up = 0;
+
+	if (card->irq.requested && card->irq.nr) {
+		free_irq(card->irq.nr, card);
+		card->irq.requested = 0;
+	}
+	if (fw_up) {
+		if (card->pdat->enable_irq)
+			card->pdat->enable_irq(card->pdev, 0);
+		softing_set_reset_dpram(card);
+		if (card->pdat->reset)
+			card->pdat->reset(card->pdev, 1);
+	}
+	mutex_unlock(&card->fw.lock);
+}
+
+static __devinit int softing_card_boot(struct softing *card)
+{
+	int ret, j;
+	static const uint8_t stream[] = {
+		0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, };
+	unsigned char back[sizeof(stream)];
+
+	if (mutex_lock_interruptible(&card->fw.lock))
+		return -ERESTARTSYS;
+	if (card->fw.up) {
+		mutex_unlock(&card->fw.lock);
+		return 0;
+	}
+	/* reset board */
+	if (card->pdat->enable_irq)
+		card->pdat->enable_irq(card->pdev, 1);
+	/* boot card */
+	softing_set_reset_dpram(card);
+	if (card->pdat->reset)
+		card->pdat->reset(card->pdev, 1);
+	for (j = 0; (j + sizeof(stream)) < card->dpram_size;
+			j += sizeof(stream)) {
+
+		memcpy_toio(&card->dpram[j], stream, sizeof(stream));
+		/* flush IO cache */
+		mb();
+		memcpy_fromio(back, &card->dpram[j], sizeof(stream));
+
+		if (!memcmp(back, stream, sizeof(stream)))
+			continue;
+		/* memory is not equal */
+		dev_alert(&card->pdev->dev, "dpram failed at 0x%04x\n", j);
+		ret = -EIO;
+		goto failed;
+	}
+	wmb();
+	/* load boot firmware */
+	ret = softing_load_fw(card->pdat->boot.fw, card, card->dpram,
+				card->dpram_size,
+				card->pdat->boot.offs - card->pdat->boot.addr);
+	if (ret < 0)
+		goto failed;
+	/* load loader firmware */
+	ret = softing_load_fw(card->pdat->load.fw, card, card->dpram,
+				card->dpram_size,
+				card->pdat->load.offs - card->pdat->load.addr);
+	if (ret < 0)
+		goto failed;
+
+	if (card->pdat->reset)
+		card->pdat->reset(card->pdev, 0);
+	softing_clr_reset_dpram(card);
+	ret = softing_bootloader_command(card, 0, "card boot");
+	if (ret < 0)
+		goto failed;
+	ret = softing_load_app_fw(card->pdat->app.fw, card);
+	if (ret < 0)
+		goto failed;
+
+	ret = softing_chip_poweron(card);
+	if (ret < 0)
+		goto failed;
+
+	card->fw.up = 1;
+	mutex_unlock(&card->fw.lock);
+	return 0;
+failed:
+	card->fw.up = 0;
+	if (card->pdat->enable_irq)
+		card->pdat->enable_irq(card->pdev, 0);
+	softing_set_reset_dpram(card);
+	if (card->pdat->reset)
+		card->pdat->reset(card->pdev, 1);
+	mutex_unlock(&card->fw.lock);
+	return ret;
+}
+
+/*
+ * netdev sysfs
+ */
+static ssize_t show_channel(struct device *dev, struct device_attribute *attr,
+		char *buf)
+{
+	struct net_device *ndev = to_net_dev(dev);
+	struct softing_priv *priv = netdev2softing(ndev);
+
+	return sprintf(buf, "%i\n", priv->index);
+}
+
+static ssize_t show_chip(struct device *dev, struct device_attribute *attr,
+		char *buf)
+{
+	struct net_device *ndev = to_net_dev(dev);
+	struct softing_priv *priv = netdev2softing(ndev);
+
+	return sprintf(buf, "%i\n", priv->chip);
+}
+
+static ssize_t show_output(struct device *dev, struct device_attribute *attr,
+		char *buf)
+{
+	struct net_device *ndev = to_net_dev(dev);
+	struct softing_priv *priv = netdev2softing(ndev);
+
+	return sprintf(buf, "0x%02x\n", priv->output);
+}
+
+static ssize_t store_output(struct device *dev, struct device_attribute *attr,
+		const char *buf, size_t count)
+{
+	struct net_device *ndev = to_net_dev(dev);
+	struct softing_priv *priv = netdev2softing(ndev);
+	struct softing *card = priv->card;
+	unsigned long val;
+	int ret;
+
+	ret = strict_strtoul(buf, 0, &val);
+	if (ret < 0)
+		return ret;
+	val &= 0xFF;
+
+	ret = mutex_lock_interruptible(&card->fw.lock);
+	if (ret)
+		return -ERESTARTSYS;
+	if (netif_running(ndev)) {
+		mutex_unlock(&card->fw.lock);
+		return -EBUSY;
+	}
+	priv->output = val;
+	mutex_unlock(&card->fw.lock);
+	return count;
+}
+
+static const DEVICE_ATTR(channel, S_IRUGO, show_channel, NULL);
+static const DEVICE_ATTR(chip, S_IRUGO, show_chip, NULL);
+static const DEVICE_ATTR(output, S_IRUGO | S_IWUSR, show_output, store_output);
+
+static const struct attribute *const netdev_sysfs_attrs[] = {
+	&dev_attr_channel.attr,
+	&dev_attr_chip.attr,
+	&dev_attr_output.attr,
+	NULL,
+};
+static const struct attribute_group netdev_sysfs_group = {
+	.name = NULL,
+	.attrs = (struct attribute **)netdev_sysfs_attrs,
+};
+
+static const struct net_device_ops softing_netdev_ops = {
+	.ndo_open = softing_netdev_open,
+	.ndo_stop = softing_netdev_stop,
+	.ndo_start_xmit	= softing_netdev_start_xmit,
+};
+
+static const struct can_bittiming_const softing_btr_const = {
+	.name = "softing",
+	.tseg1_min = 1,
+	.tseg1_max = 16,
+	.tseg2_min = 1,
+	.tseg2_max = 8,
+	.sjw_max = 4, /* overruled */
+	.brp_min = 1,
+	.brp_max = 32, /* overruled */
+	.brp_inc = 1,
+};
+
+
+static __devinit struct net_device *softing_netdev_create(struct softing *card,
+		uint16_t chip_id)
+{
+	struct net_device *netdev;
+	struct softing_priv *priv;
+
+	netdev = alloc_candev(sizeof(*priv), TX_ECHO_SKB_MAX);
+	if (!netdev) {
+		dev_alert(&card->pdev->dev, "alloc_candev failed\n");
+		return NULL;
+	}
+	priv = netdev_priv(netdev);
+	priv->netdev = netdev;
+	priv->card = card;
+	memcpy(&priv->btr_const, &softing_btr_const, sizeof(priv->btr_const));
+	priv->btr_const.brp_max = card->pdat->max_brp;
+	priv->btr_const.sjw_max = card->pdat->max_sjw;
+	priv->can.bittiming_const = &priv->btr_const;
+	priv->can.clock.freq = 8000000;
+	priv->chip = chip_id;
+	priv->output = softing_default_output(netdev);
+	SET_NETDEV_DEV(netdev, &card->pdev->dev);
+
+	netdev->flags |= IFF_ECHO;
+	netdev->netdev_ops = &softing_netdev_ops;
+	priv->can.do_set_mode = softing_candev_set_mode;
+	priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES;
+
+	return netdev;
+}
+
+static __devinit int softing_netdev_register(struct net_device *netdev)
+{
+	int ret;
+
+	netdev->sysfs_groups[0] = &netdev_sysfs_group;
+	ret = register_candev(netdev);
+	if (ret) {
+		dev_alert(&netdev->dev, "register failed\n");
+		return ret;
+	}
+	return 0;
+}
+
+static void softing_netdev_cleanup(struct net_device *netdev)
+{
+	unregister_candev(netdev);
+	free_candev(netdev);
+}
+
+/*
+ * sysfs for Platform device
+ */
+#define DEV_ATTR_RO(name, member) \
+static ssize_t show_##name(struct device *dev, \
+		struct device_attribute *attr, char *buf) \
+{ \
+	struct softing *card = platform_get_drvdata(to_platform_device(dev)); \
+	return sprintf(buf, "%u\n", card->member); \
+} \
+static DEVICE_ATTR(name, 0444, show_##name, NULL)
+
+#define DEV_ATTR_RO_STR(name, member) \
+static ssize_t show_##name(struct device *dev, \
+		struct device_attribute *attr, char *buf) \
+{ \
+	struct softing *card = platform_get_drvdata(to_platform_device(dev)); \
+	return sprintf(buf, "%s\n", card->member); \
+} \
+static DEVICE_ATTR(name, 0444, show_##name, NULL)
+
+DEV_ATTR_RO(serial, id.serial);
+DEV_ATTR_RO_STR(firmware, pdat->app.fw);
+DEV_ATTR_RO(firmware_version, id.fw_version);
+DEV_ATTR_RO_STR(hardware, pdat->name);
+DEV_ATTR_RO(hardware_version, id.hw_version);
+DEV_ATTR_RO(license, id.license);
+DEV_ATTR_RO(frequency, id.freq);
+DEV_ATTR_RO(txpending, tx.pending);
+
+static struct attribute *softing_pdev_attrs[] = {
+	&dev_attr_serial.attr,
+	&dev_attr_firmware.attr,
+	&dev_attr_firmware_version.attr,
+	&dev_attr_hardware.attr,
+	&dev_attr_hardware_version.attr,
+	&dev_attr_license.attr,
+	&dev_attr_frequency.attr,
+	&dev_attr_txpending.attr,
+	NULL,
+};
+
+static const struct attribute_group softing_pdev_group = {
+	.name = NULL,
+	.attrs = softing_pdev_attrs,
+};
+
+/*
+ * platform driver
+ */
+static __devexit int softing_pdev_remove(struct platform_device *pdev)
+{
+	struct softing *card = platform_get_drvdata(pdev);
+	int j;
+
+	/* first, disable card*/
+	softing_card_shutdown(card);
+
+	for (j = 0; j < ARRAY_SIZE(card->net); ++j) {
+		if (!card->net[j])
+			continue;
+		softing_netdev_cleanup(card->net[j]);
+		card->net[j] = NULL;
+	}
+	sysfs_remove_group(&pdev->dev.kobj, &softing_pdev_group);
+
+	iounmap(card->dpram);
+	kfree(card);
+	return 0;
+}
+
+static __devinit int softing_pdev_probe(struct platform_device *pdev)
+{
+	const struct softing_platform_data *pdat = pdev->dev.platform_data;
+	struct softing *card;
+	struct net_device *netdev;
+	struct softing_priv *priv;
+	struct resource *pres;
+	int ret;
+	int j;
+
+	if (!pdat) {
+		dev_warn(&pdev->dev, "no platform data\n");
+		return -EINVAL;
+	}
+	if (pdat->nbus > ARRAY_SIZE(card->net)) {
+		dev_warn(&pdev->dev, "%u nets??\n", pdat->nbus);
+		return -EINVAL;
+	}
+
+	card = kzalloc(sizeof(*card), GFP_KERNEL);
+	if (!card)
+		return -ENOMEM;
+	card->pdat = pdat;
+	card->pdev = pdev;
+	platform_set_drvdata(pdev, card);
+	mutex_init(&card->fw.lock);
+	spin_lock_init(&card->spin);
+
+	ret = -EINVAL;
+	pres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!pres)
+		goto platform_resource_failed;;
+	card->dpram_phys = pres->start;
+	card->dpram_size = pres->end - pres->start + 1;
+	card->dpram = ioremap_nocache(card->dpram_phys, card->dpram_size);
+	if (!card->dpram) {
+		dev_alert(&card->pdev->dev, "dpram ioremap failed\n");
+		goto ioremap_failed;
+	}
+
+	pres = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (pres)
+		card->irq.nr = pres->start;
+
+	/* reset card */
+	ret = softing_card_boot(card);
+	if (ret < 0) {
+		dev_alert(&pdev->dev, "failed to boot\n");
+		goto boot_failed;
+	}
+
+	/* only now, the chip's are known */
+	card->id.freq = card->pdat->freq;
+
+	ret = sysfs_create_group(&pdev->dev.kobj, &softing_pdev_group);
+	if (ret < 0) {
+		dev_alert(&card->pdev->dev, "sysfs failed\n");
+		goto sysfs_failed;
+	}
+
+	ret = -ENOMEM;
+	for (j = 0; j < ARRAY_SIZE(card->net); ++j) {
+		card->net[j] = netdev =
+			softing_netdev_create(card, card->id.chip[j]);
+		if (!netdev) {
+			dev_alert(&pdev->dev, "failed to make can[%i]", j);
+			goto netdev_failed;
+		}
+		priv = netdev_priv(card->net[j]);
+		priv->index = j;
+		ret = softing_netdev_register(netdev);
+		if (ret) {
+			free_candev(netdev);
+			card->net[j] = NULL;
+			dev_alert(&card->pdev->dev,
+					"failed to register can[%i]\n", j);
+			goto netdev_failed;
+		}
+	}
+	dev_info(&card->pdev->dev, "%s ready.\n", card->pdat->name);
+	return 0;
+
+netdev_failed:
+	for (j = 0; j < ARRAY_SIZE(card->net); ++j) {
+		if (!card->net[j])
+			continue;
+		softing_netdev_cleanup(card->net[j]);
+	}
+	sysfs_remove_group(&pdev->dev.kobj, &softing_pdev_group);
+sysfs_failed:
+	softing_card_shutdown(card);
+boot_failed:
+	iounmap(card->dpram);
+ioremap_failed:
+platform_resource_failed:
+	kfree(card);
+	return ret;
+}
+
+static struct platform_driver softing_driver = {
+	.driver = {
+		.name = "softing",
+		.owner = THIS_MODULE,
+	},
+	.probe = softing_pdev_probe,
+	.remove = __devexit_p(softing_pdev_remove),
+};
+
+MODULE_ALIAS("platform:softing");
+
+static int __init softing_start(void)
+{
+	return platform_driver_register(&softing_driver);
+}
+
+static void __exit softing_stop(void)
+{
+	platform_driver_unregister(&softing_driver);
+}
+
+module_init(softing_start);
+module_exit(softing_stop);
+
+MODULE_DESCRIPTION("Softing DPRAM CAN driver");
+MODULE_AUTHOR("Kurt Van Dijck <kurt.van.dijck@eia.be>");
+MODULE_LICENSE("GPL v2");
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/can/softing/softing_platform.h linux-libre-2.6.38-gnu1/drivers/net/can/softing/softing_platform.h
--- linux-libre-2.6.37-gnu1/drivers/net/can/softing/softing_platform.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/can/softing/softing_platform.h	2013-05-03 02:04:15.000000000 -0400
@@ -0,0 +1,40 @@
+
+#include <linux/platform_device.h>
+
+#ifndef _SOFTING_DEVICE_H_
+#define _SOFTING_DEVICE_H_
+
+/* softing firmware directory prefix */
+#define fw_dir /*(DEBLOBBED)*/
+
+struct softing_platform_data {
+	unsigned int manf;
+	unsigned int prod;
+	/*
+	 * generation
+	 * 1st with NEC or SJA1000
+	 * 8bit, exclusive interrupt, ...
+	 * 2nd only SJA1000
+	 * 16bit, shared interrupt
+	 */
+	int generation;
+	int nbus; /* # busses on device */
+	unsigned int freq; /* operating frequency in Hz */
+	unsigned int max_brp;
+	unsigned int max_sjw;
+	unsigned long dpram_size;
+	const char *name;
+	struct {
+		unsigned long offs;
+		unsigned long addr;
+		const char *fw;
+	} boot, load, app;
+	/*
+	 * reset() function
+	 * bring pdev in or out of reset, depending on value
+	 */
+	int (*reset)(struct platform_device *pdev, int value);
+	int (*enable_irq)(struct platform_device *pdev, int value);
+};
+
+#endif
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/cassini.c linux-libre-2.6.38-gnu1/drivers/net/cassini.c
--- linux-libre-2.6.37-gnu1/drivers/net/cassini.c	2013-05-03 03:58:13.000000000 -0400
+++ linux-libre-2.6.38-gnu1/drivers/net/cassini.c	2013-05-03 01:58:18.000000000 -0400
@@ -2788,7 +2788,7 @@ static inline int cas_xmit_tx_ringN(stru
 
 	ctrl = 0;
 	if (skb->ip_summed == CHECKSUM_PARTIAL) {
-		const u64 csum_start_off = skb_transport_offset(skb);
+		const u64 csum_start_off = skb_checksum_start_offset(skb);
 		const u64 csum_stuff_off = csum_start_off + skb->csum_offset;
 
 		ctrl =  TX_DESC_CSUM_EN |
@@ -3203,6 +3203,10 @@ static int cas_get_vpd_info(struct cas *
 	int phy_type = CAS_PHY_MII_MDIO0; /* default phy type */
 	int mac_off  = 0;
 
+#if defined(CONFIG_SPARC)
+	const unsigned char *addr;
+#endif
+
 	/* give us access to the PROM */
 	writel(BIM_LOCAL_DEV_PROM | BIM_LOCAL_DEV_PAD,
 	       cp->regs + REG_BIM_LOCAL_DEV_EN);
@@ -3350,6 +3354,14 @@ use_random_mac_addr:
 	if (found & VPD_FOUND_MAC)
 		goto done;
 
+#if defined(CONFIG_SPARC)
+	addr = of_get_property(cp->of_node, "local-mac-address", NULL);
+	if (addr != NULL) {
+		memcpy(dev_addr, addr, 6);
+		goto done;
+	}
+#endif
+
 	/* Sun MAC prefix then 3 random bytes. */
 	pr_info("MAC address not found in ROM VPD\n");
 	dev_addr[0] = 0x08;
@@ -3880,7 +3892,7 @@ static int cas_change_mtu(struct net_dev
 	schedule_work(&cp->reset_task);
 #endif
 
-	flush_scheduled_work();
+	flush_work_sync(&cp->reset_task);
 	return 0;
 }
 
@@ -5019,6 +5031,10 @@ static int __devinit cas_init_one(struct
 	cp->msg_enable = (cassini_debug < 0) ? CAS_DEF_MSG_ENABLE :
 	  cassini_debug;
 
+#if defined(CONFIG_SPARC)
+	cp->of_node = pci_device_to_OF_node(pdev);
+#endif
+
 	cp->link_transition = LINK_TRANSITION_UNKNOWN;
 	cp->link_transition_jiffies_valid = 0;
 
@@ -5177,7 +5193,7 @@ static void __devexit cas_remove_one(str
 		vfree(cp->fw_data);
 
 	mutex_lock(&cp->pm_mutex);
-	flush_scheduled_work();
+	cancel_work_sync(&cp->reset_task);
 	if (cp->hw_running)
 		cas_shutdown(cp);
 	mutex_unlock(&cp->pm_mutex);
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/cassini.h linux-libre-2.6.38-gnu1/drivers/net/cassini.h
--- linux-libre-2.6.37-gnu1/drivers/net/cassini.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/cassini.h	2011-03-14 21:20:32.000000000 -0400
@@ -2868,6 +2868,9 @@ struct cas {
 	dma_addr_t block_dvma, tx_tiny_dvma[N_TX_RINGS];
 	struct pci_dev *pdev;
 	struct net_device *dev;
+#if defined(CONFIG_OF)
+	struct device_node	*of_node;
+#endif
 
 	/* Firmware Info */
 	u16			fw_load_addr;
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/chelsio/my3126.c linux-libre-2.6.38-gnu1/drivers/net/chelsio/my3126.c
--- linux-libre-2.6.37-gnu1/drivers/net/chelsio/my3126.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/chelsio/my3126.c	2011-03-14 21:20:32.000000000 -0400
@@ -22,7 +22,7 @@ static int my3126_interrupt_enable(struc
 
 static int my3126_interrupt_disable(struct cphy *cphy)
 {
-	cancel_rearming_delayed_work(&cphy->phy_update);
+	cancel_delayed_work_sync(&cphy->phy_update);
 	return 0;
 }
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/chelsio/sge.c linux-libre-2.6.38-gnu1/drivers/net/chelsio/sge.c
--- linux-libre-2.6.37-gnu1/drivers/net/chelsio/sge.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/chelsio/sge.c	2011-03-14 21:20:32.000000000 -0400
@@ -273,6 +273,10 @@ struct sge {
 	struct cmdQ cmdQ[SGE_CMDQ_N] ____cacheline_aligned_in_smp;
 };
 
+static const u8 ch_mac_addr[ETH_ALEN] = {
+	0x0, 0x7, 0x43, 0x0, 0x0, 0x0
+};
+
 /*
  * stop tasklet and free all pending skb's
  */
@@ -2012,10 +2016,6 @@ static void espibug_workaround_t204(unsi
 				continue;
 
 			if (!skb->cb[0]) {
-				u8 ch_mac_addr[ETH_ALEN] = {
-					0x0, 0x7, 0x43, 0x0, 0x0, 0x0
-				};
-
 				skb_copy_to_linear_data_offset(skb,
 						    sizeof(struct cpl_tx_pkt),
 							       ch_mac_addr,
@@ -2048,8 +2048,6 @@ static void espibug_workaround(unsigned
 
 	        if ((seop & 0xfff0fff) == 0xfff && skb) {
 	                if (!skb->cb[0]) {
-	                        u8 ch_mac_addr[ETH_ALEN] =
-	                            {0x0, 0x7, 0x43, 0x0, 0x0, 0x0};
 	                        skb_copy_to_linear_data_offset(skb,
 						     sizeof(struct cpl_tx_pkt),
 							       ch_mac_addr,
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/chelsio/subr.c linux-libre-2.6.38-gnu1/drivers/net/chelsio/subr.c
--- linux-libre-2.6.37-gnu1/drivers/net/chelsio/subr.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/chelsio/subr.c	2011-03-14 21:20:32.000000000 -0400
@@ -556,7 +556,7 @@ struct chelsio_vpd_t {
 #define EEPROM_MAX_POLL   4
 
 /*
- * Read SEEPROM. A zero is written to the flag register when the addres is
+ * Read SEEPROM. A zero is written to the flag register when the address is
  * written to the Control register. The hardware device will set the flag to a
  * one when 4B have been transferred to the Data register.
  */
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/cnic.c linux-libre-2.6.38-gnu1/drivers/net/cnic.c
--- linux-libre-2.6.37-gnu1/drivers/net/cnic.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/cnic.c	2011-03-14 21:20:32.000000000 -0400
@@ -59,6 +59,7 @@ MODULE_DESCRIPTION("Broadcom NetXtreme I
 MODULE_LICENSE("GPL");
 MODULE_VERSION(CNIC_MODULE_VERSION);
 
+/* cnic_dev_list modifications are protected by both rtnl and cnic_dev_lock */
 static LIST_HEAD(cnic_dev_list);
 static LIST_HEAD(cnic_udev_list);
 static DEFINE_RWLOCK(cnic_dev_lock);
@@ -278,6 +279,7 @@ static int cnic_send_nlmsg(struct cnic_l
 	u32 msg_type = ISCSI_KEVENT_IF_DOWN;
 	struct cnic_ulp_ops *ulp_ops;
 	struct cnic_uio_dev *udev = cp->udev;
+	int rc = 0, retry = 0;
 
 	if (!udev || udev->uio_dev == -1)
 		return -ENODEV;
@@ -302,14 +304,26 @@ static int cnic_send_nlmsg(struct cnic_l
 		path_req.pmtu = csk->mtu;
 	}
 
-	rcu_read_lock();
-	ulp_ops = rcu_dereference(cnic_ulp_tbl[CNIC_ULP_ISCSI]);
-	if (ulp_ops)
-		ulp_ops->iscsi_nl_send_msg(cp->dev, msg_type, buf, len);
-	rcu_read_unlock();
+	while (retry < 3) {
+		rc = 0;
+		rcu_read_lock();
+		ulp_ops = rcu_dereference(cnic_ulp_tbl[CNIC_ULP_ISCSI]);
+		if (ulp_ops)
+			rc = ulp_ops->iscsi_nl_send_msg(
+				cp->ulp_handle[CNIC_ULP_ISCSI],
+				msg_type, buf, len);
+		rcu_read_unlock();
+		if (rc == 0 || msg_type != ISCSI_KEVENT_PATH_REQ)
+			break;
+
+		msleep(100);
+		retry++;
+	}
 	return 0;
 }
 
+static void cnic_cm_upcall(struct cnic_local *, struct cnic_sock *, u8);
+
 static int cnic_iscsi_nl_msg_recv(struct cnic_dev *dev, u32 msg_type,
 				  char *buf, u16 len)
 {
@@ -339,7 +353,9 @@ static int cnic_iscsi_nl_msg_recv(struct
 		}
 		csk = &cp->csk_tbl[l5_cid];
 		csk_hold(csk);
-		if (cnic_in_use(csk)) {
+		if (cnic_in_use(csk) &&
+		    test_bit(SK_F_CONNECT_START, &csk->flags)) {
+
 			memcpy(csk->ha, path_resp->mac_addr, 6);
 			if (test_bit(SK_F_IPV6, &csk->flags))
 				memcpy(&csk->src_ip[0], &path_resp->src.v6_addr,
@@ -347,8 +363,16 @@ static int cnic_iscsi_nl_msg_recv(struct
 			else
 				memcpy(&csk->src_ip[0], &path_resp->src.v4_addr,
 				       sizeof(struct in_addr));
-			if (is_valid_ether_addr(csk->ha))
+
+			if (is_valid_ether_addr(csk->ha)) {
 				cnic_cm_set_pg(csk);
+			} else if (!test_bit(SK_F_OFFLD_SCHED, &csk->flags) &&
+				!test_bit(SK_F_OFFLD_COMPLETE, &csk->flags)) {
+
+				cnic_cm_upcall(cp, csk,
+					L4_KCQE_OPCODE_VALUE_CONNECT_COMPLETE);
+				clear_bit(SK_F_CONNECT_START, &csk->flags);
+			}
 		}
 		csk_put(csk);
 		rcu_read_unlock();
@@ -402,19 +426,6 @@ static int cnic_abort_prep(struct cnic_s
 	return 0;
 }
 
-static void cnic_uio_stop(void)
-{
-	struct cnic_dev *dev;
-
-	read_lock(&cnic_dev_lock);
-	list_for_each_entry(dev, &cnic_dev_list, list) {
-		struct cnic_local *cp = dev->cnic_priv;
-
-		cnic_send_nlmsg(cp, ISCSI_KEVENT_IF_DOWN, NULL);
-	}
-	read_unlock(&cnic_dev_lock);
-}
-
 int cnic_register_driver(int ulp_type, struct cnic_ulp_ops *ulp_ops)
 {
 	struct cnic_dev *dev;
@@ -445,14 +456,12 @@ int cnic_register_driver(int ulp_type, s
 
 	/* Prevent race conditions with netdev_event */
 	rtnl_lock();
-	read_lock(&cnic_dev_lock);
 	list_for_each_entry(dev, &cnic_dev_list, list) {
 		struct cnic_local *cp = dev->cnic_priv;
 
 		if (!test_and_set_bit(ULP_F_INIT, &cp->ulp_flags[ulp_type]))
 			ulp_ops->cnic_init(dev);
 	}
-	read_unlock(&cnic_dev_lock);
 	rtnl_unlock();
 
 	return 0;
@@ -488,9 +497,6 @@ int cnic_unregister_driver(int ulp_type)
 	}
 	read_unlock(&cnic_dev_lock);
 
-	if (ulp_type == CNIC_ULP_ISCSI)
-		cnic_uio_stop();
-
 	rcu_assign_pointer(cnic_ulp_tbl[ulp_type], NULL);
 
 	mutex_unlock(&cnic_lock);
@@ -574,6 +580,9 @@ static int cnic_unregister_device(struct
 	}
 	mutex_unlock(&cnic_lock);
 
+	if (ulp_type == CNIC_ULP_ISCSI)
+		cnic_send_nlmsg(cp, ISCSI_KEVENT_IF_DOWN, NULL);
+
 	synchronize_rcu();
 
 	while (test_bit(ULP_F_CALL_PENDING, &cp->ulp_flags[ulp_type]) &&
@@ -690,13 +699,13 @@ static void cnic_free_dma(struct cnic_de
 static void cnic_setup_page_tbl(struct cnic_dev *dev, struct cnic_dma *dma)
 {
 	int i;
-	u32 *page_table = dma->pgtbl;
+	__le32 *page_table = (__le32 *) dma->pgtbl;
 
 	for (i = 0; i < dma->num_pages; i++) {
 		/* Each entry needs to be in big endian format. */
-		*page_table = (u32) ((u64) dma->pg_map_arr[i] >> 32);
+		*page_table = cpu_to_le32((u64) dma->pg_map_arr[i] >> 32);
 		page_table++;
-		*page_table = (u32) dma->pg_map_arr[i];
+		*page_table = cpu_to_le32(dma->pg_map_arr[i] & 0xffffffff);
 		page_table++;
 	}
 }
@@ -704,13 +713,13 @@ static void cnic_setup_page_tbl(struct c
 static void cnic_setup_page_tbl_le(struct cnic_dev *dev, struct cnic_dma *dma)
 {
 	int i;
-	u32 *page_table = dma->pgtbl;
+	__le32 *page_table = (__le32 *) dma->pgtbl;
 
 	for (i = 0; i < dma->num_pages; i++) {
 		/* Each entry needs to be in little endian format. */
-		*page_table = dma->pg_map_arr[i] & 0xffffffff;
+		*page_table = cpu_to_le32(dma->pg_map_arr[i] & 0xffffffff);
 		page_table++;
-		*page_table = (u32) ((u64) dma->pg_map_arr[i] >> 32);
+		*page_table = cpu_to_le32((u64) dma->pg_map_arr[i] >> 32);
 		page_table++;
 	}
 }
@@ -821,12 +830,14 @@ static void cnic_free_resc(struct cnic_d
 	cnic_free_dma(dev, &cp->conn_buf_info);
 	cnic_free_dma(dev, &cp->kwq_info);
 	cnic_free_dma(dev, &cp->kwq_16_data_info);
+	cnic_free_dma(dev, &cp->kcq2.dma);
 	cnic_free_dma(dev, &cp->kcq1.dma);
 	kfree(cp->iscsi_tbl);
 	cp->iscsi_tbl = NULL;
 	kfree(cp->ctx_tbl);
 	cp->ctx_tbl = NULL;
 
+	cnic_free_id_tbl(&cp->fcoe_cid_tbl);
 	cnic_free_id_tbl(&cp->cid_tbl);
 }
 
@@ -1120,12 +1131,22 @@ static int cnic_alloc_bnx2x_resc(struct
 
 	cp->iro_arr = ethdev->iro_arr;
 
-	cp->max_cid_space = MAX_ISCSI_TBL_SZ;
+	cp->max_cid_space = MAX_ISCSI_TBL_SZ + BNX2X_FCOE_NUM_CONNECTIONS;
 	cp->iscsi_start_cid = start_cid;
+	cp->fcoe_start_cid = start_cid + MAX_ISCSI_TBL_SZ;
+
+	if (BNX2X_CHIP_IS_E2(cp->chip_id)) {
+		cp->max_cid_space += BNX2X_FCOE_NUM_CONNECTIONS;
+		cp->fcoe_init_cid = ethdev->fcoe_init_cid;
+		if (!cp->fcoe_init_cid)
+			cp->fcoe_init_cid = 0x10;
+	}
+
 	if (start_cid < BNX2X_ISCSI_START_CID) {
 		u32 delta = BNX2X_ISCSI_START_CID - start_cid;
 
 		cp->iscsi_start_cid = BNX2X_ISCSI_START_CID;
+		cp->fcoe_start_cid += delta;
 		cp->max_cid_space += delta;
 	}
 
@@ -1144,6 +1165,9 @@ static int cnic_alloc_bnx2x_resc(struct
 		cp->ctx_tbl[i].ulp_proto_id = CNIC_ULP_ISCSI;
 	}
 
+	for (i = MAX_ISCSI_TBL_SZ; i < cp->max_cid_space; i++)
+		cp->ctx_tbl[i].ulp_proto_id = CNIC_ULP_FCOE;
+
 	pages = PAGE_ALIGN(cp->max_cid_space * CNIC_KWQ16_DATA_SIZE) /
 		PAGE_SIZE;
 
@@ -1167,6 +1191,12 @@ static int cnic_alloc_bnx2x_resc(struct
 	if (ret)
 		goto error;
 
+	if (BNX2X_CHIP_IS_E2(cp->chip_id)) {
+		ret = cnic_alloc_kcq(dev, &cp->kcq2);
+		if (ret)
+			goto error;
+	}
+
 	pages = PAGE_ALIGN(BNX2X_ISCSI_NUM_CONNECTIONS *
 			   BNX2X_ISCSI_CONN_BUF_SIZE) / PAGE_SIZE;
 	ret = cnic_alloc_dma(dev, &cp->conn_buf_info, pages, 1);
@@ -1260,12 +1290,18 @@ static int cnic_submit_kwqe_16(struct cn
 	struct cnic_local *cp = dev->cnic_priv;
 	struct l5cm_spe kwqe;
 	struct kwqe_16 *kwq[1];
+	u16 type_16;
 	int ret;
 
 	kwqe.hdr.conn_and_cmd_data =
 		cpu_to_le32(((cmd << SPE_HDR_CMD_ID_SHIFT) |
 			     BNX2X_HW_CID(cp, cid)));
-	kwqe.hdr.type = cpu_to_le16(type);
+
+	type_16 = (type << SPE_HDR_CONN_TYPE_SHIFT) & SPE_HDR_CONN_TYPE;
+	type_16 |= (cp->pfid << SPE_HDR_FUNCTION_ID_SHIFT) &
+		   SPE_HDR_FUNCTION_ID;
+
+	kwqe.hdr.type = cpu_to_le16(type_16);
 	kwqe.hdr.reserved1 = 0;
 	kwqe.data.phy_address.lo = cpu_to_le32(l5_data->phy_address.lo);
 	kwqe.data.phy_address.hi = cpu_to_le32(l5_data->phy_address.hi);
@@ -1431,8 +1467,11 @@ static void cnic_free_bnx2x_conn_resc(st
 		cnic_free_dma(dev, &iscsi->hq_info);
 		cnic_free_dma(dev, &iscsi->r2tq_info);
 		cnic_free_dma(dev, &iscsi->task_array_info);
+		cnic_free_id(&cp->cid_tbl, ctx->cid);
+	} else {
+		cnic_free_id(&cp->fcoe_cid_tbl, ctx->cid);
 	}
-	cnic_free_id(&cp->cid_tbl, ctx->cid);
+
 	ctx->cid = 0;
 }
 
@@ -1444,6 +1483,16 @@ static int cnic_alloc_bnx2x_conn_resc(st
 	struct cnic_context *ctx = &cp->ctx_tbl[l5_cid];
 	struct cnic_iscsi *iscsi = ctx->proto.iscsi;
 
+	if (ctx->ulp_proto_id == CNIC_ULP_FCOE) {
+		cid = cnic_alloc_new_id(&cp->fcoe_cid_tbl);
+		if (cid == -1) {
+			ret = -ENOMEM;
+			goto error;
+		}
+		ctx->cid = cid;
+		return 0;
+	}
+
 	cid = cnic_alloc_new_id(&cp->cid_tbl);
 	if (cid == -1) {
 		ret = -ENOMEM;
@@ -1701,7 +1750,7 @@ static int cnic_bnx2x_iscsi_ofld1(struct
 		*work = num;
 		return -EINVAL;
 	}
-	*work = 2 + req2->num_additional_wqes;;
+	*work = 2 + req2->num_additional_wqes;
 
 	l5_cid = req1->iscsi_conn_id;
 	if (l5_cid >= MAX_ISCSI_TBL_SZ)
@@ -1776,19 +1825,15 @@ static int cnic_bnx2x_destroy_ramrod(str
 	struct cnic_context *ctx = &cp->ctx_tbl[l5_cid];
 	union l5cm_specific_data l5_data;
 	int ret;
-	u32 hw_cid, type;
+	u32 hw_cid;
 
 	init_waitqueue_head(&ctx->waitq);
 	ctx->wait_cond = 0;
 	memset(&l5_data, 0, sizeof(l5_data));
 	hw_cid = BNX2X_HW_CID(cp, ctx->cid);
-	type = (NONE_CONNECTION_TYPE << SPE_HDR_CONN_TYPE_SHIFT)
-		& SPE_HDR_CONN_TYPE;
-	type |= ((cp->pfid << SPE_HDR_FUNCTION_ID_SHIFT) &
-		 SPE_HDR_FUNCTION_ID);
 
 	ret = cnic_submit_kwqe_16(dev, RAMROD_CMD_ID_COMMON_CFC_DEL,
-				  hw_cid, type, &l5_data);
+				  hw_cid, NONE_CONNECTION_TYPE, &l5_data);
 
 	if (ret == 0)
 		wait_event(ctx->waitq, ctx->wait_cond);
@@ -2084,8 +2129,306 @@ static int cnic_bnx2x_update_pg(struct c
 	return 0;
 }
 
-static int cnic_submit_bnx2x_kwqes(struct cnic_dev *dev, struct kwqe *wqes[],
-				   u32 num_wqes)
+static int cnic_bnx2x_fcoe_stat(struct cnic_dev *dev, struct kwqe *kwqe)
+{
+	struct fcoe_kwqe_stat *req;
+	struct fcoe_stat_ramrod_params *fcoe_stat;
+	union l5cm_specific_data l5_data;
+	struct cnic_local *cp = dev->cnic_priv;
+	int ret;
+	u32 cid;
+
+	req = (struct fcoe_kwqe_stat *) kwqe;
+	cid = BNX2X_HW_CID(cp, cp->fcoe_init_cid);
+
+	fcoe_stat = cnic_get_kwqe_16_data(cp, BNX2X_FCOE_L5_CID_BASE, &l5_data);
+	if (!fcoe_stat)
+		return -ENOMEM;
+
+	memset(fcoe_stat, 0, sizeof(*fcoe_stat));
+	memcpy(&fcoe_stat->stat_kwqe, req, sizeof(*req));
+
+	ret = cnic_submit_kwqe_16(dev, FCOE_RAMROD_CMD_ID_STAT, cid,
+				  FCOE_CONNECTION_TYPE, &l5_data);
+	return ret;
+}
+
+static int cnic_bnx2x_fcoe_init1(struct cnic_dev *dev, struct kwqe *wqes[],
+				 u32 num, int *work)
+{
+	int ret;
+	struct cnic_local *cp = dev->cnic_priv;
+	u32 cid;
+	struct fcoe_init_ramrod_params *fcoe_init;
+	struct fcoe_kwqe_init1 *req1;
+	struct fcoe_kwqe_init2 *req2;
+	struct fcoe_kwqe_init3 *req3;
+	union l5cm_specific_data l5_data;
+
+	if (num < 3) {
+		*work = num;
+		return -EINVAL;
+	}
+	req1 = (struct fcoe_kwqe_init1 *) wqes[0];
+	req2 = (struct fcoe_kwqe_init2 *) wqes[1];
+	req3 = (struct fcoe_kwqe_init3 *) wqes[2];
+	if (req2->hdr.op_code != FCOE_KWQE_OPCODE_INIT2) {
+		*work = 1;
+		return -EINVAL;
+	}
+	if (req3->hdr.op_code != FCOE_KWQE_OPCODE_INIT3) {
+		*work = 2;
+		return -EINVAL;
+	}
+
+	if (sizeof(*fcoe_init) > CNIC_KWQ16_DATA_SIZE) {
+		netdev_err(dev->netdev, "fcoe_init size too big\n");
+		return -ENOMEM;
+	}
+	fcoe_init = cnic_get_kwqe_16_data(cp, BNX2X_FCOE_L5_CID_BASE, &l5_data);
+	if (!fcoe_init)
+		return -ENOMEM;
+
+	memset(fcoe_init, 0, sizeof(*fcoe_init));
+	memcpy(&fcoe_init->init_kwqe1, req1, sizeof(*req1));
+	memcpy(&fcoe_init->init_kwqe2, req2, sizeof(*req2));
+	memcpy(&fcoe_init->init_kwqe3, req3, sizeof(*req3));
+	fcoe_init->eq_addr.lo = cp->kcq2.dma.pg_map_arr[0] & 0xffffffff;
+	fcoe_init->eq_addr.hi = (u64) cp->kcq2.dma.pg_map_arr[0] >> 32;
+	fcoe_init->eq_next_page_addr.lo =
+		cp->kcq2.dma.pg_map_arr[1] & 0xffffffff;
+	fcoe_init->eq_next_page_addr.hi =
+		(u64) cp->kcq2.dma.pg_map_arr[1] >> 32;
+
+	fcoe_init->sb_num = cp->status_blk_num;
+	fcoe_init->eq_prod = MAX_KCQ_IDX;
+	fcoe_init->sb_id = HC_INDEX_FCOE_EQ_CONS;
+	cp->kcq2.sw_prod_idx = 0;
+
+	cid = BNX2X_HW_CID(cp, cp->fcoe_init_cid);
+	ret = cnic_submit_kwqe_16(dev, FCOE_RAMROD_CMD_ID_INIT, cid,
+				  FCOE_CONNECTION_TYPE, &l5_data);
+	*work = 3;
+	return ret;
+}
+
+static int cnic_bnx2x_fcoe_ofld1(struct cnic_dev *dev, struct kwqe *wqes[],
+				 u32 num, int *work)
+{
+	int ret = 0;
+	u32 cid = -1, l5_cid;
+	struct cnic_local *cp = dev->cnic_priv;
+	struct fcoe_kwqe_conn_offload1 *req1;
+	struct fcoe_kwqe_conn_offload2 *req2;
+	struct fcoe_kwqe_conn_offload3 *req3;
+	struct fcoe_kwqe_conn_offload4 *req4;
+	struct fcoe_conn_offload_ramrod_params *fcoe_offload;
+	struct cnic_context *ctx;
+	struct fcoe_context *fctx;
+	struct regpair ctx_addr;
+	union l5cm_specific_data l5_data;
+	struct fcoe_kcqe kcqe;
+	struct kcqe *cqes[1];
+
+	if (num < 4) {
+		*work = num;
+		return -EINVAL;
+	}
+	req1 = (struct fcoe_kwqe_conn_offload1 *) wqes[0];
+	req2 = (struct fcoe_kwqe_conn_offload2 *) wqes[1];
+	req3 = (struct fcoe_kwqe_conn_offload3 *) wqes[2];
+	req4 = (struct fcoe_kwqe_conn_offload4 *) wqes[3];
+
+	*work = 4;
+
+	l5_cid = req1->fcoe_conn_id;
+	if (l5_cid >= BNX2X_FCOE_NUM_CONNECTIONS)
+		goto err_reply;
+
+	l5_cid += BNX2X_FCOE_L5_CID_BASE;
+
+	ctx = &cp->ctx_tbl[l5_cid];
+	if (test_bit(CTX_FL_OFFLD_START, &ctx->ctx_flags))
+		goto err_reply;
+
+	ret = cnic_alloc_bnx2x_conn_resc(dev, l5_cid);
+	if (ret) {
+		ret = 0;
+		goto err_reply;
+	}
+	cid = ctx->cid;
+
+	fctx = cnic_get_bnx2x_ctx(dev, cid, 1, &ctx_addr);
+	if (fctx) {
+		u32 hw_cid = BNX2X_HW_CID(cp, cid);
+		u32 val;
+
+		val = CDU_RSRVD_VALUE_TYPE_A(hw_cid, CDU_REGION_NUMBER_XCM_AG,
+					     FCOE_CONNECTION_TYPE);
+		fctx->xstorm_ag_context.cdu_reserved = val;
+		val = CDU_RSRVD_VALUE_TYPE_A(hw_cid, CDU_REGION_NUMBER_UCM_AG,
+					     FCOE_CONNECTION_TYPE);
+		fctx->ustorm_ag_context.cdu_usage = val;
+	}
+	if (sizeof(*fcoe_offload) > CNIC_KWQ16_DATA_SIZE) {
+		netdev_err(dev->netdev, "fcoe_offload size too big\n");
+		goto err_reply;
+	}
+	fcoe_offload = cnic_get_kwqe_16_data(cp, l5_cid, &l5_data);
+	if (!fcoe_offload)
+		goto err_reply;
+
+	memset(fcoe_offload, 0, sizeof(*fcoe_offload));
+	memcpy(&fcoe_offload->offload_kwqe1, req1, sizeof(*req1));
+	memcpy(&fcoe_offload->offload_kwqe2, req2, sizeof(*req2));
+	memcpy(&fcoe_offload->offload_kwqe3, req3, sizeof(*req3));
+	memcpy(&fcoe_offload->offload_kwqe4, req4, sizeof(*req4));
+
+	cid = BNX2X_HW_CID(cp, cid);
+	ret = cnic_submit_kwqe_16(dev, FCOE_RAMROD_CMD_ID_OFFLOAD_CONN, cid,
+				  FCOE_CONNECTION_TYPE, &l5_data);
+	if (!ret)
+		set_bit(CTX_FL_OFFLD_START, &ctx->ctx_flags);
+
+	return ret;
+
+err_reply:
+	if (cid != -1)
+		cnic_free_bnx2x_conn_resc(dev, l5_cid);
+
+	memset(&kcqe, 0, sizeof(kcqe));
+	kcqe.op_code = FCOE_KCQE_OPCODE_OFFLOAD_CONN;
+	kcqe.fcoe_conn_id = req1->fcoe_conn_id;
+	kcqe.completion_status = FCOE_KCQE_COMPLETION_STATUS_CTX_ALLOC_FAILURE;
+
+	cqes[0] = (struct kcqe *) &kcqe;
+	cnic_reply_bnx2x_kcqes(dev, CNIC_ULP_FCOE, cqes, 1);
+	return ret;
+}
+
+static int cnic_bnx2x_fcoe_enable(struct cnic_dev *dev, struct kwqe *kwqe)
+{
+	struct fcoe_kwqe_conn_enable_disable *req;
+	struct fcoe_conn_enable_disable_ramrod_params *fcoe_enable;
+	union l5cm_specific_data l5_data;
+	int ret;
+	u32 cid, l5_cid;
+	struct cnic_local *cp = dev->cnic_priv;
+
+	req = (struct fcoe_kwqe_conn_enable_disable *) kwqe;
+	cid = req->context_id;
+	l5_cid = req->conn_id + BNX2X_FCOE_L5_CID_BASE;
+
+	if (sizeof(*fcoe_enable) > CNIC_KWQ16_DATA_SIZE) {
+		netdev_err(dev->netdev, "fcoe_enable size too big\n");
+		return -ENOMEM;
+	}
+	fcoe_enable = cnic_get_kwqe_16_data(cp, l5_cid, &l5_data);
+	if (!fcoe_enable)
+		return -ENOMEM;
+
+	memset(fcoe_enable, 0, sizeof(*fcoe_enable));
+	memcpy(&fcoe_enable->enable_disable_kwqe, req, sizeof(*req));
+	ret = cnic_submit_kwqe_16(dev, FCOE_RAMROD_CMD_ID_ENABLE_CONN, cid,
+				  FCOE_CONNECTION_TYPE, &l5_data);
+	return ret;
+}
+
+static int cnic_bnx2x_fcoe_disable(struct cnic_dev *dev, struct kwqe *kwqe)
+{
+	struct fcoe_kwqe_conn_enable_disable *req;
+	struct fcoe_conn_enable_disable_ramrod_params *fcoe_disable;
+	union l5cm_specific_data l5_data;
+	int ret;
+	u32 cid, l5_cid;
+	struct cnic_local *cp = dev->cnic_priv;
+
+	req = (struct fcoe_kwqe_conn_enable_disable *) kwqe;
+	cid = req->context_id;
+	l5_cid = req->conn_id;
+	if (l5_cid >= BNX2X_FCOE_NUM_CONNECTIONS)
+		return -EINVAL;
+
+	l5_cid += BNX2X_FCOE_L5_CID_BASE;
+
+	if (sizeof(*fcoe_disable) > CNIC_KWQ16_DATA_SIZE) {
+		netdev_err(dev->netdev, "fcoe_disable size too big\n");
+		return -ENOMEM;
+	}
+	fcoe_disable = cnic_get_kwqe_16_data(cp, l5_cid, &l5_data);
+	if (!fcoe_disable)
+		return -ENOMEM;
+
+	memset(fcoe_disable, 0, sizeof(*fcoe_disable));
+	memcpy(&fcoe_disable->enable_disable_kwqe, req, sizeof(*req));
+	ret = cnic_submit_kwqe_16(dev, FCOE_RAMROD_CMD_ID_DISABLE_CONN, cid,
+				  FCOE_CONNECTION_TYPE, &l5_data);
+	return ret;
+}
+
+static int cnic_bnx2x_fcoe_destroy(struct cnic_dev *dev, struct kwqe *kwqe)
+{
+	struct fcoe_kwqe_conn_destroy *req;
+	union l5cm_specific_data l5_data;
+	int ret;
+	u32 cid, l5_cid;
+	struct cnic_local *cp = dev->cnic_priv;
+	struct cnic_context *ctx;
+	struct fcoe_kcqe kcqe;
+	struct kcqe *cqes[1];
+
+	req = (struct fcoe_kwqe_conn_destroy *) kwqe;
+	cid = req->context_id;
+	l5_cid = req->conn_id;
+	if (l5_cid >= BNX2X_FCOE_NUM_CONNECTIONS)
+		return -EINVAL;
+
+	l5_cid += BNX2X_FCOE_L5_CID_BASE;
+
+	ctx = &cp->ctx_tbl[l5_cid];
+
+	init_waitqueue_head(&ctx->waitq);
+	ctx->wait_cond = 0;
+
+	memset(&l5_data, 0, sizeof(l5_data));
+	ret = cnic_submit_kwqe_16(dev, FCOE_RAMROD_CMD_ID_TERMINATE_CONN, cid,
+				  FCOE_CONNECTION_TYPE, &l5_data);
+	if (ret == 0) {
+		wait_event(ctx->waitq, ctx->wait_cond);
+		set_bit(CTX_FL_DELETE_WAIT, &ctx->ctx_flags);
+		queue_delayed_work(cnic_wq, &cp->delete_task,
+				   msecs_to_jiffies(2000));
+	}
+
+	memset(&kcqe, 0, sizeof(kcqe));
+	kcqe.op_code = FCOE_KCQE_OPCODE_DESTROY_CONN;
+	kcqe.fcoe_conn_id = req->conn_id;
+	kcqe.fcoe_conn_context_id = cid;
+
+	cqes[0] = (struct kcqe *) &kcqe;
+	cnic_reply_bnx2x_kcqes(dev, CNIC_ULP_FCOE, cqes, 1);
+	return ret;
+}
+
+static int cnic_bnx2x_fcoe_fw_destroy(struct cnic_dev *dev, struct kwqe *kwqe)
+{
+	struct fcoe_kwqe_destroy *req;
+	union l5cm_specific_data l5_data;
+	struct cnic_local *cp = dev->cnic_priv;
+	int ret;
+	u32 cid;
+
+	req = (struct fcoe_kwqe_destroy *) kwqe;
+	cid = BNX2X_HW_CID(cp, cp->fcoe_init_cid);
+
+	memset(&l5_data, 0, sizeof(l5_data));
+	ret = cnic_submit_kwqe_16(dev, FCOE_RAMROD_CMD_ID_DESTROY, cid,
+				  FCOE_CONNECTION_TYPE, &l5_data);
+	return ret;
+}
+
+static int cnic_submit_bnx2x_iscsi_kwqes(struct cnic_dev *dev,
+					 struct kwqe *wqes[], u32 num_wqes)
 {
 	int i, work, ret;
 	u32 opcode;
@@ -2149,6 +2492,98 @@ static int cnic_submit_bnx2x_kwqes(struc
 	return 0;
 }
 
+static int cnic_submit_bnx2x_fcoe_kwqes(struct cnic_dev *dev,
+					struct kwqe *wqes[], u32 num_wqes)
+{
+	struct cnic_local *cp = dev->cnic_priv;
+	int i, work, ret;
+	u32 opcode;
+	struct kwqe *kwqe;
+
+	if (!test_bit(CNIC_F_CNIC_UP, &dev->flags))
+		return -EAGAIN;		/* bnx2 is down */
+
+	if (BNX2X_CHIP_NUM(cp->chip_id) == BNX2X_CHIP_NUM_57710)
+		return -EINVAL;
+
+	for (i = 0; i < num_wqes; ) {
+		kwqe = wqes[i];
+		opcode = KWQE_OPCODE(kwqe->kwqe_op_flag);
+		work = 1;
+
+		switch (opcode) {
+		case FCOE_KWQE_OPCODE_INIT1:
+			ret = cnic_bnx2x_fcoe_init1(dev, &wqes[i],
+						    num_wqes - i, &work);
+			break;
+		case FCOE_KWQE_OPCODE_OFFLOAD_CONN1:
+			ret = cnic_bnx2x_fcoe_ofld1(dev, &wqes[i],
+						    num_wqes - i, &work);
+			break;
+		case FCOE_KWQE_OPCODE_ENABLE_CONN:
+			ret = cnic_bnx2x_fcoe_enable(dev, kwqe);
+			break;
+		case FCOE_KWQE_OPCODE_DISABLE_CONN:
+			ret = cnic_bnx2x_fcoe_disable(dev, kwqe);
+			break;
+		case FCOE_KWQE_OPCODE_DESTROY_CONN:
+			ret = cnic_bnx2x_fcoe_destroy(dev, kwqe);
+			break;
+		case FCOE_KWQE_OPCODE_DESTROY:
+			ret = cnic_bnx2x_fcoe_fw_destroy(dev, kwqe);
+			break;
+		case FCOE_KWQE_OPCODE_STAT:
+			ret = cnic_bnx2x_fcoe_stat(dev, kwqe);
+			break;
+		default:
+			ret = 0;
+			netdev_err(dev->netdev, "Unknown type of KWQE(0x%x)\n",
+				   opcode);
+			break;
+		}
+		if (ret < 0)
+			netdev_err(dev->netdev, "KWQE(0x%x) failed\n",
+				   opcode);
+		i += work;
+	}
+	return 0;
+}
+
+static int cnic_submit_bnx2x_kwqes(struct cnic_dev *dev, struct kwqe *wqes[],
+				   u32 num_wqes)
+{
+	int ret = -EINVAL;
+	u32 layer_code;
+
+	if (!test_bit(CNIC_F_CNIC_UP, &dev->flags))
+		return -EAGAIN;		/* bnx2x is down */
+
+	if (!num_wqes)
+		return 0;
+
+	layer_code = wqes[0]->kwqe_op_flag & KWQE_LAYER_MASK;
+	switch (layer_code) {
+	case KWQE_FLAGS_LAYER_MASK_L5_ISCSI:
+	case KWQE_FLAGS_LAYER_MASK_L4:
+	case KWQE_FLAGS_LAYER_MASK_L2:
+		ret = cnic_submit_bnx2x_iscsi_kwqes(dev, wqes, num_wqes);
+		break;
+
+	case KWQE_FLAGS_LAYER_MASK_L5_FCOE:
+		ret = cnic_submit_bnx2x_fcoe_kwqes(dev, wqes, num_wqes);
+		break;
+	}
+	return ret;
+}
+
+static inline u32 cnic_get_kcqe_layer_mask(u32 opflag)
+{
+	if (unlikely(KCQE_OPCODE(opflag) == FCOE_RAMROD_CMD_ID_TERMINATE_CONN))
+		return KCQE_FLAGS_LAYER_MASK_L4;
+
+	return opflag & KCQE_FLAGS_LAYER_MASK;
+}
+
 static void service_kcqes(struct cnic_dev *dev, int num_cqes)
 {
 	struct cnic_local *cp = dev->cnic_priv;
@@ -2160,7 +2595,7 @@ static void service_kcqes(struct cnic_de
 		struct cnic_ulp_ops *ulp_ops;
 		int ulp_type;
 		u32 kcqe_op_flag = cp->completed_kcq[i]->kcqe_op_flag;
-		u32 kcqe_layer = kcqe_op_flag & KCQE_FLAGS_LAYER_MASK;
+		u32 kcqe_layer = cnic_get_kcqe_layer_mask(kcqe_op_flag);
 
 		if (unlikely(kcqe_op_flag & KCQE_RAMROD_COMPLETION))
 			comp++;
@@ -2168,7 +2603,7 @@ static void service_kcqes(struct cnic_de
 		while (j < num_cqes) {
 			u32 next_op = cp->completed_kcq[i + j]->kcqe_op_flag;
 
-			if ((next_op & KCQE_FLAGS_LAYER_MASK) != kcqe_layer)
+			if (cnic_get_kcqe_layer_mask(next_op) != kcqe_layer)
 				break;
 
 			if (unlikely(next_op & KCQE_RAMROD_COMPLETION))
@@ -2180,6 +2615,8 @@ static void service_kcqes(struct cnic_de
 			ulp_type = CNIC_ULP_RDMA;
 		else if (kcqe_layer == KCQE_FLAGS_LAYER_MASK_L5_ISCSI)
 			ulp_type = CNIC_ULP_ISCSI;
+		else if (kcqe_layer == KCQE_FLAGS_LAYER_MASK_L5_FCOE)
+			ulp_type = CNIC_ULP_FCOE;
 		else if (kcqe_layer == KCQE_FLAGS_LAYER_MASK_L4)
 			ulp_type = CNIC_ULP_L4;
 		else if (kcqe_layer == KCQE_FLAGS_LAYER_MASK_L2)
@@ -2323,6 +2760,8 @@ static u32 cnic_service_bnx2_queues(stru
 	u32 status_idx = (u16) *cp->kcq1.status_idx_ptr;
 	int kcqe_cnt;
 
+	/* status block index must be read before reading other fields */
+	rmb();
 	cp->kwq_con_idx = *cp->kwq_con_idx_ptr;
 
 	while ((kcqe_cnt = cnic_get_kcqes(dev, &cp->kcq1))) {
@@ -2333,6 +2772,8 @@ static u32 cnic_service_bnx2_queues(stru
 		barrier();
 		if (status_idx != *cp->kcq1.status_idx_ptr) {
 			status_idx = (u16) *cp->kcq1.status_idx_ptr;
+			/* status block index must be read first */
+			rmb();
 			cp->kwq_con_idx = *cp->kwq_con_idx_ptr;
 		} else
 			break;
@@ -2348,11 +2789,12 @@ static u32 cnic_service_bnx2_queues(stru
 static int cnic_service_bnx2(void *data, void *status_blk)
 {
 	struct cnic_dev *dev = data;
-	struct cnic_local *cp = dev->cnic_priv;
-	u32 status_idx = *cp->kcq1.status_idx_ptr;
 
-	if (unlikely(!test_bit(CNIC_F_CNIC_UP, &dev->flags)))
-		return status_idx;
+	if (unlikely(!test_bit(CNIC_F_CNIC_UP, &dev->flags))) {
+		struct status_block *sblk = status_blk;
+
+		return sblk->status_idx;
+	}
 
 	return cnic_service_bnx2_queues(dev);
 }
@@ -2371,9 +2813,10 @@ static void cnic_service_bnx2_msix(unsig
 static void cnic_doirq(struct cnic_dev *dev)
 {
 	struct cnic_local *cp = dev->cnic_priv;
-	u16 prod = cp->kcq1.sw_prod_idx & MAX_KCQ_IDX;
 
 	if (likely(test_bit(CNIC_F_CNIC_UP, &dev->flags))) {
+		u16 prod = cp->kcq1.sw_prod_idx & MAX_KCQ_IDX;
+
 		prefetch(cp->status_blk.gen);
 		prefetch(&cp->kcq1.kcq[KCQ_PG(prod)][KCQ_IDX(prod)]);
 
@@ -2449,6 +2892,8 @@ static u32 cnic_service_bnx2x_kcq(struct
 	u32 last_status = *info->status_idx_ptr;
 	int kcqe_cnt;
 
+	/* status block index must be read before reading the KCQ */
+	rmb();
 	while ((kcqe_cnt = cnic_get_kcqes(dev, info))) {
 
 		service_kcqes(dev, kcqe_cnt);
@@ -2459,6 +2904,8 @@ static u32 cnic_service_bnx2x_kcq(struct
 			break;
 
 		last_status = *info->status_idx_ptr;
+		/* status block index must be read before reading the KCQ */
+		rmb();
 	}
 	return last_status;
 }
@@ -2467,20 +2914,36 @@ static void cnic_service_bnx2x_bh(unsign
 {
 	struct cnic_dev *dev = (struct cnic_dev *) data;
 	struct cnic_local *cp = dev->cnic_priv;
-	u32 status_idx;
+	u32 status_idx, new_status_idx;
 
 	if (unlikely(!test_bit(CNIC_F_CNIC_UP, &dev->flags)))
 		return;
 
-	status_idx = cnic_service_bnx2x_kcq(dev, &cp->kcq1);
+	while (1) {
+		status_idx = cnic_service_bnx2x_kcq(dev, &cp->kcq1);
+
+		CNIC_WR16(dev, cp->kcq1.io_addr,
+			  cp->kcq1.sw_prod_idx + MAX_KCQ_IDX);
+
+		if (!BNX2X_CHIP_IS_E2(cp->chip_id)) {
+			cnic_ack_bnx2x_int(dev, cp->bnx2x_igu_sb_id, USTORM_ID,
+					   status_idx, IGU_INT_ENABLE, 1);
+			break;
+		}
+
+		new_status_idx = cnic_service_bnx2x_kcq(dev, &cp->kcq2);
+
+		if (new_status_idx != status_idx)
+			continue;
+
+		CNIC_WR16(dev, cp->kcq2.io_addr, cp->kcq2.sw_prod_idx +
+			  MAX_KCQ_IDX);
 
-	CNIC_WR16(dev, cp->kcq1.io_addr, cp->kcq1.sw_prod_idx + MAX_KCQ_IDX);
-	if (BNX2X_CHIP_IS_E2(cp->chip_id))
 		cnic_ack_igu_sb(dev, cp->bnx2x_igu_sb_id, IGU_SEG_ACCESS_DEF,
 				status_idx, IGU_INT_ENABLE, 1);
-	else
-		cnic_ack_bnx2x_int(dev, cp->bnx2x_igu_sb_id, USTORM_ID,
-				   status_idx, IGU_INT_ENABLE, 1);
+
+		break;
+	}
 }
 
 static int cnic_service_bnx2x(void *data, void *status_blk)
@@ -2889,7 +3352,7 @@ static void cnic_cm_cleanup(struct cnic_
 		struct cnic_dev *dev = csk->dev;
 		struct cnic_local *cp = dev->cnic_priv;
 
-		cnic_free_id(&cp->csk_port_tbl, csk->src_port);
+		cnic_free_id(&cp->csk_port_tbl, be16_to_cpu(csk->src_port));
 		csk->src_port = 0;
 	}
 }
@@ -3020,7 +3483,8 @@ static int cnic_get_route(struct cnic_so
 	int is_v6, rc = 0;
 	struct dst_entry *dst = NULL;
 	struct net_device *realdev;
-	u32 local_port;
+	__be16 local_port;
+	u32 port_id;
 
 	if (saddr->local.v6.sin6_family == AF_INET6 &&
 	    saddr->remote.v6.sin6_family == AF_INET6)
@@ -3060,19 +3524,21 @@ static int cnic_get_route(struct cnic_so
 		}
 	}
 
-	if (local_port >= CNIC_LOCAL_PORT_MIN &&
-	    local_port < CNIC_LOCAL_PORT_MAX) {
-		if (cnic_alloc_id(&cp->csk_port_tbl, local_port))
-			local_port = 0;
+	port_id = be16_to_cpu(local_port);
+	if (port_id >= CNIC_LOCAL_PORT_MIN &&
+	    port_id < CNIC_LOCAL_PORT_MAX) {
+		if (cnic_alloc_id(&cp->csk_port_tbl, port_id))
+			port_id = 0;
 	} else
-		local_port = 0;
+		port_id = 0;
 
-	if (!local_port) {
-		local_port = cnic_alloc_new_id(&cp->csk_port_tbl);
-		if (local_port == -1) {
+	if (!port_id) {
+		port_id = cnic_alloc_new_id(&cp->csk_port_tbl);
+		if (port_id == -1) {
 			rc = -ENOMEM;
 			goto err_out;
 		}
+		local_port = cpu_to_be16(port_id);
 	}
 	csk->src_port = local_port;
 
@@ -3214,6 +3680,18 @@ done:
 	csk_put(csk);
 }
 
+static void cnic_process_fcoe_term_conn(struct cnic_dev *dev, struct kcqe *kcqe)
+{
+	struct cnic_local *cp = dev->cnic_priv;
+	struct fcoe_kcqe *fc_kcqe = (struct fcoe_kcqe *) kcqe;
+	u32 l5_cid = fc_kcqe->fcoe_conn_id + BNX2X_FCOE_L5_CID_BASE;
+	struct cnic_context *ctx = &cp->ctx_tbl[l5_cid];
+
+	ctx->timestamp = jiffies;
+	ctx->wait_cond = 1;
+	wake_up(&ctx->waitq);
+}
+
 static void cnic_cm_process_kcqe(struct cnic_dev *dev, struct kcqe *kcqe)
 {
 	struct cnic_local *cp = dev->cnic_priv;
@@ -3222,6 +3700,10 @@ static void cnic_cm_process_kcqe(struct
 	u32 l5_cid;
 	struct cnic_sock *csk;
 
+	if (opcode == FCOE_RAMROD_CMD_ID_TERMINATE_CONN) {
+		cnic_process_fcoe_term_conn(dev, kcqe);
+		return;
+	}
 	if (opcode == L4_KCQE_OPCODE_VALUE_OFFLOAD_PG ||
 	    opcode == L4_KCQE_OPCODE_VALUE_UPDATE_PG) {
 		cnic_cm_process_offld_pg(dev, l4kcqe);
@@ -3858,7 +4340,7 @@ static void cnic_shutdown_bnx2_rx_ring(s
 
 	memset(&l2kwqe, 0, sizeof(l2kwqe));
 	wqes[0] = &l2kwqe;
-	l2kwqe.kwqe_op_flag = (L2_LAYER_CODE << KWQE_FLAGS_LAYER_SHIFT) |
+	l2kwqe.kwqe_op_flag = (L2_LAYER_CODE << KWQE_LAYER_SHIFT) |
 			      (L2_KWQE_OPCODE_VALUE_FLUSH <<
 			       KWQE_OPCODE_SHIFT) | 2;
 	dev->submit_kwqes(dev, wqes, 1);
@@ -4112,7 +4594,7 @@ static void cnic_init_bnx2x_tx_ring(stru
 	struct host_sp_status_block *sb = cp->bnx2x_def_status_blk;
 	int port = CNIC_PORT(cp);
 	int i;
-	int cli = BNX2X_ISCSI_CL_ID(CNIC_E1HVN(cp));
+	u32 cli = cp->ethdev->iscsi_l2_client_id;
 	u32 val;
 
 	memset(txbd, 0, BCM_PAGE_SIZE);
@@ -4173,7 +4655,7 @@ static void cnic_init_bnx2x_rx_ring(stru
 	struct host_sp_status_block *sb = cp->bnx2x_def_status_blk;
 	int i;
 	int port = CNIC_PORT(cp);
-	int cli = BNX2X_ISCSI_CL_ID(CNIC_E1HVN(cp));
+	u32 cli = cp->ethdev->iscsi_l2_client_id;
 	int cl_qzone_id = BNX2X_CL_QZONE_ID(cp, cli);
 	u32 val;
 	dma_addr_t ring_map = udev->l2_ring_map;
@@ -4237,12 +4719,39 @@ static void cnic_init_bnx2x_rx_ring(stru
 
 	cp->rx_cons_ptr =
 		&sb->sp_sb.index_values[HC_SP_INDEX_ETH_ISCSI_RX_CQ_CONS];
+	cp->rx_cons = *cp->rx_cons_ptr;
+}
+
+static int cnic_read_bnx2x_iscsi_mac(struct cnic_dev *dev, u32 upper_addr,
+				     u32 lower_addr)
+{
+	u32 val;
+	u8 mac[6];
+
+	val = CNIC_RD(dev, upper_addr);
+
+	mac[0] = (u8) (val >> 8);
+	mac[1] = (u8) val;
+
+	val = CNIC_RD(dev, lower_addr);
+
+	mac[2] = (u8) (val >> 24);
+	mac[3] = (u8) (val >> 16);
+	mac[4] = (u8) (val >> 8);
+	mac[5] = (u8) val;
+
+	if (is_valid_ether_addr(mac)) {
+		memcpy(dev->mac_addr, mac, 6);
+		return 0;
+	} else {
+		return -EINVAL;
+	}
 }
 
 static void cnic_get_bnx2x_iscsi_info(struct cnic_dev *dev)
 {
 	struct cnic_local *cp = dev->cnic_priv;
-	u32 base, base2, addr, val;
+	u32 base, base2, addr, addr1, val;
 	int port = CNIC_PORT(cp);
 
 	dev->max_iscsi_conn = 0;
@@ -4255,20 +4764,10 @@ static void cnic_get_bnx2x_iscsi_info(st
 	addr = BNX2X_SHMEM_ADDR(base,
 		dev_info.port_hw_config[port].iscsi_mac_upper);
 
-	val = CNIC_RD(dev, addr);
-
-	dev->mac_addr[0] = (u8) (val >> 8);
-	dev->mac_addr[1] = (u8) val;
-
-	addr = BNX2X_SHMEM_ADDR(base,
+	addr1 = BNX2X_SHMEM_ADDR(base,
 		dev_info.port_hw_config[port].iscsi_mac_lower);
 
-	val = CNIC_RD(dev, addr);
-
-	dev->mac_addr[2] = (u8) (val >> 24);
-	dev->mac_addr[3] = (u8) (val >> 16);
-	dev->mac_addr[4] = (u8) (val >> 8);
-	dev->mac_addr[5] = (u8) val;
+	cnic_read_bnx2x_iscsi_mac(dev, addr, addr1);
 
 	addr = BNX2X_SHMEM_ADDR(base, validity_map[port]);
 	val = CNIC_RD(dev, addr);
@@ -4284,6 +4783,10 @@ static void cnic_get_bnx2x_iscsi_info(st
 			val16 ^= 0x1e1e;
 		dev->max_iscsi_conn = val16;
 	}
+
+	if (BNX2X_CHIP_IS_E2(cp->chip_id))
+		dev->max_fcoe_conn = BNX2X_FCOE_NUM_CONNECTIONS;
+
 	if (BNX2X_CHIP_IS_E1H(cp->chip_id) || BNX2X_CHIP_IS_E2(cp->chip_id)) {
 		int func = CNIC_FUNC(cp);
 		u32 mf_cfg_addr;
@@ -4294,21 +4797,90 @@ static void cnic_get_bnx2x_iscsi_info(st
 		else
 			mf_cfg_addr = base + BNX2X_SHMEM_MF_BLK_OFFSET;
 
-		addr = mf_cfg_addr +
-			offsetof(struct mf_cfg, func_mf_config[func].e1hov_tag);
+		if (BNX2X_CHIP_IS_E2(cp->chip_id)) {
+			/* Must determine if the MF is SD vs SI mode */
+			addr = BNX2X_SHMEM_ADDR(base,
+					dev_info.shared_feature_config.config);
+			val = CNIC_RD(dev, addr);
+			if ((val & SHARED_FEAT_CFG_FORCE_SF_MODE_MASK) ==
+			    SHARED_FEAT_CFG_FORCE_SF_MODE_SWITCH_INDEPT) {
+				int rc;
+
+				/* MULTI_FUNCTION_SI mode */
+				addr = BNX2X_MF_CFG_ADDR(mf_cfg_addr,
+					func_ext_config[func].func_cfg);
+				val = CNIC_RD(dev, addr);
+				if (!(val & MACP_FUNC_CFG_FLAGS_ISCSI_OFFLOAD))
+					dev->max_iscsi_conn = 0;
+
+				if (!(val & MACP_FUNC_CFG_FLAGS_FCOE_OFFLOAD))
+					dev->max_fcoe_conn = 0;
+
+				addr = BNX2X_MF_CFG_ADDR(mf_cfg_addr,
+					func_ext_config[func].
+					iscsi_mac_addr_upper);
+				addr1 = BNX2X_MF_CFG_ADDR(mf_cfg_addr,
+					func_ext_config[func].
+					iscsi_mac_addr_lower);
+				rc = cnic_read_bnx2x_iscsi_mac(dev, addr,
+								addr1);
+				if (rc && func > 1)
+					dev->max_iscsi_conn = 0;
+
+				return;
+			}
+		}
+
+		addr = BNX2X_MF_CFG_ADDR(mf_cfg_addr,
+			func_mf_config[func].e1hov_tag);
 
 		val = CNIC_RD(dev, addr);
 		val &= FUNC_MF_CFG_E1HOV_TAG_MASK;
 		if (val != FUNC_MF_CFG_E1HOV_TAG_DEFAULT) {
-			addr = mf_cfg_addr +
-				offsetof(struct mf_cfg,
-					 func_mf_config[func].config);
-			val = CNIC_RD(dev, addr);
-			val &= FUNC_MF_CFG_PROTOCOL_MASK;
-			if (val != FUNC_MF_CFG_PROTOCOL_ISCSI)
-				dev->max_iscsi_conn = 0;
+			dev->max_fcoe_conn = 0;
+			dev->max_iscsi_conn = 0;
 		}
 	}
+	if (!is_valid_ether_addr(dev->mac_addr))
+		dev->max_iscsi_conn = 0;
+}
+
+static void cnic_init_bnx2x_kcq(struct cnic_dev *dev)
+{
+	struct cnic_local *cp = dev->cnic_priv;
+	u32 pfid = cp->pfid;
+
+	cp->kcq1.io_addr = BAR_CSTRORM_INTMEM +
+			   CSTORM_ISCSI_EQ_PROD_OFFSET(pfid, 0);
+	cp->kcq1.sw_prod_idx = 0;
+
+	if (BNX2X_CHIP_IS_E2(cp->chip_id)) {
+		struct host_hc_status_block_e2 *sb = cp->status_blk.gen;
+
+		cp->kcq1.hw_prod_idx_ptr =
+			&sb->sb.index_values[HC_INDEX_ISCSI_EQ_CONS];
+		cp->kcq1.status_idx_ptr =
+			&sb->sb.running_index[SM_RX_ID];
+	} else {
+		struct host_hc_status_block_e1x *sb = cp->status_blk.gen;
+
+		cp->kcq1.hw_prod_idx_ptr =
+			&sb->sb.index_values[HC_INDEX_ISCSI_EQ_CONS];
+		cp->kcq1.status_idx_ptr =
+			&sb->sb.running_index[SM_RX_ID];
+	}
+
+	if (BNX2X_CHIP_IS_E2(cp->chip_id)) {
+		struct host_hc_status_block_e2 *sb = cp->status_blk.gen;
+
+		cp->kcq2.io_addr = BAR_USTRORM_INTMEM +
+					USTORM_FCOE_EQ_PROD_OFFSET(pfid);
+		cp->kcq2.sw_prod_idx = 0;
+		cp->kcq2.hw_prod_idx_ptr =
+			&sb->sb.index_values[HC_INDEX_FCOE_EQ_CONS];
+		cp->kcq2.status_idx_ptr =
+			&sb->sb.running_index[SM_RX_ID];
+	}
 }
 
 static int cnic_start_bnx2x_hw(struct cnic_dev *dev)
@@ -4341,28 +4913,19 @@ static int cnic_start_bnx2x_hw(struct cn
 	if (ret)
 		return -ENOMEM;
 
-	cp->bnx2x_igu_sb_id = ethdev->irq_arr[0].status_blk_num2;
-
-	cp->kcq1.io_addr = BAR_CSTRORM_INTMEM +
-			  CSTORM_ISCSI_EQ_PROD_OFFSET(pfid, 0);
-	cp->kcq1.sw_prod_idx = 0;
-
 	if (BNX2X_CHIP_IS_E2(cp->chip_id)) {
-		struct host_hc_status_block_e2 *sb = cp->status_blk.gen;
-
-		cp->kcq1.hw_prod_idx_ptr =
-			&sb->sb.index_values[HC_INDEX_ISCSI_EQ_CONS];
-		cp->kcq1.status_idx_ptr =
-			&sb->sb.running_index[SM_RX_ID];
-	} else {
-		struct host_hc_status_block_e1x *sb = cp->status_blk.gen;
+		ret = cnic_init_id_tbl(&cp->fcoe_cid_tbl,
+					BNX2X_FCOE_NUM_CONNECTIONS,
+					cp->fcoe_start_cid);
 
-		cp->kcq1.hw_prod_idx_ptr =
-			&sb->sb.index_values[HC_INDEX_ISCSI_EQ_CONS];
-		cp->kcq1.status_idx_ptr =
-			&sb->sb.running_index[SM_RX_ID];
+		if (ret)
+			return -ENOMEM;
 	}
 
+	cp->bnx2x_igu_sb_id = ethdev->irq_arr[0].status_blk_num2;
+
+	cnic_init_bnx2x_kcq(dev);
+
 	cnic_get_bnx2x_iscsi_info(dev);
 
 	/* Only 1 EQ */
@@ -4430,8 +4993,9 @@ static void cnic_init_rings(struct cnic_
 		cnic_init_bnx2_rx_ring(dev);
 		set_bit(CNIC_LCL_FL_RINGS_INITED, &cp->cnic_local_flags);
 	} else if (test_bit(CNIC_F_BNX2X_CLASS, &dev->flags)) {
-		u32 cli = BNX2X_ISCSI_CL_ID(CNIC_E1HVN(cp));
-		u32 cl_qzone_id, type;
+		u32 cli = cp->ethdev->iscsi_l2_client_id;
+		u32 cid = cp->ethdev->iscsi_l2_cid;
+		u32 cl_qzone_id;
 		struct client_init_ramrod_data *data;
 		union l5cm_specific_data l5_data;
 		struct ustorm_eth_rx_producers rx_prods = {0};
@@ -4463,15 +5027,10 @@ static void cnic_init_rings(struct cnic_
 		l5_data.phy_address.lo = udev->l2_buf_map & 0xffffffff;
 		l5_data.phy_address.hi = (u64) udev->l2_buf_map >> 32;
 
-		type = (ETH_CONNECTION_TYPE << SPE_HDR_CONN_TYPE_SHIFT)
-			& SPE_HDR_CONN_TYPE;
-		type |= ((cp->pfid << SPE_HDR_FUNCTION_ID_SHIFT) &
-			SPE_HDR_FUNCTION_ID);
-
 		set_bit(CNIC_LCL_FL_RINGS_INITED, &cp->cnic_local_flags);
 
 		cnic_submit_kwqe_16(dev, RAMROD_CMD_ID_ETH_CLIENT_SETUP,
-			BNX2X_ISCSI_L2_CID, type, &l5_data);
+			cid, ETH_CONNECTION_TYPE, &l5_data);
 
 		i = 0;
 		while (test_bit(CNIC_LCL_FL_L2_WAIT, &cp->cnic_local_flags) &&
@@ -4482,7 +5041,7 @@ static void cnic_init_rings(struct cnic_
 			netdev_err(dev->netdev,
 				"iSCSI CLIENT_SETUP did not complete\n");
 		cnic_spq_completion(dev, DRV_CTL_RET_L2_SPQ_CREDIT_CMD, 1);
-		cnic_ring_ctl(dev, BNX2X_ISCSI_L2_CID, cli, 1);
+		cnic_ring_ctl(dev, cid, cli, 1);
 	}
 }
 
@@ -4497,19 +5056,19 @@ static void cnic_shutdown_rings(struct c
 		cnic_shutdown_bnx2_rx_ring(dev);
 	} else if (test_bit(CNIC_F_BNX2X_CLASS, &dev->flags)) {
 		struct cnic_local *cp = dev->cnic_priv;
-		u32 cli = BNX2X_ISCSI_CL_ID(CNIC_E1HVN(cp));
+		u32 cli = cp->ethdev->iscsi_l2_client_id;
+		u32 cid = cp->ethdev->iscsi_l2_cid;
 		union l5cm_specific_data l5_data;
 		int i;
-		u32 type;
 
-		cnic_ring_ctl(dev, BNX2X_ISCSI_L2_CID, cli, 0);
+		cnic_ring_ctl(dev, cid, cli, 0);
 
 		set_bit(CNIC_LCL_FL_L2_WAIT, &cp->cnic_local_flags);
 
 		l5_data.phy_address.lo = cli;
 		l5_data.phy_address.hi = 0;
 		cnic_submit_kwqe_16(dev, RAMROD_CMD_ID_ETH_HALT,
-			BNX2X_ISCSI_L2_CID, ETH_CONNECTION_TYPE, &l5_data);
+			cid, ETH_CONNECTION_TYPE, &l5_data);
 		i = 0;
 		while (test_bit(CNIC_LCL_FL_L2_WAIT, &cp->cnic_local_flags) &&
 		       ++i < 10)
@@ -4521,12 +5080,8 @@ static void cnic_shutdown_rings(struct c
 		cnic_spq_completion(dev, DRV_CTL_RET_L2_SPQ_CREDIT_CMD, 1);
 
 		memset(&l5_data, 0, sizeof(l5_data));
-		type = (NONE_CONNECTION_TYPE << SPE_HDR_CONN_TYPE_SHIFT)
-			& SPE_HDR_CONN_TYPE;
-		type |= ((cp->pfid << SPE_HDR_FUNCTION_ID_SHIFT) &
-			 SPE_HDR_FUNCTION_ID);
 		cnic_submit_kwqe_16(dev, RAMROD_CMD_ID_COMMON_CFC_DEL,
-			BNX2X_ISCSI_L2_CID, type, &l5_data);
+			cid, NONE_CONNECTION_TYPE, &l5_data);
 		msleep(10);
 	}
 	clear_bit(CNIC_LCL_FL_RINGS_INITED, &cp->cnic_local_flags);
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/cnic_defs.h linux-libre-2.6.38-gnu1/drivers/net/cnic_defs.h
--- linux-libre-2.6.37-gnu1/drivers/net/cnic_defs.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/cnic_defs.h	2011-03-14 21:20:32.000000000 -0400
@@ -35,6 +35,40 @@
 #define L5CM_RAMROD_CMD_ID_SEARCHER_DELETE	(L5CM_RAMROD_CMD_ID_BASE + 14)
 #define L5CM_RAMROD_CMD_ID_TERMINATE_OFFLOAD	(L5CM_RAMROD_CMD_ID_BASE + 15)
 
+#define FCOE_KCQE_OPCODE_INIT_FUNC			(0x10)
+#define FCOE_KCQE_OPCODE_DESTROY_FUNC			(0x11)
+#define FCOE_KCQE_OPCODE_STAT_FUNC			(0x12)
+#define FCOE_KCQE_OPCODE_OFFLOAD_CONN			(0x15)
+#define FCOE_KCQE_OPCODE_ENABLE_CONN			(0x16)
+#define FCOE_KCQE_OPCODE_DISABLE_CONN			(0x17)
+#define FCOE_KCQE_OPCODE_DESTROY_CONN			(0x18)
+#define FCOE_KCQE_OPCODE_CQ_EVENT_NOTIFICATION  (0x20)
+#define FCOE_KCQE_OPCODE_FCOE_ERROR				(0x21)
+
+#define FCOE_RAMROD_CMD_ID_INIT			(FCOE_KCQE_OPCODE_INIT_FUNC)
+#define FCOE_RAMROD_CMD_ID_DESTROY		(FCOE_KCQE_OPCODE_DESTROY_FUNC)
+#define FCOE_RAMROD_CMD_ID_OFFLOAD_CONN		(FCOE_KCQE_OPCODE_OFFLOAD_CONN)
+#define FCOE_RAMROD_CMD_ID_ENABLE_CONN		(FCOE_KCQE_OPCODE_ENABLE_CONN)
+#define FCOE_RAMROD_CMD_ID_DISABLE_CONN		(FCOE_KCQE_OPCODE_DISABLE_CONN)
+#define FCOE_RAMROD_CMD_ID_DESTROY_CONN		(FCOE_KCQE_OPCODE_DESTROY_CONN)
+#define FCOE_RAMROD_CMD_ID_STAT			(FCOE_KCQE_OPCODE_STAT_FUNC)
+#define FCOE_RAMROD_CMD_ID_TERMINATE_CONN	(0x81)
+
+#define FCOE_KWQE_OPCODE_INIT1                  (0)
+#define FCOE_KWQE_OPCODE_INIT2                  (1)
+#define FCOE_KWQE_OPCODE_INIT3                  (2)
+#define FCOE_KWQE_OPCODE_OFFLOAD_CONN1  (3)
+#define FCOE_KWQE_OPCODE_OFFLOAD_CONN2  (4)
+#define FCOE_KWQE_OPCODE_OFFLOAD_CONN3  (5)
+#define FCOE_KWQE_OPCODE_OFFLOAD_CONN4  (6)
+#define FCOE_KWQE_OPCODE_ENABLE_CONN	(7)
+#define FCOE_KWQE_OPCODE_DISABLE_CONN	(8)
+#define FCOE_KWQE_OPCODE_DESTROY_CONN	(9)
+#define FCOE_KWQE_OPCODE_DESTROY		(10)
+#define FCOE_KWQE_OPCODE_STAT			(11)
+
+#define FCOE_KCQE_COMPLETION_STATUS_CTX_ALLOC_FAILURE	(0x3)
+
 /* KCQ (kernel completion queue) response op codes */
 #define L4_KCQE_OPCODE_VALUE_CLOSE_COMP             (53)
 #define L4_KCQE_OPCODE_VALUE_RESET_COMP             (54)
@@ -683,6 +717,1496 @@ struct cstorm_iscsi_ag_context {
 };
 
 /*
+ * Parameters initialized during offloaded according to FLOGI/PLOGI/PRLI and used in FCoE context section
+ */
+struct ustorm_fcoe_params {
+#if defined(__BIG_ENDIAN)
+	u16 fcoe_conn_id;
+	u16 flags;
+#define USTORM_FCOE_PARAMS_B_MUL_N_PORT_IDS (0x1<<0)
+#define USTORM_FCOE_PARAMS_B_MUL_N_PORT_IDS_SHIFT 0
+#define USTORM_FCOE_PARAMS_B_E_D_TOV_RES (0x1<<1)
+#define USTORM_FCOE_PARAMS_B_E_D_TOV_RES_SHIFT 1
+#define USTORM_FCOE_PARAMS_B_CONT_INCR_SEQ_CNT (0x1<<2)
+#define USTORM_FCOE_PARAMS_B_CONT_INCR_SEQ_CNT_SHIFT 2
+#define USTORM_FCOE_PARAMS_B_CONF_REQ (0x1<<3)
+#define USTORM_FCOE_PARAMS_B_CONF_REQ_SHIFT 3
+#define USTORM_FCOE_PARAMS_B_REC_VALID (0x1<<4)
+#define USTORM_FCOE_PARAMS_B_REC_VALID_SHIFT 4
+#define USTORM_FCOE_PARAMS_B_CQ_TOGGLE_BIT (0x1<<5)
+#define USTORM_FCOE_PARAMS_B_CQ_TOGGLE_BIT_SHIFT 5
+#define USTORM_FCOE_PARAMS_B_XFRQ_TOGGLE_BIT (0x1<<6)
+#define USTORM_FCOE_PARAMS_B_XFRQ_TOGGLE_BIT_SHIFT 6
+#define USTORM_FCOE_PARAMS_B_C2_VALID (0x1<<7)
+#define USTORM_FCOE_PARAMS_B_C2_VALID_SHIFT 7
+#define USTORM_FCOE_PARAMS_B_ACK_0 (0x1<<8)
+#define USTORM_FCOE_PARAMS_B_ACK_0_SHIFT 8
+#define USTORM_FCOE_PARAMS_RSRV0 (0x7F<<9)
+#define USTORM_FCOE_PARAMS_RSRV0_SHIFT 9
+#elif defined(__LITTLE_ENDIAN)
+	u16 flags;
+#define USTORM_FCOE_PARAMS_B_MUL_N_PORT_IDS (0x1<<0)
+#define USTORM_FCOE_PARAMS_B_MUL_N_PORT_IDS_SHIFT 0
+#define USTORM_FCOE_PARAMS_B_E_D_TOV_RES (0x1<<1)
+#define USTORM_FCOE_PARAMS_B_E_D_TOV_RES_SHIFT 1
+#define USTORM_FCOE_PARAMS_B_CONT_INCR_SEQ_CNT (0x1<<2)
+#define USTORM_FCOE_PARAMS_B_CONT_INCR_SEQ_CNT_SHIFT 2
+#define USTORM_FCOE_PARAMS_B_CONF_REQ (0x1<<3)
+#define USTORM_FCOE_PARAMS_B_CONF_REQ_SHIFT 3
+#define USTORM_FCOE_PARAMS_B_REC_VALID (0x1<<4)
+#define USTORM_FCOE_PARAMS_B_REC_VALID_SHIFT 4
+#define USTORM_FCOE_PARAMS_B_CQ_TOGGLE_BIT (0x1<<5)
+#define USTORM_FCOE_PARAMS_B_CQ_TOGGLE_BIT_SHIFT 5
+#define USTORM_FCOE_PARAMS_B_XFRQ_TOGGLE_BIT (0x1<<6)
+#define USTORM_FCOE_PARAMS_B_XFRQ_TOGGLE_BIT_SHIFT 6
+#define USTORM_FCOE_PARAMS_B_C2_VALID (0x1<<7)
+#define USTORM_FCOE_PARAMS_B_C2_VALID_SHIFT 7
+#define USTORM_FCOE_PARAMS_B_ACK_0 (0x1<<8)
+#define USTORM_FCOE_PARAMS_B_ACK_0_SHIFT 8
+#define USTORM_FCOE_PARAMS_RSRV0 (0x7F<<9)
+#define USTORM_FCOE_PARAMS_RSRV0_SHIFT 9
+	u16 fcoe_conn_id;
+#endif
+#if defined(__BIG_ENDIAN)
+	u8 hc_csdm_byte_en;
+	u8 func_id;
+	u8 port_id;
+	u8 vnic_id;
+#elif defined(__LITTLE_ENDIAN)
+	u8 vnic_id;
+	u8 port_id;
+	u8 func_id;
+	u8 hc_csdm_byte_en;
+#endif
+#if defined(__BIG_ENDIAN)
+	u16 rx_total_conc_seqs;
+	u16 rx_max_fc_pay_len;
+#elif defined(__LITTLE_ENDIAN)
+	u16 rx_max_fc_pay_len;
+	u16 rx_total_conc_seqs;
+#endif
+#if defined(__BIG_ENDIAN)
+	u16 ox_id;
+	u16 rx_max_conc_seqs;
+#elif defined(__LITTLE_ENDIAN)
+	u16 rx_max_conc_seqs;
+	u16 ox_id;
+#endif
+};
+
+/*
+ * FCoE 16-bits index structure
+ */
+struct fcoe_idx16_fields {
+	u16 fields;
+#define FCOE_IDX16_FIELDS_IDX (0x7FFF<<0)
+#define FCOE_IDX16_FIELDS_IDX_SHIFT 0
+#define FCOE_IDX16_FIELDS_MSB (0x1<<15)
+#define FCOE_IDX16_FIELDS_MSB_SHIFT 15
+};
+
+/*
+ * FCoE 16-bits index union
+ */
+union fcoe_idx16_field_union {
+	struct fcoe_idx16_fields fields;
+	u16 val;
+};
+
+/*
+ * 4 regs size
+ */
+struct fcoe_bd_ctx {
+	u32 buf_addr_hi;
+	u32 buf_addr_lo;
+#if defined(__BIG_ENDIAN)
+	u16 rsrv0;
+	u16 buf_len;
+#elif defined(__LITTLE_ENDIAN)
+	u16 buf_len;
+	u16 rsrv0;
+#endif
+#if defined(__BIG_ENDIAN)
+	u16 rsrv1;
+	u16 flags;
+#elif defined(__LITTLE_ENDIAN)
+	u16 flags;
+	u16 rsrv1;
+#endif
+};
+
+/*
+ * Parameters required for placement according to SGL
+ */
+struct ustorm_fcoe_data_place {
+#if defined(__BIG_ENDIAN)
+	u16 cached_sge_off;
+	u8 cached_num_sges;
+	u8 cached_sge_idx;
+#elif defined(__LITTLE_ENDIAN)
+	u8 cached_sge_idx;
+	u8 cached_num_sges;
+	u16 cached_sge_off;
+#endif
+	struct fcoe_bd_ctx cached_sge[3];
+};
+
+struct fcoe_task_ctx_entry_txwr_rxrd {
+#if defined(__BIG_ENDIAN)
+	u16 verify_tx_seq;
+	u8 init_flags;
+#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TASK_TYPE (0x7<<0)
+#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TASK_TYPE_SHIFT 0
+#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_DEV_TYPE (0x1<<3)
+#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_DEV_TYPE_SHIFT 3
+#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_CLASS_TYPE (0x1<<4)
+#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_CLASS_TYPE_SHIFT 4
+#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_SINGLE_SGE (0x1<<5)
+#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_SINGLE_SGE_SHIFT 5
+#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_RSRV5 (0x3<<6)
+#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_RSRV5_SHIFT 6
+	u8 tx_flags;
+#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TX_STATE (0xF<<0)
+#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TX_STATE_SHIFT 0
+#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_RSRV4 (0xF<<4)
+#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_RSRV4_SHIFT 4
+#elif defined(__LITTLE_ENDIAN)
+	u8 tx_flags;
+#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TX_STATE (0xF<<0)
+#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TX_STATE_SHIFT 0
+#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_RSRV4 (0xF<<4)
+#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_RSRV4_SHIFT 4
+	u8 init_flags;
+#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TASK_TYPE (0x7<<0)
+#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TASK_TYPE_SHIFT 0
+#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_DEV_TYPE (0x1<<3)
+#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_DEV_TYPE_SHIFT 3
+#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_CLASS_TYPE (0x1<<4)
+#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_CLASS_TYPE_SHIFT 4
+#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_SINGLE_SGE (0x1<<5)
+#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_SINGLE_SGE_SHIFT 5
+#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_RSRV5 (0x3<<6)
+#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_RSRV5_SHIFT 6
+	u16 verify_tx_seq;
+#endif
+};
+
+struct fcoe_fcp_cmd_payload {
+	u32 opaque[8];
+};
+
+struct fcoe_fc_hdr {
+#if defined(__BIG_ENDIAN)
+	u8 cs_ctl;
+	u8 s_id[3];
+#elif defined(__LITTLE_ENDIAN)
+	u8 s_id[3];
+	u8 cs_ctl;
+#endif
+#if defined(__BIG_ENDIAN)
+	u8 r_ctl;
+	u8 d_id[3];
+#elif defined(__LITTLE_ENDIAN)
+	u8 d_id[3];
+	u8 r_ctl;
+#endif
+#if defined(__BIG_ENDIAN)
+	u8 seq_id;
+	u8 df_ctl;
+	u16 seq_cnt;
+#elif defined(__LITTLE_ENDIAN)
+	u16 seq_cnt;
+	u8 df_ctl;
+	u8 seq_id;
+#endif
+#if defined(__BIG_ENDIAN)
+	u8 type;
+	u8 f_ctl[3];
+#elif defined(__LITTLE_ENDIAN)
+	u8 f_ctl[3];
+	u8 type;
+#endif
+	u32 parameters;
+#if defined(__BIG_ENDIAN)
+	u16 ox_id;
+	u16 rx_id;
+#elif defined(__LITTLE_ENDIAN)
+	u16 rx_id;
+	u16 ox_id;
+#endif
+};
+
+struct fcoe_fc_frame {
+	struct fcoe_fc_hdr fc_hdr;
+	u32 reserved0[2];
+};
+
+union fcoe_cmd_flow_info {
+	struct fcoe_fcp_cmd_payload fcp_cmd_payload;
+	struct fcoe_fc_frame mp_fc_frame;
+};
+
+struct fcoe_read_flow_info {
+	struct fcoe_fc_hdr fc_data_in_hdr;
+	u32 reserved[2];
+};
+
+struct fcoe_fcp_xfr_rdy_payload {
+	u32 burst_len;
+	u32 data_ro;
+};
+
+struct fcoe_write_flow_info {
+	struct fcoe_fc_hdr fc_data_out_hdr;
+	struct fcoe_fcp_xfr_rdy_payload fcp_xfr_payload;
+};
+
+struct fcoe_fcp_rsp_flags {
+	u8 flags;
+#define FCOE_FCP_RSP_FLAGS_FCP_RSP_LEN_VALID (0x1<<0)
+#define FCOE_FCP_RSP_FLAGS_FCP_RSP_LEN_VALID_SHIFT 0
+#define FCOE_FCP_RSP_FLAGS_FCP_SNS_LEN_VALID (0x1<<1)
+#define FCOE_FCP_RSP_FLAGS_FCP_SNS_LEN_VALID_SHIFT 1
+#define FCOE_FCP_RSP_FLAGS_FCP_RESID_OVER (0x1<<2)
+#define FCOE_FCP_RSP_FLAGS_FCP_RESID_OVER_SHIFT 2
+#define FCOE_FCP_RSP_FLAGS_FCP_RESID_UNDER (0x1<<3)
+#define FCOE_FCP_RSP_FLAGS_FCP_RESID_UNDER_SHIFT 3
+#define FCOE_FCP_RSP_FLAGS_FCP_CONF_REQ (0x1<<4)
+#define FCOE_FCP_RSP_FLAGS_FCP_CONF_REQ_SHIFT 4
+#define FCOE_FCP_RSP_FLAGS_FCP_BIDI_FLAGS (0x7<<5)
+#define FCOE_FCP_RSP_FLAGS_FCP_BIDI_FLAGS_SHIFT 5
+};
+
+struct fcoe_fcp_rsp_payload {
+	struct regpair reserved0;
+	u32 fcp_resid;
+#if defined(__BIG_ENDIAN)
+	u16 retry_delay_timer;
+	struct fcoe_fcp_rsp_flags fcp_flags;
+	u8 scsi_status_code;
+#elif defined(__LITTLE_ENDIAN)
+	u8 scsi_status_code;
+	struct fcoe_fcp_rsp_flags fcp_flags;
+	u16 retry_delay_timer;
+#endif
+	u32 fcp_rsp_len;
+	u32 fcp_sns_len;
+};
+
+/*
+ * Fixed size structure in order to plant it in Union structure
+ */
+struct fcoe_fcp_rsp_union {
+	struct fcoe_fcp_rsp_payload payload;
+	struct regpair reserved0;
+};
+
+/*
+ * Fixed size structure in order to plant it in Union structure
+ */
+struct fcoe_abts_rsp_union {
+	u32 r_ctl;
+	u32 abts_rsp_payload[7];
+};
+
+union fcoe_rsp_flow_info {
+	struct fcoe_fcp_rsp_union fcp_rsp;
+	struct fcoe_abts_rsp_union abts_rsp;
+};
+
+struct fcoe_cleanup_flow_info {
+#if defined(__BIG_ENDIAN)
+	u16 reserved1;
+	u16 task_id;
+#elif defined(__LITTLE_ENDIAN)
+	u16 task_id;
+	u16 reserved1;
+#endif
+	u32 reserved2[7];
+};
+
+/*
+ * 32 bytes used for general purposes
+ */
+union fcoe_general_task_ctx {
+	union fcoe_cmd_flow_info cmd_info;
+	struct fcoe_read_flow_info read_info;
+	struct fcoe_write_flow_info write_info;
+	union fcoe_rsp_flow_info rsp_info;
+	struct fcoe_cleanup_flow_info cleanup_info;
+	u32 comp_info[8];
+};
+
+struct fcoe_s_stat_ctx {
+	u8 flags;
+#define FCOE_S_STAT_CTX_ACTIVE (0x1<<0)
+#define FCOE_S_STAT_CTX_ACTIVE_SHIFT 0
+#define FCOE_S_STAT_CTX_ACK_ABORT_SEQ_COND (0x1<<1)
+#define FCOE_S_STAT_CTX_ACK_ABORT_SEQ_COND_SHIFT 1
+#define FCOE_S_STAT_CTX_ABTS_PERFORMED (0x1<<2)
+#define FCOE_S_STAT_CTX_ABTS_PERFORMED_SHIFT 2
+#define FCOE_S_STAT_CTX_SEQ_TIMEOUT (0x1<<3)
+#define FCOE_S_STAT_CTX_SEQ_TIMEOUT_SHIFT 3
+#define FCOE_S_STAT_CTX_P_RJT (0x1<<4)
+#define FCOE_S_STAT_CTX_P_RJT_SHIFT 4
+#define FCOE_S_STAT_CTX_ACK_EOFT (0x1<<5)
+#define FCOE_S_STAT_CTX_ACK_EOFT_SHIFT 5
+#define FCOE_S_STAT_CTX_RSRV1 (0x3<<6)
+#define FCOE_S_STAT_CTX_RSRV1_SHIFT 6
+};
+
+/*
+ * Common section. Both TX and RX processing might write and read from it in different flows
+ */
+struct fcoe_task_ctx_entry_tx_rx_cmn {
+	u32 data_2_trns;
+	union fcoe_general_task_ctx general;
+#if defined(__BIG_ENDIAN)
+	u16 tx_low_seq_cnt;
+	struct fcoe_s_stat_ctx tx_s_stat;
+	u8 tx_seq_id;
+#elif defined(__LITTLE_ENDIAN)
+	u8 tx_seq_id;
+	struct fcoe_s_stat_ctx tx_s_stat;
+	u16 tx_low_seq_cnt;
+#endif
+	u32 common_flags;
+#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_CID (0xFFFFFF<<0)
+#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_CID_SHIFT 0
+#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_VALID (0x1<<24)
+#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_VALID_SHIFT 24
+#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_SEQ_INIT (0x1<<25)
+#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_SEQ_INIT_SHIFT 25
+#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_PEND_XFER (0x1<<26)
+#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_PEND_XFER_SHIFT 26
+#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_PEND_CONF (0x1<<27)
+#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_PEND_CONF_SHIFT 27
+#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_EXP_FIRST_FRAME (0x1<<28)
+#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_EXP_FIRST_FRAME_SHIFT 28
+#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_RSRV (0x7<<29)
+#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_RSRV_SHIFT 29
+};
+
+struct fcoe_task_ctx_entry_rxwr_txrd {
+#if defined(__BIG_ENDIAN)
+	u16 rx_id;
+	u16 rx_flags;
+#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_RX_STATE (0xF<<0)
+#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_RX_STATE_SHIFT 0
+#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_NUM_RQ_WQE (0x7<<4)
+#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_NUM_RQ_WQE_SHIFT 4
+#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_CONF_REQ (0x1<<7)
+#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_CONF_REQ_SHIFT 7
+#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_MISS_FRAME (0x1<<8)
+#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_MISS_FRAME_SHIFT 8
+#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_RESERVED0 (0x7F<<9)
+#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_RESERVED0_SHIFT 9
+#elif defined(__LITTLE_ENDIAN)
+	u16 rx_flags;
+#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_RX_STATE (0xF<<0)
+#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_RX_STATE_SHIFT 0
+#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_NUM_RQ_WQE (0x7<<4)
+#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_NUM_RQ_WQE_SHIFT 4
+#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_CONF_REQ (0x1<<7)
+#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_CONF_REQ_SHIFT 7
+#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_MISS_FRAME (0x1<<8)
+#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_MISS_FRAME_SHIFT 8
+#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_RESERVED0 (0x7F<<9)
+#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_RESERVED0_SHIFT 9
+	u16 rx_id;
+#endif
+};
+
+struct fcoe_seq_ctx {
+#if defined(__BIG_ENDIAN)
+	u16 low_seq_cnt;
+	struct fcoe_s_stat_ctx s_stat;
+	u8 seq_id;
+#elif defined(__LITTLE_ENDIAN)
+	u8 seq_id;
+	struct fcoe_s_stat_ctx s_stat;
+	u16 low_seq_cnt;
+#endif
+#if defined(__BIG_ENDIAN)
+	u16 err_seq_cnt;
+	u16 high_seq_cnt;
+#elif defined(__LITTLE_ENDIAN)
+	u16 high_seq_cnt;
+	u16 err_seq_cnt;
+#endif
+	u32 low_exp_ro;
+	u32 high_exp_ro;
+};
+
+struct fcoe_single_sge_ctx {
+	struct regpair cur_buf_addr;
+#if defined(__BIG_ENDIAN)
+	u16 reserved0;
+	u16 cur_buf_rem;
+#elif defined(__LITTLE_ENDIAN)
+	u16 cur_buf_rem;
+	u16 reserved0;
+#endif
+};
+
+struct fcoe_mul_sges_ctx {
+	struct regpair cur_sge_addr;
+#if defined(__BIG_ENDIAN)
+	u8 sgl_size;
+	u8 cur_sge_idx;
+	u16 cur_sge_off;
+#elif defined(__LITTLE_ENDIAN)
+	u16 cur_sge_off;
+	u8 cur_sge_idx;
+	u8 sgl_size;
+#endif
+};
+
+union fcoe_sgl_ctx {
+	struct fcoe_single_sge_ctx single_sge;
+	struct fcoe_mul_sges_ctx mul_sges;
+};
+
+struct fcoe_task_ctx_entry_rx_only {
+	struct fcoe_seq_ctx seq_ctx;
+	struct fcoe_seq_ctx ooo_seq_ctx;
+	u32 rsrv3;
+	union fcoe_sgl_ctx sgl_ctx;
+};
+
+struct ustorm_fcoe_task_ctx_entry_rd {
+	struct fcoe_task_ctx_entry_txwr_rxrd tx_wr_rx_rd;
+	struct fcoe_task_ctx_entry_tx_rx_cmn cmn;
+	struct fcoe_task_ctx_entry_rxwr_txrd rx_wr_tx_rd;
+	struct fcoe_task_ctx_entry_rx_only rx_wr;
+	u32 reserved;
+};
+
+/*
+ * Ustorm FCoE Storm Context
+ */
+struct ustorm_fcoe_st_context {
+	struct ustorm_fcoe_params fcoe_params;
+	struct regpair task_addr;
+	struct regpair cq_base_addr;
+	struct regpair rq_pbl_base;
+	struct regpair rq_cur_page_addr;
+	struct regpair confq_pbl_base_addr;
+	struct regpair conn_db_base;
+	struct regpair xfrq_base_addr;
+	struct regpair lcq_base_addr;
+#if defined(__BIG_ENDIAN)
+	union fcoe_idx16_field_union rq_cons;
+	union fcoe_idx16_field_union rq_prod;
+#elif defined(__LITTLE_ENDIAN)
+	union fcoe_idx16_field_union rq_prod;
+	union fcoe_idx16_field_union rq_cons;
+#endif
+#if defined(__BIG_ENDIAN)
+	u16 xfrq_prod;
+	u16 cq_cons;
+#elif defined(__LITTLE_ENDIAN)
+	u16 cq_cons;
+	u16 xfrq_prod;
+#endif
+#if defined(__BIG_ENDIAN)
+	u16 lcq_cons;
+	u16 hc_cram_address;
+#elif defined(__LITTLE_ENDIAN)
+	u16 hc_cram_address;
+	u16 lcq_cons;
+#endif
+#if defined(__BIG_ENDIAN)
+	u16 sq_xfrq_lcq_confq_size;
+	u16 confq_prod;
+#elif defined(__LITTLE_ENDIAN)
+	u16 confq_prod;
+	u16 sq_xfrq_lcq_confq_size;
+#endif
+#if defined(__BIG_ENDIAN)
+	u8 hc_csdm_agg_int;
+	u8 flags;
+#define USTORM_FCOE_ST_CONTEXT_MID_SEQ_PROC_FLAG (0x1<<0)
+#define USTORM_FCOE_ST_CONTEXT_MID_SEQ_PROC_FLAG_SHIFT 0
+#define USTORM_FCOE_ST_CONTEXT_CACHED_CONN_FLAG (0x1<<1)
+#define USTORM_FCOE_ST_CONTEXT_CACHED_CONN_FLAG_SHIFT 1
+#define USTORM_FCOE_ST_CONTEXT_CACHED_TCE_FLAG (0x1<<2)
+#define USTORM_FCOE_ST_CONTEXT_CACHED_TCE_FLAG_SHIFT 2
+#define USTORM_FCOE_ST_CONTEXT_RSRV1 (0x1F<<3)
+#define USTORM_FCOE_ST_CONTEXT_RSRV1_SHIFT 3
+	u8 available_rqes;
+	u8 sp_q_flush_cnt;
+#elif defined(__LITTLE_ENDIAN)
+	u8 sp_q_flush_cnt;
+	u8 available_rqes;
+	u8 flags;
+#define USTORM_FCOE_ST_CONTEXT_MID_SEQ_PROC_FLAG (0x1<<0)
+#define USTORM_FCOE_ST_CONTEXT_MID_SEQ_PROC_FLAG_SHIFT 0
+#define USTORM_FCOE_ST_CONTEXT_CACHED_CONN_FLAG (0x1<<1)
+#define USTORM_FCOE_ST_CONTEXT_CACHED_CONN_FLAG_SHIFT 1
+#define USTORM_FCOE_ST_CONTEXT_CACHED_TCE_FLAG (0x1<<2)
+#define USTORM_FCOE_ST_CONTEXT_CACHED_TCE_FLAG_SHIFT 2
+#define USTORM_FCOE_ST_CONTEXT_RSRV1 (0x1F<<3)
+#define USTORM_FCOE_ST_CONTEXT_RSRV1_SHIFT 3
+	u8 hc_csdm_agg_int;
+#endif
+	struct ustorm_fcoe_data_place data_place;
+	struct ustorm_fcoe_task_ctx_entry_rd tce;
+};
+
+/*
+ * The FCoE non-aggregative context of Tstorm
+ */
+struct tstorm_fcoe_st_context {
+	struct regpair reserved0;
+	struct regpair reserved1;
+};
+
+/*
+ * The fcoe aggregative context section of Xstorm
+ */
+struct xstorm_fcoe_extra_ag_context_section {
+#if defined(__BIG_ENDIAN)
+	u8 tcp_agg_vars1;
+#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED51 (0x3<<0)
+#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED51_SHIFT 0
+#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_ACK_TO_FE_UPDATED (0x3<<2)
+#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_ACK_TO_FE_UPDATED_SHIFT 2
+#define XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_PBF_TX_SEQ_ACK_CF (0x3<<4)
+#define XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_PBF_TX_SEQ_ACK_CF_SHIFT 4
+#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED_CLEAR_DA_TIMER_EN (0x1<<6)
+#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED_CLEAR_DA_TIMER_EN_SHIFT 6
+#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED_DA_EXPIRATION_FLAG (0x1<<7)
+#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED_DA_EXPIRATION_FLAG_SHIFT 7
+	u8 __reserved_da_cnt;
+	u16 __mtu;
+#elif defined(__LITTLE_ENDIAN)
+	u16 __mtu;
+	u8 __reserved_da_cnt;
+	u8 tcp_agg_vars1;
+#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED51 (0x3<<0)
+#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED51_SHIFT 0
+#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_ACK_TO_FE_UPDATED (0x3<<2)
+#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_ACK_TO_FE_UPDATED_SHIFT 2
+#define XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_PBF_TX_SEQ_ACK_CF (0x3<<4)
+#define XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_PBF_TX_SEQ_ACK_CF_SHIFT 4
+#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED_CLEAR_DA_TIMER_EN (0x1<<6)
+#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED_CLEAR_DA_TIMER_EN_SHIFT 6
+#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED_DA_EXPIRATION_FLAG (0x1<<7)
+#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED_DA_EXPIRATION_FLAG_SHIFT 7
+#endif
+	u32 __task_addr_lo;
+	u32 __task_addr_hi;
+	u32 __reserved55;
+	u32 __tx_prods;
+#if defined(__BIG_ENDIAN)
+	u8 __agg_val8_th;
+	u8 __agg_val8;
+	u16 tcp_agg_vars2;
+#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED57 (0x1<<0)
+#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED57_SHIFT 0
+#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED58 (0x1<<1)
+#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED58_SHIFT 1
+#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED59 (0x1<<2)
+#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED59_SHIFT 2
+#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX3_FLAG (0x1<<3)
+#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX3_FLAG_SHIFT 3
+#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX4_FLAG (0x1<<4)
+#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX4_FLAG_SHIFT 4
+#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED60 (0x1<<5)
+#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED60_SHIFT 5
+#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED_ACK_TO_FE_UPDATED_EN (0x1<<6)
+#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED_ACK_TO_FE_UPDATED_EN_SHIFT 6
+#define XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_PBF_TX_SEQ_ACK_CF_EN (0x1<<7)
+#define XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_PBF_TX_SEQ_ACK_CF_EN_SHIFT 7
+#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED_TX_FIN_FLAG_EN (0x1<<8)
+#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED_TX_FIN_FLAG_EN_SHIFT 8
+#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX1_FLAG (0x1<<9)
+#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX1_FLAG_SHIFT 9
+#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_SET_RTO_CF (0x3<<10)
+#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_SET_RTO_CF_SHIFT 10
+#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_TS_TO_ECHO_UPDATED_CF (0x3<<12)
+#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_TS_TO_ECHO_UPDATED_CF_SHIFT 12
+#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX8_CF (0x3<<14)
+#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX8_CF_SHIFT 14
+#elif defined(__LITTLE_ENDIAN)
+	u16 tcp_agg_vars2;
+#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED57 (0x1<<0)
+#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED57_SHIFT 0
+#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED58 (0x1<<1)
+#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED58_SHIFT 1
+#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED59 (0x1<<2)
+#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED59_SHIFT 2
+#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX3_FLAG (0x1<<3)
+#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX3_FLAG_SHIFT 3
+#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX4_FLAG (0x1<<4)
+#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX4_FLAG_SHIFT 4
+#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED60 (0x1<<5)
+#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED60_SHIFT 5
+#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED_ACK_TO_FE_UPDATED_EN (0x1<<6)
+#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED_ACK_TO_FE_UPDATED_EN_SHIFT 6
+#define XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_PBF_TX_SEQ_ACK_CF_EN (0x1<<7)
+#define XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_PBF_TX_SEQ_ACK_CF_EN_SHIFT 7
+#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED_TX_FIN_FLAG_EN (0x1<<8)
+#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED_TX_FIN_FLAG_EN_SHIFT 8
+#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX1_FLAG (0x1<<9)
+#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX1_FLAG_SHIFT 9
+#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_SET_RTO_CF (0x3<<10)
+#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_SET_RTO_CF_SHIFT 10
+#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_TS_TO_ECHO_UPDATED_CF (0x3<<12)
+#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_TS_TO_ECHO_UPDATED_CF_SHIFT 12
+#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX8_CF (0x3<<14)
+#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX8_CF_SHIFT 14
+	u8 __agg_val8;
+	u8 __agg_val8_th;
+#endif
+	u32 __sq_base_addr_lo;
+	u32 __sq_base_addr_hi;
+	u32 __xfrq_base_addr_lo;
+	u32 __xfrq_base_addr_hi;
+#if defined(__BIG_ENDIAN)
+	u16 __xfrq_cons;
+	u16 __xfrq_prod;
+#elif defined(__LITTLE_ENDIAN)
+	u16 __xfrq_prod;
+	u16 __xfrq_cons;
+#endif
+#if defined(__BIG_ENDIAN)
+	u8 __tcp_agg_vars5;
+	u8 __tcp_agg_vars4;
+	u8 __tcp_agg_vars3;
+	u8 __reserved_force_pure_ack_cnt;
+#elif defined(__LITTLE_ENDIAN)
+	u8 __reserved_force_pure_ack_cnt;
+	u8 __tcp_agg_vars3;
+	u8 __tcp_agg_vars4;
+	u8 __tcp_agg_vars5;
+#endif
+	u32 __tcp_agg_vars6;
+#if defined(__BIG_ENDIAN)
+	u16 __agg_misc6;
+	u16 __tcp_agg_vars7;
+#elif defined(__LITTLE_ENDIAN)
+	u16 __tcp_agg_vars7;
+	u16 __agg_misc6;
+#endif
+	u32 __agg_val10;
+	u32 __agg_val10_th;
+#if defined(__BIG_ENDIAN)
+	u16 __reserved3;
+	u8 __reserved2;
+	u8 __da_only_cnt;
+#elif defined(__LITTLE_ENDIAN)
+	u8 __da_only_cnt;
+	u8 __reserved2;
+	u16 __reserved3;
+#endif
+};
+
+/*
+ * The fcoe aggregative context of Xstorm
+ */
+struct xstorm_fcoe_ag_context {
+#if defined(__BIG_ENDIAN)
+	u16 agg_val1;
+	u8 agg_vars1;
+#define __XSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM0 (0x1<<0)
+#define __XSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM0_SHIFT 0
+#define __XSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM1 (0x1<<1)
+#define __XSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM1_SHIFT 1
+#define __XSTORM_FCOE_AG_CONTEXT_RESERVED51 (0x1<<2)
+#define __XSTORM_FCOE_AG_CONTEXT_RESERVED51_SHIFT 2
+#define __XSTORM_FCOE_AG_CONTEXT_RESERVED52 (0x1<<3)
+#define __XSTORM_FCOE_AG_CONTEXT_RESERVED52_SHIFT 3
+#define __XSTORM_FCOE_AG_CONTEXT_MORE_TO_SEND_EN (0x1<<4)
+#define __XSTORM_FCOE_AG_CONTEXT_MORE_TO_SEND_EN_SHIFT 4
+#define XSTORM_FCOE_AG_CONTEXT_NAGLE_EN (0x1<<5)
+#define XSTORM_FCOE_AG_CONTEXT_NAGLE_EN_SHIFT 5
+#define __XSTORM_FCOE_AG_CONTEXT_DQ_SPARE_FLAG (0x1<<6)
+#define __XSTORM_FCOE_AG_CONTEXT_DQ_SPARE_FLAG_SHIFT 6
+#define __XSTORM_FCOE_AG_CONTEXT_RESERVED_UNA_GT_NXT_EN (0x1<<7)
+#define __XSTORM_FCOE_AG_CONTEXT_RESERVED_UNA_GT_NXT_EN_SHIFT 7
+	u8 __state;
+#elif defined(__LITTLE_ENDIAN)
+	u8 __state;
+	u8 agg_vars1;
+#define __XSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM0 (0x1<<0)
+#define __XSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM0_SHIFT 0
+#define __XSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM1 (0x1<<1)
+#define __XSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM1_SHIFT 1
+#define __XSTORM_FCOE_AG_CONTEXT_RESERVED51 (0x1<<2)
+#define __XSTORM_FCOE_AG_CONTEXT_RESERVED51_SHIFT 2
+#define __XSTORM_FCOE_AG_CONTEXT_RESERVED52 (0x1<<3)
+#define __XSTORM_FCOE_AG_CONTEXT_RESERVED52_SHIFT 3
+#define __XSTORM_FCOE_AG_CONTEXT_MORE_TO_SEND_EN (0x1<<4)
+#define __XSTORM_FCOE_AG_CONTEXT_MORE_TO_SEND_EN_SHIFT 4
+#define XSTORM_FCOE_AG_CONTEXT_NAGLE_EN (0x1<<5)
+#define XSTORM_FCOE_AG_CONTEXT_NAGLE_EN_SHIFT 5
+#define __XSTORM_FCOE_AG_CONTEXT_DQ_SPARE_FLAG (0x1<<6)
+#define __XSTORM_FCOE_AG_CONTEXT_DQ_SPARE_FLAG_SHIFT 6
+#define __XSTORM_FCOE_AG_CONTEXT_RESERVED_UNA_GT_NXT_EN (0x1<<7)
+#define __XSTORM_FCOE_AG_CONTEXT_RESERVED_UNA_GT_NXT_EN_SHIFT 7
+	u16 agg_val1;
+#endif
+#if defined(__BIG_ENDIAN)
+	u8 cdu_reserved;
+	u8 __agg_vars4;
+	u8 agg_vars3;
+#define XSTORM_FCOE_AG_CONTEXT_PHYSICAL_QUEUE_NUM2 (0x3F<<0)
+#define XSTORM_FCOE_AG_CONTEXT_PHYSICAL_QUEUE_NUM2_SHIFT 0
+#define __XSTORM_FCOE_AG_CONTEXT_AUX19_CF (0x3<<6)
+#define __XSTORM_FCOE_AG_CONTEXT_AUX19_CF_SHIFT 6
+	u8 agg_vars2;
+#define __XSTORM_FCOE_AG_CONTEXT_DQ_CF (0x3<<0)
+#define __XSTORM_FCOE_AG_CONTEXT_DQ_CF_SHIFT 0
+#define __XSTORM_FCOE_AG_CONTEXT_DQ_SPARE_FLAG_EN (0x1<<2)
+#define __XSTORM_FCOE_AG_CONTEXT_DQ_SPARE_FLAG_EN_SHIFT 2
+#define __XSTORM_FCOE_AG_CONTEXT_AUX8_FLAG (0x1<<3)
+#define __XSTORM_FCOE_AG_CONTEXT_AUX8_FLAG_SHIFT 3
+#define __XSTORM_FCOE_AG_CONTEXT_AUX9_FLAG (0x1<<4)
+#define __XSTORM_FCOE_AG_CONTEXT_AUX9_FLAG_SHIFT 4
+#define XSTORM_FCOE_AG_CONTEXT_DECISION_RULE1 (0x3<<5)
+#define XSTORM_FCOE_AG_CONTEXT_DECISION_RULE1_SHIFT 5
+#define __XSTORM_FCOE_AG_CONTEXT_DQ_CF_EN (0x1<<7)
+#define __XSTORM_FCOE_AG_CONTEXT_DQ_CF_EN_SHIFT 7
+#elif defined(__LITTLE_ENDIAN)
+	u8 agg_vars2;
+#define __XSTORM_FCOE_AG_CONTEXT_DQ_CF (0x3<<0)
+#define __XSTORM_FCOE_AG_CONTEXT_DQ_CF_SHIFT 0
+#define __XSTORM_FCOE_AG_CONTEXT_DQ_SPARE_FLAG_EN (0x1<<2)
+#define __XSTORM_FCOE_AG_CONTEXT_DQ_SPARE_FLAG_EN_SHIFT 2
+#define __XSTORM_FCOE_AG_CONTEXT_AUX8_FLAG (0x1<<3)
+#define __XSTORM_FCOE_AG_CONTEXT_AUX8_FLAG_SHIFT 3
+#define __XSTORM_FCOE_AG_CONTEXT_AUX9_FLAG (0x1<<4)
+#define __XSTORM_FCOE_AG_CONTEXT_AUX9_FLAG_SHIFT 4
+#define XSTORM_FCOE_AG_CONTEXT_DECISION_RULE1 (0x3<<5)
+#define XSTORM_FCOE_AG_CONTEXT_DECISION_RULE1_SHIFT 5
+#define __XSTORM_FCOE_AG_CONTEXT_DQ_CF_EN (0x1<<7)
+#define __XSTORM_FCOE_AG_CONTEXT_DQ_CF_EN_SHIFT 7
+	u8 agg_vars3;
+#define XSTORM_FCOE_AG_CONTEXT_PHYSICAL_QUEUE_NUM2 (0x3F<<0)
+#define XSTORM_FCOE_AG_CONTEXT_PHYSICAL_QUEUE_NUM2_SHIFT 0
+#define __XSTORM_FCOE_AG_CONTEXT_AUX19_CF (0x3<<6)
+#define __XSTORM_FCOE_AG_CONTEXT_AUX19_CF_SHIFT 6
+	u8 __agg_vars4;
+	u8 cdu_reserved;
+#endif
+	u32 more_to_send;
+#if defined(__BIG_ENDIAN)
+	u16 agg_vars5;
+#define XSTORM_FCOE_AG_CONTEXT_DECISION_RULE5 (0x3<<0)
+#define XSTORM_FCOE_AG_CONTEXT_DECISION_RULE5_SHIFT 0
+#define XSTORM_FCOE_AG_CONTEXT_PHYSICAL_QUEUE_NUM0 (0x3F<<2)
+#define XSTORM_FCOE_AG_CONTEXT_PHYSICAL_QUEUE_NUM0_SHIFT 2
+#define XSTORM_FCOE_AG_CONTEXT_PHYSICAL_QUEUE_NUM1 (0x3F<<8)
+#define XSTORM_FCOE_AG_CONTEXT_PHYSICAL_QUEUE_NUM1_SHIFT 8
+#define __XSTORM_FCOE_AG_CONTEXT_CONFQ_DEC_RULE (0x3<<14)
+#define __XSTORM_FCOE_AG_CONTEXT_CONFQ_DEC_RULE_SHIFT 14
+	u16 sq_cons;
+#elif defined(__LITTLE_ENDIAN)
+	u16 sq_cons;
+	u16 agg_vars5;
+#define XSTORM_FCOE_AG_CONTEXT_DECISION_RULE5 (0x3<<0)
+#define XSTORM_FCOE_AG_CONTEXT_DECISION_RULE5_SHIFT 0
+#define XSTORM_FCOE_AG_CONTEXT_PHYSICAL_QUEUE_NUM0 (0x3F<<2)
+#define XSTORM_FCOE_AG_CONTEXT_PHYSICAL_QUEUE_NUM0_SHIFT 2
+#define XSTORM_FCOE_AG_CONTEXT_PHYSICAL_QUEUE_NUM1 (0x3F<<8)
+#define XSTORM_FCOE_AG_CONTEXT_PHYSICAL_QUEUE_NUM1_SHIFT 8
+#define __XSTORM_FCOE_AG_CONTEXT_CONFQ_DEC_RULE (0x3<<14)
+#define __XSTORM_FCOE_AG_CONTEXT_CONFQ_DEC_RULE_SHIFT 14
+#endif
+	struct xstorm_fcoe_extra_ag_context_section __extra_section;
+#if defined(__BIG_ENDIAN)
+	u16 agg_vars7;
+#define __XSTORM_FCOE_AG_CONTEXT_AGG_VAL11_DECISION_RULE (0x7<<0)
+#define __XSTORM_FCOE_AG_CONTEXT_AGG_VAL11_DECISION_RULE_SHIFT 0
+#define __XSTORM_FCOE_AG_CONTEXT_AUX13_FLAG (0x1<<3)
+#define __XSTORM_FCOE_AG_CONTEXT_AUX13_FLAG_SHIFT 3
+#define __XSTORM_FCOE_AG_CONTEXT_QUEUE0_CF (0x3<<4)
+#define __XSTORM_FCOE_AG_CONTEXT_QUEUE0_CF_SHIFT 4
+#define XSTORM_FCOE_AG_CONTEXT_DECISION_RULE3 (0x3<<6)
+#define XSTORM_FCOE_AG_CONTEXT_DECISION_RULE3_SHIFT 6
+#define XSTORM_FCOE_AG_CONTEXT_AUX1_CF (0x3<<8)
+#define XSTORM_FCOE_AG_CONTEXT_AUX1_CF_SHIFT 8
+#define __XSTORM_FCOE_AG_CONTEXT_RESERVED62 (0x1<<10)
+#define __XSTORM_FCOE_AG_CONTEXT_RESERVED62_SHIFT 10
+#define __XSTORM_FCOE_AG_CONTEXT_AUX1_CF_EN (0x1<<11)
+#define __XSTORM_FCOE_AG_CONTEXT_AUX1_CF_EN_SHIFT 11
+#define __XSTORM_FCOE_AG_CONTEXT_AUX10_FLAG (0x1<<12)
+#define __XSTORM_FCOE_AG_CONTEXT_AUX10_FLAG_SHIFT 12
+#define __XSTORM_FCOE_AG_CONTEXT_AUX11_FLAG (0x1<<13)
+#define __XSTORM_FCOE_AG_CONTEXT_AUX11_FLAG_SHIFT 13
+#define __XSTORM_FCOE_AG_CONTEXT_AUX12_FLAG (0x1<<14)
+#define __XSTORM_FCOE_AG_CONTEXT_AUX12_FLAG_SHIFT 14
+#define __XSTORM_FCOE_AG_CONTEXT_AUX2_FLAG (0x1<<15)
+#define __XSTORM_FCOE_AG_CONTEXT_AUX2_FLAG_SHIFT 15
+	u8 agg_val3_th;
+	u8 agg_vars6;
+#define XSTORM_FCOE_AG_CONTEXT_DECISION_RULE6 (0x7<<0)
+#define XSTORM_FCOE_AG_CONTEXT_DECISION_RULE6_SHIFT 0
+#define __XSTORM_FCOE_AG_CONTEXT_XFRQ_DEC_RULE (0x7<<3)
+#define __XSTORM_FCOE_AG_CONTEXT_XFRQ_DEC_RULE_SHIFT 3
+#define __XSTORM_FCOE_AG_CONTEXT_SQ_DEC_RULE (0x3<<6)
+#define __XSTORM_FCOE_AG_CONTEXT_SQ_DEC_RULE_SHIFT 6
+#elif defined(__LITTLE_ENDIAN)
+	u8 agg_vars6;
+#define XSTORM_FCOE_AG_CONTEXT_DECISION_RULE6 (0x7<<0)
+#define XSTORM_FCOE_AG_CONTEXT_DECISION_RULE6_SHIFT 0
+#define __XSTORM_FCOE_AG_CONTEXT_XFRQ_DEC_RULE (0x7<<3)
+#define __XSTORM_FCOE_AG_CONTEXT_XFRQ_DEC_RULE_SHIFT 3
+#define __XSTORM_FCOE_AG_CONTEXT_SQ_DEC_RULE (0x3<<6)
+#define __XSTORM_FCOE_AG_CONTEXT_SQ_DEC_RULE_SHIFT 6
+	u8 agg_val3_th;
+	u16 agg_vars7;
+#define __XSTORM_FCOE_AG_CONTEXT_AGG_VAL11_DECISION_RULE (0x7<<0)
+#define __XSTORM_FCOE_AG_CONTEXT_AGG_VAL11_DECISION_RULE_SHIFT 0
+#define __XSTORM_FCOE_AG_CONTEXT_AUX13_FLAG (0x1<<3)
+#define __XSTORM_FCOE_AG_CONTEXT_AUX13_FLAG_SHIFT 3
+#define __XSTORM_FCOE_AG_CONTEXT_QUEUE0_CF (0x3<<4)
+#define __XSTORM_FCOE_AG_CONTEXT_QUEUE0_CF_SHIFT 4
+#define XSTORM_FCOE_AG_CONTEXT_DECISION_RULE3 (0x3<<6)
+#define XSTORM_FCOE_AG_CONTEXT_DECISION_RULE3_SHIFT 6
+#define XSTORM_FCOE_AG_CONTEXT_AUX1_CF (0x3<<8)
+#define XSTORM_FCOE_AG_CONTEXT_AUX1_CF_SHIFT 8
+#define __XSTORM_FCOE_AG_CONTEXT_RESERVED62 (0x1<<10)
+#define __XSTORM_FCOE_AG_CONTEXT_RESERVED62_SHIFT 10
+#define __XSTORM_FCOE_AG_CONTEXT_AUX1_CF_EN (0x1<<11)
+#define __XSTORM_FCOE_AG_CONTEXT_AUX1_CF_EN_SHIFT 11
+#define __XSTORM_FCOE_AG_CONTEXT_AUX10_FLAG (0x1<<12)
+#define __XSTORM_FCOE_AG_CONTEXT_AUX10_FLAG_SHIFT 12
+#define __XSTORM_FCOE_AG_CONTEXT_AUX11_FLAG (0x1<<13)
+#define __XSTORM_FCOE_AG_CONTEXT_AUX11_FLAG_SHIFT 13
+#define __XSTORM_FCOE_AG_CONTEXT_AUX12_FLAG (0x1<<14)
+#define __XSTORM_FCOE_AG_CONTEXT_AUX12_FLAG_SHIFT 14
+#define __XSTORM_FCOE_AG_CONTEXT_AUX2_FLAG (0x1<<15)
+#define __XSTORM_FCOE_AG_CONTEXT_AUX2_FLAG_SHIFT 15
+#endif
+#if defined(__BIG_ENDIAN)
+	u16 __agg_val11_th;
+	u16 __agg_val11;
+#elif defined(__LITTLE_ENDIAN)
+	u16 __agg_val11;
+	u16 __agg_val11_th;
+#endif
+#if defined(__BIG_ENDIAN)
+	u8 __reserved1;
+	u8 __agg_val6_th;
+	u16 __confq_tx_prod;
+#elif defined(__LITTLE_ENDIAN)
+	u16 __confq_tx_prod;
+	u8 __agg_val6_th;
+	u8 __reserved1;
+#endif
+#if defined(__BIG_ENDIAN)
+	u16 confq_cons;
+	u16 confq_prod;
+#elif defined(__LITTLE_ENDIAN)
+	u16 confq_prod;
+	u16 confq_cons;
+#endif
+	u32 agg_vars8;
+#define __XSTORM_FCOE_AG_CONTEXT_CACHE_WQE_IDX (0xFFFFFF<<0)
+#define __XSTORM_FCOE_AG_CONTEXT_CACHE_WQE_IDX_SHIFT 0
+#define XSTORM_FCOE_AG_CONTEXT_AGG_MISC3 (0xFF<<24)
+#define XSTORM_FCOE_AG_CONTEXT_AGG_MISC3_SHIFT 24
+#if defined(__BIG_ENDIAN)
+	u16 ox_id;
+	u16 sq_prod;
+#elif defined(__LITTLE_ENDIAN)
+	u16 sq_prod;
+	u16 ox_id;
+#endif
+#if defined(__BIG_ENDIAN)
+	u8 agg_val3;
+	u8 agg_val6;
+	u8 agg_val5_th;
+	u8 agg_val5;
+#elif defined(__LITTLE_ENDIAN)
+	u8 agg_val5;
+	u8 agg_val5_th;
+	u8 agg_val6;
+	u8 agg_val3;
+#endif
+#if defined(__BIG_ENDIAN)
+	u16 __pbf_tx_seq_ack;
+	u16 agg_limit1;
+#elif defined(__LITTLE_ENDIAN)
+	u16 agg_limit1;
+	u16 __pbf_tx_seq_ack;
+#endif
+	u32 completion_seq;
+	u32 confq_pbl_base_lo;
+	u32 confq_pbl_base_hi;
+};
+
+/*
+ * The fcoe extra aggregative context section of Tstorm
+ */
+struct tstorm_fcoe_extra_ag_context_section {
+	u32 __agg_val1;
+#if defined(__BIG_ENDIAN)
+	u8 __tcp_agg_vars2;
+	u8 __agg_val3;
+	u16 __agg_val2;
+#elif defined(__LITTLE_ENDIAN)
+	u16 __agg_val2;
+	u8 __agg_val3;
+	u8 __tcp_agg_vars2;
+#endif
+#if defined(__BIG_ENDIAN)
+	u16 __agg_val5;
+	u8 __agg_val6;
+	u8 __tcp_agg_vars3;
+#elif defined(__LITTLE_ENDIAN)
+	u8 __tcp_agg_vars3;
+	u8 __agg_val6;
+	u16 __agg_val5;
+#endif
+	u32 __lcq_prod;
+	u32 rtt_seq;
+	u32 rtt_time;
+	u32 __reserved66;
+	u32 wnd_right_edge;
+	u32 tcp_agg_vars1;
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_FIN_SENT_FLAG (0x1<<0)
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_FIN_SENT_FLAG_SHIFT 0
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_LAST_PACKET_FIN_FLAG (0x1<<1)
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_LAST_PACKET_FIN_FLAG_SHIFT 1
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_WND_UPD_CF (0x3<<2)
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_WND_UPD_CF_SHIFT 2
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_TIMEOUT_CF (0x3<<4)
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_TIMEOUT_CF_SHIFT 4
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_WND_UPD_CF_EN (0x1<<6)
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_WND_UPD_CF_EN_SHIFT 6
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_TIMEOUT_CF_EN (0x1<<7)
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_TIMEOUT_CF_EN_SHIFT 7
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RETRANSMIT_SEQ_EN (0x1<<8)
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RETRANSMIT_SEQ_EN_SHIFT 8
+#define __TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_LCQ_SND_EN (0x1<<9)
+#define __TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_LCQ_SND_EN_SHIFT 9
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX1_FLAG (0x1<<10)
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX1_FLAG_SHIFT 10
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX2_FLAG (0x1<<11)
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX2_FLAG_SHIFT 11
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX1_CF_EN (0x1<<12)
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX1_CF_EN_SHIFT 12
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX2_CF_EN (0x1<<13)
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX2_CF_EN_SHIFT 13
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX1_CF (0x3<<14)
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX1_CF_SHIFT 14
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX2_CF (0x3<<16)
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX2_CF_SHIFT 16
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_TX_BLOCKED (0x1<<18)
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_TX_BLOCKED_SHIFT 18
+#define __TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX10_CF_EN (0x1<<19)
+#define __TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX10_CF_EN_SHIFT 19
+#define __TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX11_CF_EN (0x1<<20)
+#define __TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX11_CF_EN_SHIFT 20
+#define __TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX12_CF_EN (0x1<<21)
+#define __TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX12_CF_EN_SHIFT 21
+#define __TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED1 (0x3<<22)
+#define __TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED1_SHIFT 22
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RETRANSMIT_PEND_SEQ (0xF<<24)
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RETRANSMIT_PEND_SEQ_SHIFT 24
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RETRANSMIT_DONE_SEQ (0xF<<28)
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RETRANSMIT_DONE_SEQ_SHIFT 28
+	u32 snd_max;
+	u32 __lcq_cons;
+	u32 __reserved2;
+};
+
+/*
+ * The fcoe aggregative context of Tstorm
+ */
+struct tstorm_fcoe_ag_context {
+#if defined(__BIG_ENDIAN)
+	u16 ulp_credit;
+	u8 agg_vars1;
+#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM0 (0x1<<0)
+#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM0_SHIFT 0
+#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM1 (0x1<<1)
+#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM1_SHIFT 1
+#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM2 (0x1<<2)
+#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM2_SHIFT 2
+#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM3 (0x1<<3)
+#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM3_SHIFT 3
+#define __TSTORM_FCOE_AG_CONTEXT_QUEUE0_FLUSH_CF (0x3<<4)
+#define __TSTORM_FCOE_AG_CONTEXT_QUEUE0_FLUSH_CF_SHIFT 4
+#define __TSTORM_FCOE_AG_CONTEXT_AUX3_FLAG (0x1<<6)
+#define __TSTORM_FCOE_AG_CONTEXT_AUX3_FLAG_SHIFT 6
+#define __TSTORM_FCOE_AG_CONTEXT_AUX4_FLAG (0x1<<7)
+#define __TSTORM_FCOE_AG_CONTEXT_AUX4_FLAG_SHIFT 7
+	u8 state;
+#elif defined(__LITTLE_ENDIAN)
+	u8 state;
+	u8 agg_vars1;
+#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM0 (0x1<<0)
+#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM0_SHIFT 0
+#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM1 (0x1<<1)
+#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM1_SHIFT 1
+#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM2 (0x1<<2)
+#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM2_SHIFT 2
+#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM3 (0x1<<3)
+#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM3_SHIFT 3
+#define __TSTORM_FCOE_AG_CONTEXT_QUEUE0_FLUSH_CF (0x3<<4)
+#define __TSTORM_FCOE_AG_CONTEXT_QUEUE0_FLUSH_CF_SHIFT 4
+#define __TSTORM_FCOE_AG_CONTEXT_AUX3_FLAG (0x1<<6)
+#define __TSTORM_FCOE_AG_CONTEXT_AUX3_FLAG_SHIFT 6
+#define __TSTORM_FCOE_AG_CONTEXT_AUX4_FLAG (0x1<<7)
+#define __TSTORM_FCOE_AG_CONTEXT_AUX4_FLAG_SHIFT 7
+	u16 ulp_credit;
+#endif
+#if defined(__BIG_ENDIAN)
+	u16 __agg_val4;
+	u16 agg_vars2;
+#define __TSTORM_FCOE_AG_CONTEXT_AUX5_FLAG (0x1<<0)
+#define __TSTORM_FCOE_AG_CONTEXT_AUX5_FLAG_SHIFT 0
+#define __TSTORM_FCOE_AG_CONTEXT_AUX6_FLAG (0x1<<1)
+#define __TSTORM_FCOE_AG_CONTEXT_AUX6_FLAG_SHIFT 1
+#define __TSTORM_FCOE_AG_CONTEXT_AUX4_CF (0x3<<2)
+#define __TSTORM_FCOE_AG_CONTEXT_AUX4_CF_SHIFT 2
+#define __TSTORM_FCOE_AG_CONTEXT_AUX5_CF (0x3<<4)
+#define __TSTORM_FCOE_AG_CONTEXT_AUX5_CF_SHIFT 4
+#define __TSTORM_FCOE_AG_CONTEXT_AUX6_CF (0x3<<6)
+#define __TSTORM_FCOE_AG_CONTEXT_AUX6_CF_SHIFT 6
+#define __TSTORM_FCOE_AG_CONTEXT_AUX7_CF (0x3<<8)
+#define __TSTORM_FCOE_AG_CONTEXT_AUX7_CF_SHIFT 8
+#define __TSTORM_FCOE_AG_CONTEXT_AUX7_FLAG (0x1<<10)
+#define __TSTORM_FCOE_AG_CONTEXT_AUX7_FLAG_SHIFT 10
+#define __TSTORM_FCOE_AG_CONTEXT_QUEUE0_FLUSH_CF_EN (0x1<<11)
+#define __TSTORM_FCOE_AG_CONTEXT_QUEUE0_FLUSH_CF_EN_SHIFT 11
+#define TSTORM_FCOE_AG_CONTEXT_AUX4_CF_EN (0x1<<12)
+#define TSTORM_FCOE_AG_CONTEXT_AUX4_CF_EN_SHIFT 12
+#define TSTORM_FCOE_AG_CONTEXT_AUX5_CF_EN (0x1<<13)
+#define TSTORM_FCOE_AG_CONTEXT_AUX5_CF_EN_SHIFT 13
+#define TSTORM_FCOE_AG_CONTEXT_AUX6_CF_EN (0x1<<14)
+#define TSTORM_FCOE_AG_CONTEXT_AUX6_CF_EN_SHIFT 14
+#define TSTORM_FCOE_AG_CONTEXT_AUX7_CF_EN (0x1<<15)
+#define TSTORM_FCOE_AG_CONTEXT_AUX7_CF_EN_SHIFT 15
+#elif defined(__LITTLE_ENDIAN)
+	u16 agg_vars2;
+#define __TSTORM_FCOE_AG_CONTEXT_AUX5_FLAG (0x1<<0)
+#define __TSTORM_FCOE_AG_CONTEXT_AUX5_FLAG_SHIFT 0
+#define __TSTORM_FCOE_AG_CONTEXT_AUX6_FLAG (0x1<<1)
+#define __TSTORM_FCOE_AG_CONTEXT_AUX6_FLAG_SHIFT 1
+#define __TSTORM_FCOE_AG_CONTEXT_AUX4_CF (0x3<<2)
+#define __TSTORM_FCOE_AG_CONTEXT_AUX4_CF_SHIFT 2
+#define __TSTORM_FCOE_AG_CONTEXT_AUX5_CF (0x3<<4)
+#define __TSTORM_FCOE_AG_CONTEXT_AUX5_CF_SHIFT 4
+#define __TSTORM_FCOE_AG_CONTEXT_AUX6_CF (0x3<<6)
+#define __TSTORM_FCOE_AG_CONTEXT_AUX6_CF_SHIFT 6
+#define __TSTORM_FCOE_AG_CONTEXT_AUX7_CF (0x3<<8)
+#define __TSTORM_FCOE_AG_CONTEXT_AUX7_CF_SHIFT 8
+#define __TSTORM_FCOE_AG_CONTEXT_AUX7_FLAG (0x1<<10)
+#define __TSTORM_FCOE_AG_CONTEXT_AUX7_FLAG_SHIFT 10
+#define __TSTORM_FCOE_AG_CONTEXT_QUEUE0_FLUSH_CF_EN (0x1<<11)
+#define __TSTORM_FCOE_AG_CONTEXT_QUEUE0_FLUSH_CF_EN_SHIFT 11
+#define TSTORM_FCOE_AG_CONTEXT_AUX4_CF_EN (0x1<<12)
+#define TSTORM_FCOE_AG_CONTEXT_AUX4_CF_EN_SHIFT 12
+#define TSTORM_FCOE_AG_CONTEXT_AUX5_CF_EN (0x1<<13)
+#define TSTORM_FCOE_AG_CONTEXT_AUX5_CF_EN_SHIFT 13
+#define TSTORM_FCOE_AG_CONTEXT_AUX6_CF_EN (0x1<<14)
+#define TSTORM_FCOE_AG_CONTEXT_AUX6_CF_EN_SHIFT 14
+#define TSTORM_FCOE_AG_CONTEXT_AUX7_CF_EN (0x1<<15)
+#define TSTORM_FCOE_AG_CONTEXT_AUX7_CF_EN_SHIFT 15
+	u16 __agg_val4;
+#endif
+	struct tstorm_fcoe_extra_ag_context_section __extra_section;
+};
+
+/*
+ * The fcoe aggregative context of Ustorm
+ */
+struct ustorm_fcoe_ag_context {
+#if defined(__BIG_ENDIAN)
+	u8 __aux_counter_flags;
+	u8 agg_vars2;
+#define USTORM_FCOE_AG_CONTEXT_TX_CF (0x3<<0)
+#define USTORM_FCOE_AG_CONTEXT_TX_CF_SHIFT 0
+#define __USTORM_FCOE_AG_CONTEXT_TIMER_CF (0x3<<2)
+#define __USTORM_FCOE_AG_CONTEXT_TIMER_CF_SHIFT 2
+#define USTORM_FCOE_AG_CONTEXT_AGG_MISC4_RULE (0x7<<4)
+#define USTORM_FCOE_AG_CONTEXT_AGG_MISC4_RULE_SHIFT 4
+#define __USTORM_FCOE_AG_CONTEXT_AGG_VAL2_MASK (0x1<<7)
+#define __USTORM_FCOE_AG_CONTEXT_AGG_VAL2_MASK_SHIFT 7
+	u8 agg_vars1;
+#define __USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM0 (0x1<<0)
+#define __USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM0_SHIFT 0
+#define USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM1 (0x1<<1)
+#define USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM1_SHIFT 1
+#define USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM2 (0x1<<2)
+#define USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM2_SHIFT 2
+#define USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM3 (0x1<<3)
+#define USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM3_SHIFT 3
+#define USTORM_FCOE_AG_CONTEXT_INV_CF (0x3<<4)
+#define USTORM_FCOE_AG_CONTEXT_INV_CF_SHIFT 4
+#define USTORM_FCOE_AG_CONTEXT_COMPLETION_CF (0x3<<6)
+#define USTORM_FCOE_AG_CONTEXT_COMPLETION_CF_SHIFT 6
+	u8 state;
+#elif defined(__LITTLE_ENDIAN)
+	u8 state;
+	u8 agg_vars1;
+#define __USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM0 (0x1<<0)
+#define __USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM0_SHIFT 0
+#define USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM1 (0x1<<1)
+#define USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM1_SHIFT 1
+#define USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM2 (0x1<<2)
+#define USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM2_SHIFT 2
+#define USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM3 (0x1<<3)
+#define USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM3_SHIFT 3
+#define USTORM_FCOE_AG_CONTEXT_INV_CF (0x3<<4)
+#define USTORM_FCOE_AG_CONTEXT_INV_CF_SHIFT 4
+#define USTORM_FCOE_AG_CONTEXT_COMPLETION_CF (0x3<<6)
+#define USTORM_FCOE_AG_CONTEXT_COMPLETION_CF_SHIFT 6
+	u8 agg_vars2;
+#define USTORM_FCOE_AG_CONTEXT_TX_CF (0x3<<0)
+#define USTORM_FCOE_AG_CONTEXT_TX_CF_SHIFT 0
+#define __USTORM_FCOE_AG_CONTEXT_TIMER_CF (0x3<<2)
+#define __USTORM_FCOE_AG_CONTEXT_TIMER_CF_SHIFT 2
+#define USTORM_FCOE_AG_CONTEXT_AGG_MISC4_RULE (0x7<<4)
+#define USTORM_FCOE_AG_CONTEXT_AGG_MISC4_RULE_SHIFT 4
+#define __USTORM_FCOE_AG_CONTEXT_AGG_VAL2_MASK (0x1<<7)
+#define __USTORM_FCOE_AG_CONTEXT_AGG_VAL2_MASK_SHIFT 7
+	u8 __aux_counter_flags;
+#endif
+#if defined(__BIG_ENDIAN)
+	u8 cdu_usage;
+	u8 agg_misc2;
+	u16 pbf_tx_seq_ack;
+#elif defined(__LITTLE_ENDIAN)
+	u16 pbf_tx_seq_ack;
+	u8 agg_misc2;
+	u8 cdu_usage;
+#endif
+	u32 agg_misc4;
+#if defined(__BIG_ENDIAN)
+	u8 agg_val3_th;
+	u8 agg_val3;
+	u16 agg_misc3;
+#elif defined(__LITTLE_ENDIAN)
+	u16 agg_misc3;
+	u8 agg_val3;
+	u8 agg_val3_th;
+#endif
+	u32 expired_task_id;
+	u32 agg_misc4_th;
+#if defined(__BIG_ENDIAN)
+	u16 cq_prod;
+	u16 cq_cons;
+#elif defined(__LITTLE_ENDIAN)
+	u16 cq_cons;
+	u16 cq_prod;
+#endif
+#if defined(__BIG_ENDIAN)
+	u16 __reserved2;
+	u8 decision_rules;
+#define USTORM_FCOE_AG_CONTEXT_CQ_DEC_RULE (0x7<<0)
+#define USTORM_FCOE_AG_CONTEXT_CQ_DEC_RULE_SHIFT 0
+#define __USTORM_FCOE_AG_CONTEXT_AGG_VAL3_RULE (0x7<<3)
+#define __USTORM_FCOE_AG_CONTEXT_AGG_VAL3_RULE_SHIFT 3
+#define USTORM_FCOE_AG_CONTEXT_CQ_ARM_N_FLAG (0x1<<6)
+#define USTORM_FCOE_AG_CONTEXT_CQ_ARM_N_FLAG_SHIFT 6
+#define __USTORM_FCOE_AG_CONTEXT_RESERVED1 (0x1<<7)
+#define __USTORM_FCOE_AG_CONTEXT_RESERVED1_SHIFT 7
+	u8 decision_rule_enable_bits;
+#define __USTORM_FCOE_AG_CONTEXT_RESERVED_INV_CF_EN (0x1<<0)
+#define __USTORM_FCOE_AG_CONTEXT_RESERVED_INV_CF_EN_SHIFT 0
+#define USTORM_FCOE_AG_CONTEXT_COMPLETION_CF_EN (0x1<<1)
+#define USTORM_FCOE_AG_CONTEXT_COMPLETION_CF_EN_SHIFT 1
+#define USTORM_FCOE_AG_CONTEXT_TX_CF_EN (0x1<<2)
+#define USTORM_FCOE_AG_CONTEXT_TX_CF_EN_SHIFT 2
+#define __USTORM_FCOE_AG_CONTEXT_TIMER_CF_EN (0x1<<3)
+#define __USTORM_FCOE_AG_CONTEXT_TIMER_CF_EN_SHIFT 3
+#define __USTORM_FCOE_AG_CONTEXT_AUX1_CF_EN (0x1<<4)
+#define __USTORM_FCOE_AG_CONTEXT_AUX1_CF_EN_SHIFT 4
+#define __USTORM_FCOE_AG_CONTEXT_QUEUE0_CF_EN (0x1<<5)
+#define __USTORM_FCOE_AG_CONTEXT_QUEUE0_CF_EN_SHIFT 5
+#define __USTORM_FCOE_AG_CONTEXT_AUX3_CF_EN (0x1<<6)
+#define __USTORM_FCOE_AG_CONTEXT_AUX3_CF_EN_SHIFT 6
+#define __USTORM_FCOE_AG_CONTEXT_DQ_CF_EN (0x1<<7)
+#define __USTORM_FCOE_AG_CONTEXT_DQ_CF_EN_SHIFT 7
+#elif defined(__LITTLE_ENDIAN)
+	u8 decision_rule_enable_bits;
+#define __USTORM_FCOE_AG_CONTEXT_RESERVED_INV_CF_EN (0x1<<0)
+#define __USTORM_FCOE_AG_CONTEXT_RESERVED_INV_CF_EN_SHIFT 0
+#define USTORM_FCOE_AG_CONTEXT_COMPLETION_CF_EN (0x1<<1)
+#define USTORM_FCOE_AG_CONTEXT_COMPLETION_CF_EN_SHIFT 1
+#define USTORM_FCOE_AG_CONTEXT_TX_CF_EN (0x1<<2)
+#define USTORM_FCOE_AG_CONTEXT_TX_CF_EN_SHIFT 2
+#define __USTORM_FCOE_AG_CONTEXT_TIMER_CF_EN (0x1<<3)
+#define __USTORM_FCOE_AG_CONTEXT_TIMER_CF_EN_SHIFT 3
+#define __USTORM_FCOE_AG_CONTEXT_AUX1_CF_EN (0x1<<4)
+#define __USTORM_FCOE_AG_CONTEXT_AUX1_CF_EN_SHIFT 4
+#define __USTORM_FCOE_AG_CONTEXT_QUEUE0_CF_EN (0x1<<5)
+#define __USTORM_FCOE_AG_CONTEXT_QUEUE0_CF_EN_SHIFT 5
+#define __USTORM_FCOE_AG_CONTEXT_AUX3_CF_EN (0x1<<6)
+#define __USTORM_FCOE_AG_CONTEXT_AUX3_CF_EN_SHIFT 6
+#define __USTORM_FCOE_AG_CONTEXT_DQ_CF_EN (0x1<<7)
+#define __USTORM_FCOE_AG_CONTEXT_DQ_CF_EN_SHIFT 7
+	u8 decision_rules;
+#define USTORM_FCOE_AG_CONTEXT_CQ_DEC_RULE (0x7<<0)
+#define USTORM_FCOE_AG_CONTEXT_CQ_DEC_RULE_SHIFT 0
+#define __USTORM_FCOE_AG_CONTEXT_AGG_VAL3_RULE (0x7<<3)
+#define __USTORM_FCOE_AG_CONTEXT_AGG_VAL3_RULE_SHIFT 3
+#define USTORM_FCOE_AG_CONTEXT_CQ_ARM_N_FLAG (0x1<<6)
+#define USTORM_FCOE_AG_CONTEXT_CQ_ARM_N_FLAG_SHIFT 6
+#define __USTORM_FCOE_AG_CONTEXT_RESERVED1 (0x1<<7)
+#define __USTORM_FCOE_AG_CONTEXT_RESERVED1_SHIFT 7
+	u16 __reserved2;
+#endif
+};
+
+/*
+ * Ethernet context section
+ */
+struct xstorm_fcoe_eth_context_section {
+#if defined(__BIG_ENDIAN)
+	u8 remote_addr_4;
+	u8 remote_addr_5;
+	u8 local_addr_0;
+	u8 local_addr_1;
+#elif defined(__LITTLE_ENDIAN)
+	u8 local_addr_1;
+	u8 local_addr_0;
+	u8 remote_addr_5;
+	u8 remote_addr_4;
+#endif
+#if defined(__BIG_ENDIAN)
+	u8 remote_addr_0;
+	u8 remote_addr_1;
+	u8 remote_addr_2;
+	u8 remote_addr_3;
+#elif defined(__LITTLE_ENDIAN)
+	u8 remote_addr_3;
+	u8 remote_addr_2;
+	u8 remote_addr_1;
+	u8 remote_addr_0;
+#endif
+#if defined(__BIG_ENDIAN)
+	u16 reserved_vlan_type;
+	u16 params;
+#define XSTORM_FCOE_ETH_CONTEXT_SECTION_VLAN_ID (0xFFF<<0)
+#define XSTORM_FCOE_ETH_CONTEXT_SECTION_VLAN_ID_SHIFT 0
+#define XSTORM_FCOE_ETH_CONTEXT_SECTION_CFI (0x1<<12)
+#define XSTORM_FCOE_ETH_CONTEXT_SECTION_CFI_SHIFT 12
+#define XSTORM_FCOE_ETH_CONTEXT_SECTION_PRIORITY (0x7<<13)
+#define XSTORM_FCOE_ETH_CONTEXT_SECTION_PRIORITY_SHIFT 13
+#elif defined(__LITTLE_ENDIAN)
+	u16 params;
+#define XSTORM_FCOE_ETH_CONTEXT_SECTION_VLAN_ID (0xFFF<<0)
+#define XSTORM_FCOE_ETH_CONTEXT_SECTION_VLAN_ID_SHIFT 0
+#define XSTORM_FCOE_ETH_CONTEXT_SECTION_CFI (0x1<<12)
+#define XSTORM_FCOE_ETH_CONTEXT_SECTION_CFI_SHIFT 12
+#define XSTORM_FCOE_ETH_CONTEXT_SECTION_PRIORITY (0x7<<13)
+#define XSTORM_FCOE_ETH_CONTEXT_SECTION_PRIORITY_SHIFT 13
+	u16 reserved_vlan_type;
+#endif
+#if defined(__BIG_ENDIAN)
+	u8 local_addr_2;
+	u8 local_addr_3;
+	u8 local_addr_4;
+	u8 local_addr_5;
+#elif defined(__LITTLE_ENDIAN)
+	u8 local_addr_5;
+	u8 local_addr_4;
+	u8 local_addr_3;
+	u8 local_addr_2;
+#endif
+};
+
+/*
+ * Flags used in FCoE context section - 1 byte
+ */
+struct xstorm_fcoe_context_flags {
+	u8 flags;
+#define XSTORM_FCOE_CONTEXT_FLAGS_B_PROC_Q (0x3<<0)
+#define XSTORM_FCOE_CONTEXT_FLAGS_B_PROC_Q_SHIFT 0
+#define XSTORM_FCOE_CONTEXT_FLAGS_B_MID_SEQ (0x1<<2)
+#define XSTORM_FCOE_CONTEXT_FLAGS_B_MID_SEQ_SHIFT 2
+#define XSTORM_FCOE_CONTEXT_FLAGS_B_EXCHANGE_CLEANUP_DEFFERED (0x1<<3)
+#define XSTORM_FCOE_CONTEXT_FLAGS_B_EXCHANGE_CLEANUP_DEFFERED_SHIFT 3
+#define XSTORM_FCOE_CONTEXT_FLAGS_B_REC_SUPPORT (0x1<<4)
+#define XSTORM_FCOE_CONTEXT_FLAGS_B_REC_SUPPORT_SHIFT 4
+#define XSTORM_FCOE_CONTEXT_FLAGS_B_SQ_TOGGLE (0x1<<5)
+#define XSTORM_FCOE_CONTEXT_FLAGS_B_SQ_TOGGLE_SHIFT 5
+#define XSTORM_FCOE_CONTEXT_FLAGS_B_XFRQ_TOGGLE (0x1<<6)
+#define XSTORM_FCOE_CONTEXT_FLAGS_B_XFRQ_TOGGLE_SHIFT 6
+#define XSTORM_FCOE_CONTEXT_FLAGS_B_ABTS_DEFFERED (0x1<<7)
+#define XSTORM_FCOE_CONTEXT_FLAGS_B_ABTS_DEFFERED_SHIFT 7
+};
+
+/*
+ * FCoE SQ element
+ */
+struct fcoe_sqe {
+	u16 wqe;
+#define FCOE_SQE_TASK_ID (0x7FFF<<0)
+#define FCOE_SQE_TASK_ID_SHIFT 0
+#define FCOE_SQE_TOGGLE_BIT (0x1<<15)
+#define FCOE_SQE_TOGGLE_BIT_SHIFT 15
+};
+
+/*
+ * FCoE XFRQ element
+ */
+struct fcoe_xfrqe {
+	u16 wqe;
+#define FCOE_XFRQE_TASK_ID (0x7FFF<<0)
+#define FCOE_XFRQE_TASK_ID_SHIFT 0
+#define FCOE_XFRQE_TOGGLE_BIT (0x1<<15)
+#define FCOE_XFRQE_TOGGLE_BIT_SHIFT 15
+};
+
+/*
+ * FCoE SQ\XFRQ element
+ */
+struct fcoe_cached_wqe {
+#if defined(__BIG_ENDIAN)
+	struct fcoe_xfrqe xfrqe;
+	struct fcoe_sqe sqe;
+#elif defined(__LITTLE_ENDIAN)
+	struct fcoe_sqe sqe;
+	struct fcoe_xfrqe xfrqe;
+#endif
+};
+
+struct fcoe_task_ctx_entry_tx_only {
+	union fcoe_sgl_ctx sgl_ctx;
+};
+
+struct xstorm_fcoe_task_ctx_entry_rd {
+	struct fcoe_task_ctx_entry_tx_only tx_wr;
+	struct fcoe_task_ctx_entry_txwr_rxrd tx_wr_rx_rd;
+	struct fcoe_task_ctx_entry_tx_rx_cmn cmn;
+	struct fcoe_task_ctx_entry_rxwr_txrd rx_wr_tx_rd;
+};
+
+/*
+ * Cached SGEs
+ */
+struct common_fcoe_sgl {
+	struct fcoe_bd_ctx sge[2];
+};
+
+/*
+ * FCP_DATA parameters required for transmission
+ */
+struct xstorm_fcoe_fcp_data {
+	u32 io_rem;
+#if defined(__BIG_ENDIAN)
+	u16 cached_sge_off;
+	u8 cached_num_sges;
+	u8 cached_sge_idx;
+#elif defined(__LITTLE_ENDIAN)
+	u8 cached_sge_idx;
+	u8 cached_num_sges;
+	u16 cached_sge_off;
+#endif
+	struct common_fcoe_sgl cached_sgl;
+};
+
+/*
+ * FCoE context section
+ */
+struct xstorm_fcoe_context_section {
+#if defined(__BIG_ENDIAN)
+	u8 vlan_flag;
+	u8 s_id[3];
+#elif defined(__LITTLE_ENDIAN)
+	u8 s_id[3];
+	u8 vlan_flag;
+#endif
+#if defined(__BIG_ENDIAN)
+	u8 func_id;
+	u8 d_id[3];
+#elif defined(__LITTLE_ENDIAN)
+	u8 d_id[3];
+	u8 func_id;
+#endif
+#if defined(__BIG_ENDIAN)
+	u16 sq_xfrq_lcq_confq_size;
+	u16 tx_max_fc_pay_len;
+#elif defined(__LITTLE_ENDIAN)
+	u16 tx_max_fc_pay_len;
+	u16 sq_xfrq_lcq_confq_size;
+#endif
+	u32 lcq_prod;
+#if defined(__BIG_ENDIAN)
+	u8 port_id;
+	u8 tx_max_conc_seqs_c3;
+	u8 seq_id;
+	struct xstorm_fcoe_context_flags tx_flags;
+#elif defined(__LITTLE_ENDIAN)
+	struct xstorm_fcoe_context_flags tx_flags;
+	u8 seq_id;
+	u8 tx_max_conc_seqs_c3;
+	u8 port_id;
+#endif
+#if defined(__BIG_ENDIAN)
+	u16 verify_tx_seq;
+	u8 func_mode;
+	u8 vnic_id;
+#elif defined(__LITTLE_ENDIAN)
+	u8 vnic_id;
+	u8 func_mode;
+	u16 verify_tx_seq;
+#endif
+	struct regpair confq_curr_page_addr;
+	struct fcoe_cached_wqe cached_wqe[8];
+	struct regpair lcq_base_addr;
+	struct xstorm_fcoe_task_ctx_entry_rd tce;
+	struct xstorm_fcoe_fcp_data fcp_data;
+#if defined(__BIG_ENDIAN)
+	u16 fcoe_tx_stat_params_ram_addr;
+	u16 cmng_port_ram_addr;
+#elif defined(__LITTLE_ENDIAN)
+	u16 cmng_port_ram_addr;
+	u16 fcoe_tx_stat_params_ram_addr;
+#endif
+#if defined(__BIG_ENDIAN)
+	u8 fcp_cmd_pb_cmd_size;
+	u8 eth_hdr_size;
+	u16 pbf_addr;
+#elif defined(__LITTLE_ENDIAN)
+	u16 pbf_addr;
+	u8 eth_hdr_size;
+	u8 fcp_cmd_pb_cmd_size;
+#endif
+#if defined(__BIG_ENDIAN)
+	u8 reserved2[2];
+	u8 cos;
+	u8 dcb_version;
+#elif defined(__LITTLE_ENDIAN)
+	u8 dcb_version;
+	u8 cos;
+	u8 reserved2[2];
+#endif
+	u32 reserved3;
+	struct regpair reserved4[2];
+};
+
+/*
+ * Xstorm FCoE Storm Context
+ */
+struct xstorm_fcoe_st_context {
+	struct xstorm_fcoe_eth_context_section eth;
+	struct xstorm_fcoe_context_section fcoe;
+};
+
+/*
+ * Fcoe connection context
+ */
+struct fcoe_context {
+	struct ustorm_fcoe_st_context ustorm_st_context;
+	struct tstorm_fcoe_st_context tstorm_st_context;
+	struct xstorm_fcoe_ag_context xstorm_ag_context;
+	struct tstorm_fcoe_ag_context tstorm_ag_context;
+	struct ustorm_fcoe_ag_context ustorm_ag_context;
+	struct timers_block_context timers_context;
+	struct xstorm_fcoe_st_context xstorm_st_context;
+};
+
+/*
  * iSCSI context region, used only in iSCSI
  */
 struct ustorm_iscsi_rq_db {
@@ -2268,6 +3792,577 @@ struct iscsi_context {
 };
 
 /*
+ * FCoE KCQ CQE parameters
+ */
+union fcoe_kcqe_params {
+	u32 reserved0[4];
+};
+
+/*
+ * FCoE KCQ CQE
+ */
+struct fcoe_kcqe {
+	u32 fcoe_conn_id;
+	u32 completion_status;
+	u32 fcoe_conn_context_id;
+	union fcoe_kcqe_params params;
+#if defined(__BIG_ENDIAN)
+	u8 flags;
+#define FCOE_KCQE_RESERVED0 (0x7<<0)
+#define FCOE_KCQE_RESERVED0_SHIFT 0
+#define FCOE_KCQE_RAMROD_COMPLETION (0x1<<3)
+#define FCOE_KCQE_RAMROD_COMPLETION_SHIFT 3
+#define FCOE_KCQE_LAYER_CODE (0x7<<4)
+#define FCOE_KCQE_LAYER_CODE_SHIFT 4
+#define FCOE_KCQE_LINKED_WITH_NEXT (0x1<<7)
+#define FCOE_KCQE_LINKED_WITH_NEXT_SHIFT 7
+	u8 op_code;
+	u16 qe_self_seq;
+#elif defined(__LITTLE_ENDIAN)
+	u16 qe_self_seq;
+	u8 op_code;
+	u8 flags;
+#define FCOE_KCQE_RESERVED0 (0x7<<0)
+#define FCOE_KCQE_RESERVED0_SHIFT 0
+#define FCOE_KCQE_RAMROD_COMPLETION (0x1<<3)
+#define FCOE_KCQE_RAMROD_COMPLETION_SHIFT 3
+#define FCOE_KCQE_LAYER_CODE (0x7<<4)
+#define FCOE_KCQE_LAYER_CODE_SHIFT 4
+#define FCOE_KCQE_LINKED_WITH_NEXT (0x1<<7)
+#define FCOE_KCQE_LINKED_WITH_NEXT_SHIFT 7
+#endif
+};
+
+/*
+ * FCoE KWQE header
+ */
+struct fcoe_kwqe_header {
+#if defined(__BIG_ENDIAN)
+	u8 flags;
+#define FCOE_KWQE_HEADER_RESERVED0 (0xF<<0)
+#define FCOE_KWQE_HEADER_RESERVED0_SHIFT 0
+#define FCOE_KWQE_HEADER_LAYER_CODE (0x7<<4)
+#define FCOE_KWQE_HEADER_LAYER_CODE_SHIFT 4
+#define FCOE_KWQE_HEADER_RESERVED1 (0x1<<7)
+#define FCOE_KWQE_HEADER_RESERVED1_SHIFT 7
+	u8 op_code;
+#elif defined(__LITTLE_ENDIAN)
+	u8 op_code;
+	u8 flags;
+#define FCOE_KWQE_HEADER_RESERVED0 (0xF<<0)
+#define FCOE_KWQE_HEADER_RESERVED0_SHIFT 0
+#define FCOE_KWQE_HEADER_LAYER_CODE (0x7<<4)
+#define FCOE_KWQE_HEADER_LAYER_CODE_SHIFT 4
+#define FCOE_KWQE_HEADER_RESERVED1 (0x1<<7)
+#define FCOE_KWQE_HEADER_RESERVED1_SHIFT 7
+#endif
+};
+
+/*
+ * FCoE firmware init request 1
+ */
+struct fcoe_kwqe_init1 {
+#if defined(__BIG_ENDIAN)
+	struct fcoe_kwqe_header hdr;
+	u16 num_tasks;
+#elif defined(__LITTLE_ENDIAN)
+	u16 num_tasks;
+	struct fcoe_kwqe_header hdr;
+#endif
+	u32 task_list_pbl_addr_lo;
+	u32 task_list_pbl_addr_hi;
+	u32 dummy_buffer_addr_lo;
+	u32 dummy_buffer_addr_hi;
+#if defined(__BIG_ENDIAN)
+	u16 rq_num_wqes;
+	u16 sq_num_wqes;
+#elif defined(__LITTLE_ENDIAN)
+	u16 sq_num_wqes;
+	u16 rq_num_wqes;
+#endif
+#if defined(__BIG_ENDIAN)
+	u16 cq_num_wqes;
+	u16 rq_buffer_log_size;
+#elif defined(__LITTLE_ENDIAN)
+	u16 rq_buffer_log_size;
+	u16 cq_num_wqes;
+#endif
+#if defined(__BIG_ENDIAN)
+	u8 flags;
+#define FCOE_KWQE_INIT1_LOG_PAGE_SIZE (0xF<<0)
+#define FCOE_KWQE_INIT1_LOG_PAGE_SIZE_SHIFT 0
+#define FCOE_KWQE_INIT1_LOG_CACHED_PBES_PER_FUNC (0x7<<4)
+#define FCOE_KWQE_INIT1_LOG_CACHED_PBES_PER_FUNC_SHIFT 4
+#define FCOE_KWQE_INIT1_RESERVED1 (0x1<<7)
+#define FCOE_KWQE_INIT1_RESERVED1_SHIFT 7
+	u8 num_sessions_log;
+	u16 mtu;
+#elif defined(__LITTLE_ENDIAN)
+	u16 mtu;
+	u8 num_sessions_log;
+	u8 flags;
+#define FCOE_KWQE_INIT1_LOG_PAGE_SIZE (0xF<<0)
+#define FCOE_KWQE_INIT1_LOG_PAGE_SIZE_SHIFT 0
+#define FCOE_KWQE_INIT1_LOG_CACHED_PBES_PER_FUNC (0x7<<4)
+#define FCOE_KWQE_INIT1_LOG_CACHED_PBES_PER_FUNC_SHIFT 4
+#define FCOE_KWQE_INIT1_RESERVED1 (0x1<<7)
+#define FCOE_KWQE_INIT1_RESERVED1_SHIFT 7
+#endif
+};
+
+/*
+ * FCoE firmware init request 2
+ */
+struct fcoe_kwqe_init2 {
+#if defined(__BIG_ENDIAN)
+	struct fcoe_kwqe_header hdr;
+	u16 reserved0;
+#elif defined(__LITTLE_ENDIAN)
+	u16 reserved0;
+	struct fcoe_kwqe_header hdr;
+#endif
+	u32 hash_tbl_pbl_addr_lo;
+	u32 hash_tbl_pbl_addr_hi;
+	u32 t2_hash_tbl_addr_lo;
+	u32 t2_hash_tbl_addr_hi;
+	u32 t2_ptr_hash_tbl_addr_lo;
+	u32 t2_ptr_hash_tbl_addr_hi;
+	u32 free_list_count;
+};
+
+/*
+ * FCoE firmware init request 3
+ */
+struct fcoe_kwqe_init3 {
+#if defined(__BIG_ENDIAN)
+	struct fcoe_kwqe_header hdr;
+	u16 reserved0;
+#elif defined(__LITTLE_ENDIAN)
+	u16 reserved0;
+	struct fcoe_kwqe_header hdr;
+#endif
+	u32 error_bit_map_lo;
+	u32 error_bit_map_hi;
+#if defined(__BIG_ENDIAN)
+	u8 reserved21[3];
+	u8 cached_session_enable;
+#elif defined(__LITTLE_ENDIAN)
+	u8 cached_session_enable;
+	u8 reserved21[3];
+#endif
+	u32 reserved2[4];
+};
+
+/*
+ * FCoE connection offload request 1
+ */
+struct fcoe_kwqe_conn_offload1 {
+#if defined(__BIG_ENDIAN)
+	struct fcoe_kwqe_header hdr;
+	u16 fcoe_conn_id;
+#elif defined(__LITTLE_ENDIAN)
+	u16 fcoe_conn_id;
+	struct fcoe_kwqe_header hdr;
+#endif
+	u32 sq_addr_lo;
+	u32 sq_addr_hi;
+	u32 rq_pbl_addr_lo;
+	u32 rq_pbl_addr_hi;
+	u32 rq_first_pbe_addr_lo;
+	u32 rq_first_pbe_addr_hi;
+#if defined(__BIG_ENDIAN)
+	u16 reserved0;
+	u16 rq_prod;
+#elif defined(__LITTLE_ENDIAN)
+	u16 rq_prod;
+	u16 reserved0;
+#endif
+};
+
+/*
+ * FCoE connection offload request 2
+ */
+struct fcoe_kwqe_conn_offload2 {
+#if defined(__BIG_ENDIAN)
+	struct fcoe_kwqe_header hdr;
+	u16 tx_max_fc_pay_len;
+#elif defined(__LITTLE_ENDIAN)
+	u16 tx_max_fc_pay_len;
+	struct fcoe_kwqe_header hdr;
+#endif
+	u32 cq_addr_lo;
+	u32 cq_addr_hi;
+	u32 xferq_addr_lo;
+	u32 xferq_addr_hi;
+	u32 conn_db_addr_lo;
+	u32 conn_db_addr_hi;
+	u32 reserved1;
+};
+
+/*
+ * FCoE connection offload request 3
+ */
+struct fcoe_kwqe_conn_offload3 {
+#if defined(__BIG_ENDIAN)
+	struct fcoe_kwqe_header hdr;
+	u16 vlan_tag;
+#define FCOE_KWQE_CONN_OFFLOAD3_VLAN_ID (0xFFF<<0)
+#define FCOE_KWQE_CONN_OFFLOAD3_VLAN_ID_SHIFT 0
+#define FCOE_KWQE_CONN_OFFLOAD3_CFI (0x1<<12)
+#define FCOE_KWQE_CONN_OFFLOAD3_CFI_SHIFT 12
+#define FCOE_KWQE_CONN_OFFLOAD3_PRIORITY (0x7<<13)
+#define FCOE_KWQE_CONN_OFFLOAD3_PRIORITY_SHIFT 13
+#elif defined(__LITTLE_ENDIAN)
+	u16 vlan_tag;
+#define FCOE_KWQE_CONN_OFFLOAD3_VLAN_ID (0xFFF<<0)
+#define FCOE_KWQE_CONN_OFFLOAD3_VLAN_ID_SHIFT 0
+#define FCOE_KWQE_CONN_OFFLOAD3_CFI (0x1<<12)
+#define FCOE_KWQE_CONN_OFFLOAD3_CFI_SHIFT 12
+#define FCOE_KWQE_CONN_OFFLOAD3_PRIORITY (0x7<<13)
+#define FCOE_KWQE_CONN_OFFLOAD3_PRIORITY_SHIFT 13
+	struct fcoe_kwqe_header hdr;
+#endif
+#if defined(__BIG_ENDIAN)
+	u8 tx_max_conc_seqs_c3;
+	u8 s_id[3];
+#elif defined(__LITTLE_ENDIAN)
+	u8 s_id[3];
+	u8 tx_max_conc_seqs_c3;
+#endif
+#if defined(__BIG_ENDIAN)
+	u8 flags;
+#define FCOE_KWQE_CONN_OFFLOAD3_B_MUL_N_PORT_IDS (0x1<<0)
+#define FCOE_KWQE_CONN_OFFLOAD3_B_MUL_N_PORT_IDS_SHIFT 0
+#define FCOE_KWQE_CONN_OFFLOAD3_B_E_D_TOV_RES (0x1<<1)
+#define FCOE_KWQE_CONN_OFFLOAD3_B_E_D_TOV_RES_SHIFT 1
+#define FCOE_KWQE_CONN_OFFLOAD3_B_CONT_INCR_SEQ_CNT (0x1<<2)
+#define FCOE_KWQE_CONN_OFFLOAD3_B_CONT_INCR_SEQ_CNT_SHIFT 2
+#define FCOE_KWQE_CONN_OFFLOAD3_B_CONF_REQ (0x1<<3)
+#define FCOE_KWQE_CONN_OFFLOAD3_B_CONF_REQ_SHIFT 3
+#define FCOE_KWQE_CONN_OFFLOAD3_B_REC_VALID (0x1<<4)
+#define FCOE_KWQE_CONN_OFFLOAD3_B_REC_VALID_SHIFT 4
+#define FCOE_KWQE_CONN_OFFLOAD3_B_C2_VALID (0x1<<5)
+#define FCOE_KWQE_CONN_OFFLOAD3_B_C2_VALID_SHIFT 5
+#define FCOE_KWQE_CONN_OFFLOAD3_B_ACK_0 (0x1<<6)
+#define FCOE_KWQE_CONN_OFFLOAD3_B_ACK_0_SHIFT 6
+#define FCOE_KWQE_CONN_OFFLOAD3_B_VLAN_FLAG (0x1<<7)
+#define FCOE_KWQE_CONN_OFFLOAD3_B_VLAN_FLAG_SHIFT 7
+	u8 d_id[3];
+#elif defined(__LITTLE_ENDIAN)
+	u8 d_id[3];
+	u8 flags;
+#define FCOE_KWQE_CONN_OFFLOAD3_B_MUL_N_PORT_IDS (0x1<<0)
+#define FCOE_KWQE_CONN_OFFLOAD3_B_MUL_N_PORT_IDS_SHIFT 0
+#define FCOE_KWQE_CONN_OFFLOAD3_B_E_D_TOV_RES (0x1<<1)
+#define FCOE_KWQE_CONN_OFFLOAD3_B_E_D_TOV_RES_SHIFT 1
+#define FCOE_KWQE_CONN_OFFLOAD3_B_CONT_INCR_SEQ_CNT (0x1<<2)
+#define FCOE_KWQE_CONN_OFFLOAD3_B_CONT_INCR_SEQ_CNT_SHIFT 2
+#define FCOE_KWQE_CONN_OFFLOAD3_B_CONF_REQ (0x1<<3)
+#define FCOE_KWQE_CONN_OFFLOAD3_B_CONF_REQ_SHIFT 3
+#define FCOE_KWQE_CONN_OFFLOAD3_B_REC_VALID (0x1<<4)
+#define FCOE_KWQE_CONN_OFFLOAD3_B_REC_VALID_SHIFT 4
+#define FCOE_KWQE_CONN_OFFLOAD3_B_C2_VALID (0x1<<5)
+#define FCOE_KWQE_CONN_OFFLOAD3_B_C2_VALID_SHIFT 5
+#define FCOE_KWQE_CONN_OFFLOAD3_B_ACK_0 (0x1<<6)
+#define FCOE_KWQE_CONN_OFFLOAD3_B_ACK_0_SHIFT 6
+#define FCOE_KWQE_CONN_OFFLOAD3_B_VLAN_FLAG (0x1<<7)
+#define FCOE_KWQE_CONN_OFFLOAD3_B_VLAN_FLAG_SHIFT 7
+#endif
+	u32 reserved;
+	u32 confq_first_pbe_addr_lo;
+	u32 confq_first_pbe_addr_hi;
+#if defined(__BIG_ENDIAN)
+	u16 rx_max_fc_pay_len;
+	u16 tx_total_conc_seqs;
+#elif defined(__LITTLE_ENDIAN)
+	u16 tx_total_conc_seqs;
+	u16 rx_max_fc_pay_len;
+#endif
+#if defined(__BIG_ENDIAN)
+	u8 rx_open_seqs_exch_c3;
+	u8 rx_max_conc_seqs_c3;
+	u16 rx_total_conc_seqs;
+#elif defined(__LITTLE_ENDIAN)
+	u16 rx_total_conc_seqs;
+	u8 rx_max_conc_seqs_c3;
+	u8 rx_open_seqs_exch_c3;
+#endif
+};
+
+/*
+ * FCoE connection offload request 4
+ */
+struct fcoe_kwqe_conn_offload4 {
+#if defined(__BIG_ENDIAN)
+	struct fcoe_kwqe_header hdr;
+	u8 reserved2;
+	u8 e_d_tov_timer_val;
+#elif defined(__LITTLE_ENDIAN)
+	u8 e_d_tov_timer_val;
+	u8 reserved2;
+	struct fcoe_kwqe_header hdr;
+#endif
+	u8 src_mac_addr_lo32[4];
+#if defined(__BIG_ENDIAN)
+	u8 dst_mac_addr_hi16[2];
+	u8 src_mac_addr_hi16[2];
+#elif defined(__LITTLE_ENDIAN)
+	u8 src_mac_addr_hi16[2];
+	u8 dst_mac_addr_hi16[2];
+#endif
+	u8 dst_mac_addr_lo32[4];
+	u32 lcq_addr_lo;
+	u32 lcq_addr_hi;
+	u32 confq_pbl_base_addr_lo;
+	u32 confq_pbl_base_addr_hi;
+};
+
+/*
+ * FCoE connection enable request
+ */
+struct fcoe_kwqe_conn_enable_disable {
+#if defined(__BIG_ENDIAN)
+	struct fcoe_kwqe_header hdr;
+	u16 reserved0;
+#elif defined(__LITTLE_ENDIAN)
+	u16 reserved0;
+	struct fcoe_kwqe_header hdr;
+#endif
+	u8 src_mac_addr_lo32[4];
+#if defined(__BIG_ENDIAN)
+	u16 vlan_tag;
+#define FCOE_KWQE_CONN_ENABLE_DISABLE_VLAN_ID (0xFFF<<0)
+#define FCOE_KWQE_CONN_ENABLE_DISABLE_VLAN_ID_SHIFT 0
+#define FCOE_KWQE_CONN_ENABLE_DISABLE_CFI (0x1<<12)
+#define FCOE_KWQE_CONN_ENABLE_DISABLE_CFI_SHIFT 12
+#define FCOE_KWQE_CONN_ENABLE_DISABLE_PRIORITY (0x7<<13)
+#define FCOE_KWQE_CONN_ENABLE_DISABLE_PRIORITY_SHIFT 13
+	u8 src_mac_addr_hi16[2];
+#elif defined(__LITTLE_ENDIAN)
+	u8 src_mac_addr_hi16[2];
+	u16 vlan_tag;
+#define FCOE_KWQE_CONN_ENABLE_DISABLE_VLAN_ID (0xFFF<<0)
+#define FCOE_KWQE_CONN_ENABLE_DISABLE_VLAN_ID_SHIFT 0
+#define FCOE_KWQE_CONN_ENABLE_DISABLE_CFI (0x1<<12)
+#define FCOE_KWQE_CONN_ENABLE_DISABLE_CFI_SHIFT 12
+#define FCOE_KWQE_CONN_ENABLE_DISABLE_PRIORITY (0x7<<13)
+#define FCOE_KWQE_CONN_ENABLE_DISABLE_PRIORITY_SHIFT 13
+#endif
+	u8 dst_mac_addr_lo32[4];
+#if defined(__BIG_ENDIAN)
+	u16 reserved1;
+	u8 dst_mac_addr_hi16[2];
+#elif defined(__LITTLE_ENDIAN)
+	u8 dst_mac_addr_hi16[2];
+	u16 reserved1;
+#endif
+#if defined(__BIG_ENDIAN)
+	u8 vlan_flag;
+	u8 s_id[3];
+#elif defined(__LITTLE_ENDIAN)
+	u8 s_id[3];
+	u8 vlan_flag;
+#endif
+#if defined(__BIG_ENDIAN)
+	u8 reserved3;
+	u8 d_id[3];
+#elif defined(__LITTLE_ENDIAN)
+	u8 d_id[3];
+	u8 reserved3;
+#endif
+	u32 context_id;
+	u32 conn_id;
+	u32 reserved4;
+};
+
+/*
+ * FCoE connection destroy request
+ */
+struct fcoe_kwqe_conn_destroy {
+#if defined(__BIG_ENDIAN)
+	struct fcoe_kwqe_header hdr;
+	u16 reserved0;
+#elif defined(__LITTLE_ENDIAN)
+	u16 reserved0;
+	struct fcoe_kwqe_header hdr;
+#endif
+	u32 context_id;
+	u32 conn_id;
+	u32 reserved1[5];
+};
+
+/*
+ * FCoe destroy request
+ */
+struct fcoe_kwqe_destroy {
+#if defined(__BIG_ENDIAN)
+	struct fcoe_kwqe_header hdr;
+	u16 reserved0;
+#elif defined(__LITTLE_ENDIAN)
+	u16 reserved0;
+	struct fcoe_kwqe_header hdr;
+#endif
+	u32 reserved1[7];
+};
+
+/*
+ * FCoe statistics request
+ */
+struct fcoe_kwqe_stat {
+#if defined(__BIG_ENDIAN)
+	struct fcoe_kwqe_header hdr;
+	u16 reserved0;
+#elif defined(__LITTLE_ENDIAN)
+	u16 reserved0;
+	struct fcoe_kwqe_header hdr;
+#endif
+	u32 stat_params_addr_lo;
+	u32 stat_params_addr_hi;
+	u32 reserved1[5];
+};
+
+/*
+ * FCoE KWQ WQE
+ */
+union fcoe_kwqe {
+	struct fcoe_kwqe_init1 init1;
+	struct fcoe_kwqe_init2 init2;
+	struct fcoe_kwqe_init3 init3;
+	struct fcoe_kwqe_conn_offload1 conn_offload1;
+	struct fcoe_kwqe_conn_offload2 conn_offload2;
+	struct fcoe_kwqe_conn_offload3 conn_offload3;
+	struct fcoe_kwqe_conn_offload4 conn_offload4;
+	struct fcoe_kwqe_conn_enable_disable conn_enable_disable;
+	struct fcoe_kwqe_conn_destroy conn_destroy;
+	struct fcoe_kwqe_destroy destroy;
+	struct fcoe_kwqe_stat statistics;
+};
+
+struct fcoe_task_ctx_entry {
+	struct fcoe_task_ctx_entry_tx_only tx_wr_only;
+	struct fcoe_task_ctx_entry_txwr_rxrd tx_wr_rx_rd;
+	struct fcoe_task_ctx_entry_tx_rx_cmn cmn;
+	struct fcoe_task_ctx_entry_rxwr_txrd rx_wr_tx_rd;
+	struct fcoe_task_ctx_entry_rx_only rx_wr_only;
+	u32 reserved[4];
+};
+
+/*
+ * FCoE connection enable\disable params passed by driver to FW in FCoE enable ramrod
+ */
+struct fcoe_conn_enable_disable_ramrod_params {
+	struct fcoe_kwqe_conn_enable_disable enable_disable_kwqe;
+};
+
+
+/*
+ * FCoE connection offload params passed by driver to FW in FCoE offload ramrod
+ */
+struct fcoe_conn_offload_ramrod_params {
+	struct fcoe_kwqe_conn_offload1 offload_kwqe1;
+	struct fcoe_kwqe_conn_offload2 offload_kwqe2;
+	struct fcoe_kwqe_conn_offload3 offload_kwqe3;
+	struct fcoe_kwqe_conn_offload4 offload_kwqe4;
+};
+
+/*
+ * FCoE init params passed by driver to FW in FCoE init ramrod
+ */
+struct fcoe_init_ramrod_params {
+	struct fcoe_kwqe_init1 init_kwqe1;
+	struct fcoe_kwqe_init2 init_kwqe2;
+	struct fcoe_kwqe_init3 init_kwqe3;
+	struct regpair eq_addr;
+	struct regpair eq_next_page_addr;
+#if defined(__BIG_ENDIAN)
+	u16 sb_num;
+	u16 eq_prod;
+#elif defined(__LITTLE_ENDIAN)
+	u16 eq_prod;
+	u16 sb_num;
+#endif
+#if defined(__BIG_ENDIAN)
+	u16 reserved1;
+	u8 reserved0;
+	u8 sb_id;
+#elif defined(__LITTLE_ENDIAN)
+	u8 sb_id;
+	u8 reserved0;
+	u16 reserved1;
+#endif
+};
+
+
+/*
+ * FCoE statistics params buffer passed by driver to FW in FCoE statistics ramrod
+ */
+struct fcoe_stat_ramrod_params {
+	struct fcoe_kwqe_stat stat_kwqe;
+};
+
+
+/*
+ * FCoE 16-bits vlan structure
+ */
+struct fcoe_vlan_fields {
+	u16 fields;
+#define FCOE_VLAN_FIELDS_VID (0xFFF<<0)
+#define FCOE_VLAN_FIELDS_VID_SHIFT 0
+#define FCOE_VLAN_FIELDS_CLI (0x1<<12)
+#define FCOE_VLAN_FIELDS_CLI_SHIFT 12
+#define FCOE_VLAN_FIELDS_PRI (0x7<<13)
+#define FCOE_VLAN_FIELDS_PRI_SHIFT 13
+};
+
+
+/*
+ * FCoE 16-bits vlan union
+ */
+union fcoe_vlan_field_union {
+	struct fcoe_vlan_fields fields;
+	u16 val;
+};
+
+/*
+ * Parameters used for Class 2 verifications
+ */
+struct ustorm_fcoe_c2_params {
+#if defined(__BIG_ENDIAN)
+	u16 e2e_credit;
+	u16 con_seq;
+#elif defined(__LITTLE_ENDIAN)
+	u16 con_seq;
+	u16 e2e_credit;
+#endif
+#if defined(__BIG_ENDIAN)
+	u16 ackq_prod;
+	u16 open_seq_per_exch;
+#elif defined(__LITTLE_ENDIAN)
+	u16 open_seq_per_exch;
+	u16 ackq_prod;
+#endif
+	struct regpair ackq_pbl_base;
+	struct regpair ackq_cur_seg;
+};
+
+/*
+ * Parameters used for Class 2 verifications
+ */
+struct xstorm_fcoe_c2_params {
+#if defined(__BIG_ENDIAN)
+	u16 reserved0;
+	u8 ackq_x_prod;
+	u8 max_conc_seqs_c2;
+#elif defined(__LITTLE_ENDIAN)
+	u8 max_conc_seqs_c2;
+	u8 ackq_x_prod;
+	u16 reserved0;
+#endif
+	struct regpair ackq_pbl_base;
+	struct regpair ackq_cur_seg;
+};
+
+/*
  * Buffer per connection, used in Tstorm
  */
 struct iscsi_conn_buf {
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/cnic.h linux-libre-2.6.38-gnu1/drivers/net/cnic.h
--- linux-libre-2.6.37-gnu1/drivers/net/cnic.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/cnic.h	2011-03-14 21:20:32.000000000 -0400
@@ -82,7 +82,7 @@ struct cnic_redirect_entry {
 #define MAX_ISCSI_TBL_SZ	256
 
 #define CNIC_LOCAL_PORT_MIN	60000
-#define CNIC_LOCAL_PORT_MAX	61000
+#define CNIC_LOCAL_PORT_MAX	61024
 #define CNIC_LOCAL_PORT_RANGE	(CNIC_LOCAL_PORT_MAX - CNIC_LOCAL_PORT_MIN)
 
 #define KWQE_CNT (BCM_PAGE_SIZE / sizeof(struct kwqe))
@@ -258,6 +258,7 @@ struct cnic_local {
 	u16		kwq_con_idx;
 
 	struct kcq_info	kcq1;
+	struct kcq_info	kcq2;
 
 	union {
 		void				*gen;
@@ -290,6 +291,10 @@ struct cnic_local {
 	atomic_t		iscsi_conn;
 	u32			iscsi_start_cid;
 
+	u32			fcoe_init_cid;
+	u32			fcoe_start_cid;
+	struct cnic_id_tbl	fcoe_cid_tbl;
+
 	u32			max_cid_space;
 
 	/* per connection parameters */
@@ -356,11 +361,6 @@ struct bnx2x_bd_chain_next {
 #define BNX2X_CONTEXT_MEM_SIZE		1024
 #define BNX2X_FCOE_CID			16
 
-/* iSCSI client IDs are 17, 19, 21, 23 */
-#define BNX2X_ISCSI_BASE_CL_ID		17
-#define BNX2X_ISCSI_CL_ID(vn)		(BNX2X_ISCSI_BASE_CL_ID + ((vn) << 1))
-
-#define BNX2X_ISCSI_L2_CID		17
 #define BNX2X_ISCSI_START_CID		18
 #define BNX2X_ISCSI_NUM_CONNECTIONS	128
 #define BNX2X_ISCSI_TASK_CONTEXT_SIZE	128
@@ -372,6 +372,10 @@ struct bnx2x_bd_chain_next {
 #define BNX2X_ISCSI_PBL_NOT_CACHED	0xff
 #define BNX2X_ISCSI_PDU_HEADER_NOT_CACHED	0xff
 
+#define BNX2X_FCOE_NUM_CONNECTIONS	128
+
+#define BNX2X_FCOE_L5_CID_BASE		MAX_ISCSI_TBL_SZ
+
 #define BNX2X_CHIP_NUM_57710		0x164e
 #define BNX2X_CHIP_NUM_57711		0x164f
 #define BNX2X_CHIP_NUM_57711E		0x1650
@@ -427,6 +431,13 @@ struct bnx2x_bd_chain_next {
 		 (CNIC_RD(dev, BNX2X_SHMEM2_ADDR(base, size)) >	\
 		  offsetof(struct shmem2_region, field)))
 
+#define BNX2X_MF_CFG_ADDR(base, field)				\
+			((base) + offsetof(struct mf_cfg, field))
+
+#ifndef ETH_MAX_RX_CLIENTS_E2
+#define ETH_MAX_RX_CLIENTS_E2 		ETH_MAX_RX_CLIENTS_E1H
+#endif
+
 #define CNIC_PORT(cp)			((cp)->pfid & 1)
 #define CNIC_FUNC(cp)			((cp)->func)
 #define CNIC_PATH(cp)			(!BNX2X_CHIP_IS_E2(cp->chip_id) ? 0 :\
@@ -439,7 +450,9 @@ struct bnx2x_bd_chain_next {
 #define BNX2X_SW_CID(x)			(x & 0x1ffff)
 
 #define BNX2X_CL_QZONE_ID(cp, cli)					\
-		(cli + (CNIC_PORT(cp) * ETH_MAX_RX_CLIENTS_E1H))
+		(cli + (CNIC_PORT(cp) * (BNX2X_CHIP_IS_E2(cp->chip_id) ?\
+					ETH_MAX_RX_CLIENTS_E2 :		\
+					ETH_MAX_RX_CLIENTS_E1H)))
 
 #define TCP_TSTORM_OOO_DROP_AND_PROC_ACK	(0<<4)
 #endif
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/cnic_if.h linux-libre-2.6.38-gnu1/drivers/net/cnic_if.h
--- linux-libre-2.6.37-gnu1/drivers/net/cnic_if.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/cnic_if.h	2011-03-14 21:20:32.000000000 -0400
@@ -1,6 +1,6 @@
 /* cnic_if.h: Broadcom CNIC core network driver.
  *
- * Copyright (c) 2006-2010 Broadcom Corporation
+ * Copyright (c) 2006-2011 Broadcom 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
@@ -12,22 +12,31 @@
 #ifndef CNIC_IF_H
 #define CNIC_IF_H
 
-#define CNIC_MODULE_VERSION	"2.2.6"
-#define CNIC_MODULE_RELDATE	"Oct 12, 2010"
+#define CNIC_MODULE_VERSION	"2.2.12"
+#define CNIC_MODULE_RELDATE	"Jan 03, 2011"
 
 #define CNIC_ULP_RDMA		0
 #define CNIC_ULP_ISCSI		1
-#define CNIC_ULP_L4		2
-#define MAX_CNIC_ULP_TYPE_EXT	2
-#define MAX_CNIC_ULP_TYPE	3
+#define CNIC_ULP_FCOE		2
+#define CNIC_ULP_L4		3
+#define MAX_CNIC_ULP_TYPE_EXT	3
+#define MAX_CNIC_ULP_TYPE	4
 
 struct kwqe {
 	u32 kwqe_op_flag;
 
+#define KWQE_QID_SHIFT		8
 #define KWQE_OPCODE_MASK	0x00ff0000
 #define KWQE_OPCODE_SHIFT	16
-#define KWQE_FLAGS_LAYER_SHIFT	28
 #define KWQE_OPCODE(x)		((x & KWQE_OPCODE_MASK) >> KWQE_OPCODE_SHIFT)
+#define KWQE_LAYER_MASK			0x70000000
+#define KWQE_LAYER_SHIFT		28
+#define KWQE_FLAGS_LAYER_MASK_L2	(2<<28)
+#define KWQE_FLAGS_LAYER_MASK_L3	(3<<28)
+#define KWQE_FLAGS_LAYER_MASK_L4	(4<<28)
+#define KWQE_FLAGS_LAYER_MASK_L5_RDMA	(5<<28)
+#define KWQE_FLAGS_LAYER_MASK_L5_ISCSI	(6<<28)
+#define KWQE_FLAGS_LAYER_MASK_L5_FCOE	(7<<28)
 
 	u32 kwqe_info0;
 	u32 kwqe_info1;
@@ -62,6 +71,7 @@ struct kcqe {
 		#define KCQE_FLAGS_LAYER_MASK_L4	(4<<28)
 		#define KCQE_FLAGS_LAYER_MASK_L5_RDMA	(5<<28)
 		#define KCQE_FLAGS_LAYER_MASK_L5_ISCSI	(6<<28)
+		#define KCQE_FLAGS_LAYER_MASK_L5_FCOE	(7<<28)
 		#define KCQE_FLAGS_NEXT 		(1<<31)
 		#define KCQE_FLAGS_OPCODE_MASK		(0xff<<16)
 		#define KCQE_FLAGS_OPCODE_SHIFT		(16)
@@ -301,7 +311,7 @@ struct cnic_ulp_ops {
 	void (*cm_abort_complete)(struct cnic_sock *);
 	void (*cm_remote_close)(struct cnic_sock *);
 	void (*cm_remote_abort)(struct cnic_sock *);
-	void (*iscsi_nl_send_msg)(struct cnic_dev *dev, u32 msg_type,
+	int (*iscsi_nl_send_msg)(void *ulp_ctx, u32 msg_type,
 				  char *data, u16 data_size);
 	struct module *owner;
 	atomic_t ref_count;
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/cris/eth_v10.c linux-libre-2.6.38-gnu1/drivers/net/cris/eth_v10.c
--- linux-libre-2.6.37-gnu1/drivers/net/cris/eth_v10.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/cris/eth_v10.c	2011-03-14 21:20:32.000000000 -0400
@@ -59,7 +59,6 @@ static struct sockaddr default_mac = {
 
 /* Information that need to be kept for each board. */
 struct net_local {
-	struct net_device_stats stats;
 	struct mii_if_info mii_if;
 
 	/* Tx control lock.  This protects the transmit buffer ring
@@ -1059,7 +1058,7 @@ e100_tx_timeout(struct net_device *dev)
 
 	/* remember we got an error */
 
-	np->stats.tx_errors++;
+	dev->stats.tx_errors++;
 
 	/* reset the TX DMA in case it has hung on something */
 
@@ -1157,7 +1156,7 @@ e100rxtx_interrupt(int irq, void *dev_id
 			 * allocate a new buffer to put a packet in.
 			 */
 			e100_rx(dev);
-			np->stats.rx_packets++;
+			dev->stats.rx_packets++;
 			/* restart/continue on the channel, for safety */
 			*R_DMA_CH1_CMD = IO_STATE(R_DMA_CH1_CMD, cmd, restart);
 			/* clear dma channel 1 eop/descr irq bits */
@@ -1173,8 +1172,8 @@ e100rxtx_interrupt(int irq, void *dev_id
 	/* Report any packets that have been sent */
 	while (virt_to_phys(myFirstTxDesc) != *R_DMA_CH0_FIRST &&
 	       (netif_queue_stopped(dev) || myFirstTxDesc != myNextTxDesc)) {
-		np->stats.tx_bytes += myFirstTxDesc->skb->len;
-		np->stats.tx_packets++;
+		dev->stats.tx_bytes += myFirstTxDesc->skb->len;
+		dev->stats.tx_packets++;
 
 		/* dma is ready with the transmission of the data in tx_skb, so now
 		   we can release the skb memory */
@@ -1197,7 +1196,6 @@ static irqreturn_t
 e100nw_interrupt(int irq, void *dev_id)
 {
 	struct net_device *dev = (struct net_device *)dev_id;
-	struct net_local *np = netdev_priv(dev);
 	unsigned long irqbits = *R_IRQ_MASK0_RD;
 
 	/* check for underrun irq */
@@ -1205,13 +1203,13 @@ e100nw_interrupt(int irq, void *dev_id)
 		SETS(network_tr_ctrl_shadow, R_NETWORK_TR_CTRL, clr_error, clr);
 		*R_NETWORK_TR_CTRL = network_tr_ctrl_shadow;
 		SETS(network_tr_ctrl_shadow, R_NETWORK_TR_CTRL, clr_error, nop);
-		np->stats.tx_errors++;
+		dev->stats.tx_errors++;
 		D(printk("ethernet receiver underrun!\n"));
 	}
 
 	/* check for overrun irq */
 	if (irqbits & IO_STATE(R_IRQ_MASK0_RD, overrun, active)) {
-		update_rx_stats(&np->stats); /* this will ack the irq */
+		update_rx_stats(&dev->stats); /* this will ack the irq */
 		D(printk("ethernet receiver overrun!\n"));
 	}
 	/* check for excessive collision irq */
@@ -1219,7 +1217,7 @@ e100nw_interrupt(int irq, void *dev_id)
 		SETS(network_tr_ctrl_shadow, R_NETWORK_TR_CTRL, clr_error, clr);
 		*R_NETWORK_TR_CTRL = network_tr_ctrl_shadow;
 		SETS(network_tr_ctrl_shadow, R_NETWORK_TR_CTRL, clr_error, nop);
-		np->stats.tx_errors++;
+		dev->stats.tx_errors++;
 		D(printk("ethernet excessive collisions!\n"));
 	}
 	return IRQ_HANDLED;
@@ -1250,7 +1248,7 @@ e100_rx(struct net_device *dev)
 	spin_unlock(&np->led_lock);
 
 	length = myNextRxDesc->descr.hw_len - 4;
-	np->stats.rx_bytes += length;
+	dev->stats.rx_bytes += length;
 
 #ifdef ETHDEBUG
 	printk("Got a packet of length %d:\n", length);
@@ -1268,7 +1266,7 @@ e100_rx(struct net_device *dev)
 		/* Small packet, copy data */
 		skb = dev_alloc_skb(length - ETHER_HEAD_LEN);
 		if (!skb) {
-			np->stats.rx_errors++;
+			dev->stats.rx_errors++;
 			printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n", dev->name);
 			goto update_nextrxdesc;
 		}
@@ -1294,7 +1292,7 @@ e100_rx(struct net_device *dev)
 		int align;
 		struct sk_buff *new_skb = dev_alloc_skb(MAX_MEDIA_DATA_SIZE + 2 * L1_CACHE_BYTES);
 		if (!new_skb) {
-			np->stats.rx_errors++;
+			dev->stats.rx_errors++;
 			printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n", dev->name);
 			goto update_nextrxdesc;
 		}
@@ -1333,8 +1331,6 @@ e100_rx(struct net_device *dev)
 static int
 e100_close(struct net_device *dev)
 {
-	struct net_local *np = netdev_priv(dev);
-
 	printk(KERN_INFO "Closing %s.\n", dev->name);
 
 	netif_stop_queue(dev);
@@ -1366,8 +1362,8 @@ e100_close(struct net_device *dev)
 
 	/* Update the statistics here. */
 
-	update_rx_stats(&np->stats);
-	update_tx_stats(&np->stats);
+	update_rx_stats(&dev->stats);
+	update_tx_stats(&dev->stats);
 
 	/* Stop speed/duplex timers */
 	del_timer(&speed_timer);
@@ -1545,11 +1541,11 @@ e100_get_stats(struct net_device *dev)
 
 	spin_lock_irqsave(&lp->lock, flags);
 
-	update_rx_stats(&lp->stats);
-	update_tx_stats(&lp->stats);
+	update_rx_stats(&dev->stats);
+	update_tx_stats(&dev->stats);
 
 	spin_unlock_irqrestore(&lp->lock, flags);
-	return &lp->stats;
+	return &dev->stats;
 }
 
 /*
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/cxgb3/ael1002.c linux-libre-2.6.38-gnu1/drivers/net/cxgb3/ael1002.c
--- linux-libre-2.6.37-gnu1/drivers/net/cxgb3/ael1002.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/cxgb3/ael1002.c	2011-03-14 21:20:32.000000000 -0400
@@ -292,7 +292,7 @@ unknown:
  */
 static int ael2005_setup_sr_edc(struct cphy *phy)
 {
-	static struct reg_val regs[] = {
+	static const struct reg_val regs[] = {
 		{ MDIO_MMD_PMAPMD, 0xc003, 0xffff, 0x181 },
 		{ MDIO_MMD_PMAPMD, 0xc010, 0xffff, 0x448a },
 		{ MDIO_MMD_PMAPMD, 0xc04a, 0xffff, 0x5200 },
@@ -324,11 +324,11 @@ static int ael2005_setup_sr_edc(struct c
 
 static int ael2005_setup_twinax_edc(struct cphy *phy, int modtype)
 {
-	static struct reg_val regs[] = {
+	static const struct reg_val regs[] = {
 		{ MDIO_MMD_PMAPMD, 0xc04a, 0xffff, 0x5a00 },
 		{ 0, 0, 0, 0 }
 	};
-	static struct reg_val preemphasis[] = {
+	static const struct reg_val preemphasis[] = {
 		{ MDIO_MMD_PMAPMD, 0xc014, 0xffff, 0xfe16 },
 		{ MDIO_MMD_PMAPMD, 0xc015, 0xffff, 0xa000 },
 		{ 0, 0, 0, 0 }
@@ -393,7 +393,7 @@ static int ael2005_intr_clear(struct cph
 
 static int ael2005_reset(struct cphy *phy, int wait)
 {
-	static struct reg_val regs0[] = {
+	static const struct reg_val regs0[] = {
 		{ MDIO_MMD_PMAPMD, 0xc001, 0, 1 << 5 },
 		{ MDIO_MMD_PMAPMD, 0xc017, 0, 1 << 5 },
 		{ MDIO_MMD_PMAPMD, 0xc013, 0xffff, 0xf341 },
@@ -403,7 +403,7 @@ static int ael2005_reset(struct cphy *ph
 		{ MDIO_MMD_PMAPMD, 0xc210, 0xffff, 0 },
 		{ 0, 0, 0, 0 }
 	};
-	static struct reg_val regs1[] = {
+	static const struct reg_val regs1[] = {
 		{ MDIO_MMD_PMAPMD, 0xca00, 0xffff, 0x0080 },
 		{ MDIO_MMD_PMAPMD, 0xca12, 0xffff, 0 },
 		{ 0, 0, 0, 0 }
@@ -522,7 +522,7 @@ int t3_ael2005_phy_prep(struct cphy *phy
  */
 static int ael2020_setup_sr_edc(struct cphy *phy)
 {
-	static struct reg_val regs[] = {
+	static const struct reg_val regs[] = {
 		/* set CDR offset to 10 */
 		{ MDIO_MMD_PMAPMD, 0xcc01, 0xffff, 0x488a },
 
@@ -551,20 +551,20 @@ static int ael2020_setup_sr_edc(struct c
 static int ael2020_setup_twinax_edc(struct cphy *phy, int modtype)
 {
 	/* set uC to 40MHz */
-	static struct reg_val uCclock40MHz[] = {
+	static const struct reg_val uCclock40MHz[] = {
 		{ MDIO_MMD_PMAPMD, 0xff28, 0xffff, 0x4001 },
 		{ MDIO_MMD_PMAPMD, 0xff2a, 0xffff, 0x0002 },
 		{ 0, 0, 0, 0 }
 	};
 
 	/* activate uC clock */
-	static struct reg_val uCclockActivate[] = {
+	static const struct reg_val uCclockActivate[] = {
 		{ MDIO_MMD_PMAPMD, 0xd000, 0xffff, 0x5200 },
 		{ 0, 0, 0, 0 }
 	};
 
 	/* set PC to start of SRAM and activate uC */
-	static struct reg_val uCactivate[] = {
+	static const struct reg_val uCactivate[] = {
 		{ MDIO_MMD_PMAPMD, 0xd080, 0xffff, 0x0100 },
 		{ MDIO_MMD_PMAPMD, 0xd092, 0xffff, 0x0000 },
 		{ 0, 0, 0, 0 }
@@ -624,7 +624,7 @@ static int ael2020_get_module_type(struc
  */
 static int ael2020_intr_enable(struct cphy *phy)
 {
-	struct reg_val regs[] = {
+	static const struct reg_val regs[] = {
 		/* output Module's Loss Of Signal (LOS) to LED */
 		{ MDIO_MMD_PMAPMD, AEL2020_GPIO_CFG+AEL2020_GPIO_LSTAT,
 			0xffff, 0x4 },
@@ -664,7 +664,7 @@ static int ael2020_intr_enable(struct cp
  */
 static int ael2020_intr_disable(struct cphy *phy)
 {
-	struct reg_val regs[] = {
+	static const struct reg_val regs[] = {
 		/* reset "link status" LED to "off" */
 		{ MDIO_MMD_PMAPMD, AEL2020_GPIO_CTRL,
 			0xffff, 0xb << (AEL2020_GPIO_LSTAT*4) },
@@ -701,7 +701,7 @@ static int ael2020_intr_clear(struct cph
 	return err ? err : t3_phy_lasi_intr_clear(phy);
 }
 
-static struct reg_val ael2020_reset_regs[] = {
+static const struct reg_val ael2020_reset_regs[] = {
 	/* Erratum #2: CDRLOL asserted, causing PMA link down status */
 	{ MDIO_MMD_PMAPMD, 0xc003, 0xffff, 0x3101 },
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/cxgb3/cxgb3_main.c linux-libre-2.6.38-gnu1/drivers/net/cxgb3/cxgb3_main.c
--- linux-libre-2.6.37-gnu1/drivers/net/cxgb3/cxgb3_main.c	2013-05-03 03:58:16.000000000 -0400
+++ linux-libre-2.6.38-gnu1/drivers/net/cxgb3/cxgb3_main.c	2013-05-03 01:58:22.000000000 -0400
@@ -1352,6 +1352,7 @@ out:
 static int offload_close(struct t3cdev *tdev)
 {
 	struct adapter *adapter = tdev2adap(tdev);
+	struct t3c_data *td = T3C_DATA(tdev);
 
 	if (!test_bit(OFFLOAD_DEVMAP_BIT, &adapter->open_device_map))
 		return 0;
@@ -1362,7 +1363,7 @@ static int offload_close(struct t3cdev *
 	sysfs_remove_group(&tdev->lldev->dev.kobj, &offload_attr_group);
 
 	/* Flush work scheduled while releasing TIDs */
-	flush_scheduled_work();
+	flush_work_sync(&td->tid_release_task);
 
 	tdev->lldev = NULL;
 	cxgb3_set_dummy_ops(tdev);
@@ -2999,12 +3000,11 @@ static pci_ers_result_t t3_io_error_dete
 					     pci_channel_state_t state)
 {
 	struct adapter *adapter = pci_get_drvdata(pdev);
-	int ret;
 
 	if (state == pci_channel_io_perm_failure)
 		return PCI_ERS_RESULT_DISCONNECT;
 
-	ret = t3_adapter_error(adapter, 0, 0);
+	t3_adapter_error(adapter, 0, 0);
 
 	/* Request a slot reset. */
 	return PCI_ERS_RESULT_NEED_RESET;
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/cxgb3/cxgb3_offload.c linux-libre-2.6.38-gnu1/drivers/net/cxgb3/cxgb3_offload.c
--- linux-libre-2.6.37-gnu1/drivers/net/cxgb3/cxgb3_offload.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/cxgb3/cxgb3_offload.c	2011-03-14 21:20:32.000000000 -0400
@@ -1164,12 +1164,10 @@ static void cxgb_redirect(struct dst_ent
  */
 void *cxgb_alloc_mem(unsigned long size)
 {
-	void *p = kmalloc(size, GFP_KERNEL);
+	void *p = kzalloc(size, GFP_KERNEL);
 
 	if (!p)
-		p = vmalloc(size);
-	if (p)
-		memset(p, 0, size);
+		p = vzalloc(size);
 	return p;
 }
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/cxgb3/mc5.c linux-libre-2.6.38-gnu1/drivers/net/cxgb3/mc5.c
--- linux-libre-2.6.37-gnu1/drivers/net/cxgb3/mc5.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/cxgb3/mc5.c	2011-03-14 21:20:32.000000000 -0400
@@ -318,7 +318,7 @@ static void mc5_dbgi_mode_disable(const
 
 /*
  * Initialization that requires the OS and protocol layers to already
- * be intialized goes here.
+ * be initialized goes here.
  */
 int t3_mc5_init(struct mc5 *mc5, unsigned int nservers, unsigned int nfilters,
 		unsigned int nroutes)
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/cxgb3/t3_hw.c linux-libre-2.6.38-gnu1/drivers/net/cxgb3/t3_hw.c
--- linux-libre-2.6.37-gnu1/drivers/net/cxgb3/t3_hw.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/cxgb3/t3_hw.c	2011-03-14 21:20:32.000000000 -0400
@@ -607,7 +607,7 @@ struct t3_vpd {
  *
  *	Read a 32-bit word from a location in VPD EEPROM using the card's PCI
  *	VPD ROM capability.  A zero is written to the flag bit when the
- *	addres is written to the control register.  The hardware device will
+ *	address is written to the control register.  The hardware device will
  *	set the flag to 1 when 4 bytes have been read into the data register.
  */
 int t3_seeprom_read(struct adapter *adapter, u32 addr, __le32 *data)
@@ -1562,7 +1562,7 @@ static void tp_intr_handler(struct adapt
 		{0}
 	};
 
-	static struct intr_info tp_intr_info_t3c[] = {
+	static const struct intr_info tp_intr_info_t3c[] = {
 		{0x1fffffff, "TP parity error", -1, 1},
 		{F_FLMRXFLSTEMPTY, "TP out of Rx pages", -1, 1},
 		{F_FLMTXFLSTEMPTY, "TP out of Tx pages", -1, 1},
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/cxgb4/cxgb4.h linux-libre-2.6.38-gnu1/drivers/net/cxgb4/cxgb4.h
--- linux-libre-2.6.37-gnu1/drivers/net/cxgb4/cxgb4.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/cxgb4/cxgb4.h	2011-03-14 21:20:32.000000000 -0400
@@ -482,11 +482,9 @@ struct adapter {
 	void __iomem *regs;
 	struct pci_dev *pdev;
 	struct device *pdev_dev;
-	unsigned long registered_device_map;
 	unsigned int fn;
 	unsigned int flags;
 
-	const char *name;
 	int msg_enable;
 
 	struct adapter_params params;
@@ -497,7 +495,7 @@ struct adapter {
 
 	struct {
 		unsigned short vec;
-		char desc[14];
+		char desc[IFNAMSIZ + 10];
 	} msix_info[MAX_INGQ + 1];
 
 	struct sge sge;
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/cxgb4/cxgb4_main.c linux-libre-2.6.38-gnu1/drivers/net/cxgb4/cxgb4_main.c
--- linux-libre-2.6.37-gnu1/drivers/net/cxgb4/cxgb4_main.c	2013-05-03 03:58:20.000000000 -0400
+++ linux-libre-2.6.38-gnu1/drivers/net/cxgb4/cxgb4_main.c	2013-05-03 01:58:26.000000000 -0400
@@ -522,39 +522,33 @@ static irqreturn_t t4_nondata_intr(int i
  */
 static void name_msix_vecs(struct adapter *adap)
 {
-	int i, j, msi_idx = 2, n = sizeof(adap->msix_info[0].desc) - 1;
+	int i, j, msi_idx = 2, n = sizeof(adap->msix_info[0].desc);
 
 	/* non-data interrupts */
-	snprintf(adap->msix_info[0].desc, n, "%s", adap->name);
-	adap->msix_info[0].desc[n] = 0;
+	snprintf(adap->msix_info[0].desc, n, "%s", adap->port[0]->name);
 
 	/* FW events */
-	snprintf(adap->msix_info[1].desc, n, "%s-FWeventq", adap->name);
-	adap->msix_info[1].desc[n] = 0;
+	snprintf(adap->msix_info[1].desc, n, "%s-FWeventq",
+		 adap->port[0]->name);
 
 	/* Ethernet queues */
 	for_each_port(adap, j) {
 		struct net_device *d = adap->port[j];
 		const struct port_info *pi = netdev_priv(d);
 
-		for (i = 0; i < pi->nqsets; i++, msi_idx++) {
+		for (i = 0; i < pi->nqsets; i++, msi_idx++)
 			snprintf(adap->msix_info[msi_idx].desc, n, "%s-Rx%d",
 				 d->name, i);
-			adap->msix_info[msi_idx].desc[n] = 0;
-		}
 	}
 
 	/* offload queues */
-	for_each_ofldrxq(&adap->sge, i) {
-		snprintf(adap->msix_info[msi_idx].desc, n, "%s-ofld%d",
-			 adap->name, i);
-		adap->msix_info[msi_idx++].desc[n] = 0;
-	}
-	for_each_rdmarxq(&adap->sge, i) {
-		snprintf(adap->msix_info[msi_idx].desc, n, "%s-rdma%d",
-			 adap->name, i);
-		adap->msix_info[msi_idx++].desc[n] = 0;
-	}
+	for_each_ofldrxq(&adap->sge, i)
+		snprintf(adap->msix_info[msi_idx++].desc, n, "%s-ofld%d",
+			 adap->port[0]->name, i);
+
+	for_each_rdmarxq(&adap->sge, i)
+		snprintf(adap->msix_info[msi_idx++].desc, n, "%s-rdma%d",
+			 adap->port[0]->name, i);
 }
 
 static int request_msix_queue_irqs(struct adapter *adap)
@@ -868,12 +862,10 @@ out:	release_firmware(fw);
  */
 void *t4_alloc_mem(size_t size)
 {
-	void *p = kmalloc(size, GFP_KERNEL);
+	void *p = kzalloc(size, GFP_KERNEL);
 
 	if (!p)
-		p = vmalloc(size);
-	if (p)
-		memset(p, 0, size);
+		p = vzalloc(size);
 	return p;
 }
 
@@ -1377,7 +1369,12 @@ static unsigned int from_fw_linkcaps(uns
 	} else if (type == FW_PORT_TYPE_KR)
 		v |= SUPPORTED_Backplane | SUPPORTED_10000baseKR_Full;
 	else if (type == FW_PORT_TYPE_BP_AP)
-		v |= SUPPORTED_Backplane | SUPPORTED_10000baseR_FEC;
+		v |= SUPPORTED_Backplane | SUPPORTED_10000baseR_FEC |
+		     SUPPORTED_10000baseKR_Full | SUPPORTED_1000baseKX_Full;
+	else if (type == FW_PORT_TYPE_BP4_AP)
+		v |= SUPPORTED_Backplane | SUPPORTED_10000baseR_FEC |
+		     SUPPORTED_10000baseKR_Full | SUPPORTED_1000baseKX_Full |
+		     SUPPORTED_10000baseKX4_Full;
 	else if (type == FW_PORT_TYPE_FIBER_XFI ||
 		 type == FW_PORT_TYPE_FIBER_XAUI || type == FW_PORT_TYPE_SFP)
 		v |= SUPPORTED_FIBRE;
@@ -2668,7 +2665,7 @@ static int cxgb_up(struct adapter *adap)
 	} else {
 		err = request_irq(adap->pdev->irq, t4_intr_handler(adap),
 				  (adap->flags & USING_MSI) ? 0 : IRQF_SHARED,
-				  adap->name, adap);
+				  adap->port[0]->name, adap);
 		if (err)
 			goto irq_err;
 	}
@@ -2713,16 +2710,14 @@ static int cxgb_open(struct net_device *
 	struct port_info *pi = netdev_priv(dev);
 	struct adapter *adapter = pi->adapter;
 
+	netif_carrier_off(dev);
+
 	if (!(adapter->flags & FULL_INIT_DONE)) {
 		err = cxgb_up(adapter);
 		if (err < 0)
 			return err;
 	}
 
-	netif_set_real_num_tx_queues(dev, pi->nqsets);
-	err = netif_set_real_num_rx_queues(dev, pi->nqsets);
-	if (err)
-		return err;
 	err = link_start(dev);
 	if (!err)
 		netif_tx_start_all_queues(dev);
@@ -3491,49 +3486,53 @@ static int __devinit init_rss(struct ada
 	return 0;
 }
 
-static void __devinit print_port_info(struct adapter *adap)
+static void __devinit print_port_info(const struct net_device *dev)
 {
 	static const char *base[] = {
 		"R XFI", "R XAUI", "T SGMII", "T XFI", "T XAUI", "KX4", "CX4",
-		"KX", "KR", "KR SFP+", "KR FEC"
+		"KX", "KR", "R SFP+", "KR/KX", "KR/KX/KX4"
 	};
 
-	int i;
 	char buf[80];
+	char *bufp = buf;
 	const char *spd = "";
+	const struct port_info *pi = netdev_priv(dev);
+	const struct adapter *adap = pi->adapter;
 
 	if (adap->params.pci.speed == PCI_EXP_LNKSTA_CLS_2_5GB)
 		spd = " 2.5 GT/s";
 	else if (adap->params.pci.speed == PCI_EXP_LNKSTA_CLS_5_0GB)
 		spd = " 5 GT/s";
 
-	for_each_port(adap, i) {
-		struct net_device *dev = adap->port[i];
-		const struct port_info *pi = netdev_priv(dev);
-		char *bufp = buf;
+	if (pi->link_cfg.supported & FW_PORT_CAP_SPEED_100M)
+		bufp += sprintf(bufp, "100/");
+	if (pi->link_cfg.supported & FW_PORT_CAP_SPEED_1G)
+		bufp += sprintf(bufp, "1000/");
+	if (pi->link_cfg.supported & FW_PORT_CAP_SPEED_10G)
+		bufp += sprintf(bufp, "10G/");
+	if (bufp != buf)
+		--bufp;
+	sprintf(bufp, "BASE-%s", base[pi->port_type]);
 
-		if (!test_bit(i, &adap->registered_device_map))
-			continue;
+	netdev_info(dev, "Chelsio %s rev %d %s %sNIC PCIe x%d%s%s\n",
+		    adap->params.vpd.id, adap->params.rev, buf,
+		    is_offload(adap) ? "R" : "", adap->params.pci.width, spd,
+		    (adap->flags & USING_MSIX) ? " MSI-X" :
+		    (adap->flags & USING_MSI) ? " MSI" : "");
+	netdev_info(dev, "S/N: %s, E/C: %s\n",
+		    adap->params.vpd.sn, adap->params.vpd.ec);
+}
 
-		if (pi->link_cfg.supported & FW_PORT_CAP_SPEED_100M)
-			bufp += sprintf(bufp, "100/");
-		if (pi->link_cfg.supported & FW_PORT_CAP_SPEED_1G)
-			bufp += sprintf(bufp, "1000/");
-		if (pi->link_cfg.supported & FW_PORT_CAP_SPEED_10G)
-			bufp += sprintf(bufp, "10G/");
-		if (bufp != buf)
-			--bufp;
-		sprintf(bufp, "BASE-%s", base[pi->port_type]);
+static void __devinit enable_pcie_relaxed_ordering(struct pci_dev *dev)
+{
+	u16 v;
+	int pos;
 
-		netdev_info(dev, "Chelsio %s rev %d %s %sNIC PCIe x%d%s%s\n",
-			    adap->params.vpd.id, adap->params.rev,
-			    buf, is_offload(adap) ? "R" : "",
-			    adap->params.pci.width, spd,
-			    (adap->flags & USING_MSIX) ? " MSI-X" :
-			    (adap->flags & USING_MSI) ? " MSI" : "");
-		if (adap->name == dev->name)
-			netdev_info(dev, "S/N: %s, E/C: %s\n",
-				    adap->params.vpd.sn, adap->params.vpd.ec);
+	pos = pci_pcie_cap(dev);
+	if (pos > 0) {
+		pci_read_config_word(dev, pos + PCI_EXP_DEVCTL, &v);
+		v |= PCI_EXP_DEVCTL_RELAX_EN;
+		pci_write_config_word(dev, pos + PCI_EXP_DEVCTL, v);
 	}
 }
 
@@ -3611,6 +3610,7 @@ static int __devinit init_one(struct pci
 	}
 
 	pci_enable_pcie_error_reporting(pdev);
+	enable_pcie_relaxed_ordering(pdev);
 	pci_set_master(pdev);
 	pci_save_state(pdev);
 
@@ -3630,7 +3630,6 @@ static int __devinit init_one(struct pci
 	adapter->pdev = pdev;
 	adapter->pdev_dev = &pdev->dev;
 	adapter->fn = func;
-	adapter->name = pci_name(pdev);
 	adapter->msg_enable = dflt_msg_enable;
 	memset(adapter->chan_map, 0xff, sizeof(adapter->chan_map));
 
@@ -3664,7 +3663,6 @@ static int __devinit init_one(struct pci
 		pi->xact_addr_filt = -1;
 		pi->rx_offload = RX_CSO;
 		pi->port_id = i;
-		netif_carrier_off(netdev);
 		netdev->irq = pdev->irq;
 
 		netdev->features |= NETIF_F_SG | TSO_FLAGS;
@@ -3721,27 +3719,24 @@ static int __devinit init_one(struct pci
 	 * register at least one net device.
 	 */
 	for_each_port(adapter, i) {
+		pi = adap2pinfo(adapter, i);
+		netif_set_real_num_tx_queues(adapter->port[i], pi->nqsets);
+		netif_set_real_num_rx_queues(adapter->port[i], pi->nqsets);
+
 		err = register_netdev(adapter->port[i]);
 		if (err)
-			dev_warn(&pdev->dev,
-				 "cannot register net device %s, skipping\n",
-				 adapter->port[i]->name);
-		else {
-			/*
-			 * Change the name we use for messages to the name of
-			 * the first successfully registered interface.
-			 */
-			if (!adapter->registered_device_map)
-				adapter->name = adapter->port[i]->name;
-
-			__set_bit(i, &adapter->registered_device_map);
-			adapter->chan_map[adap2pinfo(adapter, i)->tx_chan] = i;
-		}
+			break;
+		adapter->chan_map[pi->tx_chan] = i;
+		print_port_info(adapter->port[i]);
 	}
-	if (!adapter->registered_device_map) {
+	if (i == 0) {
 		dev_err(&pdev->dev, "could not register any net devices\n");
 		goto out_free_dev;
 	}
+	if (err) {
+		dev_warn(&pdev->dev, "only %d net devices registered\n", i);
+		err = 0;
+	};
 
 	if (cxgb4_debugfs_root) {
 		adapter->debugfs_root = debugfs_create_dir(pci_name(pdev),
@@ -3752,8 +3747,6 @@ static int __devinit init_one(struct pci
 	if (is_offload(adapter))
 		attach_ulds(adapter);
 
-	print_port_info(adapter);
-
 sriov:
 #ifdef CONFIG_PCI_IOV
 	if (func < ARRAY_SIZE(num_vf) && num_vf[func] > 0)
@@ -3792,7 +3785,7 @@ static void __devexit remove_one(struct
 			detach_ulds(adapter);
 
 		for_each_port(adapter, i)
-			if (test_bit(i, &adapter->registered_device_map))
+			if (adapter->port[i]->reg_state == NETREG_REGISTERED)
 				unregister_netdev(adapter->port[i]);
 
 		if (adapter->debugfs_root)
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/cxgb4/sge.c linux-libre-2.6.38-gnu1/drivers/net/cxgb4/sge.c
--- linux-libre-2.6.37-gnu1/drivers/net/cxgb4/sge.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/cxgb4/sge.c	2011-03-14 21:20:32.000000000 -0400
@@ -579,6 +579,7 @@ static inline void __refill_fl(struct ad
  *	@phys: the physical address of the allocated ring
  *	@metadata: address of the array holding the SW state for the ring
  *	@stat_size: extra space in HW ring for status information
+ *	@node: preferred node for memory allocations
  *
  *	Allocates resources for an SGE descriptor ring, such as Tx queues,
  *	free buffer lists, or response queues.  Each SGE ring requires
@@ -590,7 +591,7 @@ static inline void __refill_fl(struct ad
  */
 static void *alloc_ring(struct device *dev, size_t nelem, size_t elem_size,
 			size_t sw_size, dma_addr_t *phys, void *metadata,
-			size_t stat_size)
+			size_t stat_size, int node)
 {
 	size_t len = nelem * elem_size + stat_size;
 	void *s = NULL;
@@ -599,7 +600,7 @@ static void *alloc_ring(struct device *d
 	if (!p)
 		return NULL;
 	if (sw_size) {
-		s = kcalloc(nelem, sw_size, GFP_KERNEL);
+		s = kzalloc_node(nelem * sw_size, GFP_KERNEL, node);
 
 		if (!s) {
 			dma_free_coherent(dev, len, p, *phys);
@@ -1982,7 +1983,7 @@ int t4_sge_alloc_rxq(struct adapter *ada
 	iq->size = roundup(iq->size, 16);
 
 	iq->desc = alloc_ring(adap->pdev_dev, iq->size, iq->iqe_len, 0,
-			      &iq->phys_addr, NULL, 0);
+			      &iq->phys_addr, NULL, 0, NUMA_NO_NODE);
 	if (!iq->desc)
 		return -ENOMEM;
 
@@ -2008,12 +2009,14 @@ int t4_sge_alloc_rxq(struct adapter *ada
 		fl->size = roundup(fl->size, 8);
 		fl->desc = alloc_ring(adap->pdev_dev, fl->size, sizeof(__be64),
 				      sizeof(struct rx_sw_desc), &fl->addr,
-				      &fl->sdesc, STAT_LEN);
+				      &fl->sdesc, STAT_LEN, NUMA_NO_NODE);
 		if (!fl->desc)
 			goto fl_nomem;
 
 		flsz = fl->size / 8 + STAT_LEN / sizeof(struct tx_desc);
 		c.iqns_to_fl0congen = htonl(FW_IQ_CMD_FL0PACKEN |
+					    FW_IQ_CMD_FL0FETCHRO(1) |
+					    FW_IQ_CMD_FL0DATARO(1) |
 					    FW_IQ_CMD_FL0PADEN);
 		c.fl0dcaen_to_fl0cidxfthresh = htons(FW_IQ_CMD_FL0FBMIN(2) |
 				FW_IQ_CMD_FL0FBMAX(3));
@@ -2093,7 +2096,8 @@ int t4_sge_alloc_eth_txq(struct adapter
 
 	txq->q.desc = alloc_ring(adap->pdev_dev, txq->q.size,
 			sizeof(struct tx_desc), sizeof(struct tx_sw_desc),
-			&txq->q.phys_addr, &txq->q.sdesc, STAT_LEN);
+			&txq->q.phys_addr, &txq->q.sdesc, STAT_LEN,
+			netdev_queue_numa_node_read(netdevq));
 	if (!txq->q.desc)
 		return -ENOMEM;
 
@@ -2106,6 +2110,7 @@ int t4_sge_alloc_eth_txq(struct adapter
 	c.viid_pkd = htonl(FW_EQ_ETH_CMD_VIID(pi->viid));
 	c.fetchszm_to_iqid = htonl(FW_EQ_ETH_CMD_HOSTFCMODE(2) |
 				   FW_EQ_ETH_CMD_PCIECHN(pi->tx_chan) |
+				   FW_EQ_ETH_CMD_FETCHRO(1) |
 				   FW_EQ_ETH_CMD_IQID(iqid));
 	c.dcaen_to_eqsize = htonl(FW_EQ_ETH_CMD_FBMIN(2) |
 				  FW_EQ_ETH_CMD_FBMAX(3) |
@@ -2144,7 +2149,7 @@ int t4_sge_alloc_ctrl_txq(struct adapter
 
 	txq->q.desc = alloc_ring(adap->pdev_dev, nentries,
 				 sizeof(struct tx_desc), 0, &txq->q.phys_addr,
-				 NULL, 0);
+				 NULL, 0, NUMA_NO_NODE);
 	if (!txq->q.desc)
 		return -ENOMEM;
 
@@ -2158,6 +2163,7 @@ int t4_sge_alloc_ctrl_txq(struct adapter
 	c.physeqid_pkd = htonl(0);
 	c.fetchszm_to_iqid = htonl(FW_EQ_CTRL_CMD_HOSTFCMODE(2) |
 				   FW_EQ_CTRL_CMD_PCIECHN(pi->tx_chan) |
+				   FW_EQ_CTRL_CMD_FETCHRO |
 				   FW_EQ_CTRL_CMD_IQID(iqid));
 	c.dcaen_to_eqsize = htonl(FW_EQ_CTRL_CMD_FBMIN(2) |
 				  FW_EQ_CTRL_CMD_FBMAX(3) |
@@ -2194,7 +2200,8 @@ int t4_sge_alloc_ofld_txq(struct adapter
 
 	txq->q.desc = alloc_ring(adap->pdev_dev, txq->q.size,
 			sizeof(struct tx_desc), sizeof(struct tx_sw_desc),
-			&txq->q.phys_addr, &txq->q.sdesc, STAT_LEN);
+			&txq->q.phys_addr, &txq->q.sdesc, STAT_LEN,
+			NUMA_NO_NODE);
 	if (!txq->q.desc)
 		return -ENOMEM;
 
@@ -2207,6 +2214,7 @@ int t4_sge_alloc_ofld_txq(struct adapter
 				 FW_EQ_OFLD_CMD_EQSTART | FW_LEN16(c));
 	c.fetchszm_to_iqid = htonl(FW_EQ_OFLD_CMD_HOSTFCMODE(2) |
 				   FW_EQ_OFLD_CMD_PCIECHN(pi->tx_chan) |
+				   FW_EQ_OFLD_CMD_FETCHRO(1) |
 				   FW_EQ_OFLD_CMD_IQID(iqid));
 	c.dcaen_to_eqsize = htonl(FW_EQ_OFLD_CMD_FBMIN(2) |
 				  FW_EQ_OFLD_CMD_FBMAX(3) |
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/cxgb4/t4fw_api.h linux-libre-2.6.38-gnu1/drivers/net/cxgb4/t4fw_api.h
--- linux-libre-2.6.37-gnu1/drivers/net/cxgb4/t4fw_api.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/cxgb4/t4fw_api.h	2011-03-14 21:20:32.000000000 -0400
@@ -1239,6 +1239,7 @@ enum fw_port_type {
 	FW_PORT_TYPE_KR,
 	FW_PORT_TYPE_SFP,
 	FW_PORT_TYPE_BP_AP,
+	FW_PORT_TYPE_BP4_AP,
 
 	FW_PORT_TYPE_NONE = FW_PORT_CMD_PTYPE_MASK
 };
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/cxgb4/t4_hw.c linux-libre-2.6.38-gnu1/drivers/net/cxgb4/t4_hw.c
--- linux-libre-2.6.37-gnu1/drivers/net/cxgb4/t4_hw.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/cxgb4/t4_hw.c	2011-03-14 21:20:32.000000000 -0400
@@ -183,7 +183,7 @@ static void dump_mbox(struct adapter *ad
 int t4_wr_mbox_meat(struct adapter *adap, int mbox, const void *cmd, int size,
 		    void *rpl, bool sleep_ok)
 {
-	static int delay[] = {
+	static const int delay[] = {
 		1, 1, 3, 5, 10, 10, 20, 50, 100, 200
 	};
 
@@ -330,18 +330,6 @@ int t4_edc_read(struct adapter *adap, in
 	return 0;
 }
 
-/*
- * Partial EEPROM Vital Product Data structure.  Includes only the ID and
- * VPD-R header.
- */
-struct t4_vpd_hdr {
-	u8  id_tag;
-	u8  id_len[2];
-	u8  id_data[ID_LEN];
-	u8  vpdr_tag;
-	u8  vpdr_len[2];
-};
-
 #define EEPROM_STAT_ADDR   0x7bfc
 #define VPD_BASE           0
 #define VPD_LEN            512
@@ -370,25 +358,38 @@ int t4_seeprom_wp(struct adapter *adapte
 static int get_vpd_params(struct adapter *adapter, struct vpd_params *p)
 {
 	int i, ret;
-	int ec, sn, v2;
+	int ec, sn;
 	u8 vpd[VPD_LEN], csum;
-	unsigned int vpdr_len;
-	const struct t4_vpd_hdr *v;
+	unsigned int vpdr_len, kw_offset, id_len;
 
 	ret = pci_read_vpd(adapter->pdev, VPD_BASE, sizeof(vpd), vpd);
 	if (ret < 0)
 		return ret;
 
-	v = (const struct t4_vpd_hdr *)vpd;
-	vpdr_len = pci_vpd_lrdt_size(&v->vpdr_tag);
-	if (vpdr_len + sizeof(struct t4_vpd_hdr) > VPD_LEN) {
+	if (vpd[0] != PCI_VPD_LRDT_ID_STRING) {
+		dev_err(adapter->pdev_dev, "missing VPD ID string\n");
+		return -EINVAL;
+	}
+
+	id_len = pci_vpd_lrdt_size(vpd);
+	if (id_len > ID_LEN)
+		id_len = ID_LEN;
+
+	i = pci_vpd_find_tag(vpd, 0, VPD_LEN, PCI_VPD_LRDT_RO_DATA);
+	if (i < 0) {
+		dev_err(adapter->pdev_dev, "missing VPD-R section\n");
+		return -EINVAL;
+	}
+
+	vpdr_len = pci_vpd_lrdt_size(&vpd[i]);
+	kw_offset = i + PCI_VPD_LRDT_TAG_SIZE;
+	if (vpdr_len + kw_offset > VPD_LEN) {
 		dev_err(adapter->pdev_dev, "bad VPD-R length %u\n", vpdr_len);
 		return -EINVAL;
 	}
 
 #define FIND_VPD_KW(var, name) do { \
-	var = pci_vpd_find_info_keyword(&v->id_tag, sizeof(struct t4_vpd_hdr), \
-					vpdr_len, name); \
+	var = pci_vpd_find_info_keyword(vpd, kw_offset, vpdr_len, name); \
 	if (var < 0) { \
 		dev_err(adapter->pdev_dev, "missing VPD keyword " name "\n"); \
 		return -EINVAL; \
@@ -408,11 +409,9 @@ static int get_vpd_params(struct adapter
 
 	FIND_VPD_KW(ec, "EC");
 	FIND_VPD_KW(sn, "SN");
-	FIND_VPD_KW(v2, "V2");
 #undef FIND_VPD_KW
 
-	p->cclk = simple_strtoul(vpd + v2, NULL, 10);
-	memcpy(p->id, v->id_data, ID_LEN);
+	memcpy(p->id, vpd + PCI_VPD_LRDT_TAG_SIZE, id_len);
 	strim(p->id);
 	memcpy(p->ec, vpd + ec, EC_LEN);
 	strim(p->ec);
@@ -919,7 +918,7 @@ static int t4_handle_intr_status(struct
  */
 static void pcie_intr_handler(struct adapter *adapter)
 {
-	static struct intr_info sysbus_intr_info[] = {
+	static const struct intr_info sysbus_intr_info[] = {
 		{ RNPP, "RXNP array parity error", -1, 1 },
 		{ RPCP, "RXPC array parity error", -1, 1 },
 		{ RCIP, "RXCIF array parity error", -1, 1 },
@@ -927,7 +926,7 @@ static void pcie_intr_handler(struct ada
 		{ RFTP, "RXFT array parity error", -1, 1 },
 		{ 0 }
 	};
-	static struct intr_info pcie_port_intr_info[] = {
+	static const struct intr_info pcie_port_intr_info[] = {
 		{ TPCP, "TXPC array parity error", -1, 1 },
 		{ TNPP, "TXNP array parity error", -1, 1 },
 		{ TFTP, "TXFT array parity error", -1, 1 },
@@ -939,7 +938,7 @@ static void pcie_intr_handler(struct ada
 		{ TDUE, "Tx uncorrectable data error", -1, 1 },
 		{ 0 }
 	};
-	static struct intr_info pcie_intr_info[] = {
+	static const struct intr_info pcie_intr_info[] = {
 		{ MSIADDRLPERR, "MSI AddrL parity error", -1, 1 },
 		{ MSIADDRHPERR, "MSI AddrH parity error", -1, 1 },
 		{ MSIDATAPERR, "MSI data parity error", -1, 1 },
@@ -991,7 +990,7 @@ static void pcie_intr_handler(struct ada
  */
 static void tp_intr_handler(struct adapter *adapter)
 {
-	static struct intr_info tp_intr_info[] = {
+	static const struct intr_info tp_intr_info[] = {
 		{ 0x3fffffff, "TP parity error", -1, 1 },
 		{ FLMTXFLSTEMPTY, "TP out of Tx pages", -1, 1 },
 		{ 0 }
@@ -1008,7 +1007,7 @@ static void sge_intr_handler(struct adap
 {
 	u64 v;
 
-	static struct intr_info sge_intr_info[] = {
+	static const struct intr_info sge_intr_info[] = {
 		{ ERR_CPL_EXCEED_IQE_SIZE,
 		  "SGE received CPL exceeding IQE size", -1, 1 },
 		{ ERR_INVALID_CIDX_INC,
@@ -1053,7 +1052,7 @@ static void sge_intr_handler(struct adap
  */
 static void cim_intr_handler(struct adapter *adapter)
 {
-	static struct intr_info cim_intr_info[] = {
+	static const struct intr_info cim_intr_info[] = {
 		{ PREFDROPINT, "CIM control register prefetch drop", -1, 1 },
 		{ OBQPARERR, "CIM OBQ parity error", -1, 1 },
 		{ IBQPARERR, "CIM IBQ parity error", -1, 1 },
@@ -1063,7 +1062,7 @@ static void cim_intr_handler(struct adap
 		{ TIEQOUTPARERRINT, "CIM TIEQ incoming parity error", -1, 1 },
 		{ 0 }
 	};
-	static struct intr_info cim_upintr_info[] = {
+	static const struct intr_info cim_upintr_info[] = {
 		{ RSVDSPACEINT, "CIM reserved space access", -1, 1 },
 		{ ILLTRANSINT, "CIM illegal transaction", -1, 1 },
 		{ ILLWRINT, "CIM illegal write", -1, 1 },
@@ -1110,7 +1109,7 @@ static void cim_intr_handler(struct adap
  */
 static void ulprx_intr_handler(struct adapter *adapter)
 {
-	static struct intr_info ulprx_intr_info[] = {
+	static const struct intr_info ulprx_intr_info[] = {
 		{ 0x1800000, "ULPRX context error", -1, 1 },
 		{ 0x7fffff, "ULPRX parity error", -1, 1 },
 		{ 0 }
@@ -1125,7 +1124,7 @@ static void ulprx_intr_handler(struct ad
  */
 static void ulptx_intr_handler(struct adapter *adapter)
 {
-	static struct intr_info ulptx_intr_info[] = {
+	static const struct intr_info ulptx_intr_info[] = {
 		{ PBL_BOUND_ERR_CH3, "ULPTX channel 3 PBL out of bounds", -1,
 		  0 },
 		{ PBL_BOUND_ERR_CH2, "ULPTX channel 2 PBL out of bounds", -1,
@@ -1147,7 +1146,7 @@ static void ulptx_intr_handler(struct ad
  */
 static void pmtx_intr_handler(struct adapter *adapter)
 {
-	static struct intr_info pmtx_intr_info[] = {
+	static const struct intr_info pmtx_intr_info[] = {
 		{ PCMD_LEN_OVFL0, "PMTX channel 0 pcmd too large", -1, 1 },
 		{ PCMD_LEN_OVFL1, "PMTX channel 1 pcmd too large", -1, 1 },
 		{ PCMD_LEN_OVFL2, "PMTX channel 2 pcmd too large", -1, 1 },
@@ -1169,7 +1168,7 @@ static void pmtx_intr_handler(struct ada
  */
 static void pmrx_intr_handler(struct adapter *adapter)
 {
-	static struct intr_info pmrx_intr_info[] = {
+	static const struct intr_info pmrx_intr_info[] = {
 		{ ZERO_E_CMD_ERROR, "PMRX 0-length pcmd", -1, 1 },
 		{ PMRX_FRAMING_ERROR, "PMRX framing error", -1, 1 },
 		{ OCSPI_PAR_ERROR, "PMRX ocspi parity error", -1, 1 },
@@ -1188,7 +1187,7 @@ static void pmrx_intr_handler(struct ada
  */
 static void cplsw_intr_handler(struct adapter *adapter)
 {
-	static struct intr_info cplsw_intr_info[] = {
+	static const struct intr_info cplsw_intr_info[] = {
 		{ CIM_OP_MAP_PERR, "CPLSW CIM op_map parity error", -1, 1 },
 		{ CIM_OVFL_ERROR, "CPLSW CIM overflow", -1, 1 },
 		{ TP_FRAMING_ERROR, "CPLSW TP framing error", -1, 1 },
@@ -1207,7 +1206,7 @@ static void cplsw_intr_handler(struct ad
  */
 static void le_intr_handler(struct adapter *adap)
 {
-	static struct intr_info le_intr_info[] = {
+	static const struct intr_info le_intr_info[] = {
 		{ LIPMISS, "LE LIP miss", -1, 0 },
 		{ LIP0, "LE 0 LIP error", -1, 0 },
 		{ PARITYERR, "LE parity error", -1, 1 },
@@ -1225,11 +1224,11 @@ static void le_intr_handler(struct adapt
  */
 static void mps_intr_handler(struct adapter *adapter)
 {
-	static struct intr_info mps_rx_intr_info[] = {
+	static const struct intr_info mps_rx_intr_info[] = {
 		{ 0xffffff, "MPS Rx parity error", -1, 1 },
 		{ 0 }
 	};
-	static struct intr_info mps_tx_intr_info[] = {
+	static const struct intr_info mps_tx_intr_info[] = {
 		{ TPFIFO, "MPS Tx TP FIFO parity error", -1, 1 },
 		{ NCSIFIFO, "MPS Tx NC-SI FIFO parity error", -1, 1 },
 		{ TXDATAFIFO, "MPS Tx data FIFO parity error", -1, 1 },
@@ -1239,25 +1238,25 @@ static void mps_intr_handler(struct adap
 		{ FRMERR, "MPS Tx framing error", -1, 1 },
 		{ 0 }
 	};
-	static struct intr_info mps_trc_intr_info[] = {
+	static const struct intr_info mps_trc_intr_info[] = {
 		{ FILTMEM, "MPS TRC filter parity error", -1, 1 },
 		{ PKTFIFO, "MPS TRC packet FIFO parity error", -1, 1 },
 		{ MISCPERR, "MPS TRC misc parity error", -1, 1 },
 		{ 0 }
 	};
-	static struct intr_info mps_stat_sram_intr_info[] = {
+	static const struct intr_info mps_stat_sram_intr_info[] = {
 		{ 0x1fffff, "MPS statistics SRAM parity error", -1, 1 },
 		{ 0 }
 	};
-	static struct intr_info mps_stat_tx_intr_info[] = {
+	static const struct intr_info mps_stat_tx_intr_info[] = {
 		{ 0xfffff, "MPS statistics Tx FIFO parity error", -1, 1 },
 		{ 0 }
 	};
-	static struct intr_info mps_stat_rx_intr_info[] = {
+	static const struct intr_info mps_stat_rx_intr_info[] = {
 		{ 0xffffff, "MPS statistics Rx FIFO parity error", -1, 1 },
 		{ 0 }
 	};
-	static struct intr_info mps_cls_intr_info[] = {
+	static const struct intr_info mps_cls_intr_info[] = {
 		{ MATCHSRAM, "MPS match SRAM parity error", -1, 1 },
 		{ MATCHTCAM, "MPS match TCAM parity error", -1, 1 },
 		{ HASHSRAM, "MPS hash SRAM parity error", -1, 1 },
@@ -1356,7 +1355,7 @@ static void ma_intr_handler(struct adapt
  */
 static void smb_intr_handler(struct adapter *adap)
 {
-	static struct intr_info smb_intr_info[] = {
+	static const struct intr_info smb_intr_info[] = {
 		{ MSTTXFIFOPARINT, "SMB master Tx FIFO parity error", -1, 1 },
 		{ MSTRXFIFOPARINT, "SMB master Rx FIFO parity error", -1, 1 },
 		{ SLVFIFOPARINT, "SMB slave FIFO parity error", -1, 1 },
@@ -1372,7 +1371,7 @@ static void smb_intr_handler(struct adap
  */
 static void ncsi_intr_handler(struct adapter *adap)
 {
-	static struct intr_info ncsi_intr_info[] = {
+	static const struct intr_info ncsi_intr_info[] = {
 		{ CIM_DM_PRTY_ERR, "NC-SI CIM parity error", -1, 1 },
 		{ MPS_DM_PRTY_ERR, "NC-SI MPS parity error", -1, 1 },
 		{ TXFIFO_PRTY_ERR, "NC-SI Tx FIFO parity error", -1, 1 },
@@ -1410,7 +1409,7 @@ static void xgmac_intr_handler(struct ad
  */
 static void pl_intr_handler(struct adapter *adap)
 {
-	static struct intr_info pl_intr_info[] = {
+	static const struct intr_info pl_intr_info[] = {
 		{ FATALPERR, "T4 fatal parity error", -1, 1 },
 		{ PERRVFID, "PL VFID_MAP parity error", -1, 1 },
 		{ 0 }
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/cxgb4vf/adapter.h linux-libre-2.6.38-gnu1/drivers/net/cxgb4vf/adapter.h
--- linux-libre-2.6.37-gnu1/drivers/net/cxgb4vf/adapter.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/cxgb4vf/adapter.h	2011-03-14 21:20:32.000000000 -0400
@@ -60,7 +60,7 @@ enum {
 	 * MSI-X interrupt index usage.
 	 */
 	MSIX_FW		= 0,		/* MSI-X index for firmware Q */
-	MSIX_NIQFLINT	= 1,		/* MSI-X index base for Ingress Qs */
+	MSIX_IQFLINT	= 1,		/* MSI-X index base for Ingress Qs */
 	MSIX_EXTRAS	= 1,
 	MSIX_ENTRIES	= MAX_ETH_QSETS + MSIX_EXTRAS,
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/cxgb4vf/cxgb4vf_main.c linux-libre-2.6.38-gnu1/drivers/net/cxgb4vf/cxgb4vf_main.c
--- linux-libre-2.6.37-gnu1/drivers/net/cxgb4vf/cxgb4vf_main.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/cxgb4vf/cxgb4vf_main.c	2011-03-14 21:20:32.000000000 -0400
@@ -280,9 +280,7 @@ static void name_msix_vecs(struct adapte
 		const struct port_info *pi = netdev_priv(dev);
 		int qs, msi;
 
-		for (qs = 0, msi = MSIX_NIQFLINT;
-		     qs < pi->nqsets;
-		     qs++, msi++) {
+		for (qs = 0, msi = MSIX_IQFLINT; qs < pi->nqsets; qs++, msi++) {
 			snprintf(adapter->msix_info[msi].desc, namelen,
 				 "%s-%d", dev->name, qs);
 			adapter->msix_info[msi].desc[namelen] = 0;
@@ -309,7 +307,7 @@ static int request_msix_queue_irqs(struc
 	/*
 	 * Ethernet queues.
 	 */
-	msi = MSIX_NIQFLINT;
+	msi = MSIX_IQFLINT;
 	for_each_ethrxq(s, rxq) {
 		err = request_irq(adapter->msix_info[msi].vec,
 				  t4vf_sge_intr_msix, 0,
@@ -337,7 +335,7 @@ static void free_msix_queue_irqs(struct
 	int rxq, msi;
 
 	free_irq(adapter->msix_info[MSIX_FW].vec, &s->fw_evtq);
-	msi = MSIX_NIQFLINT;
+	msi = MSIX_IQFLINT;
 	for_each_ethrxq(s, rxq)
 		free_irq(adapter->msix_info[msi++].vec,
 			 &s->ethrxq[rxq].rspq);
@@ -527,7 +525,7 @@ static int setup_sge_queues(struct adapt
 	 * brought up at which point lots of things get nailed down
 	 * permanently ...
 	 */
-	msix = MSIX_NIQFLINT;
+	msix = MSIX_IQFLINT;
 	for_each_port(adapter, pidx) {
 		struct net_device *dev = adapter->port[pidx];
 		struct port_info *pi = netdev_priv(dev);
@@ -751,13 +749,19 @@ static int cxgb4vf_open(struct net_devic
 	netif_set_real_num_tx_queues(dev, pi->nqsets);
 	err = netif_set_real_num_rx_queues(dev, pi->nqsets);
 	if (err)
-		return err;
-	set_bit(pi->port_id, &adapter->open_device_map);
+		goto err_unwind;
 	err = link_start(dev);
 	if (err)
-		return err;
+		goto err_unwind;
+
 	netif_tx_start_all_queues(dev);
+	set_bit(pi->port_id, &adapter->open_device_map);
 	return 0;
+
+err_unwind:
+	if (adapter->open_device_map == 0)
+		adapter_down(adapter);
+	return err;
 }
 
 /*
@@ -766,13 +770,12 @@ static int cxgb4vf_open(struct net_devic
  */
 static int cxgb4vf_stop(struct net_device *dev)
 {
-	int ret;
 	struct port_info *pi = netdev_priv(dev);
 	struct adapter *adapter = pi->adapter;
 
 	netif_tx_stop_all_queues(dev);
 	netif_carrier_off(dev);
-	ret = t4vf_enable_vi(adapter, pi->viid, false, false);
+	t4vf_enable_vi(adapter, pi->viid, false, false);
 	pi->link_cfg.link_ok = 0;
 
 	clear_bit(pi->port_id, &adapter->open_device_map);
@@ -1365,6 +1368,8 @@ struct queue_port_stats {
 	u64 rx_csum;
 	u64 vlan_ex;
 	u64 vlan_ins;
+	u64 lro_pkts;
+	u64 lro_merged;
 };
 
 /*
@@ -1402,6 +1407,8 @@ static const char stats_strings[][ETH_GS
 	"RxCsumGood        ",
 	"VLANextractions   ",
 	"VLANinsertions    ",
+	"GROPackets        ",
+	"GROMerged         ",
 };
 
 /*
@@ -1451,6 +1458,8 @@ static void collect_sge_port_stats(const
 		stats->rx_csum += rxq->stats.rx_cso;
 		stats->vlan_ex += rxq->stats.vlan_ex;
 		stats->vlan_ins += txq->vlan_ins;
+		stats->lro_pkts += rxq->stats.lro_pkts;
+		stats->lro_merged += rxq->stats.lro_merged;
 	}
 }
 
@@ -1547,14 +1556,19 @@ static void cxgb4vf_get_wol(struct net_d
 }
 
 /*
+ * TCP Segmentation Offload flags which we support.
+ */
+#define TSO_FLAGS (NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_TSO_ECN)
+
+/*
  * Set TCP Segmentation Offloading feature capabilities.
  */
 static int cxgb4vf_set_tso(struct net_device *dev, u32 tso)
 {
 	if (tso)
-		dev->features |= NETIF_F_TSO | NETIF_F_TSO6;
+		dev->features |= TSO_FLAGS;
 	else
-		dev->features &= ~(NETIF_F_TSO | NETIF_F_TSO6);
+		dev->features &= ~TSO_FLAGS;
 	return 0;
 }
 
@@ -2026,7 +2040,7 @@ static int __devinit setup_debugfs(struc
 {
 	int i;
 
-	BUG_ON(adapter->debugfs_root == NULL);
+	BUG_ON(IS_ERR_OR_NULL(adapter->debugfs_root));
 
 	/*
 	 * Debugfs support is best effort.
@@ -2045,9 +2059,9 @@ static int __devinit setup_debugfs(struc
  * Tear down the /sys/kernel/debug/cxgb4vf sub-nodes created above.  We leave
  * it to our caller to tear down the directory (debugfs_root).
  */
-static void __devexit cleanup_debugfs(struct adapter *adapter)
+static void cleanup_debugfs(struct adapter *adapter)
 {
-	BUG_ON(adapter->debugfs_root == NULL);
+	BUG_ON(IS_ERR_OR_NULL(adapter->debugfs_root));
 
 	/*
 	 * Unlike our sister routine cleanup_proc(), we don't need to remove
@@ -2063,7 +2077,7 @@ static void __devexit cleanup_debugfs(st
  * adapter parameters we're going to be using and initialize basic adapter
  * hardware support.
  */
-static int adap_init0(struct adapter *adapter)
+static int __devinit adap_init0(struct adapter *adapter)
 {
 	struct vf_resources *vfres = &adapter->params.vfres;
 	struct sge_params *sge_params = &adapter->params.sge;
@@ -2475,17 +2489,6 @@ static int __devinit cxgb4vf_pci_probe(s
 	struct net_device *netdev;
 
 	/*
-	 * Vet our module parameters.
-	 */
-	if (msi != MSI_MSIX && msi != MSI_MSI) {
-		dev_err(&pdev->dev, "bad module parameter msi=%d; must be %d"
-			" (MSI-X or MSI) or %d (MSI)\n", msi, MSI_MSIX,
-			MSI_MSI);
-		err = -EINVAL;
-		goto err_out;
-	}
-
-	/*
 	 * Print our driver banner the first time we're called to initialize a
 	 * device.
 	 */
@@ -2494,7 +2497,6 @@ static int __devinit cxgb4vf_pci_probe(s
 		version_printed = 1;
 	}
 
-
 	/*
 	 * Initialize generic PCI device state.
 	 */
@@ -2631,7 +2633,7 @@ static int __devinit cxgb4vf_pci_probe(s
 		netif_carrier_off(netdev);
 		netdev->irq = pdev->irq;
 
-		netdev->features = (NETIF_F_SG | NETIF_F_TSO | NETIF_F_TSO6 |
+		netdev->features = (NETIF_F_SG | TSO_FLAGS |
 				    NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
 				    NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX |
 				    NETIF_F_GRO);
@@ -2698,11 +2700,11 @@ static int __devinit cxgb4vf_pci_probe(s
 	/*
 	 * Set up our debugfs entries.
 	 */
-	if (cxgb4vf_debugfs_root) {
+	if (!IS_ERR_OR_NULL(cxgb4vf_debugfs_root)) {
 		adapter->debugfs_root =
 			debugfs_create_dir(pci_name(pdev),
 					   cxgb4vf_debugfs_root);
-		if (adapter->debugfs_root == NULL)
+		if (IS_ERR_OR_NULL(adapter->debugfs_root))
 			dev_warn(&pdev->dev, "could not create debugfs"
 				 " directory");
 		else
@@ -2757,7 +2759,7 @@ static int __devinit cxgb4vf_pci_probe(s
 	 */
 
 err_free_debugfs:
-	if (adapter->debugfs_root) {
+	if (!IS_ERR_OR_NULL(adapter->debugfs_root)) {
 		cleanup_debugfs(adapter);
 		debugfs_remove_recursive(adapter->debugfs_root);
 	}
@@ -2789,7 +2791,6 @@ err_release_regions:
 err_disable_device:
 	pci_disable_device(pdev);
 
-err_out:
 	return err;
 }
 
@@ -2827,7 +2828,7 @@ static void __devexit cxgb4vf_pci_remove
 		/*
 		 * Tear down our debugfs entries.
 		 */
-		if (adapter->debugfs_root) {
+		if (!IS_ERR_OR_NULL(adapter->debugfs_root)) {
 			cleanup_debugfs(adapter);
 			debugfs_remove_recursive(adapter->debugfs_root);
 		}
@@ -2861,6 +2862,46 @@ static void __devexit cxgb4vf_pci_remove
 }
 
 /*
+ * "Shutdown" quiesce the device, stopping Ingress Packet and Interrupt
+ * delivery.
+ */
+static void __devexit cxgb4vf_pci_shutdown(struct pci_dev *pdev)
+{
+	struct adapter *adapter;
+	int pidx;
+
+	adapter = pci_get_drvdata(pdev);
+	if (!adapter)
+		return;
+
+	/*
+	 * Disable all Virtual Interfaces.  This will shut down the
+	 * delivery of all ingress packets into the chip for these
+	 * Virtual Interfaces.
+	 */
+	for_each_port(adapter, pidx) {
+		struct net_device *netdev;
+		struct port_info *pi;
+
+		if (!test_bit(pidx, &adapter->registered_device_map))
+			continue;
+
+		netdev = adapter->port[pidx];
+		if (!netdev)
+			continue;
+
+		pi = netdev_priv(netdev);
+		t4vf_enable_vi(adapter, pi->viid, false, false);
+	}
+
+	/*
+	 * Free up all Queues which will prevent further DMA and
+	 * Interrupts allowing various internal pathways to drain.
+	 */
+	t4vf_free_sge_resources(adapter);
+}
+
+/*
  * PCI Device registration data structures.
  */
 #define CH_DEVICE(devid, idx) \
@@ -2893,6 +2934,7 @@ static struct pci_driver cxgb4vf_driver
 	.id_table	= cxgb4vf_pci_tbl,
 	.probe		= cxgb4vf_pci_probe,
 	.remove		= __devexit_p(cxgb4vf_pci_remove),
+	.shutdown	= __devexit_p(cxgb4vf_pci_shutdown),
 };
 
 /*
@@ -2902,14 +2944,25 @@ static int __init cxgb4vf_module_init(vo
 {
 	int ret;
 
+	/*
+	 * Vet our module parameters.
+	 */
+	if (msi != MSI_MSIX && msi != MSI_MSI) {
+		printk(KERN_WARNING KBUILD_MODNAME
+		       ": bad module parameter msi=%d; must be %d"
+		       " (MSI-X or MSI) or %d (MSI)\n",
+		       msi, MSI_MSIX, MSI_MSI);
+		return -EINVAL;
+	}
+
 	/* Debugfs support is optional, just warn if this fails */
 	cxgb4vf_debugfs_root = debugfs_create_dir(KBUILD_MODNAME, NULL);
-	if (!cxgb4vf_debugfs_root)
+	if (IS_ERR_OR_NULL(cxgb4vf_debugfs_root))
 		printk(KERN_WARNING KBUILD_MODNAME ": could not create"
 		       " debugfs entry, continuing\n");
 
 	ret = pci_register_driver(&cxgb4vf_driver);
-	if (ret < 0)
+	if (ret < 0 && !IS_ERR_OR_NULL(cxgb4vf_debugfs_root))
 		debugfs_remove(cxgb4vf_debugfs_root);
 	return ret;
 }
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/cxgb4vf/sge.c linux-libre-2.6.38-gnu1/drivers/net/cxgb4vf/sge.c
--- linux-libre-2.6.37-gnu1/drivers/net/cxgb4vf/sge.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/cxgb4vf/sge.c	2011-03-14 21:20:32.000000000 -0400
@@ -1568,6 +1568,9 @@ int t4vf_ethrx_handler(struct sge_rspq *
 	} else
 		skb_checksum_none_assert(skb);
 
+	/*
+	 * Deliver the packet to the stack.
+	 */
 	if (unlikely(pkt->vlan_ex)) {
 		struct vlan_group *grp = pi->vlan_grp;
 
@@ -2143,7 +2146,7 @@ int t4vf_sge_alloc_rxq(struct adapter *a
 
 		/*
 		 * Calculate the size of the hardware free list ring plus
-		 * status page (which the SGE will place at the end of the
+		 * Status Page (which the SGE will place after the end of the
 		 * free list ring) in Egress Queue Units.
 		 */
 		flsz = (fl->size / FL_PER_EQ_UNIT +
@@ -2240,8 +2243,8 @@ int t4vf_sge_alloc_eth_txq(struct adapte
 	struct port_info *pi = netdev_priv(dev);
 
 	/*
-	 * Calculate the size of the hardware TX Queue (including the
-	 * status age on the end) in units of TX Descriptors.
+	 * Calculate the size of the hardware TX Queue (including the Status
+	 * Page on the end of the TX Queue) in units of TX Descriptors.
 	 */
 	nentries = txq->q.size + STAT_LEN / sizeof(struct tx_desc);
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/cxgb4vf/t4vf_hw.c linux-libre-2.6.38-gnu1/drivers/net/cxgb4vf/t4vf_hw.c
--- linux-libre-2.6.37-gnu1/drivers/net/cxgb4vf/t4vf_hw.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/cxgb4vf/t4vf_hw.c	2011-03-14 21:20:32.000000000 -0400
@@ -116,7 +116,7 @@ static void dump_mbox(struct adapter *ad
 int t4vf_wr_mbox_core(struct adapter *adapter, const void *cmd, int size,
 		      void *rpl, bool sleep_ok)
 {
-	static int delay[] = {
+	static const int delay[] = {
 		1, 1, 3, 5, 10, 10, 20, 50, 100
 	};
 
@@ -147,9 +147,20 @@ int t4vf_wr_mbox_core(struct adapter *ad
 	/*
 	 * Write the command array into the Mailbox Data register array and
 	 * transfer ownership of the mailbox to the firmware.
+	 *
+	 * For the VFs, the Mailbox Data "registers" are actually backed by
+	 * T4's "MA" interface rather than PL Registers (as is the case for
+	 * the PFs).  Because these are in different coherency domains, the
+	 * write to the VF's PL-register-backed Mailbox Control can race in
+	 * front of the writes to the MA-backed VF Mailbox Data "registers".
+	 * So we need to do a read-back on at least one byte of the VF Mailbox
+	 * Data registers before doing the write to the VF Mailbox Control
+	 * register.
 	 */
 	for (i = 0, p = cmd; i < size; i += 8)
 		t4_write_reg64(adapter, mbox_data + i, be64_to_cpu(*p++));
+	t4_read_reg(adapter, mbox_data);         /* flush write */
+
 	t4_write_reg(adapter, mbox_ctl,
 		     MBMSGVALID | MBOWNER(MBOX_OWNER_FW));
 	t4_read_reg(adapter, mbox_ctl);          /* flush write */
@@ -160,7 +171,7 @@ int t4vf_wr_mbox_core(struct adapter *ad
 	delay_idx = 0;
 	ms = delay[0];
 
-	for (i = 0; i < 500; i += ms) {
+	for (i = 0; i < FW_CMD_MAX_TIMEOUT; i += ms) {
 		if (sleep_ok) {
 			ms = delay[delay_idx];
 			if (delay_idx < ARRAY_SIZE(delay) - 1)
@@ -1300,7 +1311,7 @@ int t4vf_eth_eq_free(struct adapter *ada
  */
 int t4vf_handle_fw_rpl(struct adapter *adapter, const __be64 *rpl)
 {
-	struct fw_cmd_hdr *cmd_hdr = (struct fw_cmd_hdr *)rpl;
+	const struct fw_cmd_hdr *cmd_hdr = (const struct fw_cmd_hdr *)rpl;
 	u8 opcode = FW_CMD_OP_GET(be32_to_cpu(cmd_hdr->hi));
 
 	switch (opcode) {
@@ -1308,7 +1319,8 @@ int t4vf_handle_fw_rpl(struct adapter *a
 		/*
 		 * Link/module state change message.
 		 */
-		const struct fw_port_cmd *port_cmd = (void *)rpl;
+		const struct fw_port_cmd *port_cmd =
+			(const struct fw_port_cmd *)rpl;
 		u32 word;
 		int action, port_id, link_ok, speed, fc, pidx;
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/davinci_emac.c linux-libre-2.6.38-gnu1/drivers/net/davinci_emac.c
--- linux-libre-2.6.37-gnu1/drivers/net/davinci_emac.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/davinci_emac.c	2011-03-14 21:20:32.000000000 -0400
@@ -1008,7 +1008,7 @@ static void emac_rx_handler(void *token,
 	int			ret;
 
 	/* free and bail if we are shutting down */
-	if (unlikely(!netif_running(ndev))) {
+	if (unlikely(!netif_running(ndev) || !netif_carrier_ok(ndev))) {
 		dev_kfree_skb_any(skb);
 		return;
 	}
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/depca.c linux-libre-2.6.38-gnu1/drivers/net/depca.c
--- linux-libre-2.6.37-gnu1/drivers/net/depca.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/depca.c	2011-03-14 21:20:32.000000000 -0400
@@ -1094,7 +1094,7 @@ static int depca_rx(struct net_device *d
 				}
 			}
 			/* Change buffer ownership for this last frame, back to the adapter */
-			for (; lp->rx_old != entry; lp->rx_old = (++lp->rx_old) & lp->rxRingMask) {
+			for (; lp->rx_old != entry; lp->rx_old = (lp->rx_old + 1) & lp->rxRingMask) {
 				writel(readl(&lp->rx_ring[lp->rx_old].base) | R_OWN, &lp->rx_ring[lp->rx_old].base);
 			}
 			writel(readl(&lp->rx_ring[entry].base) | R_OWN, &lp->rx_ring[entry].base);
@@ -1103,7 +1103,7 @@ static int depca_rx(struct net_device *d
 		/*
 		   ** Update entry information
 		 */
-		lp->rx_new = (++lp->rx_new) & lp->rxRingMask;
+		lp->rx_new = (lp->rx_new + 1) & lp->rxRingMask;
 	}
 
 	return 0;
@@ -1148,7 +1148,7 @@ static int depca_tx(struct net_device *d
 		}
 
 		/* Update all the pointers */
-		lp->tx_old = (++lp->tx_old) & lp->txRingMask;
+		lp->tx_old = (lp->tx_old + 1) & lp->txRingMask;
 	}
 
 	return 0;
@@ -1513,7 +1513,7 @@ static enum depca_type __init depca_shme
 	return adapter;
 }
 
-static int __init depca_isa_probe (struct platform_device *device)
+static int __devinit depca_isa_probe (struct platform_device *device)
 {
 	struct net_device *dev;
 	struct depca_private *lp;
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/dl2k.c linux-libre-2.6.38-gnu1/drivers/net/dl2k.c
--- linux-libre-2.6.37-gnu1/drivers/net/dl2k.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/dl2k.c	2011-03-14 21:20:32.000000000 -0400
@@ -1753,8 +1753,6 @@ rio_close (struct net_device *dev)
 
 	/* Free all the skbuffs in the queue. */
 	for (i = 0; i < RX_RING_SIZE; i++) {
-		np->rx_ring[i].status = 0;
-		np->rx_ring[i].fraginfo = 0;
 		skb = np->rx_skbuff[i];
 		if (skb) {
 			pci_unmap_single(np->pdev,
@@ -1763,6 +1761,8 @@ rio_close (struct net_device *dev)
 			dev_kfree_skb (skb);
 			np->rx_skbuff[i] = NULL;
 		}
+		np->rx_ring[i].status = 0;
+		np->rx_ring[i].fraginfo = 0;
 	}
 	for (i = 0; i < TX_RING_SIZE; i++) {
 		skb = np->tx_skbuff[i];
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/dm9000.c linux-libre-2.6.38-gnu1/drivers/net/dm9000.c
--- linux-libre-2.6.37-gnu1/drivers/net/dm9000.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/dm9000.c	2011-03-14 21:20:32.000000000 -0400
@@ -802,10 +802,7 @@ dm9000_init_dm9000(struct net_device *de
 	/* Checksum mode */
 	dm9000_set_rx_csum_unlocked(dev, db->rx_csum);
 
-	/* GPIO0 on pre-activate PHY */
-	iow(db, DM9000_GPR, 0);	/* REG_1F bit0 activate phyxcer */
 	iow(db, DM9000_GPCR, GPCR_GEP_CNTL);	/* Let GPIO0 output */
-	iow(db, DM9000_GPR, 0);	/* Enable PHY */
 
 	ncr = (db->flags & DM9000_PLATF_EXT_PHY) ? NCR_EXT_PHY : 0;
 
@@ -852,8 +849,8 @@ static void dm9000_timeout(struct net_de
 	unsigned long flags;
 
 	/* Save previous register address */
-	reg_save = readb(db->io_addr);
 	spin_lock_irqsave(&db->lock, flags);
+	reg_save = readb(db->io_addr);
 
 	netif_stop_queue(dev);
 	dm9000_reset(db);
@@ -1194,6 +1191,10 @@ dm9000_open(struct net_device *dev)
 	if (request_irq(dev->irq, dm9000_interrupt, irqflags, dev->name, dev))
 		return -EAGAIN;
 
+	/* GPIO0 on pre-activate PHY, Reg 1F is not set by reset */
+	iow(db, DM9000_GPR, 0);	/* REG_1F bit0 activate phyxcer */
+	mdelay(1); /* delay needs by DM9000B */
+
 	/* Initialize DM9000 board */
 	dm9000_reset(db);
 	dm9000_init_dm9000(dev);
@@ -1675,7 +1676,7 @@ dm9000_drv_remove(struct platform_device
 	platform_set_drvdata(pdev, NULL);
 
 	unregister_netdev(ndev);
-	dm9000_release_board(pdev, (board_info_t *) netdev_priv(ndev));
+	dm9000_release_board(pdev, netdev_priv(ndev));
 	free_netdev(ndev);		/* free device structure */
 
 	dev_dbg(&pdev->dev, "released and freed device\n");
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/dnet.c linux-libre-2.6.38-gnu1/drivers/net/dnet.c
--- linux-libre-2.6.37-gnu1/drivers/net/dnet.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/dnet.c	2011-03-14 21:20:32.000000000 -0400
@@ -337,8 +337,6 @@ static int dnet_mii_init(struct dnet *bp
 	for (i = 0; i < PHY_MAX_ADDR; i++)
 		bp->mii_bus->irq[i] = PHY_POLL;
 
-	platform_set_drvdata(bp->dev, bp->mii_bus);
-
 	if (mdiobus_register(bp->mii_bus)) {
 		err = -ENXIO;
 		goto err_out_free_mdio_irq;
@@ -863,6 +861,7 @@ static int __devinit dnet_probe(struct p
 	bp = netdev_priv(dev);
 	bp->dev = dev;
 
+	platform_set_drvdata(pdev, dev);
 	SET_NETDEV_DEV(dev, &pdev->dev);
 
 	spin_lock_init(&bp->lock);
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/e1000/e1000_hw.c linux-libre-2.6.38-gnu1/drivers/net/e1000/e1000_hw.c
--- linux-libre-2.6.37-gnu1/drivers/net/e1000/e1000_hw.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/e1000/e1000_hw.c	2011-03-14 21:20:32.000000000 -0400
@@ -124,16 +124,22 @@ static s32 e1000_set_phy_type(struct e10
 	case M88E1000_I_PHY_ID:
 	case M88E1011_I_PHY_ID:
 	case M88E1111_I_PHY_ID:
+	case M88E1118_E_PHY_ID:
 		hw->phy_type = e1000_phy_m88;
 		break;
 	case IGP01E1000_I_PHY_ID:
 		if (hw->mac_type == e1000_82541 ||
 		    hw->mac_type == e1000_82541_rev_2 ||
 		    hw->mac_type == e1000_82547 ||
-		    hw->mac_type == e1000_82547_rev_2) {
+		    hw->mac_type == e1000_82547_rev_2)
 			hw->phy_type = e1000_phy_igp;
-			break;
-		}
+		break;
+	case RTL8211B_PHY_ID:
+		hw->phy_type = e1000_phy_8211;
+		break;
+	case RTL8201N_PHY_ID:
+		hw->phy_type = e1000_phy_8201;
+		break;
 	default:
 		/* Should never have loaded on this device */
 		hw->phy_type = e1000_phy_undefined;
@@ -318,6 +324,9 @@ s32 e1000_set_mac_type(struct e1000_hw *
 	case E1000_DEV_ID_82547GI:
 		hw->mac_type = e1000_82547_rev_2;
 		break;
+	case E1000_DEV_ID_INTEL_CE4100_GBE:
+		hw->mac_type = e1000_ce4100;
+		break;
 	default:
 		/* Should never have loaded on this device */
 		return -E1000_ERR_MAC_TYPE;
@@ -372,6 +381,9 @@ void e1000_set_media_type(struct e1000_h
 		case e1000_82542_rev2_1:
 			hw->media_type = e1000_media_type_fiber;
 			break;
+		case e1000_ce4100:
+			hw->media_type = e1000_media_type_copper;
+			break;
 		default:
 			status = er32(STATUS);
 			if (status & E1000_STATUS_TBIMODE) {
@@ -460,6 +472,7 @@ s32 e1000_reset_hw(struct e1000_hw *hw)
 		/* Reset is performed on a shadow of the control register */
 		ew32(CTRL_DUP, (ctrl | E1000_CTRL_RST));
 		break;
+	case e1000_ce4100:
 	default:
 		ew32(CTRL, (ctrl | E1000_CTRL_RST));
 		break;
@@ -952,6 +965,67 @@ static s32 e1000_setup_fiber_serdes_link
 }
 
 /**
+ * e1000_copper_link_rtl_setup - Copper link setup for e1000_phy_rtl series.
+ * @hw: Struct containing variables accessed by shared code
+ *
+ * Commits changes to PHY configuration by calling e1000_phy_reset().
+ */
+static s32 e1000_copper_link_rtl_setup(struct e1000_hw *hw)
+{
+	s32 ret_val;
+
+	/* SW reset the PHY so all changes take effect */
+	ret_val = e1000_phy_reset(hw);
+	if (ret_val) {
+		e_dbg("Error Resetting the PHY\n");
+		return ret_val;
+	}
+
+	return E1000_SUCCESS;
+}
+
+static s32 gbe_dhg_phy_setup(struct e1000_hw *hw)
+{
+	s32 ret_val;
+	u32 ctrl_aux;
+
+	switch (hw->phy_type) {
+	case e1000_phy_8211:
+		ret_val = e1000_copper_link_rtl_setup(hw);
+		if (ret_val) {
+			e_dbg("e1000_copper_link_rtl_setup failed!\n");
+			return ret_val;
+		}
+		break;
+	case e1000_phy_8201:
+		/* Set RMII mode */
+		ctrl_aux = er32(CTL_AUX);
+		ctrl_aux |= E1000_CTL_AUX_RMII;
+		ew32(CTL_AUX, ctrl_aux);
+		E1000_WRITE_FLUSH();
+
+		/* Disable the J/K bits required for receive */
+		ctrl_aux = er32(CTL_AUX);
+		ctrl_aux |= 0x4;
+		ctrl_aux &= ~0x2;
+		ew32(CTL_AUX, ctrl_aux);
+		E1000_WRITE_FLUSH();
+		ret_val = e1000_copper_link_rtl_setup(hw);
+
+		if (ret_val) {
+			e_dbg("e1000_copper_link_rtl_setup failed!\n");
+			return ret_val;
+		}
+		break;
+	default:
+		e_dbg("Error Resetting the PHY\n");
+		return E1000_ERR_PHY_TYPE;
+	}
+
+	return E1000_SUCCESS;
+}
+
+/**
  * e1000_copper_link_preconfig - early configuration for copper
  * @hw: Struct containing variables accessed by shared code
  *
@@ -1286,6 +1360,10 @@ static s32 e1000_copper_link_autoneg(str
 	if (hw->autoneg_advertised == 0)
 		hw->autoneg_advertised = AUTONEG_ADVERTISE_SPEED_DEFAULT;
 
+	/* IFE/RTL8201N PHY only supports 10/100 */
+	if (hw->phy_type == e1000_phy_8201)
+		hw->autoneg_advertised &= AUTONEG_ADVERTISE_10_100_ALL;
+
 	e_dbg("Reconfiguring auto-neg advertisement params\n");
 	ret_val = e1000_phy_setup_autoneg(hw);
 	if (ret_val) {
@@ -1341,7 +1419,7 @@ static s32 e1000_copper_link_postconfig(
 	s32 ret_val;
 	e_dbg("e1000_copper_link_postconfig");
 
-	if (hw->mac_type >= e1000_82544) {
+	if ((hw->mac_type >= e1000_82544) && (hw->mac_type != e1000_ce4100)) {
 		e1000_config_collision_dist(hw);
 	} else {
 		ret_val = e1000_config_mac_to_phy(hw);
@@ -1395,6 +1473,12 @@ static s32 e1000_setup_copper_link(struc
 		ret_val = e1000_copper_link_mgp_setup(hw);
 		if (ret_val)
 			return ret_val;
+	} else {
+		ret_val = gbe_dhg_phy_setup(hw);
+		if (ret_val) {
+			e_dbg("gbe_dhg_phy_setup failed!\n");
+			return ret_val;
+		}
 	}
 
 	if (hw->autoneg) {
@@ -1461,10 +1545,11 @@ s32 e1000_phy_setup_autoneg(struct e1000
 		return ret_val;
 
 	/* Read the MII 1000Base-T Control Register (Address 9). */
-	ret_val =
-	    e1000_read_phy_reg(hw, PHY_1000T_CTRL, &mii_1000t_ctrl_reg);
+	ret_val = e1000_read_phy_reg(hw, PHY_1000T_CTRL, &mii_1000t_ctrl_reg);
 	if (ret_val)
 		return ret_val;
+	else if (hw->phy_type == e1000_phy_8201)
+		mii_1000t_ctrl_reg &= ~REG9_SPEED_MASK;
 
 	/* Need to parse both autoneg_advertised and fc and set up
 	 * the appropriate PHY registers.  First we will parse for
@@ -1577,9 +1662,14 @@ s32 e1000_phy_setup_autoneg(struct e1000
 
 	e_dbg("Auto-Neg Advertising %x\n", mii_autoneg_adv_reg);
 
-	ret_val = e1000_write_phy_reg(hw, PHY_1000T_CTRL, mii_1000t_ctrl_reg);
-	if (ret_val)
-		return ret_val;
+	if (hw->phy_type == e1000_phy_8201) {
+		mii_1000t_ctrl_reg = 0;
+	} else {
+		ret_val = e1000_write_phy_reg(hw, PHY_1000T_CTRL,
+		                              mii_1000t_ctrl_reg);
+		if (ret_val)
+			return ret_val;
+	}
 
 	return E1000_SUCCESS;
 }
@@ -1860,7 +1950,7 @@ static s32 e1000_config_mac_to_phy(struc
 
 	/* 82544 or newer MAC, Auto Speed Detection takes care of
 	 * MAC speed/duplex configuration.*/
-	if (hw->mac_type >= e1000_82544)
+	if ((hw->mac_type >= e1000_82544) && (hw->mac_type != e1000_ce4100))
 		return E1000_SUCCESS;
 
 	/* Read the Device Control Register and set the bits to Force Speed
@@ -1870,27 +1960,49 @@ static s32 e1000_config_mac_to_phy(struc
 	ctrl |= (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
 	ctrl &= ~(E1000_CTRL_SPD_SEL | E1000_CTRL_ILOS);
 
-	/* Set up duplex in the Device Control and Transmit Control
-	 * registers depending on negotiated values.
-	 */
-	ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data);
-	if (ret_val)
-		return ret_val;
+	switch (hw->phy_type) {
+	case e1000_phy_8201:
+		ret_val = e1000_read_phy_reg(hw, PHY_CTRL, &phy_data);
+		if (ret_val)
+			return ret_val;
 
-	if (phy_data & M88E1000_PSSR_DPLX)
-		ctrl |= E1000_CTRL_FD;
-	else
-		ctrl &= ~E1000_CTRL_FD;
+		if (phy_data & RTL_PHY_CTRL_FD)
+			ctrl |= E1000_CTRL_FD;
+		else
+			ctrl &= ~E1000_CTRL_FD;
 
-	e1000_config_collision_dist(hw);
+		if (phy_data & RTL_PHY_CTRL_SPD_100)
+			ctrl |= E1000_CTRL_SPD_100;
+		else
+			ctrl |= E1000_CTRL_SPD_10;
 
-	/* Set up speed in the Device Control register depending on
-	 * negotiated values.
-	 */
-	if ((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_1000MBS)
-		ctrl |= E1000_CTRL_SPD_1000;
-	else if ((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_100MBS)
-		ctrl |= E1000_CTRL_SPD_100;
+		e1000_config_collision_dist(hw);
+		break;
+	default:
+		/* Set up duplex in the Device Control and Transmit Control
+		 * registers depending on negotiated values.
+		 */
+		ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS,
+		                             &phy_data);
+		if (ret_val)
+			return ret_val;
+
+		if (phy_data & M88E1000_PSSR_DPLX)
+			ctrl |= E1000_CTRL_FD;
+		else
+			ctrl &= ~E1000_CTRL_FD;
+
+		e1000_config_collision_dist(hw);
+
+		/* Set up speed in the Device Control register depending on
+		 * negotiated values.
+		 */
+		if ((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_1000MBS)
+			ctrl |= E1000_CTRL_SPD_1000;
+		else if ((phy_data & M88E1000_PSSR_SPEED) ==
+		         M88E1000_PSSR_100MBS)
+			ctrl |= E1000_CTRL_SPD_100;
+	}
 
 	/* Write the configured values back to the Device Control Reg. */
 	ew32(CTRL, ctrl);
@@ -2401,7 +2513,8 @@ s32 e1000_check_for_link(struct e1000_hw
 		 * speed/duplex on the MAC to the current PHY speed/duplex
 		 * settings.
 		 */
-		if (hw->mac_type >= e1000_82544)
+		if ((hw->mac_type >= e1000_82544) &&
+		    (hw->mac_type != e1000_ce4100))
 			e1000_config_collision_dist(hw);
 		else {
 			ret_val = e1000_config_mac_to_phy(hw);
@@ -2738,7 +2851,7 @@ static s32 e1000_read_phy_reg_ex(struct
 {
 	u32 i;
 	u32 mdic = 0;
-	const u32 phy_addr = 1;
+	const u32 phy_addr = (hw->mac_type == e1000_ce4100) ? hw->phy_addr : 1;
 
 	e_dbg("e1000_read_phy_reg_ex");
 
@@ -2752,28 +2865,61 @@ static s32 e1000_read_phy_reg_ex(struct
 		 * Control register.  The MAC will take care of interfacing with the
 		 * PHY to retrieve the desired data.
 		 */
-		mdic = ((reg_addr << E1000_MDIC_REG_SHIFT) |
-			(phy_addr << E1000_MDIC_PHY_SHIFT) |
-			(E1000_MDIC_OP_READ));
+		if (hw->mac_type == e1000_ce4100) {
+			mdic = ((reg_addr << E1000_MDIC_REG_SHIFT) |
+				(phy_addr << E1000_MDIC_PHY_SHIFT) |
+				(INTEL_CE_GBE_MDIC_OP_READ) |
+				(INTEL_CE_GBE_MDIC_GO));
 
-		ew32(MDIC, mdic);
+			writel(mdic, E1000_MDIO_CMD);
 
-		/* Poll the ready bit to see if the MDI read completed */
-		for (i = 0; i < 64; i++) {
-			udelay(50);
-			mdic = er32(MDIC);
-			if (mdic & E1000_MDIC_READY)
-				break;
-		}
-		if (!(mdic & E1000_MDIC_READY)) {
-			e_dbg("MDI Read did not complete\n");
-			return -E1000_ERR_PHY;
-		}
-		if (mdic & E1000_MDIC_ERROR) {
-			e_dbg("MDI Error\n");
-			return -E1000_ERR_PHY;
+			/* Poll the ready bit to see if the MDI read
+			 * completed
+			 */
+			for (i = 0; i < 64; i++) {
+				udelay(50);
+				mdic = readl(E1000_MDIO_CMD);
+				if (!(mdic & INTEL_CE_GBE_MDIC_GO))
+					break;
+			}
+
+			if (mdic & INTEL_CE_GBE_MDIC_GO) {
+				e_dbg("MDI Read did not complete\n");
+				return -E1000_ERR_PHY;
+			}
+
+			mdic = readl(E1000_MDIO_STS);
+			if (mdic & INTEL_CE_GBE_MDIC_READ_ERROR) {
+				e_dbg("MDI Read Error\n");
+				return -E1000_ERR_PHY;
+			}
+			*phy_data = (u16) mdic;
+		} else {
+			mdic = ((reg_addr << E1000_MDIC_REG_SHIFT) |
+				(phy_addr << E1000_MDIC_PHY_SHIFT) |
+				(E1000_MDIC_OP_READ));
+
+			ew32(MDIC, mdic);
+
+			/* Poll the ready bit to see if the MDI read
+			 * completed
+			 */
+			for (i = 0; i < 64; i++) {
+				udelay(50);
+				mdic = er32(MDIC);
+				if (mdic & E1000_MDIC_READY)
+					break;
+			}
+			if (!(mdic & E1000_MDIC_READY)) {
+				e_dbg("MDI Read did not complete\n");
+				return -E1000_ERR_PHY;
+			}
+			if (mdic & E1000_MDIC_ERROR) {
+				e_dbg("MDI Error\n");
+				return -E1000_ERR_PHY;
+			}
+			*phy_data = (u16) mdic;
 		}
-		*phy_data = (u16) mdic;
 	} else {
 		/* We must first send a preamble through the MDIO pin to signal the
 		 * beginning of an MII instruction.  This is done by sending 32
@@ -2840,7 +2986,7 @@ static s32 e1000_write_phy_reg_ex(struct
 {
 	u32 i;
 	u32 mdic = 0;
-	const u32 phy_addr = 1;
+	const u32 phy_addr = (hw->mac_type == e1000_ce4100) ? hw->phy_addr : 1;
 
 	e_dbg("e1000_write_phy_reg_ex");
 
@@ -2850,27 +2996,54 @@ static s32 e1000_write_phy_reg_ex(struct
 	}
 
 	if (hw->mac_type > e1000_82543) {
-		/* Set up Op-code, Phy Address, register address, and data intended
-		 * for the PHY register in the MDI Control register.  The MAC will take
-		 * care of interfacing with the PHY to send the desired data.
+		/* Set up Op-code, Phy Address, register address, and data
+		 * intended for the PHY register in the MDI Control register.
+		 * The MAC will take care of interfacing with the PHY to send
+		 * the desired data.
 		 */
-		mdic = (((u32) phy_data) |
-			(reg_addr << E1000_MDIC_REG_SHIFT) |
-			(phy_addr << E1000_MDIC_PHY_SHIFT) |
-			(E1000_MDIC_OP_WRITE));
+		if (hw->mac_type == e1000_ce4100) {
+			mdic = (((u32) phy_data) |
+				(reg_addr << E1000_MDIC_REG_SHIFT) |
+				(phy_addr << E1000_MDIC_PHY_SHIFT) |
+				(INTEL_CE_GBE_MDIC_OP_WRITE) |
+				(INTEL_CE_GBE_MDIC_GO));
 
-		ew32(MDIC, mdic);
+			writel(mdic, E1000_MDIO_CMD);
 
-		/* Poll the ready bit to see if the MDI read completed */
-		for (i = 0; i < 641; i++) {
-			udelay(5);
-			mdic = er32(MDIC);
-			if (mdic & E1000_MDIC_READY)
-				break;
-		}
-		if (!(mdic & E1000_MDIC_READY)) {
-			e_dbg("MDI Write did not complete\n");
-			return -E1000_ERR_PHY;
+			/* Poll the ready bit to see if the MDI read
+			 * completed
+			 */
+			for (i = 0; i < 640; i++) {
+				udelay(5);
+				mdic = readl(E1000_MDIO_CMD);
+				if (!(mdic & INTEL_CE_GBE_MDIC_GO))
+					break;
+			}
+			if (mdic & INTEL_CE_GBE_MDIC_GO) {
+				e_dbg("MDI Write did not complete\n");
+				return -E1000_ERR_PHY;
+			}
+		} else {
+			mdic = (((u32) phy_data) |
+				(reg_addr << E1000_MDIC_REG_SHIFT) |
+				(phy_addr << E1000_MDIC_PHY_SHIFT) |
+				(E1000_MDIC_OP_WRITE));
+
+			ew32(MDIC, mdic);
+
+			/* Poll the ready bit to see if the MDI read
+			 * completed
+			 */
+			for (i = 0; i < 641; i++) {
+				udelay(5);
+				mdic = er32(MDIC);
+				if (mdic & E1000_MDIC_READY)
+					break;
+			}
+			if (!(mdic & E1000_MDIC_READY)) {
+				e_dbg("MDI Write did not complete\n");
+				return -E1000_ERR_PHY;
+			}
 		}
 	} else {
 		/* We'll need to use the SW defined pins to shift the write command
@@ -3048,6 +3221,12 @@ static s32 e1000_detect_gig_phy(struct e
 		if (hw->phy_id == M88E1011_I_PHY_ID)
 			match = true;
 		break;
+	case e1000_ce4100:
+		if ((hw->phy_id == RTL8211B_PHY_ID) ||
+		    (hw->phy_id == RTL8201N_PHY_ID) ||
+		    (hw->phy_id == M88E1118_E_PHY_ID))
+			match = true;
+		break;
 	case e1000_82541:
 	case e1000_82541_rev_2:
 	case e1000_82547:
@@ -3291,6 +3470,9 @@ s32 e1000_phy_get_info(struct e1000_hw *
 
 	if (hw->phy_type == e1000_phy_igp)
 		return e1000_phy_igp_get_info(hw, phy_info);
+	else if ((hw->phy_type == e1000_phy_8211) ||
+	         (hw->phy_type == e1000_phy_8201))
+		return E1000_SUCCESS;
 	else
 		return e1000_phy_m88_get_info(hw, phy_info);
 }
@@ -3742,6 +3924,12 @@ static s32 e1000_do_read_eeprom(struct e
 
 	e_dbg("e1000_read_eeprom");
 
+	if (hw->mac_type == e1000_ce4100) {
+		GBE_CONFIG_FLASH_READ(GBE_CONFIG_BASE_VIRT, offset, words,
+		                      data);
+		return E1000_SUCCESS;
+	}
+
 	/* If eeprom is not yet detected, do so now */
 	if (eeprom->word_size == 0)
 		e1000_init_eeprom_params(hw);
@@ -3904,6 +4092,12 @@ static s32 e1000_do_write_eeprom(struct
 
 	e_dbg("e1000_write_eeprom");
 
+	if (hw->mac_type == e1000_ce4100) {
+		GBE_CONFIG_FLASH_WRITE(GBE_CONFIG_BASE_VIRT, offset, words,
+		                       data);
+		return E1000_SUCCESS;
+	}
+
 	/* If eeprom is not yet detected, do so now */
 	if (eeprom->word_size == 0)
 		e1000_init_eeprom_params(hw);
@@ -4892,11 +5086,11 @@ static s32 e1000_get_cable_length(struct
 	} else if (hw->phy_type == e1000_phy_igp) {	/* For IGP PHY */
 		u16 cur_agc_value;
 		u16 min_agc_value = IGP01E1000_AGC_LENGTH_TABLE_SIZE;
-		u16 agc_reg_array[IGP01E1000_PHY_CHANNEL_NUM] =
-		    { IGP01E1000_PHY_AGC_A,
-			IGP01E1000_PHY_AGC_B,
-			IGP01E1000_PHY_AGC_C,
-			IGP01E1000_PHY_AGC_D
+		static const u16 agc_reg_array[IGP01E1000_PHY_CHANNEL_NUM] = {
+		       IGP01E1000_PHY_AGC_A,
+		       IGP01E1000_PHY_AGC_B,
+		       IGP01E1000_PHY_AGC_C,
+		       IGP01E1000_PHY_AGC_D
 		};
 		/* Read the AGC registers for all channels */
 		for (i = 0; i < IGP01E1000_PHY_CHANNEL_NUM; i++) {
@@ -5071,11 +5265,11 @@ static s32 e1000_config_dsp_after_link_c
 {
 	s32 ret_val;
 	u16 phy_data, phy_saved_data, speed, duplex, i;
-	u16 dsp_reg_array[IGP01E1000_PHY_CHANNEL_NUM] =
-	    { IGP01E1000_PHY_AGC_PARAM_A,
-		IGP01E1000_PHY_AGC_PARAM_B,
-		IGP01E1000_PHY_AGC_PARAM_C,
-		IGP01E1000_PHY_AGC_PARAM_D
+	static const u16 dsp_reg_array[IGP01E1000_PHY_CHANNEL_NUM] = {
+	       IGP01E1000_PHY_AGC_PARAM_A,
+	       IGP01E1000_PHY_AGC_PARAM_B,
+	       IGP01E1000_PHY_AGC_PARAM_C,
+	       IGP01E1000_PHY_AGC_PARAM_D
 	};
 	u16 min_length, max_length;
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/e1000/e1000_hw.h linux-libre-2.6.38-gnu1/drivers/net/e1000/e1000_hw.h
--- linux-libre-2.6.37-gnu1/drivers/net/e1000/e1000_hw.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/e1000/e1000_hw.h	2011-03-14 21:20:32.000000000 -0400
@@ -41,7 +41,7 @@ struct e1000_hw;
 struct e1000_hw_stats;
 
 /* Enumerated types specific to the e1000 hardware */
-/* Media Access Controlers */
+/* Media Access Controllers */
 typedef enum {
 	e1000_undefined = 0,
 	e1000_82542_rev2_0,
@@ -52,6 +52,7 @@ typedef enum {
 	e1000_82545,
 	e1000_82545_rev_3,
 	e1000_82546,
+	e1000_ce4100,
 	e1000_82546_rev_3,
 	e1000_82541,
 	e1000_82541_rev_2,
@@ -209,9 +210,11 @@ typedef enum {
 } e1000_1000t_rx_status;
 
 typedef enum {
-    e1000_phy_m88 = 0,
-    e1000_phy_igp,
-    e1000_phy_undefined = 0xFF
+	e1000_phy_m88 = 0,
+	e1000_phy_igp,
+	e1000_phy_8211,
+	e1000_phy_8201,
+	e1000_phy_undefined = 0xFF
 } e1000_phy_type;
 
 typedef enum {
@@ -442,6 +445,7 @@ void e1000_io_write(struct e1000_hw *hw,
 #define E1000_DEV_ID_82547EI             0x1019
 #define E1000_DEV_ID_82547EI_MOBILE      0x101A
 #define E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3 0x10B5
+#define E1000_DEV_ID_INTEL_CE4100_GBE    0x2E6E
 
 #define NODE_ADDRESS_SIZE 6
 #define ETH_LENGTH_OF_ADDRESS 6
@@ -808,6 +812,16 @@ struct e1000_ffvt_entry {
 #define E1000_CTRL_EXT 0x00018	/* Extended Device Control - RW */
 #define E1000_FLA      0x0001C	/* Flash Access - RW */
 #define E1000_MDIC     0x00020	/* MDI Control - RW */
+
+extern void __iomem *ce4100_gbe_mdio_base_virt;
+#define INTEL_CE_GBE_MDIO_RCOMP_BASE    (ce4100_gbe_mdio_base_virt)
+#define E1000_MDIO_STS  (INTEL_CE_GBE_MDIO_RCOMP_BASE + 0)
+#define E1000_MDIO_CMD  (INTEL_CE_GBE_MDIO_RCOMP_BASE + 4)
+#define E1000_MDIO_DRV  (INTEL_CE_GBE_MDIO_RCOMP_BASE + 8)
+#define E1000_MDC_CMD   (INTEL_CE_GBE_MDIO_RCOMP_BASE + 0xC)
+#define E1000_RCOMP_CTL (INTEL_CE_GBE_MDIO_RCOMP_BASE + 0x20)
+#define E1000_RCOMP_STS (INTEL_CE_GBE_MDIO_RCOMP_BASE + 0x24)
+
 #define E1000_SCTL     0x00024	/* SerDes Control - RW */
 #define E1000_FEXTNVM  0x00028	/* Future Extended NVM register */
 #define E1000_FCAL     0x00028	/* Flow Control Address Low - RW */
@@ -820,6 +834,34 @@ struct e1000_ffvt_entry {
 #define E1000_IMS      0x000D0	/* Interrupt Mask Set - RW */
 #define E1000_IMC      0x000D8	/* Interrupt Mask Clear - WO */
 #define E1000_IAM      0x000E0	/* Interrupt Acknowledge Auto Mask */
+
+/* Auxiliary Control Register. This register is CE4100 specific,
+ * RMII/RGMII function is switched by this register - RW
+ * Following are bits definitions of the Auxiliary Control Register
+ */
+#define E1000_CTL_AUX  0x000E0
+#define E1000_CTL_AUX_END_SEL_SHIFT     10
+#define E1000_CTL_AUX_ENDIANESS_SHIFT   8
+#define E1000_CTL_AUX_RGMII_RMII_SHIFT  0
+
+/* descriptor and packet transfer use CTL_AUX.ENDIANESS */
+#define E1000_CTL_AUX_DES_PKT   (0x0 << E1000_CTL_AUX_END_SEL_SHIFT)
+/* descriptor use CTL_AUX.ENDIANESS, packet use default */
+#define E1000_CTL_AUX_DES       (0x1 << E1000_CTL_AUX_END_SEL_SHIFT)
+/* descriptor use default, packet use CTL_AUX.ENDIANESS */
+#define E1000_CTL_AUX_PKT       (0x2 << E1000_CTL_AUX_END_SEL_SHIFT)
+/* all use CTL_AUX.ENDIANESS */
+#define E1000_CTL_AUX_ALL       (0x3 << E1000_CTL_AUX_END_SEL_SHIFT)
+
+#define E1000_CTL_AUX_RGMII     (0x0 << E1000_CTL_AUX_RGMII_RMII_SHIFT)
+#define E1000_CTL_AUX_RMII      (0x1 << E1000_CTL_AUX_RGMII_RMII_SHIFT)
+
+/* LW little endian, Byte big endian */
+#define E1000_CTL_AUX_LWLE_BBE  (0x0 << E1000_CTL_AUX_ENDIANESS_SHIFT)
+#define E1000_CTL_AUX_LWLE_BLE  (0x1 << E1000_CTL_AUX_ENDIANESS_SHIFT)
+#define E1000_CTL_AUX_LWBE_BBE  (0x2 << E1000_CTL_AUX_ENDIANESS_SHIFT)
+#define E1000_CTL_AUX_LWBE_BLE  (0x3 << E1000_CTL_AUX_ENDIANESS_SHIFT)
+
 #define E1000_RCTL     0x00100	/* RX Control - RW */
 #define E1000_RDTR1    0x02820	/* RX Delay Timer (1) - RW */
 #define E1000_RDBAL1   0x02900	/* RX Descriptor Base Address Low (1) - RW */
@@ -1011,6 +1053,7 @@ struct e1000_ffvt_entry {
  * in more current versions of the 8254x. Despite the difference in location,
  * the registers function in the same manner.
  */
+#define E1000_82542_CTL_AUX  E1000_CTL_AUX
 #define E1000_82542_CTRL     E1000_CTRL
 #define E1000_82542_CTRL_DUP E1000_CTRL_DUP
 #define E1000_82542_STATUS   E1000_STATUS
@@ -1571,6 +1614,11 @@ struct e1000_hw {
 #define E1000_MDIC_INT_EN    0x20000000
 #define E1000_MDIC_ERROR     0x40000000
 
+#define INTEL_CE_GBE_MDIC_OP_WRITE      0x04000000
+#define INTEL_CE_GBE_MDIC_OP_READ       0x00000000
+#define INTEL_CE_GBE_MDIC_GO            0x80000000
+#define INTEL_CE_GBE_MDIC_READ_ERROR    0x80000000
+
 #define E1000_KUMCTRLSTA_MASK           0x0000FFFF
 #define E1000_KUMCTRLSTA_OFFSET         0x001F0000
 #define E1000_KUMCTRLSTA_OFFSET_SHIFT   16
@@ -2869,8 +2917,14 @@ struct e1000_host_command_info {
 #define M88E1000_14_PHY_ID M88E1000_E_PHY_ID
 #define M88E1011_I_REV_4   0x04
 #define M88E1111_I_PHY_ID  0x01410CC0
+#define M88E1118_E_PHY_ID  0x01410E40
 #define L1LXT971A_PHY_ID   0x001378E0
 
+#define RTL8211B_PHY_ID    0x001CC910
+#define RTL8201N_PHY_ID    0x8200
+#define RTL_PHY_CTRL_FD    0x0100 /* Full duplex.0=half; 1=full */
+#define RTL_PHY_CTRL_SPD_100    0x200000 /* Force 100Mb */
+
 /* Bits...
  * 15-5: page
  * 4-0: register offset
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/e1000/e1000_main.c linux-libre-2.6.38-gnu1/drivers/net/e1000/e1000_main.c
--- linux-libre-2.6.37-gnu1/drivers/net/e1000/e1000_main.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/e1000/e1000_main.c	2011-03-14 21:20:32.000000000 -0400
@@ -28,6 +28,12 @@
 
 #include "e1000.h"
 #include <net/ip6_checksum.h>
+#include <linux/io.h>
+
+/* Intel Media SOC GbE MDIO physical base address */
+static unsigned long ce4100_gbe_mdio_base_phy;
+/* Intel Media SOC GbE MDIO virtual base address */
+void __iomem *ce4100_gbe_mdio_base_virt;
 
 char e1000_driver_name[] = "e1000";
 static char e1000_driver_string[] = "Intel(R) PRO/1000 Network Driver";
@@ -79,6 +85,7 @@ static DEFINE_PCI_DEVICE_TABLE(e1000_pci
 	INTEL_E1000_ETHERNET_DEVICE(0x108A),
 	INTEL_E1000_ETHERNET_DEVICE(0x1099),
 	INTEL_E1000_ETHERNET_DEVICE(0x10B5),
+	INTEL_E1000_ETHERNET_DEVICE(0x2E6E),
 	/* required last entry */
 	{0,}
 };
@@ -459,6 +466,7 @@ static void e1000_power_down_phy(struct
 		case e1000_82545:
 		case e1000_82545_rev_3:
 		case e1000_82546:
+		case e1000_ce4100:
 		case e1000_82546_rev_3:
 		case e1000_82541:
 		case e1000_82541_rev_2:
@@ -573,6 +581,7 @@ void e1000_reset(struct e1000_adapter *a
 	case e1000_82545:
 	case e1000_82545_rev_3:
 	case e1000_82546:
+	case e1000_ce4100:
 	case e1000_82546_rev_3:
 		pba = E1000_PBA_48K;
 		break;
@@ -894,6 +903,7 @@ static int __devinit e1000_probe(struct
 	static int global_quad_port_a = 0; /* global ksp3 port a indication */
 	int i, err, pci_using_dac;
 	u16 eeprom_data = 0;
+	u16 tmp = 0;
 	u16 eeprom_apme_mask = E1000_EEPROM_APME;
 	int bars, need_ioport;
 
@@ -971,11 +981,13 @@ static int __devinit e1000_probe(struct
 		 */
 		dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(64));
 		pci_using_dac = 1;
-	} else if (!dma_set_mask(&pdev->dev, DMA_BIT_MASK(32))) {
-		dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
 	} else {
-		pr_err("No usable DMA config, aborting\n");
-		goto err_dma;
+		err = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
+		if (err) {
+			pr_err("No usable DMA config, aborting\n");
+			goto err_dma;
+		}
+		dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
 	}
 
 	netdev->netdev_ops = &e1000_netdev_ops;
@@ -994,6 +1006,14 @@ static int __devinit e1000_probe(struct
 		goto err_sw_init;
 
 	err = -EIO;
+	if (hw->mac_type == e1000_ce4100) {
+		ce4100_gbe_mdio_base_phy = pci_resource_start(pdev, BAR_1);
+		ce4100_gbe_mdio_base_virt = ioremap(ce4100_gbe_mdio_base_phy,
+		                                pci_resource_len(pdev, BAR_1));
+
+		if (!ce4100_gbe_mdio_base_virt)
+			goto err_mdio_ioremap;
+	}
 
 	if (hw->mac_type >= e1000_82543) {
 		netdev->features = NETIF_F_SG |
@@ -1133,6 +1153,20 @@ static int __devinit e1000_probe(struct
 	adapter->wol = adapter->eeprom_wol;
 	device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol);
 
+	/* Auto detect PHY address */
+	if (hw->mac_type == e1000_ce4100) {
+		for (i = 0; i < 32; i++) {
+			hw->phy_addr = i;
+			e1000_read_phy_reg(hw, PHY_ID2, &tmp);
+			if (tmp == 0 || tmp == 0xFF) {
+				if (i == 31)
+					goto err_eeprom;
+				continue;
+			} else
+				break;
+		}
+	}
+
 	/* reset the hardware with the new settings */
 	e1000_reset(adapter);
 
@@ -1169,6 +1203,8 @@ err_eeprom:
 	kfree(adapter->rx_ring);
 err_dma:
 err_sw_init:
+err_mdio_ioremap:
+	iounmap(ce4100_gbe_mdio_base_virt);
 	iounmap(hw->hw_addr);
 err_ioremap:
 	free_netdev(netdev);
@@ -1407,6 +1443,7 @@ static bool e1000_check_64k_bound(struct
 	/* First rev 82545 and 82546 need to not allow any memory
 	 * write location to cross 64k boundary due to errata 23 */
 	if (hw->mac_type == e1000_82545 ||
+	    hw->mac_type == e1000_ce4100 ||
 	    hw->mac_type == e1000_82546) {
 		return ((begin ^ (end - 1)) >> 16) != 0 ? false : true;
 	}
@@ -1429,13 +1466,12 @@ static int e1000_setup_tx_resources(stru
 	int size;
 
 	size = sizeof(struct e1000_buffer) * txdr->count;
-	txdr->buffer_info = vmalloc(size);
+	txdr->buffer_info = vzalloc(size);
 	if (!txdr->buffer_info) {
 		e_err(probe, "Unable to allocate memory for the Tx descriptor "
 		      "ring\n");
 		return -ENOMEM;
 	}
-	memset(txdr->buffer_info, 0, size);
 
 	/* round up to nearest 4K */
 
@@ -1625,13 +1661,12 @@ static int e1000_setup_rx_resources(stru
 	int size, desc_len;
 
 	size = sizeof(struct e1000_buffer) * rxdr->count;
-	rxdr->buffer_info = vmalloc(size);
+	rxdr->buffer_info = vzalloc(size);
 	if (!rxdr->buffer_info) {
 		e_err(probe, "Unable to allocate memory for the Rx descriptor "
 		      "ring\n");
 		return -ENOMEM;
 	}
-	memset(rxdr->buffer_info, 0, size);
 
 	desc_len = sizeof(struct e1000_rx_desc);
 
@@ -2198,7 +2233,7 @@ static void e1000_set_rx_mode(struct net
 	 * addresses take precedence to avoid disabling unicast filtering
 	 * when possible.
 	 *
-	 * RAR 0 is used for the station MAC adddress
+	 * RAR 0 is used for the station MAC address
 	 * if there are not 14 addresses, go ahead and clear the filters
 	 */
 	i = 1;
@@ -2726,7 +2761,7 @@ static bool e1000_tx_csum(struct e1000_a
 		break;
 	}
 
-	css = skb_transport_offset(skb);
+	css = skb_checksum_start_offset(skb);
 
 	i = tx_ring->next_to_use;
 	buffer_info = &tx_ring->buffer_info[i];
@@ -3443,9 +3478,17 @@ static irqreturn_t e1000_intr(int irq, v
 	struct e1000_hw *hw = &adapter->hw;
 	u32 icr = er32(ICR);
 
-	if (unlikely((!icr) || test_bit(__E1000_DOWN, &adapter->flags)))
+	if (unlikely((!icr)))
 		return IRQ_NONE;  /* Not our interrupt */
 
+	/*
+	 * we might have caused the interrupt, but the above
+	 * read cleared it, and just in case the driver is
+	 * down there is nothing to do so return handled
+	 */
+	if (unlikely(test_bit(__E1000_DOWN, &adapter->flags)))
+		return IRQ_HANDLED;
+
 	if (unlikely(icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC))) {
 		hw->get_link_status = 1;
 		/* guard against interrupt when we're going down */
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/e1000/e1000_osdep.h linux-libre-2.6.38-gnu1/drivers/net/e1000/e1000_osdep.h
--- linux-libre-2.6.37-gnu1/drivers/net/e1000/e1000_osdep.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/e1000/e1000_osdep.h	2011-03-14 21:20:32.000000000 -0400
@@ -34,12 +34,22 @@
 #ifndef _E1000_OSDEP_H_
 #define _E1000_OSDEP_H_
 
-#include <linux/types.h>
-#include <linux/pci.h>
-#include <linux/delay.h>
 #include <asm/io.h>
-#include <linux/interrupt.h>
-#include <linux/sched.h>
+
+#define CONFIG_RAM_BASE         0x60000
+#define GBE_CONFIG_OFFSET       0x0
+
+#define GBE_CONFIG_RAM_BASE \
+	((unsigned int)(CONFIG_RAM_BASE + GBE_CONFIG_OFFSET))
+
+#define GBE_CONFIG_BASE_VIRT \
+	((void __iomem *)phys_to_virt(GBE_CONFIG_RAM_BASE))
+
+#define GBE_CONFIG_FLASH_WRITE(base, offset, count, data) \
+	(iowrite16_rep(base + offset, data, count))
+
+#define GBE_CONFIG_FLASH_READ(base, offset, count, data) \
+	(ioread16_rep(base + (offset << 1), data, count))
 
 #define er32(reg)							\
 	(readl(hw->hw_addr + ((hw->mac_type >= e1000_82543)		\
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/e1000/e1000_param.c linux-libre-2.6.38-gnu1/drivers/net/e1000/e1000_param.c
--- linux-libre-2.6.37-gnu1/drivers/net/e1000/e1000_param.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/e1000/e1000_param.c	2011-03-14 21:20:32.000000000 -0400
@@ -352,12 +352,13 @@ void __devinit e1000_check_options(struc
 	}
 	{ /* Flow Control */
 
-		struct e1000_opt_list fc_list[] =
-			{{ E1000_FC_NONE,    "Flow Control Disabled" },
-			 { E1000_FC_RX_PAUSE,"Flow Control Receive Only" },
-			 { E1000_FC_TX_PAUSE,"Flow Control Transmit Only" },
-			 { E1000_FC_FULL,    "Flow Control Enabled" },
-			 { E1000_FC_DEFAULT, "Flow Control Hardware Default" }};
+		static const struct e1000_opt_list fc_list[] = {
+		       { E1000_FC_NONE, "Flow Control Disabled" },
+		       { E1000_FC_RX_PAUSE, "Flow Control Receive Only" },
+		       { E1000_FC_TX_PAUSE, "Flow Control Transmit Only" },
+		       { E1000_FC_FULL, "Flow Control Enabled" },
+		       { E1000_FC_DEFAULT, "Flow Control Hardware Default" }
+		};
 
 		opt = (struct e1000_option) {
 			.type = list_option,
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/e1000e/82571.c linux-libre-2.6.38-gnu1/drivers/net/e1000e/82571.c
--- linux-libre-2.6.37-gnu1/drivers/net/e1000e/82571.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/e1000e/82571.c	2011-03-14 21:20:32.000000000 -0400
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel PRO/1000 Linux driver
-  Copyright(c) 1999 - 2010 Intel Corporation.
+  Copyright(c) 1999 - 2011 Intel 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,
@@ -52,6 +52,7 @@
 			      (ID_LED_DEF1_DEF2))
 
 #define E1000_GCR_L1_ACT_WITHOUT_L0S_RX 0x08000000
+#define AN_RETRY_COUNT          5 /* Autoneg Retry Count value */
 #define E1000_BASE1000T_STATUS          10
 #define E1000_IDLE_ERROR_COUNT_MASK     0xFF
 #define E1000_RECEIVE_ERROR_COUNTER     21
@@ -74,6 +75,11 @@ static bool e1000_check_mng_mode_82574(s
 static s32 e1000_led_on_82574(struct e1000_hw *hw);
 static void e1000_put_hw_semaphore_82571(struct e1000_hw *hw);
 static void e1000_power_down_phy_copper_82571(struct e1000_hw *hw);
+static void e1000_put_hw_semaphore_82573(struct e1000_hw *hw);
+static s32 e1000_get_hw_semaphore_82574(struct e1000_hw *hw);
+static void e1000_put_hw_semaphore_82574(struct e1000_hw *hw);
+static s32 e1000_set_d0_lplu_state_82574(struct e1000_hw *hw, bool active);
+static s32 e1000_set_d3_lplu_state_82574(struct e1000_hw *hw, bool active);
 
 /**
  *  e1000_init_phy_params_82571 - Init PHY func ptrs.
@@ -107,6 +113,10 @@ static s32 e1000_init_phy_params_82571(s
 	case e1000_82574:
 	case e1000_82583:
 		phy->type		 = e1000_phy_bm;
+		phy->ops.acquire = e1000_get_hw_semaphore_82574;
+		phy->ops.release = e1000_put_hw_semaphore_82574;
+		phy->ops.set_d0_lplu_state = e1000_set_d0_lplu_state_82574;
+		phy->ops.set_d3_lplu_state = e1000_set_d3_lplu_state_82574;
 		break;
 	default:
 		return -E1000_ERR_PHY;
@@ -115,29 +125,36 @@ static s32 e1000_init_phy_params_82571(s
 
 	/* This can only be done after all function pointers are setup. */
 	ret_val = e1000_get_phy_id_82571(hw);
+	if (ret_val) {
+		e_dbg("Error getting PHY ID\n");
+		return ret_val;
+	}
 
 	/* Verify phy id */
 	switch (hw->mac.type) {
 	case e1000_82571:
 	case e1000_82572:
 		if (phy->id != IGP01E1000_I_PHY_ID)
-			return -E1000_ERR_PHY;
+			ret_val = -E1000_ERR_PHY;
 		break;
 	case e1000_82573:
 		if (phy->id != M88E1111_I_PHY_ID)
-			return -E1000_ERR_PHY;
+			ret_val = -E1000_ERR_PHY;
 		break;
 	case e1000_82574:
 	case e1000_82583:
 		if (phy->id != BME1000_E_PHY_ID_R2)
-			return -E1000_ERR_PHY;
+			ret_val = -E1000_ERR_PHY;
 		break;
 	default:
-		return -E1000_ERR_PHY;
+		ret_val = -E1000_ERR_PHY;
 		break;
 	}
 
-	return 0;
+	if (ret_val)
+		e_dbg("PHY ID unknown: type = 0x%08x\n", phy->id);
+
+	return ret_val;
 }
 
 /**
@@ -200,6 +217,17 @@ static s32 e1000_init_nvm_params_82571(s
 		break;
 	}
 
+	/* Function Pointers */
+	switch (hw->mac.type) {
+	case e1000_82574:
+	case e1000_82583:
+		nvm->ops.acquire = e1000_get_hw_semaphore_82574;
+		nvm->ops.release = e1000_put_hw_semaphore_82574;
+		break;
+	default:
+		break;
+	}
+
 	return 0;
 }
 
@@ -300,7 +328,7 @@ static s32 e1000_init_mac_params_82571(s
 
 	/*
 	 * Ensure that the inter-port SWSM.SMBI lock bit is clear before
-	 * first NVM or PHY acess. This should be done for single-port
+	 * first NVM or PHY access. This should be done for single-port
 	 * devices, and for one port only on dual-port devices so that
 	 * for those devices we can still use the SMBI lock to synchronize
 	 * inter-port accesses to the PHY & NVM.
@@ -542,6 +570,146 @@ static void e1000_put_hw_semaphore_82571
 	swsm &= ~(E1000_SWSM_SMBI | E1000_SWSM_SWESMBI);
 	ew32(SWSM, swsm);
 }
+/**
+ *  e1000_get_hw_semaphore_82573 - Acquire hardware semaphore
+ *  @hw: pointer to the HW structure
+ *
+ *  Acquire the HW semaphore during reset.
+ *
+ **/
+static s32 e1000_get_hw_semaphore_82573(struct e1000_hw *hw)
+{
+	u32 extcnf_ctrl;
+	s32 ret_val = 0;
+	s32 i = 0;
+
+	extcnf_ctrl = er32(EXTCNF_CTRL);
+	extcnf_ctrl |= E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP;
+	do {
+		ew32(EXTCNF_CTRL, extcnf_ctrl);
+		extcnf_ctrl = er32(EXTCNF_CTRL);
+
+		if (extcnf_ctrl & E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP)
+			break;
+
+		extcnf_ctrl |= E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP;
+
+		msleep(2);
+		i++;
+	} while (i < MDIO_OWNERSHIP_TIMEOUT);
+
+	if (i == MDIO_OWNERSHIP_TIMEOUT) {
+		/* Release semaphores */
+		e1000_put_hw_semaphore_82573(hw);
+		e_dbg("Driver can't access the PHY\n");
+		ret_val = -E1000_ERR_PHY;
+		goto out;
+	}
+
+out:
+	return ret_val;
+}
+
+/**
+ *  e1000_put_hw_semaphore_82573 - Release hardware semaphore
+ *  @hw: pointer to the HW structure
+ *
+ *  Release hardware semaphore used during reset.
+ *
+ **/
+static void e1000_put_hw_semaphore_82573(struct e1000_hw *hw)
+{
+	u32 extcnf_ctrl;
+
+	extcnf_ctrl = er32(EXTCNF_CTRL);
+	extcnf_ctrl &= ~E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP;
+	ew32(EXTCNF_CTRL, extcnf_ctrl);
+}
+
+static DEFINE_MUTEX(swflag_mutex);
+
+/**
+ *  e1000_get_hw_semaphore_82574 - Acquire hardware semaphore
+ *  @hw: pointer to the HW structure
+ *
+ *  Acquire the HW semaphore to access the PHY or NVM.
+ *
+ **/
+static s32 e1000_get_hw_semaphore_82574(struct e1000_hw *hw)
+{
+	s32 ret_val;
+
+	mutex_lock(&swflag_mutex);
+	ret_val = e1000_get_hw_semaphore_82573(hw);
+	if (ret_val)
+		mutex_unlock(&swflag_mutex);
+	return ret_val;
+}
+
+/**
+ *  e1000_put_hw_semaphore_82574 - Release hardware semaphore
+ *  @hw: pointer to the HW structure
+ *
+ *  Release hardware semaphore used to access the PHY or NVM
+ *
+ **/
+static void e1000_put_hw_semaphore_82574(struct e1000_hw *hw)
+{
+	e1000_put_hw_semaphore_82573(hw);
+	mutex_unlock(&swflag_mutex);
+}
+
+/**
+ *  e1000_set_d0_lplu_state_82574 - Set Low Power Linkup D0 state
+ *  @hw: pointer to the HW structure
+ *  @active: true to enable LPLU, false to disable
+ *
+ *  Sets the LPLU D0 state according to the active flag.
+ *  LPLU will not be activated unless the
+ *  device autonegotiation advertisement meets standards of
+ *  either 10 or 10/100 or 10/100/1000 at all duplexes.
+ *  This is a function pointer entry point only called by
+ *  PHY setup routines.
+ **/
+static s32 e1000_set_d0_lplu_state_82574(struct e1000_hw *hw, bool active)
+{
+	u16 data = er32(POEMB);
+
+	if (active)
+		data |= E1000_PHY_CTRL_D0A_LPLU;
+	else
+		data &= ~E1000_PHY_CTRL_D0A_LPLU;
+
+	ew32(POEMB, data);
+	return 0;
+}
+
+/**
+ *  e1000_set_d3_lplu_state_82574 - Sets low power link up state for D3
+ *  @hw: pointer to the HW structure
+ *  @active: boolean used to enable/disable lplu
+ *
+ *  The low power link up (lplu) state is set to the power management level D3
+ *  when active is true, else clear lplu for D3. LPLU
+ *  is used during Dx states where the power conservation is most important.
+ *  During driver activity, SmartSpeed should be enabled so performance is
+ *  maintained.
+ **/
+static s32 e1000_set_d3_lplu_state_82574(struct e1000_hw *hw, bool active)
+{
+	u16 data = er32(POEMB);
+
+	if (!active) {
+		data &= ~E1000_PHY_CTRL_NOND0A_LPLU;
+	} else if ((hw->phy.autoneg_advertised == E1000_ALL_SPEED_DUPLEX) ||
+		   (hw->phy.autoneg_advertised == E1000_ALL_NOT_GIG) ||
+		   (hw->phy.autoneg_advertised == E1000_ALL_10_SPEED)) {
+		data |= E1000_PHY_CTRL_NOND0A_LPLU;
+	}
+
+	ew32(POEMB, data);
+	return 0;
+}
 
 /**
  *  e1000_acquire_nvm_82571 - Request for access to the EEPROM
@@ -562,8 +730,6 @@ static s32 e1000_acquire_nvm_82571(struc
 
 	switch (hw->mac.type) {
 	case e1000_82573:
-	case e1000_82574:
-	case e1000_82583:
 		break;
 	default:
 		ret_val = e1000e_acquire_nvm(hw);
@@ -853,9 +1019,8 @@ static s32 e1000_set_d0_lplu_state_82571
  **/
 static s32 e1000_reset_hw_82571(struct e1000_hw *hw)
 {
-	u32 ctrl, extcnf_ctrl, ctrl_ext, icr;
+	u32 ctrl, ctrl_ext;
 	s32 ret_val;
-	u16 i = 0;
 
 	/*
 	 * Prevent the PCI-E bus from sticking if there is no TLP connection
@@ -880,33 +1045,33 @@ static s32 e1000_reset_hw_82571(struct e
 	 */
 	switch (hw->mac.type) {
 	case e1000_82573:
+		ret_val = e1000_get_hw_semaphore_82573(hw);
+		break;
 	case e1000_82574:
 	case e1000_82583:
-		extcnf_ctrl = er32(EXTCNF_CTRL);
-		extcnf_ctrl |= E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP;
-
-		do {
-			ew32(EXTCNF_CTRL, extcnf_ctrl);
-			extcnf_ctrl = er32(EXTCNF_CTRL);
-
-			if (extcnf_ctrl & E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP)
-				break;
-
-			extcnf_ctrl |= E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP;
-
-			msleep(2);
-			i++;
-		} while (i < MDIO_OWNERSHIP_TIMEOUT);
+		ret_val = e1000_get_hw_semaphore_82574(hw);
 		break;
 	default:
 		break;
 	}
+	if (ret_val)
+		e_dbg("Cannot acquire MDIO ownership\n");
 
 	ctrl = er32(CTRL);
 
 	e_dbg("Issuing a global reset to MAC\n");
 	ew32(CTRL, ctrl | E1000_CTRL_RST);
 
+	/* Must release MDIO ownership and mutex after MAC reset. */
+	switch (hw->mac.type) {
+	case e1000_82574:
+	case e1000_82583:
+		e1000_put_hw_semaphore_82574(hw);
+		break;
+	default:
+		break;
+	}
+
 	if (hw->nvm.type == e1000_nvm_flash_hw) {
 		udelay(10);
 		ctrl_ext = er32(CTRL_EXT);
@@ -938,7 +1103,7 @@ static s32 e1000_reset_hw_82571(struct e
 
 	/* Clear any pending interrupt events. */
 	ew32(IMC, 0xffffffff);
-	icr = er32(ICR);
+	er32(ICR);
 
 	if (hw->mac.type == e1000_82571) {
 		/* Install any alternate MAC address into RAR0 */
@@ -1145,7 +1310,7 @@ static void e1000_initialize_hw_bits_825
 		 * apply workaround for hardware errata documented in errata
 		 * docs Fixes issue where some error prone or unreliable PCIe
 		 * completions are occurring, particularly with ASPM enabled.
-		 * Without fix, issue can cause tx timeouts.
+		 * Without fix, issue can cause Tx timeouts.
 		 */
 		reg = er32(GCR2);
 		reg |= 1;
@@ -1402,6 +1567,8 @@ static s32 e1000_check_for_serdes_link_8
 	u32 rxcw;
 	u32 ctrl;
 	u32 status;
+	u32 txcw;
+	u32 i;
 	s32 ret_val = 0;
 
 	ctrl = er32(CTRL);
@@ -1422,8 +1589,10 @@ static s32 e1000_check_for_serdes_link_8
 				    e1000_serdes_link_autoneg_progress;
 				mac->serdes_has_link = false;
 				e_dbg("AN_UP     -> AN_PROG\n");
+			} else {
+				mac->serdes_has_link = true;
 			}
-		break;
+			break;
 
 		case e1000_serdes_link_forced_up:
 			/*
@@ -1431,8 +1600,10 @@ static s32 e1000_check_for_serdes_link_8
 			 * auto-negotiation in the TXCW register and disable
 			 * forced link in the Device Control register in an
 			 * attempt to auto-negotiate with our link partner.
+			 * If the partner code word is null, stop forcing
+			 * and restart auto negotiation.
 			 */
-			if (rxcw & E1000_RXCW_C) {
+			if ((rxcw & E1000_RXCW_C) || !(rxcw & E1000_RXCW_CW))  {
 				/* Enable autoneg, and unforce link up */
 				ew32(TXCW, mac->txcw);
 				ew32(CTRL, (ctrl & ~E1000_CTRL_SLU));
@@ -1440,6 +1611,8 @@ static s32 e1000_check_for_serdes_link_8
 				    e1000_serdes_link_autoneg_progress;
 				mac->serdes_has_link = false;
 				e_dbg("FORCED_UP -> AN_PROG\n");
+			} else {
+				mac->serdes_has_link = true;
 			}
 			break;
 
@@ -1495,6 +1668,7 @@ static s32 e1000_check_for_serdes_link_8
 			ew32(CTRL, (ctrl & ~E1000_CTRL_SLU));
 			mac->serdes_link_state =
 			    e1000_serdes_link_autoneg_progress;
+			mac->serdes_has_link = false;
 			e_dbg("DOWN      -> AN_PROG\n");
 			break;
 		}
@@ -1505,16 +1679,32 @@ static s32 e1000_check_for_serdes_link_8
 			e_dbg("ANYSTATE  -> DOWN\n");
 		} else {
 			/*
-			 * We have sync, and can tolerate one invalid (IV)
-			 * codeword before declaring link down, so reread
-			 * to look again.
+			 * Check several times, if Sync and Config
+			 * both are consistently 1 then simply ignore
+			 * the Invalid bit and restart Autoneg
 			 */
-			udelay(10);
-			rxcw = er32(RXCW);
-			if (rxcw & E1000_RXCW_IV) {
-				mac->serdes_link_state = e1000_serdes_link_down;
+			for (i = 0; i < AN_RETRY_COUNT; i++) {
+				udelay(10);
+				rxcw = er32(RXCW);
+				if ((rxcw & E1000_RXCW_IV) &&
+				    !((rxcw & E1000_RXCW_SYNCH) &&
+				      (rxcw & E1000_RXCW_C))) {
+					mac->serdes_has_link = false;
+					mac->serdes_link_state =
+					    e1000_serdes_link_down;
+					e_dbg("ANYSTATE  -> DOWN\n");
+					break;
+				}
+			}
+
+			if (i == AN_RETRY_COUNT) {
+				txcw = er32(TXCW);
+				txcw |= E1000_TXCW_ANE;
+				ew32(TXCW, txcw);
+				mac->serdes_link_state =
+				    e1000_serdes_link_autoneg_progress;
 				mac->serdes_has_link = false;
-				e_dbg("ANYSTATE  -> DOWN\n");
+				e_dbg("ANYSTATE  -> AN_PROG\n");
 			}
 		}
 	}
@@ -1897,7 +2087,7 @@ struct e1000_info e1000_82574_info = {
 				  | FLAG_HAS_AMT
 				  | FLAG_HAS_CTRLEXT_ON_LOAD,
 	.flags2			  = FLAG2_CHECK_PHY_HANG,
-	.pba			= 36,
+	.pba			= 32,
 	.max_hw_frame_size	= DEFAULT_JUMBO,
 	.get_variants		= e1000_get_variants_82571,
 	.mac_ops		= &e82571_mac_ops,
@@ -1914,7 +2104,7 @@ struct e1000_info e1000_82583_info = {
 				  | FLAG_HAS_SMART_POWER_DOWN
 				  | FLAG_HAS_AMT
 				  | FLAG_HAS_CTRLEXT_ON_LOAD,
-	.pba			= 36,
+	.pba			= 32,
 	.max_hw_frame_size	= ETH_FRAME_LEN + ETH_FCS_LEN,
 	.get_variants		= e1000_get_variants_82571,
 	.mac_ops		= &e82571_mac_ops,
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/e1000e/defines.h linux-libre-2.6.38-gnu1/drivers/net/e1000e/defines.h
--- linux-libre-2.6.37-gnu1/drivers/net/e1000e/defines.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/e1000e/defines.h	2011-03-14 21:20:32.000000000 -0400
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel PRO/1000 Linux driver
-  Copyright(c) 1999 - 2010 Intel Corporation.
+  Copyright(c) 1999 - 2011 Intel 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,
@@ -488,6 +488,9 @@
 #define E1000_BLK_PHY_RESET   12
 #define E1000_ERR_SWFW_SYNC 13
 #define E1000_NOT_IMPLEMENTED 14
+#define E1000_ERR_INVALID_ARGUMENT  16
+#define E1000_ERR_NO_SPACE          17
+#define E1000_ERR_NVM_PBA_SECTION   18
 
 /* Loop limit on how long we wait for auto-negotiation to complete */
 #define FIBER_LINK_UP_LIMIT               50
@@ -516,6 +519,7 @@
 #define E1000_TXCW_ANE        0x80000000        /* Auto-neg enable */
 
 /* Receive Configuration Word */
+#define E1000_RXCW_CW         0x0000ffff        /* RxConfigWord mask */
 #define E1000_RXCW_IV         0x08000000        /* Receive config invalid */
 #define E1000_RXCW_C          0x20000000        /* Receive config */
 #define E1000_RXCW_SYNCH      0x40000000        /* Receive config synch */
@@ -649,13 +653,16 @@
 /* Mask bits for fields in Word 0x03 of the EEPROM */
 #define NVM_COMPAT_LOM    0x0800
 
+/* length of string needed to store PBA number */
+#define E1000_PBANUM_LENGTH             11
+
 /* For checksumming, the sum of all words in the NVM should equal 0xBABA. */
 #define NVM_SUM                    0xBABA
 
 /* PBA (printed board assembly) number words */
 #define NVM_PBA_OFFSET_0           8
 #define NVM_PBA_OFFSET_1           9
-
+#define NVM_PBA_PTR_GUARD          0xFAFA
 #define NVM_WORD_SIZE_BASE_SHIFT   6
 
 /* NVM Commands - SPI */
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/e1000e/e1000.h linux-libre-2.6.38-gnu1/drivers/net/e1000e/e1000.h
--- linux-libre-2.6.37-gnu1/drivers/net/e1000e/e1000.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/e1000e/e1000.h	2011-03-14 21:20:32.000000000 -0400
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel PRO/1000 Linux driver
-  Copyright(c) 1999 - 2010 Intel Corporation.
+  Copyright(c) 1999 - 2011 Intel 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,
@@ -38,6 +38,7 @@
 #include <linux/netdevice.h>
 #include <linux/pci.h>
 #include <linux/pci-aspm.h>
+#include <linux/crc32.h>
 
 #include "hw.h"
 
@@ -482,6 +483,7 @@ extern const char e1000e_driver_version[
 
 extern void e1000e_check_options(struct e1000_adapter *adapter);
 extern void e1000e_set_ethtool_ops(struct net_device *netdev);
+extern void e1000e_led_blink_task(struct work_struct *work);
 
 extern int e1000e_up(struct e1000_adapter *adapter);
 extern void e1000e_down(struct e1000_adapter *adapter);
@@ -495,6 +497,8 @@ extern void e1000e_free_tx_resources(str
 extern void e1000e_update_stats(struct e1000_adapter *adapter);
 extern void e1000e_set_interrupt_capability(struct e1000_adapter *adapter);
 extern void e1000e_reset_interrupt_capability(struct e1000_adapter *adapter);
+extern void e1000e_get_hw_control(struct e1000_adapter *adapter);
+extern void e1000e_release_hw_control(struct e1000_adapter *adapter);
 extern void e1000e_disable_aspm(struct pci_dev *pdev, u16 state);
 
 extern unsigned int copybreak;
@@ -513,7 +517,8 @@ extern struct e1000_info e1000_pch_info;
 extern struct e1000_info e1000_pch2_info;
 extern struct e1000_info e1000_es2_info;
 
-extern s32 e1000e_read_pba_num(struct e1000_hw *hw, u32 *pba_num);
+extern s32 e1000_read_pba_string_generic(struct e1000_hw *hw, u8 *pba_num,
+					 u32 pba_num_size);
 
 extern s32  e1000e_commit_phy(struct e1000_hw *hw);
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/e1000e/es2lan.c linux-libre-2.6.38-gnu1/drivers/net/e1000e/es2lan.c
--- linux-libre-2.6.37-gnu1/drivers/net/e1000e/es2lan.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/e1000e/es2lan.c	2011-03-14 21:20:32.000000000 -0400
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel PRO/1000 Linux driver
-  Copyright(c) 1999 - 2010 Intel Corporation.
+  Copyright(c) 1999 - 2011 Intel 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,
@@ -100,8 +100,8 @@
  * with a lower bound at "index" and the upper bound at
  * "index + 5".
  */
-static const u16 e1000_gg82563_cable_length_table[] =
-	 { 0, 60, 115, 150, 150, 60, 115, 150, 180, 180, 0xFF };
+static const u16 e1000_gg82563_cable_length_table[] = {
+	 0, 60, 115, 150, 150, 60, 115, 150, 180, 180, 0xFF };
 #define GG82563_CABLE_LENGTH_TABLE_SIZE \
 		ARRAY_SIZE(e1000_gg82563_cable_length_table)
 
@@ -426,8 +426,8 @@ static void e1000_release_swfw_sync_8000
 {
 	u32 swfw_sync;
 
-	while (e1000e_get_hw_semaphore(hw) != 0);
-	/* Empty */
+	while (e1000e_get_hw_semaphore(hw) != 0)
+		; /* Empty */
 
 	swfw_sync = er32(SW_FW_SYNC);
 	swfw_sync &= ~mask;
@@ -784,7 +784,7 @@ static s32 e1000_get_link_up_info_80003e
  **/
 static s32 e1000_reset_hw_80003es2lan(struct e1000_hw *hw)
 {
-	u32 ctrl, icr;
+	u32 ctrl;
 	s32 ret_val;
 
 	/*
@@ -818,7 +818,7 @@ static s32 e1000_reset_hw_80003es2lan(st
 
 	/* Clear any pending interrupt events. */
 	ew32(IMC, 0xffffffff);
-	icr = er32(ICR);
+	er32(ICR);
 
 	ret_val = e1000_check_alt_mac_addr_generic(hw);
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/e1000e/ethtool.c linux-libre-2.6.38-gnu1/drivers/net/e1000e/ethtool.c
--- linux-libre-2.6.37-gnu1/drivers/net/e1000e/ethtool.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/e1000e/ethtool.c	2011-03-14 21:20:32.000000000 -0400
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel PRO/1000 Linux driver
-  Copyright(c) 1999 - 2010 Intel Corporation.
+  Copyright(c) 1999 - 2011 Intel 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,
@@ -45,63 +45,67 @@ struct e1000_stats {
 	int stat_offset;
 };
 
-#define E1000_STAT(m)		E1000_STATS, \
-				sizeof(((struct e1000_adapter *)0)->m), \
-		      		offsetof(struct e1000_adapter, m)
-#define E1000_NETDEV_STAT(m)	NETDEV_STATS, \
-				sizeof(((struct net_device *)0)->m), \
-				offsetof(struct net_device, m)
+#define E1000_STAT(str, m) { \
+			.stat_string = str, \
+			.type = E1000_STATS, \
+			.sizeof_stat = sizeof(((struct e1000_adapter *)0)->m), \
+			.stat_offset = offsetof(struct e1000_adapter, m) }
+#define E1000_NETDEV_STAT(str, m) { \
+			.stat_string = str, \
+			.type = NETDEV_STATS, \
+			.sizeof_stat = sizeof(((struct net_device *)0)->m), \
+			.stat_offset = offsetof(struct net_device, m) }
 
 static const struct e1000_stats e1000_gstrings_stats[] = {
-	{ "rx_packets", E1000_STAT(stats.gprc) },
-	{ "tx_packets", E1000_STAT(stats.gptc) },
-	{ "rx_bytes", E1000_STAT(stats.gorc) },
-	{ "tx_bytes", E1000_STAT(stats.gotc) },
-	{ "rx_broadcast", E1000_STAT(stats.bprc) },
-	{ "tx_broadcast", E1000_STAT(stats.bptc) },
-	{ "rx_multicast", E1000_STAT(stats.mprc) },
-	{ "tx_multicast", E1000_STAT(stats.mptc) },
-	{ "rx_errors", E1000_NETDEV_STAT(stats.rx_errors) },
-	{ "tx_errors", E1000_NETDEV_STAT(stats.tx_errors) },
-	{ "tx_dropped", E1000_NETDEV_STAT(stats.tx_dropped) },
-	{ "multicast", E1000_STAT(stats.mprc) },
-	{ "collisions", E1000_STAT(stats.colc) },
-	{ "rx_length_errors", E1000_NETDEV_STAT(stats.rx_length_errors) },
-	{ "rx_over_errors", E1000_NETDEV_STAT(stats.rx_over_errors) },
-	{ "rx_crc_errors", E1000_STAT(stats.crcerrs) },
-	{ "rx_frame_errors", E1000_NETDEV_STAT(stats.rx_frame_errors) },
-	{ "rx_no_buffer_count", E1000_STAT(stats.rnbc) },
-	{ "rx_missed_errors", E1000_STAT(stats.mpc) },
-	{ "tx_aborted_errors", E1000_STAT(stats.ecol) },
-	{ "tx_carrier_errors", E1000_STAT(stats.tncrs) },
-	{ "tx_fifo_errors", E1000_NETDEV_STAT(stats.tx_fifo_errors) },
-	{ "tx_heartbeat_errors", E1000_NETDEV_STAT(stats.tx_heartbeat_errors) },
-	{ "tx_window_errors", E1000_STAT(stats.latecol) },
-	{ "tx_abort_late_coll", E1000_STAT(stats.latecol) },
-	{ "tx_deferred_ok", E1000_STAT(stats.dc) },
-	{ "tx_single_coll_ok", E1000_STAT(stats.scc) },
-	{ "tx_multi_coll_ok", E1000_STAT(stats.mcc) },
-	{ "tx_timeout_count", E1000_STAT(tx_timeout_count) },
-	{ "tx_restart_queue", E1000_STAT(restart_queue) },
-	{ "rx_long_length_errors", E1000_STAT(stats.roc) },
-	{ "rx_short_length_errors", E1000_STAT(stats.ruc) },
-	{ "rx_align_errors", E1000_STAT(stats.algnerrc) },
-	{ "tx_tcp_seg_good", E1000_STAT(stats.tsctc) },
-	{ "tx_tcp_seg_failed", E1000_STAT(stats.tsctfc) },
-	{ "rx_flow_control_xon", E1000_STAT(stats.xonrxc) },
-	{ "rx_flow_control_xoff", E1000_STAT(stats.xoffrxc) },
-	{ "tx_flow_control_xon", E1000_STAT(stats.xontxc) },
-	{ "tx_flow_control_xoff", E1000_STAT(stats.xofftxc) },
-	{ "rx_long_byte_count", E1000_STAT(stats.gorc) },
-	{ "rx_csum_offload_good", E1000_STAT(hw_csum_good) },
-	{ "rx_csum_offload_errors", E1000_STAT(hw_csum_err) },
-	{ "rx_header_split", E1000_STAT(rx_hdr_split) },
-	{ "alloc_rx_buff_failed", E1000_STAT(alloc_rx_buff_failed) },
-	{ "tx_smbus", E1000_STAT(stats.mgptc) },
-	{ "rx_smbus", E1000_STAT(stats.mgprc) },
-	{ "dropped_smbus", E1000_STAT(stats.mgpdc) },
-	{ "rx_dma_failed", E1000_STAT(rx_dma_failed) },
-	{ "tx_dma_failed", E1000_STAT(tx_dma_failed) },
+	E1000_STAT("rx_packets", stats.gprc),
+	E1000_STAT("tx_packets", stats.gptc),
+	E1000_STAT("rx_bytes", stats.gorc),
+	E1000_STAT("tx_bytes", stats.gotc),
+	E1000_STAT("rx_broadcast", stats.bprc),
+	E1000_STAT("tx_broadcast", stats.bptc),
+	E1000_STAT("rx_multicast", stats.mprc),
+	E1000_STAT("tx_multicast", stats.mptc),
+	E1000_NETDEV_STAT("rx_errors", stats.rx_errors),
+	E1000_NETDEV_STAT("tx_errors", stats.tx_errors),
+	E1000_NETDEV_STAT("tx_dropped", stats.tx_dropped),
+	E1000_STAT("multicast", stats.mprc),
+	E1000_STAT("collisions", stats.colc),
+	E1000_NETDEV_STAT("rx_length_errors", stats.rx_length_errors),
+	E1000_NETDEV_STAT("rx_over_errors", stats.rx_over_errors),
+	E1000_STAT("rx_crc_errors", stats.crcerrs),
+	E1000_NETDEV_STAT("rx_frame_errors", stats.rx_frame_errors),
+	E1000_STAT("rx_no_buffer_count", stats.rnbc),
+	E1000_STAT("rx_missed_errors", stats.mpc),
+	E1000_STAT("tx_aborted_errors", stats.ecol),
+	E1000_STAT("tx_carrier_errors", stats.tncrs),
+	E1000_NETDEV_STAT("tx_fifo_errors", stats.tx_fifo_errors),
+	E1000_NETDEV_STAT("tx_heartbeat_errors", stats.tx_heartbeat_errors),
+	E1000_STAT("tx_window_errors", stats.latecol),
+	E1000_STAT("tx_abort_late_coll", stats.latecol),
+	E1000_STAT("tx_deferred_ok", stats.dc),
+	E1000_STAT("tx_single_coll_ok", stats.scc),
+	E1000_STAT("tx_multi_coll_ok", stats.mcc),
+	E1000_STAT("tx_timeout_count", tx_timeout_count),
+	E1000_STAT("tx_restart_queue", restart_queue),
+	E1000_STAT("rx_long_length_errors", stats.roc),
+	E1000_STAT("rx_short_length_errors", stats.ruc),
+	E1000_STAT("rx_align_errors", stats.algnerrc),
+	E1000_STAT("tx_tcp_seg_good", stats.tsctc),
+	E1000_STAT("tx_tcp_seg_failed", stats.tsctfc),
+	E1000_STAT("rx_flow_control_xon", stats.xonrxc),
+	E1000_STAT("rx_flow_control_xoff", stats.xoffrxc),
+	E1000_STAT("tx_flow_control_xon", stats.xontxc),
+	E1000_STAT("tx_flow_control_xoff", stats.xofftxc),
+	E1000_STAT("rx_long_byte_count", stats.gorc),
+	E1000_STAT("rx_csum_offload_good", hw_csum_good),
+	E1000_STAT("rx_csum_offload_errors", hw_csum_err),
+	E1000_STAT("rx_header_split", rx_hdr_split),
+	E1000_STAT("alloc_rx_buff_failed", alloc_rx_buff_failed),
+	E1000_STAT("tx_smbus", stats.mgptc),
+	E1000_STAT("rx_smbus", stats.mgprc),
+	E1000_STAT("dropped_smbus", stats.mgpdc),
+	E1000_STAT("rx_dma_failed", rx_dma_failed),
+	E1000_STAT("tx_dma_failed", tx_dma_failed),
 };
 
 #define E1000_GLOBAL_STATS_LEN	ARRAY_SIZE(e1000_gstrings_stats)
@@ -194,20 +198,6 @@ static int e1000_get_settings(struct net
 	return 0;
 }
 
-static u32 e1000_get_link(struct net_device *netdev)
-{
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-	struct e1000_hw *hw = &adapter->hw;
-
-	/*
-	 * Avoid touching hardware registers when possible, otherwise
-	 * link negotiation can get messed up when user-level scripts
-	 * are rapidly polling the driver to see if link is up.
-	 */
-	return netif_running(netdev) ? netif_carrier_ok(netdev) :
-	    !!(er32(STATUS) & E1000_STATUS_LU);
-}
-
 static int e1000_set_spd_dplx(struct e1000_adapter *adapter, u16 spddplx)
 {
 	struct e1000_mac_info *mac = &adapter->hw.mac;
@@ -634,20 +624,24 @@ static void e1000_get_drvinfo(struct net
 	struct e1000_adapter *adapter = netdev_priv(netdev);
 	char firmware_version[32];
 
-	strncpy(drvinfo->driver,  e1000e_driver_name, 32);
-	strncpy(drvinfo->version, e1000e_driver_version, 32);
+	strncpy(drvinfo->driver,  e1000e_driver_name,
+		sizeof(drvinfo->driver) - 1);
+	strncpy(drvinfo->version, e1000e_driver_version,
+		sizeof(drvinfo->version) - 1);
 
 	/*
 	 * EEPROM image version # is reported as firmware version # for
 	 * PCI-E controllers
 	 */
-	sprintf(firmware_version, "%d.%d-%d",
+	snprintf(firmware_version, sizeof(firmware_version), "%d.%d-%d",
 		(adapter->eeprom_vers & 0xF000) >> 12,
 		(adapter->eeprom_vers & 0x0FF0) >> 4,
 		(adapter->eeprom_vers & 0x000F));
 
-	strncpy(drvinfo->fw_version, firmware_version, 32);
-	strncpy(drvinfo->bus_info, pci_name(adapter->pdev), 32);
+	strncpy(drvinfo->fw_version, firmware_version,
+		sizeof(drvinfo->fw_version) - 1);
+	strncpy(drvinfo->bus_info, pci_name(adapter->pdev),
+		sizeof(drvinfo->bus_info) - 1);
 	drvinfo->regdump_len = e1000_get_regs_len(netdev);
 	drvinfo->eedump_len = e1000_get_eeprom_len(netdev);
 }
@@ -763,8 +757,8 @@ static bool reg_pattern_test(struct e100
 			     int reg, int offset, u32 mask, u32 write)
 {
 	u32 pat, val;
-	static const u32 test[] =
-		{0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF};
+	static const u32 test[] = {
+		0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF};
 	for (pat = 0; pat < ARRAY_SIZE(test); pat++) {
 		E1000_WRITE_REG_ARRAY(&adapter->hw, reg, offset,
 				      (test[pat] & write));
@@ -1263,6 +1257,7 @@ static int e1000_integrated_phy_loopback
 	u32 ctrl_reg = 0;
 	u32 stat_reg = 0;
 	u16 phy_reg = 0;
+	s32 ret_val = 0;
 
 	hw->mac.autoneg = 0;
 
@@ -1322,7 +1317,13 @@ static int e1000_integrated_phy_loopback
 	case e1000_phy_82577:
 	case e1000_phy_82578:
 		/* Workaround: K1 must be disabled for stable 1Gbps operation */
+		ret_val = hw->phy.ops.acquire(hw);
+		if (ret_val) {
+			e_err("Cannot setup 1Gbps loopback.\n");
+			return ret_val;
+		}
 		e1000_configure_k1_ich8lan(hw, false);
+		hw->phy.ops.release(hw);
 		break;
 	case e1000_phy_82579:
 		/* Disable PHY energy detect power down */
@@ -1707,6 +1708,19 @@ static void e1000_diag_test(struct net_d
 	bool if_running = netif_running(netdev);
 
 	set_bit(__E1000_TESTING, &adapter->state);
+
+	if (!if_running) {
+		/* Get control of and reset hardware */
+		if (adapter->flags & FLAG_HAS_AMT)
+			e1000e_get_hw_control(adapter);
+
+		e1000e_power_up_phy(adapter);
+
+		adapter->hw.phy.autoneg_wait_to_complete = 1;
+		e1000e_reset(adapter);
+		adapter->hw.phy.autoneg_wait_to_complete = 0;
+	}
+
 	if (eth_test->flags == ETH_TEST_FL_OFFLINE) {
 		/* Offline tests */
 
@@ -1720,8 +1734,6 @@ static void e1000_diag_test(struct net_d
 		if (if_running)
 			/* indicate we're in test mode */
 			dev_close(netdev);
-		else
-			e1000e_reset(adapter);
 
 		if (e1000_reg_test(adapter, &data[0]))
 			eth_test->flags |= ETH_TEST_FL_FAILED;
@@ -1735,8 +1747,6 @@ static void e1000_diag_test(struct net_d
 			eth_test->flags |= ETH_TEST_FL_FAILED;
 
 		e1000e_reset(adapter);
-		/* make sure the phy is powered up */
-		e1000e_power_up_phy(adapter);
 		if (e1000_loopback_test(adapter, &data[3]))
 			eth_test->flags |= ETH_TEST_FL_FAILED;
 
@@ -1758,28 +1768,29 @@ static void e1000_diag_test(struct net_d
 		if (if_running)
 			dev_open(netdev);
 	} else {
-		if (!if_running && (adapter->flags & FLAG_HAS_AMT)) {
-			clear_bit(__E1000_TESTING, &adapter->state);
-			dev_open(netdev);
-			set_bit(__E1000_TESTING, &adapter->state);
-		}
+		/* Online tests */
 
 		e_info("online testing starting\n");
-		/* Online tests */
-		if (e1000_link_test(adapter, &data[4]))
-			eth_test->flags |= ETH_TEST_FL_FAILED;
 
-		/* Online tests aren't run; pass by default */
+		/* register, eeprom, intr and loopback tests not run online */
 		data[0] = 0;
 		data[1] = 0;
 		data[2] = 0;
 		data[3] = 0;
 
-		if (!if_running && (adapter->flags & FLAG_HAS_AMT))
-			dev_close(netdev);
+		if (e1000_link_test(adapter, &data[4]))
+			eth_test->flags |= ETH_TEST_FL_FAILED;
 
 		clear_bit(__E1000_TESTING, &adapter->state);
 	}
+
+	if (!if_running) {
+		e1000e_reset(adapter);
+
+		if (adapter->flags & FLAG_HAS_AMT)
+			e1000e_release_hw_control(adapter);
+	}
+
 	msleep_interruptible(4 * 1000);
 }
 
@@ -1860,7 +1871,7 @@ static int e1000_set_wol(struct net_devi
 /* bit defines for adapter->led_status */
 #define E1000_LED_ON		0
 
-static void e1000e_led_blink_task(struct work_struct *work)
+void e1000e_led_blink_task(struct work_struct *work)
 {
 	struct e1000_adapter *adapter = container_of(work,
 	                                struct e1000_adapter, led_blink_task);
@@ -1892,7 +1903,6 @@ static int e1000_phys_id(struct net_devi
 	    (hw->mac.type == e1000_pch2lan) ||
 	    (hw->mac.type == e1000_82583) ||
 	    (hw->mac.type == e1000_82574)) {
-		INIT_WORK(&adapter->led_blink_task, e1000e_led_blink_task);
 		if (!adapter->blink_timer.function) {
 			init_timer(&adapter->blink_timer);
 			adapter->blink_timer.function =
@@ -1986,6 +1996,9 @@ static void e1000_get_ethtool_stats(stru
 			p = (char *) adapter +
 					e1000_gstrings_stats[i].stat_offset;
 			break;
+		default:
+			data[i] = 0;
+			continue;
 		}
 
 		data[i] = (e1000_gstrings_stats[i].sizeof_stat ==
@@ -2024,7 +2037,7 @@ static const struct ethtool_ops e1000_et
 	.get_msglevel		= e1000_get_msglevel,
 	.set_msglevel		= e1000_set_msglevel,
 	.nway_reset		= e1000_nway_reset,
-	.get_link		= e1000_get_link,
+	.get_link		= ethtool_op_get_link,
 	.get_eeprom_len		= e1000_get_eeprom_len,
 	.get_eeprom		= e1000_get_eeprom,
 	.set_eeprom		= e1000_set_eeprom,
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/e1000e/hw.h linux-libre-2.6.38-gnu1/drivers/net/e1000e/hw.h
--- linux-libre-2.6.37-gnu1/drivers/net/e1000e/hw.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/e1000e/hw.h	2011-03-14 21:20:32.000000000 -0400
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel PRO/1000 Linux driver
-  Copyright(c) 1999 - 2010 Intel Corporation.
+  Copyright(c) 1999 - 2011 Intel 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,
@@ -83,6 +83,7 @@ enum e1e_registers {
 	E1000_EXTCNF_CTRL  = 0x00F00, /* Extended Configuration Control */
 	E1000_EXTCNF_SIZE  = 0x00F08, /* Extended Configuration Size */
 	E1000_PHY_CTRL     = 0x00F10, /* PHY Control Register in CSR */
+#define E1000_POEMB	E1000_PHY_CTRL	/* PHY OEM Bits */
 	E1000_PBA      = 0x01000, /* Packet Buffer Allocation - RW */
 	E1000_PBS      = 0x01008, /* Packet Buffer Size */
 	E1000_EEMNGCTL = 0x01010, /* MNG EEprom Control */
@@ -101,7 +102,7 @@ enum e1e_registers {
 	E1000_RDTR     = 0x02820, /* Rx Delay Timer - RW */
 	E1000_RXDCTL_BASE = 0x02828, /* Rx Descriptor Control - RW */
 #define E1000_RXDCTL(_n)   (E1000_RXDCTL_BASE + (_n << 8))
-	E1000_RADV     = 0x0282C, /* RX Interrupt Absolute Delay Timer - RW */
+	E1000_RADV     = 0x0282C, /* Rx Interrupt Absolute Delay Timer - RW */
 
 /* Convenience macros
  *
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/e1000e/ich8lan.c linux-libre-2.6.38-gnu1/drivers/net/e1000e/ich8lan.c
--- linux-libre-2.6.37-gnu1/drivers/net/e1000e/ich8lan.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/e1000e/ich8lan.c	2011-03-14 21:20:32.000000000 -0400
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel PRO/1000 Linux driver
-  Copyright(c) 1999 - 2010 Intel Corporation.
+  Copyright(c) 1999 - 2011 Intel 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,
@@ -321,7 +321,7 @@ static s32 e1000_init_phy_params_pchlan(
 	}
 
 	/*
-	 * Reset the PHY before any acccess to it.  Doing so, ensures that
+	 * Reset the PHY before any access to it.  Doing so, ensures that
 	 * the PHY is in a known good state before we read/write PHY registers.
 	 * The generic reset is sufficient here, because we haven't determined
 	 * the PHY type yet.
@@ -338,12 +338,17 @@ static s32 e1000_init_phy_params_pchlan(
 	}
 
 	phy->id = e1000_phy_unknown;
-	ret_val = e1000e_get_phy_id(hw);
-	if (ret_val)
-		goto out;
-	if ((phy->id == 0) || (phy->id == PHY_REVISION_MASK)) {
+	switch (hw->mac.type) {
+	default:
+		ret_val = e1000e_get_phy_id(hw);
+		if (ret_val)
+			goto out;
+		if ((phy->id != 0) && (phy->id != PHY_REVISION_MASK))
+			break;
+		/* fall-through */
+	case e1000_pch2lan:
 		/*
-		 * In case the PHY needs to be in mdio slow mode (eg. 82577),
+		 * In case the PHY needs to be in mdio slow mode,
 		 * set slow mode and try to get the PHY id again.
 		 */
 		ret_val = e1000_set_mdio_slow_mode_hv(hw);
@@ -352,6 +357,7 @@ static s32 e1000_init_phy_params_pchlan(
 		ret_val = e1000e_get_phy_id(hw);
 		if (ret_val)
 			goto out;
+		break;
 	}
 	phy->type = e1000e_get_phy_type_from_id(phy->id);
 
@@ -1389,22 +1395,6 @@ void e1000_copy_rx_addrs_to_phy_ich8lan(
 	}
 }
 
-static u32 e1000_calc_rx_da_crc(u8 mac[])
-{
-	u32 poly = 0xEDB88320;	/* Polynomial for 802.3 CRC calculation */
-	u32 i, j, mask, crc;
-
-	crc = 0xffffffff;
-	for (i = 0; i < 6; i++) {
-		crc = crc ^ mac[i];
-		for (j = 8; j > 0; j--) {
-			mask = (crc & 1) * (-1);
-			crc = (crc >> 1) ^ (poly & mask);
-		}
-	}
-	return ~crc;
-}
-
 /**
  *  e1000_lv_jumbo_workaround_ich8lan - required for jumbo frame operation
  *  with 82579 PHY
@@ -1447,8 +1437,7 @@ s32 e1000_lv_jumbo_workaround_ich8lan(st
 			mac_addr[4] = (addr_high & 0xFF);
 			mac_addr[5] = ((addr_high >> 8) & 0xFF);
 
-			ew32(PCH_RAICC(i),
-					e1000_calc_rx_da_crc(mac_addr));
+			ew32(PCH_RAICC(i), ~ether_crc_le(ETH_ALEN, mac_addr));
 		}
 
 		/* Write Rx addresses to the PHY */
@@ -2303,11 +2292,10 @@ static s32 e1000_read_flash_data_ich8lan
 		 */
 		if (ret_val == 0) {
 			flash_data = er32flash(ICH_FLASH_FDATA0);
-			if (size == 1) {
+			if (size == 1)
 				*data = (u8)(flash_data & 0x000000FF);
-			} else if (size == 2) {
+			else if (size == 2)
 				*data = (u16)(flash_data & 0x0000FFFF);
-			}
 			break;
 		} else {
 			/*
@@ -2972,7 +2960,7 @@ static s32 e1000_reset_hw_ich8lan(struct
 {
 	struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan;
 	u16 reg;
-	u32 ctrl, icr, kab;
+	u32 ctrl, kab;
 	s32 ret_val;
 
 	/*
@@ -3062,7 +3050,7 @@ static s32 e1000_reset_hw_ich8lan(struct
 		ew32(CRC_OFFSET, 0x65656565);
 
 	ew32(IMC, 0xffffffff);
-	icr = er32(ICR);
+	er32(ICR);
 
 	kab = er32(KABGTXD);
 	kab |= E1000_KABGTXD_BGSQLBIAS;
@@ -3113,7 +3101,7 @@ static s32 e1000_init_hw_ich8lan(struct
 	 * Reset the phy after disabling host wakeup to reset the Rx buffer.
 	 */
 	if (hw->phy.type == e1000_phy_82578) {
-		hw->phy.ops.read_reg(hw, BM_WUC, &i);
+		e1e_rphy(hw, BM_WUC, &i);
 		ret_val = e1000_phy_hw_reset_ich8lan(hw);
 		if (ret_val)
 			return ret_val;
@@ -3271,9 +3259,8 @@ static s32 e1000_setup_link_ich8lan(stru
 	    (hw->phy.type == e1000_phy_82577)) {
 		ew32(FCRTV_PCH, hw->fc.refresh_time);
 
-		ret_val = hw->phy.ops.write_reg(hw,
-		                             PHY_REG(BM_PORT_CTRL_PAGE, 27),
-		                             hw->fc.pause_time);
+		ret_val = e1e_wphy(hw, PHY_REG(BM_PORT_CTRL_PAGE, 27),
+				   hw->fc.pause_time);
 		if (ret_val)
 			return ret_val;
 	}
@@ -3337,8 +3324,7 @@ static s32 e1000_setup_copper_link_ich8l
 			return ret_val;
 		break;
 	case e1000_phy_ife:
-		ret_val = hw->phy.ops.read_reg(hw, IFE_PHY_MDIX_CONTROL,
-		                               &reg_data);
+		ret_val = e1e_rphy(hw, IFE_PHY_MDIX_CONTROL, &reg_data);
 		if (ret_val)
 			return ret_val;
 
@@ -3356,8 +3342,7 @@ static s32 e1000_setup_copper_link_ich8l
 			reg_data |= IFE_PMC_AUTO_MDIX;
 			break;
 		}
-		ret_val = hw->phy.ops.write_reg(hw, IFE_PHY_MDIX_CONTROL,
-		                                reg_data);
+		ret_val = e1e_wphy(hw, IFE_PHY_MDIX_CONTROL, reg_data);
 		if (ret_val)
 			return ret_val;
 		break;
@@ -3591,7 +3576,7 @@ void e1000e_disable_gig_wol_ich8lan(stru
 	ew32(PHY_CTRL, phy_ctrl);
 
 	if (hw->mac.type >= e1000_pchlan) {
-		e1000_oem_bits_config_ich8lan(hw, true);
+		e1000_oem_bits_config_ich8lan(hw, false);
 		ret_val = hw->phy.ops.acquire(hw);
 		if (ret_val)
 			return;
@@ -3641,7 +3626,8 @@ static s32 e1000_led_off_ich8lan(struct
 {
 	if (hw->phy.type == e1000_phy_ife)
 		return e1e_wphy(hw, IFE_PHY_SPECIAL_CONTROL_LED,
-			       (IFE_PSCL_PROBE_MODE | IFE_PSCL_PROBE_LEDS_OFF));
+				(IFE_PSCL_PROBE_MODE |
+				 IFE_PSCL_PROBE_LEDS_OFF));
 
 	ew32(LEDCTL, hw->mac.ledctl_mode1);
 	return 0;
@@ -3655,8 +3641,7 @@ static s32 e1000_led_off_ich8lan(struct
  **/
 static s32 e1000_setup_led_pchlan(struct e1000_hw *hw)
 {
-	return hw->phy.ops.write_reg(hw, HV_LED_CONFIG,
-					(u16)hw->mac.ledctl_mode1);
+	return e1e_wphy(hw, HV_LED_CONFIG, (u16)hw->mac.ledctl_mode1);
 }
 
 /**
@@ -3667,8 +3652,7 @@ static s32 e1000_setup_led_pchlan(struct
  **/
 static s32 e1000_cleanup_led_pchlan(struct e1000_hw *hw)
 {
-	return hw->phy.ops.write_reg(hw, HV_LED_CONFIG,
-					(u16)hw->mac.ledctl_default);
+	return e1e_wphy(hw, HV_LED_CONFIG, (u16)hw->mac.ledctl_default);
 }
 
 /**
@@ -3699,7 +3683,7 @@ static s32 e1000_led_on_pchlan(struct e1
 		}
 	}
 
-	return hw->phy.ops.write_reg(hw, HV_LED_CONFIG, data);
+	return e1e_wphy(hw, HV_LED_CONFIG, data);
 }
 
 /**
@@ -3730,7 +3714,7 @@ static s32 e1000_led_off_pchlan(struct e
 		}
 	}
 
-	return hw->phy.ops.write_reg(hw, HV_LED_CONFIG, data);
+	return e1e_wphy(hw, HV_LED_CONFIG, data);
 }
 
 /**
@@ -3839,20 +3823,20 @@ static void e1000_clear_hw_cntrs_ich8lan
 	if ((hw->phy.type == e1000_phy_82578) ||
 	    (hw->phy.type == e1000_phy_82579) ||
 	    (hw->phy.type == e1000_phy_82577)) {
-		hw->phy.ops.read_reg(hw, HV_SCC_UPPER, &phy_data);
-		hw->phy.ops.read_reg(hw, HV_SCC_LOWER, &phy_data);
-		hw->phy.ops.read_reg(hw, HV_ECOL_UPPER, &phy_data);
-		hw->phy.ops.read_reg(hw, HV_ECOL_LOWER, &phy_data);
-		hw->phy.ops.read_reg(hw, HV_MCC_UPPER, &phy_data);
-		hw->phy.ops.read_reg(hw, HV_MCC_LOWER, &phy_data);
-		hw->phy.ops.read_reg(hw, HV_LATECOL_UPPER, &phy_data);
-		hw->phy.ops.read_reg(hw, HV_LATECOL_LOWER, &phy_data);
-		hw->phy.ops.read_reg(hw, HV_COLC_UPPER, &phy_data);
-		hw->phy.ops.read_reg(hw, HV_COLC_LOWER, &phy_data);
-		hw->phy.ops.read_reg(hw, HV_DC_UPPER, &phy_data);
-		hw->phy.ops.read_reg(hw, HV_DC_LOWER, &phy_data);
-		hw->phy.ops.read_reg(hw, HV_TNCRS_UPPER, &phy_data);
-		hw->phy.ops.read_reg(hw, HV_TNCRS_LOWER, &phy_data);
+		e1e_rphy(hw, HV_SCC_UPPER, &phy_data);
+		e1e_rphy(hw, HV_SCC_LOWER, &phy_data);
+		e1e_rphy(hw, HV_ECOL_UPPER, &phy_data);
+		e1e_rphy(hw, HV_ECOL_LOWER, &phy_data);
+		e1e_rphy(hw, HV_MCC_UPPER, &phy_data);
+		e1e_rphy(hw, HV_MCC_LOWER, &phy_data);
+		e1e_rphy(hw, HV_LATECOL_UPPER, &phy_data);
+		e1e_rphy(hw, HV_LATECOL_LOWER, &phy_data);
+		e1e_rphy(hw, HV_COLC_UPPER, &phy_data);
+		e1e_rphy(hw, HV_COLC_LOWER, &phy_data);
+		e1e_rphy(hw, HV_DC_UPPER, &phy_data);
+		e1e_rphy(hw, HV_DC_LOWER, &phy_data);
+		e1e_rphy(hw, HV_TNCRS_UPPER, &phy_data);
+		e1e_rphy(hw, HV_TNCRS_LOWER, &phy_data);
 	}
 }
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/e1000e/lib.c linux-libre-2.6.38-gnu1/drivers/net/e1000e/lib.c
--- linux-libre-2.6.37-gnu1/drivers/net/e1000e/lib.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/e1000e/lib.c	2011-03-14 21:20:32.000000000 -0400
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel PRO/1000 Linux driver
-  Copyright(c) 1999 - 2010 Intel Corporation.
+  Copyright(c) 1999 - 2011 Intel 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,
@@ -493,9 +493,8 @@ s32 e1000e_check_for_copper_link(struct
 	 * different link partner.
 	 */
 	ret_val = e1000e_config_fc_after_link_up(hw);
-	if (ret_val) {
+	if (ret_val)
 		e_dbg("Error configuring flow control\n");
-	}
 
 	return ret_val;
 }
@@ -534,7 +533,7 @@ s32 e1000e_check_for_fiber_link(struct e
 			mac->autoneg_failed = 1;
 			return 0;
 		}
-		e_dbg("NOT RXing /C/, disable AutoNeg and force link.\n");
+		e_dbg("NOT Rx'ing /C/, disable AutoNeg and force link.\n");
 
 		/* Disable auto-negotiation in the TXCW register */
 		ew32(TXCW, (mac->txcw & ~E1000_TXCW_ANE));
@@ -557,7 +556,7 @@ s32 e1000e_check_for_fiber_link(struct e
 		 * and disable forced link in the Device Control register
 		 * in an attempt to auto-negotiate with our link partner.
 		 */
-		e_dbg("RXing /C/, enable AutoNeg and stop forcing link.\n");
+		e_dbg("Rx'ing /C/, enable AutoNeg and stop forcing link.\n");
 		ew32(TXCW, mac->txcw);
 		ew32(CTRL, (ctrl & ~E1000_CTRL_SLU));
 
@@ -599,7 +598,7 @@ s32 e1000e_check_for_serdes_link(struct
 			mac->autoneg_failed = 1;
 			return 0;
 		}
-		e_dbg("NOT RXing /C/, disable AutoNeg and force link.\n");
+		e_dbg("NOT Rx'ing /C/, disable AutoNeg and force link.\n");
 
 		/* Disable auto-negotiation in the TXCW register */
 		ew32(TXCW, (mac->txcw & ~E1000_TXCW_ANE));
@@ -622,7 +621,7 @@ s32 e1000e_check_for_serdes_link(struct
 		 * and disable forced link in the Device Control register
 		 * in an attempt to auto-negotiate with our link partner.
 		 */
-		e_dbg("RXing /C/, enable AutoNeg and stop forcing link.\n");
+		e_dbg("Rx'ing /C/, enable AutoNeg and stop forcing link.\n");
 		ew32(TXCW, mac->txcw);
 		ew32(CTRL, (ctrl & ~E1000_CTRL_SLU));
 
@@ -801,9 +800,9 @@ static s32 e1000_commit_fc_settings_gene
 	 * The possible values of the "fc" parameter are:
 	 *      0:  Flow control is completely disabled
 	 *      1:  Rx flow control is enabled (we can receive pause frames,
-	 *	  but not send pause frames).
+	 *          but not send pause frames).
 	 *      2:  Tx flow control is enabled (we can send pause frames but we
-	 *	  do not support receiving pause frames).
+	 *          do not support receiving pause frames).
 	 *      3:  Both Rx and Tx flow control (symmetric) are enabled.
 	 */
 	switch (hw->fc.current_mode) {
@@ -1032,9 +1031,9 @@ s32 e1000e_force_mac_fc(struct e1000_hw
 	 * The possible values of the "fc" parameter are:
 	 *      0:  Flow control is completely disabled
 	 *      1:  Rx flow control is enabled (we can receive pause
-	 *	  frames but not send pause frames).
+	 *          frames but not send pause frames).
 	 *      2:  Tx flow control is enabled (we can send pause frames
-	 *	  frames but we do not receive pause frames).
+	 *          frames but we do not receive pause frames).
 	 *      3:  Both Rx and Tx flow control (symmetric) is enabled.
 	 *  other:  No other values should be possible at this point.
 	 */
@@ -1136,7 +1135,8 @@ s32 e1000e_config_fc_after_link_up(struc
 		ret_val = e1e_rphy(hw, PHY_AUTONEG_ADV, &mii_nway_adv_reg);
 		if (ret_val)
 			return ret_val;
-		ret_val = e1e_rphy(hw, PHY_LP_ABILITY, &mii_nway_lp_ability_reg);
+		ret_val =
+		    e1e_rphy(hw, PHY_LP_ABILITY, &mii_nway_lp_ability_reg);
 		if (ret_val)
 			return ret_val;
 
@@ -1189,7 +1189,7 @@ s32 e1000e_config_fc_after_link_up(struc
 			} else {
 				hw->fc.current_mode = e1000_fc_rx_pause;
 				e_dbg("Flow Control = "
-					 "RX PAUSE frames only.\r\n");
+				      "Rx PAUSE frames only.\r\n");
 			}
 		}
 		/*
@@ -1496,9 +1496,8 @@ s32 e1000e_setup_led_generic(struct e100
 {
 	u32 ledctl;
 
-	if (hw->mac.ops.setup_led != e1000e_setup_led_generic) {
+	if (hw->mac.ops.setup_led != e1000e_setup_led_generic)
 		return -E1000_ERR_CONFIG;
-	}
 
 	if (hw->phy.media_type == e1000_media_type_fiber) {
 		ledctl = er32(LEDCTL);
@@ -2139,6 +2138,119 @@ s32 e1000e_write_nvm_spi(struct e1000_hw
 }
 
 /**
+ *  e1000_read_pba_string_generic - Read device part number
+ *  @hw: pointer to the HW structure
+ *  @pba_num: pointer to device part number
+ *  @pba_num_size: size of part number buffer
+ *
+ *  Reads the product board assembly (PBA) number from the EEPROM and stores
+ *  the value in pba_num.
+ **/
+s32 e1000_read_pba_string_generic(struct e1000_hw *hw, u8 *pba_num,
+				  u32 pba_num_size)
+{
+	s32 ret_val;
+	u16 nvm_data;
+	u16 pba_ptr;
+	u16 offset;
+	u16 length;
+
+	if (pba_num == NULL) {
+		e_dbg("PBA string buffer was null\n");
+		ret_val = E1000_ERR_INVALID_ARGUMENT;
+		goto out;
+	}
+
+	ret_val = e1000_read_nvm(hw, NVM_PBA_OFFSET_0, 1, &nvm_data);
+	if (ret_val) {
+		e_dbg("NVM Read Error\n");
+		goto out;
+	}
+
+	ret_val = e1000_read_nvm(hw, NVM_PBA_OFFSET_1, 1, &pba_ptr);
+	if (ret_val) {
+		e_dbg("NVM Read Error\n");
+		goto out;
+	}
+
+	/*
+	 * if nvm_data is not ptr guard the PBA must be in legacy format which
+	 * means pba_ptr is actually our second data word for the PBA number
+	 * and we can decode it into an ascii string
+	 */
+	if (nvm_data != NVM_PBA_PTR_GUARD) {
+		e_dbg("NVM PBA number is not stored as string\n");
+
+		/* we will need 11 characters to store the PBA */
+		if (pba_num_size < 11) {
+			e_dbg("PBA string buffer too small\n");
+			return E1000_ERR_NO_SPACE;
+		}
+
+		/* extract hex string from data and pba_ptr */
+		pba_num[0] = (nvm_data >> 12) & 0xF;
+		pba_num[1] = (nvm_data >> 8) & 0xF;
+		pba_num[2] = (nvm_data >> 4) & 0xF;
+		pba_num[3] = nvm_data & 0xF;
+		pba_num[4] = (pba_ptr >> 12) & 0xF;
+		pba_num[5] = (pba_ptr >> 8) & 0xF;
+		pba_num[6] = '-';
+		pba_num[7] = 0;
+		pba_num[8] = (pba_ptr >> 4) & 0xF;
+		pba_num[9] = pba_ptr & 0xF;
+
+		/* put a null character on the end of our string */
+		pba_num[10] = '\0';
+
+		/* switch all the data but the '-' to hex char */
+		for (offset = 0; offset < 10; offset++) {
+			if (pba_num[offset] < 0xA)
+				pba_num[offset] += '0';
+			else if (pba_num[offset] < 0x10)
+				pba_num[offset] += 'A' - 0xA;
+		}
+
+		goto out;
+	}
+
+	ret_val = e1000_read_nvm(hw, pba_ptr, 1, &length);
+	if (ret_val) {
+		e_dbg("NVM Read Error\n");
+		goto out;
+	}
+
+	if (length == 0xFFFF || length == 0) {
+		e_dbg("NVM PBA number section invalid length\n");
+		ret_val = E1000_ERR_NVM_PBA_SECTION;
+		goto out;
+	}
+	/* check if pba_num buffer is big enough */
+	if (pba_num_size < (((u32)length * 2) - 1)) {
+		e_dbg("PBA string buffer too small\n");
+		ret_val = E1000_ERR_NO_SPACE;
+		goto out;
+	}
+
+	/* trim pba length from start of string */
+	pba_ptr++;
+	length--;
+
+	for (offset = 0; offset < length; offset++) {
+		ret_val = e1000_read_nvm(hw, pba_ptr + offset, 1, &nvm_data);
+		if (ret_val) {
+			e_dbg("NVM Read Error\n");
+			goto out;
+		}
+		pba_num[offset * 2] = (u8)(nvm_data >> 8);
+		pba_num[(offset * 2) + 1] = (u8)(nvm_data & 0xFF);
+	}
+	pba_num[offset * 2] = '\0';
+
+out:
+	return ret_val;
+}
+
+/**
  *  e1000_read_mac_addr_generic - Read device MAC address
  *  @hw: pointer to the HW structure
  *
@@ -2579,25 +2691,3 @@ bool e1000e_enable_mng_pass_thru(struct
 out:
 	return ret_val;
 }
-
-s32 e1000e_read_pba_num(struct e1000_hw *hw, u32 *pba_num)
-{
-	s32 ret_val;
-	u16 nvm_data;
-
-	ret_val = e1000_read_nvm(hw, NVM_PBA_OFFSET_0, 1, &nvm_data);
-	if (ret_val) {
-		e_dbg("NVM Read Error\n");
-		return ret_val;
-	}
-	*pba_num = (u32)(nvm_data << 16);
-
-	ret_val = e1000_read_nvm(hw, NVM_PBA_OFFSET_1, 1, &nvm_data);
-	if (ret_val) {
-		e_dbg("NVM Read Error\n");
-		return ret_val;
-	}
-	*pba_num |= nvm_data;
-
-	return 0;
-}
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/e1000e/Makefile linux-libre-2.6.38-gnu1/drivers/net/e1000e/Makefile
--- linux-libre-2.6.37-gnu1/drivers/net/e1000e/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/e1000e/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -1,7 +1,7 @@
 ################################################################################
 #
 # Intel PRO/1000 Linux driver
-# Copyright(c) 1999 - 2008 Intel Corporation.
+# Copyright(c) 1999 - 2011 Intel 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,
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/e1000e/netdev.c linux-libre-2.6.38-gnu1/drivers/net/e1000e/netdev.c
--- linux-libre-2.6.37-gnu1/drivers/net/e1000e/netdev.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/e1000e/netdev.c	2011-03-14 21:20:32.000000000 -0400
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel PRO/1000 Linux driver
-  Copyright(c) 1999 - 2010 Intel Corporation.
+  Copyright(c) 1999 - 2011 Intel 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,
@@ -54,7 +54,7 @@
 
 #define DRV_EXTRAVERSION "-k2"
 
-#define DRV_VERSION "1.2.7" DRV_EXTRAVERSION
+#define DRV_VERSION "1.2.20" DRV_EXTRAVERSION
 char e1000e_driver_name[] = "e1000e";
 const char e1000e_driver_version[] = DRV_VERSION;
 
@@ -77,17 +77,17 @@ struct e1000_reg_info {
 	char *name;
 };
 
-#define E1000_RDFH	0x02410 /* Rx Data FIFO Head - RW */
-#define E1000_RDFT	0x02418 /* Rx Data FIFO Tail - RW */
-#define E1000_RDFHS	0x02420 /* Rx Data FIFO Head Saved - RW */
-#define E1000_RDFTS	0x02428 /* Rx Data FIFO Tail Saved - RW */
-#define E1000_RDFPC	0x02430 /* Rx Data FIFO Packet Count - RW */
+#define E1000_RDFH	0x02410	/* Rx Data FIFO Head - RW */
+#define E1000_RDFT	0x02418	/* Rx Data FIFO Tail - RW */
+#define E1000_RDFHS	0x02420	/* Rx Data FIFO Head Saved - RW */
+#define E1000_RDFTS	0x02428	/* Rx Data FIFO Tail Saved - RW */
+#define E1000_RDFPC	0x02430	/* Rx Data FIFO Packet Count - RW */
 
-#define E1000_TDFH	0x03410 /* Tx Data FIFO Head - RW */
-#define E1000_TDFT	0x03418 /* Tx Data FIFO Tail - RW */
-#define E1000_TDFHS	0x03420 /* Tx Data FIFO Head Saved - RW */
-#define E1000_TDFTS	0x03428 /* Tx Data FIFO Tail Saved - RW */
-#define E1000_TDFPC	0x03430 /* Tx Data FIFO Packet Count - RW */
+#define E1000_TDFH	0x03410	/* Tx Data FIFO Head - RW */
+#define E1000_TDFT	0x03418	/* Tx Data FIFO Tail - RW */
+#define E1000_TDFHS	0x03420	/* Tx Data FIFO Head Saved - RW */
+#define E1000_TDFTS	0x03428	/* Tx Data FIFO Tail Saved - RW */
+#define E1000_TDFPC	0x03430	/* Tx Data FIFO Packet Count - RW */
 
 static const struct e1000_reg_info e1000_reg_info_tbl[] = {
 
@@ -99,7 +99,7 @@ static const struct e1000_reg_info e1000
 	/* Interrupt Registers */
 	{E1000_ICR, "ICR"},
 
-	/* RX Registers */
+	/* Rx Registers */
 	{E1000_RCTL, "RCTL"},
 	{E1000_RDLEN, "RDLEN"},
 	{E1000_RDH, "RDH"},
@@ -115,7 +115,7 @@ static const struct e1000_reg_info e1000
 	{E1000_RDFTS, "RDFTS"},
 	{E1000_RDFPC, "RDFPC"},
 
-	/* TX Registers */
+	/* Tx Registers */
 	{E1000_TCTL, "TCTL"},
 	{E1000_TDBAL, "TDBAL"},
 	{E1000_TDBAH, "TDBAH"},
@@ -160,7 +160,7 @@ static void e1000_regdump(struct e1000_h
 		break;
 	default:
 		printk(KERN_INFO "%-15s %08x\n",
-			reginfo->name, __er32(hw, reginfo->ofs));
+		       reginfo->name, __er32(hw, reginfo->ofs));
 		return;
 	}
 
@@ -171,9 +171,8 @@ static void e1000_regdump(struct e1000_h
 	printk(KERN_CONT "\n");
 }
 
-
 /*
- * e1000e_dump - Print registers, tx-ring and rx-ring
+ * e1000e_dump - Print registers, Tx-ring and Rx-ring
  */
 static void e1000e_dump(struct e1000_adapter *adapter)
 {
@@ -182,12 +181,20 @@ static void e1000e_dump(struct e1000_ada
 	struct e1000_reg_info *reginfo;
 	struct e1000_ring *tx_ring = adapter->tx_ring;
 	struct e1000_tx_desc *tx_desc;
-	struct my_u0 { u64 a; u64 b; } *u0;
+	struct my_u0 {
+		u64 a;
+		u64 b;
+	} *u0;
 	struct e1000_buffer *buffer_info;
 	struct e1000_ring *rx_ring = adapter->rx_ring;
 	union e1000_rx_desc_packet_split *rx_desc_ps;
 	struct e1000_rx_desc *rx_desc;
-	struct my_u1 { u64 a; u64 b; u64 c; u64 d; } *u1;
+	struct my_u1 {
+		u64 a;
+		u64 b;
+		u64 c;
+		u64 d;
+	} *u1;
 	u32 staterr;
 	int i = 0;
 
@@ -198,12 +205,10 @@ static void e1000e_dump(struct e1000_ada
 	if (netdev) {
 		dev_info(&adapter->pdev->dev, "Net device Info\n");
 		printk(KERN_INFO "Device Name     state            "
-			"trans_start      last_rx\n");
+		       "trans_start      last_rx\n");
 		printk(KERN_INFO "%-15s %016lX %016lX %016lX\n",
-			netdev->name,
-			netdev->state,
-			netdev->trans_start,
-			netdev->last_rx);
+		       netdev->name, netdev->state, netdev->trans_start,
+		       netdev->last_rx);
 	}
 
 	/* Print Registers */
@@ -214,26 +219,26 @@ static void e1000e_dump(struct e1000_ada
 		e1000_regdump(hw, reginfo);
 	}
 
-	/* Print TX Ring Summary */
+	/* Print Tx Ring Summary */
 	if (!netdev || !netif_running(netdev))
 		goto exit;
 
-	dev_info(&adapter->pdev->dev, "TX Rings Summary\n");
+	dev_info(&adapter->pdev->dev, "Tx Ring Summary\n");
 	printk(KERN_INFO "Queue [NTU] [NTC] [bi(ntc)->dma  ]"
-		" leng ntw timestamp\n");
+	       " leng ntw timestamp\n");
 	buffer_info = &tx_ring->buffer_info[tx_ring->next_to_clean];
 	printk(KERN_INFO " %5d %5X %5X %016llX %04X %3X %016llX\n",
-		0, tx_ring->next_to_use, tx_ring->next_to_clean,
-		(unsigned long long)buffer_info->dma,
-		buffer_info->length,
-		buffer_info->next_to_watch,
-		(unsigned long long)buffer_info->time_stamp);
+	       0, tx_ring->next_to_use, tx_ring->next_to_clean,
+	       (unsigned long long)buffer_info->dma,
+	       buffer_info->length,
+	       buffer_info->next_to_watch,
+	       (unsigned long long)buffer_info->time_stamp);
 
-	/* Print TX Rings */
+	/* Print Tx Ring */
 	if (!netif_msg_tx_done(adapter))
 		goto rx_ring_summary;
 
-	dev_info(&adapter->pdev->dev, "TX Rings Dump\n");
+	dev_info(&adapter->pdev->dev, "Tx Ring Dump\n");
 
 	/* Transmit Descriptor Formats - DEXT[29] is 0 (Legacy) or 1 (Extended)
 	 *
@@ -263,22 +268,22 @@ static void e1000e_dump(struct e1000_ada
 	 *   63       48 47     40 39  36 35    32 31     24 23  20 19        0
 	 */
 	printk(KERN_INFO "Tl[desc]     [address 63:0  ] [SpeCssSCmCsLen]"
-		" [bi->dma       ] leng  ntw timestamp        bi->skb "
-		"<-- Legacy format\n");
+	       " [bi->dma       ] leng  ntw timestamp        bi->skb "
+	       "<-- Legacy format\n");
 	printk(KERN_INFO "Tc[desc]     [Ce CoCsIpceCoS] [MssHlRSCm0Plen]"
-		" [bi->dma       ] leng  ntw timestamp        bi->skb "
-		"<-- Ext Context format\n");
+	       " [bi->dma       ] leng  ntw timestamp        bi->skb "
+	       "<-- Ext Context format\n");
 	printk(KERN_INFO "Td[desc]     [address 63:0  ] [VlaPoRSCm1Dlen]"
-		" [bi->dma       ] leng  ntw timestamp        bi->skb "
-		"<-- Ext Data format\n");
+	       " [bi->dma       ] leng  ntw timestamp        bi->skb "
+	       "<-- Ext Data format\n");
 	for (i = 0; tx_ring->desc && (i < tx_ring->count); i++) {
 		tx_desc = E1000_TX_DESC(*tx_ring, i);
 		buffer_info = &tx_ring->buffer_info[i];
 		u0 = (struct my_u0 *)tx_desc;
 		printk(KERN_INFO "T%c[0x%03X]    %016llX %016llX %016llX "
-			"%04X  %3X %016llX %p",
-		       (!(le64_to_cpu(u0->b) & (1<<29)) ? 'l' :
-			((le64_to_cpu(u0->b) & (1<<20)) ? 'd' : 'c')), i,
+		       "%04X  %3X %016llX %p",
+		       (!(le64_to_cpu(u0->b) & (1 << 29)) ? 'l' :
+			((le64_to_cpu(u0->b) & (1 << 20)) ? 'd' : 'c')), i,
 		       (unsigned long long)le64_to_cpu(u0->a),
 		       (unsigned long long)le64_to_cpu(u0->b),
 		       (unsigned long long)buffer_info->dma,
@@ -296,22 +301,22 @@ static void e1000e_dump(struct e1000_ada
 
 		if (netif_msg_pktdata(adapter) && buffer_info->dma != 0)
 			print_hex_dump(KERN_INFO, "", DUMP_PREFIX_ADDRESS,
-					16, 1, phys_to_virt(buffer_info->dma),
-					buffer_info->length, true);
+				       16, 1, phys_to_virt(buffer_info->dma),
+				       buffer_info->length, true);
 	}
 
-	/* Print RX Rings Summary */
+	/* Print Rx Ring Summary */
 rx_ring_summary:
-	dev_info(&adapter->pdev->dev, "RX Rings Summary\n");
+	dev_info(&adapter->pdev->dev, "Rx Ring Summary\n");
 	printk(KERN_INFO "Queue [NTU] [NTC]\n");
 	printk(KERN_INFO " %5d %5X %5X\n", 0,
-		rx_ring->next_to_use, rx_ring->next_to_clean);
+	       rx_ring->next_to_use, rx_ring->next_to_clean);
 
-	/* Print RX Rings */
+	/* Print Rx Ring */
 	if (!netif_msg_rx_status(adapter))
 		goto exit;
 
-	dev_info(&adapter->pdev->dev, "RX Rings Dump\n");
+	dev_info(&adapter->pdev->dev, "Rx Ring Dump\n");
 	switch (adapter->rx_ps_pages) {
 	case 1:
 	case 2:
@@ -329,7 +334,7 @@ rx_ring_summary:
 		 *    +-----------------------------------------------------+
 		 */
 		printk(KERN_INFO "R  [desc]      [buffer 0 63:0 ] "
-			"[buffer 1 63:0 ] "
+		       "[buffer 1 63:0 ] "
 		       "[buffer 2 63:0 ] [buffer 3 63:0 ] [bi->dma       ] "
 		       "[bi->skb] <-- Ext Pkt Split format\n");
 		/* [Extended] Receive Descriptor (Write-Back) Format
@@ -344,7 +349,7 @@ rx_ring_summary:
 		 *   63       48 47    32 31            20 19               0
 		 */
 		printk(KERN_INFO "RWB[desc]      [ck ipid mrqhsh] "
-			"[vl   l0 ee  es] "
+		       "[vl   l0 ee  es] "
 		       "[ l3  l2  l1 hs] [reserved      ] ---------------- "
 		       "[bi->skb] <-- Ext Rx Write-Back format\n");
 		for (i = 0; i < rx_ring->count; i++) {
@@ -352,26 +357,26 @@ rx_ring_summary:
 			rx_desc_ps = E1000_RX_DESC_PS(*rx_ring, i);
 			u1 = (struct my_u1 *)rx_desc_ps;
 			staterr =
-				le32_to_cpu(rx_desc_ps->wb.middle.status_error);
+			    le32_to_cpu(rx_desc_ps->wb.middle.status_error);
 			if (staterr & E1000_RXD_STAT_DD) {
 				/* Descriptor Done */
 				printk(KERN_INFO "RWB[0x%03X]     %016llX "
-					"%016llX %016llX %016llX "
-					"---------------- %p", i,
-					(unsigned long long)le64_to_cpu(u1->a),
-					(unsigned long long)le64_to_cpu(u1->b),
-					(unsigned long long)le64_to_cpu(u1->c),
-					(unsigned long long)le64_to_cpu(u1->d),
-					buffer_info->skb);
+				       "%016llX %016llX %016llX "
+				       "---------------- %p", i,
+				       (unsigned long long)le64_to_cpu(u1->a),
+				       (unsigned long long)le64_to_cpu(u1->b),
+				       (unsigned long long)le64_to_cpu(u1->c),
+				       (unsigned long long)le64_to_cpu(u1->d),
+				       buffer_info->skb);
 			} else {
 				printk(KERN_INFO "R  [0x%03X]     %016llX "
-					"%016llX %016llX %016llX %016llX %p", i,
-					(unsigned long long)le64_to_cpu(u1->a),
-					(unsigned long long)le64_to_cpu(u1->b),
-					(unsigned long long)le64_to_cpu(u1->c),
-					(unsigned long long)le64_to_cpu(u1->d),
-					(unsigned long long)buffer_info->dma,
-					buffer_info->skb);
+				       "%016llX %016llX %016llX %016llX %p", i,
+				       (unsigned long long)le64_to_cpu(u1->a),
+				       (unsigned long long)le64_to_cpu(u1->b),
+				       (unsigned long long)le64_to_cpu(u1->c),
+				       (unsigned long long)le64_to_cpu(u1->d),
+				       (unsigned long long)buffer_info->dma,
+				       buffer_info->skb);
 
 				if (netif_msg_pktdata(adapter))
 					print_hex_dump(KERN_INFO, "",
@@ -400,18 +405,18 @@ rx_ring_summary:
 		 * 63       48 47    40 39      32 31         16 15      0
 		 */
 		printk(KERN_INFO "Rl[desc]     [address 63:0  ] "
-			"[vl er S cks ln] [bi->dma       ] [bi->skb] "
-			"<-- Legacy format\n");
+		       "[vl er S cks ln] [bi->dma       ] [bi->skb] "
+		       "<-- Legacy format\n");
 		for (i = 0; rx_ring->desc && (i < rx_ring->count); i++) {
 			rx_desc = E1000_RX_DESC(*rx_ring, i);
 			buffer_info = &rx_ring->buffer_info[i];
 			u0 = (struct my_u0 *)rx_desc;
 			printk(KERN_INFO "Rl[0x%03X]    %016llX %016llX "
-				"%016llX %p", i,
-				(unsigned long long)le64_to_cpu(u0->a),
-				(unsigned long long)le64_to_cpu(u0->b),
-				(unsigned long long)buffer_info->dma,
-				buffer_info->skb);
+			       "%016llX %p", i,
+			       (unsigned long long)le64_to_cpu(u0->a),
+			       (unsigned long long)le64_to_cpu(u0->b),
+			       (unsigned long long)buffer_info->dma,
+			       buffer_info->skb);
 			if (i == rx_ring->next_to_use)
 				printk(KERN_CONT " NTU\n");
 			else if (i == rx_ring->next_to_clean)
@@ -421,9 +426,10 @@ rx_ring_summary:
 
 			if (netif_msg_pktdata(adapter))
 				print_hex_dump(KERN_INFO, "",
-					DUMP_PREFIX_ADDRESS,
-					16, 1, phys_to_virt(buffer_info->dma),
-					adapter->rx_buffer_len, true);
+					       DUMP_PREFIX_ADDRESS,
+					       16, 1,
+					       phys_to_virt(buffer_info->dma),
+					       adapter->rx_buffer_len, true);
 		}
 	}
 
@@ -450,8 +456,7 @@ static int e1000_desc_unused(struct e100
  * @skb: pointer to sk_buff to be indicated to stack
  **/
 static void e1000_receive_skb(struct e1000_adapter *adapter,
-			      struct net_device *netdev,
-			      struct sk_buff *skb,
+			      struct net_device *netdev, struct sk_buff *skb,
 			      u8 status, __le16 vlan)
 {
 	skb->protocol = eth_type_trans(skb, netdev);
@@ -464,7 +469,7 @@ static void e1000_receive_skb(struct e10
 }
 
 /**
- * e1000_rx_checksum - Receive Checksum Offload for 82543
+ * e1000_rx_checksum - Receive Checksum Offload
  * @adapter:     board private structure
  * @status_err:  receive descriptor status and error fields
  * @csum:	receive descriptor csum field
@@ -548,7 +553,7 @@ map_skb:
 						  adapter->rx_buffer_len,
 						  DMA_FROM_DEVICE);
 		if (dma_mapping_error(&pdev->dev, buffer_info->dma)) {
-			dev_err(&pdev->dev, "RX DMA map failed\n");
+			dev_err(&pdev->dev, "Rx DMA map failed\n");
 			adapter->rx_dma_failed++;
 			break;
 		}
@@ -601,7 +606,8 @@ static void e1000_alloc_rx_buffers_ps(st
 			ps_page = &buffer_info->ps_pages[j];
 			if (j >= adapter->rx_ps_pages) {
 				/* all unused desc entries get hw null ptr */
-				rx_desc->read.buffer_addr[j+1] = ~cpu_to_le64(0);
+				rx_desc->read.buffer_addr[j + 1] =
+				    ~cpu_to_le64(0);
 				continue;
 			}
 			if (!ps_page->page) {
@@ -617,7 +623,7 @@ static void e1000_alloc_rx_buffers_ps(st
 				if (dma_mapping_error(&pdev->dev,
 						      ps_page->dma)) {
 					dev_err(&adapter->pdev->dev,
-					  "RX DMA page map failed\n");
+						"Rx DMA page map failed\n");
 					adapter->rx_dma_failed++;
 					goto no_buffers;
 				}
@@ -627,8 +633,8 @@ static void e1000_alloc_rx_buffers_ps(st
 			 * didn't change because each write-back
 			 * erases this info.
 			 */
-			rx_desc->read.buffer_addr[j+1] =
-			     cpu_to_le64(ps_page->dma);
+			rx_desc->read.buffer_addr[j + 1] =
+			    cpu_to_le64(ps_page->dma);
 		}
 
 		skb = netdev_alloc_skb_ip_align(netdev,
@@ -644,7 +650,7 @@ static void e1000_alloc_rx_buffers_ps(st
 						  adapter->rx_ps_bsize0,
 						  DMA_FROM_DEVICE);
 		if (dma_mapping_error(&pdev->dev, buffer_info->dma)) {
-			dev_err(&pdev->dev, "RX DMA map failed\n");
+			dev_err(&pdev->dev, "Rx DMA map failed\n");
 			adapter->rx_dma_failed++;
 			/* cleanup skb */
 			dev_kfree_skb_any(skb);
@@ -662,7 +668,7 @@ static void e1000_alloc_rx_buffers_ps(st
 			 * such as IA-64).
 			 */
 			wmb();
-			writel(i<<1, adapter->hw.hw_addr + rx_ring->tail);
+			writel(i << 1, adapter->hw.hw_addr + rx_ring->tail);
 		}
 
 		i++;
@@ -931,6 +937,9 @@ static void e1000_print_hw_hang(struct w
 	u16 phy_status, phy_1000t_status, phy_ext_status;
 	u16 pci_status;
 
+	if (test_bit(__E1000_DOWN, &adapter->state))
+		return;
+
 	e1e_rphy(hw, PHY_STATUS, &phy_status);
 	e1e_rphy(hw, PHY_1000T_STATUS, &phy_1000t_status);
 	e1e_rphy(hw, PHY_EXT_STATUS, &phy_ext_status);
@@ -1106,11 +1115,10 @@ static bool e1000_clean_rx_irq_ps(struct
 		cleaned = 1;
 		cleaned_count++;
 		dma_unmap_single(&pdev->dev, buffer_info->dma,
-				 adapter->rx_ps_bsize0,
-				 DMA_FROM_DEVICE);
+				 adapter->rx_ps_bsize0, DMA_FROM_DEVICE);
 		buffer_info->dma = 0;
 
-		/* see !EOP comment in other rx routine */
+		/* see !EOP comment in other Rx routine */
 		if (!(staterr & E1000_RXD_STAT_EOP))
 			adapter->flags2 |= FLAG2_IS_DISCARDING;
 
@@ -1325,7 +1333,7 @@ static bool e1000_clean_jumbo_rx_irq(str
 				goto next_desc;
 		}
 
-#define rxtop rx_ring->rx_skb_top
+#define rxtop (rx_ring->rx_skb_top)
 		if (!(status & E1000_RXD_STAT_EOP)) {
 			/* this descriptor is only the beginning (or middle) */
 			if (!rxtop) {
@@ -1501,6 +1509,9 @@ static void e1000e_downshift_workaround(
 	struct e1000_adapter *adapter = container_of(work,
 					struct e1000_adapter, downshift_task);
 
+	if (test_bit(__E1000_DOWN, &adapter->state))
+		return;
+
 	e1000e_gig_downshift_workaround_ich8lan(&adapter->hw);
 }
 
@@ -1806,9 +1817,8 @@ void e1000e_set_interrupt_capability(str
 				err = pci_enable_msix(adapter->pdev,
 						      adapter->msix_entries,
 						      adapter->num_vectors);
-				if (err == 0) {
+				if (err == 0)
 					return;
-				}
 			}
 			/* MSI-X failed, so fall through and try MSI */
 			e_err("Failed to initialize MSI-X interrupts.  "
@@ -1981,15 +1991,15 @@ static void e1000_irq_enable(struct e100
 }
 
 /**
- * e1000_get_hw_control - get control of the h/w from f/w
+ * e1000e_get_hw_control - get control of the h/w from f/w
  * @adapter: address of board private structure
  *
- * e1000_get_hw_control sets {CTRL_EXT|SWSM}:DRV_LOAD bit.
+ * e1000e_get_hw_control sets {CTRL_EXT|SWSM}:DRV_LOAD bit.
  * For ASF and Pass Through versions of f/w this means that
  * the driver is loaded. For AMT version (only with 82573)
  * of the f/w this means that the network i/f is open.
  **/
-static void e1000_get_hw_control(struct e1000_adapter *adapter)
+void e1000e_get_hw_control(struct e1000_adapter *adapter)
 {
 	struct e1000_hw *hw = &adapter->hw;
 	u32 ctrl_ext;
@@ -2006,16 +2016,16 @@ static void e1000_get_hw_control(struct
 }
 
 /**
- * e1000_release_hw_control - release control of the h/w to f/w
+ * e1000e_release_hw_control - release control of the h/w to f/w
  * @adapter: address of board private structure
  *
- * e1000_release_hw_control resets {CTRL_EXT|SWSM}:DRV_LOAD bit.
+ * e1000e_release_hw_control resets {CTRL_EXT|SWSM}:DRV_LOAD bit.
  * For ASF and Pass Through versions of f/w this means that the
  * driver is no longer loaded. For AMT version (only with 82573) i
  * of the f/w this means that the network i/f is closed.
  *
  **/
-static void e1000_release_hw_control(struct e1000_adapter *adapter)
+void e1000e_release_hw_control(struct e1000_adapter *adapter)
 {
 	struct e1000_hw *hw = &adapter->hw;
 	u32 ctrl_ext;
@@ -2059,10 +2069,9 @@ int e1000e_setup_tx_resources(struct e10
 	int err = -ENOMEM, size;
 
 	size = sizeof(struct e1000_buffer) * tx_ring->count;
-	tx_ring->buffer_info = vmalloc(size);
+	tx_ring->buffer_info = vzalloc(size);
 	if (!tx_ring->buffer_info)
 		goto err;
-	memset(tx_ring->buffer_info, 0, size);
 
 	/* round up to nearest 4K */
 	tx_ring->size = tx_ring->count * sizeof(struct e1000_tx_desc);
@@ -2095,10 +2104,9 @@ int e1000e_setup_rx_resources(struct e10
 	int i, size, desc_len, err = -ENOMEM;
 
 	size = sizeof(struct e1000_buffer) * rx_ring->count;
-	rx_ring->buffer_info = vmalloc(size);
+	rx_ring->buffer_info = vzalloc(size);
 	if (!rx_ring->buffer_info)
 		goto err;
-	memset(rx_ring->buffer_info, 0, size);
 
 	for (i = 0; i < rx_ring->count; i++) {
 		buffer_info = &rx_ring->buffer_info[i];
@@ -2132,7 +2140,7 @@ err_pages:
 	}
 err:
 	vfree(rx_ring->buffer_info);
-	e_err("Unable to allocate memory for the transmit descriptor ring\n");
+	e_err("Unable to allocate memory for the receive descriptor ring\n");
 	return err;
 }
 
@@ -2200,9 +2208,8 @@ void e1000e_free_rx_resources(struct e10
 
 	e1000_clean_rx_ring(adapter);
 
-	for (i = 0; i < rx_ring->count; i++) {
+	for (i = 0; i < rx_ring->count; i++)
 		kfree(rx_ring->buffer_info[i].ps_pages);
-	}
 
 	vfree(rx_ring->buffer_info);
 	rx_ring->buffer_info = NULL;
@@ -2242,20 +2249,18 @@ static unsigned int e1000_update_itr(str
 		/* handle TSO and jumbo frames */
 		if (bytes/packets > 8000)
 			retval = bulk_latency;
-		else if ((packets < 5) && (bytes > 512)) {
+		else if ((packets < 5) && (bytes > 512))
 			retval = low_latency;
-		}
 		break;
 	case low_latency:  /* 50 usec aka 20000 ints/s */
 		if (bytes > 10000) {
 			/* this if handles the TSO accounting */
-			if (bytes/packets > 8000) {
+			if (bytes/packets > 8000)
 				retval = bulk_latency;
-			} else if ((packets < 10) || ((bytes/packets) > 1200)) {
+			else if ((packets < 10) || ((bytes/packets) > 1200))
 				retval = bulk_latency;
-			} else if ((packets > 35)) {
+			else if ((packets > 35))
 				retval = lowest_latency;
-			}
 		} else if (bytes/packets > 2000) {
 			retval = bulk_latency;
 		} else if (packets <= 2 && bytes < 512) {
@@ -2264,9 +2269,8 @@ static unsigned int e1000_update_itr(str
 		break;
 	case bulk_latency: /* 250 usec aka 4000 ints/s */
 		if (bytes > 25000) {
-			if (packets > 35) {
+			if (packets > 35)
 				retval = low_latency;
-			}
 		} else if (bytes < 6000) {
 			retval = low_latency;
 		}
@@ -2452,7 +2456,7 @@ static void e1000_vlan_rx_kill_vid(struc
 	     E1000_MNG_DHCP_COOKIE_STATUS_VLAN) &&
 	    (vid == adapter->mng_vlan_id)) {
 		/* release control to f/w */
-		e1000_release_hw_control(adapter);
+		e1000e_release_hw_control(adapter);
 		return;
 	}
 
@@ -2617,7 +2621,7 @@ static void e1000_init_manageability_pt(
 }
 
 /**
- * e1000_configure_tx - Configure 8254x Transmit Unit after Reset
+ * e1000_configure_tx - Configure Transmit Unit after Reset
  * @adapter: board private structure
  *
  * Configure the Tx unit of the MAC after a reset.
@@ -2670,7 +2674,7 @@ static void e1000_configure_tx(struct e1
 		 * hthresh = 1 ==> prefetch when one or more available
 		 * pthresh = 0x1f ==> prefetch if internal cache 31 or less
 		 * BEWARE: this seems to work but should be considered first if
-		 * there are tx hangs or other tx related bugs
+		 * there are Tx hangs or other Tx related bugs
 		 */
 		txdctl |= E1000_TXDCTL_DMA_BURST_ENABLE;
 		ew32(TXDCTL(0), txdctl);
@@ -2741,6 +2745,9 @@ static void e1000_setup_rctl(struct e100
 			ret_val = e1000_lv_jumbo_workaround_ich8lan(hw, true);
 		else
 			ret_val = e1000_lv_jumbo_workaround_ich8lan(hw, false);
+
+		if (ret_val)
+			e_dbg("failed to enable jumbo frame workaround mode\n");
 	}
 
 	/* Program MC offset vector base */
@@ -2881,7 +2888,7 @@ static void e1000_configure_rx(struct e1
 	if (adapter->rx_ps_pages) {
 		/* this is a 32 byte descriptor */
 		rdlen = rx_ring->count *
-			sizeof(union e1000_rx_desc_packet_split);
+		    sizeof(union e1000_rx_desc_packet_split);
 		adapter->clean_rx = e1000_clean_rx_irq_ps;
 		adapter->alloc_rx_buf = e1000_alloc_rx_buffers_ps;
 	} else if (adapter->netdev->mtu > ETH_FRAME_LEN + ETH_FCS_LEN) {
@@ -2904,7 +2911,7 @@ static void e1000_configure_rx(struct e1
 		/*
 		 * set the writeback threshold (only takes effect if the RDTR
 		 * is set). set GRAN=1 and write back up to 0x4 worth, and
-		 * enable prefetching of 0x20 rx descriptors
+		 * enable prefetching of 0x20 Rx descriptors
 		 * granularity = 01
 		 * wthresh = 04,
 		 * hthresh = 04,
@@ -2985,12 +2992,10 @@ static void e1000_configure_rx(struct e1
 			 * excessive C-state transition latencies result in
 			 * dropped transactions.
 			 */
-			pm_qos_update_request(
-				&adapter->netdev->pm_qos_req, 55);
+			pm_qos_update_request(&adapter->netdev->pm_qos_req, 55);
 		} else {
-			pm_qos_update_request(
-				&adapter->netdev->pm_qos_req,
-				PM_QOS_DEFAULT_VALUE);
+			pm_qos_update_request(&adapter->netdev->pm_qos_req,
+					      PM_QOS_DEFAULT_VALUE);
 		}
 	}
 
@@ -3156,7 +3161,7 @@ void e1000e_reset(struct e1000_adapter *
 		/* lower 16 bits has Rx packet buffer allocation size in KB */
 		pba &= 0xffff;
 		/*
-		 * the Tx fifo also stores 16 bytes of information about the tx
+		 * the Tx fifo also stores 16 bytes of information about the Tx
 		 * but don't include ethernet FCS because hardware appends it
 		 */
 		min_tx_space = (adapter->max_frame_size +
@@ -3179,7 +3184,7 @@ void e1000e_reset(struct e1000_adapter *
 			pba -= min_tx_space - tx_space;
 
 			/*
-			 * if short on Rx space, Rx wins and must trump tx
+			 * if short on Rx space, Rx wins and must trump Tx
 			 * adjustment or use Early Receive if available
 			 */
 			if ((pba < min_rx_space) &&
@@ -3191,7 +3196,6 @@ void e1000e_reset(struct e1000_adapter *
 		ew32(PBA, pba);
 	}
 
-
 	/*
 	 * flow control settings
 	 *
@@ -3279,7 +3283,7 @@ void e1000e_reset(struct e1000_adapter *
 	 * that the network interface is in control
 	 */
 	if (adapter->flags & FLAG_HAS_AMT)
-		e1000_get_hw_control(adapter);
+		e1000e_get_hw_control(adapter);
 
 	ew32(WUC, 0);
 
@@ -3292,6 +3296,13 @@ void e1000e_reset(struct e1000_adapter *
 	ew32(VET, ETH_P_8021Q);
 
 	e1000e_reset_adaptive(hw);
+
+	if (!netif_running(adapter->netdev) &&
+	    !test_bit(__E1000_TESTING, &adapter->state)) {
+		e1000_power_down_phy(adapter);
+		return;
+	}
+
 	e1000_get_phy_info(hw);
 
 	if ((adapter->flags & FLAG_HAS_SMART_POWER_DOWN) &&
@@ -3333,6 +3344,21 @@ int e1000e_up(struct e1000_adapter *adap
 	return 0;
 }
 
+static void e1000e_flush_descriptors(struct e1000_adapter *adapter)
+{
+	struct e1000_hw *hw = &adapter->hw;
+
+	if (!(adapter->flags2 & FLAG2_DMA_BURST))
+		return;
+
+	/* flush pending descriptor writebacks to memory */
+	ew32(TIDV, adapter->tx_int_delay | E1000_TIDV_FPD);
+	ew32(RDTR, adapter->rx_int_delay | E1000_RDTR_FPD);
+
+	/* execute the writes immediately */
+	e1e_flush();
+}
+
 void e1000e_down(struct e1000_adapter *adapter)
 {
 	struct net_device *netdev = adapter->netdev;
@@ -3372,6 +3398,9 @@ void e1000e_down(struct e1000_adapter *a
 
 	if (!pci_channel_offline(adapter->pdev))
 		e1000e_reset(adapter);
+
+	e1000e_flush_descriptors(adapter);
+
 	e1000_clean_tx_ring(adapter);
 	e1000_clean_rx_ring(adapter);
 
@@ -3577,7 +3606,7 @@ static int e1000_open(struct net_device
 	 * interface is now open and reset the part to a known state.
 	 */
 	if (adapter->flags & FLAG_HAS_AMT) {
-		e1000_get_hw_control(adapter);
+		e1000e_get_hw_control(adapter);
 		e1000e_reset(adapter);
 	}
 
@@ -3641,7 +3670,7 @@ static int e1000_open(struct net_device
 	return 0;
 
 err_req_irq:
-	e1000_release_hw_control(adapter);
+	e1000e_release_hw_control(adapter);
 	e1000_power_down_phy(adapter);
 	e1000e_free_rx_resources(adapter);
 err_setup_rx:
@@ -3696,8 +3725,9 @@ static int e1000_close(struct net_device
 	 * If AMT is enabled, let the firmware know that the network
 	 * interface is now closed
 	 */
-	if (adapter->flags & FLAG_HAS_AMT)
-		e1000_release_hw_control(adapter);
+	if ((adapter->flags & FLAG_HAS_AMT) &&
+	    !test_bit(__E1000_TESTING, &adapter->state))
+		e1000e_release_hw_control(adapter);
 
 	if ((adapter->flags & FLAG_HAS_ERT) ||
 	    (adapter->hw.mac.type == e1000_pch2lan))
@@ -3759,6 +3789,10 @@ static void e1000e_update_phy_task(struc
 {
 	struct e1000_adapter *adapter = container_of(work,
 					struct e1000_adapter, update_phy_task);
+
+	if (test_bit(__E1000_DOWN, &adapter->state))
+		return;
+
 	e1000_get_phy_info(&adapter->hw);
 }
 
@@ -3769,6 +3803,10 @@ static void e1000e_update_phy_task(struc
 static void e1000_update_phy_info(unsigned long data)
 {
 	struct e1000_adapter *adapter = (struct e1000_adapter *) data;
+
+	if (test_bit(__E1000_DOWN, &adapter->state))
+		return;
+
 	schedule_work(&adapter->update_phy_task);
 }
 
@@ -4036,11 +4074,11 @@ static void e1000_print_link_info(struct
 	       adapter->netdev->name,
 	       adapter->link_speed,
 	       (adapter->link_duplex == FULL_DUPLEX) ?
-	                        "Full Duplex" : "Half Duplex",
+	       "Full Duplex" : "Half Duplex",
 	       ((ctrl & E1000_CTRL_TFCE) && (ctrl & E1000_CTRL_RFCE)) ?
-	                        "RX/TX" :
-	       ((ctrl & E1000_CTRL_RFCE) ? "RX" :
-	       ((ctrl & E1000_CTRL_TFCE) ? "TX" : "None" )));
+	       "Rx/Tx" :
+	       ((ctrl & E1000_CTRL_RFCE) ? "Rx" :
+		((ctrl & E1000_CTRL_TFCE) ? "Tx" : "None")));
 }
 
 static bool e1000e_has_link(struct e1000_adapter *adapter)
@@ -4143,6 +4181,9 @@ static void e1000_watchdog_task(struct w
 	u32 link, tctl;
 	int tx_pending = 0;
 
+	if (test_bit(__E1000_DOWN, &adapter->state))
+		return;
+
 	link = e1000e_has_link(adapter);
 	if ((netif_carrier_ok(netdev)) && link) {
 		/* Cancel scheduled suspend requests. */
@@ -4303,7 +4344,6 @@ link_up:
 			 * to get done, so reset controller to flush Tx.
 			 * (Do the reset outside of interrupt context).
 			 */
-			adapter->tx_timeout_count++;
 			schedule_work(&adapter->reset_task);
 			/* return immediately since reset is imminent */
 			return;
@@ -4332,19 +4372,12 @@ link_up:
 	else
 		ew32(ICS, E1000_ICS_RXDMT0);
 
+	/* flush pending descriptors to memory before detecting Tx hang */
+	e1000e_flush_descriptors(adapter);
+
 	/* Force detection of hung controller every watchdog period */
 	adapter->detect_tx_hung = 1;
 
-	/* flush partial descriptors to memory before detecting tx hang */
-	if (adapter->flags2 & FLAG2_DMA_BURST) {
-		ew32(TIDV, adapter->tx_int_delay | E1000_TIDV_FPD);
-		ew32(RDTR, adapter->rx_int_delay | E1000_RDTR_FPD);
-		/*
-		 * no need to flush the writes because the timeout code does
-		 * an er32 first thing
-		 */
-	}
-
 	/*
 	 * With 82571 controllers, LAA may be overwritten due to controller
 	 * reset from the other port. Set the appropriate LAA in RAR[0]
@@ -4475,7 +4508,7 @@ static bool e1000_tx_csum(struct e1000_a
 		break;
 	}
 
-	css = skb_transport_offset(skb);
+	css = skb_checksum_start_offset(skb);
 
 	i = tx_ring->next_to_use;
 	buffer_info = &tx_ring->buffer_info[i];
@@ -4526,7 +4559,7 @@ static int e1000_tx_map(struct e1000_ada
 		buffer_info->next_to_watch = i;
 		buffer_info->dma = dma_map_single(&pdev->dev,
 						  skb->data + offset,
-						  size,	DMA_TO_DEVICE);
+						  size, DMA_TO_DEVICE);
 		buffer_info->mapped_as_page = false;
 		if (dma_mapping_error(&pdev->dev, buffer_info->dma))
 			goto dma_error;
@@ -4573,7 +4606,7 @@ static int e1000_tx_map(struct e1000_ada
 		}
 	}
 
-	segs = skb_shinfo(skb)->gso_segs ?: 1;
+	segs = skb_shinfo(skb)->gso_segs ? : 1;
 	/* multiply data chunks by size of headers */
 	bytecount = ((segs - 1) * skb_headlen(skb)) + skb->len;
 
@@ -4585,17 +4618,17 @@ static int e1000_tx_map(struct e1000_ada
 	return count;
 
 dma_error:
-	dev_err(&pdev->dev, "TX DMA map failed\n");
+	dev_err(&pdev->dev, "Tx DMA map failed\n");
 	buffer_info->dma = 0;
 	if (count)
 		count--;
 
 	while (count--) {
-		if (i==0)
+		if (i == 0)
 			i += tx_ring->count;
 		i--;
 		buffer_info = &tx_ring->buffer_info[i];
-		e1000_put_txbuf(adapter, buffer_info);;
+		e1000_put_txbuf(adapter, buffer_info);
 	}
 
 	return 0;
@@ -4631,7 +4664,7 @@ static void e1000_tx_queue(struct e1000_
 
 	i = tx_ring->next_to_use;
 
-	while (count--) {
+	do {
 		buffer_info = &tx_ring->buffer_info[i];
 		tx_desc = E1000_TX_DESC(*tx_ring, i);
 		tx_desc->buffer_addr = cpu_to_le64(buffer_info->dma);
@@ -4642,7 +4675,7 @@ static void e1000_tx_queue(struct e1000_
 		i++;
 		if (i == tx_ring->count)
 			i = 0;
-	}
+	} while (--count > 0);
 
 	tx_desc->lower.data |= cpu_to_le32(adapter->txd_cmd);
 
@@ -4882,6 +4915,10 @@ static void e1000_reset_task(struct work
 	struct e1000_adapter *adapter;
 	adapter = container_of(work, struct e1000_adapter, reset_task);
 
+	/* don't run the task if already down */
+	if (test_bit(__E1000_DOWN, &adapter->state))
+		return;
+
 	if (!((adapter->flags & FLAG_RX_NEEDS_RESTART) &&
 	      (adapter->flags & FLAG_RX_RESTART_NOW))) {
 		e1000e_dump(adapter);
@@ -5216,7 +5253,7 @@ static int __e1000_shutdown(struct pci_d
 	 * Release control of h/w to f/w.  If f/w is AMT enabled, this
 	 * would have already happened in close and is redundant.
 	 */
-	e1000_release_hw_control(adapter);
+	e1000e_release_hw_control(adapter);
 
 	pci_disable_device(pdev);
 
@@ -5373,7 +5410,7 @@ static int __e1000_resume(struct pci_dev
 	 * under the control of the driver.
 	 */
 	if (!(adapter->flags & FLAG_HAS_AMT))
-		e1000_get_hw_control(adapter);
+		e1000e_get_hw_control(adapter);
 
 	return 0;
 }
@@ -5465,6 +5502,36 @@ static void e1000_shutdown(struct pci_de
 }
 
 #ifdef CONFIG_NET_POLL_CONTROLLER
+
+static irqreturn_t e1000_intr_msix(int irq, void *data)
+{
+	struct net_device *netdev = data;
+	struct e1000_adapter *adapter = netdev_priv(netdev);
+	int vector, msix_irq;
+
+	if (adapter->msix_entries) {
+		vector = 0;
+		msix_irq = adapter->msix_entries[vector].vector;
+		disable_irq(msix_irq);
+		e1000_intr_msix_rx(msix_irq, netdev);
+		enable_irq(msix_irq);
+
+		vector++;
+		msix_irq = adapter->msix_entries[vector].vector;
+		disable_irq(msix_irq);
+		e1000_intr_msix_tx(msix_irq, netdev);
+		enable_irq(msix_irq);
+
+		vector++;
+		msix_irq = adapter->msix_entries[vector].vector;
+		disable_irq(msix_irq);
+		e1000_msix_other(msix_irq, netdev);
+		enable_irq(msix_irq);
+	}
+
+	return IRQ_HANDLED;
+}
+
 /*
  * Polling 'interrupt' - used by things like netconsole to send skbs
  * without having to re-enable interrupts. It's not called while
@@ -5474,10 +5541,21 @@ static void e1000_netpoll(struct net_dev
 {
 	struct e1000_adapter *adapter = netdev_priv(netdev);
 
-	disable_irq(adapter->pdev->irq);
-	e1000_intr(adapter->pdev->irq, netdev);
-
-	enable_irq(adapter->pdev->irq);
+	switch (adapter->int_mode) {
+	case E1000E_INT_MODE_MSIX:
+		e1000_intr_msix(adapter->pdev->irq, netdev);
+		break;
+	case E1000E_INT_MODE_MSI:
+		disable_irq(adapter->pdev->irq);
+		e1000_intr_msi(adapter->pdev->irq, netdev);
+		enable_irq(adapter->pdev->irq);
+		break;
+	default: /* E1000E_INT_MODE_LEGACY */
+		disable_irq(adapter->pdev->irq);
+		e1000_intr(adapter->pdev->irq, netdev);
+		enable_irq(adapter->pdev->irq);
+		break;
+	}
 }
 #endif
 
@@ -5579,7 +5657,7 @@ static void e1000_io_resume(struct pci_d
 	 * under the control of the driver.
 	 */
 	if (!(adapter->flags & FLAG_HAS_AMT))
-		e1000_get_hw_control(adapter);
+		e1000e_get_hw_control(adapter);
 
 }
 
@@ -5587,7 +5665,8 @@ static void e1000_print_device_info(stru
 {
 	struct e1000_hw *hw = &adapter->hw;
 	struct net_device *netdev = adapter->netdev;
-	u32 pba_num;
+	u32 ret_val;
+	u8 pba_str[E1000_PBANUM_LENGTH];
 
 	/* print bus type/speed/width info */
 	e_info("(PCI Express:2.5GB/s:%s) %pM\n",
@@ -5598,9 +5677,12 @@ static void e1000_print_device_info(stru
 	       netdev->dev_addr);
 	e_info("Intel(R) PRO/%s Network Connection\n",
 	       (hw->phy.type == e1000_phy_ife) ? "10/100" : "1000");
-	e1000e_read_pba_num(hw, &pba_num);
-	e_info("MAC: %d, PHY: %d, PBA No: %06x-%03x\n",
-	       hw->mac.type, hw->phy.type, (pba_num >> 8), (pba_num & 0xff));
+	ret_val = e1000_read_pba_string_generic(hw, pba_str,
+						E1000_PBANUM_LENGTH);
+	if (ret_val)
+		strncpy((char *)pba_str, "Unknown", sizeof(pba_str) - 1);
+	e_info("MAC: %d, PHY: %d, PBA No: %s\n",
+	       hw->mac.type, hw->phy.type, pba_str);
 }
 
 static void e1000_eeprom_checks(struct e1000_adapter *adapter)
@@ -5864,6 +5946,7 @@ static int __devinit e1000_probe(struct
 	INIT_WORK(&adapter->downshift_task, e1000e_downshift_workaround);
 	INIT_WORK(&adapter->update_phy_task, e1000e_update_phy_task);
 	INIT_WORK(&adapter->print_hang_task, e1000_print_hw_hang);
+	INIT_WORK(&adapter->led_blink_task, e1000e_led_blink_task);
 
 	/* Initialize link parameters. User can change them with ethtool */
 	adapter->hw.mac.autoneg = 1;
@@ -5884,7 +5967,8 @@ static int __devinit e1000_probe(struct
 		/* APME bit in EEPROM is mapped to WUC.APME */
 		eeprom_data = er32(WUC);
 		eeprom_apme_mask = E1000_WUC_APME;
-		if (eeprom_data & E1000_WUC_PHY_WAKE)
+		if ((hw->mac.type > e1000_ich10lan) &&
+		    (eeprom_data & E1000_WUC_PHY_WAKE))
 			adapter->flags2 |= FLAG2_HAS_PHY_WAKEUP;
 	} else if (adapter->flags & FLAG_APME_IN_CTRL3) {
 		if (adapter->flags & FLAG_APME_CHECK_PORT_B &&
@@ -5924,9 +6008,9 @@ static int __devinit e1000_probe(struct
 	 * under the control of the driver.
 	 */
 	if (!(adapter->flags & FLAG_HAS_AMT))
-		e1000_get_hw_control(adapter);
+		e1000e_get_hw_control(adapter);
 
-	strcpy(netdev->name, "eth%d");
+	strncpy(netdev->name, "eth%d", sizeof(netdev->name) - 1);
 	err = register_netdev(netdev);
 	if (err)
 		goto err_register;
@@ -5943,12 +6027,11 @@ static int __devinit e1000_probe(struct
 
 err_register:
 	if (!(adapter->flags & FLAG_HAS_AMT))
-		e1000_release_hw_control(adapter);
+		e1000e_release_hw_control(adapter);
 err_eeprom:
 	if (!e1000_check_reset_block(&adapter->hw))
 		e1000_phy_hw_reset(&adapter->hw);
 err_hw_init:
-
 	kfree(adapter->tx_ring);
 	kfree(adapter->rx_ring);
 err_sw_init:
@@ -5984,8 +6067,8 @@ static void __devexit e1000_remove(struc
 	bool down = test_bit(__E1000_DOWN, &adapter->state);
 
 	/*
-	 * flush_scheduled work may reschedule our watchdog task, so
-	 * explicitly disable watchdog tasks from being rescheduled
+	 * The timers may be rescheduled, so explicitly disable them
+	 * from being rescheduled.
 	 */
 	if (!down)
 		set_bit(__E1000_DOWN, &adapter->state);
@@ -5996,8 +6079,8 @@ static void __devexit e1000_remove(struc
 	cancel_work_sync(&adapter->watchdog_task);
 	cancel_work_sync(&adapter->downshift_task);
 	cancel_work_sync(&adapter->update_phy_task);
+	cancel_work_sync(&adapter->led_blink_task);
 	cancel_work_sync(&adapter->print_hang_task);
-	flush_scheduled_work();
 
 	if (!(netdev->flags & IFF_UP))
 		e1000_power_down_phy(adapter);
@@ -6014,7 +6097,7 @@ static void __devexit e1000_remove(struc
 	 * Release control of h/w to f/w.  If f/w is AMT enabled, this
 	 * would have already happened in close and is redundant.
 	 */
-	e1000_release_hw_control(adapter);
+	e1000e_release_hw_control(adapter);
 
 	e1000e_reset_interrupt_capability(adapter);
 	kfree(adapter->tx_ring);
@@ -6145,7 +6228,7 @@ static int __init e1000_init_module(void
 	int ret;
 	pr_info("Intel(R) PRO/1000 Network Driver - %s\n",
 		e1000e_driver_version);
-	pr_info("Copyright (c) 1999 - 2010 Intel Corporation.\n");
+	pr_info("Copyright(c) 1999 - 2011 Intel Corporation.\n");
 	ret = pci_register_driver(&e1000_driver);
 
 	return ret;
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/e1000e/param.c linux-libre-2.6.38-gnu1/drivers/net/e1000e/param.c
--- linux-libre-2.6.37-gnu1/drivers/net/e1000e/param.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/e1000e/param.c	2011-03-14 21:20:32.000000000 -0400
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel PRO/1000 Linux driver
-  Copyright(c) 1999 - 2010 Intel Corporation.
+  Copyright(c) 1999 - 2011 Intel 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,
@@ -62,10 +62,9 @@ MODULE_PARM_DESC(copybreak,
 	module_param_array_named(X, X, int, &num_##X, 0);	\
 	MODULE_PARM_DESC(X, desc);
 
-
 /*
  * Transmit Interrupt Delay in units of 1.024 microseconds
- * Tx interrupt delay needs to typically be set to something non zero
+ * Tx interrupt delay needs to typically be set to something non-zero
  *
  * Valid Range: 0-65535
  */
@@ -112,6 +111,7 @@ E1000_PARAM(InterruptThrottleRate, "Inte
 #define DEFAULT_ITR 3
 #define MAX_ITR 100000
 #define MIN_ITR 100
+
 /* IntMode (Interrupt Mode)
  *
  * Valid Range: 0 - 2
@@ -421,7 +421,7 @@ void __devinit e1000e_check_options(stru
 		static const struct e1000_option opt = {
 			.type = enable_option,
 			.name = "CRC Stripping",
-			.err  = "defaulting to enabled",
+			.err  = "defaulting to Enabled",
 			.def  = OPTION_ENABLED
 		};
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/e1000e/phy.c linux-libre-2.6.38-gnu1/drivers/net/e1000e/phy.c
--- linux-libre-2.6.37-gnu1/drivers/net/e1000e/phy.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/e1000e/phy.c	2011-03-14 21:20:32.000000000 -0400
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel PRO/1000 Linux driver
-  Copyright(c) 1999 - 2010 Intel Corporation.
+  Copyright(c) 1999 - 2011 Intel 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,
@@ -42,20 +42,20 @@ static s32 e1000_access_phy_debug_regs_h
                                           u16 *data, bool read);
 
 /* Cable length tables */
-static const u16 e1000_m88_cable_length_table[] =
-	{ 0, 50, 80, 110, 140, 140, E1000_CABLE_LENGTH_UNDEFINED };
+static const u16 e1000_m88_cable_length_table[] = {
+	0, 50, 80, 110, 140, 140, E1000_CABLE_LENGTH_UNDEFINED };
 #define M88E1000_CABLE_LENGTH_TABLE_SIZE \
 		ARRAY_SIZE(e1000_m88_cable_length_table)
 
-static const u16 e1000_igp_2_cable_length_table[] =
-	{ 0, 0, 0, 0, 0, 0, 0, 0, 3, 5, 8, 11, 13, 16, 18, 21, 0, 0, 0, 3,
-	  6, 10, 13, 16, 19, 23, 26, 29, 32, 35, 38, 41, 6, 10, 14, 18, 22,
-	  26, 30, 33, 37, 41, 44, 48, 51, 54, 58, 61, 21, 26, 31, 35, 40,
-	  44, 49, 53, 57, 61, 65, 68, 72, 75, 79, 82, 40, 45, 51, 56, 61,
-	  66, 70, 75, 79, 83, 87, 91, 94, 98, 101, 104, 60, 66, 72, 77, 82,
-	  87, 92, 96, 100, 104, 108, 111, 114, 117, 119, 121, 83, 89, 95,
-	  100, 105, 109, 113, 116, 119, 122, 124, 104, 109, 114, 118, 121,
-	  124};
+static const u16 e1000_igp_2_cable_length_table[] = {
+	0, 0, 0, 0, 0, 0, 0, 0, 3, 5, 8, 11, 13, 16, 18, 21, 0, 0, 0, 3,
+	6, 10, 13, 16, 19, 23, 26, 29, 32, 35, 38, 41, 6, 10, 14, 18, 22,
+	26, 30, 33, 37, 41, 44, 48, 51, 54, 58, 61, 21, 26, 31, 35, 40,
+	44, 49, 53, 57, 61, 65, 68, 72, 75, 79, 82, 40, 45, 51, 56, 61,
+	66, 70, 75, 79, 83, 87, 91, 94, 98, 101, 104, 60, 66, 72, 77, 82,
+	87, 92, 96, 100, 104, 108, 111, 114, 117, 119, 121, 83, 89, 95,
+	100, 105, 109, 113, 116, 119, 122, 124, 104, 109, 114, 118, 121,
+	124};
 #define IGP02E1000_CABLE_LENGTH_TABLE_SIZE \
 		ARRAY_SIZE(e1000_igp_2_cable_length_table)
 
@@ -226,6 +226,13 @@ s32 e1000e_read_phy_reg_mdic(struct e100
 	}
 	*data = (u16) mdic;
 
+	/*
+	 * Allow some time after each MDIC transaction to avoid
+	 * reading duplicate data in the next MDIC transaction.
+	 */
+	if (hw->mac.type == e1000_pch2lan)
+		udelay(100);
+
 	return 0;
 }
 
@@ -279,6 +286,13 @@ s32 e1000e_write_phy_reg_mdic(struct e10
 		return -E1000_ERR_PHY;
 	}
 
+	/*
+	 * Allow some time after each MDIC transaction to avoid
+	 * reading duplicate data in the next MDIC transaction.
+	 */
+	if (hw->mac.type == e1000_pch2lan)
+		udelay(100);
+
 	return 0;
 }
 
@@ -623,12 +637,11 @@ s32 e1000e_write_kmrn_reg_locked(struct
  **/
 s32 e1000_copper_link_setup_82577(struct e1000_hw *hw)
 {
-	struct e1000_phy_info *phy = &hw->phy;
 	s32 ret_val;
 	u16 phy_data;
 
-	/* Enable CRS on TX. This must be set for half-duplex operation. */
-	ret_val = phy->ops.read_reg(hw, I82577_CFG_REG, &phy_data);
+	/* Enable CRS on Tx. This must be set for half-duplex operation. */
+	ret_val = e1e_rphy(hw, I82577_CFG_REG, &phy_data);
 	if (ret_val)
 		goto out;
 
@@ -637,7 +650,7 @@ s32 e1000_copper_link_setup_82577(struct
 	/* Enable downshift */
 	phy_data |= I82577_CFG_ENABLE_DOWNSHIFT;
 
-	ret_val = phy->ops.write_reg(hw, I82577_CFG_REG, phy_data);
+	ret_val = e1e_wphy(hw, I82577_CFG_REG, phy_data);
 
 out:
 	return ret_val;
@@ -760,16 +773,14 @@ s32 e1000e_copper_link_setup_m88(struct
 	}
 
 	if (phy->type == e1000_phy_82578) {
-		ret_val = phy->ops.read_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL,
-		                            &phy_data);
+		ret_val = e1e_rphy(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_data);
 		if (ret_val)
 			return ret_val;
 
 		/* 82578 PHY - set the downshift count to 1x. */
 		phy_data |= I82578_EPSCR_DOWNSHIFT_ENABLE;
 		phy_data &= ~I82578_EPSCR_DOWNSHIFT_COUNTER_MASK;
-		ret_val = phy->ops.write_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL,
-		                             phy_data);
+		ret_val = e1e_wphy(hw, M88E1000_EXT_PHY_SPEC_CTRL, phy_data);
 		if (ret_val)
 			return ret_val;
 	}
@@ -1043,9 +1054,8 @@ static s32 e1000_phy_setup_autoneg(struc
 
 	e_dbg("Auto-Neg Advertising %x\n", mii_autoneg_adv_reg);
 
-	if (phy->autoneg_mask & ADVERTISE_1000_FULL) {
+	if (phy->autoneg_mask & ADVERTISE_1000_FULL)
 		ret_val = e1e_wphy(hw, PHY_1000T_CTRL, mii_1000t_ctrl_reg);
-	}
 
 	return ret_val;
 }
@@ -1306,9 +1316,8 @@ s32 e1000e_phy_force_speed_duplex_m88(st
 				 * We didn't get link.
 				 * Reset the DSP and cross our fingers.
 				 */
-				ret_val = e1e_wphy(hw,
-						M88E1000_PHY_PAGE_SELECT,
-						0x001d);
+				ret_val = e1e_wphy(hw, M88E1000_PHY_PAGE_SELECT,
+						   0x001d);
 				if (ret_val)
 					return ret_val;
 				ret_val = e1000e_phy_reset_dsp(hw);
@@ -1840,11 +1849,12 @@ s32 e1000e_get_cable_length_igp_2(struct
 	u16 phy_data, i, agc_value = 0;
 	u16 cur_agc_index, max_agc_index = 0;
 	u16 min_agc_index = IGP02E1000_CABLE_LENGTH_TABLE_SIZE - 1;
-	u16 agc_reg_array[IGP02E1000_PHY_CHANNEL_NUM] =
-							 {IGP02E1000_PHY_AGC_A,
-							  IGP02E1000_PHY_AGC_B,
-							  IGP02E1000_PHY_AGC_C,
-							  IGP02E1000_PHY_AGC_D};
+	static const u16 agc_reg_array[IGP02E1000_PHY_CHANNEL_NUM] = {
+	       IGP02E1000_PHY_AGC_A,
+	       IGP02E1000_PHY_AGC_B,
+	       IGP02E1000_PHY_AGC_C,
+	       IGP02E1000_PHY_AGC_D
+	};
 
 	/* Read the AGC registers for all channels */
 	for (i = 0; i < IGP02E1000_PHY_CHANNEL_NUM; i++) {
@@ -2976,7 +2986,7 @@ s32 e1000_write_phy_reg_hv_locked(struct
 }
 
 /**
- *  e1000_get_phy_addr_for_hv_page - Get PHY adrress based on page
+ *  e1000_get_phy_addr_for_hv_page - Get PHY address based on page
  *  @page: page to be accessed
  **/
 static u32 e1000_get_phy_addr_for_hv_page(u32 page)
@@ -3057,12 +3067,12 @@ s32 e1000_link_stall_workaround_hv(struc
 		goto out;
 
 	/* Do not apply workaround if in PHY loopback bit 14 set */
-	hw->phy.ops.read_reg(hw, PHY_CONTROL, &data);
+	e1e_rphy(hw, PHY_CONTROL, &data);
 	if (data & PHY_CONTROL_LB)
 		goto out;
 
 	/* check if link is up and at 1Gbps */
-	ret_val = hw->phy.ops.read_reg(hw, BM_CS_STATUS, &data);
+	ret_val = e1e_rphy(hw, BM_CS_STATUS, &data);
 	if (ret_val)
 		goto out;
 
@@ -3078,14 +3088,12 @@ s32 e1000_link_stall_workaround_hv(struc
 	mdelay(200);
 
 	/* flush the packets in the fifo buffer */
-	ret_val = hw->phy.ops.write_reg(hw, HV_MUX_DATA_CTRL,
-	                                HV_MUX_DATA_CTRL_GEN_TO_MAC |
-	                                HV_MUX_DATA_CTRL_FORCE_SPEED);
+	ret_val = e1e_wphy(hw, HV_MUX_DATA_CTRL, HV_MUX_DATA_CTRL_GEN_TO_MAC |
+			   HV_MUX_DATA_CTRL_FORCE_SPEED);
 	if (ret_val)
 		goto out;
 
-	ret_val = hw->phy.ops.write_reg(hw, HV_MUX_DATA_CTRL,
-	                                HV_MUX_DATA_CTRL_GEN_TO_MAC);
+	ret_val = e1e_wphy(hw, HV_MUX_DATA_CTRL, HV_MUX_DATA_CTRL_GEN_TO_MAC);
 
 out:
 	return ret_val;
@@ -3105,7 +3113,7 @@ s32 e1000_check_polarity_82577(struct e1
 	s32 ret_val;
 	u16 data;
 
-	ret_val = phy->ops.read_reg(hw, I82577_PHY_STATUS_2, &data);
+	ret_val = e1e_rphy(hw, I82577_PHY_STATUS_2, &data);
 
 	if (!ret_val)
 		phy->cable_polarity = (data & I82577_PHY_STATUS2_REV_POLARITY)
@@ -3128,13 +3136,13 @@ s32 e1000_phy_force_speed_duplex_82577(s
 	u16 phy_data;
 	bool link;
 
-	ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &phy_data);
+	ret_val = e1e_rphy(hw, PHY_CONTROL, &phy_data);
 	if (ret_val)
 		goto out;
 
 	e1000e_phy_force_speed_duplex_setup(hw, &phy_data);
 
-	ret_val = phy->ops.write_reg(hw, PHY_CONTROL, phy_data);
+	ret_val = e1e_wphy(hw, PHY_CONTROL, phy_data);
 	if (ret_val)
 		goto out;
 
@@ -3198,7 +3206,7 @@ s32 e1000_get_phy_info_82577(struct e100
 	if (ret_val)
 		goto out;
 
-	ret_val = phy->ops.read_reg(hw, I82577_PHY_STATUS_2, &data);
+	ret_val = e1e_rphy(hw, I82577_PHY_STATUS_2, &data);
 	if (ret_val)
 		goto out;
 
@@ -3210,7 +3218,7 @@ s32 e1000_get_phy_info_82577(struct e100
 		if (ret_val)
 			goto out;
 
-		ret_val = phy->ops.read_reg(hw, PHY_1000T_STATUS, &data);
+		ret_val = e1e_rphy(hw, PHY_1000T_STATUS, &data);
 		if (ret_val)
 			goto out;
 
@@ -3244,7 +3252,7 @@ s32 e1000_get_cable_length_82577(struct
 	s32 ret_val;
 	u16 phy_data, length;
 
-	ret_val = phy->ops.read_reg(hw, I82577_PHY_DIAG_STATUS, &phy_data);
+	ret_val = e1e_rphy(hw, I82577_PHY_DIAG_STATUS, &phy_data);
 	if (ret_val)
 		goto out;
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/e2100.c linux-libre-2.6.38-gnu1/drivers/net/e2100.c
--- linux-libre-2.6.37-gnu1/drivers/net/e2100.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/e2100.c	2011-03-14 21:20:32.000000000 -0400
@@ -216,7 +216,7 @@ static int __init e21_probe1(struct net_
 		printk(" %02X", station_addr[i]);
 
 	if (dev->irq < 2) {
-		int irqlist[] = {15, 11, 10, 12, 5, 9, 3, 4};
+		static const int irqlist[] = {15, 11, 10, 12, 5, 9, 3, 4};
 		for (i = 0; i < ARRAY_SIZE(irqlist); i++)
 			if (request_irq (irqlist[i], NULL, 0, "bogus", NULL) != -EBUSY) {
 				dev->irq = irqlist[i];
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/eepro.c linux-libre-2.6.38-gnu1/drivers/net/eepro.c
--- linux-libre-2.6.37-gnu1/drivers/net/eepro.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/eepro.c	2011-03-14 21:20:32.000000000 -0400
@@ -302,7 +302,7 @@ struct eepro_local {
 #define ee_id_eepro10p0 0x10   /* ID for eepro/10+ */
 #define ee_id_eepro10p1 0x31
 
-#define TX_TIMEOUT 40
+#define TX_TIMEOUT ((4*HZ)/10)
 
 /* Index to functions, as function prototypes. */
 
@@ -891,12 +891,13 @@ err:
    there is non-reboot way to recover if something goes wrong.
    */
 
-static char irqrmap[] = {-1,-1,0,1,-1,2,-1,-1,-1,0,3,4,-1,-1,-1,-1};
-static char irqrmap2[] = {-1,-1,4,0,1,2,-1,3,-1,4,5,6,7,-1,-1,-1};
+static const char irqrmap[] = {-1,-1,0,1,-1,2,-1,-1,-1,0,3,4,-1,-1,-1,-1};
+static const char irqrmap2[] = {-1,-1,4,0,1,2,-1,3,-1,4,5,6,7,-1,-1,-1};
 static int	eepro_grab_irq(struct net_device *dev)
 {
-	int irqlist[] = { 3, 4, 5, 7, 9, 10, 11, 12, 0 };
-	int *irqp = irqlist, temp_reg, ioaddr = dev->base_addr;
+	static const int irqlist[] = { 3, 4, 5, 7, 9, 10, 11, 12, 0 };
+	const int *irqp = irqlist;
+	int temp_reg, ioaddr = dev->base_addr;
 
 	eepro_sw2bank1(ioaddr); /* be CAREFUL, BANK 1 now */
 
@@ -1760,7 +1761,7 @@ module_param_array(io, int, NULL, 0);
 module_param_array(irq, int, NULL, 0);
 module_param_array(mem, int, NULL, 0);
 module_param(autodetect, int, 0);
-MODULE_PARM_DESC(io, "EtherExpress Pro/10 I/O base addres(es)");
+MODULE_PARM_DESC(io, "EtherExpress Pro/10 I/O base address(es)");
 MODULE_PARM_DESC(irq, "EtherExpress Pro/10 IRQ number(s)");
 MODULE_PARM_DESC(mem, "EtherExpress Pro/10 Rx buffer size(es) in kB (3-29)");
 MODULE_PARM_DESC(autodetect, "EtherExpress Pro/10 force board(s) detection (0-1)");
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/eexpress.c linux-libre-2.6.38-gnu1/drivers/net/eexpress.c
--- linux-libre-2.6.37-gnu1/drivers/net/eexpress.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/eexpress.c	2011-03-14 21:20:32.000000000 -0400
@@ -1103,7 +1103,7 @@ static int __init eexp_hw_probe(struct n
 		dev->dev_addr[i] = ((unsigned char *)hw_addr)[5-i];
 
 	{
-		static char irqmap[]={0, 9, 3, 4, 5, 10, 11, 0};
+		static const char irqmap[] = { 0, 9, 3, 4, 5, 10, 11, 0 };
 		unsigned short setupval = eexp_hw_readeeprom(ioaddr,0);
 
 		/* Use the IRQ from EEPROM if none was given */
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/ehea/ehea_ethtool.c linux-libre-2.6.38-gnu1/drivers/net/ehea/ehea_ethtool.c
--- linux-libre-2.6.37-gnu1/drivers/net/ehea/ehea_ethtool.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/ehea/ehea_ethtool.c	2011-03-14 21:20:32.000000000 -0400
@@ -26,6 +26,8 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include "ehea.h"
 #include "ehea_phyp.h"
 
@@ -118,10 +120,10 @@ doit:
 	ret = ehea_set_portspeed(port, sp);
 
 	if (!ret)
-		ehea_info("%s: Port speed successfully set: %dMbps "
-			  "%s Duplex",
-			  port->netdev->name, port->port_speed,
-			  port->full_duplex == 1 ? "Full" : "Half");
+		netdev_info(dev,
+			    "Port speed successfully set: %dMbps %s Duplex\n",
+			    port->port_speed,
+			    port->full_duplex == 1 ? "Full" : "Half");
 out:
 	return ret;
 }
@@ -134,10 +136,10 @@ static int ehea_nway_reset(struct net_de
 	ret = ehea_set_portspeed(port, EHEA_SPEED_AUTONEG);
 
 	if (!ret)
-		ehea_info("%s: Port speed successfully set: %dMbps "
-			  "%s Duplex",
-			  port->netdev->name, port->port_speed,
-			  port->full_duplex == 1 ? "Full" : "Half");
+		netdev_info(port->netdev,
+			    "Port speed successfully set: %dMbps %s Duplex\n",
+			    port->port_speed,
+			    port->full_duplex == 1 ? "Full" : "Half");
 	return ret;
 }
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/ehea/ehea.h linux-libre-2.6.38-gnu1/drivers/net/ehea/ehea.h
--- linux-libre-2.6.37-gnu1/drivers/net/ehea/ehea.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/ehea/ehea.h	2011-03-14 21:20:32.000000000 -0400
@@ -40,7 +40,7 @@
 #include <asm/io.h>
 
 #define DRV_NAME	"ehea"
-#define DRV_VERSION	"EHEA_0106"
+#define DRV_VERSION	"EHEA_0107"
 
 /* eHEA capability flags */
 #define DLPAR_PORT_ADD_REM 1
@@ -130,19 +130,6 @@
 
 /* utility functions */
 
-#define ehea_info(fmt, args...) \
-	printk(KERN_INFO DRV_NAME ": " fmt "\n", ## args)
-
-#define ehea_error(fmt, args...) \
-	printk(KERN_ERR DRV_NAME ": Error in %s: " fmt "\n", __func__, ## args)
-
-#ifdef DEBUG
-#define ehea_debug(fmt, args...) \
-	printk(KERN_DEBUG DRV_NAME ": " fmt, ## args)
-#else
-#define ehea_debug(fmt, args...) do {} while (0)
-#endif
-
 void ehea_dump(void *adr, int len, char *msg);
 
 #define EHEA_BMASK(pos, length) (((pos) << 16) + (length))
@@ -515,6 +502,4 @@ void ehea_set_ethtool_ops(struct net_dev
 int ehea_sense_port_attr(struct ehea_port *port);
 int ehea_set_portspeed(struct ehea_port *port, u32 port_speed);
 
-extern struct work_struct ehea_rereg_mr_task;
-
 #endif	/* __EHEA_H__ */
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/ehea/ehea_main.c linux-libre-2.6.38-gnu1/drivers/net/ehea/ehea_main.c
--- linux-libre-2.6.37-gnu1/drivers/net/ehea/ehea_main.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/ehea/ehea_main.c	2011-03-14 21:20:32.000000000 -0400
@@ -26,6 +26,8 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/in.h>
 #include <linux/ip.h>
 #include <linux/tcp.h>
@@ -101,7 +103,6 @@ MODULE_PARM_DESC(use_lro, " Large Receiv
 static int port_name_cnt;
 static LIST_HEAD(adapter_list);
 static unsigned long ehea_driver_flags;
-struct work_struct ehea_rereg_mr_task;
 static DEFINE_MUTEX(dlpar_mem_lock);
 struct ehea_fw_handle_array ehea_fw_handles;
 struct ehea_bcmc_reg_array ehea_bcmc_regs;
@@ -136,8 +137,8 @@ void ehea_dump(void *adr, int len, char
 	int x;
 	unsigned char *deb = adr;
 	for (x = 0; x < len; x += 16) {
-		printk(DRV_NAME " %s adr=%p ofs=%04x %016llx %016llx\n", msg,
-			  deb, x, *((u64 *)&deb[0]), *((u64 *)&deb[8]));
+		pr_info("%s adr=%p ofs=%04x %016llx %016llx\n",
+			msg, deb, x, *((u64 *)&deb[0]), *((u64 *)&deb[8]));
 		deb += 16;
 	}
 }
@@ -337,7 +338,7 @@ static struct net_device_stats *ehea_get
 
 	cb2 = (void *)get_zeroed_page(GFP_KERNEL);
 	if (!cb2) {
-		ehea_error("no mem for cb2");
+		netdev_err(dev, "no mem for cb2\n");
 		goto out;
 	}
 
@@ -345,7 +346,7 @@ static struct net_device_stats *ehea_get
 				      port->logical_port_id,
 				      H_PORT_CB2, H_PORT_CB2_ALL, cb2);
 	if (hret != H_SUCCESS) {
-		ehea_error("query_ehea_port failed");
+		netdev_err(dev, "query_ehea_port failed\n");
 		goto out_herr;
 	}
 
@@ -400,7 +401,7 @@ static void ehea_refill_rq1(struct ehea_
 			skb_arr_rq1[index] = netdev_alloc_skb(dev,
 							      EHEA_L_PKT_SIZE);
 			if (!skb_arr_rq1[index]) {
-				ehea_info("Unable to allocate enough skb in the array\n");
+				netdev_info(dev, "Unable to allocate enough skb in the array\n");
 				pr->rq1_skba.os_skbs = fill_wqes - i;
 				break;
 			}
@@ -424,19 +425,19 @@ static void ehea_init_fill_rq1(struct eh
 	int i;
 
 	if (nr_rq1a > pr->rq1_skba.len) {
-		ehea_error("NR_RQ1A bigger than skb array len\n");
+		netdev_err(dev, "NR_RQ1A bigger than skb array len\n");
 		return;
 	}
 
 	for (i = 0; i < nr_rq1a; i++) {
 		skb_arr_rq1[i] = netdev_alloc_skb(dev, EHEA_L_PKT_SIZE);
 		if (!skb_arr_rq1[i]) {
-			ehea_info("No enough memory to allocate skb array\n");
+			netdev_info(dev, "Not enough memory to allocate skb array\n");
 			break;
 		}
 	}
 	/* Ring doorbell */
-	ehea_update_rq1a(pr->qp, i);
+	ehea_update_rq1a(pr->qp, i - 1);
 }
 
 static int ehea_refill_rq_def(struct ehea_port_res *pr,
@@ -469,8 +470,9 @@ static int ehea_refill_rq_def(struct ehe
 		if (!skb) {
 			q_skba->os_skbs = fill_wqes - i;
 			if (q_skba->os_skbs == q_skba->len - 2) {
-				ehea_info("%s: rq%i ran dry - no mem for skb",
-					  pr->port->netdev->name, rq_nr);
+				netdev_info(pr->port->netdev,
+					    "rq%i ran dry - no mem for skb\n",
+					    rq_nr);
 				ret = -ENOMEM;
 			}
 			break;
@@ -635,8 +637,8 @@ static int ehea_treat_poll_error(struct
 
 	if (cqe->status & EHEA_CQE_STAT_FAT_ERR_MASK) {
 		if (netif_msg_rx_err(pr->port)) {
-			ehea_error("Critical receive error for QP %d. "
-				   "Resetting port.", pr->qp->init_attr.qp_nr);
+			pr_err("Critical receive error for QP %d. Resetting port.\n",
+			       pr->qp->init_attr.qp_nr);
 			ehea_dump(cqe, sizeof(*cqe), "CQE");
 		}
 		ehea_schedule_port_reset(pr->port);
@@ -738,13 +740,13 @@ static int ehea_proc_rwqes(struct net_de
 							  skb_arr_rq1_len,
 							  wqe_index);
 				if (unlikely(!skb)) {
-					if (netif_msg_rx_err(port))
-						ehea_error("LL rq1: skb=NULL");
+					netif_info(port, rx_err, dev,
+						  "LL rq1: skb=NULL\n");
 
 					skb = netdev_alloc_skb(dev,
 							       EHEA_L_PKT_SIZE);
 					if (!skb) {
-						ehea_info("Not enough memory to allocate skb\n");
+						netdev_err(dev, "Not enough memory to allocate skb\n");
 						break;
 					}
 				}
@@ -756,8 +758,8 @@ static int ehea_proc_rwqes(struct net_de
 				skb = get_skb_by_index(skb_arr_rq2,
 						       skb_arr_rq2_len, cqe);
 				if (unlikely(!skb)) {
-					if (netif_msg_rx_err(port))
-						ehea_error("rq2: skb=NULL");
+					netif_err(port, rx_err, dev,
+						  "rq2: skb=NULL\n");
 					break;
 				}
 				ehea_fill_skb(dev, skb, cqe);
@@ -767,8 +769,8 @@ static int ehea_proc_rwqes(struct net_de
 				skb = get_skb_by_index(skb_arr_rq3,
 						       skb_arr_rq3_len, cqe);
 				if (unlikely(!skb)) {
-					if (netif_msg_rx_err(port))
-						ehea_error("rq3: skb=NULL");
+					netif_err(port, rx_err, dev,
+						  "rq3: skb=NULL\n");
 					break;
 				}
 				ehea_fill_skb(dev, skb, cqe);
@@ -840,7 +842,7 @@ static void check_sqs(struct ehea_port *
 					 msecs_to_jiffies(100));
 
 		if (!ret) {
-			ehea_error("HW/SW queues out of sync");
+			pr_err("HW/SW queues out of sync\n");
 			ehea_schedule_port_reset(pr->port);
 			return;
 		}
@@ -873,14 +875,14 @@ static struct ehea_cqe *ehea_proc_cqes(s
 		}
 
 		if (cqe->status & EHEA_CQE_STAT_ERR_MASK) {
-			ehea_error("Bad send completion status=0x%04X",
-				   cqe->status);
+			pr_err("Bad send completion status=0x%04X\n",
+			       cqe->status);
 
 			if (netif_msg_tx_err(pr->port))
 				ehea_dump(cqe, sizeof(*cqe), "Send CQE");
 
 			if (cqe->status & EHEA_CQE_STAT_RESET_MASK) {
-				ehea_error("Resetting port");
+				pr_err("Resetting port\n");
 				ehea_schedule_port_reset(pr->port);
 				break;
 			}
@@ -998,8 +1000,8 @@ static irqreturn_t ehea_qp_aff_irq_handl
 
 	while (eqe) {
 		qp_token = EHEA_BMASK_GET(EHEA_EQE_QP_TOKEN, eqe->entry);
-		ehea_error("QP aff_err: entry=0x%llx, token=0x%x",
-			   eqe->entry, qp_token);
+		pr_err("QP aff_err: entry=0x%llx, token=0x%x\n",
+		       eqe->entry, qp_token);
 
 		qp = port->port_res[qp_token].qp;
 
@@ -1017,7 +1019,7 @@ static irqreturn_t ehea_qp_aff_irq_handl
 	}
 
 	if (reset_port) {
-		ehea_error("Resetting port");
+		pr_err("Resetting port\n");
 		ehea_schedule_port_reset(port);
 	}
 
@@ -1045,7 +1047,7 @@ int ehea_sense_port_attr(struct ehea_por
 	/* may be called via ehea_neq_tasklet() */
 	cb0 = (void *)get_zeroed_page(GFP_ATOMIC);
 	if (!cb0) {
-		ehea_error("no mem for cb0");
+		pr_err("no mem for cb0\n");
 		ret = -ENOMEM;
 		goto out;
 	}
@@ -1137,7 +1139,7 @@ int ehea_set_portspeed(struct ehea_port
 
 	cb4 = (void *)get_zeroed_page(GFP_KERNEL);
 	if (!cb4) {
-		ehea_error("no mem for cb4");
+		pr_err("no mem for cb4\n");
 		ret = -ENOMEM;
 		goto out;
 	}
@@ -1188,16 +1190,16 @@ int ehea_set_portspeed(struct ehea_port
 				break;
 			}
 		} else {
-			ehea_error("Failed sensing port speed");
+			pr_err("Failed sensing port speed\n");
 			ret = -EIO;
 		}
 	} else {
 		if (hret == H_AUTHORITY) {
-			ehea_info("Hypervisor denied setting port speed");
+			pr_info("Hypervisor denied setting port speed\n");
 			ret = -EPERM;
 		} else {
 			ret = -EIO;
-			ehea_error("Failed setting port speed");
+			pr_err("Failed setting port speed\n");
 		}
 	}
 	if (!prop_carrier_state || (port->phy_link == EHEA_PHY_LINK_UP))
@@ -1214,80 +1216,78 @@ static void ehea_parse_eqe(struct ehea_a
 	u8 ec;
 	u8 portnum;
 	struct ehea_port *port;
+	struct net_device *dev;
 
 	ec = EHEA_BMASK_GET(NEQE_EVENT_CODE, eqe);
 	portnum = EHEA_BMASK_GET(NEQE_PORTNUM, eqe);
 	port = ehea_get_port(adapter, portnum);
+	dev = port->netdev;
 
 	switch (ec) {
 	case EHEA_EC_PORTSTATE_CHG:	/* port state change */
 
 		if (!port) {
-			ehea_error("unknown portnum %x", portnum);
+			netdev_err(dev, "unknown portnum %x\n", portnum);
 			break;
 		}
 
 		if (EHEA_BMASK_GET(NEQE_PORT_UP, eqe)) {
-			if (!netif_carrier_ok(port->netdev)) {
+			if (!netif_carrier_ok(dev)) {
 				ret = ehea_sense_port_attr(port);
 				if (ret) {
-					ehea_error("failed resensing port "
-						   "attributes");
+					netdev_err(dev, "failed resensing port attributes\n");
 					break;
 				}
 
-				if (netif_msg_link(port))
-					ehea_info("%s: Logical port up: %dMbps "
-						  "%s Duplex",
-						  port->netdev->name,
-						  port->port_speed,
-						  port->full_duplex ==
-						  1 ? "Full" : "Half");
+				netif_info(port, link, dev,
+					   "Logical port up: %dMbps %s Duplex\n",
+					   port->port_speed,
+					   port->full_duplex == 1 ?
+					   "Full" : "Half");
 
-				netif_carrier_on(port->netdev);
-				netif_wake_queue(port->netdev);
+				netif_carrier_on(dev);
+				netif_wake_queue(dev);
 			}
 		} else
-			if (netif_carrier_ok(port->netdev)) {
-				if (netif_msg_link(port))
-					ehea_info("%s: Logical port down",
-						  port->netdev->name);
-				netif_carrier_off(port->netdev);
-				netif_stop_queue(port->netdev);
+			if (netif_carrier_ok(dev)) {
+				netif_info(port, link, dev,
+					   "Logical port down\n");
+				netif_carrier_off(dev);
+				netif_stop_queue(dev);
 			}
 
 		if (EHEA_BMASK_GET(NEQE_EXTSWITCH_PORT_UP, eqe)) {
 			port->phy_link = EHEA_PHY_LINK_UP;
-			if (netif_msg_link(port))
-				ehea_info("%s: Physical port up",
-					  port->netdev->name);
+			netif_info(port, link, dev,
+				   "Physical port up\n");
 			if (prop_carrier_state)
-				netif_carrier_on(port->netdev);
+				netif_carrier_on(dev);
 		} else {
 			port->phy_link = EHEA_PHY_LINK_DOWN;
-			if (netif_msg_link(port))
-				ehea_info("%s: Physical port down",
-					  port->netdev->name);
+			netif_info(port, link, dev,
+				   "Physical port down\n");
 			if (prop_carrier_state)
-				netif_carrier_off(port->netdev);
+				netif_carrier_off(dev);
 		}
 
 		if (EHEA_BMASK_GET(NEQE_EXTSWITCH_PRIMARY, eqe))
-			ehea_info("External switch port is primary port");
+			netdev_info(dev,
+				    "External switch port is primary port\n");
 		else
-			ehea_info("External switch port is backup port");
+			netdev_info(dev,
+				    "External switch port is backup port\n");
 
 		break;
 	case EHEA_EC_ADAPTER_MALFUNC:
-		ehea_error("Adapter malfunction");
+		netdev_err(dev, "Adapter malfunction\n");
 		break;
 	case EHEA_EC_PORT_MALFUNC:
-		ehea_info("Port malfunction: Device: %s", port->netdev->name);
-		netif_carrier_off(port->netdev);
-		netif_stop_queue(port->netdev);
+		netdev_info(dev, "Port malfunction\n");
+		netif_carrier_off(dev);
+		netif_stop_queue(dev);
 		break;
 	default:
-		ehea_error("unknown event code %x, eqe=0x%llX", ec, eqe);
+		netdev_err(dev, "unknown event code %x, eqe=0x%llX\n", ec, eqe);
 		break;
 	}
 }
@@ -1299,13 +1299,13 @@ static void ehea_neq_tasklet(unsigned lo
 	u64 event_mask;
 
 	eqe = ehea_poll_eq(adapter->neq);
-	ehea_debug("eqe=%p", eqe);
+	pr_debug("eqe=%p\n", eqe);
 
 	while (eqe) {
-		ehea_debug("*eqe=%lx", eqe->entry);
+		pr_debug("*eqe=%lx\n", (unsigned long) eqe->entry);
 		ehea_parse_eqe(adapter, eqe->entry);
 		eqe = ehea_poll_eq(adapter->neq);
-		ehea_debug("next eqe=%p", eqe);
+		pr_debug("next eqe=%p\n", eqe);
 	}
 
 	event_mask = EHEA_BMASK_SET(NELR_PORTSTATE_CHG, 1)
@@ -1329,9 +1329,7 @@ static int ehea_fill_port_res(struct ehe
 	int ret;
 	struct ehea_qp_init_attr *init_attr = &pr->qp->init_attr;
 
-	ehea_init_fill_rq1(pr, init_attr->act_nr_rwqes_rq1
-			       - init_attr->act_nr_rwqes_rq2
-			       - init_attr->act_nr_rwqes_rq3 - 1);
+	ehea_init_fill_rq1(pr, pr->rq1_skba.len);
 
 	ret = ehea_refill_rq2(pr, init_attr->act_nr_rwqes_rq2 - 1);
 
@@ -1354,14 +1352,14 @@ static int ehea_reg_interrupts(struct ne
 				  ehea_qp_aff_irq_handler,
 				  IRQF_DISABLED, port->int_aff_name, port);
 	if (ret) {
-		ehea_error("failed registering irq for qp_aff_irq_handler:"
-			   "ist=%X", port->qp_eq->attr.ist1);
+		netdev_err(dev, "failed registering irq for qp_aff_irq_handler:ist=%X\n",
+			   port->qp_eq->attr.ist1);
 		goto out_free_qpeq;
 	}
 
-	if (netif_msg_ifup(port))
-		ehea_info("irq_handle 0x%X for function qp_aff_irq_handler "
-			  "registered", port->qp_eq->attr.ist1);
+	netif_info(port, ifup, dev,
+		   "irq_handle 0x%X for function qp_aff_irq_handler registered\n",
+		   port->qp_eq->attr.ist1);
 
 
 	for (i = 0; i < port->num_def_qps + port->num_add_tx_qps; i++) {
@@ -1373,14 +1371,13 @@ static int ehea_reg_interrupts(struct ne
 					  IRQF_DISABLED, pr->int_send_name,
 					  pr);
 		if (ret) {
-			ehea_error("failed registering irq for ehea_queue "
-				   "port_res_nr:%d, ist=%X", i,
-				   pr->eq->attr.ist1);
+			netdev_err(dev, "failed registering irq for ehea_queue port_res_nr:%d, ist=%X\n",
+				   i, pr->eq->attr.ist1);
 			goto out_free_req;
 		}
-		if (netif_msg_ifup(port))
-			ehea_info("irq_handle 0x%X for function ehea_queue_int "
-				  "%d registered", pr->eq->attr.ist1, i);
+		netif_info(port, ifup, dev,
+			   "irq_handle 0x%X for function ehea_queue_int %d registered\n",
+			   pr->eq->attr.ist1, i);
 	}
 out:
 	return ret;
@@ -1411,16 +1408,16 @@ static void ehea_free_interrupts(struct
 	for (i = 0; i < port->num_def_qps + port->num_add_tx_qps; i++) {
 		pr = &port->port_res[i];
 		ibmebus_free_irq(pr->eq->attr.ist1, pr);
-		if (netif_msg_intr(port))
-			ehea_info("free send irq for res %d with handle 0x%X",
-				  i, pr->eq->attr.ist1);
+		netif_info(port, intr, dev,
+			   "free send irq for res %d with handle 0x%X\n",
+			   i, pr->eq->attr.ist1);
 	}
 
 	/* associated events */
 	ibmebus_free_irq(port->qp_eq->attr.ist1, port);
-	if (netif_msg_intr(port))
-		ehea_info("associated event interrupt for handle 0x%X freed",
-			  port->qp_eq->attr.ist1);
+	netif_info(port, intr, dev,
+		   "associated event interrupt for handle 0x%X freed\n",
+		   port->qp_eq->attr.ist1);
 }
 
 static int ehea_configure_port(struct ehea_port *port)
@@ -1489,7 +1486,7 @@ int ehea_gen_smrs(struct ehea_port_res *
 out_free:
 	ehea_rem_mr(&pr->send_mr);
 out:
-	ehea_error("Generating SMRS failed\n");
+	pr_err("Generating SMRS failed\n");
 	return -EIO;
 }
 
@@ -1506,12 +1503,10 @@ static int ehea_init_q_skba(struct ehea_
 {
 	int arr_size = sizeof(void *) * max_q_entries;
 
-	q_skba->arr = vmalloc(arr_size);
+	q_skba->arr = vzalloc(arr_size);
 	if (!q_skba->arr)
 		return -ENOMEM;
 
-	memset(q_skba->arr, 0, arr_size);
-
 	q_skba->len = max_q_entries;
 	q_skba->index = 0;
 	q_skba->os_skbs = 0;
@@ -1546,7 +1541,7 @@ static int ehea_init_port_res(struct ehe
 
 	pr->eq = ehea_create_eq(adapter, eq_type, EHEA_MAX_ENTRIES_EQ, 0);
 	if (!pr->eq) {
-		ehea_error("create_eq failed (eq)");
+		pr_err("create_eq failed (eq)\n");
 		goto out_free;
 	}
 
@@ -1554,7 +1549,7 @@ static int ehea_init_port_res(struct ehe
 				     pr->eq->fw_handle,
 				     port->logical_port_id);
 	if (!pr->recv_cq) {
-		ehea_error("create_cq failed (cq_recv)");
+		pr_err("create_cq failed (cq_recv)\n");
 		goto out_free;
 	}
 
@@ -1562,19 +1557,19 @@ static int ehea_init_port_res(struct ehe
 				     pr->eq->fw_handle,
 				     port->logical_port_id);
 	if (!pr->send_cq) {
-		ehea_error("create_cq failed (cq_send)");
+		pr_err("create_cq failed (cq_send)\n");
 		goto out_free;
 	}
 
 	if (netif_msg_ifup(port))
-		ehea_info("Send CQ: act_nr_cqes=%d, Recv CQ: act_nr_cqes=%d",
-			  pr->send_cq->attr.act_nr_of_cqes,
-			  pr->recv_cq->attr.act_nr_of_cqes);
+		pr_info("Send CQ: act_nr_cqes=%d, Recv CQ: act_nr_cqes=%d\n",
+			pr->send_cq->attr.act_nr_of_cqes,
+			pr->recv_cq->attr.act_nr_of_cqes);
 
 	init_attr = kzalloc(sizeof(*init_attr), GFP_KERNEL);
 	if (!init_attr) {
 		ret = -ENOMEM;
-		ehea_error("no mem for ehea_qp_init_attr");
+		pr_err("no mem for ehea_qp_init_attr\n");
 		goto out_free;
 	}
 
@@ -1599,18 +1594,18 @@ static int ehea_init_port_res(struct ehe
 
 	pr->qp = ehea_create_qp(adapter, adapter->pd, init_attr);
 	if (!pr->qp) {
-		ehea_error("create_qp failed");
+		pr_err("create_qp failed\n");
 		ret = -EIO;
 		goto out_free;
 	}
 
 	if (netif_msg_ifup(port))
-		ehea_info("QP: qp_nr=%d\n act_nr_snd_wqe=%d\n nr_rwqe_rq1=%d\n "
-			  "nr_rwqe_rq2=%d\n nr_rwqe_rq3=%d", init_attr->qp_nr,
-			  init_attr->act_nr_send_wqes,
-			  init_attr->act_nr_rwqes_rq1,
-			  init_attr->act_nr_rwqes_rq2,
-			  init_attr->act_nr_rwqes_rq3);
+		pr_info("QP: qp_nr=%d\n act_nr_snd_wqe=%d\n nr_rwqe_rq1=%d\n nr_rwqe_rq2=%d\n nr_rwqe_rq3=%d\n",
+			init_attr->qp_nr,
+			init_attr->act_nr_send_wqes,
+			init_attr->act_nr_rwqes_rq1,
+			init_attr->act_nr_rwqes_rq2,
+			init_attr->act_nr_rwqes_rq3);
 
 	pr->sq_skba_size = init_attr->act_nr_send_wqes + 1;
 
@@ -1761,7 +1756,7 @@ static void write_swqe2_TSO(struct sk_bu
 			swqe->descriptors++;
 		}
 	} else
-		ehea_error("cannot handle fragmented headers");
+		pr_err("cannot handle fragmented headers\n");
 }
 
 static void write_swqe2_nonTSO(struct sk_buff *skb,
@@ -1857,8 +1852,8 @@ static int ehea_broadcast_reg_helper(str
 				     port->logical_port_id,
 				     reg_type, port->mac_addr, 0, hcallid);
 	if (hret != H_SUCCESS) {
-		ehea_error("%sregistering bc address failed (tagged)",
-			   hcallid == H_REG_BCMC ? "" : "de");
+		pr_err("%sregistering bc address failed (tagged)\n",
+		       hcallid == H_REG_BCMC ? "" : "de");
 		ret = -EIO;
 		goto out_herr;
 	}
@@ -1869,8 +1864,8 @@ static int ehea_broadcast_reg_helper(str
 				     port->logical_port_id,
 				     reg_type, port->mac_addr, 0, hcallid);
 	if (hret != H_SUCCESS) {
-		ehea_error("%sregistering bc address failed (vlan)",
-			   hcallid == H_REG_BCMC ? "" : "de");
+		pr_err("%sregistering bc address failed (vlan)\n",
+		       hcallid == H_REG_BCMC ? "" : "de");
 		ret = -EIO;
 	}
 out_herr:
@@ -1892,7 +1887,7 @@ static int ehea_set_mac_addr(struct net_
 
 	cb0 = (void *)get_zeroed_page(GFP_KERNEL);
 	if (!cb0) {
-		ehea_error("no mem for cb0");
+		pr_err("no mem for cb0\n");
 		ret = -ENOMEM;
 		goto out;
 	}
@@ -1940,11 +1935,11 @@ out:
 static void ehea_promiscuous_error(u64 hret, int enable)
 {
 	if (hret == H_AUTHORITY)
-		ehea_info("Hypervisor denied %sabling promiscuous mode",
-			  enable == 1 ? "en" : "dis");
+		pr_info("Hypervisor denied %sabling promiscuous mode\n",
+			enable == 1 ? "en" : "dis");
 	else
-		ehea_error("failed %sabling promiscuous mode",
-			   enable == 1 ? "en" : "dis");
+		pr_err("failed %sabling promiscuous mode\n",
+		       enable == 1 ? "en" : "dis");
 }
 
 static void ehea_promiscuous(struct net_device *dev, int enable)
@@ -1958,7 +1953,7 @@ static void ehea_promiscuous(struct net_
 
 	cb7 = (void *)get_zeroed_page(GFP_ATOMIC);
 	if (!cb7) {
-		ehea_error("no mem for cb7");
+		pr_err("no mem for cb7\n");
 		goto out;
 	}
 
@@ -2018,7 +2013,7 @@ static int ehea_drop_multicast_list(stru
 		hret = ehea_multicast_reg_helper(port, mc_entry->macaddr,
 						 H_DEREG_BCMC);
 		if (hret) {
-			ehea_error("failed deregistering mcast MAC");
+			pr_err("failed deregistering mcast MAC\n");
 			ret = -EIO;
 		}
 
@@ -2041,7 +2036,8 @@ static void ehea_allmulti(struct net_dev
 			if (!hret)
 				port->allmulti = 1;
 			else
-				ehea_error("failed enabling IFF_ALLMULTI");
+				netdev_err(dev,
+					   "failed enabling IFF_ALLMULTI\n");
 		}
 	} else
 		if (!enable) {
@@ -2050,7 +2046,8 @@ static void ehea_allmulti(struct net_dev
 			if (!hret)
 				port->allmulti = 0;
 			else
-				ehea_error("failed disabling IFF_ALLMULTI");
+				netdev_err(dev,
+					   "failed disabling IFF_ALLMULTI\n");
 		}
 }
 
@@ -2061,7 +2058,7 @@ static void ehea_add_multicast_entry(str
 
 	ehea_mcl_entry = kzalloc(sizeof(*ehea_mcl_entry), GFP_ATOMIC);
 	if (!ehea_mcl_entry) {
-		ehea_error("no mem for mcl_entry");
+		pr_err("no mem for mcl_entry\n");
 		return;
 	}
 
@@ -2074,7 +2071,7 @@ static void ehea_add_multicast_entry(str
 	if (!hret)
 		list_add(&ehea_mcl_entry->list, &port->mc_list->list);
 	else {
-		ehea_error("failed registering mcast MAC");
+		pr_err("failed registering mcast MAC\n");
 		kfree(ehea_mcl_entry);
 	}
 }
@@ -2107,9 +2104,8 @@ static void ehea_set_multicast_list(stru
 		}
 
 		if (netdev_mc_count(dev) > port->adapter->max_mc_mac) {
-			ehea_info("Mcast registration limit reached (0x%llx). "
-				  "Use ALLMULTI!",
-				  port->adapter->max_mc_mac);
+			pr_info("Mcast registration limit reached (0x%llx). Use ALLMULTI!\n",
+				port->adapter->max_mc_mac);
 			goto out;
 		}
 
@@ -2315,10 +2311,10 @@ static int ehea_start_xmit(struct sk_buf
 	}
 	pr->swqe_id_counter += 1;
 
-	if (netif_msg_tx_queued(port)) {
-		ehea_info("post swqe on QP %d", pr->qp->init_attr.qp_nr);
+	netif_info(port, tx_queued, dev,
+		   "post swqe on QP %d\n", pr->qp->init_attr.qp_nr);
+	if (netif_msg_tx_queued(port))
 		ehea_dump(swqe, 512, "swqe");
-	}
 
 	if (unlikely(test_bit(__EHEA_STOP_XFER, &ehea_driver_flags))) {
 		netif_stop_queue(dev);
@@ -2354,14 +2350,14 @@ static void ehea_vlan_rx_register(struct
 
 	cb1 = (void *)get_zeroed_page(GFP_KERNEL);
 	if (!cb1) {
-		ehea_error("no mem for cb1");
+		pr_err("no mem for cb1\n");
 		goto out;
 	}
 
 	hret = ehea_h_modify_ehea_port(adapter->handle, port->logical_port_id,
 				       H_PORT_CB1, H_PORT_CB1_ALL, cb1);
 	if (hret != H_SUCCESS)
-		ehea_error("modify_ehea_port failed");
+		pr_err("modify_ehea_port failed\n");
 
 	free_page((unsigned long)cb1);
 out:
@@ -2378,14 +2374,14 @@ static void ehea_vlan_rx_add_vid(struct
 
 	cb1 = (void *)get_zeroed_page(GFP_KERNEL);
 	if (!cb1) {
-		ehea_error("no mem for cb1");
+		pr_err("no mem for cb1\n");
 		goto out;
 	}
 
 	hret = ehea_h_query_ehea_port(adapter->handle, port->logical_port_id,
 				      H_PORT_CB1, H_PORT_CB1_ALL, cb1);
 	if (hret != H_SUCCESS) {
-		ehea_error("query_ehea_port failed");
+		pr_err("query_ehea_port failed\n");
 		goto out;
 	}
 
@@ -2395,7 +2391,7 @@ static void ehea_vlan_rx_add_vid(struct
 	hret = ehea_h_modify_ehea_port(adapter->handle, port->logical_port_id,
 				       H_PORT_CB1, H_PORT_CB1_ALL, cb1);
 	if (hret != H_SUCCESS)
-		ehea_error("modify_ehea_port failed");
+		pr_err("modify_ehea_port failed\n");
 out:
 	free_page((unsigned long)cb1);
 	return;
@@ -2413,14 +2409,14 @@ static void ehea_vlan_rx_kill_vid(struct
 
 	cb1 = (void *)get_zeroed_page(GFP_KERNEL);
 	if (!cb1) {
-		ehea_error("no mem for cb1");
+		pr_err("no mem for cb1\n");
 		goto out;
 	}
 
 	hret = ehea_h_query_ehea_port(adapter->handle, port->logical_port_id,
 				      H_PORT_CB1, H_PORT_CB1_ALL, cb1);
 	if (hret != H_SUCCESS) {
-		ehea_error("query_ehea_port failed");
+		pr_err("query_ehea_port failed\n");
 		goto out;
 	}
 
@@ -2430,7 +2426,7 @@ static void ehea_vlan_rx_kill_vid(struct
 	hret = ehea_h_modify_ehea_port(adapter->handle, port->logical_port_id,
 				       H_PORT_CB1, H_PORT_CB1_ALL, cb1);
 	if (hret != H_SUCCESS)
-		ehea_error("modify_ehea_port failed");
+		pr_err("modify_ehea_port failed\n");
 out:
 	free_page((unsigned long)cb1);
 }
@@ -2452,7 +2448,7 @@ int ehea_activate_qp(struct ehea_adapter
 	hret = ehea_h_query_ehea_qp(adapter->handle, 0, qp->fw_handle,
 				    EHEA_BMASK_SET(H_QPCB0_ALL, 0xFFFF), cb0);
 	if (hret != H_SUCCESS) {
-		ehea_error("query_ehea_qp failed (1)");
+		pr_err("query_ehea_qp failed (1)\n");
 		goto out;
 	}
 
@@ -2461,14 +2457,14 @@ int ehea_activate_qp(struct ehea_adapter
 				     EHEA_BMASK_SET(H_QPCB0_QP_CTL_REG, 1), cb0,
 				     &dummy64, &dummy64, &dummy16, &dummy16);
 	if (hret != H_SUCCESS) {
-		ehea_error("modify_ehea_qp failed (1)");
+		pr_err("modify_ehea_qp failed (1)\n");
 		goto out;
 	}
 
 	hret = ehea_h_query_ehea_qp(adapter->handle, 0, qp->fw_handle,
 				    EHEA_BMASK_SET(H_QPCB0_ALL, 0xFFFF), cb0);
 	if (hret != H_SUCCESS) {
-		ehea_error("query_ehea_qp failed (2)");
+		pr_err("query_ehea_qp failed (2)\n");
 		goto out;
 	}
 
@@ -2477,14 +2473,14 @@ int ehea_activate_qp(struct ehea_adapter
 				     EHEA_BMASK_SET(H_QPCB0_QP_CTL_REG, 1), cb0,
 				     &dummy64, &dummy64, &dummy16, &dummy16);
 	if (hret != H_SUCCESS) {
-		ehea_error("modify_ehea_qp failed (2)");
+		pr_err("modify_ehea_qp failed (2)\n");
 		goto out;
 	}
 
 	hret = ehea_h_query_ehea_qp(adapter->handle, 0, qp->fw_handle,
 				    EHEA_BMASK_SET(H_QPCB0_ALL, 0xFFFF), cb0);
 	if (hret != H_SUCCESS) {
-		ehea_error("query_ehea_qp failed (3)");
+		pr_err("query_ehea_qp failed (3)\n");
 		goto out;
 	}
 
@@ -2493,14 +2489,14 @@ int ehea_activate_qp(struct ehea_adapter
 				     EHEA_BMASK_SET(H_QPCB0_QP_CTL_REG, 1), cb0,
 				     &dummy64, &dummy64, &dummy16, &dummy16);
 	if (hret != H_SUCCESS) {
-		ehea_error("modify_ehea_qp failed (3)");
+		pr_err("modify_ehea_qp failed (3)\n");
 		goto out;
 	}
 
 	hret = ehea_h_query_ehea_qp(adapter->handle, 0, qp->fw_handle,
 				    EHEA_BMASK_SET(H_QPCB0_ALL, 0xFFFF), cb0);
 	if (hret != H_SUCCESS) {
-		ehea_error("query_ehea_qp failed (4)");
+		pr_err("query_ehea_qp failed (4)\n");
 		goto out;
 	}
 
@@ -2521,7 +2517,7 @@ static int ehea_port_res_setup(struct eh
 				   EHEA_MAX_ENTRIES_EQ, 1);
 	if (!port->qp_eq) {
 		ret = -EINVAL;
-		ehea_error("ehea_create_eq failed (qp_eq)");
+		pr_err("ehea_create_eq failed (qp_eq)\n");
 		goto out_kill_eq;
 	}
 
@@ -2602,27 +2598,27 @@ static int ehea_up(struct net_device *de
 	ret = ehea_port_res_setup(port, port->num_def_qps,
 				  port->num_add_tx_qps);
 	if (ret) {
-		ehea_error("port_res_failed");
+		netdev_err(dev, "port_res_failed\n");
 		goto out;
 	}
 
 	/* Set default QP for this port */
 	ret = ehea_configure_port(port);
 	if (ret) {
-		ehea_error("ehea_configure_port failed. ret:%d", ret);
+		netdev_err(dev, "ehea_configure_port failed. ret:%d\n", ret);
 		goto out_clean_pr;
 	}
 
 	ret = ehea_reg_interrupts(dev);
 	if (ret) {
-		ehea_error("reg_interrupts failed. ret:%d", ret);
+		netdev_err(dev, "reg_interrupts failed. ret:%d\n", ret);
 		goto out_clean_pr;
 	}
 
 	for (i = 0; i < port->num_def_qps + port->num_add_tx_qps; i++) {
 		ret = ehea_activate_qp(port->adapter, port->port_res[i].qp);
 		if (ret) {
-			ehea_error("activate_qp failed");
+			netdev_err(dev, "activate_qp failed\n");
 			goto out_free_irqs;
 		}
 	}
@@ -2630,7 +2626,7 @@ static int ehea_up(struct net_device *de
 	for (i = 0; i < port->num_def_qps; i++) {
 		ret = ehea_fill_port_res(&port->port_res[i]);
 		if (ret) {
-			ehea_error("out_free_irqs");
+			netdev_err(dev, "out_free_irqs\n");
 			goto out_free_irqs;
 		}
 	}
@@ -2653,7 +2649,7 @@ out_clean_pr:
 	ehea_clean_all_portres(port);
 out:
 	if (ret)
-		ehea_info("Failed starting %s. ret=%i", dev->name, ret);
+		netdev_info(dev, "Failed starting. ret=%i\n", ret);
 
 	ehea_update_bcmc_registrations();
 	ehea_update_firmware_handles();
@@ -2684,8 +2680,7 @@ static int ehea_open(struct net_device *
 
 	mutex_lock(&port->port_lock);
 
-	if (netif_msg_ifup(port))
-		ehea_info("enabling port %s", dev->name);
+	netif_info(port, ifup, dev, "enabling port\n");
 
 	ret = ehea_up(dev);
 	if (!ret) {
@@ -2720,8 +2715,7 @@ static int ehea_down(struct net_device *
 
 	ret = ehea_clean_all_portres(port);
 	if (ret)
-		ehea_info("Failed freeing resources for %s. ret=%i",
-			  dev->name, ret);
+		netdev_info(dev, "Failed freeing resources. ret=%i\n", ret);
 
 	ehea_update_firmware_handles();
 
@@ -2733,8 +2727,7 @@ static int ehea_stop(struct net_device *
 	int ret;
 	struct ehea_port *port = netdev_priv(dev);
 
-	if (netif_msg_ifdown(port))
-		ehea_info("disabling port %s", dev->name);
+	netif_info(port, ifdown, dev, "disabling port\n");
 
 	set_bit(__EHEA_DISABLE_PORT_RESET, &port->flags);
 	cancel_work_sync(&port->reset_task);
@@ -2775,7 +2768,7 @@ static void ehea_flush_sq(struct ehea_po
 			 msecs_to_jiffies(100));
 
 		if (!ret) {
-			ehea_error("WARNING: sq not flushed completely");
+			pr_err("WARNING: sq not flushed completely\n");
 			break;
 		}
 	}
@@ -2811,7 +2804,7 @@ int ehea_stop_qps(struct net_device *dev
 					    EHEA_BMASK_SET(H_QPCB0_ALL, 0xFFFF),
 					    cb0);
 		if (hret != H_SUCCESS) {
-			ehea_error("query_ehea_qp failed (1)");
+			pr_err("query_ehea_qp failed (1)\n");
 			goto out;
 		}
 
@@ -2823,7 +2816,7 @@ int ehea_stop_qps(struct net_device *dev
 							    1), cb0, &dummy64,
 					     &dummy64, &dummy16, &dummy16);
 		if (hret != H_SUCCESS) {
-			ehea_error("modify_ehea_qp failed (1)");
+			pr_err("modify_ehea_qp failed (1)\n");
 			goto out;
 		}
 
@@ -2831,14 +2824,14 @@ int ehea_stop_qps(struct net_device *dev
 					    EHEA_BMASK_SET(H_QPCB0_ALL, 0xFFFF),
 					    cb0);
 		if (hret != H_SUCCESS) {
-			ehea_error("query_ehea_qp failed (2)");
+			pr_err("query_ehea_qp failed (2)\n");
 			goto out;
 		}
 
 		/* deregister shared memory regions */
 		dret = ehea_rem_smrs(pr);
 		if (dret) {
-			ehea_error("unreg shared memory region failed");
+			pr_err("unreg shared memory region failed\n");
 			goto out;
 		}
 	}
@@ -2907,7 +2900,7 @@ int ehea_restart_qps(struct net_device *
 
 		ret = ehea_gen_smrs(pr);
 		if (ret) {
-			ehea_error("creation of shared memory regions failed");
+			netdev_err(dev, "creation of shared memory regions failed\n");
 			goto out;
 		}
 
@@ -2918,7 +2911,7 @@ int ehea_restart_qps(struct net_device *
 					    EHEA_BMASK_SET(H_QPCB0_ALL, 0xFFFF),
 					    cb0);
 		if (hret != H_SUCCESS) {
-			ehea_error("query_ehea_qp failed (1)");
+			netdev_err(dev, "query_ehea_qp failed (1)\n");
 			goto out;
 		}
 
@@ -2930,7 +2923,7 @@ int ehea_restart_qps(struct net_device *
 							    1), cb0, &dummy64,
 					     &dummy64, &dummy16, &dummy16);
 		if (hret != H_SUCCESS) {
-			ehea_error("modify_ehea_qp failed (1)");
+			netdev_err(dev, "modify_ehea_qp failed (1)\n");
 			goto out;
 		}
 
@@ -2938,7 +2931,7 @@ int ehea_restart_qps(struct net_device *
 					    EHEA_BMASK_SET(H_QPCB0_ALL, 0xFFFF),
 					    cb0);
 		if (hret != H_SUCCESS) {
-			ehea_error("query_ehea_qp failed (2)");
+			netdev_err(dev, "query_ehea_qp failed (2)\n");
 			goto out;
 		}
 
@@ -2975,8 +2968,7 @@ static void ehea_reset_port(struct work_
 
 	ehea_set_multicast_list(dev);
 
-	if (netif_msg_timer(port))
-		ehea_info("Device %s resetted successfully", dev->name);
+	netif_info(port, timer, dev, "reset successful\n");
 
 	port_napi_enable(port);
 
@@ -2986,12 +2978,12 @@ out:
 	mutex_unlock(&dlpar_mem_lock);
 }
 
-static void ehea_rereg_mrs(struct work_struct *work)
+static void ehea_rereg_mrs(void)
 {
 	int ret, i;
 	struct ehea_adapter *adapter;
 
-	ehea_info("LPAR memory changed - re-initializing driver");
+	pr_info("LPAR memory changed - re-initializing driver\n");
 
 	list_for_each_entry(adapter, &adapter_list, list)
 		if (adapter->active_ports) {
@@ -3023,8 +3015,7 @@ static void ehea_rereg_mrs(struct work_s
 			/* Unregister old memory region */
 			ret = ehea_rem_mr(&adapter->mr);
 			if (ret) {
-				ehea_error("unregister MR failed - driver"
-					   " inoperable!");
+				pr_err("unregister MR failed - driver inoperable!\n");
 				goto out;
 			}
 		}
@@ -3036,8 +3027,7 @@ static void ehea_rereg_mrs(struct work_s
 			/* Register new memory region */
 			ret = ehea_reg_kernel_mr(adapter, &adapter->mr);
 			if (ret) {
-				ehea_error("register MR failed - driver"
-					   " inoperable!");
+				pr_err("register MR failed - driver inoperable!\n");
 				goto out;
 			}
 
@@ -3060,7 +3050,7 @@ static void ehea_rereg_mrs(struct work_s
 				}
 			}
 		}
-	ehea_info("re-initializing driver complete");
+	pr_info("re-initializing driver complete\n");
 out:
 	return;
 }
@@ -3113,7 +3103,7 @@ int ehea_get_jumboframe_status(struct eh
 	/* (Try to) enable *jumbo frames */
 	cb4 = (void *)get_zeroed_page(GFP_KERNEL);
 	if (!cb4) {
-		ehea_error("no mem for cb4");
+		pr_err("no mem for cb4\n");
 		ret = -ENOMEM;
 		goto out;
 	} else {
@@ -3175,13 +3165,13 @@ static struct device *ehea_register_port
 
 	ret = of_device_register(&port->ofdev);
 	if (ret) {
-		ehea_error("failed to register device. ret=%d", ret);
+		pr_err("failed to register device. ret=%d\n", ret);
 		goto out;
 	}
 
 	ret = device_create_file(&port->ofdev.dev, &dev_attr_log_port_id);
 	if (ret) {
-		ehea_error("failed to register attributes, ret=%d", ret);
+		pr_err("failed to register attributes, ret=%d\n", ret);
 		goto out_unreg_of_dev;
 	}
 
@@ -3231,7 +3221,7 @@ struct ehea_port *ehea_setup_single_port
 	dev = alloc_etherdev(sizeof(struct ehea_port));
 
 	if (!dev) {
-		ehea_error("no mem for net_device");
+		pr_err("no mem for net_device\n");
 		ret = -ENOMEM;
 		goto out_err;
 	}
@@ -3285,7 +3275,7 @@ struct ehea_port *ehea_setup_single_port
 
 	ret = register_netdev(dev);
 	if (ret) {
-		ehea_error("register_netdev failed. ret=%d", ret);
+		pr_err("register_netdev failed. ret=%d\n", ret);
 		goto out_unreg_port;
 	}
 
@@ -3293,11 +3283,10 @@ struct ehea_port *ehea_setup_single_port
 
 	ret = ehea_get_jumboframe_status(port, &jumbo);
 	if (ret)
-		ehea_error("failed determining jumbo frame status for %s",
-			   port->netdev->name);
+		netdev_err(dev, "failed determining jumbo frame status\n");
 
-	ehea_info("%s: Jumbo frames are %sabled", dev->name,
-		  jumbo == 1 ? "en" : "dis");
+	netdev_info(dev, "Jumbo frames are %sabled\n",
+		    jumbo == 1 ? "en" : "dis");
 
 	adapter->active_ports++;
 
@@ -3313,14 +3302,16 @@ out_free_ethdev:
 	free_netdev(dev);
 
 out_err:
-	ehea_error("setting up logical port with id=%d failed, ret=%d",
-		   logical_port_id, ret);
+	pr_err("setting up logical port with id=%d failed, ret=%d\n",
+	       logical_port_id, ret);
 	return NULL;
 }
 
 static void ehea_shutdown_single_port(struct ehea_port *port)
 {
 	struct ehea_adapter *adapter = port->adapter;
+
+	cancel_work_sync(&port->reset_task);
 	unregister_netdev(port->netdev);
 	ehea_unregister_port(port);
 	kfree(port->mc_list);
@@ -3342,13 +3333,13 @@ static int ehea_setup_ports(struct ehea_
 		dn_log_port_id = of_get_property(eth_dn, "ibm,hea-port-no",
 						 NULL);
 		if (!dn_log_port_id) {
-			ehea_error("bad device node: eth_dn name=%s",
-				   eth_dn->full_name);
+			pr_err("bad device node: eth_dn name=%s\n",
+			       eth_dn->full_name);
 			continue;
 		}
 
 		if (ehea_add_adapter_mr(adapter)) {
-			ehea_error("creating MR failed");
+			pr_err("creating MR failed\n");
 			of_node_put(eth_dn);
 			return -EIO;
 		}
@@ -3357,9 +3348,8 @@ static int ehea_setup_ports(struct ehea_
 							  *dn_log_port_id,
 							  eth_dn);
 		if (adapter->port[i])
-			ehea_info("%s -> logical port id #%d",
-				  adapter->port[i]->netdev->name,
-				  *dn_log_port_id);
+			netdev_info(adapter->port[i]->netdev,
+				    "logical port id #%d\n", *dn_log_port_id);
 		else
 			ehea_remove_adapter_mr(adapter);
 
@@ -3404,21 +3394,20 @@ static ssize_t ehea_probe_port(struct de
 	port = ehea_get_port(adapter, logical_port_id);
 
 	if (port) {
-		ehea_info("adding port with logical port id=%d failed. port "
-			  "already configured as %s.", logical_port_id,
-			  port->netdev->name);
+		netdev_info(port->netdev, "adding port with logical port id=%d failed: port already configured\n",
+			    logical_port_id);
 		return -EINVAL;
 	}
 
 	eth_dn = ehea_get_eth_dn(adapter, logical_port_id);
 
 	if (!eth_dn) {
-		ehea_info("no logical port with id %d found", logical_port_id);
+		pr_info("no logical port with id %d found\n", logical_port_id);
 		return -EINVAL;
 	}
 
 	if (ehea_add_adapter_mr(adapter)) {
-		ehea_error("creating MR failed");
+		pr_err("creating MR failed\n");
 		return -EIO;
 	}
 
@@ -3433,8 +3422,8 @@ static ssize_t ehea_probe_port(struct de
 				break;
 			}
 
-		ehea_info("added %s (logical port id=%d)", port->netdev->name,
-			  logical_port_id);
+		netdev_info(port->netdev, "added: (logical port id=%d)\n",
+			    logical_port_id);
 	} else {
 		ehea_remove_adapter_mr(adapter);
 		return -EIO;
@@ -3457,8 +3446,8 @@ static ssize_t ehea_remove_port(struct d
 	port = ehea_get_port(adapter, logical_port_id);
 
 	if (port) {
-		ehea_info("removed %s (logical port id=%d)", port->netdev->name,
-			  logical_port_id);
+		netdev_info(port->netdev, "removed: (logical port id=%d)\n",
+			    logical_port_id);
 
 		ehea_shutdown_single_port(port);
 
@@ -3468,8 +3457,8 @@ static ssize_t ehea_remove_port(struct d
 				break;
 			}
 	} else {
-		ehea_error("removing port with logical port id=%d failed. port "
-			   "not configured.", logical_port_id);
+		pr_err("removing port with logical port id=%d failed. port not configured.\n",
+		       logical_port_id);
 		return -EINVAL;
 	}
 
@@ -3506,7 +3495,7 @@ static int __devinit ehea_probe_adapter(
 	int ret;
 
 	if (!dev || !dev->dev.of_node) {
-		ehea_error("Invalid ibmebus device probed");
+		pr_err("Invalid ibmebus device probed\n");
 		return -EINVAL;
 	}
 
@@ -3610,8 +3599,6 @@ static int __devexit ehea_remove(struct
 
 	ehea_remove_device_sysfs(dev);
 
-	flush_scheduled_work();
-
 	ibmebus_free_irq(adapter->neq->attr.ist1, adapter);
 	tasklet_kill(&adapter->neq_tasklet);
 
@@ -3654,21 +3641,21 @@ static int ehea_mem_notifier(struct noti
 
 	switch (action) {
 	case MEM_CANCEL_OFFLINE:
-		ehea_info("memory offlining canceled");
+		pr_info("memory offlining canceled");
 		/* Readd canceled memory block */
 	case MEM_ONLINE:
-		ehea_info("memory is going online");
+		pr_info("memory is going online");
 		set_bit(__EHEA_STOP_XFER, &ehea_driver_flags);
 		if (ehea_add_sect_bmap(arg->start_pfn, arg->nr_pages))
 			goto out_unlock;
-		ehea_rereg_mrs(NULL);
+		ehea_rereg_mrs();
 		break;
 	case MEM_GOING_OFFLINE:
-		ehea_info("memory is going offline");
+		pr_info("memory is going offline");
 		set_bit(__EHEA_STOP_XFER, &ehea_driver_flags);
 		if (ehea_rem_sect_bmap(arg->start_pfn, arg->nr_pages))
 			goto out_unlock;
-		ehea_rereg_mrs(NULL);
+		ehea_rereg_mrs();
 		break;
 	default:
 		break;
@@ -3690,7 +3677,7 @@ static int ehea_reboot_notifier(struct n
 				unsigned long action, void *unused)
 {
 	if (action == SYS_RESTART) {
-		ehea_info("Reboot: freeing all eHEA resources");
+		pr_info("Reboot: freeing all eHEA resources\n");
 		ibmebus_unregister_driver(&ehea_driver);
 	}
 	return NOTIFY_DONE;
@@ -3706,22 +3693,22 @@ static int check_module_parm(void)
 
 	if ((rq1_entries < EHEA_MIN_ENTRIES_QP) ||
 	    (rq1_entries > EHEA_MAX_ENTRIES_RQ1)) {
-		ehea_info("Bad parameter: rq1_entries");
+		pr_info("Bad parameter: rq1_entries\n");
 		ret = -EINVAL;
 	}
 	if ((rq2_entries < EHEA_MIN_ENTRIES_QP) ||
 	    (rq2_entries > EHEA_MAX_ENTRIES_RQ2)) {
-		ehea_info("Bad parameter: rq2_entries");
+		pr_info("Bad parameter: rq2_entries\n");
 		ret = -EINVAL;
 	}
 	if ((rq3_entries < EHEA_MIN_ENTRIES_QP) ||
 	    (rq3_entries > EHEA_MAX_ENTRIES_RQ3)) {
-		ehea_info("Bad parameter: rq3_entries");
+		pr_info("Bad parameter: rq3_entries\n");
 		ret = -EINVAL;
 	}
 	if ((sq_entries < EHEA_MIN_ENTRIES_QP) ||
 	    (sq_entries > EHEA_MAX_ENTRIES_SQ)) {
-		ehea_info("Bad parameter: sq_entries");
+		pr_info("Bad parameter: sq_entries\n");
 		ret = -EINVAL;
 	}
 
@@ -3741,11 +3728,8 @@ int __init ehea_module_init(void)
 {
 	int ret;
 
-	printk(KERN_INFO "IBM eHEA ethernet device driver (Release %s)\n",
-	       DRV_VERSION);
-
+	pr_info("IBM eHEA ethernet device driver (Release %s)\n", DRV_VERSION);
 
-	INIT_WORK(&ehea_rereg_mr_task, ehea_rereg_mrs);
 	memset(&ehea_fw_handles, 0, sizeof(ehea_fw_handles));
 	memset(&ehea_bcmc_regs, 0, sizeof(ehea_bcmc_regs));
 
@@ -3762,27 +3746,27 @@ int __init ehea_module_init(void)
 
 	ret = register_reboot_notifier(&ehea_reboot_nb);
 	if (ret)
-		ehea_info("failed registering reboot notifier");
+		pr_info("failed registering reboot notifier\n");
 
 	ret = register_memory_notifier(&ehea_mem_nb);
 	if (ret)
-		ehea_info("failed registering memory remove notifier");
+		pr_info("failed registering memory remove notifier\n");
 
 	ret = crash_shutdown_register(ehea_crash_handler);
 	if (ret)
-		ehea_info("failed registering crash handler");
+		pr_info("failed registering crash handler\n");
 
 	ret = ibmebus_register_driver(&ehea_driver);
 	if (ret) {
-		ehea_error("failed registering eHEA device driver on ebus");
+		pr_err("failed registering eHEA device driver on ebus\n");
 		goto out2;
 	}
 
 	ret = driver_create_file(&ehea_driver.driver,
 				 &driver_attr_capabilities);
 	if (ret) {
-		ehea_error("failed to register capabilities attribute, ret=%d",
-			   ret);
+		pr_err("failed to register capabilities attribute, ret=%d\n",
+		       ret);
 		goto out3;
 	}
 
@@ -3802,13 +3786,12 @@ static void __exit ehea_module_exit(void
 {
 	int ret;
 
-	flush_scheduled_work();
 	driver_remove_file(&ehea_driver.driver, &driver_attr_capabilities);
 	ibmebus_unregister_driver(&ehea_driver);
 	unregister_reboot_notifier(&ehea_reboot_nb);
 	ret = crash_shutdown_unregister(ehea_crash_handler);
 	if (ret)
-		ehea_info("failed unregistering crash handler");
+		pr_info("failed unregistering crash handler\n");
 	unregister_memory_notifier(&ehea_mem_nb);
 	kfree(ehea_fw_handles.arr);
 	kfree(ehea_bcmc_regs.arr);
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/ehea/ehea_phyp.c linux-libre-2.6.38-gnu1/drivers/net/ehea/ehea_phyp.c
--- linux-libre-2.6.37-gnu1/drivers/net/ehea/ehea_phyp.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/ehea/ehea_phyp.c	2011-03-14 21:20:32.000000000 -0400
@@ -26,6 +26,8 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include "ehea_phyp.h"
 
 
@@ -67,12 +69,11 @@ static long ehea_plpar_hcall_norets(unsi
 		}
 
 		if (ret < H_SUCCESS)
-			ehea_error("opcode=%lx ret=%lx"
-				   " arg1=%lx arg2=%lx arg3=%lx arg4=%lx"
-				   " arg5=%lx arg6=%lx arg7=%lx ",
-				   opcode, ret,
-				   arg1, arg2, arg3, arg4, arg5,
-				   arg6, arg7);
+			pr_err("opcode=%lx ret=%lx"
+			       " arg1=%lx arg2=%lx arg3=%lx arg4=%lx"
+			       " arg5=%lx arg6=%lx arg7=%lx\n",
+			       opcode, ret,
+			       arg1, arg2, arg3, arg4, arg5, arg6, arg7);
 
 		return ret;
 	}
@@ -114,19 +115,18 @@ static long ehea_plpar_hcall9(unsigned l
 		    && (((cb_cat == H_PORT_CB4) && ((arg3 == H_PORT_CB4_JUMBO)
 		    || (arg3 == H_PORT_CB4_SPEED))) || ((cb_cat == H_PORT_CB7)
 		    && (arg3 == H_PORT_CB7_DUCQPN)))))
-			ehea_error("opcode=%lx ret=%lx"
-				   " arg1=%lx arg2=%lx arg3=%lx arg4=%lx"
-				   " arg5=%lx arg6=%lx arg7=%lx arg8=%lx"
-				   " arg9=%lx"
-				   " out1=%lx out2=%lx out3=%lx out4=%lx"
-				   " out5=%lx out6=%lx out7=%lx out8=%lx"
-				   " out9=%lx",
-				   opcode, ret,
-				   arg1, arg2, arg3, arg4, arg5,
-				   arg6, arg7, arg8, arg9,
-				   outs[0], outs[1], outs[2], outs[3],
-				   outs[4], outs[5], outs[6], outs[7],
-				   outs[8]);
+			pr_err("opcode=%lx ret=%lx"
+			       " arg1=%lx arg2=%lx arg3=%lx arg4=%lx"
+			       " arg5=%lx arg6=%lx arg7=%lx arg8=%lx"
+			       " arg9=%lx"
+			       " out1=%lx out2=%lx out3=%lx out4=%lx"
+			       " out5=%lx out6=%lx out7=%lx out8=%lx"
+			       " out9=%lx\n",
+			       opcode, ret,
+			       arg1, arg2, arg3, arg4, arg5,
+			       arg6, arg7, arg8, arg9,
+			       outs[0], outs[1], outs[2], outs[3], outs[4],
+			       outs[5], outs[6], outs[7], outs[8]);
 		return ret;
 	}
 
@@ -515,7 +515,7 @@ u64 ehea_h_register_rpage_mr(const u64 a
 			     const u64 log_pageaddr, const u64 count)
 {
 	if ((count > 1) && (log_pageaddr & ~PAGE_MASK)) {
-		ehea_error("not on pageboundary");
+		pr_err("not on pageboundary\n");
 		return H_PARAMETER;
 	}
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/ehea/ehea_qmr.c linux-libre-2.6.38-gnu1/drivers/net/ehea/ehea_qmr.c
--- linux-libre-2.6.37-gnu1/drivers/net/ehea/ehea_qmr.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/ehea/ehea_qmr.c	2011-03-14 21:20:32.000000000 -0400
@@ -26,6 +26,8 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/mm.h>
 #include <linux/slab.h>
 #include "ehea.h"
@@ -45,7 +47,7 @@ static void *hw_qpageit_get_inc(struct h
 		queue->current_q_offset -= queue->pagesize;
 		retvalue = NULL;
 	} else if (((u64) retvalue) & (EHEA_PAGESIZE-1)) {
-		ehea_error("not on pageboundary");
+		pr_err("not on pageboundary\n");
 		retvalue = NULL;
 	}
 	return retvalue;
@@ -58,15 +60,15 @@ static int hw_queue_ctor(struct hw_queue
 	int i, k;
 
 	if ((pagesize > PAGE_SIZE) || (!pages_per_kpage)) {
-		ehea_error("pagesize conflict! kernel pagesize=%d, "
-			   "ehea pagesize=%d", (int)PAGE_SIZE, (int)pagesize);
+		pr_err("pagesize conflict! kernel pagesize=%d, ehea pagesize=%d\n",
+		       (int)PAGE_SIZE, (int)pagesize);
 		return -EINVAL;
 	}
 
 	queue->queue_length = nr_of_pages * pagesize;
 	queue->queue_pages = kmalloc(nr_of_pages * sizeof(void *), GFP_KERNEL);
 	if (!queue->queue_pages) {
-		ehea_error("no mem for queue_pages");
+		pr_err("no mem for queue_pages\n");
 		return -ENOMEM;
 	}
 
@@ -130,7 +132,7 @@ struct ehea_cq *ehea_create_cq(struct eh
 
 	cq = kzalloc(sizeof(*cq), GFP_KERNEL);
 	if (!cq) {
-		ehea_error("no mem for cq");
+		pr_err("no mem for cq\n");
 		goto out_nomem;
 	}
 
@@ -147,7 +149,7 @@ struct ehea_cq *ehea_create_cq(struct eh
 	hret = ehea_h_alloc_resource_cq(adapter->handle, &cq->attr,
 					&cq->fw_handle, &cq->epas);
 	if (hret != H_SUCCESS) {
-		ehea_error("alloc_resource_cq failed");
+		pr_err("alloc_resource_cq failed\n");
 		goto out_freemem;
 	}
 
@@ -159,7 +161,7 @@ struct ehea_cq *ehea_create_cq(struct eh
 	for (counter = 0; counter < cq->attr.nr_pages; counter++) {
 		vpage = hw_qpageit_get_inc(&cq->hw_queue);
 		if (!vpage) {
-			ehea_error("hw_qpageit_get_inc failed");
+			pr_err("hw_qpageit_get_inc failed\n");
 			goto out_kill_hwq;
 		}
 
@@ -168,9 +170,8 @@ struct ehea_cq *ehea_create_cq(struct eh
 					     0, EHEA_CQ_REGISTER_ORIG,
 					     cq->fw_handle, rpage, 1);
 		if (hret < H_SUCCESS) {
-			ehea_error("register_rpage_cq failed ehea_cq=%p "
-				   "hret=%llx counter=%i act_pages=%i",
-				   cq, hret, counter, cq->attr.nr_pages);
+			pr_err("register_rpage_cq failed ehea_cq=%p hret=%llx counter=%i act_pages=%i\n",
+			       cq, hret, counter, cq->attr.nr_pages);
 			goto out_kill_hwq;
 		}
 
@@ -178,14 +179,14 @@ struct ehea_cq *ehea_create_cq(struct eh
 			vpage = hw_qpageit_get_inc(&cq->hw_queue);
 
 			if ((hret != H_SUCCESS) || (vpage)) {
-				ehea_error("registration of pages not "
-					   "complete hret=%llx\n", hret);
+				pr_err("registration of pages not complete hret=%llx\n",
+				       hret);
 				goto out_kill_hwq;
 			}
 		} else {
 			if (hret != H_PAGE_REGISTERED) {
-				ehea_error("CQ: registration of page failed "
-					   "hret=%llx\n", hret);
+				pr_err("CQ: registration of page failed hret=%llx\n",
+				       hret);
 				goto out_kill_hwq;
 			}
 		}
@@ -241,7 +242,7 @@ int ehea_destroy_cq(struct ehea_cq *cq)
 	}
 
 	if (hret != H_SUCCESS) {
-		ehea_error("destroy CQ failed");
+		pr_err("destroy CQ failed\n");
 		return -EIO;
 	}
 
@@ -259,7 +260,7 @@ struct ehea_eq *ehea_create_eq(struct eh
 
 	eq = kzalloc(sizeof(*eq), GFP_KERNEL);
 	if (!eq) {
-		ehea_error("no mem for eq");
+		pr_err("no mem for eq\n");
 		return NULL;
 	}
 
@@ -272,21 +273,21 @@ struct ehea_eq *ehea_create_eq(struct eh
 	hret = ehea_h_alloc_resource_eq(adapter->handle,
 					&eq->attr, &eq->fw_handle);
 	if (hret != H_SUCCESS) {
-		ehea_error("alloc_resource_eq failed");
+		pr_err("alloc_resource_eq failed\n");
 		goto out_freemem;
 	}
 
 	ret = hw_queue_ctor(&eq->hw_queue, eq->attr.nr_pages,
 			    EHEA_PAGESIZE, sizeof(struct ehea_eqe));
 	if (ret) {
-		ehea_error("can't allocate eq pages");
+		pr_err("can't allocate eq pages\n");
 		goto out_freeres;
 	}
 
 	for (i = 0; i < eq->attr.nr_pages; i++) {
 		vpage = hw_qpageit_get_inc(&eq->hw_queue);
 		if (!vpage) {
-			ehea_error("hw_qpageit_get_inc failed");
+			pr_err("hw_qpageit_get_inc failed\n");
 			hret = H_RESOURCE;
 			goto out_kill_hwq;
 		}
@@ -370,7 +371,7 @@ int ehea_destroy_eq(struct ehea_eq *eq)
 	}
 
 	if (hret != H_SUCCESS) {
-		ehea_error("destroy EQ failed");
+		pr_err("destroy EQ failed\n");
 		return -EIO;
 	}
 
@@ -395,7 +396,7 @@ int ehea_qp_alloc_register(struct ehea_q
 	for (cnt = 0; cnt < nr_pages; cnt++) {
 		vpage = hw_qpageit_get_inc(hw_queue);
 		if (!vpage) {
-			ehea_error("hw_qpageit_get_inc failed");
+			pr_err("hw_qpageit_get_inc failed\n");
 			goto out_kill_hwq;
 		}
 		rpage = virt_to_abs(vpage);
@@ -403,7 +404,7 @@ int ehea_qp_alloc_register(struct ehea_q
 					     0, h_call_q_selector,
 					     qp->fw_handle, rpage, 1);
 		if (hret < H_SUCCESS) {
-			ehea_error("register_rpage_qp failed");
+			pr_err("register_rpage_qp failed\n");
 			goto out_kill_hwq;
 		}
 	}
@@ -432,7 +433,7 @@ struct ehea_qp *ehea_create_qp(struct eh
 
 	qp = kzalloc(sizeof(*qp), GFP_KERNEL);
 	if (!qp) {
-		ehea_error("no mem for qp");
+		pr_err("no mem for qp\n");
 		return NULL;
 	}
 
@@ -441,7 +442,7 @@ struct ehea_qp *ehea_create_qp(struct eh
 	hret = ehea_h_alloc_resource_qp(adapter->handle, init_attr, pd,
 					&qp->fw_handle, &qp->epas);
 	if (hret != H_SUCCESS) {
-		ehea_error("ehea_h_alloc_resource_qp failed");
+		pr_err("ehea_h_alloc_resource_qp failed\n");
 		goto out_freemem;
 	}
 
@@ -455,7 +456,7 @@ struct ehea_qp *ehea_create_qp(struct eh
 				     init_attr->act_wqe_size_enc_sq, adapter,
 				     0);
 	if (ret) {
-		ehea_error("can't register for sq ret=%x", ret);
+		pr_err("can't register for sq ret=%x\n", ret);
 		goto out_freeres;
 	}
 
@@ -465,7 +466,7 @@ struct ehea_qp *ehea_create_qp(struct eh
 				     init_attr->act_wqe_size_enc_rq1,
 				     adapter, 1);
 	if (ret) {
-		ehea_error("can't register for rq1 ret=%x", ret);
+		pr_err("can't register for rq1 ret=%x\n", ret);
 		goto out_kill_hwsq;
 	}
 
@@ -476,7 +477,7 @@ struct ehea_qp *ehea_create_qp(struct eh
 					     init_attr->act_wqe_size_enc_rq2,
 					     adapter, 2);
 		if (ret) {
-			ehea_error("can't register for rq2 ret=%x", ret);
+			pr_err("can't register for rq2 ret=%x\n", ret);
 			goto out_kill_hwr1q;
 		}
 	}
@@ -488,7 +489,7 @@ struct ehea_qp *ehea_create_qp(struct eh
 					     init_attr->act_wqe_size_enc_rq3,
 					     adapter, 3);
 		if (ret) {
-			ehea_error("can't register for rq3 ret=%x", ret);
+			pr_err("can't register for rq3 ret=%x\n", ret);
 			goto out_kill_hwr2q;
 		}
 	}
@@ -553,7 +554,7 @@ int ehea_destroy_qp(struct ehea_qp *qp)
 	}
 
 	if (hret != H_SUCCESS) {
-		ehea_error("destroy QP failed");
+		pr_err("destroy QP failed\n");
 		return -EIO;
 	}
 
@@ -842,7 +843,7 @@ static u64 ehea_reg_mr_section(int top,
 		    (hret != H_PAGE_REGISTERED)) {
 			ehea_h_free_resource(adapter->handle, mr->handle,
 					     FORCE_FREE);
-			ehea_error("register_rpage_mr failed");
+			pr_err("register_rpage_mr failed\n");
 			return hret;
 		}
 	}
@@ -896,7 +897,7 @@ int ehea_reg_kernel_mr(struct ehea_adapt
 
 	pt = (void *)get_zeroed_page(GFP_KERNEL);
 	if (!pt) {
-		ehea_error("no mem");
+		pr_err("no mem\n");
 		ret = -ENOMEM;
 		goto out;
 	}
@@ -906,14 +907,14 @@ int ehea_reg_kernel_mr(struct ehea_adapt
 					&mr->handle, &mr->lkey);
 
 	if (hret != H_SUCCESS) {
-		ehea_error("alloc_resource_mr failed");
+		pr_err("alloc_resource_mr failed\n");
 		ret = -EIO;
 		goto out;
 	}
 
 	if (!ehea_bmap) {
 		ehea_h_free_resource(adapter->handle, mr->handle, FORCE_FREE);
-		ehea_error("no busmap available");
+		pr_err("no busmap available\n");
 		ret = -EIO;
 		goto out;
 	}
@@ -929,7 +930,7 @@ int ehea_reg_kernel_mr(struct ehea_adapt
 
 	if (hret != H_SUCCESS) {
 		ehea_h_free_resource(adapter->handle, mr->handle, FORCE_FREE);
-		ehea_error("registering mr failed");
+		pr_err("registering mr failed\n");
 		ret = -EIO;
 		goto out;
 	}
@@ -952,7 +953,7 @@ int ehea_rem_mr(struct ehea_mr *mr)
 	hret = ehea_h_free_resource(mr->adapter->handle, mr->handle,
 				    FORCE_FREE);
 	if (hret != H_SUCCESS) {
-		ehea_error("destroy MR failed");
+		pr_err("destroy MR failed\n");
 		return -EIO;
 	}
 
@@ -987,14 +988,14 @@ void print_error_data(u64 *data)
 		length = EHEA_PAGESIZE;
 
 	if (type == EHEA_AER_RESTYPE_QP)
-		ehea_error("QP (resource=%llX) state: AER=0x%llX, AERR=0x%llX, "
-			   "port=%llX", resource, data[6], data[12], data[22]);
+		pr_err("QP (resource=%llX) state: AER=0x%llX, AERR=0x%llX, port=%llX\n",
+		       resource, data[6], data[12], data[22]);
 	else if (type == EHEA_AER_RESTYPE_CQ)
-		ehea_error("CQ (resource=%llX) state: AER=0x%llX", resource,
-			   data[6]);
+		pr_err("CQ (resource=%llX) state: AER=0x%llX\n",
+		       resource, data[6]);
 	else if (type == EHEA_AER_RESTYPE_EQ)
-		ehea_error("EQ (resource=%llX) state: AER=0x%llX", resource,
-			   data[6]);
+		pr_err("EQ (resource=%llX) state: AER=0x%llX\n",
+		       resource, data[6]);
 
 	ehea_dump(data, length, "error data");
 }
@@ -1008,7 +1009,7 @@ u64 ehea_error_data(struct ehea_adapter
 
 	rblock = (void *)get_zeroed_page(GFP_KERNEL);
 	if (!rblock) {
-		ehea_error("Cannot allocate rblock memory.");
+		pr_err("Cannot allocate rblock memory\n");
 		goto out;
 	}
 
@@ -1020,9 +1021,9 @@ u64 ehea_error_data(struct ehea_adapter
 		*aerr = rblock[12];
 		print_error_data(rblock);
 	} else if (ret == H_R_STATE) {
-		ehea_error("No error data available: %llX.", res_handle);
+		pr_err("No error data available: %llX\n", res_handle);
 	} else
-		ehea_error("Error data could not be fetched: %llX", res_handle);
+		pr_err("Error data could not be fetched: %llX\n", res_handle);
 
 	free_page((unsigned long)rblock);
 out:
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/enc28j60.c linux-libre-2.6.38-gnu1/drivers/net/enc28j60.c
--- linux-libre-2.6.37-gnu1/drivers/net/enc28j60.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/enc28j60.c	2011-03-14 21:20:32.000000000 -0400
@@ -812,7 +812,7 @@ static void enc28j60_read_tsv(struct enc
 	if (netif_msg_hw(priv))
 		printk(KERN_DEBUG DRV_NAME ": reading TSV at addr:0x%04x\n",
 			 endptr + 1);
-	enc28j60_mem_read(priv, endptr + 1, sizeof(tsv), tsv);
+	enc28j60_mem_read(priv, endptr + 1, TSV_SIZE, tsv);
 }
 
 static void enc28j60_dump_tsv(struct enc28j60_net *priv, const char *msg,
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/enic/enic.h linux-libre-2.6.38-gnu1/drivers/net/enic/enic.h
--- linux-libre-2.6.37-gnu1/drivers/net/enic/enic.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/enic/enic.h	2011-03-14 21:20:32.000000000 -0400
@@ -32,7 +32,7 @@
 
 #define DRV_NAME		"enic"
 #define DRV_DESCRIPTION		"Cisco VIC Ethernet NIC Driver"
-#define DRV_VERSION		"1.4.1.6"
+#define DRV_VERSION		"1.4.1.10"
 #define DRV_COPYRIGHT		"Copyright 2008-2010 Cisco Systems, Inc"
 
 #define ENIC_BARS_MAX		6
@@ -61,6 +61,8 @@ struct enic_port_profile {
 	char name[PORT_PROFILE_MAX];
 	u8 instance_uuid[PORT_UUID_MAX];
 	u8 host_uuid[PORT_UUID_MAX];
+	u8 vf_mac[ETH_ALEN];
+	u8 mac_addr[ETH_ALEN];
 };
 
 /* Per-instance private data structure */
@@ -78,8 +80,10 @@ struct enic {
 	spinlock_t devcmd_lock;
 	u8 mac_addr[ETH_ALEN];
 	u8 mc_addr[ENIC_MULTICAST_PERFECT_FILTERS][ETH_ALEN];
+	u8 uc_addr[ENIC_UNICAST_PERFECT_FILTERS][ETH_ALEN];
 	unsigned int flags;
 	unsigned int mc_count;
+	unsigned int uc_count;
 	int csum_rx_enabled;
 	u32 port_mtu;
 	u32 rx_coalesce_usecs;
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/enic/enic_main.c linux-libre-2.6.38-gnu1/drivers/net/enic/enic_main.c
--- linux-libre-2.6.37-gnu1/drivers/net/enic/enic_main.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/enic/enic_main.c	2011-03-14 21:20:32.000000000 -0400
@@ -702,7 +702,7 @@ static inline void enic_queue_wq_skb_csu
 {
 	unsigned int head_len = skb_headlen(skb);
 	unsigned int len_left = skb->len - head_len;
-	unsigned int hdr_len = skb_transport_offset(skb);
+	unsigned int hdr_len = skb_checksum_start_offset(skb);
 	unsigned int csum_offset = hdr_len + skb->csum_offset;
 	int eop = (len_left == 0);
 
@@ -1002,7 +1002,7 @@ static int enic_dev_packet_filter(struct
 	return err;
 }
 
-static int enic_dev_add_multicast_addr(struct enic *enic, u8 *addr)
+static int enic_dev_add_addr(struct enic *enic, u8 *addr)
 {
 	int err;
 
@@ -1013,7 +1013,7 @@ static int enic_dev_add_multicast_addr(s
 	return err;
 }
 
-static int enic_dev_del_multicast_addr(struct enic *enic, u8 *addr)
+static int enic_dev_del_addr(struct enic *enic, u8 *addr)
 {
 	int err;
 
@@ -1024,29 +1024,19 @@ static int enic_dev_del_multicast_addr(s
 	return err;
 }
 
-/* netif_tx_lock held, BHs disabled */
-static void enic_set_multicast_list(struct net_device *netdev)
+static void enic_add_multicast_addr_list(struct enic *enic)
 {
-	struct enic *enic = netdev_priv(netdev);
+	struct net_device *netdev = enic->netdev;
 	struct netdev_hw_addr *ha;
-	int directed = 1;
-	int multicast = (netdev->flags & IFF_MULTICAST) ? 1 : 0;
-	int broadcast = (netdev->flags & IFF_BROADCAST) ? 1 : 0;
-	int promisc = (netdev->flags & IFF_PROMISC) ? 1 : 0;
 	unsigned int mc_count = netdev_mc_count(netdev);
-	int allmulti = (netdev->flags & IFF_ALLMULTI) ||
-		mc_count > ENIC_MULTICAST_PERFECT_FILTERS;
-	unsigned int flags = netdev->flags | (allmulti ? IFF_ALLMULTI : 0);
 	u8 mc_addr[ENIC_MULTICAST_PERFECT_FILTERS][ETH_ALEN];
 	unsigned int i, j;
 
-	if (mc_count > ENIC_MULTICAST_PERFECT_FILTERS)
+	if (mc_count > ENIC_MULTICAST_PERFECT_FILTERS) {
+		netdev_warn(netdev, "Registering only %d out of %d "
+			"multicast addresses\n",
+			ENIC_MULTICAST_PERFECT_FILTERS, mc_count);
 		mc_count = ENIC_MULTICAST_PERFECT_FILTERS;
-
-	if (enic->flags != flags) {
-		enic->flags = flags;
-		enic_dev_packet_filter(enic, directed,
-			multicast, broadcast, promisc, allmulti);
 	}
 
 	/* Is there an easier way?  Trying to minimize to
@@ -1068,7 +1058,7 @@ static void enic_set_multicast_list(stru
 				mc_addr[j]) == 0)
 				break;
 		if (j == mc_count)
-			enic_dev_del_multicast_addr(enic, enic->mc_addr[i]);
+			enic_dev_del_addr(enic, enic->mc_addr[i]);
 	}
 
 	for (i = 0; i < mc_count; i++) {
@@ -1077,7 +1067,7 @@ static void enic_set_multicast_list(stru
 				enic->mc_addr[j]) == 0)
 				break;
 		if (j == enic->mc_count)
-			enic_dev_add_multicast_addr(enic, mc_addr[i]);
+			enic_dev_add_addr(enic, mc_addr[i]);
 	}
 
 	/* Save the list to compare against next time
@@ -1089,6 +1079,89 @@ static void enic_set_multicast_list(stru
 	enic->mc_count = mc_count;
 }
 
+static void enic_add_unicast_addr_list(struct enic *enic)
+{
+	struct net_device *netdev = enic->netdev;
+	struct netdev_hw_addr *ha;
+	unsigned int uc_count = netdev_uc_count(netdev);
+	u8 uc_addr[ENIC_UNICAST_PERFECT_FILTERS][ETH_ALEN];
+	unsigned int i, j;
+
+	if (uc_count > ENIC_UNICAST_PERFECT_FILTERS) {
+		netdev_warn(netdev, "Registering only %d out of %d "
+			"unicast addresses\n",
+			ENIC_UNICAST_PERFECT_FILTERS, uc_count);
+		uc_count = ENIC_UNICAST_PERFECT_FILTERS;
+	}
+
+	/* Is there an easier way?  Trying to minimize to
+	 * calls to add/del unicast addrs.  We keep the
+	 * addrs from the last call in enic->uc_addr and
+	 * look for changes to add/del.
+	 */
+
+	i = 0;
+	netdev_for_each_uc_addr(ha, netdev) {
+		if (i == uc_count)
+			break;
+		memcpy(uc_addr[i++], ha->addr, ETH_ALEN);
+	}
+
+	for (i = 0; i < enic->uc_count; i++) {
+		for (j = 0; j < uc_count; j++)
+			if (compare_ether_addr(enic->uc_addr[i],
+				uc_addr[j]) == 0)
+				break;
+		if (j == uc_count)
+			enic_dev_del_addr(enic, enic->uc_addr[i]);
+	}
+
+	for (i = 0; i < uc_count; i++) {
+		for (j = 0; j < enic->uc_count; j++)
+			if (compare_ether_addr(uc_addr[i],
+				enic->uc_addr[j]) == 0)
+				break;
+		if (j == enic->uc_count)
+			enic_dev_add_addr(enic, uc_addr[i]);
+	}
+
+	/* Save the list to compare against next time
+	 */
+
+	for (i = 0; i < uc_count; i++)
+		memcpy(enic->uc_addr[i], uc_addr[i], ETH_ALEN);
+
+	enic->uc_count = uc_count;
+}
+
+/* netif_tx_lock held, BHs disabled */
+static void enic_set_rx_mode(struct net_device *netdev)
+{
+	struct enic *enic = netdev_priv(netdev);
+	int directed = 1;
+	int multicast = (netdev->flags & IFF_MULTICAST) ? 1 : 0;
+	int broadcast = (netdev->flags & IFF_BROADCAST) ? 1 : 0;
+	int promisc = (netdev->flags & IFF_PROMISC) ||
+		netdev_uc_count(netdev) > ENIC_UNICAST_PERFECT_FILTERS;
+	int allmulti = (netdev->flags & IFF_ALLMULTI) ||
+		netdev_mc_count(netdev) > ENIC_MULTICAST_PERFECT_FILTERS;
+	unsigned int flags = netdev->flags |
+		(allmulti ? IFF_ALLMULTI : 0) |
+		(promisc ? IFF_PROMISC : 0);
+
+	if (enic->flags != flags) {
+		enic->flags = flags;
+		enic_dev_packet_filter(enic, directed,
+			multicast, broadcast, promisc, allmulti);
+	}
+
+	if (!promisc) {
+		enic_add_unicast_addr_list(enic);
+		if (!allmulti)
+			enic_add_multicast_addr_list(enic);
+	}
+}
+
 /* rtnl lock is held */
 static void enic_vlan_rx_register(struct net_device *netdev,
 	struct vlan_group *vlan_group)
@@ -1158,11 +1231,31 @@ static int enic_dev_init_done(struct eni
 	return err;
 }
 
+static int enic_set_vf_mac(struct net_device *netdev, int vf, u8 *mac)
+{
+	struct enic *enic = netdev_priv(netdev);
+
+	if (vf != PORT_SELF_VF)
+		return -EOPNOTSUPP;
+
+	/* Ignore the vf argument for now. We can assume the request
+	 * is coming on a vf.
+	 */
+	if (is_valid_ether_addr(mac)) {
+		memcpy(enic->pp.vf_mac, mac, ETH_ALEN);
+		return 0;
+	} else
+		return -EINVAL;
+}
+
 static int enic_set_port_profile(struct enic *enic, u8 *mac)
 {
 	struct vic_provinfo *vp;
 	u8 oui[3] = VIC_PROVINFO_CISCO_OUI;
+	u16 os_type = VIC_GENERIC_PROV_OS_TYPE_LINUX;
 	char uuid_str[38];
+	char client_mac_str[18];
+	u8 *client_mac;
 	int err;
 
 	err = enic_vnic_dev_deinit(enic);
@@ -1180,46 +1273,63 @@ static int enic_set_port_profile(struct
 			return -EADDRNOTAVAIL;
 
 		vp = vic_provinfo_alloc(GFP_KERNEL, oui,
-			VIC_PROVINFO_LINUX_TYPE);
+			VIC_PROVINFO_GENERIC_TYPE);
 		if (!vp)
 			return -ENOMEM;
 
 		vic_provinfo_add_tlv(vp,
-			VIC_LINUX_PROV_TLV_PORT_PROFILE_NAME_STR,
+			VIC_GENERIC_PROV_TLV_PORT_PROFILE_NAME_STR,
 			strlen(enic->pp.name) + 1, enic->pp.name);
 
+		if (!is_zero_ether_addr(enic->pp.mac_addr))
+			client_mac = enic->pp.mac_addr;
+		else
+			client_mac = mac;
+
 		vic_provinfo_add_tlv(vp,
-			VIC_LINUX_PROV_TLV_CLIENT_MAC_ADDR,
-			ETH_ALEN, mac);
+			VIC_GENERIC_PROV_TLV_CLIENT_MAC_ADDR,
+			ETH_ALEN, client_mac);
+
+		sprintf(client_mac_str, "%pM", client_mac);
+		vic_provinfo_add_tlv(vp,
+			VIC_GENERIC_PROV_TLV_CLUSTER_PORT_UUID_STR,
+			sizeof(client_mac_str), client_mac_str);
 
 		if (enic->pp.set & ENIC_SET_INSTANCE) {
 			sprintf(uuid_str, "%pUB", enic->pp.instance_uuid);
 			vic_provinfo_add_tlv(vp,
-				VIC_LINUX_PROV_TLV_CLIENT_UUID_STR,
+				VIC_GENERIC_PROV_TLV_CLIENT_UUID_STR,
 				sizeof(uuid_str), uuid_str);
 		}
 
 		if (enic->pp.set & ENIC_SET_HOST) {
 			sprintf(uuid_str, "%pUB", enic->pp.host_uuid);
 			vic_provinfo_add_tlv(vp,
-				VIC_LINUX_PROV_TLV_HOST_UUID_STR,
+				VIC_GENERIC_PROV_TLV_HOST_UUID_STR,
 				sizeof(uuid_str), uuid_str);
 		}
 
+		os_type = htons(os_type);
+		vic_provinfo_add_tlv(vp,
+			VIC_GENERIC_PROV_TLV_OS_TYPE,
+			sizeof(os_type), &os_type);
+
 		err = enic_dev_init_prov(enic, vp);
 		vic_provinfo_free(vp);
 		if (err)
 			return err;
+
+		enic->pp.set |= ENIC_SET_APPLIED;
 		break;
 
 	case PORT_REQUEST_DISASSOCIATE:
+		enic->pp.set &= ~ENIC_SET_APPLIED;
 		break;
 
 	default:
 		return -EINVAL;
 	}
 
-	enic->pp.set |= ENIC_SET_APPLIED;
 	return 0;
 }
 
@@ -1227,29 +1337,31 @@ static int enic_set_vf_port(struct net_d
 	struct nlattr *port[])
 {
 	struct enic *enic = netdev_priv(netdev);
+	struct enic_port_profile new_pp;
+	int err = 0;
 
-	memset(&enic->pp, 0, sizeof(enic->pp));
+	memset(&new_pp, 0, sizeof(new_pp));
 
 	if (port[IFLA_PORT_REQUEST]) {
-		enic->pp.set |= ENIC_SET_REQUEST;
-		enic->pp.request = nla_get_u8(port[IFLA_PORT_REQUEST]);
+		new_pp.set |= ENIC_SET_REQUEST;
+		new_pp.request = nla_get_u8(port[IFLA_PORT_REQUEST]);
 	}
 
 	if (port[IFLA_PORT_PROFILE]) {
-		enic->pp.set |= ENIC_SET_NAME;
-		memcpy(enic->pp.name, nla_data(port[IFLA_PORT_PROFILE]),
+		new_pp.set |= ENIC_SET_NAME;
+		memcpy(new_pp.name, nla_data(port[IFLA_PORT_PROFILE]),
 			PORT_PROFILE_MAX);
 	}
 
 	if (port[IFLA_PORT_INSTANCE_UUID]) {
-		enic->pp.set |= ENIC_SET_INSTANCE;
-		memcpy(enic->pp.instance_uuid,
+		new_pp.set |= ENIC_SET_INSTANCE;
+		memcpy(new_pp.instance_uuid,
 			nla_data(port[IFLA_PORT_INSTANCE_UUID]), PORT_UUID_MAX);
 	}
 
 	if (port[IFLA_PORT_HOST_UUID]) {
-		enic->pp.set |= ENIC_SET_HOST;
-		memcpy(enic->pp.host_uuid,
+		new_pp.set |= ENIC_SET_HOST;
+		memcpy(new_pp.host_uuid,
 			nla_data(port[IFLA_PORT_HOST_UUID]), PORT_UUID_MAX);
 	}
 
@@ -1257,21 +1369,39 @@ static int enic_set_vf_port(struct net_d
 	if (vf != PORT_SELF_VF)
 		return -EOPNOTSUPP;
 
-	if (!(enic->pp.set & ENIC_SET_REQUEST))
+	if (!(new_pp.set & ENIC_SET_REQUEST))
 		return -EOPNOTSUPP;
 
-	if (enic->pp.request == PORT_REQUEST_ASSOCIATE) {
-
-		/* If the interface mac addr hasn't been assigned,
-		 * assign a random mac addr before setting port-
-		 * profile.
-		 */
+	if (new_pp.request == PORT_REQUEST_ASSOCIATE) {
+		/* Special case handling */
+		if (!is_zero_ether_addr(enic->pp.vf_mac))
+			memcpy(new_pp.mac_addr, enic->pp.vf_mac, ETH_ALEN);
 
 		if (is_zero_ether_addr(netdev->dev_addr))
 			random_ether_addr(netdev->dev_addr);
+	} else if (new_pp.request == PORT_REQUEST_DISASSOCIATE) {
+		if (!is_zero_ether_addr(enic->pp.mac_addr))
+			enic_dev_del_addr(enic, enic->pp.mac_addr);
 	}
 
-	return enic_set_port_profile(enic, netdev->dev_addr);
+	memcpy(&enic->pp, &new_pp, sizeof(struct enic_port_profile));
+
+	err = enic_set_port_profile(enic, netdev->dev_addr);
+	if (err)
+		goto set_port_profile_cleanup;
+
+	if (!is_zero_ether_addr(enic->pp.mac_addr))
+		enic_dev_add_addr(enic, enic->pp.mac_addr);
+
+set_port_profile_cleanup:
+	memset(enic->pp.vf_mac, 0, ETH_ALEN);
+
+	if (err || enic->pp.request == PORT_REQUEST_DISASSOCIATE) {
+		memset(netdev->dev_addr, 0, ETH_ALEN);
+		memset(enic->pp.mac_addr, 0, ETH_ALEN);
+	}
+
+	return err;
 }
 
 static int enic_get_vf_port(struct net_device *netdev, int vf,
@@ -1851,8 +1981,11 @@ static int enic_open(struct net_device *
 	for (i = 0; i < enic->rq_count; i++)
 		vnic_rq_enable(&enic->rq[i]);
 
-	enic_dev_add_station_addr(enic);
-	enic_set_multicast_list(netdev);
+	if (enic_is_dynamic(enic) && !is_zero_ether_addr(enic->pp.mac_addr))
+		enic_dev_add_addr(enic, enic->pp.mac_addr);
+	else
+		enic_dev_add_station_addr(enic);
+	enic_set_rx_mode(netdev);
 
 	netif_wake_queue(netdev);
 
@@ -1899,7 +2032,10 @@ static int enic_stop(struct net_device *
 
 	netif_carrier_off(netdev);
 	netif_tx_disable(netdev);
-	enic_dev_del_station_addr(enic);
+	if (enic_is_dynamic(enic) && !is_zero_ether_addr(enic->pp.mac_addr))
+		enic_dev_del_addr(enic, enic->pp.mac_addr);
+	else
+		enic_dev_del_station_addr(enic);
 
 	for (i = 0; i < enic->wq_count; i++) {
 		err = vnic_wq_disable(&enic->wq[i]);
@@ -2043,7 +2179,7 @@ static int enic_dev_hang_reset(struct en
 
 static int enic_set_rsskey(struct enic *enic)
 {
-	u64 rss_key_buf_pa;
+	dma_addr_t rss_key_buf_pa;
 	union vnic_rss_key *rss_key_buf_va = NULL;
 	union vnic_rss_key rss_key = {
 		.key[0].b = {85, 67, 83, 97, 119, 101, 115, 111, 109, 101},
@@ -2074,7 +2210,7 @@ static int enic_set_rsskey(struct enic *
 
 static int enic_set_rsscpu(struct enic *enic, u8 rss_hash_bits)
 {
-	u64 rss_cpu_buf_pa;
+	dma_addr_t rss_cpu_buf_pa;
 	union vnic_rss_cpu *rss_cpu_buf_va = NULL;
 	unsigned int i;
 	int err;
@@ -2329,7 +2465,8 @@ static const struct net_device_ops enic_
 	.ndo_start_xmit		= enic_hard_start_xmit,
 	.ndo_get_stats		= enic_get_stats,
 	.ndo_validate_addr	= eth_validate_addr,
-	.ndo_set_multicast_list	= enic_set_multicast_list,
+	.ndo_set_rx_mode	= enic_set_rx_mode,
+	.ndo_set_multicast_list	= enic_set_rx_mode,
 	.ndo_set_mac_address	= enic_set_mac_address_dynamic,
 	.ndo_change_mtu		= enic_change_mtu,
 	.ndo_vlan_rx_register	= enic_vlan_rx_register,
@@ -2338,6 +2475,9 @@ static const struct net_device_ops enic_
 	.ndo_tx_timeout		= enic_tx_timeout,
 	.ndo_set_vf_port	= enic_set_vf_port,
 	.ndo_get_vf_port	= enic_get_vf_port,
+#ifdef IFLA_VF_MAX
+	.ndo_set_vf_mac		= enic_set_vf_mac,
+#endif
 #ifdef CONFIG_NET_POLL_CONTROLLER
 	.ndo_poll_controller	= enic_poll_controller,
 #endif
@@ -2350,7 +2490,8 @@ static const struct net_device_ops enic_
 	.ndo_get_stats		= enic_get_stats,
 	.ndo_validate_addr	= eth_validate_addr,
 	.ndo_set_mac_address	= enic_set_mac_address,
-	.ndo_set_multicast_list	= enic_set_multicast_list,
+	.ndo_set_rx_mode	= enic_set_rx_mode,
+	.ndo_set_multicast_list	= enic_set_rx_mode,
 	.ndo_change_mtu		= enic_change_mtu,
 	.ndo_vlan_rx_register	= enic_vlan_rx_register,
 	.ndo_vlan_rx_add_vid	= enic_vlan_rx_add_vid,
@@ -2694,7 +2835,7 @@ static void __devexit enic_remove(struct
 	if (netdev) {
 		struct enic *enic = netdev_priv(netdev);
 
-		flush_scheduled_work();
+		cancel_work_sync(&enic->reset);
 		unregister_netdev(netdev);
 		enic_dev_deinit(enic);
 		vnic_dev_close(enic->vdev);
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/enic/enic_res.h linux-libre-2.6.38-gnu1/drivers/net/enic/enic_res.h
--- linux-libre-2.6.37-gnu1/drivers/net/enic/enic_res.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/enic/enic_res.h	2011-03-14 21:20:32.000000000 -0400
@@ -34,6 +34,7 @@
 #define ENIC_MAX_MTU			9000
 
 #define ENIC_MULTICAST_PERFECT_FILTERS	32
+#define ENIC_UNICAST_PERFECT_FILTERS	32
 
 #define ENIC_NON_TSO_MAX_DESC		16
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/enic/vnic_vic.h linux-libre-2.6.38-gnu1/drivers/net/enic/vnic_vic.h
--- linux-libre-2.6.37-gnu1/drivers/net/enic/vnic_vic.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/enic/vnic_vic.h	2011-03-14 21:20:32.000000000 -0400
@@ -24,14 +24,29 @@
 /* Note: String field lengths include null char */
 
 #define VIC_PROVINFO_CISCO_OUI		{ 0x00, 0x00, 0x0c }
-#define VIC_PROVINFO_LINUX_TYPE		0x2
+#define VIC_PROVINFO_GENERIC_TYPE		0x4
 
-enum vic_linux_prov_tlv_type {
-	VIC_LINUX_PROV_TLV_PORT_PROFILE_NAME_STR = 0,
-	VIC_LINUX_PROV_TLV_CLIENT_MAC_ADDR = 1,			/* u8[6] */
-	VIC_LINUX_PROV_TLV_CLIENT_NAME_STR = 2,
-	VIC_LINUX_PROV_TLV_HOST_UUID_STR = 8,
-	VIC_LINUX_PROV_TLV_CLIENT_UUID_STR = 9,
+enum vic_generic_prov_tlv_type {
+	VIC_GENERIC_PROV_TLV_PORT_PROFILE_NAME_STR = 0,
+	VIC_GENERIC_PROV_TLV_CLIENT_MAC_ADDR = 1,
+	VIC_GENERIC_PROV_TLV_CLIENT_NAME_STR = 2,
+	VIC_GENERIC_PROV_TLV_CLUSTER_PORT_NAME_STR = 3,
+	VIC_GENERIC_PROV_TLV_CLUSTER_PORT_UUID_STR = 4,
+	VIC_GENERIC_PROV_TLV_CLUSTER_UUID_STR = 5,
+	VIC_GENERIC_PROV_TLV_CLUSTER_NAME_STR = 7,
+	VIC_GENERIC_PROV_TLV_HOST_UUID_STR = 8,
+	VIC_GENERIC_PROV_TLV_CLIENT_UUID_STR = 9,
+	VIC_GENERIC_PROV_TLV_INCARNATION_NUMBER = 10,
+	VIC_GENERIC_PROV_TLV_OS_TYPE = 11,
+	VIC_GENERIC_PROV_TLV_OS_VENDOR = 12,
+	VIC_GENERIC_PROV_TLV_CLIENT_TYPE = 15,
+};
+
+enum vic_generic_prov_os_type {
+	VIC_GENERIC_PROV_OS_TYPE_UNKNOWN = 0,
+	VIC_GENERIC_PROV_OS_TYPE_ESX = 1,
+	VIC_GENERIC_PROV_OS_TYPE_LINUX = 2,
+	VIC_GENERIC_PROV_OS_TYPE_WINDOWS = 3,
 };
 
 struct vic_provinfo {
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/ethoc.c linux-libre-2.6.38-gnu1/drivers/net/ethoc.c
--- linux-libre-2.6.37-gnu1/drivers/net/ethoc.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/ethoc.c	2011-03-14 21:20:32.000000000 -0400
@@ -19,6 +19,7 @@
 #include <linux/platform_device.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
+#include <linux/of.h>
 #include <net/ethoc.h>
 
 static int buffer_size = 0x8000; /* 32 KBytes */
@@ -184,7 +185,6 @@ MODULE_PARM_DESC(buffer_size, "DMA buffe
  * @netdev:	pointer to network device structure
  * @napi:	NAPI structure
  * @msg_enable:	device state flags
- * @rx_lock:	receive lock
  * @lock:	device lock
  * @phy:	attached PHY
  * @mdio:	MDIO bus for PHY access
@@ -209,7 +209,6 @@ struct ethoc {
 	struct napi_struct napi;
 	u32 msg_enable;
 
-	spinlock_t rx_lock;
 	spinlock_t lock;
 
 	struct phy_device *phy;
@@ -413,10 +412,21 @@ static int ethoc_rx(struct net_device *d
 		unsigned int entry;
 		struct ethoc_bd bd;
 
-		entry = priv->num_tx + (priv->cur_rx % priv->num_rx);
+		entry = priv->num_tx + priv->cur_rx;
 		ethoc_read_bd(priv, entry, &bd);
-		if (bd.stat & RX_BD_EMPTY)
-			break;
+		if (bd.stat & RX_BD_EMPTY) {
+			ethoc_ack_irq(priv, INT_MASK_RX);
+			/* If packet (interrupt) came in between checking
+			 * BD_EMTPY and clearing the interrupt source, then we
+			 * risk missing the packet as the RX interrupt won't
+			 * trigger right away when we reenable it; hence, check
+			 * BD_EMTPY here again to make sure there isn't such a
+			 * packet waiting for us...
+			 */
+			ethoc_read_bd(priv, entry, &bd);
+			if (bd.stat & RX_BD_EMPTY)
+				break;
+		}
 
 		if (ethoc_update_rx_stats(priv, &bd) == 0) {
 			int size = bd.stat >> 16;
@@ -446,13 +456,14 @@ static int ethoc_rx(struct net_device *d
 		bd.stat &= ~RX_BD_STATS;
 		bd.stat |=  RX_BD_EMPTY;
 		ethoc_write_bd(priv, entry, &bd);
-		priv->cur_rx++;
+		if (++priv->cur_rx == priv->num_rx)
+			priv->cur_rx = 0;
 	}
 
 	return count;
 }
 
-static int ethoc_update_tx_stats(struct ethoc *dev, struct ethoc_bd *bd)
+static void ethoc_update_tx_stats(struct ethoc *dev, struct ethoc_bd *bd)
 {
 	struct net_device *netdev = dev->netdev;
 
@@ -482,32 +493,44 @@ static int ethoc_update_tx_stats(struct
 	netdev->stats.collisions += (bd->stat >> 4) & 0xf;
 	netdev->stats.tx_bytes += bd->stat >> 16;
 	netdev->stats.tx_packets++;
-	return 0;
 }
 
-static void ethoc_tx(struct net_device *dev)
+static int ethoc_tx(struct net_device *dev, int limit)
 {
 	struct ethoc *priv = netdev_priv(dev);
+	int count;
+	struct ethoc_bd bd;
 
-	spin_lock(&priv->lock);
+	for (count = 0; count < limit; ++count) {
+		unsigned int entry;
 
-	while (priv->dty_tx != priv->cur_tx) {
-		unsigned int entry = priv->dty_tx % priv->num_tx;
-		struct ethoc_bd bd;
+		entry = priv->dty_tx & (priv->num_tx-1);
 
 		ethoc_read_bd(priv, entry, &bd);
-		if (bd.stat & TX_BD_READY)
-			break;
 
-		entry = (++priv->dty_tx) % priv->num_tx;
-		(void)ethoc_update_tx_stats(priv, &bd);
+		if (bd.stat & TX_BD_READY || (priv->dty_tx == priv->cur_tx)) {
+			ethoc_ack_irq(priv, INT_MASK_TX);
+			/* If interrupt came in between reading in the BD
+			 * and clearing the interrupt source, then we risk
+			 * missing the event as the TX interrupt won't trigger
+			 * right away when we reenable it; hence, check
+			 * BD_EMPTY here again to make sure there isn't such an
+			 * event pending...
+			 */
+			ethoc_read_bd(priv, entry, &bd);
+			if (bd.stat & TX_BD_READY ||
+			    (priv->dty_tx == priv->cur_tx))
+				break;
+		}
+
+		ethoc_update_tx_stats(priv, &bd);
+		priv->dty_tx++;
 	}
 
 	if ((priv->cur_tx - priv->dty_tx) <= (priv->num_tx / 2))
 		netif_wake_queue(dev);
 
-	ethoc_ack_irq(priv, INT_MASK_TX);
-	spin_unlock(&priv->lock);
+	return count;
 }
 
 static irqreturn_t ethoc_interrupt(int irq, void *dev_id)
@@ -515,32 +538,38 @@ static irqreturn_t ethoc_interrupt(int i
 	struct net_device *dev = dev_id;
 	struct ethoc *priv = netdev_priv(dev);
 	u32 pending;
+	u32 mask;
 
-	ethoc_disable_irq(priv, INT_MASK_ALL);
+	/* Figure out what triggered the interrupt...
+	 * The tricky bit here is that the interrupt source bits get
+	 * set in INT_SOURCE for an event irregardless of whether that
+	 * event is masked or not.  Thus, in order to figure out what
+	 * triggered the interrupt, we need to remove the sources
+	 * for all events that are currently masked.  This behaviour
+	 * is not particularly well documented but reasonable...
+	 */
+	mask = ethoc_read(priv, INT_MASK);
 	pending = ethoc_read(priv, INT_SOURCE);
+	pending &= mask;
+
 	if (unlikely(pending == 0)) {
-		ethoc_enable_irq(priv, INT_MASK_ALL);
 		return IRQ_NONE;
 	}
 
 	ethoc_ack_irq(priv, pending);
 
+	/* We always handle the dropped packet interrupt */
 	if (pending & INT_MASK_BUSY) {
 		dev_err(&dev->dev, "packet dropped\n");
 		dev->stats.rx_dropped++;
 	}
 
-	if (pending & INT_MASK_RX) {
-		if (napi_schedule_prep(&priv->napi))
-			__napi_schedule(&priv->napi);
-	} else {
-		ethoc_enable_irq(priv, INT_MASK_RX);
+	/* Handle receive/transmit event by switching to polling */
+	if (pending & (INT_MASK_TX | INT_MASK_RX)) {
+		ethoc_disable_irq(priv, INT_MASK_TX | INT_MASK_RX);
+		napi_schedule(&priv->napi);
 	}
 
-	if (pending & INT_MASK_TX)
-		ethoc_tx(dev);
-
-	ethoc_enable_irq(priv, INT_MASK_ALL & ~INT_MASK_RX);
 	return IRQ_HANDLED;
 }
 
@@ -566,26 +595,29 @@ static int ethoc_get_mac_address(struct
 static int ethoc_poll(struct napi_struct *napi, int budget)
 {
 	struct ethoc *priv = container_of(napi, struct ethoc, napi);
-	int work_done = 0;
+	int rx_work_done = 0;
+	int tx_work_done = 0;
 
-	work_done = ethoc_rx(priv->netdev, budget);
-	if (work_done < budget) {
-		ethoc_enable_irq(priv, INT_MASK_RX);
+	rx_work_done = ethoc_rx(priv->netdev, budget);
+	tx_work_done = ethoc_tx(priv->netdev, budget);
+
+	if (rx_work_done < budget && tx_work_done < budget) {
 		napi_complete(napi);
+		ethoc_enable_irq(priv, INT_MASK_TX | INT_MASK_RX);
 	}
 
-	return work_done;
+	return rx_work_done;
 }
 
 static int ethoc_mdio_read(struct mii_bus *bus, int phy, int reg)
 {
-	unsigned long timeout = jiffies + ETHOC_MII_TIMEOUT;
 	struct ethoc *priv = bus->priv;
+	int i;
 
 	ethoc_write(priv, MIIADDRESS, MIIADDRESS_ADDR(phy, reg));
 	ethoc_write(priv, MIICOMMAND, MIICOMMAND_READ);
 
-	while (time_before(jiffies, timeout)) {
+	for (i=0; i < 5; i++) {
 		u32 status = ethoc_read(priv, MIISTATUS);
 		if (!(status & MIISTATUS_BUSY)) {
 			u32 data = ethoc_read(priv, MIIRX_DATA);
@@ -593,8 +625,7 @@ static int ethoc_mdio_read(struct mii_bu
 			ethoc_write(priv, MIICOMMAND, 0);
 			return data;
 		}
-
-		schedule();
+		usleep_range(100,200);
 	}
 
 	return -EBUSY;
@@ -602,22 +633,21 @@ static int ethoc_mdio_read(struct mii_bu
 
 static int ethoc_mdio_write(struct mii_bus *bus, int phy, int reg, u16 val)
 {
-	unsigned long timeout = jiffies + ETHOC_MII_TIMEOUT;
 	struct ethoc *priv = bus->priv;
+	int i;
 
 	ethoc_write(priv, MIIADDRESS, MIIADDRESS_ADDR(phy, reg));
 	ethoc_write(priv, MIITX_DATA, val);
 	ethoc_write(priv, MIICOMMAND, MIICOMMAND_WRITE);
 
-	while (time_before(jiffies, timeout)) {
+	for (i=0; i < 5; i++) {
 		u32 stat = ethoc_read(priv, MIISTATUS);
 		if (!(stat & MIISTATUS_BUSY)) {
 			/* reset MII command register */
 			ethoc_write(priv, MIICOMMAND, 0);
 			return 0;
 		}
-
-		schedule();
+		usleep_range(100,200);
 	}
 
 	return -EBUSY;
@@ -971,9 +1001,17 @@ static int __devinit ethoc_probe(struct
 	/* calculate the number of TX/RX buffers, maximum 128 supported */
 	num_bd = min_t(unsigned int,
 		128, (netdev->mem_end - netdev->mem_start + 1) / ETHOC_BUFSIZ);
-	priv->num_tx = max(2, num_bd / 4);
+	if (num_bd < 4) {
+		ret = -ENODEV;
+		goto error;
+	}
+	/* num_tx must be a power of two */
+	priv->num_tx = rounddown_pow_of_two(num_bd >> 1);
 	priv->num_rx = num_bd - priv->num_tx;
 
+	dev_dbg(&pdev->dev, "ethoc: num_tx: %d num_rx: %d\n",
+		priv->num_tx, priv->num_rx);
+
 	priv->vma = devm_kzalloc(&pdev->dev, num_bd*sizeof(void*), GFP_KERNEL);
 	if (!priv->vma) {
 		ret = -ENOMEM;
@@ -982,10 +1020,23 @@ static int __devinit ethoc_probe(struct
 
 	/* Allow the platform setup code to pass in a MAC address. */
 	if (pdev->dev.platform_data) {
-		struct ethoc_platform_data *pdata =
-			(struct ethoc_platform_data *)pdev->dev.platform_data;
+		struct ethoc_platform_data *pdata = pdev->dev.platform_data;
 		memcpy(netdev->dev_addr, pdata->hwaddr, IFHWADDRLEN);
 		priv->phy_id = pdata->phy_id;
+	} else {
+		priv->phy_id = -1;
+
+#ifdef CONFIG_OF
+		{
+		const uint8_t* mac;
+
+		mac = of_get_property(pdev->dev.of_node,
+				      "local-mac-address",
+				      NULL);
+		if (mac)
+			memcpy(netdev->dev_addr, mac, IFHWADDRLEN);
+		}
+#endif
 	}
 
 	/* Check that the given MAC address is valid. If it isn't, read the
@@ -1046,7 +1097,6 @@ static int __devinit ethoc_probe(struct
 	/* setup NAPI */
 	netif_napi_add(netdev, &priv->napi, ethoc_poll, 64);
 
-	spin_lock_init(&priv->rx_lock);
 	spin_lock_init(&priv->lock);
 
 	ret = register_netdev(netdev);
@@ -1113,6 +1163,16 @@ static int ethoc_resume(struct platform_
 # define ethoc_resume  NULL
 #endif
 
+#ifdef CONFIG_OF
+static struct of_device_id ethoc_match[] = {
+	{
+		.compatible = "opencores,ethoc",
+	},
+	{},
+};
+MODULE_DEVICE_TABLE(of, ethoc_match);
+#endif
+
 static struct platform_driver ethoc_driver = {
 	.probe   = ethoc_probe,
 	.remove  = __devexit_p(ethoc_remove),
@@ -1120,6 +1180,10 @@ static struct platform_driver ethoc_driv
 	.resume  = ethoc_resume,
 	.driver  = {
 		.name = "ethoc",
+		.owner = THIS_MODULE,
+#ifdef CONFIG_OF
+		.of_match_table = ethoc_match,
+#endif
 	},
 };
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/fec.c linux-libre-2.6.38-gnu1/drivers/net/fec.c
--- linux-libre-2.6.37-gnu1/drivers/net/fec.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/fec.c	2011-03-14 21:20:32.000000000 -0400
@@ -17,6 +17,8 @@
  *
  * Bug fixes and cleanup by Philippe De Muyter (phdm@macqel.be)
  * Copyright (c) 2004-2006 Macq Electronique SA.
+ *
+ * Copyright (C) 2010 Freescale Semiconductor, Inc.
  */
 
 #include <linux/module.h>
@@ -45,29 +47,42 @@
 
 #include <asm/cacheflush.h>
 
-#ifndef CONFIG_ARCH_MXC
+#ifndef CONFIG_ARM
 #include <asm/coldfire.h>
 #include <asm/mcfsim.h>
 #endif
 
 #include "fec.h"
 
-#ifdef CONFIG_ARCH_MXC
-#include <mach/hardware.h>
+#if defined(CONFIG_ARCH_MXC) || defined(CONFIG_SOC_IMX28)
 #define FEC_ALIGNMENT	0xf
 #else
 #define FEC_ALIGNMENT	0x3
 #endif
 
-/*
- * Define the fixed address of the FEC hardware.
- */
-#if defined(CONFIG_M5272)
+#define DRIVER_NAME	"fec"
 
-static unsigned char	fec_mac_default[] = {
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* Controller is ENET-MAC */
+#define FEC_QUIRK_ENET_MAC		(1 << 0)
+/* Controller needs driver to swap frame */
+#define FEC_QUIRK_SWAP_FRAME		(1 << 1)
+
+static struct platform_device_id fec_devtype[] = {
+	{
+		.name = DRIVER_NAME,
+		.driver_data = 0,
+	}, {
+		.name = "imx28-fec",
+		.driver_data = FEC_QUIRK_ENET_MAC | FEC_QUIRK_SWAP_FRAME,
+	},
+	{ }
 };
 
+static unsigned char macaddr[ETH_ALEN];
+module_param_array(macaddr, byte, NULL, 0);
+MODULE_PARM_DESC(macaddr, "FEC Ethernet MAC address");
+
+#if defined(CONFIG_M5272)
 /*
  * Some hardware gets it MAC address out of local flash memory.
  * if this is non-zero then assume it is the address to get MAC from.
@@ -133,7 +148,8 @@ static unsigned char	fec_mac_default[] =
  * account when setting it.
  */
 #if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x) || \
-    defined(CONFIG_M520x) || defined(CONFIG_M532x) || defined(CONFIG_ARCH_MXC)
+    defined(CONFIG_M520x) || defined(CONFIG_M532x) || \
+    defined(CONFIG_ARCH_MXC) || defined(CONFIG_SOC_IMX28)
 #define	OPT_FRAME_SIZE	(PKT_MAXBUF_SIZE << 16)
 #else
 #define	OPT_FRAME_SIZE	0
@@ -186,7 +202,6 @@ struct fec_enet_private {
 	int     mii_timeout;
 	uint    phy_speed;
 	phy_interface_t	phy_interface;
-	int	index;
 	int	link;
 	int	full_duplex;
 	struct	completion mdio_done;
@@ -213,10 +228,23 @@ static void fec_stop(struct net_device *
 /* Transmitter timeout */
 #define TX_TIMEOUT (2 * HZ)
 
+static void *swap_buffer(void *bufaddr, int len)
+{
+	int i;
+	unsigned int *buf = bufaddr;
+
+	for (i = 0; i < (len + 3) / 4; i++, buf++)
+		*buf = cpu_to_be32(*buf);
+
+	return bufaddr;
+}
+
 static netdev_tx_t
 fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct fec_enet_private *fep = netdev_priv(dev);
+	const struct platform_device_id *id_entry =
+				platform_get_device_id(fep->pdev);
 	struct bufdesc *bdp;
 	void *bufaddr;
 	unsigned short	status;
@@ -261,6 +289,14 @@ fec_enet_start_xmit(struct sk_buff *skb,
 		bufaddr = fep->tx_bounce[index];
 	}
 
+	/*
+	 * Some design made an incorrect assumption on endian mode of
+	 * the system that it's running on. As the result, driver has to
+	 * swap every frame going to and coming from the controller.
+	 */
+	if (id_entry->driver_data & FEC_QUIRK_SWAP_FRAME)
+		swap_buffer(bufaddr, skb->len);
+
 	/* Save skb pointer */
 	fep->tx_skbuff[fep->skb_cur] = skb;
 
@@ -429,6 +465,8 @@ static void
 fec_enet_rx(struct net_device *dev)
 {
 	struct	fec_enet_private *fep = netdev_priv(dev);
+	const struct platform_device_id *id_entry =
+				platform_get_device_id(fep->pdev);
 	struct bufdesc *bdp;
 	unsigned short status;
 	struct	sk_buff	*skb;
@@ -492,6 +530,9 @@ fec_enet_rx(struct net_device *dev)
 	        dma_unmap_single(NULL, bdp->cbd_bufaddr, bdp->cbd_datlen,
         			DMA_FROM_DEVICE);
 
+		if (id_entry->driver_data & FEC_QUIRK_SWAP_FRAME)
+			swap_buffer(data, pkt_len);
+
 		/* This does 16 byte alignment, exactly what we need.
 		 * The packet length includes FCS, but we don't want to
 		 * include that when passing upstream as it messes up
@@ -538,37 +579,50 @@ rx_processing_done:
 }
 
 /* ------------------------------------------------------------------------- */
-#ifdef CONFIG_M5272
 static void __inline__ fec_get_mac(struct net_device *dev)
 {
 	struct fec_enet_private *fep = netdev_priv(dev);
+	struct fec_platform_data *pdata = fep->pdev->dev.platform_data;
 	unsigned char *iap, tmpaddr[ETH_ALEN];
 
-	if (FEC_FLASHMAC) {
-		/*
-		 * Get MAC address from FLASH.
-		 * If it is all 1's or 0's, use the default.
-		 */
-		iap = (unsigned char *)FEC_FLASHMAC;
-		if ((iap[0] == 0) && (iap[1] == 0) && (iap[2] == 0) &&
-		    (iap[3] == 0) && (iap[4] == 0) && (iap[5] == 0))
-			iap = fec_mac_default;
-		if ((iap[0] == 0xff) && (iap[1] == 0xff) && (iap[2] == 0xff) &&
-		    (iap[3] == 0xff) && (iap[4] == 0xff) && (iap[5] == 0xff))
-			iap = fec_mac_default;
-	} else {
-		*((unsigned long *) &tmpaddr[0]) = readl(fep->hwp + FEC_ADDR_LOW);
-		*((unsigned short *) &tmpaddr[4]) = (readl(fep->hwp + FEC_ADDR_HIGH) >> 16);
+	/*
+	 * try to get mac address in following order:
+	 *
+	 * 1) module parameter via kernel command line in form
+	 *    fec.macaddr=0x00,0x04,0x9f,0x01,0x30,0xe0
+	 */
+	iap = macaddr;
+
+	/*
+	 * 2) from flash or fuse (via platform data)
+	 */
+	if (!is_valid_ether_addr(iap)) {
+#ifdef CONFIG_M5272
+		if (FEC_FLASHMAC)
+			iap = (unsigned char *)FEC_FLASHMAC;
+#else
+		if (pdata)
+			memcpy(iap, pdata->mac, ETH_ALEN);
+#endif
+	}
+
+	/*
+	 * 3) FEC mac registers set by bootloader
+	 */
+	if (!is_valid_ether_addr(iap)) {
+		*((unsigned long *) &tmpaddr[0]) =
+			be32_to_cpu(readl(fep->hwp + FEC_ADDR_LOW));
+		*((unsigned short *) &tmpaddr[4]) =
+			be16_to_cpu(readl(fep->hwp + FEC_ADDR_HIGH) >> 16);
 		iap = &tmpaddr[0];
 	}
 
 	memcpy(dev->dev_addr, iap, ETH_ALEN);
 
-	/* Adjust MAC if using default MAC address */
-	if (iap == fec_mac_default)
-		 dev->dev_addr[ETH_ALEN-1] = fec_mac_default[ETH_ALEN-1] + fep->index;
+	/* Adjust MAC if using macaddr */
+	if (iap == macaddr)
+		 dev->dev_addr[ETH_ALEN-1] = macaddr[ETH_ALEN-1] + fep->pdev->id;
 }
-#endif
 
 /* ------------------------------------------------------------------------- */
 
@@ -651,8 +705,8 @@ static int fec_enet_mdio_write(struct mi
 	fep->mii_timeout = 0;
 	init_completion(&fep->mdio_done);
 
-	/* start a read op */
-	writel(FEC_MMFR_ST | FEC_MMFR_OP_READ |
+	/* start a write op */
+	writel(FEC_MMFR_ST | FEC_MMFR_OP_WRITE |
 		FEC_MMFR_PA(mii_id) | FEC_MMFR_RA(regnum) |
 		FEC_MMFR_TA | FEC_MMFR_DATA(value),
 		fep->hwp + FEC_MII_DATA);
@@ -681,6 +735,7 @@ static int fec_enet_mii_probe(struct net
 	char mdio_bus_id[MII_BUS_ID_SIZE];
 	char phy_name[MII_BUS_ID_SIZE + 3];
 	int phy_id;
+	int dev_id = fep->pdev->id;
 
 	fep->phy_dev = NULL;
 
@@ -692,6 +747,8 @@ static int fec_enet_mii_probe(struct net
 			continue;
 		if (fep->mii_bus->phy_map[phy_id]->phy_id == 0)
 			continue;
+		if (dev_id--)
+			continue;
 		strncpy(mdio_bus_id, fep->mii_bus->id, MII_BUS_ID_SIZE);
 		break;
 	}
@@ -729,10 +786,35 @@ static int fec_enet_mii_probe(struct net
 
 static int fec_enet_mii_init(struct platform_device *pdev)
 {
+	static struct mii_bus *fec0_mii_bus;
 	struct net_device *dev = platform_get_drvdata(pdev);
 	struct fec_enet_private *fep = netdev_priv(dev);
+	const struct platform_device_id *id_entry =
+				platform_get_device_id(fep->pdev);
 	int err = -ENXIO, i;
 
+	/*
+	 * The dual fec interfaces are not equivalent with enet-mac.
+	 * Here are the differences:
+	 *
+	 *  - fec0 supports MII & RMII modes while fec1 only supports RMII
+	 *  - fec0 acts as the 1588 time master while fec1 is slave
+	 *  - external phys can only be configured by fec0
+	 *
+	 * That is to say fec1 can not work independently. It only works
+	 * when fec0 is working. The reason behind this design is that the
+	 * second interface is added primarily for Switch mode.
+	 *
+	 * Because of the last point above, both phys are attached on fec0
+	 * mdio interface in board design, and need to be configured by
+	 * fec0 mii_bus.
+	 */
+	if ((id_entry->driver_data & FEC_QUIRK_ENET_MAC) && pdev->id) {
+		/* fec1 uses fec0 mii_bus */
+		fep->mii_bus = fec0_mii_bus;
+		return 0;
+	}
+
 	fep->mii_timeout = 0;
 
 	/*
@@ -769,6 +851,10 @@ static int fec_enet_mii_init(struct plat
 	if (mdiobus_register(fep->mii_bus))
 		goto err_out_free_mdio_irq;
 
+	/* save fec0 mii_bus */
+	if (id_entry->driver_data & FEC_QUIRK_ENET_MAC)
+		fec0_mii_bus = fep->mii_bus;
+
 	return 0;
 
 err_out_free_mdio_irq:
@@ -1067,9 +1153,8 @@ static const struct net_device_ops fec_n
  /*
   * XXX:  We need to clean up on failure exits here.
   *
-  * index is only used in legacy code
   */
-static int fec_enet_init(struct net_device *dev, int index)
+static int fec_enet_init(struct net_device *dev)
 {
 	struct fec_enet_private *fep = netdev_priv(dev);
 	struct bufdesc *cbd_base;
@@ -1086,26 +1171,11 @@ static int fec_enet_init(struct net_devi
 
 	spin_lock_init(&fep->hw_lock);
 
-	fep->index = index;
 	fep->hwp = (void __iomem *)dev->base_addr;
 	fep->netdev = dev;
 
-	/* Set the Ethernet address */
-#ifdef CONFIG_M5272
+	/* Get the Ethernet address */
 	fec_get_mac(dev);
-#else
-	{
-		unsigned long l;
-		l = readl(fep->hwp + FEC_ADDR_LOW);
-		dev->dev_addr[0] = (unsigned char)((l & 0xFF000000) >> 24);
-		dev->dev_addr[1] = (unsigned char)((l & 0x00FF0000) >> 16);
-		dev->dev_addr[2] = (unsigned char)((l & 0x0000FF00) >> 8);
-		dev->dev_addr[3] = (unsigned char)((l & 0x000000FF) >> 0);
-		l = readl(fep->hwp + FEC_ADDR_HIGH);
-		dev->dev_addr[4] = (unsigned char)((l & 0xFF000000) >> 24);
-		dev->dev_addr[5] = (unsigned char)((l & 0x00FF0000) >> 16);
-	}
-#endif
 
 	/* Set receive and transmit descriptor base. */
 	fep->rx_bd_base = cbd_base;
@@ -1156,12 +1226,25 @@ static void
 fec_restart(struct net_device *dev, int duplex)
 {
 	struct fec_enet_private *fep = netdev_priv(dev);
+	const struct platform_device_id *id_entry =
+				platform_get_device_id(fep->pdev);
 	int i;
+	u32 val, temp_mac[2];
 
 	/* Whack a reset.  We should wait for this. */
 	writel(1, fep->hwp + FEC_ECNTRL);
 	udelay(10);
 
+	/*
+	 * enet-mac reset will reset mac address registers too,
+	 * so need to reconfigure it.
+	 */
+	if (id_entry->driver_data & FEC_QUIRK_ENET_MAC) {
+		memcpy(&temp_mac, dev->dev_addr, ETH_ALEN);
+		writel(cpu_to_be32(temp_mac[0]), fep->hwp + FEC_ADDR_LOW);
+		writel(cpu_to_be32(temp_mac[1]), fep->hwp + FEC_ADDR_HIGH);
+	}
+
 	/* Clear any outstanding interrupt. */
 	writel(0xffc00000, fep->hwp + FEC_IEVENT);
 
@@ -1208,20 +1291,45 @@ fec_restart(struct net_device *dev, int
 	/* Set MII speed */
 	writel(fep->phy_speed, fep->hwp + FEC_MII_SPEED);
 
+	/*
+	 * The phy interface and speed need to get configured
+	 * differently on enet-mac.
+	 */
+	if (id_entry->driver_data & FEC_QUIRK_ENET_MAC) {
+		val = readl(fep->hwp + FEC_R_CNTRL);
+
+		/* MII or RMII */
+		if (fep->phy_interface == PHY_INTERFACE_MODE_RMII)
+			val |= (1 << 8);
+		else
+			val &= ~(1 << 8);
+
+		/* 10M or 100M */
+		if (fep->phy_dev && fep->phy_dev->speed == SPEED_100)
+			val &= ~(1 << 9);
+		else
+			val |= (1 << 9);
+
+		writel(val, fep->hwp + FEC_R_CNTRL);
+	} else {
 #ifdef FEC_MIIGSK_ENR
-	if (fep->phy_interface == PHY_INTERFACE_MODE_RMII) {
-		/* disable the gasket and wait */
-		writel(0, fep->hwp + FEC_MIIGSK_ENR);
-		while (readl(fep->hwp + FEC_MIIGSK_ENR) & 4)
-			udelay(1);
+		if (fep->phy_interface == PHY_INTERFACE_MODE_RMII) {
+			/* disable the gasket and wait */
+			writel(0, fep->hwp + FEC_MIIGSK_ENR);
+			while (readl(fep->hwp + FEC_MIIGSK_ENR) & 4)
+				udelay(1);
 
-		/* configure the gasket: RMII, 50 MHz, no loopback, no echo */
-		writel(1, fep->hwp + FEC_MIIGSK_CFGR);
+			/*
+			 * configure the gasket:
+			 *   RMII, 50 MHz, no loopback, no echo
+			 */
+			writel(1, fep->hwp + FEC_MIIGSK_CFGR);
 
-		/* re-enable the gasket */
-		writel(2, fep->hwp + FEC_MIIGSK_ENR);
-	}
+			/* re-enable the gasket */
+			writel(2, fep->hwp + FEC_MIIGSK_ENR);
+		}
 #endif
+	}
 
 	/* And last, enable the transmit and receive processing */
 	writel(2, fep->hwp + FEC_ECNTRL);
@@ -1316,7 +1424,7 @@ fec_probe(struct platform_device *pdev)
 	}
 	clk_enable(fep->clk);
 
-	ret = fec_enet_init(ndev, 0);
+	ret = fec_enet_init(ndev);
 	if (ret)
 		goto failed_init;
 
@@ -1380,8 +1488,10 @@ fec_suspend(struct device *dev)
 
 	if (ndev) {
 		fep = netdev_priv(ndev);
-		if (netif_running(ndev))
-			fec_enet_close(ndev);
+		if (netif_running(ndev)) {
+			fec_stop(ndev);
+			netif_device_detach(ndev);
+		}
 		clk_disable(fep->clk);
 	}
 	return 0;
@@ -1396,8 +1506,10 @@ fec_resume(struct device *dev)
 	if (ndev) {
 		fep = netdev_priv(ndev);
 		clk_enable(fep->clk);
-		if (netif_running(ndev))
-			fec_enet_open(ndev);
+		if (netif_running(ndev)) {
+			fec_restart(ndev, fep->full_duplex);
+			netif_device_attach(ndev);
+		}
 	}
 	return 0;
 }
@@ -1414,12 +1526,13 @@ static const struct dev_pm_ops fec_pm_op
 
 static struct platform_driver fec_driver = {
 	.driver	= {
-		.name	= "fec",
+		.name	= DRIVER_NAME,
 		.owner	= THIS_MODULE,
 #ifdef CONFIG_PM
 		.pm	= &fec_pm_ops,
 #endif
 	},
+	.id_table = fec_devtype,
 	.probe	= fec_probe,
 	.remove	= __devexit_p(fec_drv_remove),
 };
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/fec.h linux-libre-2.6.38-gnu1/drivers/net/fec.h
--- linux-libre-2.6.37-gnu1/drivers/net/fec.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/fec.h	2011-03-14 21:20:32.000000000 -0400
@@ -14,7 +14,8 @@
 /****************************************************************************/
 
 #if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x) || \
-    defined(CONFIG_M520x) || defined(CONFIG_M532x) || defined(CONFIG_ARCH_MXC)
+    defined(CONFIG_M520x) || defined(CONFIG_M532x) || \
+    defined(CONFIG_ARCH_MXC) || defined(CONFIG_SOC_IMX28)
 /*
  *	Just figures, Motorola would have to change the offsets for
  *	registers in the same peripheral device on different models
@@ -78,7 +79,7 @@
 /*
  *	Define the buffer descriptor structure.
  */
-#ifdef CONFIG_ARCH_MXC
+#if defined(CONFIG_ARCH_MXC) || defined(CONFIG_SOC_IMX28)
 struct bufdesc {
 	unsigned short cbd_datlen;	/* Data length */
 	unsigned short cbd_sc;	/* Control and status info */
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/fec_mpc52xx.c linux-libre-2.6.38-gnu1/drivers/net/fec_mpc52xx.c
--- linux-libre-2.6.37-gnu1/drivers/net/fec_mpc52xx.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/fec_mpc52xx.c	2011-03-14 21:20:32.000000000 -0400
@@ -366,9 +366,8 @@ static irqreturn_t mpc52xx_fec_tx_interr
 {
 	struct net_device *dev = dev_id;
 	struct mpc52xx_fec_priv *priv = netdev_priv(dev);
-	unsigned long flags;
 
-	spin_lock_irqsave(&priv->lock, flags);
+	spin_lock(&priv->lock);
 	while (bcom_buffer_done(priv->tx_dmatsk)) {
 		struct sk_buff *skb;
 		struct bcom_fec_bd *bd;
@@ -379,7 +378,7 @@ static irqreturn_t mpc52xx_fec_tx_interr
 
 		dev_kfree_skb_irq(skb);
 	}
-	spin_unlock_irqrestore(&priv->lock, flags);
+	spin_unlock(&priv->lock);
 
 	netif_wake_queue(dev);
 
@@ -395,9 +394,8 @@ static irqreturn_t mpc52xx_fec_rx_interr
 	struct bcom_fec_bd *bd;
 	u32 status, physaddr;
 	int length;
-	unsigned long flags;
 
-	spin_lock_irqsave(&priv->lock, flags);
+	spin_lock(&priv->lock);
 
 	while (bcom_buffer_done(priv->rx_dmatsk)) {
 
@@ -429,7 +427,7 @@ static irqreturn_t mpc52xx_fec_rx_interr
 
 		/* Process the received skb - Drop the spin lock while
 		 * calling into the network stack */
-		spin_unlock_irqrestore(&priv->lock, flags);
+		spin_unlock(&priv->lock);
 
 		dma_unmap_single(dev->dev.parent, physaddr, rskb->len,
 				 DMA_FROM_DEVICE);
@@ -438,10 +436,10 @@ static irqreturn_t mpc52xx_fec_rx_interr
 		rskb->protocol = eth_type_trans(rskb, dev);
 		netif_rx(rskb);
 
-		spin_lock_irqsave(&priv->lock, flags);
+		spin_lock(&priv->lock);
 	}
 
-	spin_unlock_irqrestore(&priv->lock, flags);
+	spin_unlock(&priv->lock);
 
 	return IRQ_HANDLED;
 }
@@ -452,7 +450,6 @@ static irqreturn_t mpc52xx_fec_interrupt
 	struct mpc52xx_fec_priv *priv = netdev_priv(dev);
 	struct mpc52xx_fec __iomem *fec = priv->fec;
 	u32 ievent;
-	unsigned long flags;
 
 	ievent = in_be32(&fec->ievent);
 
@@ -470,9 +467,9 @@ static irqreturn_t mpc52xx_fec_interrupt
 		if (net_ratelimit() && (ievent & FEC_IEVENT_XFIFO_ERROR))
 			dev_warn(&dev->dev, "FEC_IEVENT_XFIFO_ERROR\n");
 
-		spin_lock_irqsave(&priv->lock, flags);
+		spin_lock(&priv->lock);
 		mpc52xx_fec_reset(dev);
-		spin_unlock_irqrestore(&priv->lock, flags);
+		spin_unlock(&priv->lock);
 
 		return IRQ_HANDLED;
 	}
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/forcedeth.c linux-libre-2.6.38-gnu1/drivers/net/forcedeth.c
--- linux-libre-2.6.37-gnu1/drivers/net/forcedeth.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/forcedeth.c	2011-03-14 21:20:32.000000000 -0400
@@ -39,6 +39,9 @@
  * DEV_NEED_TIMERIRQ will not harm you on sane hardware, only generating a few
  * superfluous timer interrupts from the nic.
  */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #define FORCEDETH_VERSION		"0.64"
 #define DRV_NAME			"forcedeth"
 
@@ -60,18 +63,12 @@
 #include <linux/if_vlan.h>
 #include <linux/dma-mapping.h>
 #include <linux/slab.h>
+#include <linux/uaccess.h>
+#include  <linux/io.h>
 
 #include <asm/irq.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
 #include <asm/system.h>
 
-#if 0
-#define dprintk			printk
-#else
-#define dprintk(x...)		do { } while (0)
-#endif
-
 #define TX_WORK_PER_LOOP  64
 #define RX_WORK_PER_LOOP  64
 
@@ -186,9 +183,9 @@ enum {
 	NvRegSlotTime = 0x9c,
 #define NVREG_SLOTTIME_LEGBF_ENABLED	0x80000000
 #define NVREG_SLOTTIME_10_100_FULL	0x00007f00
-#define NVREG_SLOTTIME_1000_FULL 	0x0003ff00
+#define NVREG_SLOTTIME_1000_FULL	0x0003ff00
 #define NVREG_SLOTTIME_HALF		0x0000ff00
-#define NVREG_SLOTTIME_DEFAULT	 	0x00007f00
+#define NVREG_SLOTTIME_DEFAULT		0x00007f00
 #define NVREG_SLOTTIME_MASK		0x000000ff
 
 	NvRegTxDeferral = 0xA0,
@@ -297,7 +294,7 @@ enum {
 #define NVREG_WAKEUPFLAGS_ENABLE	0x1111
 
 	NvRegMgmtUnitGetVersion = 0x204,
-#define NVREG_MGMTUNITGETVERSION     	0x01
+#define NVREG_MGMTUNITGETVERSION	0x01
 	NvRegMgmtUnitVersion = 0x208,
 #define NVREG_MGMTUNITVERSION		0x08
 	NvRegPowerCap = 0x268,
@@ -368,8 +365,8 @@ struct ring_desc_ex {
 };
 
 union ring_type {
-	struct ring_desc* orig;
-	struct ring_desc_ex* ex;
+	struct ring_desc *orig;
+	struct ring_desc_ex *ex;
 };
 
 #define FLAG_MASK_V1 0xffff0000
@@ -444,10 +441,10 @@ union ring_type {
 #define NV_RX3_VLAN_TAG_MASK	(0x0000FFFF)
 
 /* Miscelaneous hardware related defines: */
-#define NV_PCI_REGSZ_VER1      	0x270
-#define NV_PCI_REGSZ_VER2      	0x2d4
-#define NV_PCI_REGSZ_VER3      	0x604
-#define NV_PCI_REGSZ_MAX       	0x604
+#define NV_PCI_REGSZ_VER1	0x270
+#define NV_PCI_REGSZ_VER2	0x2d4
+#define NV_PCI_REGSZ_VER3	0x604
+#define NV_PCI_REGSZ_MAX	0x604
 
 /* various timeout delays: all in usec */
 #define NV_TXRX_RESET_DELAY	4
@@ -717,7 +714,7 @@ static const struct register_test nv_reg
 	{ NvRegMulticastAddrA, 0xffffffff },
 	{ NvRegTxWatermark, 0x0ff },
 	{ NvRegWakeUpFlags, 0x07777 },
-	{ 0,0 }
+	{ 0, 0 }
 };
 
 struct nv_skb_map {
@@ -911,7 +908,7 @@ static int phy_cross = NV_CROSSOVER_DETE
  * Power down phy when interface is down (persists through reboot;
  * older Linux and other OSes may not power it up again)
  */
-static int phy_power_down = 0;
+static int phy_power_down;
 
 static inline struct fe_priv *get_nvpriv(struct net_device *dev)
 {
@@ -948,7 +945,7 @@ static bool nv_optimized(struct fe_priv
 }
 
 static int reg_delay(struct net_device *dev, int offset, u32 mask, u32 target,
-				int delay, int delaymax, const char *msg)
+		     int delay, int delaymax)
 {
 	u8 __iomem *base = get_hwbase(dev);
 
@@ -956,11 +953,8 @@ static int reg_delay(struct net_device *
 	do {
 		udelay(delay);
 		delaymax -= delay;
-		if (delaymax < 0) {
-			if (msg)
-				printk("%s", msg);
+		if (delaymax < 0)
 			return 1;
-		}
 	} while ((readl(base + offset) & mask) != target);
 	return 0;
 }
@@ -984,12 +978,10 @@ static void setup_hw_rings(struct net_de
 	u8 __iomem *base = get_hwbase(dev);
 
 	if (!nv_optimized(np)) {
-		if (rxtx_flags & NV_SETUP_RX_RING) {
+		if (rxtx_flags & NV_SETUP_RX_RING)
 			writel(dma_low(np->ring_addr), base + NvRegRxRingPhysAddr);
-		}
-		if (rxtx_flags & NV_SETUP_TX_RING) {
+		if (rxtx_flags & NV_SETUP_TX_RING)
 			writel(dma_low(np->ring_addr + np->rx_ring_size*sizeof(struct ring_desc)), base + NvRegTxRingPhysAddr);
-		}
 	} else {
 		if (rxtx_flags & NV_SETUP_RX_RING) {
 			writel(dma_low(np->ring_addr), base + NvRegRxRingPhysAddr);
@@ -1015,10 +1007,8 @@ static void free_rings(struct net_device
 			pci_free_consistent(np->pci_dev, sizeof(struct ring_desc_ex) * (np->rx_ring_size + np->tx_ring_size),
 					    np->rx_ring.ex, np->ring_addr);
 	}
-	if (np->rx_skb)
-		kfree(np->rx_skb);
-	if (np->tx_skb)
-		kfree(np->tx_skb);
+	kfree(np->rx_skb);
+	kfree(np->tx_skb);
 }
 
 static int using_multi_irqs(struct net_device *dev)
@@ -1145,23 +1135,15 @@ static int mii_rw(struct net_device *dev
 	writel(reg, base + NvRegMIIControl);
 
 	if (reg_delay(dev, NvRegMIIControl, NVREG_MIICTL_INUSE, 0,
-			NV_MIIPHY_DELAY, NV_MIIPHY_DELAYMAX, NULL)) {
-		dprintk(KERN_DEBUG "%s: mii_rw of reg %d at PHY %d timed out.\n",
-				dev->name, miireg, addr);
+			NV_MIIPHY_DELAY, NV_MIIPHY_DELAYMAX)) {
 		retval = -1;
 	} else if (value != MII_READ) {
 		/* it was a write operation - fewer failures are detectable */
-		dprintk(KERN_DEBUG "%s: mii_rw wrote 0x%x to reg %d at PHY %d\n",
-				dev->name, value, miireg, addr);
 		retval = 0;
 	} else if (readl(base + NvRegMIIStatus) & NVREG_MIISTAT_ERROR) {
-		dprintk(KERN_DEBUG "%s: mii_rw of reg %d at PHY %d failed.\n",
-				dev->name, miireg, addr);
 		retval = -1;
 	} else {
 		retval = readl(base + NvRegMIIData);
-		dprintk(KERN_DEBUG "%s: mii_rw read from reg %d at PHY %d: 0x%x.\n",
-				dev->name, miireg, addr, retval);
 	}
 
 	return retval;
@@ -1174,16 +1156,15 @@ static int phy_reset(struct net_device *
 	unsigned int tries = 0;
 
 	miicontrol = BMCR_RESET | bmcr_setup;
-	if (mii_rw(dev, np->phyaddr, MII_BMCR, miicontrol)) {
+	if (mii_rw(dev, np->phyaddr, MII_BMCR, miicontrol))
 		return -1;
-	}
 
 	/* wait for 500ms */
 	msleep(500);
 
 	/* must wait till reset is deasserted */
 	while (miicontrol & BMCR_RESET) {
-		msleep(10);
+		usleep_range(10000, 20000);
 		miicontrol = mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ);
 		/* FIXME: 100 tries seem excessive */
 		if (tries++ > 100)
@@ -1192,106 +1173,239 @@ static int phy_reset(struct net_device *
 	return 0;
 }
 
+static int init_realtek_8211b(struct net_device *dev, struct fe_priv *np)
+{
+	static const struct {
+		int reg;
+		int init;
+	} ri[] = {
+		{ PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1 },
+		{ PHY_REALTEK_INIT_REG2, PHY_REALTEK_INIT2 },
+		{ PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT3 },
+		{ PHY_REALTEK_INIT_REG3, PHY_REALTEK_INIT4 },
+		{ PHY_REALTEK_INIT_REG4, PHY_REALTEK_INIT5 },
+		{ PHY_REALTEK_INIT_REG5, PHY_REALTEK_INIT6 },
+		{ PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1 },
+	};
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(ri); i++) {
+		if (mii_rw(dev, np->phyaddr, ri[i].reg, ri[i].init))
+			return PHY_ERROR;
+	}
+
+	return 0;
+}
+
+static int init_realtek_8211c(struct net_device *dev, struct fe_priv *np)
+{
+	u32 reg;
+	u8 __iomem *base = get_hwbase(dev);
+	u32 powerstate = readl(base + NvRegPowerState2);
+
+	/* need to perform hw phy reset */
+	powerstate |= NVREG_POWERSTATE2_PHY_RESET;
+	writel(powerstate, base + NvRegPowerState2);
+	msleep(25);
+
+	powerstate &= ~NVREG_POWERSTATE2_PHY_RESET;
+	writel(powerstate, base + NvRegPowerState2);
+	msleep(25);
+
+	reg = mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG6, MII_READ);
+	reg |= PHY_REALTEK_INIT9;
+	if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG6, reg))
+		return PHY_ERROR;
+	if (mii_rw(dev, np->phyaddr,
+		   PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT10))
+		return PHY_ERROR;
+	reg = mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG7, MII_READ);
+	if (!(reg & PHY_REALTEK_INIT11)) {
+		reg |= PHY_REALTEK_INIT11;
+		if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG7, reg))
+			return PHY_ERROR;
+	}
+	if (mii_rw(dev, np->phyaddr,
+		   PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1))
+		return PHY_ERROR;
+
+	return 0;
+}
+
+static int init_realtek_8201(struct net_device *dev, struct fe_priv *np)
+{
+	u32 phy_reserved;
+
+	if (np->driver_data & DEV_NEED_PHY_INIT_FIX) {
+		phy_reserved = mii_rw(dev, np->phyaddr,
+				      PHY_REALTEK_INIT_REG6, MII_READ);
+		phy_reserved |= PHY_REALTEK_INIT7;
+		if (mii_rw(dev, np->phyaddr,
+			   PHY_REALTEK_INIT_REG6, phy_reserved))
+			return PHY_ERROR;
+	}
+
+	return 0;
+}
+
+static int init_realtek_8201_cross(struct net_device *dev, struct fe_priv *np)
+{
+	u32 phy_reserved;
+
+	if (phy_cross == NV_CROSSOVER_DETECTION_DISABLED) {
+		if (mii_rw(dev, np->phyaddr,
+			   PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT3))
+			return PHY_ERROR;
+		phy_reserved = mii_rw(dev, np->phyaddr,
+				      PHY_REALTEK_INIT_REG2, MII_READ);
+		phy_reserved &= ~PHY_REALTEK_INIT_MSK1;
+		phy_reserved |= PHY_REALTEK_INIT3;
+		if (mii_rw(dev, np->phyaddr,
+			   PHY_REALTEK_INIT_REG2, phy_reserved))
+			return PHY_ERROR;
+		if (mii_rw(dev, np->phyaddr,
+			   PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1))
+			return PHY_ERROR;
+	}
+
+	return 0;
+}
+
+static int init_cicada(struct net_device *dev, struct fe_priv *np,
+		       u32 phyinterface)
+{
+	u32 phy_reserved;
+
+	if (phyinterface & PHY_RGMII) {
+		phy_reserved = mii_rw(dev, np->phyaddr, MII_RESV1, MII_READ);
+		phy_reserved &= ~(PHY_CICADA_INIT1 | PHY_CICADA_INIT2);
+		phy_reserved |= (PHY_CICADA_INIT3 | PHY_CICADA_INIT4);
+		if (mii_rw(dev, np->phyaddr, MII_RESV1, phy_reserved))
+			return PHY_ERROR;
+		phy_reserved = mii_rw(dev, np->phyaddr, MII_NCONFIG, MII_READ);
+		phy_reserved |= PHY_CICADA_INIT5;
+		if (mii_rw(dev, np->phyaddr, MII_NCONFIG, phy_reserved))
+			return PHY_ERROR;
+	}
+	phy_reserved = mii_rw(dev, np->phyaddr, MII_SREVISION, MII_READ);
+	phy_reserved |= PHY_CICADA_INIT6;
+	if (mii_rw(dev, np->phyaddr, MII_SREVISION, phy_reserved))
+		return PHY_ERROR;
+
+	return 0;
+}
+
+static int init_vitesse(struct net_device *dev, struct fe_priv *np)
+{
+	u32 phy_reserved;
+
+	if (mii_rw(dev, np->phyaddr,
+		   PHY_VITESSE_INIT_REG1, PHY_VITESSE_INIT1))
+		return PHY_ERROR;
+	if (mii_rw(dev, np->phyaddr,
+		   PHY_VITESSE_INIT_REG2, PHY_VITESSE_INIT2))
+		return PHY_ERROR;
+	phy_reserved = mii_rw(dev, np->phyaddr,
+			      PHY_VITESSE_INIT_REG4, MII_READ);
+	if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG4, phy_reserved))
+		return PHY_ERROR;
+	phy_reserved = mii_rw(dev, np->phyaddr,
+			      PHY_VITESSE_INIT_REG3, MII_READ);
+	phy_reserved &= ~PHY_VITESSE_INIT_MSK1;
+	phy_reserved |= PHY_VITESSE_INIT3;
+	if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG3, phy_reserved))
+		return PHY_ERROR;
+	if (mii_rw(dev, np->phyaddr,
+		   PHY_VITESSE_INIT_REG2, PHY_VITESSE_INIT4))
+		return PHY_ERROR;
+	if (mii_rw(dev, np->phyaddr,
+		   PHY_VITESSE_INIT_REG2, PHY_VITESSE_INIT5))
+		return PHY_ERROR;
+	phy_reserved = mii_rw(dev, np->phyaddr,
+			      PHY_VITESSE_INIT_REG4, MII_READ);
+	phy_reserved &= ~PHY_VITESSE_INIT_MSK1;
+	phy_reserved |= PHY_VITESSE_INIT3;
+	if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG4, phy_reserved))
+		return PHY_ERROR;
+	phy_reserved = mii_rw(dev, np->phyaddr,
+			      PHY_VITESSE_INIT_REG3, MII_READ);
+	if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG3, phy_reserved))
+		return PHY_ERROR;
+	if (mii_rw(dev, np->phyaddr,
+		   PHY_VITESSE_INIT_REG2, PHY_VITESSE_INIT6))
+		return PHY_ERROR;
+	if (mii_rw(dev, np->phyaddr,
+		   PHY_VITESSE_INIT_REG2, PHY_VITESSE_INIT7))
+		return PHY_ERROR;
+	phy_reserved = mii_rw(dev, np->phyaddr,
+			      PHY_VITESSE_INIT_REG4, MII_READ);
+	if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG4, phy_reserved))
+		return PHY_ERROR;
+	phy_reserved = mii_rw(dev, np->phyaddr,
+			      PHY_VITESSE_INIT_REG3, MII_READ);
+	phy_reserved &= ~PHY_VITESSE_INIT_MSK2;
+	phy_reserved |= PHY_VITESSE_INIT8;
+	if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG3, phy_reserved))
+		return PHY_ERROR;
+	if (mii_rw(dev, np->phyaddr,
+		   PHY_VITESSE_INIT_REG2, PHY_VITESSE_INIT9))
+		return PHY_ERROR;
+	if (mii_rw(dev, np->phyaddr,
+		   PHY_VITESSE_INIT_REG1, PHY_VITESSE_INIT10))
+		return PHY_ERROR;
+
+	return 0;
+}
+
 static int phy_init(struct net_device *dev)
 {
 	struct fe_priv *np = get_nvpriv(dev);
 	u8 __iomem *base = get_hwbase(dev);
-	u32 phyinterface, phy_reserved, mii_status, mii_control, mii_control_1000,reg;
+	u32 phyinterface;
+	u32 mii_status, mii_control, mii_control_1000, reg;
 
 	/* phy errata for E3016 phy */
 	if (np->phy_model == PHY_MODEL_MARVELL_E3016) {
 		reg = mii_rw(dev, np->phyaddr, MII_NCONFIG, MII_READ);
 		reg &= ~PHY_MARVELL_E3016_INITMASK;
 		if (mii_rw(dev, np->phyaddr, MII_NCONFIG, reg)) {
-			printk(KERN_INFO "%s: phy write to errata reg failed.\n", pci_name(np->pci_dev));
+			netdev_info(dev, "%s: phy write to errata reg failed\n",
+				    pci_name(np->pci_dev));
 			return PHY_ERROR;
 		}
 	}
 	if (np->phy_oui == PHY_OUI_REALTEK) {
 		if (np->phy_model == PHY_MODEL_REALTEK_8211 &&
 		    np->phy_rev == PHY_REV_REALTEK_8211B) {
-			if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1)) {
-				printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
-				return PHY_ERROR;
-			}
-			if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG2, PHY_REALTEK_INIT2)) {
-				printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
-				return PHY_ERROR;
-			}
-			if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT3)) {
-				printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
-				return PHY_ERROR;
-			}
-			if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG3, PHY_REALTEK_INIT4)) {
-				printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
-				return PHY_ERROR;
-			}
-			if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG4, PHY_REALTEK_INIT5)) {
-				printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
-				return PHY_ERROR;
-			}
-			if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG5, PHY_REALTEK_INIT6)) {
-				printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
-				return PHY_ERROR;
-			}
-			if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1)) {
-				printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
-				return PHY_ERROR;
-			}
-		}
-		if (np->phy_model == PHY_MODEL_REALTEK_8211 &&
-		    np->phy_rev == PHY_REV_REALTEK_8211C) {
-			u32 powerstate = readl(base + NvRegPowerState2);
-
-			/* need to perform hw phy reset */
-			powerstate |= NVREG_POWERSTATE2_PHY_RESET;
-			writel(powerstate, base + NvRegPowerState2);
-			msleep(25);
-
-			powerstate &= ~NVREG_POWERSTATE2_PHY_RESET;
-			writel(powerstate, base + NvRegPowerState2);
-			msleep(25);
-
-			reg = mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG6, MII_READ);
-			reg |= PHY_REALTEK_INIT9;
-			if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG6, reg)) {
-				printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+			if (init_realtek_8211b(dev, np)) {
+				netdev_info(dev, "%s: phy init failed\n",
+					    pci_name(np->pci_dev));
 				return PHY_ERROR;
 			}
-			if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT10)) {
-				printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+		} else if (np->phy_model == PHY_MODEL_REALTEK_8211 &&
+			   np->phy_rev == PHY_REV_REALTEK_8211C) {
+			if (init_realtek_8211c(dev, np)) {
+				netdev_info(dev, "%s: phy init failed\n",
+					    pci_name(np->pci_dev));
 				return PHY_ERROR;
 			}
-			reg = mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG7, MII_READ);
-			if (!(reg & PHY_REALTEK_INIT11)) {
-				reg |= PHY_REALTEK_INIT11;
-				if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG7, reg)) {
-					printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
-					return PHY_ERROR;
-				}
-			}
-			if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1)) {
-				printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+		} else if (np->phy_model == PHY_MODEL_REALTEK_8201) {
+			if (init_realtek_8201(dev, np)) {
+				netdev_info(dev, "%s: phy init failed\n",
+					    pci_name(np->pci_dev));
 				return PHY_ERROR;
 			}
 		}
-		if (np->phy_model == PHY_MODEL_REALTEK_8201) {
-			if (np->driver_data & DEV_NEED_PHY_INIT_FIX) {
-				phy_reserved = mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG6, MII_READ);
-				phy_reserved |= PHY_REALTEK_INIT7;
-				if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG6, phy_reserved)) {
-					printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
-					return PHY_ERROR;
-				}
-			}
-		}
 	}
 
 	/* set advertise register */
 	reg = mii_rw(dev, np->phyaddr, MII_ADVERTISE, MII_READ);
-	reg |= (ADVERTISE_10HALF|ADVERTISE_10FULL|ADVERTISE_100HALF|ADVERTISE_100FULL|ADVERTISE_PAUSE_ASYM|ADVERTISE_PAUSE_CAP);
+	reg |= (ADVERTISE_10HALF | ADVERTISE_10FULL |
+		ADVERTISE_100HALF | ADVERTISE_100FULL |
+		ADVERTISE_PAUSE_ASYM | ADVERTISE_PAUSE_CAP);
 	if (mii_rw(dev, np->phyaddr, MII_ADVERTISE, reg)) {
-		printk(KERN_INFO "%s: phy write to advertise failed.\n", pci_name(np->pci_dev));
+		netdev_info(dev, "%s: phy write to advertise failed\n",
+			    pci_name(np->pci_dev));
 		return PHY_ERROR;
 	}
 
@@ -1302,7 +1416,8 @@ static int phy_init(struct net_device *d
 	mii_status = mii_rw(dev, np->phyaddr, MII_BMSR, MII_READ);
 	if (mii_status & PHY_GIGABIT) {
 		np->gigabit = PHY_GIGABIT;
-		mii_control_1000 = mii_rw(dev, np->phyaddr, MII_CTRL1000, MII_READ);
+		mii_control_1000 = mii_rw(dev, np->phyaddr,
+					  MII_CTRL1000, MII_READ);
 		mii_control_1000 &= ~ADVERTISE_1000HALF;
 		if (phyinterface & PHY_RGMII)
 			mii_control_1000 |= ADVERTISE_1000FULL;
@@ -1310,11 +1425,11 @@ static int phy_init(struct net_device *d
 			mii_control_1000 &= ~ADVERTISE_1000FULL;
 
 		if (mii_rw(dev, np->phyaddr, MII_CTRL1000, mii_control_1000)) {
-			printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+			netdev_info(dev, "%s: phy init failed\n",
+				    pci_name(np->pci_dev));
 			return PHY_ERROR;
 		}
-	}
-	else
+	} else
 		np->gigabit = 0;
 
 	mii_control = mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ);
@@ -1326,7 +1441,8 @@ static int phy_init(struct net_device *d
 		/* start autoneg since we already performed hw reset above */
 		mii_control |= BMCR_ANRESTART;
 		if (mii_rw(dev, np->phyaddr, MII_BMCR, mii_control)) {
-			printk(KERN_INFO "%s: phy init failed\n", pci_name(np->pci_dev));
+			netdev_info(dev, "%s: phy init failed\n",
+				    pci_name(np->pci_dev));
 			return PHY_ERROR;
 		}
 	} else {
@@ -1334,165 +1450,42 @@ static int phy_init(struct net_device *d
 		 * (certain phys need bmcr to be setup with reset)
 		 */
 		if (phy_reset(dev, mii_control)) {
-			printk(KERN_INFO "%s: phy reset failed\n", pci_name(np->pci_dev));
+			netdev_info(dev, "%s: phy reset failed\n",
+				    pci_name(np->pci_dev));
 			return PHY_ERROR;
 		}
 	}
 
 	/* phy vendor specific configuration */
-	if ((np->phy_oui == PHY_OUI_CICADA) && (phyinterface & PHY_RGMII) ) {
-		phy_reserved = mii_rw(dev, np->phyaddr, MII_RESV1, MII_READ);
-		phy_reserved &= ~(PHY_CICADA_INIT1 | PHY_CICADA_INIT2);
-		phy_reserved |= (PHY_CICADA_INIT3 | PHY_CICADA_INIT4);
-		if (mii_rw(dev, np->phyaddr, MII_RESV1, phy_reserved)) {
-			printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
-			return PHY_ERROR;
-		}
-		phy_reserved = mii_rw(dev, np->phyaddr, MII_NCONFIG, MII_READ);
-		phy_reserved |= PHY_CICADA_INIT5;
-		if (mii_rw(dev, np->phyaddr, MII_NCONFIG, phy_reserved)) {
-			printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
-			return PHY_ERROR;
-		}
-	}
-	if (np->phy_oui == PHY_OUI_CICADA) {
-		phy_reserved = mii_rw(dev, np->phyaddr, MII_SREVISION, MII_READ);
-		phy_reserved |= PHY_CICADA_INIT6;
-		if (mii_rw(dev, np->phyaddr, MII_SREVISION, phy_reserved)) {
-			printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
-			return PHY_ERROR;
-		}
-	}
-	if (np->phy_oui == PHY_OUI_VITESSE) {
-		if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG1, PHY_VITESSE_INIT1)) {
-			printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
-			return PHY_ERROR;
-		}
-		if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG2, PHY_VITESSE_INIT2)) {
-			printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
-			return PHY_ERROR;
-		}
-		phy_reserved = mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG4, MII_READ);
-		if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG4, phy_reserved)) {
-			printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
-			return PHY_ERROR;
-		}
-		phy_reserved = mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG3, MII_READ);
-		phy_reserved &= ~PHY_VITESSE_INIT_MSK1;
-		phy_reserved |= PHY_VITESSE_INIT3;
-		if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG3, phy_reserved)) {
-			printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
-			return PHY_ERROR;
-		}
-		if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG2, PHY_VITESSE_INIT4)) {
-			printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
-			return PHY_ERROR;
-		}
-		if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG2, PHY_VITESSE_INIT5)) {
-			printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
-			return PHY_ERROR;
-		}
-		phy_reserved = mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG4, MII_READ);
-		phy_reserved &= ~PHY_VITESSE_INIT_MSK1;
-		phy_reserved |= PHY_VITESSE_INIT3;
-		if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG4, phy_reserved)) {
-			printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
-			return PHY_ERROR;
-		}
-		phy_reserved = mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG3, MII_READ);
-		if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG3, phy_reserved)) {
-			printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
-			return PHY_ERROR;
-		}
-		if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG2, PHY_VITESSE_INIT6)) {
-			printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
-			return PHY_ERROR;
-		}
-		if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG2, PHY_VITESSE_INIT7)) {
-			printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
-			return PHY_ERROR;
-		}
-		phy_reserved = mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG4, MII_READ);
-		if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG4, phy_reserved)) {
-			printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
-			return PHY_ERROR;
-		}
-		phy_reserved = mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG3, MII_READ);
-		phy_reserved &= ~PHY_VITESSE_INIT_MSK2;
-		phy_reserved |= PHY_VITESSE_INIT8;
-		if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG3, phy_reserved)) {
-			printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
-			return PHY_ERROR;
-		}
-		if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG2, PHY_VITESSE_INIT9)) {
-			printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+	if ((np->phy_oui == PHY_OUI_CICADA)) {
+		if (init_cicada(dev, np, phyinterface)) {
+			netdev_info(dev, "%s: phy init failed\n",
+				    pci_name(np->pci_dev));
 			return PHY_ERROR;
 		}
-		if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG1, PHY_VITESSE_INIT10)) {
-			printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+	} else if (np->phy_oui == PHY_OUI_VITESSE) {
+		if (init_vitesse(dev, np)) {
+			netdev_info(dev, "%s: phy init failed\n",
+				    pci_name(np->pci_dev));
 			return PHY_ERROR;
 		}
-	}
-	if (np->phy_oui == PHY_OUI_REALTEK) {
+	} else if (np->phy_oui == PHY_OUI_REALTEK) {
 		if (np->phy_model == PHY_MODEL_REALTEK_8211 &&
 		    np->phy_rev == PHY_REV_REALTEK_8211B) {
 			/* reset could have cleared these out, set them back */
-			if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1)) {
-				printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
-				return PHY_ERROR;
-			}
-			if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG2, PHY_REALTEK_INIT2)) {
-				printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
-				return PHY_ERROR;
-			}
-			if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT3)) {
-				printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
-				return PHY_ERROR;
-			}
-			if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG3, PHY_REALTEK_INIT4)) {
-				printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
-				return PHY_ERROR;
-			}
-			if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG4, PHY_REALTEK_INIT5)) {
-				printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
-				return PHY_ERROR;
-			}
-			if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG5, PHY_REALTEK_INIT6)) {
-				printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+			if (init_realtek_8211b(dev, np)) {
+				netdev_info(dev, "%s: phy init failed\n",
+					    pci_name(np->pci_dev));
 				return PHY_ERROR;
 			}
-			if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1)) {
-				printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+		} else if (np->phy_model == PHY_MODEL_REALTEK_8201) {
+			if (init_realtek_8201(dev, np) ||
+			    init_realtek_8201_cross(dev, np)) {
+				netdev_info(dev, "%s: phy init failed\n",
+					    pci_name(np->pci_dev));
 				return PHY_ERROR;
 			}
 		}
-		if (np->phy_model == PHY_MODEL_REALTEK_8201) {
-			if (np->driver_data & DEV_NEED_PHY_INIT_FIX) {
-				phy_reserved = mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG6, MII_READ);
-				phy_reserved |= PHY_REALTEK_INIT7;
-				if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG6, phy_reserved)) {
-					printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
-					return PHY_ERROR;
-				}
-			}
-			if (phy_cross == NV_CROSSOVER_DETECTION_DISABLED) {
-				if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT3)) {
-					printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
-					return PHY_ERROR;
-				}
-				phy_reserved = mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG2, MII_READ);
-				phy_reserved &= ~PHY_REALTEK_INIT_MSK1;
-				phy_reserved |= PHY_REALTEK_INIT3;
-				if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG2, phy_reserved)) {
-					printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
-					return PHY_ERROR;
-				}
-				if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1)) {
-					printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
-					return PHY_ERROR;
-				}
-			}
-		}
 	}
 
 	/* some phys clear out pause advertisment on reset, set it back */
@@ -1501,12 +1494,10 @@ static int phy_init(struct net_device *d
 	/* restart auto negotiation, power down phy */
 	mii_control = mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ);
 	mii_control |= (BMCR_ANRESTART | BMCR_ANENABLE);
-	if (phy_power_down) {
+	if (phy_power_down)
 		mii_control |= BMCR_PDOWN;
-	}
-	if (mii_rw(dev, np->phyaddr, MII_BMCR, mii_control)) {
+	if (mii_rw(dev, np->phyaddr, MII_BMCR, mii_control))
 		return PHY_ERROR;
-	}
 
 	return 0;
 }
@@ -1517,7 +1508,6 @@ static void nv_start_rx(struct net_devic
 	u8 __iomem *base = get_hwbase(dev);
 	u32 rx_ctrl = readl(base + NvRegReceiverControl);
 
-	dprintk(KERN_DEBUG "%s: nv_start_rx\n", dev->name);
 	/* Already running? Stop it. */
 	if ((readl(base + NvRegReceiverControl) & NVREG_RCVCTL_START) && !np->mac_in_use) {
 		rx_ctrl &= ~NVREG_RCVCTL_START;
@@ -1526,12 +1516,10 @@ static void nv_start_rx(struct net_devic
 	}
 	writel(np->linkspeed, base + NvRegLinkSpeed);
 	pci_push(base);
-        rx_ctrl |= NVREG_RCVCTL_START;
-        if (np->mac_in_use)
+	rx_ctrl |= NVREG_RCVCTL_START;
+	if (np->mac_in_use)
 		rx_ctrl &= ~NVREG_RCVCTL_RX_PATH_EN;
 	writel(rx_ctrl, base + NvRegReceiverControl);
-	dprintk(KERN_DEBUG "%s: nv_start_rx to duplex %d, speed 0x%08x.\n",
-				dev->name, np->duplex, np->linkspeed);
 	pci_push(base);
 }
 
@@ -1541,15 +1529,15 @@ static void nv_stop_rx(struct net_device
 	u8 __iomem *base = get_hwbase(dev);
 	u32 rx_ctrl = readl(base + NvRegReceiverControl);
 
-	dprintk(KERN_DEBUG "%s: nv_stop_rx\n", dev->name);
 	if (!np->mac_in_use)
 		rx_ctrl &= ~NVREG_RCVCTL_START;
 	else
 		rx_ctrl |= NVREG_RCVCTL_RX_PATH_EN;
 	writel(rx_ctrl, base + NvRegReceiverControl);
-	reg_delay(dev, NvRegReceiverStatus, NVREG_RCVSTAT_BUSY, 0,
-			NV_RXSTOP_DELAY1, NV_RXSTOP_DELAY1MAX,
-			KERN_INFO "nv_stop_rx: ReceiverStatus remained busy");
+	if (reg_delay(dev, NvRegReceiverStatus, NVREG_RCVSTAT_BUSY, 0,
+		      NV_RXSTOP_DELAY1, NV_RXSTOP_DELAY1MAX))
+		netdev_info(dev, "%s: ReceiverStatus remained busy\n",
+			    __func__);
 
 	udelay(NV_RXSTOP_DELAY2);
 	if (!np->mac_in_use)
@@ -1562,7 +1550,6 @@ static void nv_start_tx(struct net_devic
 	u8 __iomem *base = get_hwbase(dev);
 	u32 tx_ctrl = readl(base + NvRegTransmitterControl);
 
-	dprintk(KERN_DEBUG "%s: nv_start_tx\n", dev->name);
 	tx_ctrl |= NVREG_XMITCTL_START;
 	if (np->mac_in_use)
 		tx_ctrl &= ~NVREG_XMITCTL_TX_PATH_EN;
@@ -1576,15 +1563,15 @@ static void nv_stop_tx(struct net_device
 	u8 __iomem *base = get_hwbase(dev);
 	u32 tx_ctrl = readl(base + NvRegTransmitterControl);
 
-	dprintk(KERN_DEBUG "%s: nv_stop_tx\n", dev->name);
 	if (!np->mac_in_use)
 		tx_ctrl &= ~NVREG_XMITCTL_START;
 	else
 		tx_ctrl |= NVREG_XMITCTL_TX_PATH_EN;
 	writel(tx_ctrl, base + NvRegTransmitterControl);
-	reg_delay(dev, NvRegTransmitterStatus, NVREG_XMITSTAT_BUSY, 0,
-			NV_TXSTOP_DELAY1, NV_TXSTOP_DELAY1MAX,
-			KERN_INFO "nv_stop_tx: TransmitterStatus remained busy");
+	if (reg_delay(dev, NvRegTransmitterStatus, NVREG_XMITSTAT_BUSY, 0,
+		      NV_TXSTOP_DELAY1, NV_TXSTOP_DELAY1MAX))
+		netdev_info(dev, "%s: TransmitterStatus remained busy\n",
+			    __func__);
 
 	udelay(NV_TXSTOP_DELAY2);
 	if (!np->mac_in_use)
@@ -1609,7 +1596,6 @@ static void nv_txrx_reset(struct net_dev
 	struct fe_priv *np = netdev_priv(dev);
 	u8 __iomem *base = get_hwbase(dev);
 
-	dprintk(KERN_DEBUG "%s: nv_txrx_reset\n", dev->name);
 	writel(NVREG_TXRXCTL_BIT2 | NVREG_TXRXCTL_RESET | np->txrxctl_bits, base + NvRegTxRxControl);
 	pci_push(base);
 	udelay(NV_TXRX_RESET_DELAY);
@@ -1623,8 +1609,6 @@ static void nv_mac_reset(struct net_devi
 	u8 __iomem *base = get_hwbase(dev);
 	u32 temp1, temp2, temp3;
 
-	dprintk(KERN_DEBUG "%s: nv_mac_reset\n", dev->name);
-
 	writel(NVREG_TXRXCTL_BIT2 | NVREG_TXRXCTL_RESET | np->txrxctl_bits, base + NvRegTxRxControl);
 	pci_push(base);
 
@@ -1745,7 +1729,7 @@ static struct net_device_stats *nv_get_s
 static int nv_alloc_rx(struct net_device *dev)
 {
 	struct fe_priv *np = netdev_priv(dev);
-	struct ring_desc* less_rx;
+	struct ring_desc *less_rx;
 
 	less_rx = np->get_rx.orig;
 	if (less_rx-- == np->first_rx.orig)
@@ -1767,9 +1751,8 @@ static int nv_alloc_rx(struct net_device
 				np->put_rx.orig = np->first_rx.orig;
 			if (unlikely(np->put_rx_ctx++ == np->last_rx_ctx))
 				np->put_rx_ctx = np->first_rx_ctx;
-		} else {
+		} else
 			return 1;
-		}
 	}
 	return 0;
 }
@@ -1777,7 +1760,7 @@ static int nv_alloc_rx(struct net_device
 static int nv_alloc_rx_optimized(struct net_device *dev)
 {
 	struct fe_priv *np = netdev_priv(dev);
-	struct ring_desc_ex* less_rx;
+	struct ring_desc_ex *less_rx;
 
 	less_rx = np->get_rx.ex;
 	if (less_rx-- == np->first_rx.ex)
@@ -1800,9 +1783,8 @@ static int nv_alloc_rx_optimized(struct
 				np->put_rx.ex = np->first_rx.ex;
 			if (unlikely(np->put_rx_ctx++ == np->last_rx_ctx))
 				np->put_rx_ctx = np->first_rx_ctx;
-		} else {
+		} else
 			return 1;
-		}
 	}
 	return 0;
 }
@@ -2018,24 +2000,24 @@ static void nv_legacybackoff_reseed(stru
 
 /* Known Good seed sets */
 static const u32 main_seedset[BACKOFF_SEEDSET_ROWS][BACKOFF_SEEDSET_LFSRS] = {
-    {145, 155, 165, 175, 185, 196, 235, 245, 255, 265, 275, 285, 660, 690, 874},
-    {245, 255, 265, 575, 385, 298, 335, 345, 355, 366, 375, 385, 761, 790, 974},
-    {145, 155, 165, 175, 185, 196, 235, 245, 255, 265, 275, 285, 660, 690, 874},
-    {245, 255, 265, 575, 385, 298, 335, 345, 355, 366, 375, 386, 761, 790, 974},
-    {266, 265, 276, 585, 397, 208, 345, 355, 365, 376, 385, 396, 771, 700, 984},
-    {266, 265, 276, 586, 397, 208, 346, 355, 365, 376, 285, 396, 771, 700, 984},
-    {366, 365, 376, 686, 497, 308, 447, 455, 466, 476, 485, 496, 871, 800,  84},
-    {466, 465, 476, 786, 597, 408, 547, 555, 566, 576, 585, 597, 971, 900, 184}};
+	{145, 155, 165, 175, 185, 196, 235, 245, 255, 265, 275, 285, 660, 690, 874},
+	{245, 255, 265, 575, 385, 298, 335, 345, 355, 366, 375, 385, 761, 790, 974},
+	{145, 155, 165, 175, 185, 196, 235, 245, 255, 265, 275, 285, 660, 690, 874},
+	{245, 255, 265, 575, 385, 298, 335, 345, 355, 366, 375, 386, 761, 790, 974},
+	{266, 265, 276, 585, 397, 208, 345, 355, 365, 376, 385, 396, 771, 700, 984},
+	{266, 265, 276, 586, 397, 208, 346, 355, 365, 376, 285, 396, 771, 700, 984},
+	{366, 365, 376, 686, 497, 308, 447, 455, 466, 476, 485, 496, 871, 800,  84},
+	{466, 465, 476, 786, 597, 408, 547, 555, 566, 576, 585, 597, 971, 900, 184} };
 
 static const u32 gear_seedset[BACKOFF_SEEDSET_ROWS][BACKOFF_SEEDSET_LFSRS] = {
-    {251, 262, 273, 324, 319, 508, 375, 364, 341, 371, 398, 193, 375,  30, 295},
-    {351, 375, 373, 469, 551, 639, 477, 464, 441, 472, 498, 293, 476, 130, 395},
-    {351, 375, 373, 469, 551, 639, 477, 464, 441, 472, 498, 293, 476, 130, 397},
-    {251, 262, 273, 324, 319, 508, 375, 364, 341, 371, 398, 193, 375,  30, 295},
-    {251, 262, 273, 324, 319, 508, 375, 364, 341, 371, 398, 193, 375,  30, 295},
-    {351, 375, 373, 469, 551, 639, 477, 464, 441, 472, 498, 293, 476, 130, 395},
-    {351, 375, 373, 469, 551, 639, 477, 464, 441, 472, 498, 293, 476, 130, 395},
-    {351, 375, 373, 469, 551, 639, 477, 464, 441, 472, 498, 293, 476, 130, 395}};
+	{251, 262, 273, 324, 319, 508, 375, 364, 341, 371, 398, 193, 375,  30, 295},
+	{351, 375, 373, 469, 551, 639, 477, 464, 441, 472, 498, 293, 476, 130, 395},
+	{351, 375, 373, 469, 551, 639, 477, 464, 441, 472, 498, 293, 476, 130, 397},
+	{251, 262, 273, 324, 319, 508, 375, 364, 341, 371, 398, 193, 375,  30, 295},
+	{251, 262, 273, 324, 319, 508, 375, 364, 341, 371, 398, 193, 375,  30, 295},
+	{351, 375, 373, 469, 551, 639, 477, 464, 441, 472, 498, 293, 476, 130, 395},
+	{351, 375, 373, 469, 551, 639, 477, 464, 441, 472, 498, 293, 476, 130, 395},
+	{351, 375, 373, 469, 551, 639, 477, 464, 441, 472, 498, 293, 476, 130, 395} };
 
 static void nv_gear_backoff_reseed(struct net_device *dev)
 {
@@ -2083,13 +2065,12 @@ static void nv_gear_backoff_reseed(struc
 	temp = NVREG_BKOFFCTRL_DEFAULT | (0 << NVREG_BKOFFCTRL_SELECT);
 	temp |= combinedSeed & NVREG_BKOFFCTRL_SEED_MASK;
 	temp |= combinedSeed >> NVREG_BKOFFCTRL_GEAR;
-	writel(temp,base + NvRegBackOffControl);
+	writel(temp, base + NvRegBackOffControl);
 
-    	/* Setup seeds for all gear LFSRs. */
+	/* Setup seeds for all gear LFSRs. */
 	get_random_bytes(&seedset, sizeof(seedset));
 	seedset = seedset % BACKOFF_SEEDSET_ROWS;
-	for (i = 1; i <= BACKOFF_SEEDSET_LFSRS; i++)
-	{
+	for (i = 1; i <= BACKOFF_SEEDSET_LFSRS; i++) {
 		temp = NVREG_BKOFFCTRL_DEFAULT | (i << NVREG_BKOFFCTRL_SELECT);
 		temp |= main_seedset[seedset][i-1] & 0x3ff;
 		temp |= ((gear_seedset[seedset][i-1] & 0x3ff) << NVREG_BKOFFCTRL_GEAR);
@@ -2113,10 +2094,10 @@ static netdev_tx_t nv_start_xmit(struct
 	u32 size = skb_headlen(skb);
 	u32 entries = (size >> NV_TX2_TSO_MAX_SHIFT) + ((size & (NV_TX2_TSO_MAX_SIZE-1)) ? 1 : 0);
 	u32 empty_slots;
-	struct ring_desc* put_tx;
-	struct ring_desc* start_tx;
-	struct ring_desc* prev_tx;
-	struct nv_skb_map* prev_tx_ctx;
+	struct ring_desc *put_tx;
+	struct ring_desc *start_tx;
+	struct ring_desc *prev_tx;
+	struct nv_skb_map *prev_tx_ctx;
 	unsigned long flags;
 
 	/* add fragments to entries count */
@@ -2204,18 +2185,6 @@ static netdev_tx_t nv_start_xmit(struct
 
 	spin_unlock_irqrestore(&np->lock, flags);
 
-	dprintk(KERN_DEBUG "%s: nv_start_xmit: entries %d queued for transmission. tx_flags_extra: %x\n",
-		dev->name, entries, tx_flags_extra);
-	{
-		int j;
-		for (j=0; j<64; j++) {
-			if ((j%16) == 0)
-				dprintk("\n%03x:", j);
-			dprintk(" %02x", ((unsigned char*)skb->data)[j]);
-		}
-		dprintk("\n");
-	}
-
 	writel(NVREG_TXRXCTL_KICK|np->txrxctl_bits, get_hwbase(dev) + NvRegTxRxControl);
 	return NETDEV_TX_OK;
 }
@@ -2233,11 +2202,11 @@ static netdev_tx_t nv_start_xmit_optimiz
 	u32 size = skb_headlen(skb);
 	u32 entries = (size >> NV_TX2_TSO_MAX_SHIFT) + ((size & (NV_TX2_TSO_MAX_SIZE-1)) ? 1 : 0);
 	u32 empty_slots;
-	struct ring_desc_ex* put_tx;
-	struct ring_desc_ex* start_tx;
-	struct ring_desc_ex* prev_tx;
-	struct nv_skb_map* prev_tx_ctx;
-	struct nv_skb_map* start_tx_ctx;
+	struct ring_desc_ex *put_tx;
+	struct ring_desc_ex *start_tx;
+	struct ring_desc_ex *prev_tx;
+	struct nv_skb_map *prev_tx_ctx;
+	struct nv_skb_map *start_tx_ctx;
 	unsigned long flags;
 
 	/* add fragments to entries count */
@@ -2355,18 +2324,6 @@ static netdev_tx_t nv_start_xmit_optimiz
 
 	spin_unlock_irqrestore(&np->lock, flags);
 
-	dprintk(KERN_DEBUG "%s: nv_start_xmit_optimized: entries %d queued for transmission. tx_flags_extra: %x\n",
-		dev->name, entries, tx_flags_extra);
-	{
-		int j;
-		for (j=0; j<64; j++) {
-			if ((j%16) == 0)
-				dprintk("\n%03x:", j);
-			dprintk(" %02x", ((unsigned char*)skb->data)[j]);
-		}
-		dprintk("\n");
-	}
-
 	writel(NVREG_TXRXCTL_KICK|np->txrxctl_bits, get_hwbase(dev) + NvRegTxRxControl);
 	return NETDEV_TX_OK;
 }
@@ -2399,15 +2356,12 @@ static int nv_tx_done(struct net_device
 	struct fe_priv *np = netdev_priv(dev);
 	u32 flags;
 	int tx_work = 0;
-	struct ring_desc* orig_get_tx = np->get_tx.orig;
+	struct ring_desc *orig_get_tx = np->get_tx.orig;
 
 	while ((np->get_tx.orig != np->put_tx.orig) &&
 	       !((flags = le32_to_cpu(np->get_tx.orig->flaglen)) & NV_TX_VALID) &&
 	       (tx_work < limit)) {
 
-		dprintk(KERN_DEBUG "%s: nv_tx_done: flags 0x%x.\n",
-					dev->name, flags);
-
 		nv_unmap_txskb(np, np->get_tx_ctx);
 
 		if (np->desc_ver == DESC_VER_1) {
@@ -2464,15 +2418,12 @@ static int nv_tx_done_optimized(struct n
 	struct fe_priv *np = netdev_priv(dev);
 	u32 flags;
 	int tx_work = 0;
-	struct ring_desc_ex* orig_get_tx = np->get_tx.ex;
+	struct ring_desc_ex *orig_get_tx = np->get_tx.ex;
 
 	while ((np->get_tx.ex != np->put_tx.ex) &&
 	       !((flags = le32_to_cpu(np->get_tx.ex->flaglen)) & NV_TX2_VALID) &&
 	       (tx_work < limit)) {
 
-		dprintk(KERN_DEBUG "%s: nv_tx_done_optimized: flags 0x%x.\n",
-					dev->name, flags);
-
 		nv_unmap_txskb(np, np->get_tx_ctx);
 
 		if (flags & NV_TX2_LASTPACKET) {
@@ -2491,9 +2442,8 @@ static int nv_tx_done_optimized(struct n
 			np->get_tx_ctx->skb = NULL;
 			tx_work++;
 
-			if (np->tx_limit) {
+			if (np->tx_limit)
 				nv_tx_flip_ownership(dev);
-			}
 		}
 		if (unlikely(np->get_tx.ex++ == np->last_tx.ex))
 			np->get_tx.ex = np->first_tx.ex;
@@ -2518,57 +2468,56 @@ static void nv_tx_timeout(struct net_dev
 	u32 status;
 	union ring_type put_tx;
 	int saved_tx_limit;
+	int i;
 
 	if (np->msi_flags & NV_MSI_X_ENABLED)
 		status = readl(base + NvRegMSIXIrqStatus) & NVREG_IRQSTAT_MASK;
 	else
 		status = readl(base + NvRegIrqStatus) & NVREG_IRQSTAT_MASK;
 
-	printk(KERN_INFO "%s: Got tx_timeout. irq: %08x\n", dev->name, status);
-
-	{
-		int i;
+	netdev_info(dev, "Got tx_timeout. irq: %08x\n", status);
 
-		printk(KERN_INFO "%s: Ring at %lx\n",
-		       dev->name, (unsigned long)np->ring_addr);
-		printk(KERN_INFO "%s: Dumping tx registers\n", dev->name);
-		for (i=0;i<=np->register_size;i+= 32) {
-			printk(KERN_INFO "%3x: %08x %08x %08x %08x %08x %08x %08x %08x\n",
-					i,
-					readl(base + i + 0), readl(base + i + 4),
-					readl(base + i + 8), readl(base + i + 12),
-					readl(base + i + 16), readl(base + i + 20),
-					readl(base + i + 24), readl(base + i + 28));
-		}
-		printk(KERN_INFO "%s: Dumping tx ring\n", dev->name);
-		for (i=0;i<np->tx_ring_size;i+= 4) {
-			if (!nv_optimized(np)) {
-				printk(KERN_INFO "%03x: %08x %08x // %08x %08x // %08x %08x // %08x %08x\n",
-				       i,
-				       le32_to_cpu(np->tx_ring.orig[i].buf),
-				       le32_to_cpu(np->tx_ring.orig[i].flaglen),
-				       le32_to_cpu(np->tx_ring.orig[i+1].buf),
-				       le32_to_cpu(np->tx_ring.orig[i+1].flaglen),
-				       le32_to_cpu(np->tx_ring.orig[i+2].buf),
-				       le32_to_cpu(np->tx_ring.orig[i+2].flaglen),
-				       le32_to_cpu(np->tx_ring.orig[i+3].buf),
-				       le32_to_cpu(np->tx_ring.orig[i+3].flaglen));
-			} else {
-				printk(KERN_INFO "%03x: %08x %08x %08x // %08x %08x %08x // %08x %08x %08x // %08x %08x %08x\n",
-				       i,
-				       le32_to_cpu(np->tx_ring.ex[i].bufhigh),
-				       le32_to_cpu(np->tx_ring.ex[i].buflow),
-				       le32_to_cpu(np->tx_ring.ex[i].flaglen),
-				       le32_to_cpu(np->tx_ring.ex[i+1].bufhigh),
-				       le32_to_cpu(np->tx_ring.ex[i+1].buflow),
-				       le32_to_cpu(np->tx_ring.ex[i+1].flaglen),
-				       le32_to_cpu(np->tx_ring.ex[i+2].bufhigh),
-				       le32_to_cpu(np->tx_ring.ex[i+2].buflow),
-				       le32_to_cpu(np->tx_ring.ex[i+2].flaglen),
-				       le32_to_cpu(np->tx_ring.ex[i+3].bufhigh),
-				       le32_to_cpu(np->tx_ring.ex[i+3].buflow),
-				       le32_to_cpu(np->tx_ring.ex[i+3].flaglen));
-			}
+	netdev_info(dev, "Ring at %lx\n", (unsigned long)np->ring_addr);
+	netdev_info(dev, "Dumping tx registers\n");
+	for (i = 0; i <= np->register_size; i += 32) {
+		netdev_info(dev,
+			    "%3x: %08x %08x %08x %08x %08x %08x %08x %08x\n",
+			    i,
+			    readl(base + i + 0), readl(base + i + 4),
+			    readl(base + i + 8), readl(base + i + 12),
+			    readl(base + i + 16), readl(base + i + 20),
+			    readl(base + i + 24), readl(base + i + 28));
+	}
+	netdev_info(dev, "Dumping tx ring\n");
+	for (i = 0; i < np->tx_ring_size; i += 4) {
+		if (!nv_optimized(np)) {
+			netdev_info(dev,
+				    "%03x: %08x %08x // %08x %08x // %08x %08x // %08x %08x\n",
+				    i,
+				    le32_to_cpu(np->tx_ring.orig[i].buf),
+				    le32_to_cpu(np->tx_ring.orig[i].flaglen),
+				    le32_to_cpu(np->tx_ring.orig[i+1].buf),
+				    le32_to_cpu(np->tx_ring.orig[i+1].flaglen),
+				    le32_to_cpu(np->tx_ring.orig[i+2].buf),
+				    le32_to_cpu(np->tx_ring.orig[i+2].flaglen),
+				    le32_to_cpu(np->tx_ring.orig[i+3].buf),
+				    le32_to_cpu(np->tx_ring.orig[i+3].flaglen));
+		} else {
+			netdev_info(dev,
+				    "%03x: %08x %08x %08x // %08x %08x %08x // %08x %08x %08x // %08x %08x %08x\n",
+				    i,
+				    le32_to_cpu(np->tx_ring.ex[i].bufhigh),
+				    le32_to_cpu(np->tx_ring.ex[i].buflow),
+				    le32_to_cpu(np->tx_ring.ex[i].flaglen),
+				    le32_to_cpu(np->tx_ring.ex[i+1].bufhigh),
+				    le32_to_cpu(np->tx_ring.ex[i+1].buflow),
+				    le32_to_cpu(np->tx_ring.ex[i+1].flaglen),
+				    le32_to_cpu(np->tx_ring.ex[i+2].bufhigh),
+				    le32_to_cpu(np->tx_ring.ex[i+2].buflow),
+				    le32_to_cpu(np->tx_ring.ex[i+2].flaglen),
+				    le32_to_cpu(np->tx_ring.ex[i+3].bufhigh),
+				    le32_to_cpu(np->tx_ring.ex[i+3].buflow),
+				    le32_to_cpu(np->tx_ring.ex[i+3].flaglen));
 		}
 	}
 
@@ -2616,15 +2565,13 @@ static int nv_getlen(struct net_device *
 	int protolen;	/* length as stored in the proto field */
 
 	/* 1) calculate len according to header */
-	if ( ((struct vlan_ethhdr *)packet)->h_vlan_proto == htons(ETH_P_8021Q)) {
-		protolen = ntohs( ((struct vlan_ethhdr *)packet)->h_vlan_encapsulated_proto );
+	if (((struct vlan_ethhdr *)packet)->h_vlan_proto == htons(ETH_P_8021Q)) {
+		protolen = ntohs(((struct vlan_ethhdr *)packet)->h_vlan_encapsulated_proto);
 		hdrlen = VLAN_HLEN;
 	} else {
-		protolen = ntohs( ((struct ethhdr *)packet)->h_proto);
+		protolen = ntohs(((struct ethhdr *)packet)->h_proto);
 		hdrlen = ETH_HLEN;
 	}
-	dprintk(KERN_DEBUG "%s: nv_getlen: datalen %d, protolen %d, hdrlen %d\n",
-				dev->name, datalen, protolen, hdrlen);
 	if (protolen > ETH_DATA_LEN)
 		return datalen; /* Value in proto field not a len, no checks possible */
 
@@ -2635,26 +2582,18 @@ static int nv_getlen(struct net_device *
 			/* more data on wire than in 802 header, trim of
 			 * additional data.
 			 */
-			dprintk(KERN_DEBUG "%s: nv_getlen: accepting %d bytes.\n",
-					dev->name, protolen);
 			return protolen;
 		} else {
 			/* less data on wire than mentioned in header.
 			 * Discard the packet.
 			 */
-			dprintk(KERN_DEBUG "%s: nv_getlen: discarding long packet.\n",
-					dev->name);
 			return -1;
 		}
 	} else {
 		/* short packet. Accept only if 802 values are also short */
 		if (protolen > ETH_ZLEN) {
-			dprintk(KERN_DEBUG "%s: nv_getlen: discarding short packet.\n",
-					dev->name);
 			return -1;
 		}
-		dprintk(KERN_DEBUG "%s: nv_getlen: accepting %d bytes.\n",
-				dev->name, datalen);
 		return datalen;
 	}
 }
@@ -2667,13 +2606,10 @@ static int nv_rx_process(struct net_devi
 	struct sk_buff *skb;
 	int len;
 
-	while((np->get_rx.orig != np->put_rx.orig) &&
+	while ((np->get_rx.orig != np->put_rx.orig) &&
 	      !((flags = le32_to_cpu(np->get_rx.orig->flaglen)) & NV_RX_AVAIL) &&
 		(rx_work < limit)) {
 
-		dprintk(KERN_DEBUG "%s: nv_rx_process: flags 0x%x.\n",
-					dev->name, flags);
-
 		/*
 		 * the packet is for us - immediately tear down the pci mapping.
 		 * TODO: check if a prefetch of the first cacheline improves
@@ -2685,16 +2621,6 @@ static int nv_rx_process(struct net_devi
 		skb = np->get_rx_ctx->skb;
 		np->get_rx_ctx->skb = NULL;
 
-		{
-			int j;
-			dprintk(KERN_DEBUG "Dumping packet (flags 0x%x).",flags);
-			for (j=0; j<64; j++) {
-				if ((j%16) == 0)
-					dprintk("\n%03x:", j);
-				dprintk(" %02x", ((unsigned char*)skb->data)[j]);
-			}
-			dprintk("\n");
-		}
 		/* look at what we actually got: */
 		if (np->desc_ver == DESC_VER_1) {
 			if (likely(flags & NV_RX_DESCRIPTORVALID)) {
@@ -2710,9 +2636,8 @@ static int nv_rx_process(struct net_devi
 					}
 					/* framing errors are soft errors */
 					else if ((flags & NV_RX_ERROR_MASK) == NV_RX_FRAMINGERR) {
-						if (flags & NV_RX_SUBSTRACT1) {
+						if (flags & NV_RX_SUBSTRACT1)
 							len--;
-						}
 					}
 					/* the rest are hard errors */
 					else {
@@ -2745,9 +2670,8 @@ static int nv_rx_process(struct net_devi
 					}
 					/* framing errors are soft errors */
 					else if ((flags & NV_RX2_ERROR_MASK) == NV_RX2_FRAMINGERR) {
-						if (flags & NV_RX2_SUBSTRACT1) {
+						if (flags & NV_RX2_SUBSTRACT1)
 							len--;
-						}
 					}
 					/* the rest are hard errors */
 					else {
@@ -2771,8 +2695,6 @@ static int nv_rx_process(struct net_devi
 		/* got a valid packet - forward it to the network core */
 		skb_put(skb, len);
 		skb->protocol = eth_type_trans(skb, dev);
-		dprintk(KERN_DEBUG "%s: nv_rx_process: %d bytes, proto %d accepted.\n",
-					dev->name, len, skb->protocol);
 		napi_gro_receive(&np->napi, skb);
 		dev->stats.rx_packets++;
 		dev->stats.rx_bytes += len;
@@ -2797,13 +2719,10 @@ static int nv_rx_process_optimized(struc
 	struct sk_buff *skb;
 	int len;
 
-	while((np->get_rx.ex != np->put_rx.ex) &&
+	while ((np->get_rx.ex != np->put_rx.ex) &&
 	      !((flags = le32_to_cpu(np->get_rx.ex->flaglen)) & NV_RX2_AVAIL) &&
 	      (rx_work < limit)) {
 
-		dprintk(KERN_DEBUG "%s: nv_rx_process_optimized: flags 0x%x.\n",
-					dev->name, flags);
-
 		/*
 		 * the packet is for us - immediately tear down the pci mapping.
 		 * TODO: check if a prefetch of the first cacheline improves
@@ -2815,16 +2734,6 @@ static int nv_rx_process_optimized(struc
 		skb = np->get_rx_ctx->skb;
 		np->get_rx_ctx->skb = NULL;
 
-		{
-			int j;
-			dprintk(KERN_DEBUG "Dumping packet (flags 0x%x).",flags);
-			for (j=0; j<64; j++) {
-				if ((j%16) == 0)
-					dprintk("\n%03x:", j);
-				dprintk(" %02x", ((unsigned char*)skb->data)[j]);
-			}
-			dprintk("\n");
-		}
 		/* look at what we actually got: */
 		if (likely(flags & NV_RX2_DESCRIPTORVALID)) {
 			len = flags & LEN_MASK_V2;
@@ -2838,9 +2747,8 @@ static int nv_rx_process_optimized(struc
 				}
 				/* framing errors are soft errors */
 				else if ((flags & NV_RX2_ERROR_MASK) == NV_RX2_FRAMINGERR) {
-					if (flags & NV_RX2_SUBSTRACT1) {
+					if (flags & NV_RX2_SUBSTRACT1)
 						len--;
-					}
 				}
 				/* the rest are hard errors */
 				else {
@@ -2858,9 +2766,6 @@ static int nv_rx_process_optimized(struc
 			skb->protocol = eth_type_trans(skb, dev);
 			prefetch(skb->data);
 
-			dprintk(KERN_DEBUG "%s: nv_rx_process_optimized: %d bytes, proto %d accepted.\n",
-				dev->name, len, skb->protocol);
-
 			if (likely(!np->vlangrp)) {
 				napi_gro_receive(&np->napi, skb);
 			} else {
@@ -2949,7 +2854,7 @@ static int nv_change_mtu(struct net_devi
 		/* reinit nic view of the rx queue */
 		writel(np->rx_buf_sz, base + NvRegOffloadConfig);
 		setup_hw_rings(dev, NV_SETUP_RX_RING | NV_SETUP_TX_RING);
-		writel( ((np->rx_ring_size-1) << NVREG_RINGSZ_RXSHIFT) + ((np->tx_ring_size-1) << NVREG_RINGSZ_TXSHIFT),
+		writel(((np->rx_ring_size-1) << NVREG_RINGSZ_RXSHIFT) + ((np->tx_ring_size-1) << NVREG_RINGSZ_TXSHIFT),
 			base + NvRegRingSizes);
 		pci_push(base);
 		writel(NVREG_TXRXCTL_KICK|np->txrxctl_bits, get_hwbase(dev) + NvRegTxRxControl);
@@ -2986,7 +2891,7 @@ static void nv_copy_mac_to_hw(struct net
 static int nv_set_mac_address(struct net_device *dev, void *addr)
 {
 	struct fe_priv *np = netdev_priv(dev);
-	struct sockaddr *macaddr = (struct sockaddr*)addr;
+	struct sockaddr *macaddr = (struct sockaddr *)addr;
 
 	if (!is_valid_ether_addr(macaddr->sa_data))
 		return -EADDRNOTAVAIL;
@@ -3076,8 +2981,6 @@ static void nv_set_multicast(struct net_
 	writel(mask[0], base + NvRegMulticastMaskA);
 	writel(mask[1], base + NvRegMulticastMaskB);
 	writel(pff, base + NvRegPacketFilterFlags);
-	dprintk(KERN_INFO "%s: reconfiguration for multicast lists.\n",
-		dev->name);
 	nv_start_rx(dev);
 	spin_unlock_irq(&np->lock);
 }
@@ -3152,8 +3055,6 @@ static int nv_update_linkspeed(struct ne
 	mii_status = mii_rw(dev, np->phyaddr, MII_BMSR, MII_READ);
 
 	if (!(mii_status & BMSR_LSTATUS)) {
-		dprintk(KERN_DEBUG "%s: no link detected by phy - falling back to 10HD.\n",
-				dev->name);
 		newls = NVREG_LINKSPEED_FORCE|NVREG_LINKSPEED_10;
 		newdup = 0;
 		retval = 0;
@@ -3161,8 +3062,6 @@ static int nv_update_linkspeed(struct ne
 	}
 
 	if (np->autoneg == 0) {
-		dprintk(KERN_DEBUG "%s: nv_update_linkspeed: autoneg off, PHY set to 0x%04x.\n",
-				dev->name, np->fixed_mode);
 		if (np->fixed_mode & LPA_100FULL) {
 			newls = NVREG_LINKSPEED_FORCE|NVREG_LINKSPEED_100;
 			newdup = 1;
@@ -3185,14 +3084,11 @@ static int nv_update_linkspeed(struct ne
 		newls = NVREG_LINKSPEED_FORCE|NVREG_LINKSPEED_10;
 		newdup = 0;
 		retval = 0;
-		dprintk(KERN_DEBUG "%s: autoneg not completed - falling back to 10HD.\n", dev->name);
 		goto set_speed;
 	}
 
 	adv = mii_rw(dev, np->phyaddr, MII_ADVERTISE, MII_READ);
 	lpa = mii_rw(dev, np->phyaddr, MII_LPA, MII_READ);
-	dprintk(KERN_DEBUG "%s: nv_update_linkspeed: PHY advertises 0x%04x, lpa 0x%04x.\n",
-				dev->name, adv, lpa);
 
 	retval = 1;
 	if (np->gigabit == PHY_GIGABIT) {
@@ -3201,8 +3097,6 @@ static int nv_update_linkspeed(struct ne
 
 		if ((control_1000 & ADVERTISE_1000FULL) &&
 			(status_1000 & LPA_1000FULL)) {
-			dprintk(KERN_DEBUG "%s: nv_update_linkspeed: GBit ethernet detected.\n",
-				dev->name);
 			newls = NVREG_LINKSPEED_FORCE|NVREG_LINKSPEED_1000;
 			newdup = 1;
 			goto set_speed;
@@ -3224,7 +3118,6 @@ static int nv_update_linkspeed(struct ne
 		newls = NVREG_LINKSPEED_FORCE|NVREG_LINKSPEED_10;
 		newdup = 0;
 	} else {
-		dprintk(KERN_DEBUG "%s: bad ability %04x - falling back to 10HD.\n", dev->name, adv_lpa);
 		newls = NVREG_LINKSPEED_FORCE|NVREG_LINKSPEED_10;
 		newdup = 0;
 	}
@@ -3233,9 +3126,6 @@ set_speed:
 	if (np->duplex == newdup && np->linkspeed == newls)
 		return retval;
 
-	dprintk(KERN_INFO "%s: changing link setting from %d/%d to %d/%d.\n",
-			dev->name, np->linkspeed, np->duplex, newls, newdup);
-
 	np->duplex = newdup;
 	np->linkspeed = newls;
 
@@ -3302,7 +3192,7 @@ set_speed:
 	}
 	writel(txreg, base + NvRegTxWatermark);
 
-	writel(NVREG_MISC1_FORCE | ( np->duplex ? 0 : NVREG_MISC1_HD),
+	writel(NVREG_MISC1_FORCE | (np->duplex ? 0 : NVREG_MISC1_HD),
 		base + NvRegMisc1);
 	pci_push(base);
 	writel(np->linkspeed, base + NvRegLinkSpeed);
@@ -3312,8 +3202,8 @@ set_speed:
 	/* setup pause frame */
 	if (np->duplex != 0) {
 		if (np->autoneg && np->pause_flags & NV_PAUSEFRAME_AUTONEG) {
-			adv_pause = adv & (ADVERTISE_PAUSE_CAP| ADVERTISE_PAUSE_ASYM);
-			lpa_pause = lpa & (LPA_PAUSE_CAP| LPA_PAUSE_ASYM);
+			adv_pause = adv & (ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM);
+			lpa_pause = lpa & (LPA_PAUSE_CAP | LPA_PAUSE_ASYM);
 
 			switch (adv_pause) {
 			case ADVERTISE_PAUSE_CAP:
@@ -3324,22 +3214,17 @@ set_speed:
 				}
 				break;
 			case ADVERTISE_PAUSE_ASYM:
-				if (lpa_pause == (LPA_PAUSE_CAP| LPA_PAUSE_ASYM))
-				{
+				if (lpa_pause == (LPA_PAUSE_CAP | LPA_PAUSE_ASYM))
 					pause_flags |= NV_PAUSEFRAME_TX_ENABLE;
-				}
 				break;
-			case ADVERTISE_PAUSE_CAP| ADVERTISE_PAUSE_ASYM:
-				if (lpa_pause & LPA_PAUSE_CAP)
-				{
+			case ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM:
+				if (lpa_pause & LPA_PAUSE_CAP) {
 					pause_flags |=  NV_PAUSEFRAME_RX_ENABLE;
 					if (np->pause_flags & NV_PAUSEFRAME_TX_REQ)
 						pause_flags |= NV_PAUSEFRAME_TX_ENABLE;
 				}
 				if (lpa_pause == LPA_PAUSE_ASYM)
-				{
 					pause_flags |= NV_PAUSEFRAME_RX_ENABLE;
-				}
 				break;
 			}
 		} else {
@@ -3361,14 +3246,14 @@ static void nv_linkchange(struct net_dev
 	if (nv_update_linkspeed(dev)) {
 		if (!netif_carrier_ok(dev)) {
 			netif_carrier_on(dev);
-			printk(KERN_INFO "%s: link up.\n", dev->name);
+			netdev_info(dev, "link up\n");
 			nv_txrx_gate(dev, false);
 			nv_start_rx(dev);
 		}
 	} else {
 		if (netif_carrier_ok(dev)) {
 			netif_carrier_off(dev);
-			printk(KERN_INFO "%s: link down.\n", dev->name);
+			netdev_info(dev, "link down\n");
 			nv_txrx_gate(dev, true);
 			nv_stop_rx(dev);
 		}
@@ -3382,11 +3267,9 @@ static void nv_link_irq(struct net_devic
 
 	miistat = readl(base + NvRegMIIStatus);
 	writel(NVREG_MIISTAT_LINKCHANGE, base + NvRegMIIStatus);
-	dprintk(KERN_INFO "%s: link change irq, status 0x%x.\n", dev->name, miistat);
 
 	if (miistat & (NVREG_MIISTAT_LINKCHANGE))
 		nv_linkchange(dev);
-	dprintk(KERN_DEBUG "%s: link change notification done.\n", dev->name);
 }
 
 static void nv_msi_workaround(struct fe_priv *np)
@@ -3437,8 +3320,6 @@ static irqreturn_t nv_nic_irq(int foo, v
 	struct fe_priv *np = netdev_priv(dev);
 	u8 __iomem *base = get_hwbase(dev);
 
-	dprintk(KERN_DEBUG "%s: nv_nic_irq\n", dev->name);
-
 	if (!(np->msi_flags & NV_MSI_X_ENABLED)) {
 		np->events = readl(base + NvRegIrqStatus);
 		writel(np->events, base + NvRegIrqStatus);
@@ -3446,7 +3327,6 @@ static irqreturn_t nv_nic_irq(int foo, v
 		np->events = readl(base + NvRegMSIXIrqStatus);
 		writel(np->events, base + NvRegMSIXIrqStatus);
 	}
-	dprintk(KERN_DEBUG "%s: irq: %08x\n", dev->name, np->events);
 	if (!(np->events & np->irqmask))
 		return IRQ_NONE;
 
@@ -3460,8 +3340,6 @@ static irqreturn_t nv_nic_irq(int foo, v
 		__napi_schedule(&np->napi);
 	}
 
-	dprintk(KERN_DEBUG "%s: nv_nic_irq completed\n", dev->name);
-
 	return IRQ_HANDLED;
 }
 
@@ -3476,8 +3354,6 @@ static irqreturn_t nv_nic_irq_optimized(
 	struct fe_priv *np = netdev_priv(dev);
 	u8 __iomem *base = get_hwbase(dev);
 
-	dprintk(KERN_DEBUG "%s: nv_nic_irq_optimized\n", dev->name);
-
 	if (!(np->msi_flags & NV_MSI_X_ENABLED)) {
 		np->events = readl(base + NvRegIrqStatus);
 		writel(np->events, base + NvRegIrqStatus);
@@ -3485,7 +3361,6 @@ static irqreturn_t nv_nic_irq_optimized(
 		np->events = readl(base + NvRegMSIXIrqStatus);
 		writel(np->events, base + NvRegMSIXIrqStatus);
 	}
-	dprintk(KERN_DEBUG "%s: irq: %08x\n", dev->name, np->events);
 	if (!(np->events & np->irqmask))
 		return IRQ_NONE;
 
@@ -3498,7 +3373,6 @@ static irqreturn_t nv_nic_irq_optimized(
 		writel(0, base + NvRegIrqMask);
 		__napi_schedule(&np->napi);
 	}
-	dprintk(KERN_DEBUG "%s: nv_nic_irq_optimized completed\n", dev->name);
 
 	return IRQ_HANDLED;
 }
@@ -3512,12 +3386,9 @@ static irqreturn_t nv_nic_irq_tx(int foo
 	int i;
 	unsigned long flags;
 
-	dprintk(KERN_DEBUG "%s: nv_nic_irq_tx\n", dev->name);
-
-	for (i=0; ; i++) {
+	for (i = 0;; i++) {
 		events = readl(base + NvRegMSIXIrqStatus) & NVREG_IRQ_TX_ALL;
 		writel(NVREG_IRQ_TX_ALL, base + NvRegMSIXIrqStatus);
-		dprintk(KERN_DEBUG "%s: tx irq: %08x\n", dev->name, events);
 		if (!(events & np->irqmask))
 			break;
 
@@ -3536,12 +3407,12 @@ static irqreturn_t nv_nic_irq_tx(int foo
 				mod_timer(&np->nic_poll, jiffies + POLL_WAIT);
 			}
 			spin_unlock_irqrestore(&np->lock, flags);
-			printk(KERN_DEBUG "%s: too many iterations (%d) in nv_nic_irq_tx.\n", dev->name, i);
+			netdev_dbg(dev, "%s: too many iterations (%d)\n",
+				   __func__, i);
 			break;
 		}
 
 	}
-	dprintk(KERN_DEBUG "%s: nv_nic_irq_tx completed\n", dev->name);
 
 	return IRQ_RETVAL(i);
 }
@@ -3553,7 +3424,7 @@ static int nv_napi_poll(struct napi_stru
 	u8 __iomem *base = get_hwbase(dev);
 	unsigned long flags;
 	int retcode;
-	int rx_count, tx_work=0, rx_work=0;
+	int rx_count, tx_work = 0, rx_work = 0;
 
 	do {
 		if (!nv_optimized(np)) {
@@ -3626,12 +3497,9 @@ static irqreturn_t nv_nic_irq_rx(int foo
 	int i;
 	unsigned long flags;
 
-	dprintk(KERN_DEBUG "%s: nv_nic_irq_rx\n", dev->name);
-
-	for (i=0; ; i++) {
+	for (i = 0;; i++) {
 		events = readl(base + NvRegMSIXIrqStatus) & NVREG_IRQ_RX_ALL;
 		writel(NVREG_IRQ_RX_ALL, base + NvRegMSIXIrqStatus);
-		dprintk(KERN_DEBUG "%s: rx irq: %08x\n", dev->name, events);
 		if (!(events & np->irqmask))
 			break;
 
@@ -3655,11 +3523,11 @@ static irqreturn_t nv_nic_irq_rx(int foo
 				mod_timer(&np->nic_poll, jiffies + POLL_WAIT);
 			}
 			spin_unlock_irqrestore(&np->lock, flags);
-			printk(KERN_DEBUG "%s: too many iterations (%d) in nv_nic_irq_rx.\n", dev->name, i);
+			netdev_dbg(dev, "%s: too many iterations (%d)\n",
+				   __func__, i);
 			break;
 		}
 	}
-	dprintk(KERN_DEBUG "%s: nv_nic_irq_rx completed\n", dev->name);
 
 	return IRQ_RETVAL(i);
 }
@@ -3673,12 +3541,9 @@ static irqreturn_t nv_nic_irq_other(int
 	int i;
 	unsigned long flags;
 
-	dprintk(KERN_DEBUG "%s: nv_nic_irq_other\n", dev->name);
-
-	for (i=0; ; i++) {
+	for (i = 0;; i++) {
 		events = readl(base + NvRegMSIXIrqStatus) & NVREG_IRQ_OTHER;
 		writel(NVREG_IRQ_OTHER, base + NvRegMSIXIrqStatus);
-		dprintk(KERN_DEBUG "%s: irq: %08x\n", dev->name, events);
 		if (!(events & np->irqmask))
 			break;
 
@@ -3723,12 +3588,12 @@ static irqreturn_t nv_nic_irq_other(int
 				mod_timer(&np->nic_poll, jiffies + POLL_WAIT);
 			}
 			spin_unlock_irqrestore(&np->lock, flags);
-			printk(KERN_DEBUG "%s: too many iterations (%d) in nv_nic_irq_other.\n", dev->name, i);
+			netdev_dbg(dev, "%s: too many iterations (%d)\n",
+				   __func__, i);
 			break;
 		}
 
 	}
-	dprintk(KERN_DEBUG "%s: nv_nic_irq_other completed\n", dev->name);
 
 	return IRQ_RETVAL(i);
 }
@@ -3740,8 +3605,6 @@ static irqreturn_t nv_nic_irq_test(int f
 	u8 __iomem *base = get_hwbase(dev);
 	u32 events;
 
-	dprintk(KERN_DEBUG "%s: nv_nic_irq_test\n", dev->name);
-
 	if (!(np->msi_flags & NV_MSI_X_ENABLED)) {
 		events = readl(base + NvRegIrqStatus) & NVREG_IRQSTAT_MASK;
 		writel(NVREG_IRQ_TIMER, base + NvRegIrqStatus);
@@ -3750,7 +3613,6 @@ static irqreturn_t nv_nic_irq_test(int f
 		writel(NVREG_IRQ_TIMER, base + NvRegMSIXIrqStatus);
 	}
 	pci_push(base);
-	dprintk(KERN_DEBUG "%s: irq: %08x\n", dev->name, events);
 	if (!(events & NVREG_IRQ_TIMER))
 		return IRQ_RETVAL(0);
 
@@ -3760,8 +3622,6 @@ static irqreturn_t nv_nic_irq_test(int f
 	np->intr_test = 1;
 	spin_unlock(&np->lock);
 
-	dprintk(KERN_DEBUG "%s: nv_nic_irq_test completed\n", dev->name);
-
 	return IRQ_RETVAL(1);
 }
 
@@ -3776,17 +3636,15 @@ static void set_msix_vector_map(struct n
 	 * the remaining 8 interrupts.
 	 */
 	for (i = 0; i < 8; i++) {
-		if ((irqmask >> i) & 0x1) {
+		if ((irqmask >> i) & 0x1)
 			msixmap |= vector << (i << 2);
-		}
 	}
 	writel(readl(base + NvRegMSIXMap0) | msixmap, base + NvRegMSIXMap0);
 
 	msixmap = 0;
 	for (i = 0; i < 8; i++) {
-		if ((irqmask >> (i + 8)) & 0x1) {
+		if ((irqmask >> (i + 8)) & 0x1)
 			msixmap |= vector << (i << 2);
-		}
 	}
 	writel(readl(base + NvRegMSIXMap1) | msixmap, base + NvRegMSIXMap1);
 }
@@ -3809,17 +3667,19 @@ static int nv_request_irq(struct net_dev
 	}
 
 	if (np->msi_flags & NV_MSI_X_CAPABLE) {
-		for (i = 0; i < (np->msi_flags & NV_MSI_X_VECTORS_MASK); i++) {
+		for (i = 0; i < (np->msi_flags & NV_MSI_X_VECTORS_MASK); i++)
 			np->msi_x_entry[i].entry = i;
-		}
-		if ((ret = pci_enable_msix(np->pci_dev, np->msi_x_entry, (np->msi_flags & NV_MSI_X_VECTORS_MASK))) == 0) {
+		ret = pci_enable_msix(np->pci_dev, np->msi_x_entry, (np->msi_flags & NV_MSI_X_VECTORS_MASK));
+		if (ret == 0) {
 			np->msi_flags |= NV_MSI_X_ENABLED;
 			if (optimization_mode == NV_OPTIMIZATION_MODE_THROUGHPUT && !intr_test) {
 				/* Request irq for rx handling */
 				sprintf(np->name_rx, "%s-rx", dev->name);
 				if (request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector,
 						nv_nic_irq_rx, IRQF_SHARED, np->name_rx, dev) != 0) {
-					printk(KERN_INFO "forcedeth: request_irq failed for rx %d\n", ret);
+					netdev_info(dev,
+						    "request_irq failed for rx %d\n",
+						    ret);
 					pci_disable_msix(np->pci_dev);
 					np->msi_flags &= ~NV_MSI_X_ENABLED;
 					goto out_err;
@@ -3828,7 +3688,9 @@ static int nv_request_irq(struct net_dev
 				sprintf(np->name_tx, "%s-tx", dev->name);
 				if (request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector,
 						nv_nic_irq_tx, IRQF_SHARED, np->name_tx, dev) != 0) {
-					printk(KERN_INFO "forcedeth: request_irq failed for tx %d\n", ret);
+					netdev_info(dev,
+						    "request_irq failed for tx %d\n",
+						    ret);
 					pci_disable_msix(np->pci_dev);
 					np->msi_flags &= ~NV_MSI_X_ENABLED;
 					goto out_free_rx;
@@ -3837,7 +3699,9 @@ static int nv_request_irq(struct net_dev
 				sprintf(np->name_other, "%s-other", dev->name);
 				if (request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_OTHER].vector,
 						nv_nic_irq_other, IRQF_SHARED, np->name_other, dev) != 0) {
-					printk(KERN_INFO "forcedeth: request_irq failed for link %d\n", ret);
+					netdev_info(dev,
+						    "request_irq failed for link %d\n",
+						    ret);
 					pci_disable_msix(np->pci_dev);
 					np->msi_flags &= ~NV_MSI_X_ENABLED;
 					goto out_free_tx;
@@ -3851,7 +3715,9 @@ static int nv_request_irq(struct net_dev
 			} else {
 				/* Request irq for all interrupts */
 				if (request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector, handler, IRQF_SHARED, dev->name, dev) != 0) {
-					printk(KERN_INFO "forcedeth: request_irq failed %d\n", ret);
+					netdev_info(dev,
+						    "request_irq failed %d\n",
+						    ret);
 					pci_disable_msix(np->pci_dev);
 					np->msi_flags &= ~NV_MSI_X_ENABLED;
 					goto out_err;
@@ -3864,11 +3730,13 @@ static int nv_request_irq(struct net_dev
 		}
 	}
 	if (ret != 0 && np->msi_flags & NV_MSI_CAPABLE) {
-		if ((ret = pci_enable_msi(np->pci_dev)) == 0) {
+		ret = pci_enable_msi(np->pci_dev);
+		if (ret == 0) {
 			np->msi_flags |= NV_MSI_ENABLED;
 			dev->irq = np->pci_dev->irq;
 			if (request_irq(np->pci_dev->irq, handler, IRQF_SHARED, dev->name, dev) != 0) {
-				printk(KERN_INFO "forcedeth: request_irq failed %d\n", ret);
+				netdev_info(dev, "request_irq failed %d\n",
+					    ret);
 				pci_disable_msi(np->pci_dev);
 				np->msi_flags &= ~NV_MSI_ENABLED;
 				dev->irq = np->pci_dev->irq;
@@ -3903,9 +3771,8 @@ static void nv_free_irq(struct net_devic
 	int i;
 
 	if (np->msi_flags & NV_MSI_X_ENABLED) {
-		for (i = 0; i < (np->msi_flags & NV_MSI_X_VECTORS_MASK); i++) {
+		for (i = 0; i < (np->msi_flags & NV_MSI_X_VECTORS_MASK); i++)
 			free_irq(np->msi_x_entry[i].vector, dev);
-		}
 		pci_disable_msix(np->pci_dev);
 		np->msi_flags &= ~NV_MSI_X_ENABLED;
 	} else {
@@ -3954,7 +3821,7 @@ static void nv_do_nic_poll(unsigned long
 
 	if (np->recover_error) {
 		np->recover_error = 0;
-		printk(KERN_INFO "%s: MAC in recoverable error state\n", dev->name);
+		netdev_info(dev, "MAC in recoverable error state\n");
 		if (netif_running(dev)) {
 			netif_tx_lock_bh(dev);
 			netif_addr_lock(dev);
@@ -3975,7 +3842,7 @@ static void nv_do_nic_poll(unsigned long
 			/* reinit nic view of the rx queue */
 			writel(np->rx_buf_sz, base + NvRegOffloadConfig);
 			setup_hw_rings(dev, NV_SETUP_RX_RING | NV_SETUP_TX_RING);
-			writel( ((np->rx_ring_size-1) << NVREG_RINGSZ_RXSHIFT) + ((np->tx_ring_size-1) << NVREG_RINGSZ_TXSHIFT),
+			writel(((np->rx_ring_size-1) << NVREG_RINGSZ_RXSHIFT) + ((np->tx_ring_size-1) << NVREG_RINGSZ_TXSHIFT),
 				base + NvRegRingSizes);
 			pci_push(base);
 			writel(NVREG_TXRXCTL_KICK|np->txrxctl_bits, get_hwbase(dev) + NvRegTxRxControl);
@@ -4082,6 +3949,7 @@ static int nv_set_wol(struct net_device
 		writel(flags, base + NvRegWakeUpFlags);
 		spin_unlock_irq(&np->lock);
 	}
+	device_set_wakeup_enable(&np->pci_dev->dev, np->wolenabled);
 	return 0;
 }
 
@@ -4105,7 +3973,7 @@ static int nv_get_settings(struct net_de
 	}
 
 	if (netif_carrier_ok(dev)) {
-		switch(np->linkspeed & (NVREG_LINKSPEED_MASK)) {
+		switch (np->linkspeed & (NVREG_LINKSPEED_MASK)) {
 		case NVREG_LINKSPEED_10:
 			ecmd->speed = SPEED_10;
 			break;
@@ -4250,14 +4118,14 @@ static int nv_set_settings(struct net_de
 		}
 
 		if (netif_running(dev))
-			printk(KERN_INFO "%s: link down.\n", dev->name);
+			netdev_info(dev, "link down\n");
 		bmcr = mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ);
 		if (np->phy_model == PHY_MODEL_MARVELL_E3016) {
 			bmcr |= BMCR_ANENABLE;
 			/* reset the phy in order for settings to stick,
 			 * and cause autoneg to start */
 			if (phy_reset(dev, bmcr)) {
-				printk(KERN_INFO "%s: phy reset failed\n", dev->name);
+				netdev_info(dev, "phy reset failed\n");
 				return -EINVAL;
 			}
 		} else {
@@ -4306,7 +4174,7 @@ static int nv_set_settings(struct net_de
 		if (np->phy_oui == PHY_OUI_MARVELL) {
 			/* reset the phy in order for forced mode settings to stick */
 			if (phy_reset(dev, bmcr)) {
-				printk(KERN_INFO "%s: phy reset failed\n", dev->name);
+				netdev_info(dev, "phy reset failed\n");
 				return -EINVAL;
 			}
 		} else {
@@ -4344,7 +4212,7 @@ static void nv_get_regs(struct net_devic
 
 	regs->version = FORCEDETH_REGS_VER;
 	spin_lock_irq(&np->lock);
-	for (i = 0;i <= np->register_size/sizeof(u32); i++)
+	for (i = 0; i <= np->register_size/sizeof(u32); i++)
 		rbuf[i] = readl(base + i*sizeof(u32));
 	spin_unlock_irq(&np->lock);
 }
@@ -4368,7 +4236,7 @@ static int nv_nway_reset(struct net_devi
 			spin_unlock(&np->lock);
 			netif_addr_unlock(dev);
 			netif_tx_unlock_bh(dev);
-			printk(KERN_INFO "%s: link down.\n", dev->name);
+			netdev_info(dev, "link down\n");
 		}
 
 		bmcr = mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ);
@@ -4376,7 +4244,7 @@ static int nv_nway_reset(struct net_devi
 			bmcr |= BMCR_ANENABLE;
 			/* reset the phy in order for settings to stick*/
 			if (phy_reset(dev, bmcr)) {
-				printk(KERN_INFO "%s: phy reset failed\n", dev->name);
+				netdev_info(dev, "phy reset failed\n");
 				return -EINVAL;
 			}
 		} else {
@@ -4464,10 +4332,9 @@ static int nv_set_ringparam(struct net_d
 				pci_free_consistent(np->pci_dev, sizeof(struct ring_desc_ex) * (ring->rx_pending + ring->tx_pending),
 						    rxtx_ring, ring_addr);
 		}
-		if (rx_skbuff)
-			kfree(rx_skbuff);
-		if (tx_skbuff)
-			kfree(tx_skbuff);
+
+		kfree(rx_skbuff);
+		kfree(tx_skbuff);
 		goto exit;
 	}
 
@@ -4491,14 +4358,14 @@ static int nv_set_ringparam(struct net_d
 	np->tx_ring_size = ring->tx_pending;
 
 	if (!nv_optimized(np)) {
-		np->rx_ring.orig = (struct ring_desc*)rxtx_ring;
+		np->rx_ring.orig = (struct ring_desc *)rxtx_ring;
 		np->tx_ring.orig = &np->rx_ring.orig[np->rx_ring_size];
 	} else {
-		np->rx_ring.ex = (struct ring_desc_ex*)rxtx_ring;
+		np->rx_ring.ex = (struct ring_desc_ex *)rxtx_ring;
 		np->tx_ring.ex = &np->rx_ring.ex[np->rx_ring_size];
 	}
-	np->rx_skb = (struct nv_skb_map*)rx_skbuff;
-	np->tx_skb = (struct nv_skb_map*)tx_skbuff;
+	np->rx_skb = (struct nv_skb_map *)rx_skbuff;
+	np->tx_skb = (struct nv_skb_map *)tx_skbuff;
 	np->ring_addr = ring_addr;
 
 	memset(np->rx_skb, 0, sizeof(struct nv_skb_map) * np->rx_ring_size);
@@ -4515,7 +4382,7 @@ static int nv_set_ringparam(struct net_d
 		/* reinit nic view of the queues */
 		writel(np->rx_buf_sz, base + NvRegOffloadConfig);
 		setup_hw_rings(dev, NV_SETUP_RX_RING | NV_SETUP_TX_RING);
-		writel( ((np->rx_ring_size-1) << NVREG_RINGSZ_RXSHIFT) + ((np->tx_ring_size-1) << NVREG_RINGSZ_TXSHIFT),
+		writel(((np->rx_ring_size-1) << NVREG_RINGSZ_RXSHIFT) + ((np->tx_ring_size-1) << NVREG_RINGSZ_TXSHIFT),
 			base + NvRegRingSizes);
 		pci_push(base);
 		writel(NVREG_TXRXCTL_KICK|np->txrxctl_bits, get_hwbase(dev) + NvRegTxRxControl);
@@ -4550,12 +4417,11 @@ static int nv_set_pauseparam(struct net_
 
 	if ((!np->autoneg && np->duplex == 0) ||
 	    (np->autoneg && !pause->autoneg && np->duplex == 0)) {
-		printk(KERN_INFO "%s: can not set pause settings when forced link is in half duplex.\n",
-		       dev->name);
+		netdev_info(dev, "can not set pause settings when forced link is in half duplex\n");
 		return -EINVAL;
 	}
 	if (pause->tx_pause && !(np->pause_flags & NV_PAUSEFRAME_TX_CAPABLE)) {
-		printk(KERN_INFO "%s: hardware does not support tx pause frames.\n", dev->name);
+		netdev_info(dev, "hardware does not support tx pause frames\n");
 		return -EINVAL;
 	}
 
@@ -4590,7 +4456,7 @@ static int nv_set_pauseparam(struct net_
 		mii_rw(dev, np->phyaddr, MII_ADVERTISE, adv);
 
 		if (netif_running(dev))
-			printk(KERN_INFO "%s: link down.\n", dev->name);
+			netdev_info(dev, "link down\n");
 		bmcr = mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ);
 		bmcr |= (BMCR_ANENABLE | BMCR_ANRESTART);
 		mii_rw(dev, np->phyaddr, MII_BMCR, bmcr);
@@ -4841,7 +4707,7 @@ static int nv_loopback_test(struct net_d
 	/* reinit nic view of the rx queue */
 	writel(np->rx_buf_sz, base + NvRegOffloadConfig);
 	setup_hw_rings(dev, NV_SETUP_RX_RING | NV_SETUP_TX_RING);
-	writel( ((np->rx_ring_size-1) << NVREG_RINGSZ_RXSHIFT) + ((np->tx_ring_size-1) << NVREG_RINGSZ_TXSHIFT),
+	writel(((np->rx_ring_size-1) << NVREG_RINGSZ_RXSHIFT) + ((np->tx_ring_size-1) << NVREG_RINGSZ_TXSHIFT),
 		base + NvRegRingSizes);
 	pci_push(base);
 
@@ -4852,8 +4718,7 @@ static int nv_loopback_test(struct net_d
 	pkt_len = ETH_DATA_LEN;
 	tx_skb = dev_alloc_skb(pkt_len);
 	if (!tx_skb) {
-		printk(KERN_ERR "dev_alloc_skb() failed during loopback test"
-			 " of %s\n", dev->name);
+		netdev_err(dev, "dev_alloc_skb() failed during loopback test\n");
 		ret = 0;
 		goto out;
 	}
@@ -4893,29 +4758,22 @@ static int nv_loopback_test(struct net_d
 		if (flags & NV_RX_ERROR)
 			ret = 0;
 	} else {
-		if (flags & NV_RX2_ERROR) {
+		if (flags & NV_RX2_ERROR)
 			ret = 0;
-		}
 	}
 
 	if (ret) {
 		if (len != pkt_len) {
 			ret = 0;
-			dprintk(KERN_DEBUG "%s: loopback len mismatch %d vs %d\n",
-				dev->name, len, pkt_len);
 		} else {
 			rx_skb = np->rx_skb[0].skb;
 			for (i = 0; i < pkt_len; i++) {
 				if (rx_skb->data[i] != (u8)(i & 0xff)) {
 					ret = 0;
-					dprintk(KERN_DEBUG "%s: loopback pattern check failed on byte %d\n",
-						dev->name, i);
 					break;
 				}
 			}
 		}
-	} else {
-		dprintk(KERN_DEBUG "%s: loopback - did not receive test packet\n", dev->name);
 	}
 
 	pci_unmap_single(np->pci_dev, test_dma_addr,
@@ -4958,11 +4816,10 @@ static void nv_self_test(struct net_devi
 			netif_addr_lock(dev);
 			spin_lock_irq(&np->lock);
 			nv_disable_hw_interrupts(dev, np->irqmask);
-			if (!(np->msi_flags & NV_MSI_X_ENABLED)) {
+			if (!(np->msi_flags & NV_MSI_X_ENABLED))
 				writel(NVREG_IRQSTAT_MASK, base + NvRegIrqStatus);
-			} else {
+			else
 				writel(NVREG_IRQSTAT_MASK, base + NvRegMSIXIrqStatus);
-			}
 			/* stop engines */
 			nv_stop_rxtx(dev);
 			nv_txrx_reset(dev);
@@ -5003,7 +4860,7 @@ static void nv_self_test(struct net_devi
 			/* reinit nic view of the rx queue */
 			writel(np->rx_buf_sz, base + NvRegOffloadConfig);
 			setup_hw_rings(dev, NV_SETUP_RX_RING | NV_SETUP_TX_RING);
-			writel( ((np->rx_ring_size-1) << NVREG_RINGSZ_RXSHIFT) + ((np->tx_ring_size-1) << NVREG_RINGSZ_TXSHIFT),
+			writel(((np->rx_ring_size-1) << NVREG_RINGSZ_RXSHIFT) + ((np->tx_ring_size-1) << NVREG_RINGSZ_TXSHIFT),
 				base + NvRegRingSizes);
 			pci_push(base);
 			writel(NVREG_TXRXCTL_KICK|np->txrxctl_bits, get_hwbase(dev) + NvRegTxRxControl);
@@ -5106,8 +4963,7 @@ static int nv_mgmt_acquire_sema(struct n
 		    ((tx_ctrl & NVREG_XMITCTL_MGMT_SEMA_MASK) == NVREG_XMITCTL_MGMT_SEMA_FREE)) {
 			np->mgmt_sema = 1;
 			return 1;
-		}
-		else
+		} else
 			udelay(50);
 	}
 
@@ -5167,8 +5023,6 @@ static int nv_open(struct net_device *de
 	int oom, i;
 	u32 low;
 
-	dprintk(KERN_DEBUG "nv_open: begin\n");
-
 	/* power up phy */
 	mii_rw(dev, np->phyaddr, MII_BMCR,
 	       mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ) & ~BMCR_PDOWN);
@@ -5204,7 +5058,7 @@ static int nv_open(struct net_device *de
 
 	/* give hw rings */
 	setup_hw_rings(dev, NV_SETUP_RX_RING | NV_SETUP_TX_RING);
-	writel( ((np->rx_ring_size-1) << NVREG_RINGSZ_RXSHIFT) + ((np->tx_ring_size-1) << NVREG_RINGSZ_TXSHIFT),
+	writel(((np->rx_ring_size-1) << NVREG_RINGSZ_RXSHIFT) + ((np->tx_ring_size-1) << NVREG_RINGSZ_TXSHIFT),
 		base + NvRegRingSizes);
 
 	writel(np->linkspeed, base + NvRegLinkSpeed);
@@ -5216,9 +5070,11 @@ static int nv_open(struct net_device *de
 	writel(np->vlanctl_bits, base + NvRegVlanControl);
 	pci_push(base);
 	writel(NVREG_TXRXCTL_BIT1|np->txrxctl_bits, base + NvRegTxRxControl);
-	reg_delay(dev, NvRegUnknownSetupReg5, NVREG_UNKSETUP5_BIT31, NVREG_UNKSETUP5_BIT31,
-			NV_SETUP5_DELAY, NV_SETUP5_DELAYMAX,
-			KERN_INFO "open: SetupReg5, Bit 31 remained off\n");
+	if (reg_delay(dev, NvRegUnknownSetupReg5,
+		      NVREG_UNKSETUP5_BIT31, NVREG_UNKSETUP5_BIT31,
+		      NV_SETUP5_DELAY, NV_SETUP5_DELAYMAX))
+		netdev_info(dev,
+			    "%s: SetupReg5, Bit 31 remained off\n", __func__);
 
 	writel(0, base + NvRegMIIMask);
 	writel(NVREG_IRQSTAT_MASK, base + NvRegIrqStatus);
@@ -5251,8 +5107,7 @@ static int nv_open(struct net_device *de
 			writel(NVREG_POLL_DEFAULT_THROUGHPUT, base + NvRegPollingInterval);
 		else
 			writel(NVREG_POLL_DEFAULT_CPU, base + NvRegPollingInterval);
-	}
-	else
+	} else
 		writel(poll_interval & 0xFFFF, base + NvRegPollingInterval);
 	writel(NVREG_UNKSETUP6_VAL, base + NvRegUnknownSetupReg6);
 	writel((np->phyaddr << NVREG_ADAPTCTL_PHYSHIFT)|NVREG_ADAPTCTL_PHYVALID|NVREG_ADAPTCTL_RUNNING,
@@ -5263,7 +5118,7 @@ static int nv_open(struct net_device *de
 		writel(NVREG_WAKEUPFLAGS_ENABLE , base + NvRegWakeUpFlags);
 
 	i = readl(base + NvRegPowerState);
-	if ( (i & NVREG_POWERSTATE_POWEREDUP) == 0)
+	if ((i & NVREG_POWERSTATE_POWEREDUP) == 0)
 		writel(NVREG_POWERSTATE_POWEREDUP|i, base + NvRegPowerState);
 
 	pci_push(base);
@@ -5276,9 +5131,8 @@ static int nv_open(struct net_device *de
 	writel(NVREG_IRQSTAT_MASK, base + NvRegIrqStatus);
 	pci_push(base);
 
-	if (nv_request_irq(dev, 0)) {
+	if (nv_request_irq(dev, 0))
 		goto out_drain;
-	}
 
 	/* ask for interrupts */
 	nv_enable_hw_interrupts(dev, np->irqmask);
@@ -5296,7 +5150,6 @@ static int nv_open(struct net_device *de
 		u32 miistat;
 		miistat = readl(base + NvRegMIIStatus);
 		writel(NVREG_MIISTAT_MASK_ALL, base + NvRegMIIStatus);
-		dprintk(KERN_INFO "startup: got 0x%08x.\n", miistat);
 	}
 	/* set linkspeed to invalid value, thus force nv_update_linkspeed
 	 * to init hw */
@@ -5309,7 +5162,7 @@ static int nv_open(struct net_device *de
 	if (ret) {
 		netif_carrier_on(dev);
 	} else {
-		printk(KERN_INFO "%s: no link during initialization.\n", dev->name);
+		netdev_info(dev, "no link during initialization\n");
 		netif_carrier_off(dev);
 	}
 	if (oom)
@@ -5352,7 +5205,6 @@ static int nv_close(struct net_device *d
 	base = get_hwbase(dev);
 	nv_disable_hw_interrupts(dev, np->irqmask);
 	pci_push(base);
-	dprintk(KERN_INFO "%s: Irqmask is zero again\n", dev->name);
 
 	spin_unlock_irq(&np->lock);
 
@@ -5421,8 +5273,8 @@ static int __devinit nv_probe(struct pci
 	static int printed_version;
 
 	if (!printed_version++)
-		printk(KERN_INFO "%s: Reverse Engineered nForce ethernet"
-		       " driver. Version %s.\n", DRV_NAME, FORCEDETH_VERSION);
+		pr_info("Reverse Engineered nForce ethernet driver. Version %s.\n",
+			FORCEDETH_VERSION);
 
 	dev = alloc_etherdev(sizeof(struct fe_priv));
 	err = -ENOMEM;
@@ -5465,10 +5317,6 @@ static int __devinit nv_probe(struct pci
 	err = -EINVAL;
 	addr = 0;
 	for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
-		dprintk(KERN_DEBUG "%s: resource %d start %p len %ld flags 0x%08lx.\n",
-				pci_name(pci_dev), i, (void*)pci_resource_start(pci_dev, i),
-				pci_resource_len(pci_dev, i),
-				pci_resource_flags(pci_dev, i));
 		if (pci_resource_flags(pci_dev, i) & IORESOURCE_MEM &&
 				pci_resource_len(pci_dev, i) >= np->register_size) {
 			addr = pci_resource_start(pci_dev, i);
@@ -5476,8 +5324,7 @@ static int __devinit nv_probe(struct pci
 		}
 	}
 	if (i == DEVICE_COUNT_RESOURCE) {
-		dev_printk(KERN_INFO, &pci_dev->dev,
-			   "Couldn't find register window\n");
+		dev_info(&pci_dev->dev, "Couldn't find register window\n");
 		goto out_relreg;
 	}
 
@@ -5493,13 +5340,13 @@ static int __devinit nv_probe(struct pci
 		np->txrxctl_bits = NVREG_TXRXCTL_DESC_3;
 		if (dma_64bit) {
 			if (pci_set_dma_mask(pci_dev, DMA_BIT_MASK(39)))
-				dev_printk(KERN_INFO, &pci_dev->dev,
-					"64-bit DMA failed, using 32-bit addressing\n");
+				dev_info(&pci_dev->dev,
+					 "64-bit DMA failed, using 32-bit addressing\n");
 			else
 				dev->features |= NETIF_F_HIGHDMA;
 			if (pci_set_consistent_dma_mask(pci_dev, DMA_BIT_MASK(39))) {
-				dev_printk(KERN_INFO, &pci_dev->dev,
-					"64-bit DMA (consistent) failed, using 32-bit ring buffers\n");
+				dev_info(&pci_dev->dev,
+					 "64-bit DMA (consistent) failed, using 32-bit ring buffers\n");
 			}
 		}
 	} else if (id->driver_data & DEV_HAS_LARGEDESC) {
@@ -5620,7 +5467,9 @@ static int __devinit nv_probe(struct pci
 		dev->dev_addr[4] = (np->orig_mac[0] >>  8) & 0xff;
 		dev->dev_addr[5] = (np->orig_mac[0] >>  0) & 0xff;
 		writel(txreg|NVREG_TRANSMITPOLL_MAC_ADDR_REV, base + NvRegTransmitPoll);
-		printk(KERN_DEBUG "nv_probe: set workaround bit for reversed mac addr\n");
+		dev_dbg(&pci_dev->dev,
+			"%s: set workaround bit for reversed mac addr\n",
+			__func__);
 	}
 	memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
 
@@ -5629,28 +5478,21 @@ static int __devinit nv_probe(struct pci
 		 * Bad mac address. At least one bios sets the mac address
 		 * to 01:23:45:67:89:ab
 		 */
-		dev_printk(KERN_ERR, &pci_dev->dev,
-			"Invalid Mac address detected: %pM\n",
-		        dev->dev_addr);
-		dev_printk(KERN_ERR, &pci_dev->dev,
-			"Please complain to your hardware vendor. Switching to a random MAC.\n");
+		dev_err(&pci_dev->dev,
+			"Invalid MAC address detected: %pM - Please complain to your hardware vendor.\n",
+			dev->dev_addr);
 		random_ether_addr(dev->dev_addr);
+		dev_err(&pci_dev->dev,
+			"Using random MAC address: %pM\n", dev->dev_addr);
 	}
 
-	dprintk(KERN_DEBUG "%s: MAC Address %pM\n",
-		pci_name(pci_dev), dev->dev_addr);
-
 	/* set mac address */
 	nv_copy_mac_to_hw(dev);
 
-	/* Workaround current PCI init glitch:  wakeup bits aren't
-	 * being set from PCI PM capability.
-	 */
-	device_init_wakeup(&pci_dev->dev, 1);
-
 	/* disable WOL */
 	writel(0, base + NvRegWakeUpFlags);
 	np->wolenabled = 0;
+	device_set_wakeup_enable(&pci_dev->dev, false);
 
 	if (id->driver_data & DEV_HAS_POWER_CNTRL) {
 
@@ -5663,16 +5505,15 @@ static int __devinit nv_probe(struct pci
 		writel(powerstate, base + NvRegPowerState2);
 	}
 
-	if (np->desc_ver == DESC_VER_1) {
+	if (np->desc_ver == DESC_VER_1)
 		np->tx_flags = NV_TX_VALID;
-	} else {
+	else
 		np->tx_flags = NV_TX2_VALID;
-	}
 
 	np->msi_flags = 0;
-	if ((id->driver_data & DEV_HAS_MSI) && msi) {
+	if ((id->driver_data & DEV_HAS_MSI) && msi)
 		np->msi_flags |= NV_MSI_CAPABLE;
-	}
+
 	if ((id->driver_data & DEV_HAS_MSI_X) && msix) {
 		/* msix has had reported issues when modifying irqmask
 		   as in the case of napi, therefore, disable for now
@@ -5702,11 +5543,9 @@ static int __devinit nv_probe(struct pci
 	if (id->driver_data & DEV_NEED_TIMERIRQ)
 		np->irqmask |= NVREG_IRQ_TIMER;
 	if (id->driver_data & DEV_NEED_LINKTIMER) {
-		dprintk(KERN_INFO "%s: link timer on.\n", pci_name(pci_dev));
 		np->need_linktimer = 1;
 		np->link_timeout = jiffies + LINK_TIMEOUT;
 	} else {
-		dprintk(KERN_INFO "%s: link timer off.\n", pci_name(pci_dev));
 		np->need_linktimer = 0;
 	}
 
@@ -5735,19 +5574,14 @@ static int __devinit nv_probe(struct pci
 		    nv_mgmt_acquire_sema(dev) &&
 		    nv_mgmt_get_version(dev)) {
 			np->mac_in_use = 1;
-			if (np->mgmt_version > 0) {
+			if (np->mgmt_version > 0)
 				np->mac_in_use = readl(base + NvRegMgmtUnitControl) & NVREG_MGMTUNITCONTROL_INUSE;
-			}
-			dprintk(KERN_INFO "%s: mgmt unit is running. mac in use %x.\n",
-				pci_name(pci_dev), np->mac_in_use);
 			/* management unit setup the phy already? */
 			if (np->mac_in_use &&
 			    ((readl(base + NvRegTransmitterControl) & NVREG_XMITCTL_SYNC_MASK) ==
 			     NVREG_XMITCTL_SYNC_PHY_INIT)) {
 				/* phy is inited by mgmt unit */
 				phyinitialized = 1;
-				dprintk(KERN_INFO "%s: Phy already initialized by mgmt unit.\n",
-					pci_name(pci_dev));
 			} else {
 				/* we need to init the phy */
 			}
@@ -5773,8 +5607,6 @@ static int __devinit nv_probe(struct pci
 		np->phy_model = id2 & PHYID2_MODEL_MASK;
 		id1 = (id1 & PHYID1_OUI_MASK) << PHYID1_OUI_SHFT;
 		id2 = (id2 & PHYID2_OUI_MASK) >> PHYID2_OUI_SHFT;
-		dprintk(KERN_DEBUG "%s: open: Found PHY %04x:%04x at address %d.\n",
-			pci_name(pci_dev), id1, id2, phyaddr);
 		np->phyaddr = phyaddr;
 		np->phy_oui = id1 | id2;
 
@@ -5788,8 +5620,7 @@ static int __devinit nv_probe(struct pci
 		break;
 	}
 	if (i == 33) {
-		dev_printk(KERN_INFO, &pci_dev->dev,
-			"open: Could not find a valid PHY.\n");
+		dev_info(&pci_dev->dev, "open: Could not find a valid PHY\n");
 		goto out_error;
 	}
 
@@ -5799,9 +5630,8 @@ static int __devinit nv_probe(struct pci
 	} else {
 		/* see if it is a gigabit phy */
 		u32 mii_status = mii_rw(dev, np->phyaddr, MII_BMSR, MII_READ);
-		if (mii_status & PHY_GIGABIT) {
+		if (mii_status & PHY_GIGABIT)
 			np->gigabit = PHY_GIGABIT;
-		}
 	}
 
 	/* set default link speed settings */
@@ -5811,37 +5641,29 @@ static int __devinit nv_probe(struct pci
 
 	err = register_netdev(dev);
 	if (err) {
-		dev_printk(KERN_INFO, &pci_dev->dev,
-			   "unable to register netdev: %d\n", err);
+		dev_info(&pci_dev->dev, "unable to register netdev: %d\n", err);
 		goto out_error;
 	}
 
-	dev_printk(KERN_INFO, &pci_dev->dev, "ifname %s, PHY OUI 0x%x @ %d, "
-		   "addr %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n",
-		   dev->name,
-		   np->phy_oui,
-		   np->phyaddr,
-		   dev->dev_addr[0],
-		   dev->dev_addr[1],
-		   dev->dev_addr[2],
-		   dev->dev_addr[3],
-		   dev->dev_addr[4],
-		   dev->dev_addr[5]);
+	netif_carrier_off(dev);
 
-	dev_printk(KERN_INFO, &pci_dev->dev, "%s%s%s%s%s%s%s%s%s%sdesc-v%u\n",
-		   dev->features & NETIF_F_HIGHDMA ? "highdma " : "",
-		   dev->features & (NETIF_F_IP_CSUM | NETIF_F_SG) ?
-		   	"csum " : "",
-		   dev->features & (NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_TX) ?
-		   	"vlan " : "",
-		   id->driver_data & DEV_HAS_POWER_CNTRL ? "pwrctl " : "",
-		   id->driver_data & DEV_HAS_MGMT_UNIT ? "mgmt " : "",
-		   id->driver_data & DEV_NEED_TIMERIRQ ? "timirq " : "",
-		   np->gigabit == PHY_GIGABIT ? "gbit " : "",
-		   np->need_linktimer ? "lnktim " : "",
-		   np->msi_flags & NV_MSI_CAPABLE ? "msi " : "",
-		   np->msi_flags & NV_MSI_X_CAPABLE ? "msi-x " : "",
-		   np->desc_ver);
+	dev_info(&pci_dev->dev, "ifname %s, PHY OUI 0x%x @ %d, addr %pM\n",
+		 dev->name, np->phy_oui, np->phyaddr, dev->dev_addr);
+
+	dev_info(&pci_dev->dev, "%s%s%s%s%s%s%s%s%s%sdesc-v%u\n",
+		 dev->features & NETIF_F_HIGHDMA ? "highdma " : "",
+		 dev->features & (NETIF_F_IP_CSUM | NETIF_F_SG) ?
+			"csum " : "",
+		 dev->features & (NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_TX) ?
+			"vlan " : "",
+		 id->driver_data & DEV_HAS_POWER_CNTRL ? "pwrctl " : "",
+		 id->driver_data & DEV_HAS_MGMT_UNIT ? "mgmt " : "",
+		 id->driver_data & DEV_NEED_TIMERIRQ ? "timirq " : "",
+		 np->gigabit == PHY_GIGABIT ? "gbit " : "",
+		 np->need_linktimer ? "lnktim " : "",
+		 np->msi_flags & NV_MSI_CAPABLE ? "msi " : "",
+		 np->msi_flags & NV_MSI_X_CAPABLE ? "msi-x " : "",
+		 np->desc_ver);
 
 	return 0;
 
@@ -5923,44 +5745,37 @@ static void __devexit nv_remove(struct p
 }
 
 #ifdef CONFIG_PM
-static int nv_suspend(struct pci_dev *pdev, pm_message_t state)
+static int nv_suspend(struct device *device)
 {
+	struct pci_dev *pdev = to_pci_dev(device);
 	struct net_device *dev = pci_get_drvdata(pdev);
 	struct fe_priv *np = netdev_priv(dev);
 	u8 __iomem *base = get_hwbase(dev);
 	int i;
 
 	if (netif_running(dev)) {
-		// Gross.
+		/* Gross. */
 		nv_close(dev);
 	}
 	netif_device_detach(dev);
 
 	/* save non-pci configuration space */
-	for (i = 0;i <= np->register_size/sizeof(u32); i++)
+	for (i = 0; i <= np->register_size/sizeof(u32); i++)
 		np->saved_config_space[i] = readl(base + i*sizeof(u32));
 
-	pci_save_state(pdev);
-	pci_enable_wake(pdev, pci_choose_state(pdev, state), np->wolenabled);
-	pci_disable_device(pdev);
-	pci_set_power_state(pdev, pci_choose_state(pdev, state));
 	return 0;
 }
 
-static int nv_resume(struct pci_dev *pdev)
+static int nv_resume(struct device *device)
 {
+	struct pci_dev *pdev = to_pci_dev(device);
 	struct net_device *dev = pci_get_drvdata(pdev);
 	struct fe_priv *np = netdev_priv(dev);
 	u8 __iomem *base = get_hwbase(dev);
 	int i, rc = 0;
 
-	pci_set_power_state(pdev, PCI_D0);
-	pci_restore_state(pdev);
-	/* ack any pending wake events, disable PME */
-	pci_enable_wake(pdev, PCI_D0, 0);
-
 	/* restore non-pci configuration space */
-	for (i = 0;i <= np->register_size/sizeof(u32); i++)
+	for (i = 0; i <= np->register_size/sizeof(u32); i++)
 		writel(np->saved_config_space[i], base+i*sizeof(u32));
 
 	if (np->driver_data & DEV_NEED_MSI_FIX)
@@ -5977,6 +5792,9 @@ static int nv_resume(struct pci_dev *pde
 	return rc;
 }
 
+static SIMPLE_DEV_PM_OPS(nv_pm_ops, nv_suspend, nv_resume);
+#define NV_PM_OPS (&nv_pm_ops)
+
 static void nv_shutdown(struct pci_dev *pdev)
 {
 	struct net_device *dev = pci_get_drvdata(pdev);
@@ -5990,9 +5808,8 @@ static void nv_shutdown(struct pci_dev *
 	 * If we really go for poweroff, we must not restore the MAC,
 	 * otherwise the MAC for WOL will be reversed at least on some boards.
 	 */
-	if (system_state != SYSTEM_POWER_OFF) {
+	if (system_state != SYSTEM_POWER_OFF)
 		nv_restore_mac_addr(pdev);
-	}
 
 	pci_disable_device(pdev);
 	/*
@@ -6000,15 +5817,13 @@ static void nv_shutdown(struct pci_dev *
 	 * only put the device into D3 if we really go for poweroff.
 	 */
 	if (system_state == SYSTEM_POWER_OFF) {
-		if (pci_enable_wake(pdev, PCI_D3cold, np->wolenabled))
-			pci_enable_wake(pdev, PCI_D3hot, np->wolenabled);
+		pci_wake_from_d3(pdev, np->wolenabled);
 		pci_set_power_state(pdev, PCI_D3hot);
 	}
 }
 #else
-#define nv_suspend NULL
+#define NV_PM_OPS NULL
 #define nv_shutdown NULL
-#define nv_resume NULL
 #endif /* CONFIG_PM */
 
 static DEFINE_PCI_DEVICE_TABLE(pci_tbl) = {
@@ -6180,9 +5995,8 @@ static struct pci_driver driver = {
 	.id_table	= pci_tbl,
 	.probe		= nv_probe,
 	.remove		= __devexit_p(nv_remove),
-	.suspend	= nv_suspend,
-	.resume		= nv_resume,
 	.shutdown	= nv_shutdown,
+	.driver.pm	= NV_PM_OPS,
 };
 
 static int __init init_nic(void)
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/fs_enet/fs_enet-main.c linux-libre-2.6.38-gnu1/drivers/net/fs_enet/fs_enet-main.c
--- linux-libre-2.6.37-gnu1/drivers/net/fs_enet/fs_enet-main.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/fs_enet/fs_enet-main.c	2011-03-14 21:20:32.000000000 -0400
@@ -40,6 +40,7 @@
 #include <linux/of_mdio.h>
 #include <linux/of_platform.h>
 #include <linux/of_gpio.h>
+#include <linux/of_net.h>
 
 #include <linux/vmalloc.h>
 #include <asm/pgtable.h>
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/gianfar.c linux-libre-2.6.38-gnu1/drivers/net/gianfar.c
--- linux-libre-2.6.37-gnu1/drivers/net/gianfar.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/gianfar.c	2011-03-14 21:20:32.000000000 -0400
@@ -95,6 +95,7 @@
 #include <linux/phy.h>
 #include <linux/phy_fixed.h>
 #include <linux/of.h>
+#include <linux/of_net.h>
 
 #include "gianfar.h"
 #include "fsl_pq_mdio.h"
@@ -143,7 +144,8 @@ void gfar_halt(struct net_device *dev);
 static void gfar_halt_nodisable(struct net_device *dev);
 void gfar_start(struct net_device *dev);
 static void gfar_clear_exact_match(struct net_device *dev);
-static void gfar_set_mac_for_addr(struct net_device *dev, int num, u8 *addr);
+static void gfar_set_mac_for_addr(struct net_device *dev, int num,
+				  const u8 *addr);
 static int gfar_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
 
 MODULE_AUTHOR("Freescale Semiconductor, Inc");
@@ -432,7 +434,6 @@ static void gfar_init_mac(struct net_dev
 static struct net_device_stats *gfar_get_stats(struct net_device *dev)
 {
 	struct gfar_private *priv = netdev_priv(dev);
-	struct netdev_queue *txq;
 	unsigned long rx_packets = 0, rx_bytes = 0, rx_dropped = 0;
 	unsigned long tx_packets = 0, tx_bytes = 0;
 	int i = 0;
@@ -448,9 +449,8 @@ static struct net_device_stats *gfar_get
 	dev->stats.rx_dropped = rx_dropped;
 
 	for (i = 0; i < priv->num_tx_queues; i++) {
-		txq = netdev_get_tx_queue(dev, i);
-		tx_bytes += txq->tx_bytes;
-		tx_packets += txq->tx_packets;
+		tx_bytes += priv->tx_queue[i]->stats.tx_bytes;
+		tx_packets += priv->tx_queue[i]->stats.tx_packets;
 	}
 
 	dev->stats.tx_bytes = tx_bytes;
@@ -1920,7 +1920,7 @@ int startup_gfar(struct net_device *ndev
 		if (err) {
 			for (j = 0; j < i; j++)
 				free_grp_irqs(&priv->gfargrp[j]);
-				goto irq_fail;
+			goto irq_fail;
 		}
 	}
 
@@ -2107,8 +2107,8 @@ static int gfar_start_xmit(struct sk_buf
 	}
 
 	/* Update transmit stats */
-	txq->tx_bytes += skb->len;
-	txq->tx_packets ++;
+	tx_queue->stats.tx_bytes += skb->len;
+	tx_queue->stats.tx_packets++;
 
 	txbdp = txbdp_start = tx_queue->cur_tx;
 	lstatus = txbdp->lstatus;
@@ -3094,10 +3094,10 @@ static void gfar_set_multi(struct net_de
 static void gfar_clear_exact_match(struct net_device *dev)
 {
 	int idx;
-	u8 zero_arr[MAC_ADDR_LEN] = {0,0,0,0,0,0};
+	static const u8 zero_arr[MAC_ADDR_LEN] = {0, 0, 0, 0, 0, 0};
 
 	for(idx = 1;idx < GFAR_EM_NUM + 1;idx++)
-		gfar_set_mac_for_addr(dev, idx, (u8 *)zero_arr);
+		gfar_set_mac_for_addr(dev, idx, zero_arr);
 }
 
 /* Set the appropriate hash bit for the given addr */
@@ -3132,7 +3132,8 @@ static void gfar_set_hash_for_addr(struc
 /* There are multiple MAC Address register pairs on some controllers
  * This function sets the numth pair to a given address
  */
-static void gfar_set_mac_for_addr(struct net_device *dev, int num, u8 *addr)
+static void gfar_set_mac_for_addr(struct net_device *dev, int num,
+				  const u8 *addr)
 {
 	struct gfar_private *priv = netdev_priv(dev);
 	struct gfar __iomem *regs = priv->gfargrp[0].regs;
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/gianfar.h linux-libre-2.6.38-gnu1/drivers/net/gianfar.h
--- linux-libre-2.6.37-gnu1/drivers/net/gianfar.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/gianfar.h	2011-03-14 21:20:32.000000000 -0400
@@ -907,12 +907,21 @@ enum {
 	MQ_MG_MODE
 };
 
+/*
+ * Per TX queue stats
+ */
+struct tx_q_stats {
+	unsigned long tx_packets;
+	unsigned long tx_bytes;
+};
+
 /**
  *	struct gfar_priv_tx_q - per tx queue structure
  *	@txlock: per queue tx spin lock
  *	@tx_skbuff:skb pointers
  *	@skb_curtx: to be used skb pointer
  *	@skb_dirtytx:the last used skb pointer
+ *	@stats: bytes/packets stats
  *	@qindex: index of this queue
  *	@dev: back pointer to the dev structure
  *	@grp: back pointer to the group to which this queue belongs
@@ -934,6 +943,7 @@ struct gfar_priv_tx_q {
 	struct	txbd8 *tx_bd_base;
 	struct	txbd8 *cur_tx;
 	struct	txbd8 *dirty_tx;
+	struct tx_q_stats stats;
 	struct	net_device *dev;
 	struct gfar_priv_grp *grp;
 	u16	skb_curtx;
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/greth.c linux-libre-2.6.38-gnu1/drivers/net/greth.c
--- linux-libre-2.6.37-gnu1/drivers/net/greth.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/greth.c	2011-03-14 21:20:32.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  * Aeroflex Gaisler GRETH 10/100/1G Ethernet MAC.
  *
- * 2005-2009 (c) Aeroflex Gaisler AB
+ * 2005-2010 (c) Aeroflex Gaisler AB
  *
  * This driver supports GRETH 10/100 and GRETH 10/100/1G Ethernet MACs
  * available in the GRLIB VHDL IP core library.
@@ -356,6 +356,8 @@ static int greth_open(struct net_device
 		dev_dbg(&dev->dev, " starting queue\n");
 	netif_start_queue(dev);
 
+	GRETH_REGSAVE(greth->regs->status, 0xFF);
+
 	napi_enable(&greth->napi);
 
 	greth_enable_irqs(greth);
@@ -371,7 +373,9 @@ static int greth_close(struct net_device
 
 	napi_disable(&greth->napi);
 
+	greth_disable_irqs(greth);
 	greth_disable_tx(greth);
+	greth_disable_rx(greth);
 
 	netif_stop_queue(dev);
 
@@ -388,12 +392,20 @@ greth_start_xmit(struct sk_buff *skb, st
 	struct greth_private *greth = netdev_priv(dev);
 	struct greth_bd *bdp;
 	int err = NETDEV_TX_OK;
-	u32 status, dma_addr;
+	u32 status, dma_addr, ctrl;
+	unsigned long flags;
 
-	bdp = greth->tx_bd_base + greth->tx_next;
+	/* Clean TX Ring */
+	greth_clean_tx(greth->netdev);
 
 	if (unlikely(greth->tx_free <= 0)) {
+		spin_lock_irqsave(&greth->devlock, flags);/*save from poll/irq*/
+		ctrl = GRETH_REGLOAD(greth->regs->control);
+		/* Enable TX IRQ only if not already in poll() routine */
+		if (ctrl & GRETH_RXI)
+			GRETH_REGSAVE(greth->regs->control, ctrl | GRETH_TXI);
 		netif_stop_queue(dev);
+		spin_unlock_irqrestore(&greth->devlock, flags);
 		return NETDEV_TX_BUSY;
 	}
 
@@ -406,13 +418,14 @@ greth_start_xmit(struct sk_buff *skb, st
 		goto out;
 	}
 
+	bdp = greth->tx_bd_base + greth->tx_next;
 	dma_addr = greth_read_bd(&bdp->addr);
 
 	memcpy((unsigned char *) phys_to_virt(dma_addr), skb->data, skb->len);
 
 	dma_sync_single_for_device(greth->dev, dma_addr, skb->len, DMA_TO_DEVICE);
 
-	status = GRETH_BD_EN | (skb->len & GRETH_BD_LEN);
+	status = GRETH_BD_EN | GRETH_BD_IE | (skb->len & GRETH_BD_LEN);
 
 	/* Wrap around descriptor ring */
 	if (greth->tx_next == GRETH_TXBD_NUM_MASK) {
@@ -422,22 +435,11 @@ greth_start_xmit(struct sk_buff *skb, st
 	greth->tx_next = NEXT_TX(greth->tx_next);
 	greth->tx_free--;
 
-	/* No more descriptors */
-	if (unlikely(greth->tx_free == 0)) {
-
-		/* Free transmitted descriptors */
-		greth_clean_tx(dev);
-
-		/* If nothing was cleaned, stop queue & wait for irq */
-		if (unlikely(greth->tx_free == 0)) {
-			status |= GRETH_BD_IE;
-			netif_stop_queue(dev);
-		}
-	}
-
 	/* Write descriptor control word and enable transmission */
 	greth_write_bd(&bdp->stat, status);
+	spin_lock_irqsave(&greth->devlock, flags); /*save from poll/irq*/
 	greth_enable_tx(greth);
+	spin_unlock_irqrestore(&greth->devlock, flags);
 
 out:
 	dev_kfree_skb(skb);
@@ -450,13 +452,23 @@ greth_start_xmit_gbit(struct sk_buff *sk
 {
 	struct greth_private *greth = netdev_priv(dev);
 	struct greth_bd *bdp;
-	u32 status = 0, dma_addr;
+	u32 status = 0, dma_addr, ctrl;
 	int curr_tx, nr_frags, i, err = NETDEV_TX_OK;
+	unsigned long flags;
 
 	nr_frags = skb_shinfo(skb)->nr_frags;
 
+	/* Clean TX Ring */
+	greth_clean_tx_gbit(dev);
+
 	if (greth->tx_free < nr_frags + 1) {
+		spin_lock_irqsave(&greth->devlock, flags);/*save from poll/irq*/
+		ctrl = GRETH_REGLOAD(greth->regs->control);
+		/* Enable TX IRQ only if not already in poll() routine */
+		if (ctrl & GRETH_RXI)
+			GRETH_REGSAVE(greth->regs->control, ctrl | GRETH_TXI);
 		netif_stop_queue(dev);
+		spin_unlock_irqrestore(&greth->devlock, flags);
 		err = NETDEV_TX_BUSY;
 		goto out;
 	}
@@ -499,7 +511,7 @@ greth_start_xmit_gbit(struct sk_buff *sk
 		greth->tx_skbuff[curr_tx] = NULL;
 		bdp = greth->tx_bd_base + curr_tx;
 
-		status = GRETH_TXBD_CSALL;
+		status = GRETH_TXBD_CSALL | GRETH_BD_EN;
 		status |= frag->size & GRETH_BD_LEN;
 
 		/* Wrap around descriptor ring */
@@ -509,14 +521,8 @@ greth_start_xmit_gbit(struct sk_buff *sk
 		/* More fragments left */
 		if (i < nr_frags - 1)
 			status |= GRETH_TXBD_MORE;
-
-		/* ... last fragment, check if out of descriptors  */
-		else if (greth->tx_free - nr_frags - 1 < (MAX_SKB_FRAGS + 1)) {
-
-			/* Enable interrupts and stop queue */
-			status |= GRETH_BD_IE;
-			netif_stop_queue(dev);
-		}
+		else
+			status |= GRETH_BD_IE; /* enable IRQ on last fragment */
 
 		greth_write_bd(&bdp->stat, status);
 
@@ -536,26 +542,29 @@ greth_start_xmit_gbit(struct sk_buff *sk
 
 	wmb();
 
-	/* Enable the descriptors that we configured ...  */
-	for (i = 0; i < nr_frags + 1; i++) {
-		bdp = greth->tx_bd_base + greth->tx_next;
-		greth_write_bd(&bdp->stat, greth_read_bd(&bdp->stat) | GRETH_BD_EN);
-		greth->tx_next = NEXT_TX(greth->tx_next);
-		greth->tx_free--;
-	}
+	/* Enable the descriptor chain by enabling the first descriptor */
+	bdp = greth->tx_bd_base + greth->tx_next;
+	greth_write_bd(&bdp->stat, greth_read_bd(&bdp->stat) | GRETH_BD_EN);
+	greth->tx_next = curr_tx;
+	greth->tx_free -= nr_frags + 1;
+
+	wmb();
 
+	spin_lock_irqsave(&greth->devlock, flags); /*save from poll/irq*/
 	greth_enable_tx(greth);
+	spin_unlock_irqrestore(&greth->devlock, flags);
 
 	return NETDEV_TX_OK;
 
 frag_map_error:
-	/* Unmap SKB mappings that succeeded */
+	/* Unmap SKB mappings that succeeded and disable descriptor */
 	for (i = 0; greth->tx_next + i != curr_tx; i++) {
 		bdp = greth->tx_bd_base + greth->tx_next + i;
 		dma_unmap_single(greth->dev,
 				 greth_read_bd(&bdp->addr),
 				 greth_read_bd(&bdp->stat) & GRETH_BD_LEN,
 				 DMA_TO_DEVICE);
+		greth_write_bd(&bdp->stat, 0);
 	}
 map_error:
 	if (net_ratelimit())
@@ -565,12 +574,11 @@ out:
 	return err;
 }
 
-
 static irqreturn_t greth_interrupt(int irq, void *dev_id)
 {
 	struct net_device *dev = dev_id;
 	struct greth_private *greth;
-	u32 status;
+	u32 status, ctrl;
 	irqreturn_t retval = IRQ_NONE;
 
 	greth = netdev_priv(dev);
@@ -580,13 +588,15 @@ static irqreturn_t greth_interrupt(int i
 	/* Get the interrupt events that caused us to be here. */
 	status = GRETH_REGLOAD(greth->regs->status);
 
-	/* Handle rx and tx interrupts through poll */
-	if (status & (GRETH_INT_RX | GRETH_INT_TX)) {
-
-		/* Clear interrupt status */
-		GRETH_REGORIN(greth->regs->status,
-			      status & (GRETH_INT_RX | GRETH_INT_TX));
+	/* Must see if interrupts are enabled also, INT_TX|INT_RX flags may be
+	 * set regardless of whether IRQ is enabled or not. Especially
+	 * important when shared IRQ.
+	 */
+	ctrl = GRETH_REGLOAD(greth->regs->control);
 
+	/* Handle rx and tx interrupts through poll */
+	if (((status & (GRETH_INT_RE | GRETH_INT_RX)) && (ctrl & GRETH_RXI)) ||
+	    ((status & (GRETH_INT_TE | GRETH_INT_TX)) && (ctrl & GRETH_TXI))) {
 		retval = IRQ_HANDLED;
 
 		/* Disable interrupts and schedule poll() */
@@ -610,6 +620,8 @@ static void greth_clean_tx(struct net_de
 
 	while (1) {
 		bdp = greth->tx_bd_base + greth->tx_last;
+		GRETH_REGSAVE(greth->regs->status, GRETH_INT_TE | GRETH_INT_TX);
+		mb();
 		stat = greth_read_bd(&bdp->stat);
 
 		if (unlikely(stat & GRETH_BD_EN))
@@ -670,7 +682,10 @@ static void greth_clean_tx_gbit(struct n
 
 		/* We only clean fully completed SKBs */
 		bdp_last_frag = greth->tx_bd_base + SKIP_TX(greth->tx_last, nr_frags);
-		stat = bdp_last_frag->stat;
+
+		GRETH_REGSAVE(greth->regs->status, GRETH_INT_TE | GRETH_INT_TX);
+		mb();
+		stat = greth_read_bd(&bdp_last_frag->stat);
 
 		if (stat & GRETH_BD_EN)
 			break;
@@ -702,21 +717,9 @@ static void greth_clean_tx_gbit(struct n
 		greth->tx_free += nr_frags+1;
 		dev_kfree_skb(skb);
 	}
-	if (greth->tx_free > (MAX_SKB_FRAGS + 1)) {
-		netif_wake_queue(dev);
-	}
-}
 
-static int greth_pending_packets(struct greth_private *greth)
-{
-	struct greth_bd *bdp;
-	u32 status;
-	bdp = greth->rx_bd_base + greth->rx_cur;
-	status = greth_read_bd(&bdp->stat);
-	if (status & GRETH_BD_EN)
-		return 0;
-	else
-		return 1;
+	if (netif_queue_stopped(dev) && (greth->tx_free > (MAX_SKB_FRAGS+1)))
+		netif_wake_queue(dev);
 }
 
 static int greth_rx(struct net_device *dev, int limit)
@@ -727,20 +730,24 @@ static int greth_rx(struct net_device *d
 	int pkt_len;
 	int bad, count;
 	u32 status, dma_addr;
+	unsigned long flags;
 
 	greth = netdev_priv(dev);
 
 	for (count = 0; count < limit; ++count) {
 
 		bdp = greth->rx_bd_base + greth->rx_cur;
+		GRETH_REGSAVE(greth->regs->status, GRETH_INT_RE | GRETH_INT_RX);
+		mb();
 		status = greth_read_bd(&bdp->stat);
-		dma_addr = greth_read_bd(&bdp->addr);
-		bad = 0;
 
 		if (unlikely(status & GRETH_BD_EN)) {
 			break;
 		}
 
+		dma_addr = greth_read_bd(&bdp->addr);
+		bad = 0;
+
 		/* Check status for errors. */
 		if (unlikely(status & GRETH_RXBD_STATUS)) {
 			if (status & GRETH_RXBD_ERR_FT) {
@@ -802,7 +809,9 @@ static int greth_rx(struct net_device *d
 
 		dma_sync_single_for_device(greth->dev, dma_addr, MAX_FRAME_SIZE, DMA_FROM_DEVICE);
 
+		spin_lock_irqsave(&greth->devlock, flags); /* save from XMIT */
 		greth_enable_rx(greth);
+		spin_unlock_irqrestore(&greth->devlock, flags);
 
 		greth->rx_cur = NEXT_RX(greth->rx_cur);
 	}
@@ -836,6 +845,7 @@ static int greth_rx_gbit(struct net_devi
 	int pkt_len;
 	int bad, count = 0;
 	u32 status, dma_addr;
+	unsigned long flags;
 
 	greth = netdev_priv(dev);
 
@@ -843,6 +853,8 @@ static int greth_rx_gbit(struct net_devi
 
 		bdp = greth->rx_bd_base + greth->rx_cur;
 		skb = greth->rx_skbuff[greth->rx_cur];
+		GRETH_REGSAVE(greth->regs->status, GRETH_INT_RE | GRETH_INT_RX);
+		mb();
 		status = greth_read_bd(&bdp->stat);
 		bad = 0;
 
@@ -865,10 +877,9 @@ static int greth_rx_gbit(struct net_devi
 			}
 		}
 
-		/* Allocate new skb to replace current */
-		newskb = netdev_alloc_skb(dev, MAX_FRAME_SIZE + NET_IP_ALIGN);
-
-		if (!bad && newskb) {
+		/* Allocate new skb to replace current, not needed if the
+		 * current skb can be reused */
+		if (!bad && (newskb=netdev_alloc_skb(dev, MAX_FRAME_SIZE + NET_IP_ALIGN))) {
 			skb_reserve(newskb, NET_IP_ALIGN);
 
 			dma_addr = dma_map_single(greth->dev,
@@ -905,11 +916,22 @@ static int greth_rx_gbit(struct net_devi
 				if (net_ratelimit())
 					dev_warn(greth->dev, "Could not create DMA mapping, dropping packet\n");
 				dev_kfree_skb(newskb);
+				/* reusing current skb, so it is a drop */
 				dev->stats.rx_dropped++;
 			}
+		} else if (bad) {
+			/* Bad Frame transfer, the skb is reused */
+			dev->stats.rx_dropped++;
 		} else {
+			/* Failed Allocating a new skb. This is rather stupid
+			 * but the current "filled" skb is reused, as if
+			 * transfer failure. One could argue that RX descriptor
+			 * table handling should be divided into cleaning and
+			 * filling as the TX part of the driver
+			 */
 			if (net_ratelimit())
 				dev_warn(greth->dev, "Could not allocate SKB, dropping packet\n");
+			/* reusing current skb, so it is a drop */
 			dev->stats.rx_dropped++;
 		}
 
@@ -920,7 +942,9 @@ static int greth_rx_gbit(struct net_devi
 
 		wmb();
 		greth_write_bd(&bdp->stat, status);
+		spin_lock_irqsave(&greth->devlock, flags);
 		greth_enable_rx(greth);
+		spin_unlock_irqrestore(&greth->devlock, flags);
 		greth->rx_cur = NEXT_RX(greth->rx_cur);
 	}
 
@@ -932,15 +956,18 @@ static int greth_poll(struct napi_struct
 {
 	struct greth_private *greth;
 	int work_done = 0;
+	unsigned long flags;
+	u32 mask, ctrl;
 	greth = container_of(napi, struct greth_private, napi);
 
-	if (greth->gbit_mac) {
-		greth_clean_tx_gbit(greth->netdev);
-	} else {
-		greth_clean_tx(greth->netdev);
+restart_txrx_poll:
+	if (netif_queue_stopped(greth->netdev)) {
+		if (greth->gbit_mac)
+			greth_clean_tx_gbit(greth->netdev);
+		else
+			greth_clean_tx(greth->netdev);
 	}
 
-restart_poll:
 	if (greth->gbit_mac) {
 		work_done += greth_rx_gbit(greth->netdev, budget - work_done);
 	} else {
@@ -949,15 +976,29 @@ restart_poll:
 
 	if (work_done < budget) {
 
-		napi_complete(napi);
+		spin_lock_irqsave(&greth->devlock, flags);
 
-		if (greth_pending_packets(greth)) {
-			napi_reschedule(napi);
-			goto restart_poll;
+		ctrl = GRETH_REGLOAD(greth->regs->control);
+		if (netif_queue_stopped(greth->netdev)) {
+			GRETH_REGSAVE(greth->regs->control,
+					ctrl | GRETH_TXI | GRETH_RXI);
+			mask = GRETH_INT_RX | GRETH_INT_RE |
+			       GRETH_INT_TX | GRETH_INT_TE;
+		} else {
+			GRETH_REGSAVE(greth->regs->control, ctrl | GRETH_RXI);
+			mask = GRETH_INT_RX | GRETH_INT_RE;
+		}
+
+		if (GRETH_REGLOAD(greth->regs->status) & mask) {
+			GRETH_REGSAVE(greth->regs->control, ctrl);
+			spin_unlock_irqrestore(&greth->devlock, flags);
+			goto restart_txrx_poll;
+		} else {
+			__napi_complete(napi);
+			spin_unlock_irqrestore(&greth->devlock, flags);
 		}
 	}
 
-	greth_enable_irqs(greth);
 	return work_done;
 }
 
@@ -1152,11 +1193,11 @@ static const struct ethtool_ops greth_et
 };
 
 static struct net_device_ops greth_netdev_ops = {
-	.ndo_open = greth_open,
-	.ndo_stop = greth_close,
-	.ndo_start_xmit = greth_start_xmit,
-	.ndo_set_mac_address = greth_set_mac_add,
-	.ndo_validate_addr 	= eth_validate_addr,
+	.ndo_open		= greth_open,
+	.ndo_stop		= greth_close,
+	.ndo_start_xmit		= greth_start_xmit,
+	.ndo_set_mac_address	= greth_set_mac_add,
+	.ndo_validate_addr	= eth_validate_addr,
 };
 
 static inline int wait_for_mdio(struct greth_private *greth)
@@ -1217,29 +1258,26 @@ static void greth_link_change(struct net
 	struct greth_private *greth = netdev_priv(dev);
 	struct phy_device *phydev = greth->phy;
 	unsigned long flags;
-
 	int status_change = 0;
+	u32 ctrl;
 
 	spin_lock_irqsave(&greth->devlock, flags);
 
 	if (phydev->link) {
 
 		if ((greth->speed != phydev->speed) || (greth->duplex != phydev->duplex)) {
-
-			GRETH_REGANDIN(greth->regs->control,
-				       ~(GRETH_CTRL_FD | GRETH_CTRL_SP | GRETH_CTRL_GB));
+			ctrl = GRETH_REGLOAD(greth->regs->control) &
+			       ~(GRETH_CTRL_FD | GRETH_CTRL_SP | GRETH_CTRL_GB);
 
 			if (phydev->duplex)
-				GRETH_REGORIN(greth->regs->control, GRETH_CTRL_FD);
-
-			if (phydev->speed == SPEED_100) {
-
-				GRETH_REGORIN(greth->regs->control, GRETH_CTRL_SP);
-			}
+				ctrl |= GRETH_CTRL_FD;
 
+			if (phydev->speed == SPEED_100)
+				ctrl |= GRETH_CTRL_SP;
 			else if (phydev->speed == SPEED_1000)
-				GRETH_REGORIN(greth->regs->control, GRETH_CTRL_GB);
+				ctrl |= GRETH_CTRL_GB;
 
+			GRETH_REGSAVE(greth->regs->control, ctrl);
 			greth->speed = phydev->speed;
 			greth->duplex = phydev->duplex;
 			status_change = 1;
@@ -1600,6 +1638,9 @@ static struct of_device_id greth_of_matc
 	{
 	 .name = "GAISLER_ETHMAC",
 	 },
+	{
+	 .name = "01_01d",
+	 },
 	{},
 };
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/greth.h linux-libre-2.6.38-gnu1/drivers/net/greth.h
--- linux-libre-2.6.37-gnu1/drivers/net/greth.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/greth.h	2011-03-14 21:20:32.000000000 -0400
@@ -23,6 +23,7 @@
 #define GRETH_BD_LEN 0x7FF
 
 #define GRETH_TXEN 0x1
+#define GRETH_INT_TE 0x2
 #define GRETH_INT_TX 0x8
 #define GRETH_TXI 0x4
 #define GRETH_TXBD_STATUS 0x0001C000
@@ -35,6 +36,7 @@
 #define GRETH_TXBD_ERR_UE 0x4000
 #define GRETH_TXBD_ERR_AL 0x8000
 
+#define GRETH_INT_RE         0x1
 #define GRETH_INT_RX         0x4
 #define GRETH_RXEN           0x2
 #define GRETH_RXI            0x8
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/hamradio/yam.c linux-libre-2.6.38-gnu1/drivers/net/hamradio/yam.c
--- linux-libre-2.6.37-gnu1/drivers/net/hamradio/yam.c	2013-05-03 03:59:24.000000000 -0400
+++ linux-libre-2.6.38-gnu1/drivers/net/hamradio/yam.c	2013-05-03 01:59:39.000000000 -0400
@@ -396,7 +396,7 @@ static unsigned char *add_mcs(unsigned c
 	while (p) {
 		if (p->bitrate == bitrate) {
 			memcpy(p->bits, bits, YAM_FPGA_SIZE);
-			return p->bits;
+			goto out;
 		}
 		p = p->next;
 	}
@@ -411,7 +411,7 @@ static unsigned char *add_mcs(unsigned c
 	p->bitrate = bitrate;
 	p->next = yam_data;
 	yam_data = p;
-
+ out:
 	release_firmware(fw);
 	return p->bits;
 }
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/hp.c linux-libre-2.6.38-gnu1/drivers/net/hp.c
--- linux-libre-2.6.37-gnu1/drivers/net/hp.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/hp.c	2011-03-14 21:20:32.000000000 -0400
@@ -162,9 +162,9 @@ static int __init hp_probe1(struct net_d
 
 	/* Snarf the interrupt now.  Someday this could be moved to open(). */
 	if (dev->irq < 2) {
-		int irq_16list[] = { 11, 10, 5, 3, 4, 7, 9, 0};
-		int irq_8list[] = { 7, 5, 3, 4, 9, 0};
-		int *irqp = wordmode ? irq_16list : irq_8list;
+		static const int irq_16list[] = { 11, 10, 5, 3, 4, 7, 9, 0};
+		static const int irq_8list[] = { 7, 5, 3, 4, 9, 0};
+		const int *irqp = wordmode ? irq_16list : irq_8list;
 		do {
 			int irq = *irqp;
 			if (request_irq (irq, NULL, 0, "bogus", NULL) != -EBUSY) {
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/ibm_newemac/core.c linux-libre-2.6.38-gnu1/drivers/net/ibm_newemac/core.c
--- linux-libre-2.6.37-gnu1/drivers/net/ibm_newemac/core.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/ibm_newemac/core.c	2011-03-14 21:20:32.000000000 -0400
@@ -1279,7 +1279,7 @@ static void emac_force_link_update(struc
 	netif_carrier_off(dev->ndev);
 	smp_rmb();
 	if (dev->link_polling) {
-		cancel_rearming_delayed_work(&dev->link_work);
+		cancel_delayed_work_sync(&dev->link_work);
 		if (dev->link_polling)
 			schedule_delayed_work(&dev->link_work,  PHY_POLL_LINK_OFF);
 	}
@@ -1294,7 +1294,7 @@ static int emac_close(struct net_device
 
 	if (dev->phy.address >= 0) {
 		dev->link_polling = 0;
-		cancel_rearming_delayed_work(&dev->link_work);
+		cancel_delayed_work_sync(&dev->link_work);
 	}
 	mutex_lock(&dev->link_lock);
 	emac_netif_stop(dev);
@@ -2950,7 +2950,7 @@ static int __devexit emac_remove(struct
 
 	unregister_netdev(dev->ndev);
 
-	flush_scheduled_work();
+	cancel_work_sync(&dev->reset_work);
 
 	if (emac_has_feature(dev, EMAC_FTR_HAS_TAH))
 		tah_detach(dev->tah_dev, dev->tah_port);
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/ibmveth.c linux-libre-2.6.38-gnu1/drivers/net/ibmveth.c
--- linux-libre-2.6.37-gnu1/drivers/net/ibmveth.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/ibmveth.c	2011-03-14 21:20:32.000000000 -0400
@@ -729,11 +729,6 @@ static void netdev_get_drvinfo(struct ne
 		sizeof(info->version) - 1);
 }
 
-static u32 netdev_get_link(struct net_device *dev)
-{
-	return 1;
-}
-
 static void ibmveth_set_rx_csum_flags(struct net_device *dev, u32 data)
 {
 	struct ibmveth_adapter *adapter = netdev_priv(dev);
@@ -918,7 +913,7 @@ static void ibmveth_get_ethtool_stats(st
 static const struct ethtool_ops netdev_ethtool_ops = {
 	.get_drvinfo		= netdev_get_drvinfo,
 	.get_settings		= netdev_get_settings,
-	.get_link		= netdev_get_link,
+	.get_link		= ethtool_op_get_link,
 	.set_tx_csum		= ibmveth_set_tx_csum,
 	.get_rx_csum		= ibmveth_get_rx_csum,
 	.set_rx_csum		= ibmveth_set_rx_csum,
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/ifb.c linux-libre-2.6.38-gnu1/drivers/net/ifb.c
--- linux-libre-2.6.37-gnu1/drivers/net/ifb.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/ifb.c	2011-03-14 21:20:32.000000000 -0400
@@ -36,22 +36,10 @@
 #include <net/pkt_sched.h>
 #include <net/net_namespace.h>
 
-#define TX_TIMEOUT  (2*HZ)
-
 #define TX_Q_LIMIT    32
 struct ifb_private {
 	struct tasklet_struct   ifb_tasklet;
 	int     tasklet_pending;
-	/* mostly debug stats leave in for now */
-	unsigned long   st_task_enter; /* tasklet entered */
-	unsigned long   st_txq_refl_try; /* transmit queue refill attempt */
-	unsigned long   st_rxq_enter; /* receive queue entered */
-	unsigned long   st_rx2tx_tran; /* receive to trasmit transfers */
-	unsigned long   st_rxq_notenter; /*receiveQ not entered, resched */
-	unsigned long   st_rx_frm_egr; /* received from egress path */
-	unsigned long   st_rx_frm_ing; /* received from ingress path */
-	unsigned long   st_rxq_check;
-	unsigned long   st_rxq_rsch;
 	struct sk_buff_head     rq;
 	struct sk_buff_head     tq;
 };
@@ -73,24 +61,17 @@ static void ri_tasklet(unsigned long dev
 	struct sk_buff *skb;
 
 	txq = netdev_get_tx_queue(_dev, 0);
-	dp->st_task_enter++;
 	if ((skb = skb_peek(&dp->tq)) == NULL) {
-		dp->st_txq_refl_try++;
 		if (__netif_tx_trylock(txq)) {
-			dp->st_rxq_enter++;
-			while ((skb = skb_dequeue(&dp->rq)) != NULL) {
-				skb_queue_tail(&dp->tq, skb);
-				dp->st_rx2tx_tran++;
-			}
+			skb_queue_splice_tail_init(&dp->rq, &dp->tq);
 			__netif_tx_unlock(txq);
 		} else {
 			/* reschedule */
-			dp->st_rxq_notenter++;
 			goto resched;
 		}
 	}
 
-	while ((skb = skb_dequeue(&dp->tq)) != NULL) {
+	while ((skb = __skb_dequeue(&dp->tq)) != NULL) {
 		u32 from = G_TC_FROM(skb->tc_verd);
 
 		skb->tc_verd = 0;
@@ -112,24 +93,20 @@ static void ri_tasklet(unsigned long dev
 		skb->skb_iif = _dev->ifindex;
 
 		if (from & AT_EGRESS) {
-			dp->st_rx_frm_egr++;
 			dev_queue_xmit(skb);
 		} else if (from & AT_INGRESS) {
-			dp->st_rx_frm_ing++;
 			skb_pull(skb, skb->dev->hard_header_len);
-			netif_rx(skb);
+			netif_receive_skb(skb);
 		} else
 			BUG();
 	}
 
 	if (__netif_tx_trylock(txq)) {
-		dp->st_rxq_check++;
 		if ((skb = skb_peek(&dp->rq)) == NULL) {
 			dp->tasklet_pending = 0;
 			if (netif_queue_stopped(_dev))
 				netif_wake_queue(_dev);
 		} else {
-			dp->st_rxq_rsch++;
 			__netif_tx_unlock(txq);
 			goto resched;
 		}
@@ -149,6 +126,10 @@ static const struct net_device_ops ifb_n
 	.ndo_validate_addr = eth_validate_addr,
 };
 
+#define IFB_FEATURES (NETIF_F_NO_CSUM | NETIF_F_SG  | NETIF_F_FRAGLIST	| \
+		      NETIF_F_TSO_ECN | NETIF_F_TSO | NETIF_F_TSO6	| \
+		      NETIF_F_HIGHDMA | NETIF_F_HW_VLAN_TX)
+
 static void ifb_setup(struct net_device *dev)
 {
 	/* Initialize the device structure. */
@@ -159,6 +140,9 @@ static void ifb_setup(struct net_device
 	ether_setup(dev);
 	dev->tx_queue_len = TX_Q_LIMIT;
 
+	dev->features |= IFB_FEATURES;
+	dev->vlan_features |= IFB_FEATURES;
+
 	dev->flags |= IFF_NOARP;
 	dev->flags &= ~IFF_MULTICAST;
 	dev->priv_flags &= ~IFF_XMIT_DST_RELEASE;
@@ -184,7 +168,7 @@ static netdev_tx_t ifb_xmit(struct sk_bu
 		netif_stop_queue(dev);
 	}
 
-	skb_queue_tail(&dp->rq, skb);
+	__skb_queue_tail(&dp->rq, skb);
 	if (!dp->tasklet_pending) {
 		dp->tasklet_pending = 1;
 		tasklet_schedule(&dp->ifb_tasklet);
@@ -199,8 +183,8 @@ static int ifb_close(struct net_device *
 
 	tasklet_kill(&dp->ifb_tasklet);
 	netif_stop_queue(dev);
-	skb_queue_purge(&dp->rq);
-	skb_queue_purge(&dp->tq);
+	__skb_queue_purge(&dp->rq);
+	__skb_queue_purge(&dp->tq);
 	return 0;
 }
 
@@ -209,8 +193,8 @@ static int ifb_open(struct net_device *d
 	struct ifb_private *dp = netdev_priv(dev);
 
 	tasklet_init(&dp->ifb_tasklet, ri_tasklet, (unsigned long)dev);
-	skb_queue_head_init(&dp->rq);
-	skb_queue_head_init(&dp->tq);
+	__skb_queue_head_init(&dp->rq);
+	__skb_queue_head_init(&dp->tq);
 	netif_start_queue(dev);
 
 	return 0;
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/igb/e1000_82575.c linux-libre-2.6.38-gnu1/drivers/net/igb/e1000_82575.c
--- linux-libre-2.6.37-gnu1/drivers/net/igb/e1000_82575.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/igb/e1000_82575.c	2011-03-14 21:20:32.000000000 -0400
@@ -134,6 +134,8 @@ static s32 igb_get_invariants_82575(stru
 	case E1000_DEV_ID_82580_COPPER_DUAL:
 	case E1000_DEV_ID_DH89XXCC_SGMII:
 	case E1000_DEV_ID_DH89XXCC_SERDES:
+	case E1000_DEV_ID_DH89XXCC_BACKPLANE:
+	case E1000_DEV_ID_DH89XXCC_SFP:
 		mac->type = e1000_82580;
 		break;
 	case E1000_DEV_ID_I350_COPPER:
@@ -1478,6 +1480,39 @@ out:
 }
 
 /**
+ *  igb_vmdq_set_anti_spoofing_pf - enable or disable anti-spoofing
+ *  @hw: pointer to the hardware struct
+ *  @enable: state to enter, either enabled or disabled
+ *  @pf: Physical Function pool - do not set anti-spoofing for the PF
+ *
+ *  enables/disables L2 switch anti-spoofing functionality.
+ **/
+void igb_vmdq_set_anti_spoofing_pf(struct e1000_hw *hw, bool enable, int pf)
+{
+	u32 dtxswc;
+
+	switch (hw->mac.type) {
+	case e1000_82576:
+	case e1000_i350:
+		dtxswc = rd32(E1000_DTXSWC);
+		if (enable) {
+			dtxswc |= (E1000_DTXSWC_MAC_SPOOF_MASK |
+				   E1000_DTXSWC_VLAN_SPOOF_MASK);
+			/* The PF can spoof - it has to in order to
+			 * support emulation mode NICs */
+			dtxswc ^= (1 << pf | 1 << (pf + MAX_NUM_VFS));
+		} else {
+			dtxswc &= ~(E1000_DTXSWC_MAC_SPOOF_MASK |
+				    E1000_DTXSWC_VLAN_SPOOF_MASK);
+		}
+		wr32(E1000_DTXSWC, dtxswc);
+		break;
+	default:
+		break;
+	}
+}
+
+/**
  *  igb_vmdq_set_loopback_pf - enable or disable vmdq loopback
  *  @hw: pointer to the hardware struct
  *  @enable: state to enter, either enabled or disabled
@@ -1578,7 +1613,7 @@ static s32 igb_reset_mdicnfg_82580(struc
 {
 	s32 ret_val = 0;
 	u32 mdicnfg;
-	u16 nvm_data;
+	u16 nvm_data = 0;
 
 	if (hw->mac.type != e1000_82580)
 		goto out;
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/igb/e1000_82575.h linux-libre-2.6.38-gnu1/drivers/net/igb/e1000_82575.h
--- linux-libre-2.6.37-gnu1/drivers/net/igb/e1000_82575.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/igb/e1000_82575.h	2011-03-14 21:20:32.000000000 -0400
@@ -194,6 +194,10 @@ struct e1000_adv_tx_context_desc {
 #define E1000_NVM_APME_82575          0x0400
 #define MAX_NUM_VFS                   8
 
+#define E1000_DTXSWC_MAC_SPOOF_MASK   0x000000FF /* Per VF MAC spoof control */
+#define E1000_DTXSWC_VLAN_SPOOF_MASK  0x0000FF00 /* Per VF VLAN spoof control */
+#define E1000_DTXSWC_LLE_MASK         0x00FF0000 /* Per VF Local LB enables */
+#define E1000_DTXSWC_VLAN_SPOOF_SHIFT 8
 #define E1000_DTXSWC_VMDQ_LOOPBACK_EN (1 << 31)  /* global VF LB enable */
 
 /* Easy defines for setting default pool, would normally be left a zero */
@@ -243,6 +247,7 @@ struct e1000_adv_tx_context_desc {
 
 /* RX packet buffer size defines */
 #define E1000_RXPBS_SIZE_MASK_82576  0x0000007F
+void igb_vmdq_set_anti_spoofing_pf(struct e1000_hw *, bool, int);
 void igb_vmdq_set_loopback_pf(struct e1000_hw *, bool);
 void igb_vmdq_set_replication_pf(struct e1000_hw *, bool);
 u16 igb_rxpbs_adjust_82580(u32 data);
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/igb/e1000_defines.h linux-libre-2.6.38-gnu1/drivers/net/igb/e1000_defines.h
--- linux-libre-2.6.37-gnu1/drivers/net/igb/e1000_defines.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/igb/e1000_defines.h	2011-03-14 21:20:32.000000000 -0400
@@ -419,6 +419,9 @@
 #define E1000_ERR_SWFW_SYNC 13
 #define E1000_NOT_IMPLEMENTED 14
 #define E1000_ERR_MBX      15
+#define E1000_ERR_INVALID_ARGUMENT  16
+#define E1000_ERR_NO_SPACE          17
+#define E1000_ERR_NVM_PBA_SECTION   18
 
 /* Loop limit on how long we wait for auto-negotiation to complete */
 #define COPPER_LINK_UP_LIMIT              10
@@ -580,11 +583,15 @@
 
 /* Mask bits for fields in Word 0x1a of the NVM */
 
+/* length of string needed to store part num */
+#define E1000_PBANUM_LENGTH         11
+
 /* For checksumming, the sum of all words in the NVM should equal 0xBABA. */
 #define NVM_SUM                    0xBABA
 
 #define NVM_PBA_OFFSET_0           8
 #define NVM_PBA_OFFSET_1           9
+#define NVM_PBA_PTR_GUARD          0xFAFA
 #define NVM_WORD_SIZE_BASE_SHIFT   6
 
 /* NVM Commands - Microwire */
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/igb/e1000_hw.h linux-libre-2.6.38-gnu1/drivers/net/igb/e1000_hw.h
--- linux-libre-2.6.37-gnu1/drivers/net/igb/e1000_hw.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/igb/e1000_hw.h	2011-03-14 21:20:32.000000000 -0400
@@ -54,8 +54,10 @@ struct e1000_hw;
 #define E1000_DEV_ID_82580_SERDES             0x1510
 #define E1000_DEV_ID_82580_SGMII              0x1511
 #define E1000_DEV_ID_82580_COPPER_DUAL        0x1516
-#define E1000_DEV_ID_DH89XXCC_SGMII           0x0436
-#define E1000_DEV_ID_DH89XXCC_SERDES          0x0438
+#define E1000_DEV_ID_DH89XXCC_SGMII           0x0438
+#define E1000_DEV_ID_DH89XXCC_SERDES          0x043A
+#define E1000_DEV_ID_DH89XXCC_BACKPLANE       0x043C
+#define E1000_DEV_ID_DH89XXCC_SFP             0x0440
 #define E1000_DEV_ID_I350_COPPER              0x1521
 #define E1000_DEV_ID_I350_FIBER               0x1522
 #define E1000_DEV_ID_I350_SERDES              0x1523
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/igb/e1000_nvm.c linux-libre-2.6.38-gnu1/drivers/net/igb/e1000_nvm.c
--- linux-libre-2.6.37-gnu1/drivers/net/igb/e1000_nvm.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/igb/e1000_nvm.c	2011-03-14 21:20:32.000000000 -0400
@@ -445,31 +445,112 @@ out:
 }
 
 /**
- *  igb_read_part_num - Read device part number
+ *  igb_read_part_string - Read device part number
  *  @hw: pointer to the HW structure
  *  @part_num: pointer to device part number
+ *  @part_num_size: size of part number buffer
  *
  *  Reads the product board assembly (PBA) number from the EEPROM and stores
  *  the value in part_num.
  **/
-s32 igb_read_part_num(struct e1000_hw *hw, u32 *part_num)
+s32 igb_read_part_string(struct e1000_hw *hw, u8 *part_num, u32 part_num_size)
 {
-	s32  ret_val;
+	s32 ret_val;
 	u16 nvm_data;
+	u16 pointer;
+	u16 offset;
+	u16 length;
+
+	if (part_num == NULL) {
+		hw_dbg("PBA string buffer was null\n");
+		ret_val = E1000_ERR_INVALID_ARGUMENT;
+		goto out;
+	}
 
 	ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_0, 1, &nvm_data);
 	if (ret_val) {
 		hw_dbg("NVM Read Error\n");
 		goto out;
 	}
-	*part_num = (u32)(nvm_data << 16);
 
-	ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_1, 1, &nvm_data);
+	ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_1, 1, &pointer);
 	if (ret_val) {
 		hw_dbg("NVM Read Error\n");
 		goto out;
 	}
-	*part_num |= nvm_data;
+
+	/*
+	 * if nvm_data is not ptr guard the PBA must be in legacy format which
+	 * means pointer is actually our second data word for the PBA number
+	 * and we can decode it into an ascii string
+	 */
+	if (nvm_data != NVM_PBA_PTR_GUARD) {
+		hw_dbg("NVM PBA number is not stored as string\n");
+
+		/* we will need 11 characters to store the PBA */
+		if (part_num_size < 11) {
+			hw_dbg("PBA string buffer too small\n");
+			return E1000_ERR_NO_SPACE;
+		}
+
+		/* extract hex string from data and pointer */
+		part_num[0] = (nvm_data >> 12) & 0xF;
+		part_num[1] = (nvm_data >> 8) & 0xF;
+		part_num[2] = (nvm_data >> 4) & 0xF;
+		part_num[3] = nvm_data & 0xF;
+		part_num[4] = (pointer >> 12) & 0xF;
+		part_num[5] = (pointer >> 8) & 0xF;
+		part_num[6] = '-';
+		part_num[7] = 0;
+		part_num[8] = (pointer >> 4) & 0xF;
+		part_num[9] = pointer & 0xF;
+
+		/* put a null character on the end of our string */
+		part_num[10] = '\0';
+
+		/* switch all the data but the '-' to hex char */
+		for (offset = 0; offset < 10; offset++) {
+			if (part_num[offset] < 0xA)
+				part_num[offset] += '0';
+			else if (part_num[offset] < 0x10)
+				part_num[offset] += 'A' - 0xA;
+		}
+
+		goto out;
+	}
+
+	ret_val = hw->nvm.ops.read(hw, pointer, 1, &length);
+	if (ret_val) {
+		hw_dbg("NVM Read Error\n");
+		goto out;
+	}
+
+	if (length == 0xFFFF || length == 0) {
+		hw_dbg("NVM PBA number section invalid length\n");
+		ret_val = E1000_ERR_NVM_PBA_SECTION;
+		goto out;
+	}
+	/* check if part_num buffer is big enough */
+	if (part_num_size < (((u32)length * 2) - 1)) {
+		hw_dbg("PBA string buffer too small\n");
+		ret_val = E1000_ERR_NO_SPACE;
+		goto out;
+	}
+
+	/* trim pba length from start of string */
+	pointer++;
+	length--;
+
+	for (offset = 0; offset < length; offset++) {
+		ret_val = hw->nvm.ops.read(hw, pointer + offset, 1, &nvm_data);
+		if (ret_val) {
+			hw_dbg("NVM Read Error\n");
+			goto out;
+		}
+		part_num[offset * 2] = (u8)(nvm_data >> 8);
+		part_num[(offset * 2) + 1] = (u8)(nvm_data & 0xFF);
+	}
+	part_num[offset * 2] = '\0';
 
 out:
 	return ret_val;
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/igb/e1000_nvm.h linux-libre-2.6.38-gnu1/drivers/net/igb/e1000_nvm.h
--- linux-libre-2.6.37-gnu1/drivers/net/igb/e1000_nvm.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/igb/e1000_nvm.h	2011-03-14 21:20:32.000000000 -0400
@@ -32,6 +32,8 @@ s32  igb_acquire_nvm(struct e1000_hw *hw
 void igb_release_nvm(struct e1000_hw *hw);
 s32  igb_read_mac_addr(struct e1000_hw *hw);
 s32  igb_read_part_num(struct e1000_hw *hw, u32 *part_num);
+s32  igb_read_part_string(struct e1000_hw *hw, u8 *part_num,
+                          u32 part_num_size);
 s32  igb_read_nvm_eerd(struct e1000_hw *hw, u16 offset, u16 words, u16 *data);
 s32  igb_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data);
 s32  igb_validate_nvm_checksum(struct e1000_hw *hw);
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/igb/e1000_phy.c linux-libre-2.6.38-gnu1/drivers/net/igb/e1000_phy.c
--- linux-libre-2.6.37-gnu1/drivers/net/igb/e1000_phy.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/igb/e1000_phy.c	2011-03-14 21:20:32.000000000 -0400
@@ -1757,11 +1757,12 @@ s32 igb_get_cable_length_igp_2(struct e1
 	u16 phy_data, i, agc_value = 0;
 	u16 cur_agc_index, max_agc_index = 0;
 	u16 min_agc_index = IGP02E1000_CABLE_LENGTH_TABLE_SIZE - 1;
-	u16 agc_reg_array[IGP02E1000_PHY_CHANNEL_NUM] =
-							 {IGP02E1000_PHY_AGC_A,
-							  IGP02E1000_PHY_AGC_B,
-							  IGP02E1000_PHY_AGC_C,
-							  IGP02E1000_PHY_AGC_D};
+	static const u16 agc_reg_array[IGP02E1000_PHY_CHANNEL_NUM] = {
+	       IGP02E1000_PHY_AGC_A,
+	       IGP02E1000_PHY_AGC_B,
+	       IGP02E1000_PHY_AGC_C,
+	       IGP02E1000_PHY_AGC_D
+	};
 
 	/* Read the AGC registers for all channels */
 	for (i = 0; i < IGP02E1000_PHY_CHANNEL_NUM; i++) {
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/igb/e1000_regs.h linux-libre-2.6.38-gnu1/drivers/net/igb/e1000_regs.h
--- linux-libre-2.6.37-gnu1/drivers/net/igb/e1000_regs.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/igb/e1000_regs.h	2011-03-14 21:20:32.000000000 -0400
@@ -301,6 +301,7 @@
 #define E1000_VFTE      0x00C90 /* VF Transmit Enables */
 #define E1000_QDE       0x02408 /* Queue Drop Enable - RW */
 #define E1000_DTXSWC    0x03500 /* DMA Tx Switch Control - RW */
+#define E1000_WVBR      0x03554 /* VM Wrong Behavior - RWS */
 #define E1000_RPLOLR    0x05AF0 /* Replication Offload - RW */
 #define E1000_UTA       0x0A000 /* Unicast Table Array - RW */
 #define E1000_IOVTCL    0x05BBC /* IOV Control Register */
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/igb/igb.h linux-libre-2.6.38-gnu1/drivers/net/igb/igb.h
--- linux-libre-2.6.37-gnu1/drivers/net/igb/igb.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/igb/igb.h	2011-03-14 21:20:32.000000000 -0400
@@ -324,6 +324,7 @@ struct igb_adapter {
 	unsigned int vfs_allocated_count;
 	struct vf_data_storage *vf_data;
 	u32 rss_queues;
+	u32 wvbr;
 };
 
 #define IGB_FLAG_HAS_MSI           (1 << 0)
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/igb/igb_main.c linux-libre-2.6.38-gnu1/drivers/net/igb/igb_main.c
--- linux-libre-2.6.37-gnu1/drivers/net/igb/igb_main.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/igb/igb_main.c	2011-03-14 21:20:32.000000000 -0400
@@ -73,6 +73,8 @@ static DEFINE_PCI_DEVICE_TABLE(igb_pci_t
 	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82580_COPPER_DUAL), board_82575 },
 	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_DH89XXCC_SGMII), board_82575 },
 	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_DH89XXCC_SERDES), board_82575 },
+	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_DH89XXCC_BACKPLANE), board_82575 },
+	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_DH89XXCC_SFP), board_82575 },
 	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82576), board_82575 },
 	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82576_NS), board_82575 },
 	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82576_NS_SERDES), board_82575 },
@@ -1654,7 +1656,7 @@ void igb_reset(struct igb_adapter *adapt
 	if (adapter->vfs_allocated_count) {
 		int i;
 		for (i = 0 ; i < adapter->vfs_allocated_count; i++)
-			adapter->vf_data[i].flags = 0;
+			adapter->vf_data[i].flags &= IGB_VF_FLAG_PF_SET_MAC;
 
 		/* ping all the active vfs to let them know we are going down */
 		igb_ping_all_vfs(adapter);
@@ -1729,12 +1731,13 @@ static int __devinit igb_probe(struct pc
 	struct igb_adapter *adapter;
 	struct e1000_hw *hw;
 	u16 eeprom_data = 0;
+	s32 ret_val;
 	static int global_quad_port_a; /* global quad port a indication */
 	const struct e1000_info *ei = igb_info_tbl[ent->driver_data];
 	unsigned long mmio_start, mmio_len;
 	int err, pci_using_dac;
 	u16 eeprom_apme_mask = IGB_EEPROM_APME;
-	u32 part_num;
+	u8 part_str[E1000_PBANUM_LENGTH];
 
 	/* Catch broken hardware that put the wrong VF device ID in
 	 * the PCIe SR-IOV capability.
@@ -2000,10 +2003,10 @@ static int __devinit igb_probe(struct pc
 		   "unknown"),
 		 netdev->dev_addr);
 
-	igb_read_part_num(hw, &part_num);
-	dev_info(&pdev->dev, "%s: PBA No: %06x-%03x\n", netdev->name,
-		(part_num >> 8), (part_num & 0xff));
-
+	ret_val = igb_read_part_string(hw, part_str, E1000_PBANUM_LENGTH);
+	if (ret_val)
+		strcpy(part_str, "Unknown");
+	dev_info(&pdev->dev, "%s: PBA No: %s\n", netdev->name, part_str);
 	dev_info(&pdev->dev,
 		"Using %s interrupts. %d rx queue(s), %d tx queue(s)\n",
 		adapter->msix_entries ? "MSI-X" :
@@ -2049,13 +2052,16 @@ static void __devexit igb_remove(struct
 	struct igb_adapter *adapter = netdev_priv(netdev);
 	struct e1000_hw *hw = &adapter->hw;
 
-	/* flush_scheduled work may reschedule our watchdog task, so
-	 * explicitly disable watchdog tasks from being rescheduled  */
+	/*
+	 * The watchdog timer may be rescheduled, so explicitly
+	 * disable watchdog from being rescheduled.
+	 */
 	set_bit(__IGB_DOWN, &adapter->state);
 	del_timer_sync(&adapter->watchdog_timer);
 	del_timer_sync(&adapter->phy_info_timer);
 
-	flush_scheduled_work();
+	cancel_work_sync(&adapter->reset_task);
+	cancel_work_sync(&adapter->watchdog_task);
 
 #ifdef CONFIG_IGB_DCA
 	if (adapter->flags & IGB_FLAG_DCA_ENABLED) {
@@ -2436,10 +2442,9 @@ int igb_setup_tx_resources(struct igb_ri
 	int size;
 
 	size = sizeof(struct igb_buffer) * tx_ring->count;
-	tx_ring->buffer_info = vmalloc(size);
+	tx_ring->buffer_info = vzalloc(size);
 	if (!tx_ring->buffer_info)
 		goto err;
-	memset(tx_ring->buffer_info, 0, size);
 
 	/* round up to nearest 4K */
 	tx_ring->size = tx_ring->count * sizeof(union e1000_adv_tx_desc);
@@ -2587,10 +2592,9 @@ int igb_setup_rx_resources(struct igb_ri
 	int size, desc_len;
 
 	size = sizeof(struct igb_buffer) * rx_ring->count;
-	rx_ring->buffer_info = vmalloc(size);
+	rx_ring->buffer_info = vzalloc(size);
 	if (!rx_ring->buffer_info)
 		goto err;
-	memset(rx_ring->buffer_info, 0, size);
 
 	desc_len = sizeof(union e1000_adv_rx_desc);
 
@@ -3362,6 +3366,45 @@ static void igb_set_rx_mode(struct net_d
 	igb_restore_vf_multicasts(adapter);
 }
 
+static void igb_check_wvbr(struct igb_adapter *adapter)
+{
+	struct e1000_hw *hw = &adapter->hw;
+	u32 wvbr = 0;
+
+	switch (hw->mac.type) {
+	case e1000_82576:
+	case e1000_i350:
+		if (!(wvbr = rd32(E1000_WVBR)))
+			return;
+		break;
+	default:
+		break;
+	}
+
+	adapter->wvbr |= wvbr;
+}
+
+#define IGB_STAGGERED_QUEUE_OFFSET 8
+
+static void igb_spoof_check(struct igb_adapter *adapter)
+{
+	int j;
+
+	if (!adapter->wvbr)
+		return;
+
+	for(j = 0; j < adapter->vfs_allocated_count; j++) {
+		if (adapter->wvbr & (1 << j) ||
+		    adapter->wvbr & (1 << (j + IGB_STAGGERED_QUEUE_OFFSET))) {
+			dev_warn(&adapter->pdev->dev,
+				"Spoof event(s) detected on VF %d\n", j);
+			adapter->wvbr &=
+				~((1 << j) |
+				  (1 << (j + IGB_STAGGERED_QUEUE_OFFSET)));
+		}
+	}
+}
+
 /* Need to wait a few seconds after link up to get diagnostic information from
  * the phy */
 static void igb_update_phy_info(unsigned long data)
@@ -3521,6 +3564,8 @@ static void igb_watchdog_task(struct wor
 		wr32(E1000_ICS, E1000_ICS_RXDMT0);
 	}
 
+	igb_spoof_check(adapter);
+
 	/* Reset the timer */
 	if (!test_bit(__IGB_DOWN, &adapter->state))
 		mod_timer(&adapter->watchdog_timer,
@@ -4517,6 +4562,10 @@ static irqreturn_t igb_msix_other(int ir
 	if (icr & E1000_ICR_DOUTSYNC) {
 		/* HW is reporting DMA is out of sync */
 		adapter->stats.doosync++;
+		/* The DMA Out of Sync is also indication of a spoof event
+		 * in IOV mode. Check the Wrong VM Behavior register to
+		 * see if it is really a spoof event. */
+		igb_check_wvbr(adapter);
 	}
 
 	/* Check for a mailbox event */
@@ -4969,8 +5018,8 @@ static int igb_set_vf_vlan(struct igb_ad
 
 static inline void igb_vf_reset(struct igb_adapter *adapter, u32 vf)
 {
-	/* clear flags */
-	adapter->vf_data[vf].flags &= ~(IGB_VF_FLAG_PF_SET_MAC);
+	/* clear flags - except flag that indicates PF has set the MAC */
+	adapter->vf_data[vf].flags &= IGB_VF_FLAG_PF_SET_MAC;
 	adapter->vf_data[vf].last_nack = jiffies;
 
 	/* reset offloads to defaults */
@@ -5024,7 +5073,7 @@ static void igb_vf_reset_msg(struct igb_
 	reg = rd32(E1000_VFRE);
 	wr32(E1000_VFRE, reg | (1 << vf));
 
-	adapter->vf_data[vf].flags = IGB_VF_FLAG_CTS;
+	adapter->vf_data[vf].flags |= IGB_VF_FLAG_CTS;
 
 	/* reply to reset with ack and vf mac address */
 	msgbuf[0] = E1000_VF_RESET | E1000_VT_MSGTYPE_ACK;
@@ -5103,7 +5152,14 @@ static void igb_rcv_msg_from_vf(struct i
 
 	switch ((msgbuf[0] & 0xFFFF)) {
 	case E1000_VF_SET_MAC_ADDR:
-		retval = igb_set_vf_mac_addr(adapter, msgbuf, vf);
+		retval = -EINVAL;
+		if (!(vf_data->flags & IGB_VF_FLAG_PF_SET_MAC))
+			retval = igb_set_vf_mac_addr(adapter, msgbuf, vf);
+		else
+			dev_warn(&pdev->dev,
+				 "VF %d attempted to override administratively "
+				 "set MAC address\nReload the VF driver to "
+				 "resume operations\n", vf);
 		break;
 	case E1000_VF_SET_PROMISC:
 		retval = igb_set_vf_promisc(adapter, msgbuf, vf);
@@ -5115,8 +5171,12 @@ static void igb_rcv_msg_from_vf(struct i
 		retval = igb_set_vf_rlpml(adapter, msgbuf[1], vf);
 		break;
 	case E1000_VF_SET_VLAN:
-		if (adapter->vf_data[vf].pf_vlan)
-			retval = -1;
+		retval = -1;
+		if (vf_data->pf_vlan)
+			dev_warn(&pdev->dev,
+				 "VF %d attempted to override administratively "
+				 "set VLAN tag\nReload the VF driver to "
+				 "resume operations\n", vf);
 		else
 			retval = igb_set_vf_vlan(adapter, msgbuf, vf);
 		break;
@@ -6580,6 +6640,8 @@ static void igb_vmm_control(struct igb_a
 	if (adapter->vfs_allocated_count) {
 		igb_vmdq_set_loopback_pf(hw, true);
 		igb_vmdq_set_replication_pf(hw, true);
+		igb_vmdq_set_anti_spoofing_pf(hw, true,
+						adapter->vfs_allocated_count);
 	} else {
 		igb_vmdq_set_loopback_pf(hw, false);
 		igb_vmdq_set_replication_pf(hw, false);
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/igbvf/defines.h linux-libre-2.6.38-gnu1/drivers/net/igbvf/defines.h
--- linux-libre-2.6.37-gnu1/drivers/net/igbvf/defines.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/igbvf/defines.h	2011-03-14 21:20:32.000000000 -0400
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel(R) 82576 Virtual Function Linux driver
-  Copyright(c) 1999 - 2009 Intel Corporation.
+  Copyright(c) 1999 - 2010 Intel 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,
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/igbvf/ethtool.c linux-libre-2.6.38-gnu1/drivers/net/igbvf/ethtool.c
--- linux-libre-2.6.37-gnu1/drivers/net/igbvf/ethtool.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/igbvf/ethtool.c	2011-03-14 21:20:32.000000000 -0400
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel(R) 82576 Virtual Function Linux driver
-  Copyright(c) 2009 Intel Corporation.
+  Copyright(c) 2009 - 2010 Intel 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,
@@ -110,11 +110,6 @@ static int igbvf_get_settings(struct net
 	return 0;
 }
 
-static u32 igbvf_get_link(struct net_device *netdev)
-{
-	return netif_carrier_ok(netdev);
-}
-
 static int igbvf_set_settings(struct net_device *netdev,
                               struct ethtool_cmd *ecmd)
 {
@@ -515,7 +510,7 @@ static const struct ethtool_ops igbvf_et
 	.get_msglevel		= igbvf_get_msglevel,
 	.set_msglevel		= igbvf_set_msglevel,
 	.nway_reset		= igbvf_nway_reset,
-	.get_link		= igbvf_get_link,
+	.get_link		= ethtool_op_get_link,
 	.get_eeprom_len		= igbvf_get_eeprom_len,
 	.get_eeprom		= igbvf_get_eeprom,
 	.set_eeprom		= igbvf_set_eeprom,
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/igbvf/igbvf.h linux-libre-2.6.38-gnu1/drivers/net/igbvf/igbvf.h
--- linux-libre-2.6.37-gnu1/drivers/net/igbvf/igbvf.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/igbvf/igbvf.h	2011-03-14 21:20:32.000000000 -0400
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel(R) 82576 Virtual Function Linux driver
-  Copyright(c) 2009 Intel Corporation.
+  Copyright(c) 2009 - 2010 Intel 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,
@@ -97,6 +97,7 @@ struct igbvf_adapter;
 
 enum igbvf_boards {
 	board_vf,
+	board_i350_vf,
 };
 
 struct igbvf_queue_stats {
@@ -126,7 +127,6 @@ struct igbvf_buffer {
 			unsigned int page_offset;
 		};
 	};
-	struct page *page;
 };
 
 union igbvf_desc {
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/igbvf/Makefile linux-libre-2.6.38-gnu1/drivers/net/igbvf/Makefile
--- linux-libre-2.6.37-gnu1/drivers/net/igbvf/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/igbvf/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -1,7 +1,7 @@
 ################################################################################
 #
 # Intel(R) 82576 Virtual Function Linux driver
-# Copyright(c) 2009 Intel Corporation.
+# Copyright(c) 2009 - 2010 Intel 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,
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/igbvf/mbx.c linux-libre-2.6.38-gnu1/drivers/net/igbvf/mbx.c
--- linux-libre-2.6.37-gnu1/drivers/net/igbvf/mbx.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/igbvf/mbx.c	2011-03-14 21:20:32.000000000 -0400
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel(R) 82576 Virtual Function Linux driver
-  Copyright(c) 2009 Intel Corporation.
+  Copyright(c) 2009 - 2010 Intel 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,
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/igbvf/mbx.h linux-libre-2.6.38-gnu1/drivers/net/igbvf/mbx.h
--- linux-libre-2.6.37-gnu1/drivers/net/igbvf/mbx.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/igbvf/mbx.h	2011-03-14 21:20:32.000000000 -0400
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel(R) 82576 Virtual Function Linux driver
-  Copyright(c) 1999 - 2009 Intel Corporation.
+  Copyright(c) 1999 - 2010 Intel 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,
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/igbvf/netdev.c linux-libre-2.6.38-gnu1/drivers/net/igbvf/netdev.c
--- linux-libre-2.6.37-gnu1/drivers/net/igbvf/netdev.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/igbvf/netdev.c	2011-03-14 21:20:32.000000000 -0400
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel(R) 82576 Virtual Function Linux driver
-  Copyright(c) 2009 Intel Corporation.
+  Copyright(c) 2009 - 2010 Intel 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,
@@ -44,12 +44,13 @@
 
 #include "igbvf.h"
 
-#define DRV_VERSION "1.0.0-k0"
+#define DRV_VERSION "1.0.8-k0"
 char igbvf_driver_name[] = "igbvf";
 const char igbvf_driver_version[] = DRV_VERSION;
 static const char igbvf_driver_string[] =
 				"Intel(R) Virtual Function Network Driver";
-static const char igbvf_copyright[] = "Copyright (c) 2009 Intel Corporation.";
+static const char igbvf_copyright[] =
+				"Copyright (c) 2009 - 2010 Intel Corporation.";
 
 static int igbvf_poll(struct napi_struct *napi, int budget);
 static void igbvf_reset(struct igbvf_adapter *);
@@ -63,8 +64,16 @@ static struct igbvf_info igbvf_vf_info =
 	.init_ops               = e1000_init_function_pointers_vf,
 };
 
+static struct igbvf_info igbvf_i350_vf_info = {
+	.mac			= e1000_vfadapt_i350,
+	.flags			= 0,
+	.pba			= 10,
+	.init_ops		= e1000_init_function_pointers_vf,
+};
+
 static const struct igbvf_info *igbvf_info_tbl[] = {
 	[board_vf]              = &igbvf_vf_info,
+	[board_i350_vf]		= &igbvf_i350_vf_info,
 };
 
 /**
@@ -429,10 +438,9 @@ int igbvf_setup_tx_resources(struct igbv
 	int size;
 
 	size = sizeof(struct igbvf_buffer) * tx_ring->count;
-	tx_ring->buffer_info = vmalloc(size);
+	tx_ring->buffer_info = vzalloc(size);
 	if (!tx_ring->buffer_info)
 		goto err;
-	memset(tx_ring->buffer_info, 0, size);
 
 	/* round up to nearest 4K */
 	tx_ring->size = tx_ring->count * sizeof(union e1000_adv_tx_desc);
@@ -469,10 +477,9 @@ int igbvf_setup_rx_resources(struct igbv
 	int size, desc_len;
 
 	size = sizeof(struct igbvf_buffer) * rx_ring->count;
-	rx_ring->buffer_info = vmalloc(size);
+	rx_ring->buffer_info = vzalloc(size);
 	if (!rx_ring->buffer_info)
 		goto err;
-	memset(rx_ring->buffer_info, 0, size);
 
 	desc_len = sizeof(union e1000_adv_rx_desc);
 
@@ -1851,8 +1858,6 @@ static void igbvf_watchdog_task(struct w
 
 	if (link) {
 		if (!netif_carrier_ok(netdev)) {
-			bool txb2b = 1;
-
 			mac->ops.get_link_up_info(&adapter->hw,
 			                          &adapter->link_speed,
 			                          &adapter->link_duplex);
@@ -1862,11 +1867,9 @@ static void igbvf_watchdog_task(struct w
 			adapter->tx_timeout_factor = 1;
 			switch (adapter->link_speed) {
 			case SPEED_10:
-				txb2b = 0;
 				adapter->tx_timeout_factor = 16;
 				break;
 			case SPEED_100:
-				txb2b = 0;
 				/* maybe add some timeout factor ? */
 				break;
 			}
@@ -2830,13 +2833,14 @@ static void __devexit igbvf_remove(struc
 	struct e1000_hw *hw = &adapter->hw;
 
 	/*
-	 * flush_scheduled work may reschedule our watchdog task, so
-	 * explicitly disable watchdog tasks from being rescheduled
+	 * The watchdog timer may be rescheduled, so explicitly
+	 * disable it from being rescheduled.
 	 */
 	set_bit(__IGBVF_DOWN, &adapter->state);
 	del_timer_sync(&adapter->watchdog_timer);
 
-	flush_scheduled_work();
+	cancel_work_sync(&adapter->reset_task);
+	cancel_work_sync(&adapter->watchdog_task);
 
 	unregister_netdev(netdev);
 
@@ -2869,6 +2873,7 @@ static struct pci_error_handlers igbvf_e
 
 static DEFINE_PCI_DEVICE_TABLE(igbvf_pci_tbl) = {
 	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82576_VF), board_vf },
+	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_I350_VF), board_i350_vf },
 	{ } /* terminate list */
 };
 MODULE_DEVICE_TABLE(pci, igbvf_pci_tbl);
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/igbvf/regs.h linux-libre-2.6.38-gnu1/drivers/net/igbvf/regs.h
--- linux-libre-2.6.37-gnu1/drivers/net/igbvf/regs.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/igbvf/regs.h	2011-03-14 21:20:32.000000000 -0400
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel(R) 82576 Virtual Function Linux driver
-  Copyright(c) 2009 Intel Corporation.
+  Copyright(c) 2009 - 2010 Intel 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,
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/igbvf/vf.c linux-libre-2.6.38-gnu1/drivers/net/igbvf/vf.c
--- linux-libre-2.6.37-gnu1/drivers/net/igbvf/vf.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/igbvf/vf.c	2011-03-14 21:20:32.000000000 -0400
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel(R) 82576 Virtual Function Linux driver
-  Copyright(c) 2009 Intel Corporation.
+  Copyright(c) 2009 - 2010 Intel 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,
@@ -220,7 +220,7 @@ static u32 e1000_hash_mc_addr_vf(struct
  *  The parameter rar_count will usually be hw->mac.rar_entry_count
  *  unless there are workarounds that change this.
  **/
-void e1000_update_mc_addr_list_vf(struct e1000_hw *hw,
+static void e1000_update_mc_addr_list_vf(struct e1000_hw *hw,
                                   u8 *mc_addr_list, u32 mc_addr_count,
                                   u32 rar_used_count, u32 rar_count)
 {
@@ -362,8 +362,8 @@ static s32 e1000_check_for_link_vf(struc
 	 * or a virtual function reset
 	 */
 
-	/* If we were hit with a reset drop the link */
-	if (!mbx->ops.check_for_rst(hw))
+	/* If we were hit with a reset or timeout drop the link */
+	if (!mbx->ops.check_for_rst(hw) || !mbx->timeout)
 		mac->get_link_status = true;
 
 	if (!mac->get_link_status)
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/igbvf/vf.h linux-libre-2.6.38-gnu1/drivers/net/igbvf/vf.h
--- linux-libre-2.6.37-gnu1/drivers/net/igbvf/vf.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/igbvf/vf.h	2011-03-14 21:20:32.000000000 -0400
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel(R) 82576 Virtual Function Linux driver
-  Copyright(c) 2009 Intel Corporation.
+  Copyright(c) 2009 - 2010 Intel 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,
@@ -39,6 +39,7 @@
 struct e1000_hw;
 
 #define E1000_DEV_ID_82576_VF                 0x10CA
+#define E1000_DEV_ID_I350_VF                  0x1520
 #define E1000_REVISION_0 0
 #define E1000_REVISION_1 1
 #define E1000_REVISION_2 2
@@ -133,6 +134,7 @@ struct e1000_adv_tx_context_desc {
 enum e1000_mac_type {
 	e1000_undefined = 0,
 	e1000_vfadapt,
+	e1000_vfadapt_i350,
 	e1000_num_macs  /* List is 1-based, so subtract 1 for true count. */
 };
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/irda/act200l-sir.c linux-libre-2.6.38-gnu1/drivers/net/irda/act200l-sir.c
--- linux-libre-2.6.37-gnu1/drivers/net/irda/act200l-sir.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/irda/act200l-sir.c	2011-03-14 21:20:32.000000000 -0400
@@ -199,7 +199,7 @@ static int act200l_reset(struct sir_dev
 {
 	unsigned state = dev->fsm.substate;
 	unsigned delay = 0;
-	u8 control[9] = {
+	static const u8 control[9] = {
 		ACT200L_REG15,
 		ACT200L_REG13 | ACT200L_SHDW,
 		ACT200L_REG21 | ACT200L_EXCK | ACT200L_OSCL,
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/irda/bfin_sir.h linux-libre-2.6.38-gnu1/drivers/net/irda/bfin_sir.h
--- linux-libre-2.6.37-gnu1/drivers/net/irda/bfin_sir.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/irda/bfin_sir.h	2011-03-14 21:20:32.000000000 -0400
@@ -26,6 +26,8 @@
 #include <asm/cacheflush.h>
 #include <asm/dma.h>
 #include <asm/portmux.h>
+#include <mach/bfin_serial_5xx.h>
+#undef DRIVER_NAME
 
 #ifdef CONFIG_SIR_BFIN_DMA
 struct dma_rx_buf {
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/irda/donauboe.c linux-libre-2.6.38-gnu1/drivers/net/irda/donauboe.c
--- linux-libre-2.6.37-gnu1/drivers/net/irda/donauboe.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/irda/donauboe.c	2011-03-14 21:20:32.000000000 -0400
@@ -818,9 +818,9 @@ toshoboe_probe (struct toshoboe_cb *self
 {
   int i, j, n;
 #ifdef USE_MIR
-  int bauds[] = { 9600, 115200, 4000000, 1152000 };
+  static const int bauds[] = { 9600, 115200, 4000000, 1152000 };
 #else
-  int bauds[] = { 9600, 115200, 4000000 };
+  static const int bauds[] = { 9600, 115200, 4000000 };
 #endif
   unsigned long flags;
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/irda/donauboe.h linux-libre-2.6.38-gnu1/drivers/net/irda/donauboe.h
--- linux-libre-2.6.37-gnu1/drivers/net/irda/donauboe.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/irda/donauboe.h	2011-03-14 21:20:32.000000000 -0400
@@ -30,7 +30,7 @@
  *     or the type-DO IR port.
  *
  * IrDA chip set list from Toshiba Computer Engineering Corp.
- * model			method	maker	controler		Version 
+ * model			method	maker	controller		Version 
  * Portege 320CT	FIR,SIR Toshiba Oboe(Triangle) 
  * Portege 3010CT	FIR,SIR Toshiba Oboe(Sydney) 
  * Portege 3015CT	FIR,SIR Toshiba Oboe(Sydney) 
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/irda/mcs7780.c linux-libre-2.6.38-gnu1/drivers/net/irda/mcs7780.c
--- linux-libre-2.6.37-gnu1/drivers/net/irda/mcs7780.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/irda/mcs7780.c	2011-03-14 21:20:32.000000000 -0400
@@ -959,7 +959,7 @@ static void mcs_disconnect(struct usb_in
 	if (!mcs)
 		return;
 
-	flush_scheduled_work();
+	cancel_work_sync(&mcs->work);
 
 	unregister_netdev(mcs->netdev);
 	free_netdev(mcs->netdev);
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/irda/sh_irda.c linux-libre-2.6.38-gnu1/drivers/net/irda/sh_irda.c
--- linux-libre-2.6.37-gnu1/drivers/net/irda/sh_irda.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/irda/sh_irda.c	2011-03-14 21:20:32.000000000 -0400
@@ -635,7 +635,7 @@ static int sh_irda_hard_xmit(struct sk_b
 
 	ret = sh_irda_set_baudrate(self, speed);
 	if (ret < 0)
-		return ret;
+		goto sh_irda_hard_xmit_end;
 
 	self->tx_buff.len = 0;
 	if (skb->len) {
@@ -652,11 +652,21 @@ static int sh_irda_hard_xmit(struct sk_b
 
 		sh_irda_write(self, IRTFLR, self->tx_buff.len);
 		sh_irda_write(self, IRTCTR, ARMOD | TE);
-	}
+	} else
+		goto sh_irda_hard_xmit_end;
 
 	dev_kfree_skb(skb);
 
 	return 0;
+
+sh_irda_hard_xmit_end:
+	sh_irda_set_baudrate(self, 9600);
+	netif_wake_queue(self->ndev);
+	sh_irda_rcv_ctrl(self, 1);
+	dev_kfree_skb(skb);
+
+	return ret;
+
 }
 
 static int sh_irda_ioctl(struct net_device *ndev, struct ifreq *ifreq, int cmd)
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/irda/smsc-ircc2.c linux-libre-2.6.38-gnu1/drivers/net/irda/smsc-ircc2.c
--- linux-libre-2.6.37-gnu1/drivers/net/irda/smsc-ircc2.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/irda/smsc-ircc2.c	2011-03-14 21:20:32.000000000 -0400
@@ -376,7 +376,7 @@ MODULE_DEVICE_TABLE(pnp, smsc_ircc_pnp_t
 static int pnp_driver_registered;
 
 #ifdef CONFIG_PNP
-static int __init smsc_ircc_pnp_probe(struct pnp_dev *dev,
+static int __devinit smsc_ircc_pnp_probe(struct pnp_dev *dev,
 				      const struct pnp_device_id *dev_id)
 {
 	unsigned int firbase, sirbase;
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/iseries_veth.c linux-libre-2.6.38-gnu1/drivers/net/iseries_veth.c
--- linux-libre-2.6.37-gnu1/drivers/net/iseries_veth.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/iseries_veth.c	2011-03-14 21:20:32.000000000 -0400
@@ -885,17 +885,8 @@ static void veth_stop_connection(struct
 	veth_kick_statemachine(cnx);
 	spin_unlock_irq(&cnx->lock);
 
-	/* There's a slim chance the reset code has just queued the
-	 * statemachine to run in five seconds. If so we need to cancel
-	 * that and requeue the work to run now. */
-	if (cancel_delayed_work(&cnx->statemachine_wq)) {
-		spin_lock_irq(&cnx->lock);
-		veth_kick_statemachine(cnx);
-		spin_unlock_irq(&cnx->lock);
-	}
-
-	/* Wait for the state machine to run. */
-	flush_scheduled_work();
+	/* ensure the statemachine runs now and waits for its completion */
+	flush_delayed_work_sync(&cnx->statemachine_wq);
 }
 
 static void veth_destroy_connection(struct veth_lpar_connection *cnx)
@@ -1009,15 +1000,10 @@ static int veth_get_settings(struct net_
 	return 0;
 }
 
-static u32 veth_get_link(struct net_device *dev)
-{
-	return 1;
-}
-
 static const struct ethtool_ops ops = {
 	.get_drvinfo = veth_get_drvinfo,
 	.get_settings = veth_get_settings,
-	.get_link = veth_get_link,
+	.get_link = ethtool_op_get_link,
 };
 
 static const struct net_device_ops veth_netdev_ops = {
@@ -1605,7 +1591,7 @@ static int veth_probe(struct vio_dev *vd
 	}
 	veth_dev[i] = dev;
 
-	port = (struct veth_port*)netdev_priv(dev);
+	port = netdev_priv(dev);
 
 	/* Start the state machine on each connection on this vlan. If we're
 	 * the first dev to do so this will commence link negotiation */
@@ -1658,15 +1644,14 @@ static void __exit veth_module_cleanup(v
 	/* Disconnect our "irq" to stop events coming from the Hypervisor. */
 	HvLpEvent_unregisterHandler(HvLpEvent_Type_VirtualLan);
 
-	/* Make sure any work queued from Hypervisor callbacks is finished. */
-	flush_scheduled_work();
-
 	for (i = 0; i < HVMAXARCHITECTEDLPS; ++i) {
 		cnx = veth_cnx[i];
 
 		if (!cnx)
 			continue;
 
+		/* Cancel work queued from Hypervisor callbacks */
+		cancel_delayed_work_sync(&cnx->statemachine_wq);
 		/* Remove the connection from sysfs */
 		kobject_del(&cnx->kobject);
 		/* Drop the driver's reference to the connection */
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/ixgb/ixgb_main.c linux-libre-2.6.38-gnu1/drivers/net/ixgb/ixgb_main.c
--- linux-libre-2.6.37-gnu1/drivers/net/ixgb/ixgb_main.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/ixgb/ixgb_main.c	2011-03-14 21:20:32.000000000 -0400
@@ -98,6 +98,8 @@ static void ixgb_alloc_rx_buffers(struct
 static void ixgb_tx_timeout(struct net_device *dev);
 static void ixgb_tx_timeout_task(struct work_struct *work);
 
+static void ixgb_vlan_strip_enable(struct ixgb_adapter *adapter);
+static void ixgb_vlan_strip_disable(struct ixgb_adapter *adapter);
 static void ixgb_vlan_rx_register(struct net_device *netdev,
                                   struct vlan_group *grp);
 static void ixgb_vlan_rx_add_vid(struct net_device *netdev, u16 vid);
@@ -525,7 +527,7 @@ ixgb_remove(struct pci_dev *pdev)
 	struct net_device *netdev = pci_get_drvdata(pdev);
 	struct ixgb_adapter *adapter = netdev_priv(netdev);
 
-	flush_scheduled_work();
+	cancel_work_sync(&adapter->tx_timeout_task);
 
 	unregister_netdev(netdev);
 
@@ -669,13 +671,12 @@ ixgb_setup_tx_resources(struct ixgb_adap
 	int size;
 
 	size = sizeof(struct ixgb_buffer) * txdr->count;
-	txdr->buffer_info = vmalloc(size);
+	txdr->buffer_info = vzalloc(size);
 	if (!txdr->buffer_info) {
 		netif_err(adapter, probe, adapter->netdev,
 			  "Unable to allocate transmit descriptor ring memory\n");
 		return -ENOMEM;
 	}
-	memset(txdr->buffer_info, 0, size);
 
 	/* round up to nearest 4K */
 
@@ -759,13 +760,12 @@ ixgb_setup_rx_resources(struct ixgb_adap
 	int size;
 
 	size = sizeof(struct ixgb_buffer) * rxdr->count;
-	rxdr->buffer_info = vmalloc(size);
+	rxdr->buffer_info = vzalloc(size);
 	if (!rxdr->buffer_info) {
 		netif_err(adapter, probe, adapter->netdev,
 			  "Unable to allocate receive descriptor ring\n");
 		return -ENOMEM;
 	}
-	memset(rxdr->buffer_info, 0, size);
 
 	/* Round up to nearest 4K */
 
@@ -1078,6 +1078,8 @@ ixgb_set_multi(struct net_device *netdev
 
 	if (netdev->flags & IFF_PROMISC) {
 		rctl |= (IXGB_RCTL_UPE | IXGB_RCTL_MPE);
+		/* disable VLAN filtering */
+		rctl &= ~IXGB_RCTL_CFIEN;
 		rctl &= ~IXGB_RCTL_VFE;
 	} else {
 		if (netdev->flags & IFF_ALLMULTI) {
@@ -1086,7 +1088,9 @@ ixgb_set_multi(struct net_device *netdev
 		} else {
 			rctl &= ~(IXGB_RCTL_UPE | IXGB_RCTL_MPE);
 		}
+		/* enable VLAN filtering */
 		rctl |= IXGB_RCTL_VFE;
+		rctl &= ~IXGB_RCTL_CFIEN;
 	}
 
 	if (netdev_mc_count(netdev) > IXGB_MAX_NUM_MULTICAST_ADDRESSES) {
@@ -1105,6 +1109,12 @@ ixgb_set_multi(struct net_device *netdev
 
 		ixgb_mc_addr_list_update(hw, mta, netdev_mc_count(netdev), 0);
 	}
+
+	if (netdev->features & NETIF_F_HW_VLAN_RX)
+		ixgb_vlan_strip_enable(adapter);
+	else
+		ixgb_vlan_strip_disable(adapter);
+
 }
 
 /**
@@ -1252,7 +1262,7 @@ ixgb_tx_csum(struct ixgb_adapter *adapte
 
 	if (likely(skb->ip_summed == CHECKSUM_PARTIAL)) {
 		struct ixgb_buffer *buffer_info;
-		css = skb_transport_offset(skb);
+		css = skb_checksum_start_offset(skb);
 		cso = css + skb->csum_offset;
 
 		i = adapter->tx_ring.next_to_use;
@@ -2152,33 +2162,30 @@ static void
 ixgb_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp)
 {
 	struct ixgb_adapter *adapter = netdev_priv(netdev);
-	u32 ctrl, rctl;
 
-	ixgb_irq_disable(adapter);
 	adapter->vlgrp = grp;
+}
 
-	if (grp) {
-		/* enable VLAN tag insert/strip */
-		ctrl = IXGB_READ_REG(&adapter->hw, CTRL0);
-		ctrl |= IXGB_CTRL0_VME;
-		IXGB_WRITE_REG(&adapter->hw, CTRL0, ctrl);
-
-		/* enable VLAN receive filtering */
+static void
+ixgb_vlan_strip_enable(struct ixgb_adapter *adapter)
+{
+	u32 ctrl;
 
-		rctl = IXGB_READ_REG(&adapter->hw, RCTL);
-		rctl &= ~IXGB_RCTL_CFIEN;
-		IXGB_WRITE_REG(&adapter->hw, RCTL, rctl);
-	} else {
-		/* disable VLAN tag insert/strip */
+	/* enable VLAN tag insert/strip */
+	ctrl = IXGB_READ_REG(&adapter->hw, CTRL0);
+	ctrl |= IXGB_CTRL0_VME;
+	IXGB_WRITE_REG(&adapter->hw, CTRL0, ctrl);
+}
 
-		ctrl = IXGB_READ_REG(&adapter->hw, CTRL0);
-		ctrl &= ~IXGB_CTRL0_VME;
-		IXGB_WRITE_REG(&adapter->hw, CTRL0, ctrl);
-	}
+static void
+ixgb_vlan_strip_disable(struct ixgb_adapter *adapter)
+{
+	u32 ctrl;
 
-	/* don't enable interrupts unless we are UP */
-	if (adapter->netdev->flags & IFF_UP)
-		ixgb_irq_enable(adapter);
+	/* disable VLAN tag insert/strip */
+	ctrl = IXGB_READ_REG(&adapter->hw, CTRL0);
+	ctrl &= ~IXGB_CTRL0_VME;
+	IXGB_WRITE_REG(&adapter->hw, CTRL0, ctrl);
 }
 
 static void
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/ixgb/ixgb_param.c linux-libre-2.6.38-gnu1/drivers/net/ixgb/ixgb_param.c
--- linux-libre-2.6.37-gnu1/drivers/net/ixgb/ixgb_param.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/ixgb/ixgb_param.c	2011-03-14 21:20:32.000000000 -0400
@@ -191,9 +191,9 @@ struct ixgb_option {
 		} r;
 		struct {	/* list_option info */
 			int nr;
-			struct ixgb_opt_list {
+			const struct ixgb_opt_list {
 				int i;
-				char *str;
+				const char *str;
 			} *p;
 		} l;
 	} arg;
@@ -226,7 +226,7 @@ ixgb_validate_option(unsigned int *value
 		break;
 	case list_option: {
 		int i;
-		struct ixgb_opt_list *ent;
+		const struct ixgb_opt_list *ent;
 
 		for (i = 0; i < opt->arg.l.nr; i++) {
 			ent = &opt->arg.l.p[i];
@@ -322,14 +322,15 @@ ixgb_check_options(struct ixgb_adapter *
 	}
 	{ /* Flow Control */
 
-		struct ixgb_opt_list fc_list[] =
-			{{ ixgb_fc_none,	"Flow Control Disabled" },
-			 { ixgb_fc_rx_pause,"Flow Control Receive Only" },
-			 { ixgb_fc_tx_pause,"Flow Control Transmit Only" },
-			 { ixgb_fc_full,	"Flow Control Enabled" },
-			 { ixgb_fc_default, "Flow Control Hardware Default" }};
+		static const struct ixgb_opt_list fc_list[] = {
+		       { ixgb_fc_none, "Flow Control Disabled" },
+		       { ixgb_fc_rx_pause, "Flow Control Receive Only" },
+		       { ixgb_fc_tx_pause, "Flow Control Transmit Only" },
+		       { ixgb_fc_full, "Flow Control Enabled" },
+		       { ixgb_fc_default, "Flow Control Hardware Default" }
+		};
 
-		const struct ixgb_option opt = {
+		static const struct ixgb_option opt = {
 			.type = list_option,
 			.name = "Flow Control",
 			.err  = "reading default settings from EEPROM",
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/ixgbe/ixgbe_82598.c linux-libre-2.6.38-gnu1/drivers/net/ixgbe/ixgbe_82598.c
--- linux-libre-2.6.37-gnu1/drivers/net/ixgbe/ixgbe_82598.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/ixgbe/ixgbe_82598.c	2011-03-14 21:20:32.000000000 -0400
@@ -38,9 +38,6 @@
 #define IXGBE_82598_MC_TBL_SIZE  128
 #define IXGBE_82598_VFT_TBL_SIZE 128
 
-static s32 ixgbe_get_copper_link_capabilities_82598(struct ixgbe_hw *hw,
-                                             ixgbe_link_speed *speed,
-                                             bool *autoneg);
 static s32 ixgbe_setup_copper_link_82598(struct ixgbe_hw *hw,
                                          ixgbe_link_speed speed,
                                          bool autoneg,
@@ -156,7 +153,7 @@ static s32 ixgbe_init_phy_ops_82598(stru
 	if (mac->ops.get_media_type(hw) == ixgbe_media_type_copper) {
 		mac->ops.setup_link = &ixgbe_setup_copper_link_82598;
 		mac->ops.get_link_capabilities =
-		                  &ixgbe_get_copper_link_capabilities_82598;
+			&ixgbe_get_copper_link_capabilities_generic;
 	}
 
 	switch (hw->phy.type) {
@@ -274,37 +271,6 @@ static s32 ixgbe_get_link_capabilities_8
 }
 
 /**
- *  ixgbe_get_copper_link_capabilities_82598 - Determines link capabilities
- *  @hw: pointer to hardware structure
- *  @speed: pointer to link speed
- *  @autoneg: boolean auto-negotiation value
- *
- *  Determines the link capabilities by reading the AUTOC register.
- **/
-static s32 ixgbe_get_copper_link_capabilities_82598(struct ixgbe_hw *hw,
-						    ixgbe_link_speed *speed,
-						    bool *autoneg)
-{
-	s32 status = IXGBE_ERR_LINK_SETUP;
-	u16 speed_ability;
-
-	*speed = 0;
-	*autoneg = true;
-
-	status = hw->phy.ops.read_reg(hw, MDIO_SPEED, MDIO_MMD_PMAPMD,
-	                              &speed_ability);
-
-	if (status == 0) {
-		if (speed_ability & MDIO_SPEED_10G)
-		    *speed |= IXGBE_LINK_SPEED_10GB_FULL;
-		if (speed_ability & MDIO_PMA_SPEED_1000)
-		    *speed |= IXGBE_LINK_SPEED_1GB_FULL;
-	}
-
-	return status;
-}
-
-/**
  *  ixgbe_get_media_type_82598 - Determines media type
  *  @hw: pointer to hardware structure
  *
@@ -357,6 +323,7 @@ static s32 ixgbe_fc_enable_82598(struct
 	u32 fctrl_reg;
 	u32 rmcs_reg;
 	u32 reg;
+	u32 rx_pba_size;
 	u32 link_speed = 0;
 	bool link_up;
 
@@ -459,16 +426,18 @@ static s32 ixgbe_fc_enable_82598(struct
 
 	/* Set up and enable Rx high/low water mark thresholds, enable XON. */
 	if (hw->fc.current_mode & ixgbe_fc_tx_pause) {
-		if (hw->fc.send_xon) {
-			IXGBE_WRITE_REG(hw, IXGBE_FCRTL(packetbuf_num),
-			                (hw->fc.low_water | IXGBE_FCRTL_XONE));
-		} else {
-			IXGBE_WRITE_REG(hw, IXGBE_FCRTL(packetbuf_num),
-			                hw->fc.low_water);
-		}
+		rx_pba_size = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(packetbuf_num));
+		rx_pba_size >>= IXGBE_RXPBSIZE_SHIFT;
 
-		IXGBE_WRITE_REG(hw, IXGBE_FCRTH(packetbuf_num),
-		                (hw->fc.high_water | IXGBE_FCRTH_FCEN));
+		reg = (rx_pba_size - hw->fc.low_water) << 6;
+		if (hw->fc.send_xon)
+			reg |= IXGBE_FCRTL_XONE;
+		IXGBE_WRITE_REG(hw, IXGBE_FCRTL(packetbuf_num), reg);
+
+		reg = (rx_pba_size - hw->fc.high_water) << 10;
+		reg |= IXGBE_FCRTH_FCEN;
+
+		IXGBE_WRITE_REG(hw, IXGBE_FCRTH(packetbuf_num), reg);
 	}
 
 	/* Configure pause time (2 TCs per register) */
@@ -1222,6 +1191,7 @@ static struct ixgbe_mac_operations mac_o
 static struct ixgbe_eeprom_operations eeprom_ops_82598 = {
 	.init_params		= &ixgbe_init_eeprom_params_generic,
 	.read			= &ixgbe_read_eerd_generic,
+	.calc_checksum          = &ixgbe_calc_eeprom_checksum_generic,
 	.validate_checksum	= &ixgbe_validate_eeprom_checksum_generic,
 	.update_checksum	= &ixgbe_update_eeprom_checksum_generic,
 };
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/ixgbe/ixgbe_82599.c linux-libre-2.6.38-gnu1/drivers/net/ixgbe/ixgbe_82599.c
--- linux-libre-2.6.37-gnu1/drivers/net/ixgbe/ixgbe_82599.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/ixgbe/ixgbe_82599.c	2011-03-14 21:20:32.000000000 -0400
@@ -56,9 +56,6 @@ static s32 ixgbe_setup_mac_link_82599(st
                                ixgbe_link_speed speed,
                                bool autoneg,
                                bool autoneg_wait_to_complete);
-static s32 ixgbe_get_copper_link_capabilities_82599(struct ixgbe_hw *hw,
-                                             ixgbe_link_speed *speed,
-                                             bool *autoneg);
 static s32 ixgbe_setup_copper_link_82599(struct ixgbe_hw *hw,
                                          ixgbe_link_speed speed,
                                          bool autoneg,
@@ -68,9 +65,9 @@ static s32 ixgbe_verify_fw_version_82599
 static void ixgbe_init_mac_link_ops_82599(struct ixgbe_hw *hw)
 {
 	struct ixgbe_mac_info *mac = &hw->mac;
-	if (hw->phy.multispeed_fiber) {
-		/* Set up dual speed SFP+ support */
-		mac->ops.setup_link = &ixgbe_setup_mac_link_multispeed_fiber;
+
+	/* enable the laser control functions for SFP+ fiber */
+	if (mac->ops.get_media_type(hw) == ixgbe_media_type_fiber) {
 		mac->ops.disable_tx_laser =
 		                       &ixgbe_disable_tx_laser_multispeed_fiber;
 		mac->ops.enable_tx_laser =
@@ -80,6 +77,12 @@ static void ixgbe_init_mac_link_ops_8259
 		mac->ops.disable_tx_laser = NULL;
 		mac->ops.enable_tx_laser = NULL;
 		mac->ops.flap_tx_laser = NULL;
+	}
+
+	if (hw->phy.multispeed_fiber) {
+		/* Set up dual speed SFP+ support */
+		mac->ops.setup_link = &ixgbe_setup_mac_link_multispeed_fiber;
+	} else {
 		if ((mac->ops.get_media_type(hw) ==
 		     ixgbe_media_type_backplane) &&
 		    (hw->phy.smart_speed == ixgbe_smart_speed_auto ||
@@ -93,6 +96,8 @@ static void ixgbe_init_mac_link_ops_8259
 static s32 ixgbe_setup_sfp_modules_82599(struct ixgbe_hw *hw)
 {
 	s32 ret_val = 0;
+	u32 reg_anlp1 = 0;
+	u32 i = 0;
 	u16 list_offset, data_offset, data_value;
 
 	if (hw->phy.sfp_type != ixgbe_sfp_type_unknown) {
@@ -119,14 +124,34 @@ static s32 ixgbe_setup_sfp_modules_82599
 			IXGBE_WRITE_FLUSH(hw);
 			hw->eeprom.ops.read(hw, ++data_offset, &data_value);
 		}
-		/* Now restart DSP by setting Restart_AN */
-		IXGBE_WRITE_REG(hw, IXGBE_AUTOC,
-		    (IXGBE_READ_REG(hw, IXGBE_AUTOC) | IXGBE_AUTOC_AN_RESTART));
 
 		/* Release the semaphore */
 		ixgbe_release_swfw_sync(hw, IXGBE_GSSR_MAC_CSR_SM);
 		/* Delay obtaining semaphore again to allow FW access */
 		msleep(hw->eeprom.semaphore_delay);
+
+		/* Now restart DSP by setting Restart_AN and clearing LMS */
+		IXGBE_WRITE_REG(hw, IXGBE_AUTOC, ((IXGBE_READ_REG(hw,
+		                IXGBE_AUTOC) & ~IXGBE_AUTOC_LMS_MASK) |
+		                IXGBE_AUTOC_AN_RESTART));
+
+		/* Wait for AN to leave state 0 */
+		for (i = 0; i < 10; i++) {
+			msleep(4);
+			reg_anlp1 = IXGBE_READ_REG(hw, IXGBE_ANLP1);
+			if (reg_anlp1 & IXGBE_ANLP1_AN_STATE_MASK)
+				break;
+		}
+		if (!(reg_anlp1 & IXGBE_ANLP1_AN_STATE_MASK)) {
+			hw_dbg(hw, "sfp module setup not complete\n");
+			ret_val = IXGBE_ERR_SFP_SETUP_NOT_COMPLETE;
+			goto setup_sfp_out;
+		}
+
+		/* Restart DSP by setting Restart_AN and return to SFI mode */
+		IXGBE_WRITE_REG(hw, IXGBE_AUTOC, (IXGBE_READ_REG(hw,
+		                IXGBE_AUTOC) | IXGBE_AUTOC_LMS_10G_SERIAL |
+		                IXGBE_AUTOC_AN_RESTART));
 	}
 
 setup_sfp_out:
@@ -174,7 +199,7 @@ static s32 ixgbe_init_phy_ops_82599(stru
 	if (mac->ops.get_media_type(hw) == ixgbe_media_type_copper) {
 		mac->ops.setup_link = &ixgbe_setup_copper_link_82599;
 		mac->ops.get_link_capabilities =
-		                  &ixgbe_get_copper_link_capabilities_82599;
+			&ixgbe_get_copper_link_capabilities_generic;
 	}
 
 	/* Set necessary function pointers based on phy type */
@@ -184,6 +209,10 @@ static s32 ixgbe_init_phy_ops_82599(stru
 		phy->ops.get_firmware_version =
 		             &ixgbe_get_phy_firmware_version_tnx;
 		break;
+	case ixgbe_phy_aq:
+		phy->ops.get_firmware_version =
+			&ixgbe_get_phy_firmware_version_generic;
+		break;
 	default:
 		break;
 	}
@@ -290,37 +319,6 @@ out:
 }
 
 /**
- *  ixgbe_get_copper_link_capabilities_82599 - Determines link capabilities
- *  @hw: pointer to hardware structure
- *  @speed: pointer to link speed
- *  @autoneg: boolean auto-negotiation value
- *
- *  Determines the link capabilities by reading the AUTOC register.
- **/
-static s32 ixgbe_get_copper_link_capabilities_82599(struct ixgbe_hw *hw,
-                                                    ixgbe_link_speed *speed,
-                                                    bool *autoneg)
-{
-	s32 status = IXGBE_ERR_LINK_SETUP;
-	u16 speed_ability;
-
-	*speed = 0;
-	*autoneg = true;
-
-	status = hw->phy.ops.read_reg(hw, MDIO_SPEED, MDIO_MMD_PMAPMD,
-	                              &speed_ability);
-
-	if (status == 0) {
-		if (speed_ability & MDIO_SPEED_10G)
-		    *speed |= IXGBE_LINK_SPEED_10GB_FULL;
-		if (speed_ability & MDIO_PMA_SPEED_1000)
-		    *speed |= IXGBE_LINK_SPEED_1GB_FULL;
-	}
-
-	return status;
-}
-
-/**
  *  ixgbe_get_media_type_82599 - Get media type
  *  @hw: pointer to hardware structure
  *
@@ -332,7 +330,8 @@ static enum ixgbe_media_type ixgbe_get_m
 
 	/* Detect if there is a copper PHY attached. */
 	if (hw->phy.type == ixgbe_phy_cu_unknown ||
-	    hw->phy.type == ixgbe_phy_tn) {
+	    hw->phy.type == ixgbe_phy_tn ||
+	    hw->phy.type == ixgbe_phy_aq) {
 		media_type = ixgbe_media_type_copper;
 		goto out;
 	}
@@ -342,11 +341,13 @@ static enum ixgbe_media_type ixgbe_get_m
 	case IXGBE_DEV_ID_82599_KX4_MEZZ:
 	case IXGBE_DEV_ID_82599_COMBO_BACKPLANE:
 	case IXGBE_DEV_ID_82599_KR:
+	case IXGBE_DEV_ID_82599_BACKPLANE_FCOE:
 	case IXGBE_DEV_ID_82599_XAUI_LOM:
 		/* Default device ID is mezzanine card KX/KX4 */
 		media_type = ixgbe_media_type_backplane;
 		break;
 	case IXGBE_DEV_ID_82599_SFP:
+	case IXGBE_DEV_ID_82599_SFP_FCOE:
 	case IXGBE_DEV_ID_82599_SFP_EM:
 		media_type = ixgbe_media_type_fiber;
 		break;
@@ -1002,7 +1003,7 @@ s32 ixgbe_reinit_fdir_tables_82599(struc
 		udelay(10);
 	}
 	if (i >= IXGBE_FDIRCMD_CMD_POLL) {
-		hw_dbg(hw ,"Flow Director previous command isn't complete, "
+		hw_dbg(hw, "Flow Director previous command isn't complete, "
 		       "aborting table re-initialization.\n");
 		return IXGBE_ERR_FDIR_REINIT_FAILED;
 	}
@@ -1078,7 +1079,7 @@ s32 ixgbe_init_fdir_signature_82599(stru
 
 	/*
 	 * The defaults in the HW for RX PB 1-7 are not zero and so should be
-	 * intialized to zero for non DCB mode otherwise actual total RX PB
+	 * initialized to zero for non DCB mode otherwise actual total RX PB
 	 * would be bigger than programmed and filter space would run into
 	 * the PB 0 region.
 	 */
@@ -1112,13 +1113,10 @@ s32 ixgbe_init_fdir_signature_82599(stru
 	/* Move the flexible bytes to use the ethertype - shift 6 words */
 	fdirctrl |= (0x6 << IXGBE_FDIRCTRL_FLEX_SHIFT);
 
-	fdirctrl |= IXGBE_FDIRCTRL_REPORT_STATUS;
 
 	/* Prime the keys for hashing */
-	IXGBE_WRITE_REG(hw, IXGBE_FDIRHKEY,
-	                htonl(IXGBE_ATR_BUCKET_HASH_KEY));
-	IXGBE_WRITE_REG(hw, IXGBE_FDIRSKEY,
-	                htonl(IXGBE_ATR_SIGNATURE_HASH_KEY));
+	IXGBE_WRITE_REG(hw, IXGBE_FDIRHKEY, IXGBE_ATR_BUCKET_HASH_KEY);
+	IXGBE_WRITE_REG(hw, IXGBE_FDIRSKEY, IXGBE_ATR_SIGNATURE_HASH_KEY);
 
 	/*
 	 * Poll init-done after we write the register.  Estimated times:
@@ -1169,7 +1167,7 @@ s32 ixgbe_init_fdir_perfect_82599(struct
 
 	/*
 	 * The defaults in the HW for RX PB 1-7 are not zero and so should be
-	 * intialized to zero for non DCB mode otherwise actual total RX PB
+	 * initialized to zero for non DCB mode otherwise actual total RX PB
 	 * would be bigger than programmed and filter space would run into
 	 * the PB 0 region.
 	 */
@@ -1208,10 +1206,8 @@ s32 ixgbe_init_fdir_perfect_82599(struct
 	fdirctrl |= (0x6 << IXGBE_FDIRCTRL_FLEX_SHIFT);
 
 	/* Prime the keys for hashing */
-	IXGBE_WRITE_REG(hw, IXGBE_FDIRHKEY,
-	                htonl(IXGBE_ATR_BUCKET_HASH_KEY));
-	IXGBE_WRITE_REG(hw, IXGBE_FDIRSKEY,
-	                htonl(IXGBE_ATR_SIGNATURE_HASH_KEY));
+	IXGBE_WRITE_REG(hw, IXGBE_FDIRHKEY, IXGBE_ATR_BUCKET_HASH_KEY);
+	IXGBE_WRITE_REG(hw, IXGBE_FDIRSKEY, IXGBE_ATR_SIGNATURE_HASH_KEY);
 
 	/*
 	 * Poll init-done after we write the register.  Estimated times:
@@ -1250,8 +1246,8 @@ s32 ixgbe_init_fdir_perfect_82599(struct
  *  @stream: input bitstream to compute the hash on
  *  @key: 32-bit hash key
  **/
-static u16 ixgbe_atr_compute_hash_82599(struct ixgbe_atr_input *atr_input,
-                                        u32 key)
+static u32 ixgbe_atr_compute_hash_82599(union ixgbe_atr_input *atr_input,
+					u32 key)
 {
 	/*
 	 * The algorithm is as follows:
@@ -1271,410 +1267,250 @@ static u16 ixgbe_atr_compute_hash_82599(
 	 *    To simplify for programming, the algorithm is implemented
 	 *    in software this way:
 	 *
-	 *    Key[31:0], Stream[335:0]
+	 *    key[31:0], hi_hash_dword[31:0], lo_hash_dword[31:0], hash[15:0]
 	 *
-	 *    tmp_key[11 * 32 - 1:0] = 11{Key[31:0] = key concatenated 11 times
-	 *    int_key[350:0] = tmp_key[351:1]
-	 *    int_stream[365:0] = Stream[14:0] | Stream[335:0] | Stream[335:321]
+	 *    for (i = 0; i < 352; i+=32)
+	 *        hi_hash_dword[31:0] ^= Stream[(i+31):i];
 	 *
-	 *    hash[15:0] = 0;
-	 *    for (i = 0; i < 351; i++) {
-	 *        if (int_key[i])
-	 *            hash ^= int_stream[(i + 15):i];
+	 *    lo_hash_dword[15:0]  ^= Stream[15:0];
+	 *    lo_hash_dword[15:0]  ^= hi_hash_dword[31:16];
+	 *    lo_hash_dword[31:16] ^= hi_hash_dword[15:0];
+	 *
+	 *    hi_hash_dword[31:0]  ^= Stream[351:320];
+	 *
+	 *    if(key[0])
+	 *        hash[15:0] ^= Stream[15:0];
+	 *
+	 *    for (i = 0; i < 16; i++) {
+	 *        if (key[i])
+	 *            hash[15:0] ^= lo_hash_dword[(i+15):i];
+	 *        if (key[i + 16])
+	 *            hash[15:0] ^= hi_hash_dword[(i+15):i];
 	 *    }
+	 *
 	 */
+	__be32 common_hash_dword = 0;
+	u32 hi_hash_dword, lo_hash_dword, flow_vm_vlan;
+	u32 hash_result = 0;
+	u8 i;
 
-	union {
-		u64    fill[6];
-		u32    key[11];
-		u8     key_stream[44];
-	} tmp_key;
-
-	u8   *stream = (u8 *)atr_input;
-	u8   int_key[44];      /* upper-most bit unused */
-	u8   hash_str[46];     /* upper-most 2 bits unused */
-	u16  hash_result = 0;
-	int  i, j, k, h;
+	/* record the flow_vm_vlan bits as they are a key part to the hash */
+	flow_vm_vlan = ntohl(atr_input->dword_stream[0]);
 
-	/*
-	 * Initialize the fill member to prevent warnings
-	 * on some compilers
-	 */
-	 tmp_key.fill[0] = 0;
+	/* generate common hash dword */
+	for (i = 10; i; i -= 2)
+		common_hash_dword ^= atr_input->dword_stream[i] ^
+				     atr_input->dword_stream[i - 1];
 
-	/* First load the temporary key stream */
-	for (i = 0; i < 6; i++) {
-		u64 fillkey = ((u64)key << 32) | key;
-		tmp_key.fill[i] = fillkey;
-	}
+	hi_hash_dword = ntohl(common_hash_dword);
 
-	/*
-	 * Set the interim key for the hashing.  Bit 352 is unused, so we must
-	 * shift and compensate when building the key.
-	 */
+	/* low dword is word swapped version of common */
+	lo_hash_dword = (hi_hash_dword >> 16) | (hi_hash_dword << 16);
 
-	int_key[0] = tmp_key.key_stream[0] >> 1;
-	for (i = 1, j = 0; i < 44; i++) {
-		unsigned int this_key = tmp_key.key_stream[j] << 7;
-		j++;
-		int_key[i] = (u8)(this_key | (tmp_key.key_stream[j] >> 1));
-	}
+	/* apply flow ID/VM pool/VLAN ID bits to hash words */
+	hi_hash_dword ^= flow_vm_vlan ^ (flow_vm_vlan >> 16);
 
-	/*
-	 * Set the interim bit string for the hashing.  Bits 368 and 367 are
-	 * unused, so shift and compensate when building the string.
-	 */
-	hash_str[0] = (stream[40] & 0x7f) >> 1;
-	for (i = 1, j = 40; i < 46; i++) {
-		unsigned int this_str = stream[j] << 7;
-		j++;
-		if (j > 41)
-			j = 0;
-		hash_str[i] = (u8)(this_str | (stream[j] >> 1));
-	}
+	/* Process bits 0 and 16 */
+	if (key & 0x0001) hash_result ^= lo_hash_dword;
+	if (key & 0x00010000) hash_result ^= hi_hash_dword;
 
 	/*
-	 * Now compute the hash.  i is the index into hash_str, j is into our
-	 * key stream, k is counting the number of bits, and h interates within
-	 * each byte.
+	 * apply flow ID/VM pool/VLAN ID bits to lo hash dword, we had to
+	 * delay this because bit 0 of the stream should not be processed
+	 * so we do not add the vlan until after bit 0 was processed
 	 */
-	for (i = 45, j = 43, k = 0; k < 351 && i >= 2 && j >= 0; i--, j--) {
-		for (h = 0; h < 8 && k < 351; h++, k++) {
-			if (int_key[j] & (1 << h)) {
-				/*
-				 * Key bit is set, XOR in the current 16-bit
-				 * string.  Example of processing:
-				 *    h = 0,
-				 *      tmp = (hash_str[i - 2] & 0 << 16) |
-				 *            (hash_str[i - 1] & 0xff << 8) |
-				 *            (hash_str[i] & 0xff >> 0)
-				 *      So tmp = hash_str[15 + k:k], since the
-				 *      i + 2 clause rolls off the 16-bit value
-				 *    h = 7,
-				 *      tmp = (hash_str[i - 2] & 0x7f << 9) |
-				 *            (hash_str[i - 1] & 0xff << 1) |
-				 *            (hash_str[i] & 0x80 >> 7)
-				 */
-				int tmp = (hash_str[i] >> h);
-				tmp |= (hash_str[i - 1] << (8 - h));
-				tmp |= (int)(hash_str[i - 2] & ((1 << h) - 1))
-				             << (16 - h);
-				hash_result ^= (u16)tmp;
-			}
-		}
-	}
-
-	return hash_result;
-}
-
-/**
- *  ixgbe_atr_set_vlan_id_82599 - Sets the VLAN id in the ATR input stream
- *  @input: input stream to modify
- *  @vlan: the VLAN id to load
- **/
-s32 ixgbe_atr_set_vlan_id_82599(struct ixgbe_atr_input *input, u16 vlan)
-{
-	input->byte_stream[IXGBE_ATR_VLAN_OFFSET + 1] = vlan >> 8;
-	input->byte_stream[IXGBE_ATR_VLAN_OFFSET] = vlan & 0xff;
-
-	return 0;
-}
-
-/**
- *  ixgbe_atr_set_src_ipv4_82599 - Sets the source IPv4 address
- *  @input: input stream to modify
- *  @src_addr: the IP address to load
- **/
-s32 ixgbe_atr_set_src_ipv4_82599(struct ixgbe_atr_input *input, u32 src_addr)
-{
-	input->byte_stream[IXGBE_ATR_SRC_IPV4_OFFSET + 3] = src_addr >> 24;
-	input->byte_stream[IXGBE_ATR_SRC_IPV4_OFFSET + 2] =
-	                                               (src_addr >> 16) & 0xff;
-	input->byte_stream[IXGBE_ATR_SRC_IPV4_OFFSET + 1] =
-	                                                (src_addr >> 8) & 0xff;
-	input->byte_stream[IXGBE_ATR_SRC_IPV4_OFFSET] = src_addr & 0xff;
-
-	return 0;
-}
-
-/**
- *  ixgbe_atr_set_dst_ipv4_82599 - Sets the destination IPv4 address
- *  @input: input stream to modify
- *  @dst_addr: the IP address to load
- **/
-s32 ixgbe_atr_set_dst_ipv4_82599(struct ixgbe_atr_input *input, u32 dst_addr)
-{
-	input->byte_stream[IXGBE_ATR_DST_IPV4_OFFSET + 3] = dst_addr >> 24;
-	input->byte_stream[IXGBE_ATR_DST_IPV4_OFFSET + 2] =
-	                                               (dst_addr >> 16) & 0xff;
-	input->byte_stream[IXGBE_ATR_DST_IPV4_OFFSET + 1] =
-	                                                (dst_addr >> 8) & 0xff;
-	input->byte_stream[IXGBE_ATR_DST_IPV4_OFFSET] = dst_addr & 0xff;
-
-	return 0;
-}
-
-/**
- *  ixgbe_atr_set_src_port_82599 - Sets the source port
- *  @input: input stream to modify
- *  @src_port: the source port to load
- **/
-s32 ixgbe_atr_set_src_port_82599(struct ixgbe_atr_input *input, u16 src_port)
-{
-	input->byte_stream[IXGBE_ATR_SRC_PORT_OFFSET + 1] = src_port >> 8;
-	input->byte_stream[IXGBE_ATR_SRC_PORT_OFFSET] = src_port & 0xff;
-
-	return 0;
-}
-
-/**
- *  ixgbe_atr_set_dst_port_82599 - Sets the destination port
- *  @input: input stream to modify
- *  @dst_port: the destination port to load
- **/
-s32 ixgbe_atr_set_dst_port_82599(struct ixgbe_atr_input *input, u16 dst_port)
-{
-	input->byte_stream[IXGBE_ATR_DST_PORT_OFFSET + 1] = dst_port >> 8;
-	input->byte_stream[IXGBE_ATR_DST_PORT_OFFSET] = dst_port & 0xff;
-
-	return 0;
-}
-
-/**
- *  ixgbe_atr_set_flex_byte_82599 - Sets the flexible bytes
- *  @input: input stream to modify
- *  @flex_bytes: the flexible bytes to load
- **/
-s32 ixgbe_atr_set_flex_byte_82599(struct ixgbe_atr_input *input, u16 flex_byte)
-{
-	input->byte_stream[IXGBE_ATR_FLEX_BYTE_OFFSET + 1] = flex_byte >> 8;
-	input->byte_stream[IXGBE_ATR_FLEX_BYTE_OFFSET] = flex_byte & 0xff;
-
-	return 0;
-}
-
-/**
- *  ixgbe_atr_set_l4type_82599 - Sets the layer 4 packet type
- *  @input: input stream to modify
- *  @l4type: the layer 4 type value to load
- **/
-s32 ixgbe_atr_set_l4type_82599(struct ixgbe_atr_input *input, u8 l4type)
-{
-	input->byte_stream[IXGBE_ATR_L4TYPE_OFFSET] = l4type;
-
-	return 0;
-}
-
-/**
- *  ixgbe_atr_get_vlan_id_82599 - Gets the VLAN id from the ATR input stream
- *  @input: input stream to search
- *  @vlan: the VLAN id to load
- **/
-static s32 ixgbe_atr_get_vlan_id_82599(struct ixgbe_atr_input *input, u16 *vlan)
-{
-	*vlan = input->byte_stream[IXGBE_ATR_VLAN_OFFSET];
-	*vlan |= input->byte_stream[IXGBE_ATR_VLAN_OFFSET + 1] << 8;
+	lo_hash_dword ^= flow_vm_vlan ^ (flow_vm_vlan << 16);
 
-	return 0;
-}
 
-/**
- *  ixgbe_atr_get_src_ipv4_82599 - Gets the source IPv4 address
- *  @input: input stream to search
- *  @src_addr: the IP address to load
- **/
-static s32 ixgbe_atr_get_src_ipv4_82599(struct ixgbe_atr_input *input,
-                                        u32 *src_addr)
-{
-	*src_addr = input->byte_stream[IXGBE_ATR_SRC_IPV4_OFFSET];
-	*src_addr |= input->byte_stream[IXGBE_ATR_SRC_IPV4_OFFSET + 1] << 8;
-	*src_addr |= input->byte_stream[IXGBE_ATR_SRC_IPV4_OFFSET + 2] << 16;
-	*src_addr |= input->byte_stream[IXGBE_ATR_SRC_IPV4_OFFSET + 3] << 24;
+	/* process the remaining 30 bits in the key 2 bits at a time */
+	for (i = 15; i; i-- ) {
+		if (key & (0x0001 << i)) hash_result ^= lo_hash_dword >> i;
+		if (key & (0x00010000 << i)) hash_result ^= hi_hash_dword >> i;
+	}
 
-	return 0;
+	return hash_result & IXGBE_ATR_HASH_MASK;
 }
 
-/**
- *  ixgbe_atr_get_dst_ipv4_82599 - Gets the destination IPv4 address
- *  @input: input stream to search
- *  @dst_addr: the IP address to load
- **/
-static s32 ixgbe_atr_get_dst_ipv4_82599(struct ixgbe_atr_input *input,
-                                        u32 *dst_addr)
-{
-	*dst_addr = input->byte_stream[IXGBE_ATR_DST_IPV4_OFFSET];
-	*dst_addr |= input->byte_stream[IXGBE_ATR_DST_IPV4_OFFSET + 1] << 8;
-	*dst_addr |= input->byte_stream[IXGBE_ATR_DST_IPV4_OFFSET + 2] << 16;
-	*dst_addr |= input->byte_stream[IXGBE_ATR_DST_IPV4_OFFSET + 3] << 24;
-
-	return 0;
-}
+/*
+ * These defines allow us to quickly generate all of the necessary instructions
+ * in the function below by simply calling out IXGBE_COMPUTE_SIG_HASH_ITERATION
+ * for values 0 through 15
+ */
+#define IXGBE_ATR_COMMON_HASH_KEY \
+		(IXGBE_ATR_BUCKET_HASH_KEY & IXGBE_ATR_SIGNATURE_HASH_KEY)
+#define IXGBE_COMPUTE_SIG_HASH_ITERATION(_n) \
+do { \
+	u32 n = (_n); \
+	if (IXGBE_ATR_COMMON_HASH_KEY & (0x01 << n)) \
+		common_hash ^= lo_hash_dword >> n; \
+	else if (IXGBE_ATR_BUCKET_HASH_KEY & (0x01 << n)) \
+		bucket_hash ^= lo_hash_dword >> n; \
+	else if (IXGBE_ATR_SIGNATURE_HASH_KEY & (0x01 << n)) \
+		sig_hash ^= lo_hash_dword << (16 - n); \
+	if (IXGBE_ATR_COMMON_HASH_KEY & (0x01 << (n + 16))) \
+		common_hash ^= hi_hash_dword >> n; \
+	else if (IXGBE_ATR_BUCKET_HASH_KEY & (0x01 << (n + 16))) \
+		bucket_hash ^= hi_hash_dword >> n; \
+	else if (IXGBE_ATR_SIGNATURE_HASH_KEY & (0x01 << (n + 16))) \
+		sig_hash ^= hi_hash_dword << (16 - n); \
+} while (0);
 
 /**
- *  ixgbe_atr_get_src_ipv6_82599 - Gets the source IPv6 address
- *  @input: input stream to search
- *  @src_addr_1: the first 4 bytes of the IP address to load
- *  @src_addr_2: the second 4 bytes of the IP address to load
- *  @src_addr_3: the third 4 bytes of the IP address to load
- *  @src_addr_4: the fourth 4 bytes of the IP address to load
+ *  ixgbe_atr_compute_sig_hash_82599 - Compute the signature hash
+ *  @stream: input bitstream to compute the hash on
+ *
+ *  This function is almost identical to the function above but contains
+ *  several optomizations such as unwinding all of the loops, letting the
+ *  compiler work out all of the conditional ifs since the keys are static
+ *  defines, and computing two keys at once since the hashed dword stream
+ *  will be the same for both keys.
  **/
-static s32 ixgbe_atr_get_src_ipv6_82599(struct ixgbe_atr_input *input,
-                                        u32 *src_addr_1, u32 *src_addr_2,
-                                        u32 *src_addr_3, u32 *src_addr_4)
+static u32 ixgbe_atr_compute_sig_hash_82599(union ixgbe_atr_hash_dword input,
+					    union ixgbe_atr_hash_dword common)
 {
-	*src_addr_1 = input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 12];
-	*src_addr_1 = input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 13] << 8;
-	*src_addr_1 = input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 14] << 16;
-	*src_addr_1 = input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 15] << 24;
-
-	*src_addr_2 = input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 8];
-	*src_addr_2 = input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 9] << 8;
-	*src_addr_2 = input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 10] << 16;
-	*src_addr_2 = input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 11] << 24;
-
-	*src_addr_3 = input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 4];
-	*src_addr_3 = input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 5] << 8;
-	*src_addr_3 = input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 6] << 16;
-	*src_addr_3 = input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 7] << 24;
+	u32 hi_hash_dword, lo_hash_dword, flow_vm_vlan;
+	u32 sig_hash = 0, bucket_hash = 0, common_hash = 0;
 
-	*src_addr_4 = input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET];
-	*src_addr_4 = input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 1] << 8;
-	*src_addr_4 = input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 2] << 16;
-	*src_addr_4 = input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 3] << 24;
+	/* record the flow_vm_vlan bits as they are a key part to the hash */
+	flow_vm_vlan = ntohl(input.dword);
 
-	return 0;
-}
+	/* generate common hash dword */
+	hi_hash_dword = ntohl(common.dword);
 
-/**
- *  ixgbe_atr_get_src_port_82599 - Gets the source port
- *  @input: input stream to modify
- *  @src_port: the source port to load
- *
- *  Even though the input is given in big-endian, the FDIRPORT registers
- *  expect the ports to be programmed in little-endian.  Hence the need to swap
- *  endianness when retrieving the data.  This can be confusing since the
- *  internal hash engine expects it to be big-endian.
- **/
-static s32 ixgbe_atr_get_src_port_82599(struct ixgbe_atr_input *input,
-                                        u16 *src_port)
-{
-	*src_port = input->byte_stream[IXGBE_ATR_SRC_PORT_OFFSET] << 8;
-	*src_port |= input->byte_stream[IXGBE_ATR_SRC_PORT_OFFSET + 1];
+	/* low dword is word swapped version of common */
+	lo_hash_dword = (hi_hash_dword >> 16) | (hi_hash_dword << 16);
 
-	return 0;
-}
+	/* apply flow ID/VM pool/VLAN ID bits to hash words */
+	hi_hash_dword ^= flow_vm_vlan ^ (flow_vm_vlan >> 16);
 
-/**
- *  ixgbe_atr_get_dst_port_82599 - Gets the destination port
- *  @input: input stream to modify
- *  @dst_port: the destination port to load
- *
- *  Even though the input is given in big-endian, the FDIRPORT registers
- *  expect the ports to be programmed in little-endian.  Hence the need to swap
- *  endianness when retrieving the data.  This can be confusing since the
- *  internal hash engine expects it to be big-endian.
- **/
-static s32 ixgbe_atr_get_dst_port_82599(struct ixgbe_atr_input *input,
-                                        u16 *dst_port)
-{
-	*dst_port = input->byte_stream[IXGBE_ATR_DST_PORT_OFFSET] << 8;
-	*dst_port |= input->byte_stream[IXGBE_ATR_DST_PORT_OFFSET + 1];
+	/* Process bits 0 and 16 */
+	IXGBE_COMPUTE_SIG_HASH_ITERATION(0);
 
-	return 0;
-}
+	/*
+	 * apply flow ID/VM pool/VLAN ID bits to lo hash dword, we had to
+	 * delay this because bit 0 of the stream should not be processed
+	 * so we do not add the vlan until after bit 0 was processed
+	 */
+	lo_hash_dword ^= flow_vm_vlan ^ (flow_vm_vlan << 16);
 
-/**
- *  ixgbe_atr_get_flex_byte_82599 - Gets the flexible bytes
- *  @input: input stream to modify
- *  @flex_bytes: the flexible bytes to load
- **/
-static s32 ixgbe_atr_get_flex_byte_82599(struct ixgbe_atr_input *input,
-                                         u16 *flex_byte)
-{
-	*flex_byte = input->byte_stream[IXGBE_ATR_FLEX_BYTE_OFFSET];
-	*flex_byte |= input->byte_stream[IXGBE_ATR_FLEX_BYTE_OFFSET + 1] << 8;
+	/* Process remaining 30 bit of the key */
+	IXGBE_COMPUTE_SIG_HASH_ITERATION(1);
+	IXGBE_COMPUTE_SIG_HASH_ITERATION(2);
+	IXGBE_COMPUTE_SIG_HASH_ITERATION(3);
+	IXGBE_COMPUTE_SIG_HASH_ITERATION(4);
+	IXGBE_COMPUTE_SIG_HASH_ITERATION(5);
+	IXGBE_COMPUTE_SIG_HASH_ITERATION(6);
+	IXGBE_COMPUTE_SIG_HASH_ITERATION(7);
+	IXGBE_COMPUTE_SIG_HASH_ITERATION(8);
+	IXGBE_COMPUTE_SIG_HASH_ITERATION(9);
+	IXGBE_COMPUTE_SIG_HASH_ITERATION(10);
+	IXGBE_COMPUTE_SIG_HASH_ITERATION(11);
+	IXGBE_COMPUTE_SIG_HASH_ITERATION(12);
+	IXGBE_COMPUTE_SIG_HASH_ITERATION(13);
+	IXGBE_COMPUTE_SIG_HASH_ITERATION(14);
+	IXGBE_COMPUTE_SIG_HASH_ITERATION(15);
 
-	return 0;
-}
+	/* combine common_hash result with signature and bucket hashes */
+	bucket_hash ^= common_hash;
+	bucket_hash &= IXGBE_ATR_HASH_MASK;
 
-/**
- *  ixgbe_atr_get_l4type_82599 - Gets the layer 4 packet type
- *  @input: input stream to modify
- *  @l4type: the layer 4 type value to load
- **/
-static s32 ixgbe_atr_get_l4type_82599(struct ixgbe_atr_input *input,
-                                      u8 *l4type)
-{
-	*l4type = input->byte_stream[IXGBE_ATR_L4TYPE_OFFSET];
+	sig_hash ^= common_hash << 16;
+	sig_hash &= IXGBE_ATR_HASH_MASK << 16;
 
-	return 0;
+	/* return completed signature hash */
+	return sig_hash ^ bucket_hash;
 }
 
 /**
  *  ixgbe_atr_add_signature_filter_82599 - Adds a signature hash filter
  *  @hw: pointer to hardware structure
- *  @stream: input bitstream
+ *  @input: unique input dword
+ *  @common: compressed common input dword
  *  @queue: queue index to direct traffic to
  **/
 s32 ixgbe_fdir_add_signature_filter_82599(struct ixgbe_hw *hw,
-                                          struct ixgbe_atr_input *input,
+                                          union ixgbe_atr_hash_dword input,
+                                          union ixgbe_atr_hash_dword common,
                                           u8 queue)
 {
 	u64  fdirhashcmd;
-	u64  fdircmd;
-	u32  fdirhash;
-	u16  bucket_hash, sig_hash;
-	u8   l4type;
-
-	bucket_hash = ixgbe_atr_compute_hash_82599(input,
-	                                           IXGBE_ATR_BUCKET_HASH_KEY);
-
-	/* bucket_hash is only 15 bits */
-	bucket_hash &= IXGBE_ATR_HASH_MASK;
-
-	sig_hash = ixgbe_atr_compute_hash_82599(input,
-	                                        IXGBE_ATR_SIGNATURE_HASH_KEY);
-
-	/* Get the l4type in order to program FDIRCMD properly */
-	/* lowest 2 bits are FDIRCMD.L4TYPE, third lowest bit is FDIRCMD.IPV6 */
-	ixgbe_atr_get_l4type_82599(input, &l4type);
+	u32  fdircmd;
 
 	/*
-	 * The lower 32-bits of fdirhashcmd is for FDIRHASH, the upper 32-bits
-	 * is for FDIRCMD.  Then do a 64-bit register write from FDIRHASH.
+	 * Get the flow_type in order to program FDIRCMD properly
+	 * lowest 2 bits are FDIRCMD.L4TYPE, third lowest bit is FDIRCMD.IPV6
 	 */
-	fdirhash = sig_hash << IXGBE_FDIRHASH_SIG_SW_INDEX_SHIFT | bucket_hash;
-
-	fdircmd = (IXGBE_FDIRCMD_CMD_ADD_FLOW | IXGBE_FDIRCMD_FILTER_UPDATE |
-	           IXGBE_FDIRCMD_LAST | IXGBE_FDIRCMD_QUEUE_EN);
-
-	switch (l4type & IXGBE_ATR_L4TYPE_MASK) {
-	case IXGBE_ATR_L4TYPE_TCP:
-		fdircmd |= IXGBE_FDIRCMD_L4TYPE_TCP;
-		break;
-	case IXGBE_ATR_L4TYPE_UDP:
-		fdircmd |= IXGBE_FDIRCMD_L4TYPE_UDP;
-		break;
-	case IXGBE_ATR_L4TYPE_SCTP:
-		fdircmd |= IXGBE_FDIRCMD_L4TYPE_SCTP;
+	switch (input.formatted.flow_type) {
+	case IXGBE_ATR_FLOW_TYPE_TCPV4:
+	case IXGBE_ATR_FLOW_TYPE_UDPV4:
+	case IXGBE_ATR_FLOW_TYPE_SCTPV4:
+	case IXGBE_ATR_FLOW_TYPE_TCPV6:
+	case IXGBE_ATR_FLOW_TYPE_UDPV6:
+	case IXGBE_ATR_FLOW_TYPE_SCTPV6:
 		break;
 	default:
-		hw_dbg(hw, "Error on l4type input\n");
+		hw_dbg(hw, " Error on flow type input\n");
 		return IXGBE_ERR_CONFIG;
 	}
 
-	if (l4type & IXGBE_ATR_L4TYPE_IPV6_MASK)
-		fdircmd |= IXGBE_FDIRCMD_IPV6;
+	/* configure FDIRCMD register */
+	fdircmd = IXGBE_FDIRCMD_CMD_ADD_FLOW | IXGBE_FDIRCMD_FILTER_UPDATE |
+	          IXGBE_FDIRCMD_LAST | IXGBE_FDIRCMD_QUEUE_EN;
+	fdircmd |= input.formatted.flow_type << IXGBE_FDIRCMD_FLOW_TYPE_SHIFT;
+	fdircmd |= (u32)queue << IXGBE_FDIRCMD_RX_QUEUE_SHIFT;
 
-	fdircmd |= ((u64)queue << IXGBE_FDIRCMD_RX_QUEUE_SHIFT);
-	fdirhashcmd = ((fdircmd << 32) | fdirhash);
+	/*
+	 * The lower 32-bits of fdirhashcmd is for FDIRHASH, the upper 32-bits
+	 * is for FDIRCMD.  Then do a 64-bit register write from FDIRHASH.
+	 */
+	fdirhashcmd = (u64)fdircmd << 32;
+	fdirhashcmd |= ixgbe_atr_compute_sig_hash_82599(input, common);
 
 	IXGBE_WRITE_REG64(hw, IXGBE_FDIRHASH, fdirhashcmd);
 
+	hw_dbg(hw, "Tx Queue=%x hash=%x\n", queue, (u32)fdirhashcmd);
+
 	return 0;
 }
 
 /**
+ *  ixgbe_get_fdirtcpm_82599 - generate a tcp port from atr_input_masks
+ *  @input_mask: mask to be bit swapped
+ *
+ *  The source and destination port masks for flow director are bit swapped
+ *  in that bit 15 effects bit 0, 14 effects 1, 13, 2 etc.  In order to
+ *  generate a correctly swapped value we need to bit swap the mask and that
+ *  is what is accomplished by this function.
+ **/
+static u32 ixgbe_get_fdirtcpm_82599(struct ixgbe_atr_input_masks *input_masks)
+{
+	u32 mask = ntohs(input_masks->dst_port_mask);
+	mask <<= IXGBE_FDIRTCPM_DPORTM_SHIFT;
+	mask |= ntohs(input_masks->src_port_mask);
+	mask = ((mask & 0x55555555) << 1) | ((mask & 0xAAAAAAAA) >> 1);
+	mask = ((mask & 0x33333333) << 2) | ((mask & 0xCCCCCCCC) >> 2);
+	mask = ((mask & 0x0F0F0F0F) << 4) | ((mask & 0xF0F0F0F0) >> 4);
+	return ((mask & 0x00FF00FF) << 8) | ((mask & 0xFF00FF00) >> 8);
+}
+
+/*
+ * These two macros are meant to address the fact that we have registers
+ * that are either all or in part big-endian.  As a result on big-endian
+ * systems we will end up byte swapping the value to little-endian before
+ * it is byte swapped again and written to the hardware in the original
+ * big-endian format.
+ */
+#define IXGBE_STORE_AS_BE32(_value) \
+	(((u32)(_value) >> 24) | (((u32)(_value) & 0x00FF0000) >> 8) | \
+	 (((u32)(_value) & 0x0000FF00) << 8) | ((u32)(_value) << 24))
+
+#define IXGBE_WRITE_REG_BE32(a, reg, value) \
+	IXGBE_WRITE_REG((a), (reg), IXGBE_STORE_AS_BE32(ntohl(value)))
+
+#define IXGBE_STORE_AS_BE16(_value) \
+	(((u16)(_value) >> 8) | ((u16)(_value) << 8))
+
+/**
  *  ixgbe_fdir_add_perfect_filter_82599 - Adds a perfect filter
  *  @hw: pointer to hardware structure
  *  @input: input bitstream
@@ -1686,135 +1522,139 @@ s32 ixgbe_fdir_add_signature_filter_8259
  *  hardware writes must be protected from one another.
  **/
 s32 ixgbe_fdir_add_perfect_filter_82599(struct ixgbe_hw *hw,
-                                      struct ixgbe_atr_input *input,
+                                      union ixgbe_atr_input *input,
                                       struct ixgbe_atr_input_masks *input_masks,
                                       u16 soft_id, u8 queue)
 {
-	u32 fdircmd = 0;
 	u32 fdirhash;
-	u32 src_ipv4 = 0, dst_ipv4 = 0;
-	u32 src_ipv6_1, src_ipv6_2, src_ipv6_3, src_ipv6_4;
-	u16 src_port, dst_port, vlan_id, flex_bytes;
-	u16 bucket_hash;
-	u8  l4type;
-	u8  fdirm = 0;
-
-	/* Get our input values */
-	ixgbe_atr_get_l4type_82599(input, &l4type);
+	u32 fdircmd;
+	u32 fdirport, fdirtcpm;
+	u32 fdirvlan;
+	/* start with VLAN, flex bytes, VM pool, and IPv6 destination masked */
+	u32 fdirm = IXGBE_FDIRM_VLANID | IXGBE_FDIRM_VLANP | IXGBE_FDIRM_FLEX |
+		    IXGBE_FDIRM_POOL | IXGBE_FDIRM_DIPv6;
 
 	/*
-	 * Check l4type formatting, and bail out before we touch the hardware
+	 * Check flow_type formatting, and bail out before we touch the hardware
 	 * if there's a configuration issue
 	 */
-	switch (l4type & IXGBE_ATR_L4TYPE_MASK) {
-	case IXGBE_ATR_L4TYPE_TCP:
-		fdircmd |= IXGBE_FDIRCMD_L4TYPE_TCP;
-		break;
-	case IXGBE_ATR_L4TYPE_UDP:
-		fdircmd |= IXGBE_FDIRCMD_L4TYPE_UDP;
-		break;
-	case IXGBE_ATR_L4TYPE_SCTP:
-		fdircmd |= IXGBE_FDIRCMD_L4TYPE_SCTP;
+	switch (input->formatted.flow_type) {
+	case IXGBE_ATR_FLOW_TYPE_IPV4:
+		/* use the L4 protocol mask for raw IPv4/IPv6 traffic */
+		fdirm |= IXGBE_FDIRM_L4P;
+	case IXGBE_ATR_FLOW_TYPE_SCTPV4:
+		if (input_masks->dst_port_mask || input_masks->src_port_mask) {
+			hw_dbg(hw, " Error on src/dst port mask\n");
+			return IXGBE_ERR_CONFIG;
+		}
+	case IXGBE_ATR_FLOW_TYPE_TCPV4:
+	case IXGBE_ATR_FLOW_TYPE_UDPV4:
 		break;
 	default:
-		hw_dbg(hw, "Error on l4type input\n");
+		hw_dbg(hw, " Error on flow type input\n");
 		return IXGBE_ERR_CONFIG;
 	}
 
-	bucket_hash = ixgbe_atr_compute_hash_82599(input,
-	                                           IXGBE_ATR_BUCKET_HASH_KEY);
-
-	/* bucket_hash is only 15 bits */
-	bucket_hash &= IXGBE_ATR_HASH_MASK;
-
-	ixgbe_atr_get_vlan_id_82599(input, &vlan_id);
-	ixgbe_atr_get_src_port_82599(input, &src_port);
-	ixgbe_atr_get_dst_port_82599(input, &dst_port);
-	ixgbe_atr_get_flex_byte_82599(input, &flex_bytes);
-
-	fdirhash = soft_id << IXGBE_FDIRHASH_SIG_SW_INDEX_SHIFT | bucket_hash;
-
-	/* Now figure out if we're IPv4 or IPv6 */
-	if (l4type & IXGBE_ATR_L4TYPE_IPV6_MASK) {
-		/* IPv6 */
-		ixgbe_atr_get_src_ipv6_82599(input, &src_ipv6_1, &src_ipv6_2,
-	                                     &src_ipv6_3, &src_ipv6_4);
-
-		IXGBE_WRITE_REG(hw, IXGBE_FDIRSIPv6(0), src_ipv6_1);
-		IXGBE_WRITE_REG(hw, IXGBE_FDIRSIPv6(1), src_ipv6_2);
-		IXGBE_WRITE_REG(hw, IXGBE_FDIRSIPv6(2), src_ipv6_3);
-		/* The last 4 bytes is the same register as IPv4 */
-		IXGBE_WRITE_REG(hw, IXGBE_FDIRIPSA, src_ipv6_4);
-
-		fdircmd |= IXGBE_FDIRCMD_IPV6;
-		fdircmd |= IXGBE_FDIRCMD_IPv6DMATCH;
-	} else {
-		/* IPv4 */
-		ixgbe_atr_get_src_ipv4_82599(input, &src_ipv4);
-		IXGBE_WRITE_REG(hw, IXGBE_FDIRIPSA, src_ipv4);
-	}
-
-	ixgbe_atr_get_dst_ipv4_82599(input, &dst_ipv4);
-	IXGBE_WRITE_REG(hw, IXGBE_FDIRIPDA, dst_ipv4);
-
-	IXGBE_WRITE_REG(hw, IXGBE_FDIRVLAN, (vlan_id |
-	                            (flex_bytes << IXGBE_FDIRVLAN_FLEX_SHIFT)));
-	IXGBE_WRITE_REG(hw, IXGBE_FDIRPORT, (src_port |
-	              (dst_port << IXGBE_FDIRPORT_DESTINATION_SHIFT)));
-
 	/*
-	 * Program the relevant mask registers.  L4type cannot be
-	 * masked out in this implementation.
+	 * Program the relevant mask registers.  If src/dst_port or src/dst_addr
+	 * are zero, then assume a full mask for that field.  Also assume that
+	 * a VLAN of 0 is unspecified, so mask that out as well.  L4type
+	 * cannot be masked out in this implementation.
 	 *
 	 * This also assumes IPv4 only.  IPv6 masking isn't supported at this
 	 * point in time.
 	 */
-	IXGBE_WRITE_REG(hw, IXGBE_FDIRSIP4M, input_masks->src_ip_mask);
-	IXGBE_WRITE_REG(hw, IXGBE_FDIRDIP4M, input_masks->dst_ip_mask);
 
-	switch (l4type & IXGBE_ATR_L4TYPE_MASK) {
-	case IXGBE_ATR_L4TYPE_TCP:
-		IXGBE_WRITE_REG(hw, IXGBE_FDIRTCPM, input_masks->src_port_mask);
-		IXGBE_WRITE_REG(hw, IXGBE_FDIRTCPM,
-				(IXGBE_READ_REG(hw, IXGBE_FDIRTCPM) |
-				 (input_masks->dst_port_mask << 16)));
+	/* Program FDIRM */
+	switch (ntohs(input_masks->vlan_id_mask) & 0xEFFF) {
+	case 0xEFFF:
+		/* Unmask VLAN ID - bit 0 and fall through to unmask prio */
+		fdirm &= ~IXGBE_FDIRM_VLANID;
+	case 0xE000:
+		/* Unmask VLAN prio - bit 1 */
+		fdirm &= ~IXGBE_FDIRM_VLANP;
 		break;
-	case IXGBE_ATR_L4TYPE_UDP:
-		IXGBE_WRITE_REG(hw, IXGBE_FDIRUDPM, input_masks->src_port_mask);
-		IXGBE_WRITE_REG(hw, IXGBE_FDIRUDPM,
-				(IXGBE_READ_REG(hw, IXGBE_FDIRUDPM) |
-				 (input_masks->src_port_mask << 16)));
+	case 0x0FFF:
+		/* Unmask VLAN ID - bit 0 */
+		fdirm &= ~IXGBE_FDIRM_VLANID;
 		break;
-	default:
-		/* this already would have failed above */
+	case 0x0000:
+		/* do nothing, vlans already masked */
 		break;
+	default:
+		hw_dbg(hw, " Error on VLAN mask\n");
+		return IXGBE_ERR_CONFIG;
 	}
 
-	/* Program the last mask register, FDIRM */
-	if (input_masks->vlan_id_mask)
-		/* Mask both VLAN and VLANP - bits 0 and 1 */
-		fdirm |= 0x3;
-
-	if (input_masks->data_mask)
-		/* Flex bytes need masking, so mask the whole thing - bit 4 */
-		fdirm |= 0x10;
+	if (input_masks->flex_mask & 0xFFFF) {
+		if ((input_masks->flex_mask & 0xFFFF) != 0xFFFF) {
+			hw_dbg(hw, " Error on flexible byte mask\n");
+			return IXGBE_ERR_CONFIG;
+		}
+		/* Unmask Flex Bytes - bit 4 */
+		fdirm &= ~IXGBE_FDIRM_FLEX;
+	}
 
 	/* Now mask VM pool and destination IPv6 - bits 5 and 2 */
-	fdirm |= 0x24;
-
 	IXGBE_WRITE_REG(hw, IXGBE_FDIRM, fdirm);
 
-	fdircmd |= IXGBE_FDIRCMD_CMD_ADD_FLOW;
-	fdircmd |= IXGBE_FDIRCMD_FILTER_UPDATE;
-	fdircmd |= IXGBE_FDIRCMD_LAST;
-	fdircmd |= IXGBE_FDIRCMD_QUEUE_EN;
-	fdircmd |= queue << IXGBE_FDIRCMD_RX_QUEUE_SHIFT;
+	/* store the TCP/UDP port masks, bit reversed from port layout */
+	fdirtcpm = ixgbe_get_fdirtcpm_82599(input_masks);
+
+	/* write both the same so that UDP and TCP use the same mask */
+	IXGBE_WRITE_REG(hw, IXGBE_FDIRTCPM, ~fdirtcpm);
+	IXGBE_WRITE_REG(hw, IXGBE_FDIRUDPM, ~fdirtcpm);
+
+	/* store source and destination IP masks (big-enian) */
+	IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRSIP4M,
+			     ~input_masks->src_ip_mask[0]);
+	IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRDIP4M,
+			     ~input_masks->dst_ip_mask[0]);
+
+	/* Apply masks to input data */
+	input->formatted.vlan_id &= input_masks->vlan_id_mask;
+	input->formatted.flex_bytes &= input_masks->flex_mask;
+	input->formatted.src_port &= input_masks->src_port_mask;
+	input->formatted.dst_port &= input_masks->dst_port_mask;
+	input->formatted.src_ip[0] &= input_masks->src_ip_mask[0];
+	input->formatted.dst_ip[0] &= input_masks->dst_ip_mask[0];
+
+	/* record vlan (little-endian) and flex_bytes(big-endian) */
+	fdirvlan =
+		IXGBE_STORE_AS_BE16(ntohs(input->formatted.flex_bytes));
+	fdirvlan <<= IXGBE_FDIRVLAN_FLEX_SHIFT;
+	fdirvlan |= ntohs(input->formatted.vlan_id);
+	IXGBE_WRITE_REG(hw, IXGBE_FDIRVLAN, fdirvlan);
+
+	/* record source and destination port (little-endian)*/
+	fdirport = ntohs(input->formatted.dst_port);
+	fdirport <<= IXGBE_FDIRPORT_DESTINATION_SHIFT;
+	fdirport |= ntohs(input->formatted.src_port);
+	IXGBE_WRITE_REG(hw, IXGBE_FDIRPORT, fdirport);
+
+	/* record the first 32 bits of the destination address (big-endian) */
+	IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRIPDA, input->formatted.dst_ip[0]);
+
+	/* record the source address (big-endian) */
+	IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRIPSA, input->formatted.src_ip[0]);
+
+	/* configure FDIRCMD register */
+	fdircmd = IXGBE_FDIRCMD_CMD_ADD_FLOW | IXGBE_FDIRCMD_FILTER_UPDATE |
+		  IXGBE_FDIRCMD_LAST | IXGBE_FDIRCMD_QUEUE_EN;
+	fdircmd |= input->formatted.flow_type << IXGBE_FDIRCMD_FLOW_TYPE_SHIFT;
+	fdircmd |= (u32)queue << IXGBE_FDIRCMD_RX_QUEUE_SHIFT;
+
+	/* we only want the bucket hash so drop the upper 16 bits */
+	fdirhash = ixgbe_atr_compute_hash_82599(input,
+						IXGBE_ATR_BUCKET_HASH_KEY);
+	fdirhash |= soft_id << IXGBE_FDIRHASH_SIG_SW_INDEX_SHIFT;
 
 	IXGBE_WRITE_REG(hw, IXGBE_FDIRHASH, fdirhash);
 	IXGBE_WRITE_REG(hw, IXGBE_FDIRCMD, fdircmd);
 
 	return 0;
 }
+
 /**
  *  ixgbe_read_analog_reg8_82599 - Reads 8 bit Omer analog register
  *  @hw: pointer to hardware structure
@@ -1924,6 +1764,7 @@ static u32 ixgbe_get_supported_physical_
 	hw->phy.ops.identify(hw);
 
 	if (hw->phy.type == ixgbe_phy_tn ||
+	    hw->phy.type == ixgbe_phy_aq ||
 	    hw->phy.type == ixgbe_phy_cu_unknown) {
 		hw->phy.ops.read_reg(hw, MDIO_PMA_EXTABLE, MDIO_MMD_PMAPMD,
 				     &ext_ability);
@@ -2125,51 +1966,6 @@ fw_version_out:
 	return status;
 }
 
-/**
- *  ixgbe_get_wwn_prefix_82599 - Get alternative WWNN/WWPN prefix from
- *  the EEPROM
- *  @hw: pointer to hardware structure
- *  @wwnn_prefix: the alternative WWNN prefix
- *  @wwpn_prefix: the alternative WWPN prefix
- *
- *  This function will read the EEPROM from the alternative SAN MAC address
- *  block to check the support for the alternative WWNN/WWPN prefix support.
- **/
-static s32 ixgbe_get_wwn_prefix_82599(struct ixgbe_hw *hw, u16 *wwnn_prefix,
-                                      u16 *wwpn_prefix)
-{
-	u16 offset, caps;
-	u16 alt_san_mac_blk_offset;
-
-	/* clear output first */
-	*wwnn_prefix = 0xFFFF;
-	*wwpn_prefix = 0xFFFF;
-
-	/* check if alternative SAN MAC is supported */
-	hw->eeprom.ops.read(hw, IXGBE_ALT_SAN_MAC_ADDR_BLK_PTR,
-	                    &alt_san_mac_blk_offset);
-
-	if ((alt_san_mac_blk_offset == 0) ||
-	    (alt_san_mac_blk_offset == 0xFFFF))
-		goto wwn_prefix_out;
-
-	/* check capability in alternative san mac address block */
-	offset = alt_san_mac_blk_offset + IXGBE_ALT_SAN_MAC_ADDR_CAPS_OFFSET;
-	hw->eeprom.ops.read(hw, offset, &caps);
-	if (!(caps & IXGBE_ALT_SAN_MAC_ADDR_CAPS_ALTWWN))
-		goto wwn_prefix_out;
-
-	/* get the corresponding prefix for WWNN/WWPN */
-	offset = alt_san_mac_blk_offset + IXGBE_ALT_SAN_MAC_ADDR_WWNN_OFFSET;
-	hw->eeprom.ops.read(hw, offset, wwnn_prefix);
-
-	offset = alt_san_mac_blk_offset + IXGBE_ALT_SAN_MAC_ADDR_WWPN_OFFSET;
-	hw->eeprom.ops.read(hw, offset, wwpn_prefix);
-
-wwn_prefix_out:
-	return 0;
-}
-
 static struct ixgbe_mac_operations mac_ops_82599 = {
 	.init_hw                = &ixgbe_init_hw_generic,
 	.reset_hw               = &ixgbe_reset_hw_82599,
@@ -2181,7 +1977,7 @@ static struct ixgbe_mac_operations mac_o
 	.get_mac_addr           = &ixgbe_get_mac_addr_generic,
 	.get_san_mac_addr       = &ixgbe_get_san_mac_addr_generic,
 	.get_device_caps        = &ixgbe_get_device_caps_82599,
-	.get_wwn_prefix         = &ixgbe_get_wwn_prefix_82599,
+	.get_wwn_prefix         = &ixgbe_get_wwn_prefix_generic,
 	.stop_adapter           = &ixgbe_stop_adapter_generic,
 	.get_bus_info           = &ixgbe_get_bus_info_generic,
 	.set_lan_id             = &ixgbe_set_lan_id_multi_port_pcie,
@@ -2208,12 +2004,15 @@ static struct ixgbe_mac_operations mac_o
 	.fc_enable              = &ixgbe_fc_enable_generic,
 	.init_uta_tables        = &ixgbe_init_uta_tables_generic,
 	.setup_sfp              = &ixgbe_setup_sfp_modules_82599,
+	.set_mac_anti_spoofing  = &ixgbe_set_mac_anti_spoofing,
+	.set_vlan_anti_spoofing = &ixgbe_set_vlan_anti_spoofing,
 };
 
 static struct ixgbe_eeprom_operations eeprom_ops_82599 = {
 	.init_params            = &ixgbe_init_eeprom_params_generic,
 	.read                   = &ixgbe_read_eerd_generic,
 	.write                  = &ixgbe_write_eeprom_generic,
+	.calc_checksum          = &ixgbe_calc_eeprom_checksum_generic,
 	.validate_checksum      = &ixgbe_validate_eeprom_checksum_generic,
 	.update_checksum        = &ixgbe_update_eeprom_checksum_generic,
 };
@@ -2240,5 +2039,5 @@ struct ixgbe_info ixgbe_82599_info = {
 	.mac_ops                = &mac_ops_82599,
 	.eeprom_ops             = &eeprom_ops_82599,
 	.phy_ops                = &phy_ops_82599,
-	.mbx_ops                = &mbx_ops_82599,
+	.mbx_ops                = &mbx_ops_generic,
 };
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/ixgbe/ixgbe_common.c linux-libre-2.6.38-gnu1/drivers/net/ixgbe/ixgbe_common.c
--- linux-libre-2.6.37-gnu1/drivers/net/ixgbe/ixgbe_common.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/ixgbe/ixgbe_common.c	2011-03-14 21:20:32.000000000 -0400
@@ -45,14 +45,12 @@ static u16 ixgbe_shift_in_eeprom_bits(st
 static void ixgbe_raise_eeprom_clk(struct ixgbe_hw *hw, u32 *eec);
 static void ixgbe_lower_eeprom_clk(struct ixgbe_hw *hw, u32 *eec);
 static void ixgbe_release_eeprom(struct ixgbe_hw *hw);
-static u16 ixgbe_calc_eeprom_checksum(struct ixgbe_hw *hw);
 
 static void ixgbe_enable_rar(struct ixgbe_hw *hw, u32 index);
 static void ixgbe_disable_rar(struct ixgbe_hw *hw, u32 index);
 static s32 ixgbe_mta_vector(struct ixgbe_hw *hw, u8 *mc_addr);
 static void ixgbe_add_uc_addr(struct ixgbe_hw *hw, u8 *addr, u32 vmdq);
 static s32 ixgbe_setup_fc(struct ixgbe_hw *hw, s32 packetbuf_num);
-static s32 ixgbe_poll_eerd_eewr_done(struct ixgbe_hw *hw, u32 ee_reg);
 
 /**
  *  ixgbe_start_hw_generic - Prepare hardware for Tx/Rx
@@ -198,30 +196,110 @@ s32 ixgbe_clear_hw_cntrs_generic(struct
 }
 
 /**
- *  ixgbe_read_pba_num_generic - Reads part number from EEPROM
+ *  ixgbe_read_pba_string_generic - Reads part number string from EEPROM
  *  @hw: pointer to hardware structure
- *  @pba_num: stores the part number from the EEPROM
+ *  @pba_num: stores the part number string from the EEPROM
+ *  @pba_num_size: part number string buffer length
  *
- *  Reads the part number from the EEPROM.
+ *  Reads the part number string from the EEPROM.
  **/
-s32 ixgbe_read_pba_num_generic(struct ixgbe_hw *hw, u32 *pba_num)
+s32 ixgbe_read_pba_string_generic(struct ixgbe_hw *hw, u8 *pba_num,
+                                  u32 pba_num_size)
 {
 	s32 ret_val;
 	u16 data;
+	u16 pba_ptr;
+	u16 offset;
+	u16 length;
+
+	if (pba_num == NULL) {
+		hw_dbg(hw, "PBA string buffer was null\n");
+		return IXGBE_ERR_INVALID_ARGUMENT;
+	}
 
 	ret_val = hw->eeprom.ops.read(hw, IXGBE_PBANUM0_PTR, &data);
 	if (ret_val) {
 		hw_dbg(hw, "NVM Read Error\n");
 		return ret_val;
 	}
-	*pba_num = (u32)(data << 16);
 
-	ret_val = hw->eeprom.ops.read(hw, IXGBE_PBANUM1_PTR, &data);
+	ret_val = hw->eeprom.ops.read(hw, IXGBE_PBANUM1_PTR, &pba_ptr);
+	if (ret_val) {
+		hw_dbg(hw, "NVM Read Error\n");
+		return ret_val;
+	}
+
+	/*
+	 * if data is not ptr guard the PBA must be in legacy format which
+	 * means pba_ptr is actually our second data word for the PBA number
+	 * and we can decode it into an ascii string
+	 */
+	if (data != IXGBE_PBANUM_PTR_GUARD) {
+		hw_dbg(hw, "NVM PBA number is not stored as string\n");
+
+		/* we will need 11 characters to store the PBA */
+		if (pba_num_size < 11) {
+			hw_dbg(hw, "PBA string buffer too small\n");
+			return IXGBE_ERR_NO_SPACE;
+		}
+
+		/* extract hex string from data and pba_ptr */
+		pba_num[0] = (data >> 12) & 0xF;
+		pba_num[1] = (data >> 8) & 0xF;
+		pba_num[2] = (data >> 4) & 0xF;
+		pba_num[3] = data & 0xF;
+		pba_num[4] = (pba_ptr >> 12) & 0xF;
+		pba_num[5] = (pba_ptr >> 8) & 0xF;
+		pba_num[6] = '-';
+		pba_num[7] = 0;
+		pba_num[8] = (pba_ptr >> 4) & 0xF;
+		pba_num[9] = pba_ptr & 0xF;
+
+		/* put a null character on the end of our string */
+		pba_num[10] = '\0';
+
+		/* switch all the data but the '-' to hex char */
+		for (offset = 0; offset < 10; offset++) {
+			if (pba_num[offset] < 0xA)
+				pba_num[offset] += '0';
+			else if (pba_num[offset] < 0x10)
+				pba_num[offset] += 'A' - 0xA;
+		}
+
+		return 0;
+	}
+
+	ret_val = hw->eeprom.ops.read(hw, pba_ptr, &length);
 	if (ret_val) {
 		hw_dbg(hw, "NVM Read Error\n");
 		return ret_val;
 	}
-	*pba_num |= data;
+
+	if (length == 0xFFFF || length == 0) {
+		hw_dbg(hw, "NVM PBA number section invalid length\n");
+		return IXGBE_ERR_PBA_SECTION;
+	}
+
+	/* check if pba_num buffer is big enough */
+	if (pba_num_size  < (((u32)length * 2) - 1)) {
+		hw_dbg(hw, "PBA string buffer too small\n");
+		return IXGBE_ERR_NO_SPACE;
+	}
+
+	/* trim pba length from start of string */
+	pba_ptr++;
+	length--;
+
+	for (offset = 0; offset < length; offset++) {
+		ret_val = hw->eeprom.ops.read(hw, pba_ptr + offset, &data);
+		if (ret_val) {
+			hw_dbg(hw, "NVM Read Error\n");
+			return ret_val;
+		}
+		pba_num[offset * 2] = (u8)(data >> 8);
+		pba_num[(offset * 2) + 1] = (u8)(data & 0xFF);
+	}
+	pba_num[offset * 2] = '\0';
 
 	return 0;
 }
@@ -638,7 +716,7 @@ out:
  *  Polls the status bit (bit 1) of the EERD or EEWR to determine when the
  *  read or write is done respectively.
  **/
-static s32 ixgbe_poll_eerd_eewr_done(struct ixgbe_hw *hw, u32 ee_reg)
+s32 ixgbe_poll_eerd_eewr_done(struct ixgbe_hw *hw, u32 ee_reg)
 {
 	u32 i;
 	u32 reg;
@@ -1009,7 +1087,7 @@ static void ixgbe_release_eeprom(struct
  *  ixgbe_calc_eeprom_checksum - Calculates and returns the checksum
  *  @hw: pointer to hardware structure
  **/
-static u16 ixgbe_calc_eeprom_checksum(struct ixgbe_hw *hw)
+u16 ixgbe_calc_eeprom_checksum_generic(struct ixgbe_hw *hw)
 {
 	u16 i;
 	u16 j;
@@ -1072,7 +1150,7 @@ s32 ixgbe_validate_eeprom_checksum_gener
 	status = hw->eeprom.ops.read(hw, 0, &checksum);
 
 	if (status == 0) {
-		checksum = ixgbe_calc_eeprom_checksum(hw);
+		checksum = hw->eeprom.ops.calc_checksum(hw);
 
 		hw->eeprom.ops.read(hw, IXGBE_EEPROM_CHECKSUM, &read_checksum);
 
@@ -1110,7 +1188,7 @@ s32 ixgbe_update_eeprom_checksum_generic
 	status = hw->eeprom.ops.read(hw, 0, &checksum);
 
 	if (status == 0) {
-		checksum = ixgbe_calc_eeprom_checksum(hw);
+		checksum = hw->eeprom.ops.calc_checksum(hw);
 		status = hw->eeprom.ops.write(hw, IXGBE_EEPROM_CHECKSUM,
 		                            checksum);
 	} else {
@@ -1292,6 +1370,9 @@ s32 ixgbe_init_rx_addrs_generic(struct i
 		hw_dbg(hw, " New MAC Addr =%pM\n", hw->mac.addr);
 
 		hw->mac.ops.set_rar(hw, 0, hw->mac.addr, 0, IXGBE_RAH_AV);
+
+		/*  clear VMDq pool/queue selection for RAR 0 */
+		hw->mac.ops.clear_vmdq(hw, 0, IXGBE_CLEAR_VMDQ_ALL);
 	}
 	hw->addr_ctrl.overflow_promisc = 0;
 
@@ -1595,6 +1676,7 @@ s32 ixgbe_fc_enable_generic(struct ixgbe
 	u32 mflcn_reg, fccfg_reg;
 	u32 reg;
 	u32 rx_pba_size;
+	u32 fcrtl, fcrth;
 
 #ifdef CONFIG_DCB
 	if (hw->fc.requested_mode == ixgbe_fc_pfc)
@@ -1671,41 +1753,21 @@ s32 ixgbe_fc_enable_generic(struct ixgbe
 	IXGBE_WRITE_REG(hw, IXGBE_MFLCN, mflcn_reg);
 	IXGBE_WRITE_REG(hw, IXGBE_FCCFG, fccfg_reg);
 
-	reg = IXGBE_READ_REG(hw, IXGBE_MTQC);
-	/* Thresholds are different for link flow control when in DCB mode */
-	if (reg & IXGBE_MTQC_RT_ENA) {
-		rx_pba_size = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(packetbuf_num));
-
-		/* Always disable XON for LFC when in DCB mode */
-		reg = (rx_pba_size >> 5) & 0xFFE0;
-		IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(packetbuf_num), reg);
+	rx_pba_size = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(packetbuf_num));
+	rx_pba_size >>= IXGBE_RXPBSIZE_SHIFT;
 
-		reg = (rx_pba_size >> 2) & 0xFFE0;
-		if (hw->fc.current_mode & ixgbe_fc_tx_pause)
-			reg |= IXGBE_FCRTH_FCEN;
-		IXGBE_WRITE_REG(hw, IXGBE_FCRTH_82599(packetbuf_num), reg);
-	} else {
-		/*
-		 * Set up and enable Rx high/low water mark thresholds,
-		 * enable XON.
-		 */
-		if (hw->fc.current_mode & ixgbe_fc_tx_pause) {
-			if (hw->fc.send_xon) {
-				IXGBE_WRITE_REG(hw,
-				              IXGBE_FCRTL_82599(packetbuf_num),
-			                      (hw->fc.low_water |
-				              IXGBE_FCRTL_XONE));
-			} else {
-				IXGBE_WRITE_REG(hw,
-				              IXGBE_FCRTL_82599(packetbuf_num),
-				              hw->fc.low_water);
-			}
+	fcrth = (rx_pba_size - hw->fc.high_water) << 10;
+	fcrtl = (rx_pba_size - hw->fc.low_water) << 10;
 
-			IXGBE_WRITE_REG(hw, IXGBE_FCRTH_82599(packetbuf_num),
-			               (hw->fc.high_water | IXGBE_FCRTH_FCEN));
-		}
+	if (hw->fc.current_mode & ixgbe_fc_tx_pause) {
+		fcrth |= IXGBE_FCRTH_FCEN;
+		if (hw->fc.send_xon)
+			fcrtl |= IXGBE_FCRTL_XONE;
 	}
 
+	IXGBE_WRITE_REG(hw, IXGBE_FCRTH_82599(packetbuf_num), fcrth);
+	IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(packetbuf_num), fcrtl);
+
 	/* Configure pause time (2 TCs per register) */
 	reg = IXGBE_READ_REG(hw, IXGBE_FCTTV(packetbuf_num / 2));
 	if ((packetbuf_num & 1) == 0)
@@ -2705,3 +2767,112 @@ s32 ixgbe_check_mac_link_generic(struct
 
 	return 0;
 }
+
+/**
+ *  ixgbe_get_wwn_prefix_generic Get alternative WWNN/WWPN prefix from
+ *  the EEPROM
+ *  @hw: pointer to hardware structure
+ *  @wwnn_prefix: the alternative WWNN prefix
+ *  @wwpn_prefix: the alternative WWPN prefix
+ *
+ *  This function will read the EEPROM from the alternative SAN MAC address
+ *  block to check the support for the alternative WWNN/WWPN prefix support.
+ **/
+s32 ixgbe_get_wwn_prefix_generic(struct ixgbe_hw *hw, u16 *wwnn_prefix,
+                                        u16 *wwpn_prefix)
+{
+	u16 offset, caps;
+	u16 alt_san_mac_blk_offset;
+
+	/* clear output first */
+	*wwnn_prefix = 0xFFFF;
+	*wwpn_prefix = 0xFFFF;
+
+	/* check if alternative SAN MAC is supported */
+	hw->eeprom.ops.read(hw, IXGBE_ALT_SAN_MAC_ADDR_BLK_PTR,
+	                    &alt_san_mac_blk_offset);
+
+	if ((alt_san_mac_blk_offset == 0) ||
+	    (alt_san_mac_blk_offset == 0xFFFF))
+		goto wwn_prefix_out;
+
+	/* check capability in alternative san mac address block */
+	offset = alt_san_mac_blk_offset + IXGBE_ALT_SAN_MAC_ADDR_CAPS_OFFSET;
+	hw->eeprom.ops.read(hw, offset, &caps);
+	if (!(caps & IXGBE_ALT_SAN_MAC_ADDR_CAPS_ALTWWN))
+		goto wwn_prefix_out;
+
+	/* get the corresponding prefix for WWNN/WWPN */
+	offset = alt_san_mac_blk_offset + IXGBE_ALT_SAN_MAC_ADDR_WWNN_OFFSET;
+	hw->eeprom.ops.read(hw, offset, wwnn_prefix);
+
+	offset = alt_san_mac_blk_offset + IXGBE_ALT_SAN_MAC_ADDR_WWPN_OFFSET;
+	hw->eeprom.ops.read(hw, offset, wwpn_prefix);
+
+wwn_prefix_out:
+	return 0;
+}
+
+/**
+ *  ixgbe_set_mac_anti_spoofing - Enable/Disable MAC anti-spoofing
+ *  @hw: pointer to hardware structure
+ *  @enable: enable or disable switch for anti-spoofing
+ *  @pf: Physical Function pool - do not enable anti-spoofing for the PF
+ *
+ **/
+void ixgbe_set_mac_anti_spoofing(struct ixgbe_hw *hw, bool enable, int pf)
+{
+	int j;
+	int pf_target_reg = pf >> 3;
+	int pf_target_shift = pf % 8;
+	u32 pfvfspoof = 0;
+
+	if (hw->mac.type == ixgbe_mac_82598EB)
+		return;
+
+	if (enable)
+		pfvfspoof = IXGBE_SPOOF_MACAS_MASK;
+
+	/*
+	 * PFVFSPOOF register array is size 8 with 8 bits assigned to
+	 * MAC anti-spoof enables in each register array element.
+	 */
+	for (j = 0; j < IXGBE_PFVFSPOOF_REG_COUNT; j++)
+		IXGBE_WRITE_REG(hw, IXGBE_PFVFSPOOF(j), pfvfspoof);
+
+	/* If not enabling anti-spoofing then done */
+	if (!enable)
+		return;
+
+	/*
+	 * The PF should be allowed to spoof so that it can support
+	 * emulation mode NICs.  Reset the bit assigned to the PF
+	 */
+	pfvfspoof = IXGBE_READ_REG(hw, IXGBE_PFVFSPOOF(pf_target_reg));
+	pfvfspoof ^= (1 << pf_target_shift);
+	IXGBE_WRITE_REG(hw, IXGBE_PFVFSPOOF(pf_target_reg), pfvfspoof);
+}
+
+/**
+ *  ixgbe_set_vlan_anti_spoofing - Enable/Disable VLAN anti-spoofing
+ *  @hw: pointer to hardware structure
+ *  @enable: enable or disable switch for VLAN anti-spoofing
+ *  @pf: Virtual Function pool - VF Pool to set for VLAN anti-spoofing
+ *
+ **/
+void ixgbe_set_vlan_anti_spoofing(struct ixgbe_hw *hw, bool enable, int vf)
+{
+	int vf_target_reg = vf >> 3;
+	int vf_target_shift = vf % 8 + IXGBE_SPOOF_VLANAS_SHIFT;
+	u32 pfvfspoof;
+
+	if (hw->mac.type == ixgbe_mac_82598EB)
+		return;
+
+	pfvfspoof = IXGBE_READ_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg));
+	if (enable)
+		pfvfspoof |= (1 << vf_target_shift);
+	else
+		pfvfspoof &= ~(1 << vf_target_shift);
+	IXGBE_WRITE_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg), pfvfspoof);
+}
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/ixgbe/ixgbe_common.h linux-libre-2.6.38-gnu1/drivers/net/ixgbe/ixgbe_common.h
--- linux-libre-2.6.37-gnu1/drivers/net/ixgbe/ixgbe_common.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/ixgbe/ixgbe_common.h	2011-03-14 21:20:32.000000000 -0400
@@ -35,7 +35,8 @@ s32 ixgbe_init_ops_generic(struct ixgbe_
 s32 ixgbe_init_hw_generic(struct ixgbe_hw *hw);
 s32 ixgbe_start_hw_generic(struct ixgbe_hw *hw);
 s32 ixgbe_clear_hw_cntrs_generic(struct ixgbe_hw *hw);
-s32 ixgbe_read_pba_num_generic(struct ixgbe_hw *hw, u32 *pba_num);
+s32 ixgbe_read_pba_string_generic(struct ixgbe_hw *hw, u8 *pba_num,
+                                  u32 pba_num_size);
 s32 ixgbe_get_mac_addr_generic(struct ixgbe_hw *hw, u8 *mac_addr);
 s32 ixgbe_get_bus_info_generic(struct ixgbe_hw *hw);
 void ixgbe_set_lan_id_multi_port_pcie(struct ixgbe_hw *hw);
@@ -49,9 +50,11 @@ s32 ixgbe_write_eeprom_generic(struct ix
 s32 ixgbe_read_eerd_generic(struct ixgbe_hw *hw, u16 offset, u16 *data);
 s32 ixgbe_read_eeprom_bit_bang_generic(struct ixgbe_hw *hw, u16 offset,
                                        u16 *data);
+u16 ixgbe_calc_eeprom_checksum_generic(struct ixgbe_hw *hw);
 s32 ixgbe_validate_eeprom_checksum_generic(struct ixgbe_hw *hw,
                                            u16 *checksum_val);
 s32 ixgbe_update_eeprom_checksum_generic(struct ixgbe_hw *hw);
+s32 ixgbe_poll_eerd_eewr_done(struct ixgbe_hw *hw, u32 ee_reg);
 
 s32 ixgbe_set_rar_generic(struct ixgbe_hw *hw, u32 index, u8 *addr, u32 vmdq,
                           u32 enable_addr);
@@ -81,9 +84,12 @@ s32 ixgbe_clear_vfta_generic(struct ixgb
 s32 ixgbe_check_mac_link_generic(struct ixgbe_hw *hw,
                                  ixgbe_link_speed *speed,
                                  bool *link_up, bool link_up_wait_to_complete);
-
+s32 ixgbe_get_wwn_prefix_generic(struct ixgbe_hw *hw, u16 *wwnn_prefix,
+                                 u16 *wwpn_prefix);
 s32 ixgbe_blink_led_start_generic(struct ixgbe_hw *hw, u32 index);
 s32 ixgbe_blink_led_stop_generic(struct ixgbe_hw *hw, u32 index);
+void ixgbe_set_mac_anti_spoofing(struct ixgbe_hw *hw, bool enable, int pf);
+void ixgbe_set_vlan_anti_spoofing(struct ixgbe_hw *hw, bool enable, int vf);
 
 #define IXGBE_WRITE_REG(a, reg, value) writel((value), ((a)->hw_addr + (reg)))
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/ixgbe/ixgbe_dcb_82598.c linux-libre-2.6.38-gnu1/drivers/net/ixgbe/ixgbe_dcb_82598.c
--- linux-libre-2.6.37-gnu1/drivers/net/ixgbe/ixgbe_dcb_82598.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/ixgbe/ixgbe_dcb_82598.c	2011-03-14 21:20:32.000000000 -0400
@@ -256,21 +256,17 @@ s32 ixgbe_dcb_config_pfc_82598(struct ix
 	 * for each traffic class.
 	 */
 	for (i = 0; i < MAX_TRAFFIC_CLASS; i++) {
-		if (dcb_config->rx_pba_cfg == pba_equal) {
-			rx_pba_size = IXGBE_RXPBSIZE_64KB;
-		} else {
-			rx_pba_size = (i < 4) ? IXGBE_RXPBSIZE_80KB
-					      : IXGBE_RXPBSIZE_48KB;
-		}
+		rx_pba_size = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(i));
+		rx_pba_size >>= IXGBE_RXPBSIZE_SHIFT;
+		reg = (rx_pba_size - hw->fc.low_water) << 10;
 
-		reg = ((rx_pba_size >> 5) &  0xFFF0);
 		if (dcb_config->tc_config[i].dcb_pfc == pfc_enabled_tx ||
 		    dcb_config->tc_config[i].dcb_pfc == pfc_enabled_full)
 			reg |= IXGBE_FCRTL_XONE;
 
 		IXGBE_WRITE_REG(hw, IXGBE_FCRTL(i), reg);
 
-		reg = ((rx_pba_size >> 2) & 0xFFF0);
+		reg = (rx_pba_size - hw->fc.high_water) << 10;
 		if (dcb_config->tc_config[i].dcb_pfc == pfc_enabled_tx ||
 		    dcb_config->tc_config[i].dcb_pfc == pfc_enabled_full)
 			reg |= IXGBE_FCRTH_FCEN;
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/ixgbe/ixgbe_dcb_82599.c linux-libre-2.6.38-gnu1/drivers/net/ixgbe/ixgbe_dcb_82599.c
--- linux-libre-2.6.37-gnu1/drivers/net/ixgbe/ixgbe_dcb_82599.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/ixgbe/ixgbe_dcb_82599.c	2011-03-14 21:20:32.000000000 -0400
@@ -251,19 +251,17 @@ s32 ixgbe_dcb_config_pfc_82599(struct ix
 
 	/* Configure PFC Tx thresholds per TC */
 	for (i = 0; i < MAX_TRAFFIC_CLASS; i++) {
-		if (dcb_config->rx_pba_cfg == pba_equal)
-			rx_pba_size = IXGBE_RXPBSIZE_64KB;
-		else
-			rx_pba_size = (i < 4) ? IXGBE_RXPBSIZE_80KB
-			                      : IXGBE_RXPBSIZE_48KB;
+		rx_pba_size = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(i));
+		rx_pba_size >>= IXGBE_RXPBSIZE_SHIFT;
+
+		reg = (rx_pba_size - hw->fc.low_water) << 10;
 
-		reg = ((rx_pba_size >> 5) & 0xFFE0);
 		if (dcb_config->tc_config[i].dcb_pfc == pfc_enabled_full ||
 		    dcb_config->tc_config[i].dcb_pfc == pfc_enabled_tx)
 			reg |= IXGBE_FCRTL_XONE;
 		IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(i), reg);
 
-		reg = ((rx_pba_size >> 2) & 0xFFE0);
+		reg = (rx_pba_size - hw->fc.high_water) << 10;
 		if (dcb_config->tc_config[i].dcb_pfc == pfc_enabled_full ||
 		    dcb_config->tc_config[i].dcb_pfc == pfc_enabled_tx)
 			reg |= IXGBE_FCRTH_FCEN;
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/ixgbe/ixgbe_dcb.c linux-libre-2.6.38-gnu1/drivers/net/ixgbe/ixgbe_dcb.c
--- linux-libre-2.6.37-gnu1/drivers/net/ixgbe/ixgbe_dcb.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/ixgbe/ixgbe_dcb.c	2011-03-14 21:20:32.000000000 -0400
@@ -42,7 +42,8 @@
  * It should be called only after the rules are checked by
  * ixgbe_dcb_check_config().
  */
-s32 ixgbe_dcb_calculate_tc_credits(struct ixgbe_dcb_config *dcb_config,
+s32 ixgbe_dcb_calculate_tc_credits(struct ixgbe_hw *hw,
+				   struct ixgbe_dcb_config *dcb_config,
 				   int max_frame, u8 direction)
 {
 	struct tc_bw_alloc *p;
@@ -124,7 +125,8 @@ s32 ixgbe_dcb_calculate_tc_credits(struc
 			 * credit may not be enough to send out a TSO
 			 * packet in descriptor plane arbitration.
 			 */
-			if (credit_max &&
+			if ((hw->mac.type == ixgbe_mac_82598EB) &&
+			    credit_max &&
 			    (credit_max < MINIMUM_CREDIT_FOR_TSO))
 				credit_max = MINIMUM_CREDIT_FOR_TSO;
 
@@ -150,10 +152,17 @@ s32 ixgbe_dcb_hw_config(struct ixgbe_hw
                         struct ixgbe_dcb_config *dcb_config)
 {
 	s32 ret = 0;
-	if (hw->mac.type == ixgbe_mac_82598EB)
+	switch (hw->mac.type) {
+	case ixgbe_mac_82598EB:
 		ret = ixgbe_dcb_hw_config_82598(hw, dcb_config);
-	else if (hw->mac.type == ixgbe_mac_82599EB)
+		break;
+	case ixgbe_mac_82599EB:
+	case ixgbe_mac_X540:
 		ret = ixgbe_dcb_hw_config_82599(hw, dcb_config);
+		break;
+	default:
+		break;
+	}
 	return ret;
 }
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/ixgbe/ixgbe_dcb.h linux-libre-2.6.38-gnu1/drivers/net/ixgbe/ixgbe_dcb.h
--- linux-libre-2.6.37-gnu1/drivers/net/ixgbe/ixgbe_dcb.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/ixgbe/ixgbe_dcb.h	2011-03-14 21:20:32.000000000 -0400
@@ -150,7 +150,8 @@ struct ixgbe_dcb_config {
 /* DCB driver APIs */
 
 /* DCB credits calculation */
-s32 ixgbe_dcb_calculate_tc_credits(struct ixgbe_dcb_config *, int, u8);
+s32 ixgbe_dcb_calculate_tc_credits(struct ixgbe_hw *,
+				   struct ixgbe_dcb_config *, int, u8);
 
 /* DCB hw initialization */
 s32 ixgbe_dcb_hw_config(struct ixgbe_hw *, struct ixgbe_dcb_config *);
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/ixgbe/ixgbe_dcb_nl.c linux-libre-2.6.38-gnu1/drivers/net/ixgbe/ixgbe_dcb_nl.c
--- linux-libre-2.6.37-gnu1/drivers/net/ixgbe/ixgbe_dcb_nl.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/ixgbe/ixgbe_dcb_nl.c	2011-03-14 21:20:32.000000000 -0400
@@ -130,15 +130,21 @@ static u8 ixgbe_dcbnl_set_state(struct n
 			netdev->netdev_ops->ndo_stop(netdev);
 		ixgbe_clear_interrupt_scheme(adapter);
 
-		if (adapter->hw.mac.type == ixgbe_mac_82598EB) {
+		adapter->flags &= ~IXGBE_FLAG_RSS_ENABLED;
+		switch (adapter->hw.mac.type) {
+		case ixgbe_mac_82598EB:
 			adapter->last_lfc_mode = adapter->hw.fc.current_mode;
 			adapter->hw.fc.requested_mode = ixgbe_fc_none;
-		}
-		adapter->flags &= ~IXGBE_FLAG_RSS_ENABLED;
-		if (adapter->hw.mac.type == ixgbe_mac_82599EB) {
+			break;
+		case ixgbe_mac_82599EB:
+		case ixgbe_mac_X540:
 			adapter->flags &= ~IXGBE_FLAG_FDIR_HASH_CAPABLE;
 			adapter->flags &= ~IXGBE_FLAG_FDIR_PERFECT_CAPABLE;
+			break;
+		default:
+			break;
 		}
+
 		adapter->flags |= IXGBE_FLAG_DCB_ENABLED;
 		ixgbe_init_interrupt_scheme(adapter);
 		if (netif_running(netdev))
@@ -155,8 +161,14 @@ static u8 ixgbe_dcbnl_set_state(struct n
 			adapter->dcb_cfg.pfc_mode_enable = false;
 			adapter->flags &= ~IXGBE_FLAG_DCB_ENABLED;
 			adapter->flags |= IXGBE_FLAG_RSS_ENABLED;
-			if (adapter->hw.mac.type == ixgbe_mac_82599EB)
+			switch (adapter->hw.mac.type) {
+			case ixgbe_mac_82599EB:
+			case ixgbe_mac_X540:
 				adapter->flags |= IXGBE_FLAG_FDIR_HASH_CAPABLE;
+				break;
+			default:
+				break;
+			}
 
 			ixgbe_init_interrupt_scheme(adapter);
 			if (netif_running(netdev))
@@ -178,9 +190,14 @@ static void ixgbe_dcbnl_get_perm_hw_addr
 	for (i = 0; i < netdev->addr_len; i++)
 		perm_addr[i] = adapter->hw.mac.perm_addr[i];
 
-	if (adapter->hw.mac.type == ixgbe_mac_82599EB) {
+	switch (adapter->hw.mac.type) {
+	case ixgbe_mac_82599EB:
+	case ixgbe_mac_X540:
 		for (j = 0; j < netdev->addr_len; j++, i++)
 			perm_addr[i] = adapter->hw.mac.san_addr[j];
+		break;
+	default:
+		break;
 	}
 }
 
@@ -366,15 +383,29 @@ static u8 ixgbe_dcbnl_set_all(struct net
 	}
 
 	if (adapter->dcb_cfg.pfc_mode_enable) {
-		if ((adapter->hw.mac.type != ixgbe_mac_82598EB) &&
-			(adapter->hw.fc.current_mode != ixgbe_fc_pfc))
-			adapter->last_lfc_mode = adapter->hw.fc.current_mode;
+		switch (adapter->hw.mac.type) {
+		case ixgbe_mac_82599EB:
+		case ixgbe_mac_X540:
+			if (adapter->hw.fc.current_mode != ixgbe_fc_pfc)
+				adapter->last_lfc_mode =
+				                  adapter->hw.fc.current_mode;
+			break;
+		default:
+			break;
+		}
 		adapter->hw.fc.requested_mode = ixgbe_fc_pfc;
 	} else {
-		if (adapter->hw.mac.type != ixgbe_mac_82598EB)
-			adapter->hw.fc.requested_mode = adapter->last_lfc_mode;
-		else
+		switch (adapter->hw.mac.type) {
+		case ixgbe_mac_82598EB:
 			adapter->hw.fc.requested_mode = ixgbe_fc_none;
+			break;
+		case ixgbe_mac_82599EB:
+		case ixgbe_mac_X540:
+			adapter->hw.fc.requested_mode = adapter->last_lfc_mode;
+			break;
+		default:
+			break;
+		}
 	}
 
 	if (adapter->dcb_set_bitmap & BIT_RESETLINK) {
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/ixgbe/ixgbe_ethtool.c linux-libre-2.6.38-gnu1/drivers/net/ixgbe/ixgbe_ethtool.c
--- linux-libre-2.6.37-gnu1/drivers/net/ixgbe/ixgbe_ethtool.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/ixgbe/ixgbe_ethtool.c	2011-03-14 21:20:32.000000000 -0400
@@ -185,6 +185,16 @@ static int ixgbe_get_settings(struct net
 					     ADVERTISED_FIBRE);
 			ecmd->port = PORT_FIBRE;
 			ecmd->autoneg = AUTONEG_DISABLE;
+		} else if ((hw->device_id == IXGBE_DEV_ID_82599_COMBO_BACKPLANE) ||
+			   (hw->device_id == IXGBE_DEV_ID_82599_KX4_MEZZ)) {
+			ecmd->supported |= (SUPPORTED_1000baseT_Full |
+					    SUPPORTED_Autoneg |
+					    SUPPORTED_FIBRE);
+			ecmd->advertising = (ADVERTISED_10000baseT_Full |
+					     ADVERTISED_1000baseT_Full |
+					     ADVERTISED_Autoneg |
+					     ADVERTISED_FIBRE);
+			ecmd->port = PORT_FIBRE;
 		} else {
 			ecmd->supported |= (SUPPORTED_1000baseT_Full |
 					    SUPPORTED_FIBRE);
@@ -204,6 +214,7 @@ static int ixgbe_get_settings(struct net
 	/* Get PHY type */
 	switch (adapter->hw.phy.type) {
 	case ixgbe_phy_tn:
+	case ixgbe_phy_aq:
 	case ixgbe_phy_cu_unknown:
 		/* Copper 10G-BASET */
 		ecmd->port = PORT_TP;
@@ -332,13 +343,6 @@ static void ixgbe_get_pauseparam(struct
 	else
 		pause->autoneg = 1;
 
-#ifdef CONFIG_DCB
-	if (hw->fc.current_mode == ixgbe_fc_pfc) {
-		pause->rx_pause = 0;
-		pause->tx_pause = 0;
-	}
-
-#endif
 	if (hw->fc.current_mode == ixgbe_fc_rx_pause) {
 		pause->rx_pause = 1;
 	} else if (hw->fc.current_mode == ixgbe_fc_tx_pause) {
@@ -346,6 +350,11 @@ static void ixgbe_get_pauseparam(struct
 	} else if (hw->fc.current_mode == ixgbe_fc_full) {
 		pause->rx_pause = 1;
 		pause->tx_pause = 1;
+#ifdef CONFIG_DCB
+	} else if (hw->fc.current_mode == ixgbe_fc_pfc) {
+		pause->rx_pause = 0;
+		pause->tx_pause = 0;
+#endif
 	}
 }
 
@@ -363,7 +372,6 @@ static int ixgbe_set_pauseparam(struct n
 		return -EINVAL;
 
 #endif
-
 	fc = hw->fc;
 
 	if (pause->autoneg != AUTONEG_ENABLE)
@@ -412,11 +420,6 @@ static int ixgbe_set_rx_csum(struct net_
 	else
 		adapter->flags &= ~IXGBE_FLAG_RX_CSUM_ENABLED;
 
-	if (netif_running(netdev))
-		ixgbe_reinit_locked(adapter);
-	else
-		ixgbe_reset(adapter);
-
 	return 0;
 }
 
@@ -428,16 +431,21 @@ static u32 ixgbe_get_tx_csum(struct net_
 static int ixgbe_set_tx_csum(struct net_device *netdev, u32 data)
 {
 	struct ixgbe_adapter *adapter = netdev_priv(netdev);
+	u32 feature_list;
 
-	if (data) {
-		netdev->features |= (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM);
-		if (adapter->hw.mac.type == ixgbe_mac_82599EB)
-			netdev->features |= NETIF_F_SCTP_CSUM;
-	} else {
-		netdev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM);
-		if (adapter->hw.mac.type == ixgbe_mac_82599EB)
-			netdev->features &= ~NETIF_F_SCTP_CSUM;
+	feature_list = (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM);
+	switch (adapter->hw.mac.type) {
+	case ixgbe_mac_82599EB:
+	case ixgbe_mac_X540:
+		feature_list |= NETIF_F_SCTP_CSUM;
+		break;
+	default:
+		break;
 	}
+	if (data)
+		netdev->features |= feature_list;
+	else
+		netdev->features &= ~feature_list;
 
 	return 0;
 }
@@ -530,10 +538,20 @@ static void ixgbe_get_regs(struct net_de
 	regs_buff[32] = IXGBE_READ_REG(hw, IXGBE_FCTTV(1));
 	regs_buff[33] = IXGBE_READ_REG(hw, IXGBE_FCTTV(2));
 	regs_buff[34] = IXGBE_READ_REG(hw, IXGBE_FCTTV(3));
-	for (i = 0; i < 8; i++)
-		regs_buff[35 + i] = IXGBE_READ_REG(hw, IXGBE_FCRTL(i));
-	for (i = 0; i < 8; i++)
-		regs_buff[43 + i] = IXGBE_READ_REG(hw, IXGBE_FCRTH(i));
+	for (i = 0; i < 8; i++) {
+		switch (hw->mac.type) {
+		case ixgbe_mac_82598EB:
+			regs_buff[35 + i] = IXGBE_READ_REG(hw, IXGBE_FCRTL(i));
+			regs_buff[43 + i] = IXGBE_READ_REG(hw, IXGBE_FCRTH(i));
+			break;
+		case ixgbe_mac_82599EB:
+			regs_buff[35 + i] = IXGBE_READ_REG(hw, IXGBE_FCRTL_82599(i));
+			regs_buff[43 + i] = IXGBE_READ_REG(hw, IXGBE_FCRTH_82599(i));
+			break;
+		default:
+			break;
+		}
+	}
 	regs_buff[51] = IXGBE_READ_REG(hw, IXGBE_FCRTV);
 	regs_buff[52] = IXGBE_READ_REG(hw, IXGBE_TFCS);
 
@@ -615,6 +633,7 @@ static void ixgbe_get_regs(struct net_de
 	regs_buff[827] = IXGBE_READ_REG(hw, IXGBE_WUPM);
 	regs_buff[828] = IXGBE_READ_REG(hw, IXGBE_FHFT(0));
 
+	/* DCB */
 	regs_buff[829] = IXGBE_READ_REG(hw, IXGBE_RMCS);
 	regs_buff[830] = IXGBE_READ_REG(hw, IXGBE_DPMCS);
 	regs_buff[831] = IXGBE_READ_REG(hw, IXGBE_PDPMCS);
@@ -820,9 +839,10 @@ static void ixgbe_get_drvinfo(struct net
 	struct ixgbe_adapter *adapter = netdev_priv(netdev);
 	char firmware_version[32];
 
-	strncpy(drvinfo->driver, ixgbe_driver_name, sizeof(drvinfo->driver));
+	strncpy(drvinfo->driver, ixgbe_driver_name,
+	        sizeof(drvinfo->driver) - 1);
 	strncpy(drvinfo->version, ixgbe_driver_version,
-	        sizeof(drvinfo->version));
+	        sizeof(drvinfo->version) - 1);
 
 	snprintf(firmware_version, sizeof(firmware_version), "%d.%d-%d",
 	         (adapter->eeprom_version & 0xF000) >> 12,
@@ -905,13 +925,11 @@ static int ixgbe_set_ringparam(struct ne
 			memcpy(&temp_tx_ring[i], adapter->tx_ring[i],
 			       sizeof(struct ixgbe_ring));
 			temp_tx_ring[i].count = new_tx_count;
-			err = ixgbe_setup_tx_resources(adapter,
-			                               &temp_tx_ring[i]);
+			err = ixgbe_setup_tx_resources(&temp_tx_ring[i]);
 			if (err) {
 				while (i) {
 					i--;
-					ixgbe_free_tx_resources(adapter,
-					                      &temp_tx_ring[i]);
+					ixgbe_free_tx_resources(&temp_tx_ring[i]);
 				}
 				goto clear_reset;
 			}
@@ -930,13 +948,11 @@ static int ixgbe_set_ringparam(struct ne
 			memcpy(&temp_rx_ring[i], adapter->rx_ring[i],
 			       sizeof(struct ixgbe_ring));
 			temp_rx_ring[i].count = new_rx_count;
-			err = ixgbe_setup_rx_resources(adapter,
-			                               &temp_rx_ring[i]);
+			err = ixgbe_setup_rx_resources(&temp_rx_ring[i]);
 			if (err) {
 				while (i) {
 					i--;
-					ixgbe_free_rx_resources(adapter,
-					                      &temp_rx_ring[i]);
+					ixgbe_free_rx_resources(&temp_rx_ring[i]);
 				}
 				goto err_setup;
 			}
@@ -951,8 +967,7 @@ static int ixgbe_set_ringparam(struct ne
 		/* tx */
 		if (new_tx_count != adapter->tx_ring_count) {
 			for (i = 0; i < adapter->num_tx_queues; i++) {
-				ixgbe_free_tx_resources(adapter,
-				                        adapter->tx_ring[i]);
+				ixgbe_free_tx_resources(adapter->tx_ring[i]);
 				memcpy(adapter->tx_ring[i], &temp_tx_ring[i],
 				       sizeof(struct ixgbe_ring));
 			}
@@ -962,8 +977,7 @@ static int ixgbe_set_ringparam(struct ne
 		/* rx */
 		if (new_rx_count != adapter->rx_ring_count) {
 			for (i = 0; i < adapter->num_rx_queues; i++) {
-				ixgbe_free_rx_resources(adapter,
-				                        adapter->rx_ring[i]);
+				ixgbe_free_rx_resources(adapter->rx_ring[i]);
 				memcpy(adapter->rx_ring[i], &temp_rx_ring[i],
 				       sizeof(struct ixgbe_ring));
 			}
@@ -1144,7 +1158,7 @@ struct ixgbe_reg_test {
 #define TABLE64_TEST_HI	6
 
 /* default 82599 register test */
-static struct ixgbe_reg_test reg_test_82599[] = {
+static const struct ixgbe_reg_test reg_test_82599[] = {
 	{ IXGBE_FCRTL_82599(0), 1, PATTERN_TEST, 0x8007FFF0, 0x8007FFF0 },
 	{ IXGBE_FCRTH_82599(0), 1, PATTERN_TEST, 0x8007FFF0, 0x8007FFF0 },
 	{ IXGBE_PFCTOP, 1, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF },
@@ -1168,7 +1182,7 @@ static struct ixgbe_reg_test reg_test_82
 };
 
 /* default 82598 register test */
-static struct ixgbe_reg_test reg_test_82598[] = {
+static const struct ixgbe_reg_test reg_test_82598[] = {
 	{ IXGBE_FCRTL(0), 1, PATTERN_TEST, 0x8007FFF0, 0x8007FFF0 },
 	{ IXGBE_FCRTH(0), 1, PATTERN_TEST, 0x8007FFF0, 0x8007FFF0 },
 	{ IXGBE_PFCTOP, 1, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF },
@@ -1195,18 +1209,22 @@ static struct ixgbe_reg_test reg_test_82
 	{ 0, 0, 0, 0 }
 };
 
+static const u32 register_test_patterns[] = {
+	0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF
+};
+
 #define REG_PATTERN_TEST(R, M, W)                                             \
 {                                                                             \
 	u32 pat, val, before;                                                 \
-	const u32 _test[] = {0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF}; \
-	for (pat = 0; pat < ARRAY_SIZE(_test); pat++) {                       \
+	for (pat = 0; pat < ARRAY_SIZE(register_test_patterns); pat++) {      \
 		before = readl(adapter->hw.hw_addr + R);                      \
-		writel((_test[pat] & W), (adapter->hw.hw_addr + R));          \
+		writel((register_test_patterns[pat] & W),                     \
+		       (adapter->hw.hw_addr + R));                            \
 		val = readl(adapter->hw.hw_addr + R);                         \
-		if (val != (_test[pat] & W & M)) {                            \
-			e_err(drv, "pattern test reg %04X failed: got "   \
-			      "0x%08X expected 0x%08X\n",		      \
-			      R, val, (_test[pat] & W & M));                \
+		if (val != (register_test_patterns[pat] & W & M)) {           \
+			e_err(drv, "pattern test reg %04X failed: got "       \
+			      "0x%08X expected 0x%08X\n",                     \
+			      R, val, (register_test_patterns[pat] & W & M)); \
 			*data = R;                                            \
 			writel(before, adapter->hw.hw_addr + R);              \
 			return 1;                                             \
@@ -1233,16 +1251,24 @@ static struct ixgbe_reg_test reg_test_82
 
 static int ixgbe_reg_test(struct ixgbe_adapter *adapter, u64 *data)
 {
-	struct ixgbe_reg_test *test;
+	const struct ixgbe_reg_test *test;
 	u32 value, before, after;
 	u32 i, toggle;
 
-	if (adapter->hw.mac.type == ixgbe_mac_82599EB) {
-		toggle = 0x7FFFF30F;
-		test = reg_test_82599;
-	} else {
+	switch (adapter->hw.mac.type) {
+	case ixgbe_mac_82598EB:
 		toggle = 0x7FFFF3FF;
 		test = reg_test_82598;
+		break;
+	case ixgbe_mac_82599EB:
+	case ixgbe_mac_X540:
+		toggle = 0x7FFFF30F;
+		test = reg_test_82599;
+		break;
+	default:
+		*data = 1;
+		return 1;
+		break;
 	}
 
 	/*
@@ -1451,25 +1477,28 @@ static void ixgbe_free_desc_rings(struct
 	reg_ctl = IXGBE_READ_REG(hw, IXGBE_RXCTRL);
 	reg_ctl &= ~IXGBE_RXCTRL_RXEN;
 	IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, reg_ctl);
-	reg_ctl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(rx_ring->reg_idx));
-	reg_ctl &= ~IXGBE_RXDCTL_ENABLE;
-	IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(rx_ring->reg_idx), reg_ctl);
+	ixgbe_disable_rx_queue(adapter, rx_ring);
 
 	/* now Tx */
 	reg_ctl = IXGBE_READ_REG(hw, IXGBE_TXDCTL(tx_ring->reg_idx));
 	reg_ctl &= ~IXGBE_TXDCTL_ENABLE;
 	IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(tx_ring->reg_idx), reg_ctl);
 
-	if (hw->mac.type == ixgbe_mac_82599EB) {
+	switch (hw->mac.type) {
+	case ixgbe_mac_82599EB:
+	case ixgbe_mac_X540:
 		reg_ctl = IXGBE_READ_REG(hw, IXGBE_DMATXCTL);
 		reg_ctl &= ~IXGBE_DMATXCTL_TE;
 		IXGBE_WRITE_REG(hw, IXGBE_DMATXCTL, reg_ctl);
+		break;
+	default:
+		break;
 	}
 
 	ixgbe_reset(adapter);
 
-	ixgbe_free_tx_resources(adapter, &adapter->test_tx_ring);
-	ixgbe_free_rx_resources(adapter, &adapter->test_rx_ring);
+	ixgbe_free_tx_resources(&adapter->test_tx_ring);
+	ixgbe_free_rx_resources(&adapter->test_rx_ring);
 }
 
 static int ixgbe_setup_desc_rings(struct ixgbe_adapter *adapter)
@@ -1483,17 +1512,24 @@ static int ixgbe_setup_desc_rings(struct
 	/* Setup Tx descriptor ring and Tx buffers */
 	tx_ring->count = IXGBE_DEFAULT_TXD;
 	tx_ring->queue_index = 0;
+	tx_ring->dev = &adapter->pdev->dev;
+	tx_ring->netdev = adapter->netdev;
 	tx_ring->reg_idx = adapter->tx_ring[0]->reg_idx;
 	tx_ring->numa_node = adapter->node;
 
-	err = ixgbe_setup_tx_resources(adapter, tx_ring);
+	err = ixgbe_setup_tx_resources(tx_ring);
 	if (err)
 		return 1;
 
-	if (adapter->hw.mac.type == ixgbe_mac_82599EB) {
+	switch (adapter->hw.mac.type) {
+	case ixgbe_mac_82599EB:
+	case ixgbe_mac_X540:
 		reg_data = IXGBE_READ_REG(&adapter->hw, IXGBE_DMATXCTL);
 		reg_data |= IXGBE_DMATXCTL_TE;
 		IXGBE_WRITE_REG(&adapter->hw, IXGBE_DMATXCTL, reg_data);
+		break;
+	default:
+		break;
 	}
 
 	ixgbe_configure_tx_ring(adapter, tx_ring);
@@ -1501,11 +1537,13 @@ static int ixgbe_setup_desc_rings(struct
 	/* Setup Rx Descriptor ring and Rx buffers */
 	rx_ring->count = IXGBE_DEFAULT_RXD;
 	rx_ring->queue_index = 0;
+	rx_ring->dev = &adapter->pdev->dev;
+	rx_ring->netdev = adapter->netdev;
 	rx_ring->reg_idx = adapter->rx_ring[0]->reg_idx;
 	rx_ring->rx_buf_len = IXGBE_RXBUFFER_2048;
 	rx_ring->numa_node = adapter->node;
 
-	err = ixgbe_setup_rx_resources(adapter, rx_ring);
+	err = ixgbe_setup_rx_resources(rx_ring);
 	if (err) {
 		ret_val = 4;
 		goto err_nomem;
@@ -1604,8 +1642,7 @@ static int ixgbe_check_lbtest_frame(stru
 	return 13;
 }
 
-static u16 ixgbe_clean_test_rings(struct ixgbe_adapter *adapter,
-                                  struct ixgbe_ring *rx_ring,
+static u16 ixgbe_clean_test_rings(struct ixgbe_ring *rx_ring,
                                   struct ixgbe_ring *tx_ring,
                                   unsigned int size)
 {
@@ -1627,7 +1664,7 @@ static u16 ixgbe_clean_test_rings(struct
 		rx_buffer_info = &rx_ring->rx_buffer_info[rx_ntc];
 
 		/* unmap Rx buffer, will be remapped by alloc_rx_buffers */
-		dma_unmap_single(&adapter->pdev->dev,
+		dma_unmap_single(rx_ring->dev,
 		                 rx_buffer_info->dma,
 				 bufsz,
 				 DMA_FROM_DEVICE);
@@ -1639,7 +1676,7 @@ static u16 ixgbe_clean_test_rings(struct
 
 		/* unmap buffer on Tx side */
 		tx_buffer_info = &tx_ring->tx_buffer_info[tx_ntc];
-		ixgbe_unmap_and_free_tx_resource(adapter, tx_buffer_info);
+		ixgbe_unmap_and_free_tx_resource(tx_ring, tx_buffer_info);
 
 		/* increment Rx/Tx next to clean counters */
 		rx_ntc++;
@@ -1655,7 +1692,7 @@ static u16 ixgbe_clean_test_rings(struct
 	}
 
 	/* re-map buffers to ring, store next to clean values */
-	ixgbe_alloc_rx_buffers(adapter, rx_ring, count);
+	ixgbe_alloc_rx_buffers(rx_ring, count);
 	rx_ring->next_to_clean = rx_ntc;
 	tx_ring->next_to_clean = tx_ntc;
 
@@ -1699,7 +1736,6 @@ static int ixgbe_run_loopback_test(struc
 		for (i = 0; i < 64; i++) {
 			skb_get(skb);
 			tx_ret_val = ixgbe_xmit_frame_ring(skb,
-							   adapter->netdev,
 							   adapter,
 							   tx_ring);
 			if (tx_ret_val == NETDEV_TX_OK)
@@ -1714,8 +1750,7 @@ static int ixgbe_run_loopback_test(struc
 		/* allow 200 milliseconds for packets to go from Tx to Rx */
 		msleep(200);
 
-		good_cnt = ixgbe_clean_test_rings(adapter, rx_ring,
-						  tx_ring, size);
+		good_cnt = ixgbe_clean_test_rings(rx_ring, tx_ring, size);
 		if (good_cnt != 64) {
 			ret_val = 13;
 			break;
@@ -1847,7 +1882,25 @@ static int ixgbe_wol_exclusion(struct ix
 	struct ixgbe_hw *hw = &adapter->hw;
 	int retval = 1;
 
+	/* WOL not supported except for the following */
 	switch(hw->device_id) {
+	case IXGBE_DEV_ID_82599_SFP:
+		/* Only this subdevice supports WOL */
+		if (hw->subsystem_device_id != IXGBE_SUBDEV_ID_82599_SFP) {
+			wol->supported = 0;
+			break;
+		}
+		retval = 0;
+		break;
+	case IXGBE_DEV_ID_82599_COMBO_BACKPLANE:
+		/* All except this subdevice support WOL */
+		if (hw->subsystem_device_id ==
+		    IXGBE_SUBDEV_ID_82599_KX4_KR_MEZZ) {
+			wol->supported = 0;
+			break;
+		}
+		retval = 0;
+		break;
 	case IXGBE_DEV_ID_82599_KX4:
 		retval = 0;
 		break;
@@ -1985,6 +2038,41 @@ static int ixgbe_get_coalesce(struct net
 	return 0;
 }
 
+/*
+ * this function must be called before setting the new value of
+ * rx_itr_setting
+ */
+static bool ixgbe_update_rsc(struct ixgbe_adapter *adapter,
+			     struct ethtool_coalesce *ec)
+{
+	struct net_device *netdev = adapter->netdev;
+
+	if (!(adapter->flags2 & IXGBE_FLAG2_RSC_CAPABLE))
+		return false;
+
+	/* if interrupt rate is too high then disable RSC */
+	if (ec->rx_coalesce_usecs != 1 &&
+	    ec->rx_coalesce_usecs <= 1000000/IXGBE_MAX_RSC_INT_RATE) {
+		if (adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED) {
+			e_info(probe, "rx-usecs set too low, "
+				      "disabling RSC\n");
+			adapter->flags2 &= ~IXGBE_FLAG2_RSC_ENABLED;
+			return true;
+		}
+	} else {
+		/* check the feature flag value and enable RSC if necessary */
+		if ((netdev->features & NETIF_F_LRO) &&
+		    !(adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED)) {
+			e_info(probe, "rx-usecs set to %d, "
+				      "re-enabling RSC\n",
+			       ec->rx_coalesce_usecs);
+			adapter->flags2 |= IXGBE_FLAG2_RSC_ENABLED;
+			return true;
+		}
+	}
+	return false;
+}
+
 static int ixgbe_set_coalesce(struct net_device *netdev,
                               struct ethtool_coalesce *ec)
 {
@@ -2002,17 +2090,14 @@ static int ixgbe_set_coalesce(struct net
 		adapter->tx_ring[0]->work_limit = ec->tx_max_coalesced_frames_irq;
 
 	if (ec->rx_coalesce_usecs > 1) {
-		u32 max_int;
-		if (adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED)
-			max_int = IXGBE_MAX_RSC_INT_RATE;
-		else
-			max_int = IXGBE_MAX_INT_RATE;
-
 		/* check the limits */
-		if ((1000000/ec->rx_coalesce_usecs > max_int) ||
+		if ((1000000/ec->rx_coalesce_usecs > IXGBE_MAX_INT_RATE) ||
 		    (1000000/ec->rx_coalesce_usecs < IXGBE_MIN_INT_RATE))
 			return -EINVAL;
 
+		/* check the old value and enable RSC if necessary */
+		need_reset = ixgbe_update_rsc(adapter, ec);
+
 		/* store the value in ints/second */
 		adapter->rx_eitr_param = 1000000/ec->rx_coalesce_usecs;
 
@@ -2021,32 +2106,21 @@ static int ixgbe_set_coalesce(struct net
 		/* clear the lower bit as its used for dynamic state */
 		adapter->rx_itr_setting &= ~1;
 	} else if (ec->rx_coalesce_usecs == 1) {
+		/* check the old value and enable RSC if necessary */
+		need_reset = ixgbe_update_rsc(adapter, ec);
+
 		/* 1 means dynamic mode */
 		adapter->rx_eitr_param = 20000;
 		adapter->rx_itr_setting = 1;
 	} else {
+		/* check the old value and enable RSC if necessary */
+		need_reset = ixgbe_update_rsc(adapter, ec);
 		/*
 		 * any other value means disable eitr, which is best
 		 * served by setting the interrupt rate very high
 		 */
 		adapter->rx_eitr_param = IXGBE_MAX_INT_RATE;
 		adapter->rx_itr_setting = 0;
-
-		/*
-		 * if hardware RSC is enabled, disable it when
-		 * setting low latency mode, to avoid errata, assuming
-		 * that when the user set low latency mode they want
-		 * it at the cost of anything else
-		 */
-		if (adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED) {
-			adapter->flags2 &= ~IXGBE_FLAG2_RSC_ENABLED;
-			if (netdev->features & NETIF_F_LRO) {
-				netdev->features &= ~NETIF_F_LRO;
-				e_info(probe, "rx-usecs set to 0, "
-				       "disabling RSC\n");
-			}
-			need_reset = true;
-		}
 	}
 
 	if (ec->tx_coalesce_usecs > 1) {
@@ -2127,34 +2201,45 @@ static int ixgbe_set_flags(struct net_de
 	need_reset = (data & ETH_FLAG_RXVLAN) !=
 		     (netdev->features & NETIF_F_HW_VLAN_RX);
 
-	rc = ethtool_op_set_flags(netdev, data, ETH_FLAG_LRO |
+	rc = ethtool_op_set_flags(netdev, data, ETH_FLAG_LRO | ETH_FLAG_NTUPLE |
 					ETH_FLAG_RXVLAN | ETH_FLAG_TXVLAN);
 	if (rc)
 		return rc;
 
 	/* if state changes we need to update adapter->flags and reset */
-	if (adapter->flags2 & IXGBE_FLAG2_RSC_CAPABLE) {
-		/*
-		 * cast both to bool and verify if they are set the same
-		 * but only enable RSC if itr is non-zero, as
-		 * itr=0 and RSC are mutually exclusive
-		 */
-		if (((!!(data & ETH_FLAG_LRO)) !=
-		     (!!(adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED))) &&
-		    adapter->rx_itr_setting) {
+	if ((adapter->flags2 & IXGBE_FLAG2_RSC_CAPABLE) &&
+	    (!!(data & ETH_FLAG_LRO) !=
+	     !!(adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED))) {
+		if ((data & ETH_FLAG_LRO) &&
+		    (!adapter->rx_itr_setting ||
+		     (adapter->rx_itr_setting > IXGBE_MAX_RSC_INT_RATE))) {
+			e_info(probe, "rx-usecs set too low, "
+				      "not enabling RSC.\n");
+		} else {
 			adapter->flags2 ^= IXGBE_FLAG2_RSC_ENABLED;
 			switch (adapter->hw.mac.type) {
 			case ixgbe_mac_82599EB:
 				need_reset = true;
 				break;
+			case ixgbe_mac_X540: {
+				int i;
+				for (i = 0; i < adapter->num_rx_queues; i++) {
+					struct ixgbe_ring *ring =
+					                  adapter->rx_ring[i];
+					if (adapter->flags2 &
+					    IXGBE_FLAG2_RSC_ENABLED) {
+						ixgbe_configure_rscctl(adapter,
+						                       ring);
+					} else {
+						ixgbe_clear_rscctl(adapter,
+						                   ring);
+					}
+				}
+			}
+				break;
 			default:
 				break;
 			}
-		} else if (!adapter->rx_itr_setting) {
-			netdev->features &= ~NETIF_F_LRO;
-			if (data & ETH_FLAG_LRO)
-				e_info(probe, "rx-usecs set to 0, "
-				       "LRO/RSC cannot be enabled.\n");
 		}
 	}
 
@@ -2192,10 +2277,11 @@ static int ixgbe_set_rx_ntuple(struct ne
                                struct ethtool_rx_ntuple *cmd)
 {
 	struct ixgbe_adapter *adapter = netdev_priv(dev);
-	struct ethtool_rx_ntuple_flow_spec fs = cmd->fs;
-	struct ixgbe_atr_input input_struct;
+	struct ethtool_rx_ntuple_flow_spec *fs = &cmd->fs;
+	union ixgbe_atr_input input_struct;
 	struct ixgbe_atr_input_masks input_masks;
 	int target_queue;
+	int err;
 
 	if (adapter->hw.mac.type == ixgbe_mac_82598EB)
 		return -EOPNOTSUPP;
@@ -2204,67 +2290,122 @@ static int ixgbe_set_rx_ntuple(struct ne
 	 * Don't allow programming if the action is a queue greater than
 	 * the number of online Tx queues.
 	 */
-	if ((fs.action >= adapter->num_tx_queues) ||
-	    (fs.action < ETHTOOL_RXNTUPLE_ACTION_DROP))
+	if ((fs->action >= adapter->num_tx_queues) ||
+	    (fs->action < ETHTOOL_RXNTUPLE_ACTION_DROP))
 		return -EINVAL;
 
-	memset(&input_struct, 0, sizeof(struct ixgbe_atr_input));
+	memset(&input_struct, 0, sizeof(union ixgbe_atr_input));
 	memset(&input_masks, 0, sizeof(struct ixgbe_atr_input_masks));
 
-	input_masks.src_ip_mask = fs.m_u.tcp_ip4_spec.ip4src;
-	input_masks.dst_ip_mask = fs.m_u.tcp_ip4_spec.ip4dst;
-	input_masks.src_port_mask = fs.m_u.tcp_ip4_spec.psrc;
-	input_masks.dst_port_mask = fs.m_u.tcp_ip4_spec.pdst;
-	input_masks.vlan_id_mask = fs.vlan_tag_mask;
-	/* only use the lowest 2 bytes for flex bytes */
-	input_masks.data_mask = (fs.data_mask & 0xffff);
-
-	switch (fs.flow_type) {
+	/* record flow type */
+	switch (fs->flow_type) {
+	case IPV4_FLOW:
+		input_struct.formatted.flow_type = IXGBE_ATR_FLOW_TYPE_IPV4;
+		break;
 	case TCP_V4_FLOW:
-		ixgbe_atr_set_l4type_82599(&input_struct, IXGBE_ATR_L4TYPE_TCP);
+		input_struct.formatted.flow_type = IXGBE_ATR_FLOW_TYPE_TCPV4;
 		break;
 	case UDP_V4_FLOW:
-		ixgbe_atr_set_l4type_82599(&input_struct, IXGBE_ATR_L4TYPE_UDP);
+		input_struct.formatted.flow_type = IXGBE_ATR_FLOW_TYPE_UDPV4;
 		break;
 	case SCTP_V4_FLOW:
-		ixgbe_atr_set_l4type_82599(&input_struct, IXGBE_ATR_L4TYPE_SCTP);
+		input_struct.formatted.flow_type = IXGBE_ATR_FLOW_TYPE_SCTPV4;
 		break;
 	default:
 		return -1;
 	}
 
-	/* Mask bits from the inputs based on user-supplied mask */
-	ixgbe_atr_set_src_ipv4_82599(&input_struct,
-	            (fs.h_u.tcp_ip4_spec.ip4src & ~fs.m_u.tcp_ip4_spec.ip4src));
-	ixgbe_atr_set_dst_ipv4_82599(&input_struct,
-	            (fs.h_u.tcp_ip4_spec.ip4dst & ~fs.m_u.tcp_ip4_spec.ip4dst));
-	/* 82599 expects these to be byte-swapped for perfect filtering */
-	ixgbe_atr_set_src_port_82599(&input_struct,
-	       ((ntohs(fs.h_u.tcp_ip4_spec.psrc)) & ~fs.m_u.tcp_ip4_spec.psrc));
-	ixgbe_atr_set_dst_port_82599(&input_struct,
-	       ((ntohs(fs.h_u.tcp_ip4_spec.pdst)) & ~fs.m_u.tcp_ip4_spec.pdst));
+	/* copy vlan tag minus the CFI bit */
+	if ((fs->vlan_tag & 0xEFFF) || (~fs->vlan_tag_mask & 0xEFFF)) {
+		input_struct.formatted.vlan_id = htons(fs->vlan_tag & 0xEFFF);
+		if (!fs->vlan_tag_mask) {
+			input_masks.vlan_id_mask = htons(0xEFFF);
+		} else {
+			switch (~fs->vlan_tag_mask & 0xEFFF) {
+			/* all of these are valid vlan-mask values */
+			case 0xEFFF:
+			case 0xE000:
+			case 0x0FFF:
+			case 0x0000:
+				input_masks.vlan_id_mask =
+					htons(~fs->vlan_tag_mask);
+				break;
+			/* exit with error if vlan-mask is invalid */
+			default:
+				e_err(drv, "Partial VLAN ID or "
+				      "priority mask in vlan-mask is not "
+				      "supported by hardware\n");
+				return -1;
+			}
+		}
+	}
 
-	/* VLAN and Flex bytes are either completely masked or not */
-	if (!fs.vlan_tag_mask)
-		ixgbe_atr_set_vlan_id_82599(&input_struct, fs.vlan_tag);
+	/* make sure we only use the first 2 bytes of user data */
+	if ((fs->data & 0xFFFF) || (~fs->data_mask & 0xFFFF)) {
+		input_struct.formatted.flex_bytes = htons(fs->data & 0xFFFF);
+		if (!(fs->data_mask & 0xFFFF)) {
+			input_masks.flex_mask = 0xFFFF;
+		} else if (~fs->data_mask & 0xFFFF) {
+			e_err(drv, "Partial user-def-mask is not "
+			      "supported by hardware\n");
+			return -1;
+		}
+	}
 
-	if (!input_masks.data_mask)
-		/* make sure we only use the first 2 bytes of user data */
-		ixgbe_atr_set_flex_byte_82599(&input_struct,
-		                              (fs.data & 0xffff));
+	/*
+	 * Copy input into formatted structures
+	 *
+	 * These assignments are based on the following logic
+	 * If neither input or mask are set assume value is masked out.
+	 * If input is set, but mask is not mask should default to accept all.
+	 * If input is not set, but mask is set then mask likely results in 0.
+	 * If input is set and mask is set then assign both.
+	 */
+	if (fs->h_u.tcp_ip4_spec.ip4src || ~fs->m_u.tcp_ip4_spec.ip4src) {
+		input_struct.formatted.src_ip[0] = fs->h_u.tcp_ip4_spec.ip4src;
+		if (!fs->m_u.tcp_ip4_spec.ip4src)
+			input_masks.src_ip_mask[0] = 0xFFFFFFFF;
+		else
+			input_masks.src_ip_mask[0] =
+				~fs->m_u.tcp_ip4_spec.ip4src;
+	}
+	if (fs->h_u.tcp_ip4_spec.ip4dst || ~fs->m_u.tcp_ip4_spec.ip4dst) {
+		input_struct.formatted.dst_ip[0] = fs->h_u.tcp_ip4_spec.ip4dst;
+		if (!fs->m_u.tcp_ip4_spec.ip4dst)
+			input_masks.dst_ip_mask[0] = 0xFFFFFFFF;
+		else
+			input_masks.dst_ip_mask[0] =
+				~fs->m_u.tcp_ip4_spec.ip4dst;
+	}
+	if (fs->h_u.tcp_ip4_spec.psrc || ~fs->m_u.tcp_ip4_spec.psrc) {
+		input_struct.formatted.src_port = fs->h_u.tcp_ip4_spec.psrc;
+		if (!fs->m_u.tcp_ip4_spec.psrc)
+			input_masks.src_port_mask = 0xFFFF;
+		else
+			input_masks.src_port_mask = ~fs->m_u.tcp_ip4_spec.psrc;
+	}
+	if (fs->h_u.tcp_ip4_spec.pdst || ~fs->m_u.tcp_ip4_spec.pdst) {
+		input_struct.formatted.dst_port = fs->h_u.tcp_ip4_spec.pdst;
+		if (!fs->m_u.tcp_ip4_spec.pdst)
+			input_masks.dst_port_mask = 0xFFFF;
+		else
+			input_masks.dst_port_mask = ~fs->m_u.tcp_ip4_spec.pdst;
+	}
 
 	/* determine if we need to drop or route the packet */
-	if (fs.action == ETHTOOL_RXNTUPLE_ACTION_DROP)
+	if (fs->action == ETHTOOL_RXNTUPLE_ACTION_DROP)
 		target_queue = MAX_RX_QUEUES - 1;
 	else
-		target_queue = fs.action;
+		target_queue = fs->action;
 
 	spin_lock(&adapter->fdir_perfect_lock);
-	ixgbe_fdir_add_perfect_filter_82599(&adapter->hw, &input_struct,
-	                                    &input_masks, 0, target_queue);
+	err = ixgbe_fdir_add_perfect_filter_82599(&adapter->hw,
+						  &input_struct,
+						  &input_masks, 0,
+						  target_queue);
 	spin_unlock(&adapter->fdir_perfect_lock);
 
-	return 0;
+	return err ? -1 : 0;
 }
 
 static const struct ethtool_ops ixgbe_ethtool_ops = {
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/ixgbe/ixgbe_fcoe.c linux-libre-2.6.38-gnu1/drivers/net/ixgbe/ixgbe_fcoe.c
--- linux-libre-2.6.37-gnu1/drivers/net/ixgbe/ixgbe_fcoe.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/ixgbe/ixgbe_fcoe.c	2011-03-14 21:20:32.000000000 -0400
@@ -68,7 +68,7 @@ static inline bool ixgbe_rx_is_fcoe(unio
 static inline void ixgbe_fcoe_clear_ddp(struct ixgbe_fcoe_ddp *ddp)
 {
 	ddp->len = 0;
-	ddp->err = 0;
+	ddp->err = 1;
 	ddp->udl = NULL;
 	ddp->udp = 0UL;
 	ddp->sgl = NULL;
@@ -92,6 +92,7 @@ int ixgbe_fcoe_ddp_put(struct net_device
 	struct ixgbe_fcoe *fcoe;
 	struct ixgbe_adapter *adapter;
 	struct ixgbe_fcoe_ddp *ddp;
+	u32 fcbuff;
 
 	if (!netdev)
 		goto out_ddp_put;
@@ -115,7 +116,14 @@ int ixgbe_fcoe_ddp_put(struct net_device
 		IXGBE_WRITE_REG(&adapter->hw, IXGBE_FCBUFF, 0);
 		IXGBE_WRITE_REG(&adapter->hw, IXGBE_FCDMARW,
 				(xid | IXGBE_FCDMARW_WE));
+
+		/* guaranteed to be invalidated after 100us */
+		IXGBE_WRITE_REG(&adapter->hw, IXGBE_FCDMARW,
+				(xid | IXGBE_FCDMARW_RE));
+		fcbuff = IXGBE_READ_REG(&adapter->hw, IXGBE_FCBUFF);
 		spin_unlock_bh(&fcoe->lock);
+		if (fcbuff & IXGBE_FCBUFF_VALID)
+			udelay(100);
 	}
 	if (ddp->sgl)
 		pci_unmap_sg(adapter->pdev, ddp->sgl, ddp->sgc,
@@ -151,13 +159,13 @@ int ixgbe_fcoe_ddp_get(struct net_device
 	struct scatterlist *sg;
 	unsigned int i, j, dmacount;
 	unsigned int len;
-	static const unsigned int bufflen = 4096;
+	static const unsigned int bufflen = IXGBE_FCBUFF_MIN;
 	unsigned int firstoff = 0;
 	unsigned int lastsize;
 	unsigned int thisoff = 0;
 	unsigned int thislen = 0;
 	u32 fcbuff, fcdmarw, fcfltrw;
-	dma_addr_t addr;
+	dma_addr_t addr = 0;
 
 	if (!netdev || !sgl)
 		return 0;
@@ -168,6 +176,11 @@ int ixgbe_fcoe_ddp_get(struct net_device
 		return 0;
 	}
 
+	/* no DDP if we are already down or resetting */
+	if (test_bit(__IXGBE_DOWN, &adapter->state) ||
+	    test_bit(__IXGBE_RESETTING, &adapter->state))
+		return 0;
+
 	fcoe = &adapter->fcoe;
 	if (!fcoe->pool) {
 		e_warn(drv, "xid=0x%x no ddp pool for fcoe\n", xid);
@@ -241,6 +254,24 @@ int ixgbe_fcoe_ddp_get(struct net_device
 	/* only the last buffer may have non-full bufflen */
 	lastsize = thisoff + thislen;
 
+	/*
+	 * lastsize can not be buffer len.
+	 * If it is then adding another buffer with lastsize = 1.
+	 */
+	if (lastsize == bufflen) {
+		if (j >= IXGBE_BUFFCNT_MAX) {
+			e_err(drv, "xid=%x:%d,%d,%d:addr=%llx "
+				"not enough user buffers. We need an extra "
+				"buffer because lastsize is bufflen.\n",
+				xid, i, j, dmacount, (u64)addr);
+			goto out_noddp_free;
+		}
+
+		ddp->udl[j] = (u64)(fcoe->extra_ddp_buffer_dma);
+		j++;
+		lastsize = 1;
+	}
+
 	fcbuff = (IXGBE_FCBUFF_4KB << IXGBE_FCBUFF_BUFFSIZE_SHIFT);
 	fcbuff |= ((j & 0xff) << IXGBE_FCBUFF_BUFFCNT_SHIFT);
 	fcbuff |= (firstoff << IXGBE_FCBUFF_OFFSET_SHIFT);
@@ -519,6 +550,24 @@ void ixgbe_configure_fcoe(struct ixgbe_a
 			e_err(drv, "failed to allocated FCoE DDP pool\n");
 
 		spin_lock_init(&fcoe->lock);
+
+		/* Extra buffer to be shared by all DDPs for HW work around */
+		fcoe->extra_ddp_buffer = kmalloc(IXGBE_FCBUFF_MIN, GFP_ATOMIC);
+		if (fcoe->extra_ddp_buffer == NULL) {
+			e_err(drv, "failed to allocated extra DDP buffer\n");
+			goto out_extra_ddp_buffer_alloc;
+		}
+
+		fcoe->extra_ddp_buffer_dma =
+			dma_map_single(&adapter->pdev->dev,
+				       fcoe->extra_ddp_buffer,
+				       IXGBE_FCBUFF_MIN,
+				       DMA_FROM_DEVICE);
+		if (dma_mapping_error(&adapter->pdev->dev,
+				      fcoe->extra_ddp_buffer_dma)) {
+			e_err(drv, "failed to map extra DDP buffer\n");
+			goto out_extra_ddp_buffer_dma;
+		}
 	}
 
 	/* Enable L2 eth type filter for FCoE */
@@ -568,6 +617,14 @@ void ixgbe_configure_fcoe(struct ixgbe_a
 		}
 	}
 #endif
+
+	return;
+
+out_extra_ddp_buffer_dma:
+	kfree(fcoe->extra_ddp_buffer);
+out_extra_ddp_buffer_alloc:
+	pci_pool_destroy(fcoe->pool);
+	fcoe->pool = NULL;
 }
 
 /**
@@ -587,6 +644,11 @@ void ixgbe_cleanup_fcoe(struct ixgbe_ada
 	if (fcoe->pool) {
 		for (i = 0; i < IXGBE_FCOE_DDP_MAX; i++)
 			ixgbe_fcoe_ddp_put(adapter->netdev, i);
+		dma_unmap_single(&adapter->pdev->dev,
+				 fcoe->extra_ddp_buffer_dma,
+				 IXGBE_FCBUFF_MIN,
+				 DMA_FROM_DEVICE);
+		kfree(fcoe->extra_ddp_buffer);
 		pci_pool_destroy(fcoe->pool);
 		fcoe->pool = NULL;
 	}
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/ixgbe/ixgbe_fcoe.h linux-libre-2.6.38-gnu1/drivers/net/ixgbe/ixgbe_fcoe.h
--- linux-libre-2.6.37-gnu1/drivers/net/ixgbe/ixgbe_fcoe.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/ixgbe/ixgbe_fcoe.h	2011-03-14 21:20:32.000000000 -0400
@@ -70,6 +70,8 @@ struct ixgbe_fcoe {
 	spinlock_t lock;
 	struct pci_pool *pool;
 	struct ixgbe_fcoe_ddp ddp[IXGBE_FCOE_DDP_MAX];
+	unsigned char *extra_ddp_buffer;
+	dma_addr_t extra_ddp_buffer_dma;
 };
 
 #endif /* _IXGBE_FCOE_H */
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/ixgbe/ixgbe.h linux-libre-2.6.38-gnu1/drivers/net/ixgbe/ixgbe.h
--- linux-libre-2.6.37-gnu1/drivers/net/ixgbe/ixgbe.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/ixgbe/ixgbe.h	2011-03-14 21:20:32.000000000 -0400
@@ -61,10 +61,8 @@
 #define IXGBE_MIN_RXD			     64
 
 /* flow control */
-#define IXGBE_DEFAULT_FCRTL		0x10000
 #define IXGBE_MIN_FCRTL			   0x40
 #define IXGBE_MAX_FCRTL			0x7FF80
-#define IXGBE_DEFAULT_FCRTH		0x20000
 #define IXGBE_MIN_FCRTH			  0x600
 #define IXGBE_MAX_FCRTH			0x7FFF0
 #define IXGBE_DEFAULT_FCPAUSE		 0xFFFF
@@ -130,7 +128,9 @@ struct ixgbe_tx_buffer {
 	unsigned long time_stamp;
 	u16 length;
 	u16 next_to_watch;
-	u16 mapped_as_page;
+	unsigned int bytecount;
+	u16 gso_segs;
+	u8 mapped_as_page;
 };
 
 struct ixgbe_rx_buffer {
@@ -146,12 +146,56 @@ struct ixgbe_queue_stats {
 	u64 bytes;
 };
 
+struct ixgbe_tx_queue_stats {
+	u64 restart_queue;
+	u64 tx_busy;
+	u64 completed;
+	u64 tx_done_old;
+};
+
+struct ixgbe_rx_queue_stats {
+	u64 rsc_count;
+	u64 rsc_flush;
+	u64 non_eop_descs;
+	u64 alloc_rx_page_failed;
+	u64 alloc_rx_buff_failed;
+};
+
+enum ixbge_ring_state_t {
+	__IXGBE_TX_FDIR_INIT_DONE,
+	__IXGBE_TX_DETECT_HANG,
+	__IXGBE_HANG_CHECK_ARMED,
+	__IXGBE_RX_PS_ENABLED,
+	__IXGBE_RX_RSC_ENABLED,
+};
+
+#define ring_is_ps_enabled(ring) \
+	test_bit(__IXGBE_RX_PS_ENABLED, &(ring)->state)
+#define set_ring_ps_enabled(ring) \
+	set_bit(__IXGBE_RX_PS_ENABLED, &(ring)->state)
+#define clear_ring_ps_enabled(ring) \
+	clear_bit(__IXGBE_RX_PS_ENABLED, &(ring)->state)
+#define check_for_tx_hang(ring) \
+	test_bit(__IXGBE_TX_DETECT_HANG, &(ring)->state)
+#define set_check_for_tx_hang(ring) \
+	set_bit(__IXGBE_TX_DETECT_HANG, &(ring)->state)
+#define clear_check_for_tx_hang(ring) \
+	clear_bit(__IXGBE_TX_DETECT_HANG, &(ring)->state)
+#define ring_is_rsc_enabled(ring) \
+	test_bit(__IXGBE_RX_RSC_ENABLED, &(ring)->state)
+#define set_ring_rsc_enabled(ring) \
+	set_bit(__IXGBE_RX_RSC_ENABLED, &(ring)->state)
+#define clear_ring_rsc_enabled(ring) \
+	clear_bit(__IXGBE_RX_RSC_ENABLED, &(ring)->state)
 struct ixgbe_ring {
 	void *desc;			/* descriptor ring memory */
+	struct device *dev;             /* device for DMA mapping */
+	struct net_device *netdev;      /* netdev ring belongs to */
 	union {
 		struct ixgbe_tx_buffer *tx_buffer_info;
 		struct ixgbe_rx_buffer *rx_buffer_info;
 	};
+	unsigned long state;
 	u8 atr_sample_rate;
 	u8 atr_count;
 	u16 count;			/* amount of descriptors */
@@ -160,38 +204,30 @@ struct ixgbe_ring {
 	u16 next_to_clean;
 
 	u8 queue_index; /* needed for multiqueue queue management */
-
-#define IXGBE_RING_RX_PS_ENABLED                (u8)(1)
-	u8 flags;			/* per ring feature flags */
-	u16 head;
-	u16 tail;
-
-	unsigned int total_bytes;
-	unsigned int total_packets;
-
-#ifdef CONFIG_IXGBE_DCA
-	/* cpu for tx queue */
-	int cpu;
-#endif
-
-	u16 work_limit;			/* max work per interrupt */
-	u16 reg_idx;			/* holds the special value that gets
+	u8 reg_idx;			/* holds the special value that gets
 					 * the hardware register offset
 					 * associated with this ring, which is
 					 * different for DCB and RSS modes
 					 */
 
+	u16 work_limit;			/* max work per interrupt */
+
+	u8 __iomem *tail;
+
+	unsigned int total_bytes;
+	unsigned int total_packets;
+
 	struct ixgbe_queue_stats stats;
 	struct u64_stats_sync syncp;
+	union {
+		struct ixgbe_tx_queue_stats tx_stats;
+		struct ixgbe_rx_queue_stats rx_stats;
+	};
 	int numa_node;
-	unsigned long reinit_state;
-	u64 rsc_count;			/* stat for coalesced packets */
-	u64 rsc_flush;			/* stats for flushed packets */
-	u32 restart_queue;		/* track tx queue restarts */
-	u32 non_eop_descs;		/* track hardware descriptor chaining */
-
 	unsigned int size;		/* length in bytes */
 	dma_addr_t dma;			/* phys. address of descriptor ring */
+	struct rcu_head rcu;
+	struct ixgbe_q_vector *q_vector; /* back-pointer to host q_vector */
 } ____cacheline_internodealigned_in_smp;
 
 enum ixgbe_ring_f_enum {
@@ -237,6 +273,9 @@ struct ixgbe_q_vector {
 	unsigned int v_idx; /* index of q_vector within array, also used for
 	                     * finding the bit in EICR and friends that
 	                     * represents the vector for this ring */
+#ifdef CONFIG_IXGBE_DCA
+	int cpu;	    /* CPU for DCA */
+#endif
 	struct napi_struct napi;
 	DECLARE_BITMAP(rxr_idx, MAX_RX_QUEUES); /* Rx ring indices */
 	DECLARE_BITMAP(txr_idx, MAX_TX_QUEUES); /* Tx ring indices */
@@ -246,6 +285,7 @@ struct ixgbe_q_vector {
 	u8 rx_itr;
 	u32 eitr;
 	cpumask_var_t affinity_mask;
+	char name[IFNAMSIZ + 9];
 };
 
 /* Helper macros to switch between ints/sec and what the register uses.
@@ -294,7 +334,6 @@ struct ixgbe_adapter {
 	u16 bd_number;
 	struct work_struct reset_task;
 	struct ixgbe_q_vector *q_vector[MAX_MSIX_Q_VECTORS];
-	char name[MAX_MSIX_COUNT][IFNAMSIZ + 9];
 	struct ixgbe_dcb_config dcb_cfg;
 	struct ixgbe_dcb_config temp_dcb_cfg;
 	u8 dcb_set_bitmap;
@@ -417,6 +456,7 @@ struct ixgbe_adapter {
 	int node;
 	struct work_struct check_overtemp_task;
 	u32 interrupt_event;
+	char lsc_int_name[IFNAMSIZ + 9];
 
 	/* SR-IOV */
 	DECLARE_BITMAP(active_vfs, IXGBE_MAX_VF_FUNCTIONS);
@@ -428,17 +468,25 @@ enum ixbge_state_t {
 	__IXGBE_TESTING,
 	__IXGBE_RESETTING,
 	__IXGBE_DOWN,
-	__IXGBE_FDIR_INIT_DONE,
 	__IXGBE_SFP_MODULE_NOT_FOUND
 };
 
+struct ixgbe_rsc_cb {
+	dma_addr_t dma;
+	u16 skb_cnt;
+	bool delay_unmap;
+};
+#define IXGBE_RSC_CB(skb) ((struct ixgbe_rsc_cb *)(skb)->cb)
+
 enum ixgbe_boards {
 	board_82598,
 	board_82599,
+	board_X540,
 };
 
 extern struct ixgbe_info ixgbe_82598_info;
 extern struct ixgbe_info ixgbe_82599_info;
+extern struct ixgbe_info ixgbe_X540_info;
 #ifdef CONFIG_IXGBE_DCB
 extern const struct dcbnl_rtnl_ops dcbnl_ops;
 extern int ixgbe_copy_dcb_cfg(struct ixgbe_dcb_config *src_dcb_cfg,
@@ -454,50 +502,41 @@ extern void ixgbe_down(struct ixgbe_adap
 extern void ixgbe_reinit_locked(struct ixgbe_adapter *adapter);
 extern void ixgbe_reset(struct ixgbe_adapter *adapter);
 extern void ixgbe_set_ethtool_ops(struct net_device *netdev);
-extern int ixgbe_setup_rx_resources(struct ixgbe_adapter *, struct ixgbe_ring *);
-extern int ixgbe_setup_tx_resources(struct ixgbe_adapter *, struct ixgbe_ring *);
-extern void ixgbe_free_rx_resources(struct ixgbe_adapter *, struct ixgbe_ring *);
-extern void ixgbe_free_tx_resources(struct ixgbe_adapter *, struct ixgbe_ring *);
+extern int ixgbe_setup_rx_resources(struct ixgbe_ring *);
+extern int ixgbe_setup_tx_resources(struct ixgbe_ring *);
+extern void ixgbe_free_rx_resources(struct ixgbe_ring *);
+extern void ixgbe_free_tx_resources(struct ixgbe_ring *);
 extern void ixgbe_configure_rx_ring(struct ixgbe_adapter *,struct ixgbe_ring *);
 extern void ixgbe_configure_tx_ring(struct ixgbe_adapter *,struct ixgbe_ring *);
+extern void ixgbe_disable_rx_queue(struct ixgbe_adapter *adapter,
+				   struct ixgbe_ring *);
 extern void ixgbe_update_stats(struct ixgbe_adapter *adapter);
 extern int ixgbe_init_interrupt_scheme(struct ixgbe_adapter *adapter);
 extern void ixgbe_clear_interrupt_scheme(struct ixgbe_adapter *adapter);
 extern netdev_tx_t ixgbe_xmit_frame_ring(struct sk_buff *,
-					 struct net_device *,
 					 struct ixgbe_adapter *,
 					 struct ixgbe_ring *);
-extern void ixgbe_unmap_and_free_tx_resource(struct ixgbe_adapter *,
+extern void ixgbe_unmap_and_free_tx_resource(struct ixgbe_ring *,
                                              struct ixgbe_tx_buffer *);
-extern void ixgbe_alloc_rx_buffers(struct ixgbe_adapter *adapter,
-                                   struct ixgbe_ring *rx_ring,
-                                   int cleaned_count);
+extern void ixgbe_alloc_rx_buffers(struct ixgbe_ring *, u16);
 extern void ixgbe_write_eitr(struct ixgbe_q_vector *);
 extern int ethtool_ioctl(struct ifreq *ifr);
+extern u8 ixgbe_dcb_txq_to_tc(struct ixgbe_adapter *adapter, u8 index);
 extern s32 ixgbe_reinit_fdir_tables_82599(struct ixgbe_hw *hw);
 extern s32 ixgbe_init_fdir_signature_82599(struct ixgbe_hw *hw, u32 pballoc);
 extern s32 ixgbe_init_fdir_perfect_82599(struct ixgbe_hw *hw, u32 pballoc);
 extern s32 ixgbe_fdir_add_signature_filter_82599(struct ixgbe_hw *hw,
-                                                 struct ixgbe_atr_input *input,
+						 union ixgbe_atr_hash_dword input,
+						 union ixgbe_atr_hash_dword common,
                                                  u8 queue);
 extern s32 ixgbe_fdir_add_perfect_filter_82599(struct ixgbe_hw *hw,
-                                      struct ixgbe_atr_input *input,
+                                      union ixgbe_atr_input *input,
                                       struct ixgbe_atr_input_masks *input_masks,
                                       u16 soft_id, u8 queue);
-extern s32 ixgbe_atr_set_vlan_id_82599(struct ixgbe_atr_input *input,
-                                       u16 vlan_id);
-extern s32 ixgbe_atr_set_src_ipv4_82599(struct ixgbe_atr_input *input,
-                                        u32 src_addr);
-extern s32 ixgbe_atr_set_dst_ipv4_82599(struct ixgbe_atr_input *input,
-                                        u32 dst_addr);
-extern s32 ixgbe_atr_set_src_port_82599(struct ixgbe_atr_input *input,
-                                        u16 src_port);
-extern s32 ixgbe_atr_set_dst_port_82599(struct ixgbe_atr_input *input,
-                                        u16 dst_port);
-extern s32 ixgbe_atr_set_flex_byte_82599(struct ixgbe_atr_input *input,
-                                         u16 flex_byte);
-extern s32 ixgbe_atr_set_l4type_82599(struct ixgbe_atr_input *input,
-                                      u8 l4type);
+extern void ixgbe_configure_rscctl(struct ixgbe_adapter *adapter,
+                                   struct ixgbe_ring *ring);
+extern void ixgbe_clear_rscctl(struct ixgbe_adapter *adapter,
+                               struct ixgbe_ring *ring);
 extern void ixgbe_set_rx_mode(struct net_device *netdev);
 #ifdef IXGBE_FCOE
 extern void ixgbe_configure_fcoe(struct ixgbe_adapter *adapter);
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/ixgbe/ixgbe_main.c linux-libre-2.6.38-gnu1/drivers/net/ixgbe/ixgbe_main.c
--- linux-libre-2.6.37-gnu1/drivers/net/ixgbe/ixgbe_main.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/ixgbe/ixgbe_main.c	2011-03-14 21:20:32.000000000 -0400
@@ -52,13 +52,14 @@ char ixgbe_driver_name[] = "ixgbe";
 static const char ixgbe_driver_string[] =
 			      "Intel(R) 10 Gigabit PCI Express Network Driver";
 
-#define DRV_VERSION "2.0.84-k2"
+#define DRV_VERSION "3.2.9-k2"
 const char ixgbe_driver_version[] = DRV_VERSION;
 static char ixgbe_copyright[] = "Copyright (c) 1999-2010 Intel Corporation.";
 
 static const struct ixgbe_info *ixgbe_info_tbl[] = {
 	[board_82598] = &ixgbe_82598_info,
 	[board_82599] = &ixgbe_82599_info,
+	[board_X540] = &ixgbe_X540_info,
 };
 
 /* ixgbe_pci_tbl - PCI Device ID Table
@@ -108,10 +109,16 @@ static DEFINE_PCI_DEVICE_TABLE(ixgbe_pci
 	 board_82599 },
 	{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_CX4),
 	 board_82599 },
+	{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_BACKPLANE_FCOE),
+	 board_82599 },
+	{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_SFP_FCOE),
+	 board_82599 },
 	{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_T3_LOM),
 	 board_82599 },
 	{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_COMBO_BACKPLANE),
 	 board_82599 },
+	{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X540T),
+	 board_X540 },
 
 	/* required last entry */
 	{0, }
@@ -560,6 +567,7 @@ static void ixgbe_set_ivar(struct ixgbe_
 		IXGBE_WRITE_REG(hw, IXGBE_IVAR(index), ivar);
 		break;
 	case ixgbe_mac_82599EB:
+	case ixgbe_mac_X540:
 		if (direction == -1) {
 			/* other causes */
 			msix_vector |= IXGBE_IVAR_ALLOC_VAL;
@@ -589,29 +597,34 @@ static inline void ixgbe_irq_rearm_queue
 {
 	u32 mask;
 
-	if (adapter->hw.mac.type == ixgbe_mac_82598EB) {
+	switch (adapter->hw.mac.type) {
+	case ixgbe_mac_82598EB:
 		mask = (IXGBE_EIMS_RTX_QUEUE & qmask);
 		IXGBE_WRITE_REG(&adapter->hw, IXGBE_EICS, mask);
-	} else {
+		break;
+	case ixgbe_mac_82599EB:
+	case ixgbe_mac_X540:
 		mask = (qmask & 0xFFFFFFFF);
 		IXGBE_WRITE_REG(&adapter->hw, IXGBE_EICS_EX(0), mask);
 		mask = (qmask >> 32);
 		IXGBE_WRITE_REG(&adapter->hw, IXGBE_EICS_EX(1), mask);
+		break;
+	default:
+		break;
 	}
 }
 
-void ixgbe_unmap_and_free_tx_resource(struct ixgbe_adapter *adapter,
-				      struct ixgbe_tx_buffer
-				      *tx_buffer_info)
+void ixgbe_unmap_and_free_tx_resource(struct ixgbe_ring *tx_ring,
+				      struct ixgbe_tx_buffer *tx_buffer_info)
 {
 	if (tx_buffer_info->dma) {
 		if (tx_buffer_info->mapped_as_page)
-			dma_unmap_page(&adapter->pdev->dev,
+			dma_unmap_page(tx_ring->dev,
 				       tx_buffer_info->dma,
 				       tx_buffer_info->length,
 				       DMA_TO_DEVICE);
 		else
-			dma_unmap_single(&adapter->pdev->dev,
+			dma_unmap_single(tx_ring->dev,
 					 tx_buffer_info->dma,
 					 tx_buffer_info->length,
 					 DMA_TO_DEVICE);
@@ -626,92 +639,166 @@ void ixgbe_unmap_and_free_tx_resource(st
 }
 
 /**
- * ixgbe_tx_xon_state - check the tx ring xon state
- * @adapter: the ixgbe adapter
- * @tx_ring: the corresponding tx_ring
+ * ixgbe_dcb_txq_to_tc - convert a reg index to a traffic class
+ * @adapter: driver private struct
+ * @index: reg idx of queue to query (0-127)
  *
- * If not in DCB mode, checks TFCS.TXOFF, otherwise, find out the
- * corresponding TC of this tx_ring when checking TFCS.
+ * Helper function to determine the traffic index for a paticular
+ * register index.
  *
- * Returns : true if in xon state (currently not paused)
+ * Returns : a tc index for use in range 0-7, or 0-3
  */
-static inline bool ixgbe_tx_xon_state(struct ixgbe_adapter *adapter,
-				      struct ixgbe_ring *tx_ring)
+u8 ixgbe_dcb_txq_to_tc(struct ixgbe_adapter *adapter, u8 reg_idx)
 {
-	u32 txoff = IXGBE_TFCS_TXOFF;
+	int tc = -1;
+	int dcb_i = adapter->ring_feature[RING_F_DCB].indices;
 
-#ifdef CONFIG_IXGBE_DCB
-	if (adapter->dcb_cfg.pfc_mode_enable) {
-		int tc;
-		int reg_idx = tx_ring->reg_idx;
-		int dcb_i = adapter->ring_feature[RING_F_DCB].indices;
+	/* if DCB is not enabled the queues have no TC */
+	if (!(adapter->flags & IXGBE_FLAG_DCB_ENABLED))
+		return tc;
 
-		switch (adapter->hw.mac.type) {
+	/* check valid range */
+	if (reg_idx >= adapter->hw.mac.max_tx_queues)
+		return tc;
+
+	switch (adapter->hw.mac.type) {
+	case ixgbe_mac_82598EB:
+		tc = reg_idx >> 2;
+		break;
+	default:
+		if (dcb_i != 4 && dcb_i != 8)
+			break;
+
+		/* if VMDq is enabled the lowest order bits determine TC */
+		if (adapter->flags & (IXGBE_FLAG_SRIOV_ENABLED |
+				      IXGBE_FLAG_VMDQ_ENABLED)) {
+			tc = reg_idx & (dcb_i - 1);
+			break;
+		}
+
+		/*
+		 * Convert the reg_idx into the correct TC. This bitmask
+		 * targets the last full 32 ring traffic class and assigns
+		 * it a value of 1. From there the rest of the rings are
+		 * based on shifting the mask further up to include the
+		 * reg_idx / 16 and then reg_idx / 8. It assumes dcB_i
+		 * will only ever be 8 or 4 and that reg_idx will never
+		 * be greater then 128. The code without the power of 2
+		 * optimizations would be:
+		 * (((reg_idx % 32) + 32) * dcb_i) >> (9 - reg_idx / 32)
+		 */
+		tc = ((reg_idx & 0X1F) + 0x20) * dcb_i;
+		tc >>= 9 - (reg_idx >> 5);
+	}
+
+	return tc;
+}
+
+static void ixgbe_update_xoff_received(struct ixgbe_adapter *adapter)
+{
+	struct ixgbe_hw *hw = &adapter->hw;
+	struct ixgbe_hw_stats *hwstats = &adapter->stats;
+	u32 data = 0;
+	u32 xoff[8] = {0};
+	int i;
+
+	if ((hw->fc.current_mode == ixgbe_fc_full) ||
+	    (hw->fc.current_mode == ixgbe_fc_rx_pause)) {
+		switch (hw->mac.type) {
 		case ixgbe_mac_82598EB:
-			tc = reg_idx >> 2;
-			txoff = IXGBE_TFCS_TXOFF0;
+			data = IXGBE_READ_REG(hw, IXGBE_LXOFFRXC);
 			break;
-		case ixgbe_mac_82599EB:
-			tc = 0;
-			txoff = IXGBE_TFCS_TXOFF;
-			if (dcb_i == 8) {
-				/* TC0, TC1 */
-				tc = reg_idx >> 5;
-				if (tc == 2) /* TC2, TC3 */
-					tc += (reg_idx - 64) >> 4;
-				else if (tc == 3) /* TC4, TC5, TC6, TC7 */
-					tc += 1 + ((reg_idx - 96) >> 3);
-			} else if (dcb_i == 4) {
-				/* TC0, TC1 */
-				tc = reg_idx >> 6;
-				if (tc == 1) {
-					tc += (reg_idx - 64) >> 5;
-					if (tc == 2) /* TC2, TC3 */
-						tc += (reg_idx - 96) >> 4;
-				}
-			}
+		default:
+			data = IXGBE_READ_REG(hw, IXGBE_LXOFFRXCNT);
+		}
+		hwstats->lxoffrxc += data;
+
+		/* refill credits (no tx hang) if we received xoff */
+		if (!data)
+			return;
+
+		for (i = 0; i < adapter->num_tx_queues; i++)
+			clear_bit(__IXGBE_HANG_CHECK_ARMED,
+				  &adapter->tx_ring[i]->state);
+		return;
+	} else if (!(adapter->dcb_cfg.pfc_mode_enable))
+		return;
+
+	/* update stats for each tc, only valid with PFC enabled */
+	for (i = 0; i < MAX_TX_PACKET_BUFFERS; i++) {
+		switch (hw->mac.type) {
+		case ixgbe_mac_82598EB:
+			xoff[i] = IXGBE_READ_REG(hw, IXGBE_PXOFFRXC(i));
 			break;
 		default:
-			tc = 0;
+			xoff[i] = IXGBE_READ_REG(hw, IXGBE_PXOFFRXCNT(i));
 		}
-		txoff <<= tc;
+		hwstats->pxoffrxc[i] += xoff[i];
+	}
+
+	/* disarm tx queues that have received xoff frames */
+	for (i = 0; i < adapter->num_tx_queues; i++) {
+		struct ixgbe_ring *tx_ring = adapter->tx_ring[i];
+		u32 tc = ixgbe_dcb_txq_to_tc(adapter, tx_ring->reg_idx);
+
+		if (xoff[tc])
+			clear_bit(__IXGBE_HANG_CHECK_ARMED, &tx_ring->state);
 	}
-#endif
-	return IXGBE_READ_REG(&adapter->hw, IXGBE_TFCS) & txoff;
 }
 
-static inline bool ixgbe_check_tx_hang(struct ixgbe_adapter *adapter,
-				       struct ixgbe_ring *tx_ring,
-				       unsigned int eop)
+static u64 ixgbe_get_tx_completed(struct ixgbe_ring *ring)
+{
+	return ring->tx_stats.completed;
+}
+
+static u64 ixgbe_get_tx_pending(struct ixgbe_ring *ring)
 {
+	struct ixgbe_adapter *adapter = netdev_priv(ring->netdev);
 	struct ixgbe_hw *hw = &adapter->hw;
 
-	/* Detect a transmit hang in hardware, this serializes the
-	 * check with the clearing of time_stamp and movement of eop */
-	adapter->detect_tx_hung = false;
-	if (tx_ring->tx_buffer_info[eop].time_stamp &&
-	    time_after(jiffies, tx_ring->tx_buffer_info[eop].time_stamp + HZ) &&
-	    ixgbe_tx_xon_state(adapter, tx_ring)) {
-		/* detected Tx unit hang */
-		union ixgbe_adv_tx_desc *tx_desc;
-		tx_desc = IXGBE_TX_DESC_ADV(tx_ring, eop);
-		e_err(drv, "Detected Tx Unit Hang\n"
-		      "  Tx Queue             <%d>\n"
-		      "  TDH, TDT             <%x>, <%x>\n"
-		      "  next_to_use          <%x>\n"
-		      "  next_to_clean        <%x>\n"
-		      "tx_buffer_info[next_to_clean]\n"
-		      "  time_stamp           <%lx>\n"
-		      "  jiffies              <%lx>\n",
-		      tx_ring->queue_index,
-		      IXGBE_READ_REG(hw, tx_ring->head),
-		      IXGBE_READ_REG(hw, tx_ring->tail),
-		      tx_ring->next_to_use, eop,
-		      tx_ring->tx_buffer_info[eop].time_stamp, jiffies);
-		return true;
+	u32 head = IXGBE_READ_REG(hw, IXGBE_TDH(ring->reg_idx));
+	u32 tail = IXGBE_READ_REG(hw, IXGBE_TDT(ring->reg_idx));
+
+	if (head != tail)
+		return (head < tail) ?
+			tail - head : (tail + ring->count - head);
+
+	return 0;
+}
+
+static inline bool ixgbe_check_tx_hang(struct ixgbe_ring *tx_ring)
+{
+	u32 tx_done = ixgbe_get_tx_completed(tx_ring);
+	u32 tx_done_old = tx_ring->tx_stats.tx_done_old;
+	u32 tx_pending = ixgbe_get_tx_pending(tx_ring);
+	bool ret = false;
+
+	clear_check_for_tx_hang(tx_ring);
+
+	/*
+	 * Check for a hung queue, but be thorough. This verifies
+	 * that a transmit has been completed since the previous
+	 * check AND there is at least one packet pending. The
+	 * ARMED bit is set to indicate a potential hang. The
+	 * bit is cleared if a pause frame is received to remove
+	 * false hang detection due to PFC or 802.3x frames. By
+	 * requiring this to fail twice we avoid races with
+	 * pfc clearing the ARMED bit and conditions where we
+	 * run the check_tx_hang logic with a transmit completion
+	 * pending but without time to complete it yet.
+	 */
+	if ((tx_done_old == tx_done) && tx_pending) {
+		/* make sure it is true for two checks in a row */
+		ret = test_and_set_bit(__IXGBE_HANG_CHECK_ARMED,
+				       &tx_ring->state);
+	} else {
+		/* update completed stats and continue */
+		tx_ring->tx_stats.tx_done_old = tx_done;
+		/* reset the countdown */
+		clear_bit(__IXGBE_HANG_CHECK_ARMED, &tx_ring->state);
 	}
 
-	return false;
+	return ret;
 }
 
 #define IXGBE_MAX_TXD_PWR       14
@@ -734,11 +821,10 @@ static bool ixgbe_clean_tx_irq(struct ix
 			       struct ixgbe_ring *tx_ring)
 {
 	struct ixgbe_adapter *adapter = q_vector->adapter;
-	struct net_device *netdev = adapter->netdev;
 	union ixgbe_adv_tx_desc *tx_desc, *eop_desc;
 	struct ixgbe_tx_buffer *tx_buffer_info;
-	unsigned int i, eop, count = 0;
 	unsigned int total_bytes = 0, total_packets = 0;
+	u16 i, eop, count = 0;
 
 	i = tx_ring->next_to_clean;
 	eop = tx_ring->tx_buffer_info[i].next_to_watch;
@@ -749,148 +835,182 @@ static bool ixgbe_clean_tx_irq(struct ix
 		bool cleaned = false;
 		rmb(); /* read buffer_info after eop_desc */
 		for ( ; !cleaned; count++) {
-			struct sk_buff *skb;
 			tx_desc = IXGBE_TX_DESC_ADV(tx_ring, i);
 			tx_buffer_info = &tx_ring->tx_buffer_info[i];
-			cleaned = (i == eop);
-			skb = tx_buffer_info->skb;
-
-			if (cleaned && skb) {
-				unsigned int segs, bytecount;
-				unsigned int hlen = skb_headlen(skb);
-
-				/* gso_segs is currently only valid for tcp */
-				segs = skb_shinfo(skb)->gso_segs ?: 1;
-#ifdef IXGBE_FCOE
-				/* adjust for FCoE Sequence Offload */
-				if ((adapter->flags & IXGBE_FLAG_FCOE_ENABLED)
-				    && skb_is_gso(skb)
-				    && vlan_get_protocol(skb) ==
-				    htons(ETH_P_FCOE)) {
-					hlen = skb_transport_offset(skb) +
-						sizeof(struct fc_frame_header) +
-						sizeof(struct fcoe_crc_eof);
-					segs = DIV_ROUND_UP(skb->len - hlen,
-						skb_shinfo(skb)->gso_size);
-				}
-#endif /* IXGBE_FCOE */
-				/* multiply data chunks by size of headers */
-				bytecount = ((segs - 1) * hlen) + skb->len;
-				total_packets += segs;
-				total_bytes += bytecount;
-			}
-
-			ixgbe_unmap_and_free_tx_resource(adapter,
-							 tx_buffer_info);
 
 			tx_desc->wb.status = 0;
+			cleaned = (i == eop);
 
 			i++;
 			if (i == tx_ring->count)
 				i = 0;
+
+			if (cleaned && tx_buffer_info->skb) {
+				total_bytes += tx_buffer_info->bytecount;
+				total_packets += tx_buffer_info->gso_segs;
+			}
+
+			ixgbe_unmap_and_free_tx_resource(tx_ring,
+							 tx_buffer_info);
 		}
 
+		tx_ring->tx_stats.completed++;
 		eop = tx_ring->tx_buffer_info[i].next_to_watch;
 		eop_desc = IXGBE_TX_DESC_ADV(tx_ring, eop);
 	}
 
 	tx_ring->next_to_clean = i;
+	tx_ring->total_bytes += total_bytes;
+	tx_ring->total_packets += total_packets;
+	u64_stats_update_begin(&tx_ring->syncp);
+	tx_ring->stats.packets += total_packets;
+	tx_ring->stats.bytes += total_bytes;
+	u64_stats_update_end(&tx_ring->syncp);
+
+	if (check_for_tx_hang(tx_ring) && ixgbe_check_tx_hang(tx_ring)) {
+		/* schedule immediate reset if we believe we hung */
+		struct ixgbe_hw *hw = &adapter->hw;
+		tx_desc = IXGBE_TX_DESC_ADV(tx_ring, eop);
+		e_err(drv, "Detected Tx Unit Hang\n"
+			"  Tx Queue             <%d>\n"
+			"  TDH, TDT             <%x>, <%x>\n"
+			"  next_to_use          <%x>\n"
+			"  next_to_clean        <%x>\n"
+			"tx_buffer_info[next_to_clean]\n"
+			"  time_stamp           <%lx>\n"
+			"  jiffies              <%lx>\n",
+			tx_ring->queue_index,
+			IXGBE_READ_REG(hw, IXGBE_TDH(tx_ring->reg_idx)),
+			IXGBE_READ_REG(hw, IXGBE_TDT(tx_ring->reg_idx)),
+			tx_ring->next_to_use, eop,
+			tx_ring->tx_buffer_info[eop].time_stamp, jiffies);
+
+		netif_stop_subqueue(tx_ring->netdev, tx_ring->queue_index);
+
+		e_info(probe,
+		       "tx hang %d detected on queue %d, resetting adapter\n",
+			adapter->tx_timeout_count + 1, tx_ring->queue_index);
+
+		/* schedule immediate reset if we believe we hung */
+		ixgbe_tx_timeout(adapter->netdev);
+
+		/* the adapter is about to reset, no point in enabling stuff */
+		return true;
+	}
 
 #define TX_WAKE_THRESHOLD (DESC_NEEDED * 2)
-	if (unlikely(count && netif_carrier_ok(netdev) &&
+	if (unlikely(count && netif_carrier_ok(tx_ring->netdev) &&
 		     (IXGBE_DESC_UNUSED(tx_ring) >= TX_WAKE_THRESHOLD))) {
 		/* Make sure that anybody stopping the queue after this
 		 * sees the new next_to_clean.
 		 */
 		smp_mb();
-		if (__netif_subqueue_stopped(netdev, tx_ring->queue_index) &&
+		if (__netif_subqueue_stopped(tx_ring->netdev, tx_ring->queue_index) &&
 		    !test_bit(__IXGBE_DOWN, &adapter->state)) {
-			netif_wake_subqueue(netdev, tx_ring->queue_index);
-			++tx_ring->restart_queue;
-		}
-	}
-
-	if (adapter->detect_tx_hung) {
-		if (ixgbe_check_tx_hang(adapter, tx_ring, i)) {
-			/* schedule immediate reset if we believe we hung */
-			e_info(probe, "tx hang %d detected, resetting "
-			       "adapter\n", adapter->tx_timeout_count + 1);
-			ixgbe_tx_timeout(adapter->netdev);
+			netif_wake_subqueue(tx_ring->netdev, tx_ring->queue_index);
+			++tx_ring->tx_stats.restart_queue;
 		}
 	}
 
-	/* re-arm the interrupt */
-	if (count >= tx_ring->work_limit)
-		ixgbe_irq_rearm_queues(adapter, ((u64)1 << q_vector->v_idx));
-
-	tx_ring->total_bytes += total_bytes;
-	tx_ring->total_packets += total_packets;
-	u64_stats_update_begin(&tx_ring->syncp);
-	tx_ring->stats.packets += total_packets;
-	tx_ring->stats.bytes += total_bytes;
-	u64_stats_update_end(&tx_ring->syncp);
 	return count < tx_ring->work_limit;
 }
 
 #ifdef CONFIG_IXGBE_DCA
 static void ixgbe_update_rx_dca(struct ixgbe_adapter *adapter,
-				struct ixgbe_ring *rx_ring)
+				struct ixgbe_ring *rx_ring,
+				int cpu)
 {
+	struct ixgbe_hw *hw = &adapter->hw;
 	u32 rxctrl;
-	int cpu = get_cpu();
-	int q = rx_ring->reg_idx;
+	u8 reg_idx = rx_ring->reg_idx;
 
-	if (rx_ring->cpu != cpu) {
-		rxctrl = IXGBE_READ_REG(&adapter->hw, IXGBE_DCA_RXCTRL(q));
-		if (adapter->hw.mac.type == ixgbe_mac_82598EB) {
-			rxctrl &= ~IXGBE_DCA_RXCTRL_CPUID_MASK;
-			rxctrl |= dca3_get_tag(&adapter->pdev->dev, cpu);
-		} else if (adapter->hw.mac.type == ixgbe_mac_82599EB) {
-			rxctrl &= ~IXGBE_DCA_RXCTRL_CPUID_MASK_82599;
-			rxctrl |= (dca3_get_tag(&adapter->pdev->dev, cpu) <<
-				   IXGBE_DCA_RXCTRL_CPUID_SHIFT_82599);
-		}
-		rxctrl |= IXGBE_DCA_RXCTRL_DESC_DCA_EN;
-		rxctrl |= IXGBE_DCA_RXCTRL_HEAD_DCA_EN;
-		rxctrl &= ~(IXGBE_DCA_RXCTRL_DESC_RRO_EN);
-		rxctrl &= ~(IXGBE_DCA_RXCTRL_DESC_WRO_EN |
-			    IXGBE_DCA_RXCTRL_DESC_HSRO_EN);
-		IXGBE_WRITE_REG(&adapter->hw, IXGBE_DCA_RXCTRL(q), rxctrl);
-		rx_ring->cpu = cpu;
+	rxctrl = IXGBE_READ_REG(hw, IXGBE_DCA_RXCTRL(reg_idx));
+	switch (hw->mac.type) {
+	case ixgbe_mac_82598EB:
+		rxctrl &= ~IXGBE_DCA_RXCTRL_CPUID_MASK;
+		rxctrl |= dca3_get_tag(&adapter->pdev->dev, cpu);
+		break;
+	case ixgbe_mac_82599EB:
+	case ixgbe_mac_X540:
+		rxctrl &= ~IXGBE_DCA_RXCTRL_CPUID_MASK_82599;
+		rxctrl |= (dca3_get_tag(&adapter->pdev->dev, cpu) <<
+			   IXGBE_DCA_RXCTRL_CPUID_SHIFT_82599);
+		break;
+	default:
+		break;
 	}
-	put_cpu();
+	rxctrl |= IXGBE_DCA_RXCTRL_DESC_DCA_EN;
+	rxctrl |= IXGBE_DCA_RXCTRL_HEAD_DCA_EN;
+	rxctrl &= ~(IXGBE_DCA_RXCTRL_DESC_RRO_EN);
+	rxctrl &= ~(IXGBE_DCA_RXCTRL_DESC_WRO_EN |
+		    IXGBE_DCA_RXCTRL_DESC_HSRO_EN);
+	IXGBE_WRITE_REG(hw, IXGBE_DCA_RXCTRL(reg_idx), rxctrl);
 }
 
 static void ixgbe_update_tx_dca(struct ixgbe_adapter *adapter,
-				struct ixgbe_ring *tx_ring)
+				struct ixgbe_ring *tx_ring,
+				int cpu)
 {
+	struct ixgbe_hw *hw = &adapter->hw;
 	u32 txctrl;
+	u8 reg_idx = tx_ring->reg_idx;
+
+	switch (hw->mac.type) {
+	case ixgbe_mac_82598EB:
+		txctrl = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL(reg_idx));
+		txctrl &= ~IXGBE_DCA_TXCTRL_CPUID_MASK;
+		txctrl |= dca3_get_tag(&adapter->pdev->dev, cpu);
+		txctrl |= IXGBE_DCA_TXCTRL_DESC_DCA_EN;
+		txctrl &= ~IXGBE_DCA_TXCTRL_TX_WB_RO_EN;
+		IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL(reg_idx), txctrl);
+		break;
+	case ixgbe_mac_82599EB:
+	case ixgbe_mac_X540:
+		txctrl = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL_82599(reg_idx));
+		txctrl &= ~IXGBE_DCA_TXCTRL_CPUID_MASK_82599;
+		txctrl |= (dca3_get_tag(&adapter->pdev->dev, cpu) <<
+			   IXGBE_DCA_TXCTRL_CPUID_SHIFT_82599);
+		txctrl |= IXGBE_DCA_TXCTRL_DESC_DCA_EN;
+		txctrl &= ~IXGBE_DCA_TXCTRL_TX_WB_RO_EN;
+		IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL_82599(reg_idx), txctrl);
+		break;
+	default:
+		break;
+	}
+}
+
+static void ixgbe_update_dca(struct ixgbe_q_vector *q_vector)
+{
+	struct ixgbe_adapter *adapter = q_vector->adapter;
 	int cpu = get_cpu();
-	int q = tx_ring->reg_idx;
-	struct ixgbe_hw *hw = &adapter->hw;
+	long r_idx;
+	int i;
 
-	if (tx_ring->cpu != cpu) {
-		if (adapter->hw.mac.type == ixgbe_mac_82598EB) {
-			txctrl = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL(q));
-			txctrl &= ~IXGBE_DCA_TXCTRL_CPUID_MASK;
-			txctrl |= dca3_get_tag(&adapter->pdev->dev, cpu);
-			txctrl |= IXGBE_DCA_TXCTRL_DESC_DCA_EN;
-			IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL(q), txctrl);
-		} else if (adapter->hw.mac.type == ixgbe_mac_82599EB) {
-			txctrl = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL_82599(q));
-			txctrl &= ~IXGBE_DCA_TXCTRL_CPUID_MASK_82599;
-			txctrl |= (dca3_get_tag(&adapter->pdev->dev, cpu) <<
-				  IXGBE_DCA_TXCTRL_CPUID_SHIFT_82599);
-			txctrl |= IXGBE_DCA_TXCTRL_DESC_DCA_EN;
-			IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL_82599(q), txctrl);
-		}
-		tx_ring->cpu = cpu;
+	if (q_vector->cpu == cpu)
+		goto out_no_update;
+
+	r_idx = find_first_bit(q_vector->txr_idx, adapter->num_tx_queues);
+	for (i = 0; i < q_vector->txr_count; i++) {
+		ixgbe_update_tx_dca(adapter, adapter->tx_ring[r_idx], cpu);
+		r_idx = find_next_bit(q_vector->txr_idx, adapter->num_tx_queues,
+				      r_idx + 1);
+	}
+
+	r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues);
+	for (i = 0; i < q_vector->rxr_count; i++) {
+		ixgbe_update_rx_dca(adapter, adapter->rx_ring[r_idx], cpu);
+		r_idx = find_next_bit(q_vector->rxr_idx, adapter->num_rx_queues,
+				      r_idx + 1);
 	}
+
+	q_vector->cpu = cpu;
+out_no_update:
 	put_cpu();
 }
 
 static void ixgbe_setup_dca(struct ixgbe_adapter *adapter)
 {
+	int num_q_vectors;
 	int i;
 
 	if (!(adapter->flags & IXGBE_FLAG_DCA_ENABLED))
@@ -899,22 +1019,25 @@ static void ixgbe_setup_dca(struct ixgbe
 	/* always use CB2 mode, difference is masked in the CB driver */
 	IXGBE_WRITE_REG(&adapter->hw, IXGBE_DCA_CTRL, 2);
 
-	for (i = 0; i < adapter->num_tx_queues; i++) {
-		adapter->tx_ring[i]->cpu = -1;
-		ixgbe_update_tx_dca(adapter, adapter->tx_ring[i]);
-	}
-	for (i = 0; i < adapter->num_rx_queues; i++) {
-		adapter->rx_ring[i]->cpu = -1;
-		ixgbe_update_rx_dca(adapter, adapter->rx_ring[i]);
+	if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED)
+		num_q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS;
+	else
+		num_q_vectors = 1;
+
+	for (i = 0; i < num_q_vectors; i++) {
+		adapter->q_vector[i]->cpu = -1;
+		ixgbe_update_dca(adapter->q_vector[i]);
 	}
 }
 
 static int __ixgbe_notify_dca(struct device *dev, void *data)
 {
-	struct net_device *netdev = dev_get_drvdata(dev);
-	struct ixgbe_adapter *adapter = netdev_priv(netdev);
+	struct ixgbe_adapter *adapter = dev_get_drvdata(dev);
 	unsigned long event = *(unsigned long *)data;
 
+	if (!(adapter->flags & IXGBE_FLAG_DCA_ENABLED))
+		return 0;
+
 	switch (event) {
 	case DCA_PROVIDER_ADD:
 		/* if we're already enabled, don't do it again */
@@ -1013,8 +1136,7 @@ static inline void ixgbe_rx_checksum(str
 	skb->ip_summed = CHECKSUM_UNNECESSARY;
 }
 
-static inline void ixgbe_release_rx_desc(struct ixgbe_hw *hw,
-					 struct ixgbe_ring *rx_ring, u32 val)
+static inline void ixgbe_release_rx_desc(struct ixgbe_ring *rx_ring, u32 val)
 {
 	/*
 	 * Force memory writes to complete before letting h/w
@@ -1023,72 +1145,81 @@ static inline void ixgbe_release_rx_desc
 	 * such as IA-64).
 	 */
 	wmb();
-	IXGBE_WRITE_REG(hw, IXGBE_RDT(rx_ring->reg_idx), val);
+	writel(val, rx_ring->tail);
 }
 
 /**
  * ixgbe_alloc_rx_buffers - Replace used receive buffers; packet split
- * @adapter: address of board private structure
+ * @rx_ring: ring to place buffers on
+ * @cleaned_count: number of buffers to replace
  **/
-void ixgbe_alloc_rx_buffers(struct ixgbe_adapter *adapter,
-			    struct ixgbe_ring *rx_ring,
-			    int cleaned_count)
+void ixgbe_alloc_rx_buffers(struct ixgbe_ring *rx_ring, u16 cleaned_count)
 {
-	struct net_device *netdev = adapter->netdev;
-	struct pci_dev *pdev = adapter->pdev;
 	union ixgbe_adv_rx_desc *rx_desc;
 	struct ixgbe_rx_buffer *bi;
-	unsigned int i;
-	unsigned int bufsz = rx_ring->rx_buf_len;
+	struct sk_buff *skb;
+	u16 i = rx_ring->next_to_use;
 
-	i = rx_ring->next_to_use;
-	bi = &rx_ring->rx_buffer_info[i];
+	/* do nothing if no valid netdev defined */
+	if (!rx_ring->netdev)
+		return;
 
 	while (cleaned_count--) {
 		rx_desc = IXGBE_RX_DESC_ADV(rx_ring, i);
+		bi = &rx_ring->rx_buffer_info[i];
+		skb = bi->skb;
 
-		if (!bi->page_dma &&
-		    (rx_ring->flags & IXGBE_RING_RX_PS_ENABLED)) {
-			if (!bi->page) {
-				bi->page = netdev_alloc_page(netdev);
-				if (!bi->page) {
-					adapter->alloc_rx_page_failed++;
-					goto no_buffers;
-				}
-				bi->page_offset = 0;
-			} else {
-				/* use a half page if we're re-using */
-				bi->page_offset ^= (PAGE_SIZE / 2);
-			}
-
-			bi->page_dma = dma_map_page(&pdev->dev, bi->page,
-						    bi->page_offset,
-						    (PAGE_SIZE / 2),
-						    DMA_FROM_DEVICE);
-		}
-
-		if (!bi->skb) {
-			struct sk_buff *skb = netdev_alloc_skb_ip_align(netdev,
-									bufsz);
-			bi->skb = skb;
-
+		if (!skb) {
+			skb = netdev_alloc_skb_ip_align(rx_ring->netdev,
+							rx_ring->rx_buf_len);
 			if (!skb) {
-				adapter->alloc_rx_buff_failed++;
+				rx_ring->rx_stats.alloc_rx_buff_failed++;
 				goto no_buffers;
 			}
 			/* initialize queue mapping */
 			skb_record_rx_queue(skb, rx_ring->queue_index);
+			bi->skb = skb;
 		}
 
 		if (!bi->dma) {
-			bi->dma = dma_map_single(&pdev->dev,
-						 bi->skb->data,
+			bi->dma = dma_map_single(rx_ring->dev,
+						 skb->data,
 						 rx_ring->rx_buf_len,
 						 DMA_FROM_DEVICE);
+			if (dma_mapping_error(rx_ring->dev, bi->dma)) {
+				rx_ring->rx_stats.alloc_rx_buff_failed++;
+				bi->dma = 0;
+				goto no_buffers;
+			}
 		}
-		/* Refresh the desc even if buffer_addrs didn't change because
-		 * each write-back erases this info. */
-		if (rx_ring->flags & IXGBE_RING_RX_PS_ENABLED) {
+
+		if (ring_is_ps_enabled(rx_ring)) {
+			if (!bi->page) {
+				bi->page = netdev_alloc_page(rx_ring->netdev);
+				if (!bi->page) {
+					rx_ring->rx_stats.alloc_rx_page_failed++;
+					goto no_buffers;
+				}
+			}
+
+			if (!bi->page_dma) {
+				/* use a half page if we're re-using */
+				bi->page_offset ^= PAGE_SIZE / 2;
+				bi->page_dma = dma_map_page(rx_ring->dev,
+							    bi->page,
+							    bi->page_offset,
+							    PAGE_SIZE / 2,
+							    DMA_FROM_DEVICE);
+				if (dma_mapping_error(rx_ring->dev,
+						      bi->page_dma)) {
+					rx_ring->rx_stats.alloc_rx_page_failed++;
+					bi->page_dma = 0;
+					goto no_buffers;
+				}
+			}
+
+			/* Refresh the desc even if buffer_addrs didn't change
+			 * because each write-back erases this info. */
 			rx_desc->read.pkt_addr = cpu_to_le64(bi->page_dma);
 			rx_desc->read.hdr_addr = cpu_to_le64(bi->dma);
 		} else {
@@ -1099,56 +1230,48 @@ void ixgbe_alloc_rx_buffers(struct ixgbe
 		i++;
 		if (i == rx_ring->count)
 			i = 0;
-		bi = &rx_ring->rx_buffer_info[i];
 	}
 
 no_buffers:
 	if (rx_ring->next_to_use != i) {
 		rx_ring->next_to_use = i;
-		if (i-- == 0)
-			i = (rx_ring->count - 1);
-
-		ixgbe_release_rx_desc(&adapter->hw, rx_ring, i);
+		ixgbe_release_rx_desc(rx_ring, i);
 	}
 }
 
-static inline u16 ixgbe_get_hdr_info(union ixgbe_adv_rx_desc *rx_desc)
-{
-	return rx_desc->wb.lower.lo_dword.hs_rss.hdr_info;
-}
-
-static inline u16 ixgbe_get_pkt_info(union ixgbe_adv_rx_desc *rx_desc)
-{
-	return rx_desc->wb.lower.lo_dword.hs_rss.pkt_info;
-}
-
-static inline u32 ixgbe_get_rsc_count(union ixgbe_adv_rx_desc *rx_desc)
+static inline u16 ixgbe_get_hlen(union ixgbe_adv_rx_desc *rx_desc)
 {
-	return (le32_to_cpu(rx_desc->wb.lower.lo_dword.data) &
-		IXGBE_RXDADV_RSCCNT_MASK) >>
-		IXGBE_RXDADV_RSCCNT_SHIFT;
+	/* HW will not DMA in data larger than the given buffer, even if it
+	 * parses the (NFS, of course) header to be larger.  In that case, it
+	 * fills the header buffer and spills the rest into the page.
+	 */
+	u16 hdr_info = le16_to_cpu(rx_desc->wb.lower.lo_dword.hs_rss.hdr_info);
+	u16 hlen = (hdr_info &  IXGBE_RXDADV_HDRBUFLEN_MASK) >>
+		    IXGBE_RXDADV_HDRBUFLEN_SHIFT;
+	if (hlen > IXGBE_RX_HDR_SIZE)
+		hlen = IXGBE_RX_HDR_SIZE;
+	return hlen;
 }
 
 /**
  * ixgbe_transform_rsc_queue - change rsc queue into a full packet
  * @skb: pointer to the last skb in the rsc queue
- * @count: pointer to number of packets coalesced in this context
  *
  * This function changes a queue full of hw rsc buffers into a completed
  * packet.  It uses the ->prev pointers to find the first packet and then
  * turns it into the frag list owner.
  **/
-static inline struct sk_buff *ixgbe_transform_rsc_queue(struct sk_buff *skb,
-							u64 *count)
+static inline struct sk_buff *ixgbe_transform_rsc_queue(struct sk_buff *skb)
 {
 	unsigned int frag_list_size = 0;
+	unsigned int skb_cnt = 1;
 
 	while (skb->prev) {
 		struct sk_buff *prev = skb->prev;
 		frag_list_size += skb->len;
 		skb->prev = NULL;
 		skb = prev;
-		*count += 1;
+		skb_cnt++;
 	}
 
 	skb_shinfo(skb)->frag_list = skb->next;
@@ -1156,68 +1279,59 @@ static inline struct sk_buff *ixgbe_tran
 	skb->len += frag_list_size;
 	skb->data_len += frag_list_size;
 	skb->truesize += frag_list_size;
+	IXGBE_RSC_CB(skb)->skb_cnt = skb_cnt;
+
 	return skb;
 }
 
-struct ixgbe_rsc_cb {
-	dma_addr_t dma;
-	bool delay_unmap;
-};
-
-#define IXGBE_RSC_CB(skb) ((struct ixgbe_rsc_cb *)(skb)->cb)
+static inline bool ixgbe_get_rsc_state(union ixgbe_adv_rx_desc *rx_desc)
+{
+	return !!(le32_to_cpu(rx_desc->wb.lower.lo_dword.data) &
+		IXGBE_RXDADV_RSCCNT_MASK);
+}
 
-static bool ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector,
+static void ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector,
 			       struct ixgbe_ring *rx_ring,
 			       int *work_done, int work_to_do)
 {
 	struct ixgbe_adapter *adapter = q_vector->adapter;
-	struct pci_dev *pdev = adapter->pdev;
 	union ixgbe_adv_rx_desc *rx_desc, *next_rxd;
 	struct ixgbe_rx_buffer *rx_buffer_info, *next_buffer;
 	struct sk_buff *skb;
-	unsigned int i, rsc_count = 0;
-	u32 len, staterr;
-	u16 hdr_info;
-	bool cleaned = false;
-	int cleaned_count = 0;
 	unsigned int total_rx_bytes = 0, total_rx_packets = 0;
+	const int current_node = numa_node_id();
 #ifdef IXGBE_FCOE
 	int ddp_bytes = 0;
 #endif /* IXGBE_FCOE */
+	u32 staterr;
+	u16 i;
+	u16 cleaned_count = 0;
+	bool pkt_is_rsc = false;
 
 	i = rx_ring->next_to_clean;
 	rx_desc = IXGBE_RX_DESC_ADV(rx_ring, i);
 	staterr = le32_to_cpu(rx_desc->wb.upper.status_error);
-	rx_buffer_info = &rx_ring->rx_buffer_info[i];
 
 	while (staterr & IXGBE_RXD_STAT_DD) {
 		u32 upper_len = 0;
-		if (*work_done >= work_to_do)
-			break;
-		(*work_done)++;
 
 		rmb(); /* read descriptor and rx_buffer_info after status DD */
-		if (rx_ring->flags & IXGBE_RING_RX_PS_ENABLED) {
-			hdr_info = le16_to_cpu(ixgbe_get_hdr_info(rx_desc));
-			len = (hdr_info & IXGBE_RXDADV_HDRBUFLEN_MASK) >>
-			       IXGBE_RXDADV_HDRBUFLEN_SHIFT;
-			upper_len = le16_to_cpu(rx_desc->wb.upper.length);
-			if ((len > IXGBE_RX_HDR_SIZE) ||
-			    (upper_len && !(hdr_info & IXGBE_RXDADV_SPH)))
-				len = IXGBE_RX_HDR_SIZE;
-		} else {
-			len = le16_to_cpu(rx_desc->wb.upper.length);
-		}
 
-		cleaned = true;
+		rx_buffer_info = &rx_ring->rx_buffer_info[i];
+
 		skb = rx_buffer_info->skb;
-		prefetch(skb->data);
 		rx_buffer_info->skb = NULL;
+		prefetch(skb->data);
+
+		if (ring_is_rsc_enabled(rx_ring))
+			pkt_is_rsc = ixgbe_get_rsc_state(rx_desc);
 
+		/* if this is a skb from previous receive DMA will be 0 */
 		if (rx_buffer_info->dma) {
-			if ((adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED) &&
-			    (!(staterr & IXGBE_RXD_STAT_EOP)) &&
-				 (!(skb->prev))) {
+			u16 hlen;
+			if (pkt_is_rsc &&
+			    !(staterr & IXGBE_RXD_STAT_EOP) &&
+			    !skb->prev) {
 				/*
 				 * When HWRSC is enabled, delay unmapping
 				 * of the first packet. It carries the
@@ -1228,29 +1342,42 @@ static bool ixgbe_clean_rx_irq(struct ix
 				IXGBE_RSC_CB(skb)->delay_unmap = true;
 				IXGBE_RSC_CB(skb)->dma = rx_buffer_info->dma;
 			} else {
-				dma_unmap_single(&pdev->dev,
+				dma_unmap_single(rx_ring->dev,
 						 rx_buffer_info->dma,
 						 rx_ring->rx_buf_len,
 						 DMA_FROM_DEVICE);
 			}
 			rx_buffer_info->dma = 0;
-			skb_put(skb, len);
+
+			if (ring_is_ps_enabled(rx_ring)) {
+				hlen = ixgbe_get_hlen(rx_desc);
+				upper_len = le16_to_cpu(rx_desc->wb.upper.length);
+			} else {
+				hlen = le16_to_cpu(rx_desc->wb.upper.length);
+			}
+
+			skb_put(skb, hlen);
+		} else {
+			/* assume packet split since header is unmapped */
+			upper_len = le16_to_cpu(rx_desc->wb.upper.length);
 		}
 
 		if (upper_len) {
-			dma_unmap_page(&pdev->dev, rx_buffer_info->page_dma,
-				       PAGE_SIZE / 2, DMA_FROM_DEVICE);
+			dma_unmap_page(rx_ring->dev,
+				       rx_buffer_info->page_dma,
+				       PAGE_SIZE / 2,
+				       DMA_FROM_DEVICE);
 			rx_buffer_info->page_dma = 0;
 			skb_fill_page_desc(skb, skb_shinfo(skb)->nr_frags,
 					   rx_buffer_info->page,
 					   rx_buffer_info->page_offset,
 					   upper_len);
 
-			if ((rx_ring->rx_buf_len > (PAGE_SIZE / 2)) ||
-			    (page_count(rx_buffer_info->page) != 1))
-				rx_buffer_info->page = NULL;
-			else
+			if ((page_count(rx_buffer_info->page) == 1) &&
+			    (page_to_nid(rx_buffer_info->page) == current_node))
 				get_page(rx_buffer_info->page);
+			else
+				rx_buffer_info->page = NULL;
 
 			skb->len += upper_len;
 			skb->data_len += upper_len;
@@ -1265,10 +1392,7 @@ static bool ixgbe_clean_rx_irq(struct ix
 		prefetch(next_rxd);
 		cleaned_count++;
 
-		if (adapter->flags2 & IXGBE_FLAG2_RSC_CAPABLE)
-			rsc_count = ixgbe_get_rsc_count(rx_desc);
-
-		if (rsc_count) {
+		if (pkt_is_rsc) {
 			u32 nextp = (staterr & IXGBE_RXDADV_NEXTP_MASK) >>
 				     IXGBE_RXDADV_NEXTP_SHIFT;
 			next_buffer = &rx_ring->rx_buffer_info[nextp];
@@ -1276,32 +1400,8 @@ static bool ixgbe_clean_rx_irq(struct ix
 			next_buffer = &rx_ring->rx_buffer_info[i];
 		}
 
-		if (staterr & IXGBE_RXD_STAT_EOP) {
-			if (skb->prev)
-				skb = ixgbe_transform_rsc_queue(skb,
-								&(rx_ring->rsc_count));
-			if (adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED) {
-				if (IXGBE_RSC_CB(skb)->delay_unmap) {
-					dma_unmap_single(&pdev->dev,
-							 IXGBE_RSC_CB(skb)->dma,
-							 rx_ring->rx_buf_len,
-							 DMA_FROM_DEVICE);
-					IXGBE_RSC_CB(skb)->dma = 0;
-					IXGBE_RSC_CB(skb)->delay_unmap = false;
-				}
-				if (rx_ring->flags & IXGBE_RING_RX_PS_ENABLED)
-					rx_ring->rsc_count +=
-						skb_shinfo(skb)->nr_frags;
-				else
-					rx_ring->rsc_count++;
-				rx_ring->rsc_flush++;
-			}
-			u64_stats_update_begin(&rx_ring->syncp);
-			rx_ring->stats.packets++;
-			rx_ring->stats.bytes += skb->len;
-			u64_stats_update_end(&rx_ring->syncp);
-		} else {
-			if (rx_ring->flags & IXGBE_RING_RX_PS_ENABLED) {
+		if (!(staterr & IXGBE_RXD_STAT_EOP)) {
+			if (ring_is_ps_enabled(rx_ring)) {
 				rx_buffer_info->skb = next_buffer->skb;
 				rx_buffer_info->dma = next_buffer->dma;
 				next_buffer->skb = skb;
@@ -1310,12 +1410,45 @@ static bool ixgbe_clean_rx_irq(struct ix
 				skb->next = next_buffer->skb;
 				skb->next->prev = skb;
 			}
-			rx_ring->non_eop_descs++;
+			rx_ring->rx_stats.non_eop_descs++;
 			goto next_desc;
 		}
 
+		if (skb->prev) {
+			skb = ixgbe_transform_rsc_queue(skb);
+			/* if we got here without RSC the packet is invalid */
+			if (!pkt_is_rsc) {
+				__pskb_trim(skb, 0);
+				rx_buffer_info->skb = skb;
+				goto next_desc;
+			}
+		}
+
+		if (ring_is_rsc_enabled(rx_ring)) {
+			if (IXGBE_RSC_CB(skb)->delay_unmap) {
+				dma_unmap_single(rx_ring->dev,
+						 IXGBE_RSC_CB(skb)->dma,
+						 rx_ring->rx_buf_len,
+						 DMA_FROM_DEVICE);
+				IXGBE_RSC_CB(skb)->dma = 0;
+				IXGBE_RSC_CB(skb)->delay_unmap = false;
+			}
+		}
+		if (pkt_is_rsc) {
+			if (ring_is_ps_enabled(rx_ring))
+				rx_ring->rx_stats.rsc_count +=
+					skb_shinfo(skb)->nr_frags;
+			else
+				rx_ring->rx_stats.rsc_count +=
+					IXGBE_RSC_CB(skb)->skb_cnt;
+			rx_ring->rx_stats.rsc_flush++;
+		}
+
+		/* ERR_MASK will only have valid bits if EOP set */
 		if (staterr & IXGBE_RXDADV_ERR_FRAME_ERR_MASK) {
-			dev_kfree_skb_irq(skb);
+			/* trim packet back to size 0 and recycle it */
+			__pskb_trim(skb, 0);
+			rx_buffer_info->skb = skb;
 			goto next_desc;
 		}
 
@@ -1325,7 +1458,7 @@ static bool ixgbe_clean_rx_irq(struct ix
 		total_rx_bytes += skb->len;
 		total_rx_packets++;
 
-		skb->protocol = eth_type_trans(skb, adapter->netdev);
+		skb->protocol = eth_type_trans(skb, rx_ring->netdev);
 #ifdef IXGBE_FCOE
 		/* if ddp, not passing to ULD unless for FCP_RSP or error */
 		if (adapter->flags & IXGBE_FLAG_FCOE_ENABLED) {
@@ -1339,16 +1472,18 @@ static bool ixgbe_clean_rx_irq(struct ix
 next_desc:
 		rx_desc->wb.upper.status_error = 0;
 
+		(*work_done)++;
+		if (*work_done >= work_to_do)
+			break;
+
 		/* return some buffers to hardware, one at a time is too slow */
 		if (cleaned_count >= IXGBE_RX_BUFFER_WRITE) {
-			ixgbe_alloc_rx_buffers(adapter, rx_ring, cleaned_count);
+			ixgbe_alloc_rx_buffers(rx_ring, cleaned_count);
 			cleaned_count = 0;
 		}
 
 		/* use prefetched values */
 		rx_desc = next_rxd;
-		rx_buffer_info = &rx_ring->rx_buffer_info[i];
-
 		staterr = le32_to_cpu(rx_desc->wb.upper.status_error);
 	}
 
@@ -1356,14 +1491,14 @@ next_desc:
 	cleaned_count = IXGBE_DESC_UNUSED(rx_ring);
 
 	if (cleaned_count)
-		ixgbe_alloc_rx_buffers(adapter, rx_ring, cleaned_count);
+		ixgbe_alloc_rx_buffers(rx_ring, cleaned_count);
 
 #ifdef IXGBE_FCOE
 	/* include DDPed FCoE data */
 	if (ddp_bytes > 0) {
 		unsigned int mss;
 
-		mss = adapter->netdev->mtu - sizeof(struct fcoe_hdr) -
+		mss = rx_ring->netdev->mtu - sizeof(struct fcoe_hdr) -
 			sizeof(struct fc_frame_header) -
 			sizeof(struct fcoe_crc_eof);
 		if (mss > 512)
@@ -1375,8 +1510,10 @@ next_desc:
 
 	rx_ring->total_packets += total_rx_packets;
 	rx_ring->total_bytes += total_rx_bytes;
-
-	return cleaned;
+	u64_stats_update_begin(&rx_ring->syncp);
+	rx_ring->stats.packets += total_rx_packets;
+	rx_ring->stats.bytes += total_rx_bytes;
+	u64_stats_update_end(&rx_ring->syncp);
 }
 
 static int ixgbe_clean_rxonly(struct napi_struct *, int);
@@ -1390,7 +1527,7 @@ static int ixgbe_clean_rxonly(struct nap
 static void ixgbe_configure_msix(struct ixgbe_adapter *adapter)
 {
 	struct ixgbe_q_vector *q_vector;
-	int i, j, q_vectors, v_idx, r_idx;
+	int i, q_vectors, v_idx, r_idx;
 	u32 mask;
 
 	q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS;
@@ -1406,8 +1543,8 @@ static void ixgbe_configure_msix(struct
 				       adapter->num_rx_queues);
 
 		for (i = 0; i < q_vector->rxr_count; i++) {
-			j = adapter->rx_ring[r_idx]->reg_idx;
-			ixgbe_set_ivar(adapter, 0, j, v_idx);
+			u8 reg_idx = adapter->rx_ring[r_idx]->reg_idx;
+			ixgbe_set_ivar(adapter, 0, reg_idx, v_idx);
 			r_idx = find_next_bit(q_vector->rxr_idx,
 					      adapter->num_rx_queues,
 					      r_idx + 1);
@@ -1416,8 +1553,8 @@ static void ixgbe_configure_msix(struct
 				       adapter->num_tx_queues);
 
 		for (i = 0; i < q_vector->txr_count; i++) {
-			j = adapter->tx_ring[r_idx]->reg_idx;
-			ixgbe_set_ivar(adapter, 1, j, v_idx);
+			u8 reg_idx = adapter->tx_ring[r_idx]->reg_idx;
+			ixgbe_set_ivar(adapter, 1, reg_idx, v_idx);
 			r_idx = find_next_bit(q_vector->txr_idx,
 					      adapter->num_tx_queues,
 					      r_idx + 1);
@@ -1448,11 +1585,19 @@ static void ixgbe_configure_msix(struct
 		}
 	}
 
-	if (adapter->hw.mac.type == ixgbe_mac_82598EB)
+	switch (adapter->hw.mac.type) {
+	case ixgbe_mac_82598EB:
 		ixgbe_set_ivar(adapter, -1, IXGBE_IVAR_OTHER_CAUSES_INDEX,
 			       v_idx);
-	else if (adapter->hw.mac.type == ixgbe_mac_82599EB)
+		break;
+	case ixgbe_mac_82599EB:
+	case ixgbe_mac_X540:
 		ixgbe_set_ivar(adapter, -1, 1, v_idx);
+		break;
+
+	default:
+		break;
+	}
 	IXGBE_WRITE_REG(&adapter->hw, IXGBE_EITR(v_idx), 1950);
 
 	/* set up to autoclear timer, and the vectors */
@@ -1548,12 +1693,15 @@ void ixgbe_write_eitr(struct ixgbe_q_vec
 	int v_idx = q_vector->v_idx;
 	u32 itr_reg = EITR_INTS_PER_SEC_TO_REG(q_vector->eitr);
 
-	if (adapter->hw.mac.type == ixgbe_mac_82598EB) {
+	switch (adapter->hw.mac.type) {
+	case ixgbe_mac_82598EB:
 		/* must write high and low 16 bits to reset counter */
 		itr_reg |= (itr_reg << 16);
-	} else if (adapter->hw.mac.type == ixgbe_mac_82599EB) {
+		break;
+	case ixgbe_mac_82599EB:
+	case ixgbe_mac_X540:
 		/*
-		 * 82599 can support a value of zero, so allow it for
+		 * 82599 and X540 can support a value of zero, so allow it for
 		 * max interrupt rate, but there is an errata where it can
 		 * not be zero with RSC
 		 */
@@ -1566,6 +1714,9 @@ void ixgbe_write_eitr(struct ixgbe_q_vec
 		 * immediate assertion of the interrupt
 		 */
 		itr_reg |= IXGBE_EITR_CNT_WDIS;
+		break;
+	default:
+		break;
 	}
 	IXGBE_WRITE_REG(hw, IXGBE_EITR(v_idx), itr_reg);
 }
@@ -1573,14 +1724,13 @@ void ixgbe_write_eitr(struct ixgbe_q_vec
 static void ixgbe_set_itr_msix(struct ixgbe_q_vector *q_vector)
 {
 	struct ixgbe_adapter *adapter = q_vector->adapter;
+	int i, r_idx;
 	u32 new_itr;
 	u8 current_itr, ret_itr;
-	int i, r_idx;
-	struct ixgbe_ring *rx_ring, *tx_ring;
 
 	r_idx = find_first_bit(q_vector->txr_idx, adapter->num_tx_queues);
 	for (i = 0; i < q_vector->txr_count; i++) {
-		tx_ring = adapter->tx_ring[r_idx];
+		struct ixgbe_ring *tx_ring = adapter->tx_ring[r_idx];
 		ret_itr = ixgbe_update_itr(adapter, q_vector->eitr,
 					   q_vector->tx_itr,
 					   tx_ring->total_packets,
@@ -1595,7 +1745,7 @@ static void ixgbe_set_itr_msix(struct ix
 
 	r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues);
 	for (i = 0; i < q_vector->rxr_count; i++) {
-		rx_ring = adapter->rx_ring[r_idx];
+		struct ixgbe_ring *rx_ring = adapter->rx_ring[r_idx];
 		ret_itr = ixgbe_update_itr(adapter, q_vector->eitr,
 					   q_vector->rx_itr,
 					   rx_ring->total_packets,
@@ -1626,7 +1776,7 @@ static void ixgbe_set_itr_msix(struct ix
 
 	if (new_itr != q_vector->eitr) {
 		/* do an exponential smoothing */
-		new_itr = ((q_vector->eitr * 90)/100) + ((new_itr * 10)/100);
+		new_itr = ((q_vector->eitr * 9) + new_itr)/10;
 
 		/* save the algorithm value here, not the smoothed one */
 		q_vector->eitr = new_itr;
@@ -1694,17 +1844,18 @@ static void ixgbe_check_sfp_event(struct
 {
 	struct ixgbe_hw *hw = &adapter->hw;
 
+	if (eicr & IXGBE_EICR_GPI_SDP2) {
+		/* Clear the interrupt */
+		IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP2);
+		if (!test_bit(__IXGBE_DOWN, &adapter->state))
+			schedule_work(&adapter->sfp_config_module_task);
+	}
+
 	if (eicr & IXGBE_EICR_GPI_SDP1) {
 		/* Clear the interrupt */
 		IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP1);
-		schedule_work(&adapter->multispeed_fiber_task);
-	} else if (eicr & IXGBE_EICR_GPI_SDP2) {
-		/* Clear the interrupt */
-		IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP2);
-		schedule_work(&adapter->sfp_config_module_task);
-	} else {
-		/* Interrupt isn't for us... */
-		return;
+		if (!test_bit(__IXGBE_DOWN, &adapter->state))
+			schedule_work(&adapter->multispeed_fiber_task);
 	}
 }
 
@@ -1744,16 +1895,16 @@ static irqreturn_t ixgbe_msix_lsc(int ir
 	if (eicr & IXGBE_EICR_MAILBOX)
 		ixgbe_msg_task(adapter);
 
-	if (hw->mac.type == ixgbe_mac_82598EB)
-		ixgbe_check_fan_failure(adapter, eicr);
-
-	if (hw->mac.type == ixgbe_mac_82599EB) {
+	switch (hw->mac.type) {
+	case ixgbe_mac_82599EB:
 		ixgbe_check_sfp_event(adapter, eicr);
-		adapter->interrupt_event = eicr;
 		if ((adapter->flags2 & IXGBE_FLAG2_TEMP_SENSOR_CAPABLE) &&
-		    ((eicr & IXGBE_EICR_GPI_SDP0) || (eicr & IXGBE_EICR_LSC)))
+		    ((eicr & IXGBE_EICR_GPI_SDP0) || (eicr & IXGBE_EICR_LSC))) {
+			adapter->interrupt_event = eicr;
 			schedule_work(&adapter->check_overtemp_task);
-
+		}
+		/* now fallthrough to handle Flow Director */
+	case ixgbe_mac_X540:
 		/* Handle Flow Director Full threshold interrupt */
 		if (eicr & IXGBE_EICR_FLOW_DIR) {
 			int i;
@@ -1763,12 +1914,18 @@ static irqreturn_t ixgbe_msix_lsc(int ir
 			for (i = 0; i < adapter->num_tx_queues; i++) {
 				struct ixgbe_ring *tx_ring =
 							    adapter->tx_ring[i];
-				if (test_and_clear_bit(__IXGBE_FDIR_INIT_DONE,
-						       &tx_ring->reinit_state))
+				if (test_and_clear_bit(__IXGBE_TX_FDIR_INIT_DONE,
+						       &tx_ring->state))
 					schedule_work(&adapter->fdir_reinit_task);
 			}
 		}
+		break;
+	default:
+		break;
 	}
+
+	ixgbe_check_fan_failure(adapter, eicr);
+
 	if (!test_bit(__IXGBE_DOWN, &adapter->state))
 		IXGBE_WRITE_REG(hw, IXGBE_EIMS, IXGBE_EIMS_OTHER);
 
@@ -1779,15 +1936,24 @@ static inline void ixgbe_irq_enable_queu
 					   u64 qmask)
 {
 	u32 mask;
+	struct ixgbe_hw *hw = &adapter->hw;
 
-	if (adapter->hw.mac.type == ixgbe_mac_82598EB) {
+	switch (hw->mac.type) {
+	case ixgbe_mac_82598EB:
 		mask = (IXGBE_EIMS_RTX_QUEUE & qmask);
-		IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, mask);
-	} else {
+		IXGBE_WRITE_REG(hw, IXGBE_EIMS, mask);
+		break;
+	case ixgbe_mac_82599EB:
+	case ixgbe_mac_X540:
 		mask = (qmask & 0xFFFFFFFF);
-		IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS_EX(0), mask);
+		if (mask)
+			IXGBE_WRITE_REG(hw, IXGBE_EIMS_EX(0), mask);
 		mask = (qmask >> 32);
-		IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS_EX(1), mask);
+		if (mask)
+			IXGBE_WRITE_REG(hw, IXGBE_EIMS_EX(1), mask);
+		break;
+	default:
+		break;
 	}
 	/* skip the flush */
 }
@@ -1796,15 +1962,24 @@ static inline void ixgbe_irq_disable_que
 					    u64 qmask)
 {
 	u32 mask;
+	struct ixgbe_hw *hw = &adapter->hw;
 
-	if (adapter->hw.mac.type == ixgbe_mac_82598EB) {
+	switch (hw->mac.type) {
+	case ixgbe_mac_82598EB:
 		mask = (IXGBE_EIMS_RTX_QUEUE & qmask);
-		IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, mask);
-	} else {
+		IXGBE_WRITE_REG(hw, IXGBE_EIMC, mask);
+		break;
+	case ixgbe_mac_82599EB:
+	case ixgbe_mac_X540:
 		mask = (qmask & 0xFFFFFFFF);
-		IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC_EX(0), mask);
+		if (mask)
+			IXGBE_WRITE_REG(hw, IXGBE_EIMC_EX(0), mask);
 		mask = (qmask >> 32);
-		IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC_EX(1), mask);
+		if (mask)
+			IXGBE_WRITE_REG(hw, IXGBE_EIMC_EX(1), mask);
+		break;
+	default:
+		break;
 	}
 	/* skip the flush */
 }
@@ -1847,8 +2022,13 @@ static irqreturn_t ixgbe_msix_clean_rx(i
 	int r_idx;
 	int i;
 
+#ifdef CONFIG_IXGBE_DCA
+	if (adapter->flags & IXGBE_FLAG_DCA_ENABLED)
+		ixgbe_update_dca(q_vector);
+#endif
+
 	r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues);
-	for (i = 0;  i < q_vector->rxr_count; i++) {
+	for (i = 0; i < q_vector->rxr_count; i++) {
 		rx_ring = adapter->rx_ring[r_idx];
 		rx_ring->total_bytes = 0;
 		rx_ring->total_packets = 0;
@@ -1859,7 +2039,6 @@ static irqreturn_t ixgbe_msix_clean_rx(i
 	if (!q_vector->rxr_count)
 		return IRQ_HANDLED;
 
-	/* disable interrupts on this vector only */
 	/* EIAM disabled interrupts (on this vector) for us */
 	napi_schedule(&q_vector->napi);
 
@@ -1918,13 +2097,14 @@ static int ixgbe_clean_rxonly(struct nap
 	int work_done = 0;
 	long r_idx;
 
-	r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues);
-	rx_ring = adapter->rx_ring[r_idx];
 #ifdef CONFIG_IXGBE_DCA
 	if (adapter->flags & IXGBE_FLAG_DCA_ENABLED)
-		ixgbe_update_rx_dca(adapter, rx_ring);
+		ixgbe_update_dca(q_vector);
 #endif
 
+	r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues);
+	rx_ring = adapter->rx_ring[r_idx];
+
 	ixgbe_clean_rx_irq(q_vector, rx_ring, &work_done, budget);
 
 	/* If all Rx work done, exit the polling mode */
@@ -1958,13 +2138,14 @@ static int ixgbe_clean_rxtx_many(struct
 	long r_idx;
 	bool tx_clean_complete = true;
 
+#ifdef CONFIG_IXGBE_DCA
+	if (adapter->flags & IXGBE_FLAG_DCA_ENABLED)
+		ixgbe_update_dca(q_vector);
+#endif
+
 	r_idx = find_first_bit(q_vector->txr_idx, adapter->num_tx_queues);
 	for (i = 0; i < q_vector->txr_count; i++) {
 		ring = adapter->tx_ring[r_idx];
-#ifdef CONFIG_IXGBE_DCA
-		if (adapter->flags & IXGBE_FLAG_DCA_ENABLED)
-			ixgbe_update_tx_dca(adapter, ring);
-#endif
 		tx_clean_complete &= ixgbe_clean_tx_irq(q_vector, ring);
 		r_idx = find_next_bit(q_vector->txr_idx, adapter->num_tx_queues,
 				      r_idx + 1);
@@ -1977,10 +2158,6 @@ static int ixgbe_clean_rxtx_many(struct
 	r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues);
 	for (i = 0; i < q_vector->rxr_count; i++) {
 		ring = adapter->rx_ring[r_idx];
-#ifdef CONFIG_IXGBE_DCA
-		if (adapter->flags & IXGBE_FLAG_DCA_ENABLED)
-			ixgbe_update_rx_dca(adapter, ring);
-#endif
 		ixgbe_clean_rx_irq(q_vector, ring, &work_done, budget);
 		r_idx = find_next_bit(q_vector->rxr_idx, adapter->num_rx_queues,
 				      r_idx + 1);
@@ -2019,13 +2196,14 @@ static int ixgbe_clean_txonly(struct nap
 	int work_done = 0;
 	long r_idx;
 
-	r_idx = find_first_bit(q_vector->txr_idx, adapter->num_tx_queues);
-	tx_ring = adapter->tx_ring[r_idx];
 #ifdef CONFIG_IXGBE_DCA
 	if (adapter->flags & IXGBE_FLAG_DCA_ENABLED)
-		ixgbe_update_tx_dca(adapter, tx_ring);
+		ixgbe_update_dca(q_vector);
 #endif
 
+	r_idx = find_first_bit(q_vector->txr_idx, adapter->num_tx_queues);
+	tx_ring = adapter->tx_ring[r_idx];
+
 	if (!ixgbe_clean_tx_irq(q_vector, tx_ring))
 		work_done = budget;
 
@@ -2046,24 +2224,27 @@ static inline void map_vector_to_rxq(str
 				     int r_idx)
 {
 	struct ixgbe_q_vector *q_vector = a->q_vector[v_idx];
+	struct ixgbe_ring *rx_ring = a->rx_ring[r_idx];
 
 	set_bit(r_idx, q_vector->rxr_idx);
 	q_vector->rxr_count++;
+	rx_ring->q_vector = q_vector;
 }
 
 static inline void map_vector_to_txq(struct ixgbe_adapter *a, int v_idx,
 				     int t_idx)
 {
 	struct ixgbe_q_vector *q_vector = a->q_vector[v_idx];
+	struct ixgbe_ring *tx_ring = a->tx_ring[t_idx];
 
 	set_bit(t_idx, q_vector->txr_idx);
 	q_vector->txr_count++;
+	tx_ring->q_vector = q_vector;
 }
 
 /**
  * ixgbe_map_rings_to_vectors - Maps descriptor rings to vectors
  * @adapter: board private structure to initialize
- * @vectors: allotted vector count for descriptor rings
  *
  * This function maps descriptor rings to the queue-specific vectors
  * we were allotted through the MSI-X enabling code.  Ideally, we'd have
@@ -2071,9 +2252,9 @@ static inline void map_vector_to_txq(str
  * group the rings as "efficiently" as possible.  You would add new
  * mapping configurations in here.
  **/
-static int ixgbe_map_rings_to_vectors(struct ixgbe_adapter *adapter,
-				      int vectors)
+static int ixgbe_map_rings_to_vectors(struct ixgbe_adapter *adapter)
 {
+	int q_vectors;
 	int v_start = 0;
 	int rxr_idx = 0, txr_idx = 0;
 	int rxr_remaining = adapter->num_rx_queues;
@@ -2086,11 +2267,13 @@ static int ixgbe_map_rings_to_vectors(st
 	if (!(adapter->flags & IXGBE_FLAG_MSIX_ENABLED))
 		goto out;
 
+	q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS;
+
 	/*
 	 * The ideal configuration...
 	 * We have enough vectors to map one per queue.
 	 */
-	if (vectors == adapter->num_rx_queues + adapter->num_tx_queues) {
+	if (q_vectors == adapter->num_rx_queues + adapter->num_tx_queues) {
 		for (; rxr_idx < rxr_remaining; v_start++, rxr_idx++)
 			map_vector_to_rxq(adapter, v_start, rxr_idx);
 
@@ -2106,23 +2289,20 @@ static int ixgbe_map_rings_to_vectors(st
 	 * multiple queues per vector.
 	 */
 	/* Re-adjusting *qpv takes care of the remainder. */
-	for (i = v_start; i < vectors; i++) {
-		rqpv = DIV_ROUND_UP(rxr_remaining, vectors - i);
+	for (i = v_start; i < q_vectors; i++) {
+		rqpv = DIV_ROUND_UP(rxr_remaining, q_vectors - i);
 		for (j = 0; j < rqpv; j++) {
 			map_vector_to_rxq(adapter, i, rxr_idx);
 			rxr_idx++;
 			rxr_remaining--;
 		}
-	}
-	for (i = v_start; i < vectors; i++) {
-		tqpv = DIV_ROUND_UP(txr_remaining, vectors - i);
+		tqpv = DIV_ROUND_UP(txr_remaining, q_vectors - i);
 		for (j = 0; j < tqpv; j++) {
 			map_vector_to_txq(adapter, i, txr_idx);
 			txr_idx++;
 			txr_remaining--;
 		}
 	}
-
 out:
 	return err;
 }
@@ -2144,30 +2324,36 @@ static int ixgbe_request_msix_irqs(struc
 	/* Decrement for Other and TCP Timer vectors */
 	q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS;
 
-	/* Map the Tx/Rx rings to the vectors we were allotted. */
-	err = ixgbe_map_rings_to_vectors(adapter, q_vectors);
+	err = ixgbe_map_rings_to_vectors(adapter);
 	if (err)
-		goto out;
+		return err;
 
-#define SET_HANDLER(_v) ((!(_v)->rxr_count) ? &ixgbe_msix_clean_tx : \
-			 (!(_v)->txr_count) ? &ixgbe_msix_clean_rx : \
-			 &ixgbe_msix_clean_many)
+#define SET_HANDLER(_v) (((_v)->rxr_count && (_v)->txr_count)        \
+					  ? &ixgbe_msix_clean_many : \
+			  (_v)->rxr_count ? &ixgbe_msix_clean_rx   : \
+			  (_v)->txr_count ? &ixgbe_msix_clean_tx   : \
+			  NULL)
 	for (vector = 0; vector < q_vectors; vector++) {
-		handler = SET_HANDLER(adapter->q_vector[vector]);
+		struct ixgbe_q_vector *q_vector = adapter->q_vector[vector];
+		handler = SET_HANDLER(q_vector);
 
 		if (handler == &ixgbe_msix_clean_rx) {
-			sprintf(adapter->name[vector], "%s-%s-%d",
-				netdev->name, "rx", ri++);
+			snprintf(q_vector->name, sizeof(q_vector->name) - 1,
+			         "%s-%s-%d", netdev->name, "rx", ri++);
 		} else if (handler == &ixgbe_msix_clean_tx) {
-			sprintf(adapter->name[vector], "%s-%s-%d",
-				netdev->name, "tx", ti++);
-		} else
-			sprintf(adapter->name[vector], "%s-%s-%d",
-				netdev->name, "TxRx", vector);
-
+			snprintf(q_vector->name, sizeof(q_vector->name) - 1,
+			         "%s-%s-%d", netdev->name, "tx", ti++);
+		} else if (handler == &ixgbe_msix_clean_many) {
+			snprintf(q_vector->name, sizeof(q_vector->name) - 1,
+			         "%s-%s-%d", netdev->name, "TxRx", ri++);
+			ti++;
+		} else {
+			/* skip this unused q_vector */
+			continue;
+		}
 		err = request_irq(adapter->msix_entries[vector].vector,
-				  handler, 0, adapter->name[vector],
-				  adapter->q_vector[vector]);
+				  handler, 0, q_vector->name,
+				  q_vector);
 		if (err) {
 			e_err(probe, "request_irq failed for MSIX interrupt "
 			      "Error: %d\n", err);
@@ -2175,9 +2361,9 @@ static int ixgbe_request_msix_irqs(struc
 		}
 	}
 
-	sprintf(adapter->name[vector], "%s:lsc", netdev->name);
+	sprintf(adapter->lsc_int_name, "%s:lsc", netdev->name);
 	err = request_irq(adapter->msix_entries[vector].vector,
-			  ixgbe_msix_lsc, 0, adapter->name[vector], netdev);
+			  ixgbe_msix_lsc, 0, adapter->lsc_int_name, netdev);
 	if (err) {
 		e_err(probe, "request_irq for msix_lsc failed: %d\n", err);
 		goto free_queue_irqs;
@@ -2193,17 +2379,16 @@ free_queue_irqs:
 	pci_disable_msix(adapter->pdev);
 	kfree(adapter->msix_entries);
 	adapter->msix_entries = NULL;
-out:
 	return err;
 }
 
 static void ixgbe_set_itr(struct ixgbe_adapter *adapter)
 {
 	struct ixgbe_q_vector *q_vector = adapter->q_vector[0];
-	u8 current_itr;
-	u32 new_itr = q_vector->eitr;
 	struct ixgbe_ring *rx_ring = adapter->rx_ring[0];
 	struct ixgbe_ring *tx_ring = adapter->tx_ring[0];
+	u32 new_itr = q_vector->eitr;
+	u8 current_itr;
 
 	q_vector->tx_itr = ixgbe_update_itr(adapter, new_itr,
 					    q_vector->tx_itr,
@@ -2233,9 +2418,9 @@ static void ixgbe_set_itr(struct ixgbe_a
 
 	if (new_itr != q_vector->eitr) {
 		/* do an exponential smoothing */
-		new_itr = ((q_vector->eitr * 90)/100) + ((new_itr * 10)/100);
+		new_itr = ((q_vector->eitr * 9) + new_itr)/10;
 
-		/* save the algorithm value here, not the smoothed one */
+		/* save the algorithm value here */
 		q_vector->eitr = new_itr;
 
 		ixgbe_write_eitr(q_vector);
@@ -2256,12 +2441,17 @@ static inline void ixgbe_irq_enable(stru
 		mask |= IXGBE_EIMS_GPI_SDP0;
 	if (adapter->flags & IXGBE_FLAG_FAN_FAIL_CAPABLE)
 		mask |= IXGBE_EIMS_GPI_SDP1;
-	if (adapter->hw.mac.type == ixgbe_mac_82599EB) {
+	switch (adapter->hw.mac.type) {
+	case ixgbe_mac_82599EB:
+	case ixgbe_mac_X540:
 		mask |= IXGBE_EIMS_ECC;
 		mask |= IXGBE_EIMS_GPI_SDP1;
 		mask |= IXGBE_EIMS_GPI_SDP2;
 		if (adapter->num_vfs)
 			mask |= IXGBE_EIMS_MAILBOX;
+		break;
+	default:
+		break;
 	}
 	if (adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE ||
 	    adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE)
@@ -2317,13 +2507,20 @@ static irqreturn_t ixgbe_intr(int irq, v
 	if (eicr & IXGBE_EICR_LSC)
 		ixgbe_check_lsc(adapter);
 
-	if (hw->mac.type == ixgbe_mac_82599EB)
+	switch (hw->mac.type) {
+	case ixgbe_mac_82599EB:
 		ixgbe_check_sfp_event(adapter, eicr);
+		if ((adapter->flags2 & IXGBE_FLAG2_TEMP_SENSOR_CAPABLE) &&
+		    ((eicr & IXGBE_EICR_GPI_SDP0) || (eicr & IXGBE_EICR_LSC))) {
+			adapter->interrupt_event = eicr;
+			schedule_work(&adapter->check_overtemp_task);
+		}
+		break;
+	default:
+		break;
+	}
 
 	ixgbe_check_fan_failure(adapter, eicr);
-	if ((adapter->flags2 & IXGBE_FLAG2_TEMP_SENSOR_CAPABLE) &&
-	    ((eicr & IXGBE_EICR_GPI_SDP0) || (eicr & IXGBE_EICR_LSC)))
-		schedule_work(&adapter->check_overtemp_task);
 
 	if (napi_schedule_prep(&(q_vector->napi))) {
 		adapter->tx_ring[0]->total_packets = 0;
@@ -2416,14 +2613,20 @@ static void ixgbe_free_irq(struct ixgbe_
  **/
 static inline void ixgbe_irq_disable(struct ixgbe_adapter *adapter)
 {
-	if (adapter->hw.mac.type == ixgbe_mac_82598EB) {
+	switch (adapter->hw.mac.type) {
+	case ixgbe_mac_82598EB:
 		IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, ~0);
-	} else {
+		break;
+	case ixgbe_mac_82599EB:
+	case ixgbe_mac_X540:
 		IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, 0xFFFF0000);
 		IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC_EX(0), ~0);
 		IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC_EX(1), ~0);
 		if (adapter->num_vfs > 32)
 			IXGBE_WRITE_REG(&adapter->hw, IXGBE_EITRSEL, 0);
+		break;
+	default:
+		break;
 	}
 	IXGBE_WRITE_FLUSH(&adapter->hw);
 	if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) {
@@ -2469,7 +2672,7 @@ void ixgbe_configure_tx_ring(struct ixgb
 	u64 tdba = ring->dma;
 	int wait_loop = 10;
 	u32 txdctl;
-	u16 reg_idx = ring->reg_idx;
+	u8 reg_idx = ring->reg_idx;
 
 	/* disable queue to avoid issues while updating state */
 	txdctl = IXGBE_READ_REG(hw, IXGBE_TXDCTL(reg_idx));
@@ -2484,8 +2687,7 @@ void ixgbe_configure_tx_ring(struct ixgb
 			ring->count * sizeof(union ixgbe_adv_tx_desc));
 	IXGBE_WRITE_REG(hw, IXGBE_TDH(reg_idx), 0);
 	IXGBE_WRITE_REG(hw, IXGBE_TDT(reg_idx), 0);
-	ring->head = IXGBE_TDH(reg_idx);
-	ring->tail = IXGBE_TDT(reg_idx);
+	ring->tail = hw->hw_addr + IXGBE_TDT(reg_idx);
 
 	/* configure fetching thresholds */
 	if (adapter->rx_itr_setting == 0) {
@@ -2501,7 +2703,16 @@ void ixgbe_configure_tx_ring(struct ixgb
 	}
 
 	/* reinitialize flowdirector state */
-	set_bit(__IXGBE_FDIR_INIT_DONE, &ring->reinit_state);
+	if ((adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE) &&
+	    adapter->atr_sample_rate) {
+		ring->atr_sample_rate = adapter->atr_sample_rate;
+		ring->atr_count = 0;
+		set_bit(__IXGBE_TX_FDIR_INIT_DONE, &ring->state);
+	} else {
+		ring->atr_sample_rate = 0;
+	}
+
+	clear_bit(__IXGBE_HANG_CHECK_ARMED, &ring->state);
 
 	/* enable queue */
 	txdctl |= IXGBE_TXDCTL_ENABLE;
@@ -2592,16 +2803,22 @@ static void ixgbe_configure_srrctl(struc
 				   struct ixgbe_ring *rx_ring)
 {
 	u32 srrctl;
-	int index;
-	struct ixgbe_ring_feature *feature = adapter->ring_feature;
+	u8 reg_idx = rx_ring->reg_idx;
 
-	index = rx_ring->reg_idx;
-	if (adapter->hw.mac.type == ixgbe_mac_82598EB) {
-		unsigned long mask;
-		mask = (unsigned long) feature[RING_F_RSS].mask;
-		index = index & mask;
+	switch (adapter->hw.mac.type) {
+	case ixgbe_mac_82598EB: {
+		struct ixgbe_ring_feature *feature = adapter->ring_feature;
+		const int mask = feature[RING_F_RSS].mask;
+		reg_idx = reg_idx & mask;
 	}
-	srrctl = IXGBE_READ_REG(&adapter->hw, IXGBE_SRRCTL(index));
+		break;
+	case ixgbe_mac_82599EB:
+	case ixgbe_mac_X540:
+	default:
+		break;
+	}
+
+	srrctl = IXGBE_READ_REG(&adapter->hw, IXGBE_SRRCTL(reg_idx));
 
 	srrctl &= ~IXGBE_SRRCTL_BSIZEHDR_MASK;
 	srrctl &= ~IXGBE_SRRCTL_BSIZEPKT_MASK;
@@ -2611,7 +2828,7 @@ static void ixgbe_configure_srrctl(struc
 	srrctl |= (IXGBE_RX_HDR_SIZE << IXGBE_SRRCTL_BSIZEHDRSIZE_SHIFT) &
 		  IXGBE_SRRCTL_BSIZEHDR_MASK;
 
-	if (rx_ring->flags & IXGBE_RING_RX_PS_ENABLED) {
+	if (ring_is_ps_enabled(rx_ring)) {
 #if (PAGE_SIZE / 2) > IXGBE_MAX_RXBUFFER
 		srrctl |= IXGBE_MAX_RXBUFFER >> IXGBE_SRRCTL_BSIZEPKT_SHIFT;
 #else
@@ -2624,7 +2841,7 @@ static void ixgbe_configure_srrctl(struc
 		srrctl |= IXGBE_SRRCTL_DESCTYPE_ADV_ONEBUF;
 	}
 
-	IXGBE_WRITE_REG(&adapter->hw, IXGBE_SRRCTL(index), srrctl);
+	IXGBE_WRITE_REG(&adapter->hw, IXGBE_SRRCTL(reg_idx), srrctl);
 }
 
 static void ixgbe_setup_mrqc(struct ixgbe_adapter *adapter)
@@ -2694,19 +2911,36 @@ static void ixgbe_setup_mrqc(struct ixgb
 }
 
 /**
+ * ixgbe_clear_rscctl - disable RSC for the indicated ring
+ * @adapter: address of board private structure
+ * @ring: structure containing ring specific data
+ **/
+void ixgbe_clear_rscctl(struct ixgbe_adapter *adapter,
+                        struct ixgbe_ring *ring)
+{
+	struct ixgbe_hw *hw = &adapter->hw;
+	u32 rscctrl;
+	u8 reg_idx = ring->reg_idx;
+
+	rscctrl = IXGBE_READ_REG(hw, IXGBE_RSCCTL(reg_idx));
+	rscctrl &= ~IXGBE_RSCCTL_RSCEN;
+	IXGBE_WRITE_REG(hw, IXGBE_RSCCTL(reg_idx), rscctrl);
+}
+
+/**
  * ixgbe_configure_rscctl - enable RSC for the indicated ring
  * @adapter:    address of board private structure
  * @index:      index of ring to set
  **/
-static void ixgbe_configure_rscctl(struct ixgbe_adapter *adapter,
+void ixgbe_configure_rscctl(struct ixgbe_adapter *adapter,
 				   struct ixgbe_ring *ring)
 {
 	struct ixgbe_hw *hw = &adapter->hw;
 	u32 rscctrl;
 	int rx_buf_len;
-	u16 reg_idx = ring->reg_idx;
+	u8 reg_idx = ring->reg_idx;
 
-	if (!(adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED))
+	if (!ring_is_rsc_enabled(ring))
 		return;
 
 	rx_buf_len = ring->rx_buf_len;
@@ -2717,7 +2951,7 @@ static void ixgbe_configure_rscctl(struc
 	 * total size of max desc * buf_len is not greater
 	 * than 65535
 	 */
-	if (ring->flags & IXGBE_RING_RX_PS_ENABLED) {
+	if (ring_is_ps_enabled(ring)) {
 #if (MAX_SKB_FRAGS > 16)
 		rscctrl |= IXGBE_RSCCTL_MAXDESC_16;
 #elif (MAX_SKB_FRAGS > 8)
@@ -2770,9 +3004,9 @@ static void ixgbe_rx_desc_queue_enable(s
 				       struct ixgbe_ring *ring)
 {
 	struct ixgbe_hw *hw = &adapter->hw;
-	int reg_idx = ring->reg_idx;
 	int wait_loop = IXGBE_MAX_RX_DESC_POLL;
 	u32 rxdctl;
+	u8 reg_idx = ring->reg_idx;
 
 	/* RXDCTL.EN will return 0 on 82598 if link is down, so skip it */
 	if (hw->mac.type == ixgbe_mac_82598EB &&
@@ -2790,19 +3024,47 @@ static void ixgbe_rx_desc_queue_enable(s
 	}
 }
 
+void ixgbe_disable_rx_queue(struct ixgbe_adapter *adapter,
+			    struct ixgbe_ring *ring)
+{
+	struct ixgbe_hw *hw = &adapter->hw;
+	int wait_loop = IXGBE_MAX_RX_DESC_POLL;
+	u32 rxdctl;
+	u8 reg_idx = ring->reg_idx;
+
+	rxdctl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(reg_idx));
+	rxdctl &= ~IXGBE_RXDCTL_ENABLE;
+
+	/* write value back with RXDCTL.ENABLE bit cleared */
+	IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(reg_idx), rxdctl);
+
+	if (hw->mac.type == ixgbe_mac_82598EB &&
+	    !(IXGBE_READ_REG(hw, IXGBE_LINKS) & IXGBE_LINKS_UP))
+		return;
+
+	/* the hardware may take up to 100us to really disable the rx queue */
+	do {
+		udelay(10);
+		rxdctl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(reg_idx));
+	} while (--wait_loop && (rxdctl & IXGBE_RXDCTL_ENABLE));
+
+	if (!wait_loop) {
+		e_err(drv, "RXDCTL.ENABLE on Rx queue %d not cleared within "
+		      "the polling period\n", reg_idx);
+	}
+}
+
 void ixgbe_configure_rx_ring(struct ixgbe_adapter *adapter,
 			     struct ixgbe_ring *ring)
 {
 	struct ixgbe_hw *hw = &adapter->hw;
 	u64 rdba = ring->dma;
 	u32 rxdctl;
-	u16 reg_idx = ring->reg_idx;
+	u8 reg_idx = ring->reg_idx;
 
 	/* disable queue to avoid issues while updating state */
 	rxdctl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(reg_idx));
-	IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(reg_idx),
-			rxdctl & ~IXGBE_RXDCTL_ENABLE);
-	IXGBE_WRITE_FLUSH(hw);
+	ixgbe_disable_rx_queue(adapter, ring);
 
 	IXGBE_WRITE_REG(hw, IXGBE_RDBAL(reg_idx), (rdba & DMA_BIT_MASK(32)));
 	IXGBE_WRITE_REG(hw, IXGBE_RDBAH(reg_idx), (rdba >> 32));
@@ -2810,8 +3072,7 @@ void ixgbe_configure_rx_ring(struct ixgb
 			ring->count * sizeof(union ixgbe_adv_rx_desc));
 	IXGBE_WRITE_REG(hw, IXGBE_RDH(reg_idx), 0);
 	IXGBE_WRITE_REG(hw, IXGBE_RDT(reg_idx), 0);
-	ring->head = IXGBE_RDH(reg_idx);
-	ring->tail = IXGBE_RDT(reg_idx);
+	ring->tail = hw->hw_addr + IXGBE_RDT(reg_idx);
 
 	ixgbe_configure_srrctl(adapter, ring);
 	ixgbe_configure_rscctl(adapter, ring);
@@ -2833,7 +3094,7 @@ void ixgbe_configure_rx_ring(struct ixgb
 	IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(reg_idx), rxdctl);
 
 	ixgbe_rx_desc_queue_enable(adapter, ring);
-	ixgbe_alloc_rx_buffers(adapter, ring, IXGBE_DESC_UNUSED(ring));
+	ixgbe_alloc_rx_buffers(ring, IXGBE_DESC_UNUSED(ring));
 }
 
 static void ixgbe_setup_psrtype(struct ixgbe_adapter *adapter)
@@ -2899,6 +3160,9 @@ static void ixgbe_configure_virtualizati
 
 	/* enable Tx loopback for VF/PF communication */
 	IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, IXGBE_PFDTXGSWC_VT_LBEN);
+	/* Enable MAC Anti-Spoofing */
+	hw->mac.ops.set_mac_anti_spoofing(hw, (adapter->num_vfs != 0),
+					  adapter->num_vfs);
 }
 
 static void ixgbe_set_rx_buffer_len(struct ixgbe_adapter *adapter)
@@ -2912,9 +3176,16 @@ static void ixgbe_set_rx_buffer_len(stru
 	u32 mhadd, hlreg0;
 
 	/* Decide whether to use packet split mode or not */
+	/* On by default */
+	adapter->flags |= IXGBE_FLAG_RX_PS_ENABLED;
+
 	/* Do not use packet split if we're in SR-IOV Mode */
-	if (!adapter->num_vfs)
-		adapter->flags |= IXGBE_FLAG_RX_PS_ENABLED;
+	if (adapter->num_vfs)
+		adapter->flags &= ~IXGBE_FLAG_RX_PS_ENABLED;
+
+	/* Disable packet split due to 82599 erratum #45 */
+	if (hw->mac.type == ixgbe_mac_82599EB)
+		adapter->flags &= ~IXGBE_FLAG_RX_PS_ENABLED;
 
 	/* Set the RX buffer length according to the mode */
 	if (adapter->flags & IXGBE_FLAG_RX_PS_ENABLED) {
@@ -2956,24 +3227,32 @@ static void ixgbe_set_rx_buffer_len(stru
 		rx_ring->rx_buf_len = rx_buf_len;
 
 		if (adapter->flags & IXGBE_FLAG_RX_PS_ENABLED)
-			rx_ring->flags |= IXGBE_RING_RX_PS_ENABLED;
+			set_ring_ps_enabled(rx_ring);
 		else
-			rx_ring->flags &= ~IXGBE_RING_RX_PS_ENABLED;
+			clear_ring_ps_enabled(rx_ring);
+
+		if (adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED)
+			set_ring_rsc_enabled(rx_ring);
+		else
+			clear_ring_rsc_enabled(rx_ring);
 
 #ifdef IXGBE_FCOE
 		if (netdev->features & NETIF_F_FCOE_MTU) {
 			struct ixgbe_ring_feature *f;
 			f = &adapter->ring_feature[RING_F_FCOE];
 			if ((i >= f->mask) && (i < f->mask + f->indices)) {
-				rx_ring->flags &= ~IXGBE_RING_RX_PS_ENABLED;
+				clear_ring_ps_enabled(rx_ring);
 				if (rx_buf_len < IXGBE_FCOE_JUMBO_FRAME_SIZE)
 					rx_ring->rx_buf_len =
 						IXGBE_FCOE_JUMBO_FRAME_SIZE;
+			} else if (!ring_is_rsc_enabled(rx_ring) &&
+				   !ring_is_ps_enabled(rx_ring)) {
+				rx_ring->rx_buf_len =
+						IXGBE_FCOE_JUMBO_FRAME_SIZE;
 			}
 		}
 #endif /* IXGBE_FCOE */
 	}
-
 }
 
 static void ixgbe_setup_rdrxctl(struct ixgbe_adapter *adapter)
@@ -2996,6 +3275,7 @@ static void ixgbe_setup_rdrxctl(struct i
 		rdrxctl |= IXGBE_RDRXCTL_MVMEN;
 		break;
 	case ixgbe_mac_82599EB:
+	case ixgbe_mac_X540:
 		/* Disable RSC for ACK packets */
 		IXGBE_WRITE_REG(hw, IXGBE_RSCDBU,
 		   (IXGBE_RSCDBU_RSCACKDIS | IXGBE_READ_REG(hw, IXGBE_RSCDBU)));
@@ -3123,6 +3403,7 @@ static void ixgbe_vlan_strip_disable(str
 		IXGBE_WRITE_REG(hw, IXGBE_VLNCTRL, vlnctrl);
 		break;
 	case ixgbe_mac_82599EB:
+	case ixgbe_mac_X540:
 		for (i = 0; i < adapter->num_rx_queues; i++) {
 			j = adapter->rx_ring[i]->reg_idx;
 			vlnctrl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(j));
@@ -3152,6 +3433,7 @@ static void ixgbe_vlan_strip_enable(stru
 		IXGBE_WRITE_REG(hw, IXGBE_VLNCTRL, vlnctrl);
 		break;
 	case ixgbe_mac_82599EB:
+	case ixgbe_mac_X540:
 		for (i = 0; i < adapter->num_rx_queues; i++) {
 			j = adapter->rx_ring[i]->reg_idx;
 			vlnctrl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(j));
@@ -3349,8 +3631,6 @@ static void ixgbe_configure_dcb(struct i
 {
 	struct ixgbe_hw *hw = &adapter->hw;
 	int max_frame = adapter->netdev->mtu + ETH_HLEN + ETH_FCS_LEN;
-	u32 txdctl;
-	int i, j;
 
 	if (!(adapter->flags & IXGBE_FLAG_DCB_ENABLED)) {
 		if (hw->mac.type == ixgbe_mac_82598EB)
@@ -3366,25 +3646,18 @@ static void ixgbe_configure_dcb(struct i
 		max_frame = max(max_frame, IXGBE_FCOE_JUMBO_FRAME_SIZE);
 #endif
 
-	ixgbe_dcb_calculate_tc_credits(&adapter->dcb_cfg, max_frame,
+	ixgbe_dcb_calculate_tc_credits(hw, &adapter->dcb_cfg, max_frame,
 					DCB_TX_CONFIG);
-	ixgbe_dcb_calculate_tc_credits(&adapter->dcb_cfg, max_frame,
+	ixgbe_dcb_calculate_tc_credits(hw, &adapter->dcb_cfg, max_frame,
 					DCB_RX_CONFIG);
 
-	/* reconfigure the hardware */
-	ixgbe_dcb_hw_config(&adapter->hw, &adapter->dcb_cfg);
-
-	for (i = 0; i < adapter->num_tx_queues; i++) {
-		j = adapter->tx_ring[i]->reg_idx;
-		txdctl = IXGBE_READ_REG(hw, IXGBE_TXDCTL(j));
-		/* PThresh workaround for Tx hang with DFP enabled. */
-		txdctl |= 32;
-		IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(j), txdctl);
-	}
 	/* Enable VLAN tag insert/strip */
 	adapter->netdev->features |= NETIF_F_HW_VLAN_RX;
 
 	hw->mac.ops.set_vfta(&adapter->hw, 0, 0, true);
+
+	/* reconfigure the hardware */
+	ixgbe_dcb_hw_config(hw, &adapter->dcb_cfg);
 }
 
 #endif
@@ -3455,7 +3728,8 @@ static void ixgbe_sfp_link_config(struct
 			 * We need to try and force an autonegotiation
 			 * session, then bring up link.
 			 */
-			hw->mac.ops.setup_sfp(hw);
+			if (hw->mac.ops.setup_sfp)
+				hw->mac.ops.setup_sfp(hw);
 			if (!(adapter->flags & IXGBE_FLAG_IN_SFP_LINK_TASK))
 				schedule_work(&adapter->multispeed_fiber_task);
 		} else {
@@ -3516,8 +3790,9 @@ static void ixgbe_setup_gpie(struct ixgb
 		case ixgbe_mac_82598EB:
 			IXGBE_WRITE_REG(hw, IXGBE_EIAM, IXGBE_EICS_RTX_QUEUE);
 			break;
-		default:
 		case ixgbe_mac_82599EB:
+		case ixgbe_mac_X540:
+		default:
 			IXGBE_WRITE_REG(hw, IXGBE_EIAM_EX(0), 0xFFFFFFFF);
 			IXGBE_WRITE_REG(hw, IXGBE_EIAM_EX(1), 0xFFFFFFFF);
 			break;
@@ -3561,13 +3836,24 @@ static int ixgbe_up_complete(struct ixgb
 	else
 		ixgbe_configure_msi_and_legacy(adapter);
 
-	/* enable the optics */
-	if (hw->phy.multispeed_fiber)
+	/* enable the optics for both mult-speed fiber and 82599 SFP+ fiber */
+	if (hw->mac.ops.enable_tx_laser &&
+	    ((hw->phy.multispeed_fiber) ||
+	     ((hw->mac.ops.get_media_type(hw) == ixgbe_media_type_fiber) &&
+	      (hw->mac.type == ixgbe_mac_82599EB))))
 		hw->mac.ops.enable_tx_laser(hw);
 
 	clear_bit(__IXGBE_DOWN, &adapter->state);
 	ixgbe_napi_enable_all(adapter);
 
+	if (ixgbe_is_sfp(hw)) {
+		ixgbe_sfp_link_config(adapter);
+	} else {
+		err = ixgbe_non_sfp_link_config(hw);
+		if (err)
+			e_err(probe, "link_config FAILED %d\n", err);
+	}
+
 	/* clear any pending interrupts, may auto mask */
 	IXGBE_READ_REG(hw, IXGBE_EICR);
 	ixgbe_irq_enable(adapter, true, true);
@@ -3590,26 +3876,8 @@ static int ixgbe_up_complete(struct ixgb
 	 * If we're not hot-pluggable SFP+, we just need to configure link
 	 * and bring it up.
 	 */
-	if (hw->phy.type == ixgbe_phy_unknown) {
-		err = hw->phy.ops.identify(hw);
-		if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) {
-			/*
-			 * Take the device down and schedule the sfp tasklet
-			 * which will unregister_netdev and log it.
-			 */
-			ixgbe_down(adapter);
-			schedule_work(&adapter->sfp_config_module_task);
-			return err;
-		}
-	}
-
-	if (ixgbe_is_sfp(hw)) {
-		ixgbe_sfp_link_config(adapter);
-	} else {
-		err = ixgbe_non_sfp_link_config(hw);
-		if (err)
-			e_err(probe, "link_config FAILED %d\n", err);
-	}
+	if (hw->phy.type == ixgbe_phy_unknown)
+		schedule_work(&adapter->sfp_config_module_task);
 
 	/* enable transmits */
 	netif_tx_start_all_queues(adapter->netdev);
@@ -3687,15 +3955,13 @@ void ixgbe_reset(struct ixgbe_adapter *a
 
 /**
  * ixgbe_clean_rx_ring - Free Rx Buffers per Queue
- * @adapter: board private structure
  * @rx_ring: ring to free buffers from
  **/
-static void ixgbe_clean_rx_ring(struct ixgbe_adapter *adapter,
-				struct ixgbe_ring *rx_ring)
+static void ixgbe_clean_rx_ring(struct ixgbe_ring *rx_ring)
 {
-	struct pci_dev *pdev = adapter->pdev;
+	struct device *dev = rx_ring->dev;
 	unsigned long size;
-	unsigned int i;
+	u16 i;
 
 	/* ring already cleared, nothing to do */
 	if (!rx_ring->rx_buffer_info)
@@ -3707,7 +3973,7 @@ static void ixgbe_clean_rx_ring(struct i
 
 		rx_buffer_info = &rx_ring->rx_buffer_info[i];
 		if (rx_buffer_info->dma) {
-			dma_unmap_single(&pdev->dev, rx_buffer_info->dma,
+			dma_unmap_single(rx_ring->dev, rx_buffer_info->dma,
 					 rx_ring->rx_buf_len,
 					 DMA_FROM_DEVICE);
 			rx_buffer_info->dma = 0;
@@ -3718,7 +3984,7 @@ static void ixgbe_clean_rx_ring(struct i
 			do {
 				struct sk_buff *this = skb;
 				if (IXGBE_RSC_CB(this)->delay_unmap) {
-					dma_unmap_single(&pdev->dev,
+					dma_unmap_single(dev,
 							 IXGBE_RSC_CB(this)->dma,
 							 rx_ring->rx_buf_len,
 							 DMA_FROM_DEVICE);
@@ -3732,7 +3998,7 @@ static void ixgbe_clean_rx_ring(struct i
 		if (!rx_buffer_info->page)
 			continue;
 		if (rx_buffer_info->page_dma) {
-			dma_unmap_page(&pdev->dev, rx_buffer_info->page_dma,
+			dma_unmap_page(dev, rx_buffer_info->page_dma,
 				       PAGE_SIZE / 2, DMA_FROM_DEVICE);
 			rx_buffer_info->page_dma = 0;
 		}
@@ -3749,24 +4015,17 @@ static void ixgbe_clean_rx_ring(struct i
 
 	rx_ring->next_to_clean = 0;
 	rx_ring->next_to_use = 0;
-
-	if (rx_ring->head)
-		writel(0, adapter->hw.hw_addr + rx_ring->head);
-	if (rx_ring->tail)
-		writel(0, adapter->hw.hw_addr + rx_ring->tail);
 }
 
 /**
  * ixgbe_clean_tx_ring - Free Tx Buffers
- * @adapter: board private structure
  * @tx_ring: ring to be cleaned
  **/
-static void ixgbe_clean_tx_ring(struct ixgbe_adapter *adapter,
-				struct ixgbe_ring *tx_ring)
+static void ixgbe_clean_tx_ring(struct ixgbe_ring *tx_ring)
 {
 	struct ixgbe_tx_buffer *tx_buffer_info;
 	unsigned long size;
-	unsigned int i;
+	u16 i;
 
 	/* ring already cleared, nothing to do */
 	if (!tx_ring->tx_buffer_info)
@@ -3775,7 +4034,7 @@ static void ixgbe_clean_tx_ring(struct i
 	/* Free all the Tx ring sk_buffs */
 	for (i = 0; i < tx_ring->count; i++) {
 		tx_buffer_info = &tx_ring->tx_buffer_info[i];
-		ixgbe_unmap_and_free_tx_resource(adapter, tx_buffer_info);
+		ixgbe_unmap_and_free_tx_resource(tx_ring, tx_buffer_info);
 	}
 
 	size = sizeof(struct ixgbe_tx_buffer) * tx_ring->count;
@@ -3786,11 +4045,6 @@ static void ixgbe_clean_tx_ring(struct i
 
 	tx_ring->next_to_use = 0;
 	tx_ring->next_to_clean = 0;
-
-	if (tx_ring->head)
-		writel(0, adapter->hw.hw_addr + tx_ring->head);
-	if (tx_ring->tail)
-		writel(0, adapter->hw.hw_addr + tx_ring->tail);
 }
 
 /**
@@ -3802,7 +4056,7 @@ static void ixgbe_clean_all_rx_rings(str
 	int i;
 
 	for (i = 0; i < adapter->num_rx_queues; i++)
-		ixgbe_clean_rx_ring(adapter, adapter->rx_ring[i]);
+		ixgbe_clean_rx_ring(adapter->rx_ring[i]);
 }
 
 /**
@@ -3814,7 +4068,7 @@ static void ixgbe_clean_all_tx_rings(str
 	int i;
 
 	for (i = 0; i < adapter->num_tx_queues; i++)
-		ixgbe_clean_tx_ring(adapter, adapter->tx_ring[i]);
+		ixgbe_clean_tx_ring(adapter->tx_ring[i]);
 }
 
 void ixgbe_down(struct ixgbe_adapter *adapter)
@@ -3823,7 +4077,7 @@ void ixgbe_down(struct ixgbe_adapter *ad
 	struct ixgbe_hw *hw = &adapter->hw;
 	u32 rxctrl;
 	u32 txdctl;
-	int i, j;
+	int i;
 	int num_q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS;
 
 	/* signal that we are down to the interrupt handler */
@@ -3846,7 +4100,11 @@ void ixgbe_down(struct ixgbe_adapter *ad
 	rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL);
 	IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, rxctrl & ~IXGBE_RXCTRL_RXEN);
 
-	IXGBE_WRITE_FLUSH(hw);
+	/* disable all enabled rx queues */
+	for (i = 0; i < adapter->num_rx_queues; i++)
+		/* this call also flushes the previous write */
+		ixgbe_disable_rx_queue(adapter, adapter->rx_ring[i]);
+
 	msleep(10);
 
 	netif_tx_stop_all_queues(netdev);
@@ -3881,26 +4139,36 @@ void ixgbe_down(struct ixgbe_adapter *ad
 
 	/* disable transmits in the hardware now that interrupts are off */
 	for (i = 0; i < adapter->num_tx_queues; i++) {
-		j = adapter->tx_ring[i]->reg_idx;
-		txdctl = IXGBE_READ_REG(hw, IXGBE_TXDCTL(j));
-		IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(j),
+		u8 reg_idx = adapter->tx_ring[i]->reg_idx;
+		txdctl = IXGBE_READ_REG(hw, IXGBE_TXDCTL(reg_idx));
+		IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(reg_idx),
 				(txdctl & ~IXGBE_TXDCTL_ENABLE));
 	}
 	/* Disable the Tx DMA engine on 82599 */
-	if (hw->mac.type == ixgbe_mac_82599EB)
+	switch (hw->mac.type) {
+	case ixgbe_mac_82599EB:
+	case ixgbe_mac_X540:
 		IXGBE_WRITE_REG(hw, IXGBE_DMATXCTL,
 				(IXGBE_READ_REG(hw, IXGBE_DMATXCTL) &
 				 ~IXGBE_DMATXCTL_TE));
-
-	/* power down the optics */
-	if (hw->phy.multispeed_fiber)
-		hw->mac.ops.disable_tx_laser(hw);
+		break;
+	default:
+		break;
+	}
 
 	/* clear n-tuple filters that are cached */
 	ethtool_ntuple_flush(netdev);
 
 	if (!pci_channel_offline(adapter->pdev))
 		ixgbe_reset(adapter);
+
+	/* power down the optics for multispeed fiber and 82599 SFP+ fiber */
+	if (hw->mac.ops.disable_tx_laser &&
+	    ((hw->phy.multispeed_fiber) ||
+	     ((hw->mac.ops.get_media_type(hw) == ixgbe_media_type_fiber) &&
+	      (hw->mac.type == ixgbe_mac_82599EB))))
+		hw->mac.ops.disable_tx_laser(hw);
+
 	ixgbe_clean_all_tx_rings(adapter);
 	ixgbe_clean_all_rx_rings(adapter);
 
@@ -3925,10 +4193,8 @@ static int ixgbe_poll(struct napi_struct
 	int tx_clean_complete, work_done = 0;
 
 #ifdef CONFIG_IXGBE_DCA
-	if (adapter->flags & IXGBE_FLAG_DCA_ENABLED) {
-		ixgbe_update_tx_dca(adapter, adapter->tx_ring[0]);
-		ixgbe_update_rx_dca(adapter, adapter->rx_ring[0]);
-	}
+	if (adapter->flags & IXGBE_FLAG_DCA_ENABLED)
+		ixgbe_update_dca(q_vector);
 #endif
 
 	tx_clean_complete = ixgbe_clean_tx_irq(q_vector, adapter->tx_ring[0]);
@@ -3956,6 +4222,8 @@ static void ixgbe_tx_timeout(struct net_
 {
 	struct ixgbe_adapter *adapter = netdev_priv(netdev);
 
+	adapter->tx_timeout_count++;
+
 	/* Do the reset outside of interrupt context */
 	schedule_work(&adapter->reset_task);
 }
@@ -3970,8 +4238,6 @@ static void ixgbe_reset_task(struct work
 	    test_bit(__IXGBE_RESETTING, &adapter->state))
 		return;
 
-	adapter->tx_timeout_count++;
-
 	ixgbe_dump(adapter);
 	netdev_err(adapter->netdev, "Reset adapter\n");
 	ixgbe_reinit_locked(adapter);
@@ -4221,19 +4487,16 @@ static void ixgbe_acquire_msix_vectors(s
 static inline bool ixgbe_cache_ring_rss(struct ixgbe_adapter *adapter)
 {
 	int i;
-	bool ret = false;
 
-	if (adapter->flags & IXGBE_FLAG_RSS_ENABLED) {
-		for (i = 0; i < adapter->num_rx_queues; i++)
-			adapter->rx_ring[i]->reg_idx = i;
-		for (i = 0; i < adapter->num_tx_queues; i++)
-			adapter->tx_ring[i]->reg_idx = i;
-		ret = true;
-	} else {
-		ret = false;
-	}
+	if (!(adapter->flags & IXGBE_FLAG_RSS_ENABLED))
+		return false;
 
-	return ret;
+	for (i = 0; i < adapter->num_rx_queues; i++)
+		adapter->rx_ring[i]->reg_idx = i;
+	for (i = 0; i < adapter->num_tx_queues; i++)
+		adapter->tx_ring[i]->reg_idx = i;
+
+	return true;
 }
 
 #ifdef CONFIG_IXGBE_DCB
@@ -4250,71 +4513,67 @@ static inline bool ixgbe_cache_ring_dcb(
 	bool ret = false;
 	int dcb_i = adapter->ring_feature[RING_F_DCB].indices;
 
-	if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) {
-		if (adapter->hw.mac.type == ixgbe_mac_82598EB) {
-			/* the number of queues is assumed to be symmetric */
-			for (i = 0; i < dcb_i; i++) {
-				adapter->rx_ring[i]->reg_idx = i << 3;
-				adapter->tx_ring[i]->reg_idx = i << 2;
-			}
-			ret = true;
-		} else if (adapter->hw.mac.type == ixgbe_mac_82599EB) {
-			if (dcb_i == 8) {
-				/*
-				 * Tx TC0 starts at: descriptor queue 0
-				 * Tx TC1 starts at: descriptor queue 32
-				 * Tx TC2 starts at: descriptor queue 64
-				 * Tx TC3 starts at: descriptor queue 80
-				 * Tx TC4 starts at: descriptor queue 96
-				 * Tx TC5 starts at: descriptor queue 104
-				 * Tx TC6 starts at: descriptor queue 112
-				 * Tx TC7 starts at: descriptor queue 120
-				 *
-				 * Rx TC0-TC7 are offset by 16 queues each
-				 */
-				for (i = 0; i < 3; i++) {
-					adapter->tx_ring[i]->reg_idx = i << 5;
-					adapter->rx_ring[i]->reg_idx = i << 4;
-				}
-				for ( ; i < 5; i++) {
-					adapter->tx_ring[i]->reg_idx =
-								 ((i + 2) << 4);
-					adapter->rx_ring[i]->reg_idx = i << 4;
-				}
-				for ( ; i < dcb_i; i++) {
-					adapter->tx_ring[i]->reg_idx =
-								 ((i + 8) << 3);
-					adapter->rx_ring[i]->reg_idx = i << 4;
-				}
-
-				ret = true;
-			} else if (dcb_i == 4) {
-				/*
-				 * Tx TC0 starts at: descriptor queue 0
-				 * Tx TC1 starts at: descriptor queue 64
-				 * Tx TC2 starts at: descriptor queue 96
-				 * Tx TC3 starts at: descriptor queue 112
-				 *
-				 * Rx TC0-TC3 are offset by 32 queues each
-				 */
-				adapter->tx_ring[0]->reg_idx = 0;
-				adapter->tx_ring[1]->reg_idx = 64;
-				adapter->tx_ring[2]->reg_idx = 96;
-				adapter->tx_ring[3]->reg_idx = 112;
-				for (i = 0 ; i < dcb_i; i++)
-					adapter->rx_ring[i]->reg_idx = i << 5;
+	if (!(adapter->flags & IXGBE_FLAG_DCB_ENABLED))
+		return false;
 
-				ret = true;
-			} else {
-				ret = false;
+	/* the number of queues is assumed to be symmetric */
+	switch (adapter->hw.mac.type) {
+	case ixgbe_mac_82598EB:
+		for (i = 0; i < dcb_i; i++) {
+			adapter->rx_ring[i]->reg_idx = i << 3;
+			adapter->tx_ring[i]->reg_idx = i << 2;
+		}
+		ret = true;
+		break;
+	case ixgbe_mac_82599EB:
+	case ixgbe_mac_X540:
+		if (dcb_i == 8) {
+			/*
+			 * Tx TC0 starts at: descriptor queue 0
+			 * Tx TC1 starts at: descriptor queue 32
+			 * Tx TC2 starts at: descriptor queue 64
+			 * Tx TC3 starts at: descriptor queue 80
+			 * Tx TC4 starts at: descriptor queue 96
+			 * Tx TC5 starts at: descriptor queue 104
+			 * Tx TC6 starts at: descriptor queue 112
+			 * Tx TC7 starts at: descriptor queue 120
+			 *
+			 * Rx TC0-TC7 are offset by 16 queues each
+			 */
+			for (i = 0; i < 3; i++) {
+				adapter->tx_ring[i]->reg_idx = i << 5;
+				adapter->rx_ring[i]->reg_idx = i << 4;
 			}
-		} else {
-			ret = false;
+			for ( ; i < 5; i++) {
+				adapter->tx_ring[i]->reg_idx = ((i + 2) << 4);
+				adapter->rx_ring[i]->reg_idx = i << 4;
+			}
+			for ( ; i < dcb_i; i++) {
+				adapter->tx_ring[i]->reg_idx = ((i + 8) << 3);
+				adapter->rx_ring[i]->reg_idx = i << 4;
+			}
+			ret = true;
+		} else if (dcb_i == 4) {
+			/*
+			 * Tx TC0 starts at: descriptor queue 0
+			 * Tx TC1 starts at: descriptor queue 64
+			 * Tx TC2 starts at: descriptor queue 96
+			 * Tx TC3 starts at: descriptor queue 112
+			 *
+			 * Rx TC0-TC3 are offset by 32 queues each
+			 */
+			adapter->tx_ring[0]->reg_idx = 0;
+			adapter->tx_ring[1]->reg_idx = 64;
+			adapter->tx_ring[2]->reg_idx = 96;
+			adapter->tx_ring[3]->reg_idx = 112;
+			for (i = 0 ; i < dcb_i; i++)
+				adapter->rx_ring[i]->reg_idx = i << 5;
+			ret = true;
 		}
-	} else {
-		ret = false;
+		break;
+	default:
+		break;
 	}
-
 	return ret;
 }
 #endif
@@ -4354,55 +4613,55 @@ static inline bool ixgbe_cache_ring_fdir
  */
 static inline bool ixgbe_cache_ring_fcoe(struct ixgbe_adapter *adapter)
 {
-	int i, fcoe_rx_i = 0, fcoe_tx_i = 0;
-	bool ret = false;
 	struct ixgbe_ring_feature *f = &adapter->ring_feature[RING_F_FCOE];
+	int i;
+	u8 fcoe_rx_i = 0, fcoe_tx_i = 0;
+
+	if (!(adapter->flags & IXGBE_FLAG_FCOE_ENABLED))
+		return false;
 
-	if (adapter->flags & IXGBE_FLAG_FCOE_ENABLED) {
 #ifdef CONFIG_IXGBE_DCB
-		if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) {
-			struct ixgbe_fcoe *fcoe = &adapter->fcoe;
+	if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) {
+		struct ixgbe_fcoe *fcoe = &adapter->fcoe;
 
-			ixgbe_cache_ring_dcb(adapter);
-			/* find out queues in TC for FCoE */
-			fcoe_rx_i = adapter->rx_ring[fcoe->tc]->reg_idx + 1;
-			fcoe_tx_i = adapter->tx_ring[fcoe->tc]->reg_idx + 1;
-			/*
-			 * In 82599, the number of Tx queues for each traffic
-			 * class for both 8-TC and 4-TC modes are:
-			 * TCs  : TC0 TC1 TC2 TC3 TC4 TC5 TC6 TC7
-			 * 8 TCs:  32  32  16  16   8   8   8   8
-			 * 4 TCs:  64  64  32  32
-			 * We have max 8 queues for FCoE, where 8 the is
-			 * FCoE redirection table size. If TC for FCoE is
-			 * less than or equal to TC3, we have enough queues
-			 * to add max of 8 queues for FCoE, so we start FCoE
-			 * tx descriptor from the next one, i.e., reg_idx + 1.
-			 * If TC for FCoE is above TC3, implying 8 TC mode,
-			 * and we need 8 for FCoE, we have to take all queues
-			 * in that traffic class for FCoE.
-			 */
-			if ((f->indices == IXGBE_FCRETA_SIZE) && (fcoe->tc > 3))
-				fcoe_tx_i--;
-		}
+		ixgbe_cache_ring_dcb(adapter);
+		/* find out queues in TC for FCoE */
+		fcoe_rx_i = adapter->rx_ring[fcoe->tc]->reg_idx + 1;
+		fcoe_tx_i = adapter->tx_ring[fcoe->tc]->reg_idx + 1;
+		/*
+		 * In 82599, the number of Tx queues for each traffic
+		 * class for both 8-TC and 4-TC modes are:
+		 * TCs  : TC0 TC1 TC2 TC3 TC4 TC5 TC6 TC7
+		 * 8 TCs:  32  32  16  16   8   8   8   8
+		 * 4 TCs:  64  64  32  32
+		 * We have max 8 queues for FCoE, where 8 the is
+		 * FCoE redirection table size. If TC for FCoE is
+		 * less than or equal to TC3, we have enough queues
+		 * to add max of 8 queues for FCoE, so we start FCoE
+		 * Tx queue from the next one, i.e., reg_idx + 1.
+		 * If TC for FCoE is above TC3, implying 8 TC mode,
+		 * and we need 8 for FCoE, we have to take all queues
+		 * in that traffic class for FCoE.
+		 */
+		if ((f->indices == IXGBE_FCRETA_SIZE) && (fcoe->tc > 3))
+			fcoe_tx_i--;
+	}
 #endif /* CONFIG_IXGBE_DCB */
-		if (adapter->flags & IXGBE_FLAG_RSS_ENABLED) {
-			if ((adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE) ||
-			    (adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE))
-				ixgbe_cache_ring_fdir(adapter);
-			else
-				ixgbe_cache_ring_rss(adapter);
+	if (adapter->flags & IXGBE_FLAG_RSS_ENABLED) {
+		if ((adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE) ||
+		    (adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE))
+			ixgbe_cache_ring_fdir(adapter);
+		else
+			ixgbe_cache_ring_rss(adapter);
 
-			fcoe_rx_i = f->mask;
-			fcoe_tx_i = f->mask;
-		}
-		for (i = 0; i < f->indices; i++, fcoe_rx_i++, fcoe_tx_i++) {
-			adapter->rx_ring[f->mask + i]->reg_idx = fcoe_rx_i;
-			adapter->tx_ring[f->mask + i]->reg_idx = fcoe_tx_i;
-		}
-		ret = true;
+		fcoe_rx_i = f->mask;
+		fcoe_tx_i = f->mask;
 	}
-	return ret;
+	for (i = 0; i < f->indices; i++, fcoe_rx_i++, fcoe_tx_i++) {
+		adapter->rx_ring[f->mask + i]->reg_idx = fcoe_rx_i;
+		adapter->tx_ring[f->mask + i]->reg_idx = fcoe_tx_i;
+	}
+	return true;
 }
 
 #endif /* IXGBE_FCOE */
@@ -4471,65 +4730,55 @@ static void ixgbe_cache_ring_register(st
  **/
 static int ixgbe_alloc_queues(struct ixgbe_adapter *adapter)
 {
-	int i;
-	int orig_node = adapter->node;
+	int rx = 0, tx = 0, nid = adapter->node;
 
-	for (i = 0; i < adapter->num_tx_queues; i++) {
-		struct ixgbe_ring *ring = adapter->tx_ring[i];
-		if (orig_node == -1) {
-			int cur_node = next_online_node(adapter->node);
-			if (cur_node == MAX_NUMNODES)
-				cur_node = first_online_node;
-			adapter->node = cur_node;
-		}
-		ring = kzalloc_node(sizeof(struct ixgbe_ring), GFP_KERNEL,
-				    adapter->node);
+	if (nid < 0 || !node_online(nid))
+		nid = first_online_node;
+
+	for (; tx < adapter->num_tx_queues; tx++) {
+		struct ixgbe_ring *ring;
+
+		ring = kzalloc_node(sizeof(*ring), GFP_KERNEL, nid);
 		if (!ring)
-			ring = kzalloc(sizeof(struct ixgbe_ring), GFP_KERNEL);
+			ring = kzalloc(sizeof(*ring), GFP_KERNEL);
 		if (!ring)
-			goto err_tx_ring_allocation;
+			goto err_allocation;
 		ring->count = adapter->tx_ring_count;
-		ring->queue_index = i;
-		ring->numa_node = adapter->node;
+		ring->queue_index = tx;
+		ring->numa_node = nid;
+		ring->dev = &adapter->pdev->dev;
+		ring->netdev = adapter->netdev;
 
-		adapter->tx_ring[i] = ring;
+		adapter->tx_ring[tx] = ring;
 	}
 
-	/* Restore the adapter's original node */
-	adapter->node = orig_node;
+	for (; rx < adapter->num_rx_queues; rx++) {
+		struct ixgbe_ring *ring;
 
-	for (i = 0; i < adapter->num_rx_queues; i++) {
-		struct ixgbe_ring *ring = adapter->rx_ring[i];
-		if (orig_node == -1) {
-			int cur_node = next_online_node(adapter->node);
-			if (cur_node == MAX_NUMNODES)
-				cur_node = first_online_node;
-			adapter->node = cur_node;
-		}
-		ring = kzalloc_node(sizeof(struct ixgbe_ring), GFP_KERNEL,
-				    adapter->node);
+		ring = kzalloc_node(sizeof(*ring), GFP_KERNEL, nid);
 		if (!ring)
-			ring = kzalloc(sizeof(struct ixgbe_ring), GFP_KERNEL);
+			ring = kzalloc(sizeof(*ring), GFP_KERNEL);
 		if (!ring)
-			goto err_rx_ring_allocation;
+			goto err_allocation;
 		ring->count = adapter->rx_ring_count;
-		ring->queue_index = i;
-		ring->numa_node = adapter->node;
+		ring->queue_index = rx;
+		ring->numa_node = nid;
+		ring->dev = &adapter->pdev->dev;
+		ring->netdev = adapter->netdev;
 
-		adapter->rx_ring[i] = ring;
+		adapter->rx_ring[rx] = ring;
 	}
 
-	/* Restore the adapter's original node */
-	adapter->node = orig_node;
-
 	ixgbe_cache_ring_register(adapter);
 
 	return 0;
 
-err_rx_ring_allocation:
-	for (i = 0; i < adapter->num_tx_queues; i++)
-		kfree(adapter->tx_ring[i]);
-err_tx_ring_allocation:
+err_allocation:
+	while (tx)
+		kfree(adapter->tx_ring[--tx]);
+
+	while (rx)
+		kfree(adapter->rx_ring[--rx]);
 	return -ENOMEM;
 }
 
@@ -4580,6 +4829,12 @@ static int ixgbe_set_interrupt_capabilit
 
 	adapter->flags &= ~IXGBE_FLAG_DCB_ENABLED;
 	adapter->flags &= ~IXGBE_FLAG_RSS_ENABLED;
+	if (adapter->flags & (IXGBE_FLAG_FDIR_HASH_CAPABLE |
+			      IXGBE_FLAG_FDIR_PERFECT_CAPABLE)) {
+		e_err(probe,
+		      "Flow Director is not supported while multiple "
+		      "queues are disabled.  Disabling Flow Director\n");
+	}
 	adapter->flags &= ~IXGBE_FLAG_FDIR_HASH_CAPABLE;
 	adapter->flags &= ~IXGBE_FLAG_FDIR_PERFECT_CAPABLE;
 	adapter->atr_sample_rate = 0;
@@ -4616,16 +4871,13 @@ static int ixgbe_alloc_q_vectors(struct
 {
 	int q_idx, num_q_vectors;
 	struct ixgbe_q_vector *q_vector;
-	int napi_vectors;
 	int (*poll)(struct napi_struct *, int);
 
 	if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) {
 		num_q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS;
-		napi_vectors = adapter->num_rx_queues;
 		poll = &ixgbe_clean_rxtx_many;
 	} else {
 		num_q_vectors = 1;
-		napi_vectors = 1;
 		poll = &ixgbe_poll;
 	}
 
@@ -4751,6 +5003,11 @@ err_set_interrupt:
 	return err;
 }
 
+static void ring_free_rcu(struct rcu_head *head)
+{
+	kfree(container_of(head, struct ixgbe_ring, rcu));
+}
+
 /**
  * ixgbe_clear_interrupt_scheme - Clear the current interrupt scheme settings
  * @adapter: board private structure to clear interrupt scheme on
@@ -4767,7 +5024,12 @@ void ixgbe_clear_interrupt_scheme(struct
 		adapter->tx_ring[i] = NULL;
 	}
 	for (i = 0; i < adapter->num_rx_queues; i++) {
-		kfree(adapter->rx_ring[i]);
+		struct ixgbe_ring *ring = adapter->rx_ring[i];
+
+		/* ixgbe_get_stats64() might access this ring, we must wait
+		 * a grace period before freeing it.
+		 */
+		call_rcu(&ring->rcu, ring_free_rcu);
 		adapter->rx_ring[i] = NULL;
 	}
 
@@ -4847,6 +5109,7 @@ static int __devinit ixgbe_sw_init(struc
 	int j;
 	struct tc_configuration *tc;
 #endif
+	int max_frame = dev->mtu + ETH_HLEN + ETH_FCS_LEN;
 
 	/* PCI config space info */
 
@@ -4861,26 +5124,24 @@ static int __devinit ixgbe_sw_init(struc
 	adapter->ring_feature[RING_F_RSS].indices = rss;
 	adapter->flags |= IXGBE_FLAG_RSS_ENABLED;
 	adapter->ring_feature[RING_F_DCB].indices = IXGBE_MAX_DCB_INDICES;
-	if (hw->mac.type == ixgbe_mac_82598EB) {
+	switch (hw->mac.type) {
+	case ixgbe_mac_82598EB:
 		if (hw->device_id == IXGBE_DEV_ID_82598AT)
 			adapter->flags |= IXGBE_FLAG_FAN_FAIL_CAPABLE;
 		adapter->max_msix_q_vectors = MAX_MSIX_Q_VECTORS_82598;
-	} else if (hw->mac.type == ixgbe_mac_82599EB) {
+		break;
+	case ixgbe_mac_82599EB:
+	case ixgbe_mac_X540:
 		adapter->max_msix_q_vectors = MAX_MSIX_Q_VECTORS_82599;
 		adapter->flags2 |= IXGBE_FLAG2_RSC_CAPABLE;
 		adapter->flags2 |= IXGBE_FLAG2_RSC_ENABLED;
 		if (hw->device_id == IXGBE_DEV_ID_82599_T3_LOM)
 			adapter->flags2 |= IXGBE_FLAG2_TEMP_SENSOR_CAPABLE;
-		if (dev->features & NETIF_F_NTUPLE) {
-			/* Flow Director perfect filter enabled */
-			adapter->flags |= IXGBE_FLAG_FDIR_PERFECT_CAPABLE;
-			adapter->atr_sample_rate = 0;
-			spin_lock_init(&adapter->fdir_perfect_lock);
-		} else {
-			/* Flow Director hash filters enabled */
-			adapter->flags |= IXGBE_FLAG_FDIR_HASH_CAPABLE;
-			adapter->atr_sample_rate = 20;
-		}
+		/* n-tuple support exists, always init our spinlock */
+		spin_lock_init(&adapter->fdir_perfect_lock);
+		/* Flow Director hash filters enabled */
+		adapter->flags |= IXGBE_FLAG_FDIR_HASH_CAPABLE;
+		adapter->atr_sample_rate = 20;
 		adapter->ring_feature[RING_F_FDIR].indices =
 							 IXGBE_MAX_FDIR_INDICES;
 		adapter->fdir_pballoc = 0;
@@ -4894,6 +5155,9 @@ static int __devinit ixgbe_sw_init(struc
 		adapter->fcoe.up = IXGBE_FCOE_DEFTC;
 #endif
 #endif /* IXGBE_FCOE */
+		break;
+	default:
+		break;
 	}
 
 #ifdef CONFIG_IXGBE_DCB
@@ -4923,8 +5187,8 @@ static int __devinit ixgbe_sw_init(struc
 #ifdef CONFIG_DCB
 	adapter->last_lfc_mode = hw->fc.current_mode;
 #endif
-	hw->fc.high_water = IXGBE_DEFAULT_FCRTH;
-	hw->fc.low_water = IXGBE_DEFAULT_FCRTL;
+	hw->fc.high_water = FC_HIGH_WATER(max_frame);
+	hw->fc.low_water = FC_LOW_WATER(max_frame);
 	hw->fc.pause_time = IXGBE_DEFAULT_FCPAUSE;
 	hw->fc.send_xon = true;
 	hw->fc.disable_fc_autoneg = false;
@@ -4962,30 +5226,27 @@ static int __devinit ixgbe_sw_init(struc
 
 /**
  * ixgbe_setup_tx_resources - allocate Tx resources (Descriptors)
- * @adapter: board private structure
  * @tx_ring:    tx descriptor ring (for a specific queue) to setup
  *
  * Return 0 on success, negative on failure
  **/
-int ixgbe_setup_tx_resources(struct ixgbe_adapter *adapter,
-			     struct ixgbe_ring *tx_ring)
+int ixgbe_setup_tx_resources(struct ixgbe_ring *tx_ring)
 {
-	struct pci_dev *pdev = adapter->pdev;
+	struct device *dev = tx_ring->dev;
 	int size;
 
 	size = sizeof(struct ixgbe_tx_buffer) * tx_ring->count;
-	tx_ring->tx_buffer_info = vmalloc_node(size, tx_ring->numa_node);
+	tx_ring->tx_buffer_info = vzalloc_node(size, tx_ring->numa_node);
 	if (!tx_ring->tx_buffer_info)
-		tx_ring->tx_buffer_info = vmalloc(size);
+		tx_ring->tx_buffer_info = vzalloc(size);
 	if (!tx_ring->tx_buffer_info)
 		goto err;
-	memset(tx_ring->tx_buffer_info, 0, size);
 
 	/* round up to nearest 4K */
 	tx_ring->size = tx_ring->count * sizeof(union ixgbe_adv_tx_desc);
 	tx_ring->size = ALIGN(tx_ring->size, 4096);
 
-	tx_ring->desc = dma_alloc_coherent(&pdev->dev, tx_ring->size,
+	tx_ring->desc = dma_alloc_coherent(dev, tx_ring->size,
 					   &tx_ring->dma, GFP_KERNEL);
 	if (!tx_ring->desc)
 		goto err;
@@ -4998,7 +5259,7 @@ int ixgbe_setup_tx_resources(struct ixgb
 err:
 	vfree(tx_ring->tx_buffer_info);
 	tx_ring->tx_buffer_info = NULL;
-	e_err(probe, "Unable to allocate memory for the Tx descriptor ring\n");
+	dev_err(dev, "Unable to allocate memory for the Tx descriptor ring\n");
 	return -ENOMEM;
 }
 
@@ -5017,7 +5278,7 @@ static int ixgbe_setup_all_tx_resources(
 	int i, err = 0;
 
 	for (i = 0; i < adapter->num_tx_queues; i++) {
-		err = ixgbe_setup_tx_resources(adapter, adapter->tx_ring[i]);
+		err = ixgbe_setup_tx_resources(adapter->tx_ring[i]);
 		if (!err)
 			continue;
 		e_err(probe, "Allocation for Tx Queue %u failed\n", i);
@@ -5029,48 +5290,40 @@ static int ixgbe_setup_all_tx_resources(
 
 /**
  * ixgbe_setup_rx_resources - allocate Rx resources (Descriptors)
- * @adapter: board private structure
  * @rx_ring:    rx descriptor ring (for a specific queue) to setup
  *
  * Returns 0 on success, negative on failure
  **/
-int ixgbe_setup_rx_resources(struct ixgbe_adapter *adapter,
-			     struct ixgbe_ring *rx_ring)
+int ixgbe_setup_rx_resources(struct ixgbe_ring *rx_ring)
 {
-	struct pci_dev *pdev = adapter->pdev;
+	struct device *dev = rx_ring->dev;
 	int size;
 
 	size = sizeof(struct ixgbe_rx_buffer) * rx_ring->count;
-	rx_ring->rx_buffer_info = vmalloc_node(size, adapter->node);
+	rx_ring->rx_buffer_info = vzalloc_node(size, rx_ring->numa_node);
 	if (!rx_ring->rx_buffer_info)
-		rx_ring->rx_buffer_info = vmalloc(size);
-	if (!rx_ring->rx_buffer_info) {
-		e_err(probe, "vmalloc allocation failed for the Rx "
-		      "descriptor ring\n");
-		goto alloc_failed;
-	}
-	memset(rx_ring->rx_buffer_info, 0, size);
+		rx_ring->rx_buffer_info = vzalloc(size);
+	if (!rx_ring->rx_buffer_info)
+		goto err;
 
 	/* Round up to nearest 4K */
 	rx_ring->size = rx_ring->count * sizeof(union ixgbe_adv_rx_desc);
 	rx_ring->size = ALIGN(rx_ring->size, 4096);
 
-	rx_ring->desc = dma_alloc_coherent(&pdev->dev, rx_ring->size,
+	rx_ring->desc = dma_alloc_coherent(dev, rx_ring->size,
 					   &rx_ring->dma, GFP_KERNEL);
 
-	if (!rx_ring->desc) {
-		e_err(probe, "Memory allocation failed for the Rx "
-		      "descriptor ring\n");
-		vfree(rx_ring->rx_buffer_info);
-		goto alloc_failed;
-	}
+	if (!rx_ring->desc)
+		goto err;
 
 	rx_ring->next_to_clean = 0;
 	rx_ring->next_to_use = 0;
 
 	return 0;
-
-alloc_failed:
+err:
+	vfree(rx_ring->rx_buffer_info);
+	rx_ring->rx_buffer_info = NULL;
+	dev_err(dev, "Unable to allocate memory for the Rx descriptor ring\n");
 	return -ENOMEM;
 }
 
@@ -5084,13 +5337,12 @@ alloc_failed:
  *
  * Return 0 on success, negative on failure
  **/
-
 static int ixgbe_setup_all_rx_resources(struct ixgbe_adapter *adapter)
 {
 	int i, err = 0;
 
 	for (i = 0; i < adapter->num_rx_queues; i++) {
-		err = ixgbe_setup_rx_resources(adapter, adapter->rx_ring[i]);
+		err = ixgbe_setup_rx_resources(adapter->rx_ring[i]);
 		if (!err)
 			continue;
 		e_err(probe, "Allocation for Rx Queue %u failed\n", i);
@@ -5102,23 +5354,23 @@ static int ixgbe_setup_all_rx_resources(
 
 /**
  * ixgbe_free_tx_resources - Free Tx Resources per Queue
- * @adapter: board private structure
  * @tx_ring: Tx descriptor ring for a specific queue
  *
  * Free all transmit software resources
  **/
-void ixgbe_free_tx_resources(struct ixgbe_adapter *adapter,
-			     struct ixgbe_ring *tx_ring)
+void ixgbe_free_tx_resources(struct ixgbe_ring *tx_ring)
 {
-	struct pci_dev *pdev = adapter->pdev;
-
-	ixgbe_clean_tx_ring(adapter, tx_ring);
+	ixgbe_clean_tx_ring(tx_ring);
 
 	vfree(tx_ring->tx_buffer_info);
 	tx_ring->tx_buffer_info = NULL;
 
-	dma_free_coherent(&pdev->dev, tx_ring->size, tx_ring->desc,
-			  tx_ring->dma);
+	/* if not set, then don't free */
+	if (!tx_ring->desc)
+		return;
+
+	dma_free_coherent(tx_ring->dev, tx_ring->size,
+			  tx_ring->desc, tx_ring->dma);
 
 	tx_ring->desc = NULL;
 }
@@ -5135,28 +5387,28 @@ static void ixgbe_free_all_tx_resources(
 
 	for (i = 0; i < adapter->num_tx_queues; i++)
 		if (adapter->tx_ring[i]->desc)
-			ixgbe_free_tx_resources(adapter, adapter->tx_ring[i]);
+			ixgbe_free_tx_resources(adapter->tx_ring[i]);
 }
 
 /**
  * ixgbe_free_rx_resources - Free Rx Resources
- * @adapter: board private structure
  * @rx_ring: ring to clean the resources from
  *
  * Free all receive software resources
  **/
-void ixgbe_free_rx_resources(struct ixgbe_adapter *adapter,
-			     struct ixgbe_ring *rx_ring)
+void ixgbe_free_rx_resources(struct ixgbe_ring *rx_ring)
 {
-	struct pci_dev *pdev = adapter->pdev;
-
-	ixgbe_clean_rx_ring(adapter, rx_ring);
+	ixgbe_clean_rx_ring(rx_ring);
 
 	vfree(rx_ring->rx_buffer_info);
 	rx_ring->rx_buffer_info = NULL;
 
-	dma_free_coherent(&pdev->dev, rx_ring->size, rx_ring->desc,
-			  rx_ring->dma);
+	/* if not set, then don't free */
+	if (!rx_ring->desc)
+		return;
+
+	dma_free_coherent(rx_ring->dev, rx_ring->size,
+			  rx_ring->desc, rx_ring->dma);
 
 	rx_ring->desc = NULL;
 }
@@ -5173,7 +5425,7 @@ static void ixgbe_free_all_rx_resources(
 
 	for (i = 0; i < adapter->num_rx_queues; i++)
 		if (adapter->rx_ring[i]->desc)
-			ixgbe_free_rx_resources(adapter, adapter->rx_ring[i]);
+			ixgbe_free_rx_resources(adapter->rx_ring[i]);
 }
 
 /**
@@ -5186,6 +5438,7 @@ static void ixgbe_free_all_rx_resources(
 static int ixgbe_change_mtu(struct net_device *netdev, int new_mtu)
 {
 	struct ixgbe_adapter *adapter = netdev_priv(netdev);
+	struct ixgbe_hw *hw = &adapter->hw;
 	int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN;
 
 	/* MTU < 68 is an error and causes problems on some kernels */
@@ -5196,6 +5449,9 @@ static int ixgbe_change_mtu(struct net_d
 	/* must set new MTU before calling down or up */
 	netdev->mtu = new_mtu;
 
+	hw->fc.high_water = FC_HIGH_WATER(max_frame);
+	hw->fc.low_water = FC_LOW_WATER(max_frame);
+
 	if (netif_running(netdev))
 		ixgbe_reinit_locked(adapter);
 
@@ -5291,8 +5547,8 @@ static int ixgbe_close(struct net_device
 #ifdef CONFIG_PM
 static int ixgbe_resume(struct pci_dev *pdev)
 {
-	struct net_device *netdev = pci_get_drvdata(pdev);
-	struct ixgbe_adapter *adapter = netdev_priv(netdev);
+	struct ixgbe_adapter *adapter = pci_get_drvdata(pdev);
+	struct net_device *netdev = adapter->netdev;
 	u32 err;
 
 	pci_set_power_state(pdev, PCI_D0);
@@ -5323,7 +5579,7 @@ static int ixgbe_resume(struct pci_dev *
 	IXGBE_WRITE_REG(&adapter->hw, IXGBE_WUS, ~0);
 
 	if (netif_running(netdev)) {
-		err = ixgbe_open(adapter->netdev);
+		err = ixgbe_open(netdev);
 		if (err)
 			return err;
 	}
@@ -5336,8 +5592,8 @@ static int ixgbe_resume(struct pci_dev *
 
 static int __ixgbe_shutdown(struct pci_dev *pdev, bool *enable_wake)
 {
-	struct net_device *netdev = pci_get_drvdata(pdev);
-	struct ixgbe_adapter *adapter = netdev_priv(netdev);
+	struct ixgbe_adapter *adapter = pci_get_drvdata(pdev);
+	struct net_device *netdev = adapter->netdev;
 	struct ixgbe_hw *hw = &adapter->hw;
 	u32 ctrl, fctrl;
 	u32 wufc = adapter->wol;
@@ -5354,6 +5610,8 @@ static int __ixgbe_shutdown(struct pci_d
 		ixgbe_free_all_rx_resources(adapter);
 	}
 
+	ixgbe_clear_interrupt_scheme(adapter);
+
 #ifdef CONFIG_PM
 	retval = pci_save_state(pdev);
 	if (retval)
@@ -5380,15 +5638,20 @@ static int __ixgbe_shutdown(struct pci_d
 		IXGBE_WRITE_REG(hw, IXGBE_WUFC, 0);
 	}
 
-	if (wufc && hw->mac.type == ixgbe_mac_82599EB)
-		pci_wake_from_d3(pdev, true);
-	else
+	switch (hw->mac.type) {
+	case ixgbe_mac_82598EB:
 		pci_wake_from_d3(pdev, false);
+		break;
+	case ixgbe_mac_82599EB:
+	case ixgbe_mac_X540:
+		pci_wake_from_d3(pdev, !!wufc);
+		break;
+	default:
+		break;
+	}
 
 	*enable_wake = !!wufc;
 
-	ixgbe_clear_interrupt_scheme(adapter);
-
 	ixgbe_release_hw_control(adapter);
 
 	pci_disable_device(pdev);
@@ -5437,10 +5700,12 @@ void ixgbe_update_stats(struct ixgbe_ada
 {
 	struct net_device *netdev = adapter->netdev;
 	struct ixgbe_hw *hw = &adapter->hw;
+	struct ixgbe_hw_stats *hwstats = &adapter->stats;
 	u64 total_mpc = 0;
 	u32 i, missed_rx = 0, mpc, bprc, lxon, lxoff, xon_off_tot;
-	u64 non_eop_descs = 0, restart_queue = 0;
-	struct ixgbe_hw_stats *hwstats = &adapter->stats;
+	u64 non_eop_descs = 0, restart_queue = 0, tx_busy = 0;
+	u64 alloc_rx_page_failed = 0, alloc_rx_buff_failed = 0;
+	u64 bytes = 0, packets = 0;
 
 	if (test_bit(__IXGBE_DOWN, &adapter->state) ||
 	    test_bit(__IXGBE_RESETTING, &adapter->state))
@@ -5453,21 +5718,41 @@ void ixgbe_update_stats(struct ixgbe_ada
 			adapter->hw_rx_no_dma_resources +=
 				IXGBE_READ_REG(hw, IXGBE_QPRDC(i));
 		for (i = 0; i < adapter->num_rx_queues; i++) {
-			rsc_count += adapter->rx_ring[i]->rsc_count;
-			rsc_flush += adapter->rx_ring[i]->rsc_flush;
+			rsc_count += adapter->rx_ring[i]->rx_stats.rsc_count;
+			rsc_flush += adapter->rx_ring[i]->rx_stats.rsc_flush;
 		}
 		adapter->rsc_total_count = rsc_count;
 		adapter->rsc_total_flush = rsc_flush;
 	}
 
+	for (i = 0; i < adapter->num_rx_queues; i++) {
+		struct ixgbe_ring *rx_ring = adapter->rx_ring[i];
+		non_eop_descs += rx_ring->rx_stats.non_eop_descs;
+		alloc_rx_page_failed += rx_ring->rx_stats.alloc_rx_page_failed;
+		alloc_rx_buff_failed += rx_ring->rx_stats.alloc_rx_buff_failed;
+		bytes += rx_ring->stats.bytes;
+		packets += rx_ring->stats.packets;
+	}
+	adapter->non_eop_descs = non_eop_descs;
+	adapter->alloc_rx_page_failed = alloc_rx_page_failed;
+	adapter->alloc_rx_buff_failed = alloc_rx_buff_failed;
+	netdev->stats.rx_bytes = bytes;
+	netdev->stats.rx_packets = packets;
+
+	bytes = 0;
+	packets = 0;
 	/* gather some stats to the adapter struct that are per queue */
-	for (i = 0; i < adapter->num_tx_queues; i++)
-		restart_queue += adapter->tx_ring[i]->restart_queue;
+	for (i = 0; i < adapter->num_tx_queues; i++) {
+		struct ixgbe_ring *tx_ring = adapter->tx_ring[i];
+		restart_queue += tx_ring->tx_stats.restart_queue;
+		tx_busy += tx_ring->tx_stats.tx_busy;
+		bytes += tx_ring->stats.bytes;
+		packets += tx_ring->stats.packets;
+	}
 	adapter->restart_queue = restart_queue;
-
-	for (i = 0; i < adapter->num_rx_queues; i++)
-		non_eop_descs += adapter->rx_ring[i]->non_eop_descs;
-	adapter->non_eop_descs = non_eop_descs;
+	adapter->tx_busy = tx_busy;
+	netdev->stats.tx_bytes = bytes;
+	netdev->stats.tx_packets = packets;
 
 	hwstats->crcerrs += IXGBE_READ_REG(hw, IXGBE_CRCERRS);
 	for (i = 0; i < 8; i++) {
@@ -5482,17 +5767,18 @@ void ixgbe_update_stats(struct ixgbe_ada
 		hwstats->qbtc[i] += IXGBE_READ_REG(hw, IXGBE_QBTC(i));
 		hwstats->qprc[i] += IXGBE_READ_REG(hw, IXGBE_QPRC(i));
 		hwstats->qbrc[i] += IXGBE_READ_REG(hw, IXGBE_QBRC(i));
-		if (hw->mac.type == ixgbe_mac_82599EB) {
-			hwstats->pxonrxc[i] +=
-				IXGBE_READ_REG(hw, IXGBE_PXONRXCNT(i));
-			hwstats->pxoffrxc[i] +=
-				IXGBE_READ_REG(hw, IXGBE_PXOFFRXCNT(i));
-			hwstats->qprdc[i] += IXGBE_READ_REG(hw, IXGBE_QPRDC(i));
-		} else {
+		switch (hw->mac.type) {
+		case ixgbe_mac_82598EB:
 			hwstats->pxonrxc[i] +=
 				IXGBE_READ_REG(hw, IXGBE_PXONRXC(i));
-			hwstats->pxoffrxc[i] +=
-				IXGBE_READ_REG(hw, IXGBE_PXOFFRXC(i));
+			break;
+		case ixgbe_mac_82599EB:
+		case ixgbe_mac_X540:
+			hwstats->pxonrxc[i] +=
+				IXGBE_READ_REG(hw, IXGBE_PXONRXCNT(i));
+			break;
+		default:
+			break;
 		}
 		hwstats->pxontxc[i] += IXGBE_READ_REG(hw, IXGBE_PXONTXC(i));
 		hwstats->pxofftxc[i] += IXGBE_READ_REG(hw, IXGBE_PXOFFTXC(i));
@@ -5501,21 +5787,25 @@ void ixgbe_update_stats(struct ixgbe_ada
 	/* work around hardware counting issue */
 	hwstats->gprc -= missed_rx;
 
+	ixgbe_update_xoff_received(adapter);
+
 	/* 82598 hardware only has a 32 bit counter in the high register */
-	if (hw->mac.type == ixgbe_mac_82599EB) {
-		u64 tmp;
+	switch (hw->mac.type) {
+	case ixgbe_mac_82598EB:
+		hwstats->lxonrxc += IXGBE_READ_REG(hw, IXGBE_LXONRXC);
+		hwstats->gorc += IXGBE_READ_REG(hw, IXGBE_GORCH);
+		hwstats->gotc += IXGBE_READ_REG(hw, IXGBE_GOTCH);
+		hwstats->tor += IXGBE_READ_REG(hw, IXGBE_TORH);
+		break;
+	case ixgbe_mac_82599EB:
+	case ixgbe_mac_X540:
 		hwstats->gorc += IXGBE_READ_REG(hw, IXGBE_GORCL);
-		tmp = IXGBE_READ_REG(hw, IXGBE_GORCH) & 0xF;
-						/* 4 high bits of GORC */
-		hwstats->gorc += (tmp << 32);
+		IXGBE_READ_REG(hw, IXGBE_GORCH); /* to clear */
 		hwstats->gotc += IXGBE_READ_REG(hw, IXGBE_GOTCL);
-		tmp = IXGBE_READ_REG(hw, IXGBE_GOTCH) & 0xF;
-						/* 4 high bits of GOTC */
-		hwstats->gotc += (tmp << 32);
+		IXGBE_READ_REG(hw, IXGBE_GOTCH); /* to clear */
 		hwstats->tor += IXGBE_READ_REG(hw, IXGBE_TORL);
-		IXGBE_READ_REG(hw, IXGBE_TORH);	/* to clear */
+		IXGBE_READ_REG(hw, IXGBE_TORH); /* to clear */
 		hwstats->lxonrxc += IXGBE_READ_REG(hw, IXGBE_LXONRXCNT);
-		hwstats->lxoffrxc += IXGBE_READ_REG(hw, IXGBE_LXOFFRXCNT);
 		hwstats->fdirmatch += IXGBE_READ_REG(hw, IXGBE_FDIRMATCH);
 		hwstats->fdirmiss += IXGBE_READ_REG(hw, IXGBE_FDIRMISS);
 #ifdef IXGBE_FCOE
@@ -5526,12 +5816,9 @@ void ixgbe_update_stats(struct ixgbe_ada
 		hwstats->fcoedwrc += IXGBE_READ_REG(hw, IXGBE_FCOEDWRC);
 		hwstats->fcoedwtc += IXGBE_READ_REG(hw, IXGBE_FCOEDWTC);
 #endif /* IXGBE_FCOE */
-	} else {
-		hwstats->lxonrxc += IXGBE_READ_REG(hw, IXGBE_LXONRXC);
-		hwstats->lxoffrxc += IXGBE_READ_REG(hw, IXGBE_LXOFFRXC);
-		hwstats->gorc += IXGBE_READ_REG(hw, IXGBE_GORCH);
-		hwstats->gotc += IXGBE_READ_REG(hw, IXGBE_GOTCH);
-		hwstats->tor += IXGBE_READ_REG(hw, IXGBE_TORH);
+		break;
+	default:
+		break;
 	}
 	bprc = IXGBE_READ_REG(hw, IXGBE_BPRC);
 	hwstats->bprc += bprc;
@@ -5682,7 +5969,8 @@ static void ixgbe_sfp_config_module_task
 		unregister_netdev(adapter->netdev);
 		return;
 	}
-	hw->mac.ops.setup_sfp(hw);
+	if (hw->mac.ops.setup_sfp)
+		hw->mac.ops.setup_sfp(hw);
 
 	if (!(adapter->flags & IXGBE_FLAG_IN_SFP_LINK_TASK))
 		/* This will also work for DA Twinax connections */
@@ -5704,8 +5992,8 @@ static void ixgbe_fdir_reinit_task(struc
 
 	if (ixgbe_reinit_fdir_tables_82599(hw) == 0) {
 		for (i = 0; i < adapter->num_tx_queues; i++)
-			set_bit(__IXGBE_FDIR_INIT_DONE,
-				&(adapter->tx_ring[i]->reinit_state));
+			set_bit(__IXGBE_TX_FDIR_INIT_DONE,
+				&(adapter->tx_ring[i]->state));
 	} else {
 		e_err(probe, "failed to finish FDIR re-initialization, "
 		      "ignored adding FDIR ATR filters\n");
@@ -5714,6 +6002,26 @@ static void ixgbe_fdir_reinit_task(struc
 	netif_tx_start_all_queues(adapter->netdev);
 }
 
+static void ixgbe_spoof_check(struct ixgbe_adapter *adapter)
+{
+	u32 ssvpc;
+
+	/* Do not perform spoof check for 82598 */
+	if (adapter->hw.mac.type == ixgbe_mac_82598EB)
+		return;
+
+	ssvpc = IXGBE_READ_REG(&adapter->hw, IXGBE_SSVPC);
+
+	/*
+	 * ssvpc register is cleared on read, if zero then no
+	 * spoofed packets in the last interval.
+	 */
+	if (!ssvpc)
+		return;
+
+	e_warn(drv, "%d Spoofed packets detected\n", ssvpc);
+}
+
 static DEFINE_MUTEX(ixgbe_watchdog_lock);
 
 /**
@@ -5767,17 +6075,27 @@ static void ixgbe_watchdog_task(struct w
 		if (!netif_carrier_ok(netdev)) {
 			bool flow_rx, flow_tx;
 
-			if (hw->mac.type == ixgbe_mac_82599EB) {
-				u32 mflcn = IXGBE_READ_REG(hw, IXGBE_MFLCN);
-				u32 fccfg = IXGBE_READ_REG(hw, IXGBE_FCCFG);
-				flow_rx = !!(mflcn & IXGBE_MFLCN_RFCE);
-				flow_tx = !!(fccfg & IXGBE_FCCFG_TFCE_802_3X);
-			} else {
+			switch (hw->mac.type) {
+			case ixgbe_mac_82598EB: {
 				u32 frctl = IXGBE_READ_REG(hw, IXGBE_FCTRL);
 				u32 rmcs = IXGBE_READ_REG(hw, IXGBE_RMCS);
 				flow_rx = !!(frctl & IXGBE_FCTRL_RFCE);
 				flow_tx = !!(rmcs & IXGBE_RMCS_TFCE_802_3X);
 			}
+				break;
+			case ixgbe_mac_82599EB:
+			case ixgbe_mac_X540: {
+				u32 mflcn = IXGBE_READ_REG(hw, IXGBE_MFLCN);
+				u32 fccfg = IXGBE_READ_REG(hw, IXGBE_FCCFG);
+				flow_rx = !!(mflcn & IXGBE_MFLCN_RFCE);
+				flow_tx = !!(fccfg & IXGBE_FCCFG_TFCE_802_3X);
+			}
+				break;
+			default:
+				flow_tx = false;
+				flow_rx = false;
+				break;
+			}
 
 			e_info(drv, "NIC Link is Up %s, Flow Control: %s\n",
 			       (link_speed == IXGBE_LINK_SPEED_10GB_FULL ?
@@ -5791,7 +6109,10 @@ static void ixgbe_watchdog_task(struct w
 			netif_carrier_on(netdev);
 		} else {
 			/* Force detection of hung controller */
-			adapter->detect_tx_hung = true;
+			for (i = 0; i < adapter->num_tx_queues; i++) {
+				tx_ring = adapter->tx_ring[i];
+				set_check_for_tx_hang(tx_ring);
+			}
 		}
 	} else {
 		adapter->link_up = false;
@@ -5821,6 +6142,7 @@ static void ixgbe_watchdog_task(struct w
 		}
 	}
 
+	ixgbe_spoof_check(adapter);
 	ixgbe_update_stats(adapter);
 	mutex_unlock(&ixgbe_watchdog_lock);
 }
@@ -6003,15 +6325,17 @@ static bool ixgbe_tx_csum(struct ixgbe_a
 static int ixgbe_tx_map(struct ixgbe_adapter *adapter,
 			struct ixgbe_ring *tx_ring,
 			struct sk_buff *skb, u32 tx_flags,
-			unsigned int first)
+			unsigned int first, const u8 hdr_len)
 {
-	struct pci_dev *pdev = adapter->pdev;
+	struct device *dev = tx_ring->dev;
 	struct ixgbe_tx_buffer *tx_buffer_info;
 	unsigned int len;
 	unsigned int total = skb->len;
 	unsigned int offset = 0, size, count = 0, i;
 	unsigned int nr_frags = skb_shinfo(skb)->nr_frags;
 	unsigned int f;
+	unsigned int bytecount = skb->len;
+	u16 gso_segs = 1;
 
 	i = tx_ring->next_to_use;
 
@@ -6026,10 +6350,10 @@ static int ixgbe_tx_map(struct ixgbe_ada
 
 		tx_buffer_info->length = size;
 		tx_buffer_info->mapped_as_page = false;
-		tx_buffer_info->dma = dma_map_single(&pdev->dev,
+		tx_buffer_info->dma = dma_map_single(dev,
 						     skb->data + offset,
 						     size, DMA_TO_DEVICE);
-		if (dma_mapping_error(&pdev->dev, tx_buffer_info->dma))
+		if (dma_mapping_error(dev, tx_buffer_info->dma))
 			goto dma_error;
 		tx_buffer_info->time_stamp = jiffies;
 		tx_buffer_info->next_to_watch = i;
@@ -6062,12 +6386,12 @@ static int ixgbe_tx_map(struct ixgbe_ada
 			size = min(len, (uint)IXGBE_MAX_DATA_PER_TXD);
 
 			tx_buffer_info->length = size;
-			tx_buffer_info->dma = dma_map_page(&adapter->pdev->dev,
+			tx_buffer_info->dma = dma_map_page(dev,
 							   frag->page,
 							   offset, size,
 							   DMA_TO_DEVICE);
 			tx_buffer_info->mapped_as_page = true;
-			if (dma_mapping_error(&pdev->dev, tx_buffer_info->dma))
+			if (dma_mapping_error(dev, tx_buffer_info->dma))
 				goto dma_error;
 			tx_buffer_info->time_stamp = jiffies;
 			tx_buffer_info->next_to_watch = i;
@@ -6081,6 +6405,19 @@ static int ixgbe_tx_map(struct ixgbe_ada
 			break;
 	}
 
+	if (tx_flags & IXGBE_TX_FLAGS_TSO)
+		gso_segs = skb_shinfo(skb)->gso_segs;
+#ifdef IXGBE_FCOE
+	/* adjust for FCoE Sequence Offload */
+	else if (tx_flags & IXGBE_TX_FLAGS_FSO)
+		gso_segs = DIV_ROUND_UP(skb->len - hdr_len,
+					skb_shinfo(skb)->gso_size);
+#endif /* IXGBE_FCOE */
+	bytecount += (gso_segs - 1) * hdr_len;
+
+	/* multiply data chunks by size of headers */
+	tx_ring->tx_buffer_info[i].bytecount = bytecount;
+	tx_ring->tx_buffer_info[i].gso_segs = gso_segs;
 	tx_ring->tx_buffer_info[i].skb = skb;
 	tx_ring->tx_buffer_info[first].next_to_watch = i;
 
@@ -6102,14 +6439,13 @@ dma_error:
 			i += tx_ring->count;
 		i--;
 		tx_buffer_info = &tx_ring->tx_buffer_info[i];
-		ixgbe_unmap_and_free_tx_resource(adapter, tx_buffer_info);
+		ixgbe_unmap_and_free_tx_resource(tx_ring, tx_buffer_info);
 	}
 
 	return 0;
 }
 
-static void ixgbe_tx_queue(struct ixgbe_adapter *adapter,
-			   struct ixgbe_ring *tx_ring,
+static void ixgbe_tx_queue(struct ixgbe_ring *tx_ring,
 			   int tx_flags, int count, u32 paylen, u8 hdr_len)
 {
 	union ixgbe_adv_tx_desc *tx_desc = NULL;
@@ -6174,60 +6510,100 @@ static void ixgbe_tx_queue(struct ixgbe_
 	wmb();
 
 	tx_ring->next_to_use = i;
-	writel(i, adapter->hw.hw_addr + tx_ring->tail);
+	writel(i, tx_ring->tail);
 }
 
-static void ixgbe_atr(struct ixgbe_adapter *adapter, struct sk_buff *skb,
-		      int queue, u32 tx_flags, __be16 protocol)
+static void ixgbe_atr(struct ixgbe_ring *ring, struct sk_buff *skb,
+		      u32 tx_flags, __be16 protocol)
 {
-	struct ixgbe_atr_input atr_input;
+	struct ixgbe_q_vector *q_vector = ring->q_vector;
+	union ixgbe_atr_hash_dword input = { .dword = 0 };
+	union ixgbe_atr_hash_dword common = { .dword = 0 };
+	union {
+		unsigned char *network;
+		struct iphdr *ipv4;
+		struct ipv6hdr *ipv6;
+	} hdr;
 	struct tcphdr *th;
-	struct iphdr *iph = ip_hdr(skb);
-	struct ethhdr *eth = (struct ethhdr *)skb->data;
-	u16 vlan_id, src_port, dst_port, flex_bytes;
-	u32 src_ipv4_addr, dst_ipv4_addr;
-	u8 l4type = 0;
+	__be16 vlan_id;
 
-	/* Right now, we support IPv4 only */
-	if (protocol != htons(ETH_P_IP))
+	/* if ring doesn't have a interrupt vector, cannot perform ATR */
+	if (!q_vector)
 		return;
-	/* check if we're UDP or TCP */
-	if (iph->protocol == IPPROTO_TCP) {
-		th = tcp_hdr(skb);
-		src_port = th->source;
-		dst_port = th->dest;
-		l4type |= IXGBE_ATR_L4TYPE_TCP;
-		/* l4type IPv4 type is 0, no need to assign */
-	} else {
-		/* Unsupported L4 header, just bail here */
+
+	/* do nothing if sampling is disabled */
+	if (!ring->atr_sample_rate)
 		return;
-	}
 
-	memset(&atr_input, 0, sizeof(struct ixgbe_atr_input));
+	ring->atr_count++;
 
-	vlan_id = (tx_flags & IXGBE_TX_FLAGS_VLAN_MASK) >>
-		   IXGBE_TX_FLAGS_VLAN_SHIFT;
-	src_ipv4_addr = iph->saddr;
-	dst_ipv4_addr = iph->daddr;
-	flex_bytes = eth->h_proto;
+	/* snag network header to get L4 type and address */
+	hdr.network = skb_network_header(skb);
 
-	ixgbe_atr_set_vlan_id_82599(&atr_input, vlan_id);
-	ixgbe_atr_set_src_port_82599(&atr_input, dst_port);
-	ixgbe_atr_set_dst_port_82599(&atr_input, src_port);
-	ixgbe_atr_set_flex_byte_82599(&atr_input, flex_bytes);
-	ixgbe_atr_set_l4type_82599(&atr_input, l4type);
-	/* src and dst are inverted, think how the receiver sees them */
-	ixgbe_atr_set_src_ipv4_82599(&atr_input, dst_ipv4_addr);
-	ixgbe_atr_set_dst_ipv4_82599(&atr_input, src_ipv4_addr);
+	/* Currently only IPv4/IPv6 with TCP is supported */
+	if ((protocol != __constant_htons(ETH_P_IPV6) ||
+	     hdr.ipv6->nexthdr != IPPROTO_TCP) &&
+	    (protocol != __constant_htons(ETH_P_IP) ||
+	     hdr.ipv4->protocol != IPPROTO_TCP))
+		return;
+
+	th = tcp_hdr(skb);
+
+	/* skip this packet since the socket is closing */
+	if (th->fin)
+		return;
+
+	/* sample on all syn packets or once every atr sample count */
+	if (!th->syn && (ring->atr_count < ring->atr_sample_rate))
+		return;
+
+	/* reset sample count */
+	ring->atr_count = 0;
+
+	vlan_id = htons(tx_flags >> IXGBE_TX_FLAGS_VLAN_SHIFT);
+
+	/*
+	 * src and dst are inverted, think how the receiver sees them
+	 *
+	 * The input is broken into two sections, a non-compressed section
+	 * containing vm_pool, vlan_id, and flow_type.  The rest of the data
+	 * is XORed together and stored in the compressed dword.
+	 */
+	input.formatted.vlan_id = vlan_id;
+
+	/*
+	 * since src port and flex bytes occupy the same word XOR them together
+	 * and write the value to source port portion of compressed dword
+	 */
+	if (vlan_id)
+		common.port.src ^= th->dest ^ __constant_htons(ETH_P_8021Q);
+	else
+		common.port.src ^= th->dest ^ protocol;
+	common.port.dst ^= th->source;
+
+	if (protocol == __constant_htons(ETH_P_IP)) {
+		input.formatted.flow_type = IXGBE_ATR_FLOW_TYPE_TCPV4;
+		common.ip ^= hdr.ipv4->saddr ^ hdr.ipv4->daddr;
+	} else {
+		input.formatted.flow_type = IXGBE_ATR_FLOW_TYPE_TCPV6;
+		common.ip ^= hdr.ipv6->saddr.s6_addr32[0] ^
+			     hdr.ipv6->saddr.s6_addr32[1] ^
+			     hdr.ipv6->saddr.s6_addr32[2] ^
+			     hdr.ipv6->saddr.s6_addr32[3] ^
+			     hdr.ipv6->daddr.s6_addr32[0] ^
+			     hdr.ipv6->daddr.s6_addr32[1] ^
+			     hdr.ipv6->daddr.s6_addr32[2] ^
+			     hdr.ipv6->daddr.s6_addr32[3];
+	}
 
 	/* This assumes the Rx queue and Tx queue are bound to the same CPU */
-	ixgbe_fdir_add_signature_filter_82599(&adapter->hw, &atr_input, queue);
+	ixgbe_fdir_add_signature_filter_82599(&q_vector->adapter->hw,
+					      input, common, ring->queue_index);
 }
 
-static int __ixgbe_maybe_stop_tx(struct net_device *netdev,
-				 struct ixgbe_ring *tx_ring, int size)
+static int __ixgbe_maybe_stop_tx(struct ixgbe_ring *tx_ring, int size)
 {
-	netif_stop_subqueue(netdev, tx_ring->queue_index);
+	netif_stop_subqueue(tx_ring->netdev, tx_ring->queue_index);
 	/* Herbert's original patch had:
 	 *  smp_mb__after_netif_stop_queue();
 	 * but since that doesn't exist yet, just open code it. */
@@ -6239,17 +6615,16 @@ static int __ixgbe_maybe_stop_tx(struct
 		return -EBUSY;
 
 	/* A reprieve! - use start_queue because it doesn't call schedule */
-	netif_start_subqueue(netdev, tx_ring->queue_index);
-	++tx_ring->restart_queue;
+	netif_start_subqueue(tx_ring->netdev, tx_ring->queue_index);
+	++tx_ring->tx_stats.restart_queue;
 	return 0;
 }
 
-static int ixgbe_maybe_stop_tx(struct net_device *netdev,
-			      struct ixgbe_ring *tx_ring, int size)
+static int ixgbe_maybe_stop_tx(struct ixgbe_ring *tx_ring, int size)
 {
 	if (likely(IXGBE_DESC_UNUSED(tx_ring) >= size))
 		return 0;
-	return __ixgbe_maybe_stop_tx(netdev, tx_ring, size);
+	return __ixgbe_maybe_stop_tx(tx_ring, size);
 }
 
 static u16 ixgbe_select_queue(struct net_device *dev, struct sk_buff *skb)
@@ -6294,11 +6669,10 @@ static u16 ixgbe_select_queue(struct net
 	return skb_tx_hash(dev, skb);
 }
 
-netdev_tx_t ixgbe_xmit_frame_ring(struct sk_buff *skb, struct net_device *netdev,
+netdev_tx_t ixgbe_xmit_frame_ring(struct sk_buff *skb,
 			  struct ixgbe_adapter *adapter,
 			  struct ixgbe_ring *tx_ring)
 {
-	struct netdev_queue *txq;
 	unsigned int first;
 	unsigned int tx_flags = 0;
 	u8 hdr_len = 0;
@@ -6355,8 +6729,8 @@ netdev_tx_t ixgbe_xmit_frame_ring(struct
 	for (f = 0; f < skb_shinfo(skb)->nr_frags; f++)
 		count += TXD_USE_COUNT(skb_shinfo(skb)->frags[f].size);
 
-	if (ixgbe_maybe_stop_tx(netdev, tx_ring, count)) {
-		adapter->tx_busy++;
+	if (ixgbe_maybe_stop_tx(tx_ring, count)) {
+		tx_ring->tx_stats.tx_busy++;
 		return NETDEV_TX_BUSY;
 	}
 
@@ -6390,25 +6764,13 @@ netdev_tx_t ixgbe_xmit_frame_ring(struct
 			tx_flags |= IXGBE_TX_FLAGS_CSUM;
 	}
 
-	count = ixgbe_tx_map(adapter, tx_ring, skb, tx_flags, first);
+	count = ixgbe_tx_map(adapter, tx_ring, skb, tx_flags, first, hdr_len);
 	if (count) {
 		/* add the ATR filter if ATR is on */
-		if (tx_ring->atr_sample_rate) {
-			++tx_ring->atr_count;
-			if ((tx_ring->atr_count >= tx_ring->atr_sample_rate) &&
-			     test_bit(__IXGBE_FDIR_INIT_DONE,
-				      &tx_ring->reinit_state)) {
-				ixgbe_atr(adapter, skb, tx_ring->queue_index,
-					  tx_flags, protocol);
-				tx_ring->atr_count = 0;
-			}
-		}
-		txq = netdev_get_tx_queue(netdev, tx_ring->queue_index);
-		txq->tx_bytes += skb->len;
-		txq->tx_packets++;
-		ixgbe_tx_queue(adapter, tx_ring, tx_flags, count, skb->len,
-			       hdr_len);
-		ixgbe_maybe_stop_tx(netdev, tx_ring, DESC_NEEDED);
+		if (test_bit(__IXGBE_TX_FDIR_INIT_DONE, &tx_ring->state))
+			ixgbe_atr(tx_ring, skb, tx_flags, protocol);
+		ixgbe_tx_queue(tx_ring, tx_flags, count, skb->len, hdr_len);
+		ixgbe_maybe_stop_tx(tx_ring, DESC_NEEDED);
 
 	} else {
 		dev_kfree_skb_any(skb);
@@ -6425,7 +6787,7 @@ static netdev_tx_t ixgbe_xmit_frame(stru
 	struct ixgbe_ring *tx_ring;
 
 	tx_ring = adapter->tx_ring[skb->queue_mapping];
-	return ixgbe_xmit_frame_ring(skb, netdev, adapter, tx_ring);
+	return ixgbe_xmit_frame_ring(skb, adapter, tx_ring);
 }
 
 /**
@@ -6564,22 +6926,39 @@ static struct rtnl_link_stats64 *ixgbe_g
 	struct ixgbe_adapter *adapter = netdev_priv(netdev);
 	int i;
 
-	/* accurate rx/tx bytes/packets stats */
-	dev_txq_stats_fold(netdev, stats);
+	rcu_read_lock();
 	for (i = 0; i < adapter->num_rx_queues; i++) {
-		struct ixgbe_ring *ring = adapter->rx_ring[i];
+		struct ixgbe_ring *ring = ACCESS_ONCE(adapter->rx_ring[i]);
 		u64 bytes, packets;
 		unsigned int start;
 
-		do {
-			start = u64_stats_fetch_begin_bh(&ring->syncp);
-			packets = ring->stats.packets;
-			bytes   = ring->stats.bytes;
-		} while (u64_stats_fetch_retry_bh(&ring->syncp, start));
-		stats->rx_packets += packets;
-		stats->rx_bytes   += bytes;
+		if (ring) {
+			do {
+				start = u64_stats_fetch_begin_bh(&ring->syncp);
+				packets = ring->stats.packets;
+				bytes   = ring->stats.bytes;
+			} while (u64_stats_fetch_retry_bh(&ring->syncp, start));
+			stats->rx_packets += packets;
+			stats->rx_bytes   += bytes;
+		}
 	}
 
+	for (i = 0; i < adapter->num_tx_queues; i++) {
+		struct ixgbe_ring *ring = ACCESS_ONCE(adapter->tx_ring[i]);
+		u64 bytes, packets;
+		unsigned int start;
+
+		if (ring) {
+			do {
+				start = u64_stats_fetch_begin_bh(&ring->syncp);
+				packets = ring->stats.packets;
+				bytes   = ring->stats.bytes;
+			} while (u64_stats_fetch_retry_bh(&ring->syncp, start));
+			stats->tx_packets += packets;
+			stats->tx_bytes   += bytes;
+		}
+	}
+	rcu_read_unlock();
 	/* following stats updated by ixgbe_watchdog_task() */
 	stats->multicast	= netdev->stats.multicast;
 	stats->rx_errors	= netdev->stats.rx_errors;
@@ -6628,7 +7007,7 @@ static void __devinit ixgbe_probe_vf(str
 	struct ixgbe_hw *hw = &adapter->hw;
 	int err;
 
-	if (hw->mac.type != ixgbe_mac_82599EB || !max_vfs)
+	if (hw->mac.type == ixgbe_mac_82598EB || !max_vfs)
 		return;
 
 	/* The 82599 supports up to 64 VFs per physical function
@@ -6694,11 +7073,12 @@ static int __devinit ixgbe_probe(struct
 	const struct ixgbe_info *ii = ixgbe_info_tbl[ent->driver_data];
 	static int cards_found;
 	int i, err, pci_using_dac;
+	u8 part_str[IXGBE_PBANUM_LENGTH];
 	unsigned int indices = num_possible_cpus();
 #ifdef IXGBE_FCOE
 	u16 device_caps;
 #endif
-	u32 part_num, eec;
+	u32 eec;
 
 	/* Catch broken hardware that put the wrong VF device ID in
 	 * the PCIe SR-IOV capability.
@@ -6761,8 +7141,8 @@ static int __devinit ixgbe_probe(struct
 
 	SET_NETDEV_DEV(netdev, &pdev->dev);
 
-	pci_set_drvdata(pdev, netdev);
 	adapter = netdev_priv(netdev);
+	pci_set_drvdata(pdev, adapter);
 
 	adapter->netdev = netdev;
 	adapter->pdev = pdev;
@@ -6785,7 +7165,7 @@ static int __devinit ixgbe_probe(struct
 	netdev->netdev_ops = &ixgbe_netdev_ops;
 	ixgbe_set_ethtool_ops(netdev);
 	netdev->watchdog_timeo = 5 * HZ;
-	strcpy(netdev->name, pci_name(pdev));
+	strncpy(netdev->name, pci_name(pdev), sizeof(netdev->name) - 1);
 
 	adapter->bd_number = cards_found;
 
@@ -6835,8 +7215,14 @@ static int __devinit ixgbe_probe(struct
 		goto err_sw_init;
 
 	/* Make it possible the adapter to be woken up via WOL */
-	if (adapter->hw.mac.type == ixgbe_mac_82599EB)
+	switch (adapter->hw.mac.type) {
+	case ixgbe_mac_82599EB:
+	case ixgbe_mac_X540:
 		IXGBE_WRITE_REG(&adapter->hw, IXGBE_WUS, ~0);
+		break;
+	default:
+		break;
+	}
 
 	/*
 	 * If there is a fan on this device and it has failed log the
@@ -6944,8 +7330,11 @@ static int __devinit ixgbe_probe(struct
 		goto err_eeprom;
 	}
 
-	/* power down the optics */
-	if (hw->phy.multispeed_fiber)
+	/* power down the optics for multispeed fiber and 82599 SFP+ fiber */
+	if (hw->mac.ops.disable_tx_laser &&
+	    ((hw->phy.multispeed_fiber) ||
+	     ((hw->mac.ops.get_media_type(hw) == ixgbe_media_type_fiber) &&
+	      (hw->mac.type == ixgbe_mac_82599EB))))
 		hw->mac.ops.disable_tx_laser(hw);
 
 	init_timer(&adapter->watchdog_timer);
@@ -6960,6 +7349,18 @@ static int __devinit ixgbe_probe(struct
 		goto err_sw_init;
 
 	switch (pdev->device) {
+	case IXGBE_DEV_ID_82599_SFP:
+		/* Only this subdevice supports WOL */
+		if (pdev->subsystem_device == IXGBE_SUBDEV_ID_82599_SFP)
+			adapter->wol = (IXGBE_WUFC_MAG | IXGBE_WUFC_EX |
+			                IXGBE_WUFC_MC | IXGBE_WUFC_BC);
+		break;
+	case IXGBE_DEV_ID_82599_COMBO_BACKPLANE:
+		/* All except this subdevice support WOL */
+		if (pdev->subsystem_device != IXGBE_SUBDEV_ID_82599_KX4_KR_MEZZ)
+			adapter->wol = (IXGBE_WUFC_MAG | IXGBE_WUFC_EX |
+			                IXGBE_WUFC_MC | IXGBE_WUFC_BC);
+		break;
 	case IXGBE_DEV_ID_82599_KX4:
 		adapter->wol = (IXGBE_WUFC_MAG | IXGBE_WUFC_EX |
 				IXGBE_WUFC_MC | IXGBE_WUFC_BC);
@@ -6983,16 +7384,17 @@ static int __devinit ixgbe_probe(struct
 		    hw->bus.width == ixgbe_bus_width_pcie_x1 ? "Width x1" :
 		    "Unknown"),
 		   netdev->dev_addr);
-	ixgbe_read_pba_num_generic(hw, &part_num);
+
+	err = ixgbe_read_pba_string_generic(hw, part_str, IXGBE_PBANUM_LENGTH);
+	if (err)
+		strncpy(part_str, "Unknown", IXGBE_PBANUM_LENGTH);
 	if (ixgbe_is_sfp(hw) && hw->phy.sfp_type != ixgbe_sfp_type_not_present)
-		e_dev_info("MAC: %d, PHY: %d, SFP+: %d, "
-			   "PBA No: %06x-%03x\n",
+		e_dev_info("MAC: %d, PHY: %d, SFP+: %d, PBA No: %s\n",
 			   hw->mac.type, hw->phy.type, hw->phy.sfp_type,
-			   (part_num >> 8), (part_num & 0xff));
+		           part_str);
 	else
-		e_dev_info("MAC: %d, PHY: %d, PBA No: %06x-%03x\n",
-			   hw->mac.type, hw->phy.type,
-			   (part_num >> 8), (part_num & 0xff));
+		e_dev_info("MAC: %d, PHY: %d, PBA No: %s\n",
+			   hw->mac.type, hw->phy.type, part_str);
 
 	if (hw->bus.width <= ixgbe_bus_width_pcie_x4) {
 		e_dev_warn("PCI-Express bandwidth available for this card is "
@@ -7085,17 +7487,19 @@ err_dma:
  **/
 static void __devexit ixgbe_remove(struct pci_dev *pdev)
 {
-	struct net_device *netdev = pci_get_drvdata(pdev);
-	struct ixgbe_adapter *adapter = netdev_priv(netdev);
+	struct ixgbe_adapter *adapter = pci_get_drvdata(pdev);
+	struct net_device *netdev = adapter->netdev;
 
 	set_bit(__IXGBE_DOWN, &adapter->state);
-	/* clear the module not found bit to make sure the worker won't
-	 * reschedule
+
+	/*
+	 * The timers may be rescheduled, so explicitly disable them
+	 * from being rescheduled.
 	 */
 	clear_bit(__IXGBE_SFP_MODULE_NOT_FOUND, &adapter->state);
 	del_timer_sync(&adapter->watchdog_timer);
-
 	del_timer_sync(&adapter->sfp_timer);
+
 	cancel_work_sync(&adapter->watchdog_task);
 	cancel_work_sync(&adapter->sfp_task);
 	cancel_work_sync(&adapter->multispeed_fiber_task);
@@ -7103,7 +7507,8 @@ static void __devexit ixgbe_remove(struc
 	if (adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE ||
 	    adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE)
 		cancel_work_sync(&adapter->fdir_reinit_task);
-	flush_scheduled_work();
+	if (adapter->flags2 & IXGBE_FLAG2_TEMP_SENSOR_CAPABLE)
+		cancel_work_sync(&adapter->check_overtemp_task);
 
 #ifdef CONFIG_IXGBE_DCA
 	if (adapter->flags & IXGBE_FLAG_DCA_ENABLED) {
@@ -7156,8 +7561,8 @@ static void __devexit ixgbe_remove(struc
 static pci_ers_result_t ixgbe_io_error_detected(struct pci_dev *pdev,
 						pci_channel_state_t state)
 {
-	struct net_device *netdev = pci_get_drvdata(pdev);
-	struct ixgbe_adapter *adapter = netdev_priv(netdev);
+	struct ixgbe_adapter *adapter = pci_get_drvdata(pdev);
+	struct net_device *netdev = adapter->netdev;
 
 	netif_device_detach(netdev);
 
@@ -7180,8 +7585,7 @@ static pci_ers_result_t ixgbe_io_error_d
  */
 static pci_ers_result_t ixgbe_io_slot_reset(struct pci_dev *pdev)
 {
-	struct net_device *netdev = pci_get_drvdata(pdev);
-	struct ixgbe_adapter *adapter = netdev_priv(netdev);
+	struct ixgbe_adapter *adapter = pci_get_drvdata(pdev);
 	pci_ers_result_t result;
 	int err;
 
@@ -7219,8 +7623,8 @@ static pci_ers_result_t ixgbe_io_slot_re
  */
 static void ixgbe_io_resume(struct pci_dev *pdev)
 {
-	struct net_device *netdev = pci_get_drvdata(pdev);
-	struct ixgbe_adapter *adapter = netdev_priv(netdev);
+	struct ixgbe_adapter *adapter = pci_get_drvdata(pdev);
+	struct net_device *netdev = adapter->netdev;
 
 	if (netif_running(netdev)) {
 		if (ixgbe_up(adapter)) {
@@ -7285,6 +7689,7 @@ static void __exit ixgbe_exit_module(voi
 	dca_unregister_notify(&dca_notifier);
 #endif
 	pci_unregister_driver(&ixgbe_driver);
+	rcu_barrier(); /* Wait for completion of call_rcu()'s */
 }
 
 #ifdef CONFIG_IXGBE_DCA
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/ixgbe/ixgbe_mbx.c linux-libre-2.6.38-gnu1/drivers/net/ixgbe/ixgbe_mbx.c
--- linux-libre-2.6.37-gnu1/drivers/net/ixgbe/ixgbe_mbx.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/ixgbe/ixgbe_mbx.c	2011-03-14 21:20:32.000000000 -0400
@@ -319,8 +319,16 @@ static s32 ixgbe_check_for_rst_pf(struct
 	u32 vflre = 0;
 	s32 ret_val = IXGBE_ERR_MBX;
 
-	if (hw->mac.type == ixgbe_mac_82599EB)
+	switch (hw->mac.type) {
+	case ixgbe_mac_82599EB:
 		vflre = IXGBE_READ_REG(hw, IXGBE_VFLRE(reg_offset));
+		break;
+	case ixgbe_mac_X540:
+		vflre = IXGBE_READ_REG(hw, IXGBE_VFLREC(reg_offset));
+		break;
+	default:
+		break;
+	}
 
 	if (vflre & (1 << vf_shift)) {
 		ret_val = 0;
@@ -439,22 +447,26 @@ void ixgbe_init_mbx_params_pf(struct ixg
 {
 	struct ixgbe_mbx_info *mbx = &hw->mbx;
 
-	if (hw->mac.type != ixgbe_mac_82599EB)
-		return;
-
-	mbx->timeout = 0;
-	mbx->usec_delay = 0;
+	switch (hw->mac.type) {
+	case ixgbe_mac_82599EB:
+	case ixgbe_mac_X540:
+		mbx->timeout = 0;
+		mbx->usec_delay = 0;
 
-	mbx->size = IXGBE_VFMAILBOX_SIZE;
+		mbx->size = IXGBE_VFMAILBOX_SIZE;
 
-	mbx->stats.msgs_tx = 0;
-	mbx->stats.msgs_rx = 0;
-	mbx->stats.reqs = 0;
-	mbx->stats.acks = 0;
-	mbx->stats.rsts = 0;
+		mbx->stats.msgs_tx = 0;
+		mbx->stats.msgs_rx = 0;
+		mbx->stats.reqs = 0;
+		mbx->stats.acks = 0;
+		mbx->stats.rsts = 0;
+		break;
+	default:
+		break;
+	}
 }
 
-struct ixgbe_mbx_operations mbx_ops_82599 = {
+struct ixgbe_mbx_operations mbx_ops_generic = {
 	.read                   = ixgbe_read_mbx_pf,
 	.write                  = ixgbe_write_mbx_pf,
 	.read_posted            = ixgbe_read_posted_mbx,
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/ixgbe/ixgbe_mbx.h linux-libre-2.6.38-gnu1/drivers/net/ixgbe/ixgbe_mbx.h
--- linux-libre-2.6.37-gnu1/drivers/net/ixgbe/ixgbe_mbx.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/ixgbe/ixgbe_mbx.h	2011-03-14 21:20:32.000000000 -0400
@@ -88,6 +88,6 @@ s32 ixgbe_check_for_ack(struct ixgbe_hw
 s32 ixgbe_check_for_rst(struct ixgbe_hw *, u16);
 void ixgbe_init_mbx_params_pf(struct ixgbe_hw *);
 
-extern struct ixgbe_mbx_operations mbx_ops_82599;
+extern struct ixgbe_mbx_operations mbx_ops_generic;
 
 #endif /* _IXGBE_MBX_H_ */
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/ixgbe/ixgbe_phy.c linux-libre-2.6.38-gnu1/drivers/net/ixgbe/ixgbe_phy.c
--- linux-libre-2.6.37-gnu1/drivers/net/ixgbe/ixgbe_phy.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/ixgbe/ixgbe_phy.c	2011-03-14 21:20:32.000000000 -0400
@@ -115,6 +115,9 @@ static enum ixgbe_phy_type ixgbe_get_phy
 	case TN1010_PHY_ID:
 		phy_type = ixgbe_phy_tn;
 		break;
+	case X540_PHY_ID:
+		phy_type = ixgbe_phy_aq;
+		break;
 	case QT2022_PHY_ID:
 		phy_type = ixgbe_phy_qt;
 		break;
@@ -425,6 +428,39 @@ s32 ixgbe_setup_phy_link_speed_generic(s
 }
 
 /**
+ * ixgbe_get_copper_link_capabilities_generic - Determines link capabilities
+ * @hw: pointer to hardware structure
+ * @speed: pointer to link speed
+ * @autoneg: boolean auto-negotiation value
+ *
+ * Determines the link capabilities by reading the AUTOC register.
+ */
+s32 ixgbe_get_copper_link_capabilities_generic(struct ixgbe_hw *hw,
+                                               ixgbe_link_speed *speed,
+                                               bool *autoneg)
+{
+	s32 status = IXGBE_ERR_LINK_SETUP;
+	u16 speed_ability;
+
+	*speed = 0;
+	*autoneg = true;
+
+	status = hw->phy.ops.read_reg(hw, MDIO_SPEED, MDIO_MMD_PMAPMD,
+	                              &speed_ability);
+
+	if (status == 0) {
+		if (speed_ability & MDIO_SPEED_10G)
+			*speed |= IXGBE_LINK_SPEED_10GB_FULL;
+		if (speed_ability & MDIO_PMA_SPEED_1000)
+			*speed |= IXGBE_LINK_SPEED_1GB_FULL;
+		if (speed_ability & MDIO_PMA_SPEED_100)
+			*speed |= IXGBE_LINK_SPEED_100_FULL;
+	}
+
+	return status;
+}
+
+/**
  *  ixgbe_reset_phy_nl - Performs a PHY reset
  *  @hw: pointer to hardware structure
  **/
@@ -1375,6 +1411,22 @@ s32 ixgbe_get_phy_firmware_version_tnx(s
 	                              firmware_version);
 
 	return status;
+}
+
+/**
+ *  ixgbe_get_phy_firmware_version_generic - Gets the PHY Firmware Version
+ *  @hw: pointer to hardware structure
+ *  @firmware_version: pointer to the PHY Firmware Version
+**/
+s32 ixgbe_get_phy_firmware_version_generic(struct ixgbe_hw *hw,
+                                           u16 *firmware_version)
+{
+	s32 status = 0;
+
+	status = hw->phy.ops.read_reg(hw, AQ_FW_REV, MDIO_MMD_VEND1,
+	                              firmware_version);
+
+	return status;
 }
 
 /**
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/ixgbe/ixgbe_phy.h linux-libre-2.6.38-gnu1/drivers/net/ixgbe/ixgbe_phy.h
--- linux-libre-2.6.37-gnu1/drivers/net/ixgbe/ixgbe_phy.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/ixgbe/ixgbe_phy.h	2011-03-14 21:20:32.000000000 -0400
@@ -96,6 +96,9 @@ s32 ixgbe_setup_phy_link_speed_generic(s
                                        ixgbe_link_speed speed,
                                        bool autoneg,
                                        bool autoneg_wait_to_complete);
+s32 ixgbe_get_copper_link_capabilities_generic(struct ixgbe_hw *hw,
+                                               ixgbe_link_speed *speed,
+                                               bool *autoneg);
 
 /* PHY specific */
 s32 ixgbe_check_phy_link_tnx(struct ixgbe_hw *hw,
@@ -103,6 +106,8 @@ s32 ixgbe_check_phy_link_tnx(struct ixgb
                              bool *link_up);
 s32 ixgbe_get_phy_firmware_version_tnx(struct ixgbe_hw *hw,
                                        u16 *firmware_version);
+s32 ixgbe_get_phy_firmware_version_generic(struct ixgbe_hw *hw,
+                                           u16 *firmware_version);
 
 s32 ixgbe_reset_phy_nl(struct ixgbe_hw *hw);
 s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw);
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/ixgbe/ixgbe_sriov.c linux-libre-2.6.38-gnu1/drivers/net/ixgbe/ixgbe_sriov.c
--- linux-libre-2.6.37-gnu1/drivers/net/ixgbe/ixgbe_sriov.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/ixgbe/ixgbe_sriov.c	2011-03-14 21:20:32.000000000 -0400
@@ -68,7 +68,7 @@ static int ixgbe_set_vf_multicasts(struc
 	 * addresses
 	 */
 	for (i = 0; i < entries; i++) {
-		vfinfo->vf_mc_hashes[i] = hash_list[i];;
+		vfinfo->vf_mc_hashes[i] = hash_list[i];
 	}
 
 	for (i = 0; i < vfinfo->num_vf_mc_hashes; i++) {
@@ -110,12 +110,10 @@ static int ixgbe_set_vf_vlan(struct ixgb
 	return adapter->hw.mac.ops.set_vfta(&adapter->hw, vid, vf, (bool)add);
 }
 
-
 static void ixgbe_set_vmolr(struct ixgbe_hw *hw, u32 vf, bool aupe)
 {
 	u32 vmolr = IXGBE_READ_REG(hw, IXGBE_VMOLR(vf));
 	vmolr |= (IXGBE_VMOLR_ROMPE |
-		  IXGBE_VMOLR_ROPE |
 		  IXGBE_VMOLR_BAM);
 	if (aupe)
 		vmolr |= IXGBE_VMOLR_AUPE;
@@ -178,8 +176,7 @@ static int ixgbe_set_vf_mac(struct ixgbe
 int ixgbe_vf_configuration(struct pci_dev *pdev, unsigned int event_mask)
 {
 	unsigned char vf_mac_addr[6];
-	struct net_device *netdev = pci_get_drvdata(pdev);
-	struct ixgbe_adapter *adapter = netdev_priv(netdev);
+	struct ixgbe_adapter *adapter = pci_get_drvdata(pdev);
 	unsigned int vfn = (event_mask & 0x3f);
 
 	bool enable = ((event_mask & 0x10000000U) != 0);
@@ -216,6 +213,11 @@ static inline void ixgbe_vf_reset_msg(st
 	reg |= (reg | (1 << vf_shift));
 	IXGBE_WRITE_REG(hw, IXGBE_VFRE(reg_offset), reg);
 
+	/* Enable counting of spoofed packets in the SSVPC register */
+	reg = IXGBE_READ_REG(hw, IXGBE_VMECM(reg_offset));
+	reg |= (1 << vf_shift);
+	IXGBE_WRITE_REG(hw, IXGBE_VMECM(reg_offset), reg);
+
 	ixgbe_vf_reset_event(adapter, vf);
 }
 
@@ -228,6 +230,7 @@ static int ixgbe_rcv_msg_from_vf(struct
 	int entries;
 	u16 *hash_list;
 	int add, vid;
+	u8 *new_mac;
 
 	retval = ixgbe_read_mbx(hw, msgbuf, mbx_size, vf);
 
@@ -245,15 +248,22 @@ static int ixgbe_rcv_msg_from_vf(struct
 
 	if (msgbuf[0] == IXGBE_VF_RESET) {
 		unsigned char *vf_mac = adapter->vfinfo[vf].vf_mac_addresses;
-		u8 *addr = (u8 *)(&msgbuf[1]);
+		new_mac = (u8 *)(&msgbuf[1]);
 		e_info(probe, "VF Reset msg received from vf %d\n", vf);
 		adapter->vfinfo[vf].clear_to_send = false;
 		ixgbe_vf_reset_msg(adapter, vf);
 		adapter->vfinfo[vf].clear_to_send = true;
 
+		if (is_valid_ether_addr(new_mac) &&
+		    !adapter->vfinfo[vf].pf_set_mac)
+			ixgbe_set_vf_mac(adapter, vf, vf_mac);
+		else
+			ixgbe_set_vf_mac(adapter,
+				 vf, adapter->vfinfo[vf].vf_mac_addresses);
+
 		/* reply to reset with ack and vf mac address */
 		msgbuf[0] = IXGBE_VF_RESET | IXGBE_VT_MSGTYPE_ACK;
-		memcpy(addr, vf_mac, IXGBE_ETH_LENGTH_OF_ADDRESS);
+		memcpy(new_mac, vf_mac, IXGBE_ETH_LENGTH_OF_ADDRESS);
 		/*
 		 * Piggyback the multicast filter type so VF can compute the
 		 * correct vectors
@@ -272,14 +282,16 @@ static int ixgbe_rcv_msg_from_vf(struct
 
 	switch ((msgbuf[0] & 0xFFFF)) {
 	case IXGBE_VF_SET_MAC_ADDR:
-		{
-			u8 *new_mac = ((u8 *)(&msgbuf[1]));
-			if (is_valid_ether_addr(new_mac) &&
-			    !adapter->vfinfo[vf].pf_set_mac)
-				ixgbe_set_vf_mac(adapter, vf, new_mac);
-			else
-				ixgbe_set_vf_mac(adapter,
-				  vf, adapter->vfinfo[vf].vf_mac_addresses);
+		new_mac = ((u8 *)(&msgbuf[1]));
+		if (is_valid_ether_addr(new_mac) &&
+		    !adapter->vfinfo[vf].pf_set_mac) {
+			ixgbe_set_vf_mac(adapter, vf, new_mac);
+		} else if (memcmp(adapter->vfinfo[vf].vf_mac_addresses,
+				  new_mac, ETH_ALEN)) {
+			e_warn(drv, "VF %d attempted to override "
+			       "administratively set MAC address\nReload "
+			       "the VF driver to resume operations\n", vf);
+			retval = -1;
 		}
 		break;
 	case IXGBE_VF_SET_MULTICAST:
@@ -296,7 +308,15 @@ static int ixgbe_rcv_msg_from_vf(struct
 		add = (msgbuf[0] & IXGBE_VT_MSGINFO_MASK)
 		      >> IXGBE_VT_MSGINFO_SHIFT;
 		vid = (msgbuf[1] & IXGBE_VLVF_VLANID_MASK);
-		retval = ixgbe_set_vf_vlan(adapter, add, vid, vf);
+		if (adapter->vfinfo[vf].pf_vlan) {
+			e_warn(drv, "VF %d attempted to override "
+			       "administratively set VLAN configuration\n"
+			       "Reload the VF driver to resume operations\n",
+			       vf);
+			retval = -1;
+		} else {
+			retval = ixgbe_set_vf_vlan(adapter, add, vid, vf);
+		}
 		break;
 	default:
 		e_err(drv, "Unhandled Msg %8.8x\n", msgbuf[0]);
@@ -395,6 +415,7 @@ int ixgbe_ndo_set_vf_vlan(struct net_dev
 {
 	int err = 0;
 	struct ixgbe_adapter *adapter = netdev_priv(netdev);
+	struct ixgbe_hw *hw = &adapter->hw;
 
 	if ((vf >= adapter->num_vfs) || (vlan > 4095) || (qos > 7))
 		return -EINVAL;
@@ -403,7 +424,8 @@ int ixgbe_ndo_set_vf_vlan(struct net_dev
 		if (err)
 			goto out;
 		ixgbe_set_vmvir(adapter, vlan | (qos << VLAN_PRIO_SHIFT), vf);
-		ixgbe_set_vmolr(&adapter->hw, vf, false);
+		ixgbe_set_vmolr(hw, vf, false);
+		hw->mac.ops.set_vlan_anti_spoofing(hw, true, vf);
 		adapter->vfinfo[vf].pf_vlan = vlan;
 		adapter->vfinfo[vf].pf_qos = qos;
 		dev_info(&adapter->pdev->dev,
@@ -420,7 +442,8 @@ int ixgbe_ndo_set_vf_vlan(struct net_dev
 		err = ixgbe_set_vf_vlan(adapter, false,
 					adapter->vfinfo[vf].pf_vlan, vf);
 		ixgbe_set_vmvir(adapter, vlan, vf);
-		ixgbe_set_vmolr(&adapter->hw, vf, true);
+		ixgbe_set_vmolr(hw, vf, true);
+		hw->mac.ops.set_vlan_anti_spoofing(hw, false, vf);
 		adapter->vfinfo[vf].pf_vlan = 0;
 		adapter->vfinfo[vf].pf_qos = 0;
        }
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/ixgbe/ixgbe_type.h linux-libre-2.6.38-gnu1/drivers/net/ixgbe/ixgbe_type.h
--- linux-libre-2.6.37-gnu1/drivers/net/ixgbe/ixgbe_type.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/ixgbe/ixgbe_type.h	2011-03-14 21:20:32.000000000 -0400
@@ -54,9 +54,14 @@
 #define IXGBE_DEV_ID_82599_T3_LOM        0x151C
 #define IXGBE_DEV_ID_82599_CX4           0x10F9
 #define IXGBE_DEV_ID_82599_SFP           0x10FB
+#define IXGBE_DEV_ID_82599_BACKPLANE_FCOE       0x152a
+#define IXGBE_DEV_ID_82599_SFP_FCOE      0x1529
+#define IXGBE_SUBDEV_ID_82599_SFP        0x11A9
 #define IXGBE_DEV_ID_82599_SFP_EM        0x1507
 #define IXGBE_DEV_ID_82599_XAUI_LOM      0x10FC
 #define IXGBE_DEV_ID_82599_COMBO_BACKPLANE 0x10F8
+#define IXGBE_SUBDEV_ID_82599_KX4_KR_MEZZ  0x000C
+#define IXGBE_DEV_ID_X540T               0x1528
 
 /* General Registers */
 #define IXGBE_CTRL      0x00000
@@ -225,6 +230,7 @@
 #define IXGBE_VT_CTL    0x051B0
 #define IXGBE_VFRE(_i)  (0x051E0 + ((_i) * 4))
 #define IXGBE_VFTE(_i)  (0x08110 + ((_i) * 4))
+#define IXGBE_VMECM(_i) (0x08790 + ((_i) * 4))
 #define IXGBE_QDE       0x2F04
 #define IXGBE_VMOLR(_i) (0x0F000 + ((_i) * 4)) /* 64 total */
 #define IXGBE_UTA(_i)   (0x0F400 + ((_i) * 4))
@@ -279,7 +285,8 @@
 #define IXGBE_TDWBAH(_i) (0x0603C + ((_i) * 0x40))
 #define IXGBE_DTXCTL    0x07E00
 
-#define IXGBE_DMATXCTL  0x04A80
+#define IXGBE_DMATXCTL      0x04A80
+#define IXGBE_PFVFSPOOF(_i) (0x08200 + ((_i) * 4)) /* 8 of these 0 - 7 */
 #define IXGBE_PFDTXGSWC     0x08220
 #define IXGBE_DTXMXSZRQ     0x08100
 #define IXGBE_DTXTCPFLGL    0x04A88
@@ -293,6 +300,13 @@
 #define IXGBE_DMATXCTL_VT_SHIFT 16  /* VLAN EtherType */
 
 #define IXGBE_PFDTXGSWC_VT_LBEN 0x1 /* Local L2 VT switch enable */
+
+/* Anti-spoofing defines */
+#define IXGBE_SPOOF_MACAS_MASK          0xFF
+#define IXGBE_SPOOF_VLANAS_MASK         0xFF00
+#define IXGBE_SPOOF_VLANAS_SHIFT        8
+#define IXGBE_PFVFSPOOF_REG_COUNT       8
+
 #define IXGBE_DCA_TXCTRL(_i)    (0x07200 + ((_i) * 4)) /* 16 of these (0-15) */
 /* Tx DCA Control register : 128 of these (0-127) */
 #define IXGBE_DCA_TXCTRL_82599(_i)  (0x0600C + ((_i) * 0x40))
@@ -994,8 +1008,10 @@
 /* PHY IDs*/
 #define TN1010_PHY_ID    0x00A19410
 #define TNX_FW_REV       0xB
+#define X540_PHY_ID      0x01540200
 #define QT2022_PHY_ID    0x0043A400
 #define ATH_PHY_ID       0x03429050
+#define AQ_FW_REV        0x20
 
 /* PHY Types */
 #define IXGBE_M88E1145_E_PHY_ID  0x01410CD0
@@ -1463,6 +1479,8 @@
 #define IXGBE_ANLP1_PAUSE               0x0C00
 #define IXGBE_ANLP1_SYM_PAUSE           0x0400
 #define IXGBE_ANLP1_ASM_PAUSE           0x0800
+#define IXGBE_ANLP1_AN_STATE_MASK       0x000f0000
+
 
 /* SW Semaphore Register bitmasks */
 #define IXGBE_SWSM_SMBI 0x00000001 /* Driver Semaphore bit */
@@ -1491,6 +1509,7 @@
 #define IXGBE_EEC_PRES      0x00000100 /* EEPROM Present */
 #define IXGBE_EEC_ARD       0x00000200 /* EEPROM Auto Read Done */
 #define IXGBE_EEC_FLUP      0x00800000 /* Flash update command */
+#define IXGBE_EEC_SEC1VAL   0x02000000 /* Sector 1 Valid */
 #define IXGBE_EEC_FLUDONE   0x04000000 /* Flash update done */
 /* EEPROM Addressing bits based on type (0-small, 1-large) */
 #define IXGBE_EEC_ADDR_SIZE 0x00000400
@@ -1500,12 +1519,18 @@
 #define IXGBE_EEPROM_WORD_SIZE_SHIFT  6
 #define IXGBE_EEPROM_OPCODE_BITS      8
 
+/* Part Number String Length */
+#define IXGBE_PBANUM_LENGTH 11
+
 /* Checksum and EEPROM pointers */
+#define IXGBE_PBANUM_PTR_GUARD  0xFAFA
 #define IXGBE_EEPROM_CHECKSUM   0x3F
 #define IXGBE_EEPROM_SUM        0xBABA
 #define IXGBE_PCIE_ANALOG_PTR   0x03
 #define IXGBE_ATLAS0_CONFIG_PTR 0x04
+#define IXGBE_PHY_PTR           0x04
 #define IXGBE_ATLAS1_CONFIG_PTR 0x05
+#define IXGBE_OPTION_ROM_PTR    0x05
 #define IXGBE_PCIE_GENERAL_PTR  0x06
 #define IXGBE_PCIE_CONFIG0_PTR  0x07
 #define IXGBE_PCIE_CONFIG1_PTR  0x08
@@ -1922,10 +1947,9 @@ enum ixgbe_fdir_pballoc_type {
 #define IXGBE_FDIRM_VLANID                      0x00000001
 #define IXGBE_FDIRM_VLANP                       0x00000002
 #define IXGBE_FDIRM_POOL                        0x00000004
-#define IXGBE_FDIRM_L3P                         0x00000008
-#define IXGBE_FDIRM_L4P                         0x00000010
-#define IXGBE_FDIRM_FLEX                        0x00000020
-#define IXGBE_FDIRM_DIPv6                       0x00000040
+#define IXGBE_FDIRM_L4P                         0x00000008
+#define IXGBE_FDIRM_FLEX                        0x00000010
+#define IXGBE_FDIRM_DIPv6                       0x00000020
 
 #define IXGBE_FDIRFREE_FREE_MASK                0xFFFF
 #define IXGBE_FDIRFREE_FREE_SHIFT               0
@@ -1965,6 +1989,7 @@ enum ixgbe_fdir_pballoc_type {
 #define IXGBE_FDIRCMD_LAST                      0x00000800
 #define IXGBE_FDIRCMD_COLLISION                 0x00001000
 #define IXGBE_FDIRCMD_QUEUE_EN                  0x00008000
+#define IXGBE_FDIRCMD_FLOW_TYPE_SHIFT           5
 #define IXGBE_FDIRCMD_RX_QUEUE_SHIFT            16
 #define IXGBE_FDIRCMD_VT_POOL_SHIFT             24
 #define IXGBE_FDIR_INIT_DONE_POLL               10
@@ -2113,57 +2138,95 @@ typedef u32 ixgbe_physical_layer;
 #define IXGBE_PHYSICAL_LAYER_10GBASE_XAUI 0x1000
 #define IXGBE_PHYSICAL_LAYER_SFP_ACTIVE_DA 0x2000
 
-/* Software ATR hash keys */
-#define IXGBE_ATR_BUCKET_HASH_KEY    0xE214AD3D
-#define IXGBE_ATR_SIGNATURE_HASH_KEY 0x14364D17
+/* Flow Control Macros */
+#define PAUSE_RTT	8
+#define PAUSE_MTU(MTU)	((MTU + 1024 - 1) / 1024)
 
-/* Software ATR input stream offsets and masks */
-#define IXGBE_ATR_VLAN_OFFSET       0
-#define IXGBE_ATR_SRC_IPV6_OFFSET   2
-#define IXGBE_ATR_SRC_IPV4_OFFSET  14
-#define IXGBE_ATR_DST_IPV6_OFFSET  18
-#define IXGBE_ATR_DST_IPV4_OFFSET  30
-#define IXGBE_ATR_SRC_PORT_OFFSET  34
-#define IXGBE_ATR_DST_PORT_OFFSET  36
-#define IXGBE_ATR_FLEX_BYTE_OFFSET 38
-#define IXGBE_ATR_VM_POOL_OFFSET   40
-#define IXGBE_ATR_L4TYPE_OFFSET    41
+#define FC_HIGH_WATER(MTU) ((((PAUSE_RTT + PAUSE_MTU(MTU)) * 144) + 99) / 100 +\
+				PAUSE_MTU(MTU))
+#define FC_LOW_WATER(MTU)  (2 * (2 * PAUSE_MTU(MTU) + PAUSE_RTT))
 
+/* Software ATR hash keys */
+#define IXGBE_ATR_BUCKET_HASH_KEY    0x3DAD14E2
+#define IXGBE_ATR_SIGNATURE_HASH_KEY 0x174D3614
+
+/* Software ATR input stream values and masks */
+#define IXGBE_ATR_HASH_MASK     0x7fff
 #define IXGBE_ATR_L4TYPE_MASK      0x3
-#define IXGBE_ATR_L4TYPE_IPV6_MASK 0x4
 #define IXGBE_ATR_L4TYPE_UDP       0x1
 #define IXGBE_ATR_L4TYPE_TCP       0x2
 #define IXGBE_ATR_L4TYPE_SCTP      0x3
-#define IXGBE_ATR_HASH_MASK     0x7fff
+#define IXGBE_ATR_L4TYPE_IPV6_MASK 0x4
+enum ixgbe_atr_flow_type {
+	IXGBE_ATR_FLOW_TYPE_IPV4   = 0x0,
+	IXGBE_ATR_FLOW_TYPE_UDPV4  = 0x1,
+	IXGBE_ATR_FLOW_TYPE_TCPV4  = 0x2,
+	IXGBE_ATR_FLOW_TYPE_SCTPV4 = 0x3,
+	IXGBE_ATR_FLOW_TYPE_IPV6   = 0x4,
+	IXGBE_ATR_FLOW_TYPE_UDPV6  = 0x5,
+	IXGBE_ATR_FLOW_TYPE_TCPV6  = 0x6,
+	IXGBE_ATR_FLOW_TYPE_SCTPV6 = 0x7,
+};
 
 /* Flow Director ATR input struct. */
-struct ixgbe_atr_input {
-	/* Byte layout in order, all values with MSB first:
+union ixgbe_atr_input {
+	/*
+	 * Byte layout in order, all values with MSB first:
 	 *
+	 * vm_pool    - 1 byte
+	 * flow_type  - 1 byte
 	 * vlan_id    - 2 bytes
 	 * src_ip     - 16 bytes
 	 * dst_ip     - 16 bytes
 	 * src_port   - 2 bytes
 	 * dst_port   - 2 bytes
 	 * flex_bytes - 2 bytes
-	 * vm_pool    - 1 byte
-	 * l4type     - 1 byte
+	 * rsvd0      - 2 bytes - space reserved must be 0.
 	 */
-	u8 byte_stream[42];
+	struct {
+		u8     vm_pool;
+		u8     flow_type;
+		__be16 vlan_id;
+		__be32 dst_ip[4];
+		__be32 src_ip[4];
+		__be16 src_port;
+		__be16 dst_port;
+		__be16 flex_bytes;
+		__be16 rsvd0;
+	} formatted;
+	__be32 dword_stream[11];
+};
+
+/* Flow Director compressed ATR hash input struct */
+union ixgbe_atr_hash_dword {
+	struct {
+		u8 vm_pool;
+		u8 flow_type;
+		__be16 vlan_id;
+	} formatted;
+	__be32 ip;
+	struct {
+		__be16 src;
+		__be16 dst;
+	} port;
+	__be16 flex_bytes;
+	__be32 dword;
 };
 
 struct ixgbe_atr_input_masks {
-	u32 src_ip_mask;
-	u32 dst_ip_mask;
-	u16 src_port_mask;
-	u16 dst_port_mask;
-	u16 vlan_id_mask;
-	u16 data_mask;
+	__be16 rsvd0;
+	__be16 vlan_id_mask;
+	__be32 dst_ip_mask[4];
+	__be32 src_ip_mask[4];
+	__be16 src_port_mask;
+	__be16 dst_port_mask;
+	__be16 flex_mask;
 };
 
 enum ixgbe_eeprom_type {
 	ixgbe_eeprom_uninitialized = 0,
 	ixgbe_eeprom_spi,
+	ixgbe_flash,
 	ixgbe_eeprom_none /* No NVM support */
 };
 
@@ -2171,12 +2234,14 @@ enum ixgbe_mac_type {
 	ixgbe_mac_unknown = 0,
 	ixgbe_mac_82598EB,
 	ixgbe_mac_82599EB,
+	ixgbe_mac_X540,
 	ixgbe_num_macs
 };
 
 enum ixgbe_phy_type {
 	ixgbe_phy_unknown = 0,
 	ixgbe_phy_tn,
+	ixgbe_phy_aq,
 	ixgbe_phy_cu_unknown,
 	ixgbe_phy_qt,
 	ixgbe_phy_xaui,
@@ -2405,6 +2470,7 @@ struct ixgbe_eeprom_operations {
 	s32 (*write)(struct ixgbe_hw *, u16, u16);
 	s32 (*validate_checksum)(struct ixgbe_hw *, u16 *);
 	s32 (*update_checksum)(struct ixgbe_hw *);
+	u16 (*calc_checksum)(struct ixgbe_hw *);
 };
 
 struct ixgbe_mac_operations {
@@ -2454,6 +2520,8 @@ struct ixgbe_mac_operations {
 	s32 (*clear_vfta)(struct ixgbe_hw *);
 	s32 (*set_vfta)(struct ixgbe_hw *, u32, u32, bool);
 	s32 (*init_uta_tables)(struct ixgbe_hw *);
+	void (*set_mac_anti_spoofing)(struct ixgbe_hw *, bool, int);
+	void (*set_vlan_anti_spoofing)(struct ixgbe_hw *, bool, int);
 
 	/* Flow Control */
 	s32 (*fc_enable)(struct ixgbe_hw *, s32);
@@ -2574,6 +2642,7 @@ struct ixgbe_hw {
 	u16				subsystem_vendor_id;
 	u8				revision_id;
 	bool				adapter_stopped;
+	bool				force_full_reset;
 };
 
 struct ixgbe_info {
@@ -2614,6 +2683,9 @@ struct ixgbe_info {
 #define IXGBE_ERR_NO_SPACE                      -25
 #define IXGBE_ERR_OVERTEMP                      -26
 #define IXGBE_ERR_RAR_INDEX                     -27
+#define IXGBE_ERR_SFP_SETUP_NOT_COMPLETE        -30
+#define IXGBE_ERR_PBA_SECTION                   -31
+#define IXGBE_ERR_INVALID_ARGUMENT              -32
 #define IXGBE_NOT_IMPLEMENTED                   0x7FFFFFFF
 
 #endif /* _IXGBE_TYPE_H_ */
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/ixgbe/ixgbe_x540.c linux-libre-2.6.38-gnu1/drivers/net/ixgbe/ixgbe_x540.c
--- linux-libre-2.6.37-gnu1/drivers/net/ixgbe/ixgbe_x540.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/ixgbe/ixgbe_x540.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,724 @@
+/*******************************************************************************
+
+  Intel 10 Gigabit PCI Express Linux driver
+  Copyright(c) 1999 - 2010 Intel 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.,
+  51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+
+  The full GNU General Public License is included in this distribution in
+  the file called "COPYING".
+
+  Contact Information:
+  e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
+  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+
+*******************************************************************************/
+
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+
+#include "ixgbe.h"
+#include "ixgbe_phy.h"
+//#include "ixgbe_mbx.h"
+
+#define IXGBE_X540_MAX_TX_QUEUES 128
+#define IXGBE_X540_MAX_RX_QUEUES 128
+#define IXGBE_X540_RAR_ENTRIES   128
+#define IXGBE_X540_MC_TBL_SIZE   128
+#define IXGBE_X540_VFT_TBL_SIZE  128
+
+static s32 ixgbe_update_flash_X540(struct ixgbe_hw *hw);
+static s32 ixgbe_poll_flash_update_done_X540(struct ixgbe_hw *hw);
+static s32 ixgbe_acquire_swfw_sync_X540(struct ixgbe_hw *hw, u16 mask);
+static void ixgbe_release_swfw_sync_X540(struct ixgbe_hw *hw, u16 mask);
+static s32 ixgbe_get_swfw_sync_semaphore(struct ixgbe_hw *hw);
+static void ixgbe_release_swfw_sync_semaphore(struct ixgbe_hw *hw);
+
+static enum ixgbe_media_type ixgbe_get_media_type_X540(struct ixgbe_hw *hw)
+{
+	return ixgbe_media_type_copper;
+}
+
+static s32 ixgbe_get_invariants_X540(struct ixgbe_hw *hw)
+{
+	struct ixgbe_mac_info *mac = &hw->mac;
+
+	/* Call PHY identify routine to get the phy type */
+	ixgbe_identify_phy_generic(hw);
+
+	mac->mcft_size = IXGBE_X540_MC_TBL_SIZE;
+	mac->vft_size = IXGBE_X540_VFT_TBL_SIZE;
+	mac->num_rar_entries = IXGBE_X540_RAR_ENTRIES;
+	mac->max_rx_queues = IXGBE_X540_MAX_RX_QUEUES;
+	mac->max_tx_queues = IXGBE_X540_MAX_TX_QUEUES;
+	mac->max_msix_vectors = ixgbe_get_pcie_msix_count_generic(hw);
+
+	return 0;
+}
+
+/**
+ *  ixgbe_setup_mac_link_X540 - Set the auto advertised capabilitires
+ *  @hw: pointer to hardware structure
+ *  @speed: new link speed
+ *  @autoneg: true if autonegotiation enabled
+ *  @autoneg_wait_to_complete: true when waiting for completion is needed
+ **/
+static s32 ixgbe_setup_mac_link_X540(struct ixgbe_hw *hw,
+                                     ixgbe_link_speed speed, bool autoneg,
+                                     bool autoneg_wait_to_complete)
+{
+	return hw->phy.ops.setup_link_speed(hw, speed, autoneg,
+	                                    autoneg_wait_to_complete);
+}
+
+/**
+ *  ixgbe_reset_hw_X540 - Perform hardware reset
+ *  @hw: pointer to hardware structure
+ *
+ *  Resets the hardware by resetting the transmit and receive units, masks
+ *  and clears all interrupts, perform a PHY reset, and perform a link (MAC)
+ *  reset.
+ **/
+static s32 ixgbe_reset_hw_X540(struct ixgbe_hw *hw)
+{
+	ixgbe_link_speed link_speed;
+	s32 status = 0;
+	u32 ctrl;
+	u32 ctrl_ext;
+	u32 reset_bit;
+	u32 i;
+	u32 autoc;
+	u32 autoc2;
+	bool link_up = false;
+
+	/* Call adapter stop to disable tx/rx and clear interrupts */
+	hw->mac.ops.stop_adapter(hw);
+
+	/*
+	 * Prevent the PCI-E bus from from hanging by disabling PCI-E master
+	 * access and verify no pending requests before reset
+	 */
+	status = ixgbe_disable_pcie_master(hw);
+	if (status != 0) {
+		status = IXGBE_ERR_MASTER_REQUESTS_PENDING;
+		hw_dbg(hw, "PCI-E Master disable polling has failed.\n");
+	}
+
+	/*
+	 * Issue global reset to the MAC.  Needs to be SW reset if link is up.
+	 * If link reset is used when link is up, it might reset the PHY when
+	 * mng is using it.  If link is down or the flag to force full link
+	 * reset is set, then perform link reset.
+	 */
+	if (hw->force_full_reset) {
+		reset_bit = IXGBE_CTRL_LNK_RST;
+	} else {
+		hw->mac.ops.check_link(hw, &link_speed, &link_up, false);
+		if (!link_up)
+			reset_bit = IXGBE_CTRL_LNK_RST;
+		else
+			reset_bit = IXGBE_CTRL_RST;
+	}
+
+	ctrl = IXGBE_READ_REG(hw, IXGBE_CTRL);
+	IXGBE_WRITE_REG(hw, IXGBE_CTRL, (ctrl | reset_bit));
+	IXGBE_WRITE_FLUSH(hw);
+
+	/* Poll for reset bit to self-clear indicating reset is complete */
+	for (i = 0; i < 10; i++) {
+		udelay(1);
+		ctrl = IXGBE_READ_REG(hw, IXGBE_CTRL);
+		if (!(ctrl & reset_bit))
+			break;
+	}
+	if (ctrl & reset_bit) {
+		status = IXGBE_ERR_RESET_FAILED;
+		hw_dbg(hw, "Reset polling failed to complete.\n");
+	}
+
+	/* Clear PF Reset Done bit so PF/VF Mail Ops can work */
+	ctrl_ext = IXGBE_READ_REG(hw, IXGBE_CTRL_EXT);
+	ctrl_ext |= IXGBE_CTRL_EXT_PFRSTD;
+	IXGBE_WRITE_REG(hw, IXGBE_CTRL_EXT, ctrl_ext);
+
+	msleep(50);
+
+	/* Set the Rx packet buffer size. */
+	IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(0), 384 << IXGBE_RXPBSIZE_SHIFT);
+
+	/* Store the permanent mac address */
+	hw->mac.ops.get_mac_addr(hw, hw->mac.perm_addr);
+
+	/*
+	 * Store the original AUTOC/AUTOC2 values if they have not been
+	 * stored off yet.  Otherwise restore the stored original
+	 * values since the reset operation sets back to defaults.
+	 */
+	autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC);
+	autoc2 = IXGBE_READ_REG(hw, IXGBE_AUTOC2);
+	if (hw->mac.orig_link_settings_stored == false) {
+		hw->mac.orig_autoc = autoc;
+		hw->mac.orig_autoc2 = autoc2;
+		hw->mac.orig_link_settings_stored = true;
+	} else {
+		if (autoc != hw->mac.orig_autoc)
+			IXGBE_WRITE_REG(hw, IXGBE_AUTOC, (hw->mac.orig_autoc |
+			                IXGBE_AUTOC_AN_RESTART));
+
+		if ((autoc2 & IXGBE_AUTOC2_UPPER_MASK) !=
+		    (hw->mac.orig_autoc2 & IXGBE_AUTOC2_UPPER_MASK)) {
+			autoc2 &= ~IXGBE_AUTOC2_UPPER_MASK;
+			autoc2 |= (hw->mac.orig_autoc2 &
+			           IXGBE_AUTOC2_UPPER_MASK);
+			IXGBE_WRITE_REG(hw, IXGBE_AUTOC2, autoc2);
+		}
+	}
+
+	/*
+	 * Store MAC address from RAR0, clear receive address registers, and
+	 * clear the multicast table.  Also reset num_rar_entries to 128,
+	 * since we modify this value when programming the SAN MAC address.
+	 */
+	hw->mac.num_rar_entries = 128;
+	hw->mac.ops.init_rx_addrs(hw);
+
+	/* Store the permanent mac address */
+	hw->mac.ops.get_mac_addr(hw, hw->mac.perm_addr);
+
+	/* Store the permanent SAN mac address */
+	hw->mac.ops.get_san_mac_addr(hw, hw->mac.san_addr);
+
+	/* Add the SAN MAC address to the RAR only if it's a valid address */
+	if (ixgbe_validate_mac_addr(hw->mac.san_addr) == 0) {
+		hw->mac.ops.set_rar(hw, hw->mac.num_rar_entries - 1,
+		                    hw->mac.san_addr, 0, IXGBE_RAH_AV);
+
+		/* Reserve the last RAR for the SAN MAC address */
+		hw->mac.num_rar_entries--;
+	}
+
+	/* Store the alternative WWNN/WWPN prefix */
+	hw->mac.ops.get_wwn_prefix(hw, &hw->mac.wwnn_prefix,
+	                           &hw->mac.wwpn_prefix);
+
+	return status;
+}
+
+/**
+ *  ixgbe_get_supported_physical_layer_X540 - Returns physical layer type
+ *  @hw: pointer to hardware structure
+ *
+ *  Determines physical layer capabilities of the current configuration.
+ **/
+static u32 ixgbe_get_supported_physical_layer_X540(struct ixgbe_hw *hw)
+{
+	u32 physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN;
+	u16 ext_ability = 0;
+
+	hw->phy.ops.identify(hw);
+
+	hw->phy.ops.read_reg(hw, MDIO_PMA_EXTABLE, MDIO_MMD_PMAPMD,
+			     &ext_ability);
+	if (ext_ability & MDIO_PMA_EXTABLE_10GBT)
+		physical_layer |= IXGBE_PHYSICAL_LAYER_10GBASE_T;
+	if (ext_ability & MDIO_PMA_EXTABLE_1000BT)
+		physical_layer |= IXGBE_PHYSICAL_LAYER_1000BASE_T;
+	if (ext_ability & MDIO_PMA_EXTABLE_100BTX)
+		physical_layer |= IXGBE_PHYSICAL_LAYER_100BASE_TX;
+
+	return physical_layer;
+}
+
+/**
+ * ixgbe_init_eeprom_params_X540 - Initialize EEPROM params
+ * @hw: pointer to hardware structure
+ **/
+static s32 ixgbe_init_eeprom_params_X540(struct ixgbe_hw *hw)
+{
+	struct ixgbe_eeprom_info *eeprom = &hw->eeprom;
+	u32 eec;
+	u16 eeprom_size;
+
+	if (eeprom->type == ixgbe_eeprom_uninitialized) {
+		eeprom->semaphore_delay = 10;
+		eeprom->type = ixgbe_flash;
+
+		eec = IXGBE_READ_REG(hw, IXGBE_EEC);
+		eeprom_size = (u16)((eec & IXGBE_EEC_SIZE) >>
+		                    IXGBE_EEC_SIZE_SHIFT);
+		eeprom->word_size = 1 << (eeprom_size +
+		                          IXGBE_EEPROM_WORD_SIZE_SHIFT);
+
+		hw_dbg(hw, "Eeprom params: type = %d, size = %d\n",
+		        eeprom->type, eeprom->word_size);
+	}
+
+	return 0;
+}
+
+/**
+ * ixgbe_read_eerd_X540 - Read EEPROM word using EERD
+ * @hw: pointer to hardware structure
+ * @offset: offset of word in the EEPROM to read
+ * @data: word read from the EERPOM
+ **/
+static s32 ixgbe_read_eerd_X540(struct ixgbe_hw *hw, u16 offset, u16 *data)
+{
+	s32 status;
+
+	if (ixgbe_acquire_swfw_sync_X540(hw, IXGBE_GSSR_EEP_SM) == 0)
+		status = ixgbe_read_eerd_generic(hw, offset, data);
+	else
+		status = IXGBE_ERR_SWFW_SYNC;
+
+	ixgbe_release_swfw_sync_X540(hw, IXGBE_GSSR_EEP_SM);
+	return status;
+}
+
+/**
+ * ixgbe_write_eewr_X540 - Write EEPROM word using EEWR
+ * @hw: pointer to hardware structure
+ * @offset: offset of  word in the EEPROM to write
+ * @data: word write to the EEPROM
+ *
+ * Write a 16 bit word to the EEPROM using the EEWR register.
+ **/
+static s32 ixgbe_write_eewr_X540(struct ixgbe_hw *hw, u16 offset, u16 data)
+{
+	u32 eewr;
+	s32 status;
+
+	hw->eeprom.ops.init_params(hw);
+
+	if (offset >= hw->eeprom.word_size) {
+		status = IXGBE_ERR_EEPROM;
+		goto out;
+	}
+
+	eewr = (offset << IXGBE_EEPROM_RW_ADDR_SHIFT) |
+	       (data << IXGBE_EEPROM_RW_REG_DATA) |
+	       IXGBE_EEPROM_RW_REG_START;
+
+	if (ixgbe_acquire_swfw_sync_X540(hw, IXGBE_GSSR_EEP_SM) == 0) {
+		status = ixgbe_poll_eerd_eewr_done(hw, IXGBE_NVM_POLL_WRITE);
+		if (status != 0) {
+			hw_dbg(hw, "Eeprom write EEWR timed out\n");
+			goto out;
+		}
+
+		IXGBE_WRITE_REG(hw, IXGBE_EEWR, eewr);
+
+		status = ixgbe_poll_eerd_eewr_done(hw, IXGBE_NVM_POLL_WRITE);
+		if (status != 0) {
+			hw_dbg(hw, "Eeprom write EEWR timed out\n");
+			goto out;
+		}
+	} else {
+		status = IXGBE_ERR_SWFW_SYNC;
+	}
+
+out:
+	ixgbe_release_swfw_sync_X540(hw, IXGBE_GSSR_EEP_SM);
+	return status;
+}
+
+/**
+ * ixgbe_calc_eeprom_checksum_X540 - Calculates and returns the checksum
+ * @hw: pointer to hardware structure
+ **/
+static u16 ixgbe_calc_eeprom_checksum_X540(struct ixgbe_hw *hw)
+{
+	u16 i;
+	u16 j;
+	u16 checksum = 0;
+	u16 length = 0;
+	u16 pointer = 0;
+	u16 word = 0;
+
+	/* Include 0x0-0x3F in the checksum */
+	for (i = 0; i < IXGBE_EEPROM_CHECKSUM; i++) {
+		if (hw->eeprom.ops.read(hw, i, &word) != 0) {
+			hw_dbg(hw, "EEPROM read failed\n");
+			break;
+		}
+		checksum += word;
+	}
+
+	/*
+	 * Include all data from pointers 0x3, 0x6-0xE.  This excludes the
+	 * FW, PHY module, and PCIe Expansion/Option ROM pointers.
+	 */
+	for (i = IXGBE_PCIE_ANALOG_PTR; i < IXGBE_FW_PTR; i++) {
+		if (i == IXGBE_PHY_PTR || i == IXGBE_OPTION_ROM_PTR)
+			continue;
+
+		if (hw->eeprom.ops.read(hw, i, &pointer) != 0) {
+			hw_dbg(hw, "EEPROM read failed\n");
+			break;
+		}
+
+		/* Skip pointer section if the pointer is invalid. */
+		if (pointer == 0xFFFF || pointer == 0 ||
+		    pointer >= hw->eeprom.word_size)
+			continue;
+
+		if (hw->eeprom.ops.read(hw, pointer, &length) != 0) {
+			hw_dbg(hw, "EEPROM read failed\n");
+			break;
+		}
+
+		/* Skip pointer section if length is invalid. */
+		if (length == 0xFFFF || length == 0 ||
+		    (pointer + length) >= hw->eeprom.word_size)
+			continue;
+
+		for (j = pointer+1; j <= pointer+length; j++) {
+			if (hw->eeprom.ops.read(hw, j, &word) != 0) {
+				hw_dbg(hw, "EEPROM read failed\n");
+				break;
+			}
+			checksum += word;
+		}
+	}
+
+	checksum = (u16)IXGBE_EEPROM_SUM - checksum;
+
+	return checksum;
+}
+
+/**
+ * ixgbe_update_eeprom_checksum_X540 - Updates the EEPROM checksum and flash
+ * @hw: pointer to hardware structure
+ *
+ * After writing EEPROM to shadow RAM using EEWR register, software calculates
+ * checksum and updates the EEPROM and instructs the hardware to update
+ * the flash.
+ **/
+static s32 ixgbe_update_eeprom_checksum_X540(struct ixgbe_hw *hw)
+{
+	s32 status;
+
+	status = ixgbe_update_eeprom_checksum_generic(hw);
+
+	if (status)
+		status = ixgbe_update_flash_X540(hw);
+
+	return status;
+}
+
+/**
+ * ixgbe_update_flash_X540 - Instruct HW to copy EEPROM to Flash device
+ * @hw: pointer to hardware structure
+ *
+ * Set FLUP (bit 23) of the EEC register to instruct Hardware to copy
+ * EEPROM from shadow RAM to the flash device.
+ **/
+static s32 ixgbe_update_flash_X540(struct ixgbe_hw *hw)
+{
+	u32 flup;
+	s32 status = IXGBE_ERR_EEPROM;
+
+	status = ixgbe_poll_flash_update_done_X540(hw);
+	if (status == IXGBE_ERR_EEPROM) {
+		hw_dbg(hw, "Flash update time out\n");
+		goto out;
+	}
+
+	flup = IXGBE_READ_REG(hw, IXGBE_EEC) | IXGBE_EEC_FLUP;
+	IXGBE_WRITE_REG(hw, IXGBE_EEC, flup);
+
+	status = ixgbe_poll_flash_update_done_X540(hw);
+	if (status)
+		hw_dbg(hw, "Flash update complete\n");
+	else
+		hw_dbg(hw, "Flash update time out\n");
+
+	if (hw->revision_id == 0) {
+		flup = IXGBE_READ_REG(hw, IXGBE_EEC);
+
+		if (flup & IXGBE_EEC_SEC1VAL) {
+			flup |= IXGBE_EEC_FLUP;
+			IXGBE_WRITE_REG(hw, IXGBE_EEC, flup);
+		}
+
+		status = ixgbe_poll_flash_update_done_X540(hw);
+		if (status)
+			hw_dbg(hw, "Flash update complete\n");
+		else
+			hw_dbg(hw, "Flash update time out\n");
+
+	}
+out:
+	return status;
+}
+
+/**
+ * ixgbe_poll_flash_update_done_X540 - Poll flash update status
+ * @hw: pointer to hardware structure
+ *
+ * Polls the FLUDONE (bit 26) of the EEC Register to determine when the
+ * flash update is done.
+ **/
+static s32 ixgbe_poll_flash_update_done_X540(struct ixgbe_hw *hw)
+{
+	u32 i;
+	u32 reg;
+	s32 status = IXGBE_ERR_EEPROM;
+
+	for (i = 0; i < IXGBE_FLUDONE_ATTEMPTS; i++) {
+		reg = IXGBE_READ_REG(hw, IXGBE_EEC);
+		if (reg & IXGBE_EEC_FLUDONE) {
+			status = 0;
+			break;
+		}
+		udelay(5);
+	}
+	return status;
+}
+
+/**
+ * ixgbe_acquire_swfw_sync_X540 - Acquire SWFW semaphore
+ * @hw: pointer to hardware structure
+ * @mask: Mask to specify which semaphore to acquire
+ *
+ * Acquires the SWFW semaphore thought the SW_FW_SYNC register for
+ * the specified function (CSR, PHY0, PHY1, NVM, Flash)
+ **/
+static s32 ixgbe_acquire_swfw_sync_X540(struct ixgbe_hw *hw, u16 mask)
+{
+	u32 swfw_sync;
+	u32 swmask = mask;
+	u32 fwmask = mask << 5;
+	u32 hwmask = 0;
+	u32 timeout = 200;
+	u32 i;
+
+	if (swmask == IXGBE_GSSR_EEP_SM)
+		hwmask = IXGBE_GSSR_FLASH_SM;
+
+	for (i = 0; i < timeout; i++) {
+		/*
+		 * SW NVM semaphore bit is used for access to all
+		 * SW_FW_SYNC bits (not just NVM)
+		 */
+		if (ixgbe_get_swfw_sync_semaphore(hw))
+			return IXGBE_ERR_SWFW_SYNC;
+
+		swfw_sync = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC);
+		if (!(swfw_sync & (fwmask | swmask | hwmask))) {
+			swfw_sync |= swmask;
+			IXGBE_WRITE_REG(hw, IXGBE_SWFW_SYNC, swfw_sync);
+			ixgbe_release_swfw_sync_semaphore(hw);
+			break;
+		} else {
+			/*
+			 * Firmware currently using resource (fwmask),
+			 * hardware currently using resource (hwmask),
+			 * or other software thread currently using
+			 * resource (swmask)
+			 */
+			ixgbe_release_swfw_sync_semaphore(hw);
+			msleep(5);
+		}
+	}
+
+	/*
+	 * If the resource is not released by the FW/HW the SW can assume that
+	 * the FW/HW malfunctions. In that case the SW should sets the
+	 * SW bit(s) of the requested resource(s) while ignoring the
+	 * corresponding FW/HW bits in the SW_FW_SYNC register.
+	 */
+	if (i >= timeout) {
+		swfw_sync = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC);
+		if (swfw_sync & (fwmask | hwmask)) {
+			if (ixgbe_get_swfw_sync_semaphore(hw))
+				return IXGBE_ERR_SWFW_SYNC;
+
+			swfw_sync |= swmask;
+			IXGBE_WRITE_REG(hw, IXGBE_SWFW_SYNC, swfw_sync);
+			ixgbe_release_swfw_sync_semaphore(hw);
+		}
+	}
+
+	msleep(5);
+	return 0;
+}
+
+/**
+ * ixgbe_release_swfw_sync_X540 - Release SWFW semaphore
+ * @hw: pointer to hardware structure
+ * @mask: Mask to specify which semaphore to release
+ *
+ * Releases the SWFW semaphore throught the SW_FW_SYNC register
+ * for the specified function (CSR, PHY0, PHY1, EVM, Flash)
+ **/
+static void ixgbe_release_swfw_sync_X540(struct ixgbe_hw *hw, u16 mask)
+{
+	u32 swfw_sync;
+	u32 swmask = mask;
+
+	ixgbe_get_swfw_sync_semaphore(hw);
+
+	swfw_sync = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC);
+	swfw_sync &= ~swmask;
+	IXGBE_WRITE_REG(hw, IXGBE_SWFW_SYNC, swfw_sync);
+
+	ixgbe_release_swfw_sync_semaphore(hw);
+	msleep(5);
+}
+
+/**
+ * ixgbe_get_nvm_semaphore - Get hardware semaphore
+ * @hw: pointer to hardware structure
+ *
+ * Sets the hardware semaphores so SW/FW can gain control of shared resources
+ **/
+static s32 ixgbe_get_swfw_sync_semaphore(struct ixgbe_hw *hw)
+{
+	s32 status = IXGBE_ERR_EEPROM;
+	u32 timeout = 2000;
+	u32 i;
+	u32 swsm;
+
+	/* Get SMBI software semaphore between device drivers first */
+	for (i = 0; i < timeout; i++) {
+		/*
+		 * If the SMBI bit is 0 when we read it, then the bit will be
+		 * set and we have the semaphore
+		 */
+		swsm = IXGBE_READ_REG(hw, IXGBE_SWSM);
+		if (!(swsm & IXGBE_SWSM_SMBI)) {
+			status = 0;
+			break;
+		}
+		udelay(50);
+	}
+
+	/* Now get the semaphore between SW/FW through the REGSMP bit */
+	if (status) {
+		for (i = 0; i < timeout; i++) {
+			swsm = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC);
+			if (!(swsm & IXGBE_SWFW_REGSMP))
+				break;
+
+			udelay(50);
+		}
+	} else {
+		hw_dbg(hw, "Software semaphore SMBI between device drivers "
+		           "not granted.\n");
+	}
+
+	return status;
+}
+
+/**
+ * ixgbe_release_nvm_semaphore - Release hardware semaphore
+ * @hw: pointer to hardware structure
+ *
+ * This function clears hardware semaphore bits.
+ **/
+static void ixgbe_release_swfw_sync_semaphore(struct ixgbe_hw *hw)
+{
+	 u32 swsm;
+
+	/* Release both semaphores by writing 0 to the bits REGSMP and SMBI */
+
+	swsm = IXGBE_READ_REG(hw, IXGBE_SWSM);
+	swsm &= ~IXGBE_SWSM_SMBI;
+	IXGBE_WRITE_REG(hw, IXGBE_SWSM, swsm);
+
+	swsm = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC);
+	swsm &= ~IXGBE_SWFW_REGSMP;
+	IXGBE_WRITE_REG(hw, IXGBE_SWFW_SYNC, swsm);
+
+	IXGBE_WRITE_FLUSH(hw);
+}
+
+static struct ixgbe_mac_operations mac_ops_X540 = {
+	.init_hw                = &ixgbe_init_hw_generic,
+	.reset_hw               = &ixgbe_reset_hw_X540,
+	.start_hw               = &ixgbe_start_hw_generic,
+	.clear_hw_cntrs         = &ixgbe_clear_hw_cntrs_generic,
+	.get_media_type         = &ixgbe_get_media_type_X540,
+	.get_supported_physical_layer =
+                                  &ixgbe_get_supported_physical_layer_X540,
+	.enable_rx_dma          = &ixgbe_enable_rx_dma_generic,
+	.get_mac_addr           = &ixgbe_get_mac_addr_generic,
+	.get_san_mac_addr       = &ixgbe_get_san_mac_addr_generic,
+	.get_device_caps        = NULL,
+	.get_wwn_prefix         = &ixgbe_get_wwn_prefix_generic,
+	.stop_adapter           = &ixgbe_stop_adapter_generic,
+	.get_bus_info           = &ixgbe_get_bus_info_generic,
+	.set_lan_id             = &ixgbe_set_lan_id_multi_port_pcie,
+	.read_analog_reg8       = NULL,
+	.write_analog_reg8      = NULL,
+	.setup_link             = &ixgbe_setup_mac_link_X540,
+	.check_link             = &ixgbe_check_mac_link_generic,
+	.get_link_capabilities  = &ixgbe_get_copper_link_capabilities_generic,
+	.led_on                 = &ixgbe_led_on_generic,
+	.led_off                = &ixgbe_led_off_generic,
+	.blink_led_start        = &ixgbe_blink_led_start_generic,
+	.blink_led_stop         = &ixgbe_blink_led_stop_generic,
+	.set_rar                = &ixgbe_set_rar_generic,
+	.clear_rar              = &ixgbe_clear_rar_generic,
+	.set_vmdq               = &ixgbe_set_vmdq_generic,
+	.clear_vmdq             = &ixgbe_clear_vmdq_generic,
+	.init_rx_addrs          = &ixgbe_init_rx_addrs_generic,
+	.update_uc_addr_list    = &ixgbe_update_uc_addr_list_generic,
+	.update_mc_addr_list    = &ixgbe_update_mc_addr_list_generic,
+	.enable_mc              = &ixgbe_enable_mc_generic,
+	.disable_mc             = &ixgbe_disable_mc_generic,
+	.clear_vfta             = &ixgbe_clear_vfta_generic,
+	.set_vfta               = &ixgbe_set_vfta_generic,
+	.fc_enable              = &ixgbe_fc_enable_generic,
+	.init_uta_tables        = &ixgbe_init_uta_tables_generic,
+	.setup_sfp              = NULL,
+	.set_mac_anti_spoofing  = &ixgbe_set_mac_anti_spoofing,
+	.set_vlan_anti_spoofing = &ixgbe_set_vlan_anti_spoofing,
+};
+
+static struct ixgbe_eeprom_operations eeprom_ops_X540 = {
+	.init_params            = &ixgbe_init_eeprom_params_X540,
+	.read                   = &ixgbe_read_eerd_X540,
+	.write                  = &ixgbe_write_eewr_X540,
+	.calc_checksum		= &ixgbe_calc_eeprom_checksum_X540,
+	.validate_checksum      = &ixgbe_validate_eeprom_checksum_generic,
+	.update_checksum        = &ixgbe_update_eeprom_checksum_X540,
+};
+
+static struct ixgbe_phy_operations phy_ops_X540 = {
+	.identify               = &ixgbe_identify_phy_generic,
+	.identify_sfp           = &ixgbe_identify_sfp_module_generic,
+	.init			= NULL,
+	.reset                  = &ixgbe_reset_phy_generic,
+	.read_reg               = &ixgbe_read_phy_reg_generic,
+	.write_reg              = &ixgbe_write_phy_reg_generic,
+	.setup_link             = &ixgbe_setup_phy_link_generic,
+	.setup_link_speed       = &ixgbe_setup_phy_link_speed_generic,
+	.read_i2c_byte          = &ixgbe_read_i2c_byte_generic,
+	.write_i2c_byte         = &ixgbe_write_i2c_byte_generic,
+	.read_i2c_eeprom        = &ixgbe_read_i2c_eeprom_generic,
+	.write_i2c_eeprom       = &ixgbe_write_i2c_eeprom_generic,
+	.check_overtemp         = &ixgbe_tn_check_overtemp,
+};
+
+struct ixgbe_info ixgbe_X540_info = {
+	.mac                    = ixgbe_mac_X540,
+	.get_invariants         = &ixgbe_get_invariants_X540,
+	.mac_ops                = &mac_ops_X540,
+	.eeprom_ops             = &eeprom_ops_X540,
+	.phy_ops                = &phy_ops_X540,
+	.mbx_ops                = &mbx_ops_generic,
+};
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/ixgbe/Makefile linux-libre-2.6.38-gnu1/drivers/net/ixgbe/Makefile
--- linux-libre-2.6.37-gnu1/drivers/net/ixgbe/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/ixgbe/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -34,7 +34,7 @@ obj-$(CONFIG_IXGBE) += ixgbe.o
 
 ixgbe-objs := ixgbe_main.o ixgbe_common.o ixgbe_ethtool.o \
               ixgbe_82599.o ixgbe_82598.o ixgbe_phy.o ixgbe_sriov.o \
-              ixgbe_mbx.o
+              ixgbe_mbx.o ixgbe_x540.o
 
 ixgbe-$(CONFIG_IXGBE_DCB) +=  ixgbe_dcb.o ixgbe_dcb_82598.o \
                               ixgbe_dcb_82599.o ixgbe_dcb_nl.o
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/ixgbevf/defines.h linux-libre-2.6.38-gnu1/drivers/net/ixgbevf/defines.h
--- linux-libre-2.6.37-gnu1/drivers/net/ixgbevf/defines.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/ixgbevf/defines.h	2011-03-14 21:20:32.000000000 -0400
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 82599 Virtual Function driver
-  Copyright(c) 1999 - 2009 Intel Corporation.
+  Copyright(c) 1999 - 2010 Intel 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,
@@ -30,6 +30,7 @@
 
 /* Device IDs */
 #define IXGBE_DEV_ID_82599_VF           0x10ED
+#define IXGBE_DEV_ID_X540_VF            0x1515
 
 #define IXGBE_VF_IRQ_CLEAR_MASK         7
 #define IXGBE_VF_MAX_TX_QUEUES          1
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/ixgbevf/ethtool.c linux-libre-2.6.38-gnu1/drivers/net/ixgbevf/ethtool.c
--- linux-libre-2.6.37-gnu1/drivers/net/ixgbevf/ethtool.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/ixgbevf/ethtool.c	2011-03-14 21:20:32.000000000 -0400
@@ -544,7 +544,7 @@ struct ixgbevf_reg_test {
 #define TABLE64_TEST_HI	6
 
 /* default VF register test */
-static struct ixgbevf_reg_test reg_test_vf[] = {
+static const struct ixgbevf_reg_test reg_test_vf[] = {
 	{ IXGBE_VFRDBAL(0), 2, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFF80 },
 	{ IXGBE_VFRDBAH(0), 2, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF },
 	{ IXGBE_VFRDLEN(0), 2, PATTERN_TEST, 0x000FFF80, 0x000FFFFF },
@@ -557,19 +557,23 @@ static struct ixgbevf_reg_test reg_test_
 	{ 0, 0, 0, 0 }
 };
 
+static const u32 register_test_patterns[] = {
+	0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF
+};
+
 #define REG_PATTERN_TEST(R, M, W)                                             \
 {                                                                             \
 	u32 pat, val, before;                                                 \
-	const u32 _test[] = {0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF}; \
-	for (pat = 0; pat < ARRAY_SIZE(_test); pat++) {                       \
+	for (pat = 0; pat < ARRAY_SIZE(register_test_patterns); pat++) {      \
 		before = readl(adapter->hw.hw_addr + R);                      \
-		writel((_test[pat] & W), (adapter->hw.hw_addr + R));          \
+		writel((register_test_patterns[pat] & W),                     \
+		       (adapter->hw.hw_addr + R));                            \
 		val = readl(adapter->hw.hw_addr + R);                         \
-		if (val != (_test[pat] & W & M)) {                            \
+		if (val != (register_test_patterns[pat] & W & M)) {           \
 			hw_dbg(&adapter->hw,                                  \
 			"pattern test reg %04X failed: got "                  \
 			"0x%08X expected 0x%08X\n",                           \
-			R, val, (_test[pat] & W & M));                        \
+			R, val, (register_test_patterns[pat] & W & M));       \
 			*data = R;                                            \
 			writel(before, adapter->hw.hw_addr + R);              \
 			return 1;                                             \
@@ -596,7 +600,7 @@ static struct ixgbevf_reg_test reg_test_
 
 static int ixgbevf_reg_test(struct ixgbevf_adapter *adapter, u64 *data)
 {
-	struct ixgbevf_reg_test *test;
+	const struct ixgbevf_reg_test *test;
 	u32 i;
 
 	test = reg_test_vf;
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/ixgbevf/ixgbevf.h linux-libre-2.6.38-gnu1/drivers/net/ixgbevf/ixgbevf.h
--- linux-libre-2.6.37-gnu1/drivers/net/ixgbevf/ixgbevf.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/ixgbevf/ixgbevf.h	2011-03-14 21:20:32.000000000 -0400
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 82599 Virtual Function driver
-  Copyright(c) 1999 - 2009 Intel Corporation.
+  Copyright(c) 1999 - 2010 Intel 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,
@@ -275,9 +275,11 @@ enum ixbgevf_state_t {
 
 enum ixgbevf_boards {
 	board_82599_vf,
+	board_X540_vf,
 };
 
-extern struct ixgbevf_info ixgbevf_vf_info;
+extern struct ixgbevf_info ixgbevf_82599_vf_info;
+extern struct ixgbevf_info ixgbevf_X540_vf_info;
 extern struct ixgbe_mac_operations ixgbevf_mbx_ops;
 
 /* needed by ethtool.c */
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/ixgbevf/ixgbevf_main.c linux-libre-2.6.38-gnu1/drivers/net/ixgbevf/ixgbevf_main.c
--- linux-libre-2.6.37-gnu1/drivers/net/ixgbevf/ixgbevf_main.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/ixgbevf/ixgbevf_main.c	2011-03-14 21:20:32.000000000 -0400
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 82599 Virtual Function driver
-  Copyright(c) 1999 - 2009 Intel Corporation.
+  Copyright(c) 1999 - 2010 Intel 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,
@@ -51,12 +51,14 @@ char ixgbevf_driver_name[] = "ixgbevf";
 static const char ixgbevf_driver_string[] =
 	"Intel(R) 82599 Virtual Function";
 
-#define DRV_VERSION "1.0.0-k0"
+#define DRV_VERSION "1.0.19-k0"
 const char ixgbevf_driver_version[] = DRV_VERSION;
-static char ixgbevf_copyright[] = "Copyright (c) 2009 Intel Corporation.";
+static char ixgbevf_copyright[] =
+	"Copyright (c) 2009 - 2010 Intel Corporation.";
 
 static const struct ixgbevf_info *ixgbevf_info_tbl[] = {
-	[board_82599_vf] = &ixgbevf_vf_info,
+	[board_82599_vf] = &ixgbevf_82599_vf_info,
+	[board_X540_vf]  = &ixgbevf_X540_vf_info,
 };
 
 /* ixgbevf_pci_tbl - PCI Device ID Table
@@ -70,6 +72,8 @@ static const struct ixgbevf_info *ixgbev
 static struct pci_device_id ixgbevf_pci_tbl[] = {
 	{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_VF),
 	board_82599_vf},
+	{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X540_VF),
+	board_X540_vf},
 
 	/* required last entry */
 	{0, }
@@ -2488,10 +2492,9 @@ int ixgbevf_setup_tx_resources(struct ix
 	int size;
 
 	size = sizeof(struct ixgbevf_tx_buffer) * tx_ring->count;
-	tx_ring->tx_buffer_info = vmalloc(size);
+	tx_ring->tx_buffer_info = vzalloc(size);
 	if (!tx_ring->tx_buffer_info)
 		goto err;
-	memset(tx_ring->tx_buffer_info, 0, size);
 
 	/* round up to nearest 4K */
 	tx_ring->size = tx_ring->count * sizeof(union ixgbe_adv_tx_desc);
@@ -2555,14 +2558,13 @@ int ixgbevf_setup_rx_resources(struct ix
 	int size;
 
 	size = sizeof(struct ixgbevf_rx_buffer) * rx_ring->count;
-	rx_ring->rx_buffer_info = vmalloc(size);
+	rx_ring->rx_buffer_info = vzalloc(size);
 	if (!rx_ring->rx_buffer_info) {
 		hw_dbg(&adapter->hw,
 		       "Unable to vmalloc buffer memory for "
 		       "the receive descriptor ring\n");
 		goto alloc_failed;
 	}
-	memset(rx_ring->rx_buffer_info, 0, size);
 
 	/* Round up to nearest 4K */
 	rx_ring->size = rx_ring->count * sizeof(union ixgbe_adv_rx_desc);
@@ -3424,10 +3426,6 @@ static int __devinit ixgbevf_probe(struc
 	if (hw->mac.ops.get_bus_info)
 		hw->mac.ops.get_bus_info(hw);
 
-
-	netif_carrier_off(netdev);
-	netif_tx_stop_all_queues(netdev);
-
 	strcpy(netdev->name, "eth%d");
 
 	err = register_netdev(netdev);
@@ -3436,6 +3434,8 @@ static int __devinit ixgbevf_probe(struc
 
 	adapter->netdev_registered = true;
 
+	netif_carrier_off(netdev);
+
 	ixgbevf_init_last_counter_stats(adapter);
 
 	/* print the MAC address */
@@ -3487,10 +3487,9 @@ static void __devexit ixgbevf_remove(str
 
 	del_timer_sync(&adapter->watchdog_timer);
 
+	cancel_work_sync(&adapter->reset_task);
 	cancel_work_sync(&adapter->watchdog_task);
 
-	flush_scheduled_work();
-
 	if (adapter->netdev_registered) {
 		unregister_netdev(netdev);
 		adapter->netdev_registered = false;
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/ixgbevf/Makefile linux-libre-2.6.38-gnu1/drivers/net/ixgbevf/Makefile
--- linux-libre-2.6.37-gnu1/drivers/net/ixgbevf/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/ixgbevf/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -1,7 +1,7 @@
 ################################################################################
 #
 # Intel 82599 Virtual Function driver
-# Copyright(c) 1999 - 2009 Intel Corporation.
+# Copyright(c) 1999 - 2010 Intel 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,
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/ixgbevf/mbx.c linux-libre-2.6.38-gnu1/drivers/net/ixgbevf/mbx.c
--- linux-libre-2.6.37-gnu1/drivers/net/ixgbevf/mbx.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/ixgbevf/mbx.c	2011-03-14 21:20:32.000000000 -0400
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 82599 Virtual Function driver
-  Copyright(c) 1999 - 2009 Intel Corporation.
+  Copyright(c) 1999 - 2010 Intel 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,
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/ixgbevf/mbx.h linux-libre-2.6.38-gnu1/drivers/net/ixgbevf/mbx.h
--- linux-libre-2.6.37-gnu1/drivers/net/ixgbevf/mbx.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/ixgbevf/mbx.h	2011-03-14 21:20:32.000000000 -0400
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 82599 Virtual Function driver
-  Copyright(c) 1999 - 2009 Intel Corporation.
+  Copyright(c) 1999 - 2010 Intel 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,
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/ixgbevf/regs.h linux-libre-2.6.38-gnu1/drivers/net/ixgbevf/regs.h
--- linux-libre-2.6.37-gnu1/drivers/net/ixgbevf/regs.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/ixgbevf/regs.h	2011-03-14 21:20:32.000000000 -0400
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 82599 Virtual Function driver
-  Copyright(c) 1999 - 2009 Intel Corporation.
+  Copyright(c) 1999 - 2010 Intel 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,
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/ixgbevf/vf.c linux-libre-2.6.38-gnu1/drivers/net/ixgbevf/vf.c
--- linux-libre-2.6.37-gnu1/drivers/net/ixgbevf/vf.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/ixgbevf/vf.c	2011-03-14 21:20:32.000000000 -0400
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 82599 Virtual Function driver
-  Copyright(c) 1999 - 2009 Intel Corporation.
+  Copyright(c) 1999 - 2010 Intel 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,
@@ -381,8 +381,12 @@ static struct ixgbe_mac_operations ixgbe
 	.set_vfta            = ixgbevf_set_vfta_vf,
 };
 
-struct ixgbevf_info ixgbevf_vf_info = {
+struct ixgbevf_info ixgbevf_82599_vf_info = {
 	.mac = ixgbe_mac_82599_vf,
 	.mac_ops = &ixgbevf_mac_ops,
 };
 
+struct ixgbevf_info ixgbevf_X540_vf_info = {
+	.mac = ixgbe_mac_X540_vf,
+	.mac_ops = &ixgbevf_mac_ops,
+};
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/ixgbevf/vf.h linux-libre-2.6.38-gnu1/drivers/net/ixgbevf/vf.h
--- linux-libre-2.6.37-gnu1/drivers/net/ixgbevf/vf.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/ixgbevf/vf.h	2011-03-14 21:20:32.000000000 -0400
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 82599 Virtual Function driver
-  Copyright(c) 1999 - 2009 Intel Corporation.
+  Copyright(c) 1999 - 2010 Intel 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,
@@ -73,6 +73,7 @@ struct ixgbe_mac_operations {
 enum ixgbe_mac_type {
 	ixgbe_mac_unknown = 0,
 	ixgbe_mac_82599_vf,
+	ixgbe_mac_X540_vf,
 	ixgbe_num_macs
 };
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/jme.c linux-libre-2.6.38-gnu1/drivers/net/jme.c
--- linux-libre-2.6.37-gnu1/drivers/net/jme.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/jme.c	2011-03-14 21:20:32.000000000 -0400
@@ -135,7 +135,7 @@ jme_reset_phy_processor(struct jme_adapt
 
 static void
 jme_setup_wakeup_frame(struct jme_adapter *jme,
-		u32 *mask, u32 crc, int fnr)
+		       const u32 *mask, u32 crc, int fnr)
 {
 	int i;
 
@@ -163,7 +163,7 @@ jme_setup_wakeup_frame(struct jme_adapte
 static inline void
 jme_reset_mac_processor(struct jme_adapter *jme)
 {
-	u32 mask[WAKEUP_FRAME_MASK_DWNR] = {0, 0, 0, 0};
+	static const u32 mask[WAKEUP_FRAME_MASK_DWNR] = {0, 0, 0, 0};
 	u32 crc = 0xCDCDCDCD;
 	u32 gpreg0;
 	int i;
@@ -2076,12 +2076,11 @@ jme_change_mtu(struct net_device *netdev
 	}
 
 	if (new_mtu > 1900) {
-		netdev->features &= ~(NETIF_F_HW_CSUM |
-				NETIF_F_TSO |
-				NETIF_F_TSO6);
+		netdev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
+				NETIF_F_TSO | NETIF_F_TSO6);
 	} else {
 		if (test_bit(JME_FLAG_TXCSUM, &jme->flags))
-			netdev->features |= NETIF_F_HW_CSUM;
+			netdev->features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
 		if (test_bit(JME_FLAG_TSO, &jme->flags))
 			netdev->features |= NETIF_F_TSO | NETIF_F_TSO6;
 	}
@@ -2514,10 +2513,12 @@ jme_set_tx_csum(struct net_device *netde
 	if (on) {
 		set_bit(JME_FLAG_TXCSUM, &jme->flags);
 		if (netdev->mtu <= 1900)
-			netdev->features |= NETIF_F_HW_CSUM;
+			netdev->features |=
+				NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
 	} else {
 		clear_bit(JME_FLAG_TXCSUM, &jme->flags);
-		netdev->features &= ~NETIF_F_HW_CSUM;
+		netdev->features &=
+				~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM);
 	}
 
 	return 0;
@@ -2797,7 +2798,8 @@ jme_init_one(struct pci_dev *pdev,
 	netdev->netdev_ops = &jme_netdev_ops;
 	netdev->ethtool_ops		= &jme_ethtool_ops;
 	netdev->watchdog_timeo		= TX_TIMEOUT;
-	netdev->features		=	NETIF_F_HW_CSUM |
+	netdev->features		=	NETIF_F_IP_CSUM |
+						NETIF_F_IPV6_CSUM |
 						NETIF_F_SG |
 						NETIF_F_TSO |
 						NETIF_F_TSO6 |
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/Kconfig linux-libre-2.6.38-gnu1/drivers/net/Kconfig
--- linux-libre-2.6.37-gnu1/drivers/net/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -1533,7 +1533,7 @@ config E100
 
 	  <http://support.intel.com/support/network/adapter/pro100/21397.htm>
 
-          to identify the adapter.
+	  to identify the adapter.
 
 	  For the latest Intel PRO/100 network driver for Linux, see:
 
@@ -1786,17 +1786,17 @@ config KS8842
 	tristate "Micrel KSZ8841/42 with generic bus interface"
 	depends on HAS_IOMEM && DMA_ENGINE
 	help
-	 This platform driver is for KSZ8841(1-port) / KS8842(2-port)
-	 ethernet switch chip (managed, VLAN, QoS) from Micrel or
-	 Timberdale(FPGA).
+	  This platform driver is for KSZ8841(1-port) / KS8842(2-port)
+	  ethernet switch chip (managed, VLAN, QoS) from Micrel or
+	  Timberdale(FPGA).
 
 config KS8851
-       tristate "Micrel KS8851 SPI"
-       depends on SPI
-       select MII
+	tristate "Micrel KS8851 SPI"
+	depends on SPI
+	select MII
 	select CRC32
-       help
-         SPI driver for Micrel KS8851 SPI attached network chip.
+	help
+	  SPI driver for Micrel KS8851 SPI attached network chip.
 
 config KS8851_MLL
 	tristate "Micrel KS8851 MLL"
@@ -1944,19 +1944,12 @@ config 68360_ENET
 config FEC
 	bool "FEC ethernet controller (of ColdFire and some i.MX CPUs)"
 	depends on M523x || M527x || M5272 || M528x || M520x || M532x || \
-		MACH_MX27 || ARCH_MX35 || ARCH_MX25 || ARCH_MX5
+		MACH_MX27 || ARCH_MX35 || ARCH_MX25 || ARCH_MX5 || SOC_IMX28
 	select PHYLIB
 	help
 	  Say Y here if you want to use the built-in 10/100 Fast ethernet
 	  controller on some Motorola ColdFire and Freescale i.MX processors.
 
-config FEC2
-	bool "Second FEC ethernet controller (on some ColdFire CPUs)"
-	depends on FEC
-	help
-	  Say Y here if you want to use the second built-in 10/100 Fast
-	  ethernet controller on some Motorola ColdFire processors.
-
 config FEC_MPC52xx
 	tristate "MPC52xx FEC driver"
 	depends on PPC_MPC52xx && PPC_BESTCOMM
@@ -2133,25 +2126,25 @@ config IP1000
 	  will be called ipg.  This is recommended.
 
 config IGB
-       tristate "Intel(R) 82575/82576 PCI-Express Gigabit Ethernet support"
-       depends on PCI
-       ---help---
-         This driver supports Intel(R) 82575/82576 gigabit ethernet family of
-         adapters.  For more information on how to identify your adapter, go
-         to the Adapter & Driver ID Guide at:
+	tristate "Intel(R) 82575/82576 PCI-Express Gigabit Ethernet support"
+	depends on PCI
+	---help---
+	  This driver supports Intel(R) 82575/82576 gigabit ethernet family of
+	  adapters.  For more information on how to identify your adapter, go
+	  to the Adapter & Driver ID Guide at:
 
-         <http://support.intel.com/support/network/adapter/pro100/21397.htm>
+	  <http://support.intel.com/support/network/adapter/pro100/21397.htm>
 
-         For general information and support, go to the Intel support
-         website at:
+	  For general information and support, go to the Intel support
+	  website at:
 
-         <http://support.intel.com>
+	  <http://support.intel.com>
 
-         More specific information on configuring the driver is in
-         <file:Documentation/networking/e1000.txt>.
+	  More specific information on configuring the driver is in
+	  <file:Documentation/networking/e1000.txt>.
 
-         To compile this driver as a module, choose M here. The module
-         will be called igb.
+	  To compile this driver as a module, choose M here. The module
+	  will be called igb.
 
 config IGB_DCA
 	bool "Direct Cache Access (DCA) Support"
@@ -2163,25 +2156,25 @@ config IGB_DCA
 	  is used, with the intent of lessening the impact of cache misses.
 
 config IGBVF
-       tristate "Intel(R) 82576 Virtual Function Ethernet support"
-       depends on PCI
-       ---help---
-         This driver supports Intel(R) 82576 virtual functions.  For more
-         information on how to identify your adapter, go to the Adapter &
-         Driver ID Guide at:
+	tristate "Intel(R) 82576 Virtual Function Ethernet support"
+	depends on PCI
+	---help---
+	  This driver supports Intel(R) 82576 virtual functions.  For more
+	  information on how to identify your adapter, go to the Adapter &
+	  Driver ID Guide at:
 
-         <http://support.intel.com/support/network/adapter/pro100/21397.htm>
+	  <http://support.intel.com/support/network/adapter/pro100/21397.htm>
 
-         For general information and support, go to the Intel support
-         website at:
+	  For general information and support, go to the Intel support
+	  website at:
 
-         <http://support.intel.com>
+	  <http://support.intel.com>
 
-         More specific information on configuring the driver is in
-         <file:Documentation/networking/e1000.txt>.
+	  More specific information on configuring the driver is in
+	  <file:Documentation/networking/e1000.txt>.
 
-         To compile this driver as a module, choose M here. The module
-         will be called igbvf.
+	  To compile this driver as a module, choose M here. The module
+	  will be called igbvf.
 
 source "drivers/net/ixp2000/Kconfig"
 
@@ -2233,6 +2226,7 @@ config YELLOWFIN
 config R8169
 	tristate "Realtek 8169 gigabit ethernet support"
 	depends on PCI
+	select FW_LOADER
 	select CRC32
 	select MII
 	---help---
@@ -2300,14 +2294,14 @@ config SKGE
 	  will be called skge.  This is recommended.
 
 config SKGE_DEBUG
-       bool "Debugging interface"
-       depends on SKGE && DEBUG_FS
-       help
-	 This option adds the ability to dump driver state for debugging.
-	 The file /sys/kernel/debug/skge/ethX displays the state of the internal
-	 transmit and receive rings.
+	bool "Debugging interface"
+	depends on SKGE && DEBUG_FS
+	help
+	  This option adds the ability to dump driver state for debugging.
+	  The file /sys/kernel/debug/skge/ethX displays the state of the internal
+	  transmit and receive rings.
 
-	 If unsure, say N.
+	  If unsure, say N.
 
 config SKY2
 	tristate "SysKonnect Yukon2 support"
@@ -2326,14 +2320,14 @@ config SKY2
 	  will be called sky2.  This is recommended.
 
 config SKY2_DEBUG
-       bool "Debugging interface"
-       depends on SKY2 && DEBUG_FS
-       help
-	 This option adds the ability to dump driver state for debugging.
-	 The file /sys/kernel/debug/sky2/ethX displays the state of the internal
-	 transmit and receive rings.
+	bool "Debugging interface"
+	depends on SKY2 && DEBUG_FS
+	help
+	  This option adds the ability to dump driver state for debugging.
+	  The file /sys/kernel/debug/sky2/ethX displays the state of the internal
+	  transmit and receive rings.
 
-	 If unsure, say N.
+	  If unsure, say N.
 
 config VIA_VELOCITY
 	tristate "VIA Velocity support"
@@ -2389,12 +2383,12 @@ config SPIDER_NET
 	  Cell Processor-Based Blades from IBM.
 
 config TSI108_ETH
-	   tristate "Tundra TSI108 gigabit Ethernet support"
-	   depends on TSI108_BRIDGE
-	   help
-	     This driver supports Tundra TSI108 gigabit Ethernet ports.
-	     To compile this driver as a module, choose M here: the module
-	     will be called tsi108_eth.
+	tristate "Tundra TSI108 gigabit Ethernet support"
+	depends on TSI108_BRIDGE
+	help
+	  This driver supports Tundra TSI108 gigabit Ethernet ports.
+	  To compile this driver as a module, choose M here: the module
+	  will be called tsi108_eth.
 
 config GELIC_NET
 	tristate "PS3 Gigabit Ethernet driver"
@@ -2573,32 +2567,32 @@ config MDIO
 	tristate
 
 config CHELSIO_T1
-        tristate "Chelsio 10Gb Ethernet support"
-        depends on PCI
+	tristate "Chelsio 10Gb Ethernet support"
+	depends on PCI
 	select CRC32
 	select MDIO
-        help
-          This driver supports Chelsio gigabit and 10-gigabit
-          Ethernet cards. More information about adapter features and
+	help
+	  This driver supports Chelsio gigabit and 10-gigabit
+	  Ethernet cards. More information about adapter features and
 	  performance tuning is in <file:Documentation/networking/cxgb.txt>.
 
-          For general information about Chelsio and our products, visit
-          our website at <http://www.chelsio.com>.
+	  For general information about Chelsio and our products, visit
+	  our website at <http://www.chelsio.com>.
 
-          For customer support, please visit our customer support page at
-          <http://www.chelsio.com/support.html>.
+	  For customer support, please visit our customer support page at
+	  <http://www.chelsio.com/support.html>.
 
-          Please send feedback to <linux-bugs@chelsio.com>.
+	  Please send feedback to <linux-bugs@chelsio.com>.
 
-          To compile this driver as a module, choose M here: the module
-          will be called cxgb.
+	  To compile this driver as a module, choose M here: the module
+	  will be called cxgb.
 
 config CHELSIO_T1_1G
-        bool "Chelsio gigabit Ethernet support"
-        depends on CHELSIO_T1
-        help
-          Enables support for Chelsio's gigabit Ethernet PCI cards.  If you
-          are using only 10G cards say 'N' here.
+	bool "Chelsio gigabit Ethernet support"
+	depends on CHELSIO_T1
+	help
+	  Enables support for Chelsio's gigabit Ethernet PCI cards.  If you
+	  are using only 10G cards say 'N' here.
 
 config CHELSIO_T3_DEPENDS
 	tristate
@@ -2728,26 +2722,26 @@ config IXGBE_DCB
 	  If unsure, say N.
 
 config IXGBEVF
-       tristate "Intel(R) 82599 Virtual Function Ethernet support"
-       depends on PCI_MSI
-       ---help---
-         This driver supports Intel(R) 82599 virtual functions.  For more
-         information on how to identify your adapter, go to the Adapter &
-         Driver ID Guide at:
+	tristate "Intel(R) 82599 Virtual Function Ethernet support"
+	depends on PCI_MSI
+	---help---
+	  This driver supports Intel(R) 82599 virtual functions.  For more
+	  information on how to identify your adapter, go to the Adapter &
+	  Driver ID Guide at:
 
-         <http://support.intel.com/support/network/sb/CS-008441.htm>
+	  <http://support.intel.com/support/network/sb/CS-008441.htm>
 
-         For general information and support, go to the Intel support
-         website at:
+	  For general information and support, go to the Intel support
+	  website at:
 
-         <http://support.intel.com>
+	  <http://support.intel.com>
 
-         More specific information on configuring the driver is in
-         <file:Documentation/networking/ixgbevf.txt>.
+	  More specific information on configuring the driver is in
+	  <file:Documentation/networking/ixgbevf.txt>.
 
-         To compile this driver as a module, choose M here. The module
-         will be called ixgbevf.  MSI-X interrupt support is required
-         for this driver to work correctly.
+	  To compile this driver as a module, choose M here. The module
+	  will be called ixgbevf.  MSI-X interrupt support is required
+	  for this driver to work correctly.
 
 config IXGB
 	tristate "Intel(R) PRO/10GbE support"
@@ -2772,29 +2766,38 @@ config IXGB
 	  will be called ixgb.
 
 config S2IO
-	tristate "S2IO 10Gbe XFrame NIC"
+	tristate "Exar Xframe 10Gb Ethernet Adapter"
 	depends on PCI
 	---help---
-	  This driver supports the 10Gbe XFrame NIC of S2IO. 
+	  This driver supports Exar Corp's Xframe Series 10Gb Ethernet Adapters.
+
 	  More specific information on configuring the driver is in 
 	  <file:Documentation/networking/s2io.txt>.
 
+	  To compile this driver as a module, choose M here. The module
+	  will be called s2io.
+
 config VXGE
-	tristate "Neterion X3100 Series 10GbE PCIe Server Adapter"
+	tristate "Exar X3100 Series 10GbE PCIe Server Adapter"
 	depends on PCI && INET
 	---help---
-	  This driver supports Neterion Inc's X3100 Series 10 GbE PCIe
+	  This driver supports Exar Corp's X3100 Series 10 GbE PCIe
 	  I/O Virtualized Server Adapter.
+
 	  More specific information on configuring the driver is in
 	  <file:Documentation/networking/vxge.txt>.
 
+	  To compile this driver as a module, choose M here. The module
+	  will be called vxge.
+
 config VXGE_DEBUG_TRACE_ALL
 	bool "Enabling All Debug trace statments in driver"
 	default n
 	depends on VXGE
 	---help---
 	  Say Y here if you want to enabling all the debug trace statements in
-	  driver. By  default only few debug trace statements are enabled.
+	  the vxge driver. By default only few debug trace statements are
+	  enabled.
 
 config MYRI10GE
 	tristate "Myricom Myri-10G Ethernet support"
@@ -2861,7 +2864,7 @@ config MLX4_CORE
 	default n
 
 config MLX4_DEBUG
-	bool "Verbose debugging output" if (MLX4_CORE && EMBEDDED)
+	bool "Verbose debugging output" if (MLX4_CORE && EXPERT)
 	depends on MLX4_CORE
 	default y
 	---help---
@@ -2906,18 +2909,18 @@ config QLGE
 	  will be called qlge.
 
 config BNA
-        tristate "Brocade 1010/1020 10Gb Ethernet Driver support"
-        depends on PCI
-        ---help---
-          This driver supports Brocade 1010/1020 10Gb CEE capable Ethernet
-          cards.
-          To compile this driver as a module, choose M here: the module
-          will be called bna.
+	tristate "Brocade 1010/1020 10Gb Ethernet Driver support"
+	depends on PCI
+	---help---
+	  This driver supports Brocade 1010/1020 10Gb CEE capable Ethernet
+	  cards.
+	  To compile this driver as a module, choose M here: the module
+	  will be called bna.
 
-          For general information and support, go to the Brocade support
-          website at:
+	  For general information and support, go to the Brocade support
+	  website at:
 
-          <http://support.brocade.com>
+	  <http://support.brocade.com>
 
 source "drivers/net/sfc/Kconfig"
 
@@ -2960,6 +2963,7 @@ config TILE_NET
 config XEN_NETDEV_FRONTEND
 	tristate "Xen network device frontend driver"
 	depends on XEN
+	select XEN_XENBUS_FRONTEND
 	default y
 	help
 	  The network device frontend driver allows the kernel to
@@ -3239,18 +3243,18 @@ config PPP_BSDCOMP
 	  modules once you have said "make modules". If unsure, say N.
 
 config PPP_MPPE
-       tristate "PPP MPPE compression (encryption) (EXPERIMENTAL)"
-       depends on PPP && EXPERIMENTAL
-       select CRYPTO
-       select CRYPTO_SHA1
-       select CRYPTO_ARC4
-       select CRYPTO_ECB
-       ---help---
-         Support for the MPPE Encryption protocol, as employed by the
-	 Microsoft Point-to-Point Tunneling Protocol.
+	tristate "PPP MPPE compression (encryption) (EXPERIMENTAL)"
+	depends on PPP && EXPERIMENTAL
+	select CRYPTO
+	select CRYPTO_SHA1
+	select CRYPTO_ARC4
+	select CRYPTO_ECB
+	---help---
+	  Support for the MPPE Encryption protocol, as employed by the
+	  Microsoft Point-to-Point Tunneling Protocol.
 
-	 See http://pptpclient.sourceforge.net/ for information on
-	 configuring PPTP clients and servers to utilize this method.
+	  See http://pptpclient.sourceforge.net/ for information on
+	  configuring PPTP clients and servers to utilize this method.
 
 config PPPOE
 	tristate "PPP over Ethernet (EXPERIMENTAL)"
@@ -3385,8 +3389,7 @@ config NETCONSOLE
 
 config NETCONSOLE_DYNAMIC
 	bool "Dynamic reconfiguration of logging targets"
-	depends on NETCONSOLE && SYSFS
-	select CONFIGFS_FS
+	depends on NETCONSOLE && SYSFS && CONFIGFS_FS
 	help
 	  This option enables the ability to dynamically reconfigure target
 	  parameters (interface, IP addresses, port numbers, MAC addresses)
@@ -3409,14 +3412,14 @@ config VIRTIO_NET
 	depends on EXPERIMENTAL && VIRTIO
 	---help---
 	  This is the virtual network driver for virtio.  It can be used with
-          lguest or QEMU based VMMs (like KVM or Xen).  Say Y or M.
+	  lguest or QEMU based VMMs (like KVM or Xen).  Say Y or M.
 
 config VMXNET3
-       tristate "VMware VMXNET3 ethernet driver"
-       depends on PCI && INET
-       help
-         This driver supports VMware's vmxnet3 virtual ethernet NIC.
-         To compile this driver as a module, choose M here: the
-         module will be called vmxnet3.
+	tristate "VMware VMXNET3 ethernet driver"
+	depends on PCI && INET
+	help
+	  This driver supports VMware's vmxnet3 virtual ethernet NIC.
+	  To compile this driver as a module, choose M here: the
+	  module will be called vmxnet3.
 
 endif # NETDEVICES
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/ks8851.c linux-libre-2.6.38-gnu1/drivers/net/ks8851.c
--- linux-libre-2.6.37-gnu1/drivers/net/ks8851.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/ks8851.c	2011-03-14 21:20:32.000000000 -0400
@@ -1545,6 +1545,37 @@ static int ks8851_read_selftest(struct k
 
 /* driver bus management functions */
 
+#ifdef CONFIG_PM
+static int ks8851_suspend(struct spi_device *spi, pm_message_t state)
+{
+	struct ks8851_net *ks = dev_get_drvdata(&spi->dev);
+	struct net_device *dev = ks->netdev;
+
+	if (netif_running(dev)) {
+		netif_device_detach(dev);
+		ks8851_net_stop(dev);
+	}
+
+	return 0;
+}
+
+static int ks8851_resume(struct spi_device *spi)
+{
+	struct ks8851_net *ks = dev_get_drvdata(&spi->dev);
+	struct net_device *dev = ks->netdev;
+
+	if (netif_running(dev)) {
+		ks8851_net_open(dev);
+		netif_device_attach(dev);
+	}
+
+	return 0;
+}
+#else
+#define ks8851_suspend NULL
+#define ks8851_resume NULL
+#endif
+
 static int __devinit ks8851_probe(struct spi_device *spi)
 {
 	struct net_device *ndev;
@@ -1679,6 +1710,8 @@ static struct spi_driver ks8851_driver =
 	},
 	.probe = ks8851_probe,
 	.remove = __devexit_p(ks8851_remove),
+	.suspend = ks8851_suspend,
+	.resume = ks8851_resume,
 };
 
 static int __init ks8851_init(void)
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/ksz884x.c linux-libre-2.6.38-gnu1/drivers/net/ksz884x.c
--- linux-libre-2.6.37-gnu1/drivers/net/ksz884x.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/ksz884x.c	2011-03-14 21:20:32.000000000 -0400
@@ -3570,7 +3570,7 @@ static void hw_cfg_wol(struct ksz_hw *hw
  * This routine is used to program Wake-on-LAN pattern.
  */
 static void hw_set_wol_frame(struct ksz_hw *hw, int i, uint mask_size,
-	u8 *mask, uint frame_size, u8 *pattern)
+	const u8 *mask, uint frame_size, const u8 *pattern)
 {
 	int bits;
 	int from;
@@ -3626,9 +3626,9 @@ static void hw_set_wol_frame(struct ksz_
  *
  * This routine is used to add ARP pattern for waking up the host.
  */
-static void hw_add_wol_arp(struct ksz_hw *hw, u8 *ip_addr)
+static void hw_add_wol_arp(struct ksz_hw *hw, const u8 *ip_addr)
 {
-	u8 mask[6] = { 0x3F, 0xF0, 0x3F, 0x00, 0xC0, 0x03 };
+	static const u8 mask[6] = { 0x3F, 0xF0, 0x3F, 0x00, 0xC0, 0x03 };
 	u8 pattern[42] = {
 		0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -3651,8 +3651,8 @@ static void hw_add_wol_arp(struct ksz_hw
  */
 static void hw_add_wol_bcast(struct ksz_hw *hw)
 {
-	u8 mask[] = { 0x3F };
-	u8 pattern[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
+	static const u8 mask[] = { 0x3F };
+	static const u8 pattern[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
 
 	hw_set_wol_frame(hw, 2, 1, mask, MAC_ADDR_LEN, pattern);
 }
@@ -3669,7 +3669,7 @@ static void hw_add_wol_bcast(struct ksz_
  */
 static void hw_add_wol_mcast(struct ksz_hw *hw)
 {
-	u8 mask[] = { 0x3F };
+	static const u8 mask[] = { 0x3F };
 	u8 pattern[] = { 0x33, 0x33, 0xFF, 0x00, 0x00, 0x00 };
 
 	memcpy(&pattern[3], &hw->override_addr[3], 3);
@@ -3687,7 +3687,7 @@ static void hw_add_wol_mcast(struct ksz_
  */
 static void hw_add_wol_ucast(struct ksz_hw *hw)
 {
-	u8 mask[] = { 0x3F };
+	static const u8 mask[] = { 0x3F };
 
 	hw_set_wol_frame(hw, 0, 1, mask, MAC_ADDR_LEN, hw->override_addr);
 }
@@ -3700,7 +3700,7 @@ static void hw_add_wol_ucast(struct ksz_
  *
  * This routine is used to enable Wake-on-LAN depending on driver settings.
  */
-static void hw_enable_wol(struct ksz_hw *hw, u32 wol_enable, u8 *net_addr)
+static void hw_enable_wol(struct ksz_hw *hw, u32 wol_enable, const u8 *net_addr)
 {
 	hw_cfg_wol(hw, KS8841_WOL_MAGIC_ENABLE, (wol_enable & WAKE_MAGIC));
 	hw_cfg_wol(hw, KS8841_WOL_FRAME0_ENABLE, (wol_enable & WAKE_UCAST));
@@ -6208,7 +6208,7 @@ static int netdev_set_wol(struct net_dev
 	struct dev_info *hw_priv = priv->adapter;
 
 	/* Need to find a way to retrieve the device IP address. */
-	u8 net_addr[] = { 192, 168, 1, 1 };
+	static const u8 net_addr[] = { 192, 168, 1, 1 };
 
 	if (wol->wolopts & ~hw_priv->wol_support)
 		return -EINVAL;
@@ -6953,7 +6953,7 @@ static void read_other_addr(struct ksz_h
 #define PCI_VENDOR_ID_MICREL_KS		0x16c6
 #endif
 
-static int __init pcidev_init(struct pci_dev *pdev,
+static int __devinit pcidev_init(struct pci_dev *pdev,
 	const struct pci_device_id *id)
 {
 	struct net_device *dev;
@@ -7241,7 +7241,7 @@ static int pcidev_suspend(struct pci_dev
 	struct ksz_hw *hw = &hw_priv->hw;
 
 	/* Need to find a way to retrieve the device IP address. */
-	u8 net_addr[] = { 192, 168, 1, 1 };
+	static const u8 net_addr[] = { 192, 168, 1, 1 };
 
 	for (i = 0; i < hw->dev_count; i++) {
 		if (info->netdev[i]) {
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/lance.c linux-libre-2.6.38-gnu1/drivers/net/lance.c
--- linux-libre-2.6.37-gnu1/drivers/net/lance.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/lance.c	2011-03-14 21:20:32.000000000 -0400
@@ -207,7 +207,7 @@ tx_full and tbusy flags.
 #define LANCE_BUS_IF 0x16
 #define LANCE_TOTAL_SIZE 0x18
 
-#define TX_TIMEOUT	20
+#define TX_TIMEOUT	(HZ/5)
 
 /* The LANCE Rx and Tx ring descriptors. */
 struct lance_rx_head {
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/lib82596.c linux-libre-2.6.38-gnu1/drivers/net/lib82596.c
--- linux-libre-2.6.37-gnu1/drivers/net/lib82596.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/lib82596.c	2011-03-14 21:20:32.000000000 -0400
@@ -161,7 +161,7 @@ enum commands {
 #define	 RX_SUSPEND	0x0030
 #define	 RX_ABORT	0x0040
 
-#define TX_TIMEOUT	5
+#define TX_TIMEOUT	(HZ/20)
 
 
 struct i596_reg {
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/lib8390.c linux-libre-2.6.38-gnu1/drivers/net/lib8390.c
--- linux-libre-2.6.37-gnu1/drivers/net/lib8390.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/lib8390.c	2011-03-14 21:20:32.000000000 -0400
@@ -203,7 +203,7 @@ static void __NS8390_init(struct net_dev
 static int __ei_open(struct net_device *dev)
 {
 	unsigned long flags;
-	struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev);
+	struct ei_device *ei_local = netdev_priv(dev);
 
 	if (dev->watchdog_timeo <= 0)
 		 dev->watchdog_timeo = TX_TIMEOUT;
@@ -231,7 +231,7 @@ static int __ei_open(struct net_device *
  */
 static int __ei_close(struct net_device *dev)
 {
-	struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev);
+	struct ei_device *ei_local = netdev_priv(dev);
 	unsigned long flags;
 
 	/*
@@ -256,7 +256,7 @@ static int __ei_close(struct net_device
 static void __ei_tx_timeout(struct net_device *dev)
 {
 	unsigned long e8390_base = dev->base_addr;
-	struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev);
+	struct ei_device *ei_local = netdev_priv(dev);
 	int txsr, isr, tickssofar = jiffies - dev_trans_start(dev);
 	unsigned long flags;
 
@@ -303,7 +303,7 @@ static netdev_tx_t __ei_start_xmit(struc
 				   struct net_device *dev)
 {
 	unsigned long e8390_base = dev->base_addr;
-	struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev);
+	struct ei_device *ei_local = netdev_priv(dev);
 	int send_length = skb->len, output_page;
 	unsigned long flags;
 	char buf[ETH_ZLEN];
@@ -592,7 +592,7 @@ static void ei_tx_err(struct net_device
 static void ei_tx_intr(struct net_device *dev)
 {
 	unsigned long e8390_base = dev->base_addr;
-	struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev);
+	struct ei_device *ei_local = netdev_priv(dev);
 	int status = ei_inb(e8390_base + EN0_TSR);
 
 	ei_outb_p(ENISR_TX, e8390_base + EN0_ISR); /* Ack intr. */
@@ -675,7 +675,7 @@ static void ei_tx_intr(struct net_device
 static void ei_receive(struct net_device *dev)
 {
 	unsigned long e8390_base = dev->base_addr;
-	struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev);
+	struct ei_device *ei_local = netdev_priv(dev);
 	unsigned char rxing_page, this_frame, next_frame;
 	unsigned short current_offset;
 	int rx_pkt_count = 0;
@@ -879,7 +879,7 @@ static void ei_rx_overrun(struct net_dev
 static struct net_device_stats *__ei_get_stats(struct net_device *dev)
 {
 	unsigned long ioaddr = dev->base_addr;
-	struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev);
+	struct ei_device *ei_local = netdev_priv(dev);
 	unsigned long flags;
 
 	/* If the card is stopped, just return the present stats. */
@@ -927,7 +927,7 @@ static void do_set_multicast_list(struct
 {
 	unsigned long e8390_base = dev->base_addr;
 	int i;
-	struct ei_device *ei_local = (struct ei_device*)netdev_priv(dev);
+	struct ei_device *ei_local = netdev_priv(dev);
 
 	if (!(dev->flags&(IFF_PROMISC|IFF_ALLMULTI)))
 	{
@@ -981,7 +981,7 @@ static void do_set_multicast_list(struct
 static void __ei_set_multicast_list(struct net_device *dev)
 {
 	unsigned long flags;
-	struct ei_device *ei_local = (struct ei_device*)netdev_priv(dev);
+	struct ei_device *ei_local = netdev_priv(dev);
 
 	spin_lock_irqsave(&ei_local->page_lock, flags);
 	do_set_multicast_list(dev);
@@ -998,7 +998,7 @@ static void __ei_set_multicast_list(stru
 
 static void ethdev_setup(struct net_device *dev)
 {
-	struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev);
+	struct ei_device *ei_local = netdev_priv(dev);
 	if (ei_debug > 1)
 		printk(version);
 
@@ -1036,7 +1036,7 @@ static struct net_device *____alloc_ei_n
 static void __NS8390_init(struct net_device *dev, int startp)
 {
 	unsigned long e8390_base = dev->base_addr;
-	struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev);
+	struct ei_device *ei_local = netdev_priv(dev);
 	int i;
 	int endcfg = ei_local->word16
 	    ? (0x48 | ENDCFG_WTS | (ei_local->bigendian ? ENDCFG_BOS : 0))
@@ -1099,7 +1099,7 @@ static void NS8390_trigger_send(struct n
 								int start_page)
 {
 	unsigned long e8390_base = dev->base_addr;
- 	struct ei_device *ei_local __attribute((unused)) = (struct ei_device *) netdev_priv(dev);
+ 	struct ei_device *ei_local __attribute((unused)) = netdev_priv(dev);
 
 	ei_outb_p(E8390_NODMA+E8390_PAGE0, e8390_base+E8390_CMD);
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/ll_temac_main.c linux-libre-2.6.38-gnu1/drivers/net/ll_temac_main.c
--- linux-libre-2.6.37-gnu1/drivers/net/ll_temac_main.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/ll_temac_main.c	2011-03-14 21:20:32.000000000 -0400
@@ -238,7 +238,7 @@ static int temac_dma_bd_init(struct net_
 		goto out;
 	}
 	/* allocate the tx and rx ring buffer descriptors. */
-	/* returns a virtual addres and a physical address. */
+	/* returns a virtual address and a physical address. */
 	lp->tx_bd_v = dma_alloc_coherent(ndev->dev.parent,
 					 sizeof(*lp->tx_bd_v) * TX_BD_NUM,
 					 &lp->tx_bd_p, GFP_KERNEL);
@@ -692,7 +692,7 @@ static int temac_start_xmit(struct sk_bu
 
 	cur_p->app0 = 0;
 	if (skb->ip_summed == CHECKSUM_PARTIAL) {
-		unsigned int csum_start_off = skb_transport_offset(skb);
+		unsigned int csum_start_off = skb_checksum_start_offset(skb);
 		unsigned int csum_index_off = csum_start_off + skb->csum_offset;
 
 		cur_p->app0 |= 1; /* TX Checksum Enabled */
@@ -952,7 +952,7 @@ static const struct attribute_group tema
 	.attrs = temac_device_attrs,
 };
 
-static int __init
+static int __devinit
 temac_of_probe(struct platform_device *op, const struct of_device_id *match)
 {
 	struct device_node *np;
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/macb.c linux-libre-2.6.38-gnu1/drivers/net/macb.c
--- linux-libre-2.6.37-gnu1/drivers/net/macb.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/macb.c	2011-03-14 21:20:32.000000000 -0400
@@ -260,7 +260,7 @@ static int macb_mii_init(struct macb *bp
 	for (i = 0; i < PHY_MAX_ADDR; i++)
 		bp->mii_bus->irq[i] = PHY_POLL;
 
-	platform_set_drvdata(bp->dev, bp->mii_bus);
+	dev_set_drvdata(&bp->dev->dev, bp->mii_bus);
 
 	if (mdiobus_register(bp->mii_bus))
 		goto err_out_free_mdio_irq;
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/macvlan.c linux-libre-2.6.38-gnu1/drivers/net/macvlan.c
--- linux-libre-2.6.37-gnu1/drivers/net/macvlan.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/macvlan.c	2011-03-14 21:20:32.000000000 -0400
@@ -38,6 +38,7 @@ struct macvlan_port {
 	struct hlist_head	vlan_hash[MACVLAN_HASH_SIZE];
 	struct list_head	vlans;
 	struct rcu_head		rcu;
+	bool 			passthru;
 };
 
 #define macvlan_port_get_rcu(dev) \
@@ -169,6 +170,7 @@ static struct sk_buff *macvlan_handle_fr
 			macvlan_broadcast(skb, port, NULL,
 					  MACVLAN_MODE_PRIVATE |
 					  MACVLAN_MODE_VEPA    |
+					  MACVLAN_MODE_PASSTHRU|
 					  MACVLAN_MODE_BRIDGE);
 		else if (src->mode == MACVLAN_MODE_VEPA)
 			/* flood to everyone except source */
@@ -185,7 +187,10 @@ static struct sk_buff *macvlan_handle_fr
 		return skb;
 	}
 
-	vlan = macvlan_hash_lookup(port, eth->h_dest);
+	if (port->passthru)
+		vlan = list_first_entry(&port->vlans, struct macvlan_dev, list);
+	else
+		vlan = macvlan_hash_lookup(port, eth->h_dest);
 	if (vlan == NULL)
 		return skb;
 
@@ -243,18 +248,22 @@ xmit_world:
 netdev_tx_t macvlan_start_xmit(struct sk_buff *skb,
 			       struct net_device *dev)
 {
-	int i = skb_get_queue_mapping(skb);
-	struct netdev_queue *txq = netdev_get_tx_queue(dev, i);
 	unsigned int len = skb->len;
 	int ret;
+	const struct macvlan_dev *vlan = netdev_priv(dev);
 
 	ret = macvlan_queue_xmit(skb, dev);
 	if (likely(ret == NET_XMIT_SUCCESS || ret == NET_XMIT_CN)) {
-		txq->tx_packets++;
-		txq->tx_bytes += len;
-	} else
-		txq->tx_dropped++;
+		struct macvlan_pcpu_stats *pcpu_stats;
 
+		pcpu_stats = this_cpu_ptr(vlan->pcpu_stats);
+		u64_stats_update_begin(&pcpu_stats->syncp);
+		pcpu_stats->tx_packets++;
+		pcpu_stats->tx_bytes += len;
+		u64_stats_update_end(&pcpu_stats->syncp);
+	} else {
+		this_cpu_inc(vlan->pcpu_stats->tx_dropped);
+	}
 	return ret;
 }
 EXPORT_SYMBOL_GPL(macvlan_start_xmit);
@@ -284,6 +293,11 @@ static int macvlan_open(struct net_devic
 	struct net_device *lowerdev = vlan->lowerdev;
 	int err;
 
+	if (vlan->port->passthru) {
+		dev_set_promiscuity(lowerdev, 1);
+		goto hash_add;
+	}
+
 	err = -EBUSY;
 	if (macvlan_addr_busy(vlan->port, dev->dev_addr))
 		goto out;
@@ -296,6 +310,8 @@ static int macvlan_open(struct net_devic
 		if (err < 0)
 			goto del_unicast;
 	}
+
+hash_add:
 	macvlan_hash_add(vlan);
 	return 0;
 
@@ -310,12 +326,18 @@ static int macvlan_stop(struct net_devic
 	struct macvlan_dev *vlan = netdev_priv(dev);
 	struct net_device *lowerdev = vlan->lowerdev;
 
+	if (vlan->port->passthru) {
+		dev_set_promiscuity(lowerdev, -1);
+		goto hash_del;
+	}
+
 	dev_mc_unsync(lowerdev, dev);
 	if (dev->flags & IFF_ALLMULTI)
 		dev_set_allmulti(lowerdev, -1);
 
 	dev_uc_del(lowerdev, dev->dev_addr);
 
+hash_del:
 	macvlan_hash_del(vlan);
 	return 0;
 }
@@ -414,14 +436,15 @@ static int macvlan_init(struct net_devic
 	dev->state		= (dev->state & ~MACVLAN_STATE_MASK) |
 				  (lowerdev->state & MACVLAN_STATE_MASK);
 	dev->features 		= lowerdev->features & MACVLAN_FEATURES;
+	dev->features		|= NETIF_F_LLTX;
 	dev->gso_max_size	= lowerdev->gso_max_size;
 	dev->iflink		= lowerdev->ifindex;
 	dev->hard_header_len	= lowerdev->hard_header_len;
 
 	macvlan_set_lockdep_class(dev);
 
-	vlan->rx_stats = alloc_percpu(struct macvlan_rx_stats);
-	if (!vlan->rx_stats)
+	vlan->pcpu_stats = alloc_percpu(struct macvlan_pcpu_stats);
+	if (!vlan->pcpu_stats)
 		return -ENOMEM;
 
 	return 0;
@@ -431,7 +454,7 @@ static void macvlan_uninit(struct net_de
 {
 	struct macvlan_dev *vlan = netdev_priv(dev);
 
-	free_percpu(vlan->rx_stats);
+	free_percpu(vlan->pcpu_stats);
 }
 
 static struct rtnl_link_stats64 *macvlan_dev_get_stats64(struct net_device *dev,
@@ -439,33 +462,38 @@ static struct rtnl_link_stats64 *macvlan
 {
 	struct macvlan_dev *vlan = netdev_priv(dev);
 
-	dev_txq_stats_fold(dev, stats);
-
-	if (vlan->rx_stats) {
-		struct macvlan_rx_stats *p, accum = {0};
-		u64 rx_packets, rx_bytes, rx_multicast;
+	if (vlan->pcpu_stats) {
+		struct macvlan_pcpu_stats *p;
+		u64 rx_packets, rx_bytes, rx_multicast, tx_packets, tx_bytes;
+		u32 rx_errors = 0, tx_dropped = 0;
 		unsigned int start;
 		int i;
 
 		for_each_possible_cpu(i) {
-			p = per_cpu_ptr(vlan->rx_stats, i);
+			p = per_cpu_ptr(vlan->pcpu_stats, i);
 			do {
 				start = u64_stats_fetch_begin_bh(&p->syncp);
 				rx_packets	= p->rx_packets;
 				rx_bytes	= p->rx_bytes;
 				rx_multicast	= p->rx_multicast;
+				tx_packets	= p->tx_packets;
+				tx_bytes	= p->tx_bytes;
 			} while (u64_stats_fetch_retry_bh(&p->syncp, start));
-			accum.rx_packets	+= rx_packets;
-			accum.rx_bytes		+= rx_bytes;
-			accum.rx_multicast	+= rx_multicast;
-			/* rx_errors is an ulong, updated without syncp protection */
-			accum.rx_errors		+= p->rx_errors;
+
+			stats->rx_packets	+= rx_packets;
+			stats->rx_bytes		+= rx_bytes;
+			stats->multicast	+= rx_multicast;
+			stats->tx_packets	+= tx_packets;
+			stats->tx_bytes		+= tx_bytes;
+			/* rx_errors & tx_dropped are u32, updated
+			 * without syncp protection.
+			 */
+			rx_errors	+= p->rx_errors;
+			tx_dropped	+= p->tx_dropped;
 		}
-		stats->rx_packets = accum.rx_packets;
-		stats->rx_bytes   = accum.rx_bytes;
-		stats->rx_errors  = accum.rx_errors;
-		stats->rx_dropped = accum.rx_errors;
-		stats->multicast  = accum.rx_multicast;
+		stats->rx_errors	= rx_errors;
+		stats->rx_dropped	= rx_errors;
+		stats->tx_dropped	= tx_dropped;
 	}
 	return stats;
 }
@@ -549,6 +577,7 @@ static int macvlan_port_create(struct ne
 	if (port == NULL)
 		return -ENOMEM;
 
+	port->passthru = false;
 	port->dev = dev;
 	INIT_LIST_HEAD(&port->vlans);
 	for (i = 0; i < MACVLAN_HASH_SIZE; i++)
@@ -593,6 +622,7 @@ static int macvlan_validate(struct nlatt
 		case MACVLAN_MODE_PRIVATE:
 		case MACVLAN_MODE_VEPA:
 		case MACVLAN_MODE_BRIDGE:
+		case MACVLAN_MODE_PASSTHRU:
 			break;
 		default:
 			return -EINVAL;
@@ -601,25 +631,6 @@ static int macvlan_validate(struct nlatt
 	return 0;
 }
 
-static int macvlan_get_tx_queues(struct net *net,
-				 struct nlattr *tb[],
-				 unsigned int *num_tx_queues,
-				 unsigned int *real_num_tx_queues)
-{
-	struct net_device *real_dev;
-
-	if (!tb[IFLA_LINK])
-		return -EINVAL;
-
-	real_dev = __dev_get_by_index(net, nla_get_u32(tb[IFLA_LINK]));
-	if (!real_dev)
-		return -ENODEV;
-
-	*num_tx_queues      = real_dev->num_tx_queues;
-	*real_num_tx_queues = real_dev->real_num_tx_queues;
-	return 0;
-}
-
 int macvlan_common_newlink(struct net *src_net, struct net_device *dev,
 			   struct nlattr *tb[], struct nlattr *data[],
 			   int (*receive)(struct sk_buff *skb),
@@ -661,6 +672,10 @@ int macvlan_common_newlink(struct net *s
 	}
 	port = macvlan_port_get(lowerdev);
 
+	/* Only 1 macvlan device can be created in passthru mode */
+	if (port->passthru)
+		return -EINVAL;
+
 	vlan->lowerdev = lowerdev;
 	vlan->dev      = dev;
 	vlan->port     = port;
@@ -671,6 +686,13 @@ int macvlan_common_newlink(struct net *s
 	if (data && data[IFLA_MACVLAN_MODE])
 		vlan->mode = nla_get_u32(data[IFLA_MACVLAN_MODE]);
 
+	if (vlan->mode == MACVLAN_MODE_PASSTHRU) {
+		if (!list_empty(&port->vlans))
+			return -EINVAL;
+		port->passthru = true;
+		memcpy(dev->dev_addr, lowerdev->dev_addr, ETH_ALEN);
+	}
+
 	err = register_netdevice(dev);
 	if (err < 0)
 		goto destroy_port;
@@ -743,7 +765,6 @@ int macvlan_link_register(struct rtnl_li
 {
 	/* common fields */
 	ops->priv_size		= sizeof(struct macvlan_dev);
-	ops->get_tx_queues	= macvlan_get_tx_queues;
 	ops->validate		= macvlan_validate;
 	ops->maxtype		= IFLA_MACVLAN_MAX;
 	ops->policy		= macvlan_policy;
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/macvtap.c linux-libre-2.6.38-gnu1/drivers/net/macvtap.c
--- linux-libre-2.6.37-gnu1/drivers/net/macvtap.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/macvtap.c	2011-03-14 21:20:32.000000000 -0400
@@ -504,8 +504,7 @@ static int macvtap_skb_to_vnet_hdr(const
 
 	if (skb->ip_summed == CHECKSUM_PARTIAL) {
 		vnet_hdr->flags = VIRTIO_NET_HDR_F_NEEDS_CSUM;
-		vnet_hdr->csum_start = skb->csum_start -
-					skb_headroom(skb);
+		vnet_hdr->csum_start = skb_checksum_start_offset(skb);
 		vnet_hdr->csum_offset = skb->csum_offset;
 	} /* else everything is zero */
 
@@ -529,8 +528,9 @@ static ssize_t macvtap_get_user(struct m
 		vnet_hdr_len = q->vnet_hdr_sz;
 
 		err = -EINVAL;
-		if ((len -= vnet_hdr_len) < 0)
+		if (len < vnet_hdr_len)
 			goto err;
+		len -= vnet_hdr_len;
 
 		err = memcpy_fromiovecend((void *)&vnet_hdr, iv, 0,
 					   sizeof(vnet_hdr));
@@ -586,7 +586,7 @@ err:
 	rcu_read_lock_bh();
 	vlan = rcu_dereference(q->vlan);
 	if (vlan)
-		netdev_get_tx_queue(vlan->dev, 0)->tx_dropped++;
+		vlan->dev->stats.tx_dropped++;
 	rcu_read_unlock_bh();
 
 	return err;
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/mlx4/alloc.c linux-libre-2.6.38-gnu1/drivers/net/mlx4/alloc.c
--- linux-libre-2.6.37-gnu1/drivers/net/mlx4/alloc.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/mlx4/alloc.c	2011-03-14 21:20:32.000000000 -0400
@@ -178,6 +178,7 @@ int mlx4_buf_alloc(struct mlx4_dev *dev,
 	} else {
 		int i;
 
+		buf->direct.buf  = NULL;
 		buf->nbufs       = (size + PAGE_SIZE - 1) / PAGE_SIZE;
 		buf->npages      = buf->nbufs;
 		buf->page_shift  = PAGE_SHIFT;
@@ -229,7 +230,7 @@ void mlx4_buf_free(struct mlx4_dev *dev,
 		dma_free_coherent(&dev->pdev->dev, size, buf->direct.buf,
 				  buf->direct.map);
 	else {
-		if (BITS_PER_LONG == 64)
+		if (BITS_PER_LONG == 64 && buf->direct.buf)
 			vunmap(buf->direct.buf);
 
 		for (i = 0; i < buf->nbufs; ++i)
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/mlx4/catas.c linux-libre-2.6.38-gnu1/drivers/net/mlx4/catas.c
--- linux-libre-2.6.37-gnu1/drivers/net/mlx4/catas.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/mlx4/catas.c	2011-03-14 21:20:32.000000000 -0400
@@ -113,7 +113,7 @@ static void catas_reset(struct work_stru
 void mlx4_start_catas_poll(struct mlx4_dev *dev)
 {
 	struct mlx4_priv *priv = mlx4_priv(dev);
-	unsigned long addr;
+	phys_addr_t addr;
 
 	INIT_LIST_HEAD(&priv->catas_err.list);
 	init_timer(&priv->catas_err.timer);
@@ -124,8 +124,8 @@ void mlx4_start_catas_poll(struct mlx4_d
 
 	priv->catas_err.map = ioremap(addr, priv->fw.catas_size * 4);
 	if (!priv->catas_err.map) {
-		mlx4_warn(dev, "Failed to map internal error buffer at 0x%lx\n",
-			  addr);
+		mlx4_warn(dev, "Failed to map internal error buffer at 0x%llx\n",
+			  (unsigned long long) addr);
 		return;
 	}
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/mlx4/en_main.c linux-libre-2.6.38-gnu1/drivers/net/mlx4/en_main.c
--- linux-libre-2.6.37-gnu1/drivers/net/mlx4/en_main.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/mlx4/en_main.c	2011-03-14 21:20:32.000000000 -0400
@@ -202,7 +202,8 @@ static void *mlx4_en_add(struct mlx4_dev
 	if (mlx4_uar_alloc(dev, &mdev->priv_uar))
 		goto err_pd;
 
-	mdev->uar_map = ioremap(mdev->priv_uar.pfn << PAGE_SHIFT, PAGE_SIZE);
+	mdev->uar_map = ioremap((phys_addr_t) mdev->priv_uar.pfn << PAGE_SHIFT,
+				PAGE_SIZE);
 	if (!mdev->uar_map)
 		goto err_uar;
 	spin_lock_init(&mdev->uar_lock);
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/mlx4/en_netdev.c linux-libre-2.6.38-gnu1/drivers/net/mlx4/en_netdev.c
--- linux-libre-2.6.37-gnu1/drivers/net/mlx4/en_netdev.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/mlx4/en_netdev.c	2011-03-14 21:20:32.000000000 -0400
@@ -972,7 +972,8 @@ int mlx4_en_init_netdev(struct mlx4_en_d
 	int i;
 	int err;
 
-	dev = alloc_etherdev_mq(sizeof(struct mlx4_en_priv), prof->tx_ring_num);
+	dev = alloc_etherdev_mqs(sizeof(struct mlx4_en_priv),
+	    prof->tx_ring_num, prof->rx_ring_num);
 	if (dev == NULL) {
 		mlx4_err(mdev, "Net device allocation failed\n");
 		return -ENOMEM;
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/mlx4/fw.c linux-libre-2.6.38-gnu1/drivers/net/mlx4/fw.c
--- linux-libre-2.6.37-gnu1/drivers/net/mlx4/fw.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/mlx4/fw.c	2011-03-14 21:20:32.000000000 -0400
@@ -289,10 +289,8 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *
 		MLX4_GET(field, outbox, QUERY_DEV_CAP_LOG_BF_REG_SZ_OFFSET);
 		dev_cap->bf_reg_size = 1 << (field & 0x1f);
 		MLX4_GET(field, outbox, QUERY_DEV_CAP_LOG_MAX_BF_REGS_PER_PAGE_OFFSET);
-		if ((1 << (field & 0x3f)) > (PAGE_SIZE / dev_cap->bf_reg_size)) {
-			mlx4_warn(dev, "firmware bug: log2 # of blue flame regs is invalid (%d), forcing 3\n", field & 0x1f);
+		if ((1 << (field & 0x3f)) > (PAGE_SIZE / dev_cap->bf_reg_size))
 			field = 3;
-		}
 		dev_cap->bf_regs_per_page = 1 << (field & 0x3f);
 		mlx4_dbg(dev, "BlueFlame available (reg size %d, regs/page %d)\n",
 			 dev_cap->bf_reg_size, dev_cap->bf_regs_per_page);
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/mlx4/main.c linux-libre-2.6.38-gnu1/drivers/net/mlx4/main.c
--- linux-libre-2.6.37-gnu1/drivers/net/mlx4/main.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/mlx4/main.c	2011-03-14 21:20:32.000000000 -0400
@@ -829,7 +829,7 @@ static int mlx4_setup_hca(struct mlx4_de
 		goto err_uar_table_free;
 	}
 
-	priv->kar = ioremap(priv->driver_uar.pfn << PAGE_SHIFT, PAGE_SIZE);
+	priv->kar = ioremap((phys_addr_t) priv->driver_uar.pfn << PAGE_SHIFT, PAGE_SIZE);
 	if (!priv->kar) {
 		mlx4_err(dev, "Couldn't map kernel access region, "
 			 "aborting.\n");
@@ -1286,6 +1286,21 @@ static DEFINE_PCI_DEVICE_TABLE(mlx4_pci_
 	{ PCI_VDEVICE(MELLANOX, 0x6764) }, /* MT26468 ConnectX EN 10GigE PCIe gen2*/
 	{ PCI_VDEVICE(MELLANOX, 0x6746) }, /* MT26438 ConnectX EN 40GigE PCIe gen2 5GT/s */
 	{ PCI_VDEVICE(MELLANOX, 0x676e) }, /* MT26478 ConnectX2 40GigE PCIe gen2 */
+	{ PCI_VDEVICE(MELLANOX, 0x1002) }, /* MT25400 Family [ConnectX-2 Virtual Function] */
+	{ PCI_VDEVICE(MELLANOX, 0x1003) }, /* MT27500 Family [ConnectX-3] */
+	{ PCI_VDEVICE(MELLANOX, 0x1004) }, /* MT27500 Family [ConnectX-3 Virtual Function] */
+	{ PCI_VDEVICE(MELLANOX, 0x1005) }, /* MT27510 Family */
+	{ PCI_VDEVICE(MELLANOX, 0x1006) }, /* MT27511 Family */
+	{ PCI_VDEVICE(MELLANOX, 0x1007) }, /* MT27520 Family */
+	{ PCI_VDEVICE(MELLANOX, 0x1008) }, /* MT27521 Family */
+	{ PCI_VDEVICE(MELLANOX, 0x1009) }, /* MT27530 Family */
+	{ PCI_VDEVICE(MELLANOX, 0x100a) }, /* MT27531 Family */
+	{ PCI_VDEVICE(MELLANOX, 0x100b) }, /* MT27540 Family */
+	{ PCI_VDEVICE(MELLANOX, 0x100c) }, /* MT27541 Family */
+	{ PCI_VDEVICE(MELLANOX, 0x100d) }, /* MT27550 Family */
+	{ PCI_VDEVICE(MELLANOX, 0x100e) }, /* MT27551 Family */
+	{ PCI_VDEVICE(MELLANOX, 0x100f) }, /* MT27560 Family */
+	{ PCI_VDEVICE(MELLANOX, 0x1010) }, /* MT27561 Family */
 	{ 0, }
 };
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/mlx4/mcg.c linux-libre-2.6.38-gnu1/drivers/net/mlx4/mcg.c
--- linux-libre-2.6.37-gnu1/drivers/net/mlx4/mcg.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/mlx4/mcg.c	2011-03-14 21:20:32.000000000 -0400
@@ -95,7 +95,8 @@ static int mlx4_MGID_HASH(struct mlx4_de
  * entry in hash chain and *mgm holds end of hash chain.
  */
 static int find_mgm(struct mlx4_dev *dev,
-		    u8 *gid, struct mlx4_cmd_mailbox *mgm_mailbox,
+		    u8 *gid, enum mlx4_protocol protocol,
+		    struct mlx4_cmd_mailbox *mgm_mailbox,
 		    u16 *hash, int *prev, int *index)
 {
 	struct mlx4_cmd_mailbox *mailbox;
@@ -134,7 +135,8 @@ static int find_mgm(struct mlx4_dev *dev
 			return err;
 		}
 
-		if (!memcmp(mgm->gid, gid, 16))
+		if (!memcmp(mgm->gid, gid, 16) &&
+		    be32_to_cpu(mgm->members_count) >> 30 == protocol)
 			return err;
 
 		*prev = *index;
@@ -146,7 +148,7 @@ static int find_mgm(struct mlx4_dev *dev
 }
 
 int mlx4_multicast_attach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
-			  int block_mcast_loopback)
+			  int block_mcast_loopback, enum mlx4_protocol protocol)
 {
 	struct mlx4_priv *priv = mlx4_priv(dev);
 	struct mlx4_cmd_mailbox *mailbox;
@@ -165,7 +167,7 @@ int mlx4_multicast_attach(struct mlx4_de
 
 	mutex_lock(&priv->mcg_table.mutex);
 
-	err = find_mgm(dev, gid, mailbox, &hash, &prev, &index);
+	err = find_mgm(dev, gid, protocol, mailbox, &hash, &prev, &index);
 	if (err)
 		goto out;
 
@@ -187,7 +189,7 @@ int mlx4_multicast_attach(struct mlx4_de
 		memcpy(mgm->gid, gid, 16);
 	}
 
-	members_count = be32_to_cpu(mgm->members_count);
+	members_count = be32_to_cpu(mgm->members_count) & 0xffffff;
 	if (members_count == MLX4_QP_PER_MGM) {
 		mlx4_err(dev, "MGM at index %x is full.\n", index);
 		err = -ENOMEM;
@@ -207,7 +209,7 @@ int mlx4_multicast_attach(struct mlx4_de
 	else
 		mgm->qp[members_count++] = cpu_to_be32(qp->qpn & MGM_QPN_MASK);
 
-	mgm->members_count       = cpu_to_be32(members_count);
+	mgm->members_count = cpu_to_be32(members_count | (u32) protocol << 30);
 
 	err = mlx4_WRITE_MCG(dev, index, mailbox);
 	if (err)
@@ -242,7 +244,8 @@ out:
 }
 EXPORT_SYMBOL_GPL(mlx4_multicast_attach);
 
-int mlx4_multicast_detach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16])
+int mlx4_multicast_detach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
+			  enum mlx4_protocol protocol)
 {
 	struct mlx4_priv *priv = mlx4_priv(dev);
 	struct mlx4_cmd_mailbox *mailbox;
@@ -260,7 +263,7 @@ int mlx4_multicast_detach(struct mlx4_de
 
 	mutex_lock(&priv->mcg_table.mutex);
 
-	err = find_mgm(dev, gid, mailbox, &hash, &prev, &index);
+	err = find_mgm(dev, gid, protocol, mailbox, &hash, &prev, &index);
 	if (err)
 		goto out;
 
@@ -270,7 +273,7 @@ int mlx4_multicast_detach(struct mlx4_de
 		goto out;
 	}
 
-	members_count = be32_to_cpu(mgm->members_count);
+	members_count = be32_to_cpu(mgm->members_count) & 0xffffff;
 	for (loc = -1, i = 0; i < members_count; ++i)
 		if ((be32_to_cpu(mgm->qp[i]) & MGM_QPN_MASK) == qp->qpn)
 			loc = i;
@@ -282,7 +285,7 @@ int mlx4_multicast_detach(struct mlx4_de
 	}
 
 
-	mgm->members_count = cpu_to_be32(--members_count);
+	mgm->members_count = cpu_to_be32(--members_count | (u32) protocol << 30);
 	mgm->qp[loc]       = mgm->qp[i - 1];
 	mgm->qp[i - 1]     = 0;
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/mv643xx_eth.c linux-libre-2.6.38-gnu1/drivers/net/mv643xx_eth.c
--- linux-libre-2.6.37-gnu1/drivers/net/mv643xx_eth.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/mv643xx_eth.c	2011-03-14 21:20:32.000000000 -0400
@@ -1514,11 +1514,6 @@ static int mv643xx_eth_nway_reset(struct
 	return genphy_restart_aneg(mp->phy);
 }
 
-static u32 mv643xx_eth_get_link(struct net_device *dev)
-{
-	return !!netif_carrier_ok(dev);
-}
-
 static int
 mv643xx_eth_get_coalesce(struct net_device *dev, struct ethtool_coalesce *ec)
 {
@@ -1658,7 +1653,7 @@ static const struct ethtool_ops mv643xx_
 	.set_settings		= mv643xx_eth_set_settings,
 	.get_drvinfo		= mv643xx_eth_get_drvinfo,
 	.nway_reset		= mv643xx_eth_nway_reset,
-	.get_link		= mv643xx_eth_get_link,
+	.get_link		= ethtool_op_get_link,
 	.get_coalesce		= mv643xx_eth_get_coalesce,
 	.set_coalesce		= mv643xx_eth_set_coalesce,
 	.get_ringparam		= mv643xx_eth_get_ringparam,
@@ -2983,7 +2978,7 @@ static int mv643xx_eth_remove(struct pla
 	unregister_netdev(mp->dev);
 	if (mp->phy != NULL)
 		phy_detach(mp->phy);
-	flush_scheduled_work();
+	cancel_work_sync(&mp->tx_timeout_task);
 	free_netdev(mp->dev);
 
 	platform_set_drvdata(pdev, NULL);
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/myri10ge/myri10ge.c linux-libre-2.6.38-gnu1/drivers/net/myri10ge/myri10ge.c
--- linux-libre-2.6.37-gnu1/drivers/net/myri10ge/myri10ge.c	2013-05-03 03:58:38.000000000 -0400
+++ linux-libre-2.6.38-gnu1/drivers/net/myri10ge/myri10ge.c	2013-05-03 01:58:45.000000000 -0400
@@ -2733,7 +2733,7 @@ again:
 	odd_flag = 0;
 	flags = (MXGEFW_FLAGS_NO_TSO | MXGEFW_FLAGS_FIRST);
 	if (likely(skb->ip_summed == CHECKSUM_PARTIAL)) {
-		cksum_offset = skb_transport_offset(skb);
+		cksum_offset = skb_checksum_start_offset(skb);
 		pseudo_hdr_offset = cksum_offset + skb->csum_offset;
 		/* If the headers are excessively large, then we must
 		 * fall back to a software checksum */
@@ -3393,9 +3393,7 @@ static int myri10ge_resume(struct pci_de
 		return -EIO;
 	}
 
-	status = pci_restore_state(pdev);
-	if (status)
-		return status;
+	pci_restore_state(pdev);
 
 	status = pci_enable_device(pdev);
 	if (status) {
@@ -4057,7 +4055,7 @@ static void myri10ge_remove(struct pci_d
 	if (mgp == NULL)
 		return;
 
-	flush_scheduled_work();
+	cancel_work_sync(&mgp->watchdog_work);
 	netdev = mgp->dev;
 	unregister_netdev(netdev);
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/ne-h8300.c linux-libre-2.6.38-gnu1/drivers/net/ne-h8300.c
--- linux-libre-2.6.37-gnu1/drivers/net/ne-h8300.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/ne-h8300.c	2011-03-14 21:20:32.000000000 -0400
@@ -86,7 +86,7 @@ static u32 reg_offset[16];
 
 static int __init init_reg_offset(struct net_device *dev,unsigned long base_addr)
 {
-	struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev);
+	struct ei_device *ei_local = netdev_priv(dev);
 	int i;
 	unsigned char bus_width;
 
@@ -218,7 +218,7 @@ static int __init ne_probe1(struct net_d
 	int start_page, stop_page;
 	int reg0, ret;
 	static unsigned version_printed;
-	struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev);
+	struct ei_device *ei_local = netdev_priv(dev);
 	unsigned char bus_width;
 
 	if (!request_region(ioaddr, NE_IO_EXTENT, DRV_NAME))
@@ -371,7 +371,7 @@ static int ne_close(struct net_device *d
 static void ne_reset_8390(struct net_device *dev)
 {
 	unsigned long reset_start_time = jiffies;
-	struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev);
+	struct ei_device *ei_local = netdev_priv(dev);
 
 	if (ei_debug > 1)
 		printk(KERN_DEBUG "resetting the 8390 t=%ld...", jiffies);
@@ -397,7 +397,7 @@ static void ne_reset_8390(struct net_dev
 
 static void ne_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
 {
-	struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev);
+	struct ei_device *ei_local = netdev_priv(dev);
 	/* This *shouldn't* happen. If it does, it's the last thing you'll see */
 
 	if (ei_status.dmaing)
@@ -437,7 +437,7 @@ static void ne_get_8390_hdr(struct net_d
 
 static void ne_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
 {
-	struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev);
+	struct ei_device *ei_local = netdev_priv(dev);
 #ifdef NE_SANITY_CHECK
 	int xfer_count = count;
 #endif
@@ -507,7 +507,7 @@ static void ne_block_input(struct net_de
 static void ne_block_output(struct net_device *dev, int count,
 		const unsigned char *buf, const int start_page)
 {
-	struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev);
+	struct ei_device *ei_local = netdev_priv(dev);
 	unsigned long dma_start;
 #ifdef NE_SANITY_CHECK
 	int retries = 0;
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/netconsole.c linux-libre-2.6.38-gnu1/drivers/net/netconsole.c
--- linux-libre-2.6.37-gnu1/drivers/net/netconsole.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/netconsole.c	2011-03-14 21:20:32.000000000 -0400
@@ -664,6 +664,7 @@ static int netconsole_netdev_event(struc
 	unsigned long flags;
 	struct netconsole_target *nt;
 	struct net_device *dev = ptr;
+	bool stopped = false;
 
 	if (!(event == NETDEV_CHANGENAME || event == NETDEV_UNREGISTER ||
 	      event == NETDEV_BONDING_DESLAVE || event == NETDEV_GOING_DOWN))
@@ -690,15 +691,16 @@ static int netconsole_netdev_event(struc
 			case NETDEV_GOING_DOWN:
 			case NETDEV_BONDING_DESLAVE:
 				nt->enabled = 0;
+				stopped = true;
 				break;
 			}
 		}
 		netconsole_target_put(nt);
 	}
 	spin_unlock_irqrestore(&target_list_lock, flags);
-	if (event == NETDEV_UNREGISTER || event == NETDEV_BONDING_DESLAVE)
-		printk(KERN_INFO "netconsole: network logging stopped, "
-			"interface %s %s\n",  dev->name,
+	if (stopped && (event == NETDEV_UNREGISTER || event == NETDEV_BONDING_DESLAVE))
+		printk(KERN_INFO "netconsole: network logging stopped on "
+			"interface %s as it %s\n",  dev->name,
 			event == NETDEV_UNREGISTER ? "unregistered" : "released slaves");
 
 done:
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/netxen/netxen_nic_ethtool.c linux-libre-2.6.38-gnu1/drivers/net/netxen/netxen_nic_ethtool.c
--- linux-libre-2.6.37-gnu1/drivers/net/netxen/netxen_nic_ethtool.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/netxen/netxen_nic_ethtool.c	2011-03-14 21:20:32.000000000 -0400
@@ -720,7 +720,21 @@ static u32 netxen_nic_get_rx_csum(struct
 static int netxen_nic_set_rx_csum(struct net_device *dev, u32 data)
 {
 	struct netxen_adapter *adapter = netdev_priv(dev);
-	adapter->rx_csum = !!data;
+
+	if (data) {
+		adapter->rx_csum = data;
+		return 0;
+	}
+
+	if (dev->features & NETIF_F_LRO) {
+		if (netxen_config_hw_lro(adapter, NETXEN_NIC_LRO_DISABLED))
+			return -EIO;
+
+		dev->features &= ~NETIF_F_LRO;
+		netxen_send_lro_cleanup(adapter);
+		netdev_info(dev, "disabling LRO as rx_csum is off\n");
+	}
+	adapter->rx_csum = data;
 	return 0;
 }
 
@@ -893,11 +907,19 @@ static int netxen_nic_set_flags(struct n
 	if (!(adapter->capabilities & NX_FW_CAPABILITY_HW_LRO))
 		return -EINVAL;
 
+	if (!adapter->rx_csum) {
+		netdev_info(netdev, "rx csum is off, cannot toggle LRO\n");
+		return -EINVAL;
+	}
+
+	if (!!(data & ETH_FLAG_LRO) == !!(netdev->features & NETIF_F_LRO))
+		return 0;
+
 	if (data & ETH_FLAG_LRO) {
 		hw_lro = NETXEN_NIC_LRO_ENABLED;
 		netdev->features |= NETIF_F_LRO;
 	} else {
-		hw_lro = 0;
+		hw_lro = NETXEN_NIC_LRO_DISABLED;
 		netdev->features &= ~NETIF_F_LRO;
 	}
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/netxen/netxen_nic.h linux-libre-2.6.38-gnu1/drivers/net/netxen/netxen_nic.h
--- linux-libre-2.6.37-gnu1/drivers/net/netxen/netxen_nic.h	2013-05-03 03:58:41.000000000 -0400
+++ linux-libre-2.6.38-gnu1/drivers/net/netxen/netxen_nic.h	2013-05-03 01:58:49.000000000 -0400
@@ -53,8 +53,8 @@
 
 #define _NETXEN_NIC_LINUX_MAJOR 4
 #define _NETXEN_NIC_LINUX_MINOR 0
-#define _NETXEN_NIC_LINUX_SUBVERSION 74
-#define NETXEN_NIC_LINUX_VERSIONID  "4.0.74"
+#define _NETXEN_NIC_LINUX_SUBVERSION 75
+#define NETXEN_NIC_LINUX_VERSIONID  "4.0.75"
 
 #define NETXEN_VERSION_CODE(a, b, c)	(((a) << 24) + ((b) << 16) + (c))
 #define _major(v)	(((v) >> 24) & 0xff)
@@ -1132,6 +1132,7 @@ typedef struct {
 #define NETXEN_NIC_MSI_ENABLED		0x02
 #define NETXEN_NIC_MSIX_ENABLED		0x04
 #define NETXEN_NIC_LRO_ENABLED		0x08
+#define NETXEN_NIC_LRO_DISABLED		0x00
 #define NETXEN_NIC_BRIDGE_ENABLED       0X10
 #define NETXEN_NIC_DIAG_ENABLED		0x20
 #define NETXEN_IS_MSI_FAMILY(adapter) \
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/netxen/netxen_nic_hw.c linux-libre-2.6.38-gnu1/drivers/net/netxen/netxen_nic_hw.c
--- linux-libre-2.6.37-gnu1/drivers/net/netxen/netxen_nic_hw.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/netxen/netxen_nic_hw.c	2011-03-14 21:20:32.000000000 -0400
@@ -655,7 +655,7 @@ nx_p3_sre_macaddr_change(struct netxen_a
 }
 
 static int nx_p3_nic_add_mac(struct netxen_adapter *adapter,
-		u8 *addr, struct list_head *del_list)
+		const u8 *addr, struct list_head *del_list)
 {
 	struct list_head *head;
 	nx_mac_list_t *cur;
@@ -686,7 +686,9 @@ static void netxen_p3_nic_set_multi(stru
 {
 	struct netxen_adapter *adapter = netdev_priv(netdev);
 	struct netdev_hw_addr *ha;
-	u8 bcast_addr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+	static const u8 bcast_addr[ETH_ALEN] = {
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff
+	};
 	u32 mode = VPORT_MISS_MODE_DROP;
 	LIST_HEAD(del_list);
 	struct list_head *head;
@@ -807,9 +809,6 @@ int netxen_config_hw_lro(struct netxen_a
 	u64 word;
 	int rv = 0;
 
-	if ((adapter->flags & NETXEN_NIC_LRO_ENABLED) == enable)
-		return 0;
-
 	memset(&req, 0, sizeof(nx_nic_req_t));
 
 	req.qhdr = cpu_to_le64(NX_HOST_REQUEST << 23);
@@ -825,8 +824,6 @@ int netxen_config_hw_lro(struct netxen_a
 			"configure hw lro request\n");
 	}
 
-	adapter->flags ^= NETXEN_NIC_LRO_ENABLED;
-
 	return rv;
 }
 
@@ -869,9 +866,11 @@ int netxen_config_rss(struct netxen_adap
 	u64 word;
 	int i, rv;
 
-	u64 key[] = { 0xbeac01fa6a42b73bULL, 0x8030f20c77cb2da3ULL,
-			0xae7b30b4d0ca2bcbULL, 0x43a38fb04167253dULL,
-			0x255b0ec26d5a56daULL };
+	static const u64 key[] = {
+		0xbeac01fa6a42b73bULL, 0x8030f20c77cb2da3ULL,
+		0xae7b30b4d0ca2bcbULL, 0x43a38fb04167253dULL,
+		0x255b0ec26d5a56daULL
+	};
 
 
 	memset(&req, 0, sizeof(nx_nic_req_t));
@@ -895,7 +894,7 @@ int netxen_config_rss(struct netxen_adap
 		((u64)(enable & 0x1) << 8) |
 		((0x7ULL) << 48);
 	req.words[0] = cpu_to_le64(word);
-	for (i = 0; i < 5; i++)
+	for (i = 0; i < ARRAY_SIZE(key); i++)
 		req.words[i+1] = cpu_to_le64(key[i]);
 
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/netxen/netxen_nic_init.c linux-libre-2.6.38-gnu1/drivers/net/netxen/netxen_nic_init.c
--- linux-libre-2.6.37-gnu1/drivers/net/netxen/netxen_nic_init.c	2013-05-03 03:58:38.000000000 -0400
+++ linux-libre-2.6.38-gnu1/drivers/net/netxen/netxen_nic_init.c	2013-05-03 01:58:46.000000000 -0400
@@ -214,13 +214,12 @@ int netxen_alloc_sw_resources(struct net
 	tx_ring->num_desc = adapter->num_txd;
 	tx_ring->txq = netdev_get_tx_queue(netdev, 0);
 
-	cmd_buf_arr = vmalloc(TX_BUFF_RINGSIZE(tx_ring));
+	cmd_buf_arr = vzalloc(TX_BUFF_RINGSIZE(tx_ring));
 	if (cmd_buf_arr == NULL) {
 		dev_err(&pdev->dev, "%s: failed to allocate cmd buffer ring\n",
 		       netdev->name);
 		goto err_out;
 	}
-	memset(cmd_buf_arr, 0, TX_BUFF_RINGSIZE(tx_ring));
 	tx_ring->cmd_buf_arr = cmd_buf_arr;
 
 	recv_ctx = &adapter->recv_ctx;
@@ -279,8 +278,7 @@ int netxen_alloc_sw_resources(struct net
 			break;
 
 		}
-		rds_ring->rx_buf_arr = (struct netxen_rx_buffer *)
-			vmalloc(RCV_BUFF_RINGSIZE(rds_ring));
+		rds_ring->rx_buf_arr = vzalloc(RCV_BUFF_RINGSIZE(rds_ring));
 		if (rds_ring->rx_buf_arr == NULL) {
 			printk(KERN_ERR "%s: Failed to allocate "
 				"rx buffer ring %d\n",
@@ -288,7 +286,6 @@ int netxen_alloc_sw_resources(struct net
 			/* free whatever was already allocated */
 			goto err_out;
 		}
-		memset(rds_ring->rx_buf_arr, 0, RCV_BUFF_RINGSIZE(rds_ring));
 		INIT_LIST_HEAD(&rds_ring->free_list);
 		/*
 		 * Now go through all of them, set reference handles
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/netxen/netxen_nic_main.c linux-libre-2.6.38-gnu1/drivers/net/netxen/netxen_nic_main.c
--- linux-libre-2.6.37-gnu1/drivers/net/netxen/netxen_nic_main.c	2013-05-03 03:58:44.000000000 -0400
+++ linux-libre-2.6.38-gnu1/drivers/net/netxen/netxen_nic_main.c	2013-05-03 01:58:52.000000000 -0400
@@ -38,7 +38,7 @@
 #include <linux/sysfs.h>
 #include <linux/aer.h>
 
-MODULE_DESCRIPTION("QLogic/NetXen (1/10) GbE Converged Ethernet Driver");
+MODULE_DESCRIPTION("QLogic/NetXen (1/10) GbE Intelligent Ethernet Driver");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(NETXEN_NIC_LINUX_VERSIONID);
 /*(DEBLOBBED)*/
@@ -762,8 +762,6 @@ netxen_check_options(struct netxen_adapt
 	if (adapter->fw_version >= NETXEN_VERSION_CODE(4, 0, 222))
 		adapter->capabilities = NXRD32(adapter, CRB_FW_CAPABILITIES_1);
 
-	adapter->flags &= ~NETXEN_NIC_LRO_ENABLED;
-
 	if (adapter->ahw.port_type == NETXEN_NIC_XGBE) {
 		adapter->num_rxd = DEFAULT_RCV_DESCRIPTORS_10G;
 		adapter->num_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS_10G;
@@ -990,7 +988,7 @@ __netxen_nic_up(struct netxen_adapter *a
 	if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
 		netxen_config_intr_coalesce(adapter);
 
-	if (adapter->capabilities & NX_FW_CAPABILITY_HW_LRO)
+	if (netdev->features & NETIF_F_LRO)
 		netxen_config_hw_lro(adapter, NETXEN_NIC_LRO_ENABLED);
 
 	netxen_napi_enable(adapter);
@@ -1277,6 +1275,7 @@ netxen_nic_probe(struct pci_dev *pdev, c
 	int i = 0, err;
 	int pci_func_id = PCI_FUNC(pdev->devfn);
 	uint8_t revision_id;
+	u32 val;
 
 	if (pdev->revision >= NX_P3_A0 && pdev->revision <= NX_P3_B1) {
 		pr_warning("%s: chip revisions between 0x%x-0x%x "
@@ -1352,8 +1351,9 @@ netxen_nic_probe(struct pci_dev *pdev, c
 		break;
 	}
 
-	if (reset_devices) {
-		if (adapter->portnum == 0) {
+	if (adapter->portnum == 0) {
+		val = NXRD32(adapter, NX_CRB_DEV_REF_COUNT);
+		if (val != 0xffffffff && val != 0) {
 			NXWR32(adapter, NX_CRB_DEV_REF_COUNT, 0);
 			adapter->need_fw_reset = 1;
 		}
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/ni52.c linux-libre-2.6.38-gnu1/drivers/net/ni52.c
--- linux-libre-2.6.37-gnu1/drivers/net/ni52.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/ni52.c	2011-03-14 21:20:32.000000000 -0400
@@ -388,9 +388,9 @@ static long memend;	/* e.g 0xd4000 */
 struct net_device * __init ni52_probe(int unit)
 {
 	struct net_device *dev = alloc_etherdev(sizeof(struct priv));
-	static int ports[] = {0x300, 0x280, 0x360 , 0x320 , 0x340, 0};
+	static const int ports[] = {0x300, 0x280, 0x360, 0x320, 0x340, 0};
+	const int *port;
 	struct priv *p;
-	int *port;
 	int err = 0;
 
 	if (!dev)
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/ni65.c linux-libre-2.6.38-gnu1/drivers/net/ni65.c
--- linux-libre-2.6.37-gnu1/drivers/net/ni65.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/ni65.c	2011-03-14 21:20:32.000000000 -0400
@@ -361,8 +361,8 @@ static int dma;
 struct net_device * __init ni65_probe(int unit)
 {
 	struct net_device *dev = alloc_etherdev(0);
-	static int ports[] = {0x360,0x300,0x320,0x340, 0};
-	int *port;
+	static const int ports[] = { 0x360, 0x300, 0x320, 0x340, 0 };
+	const int *port;
 	int err = 0;
 
 	if (!dev)
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/niu.c linux-libre-2.6.38-gnu1/drivers/net/niu.c
--- linux-libre-2.6.37-gnu1/drivers/net/niu.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/niu.c	2011-03-14 21:20:32.000000000 -0400
@@ -4489,6 +4489,9 @@ static int niu_alloc_channels(struct niu
 {
 	struct niu_parent *parent = np->parent;
 	int first_rx_channel, first_tx_channel;
+	int num_rx_rings, num_tx_rings;
+	struct rx_ring_info *rx_rings;
+	struct tx_ring_info *tx_rings;
 	int i, port, err;
 
 	port = np->port;
@@ -4498,18 +4501,21 @@ static int niu_alloc_channels(struct niu
 		first_tx_channel += parent->txchan_per_port[i];
 	}
 
-	np->num_rx_rings = parent->rxchan_per_port[port];
-	np->num_tx_rings = parent->txchan_per_port[port];
-
-	netif_set_real_num_rx_queues(np->dev, np->num_rx_rings);
-	netif_set_real_num_tx_queues(np->dev, np->num_tx_rings);
+	num_rx_rings = parent->rxchan_per_port[port];
+	num_tx_rings = parent->txchan_per_port[port];
 
-	np->rx_rings = kcalloc(np->num_rx_rings, sizeof(struct rx_ring_info),
-			       GFP_KERNEL);
+	rx_rings = kcalloc(num_rx_rings, sizeof(struct rx_ring_info),
+			   GFP_KERNEL);
 	err = -ENOMEM;
-	if (!np->rx_rings)
+	if (!rx_rings)
 		goto out_err;
 
+	np->num_rx_rings = num_rx_rings;
+	smp_wmb();
+	np->rx_rings = rx_rings;
+
+	netif_set_real_num_rx_queues(np->dev, num_rx_rings);
+
 	for (i = 0; i < np->num_rx_rings; i++) {
 		struct rx_ring_info *rp = &np->rx_rings[i];
 
@@ -4538,12 +4544,18 @@ static int niu_alloc_channels(struct niu
 			return err;
 	}
 
-	np->tx_rings = kcalloc(np->num_tx_rings, sizeof(struct tx_ring_info),
-			       GFP_KERNEL);
+	tx_rings = kcalloc(num_tx_rings, sizeof(struct tx_ring_info),
+			   GFP_KERNEL);
 	err = -ENOMEM;
-	if (!np->tx_rings)
+	if (!tx_rings)
 		goto out_err;
 
+	np->num_tx_rings = num_tx_rings;
+	smp_wmb();
+	np->tx_rings = tx_rings;
+
+	netif_set_real_num_tx_queues(np->dev, num_tx_rings);
+
 	for (i = 0; i < np->num_tx_rings; i++) {
 		struct tx_ring_info *rp = &np->tx_rings[i];
 
@@ -6246,11 +6258,17 @@ static void niu_sync_mac_stats(struct ni
 static void niu_get_rx_stats(struct niu *np)
 {
 	unsigned long pkts, dropped, errors, bytes;
+	struct rx_ring_info *rx_rings;
 	int i;
 
 	pkts = dropped = errors = bytes = 0;
+
+	rx_rings = ACCESS_ONCE(np->rx_rings);
+	if (!rx_rings)
+		goto no_rings;
+
 	for (i = 0; i < np->num_rx_rings; i++) {
-		struct rx_ring_info *rp = &np->rx_rings[i];
+		struct rx_ring_info *rp = &rx_rings[i];
 
 		niu_sync_rx_discard_stats(np, rp, 0);
 
@@ -6259,6 +6277,8 @@ static void niu_get_rx_stats(struct niu
 		dropped += rp->rx_dropped;
 		errors += rp->rx_errors;
 	}
+
+no_rings:
 	np->dev->stats.rx_packets = pkts;
 	np->dev->stats.rx_bytes = bytes;
 	np->dev->stats.rx_dropped = dropped;
@@ -6268,16 +6288,24 @@ static void niu_get_rx_stats(struct niu
 static void niu_get_tx_stats(struct niu *np)
 {
 	unsigned long pkts, errors, bytes;
+	struct tx_ring_info *tx_rings;
 	int i;
 
 	pkts = errors = bytes = 0;
+
+	tx_rings = ACCESS_ONCE(np->tx_rings);
+	if (!tx_rings)
+		goto no_rings;
+
 	for (i = 0; i < np->num_tx_rings; i++) {
-		struct tx_ring_info *rp = &np->tx_rings[i];
+		struct tx_ring_info *rp = &tx_rings[i];
 
 		pkts += rp->tx_packets;
 		bytes += rp->tx_bytes;
 		errors += rp->tx_errors;
 	}
+
+no_rings:
 	np->dev->stats.tx_packets = pkts;
 	np->dev->stats.tx_bytes = bytes;
 	np->dev->stats.tx_errors = errors;
@@ -6287,9 +6315,10 @@ static struct net_device_stats *niu_get_
 {
 	struct niu *np = netdev_priv(dev);
 
-	niu_get_rx_stats(np);
-	niu_get_tx_stats(np);
-
+	if (netif_running(dev)) {
+		niu_get_rx_stats(np);
+		niu_get_tx_stats(np);
+	}
 	return &dev->stats;
 }
 
@@ -6589,7 +6618,7 @@ static u64 niu_compute_tx_flags(struct s
 			     (ip_proto == IPPROTO_UDP ?
 			      TXHDR_CSUM_UDP : TXHDR_CSUM_SCTP));
 
-		start = skb_transport_offset(skb) -
+		start = skb_checksum_start_offset(skb) -
 			(pad_bytes + sizeof(struct tx_pkt_hdr));
 		stuff = start + skb->csum_offset;
 
@@ -9917,7 +9946,7 @@ static int niu_suspend(struct pci_dev *p
 	if (!netif_running(dev))
 		return 0;
 
-	flush_scheduled_work();
+	flush_work_sync(&np->reset_task);
 	niu_netif_stop(np);
 
 	del_timer_sync(&np->timer);
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/ns83820.c linux-libre-2.6.38-gnu1/drivers/net/ns83820.c
--- linux-libre-2.6.37-gnu1/drivers/net/ns83820.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/ns83820.c	2011-03-14 21:20:32.000000000 -0400
@@ -1988,12 +1988,11 @@ static int __devinit ns83820_init_one(st
 	}
 
 	ndev = alloc_etherdev(sizeof(struct ns83820));
-	dev = PRIV(ndev);
-
 	err = -ENOMEM;
-	if (!dev)
+	if (!ndev)
 		goto out;
 
+	dev = PRIV(ndev);
 	dev->ndev = ndev;
 
 	spin_lock_init(&dev->rx_info.lock);
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/pch_gbe/pch_gbe_ethtool.c linux-libre-2.6.38-gnu1/drivers/net/pch_gbe/pch_gbe_ethtool.c
--- linux-libre-2.6.37-gnu1/drivers/net/pch_gbe/pch_gbe_ethtool.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/pch_gbe/pch_gbe_ethtool.c	2011-03-14 21:20:32.000000000 -0400
@@ -469,18 +469,6 @@ static int pch_gbe_set_rx_csum(struct ne
 }
 
 /**
- * pch_gbe_get_tx_csum - Report whether transmit checksums are turned on or off
- * @netdev:  Network interface device structure
- * Returns
- *	true(1):  Checksum On
- *	false(0): Checksum Off
- */
-static u32 pch_gbe_get_tx_csum(struct net_device *netdev)
-{
-	return (netdev->features & NETIF_F_HW_CSUM) != 0;
-}
-
-/**
  * pch_gbe_set_tx_csum - Turn transmit checksums on or off
  * @netdev: Network interface device structure
  * @data:   Checksum on[true] or off[false]
@@ -493,11 +481,7 @@ static int pch_gbe_set_tx_csum(struct ne
 	struct pch_gbe_adapter *adapter = netdev_priv(netdev);
 
 	adapter->tx_csum = data;
-	if (data)
-		netdev->features |= NETIF_F_HW_CSUM;
-	else
-		netdev->features &= ~NETIF_F_HW_CSUM;
-	return 0;
+	return ethtool_op_set_tx_ipv6_csum(netdev, data);
 }
 
 /**
@@ -572,7 +556,6 @@ static const struct ethtool_ops pch_gbe_
 	.set_pauseparam = pch_gbe_set_pauseparam,
 	.get_rx_csum = pch_gbe_get_rx_csum,
 	.set_rx_csum = pch_gbe_set_rx_csum,
-	.get_tx_csum = pch_gbe_get_tx_csum,
 	.set_tx_csum = pch_gbe_set_tx_csum,
 	.get_strings = pch_gbe_get_strings,
 	.get_ethtool_stats = pch_gbe_get_ethtool_stats,
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/pch_gbe/pch_gbe.h linux-libre-2.6.38-gnu1/drivers/net/pch_gbe/pch_gbe.h
--- linux-libre-2.6.37-gnu1/drivers/net/pch_gbe/pch_gbe.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/pch_gbe/pch_gbe.h	2011-03-14 21:20:32.000000000 -0400
@@ -73,7 +73,7 @@ struct pch_gbe_regs {
 	struct pch_gbe_regs_mac_adr mac_adr[16];
 	u32 ADDR_MASK;
 	u32 MIIM;
-	u32 reserve2;
+	u32 MAC_ADDR_LOAD;
 	u32 RGMII_ST;
 	u32 RGMII_CTRL;
 	u32 reserve3[3];
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/pch_gbe/pch_gbe_main.c linux-libre-2.6.38-gnu1/drivers/net/pch_gbe/pch_gbe_main.c
--- linux-libre-2.6.37-gnu1/drivers/net/pch_gbe/pch_gbe_main.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/pch_gbe/pch_gbe_main.c	2011-03-14 21:20:32.000000000 -0400
@@ -29,6 +29,7 @@ const char pch_driver_version[] = DRV_VE
 #define PCH_GBE_SHORT_PKT		64
 #define DSC_INIT16			0xC000
 #define PCH_GBE_DMA_ALIGN		0
+#define PCH_GBE_DMA_PADDING		2
 #define PCH_GBE_WATCHDOG_PERIOD		(1 * HZ)	/* watchdog time */
 #define PCH_GBE_COPYBREAK_DEFAULT	256
 #define PCH_GBE_PCI_BAR			1
@@ -88,6 +89,12 @@ static unsigned int copybreak __read_mos
 static int pch_gbe_mdio_read(struct net_device *netdev, int addr, int reg);
 static void pch_gbe_mdio_write(struct net_device *netdev, int addr, int reg,
 			       int data);
+
+inline void pch_gbe_mac_load_mac_addr(struct pch_gbe_hw *hw)
+{
+	iowrite32(0x01, &hw->reg->MAC_ADDR_LOAD);
+}
+
 /**
  * pch_gbe_mac_read_mac_addr - Read MAC address
  * @hw:	            Pointer to the HW structure
@@ -519,7 +526,9 @@ static void pch_gbe_reset_task(struct wo
 	struct pch_gbe_adapter *adapter;
 	adapter = container_of(work, struct pch_gbe_adapter, reset_task);
 
+	rtnl_lock();
 	pch_gbe_reinit_locked(adapter);
+	rtnl_unlock();
 }
 
 /**
@@ -528,14 +537,8 @@ static void pch_gbe_reset_task(struct wo
  */
 void pch_gbe_reinit_locked(struct pch_gbe_adapter *adapter)
 {
-	struct net_device *netdev = adapter->netdev;
-
-	rtnl_lock();
-	if (netif_running(netdev)) {
-		pch_gbe_down(adapter);
-		pch_gbe_up(adapter);
-	}
-	rtnl_unlock();
+	pch_gbe_down(adapter);
+	pch_gbe_up(adapter);
 }
 
 /**
@@ -1369,16 +1372,13 @@ pch_gbe_clean_rx(struct pch_gbe_adapter
 	struct pch_gbe_buffer *buffer_info;
 	struct pch_gbe_rx_desc *rx_desc;
 	u32 length;
-	unsigned char tmp_packet[ETH_HLEN];
 	unsigned int i;
 	unsigned int cleaned_count = 0;
 	bool cleaned = false;
-	struct sk_buff *skb;
+	struct sk_buff *skb, *new_skb;
 	u8 dma_status;
 	u16 gbec_status;
 	u32 tcp_ip_status;
-	u8 skb_copy_flag = 0;
-	u8 skb_padding_flag = 0;
 
 	i = rx_ring->next_to_clean;
 
@@ -1422,55 +1422,70 @@ pch_gbe_clean_rx(struct pch_gbe_adapter
 			pr_err("Receive CRC Error\n");
 		} else {
 			/* get receive length */
-			/* length convert[-3], padding[-2] */
-			length = (rx_desc->rx_words_eob) - 3 - 2;
+			/* length convert[-3] */
+			length = (rx_desc->rx_words_eob) - 3;
 
 			/* Decide the data conversion method */
 			if (!adapter->rx_csum) {
 				/* [Header:14][payload] */
-				skb_padding_flag = 0;
-				skb_copy_flag = 1;
+				if (NET_IP_ALIGN) {
+					/* Because alignment differs,
+					 * the new_skb is newly allocated,
+					 * and data is copied to new_skb.*/
+					new_skb = netdev_alloc_skb(netdev,
+							 length + NET_IP_ALIGN);
+					if (!new_skb) {
+						/* dorrop error */
+						pr_err("New skb allocation "
+							"Error\n");
+						goto dorrop;
+					}
+					skb_reserve(new_skb, NET_IP_ALIGN);
+					memcpy(new_skb->data, skb->data,
+					       length);
+					skb = new_skb;
+				} else {
+					/* DMA buffer is used as SKB as it is.*/
+					buffer_info->skb = NULL;
+				}
 			} else {
 				/* [Header:14][padding:2][payload] */
-				skb_padding_flag = 1;
-				if (length < copybreak)
-					skb_copy_flag = 1;
-				else
-					skb_copy_flag = 0;
-			}
-
-			/* Data conversion */
-			if (skb_copy_flag) {	/* recycle  skb */
-				struct sk_buff *new_skb;
-				new_skb =
-				    netdev_alloc_skb(netdev,
-						     length + NET_IP_ALIGN);
-				if (new_skb) {
-					if (!skb_padding_flag) {
-						skb_reserve(new_skb,
-								NET_IP_ALIGN);
+				/* The length includes padding length */
+				length = length - PCH_GBE_DMA_PADDING;
+				if ((length < copybreak) ||
+				    (NET_IP_ALIGN != PCH_GBE_DMA_PADDING)) {
+					/* Because alignment differs,
+					 * the new_skb is newly allocated,
+					 * and data is copied to new_skb.
+					 * Padding data is deleted
+					 * at the time of a copy.*/
+					new_skb = netdev_alloc_skb(netdev,
+							 length + NET_IP_ALIGN);
+					if (!new_skb) {
+						/* dorrop error */
+						pr_err("New skb allocation "
+							"Error\n");
+						goto dorrop;
 					}
+					skb_reserve(new_skb, NET_IP_ALIGN);
 					memcpy(new_skb->data, skb->data,
-						length);
-					/* save the skb
-					 * in buffer_info as good */
+					       ETH_HLEN);
+					memcpy(&new_skb->data[ETH_HLEN],
+					       &skb->data[ETH_HLEN +
+					       PCH_GBE_DMA_PADDING],
+					       length - ETH_HLEN);
 					skb = new_skb;
-				} else if (!skb_padding_flag) {
-					/* dorrop error */
-					pr_err("New skb allocation Error\n");
-					goto dorrop;
+				} else {
+					/* Padding data is deleted
+					 * by moving header data.*/
+					memmove(&skb->data[PCH_GBE_DMA_PADDING],
+						&skb->data[0], ETH_HLEN);
+					skb_reserve(skb, NET_IP_ALIGN);
+					buffer_info->skb = NULL;
 				}
-			} else {
-				buffer_info->skb = NULL;
-			}
-			if (skb_padding_flag) {
-				memcpy(&tmp_packet[0], &skb->data[0], ETH_HLEN);
-				memcpy(&skb->data[NET_IP_ALIGN], &tmp_packet[0],
-					ETH_HLEN);
-				skb_reserve(skb, NET_IP_ALIGN);
-
 			}
-
+			/* The length includes FCS length */
+			length = length - ETH_FCS_LEN;
 			/* update status of driver */
 			adapter->stats.rx_bytes += length;
 			adapter->stats.rx_packets++;
@@ -1523,12 +1538,11 @@ int pch_gbe_setup_tx_resources(struct pc
 	int desNo;
 
 	size = (int)sizeof(struct pch_gbe_buffer) * tx_ring->count;
-	tx_ring->buffer_info = vmalloc(size);
+	tx_ring->buffer_info = vzalloc(size);
 	if (!tx_ring->buffer_info) {
 		pr_err("Unable to allocate memory for the buffer infomation\n");
 		return -ENOMEM;
 	}
-	memset(tx_ring->buffer_info, 0, size);
 
 	tx_ring->size = tx_ring->count * (int)sizeof(struct pch_gbe_tx_desc);
 
@@ -1573,12 +1587,11 @@ int pch_gbe_setup_rx_resources(struct pc
 	int desNo;
 
 	size = (int)sizeof(struct pch_gbe_buffer) * rx_ring->count;
-	rx_ring->buffer_info = vmalloc(size);
+	rx_ring->buffer_info = vzalloc(size);
 	if (!rx_ring->buffer_info) {
 		pr_err("Unable to allocate memory for the receive descriptor ring\n");
 		return -ENOMEM;
 	}
-	memset(rx_ring->buffer_info, 0, size);
 	rx_ring->size = rx_ring->count * (int)sizeof(struct pch_gbe_rx_desc);
 	rx_ring->desc =	dma_alloc_coherent(&pdev->dev, rx_ring->size,
 					   &rx_ring->dma, GFP_KERNEL);
@@ -2249,7 +2262,7 @@ static void pch_gbe_remove(struct pci_de
 	struct net_device *netdev = pci_get_drvdata(pdev);
 	struct pch_gbe_adapter *adapter = netdev_priv(netdev);
 
-	flush_scheduled_work();
+	cancel_work_sync(&adapter->reset_task);
 	unregister_netdev(netdev);
 
 	pch_gbe_hal_phy_hw_reset(&adapter->hw);
@@ -2321,9 +2334,10 @@ static int pch_gbe_probe(struct pci_dev
 	netdev->watchdog_timeo = PCH_GBE_WATCHDOG_PERIOD;
 	netif_napi_add(netdev, &adapter->napi,
 		       pch_gbe_napi_poll, PCH_GBE_RX_WEIGHT);
-	netdev->features = NETIF_F_HW_CSUM | NETIF_F_GRO;
+	netdev->features = NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | NETIF_F_GRO;
 	pch_gbe_set_ethtool_ops(netdev);
 
+	pch_gbe_mac_load_mac_addr(&adapter->hw);
 	pch_gbe_mac_reset_hw(&adapter->hw);
 
 	/* setup the private structure */
@@ -2360,9 +2374,9 @@ static int pch_gbe_probe(struct pci_dev
 	pch_gbe_check_options(adapter);
 
 	if (adapter->tx_csum)
-		netdev->features |= NETIF_F_HW_CSUM;
+		netdev->features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
 	else
-		netdev->features &= ~NETIF_F_HW_CSUM;
+		netdev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM);
 
 	/* initialize the wol settings based on the eeprom settings */
 	adapter->wake_up_evt = PCH_GBE_WL_INIT_SETTING;
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/pcmcia/axnet_cs.c linux-libre-2.6.38-gnu1/drivers/net/pcmcia/axnet_cs.c
--- linux-libre-2.6.37-gnu1/drivers/net/pcmcia/axnet_cs.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/pcmcia/axnet_cs.c	2011-03-14 21:20:32.000000000 -0400
@@ -876,7 +876,7 @@ static void do_set_multicast_list(struct
 static int ax_open(struct net_device *dev)
 {
 	unsigned long flags;
-	struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev);
+	struct ei_device *ei_local = netdev_priv(dev);
 
 	/*
 	 *	Grab the page lock so we own the register set, then call
@@ -927,7 +927,7 @@ static int ax_close(struct net_device *d
 static void axnet_tx_timeout(struct net_device *dev)
 {
 	long e8390_base = dev->base_addr;
-	struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev);
+	struct ei_device *ei_local = netdev_priv(dev);
 	int txsr, isr, tickssofar = jiffies - dev_trans_start(dev);
 	unsigned long flags;
 
@@ -974,7 +974,7 @@ static netdev_tx_t axnet_start_xmit(stru
 					  struct net_device *dev)
 {
 	long e8390_base = dev->base_addr;
-	struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev);
+	struct ei_device *ei_local = netdev_priv(dev);
 	int length, send_length, output_page;
 	unsigned long flags;
 	u8 packet[ETH_ZLEN];
@@ -1271,7 +1271,7 @@ static void ei_tx_err(struct net_device
 static void ei_tx_intr(struct net_device *dev)
 {
 	long e8390_base = dev->base_addr;
-	struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev);
+	struct ei_device *ei_local = netdev_priv(dev);
 	int status = inb(e8390_base + EN0_TSR);
     
 	/*
@@ -1355,7 +1355,7 @@ static void ei_tx_intr(struct net_device
 static void ei_receive(struct net_device *dev)
 {
 	long e8390_base = dev->base_addr;
-	struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev);
+	struct ei_device *ei_local = netdev_priv(dev);
 	unsigned char rxing_page, this_frame, next_frame;
 	unsigned short current_offset;
 	int rx_pkt_count = 0;
@@ -1488,12 +1488,10 @@ static void ei_rx_overrun(struct net_dev
     
 	/* 
 	 * Wait a full Tx time (1.2ms) + some guard time, NS says 1.6ms total.
-	 * Early datasheets said to poll the reset bit, but now they say that
-	 * it "is not a reliable indicator and subsequently should be ignored."
-	 * We wait at least 10ms.
+	 * We wait at least 2ms.
 	 */
 
-	mdelay(10);
+	mdelay(2);
 
 	/*
 	 * Reset RBCR[01] back to zero as per magic incantation.
@@ -1540,7 +1538,7 @@ static void ei_rx_overrun(struct net_dev
 static struct net_device_stats *get_stats(struct net_device *dev)
 {
 	long ioaddr = dev->base_addr;
-	struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev);
+	struct ei_device *ei_local = netdev_priv(dev);
 	unsigned long flags;
     
 	/* If the card is stopped, just return the present stats. */
@@ -1589,7 +1587,7 @@ static void do_set_multicast_list(struct
 {
 	long e8390_base = dev->base_addr;
 	int i;
-	struct ei_device *ei_local = (struct ei_device*)netdev_priv(dev);
+	struct ei_device *ei_local = netdev_priv(dev);
 
 	if (!(dev->flags&(IFF_PROMISC|IFF_ALLMULTI))) {
 		memset(ei_local->mcfilter, 0, 8);
@@ -1647,7 +1645,7 @@ static void AX88190_init(struct net_devi
 {
 	axnet_dev_t *info = PRIV(dev);
 	long e8390_base = dev->base_addr;
-	struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev);
+	struct ei_device *ei_local = netdev_priv(dev);
 	int i;
 	int endcfg = ei_local->word16 ? (0x48 | ENDCFG_WTS) : 0x48;
     
@@ -1713,7 +1711,7 @@ static void NS8390_trigger_send(struct n
 								int start_page)
 {
 	long e8390_base = dev->base_addr;
- 	struct ei_device *ei_local __attribute((unused)) = (struct ei_device *) netdev_priv(dev);
+ 	struct ei_device *ei_local __attribute((unused)) = netdev_priv(dev);
     
 	if (inb_p(e8390_base) & E8390_TRANS) 
 	{
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/pcmcia/fmvj18x_cs.c linux-libre-2.6.38-gnu1/drivers/net/pcmcia/fmvj18x_cs.c
--- linux-libre-2.6.37-gnu1/drivers/net/pcmcia/fmvj18x_cs.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/pcmcia/fmvj18x_cs.c	2011-03-14 21:20:32.000000000 -0400
@@ -691,6 +691,7 @@ static struct pcmcia_device_id fmvj18x_i
 	PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0105, 0x0e0a),
 	PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0032, 0x0e01),
 	PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0032, 0x0a05),
+	PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0032, 0x0b05),
 	PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0032, 0x1101),
 	PCMCIA_DEVICE_NULL,
 };
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/pcmcia/nmclan_cs.c linux-libre-2.6.38-gnu1/drivers/net/pcmcia/nmclan_cs.c
--- linux-libre-2.6.37-gnu1/drivers/net/pcmcia/nmclan_cs.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/pcmcia/nmclan_cs.c	2011-03-14 21:20:32.000000000 -0400
@@ -1291,7 +1291,7 @@ updateCRC
 
 static void updateCRC(int *CRC, int bit)
 {
-  int poly[]={
+  static const int poly[]={
     1,1,1,0, 1,1,0,1,
     1,0,1,1, 1,0,0,0,
     1,0,0,0, 0,0,1,1,
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/pcmcia/pcnet_cs.c linux-libre-2.6.38-gnu1/drivers/net/pcmcia/pcnet_cs.c
--- linux-libre-2.6.37-gnu1/drivers/net/pcmcia/pcnet_cs.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/pcmcia/pcnet_cs.c	2011-03-14 21:20:32.000000000 -0400
@@ -1536,6 +1536,7 @@ static struct pcmcia_device_id pcnet_ids
 	PCMCIA_DEVICE_PROD_ID12("CONTEC", "C-NET(PC)C-10L", 0x21cab552, 0xf6f90722),
 	PCMCIA_DEVICE_PROD_ID12("corega", "FEther PCC-TXF", 0x0a21501a, 0xa51564a2),
 	PCMCIA_DEVICE_PROD_ID12("corega", "Ether CF-TD", 0x0a21501a, 0x6589340a),
+	PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega Ether CF-TD LAN Card", 0x5261440f, 0x8797663b),
 	PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega EtherII PCC-T", 0x5261440f, 0xfa9d85bd),
 	PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega EtherII PCC-TD", 0x5261440f, 0xc49bd73d),
 	PCMCIA_DEVICE_PROD_ID12("Corega K.K.", "corega EtherII PCC-TD", 0xd4fdcbd8, 0xc49bd73d),
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/phy/phy.c linux-libre-2.6.38-gnu1/drivers/net/phy/phy.c
--- linux-libre-2.6.37-gnu1/drivers/net/phy/phy.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/phy/phy.c	2011-03-14 21:20:32.000000000 -0400
@@ -47,11 +47,11 @@ void phy_print_status(struct phy_device
 	pr_info("PHY: %s - Link is %s", dev_name(&phydev->dev),
 			phydev->link ? "Up" : "Down");
 	if (phydev->link)
-		printk(" - %d/%s", phydev->speed,
+		printk(KERN_CONT " - %d/%s", phydev->speed,
 				DUPLEX_FULL == phydev->duplex ?
 				"Full" : "Half");
 
-	printk("\n");
+	printk(KERN_CONT "\n");
 }
 EXPORT_SYMBOL(phy_print_status);
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/ppp_async.c linux-libre-2.6.38-gnu1/drivers/net/ppp_async.c
--- linux-libre-2.6.37-gnu1/drivers/net/ppp_async.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/ppp_async.c	2011-03-14 21:20:32.000000000 -0400
@@ -32,6 +32,7 @@
 #include <linux/init.h>
 #include <linux/jiffies.h>
 #include <linux/slab.h>
+#include <asm/unaligned.h>
 #include <asm/uaccess.h>
 #include <asm/string.h>
 
@@ -542,7 +543,7 @@ ppp_async_encode(struct asyncppp *ap)
 	data = ap->tpkt->data;
 	count = ap->tpkt->len;
 	fcs = ap->tfcs;
-	proto = (data[0] << 8) + data[1];
+	proto = get_unaligned_be16(data);
 
 	/*
 	 * LCP packets with code values between 1 (configure-reqest)
@@ -963,7 +964,7 @@ static void async_lcp_peek(struct asyncp
 	code = data[0];
 	if (code != CONFACK && code != CONFREQ)
 		return;
-	dlen = (data[2] << 8) + data[3];
+	dlen = get_unaligned_be16(data + 2);
 	if (len < dlen)
 		return;		/* packet got truncated or length is bogus */
 
@@ -997,15 +998,14 @@ static void async_lcp_peek(struct asyncp
 	while (dlen >= 2 && dlen >= data[1] && data[1] >= 2) {
 		switch (data[0]) {
 		case LCP_MRU:
-			val = (data[2] << 8) + data[3];
+			val = get_unaligned_be16(data + 2);
 			if (inbound)
 				ap->mru = val;
 			else
 				ap->chan.mtu = val;
 			break;
 		case LCP_ASYNCMAP:
-			val = (data[2] << 24) + (data[3] << 16)
-				+ (data[4] << 8) + data[5];
+			val = get_unaligned_be32(data + 2);
 			if (inbound)
 				ap->raccm = val;
 			else
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/ppp_deflate.c linux-libre-2.6.38-gnu1/drivers/net/ppp_deflate.c
--- linux-libre-2.6.37-gnu1/drivers/net/ppp_deflate.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/ppp_deflate.c	2011-03-14 21:20:32.000000000 -0400
@@ -41,6 +41,7 @@
 #include <linux/ppp-comp.h>
 
 #include <linux/zlib.h>
+#include <asm/unaligned.h>
 
 /*
  * State for a Deflate (de)compressor.
@@ -232,11 +233,9 @@ static int z_compress(void *arg, unsigne
 	 */
 	wptr[0] = PPP_ADDRESS(rptr);
 	wptr[1] = PPP_CONTROL(rptr);
-	wptr[2] = PPP_COMP >> 8;
-	wptr[3] = PPP_COMP;
+	put_unaligned_be16(PPP_COMP, wptr + 2);
 	wptr += PPP_HDRLEN;
-	wptr[0] = state->seqno >> 8;
-	wptr[1] = state->seqno;
+	put_unaligned_be16(state->seqno, wptr);
 	wptr += DEFLATE_OVHD;
 	olen = PPP_HDRLEN + DEFLATE_OVHD;
 	state->strm.next_out = wptr;
@@ -451,7 +450,7 @@ static int z_decompress(void *arg, unsig
 	}
 
 	/* Check the sequence number. */
-	seq = (ibuf[PPP_HDRLEN] << 8) + ibuf[PPP_HDRLEN+1];
+	seq = get_unaligned_be16(ibuf + PPP_HDRLEN);
 	if (seq != (state->seqno & 0xffff)) {
 		if (state->debug)
 			printk(KERN_DEBUG "z_decompress%d: bad seq # %d, expected %d\n",
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/ppp_generic.c linux-libre-2.6.38-gnu1/drivers/net/ppp_generic.c
--- linux-libre-2.6.37-gnu1/drivers/net/ppp_generic.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/ppp_generic.c	2011-03-14 21:20:32.000000000 -0400
@@ -46,6 +46,7 @@
 #include <linux/device.h>
 #include <linux/mutex.h>
 #include <linux/slab.h>
+#include <asm/unaligned.h>
 #include <net/slhc_vj.h>
 #include <asm/atomic.h>
 
@@ -210,7 +211,7 @@ struct ppp_net {
 };
 
 /* Get the PPP protocol number from a skb */
-#define PPP_PROTO(skb)	(((skb)->data[0] << 8) + (skb)->data[1])
+#define PPP_PROTO(skb)	get_unaligned_be16((skb)->data)
 
 /* We limit the length of ppp->file.rq to this (arbitrary) value */
 #define PPP_MAX_RQLEN	32
@@ -964,8 +965,7 @@ ppp_start_xmit(struct sk_buff *skb, stru
 
 	pp = skb_push(skb, 2);
 	proto = npindex_to_proto[npi];
-	pp[0] = proto >> 8;
-	pp[1] = proto;
+	put_unaligned_be16(proto, pp);
 
 	netif_stop_queue(dev);
 	skb_queue_tail(&ppp->file.xq, skb);
@@ -1136,8 +1136,7 @@ ppp_send_frame(struct ppp *ppp, struct s
 		   a four-byte PPP header on each packet */
 		*skb_push(skb, 2) = 1;
 		if (ppp->pass_filter &&
-		    sk_run_filter(skb, ppp->pass_filter,
-				  ppp->pass_len) == 0) {
+		    sk_run_filter(skb, ppp->pass_filter) == 0) {
 			if (ppp->debug & 1)
 				printk(KERN_DEBUG "PPP: outbound frame not passed\n");
 			kfree_skb(skb);
@@ -1145,8 +1144,7 @@ ppp_send_frame(struct ppp *ppp, struct s
 		}
 		/* if this packet passes the active filter, record the time */
 		if (!(ppp->active_filter &&
-		      sk_run_filter(skb, ppp->active_filter,
-				    ppp->active_len) == 0))
+		      sk_run_filter(skb, ppp->active_filter) == 0))
 			ppp->last_xmit = jiffies;
 		skb_pull(skb, 2);
 #else
@@ -1475,8 +1473,7 @@ static int ppp_mp_explode(struct ppp *pp
 		q = skb_put(frag, flen + hdrlen);
 
 		/* make the MP header */
-		q[0] = PPP_MP >> 8;
-		q[1] = PPP_MP;
+		put_unaligned_be16(PPP_MP, q);
 		if (ppp->flags & SC_MP_XSHORTSEQ) {
 			q[2] = bits + ((ppp->nxseq >> 8) & 0xf);
 			q[3] = ppp->nxseq;
@@ -1763,8 +1760,7 @@ ppp_receive_nonmp_frame(struct ppp *ppp,
 
 			*skb_push(skb, 2) = 0;
 			if (ppp->pass_filter &&
-			    sk_run_filter(skb, ppp->pass_filter,
-					  ppp->pass_len) == 0) {
+			    sk_run_filter(skb, ppp->pass_filter) == 0) {
 				if (ppp->debug & 1)
 					printk(KERN_DEBUG "PPP: inbound frame "
 					       "not passed\n");
@@ -1772,8 +1768,7 @@ ppp_receive_nonmp_frame(struct ppp *ppp,
 				return;
 			}
 			if (!(ppp->active_filter &&
-			      sk_run_filter(skb, ppp->active_filter,
-					    ppp->active_len) == 0))
+			      sk_run_filter(skb, ppp->active_filter) == 0))
 				ppp->last_recv = jiffies;
 			__skb_pull(skb, 2);
 		} else
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/ppp_mppe.c linux-libre-2.6.38-gnu1/drivers/net/ppp_mppe.c
--- linux-libre-2.6.37-gnu1/drivers/net/ppp_mppe.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/ppp_mppe.c	2011-03-14 21:20:32.000000000 -0400
@@ -55,6 +55,7 @@
 #include <linux/ppp_defs.h>
 #include <linux/ppp-comp.h>
 #include <linux/scatterlist.h>
+#include <asm/unaligned.h>
 
 #include "ppp_mppe.h"
 
@@ -395,16 +396,14 @@ mppe_compress(void *arg, unsigned char *
 	 */
 	obuf[0] = PPP_ADDRESS(ibuf);
 	obuf[1] = PPP_CONTROL(ibuf);
-	obuf[2] = PPP_COMP >> 8;	/* isize + MPPE_OVHD + 1 */
-	obuf[3] = PPP_COMP;	/* isize + MPPE_OVHD + 2 */
+	put_unaligned_be16(PPP_COMP, obuf + 2);
 	obuf += PPP_HDRLEN;
 
 	state->ccount = (state->ccount + 1) % MPPE_CCOUNT_SPACE;
 	if (state->debug >= 7)
 		printk(KERN_DEBUG "mppe_compress[%d]: ccount %d\n", state->unit,
 		       state->ccount);
-	obuf[0] = state->ccount >> 8;
-	obuf[1] = state->ccount & 0xff;
+	put_unaligned_be16(state->ccount, obuf);
 
 	if (!state->stateful ||	/* stateless mode     */
 	    ((state->ccount & 0xff) == 0xff) ||	/* "flag" packet      */
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/ppp_synctty.c linux-libre-2.6.38-gnu1/drivers/net/ppp_synctty.c
--- linux-libre-2.6.37-gnu1/drivers/net/ppp_synctty.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/ppp_synctty.c	2011-03-14 21:20:32.000000000 -0400
@@ -45,6 +45,7 @@
 #include <linux/completion.h>
 #include <linux/init.h>
 #include <linux/slab.h>
+#include <asm/unaligned.h>
 #include <asm/uaccess.h>
 
 #define PPP_VERSION	"2.4.2"
@@ -563,7 +564,7 @@ ppp_sync_txmunge(struct syncppp *ap, str
 	int islcp;
 
 	data  = skb->data;
-	proto = (data[0] << 8) + data[1];
+	proto = get_unaligned_be16(data);
 
 	/* LCP packets with codes between 1 (configure-request)
 	 * and 7 (code-reject) must be sent as though no options
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/pptp.c linux-libre-2.6.38-gnu1/drivers/net/pptp.c
--- linux-libre-2.6.37-gnu1/drivers/net/pptp.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/pptp.c	2011-03-14 21:20:32.000000000 -0400
@@ -277,7 +277,7 @@ static int pptp_xmit(struct ppp_channel
 	iph->tos      = 0;
 	iph->daddr    = rt->rt_dst;
 	iph->saddr    = rt->rt_src;
-	iph->ttl      = dst_metric(&rt->dst, RTAX_HOPLIMIT);
+	iph->ttl      = ip4_dst_hoplimit(&rt->dst);
 	iph->tot_len  = htons(skb->len);
 
 	skb_dst_drop(skb);
@@ -673,8 +673,7 @@ static int __init pptp_init_module(void)
 	int err = 0;
 	pr_info("PPTP driver version " PPTP_DRIVER_VERSION "\n");
 
-	callid_sock = __vmalloc((MAX_CALLID + 1) * sizeof(void *),
-		GFP_KERNEL | __GFP_ZERO, PAGE_KERNEL);
+	callid_sock = vzalloc((MAX_CALLID + 1) * sizeof(void *));
 	if (!callid_sock) {
 		pr_err("PPTP: cann't allocate memory\n");
 		return -ENOMEM;
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/pxa168_eth.c linux-libre-2.6.38-gnu1/drivers/net/pxa168_eth.c
--- linux-libre-2.6.37-gnu1/drivers/net/pxa168_eth.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/pxa168_eth.c	2011-03-14 21:20:32.000000000 -0400
@@ -1450,16 +1450,11 @@ static void pxa168_get_drvinfo(struct ne
 	strncpy(info->bus_info, "N/A", 32);
 }
 
-static u32 pxa168_get_link(struct net_device *dev)
-{
-	return !!netif_carrier_ok(dev);
-}
-
 static const struct ethtool_ops pxa168_ethtool_ops = {
 	.get_settings = pxa168_get_settings,
 	.set_settings = pxa168_set_settings,
 	.get_drvinfo = pxa168_get_drvinfo,
-	.get_link = pxa168_get_link,
+	.get_link = ethtool_op_get_link,
 };
 
 static const struct net_device_ops pxa168_eth_netdev_ops = {
@@ -1607,7 +1602,7 @@ static int pxa168_eth_remove(struct plat
 	mdiobus_unregister(pep->smi_bus);
 	mdiobus_free(pep->smi_bus);
 	unregister_netdev(dev);
-	flush_scheduled_work();
+	cancel_work_sync(&pep->tx_timeout_task);
 	free_netdev(dev);
 	platform_set_drvdata(pdev, NULL);
 	return 0;
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/qla3xxx.c linux-libre-2.6.38-gnu1/drivers/net/qla3xxx.c
--- linux-libre-2.6.37-gnu1/drivers/net/qla3xxx.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/qla3xxx.c	2011-03-14 21:20:32.000000000 -0400
@@ -2467,7 +2467,7 @@ map_error:
 static netdev_tx_t ql3xxx_send(struct sk_buff *skb,
 			       struct net_device *ndev)
 {
-	struct ql3_adapter *qdev = (struct ql3_adapter *)netdev_priv(ndev);
+	struct ql3_adapter *qdev = netdev_priv(ndev);
 	struct ql3xxx_port_registers __iomem *port_regs =
 			qdev->mem_map_registers;
 	struct ql_tx_buf_cb *tx_cb;
@@ -3390,7 +3390,7 @@ static void ql_set_mac_info(struct ql3_a
 
 static void ql_display_dev_info(struct net_device *ndev)
 {
-	struct ql3_adapter *qdev = (struct ql3_adapter *)netdev_priv(ndev);
+	struct ql3_adapter *qdev = netdev_priv(ndev);
 	struct pci_dev *pdev = qdev->pdev;
 
 	netdev_info(ndev,
@@ -3573,7 +3573,7 @@ static int ql3xxx_open(struct net_device
 
 static int ql3xxx_set_mac_address(struct net_device *ndev, void *p)
 {
-	struct ql3_adapter *qdev = (struct ql3_adapter *)netdev_priv(ndev);
+	struct ql3_adapter *qdev = netdev_priv(ndev);
 	struct ql3xxx_port_registers __iomem *port_regs =
 			qdev->mem_map_registers;
 	struct sockaddr *addr = p;
@@ -3608,7 +3608,7 @@ static int ql3xxx_set_mac_address(struct
 
 static void ql3xxx_tx_timeout(struct net_device *ndev)
 {
-	struct ql3_adapter *qdev = (struct ql3_adapter *)netdev_priv(ndev);
+	struct ql3_adapter *qdev = netdev_priv(ndev);
 
 	netdev_err(ndev, "Resetting...\n");
 	/*
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/qlcnic/qlcnic_ctx.c linux-libre-2.6.38-gnu1/drivers/net/qlcnic/qlcnic_ctx.c
--- linux-libre-2.6.37-gnu1/drivers/net/qlcnic/qlcnic_ctx.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/qlcnic/qlcnic_ctx.c	2011-03-14 21:20:32.000000000 -0400
@@ -1,25 +1,8 @@
 /*
- * Copyright (C) 2009 - QLogic 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; 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.
- *
- * The full GNU General Public License is included in this distribution
- * in the file called "COPYING".
+ * QLogic qlcnic NIC Driver
+ * Copyright (c)  2009-2010 QLogic Corporation
  *
+ * See LICENSE.qlcnic for copyright and licensing details.
  */
 
 #include "qlcnic.h"
@@ -480,6 +463,11 @@ int qlcnic_fw_create_ctx(struct qlcnic_a
 {
 	int err;
 
+	if (adapter->flags & QLCNIC_NEED_FLR) {
+		pci_reset_function(adapter->pdev);
+		adapter->flags &= ~QLCNIC_NEED_FLR;
+	}
+
 	err = qlcnic_fw_cmd_create_rx_ctx(adapter);
 	if (err)
 		return err;
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/qlcnic/qlcnic_ethtool.c linux-libre-2.6.38-gnu1/drivers/net/qlcnic/qlcnic_ethtool.c
--- linux-libre-2.6.37-gnu1/drivers/net/qlcnic/qlcnic_ethtool.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/qlcnic/qlcnic_ethtool.c	2011-03-14 21:20:32.000000000 -0400
@@ -1,25 +1,8 @@
 /*
- * Copyright (C) 2009 - QLogic 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; 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.
- *
- * The full GNU General Public License is included in this distribution
- * in the file called "COPYING".
+ * QLogic qlcnic NIC Driver
+ * Copyright (c)  2009-2010 QLogic Corporation
  *
+ * See LICENSE.qlcnic for copyright and licensing details.
  */
 
 #include <linux/types.h>
@@ -101,8 +84,7 @@ static const char qlcnic_device_gstrings
 static const char qlcnic_gstrings_test[][ETH_GSTRING_LEN] = {
 	"Register_Test_on_offline",
 	"Link_Test_on_offline",
-	"Interrupt_Test_offline",
-	"Loopback_Test_offline"
+	"Interrupt_Test_offline"
 };
 
 #define QLCNIC_TEST_LEN	ARRAY_SIZE(qlcnic_gstrings_test)
@@ -643,104 +625,6 @@ static int qlcnic_get_sset_count(struct
 	}
 }
 
-#define QLC_ILB_PKT_SIZE 64
-#define QLC_NUM_ILB_PKT	16
-#define QLC_ILB_MAX_RCV_LOOP 10
-
-static void qlcnic_create_loopback_buff(unsigned char *data)
-{
-	unsigned char random_data[] = {0xa8, 0x06, 0x45, 0x00};
-	memset(data, 0x4e, QLC_ILB_PKT_SIZE);
-	memset(data, 0xff, 12);
-	memcpy(data + 12, random_data, sizeof(random_data));
-}
-
-int qlcnic_check_loopback_buff(unsigned char *data)
-{
-	unsigned char buff[QLC_ILB_PKT_SIZE];
-	qlcnic_create_loopback_buff(buff);
-	return memcmp(data, buff, QLC_ILB_PKT_SIZE);
-}
-
-static int qlcnic_do_ilb_test(struct qlcnic_adapter *adapter)
-{
-	struct qlcnic_recv_context *recv_ctx = &adapter->recv_ctx;
-	struct qlcnic_host_sds_ring *sds_ring = &recv_ctx->sds_rings[0];
-	struct sk_buff *skb;
-	int i, loop, cnt = 0;
-
-	for (i = 0; i < QLC_NUM_ILB_PKT; i++) {
-		skb = dev_alloc_skb(QLC_ILB_PKT_SIZE);
-		qlcnic_create_loopback_buff(skb->data);
-		skb_put(skb, QLC_ILB_PKT_SIZE);
-
-		adapter->diag_cnt = 0;
-		qlcnic_xmit_frame(skb, adapter->netdev);
-
-		loop = 0;
-		do {
-			msleep(1);
-			qlcnic_process_rcv_ring_diag(sds_ring);
-		} while (loop++ < QLC_ILB_MAX_RCV_LOOP &&
-			 !adapter->diag_cnt);
-
-		dev_kfree_skb_any(skb);
-
-		if (!adapter->diag_cnt)
-			dev_warn(&adapter->pdev->dev, "ILB Test: %dth packet"
-				" not recevied\n", i + 1);
-		else
-			cnt++;
-	}
-	if (cnt != i) {
-		dev_warn(&adapter->pdev->dev, "ILB Test failed\n");
-		return -1;
-	}
-	return 0;
-}
-
-static int qlcnic_loopback_test(struct net_device *netdev)
-{
-	struct qlcnic_adapter *adapter = netdev_priv(netdev);
-	int max_sds_rings = adapter->max_sds_rings;
-	int ret;
-
-	if (adapter->op_mode == QLCNIC_NON_PRIV_FUNC) {
-		dev_warn(&adapter->pdev->dev, "Loopback test not supported"
-				"for non privilege function\n");
-		return 0;
-	}
-
-	if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state))
-		return -EIO;
-
-	if (qlcnic_request_quiscent_mode(adapter)) {
-		clear_bit(__QLCNIC_RESETTING, &adapter->state);
-		return -EIO;
-	}
-
-	ret = qlcnic_diag_alloc_res(netdev, QLCNIC_LOOPBACK_TEST);
-	if (ret)
-		goto clear_it;
-
-	ret = qlcnic_set_ilb_mode(adapter);
-	if (ret)
-		goto done;
-
-	ret = qlcnic_do_ilb_test(adapter);
-
-	qlcnic_clear_ilb_mode(adapter);
-
-done:
-	qlcnic_diag_free_res(netdev, max_sds_rings);
-
-clear_it:
-	qlcnic_clear_quiscent_mode(adapter);
-	adapter->max_sds_rings = max_sds_rings;
-	clear_bit(__QLCNIC_RESETTING, &adapter->state);
-	return ret;
-}
-
 static int qlcnic_irq_test(struct net_device *netdev)
 {
 	struct qlcnic_adapter *adapter = netdev_priv(netdev);
@@ -788,14 +672,11 @@ qlcnic_diag_test(struct net_device *dev,
 	if (data[1])
 		eth_test->flags |= ETH_TEST_FL_FAILED;
 
-	if (eth_test->flags == ETH_TEST_FL_OFFLINE) {
+	if (eth_test->flags & ETH_TEST_FL_OFFLINE) {
 		data[2] = qlcnic_irq_test(dev);
 		if (data[2])
 			eth_test->flags |= ETH_TEST_FL_FAILED;
 
-		data[3] = qlcnic_loopback_test(dev);
-		if (data[3])
-			eth_test->flags |= ETH_TEST_FL_FAILED;
 
 	}
 }
@@ -925,9 +806,10 @@ static int qlcnic_set_rx_csum(struct net
 
 		dev->features &= ~NETIF_F_LRO;
 		qlcnic_send_lro_cleanup(adapter);
+		dev_info(&adapter->pdev->dev,
+					"disabling LRO as rx_csum is off\n");
 	}
 	adapter->rx_csum = !!data;
-	dev_info(&adapter->pdev->dev, "disabling LRO as rx_csum is off\n");
 	return 0;
 }
 
@@ -952,16 +834,27 @@ static int qlcnic_set_tso(struct net_dev
 static int qlcnic_blink_led(struct net_device *dev, u32 val)
 {
 	struct qlcnic_adapter *adapter = netdev_priv(dev);
+	int max_sds_rings = adapter->max_sds_rings;
+	int dev_down = 0;
 	int ret;
 
-	if (!test_bit(__QLCNIC_DEV_UP, &adapter->state))
-		return -EIO;
+	if (!test_bit(__QLCNIC_DEV_UP, &adapter->state)) {
+		dev_down = 1;
+		if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state))
+			return -EIO;
+
+		ret = qlcnic_diag_alloc_res(dev, QLCNIC_LED_TEST);
+		if (ret) {
+			clear_bit(__QLCNIC_RESETTING, &adapter->state);
+			return ret;
+		}
+	}
 
 	ret = adapter->nic_ops->config_led(adapter, 1, 0xf);
 	if (ret) {
 		dev_err(&adapter->pdev->dev,
 			"Failed to set LED blink state.\n");
-		return ret;
+		goto done;
 	}
 
 	msleep_interruptible(val * 1000);
@@ -970,10 +863,16 @@ static int qlcnic_blink_led(struct net_d
 	if (ret) {
 		dev_err(&adapter->pdev->dev,
 			"Failed to reset LED blink state.\n");
-		return ret;
+		goto done;
 	}
 
-	return 0;
+done:
+	if (dev_down) {
+		qlcnic_diag_free_res(dev, max_sds_rings);
+		clear_bit(__QLCNIC_RESETTING, &adapter->state);
+	}
+	return ret;
+
 }
 
 static void
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/qlcnic/qlcnic.h linux-libre-2.6.38-gnu1/drivers/net/qlcnic/qlcnic.h
--- linux-libre-2.6.37-gnu1/drivers/net/qlcnic/qlcnic.h	2013-05-03 03:58:46.000000000 -0400
+++ linux-libre-2.6.38-gnu1/drivers/net/qlcnic/qlcnic.h	2013-05-03 01:58:55.000000000 -0400
@@ -1,25 +1,8 @@
 /*
- * Copyright (C) 2009 - QLogic 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; 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.
- *
- * The full GNU General Public License is included in this distribution
- * in the file called "COPYING".
+ * QLogic qlcnic NIC Driver
+ * Copyright (c)  2009-2010 QLogic Corporation
  *
+ * See LICENSE.qlcnic for copyright and licensing details.
  */
 
 #ifndef _QLCNIC_H_
@@ -51,8 +34,8 @@
 
 #define _QLCNIC_LINUX_MAJOR 5
 #define _QLCNIC_LINUX_MINOR 0
-#define _QLCNIC_LINUX_SUBVERSION 11
-#define QLCNIC_LINUX_VERSIONID  "5.0.11"
+#define _QLCNIC_LINUX_SUBVERSION 15
+#define QLCNIC_LINUX_VERSIONID  "5.0.15"
 #define QLCNIC_DRV_IDC_VER  0x01
 #define QLCNIC_DRIVER_VERSION  ((_QLCNIC_LINUX_MAJOR << 16) |\
 		 (_QLCNIC_LINUX_MINOR << 8) | (_QLCNIC_LINUX_SUBVERSION))
@@ -306,6 +289,26 @@ struct uni_data_desc{
 	u32	reserved[5];
 };
 
+/* Flash Defines and Structures */
+#define QLCNIC_FLT_LOCATION	0x3F1000
+#define QLCNIC_FW_IMAGE_REGION	0x74
+struct qlcnic_flt_header {
+	u16 version;
+	u16 len;
+	u16 checksum;
+	u16 reserved;
+};
+
+struct qlcnic_flt_entry {
+	u8 region;
+	u8 reserved0;
+	u8 attrib;
+	u8 reserved1;
+	u32 size;
+	u32 start_addr;
+	u32 end_add;
+};
+
 /* Magic number to let user know flash is programmed */
 #define	QLCNIC_BDINFO_MAGIC 0x12345678
 
@@ -798,7 +801,6 @@ struct qlcnic_nic_intr_coalesce {
 #define QLCNIC_H2C_OPCODE_GET_NET_STATS 		16
 #define QLCNIC_H2C_OPCODE_PROXY_UPDATE_P2V		17
 #define QLCNIC_H2C_OPCODE_CONFIG_IPADDR 		18
-#define QLCNIC_H2C_OPCODE_CONFIG_LOOPBACK		19
 #define QLCNIC_H2C_OPCODE_PROXY_STOP_DONE		20
 #define QLCNIC_H2C_OPCODE_GET_LINKEVENT 		21
 #define QLCNIC_C2C_OPCODE				22
@@ -923,6 +925,7 @@ struct qlcnic_ipaddr {
 #define QLCNIC_MACSPOOF			0x200
 #define QLCNIC_MAC_OVERRIDE_DISABLED	0x400
 #define QLCNIC_PROMISC_DISABLED		0x800
+#define QLCNIC_NEED_FLR			0x1000
 #define QLCNIC_IS_MSI_FAMILY(adapter) \
 	((adapter)->flags & (QLCNIC_MSI_ENABLED | QLCNIC_MSIX_ENABLED))
 
@@ -942,6 +945,7 @@ struct qlcnic_ipaddr {
 
 #define QLCNIC_INTERRUPT_TEST		1
 #define QLCNIC_LOOPBACK_TEST		2
+#define QLCNIC_LED_TEST		3
 
 #define QLCNIC_FILTER_AGE	80
 #define QLCNIC_READD_AGE	20
@@ -1126,8 +1130,7 @@ struct qlcnic_eswitch {
 /* Return codes for Error handling */
 #define QL_STATUS_INVALID_PARAM	-1
 
-#define MAX_BW			100
-#define MIN_BW			1
+#define MAX_BW			100	/* % of link speed */
 #define MAX_VLAN_ID		4095
 #define MIN_VLAN_ID		2
 #define MAX_TX_QUEUES		1
@@ -1135,7 +1138,7 @@ struct qlcnic_eswitch {
 #define DEFAULT_MAC_LEARN	1
 
 #define IS_VALID_VLAN(vlan)	(vlan >= MIN_VLAN_ID && vlan < MAX_VLAN_ID)
-#define IS_VALID_BW(bw)		(bw >= MIN_BW && bw <= MAX_BW)
+#define IS_VALID_BW(bw)		(bw <= MAX_BW)
 #define IS_VALID_TX_QUEUES(que)	(que > 0 && que <= MAX_TX_QUEUES)
 #define IS_VALID_RX_QUEUES(que)	(que > 0 && que <= MAX_RX_QUEUES)
 
@@ -1314,21 +1317,15 @@ int qlcnic_config_bridged_mode(struct ql
 int qlcnic_send_lro_cleanup(struct qlcnic_adapter *adapter);
 void qlcnic_update_cmd_producer(struct qlcnic_adapter *adapter,
 		struct qlcnic_host_tx_ring *tx_ring);
-void qlcnic_clear_ilb_mode(struct qlcnic_adapter *adapter);
-int qlcnic_set_ilb_mode(struct qlcnic_adapter *adapter);
 void qlcnic_fetch_mac(struct qlcnic_adapter *, u32, u32, u8, u8 *);
 
 /* Functions from qlcnic_main.c */
-int qlcnic_request_quiscent_mode(struct qlcnic_adapter *adapter);
-void qlcnic_clear_quiscent_mode(struct qlcnic_adapter *adapter);
 int qlcnic_reset_context(struct qlcnic_adapter *);
 u32 qlcnic_issue_cmd(struct qlcnic_adapter *adapter,
 	u32 pci_fn, u32 version, u32 arg1, u32 arg2, u32 arg3, u32 cmd);
 void qlcnic_diag_free_res(struct net_device *netdev, int max_sds_rings);
 int qlcnic_diag_alloc_res(struct net_device *netdev, int test);
-int qlcnic_check_loopback_buff(unsigned char *data);
 netdev_tx_t qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev);
-void qlcnic_process_rcv_ring_diag(struct qlcnic_host_sds_ring *sds_ring);
 
 /* Management functions */
 int qlcnic_get_mac_address(struct qlcnic_adapter *, u8*);
@@ -1377,6 +1374,8 @@ static const struct qlcnic_brdinfo qlcni
 		"3200 Series Single Port 10Gb Intelligent Ethernet Adapter"},
 	{0x1077, 0x8020, 0x103c, 0x3733,
 		"NC523SFP 10Gb 2-port Server Adapter"},
+	{0x1077, 0x8020, 0x103c, 0x3346,
+		"CN1000Q Dual Port Converged Network Adapter"},
 	{0x1077, 0x8020, 0x0, 0x0, "cLOM8214 1/10GbE Controller"},
 };
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/qlcnic/qlcnic_hdr.h linux-libre-2.6.38-gnu1/drivers/net/qlcnic/qlcnic_hdr.h
--- linux-libre-2.6.37-gnu1/drivers/net/qlcnic/qlcnic_hdr.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/qlcnic/qlcnic_hdr.h	2011-03-14 21:20:32.000000000 -0400
@@ -1,25 +1,8 @@
 /*
- * Copyright (C) 2009 - QLogic 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; 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.
- *
- * The full GNU General Public License is included in this distribution
- * in the file called "COPYING".
+ * QLogic qlcnic NIC Driver
+ * Copyright (c)  2009-2010 QLogic Corporation
  *
+ * See LICENSE.qlcnic for copyright and licensing details.
  */
 
 #ifndef __QLCNIC_HDR_H_
@@ -638,7 +621,7 @@ enum {
 #define PCIX_INT_MASK		(0x10104)
 
 #define PCIX_OCM_WINDOW		(0x10800)
-#define PCIX_OCM_WINDOW_REG(func)	(PCIX_OCM_WINDOW + 0x20 * (func))
+#define PCIX_OCM_WINDOW_REG(func)	(PCIX_OCM_WINDOW + 0x4 * (func))
 
 #define PCIX_TARGET_STATUS	(0x10118)
 #define PCIX_TARGET_STATUS_F1	(0x10160)
@@ -722,7 +705,7 @@ enum {
 #define QLCNIC_DEV_NPAR_OPER		1 /* NPAR Operational */
 #define QLCNIC_DEV_NPAR_OPER_TIMEO	30 /* Operational time out */
 
-#define QLC_DEV_CHECK_ACTIVE(VAL, FN)		((VAL) &= (1 << (FN * 4)))
+#define QLC_DEV_CHECK_ACTIVE(VAL, FN)		((VAL) & (1 << (FN * 4)))
 #define QLC_DEV_SET_REF_CNT(VAL, FN)		((VAL) |= (1 << (FN * 4)))
 #define QLC_DEV_CLR_REF_CNT(VAL, FN)		((VAL) &= ~(1 << (FN * 4)))
 #define QLC_DEV_SET_RST_RDY(VAL, FN)		((VAL) |= (1 << (FN * 4)))
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/qlcnic/qlcnic_hw.c linux-libre-2.6.38-gnu1/drivers/net/qlcnic/qlcnic_hw.c
--- linux-libre-2.6.37-gnu1/drivers/net/qlcnic/qlcnic_hw.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/qlcnic/qlcnic_hw.c	2011-03-14 21:20:32.000000000 -0400
@@ -1,25 +1,8 @@
 /*
- * Copyright (C) 2009 - QLogic 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; 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.
- *
- * The full GNU General Public License is included in this distribution
- * in the file called "COPYING".
+ * QLogic qlcnic NIC Driver
+ * Copyright (c)  2009-2010 QLogic Corporation
  *
+ * See LICENSE.qlcnic for copyright and licensing details.
  */
 
 #include "qlcnic.h"
@@ -398,7 +381,7 @@ qlcnic_sre_macaddr_change(struct qlcnic_
 	return qlcnic_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1);
 }
 
-static int qlcnic_nic_add_mac(struct qlcnic_adapter *adapter, u8 *addr)
+static int qlcnic_nic_add_mac(struct qlcnic_adapter *adapter, const u8 *addr)
 {
 	struct list_head *head;
 	struct qlcnic_mac_list_s *cur;
@@ -432,7 +415,9 @@ void qlcnic_set_multi(struct net_device
 {
 	struct qlcnic_adapter *adapter = netdev_priv(netdev);
 	struct netdev_hw_addr *ha;
-	u8 bcast_addr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+	static const u8 bcast_addr[ETH_ALEN] = {
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff
+	};
 	u32 mode = VPORT_MISS_MODE_DROP;
 
 	if (!test_bit(__QLCNIC_FW_ATTACHED, &adapter->state))
@@ -638,10 +623,11 @@ int qlcnic_config_rss(struct qlcnic_adap
 	u64 word;
 	int i, rv;
 
-	const u64 key[] = { 0xbeac01fa6a42b73bULL, 0x8030f20c77cb2da3ULL,
-			0xae7b30b4d0ca2bcbULL, 0x43a38fb04167253dULL,
-			0x255b0ec26d5a56daULL };
-
+	static const u64 key[] = {
+		0xbeac01fa6a42b73bULL, 0x8030f20c77cb2da3ULL,
+		0xae7b30b4d0ca2bcbULL, 0x43a38fb04167253dULL,
+		0x255b0ec26d5a56daULL
+	};
 
 	memset(&req, 0, sizeof(struct qlcnic_nic_req));
 	req.qhdr = cpu_to_le64(QLCNIC_HOST_REQUEST << 23);
@@ -1234,56 +1220,3 @@ int qlcnic_config_led(struct qlcnic_adap
 
 	return rv;
 }
-
-static int qlcnic_set_fw_loopback(struct qlcnic_adapter *adapter, u32 flag)
-{
-	struct qlcnic_nic_req	req;
-	int			rv;
-	u64			word;
-
-	memset(&req, 0, sizeof(struct qlcnic_nic_req));
-	req.qhdr = cpu_to_le64(QLCNIC_HOST_REQUEST << 23);
-
-	word = QLCNIC_H2C_OPCODE_CONFIG_LOOPBACK |
-			((u64)adapter->portnum << 16);
-	req.req_hdr = cpu_to_le64(word);
-	req.words[0] = cpu_to_le64(flag);
-
-	rv = qlcnic_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1);
-	if (rv)
-		dev_err(&adapter->pdev->dev,
-			"%sting loopback mode failed.\n",
-					flag ? "Set" : "Reset");
-	return rv;
-}
-
-int qlcnic_set_ilb_mode(struct qlcnic_adapter *adapter)
-{
-	if (qlcnic_set_fw_loopback(adapter, 1))
-		return -EIO;
-
-	if (qlcnic_nic_set_promisc(adapter,
-				VPORT_MISS_MODE_ACCEPT_ALL)) {
-		qlcnic_set_fw_loopback(adapter, 0);
-		return -EIO;
-	}
-
-	msleep(1000);
-	return 0;
-}
-
-void qlcnic_clear_ilb_mode(struct qlcnic_adapter *adapter)
-{
-	int mode = VPORT_MISS_MODE_DROP;
-	struct net_device *netdev = adapter->netdev;
-
-	qlcnic_set_fw_loopback(adapter, 0);
-
-	if (netdev->flags & IFF_PROMISC)
-		mode = VPORT_MISS_MODE_ACCEPT_ALL;
-	else if (netdev->flags & IFF_ALLMULTI)
-		mode = VPORT_MISS_MODE_ACCEPT_MULTI;
-
-	qlcnic_nic_set_promisc(adapter, mode);
-	msleep(1000);
-}
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/qlcnic/qlcnic_init.c linux-libre-2.6.38-gnu1/drivers/net/qlcnic/qlcnic_init.c
--- linux-libre-2.6.37-gnu1/drivers/net/qlcnic/qlcnic_init.c	2013-05-03 03:58:44.000000000 -0400
+++ linux-libre-2.6.38-gnu1/drivers/net/qlcnic/qlcnic_init.c	2013-05-03 01:58:52.000000000 -0400
@@ -1,25 +1,8 @@
 /*
- * Copyright (C) 2009 - QLogic 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; 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.
- *
- * The full GNU General Public License is included in this distribution
- * in the file called "COPYING".
+ * QLogic qlcnic NIC Driver
+ * Copyright (c)  2009-2010 QLogic Corporation
  *
+ * See LICENSE.qlcnic for copyright and licensing details.
  */
 
 #include <linux/netdevice.h>
@@ -236,12 +219,11 @@ int qlcnic_alloc_sw_resources(struct qlc
 	tx_ring->num_desc = adapter->num_txd;
 	tx_ring->txq = netdev_get_tx_queue(netdev, 0);
 
-	cmd_buf_arr = vmalloc(TX_BUFF_RINGSIZE(tx_ring));
+	cmd_buf_arr = vzalloc(TX_BUFF_RINGSIZE(tx_ring));
 	if (cmd_buf_arr == NULL) {
 		dev_err(&netdev->dev, "failed to allocate cmd buffer ring\n");
 		goto err_out;
 	}
-	memset(cmd_buf_arr, 0, TX_BUFF_RINGSIZE(tx_ring));
 	tx_ring->cmd_buf_arr = cmd_buf_arr;
 
 	recv_ctx = &adapter->recv_ctx;
@@ -275,14 +257,12 @@ int qlcnic_alloc_sw_resources(struct qlc
 				rds_ring->dma_size + NET_IP_ALIGN;
 			break;
 		}
-		rds_ring->rx_buf_arr = (struct qlcnic_rx_buffer *)
-			vmalloc(RCV_BUFF_RINGSIZE(rds_ring));
+		rds_ring->rx_buf_arr = vzalloc(RCV_BUFF_RINGSIZE(rds_ring));
 		if (rds_ring->rx_buf_arr == NULL) {
 			dev_err(&netdev->dev, "Failed to allocate "
 				"rx buffer ring %d\n", ring);
 			goto err_out;
 		}
-		memset(rds_ring->rx_buf_arr, 0, RCV_BUFF_RINGSIZE(rds_ring));
 		INIT_LIST_HEAD(&rds_ring->free_list);
 		/*
 		 * Now go through all of them, set reference handles
@@ -647,12 +627,73 @@ qlcnic_setup_idc_param(struct qlcnic_ada
 	return 0;
 }
 
+static int qlcnic_get_flt_entry(struct qlcnic_adapter *adapter, u8 region,
+				struct qlcnic_flt_entry *region_entry)
+{
+	struct qlcnic_flt_header flt_hdr;
+	struct qlcnic_flt_entry *flt_entry;
+	int i = 0, ret;
+	u32 entry_size;
+
+	memset(region_entry, 0, sizeof(struct qlcnic_flt_entry));
+	ret = qlcnic_rom_fast_read_words(adapter, QLCNIC_FLT_LOCATION,
+					 (u8 *)&flt_hdr,
+					 sizeof(struct qlcnic_flt_header));
+	if (ret) {
+		dev_warn(&adapter->pdev->dev,
+			 "error reading flash layout header\n");
+		return -EIO;
+	}
+
+	entry_size = flt_hdr.len - sizeof(struct qlcnic_flt_header);
+	flt_entry = (struct qlcnic_flt_entry *)vzalloc(entry_size);
+	if (flt_entry == NULL) {
+		dev_warn(&adapter->pdev->dev, "error allocating memory\n");
+		return -EIO;
+	}
+
+	ret = qlcnic_rom_fast_read_words(adapter, QLCNIC_FLT_LOCATION +
+					 sizeof(struct qlcnic_flt_header),
+					 (u8 *)flt_entry, entry_size);
+	if (ret) {
+		dev_warn(&adapter->pdev->dev,
+			 "error reading flash layout entries\n");
+		goto err_out;
+	}
+
+	while (i < (entry_size/sizeof(struct qlcnic_flt_entry))) {
+		if (flt_entry[i].region == region)
+			break;
+		i++;
+	}
+	if (i >= (entry_size/sizeof(struct qlcnic_flt_entry))) {
+		dev_warn(&adapter->pdev->dev,
+			 "region=%x not found in %d regions\n", region, i);
+		ret = -EIO;
+		goto err_out;
+	}
+	memcpy(region_entry, &flt_entry[i], sizeof(struct qlcnic_flt_entry));
+
+err_out:
+	vfree(flt_entry);
+	return ret;
+}
+
 int
 qlcnic_check_flash_fw_ver(struct qlcnic_adapter *adapter)
 {
+	struct qlcnic_flt_entry fw_entry;
 	u32 ver = -1, min_ver;
+	int ret;
 
-	qlcnic_rom_fast_read(adapter, QLCNIC_FW_VERSION_OFFSET, (int *)&ver);
+	ret = qlcnic_get_flt_entry(adapter, QLCNIC_FW_IMAGE_REGION, &fw_entry);
+	if (!ret)
+		/* 0-4:-signature,  4-8:-fw version */
+		qlcnic_rom_fast_read(adapter, fw_entry.start_addr + 4,
+				     (int *)&ver);
+	else
+		qlcnic_rom_fast_read(adapter, QLCNIC_FW_VERSION_OFFSET,
+				     (int *)&ver);
 
 	ver = QLCNIC_DECODE_VERSION(ver);
 	min_ver = QLCNIC_MIN_FW_VERSION;
@@ -1693,99 +1734,6 @@ qlcnic_post_rx_buffers_nodb(struct qlcni
 	spin_unlock(&rds_ring->lock);
 }
 
-static void dump_skb(struct sk_buff *skb)
-{
-	int i;
-	unsigned char *data = skb->data;
-
-	for (i = 0; i < skb->len; i++) {
-		printk("%02x ", data[i]);
-		if ((i & 0x0f) == 8)
-			printk("\n");
-	}
-}
-
-static struct qlcnic_rx_buffer *
-qlcnic_process_rcv_diag(struct qlcnic_adapter *adapter,
-		struct qlcnic_host_sds_ring *sds_ring,
-		int ring, u64 sts_data0)
-{
-	struct qlcnic_recv_context *recv_ctx = &adapter->recv_ctx;
-	struct qlcnic_rx_buffer *buffer;
-	struct sk_buff *skb;
-	struct qlcnic_host_rds_ring *rds_ring;
-	int index, length, cksum, pkt_offset;
-
-	if (unlikely(ring >= adapter->max_rds_rings))
-		return NULL;
-
-	rds_ring = &recv_ctx->rds_rings[ring];
-
-	index = qlcnic_get_sts_refhandle(sts_data0);
-	if (unlikely(index >= rds_ring->num_desc))
-		return NULL;
-
-	buffer = &rds_ring->rx_buf_arr[index];
-
-	length = qlcnic_get_sts_totallength(sts_data0);
-	cksum  = qlcnic_get_sts_status(sts_data0);
-	pkt_offset = qlcnic_get_sts_pkt_offset(sts_data0);
-
-	skb = qlcnic_process_rxbuf(adapter, rds_ring, index, cksum);
-	if (!skb)
-		return buffer;
-
-	if (length > rds_ring->skb_size)
-		skb_put(skb, rds_ring->skb_size);
-	else
-		skb_put(skb, length);
-
-	if (pkt_offset)
-		skb_pull(skb, pkt_offset);
-
-	if (!qlcnic_check_loopback_buff(skb->data))
-		adapter->diag_cnt++;
-	else
-		dump_skb(skb);
-
-	dev_kfree_skb_any(skb);
-	adapter->stats.rx_pkts++;
-	adapter->stats.rxbytes += length;
-
-	return buffer;
-}
-
-void
-qlcnic_process_rcv_ring_diag(struct qlcnic_host_sds_ring *sds_ring)
-{
-	struct qlcnic_adapter *adapter = sds_ring->adapter;
-	struct status_desc *desc;
-	struct qlcnic_rx_buffer *rxbuf;
-	u64 sts_data0;
-
-	int opcode, ring, desc_cnt;
-	u32 consumer = sds_ring->consumer;
-
-	desc = &sds_ring->desc_head[consumer];
-	sts_data0 = le64_to_cpu(desc->status_desc_data[0]);
-
-	if (!(sts_data0 & STATUS_OWNER_HOST))
-		return;
-
-	desc_cnt = qlcnic_get_sts_desc_cnt(sts_data0);
-	opcode = qlcnic_get_sts_opcode(sts_data0);
-
-	ring = qlcnic_get_sts_type(sts_data0);
-	rxbuf = qlcnic_process_rcv_diag(adapter, sds_ring,
-					ring, sts_data0);
-
-	desc->status_desc_data[0] = cpu_to_le64(STATUS_OWNER_PHANTOM);
-	consumer = get_next_index(consumer, sds_ring->num_desc);
-
-	sds_ring->consumer = consumer;
-	writel(consumer, sds_ring->crb_sts_consumer);
-}
-
 void
 qlcnic_fetch_mac(struct qlcnic_adapter *adapter, u32 off1, u32 off2,
 			u8 alt_mac, u8 *mac)
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/qlcnic/qlcnic_main.c linux-libre-2.6.38-gnu1/drivers/net/qlcnic/qlcnic_main.c
--- linux-libre-2.6.37-gnu1/drivers/net/qlcnic/qlcnic_main.c	2013-05-03 03:58:50.000000000 -0400
+++ linux-libre-2.6.38-gnu1/drivers/net/qlcnic/qlcnic_main.c	2013-05-03 01:58:59.000000000 -0400
@@ -1,25 +1,8 @@
 /*
- * Copyright (C) 2009 - QLogic 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; 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.
- *
- * The full GNU General Public License is included in this distribution
- * in the file called "COPYING".
+ * QLogic qlcnic NIC Driver
+ * Copyright (c)  2009-2010 QLogic Corporation
  *
+ * See LICENSE.qlcnic for copyright and licensing details.
  */
 
 #include <linux/slab.h>
@@ -48,15 +31,15 @@ static const char qlcnic_driver_string[]
 
 static struct workqueue_struct *qlcnic_wq;
 static int qlcnic_mac_learn;
-module_param(qlcnic_mac_learn, int, 0644);
+module_param(qlcnic_mac_learn, int, 0444);
 MODULE_PARM_DESC(qlcnic_mac_learn, "Mac Filter (0=disabled, 1=enabled)");
 
 static int use_msi = 1;
-module_param(use_msi, int, 0644);
+module_param(use_msi, int, 0444);
 MODULE_PARM_DESC(use_msi, "MSI interrupt (0=disabled, 1=enabled");
 
 static int use_msi_x = 1;
-module_param(use_msi_x, int, 0644);
+module_param(use_msi_x, int, 0444);
 MODULE_PARM_DESC(use_msi_x, "MSI-X interrupt (0=disabled, 1=enabled");
 
 static int auto_fw_reset = AUTO_FW_RESET_ENABLED;
@@ -64,11 +47,11 @@ module_param(auto_fw_reset, int, 0644);
 MODULE_PARM_DESC(auto_fw_reset, "Auto firmware reset (0=disabled, 1=enabled");
 
 static int load_fw_file;
-module_param(load_fw_file, int, 0644);
+module_param(load_fw_file, int, 0444);
 MODULE_PARM_DESC(load_fw_file, "Load firmware from (0=flash, 1=file");
 
 static int qlcnic_config_npars;
-module_param(qlcnic_config_npars, int, 0644);
+module_param(qlcnic_config_npars, int, 0444);
 MODULE_PARM_DESC(qlcnic_config_npars, "Configure NPARs (0=disabled, 1=enabled");
 
 static int __devinit qlcnic_probe(struct pci_dev *pdev,
@@ -1546,6 +1529,8 @@ qlcnic_probe(struct pci_dev *pdev, const
 	if (err)
 		goto err_out_iounmap;
 
+	adapter->flags |= QLCNIC_NEED_FLR;
+
 	err = adapter->nic_ops->start_firmware(adapter);
 	if (err) {
 		dev_err(&pdev->dev, "Loading fw failed.Please Reboot\n");
@@ -2854,61 +2839,6 @@ qlcnic_set_npar_non_operational(struct q
 	qlcnic_api_unlock(adapter);
 }
 
-/* Caller should held RESETTING bit.
- * This should be call in sync with qlcnic_request_quiscent_mode.
- */
-void qlcnic_clear_quiscent_mode(struct qlcnic_adapter *adapter)
-{
-	qlcnic_clr_drv_state(adapter);
-	qlcnic_api_lock(adapter);
-	QLCWR32(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_READY);
-	qlcnic_api_unlock(adapter);
-}
-
-/* Caller should held RESETTING bit.
- */
-int qlcnic_request_quiscent_mode(struct qlcnic_adapter *adapter)
-{
-	u8 timeo = adapter->dev_init_timeo / 2;
-	u32 state;
-
-	if (qlcnic_api_lock(adapter))
-		return -EIO;
-
-	state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE);
-	if (state != QLCNIC_DEV_READY)
-		return -EIO;
-
-	QLCWR32(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_NEED_QUISCENT);
-	qlcnic_api_unlock(adapter);
-	QLCDB(adapter, DRV, "NEED QUISCENT state set\n");
-	qlcnic_idc_debug_info(adapter, 0);
-
-	qlcnic_set_drv_state(adapter, QLCNIC_DEV_NEED_QUISCENT);
-
-	do {
-		msleep(2000);
-		state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE);
-		if (state == QLCNIC_DEV_QUISCENT)
-			return 0;
-		if (!qlcnic_check_drv_state(adapter)) {
-			if (qlcnic_api_lock(adapter))
-				return -EIO;
-			QLCWR32(adapter, QLCNIC_CRB_DEV_STATE,
-							QLCNIC_DEV_QUISCENT);
-			qlcnic_api_unlock(adapter);
-			QLCDB(adapter, DRV, "QUISCENT mode set\n");
-			return 0;
-		}
-	} while (--timeo);
-
-	dev_err(&adapter->pdev->dev, "Failed to quiesce device, DRV_STATE=%08x"
-		" DRV_ACTIVE=%08x\n", QLCRD32(adapter, QLCNIC_CRB_DRV_STATE),
-		QLCRD32(adapter, QLCNIC_CRB_DRV_ACTIVE));
-	qlcnic_clear_quiscent_mode(adapter);
-	return -EIO;
-}
-
 /*Transit to RESET state from READY state only */
 static void
 qlcnic_dev_request_reset(struct qlcnic_adapter *adapter)
@@ -3587,9 +3517,12 @@ validate_esw_config(struct qlcnic_adapte
 		case QLCNIC_PORT_DEFAULTS:
 			if (QLC_DEV_GET_DRV(op_mode, pci_func) !=
 						QLCNIC_NON_PRIV_FUNC) {
-				esw_cfg[i].mac_anti_spoof = 0;
-				esw_cfg[i].mac_override = 1;
-				esw_cfg[i].promisc_mode = 1;
+				if (esw_cfg[i].mac_anti_spoof != 0)
+					return QL_STATUS_INVALID_PARAM;
+				if (esw_cfg[i].mac_override != 1)
+					return QL_STATUS_INVALID_PARAM;
+				if (esw_cfg[i].promisc_mode != 1)
+					return QL_STATUS_INVALID_PARAM;
 			}
 			break;
 		case QLCNIC_ADD_VLAN:
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/qlge/qlge_dbg.c linux-libre-2.6.38-gnu1/drivers/net/qlge/qlge_dbg.c
--- linux-libre-2.6.37-gnu1/drivers/net/qlge/qlge_dbg.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/qlge/qlge_dbg.c	2011-03-14 21:20:32.000000000 -0400
@@ -1317,9 +1317,28 @@ void ql_gen_reg_dump(struct ql_adapter *
 	status = ql_get_ets_regs(qdev, &mpi_coredump->ets[0]);
 	if (status)
 		return;
+}
 
-	if (test_bit(QL_FRC_COREDUMP, &qdev->flags))
+void ql_get_dump(struct ql_adapter *qdev, void *buff)
+{
+	/*
+	 * If the dump has already been taken and is stored
+	 * in our internal buffer and if force dump is set then
+	 * just start the spool to dump it to the log file
+	 * and also, take a snapshot of the general regs to
+	 * to the user's buffer or else take complete dump
+	 * to the user's buffer if force is not set.
+	 */
+
+	if (!test_bit(QL_FRC_COREDUMP, &qdev->flags)) {
+		if (!ql_core_dump(qdev, buff))
+			ql_soft_reset_mpi_risc(qdev);
+		else
+			netif_err(qdev, drv, qdev->ndev, "coredump failed!\n");
+	} else {
+		ql_gen_reg_dump(qdev, buff);
 		ql_get_core_dump(qdev);
+	}
 }
 
 /* Coredump to messages log file using separate worker thread */
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/qlge/qlge_ethtool.c linux-libre-2.6.38-gnu1/drivers/net/qlge/qlge_ethtool.c
--- linux-libre-2.6.37-gnu1/drivers/net/qlge/qlge_ethtool.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/qlge/qlge_ethtool.c	2011-03-14 21:20:32.000000000 -0400
@@ -375,7 +375,10 @@ static void ql_get_drvinfo(struct net_de
 	strncpy(drvinfo->bus_info, pci_name(qdev->pdev), 32);
 	drvinfo->n_stats = 0;
 	drvinfo->testinfo_len = 0;
-	drvinfo->regdump_len = 0;
+	if (!test_bit(QL_FRC_COREDUMP, &qdev->flags))
+		drvinfo->regdump_len = sizeof(struct ql_mpi_coredump);
+	else
+		drvinfo->regdump_len = sizeof(struct ql_reg_dump);
 	drvinfo->eedump_len = 0;
 }
 
@@ -547,7 +550,12 @@ static void ql_self_test(struct net_devi
 
 static int ql_get_regs_len(struct net_device *ndev)
 {
-	return sizeof(struct ql_reg_dump);
+	struct ql_adapter *qdev = netdev_priv(ndev);
+
+	if (!test_bit(QL_FRC_COREDUMP, &qdev->flags))
+		return sizeof(struct ql_mpi_coredump);
+	else
+		return sizeof(struct ql_reg_dump);
 }
 
 static void ql_get_regs(struct net_device *ndev,
@@ -555,7 +563,12 @@ static void ql_get_regs(struct net_devic
 {
 	struct ql_adapter *qdev = netdev_priv(ndev);
 
-	ql_gen_reg_dump(qdev, p);
+	ql_get_dump(qdev, p);
+	qdev->core_is_dumped = 0;
+	if (!test_bit(QL_FRC_COREDUMP, &qdev->flags))
+		regs->len = sizeof(struct ql_mpi_coredump);
+	else
+		regs->len = sizeof(struct ql_reg_dump);
 }
 
 static int ql_get_coalesce(struct net_device *dev, struct ethtool_coalesce *c)
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/qlge/qlge.h linux-libre-2.6.38-gnu1/drivers/net/qlge/qlge.h
--- linux-libre-2.6.37-gnu1/drivers/net/qlge/qlge.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/qlge/qlge.h	2011-03-14 21:20:32.000000000 -0400
@@ -16,7 +16,7 @@
  */
 #define DRV_NAME  	"qlge"
 #define DRV_STRING 	"QLogic 10 Gigabit PCI-E Ethernet Driver "
-#define DRV_VERSION	"v1.00.00.25.00.00-01"
+#define DRV_VERSION	"v1.00.00.27.00.00-01"
 
 #define WQ_ADDR_ALIGN	0x3	/* 4 byte alignment */
 
@@ -2222,6 +2222,7 @@ int ql_write_mpi_reg(struct ql_adapter *
 int ql_unpause_mpi_risc(struct ql_adapter *qdev);
 int ql_pause_mpi_risc(struct ql_adapter *qdev);
 int ql_hard_reset_mpi_risc(struct ql_adapter *qdev);
+int ql_soft_reset_mpi_risc(struct ql_adapter *qdev);
 int ql_dump_risc_ram_area(struct ql_adapter *qdev, void *buf,
 		u32 ram_addr, int word_count);
 int ql_core_dump(struct ql_adapter *qdev,
@@ -2237,6 +2238,7 @@ int ql_mb_set_mgmnt_traffic_ctl(struct q
 int ql_mb_get_port_cfg(struct ql_adapter *qdev);
 int ql_mb_set_port_cfg(struct ql_adapter *qdev);
 int ql_wait_fifo_empty(struct ql_adapter *qdev);
+void ql_get_dump(struct ql_adapter *qdev, void *buff);
 void ql_gen_reg_dump(struct ql_adapter *qdev,
 			struct ql_reg_dump *mpi_coredump);
 netdev_tx_t ql_lb_send(struct sk_buff *skb, struct net_device *ndev);
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/qlge/qlge_main.c linux-libre-2.6.38-gnu1/drivers/net/qlge/qlge_main.c
--- linux-libre-2.6.37-gnu1/drivers/net/qlge/qlge_main.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/qlge/qlge_main.c	2011-03-14 21:20:32.000000000 -0400
@@ -3548,12 +3548,13 @@ err_irq:
 
 static int ql_start_rss(struct ql_adapter *qdev)
 {
-	u8 init_hash_seed[] = {0x6d, 0x5a, 0x56, 0xda, 0x25, 0x5b, 0x0e, 0xc2,
-				0x41, 0x67, 0x25, 0x3d, 0x43, 0xa3, 0x8f,
-				0xb0, 0xd0, 0xca, 0x2b, 0xcb, 0xae, 0x7b,
-				0x30, 0xb4, 0x77, 0xcb, 0x2d, 0xa3, 0x80,
-				0x30, 0xf2, 0x0c, 0x6a, 0x42, 0xb7, 0x3b,
-				0xbe, 0xac, 0x01, 0xfa};
+	static const u8 init_hash_seed[] = {
+		0x6d, 0x5a, 0x56, 0xda, 0x25, 0x5b, 0x0e, 0xc2,
+		0x41, 0x67, 0x25, 0x3d, 0x43, 0xa3, 0x8f, 0xb0,
+		0xd0, 0xca, 0x2b, 0xcb, 0xae, 0x7b, 0x30, 0xb4,
+		0x77, 0xcb, 0x2d, 0xa3, 0x80, 0x30, 0xf2, 0x0c,
+		0x6a, 0x42, 0xb7, 0x3b, 0xbe, 0xac, 0x01, 0xfa
+	};
 	struct ricb *ricb = &qdev->ricb;
 	int status = 0;
 	int i;
@@ -3844,7 +3845,7 @@ static int ql_adapter_reset(struct ql_ad
 
 static void ql_display_dev_info(struct net_device *ndev)
 {
-	struct ql_adapter *qdev = (struct ql_adapter *)netdev_priv(ndev);
+	struct ql_adapter *qdev = netdev_priv(ndev);
 
 	netif_info(qdev, probe, qdev->ndev,
 		   "Function #%d, Port %d, NIC Roll %d, NIC Rev = %d, "
@@ -4264,7 +4265,7 @@ static struct net_device_stats *qlge_get
 
 static void qlge_set_multicast_list(struct net_device *ndev)
 {
-	struct ql_adapter *qdev = (struct ql_adapter *)netdev_priv(ndev);
+	struct ql_adapter *qdev = netdev_priv(ndev);
 	struct netdev_hw_addr *ha;
 	int i, status;
 
@@ -4354,7 +4355,7 @@ exit:
 
 static int qlge_set_mac_address(struct net_device *ndev, void *p)
 {
-	struct ql_adapter *qdev = (struct ql_adapter *)netdev_priv(ndev);
+	struct ql_adapter *qdev = netdev_priv(ndev);
 	struct sockaddr *addr = p;
 	int status;
 
@@ -4377,7 +4378,7 @@ static int qlge_set_mac_address(struct n
 
 static void qlge_tx_timeout(struct net_device *ndev)
 {
-	struct ql_adapter *qdev = (struct ql_adapter *)netdev_priv(ndev);
+	struct ql_adapter *qdev = netdev_priv(ndev);
 	ql_queue_asic_error(qdev);
 }
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/qlge/qlge_mpi.c linux-libre-2.6.38-gnu1/drivers/net/qlge/qlge_mpi.c
--- linux-libre-2.6.37-gnu1/drivers/net/qlge/qlge_mpi.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/qlge/qlge_mpi.c	2011-03-14 21:20:32.000000000 -0400
@@ -87,7 +87,7 @@ exit:
 	return status;
 }
 
-static int ql_soft_reset_mpi_risc(struct ql_adapter *qdev)
+int ql_soft_reset_mpi_risc(struct ql_adapter *qdev)
 {
 	int status;
 	status = ql_write_mpi_reg(qdev, 0x00001010, 1);
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/r6040.c linux-libre-2.6.38-gnu1/drivers/net/r6040.c
--- linux-libre-2.6.37-gnu1/drivers/net/r6040.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/r6040.c	2011-03-14 21:20:32.000000000 -0400
@@ -49,8 +49,8 @@
 #include <asm/processor.h>
 
 #define DRV_NAME	"r6040"
-#define DRV_VERSION	"0.26"
-#define DRV_RELDATE	"30May2010"
+#define DRV_VERSION	"0.27"
+#define DRV_RELDATE	"23Feb2011"
 
 /* PHY CHIP Address */
 #define PHY1_ADDR	1	/* For MAC1 */
@@ -69,6 +69,8 @@
 
 /* MAC registers */
 #define MCR0		0x00	/* Control register 0 */
+#define  MCR0_PROMISC	0x0020	/* Promiscuous mode */
+#define  MCR0_HASH_EN	0x0100	/* Enable multicast hash table function */
 #define MCR1		0x04	/* Control register 1 */
 #define  MAC_RST	0x0001	/* Reset the MAC */
 #define MBCR		0x08	/* Bus control */
@@ -851,77 +853,92 @@ static void r6040_multicast_list(struct
 {
 	struct r6040_private *lp = netdev_priv(dev);
 	void __iomem *ioaddr = lp->base;
-	u16 *adrp;
-	u16 reg;
 	unsigned long flags;
 	struct netdev_hw_addr *ha;
 	int i;
+	u16 *adrp;
+	u16 hash_table[4] = { 0 };
 
-	/* MAC Address */
+	spin_lock_irqsave(&lp->lock, flags);
+
+	/* Keep our MAC Address */
 	adrp = (u16 *)dev->dev_addr;
 	iowrite16(adrp[0], ioaddr + MID_0L);
 	iowrite16(adrp[1], ioaddr + MID_0M);
 	iowrite16(adrp[2], ioaddr + MID_0H);
 
-	/* Promiscous Mode */
-	spin_lock_irqsave(&lp->lock, flags);
-
 	/* Clear AMCP & PROM bits */
-	reg = ioread16(ioaddr) & ~0x0120;
-	if (dev->flags & IFF_PROMISC) {
-		reg |= 0x0020;
-		lp->mcr0 |= 0x0020;
-	}
-	/* Too many multicast addresses
-	 * accept all traffic */
-	else if ((netdev_mc_count(dev) > MCAST_MAX) ||
-		 (dev->flags & IFF_ALLMULTI))
-		reg |= 0x0020;
+	lp->mcr0 = ioread16(ioaddr + MCR0) & ~(MCR0_PROMISC | MCR0_HASH_EN);
 
-	iowrite16(reg, ioaddr);
-	spin_unlock_irqrestore(&lp->lock, flags);
+	/* Promiscuous mode */
+	if (dev->flags & IFF_PROMISC)
+		lp->mcr0 |= MCR0_PROMISC;
 
-	/* Build the hash table */
-	if (netdev_mc_count(dev) > MCAST_MAX) {
-		u16 hash_table[4];
-		u32 crc;
+	/* Enable multicast hash table function to
+	 * receive all multicast packets. */
+	else if (dev->flags & IFF_ALLMULTI) {
+		lp->mcr0 |= MCR0_HASH_EN;
 
-		for (i = 0; i < 4; i++)
-			hash_table[i] = 0;
+		for (i = 0; i < MCAST_MAX ; i++) {
+			iowrite16(0, ioaddr + MID_1L + 8 * i);
+			iowrite16(0, ioaddr + MID_1M + 8 * i);
+			iowrite16(0, ioaddr + MID_1H + 8 * i);
+		}
 
+		for (i = 0; i < 4; i++)
+			hash_table[i] = 0xffff;
+	}
+	/* Use internal multicast address registers if the number of
+	 * multicast addresses is not greater than MCAST_MAX. */
+	else if (netdev_mc_count(dev) <= MCAST_MAX) {
+		i = 0;
 		netdev_for_each_mc_addr(ha, dev) {
-			char *addrs = ha->addr;
+			u16 *adrp = (u16 *) ha->addr;
+			iowrite16(adrp[0], ioaddr + MID_1L + 8 * i);
+			iowrite16(adrp[1], ioaddr + MID_1M + 8 * i);
+			iowrite16(adrp[2], ioaddr + MID_1H + 8 * i);
+			i++;
+		}
+		while (i < MCAST_MAX) {
+			iowrite16(0, ioaddr + MID_1L + 8 * i);
+			iowrite16(0, ioaddr + MID_1M + 8 * i);
+			iowrite16(0, ioaddr + MID_1H + 8 * i);
+			i++;
+		}
+	}
+	/* Otherwise, Enable multicast hash table function. */
+	else {
+		u32 crc;
 
-			if (!(*addrs & 1))
-				continue;
+		lp->mcr0 |= MCR0_HASH_EN;
 
-			crc = ether_crc_le(6, addrs);
+		for (i = 0; i < MCAST_MAX ; i++) {
+			iowrite16(0, ioaddr + MID_1L + 8 * i);
+			iowrite16(0, ioaddr + MID_1M + 8 * i);
+			iowrite16(0, ioaddr + MID_1H + 8 * i);
+		}
+
+		/* Build multicast hash table */
+		netdev_for_each_mc_addr(ha, dev) {
+			u8 *addrs = ha->addr;
+
+			crc = ether_crc(ETH_ALEN, addrs);
 			crc >>= 26;
-			hash_table[crc >> 4] |= 1 << (15 - (crc & 0xf));
+			hash_table[crc >> 4] |= 1 << (crc & 0xf);
 		}
-		/* Fill the MAC hash tables with their values */
+	}
+
+	iowrite16(lp->mcr0, ioaddr + MCR0);
+
+	/* Fill the MAC hash tables with their values */
+	if (lp->mcr0 && MCR0_HASH_EN) {
 		iowrite16(hash_table[0], ioaddr + MAR0);
 		iowrite16(hash_table[1], ioaddr + MAR1);
 		iowrite16(hash_table[2], ioaddr + MAR2);
 		iowrite16(hash_table[3], ioaddr + MAR3);
 	}
-	/* Multicast Address 1~4 case */
-	i = 0;
-	netdev_for_each_mc_addr(ha, dev) {
-		if (i >= MCAST_MAX)
-			break;
-		adrp = (u16 *) ha->addr;
-		iowrite16(adrp[0], ioaddr + MID_1L + 8 * i);
-		iowrite16(adrp[1], ioaddr + MID_1M + 8 * i);
-		iowrite16(adrp[2], ioaddr + MID_1H + 8 * i);
-		i++;
-	}
-	while (i < MCAST_MAX) {
-		iowrite16(0xffff, ioaddr + MID_1L + 8 * i);
-		iowrite16(0xffff, ioaddr + MID_1M + 8 * i);
-		iowrite16(0xffff, ioaddr + MID_1H + 8 * i);
-		i++;
-	}
+
+	spin_unlock_irqrestore(&lp->lock, flags);
 }
 
 static void netdev_get_drvinfo(struct net_device *dev,
@@ -1153,6 +1170,7 @@ static int __devinit r6040_init_one(stru
 	lp->mii_bus = mdiobus_alloc();
 	if (!lp->mii_bus) {
 		dev_err(&pdev->dev, "mdiobus_alloc() failed\n");
+		err = -ENOMEM;
 		goto err_out_unmap;
 	}
 
@@ -1165,6 +1183,7 @@ static int __devinit r6040_init_one(stru
 	lp->mii_bus->irq = kmalloc(sizeof(int)*PHY_MAX_ADDR, GFP_KERNEL);
 	if (!lp->mii_bus->irq) {
 		dev_err(&pdev->dev, "mii_bus irq allocation failed\n");
+		err = -ENOMEM;
 		goto err_out_mdio;
 	}
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/r8169.c linux-libre-2.6.38-gnu1/drivers/net/r8169.c
--- linux-libre-2.6.37-gnu1/drivers/net/r8169.c	2013-05-03 03:58:53.000000000 -0400
+++ linux-libre-2.6.38-gnu1/drivers/net/r8169.c	2013-05-03 01:59:03.000000000 -0400
@@ -24,6 +24,8 @@
 #include <linux/init.h>
 #include <linux/dma-mapping.h>
 #include <linux/pm_runtime.h>
+#include <linux/firmware.h>
+#include <linux/pci-aspm.h>
 
 #include <asm/system.h>
 #include <asm/io.h>
@@ -33,6 +35,9 @@
 #define MODULENAME "r8169"
 #define PFX MODULENAME ": "
 
+#define FIRMWARE_8168D_1	"/*(DEBLOBBED)*/"
+#define FIRMWARE_8168D_2	"/*(DEBLOBBED)*/"
+
 #ifdef RTL8169_DEBUG
 #define assert(expr) \
 	if (!(expr)) {					\
@@ -63,7 +68,6 @@ static const int multicast_filter_limit
 #define RX_FIFO_THRESH	7	/* 7 means NO threshold, Rx buffer level before first PCI xfer. */
 #define RX_DMA_BURST	6	/* Maximum PCI burst, '6' is 1024 */
 #define TX_DMA_BURST	6	/* Maximum PCI burst, '6' is 1024 */
-#define EarlyTxThld	0x3F	/* 0x3F means NO early transmit */
 #define SafeMtu		0x1c20	/* ... actually life sucks beyond ~7k */
 #define InterFrameGap	0x03	/* 3 means InterFrameGap = the shortest one */
 
@@ -118,7 +122,8 @@ enum mac_version {
 	RTL_GIGA_MAC_VER_24 = 0x18, // 8168CP
 	RTL_GIGA_MAC_VER_25 = 0x19, // 8168D
 	RTL_GIGA_MAC_VER_26 = 0x1a, // 8168D
-	RTL_GIGA_MAC_VER_27 = 0x1b  // 8168DP
+	RTL_GIGA_MAC_VER_27 = 0x1b, // 8168DP
+	RTL_GIGA_MAC_VER_28 = 0x1c, // 8168DP
 };
 
 #define _R(NAME,MAC,MASK) \
@@ -155,7 +160,8 @@ static const struct {
 	_R("RTL8168cp/8111cp",	RTL_GIGA_MAC_VER_24, 0xff7e1880), // PCI-E
 	_R("RTL8168d/8111d",	RTL_GIGA_MAC_VER_25, 0xff7e1880), // PCI-E
 	_R("RTL8168d/8111d",	RTL_GIGA_MAC_VER_26, 0xff7e1880), // PCI-E
-	_R("RTL8168dp/8111dp",	RTL_GIGA_MAC_VER_27, 0xff7e1880)  // PCI-E
+	_R("RTL8168dp/8111dp",	RTL_GIGA_MAC_VER_27, 0xff7e1880), // PCI-E
+	_R("RTL8168dp/8111dp",	RTL_GIGA_MAC_VER_28, 0xff7e1880)  // PCI-E
 };
 #undef _R
 
@@ -227,7 +233,14 @@ enum rtl_registers {
 	IntrMitigate	= 0xe2,
 	RxDescAddrLow	= 0xe4,
 	RxDescAddrHigh	= 0xe8,
-	EarlyTxThres	= 0xec,
+	EarlyTxThres	= 0xec,	/* 8169. Unit of 32 bytes. */
+
+#define NoEarlyTx	0x3f	/* Max value : no early transmit. */
+
+	MaxTxPacketSize	= 0xec,	/* 8101/8168. Unit of 128 bytes. */
+
+#define TxPacketMax	(8064 >> 7)
+
 	FuncEvent	= 0xf0,
 	FuncEventMask	= 0xf4,
 	FuncPresetState	= 0xf8,
@@ -248,7 +261,7 @@ enum rtl8168_8101_registers {
 #define	CSIAR_BYTE_ENABLE		0x0f
 #define	CSIAR_BYTE_ENABLE_SHIFT		12
 #define	CSIAR_ADDR_MASK			0x0fff
-
+	PMCH			= 0x6f,
 	EPHYAR			= 0x80,
 #define	EPHYAR_FLAG			0x80000000
 #define	EPHYAR_WRITE_CMD		0x80000000
@@ -267,6 +280,33 @@ enum rtl8168_8101_registers {
 #define	EFUSEAR_DATA_MASK		0xff
 };
 
+enum rtl8168_registers {
+	ERIDR			= 0x70,
+	ERIAR			= 0x74,
+#define ERIAR_FLAG			0x80000000
+#define ERIAR_WRITE_CMD			0x80000000
+#define ERIAR_READ_CMD			0x00000000
+#define ERIAR_ADDR_BYTE_ALIGN		4
+#define ERIAR_EXGMAC			0
+#define ERIAR_MSIX			1
+#define ERIAR_ASF			2
+#define ERIAR_TYPE_SHIFT		16
+#define ERIAR_BYTEEN			0x0f
+#define ERIAR_BYTEEN_SHIFT		12
+	EPHY_RXER_NUM		= 0x7c,
+	OCPDR			= 0xb0,	/* OCP GPHY access */
+#define OCPDR_WRITE_CMD			0x80000000
+#define OCPDR_READ_CMD			0x00000000
+#define OCPDR_REG_MASK			0x7f
+#define OCPDR_GPHY_REG_SHIFT		16
+#define OCPDR_DATA_MASK			0xffff
+	OCPAR			= 0xb4,
+#define OCPAR_FLAG			0x80000000
+#define OCPAR_GPHY_WRITE_CMD		0x8000f060
+#define OCPAR_GPHY_READ_CMD		0x0000f060
+	RDSAR1			= 0xd0	/* 8168c only. Undocumented on 8168dp */
+};
+
 enum rtl_register_content {
 	/* InterruptStatusBits */
 	SYSErr		= 0x8000,
@@ -490,11 +530,22 @@ struct rtl8169_private {
 #ifdef CONFIG_R8169_VLAN
 	struct vlan_group *vlgrp;
 #endif
+
+	struct mdio_ops {
+		void (*write)(void __iomem *, int, int);
+		int (*read)(void __iomem *, int);
+	} mdio_ops;
+
+	struct pll_power_ops {
+		void (*down)(struct rtl8169_private *);
+		void (*up)(struct rtl8169_private *);
+	} pll_power_ops;
+
 	int (*set_speed)(struct net_device *, u8 autoneg, u16 speed, u8 duplex);
 	int (*get_settings)(struct net_device *, struct ethtool_cmd *);
-	void (*phy_reset_enable)(void __iomem *);
+	void (*phy_reset_enable)(struct rtl8169_private *tp);
 	void (*hw_start)(struct net_device *);
-	unsigned int (*phy_reset_pending)(void __iomem *);
+	unsigned int (*phy_reset_pending)(struct rtl8169_private *tp);
 	unsigned int (*link_ok)(void __iomem *);
 	int (*do_ioctl)(struct rtl8169_private *tp, struct mii_ioctl_data *data, int cmd);
 	int pcie_cap;
@@ -504,6 +555,8 @@ struct rtl8169_private {
 	struct mii_if_info mii;
 	struct rtl8169_counters counters;
 	u32 saved_wolopts;
+
+	const struct firmware *fw;
 };
 
 MODULE_AUTHOR("Realtek and the Linux r8169 crew <netdev@vger.kernel.org>");
@@ -514,6 +567,7 @@ module_param_named(debug, debug.msg_enab
 MODULE_PARM_DESC(debug, "Debug verbosity level (0=none, ..., 16=all)");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(RTL8169_VERSION);
+/*(DEBLOBBED)*/
 
 static int rtl8169_open(struct net_device *dev);
 static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb,
@@ -535,7 +589,83 @@ static int rtl8169_poll(struct napi_stru
 static const unsigned int rtl8169_rx_config =
 	(RX_FIFO_THRESH << RxCfgFIFOShift) | (RX_DMA_BURST << RxCfgDMAShift);
 
-static void mdio_write(void __iomem *ioaddr, int reg_addr, int value)
+static u32 ocp_read(struct rtl8169_private *tp, u8 mask, u16 reg)
+{
+	void __iomem *ioaddr = tp->mmio_addr;
+	int i;
+
+	RTL_W32(OCPAR, ((u32)mask & 0x0f) << 12 | (reg & 0x0fff));
+	for (i = 0; i < 20; i++) {
+		udelay(100);
+		if (RTL_R32(OCPAR) & OCPAR_FLAG)
+			break;
+	}
+	return RTL_R32(OCPDR);
+}
+
+static void ocp_write(struct rtl8169_private *tp, u8 mask, u16 reg, u32 data)
+{
+	void __iomem *ioaddr = tp->mmio_addr;
+	int i;
+
+	RTL_W32(OCPDR, data);
+	RTL_W32(OCPAR, OCPAR_FLAG | ((u32)mask & 0x0f) << 12 | (reg & 0x0fff));
+	for (i = 0; i < 20; i++) {
+		udelay(100);
+		if ((RTL_R32(OCPAR) & OCPAR_FLAG) == 0)
+			break;
+	}
+}
+
+static void rtl8168_oob_notify(struct rtl8169_private *tp, u8 cmd)
+{
+	void __iomem *ioaddr = tp->mmio_addr;
+	int i;
+
+	RTL_W8(ERIDR, cmd);
+	RTL_W32(ERIAR, 0x800010e8);
+	msleep(2);
+	for (i = 0; i < 5; i++) {
+		udelay(100);
+		if (!(RTL_R32(ERIDR) & ERIAR_FLAG))
+			break;
+	}
+
+	ocp_write(tp, 0x1, 0x30, 0x00000001);
+}
+
+#define OOB_CMD_RESET		0x00
+#define OOB_CMD_DRIVER_START	0x05
+#define OOB_CMD_DRIVER_STOP	0x06
+
+static void rtl8168_driver_start(struct rtl8169_private *tp)
+{
+	int i;
+
+	rtl8168_oob_notify(tp, OOB_CMD_DRIVER_START);
+
+	for (i = 0; i < 10; i++) {
+		msleep(10);
+		if (ocp_read(tp, 0x0f, 0x0010) & 0x00000800)
+			break;
+	}
+}
+
+static void rtl8168_driver_stop(struct rtl8169_private *tp)
+{
+	int i;
+
+	rtl8168_oob_notify(tp, OOB_CMD_DRIVER_STOP);
+
+	for (i = 0; i < 10; i++) {
+		msleep(10);
+		if ((ocp_read(tp, 0x0f, 0x0010) & 0x00000800) == 0)
+			break;
+	}
+}
+
+
+static void r8169_mdio_write(void __iomem *ioaddr, int reg_addr, int value)
 {
 	int i;
 
@@ -557,7 +687,7 @@ static void mdio_write(void __iomem *ioa
 	udelay(20);
 }
 
-static int mdio_read(void __iomem *ioaddr, int reg_addr)
+static int r8169_mdio_read(void __iomem *ioaddr, int reg_addr)
 {
 	int i, value = -1;
 
@@ -583,34 +713,117 @@ static int mdio_read(void __iomem *ioadd
 	return value;
 }
 
-static void mdio_patch(void __iomem *ioaddr, int reg_addr, int value)
+static void r8168dp_1_mdio_access(void __iomem *ioaddr, int reg_addr, u32 data)
 {
-	mdio_write(ioaddr, reg_addr, mdio_read(ioaddr, reg_addr) | value);
+	int i;
+
+	RTL_W32(OCPDR, data |
+		((reg_addr & OCPDR_REG_MASK) << OCPDR_GPHY_REG_SHIFT));
+	RTL_W32(OCPAR, OCPAR_GPHY_WRITE_CMD);
+	RTL_W32(EPHY_RXER_NUM, 0);
+
+	for (i = 0; i < 100; i++) {
+		mdelay(1);
+		if (!(RTL_R32(OCPAR) & OCPAR_FLAG))
+			break;
+	}
 }
 
-static void mdio_plus_minus(void __iomem *ioaddr, int reg_addr, int p, int m)
+static void r8168dp_1_mdio_write(void __iomem *ioaddr, int reg_addr, int value)
+{
+	r8168dp_1_mdio_access(ioaddr, reg_addr, OCPDR_WRITE_CMD |
+		(value & OCPDR_DATA_MASK));
+}
+
+static int r8168dp_1_mdio_read(void __iomem *ioaddr, int reg_addr)
+{
+	int i;
+
+	r8168dp_1_mdio_access(ioaddr, reg_addr, OCPDR_READ_CMD);
+
+	mdelay(1);
+	RTL_W32(OCPAR, OCPAR_GPHY_READ_CMD);
+	RTL_W32(EPHY_RXER_NUM, 0);
+
+	for (i = 0; i < 100; i++) {
+		mdelay(1);
+		if (RTL_R32(OCPAR) & OCPAR_FLAG)
+			break;
+	}
+
+	return RTL_R32(OCPDR) & OCPDR_DATA_MASK;
+}
+
+#define R8168DP_1_MDIO_ACCESS_BIT	0x00020000
+
+static void r8168dp_2_mdio_start(void __iomem *ioaddr)
+{
+	RTL_W32(0xd0, RTL_R32(0xd0) & ~R8168DP_1_MDIO_ACCESS_BIT);
+}
+
+static void r8168dp_2_mdio_stop(void __iomem *ioaddr)
+{
+	RTL_W32(0xd0, RTL_R32(0xd0) | R8168DP_1_MDIO_ACCESS_BIT);
+}
+
+static void r8168dp_2_mdio_write(void __iomem *ioaddr, int reg_addr, int value)
+{
+	r8168dp_2_mdio_start(ioaddr);
+
+	r8169_mdio_write(ioaddr, reg_addr, value);
+
+	r8168dp_2_mdio_stop(ioaddr);
+}
+
+static int r8168dp_2_mdio_read(void __iomem *ioaddr, int reg_addr)
+{
+	int value;
+
+	r8168dp_2_mdio_start(ioaddr);
+
+	value = r8169_mdio_read(ioaddr, reg_addr);
+
+	r8168dp_2_mdio_stop(ioaddr);
+
+	return value;
+}
+
+static void rtl_writephy(struct rtl8169_private *tp, int location, u32 val)
+{
+	tp->mdio_ops.write(tp->mmio_addr, location, val);
+}
+
+static int rtl_readphy(struct rtl8169_private *tp, int location)
+{
+	return tp->mdio_ops.read(tp->mmio_addr, location);
+}
+
+static void rtl_patchphy(struct rtl8169_private *tp, int reg_addr, int value)
+{
+	rtl_writephy(tp, reg_addr, rtl_readphy(tp, reg_addr) | value);
+}
+
+static void rtl_w1w0_phy(struct rtl8169_private *tp, int reg_addr, int p, int m)
 {
 	int val;
 
-	val = mdio_read(ioaddr, reg_addr);
-	mdio_write(ioaddr, reg_addr, (val | p) & ~m);
+	val = rtl_readphy(tp, reg_addr);
+	rtl_writephy(tp, reg_addr, (val | p) & ~m);
 }
 
 static void rtl_mdio_write(struct net_device *dev, int phy_id, int location,
 			   int val)
 {
 	struct rtl8169_private *tp = netdev_priv(dev);
-	void __iomem *ioaddr = tp->mmio_addr;
 
-	mdio_write(ioaddr, location, val);
+	rtl_writephy(tp, location, val);
 }
 
 static int rtl_mdio_read(struct net_device *dev, int phy_id, int location)
 {
 	struct rtl8169_private *tp = netdev_priv(dev);
-	void __iomem *ioaddr = tp->mmio_addr;
 
-	return mdio_read(ioaddr, location);
+	return rtl_readphy(tp, location);
 }
 
 static void rtl_ephy_write(void __iomem *ioaddr, int reg_addr, int value)
@@ -711,14 +924,16 @@ static void rtl8169_asic_down(void __iom
 	RTL_R16(CPlusCmd);
 }
 
-static unsigned int rtl8169_tbi_reset_pending(void __iomem *ioaddr)
+static unsigned int rtl8169_tbi_reset_pending(struct rtl8169_private *tp)
 {
+	void __iomem *ioaddr = tp->mmio_addr;
+
 	return RTL_R32(TBICSR) & TBIReset;
 }
 
-static unsigned int rtl8169_xmii_reset_pending(void __iomem *ioaddr)
+static unsigned int rtl8169_xmii_reset_pending(struct rtl8169_private *tp)
 {
-	return mdio_read(ioaddr, MII_BMCR) & BMCR_RESET;
+	return rtl_readphy(tp, MII_BMCR) & BMCR_RESET;
 }
 
 static unsigned int rtl8169_tbi_link_ok(void __iomem *ioaddr)
@@ -731,17 +946,19 @@ static unsigned int rtl8169_xmii_link_ok
 	return RTL_R8(PHYstatus) & LinkStatus;
 }
 
-static void rtl8169_tbi_reset_enable(void __iomem *ioaddr)
+static void rtl8169_tbi_reset_enable(struct rtl8169_private *tp)
 {
+	void __iomem *ioaddr = tp->mmio_addr;
+
 	RTL_W32(TBICSR, RTL_R32(TBICSR) | TBIReset);
 }
 
-static void rtl8169_xmii_reset_enable(void __iomem *ioaddr)
+static void rtl8169_xmii_reset_enable(struct rtl8169_private *tp)
 {
 	unsigned int val;
 
-	val = mdio_read(ioaddr, MII_BMCR) | BMCR_RESET;
-	mdio_write(ioaddr, MII_BMCR, val & 0xffff);
+	val = rtl_readphy(tp, MII_BMCR) | BMCR_RESET;
+	rtl_writephy(tp, MII_BMCR, val & 0xffff);
 }
 
 static void __rtl8169_check_link_status(struct net_device *dev,
@@ -757,7 +974,8 @@ static void __rtl8169_check_link_status(
 		if (pm)
 			pm_request_resume(&tp->pci_dev->dev);
 		netif_carrier_on(dev);
-		netif_info(tp, ifup, dev, "link up\n");
+		if (net_ratelimit())
+			netif_info(tp, ifup, dev, "link up\n");
 	} else {
 		netif_carrier_off(dev);
 		netif_info(tp, ifdown, dev, "link down\n");
@@ -905,18 +1123,17 @@ static int rtl8169_set_speed_xmii(struct
 				  u8 autoneg, u16 speed, u8 duplex)
 {
 	struct rtl8169_private *tp = netdev_priv(dev);
-	void __iomem *ioaddr = tp->mmio_addr;
 	int giga_ctrl, bmcr;
 
 	if (autoneg == AUTONEG_ENABLE) {
 		int auto_nego;
 
-		auto_nego = mdio_read(ioaddr, MII_ADVERTISE);
+		auto_nego = rtl_readphy(tp, MII_ADVERTISE);
 		auto_nego |= (ADVERTISE_10HALF | ADVERTISE_10FULL |
 			      ADVERTISE_100HALF | ADVERTISE_100FULL);
 		auto_nego |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM;
 
-		giga_ctrl = mdio_read(ioaddr, MII_CTRL1000);
+		giga_ctrl = rtl_readphy(tp, MII_CTRL1000);
 		giga_ctrl &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF);
 
 		/* The 8100e/8101e/8102e do Fast Ethernet only. */
@@ -944,12 +1161,12 @@ static int rtl8169_set_speed_xmii(struct
 			 * Vendor specific (0x1f) and reserved (0x0e) MII
 			 * registers.
 			 */
-			mdio_write(ioaddr, 0x1f, 0x0000);
-			mdio_write(ioaddr, 0x0e, 0x0000);
+			rtl_writephy(tp, 0x1f, 0x0000);
+			rtl_writephy(tp, 0x0e, 0x0000);
 		}
 
-		mdio_write(ioaddr, MII_ADVERTISE, auto_nego);
-		mdio_write(ioaddr, MII_CTRL1000, giga_ctrl);
+		rtl_writephy(tp, MII_ADVERTISE, auto_nego);
+		rtl_writephy(tp, MII_CTRL1000, giga_ctrl);
 	} else {
 		giga_ctrl = 0;
 
@@ -963,21 +1180,21 @@ static int rtl8169_set_speed_xmii(struct
 		if (duplex == DUPLEX_FULL)
 			bmcr |= BMCR_FULLDPLX;
 
-		mdio_write(ioaddr, 0x1f, 0x0000);
+		rtl_writephy(tp, 0x1f, 0x0000);
 	}
 
 	tp->phy_1000_ctrl_reg = giga_ctrl;
 
-	mdio_write(ioaddr, MII_BMCR, bmcr);
+	rtl_writephy(tp, MII_BMCR, bmcr);
 
 	if ((tp->mac_version == RTL_GIGA_MAC_VER_02) ||
 	    (tp->mac_version == RTL_GIGA_MAC_VER_03)) {
 		if ((speed == SPEED_100) && (autoneg != AUTONEG_ENABLE)) {
-			mdio_write(ioaddr, 0x17, 0x2138);
-			mdio_write(ioaddr, 0x0e, 0x0260);
+			rtl_writephy(tp, 0x17, 0x2138);
+			rtl_writephy(tp, 0x0e, 0x0260);
 		} else {
-			mdio_write(ioaddr, 0x17, 0x2108);
-			mdio_write(ioaddr, 0x0e, 0x0000);
+			rtl_writephy(tp, 0x17, 0x2108);
+			rtl_writephy(tp, 0x0e, 0x0000);
 		}
 	}
 
@@ -1319,9 +1536,12 @@ static void rtl8169_get_mac_version(stru
 		/* 8168D family. */
 		{ 0x7cf00000, 0x28300000,	RTL_GIGA_MAC_VER_26 },
 		{ 0x7cf00000, 0x28100000,	RTL_GIGA_MAC_VER_25 },
-		{ 0x7c800000, 0x28800000,	RTL_GIGA_MAC_VER_27 },
 		{ 0x7c800000, 0x28000000,	RTL_GIGA_MAC_VER_26 },
 
+		/* 8168DP family. */
+		{ 0x7cf00000, 0x28800000,	RTL_GIGA_MAC_VER_27 },
+		{ 0x7cf00000, 0x28a00000,	RTL_GIGA_MAC_VER_28 },
+
 		/* 8168C family. */
 		{ 0x7cf00000, 0x3cb00000,	RTL_GIGA_MAC_VER_24 },
 		{ 0x7cf00000, 0x3c900000,	RTL_GIGA_MAC_VER_23 },
@@ -1385,15 +1605,195 @@ struct phy_reg {
 	u16 val;
 };
 
-static void rtl_phy_write(void __iomem *ioaddr, const struct phy_reg *regs, int len)
+static void rtl_writephy_batch(struct rtl8169_private *tp,
+			       const struct phy_reg *regs, int len)
 {
 	while (len-- > 0) {
-		mdio_write(ioaddr, regs->reg, regs->val);
+		rtl_writephy(tp, regs->reg, regs->val);
 		regs++;
 	}
 }
 
-static void rtl8169s_hw_phy_config(void __iomem *ioaddr)
+#define PHY_READ		0x00000000
+#define PHY_DATA_OR		0x10000000
+#define PHY_DATA_AND		0x20000000
+#define PHY_BJMPN		0x30000000
+#define PHY_READ_EFUSE		0x40000000
+#define PHY_READ_MAC_BYTE	0x50000000
+#define PHY_WRITE_MAC_BYTE	0x60000000
+#define PHY_CLEAR_READCOUNT	0x70000000
+#define PHY_WRITE		0x80000000
+#define PHY_READCOUNT_EQ_SKIP	0x90000000
+#define PHY_COMP_EQ_SKIPN	0xa0000000
+#define PHY_COMP_NEQ_SKIPN	0xb0000000
+#define PHY_WRITE_PREVIOUS	0xc0000000
+#define PHY_SKIPN		0xd0000000
+#define PHY_DELAY_MS		0xe0000000
+#define PHY_WRITE_ERI_WORD	0xf0000000
+
+static void
+rtl_phy_write_fw(struct rtl8169_private *tp, const struct firmware *fw)
+{
+	__le32 *phytable = (__le32 *)fw->data;
+	struct net_device *dev = tp->dev;
+	size_t index, fw_size = fw->size / sizeof(*phytable);
+	u32 predata, count;
+
+	if (fw->size % sizeof(*phytable)) {
+		netif_err(tp, probe, dev, "odd sized firmware %zd\n", fw->size);
+		return;
+	}
+
+	for (index = 0; index < fw_size; index++) {
+		u32 action = le32_to_cpu(phytable[index]);
+		u32 regno = (action & 0x0fff0000) >> 16;
+
+		switch(action & 0xf0000000) {
+		case PHY_READ:
+		case PHY_DATA_OR:
+		case PHY_DATA_AND:
+		case PHY_READ_EFUSE:
+		case PHY_CLEAR_READCOUNT:
+		case PHY_WRITE:
+		case PHY_WRITE_PREVIOUS:
+		case PHY_DELAY_MS:
+			break;
+
+		case PHY_BJMPN:
+			if (regno > index) {
+				netif_err(tp, probe, tp->dev,
+					"Out of range of firmware\n");
+				return;
+			}
+			break;
+		case PHY_READCOUNT_EQ_SKIP:
+			if (index + 2 >= fw_size) {
+				netif_err(tp, probe, tp->dev,
+					"Out of range of firmware\n");
+				return;
+			}
+			break;
+		case PHY_COMP_EQ_SKIPN:
+		case PHY_COMP_NEQ_SKIPN:
+		case PHY_SKIPN:
+			if (index + 1 + regno >= fw_size) {
+				netif_err(tp, probe, tp->dev,
+					"Out of range of firmware\n");
+				return;
+			}
+			break;
+
+		case PHY_READ_MAC_BYTE:
+		case PHY_WRITE_MAC_BYTE:
+		case PHY_WRITE_ERI_WORD:
+		default:
+			netif_err(tp, probe, tp->dev,
+				  "Invalid action 0x%08x\n", action);
+			return;
+		}
+	}
+
+	predata = 0;
+	count = 0;
+
+	for (index = 0; index < fw_size; ) {
+		u32 action = le32_to_cpu(phytable[index]);
+		u32 data = action & 0x0000ffff;
+		u32 regno = (action & 0x0fff0000) >> 16;
+
+		if (!action)
+			break;
+
+		switch(action & 0xf0000000) {
+		case PHY_READ:
+			predata = rtl_readphy(tp, regno);
+			count++;
+			index++;
+			break;
+		case PHY_DATA_OR:
+			predata |= data;
+			index++;
+			break;
+		case PHY_DATA_AND:
+			predata &= data;
+			index++;
+			break;
+		case PHY_BJMPN:
+			index -= regno;
+			break;
+		case PHY_READ_EFUSE:
+			predata = rtl8168d_efuse_read(tp->mmio_addr, regno);
+			index++;
+			break;
+		case PHY_CLEAR_READCOUNT:
+			count = 0;
+			index++;
+			break;
+		case PHY_WRITE:
+			rtl_writephy(tp, regno, data);
+			index++;
+			break;
+		case PHY_READCOUNT_EQ_SKIP:
+			if (count == data)
+				index += 2;
+			else
+				index += 1;
+			break;
+		case PHY_COMP_EQ_SKIPN:
+			if (predata == data)
+				index += regno;
+			index++;
+			break;
+		case PHY_COMP_NEQ_SKIPN:
+			if (predata != data)
+				index += regno;
+			index++;
+			break;
+		case PHY_WRITE_PREVIOUS:
+			rtl_writephy(tp, regno, predata);
+			index++;
+			break;
+		case PHY_SKIPN:
+			index += regno + 1;
+			break;
+		case PHY_DELAY_MS:
+			mdelay(data);
+			index++;
+			break;
+
+		case PHY_READ_MAC_BYTE:
+		case PHY_WRITE_MAC_BYTE:
+		case PHY_WRITE_ERI_WORD:
+		default:
+			BUG();
+		}
+	}
+}
+
+static void rtl_release_firmware(struct rtl8169_private *tp)
+{
+	release_firmware(tp->fw);
+	tp->fw = NULL;
+}
+
+static int rtl_apply_firmware(struct rtl8169_private *tp, const char *fw_name)
+{
+	const struct firmware **fw = &tp->fw;
+	int rc = !*fw;
+
+	if (rc) {
+		rc = reject_firmware(fw, fw_name, &tp->pci_dev->dev);
+		if (rc < 0)
+			goto out;
+	}
+
+	/* TODO: release firmware once rtl_phy_write_fw signals failures. */
+	rtl_phy_write_fw(tp, *fw);
+out:
+	return rc;
+}
+
+static void rtl8169s_hw_phy_config(struct rtl8169_private *tp)
 {
 	static const struct phy_reg phy_reg_init[] = {
 		{ 0x1f, 0x0001 },
@@ -1457,10 +1857,10 @@ static void rtl8169s_hw_phy_config(void
 		{ 0x00, 0x9200 }
 	};
 
-	rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init));
+	rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
 }
 
-static void rtl8169sb_hw_phy_config(void __iomem *ioaddr)
+static void rtl8169sb_hw_phy_config(struct rtl8169_private *tp)
 {
 	static const struct phy_reg phy_reg_init[] = {
 		{ 0x1f, 0x0002 },
@@ -1468,11 +1868,10 @@ static void rtl8169sb_hw_phy_config(void
 		{ 0x1f, 0x0000 }
 	};
 
-	rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init));
+	rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
 }
 
-static void rtl8169scd_hw_phy_config_quirk(struct rtl8169_private *tp,
-					   void __iomem *ioaddr)
+static void rtl8169scd_hw_phy_config_quirk(struct rtl8169_private *tp)
 {
 	struct pci_dev *pdev = tp->pci_dev;
 	u16 vendor_id, device_id;
@@ -1483,13 +1882,12 @@ static void rtl8169scd_hw_phy_config_qui
 	if ((vendor_id != PCI_VENDOR_ID_GIGABYTE) || (device_id != 0xe000))
 		return;
 
-	mdio_write(ioaddr, 0x1f, 0x0001);
-	mdio_write(ioaddr, 0x10, 0xf01b);
-	mdio_write(ioaddr, 0x1f, 0x0000);
+	rtl_writephy(tp, 0x1f, 0x0001);
+	rtl_writephy(tp, 0x10, 0xf01b);
+	rtl_writephy(tp, 0x1f, 0x0000);
 }
 
-static void rtl8169scd_hw_phy_config(struct rtl8169_private *tp,
-				     void __iomem *ioaddr)
+static void rtl8169scd_hw_phy_config(struct rtl8169_private *tp)
 {
 	static const struct phy_reg phy_reg_init[] = {
 		{ 0x1f, 0x0001 },
@@ -1531,12 +1929,12 @@ static void rtl8169scd_hw_phy_config(str
 		{ 0x1f, 0x0000 }
 	};
 
-	rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init));
+	rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
 
-	rtl8169scd_hw_phy_config_quirk(tp, ioaddr);
+	rtl8169scd_hw_phy_config_quirk(tp);
 }
 
-static void rtl8169sce_hw_phy_config(void __iomem *ioaddr)
+static void rtl8169sce_hw_phy_config(struct rtl8169_private *tp)
 {
 	static const struct phy_reg phy_reg_init[] = {
 		{ 0x1f, 0x0001 },
@@ -1586,23 +1984,23 @@ static void rtl8169sce_hw_phy_config(voi
 		{ 0x1f, 0x0000 }
 	};
 
-	rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init));
+	rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
 }
 
-static void rtl8168bb_hw_phy_config(void __iomem *ioaddr)
+static void rtl8168bb_hw_phy_config(struct rtl8169_private *tp)
 {
 	static const struct phy_reg phy_reg_init[] = {
 		{ 0x10, 0xf41b },
 		{ 0x1f, 0x0000 }
 	};
 
-	mdio_write(ioaddr, 0x1f, 0x0001);
-	mdio_patch(ioaddr, 0x16, 1 << 0);
+	rtl_writephy(tp, 0x1f, 0x0001);
+	rtl_patchphy(tp, 0x16, 1 << 0);
 
-	rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init));
+	rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
 }
 
-static void rtl8168bef_hw_phy_config(void __iomem *ioaddr)
+static void rtl8168bef_hw_phy_config(struct rtl8169_private *tp)
 {
 	static const struct phy_reg phy_reg_init[] = {
 		{ 0x1f, 0x0001 },
@@ -1610,10 +2008,10 @@ static void rtl8168bef_hw_phy_config(voi
 		{ 0x1f, 0x0000 }
 	};
 
-	rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init));
+	rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
 }
 
-static void rtl8168cp_1_hw_phy_config(void __iomem *ioaddr)
+static void rtl8168cp_1_hw_phy_config(struct rtl8169_private *tp)
 {
 	static const struct phy_reg phy_reg_init[] = {
 		{ 0x1f, 0x0000 },
@@ -1623,10 +2021,10 @@ static void rtl8168cp_1_hw_phy_config(vo
 		{ 0x1f, 0x0000 }
 	};
 
-	rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init));
+	rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
 }
 
-static void rtl8168cp_2_hw_phy_config(void __iomem *ioaddr)
+static void rtl8168cp_2_hw_phy_config(struct rtl8169_private *tp)
 {
 	static const struct phy_reg phy_reg_init[] = {
 		{ 0x1f, 0x0001 },
@@ -1634,14 +2032,14 @@ static void rtl8168cp_2_hw_phy_config(vo
 		{ 0x1f, 0x0000 }
 	};
 
-	mdio_write(ioaddr, 0x1f, 0x0000);
-	mdio_patch(ioaddr, 0x14, 1 << 5);
-	mdio_patch(ioaddr, 0x0d, 1 << 5);
+	rtl_writephy(tp, 0x1f, 0x0000);
+	rtl_patchphy(tp, 0x14, 1 << 5);
+	rtl_patchphy(tp, 0x0d, 1 << 5);
 
-	rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init));
+	rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
 }
 
-static void rtl8168c_1_hw_phy_config(void __iomem *ioaddr)
+static void rtl8168c_1_hw_phy_config(struct rtl8169_private *tp)
 {
 	static const struct phy_reg phy_reg_init[] = {
 		{ 0x1f, 0x0001 },
@@ -1663,14 +2061,14 @@ static void rtl8168c_1_hw_phy_config(voi
 		{ 0x09, 0x0000 }
 	};
 
-	rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init));
+	rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
 
-	mdio_patch(ioaddr, 0x14, 1 << 5);
-	mdio_patch(ioaddr, 0x0d, 1 << 5);
-	mdio_write(ioaddr, 0x1f, 0x0000);
+	rtl_patchphy(tp, 0x14, 1 << 5);
+	rtl_patchphy(tp, 0x0d, 1 << 5);
+	rtl_writephy(tp, 0x1f, 0x0000);
 }
 
-static void rtl8168c_2_hw_phy_config(void __iomem *ioaddr)
+static void rtl8168c_2_hw_phy_config(struct rtl8169_private *tp)
 {
 	static const struct phy_reg phy_reg_init[] = {
 		{ 0x1f, 0x0001 },
@@ -1690,15 +2088,15 @@ static void rtl8168c_2_hw_phy_config(voi
 		{ 0x1f, 0x0000 }
 	};
 
-	rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init));
+	rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
 
-	mdio_patch(ioaddr, 0x16, 1 << 0);
-	mdio_patch(ioaddr, 0x14, 1 << 5);
-	mdio_patch(ioaddr, 0x0d, 1 << 5);
-	mdio_write(ioaddr, 0x1f, 0x0000);
+	rtl_patchphy(tp, 0x16, 1 << 0);
+	rtl_patchphy(tp, 0x14, 1 << 5);
+	rtl_patchphy(tp, 0x0d, 1 << 5);
+	rtl_writephy(tp, 0x1f, 0x0000);
 }
 
-static void rtl8168c_3_hw_phy_config(void __iomem *ioaddr)
+static void rtl8168c_3_hw_phy_config(struct rtl8169_private *tp)
 {
 	static const struct phy_reg phy_reg_init[] = {
 		{ 0x1f, 0x0001 },
@@ -1712,24 +2110,239 @@ static void rtl8168c_3_hw_phy_config(voi
 		{ 0x1f, 0x0000 }
 	};
 
-	rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init));
+	rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
 
-	mdio_patch(ioaddr, 0x16, 1 << 0);
-	mdio_patch(ioaddr, 0x14, 1 << 5);
-	mdio_patch(ioaddr, 0x0d, 1 << 5);
-	mdio_write(ioaddr, 0x1f, 0x0000);
+	rtl_patchphy(tp, 0x16, 1 << 0);
+	rtl_patchphy(tp, 0x14, 1 << 5);
+	rtl_patchphy(tp, 0x0d, 1 << 5);
+	rtl_writephy(tp, 0x1f, 0x0000);
 }
 
-static void rtl8168c_4_hw_phy_config(void __iomem *ioaddr)
+static void rtl8168c_4_hw_phy_config(struct rtl8169_private *tp)
 {
-	rtl8168c_3_hw_phy_config(ioaddr);
+	rtl8168c_3_hw_phy_config(tp);
 }
 
-/*(DEBLOBBED)*/
+static void rtl8168d_1_hw_phy_config(struct rtl8169_private *tp)
+{
+	static const struct phy_reg phy_reg_init_0[] = {
+		/* Channel Estimation */
+		{ 0x1f, 0x0001 },
+		{ 0x06, 0x4064 },
+		{ 0x07, 0x2863 },
+		{ 0x08, 0x059c },
+		{ 0x09, 0x26b4 },
+		{ 0x0a, 0x6a19 },
+		{ 0x0b, 0xdcc8 },
+		{ 0x10, 0xf06d },
+		{ 0x14, 0x7f68 },
+		{ 0x18, 0x7fd9 },
+		{ 0x1c, 0xf0ff },
+		{ 0x1d, 0x3d9c },
+		{ 0x1f, 0x0003 },
+		{ 0x12, 0xf49f },
+		{ 0x13, 0x070b },
+		{ 0x1a, 0x05ad },
+		{ 0x14, 0x94c0 },
 
-/*(DEBLOBBED)*/
+		/*
+		 * Tx Error Issue
+		 * enhance line driver power
+		 */
+		{ 0x1f, 0x0002 },
+		{ 0x06, 0x5561 },
+		{ 0x1f, 0x0005 },
+		{ 0x05, 0x8332 },
+		{ 0x06, 0x5561 },
 
-static void rtl8168d_3_hw_phy_config(void __iomem *ioaddr)
+		/*
+		 * Can not link to 1Gbps with bad cable
+		 * Decrease SNR threshold form 21.07dB to 19.04dB
+		 */
+		{ 0x1f, 0x0001 },
+		{ 0x17, 0x0cc0 },
+
+		{ 0x1f, 0x0000 },
+		{ 0x0d, 0xf880 }
+	};
+	void __iomem *ioaddr = tp->mmio_addr;
+
+	rtl_writephy_batch(tp, phy_reg_init_0, ARRAY_SIZE(phy_reg_init_0));
+
+	/*
+	 * Rx Error Issue
+	 * Fine Tune Switching regulator parameter
+	 */
+	rtl_writephy(tp, 0x1f, 0x0002);
+	rtl_w1w0_phy(tp, 0x0b, 0x0010, 0x00ef);
+	rtl_w1w0_phy(tp, 0x0c, 0xa200, 0x5d00);
+
+	if (rtl8168d_efuse_read(ioaddr, 0x01) == 0xb1) {
+		static const struct phy_reg phy_reg_init[] = {
+			{ 0x1f, 0x0002 },
+			{ 0x05, 0x669a },
+			{ 0x1f, 0x0005 },
+			{ 0x05, 0x8330 },
+			{ 0x06, 0x669a },
+			{ 0x1f, 0x0002 }
+		};
+		int val;
+
+		rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
+
+		val = rtl_readphy(tp, 0x0d);
+
+		if ((val & 0x00ff) != 0x006c) {
+			static const u32 set[] = {
+				0x0065, 0x0066, 0x0067, 0x0068,
+				0x0069, 0x006a, 0x006b, 0x006c
+			};
+			int i;
+
+			rtl_writephy(tp, 0x1f, 0x0002);
+
+			val &= 0xff00;
+			for (i = 0; i < ARRAY_SIZE(set); i++)
+				rtl_writephy(tp, 0x0d, val | set[i]);
+		}
+	} else {
+		static const struct phy_reg phy_reg_init[] = {
+			{ 0x1f, 0x0002 },
+			{ 0x05, 0x6662 },
+			{ 0x1f, 0x0005 },
+			{ 0x05, 0x8330 },
+			{ 0x06, 0x6662 }
+		};
+
+		rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
+	}
+
+	/* RSET couple improve */
+	rtl_writephy(tp, 0x1f, 0x0002);
+	rtl_patchphy(tp, 0x0d, 0x0300);
+	rtl_patchphy(tp, 0x0f, 0x0010);
+
+	/* Fine tune PLL performance */
+	rtl_writephy(tp, 0x1f, 0x0002);
+	rtl_w1w0_phy(tp, 0x02, 0x0100, 0x0600);
+	rtl_w1w0_phy(tp, 0x03, 0x0000, 0xe000);
+
+	rtl_writephy(tp, 0x1f, 0x0005);
+	rtl_writephy(tp, 0x05, 0x001b);
+	if ((rtl_readphy(tp, 0x06) != 0xbf00) ||
+	    (rtl_apply_firmware(tp, FIRMWARE_8168D_1) < 0)) {
+		netif_warn(tp, probe, tp->dev, "unable to apply firmware patch\n");
+	}
+
+	rtl_writephy(tp, 0x1f, 0x0000);
+}
+
+static void rtl8168d_2_hw_phy_config(struct rtl8169_private *tp)
+{
+	static const struct phy_reg phy_reg_init_0[] = {
+		/* Channel Estimation */
+		{ 0x1f, 0x0001 },
+		{ 0x06, 0x4064 },
+		{ 0x07, 0x2863 },
+		{ 0x08, 0x059c },
+		{ 0x09, 0x26b4 },
+		{ 0x0a, 0x6a19 },
+		{ 0x0b, 0xdcc8 },
+		{ 0x10, 0xf06d },
+		{ 0x14, 0x7f68 },
+		{ 0x18, 0x7fd9 },
+		{ 0x1c, 0xf0ff },
+		{ 0x1d, 0x3d9c },
+		{ 0x1f, 0x0003 },
+		{ 0x12, 0xf49f },
+		{ 0x13, 0x070b },
+		{ 0x1a, 0x05ad },
+		{ 0x14, 0x94c0 },
+
+		/*
+		 * Tx Error Issue
+		 * enhance line driver power
+		 */
+		{ 0x1f, 0x0002 },
+		{ 0x06, 0x5561 },
+		{ 0x1f, 0x0005 },
+		{ 0x05, 0x8332 },
+		{ 0x06, 0x5561 },
+
+		/*
+		 * Can not link to 1Gbps with bad cable
+		 * Decrease SNR threshold form 21.07dB to 19.04dB
+		 */
+		{ 0x1f, 0x0001 },
+		{ 0x17, 0x0cc0 },
+
+		{ 0x1f, 0x0000 },
+		{ 0x0d, 0xf880 }
+	};
+	void __iomem *ioaddr = tp->mmio_addr;
+
+	rtl_writephy_batch(tp, phy_reg_init_0, ARRAY_SIZE(phy_reg_init_0));
+
+	if (rtl8168d_efuse_read(ioaddr, 0x01) == 0xb1) {
+		static const struct phy_reg phy_reg_init[] = {
+			{ 0x1f, 0x0002 },
+			{ 0x05, 0x669a },
+			{ 0x1f, 0x0005 },
+			{ 0x05, 0x8330 },
+			{ 0x06, 0x669a },
+
+			{ 0x1f, 0x0002 }
+		};
+		int val;
+
+		rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
+
+		val = rtl_readphy(tp, 0x0d);
+		if ((val & 0x00ff) != 0x006c) {
+			static const u32 set[] = {
+				0x0065, 0x0066, 0x0067, 0x0068,
+				0x0069, 0x006a, 0x006b, 0x006c
+			};
+			int i;
+
+			rtl_writephy(tp, 0x1f, 0x0002);
+
+			val &= 0xff00;
+			for (i = 0; i < ARRAY_SIZE(set); i++)
+				rtl_writephy(tp, 0x0d, val | set[i]);
+		}
+	} else {
+		static const struct phy_reg phy_reg_init[] = {
+			{ 0x1f, 0x0002 },
+			{ 0x05, 0x2642 },
+			{ 0x1f, 0x0005 },
+			{ 0x05, 0x8330 },
+			{ 0x06, 0x2642 }
+		};
+
+		rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
+	}
+
+	/* Fine tune PLL performance */
+	rtl_writephy(tp, 0x1f, 0x0002);
+	rtl_w1w0_phy(tp, 0x02, 0x0100, 0x0600);
+	rtl_w1w0_phy(tp, 0x03, 0x0000, 0xe000);
+
+	/* Switching regulator Slew rate */
+	rtl_writephy(tp, 0x1f, 0x0002);
+	rtl_patchphy(tp, 0x0f, 0x0017);
+
+	rtl_writephy(tp, 0x1f, 0x0005);
+	rtl_writephy(tp, 0x05, 0x001b);
+	if ((rtl_readphy(tp, 0x06) != 0xb300) ||
+	    (rtl_apply_firmware(tp, FIRMWARE_8168D_2) < 0)) {
+		netif_warn(tp, probe, tp->dev, "unable to apply firmware patch\n");
+	}
+
+	rtl_writephy(tp, 0x1f, 0x0000);
+}
+
+static void rtl8168d_3_hw_phy_config(struct rtl8169_private *tp)
 {
 	static const struct phy_reg phy_reg_init[] = {
 		{ 0x1f, 0x0002 },
@@ -1787,10 +2400,26 @@ static void rtl8168d_3_hw_phy_config(voi
 		{ 0x1f, 0x0000 }
 	};
 
-	rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init));
+	rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
 }
 
-static void rtl8102e_hw_phy_config(void __iomem *ioaddr)
+static void rtl8168d_4_hw_phy_config(struct rtl8169_private *tp)
+{
+	static const struct phy_reg phy_reg_init[] = {
+		{ 0x1f, 0x0001 },
+		{ 0x17, 0x0cc0 },
+
+		{ 0x1f, 0x0007 },
+		{ 0x1e, 0x002d },
+		{ 0x18, 0x0040 },
+		{ 0x1f, 0x0000 }
+	};
+
+	rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
+	rtl_patchphy(tp, 0x0d, 1 << 5);
+}
+
+static void rtl8102e_hw_phy_config(struct rtl8169_private *tp)
 {
 	static const struct phy_reg phy_reg_init[] = {
 		{ 0x1f, 0x0003 },
@@ -1799,18 +2428,17 @@ static void rtl8102e_hw_phy_config(void
 		{ 0x1f, 0x0000 }
 	};
 
-	mdio_write(ioaddr, 0x1f, 0x0000);
-	mdio_patch(ioaddr, 0x11, 1 << 12);
-	mdio_patch(ioaddr, 0x19, 1 << 13);
-	mdio_patch(ioaddr, 0x10, 1 << 15);
+	rtl_writephy(tp, 0x1f, 0x0000);
+	rtl_patchphy(tp, 0x11, 1 << 12);
+	rtl_patchphy(tp, 0x19, 1 << 13);
+	rtl_patchphy(tp, 0x10, 1 << 15);
 
-	rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init));
+	rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
 }
 
 static void rtl_hw_phy_config(struct net_device *dev)
 {
 	struct rtl8169_private *tp = netdev_priv(dev);
-	void __iomem *ioaddr = tp->mmio_addr;
 
 	rtl8169_print_mac_version(tp);
 
@@ -1819,60 +2447,61 @@ static void rtl_hw_phy_config(struct net
 		break;
 	case RTL_GIGA_MAC_VER_02:
 	case RTL_GIGA_MAC_VER_03:
-		rtl8169s_hw_phy_config(ioaddr);
+		rtl8169s_hw_phy_config(tp);
 		break;
 	case RTL_GIGA_MAC_VER_04:
-		rtl8169sb_hw_phy_config(ioaddr);
+		rtl8169sb_hw_phy_config(tp);
 		break;
 	case RTL_GIGA_MAC_VER_05:
-		rtl8169scd_hw_phy_config(tp, ioaddr);
+		rtl8169scd_hw_phy_config(tp);
 		break;
 	case RTL_GIGA_MAC_VER_06:
-		rtl8169sce_hw_phy_config(ioaddr);
+		rtl8169sce_hw_phy_config(tp);
 		break;
 	case RTL_GIGA_MAC_VER_07:
 	case RTL_GIGA_MAC_VER_08:
 	case RTL_GIGA_MAC_VER_09:
-		rtl8102e_hw_phy_config(ioaddr);
+		rtl8102e_hw_phy_config(tp);
 		break;
 	case RTL_GIGA_MAC_VER_11:
-		rtl8168bb_hw_phy_config(ioaddr);
+		rtl8168bb_hw_phy_config(tp);
 		break;
 	case RTL_GIGA_MAC_VER_12:
-		rtl8168bef_hw_phy_config(ioaddr);
+		rtl8168bef_hw_phy_config(tp);
 		break;
 	case RTL_GIGA_MAC_VER_17:
-		rtl8168bef_hw_phy_config(ioaddr);
+		rtl8168bef_hw_phy_config(tp);
 		break;
 	case RTL_GIGA_MAC_VER_18:
-		rtl8168cp_1_hw_phy_config(ioaddr);
+		rtl8168cp_1_hw_phy_config(tp);
 		break;
 	case RTL_GIGA_MAC_VER_19:
-		rtl8168c_1_hw_phy_config(ioaddr);
+		rtl8168c_1_hw_phy_config(tp);
 		break;
 	case RTL_GIGA_MAC_VER_20:
-		rtl8168c_2_hw_phy_config(ioaddr);
+		rtl8168c_2_hw_phy_config(tp);
 		break;
 	case RTL_GIGA_MAC_VER_21:
-		rtl8168c_3_hw_phy_config(ioaddr);
+		rtl8168c_3_hw_phy_config(tp);
 		break;
 	case RTL_GIGA_MAC_VER_22:
-		rtl8168c_4_hw_phy_config(ioaddr);
+		rtl8168c_4_hw_phy_config(tp);
 		break;
 	case RTL_GIGA_MAC_VER_23:
 	case RTL_GIGA_MAC_VER_24:
-		rtl8168cp_2_hw_phy_config(ioaddr);
+		rtl8168cp_2_hw_phy_config(tp);
 		break;
 	case RTL_GIGA_MAC_VER_25:
-		printk(KERN_ERR PFX "%s: Missing Free firmware\n", dev->name);
-		/*(DEBLOBBED)*/
+		rtl8168d_1_hw_phy_config(tp);
 		break;
 	case RTL_GIGA_MAC_VER_26:
-		printk(KERN_ERR PFX "%s: Missing Free firmware\n", dev->name);
-		/*(DEBLOBBED)*/
+		rtl8168d_2_hw_phy_config(tp);
 		break;
 	case RTL_GIGA_MAC_VER_27:
-		rtl8168d_3_hw_phy_config(ioaddr);
+		rtl8168d_3_hw_phy_config(tp);
+		break;
+	case RTL_GIGA_MAC_VER_28:
+		rtl8168d_4_hw_phy_config(tp);
 		break;
 
 	default:
@@ -1895,7 +2524,7 @@ static void rtl8169_phy_timer(unsigned l
 
 	spin_lock_irq(&tp->lock);
 
-	if (tp->phy_reset_pending(ioaddr)) {
+	if (tp->phy_reset_pending(tp)) {
 		/*
 		 * A busy loop could burn quite a few cycles on nowadays CPU.
 		 * Let's delay the execution of the timer for a few ticks.
@@ -1909,7 +2538,7 @@ static void rtl8169_phy_timer(unsigned l
 
 	netif_warn(tp, link, dev, "PHY reset until link up\n");
 
-	tp->phy_reset_enable(ioaddr);
+	tp->phy_reset_enable(tp);
 
 out_mod_timer:
 	mod_timer(timer, jiffies + timeout);
@@ -1969,12 +2598,11 @@ static void rtl8169_release_board(struct
 static void rtl8169_phy_reset(struct net_device *dev,
 			      struct rtl8169_private *tp)
 {
-	void __iomem *ioaddr = tp->mmio_addr;
 	unsigned int i;
 
-	tp->phy_reset_enable(ioaddr);
+	tp->phy_reset_enable(tp);
 	for (i = 0; i < 100; i++) {
-		if (!tp->phy_reset_pending(ioaddr))
+		if (!tp->phy_reset_pending(tp))
 			return;
 		msleep(1);
 	}
@@ -2001,7 +2629,7 @@ static void rtl8169_init_phy(struct net_
 		dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n");
 		RTL_W8(0x82, 0x01);
 		dprintk("Set PHY Reg 0x0bh = 0x00h\n");
-		mdio_write(ioaddr, 0x0b, 0x0000); //w 0x0b 15 0 0
+		rtl_writephy(tp, 0x0b, 0x0000); //w 0x0b 15 0 0
 	}
 
 	rtl8169_phy_reset(dev, tp);
@@ -2071,11 +2699,11 @@ static int rtl_xmii_ioctl(struct rtl8169
 		return 0;
 
 	case SIOCGMIIREG:
-		data->val_out = mdio_read(tp->mmio_addr, data->reg_num & 0x1f);
+		data->val_out = rtl_readphy(tp, data->reg_num & 0x1f);
 		return 0;
 
 	case SIOCSMIIREG:
-		mdio_write(tp->mmio_addr, data->reg_num & 0x1f, data->val_in);
+		rtl_writephy(tp, data->reg_num & 0x1f, data->val_in);
 		return 0;
 	}
 	return -EOPNOTSUPP;
@@ -2175,6 +2803,183 @@ static const struct net_device_ops rtl81
 
 };
 
+static void __devinit rtl_init_mdio_ops(struct rtl8169_private *tp)
+{
+	struct mdio_ops *ops = &tp->mdio_ops;
+
+	switch (tp->mac_version) {
+	case RTL_GIGA_MAC_VER_27:
+		ops->write	= r8168dp_1_mdio_write;
+		ops->read	= r8168dp_1_mdio_read;
+		break;
+	case RTL_GIGA_MAC_VER_28:
+		ops->write	= r8168dp_2_mdio_write;
+		ops->read	= r8168dp_2_mdio_read;
+		break;
+	default:
+		ops->write	= r8169_mdio_write;
+		ops->read	= r8169_mdio_read;
+		break;
+	}
+}
+
+static void r810x_phy_power_down(struct rtl8169_private *tp)
+{
+	rtl_writephy(tp, 0x1f, 0x0000);
+	rtl_writephy(tp, MII_BMCR, BMCR_PDOWN);
+}
+
+static void r810x_phy_power_up(struct rtl8169_private *tp)
+{
+	rtl_writephy(tp, 0x1f, 0x0000);
+	rtl_writephy(tp, MII_BMCR, BMCR_ANENABLE);
+}
+
+static void r810x_pll_power_down(struct rtl8169_private *tp)
+{
+	if (__rtl8169_get_wol(tp) & WAKE_ANY) {
+		rtl_writephy(tp, 0x1f, 0x0000);
+		rtl_writephy(tp, MII_BMCR, 0x0000);
+		return;
+	}
+
+	r810x_phy_power_down(tp);
+}
+
+static void r810x_pll_power_up(struct rtl8169_private *tp)
+{
+	r810x_phy_power_up(tp);
+}
+
+static void r8168_phy_power_up(struct rtl8169_private *tp)
+{
+	rtl_writephy(tp, 0x1f, 0x0000);
+	rtl_writephy(tp, 0x0e, 0x0000);
+	rtl_writephy(tp, MII_BMCR, BMCR_ANENABLE);
+}
+
+static void r8168_phy_power_down(struct rtl8169_private *tp)
+{
+	rtl_writephy(tp, 0x1f, 0x0000);
+	rtl_writephy(tp, 0x0e, 0x0200);
+	rtl_writephy(tp, MII_BMCR, BMCR_PDOWN);
+}
+
+static void r8168_pll_power_down(struct rtl8169_private *tp)
+{
+	void __iomem *ioaddr = tp->mmio_addr;
+
+	if (((tp->mac_version == RTL_GIGA_MAC_VER_27) ||
+	     (tp->mac_version == RTL_GIGA_MAC_VER_28)) &&
+	    (ocp_read(tp, 0x0f, 0x0010) & 0x00008000)) {
+		return;
+	}
+
+	if (((tp->mac_version == RTL_GIGA_MAC_VER_23) ||
+	     (tp->mac_version == RTL_GIGA_MAC_VER_24)) &&
+	    (RTL_R16(CPlusCmd) & ASF)) {
+		return;
+	}
+
+	if (__rtl8169_get_wol(tp) & WAKE_ANY) {
+		rtl_writephy(tp, 0x1f, 0x0000);
+		rtl_writephy(tp, MII_BMCR, 0x0000);
+
+		RTL_W32(RxConfig, RTL_R32(RxConfig) |
+			AcceptBroadcast | AcceptMulticast | AcceptMyPhys);
+		return;
+	}
+
+	r8168_phy_power_down(tp);
+
+	switch (tp->mac_version) {
+	case RTL_GIGA_MAC_VER_25:
+	case RTL_GIGA_MAC_VER_26:
+	case RTL_GIGA_MAC_VER_27:
+	case RTL_GIGA_MAC_VER_28:
+		RTL_W8(PMCH, RTL_R8(PMCH) & ~0x80);
+		break;
+	}
+}
+
+static void r8168_pll_power_up(struct rtl8169_private *tp)
+{
+	void __iomem *ioaddr = tp->mmio_addr;
+
+	if (((tp->mac_version == RTL_GIGA_MAC_VER_27) ||
+	     (tp->mac_version == RTL_GIGA_MAC_VER_28)) &&
+	    (ocp_read(tp, 0x0f, 0x0010) & 0x00008000)) {
+		return;
+	}
+
+	switch (tp->mac_version) {
+	case RTL_GIGA_MAC_VER_25:
+	case RTL_GIGA_MAC_VER_26:
+	case RTL_GIGA_MAC_VER_27:
+	case RTL_GIGA_MAC_VER_28:
+		RTL_W8(PMCH, RTL_R8(PMCH) | 0x80);
+		break;
+	}
+
+	r8168_phy_power_up(tp);
+}
+
+static void rtl_pll_power_op(struct rtl8169_private *tp,
+			     void (*op)(struct rtl8169_private *))
+{
+	if (op)
+		op(tp);
+}
+
+static void rtl_pll_power_down(struct rtl8169_private *tp)
+{
+	rtl_pll_power_op(tp, tp->pll_power_ops.down);
+}
+
+static void rtl_pll_power_up(struct rtl8169_private *tp)
+{
+	rtl_pll_power_op(tp, tp->pll_power_ops.up);
+}
+
+static void __devinit rtl_init_pll_power_ops(struct rtl8169_private *tp)
+{
+	struct pll_power_ops *ops = &tp->pll_power_ops;
+
+	switch (tp->mac_version) {
+	case RTL_GIGA_MAC_VER_07:
+	case RTL_GIGA_MAC_VER_08:
+	case RTL_GIGA_MAC_VER_09:
+	case RTL_GIGA_MAC_VER_10:
+	case RTL_GIGA_MAC_VER_16:
+		ops->down	= r810x_pll_power_down;
+		ops->up		= r810x_pll_power_up;
+		break;
+
+	case RTL_GIGA_MAC_VER_11:
+	case RTL_GIGA_MAC_VER_12:
+	case RTL_GIGA_MAC_VER_17:
+	case RTL_GIGA_MAC_VER_18:
+	case RTL_GIGA_MAC_VER_19:
+	case RTL_GIGA_MAC_VER_20:
+	case RTL_GIGA_MAC_VER_21:
+	case RTL_GIGA_MAC_VER_22:
+	case RTL_GIGA_MAC_VER_23:
+	case RTL_GIGA_MAC_VER_24:
+	case RTL_GIGA_MAC_VER_25:
+	case RTL_GIGA_MAC_VER_26:
+	case RTL_GIGA_MAC_VER_27:
+	case RTL_GIGA_MAC_VER_28:
+		ops->down	= r8168_pll_power_down;
+		ops->up		= r8168_pll_power_up;
+		break;
+
+	default:
+		ops->down	= NULL;
+		ops->up		= NULL;
+		break;
+	}
+}
+
 static int __devinit
 rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
@@ -2215,6 +3020,11 @@ rtl8169_init_one(struct pci_dev *pdev, c
 	mii->reg_num_mask = 0x1f;
 	mii->supports_gmii = !!(cfg->features & RTL_FEATURE_GMII);
 
+	/* disable ASPM completely as that cause random device stop working
+	 * problems as well as full system hangs for some PCIe devices users */
+	pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 |
+				     PCIE_LINK_STATE_CLKPM);
+
 	/* enable device (incl. PCI PM wakeup and hotplug setup) */
 	rc = pci_enable_device(pdev);
 	if (rc < 0) {
@@ -2248,7 +3058,7 @@ rtl8169_init_one(struct pci_dev *pdev, c
 		goto err_out_mwi_2;
 	}
 
-	tp->cp_cmd = PCIMulRW | RxChkSum;
+	tp->cp_cmd = RxChkSum;
 
 	if ((sizeof(dma_addr_t) > 4) &&
 	    !pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) && use_dac) {
@@ -2293,6 +3103,9 @@ rtl8169_init_one(struct pci_dev *pdev, c
 	/* Identify chip attached to board */
 	rtl8169_get_mac_version(tp, ioaddr);
 
+	rtl_init_mdio_ops(tp);
+	rtl_init_pll_power_ops(tp);
+
 	/* Use appropriate default if unknown */
 	if (tp->mac_version == RTL_GIGA_MAC_NONE) {
 		netif_notice(tp, probe, dev,
@@ -2383,20 +3196,18 @@ rtl8169_init_one(struct pci_dev *pdev, c
 		   dev->base_addr, dev->dev_addr,
 		   (u32)(RTL_R32(TxConfig) & 0x9cf0f8ff), dev->irq);
 
-	rtl8169_init_phy(dev, tp);
-
-	/*
-	 * Pretend we are using VLANs; This bypasses a nasty bug where
-	 * Interrupts stop flowing on high load on 8110SCd controllers.
-	 */
-	if (tp->mac_version == RTL_GIGA_MAC_VER_05)
-		RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) | RxVlan);
+	if ((tp->mac_version == RTL_GIGA_MAC_VER_27) ||
+	    (tp->mac_version == RTL_GIGA_MAC_VER_28)) {
+		rtl8168_driver_start(tp);
+	}
 
 	device_set_wakeup_enable(&pdev->dev, tp->features & RTL_FEATURE_WOL);
 
 	if (pci_dev_run_wake(pdev))
 		pm_runtime_put_noidle(&pdev->dev);
 
+	netif_carrier_off(dev);
+
 out:
 	return rc;
 
@@ -2418,7 +3229,14 @@ static void __devexit rtl8169_remove_one
 	struct net_device *dev = pci_get_drvdata(pdev);
 	struct rtl8169_private *tp = netdev_priv(dev);
 
-	flush_scheduled_work();
+	if ((tp->mac_version == RTL_GIGA_MAC_VER_27) ||
+	    (tp->mac_version == RTL_GIGA_MAC_VER_28)) {
+		rtl8168_driver_stop(tp);
+	}
+
+	cancel_delayed_work_sync(&tp->task);
+
+	rtl_release_firmware(tp);
 
 	unregister_netdev(dev);
 
@@ -2436,6 +3254,7 @@ static void __devexit rtl8169_remove_one
 static int rtl8169_open(struct net_device *dev)
 {
 	struct rtl8169_private *tp = netdev_priv(dev);
+	void __iomem *ioaddr = tp->mmio_addr;
 	struct pci_dev *pdev = tp->pci_dev;
 	int retval = -ENOMEM;
 
@@ -2471,6 +3290,17 @@ static int rtl8169_open(struct net_devic
 
 	napi_enable(&tp->napi);
 
+	rtl8169_init_phy(dev, tp);
+
+	/*
+	 * Pretend we are using VLANs; This bypasses a nasty bug where
+	 * Interrupts stop flowing on high load on 8110SCd controllers.
+	 */
+	if (tp->mac_version == RTL_GIGA_MAC_VER_05)
+		RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) | RxVlan);
+
+	rtl_pll_power_up(tp);
+
 	rtl_hw_start(dev);
 
 	rtl8169_request_timer(dev);
@@ -2478,7 +3308,7 @@ static int rtl8169_open(struct net_devic
 	tp->saved_wolopts = 0;
 	pm_runtime_put_noidle(&pdev->dev);
 
-	rtl8169_check_link_status(dev, tp, tp->mmio_addr);
+	rtl8169_check_link_status(dev, tp, ioaddr);
 out:
 	return retval;
 
@@ -2497,11 +3327,20 @@ err_pm_runtime_put:
 	goto out;
 }
 
-static void rtl8169_hw_reset(void __iomem *ioaddr)
+static void rtl8169_hw_reset(struct rtl8169_private *tp)
 {
+	void __iomem *ioaddr = tp->mmio_addr;
+
 	/* Disable interrupts */
 	rtl8169_irq_mask_and_ack(ioaddr);
 
+	if (tp->mac_version == RTL_GIGA_MAC_VER_27 ||
+	    tp->mac_version == RTL_GIGA_MAC_VER_28) {
+		while (RTL_R8(TxPoll) & NPQ)
+			udelay(20);
+
+	}
+
 	/* Reset the chipset */
 	RTL_W8(ChipCmd, CmdReset);
 
@@ -2615,7 +3454,7 @@ static void rtl_hw_start_8169(struct net
 	    (tp->mac_version == RTL_GIGA_MAC_VER_04))
 		RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
 
-	RTL_W8(EarlyTxThres, EarlyTxThld);
+	RTL_W8(EarlyTxThres, NoEarlyTx);
 
 	rtl_set_rx_max_size(ioaddr, rx_buf_sz);
 
@@ -2685,12 +3524,22 @@ static void rtl_tx_performance_tweak(str
 	}
 }
 
-static void rtl_csi_access_enable(void __iomem *ioaddr)
+static void rtl_csi_access_enable(void __iomem *ioaddr, u32 bits)
 {
 	u32 csi;
 
 	csi = rtl_csi_read(ioaddr, 0x070c) & 0x00ffffff;
-	rtl_csi_write(ioaddr, 0x070c, csi | 0x27000000);
+	rtl_csi_write(ioaddr, 0x070c, csi | bits);
+}
+
+static void rtl_csi_access_enable_1(void __iomem *ioaddr)
+{
+	rtl_csi_access_enable(ioaddr, 0x17000000);
+}
+
+static void rtl_csi_access_enable_2(void __iomem *ioaddr)
+{
+	rtl_csi_access_enable(ioaddr, 0x27000000);
 }
 
 struct ephy_info {
@@ -2725,6 +3574,21 @@ static void rtl_disable_clock_request(st
 	}
 }
 
+static void rtl_enable_clock_request(struct pci_dev *pdev)
+{
+	struct net_device *dev = pci_get_drvdata(pdev);
+	struct rtl8169_private *tp = netdev_priv(dev);
+	int cap = tp->pcie_cap;
+
+	if (cap) {
+		u16 ctl;
+
+		pci_read_config_word(pdev, cap + PCI_EXP_LNKCTL, &ctl);
+		ctl |= PCI_EXP_LNKCTL_CLKREQ_EN;
+		pci_write_config_word(pdev, cap + PCI_EXP_LNKCTL, ctl);
+	}
+}
+
 #define R8168_CPCMD_QUIRK_MASK (\
 	EnableBist | \
 	Mac_dbgo_oe | \
@@ -2750,7 +3614,7 @@ static void rtl_hw_start_8168bef(void __
 {
 	rtl_hw_start_8168bb(ioaddr, pdev);
 
-	RTL_W8(EarlyTxThres, EarlyTxThld);
+	RTL_W8(MaxTxPacketSize, TxPacketMax);
 
 	RTL_W8(Config4, RTL_R8(Config4) & ~(1 << 0));
 }
@@ -2778,7 +3642,7 @@ static void rtl_hw_start_8168cp_1(void _
 		{ 0x07, 0,	0x2000 }
 	};
 
-	rtl_csi_access_enable(ioaddr);
+	rtl_csi_access_enable_2(ioaddr);
 
 	rtl_ephy_init(ioaddr, e_info_8168cp, ARRAY_SIZE(e_info_8168cp));
 
@@ -2787,7 +3651,7 @@ static void rtl_hw_start_8168cp_1(void _
 
 static void rtl_hw_start_8168cp_2(void __iomem *ioaddr, struct pci_dev *pdev)
 {
-	rtl_csi_access_enable(ioaddr);
+	rtl_csi_access_enable_2(ioaddr);
 
 	RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en);
 
@@ -2798,14 +3662,14 @@ static void rtl_hw_start_8168cp_2(void _
 
 static void rtl_hw_start_8168cp_3(void __iomem *ioaddr, struct pci_dev *pdev)
 {
-	rtl_csi_access_enable(ioaddr);
+	rtl_csi_access_enable_2(ioaddr);
 
 	RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en);
 
 	/* Magic. */
 	RTL_W8(DBG_REG, 0x20);
 
-	RTL_W8(EarlyTxThres, EarlyTxThld);
+	RTL_W8(MaxTxPacketSize, TxPacketMax);
 
 	rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
 
@@ -2820,7 +3684,7 @@ static void rtl_hw_start_8168c_1(void __
 		{ 0x06, 0x0080,	0x0000 }
 	};
 
-	rtl_csi_access_enable(ioaddr);
+	rtl_csi_access_enable_2(ioaddr);
 
 	RTL_W8(DBG_REG, 0x06 | FIX_NAK_1 | FIX_NAK_2);
 
@@ -2836,7 +3700,7 @@ static void rtl_hw_start_8168c_2(void __
 		{ 0x03, 0x0400,	0x0220 }
 	};
 
-	rtl_csi_access_enable(ioaddr);
+	rtl_csi_access_enable_2(ioaddr);
 
 	rtl_ephy_init(ioaddr, e_info_8168c_2, ARRAY_SIZE(e_info_8168c_2));
 
@@ -2850,24 +3714,50 @@ static void rtl_hw_start_8168c_3(void __
 
 static void rtl_hw_start_8168c_4(void __iomem *ioaddr, struct pci_dev *pdev)
 {
-	rtl_csi_access_enable(ioaddr);
+	rtl_csi_access_enable_2(ioaddr);
 
 	__rtl_hw_start_8168cp(ioaddr, pdev);
 }
 
 static void rtl_hw_start_8168d(void __iomem *ioaddr, struct pci_dev *pdev)
 {
-	rtl_csi_access_enable(ioaddr);
+	rtl_csi_access_enable_2(ioaddr);
 
 	rtl_disable_clock_request(pdev);
 
-	RTL_W8(EarlyTxThres, EarlyTxThld);
+	RTL_W8(MaxTxPacketSize, TxPacketMax);
 
 	rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
 
 	RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK);
 }
 
+static void rtl_hw_start_8168d_4(void __iomem *ioaddr, struct pci_dev *pdev)
+{
+	static const struct ephy_info e_info_8168d_4[] = {
+		{ 0x0b, ~0,	0x48 },
+		{ 0x19, 0x20,	0x50 },
+		{ 0x0c, ~0,	0x20 }
+	};
+	int i;
+
+	rtl_csi_access_enable_1(ioaddr);
+
+	rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
+
+	RTL_W8(MaxTxPacketSize, TxPacketMax);
+
+	for (i = 0; i < ARRAY_SIZE(e_info_8168d_4); i++) {
+		const struct ephy_info *e = e_info_8168d_4 + i;
+		u16 w;
+
+		w = rtl_ephy_read(ioaddr, e->offset);
+		rtl_ephy_write(ioaddr, 0x03, (w & e->mask) | e->bits);
+	}
+
+	rtl_enable_clock_request(pdev);
+}
+
 static void rtl_hw_start_8168(struct net_device *dev)
 {
 	struct rtl8169_private *tp = netdev_priv(dev);
@@ -2876,7 +3766,7 @@ static void rtl_hw_start_8168(struct net
 
 	RTL_W8(Cfg9346, Cfg9346_Unlock);
 
-	RTL_W8(EarlyTxThres, EarlyTxThld);
+	RTL_W8(MaxTxPacketSize, TxPacketMax);
 
 	rtl_set_rx_max_size(ioaddr, rx_buf_sz);
 
@@ -2887,7 +3777,8 @@ static void rtl_hw_start_8168(struct net
 	RTL_W16(IntrMitigate, 0x5151);
 
 	/* Work around for RxFIFO overflow. */
-	if (tp->mac_version == RTL_GIGA_MAC_VER_11) {
+	if (tp->mac_version == RTL_GIGA_MAC_VER_11 ||
+	    tp->mac_version == RTL_GIGA_MAC_VER_22) {
 		tp->intr_event |= RxFIFOOver | PCSTimeout;
 		tp->intr_event &= ~RxOverflow;
 	}
@@ -2945,6 +3836,10 @@ static void rtl_hw_start_8168(struct net
 		rtl_hw_start_8168d(ioaddr, pdev);
 	break;
 
+	case RTL_GIGA_MAC_VER_28:
+		rtl_hw_start_8168d_4(ioaddr, pdev);
+	break;
+
 	default:
 		printk(KERN_ERR PFX "%s: unknown chipset (mac_version = %d).\n",
 			dev->name, tp->mac_version);
@@ -2969,8 +3864,7 @@ static void rtl_hw_start_8168(struct net
 	Cxpl_dbg_sel | \
 	ASF | \
 	PktCntrDisable | \
-	PCIDAC | \
-	PCIMulRW)
+	Mac_dbgo_sel)
 
 static void rtl_hw_start_8102e_1(void __iomem *ioaddr, struct pci_dev *pdev)
 {
@@ -2986,7 +3880,7 @@ static void rtl_hw_start_8102e_1(void __
 	};
 	u8 cfg1;
 
-	rtl_csi_access_enable(ioaddr);
+	rtl_csi_access_enable_2(ioaddr);
 
 	RTL_W8(DBG_REG, FIX_NAK_1);
 
@@ -3000,21 +3894,17 @@ static void rtl_hw_start_8102e_1(void __
 	if ((cfg1 & LEDS0) && (cfg1 & LEDS1))
 		RTL_W8(Config1, cfg1 & ~LEDS0);
 
-	RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R810X_CPCMD_QUIRK_MASK);
-
 	rtl_ephy_init(ioaddr, e_info_8102e_1, ARRAY_SIZE(e_info_8102e_1));
 }
 
 static void rtl_hw_start_8102e_2(void __iomem *ioaddr, struct pci_dev *pdev)
 {
-	rtl_csi_access_enable(ioaddr);
+	rtl_csi_access_enable_2(ioaddr);
 
 	rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
 
 	RTL_W8(Config1, MEMMAP | IOMAP | VPD | PMEnable);
 	RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en);
-
-	RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R810X_CPCMD_QUIRK_MASK);
 }
 
 static void rtl_hw_start_8102e_3(void __iomem *ioaddr, struct pci_dev *pdev)
@@ -3040,6 +3930,8 @@ static void rtl_hw_start_8101(struct net
 		}
 	}
 
+	RTL_W8(Cfg9346, Cfg9346_Unlock);
+
 	switch (tp->mac_version) {
 	case RTL_GIGA_MAC_VER_07:
 		rtl_hw_start_8102e_1(ioaddr, pdev);
@@ -3054,14 +3946,13 @@ static void rtl_hw_start_8101(struct net
 		break;
 	}
 
-	RTL_W8(Cfg9346, Cfg9346_Unlock);
+	RTL_W8(Cfg9346, Cfg9346_Lock);
 
-	RTL_W8(EarlyTxThres, EarlyTxThld);
+	RTL_W8(MaxTxPacketSize, TxPacketMax);
 
 	rtl_set_rx_max_size(ioaddr, rx_buf_sz);
 
-	tp->cp_cmd |= rtl_rw_cpluscmd(ioaddr) | PCIMulRW;
-
+	tp->cp_cmd &= ~R810X_CPCMD_QUIRK_MASK;
 	RTL_W16(CPlusCmd, tp->cp_cmd);
 
 	RTL_W16(IntrMitigate, 0x0000);
@@ -3071,14 +3962,10 @@ static void rtl_hw_start_8101(struct net
 	RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
 	rtl_set_rx_tx_config_registers(tp);
 
-	RTL_W8(Cfg9346, Cfg9346_Lock);
-
 	RTL_R8(IntrMask);
 
 	rtl_set_rx_mode(dev);
 
-	RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
-
 	RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xf000);
 
 	RTL_W16(IntrMask, tp->intr_event);
@@ -3357,7 +4244,7 @@ static void rtl8169_tx_timeout(struct ne
 {
 	struct rtl8169_private *tp = netdev_priv(dev);
 
-	rtl8169_hw_reset(tp->mmio_addr);
+	rtl8169_hw_reset(tp);
 
 	/* Let's wait a bit while any (async) irq lands on */
 	rtl8169_schedule_work(dev, rtl8169_reset_task);
@@ -3515,7 +4402,6 @@ static void rtl8169_pcierr_interrupt(str
 {
 	struct rtl8169_private *tp = netdev_priv(dev);
 	struct pci_dev *pdev = tp->pci_dev;
-	void __iomem *ioaddr = tp->mmio_addr;
 	u16 pci_status, pci_cmd;
 
 	pci_read_config_word(pdev, PCI_COMMAND, &pci_cmd);
@@ -3546,13 +4432,15 @@ static void rtl8169_pcierr_interrupt(str
 
 	/* The infamous DAC f*ckup only happens at boot time */
 	if ((tp->cp_cmd & PCIDAC) && !tp->dirty_rx && !tp->cur_rx) {
+		void __iomem *ioaddr = tp->mmio_addr;
+
 		netif_info(tp, intr, dev, "disabling PCI DAC\n");
 		tp->cp_cmd &= ~PCIDAC;
 		RTL_W16(CPlusCmd, tp->cp_cmd);
 		dev->features &= ~NETIF_F_HIGHDMA;
 	}
 
-	rtl8169_hw_reset(ioaddr);
+	rtl8169_hw_reset(tp);
 
 	rtl8169_schedule_work(dev, rtl8169_reinit_task);
 }
@@ -3764,12 +4652,33 @@ static irqreturn_t rtl8169_interrupt(int
 			break;
 		}
 
-		/* Work around for rx fifo overflow */
-		if (unlikely(status & RxFIFOOver) &&
-		(tp->mac_version == RTL_GIGA_MAC_VER_11)) {
-			netif_stop_queue(dev);
-			rtl8169_tx_timeout(dev);
-			break;
+		if (unlikely(status & RxFIFOOver)) {
+			switch (tp->mac_version) {
+			/* Work around for rx fifo overflow */
+			case RTL_GIGA_MAC_VER_11:
+			case RTL_GIGA_MAC_VER_22:
+			case RTL_GIGA_MAC_VER_26:
+				netif_stop_queue(dev);
+				rtl8169_tx_timeout(dev);
+				goto done;
+			/* Testers needed. */
+			case RTL_GIGA_MAC_VER_17:
+			case RTL_GIGA_MAC_VER_19:
+			case RTL_GIGA_MAC_VER_20:
+			case RTL_GIGA_MAC_VER_21:
+			case RTL_GIGA_MAC_VER_23:
+			case RTL_GIGA_MAC_VER_24:
+			case RTL_GIGA_MAC_VER_27:
+			case RTL_GIGA_MAC_VER_28:
+			/* Experimental science. Pktgen proof. */
+			case RTL_GIGA_MAC_VER_12:
+			case RTL_GIGA_MAC_VER_25:
+				if (status == RxFIFOOver)
+					goto done;
+				break;
+			default:
+				break;
+			}
 		}
 
 		if (unlikely(status & SYSErr)) {
@@ -3805,7 +4714,7 @@ static irqreturn_t rtl8169_interrupt(int
 			(status & RxFIFOOver) ? (status | RxOverflow) : status);
 		status = RTL_R16(IntrStatus);
 	}
-
+done:
 	return IRQ_RETVAL(handled);
 }
 
@@ -3879,6 +4788,8 @@ static void rtl8169_down(struct net_devi
 	rtl8169_tx_clear(tp);
 
 	rtl8169_rx_clear(tp);
+
+	rtl_pll_power_down(tp);
 }
 
 static int rtl8169_close(struct net_device *dev)
@@ -3983,9 +4894,13 @@ static struct net_device_stats *rtl8169_
 
 static void rtl8169_net_suspend(struct net_device *dev)
 {
+	struct rtl8169_private *tp = netdev_priv(dev);
+
 	if (!netif_running(dev))
 		return;
 
+	rtl_pll_power_down(tp);
+
 	netif_device_detach(dev);
 	netif_stop_queue(dev);
 }
@@ -4004,7 +4919,12 @@ static int rtl8169_suspend(struct device
 
 static void __rtl8169_resume(struct net_device *dev)
 {
+	struct rtl8169_private *tp = netdev_priv(dev);
+
 	netif_device_attach(dev);
+
+	rtl_pll_power_up(tp);
+
 	rtl8169_schedule_work(dev, rtl8169_reset_task);
 }
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/s2io.c linux-libre-2.6.38-gnu1/drivers/net/s2io.c
--- linux-libre-2.6.37-gnu1/drivers/net/s2io.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/s2io.c	2011-03-14 21:20:32.000000000 -0400
@@ -88,14 +88,14 @@
 #include "s2io.h"
 #include "s2io-regs.h"
 
-#define DRV_VERSION "2.0.26.27"
+#define DRV_VERSION "2.0.26.28"
 
 /* S2io Driver name & version. */
-static char s2io_driver_name[] = "Neterion";
-static char s2io_driver_version[] = DRV_VERSION;
+static const char s2io_driver_name[] = "Neterion";
+static const char s2io_driver_version[] = DRV_VERSION;
 
-static int rxd_size[2] = {32, 48};
-static int rxd_count[2] = {127, 85};
+static const int rxd_size[2] = {32, 48};
+static const int rxd_count[2] = {127, 85};
 
 static inline int RXD_IS_UP2DT(struct RxD_t *rxdp)
 {
@@ -3598,10 +3598,12 @@ static int s2io_set_swapper(struct s2io_
 	val64 = readq(&bar0->pif_rd_swapper_fb);
 	if (val64 != 0x0123456789ABCDEFULL) {
 		int i = 0;
-		u64 value[] = { 0xC30000C3C30000C3ULL,   /* FE=1, SE=1 */
-				0x8100008181000081ULL,  /* FE=1, SE=0 */
-				0x4200004242000042ULL,  /* FE=0, SE=1 */
-				0};                     /* FE=0, SE=0 */
+		static const u64 value[] = {
+			0xC30000C3C30000C3ULL,	/* FE=1, SE=1 */
+			0x8100008181000081ULL,	/* FE=1, SE=0 */
+			0x4200004242000042ULL,	/* FE=0, SE=1 */
+			0			/* FE=0, SE=0 */
+		};
 
 		while (i < 4) {
 			writeq(value[i], &bar0->swapper_ctrl);
@@ -3627,10 +3629,12 @@ static int s2io_set_swapper(struct s2io_
 
 	if (val64 != valt) {
 		int i = 0;
-		u64 value[] = { 0x00C3C30000C3C300ULL,  /* FE=1, SE=1 */
-				0x0081810000818100ULL,  /* FE=1, SE=0 */
-				0x0042420000424200ULL,  /* FE=0, SE=1 */
-				0};                     /* FE=0, SE=0 */
+		static const u64 value[] = {
+			0x00C3C30000C3C300ULL,	/* FE=1, SE=1 */
+			0x0081810000818100ULL,	/* FE=1, SE=0 */
+			0x0042420000424200ULL,	/* FE=0, SE=1 */
+			0			/* FE=0, SE=0 */
+		};
 
 		while (i < 4) {
 			writeq((value[i] | valr), &bar0->swapper_ctrl);
@@ -5568,30 +5572,27 @@ static void s2io_ethtool_gringparam(stru
 	struct s2io_nic *sp = netdev_priv(dev);
 	int i, tx_desc_count = 0, rx_desc_count = 0;
 
-	if (sp->rxd_mode == RXD_MODE_1)
+	if (sp->rxd_mode == RXD_MODE_1) {
 		ering->rx_max_pending = MAX_RX_DESC_1;
-	else if (sp->rxd_mode == RXD_MODE_3B)
+		ering->rx_jumbo_max_pending = MAX_RX_DESC_1;
+	} else {
 		ering->rx_max_pending = MAX_RX_DESC_2;
+		ering->rx_jumbo_max_pending = MAX_RX_DESC_2;
+	}
 
+	ering->rx_mini_max_pending = 0;
 	ering->tx_max_pending = MAX_TX_DESC;
-	for (i = 0 ; i < sp->config.tx_fifo_num ; i++)
-		tx_desc_count += sp->config.tx_cfg[i].fifo_len;
 
-	DBG_PRINT(INFO_DBG, "max txds: %d\n", sp->config.max_txds);
-	ering->tx_pending = tx_desc_count;
-	rx_desc_count = 0;
-	for (i = 0 ; i < sp->config.rx_ring_num ; i++)
+	for (i = 0; i < sp->config.rx_ring_num; i++)
 		rx_desc_count += sp->config.rx_cfg[i].num_rxd;
-
 	ering->rx_pending = rx_desc_count;
-
-	ering->rx_mini_max_pending = 0;
-	ering->rx_mini_pending = 0;
-	if (sp->rxd_mode == RXD_MODE_1)
-		ering->rx_jumbo_max_pending = MAX_RX_DESC_1;
-	else if (sp->rxd_mode == RXD_MODE_3B)
-		ering->rx_jumbo_max_pending = MAX_RX_DESC_2;
 	ering->rx_jumbo_pending = rx_desc_count;
+	ering->rx_mini_pending = 0;
+
+	for (i = 0; i < sp->config.tx_fifo_num; i++)
+		tx_desc_count += sp->config.tx_cfg[i].fifo_len;
+	ering->tx_pending = tx_desc_count;
+	DBG_PRINT(INFO_DBG, "max txds: %d\n", sp->config.max_txds);
 }
 
 /**
@@ -7692,6 +7693,8 @@ static void s2io_init_pci(struct s2io_ni
 static int s2io_verify_parm(struct pci_dev *pdev, u8 *dev_intr_type,
 			    u8 *dev_multiq)
 {
+	int i;
+
 	if ((tx_fifo_num > MAX_TX_FIFOS) || (tx_fifo_num < 1)) {
 		DBG_PRINT(ERR_DBG, "Requested number of tx fifos "
 			  "(%d) not supported\n", tx_fifo_num);
@@ -7750,6 +7753,15 @@ static int s2io_verify_parm(struct pci_d
 		DBG_PRINT(ERR_DBG, "Defaulting to 1-buffer mode\n");
 		rx_ring_mode = 1;
 	}
+
+	for (i = 0; i < MAX_RX_RINGS; i++)
+		if (rx_ring_sz[i] > MAX_RX_BLOCKS_PER_RING) {
+			DBG_PRINT(ERR_DBG, "Requested rx ring size not "
+				  "supported\nDefaulting to %d\n",
+				  MAX_RX_BLOCKS_PER_RING);
+			rx_ring_sz[i] = MAX_RX_BLOCKS_PER_RING;
+		}
+
 	return SUCCESS;
 }
 
@@ -8321,8 +8333,7 @@ mem_alloc_failed:
 
 static void __devexit s2io_rem_nic(struct pci_dev *pdev)
 {
-	struct net_device *dev =
-		(struct net_device *)pci_get_drvdata(pdev);
+	struct net_device *dev = pci_get_drvdata(pdev);
 	struct s2io_nic *sp;
 
 	if (dev == NULL) {
@@ -8330,9 +8341,11 @@ static void __devexit s2io_rem_nic(struc
 		return;
 	}
 
-	flush_scheduled_work();
-
 	sp = netdev_priv(dev);
+
+	cancel_work_sync(&sp->rst_timer_task);
+	cancel_work_sync(&sp->set_link_task);
+
 	unregister_netdev(dev);
 
 	free_shared_mem(sp);
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/s2io.h linux-libre-2.6.38-gnu1/drivers/net/s2io.h
--- linux-libre-2.6.37-gnu1/drivers/net/s2io.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/s2io.h	2011-03-14 21:20:32.000000000 -0400
@@ -355,13 +355,12 @@ struct stat_block {
 #define FIFO_OTHER_MAX_NUM			1
 
 
-#define MAX_RX_DESC_1  (MAX_RX_RINGS * MAX_RX_BLOCKS_PER_RING * 127 )
-#define MAX_RX_DESC_2  (MAX_RX_RINGS * MAX_RX_BLOCKS_PER_RING * 85 )
-#define MAX_RX_DESC_3  (MAX_RX_RINGS * MAX_RX_BLOCKS_PER_RING * 85 )
+#define MAX_RX_DESC_1  (MAX_RX_RINGS * MAX_RX_BLOCKS_PER_RING * 128)
+#define MAX_RX_DESC_2  (MAX_RX_RINGS * MAX_RX_BLOCKS_PER_RING * 86)
 #define MAX_TX_DESC    (MAX_AVAILABLE_TXDS)
 
 /* FIFO mappings for all possible number of fifos configured */
-static int fifo_map[][MAX_TX_FIFOS] = {
+static const int fifo_map[][MAX_TX_FIFOS] = {
 	{0, 0, 0, 0, 0, 0, 0, 0},
 	{0, 0, 0, 0, 1, 1, 1, 1},
 	{0, 0, 0, 1, 1, 1, 2, 2},
@@ -372,7 +371,7 @@ static int fifo_map[][MAX_TX_FIFOS] = {
 	{0, 1, 2, 3, 4, 5, 6, 7},
 };
 
-static u16 fifo_selector[MAX_TX_FIFOS] = {0, 1, 3, 3, 7, 7, 7, 7};
+static const u16 fifo_selector[MAX_TX_FIFOS] = {0, 1, 3, 3, 7, 7, 7, 7};
 
 /* Maintains Per FIFO related information. */
 struct tx_fifo_config {
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/sc92031.c linux-libre-2.6.38-gnu1/drivers/net/sc92031.c
--- linux-libre-2.6.37-gnu1/drivers/net/sc92031.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/sc92031.c	2011-03-14 21:20:32.000000000 -0400
@@ -1449,7 +1449,8 @@ static int __devinit sc92031_probe(struc
 	dev->irq = pdev->irq;
 
 	/* faked with skb_copy_and_csum_dev */
-	dev->features = NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_HIGHDMA;
+	dev->features = NETIF_F_SG | NETIF_F_HIGHDMA |
+		NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
 
 	dev->netdev_ops		= &sc92031_netdev_ops;
 	dev->watchdog_timeo	= TX_TIMEOUT;
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/sfc/efx.c linux-libre-2.6.38-gnu1/drivers/net/sfc/efx.c
--- linux-libre-2.6.37-gnu1/drivers/net/sfc/efx.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/sfc/efx.c	2011-03-14 21:20:32.000000000 -0400
@@ -23,7 +23,6 @@
 #include <linux/gfp.h>
 #include "net_driver.h"
 #include "efx.h"
-#include "mdio_10g.h"
 #include "nic.h"
 
 #include "mcdi.h"
@@ -462,9 +461,6 @@ efx_alloc_channel(struct efx_nic *efx, i
 		}
 	}
 
-	spin_lock_init(&channel->tx_stop_lock);
-	atomic_set(&channel->tx_stop_count, 1);
-
 	rx_queue = &channel->rx_queue;
 	rx_queue->efx = efx;
 	setup_timer(&rx_queue->slow_fill, efx_rx_slow_fill,
@@ -921,6 +917,7 @@ static void efx_mac_work(struct work_str
 
 static int efx_probe_port(struct efx_nic *efx)
 {
+	unsigned char *perm_addr;
 	int rc;
 
 	netif_dbg(efx, probe, efx->net_dev, "create port\n");
@@ -934,11 +931,12 @@ static int efx_probe_port(struct efx_nic
 		return rc;
 
 	/* Sanity check MAC address */
-	if (is_valid_ether_addr(efx->mac_address)) {
-		memcpy(efx->net_dev->dev_addr, efx->mac_address, ETH_ALEN);
+	perm_addr = efx->net_dev->perm_addr;
+	if (is_valid_ether_addr(perm_addr)) {
+		memcpy(efx->net_dev->dev_addr, perm_addr, ETH_ALEN);
 	} else {
 		netif_err(efx, probe, efx->net_dev, "invalid MAC address %pM\n",
-			  efx->mac_address);
+			  perm_addr);
 		if (!allow_bad_hwaddr) {
 			rc = -EINVAL;
 			goto err;
@@ -1155,6 +1153,9 @@ static int efx_wanted_channels(void)
 	int count;
 	int cpu;
 
+	if (rss_cpus)
+		return rss_cpus;
+
 	if (unlikely(!zalloc_cpumask_var(&core_mask, GFP_KERNEL))) {
 		printk(KERN_WARNING
 		       "sfc: RSS disabled due to allocation failure\n");
@@ -1268,27 +1269,18 @@ static void efx_remove_interrupts(struct
 	efx->legacy_irq = 0;
 }
 
-struct efx_tx_queue *
-efx_get_tx_queue(struct efx_nic *efx, unsigned index, unsigned type)
-{
-	unsigned tx_channel_offset =
-		separate_tx_channels ? efx->n_channels - efx->n_tx_channels : 0;
-	EFX_BUG_ON_PARANOID(index >= efx->n_tx_channels ||
-			    type >= EFX_TXQ_TYPES);
-	return &efx->channel[tx_channel_offset + index]->tx_queue[type];
-}
-
 static void efx_set_channels(struct efx_nic *efx)
 {
 	struct efx_channel *channel;
 	struct efx_tx_queue *tx_queue;
-	unsigned tx_channel_offset =
+
+	efx->tx_channel_offset =
 		separate_tx_channels ? efx->n_channels - efx->n_tx_channels : 0;
 
 	/* Channel pointers were set in efx_init_struct() but we now
 	 * need to clear them for TX queues in any RX-only channels. */
 	efx_for_each_channel(channel, efx) {
-		if (channel->channel - tx_channel_offset >=
+		if (channel->channel - efx->tx_channel_offset >=
 		    efx->n_tx_channels) {
 			efx_for_each_channel_tx_queue(tx_queue, channel)
 				tx_queue->channel = NULL;
@@ -1405,11 +1397,11 @@ static void efx_start_all(struct efx_nic
 	 * restart the transmit interface early so the watchdog timer stops */
 	efx_start_port(efx);
 
-	efx_for_each_channel(channel, efx) {
-		if (efx_dev_registered(efx))
-			efx_wake_queue(channel);
+	if (efx_dev_registered(efx))
+		netif_tx_wake_all_queues(efx->net_dev);
+
+	efx_for_each_channel(channel, efx)
 		efx_start_channel(channel);
-	}
 
 	if (efx->legacy_irq)
 		efx->legacy_irq_enabled = true;
@@ -1497,9 +1489,7 @@ static void efx_stop_all(struct efx_nic
 	/* Stop the kernel transmit interface late, so the watchdog
 	 * timer isn't ticking over the flush */
 	if (efx_dev_registered(efx)) {
-		struct efx_channel *channel;
-		efx_for_each_channel(channel, efx)
-			efx_stop_queue(channel);
+		netif_tx_stop_all_queues(efx->net_dev);
 		netif_tx_lock_bh(efx->net_dev);
 		netif_tx_unlock_bh(efx->net_dev);
 	}
@@ -1895,6 +1885,7 @@ static DEVICE_ATTR(phy_type, 0644, show_
 static int efx_register_netdev(struct efx_nic *efx)
 {
 	struct net_device *net_dev = efx->net_dev;
+	struct efx_channel *channel;
 	int rc;
 
 	net_dev->watchdog_timeo = 5 * HZ;
@@ -1917,6 +1908,14 @@ static int efx_register_netdev(struct ef
 	if (rc)
 		goto fail_locked;
 
+	efx_for_each_channel(channel, efx) {
+		struct efx_tx_queue *tx_queue;
+		efx_for_each_channel_tx_queue(tx_queue, channel) {
+			tx_queue->core_txq = netdev_get_tx_queue(
+				efx->net_dev, tx_queue->queue / EFX_TXQ_TYPES);
+		}
+	}
+
 	/* Always start with carrier off; PHY events will detect the link */
 	netif_carrier_off(efx->net_dev);
 
@@ -1980,7 +1979,6 @@ void efx_reset_down(struct efx_nic *efx,
 
 	efx_stop_all(efx);
 	mutex_lock(&efx->mac_lock);
-	mutex_lock(&efx->spi_lock);
 
 	efx_fini_channels(efx);
 	if (efx->port_initialized && method != RESET_TYPE_INVISIBLE)
@@ -2022,7 +2020,6 @@ int efx_reset_up(struct efx_nic *efx, en
 	efx_init_channels(efx);
 	efx_restore_filters(efx);
 
-	mutex_unlock(&efx->spi_lock);
 	mutex_unlock(&efx->mac_lock);
 
 	efx_start_all(efx);
@@ -2032,7 +2029,6 @@ int efx_reset_up(struct efx_nic *efx, en
 fail:
 	efx->port_initialized = false;
 
-	mutex_unlock(&efx->spi_lock);
 	mutex_unlock(&efx->mac_lock);
 
 	return rc;
@@ -2220,8 +2216,6 @@ static int efx_init_struct(struct efx_ni
 	/* Initialise common structures */
 	memset(efx, 0, sizeof(*efx));
 	spin_lock_init(&efx->biu_lock);
-	mutex_init(&efx->mdio_lock);
-	mutex_init(&efx->spi_lock);
 #ifdef CONFIG_SFC_MTD
 	INIT_LIST_HEAD(&efx->mtd_list);
 #endif
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/sfc/efx.h linux-libre-2.6.38-gnu1/drivers/net/sfc/efx.h
--- linux-libre-2.6.37-gnu1/drivers/net/sfc/efx.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/sfc/efx.h	2011-03-14 21:20:32.000000000 -0400
@@ -36,8 +36,6 @@ efx_hard_start_xmit(struct sk_buff *skb,
 extern netdev_tx_t
 efx_enqueue_skb(struct efx_tx_queue *tx_queue, struct sk_buff *skb);
 extern void efx_xmit_done(struct efx_tx_queue *tx_queue, unsigned int index);
-extern void efx_stop_queue(struct efx_channel *channel);
-extern void efx_wake_queue(struct efx_channel *channel);
 
 /* RX */
 extern int efx_probe_rx_queue(struct efx_rx_queue *rx_queue);
@@ -74,9 +72,8 @@ extern int efx_filter_insert_filter(stru
 				    bool replace);
 extern int efx_filter_remove_filter(struct efx_nic *efx,
 				    struct efx_filter_spec *spec);
-extern void efx_filter_table_clear(struct efx_nic *efx,
-				   enum efx_filter_table_id table_id,
-				   enum efx_filter_priority priority);
+extern void efx_filter_clear_rx(struct efx_nic *efx,
+				enum efx_filter_priority priority);
 
 /* Channels */
 extern void efx_process_channel_now(struct efx_channel *channel);
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/sfc/ethtool.c linux-libre-2.6.38-gnu1/drivers/net/sfc/ethtool.c
--- linux-libre-2.6.37-gnu1/drivers/net/sfc/ethtool.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/sfc/ethtool.c	2011-03-14 21:20:32.000000000 -0400
@@ -11,14 +11,13 @@
 #include <linux/netdevice.h>
 #include <linux/ethtool.h>
 #include <linux/rtnetlink.h>
+#include <linux/in.h>
 #include "net_driver.h"
 #include "workarounds.h"
 #include "selftest.h"
 #include "efx.h"
 #include "filter.h"
 #include "nic.h"
-#include "spi.h"
-#include "mdio_10g.h"
 
 struct ethtool_string {
 	char name[ETH_GSTRING_LEN];
@@ -560,12 +559,8 @@ static int efx_ethtool_set_flags(struct
 	if (rc)
 		return rc;
 
-	if (!(data & ETH_FLAG_NTUPLE)) {
-		efx_filter_table_clear(efx, EFX_FILTER_TABLE_RX_IP,
-				       EFX_FILTER_PRI_MANUAL);
-		efx_filter_table_clear(efx, EFX_FILTER_TABLE_RX_MAC,
-				       EFX_FILTER_PRI_MANUAL);
-	}
+	if (!(data & ETH_FLAG_NTUPLE))
+		efx_filter_clear_rx(efx, EFX_FILTER_PRI_MANUAL);
 
 	return 0;
 }
@@ -574,9 +569,14 @@ static void efx_ethtool_self_test(struct
 				  struct ethtool_test *test, u64 *data)
 {
 	struct efx_nic *efx = netdev_priv(net_dev);
-	struct efx_self_tests efx_tests;
+	struct efx_self_tests *efx_tests;
 	int already_up;
-	int rc;
+	int rc = -ENOMEM;
+
+	efx_tests = kzalloc(sizeof(*efx_tests), GFP_KERNEL);
+	if (!efx_tests)
+		goto fail;
+
 
 	ASSERT_RTNL();
 	if (efx->state != STATE_RUNNING) {
@@ -584,6 +584,9 @@ static void efx_ethtool_self_test(struct
 		goto fail1;
 	}
 
+	netif_info(efx, drv, efx->net_dev, "starting %sline testing\n",
+		   (test->flags & ETH_TEST_FL_OFFLINE) ? "off" : "on");
+
 	/* We need rx buffers and interrupts. */
 	already_up = (efx->net_dev->flags & IFF_UP);
 	if (!already_up) {
@@ -591,25 +594,24 @@ static void efx_ethtool_self_test(struct
 		if (rc) {
 			netif_err(efx, drv, efx->net_dev,
 				  "failed opening device.\n");
-			goto fail2;
+			goto fail1;
 		}
 	}
 
-	memset(&efx_tests, 0, sizeof(efx_tests));
-
-	rc = efx_selftest(efx, &efx_tests, test->flags);
+	rc = efx_selftest(efx, efx_tests, test->flags);
 
 	if (!already_up)
 		dev_close(efx->net_dev);
 
-	netif_dbg(efx, drv, efx->net_dev, "%s %sline self-tests\n",
-		  rc == 0 ? "passed" : "failed",
-		  (test->flags & ETH_TEST_FL_OFFLINE) ? "off" : "on");
+	netif_info(efx, drv, efx->net_dev, "%s %sline self-tests\n",
+		   rc == 0 ? "passed" : "failed",
+		   (test->flags & ETH_TEST_FL_OFFLINE) ? "off" : "on");
 
- fail2:
- fail1:
+fail1:
 	/* Fill ethtool results structures */
-	efx_ethtool_fill_self_tests(efx, &efx_tests, NULL, data);
+	efx_ethtool_fill_self_tests(efx, efx_tests, NULL, data);
+	kfree(efx_tests);
+fail:
 	if (rc)
 		test->flags |= ETH_TEST_FL_FAILED;
 }
@@ -622,68 +624,6 @@ static int efx_ethtool_nway_reset(struct
 	return mdio45_nway_restart(&efx->mdio);
 }
 
-static u32 efx_ethtool_get_link(struct net_device *net_dev)
-{
-	struct efx_nic *efx = netdev_priv(net_dev);
-
-	return efx->link_state.up;
-}
-
-static int efx_ethtool_get_eeprom_len(struct net_device *net_dev)
-{
-	struct efx_nic *efx = netdev_priv(net_dev);
-	struct efx_spi_device *spi = efx->spi_eeprom;
-
-	if (!spi)
-		return 0;
-	return min(spi->size, EFX_EEPROM_BOOTCONFIG_END) -
-		min(spi->size, EFX_EEPROM_BOOTCONFIG_START);
-}
-
-static int efx_ethtool_get_eeprom(struct net_device *net_dev,
-				  struct ethtool_eeprom *eeprom, u8 *buf)
-{
-	struct efx_nic *efx = netdev_priv(net_dev);
-	struct efx_spi_device *spi = efx->spi_eeprom;
-	size_t len;
-	int rc;
-
-	rc = mutex_lock_interruptible(&efx->spi_lock);
-	if (rc)
-		return rc;
-	rc = falcon_spi_read(efx, spi,
-			     eeprom->offset + EFX_EEPROM_BOOTCONFIG_START,
-			     eeprom->len, &len, buf);
-	mutex_unlock(&efx->spi_lock);
-
-	eeprom->magic = EFX_ETHTOOL_EEPROM_MAGIC;
-	eeprom->len = len;
-	return rc;
-}
-
-static int efx_ethtool_set_eeprom(struct net_device *net_dev,
-				  struct ethtool_eeprom *eeprom, u8 *buf)
-{
-	struct efx_nic *efx = netdev_priv(net_dev);
-	struct efx_spi_device *spi = efx->spi_eeprom;
-	size_t len;
-	int rc;
-
-	if (eeprom->magic != EFX_ETHTOOL_EEPROM_MAGIC)
-		return -EINVAL;
-
-	rc = mutex_lock_interruptible(&efx->spi_lock);
-	if (rc)
-		return rc;
-	rc = falcon_spi_write(efx, spi,
-			      eeprom->offset + EFX_EEPROM_BOOTCONFIG_START,
-			      eeprom->len, &len, buf);
-	mutex_unlock(&efx->spi_lock);
-
-	eeprom->len = len;
-	return rc;
-}
-
 static int efx_ethtool_get_coalesce(struct net_device *net_dev,
 				    struct ethtool_coalesce *coalesce)
 {
@@ -978,6 +918,7 @@ static int efx_ethtool_set_rx_ntuple(str
 	struct ethhdr *mac_entry = &ntuple->fs.h_u.ether_spec;
 	struct ethhdr *mac_mask = &ntuple->fs.m_u.ether_spec;
 	struct efx_filter_spec filter;
+	int rc;
 
 	/* Range-check action */
 	if (ntuple->fs.action < ETHTOOL_RXNTUPLE_ACTION_CLEAR ||
@@ -987,9 +928,16 @@ static int efx_ethtool_set_rx_ntuple(str
 	if (~ntuple->fs.data_mask)
 		return -EINVAL;
 
+	efx_filter_init_rx(&filter, EFX_FILTER_PRI_MANUAL, 0,
+			   (ntuple->fs.action == ETHTOOL_RXNTUPLE_ACTION_DROP) ?
+			   0xfff : ntuple->fs.action);
+
 	switch (ntuple->fs.flow_type) {
 	case TCP_V4_FLOW:
-	case UDP_V4_FLOW:
+	case UDP_V4_FLOW: {
+		u8 proto = (ntuple->fs.flow_type == TCP_V4_FLOW ?
+			    IPPROTO_TCP : IPPROTO_UDP);
+
 		/* Must match all of destination, */
 		if (ip_mask->ip4dst | ip_mask->pdst)
 			return -EINVAL;
@@ -1001,7 +949,22 @@ static int efx_ethtool_set_rx_ntuple(str
 		/* and nothing else */
 		if ((u8)~ip_mask->tos | (u16)~ntuple->fs.vlan_tag_mask)
 			return -EINVAL;
+
+		if (!ip_mask->ip4src)
+			rc = efx_filter_set_ipv4_full(&filter, proto,
+						      ip_entry->ip4dst,
+						      ip_entry->pdst,
+						      ip_entry->ip4src,
+						      ip_entry->psrc);
+		else
+			rc = efx_filter_set_ipv4_local(&filter, proto,
+						       ip_entry->ip4dst,
+						       ip_entry->pdst);
+		if (rc)
+			return rc;
 		break;
+	}
+
 	case ETHER_FLOW:
 		/* Must match all of destination, */
 		if (!is_zero_ether_addr(mac_mask->h_dest))
@@ -1014,58 +977,24 @@ static int efx_ethtool_set_rx_ntuple(str
 		if (!is_broadcast_ether_addr(mac_mask->h_source) ||
 		    mac_mask->h_proto != htons(0xffff))
 			return -EINVAL;
+
+		rc = efx_filter_set_eth_local(
+			&filter,
+			(ntuple->fs.vlan_tag_mask == 0xf000) ?
+			ntuple->fs.vlan_tag : EFX_FILTER_VID_UNSPEC,
+			mac_entry->h_dest);
+		if (rc)
+			return rc;
 		break;
+
 	default:
 		return -EINVAL;
 	}
 
-	filter.priority = EFX_FILTER_PRI_MANUAL;
-	filter.flags = 0;
-
-	switch (ntuple->fs.flow_type) {
-	case TCP_V4_FLOW:
-		if (!ip_mask->ip4src)
-			efx_filter_set_rx_tcp_full(&filter,
-						   htonl(ip_entry->ip4src),
-						   htons(ip_entry->psrc),
-						   htonl(ip_entry->ip4dst),
-						   htons(ip_entry->pdst));
-		else
-			efx_filter_set_rx_tcp_wild(&filter,
-						   htonl(ip_entry->ip4dst),
-						   htons(ip_entry->pdst));
-		break;
-	case UDP_V4_FLOW:
-		if (!ip_mask->ip4src)
-			efx_filter_set_rx_udp_full(&filter,
-						   htonl(ip_entry->ip4src),
-						   htons(ip_entry->psrc),
-						   htonl(ip_entry->ip4dst),
-						   htons(ip_entry->pdst));
-		else
-			efx_filter_set_rx_udp_wild(&filter,
-						   htonl(ip_entry->ip4dst),
-						   htons(ip_entry->pdst));
-		break;
-	case ETHER_FLOW:
-		if (ntuple->fs.vlan_tag_mask == 0xf000)
-			efx_filter_set_rx_mac_full(&filter,
-						   ntuple->fs.vlan_tag & 0xfff,
-						   mac_entry->h_dest);
-		else
-			efx_filter_set_rx_mac_wild(&filter, mac_entry->h_dest);
-		break;
-	}
-
-	if (ntuple->fs.action == ETHTOOL_RXNTUPLE_ACTION_CLEAR) {
+	if (ntuple->fs.action == ETHTOOL_RXNTUPLE_ACTION_CLEAR)
 		return efx_filter_remove_filter(efx, &filter);
-	} else {
-		if (ntuple->fs.action == ETHTOOL_RXNTUPLE_ACTION_DROP)
-			filter.dmaq_id = 0xfff;
-		else
-			filter.dmaq_id = ntuple->fs.action;
+	else
 		return efx_filter_insert_filter(efx, &filter, true);
-	}
 }
 
 static int efx_ethtool_get_rxfh_indir(struct net_device *net_dev,
@@ -1115,10 +1044,7 @@ const struct ethtool_ops efx_ethtool_ops
 	.get_msglevel		= efx_ethtool_get_msglevel,
 	.set_msglevel		= efx_ethtool_set_msglevel,
 	.nway_reset		= efx_ethtool_nway_reset,
-	.get_link		= efx_ethtool_get_link,
-	.get_eeprom_len		= efx_ethtool_get_eeprom_len,
-	.get_eeprom		= efx_ethtool_get_eeprom,
-	.set_eeprom		= efx_ethtool_set_eeprom,
+	.get_link		= ethtool_op_get_link,
 	.get_coalesce		= efx_ethtool_get_coalesce,
 	.set_coalesce		= efx_ethtool_set_coalesce,
 	.get_ringparam		= efx_ethtool_get_ringparam,
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/sfc/falcon_boards.c linux-libre-2.6.38-gnu1/drivers/net/sfc/falcon_boards.c
--- linux-libre-2.6.37-gnu1/drivers/net/sfc/falcon_boards.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/sfc/falcon_boards.c	2011-03-14 21:20:32.000000000 -0400
@@ -13,8 +13,6 @@
 #include "phy.h"
 #include "efx.h"
 #include "nic.h"
-#include "regs.h"
-#include "io.h"
 #include "workarounds.h"
 
 /* Macros for unpacking the board revision */
@@ -30,17 +28,28 @@
 #define FALCON_BOARD_SFN4112F 0x52
 
 /* Board temperature is about 15°C above ambient when air flow is
- * limited. */
+ * limited.  The maximum acceptable ambient temperature varies
+ * depending on the PHY specifications but the critical temperature
+ * above which we should shut down to avoid damage is 80°C. */
 #define FALCON_BOARD_TEMP_BIAS	15
+#define FALCON_BOARD_TEMP_CRIT	(80 + FALCON_BOARD_TEMP_BIAS)
 
 /* SFC4000 datasheet says: 'The maximum permitted junction temperature
  * is 125°C; the thermal design of the environment for the SFC4000
  * should aim to keep this well below 100°C.' */
+#define FALCON_JUNC_TEMP_MIN	0
 #define FALCON_JUNC_TEMP_MAX	90
+#define FALCON_JUNC_TEMP_CRIT	125
 
 /*****************************************************************************
  * Support for LM87 sensor chip used on several boards
  */
+#define LM87_REG_TEMP_HW_INT_LOCK	0x13
+#define LM87_REG_TEMP_HW_EXT_LOCK	0x14
+#define LM87_REG_TEMP_HW_INT		0x17
+#define LM87_REG_TEMP_HW_EXT		0x18
+#define LM87_REG_TEMP_EXT1		0x26
+#define LM87_REG_TEMP_INT		0x27
 #define LM87_REG_ALARMS1		0x41
 #define LM87_REG_ALARMS2		0x42
 #define LM87_IN_LIMITS(nr, _min, _max)			\
@@ -57,6 +66,27 @@
 
 #if defined(CONFIG_SENSORS_LM87) || defined(CONFIG_SENSORS_LM87_MODULE)
 
+static int efx_poke_lm87(struct i2c_client *client, const u8 *reg_values)
+{
+	while (*reg_values) {
+		u8 reg = *reg_values++;
+		u8 value = *reg_values++;
+		int rc = i2c_smbus_write_byte_data(client, reg, value);
+		if (rc)
+			return rc;
+	}
+	return 0;
+}
+
+static const u8 falcon_lm87_common_regs[] = {
+	LM87_REG_TEMP_HW_INT_LOCK, FALCON_BOARD_TEMP_CRIT,
+	LM87_REG_TEMP_HW_INT, FALCON_BOARD_TEMP_CRIT,
+	LM87_TEMP_EXT1_LIMITS(FALCON_JUNC_TEMP_MIN, FALCON_JUNC_TEMP_MAX),
+	LM87_REG_TEMP_HW_EXT_LOCK, FALCON_JUNC_TEMP_CRIT,
+	LM87_REG_TEMP_HW_EXT, FALCON_JUNC_TEMP_CRIT,
+	0
+};
+
 static int efx_init_lm87(struct efx_nic *efx, struct i2c_board_info *info,
 			 const u8 *reg_values)
 {
@@ -67,13 +97,16 @@ static int efx_init_lm87(struct efx_nic
 	if (!client)
 		return -EIO;
 
-	while (*reg_values) {
-		u8 reg = *reg_values++;
-		u8 value = *reg_values++;
-		rc = i2c_smbus_write_byte_data(client, reg, value);
-		if (rc)
-			goto err;
-	}
+	/* Read-to-clear alarm/interrupt status */
+	i2c_smbus_read_byte_data(client, LM87_REG_ALARMS1);
+	i2c_smbus_read_byte_data(client, LM87_REG_ALARMS2);
+
+	rc = efx_poke_lm87(client, reg_values);
+	if (rc)
+		goto err;
+	rc = efx_poke_lm87(client, falcon_lm87_common_regs);
+	if (rc)
+		goto err;
 
 	board->hwmon_client = client;
 	return 0;
@@ -91,36 +124,56 @@ static void efx_fini_lm87(struct efx_nic
 static int efx_check_lm87(struct efx_nic *efx, unsigned mask)
 {
 	struct i2c_client *client = falcon_board(efx)->hwmon_client;
-	s32 alarms1, alarms2;
+	bool temp_crit, elec_fault, is_failure;
+	u16 alarms;
+	s32 reg;
 
 	/* If link is up then do not monitor temperature */
 	if (EFX_WORKAROUND_7884(efx) && efx->link_state.up)
 		return 0;
 
-	alarms1 = i2c_smbus_read_byte_data(client, LM87_REG_ALARMS1);
-	alarms2 = i2c_smbus_read_byte_data(client, LM87_REG_ALARMS2);
-	if (alarms1 < 0)
-		return alarms1;
-	if (alarms2 < 0)
-		return alarms2;
-	alarms1 &= mask;
-	alarms2 &= mask >> 8;
-	if (alarms1 || alarms2) {
+	reg = i2c_smbus_read_byte_data(client, LM87_REG_ALARMS1);
+	if (reg < 0)
+		return reg;
+	alarms = reg;
+	reg = i2c_smbus_read_byte_data(client, LM87_REG_ALARMS2);
+	if (reg < 0)
+		return reg;
+	alarms |= reg << 8;
+	alarms &= mask;
+
+	temp_crit = false;
+	if (alarms & LM87_ALARM_TEMP_INT) {
+		reg = i2c_smbus_read_byte_data(client, LM87_REG_TEMP_INT);
+		if (reg < 0)
+			return reg;
+		if (reg > FALCON_BOARD_TEMP_CRIT)
+			temp_crit = true;
+	}
+	if (alarms & LM87_ALARM_TEMP_EXT1) {
+		reg = i2c_smbus_read_byte_data(client, LM87_REG_TEMP_EXT1);
+		if (reg < 0)
+			return reg;
+		if (reg > FALCON_JUNC_TEMP_CRIT)
+			temp_crit = true;
+	}
+	elec_fault = alarms & ~(LM87_ALARM_TEMP_INT | LM87_ALARM_TEMP_EXT1);
+	is_failure = temp_crit || elec_fault;
+
+	if (alarms)
 		netif_err(efx, hw, efx->net_dev,
-			  "LM87 detected a hardware failure (status %02x:%02x)"
-			  "%s%s%s\n",
-			  alarms1, alarms2,
-			  (alarms1 & LM87_ALARM_TEMP_INT) ?
+			  "LM87 detected a hardware %s (status %02x:%02x)"
+			  "%s%s%s%s\n",
+			  is_failure ? "failure" : "problem",
+			  alarms & 0xff, alarms >> 8,
+			  (alarms & LM87_ALARM_TEMP_INT) ?
 			  "; board is overheating" : "",
-			  (alarms1 & LM87_ALARM_TEMP_EXT1) ?
+			  (alarms & LM87_ALARM_TEMP_EXT1) ?
 			  "; controller is overheating" : "",
-			  (alarms1 & ~(LM87_ALARM_TEMP_INT | LM87_ALARM_TEMP_EXT1)
-			   || alarms2) ?
-			  "; electrical fault" : "");
-		return -ERANGE;
-	}
+			  temp_crit ? "; reached critical temperature" : "",
+			  elec_fault ? "; electrical fault" : "");
 
-	return 0;
+	return is_failure ? -ERANGE : 0;
 }
 
 #else /* !CONFIG_SENSORS_LM87 */
@@ -325,7 +378,7 @@ static ssize_t set_phy_flash_cfg(struct
 		new_mode = old_mode & ~PHY_MODE_SPECIAL;
 	else
 		new_mode = PHY_MODE_SPECIAL;
-	if (old_mode == new_mode) {
+	if (!((old_mode ^ new_mode) & PHY_MODE_SPECIAL)) {
 		err = 0;
 	} else if (efx->state != STATE_RUNNING || netif_running(efx->net_dev)) {
 		err = -EBUSY;
@@ -362,10 +415,11 @@ static void sfe4001_fini(struct efx_nic
 
 static int sfe4001_check_hw(struct efx_nic *efx)
 {
+	struct falcon_nic_data *nic_data = efx->nic_data;
 	s32 status;
 
 	/* If XAUI link is up then do not monitor */
-	if (EFX_WORKAROUND_7884(efx) && !efx->xmac_poll_required)
+	if (EFX_WORKAROUND_7884(efx) && !nic_data->xmac_poll_required)
 		return 0;
 
 	/* Check the powered status of the PHY. Lack of power implies that
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/sfc/falcon.c linux-libre-2.6.38-gnu1/drivers/net/sfc/falcon.c
--- linux-libre-2.6.37-gnu1/drivers/net/sfc/falcon.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/sfc/falcon.c	2011-03-14 21:20:32.000000000 -0400
@@ -24,7 +24,6 @@
 #include "nic.h"
 #include "regs.h"
 #include "io.h"
-#include "mdio_10g.h"
 #include "phy.h"
 #include "workarounds.h"
 
@@ -255,7 +254,6 @@ int falcon_spi_cmd(struct efx_nic *efx,
 	/* Input validation */
 	if (len > FALCON_SPI_MAX_LEN)
 		return -EINVAL;
-	BUG_ON(!mutex_is_locked(&efx->spi_lock));
 
 	/* Check that previous command is not still running */
 	rc = falcon_spi_poll(efx);
@@ -719,6 +717,7 @@ static int falcon_mdio_write(struct net_
 			     int prtad, int devad, u16 addr, u16 value)
 {
 	struct efx_nic *efx = netdev_priv(net_dev);
+	struct falcon_nic_data *nic_data = efx->nic_data;
 	efx_oword_t reg;
 	int rc;
 
@@ -726,7 +725,7 @@ static int falcon_mdio_write(struct net_
 		   "writing MDIO %d register %d.%d with 0x%04x\n",
 		    prtad, devad, addr, value);
 
-	mutex_lock(&efx->mdio_lock);
+	mutex_lock(&nic_data->mdio_lock);
 
 	/* Check MDIO not currently being accessed */
 	rc = falcon_gmii_wait(efx);
@@ -762,7 +761,7 @@ static int falcon_mdio_write(struct net_
 	}
 
 out:
-	mutex_unlock(&efx->mdio_lock);
+	mutex_unlock(&nic_data->mdio_lock);
 	return rc;
 }
 
@@ -771,10 +770,11 @@ static int falcon_mdio_read(struct net_d
 			    int prtad, int devad, u16 addr)
 {
 	struct efx_nic *efx = netdev_priv(net_dev);
+	struct falcon_nic_data *nic_data = efx->nic_data;
 	efx_oword_t reg;
 	int rc;
 
-	mutex_lock(&efx->mdio_lock);
+	mutex_lock(&nic_data->mdio_lock);
 
 	/* Check MDIO not currently being accessed */
 	rc = falcon_gmii_wait(efx);
@@ -813,7 +813,7 @@ static int falcon_mdio_read(struct net_d
 	}
 
 out:
-	mutex_unlock(&efx->mdio_lock);
+	mutex_unlock(&nic_data->mdio_lock);
 	return rc;
 }
 
@@ -841,6 +841,7 @@ static int falcon_probe_port(struct efx_
 	}
 
 	/* Fill out MDIO structure and loopback modes */
+	mutex_init(&nic_data->mdio_lock);
 	efx->mdio.mdio_read = falcon_mdio_read;
 	efx->mdio.mdio_write = falcon_mdio_write;
 	rc = efx->phy_op->probe(efx);
@@ -880,6 +881,41 @@ static void falcon_remove_port(struct ef
 	efx_nic_free_buffer(efx, &efx->stats_buffer);
 }
 
+/* Global events are basically PHY events */
+static bool
+falcon_handle_global_event(struct efx_channel *channel, efx_qword_t *event)
+{
+	struct efx_nic *efx = channel->efx;
+	struct falcon_nic_data *nic_data = efx->nic_data;
+
+	if (EFX_QWORD_FIELD(*event, FSF_AB_GLB_EV_G_PHY0_INTR) ||
+	    EFX_QWORD_FIELD(*event, FSF_AB_GLB_EV_XG_PHY0_INTR) ||
+	    EFX_QWORD_FIELD(*event, FSF_AB_GLB_EV_XFP_PHY0_INTR))
+		/* Ignored */
+		return true;
+
+	if ((efx_nic_rev(efx) == EFX_REV_FALCON_B0) &&
+	    EFX_QWORD_FIELD(*event, FSF_BB_GLB_EV_XG_MGT_INTR)) {
+		nic_data->xmac_poll_required = true;
+		return true;
+	}
+
+	if (efx_nic_rev(efx) <= EFX_REV_FALCON_A1 ?
+	    EFX_QWORD_FIELD(*event, FSF_AA_GLB_EV_RX_RECOVERY) :
+	    EFX_QWORD_FIELD(*event, FSF_BB_GLB_EV_RX_RECOVERY)) {
+		netif_err(efx, rx_err, efx->net_dev,
+			  "channel %d seen global RX_RESET event. Resetting.\n",
+			  channel->channel);
+
+		atomic_inc(&efx->rx_reset);
+		efx_schedule_reset(efx, EFX_WORKAROUND_6555(efx) ?
+				   RESET_TYPE_RX_RECOVERY : RESET_TYPE_DISABLE);
+		return true;
+	}
+
+	return false;
+}
+
 /**************************************************************************
  *
  * Falcon test code
@@ -889,6 +925,7 @@ static void falcon_remove_port(struct ef
 static int
 falcon_read_nvram(struct efx_nic *efx, struct falcon_nvconfig *nvconfig_out)
 {
+	struct falcon_nic_data *nic_data = efx->nic_data;
 	struct falcon_nvconfig *nvconfig;
 	struct efx_spi_device *spi;
 	void *region;
@@ -896,8 +933,11 @@ falcon_read_nvram(struct efx_nic *efx, s
 	__le16 *word, *limit;
 	u32 csum;
 
-	spi = efx->spi_flash ? efx->spi_flash : efx->spi_eeprom;
-	if (!spi)
+	if (efx_spi_present(&nic_data->spi_flash))
+		spi = &nic_data->spi_flash;
+	else if (efx_spi_present(&nic_data->spi_eeprom))
+		spi = &nic_data->spi_eeprom;
+	else
 		return -EINVAL;
 
 	region = kmalloc(FALCON_NVCONFIG_END, GFP_KERNEL);
@@ -905,12 +945,13 @@ falcon_read_nvram(struct efx_nic *efx, s
 		return -ENOMEM;
 	nvconfig = region + FALCON_NVCONFIG_OFFSET;
 
-	mutex_lock(&efx->spi_lock);
+	mutex_lock(&nic_data->spi_lock);
 	rc = falcon_spi_read(efx, spi, 0, FALCON_NVCONFIG_END, NULL, region);
-	mutex_unlock(&efx->spi_lock);
+	mutex_unlock(&nic_data->spi_lock);
 	if (rc) {
 		netif_err(efx, hw, efx->net_dev, "Failed to read %s\n",
-			  efx->spi_flash ? "flash" : "EEPROM");
+			  efx_spi_present(&nic_data->spi_flash) ?
+			  "flash" : "EEPROM");
 		rc = -EIO;
 		goto out;
 	}
@@ -1012,7 +1053,7 @@ static int falcon_b0_test_registers(stru
 
 /* Resets NIC to known state.  This routine must be called in process
  * context and is allowed to sleep. */
-static int falcon_reset_hw(struct efx_nic *efx, enum reset_type method)
+static int __falcon_reset_hw(struct efx_nic *efx, enum reset_type method)
 {
 	struct falcon_nic_data *nic_data = efx->nic_data;
 	efx_oword_t glb_ctl_reg_ker;
@@ -1066,22 +1107,9 @@ static int falcon_reset_hw(struct efx_ni
 
 	/* Restore PCI configuration if needed */
 	if (method == RESET_TYPE_WORLD) {
-		if (efx_nic_is_dual_func(efx)) {
-			rc = pci_restore_state(nic_data->pci_dev2);
-			if (rc) {
-				netif_err(efx, drv, efx->net_dev,
-					  "failed to restore PCI config for "
-					  "the secondary function\n");
-				goto fail3;
-			}
-		}
-		rc = pci_restore_state(efx->pci_dev);
-		if (rc) {
-			netif_err(efx, drv, efx->net_dev,
-				  "failed to restore PCI config for the "
-				  "primary function\n");
-			goto fail4;
-		}
+		if (efx_nic_is_dual_func(efx))
+			pci_restore_state(nic_data->pci_dev2);
+		pci_restore_state(efx->pci_dev);
 		netif_dbg(efx, drv, efx->net_dev,
 			  "successfully restored PCI config\n");
 	}
@@ -1092,7 +1120,7 @@ static int falcon_reset_hw(struct efx_ni
 		rc = -ETIMEDOUT;
 		netif_err(efx, hw, efx->net_dev,
 			  "timed out waiting for hardware reset\n");
-		goto fail5;
+		goto fail3;
 	}
 	netif_dbg(efx, hw, efx->net_dev, "hardware reset complete\n");
 
@@ -1100,11 +1128,21 @@ static int falcon_reset_hw(struct efx_ni
 
 	/* pci_save_state() and pci_restore_state() MUST be called in pairs */
 fail2:
-fail3:
 	pci_restore_state(efx->pci_dev);
 fail1:
-fail4:
-fail5:
+fail3:
+	return rc;
+}
+
+static int falcon_reset_hw(struct efx_nic *efx, enum reset_type method)
+{
+	struct falcon_nic_data *nic_data = efx->nic_data;
+	int rc;
+
+	mutex_lock(&nic_data->spi_lock);
+	rc = __falcon_reset_hw(efx, method);
+	mutex_unlock(&nic_data->spi_lock);
+
 	return rc;
 }
 
@@ -1189,16 +1227,11 @@ static int falcon_reset_sram(struct efx_
 	return -ETIMEDOUT;
 }
 
-static int falcon_spi_device_init(struct efx_nic *efx,
-				  struct efx_spi_device **spi_device_ret,
+static void falcon_spi_device_init(struct efx_nic *efx,
+				  struct efx_spi_device *spi_device,
 				  unsigned int device_id, u32 device_type)
 {
-	struct efx_spi_device *spi_device;
-
 	if (device_type != 0) {
-		spi_device = kzalloc(sizeof(*spi_device), GFP_KERNEL);
-		if (!spi_device)
-			return -ENOMEM;
 		spi_device->device_id = device_id;
 		spi_device->size =
 			1 << SPI_DEV_TYPE_FIELD(device_type, SPI_DEV_TYPE_SIZE);
@@ -1215,27 +1248,15 @@ static int falcon_spi_device_init(struct
 			1 << SPI_DEV_TYPE_FIELD(device_type,
 						SPI_DEV_TYPE_BLOCK_SIZE);
 	} else {
-		spi_device = NULL;
+		spi_device->size = 0;
 	}
-
-	kfree(*spi_device_ret);
-	*spi_device_ret = spi_device;
-	return 0;
-}
-
-static void falcon_remove_spi_devices(struct efx_nic *efx)
-{
-	kfree(efx->spi_eeprom);
-	efx->spi_eeprom = NULL;
-	kfree(efx->spi_flash);
-	efx->spi_flash = NULL;
 }
 
 /* Extract non-volatile configuration */
 static int falcon_probe_nvconfig(struct efx_nic *efx)
 {
+	struct falcon_nic_data *nic_data = efx->nic_data;
 	struct falcon_nvconfig *nvconfig;
-	int board_rev;
 	int rc;
 
 	nvconfig = kmalloc(sizeof(*nvconfig), GFP_KERNEL);
@@ -1243,55 +1264,32 @@ static int falcon_probe_nvconfig(struct
 		return -ENOMEM;
 
 	rc = falcon_read_nvram(efx, nvconfig);
-	if (rc == -EINVAL) {
-		netif_err(efx, probe, efx->net_dev,
-			  "NVRAM is invalid therefore using defaults\n");
-		efx->phy_type = PHY_TYPE_NONE;
-		efx->mdio.prtad = MDIO_PRTAD_NONE;
-		board_rev = 0;
-		rc = 0;
-	} else if (rc) {
-		goto fail1;
-	} else {
-		struct falcon_nvconfig_board_v2 *v2 = &nvconfig->board_v2;
-		struct falcon_nvconfig_board_v3 *v3 = &nvconfig->board_v3;
+	if (rc)
+		goto out;
 
-		efx->phy_type = v2->port0_phy_type;
-		efx->mdio.prtad = v2->port0_phy_addr;
-		board_rev = le16_to_cpu(v2->board_revision);
+	efx->phy_type = nvconfig->board_v2.port0_phy_type;
+	efx->mdio.prtad = nvconfig->board_v2.port0_phy_addr;
 
-		if (le16_to_cpu(nvconfig->board_struct_ver) >= 3) {
-			rc = falcon_spi_device_init(
-				efx, &efx->spi_flash, FFE_AB_SPI_DEVICE_FLASH,
-				le32_to_cpu(v3->spi_device_type
-					    [FFE_AB_SPI_DEVICE_FLASH]));
-			if (rc)
-				goto fail2;
-			rc = falcon_spi_device_init(
-				efx, &efx->spi_eeprom, FFE_AB_SPI_DEVICE_EEPROM,
-				le32_to_cpu(v3->spi_device_type
-					    [FFE_AB_SPI_DEVICE_EEPROM]));
-			if (rc)
-				goto fail2;
-		}
+	if (le16_to_cpu(nvconfig->board_struct_ver) >= 3) {
+		falcon_spi_device_init(
+			efx, &nic_data->spi_flash, FFE_AB_SPI_DEVICE_FLASH,
+			le32_to_cpu(nvconfig->board_v3
+				    .spi_device_type[FFE_AB_SPI_DEVICE_FLASH]));
+		falcon_spi_device_init(
+			efx, &nic_data->spi_eeprom, FFE_AB_SPI_DEVICE_EEPROM,
+			le32_to_cpu(nvconfig->board_v3
+				    .spi_device_type[FFE_AB_SPI_DEVICE_EEPROM]));
 	}
 
 	/* Read the MAC addresses */
-	memcpy(efx->mac_address, nvconfig->mac_address[0], ETH_ALEN);
+	memcpy(efx->net_dev->perm_addr, nvconfig->mac_address[0], ETH_ALEN);
 
 	netif_dbg(efx, probe, efx->net_dev, "PHY is %d phy_id %d\n",
 		  efx->phy_type, efx->mdio.prtad);
 
-	rc = falcon_probe_board(efx, board_rev);
-	if (rc)
-		goto fail2;
-
-	kfree(nvconfig);
-	return 0;
-
- fail2:
-	falcon_remove_spi_devices(efx);
- fail1:
+	rc = falcon_probe_board(efx,
+				le16_to_cpu(nvconfig->board_v2.board_revision));
+out:
 	kfree(nvconfig);
 	return rc;
 }
@@ -1299,6 +1297,7 @@ static int falcon_probe_nvconfig(struct
 /* Probe all SPI devices on the NIC */
 static void falcon_probe_spi_devices(struct efx_nic *efx)
 {
+	struct falcon_nic_data *nic_data = efx->nic_data;
 	efx_oword_t nic_stat, gpio_ctl, ee_vpd_cfg;
 	int boot_dev;
 
@@ -1327,12 +1326,14 @@ static void falcon_probe_spi_devices(str
 		efx_writeo(efx, &ee_vpd_cfg, FR_AB_EE_VPD_CFG0);
 	}
 
+	mutex_init(&nic_data->spi_lock);
+
 	if (boot_dev == FFE_AB_SPI_DEVICE_FLASH)
-		falcon_spi_device_init(efx, &efx->spi_flash,
+		falcon_spi_device_init(efx, &nic_data->spi_flash,
 				       FFE_AB_SPI_DEVICE_FLASH,
 				       default_flash_type);
 	if (boot_dev == FFE_AB_SPI_DEVICE_EEPROM)
-		falcon_spi_device_init(efx, &efx->spi_eeprom,
+		falcon_spi_device_init(efx, &nic_data->spi_eeprom,
 				       FFE_AB_SPI_DEVICE_EEPROM,
 				       large_eeprom_type);
 }
@@ -1397,7 +1398,7 @@ static int falcon_probe_nic(struct efx_n
 	}
 
 	/* Now we can reset the NIC */
-	rc = falcon_reset_hw(efx, RESET_TYPE_ALL);
+	rc = __falcon_reset_hw(efx, RESET_TYPE_ALL);
 	if (rc) {
 		netif_err(efx, probe, efx->net_dev, "failed to reset NIC\n");
 		goto fail3;
@@ -1419,8 +1420,11 @@ static int falcon_probe_nic(struct efx_n
 
 	/* Read in the non-volatile configuration */
 	rc = falcon_probe_nvconfig(efx);
-	if (rc)
+	if (rc) {
+		if (rc == -EINVAL)
+			netif_err(efx, probe, efx->net_dev, "NVRAM is invalid\n");
 		goto fail5;
+	}
 
 	/* Initialise I2C adapter */
 	board = falcon_board(efx);
@@ -1452,7 +1456,6 @@ static int falcon_probe_nic(struct efx_n
 	BUG_ON(i2c_del_adapter(&board->i2c_adap));
 	memset(&board->i2c_adap, 0, sizeof(board->i2c_adap));
  fail5:
-	falcon_remove_spi_devices(efx);
 	efx_nic_free_buffer(efx, &efx->irq_status);
  fail4:
  fail3:
@@ -1606,10 +1609,9 @@ static void falcon_remove_nic(struct efx
 	BUG_ON(rc);
 	memset(&board->i2c_adap, 0, sizeof(board->i2c_adap));
 
-	falcon_remove_spi_devices(efx);
 	efx_nic_free_buffer(efx, &efx->irq_status);
 
-	falcon_reset_hw(efx, RESET_TYPE_ALL);
+	__falcon_reset_hw(efx, RESET_TYPE_ALL);
 
 	/* Release the second function after the reset */
 	if (nic_data->pci_dev2) {
@@ -1720,6 +1722,7 @@ struct efx_nic_type falcon_a1_nic_type =
 	.reset = falcon_reset_hw,
 	.probe_port = falcon_probe_port,
 	.remove_port = falcon_remove_port,
+	.handle_global_event = falcon_handle_global_event,
 	.prepare_flush = falcon_prepare_flush,
 	.update_stats = falcon_update_nic_stats,
 	.start_stats = falcon_start_nic_stats,
@@ -1760,6 +1763,7 @@ struct efx_nic_type falcon_b0_nic_type =
 	.reset = falcon_reset_hw,
 	.probe_port = falcon_probe_port,
 	.remove_port = falcon_remove_port,
+	.handle_global_event = falcon_handle_global_event,
 	.prepare_flush = falcon_prepare_flush,
 	.update_stats = falcon_update_nic_stats,
 	.start_stats = falcon_start_nic_stats,
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/sfc/falcon_xmac.c linux-libre-2.6.38-gnu1/drivers/net/sfc/falcon_xmac.c
--- linux-libre-2.6.37-gnu1/drivers/net/sfc/falcon_xmac.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/sfc/falcon_xmac.c	2011-03-14 21:20:32.000000000 -0400
@@ -16,7 +16,6 @@
 #include "io.h"
 #include "mac.h"
 #include "mdio_10g.h"
-#include "phy.h"
 #include "workarounds.h"
 
 /**************************************************************************
@@ -88,6 +87,7 @@ int falcon_reset_xaui(struct efx_nic *ef
 
 static void falcon_ack_status_intr(struct efx_nic *efx)
 {
+	struct falcon_nic_data *nic_data = efx->nic_data;
 	efx_oword_t reg;
 
 	if ((efx_nic_rev(efx) != EFX_REV_FALCON_B0) || LOOPBACK_INTERNAL(efx))
@@ -99,7 +99,7 @@ static void falcon_ack_status_intr(struc
 
 	/* We can only use this interrupt to signal the negative edge of
 	 * xaui_align [we have to poll the positive edge]. */
-	if (efx->xmac_poll_required)
+	if (nic_data->xmac_poll_required)
 		return;
 
 	efx_reado(efx, &reg, FR_AB_XM_MGT_INT_MSK);
@@ -277,12 +277,14 @@ static bool falcon_xmac_check_fault(stru
 
 static int falcon_reconfigure_xmac(struct efx_nic *efx)
 {
+	struct falcon_nic_data *nic_data = efx->nic_data;
+
 	falcon_reconfigure_xgxs_core(efx);
 	falcon_reconfigure_xmac_core(efx);
 
 	falcon_reconfigure_mac_wrapper(efx);
 
-	efx->xmac_poll_required = !falcon_xmac_link_ok_retry(efx, 5);
+	nic_data->xmac_poll_required = !falcon_xmac_link_ok_retry(efx, 5);
 	falcon_ack_status_intr(efx);
 
 	return 0;
@@ -350,11 +352,13 @@ static void falcon_update_stats_xmac(str
 
 void falcon_poll_xmac(struct efx_nic *efx)
 {
+	struct falcon_nic_data *nic_data = efx->nic_data;
+
 	if (!EFX_WORKAROUND_5147(efx) || !efx->link_state.up ||
-	    !efx->xmac_poll_required)
+	    !nic_data->xmac_poll_required)
 		return;
 
-	efx->xmac_poll_required = !falcon_xmac_link_ok_retry(efx, 1);
+	nic_data->xmac_poll_required = !falcon_xmac_link_ok_retry(efx, 1);
 	falcon_ack_status_intr(efx);
 }
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/sfc/filter.c linux-libre-2.6.38-gnu1/drivers/net/sfc/filter.c
--- linux-libre-2.6.37-gnu1/drivers/net/sfc/filter.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/sfc/filter.c	2011-03-14 21:20:32.000000000 -0400
@@ -7,6 +7,7 @@
  * by the Free Software Foundation, incorporated herein by reference.
  */
 
+#include <linux/in.h>
 #include "efx.h"
 #include "filter.h"
 #include "io.h"
@@ -26,19 +27,26 @@
  */
 #define FILTER_CTL_SRCH_MAX 200
 
+enum efx_filter_table_id {
+	EFX_FILTER_TABLE_RX_IP = 0,
+	EFX_FILTER_TABLE_RX_MAC,
+	EFX_FILTER_TABLE_COUNT,
+};
+
 struct efx_filter_table {
+	enum efx_filter_table_id id;
 	u32		offset;		/* address of table relative to BAR */
 	unsigned	size;		/* number of entries */
 	unsigned	step;		/* step between entries */
 	unsigned	used;		/* number currently used */
 	unsigned long	*used_bitmap;
 	struct efx_filter_spec *spec;
+	unsigned	search_depth[EFX_FILTER_TYPE_COUNT];
 };
 
 struct efx_filter_state {
 	spinlock_t	lock;
 	struct efx_filter_table table[EFX_FILTER_TABLE_COUNT];
-	unsigned	search_depth[EFX_FILTER_TYPE_COUNT];
 };
 
 /* The filter hash function is LFSR polynomial x^16 + x^3 + 1 of a 32-bit
@@ -65,68 +73,203 @@ static u16 efx_filter_increment(u32 key)
 }
 
 static enum efx_filter_table_id
-efx_filter_type_table_id(enum efx_filter_type type)
+efx_filter_spec_table_id(const struct efx_filter_spec *spec)
 {
-	BUILD_BUG_ON(EFX_FILTER_TABLE_RX_IP != (EFX_FILTER_RX_TCP_FULL >> 2));
-	BUILD_BUG_ON(EFX_FILTER_TABLE_RX_IP != (EFX_FILTER_RX_TCP_WILD >> 2));
-	BUILD_BUG_ON(EFX_FILTER_TABLE_RX_IP != (EFX_FILTER_RX_UDP_FULL >> 2));
-	BUILD_BUG_ON(EFX_FILTER_TABLE_RX_IP != (EFX_FILTER_RX_UDP_WILD >> 2));
-	BUILD_BUG_ON(EFX_FILTER_TABLE_RX_MAC != (EFX_FILTER_RX_MAC_FULL >> 2));
-	BUILD_BUG_ON(EFX_FILTER_TABLE_RX_MAC != (EFX_FILTER_RX_MAC_WILD >> 2));
-	return type >> 2;
+	BUILD_BUG_ON(EFX_FILTER_TABLE_RX_IP != (EFX_FILTER_TCP_FULL >> 2));
+	BUILD_BUG_ON(EFX_FILTER_TABLE_RX_IP != (EFX_FILTER_TCP_WILD >> 2));
+	BUILD_BUG_ON(EFX_FILTER_TABLE_RX_IP != (EFX_FILTER_UDP_FULL >> 2));
+	BUILD_BUG_ON(EFX_FILTER_TABLE_RX_IP != (EFX_FILTER_UDP_WILD >> 2));
+	BUILD_BUG_ON(EFX_FILTER_TABLE_RX_MAC != (EFX_FILTER_MAC_FULL >> 2));
+	BUILD_BUG_ON(EFX_FILTER_TABLE_RX_MAC != (EFX_FILTER_MAC_WILD >> 2));
+	EFX_BUG_ON_PARANOID(spec->type == EFX_FILTER_UNSPEC);
+	return spec->type >> 2;
 }
 
-static void
-efx_filter_table_reset_search_depth(struct efx_filter_state *state,
-				    enum efx_filter_table_id table_id)
+static struct efx_filter_table *
+efx_filter_spec_table(struct efx_filter_state *state,
+		      const struct efx_filter_spec *spec)
 {
-	memset(state->search_depth + (table_id << 2), 0,
-	       sizeof(state->search_depth[0]) << 2);
+	if (spec->type == EFX_FILTER_UNSPEC)
+		return NULL;
+	else
+		return &state->table[efx_filter_spec_table_id(spec)];
+}
+
+static void efx_filter_table_reset_search_depth(struct efx_filter_table *table)
+{
+	memset(table->search_depth, 0, sizeof(table->search_depth));
 }
 
 static void efx_filter_push_rx_limits(struct efx_nic *efx)
 {
 	struct efx_filter_state *state = efx->filter_state;
+	struct efx_filter_table *table;
 	efx_oword_t filter_ctl;
 
 	efx_reado(efx, &filter_ctl, FR_BZ_RX_FILTER_CTL);
 
+	table = &state->table[EFX_FILTER_TABLE_RX_IP];
 	EFX_SET_OWORD_FIELD(filter_ctl, FRF_BZ_TCP_FULL_SRCH_LIMIT,
-			    state->search_depth[EFX_FILTER_RX_TCP_FULL] +
+			    table->search_depth[EFX_FILTER_TCP_FULL] +
 			    FILTER_CTL_SRCH_FUDGE_FULL);
 	EFX_SET_OWORD_FIELD(filter_ctl, FRF_BZ_TCP_WILD_SRCH_LIMIT,
-			    state->search_depth[EFX_FILTER_RX_TCP_WILD] +
+			    table->search_depth[EFX_FILTER_TCP_WILD] +
 			    FILTER_CTL_SRCH_FUDGE_WILD);
 	EFX_SET_OWORD_FIELD(filter_ctl, FRF_BZ_UDP_FULL_SRCH_LIMIT,
-			    state->search_depth[EFX_FILTER_RX_UDP_FULL] +
+			    table->search_depth[EFX_FILTER_UDP_FULL] +
 			    FILTER_CTL_SRCH_FUDGE_FULL);
 	EFX_SET_OWORD_FIELD(filter_ctl, FRF_BZ_UDP_WILD_SRCH_LIMIT,
-			    state->search_depth[EFX_FILTER_RX_UDP_WILD] +
+			    table->search_depth[EFX_FILTER_UDP_WILD] +
 			    FILTER_CTL_SRCH_FUDGE_WILD);
 
-	if (state->table[EFX_FILTER_TABLE_RX_MAC].size) {
+	table = &state->table[EFX_FILTER_TABLE_RX_MAC];
+	if (table->size) {
 		EFX_SET_OWORD_FIELD(
 			filter_ctl, FRF_CZ_ETHERNET_FULL_SEARCH_LIMIT,
-			state->search_depth[EFX_FILTER_RX_MAC_FULL] +
+			table->search_depth[EFX_FILTER_MAC_FULL] +
 			FILTER_CTL_SRCH_FUDGE_FULL);
 		EFX_SET_OWORD_FIELD(
 			filter_ctl, FRF_CZ_ETHERNET_WILDCARD_SEARCH_LIMIT,
-			state->search_depth[EFX_FILTER_RX_MAC_WILD] +
+			table->search_depth[EFX_FILTER_MAC_WILD] +
 			FILTER_CTL_SRCH_FUDGE_WILD);
 	}
 
 	efx_writeo(efx, &filter_ctl, FR_BZ_RX_FILTER_CTL);
 }
 
+static inline void __efx_filter_set_ipv4(struct efx_filter_spec *spec,
+					 __be32 host1, __be16 port1,
+					 __be32 host2, __be16 port2)
+{
+	spec->data[0] = ntohl(host1) << 16 | ntohs(port1);
+	spec->data[1] = ntohs(port2) << 16 | ntohl(host1) >> 16;
+	spec->data[2] = ntohl(host2);
+}
+
+/**
+ * efx_filter_set_ipv4_local - specify IPv4 host, transport protocol and port
+ * @spec: Specification to initialise
+ * @proto: Transport layer protocol number
+ * @host: Local host address (network byte order)
+ * @port: Local port (network byte order)
+ */
+int efx_filter_set_ipv4_local(struct efx_filter_spec *spec, u8 proto,
+			      __be32 host, __be16 port)
+{
+	__be32 host1;
+	__be16 port1;
+
+	EFX_BUG_ON_PARANOID(!(spec->flags & EFX_FILTER_FLAG_RX));
+
+	/* This cannot currently be combined with other filtering */
+	if (spec->type != EFX_FILTER_UNSPEC)
+		return -EPROTONOSUPPORT;
+
+	if (port == 0)
+		return -EINVAL;
+
+	switch (proto) {
+	case IPPROTO_TCP:
+		spec->type = EFX_FILTER_TCP_WILD;
+		break;
+	case IPPROTO_UDP:
+		spec->type = EFX_FILTER_UDP_WILD;
+		break;
+	default:
+		return -EPROTONOSUPPORT;
+	}
+
+	/* Filter is constructed in terms of source and destination,
+	 * with the odd wrinkle that the ports are swapped in a UDP
+	 * wildcard filter.  We need to convert from local and remote
+	 * (= zero for wildcard) addresses.
+	 */
+	host1 = 0;
+	if (proto != IPPROTO_UDP) {
+		port1 = 0;
+	} else {
+		port1 = port;
+		port = 0;
+	}
+
+	__efx_filter_set_ipv4(spec, host1, port1, host, port);
+	return 0;
+}
+
+/**
+ * efx_filter_set_ipv4_full - specify IPv4 hosts, transport protocol and ports
+ * @spec: Specification to initialise
+ * @proto: Transport layer protocol number
+ * @host: Local host address (network byte order)
+ * @port: Local port (network byte order)
+ * @rhost: Remote host address (network byte order)
+ * @rport: Remote port (network byte order)
+ */
+int efx_filter_set_ipv4_full(struct efx_filter_spec *spec, u8 proto,
+			     __be32 host, __be16 port,
+			     __be32 rhost, __be16 rport)
+{
+	EFX_BUG_ON_PARANOID(!(spec->flags & EFX_FILTER_FLAG_RX));
+
+	/* This cannot currently be combined with other filtering */
+	if (spec->type != EFX_FILTER_UNSPEC)
+		return -EPROTONOSUPPORT;
+
+	if (port == 0 || rport == 0)
+		return -EINVAL;
+
+	switch (proto) {
+	case IPPROTO_TCP:
+		spec->type = EFX_FILTER_TCP_FULL;
+		break;
+	case IPPROTO_UDP:
+		spec->type = EFX_FILTER_UDP_FULL;
+		break;
+	default:
+		return -EPROTONOSUPPORT;
+	}
+
+	__efx_filter_set_ipv4(spec, rhost, rport, host, port);
+	return 0;
+}
+
+/**
+ * efx_filter_set_eth_local - specify local Ethernet address and optional VID
+ * @spec: Specification to initialise
+ * @vid: VLAN ID to match, or %EFX_FILTER_VID_UNSPEC
+ * @addr: Local Ethernet MAC address
+ */
+int efx_filter_set_eth_local(struct efx_filter_spec *spec,
+			     u16 vid, const u8 *addr)
+{
+	EFX_BUG_ON_PARANOID(!(spec->flags & EFX_FILTER_FLAG_RX));
+
+	/* This cannot currently be combined with other filtering */
+	if (spec->type != EFX_FILTER_UNSPEC)
+		return -EPROTONOSUPPORT;
+
+	if (vid == EFX_FILTER_VID_UNSPEC) {
+		spec->type = EFX_FILTER_MAC_WILD;
+		spec->data[0] = 0;
+	} else {
+		spec->type = EFX_FILTER_MAC_FULL;
+		spec->data[0] = vid;
+	}
+
+	spec->data[1] = addr[2] << 24 | addr[3] << 16 | addr[4] << 8 | addr[5];
+	spec->data[2] = addr[0] << 8 | addr[1];
+	return 0;
+}
+
 /* Build a filter entry and return its n-tuple key. */
 static u32 efx_filter_build(efx_oword_t *filter, struct efx_filter_spec *spec)
 {
 	u32 data3;
 
-	switch (efx_filter_type_table_id(spec->type)) {
+	switch (efx_filter_spec_table_id(spec)) {
 	case EFX_FILTER_TABLE_RX_IP: {
-		bool is_udp = (spec->type == EFX_FILTER_RX_UDP_FULL ||
-			       spec->type == EFX_FILTER_RX_UDP_WILD);
+		bool is_udp = (spec->type == EFX_FILTER_UDP_FULL ||
+			       spec->type == EFX_FILTER_UDP_WILD);
 		EFX_POPULATE_OWORD_7(
 			*filter,
 			FRF_BZ_RSS_EN,
@@ -143,7 +286,7 @@ static u32 efx_filter_build(efx_oword_t
 	}
 
 	case EFX_FILTER_TABLE_RX_MAC: {
-		bool is_wild = spec->type == EFX_FILTER_RX_MAC_WILD;
+		bool is_wild = spec->type == EFX_FILTER_MAC_WILD;
 		EFX_POPULATE_OWORD_8(
 			*filter,
 			FRF_CZ_RMFT_RSS_EN,
@@ -206,6 +349,14 @@ found:
 	return filter_idx;
 }
 
+/* Construct/deconstruct external filter IDs */
+
+static inline int
+efx_filter_make_id(enum efx_filter_table_id table_id, unsigned index)
+{
+	return table_id << 16 | index;
+}
+
 /**
  * efx_filter_insert_filter - add or replace a filter
  * @efx: NIC in which to insert the filter
@@ -213,30 +364,28 @@ found:
  * @replace: Flag for whether the specified filter may replace a filter
  *	with an identical match expression and equal or lower priority
  *
- * On success, return the filter index within its table.
+ * On success, return the filter ID.
  * On failure, return a negative error code.
  */
 int efx_filter_insert_filter(struct efx_nic *efx, struct efx_filter_spec *spec,
 			     bool replace)
 {
 	struct efx_filter_state *state = efx->filter_state;
-	enum efx_filter_table_id table_id =
-		efx_filter_type_table_id(spec->type);
-	struct efx_filter_table *table = &state->table[table_id];
+	struct efx_filter_table *table = efx_filter_spec_table(state, spec);
 	struct efx_filter_spec *saved_spec;
 	efx_oword_t filter;
 	int filter_idx, depth;
 	u32 key;
 	int rc;
 
-	if (table->size == 0)
+	if (!table || table->size == 0)
 		return -EINVAL;
 
 	key = efx_filter_build(&filter, spec);
 
 	netif_vdbg(efx, hw, efx->net_dev,
 		   "%s: type %d search_depth=%d", __func__, spec->type,
-		   state->search_depth[spec->type]);
+		   table->search_depth[spec->type]);
 
 	spin_lock_bh(&state->lock);
 
@@ -263,8 +412,8 @@ int efx_filter_insert_filter(struct efx_
 	}
 	*saved_spec = *spec;
 
-	if (state->search_depth[spec->type] < depth) {
-		state->search_depth[spec->type] = depth;
+	if (table->search_depth[spec->type] < depth) {
+		table->search_depth[spec->type] = depth;
 		efx_filter_push_rx_limits(efx);
 	}
 
@@ -273,6 +422,7 @@ int efx_filter_insert_filter(struct efx_
 	netif_vdbg(efx, hw, efx->net_dev,
 		   "%s: filter type %d index %d rxq %u set",
 		   __func__, spec->type, filter_idx, spec->dmaq_id);
+	rc = efx_filter_make_id(table->id, filter_idx);
 
 out:
 	spin_unlock_bh(&state->lock);
@@ -306,15 +456,16 @@ static void efx_filter_table_clear_entry
 int efx_filter_remove_filter(struct efx_nic *efx, struct efx_filter_spec *spec)
 {
 	struct efx_filter_state *state = efx->filter_state;
-	enum efx_filter_table_id table_id =
-		efx_filter_type_table_id(spec->type);
-	struct efx_filter_table *table = &state->table[table_id];
+	struct efx_filter_table *table = efx_filter_spec_table(state, spec);
 	struct efx_filter_spec *saved_spec;
 	efx_oword_t filter;
 	int filter_idx, depth;
 	u32 key;
 	int rc;
 
+	if (!table)
+		return -EINVAL;
+
 	key = efx_filter_build(&filter, spec);
 
 	spin_lock_bh(&state->lock);
@@ -332,7 +483,7 @@ int efx_filter_remove_filter(struct efx_
 
 	efx_filter_table_clear_entry(efx, table, filter_idx);
 	if (table->used == 0)
-		efx_filter_table_reset_search_depth(state, table_id);
+		efx_filter_table_reset_search_depth(table);
 	rc = 0;
 
 out:
@@ -340,15 +491,9 @@ out:
 	return rc;
 }
 
-/**
- * efx_filter_table_clear - remove filters from a table by priority
- * @efx: NIC from which to remove the filters
- * @table_id: Table from which to remove the filters
- * @priority: Maximum priority to remove
- */
-void efx_filter_table_clear(struct efx_nic *efx,
-			    enum efx_filter_table_id table_id,
-			    enum efx_filter_priority priority)
+static void efx_filter_table_clear(struct efx_nic *efx,
+				   enum efx_filter_table_id table_id,
+				   enum efx_filter_priority priority)
 {
 	struct efx_filter_state *state = efx->filter_state;
 	struct efx_filter_table *table = &state->table[table_id];
@@ -360,11 +505,22 @@ void efx_filter_table_clear(struct efx_n
 		if (table->spec[filter_idx].priority <= priority)
 			efx_filter_table_clear_entry(efx, table, filter_idx);
 	if (table->used == 0)
-		efx_filter_table_reset_search_depth(state, table_id);
+		efx_filter_table_reset_search_depth(table);
 
 	spin_unlock_bh(&state->lock);
 }
 
+/**
+ * efx_filter_clear_rx - remove RX filters by priority
+ * @efx: NIC from which to remove the filters
+ * @priority: Maximum priority to remove
+ */
+void efx_filter_clear_rx(struct efx_nic *efx, enum efx_filter_priority priority)
+{
+	efx_filter_table_clear(efx, EFX_FILTER_TABLE_RX_IP, priority);
+	efx_filter_table_clear(efx, EFX_FILTER_TABLE_RX_MAC, priority);
+}
+
 /* Restore filter stater after reset */
 void efx_restore_filters(struct efx_nic *efx)
 {
@@ -407,6 +563,7 @@ int efx_probe_filters(struct efx_nic *ef
 
 	if (efx_nic_rev(efx) >= EFX_REV_FALCON_B0) {
 		table = &state->table[EFX_FILTER_TABLE_RX_IP];
+		table->id = EFX_FILTER_TABLE_RX_IP;
 		table->offset = FR_BZ_RX_FILTER_TBL0;
 		table->size = FR_BZ_RX_FILTER_TBL0_ROWS;
 		table->step = FR_BZ_RX_FILTER_TBL0_STEP;
@@ -414,6 +571,7 @@ int efx_probe_filters(struct efx_nic *ef
 
 	if (efx_nic_rev(efx) >= EFX_REV_SIENA_A0) {
 		table = &state->table[EFX_FILTER_TABLE_RX_MAC];
+		table->id = EFX_FILTER_TABLE_RX_MAC;
 		table->offset = FR_CZ_RX_MAC_FILTER_TBL0;
 		table->size = FR_CZ_RX_MAC_FILTER_TBL0_ROWS;
 		table->step = FR_CZ_RX_MAC_FILTER_TBL0_STEP;
@@ -428,10 +586,9 @@ int efx_probe_filters(struct efx_nic *ef
 					     GFP_KERNEL);
 		if (!table->used_bitmap)
 			goto fail;
-		table->spec = vmalloc(table->size * sizeof(*table->spec));
+		table->spec = vzalloc(table->size * sizeof(*table->spec));
 		if (!table->spec)
 			goto fail;
-		memset(table->spec, 0, table->size * sizeof(*table->spec));
 	}
 
 	return 0;
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/sfc/filter.h linux-libre-2.6.38-gnu1/drivers/net/sfc/filter.h
--- linux-libre-2.6.37-gnu1/drivers/net/sfc/filter.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/sfc/filter.h	2011-03-14 21:20:32.000000000 -0400
@@ -12,31 +12,27 @@
 
 #include <linux/types.h>
 
-enum efx_filter_table_id {
-	EFX_FILTER_TABLE_RX_IP = 0,
-	EFX_FILTER_TABLE_RX_MAC,
-	EFX_FILTER_TABLE_COUNT,
-};
-
 /**
  * enum efx_filter_type - type of hardware filter
- * @EFX_FILTER_RX_TCP_FULL: RX, matching TCP/IPv4 4-tuple
- * @EFX_FILTER_RX_TCP_WILD: RX, matching TCP/IPv4 destination (host, port)
- * @EFX_FILTER_RX_UDP_FULL: RX, matching UDP/IPv4 4-tuple
- * @EFX_FILTER_RX_UDP_WILD: RX, matching UDP/IPv4 destination (host, port)
- * @EFX_FILTER_RX_MAC_FULL: RX, matching Ethernet destination MAC address, VID
- * @EFX_FILTER_RX_MAC_WILD: RX, matching Ethernet destination MAC address
+ * @EFX_FILTER_TCP_FULL: Matching TCP/IPv4 4-tuple
+ * @EFX_FILTER_TCP_WILD: Matching TCP/IPv4 destination (host, port)
+ * @EFX_FILTER_UDP_FULL: Matching UDP/IPv4 4-tuple
+ * @EFX_FILTER_UDP_WILD: Matching UDP/IPv4 destination (host, port)
+ * @EFX_FILTER_MAC_FULL: Matching Ethernet destination MAC address, VID
+ * @EFX_FILTER_MAC_WILD: Matching Ethernet destination MAC address
+ * @EFX_FILTER_UNSPEC: Match type is unspecified
  *
- * Falcon NICs only support the RX TCP/IPv4 and UDP/IPv4 filter types.
+ * Falcon NICs only support the TCP/IPv4 and UDP/IPv4 filter types.
  */
 enum efx_filter_type {
-	EFX_FILTER_RX_TCP_FULL = 0,
-	EFX_FILTER_RX_TCP_WILD,
-	EFX_FILTER_RX_UDP_FULL,
-	EFX_FILTER_RX_UDP_WILD,
-	EFX_FILTER_RX_MAC_FULL = 4,
-	EFX_FILTER_RX_MAC_WILD,
-	EFX_FILTER_TYPE_COUNT,
+	EFX_FILTER_TCP_FULL = 0,
+	EFX_FILTER_TCP_WILD,
+	EFX_FILTER_UDP_FULL,
+	EFX_FILTER_UDP_WILD,
+	EFX_FILTER_MAC_FULL = 4,
+	EFX_FILTER_MAC_WILD,
+	EFX_FILTER_TYPE_COUNT,		/* number of specific types */
+	EFX_FILTER_UNSPEC = 0xf,
 };
 
 /**
@@ -63,13 +59,13 @@ enum efx_filter_priority {
  * @EFX_FILTER_FLAG_RX_OVERRIDE_IP: Enables a MAC filter to override
  *	any IP filter that matches the same packet.  By default, IP
  *	filters take precedence.
- *
- * Currently, no flags are defined for TX filters.
+ * @EFX_FILTER_FLAG_RX: Filter is for RX
  */
 enum efx_filter_flags {
 	EFX_FILTER_FLAG_RX_RSS = 0x01,
 	EFX_FILTER_FLAG_RX_SCATTER = 0x02,
 	EFX_FILTER_FLAG_RX_OVERRIDE_IP = 0x04,
+	EFX_FILTER_FLAG_RX = 0x08,
 };
 
 /**
@@ -91,99 +87,26 @@ struct efx_filter_spec {
 	u32	data[3];
 };
 
-/**
- * efx_filter_set_rx_tcp_full - specify RX filter with TCP/IPv4 full match
- * @spec: Specification to initialise
- * @shost: Source host address (host byte order)
- * @sport: Source port (host byte order)
- * @dhost: Destination host address (host byte order)
- * @dport: Destination port (host byte order)
- */
-static inline void
-efx_filter_set_rx_tcp_full(struct efx_filter_spec *spec,
-			   u32 shost, u16 sport, u32 dhost, u16 dport)
-{
-	spec->type = EFX_FILTER_RX_TCP_FULL;
-	spec->data[0] = sport | shost << 16;
-	spec->data[1] = dport << 16 | shost >> 16;
-	spec->data[2] = dhost;
-}
-
-/**
- * efx_filter_set_rx_tcp_wild - specify RX filter with TCP/IPv4 wildcard match
- * @spec: Specification to initialise
- * @dhost: Destination host address (host byte order)
- * @dport: Destination port (host byte order)
- */
-static inline void
-efx_filter_set_rx_tcp_wild(struct efx_filter_spec *spec, u32 dhost, u16 dport)
-{
-	spec->type = EFX_FILTER_RX_TCP_WILD;
-	spec->data[0] = 0;
-	spec->data[1] = dport << 16;
-	spec->data[2] = dhost;
-}
-
-/**
- * efx_filter_set_rx_udp_full - specify RX filter with UDP/IPv4 full match
- * @spec: Specification to initialise
- * @shost: Source host address (host byte order)
- * @sport: Source port (host byte order)
- * @dhost: Destination host address (host byte order)
- * @dport: Destination port (host byte order)
- */
-static inline void
-efx_filter_set_rx_udp_full(struct efx_filter_spec *spec,
-			   u32 shost, u16 sport, u32 dhost, u16 dport)
-{
-	spec->type = EFX_FILTER_RX_UDP_FULL;
-	spec->data[0] = sport | shost << 16;
-	spec->data[1] = dport << 16 | shost >> 16;
-	spec->data[2] = dhost;
-}
-
-/**
- * efx_filter_set_rx_udp_wild - specify RX filter with UDP/IPv4 wildcard match
- * @spec: Specification to initialise
- * @dhost: Destination host address (host byte order)
- * @dport: Destination port (host byte order)
- */
-static inline void
-efx_filter_set_rx_udp_wild(struct efx_filter_spec *spec, u32 dhost, u16 dport)
-{
-	spec->type = EFX_FILTER_RX_UDP_WILD;
-	spec->data[0] = dport;
-	spec->data[1] = 0;
-	spec->data[2] = dhost;
-}
-
-/**
- * efx_filter_set_rx_mac_full - specify RX filter with MAC full match
- * @spec: Specification to initialise
- * @vid: VLAN ID
- * @addr: Destination MAC address
- */
-static inline void efx_filter_set_rx_mac_full(struct efx_filter_spec *spec,
-					      u16 vid, const u8 *addr)
+static inline void efx_filter_init_rx(struct efx_filter_spec *spec,
+				      enum efx_filter_priority priority,
+				      enum efx_filter_flags flags,
+				      unsigned rxq_id)
 {
-	spec->type = EFX_FILTER_RX_MAC_FULL;
-	spec->data[0] = vid;
-	spec->data[1] = addr[2] << 24 | addr[3] << 16 | addr[4] << 8 | addr[5];
-	spec->data[2] = addr[0] << 8 | addr[1];
+	spec->type = EFX_FILTER_UNSPEC;
+	spec->priority = priority;
+	spec->flags = EFX_FILTER_FLAG_RX | flags;
+	spec->dmaq_id = rxq_id;
 }
 
-/**
- * efx_filter_set_rx_mac_full - specify RX filter with MAC wildcard match
- * @spec: Specification to initialise
- * @addr: Destination MAC address
- */
-static inline void efx_filter_set_rx_mac_wild(struct efx_filter_spec *spec,
-					      const u8 *addr)
-{
-	spec->type = EFX_FILTER_RX_MAC_WILD;
-	spec->data[0] = 0;
-	spec->data[1] = addr[2] << 24 | addr[3] << 16 | addr[4] << 8 | addr[5];
-	spec->data[2] = addr[0] << 8 | addr[1];
-}
+extern int efx_filter_set_ipv4_local(struct efx_filter_spec *spec, u8 proto,
+				     __be32 host, __be16 port);
+extern int efx_filter_set_ipv4_full(struct efx_filter_spec *spec, u8 proto,
+				    __be32 host, __be16 port,
+				    __be32 rhost, __be16 rport);
+extern int efx_filter_set_eth_local(struct efx_filter_spec *spec,
+				    u16 vid, const u8 *addr);
+enum {
+	EFX_FILTER_VID_UNSPEC = 0xffff,
+};
 
 #endif /* EFX_FILTER_H */
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/sfc/io.h linux-libre-2.6.38-gnu1/drivers/net/sfc/io.h
--- linux-libre-2.6.37-gnu1/drivers/net/sfc/io.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/sfc/io.h	2011-03-14 21:20:32.000000000 -0400
@@ -22,28 +22,39 @@
  *
  * Notes on locking strategy:
  *
- * Most NIC registers require 16-byte (or 8-byte, for SRAM) atomic writes
- * which necessitates locking.
- * Under normal operation few writes to NIC registers are made and these
- * registers (EVQ_RPTR_REG, RX_DESC_UPD_REG and TX_DESC_UPD_REG) are special
- * cased to allow 4-byte (hence lockless) accesses.
- *
- * It *is* safe to write to these 4-byte registers in the middle of an
- * access to an 8-byte or 16-byte register.  We therefore use a
- * spinlock to protect accesses to the larger registers, but no locks
- * for the 4-byte registers.
+ * Most CSRs are 128-bit (oword) and therefore cannot be read or
+ * written atomically.  Access from the host is buffered by the Bus
+ * Interface Unit (BIU).  Whenever the host reads from the lowest
+ * address of such a register, or from the address of a different such
+ * register, the BIU latches the register's value.  Subsequent reads
+ * from higher addresses of the same register will read the latched
+ * value.  Whenever the host writes part of such a register, the BIU
+ * collects the written value and does not write to the underlying
+ * register until all 4 dwords have been written.  A similar buffering
+ * scheme applies to host access to the NIC's 64-bit SRAM.
  *
- * A write barrier is needed to ensure that DW3 is written after DW0/1/2
- * due to the way the 16byte registers are "collected" in the BIU.
+ * Access to different CSRs and 64-bit SRAM words must be serialised,
+ * since interleaved access can result in lost writes or lost
+ * information from read-to-clear fields.  We use efx_nic::biu_lock
+ * for this.  (We could use separate locks for read and write, but
+ * this is not normally a performance bottleneck.)
  *
- * We also lock when carrying out reads, to ensure consistency of the
- * data (made possible since the BIU reads all 128 bits into a cache).
- * Reads are very rare, so this isn't a significant performance
- * impact.  (Most data transferred from NIC to host is DMAed directly
- * into host memory).
+ * The DMA descriptor pointers (RX_DESC_UPD and TX_DESC_UPD) are
+ * 128-bit but are special-cased in the BIU to avoid the need for
+ * locking in the host:
  *
- * I/O BAR access uses locks for both reads and writes (but is only provided
- * for testing purposes).
+ * - They are write-only.
+ * - The semantics of writing to these registers are such that
+ *   replacing the low 96 bits with zero does not affect functionality.
+ * - If the host writes to the last dword address of such a register
+ *   (i.e. the high 32 bits) the underlying register will always be
+ *   written.  If the collector does not hold values for the low 96
+ *   bits of the register, they will be written as zero.  Writing to
+ *   the last qword does not have this effect and must not be done.
+ * - If the host writes to the address of any other part of such a
+ *   register while the collector already holds values for some other
+ *   register, the write is discarded and the collector maintains its
+ *   current state.
  */
 
 #if BITS_PER_LONG == 64
@@ -72,7 +83,7 @@ static inline __le32 _efx_readd(struct e
 	return (__force __le32)__raw_readl(efx->membase + reg);
 }
 
-/* Writes to a normal 16-byte Efx register, locking as appropriate. */
+/* Write a normal 128-bit CSR, locking as appropriate. */
 static inline void efx_writeo(struct efx_nic *efx, efx_oword_t *value,
 			      unsigned int reg)
 {
@@ -85,21 +96,18 @@ static inline void efx_writeo(struct efx
 	spin_lock_irqsave(&efx->biu_lock, flags);
 #ifdef EFX_USE_QWORD_IO
 	_efx_writeq(efx, value->u64[0], reg + 0);
-	wmb();
 	_efx_writeq(efx, value->u64[1], reg + 8);
 #else
 	_efx_writed(efx, value->u32[0], reg + 0);
 	_efx_writed(efx, value->u32[1], reg + 4);
 	_efx_writed(efx, value->u32[2], reg + 8);
-	wmb();
 	_efx_writed(efx, value->u32[3], reg + 12);
 #endif
 	mmiowb();
 	spin_unlock_irqrestore(&efx->biu_lock, flags);
 }
 
-/* Write an 8-byte NIC SRAM entry through the supplied mapping,
- * locking as appropriate. */
+/* Write 64-bit SRAM through the supplied mapping, locking as appropriate. */
 static inline void efx_sram_writeq(struct efx_nic *efx, void __iomem *membase,
 				   efx_qword_t *value, unsigned int index)
 {
@@ -115,36 +123,25 @@ static inline void efx_sram_writeq(struc
 	__raw_writeq((__force u64)value->u64[0], membase + addr);
 #else
 	__raw_writel((__force u32)value->u32[0], membase + addr);
-	wmb();
 	__raw_writel((__force u32)value->u32[1], membase + addr + 4);
 #endif
 	mmiowb();
 	spin_unlock_irqrestore(&efx->biu_lock, flags);
 }
 
-/* Write dword to NIC register that allows partial writes
- *
- * Some registers (EVQ_RPTR_REG, RX_DESC_UPD_REG and
- * TX_DESC_UPD_REG) can be written to as a single dword.  This allows
- * for lockless writes.
- */
+/* Write a 32-bit CSR or the last dword of a special 128-bit CSR */
 static inline void efx_writed(struct efx_nic *efx, efx_dword_t *value,
 			      unsigned int reg)
 {
 	netif_vdbg(efx, hw, efx->net_dev,
-		   "writing partial register %x with "EFX_DWORD_FMT"\n",
+		   "writing register %x with "EFX_DWORD_FMT"\n",
 		   reg, EFX_DWORD_VAL(*value));
 
 	/* No lock required */
 	_efx_writed(efx, value->u32[0], reg);
 }
 
-/* Read from a NIC register
- *
- * This reads an entire 16-byte register in one go, locking as
- * appropriate.  It is essential to read the first dword first, as this
- * prompts the NIC to load the current value into the shadow register.
- */
+/* Read a 128-bit CSR, locking as appropriate. */
 static inline void efx_reado(struct efx_nic *efx, efx_oword_t *value,
 			     unsigned int reg)
 {
@@ -152,7 +149,6 @@ static inline void efx_reado(struct efx_
 
 	spin_lock_irqsave(&efx->biu_lock, flags);
 	value->u32[0] = _efx_readd(efx, reg + 0);
-	rmb();
 	value->u32[1] = _efx_readd(efx, reg + 4);
 	value->u32[2] = _efx_readd(efx, reg + 8);
 	value->u32[3] = _efx_readd(efx, reg + 12);
@@ -163,8 +159,7 @@ static inline void efx_reado(struct efx_
 		   EFX_OWORD_VAL(*value));
 }
 
-/* Read an 8-byte SRAM entry through supplied mapping,
- * locking as appropriate. */
+/* Read 64-bit SRAM through the supplied mapping, locking as appropriate. */
 static inline void efx_sram_readq(struct efx_nic *efx, void __iomem *membase,
 				  efx_qword_t *value, unsigned int index)
 {
@@ -176,7 +171,6 @@ static inline void efx_sram_readq(struct
 	value->u64[0] = (__force __le64)__raw_readq(membase + addr);
 #else
 	value->u32[0] = (__force __le32)__raw_readl(membase + addr);
-	rmb();
 	value->u32[1] = (__force __le32)__raw_readl(membase + addr + 4);
 #endif
 	spin_unlock_irqrestore(&efx->biu_lock, flags);
@@ -186,7 +180,7 @@ static inline void efx_sram_readq(struct
 		   addr, EFX_QWORD_VAL(*value));
 }
 
-/* Read dword from register that allows partial writes (sic) */
+/* Read a 32-bit CSR or SRAM */
 static inline void efx_readd(struct efx_nic *efx, efx_dword_t *value,
 				unsigned int reg)
 {
@@ -196,28 +190,28 @@ static inline void efx_readd(struct efx_
 		   reg, EFX_DWORD_VAL(*value));
 }
 
-/* Write to a register forming part of a table */
+/* Write a 128-bit CSR forming part of a table */
 static inline void efx_writeo_table(struct efx_nic *efx, efx_oword_t *value,
 				      unsigned int reg, unsigned int index)
 {
 	efx_writeo(efx, value, reg + index * sizeof(efx_oword_t));
 }
 
-/* Read to a register forming part of a table */
+/* Read a 128-bit CSR forming part of a table */
 static inline void efx_reado_table(struct efx_nic *efx, efx_oword_t *value,
 				     unsigned int reg, unsigned int index)
 {
 	efx_reado(efx, value, reg + index * sizeof(efx_oword_t));
 }
 
-/* Write to a dword register forming part of a table */
+/* Write a 32-bit CSR forming part of a table, or 32-bit SRAM */
 static inline void efx_writed_table(struct efx_nic *efx, efx_dword_t *value,
 				       unsigned int reg, unsigned int index)
 {
 	efx_writed(efx, value, reg + index * sizeof(efx_oword_t));
 }
 
-/* Read from a dword register forming part of a table */
+/* Read a 32-bit CSR forming part of a table, or 32-bit SRAM */
 static inline void efx_readd_table(struct efx_nic *efx, efx_dword_t *value,
 				   unsigned int reg, unsigned int index)
 {
@@ -231,29 +225,54 @@ static inline void efx_readd_table(struc
 #define EFX_PAGED_REG(page, reg) \
 	((page) * EFX_PAGE_BLOCK_SIZE + (reg))
 
-/* As for efx_writeo(), but for a page-mapped register. */
-static inline void efx_writeo_page(struct efx_nic *efx, efx_oword_t *value,
-				   unsigned int reg, unsigned int page)
+/* Write the whole of RX_DESC_UPD or TX_DESC_UPD */
+static inline void _efx_writeo_page(struct efx_nic *efx, efx_oword_t *value,
+				    unsigned int reg, unsigned int page)
 {
-	efx_writeo(efx, value, EFX_PAGED_REG(page, reg));
+	reg = EFX_PAGED_REG(page, reg);
+
+	netif_vdbg(efx, hw, efx->net_dev,
+		   "writing register %x with " EFX_OWORD_FMT "\n", reg,
+		   EFX_OWORD_VAL(*value));
+
+#ifdef EFX_USE_QWORD_IO
+	_efx_writeq(efx, value->u64[0], reg + 0);
+#else
+	_efx_writed(efx, value->u32[0], reg + 0);
+	_efx_writed(efx, value->u32[1], reg + 4);
+#endif
+	_efx_writed(efx, value->u32[2], reg + 8);
+	_efx_writed(efx, value->u32[3], reg + 12);
 }
+#define efx_writeo_page(efx, value, reg, page)				\
+	_efx_writeo_page(efx, value,					\
+			 reg +						\
+			 BUILD_BUG_ON_ZERO((reg) != 0x830 && (reg) != 0xa10), \
+			 page)
 
-/* As for efx_writed(), but for a page-mapped register. */
-static inline void efx_writed_page(struct efx_nic *efx, efx_dword_t *value,
-				   unsigned int reg, unsigned int page)
+/* Write a page-mapped 32-bit CSR (EVQ_RPTR or the high bits of
+ * RX_DESC_UPD or TX_DESC_UPD)
+ */
+static inline void _efx_writed_page(struct efx_nic *efx, efx_dword_t *value,
+				    unsigned int reg, unsigned int page)
 {
 	efx_writed(efx, value, EFX_PAGED_REG(page, reg));
 }
+#define efx_writed_page(efx, value, reg, page)				\
+	_efx_writed_page(efx, value,					\
+			 reg +						\
+			 BUILD_BUG_ON_ZERO((reg) != 0x400 && (reg) != 0x83c \
+					   && (reg) != 0xa1c),		\
+			 page)
 
-/* Write dword to page-mapped register with an extra lock.
- *
- * As for efx_writed_page(), but for a register that suffers from
- * SFC bug 3181. Take out a lock so the BIU collector cannot be
- * confused. */
-static inline void efx_writed_page_locked(struct efx_nic *efx,
-					  efx_dword_t *value,
-					  unsigned int reg,
-					  unsigned int page)
+/* Write TIMER_COMMAND.  This is a page-mapped 32-bit CSR, but a bug
+ * in the BIU means that writes to TIMER_COMMAND[0] invalidate the
+ * collector register.
+ */
+static inline void _efx_writed_page_locked(struct efx_nic *efx,
+					   efx_dword_t *value,
+					   unsigned int reg,
+					   unsigned int page)
 {
 	unsigned long flags __attribute__ ((unused));
 
@@ -265,5 +284,9 @@ static inline void efx_writed_page_locke
 		efx_writed(efx, value, EFX_PAGED_REG(page, reg));
 	}
 }
+#define efx_writed_page_locked(efx, value, reg, page)			\
+	_efx_writed_page_locked(efx, value,				\
+				reg + BUILD_BUG_ON_ZERO((reg) != 0x420), \
+				page)
 
 #endif /* EFX_IO_H */
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/sfc/mcdi.c linux-libre-2.6.38-gnu1/drivers/net/sfc/mcdi.c
--- linux-libre-2.6.37-gnu1/drivers/net/sfc/mcdi.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/sfc/mcdi.c	2011-03-14 21:20:32.000000000 -0400
@@ -381,7 +381,7 @@ int efx_mcdi_rpc(struct efx_nic *efx, un
 				  -rc);
 			efx_schedule_reset(efx, RESET_TYPE_MC_FAILURE);
 		} else
-			netif_err(efx, hw, efx->net_dev,
+			netif_dbg(efx, hw, efx->net_dev,
 				  "MC command 0x%x inlen %d failed rc=%d\n",
 				  cmd, (int)inlen, -rc);
 	}
@@ -463,6 +463,7 @@ static void efx_mcdi_ev_death(struct efx
 		if (mcdi->mode == MCDI_MODE_EVENTS) {
 			mcdi->resprc = rc;
 			mcdi->resplen = 0;
+			++mcdi->credits;
 		}
 	} else
 		/* Nobody was waiting for an MCDI request, so trigger a reset */
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/sfc/mcdi_phy.c linux-libre-2.6.38-gnu1/drivers/net/sfc/mcdi_phy.c
--- linux-libre-2.6.37-gnu1/drivers/net/sfc/mcdi_phy.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/sfc/mcdi_phy.c	2011-03-14 21:20:32.000000000 -0400
@@ -16,7 +16,6 @@
 #include "phy.h"
 #include "mcdi.h"
 #include "mcdi_pcol.h"
-#include "mdio_10g.h"
 #include "nic.h"
 #include "selftest.h"
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/sfc/mdio_10g.c linux-libre-2.6.38-gnu1/drivers/net/sfc/mdio_10g.c
--- linux-libre-2.6.37-gnu1/drivers/net/sfc/mdio_10g.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/sfc/mdio_10g.c	2011-03-14 21:20:32.000000000 -0400
@@ -15,7 +15,6 @@
 #include "net_driver.h"
 #include "mdio_10g.h"
 #include "workarounds.h"
-#include "nic.h"
 
 unsigned efx_mdio_id_oui(u32 id)
 {
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/sfc/mtd.c linux-libre-2.6.38-gnu1/drivers/net/sfc/mtd.c
--- linux-libre-2.6.37-gnu1/drivers/net/sfc/mtd.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/sfc/mtd.c	2011-03-14 21:20:32.000000000 -0400
@@ -321,14 +321,15 @@ static int falcon_mtd_read(struct mtd_in
 	struct efx_mtd *efx_mtd = mtd->priv;
 	const struct efx_spi_device *spi = efx_mtd->spi;
 	struct efx_nic *efx = efx_mtd->efx;
+	struct falcon_nic_data *nic_data = efx->nic_data;
 	int rc;
 
-	rc = mutex_lock_interruptible(&efx->spi_lock);
+	rc = mutex_lock_interruptible(&nic_data->spi_lock);
 	if (rc)
 		return rc;
 	rc = falcon_spi_read(efx, spi, part->offset + start, len,
 			     retlen, buffer);
-	mutex_unlock(&efx->spi_lock);
+	mutex_unlock(&nic_data->spi_lock);
 	return rc;
 }
 
@@ -337,13 +338,14 @@ static int falcon_mtd_erase(struct mtd_i
 	struct efx_mtd_partition *part = to_efx_mtd_partition(mtd);
 	struct efx_mtd *efx_mtd = mtd->priv;
 	struct efx_nic *efx = efx_mtd->efx;
+	struct falcon_nic_data *nic_data = efx->nic_data;
 	int rc;
 
-	rc = mutex_lock_interruptible(&efx->spi_lock);
+	rc = mutex_lock_interruptible(&nic_data->spi_lock);
 	if (rc)
 		return rc;
 	rc = efx_spi_erase(part, part->offset + start, len);
-	mutex_unlock(&efx->spi_lock);
+	mutex_unlock(&nic_data->spi_lock);
 	return rc;
 }
 
@@ -354,14 +356,15 @@ static int falcon_mtd_write(struct mtd_i
 	struct efx_mtd *efx_mtd = mtd->priv;
 	const struct efx_spi_device *spi = efx_mtd->spi;
 	struct efx_nic *efx = efx_mtd->efx;
+	struct falcon_nic_data *nic_data = efx->nic_data;
 	int rc;
 
-	rc = mutex_lock_interruptible(&efx->spi_lock);
+	rc = mutex_lock_interruptible(&nic_data->spi_lock);
 	if (rc)
 		return rc;
 	rc = falcon_spi_write(efx, spi, part->offset + start, len,
 			      retlen, buffer);
-	mutex_unlock(&efx->spi_lock);
+	mutex_unlock(&nic_data->spi_lock);
 	return rc;
 }
 
@@ -370,11 +373,12 @@ static int falcon_mtd_sync(struct mtd_in
 	struct efx_mtd_partition *part = to_efx_mtd_partition(mtd);
 	struct efx_mtd *efx_mtd = mtd->priv;
 	struct efx_nic *efx = efx_mtd->efx;
+	struct falcon_nic_data *nic_data = efx->nic_data;
 	int rc;
 
-	mutex_lock(&efx->spi_lock);
+	mutex_lock(&nic_data->spi_lock);
 	rc = efx_spi_slow_wait(part, true);
-	mutex_unlock(&efx->spi_lock);
+	mutex_unlock(&nic_data->spi_lock);
 	return rc;
 }
 
@@ -387,35 +391,67 @@ static struct efx_mtd_ops falcon_mtd_ops
 
 static int falcon_mtd_probe(struct efx_nic *efx)
 {
-	struct efx_spi_device *spi = efx->spi_flash;
+	struct falcon_nic_data *nic_data = efx->nic_data;
+	struct efx_spi_device *spi;
 	struct efx_mtd *efx_mtd;
-	int rc;
+	int rc = -ENODEV;
 
 	ASSERT_RTNL();
 
-	if (!spi || spi->size <= FALCON_FLASH_BOOTCODE_START)
-		return -ENODEV;
+	spi = &nic_data->spi_flash;
+	if (efx_spi_present(spi) && spi->size > FALCON_FLASH_BOOTCODE_START) {
+		efx_mtd = kzalloc(sizeof(*efx_mtd) + sizeof(efx_mtd->part[0]),
+				  GFP_KERNEL);
+		if (!efx_mtd)
+			return -ENOMEM;
 
-	efx_mtd = kzalloc(sizeof(*efx_mtd) + sizeof(efx_mtd->part[0]),
-			  GFP_KERNEL);
-	if (!efx_mtd)
-		return -ENOMEM;
+		efx_mtd->spi = spi;
+		efx_mtd->name = "flash";
+		efx_mtd->ops = &falcon_mtd_ops;
 
-	efx_mtd->spi = spi;
-	efx_mtd->name = "flash";
-	efx_mtd->ops = &falcon_mtd_ops;
+		efx_mtd->n_parts = 1;
+		efx_mtd->part[0].mtd.type = MTD_NORFLASH;
+		efx_mtd->part[0].mtd.flags = MTD_CAP_NORFLASH;
+		efx_mtd->part[0].mtd.size = spi->size - FALCON_FLASH_BOOTCODE_START;
+		efx_mtd->part[0].mtd.erasesize = spi->erase_size;
+		efx_mtd->part[0].offset = FALCON_FLASH_BOOTCODE_START;
+		efx_mtd->part[0].type_name = "sfc_flash_bootrom";
 
-	efx_mtd->n_parts = 1;
-	efx_mtd->part[0].mtd.type = MTD_NORFLASH;
-	efx_mtd->part[0].mtd.flags = MTD_CAP_NORFLASH;
-	efx_mtd->part[0].mtd.size = spi->size - FALCON_FLASH_BOOTCODE_START;
-	efx_mtd->part[0].mtd.erasesize = spi->erase_size;
-	efx_mtd->part[0].offset = FALCON_FLASH_BOOTCODE_START;
-	efx_mtd->part[0].type_name = "sfc_flash_bootrom";
+		rc = efx_mtd_probe_device(efx, efx_mtd);
+		if (rc) {
+			kfree(efx_mtd);
+			return rc;
+		}
+	}
+
+	spi = &nic_data->spi_eeprom;
+	if (efx_spi_present(spi) && spi->size > EFX_EEPROM_BOOTCONFIG_START) {
+		efx_mtd = kzalloc(sizeof(*efx_mtd) + sizeof(efx_mtd->part[0]),
+				  GFP_KERNEL);
+		if (!efx_mtd)
+			return -ENOMEM;
+
+		efx_mtd->spi = spi;
+		efx_mtd->name = "EEPROM";
+		efx_mtd->ops = &falcon_mtd_ops;
+
+		efx_mtd->n_parts = 1;
+		efx_mtd->part[0].mtd.type = MTD_RAM;
+		efx_mtd->part[0].mtd.flags = MTD_CAP_RAM;
+		efx_mtd->part[0].mtd.size =
+			min(spi->size, EFX_EEPROM_BOOTCONFIG_END) -
+			EFX_EEPROM_BOOTCONFIG_START;
+		efx_mtd->part[0].mtd.erasesize = spi->erase_size;
+		efx_mtd->part[0].offset = EFX_EEPROM_BOOTCONFIG_START;
+		efx_mtd->part[0].type_name = "sfc_bootconfig";
+
+		rc = efx_mtd_probe_device(efx, efx_mtd);
+		if (rc) {
+			kfree(efx_mtd);
+			return rc;
+		}
+	}
 
-	rc = efx_mtd_probe_device(efx, efx_mtd);
-	if (rc)
-		kfree(efx_mtd);
 	return rc;
 }
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/sfc/net_driver.h linux-libre-2.6.38-gnu1/drivers/net/sfc/net_driver.h
--- linux-libre-2.6.37-gnu1/drivers/net/sfc/net_driver.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/sfc/net_driver.h	2011-03-14 21:20:32.000000000 -0400
@@ -136,14 +136,19 @@ struct efx_tx_buffer {
  * @efx: The associated Efx NIC
  * @queue: DMA queue number
  * @channel: The associated channel
+ * @core_txq: The networking core TX queue structure
  * @buffer: The software buffer ring
  * @txd: The hardware descriptor ring
  * @ptr_mask: The size of the ring minus 1.
  * @flushed: Used when handling queue flushing
  * @read_count: Current read pointer.
  *	This is the number of buffers that have been removed from both rings.
- * @stopped: Stopped count.
- *	Set if this TX queue is currently stopping its port.
+ * @old_write_count: The value of @write_count when last checked.
+ *	This is here for performance reasons.  The xmit path will
+ *	only get the up-to-date value of @write_count if this
+ *	variable indicates that the queue is empty.  This is to
+ *	avoid cache-line ping-pong between the xmit path and the
+ *	completion path.
  * @insert_count: Current insert pointer
  *	This is the number of buffers that have been added to the
  *	software ring.
@@ -163,13 +168,17 @@ struct efx_tx_buffer {
  * @tso_long_headers: Number of packets with headers too long for standard
  *	blocks
  * @tso_packets: Number of packets via the TSO xmit path
+ * @pushes: Number of times the TX push feature has been used
+ * @empty_read_count: If the completion path has seen the queue as empty
+ *	and the transmission path has not yet checked this, the value of
+ *	@read_count bitwise-added to %EFX_EMPTY_COUNT_VALID; otherwise 0.
  */
 struct efx_tx_queue {
 	/* Members which don't change on the fast path */
 	struct efx_nic *efx ____cacheline_aligned_in_smp;
 	unsigned queue;
 	struct efx_channel *channel;
-	struct efx_nic *nic;
+	struct netdev_queue *core_txq;
 	struct efx_tx_buffer *buffer;
 	struct efx_special_buffer txd;
 	unsigned int ptr_mask;
@@ -177,7 +186,7 @@ struct efx_tx_queue {
 
 	/* Members used mainly on the completion path */
 	unsigned int read_count ____cacheline_aligned_in_smp;
-	int stopped;
+	unsigned int old_write_count;
 
 	/* Members used only on the xmit path */
 	unsigned int insert_count ____cacheline_aligned_in_smp;
@@ -187,6 +196,11 @@ struct efx_tx_queue {
 	unsigned int tso_bursts;
 	unsigned int tso_long_headers;
 	unsigned int tso_packets;
+	unsigned int pushes;
+
+	/* Members shared between paths and sometimes updated */
+	unsigned int empty_read_count ____cacheline_aligned_in_smp;
+#define EFX_EMPTY_COUNT_VALID 0x80000000
 };
 
 /**
@@ -305,7 +319,6 @@ enum efx_rx_alloc_method {
  * @irq_moderation: IRQ moderation value (in hardware ticks)
  * @napi_dev: Net device used with NAPI
  * @napi_str: NAPI control structure
- * @reset_work: Scheduled reset work thread
  * @work_pending: Is work pending via NAPI?
  * @eventq: Event queue buffer
  * @eventq_mask: Event queue pointer mask
@@ -326,8 +339,6 @@ enum efx_rx_alloc_method {
  * @n_rx_overlength: Count of RX_OVERLENGTH errors
  * @n_skbuff_leaks: Count of skbuffs leaked due to RX overrun
  * @rx_queue: RX queue for this channel
- * @tx_stop_count: Core TX queue stop count
- * @tx_stop_lock: Core TX queue stop lock
  * @tx_queue: TX queues for this channel
  */
 struct efx_channel {
@@ -366,10 +377,6 @@ struct efx_channel {
 	bool rx_pkt_csummed;
 
 	struct efx_rx_queue rx_queue;
-
-	atomic_t tx_stop_count;
-	spinlock_t tx_stop_lock;
-
 	struct efx_tx_queue tx_queue[2];
 };
 
@@ -626,10 +633,8 @@ struct efx_filter_state;
  *	Work items do not hold and must not acquire RTNL.
  * @workqueue_name: Name of workqueue
  * @reset_work: Scheduled reset workitem
- * @monitor_work: Hardware monitor workitem
  * @membase_phys: Memory BAR value as physical address
  * @membase: Memory BAR value
- * @biu_lock: BIU (bus interface unit) lock
  * @interrupt_mode: Interrupt mode
  * @irq_rx_adaptive: Adaptive IRQ moderation enabled for RX event queues
  * @irq_rx_moderation: IRQ moderation time for RX event queues
@@ -648,23 +653,14 @@ struct efx_filter_state;
  * @n_tx_channels: Number of channels used for TX
  * @rx_buffer_len: RX buffer length
  * @rx_buffer_order: Order (log2) of number of pages for each RX buffer
+ * @rx_hash_key: Toeplitz hash key for RSS
  * @rx_indir_table: Indirection table for RSS
  * @int_error_count: Number of internal errors seen recently
  * @int_error_expire: Time at which error count will be expired
  * @irq_status: Interrupt status buffer
- * @last_irq_cpu: Last CPU to handle interrupt.
- *	This register is written with the SMP processor ID whenever an
- *	interrupt is handled.  It is used by efx_nic_test_interrupt()
- *	to verify that an interrupt has occurred.
  * @irq_zero_count: Number of legacy IRQs seen with queue flags == 0
  * @fatal_irq_level: IRQ level (bit number) used for serious errors
- * @spi_flash: SPI flash device
- *	This field will be %NULL if no flash device is present (or for Siena).
- * @spi_eeprom: SPI EEPROM device
- *	This field will be %NULL if no EEPROM device is present (or for Siena).
- * @spi_lock: SPI bus lock
  * @mtd_list: List of MTDs attached to the NIC
- * @n_rx_nodesc_drop_cnt: RX no descriptor drop count
  * @nic_data: Hardware dependant state
  * @mac_lock: MAC access lock. Protects @port_enabled, @phy_mode,
  *	@port_inhibited, efx_monitor() and efx_reconfigure_port()
@@ -677,21 +673,14 @@ struct efx_filter_state;
  * @port_initialized: Port initialized?
  * @net_dev: Operating system network device. Consider holding the rtnl lock
  * @rx_checksum_enabled: RX checksumming enabled
- * @mac_stats: MAC statistics. These include all statistics the MACs
- *	can provide.  Generic code converts these into a standard
- *	&struct net_device_stats.
  * @stats_buffer: DMA buffer for statistics
- * @stats_lock: Statistics update lock. Serialises statistics fetches
  * @mac_op: MAC interface
- * @mac_address: Permanent MAC address
  * @phy_type: PHY type
- * @mdio_lock: MDIO lock
  * @phy_op: PHY interface
  * @phy_data: PHY private data (including PHY-specific stats)
  * @mdio: PHY MDIO interface
  * @mdio_bus: PHY MDIO bus ID (only used by Siena)
  * @phy_mode: PHY operating mode. Serialised by @mac_lock.
- * @xmac_poll_required: XMAC link state needs polling
  * @link_advertising: Autonegotiation advertising flags
  * @link_state: Current state of the link
  * @n_link_state_changes: Number of times the link has changed state
@@ -702,10 +691,23 @@ struct efx_filter_state;
  * @loopback_mode: Loopback status
  * @loopback_modes: Supported loopback mode bitmask
  * @loopback_selftest: Offline self-test private state
+ * @monitor_work: Hardware monitor workitem
+ * @biu_lock: BIU (bus interface unit) lock
+ * @last_irq_cpu: Last CPU to handle interrupt.
+ *	This register is written with the SMP processor ID whenever an
+ *	interrupt is handled.  It is used by efx_nic_test_interrupt()
+ *	to verify that an interrupt has occurred.
+ * @n_rx_nodesc_drop_cnt: RX no descriptor drop count
+ * @mac_stats: MAC statistics. These include all statistics the MACs
+ *	can provide.  Generic code converts these into a standard
+ *	&struct net_device_stats.
+ * @stats_lock: Statistics update lock. Serialises statistics fetches
  *
  * This is stored in the private area of the &struct net_device.
  */
 struct efx_nic {
+	/* The following fields should be written very rarely */
+
 	char name[IFNAMSIZ];
 	struct pci_dev *pci_dev;
 	const struct efx_nic_type *type;
@@ -714,10 +716,9 @@ struct efx_nic {
 	struct workqueue_struct *workqueue;
 	char workqueue_name[16];
 	struct work_struct reset_work;
-	struct delayed_work monitor_work;
 	resource_size_t membase_phys;
 	void __iomem *membase;
-	spinlock_t biu_lock;
+
 	enum efx_int_mode interrupt_mode;
 	bool irq_rx_adaptive;
 	unsigned int irq_rx_moderation;
@@ -734,6 +735,7 @@ struct efx_nic {
 	unsigned next_buffer_table;
 	unsigned n_channels;
 	unsigned n_rx_channels;
+	unsigned tx_channel_offset;
 	unsigned n_tx_channels;
 	unsigned int rx_buffer_len;
 	unsigned int rx_buffer_order;
@@ -744,19 +746,13 @@ struct efx_nic {
 	unsigned long int_error_expire;
 
 	struct efx_buffer irq_status;
-	volatile signed int last_irq_cpu;
 	unsigned irq_zero_count;
 	unsigned fatal_irq_level;
 
-	struct efx_spi_device *spi_flash;
-	struct efx_spi_device *spi_eeprom;
-	struct mutex spi_lock;
 #ifdef CONFIG_SFC_MTD
 	struct list_head mtd_list;
 #endif
 
-	unsigned n_rx_nodesc_drop_cnt;
-
 	void *nic_data;
 
 	struct mutex mac_lock;
@@ -768,22 +764,17 @@ struct efx_nic {
 	struct net_device *net_dev;
 	bool rx_checksum_enabled;
 
-	struct efx_mac_stats mac_stats;
 	struct efx_buffer stats_buffer;
-	spinlock_t stats_lock;
 
 	struct efx_mac_operations *mac_op;
-	unsigned char mac_address[ETH_ALEN];
 
 	unsigned int phy_type;
-	struct mutex mdio_lock;
 	struct efx_phy_operations *phy_op;
 	void *phy_data;
 	struct mdio_if_info mdio;
 	unsigned int mdio_bus;
 	enum efx_phy_mode phy_mode;
 
-	bool xmac_poll_required;
 	u32 link_advertising;
 	struct efx_link_state link_state;
 	unsigned int n_link_state_changes;
@@ -799,6 +790,15 @@ struct efx_nic {
 	void *loopback_selftest;
 
 	struct efx_filter_state *filter_state;
+
+	/* The following fields may be written more often */
+
+	struct delayed_work monitor_work ____cacheline_aligned_in_smp;
+	spinlock_t biu_lock;
+	volatile signed int last_irq_cpu;
+	unsigned n_rx_nodesc_drop_cnt;
+	struct efx_mac_stats mac_stats;
+	spinlock_t stats_lock;
 };
 
 static inline int efx_dev_registered(struct efx_nic *efx)
@@ -831,6 +831,7 @@ static inline unsigned int efx_port_num(
  *	be called while the controller is uninitialised.
  * @probe_port: Probe the MAC and PHY
  * @remove_port: Free resources allocated by probe_port()
+ * @handle_global_event: Handle a "global" event (may be %NULL)
  * @prepare_flush: Prepare the hardware for flushing the DMA queues
  * @update_stats: Update statistics not provided by event handling
  * @start_stats: Start the regular fetching of statistics
@@ -875,6 +876,7 @@ struct efx_nic_type {
 	int (*reset)(struct efx_nic *efx, enum reset_type method);
 	int (*probe_port)(struct efx_nic *efx);
 	void (*remove_port)(struct efx_nic *efx);
+	bool (*handle_global_event)(struct efx_channel *channel, efx_qword_t *);
 	void (*prepare_flush)(struct efx_nic *efx);
 	void (*update_stats)(struct efx_nic *efx);
 	void (*start_stats)(struct efx_nic *efx);
@@ -928,8 +930,13 @@ efx_get_channel(struct efx_nic *efx, uns
 	     _channel = (_channel->channel + 1 < (_efx)->n_channels) ?	\
 		     (_efx)->channel[_channel->channel + 1] : NULL)
 
-extern struct efx_tx_queue *
-efx_get_tx_queue(struct efx_nic *efx, unsigned index, unsigned type);
+static inline struct efx_tx_queue *
+efx_get_tx_queue(struct efx_nic *efx, unsigned index, unsigned type)
+{
+	EFX_BUG_ON_PARANOID(index >= efx->n_tx_channels ||
+			    type >= EFX_TXQ_TYPES);
+	return &efx->channel[efx->tx_channel_offset + index]->tx_queue[type];
+}
 
 static inline struct efx_tx_queue *
 efx_channel_get_tx_queue(struct efx_channel *channel, unsigned type)
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/sfc/nic.c linux-libre-2.6.38-gnu1/drivers/net/sfc/nic.c
--- linux-libre-2.6.37-gnu1/drivers/net/sfc/nic.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/sfc/nic.c	2011-03-14 21:20:32.000000000 -0400
@@ -362,6 +362,35 @@ static inline void efx_notify_tx_desc(st
 			FR_AZ_TX_DESC_UPD_DWORD_P0, tx_queue->queue);
 }
 
+/* Write pointer and first descriptor for TX descriptor ring */
+static inline void efx_push_tx_desc(struct efx_tx_queue *tx_queue,
+				    const efx_qword_t *txd)
+{
+	unsigned write_ptr;
+	efx_oword_t reg;
+
+	BUILD_BUG_ON(FRF_AZ_TX_DESC_LBN != 0);
+	BUILD_BUG_ON(FR_AA_TX_DESC_UPD_KER != FR_BZ_TX_DESC_UPD_P0);
+
+	write_ptr = tx_queue->write_count & tx_queue->ptr_mask;
+	EFX_POPULATE_OWORD_2(reg, FRF_AZ_TX_DESC_PUSH_CMD, true,
+			     FRF_AZ_TX_DESC_WPTR, write_ptr);
+	reg.qword[0] = *txd;
+	efx_writeo_page(tx_queue->efx, &reg,
+			FR_BZ_TX_DESC_UPD_P0, tx_queue->queue);
+}
+
+static inline bool
+efx_may_push_tx_desc(struct efx_tx_queue *tx_queue, unsigned int write_count)
+{
+	unsigned empty_read_count = ACCESS_ONCE(tx_queue->empty_read_count);
+
+	if (empty_read_count == 0)
+		return false;
+
+	tx_queue->empty_read_count = 0;
+	return ((empty_read_count ^ write_count) & ~EFX_EMPTY_COUNT_VALID) == 0;
+}
 
 /* For each entry inserted into the software descriptor ring, create a
  * descriptor in the hardware TX descriptor ring (in host memory), and
@@ -373,6 +402,7 @@ void efx_nic_push_buffers(struct efx_tx_
 	struct efx_tx_buffer *buffer;
 	efx_qword_t *txd;
 	unsigned write_ptr;
+	unsigned old_write_count = tx_queue->write_count;
 
 	BUG_ON(tx_queue->write_count == tx_queue->insert_count);
 
@@ -391,7 +421,15 @@ void efx_nic_push_buffers(struct efx_tx_
 	} while (tx_queue->write_count != tx_queue->insert_count);
 
 	wmb(); /* Ensure descriptors are written before they are fetched */
-	efx_notify_tx_desc(tx_queue);
+
+	if (efx_may_push_tx_desc(tx_queue, old_write_count)) {
+		txd = efx_tx_desc(tx_queue,
+				  old_write_count & tx_queue->ptr_mask);
+		efx_push_tx_desc(tx_queue, txd);
+		++tx_queue->pushes;
+	} else {
+		efx_notify_tx_desc(tx_queue);
+	}
 }
 
 /* Allocate hardware resources for a TX queue */
@@ -894,46 +932,6 @@ efx_handle_generated_event(struct efx_ch
 			  channel->channel, EFX_QWORD_VAL(*event));
 }
 
-/* Global events are basically PHY events */
-static void
-efx_handle_global_event(struct efx_channel *channel, efx_qword_t *event)
-{
-	struct efx_nic *efx = channel->efx;
-	bool handled = false;
-
-	if (EFX_QWORD_FIELD(*event, FSF_AB_GLB_EV_G_PHY0_INTR) ||
-	    EFX_QWORD_FIELD(*event, FSF_AB_GLB_EV_XG_PHY0_INTR) ||
-	    EFX_QWORD_FIELD(*event, FSF_AB_GLB_EV_XFP_PHY0_INTR)) {
-		/* Ignored */
-		handled = true;
-	}
-
-	if ((efx_nic_rev(efx) >= EFX_REV_FALCON_B0) &&
-	    EFX_QWORD_FIELD(*event, FSF_BB_GLB_EV_XG_MGT_INTR)) {
-		efx->xmac_poll_required = true;
-		handled = true;
-	}
-
-	if (efx_nic_rev(efx) <= EFX_REV_FALCON_A1 ?
-	    EFX_QWORD_FIELD(*event, FSF_AA_GLB_EV_RX_RECOVERY) :
-	    EFX_QWORD_FIELD(*event, FSF_BB_GLB_EV_RX_RECOVERY)) {
-		netif_err(efx, rx_err, efx->net_dev,
-			  "channel %d seen global RX_RESET event. Resetting.\n",
-			  channel->channel);
-
-		atomic_inc(&efx->rx_reset);
-		efx_schedule_reset(efx, EFX_WORKAROUND_6555(efx) ?
-				   RESET_TYPE_RX_RECOVERY : RESET_TYPE_DISABLE);
-		handled = true;
-	}
-
-	if (!handled)
-		netif_err(efx, hw, efx->net_dev,
-			  "channel %d unknown global event "
-			  EFX_QWORD_FMT "\n", channel->channel,
-			  EFX_QWORD_VAL(*event));
-}
-
 static void
 efx_handle_driver_event(struct efx_channel *channel, efx_qword_t *event)
 {
@@ -1050,15 +1048,17 @@ int efx_nic_process_eventq(struct efx_ch
 		case FSE_AZ_EV_CODE_DRV_GEN_EV:
 			efx_handle_generated_event(channel, &event);
 			break;
-		case FSE_AZ_EV_CODE_GLOBAL_EV:
-			efx_handle_global_event(channel, &event);
-			break;
 		case FSE_AZ_EV_CODE_DRIVER_EV:
 			efx_handle_driver_event(channel, &event);
 			break;
 		case FSE_CZ_EV_CODE_MCDI_EV:
 			efx_mcdi_process_event(channel, &event);
 			break;
+		case FSE_AZ_EV_CODE_GLOBAL_EV:
+			if (efx->type->handle_global_event &&
+			    efx->type->handle_global_event(channel, &event))
+				break;
+			/* else fall through */
 		default:
 			netif_err(channel->efx, hw, channel->efx->net_dev,
 				  "channel %d unknown event type %d (data "
@@ -1670,7 +1670,7 @@ void efx_nic_init_common(struct efx_nic
 	EFX_SET_OWORD_FIELD(temp, FRF_AZ_TX_RX_SPACER, 0xfe);
 	EFX_SET_OWORD_FIELD(temp, FRF_AZ_TX_RX_SPACER_EN, 1);
 	EFX_SET_OWORD_FIELD(temp, FRF_AZ_TX_ONE_PKT_PER_Q, 1);
-	EFX_SET_OWORD_FIELD(temp, FRF_AZ_TX_PUSH_EN, 0);
+	EFX_SET_OWORD_FIELD(temp, FRF_AZ_TX_PUSH_EN, 1);
 	EFX_SET_OWORD_FIELD(temp, FRF_AZ_TX_DIS_NON_IP_EV, 1);
 	/* Enable SW_EV to inherit in char driver - assume harmless here */
 	EFX_SET_OWORD_FIELD(temp, FRF_AZ_TX_SOFT_EVT_EN, 1);
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/sfc/nic.h linux-libre-2.6.38-gnu1/drivers/net/sfc/nic.h
--- linux-libre-2.6.37-gnu1/drivers/net/sfc/nic.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/sfc/nic.h	2011-03-14 21:20:32.000000000 -0400
@@ -15,6 +15,7 @@
 #include "net_driver.h"
 #include "efx.h"
 #include "mcdi.h"
+#include "spi.h"
 
 /*
  * Falcon hardware control
@@ -113,6 +114,11 @@ struct falcon_board {
  * @stats_pending: Is there a pending DMA of MAC statistics.
  * @stats_timer: A timer for regularly fetching MAC statistics.
  * @stats_dma_done: Pointer to the flag which indicates DMA completion.
+ * @spi_flash: SPI flash device
+ * @spi_eeprom: SPI EEPROM device
+ * @spi_lock: SPI bus lock
+ * @mdio_lock: MDIO bus lock
+ * @xmac_poll_required: XMAC link state needs polling
  */
 struct falcon_nic_data {
 	struct pci_dev *pci_dev2;
@@ -121,6 +127,11 @@ struct falcon_nic_data {
 	bool stats_pending;
 	struct timer_list stats_timer;
 	u32 *stats_dma_done;
+	struct efx_spi_device spi_flash;
+	struct efx_spi_device spi_eeprom;
+	struct mutex spi_lock;
+	struct mutex mdio_lock;
+	bool xmac_poll_required;
 };
 
 static inline struct falcon_board *falcon_board(struct efx_nic *efx)
@@ -135,7 +146,6 @@ static inline struct falcon_board *falco
  * @fw_build: Firmware build number
  * @mcdi: Management-Controller-to-Driver Interface
  * @wol_filter_id: Wake-on-LAN packet filter id
- * @ipv6_rss_key: Toeplitz hash key for IPv6 RSS
  */
 struct siena_nic_data {
 	u64 fw_version;
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/sfc/qt202x_phy.c linux-libre-2.6.38-gnu1/drivers/net/sfc/qt202x_phy.c
--- linux-libre-2.6.37-gnu1/drivers/net/sfc/qt202x_phy.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/sfc/qt202x_phy.c	2011-03-14 21:20:32.000000000 -0400
@@ -41,6 +41,8 @@
 #define PCS_UC_STATUS_LBN	0
 #define PCS_UC_STATUS_WIDTH	8
 #define PCS_UC_STATUS_FW_SAVE	0x20
+#define PMA_PMD_MODE_REG	0xc301
+#define PMA_PMD_RXIN_SEL_LBN	6
 #define PMA_PMD_FTX_CTRL2_REG	0xc309
 #define PMA_PMD_FTX_STATIC_LBN	13
 #define PMA_PMD_VEND1_REG	0xc001
@@ -282,6 +284,10 @@ static int qt2025c_select_phy_mode(struc
 	 * slow) reload of the firmware image (the microcontroller's code
 	 * memory is not affected by the microcontroller reset). */
 	efx_mdio_write(efx, 1, 0xc317, 0x00ff);
+	/* PMA/PMD loopback sets RXIN to inverse polarity and the firmware
+	 * restart doesn't reset it. We need to do that ourselves. */
+	efx_mdio_set_flag(efx, 1, PMA_PMD_MODE_REG,
+			  1 << PMA_PMD_RXIN_SEL_LBN, false);
 	efx_mdio_write(efx, 1, 0xc300, 0x0002);
 	msleep(20);
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/sfc/rx.c linux-libre-2.6.38-gnu1/drivers/net/sfc/rx.c
--- linux-libre-2.6.37-gnu1/drivers/net/sfc/rx.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/sfc/rx.c	2011-03-14 21:20:32.000000000 -0400
@@ -37,7 +37,7 @@
  * This driver supports two methods for allocating and using RX buffers:
  * each RX buffer may be backed by an skb or by an order-n page.
  *
- * When LRO is in use then the second method has a lower overhead,
+ * When GRO is in use then the second method has a lower overhead,
  * since we don't have to allocate then free skbs on reassembled frames.
  *
  * Values:
@@ -50,25 +50,25 @@
  *
  *   - Since pushing and popping descriptors are separated by the rx_queue
  *     size, so the watermarks should be ~rxd_size.
- *   - The performance win by using page-based allocation for LRO is less
- *     than the performance hit of using page-based allocation of non-LRO,
+ *   - The performance win by using page-based allocation for GRO is less
+ *     than the performance hit of using page-based allocation of non-GRO,
  *     so the watermarks should reflect this.
  *
  * Per channel we maintain a single variable, updated by each channel:
  *
- *   rx_alloc_level += (lro_performed ? RX_ALLOC_FACTOR_LRO :
+ *   rx_alloc_level += (gro_performed ? RX_ALLOC_FACTOR_GRO :
  *                      RX_ALLOC_FACTOR_SKB)
  * Per NAPI poll interval, we constrain rx_alloc_level to 0..MAX (which
  * limits the hysteresis), and update the allocation strategy:
  *
- *   rx_alloc_method = (rx_alloc_level > RX_ALLOC_LEVEL_LRO ?
+ *   rx_alloc_method = (rx_alloc_level > RX_ALLOC_LEVEL_GRO ?
  *                      RX_ALLOC_METHOD_PAGE : RX_ALLOC_METHOD_SKB)
  */
 static int rx_alloc_method = RX_ALLOC_METHOD_AUTO;
 
-#define RX_ALLOC_LEVEL_LRO 0x2000
+#define RX_ALLOC_LEVEL_GRO 0x2000
 #define RX_ALLOC_LEVEL_MAX 0x3000
-#define RX_ALLOC_FACTOR_LRO 1
+#define RX_ALLOC_FACTOR_GRO 1
 #define RX_ALLOC_FACTOR_SKB (-2)
 
 /* This is the percentage fill level below which new RX descriptors
@@ -441,19 +441,19 @@ static void efx_rx_packet__check_len(str
 	efx_rx_queue_channel(rx_queue)->n_rx_overlength++;
 }
 
-/* Pass a received packet up through the generic LRO stack
+/* Pass a received packet up through the generic GRO stack
  *
  * Handles driverlink veto, and passes the fragment up via
- * the appropriate LRO method
+ * the appropriate GRO method
  */
-static void efx_rx_packet_lro(struct efx_channel *channel,
+static void efx_rx_packet_gro(struct efx_channel *channel,
 			      struct efx_rx_buffer *rx_buf,
 			      bool checksummed)
 {
 	struct napi_struct *napi = &channel->napi_str;
 	gro_result_t gro_result;
 
-	/* Pass the skb/page into the LRO engine */
+	/* Pass the skb/page into the GRO engine */
 	if (rx_buf->page) {
 		struct efx_nic *efx = channel->efx;
 		struct page *page = rx_buf->page;
@@ -499,7 +499,7 @@ static void efx_rx_packet_lro(struct efx
 	if (gro_result == GRO_NORMAL) {
 		channel->rx_alloc_level += RX_ALLOC_FACTOR_SKB;
 	} else if (gro_result != GRO_DROP) {
-		channel->rx_alloc_level += RX_ALLOC_FACTOR_LRO;
+		channel->rx_alloc_level += RX_ALLOC_FACTOR_GRO;
 		channel->irq_mod_score += 2;
 	}
 }
@@ -605,7 +605,7 @@ void __efx_rx_packet(struct efx_channel
 	}
 
 	if (likely(checksummed || rx_buf->page)) {
-		efx_rx_packet_lro(channel, rx_buf, checksummed);
+		efx_rx_packet_gro(channel, rx_buf, checksummed);
 		return;
 	}
 
@@ -628,7 +628,7 @@ void efx_rx_strategy(struct efx_channel
 {
 	enum efx_rx_alloc_method method = rx_alloc_method;
 
-	/* Only makes sense to use page based allocation if LRO is enabled */
+	/* Only makes sense to use page based allocation if GRO is enabled */
 	if (!(channel->efx->net_dev->features & NETIF_F_GRO)) {
 		method = RX_ALLOC_METHOD_SKB;
 	} else if (method == RX_ALLOC_METHOD_AUTO) {
@@ -639,7 +639,7 @@ void efx_rx_strategy(struct efx_channel
 			channel->rx_alloc_level = RX_ALLOC_LEVEL_MAX;
 
 		/* Decide on the allocation method */
-		method = ((channel->rx_alloc_level > RX_ALLOC_LEVEL_LRO) ?
+		method = ((channel->rx_alloc_level > RX_ALLOC_LEVEL_GRO) ?
 			  RX_ALLOC_METHOD_PAGE : RX_ALLOC_METHOD_SKB);
 	}
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/sfc/siena.c linux-libre-2.6.38-gnu1/drivers/net/sfc/siena.c
--- linux-libre-2.6.37-gnu1/drivers/net/sfc/siena.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/sfc/siena.c	2011-03-14 21:20:32.000000000 -0400
@@ -194,13 +194,7 @@ static int siena_reset_hw(struct efx_nic
 
 static int siena_probe_nvconfig(struct efx_nic *efx)
 {
-	int rc;
-
-	rc = efx_mcdi_get_board_cfg(efx, efx->mac_address, NULL);
-	if (rc)
-		return rc;
-
-	return 0;
+	return efx_mcdi_get_board_cfg(efx, efx->net_dev->perm_addr, NULL);
 }
 
 static int siena_probe_nic(struct efx_nic *efx)
@@ -562,7 +556,7 @@ static int siena_set_wol(struct efx_nic
 		if (nic_data->wol_filter_id != -1)
 			efx_mcdi_wol_filter_remove(efx,
 						   nic_data->wol_filter_id);
-		rc = efx_mcdi_wol_filter_set_magic(efx, efx->mac_address,
+		rc = efx_mcdi_wol_filter_set_magic(efx, efx->net_dev->dev_addr,
 						   &nic_data->wol_filter_id);
 		if (rc)
 			goto fail;
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/sfc/spi.h linux-libre-2.6.38-gnu1/drivers/net/sfc/spi.h
--- linux-libre-2.6.37-gnu1/drivers/net/sfc/spi.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/sfc/spi.h	2011-03-14 21:20:32.000000000 -0400
@@ -61,6 +61,11 @@ struct efx_spi_device {
 	unsigned int block_size;
 };
 
+static inline bool efx_spi_present(const struct efx_spi_device *spi)
+{
+	return spi->size != 0;
+}
+
 int falcon_spi_cmd(struct efx_nic *efx,
 		   const struct efx_spi_device *spi, unsigned int command,
 		   int address, const void* in, void *out, size_t len);
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/sfc/tenxpress.c linux-libre-2.6.38-gnu1/drivers/net/sfc/tenxpress.c
--- linux-libre-2.6.37-gnu1/drivers/net/sfc/tenxpress.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/sfc/tenxpress.c	2011-03-14 21:20:32.000000000 -0400
@@ -15,9 +15,7 @@
 #include "mdio_10g.h"
 #include "nic.h"
 #include "phy.h"
-#include "regs.h"
 #include "workarounds.h"
-#include "selftest.h"
 
 /* We expect these MMDs to be in the package. */
 #define TENXPRESS_REQUIRED_DEVS (MDIO_DEVS_PMAPMD	| \
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/sfc/tx.c linux-libre-2.6.38-gnu1/drivers/net/sfc/tx.c
--- linux-libre-2.6.37-gnu1/drivers/net/sfc/tx.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/sfc/tx.c	2011-03-14 21:20:32.000000000 -0400
@@ -30,50 +30,6 @@
  */
 #define EFX_TXQ_THRESHOLD(_efx) ((_efx)->txq_entries / 2u)
 
-/* We need to be able to nest calls to netif_tx_stop_queue(), partly
- * because of the 2 hardware queues associated with each core queue,
- * but also so that we can inhibit TX for reasons other than a full
- * hardware queue. */
-void efx_stop_queue(struct efx_channel *channel)
-{
-	struct efx_nic *efx = channel->efx;
-	struct efx_tx_queue *tx_queue = efx_channel_get_tx_queue(channel, 0);
-
-	if (!tx_queue)
-		return;
-
-	spin_lock_bh(&channel->tx_stop_lock);
-	netif_vdbg(efx, tx_queued, efx->net_dev, "stop TX queue\n");
-
-	atomic_inc(&channel->tx_stop_count);
-	netif_tx_stop_queue(
-		netdev_get_tx_queue(efx->net_dev,
-				    tx_queue->queue / EFX_TXQ_TYPES));
-
-	spin_unlock_bh(&channel->tx_stop_lock);
-}
-
-/* Decrement core TX queue stop count and wake it if the count is 0 */
-void efx_wake_queue(struct efx_channel *channel)
-{
-	struct efx_nic *efx = channel->efx;
-	struct efx_tx_queue *tx_queue = efx_channel_get_tx_queue(channel, 0);
-
-	if (!tx_queue)
-		return;
-
-	local_bh_disable();
-	if (atomic_dec_and_lock(&channel->tx_stop_count,
-				&channel->tx_stop_lock)) {
-		netif_vdbg(efx, tx_queued, efx->net_dev, "waking TX queue\n");
-		netif_tx_wake_queue(
-			netdev_get_tx_queue(efx->net_dev,
-					    tx_queue->queue / EFX_TXQ_TYPES));
-		spin_unlock(&channel->tx_stop_lock);
-	}
-	local_bh_enable();
-}
-
 static void efx_dequeue_buffer(struct efx_tx_queue *tx_queue,
 			       struct efx_tx_buffer *buffer)
 {
@@ -234,21 +190,22 @@ netdev_tx_t efx_enqueue_skb(struct efx_t
 				 * checked.  Update the xmit path's
 				 * copy of read_count.
 				 */
-				++tx_queue->stopped;
+				netif_tx_stop_queue(tx_queue->core_txq);
 				/* This memory barrier protects the
-				 * change of stopped from the access
+				 * change of queue state from the access
 				 * of read_count. */
 				smp_mb();
 				tx_queue->old_read_count =
-					*(volatile unsigned *)
-					&tx_queue->read_count;
+					ACCESS_ONCE(tx_queue->read_count);
 				fill_level = (tx_queue->insert_count
 					      - tx_queue->old_read_count);
 				q_space = efx->txq_entries - 1 - fill_level;
-				if (unlikely(q_space-- <= 0))
-					goto stop;
+				if (unlikely(q_space-- <= 0)) {
+					rc = NETDEV_TX_BUSY;
+					goto unwind;
+				}
 				smp_mb();
-				--tx_queue->stopped;
+				netif_tx_start_queue(tx_queue->core_txq);
 			}
 
 			insert_ptr = tx_queue->insert_count & tx_queue->ptr_mask;
@@ -308,13 +265,6 @@ netdev_tx_t efx_enqueue_skb(struct efx_t
 
 	/* Mark the packet as transmitted, and free the SKB ourselves */
 	dev_kfree_skb_any(skb);
-	goto unwind;
-
- stop:
-	rc = NETDEV_TX_BUSY;
-
-	if (tx_queue->stopped == 1)
-		efx_stop_queue(tx_queue->channel);
 
  unwind:
 	/* Work backwards until we hit the original insert pointer value */
@@ -407,22 +357,25 @@ void efx_xmit_done(struct efx_tx_queue *
 	efx_dequeue_buffers(tx_queue, index);
 
 	/* See if we need to restart the netif queue.  This barrier
-	 * separates the update of read_count from the test of
-	 * stopped. */
+	 * separates the update of read_count from the test of the
+	 * queue state. */
 	smp_mb();
-	if (unlikely(tx_queue->stopped) && likely(efx->port_enabled)) {
+	if (unlikely(netif_tx_queue_stopped(tx_queue->core_txq)) &&
+	    likely(efx->port_enabled)) {
 		fill_level = tx_queue->insert_count - tx_queue->read_count;
 		if (fill_level < EFX_TXQ_THRESHOLD(efx)) {
 			EFX_BUG_ON_PARANOID(!efx_dev_registered(efx));
+			netif_tx_wake_queue(tx_queue->core_txq);
+		}
+	}
 
-			/* Do this under netif_tx_lock(), to avoid racing
-			 * with efx_xmit(). */
-			netif_tx_lock(efx->net_dev);
-			if (tx_queue->stopped) {
-				tx_queue->stopped = 0;
-				efx_wake_queue(tx_queue->channel);
-			}
-			netif_tx_unlock(efx->net_dev);
+	/* Check whether the hardware queue is now empty */
+	if ((int)(tx_queue->read_count - tx_queue->old_write_count) >= 0) {
+		tx_queue->old_write_count = ACCESS_ONCE(tx_queue->write_count);
+		if (tx_queue->read_count == tx_queue->old_write_count) {
+			smp_mb();
+			tx_queue->empty_read_count =
+				tx_queue->read_count | EFX_EMPTY_COUNT_VALID;
 		}
 	}
 }
@@ -470,9 +423,10 @@ void efx_init_tx_queue(struct efx_tx_que
 
 	tx_queue->insert_count = 0;
 	tx_queue->write_count = 0;
+	tx_queue->old_write_count = 0;
 	tx_queue->read_count = 0;
 	tx_queue->old_read_count = 0;
-	BUG_ON(tx_queue->stopped);
+	tx_queue->empty_read_count = 0 | EFX_EMPTY_COUNT_VALID;
 
 	/* Set up TX descriptor ring */
 	efx_nic_init_tx(tx_queue);
@@ -508,12 +462,6 @@ void efx_fini_tx_queue(struct efx_tx_que
 
 	/* Free up TSO header cache */
 	efx_fini_tso(tx_queue);
-
-	/* Release queue's stop on port, if any */
-	if (tx_queue->stopped) {
-		tx_queue->stopped = 0;
-		efx_wake_queue(tx_queue->channel);
-	}
 }
 
 void efx_remove_tx_queue(struct efx_tx_queue *tx_queue)
@@ -755,12 +703,12 @@ static int efx_tx_queue_insert(struct ef
 			 * since the xmit path last checked.  Update
 			 * the xmit path's copy of read_count.
 			 */
-			++tx_queue->stopped;
+			netif_tx_stop_queue(tx_queue->core_txq);
 			/* This memory barrier protects the change of
-			 * stopped from the access of read_count. */
+			 * queue state from the access of read_count. */
 			smp_mb();
 			tx_queue->old_read_count =
-				*(volatile unsigned *)&tx_queue->read_count;
+				ACCESS_ONCE(tx_queue->read_count);
 			fill_level = (tx_queue->insert_count
 				      - tx_queue->old_read_count);
 			q_space = efx->txq_entries - 1 - fill_level;
@@ -769,7 +717,7 @@ static int efx_tx_queue_insert(struct ef
 				return 1;
 			}
 			smp_mb();
-			--tx_queue->stopped;
+			netif_tx_start_queue(tx_queue->core_txq);
 		}
 
 		insert_ptr = tx_queue->insert_count & tx_queue->ptr_mask;
@@ -1109,8 +1057,10 @@ static int efx_enqueue_skb_tso(struct ef
 
 	while (1) {
 		rc = tso_fill_packet_with_fragment(tx_queue, skb, &state);
-		if (unlikely(rc))
-			goto stop;
+		if (unlikely(rc)) {
+			rc2 = NETDEV_TX_BUSY;
+			goto unwind;
+		}
 
 		/* Move onto the next fragment? */
 		if (state.in_len == 0) {
@@ -1139,14 +1089,6 @@ static int efx_enqueue_skb_tso(struct ef
 	netif_err(efx, tx_err, efx->net_dev,
 		  "Out of memory for TSO headers, or PCI mapping error\n");
 	dev_kfree_skb_any(skb);
-	goto unwind;
-
- stop:
-	rc2 = NETDEV_TX_BUSY;
-
-	/* Stop the queue if it wasn't stopped before. */
-	if (tx_queue->stopped == 1)
-		efx_stop_queue(tx_queue->channel);
 
  unwind:
 	/* Free the DMA mapping we were in the process of writing out */
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/sh_eth.c linux-libre-2.6.38-gnu1/drivers/net/sh_eth.c
--- linux-libre-2.6.37-gnu1/drivers/net/sh_eth.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/sh_eth.c	2011-03-14 21:20:32.000000000 -0400
@@ -45,9 +45,9 @@ static void sh_eth_set_duplex(struct net
 	u32 ioaddr = ndev->base_addr;
 
 	if (mdp->duplex) /* Full */
-		ctrl_outl(ctrl_inl(ioaddr + ECMR) | ECMR_DM, ioaddr + ECMR);
+		writel(readl(ioaddr + ECMR) | ECMR_DM, ioaddr + ECMR);
 	else		/* Half */
-		ctrl_outl(ctrl_inl(ioaddr + ECMR) & ~ECMR_DM, ioaddr + ECMR);
+		writel(readl(ioaddr + ECMR) & ~ECMR_DM, ioaddr + ECMR);
 }
 
 static void sh_eth_set_rate(struct net_device *ndev)
@@ -57,10 +57,10 @@ static void sh_eth_set_rate(struct net_d
 
 	switch (mdp->speed) {
 	case 10: /* 10BASE */
-		ctrl_outl(ctrl_inl(ioaddr + ECMR) & ~ECMR_RTM, ioaddr + ECMR);
+		writel(readl(ioaddr + ECMR) & ~ECMR_RTM, ioaddr + ECMR);
 		break;
 	case 100:/* 100BASE */
-		ctrl_outl(ctrl_inl(ioaddr + ECMR) | ECMR_RTM, ioaddr + ECMR);
+		writel(readl(ioaddr + ECMR) | ECMR_RTM, ioaddr + ECMR);
 		break;
 	default:
 		break;
@@ -96,9 +96,9 @@ static void sh_eth_set_duplex(struct net
 	u32 ioaddr = ndev->base_addr;
 
 	if (mdp->duplex) /* Full */
-		ctrl_outl(ctrl_inl(ioaddr + ECMR) | ECMR_DM, ioaddr + ECMR);
+		writel(readl(ioaddr + ECMR) | ECMR_DM, ioaddr + ECMR);
 	else		/* Half */
-		ctrl_outl(ctrl_inl(ioaddr + ECMR) & ~ECMR_DM, ioaddr + ECMR);
+		writel(readl(ioaddr + ECMR) & ~ECMR_DM, ioaddr + ECMR);
 }
 
 static void sh_eth_set_rate(struct net_device *ndev)
@@ -108,10 +108,10 @@ static void sh_eth_set_rate(struct net_d
 
 	switch (mdp->speed) {
 	case 10: /* 10BASE */
-		ctrl_outl(0, ioaddr + RTRATE);
+		writel(0, ioaddr + RTRATE);
 		break;
 	case 100:/* 100BASE */
-		ctrl_outl(1, ioaddr + RTRATE);
+		writel(1, ioaddr + RTRATE);
 		break;
 	default:
 		break;
@@ -143,7 +143,7 @@ static struct sh_eth_cpu_data sh_eth_my_
 static void sh_eth_chip_reset(struct net_device *ndev)
 {
 	/* reset device */
-	ctrl_outl(ARSTR_ARSTR, ARSTR);
+	writel(ARSTR_ARSTR, ARSTR);
 	mdelay(1);
 }
 
@@ -152,10 +152,10 @@ static void sh_eth_reset(struct net_devi
 	u32 ioaddr = ndev->base_addr;
 	int cnt = 100;
 
-	ctrl_outl(EDSR_ENALL, ioaddr + EDSR);
-	ctrl_outl(ctrl_inl(ioaddr + EDMR) | EDMR_SRST, ioaddr + EDMR);
+	writel(EDSR_ENALL, ioaddr + EDSR);
+	writel(readl(ioaddr + EDMR) | EDMR_SRST, ioaddr + EDMR);
 	while (cnt > 0) {
-		if (!(ctrl_inl(ioaddr + EDMR) & 0x3))
+		if (!(readl(ioaddr + EDMR) & 0x3))
 			break;
 		mdelay(1);
 		cnt--;
@@ -164,14 +164,14 @@ static void sh_eth_reset(struct net_devi
 		printk(KERN_ERR "Device reset fail\n");
 
 	/* Table Init */
-	ctrl_outl(0x0, ioaddr + TDLAR);
-	ctrl_outl(0x0, ioaddr + TDFAR);
-	ctrl_outl(0x0, ioaddr + TDFXR);
-	ctrl_outl(0x0, ioaddr + TDFFR);
-	ctrl_outl(0x0, ioaddr + RDLAR);
-	ctrl_outl(0x0, ioaddr + RDFAR);
-	ctrl_outl(0x0, ioaddr + RDFXR);
-	ctrl_outl(0x0, ioaddr + RDFFR);
+	writel(0x0, ioaddr + TDLAR);
+	writel(0x0, ioaddr + TDFAR);
+	writel(0x0, ioaddr + TDFXR);
+	writel(0x0, ioaddr + TDFFR);
+	writel(0x0, ioaddr + RDLAR);
+	writel(0x0, ioaddr + RDFAR);
+	writel(0x0, ioaddr + RDFXR);
+	writel(0x0, ioaddr + RDFFR);
 }
 
 static void sh_eth_set_duplex(struct net_device *ndev)
@@ -180,9 +180,9 @@ static void sh_eth_set_duplex(struct net
 	u32 ioaddr = ndev->base_addr;
 
 	if (mdp->duplex) /* Full */
-		ctrl_outl(ctrl_inl(ioaddr + ECMR) | ECMR_DM, ioaddr + ECMR);
+		writel(readl(ioaddr + ECMR) | ECMR_DM, ioaddr + ECMR);
 	else		/* Half */
-		ctrl_outl(ctrl_inl(ioaddr + ECMR) & ~ECMR_DM, ioaddr + ECMR);
+		writel(readl(ioaddr + ECMR) & ~ECMR_DM, ioaddr + ECMR);
 }
 
 static void sh_eth_set_rate(struct net_device *ndev)
@@ -192,13 +192,13 @@ static void sh_eth_set_rate(struct net_d
 
 	switch (mdp->speed) {
 	case 10: /* 10BASE */
-		ctrl_outl(GECMR_10, ioaddr + GECMR);
+		writel(GECMR_10, ioaddr + GECMR);
 		break;
 	case 100:/* 100BASE */
-		ctrl_outl(GECMR_100, ioaddr + GECMR);
+		writel(GECMR_100, ioaddr + GECMR);
 		break;
 	case 1000: /* 1000BASE */
-		ctrl_outl(GECMR_1000, ioaddr + GECMR);
+		writel(GECMR_1000, ioaddr + GECMR);
 		break;
 	default:
 		break;
@@ -283,9 +283,9 @@ static void sh_eth_reset(struct net_devi
 {
 	u32 ioaddr = ndev->base_addr;
 
-	ctrl_outl(ctrl_inl(ioaddr + EDMR) | EDMR_SRST, ioaddr + EDMR);
+	writel(readl(ioaddr + EDMR) | EDMR_SRST, ioaddr + EDMR);
 	mdelay(3);
-	ctrl_outl(ctrl_inl(ioaddr + EDMR) & ~EDMR_SRST, ioaddr + EDMR);
+	writel(readl(ioaddr + EDMR) & ~EDMR_SRST, ioaddr + EDMR);
 }
 #endif
 
@@ -336,10 +336,10 @@ static void update_mac_address(struct ne
 {
 	u32 ioaddr = ndev->base_addr;
 
-	ctrl_outl((ndev->dev_addr[0] << 24) | (ndev->dev_addr[1] << 16) |
+	writel((ndev->dev_addr[0] << 24) | (ndev->dev_addr[1] << 16) |
 		  (ndev->dev_addr[2] << 8) | (ndev->dev_addr[3]),
 		  ioaddr + MAHR);
-	ctrl_outl((ndev->dev_addr[4] << 8) | (ndev->dev_addr[5]),
+	writel((ndev->dev_addr[4] << 8) | (ndev->dev_addr[5]),
 		  ioaddr + MALR);
 }
 
@@ -358,12 +358,12 @@ static void read_mac_address(struct net_
 	if (mac[0] || mac[1] || mac[2] || mac[3] || mac[4] || mac[5]) {
 		memcpy(ndev->dev_addr, mac, 6);
 	} else {
-		ndev->dev_addr[0] = (ctrl_inl(ioaddr + MAHR) >> 24);
-		ndev->dev_addr[1] = (ctrl_inl(ioaddr + MAHR) >> 16) & 0xFF;
-		ndev->dev_addr[2] = (ctrl_inl(ioaddr + MAHR) >> 8) & 0xFF;
-		ndev->dev_addr[3] = (ctrl_inl(ioaddr + MAHR) & 0xFF);
-		ndev->dev_addr[4] = (ctrl_inl(ioaddr + MALR) >> 8) & 0xFF;
-		ndev->dev_addr[5] = (ctrl_inl(ioaddr + MALR) & 0xFF);
+		ndev->dev_addr[0] = (readl(ioaddr + MAHR) >> 24);
+		ndev->dev_addr[1] = (readl(ioaddr + MAHR) >> 16) & 0xFF;
+		ndev->dev_addr[2] = (readl(ioaddr + MAHR) >> 8) & 0xFF;
+		ndev->dev_addr[3] = (readl(ioaddr + MAHR) & 0xFF);
+		ndev->dev_addr[4] = (readl(ioaddr + MALR) >> 8) & 0xFF;
+		ndev->dev_addr[5] = (readl(ioaddr + MALR) & 0xFF);
 	}
 }
 
@@ -379,19 +379,19 @@ struct bb_info {
 /* PHY bit set */
 static void bb_set(u32 addr, u32 msk)
 {
-	ctrl_outl(ctrl_inl(addr) | msk, addr);
+	writel(readl(addr) | msk, addr);
 }
 
 /* PHY bit clear */
 static void bb_clr(u32 addr, u32 msk)
 {
-	ctrl_outl((ctrl_inl(addr) & ~msk), addr);
+	writel((readl(addr) & ~msk), addr);
 }
 
 /* PHY bit read */
 static int bb_read(u32 addr, u32 msk)
 {
-	return (ctrl_inl(addr) & msk) != 0;
+	return (readl(addr) & msk) != 0;
 }
 
 /* Data I/O pin control */
@@ -506,9 +506,9 @@ static void sh_eth_ring_format(struct ne
 		rxdesc->buffer_length = ALIGN(mdp->rx_buf_sz, 16);
 		/* Rx descriptor address set */
 		if (i == 0) {
-			ctrl_outl(mdp->rx_desc_dma, ioaddr + RDLAR);
+			writel(mdp->rx_desc_dma, ioaddr + RDLAR);
 #if defined(CONFIG_CPU_SUBTYPE_SH7763)
-			ctrl_outl(mdp->rx_desc_dma, ioaddr + RDFAR);
+			writel(mdp->rx_desc_dma, ioaddr + RDFAR);
 #endif
 		}
 	}
@@ -528,9 +528,9 @@ static void sh_eth_ring_format(struct ne
 		txdesc->buffer_length = 0;
 		if (i == 0) {
 			/* Tx descriptor address set */
-			ctrl_outl(mdp->tx_desc_dma, ioaddr + TDLAR);
+			writel(mdp->tx_desc_dma, ioaddr + TDLAR);
 #if defined(CONFIG_CPU_SUBTYPE_SH7763)
-			ctrl_outl(mdp->tx_desc_dma, ioaddr + TDFAR);
+			writel(mdp->tx_desc_dma, ioaddr + TDFAR);
 #endif
 		}
 	}
@@ -623,71 +623,71 @@ static int sh_eth_dev_init(struct net_de
 	/* Descriptor format */
 	sh_eth_ring_format(ndev);
 	if (mdp->cd->rpadir)
-		ctrl_outl(mdp->cd->rpadir_value, ioaddr + RPADIR);
+		writel(mdp->cd->rpadir_value, ioaddr + RPADIR);
 
 	/* all sh_eth int mask */
-	ctrl_outl(0, ioaddr + EESIPR);
+	writel(0, ioaddr + EESIPR);
 
 #if defined(__LITTLE_ENDIAN__)
 	if (mdp->cd->hw_swap)
-		ctrl_outl(EDMR_EL, ioaddr + EDMR);
+		writel(EDMR_EL, ioaddr + EDMR);
 	else
 #endif
-		ctrl_outl(0, ioaddr + EDMR);
+		writel(0, ioaddr + EDMR);
 
 	/* FIFO size set */
-	ctrl_outl(mdp->cd->fdr_value, ioaddr + FDR);
-	ctrl_outl(0, ioaddr + TFTR);
+	writel(mdp->cd->fdr_value, ioaddr + FDR);
+	writel(0, ioaddr + TFTR);
 
 	/* Frame recv control */
-	ctrl_outl(mdp->cd->rmcr_value, ioaddr + RMCR);
+	writel(mdp->cd->rmcr_value, ioaddr + RMCR);
 
 	rx_int_var = mdp->rx_int_var = DESC_I_RINT8 | DESC_I_RINT5;
 	tx_int_var = mdp->tx_int_var = DESC_I_TINT2;
-	ctrl_outl(rx_int_var | tx_int_var, ioaddr + TRSCER);
+	writel(rx_int_var | tx_int_var, ioaddr + TRSCER);
 
 	if (mdp->cd->bculr)
-		ctrl_outl(0x800, ioaddr + BCULR);	/* Burst sycle set */
+		writel(0x800, ioaddr + BCULR);	/* Burst sycle set */
 
-	ctrl_outl(mdp->cd->fcftr_value, ioaddr + FCFTR);
+	writel(mdp->cd->fcftr_value, ioaddr + FCFTR);
 
 	if (!mdp->cd->no_trimd)
-		ctrl_outl(0, ioaddr + TRIMD);
+		writel(0, ioaddr + TRIMD);
 
 	/* Recv frame limit set register */
-	ctrl_outl(RFLR_VALUE, ioaddr + RFLR);
+	writel(RFLR_VALUE, ioaddr + RFLR);
 
-	ctrl_outl(ctrl_inl(ioaddr + EESR), ioaddr + EESR);
-	ctrl_outl(mdp->cd->eesipr_value, ioaddr + EESIPR);
+	writel(readl(ioaddr + EESR), ioaddr + EESR);
+	writel(mdp->cd->eesipr_value, ioaddr + EESIPR);
 
 	/* PAUSE Prohibition */
-	val = (ctrl_inl(ioaddr + ECMR) & ECMR_DM) |
+	val = (readl(ioaddr + ECMR) & ECMR_DM) |
 		ECMR_ZPF | (mdp->duplex ? ECMR_DM : 0) | ECMR_TE | ECMR_RE;
 
-	ctrl_outl(val, ioaddr + ECMR);
+	writel(val, ioaddr + ECMR);
 
 	if (mdp->cd->set_rate)
 		mdp->cd->set_rate(ndev);
 
 	/* E-MAC Status Register clear */
-	ctrl_outl(mdp->cd->ecsr_value, ioaddr + ECSR);
+	writel(mdp->cd->ecsr_value, ioaddr + ECSR);
 
 	/* E-MAC Interrupt Enable register */
-	ctrl_outl(mdp->cd->ecsipr_value, ioaddr + ECSIPR);
+	writel(mdp->cd->ecsipr_value, ioaddr + ECSIPR);
 
 	/* Set MAC address */
 	update_mac_address(ndev);
 
 	/* mask reset */
 	if (mdp->cd->apr)
-		ctrl_outl(APR_AP, ioaddr + APR);
+		writel(APR_AP, ioaddr + APR);
 	if (mdp->cd->mpr)
-		ctrl_outl(MPR_MP, ioaddr + MPR);
+		writel(MPR_MP, ioaddr + MPR);
 	if (mdp->cd->tpauser)
-		ctrl_outl(TPAUSER_UNLIMITED, ioaddr + TPAUSER);
+		writel(TPAUSER_UNLIMITED, ioaddr + TPAUSER);
 
 	/* Setting the Rx mode will start the Rx process. */
-	ctrl_outl(EDRRR_R, ioaddr + EDRRR);
+	writel(EDRRR_R, ioaddr + EDRRR);
 
 	netif_start_queue(ndev);
 
@@ -811,8 +811,8 @@ static int sh_eth_rx(struct net_device *
 
 	/* Restart Rx engine if stopped. */
 	/* If we don't need to check status, don't. -KDU */
-	if (!(ctrl_inl(ndev->base_addr + EDRRR) & EDRRR_R))
-		ctrl_outl(EDRRR_R, ndev->base_addr + EDRRR);
+	if (!(readl(ndev->base_addr + EDRRR) & EDRRR_R))
+		writel(EDRRR_R, ndev->base_addr + EDRRR);
 
 	return 0;
 }
@@ -827,8 +827,8 @@ static void sh_eth_error(struct net_devi
 	u32 mask;
 
 	if (intr_status & EESR_ECI) {
-		felic_stat = ctrl_inl(ioaddr + ECSR);
-		ctrl_outl(felic_stat, ioaddr + ECSR);	/* clear int */
+		felic_stat = readl(ioaddr + ECSR);
+		writel(felic_stat, ioaddr + ECSR);	/* clear int */
 		if (felic_stat & ECSR_ICD)
 			mdp->stats.tx_carrier_errors++;
 		if (felic_stat & ECSR_LCHNG) {
@@ -839,25 +839,25 @@ static void sh_eth_error(struct net_devi
 				else
 					link_stat = PHY_ST_LINK;
 			} else {
-				link_stat = (ctrl_inl(ioaddr + PSR));
+				link_stat = (readl(ioaddr + PSR));
 				if (mdp->ether_link_active_low)
 					link_stat = ~link_stat;
 			}
 			if (!(link_stat & PHY_ST_LINK)) {
 				/* Link Down : disable tx and rx */
-				ctrl_outl(ctrl_inl(ioaddr + ECMR) &
+				writel(readl(ioaddr + ECMR) &
 					  ~(ECMR_RE | ECMR_TE), ioaddr + ECMR);
 			} else {
 				/* Link Up */
-				ctrl_outl(ctrl_inl(ioaddr + EESIPR) &
+				writel(readl(ioaddr + EESIPR) &
 					  ~DMAC_M_ECI, ioaddr + EESIPR);
 				/*clear int */
-				ctrl_outl(ctrl_inl(ioaddr + ECSR),
+				writel(readl(ioaddr + ECSR),
 					  ioaddr + ECSR);
-				ctrl_outl(ctrl_inl(ioaddr + EESIPR) |
+				writel(readl(ioaddr + EESIPR) |
 					  DMAC_M_ECI, ioaddr + EESIPR);
 				/* enable tx and rx */
-				ctrl_outl(ctrl_inl(ioaddr + ECMR) |
+				writel(readl(ioaddr + ECMR) |
 					  (ECMR_RE | ECMR_TE), ioaddr + ECMR);
 			}
 		}
@@ -888,8 +888,8 @@ static void sh_eth_error(struct net_devi
 		/* Receive Descriptor Empty int */
 		mdp->stats.rx_over_errors++;
 
-		if (ctrl_inl(ioaddr + EDRRR) ^ EDRRR_R)
-			ctrl_outl(EDRRR_R, ioaddr + EDRRR);
+		if (readl(ioaddr + EDRRR) ^ EDRRR_R)
+			writel(EDRRR_R, ioaddr + EDRRR);
 		dev_err(&ndev->dev, "Receive Descriptor Empty\n");
 	}
 	if (intr_status & EESR_RFE) {
@@ -903,7 +903,7 @@ static void sh_eth_error(struct net_devi
 		mask &= ~EESR_ADE;
 	if (intr_status & mask) {
 		/* Tx error */
-		u32 edtrr = ctrl_inl(ndev->base_addr + EDTRR);
+		u32 edtrr = readl(ndev->base_addr + EDTRR);
 		/* dmesg */
 		dev_err(&ndev->dev, "TX error. status=%8.8x cur_tx=%8.8x ",
 				intr_status, mdp->cur_tx);
@@ -915,7 +915,7 @@ static void sh_eth_error(struct net_devi
 		/* SH7712 BUG */
 		if (edtrr ^ EDTRR_TRNS) {
 			/* tx dma start */
-			ctrl_outl(EDTRR_TRNS, ndev->base_addr + EDTRR);
+			writel(EDTRR_TRNS, ndev->base_addr + EDTRR);
 		}
 		/* wakeup */
 		netif_wake_queue(ndev);
@@ -934,12 +934,12 @@ static irqreturn_t sh_eth_interrupt(int
 	spin_lock(&mdp->lock);
 
 	/* Get interrpt stat */
-	intr_status = ctrl_inl(ioaddr + EESR);
+	intr_status = readl(ioaddr + EESR);
 	/* Clear interrupt */
 	if (intr_status & (EESR_FRC | EESR_RMAF | EESR_RRF |
 			EESR_RTLF | EESR_RTSF | EESR_PRE | EESR_CERF |
 			cd->tx_check | cd->eesr_err_check)) {
-		ctrl_outl(intr_status, ioaddr + EESR);
+		writel(intr_status, ioaddr + EESR);
 		ret = IRQ_HANDLED;
 	} else
 		goto other_irq;
@@ -1000,7 +1000,7 @@ static void sh_eth_adjust_link(struct ne
 				mdp->cd->set_rate(ndev);
 		}
 		if (mdp->link == PHY_DOWN) {
-			ctrl_outl((ctrl_inl(ioaddr + ECMR) & ~ECMR_TXF)
+			writel((readl(ioaddr + ECMR) & ~ECMR_TXF)
 					| ECMR_DM, ioaddr + ECMR);
 			new_state = 1;
 			mdp->link = phydev->link;
@@ -1125,7 +1125,7 @@ static void sh_eth_tx_timeout(struct net
 
 	/* worning message out. */
 	printk(KERN_WARNING "%s: transmit timed out, status %8.8x,"
-	       " resetting...\n", ndev->name, (int)ctrl_inl(ioaddr + EESR));
+	       " resetting...\n", ndev->name, (int)readl(ioaddr + EESR));
 
 	/* tx_errors count up */
 	mdp->stats.tx_errors++;
@@ -1196,8 +1196,8 @@ static int sh_eth_start_xmit(struct sk_b
 
 	mdp->cur_tx++;
 
-	if (!(ctrl_inl(ndev->base_addr + EDTRR) & EDTRR_TRNS))
-		ctrl_outl(EDTRR_TRNS, ndev->base_addr + EDTRR);
+	if (!(readl(ndev->base_addr + EDTRR) & EDTRR_TRNS))
+		writel(EDTRR_TRNS, ndev->base_addr + EDTRR);
 
 	return NETDEV_TX_OK;
 }
@@ -1212,11 +1212,11 @@ static int sh_eth_close(struct net_devic
 	netif_stop_queue(ndev);
 
 	/* Disable interrupts by clearing the interrupt mask. */
-	ctrl_outl(0x0000, ioaddr + EESIPR);
+	writel(0x0000, ioaddr + EESIPR);
 
 	/* Stop the chip's Tx and Rx processes. */
-	ctrl_outl(0, ioaddr + EDTRR);
-	ctrl_outl(0, ioaddr + EDRRR);
+	writel(0, ioaddr + EDTRR);
+	writel(0, ioaddr + EDRRR);
 
 	/* PHY Disconnect */
 	if (mdp->phydev) {
@@ -1251,20 +1251,20 @@ static struct net_device_stats *sh_eth_g
 
 	pm_runtime_get_sync(&mdp->pdev->dev);
 
-	mdp->stats.tx_dropped += ctrl_inl(ioaddr + TROCR);
-	ctrl_outl(0, ioaddr + TROCR);	/* (write clear) */
-	mdp->stats.collisions += ctrl_inl(ioaddr + CDCR);
-	ctrl_outl(0, ioaddr + CDCR);	/* (write clear) */
-	mdp->stats.tx_carrier_errors += ctrl_inl(ioaddr + LCCR);
-	ctrl_outl(0, ioaddr + LCCR);	/* (write clear) */
+	mdp->stats.tx_dropped += readl(ioaddr + TROCR);
+	writel(0, ioaddr + TROCR);	/* (write clear) */
+	mdp->stats.collisions += readl(ioaddr + CDCR);
+	writel(0, ioaddr + CDCR);	/* (write clear) */
+	mdp->stats.tx_carrier_errors += readl(ioaddr + LCCR);
+	writel(0, ioaddr + LCCR);	/* (write clear) */
 #if defined(CONFIG_CPU_SUBTYPE_SH7763)
-	mdp->stats.tx_carrier_errors += ctrl_inl(ioaddr + CERCR);/* CERCR */
-	ctrl_outl(0, ioaddr + CERCR);	/* (write clear) */
-	mdp->stats.tx_carrier_errors += ctrl_inl(ioaddr + CEECR);/* CEECR */
-	ctrl_outl(0, ioaddr + CEECR);	/* (write clear) */
+	mdp->stats.tx_carrier_errors += readl(ioaddr + CERCR);/* CERCR */
+	writel(0, ioaddr + CERCR);	/* (write clear) */
+	mdp->stats.tx_carrier_errors += readl(ioaddr + CEECR);/* CEECR */
+	writel(0, ioaddr + CEECR);	/* (write clear) */
 #else
-	mdp->stats.tx_carrier_errors += ctrl_inl(ioaddr + CNDCR);
-	ctrl_outl(0, ioaddr + CNDCR);	/* (write clear) */
+	mdp->stats.tx_carrier_errors += readl(ioaddr + CNDCR);
+	writel(0, ioaddr + CNDCR);	/* (write clear) */
 #endif
 	pm_runtime_put_sync(&mdp->pdev->dev);
 
@@ -1295,11 +1295,11 @@ static void sh_eth_set_multicast_list(st
 
 	if (ndev->flags & IFF_PROMISC) {
 		/* Set promiscuous. */
-		ctrl_outl((ctrl_inl(ioaddr + ECMR) & ~ECMR_MCT) | ECMR_PRM,
+		writel((readl(ioaddr + ECMR) & ~ECMR_MCT) | ECMR_PRM,
 			  ioaddr + ECMR);
 	} else {
 		/* Normal, unicast/broadcast-only mode. */
-		ctrl_outl((ctrl_inl(ioaddr + ECMR) & ~ECMR_PRM) | ECMR_MCT,
+		writel((readl(ioaddr + ECMR) & ~ECMR_PRM) | ECMR_MCT,
 			  ioaddr + ECMR);
 	}
 }
@@ -1307,30 +1307,30 @@ static void sh_eth_set_multicast_list(st
 /* SuperH's TSU register init function */
 static void sh_eth_tsu_init(u32 ioaddr)
 {
-	ctrl_outl(0, ioaddr + TSU_FWEN0);	/* Disable forward(0->1) */
-	ctrl_outl(0, ioaddr + TSU_FWEN1);	/* Disable forward(1->0) */
-	ctrl_outl(0, ioaddr + TSU_FCM);	/* forward fifo 3k-3k */
-	ctrl_outl(0xc, ioaddr + TSU_BSYSL0);
-	ctrl_outl(0xc, ioaddr + TSU_BSYSL1);
-	ctrl_outl(0, ioaddr + TSU_PRISL0);
-	ctrl_outl(0, ioaddr + TSU_PRISL1);
-	ctrl_outl(0, ioaddr + TSU_FWSL0);
-	ctrl_outl(0, ioaddr + TSU_FWSL1);
-	ctrl_outl(TSU_FWSLC_POSTENU | TSU_FWSLC_POSTENL, ioaddr + TSU_FWSLC);
+	writel(0, ioaddr + TSU_FWEN0);	/* Disable forward(0->1) */
+	writel(0, ioaddr + TSU_FWEN1);	/* Disable forward(1->0) */
+	writel(0, ioaddr + TSU_FCM);	/* forward fifo 3k-3k */
+	writel(0xc, ioaddr + TSU_BSYSL0);
+	writel(0xc, ioaddr + TSU_BSYSL1);
+	writel(0, ioaddr + TSU_PRISL0);
+	writel(0, ioaddr + TSU_PRISL1);
+	writel(0, ioaddr + TSU_FWSL0);
+	writel(0, ioaddr + TSU_FWSL1);
+	writel(TSU_FWSLC_POSTENU | TSU_FWSLC_POSTENL, ioaddr + TSU_FWSLC);
 #if defined(CONFIG_CPU_SUBTYPE_SH7763)
-	ctrl_outl(0, ioaddr + TSU_QTAG0);	/* Disable QTAG(0->1) */
-	ctrl_outl(0, ioaddr + TSU_QTAG1);	/* Disable QTAG(1->0) */
+	writel(0, ioaddr + TSU_QTAG0);	/* Disable QTAG(0->1) */
+	writel(0, ioaddr + TSU_QTAG1);	/* Disable QTAG(1->0) */
 #else
-	ctrl_outl(0, ioaddr + TSU_QTAGM0);	/* Disable QTAG(0->1) */
-	ctrl_outl(0, ioaddr + TSU_QTAGM1);	/* Disable QTAG(1->0) */
+	writel(0, ioaddr + TSU_QTAGM0);	/* Disable QTAG(0->1) */
+	writel(0, ioaddr + TSU_QTAGM1);	/* Disable QTAG(1->0) */
 #endif
-	ctrl_outl(0, ioaddr + TSU_FWSR);	/* all interrupt status clear */
-	ctrl_outl(0, ioaddr + TSU_FWINMK);	/* Disable all interrupt */
-	ctrl_outl(0, ioaddr + TSU_TEN);	/* Disable all CAM entry */
-	ctrl_outl(0, ioaddr + TSU_POST1);	/* Disable CAM entry [ 0- 7] */
-	ctrl_outl(0, ioaddr + TSU_POST2);	/* Disable CAM entry [ 8-15] */
-	ctrl_outl(0, ioaddr + TSU_POST3);	/* Disable CAM entry [16-23] */
-	ctrl_outl(0, ioaddr + TSU_POST4);	/* Disable CAM entry [24-31] */
+	writel(0, ioaddr + TSU_FWSR);	/* all interrupt status clear */
+	writel(0, ioaddr + TSU_FWINMK);	/* Disable all interrupt */
+	writel(0, ioaddr + TSU_TEN);	/* Disable all CAM entry */
+	writel(0, ioaddr + TSU_POST1);	/* Disable CAM entry [ 0- 7] */
+	writel(0, ioaddr + TSU_POST2);	/* Disable CAM entry [ 8-15] */
+	writel(0, ioaddr + TSU_POST3);	/* Disable CAM entry [16-23] */
+	writel(0, ioaddr + TSU_POST4);	/* Disable CAM entry [24-31] */
 }
 #endif /* SH_ETH_HAS_TSU */
 
@@ -1552,7 +1552,6 @@ static int sh_eth_drv_remove(struct plat
 
 	sh_mdio_release(ndev);
 	unregister_netdev(ndev);
-	flush_scheduled_work();
 	pm_runtime_disable(&pdev->dev);
 	free_netdev(ndev);
 	platform_set_drvdata(pdev, NULL);
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/sh_eth.h linux-libre-2.6.38-gnu1/drivers/net/sh_eth.h
--- linux-libre-2.6.37-gnu1/drivers/net/sh_eth.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/sh_eth.h	2011-03-14 21:20:32.000000000 -0400
@@ -26,7 +26,6 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/spinlock.h>
-#include <linux/workqueue.h>
 #include <linux/netdevice.h>
 #include <linux/phy.h>
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/sis190.c linux-libre-2.6.38-gnu1/drivers/net/sis190.c
--- linux-libre-2.6.37-gnu1/drivers/net/sis190.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/sis190.c	2011-03-14 21:20:32.000000000 -0400
@@ -1915,9 +1915,10 @@ err_release_board:
 static void __devexit sis190_remove_one(struct pci_dev *pdev)
 {
 	struct net_device *dev = pci_get_drvdata(pdev);
+	struct sis190_private *tp = netdev_priv(dev);
 
 	sis190_mii_remove(dev);
-	flush_scheduled_work();
+	cancel_work_sync(&tp->phy_task);
 	unregister_netdev(dev);
 	sis190_release_board(pdev);
 	pci_set_drvdata(pdev, NULL);
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/sis900.c linux-libre-2.6.38-gnu1/drivers/net/sis900.c
--- linux-libre-2.6.37-gnu1/drivers/net/sis900.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/sis900.c	2011-03-14 21:20:32.000000000 -0400
@@ -36,7 +36,7 @@
    Rev 1.07.06 Nov.  7 2000 Jeff Garzik <jgarzik@pobox.com> some bug fix and cleaning
    Rev 1.07.05 Nov.  6 2000 metapirat<metapirat@gmx.de> contribute media type select by ifconfig
    Rev 1.07.04 Sep.  6 2000 Lei-Chun Chang added ICS1893 PHY support
-   Rev 1.07.03 Aug. 24 2000 Lei-Chun Chang (lcchang@sis.com.tw) modified 630E eqaulizer workaround rule
+   Rev 1.07.03 Aug. 24 2000 Lei-Chun Chang (lcchang@sis.com.tw) modified 630E equalizer workaround rule
    Rev 1.07.01 Aug. 08 2000 Ollie Lho minor update for SiS 630E and SiS 630E A1
    Rev 1.07    Mar. 07 2000 Ollie Lho bug fix in Rx buffer ring
    Rev 1.06.04 Feb. 11 2000 Jeff Garzik <jgarzik@pobox.com> softnet and init for kernel 2.4
@@ -1777,6 +1777,7 @@ static int sis900_rx(struct net_device *
 					      "cur_rx:%4.4d, dirty_rx:%4.4d\n",
 					      net_dev->name, sis_priv->cur_rx,
 					      sis_priv->dirty_rx);
+				dev_kfree_skb(skb);
 				break;
 			}
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/skfp/smt.c linux-libre-2.6.38-gnu1/drivers/net/skfp/smt.c
--- linux-libre-2.6.37-gnu1/drivers/net/skfp/smt.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/skfp/smt.c	2011-03-14 21:20:32.000000000 -0400
@@ -1263,7 +1263,7 @@ void smt_set_timestamp(struct s_smc *smc
 static void smt_fill_policy(struct s_smc *smc, struct smt_p_policy *policy)
 {
 	int	i ;
-	u_char	*map ;
+	const u_char *map ;
 	u_short	in ;
 	u_short	out ;
 
@@ -1271,7 +1271,7 @@ static void smt_fill_policy(struct s_smc
 	 * MIB para 101b (fddiSMTConnectionPolicy) coding
 	 * is different from 0005 coding
 	 */
-	static u_char	ansi_weirdness[16] = {
+	static const u_char ansi_weirdness[16] = {
 		0,7,5,3,8,1,6,4,9,10,2,11,12,13,14,15
 	} ;
 	SMTSETPARA(policy,SMT_P_POLICY) ;
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/skge.c linux-libre-2.6.38-gnu1/drivers/net/skge.c
--- linux-libre-2.6.37-gnu1/drivers/net/skge.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/skge.c	2011-03-14 21:20:32.000000000 -0400
@@ -1191,7 +1191,7 @@ static void genesis_init(struct skge_hw
 
 static void genesis_reset(struct skge_hw *hw, int port)
 {
-	const u8 zero[8]  = { 0 };
+	static const u8 zero[8]  = { 0 };
 	u32 reg;
 
 	skge_write8(hw, SK_REG(port, GMAC_IRQ_MSK), 0);
@@ -1557,7 +1557,7 @@ static void genesis_mac_init(struct skge
 	int jumbo = hw->dev[port]->mtu > ETH_DATA_LEN;
 	int i;
 	u32 r;
-	const u8 zero[6]  = { 0 };
+	static const u8 zero[6]  = { 0 };
 
 	for (i = 0; i < 10; i++) {
 		skge_write16(hw, SK_REG(port, TX_MFF_CTRL1),
@@ -2764,7 +2764,7 @@ static netdev_tx_t skge_xmit_frame(struc
 	td->dma_hi = map >> 32;
 
 	if (skb->ip_summed == CHECKSUM_PARTIAL) {
-		const int offset = skb_transport_offset(skb);
+		const int offset = skb_checksum_start_offset(skb);
 
 		/* This seems backwards, but it is what the sk98lin
 		 * does.  Looks like hardware is wrong?
@@ -3856,9 +3856,6 @@ static struct net_device *skge_devinit(s
 	memcpy_fromio(dev->dev_addr, hw->regs + B2_MAC_1 + port*8, ETH_ALEN);
 	memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
 
-	/* device is off until link detection */
-	netif_carrier_off(dev);
-
 	return dev;
 }
 
@@ -4012,8 +4009,6 @@ static void __devexit skge_remove(struct
 	if (!hw)
 		return;
 
-	flush_scheduled_work();
-
 	dev1 = hw->dev[1];
 	if (dev1)
 		unregister_netdev(dev1);
@@ -4044,53 +4039,40 @@ static void __devexit skge_remove(struct
 }
 
 #ifdef CONFIG_PM
-static int skge_suspend(struct pci_dev *pdev, pm_message_t state)
+static int skge_suspend(struct device *dev)
 {
+	struct pci_dev *pdev = to_pci_dev(dev);
 	struct skge_hw *hw  = pci_get_drvdata(pdev);
-	int i, err, wol = 0;
+	int i;
 
 	if (!hw)
 		return 0;
 
-	err = pci_save_state(pdev);
-	if (err)
-		return err;
-
 	for (i = 0; i < hw->ports; i++) {
 		struct net_device *dev = hw->dev[i];
 		struct skge_port *skge = netdev_priv(dev);
 
 		if (netif_running(dev))
 			skge_down(dev);
+
 		if (skge->wol)
 			skge_wol_init(skge);
-
-		wol |= skge->wol;
 	}
 
 	skge_write32(hw, B0_IMSK, 0);
 
-	pci_prepare_to_sleep(pdev);
-
 	return 0;
 }
 
-static int skge_resume(struct pci_dev *pdev)
+static int skge_resume(struct device *dev)
 {
+	struct pci_dev *pdev = to_pci_dev(dev);
 	struct skge_hw *hw  = pci_get_drvdata(pdev);
 	int i, err;
 
 	if (!hw)
 		return 0;
 
-	err = pci_back_from_sleep(pdev);
-	if (err)
-		goto out;
-
-	err = pci_restore_state(pdev);
-	if (err)
-		goto out;
-
 	err = skge_reset(hw);
 	if (err)
 		goto out;
@@ -4111,12 +4093,19 @@ static int skge_resume(struct pci_dev *p
 out:
 	return err;
 }
+
+static SIMPLE_DEV_PM_OPS(skge_pm_ops, skge_suspend, skge_resume);
+#define SKGE_PM_OPS (&skge_pm_ops)
+
+#else
+
+#define SKGE_PM_OPS NULL
 #endif
 
 static void skge_shutdown(struct pci_dev *pdev)
 {
 	struct skge_hw *hw  = pci_get_drvdata(pdev);
-	int i, wol = 0;
+	int i;
 
 	if (!hw)
 		return;
@@ -4127,15 +4116,10 @@ static void skge_shutdown(struct pci_dev
 
 		if (skge->wol)
 			skge_wol_init(skge);
-		wol |= skge->wol;
 	}
 
-	if (pci_enable_wake(pdev, PCI_D3cold, wol))
-		pci_enable_wake(pdev, PCI_D3hot, wol);
-
-	pci_disable_device(pdev);
+	pci_wake_from_d3(pdev, device_may_wakeup(&pdev->dev));
 	pci_set_power_state(pdev, PCI_D3hot);
-
 }
 
 static struct pci_driver skge_driver = {
@@ -4143,11 +4127,8 @@ static struct pci_driver skge_driver = {
 	.id_table =     skge_id_table,
 	.probe =        skge_probe,
 	.remove =       __devexit_p(skge_remove),
-#ifdef CONFIG_PM
-	.suspend = 	skge_suspend,
-	.resume = 	skge_resume,
-#endif
 	.shutdown =	skge_shutdown,
+	.driver.pm =	SKGE_PM_OPS,
 };
 
 static struct dmi_system_id skge_32bit_dma_boards[] = {
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/sky2.c linux-libre-2.6.38-gnu1/drivers/net/sky2.c
--- linux-libre-2.6.37-gnu1/drivers/net/sky2.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/sky2.c	2011-03-14 21:20:32.000000000 -0400
@@ -46,10 +46,6 @@
 
 #include <asm/irq.h>
 
-#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
-#define SKY2_VLAN_TAG_USED 1
-#endif
-
 #include "sky2.h"
 
 #define DRV_NAME		"sky2"
@@ -1326,39 +1322,34 @@ static int sky2_ioctl(struct net_device
 	return err;
 }
 
-#ifdef SKY2_VLAN_TAG_USED
-static void sky2_set_vlan_mode(struct sky2_hw *hw, u16 port, bool onoff)
-{
-	if (onoff) {
-		sky2_write32(hw, SK_REG(port, RX_GMF_CTRL_T),
-			     RX_VLAN_STRIP_ON);
-		sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T),
-			     TX_VLAN_TAG_ON);
-	} else {
-		sky2_write32(hw, SK_REG(port, RX_GMF_CTRL_T),
-			     RX_VLAN_STRIP_OFF);
-		sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T),
-			     TX_VLAN_TAG_OFF);
-	}
-}
+#define NETIF_F_ALL_VLAN (NETIF_F_HW_VLAN_TX|NETIF_F_HW_VLAN_RX)
 
-static void sky2_vlan_rx_register(struct net_device *dev, struct vlan_group *grp)
+static void sky2_vlan_mode(struct net_device *dev)
 {
 	struct sky2_port *sky2 = netdev_priv(dev);
 	struct sky2_hw *hw = sky2->hw;
 	u16 port = sky2->port;
 
-	netif_tx_lock_bh(dev);
-	napi_disable(&hw->napi);
+	if (dev->features & NETIF_F_HW_VLAN_RX)
+		sky2_write32(hw, SK_REG(port, RX_GMF_CTRL_T),
+			     RX_VLAN_STRIP_ON);
+	else
+		sky2_write32(hw, SK_REG(port, RX_GMF_CTRL_T),
+			     RX_VLAN_STRIP_OFF);
 
-	sky2->vlgrp = grp;
-	sky2_set_vlan_mode(hw, port, grp != NULL);
+	dev->vlan_features = dev->features &~ NETIF_F_ALL_VLAN;
+	if (dev->features & NETIF_F_HW_VLAN_TX)
+		sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T),
+			     TX_VLAN_TAG_ON);
+	else {
+		sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T),
+			     TX_VLAN_TAG_OFF);
 
-	sky2_read32(hw, B0_Y2_SP_LISR);
-	napi_enable(&hw->napi);
-	netif_tx_unlock_bh(dev);
+		/* Can't do transmit offload of vlan without hw vlan */
+		dev->vlan_features &= ~(NETIF_F_TSO | NETIF_F_SG
+					| NETIF_F_ALL_CSUM);
+	}
 }
-#endif
 
 /* Amount of required worst case padding in rx buffer */
 static inline unsigned sky2_rx_pad(const struct sky2_hw *hw)
@@ -1635,9 +1626,7 @@ static void sky2_hw_up(struct sky2_port
 	sky2_prefetch_init(hw, txqaddr[port], sky2->tx_le_map,
 			   sky2->tx_ring_size - 1);
 
-#ifdef SKY2_VLAN_TAG_USED
-	sky2_set_vlan_mode(hw, port, sky2->vlgrp != NULL);
-#endif
+	sky2_vlan_mode(sky2->netdev);
 
 	sky2_rx_start(sky2);
 }
@@ -1780,7 +1769,7 @@ static netdev_tx_t sky2_xmit_frame(struc
 	}
 
 	ctrl = 0;
-#ifdef SKY2_VLAN_TAG_USED
+
 	/* Add VLAN tag, can piggyback on LRGLEN or ADDR64 */
 	if (vlan_tx_tag_present(skb)) {
 		if (!le) {
@@ -1792,7 +1781,6 @@ static netdev_tx_t sky2_xmit_frame(struc
 		le->length = cpu_to_be16(vlan_tx_tag_get(skb));
 		ctrl |= INS_VLAN;
 	}
-#endif
 
 	/* Handle TCP checksum offload */
 	if (skb->ip_summed == CHECKSUM_PARTIAL) {
@@ -1917,8 +1905,10 @@ static void sky2_tx_complete(struct sky2
 			netif_printk(sky2, tx_done, KERN_DEBUG, dev,
 				     "tx done %u\n", idx);
 
-			dev->stats.tx_packets++;
-			dev->stats.tx_bytes += skb->len;
+			u64_stats_update_begin(&sky2->tx_stats.syncp);
+			++sky2->tx_stats.packets;
+			sky2->tx_stats.bytes += skb->len;
+			u64_stats_update_end(&sky2->tx_stats.syncp);
 
 			re->skb = NULL;
 			dev_kfree_skb_any(skb);
@@ -2430,11 +2420,8 @@ static struct sk_buff *sky2_receive(stru
 	struct sk_buff *skb = NULL;
 	u16 count = (status & GMR_FS_LEN) >> 16;
 
-#ifdef SKY2_VLAN_TAG_USED
-	/* Account for vlan tag */
-	if (sky2->vlgrp && (status & GMR_FS_VLAN))
-		count -= VLAN_HLEN;
-#endif
+	if (status & GMR_FS_VLAN)
+		count -= VLAN_HLEN;	/* Account for vlan tag */
 
 	netif_printk(sky2, rx_status, KERN_DEBUG, dev,
 		     "rx slot %u status 0x%x len %d\n",
@@ -2460,7 +2447,7 @@ static struct sk_buff *sky2_receive(stru
 
 	/* if length reported by DMA does not match PHY, packet was truncated */
 	if (length != count)
-		goto len_error;
+		goto error;
 
 okay:
 	if (length < copybreak)
@@ -2475,34 +2462,13 @@ resubmit:
 
 	return skb;
 
-len_error:
-	/* Truncation of overlength packets
-	   causes PHY length to not match MAC length */
-	++dev->stats.rx_length_errors;
-	if (net_ratelimit())
-		netif_info(sky2, rx_err, dev,
-			   "rx length error: status %#x length %d\n",
-			   status, length);
-	goto resubmit;
-
 error:
 	++dev->stats.rx_errors;
-	if (status & GMR_FS_RX_FF_OV) {
-		dev->stats.rx_over_errors++;
-		goto resubmit;
-	}
 
 	if (net_ratelimit())
 		netif_info(sky2, rx_err, dev,
 			   "rx error, status 0x%x length %d\n", status, length);
 
-	if (status & (GMR_FS_LONG_ERR | GMR_FS_UN_SIZE))
-		dev->stats.rx_length_errors++;
-	if (status & GMR_FS_FRAGMENT)
-		dev->stats.rx_frame_errors++;
-	if (status & GMR_FS_CRC_ERR)
-		dev->stats.rx_crc_errors++;
-
 	goto resubmit;
 }
 
@@ -2523,17 +2489,9 @@ static inline void sky2_tx_done(struct n
 static inline void sky2_skb_rx(const struct sky2_port *sky2,
 			       u32 status, struct sk_buff *skb)
 {
-#ifdef SKY2_VLAN_TAG_USED
-	u16 vlan_tag = be16_to_cpu(sky2->rx_tag);
-	if (sky2->vlgrp && (status & GMR_FS_VLAN)) {
-		if (skb->ip_summed == CHECKSUM_NONE)
-			vlan_hwaccel_receive_skb(skb, sky2->vlgrp, vlan_tag);
-		else
-			vlan_gro_receive(&sky2->hw->napi, sky2->vlgrp,
-					 vlan_tag, skb);
-		return;
-	}
-#endif
+	if (status & GMR_FS_VLAN)
+		__vlan_hwaccel_put_tag(skb, be16_to_cpu(sky2->rx_tag));
+
 	if (skb->ip_summed == CHECKSUM_NONE)
 		netif_receive_skb(skb);
 	else
@@ -2543,14 +2501,19 @@ static inline void sky2_skb_rx(const str
 static inline void sky2_rx_done(struct sky2_hw *hw, unsigned port,
 				unsigned packets, unsigned bytes)
 {
-	if (packets) {
-		struct net_device *dev = hw->dev[port];
+	struct net_device *dev = hw->dev[port];
+	struct sky2_port *sky2 = netdev_priv(dev);
 
-		dev->stats.rx_packets += packets;
-		dev->stats.rx_bytes += bytes;
-		dev->last_rx = jiffies;
-		sky2_rx_update(netdev_priv(dev), rxqaddr[port]);
-	}
+	if (packets == 0)
+		return;
+
+	u64_stats_update_begin(&sky2->rx_stats.syncp);
+	sky2->rx_stats.packets += packets;
+	sky2->rx_stats.bytes += bytes;
+	u64_stats_update_end(&sky2->rx_stats.syncp);
+
+	dev->last_rx = jiffies;
+	sky2_rx_update(netdev_priv(dev), rxqaddr[port]);
 }
 
 static void sky2_rx_checksum(struct sky2_port *sky2, u32 status)
@@ -2645,7 +2608,6 @@ static int sky2_status_intr(struct sky2_
 				goto exit_loop;
 			break;
 
-#ifdef SKY2_VLAN_TAG_USED
 		case OP_RXVLAN:
 			sky2->rx_tag = length;
 			break;
@@ -2653,7 +2615,6 @@ static int sky2_status_intr(struct sky2_
 		case OP_RXCHKSVLAN:
 			sky2->rx_tag = length;
 			/* fall through */
-#endif
 		case OP_RXCHKS:
 			if (likely(sky2->flags & SKY2_FLAG_RX_CHECKSUM))
 				sky2_rx_checksum(sky2, status);
@@ -3056,6 +3017,10 @@ static int __devinit sky2_init(struct sk
 			| SKY2_HW_NEW_LE
 			| SKY2_HW_AUTO_TX_SUM
 			| SKY2_HW_ADV_POWER_CTL;
+
+		/* The workaround for status conflicts VLAN tag detection. */
+		if (hw->chip_rev == CHIP_REV_YU_FE2_A0)
+			hw->flags |= SKY2_HW_VLAN_BROKEN;
 		break;
 
 	case CHIP_ID_YUKON_SUPR:
@@ -3398,12 +3363,24 @@ static int sky2_set_wol(struct net_devic
 {
 	struct sky2_port *sky2 = netdev_priv(dev);
 	struct sky2_hw *hw = sky2->hw;
+	bool enable_wakeup = false;
+	int i;
 
 	if ((wol->wolopts & ~sky2_wol_supported(sky2->hw)) ||
 	    !device_can_wakeup(&hw->pdev->dev))
 		return -EOPNOTSUPP;
 
 	sky2->wol = wol->wolopts;
+
+	for (i = 0; i < hw->ports; i++) {
+		struct net_device *dev = hw->dev[i];
+		struct sky2_port *sky2 = netdev_priv(dev);
+
+		if (sky2->wol)
+			enable_wakeup = true;
+	}
+	device_set_wakeup_enable(&hw->pdev->dev, enable_wakeup);
+
 	return 0;
 }
 
@@ -3413,18 +3390,15 @@ static u32 sky2_supported_modes(const st
 		u32 modes = SUPPORTED_10baseT_Half
 			| SUPPORTED_10baseT_Full
 			| SUPPORTED_100baseT_Half
-			| SUPPORTED_100baseT_Full
-			| SUPPORTED_Autoneg | SUPPORTED_TP;
+			| SUPPORTED_100baseT_Full;
 
 		if (hw->flags & SKY2_HW_GIGABIT)
 			modes |= SUPPORTED_1000baseT_Half
 				| SUPPORTED_1000baseT_Full;
 		return modes;
 	} else
-		return  SUPPORTED_1000baseT_Half
-			| SUPPORTED_1000baseT_Full
-			| SUPPORTED_Autoneg
-			| SUPPORTED_FIBRE;
+		return SUPPORTED_1000baseT_Half
+			| SUPPORTED_1000baseT_Full;
 }
 
 static int sky2_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
@@ -3438,9 +3412,11 @@ static int sky2_get_settings(struct net_
 	if (sky2_is_copper(hw)) {
 		ecmd->port = PORT_TP;
 		ecmd->speed = sky2->speed;
+		ecmd->supported |=  SUPPORTED_Autoneg | SUPPORTED_TP;
 	} else {
 		ecmd->speed = SPEED_1000;
 		ecmd->port = PORT_FIBRE;
+		ecmd->supported |=  SUPPORTED_Autoneg | SUPPORTED_FIBRE;
 	}
 
 	ecmd->advertising = sky2->advertising;
@@ -3457,8 +3433,19 @@ static int sky2_set_settings(struct net_
 	u32 supported = sky2_supported_modes(hw);
 
 	if (ecmd->autoneg == AUTONEG_ENABLE) {
+		if (ecmd->advertising & ~supported)
+			return -EINVAL;
+
+		if (sky2_is_copper(hw))
+			sky2->advertising = ecmd->advertising |
+					    ADVERTISED_TP |
+					    ADVERTISED_Autoneg;
+		else
+			sky2->advertising = ecmd->advertising |
+					    ADVERTISED_FIBRE |
+					    ADVERTISED_Autoneg;
+
 		sky2->flags |= SKY2_FLAG_AUTO_SPEED;
-		ecmd->advertising = supported;
 		sky2->duplex = -1;
 		sky2->speed = -1;
 	} else {
@@ -3502,8 +3489,6 @@ static int sky2_set_settings(struct net_
 		sky2->flags &= ~SKY2_FLAG_AUTO_SPEED;
 	}
 
-	sky2->advertising = ecmd->advertising;
-
 	if (netif_running(dev)) {
 		sky2_phy_reinit(sky2);
 		sky2_set_multicast(dev);
@@ -3614,13 +3599,11 @@ static void sky2_phy_stats(struct sky2_p
 	unsigned port = sky2->port;
 	int i;
 
-	data[0] = (u64) gma_read32(hw, port, GM_TXO_OK_HI) << 32
-	    | (u64) gma_read32(hw, port, GM_TXO_OK_LO);
-	data[1] = (u64) gma_read32(hw, port, GM_RXO_OK_HI) << 32
-	    | (u64) gma_read32(hw, port, GM_RXO_OK_LO);
+	data[0] = get_stats64(hw, port, GM_TXO_OK_LO);
+	data[1] = get_stats64(hw, port, GM_RXO_OK_LO);
 
 	for (i = 2; i < count; i++)
-		data[i] = (u64) gma_read32(hw, port, sky2_stats[i].offset);
+		data[i] = get_stats32(hw, port, sky2_stats[i].offset);
 }
 
 static void sky2_set_msglevel(struct net_device *netdev, u32 value)
@@ -3738,6 +3721,51 @@ static void sky2_set_multicast(struct ne
 	gma_write16(hw, port, GM_RX_CTRL, reg);
 }
 
+static struct rtnl_link_stats64 *sky2_get_stats(struct net_device *dev,
+						struct rtnl_link_stats64 *stats)
+{
+	struct sky2_port *sky2 = netdev_priv(dev);
+	struct sky2_hw *hw = sky2->hw;
+	unsigned port = sky2->port;
+	unsigned int start;
+	u64 _bytes, _packets;
+
+	do {
+		start = u64_stats_fetch_begin_bh(&sky2->rx_stats.syncp);
+		_bytes = sky2->rx_stats.bytes;
+		_packets = sky2->rx_stats.packets;
+	} while (u64_stats_fetch_retry_bh(&sky2->rx_stats.syncp, start));
+
+	stats->rx_packets = _packets;
+	stats->rx_bytes = _bytes;
+
+	do {
+		start = u64_stats_fetch_begin_bh(&sky2->tx_stats.syncp);
+		_bytes = sky2->tx_stats.bytes;
+		_packets = sky2->tx_stats.packets;
+	} while (u64_stats_fetch_retry_bh(&sky2->tx_stats.syncp, start));
+
+	stats->tx_packets = _packets;
+	stats->tx_bytes = _bytes;
+
+	stats->multicast = get_stats32(hw, port, GM_RXF_MC_OK)
+		+ get_stats32(hw, port, GM_RXF_BC_OK);
+
+	stats->collisions = get_stats32(hw, port, GM_TXF_COL);
+
+	stats->rx_length_errors = get_stats32(hw, port, GM_RXF_LNG_ERR);
+	stats->rx_crc_errors = get_stats32(hw, port, GM_RXF_FCS_ERR);
+	stats->rx_frame_errors = get_stats32(hw, port, GM_RXF_SHT)
+		+ get_stats32(hw, port, GM_RXE_FRAG);
+	stats->rx_over_errors = get_stats32(hw, port, GM_RXE_FIFO_OV);
+
+	stats->rx_dropped = dev->stats.rx_dropped;
+	stats->rx_fifo_errors = dev->stats.rx_fifo_errors;
+	stats->tx_fifo_errors = dev->stats.tx_fifo_errors;
+
+	return stats;
+}
+
 /* Can have one global because blinking is controlled by
  * ethtool and that is always under RTNL mutex
  */
@@ -4188,15 +4216,28 @@ static int sky2_set_eeprom(struct net_de
 static int sky2_set_flags(struct net_device *dev, u32 data)
 {
 	struct sky2_port *sky2 = netdev_priv(dev);
-	u32 supported =
-		(sky2->hw->flags & SKY2_HW_RSS_BROKEN) ? 0 : ETH_FLAG_RXHASH;
+	unsigned long old_feat = dev->features;
+	u32 supported = 0;
 	int rc;
 
+	if (!(sky2->hw->flags & SKY2_HW_RSS_BROKEN))
+		supported |= ETH_FLAG_RXHASH;
+
+	if (!(sky2->hw->flags & SKY2_HW_VLAN_BROKEN))
+		supported |= ETH_FLAG_RXVLAN | ETH_FLAG_TXVLAN;
+
+	printk(KERN_DEBUG "sky2 set_flags: supported %x data %x\n",
+	       supported, data);
+
 	rc = ethtool_op_set_flags(dev, data, supported);
 	if (rc)
 		return rc;
 
-	rx_set_rss(dev);
+	if ((old_feat ^ dev->features) & NETIF_F_RXHASH)
+		rx_set_rss(dev);
+
+	if ((old_feat ^ dev->features) & NETIF_F_ALL_VLAN)
+		sky2_vlan_mode(dev);
 
 	return 0;
 }
@@ -4232,6 +4273,7 @@ static const struct ethtool_ops sky2_eth
 	.get_sset_count = sky2_get_sset_count,
 	.get_ethtool_stats = sky2_get_ethtool_stats,
 	.set_flags	= sky2_set_flags,
+	.get_flags	= ethtool_op_get_flags,
 };
 
 #ifdef CONFIG_SKY2_DEBUG
@@ -4512,9 +4554,7 @@ static const struct net_device_ops sky2_
 	.ndo_set_multicast_list	= sky2_set_multicast,
 	.ndo_change_mtu		= sky2_change_mtu,
 	.ndo_tx_timeout		= sky2_tx_timeout,
-#ifdef SKY2_VLAN_TAG_USED
-	.ndo_vlan_rx_register	= sky2_vlan_rx_register,
-#endif
+	.ndo_get_stats64	= sky2_get_stats,
 #ifdef CONFIG_NET_POLL_CONTROLLER
 	.ndo_poll_controller	= sky2_netpoll,
 #endif
@@ -4529,9 +4569,7 @@ static const struct net_device_ops sky2_
 	.ndo_set_multicast_list	= sky2_set_multicast,
 	.ndo_change_mtu		= sky2_change_mtu,
 	.ndo_tx_timeout		= sky2_tx_timeout,
-#ifdef SKY2_VLAN_TAG_USED
-	.ndo_vlan_rx_register	= sky2_vlan_rx_register,
-#endif
+	.ndo_get_stats64	= sky2_get_stats,
   },
 };
 
@@ -4582,7 +4620,8 @@ static __devinit struct net_device *sky2
 	sky2->port = port;
 
 	dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG
-		| NETIF_F_TSO  | NETIF_F_GRO;
+		| NETIF_F_TSO | NETIF_F_GRO;
+
 	if (highmem)
 		dev->features |= NETIF_F_HIGHDMA;
 
@@ -4590,13 +4629,8 @@ static __devinit struct net_device *sky2
 	if (!(hw->flags & SKY2_HW_RSS_BROKEN))
 		dev->features |= NETIF_F_RXHASH;
 
-#ifdef SKY2_VLAN_TAG_USED
-	/* The workaround for FE+ status conflicts with VLAN tag detection. */
-	if (!(sky2->hw->chip_id == CHIP_ID_YUKON_FE_P &&
-	      sky2->hw->chip_rev == CHIP_REV_YU_FE2_A0)) {
+	if (!(hw->flags & SKY2_HW_VLAN_BROKEN))
 		dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
-	}
-#endif
 
 	/* read the mac address */
 	memcpy_fromio(dev->dev_addr, hw->regs + B2_MAC_1 + port * 8, ETH_ALEN);
@@ -4920,10 +4954,11 @@ static void __devexit sky2_remove(struct
 	pci_set_drvdata(pdev, NULL);
 }
 
-static int sky2_suspend(struct pci_dev *pdev, pm_message_t state)
+static int sky2_suspend(struct device *dev)
 {
+	struct pci_dev *pdev = to_pci_dev(dev);
 	struct sky2_hw *hw = pci_get_drvdata(pdev);
-	int i, wol = 0;
+	int i;
 
 	if (!hw)
 		return 0;
@@ -4940,41 +4975,24 @@ static int sky2_suspend(struct pci_dev *
 
 		if (sky2->wol)
 			sky2_wol_init(sky2);
-
-		wol |= sky2->wol;
 	}
 
-	device_set_wakeup_enable(&pdev->dev, wol != 0);
-
 	sky2_power_aux(hw);
 	rtnl_unlock();
 
-	pci_save_state(pdev);
-	pci_enable_wake(pdev, pci_choose_state(pdev, state), wol);
-	pci_set_power_state(pdev, pci_choose_state(pdev, state));
-
 	return 0;
 }
 
 #ifdef CONFIG_PM
-static int sky2_resume(struct pci_dev *pdev)
+static int sky2_resume(struct device *dev)
 {
+	struct pci_dev *pdev = to_pci_dev(dev);
 	struct sky2_hw *hw = pci_get_drvdata(pdev);
 	int err;
 
 	if (!hw)
 		return 0;
 
-	err = pci_set_power_state(pdev, PCI_D0);
-	if (err)
-		goto out;
-
-	err = pci_restore_state(pdev);
-	if (err)
-		goto out;
-
-	pci_enable_wake(pdev, PCI_D0, 0);
-
 	/* Re-enable all clocks */
 	err = pci_write_config_dword(pdev, PCI_DEV_REG3, 0);
 	if (err) {
@@ -4994,11 +5012,20 @@ out:
 	pci_disable_device(pdev);
 	return err;
 }
+
+static SIMPLE_DEV_PM_OPS(sky2_pm_ops, sky2_suspend, sky2_resume);
+#define SKY2_PM_OPS (&sky2_pm_ops)
+
+#else
+
+#define SKY2_PM_OPS NULL
 #endif
 
 static void sky2_shutdown(struct pci_dev *pdev)
 {
-	sky2_suspend(pdev, PMSG_SUSPEND);
+	sky2_suspend(&pdev->dev);
+	pci_wake_from_d3(pdev, device_may_wakeup(&pdev->dev));
+	pci_set_power_state(pdev, PCI_D3hot);
 }
 
 static struct pci_driver sky2_driver = {
@@ -5006,11 +5033,8 @@ static struct pci_driver sky2_driver = {
 	.id_table = sky2_id_table,
 	.probe = sky2_probe,
 	.remove = __devexit_p(sky2_remove),
-#ifdef CONFIG_PM
-	.suspend = sky2_suspend,
-	.resume = sky2_resume,
-#endif
 	.shutdown = sky2_shutdown,
+	.driver.pm = SKY2_PM_OPS,
 };
 
 static int __init sky2_init_module(void)
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/sky2.h linux-libre-2.6.38-gnu1/drivers/net/sky2.h
--- linux-libre-2.6.37-gnu1/drivers/net/sky2.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/sky2.h	2011-03-14 21:20:32.000000000 -0400
@@ -2200,6 +2200,12 @@ enum flow_control {
 	FC_BOTH	= 3,
 };
 
+struct sky2_stats {
+	struct u64_stats_sync syncp;
+	u64		packets;
+	u64		bytes;
+};
+
 struct sky2_port {
 	struct sky2_hw	     *hw;
 	struct net_device    *netdev;
@@ -2209,6 +2215,8 @@ struct sky2_port {
 
 	struct tx_ring_info  *tx_ring;
 	struct sky2_tx_le    *tx_le;
+	struct sky2_stats    tx_stats;
+
 	u16		     tx_ring_size;
 	u16		     tx_cons;		/* next le to check */
 	u16		     tx_prod;		/* next le to use */
@@ -2221,17 +2229,15 @@ struct sky2_port {
 
 	struct rx_ring_info  *rx_ring ____cacheline_aligned_in_smp;
 	struct sky2_rx_le    *rx_le;
+	struct sky2_stats    rx_stats;
 
 	u16		     rx_next;		/* next re to check */
 	u16		     rx_put;		/* next le index to use */
 	u16		     rx_pending;
 	u16		     rx_data_size;
 	u16		     rx_nfrags;
-
-#ifdef SKY2_VLAN_TAG_USED
 	u16		     rx_tag;
-	struct vlan_group    *vlgrp;
-#endif
+
 	struct {
 		unsigned long last;
 		u32	mac_rp;
@@ -2275,6 +2281,7 @@ struct sky2_hw {
 #define SKY2_HW_AUTO_TX_SUM	0x00000040	/* new IP decode for Tx */
 #define SKY2_HW_ADV_POWER_CTL	0x00000080	/* additional PHY power regs */
 #define SKY2_HW_RSS_BROKEN	0x00000100
+#define SKY2_HW_VLAN_BROKEN     0x00000200
 
 	u8	     	     chip_id;
 	u8		     chip_rev;
@@ -2346,6 +2353,39 @@ static inline u32 gma_read32(struct sky2
 		| (u32) sky2_read16(hw, base+4) << 16;
 }
 
+static inline u64 gma_read64(struct sky2_hw *hw, unsigned port, unsigned reg)
+{
+	unsigned base = SK_GMAC_REG(port, reg);
+
+	return (u64) sky2_read16(hw, base)
+		| (u64) sky2_read16(hw, base+4) << 16
+		| (u64) sky2_read16(hw, base+8) << 32
+		| (u64) sky2_read16(hw, base+12) << 48;
+}
+
+/* There is no way to atomically read32 bit values from PHY, so retry */
+static inline u32 get_stats32(struct sky2_hw *hw, unsigned port, unsigned reg)
+{
+	u32 val;
+
+	do {
+		val = gma_read32(hw, port, reg);
+	} while (gma_read32(hw, port, reg) != val);
+
+	return val;
+}
+
+static inline u64 get_stats64(struct sky2_hw *hw, unsigned port, unsigned reg)
+{
+	u64 val;
+
+	do {
+		val = gma_read64(hw, port, reg);
+	} while (gma_read64(hw, port, reg) != val);
+
+	return val;
+}
+
 static inline void gma_write16(const struct sky2_hw *hw, unsigned port, int r, u16 v)
 {
 	sky2_write16(hw, SK_GMAC_REG(port,r), v);
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/smc-ultra.c linux-libre-2.6.38-gnu1/drivers/net/smc-ultra.c
--- linux-libre-2.6.37-gnu1/drivers/net/smc-ultra.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/smc-ultra.c	2011-03-14 21:20:32.000000000 -0400
@@ -277,8 +277,12 @@ static int __init ultra_probe1(struct ne
 	dev->base_addr = ioaddr+ULTRA_NIC_OFFSET;
 
 	{
-		int addr_tbl[4] = {0x0C0000, 0x0E0000, 0xFC0000, 0xFE0000};
-		short num_pages_tbl[4] = {0x20, 0x40, 0x80, 0xff};
+		static const int addr_tbl[4] = {
+			0x0C0000, 0x0E0000, 0xFC0000, 0xFE0000
+		};
+		static const short num_pages_tbl[4] = {
+			0x20, 0x40, 0x80, 0xff
+		};
 
 		dev->mem_start = ((addr & 0x0f) << 13) + addr_tbl[(addr >> 6) & 3] ;
 		num_pages = num_pages_tbl[(addr >> 4) & 3];
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/smsc911x.c linux-libre-2.6.38-gnu1/drivers/net/smsc911x.c
--- linux-libre-2.6.37-gnu1/drivers/net/smsc911x.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/smsc911x.c	2011-03-14 21:20:32.000000000 -0400
@@ -1178,6 +1178,11 @@ static int smsc911x_open(struct net_devi
 	smsc911x_reg_write(pdata, HW_CFG, 0x00050000);
 	smsc911x_reg_write(pdata, AFC_CFG, 0x006E3740);
 
+	/* Increase the legal frame size of VLAN tagged frames to 1522 bytes */
+	spin_lock_irq(&pdata->mac_lock);
+	smsc911x_mac_write(pdata, VLAN1, ETH_P_8021Q);
+	spin_unlock_irq(&pdata->mac_lock);
+
 	/* Make sure EEPROM has finished loading before setting GPIO_CFG */
 	timeout = 50;
 	while ((smsc911x_reg_read(pdata, E2P_CMD) & E2P_CMD_EPC_BUSY_) &&
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/Space.c linux-libre-2.6.38-gnu1/drivers/net/Space.c
--- linux-libre-2.6.37-gnu1/drivers/net/Space.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/Space.c	2011-03-14 21:20:32.000000000 -0400
@@ -55,8 +55,6 @@ extern struct net_device *eth16i_probe(i
 extern struct net_device *i82596_probe(int unit);
 extern struct net_device *ewrk3_probe(int unit);
 extern struct net_device *el1_probe(int unit);
-extern struct net_device *wavelan_probe(int unit);
-extern struct net_device *arlan_probe(int unit);
 extern struct net_device *el16_probe(int unit);
 extern struct net_device *elmc_probe(int unit);
 extern struct net_device *elplus_probe(int unit);
@@ -68,7 +66,6 @@ extern struct net_device *ni5010_probe(i
 extern struct net_device *ni52_probe(int unit);
 extern struct net_device *ni65_probe(int unit);
 extern struct net_device *sonic_probe(int unit);
-extern struct net_device *SK_init(int unit);
 extern struct net_device *seeq8005_probe(int unit);
 extern struct net_device *smc_init(int unit);
 extern struct net_device *atarilance_probe(int unit);
@@ -76,8 +73,6 @@ extern struct net_device *sun3lance_prob
 extern struct net_device *sun3_82586_probe(int unit);
 extern struct net_device *apne_probe(int unit);
 extern struct net_device *cs89x0_probe(int unit);
-extern struct net_device *hplance_probe(int unit);
-extern struct net_device *bagetlance_probe(int unit);
 extern struct net_device *mvme147lance_probe(int unit);
 extern struct net_device *tc515_probe(int unit);
 extern struct net_device *lance_probe(int unit);
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/stmmac/stmmac_ethtool.c linux-libre-2.6.38-gnu1/drivers/net/stmmac/stmmac_ethtool.c
--- linux-libre-2.6.37-gnu1/drivers/net/stmmac/stmmac_ethtool.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/stmmac/stmmac_ethtool.c	2011-03-14 21:20:32.000000000 -0400
@@ -94,7 +94,7 @@ static void stmmac_ethtool_getdrvinfo(st
 {
 	struct stmmac_priv *priv = netdev_priv(dev);
 
-	if (!priv->is_gmac)
+	if (!priv->plat->has_gmac)
 		strcpy(info->driver, MAC100_ETHTOOL_NAME);
 	else
 		strcpy(info->driver, GMAC_ETHTOOL_NAME);
@@ -176,7 +176,7 @@ static void stmmac_ethtool_gregs(struct
 
 	memset(reg_space, 0x0, REG_SPACE_SIZE);
 
-	if (!priv->is_gmac) {
+	if (!priv->plat->has_gmac) {
 		/* MAC registers */
 		for (i = 0; i < 12; i++)
 			reg_space[i] = readl(priv->ioaddr + (i * 4));
@@ -197,16 +197,6 @@ static void stmmac_ethtool_gregs(struct
 	}
 }
 
-static int stmmac_ethtool_set_tx_csum(struct net_device *netdev, u32 data)
-{
-	if (data)
-		netdev->features |= NETIF_F_HW_CSUM;
-	else
-		netdev->features &= ~NETIF_F_HW_CSUM;
-
-	return 0;
-}
-
 static u32 stmmac_ethtool_get_rx_csum(struct net_device *dev)
 {
 	struct stmmac_priv *priv = netdev_priv(dev);
@@ -370,7 +360,7 @@ static struct ethtool_ops stmmac_ethtool
 	.get_link = ethtool_op_get_link,
 	.get_rx_csum = stmmac_ethtool_get_rx_csum,
 	.get_tx_csum = ethtool_op_get_tx_csum,
-	.set_tx_csum = stmmac_ethtool_set_tx_csum,
+	.set_tx_csum = ethtool_op_set_tx_ipv6_csum,
 	.get_sg = ethtool_op_get_sg,
 	.set_sg = ethtool_op_set_sg,
 	.get_pauseparam = stmmac_get_pauseparam,
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/stmmac/stmmac.h linux-libre-2.6.38-gnu1/drivers/net/stmmac/stmmac.h
--- linux-libre-2.6.37-gnu1/drivers/net/stmmac/stmmac.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/stmmac/stmmac.h	2011-03-14 21:20:32.000000000 -0400
@@ -20,7 +20,7 @@
   Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
 *******************************************************************************/
 
-#define DRV_MODULE_VERSION	"Apr_2010"
+#define DRV_MODULE_VERSION	"Nov_2010"
 #include <linux/platform_device.h>
 #include <linux/stmmac.h>
 
@@ -37,7 +37,6 @@ struct stmmac_priv {
 	unsigned int cur_tx;
 	unsigned int dirty_tx;
 	unsigned int dma_tx_size;
-	int tx_coe;
 	int tx_coalesce;
 
 	struct dma_desc *dma_rx ;
@@ -48,7 +47,6 @@ struct stmmac_priv {
 	struct sk_buff_head rx_recycle;
 
 	struct net_device *dev;
-	int is_gmac;
 	dma_addr_t dma_rx_phy;
 	unsigned int dma_rx_size;
 	unsigned int dma_buf_sz;
@@ -60,14 +58,11 @@ struct stmmac_priv {
 	struct napi_struct napi;
 
 	phy_interface_t phy_interface;
-	int pbl;
-	int bus_id;
 	int phy_addr;
 	int phy_mask;
 	int (*phy_reset) (void *priv);
-	void (*fix_mac_speed) (void *priv, unsigned int speed);
-	void (*bus_setup)(void __iomem *ioaddr);
-	void *bsp_priv;
+	int rx_coe;
+	int no_csum_insertion;
 
 	int phy_irq;
 	struct phy_device *phydev;
@@ -77,47 +72,20 @@ struct stmmac_priv {
 	unsigned int flow_ctrl;
 	unsigned int pause;
 	struct mii_bus *mii;
-	int mii_clk_csr;
 
 	u32 msg_enable;
 	spinlock_t lock;
 	int wolopts;
 	int wolenabled;
-	int shutdown;
 #ifdef CONFIG_STMMAC_TIMER
 	struct stmmac_timer *tm;
 #endif
 #ifdef STMMAC_VLAN_TAG_USED
 	struct vlan_group *vlgrp;
 #endif
-	int enh_desc;
-	int rx_coe;
-	int bugged_jumbo;
-	int no_csum_insertion;
+	struct plat_stmmacenet_data *plat;
 };
 
-#ifdef CONFIG_STM_DRIVERS
-#include <linux/stm/pad.h>
-static inline int stmmac_claim_resource(struct platform_device *pdev)
-{
-	int ret = 0;
-	struct plat_stmmacenet_data *plat_dat = pdev->dev.platform_data;
-
-	/* Pad routing setup */
-	if (IS_ERR(devm_stm_pad_claim(&pdev->dev, plat_dat->pad_config,
-			dev_name(&pdev->dev)))) {
-		printk(KERN_ERR "%s: Failed to request pads!\n", __func__);
-		ret = -ENODEV;
-	}
-	return ret;
-}
-#else
-static inline int stmmac_claim_resource(struct platform_device *pdev)
-{
-	return 0;
-}
-#endif
-
 extern int stmmac_mdio_unregister(struct net_device *ndev);
 extern int stmmac_mdio_register(struct net_device *ndev);
 extern void stmmac_set_ethtool_ops(struct net_device *netdev);
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/stmmac/stmmac_main.c linux-libre-2.6.38-gnu1/drivers/net/stmmac/stmmac_main.c
--- linux-libre-2.6.37-gnu1/drivers/net/stmmac/stmmac_main.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/stmmac/stmmac_main.c	2011-03-14 21:20:32.000000000 -0400
@@ -186,6 +186,18 @@ static inline u32 stmmac_tx_avail(struct
 	return priv->dirty_tx + priv->dma_tx_size - priv->cur_tx - 1;
 }
 
+/* On some ST platforms, some HW system configuraton registers have to be
+ * set according to the link speed negotiated.
+ */
+static inline void stmmac_hw_fix_mac_speed(struct stmmac_priv *priv)
+{
+	struct phy_device *phydev = priv->phydev;
+
+	if (likely(priv->plat->fix_mac_speed))
+		priv->plat->fix_mac_speed(priv->plat->bsp_priv,
+					  phydev->speed);
+}
+
 /**
  * stmmac_adjust_link
  * @dev: net device structure
@@ -228,15 +240,13 @@ static void stmmac_adjust_link(struct ne
 			new_state = 1;
 			switch (phydev->speed) {
 			case 1000:
-				if (likely(priv->is_gmac))
+				if (likely(priv->plat->has_gmac))
 					ctrl &= ~priv->hw->link.port;
-				if (likely(priv->fix_mac_speed))
-					priv->fix_mac_speed(priv->bsp_priv,
-							    phydev->speed);
+				stmmac_hw_fix_mac_speed(priv);
 				break;
 			case 100:
 			case 10:
-				if (priv->is_gmac) {
+				if (priv->plat->has_gmac) {
 					ctrl |= priv->hw->link.port;
 					if (phydev->speed == SPEED_100) {
 						ctrl |= priv->hw->link.speed;
@@ -246,9 +256,7 @@ static void stmmac_adjust_link(struct ne
 				} else {
 					ctrl &= ~priv->hw->link.port;
 				}
-				if (likely(priv->fix_mac_speed))
-					priv->fix_mac_speed(priv->bsp_priv,
-							    phydev->speed);
+				stmmac_hw_fix_mac_speed(priv);
 				break;
 			default:
 				if (netif_msg_link(priv))
@@ -305,7 +313,7 @@ static int stmmac_init_phy(struct net_de
 		return 0;
 	}
 
-	snprintf(bus_id, MII_BUS_ID_SIZE, "%x", priv->bus_id);
+	snprintf(bus_id, MII_BUS_ID_SIZE, "%x", priv->plat->bus_id);
 	snprintf(phy_id, MII_BUS_ID_SIZE + 3, PHY_ID_FMT, bus_id,
 		 priv->phy_addr);
 	pr_debug("stmmac_init_phy:  trying to attach to %s\n", phy_id);
@@ -552,7 +560,7 @@ static void free_dma_desc_resources(stru
  */
 static void stmmac_dma_operation_mode(struct stmmac_priv *priv)
 {
-	if (likely((priv->tx_coe) && (!priv->no_csum_insertion))) {
+	if (likely((priv->plat->tx_coe) && (!priv->no_csum_insertion))) {
 		/* In case of GMAC, SF mode has to be enabled
 		 * to perform the TX COE. This depends on:
 		 * 1) TX COE if actually supported
@@ -814,7 +822,7 @@ static int stmmac_open(struct net_device
 	init_dma_desc_rings(dev);
 
 	/* DMA initialization and SW reset */
-	if (unlikely(priv->hw->dma->init(priv->ioaddr, priv->pbl,
+	if (unlikely(priv->hw->dma->init(priv->ioaddr, priv->plat->pbl,
 					 priv->dma_tx_phy,
 					 priv->dma_rx_phy) < 0)) {
 
@@ -825,19 +833,17 @@ static int stmmac_open(struct net_device
 	/* Copy the MAC addr into the HW  */
 	priv->hw->mac->set_umac_addr(priv->ioaddr, dev->dev_addr, 0);
 	/* If required, perform hw setup of the bus. */
-	if (priv->bus_setup)
-		priv->bus_setup(priv->ioaddr);
+	if (priv->plat->bus_setup)
+		priv->plat->bus_setup(priv->ioaddr);
 	/* Initialize the MAC Core */
 	priv->hw->mac->core_init(priv->ioaddr);
 
 	priv->rx_coe = priv->hw->mac->rx_coe(priv->ioaddr);
 	if (priv->rx_coe)
 		pr_info("stmmac: Rx Checksum Offload Engine supported\n");
-	if (priv->tx_coe)
+	if (priv->plat->tx_coe)
 		pr_info("\tTX Checksum insertion supported\n");
 
-	priv->shutdown = 0;
-
 	/* Initialise the MMC (if present) to disable all interrupts. */
 	writel(0xffffffff, priv->ioaddr + MMC_HIGH_INTR_MASK);
 	writel(0xffffffff, priv->ioaddr + MMC_LOW_INTR_MASK);
@@ -943,7 +949,7 @@ static int stmmac_sw_tso(struct stmmac_p
 	       skb, skb->len);
 
 	segs = skb_gso_segment(skb, priv->dev->features & ~NETIF_F_TSO);
-	if (unlikely(IS_ERR(segs)))
+	if (IS_ERR(segs))
 		goto sw_tso_end;
 
 	do {
@@ -1042,7 +1048,8 @@ static netdev_tx_t stmmac_xmit(struct sk
 		return stmmac_sw_tso(priv, skb);
 
 	if (likely((skb->ip_summed == CHECKSUM_PARTIAL))) {
-		if (unlikely((!priv->tx_coe) || (priv->no_csum_insertion)))
+		if (unlikely((!priv->plat->tx_coe) ||
+			     (priv->no_csum_insertion)))
 			skb_checksum_help(skb);
 		else
 			csum_insertion = 1;
@@ -1146,7 +1153,7 @@ static inline void stmmac_rx_refill(stru
 					   DMA_FROM_DEVICE);
 
 			(p + entry)->des2 = priv->rx_skbuff_dma[entry];
-			if (unlikely(priv->is_gmac)) {
+			if (unlikely(priv->plat->has_gmac)) {
 				if (bfsize >= BUF_SIZE_8KiB)
 					(p + entry)->des3 =
 					    (p + entry)->des2 + BUF_SIZE_8KiB;
@@ -1356,7 +1363,7 @@ static int stmmac_change_mtu(struct net_
 		return -EBUSY;
 	}
 
-	if (priv->is_gmac)
+	if (priv->plat->has_gmac)
 		max_mtu = JUMBO_LEN;
 	else
 		max_mtu = ETH_DATA_LEN;
@@ -1370,7 +1377,7 @@ static int stmmac_change_mtu(struct net_
 	 * needs to have the Tx COE disabled for oversized frames
 	 * (due to limited buffer sizes). In this case we disable
 	 * the TX csum insertionin the TDES and not use SF. */
-	if ((priv->bugged_jumbo) && (priv->dev->mtu > ETH_DATA_LEN))
+	if ((priv->plat->bugged_jumbo) && (priv->dev->mtu > ETH_DATA_LEN))
 		priv->no_csum_insertion = 1;
 	else
 		priv->no_csum_insertion = 0;
@@ -1390,7 +1397,7 @@ static irqreturn_t stmmac_interrupt(int
 		return IRQ_NONE;
 	}
 
-	if (priv->is_gmac)
+	if (priv->plat->has_gmac)
 		/* To handle GMAC own interrupts */
 		priv->hw->mac->host_irq_status((void __iomem *) dev->base_addr);
 
@@ -1487,7 +1494,8 @@ static int stmmac_probe(struct net_devic
 	dev->netdev_ops = &stmmac_netdev_ops;
 	stmmac_set_ethtool_ops(dev);
 
-	dev->features |= (NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_HIGHDMA);
+	dev->features |= NETIF_F_SG | NETIF_F_HIGHDMA |
+		NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
 	dev->watchdog_timeo = msecs_to_jiffies(watchdog);
 #ifdef STMMAC_VLAN_TAG_USED
 	/* Both mac100 and gmac support receive VLAN tag detection */
@@ -1520,7 +1528,7 @@ static int stmmac_probe(struct net_devic
 
 	DBG(probe, DEBUG, "%s: Scatter/Gather: %s - HW checksums: %s\n",
 	    dev->name, (dev->features & NETIF_F_SG) ? "on" : "off",
-	    (dev->features & NETIF_F_HW_CSUM) ? "on" : "off");
+	    (dev->features & NETIF_F_IP_CSUM) ? "on" : "off");
 
 	return ret;
 }
@@ -1536,7 +1544,7 @@ static int stmmac_mac_device_setup(struc
 
 	struct mac_device_info *device;
 
-	if (priv->is_gmac)
+	if (priv->plat->has_gmac)
 		device = dwmac1000_setup(priv->ioaddr);
 	else
 		device = dwmac100_setup(priv->ioaddr);
@@ -1544,7 +1552,7 @@ static int stmmac_mac_device_setup(struc
 	if (!device)
 		return -ENOMEM;
 
-	if (priv->enh_desc) {
+	if (priv->plat->enh_desc) {
 		device->desc = &enh_desc_ops;
 		pr_info("\tEnhanced descriptor structure\n");
 	} else
@@ -1552,8 +1560,10 @@ static int stmmac_mac_device_setup(struc
 
 	priv->hw = device;
 
-	if (device_can_wakeup(priv->device))
+	if (device_can_wakeup(priv->device)) {
 		priv->wolopts = WAKE_MAGIC; /* Magic Frame as default */
+		enable_irq_wake(dev->irq);
+	}
 
 	return 0;
 }
@@ -1598,7 +1608,7 @@ static int stmmac_associate_phy(struct d
 		plat_dat->bus_id);
 
 	/* Check that this phy is for the MAC being initialised */
-	if (priv->bus_id != plat_dat->bus_id)
+	if (priv->plat->bus_id != plat_dat->bus_id)
 		return 0;
 
 	/* OK, this PHY is connected to the MAC.
@@ -1634,15 +1644,13 @@ static int stmmac_dvr_probe(struct platf
 	struct resource *res;
 	void __iomem *addr = NULL;
 	struct net_device *ndev = NULL;
-	struct stmmac_priv *priv;
+	struct stmmac_priv *priv = NULL;
 	struct plat_stmmacenet_data *plat_dat;
 
 	pr_info("STMMAC driver:\n\tplatform registration... ");
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res) {
-		ret = -ENODEV;
-		goto out;
-	}
+	if (!res)
+		return -ENODEV;
 	pr_info("\tdone!\n");
 
 	if (!request_mem_region(res->start, resource_size(res),
@@ -1650,22 +1658,21 @@ static int stmmac_dvr_probe(struct platf
 		pr_err("%s: ERROR: memory allocation failed"
 		       "cannot get the I/O addr 0x%x\n",
 		       __func__, (unsigned int)res->start);
-		ret = -EBUSY;
-		goto out;
+		return -EBUSY;
 	}
 
 	addr = ioremap(res->start, resource_size(res));
 	if (!addr) {
 		pr_err("%s: ERROR: memory mapping failed\n", __func__);
 		ret = -ENOMEM;
-		goto out;
+		goto out_release_region;
 	}
 
 	ndev = alloc_etherdev(sizeof(struct stmmac_priv));
 	if (!ndev) {
 		pr_err("%s: ERROR: allocating the device\n", __func__);
 		ret = -ENOMEM;
-		goto out;
+		goto out_unmap;
 	}
 
 	SET_NETDEV_DEV(ndev, &pdev->dev);
@@ -1675,21 +1682,17 @@ static int stmmac_dvr_probe(struct platf
 	if (ndev->irq == -ENXIO) {
 		pr_err("%s: ERROR: MAC IRQ configuration "
 		       "information not found\n", __func__);
-		ret = -ENODEV;
-		goto out;
+		ret = -ENXIO;
+		goto out_free_ndev;
 	}
 
 	priv = netdev_priv(ndev);
 	priv->device = &(pdev->dev);
 	priv->dev = ndev;
 	plat_dat = pdev->dev.platform_data;
-	priv->bus_id = plat_dat->bus_id;
-	priv->pbl = plat_dat->pbl;	/* TLI */
-	priv->mii_clk_csr = plat_dat->clk_csr;
-	priv->tx_coe = plat_dat->tx_coe;
-	priv->bugged_jumbo = plat_dat->bugged_jumbo;
-	priv->is_gmac = plat_dat->has_gmac;	/* GMAC is on board */
-	priv->enh_desc = plat_dat->enh_desc;
+
+	priv->plat = plat_dat;
+
 	priv->ioaddr = addr;
 
 	/* PMT module is not integrated in all the MAC devices. */
@@ -1703,20 +1706,22 @@ static int stmmac_dvr_probe(struct platf
 	/* Set the I/O base addr */
 	ndev->base_addr = (unsigned long)addr;
 
-	/* Verify embedded resource for the platform */
-	ret = stmmac_claim_resource(pdev);
-	if (ret < 0)
-		goto out;
+	/* Custom initialisation */
+	if (priv->plat->init) {
+		ret = priv->plat->init(pdev);
+		if (unlikely(ret))
+			goto out_free_ndev;
+	}
 
 	/* MAC HW revice detection */
 	ret = stmmac_mac_device_setup(ndev);
 	if (ret < 0)
-		goto out;
+		goto out_plat_exit;
 
 	/* Network Device Registration */
 	ret = stmmac_probe(ndev);
 	if (ret < 0)
-		goto out;
+		goto out_plat_exit;
 
 	/* associate a PHY - it is provided by another platform bus */
 	if (!driver_for_each_device
@@ -1724,31 +1729,33 @@ static int stmmac_dvr_probe(struct platf
 	     stmmac_associate_phy)) {
 		pr_err("No PHY device is associated with this MAC!\n");
 		ret = -ENODEV;
-		goto out;
+		goto out_unregister;
 	}
 
-	priv->fix_mac_speed = plat_dat->fix_mac_speed;
-	priv->bus_setup = plat_dat->bus_setup;
-	priv->bsp_priv = plat_dat->bsp_priv;
-
 	pr_info("\t%s - (dev. name: %s - id: %d, IRQ #%d\n"
 	       "\tIO base addr: 0x%p)\n", ndev->name, pdev->name,
 	       pdev->id, ndev->irq, addr);
 
 	/* MDIO bus Registration */
-	pr_debug("\tMDIO bus (id: %d)...", priv->bus_id);
+	pr_debug("\tMDIO bus (id: %d)...", priv->plat->bus_id);
 	ret = stmmac_mdio_register(ndev);
 	if (ret < 0)
-		goto out;
+		goto out_unregister;
 	pr_debug("registered!\n");
+	return 0;
 
-out:
-	if (ret < 0) {
-		platform_set_drvdata(pdev, NULL);
-		release_mem_region(res->start, resource_size(res));
-		if (addr != NULL)
-			iounmap(addr);
-	}
+out_unregister:
+	unregister_netdev(ndev);
+out_plat_exit:
+	if (priv->plat->exit)
+		priv->plat->exit(pdev);
+out_free_ndev:
+	free_netdev(ndev);
+	platform_set_drvdata(pdev, NULL);
+out_unmap:
+	iounmap(addr);
+out_release_region:
+	release_mem_region(res->start, resource_size(res));
 
 	return ret;
 }
@@ -1777,6 +1784,9 @@ static int stmmac_dvr_remove(struct plat
 
 	stmmac_mdio_unregister(ndev);
 
+	if (priv->plat->exit)
+		priv->plat->exit(pdev);
+
 	platform_set_drvdata(pdev, NULL);
 	unregister_netdev(ndev);
 
@@ -1790,69 +1800,54 @@ static int stmmac_dvr_remove(struct plat
 }
 
 #ifdef CONFIG_PM
-static int stmmac_suspend(struct platform_device *pdev, pm_message_t state)
+static int stmmac_suspend(struct device *dev)
 {
-	struct net_device *dev = platform_get_drvdata(pdev);
-	struct stmmac_priv *priv = netdev_priv(dev);
+	struct net_device *ndev = dev_get_drvdata(dev);
+	struct stmmac_priv *priv = netdev_priv(ndev);
 	int dis_ic = 0;
 
-	if (!dev || !netif_running(dev))
+	if (!ndev || !netif_running(ndev))
 		return 0;
 
 	spin_lock(&priv->lock);
 
-	if (state.event == PM_EVENT_SUSPEND) {
-		netif_device_detach(dev);
-		netif_stop_queue(dev);
-		if (priv->phydev)
-			phy_stop(priv->phydev);
+	netif_device_detach(ndev);
+	netif_stop_queue(ndev);
+	if (priv->phydev)
+		phy_stop(priv->phydev);
 
 #ifdef CONFIG_STMMAC_TIMER
-		priv->tm->timer_stop();
-		if (likely(priv->tm->enable))
-			dis_ic = 1;
+	priv->tm->timer_stop();
+	if (likely(priv->tm->enable))
+		dis_ic = 1;
 #endif
-		napi_disable(&priv->napi);
+	napi_disable(&priv->napi);
 
-		/* Stop TX/RX DMA */
-		priv->hw->dma->stop_tx(priv->ioaddr);
-		priv->hw->dma->stop_rx(priv->ioaddr);
-		/* Clear the Rx/Tx descriptors */
-		priv->hw->desc->init_rx_desc(priv->dma_rx, priv->dma_rx_size,
-					     dis_ic);
-		priv->hw->desc->init_tx_desc(priv->dma_tx, priv->dma_tx_size);
+	/* Stop TX/RX DMA */
+	priv->hw->dma->stop_tx(priv->ioaddr);
+	priv->hw->dma->stop_rx(priv->ioaddr);
+	/* Clear the Rx/Tx descriptors */
+	priv->hw->desc->init_rx_desc(priv->dma_rx, priv->dma_rx_size,
+				     dis_ic);
+	priv->hw->desc->init_tx_desc(priv->dma_tx, priv->dma_tx_size);
 
-		/* Enable Power down mode by programming the PMT regs */
-		if (device_can_wakeup(priv->device))
-			priv->hw->mac->pmt(priv->ioaddr, priv->wolopts);
-		else
-			stmmac_disable_mac(priv->ioaddr);
-	} else {
-		priv->shutdown = 1;
-		/* Although this can appear slightly redundant it actually
-		 * makes fast the standby operation and guarantees the driver
-		 * working if hibernation is on media. */
-		stmmac_release(dev);
-	}
+	/* Enable Power down mode by programming the PMT regs */
+	if (device_may_wakeup(priv->device))
+		priv->hw->mac->pmt(priv->ioaddr, priv->wolopts);
+	else
+		stmmac_disable_mac(priv->ioaddr);
 
 	spin_unlock(&priv->lock);
 	return 0;
 }
 
-static int stmmac_resume(struct platform_device *pdev)
+static int stmmac_resume(struct device *dev)
 {
-	struct net_device *dev = platform_get_drvdata(pdev);
-	struct stmmac_priv *priv = netdev_priv(dev);
-
-	if (!netif_running(dev))
-		return 0;
+	struct net_device *ndev = dev_get_drvdata(dev);
+	struct stmmac_priv *priv = netdev_priv(ndev);
 
-	if (priv->shutdown) {
-		/* Re-open the interface and re-init the MAC/DMA
-		   and the rings (i.e. on hibernation stage) */
-		stmmac_open(dev);
+	if (!netif_running(ndev))
 		return 0;
-	}
 
 	spin_lock(&priv->lock);
 
@@ -1861,10 +1856,10 @@ static int stmmac_resume(struct platform
 	 * is received. Anyway, it's better to manually clear
 	 * this bit because it can generate problems while resuming
 	 * from another devices (e.g. serial console). */
-	if (device_can_wakeup(priv->device))
+	if (device_may_wakeup(priv->device))
 		priv->hw->mac->pmt(priv->ioaddr, 0);
 
-	netif_device_attach(dev);
+	netif_device_attach(ndev);
 
 	/* Enable the MAC and DMA */
 	stmmac_enable_mac(priv->ioaddr);
@@ -1872,31 +1867,59 @@ static int stmmac_resume(struct platform
 	priv->hw->dma->start_rx(priv->ioaddr);
 
 #ifdef CONFIG_STMMAC_TIMER
-	priv->tm->timer_start(tmrate);
+	if (likely(priv->tm->enable))
+		priv->tm->timer_start(tmrate);
 #endif
 	napi_enable(&priv->napi);
 
 	if (priv->phydev)
 		phy_start(priv->phydev);
 
-	netif_start_queue(dev);
+	netif_start_queue(ndev);
 
 	spin_unlock(&priv->lock);
 	return 0;
 }
-#endif
 
-static struct platform_driver stmmac_driver = {
-	.driver = {
-		   .name = STMMAC_RESOURCE_NAME,
-		   },
-	.probe = stmmac_dvr_probe,
-	.remove = stmmac_dvr_remove,
-#ifdef CONFIG_PM
+static int stmmac_freeze(struct device *dev)
+{
+	struct net_device *ndev = dev_get_drvdata(dev);
+
+	if (!ndev || !netif_running(ndev))
+		return 0;
+
+	return stmmac_release(ndev);
+}
+
+static int stmmac_restore(struct device *dev)
+{
+	struct net_device *ndev = dev_get_drvdata(dev);
+
+	if (!ndev || !netif_running(ndev))
+		return 0;
+
+	return stmmac_open(ndev);
+}
+
+static const struct dev_pm_ops stmmac_pm_ops = {
 	.suspend = stmmac_suspend,
 	.resume = stmmac_resume,
-#endif
+	.freeze = stmmac_freeze,
+	.thaw = stmmac_restore,
+	.restore = stmmac_restore,
+};
+#else
+static const struct dev_pm_ops stmmac_pm_ops;
+#endif /* CONFIG_PM */
 
+static struct platform_driver stmmac_driver = {
+	.probe = stmmac_dvr_probe,
+	.remove = stmmac_dvr_remove,
+	.driver = {
+		.name = STMMAC_RESOURCE_NAME,
+		.owner = THIS_MODULE,
+		.pm = &stmmac_pm_ops,
+	},
 };
 
 /**
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/stmmac/stmmac_mdio.c linux-libre-2.6.38-gnu1/drivers/net/stmmac/stmmac_mdio.c
--- linux-libre-2.6.37-gnu1/drivers/net/stmmac/stmmac_mdio.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/stmmac/stmmac_mdio.c	2011-03-14 21:20:32.000000000 -0400
@@ -53,7 +53,7 @@ static int stmmac_mdio_read(struct mii_b
 	int data;
 	u16 regValue = (((phyaddr << 11) & (0x0000F800)) |
 			((phyreg << 6) & (0x000007C0)));
-	regValue |= MII_BUSY | ((priv->mii_clk_csr & 7) << 2);
+	regValue |= MII_BUSY | ((priv->plat->clk_csr & 7) << 2);
 
 	do {} while (((readl(priv->ioaddr + mii_address)) & MII_BUSY) == 1);
 	writel(regValue, priv->ioaddr + mii_address);
@@ -85,7 +85,7 @@ static int stmmac_mdio_write(struct mii_
 	    (((phyaddr << 11) & (0x0000F800)) | ((phyreg << 6) & (0x000007C0)))
 	    | MII_WRITE;
 
-	value |= MII_BUSY | ((priv->mii_clk_csr & 7) << 2);
+	value |= MII_BUSY | ((priv->plat->clk_csr & 7) << 2);
 
 
 	/* Wait until any existing MII operation is complete */
@@ -114,7 +114,7 @@ static int stmmac_mdio_reset(struct mii_
 
 	if (priv->phy_reset) {
 		pr_debug("stmmac_mdio_reset: calling phy_reset\n");
-		priv->phy_reset(priv->bsp_priv);
+		priv->phy_reset(priv->plat->bsp_priv);
 	}
 
 	/* This is a workaround for problems with the STE101P PHY.
@@ -157,7 +157,7 @@ int stmmac_mdio_register(struct net_devi
 	new_bus->read = &stmmac_mdio_read;
 	new_bus->write = &stmmac_mdio_write;
 	new_bus->reset = &stmmac_mdio_reset;
-	snprintf(new_bus->id, MII_BUS_ID_SIZE, "%x", priv->bus_id);
+	snprintf(new_bus->id, MII_BUS_ID_SIZE, "%x", priv->plat->bus_id);
 	new_bus->priv = ndev;
 	new_bus->irq = irqlist;
 	new_bus->phy_mask = priv->phy_mask;
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/sundance.c linux-libre-2.6.38-gnu1/drivers/net/sundance.c
--- linux-libre-2.6.37-gnu1/drivers/net/sundance.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/sundance.c	2011-03-14 21:20:32.000000000 -0400
@@ -294,6 +294,9 @@ enum alta_offsets {
 	/* Aliased and bogus values! */
 	RxStatus = 0x0c,
 };
+
+#define ASIC_HI_WORD(x)	((x) + 2)
+
 enum ASICCtrl_HiWord_bit {
 	GlobalReset = 0x0001,
 	RxReset = 0x0002,
@@ -431,6 +434,7 @@ static void netdev_error(struct net_devi
 static void netdev_error(struct net_device *dev, int intr_status);
 static void set_rx_mode(struct net_device *dev);
 static int __set_mac_addr(struct net_device *dev);
+static int sundance_set_mac_addr(struct net_device *dev, void *data);
 static struct net_device_stats *get_stats(struct net_device *dev);
 static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
 static int  netdev_close(struct net_device *dev);
@@ -464,7 +468,7 @@ static const struct net_device_ops netde
 	.ndo_do_ioctl 		= netdev_ioctl,
 	.ndo_tx_timeout		= tx_timeout,
 	.ndo_change_mtu		= change_mtu,
-	.ndo_set_mac_address 	= eth_mac_addr,
+	.ndo_set_mac_address 	= sundance_set_mac_addr,
 	.ndo_validate_addr	= eth_validate_addr,
 };
 
@@ -1592,6 +1596,19 @@ static int __set_mac_addr(struct net_dev
 	return 0;
 }
 
+/* Invoked with rtnl_lock held */
+static int sundance_set_mac_addr(struct net_device *dev, void *data)
+{
+	const struct sockaddr *addr = data;
+
+	if (!is_valid_ether_addr(addr->sa_data))
+		return -EINVAL;
+	memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);
+	__set_mac_addr(dev);
+
+	return 0;
+}
+
 static const struct {
 	const char name[ETH_GSTRING_LEN];
 } sundance_stats[] = {
@@ -1772,10 +1789,10 @@ static int netdev_close(struct net_devic
     	}
 
     	iowrite16(GlobalReset | DMAReset | FIFOReset | NetworkReset,
-			ioaddr +ASICCtrl + 2);
+			ioaddr + ASIC_HI_WORD(ASICCtrl));
 
     	for (i = 2000; i > 0; i--) {
- 		if ((ioread16(ioaddr + ASICCtrl +2) & ResetBusy) == 0)
+		if ((ioread16(ioaddr + ASIC_HI_WORD(ASICCtrl)) & ResetBusy) == 0)
 			break;
 		mdelay(1);
     	}
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/sungem.c linux-libre-2.6.38-gnu1/drivers/net/sungem.c
--- linux-libre-2.6.37-gnu1/drivers/net/sungem.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/sungem.c	2011-03-14 21:20:32.000000000 -0400
@@ -1004,7 +1004,7 @@ static netdev_tx_t gem_start_xmit(struct
 
 	ctrl = 0;
 	if (skb->ip_summed == CHECKSUM_PARTIAL) {
-		const u64 csum_start_off = skb_transport_offset(skb);
+		const u64 csum_start_off = skb_checksum_start_offset(skb);
 		const u64 csum_stuff_off = csum_start_off + skb->csum_offset;
 
 		ctrl = (TXDCTRL_CENAB |
@@ -2380,10 +2380,8 @@ static int gem_suspend(struct pci_dev *p
 	 */
 	mutex_unlock(&gp->pm_mutex);
 
-	/* Wait for a pending reset task to complete */
-	while (gp->reset_task_pending)
-		yield();
-	flush_scheduled_work();
+	/* Wait for the pending reset task to complete */
+	flush_work_sync(&gp->reset_task);
 
 	/* Shut the PHY down eventually and setup WOL */
 	gem_stop_phy(gp, gp->asleep_wol);
@@ -2928,10 +2926,8 @@ static void gem_remove_one(struct pci_de
 		/* We shouldn't need any locking here */
 		gem_get_cell(gp);
 
-		/* Wait for a pending reset task to complete */
-		while (gp->reset_task_pending)
-			yield();
-		flush_scheduled_work();
+		/* Cancel reset task */
+		cancel_work_sync(&gp->reset_task);
 
 		/* Shut the PHY down */
 		gem_stop_phy(gp, 0);
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/sunhme.c linux-libre-2.6.38-gnu1/drivers/net/sunhme.c
--- linux-libre-2.6.37-gnu1/drivers/net/sunhme.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/sunhme.c	2011-03-14 21:20:32.000000000 -0400
@@ -2266,7 +2266,7 @@ static netdev_tx_t happy_meal_start_xmit
 
 	tx_flags = TXFLAG_OWN;
 	if (skb->ip_summed == CHECKSUM_PARTIAL) {
-		const u32 csum_start_off = skb_transport_offset(skb);
+		const u32 csum_start_off = skb_checksum_start_offset(skb);
 		const u32 csum_stuff_off = csum_start_off + skb->csum_offset;
 
 		tx_flags = (TXFLAG_OWN | TXFLAG_CSENABLE |
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/sunlance.c linux-libre-2.6.38-gnu1/drivers/net/sunlance.c
--- linux-libre-2.6.37-gnu1/drivers/net/sunlance.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/sunlance.c	2011-03-14 21:20:32.000000000 -0400
@@ -1295,17 +1295,9 @@ static void sparc_lance_get_drvinfo(stru
 	strcpy(info->version, "2.02");
 }
 
-static u32 sparc_lance_get_link(struct net_device *dev)
-{
-	/* We really do not keep track of this, but this
-	 * is better than not reporting anything at all.
-	 */
-	return 1;
-}
-
 static const struct ethtool_ops sparc_lance_ethtool_ops = {
 	.get_drvinfo		= sparc_lance_get_drvinfo,
-	.get_link		= sparc_lance_get_link,
+	.get_link		= ethtool_op_get_link,
 };
 
 static const struct net_device_ops sparc_lance_ops = {
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/tehuti.c linux-libre-2.6.38-gnu1/drivers/net/tehuti.c
--- linux-libre-2.6.37-gnu1/drivers/net/tehuti.c	2013-05-03 03:59:05.000000000 -0400
+++ linux-libre-2.6.38-gnu1/drivers/net/tehuti.c	2013-05-03 01:59:18.000000000 -0400
@@ -12,7 +12,7 @@
 /*
  * RX HW/SW interaction overview
  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- * There are 2 types of RX communication channels betwean driver and NIC.
+ * There are 2 types of RX communication channels between driver and NIC.
  * 1) RX Free Fifo - RXF - holds descriptors of empty buffers to accept incoming
  * traffic. This Fifo is filled by SW and is readen by HW. Each descriptor holds
  * info about buffer's location, size and ID. An ID field is used to identify a
@@ -821,7 +821,7 @@ static void bdx_setmulti(struct net_devi
 		}
 
 		/* use PMF to accept first MAC_MCST_NUM (15) addresses */
-		/* TBD: sort addreses and write them in ascending order
+		/* TBD: sort addresses and write them in ascending order
 		 * into RX_MAC_MCST regs. we skip this phase now and accept ALL
 		 * multicast frames throu IMF */
 		/* accept the rest of addresses throu IMF */
@@ -1346,7 +1346,7 @@ static void print_rxfd(struct rxf_desc *
 /*
  * TX HW/SW interaction overview
  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- * There are 2 types of TX communication channels betwean driver and NIC.
+ * There are 2 types of TX communication channels between driver and NIC.
  * 1) TX Free Fifo - TXF - holds ack descriptors for sent packets
  * 2) TX Data Fifo - TXD - holds descriptors of full buffers.
  *
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/tg3.c linux-libre-2.6.38-gnu1/drivers/net/tg3.c
--- linux-libre-2.6.37-gnu1/drivers/net/tg3.c	2013-05-03 03:59:13.000000000 -0400
+++ linux-libre-2.6.38-gnu1/drivers/net/tg3.c	2013-05-03 01:59:26.000000000 -0400
@@ -25,6 +25,7 @@
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 #include <linux/ethtool.h>
+#include <linux/mdio.h>
 #include <linux/mii.h>
 #include <linux/phy.h>
 #include <linux/brcmphy.h>
@@ -52,20 +53,14 @@
 #define BAR_0	0
 #define BAR_2	2
 
-#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
-#define TG3_VLAN_TAG_USED 1
-#else
-#define TG3_VLAN_TAG_USED 0
-#endif
-
 #include "tg3.h"
 
 #define DRV_MODULE_NAME		"tg3"
 #define TG3_MAJ_NUM			3
-#define TG3_MIN_NUM			115
+#define TG3_MIN_NUM			116
 #define DRV_MODULE_VERSION	\
 	__stringify(TG3_MAJ_NUM) "." __stringify(TG3_MIN_NUM)
-#define DRV_MODULE_RELDATE	"October 14, 2010"
+#define DRV_MODULE_RELDATE	"December 3, 2010"
 
 #define TG3_DEF_MAC_MODE	0
 #define TG3_DEF_RX_MODE		0
@@ -126,9 +121,6 @@
 				 TG3_TX_RING_SIZE)
 #define NEXT_TX(N)		(((N) + 1) & (TG3_TX_RING_SIZE - 1))
 
-#define TG3_RX_DMA_ALIGN		16
-#define TG3_RX_HEADROOM			ALIGN(VLAN_HLEN, TG3_RX_DMA_ALIGN)
-
 #define TG3_DMA_BYTE_ENAB		64
 
 #define TG3_RX_STD_DMA_SZ		1536
@@ -1760,9 +1752,9 @@ static void tg3_phy_eee_adjust(struct tg
 
 	if (tp->link_config.autoneg == AUTONEG_ENABLE &&
 	    current_link_up == 1 &&
-	    (tp->link_config.active_speed == SPEED_1000 ||
-	     (tp->link_config.active_speed == SPEED_100 &&
-	      tp->link_config.active_duplex == DUPLEX_FULL))) {
+	    tp->link_config.active_duplex == DUPLEX_FULL &&
+	    (tp->link_config.active_speed == SPEED_100 ||
+	     tp->link_config.active_speed == SPEED_1000)) {
 		u32 eeectl;
 
 		if (tp->link_config.active_speed == SPEED_1000)
@@ -1772,7 +1764,8 @@ static void tg3_phy_eee_adjust(struct tg
 
 		tw32(TG3_CPMU_EEE_CTRL, eeectl);
 
-		tg3_phy_cl45_read(tp, 0x7, TG3_CL45_D7_EEERES_STAT, &val);
+		tg3_phy_cl45_read(tp, MDIO_MMD_AN,
+				  TG3_CL45_D7_EEERES_STAT, &val);
 
 		if (val == TG3_CL45_D7_EEERES_STAT_LP_1000T ||
 		    val == TG3_CL45_D7_EEERES_STAT_LP_100TX)
@@ -2540,39 +2533,35 @@ static void __tg3_set_mac_addr(struct tg
 	tw32(MAC_TX_BACKOFF_SEED, addr_high);
 }
 
-static int tg3_set_power_state(struct tg3 *tp, pci_power_t state)
+static void tg3_enable_register_access(struct tg3 *tp)
 {
-	u32 misc_host_ctrl;
-	bool device_should_wake, do_low_power;
-
-	/* Make sure register accesses (indirect or otherwise)
-	 * will function correctly.
+	/*
+	 * Make sure register accesses (indirect or otherwise) will function
+	 * correctly.
 	 */
 	pci_write_config_dword(tp->pdev,
-			       TG3PCI_MISC_HOST_CTRL,
-			       tp->misc_host_ctrl);
+			       TG3PCI_MISC_HOST_CTRL, tp->misc_host_ctrl);
+}
 
-	switch (state) {
-	case PCI_D0:
-		pci_enable_wake(tp->pdev, state, false);
-		pci_set_power_state(tp->pdev, PCI_D0);
+static int tg3_power_up(struct tg3 *tp)
+{
+	tg3_enable_register_access(tp);
 
-		/* Switch out of Vaux if it is a NIC */
-		if (tp->tg3_flags2 & TG3_FLG2_IS_NIC)
-			tw32_wait_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl, 100);
+	pci_set_power_state(tp->pdev, PCI_D0);
 
-		return 0;
+	/* Switch out of Vaux if it is a NIC */
+	if (tp->tg3_flags2 & TG3_FLG2_IS_NIC)
+		tw32_wait_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl, 100);
 
-	case PCI_D1:
-	case PCI_D2:
-	case PCI_D3hot:
-		break;
+	return 0;
+}
 
-	default:
-		netdev_err(tp->dev, "Invalid power state (D%d) requested\n",
-			   state);
-		return -EINVAL;
-	}
+static int tg3_power_down_prepare(struct tg3 *tp)
+{
+	u32 misc_host_ctrl;
+	bool device_should_wake, do_low_power;
+
+	tg3_enable_register_access(tp);
 
 	/* Restore the CLKREQ setting. */
 	if (tp->tg3_flags3 & TG3_FLG3_CLKREQ_BUG) {
@@ -2591,8 +2580,7 @@ static int tg3_set_power_state(struct tg
 	tw32(TG3PCI_MISC_HOST_CTRL,
 	     misc_host_ctrl | MISC_HOST_CTRL_MASK_PCI_INT);
 
-	device_should_wake = pci_pme_capable(tp->pdev, state) &&
-			     device_may_wakeup(&tp->pdev->dev) &&
+	device_should_wake = device_may_wakeup(&tp->pdev->dev) &&
 			     (tp->tg3_flags & TG3_FLAG_WOL_ENABLE);
 
 	if (tp->tg3_flags3 & TG3_FLG3_USE_PHYLIB) {
@@ -2719,12 +2707,10 @@ static int tg3_set_power_state(struct tg
 		     (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE)))
 			mac_mode |= MAC_MODE_KEEP_FRAME_IN_WOL;
 
-		if (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE) {
-			mac_mode |= tp->mac_mode &
-				    (MAC_MODE_APE_TX_EN | MAC_MODE_APE_RX_EN);
-			if (mac_mode & MAC_MODE_APE_TX_EN)
-				mac_mode |= MAC_MODE_TDE_ENABLE;
-		}
+		if (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE)
+			mac_mode |= MAC_MODE_APE_TX_EN |
+				    MAC_MODE_APE_RX_EN |
+				    MAC_MODE_TDE_ENABLE;
 
 		tw32_f(MAC_MODE, mac_mode);
 		udelay(100);
@@ -2814,13 +2800,15 @@ static int tg3_set_power_state(struct tg
 
 	tg3_write_sig_post_reset(tp, RESET_KIND_SHUTDOWN);
 
-	if (device_should_wake)
-		pci_enable_wake(tp->pdev, state, true);
+	return 0;
+}
 
-	/* Finally, set the new power state. */
-	pci_set_power_state(tp->pdev, state);
+static void tg3_power_down(struct tg3 *tp)
+{
+	tg3_power_down_prepare(tp);
 
-	return 0;
+	pci_wake_from_d3(tp->pdev, tp->tg3_flags & TG3_FLAG_WOL_ENABLE);
+	pci_set_power_state(tp->pdev, PCI_D3hot);
 }
 
 static void tg3_aux_stat_to_speed_duplex(struct tg3 *tp, u32 val, u16 *speed, u8 *duplex)
@@ -2960,7 +2948,7 @@ static void tg3_phy_copper_begin(struct
 	}
 
 	if (tp->phy_flags & TG3_PHYFLG_EEE_CAP) {
-		u32 val = 0;
+		u32 val;
 
 		tw32(TG3_CPMU_EEE_MODE,
 		     tr32(TG3_CPMU_EEE_MODE) & ~TG3_CPMU_EEEMD_LPI_ENABLE);
@@ -2977,19 +2965,18 @@ static void tg3_phy_copper_begin(struct
 			tg3_phydsp_write(tp, MII_TG3_DSP_CH34TP2,
 					 val | MII_TG3_DSP_CH34TP2_HIBW01);
 
+		val = 0;
 		if (tp->link_config.autoneg == AUTONEG_ENABLE) {
 			/* Advertise 100-BaseTX EEE ability */
 			if (tp->link_config.advertising &
-			    (ADVERTISED_100baseT_Half |
-			     ADVERTISED_100baseT_Full))
-				val |= TG3_CL45_D7_EEEADV_CAP_100TX;
+			    ADVERTISED_100baseT_Full)
+				val |= MDIO_AN_EEE_ADV_100TX;
 			/* Advertise 1000-BaseT EEE ability */
 			if (tp->link_config.advertising &
-			    (ADVERTISED_1000baseT_Half |
-			     ADVERTISED_1000baseT_Full))
-				val |= TG3_CL45_D7_EEEADV_CAP_1000T;
+			    ADVERTISED_1000baseT_Full)
+				val |= MDIO_AN_EEE_ADV_1000T;
 		}
-		tg3_phy_cl45_write(tp, 0x7, TG3_CL45_D7_EEEADV_CAP, val);
+		tg3_phy_cl45_write(tp, MDIO_MMD_AN, MDIO_AN_EEE_ADV, val);
 
 		/* Turn off SM_DSP clock. */
 		val = MII_TG3_AUXCTL_SHDWSEL_AUXCTL |
@@ -4717,8 +4704,6 @@ static int tg3_rx(struct tg3_napi *tnapi
 		struct sk_buff *skb;
 		dma_addr_t dma_addr;
 		u32 opaque_key, desc_idx, *post_ptr;
-		bool hw_vlan __maybe_unused = false;
-		u16 vtag __maybe_unused = 0;
 
 		desc_idx = desc->opaque & RXD_OPAQUE_INDEX_MASK;
 		opaque_key = desc->opaque & RXD_OPAQUE_RING_MASK;
@@ -4777,12 +4762,12 @@ static int tg3_rx(struct tg3_napi *tnapi
 			tg3_recycle_rx(tnapi, tpr, opaque_key,
 				       desc_idx, *post_ptr);
 
-			copy_skb = netdev_alloc_skb(tp->dev, len + VLAN_HLEN +
+			copy_skb = netdev_alloc_skb(tp->dev, len +
 						    TG3_RAW_IP_ALIGN);
 			if (copy_skb == NULL)
 				goto drop_it_no_recycle;
 
-			skb_reserve(copy_skb, TG3_RAW_IP_ALIGN + VLAN_HLEN);
+			skb_reserve(copy_skb, TG3_RAW_IP_ALIGN);
 			skb_put(copy_skb, len);
 			pci_dma_sync_single_for_cpu(tp->pdev, dma_addr, len, PCI_DMA_FROMDEVICE);
 			skb_copy_from_linear_data(skb, copy_skb->data, len);
@@ -4809,30 +4794,11 @@ static int tg3_rx(struct tg3_napi *tnapi
 		}
 
 		if (desc->type_flags & RXD_FLAG_VLAN &&
-		    !(tp->rx_mode & RX_MODE_KEEP_VLAN_TAG)) {
-			vtag = desc->err_vlan & RXD_VLAN_MASK;
-#if TG3_VLAN_TAG_USED
-			if (tp->vlgrp)
-				hw_vlan = true;
-			else
-#endif
-			{
-				struct vlan_ethhdr *ve = (struct vlan_ethhdr *)
-						    __skb_push(skb, VLAN_HLEN);
-
-				memmove(ve, skb->data + VLAN_HLEN,
-					ETH_ALEN * 2);
-				ve->h_vlan_proto = htons(ETH_P_8021Q);
-				ve->h_vlan_TCI = htons(vtag);
-			}
-		}
+		    !(tp->rx_mode & RX_MODE_KEEP_VLAN_TAG))
+			__vlan_hwaccel_put_tag(skb,
+					       desc->err_vlan & RXD_VLAN_MASK);
 
-#if TG3_VLAN_TAG_USED
-		if (hw_vlan)
-			vlan_gro_receive(&tnapi->napi, tp->vlgrp, vtag, skb);
-		else
-#endif
-			napi_gro_receive(&tnapi->napi, skb);
+		napi_gro_receive(&tnapi->napi, skb);
 
 		received++;
 		budget--;
@@ -5735,11 +5701,9 @@ static netdev_tx_t tg3_start_xmit(struct
 		base_flags |= TXD_FLAG_TCPUDP_CSUM;
 	}
 
-#if TG3_VLAN_TAG_USED
 	if (vlan_tx_tag_present(skb))
 		base_flags |= (TXD_FLAG_VLAN |
 			       (vlan_tx_tag_get(skb) << 16));
-#endif
 
 	len = skb_headlen(skb);
 
@@ -5754,7 +5718,7 @@ static netdev_tx_t tg3_start_xmit(struct
 	dma_unmap_addr_set(&tnapi->tx_buffers[entry], mapping, mapping);
 
 	if ((tp->tg3_flags3 & TG3_FLG3_USE_JUMBO_BDFLAG) &&
-	    !mss && skb->len > ETH_DATA_LEN)
+	    !mss && skb->len > VLAN_ETH_FRAME_LEN)
 		base_flags |= TXD_FLAG_JMB_PKT;
 
 	tg3_set_txd(tnapi, entry, mapping, len, base_flags,
@@ -5981,14 +5945,13 @@ static netdev_tx_t tg3_start_xmit_dma_bu
 			}
 		}
 	}
-#if TG3_VLAN_TAG_USED
+
 	if (vlan_tx_tag_present(skb))
 		base_flags |= (TXD_FLAG_VLAN |
 			       (vlan_tx_tag_get(skb) << 16));
-#endif
 
 	if ((tp->tg3_flags3 & TG3_FLG3_USE_JUMBO_BDFLAG) &&
-	    !mss && skb->len > ETH_DATA_LEN)
+	    !mss && skb->len > VLAN_ETH_FRAME_LEN)
 		base_flags |= TXD_FLAG_JMB_PKT;
 
 	len = skb_headlen(skb);
@@ -6330,13 +6293,13 @@ static void tg3_rx_prodring_fini(struct
 	kfree(tpr->rx_jmb_buffers);
 	tpr->rx_jmb_buffers = NULL;
 	if (tpr->rx_std) {
-		pci_free_consistent(tp->pdev, TG3_RX_STD_RING_BYTES(tp),
-				    tpr->rx_std, tpr->rx_std_mapping);
+		dma_free_coherent(&tp->pdev->dev, TG3_RX_STD_RING_BYTES(tp),
+				  tpr->rx_std, tpr->rx_std_mapping);
 		tpr->rx_std = NULL;
 	}
 	if (tpr->rx_jmb) {
-		pci_free_consistent(tp->pdev, TG3_RX_JMB_RING_BYTES(tp),
-				    tpr->rx_jmb, tpr->rx_jmb_mapping);
+		dma_free_coherent(&tp->pdev->dev, TG3_RX_JMB_RING_BYTES(tp),
+				  tpr->rx_jmb, tpr->rx_jmb_mapping);
 		tpr->rx_jmb = NULL;
 	}
 }
@@ -6349,8 +6312,10 @@ static int tg3_rx_prodring_init(struct t
 	if (!tpr->rx_std_buffers)
 		return -ENOMEM;
 
-	tpr->rx_std = pci_alloc_consistent(tp->pdev, TG3_RX_STD_RING_BYTES(tp),
-					   &tpr->rx_std_mapping);
+	tpr->rx_std = dma_alloc_coherent(&tp->pdev->dev,
+					 TG3_RX_STD_RING_BYTES(tp),
+					 &tpr->rx_std_mapping,
+					 GFP_KERNEL);
 	if (!tpr->rx_std)
 		goto err_out;
 
@@ -6361,9 +6326,10 @@ static int tg3_rx_prodring_init(struct t
 		if (!tpr->rx_jmb_buffers)
 			goto err_out;
 
-		tpr->rx_jmb = pci_alloc_consistent(tp->pdev,
-						   TG3_RX_JMB_RING_BYTES(tp),
-						   &tpr->rx_jmb_mapping);
+		tpr->rx_jmb = dma_alloc_coherent(&tp->pdev->dev,
+						 TG3_RX_JMB_RING_BYTES(tp),
+						 &tpr->rx_jmb_mapping,
+						 GFP_KERNEL);
 		if (!tpr->rx_jmb)
 			goto err_out;
 	}
@@ -6482,7 +6448,7 @@ static void tg3_free_consistent(struct t
 		struct tg3_napi *tnapi = &tp->napi[i];
 
 		if (tnapi->tx_ring) {
-			pci_free_consistent(tp->pdev, TG3_TX_RING_BYTES,
+			dma_free_coherent(&tp->pdev->dev, TG3_TX_RING_BYTES,
 				tnapi->tx_ring, tnapi->tx_desc_mapping);
 			tnapi->tx_ring = NULL;
 		}
@@ -6491,25 +6457,26 @@ static void tg3_free_consistent(struct t
 		tnapi->tx_buffers = NULL;
 
 		if (tnapi->rx_rcb) {
-			pci_free_consistent(tp->pdev, TG3_RX_RCB_RING_BYTES(tp),
-					    tnapi->rx_rcb,
-					    tnapi->rx_rcb_mapping);
+			dma_free_coherent(&tp->pdev->dev,
+					  TG3_RX_RCB_RING_BYTES(tp),
+					  tnapi->rx_rcb,
+					  tnapi->rx_rcb_mapping);
 			tnapi->rx_rcb = NULL;
 		}
 
 		tg3_rx_prodring_fini(tp, &tnapi->prodring);
 
 		if (tnapi->hw_status) {
-			pci_free_consistent(tp->pdev, TG3_HW_STATUS_SIZE,
-					    tnapi->hw_status,
-					    tnapi->status_mapping);
+			dma_free_coherent(&tp->pdev->dev, TG3_HW_STATUS_SIZE,
+					  tnapi->hw_status,
+					  tnapi->status_mapping);
 			tnapi->hw_status = NULL;
 		}
 	}
 
 	if (tp->hw_stats) {
-		pci_free_consistent(tp->pdev, sizeof(struct tg3_hw_stats),
-				    tp->hw_stats, tp->stats_mapping);
+		dma_free_coherent(&tp->pdev->dev, sizeof(struct tg3_hw_stats),
+				  tp->hw_stats, tp->stats_mapping);
 		tp->hw_stats = NULL;
 	}
 }
@@ -6522,9 +6489,10 @@ static int tg3_alloc_consistent(struct t
 {
 	int i;
 
-	tp->hw_stats = pci_alloc_consistent(tp->pdev,
-					    sizeof(struct tg3_hw_stats),
-					    &tp->stats_mapping);
+	tp->hw_stats = dma_alloc_coherent(&tp->pdev->dev,
+					  sizeof(struct tg3_hw_stats),
+					  &tp->stats_mapping,
+					  GFP_KERNEL);
 	if (!tp->hw_stats)
 		goto err_out;
 
@@ -6534,9 +6502,10 @@ static int tg3_alloc_consistent(struct t
 		struct tg3_napi *tnapi = &tp->napi[i];
 		struct tg3_hw_status *sblk;
 
-		tnapi->hw_status = pci_alloc_consistent(tp->pdev,
-							TG3_HW_STATUS_SIZE,
-							&tnapi->status_mapping);
+		tnapi->hw_status = dma_alloc_coherent(&tp->pdev->dev,
+						      TG3_HW_STATUS_SIZE,
+						      &tnapi->status_mapping,
+						      GFP_KERNEL);
 		if (!tnapi->hw_status)
 			goto err_out;
 
@@ -6557,9 +6526,10 @@ static int tg3_alloc_consistent(struct t
 			if (!tnapi->tx_buffers)
 				goto err_out;
 
-			tnapi->tx_ring = pci_alloc_consistent(tp->pdev,
-							      TG3_TX_RING_BYTES,
-						       &tnapi->tx_desc_mapping);
+			tnapi->tx_ring = dma_alloc_coherent(&tp->pdev->dev,
+							    TG3_TX_RING_BYTES,
+							&tnapi->tx_desc_mapping,
+							    GFP_KERNEL);
 			if (!tnapi->tx_ring)
 				goto err_out;
 		}
@@ -6592,9 +6562,10 @@ static int tg3_alloc_consistent(struct t
 		if (!i && (tp->tg3_flags3 & TG3_FLG3_ENABLE_RSS))
 			continue;
 
-		tnapi->rx_rcb = pci_alloc_consistent(tp->pdev,
-						     TG3_RX_RCB_RING_BYTES(tp),
-						     &tnapi->rx_rcb_mapping);
+		tnapi->rx_rcb = dma_alloc_coherent(&tp->pdev->dev,
+						   TG3_RX_RCB_RING_BYTES(tp),
+						   &tnapi->rx_rcb_mapping,
+						   GFP_KERNEL);
 		if (!tnapi->rx_rcb)
 			goto err_out;
 
@@ -6978,7 +6949,7 @@ static void tg3_restore_pci_state(struct
 
 	if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5785) {
 		if (tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS)
-			pcie_set_readrq(tp->pdev, 4096);
+			pcie_set_readrq(tp->pdev, tp->pcie_readrq);
 		else {
 			pci_write_config_byte(tp->pdev, PCI_CACHE_LINE_SIZE,
 					      tp->pci_cacheline_sz);
@@ -7172,7 +7143,7 @@ static int tg3_chip_reset(struct tg3 *tp
 				      tp->pcie_cap + PCI_EXP_DEVCTL,
 				      val16);
 
-		pcie_set_readrq(tp->pdev, 4096);
+		pcie_set_readrq(tp->pdev, tp->pcie_readrq);
 
 		/* Clear error status */
 		pci_write_config_word(tp->pdev,
@@ -7213,19 +7184,21 @@ static int tg3_chip_reset(struct tg3 *tp
 		tw32(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl);
 	}
 
+	if (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE)
+		tp->mac_mode = MAC_MODE_APE_TX_EN |
+			       MAC_MODE_APE_RX_EN |
+			       MAC_MODE_TDE_ENABLE;
+
 	if (tp->phy_flags & TG3_PHYFLG_PHY_SERDES) {
-		tp->mac_mode = MAC_MODE_PORT_MODE_TBI;
-		tw32_f(MAC_MODE, tp->mac_mode);
+		tp->mac_mode |= MAC_MODE_PORT_MODE_TBI;
+		val = tp->mac_mode;
 	} else if (tp->phy_flags & TG3_PHYFLG_MII_SERDES) {
-		tp->mac_mode = MAC_MODE_PORT_MODE_GMII;
-		tw32_f(MAC_MODE, tp->mac_mode);
-	} else if (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE) {
-		tp->mac_mode &= (MAC_MODE_APE_TX_EN | MAC_MODE_APE_RX_EN);
-		if (tp->mac_mode & MAC_MODE_APE_TX_EN)
-			tp->mac_mode |= MAC_MODE_TDE_ENABLE;
-		tw32_f(MAC_MODE, tp->mac_mode);
+		tp->mac_mode |= MAC_MODE_PORT_MODE_GMII;
+		val = tp->mac_mode;
 	} else
-		tw32_f(MAC_MODE, 0);
+		val = 0;
+
+	tw32_f(MAC_MODE, val);
 	udelay(40);
 
 	tg3_ape_unlock(tp, TG3_APE_LOCK_GRC);
@@ -7792,6 +7765,37 @@ static int tg3_reset_hw(struct tg3 *tp,
 	if (tp->tg3_flags & TG3_FLAG_INIT_COMPLETE)
 		tg3_abort_hw(tp, 1);
 
+	/* Enable MAC control of LPI */
+	if (tp->phy_flags & TG3_PHYFLG_EEE_CAP) {
+		tw32_f(TG3_CPMU_EEE_LNKIDL_CTRL,
+		       TG3_CPMU_EEE_LNKIDL_PCIE_NL0 |
+		       TG3_CPMU_EEE_LNKIDL_UART_IDL);
+
+		tw32_f(TG3_CPMU_EEE_CTRL,
+		       TG3_CPMU_EEE_CTRL_EXIT_20_1_US);
+
+		val = TG3_CPMU_EEEMD_ERLY_L1_XIT_DET |
+		      TG3_CPMU_EEEMD_LPI_IN_TX |
+		      TG3_CPMU_EEEMD_LPI_IN_RX |
+		      TG3_CPMU_EEEMD_EEE_ENABLE;
+
+		if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5717)
+			val |= TG3_CPMU_EEEMD_SND_IDX_DET_EN;
+
+		if (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE)
+			val |= TG3_CPMU_EEEMD_APE_TX_DET_EN;
+
+		tw32_f(TG3_CPMU_EEE_MODE, val);
+
+		tw32_f(TG3_CPMU_EEE_DBTMR1,
+		       TG3_CPMU_DBTMR1_PCIEXIT_2047US |
+		       TG3_CPMU_DBTMR1_LNKIDLE_2047US);
+
+		tw32_f(TG3_CPMU_EEE_DBTMR2,
+		       TG3_CPMU_DBTMR1_APE_TX_2047US |
+		       TG3_CPMU_DBTMR2_TXIDXEQ_2047US);
+	}
+
 	if (reset_phy)
 		tg3_phy_reset(tp);
 
@@ -7851,18 +7855,21 @@ static int tg3_reset_hw(struct tg3 *tp,
 		tw32(GRC_MODE, grc_mode);
 	}
 
-	if (tp->pci_chip_rev_id == CHIPREV_ID_57765_A0) {
-		u32 grc_mode = tr32(GRC_MODE);
+	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) {
+		if (tp->pci_chip_rev_id == CHIPREV_ID_57765_A0) {
+			u32 grc_mode = tr32(GRC_MODE);
 
-		/* Access the lower 1K of PL PCIE block registers. */
-		val = grc_mode & ~GRC_MODE_PCIE_PORT_MASK;
-		tw32(GRC_MODE, val | GRC_MODE_PCIE_PL_SEL);
+			/* Access the lower 1K of PL PCIE block registers. */
+			val = grc_mode & ~GRC_MODE_PCIE_PORT_MASK;
+			tw32(GRC_MODE, val | GRC_MODE_PCIE_PL_SEL);
 
-		val = tr32(TG3_PCIE_TLDLPL_PORT + TG3_PCIE_PL_LO_PHYCTL5);
-		tw32(TG3_PCIE_TLDLPL_PORT + TG3_PCIE_PL_LO_PHYCTL5,
-		     val | TG3_PCIE_PL_LO_PHYCTL5_DIS_L2CLKREQ);
+			val = tr32(TG3_PCIE_TLDLPL_PORT +
+				   TG3_PCIE_PL_LO_PHYCTL5);
+			tw32(TG3_PCIE_TLDLPL_PORT + TG3_PCIE_PL_LO_PHYCTL5,
+			     val | TG3_PCIE_PL_LO_PHYCTL5_DIS_L2CLKREQ);
 
-		tw32(GRC_MODE, grc_mode);
+			tw32(GRC_MODE, grc_mode);
+		}
 
 		val = tr32(TG3_CPMU_LSPD_10MB_CLK);
 		val &= ~CPMU_LSPD_10MB_MACCLK_MASK;
@@ -7870,22 +7877,6 @@ static int tg3_reset_hw(struct tg3 *tp,
 		tw32(TG3_CPMU_LSPD_10MB_CLK, val);
 	}
 
-	/* Enable MAC control of LPI */
-	if (tp->phy_flags & TG3_PHYFLG_EEE_CAP) {
-		tw32_f(TG3_CPMU_EEE_LNKIDL_CTRL,
-		       TG3_CPMU_EEE_LNKIDL_PCIE_NL0 |
-		       TG3_CPMU_EEE_LNKIDL_UART_IDL);
-
-		tw32_f(TG3_CPMU_EEE_CTRL,
-		       TG3_CPMU_EEE_CTRL_EXIT_20_1_US);
-
-		tw32_f(TG3_CPMU_EEE_MODE,
-		       TG3_CPMU_EEEMD_ERLY_L1_XIT_DET |
-		       TG3_CPMU_EEEMD_LPI_IN_TX |
-		       TG3_CPMU_EEEMD_LPI_IN_RX |
-		       TG3_CPMU_EEEMD_EEE_ENABLE);
-	}
-
 	/* This works around an issue with Athlon chipsets on
 	 * B3 tigon3 silicon.  This bit has no effect on any
 	 * other revision.  But do not set this on PCI Express
@@ -8153,8 +8144,7 @@ static int tg3_reset_hw(struct tg3 *tp,
 		      RDMAC_MODE_FIFOURUN_ENAB | RDMAC_MODE_FIFOOREAD_ENAB |
 		      RDMAC_MODE_LNGREAD_ENAB);
 
-	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 ||
-	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719)
+	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717)
 		rdmac_mode |= RDMAC_MODE_MULT_DMA_RD_DIS;
 
 	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 ||
@@ -8194,6 +8184,10 @@ static int tg3_reset_hw(struct tg3 *tp,
 	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780 ||
 	    (tp->tg3_flags3 & TG3_FLG3_5717_PLUS)) {
 		val = tr32(TG3_RDMA_RSRVCTRL_REG);
+		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719) {
+			val &= ~TG3_RDMA_RSRVCTRL_TXMRGN_MASK;
+			val |= TG3_RDMA_RSRVCTRL_TXMRGN_320B;
+		}
 		tw32(TG3_RDMA_RSRVCTRL_REG,
 		     val | TG3_RDMA_RSRVCTRL_FIFO_OFLW_FIX);
 	}
@@ -8271,7 +8265,7 @@ static int tg3_reset_hw(struct tg3 *tp,
 	}
 
 	if (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE)
-		tp->mac_mode &= MAC_MODE_APE_TX_EN | MAC_MODE_APE_RX_EN;
+		tp->mac_mode = MAC_MODE_APE_TX_EN | MAC_MODE_APE_RX_EN;
 	else
 		tp->mac_mode = 0;
 	tp->mac_mode |= MAC_MODE_TXSTAT_ENABLE | MAC_MODE_RXSTAT_ENABLE |
@@ -9022,8 +9016,14 @@ static bool tg3_enable_msix(struct tg3 *
 		pci_disable_msix(tp->pdev);
 		return false;
 	}
-	if (tp->irq_cnt > 1)
+
+	if (tp->irq_cnt > 1) {
 		tp->tg3_flags3 |= TG3_FLG3_ENABLE_RSS;
+		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719) {
+			tp->tg3_flags3 |= TG3_FLG3_ENABLE_TSS;
+			netif_set_real_num_tx_queues(tp->dev, tp->irq_cnt - 1);
+		}
+	}
 
 	return true;
 }
@@ -9092,7 +9092,7 @@ static int tg3_open(struct net_device *d
 
 	netif_carrier_off(tp->dev);
 
-	err = tg3_set_power_state(tp, PCI_D0);
+	err = tg3_power_up(tp);
 	if (err)
 		return err;
 
@@ -9257,7 +9257,7 @@ static int tg3_close(struct net_device *
 
 	tg3_free_consistent(tp);
 
-	tg3_set_power_state(tp, PCI_D3hot);
+	tg3_power_down(tp);
 
 	netif_carrier_off(tp->dev);
 
@@ -9490,17 +9490,10 @@ static void __tg3_set_rx_mode(struct net
 	rx_mode = tp->rx_mode & ~(RX_MODE_PROMISC |
 				  RX_MODE_KEEP_VLAN_TAG);
 
+#if !defined(CONFIG_VLAN_8021Q) && !defined(CONFIG_VLAN_8021Q_MODULE)
 	/* When ASF is in use, we always keep the RX_MODE_KEEP_VLAN_TAG
 	 * flag clear.
 	 */
-#if TG3_VLAN_TAG_USED
-	if (!tp->vlgrp &&
-	    !(tp->tg3_flags & TG3_FLAG_ENABLE_ASF))
-		rx_mode |= RX_MODE_KEEP_VLAN_TAG;
-#else
-	/* By definition, VLAN is disabled always in this
-	 * case.
-	 */
 	if (!(tp->tg3_flags & TG3_FLAG_ENABLE_ASF))
 		rx_mode |= RX_MODE_KEEP_VLAN_TAG;
 #endif
@@ -11059,7 +11052,7 @@ static void tg3_self_test(struct net_dev
 	struct tg3 *tp = netdev_priv(dev);
 
 	if (tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER)
-		tg3_set_power_state(tp, PCI_D0);
+		tg3_power_up(tp);
 
 	memset(data, 0, sizeof(u64) * TG3_NUM_TEST);
 
@@ -11127,7 +11120,7 @@ static void tg3_self_test(struct net_dev
 			tg3_phy_start(tp);
 	}
 	if (tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER)
-		tg3_set_power_state(tp, PCI_D3hot);
+		tg3_power_down(tp);
 
 }
 
@@ -11156,7 +11149,9 @@ static int tg3_ioctl(struct net_device *
 		if (tp->phy_flags & TG3_PHYFLG_PHY_SERDES)
 			break;			/* We have no PHY */
 
-		if (tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER)
+		if ((tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER) ||
+		    ((tp->tg3_flags & TG3_FLAG_ENABLE_ASF) &&
+		     !netif_running(dev)))
 			return -EAGAIN;
 
 		spin_lock_bh(&tp->lock);
@@ -11172,7 +11167,9 @@ static int tg3_ioctl(struct net_device *
 		if (tp->phy_flags & TG3_PHYFLG_PHY_SERDES)
 			break;			/* We have no PHY */
 
-		if (tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER)
+		if ((tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER) ||
+		    ((tp->tg3_flags & TG3_FLAG_ENABLE_ASF) &&
+		     !netif_running(dev)))
 			return -EAGAIN;
 
 		spin_lock_bh(&tp->lock);
@@ -11188,31 +11185,6 @@ static int tg3_ioctl(struct net_device *
 	return -EOPNOTSUPP;
 }
 
-#if TG3_VLAN_TAG_USED
-static void tg3_vlan_rx_register(struct net_device *dev, struct vlan_group *grp)
-{
-	struct tg3 *tp = netdev_priv(dev);
-
-	if (!netif_running(dev)) {
-		tp->vlgrp = grp;
-		return;
-	}
-
-	tg3_netif_stop(tp);
-
-	tg3_full_lock(tp, 0);
-
-	tp->vlgrp = grp;
-
-	/* Update RX_MODE_KEEP_VLAN_TAG bit in RX_MODE register. */
-	__tg3_set_rx_mode(dev);
-
-	tg3_netif_start(tp);
-
-	tg3_full_unlock(tp);
-}
-#endif
-
 static int tg3_get_coalesce(struct net_device *dev, struct ethtool_coalesce *ec)
 {
 	struct tg3 *tp = netdev_priv(dev);
@@ -12402,8 +12374,9 @@ static void __devinit tg3_get_eeprom_hw_
 		if (cfg2 & (1 << 18))
 			tp->phy_flags |= TG3_PHYFLG_SERDES_PREEMPHASIS;
 
-		if (((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 &&
-		      GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5784_AX)) &&
+		if (((tp->tg3_flags3 & TG3_FLG3_5717_PLUS) ||
+		    ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 &&
+		      GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5784_AX))) &&
 		    (cfg2 & NIC_SRAM_DATA_CFG_2_APD_EN))
 			tp->phy_flags |= TG3_PHYFLG_ENABLE_APD;
 
@@ -12539,9 +12512,11 @@ static int __devinit tg3_phy_probe(struc
 		}
 	}
 
-	if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_5718 ||
-	    (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765 &&
-	     tp->pci_chip_rev_id != CHIPREV_ID_57765_A0))
+	if (!(tp->phy_flags & TG3_PHYFLG_ANY_SERDES) &&
+	    ((tp->pdev->device == TG3PCI_DEVICE_TIGON3_5718 &&
+	      tp->pci_chip_rev_id != CHIPREV_ID_5717_A0) ||
+	     (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765 &&
+	      tp->pci_chip_rev_id != CHIPREV_ID_57765_A0)))
 		tp->phy_flags |= TG3_PHYFLG_EEE_CAP;
 
 	if (!(tp->phy_flags & TG3_PHYFLG_ANY_SERDES) &&
@@ -13021,9 +12996,7 @@ static struct pci_dev * __devinit tg3_fi
 
 static void inline vlan_features_add(struct net_device *dev, unsigned long flags)
 {
-#if TG3_VLAN_TAG_USED
 	dev->vlan_features |= flags;
-#endif
 }
 
 static inline u32 tg3_rx_ret_ring_size(struct tg3 *tp)
@@ -13038,17 +13011,15 @@ static inline u32 tg3_rx_ret_ring_size(s
 		return 512;
 }
 
+DEFINE_PCI_DEVICE_TABLE(write_reorder_chipsets) = {
+	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_FE_GATE_700C) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_BRIDGE) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8385_0) },
+	{ },
+};
+
 static int __devinit tg3_get_invariants(struct tg3 *tp)
 {
-	static struct pci_device_id write_reorder_chipsets[] = {
-		{ PCI_DEVICE(PCI_VENDOR_ID_AMD,
-			     PCI_DEVICE_ID_AMD_FE_GATE_700C) },
-		{ PCI_DEVICE(PCI_VENDOR_ID_AMD,
-			     PCI_DEVICE_ID_AMD_8131_BRIDGE) },
-		{ PCI_DEVICE(PCI_VENDOR_ID_VIA,
-			     PCI_DEVICE_ID_VIA_8385_0) },
-		{ },
-	};
 	u32 misc_ctrl_reg;
 	u32 pci_state_reg, grc_misc_cfg;
 	u32 val;
@@ -13350,7 +13321,45 @@ static int __devinit tg3_get_invariants(
 
 		tp->tg3_flags2 |= TG3_FLG2_PCI_EXPRESS;
 
-		pcie_set_readrq(tp->pdev, 4096);
+		tp->pcie_readrq = 4096;
+		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719) {
+			u16 word;
+
+			pci_read_config_word(tp->pdev,
+					     tp->pcie_cap + PCI_EXP_LNKSTA,
+					     &word);
+			switch (word & PCI_EXP_LNKSTA_CLS) {
+			case PCI_EXP_LNKSTA_CLS_2_5GB:
+				word &= PCI_EXP_LNKSTA_NLW;
+				word >>= PCI_EXP_LNKSTA_NLW_SHIFT;
+				switch (word) {
+				case 2:
+					tp->pcie_readrq = 2048;
+					break;
+				case 4:
+					tp->pcie_readrq = 1024;
+					break;
+				}
+				break;
+
+			case PCI_EXP_LNKSTA_CLS_5_0GB:
+				word &= PCI_EXP_LNKSTA_NLW;
+				word >>= PCI_EXP_LNKSTA_NLW_SHIFT;
+				switch (word) {
+				case 1:
+					tp->pcie_readrq = 2048;
+					break;
+				case 2:
+					tp->pcie_readrq = 1024;
+					break;
+				case 4:
+					tp->pcie_readrq = 512;
+					break;
+				}
+			}
+		}
+
+		pcie_set_readrq(tp->pdev, tp->pcie_readrq);
 
 		pci_read_config_word(tp->pdev,
 				     tp->pcie_cap + PCI_EXP_LNKCTL,
@@ -13537,7 +13546,7 @@ static int __devinit tg3_get_invariants(
 	    (tp->tg3_flags3 & TG3_FLG3_5717_PLUS))
 		tp->tg3_flags |= TG3_FLAG_CPMU_PRESENT;
 
-	/* Set up tp->grc_local_ctrl before calling tg3_set_power_state().
+	/* Set up tp->grc_local_ctrl before calling tg_power_up().
 	 * GPIO1 driven high will bring 5700's external PHY out of reset.
 	 * It is also used as eeprom write protect on LOMs.
 	 */
@@ -13568,7 +13577,7 @@ static int __devinit tg3_get_invariants(
 	}
 
 	/* Force the chip into D0. */
-	err = tg3_set_power_state(tp, PCI_D0);
+	err = tg3_power_up(tp);
 	if (err) {
 		dev_err(&tp->pdev->dev, "Transition to D0 failed\n");
 		return err;
@@ -13713,8 +13722,7 @@ static int __devinit tg3_get_invariants(
 
 	/* Preserve the APE MAC_MODE bits */
 	if (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE)
-		tp->mac_mode = tr32(MAC_MODE) |
-			       MAC_MODE_APE_TX_EN | MAC_MODE_APE_RX_EN;
+		tp->mac_mode = MAC_MODE_APE_TX_EN | MAC_MODE_APE_RX_EN;
 	else
 		tp->mac_mode = TG3_DEF_MAC_MODE;
 
@@ -13781,11 +13789,11 @@ static int __devinit tg3_get_invariants(
 	else
 		tp->tg3_flags &= ~TG3_FLAG_POLL_SERDES;
 
-	tp->rx_offset = NET_IP_ALIGN + TG3_RX_HEADROOM;
+	tp->rx_offset = NET_IP_ALIGN;
 	tp->rx_copy_thresh = TG3_RX_COPY_THRESHOLD;
 	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701 &&
 	    (tp->tg3_flags & TG3_FLAG_PCIX_MODE) != 0) {
-		tp->rx_offset -= NET_IP_ALIGN;
+		tp->rx_offset = 0;
 #ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
 		tp->rx_copy_thresh = ~(u16)0;
 #endif
@@ -14144,13 +14152,19 @@ static int __devinit tg3_do_test_dma(str
 
 #define TEST_BUFFER_SIZE	0x2000
 
+DEFINE_PCI_DEVICE_TABLE(dma_wait_state_chipsets) = {
+	{ PCI_DEVICE(PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_UNI_N_PCI15) },
+	{ },
+};
+
 static int __devinit tg3_test_dma(struct tg3 *tp)
 {
 	dma_addr_t buf_dma;
 	u32 *buf, saved_dma_rwctrl;
 	int ret = 0;
 
-	buf = pci_alloc_consistent(tp->pdev, TEST_BUFFER_SIZE, &buf_dma);
+	buf = dma_alloc_coherent(&tp->pdev->dev, TEST_BUFFER_SIZE,
+				 &buf_dma, GFP_KERNEL);
 	if (!buf) {
 		ret = -ENOMEM;
 		goto out_nofree;
@@ -14312,11 +14326,6 @@ static int __devinit tg3_test_dma(struct
 	}
 	if ((tp->dma_rwctrl & DMA_RWCTRL_WRITE_BNDRY_MASK) !=
 	    DMA_RWCTRL_WRITE_BNDRY_16) {
-		static struct pci_device_id dma_wait_state_chipsets[] = {
-			{ PCI_DEVICE(PCI_VENDOR_ID_APPLE,
-				     PCI_DEVICE_ID_APPLE_UNI_N_PCI15) },
-			{ },
-		};
 
 		/* DMA test passed without adjusting DMA boundary,
 		 * now look for chipsets that are known to expose the
@@ -14334,7 +14343,7 @@ static int __devinit tg3_test_dma(struct
 	}
 
 out:
-	pci_free_consistent(tp->pdev, TEST_BUFFER_SIZE, buf, buf_dma);
+	dma_free_coherent(&tp->pdev->dev, TEST_BUFFER_SIZE, buf, buf_dma);
 out_nofree:
 	return ret;
 }
@@ -14548,9 +14557,6 @@ static const struct net_device_ops tg3_n
 	.ndo_do_ioctl		= tg3_ioctl,
 	.ndo_tx_timeout		= tg3_tx_timeout,
 	.ndo_change_mtu		= tg3_change_mtu,
-#if TG3_VLAN_TAG_USED
-	.ndo_vlan_rx_register	= tg3_vlan_rx_register,
-#endif
 #ifdef CONFIG_NET_POLL_CONTROLLER
 	.ndo_poll_controller	= tg3_poll_controller,
 #endif
@@ -14567,9 +14573,6 @@ static const struct net_device_ops tg3_n
 	.ndo_do_ioctl		= tg3_ioctl,
 	.ndo_tx_timeout		= tg3_tx_timeout,
 	.ndo_change_mtu		= tg3_change_mtu,
-#if TG3_VLAN_TAG_USED
-	.ndo_vlan_rx_register	= tg3_vlan_rx_register,
-#endif
 #ifdef CONFIG_NET_POLL_CONTROLLER
 	.ndo_poll_controller	= tg3_poll_controller,
 #endif
@@ -14619,9 +14622,7 @@ static int __devinit tg3_init_one(struct
 
 	SET_NETDEV_DEV(dev, &pdev->dev);
 
-#if TG3_VLAN_TAG_USED
 	dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
-#endif
 
 	tp = netdev_priv(dev);
 	tp->pdev = pdev;
@@ -14948,7 +14949,7 @@ static void __devexit tg3_remove_one(str
 		if (tp->fw)
 			release_firmware(tp->fw);
 
-		flush_scheduled_work();
+		cancel_work_sync(&tp->reset_task);
 
 		if (tp->tg3_flags3 & TG3_FLG3_USE_PHYLIB) {
 			tg3_phy_fini(tp);
@@ -14971,23 +14972,18 @@ static void __devexit tg3_remove_one(str
 	}
 }
 
-static int tg3_suspend(struct pci_dev *pdev, pm_message_t state)
+#ifdef CONFIG_PM_SLEEP
+static int tg3_suspend(struct device *device)
 {
+	struct pci_dev *pdev = to_pci_dev(device);
 	struct net_device *dev = pci_get_drvdata(pdev);
 	struct tg3 *tp = netdev_priv(dev);
-	pci_power_t target_state;
 	int err;
 
-	/* PCI register 4 needs to be saved whether netif_running() or not.
-	 * MSI address and data need to be saved if using MSI and
-	 * netif_running().
-	 */
-	pci_save_state(pdev);
-
 	if (!netif_running(dev))
 		return 0;
 
-	flush_scheduled_work();
+	flush_work_sync(&tp->reset_task);
 	tg3_phy_stop(tp);
 	tg3_netif_stop(tp);
 
@@ -15004,9 +15000,7 @@ static int tg3_suspend(struct pci_dev *p
 	tp->tg3_flags &= ~TG3_FLAG_INIT_COMPLETE;
 	tg3_full_unlock(tp);
 
-	target_state = pdev->pm_cap ? pci_target_state(pdev) : PCI_D3hot;
-
-	err = tg3_set_power_state(tp, target_state);
+	err = tg3_power_down_prepare(tp);
 	if (err) {
 		int err2;
 
@@ -15033,21 +15027,16 @@ out:
 	return err;
 }
 
-static int tg3_resume(struct pci_dev *pdev)
+static int tg3_resume(struct device *device)
 {
+	struct pci_dev *pdev = to_pci_dev(device);
 	struct net_device *dev = pci_get_drvdata(pdev);
 	struct tg3 *tp = netdev_priv(dev);
 	int err;
 
-	pci_restore_state(tp->pdev);
-
 	if (!netif_running(dev))
 		return 0;
 
-	err = tg3_set_power_state(tp, PCI_D0);
-	if (err)
-		return err;
-
 	netif_device_attach(dev);
 
 	tg3_full_lock(tp, 0);
@@ -15071,13 +15060,21 @@ out:
 	return err;
 }
 
+static SIMPLE_DEV_PM_OPS(tg3_pm_ops, tg3_suspend, tg3_resume);
+#define TG3_PM_OPS (&tg3_pm_ops)
+
+#else
+
+#define TG3_PM_OPS NULL
+
+#endif /* CONFIG_PM_SLEEP */
+
 static struct pci_driver tg3_driver = {
 	.name		= DRV_MODULE_NAME,
 	.id_table	= tg3_pci_tbl,
 	.probe		= tg3_init_one,
 	.remove		= __devexit_p(tg3_remove_one),
-	.suspend	= tg3_suspend,
-	.resume		= tg3_resume
+	.driver.pm	= TG3_PM_OPS,
 };
 
 static int __init tg3_init(void)
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/tg3.h linux-libre-2.6.38-gnu1/drivers/net/tg3.h
--- linux-libre-2.6.37-gnu1/drivers/net/tg3.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/tg3.h	2011-03-14 21:20:32.000000000 -0400
@@ -1094,13 +1094,19 @@
 /* 0x3664 --> 0x36b0 unused */
 
 #define TG3_CPMU_EEE_MODE		0x000036b0
-#define TG3_CPMU_EEEMD_ERLY_L1_XIT_DET	 0x00000008
-#define TG3_CPMU_EEEMD_LPI_ENABLE	 0x00000080
-#define TG3_CPMU_EEEMD_LPI_IN_TX	 0x00000100
-#define TG3_CPMU_EEEMD_LPI_IN_RX	 0x00000200
-#define TG3_CPMU_EEEMD_EEE_ENABLE	 0x00100000
-/* 0x36b4 --> 0x36b8 unused */
-
+#define  TG3_CPMU_EEEMD_APE_TX_DET_EN	 0x00000004
+#define  TG3_CPMU_EEEMD_ERLY_L1_XIT_DET	 0x00000008
+#define  TG3_CPMU_EEEMD_SND_IDX_DET_EN	 0x00000040
+#define  TG3_CPMU_EEEMD_LPI_ENABLE	 0x00000080
+#define  TG3_CPMU_EEEMD_LPI_IN_TX	 0x00000100
+#define  TG3_CPMU_EEEMD_LPI_IN_RX	 0x00000200
+#define  TG3_CPMU_EEEMD_EEE_ENABLE	 0x00100000
+#define TG3_CPMU_EEE_DBTMR1		0x000036b4
+#define  TG3_CPMU_DBTMR1_PCIEXIT_2047US	 0x07ff0000
+#define  TG3_CPMU_DBTMR1_LNKIDLE_2047US	 0x000070ff
+#define TG3_CPMU_EEE_DBTMR2		0x000036b8
+#define  TG3_CPMU_DBTMR1_APE_TX_2047US	 0x07ff0000
+#define  TG3_CPMU_DBTMR2_TXIDXEQ_2047US	 0x000070ff
 #define TG3_CPMU_EEE_LNKIDL_CTRL	0x000036bc
 #define  TG3_CPMU_EEE_LNKIDL_PCIE_NL0	 0x01000000
 #define  TG3_CPMU_EEE_LNKIDL_UART_IDL	 0x00000004
@@ -1327,6 +1333,8 @@
 
 #define TG3_RDMA_RSRVCTRL_REG		0x00004900
 #define TG3_RDMA_RSRVCTRL_FIFO_OFLW_FIX	 0x00000004
+#define TG3_RDMA_RSRVCTRL_TXMRGN_320B	 0x28000000
+#define TG3_RDMA_RSRVCTRL_TXMRGN_MASK	 0xffe00000
 /* 0x4904 --> 0x4910 unused */
 
 #define TG3_LSO_RD_DMA_CRPTEN_CTRL	0x00004910
@@ -2170,9 +2178,6 @@
 #define MII_TG3_TEST1_CRC_EN		0x8000
 
 /* Clause 45 expansion registers */
-#define TG3_CL45_D7_EEEADV_CAP		0x003c
-#define TG3_CL45_D7_EEEADV_CAP_100TX	0x0002
-#define TG3_CL45_D7_EEEADV_CAP_1000T	0x0004
 #define TG3_CL45_D7_EEERES_STAT		0x803e
 #define TG3_CL45_D7_EEERES_STAT_LP_100TX	0x0002
 #define TG3_CL45_D7_EEERES_STAT_LP_1000T	0x0004
@@ -2562,10 +2567,6 @@ struct ring_info {
 	DEFINE_DMA_UNMAP_ADDR(mapping);
 };
 
-struct tg3_config_info {
-	u32				flags;
-};
-
 struct tg3_link_config {
 	/* Describes what we're trying to get. */
 	u32				advertising;
@@ -2713,17 +2714,17 @@ struct tg3_napi {
 	u32				last_irq_tag;
 	u32				int_mbox;
 	u32				coal_now;
-	u32				tx_prod;
-	u32				tx_cons;
-	u32				tx_pending;
-	u32				prodmbox;
 
-	u32				consmbox;
+	u32				consmbox ____cacheline_aligned;
 	u32				rx_rcb_ptr;
 	u16				*rx_rcb_prod_idx;
 	struct tg3_rx_prodring_set	prodring;
-
 	struct tg3_rx_buffer_desc	*rx_rcb;
+
+	u32				tx_prod	____cacheline_aligned;
+	u32				tx_cons;
+	u32				tx_pending;
+	u32				prodmbox;
 	struct tg3_tx_buffer_desc	*tx_ring;
 	struct ring_info		*tx_buffers;
 
@@ -2807,9 +2808,6 @@ struct tg3 {
 	u32				rx_std_max_post;
 	u32				rx_offset;
 	u32				rx_pkt_map_sz;
-#if TG3_VLAN_TAG_USED
-	struct vlan_group		*vlgrp;
-#endif
 
 
 	/* begin "everything else" cacheline(s) section */
@@ -2946,6 +2944,7 @@ struct tg3 {
 	int				pcix_cap;
 	int				pcie_cap;
 	};
+	int				pcie_readrq;
 
 	struct mii_bus			*mdio_bus;
 	int				mdio_irq[PHY_MAX_ADDR];
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/tile/tilepro.c linux-libre-2.6.38-gnu1/drivers/net/tile/tilepro.c
--- linux-libre-2.6.37-gnu1/drivers/net/tile/tilepro.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/tile/tilepro.c	2011-03-14 21:20:32.000000000 -0400
@@ -142,14 +142,6 @@
 MODULE_AUTHOR("Tilera");
 MODULE_LICENSE("GPL");
 
-
-#define IS_MULTICAST(mac_addr) \
-	(((u8 *)(mac_addr))[0] & 0x01)
-
-#define IS_BROADCAST(mac_addr) \
-	(((u16 *)(mac_addr))[0] == 0xffff)
-
-
 /*
  * Queue of incoming packets for a specific cpu and device.
  *
@@ -795,7 +787,7 @@ static bool tile_net_poll_aux(struct til
 		/*
 		 * FIXME: Implement HW multicast filter.
 		 */
-		if (!IS_MULTICAST(buf) && !IS_BROADCAST(buf)) {
+		if (is_unicast_ether_addr(buf)) {
 			/* Filter packets not for our address. */
 			const u8 *mine = dev->dev_addr;
 			filter = compare_ether_addr(mine, buf);
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/tokenring/ibmtr.c linux-libre-2.6.38-gnu1/drivers/net/tokenring/ibmtr.c
--- linux-libre-2.6.37-gnu1/drivers/net/tokenring/ibmtr.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/tokenring/ibmtr.c	2011-03-14 21:20:32.000000000 -0400
@@ -657,8 +657,9 @@ static int __devinit ibmtr_probe1(struct
 #ifndef PCMCIA
 	/* finish figuring the shared RAM address */
 	if (cardpresent == TR_ISA) {
-		static __u32 ram_bndry_mask[] =
-			{ 0xffffe000, 0xffffc000, 0xffff8000, 0xffff0000 };
+		static const __u32 ram_bndry_mask[] = {
+			0xffffe000, 0xffffc000, 0xffff8000, 0xffff0000
+		};
 		__u32 new_base, rrr_32, chk_base, rbm;
 
 		rrr_32=readb(ti->mmio+ACA_OFFSET+ACA_RW+RRR_ODD) >> 2 & 0x03;
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/tulip/de2104x.c linux-libre-2.6.38-gnu1/drivers/net/tulip/de2104x.c
--- linux-libre-2.6.37-gnu1/drivers/net/tulip/de2104x.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/tulip/de2104x.c	2011-03-14 21:20:32.000000000 -0400
@@ -964,7 +964,7 @@ static void de_set_media (struct de_priv
 		dw32(MacMode, macmode);
 }
 
-static void de_next_media (struct de_private *de, u32 *media,
+static void de_next_media (struct de_private *de, const u32 *media,
 			   unsigned int n_media)
 {
 	unsigned int i;
@@ -1008,10 +1008,10 @@ static void de21040_media_timer (unsigne
 		return;
 
 	if (de->media_type == DE_MEDIA_AUI) {
-		u32 next_state = DE_MEDIA_TP;
+		static const u32 next_state = DE_MEDIA_TP;
 		de_next_media(de, &next_state, 1);
 	} else {
-		u32 next_state = DE_MEDIA_AUI;
+		static const u32 next_state = DE_MEDIA_AUI;
 		de_next_media(de, &next_state, 1);
 	}
 
@@ -1136,13 +1136,19 @@ static void de21041_media_timer (unsigne
 	 * simply resets the PHY and reloads the current media settings.
 	 */
 	if (de->media_type == DE_MEDIA_AUI) {
-		u32 next_states[] = { DE_MEDIA_BNC, DE_MEDIA_TP_AUTO };
+		static const u32 next_states[] = {
+			DE_MEDIA_BNC, DE_MEDIA_TP_AUTO
+		};
 		de_next_media(de, next_states, ARRAY_SIZE(next_states));
 	} else if (de->media_type == DE_MEDIA_BNC) {
-		u32 next_states[] = { DE_MEDIA_TP_AUTO, DE_MEDIA_AUI };
+		static const u32 next_states[] = {
+			DE_MEDIA_TP_AUTO, DE_MEDIA_AUI
+		};
 		de_next_media(de, next_states, ARRAY_SIZE(next_states));
 	} else {
-		u32 next_states[] = { DE_MEDIA_AUI, DE_MEDIA_BNC, DE_MEDIA_TP_AUTO };
+		static const u32 next_states[] = {
+			DE_MEDIA_AUI, DE_MEDIA_BNC, DE_MEDIA_TP_AUTO
+		};
 		de_next_media(de, next_states, ARRAY_SIZE(next_states));
 	}
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/tulip/tulip_core.c linux-libre-2.6.38-gnu1/drivers/net/tulip/tulip_core.c
--- linux-libre-2.6.37-gnu1/drivers/net/tulip/tulip_core.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/tulip/tulip_core.c	2011-03-14 21:20:32.000000000 -0400
@@ -1302,17 +1302,18 @@ static const struct net_device_ops tulip
 #endif
 };
 
+DEFINE_PCI_DEVICE_TABLE(early_486_chipsets) = {
+	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82424) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_496) },
+	{ },
+};
+
 static int __devinit tulip_init_one (struct pci_dev *pdev,
 				     const struct pci_device_id *ent)
 {
 	struct tulip_private *tp;
 	/* See note below on the multiport cards. */
 	static unsigned char last_phys_addr[6] = {0x00, 'L', 'i', 'n', 'u', 'x'};
-	static struct pci_device_id early_486_chipsets[] = {
-		{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82424) },
-		{ PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_496) },
-		{ },
-	};
 	static int last_irq;
 	static int multiport_cnt;	/* For four-port boards w/one EEPROM */
 	int i, irq;
@@ -1682,7 +1683,9 @@ static int __devinit tulip_init_one (str
 		tp->full_duplex_lock = 1;
 
 	if (tulip_media_cap[tp->default_port] & MediaIsMII) {
-		u16 media2advert[] = { 0x20, 0x40, 0x03e0, 0x60, 0x80, 0x100, 0x200 };
+		static const u16 media2advert[] = {
+			0x20, 0x40, 0x03e0, 0x60, 0x80, 0x100, 0x200
+		};
 		tp->mii_advertise = media2advert[tp->default_port - 9];
 		tp->mii_advertise |= (tp->flags & HAS_8023X); /* Matching bits! */
 	}
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/tun.c linux-libre-2.6.38-gnu1/drivers/net/tun.c
--- linux-libre-2.6.37-gnu1/drivers/net/tun.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/tun.c	2011-03-14 21:20:32.000000000 -0400
@@ -757,7 +757,7 @@ static __inline__ ssize_t tun_put_user(s
 
 		if (skb->ip_summed == CHECKSUM_PARTIAL) {
 			gso.flags = VIRTIO_NET_HDR_F_NEEDS_CSUM;
-			gso.csum_start = skb->csum_start - skb_headroom(skb);
+			gso.csum_start = skb_checksum_start_offset(skb);
 			gso.csum_offset = skb->csum_offset;
 		} /* else everything is zero */
 
@@ -1309,7 +1309,7 @@ static long __tun_chr_ioctl(struct file
 		break;
 
 	case SIOCGIFHWADDR:
-		/* Get hw addres */
+		/* Get hw address */
 		memcpy(ifr.ifr_hwaddr.sa_data, tun->dev->dev_addr, ETH_ALEN);
 		ifr.ifr_hwaddr.sa_family = tun->dev->type;
 		if (copy_to_user(argp, &ifr, ifreq_len))
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/ucc_geth.c linux-libre-2.6.38-gnu1/drivers/net/ucc_geth.c
--- linux-libre-2.6.37-gnu1/drivers/net/ucc_geth.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/ucc_geth.c	2011-03-14 21:20:32.000000000 -0400
@@ -28,6 +28,7 @@
 #include <linux/phy.h>
 #include <linux/workqueue.h>
 #include <linux/of_mdio.h>
+#include <linux/of_net.h>
 #include <linux/of_platform.h>
 
 #include <asm/uaccess.h>
@@ -2031,7 +2032,7 @@ static void ucc_geth_set_multi(struct ne
 			netdev_for_each_mc_addr(ha, dev) {
 				/* Only support group multicast for now.
 				 */
-				if (!(ha->addr[0] & 1))
+				if (!is_multicast_ether_addr(ha->addr))
 					continue;
 
 				/* Ask CPM to run CRC and set bit in
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/usb/cdc_ether.c linux-libre-2.6.38-gnu1/drivers/net/usb/cdc_ether.c
--- linux-libre-2.6.37-gnu1/drivers/net/usb/cdc_ether.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/usb/cdc_ether.c	2011-03-14 21:20:32.000000000 -0400
@@ -99,9 +99,7 @@ int usbnet_generic_cdc_bind(struct usbne
 		 */
 		buf = dev->udev->actconfig->extra;
 		len = dev->udev->actconfig->extralen;
-		if (len)
-			dev_dbg(&intf->dev,
-				"CDC descriptors on config\n");
+		dev_dbg(&intf->dev, "CDC descriptors on config\n");
 	}
 
 	/* Maybe CDC descriptors are after the endpoint?  This bug has
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/usb/cdc_ncm.c linux-libre-2.6.38-gnu1/drivers/net/usb/cdc_ncm.c
--- linux-libre-2.6.37-gnu1/drivers/net/usb/cdc_ncm.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/usb/cdc_ncm.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,1287 @@
+/*
+ * cdc_ncm.c
+ *
+ * Copyright (C) ST-Ericsson 2010-2011
+ * Contact: Alexey Orishko <alexey.orishko@stericsson.com>
+ * Original author: Hans Petter Selasky <hans.petter.selasky@stericsson.com>
+ *
+ * USB Host Driver for Network Control Model (NCM)
+ * http://www.usb.org/developers/devclass_docs/NCM10.zip
+ *
+ * The NCM encoding, decoding and initialization logic
+ * derives from FreeBSD 8.x. if_cdce.c and if_cdcereg.h
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose this file to be licensed under the terms
+ * of the GNU General Public License (GPL) Version 2 or the 2-clause
+ * BSD license listed below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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 <linux/module.h>
+#include <linux/init.h>
+#include <linux/netdevice.h>
+#include <linux/ctype.h>
+#include <linux/ethtool.h>
+#include <linux/workqueue.h>
+#include <linux/mii.h>
+#include <linux/crc32.h>
+#include <linux/usb.h>
+#include <linux/version.h>
+#include <linux/timer.h>
+#include <linux/spinlock.h>
+#include <linux/atomic.h>
+#include <linux/usb/usbnet.h>
+#include <linux/usb/cdc.h>
+
+#define	DRIVER_VERSION				"7-Feb-2011"
+
+/* CDC NCM subclass 3.2.1 */
+#define USB_CDC_NCM_NDP16_LENGTH_MIN		0x10
+
+/* Maximum NTB length */
+#define	CDC_NCM_NTB_MAX_SIZE_TX			16384	/* bytes */
+#define	CDC_NCM_NTB_MAX_SIZE_RX			16384	/* bytes */
+
+/* Minimum value for MaxDatagramSize, ch. 6.2.9 */
+#define	CDC_NCM_MIN_DATAGRAM_SIZE		1514	/* bytes */
+
+#define	CDC_NCM_MIN_TX_PKT			512	/* bytes */
+
+/* Default value for MaxDatagramSize */
+#define	CDC_NCM_MAX_DATAGRAM_SIZE		2048	/* bytes */
+
+/*
+ * Maximum amount of datagrams in NCM Datagram Pointer Table, not counting
+ * the last NULL entry. Any additional datagrams in NTB would be discarded.
+ */
+#define	CDC_NCM_DPT_DATAGRAMS_MAX		32
+
+/* Maximum amount of IN datagrams in NTB */
+#define	CDC_NCM_DPT_DATAGRAMS_IN_MAX		0 /* unlimited */
+
+/* Restart the timer, if amount of datagrams is less than given value */
+#define	CDC_NCM_RESTART_TIMER_DATAGRAM_CNT	3
+
+/* The following macro defines the minimum header space */
+#define	CDC_NCM_MIN_HDR_SIZE \
+	(sizeof(struct usb_cdc_ncm_nth16) + sizeof(struct usb_cdc_ncm_ndp16) + \
+	(CDC_NCM_DPT_DATAGRAMS_MAX + 1) * sizeof(struct usb_cdc_ncm_dpe16))
+
+struct cdc_ncm_data {
+	struct usb_cdc_ncm_nth16 nth16;
+	struct usb_cdc_ncm_ndp16 ndp16;
+	struct usb_cdc_ncm_dpe16 dpe16[CDC_NCM_DPT_DATAGRAMS_MAX + 1];
+};
+
+struct cdc_ncm_ctx {
+	struct cdc_ncm_data rx_ncm;
+	struct cdc_ncm_data tx_ncm;
+	struct usb_cdc_ncm_ntb_parameters ncm_parm;
+	struct timer_list tx_timer;
+
+	const struct usb_cdc_ncm_desc *func_desc;
+	const struct usb_cdc_header_desc *header_desc;
+	const struct usb_cdc_union_desc *union_desc;
+	const struct usb_cdc_ether_desc *ether_desc;
+
+	struct net_device *netdev;
+	struct usb_device *udev;
+	struct usb_host_endpoint *in_ep;
+	struct usb_host_endpoint *out_ep;
+	struct usb_host_endpoint *status_ep;
+	struct usb_interface *intf;
+	struct usb_interface *control;
+	struct usb_interface *data;
+
+	struct sk_buff *tx_curr_skb;
+	struct sk_buff *tx_rem_skb;
+
+	spinlock_t mtx;
+
+	u32 tx_timer_pending;
+	u32 tx_curr_offset;
+	u32 tx_curr_last_offset;
+	u32 tx_curr_frame_num;
+	u32 rx_speed;
+	u32 tx_speed;
+	u32 rx_max;
+	u32 tx_max;
+	u32 max_datagram_size;
+	u16 tx_max_datagrams;
+	u16 tx_remainder;
+	u16 tx_modulus;
+	u16 tx_ndp_modulus;
+	u16 tx_seq;
+	u16 connected;
+	u8 data_claimed;
+	u8 control_claimed;
+};
+
+static void cdc_ncm_tx_timeout(unsigned long arg);
+static const struct driver_info cdc_ncm_info;
+static struct usb_driver cdc_ncm_driver;
+static struct ethtool_ops cdc_ncm_ethtool_ops;
+
+static const struct usb_device_id cdc_devs[] = {
+	{ USB_INTERFACE_INFO(USB_CLASS_COMM,
+		USB_CDC_SUBCLASS_NCM, USB_CDC_PROTO_NONE),
+		.driver_info = (unsigned long)&cdc_ncm_info,
+	},
+	{
+	},
+};
+
+MODULE_DEVICE_TABLE(usb, cdc_devs);
+
+static void
+cdc_ncm_get_drvinfo(struct net_device *net, struct ethtool_drvinfo *info)
+{
+	struct usbnet *dev = netdev_priv(net);
+
+	strncpy(info->driver, dev->driver_name, sizeof(info->driver));
+	strncpy(info->version, DRIVER_VERSION, sizeof(info->version));
+	strncpy(info->fw_version, dev->driver_info->description,
+		sizeof(info->fw_version));
+	usb_make_path(dev->udev, info->bus_info, sizeof(info->bus_info));
+}
+
+static int
+cdc_ncm_do_request(struct cdc_ncm_ctx *ctx, struct usb_cdc_notification *req,
+		   void *data, u16 flags, u16 *actlen, u16 timeout)
+{
+	int err;
+
+	err = usb_control_msg(ctx->udev, (req->bmRequestType & USB_DIR_IN) ?
+				usb_rcvctrlpipe(ctx->udev, 0) :
+				usb_sndctrlpipe(ctx->udev, 0),
+				req->bNotificationType, req->bmRequestType,
+				req->wValue,
+				req->wIndex, data,
+				req->wLength, timeout);
+
+	if (err < 0) {
+		if (actlen)
+			*actlen = 0;
+		return err;
+	}
+
+	if (actlen)
+		*actlen = err;
+
+	return 0;
+}
+
+static u8 cdc_ncm_setup(struct cdc_ncm_ctx *ctx)
+{
+	struct usb_cdc_notification req;
+	u32 val;
+	u8 flags;
+	u8 iface_no;
+	int err;
+	u16 ntb_fmt_supported;
+
+	iface_no = ctx->control->cur_altsetting->desc.bInterfaceNumber;
+
+	req.bmRequestType = USB_TYPE_CLASS | USB_DIR_IN | USB_RECIP_INTERFACE;
+	req.bNotificationType = USB_CDC_GET_NTB_PARAMETERS;
+	req.wValue = 0;
+	req.wIndex = cpu_to_le16(iface_no);
+	req.wLength = cpu_to_le16(sizeof(ctx->ncm_parm));
+
+	err = cdc_ncm_do_request(ctx, &req, &ctx->ncm_parm, 0, NULL, 1000);
+	if (err) {
+		pr_debug("failed GET_NTB_PARAMETERS\n");
+		return 1;
+	}
+
+	/* read correct set of parameters according to device mode */
+	ctx->rx_max = le32_to_cpu(ctx->ncm_parm.dwNtbInMaxSize);
+	ctx->tx_max = le32_to_cpu(ctx->ncm_parm.dwNtbOutMaxSize);
+	ctx->tx_remainder = le16_to_cpu(ctx->ncm_parm.wNdpOutPayloadRemainder);
+	ctx->tx_modulus = le16_to_cpu(ctx->ncm_parm.wNdpOutDivisor);
+	ctx->tx_ndp_modulus = le16_to_cpu(ctx->ncm_parm.wNdpOutAlignment);
+	/* devices prior to NCM Errata shall set this field to zero */
+	ctx->tx_max_datagrams = le16_to_cpu(ctx->ncm_parm.wNtbOutMaxDatagrams);
+	ntb_fmt_supported = le16_to_cpu(ctx->ncm_parm.bmNtbFormatsSupported);
+
+	if (ctx->func_desc != NULL)
+		flags = ctx->func_desc->bmNetworkCapabilities;
+	else
+		flags = 0;
+
+	pr_debug("dwNtbInMaxSize=%u dwNtbOutMaxSize=%u "
+		 "wNdpOutPayloadRemainder=%u wNdpOutDivisor=%u "
+		 "wNdpOutAlignment=%u wNtbOutMaxDatagrams=%u flags=0x%x\n",
+		 ctx->rx_max, ctx->tx_max, ctx->tx_remainder, ctx->tx_modulus,
+		 ctx->tx_ndp_modulus, ctx->tx_max_datagrams, flags);
+
+	/* max count of tx datagrams */
+	if ((ctx->tx_max_datagrams == 0) ||
+			(ctx->tx_max_datagrams > CDC_NCM_DPT_DATAGRAMS_MAX))
+		ctx->tx_max_datagrams = CDC_NCM_DPT_DATAGRAMS_MAX;
+
+	/* verify maximum size of received NTB in bytes */
+	if (ctx->rx_max < USB_CDC_NCM_NTB_MIN_IN_SIZE) {
+		pr_debug("Using min receive length=%d\n",
+						USB_CDC_NCM_NTB_MIN_IN_SIZE);
+		ctx->rx_max = USB_CDC_NCM_NTB_MIN_IN_SIZE;
+	}
+
+	if (ctx->rx_max > CDC_NCM_NTB_MAX_SIZE_RX) {
+		pr_debug("Using default maximum receive length=%d\n",
+						CDC_NCM_NTB_MAX_SIZE_RX);
+		ctx->rx_max = CDC_NCM_NTB_MAX_SIZE_RX;
+	}
+
+	/* inform device about NTB input size changes */
+	if (ctx->rx_max != le32_to_cpu(ctx->ncm_parm.dwNtbInMaxSize)) {
+		req.bmRequestType = USB_TYPE_CLASS | USB_DIR_OUT |
+							USB_RECIP_INTERFACE;
+		req.bNotificationType = USB_CDC_SET_NTB_INPUT_SIZE;
+		req.wValue = 0;
+		req.wIndex = cpu_to_le16(iface_no);
+
+		if (flags & USB_CDC_NCM_NCAP_NTB_INPUT_SIZE) {
+			struct usb_cdc_ncm_ndp_input_size ndp_in_sz;
+
+			req.wLength = 8;
+			ndp_in_sz.dwNtbInMaxSize = cpu_to_le32(ctx->rx_max);
+			ndp_in_sz.wNtbInMaxDatagrams =
+					cpu_to_le16(CDC_NCM_DPT_DATAGRAMS_MAX);
+			ndp_in_sz.wReserved = 0;
+			err = cdc_ncm_do_request(ctx, &req, &ndp_in_sz, 0, NULL,
+									1000);
+		} else {
+			__le32 dwNtbInMaxSize = cpu_to_le32(ctx->rx_max);
+
+			req.wLength = 4;
+			err = cdc_ncm_do_request(ctx, &req, &dwNtbInMaxSize, 0,
+								NULL, 1000);
+		}
+
+		if (err)
+			pr_debug("Setting NTB Input Size failed\n");
+	}
+
+	/* verify maximum size of transmitted NTB in bytes */
+	if ((ctx->tx_max <
+	    (CDC_NCM_MIN_HDR_SIZE + CDC_NCM_MIN_DATAGRAM_SIZE)) ||
+	    (ctx->tx_max > CDC_NCM_NTB_MAX_SIZE_TX)) {
+		pr_debug("Using default maximum transmit length=%d\n",
+						CDC_NCM_NTB_MAX_SIZE_TX);
+		ctx->tx_max = CDC_NCM_NTB_MAX_SIZE_TX;
+	}
+
+	/*
+	 * verify that the structure alignment is:
+	 * - power of two
+	 * - not greater than the maximum transmit length
+	 * - not less than four bytes
+	 */
+	val = ctx->tx_ndp_modulus;
+
+	if ((val < USB_CDC_NCM_NDP_ALIGN_MIN_SIZE) ||
+	    (val != ((-val) & val)) || (val >= ctx->tx_max)) {
+		pr_debug("Using default alignment: 4 bytes\n");
+		ctx->tx_ndp_modulus = USB_CDC_NCM_NDP_ALIGN_MIN_SIZE;
+	}
+
+	/*
+	 * verify that the payload alignment is:
+	 * - power of two
+	 * - not greater than the maximum transmit length
+	 * - not less than four bytes
+	 */
+	val = ctx->tx_modulus;
+
+	if ((val < USB_CDC_NCM_NDP_ALIGN_MIN_SIZE) ||
+	    (val != ((-val) & val)) || (val >= ctx->tx_max)) {
+		pr_debug("Using default transmit modulus: 4 bytes\n");
+		ctx->tx_modulus = USB_CDC_NCM_NDP_ALIGN_MIN_SIZE;
+	}
+
+	/* verify the payload remainder */
+	if (ctx->tx_remainder >= ctx->tx_modulus) {
+		pr_debug("Using default transmit remainder: 0 bytes\n");
+		ctx->tx_remainder = 0;
+	}
+
+	/* adjust TX-remainder according to NCM specification. */
+	ctx->tx_remainder = ((ctx->tx_remainder - ETH_HLEN) &
+						(ctx->tx_modulus - 1));
+
+	/* additional configuration */
+
+	/* set CRC Mode */
+	if (flags & USB_CDC_NCM_NCAP_CRC_MODE) {
+		req.bmRequestType = USB_TYPE_CLASS | USB_DIR_OUT |
+							USB_RECIP_INTERFACE;
+		req.bNotificationType = USB_CDC_SET_CRC_MODE;
+		req.wValue = cpu_to_le16(USB_CDC_NCM_CRC_NOT_APPENDED);
+		req.wIndex = cpu_to_le16(iface_no);
+		req.wLength = 0;
+
+		err = cdc_ncm_do_request(ctx, &req, NULL, 0, NULL, 1000);
+		if (err)
+			pr_debug("Setting CRC mode off failed\n");
+	}
+
+	/* set NTB format, if both formats are supported */
+	if (ntb_fmt_supported & USB_CDC_NCM_NTH32_SIGN) {
+		req.bmRequestType = USB_TYPE_CLASS | USB_DIR_OUT |
+							USB_RECIP_INTERFACE;
+		req.bNotificationType = USB_CDC_SET_NTB_FORMAT;
+		req.wValue = cpu_to_le16(USB_CDC_NCM_NTB16_FORMAT);
+		req.wIndex = cpu_to_le16(iface_no);
+		req.wLength = 0;
+
+		err = cdc_ncm_do_request(ctx, &req, NULL, 0, NULL, 1000);
+		if (err)
+			pr_debug("Setting NTB format to 16-bit failed\n");
+	}
+
+	ctx->max_datagram_size = CDC_NCM_MIN_DATAGRAM_SIZE;
+
+	/* set Max Datagram Size (MTU) */
+	if (flags & USB_CDC_NCM_NCAP_MAX_DATAGRAM_SIZE) {
+		__le16 max_datagram_size;
+		u16 eth_max_sz = le16_to_cpu(ctx->ether_desc->wMaxSegmentSize);
+
+		req.bmRequestType = USB_TYPE_CLASS | USB_DIR_IN |
+							USB_RECIP_INTERFACE;
+		req.bNotificationType = USB_CDC_GET_MAX_DATAGRAM_SIZE;
+		req.wValue = 0;
+		req.wIndex = cpu_to_le16(iface_no);
+		req.wLength = cpu_to_le16(2);
+
+		err = cdc_ncm_do_request(ctx, &req, &max_datagram_size, 0, NULL,
+									1000);
+		if (err) {
+			pr_debug("GET_MAX_DATAGRAM_SIZE failed, use size=%u\n",
+						CDC_NCM_MIN_DATAGRAM_SIZE);
+		} else {
+			ctx->max_datagram_size = le16_to_cpu(max_datagram_size);
+			/* Check Eth descriptor value */
+			if (eth_max_sz < CDC_NCM_MAX_DATAGRAM_SIZE) {
+				if (ctx->max_datagram_size > eth_max_sz)
+					ctx->max_datagram_size = eth_max_sz;
+			} else {
+				if (ctx->max_datagram_size >
+						CDC_NCM_MAX_DATAGRAM_SIZE)
+					ctx->max_datagram_size =
+						CDC_NCM_MAX_DATAGRAM_SIZE;
+			}
+
+			if (ctx->max_datagram_size < CDC_NCM_MIN_DATAGRAM_SIZE)
+				ctx->max_datagram_size =
+					CDC_NCM_MIN_DATAGRAM_SIZE;
+
+			/* if value changed, update device */
+			req.bmRequestType = USB_TYPE_CLASS | USB_DIR_OUT |
+							USB_RECIP_INTERFACE;
+			req.bNotificationType = USB_CDC_SET_MAX_DATAGRAM_SIZE;
+			req.wValue = 0;
+			req.wIndex = cpu_to_le16(iface_no);
+			req.wLength = 2;
+			max_datagram_size = cpu_to_le16(ctx->max_datagram_size);
+
+			err = cdc_ncm_do_request(ctx, &req, &max_datagram_size,
+								0, NULL, 1000);
+			if (err)
+				pr_debug("SET_MAX_DATAGRAM_SIZE failed\n");
+		}
+
+	}
+
+	if (ctx->netdev->mtu != (ctx->max_datagram_size - ETH_HLEN))
+		ctx->netdev->mtu = ctx->max_datagram_size - ETH_HLEN;
+
+	return 0;
+}
+
+static void
+cdc_ncm_find_endpoints(struct cdc_ncm_ctx *ctx, struct usb_interface *intf)
+{
+	struct usb_host_endpoint *e;
+	u8 ep;
+
+	for (ep = 0; ep < intf->cur_altsetting->desc.bNumEndpoints; ep++) {
+
+		e = intf->cur_altsetting->endpoint + ep;
+		switch (e->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) {
+		case USB_ENDPOINT_XFER_INT:
+			if (usb_endpoint_dir_in(&e->desc)) {
+				if (ctx->status_ep == NULL)
+					ctx->status_ep = e;
+			}
+			break;
+
+		case USB_ENDPOINT_XFER_BULK:
+			if (usb_endpoint_dir_in(&e->desc)) {
+				if (ctx->in_ep == NULL)
+					ctx->in_ep = e;
+			} else {
+				if (ctx->out_ep == NULL)
+					ctx->out_ep = e;
+			}
+			break;
+
+		default:
+			break;
+		}
+	}
+}
+
+static void cdc_ncm_free(struct cdc_ncm_ctx *ctx)
+{
+	if (ctx == NULL)
+		return;
+
+	del_timer_sync(&ctx->tx_timer);
+
+	if (ctx->data_claimed) {
+		usb_set_intfdata(ctx->data, NULL);
+		usb_driver_release_interface(driver_of(ctx->intf), ctx->data);
+	}
+
+	if (ctx->control_claimed) {
+		usb_set_intfdata(ctx->control, NULL);
+		usb_driver_release_interface(driver_of(ctx->intf),
+								ctx->control);
+	}
+
+	if (ctx->tx_rem_skb != NULL) {
+		dev_kfree_skb_any(ctx->tx_rem_skb);
+		ctx->tx_rem_skb = NULL;
+	}
+
+	if (ctx->tx_curr_skb != NULL) {
+		dev_kfree_skb_any(ctx->tx_curr_skb);
+		ctx->tx_curr_skb = NULL;
+	}
+
+	kfree(ctx);
+}
+
+static int cdc_ncm_bind(struct usbnet *dev, struct usb_interface *intf)
+{
+	struct cdc_ncm_ctx *ctx;
+	struct usb_driver *driver;
+	u8 *buf;
+	int len;
+	int temp;
+	u8 iface_no;
+
+	ctx = kmalloc(sizeof(*ctx), GFP_KERNEL);
+	if (ctx == NULL)
+		goto error;
+
+	memset(ctx, 0, sizeof(*ctx));
+
+	init_timer(&ctx->tx_timer);
+	spin_lock_init(&ctx->mtx);
+	ctx->netdev = dev->net;
+
+	/* store ctx pointer in device data field */
+	dev->data[0] = (unsigned long)ctx;
+
+	/* get some pointers */
+	driver = driver_of(intf);
+	buf = intf->cur_altsetting->extra;
+	len = intf->cur_altsetting->extralen;
+
+	ctx->udev = dev->udev;
+	ctx->intf = intf;
+
+	/* parse through descriptors associated with control interface */
+	while ((len > 0) && (buf[0] > 2) && (buf[0] <= len)) {
+
+		if (buf[1] != USB_DT_CS_INTERFACE)
+			goto advance;
+
+		switch (buf[2]) {
+		case USB_CDC_UNION_TYPE:
+			if (buf[0] < sizeof(*(ctx->union_desc)))
+				break;
+
+			ctx->union_desc =
+					(const struct usb_cdc_union_desc *)buf;
+
+			ctx->control = usb_ifnum_to_if(dev->udev,
+					ctx->union_desc->bMasterInterface0);
+			ctx->data = usb_ifnum_to_if(dev->udev,
+					ctx->union_desc->bSlaveInterface0);
+			break;
+
+		case USB_CDC_ETHERNET_TYPE:
+			if (buf[0] < sizeof(*(ctx->ether_desc)))
+				break;
+
+			ctx->ether_desc =
+					(const struct usb_cdc_ether_desc *)buf;
+			dev->hard_mtu =
+				le16_to_cpu(ctx->ether_desc->wMaxSegmentSize);
+
+			if (dev->hard_mtu < CDC_NCM_MIN_DATAGRAM_SIZE)
+				dev->hard_mtu =	CDC_NCM_MIN_DATAGRAM_SIZE;
+			else if (dev->hard_mtu > CDC_NCM_MAX_DATAGRAM_SIZE)
+				dev->hard_mtu =	CDC_NCM_MAX_DATAGRAM_SIZE;
+			break;
+
+		case USB_CDC_NCM_TYPE:
+			if (buf[0] < sizeof(*(ctx->func_desc)))
+				break;
+
+			ctx->func_desc = (const struct usb_cdc_ncm_desc *)buf;
+			break;
+
+		default:
+			break;
+		}
+advance:
+		/* advance to next descriptor */
+		temp = buf[0];
+		buf += temp;
+		len -= temp;
+	}
+
+	/* check if we got everything */
+	if ((ctx->control == NULL) || (ctx->data == NULL) ||
+	    (ctx->ether_desc == NULL))
+		goto error;
+
+	/* claim interfaces, if any */
+	if (ctx->data != intf) {
+		temp = usb_driver_claim_interface(driver, ctx->data, dev);
+		if (temp)
+			goto error;
+		ctx->data_claimed = 1;
+	}
+
+	if (ctx->control != intf) {
+		temp = usb_driver_claim_interface(driver, ctx->control, dev);
+		if (temp)
+			goto error;
+		ctx->control_claimed = 1;
+	}
+
+	iface_no = ctx->data->cur_altsetting->desc.bInterfaceNumber;
+
+	/* reset data interface */
+	temp = usb_set_interface(dev->udev, iface_no, 0);
+	if (temp)
+		goto error;
+
+	/* initialize data interface */
+	if (cdc_ncm_setup(ctx))
+		goto error;
+
+	/* configure data interface */
+	temp = usb_set_interface(dev->udev, iface_no, 1);
+	if (temp)
+		goto error;
+
+	cdc_ncm_find_endpoints(ctx, ctx->data);
+	cdc_ncm_find_endpoints(ctx, ctx->control);
+
+	if ((ctx->in_ep == NULL) || (ctx->out_ep == NULL) ||
+	    (ctx->status_ep == NULL))
+		goto error;
+
+	dev->net->ethtool_ops = &cdc_ncm_ethtool_ops;
+
+	usb_set_intfdata(ctx->data, dev);
+	usb_set_intfdata(ctx->control, dev);
+	usb_set_intfdata(ctx->intf, dev);
+
+	temp = usbnet_get_ethernet_addr(dev, ctx->ether_desc->iMACAddress);
+	if (temp)
+		goto error;
+
+	dev_info(&dev->udev->dev, "MAC-Address: "
+				"0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x\n",
+				dev->net->dev_addr[0], dev->net->dev_addr[1],
+				dev->net->dev_addr[2], dev->net->dev_addr[3],
+				dev->net->dev_addr[4], dev->net->dev_addr[5]);
+
+	dev->in = usb_rcvbulkpipe(dev->udev,
+		ctx->in_ep->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
+	dev->out = usb_sndbulkpipe(dev->udev,
+		ctx->out_ep->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
+	dev->status = ctx->status_ep;
+	dev->rx_urb_size = ctx->rx_max;
+
+	/*
+	 * We should get an event when network connection is "connected" or
+	 * "disconnected". Set network connection in "disconnected" state
+	 * (carrier is OFF) during attach, so the IP network stack does not
+	 * start IPv6 negotiation and more.
+	 */
+	netif_carrier_off(dev->net);
+	ctx->tx_speed = ctx->rx_speed = 0;
+	return 0;
+
+error:
+	cdc_ncm_free((struct cdc_ncm_ctx *)dev->data[0]);
+	dev->data[0] = 0;
+	dev_info(&dev->udev->dev, "Descriptor failure\n");
+	return -ENODEV;
+}
+
+static void cdc_ncm_unbind(struct usbnet *dev, struct usb_interface *intf)
+{
+	struct cdc_ncm_ctx *ctx = (struct cdc_ncm_ctx *)dev->data[0];
+	struct usb_driver *driver;
+
+	if (ctx == NULL)
+		return;		/* no setup */
+
+	driver = driver_of(intf);
+
+	usb_set_intfdata(ctx->data, NULL);
+	usb_set_intfdata(ctx->control, NULL);
+	usb_set_intfdata(ctx->intf, NULL);
+
+	/* release interfaces, if any */
+	if (ctx->data_claimed) {
+		usb_driver_release_interface(driver, ctx->data);
+		ctx->data_claimed = 0;
+	}
+
+	if (ctx->control_claimed) {
+		usb_driver_release_interface(driver, ctx->control);
+		ctx->control_claimed = 0;
+	}
+
+	cdc_ncm_free(ctx);
+}
+
+static void cdc_ncm_zero_fill(u8 *ptr, u32 first, u32 end, u32 max)
+{
+	if (first >= max)
+		return;
+	if (first >= end)
+		return;
+	if (end > max)
+		end = max;
+	memset(ptr + first, 0, end - first);
+}
+
+static struct sk_buff *
+cdc_ncm_fill_tx_frame(struct cdc_ncm_ctx *ctx, struct sk_buff *skb)
+{
+	struct sk_buff *skb_out;
+	u32 rem;
+	u32 offset;
+	u32 last_offset;
+	u16 n = 0;
+	u8 ready2send = 0;
+
+	/* if there is a remaining skb, it gets priority */
+	if (skb != NULL)
+		swap(skb, ctx->tx_rem_skb);
+	else
+		ready2send = 1;
+
+	/*
+	 * +----------------+
+	 * | skb_out        |
+	 * +----------------+
+	 *           ^ offset
+	 *        ^ last_offset
+	 */
+
+	/* check if we are resuming an OUT skb */
+	if (ctx->tx_curr_skb != NULL) {
+		/* pop variables */
+		skb_out = ctx->tx_curr_skb;
+		offset = ctx->tx_curr_offset;
+		last_offset = ctx->tx_curr_last_offset;
+		n = ctx->tx_curr_frame_num;
+
+	} else {
+		/* reset variables */
+		skb_out = alloc_skb(ctx->tx_max, GFP_ATOMIC);
+		if (skb_out == NULL) {
+			if (skb != NULL) {
+				dev_kfree_skb_any(skb);
+				ctx->netdev->stats.tx_dropped++;
+			}
+			goto exit_no_skb;
+		}
+
+		/* make room for NTH and NDP */
+		offset = ALIGN(sizeof(struct usb_cdc_ncm_nth16),
+					ctx->tx_ndp_modulus) +
+					sizeof(struct usb_cdc_ncm_ndp16) +
+					(ctx->tx_max_datagrams + 1) *
+					sizeof(struct usb_cdc_ncm_dpe16);
+
+		/* store last valid offset before alignment */
+		last_offset = offset;
+		/* align first Datagram offset correctly */
+		offset = ALIGN(offset, ctx->tx_modulus) + ctx->tx_remainder;
+		/* zero buffer till the first IP datagram */
+		cdc_ncm_zero_fill(skb_out->data, 0, offset, offset);
+		n = 0;
+		ctx->tx_curr_frame_num = 0;
+	}
+
+	for (; n < ctx->tx_max_datagrams; n++) {
+		/* check if end of transmit buffer is reached */
+		if (offset >= ctx->tx_max) {
+			ready2send = 1;
+			break;
+		}
+		/* compute maximum buffer size */
+		rem = ctx->tx_max - offset;
+
+		if (skb == NULL) {
+			skb = ctx->tx_rem_skb;
+			ctx->tx_rem_skb = NULL;
+
+			/* check for end of skb */
+			if (skb == NULL)
+				break;
+		}
+
+		if (skb->len > rem) {
+			if (n == 0) {
+				/* won't fit, MTU problem? */
+				dev_kfree_skb_any(skb);
+				skb = NULL;
+				ctx->netdev->stats.tx_dropped++;
+			} else {
+				/* no room for skb - store for later */
+				if (ctx->tx_rem_skb != NULL) {
+					dev_kfree_skb_any(ctx->tx_rem_skb);
+					ctx->netdev->stats.tx_dropped++;
+				}
+				ctx->tx_rem_skb = skb;
+				skb = NULL;
+				ready2send = 1;
+			}
+			break;
+		}
+
+		memcpy(((u8 *)skb_out->data) + offset, skb->data, skb->len);
+
+		ctx->tx_ncm.dpe16[n].wDatagramLength = cpu_to_le16(skb->len);
+		ctx->tx_ncm.dpe16[n].wDatagramIndex = cpu_to_le16(offset);
+
+		/* update offset */
+		offset += skb->len;
+
+		/* store last valid offset before alignment */
+		last_offset = offset;
+
+		/* align offset correctly */
+		offset = ALIGN(offset, ctx->tx_modulus) + ctx->tx_remainder;
+
+		/* zero padding */
+		cdc_ncm_zero_fill(skb_out->data, last_offset, offset,
+								ctx->tx_max);
+		dev_kfree_skb_any(skb);
+		skb = NULL;
+	}
+
+	/* free up any dangling skb */
+	if (skb != NULL) {
+		dev_kfree_skb_any(skb);
+		skb = NULL;
+		ctx->netdev->stats.tx_dropped++;
+	}
+
+	ctx->tx_curr_frame_num = n;
+
+	if (n == 0) {
+		/* wait for more frames */
+		/* push variables */
+		ctx->tx_curr_skb = skb_out;
+		ctx->tx_curr_offset = offset;
+		ctx->tx_curr_last_offset = last_offset;
+		goto exit_no_skb;
+
+	} else if ((n < ctx->tx_max_datagrams) && (ready2send == 0)) {
+		/* wait for more frames */
+		/* push variables */
+		ctx->tx_curr_skb = skb_out;
+		ctx->tx_curr_offset = offset;
+		ctx->tx_curr_last_offset = last_offset;
+		/* set the pending count */
+		if (n < CDC_NCM_RESTART_TIMER_DATAGRAM_CNT)
+			ctx->tx_timer_pending = 2;
+		goto exit_no_skb;
+
+	} else {
+		/* frame goes out */
+		/* variables will be reset at next call */
+	}
+
+	/* check for overflow */
+	if (last_offset > ctx->tx_max)
+		last_offset = ctx->tx_max;
+
+	/* revert offset */
+	offset = last_offset;
+
+	/*
+	 * If collected data size is less or equal CDC_NCM_MIN_TX_PKT bytes,
+	 * we send buffers as it is. If we get more data, it would be more
+	 * efficient for USB HS mobile device with DMA engine to receive a full
+	 * size NTB, than canceling DMA transfer and receiving a short packet.
+	 */
+	if (offset > CDC_NCM_MIN_TX_PKT)
+		offset = ctx->tx_max;
+
+	/* final zero padding */
+	cdc_ncm_zero_fill(skb_out->data, last_offset, offset, ctx->tx_max);
+
+	/* store last offset */
+	last_offset = offset;
+
+	if ((last_offset < ctx->tx_max) && ((last_offset %
+			le16_to_cpu(ctx->out_ep->desc.wMaxPacketSize)) == 0)) {
+		/* force short packet */
+		*(((u8 *)skb_out->data) + last_offset) = 0;
+		last_offset++;
+	}
+
+	/* zero the rest of the DPEs plus the last NULL entry */
+	for (; n <= CDC_NCM_DPT_DATAGRAMS_MAX; n++) {
+		ctx->tx_ncm.dpe16[n].wDatagramLength = 0;
+		ctx->tx_ncm.dpe16[n].wDatagramIndex = 0;
+	}
+
+	/* fill out 16-bit NTB header */
+	ctx->tx_ncm.nth16.dwSignature = cpu_to_le32(USB_CDC_NCM_NTH16_SIGN);
+	ctx->tx_ncm.nth16.wHeaderLength =
+					cpu_to_le16(sizeof(ctx->tx_ncm.nth16));
+	ctx->tx_ncm.nth16.wSequence = cpu_to_le16(ctx->tx_seq);
+	ctx->tx_ncm.nth16.wBlockLength = cpu_to_le16(last_offset);
+	ctx->tx_ncm.nth16.wNdpIndex = ALIGN(sizeof(struct usb_cdc_ncm_nth16),
+							ctx->tx_ndp_modulus);
+
+	memcpy(skb_out->data, &(ctx->tx_ncm.nth16), sizeof(ctx->tx_ncm.nth16));
+	ctx->tx_seq++;
+
+	/* fill out 16-bit NDP table */
+	ctx->tx_ncm.ndp16.dwSignature =
+				cpu_to_le32(USB_CDC_NCM_NDP16_NOCRC_SIGN);
+	rem = sizeof(ctx->tx_ncm.ndp16) + ((ctx->tx_curr_frame_num + 1) *
+					sizeof(struct usb_cdc_ncm_dpe16));
+	ctx->tx_ncm.ndp16.wLength = cpu_to_le16(rem);
+	ctx->tx_ncm.ndp16.wNextNdpIndex = 0; /* reserved */
+
+	memcpy(((u8 *)skb_out->data) + ctx->tx_ncm.nth16.wNdpIndex,
+						&(ctx->tx_ncm.ndp16),
+						sizeof(ctx->tx_ncm.ndp16));
+
+	memcpy(((u8 *)skb_out->data) + ctx->tx_ncm.nth16.wNdpIndex +
+					sizeof(ctx->tx_ncm.ndp16),
+					&(ctx->tx_ncm.dpe16),
+					(ctx->tx_curr_frame_num + 1) *
+					sizeof(struct usb_cdc_ncm_dpe16));
+
+	/* set frame length */
+	skb_put(skb_out, last_offset);
+
+	/* return skb */
+	ctx->tx_curr_skb = NULL;
+	return skb_out;
+
+exit_no_skb:
+	return NULL;
+}
+
+static void cdc_ncm_tx_timeout_start(struct cdc_ncm_ctx *ctx)
+{
+	/* start timer, if not already started */
+	if (timer_pending(&ctx->tx_timer) == 0) {
+		ctx->tx_timer.function = &cdc_ncm_tx_timeout;
+		ctx->tx_timer.data = (unsigned long)ctx;
+		ctx->tx_timer.expires = jiffies + ((HZ + 999) / 1000);
+		add_timer(&ctx->tx_timer);
+	}
+}
+
+static void cdc_ncm_tx_timeout(unsigned long arg)
+{
+	struct cdc_ncm_ctx *ctx = (struct cdc_ncm_ctx *)arg;
+	u8 restart;
+
+	spin_lock(&ctx->mtx);
+	if (ctx->tx_timer_pending != 0) {
+		ctx->tx_timer_pending--;
+		restart = 1;
+	} else {
+		restart = 0;
+	}
+
+	spin_unlock(&ctx->mtx);
+
+	if (restart) {
+		spin_lock(&ctx->mtx);
+		cdc_ncm_tx_timeout_start(ctx);
+		spin_unlock(&ctx->mtx);
+	} else if (ctx->netdev != NULL) {
+		usbnet_start_xmit(NULL, ctx->netdev);
+	}
+}
+
+static struct sk_buff *
+cdc_ncm_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags)
+{
+	struct sk_buff *skb_out;
+	struct cdc_ncm_ctx *ctx = (struct cdc_ncm_ctx *)dev->data[0];
+	u8 need_timer = 0;
+
+	/*
+	 * The Ethernet API we are using does not support transmitting
+	 * multiple Ethernet frames in a single call. This driver will
+	 * accumulate multiple Ethernet frames and send out a larger
+	 * USB frame when the USB buffer is full or when a single jiffies
+	 * timeout happens.
+	 */
+	if (ctx == NULL)
+		goto error;
+
+	spin_lock(&ctx->mtx);
+	skb_out = cdc_ncm_fill_tx_frame(ctx, skb);
+	if (ctx->tx_curr_skb != NULL)
+		need_timer = 1;
+
+	/* Start timer, if there is a remaining skb */
+	if (need_timer)
+		cdc_ncm_tx_timeout_start(ctx);
+
+	if (skb_out)
+		dev->net->stats.tx_packets += ctx->tx_curr_frame_num;
+
+	spin_unlock(&ctx->mtx);
+	return skb_out;
+
+error:
+	if (skb != NULL)
+		dev_kfree_skb_any(skb);
+
+	return NULL;
+}
+
+static int cdc_ncm_rx_fixup(struct usbnet *dev, struct sk_buff *skb_in)
+{
+	struct sk_buff *skb;
+	struct cdc_ncm_ctx *ctx;
+	int sumlen;
+	int actlen;
+	int temp;
+	int nframes;
+	int x;
+	int offset;
+
+	ctx = (struct cdc_ncm_ctx *)dev->data[0];
+	if (ctx == NULL)
+		goto error;
+
+	actlen = skb_in->len;
+	sumlen = CDC_NCM_NTB_MAX_SIZE_RX;
+
+	if (actlen < (sizeof(ctx->rx_ncm.nth16) + sizeof(ctx->rx_ncm.ndp16))) {
+		pr_debug("frame too short\n");
+		goto error;
+	}
+
+	memcpy(&(ctx->rx_ncm.nth16), ((u8 *)skb_in->data),
+						sizeof(ctx->rx_ncm.nth16));
+
+	if (le32_to_cpu(ctx->rx_ncm.nth16.dwSignature) !=
+	    USB_CDC_NCM_NTH16_SIGN) {
+		pr_debug("invalid NTH16 signature <%u>\n",
+			 le32_to_cpu(ctx->rx_ncm.nth16.dwSignature));
+		goto error;
+	}
+
+	temp = le16_to_cpu(ctx->rx_ncm.nth16.wBlockLength);
+	if (temp > sumlen) {
+		pr_debug("unsupported NTB block length %u/%u\n", temp, sumlen);
+		goto error;
+	}
+
+	temp = le16_to_cpu(ctx->rx_ncm.nth16.wNdpIndex);
+	if ((temp + sizeof(ctx->rx_ncm.ndp16)) > actlen) {
+		pr_debug("invalid DPT16 index\n");
+		goto error;
+	}
+
+	memcpy(&(ctx->rx_ncm.ndp16), ((u8 *)skb_in->data) + temp,
+						sizeof(ctx->rx_ncm.ndp16));
+
+	if (le32_to_cpu(ctx->rx_ncm.ndp16.dwSignature) !=
+	    USB_CDC_NCM_NDP16_NOCRC_SIGN) {
+		pr_debug("invalid DPT16 signature <%u>\n",
+			 le32_to_cpu(ctx->rx_ncm.ndp16.dwSignature));
+		goto error;
+	}
+
+	if (le16_to_cpu(ctx->rx_ncm.ndp16.wLength) <
+	    USB_CDC_NCM_NDP16_LENGTH_MIN) {
+		pr_debug("invalid DPT16 length <%u>\n",
+			 le32_to_cpu(ctx->rx_ncm.ndp16.dwSignature));
+		goto error;
+	}
+
+	nframes = ((le16_to_cpu(ctx->rx_ncm.ndp16.wLength) -
+					sizeof(struct usb_cdc_ncm_ndp16)) /
+					sizeof(struct usb_cdc_ncm_dpe16));
+	nframes--; /* we process NDP entries except for the last one */
+
+	pr_debug("nframes = %u\n", nframes);
+
+	temp += sizeof(ctx->rx_ncm.ndp16);
+
+	if ((temp + nframes * (sizeof(struct usb_cdc_ncm_dpe16))) > actlen) {
+		pr_debug("Invalid nframes = %d\n", nframes);
+		goto error;
+	}
+
+	if (nframes > CDC_NCM_DPT_DATAGRAMS_MAX) {
+		pr_debug("Truncating number of frames from %u to %u\n",
+					nframes, CDC_NCM_DPT_DATAGRAMS_MAX);
+		nframes = CDC_NCM_DPT_DATAGRAMS_MAX;
+	}
+
+	memcpy(&(ctx->rx_ncm.dpe16), ((u8 *)skb_in->data) + temp,
+				nframes * (sizeof(struct usb_cdc_ncm_dpe16)));
+
+	for (x = 0; x < nframes; x++) {
+		offset = le16_to_cpu(ctx->rx_ncm.dpe16[x].wDatagramIndex);
+		temp = le16_to_cpu(ctx->rx_ncm.dpe16[x].wDatagramLength);
+
+		/*
+		 * CDC NCM ch. 3.7
+		 * All entries after first NULL entry are to be ignored
+		 */
+		if ((offset == 0) || (temp == 0)) {
+			if (!x)
+				goto error; /* empty NTB */
+			break;
+		}
+
+		/* sanity checking */
+		if (((offset + temp) > actlen) ||
+		    (temp > CDC_NCM_MAX_DATAGRAM_SIZE) || (temp < ETH_HLEN)) {
+			pr_debug("invalid frame detected (ignored)"
+					"offset[%u]=%u, length=%u, skb=%p\n",
+					x, offset, temp, skb_in);
+			if (!x)
+				goto error;
+			break;
+
+		} else {
+			skb = skb_clone(skb_in, GFP_ATOMIC);
+			if (!skb)
+				goto error;
+			skb->len = temp;
+			skb->data = ((u8 *)skb_in->data) + offset;
+			skb_set_tail_pointer(skb, temp);
+			usbnet_skb_return(dev, skb);
+		}
+	}
+	return 1;
+error:
+	return 0;
+}
+
+static void
+cdc_ncm_speed_change(struct cdc_ncm_ctx *ctx,
+		     struct usb_cdc_speed_change *data)
+{
+	uint32_t rx_speed = le32_to_cpu(data->DLBitRRate);
+	uint32_t tx_speed = le32_to_cpu(data->ULBitRate);
+
+	/*
+	 * Currently the USB-NET API does not support reporting the actual
+	 * device speed. Do print it instead.
+	 */
+	if ((tx_speed != ctx->tx_speed) || (rx_speed != ctx->rx_speed)) {
+		ctx->tx_speed = tx_speed;
+		ctx->rx_speed = rx_speed;
+
+		if ((tx_speed > 1000000) && (rx_speed > 1000000)) {
+			printk(KERN_INFO KBUILD_MODNAME
+				": %s: %u mbit/s downlink "
+				"%u mbit/s uplink\n",
+				ctx->netdev->name,
+				(unsigned int)(rx_speed / 1000000U),
+				(unsigned int)(tx_speed / 1000000U));
+		} else {
+			printk(KERN_INFO KBUILD_MODNAME
+				": %s: %u kbit/s downlink "
+				"%u kbit/s uplink\n",
+				ctx->netdev->name,
+				(unsigned int)(rx_speed / 1000U),
+				(unsigned int)(tx_speed / 1000U));
+		}
+	}
+}
+
+static void cdc_ncm_status(struct usbnet *dev, struct urb *urb)
+{
+	struct cdc_ncm_ctx *ctx;
+	struct usb_cdc_notification *event;
+
+	ctx = (struct cdc_ncm_ctx *)dev->data[0];
+
+	if (urb->actual_length < sizeof(*event))
+		return;
+
+	/* test for split data in 8-byte chunks */
+	if (test_and_clear_bit(EVENT_STS_SPLIT, &dev->flags)) {
+		cdc_ncm_speed_change(ctx,
+		      (struct usb_cdc_speed_change *)urb->transfer_buffer);
+		return;
+	}
+
+	event = urb->transfer_buffer;
+
+	switch (event->bNotificationType) {
+	case USB_CDC_NOTIFY_NETWORK_CONNECTION:
+		/*
+		 * According to the CDC NCM specification ch.7.1
+		 * USB_CDC_NOTIFY_NETWORK_CONNECTION notification shall be
+		 * sent by device after USB_CDC_NOTIFY_SPEED_CHANGE.
+		 */
+		ctx->connected = event->wValue;
+
+		printk(KERN_INFO KBUILD_MODNAME ": %s: network connection:"
+			" %sconnected\n",
+			ctx->netdev->name, ctx->connected ? "" : "dis");
+
+		if (ctx->connected)
+			netif_carrier_on(dev->net);
+		else {
+			netif_carrier_off(dev->net);
+			ctx->tx_speed = ctx->rx_speed = 0;
+		}
+		break;
+
+	case USB_CDC_NOTIFY_SPEED_CHANGE:
+		if (urb->actual_length < (sizeof(*event) +
+					sizeof(struct usb_cdc_speed_change)))
+			set_bit(EVENT_STS_SPLIT, &dev->flags);
+		else
+			cdc_ncm_speed_change(ctx,
+				(struct usb_cdc_speed_change *) &event[1]);
+		break;
+
+	default:
+		dev_err(&dev->udev->dev, "NCM: unexpected "
+			"notification 0x%02x!\n", event->bNotificationType);
+		break;
+	}
+}
+
+static int cdc_ncm_check_connect(struct usbnet *dev)
+{
+	struct cdc_ncm_ctx *ctx;
+
+	ctx = (struct cdc_ncm_ctx *)dev->data[0];
+	if (ctx == NULL)
+		return 1;	/* disconnected */
+
+	return !ctx->connected;
+}
+
+static int
+cdc_ncm_probe(struct usb_interface *udev, const struct usb_device_id *prod)
+{
+	return usbnet_probe(udev, prod);
+}
+
+static void cdc_ncm_disconnect(struct usb_interface *intf)
+{
+	struct usbnet *dev = usb_get_intfdata(intf);
+
+	if (dev == NULL)
+		return;		/* already disconnected */
+
+	usbnet_disconnect(intf);
+}
+
+static int cdc_ncm_manage_power(struct usbnet *dev, int status)
+{
+	dev->intf->needs_remote_wakeup = status;
+	return 0;
+}
+
+static const struct driver_info cdc_ncm_info = {
+	.description = "CDC NCM",
+	.flags = FLAG_NO_SETINT | FLAG_MULTI_PACKET,
+	.bind = cdc_ncm_bind,
+	.unbind = cdc_ncm_unbind,
+	.check_connect = cdc_ncm_check_connect,
+	.manage_power = cdc_ncm_manage_power,
+	.status = cdc_ncm_status,
+	.rx_fixup = cdc_ncm_rx_fixup,
+	.tx_fixup = cdc_ncm_tx_fixup,
+};
+
+static struct usb_driver cdc_ncm_driver = {
+	.name = "cdc_ncm",
+	.id_table = cdc_devs,
+	.probe = cdc_ncm_probe,
+	.disconnect = cdc_ncm_disconnect,
+	.suspend = usbnet_suspend,
+	.resume = usbnet_resume,
+	.supports_autosuspend = 1,
+};
+
+static struct ethtool_ops cdc_ncm_ethtool_ops = {
+	.get_drvinfo = cdc_ncm_get_drvinfo,
+	.get_link = usbnet_get_link,
+	.get_msglevel = usbnet_get_msglevel,
+	.set_msglevel = usbnet_set_msglevel,
+	.get_settings = usbnet_get_settings,
+	.set_settings = usbnet_set_settings,
+	.nway_reset = usbnet_nway_reset,
+};
+
+static int __init cdc_ncm_init(void)
+{
+	printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION "\n");
+	return usb_register(&cdc_ncm_driver);
+}
+
+module_init(cdc_ncm_init);
+
+static void __exit cdc_ncm_exit(void)
+{
+	usb_deregister(&cdc_ncm_driver);
+}
+
+module_exit(cdc_ncm_exit);
+
+MODULE_AUTHOR("Hans Petter Selasky");
+MODULE_DESCRIPTION("USB CDC NCM host driver");
+MODULE_LICENSE("Dual BSD/GPL");
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/usb/dm9601.c linux-libre-2.6.38-gnu1/drivers/net/usb/dm9601.c
--- linux-libre-2.6.37-gnu1/drivers/net/usb/dm9601.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/usb/dm9601.c	2011-03-14 21:20:32.000000000 -0400
@@ -651,6 +651,10 @@ static const struct usb_device_id produc
 	.driver_info = (unsigned long)&dm9601_info,
 	 },
 	{
+	 USB_DEVICE(0x0fe6, 0x9700),	/* DM9601 USB to Fast Ethernet Adapter */
+	 .driver_info = (unsigned long)&dm9601_info,
+	 },
+	{
 	 USB_DEVICE(0x0a46, 0x9000),	/* DM9000E */
 	 .driver_info = (unsigned long)&dm9601_info,
 	 },
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/usb/hso.c linux-libre-2.6.38-gnu1/drivers/net/usb/hso.c
--- linux-libre-2.6.37-gnu1/drivers/net/usb/hso.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/usb/hso.c	2011-03-14 21:20:32.000000000 -0400
@@ -997,6 +997,18 @@ static void packetizeRx(struct hso_net *
 	}
 }
 
+static void fix_crc_bug(struct urb *urb, __le16 max_packet_size)
+{
+	static const u8 crc_check[4] = { 0xDE, 0xAD, 0xBE, 0xEF };
+	u32 rest = urb->actual_length % le16_to_cpu(max_packet_size);
+
+	if (((rest == 5) || (rest == 6)) &&
+	    !memcmp(((u8 *)urb->transfer_buffer) + urb->actual_length - 4,
+		    crc_check, 4)) {
+		urb->actual_length -= 4;
+	}
+}
+
 /* Moving data from usb to kernel (in interrupt state) */
 static void read_bulk_callback(struct urb *urb)
 {
@@ -1025,17 +1037,8 @@ static void read_bulk_callback(struct ur
 		return;
 	}
 
-	if (odev->parent->port_spec & HSO_INFO_CRC_BUG) {
-		u32 rest;
-		u8 crc_check[4] = { 0xDE, 0xAD, 0xBE, 0xEF };
-		rest = urb->actual_length %
-			le16_to_cpu(odev->in_endp->wMaxPacketSize);
-		if (((rest == 5) || (rest == 6)) &&
-		    !memcmp(((u8 *) urb->transfer_buffer) +
-			    urb->actual_length - 4, crc_check, 4)) {
-			urb->actual_length -= 4;
-		}
-	}
+	if (odev->parent->port_spec & HSO_INFO_CRC_BUG)
+		fix_crc_bug(urb, odev->in_endp->wMaxPacketSize);
 
 	/* do we even have a packet? */
 	if (urb->actual_length) {
@@ -1227,18 +1230,8 @@ static void hso_std_serial_read_bulk_cal
 		return;
 
 	if (status == 0) {
-		if (serial->parent->port_spec & HSO_INFO_CRC_BUG) {
-			u32 rest;
-			u8 crc_check[4] = { 0xDE, 0xAD, 0xBE, 0xEF };
-			rest =
-			    urb->actual_length %
-			    le16_to_cpu(serial->in_endp->wMaxPacketSize);
-			if (((rest == 5) || (rest == 6)) &&
-			    !memcmp(((u8 *) urb->transfer_buffer) +
-				    urb->actual_length - 4, crc_check, 4)) {
-				urb->actual_length -= 4;
-			}
-		}
+		if (serial->parent->port_spec & HSO_INFO_CRC_BUG)
+			fix_crc_bug(urb, serial->in_endp->wMaxPacketSize);
 		/* Valid data, handle RX data */
 		spin_lock(&serial->serial_lock);
 		serial->rx_urb_filled[hso_urb_to_index(serial, urb)] = 1;
@@ -1741,7 +1734,6 @@ static int hso_serial_ioctl(struct tty_s
 			    unsigned int cmd, unsigned long arg)
 {
 	struct hso_serial *serial =  get_serial_by_tty(tty);
-	void __user *uarg = (void __user *)arg;
 	int ret = 0;
 	D4("IOCTL cmd: %d, arg: %ld", cmd, arg);
 
@@ -2636,15 +2628,15 @@ exit:
 
 static void hso_free_tiomget(struct hso_serial *serial)
 {
-	struct hso_tiocmget *tiocmget = serial->tiocmget;
+	struct hso_tiocmget *tiocmget;
+	if (!serial)
+		return;
+	tiocmget = serial->tiocmget;
 	if (tiocmget) {
-		if (tiocmget->urb) {
-			usb_free_urb(tiocmget->urb);
-			tiocmget->urb = NULL;
-		}
+		usb_free_urb(tiocmget->urb);
+		tiocmget->urb = NULL;
 		serial->tiocmget = NULL;
 		kfree(tiocmget);
-
 	}
 }
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/usb/ipheth.c linux-libre-2.6.38-gnu1/drivers/net/usb/ipheth.c
--- linux-libre-2.6.37-gnu1/drivers/net/usb/ipheth.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/usb/ipheth.c	2011-03-14 21:20:32.000000000 -0400
@@ -363,7 +363,7 @@ static int ipheth_tx(struct sk_buff *skb
 
 	/* Paranoid */
 	if (skb->len > IPHETH_BUF_SIZE) {
-		WARN(1, "%s: skb too large: %d bytes", __func__, skb->len);
+		WARN(1, "%s: skb too large: %d bytes\n", __func__, skb->len);
 		dev->net->stats.tx_dropped++;
 		dev_kfree_skb_irq(skb);
 		return NETDEV_TX_OK;
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/usb/kaweth.c linux-libre-2.6.38-gnu1/drivers/net/usb/kaweth.c
--- linux-libre-2.6.37-gnu1/drivers/net/usb/kaweth.c	2013-05-03 03:59:44.000000000 -0400
+++ linux-libre-2.6.38-gnu1/drivers/net/usb/kaweth.c	2013-05-03 02:00:00.000000000 -0400
@@ -403,6 +403,7 @@ static int kaweth_download_firmware(stru
 
 	if (fw->size > KAWETH_FIRMWARE_BUF_SIZE) {
 		err("Firmware too big: %zu", fw->size);
+		release_firmware(fw);
 		return -ENOSPC;
 	}
 	data_len = fw->size;
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/usb/Kconfig linux-libre-2.6.38-gnu1/drivers/net/usb/Kconfig
--- linux-libre-2.6.37-gnu1/drivers/net/usb/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/usb/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -196,6 +196,25 @@ config USB_NET_CDC_EEM
 	  IEEE 802 "local assignment" bit is set in the address, a "usbX"
 	  name is used instead.
 
+config USB_NET_CDC_NCM
+	tristate "CDC NCM support"
+	depends on USB_USBNET
+	default y
+	help
+	  This driver provides support for CDC NCM (Network Control Model
+	  Device USB Class Specification). The CDC NCM specification is
+	  available from <http://www.usb.org/>.
+
+	  Say "y" to link the driver statically, or "m" to build a
+	  dynamically linked module.
+
+	  This driver should work with at least the following devices:
+	    * ST-Ericsson M700 LTE FDD/TDD Mobile Broadband Modem (ref. design)
+	    * ST-Ericsson M5730 HSPA+ Mobile Broadband Modem (reference design)
+	    * ST-Ericsson M570 HSPA+ Mobile Broadband Modem (reference design)
+	    * ST-Ericsson M343 HSPA Mobile Broadband Modem (reference design)
+	    * Ericsson F5521gw Mobile Broadband Module
+
 config USB_NET_DM9601
 	tristate "Davicom DM9601 based USB 1.1 10/100 ethernet devices"
 	depends on USB_USBNET
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/usb/Makefile linux-libre-2.6.38-gnu1/drivers/net/usb/Makefile
--- linux-libre-2.6.37-gnu1/drivers/net/usb/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/usb/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -26,4 +26,5 @@ obj-$(CONFIG_USB_CDC_PHONET)	+= cdc-phon
 obj-$(CONFIG_USB_IPHETH)	+= ipheth.o
 obj-$(CONFIG_USB_SIERRA_NET)	+= sierra_net.o
 obj-$(CONFIG_USB_NET_CX82310_ETH)	+= cx82310_eth.o
+obj-$(CONFIG_USB_NET_CDC_NCM)	+= cdc_ncm.o
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/usb/pegasus.c linux-libre-2.6.38-gnu1/drivers/net/usb/pegasus.c
--- linux-libre-2.6.37-gnu1/drivers/net/usb/pegasus.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/usb/pegasus.c	2011-03-14 21:20:32.000000000 -0400
@@ -359,7 +359,7 @@ fail:
 
 static int mdio_read(struct net_device *dev, int phy_id, int loc)
 {
-	pegasus_t *pegasus = (pegasus_t *) netdev_priv(dev);
+	pegasus_t *pegasus = netdev_priv(dev);
 	u16 res;
 
 	read_mii_word(pegasus, phy_id, loc, &res);
@@ -397,7 +397,7 @@ fail:
 
 static void mdio_write(struct net_device *dev, int phy_id, int loc, int val)
 {
-	pegasus_t *pegasus = (pegasus_t *) netdev_priv(dev);
+	pegasus_t *pegasus = netdev_priv(dev);
 
 	write_mii_word(pegasus, phy_id, loc, val);
 }
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/usb/sierra_net.c linux-libre-2.6.38-gnu1/drivers/net/usb/sierra_net.c
--- linux-libre-2.6.37-gnu1/drivers/net/usb/sierra_net.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/usb/sierra_net.c	2011-03-14 21:20:32.000000000 -0400
@@ -802,10 +802,9 @@ static void sierra_net_unbind(struct usb
 
 	dev_dbg(&dev->udev->dev, "%s", __func__);
 
-	/* Kill the timer then flush the work queue */
+	/* kill the timer and work */
 	del_timer_sync(&priv->sync_timer);
-
-	flush_scheduled_work();
+	cancel_work_sync(&priv->sierra_net_kevent);
 
 	/* tell modem we are going away */
 	status = sierra_net_send_cmd(dev, priv->shdwn_msg,
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/usb/smsc95xx.c linux-libre-2.6.38-gnu1/drivers/net/usb/smsc95xx.c
--- linux-libre-2.6.37-gnu1/drivers/net/usb/smsc95xx.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/usb/smsc95xx.c	2011-03-14 21:20:32.000000000 -0400
@@ -1163,9 +1163,8 @@ static int smsc95xx_rx_fixup(struct usbn
 
 static u32 smsc95xx_calc_csum_preamble(struct sk_buff *skb)
 {
-	int len = skb->data - skb->head;
-	u16 high_16 = (u16)(skb->csum_offset + skb->csum_start - len);
-	u16 low_16 = (u16)(skb->csum_start - len);
+	u16 low_16 = (u16)skb_checksum_start_offset(skb);
+	u16 high_16 = low_16 + skb->csum_offset;
 	return (high_16 << 16) | low_16;
 }
 
@@ -1193,7 +1192,7 @@ static struct sk_buff *smsc95xx_tx_fixup
 		if (skb->len <= 45) {
 			/* workaround - hardware tx checksum does not work
 			 * properly with extremely small packets */
-			long csstart = skb->csum_start - skb_headroom(skb);
+			long csstart = skb_checksum_start_offset(skb);
 			__wsum calc = csum_partial(skb->data + csstart,
 				skb->len - csstart, 0);
 			*((__sum16 *)(skb->data + csstart
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/usb/usbnet.c linux-libre-2.6.38-gnu1/drivers/net/usb/usbnet.c
--- linux-libre-2.6.37-gnu1/drivers/net/usb/usbnet.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/usb/usbnet.c	2011-03-14 21:20:32.000000000 -0400
@@ -391,14 +391,19 @@ static inline void rx_process (struct us
 		goto error;
 	// else network stack removes extra byte if we forced a short packet
 
-	if (skb->len)
-		usbnet_skb_return (dev, skb);
-	else {
-		netif_dbg(dev, rx_err, dev->net, "drop\n");
-error:
-		dev->net->stats.rx_errors++;
-		skb_queue_tail (&dev->done, skb);
+	if (skb->len) {
+		/* all data was already cloned from skb inside the driver */
+		if (dev->driver_info->flags & FLAG_MULTI_PACKET)
+			dev_kfree_skb_any(skb);
+		else
+			usbnet_skb_return(dev, skb);
+		return;
 	}
+
+	netif_dbg(dev, rx_err, dev->net, "drop\n");
+error:
+	dev->net->stats.rx_errors++;
+	skb_queue_tail(&dev->done, skb);
 }
 
 /*-------------------------------------------------------------------------*/
@@ -926,8 +931,10 @@ fail_halt:
 		if (urb != NULL) {
 			clear_bit (EVENT_RX_MEMORY, &dev->flags);
 			status = usb_autopm_get_interface(dev->intf);
-			if (status < 0)
+			if (status < 0) {
+				usb_free_urb(urb);
 				goto fail_lowmem;
+			}
 			if (rx_submit (dev, urb, GFP_KERNEL) == -ENOLINK)
 				resched = 0;
 			usb_autopm_put_interface(dev->intf);
@@ -971,7 +978,8 @@ static void tx_complete (struct urb *urb
 	struct usbnet		*dev = entry->dev;
 
 	if (urb->status == 0) {
-		dev->net->stats.tx_packets++;
+		if (!(dev->driver_info->flags & FLAG_MULTI_PACKET))
+			dev->net->stats.tx_packets++;
 		dev->net->stats.tx_bytes += entry->length;
 	} else {
 		dev->net->stats.tx_errors++;
@@ -1044,8 +1052,13 @@ netdev_tx_t usbnet_start_xmit (struct sk
 	if (info->tx_fixup) {
 		skb = info->tx_fixup (dev, skb, GFP_ATOMIC);
 		if (!skb) {
-			netif_dbg(dev, tx_err, dev->net, "can't tx_fixup skb\n");
-			goto drop;
+			if (netif_msg_tx_err(dev)) {
+				netif_dbg(dev, tx_err, dev->net, "can't tx_fixup skb\n");
+				goto drop;
+			} else {
+				/* cdc_ncm collected packet; waits for more */
+				goto not_drop;
+			}
 		}
 	}
 	length = skb->len;
@@ -1067,13 +1080,18 @@ netdev_tx_t usbnet_start_xmit (struct sk
 	/* don't assume the hardware handles USB_ZERO_PACKET
 	 * NOTE:  strictly conforming cdc-ether devices should expect
 	 * the ZLP here, but ignore the one-byte packet.
+	 * NOTE2: CDC NCM specification is different from CDC ECM when
+	 * handling ZLP/short packets, so cdc_ncm driver will make short
+	 * packet itself if needed.
 	 */
 	if (length % dev->maxpacket == 0) {
 		if (!(info->flags & FLAG_SEND_ZLP)) {
-			urb->transfer_buffer_length++;
-			if (skb_tailroom(skb)) {
-				skb->data[skb->len] = 0;
-				__skb_put(skb, 1);
+			if (!(info->flags & FLAG_MULTI_PACKET)) {
+				urb->transfer_buffer_length++;
+				if (skb_tailroom(skb)) {
+					skb->data[skb->len] = 0;
+					__skb_put(skb, 1);
+				}
 			}
 		} else
 			urb->transfer_flags |= URB_ZERO_PACKET;
@@ -1122,6 +1140,7 @@ netdev_tx_t usbnet_start_xmit (struct sk
 		netif_dbg(dev, tx_err, dev->net, "drop, code %d\n", retval);
 drop:
 		dev->net->stats.tx_dropped++;
+not_drop:
 		if (skb)
 			dev_kfree_skb_any (skb);
 		usb_free_urb (urb);
@@ -1231,8 +1250,7 @@ void usbnet_disconnect (struct usb_inter
 	net = dev->net;
 	unregister_netdev (net);
 
-	/* we don't hold rtnl here ... */
-	flush_scheduled_work ();
+	cancel_work_sync(&dev->kevent);
 
 	if (dev->driver_info->unbind)
 		dev->driver_info->unbind (dev, intf);
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/via-rhine.c linux-libre-2.6.38-gnu1/drivers/net/via-rhine.c
--- linux-libre-2.6.37-gnu1/drivers/net/via-rhine.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/via-rhine.c	2011-03-14 21:20:32.000000000 -0400
@@ -30,8 +30,8 @@
 */
 
 #define DRV_NAME	"via-rhine"
-#define DRV_VERSION	"1.4.3"
-#define DRV_RELDATE	"2007-03-06"
+#define DRV_VERSION	"1.5.0"
+#define DRV_RELDATE	"2010-10-09"
 
 
 /* A few user-configurable values.
@@ -100,6 +100,7 @@ static const int multicast_filter_limit
 #include <linux/mii.h>
 #include <linux/ethtool.h>
 #include <linux/crc32.h>
+#include <linux/if_vlan.h>
 #include <linux/bitops.h>
 #include <linux/workqueue.h>
 #include <asm/processor.h>	/* Processor type for cache alignment. */
@@ -133,6 +134,9 @@ MODULE_PARM_DESC(debug, "VIA Rhine debug
 MODULE_PARM_DESC(rx_copybreak, "VIA Rhine copy breakpoint for copy-only-tiny-frames");
 MODULE_PARM_DESC(avoid_D3, "Avoid power state D3 (work-around for broken BIOSes)");
 
+#define MCAM_SIZE	32
+#define VCAM_SIZE	32
+
 /*
 		Theory of Operation
 
@@ -279,15 +283,16 @@ MODULE_DEVICE_TABLE(pci, rhine_pci_tbl);
 /* Offsets to the device registers. */
 enum register_offsets {
 	StationAddr=0x00, RxConfig=0x06, TxConfig=0x07, ChipCmd=0x08,
-	ChipCmd1=0x09,
+	ChipCmd1=0x09, TQWake=0x0A,
 	IntrStatus=0x0C, IntrEnable=0x0E,
 	MulticastFilter0=0x10, MulticastFilter1=0x14,
 	RxRingPtr=0x18, TxRingPtr=0x1C, GFIFOTest=0x54,
-	MIIPhyAddr=0x6C, MIIStatus=0x6D, PCIBusConfig=0x6E,
+	MIIPhyAddr=0x6C, MIIStatus=0x6D, PCIBusConfig=0x6E, PCIBusConfig1=0x6F,
 	MIICmd=0x70, MIIRegAddr=0x71, MIIData=0x72, MACRegEEcsr=0x74,
 	ConfigA=0x78, ConfigB=0x79, ConfigC=0x7A, ConfigD=0x7B,
 	RxMissed=0x7C, RxCRCErrs=0x7E, MiscCmd=0x81,
 	StickyHW=0x83, IntrStatus2=0x84,
+	CamMask=0x88, CamCon=0x92, CamAddr=0x93,
 	WOLcrSet=0xA0, PwcfgSet=0xA1, WOLcgSet=0xA3, WOLcrClr=0xA4,
 	WOLcrClr1=0xA6, WOLcgClr=0xA7,
 	PwrcsrSet=0xA8, PwrcsrSet1=0xA9, PwrcsrClr=0xAC, PwrcsrClr1=0xAD,
@@ -299,6 +304,40 @@ enum backoff_bits {
 	BackCaptureEffect=0x04, BackRandom=0x08
 };
 
+/* Bits in the TxConfig (TCR) register */
+enum tcr_bits {
+	TCR_PQEN=0x01,
+	TCR_LB0=0x02,		/* loopback[0] */
+	TCR_LB1=0x04,		/* loopback[1] */
+	TCR_OFSET=0x08,
+	TCR_RTGOPT=0x10,
+	TCR_RTFT0=0x20,
+	TCR_RTFT1=0x40,
+	TCR_RTSF=0x80,
+};
+
+/* Bits in the CamCon (CAMC) register */
+enum camcon_bits {
+	CAMC_CAMEN=0x01,
+	CAMC_VCAMSL=0x02,
+	CAMC_CAMWR=0x04,
+	CAMC_CAMRD=0x08,
+};
+
+/* Bits in the PCIBusConfig1 (BCR1) register */
+enum bcr1_bits {
+	BCR1_POT0=0x01,
+	BCR1_POT1=0x02,
+	BCR1_POT2=0x04,
+	BCR1_CTFT0=0x08,
+	BCR1_CTFT1=0x10,
+	BCR1_CTSF=0x20,
+	BCR1_TXQNOBK=0x40,	/* for VT6105 */
+	BCR1_VIDFR=0x80,	/* for VT6105 */
+	BCR1_MED0=0x40,		/* for VT6102 */
+	BCR1_MED1=0x80,		/* for VT6102 */
+};
+
 #ifdef USE_MMIO
 /* Registers we check that mmio and reg are the same. */
 static const int mmio_verify_registers[] = {
@@ -356,6 +395,11 @@ enum desc_status_bits {
 	DescOwn=0x80000000
 };
 
+/* Bits in *_desc.*_length */
+enum desc_length_bits {
+	DescTag=0x00010000
+};
+
 /* Bits in ChipCmd. */
 enum chip_cmd_bits {
 	CmdInit=0x01, CmdStart=0x02, CmdStop=0x04, CmdRxOn=0x08,
@@ -365,6 +409,9 @@ enum chip_cmd_bits {
 };
 
 struct rhine_private {
+	/* Bit mask for configured VLAN ids */
+	unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
+
 	/* Descriptor rings */
 	struct rx_desc *rx_ring;
 	struct tx_desc *tx_ring;
@@ -405,6 +452,23 @@ struct rhine_private {
 	void __iomem *base;
 };
 
+#define BYTE_REG_BITS_ON(x, p)      do { iowrite8((ioread8((p))|(x)), (p)); } while (0)
+#define WORD_REG_BITS_ON(x, p)      do { iowrite16((ioread16((p))|(x)), (p)); } while (0)
+#define DWORD_REG_BITS_ON(x, p)     do { iowrite32((ioread32((p))|(x)), (p)); } while (0)
+
+#define BYTE_REG_BITS_IS_ON(x, p)   (ioread8((p)) & (x))
+#define WORD_REG_BITS_IS_ON(x, p)   (ioread16((p)) & (x))
+#define DWORD_REG_BITS_IS_ON(x, p)  (ioread32((p)) & (x))
+
+#define BYTE_REG_BITS_OFF(x, p)     do { iowrite8(ioread8((p)) & (~(x)), (p)); } while (0)
+#define WORD_REG_BITS_OFF(x, p)     do { iowrite16(ioread16((p)) & (~(x)), (p)); } while (0)
+#define DWORD_REG_BITS_OFF(x, p)    do { iowrite32(ioread32((p)) & (~(x)), (p)); } while (0)
+
+#define BYTE_REG_BITS_SET(x, m, p)   do { iowrite8((ioread8((p)) & (~(m)))|(x), (p)); } while (0)
+#define WORD_REG_BITS_SET(x, m, p)   do { iowrite16((ioread16((p)) & (~(m)))|(x), (p)); } while (0)
+#define DWORD_REG_BITS_SET(x, m, p)  do { iowrite32((ioread32((p)) & (~(m)))|(x), (p)); } while (0)
+
+
 static int  mdio_read(struct net_device *dev, int phy_id, int location);
 static void mdio_write(struct net_device *dev, int phy_id, int location, int value);
 static int  rhine_open(struct net_device *dev);
@@ -422,6 +486,14 @@ static int netdev_ioctl(struct net_devic
 static const struct ethtool_ops netdev_ethtool_ops;
 static int  rhine_close(struct net_device *dev);
 static void rhine_shutdown (struct pci_dev *pdev);
+static void rhine_vlan_rx_add_vid(struct net_device *dev, unsigned short vid);
+static void rhine_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid);
+static void rhine_set_cam(void __iomem *ioaddr, int idx, u8 *addr);
+static void rhine_set_vlan_cam(void __iomem *ioaddr, int idx, u8 *addr);
+static void rhine_set_cam_mask(void __iomem *ioaddr, u32 mask);
+static void rhine_set_vlan_cam_mask(void __iomem *ioaddr, u32 mask);
+static void rhine_init_cam_filter(struct net_device *dev);
+static void rhine_update_vcam(struct net_device *dev);
 
 #define RHINE_WAIT_FOR(condition) do {					\
 	int i=1024;							\
@@ -629,6 +701,8 @@ static const struct net_device_ops rhine
 	.ndo_set_mac_address 	 = eth_mac_addr,
 	.ndo_do_ioctl		 = netdev_ioctl,
 	.ndo_tx_timeout 	 = rhine_tx_timeout,
+	.ndo_vlan_rx_add_vid	 = rhine_vlan_rx_add_vid,
+	.ndo_vlan_rx_kill_vid	 = rhine_vlan_rx_kill_vid,
 #ifdef CONFIG_NET_POLL_CONTROLLER
 	.ndo_poll_controller	 = rhine_poll,
 #endif
@@ -795,6 +869,10 @@ static int __devinit rhine_init_one(stru
 	if (rp->quirks & rqRhineI)
 		dev->features |= NETIF_F_SG|NETIF_F_HW_CSUM;
 
+	if (pdev->revision >= VT6105M)
+		dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX |
+		NETIF_F_HW_VLAN_FILTER;
+
 	/* dev->name not defined before register_netdev()! */
 	rc = register_netdev(dev);
 	if (rc)
@@ -1040,6 +1118,167 @@ static void rhine_set_carrier(struct mii
 		       netif_carrier_ok(mii->dev));
 }
 
+/**
+ * rhine_set_cam - set CAM multicast filters
+ * @ioaddr: register block of this Rhine
+ * @idx: multicast CAM index [0..MCAM_SIZE-1]
+ * @addr: multicast address (6 bytes)
+ *
+ * Load addresses into multicast filters.
+ */
+static void rhine_set_cam(void __iomem *ioaddr, int idx, u8 *addr)
+{
+	int i;
+
+	iowrite8(CAMC_CAMEN, ioaddr + CamCon);
+	wmb();
+
+	/* Paranoid -- idx out of range should never happen */
+	idx &= (MCAM_SIZE - 1);
+
+	iowrite8((u8) idx, ioaddr + CamAddr);
+
+	for (i = 0; i < 6; i++, addr++)
+		iowrite8(*addr, ioaddr + MulticastFilter0 + i);
+	udelay(10);
+	wmb();
+
+	iowrite8(CAMC_CAMWR | CAMC_CAMEN, ioaddr + CamCon);
+	udelay(10);
+
+	iowrite8(0, ioaddr + CamCon);
+}
+
+/**
+ * rhine_set_vlan_cam - set CAM VLAN filters
+ * @ioaddr: register block of this Rhine
+ * @idx: VLAN CAM index [0..VCAM_SIZE-1]
+ * @addr: VLAN ID (2 bytes)
+ *
+ * Load addresses into VLAN filters.
+ */
+static void rhine_set_vlan_cam(void __iomem *ioaddr, int idx, u8 *addr)
+{
+	iowrite8(CAMC_CAMEN | CAMC_VCAMSL, ioaddr + CamCon);
+	wmb();
+
+	/* Paranoid -- idx out of range should never happen */
+	idx &= (VCAM_SIZE - 1);
+
+	iowrite8((u8) idx, ioaddr + CamAddr);
+
+	iowrite16(*((u16 *) addr), ioaddr + MulticastFilter0 + 6);
+	udelay(10);
+	wmb();
+
+	iowrite8(CAMC_CAMWR | CAMC_CAMEN, ioaddr + CamCon);
+	udelay(10);
+
+	iowrite8(0, ioaddr + CamCon);
+}
+
+/**
+ * rhine_set_cam_mask - set multicast CAM mask
+ * @ioaddr: register block of this Rhine
+ * @mask: multicast CAM mask
+ *
+ * Mask sets multicast filters active/inactive.
+ */
+static void rhine_set_cam_mask(void __iomem *ioaddr, u32 mask)
+{
+	iowrite8(CAMC_CAMEN, ioaddr + CamCon);
+	wmb();
+
+	/* write mask */
+	iowrite32(mask, ioaddr + CamMask);
+
+	/* disable CAMEN */
+	iowrite8(0, ioaddr + CamCon);
+}
+
+/**
+ * rhine_set_vlan_cam_mask - set VLAN CAM mask
+ * @ioaddr: register block of this Rhine
+ * @mask: VLAN CAM mask
+ *
+ * Mask sets VLAN filters active/inactive.
+ */
+static void rhine_set_vlan_cam_mask(void __iomem *ioaddr, u32 mask)
+{
+	iowrite8(CAMC_CAMEN | CAMC_VCAMSL, ioaddr + CamCon);
+	wmb();
+
+	/* write mask */
+	iowrite32(mask, ioaddr + CamMask);
+
+	/* disable CAMEN */
+	iowrite8(0, ioaddr + CamCon);
+}
+
+/**
+ * rhine_init_cam_filter - initialize CAM filters
+ * @dev: network device
+ *
+ * Initialize (disable) hardware VLAN and multicast support on this
+ * Rhine.
+ */
+static void rhine_init_cam_filter(struct net_device *dev)
+{
+	struct rhine_private *rp = netdev_priv(dev);
+	void __iomem *ioaddr = rp->base;
+
+	/* Disable all CAMs */
+	rhine_set_vlan_cam_mask(ioaddr, 0);
+	rhine_set_cam_mask(ioaddr, 0);
+
+	/* disable hardware VLAN support */
+	BYTE_REG_BITS_ON(TCR_PQEN, ioaddr + TxConfig);
+	BYTE_REG_BITS_OFF(BCR1_VIDFR, ioaddr + PCIBusConfig1);
+}
+
+/**
+ * rhine_update_vcam - update VLAN CAM filters
+ * @rp: rhine_private data of this Rhine
+ *
+ * Update VLAN CAM filters to match configuration change.
+ */
+static void rhine_update_vcam(struct net_device *dev)
+{
+	struct rhine_private *rp = netdev_priv(dev);
+	void __iomem *ioaddr = rp->base;
+	u16 vid;
+	u32 vCAMmask = 0;	/* 32 vCAMs (6105M and better) */
+	unsigned int i = 0;
+
+	for_each_set_bit(vid, rp->active_vlans, VLAN_N_VID) {
+		rhine_set_vlan_cam(ioaddr, i, (u8 *)&vid);
+		vCAMmask |= 1 << i;
+		if (++i >= VCAM_SIZE)
+			break;
+	}
+	rhine_set_vlan_cam_mask(ioaddr, vCAMmask);
+}
+
+static void rhine_vlan_rx_add_vid(struct net_device *dev, unsigned short vid)
+{
+	struct rhine_private *rp = netdev_priv(dev);
+
+	spin_lock_irq(&rp->lock);
+	set_bit(vid, rp->active_vlans);
+	rhine_update_vcam(dev);
+	spin_unlock_irq(&rp->lock);
+}
+
+static void rhine_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
+{
+	struct rhine_private *rp = netdev_priv(dev);
+
+	spin_lock_irq(&rp->lock);
+	clear_bit(vid, rp->active_vlans);
+	rhine_update_vcam(dev);
+	spin_unlock_irq(&rp->lock);
+}
+
 static void init_registers(struct net_device *dev)
 {
 	struct rhine_private *rp = netdev_priv(dev);
@@ -1061,6 +1300,9 @@ static void init_registers(struct net_de
 
 	rhine_set_rx_mode(dev);
 
+	if (rp->pdev->revision >= VT6105M)
+		rhine_init_cam_filter(dev);
+
 	napi_enable(&rp->napi);
 
 	/* Enable interrupts by setting the interrupt mask. */
@@ -1276,16 +1518,28 @@ static netdev_tx_t rhine_start_tx(struct
 	rp->tx_ring[entry].desc_length =
 		cpu_to_le32(TXDESC | (skb->len >= ETH_ZLEN ? skb->len : ETH_ZLEN));
 
+	if (unlikely(vlan_tx_tag_present(skb))) {
+		rp->tx_ring[entry].tx_status = cpu_to_le32((vlan_tx_tag_get(skb)) << 16);
+		/* request tagging */
+		rp->tx_ring[entry].desc_length |= cpu_to_le32(0x020000);
+	}
+	else
+		rp->tx_ring[entry].tx_status = 0;
+
 	/* lock eth irq */
 	spin_lock_irqsave(&rp->lock, flags);
 	wmb();
-	rp->tx_ring[entry].tx_status = cpu_to_le32(DescOwn);
+	rp->tx_ring[entry].tx_status |= cpu_to_le32(DescOwn);
 	wmb();
 
 	rp->cur_tx++;
 
 	/* Non-x86 Todo: explicitly flush cache lines here. */
 
+	if (vlan_tx_tag_present(skb))
+		/* Tx queues are bits 7-0 (first Tx queue: bit 7) */
+		BYTE_REG_BITS_ON(1 << 7, ioaddr + TQWake);
+
 	/* Wake the potentially-idle transmit channel */
 	iowrite8(ioread8(ioaddr + ChipCmd1) | Cmd1TxDemand,
 	       ioaddr + ChipCmd1);
@@ -1437,6 +1691,21 @@ static void rhine_tx(struct net_device *
 	spin_unlock(&rp->lock);
 }
 
+/**
+ * rhine_get_vlan_tci - extract TCI from Rx data buffer
+ * @skb: pointer to sk_buff
+ * @data_size: used data area of the buffer including CRC
+ *
+ * If hardware VLAN tag extraction is enabled and the chip indicates a 802.1Q
+ * packet, the extracted 802.1Q header (2 bytes TPID + 2 bytes TCI) is 4-byte
+ * aligned following the CRC.
+ */
+static inline u16 rhine_get_vlan_tci(struct sk_buff *skb, int data_size)
+{
+	u8 *trailer = (u8 *)skb->data + ((data_size + 3) & ~3) + 2;
+	return ntohs(*(u16 *)trailer);
+}
+
 /* Process up to limit frames from receive ring */
 static int rhine_rx(struct net_device *dev, int limit)
 {
@@ -1454,6 +1723,7 @@ static int rhine_rx(struct net_device *d
 	for (count = 0; count < limit; ++count) {
 		struct rx_desc *desc = rp->rx_head_desc;
 		u32 desc_status = le32_to_cpu(desc->rx_status);
+		u32 desc_length = le32_to_cpu(desc->desc_length);
 		int data_size = desc_status >> 16;
 
 		if (desc_status & DescOwn)
@@ -1498,6 +1768,7 @@ static int rhine_rx(struct net_device *d
 			struct sk_buff *skb = NULL;
 			/* Length should omit the CRC */
 			int pkt_len = data_size - 4;
+			u16 vlan_tci = 0;
 
 			/* Check if the packet is long enough to accept without
 			   copying to a minimally-sized skbuff. */
@@ -1532,7 +1803,14 @@ static int rhine_rx(struct net_device *d
 						 rp->rx_buf_sz,
 						 PCI_DMA_FROMDEVICE);
 			}
+
+			if (unlikely(desc_length & DescTag))
+				vlan_tci = rhine_get_vlan_tci(skb, data_size);
+
 			skb->protocol = eth_type_trans(skb, dev);
+
+			if (unlikely(desc_length & DescTag))
+				__vlan_hwaccel_put_tag(skb, vlan_tci);
 			netif_receive_skb(skb);
 			dev->stats.rx_bytes += pkt_len;
 			dev->stats.rx_packets++;
@@ -1596,6 +1874,11 @@ static void rhine_restart_tx(struct net_
 
 		iowrite8(ioread8(ioaddr + ChipCmd) | CmdTxOn,
 		       ioaddr + ChipCmd);
+
+		if (rp->tx_ring[entry].desc_length & cpu_to_le32(0x020000))
+			/* Tx queues are bits 7-0 (first Tx queue: bit 7) */
+			BYTE_REG_BITS_ON(1 << 7, ioaddr + TQWake);
+
 		iowrite8(ioread8(ioaddr + ChipCmd1) | Cmd1TxDemand,
 		       ioaddr + ChipCmd1);
 		IOSYNC;
@@ -1631,7 +1914,7 @@ static void rhine_error(struct net_devic
 	}
 	if (intr_status & IntrTxUnderrun) {
 		if (rp->tx_thresh < 0xE0)
-			iowrite8(rp->tx_thresh += 0x20, ioaddr + TxConfig);
+			BYTE_REG_BITS_SET((rp->tx_thresh += 0x20), 0x80, ioaddr + TxConfig);
 		if (debug > 1)
 			printk(KERN_INFO "%s: Transmitter underrun, Tx "
 			       "threshold now %2.2x.\n",
@@ -1646,7 +1929,7 @@ static void rhine_error(struct net_devic
 	    (intr_status & (IntrTxAborted |
 	     IntrTxUnderrun | IntrTxDescRace)) == 0) {
 		if (rp->tx_thresh < 0xE0) {
-			iowrite8(rp->tx_thresh += 0x20, ioaddr + TxConfig);
+			BYTE_REG_BITS_SET((rp->tx_thresh += 0x20), 0x80, ioaddr + TxConfig);
 		}
 		if (debug > 1)
 			printk(KERN_INFO "%s: Unspecified error. Tx "
@@ -1688,7 +1971,8 @@ static void rhine_set_rx_mode(struct net
 	struct rhine_private *rp = netdev_priv(dev);
 	void __iomem *ioaddr = rp->base;
 	u32 mc_filter[2];	/* Multicast hash filter */
-	u8 rx_mode;		/* Note: 0x02=accept runt, 0x01=accept errs */
+	u8 rx_mode = 0x0C;	/* Note: 0x02=accept runt, 0x01=accept errs */
+	struct netdev_hw_addr *ha;
 
 	if (dev->flags & IFF_PROMISC) {		/* Set promiscuous. */
 		rx_mode = 0x1C;
@@ -1699,10 +1983,18 @@ static void rhine_set_rx_mode(struct net
 		/* Too many to match, or accept all multicasts. */
 		iowrite32(0xffffffff, ioaddr + MulticastFilter0);
 		iowrite32(0xffffffff, ioaddr + MulticastFilter1);
-		rx_mode = 0x0C;
+	} else if (rp->pdev->revision >= VT6105M) {
+		int i = 0;
+		u32 mCAMmask = 0;	/* 32 mCAMs (6105M and better) */
+		netdev_for_each_mc_addr(ha, dev) {
+			if (i == MCAM_SIZE)
+				break;
+			rhine_set_cam(ioaddr, i, ha->addr);
+			mCAMmask |= 1 << i;
+			i++;
+		}
+		rhine_set_cam_mask(ioaddr, mCAMmask);
 	} else {
-		struct netdev_hw_addr *ha;
-
 		memset(mc_filter, 0, sizeof(mc_filter));
 		netdev_for_each_mc_addr(ha, dev) {
 			int bit_nr = ether_crc(ETH_ALEN, ha->addr) >> 26;
@@ -1711,9 +2003,15 @@ static void rhine_set_rx_mode(struct net
 		}
 		iowrite32(mc_filter[0], ioaddr + MulticastFilter0);
 		iowrite32(mc_filter[1], ioaddr + MulticastFilter1);
-		rx_mode = 0x0C;
 	}
-	iowrite8(rp->rx_thresh | rx_mode, ioaddr + RxConfig);
+	/* enable/disable VLAN receive filtering */
+	if (rp->pdev->revision >= VT6105M) {
+		if (dev->flags & IFF_PROMISC)
+			BYTE_REG_BITS_OFF(BCR1_VIDFR, ioaddr + PCIBusConfig1);
+		else
+			BYTE_REG_BITS_ON(BCR1_VIDFR, ioaddr + PCIBusConfig1);
+	}
+	BYTE_REG_BITS_ON(rx_mode, ioaddr + RxConfig);
 }
 
 static void netdev_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
@@ -1966,7 +2264,7 @@ static int rhine_resume(struct pci_dev *
 	if (!netif_running(dev))
 		return 0;
 
-        if (request_irq(dev->irq, rhine_interrupt, IRQF_SHARED, dev->name, dev))
+	if (request_irq(dev->irq, rhine_interrupt, IRQF_SHARED, dev->name, dev))
 		printk(KERN_ERR "via-rhine %s: request_irq failed\n", dev->name);
 
 	ret = pci_set_power_state(pdev, PCI_D0);
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/via-velocity.c linux-libre-2.6.38-gnu1/drivers/net/via-velocity.c
--- linux-libre-2.6.37-gnu1/drivers/net/via-velocity.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/via-velocity.c	2011-03-14 21:20:32.000000000 -0400
@@ -898,7 +898,7 @@ static int velocity_set_media_mode(struc
 	set_mii_flow_control(vptr);
 
 	/*
-	   Check if new status is consisent with current status
+	   Check if new status is consistent with current status
 	   if (((mii_status & curr_status) & VELOCITY_AUTONEG_ENABLE) ||
 	       (mii_status==curr_status)) {
 	   vptr->mii_status=mii_check_media_mode(vptr->mac_regs);
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/virtio_net.c linux-libre-2.6.38-gnu1/drivers/net/virtio_net.c
--- linux-libre-2.6.37-gnu1/drivers/net/virtio_net.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/virtio_net.c	2011-03-14 21:20:32.000000000 -0400
@@ -446,6 +446,20 @@ static void skb_recv_done(struct virtque
 	}
 }
 
+static void virtnet_napi_enable(struct virtnet_info *vi)
+{
+	napi_enable(&vi->napi);
+
+	/* If all buffers were filled by other side before we napi_enabled, we
+	 * won't get another interrupt, so process any outstanding packets
+	 * now.  virtnet_poll wants re-enable the queue, so we disable here.
+	 * We synchronize against interrupts via NAPI_STATE_SCHED */
+	if (napi_schedule_prep(&vi->napi)) {
+		virtqueue_disable_cb(vi->rvq);
+		__napi_schedule(&vi->napi);
+	}
+}
+
 static void refill_work(struct work_struct *work)
 {
 	struct virtnet_info *vi;
@@ -454,7 +468,7 @@ static void refill_work(struct work_stru
 	vi = container_of(work, struct virtnet_info, refill.work);
 	napi_disable(&vi->napi);
 	still_empty = !try_fill_recv(vi, GFP_KERNEL);
-	napi_enable(&vi->napi);
+	virtnet_napi_enable(vi);
 
 	/* In theory, this can happen: if we don't get any buffers in
 	 * we will *never* try to fill again. */
@@ -519,7 +533,7 @@ static int xmit_skb(struct virtnet_info
 
 	if (skb->ip_summed == CHECKSUM_PARTIAL) {
 		hdr->hdr.flags = VIRTIO_NET_HDR_F_NEEDS_CSUM;
-		hdr->hdr.csum_start = skb->csum_start - skb_headroom(skb);
+		hdr->hdr.csum_start = skb_checksum_start_offset(skb);
 		hdr->hdr.csum_offset = skb->csum_offset;
 	} else {
 		hdr->hdr.flags = 0;
@@ -638,16 +652,7 @@ static int virtnet_open(struct net_devic
 {
 	struct virtnet_info *vi = netdev_priv(dev);
 
-	napi_enable(&vi->napi);
-
-	/* If all buffers were filled by other side before we napi_enabled, we
-	 * won't get another interrupt, so process any outstanding packets
-	 * now.  virtnet_poll wants re-enable the queue, so we disable here.
-	 * We synchronize against interrupts via NAPI_STATE_SCHED */
-	if (napi_schedule_prep(&vi->napi)) {
-		virtqueue_disable_cb(vi->rvq);
-		__napi_schedule(&vi->napi);
-	}
+	virtnet_napi_enable(vi);
 	return 0;
 }
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/vmxnet3/vmxnet3_drv.c linux-libre-2.6.38-gnu1/drivers/net/vmxnet3/vmxnet3_drv.c
--- linux-libre-2.6.37-gnu1/drivers/net/vmxnet3/vmxnet3_drv.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/vmxnet3/vmxnet3_drv.c	2011-03-14 21:20:32.000000000 -0400
@@ -44,6 +44,12 @@ MODULE_DEVICE_TABLE(pci, vmxnet3_pciid_t
 
 static atomic_t devices_found;
 
+#define VMXNET3_MAX_DEVICES 10
+static int enable_mq = 1;
+static int irq_share_mode;
+
+static void
+vmxnet3_write_mac_addr(struct vmxnet3_adapter *adapter, u8 *mac);
 
 /*
  *    Enable/Disable the given intr
@@ -99,7 +105,7 @@ vmxnet3_ack_events(struct vmxnet3_adapte
 static bool
 vmxnet3_tq_stopped(struct vmxnet3_tx_queue *tq, struct vmxnet3_adapter *adapter)
 {
-	return netif_queue_stopped(adapter->netdev);
+	return tq->stopped;
 }
 
 
@@ -107,7 +113,7 @@ static void
 vmxnet3_tq_start(struct vmxnet3_tx_queue *tq, struct vmxnet3_adapter *adapter)
 {
 	tq->stopped = false;
-	netif_start_queue(adapter->netdev);
+	netif_start_subqueue(adapter->netdev, tq - adapter->tx_queue);
 }
 
 
@@ -115,7 +121,7 @@ static void
 vmxnet3_tq_wake(struct vmxnet3_tx_queue *tq, struct vmxnet3_adapter *adapter)
 {
 	tq->stopped = false;
-	netif_wake_queue(adapter->netdev);
+	netif_wake_subqueue(adapter->netdev, (tq - adapter->tx_queue));
 }
 
 
@@ -124,7 +130,7 @@ vmxnet3_tq_stop(struct vmxnet3_tx_queue
 {
 	tq->stopped = true;
 	tq->num_stop++;
-	netif_stop_queue(adapter->netdev);
+	netif_stop_subqueue(adapter->netdev, (tq - adapter->tx_queue));
 }
 
 
@@ -135,9 +141,14 @@ static void
 vmxnet3_check_link(struct vmxnet3_adapter *adapter, bool affectTxQueue)
 {
 	u32 ret;
+	int i;
+	unsigned long flags;
 
+	spin_lock_irqsave(&adapter->cmd_lock, flags);
 	VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD, VMXNET3_CMD_GET_LINK);
 	ret = VMXNET3_READ_BAR1_REG(adapter, VMXNET3_REG_CMD);
+	spin_unlock_irqrestore(&adapter->cmd_lock, flags);
+
 	adapter->link_speed = ret >> 16;
 	if (ret & 1) { /* Link is up. */
 		printk(KERN_INFO "%s: NIC Link is Up %d Mbps\n",
@@ -145,22 +156,28 @@ vmxnet3_check_link(struct vmxnet3_adapte
 		if (!netif_carrier_ok(adapter->netdev))
 			netif_carrier_on(adapter->netdev);
 
-		if (affectTxQueue)
-			vmxnet3_tq_start(&adapter->tx_queue, adapter);
+		if (affectTxQueue) {
+			for (i = 0; i < adapter->num_tx_queues; i++)
+				vmxnet3_tq_start(&adapter->tx_queue[i],
+						 adapter);
+		}
 	} else {
 		printk(KERN_INFO "%s: NIC Link is Down\n",
 		       adapter->netdev->name);
 		if (netif_carrier_ok(adapter->netdev))
 			netif_carrier_off(adapter->netdev);
 
-		if (affectTxQueue)
-			vmxnet3_tq_stop(&adapter->tx_queue, adapter);
+		if (affectTxQueue) {
+			for (i = 0; i < adapter->num_tx_queues; i++)
+				vmxnet3_tq_stop(&adapter->tx_queue[i], adapter);
+		}
 	}
 }
 
 static void
 vmxnet3_process_events(struct vmxnet3_adapter *adapter)
 {
+	int i;
 	u32 events = le32_to_cpu(adapter->shared->ecr);
 	if (!events)
 		return;
@@ -173,19 +190,23 @@ vmxnet3_process_events(struct vmxnet3_ad
 
 	/* Check if there is an error on xmit/recv queues */
 	if (events & (VMXNET3_ECR_TQERR | VMXNET3_ECR_RQERR)) {
+		spin_lock(&adapter->cmd_lock);
 		VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
 				       VMXNET3_CMD_GET_QUEUE_STATUS);
+		spin_unlock(&adapter->cmd_lock);
 
-		if (adapter->tqd_start->status.stopped) {
-			printk(KERN_ERR "%s: tq error 0x%x\n",
-			       adapter->netdev->name,
-			       le32_to_cpu(adapter->tqd_start->status.error));
-		}
-		if (adapter->rqd_start->status.stopped) {
-			printk(KERN_ERR "%s: rq error 0x%x\n",
-			       adapter->netdev->name,
-			       adapter->rqd_start->status.error);
-		}
+		for (i = 0; i < adapter->num_tx_queues; i++)
+			if (adapter->tqd_start[i].status.stopped)
+				dev_err(&adapter->netdev->dev,
+					"%s: tq[%d] error 0x%x\n",
+					adapter->netdev->name, i, le32_to_cpu(
+					adapter->tqd_start[i].status.error));
+		for (i = 0; i < adapter->num_rx_queues; i++)
+			if (adapter->rqd_start[i].status.stopped)
+				dev_err(&adapter->netdev->dev,
+					"%s: rq[%d] error 0x%x\n",
+					adapter->netdev->name, i,
+					adapter->rqd_start[i].status.error);
 
 		schedule_work(&adapter->work);
 	}
@@ -410,7 +431,7 @@ vmxnet3_tq_cleanup(struct vmxnet3_tx_que
 }
 
 
-void
+static void
 vmxnet3_tq_destroy(struct vmxnet3_tx_queue *tq,
 		   struct vmxnet3_adapter *adapter)
 {
@@ -437,6 +458,17 @@ vmxnet3_tq_destroy(struct vmxnet3_tx_que
 }
 
 
+/* Destroy all tx queues */
+void
+vmxnet3_tq_destroy_all(struct vmxnet3_adapter *adapter)
+{
+	int i;
+
+	for (i = 0; i < adapter->num_tx_queues; i++)
+		vmxnet3_tq_destroy(&adapter->tx_queue[i], adapter);
+}
+
+
 static void
 vmxnet3_tq_init(struct vmxnet3_tx_queue *tq,
 		struct vmxnet3_adapter *adapter)
@@ -518,6 +550,14 @@ err:
 	return -ENOMEM;
 }
 
+static void
+vmxnet3_tq_cleanup_all(struct vmxnet3_adapter *adapter)
+{
+	int i;
+
+	for (i = 0; i < adapter->num_tx_queues; i++)
+		vmxnet3_tq_cleanup(&adapter->tx_queue[i], adapter);
+}
 
 /*
  *    starting from ring->next2fill, allocate rx buffers for the given ring
@@ -732,6 +772,17 @@ vmxnet3_map_pkt(struct sk_buff *skb, str
 }
 
 
+/* Init all tx queues */
+static void
+vmxnet3_tq_init_all(struct vmxnet3_adapter *adapter)
+{
+	int i;
+
+	for (i = 0; i < adapter->num_tx_queues; i++)
+		vmxnet3_tq_init(&adapter->tx_queue[i], adapter);
+}
+
+
 /*
  *    parse and copy relevant protocol headers:
  *      For a tso pkt, relevant headers are L2/3/4 including options
@@ -756,36 +807,31 @@ vmxnet3_parse_and_copy_hdr(struct sk_buf
 {
 	struct Vmxnet3_TxDataDesc *tdd;
 
-	if (ctx->mss) {
+	if (ctx->mss) {	/* TSO */
 		ctx->eth_ip_hdr_size = skb_transport_offset(skb);
 		ctx->l4_hdr_size = ((struct tcphdr *)
 				   skb_transport_header(skb))->doff * 4;
 		ctx->copy_size = ctx->eth_ip_hdr_size + ctx->l4_hdr_size;
 	} else {
-		unsigned int pull_size;
-
 		if (skb->ip_summed == CHECKSUM_PARTIAL) {
-			ctx->eth_ip_hdr_size = skb_transport_offset(skb);
+			ctx->eth_ip_hdr_size = skb_checksum_start_offset(skb);
 
 			if (ctx->ipv4) {
 				struct iphdr *iph = (struct iphdr *)
 						    skb_network_header(skb);
-				if (iph->protocol == IPPROTO_TCP) {
-					pull_size = ctx->eth_ip_hdr_size +
-						    sizeof(struct tcphdr);
-
-					if (unlikely(!pskb_may_pull(skb,
-								pull_size))) {
-						goto err;
-					}
+				if (iph->protocol == IPPROTO_TCP)
 					ctx->l4_hdr_size = ((struct tcphdr *)
 					   skb_transport_header(skb))->doff * 4;
-				} else if (iph->protocol == IPPROTO_UDP) {
+				else if (iph->protocol == IPPROTO_UDP)
+					/*
+					 * Use tcp header size so that bytes to
+					 * be copied are more than required by
+					 * the device.
+					 */
 					ctx->l4_hdr_size =
-							sizeof(struct udphdr);
-				} else {
+							sizeof(struct tcphdr);
+				else
 					ctx->l4_hdr_size = 0;
-				}
 			} else {
 				/* for simplicity, don't copy L4 headers */
 				ctx->l4_hdr_size = 0;
@@ -903,6 +949,21 @@ vmxnet3_tq_xmit(struct sk_buff *skb, str
 		}
 	}
 
+	spin_lock_irqsave(&tq->tx_lock, flags);
+
+	if (count > vmxnet3_cmd_ring_desc_avail(&tq->tx_ring)) {
+		tq->stats.tx_ring_full++;
+		dev_dbg(&adapter->netdev->dev,
+			"tx queue stopped on %s, next2comp %u"
+			" next2fill %u\n", adapter->netdev->name,
+			tq->tx_ring.next2comp, tq->tx_ring.next2fill);
+
+		vmxnet3_tq_stop(tq, adapter);
+		spin_unlock_irqrestore(&tq->tx_lock, flags);
+		return NETDEV_TX_BUSY;
+	}
+
+
 	ret = vmxnet3_parse_and_copy_hdr(skb, tq, &ctx, adapter);
 	if (ret >= 0) {
 		BUG_ON(ret <= 0 && ctx.copy_size != 0);
@@ -923,21 +984,7 @@ vmxnet3_tq_xmit(struct sk_buff *skb, str
 		}
 	} else {
 		tq->stats.drop_hdr_inspect_err++;
-		goto drop_pkt;
-	}
-
-	spin_lock_irqsave(&tq->tx_lock, flags);
-
-	if (count > vmxnet3_cmd_ring_desc_avail(&tq->tx_ring)) {
-		tq->stats.tx_ring_full++;
-		dev_dbg(&adapter->netdev->dev,
-			"tx queue stopped on %s, next2comp %u"
-			" next2fill %u\n", adapter->netdev->name,
-			tq->tx_ring.next2comp, tq->tx_ring.next2fill);
-
-		vmxnet3_tq_stop(tq, adapter);
-		spin_unlock_irqrestore(&tq->tx_lock, flags);
-		return NETDEV_TX_BUSY;
+		goto unlock_drop_pkt;
 	}
 
 	/* fill tx descs related to addr & len */
@@ -1000,7 +1047,8 @@ vmxnet3_tq_xmit(struct sk_buff *skb, str
 	if (le32_to_cpu(tq->shared->txNumDeferred) >=
 					le32_to_cpu(tq->shared->txThreshold)) {
 		tq->shared->txNumDeferred = 0;
-		VMXNET3_WRITE_BAR0_REG(adapter, VMXNET3_REG_TXPROD,
+		VMXNET3_WRITE_BAR0_REG(adapter,
+				       VMXNET3_REG_TXPROD + tq->qid * 8,
 				       tq->tx_ring.next2fill);
 	}
 
@@ -1008,6 +1056,8 @@ vmxnet3_tq_xmit(struct sk_buff *skb, str
 
 hdr_too_big:
 	tq->stats.drop_oversized_hdr++;
+unlock_drop_pkt:
+	spin_unlock_irqrestore(&tq->tx_lock, flags);
 drop_pkt:
 	tq->stats.drop_total++;
 	dev_kfree_skb(skb);
@@ -1020,7 +1070,10 @@ vmxnet3_xmit_frame(struct sk_buff *skb,
 {
 	struct vmxnet3_adapter *adapter = netdev_priv(netdev);
 
-	return vmxnet3_tq_xmit(skb, &adapter->tx_queue, adapter, netdev);
+		BUG_ON(skb->queue_mapping > adapter->num_tx_queues);
+		return vmxnet3_tq_xmit(skb,
+				       &adapter->tx_queue[skb->queue_mapping],
+				       adapter, netdev);
 }
 
 
@@ -1082,7 +1135,9 @@ static int
 vmxnet3_rq_rx_complete(struct vmxnet3_rx_queue *rq,
 		       struct vmxnet3_adapter *adapter, int quota)
 {
-	static u32 rxprod_reg[2] = {VMXNET3_REG_RXPROD, VMXNET3_REG_RXPROD2};
+	static const u32 rxprod_reg[2] = {
+		VMXNET3_REG_RXPROD, VMXNET3_REG_RXPROD2
+	};
 	u32 num_rxd = 0;
 	struct Vmxnet3_RxCompDesc *rcd;
 	struct vmxnet3_rx_ctx *ctx = &rq->rx_ctx;
@@ -1106,9 +1161,9 @@ vmxnet3_rq_rx_complete(struct vmxnet3_rx
 			break;
 		}
 		num_rxd++;
-
+		BUG_ON(rcd->rqID != rq->qid && rcd->rqID != rq->qid2);
 		idx = rcd->rxdIdx;
-		ring_idx = rcd->rqID == rq->qid ? 0 : 1;
+		ring_idx = rcd->rqID < adapter->num_rx_queues ? 0 : 1;
 		vmxnet3_getRxDesc(rxd, &rq->rx_ring[ring_idx].base[idx].rxd,
 				  &rxCmdDesc);
 		rbi = rq->buf_info[ring_idx] + idx;
@@ -1260,6 +1315,16 @@ vmxnet3_rq_cleanup(struct vmxnet3_rx_que
 }
 
 
+static void
+vmxnet3_rq_cleanup_all(struct vmxnet3_adapter *adapter)
+{
+	int i;
+
+	for (i = 0; i < adapter->num_rx_queues; i++)
+		vmxnet3_rq_cleanup(&adapter->rx_queue[i], adapter);
+}
+
+
 void vmxnet3_rq_destroy(struct vmxnet3_rx_queue *rq,
 			struct vmxnet3_adapter *adapter)
 {
@@ -1351,6 +1416,25 @@ vmxnet3_rq_init(struct vmxnet3_rx_queue
 
 
 static int
+vmxnet3_rq_init_all(struct vmxnet3_adapter *adapter)
+{
+	int i, err = 0;
+
+	for (i = 0; i < adapter->num_rx_queues; i++) {
+		err = vmxnet3_rq_init(&adapter->rx_queue[i], adapter);
+		if (unlikely(err)) {
+			dev_err(&adapter->netdev->dev, "%s: failed to "
+				"initialize rx queue%i\n",
+				adapter->netdev->name, i);
+			break;
+		}
+	}
+	return err;
+
+}
+
+
+static int
 vmxnet3_rq_create(struct vmxnet3_rx_queue *rq, struct vmxnet3_adapter *adapter)
 {
 	int i;
@@ -1398,32 +1482,176 @@ err:
 
 
 static int
+vmxnet3_rq_create_all(struct vmxnet3_adapter *adapter)
+{
+	int i, err = 0;
+
+	for (i = 0; i < adapter->num_rx_queues; i++) {
+		err = vmxnet3_rq_create(&adapter->rx_queue[i], adapter);
+		if (unlikely(err)) {
+			dev_err(&adapter->netdev->dev,
+				"%s: failed to create rx queue%i\n",
+				adapter->netdev->name, i);
+			goto err_out;
+		}
+	}
+	return err;
+err_out:
+	vmxnet3_rq_destroy_all(adapter);
+	return err;
+
+}
+
+/* Multiple queue aware polling function for tx and rx */
+
+static int
 vmxnet3_do_poll(struct vmxnet3_adapter *adapter, int budget)
 {
+	int rcd_done = 0, i;
 	if (unlikely(adapter->shared->ecr))
 		vmxnet3_process_events(adapter);
+	for (i = 0; i < adapter->num_tx_queues; i++)
+		vmxnet3_tq_tx_complete(&adapter->tx_queue[i], adapter);
 
-	vmxnet3_tq_tx_complete(&adapter->tx_queue, adapter);
-	return vmxnet3_rq_rx_complete(&adapter->rx_queue, adapter, budget);
+	for (i = 0; i < adapter->num_rx_queues; i++)
+		rcd_done += vmxnet3_rq_rx_complete(&adapter->rx_queue[i],
+						   adapter, budget);
+	return rcd_done;
 }
 
 
 static int
 vmxnet3_poll(struct napi_struct *napi, int budget)
 {
-	struct vmxnet3_adapter *adapter = container_of(napi,
-					  struct vmxnet3_adapter, napi);
+	struct vmxnet3_rx_queue *rx_queue = container_of(napi,
+					  struct vmxnet3_rx_queue, napi);
 	int rxd_done;
 
-	rxd_done = vmxnet3_do_poll(adapter, budget);
+	rxd_done = vmxnet3_do_poll(rx_queue->adapter, budget);
 
 	if (rxd_done < budget) {
 		napi_complete(napi);
-		vmxnet3_enable_intr(adapter, 0);
+		vmxnet3_enable_all_intrs(rx_queue->adapter);
 	}
 	return rxd_done;
 }
 
+/*
+ * NAPI polling function for MSI-X mode with multiple Rx queues
+ * Returns the # of the NAPI credit consumed (# of rx descriptors processed)
+ */
+
+static int
+vmxnet3_poll_rx_only(struct napi_struct *napi, int budget)
+{
+	struct vmxnet3_rx_queue *rq = container_of(napi,
+						struct vmxnet3_rx_queue, napi);
+	struct vmxnet3_adapter *adapter = rq->adapter;
+	int rxd_done;
+
+	/* When sharing interrupt with corresponding tx queue, process
+	 * tx completions in that queue as well
+	 */
+	if (adapter->share_intr == VMXNET3_INTR_BUDDYSHARE) {
+		struct vmxnet3_tx_queue *tq =
+				&adapter->tx_queue[rq - adapter->rx_queue];
+		vmxnet3_tq_tx_complete(tq, adapter);
+	}
+
+	rxd_done = vmxnet3_rq_rx_complete(rq, adapter, budget);
+
+	if (rxd_done < budget) {
+		napi_complete(napi);
+		vmxnet3_enable_intr(adapter, rq->comp_ring.intr_idx);
+	}
+	return rxd_done;
+}
+
+
+#ifdef CONFIG_PCI_MSI
+
+/*
+ * Handle completion interrupts on tx queues
+ * Returns whether or not the intr is handled
+ */
+
+static irqreturn_t
+vmxnet3_msix_tx(int irq, void *data)
+{
+	struct vmxnet3_tx_queue *tq = data;
+	struct vmxnet3_adapter *adapter = tq->adapter;
+
+	if (adapter->intr.mask_mode == VMXNET3_IMM_ACTIVE)
+		vmxnet3_disable_intr(adapter, tq->comp_ring.intr_idx);
+
+	/* Handle the case where only one irq is allocate for all tx queues */
+	if (adapter->share_intr == VMXNET3_INTR_TXSHARE) {
+		int i;
+		for (i = 0; i < adapter->num_tx_queues; i++) {
+			struct vmxnet3_tx_queue *txq = &adapter->tx_queue[i];
+			vmxnet3_tq_tx_complete(txq, adapter);
+		}
+	} else {
+		vmxnet3_tq_tx_complete(tq, adapter);
+	}
+	vmxnet3_enable_intr(adapter, tq->comp_ring.intr_idx);
+
+	return IRQ_HANDLED;
+}
+
+
+/*
+ * Handle completion interrupts on rx queues. Returns whether or not the
+ * intr is handled
+ */
+
+static irqreturn_t
+vmxnet3_msix_rx(int irq, void *data)
+{
+	struct vmxnet3_rx_queue *rq = data;
+	struct vmxnet3_adapter *adapter = rq->adapter;
+
+	/* disable intr if needed */
+	if (adapter->intr.mask_mode == VMXNET3_IMM_ACTIVE)
+		vmxnet3_disable_intr(adapter, rq->comp_ring.intr_idx);
+	napi_schedule(&rq->napi);
+
+	return IRQ_HANDLED;
+}
+
+/*
+ *----------------------------------------------------------------------------
+ *
+ * vmxnet3_msix_event --
+ *
+ *    vmxnet3 msix event intr handler
+ *
+ * Result:
+ *    whether or not the intr is handled
+ *
+ *----------------------------------------------------------------------------
+ */
+
+static irqreturn_t
+vmxnet3_msix_event(int irq, void *data)
+{
+	struct net_device *dev = data;
+	struct vmxnet3_adapter *adapter = netdev_priv(dev);
+
+	/* disable intr if needed */
+	if (adapter->intr.mask_mode == VMXNET3_IMM_ACTIVE)
+		vmxnet3_disable_intr(adapter, adapter->intr.event_intr_idx);
+
+	if (adapter->shared->ecr)
+		vmxnet3_process_events(adapter);
+
+	vmxnet3_enable_intr(adapter, adapter->intr.event_intr_idx);
+
+	return IRQ_HANDLED;
+}
+
+#endif /* CONFIG_PCI_MSI  */
+
 
 /* Interrupt handler for vmxnet3  */
 static irqreturn_t
@@ -1432,7 +1660,7 @@ vmxnet3_intr(int irq, void *dev_id)
 	struct net_device *dev = dev_id;
 	struct vmxnet3_adapter *adapter = netdev_priv(dev);
 
-	if (unlikely(adapter->intr.type == VMXNET3_IT_INTX)) {
+	if (adapter->intr.type == VMXNET3_IT_INTX) {
 		u32 icr = VMXNET3_READ_BAR1_REG(adapter, VMXNET3_REG_ICR);
 		if (unlikely(icr == 0))
 			/* not ours */
@@ -1442,77 +1670,144 @@ vmxnet3_intr(int irq, void *dev_id)
 
 	/* disable intr if needed */
 	if (adapter->intr.mask_mode == VMXNET3_IMM_ACTIVE)
-		vmxnet3_disable_intr(adapter, 0);
+		vmxnet3_disable_all_intrs(adapter);
 
-	napi_schedule(&adapter->napi);
+	napi_schedule(&adapter->rx_queue[0].napi);
 
 	return IRQ_HANDLED;
 }
 
 #ifdef CONFIG_NET_POLL_CONTROLLER
 
-
 /* netpoll callback. */
 static void
 vmxnet3_netpoll(struct net_device *netdev)
 {
 	struct vmxnet3_adapter *adapter = netdev_priv(netdev);
-	int irq;
 
-#ifdef CONFIG_PCI_MSI
-	if (adapter->intr.type == VMXNET3_IT_MSIX)
-		irq = adapter->intr.msix_entries[0].vector;
-	else
-#endif
-		irq = adapter->pdev->irq;
+	if (adapter->intr.mask_mode == VMXNET3_IMM_ACTIVE)
+		vmxnet3_disable_all_intrs(adapter);
+
+	vmxnet3_do_poll(adapter, adapter->rx_queue[0].rx_ring[0].size);
+	vmxnet3_enable_all_intrs(adapter);
 
-	disable_irq(irq);
-	vmxnet3_intr(irq, netdev);
-	enable_irq(irq);
 }
-#endif
+#endif	/* CONFIG_NET_POLL_CONTROLLER */
 
 static int
 vmxnet3_request_irqs(struct vmxnet3_adapter *adapter)
 {
-	int err;
+	struct vmxnet3_intr *intr = &adapter->intr;
+	int err = 0, i;
+	int vector = 0;
 
 #ifdef CONFIG_PCI_MSI
 	if (adapter->intr.type == VMXNET3_IT_MSIX) {
-		/* we only use 1 MSI-X vector */
-		err = request_irq(adapter->intr.msix_entries[0].vector,
-				  vmxnet3_intr, 0, adapter->netdev->name,
-				  adapter->netdev);
-	} else if (adapter->intr.type == VMXNET3_IT_MSI) {
+		for (i = 0; i < adapter->num_tx_queues; i++) {
+			if (adapter->share_intr != VMXNET3_INTR_BUDDYSHARE) {
+				sprintf(adapter->tx_queue[i].name, "%s-tx-%d",
+					adapter->netdev->name, vector);
+				err = request_irq(
+					      intr->msix_entries[vector].vector,
+					      vmxnet3_msix_tx, 0,
+					      adapter->tx_queue[i].name,
+					      &adapter->tx_queue[i]);
+			} else {
+				sprintf(adapter->tx_queue[i].name, "%s-rxtx-%d",
+					adapter->netdev->name, vector);
+			}
+			if (err) {
+				dev_err(&adapter->netdev->dev,
+					"Failed to request irq for MSIX, %s, "
+					"error %d\n",
+					adapter->tx_queue[i].name, err);
+				return err;
+			}
+
+			/* Handle the case where only 1 MSIx was allocated for
+			 * all tx queues */
+			if (adapter->share_intr == VMXNET3_INTR_TXSHARE) {
+				for (; i < adapter->num_tx_queues; i++)
+					adapter->tx_queue[i].comp_ring.intr_idx
+								= vector;
+				vector++;
+				break;
+			} else {
+				adapter->tx_queue[i].comp_ring.intr_idx
+								= vector++;
+			}
+		}
+		if (adapter->share_intr == VMXNET3_INTR_BUDDYSHARE)
+			vector = 0;
+
+		for (i = 0; i < adapter->num_rx_queues; i++) {
+			if (adapter->share_intr != VMXNET3_INTR_BUDDYSHARE)
+				sprintf(adapter->rx_queue[i].name, "%s-rx-%d",
+					adapter->netdev->name, vector);
+			else
+				sprintf(adapter->rx_queue[i].name, "%s-rxtx-%d",
+					adapter->netdev->name, vector);
+			err = request_irq(intr->msix_entries[vector].vector,
+					  vmxnet3_msix_rx, 0,
+					  adapter->rx_queue[i].name,
+					  &(adapter->rx_queue[i]));
+			if (err) {
+				printk(KERN_ERR "Failed to request irq for MSIX"
+				       ", %s, error %d\n",
+				       adapter->rx_queue[i].name, err);
+				return err;
+			}
+
+			adapter->rx_queue[i].comp_ring.intr_idx = vector++;
+		}
+
+		sprintf(intr->event_msi_vector_name, "%s-event-%d",
+			adapter->netdev->name, vector);
+		err = request_irq(intr->msix_entries[vector].vector,
+				  vmxnet3_msix_event, 0,
+				  intr->event_msi_vector_name, adapter->netdev);
+		intr->event_intr_idx = vector;
+
+	} else if (intr->type == VMXNET3_IT_MSI) {
+		adapter->num_rx_queues = 1;
 		err = request_irq(adapter->pdev->irq, vmxnet3_intr, 0,
 				  adapter->netdev->name, adapter->netdev);
-	} else
+	} else {
 #endif
-	{
+		adapter->num_rx_queues = 1;
 		err = request_irq(adapter->pdev->irq, vmxnet3_intr,
 				  IRQF_SHARED, adapter->netdev->name,
 				  adapter->netdev);
+#ifdef CONFIG_PCI_MSI
 	}
-
-	if (err)
+#endif
+	intr->num_intrs = vector + 1;
+	if (err) {
 		printk(KERN_ERR "Failed to request irq %s (intr type:%d), error"
-		       ":%d\n", adapter->netdev->name, adapter->intr.type, err);
+		       ":%d\n", adapter->netdev->name, intr->type, err);
+	} else {
+		/* Number of rx queues will not change after this */
+		for (i = 0; i < adapter->num_rx_queues; i++) {
+			struct vmxnet3_rx_queue *rq = &adapter->rx_queue[i];
+			rq->qid = i;
+			rq->qid2 = i + adapter->num_rx_queues;
+		}
 
 
-	if (!err) {
-		int i;
-		/* init our intr settings */
-		for (i = 0; i < adapter->intr.num_intrs; i++)
-			adapter->intr.mod_levels[i] = UPT1_IML_ADAPTIVE;
 
-		/* next setup intr index for all intr sources */
-		adapter->tx_queue.comp_ring.intr_idx = 0;
-		adapter->rx_queue.comp_ring.intr_idx = 0;
-		adapter->intr.event_intr_idx = 0;
+		/* init our intr settings */
+		for (i = 0; i < intr->num_intrs; i++)
+			intr->mod_levels[i] = UPT1_IML_ADAPTIVE;
+		if (adapter->intr.type != VMXNET3_IT_MSIX) {
+			adapter->intr.event_intr_idx = 0;
+			for (i = 0; i < adapter->num_tx_queues; i++)
+				adapter->tx_queue[i].comp_ring.intr_idx = 0;
+			adapter->rx_queue[0].comp_ring.intr_idx = 0;
+		}
 
 		printk(KERN_INFO "%s: intr type %u, mode %u, %u vectors "
-		       "allocated\n", adapter->netdev->name, adapter->intr.type,
-		       adapter->intr.mask_mode, adapter->intr.num_intrs);
+		       "allocated\n", adapter->netdev->name, intr->type,
+		       intr->mask_mode, intr->num_intrs);
 	}
 
 	return err;
@@ -1522,18 +1817,32 @@ vmxnet3_request_irqs(struct vmxnet3_adap
 static void
 vmxnet3_free_irqs(struct vmxnet3_adapter *adapter)
 {
-	BUG_ON(adapter->intr.type == VMXNET3_IT_AUTO ||
-	       adapter->intr.num_intrs <= 0);
+	struct vmxnet3_intr *intr = &adapter->intr;
+	BUG_ON(intr->type == VMXNET3_IT_AUTO || intr->num_intrs <= 0);
 
-	switch (adapter->intr.type) {
+	switch (intr->type) {
 #ifdef CONFIG_PCI_MSI
 	case VMXNET3_IT_MSIX:
 	{
-		int i;
+		int i, vector = 0;
 
-		for (i = 0; i < adapter->intr.num_intrs; i++)
-			free_irq(adapter->intr.msix_entries[i].vector,
-				 adapter->netdev);
+		if (adapter->share_intr != VMXNET3_INTR_BUDDYSHARE) {
+			for (i = 0; i < adapter->num_tx_queues; i++) {
+				free_irq(intr->msix_entries[vector++].vector,
+					 &(adapter->tx_queue[i]));
+				if (adapter->share_intr == VMXNET3_INTR_TXSHARE)
+					break;
+			}
+		}
+
+		for (i = 0; i < adapter->num_rx_queues; i++) {
+			free_irq(intr->msix_entries[vector++].vector,
+				 &(adapter->rx_queue[i]));
+		}
+
+		free_irq(intr->msix_entries[vector].vector,
+			 adapter->netdev);
+		BUG_ON(vector >= intr->num_intrs);
 		break;
 	}
 #endif
@@ -1554,18 +1863,14 @@ vmxnet3_vlan_rx_register(struct net_devi
 	struct vmxnet3_adapter *adapter = netdev_priv(netdev);
 	struct Vmxnet3_DriverShared *shared = adapter->shared;
 	u32 *vfTable = adapter->shared->devRead.rxFilterConf.vfTable;
+	unsigned long flags;
 
 	if (grp) {
 		/* add vlan rx stripping. */
 		if (adapter->netdev->features & NETIF_F_HW_VLAN_RX) {
 			int i;
-			struct Vmxnet3_DSDevRead *devRead = &shared->devRead;
 			adapter->vlan_grp = grp;
 
-			/* update FEATURES to device */
-			devRead->misc.uptFeatures |= UPT1_F_RXVLAN;
-			VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
-					       VMXNET3_CMD_UPDATE_FEATURE);
 			/*
 			 *  Clear entire vfTable; then enable untagged pkts.
 			 *  Note: setting one entry in vfTable to non-zero turns
@@ -1575,8 +1880,10 @@ vmxnet3_vlan_rx_register(struct net_devi
 				vfTable[i] = 0;
 
 			VMXNET3_SET_VFTABLE_ENTRY(vfTable, 0);
+			spin_lock_irqsave(&adapter->cmd_lock, flags);
 			VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
 					       VMXNET3_CMD_UPDATE_VLAN_FILTERS);
+			spin_unlock_irqrestore(&adapter->cmd_lock, flags);
 		} else {
 			printk(KERN_ERR "%s: vlan_rx_register when device has "
 			       "no NETIF_F_HW_VLAN_RX\n", netdev->name);
@@ -1595,13 +1902,10 @@ vmxnet3_vlan_rx_register(struct net_devi
 				 */
 				vfTable[i] = 0;
 			}
+			spin_lock_irqsave(&adapter->cmd_lock, flags);
 			VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
 					       VMXNET3_CMD_UPDATE_VLAN_FILTERS);
-
-			/* update FEATURES to device */
-			devRead->misc.uptFeatures &= ~UPT1_F_RXVLAN;
-			VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
-					       VMXNET3_CMD_UPDATE_FEATURE);
+			spin_unlock_irqrestore(&adapter->cmd_lock, flags);
 		}
 	}
 }
@@ -1634,10 +1938,13 @@ vmxnet3_vlan_rx_add_vid(struct net_devic
 {
 	struct vmxnet3_adapter *adapter = netdev_priv(netdev);
 	u32 *vfTable = adapter->shared->devRead.rxFilterConf.vfTable;
+	unsigned long flags;
 
 	VMXNET3_SET_VFTABLE_ENTRY(vfTable, vid);
+	spin_lock_irqsave(&adapter->cmd_lock, flags);
 	VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
 			       VMXNET3_CMD_UPDATE_VLAN_FILTERS);
+	spin_unlock_irqrestore(&adapter->cmd_lock, flags);
 }
 
 
@@ -1646,10 +1953,13 @@ vmxnet3_vlan_rx_kill_vid(struct net_devi
 {
 	struct vmxnet3_adapter *adapter = netdev_priv(netdev);
 	u32 *vfTable = adapter->shared->devRead.rxFilterConf.vfTable;
+	unsigned long flags;
 
 	VMXNET3_CLEAR_VFTABLE_ENTRY(vfTable, vid);
+	spin_lock_irqsave(&adapter->cmd_lock, flags);
 	VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
 			       VMXNET3_CMD_UPDATE_VLAN_FILTERS);
+	spin_unlock_irqrestore(&adapter->cmd_lock, flags);
 }
 
 
@@ -1680,6 +1990,7 @@ static void
 vmxnet3_set_mc(struct net_device *netdev)
 {
 	struct vmxnet3_adapter *adapter = netdev_priv(netdev);
+	unsigned long flags;
 	struct Vmxnet3_RxFilterConf *rxConf =
 					&adapter->shared->devRead.rxFilterConf;
 	u8 *new_table = NULL;
@@ -1715,6 +2026,7 @@ vmxnet3_set_mc(struct net_device *netdev
 		rxConf->mfTablePA = 0;
 	}
 
+	spin_lock_irqsave(&adapter->cmd_lock, flags);
 	if (new_mode != rxConf->rxMode) {
 		rxConf->rxMode = cpu_to_le32(new_mode);
 		VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
@@ -1723,10 +2035,20 @@ vmxnet3_set_mc(struct net_device *netdev
 
 	VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
 			       VMXNET3_CMD_UPDATE_MAC_FILTERS);
+	spin_unlock_irqrestore(&adapter->cmd_lock, flags);
 
 	kfree(new_table);
 }
 
+void
+vmxnet3_rq_destroy_all(struct vmxnet3_adapter *adapter)
+{
+	int i;
+
+	for (i = 0; i < adapter->num_rx_queues; i++)
+		vmxnet3_rq_destroy(&adapter->rx_queue[i], adapter);
+}
+
 
 /*
  *   Set up driver_shared based on settings in adapter.
@@ -1766,48 +2088,78 @@ vmxnet3_setup_driver_shared(struct vmxne
 		devRead->misc.uptFeatures |= UPT1_F_LRO;
 		devRead->misc.maxNumRxSG = cpu_to_le16(1 + MAX_SKB_FRAGS);
 	}
-	if ((adapter->netdev->features & NETIF_F_HW_VLAN_RX) &&
-	    adapter->vlan_grp) {
+	if (adapter->netdev->features & NETIF_F_HW_VLAN_RX)
 		devRead->misc.uptFeatures |= UPT1_F_RXVLAN;
-	}
 
 	devRead->misc.mtu = cpu_to_le32(adapter->netdev->mtu);
 	devRead->misc.queueDescPA = cpu_to_le64(adapter->queue_desc_pa);
 	devRead->misc.queueDescLen = cpu_to_le32(
-				     sizeof(struct Vmxnet3_TxQueueDesc) +
-				     sizeof(struct Vmxnet3_RxQueueDesc));
+		adapter->num_tx_queues * sizeof(struct Vmxnet3_TxQueueDesc) +
+		adapter->num_rx_queues * sizeof(struct Vmxnet3_RxQueueDesc));
 
 	/* tx queue settings */
-	BUG_ON(adapter->tx_queue.tx_ring.base == NULL);
-
-	devRead->misc.numTxQueues = 1;
-	tqc = &adapter->tqd_start->conf;
-	tqc->txRingBasePA   = cpu_to_le64(adapter->tx_queue.tx_ring.basePA);
-	tqc->dataRingBasePA = cpu_to_le64(adapter->tx_queue.data_ring.basePA);
-	tqc->compRingBasePA = cpu_to_le64(adapter->tx_queue.comp_ring.basePA);
-	tqc->ddPA           = cpu_to_le64(virt_to_phys(
-						adapter->tx_queue.buf_info));
-	tqc->txRingSize     = cpu_to_le32(adapter->tx_queue.tx_ring.size);
-	tqc->dataRingSize   = cpu_to_le32(adapter->tx_queue.data_ring.size);
-	tqc->compRingSize   = cpu_to_le32(adapter->tx_queue.comp_ring.size);
-	tqc->ddLen          = cpu_to_le32(sizeof(struct vmxnet3_tx_buf_info) *
-			      tqc->txRingSize);
-	tqc->intrIdx        = adapter->tx_queue.comp_ring.intr_idx;
+	devRead->misc.numTxQueues =  adapter->num_tx_queues;
+	for (i = 0; i < adapter->num_tx_queues; i++) {
+		struct vmxnet3_tx_queue	*tq = &adapter->tx_queue[i];
+		BUG_ON(adapter->tx_queue[i].tx_ring.base == NULL);
+		tqc = &adapter->tqd_start[i].conf;
+		tqc->txRingBasePA   = cpu_to_le64(tq->tx_ring.basePA);
+		tqc->dataRingBasePA = cpu_to_le64(tq->data_ring.basePA);
+		tqc->compRingBasePA = cpu_to_le64(tq->comp_ring.basePA);
+		tqc->ddPA           = cpu_to_le64(virt_to_phys(tq->buf_info));
+		tqc->txRingSize     = cpu_to_le32(tq->tx_ring.size);
+		tqc->dataRingSize   = cpu_to_le32(tq->data_ring.size);
+		tqc->compRingSize   = cpu_to_le32(tq->comp_ring.size);
+		tqc->ddLen          = cpu_to_le32(
+					sizeof(struct vmxnet3_tx_buf_info) *
+					tqc->txRingSize);
+		tqc->intrIdx        = tq->comp_ring.intr_idx;
+	}
 
 	/* rx queue settings */
-	devRead->misc.numRxQueues = 1;
-	rqc = &adapter->rqd_start->conf;
-	rqc->rxRingBasePA[0] = cpu_to_le64(adapter->rx_queue.rx_ring[0].basePA);
-	rqc->rxRingBasePA[1] = cpu_to_le64(adapter->rx_queue.rx_ring[1].basePA);
-	rqc->compRingBasePA  = cpu_to_le64(adapter->rx_queue.comp_ring.basePA);
-	rqc->ddPA            = cpu_to_le64(virt_to_phys(
-						adapter->rx_queue.buf_info));
-	rqc->rxRingSize[0]   = cpu_to_le32(adapter->rx_queue.rx_ring[0].size);
-	rqc->rxRingSize[1]   = cpu_to_le32(adapter->rx_queue.rx_ring[1].size);
-	rqc->compRingSize    = cpu_to_le32(adapter->rx_queue.comp_ring.size);
-	rqc->ddLen           = cpu_to_le32(sizeof(struct vmxnet3_rx_buf_info) *
-			       (rqc->rxRingSize[0] + rqc->rxRingSize[1]));
-	rqc->intrIdx         = adapter->rx_queue.comp_ring.intr_idx;
+	devRead->misc.numRxQueues = adapter->num_rx_queues;
+	for (i = 0; i < adapter->num_rx_queues; i++) {
+		struct vmxnet3_rx_queue	*rq = &adapter->rx_queue[i];
+		rqc = &adapter->rqd_start[i].conf;
+		rqc->rxRingBasePA[0] = cpu_to_le64(rq->rx_ring[0].basePA);
+		rqc->rxRingBasePA[1] = cpu_to_le64(rq->rx_ring[1].basePA);
+		rqc->compRingBasePA  = cpu_to_le64(rq->comp_ring.basePA);
+		rqc->ddPA            = cpu_to_le64(virt_to_phys(
+							rq->buf_info));
+		rqc->rxRingSize[0]   = cpu_to_le32(rq->rx_ring[0].size);
+		rqc->rxRingSize[1]   = cpu_to_le32(rq->rx_ring[1].size);
+		rqc->compRingSize    = cpu_to_le32(rq->comp_ring.size);
+		rqc->ddLen           = cpu_to_le32(
+					sizeof(struct vmxnet3_rx_buf_info) *
+					(rqc->rxRingSize[0] +
+					 rqc->rxRingSize[1]));
+		rqc->intrIdx         = rq->comp_ring.intr_idx;
+	}
+
+#ifdef VMXNET3_RSS
+	memset(adapter->rss_conf, 0, sizeof(*adapter->rss_conf));
+
+	if (adapter->rss) {
+		struct UPT1_RSSConf *rssConf = adapter->rss_conf;
+		devRead->misc.uptFeatures |= UPT1_F_RSS;
+		devRead->misc.numRxQueues = adapter->num_rx_queues;
+		rssConf->hashType = UPT1_RSS_HASH_TYPE_TCP_IPV4 |
+				    UPT1_RSS_HASH_TYPE_IPV4 |
+				    UPT1_RSS_HASH_TYPE_TCP_IPV6 |
+				    UPT1_RSS_HASH_TYPE_IPV6;
+		rssConf->hashFunc = UPT1_RSS_HASH_FUNC_TOEPLITZ;
+		rssConf->hashKeySize = UPT1_RSS_MAX_KEY_SIZE;
+		rssConf->indTableSize = VMXNET3_RSS_IND_TABLE_SIZE;
+		get_random_bytes(&rssConf->hashKey[0], rssConf->hashKeySize);
+		for (i = 0; i < rssConf->indTableSize; i++)
+			rssConf->indTable[i] = i % adapter->num_rx_queues;
+
+		devRead->rssConfDesc.confVer = 1;
+		devRead->rssConfDesc.confLen = sizeof(*rssConf);
+		devRead->rssConfDesc.confPA  = virt_to_phys(rssConf);
+	}
+
+#endif /* VMXNET3_RSS */
 
 	/* intr settings */
 	devRead->intrConf.autoMask = adapter->intr.mask_mode ==
@@ -1822,6 +2174,8 @@ vmxnet3_setup_driver_shared(struct vmxne
 	/* rx filter settings */
 	devRead->rxFilterConf.rxMode = 0;
 	vmxnet3_restore_vlan(adapter);
+	vmxnet3_write_mac_addr(adapter, adapter->netdev->dev_addr);
+
 	/* the rest are already zeroed */
 }
 
@@ -1829,18 +2183,19 @@ vmxnet3_setup_driver_shared(struct vmxne
 int
 vmxnet3_activate_dev(struct vmxnet3_adapter *adapter)
 {
-	int err;
+	int err, i;
 	u32 ret;
+	unsigned long flags;
 
-	dev_dbg(&adapter->netdev->dev,
-		"%s: skb_buf_size %d, rx_buf_per_pkt %d, ring sizes"
-		" %u %u %u\n", adapter->netdev->name, adapter->skb_buf_size,
-		adapter->rx_buf_per_pkt, adapter->tx_queue.tx_ring.size,
-		adapter->rx_queue.rx_ring[0].size,
-		adapter->rx_queue.rx_ring[1].size);
+	dev_dbg(&adapter->netdev->dev, "%s: skb_buf_size %d, rx_buf_per_pkt %d,"
+		" ring sizes %u %u %u\n", adapter->netdev->name,
+		adapter->skb_buf_size, adapter->rx_buf_per_pkt,
+		adapter->tx_queue[0].tx_ring.size,
+		adapter->rx_queue[0].rx_ring[0].size,
+		adapter->rx_queue[0].rx_ring[1].size);
 
-	vmxnet3_tq_init(&adapter->tx_queue, adapter);
-	err = vmxnet3_rq_init(&adapter->rx_queue, adapter);
+	vmxnet3_tq_init_all(adapter);
+	err = vmxnet3_rq_init_all(adapter);
 	if (err) {
 		printk(KERN_ERR "Failed to init rx queue for %s: error %d\n",
 		       adapter->netdev->name, err);
@@ -1860,9 +2215,11 @@ vmxnet3_activate_dev(struct vmxnet3_adap
 			       adapter->shared_pa));
 	VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_DSAH, VMXNET3_GET_ADDR_HI(
 			       adapter->shared_pa));
+	spin_lock_irqsave(&adapter->cmd_lock, flags);
 	VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
 			       VMXNET3_CMD_ACTIVATE_DEV);
 	ret = VMXNET3_READ_BAR1_REG(adapter, VMXNET3_REG_CMD);
+	spin_unlock_irqrestore(&adapter->cmd_lock, flags);
 
 	if (ret != 0) {
 		printk(KERN_ERR "Failed to activate dev %s: error %u\n",
@@ -1870,10 +2227,15 @@ vmxnet3_activate_dev(struct vmxnet3_adap
 		err = -EINVAL;
 		goto activate_err;
 	}
-	VMXNET3_WRITE_BAR0_REG(adapter, VMXNET3_REG_RXPROD,
-			       adapter->rx_queue.rx_ring[0].next2fill);
-	VMXNET3_WRITE_BAR0_REG(adapter, VMXNET3_REG_RXPROD2,
-			       adapter->rx_queue.rx_ring[1].next2fill);
+
+	for (i = 0; i < adapter->num_rx_queues; i++) {
+		VMXNET3_WRITE_BAR0_REG(adapter,
+				VMXNET3_REG_RXPROD + i * VMXNET3_REG_ALIGN,
+				adapter->rx_queue[i].rx_ring[0].next2fill);
+		VMXNET3_WRITE_BAR0_REG(adapter, (VMXNET3_REG_RXPROD2 +
+				(i * VMXNET3_REG_ALIGN)),
+				adapter->rx_queue[i].rx_ring[1].next2fill);
+	}
 
 	/* Apply the rx filter settins last. */
 	vmxnet3_set_mc(adapter->netdev);
@@ -1883,8 +2245,8 @@ vmxnet3_activate_dev(struct vmxnet3_adap
 	 * tx queue if the link is up.
 	 */
 	vmxnet3_check_link(adapter, true);
-
-	napi_enable(&adapter->napi);
+	for (i = 0; i < adapter->num_rx_queues; i++)
+		napi_enable(&adapter->rx_queue[i].napi);
 	vmxnet3_enable_all_intrs(adapter);
 	clear_bit(VMXNET3_STATE_BIT_QUIESCED, &adapter->state);
 	return 0;
@@ -1896,7 +2258,7 @@ activate_err:
 irq_err:
 rq_err:
 	/* free up buffers we allocated */
-	vmxnet3_rq_cleanup(&adapter->rx_queue, adapter);
+	vmxnet3_rq_cleanup_all(adapter);
 	return err;
 }
 
@@ -1904,28 +2266,36 @@ rq_err:
 void
 vmxnet3_reset_dev(struct vmxnet3_adapter *adapter)
 {
+	unsigned long flags;
+	spin_lock_irqsave(&adapter->cmd_lock, flags);
 	VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD, VMXNET3_CMD_RESET_DEV);
+	spin_unlock_irqrestore(&adapter->cmd_lock, flags);
 }
 
 
 int
 vmxnet3_quiesce_dev(struct vmxnet3_adapter *adapter)
 {
+	int i;
+	unsigned long flags;
 	if (test_and_set_bit(VMXNET3_STATE_BIT_QUIESCED, &adapter->state))
 		return 0;
 
 
+	spin_lock_irqsave(&adapter->cmd_lock, flags);
 	VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
 			       VMXNET3_CMD_QUIESCE_DEV);
+	spin_unlock_irqrestore(&adapter->cmd_lock, flags);
 	vmxnet3_disable_all_intrs(adapter);
 
-	napi_disable(&adapter->napi);
+	for (i = 0; i < adapter->num_rx_queues; i++)
+		napi_disable(&adapter->rx_queue[i].napi);
 	netif_tx_disable(adapter->netdev);
 	adapter->link_speed = 0;
 	netif_carrier_off(adapter->netdev);
 
-	vmxnet3_tq_cleanup(&adapter->tx_queue, adapter);
-	vmxnet3_rq_cleanup(&adapter->rx_queue, adapter);
+	vmxnet3_tq_cleanup_all(adapter);
+	vmxnet3_rq_cleanup_all(adapter);
 	vmxnet3_free_irqs(adapter);
 	return 0;
 }
@@ -2047,7 +2417,9 @@ vmxnet3_free_pci_resources(struct vmxnet
 static void
 vmxnet3_adjust_rx_ring_size(struct vmxnet3_adapter *adapter)
 {
-	size_t sz;
+	size_t sz, i, ring0_size, ring1_size, comp_size;
+	struct vmxnet3_rx_queue	*rq = &adapter->rx_queue[0];
+
 
 	if (adapter->netdev->mtu <= VMXNET3_MAX_SKB_BUF_SIZE -
 				    VMXNET3_MAX_ETH_HDR_SIZE) {
@@ -2069,11 +2441,19 @@ vmxnet3_adjust_rx_ring_size(struct vmxne
 	 * rx_buf_per_pkt * VMXNET3_RING_SIZE_ALIGN
 	 */
 	sz = adapter->rx_buf_per_pkt * VMXNET3_RING_SIZE_ALIGN;
-	adapter->rx_queue.rx_ring[0].size = (adapter->rx_queue.rx_ring[0].size +
-					     sz - 1) / sz * sz;
-	adapter->rx_queue.rx_ring[0].size = min_t(u32,
-					    adapter->rx_queue.rx_ring[0].size,
-					    VMXNET3_RX_RING_MAX_SIZE / sz * sz);
+	ring0_size = adapter->rx_queue[0].rx_ring[0].size;
+	ring0_size = (ring0_size + sz - 1) / sz * sz;
+	ring0_size = min_t(u32, ring0_size, VMXNET3_RX_RING_MAX_SIZE /
+			   sz * sz);
+	ring1_size = adapter->rx_queue[0].rx_ring[1].size;
+	comp_size = ring0_size + ring1_size;
+
+	for (i = 0; i < adapter->num_rx_queues; i++) {
+		rq = &adapter->rx_queue[i];
+		rq->rx_ring[0].size = ring0_size;
+		rq->rx_ring[1].size = ring1_size;
+		rq->comp_ring.size = comp_size;
+	}
 }
 
 
@@ -2081,29 +2461,53 @@ int
 vmxnet3_create_queues(struct vmxnet3_adapter *adapter, u32 tx_ring_size,
 		      u32 rx_ring_size, u32 rx_ring2_size)
 {
-	int err;
+	int err = 0, i;
 
-	adapter->tx_queue.tx_ring.size   = tx_ring_size;
-	adapter->tx_queue.data_ring.size = tx_ring_size;
-	adapter->tx_queue.comp_ring.size = tx_ring_size;
-	adapter->tx_queue.shared = &adapter->tqd_start->ctrl;
-	adapter->tx_queue.stopped = true;
-	err = vmxnet3_tq_create(&adapter->tx_queue, adapter);
-	if (err)
-		return err;
+	for (i = 0; i < adapter->num_tx_queues; i++) {
+		struct vmxnet3_tx_queue	*tq = &adapter->tx_queue[i];
+		tq->tx_ring.size   = tx_ring_size;
+		tq->data_ring.size = tx_ring_size;
+		tq->comp_ring.size = tx_ring_size;
+		tq->shared = &adapter->tqd_start[i].ctrl;
+		tq->stopped = true;
+		tq->adapter = adapter;
+		tq->qid = i;
+		err = vmxnet3_tq_create(tq, adapter);
+		/*
+		 * Too late to change num_tx_queues. We cannot do away with
+		 * lesser number of queues than what we asked for
+		 */
+		if (err)
+			goto queue_err;
+	}
 
-	adapter->rx_queue.rx_ring[0].size = rx_ring_size;
-	adapter->rx_queue.rx_ring[1].size = rx_ring2_size;
+	adapter->rx_queue[0].rx_ring[0].size = rx_ring_size;
+	adapter->rx_queue[0].rx_ring[1].size = rx_ring2_size;
 	vmxnet3_adjust_rx_ring_size(adapter);
-	adapter->rx_queue.comp_ring.size  = adapter->rx_queue.rx_ring[0].size +
-					    adapter->rx_queue.rx_ring[1].size;
-	adapter->rx_queue.qid  = 0;
-	adapter->rx_queue.qid2 = 1;
-	adapter->rx_queue.shared = &adapter->rqd_start->ctrl;
-	err = vmxnet3_rq_create(&adapter->rx_queue, adapter);
-	if (err)
-		vmxnet3_tq_destroy(&adapter->tx_queue, adapter);
-
+	for (i = 0; i < adapter->num_rx_queues; i++) {
+		struct vmxnet3_rx_queue *rq = &adapter->rx_queue[i];
+		/* qid and qid2 for rx queues will be assigned later when num
+		 * of rx queues is finalized after allocating intrs */
+		rq->shared = &adapter->rqd_start[i].ctrl;
+		rq->adapter = adapter;
+		err = vmxnet3_rq_create(rq, adapter);
+		if (err) {
+			if (i == 0) {
+				printk(KERN_ERR "Could not allocate any rx"
+				       "queues. Aborting.\n");
+				goto queue_err;
+			} else {
+				printk(KERN_INFO "Number of rx queues changed "
+				       "to : %d.\n", i);
+				adapter->num_rx_queues = i;
+				err = 0;
+				break;
+			}
+		}
+	}
+	return err;
+queue_err:
+	vmxnet3_tq_destroy_all(adapter);
 	return err;
 }
 
@@ -2111,11 +2515,12 @@ static int
 vmxnet3_open(struct net_device *netdev)
 {
 	struct vmxnet3_adapter *adapter;
-	int err;
+	int err, i;
 
 	adapter = netdev_priv(netdev);
 
-	spin_lock_init(&adapter->tx_queue.tx_lock);
+	for (i = 0; i < adapter->num_tx_queues; i++)
+		spin_lock_init(&adapter->tx_queue[i].tx_lock);
 
 	err = vmxnet3_create_queues(adapter, VMXNET3_DEF_TX_RING_SIZE,
 				    VMXNET3_DEF_RX_RING_SIZE,
@@ -2130,8 +2535,8 @@ vmxnet3_open(struct net_device *netdev)
 	return 0;
 
 activate_err:
-	vmxnet3_rq_destroy(&adapter->rx_queue, adapter);
-	vmxnet3_tq_destroy(&adapter->tx_queue, adapter);
+	vmxnet3_rq_destroy_all(adapter);
+	vmxnet3_tq_destroy_all(adapter);
 queue_err:
 	return err;
 }
@@ -2151,8 +2556,8 @@ vmxnet3_close(struct net_device *netdev)
 
 	vmxnet3_quiesce_dev(adapter);
 
-	vmxnet3_rq_destroy(&adapter->rx_queue, adapter);
-	vmxnet3_tq_destroy(&adapter->tx_queue, adapter);
+	vmxnet3_rq_destroy_all(adapter);
+	vmxnet3_tq_destroy_all(adapter);
 
 	clear_bit(VMXNET3_STATE_BIT_RESETTING, &adapter->state);
 
@@ -2164,6 +2569,8 @@ vmxnet3_close(struct net_device *netdev)
 void
 vmxnet3_force_close(struct vmxnet3_adapter *adapter)
 {
+	int i;
+
 	/*
 	 * we must clear VMXNET3_STATE_BIT_RESETTING, otherwise
 	 * vmxnet3_close() will deadlock.
@@ -2171,7 +2578,8 @@ vmxnet3_force_close(struct vmxnet3_adapt
 	BUG_ON(test_bit(VMXNET3_STATE_BIT_RESETTING, &adapter->state));
 
 	/* we need to enable NAPI, otherwise dev_close will deadlock */
-	napi_enable(&adapter->napi);
+	for (i = 0; i < adapter->num_rx_queues; i++)
+		napi_enable(&adapter->rx_queue[i].napi);
 	dev_close(adapter->netdev);
 }
 
@@ -2202,14 +2610,11 @@ vmxnet3_change_mtu(struct net_device *ne
 		vmxnet3_reset_dev(adapter);
 
 		/* we need to re-create the rx queue based on the new mtu */
-		vmxnet3_rq_destroy(&adapter->rx_queue, adapter);
+		vmxnet3_rq_destroy_all(adapter);
 		vmxnet3_adjust_rx_ring_size(adapter);
-		adapter->rx_queue.comp_ring.size  =
-					adapter->rx_queue.rx_ring[0].size +
-					adapter->rx_queue.rx_ring[1].size;
-		err = vmxnet3_rq_create(&adapter->rx_queue, adapter);
+		err = vmxnet3_rq_create_all(adapter);
 		if (err) {
-			printk(KERN_ERR "%s: failed to re-create rx queue,"
+			printk(KERN_ERR "%s: failed to re-create rx queues,"
 				" error %d. Closing it.\n", netdev->name, err);
 			goto out;
 		}
@@ -2274,6 +2679,55 @@ vmxnet3_read_mac_addr(struct vmxnet3_ada
 	mac[5] = (tmp >> 8) & 0xff;
 }
 
+#ifdef CONFIG_PCI_MSI
+
+/*
+ * Enable MSIx vectors.
+ * Returns :
+ *	0 on successful enabling of required vectors,
+ *	VMXNET3_LINUX_MIN_MSIX_VECT when only minumum number of vectors required
+ *	 could be enabled.
+ *	number of vectors which can be enabled otherwise (this number is smaller
+ *	 than VMXNET3_LINUX_MIN_MSIX_VECT)
+ */
+
+static int
+vmxnet3_acquire_msix_vectors(struct vmxnet3_adapter *adapter,
+			     int vectors)
+{
+	int err = 0, vector_threshold;
+	vector_threshold = VMXNET3_LINUX_MIN_MSIX_VECT;
+
+	while (vectors >= vector_threshold) {
+		err = pci_enable_msix(adapter->pdev, adapter->intr.msix_entries,
+				      vectors);
+		if (!err) {
+			adapter->intr.num_intrs = vectors;
+			return 0;
+		} else if (err < 0) {
+			printk(KERN_ERR "Failed to enable MSI-X for %s, error"
+			       " %d\n",	adapter->netdev->name, err);
+			vectors = 0;
+		} else if (err < vector_threshold) {
+			break;
+		} else {
+			/* If fails to enable required number of MSI-x vectors
+			 * try enabling minimum number of vectors required.
+			 */
+			vectors = vector_threshold;
+			printk(KERN_ERR "Failed to enable %d MSI-X for %s, try"
+			       " %d instead\n", vectors, adapter->netdev->name,
+			       vector_threshold);
+		}
+	}
+
+	printk(KERN_INFO "Number of MSI-X interrupts which can be allocatedi"
+	       " are lower than min threshold required.\n");
+	return err;
+}
+
+
+#endif /* CONFIG_PCI_MSI */
 
 static void
 vmxnet3_alloc_intr_resources(struct vmxnet3_adapter *adapter)
@@ -2281,9 +2735,11 @@ vmxnet3_alloc_intr_resources(struct vmxn
 	u32 cfg;
 
 	/* intr settings */
+	spin_lock(&adapter->cmd_lock);
 	VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
 			       VMXNET3_CMD_GET_CONF_INTR);
 	cfg = VMXNET3_READ_BAR1_REG(adapter, VMXNET3_REG_CMD);
+	spin_unlock(&adapter->cmd_lock);
 	adapter->intr.type = cfg & 0x3;
 	adapter->intr.mask_mode = (cfg >> 2) & 0x3;
 
@@ -2293,16 +2749,47 @@ vmxnet3_alloc_intr_resources(struct vmxn
 
 #ifdef CONFIG_PCI_MSI
 	if (adapter->intr.type == VMXNET3_IT_MSIX) {
-		int err;
+		int vector, err = 0;
 
-		adapter->intr.msix_entries[0].entry = 0;
-		err = pci_enable_msix(adapter->pdev, adapter->intr.msix_entries,
-				      VMXNET3_LINUX_MAX_MSIX_VECT);
-		if (!err) {
-			adapter->intr.num_intrs = 1;
-			adapter->intr.type = VMXNET3_IT_MSIX;
+		adapter->intr.num_intrs = (adapter->share_intr ==
+					   VMXNET3_INTR_TXSHARE) ? 1 :
+					   adapter->num_tx_queues;
+		adapter->intr.num_intrs += (adapter->share_intr ==
+					   VMXNET3_INTR_BUDDYSHARE) ? 0 :
+					   adapter->num_rx_queues;
+		adapter->intr.num_intrs += 1;		/* for link event */
+
+		adapter->intr.num_intrs = (adapter->intr.num_intrs >
+					   VMXNET3_LINUX_MIN_MSIX_VECT
+					   ? adapter->intr.num_intrs :
+					   VMXNET3_LINUX_MIN_MSIX_VECT);
+
+		for (vector = 0; vector < adapter->intr.num_intrs; vector++)
+			adapter->intr.msix_entries[vector].entry = vector;
+
+		err = vmxnet3_acquire_msix_vectors(adapter,
+						   adapter->intr.num_intrs);
+		/* If we cannot allocate one MSIx vector per queue
+		 * then limit the number of rx queues to 1
+		 */
+		if (err == VMXNET3_LINUX_MIN_MSIX_VECT) {
+			if (adapter->share_intr != VMXNET3_INTR_BUDDYSHARE
+			    || adapter->num_rx_queues != 1) {
+				adapter->share_intr = VMXNET3_INTR_TXSHARE;
+				printk(KERN_ERR "Number of rx queues : 1\n");
+				adapter->num_rx_queues = 1;
+				adapter->intr.num_intrs =
+						VMXNET3_LINUX_MIN_MSIX_VECT;
+			}
 			return;
 		}
+		if (!err)
+			return;
+
+		/* If we cannot allocate MSIx vectors use only one rx queue */
+		printk(KERN_INFO "Failed to enable MSI-X for %s, error %d."
+		       "#rx queues : 1, try MSI\n", adapter->netdev->name, err);
+
 		adapter->intr.type = VMXNET3_IT_MSI;
 	}
 
@@ -2310,12 +2797,15 @@ vmxnet3_alloc_intr_resources(struct vmxn
 		int err;
 		err = pci_enable_msi(adapter->pdev);
 		if (!err) {
+			adapter->num_rx_queues = 1;
 			adapter->intr.num_intrs = 1;
 			return;
 		}
 	}
 #endif /* CONFIG_PCI_MSI */
 
+	adapter->num_rx_queues = 1;
+	printk(KERN_INFO "Using INTx interrupt, #Rx queues: 1.\n");
 	adapter->intr.type = VMXNET3_IT_INTX;
 
 	/* INT-X related setting */
@@ -2343,6 +2833,7 @@ vmxnet3_tx_timeout(struct net_device *ne
 
 	printk(KERN_ERR "%s: tx hang\n", adapter->netdev->name);
 	schedule_work(&adapter->work);
+	netif_wake_queue(adapter->netdev);
 }
 
 
@@ -2399,8 +2890,29 @@ vmxnet3_probe_device(struct pci_dev *pde
 	struct net_device *netdev;
 	struct vmxnet3_adapter *adapter;
 	u8 mac[ETH_ALEN];
+	int size;
+	int num_tx_queues;
+	int num_rx_queues;
+
+#ifdef VMXNET3_RSS
+	if (enable_mq)
+		num_rx_queues = min(VMXNET3_DEVICE_MAX_RX_QUEUES,
+				    (int)num_online_cpus());
+	else
+#endif
+		num_rx_queues = 1;
+
+	if (enable_mq)
+		num_tx_queues = min(VMXNET3_DEVICE_MAX_TX_QUEUES,
+				    (int)num_online_cpus());
+	else
+		num_tx_queues = 1;
+
+	netdev = alloc_etherdev_mq(sizeof(struct vmxnet3_adapter),
+				   max(num_tx_queues, num_rx_queues));
+	printk(KERN_INFO "# of Tx queues : %d, # of Rx queues : %d\n",
+	       num_tx_queues, num_rx_queues);
 
-	netdev = alloc_etherdev(sizeof(struct vmxnet3_adapter));
 	if (!netdev) {
 		printk(KERN_ERR "Failed to alloc ethernet device for adapter "
 			"%s\n",	pci_name(pdev));
@@ -2412,6 +2924,7 @@ vmxnet3_probe_device(struct pci_dev *pde
 	adapter->netdev = netdev;
 	adapter->pdev = pdev;
 
+	spin_lock_init(&adapter->cmd_lock);
 	adapter->shared = pci_alloc_consistent(adapter->pdev,
 			  sizeof(struct Vmxnet3_DriverShared),
 			  &adapter->shared_pa);
@@ -2422,9 +2935,12 @@ vmxnet3_probe_device(struct pci_dev *pde
 		goto err_alloc_shared;
 	}
 
-	adapter->tqd_start = pci_alloc_consistent(adapter->pdev,
-			     sizeof(struct Vmxnet3_TxQueueDesc) +
-			     sizeof(struct Vmxnet3_RxQueueDesc),
+	adapter->num_rx_queues = num_rx_queues;
+	adapter->num_tx_queues = num_tx_queues;
+
+	size = sizeof(struct Vmxnet3_TxQueueDesc) * adapter->num_tx_queues;
+	size += sizeof(struct Vmxnet3_RxQueueDesc) * adapter->num_rx_queues;
+	adapter->tqd_start = pci_alloc_consistent(adapter->pdev, size,
 			     &adapter->queue_desc_pa);
 
 	if (!adapter->tqd_start) {
@@ -2433,8 +2949,8 @@ vmxnet3_probe_device(struct pci_dev *pde
 		err = -ENOMEM;
 		goto err_alloc_queue_desc;
 	}
-	adapter->rqd_start = (struct Vmxnet3_RxQueueDesc *)(adapter->tqd_start
-							    + 1);
+	adapter->rqd_start = (struct Vmxnet3_RxQueueDesc *)(adapter->tqd_start +
+							adapter->num_tx_queues);
 
 	adapter->pm_conf = kmalloc(sizeof(struct Vmxnet3_PMConf), GFP_KERNEL);
 	if (adapter->pm_conf == NULL) {
@@ -2444,6 +2960,17 @@ vmxnet3_probe_device(struct pci_dev *pde
 		goto err_alloc_pm;
 	}
 
+#ifdef VMXNET3_RSS
+
+	adapter->rss_conf = kmalloc(sizeof(struct UPT1_RSSConf), GFP_KERNEL);
+	if (adapter->rss_conf == NULL) {
+		printk(KERN_ERR "Failed to allocate memory for %s\n",
+		       pci_name(pdev));
+		err = -ENOMEM;
+		goto err_alloc_rss;
+	}
+#endif /* VMXNET3_RSS */
+
 	err = vmxnet3_alloc_pci_resources(adapter, &dma64);
 	if (err < 0)
 		goto err_alloc_pci;
@@ -2471,18 +2998,48 @@ vmxnet3_probe_device(struct pci_dev *pde
 	vmxnet3_declare_features(adapter, dma64);
 
 	adapter->dev_number = atomic_read(&devices_found);
+
+	 adapter->share_intr = irq_share_mode;
+	if (adapter->share_intr == VMXNET3_INTR_BUDDYSHARE &&
+	    adapter->num_tx_queues != adapter->num_rx_queues)
+		adapter->share_intr = VMXNET3_INTR_DONTSHARE;
+
 	vmxnet3_alloc_intr_resources(adapter);
 
+#ifdef VMXNET3_RSS
+	if (adapter->num_rx_queues > 1 &&
+	    adapter->intr.type == VMXNET3_IT_MSIX) {
+		adapter->rss = true;
+		printk(KERN_INFO "RSS is enabled.\n");
+	} else {
+		adapter->rss = false;
+	}
+#endif
+
 	vmxnet3_read_mac_addr(adapter, mac);
 	memcpy(netdev->dev_addr,  mac, netdev->addr_len);
 
 	netdev->netdev_ops = &vmxnet3_netdev_ops;
-	netdev->watchdog_timeo = 5 * HZ;
 	vmxnet3_set_ethtool_ops(netdev);
+	netdev->watchdog_timeo = 5 * HZ;
 
 	INIT_WORK(&adapter->work, vmxnet3_reset_work);
 
-	netif_napi_add(netdev, &adapter->napi, vmxnet3_poll, 64);
+	if (adapter->intr.type == VMXNET3_IT_MSIX) {
+		int i;
+		for (i = 0; i < adapter->num_rx_queues; i++) {
+			netif_napi_add(adapter->netdev,
+				       &adapter->rx_queue[i].napi,
+				       vmxnet3_poll_rx_only, 64);
+		}
+	} else {
+		netif_napi_add(adapter->netdev, &adapter->rx_queue[0].napi,
+			       vmxnet3_poll, 64);
+	}
+
+	netif_set_real_num_tx_queues(adapter->netdev, adapter->num_tx_queues);
+	netif_set_real_num_rx_queues(adapter->netdev, adapter->num_rx_queues);
+
 	SET_NETDEV_DEV(netdev, &pdev->dev);
 	err = register_netdev(netdev);
 
@@ -2502,11 +3059,14 @@ err_register:
 err_ver:
 	vmxnet3_free_pci_resources(adapter);
 err_alloc_pci:
+#ifdef VMXNET3_RSS
+	kfree(adapter->rss_conf);
+err_alloc_rss:
+#endif
 	kfree(adapter->pm_conf);
 err_alloc_pm:
-	pci_free_consistent(adapter->pdev, sizeof(struct Vmxnet3_TxQueueDesc) +
-			    sizeof(struct Vmxnet3_RxQueueDesc),
-			    adapter->tqd_start, adapter->queue_desc_pa);
+	pci_free_consistent(adapter->pdev, size, adapter->tqd_start,
+			    adapter->queue_desc_pa);
 err_alloc_queue_desc:
 	pci_free_consistent(adapter->pdev, sizeof(struct Vmxnet3_DriverShared),
 			    adapter->shared, adapter->shared_pa);
@@ -2522,17 +3082,32 @@ vmxnet3_remove_device(struct pci_dev *pd
 {
 	struct net_device *netdev = pci_get_drvdata(pdev);
 	struct vmxnet3_adapter *adapter = netdev_priv(netdev);
+	int size = 0;
+	int num_rx_queues;
 
-	flush_scheduled_work();
+#ifdef VMXNET3_RSS
+	if (enable_mq)
+		num_rx_queues = min(VMXNET3_DEVICE_MAX_RX_QUEUES,
+				    (int)num_online_cpus());
+	else
+#endif
+		num_rx_queues = 1;
+
+	cancel_work_sync(&adapter->work);
 
 	unregister_netdev(netdev);
 
 	vmxnet3_free_intr_resources(adapter);
 	vmxnet3_free_pci_resources(adapter);
+#ifdef VMXNET3_RSS
+	kfree(adapter->rss_conf);
+#endif
 	kfree(adapter->pm_conf);
-	pci_free_consistent(adapter->pdev, sizeof(struct Vmxnet3_TxQueueDesc) +
-			    sizeof(struct Vmxnet3_RxQueueDesc),
-			    adapter->tqd_start, adapter->queue_desc_pa);
+
+	size = sizeof(struct Vmxnet3_TxQueueDesc) * adapter->num_tx_queues;
+	size += sizeof(struct Vmxnet3_RxQueueDesc) * num_rx_queues;
+	pci_free_consistent(adapter->pdev, size, adapter->tqd_start,
+			    adapter->queue_desc_pa);
 	pci_free_consistent(adapter->pdev, sizeof(struct Vmxnet3_DriverShared),
 			    adapter->shared, adapter->shared_pa);
 	free_netdev(netdev);
@@ -2553,17 +3128,21 @@ vmxnet3_suspend(struct device *device)
 	u8 *arpreq;
 	struct in_device *in_dev;
 	struct in_ifaddr *ifa;
+	unsigned long flags;
 	int i = 0;
 
 	if (!netif_running(netdev))
 		return 0;
 
+	for (i = 0; i < adapter->num_rx_queues; i++)
+		napi_disable(&adapter->rx_queue[i].napi);
+
 	vmxnet3_disable_all_intrs(adapter);
 	vmxnet3_free_irqs(adapter);
 	vmxnet3_free_intr_resources(adapter);
 
 	netif_device_detach(netdev);
-	netif_stop_queue(netdev);
+	netif_tx_stop_all_queues(netdev);
 
 	/* Create wake-up filters. */
 	pmConf = adapter->pm_conf;
@@ -2633,8 +3212,10 @@ skip_arp:
 	adapter->shared->devRead.pmConfDesc.confPA = cpu_to_le64(virt_to_phys(
 								 pmConf));
 
+	spin_lock_irqsave(&adapter->cmd_lock, flags);
 	VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
 			       VMXNET3_CMD_UPDATE_PMCFG);
+	spin_unlock_irqrestore(&adapter->cmd_lock, flags);
 
 	pci_save_state(pdev);
 	pci_enable_wake(pdev, pci_choose_state(pdev, PMSG_SUSPEND),
@@ -2649,7 +3230,8 @@ skip_arp:
 static int
 vmxnet3_resume(struct device *device)
 {
-	int err;
+	int err, i = 0;
+	unsigned long flags;
 	struct pci_dev *pdev = to_pci_dev(device);
 	struct net_device *netdev = pci_get_drvdata(pdev);
 	struct vmxnet3_adapter *adapter = netdev_priv(netdev);
@@ -2677,10 +3259,14 @@ vmxnet3_resume(struct device *device)
 
 	pci_enable_wake(pdev, PCI_D0, 0);
 
+	spin_lock_irqsave(&adapter->cmd_lock, flags);
 	VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
 			       VMXNET3_CMD_UPDATE_PMCFG);
+	spin_unlock_irqrestore(&adapter->cmd_lock, flags);
 	vmxnet3_alloc_intr_resources(adapter);
 	vmxnet3_request_irqs(adapter);
+	for (i = 0; i < adapter->num_rx_queues; i++)
+		napi_enable(&adapter->rx_queue[i].napi);
 	vmxnet3_enable_all_intrs(adapter);
 
 	return 0;
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/vmxnet3/vmxnet3_ethtool.c linux-libre-2.6.38-gnu1/drivers/net/vmxnet3/vmxnet3_ethtool.c
--- linux-libre-2.6.37-gnu1/drivers/net/vmxnet3/vmxnet3_ethtool.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/vmxnet3/vmxnet3_ethtool.c	2011-03-14 21:20:32.000000000 -0400
@@ -45,6 +45,7 @@ static int
 vmxnet3_set_rx_csum(struct net_device *netdev, u32 val)
 {
 	struct vmxnet3_adapter *adapter = netdev_priv(netdev);
+	unsigned long flags;
 
 	if (adapter->rxcsum != val) {
 		adapter->rxcsum = val;
@@ -56,8 +57,10 @@ vmxnet3_set_rx_csum(struct net_device *n
 				adapter->shared->devRead.misc.uptFeatures &=
 				~UPT1_F_RXCSUM;
 
+			spin_lock_irqsave(&adapter->cmd_lock, flags);
 			VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
 					       VMXNET3_CMD_UPDATE_FEATURE);
+			spin_unlock_irqrestore(&adapter->cmd_lock, flags);
 		}
 	}
 	return 0;
@@ -68,76 +71,78 @@ vmxnet3_set_rx_csum(struct net_device *n
 static const struct vmxnet3_stat_desc
 vmxnet3_tq_dev_stats[] = {
 	/* description,         offset */
-	{ "TSO pkts tx",        offsetof(struct UPT1_TxStats, TSOPktsTxOK) },
-	{ "TSO bytes tx",       offsetof(struct UPT1_TxStats, TSOBytesTxOK) },
-	{ "ucast pkts tx",      offsetof(struct UPT1_TxStats, ucastPktsTxOK) },
-	{ "ucast bytes tx",     offsetof(struct UPT1_TxStats, ucastBytesTxOK) },
-	{ "mcast pkts tx",      offsetof(struct UPT1_TxStats, mcastPktsTxOK) },
-	{ "mcast bytes tx",     offsetof(struct UPT1_TxStats, mcastBytesTxOK) },
-	{ "bcast pkts tx",      offsetof(struct UPT1_TxStats, bcastPktsTxOK) },
-	{ "bcast bytes tx",     offsetof(struct UPT1_TxStats, bcastBytesTxOK) },
-	{ "pkts tx err",        offsetof(struct UPT1_TxStats, pktsTxError) },
-	{ "pkts tx discard",    offsetof(struct UPT1_TxStats, pktsTxDiscard) },
+	{ "Tx Queue#",        0 },
+	{ "  TSO pkts tx",	offsetof(struct UPT1_TxStats, TSOPktsTxOK) },
+	{ "  TSO bytes tx",	offsetof(struct UPT1_TxStats, TSOBytesTxOK) },
+	{ "  ucast pkts tx",	offsetof(struct UPT1_TxStats, ucastPktsTxOK) },
+	{ "  ucast bytes tx",	offsetof(struct UPT1_TxStats, ucastBytesTxOK) },
+	{ "  mcast pkts tx",	offsetof(struct UPT1_TxStats, mcastPktsTxOK) },
+	{ "  mcast bytes tx",	offsetof(struct UPT1_TxStats, mcastBytesTxOK) },
+	{ "  bcast pkts tx",	offsetof(struct UPT1_TxStats, bcastPktsTxOK) },
+	{ "  bcast bytes tx",	offsetof(struct UPT1_TxStats, bcastBytesTxOK) },
+	{ "  pkts tx err",	offsetof(struct UPT1_TxStats, pktsTxError) },
+	{ "  pkts tx discard",	offsetof(struct UPT1_TxStats, pktsTxDiscard) },
 };
 
 /* per tq stats maintained by the driver */
 static const struct vmxnet3_stat_desc
 vmxnet3_tq_driver_stats[] = {
 	/* description,         offset */
-	{"drv dropped tx total", offsetof(struct vmxnet3_tq_driver_stats,
-					drop_total) },
-	{ "   too many frags",  offsetof(struct vmxnet3_tq_driver_stats,
-					drop_too_many_frags) },
-	{ "   giant hdr",       offsetof(struct vmxnet3_tq_driver_stats,
-					drop_oversized_hdr) },
-	{ "   hdr err",         offsetof(struct vmxnet3_tq_driver_stats,
-					drop_hdr_inspect_err) },
-	{ "   tso",             offsetof(struct vmxnet3_tq_driver_stats,
-					drop_tso) },
-	{ "ring full",          offsetof(struct vmxnet3_tq_driver_stats,
-					tx_ring_full) },
-	{ "pkts linearized",    offsetof(struct vmxnet3_tq_driver_stats,
-					linearized) },
-	{ "hdr cloned",         offsetof(struct vmxnet3_tq_driver_stats,
-					copy_skb_header) },
-	{ "giant hdr",          offsetof(struct vmxnet3_tq_driver_stats,
-					oversized_hdr) },
+	{"  drv dropped tx total",	offsetof(struct vmxnet3_tq_driver_stats,
+						 drop_total) },
+	{ "     too many frags", offsetof(struct vmxnet3_tq_driver_stats,
+					  drop_too_many_frags) },
+	{ "     giant hdr",	offsetof(struct vmxnet3_tq_driver_stats,
+					 drop_oversized_hdr) },
+	{ "     hdr err",	offsetof(struct vmxnet3_tq_driver_stats,
+					 drop_hdr_inspect_err) },
+	{ "     tso",		offsetof(struct vmxnet3_tq_driver_stats,
+					 drop_tso) },
+	{ "  ring full",	offsetof(struct vmxnet3_tq_driver_stats,
+					 tx_ring_full) },
+	{ "  pkts linearized",	offsetof(struct vmxnet3_tq_driver_stats,
+					 linearized) },
+	{ "  hdr cloned",	offsetof(struct vmxnet3_tq_driver_stats,
+					 copy_skb_header) },
+	{ "  giant hdr",	offsetof(struct vmxnet3_tq_driver_stats,
+					 oversized_hdr) },
 };
 
 /* per rq stats maintained by the device */
 static const struct vmxnet3_stat_desc
 vmxnet3_rq_dev_stats[] = {
-	{ "LRO pkts rx",        offsetof(struct UPT1_RxStats, LROPktsRxOK) },
-	{ "LRO byte rx",        offsetof(struct UPT1_RxStats, LROBytesRxOK) },
-	{ "ucast pkts rx",      offsetof(struct UPT1_RxStats, ucastPktsRxOK) },
-	{ "ucast bytes rx",     offsetof(struct UPT1_RxStats, ucastBytesRxOK) },
-	{ "mcast pkts rx",      offsetof(struct UPT1_RxStats, mcastPktsRxOK) },
-	{ "mcast bytes rx",     offsetof(struct UPT1_RxStats, mcastBytesRxOK) },
-	{ "bcast pkts rx",      offsetof(struct UPT1_RxStats, bcastPktsRxOK) },
-	{ "bcast bytes rx",     offsetof(struct UPT1_RxStats, bcastBytesRxOK) },
-	{ "pkts rx out of buf", offsetof(struct UPT1_RxStats, pktsRxOutOfBuf) },
-	{ "pkts rx err",        offsetof(struct UPT1_RxStats, pktsRxError) },
+	{ "Rx Queue#",        0 },
+	{ "  LRO pkts rx",	offsetof(struct UPT1_RxStats, LROPktsRxOK) },
+	{ "  LRO byte rx",	offsetof(struct UPT1_RxStats, LROBytesRxOK) },
+	{ "  ucast pkts rx",	offsetof(struct UPT1_RxStats, ucastPktsRxOK) },
+	{ "  ucast bytes rx",	offsetof(struct UPT1_RxStats, ucastBytesRxOK) },
+	{ "  mcast pkts rx",	offsetof(struct UPT1_RxStats, mcastPktsRxOK) },
+	{ "  mcast bytes rx",	offsetof(struct UPT1_RxStats, mcastBytesRxOK) },
+	{ "  bcast pkts rx",	offsetof(struct UPT1_RxStats, bcastPktsRxOK) },
+	{ "  bcast bytes rx",	offsetof(struct UPT1_RxStats, bcastBytesRxOK) },
+	{ "  pkts rx OOB",	offsetof(struct UPT1_RxStats, pktsRxOutOfBuf) },
+	{ "  pkts rx err",	offsetof(struct UPT1_RxStats, pktsRxError) },
 };
 
 /* per rq stats maintained by the driver */
 static const struct vmxnet3_stat_desc
 vmxnet3_rq_driver_stats[] = {
 	/* description,         offset */
-	{ "drv dropped rx total", offsetof(struct vmxnet3_rq_driver_stats,
-					   drop_total) },
-	{ "   err",            offsetof(struct vmxnet3_rq_driver_stats,
-					drop_err) },
-	{ "   fcs",            offsetof(struct vmxnet3_rq_driver_stats,
-					drop_fcs) },
-	{ "rx buf alloc fail", offsetof(struct vmxnet3_rq_driver_stats,
-					rx_buf_alloc_failure) },
+	{ "  drv dropped rx total", offsetof(struct vmxnet3_rq_driver_stats,
+					     drop_total) },
+	{ "     err",		offsetof(struct vmxnet3_rq_driver_stats,
+					 drop_err) },
+	{ "     fcs",		offsetof(struct vmxnet3_rq_driver_stats,
+					 drop_fcs) },
+	{ "  rx buf alloc fail", offsetof(struct vmxnet3_rq_driver_stats,
+					  rx_buf_alloc_failure) },
 };
 
 /* gloabl stats maintained by the driver */
 static const struct vmxnet3_stat_desc
 vmxnet3_global_stats[] = {
 	/* description,         offset */
-	{ "tx timeout count",   offsetof(struct vmxnet3_adapter,
+	{ "tx timeout count",	offsetof(struct vmxnet3_adapter,
 					 tx_timeout_count) }
 };
 
@@ -151,56 +156,60 @@ vmxnet3_get_stats(struct net_device *net
 	struct UPT1_TxStats *devTxStats;
 	struct UPT1_RxStats *devRxStats;
 	struct net_device_stats *net_stats = &netdev->stats;
+	unsigned long flags;
+	int i;
 
 	adapter = netdev_priv(netdev);
 
 	/* Collect the dev stats into the shared area */
+	spin_lock_irqsave(&adapter->cmd_lock, flags);
 	VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD, VMXNET3_CMD_GET_STATS);
-
-	/* Assuming that we have a single queue device */
-	devTxStats = &adapter->tqd_start->stats;
-	devRxStats = &adapter->rqd_start->stats;
-
-	/* Get access to the driver stats per queue */
-	drvTxStats = &adapter->tx_queue.stats;
-	drvRxStats = &adapter->rx_queue.stats;
+	spin_unlock_irqrestore(&adapter->cmd_lock, flags);
 
 	memset(net_stats, 0, sizeof(*net_stats));
+	for (i = 0; i < adapter->num_tx_queues; i++) {
+		devTxStats = &adapter->tqd_start[i].stats;
+		drvTxStats = &adapter->tx_queue[i].stats;
+		net_stats->tx_packets += devTxStats->ucastPktsTxOK +
+					devTxStats->mcastPktsTxOK +
+					devTxStats->bcastPktsTxOK;
+		net_stats->tx_bytes += devTxStats->ucastBytesTxOK +
+				      devTxStats->mcastBytesTxOK +
+				      devTxStats->bcastBytesTxOK;
+		net_stats->tx_errors += devTxStats->pktsTxError;
+		net_stats->tx_dropped += drvTxStats->drop_total;
+	}
 
-	net_stats->rx_packets = devRxStats->ucastPktsRxOK +
-				devRxStats->mcastPktsRxOK +
-				devRxStats->bcastPktsRxOK;
-
-	net_stats->tx_packets = devTxStats->ucastPktsTxOK +
-				devTxStats->mcastPktsTxOK +
-				devTxStats->bcastPktsTxOK;
-
-	net_stats->rx_bytes = devRxStats->ucastBytesRxOK +
-			      devRxStats->mcastBytesRxOK +
-			      devRxStats->bcastBytesRxOK;
-
-	net_stats->tx_bytes = devTxStats->ucastBytesTxOK +
-			      devTxStats->mcastBytesTxOK +
-			      devTxStats->bcastBytesTxOK;
+	for (i = 0; i < adapter->num_rx_queues; i++) {
+		devRxStats = &adapter->rqd_start[i].stats;
+		drvRxStats = &adapter->rx_queue[i].stats;
+		net_stats->rx_packets += devRxStats->ucastPktsRxOK +
+					devRxStats->mcastPktsRxOK +
+					devRxStats->bcastPktsRxOK;
 
-	net_stats->rx_errors = devRxStats->pktsRxError;
-	net_stats->tx_errors = devTxStats->pktsTxError;
-	net_stats->rx_dropped = drvRxStats->drop_total;
-	net_stats->tx_dropped = drvTxStats->drop_total;
-	net_stats->multicast =  devRxStats->mcastPktsRxOK;
+		net_stats->rx_bytes += devRxStats->ucastBytesRxOK +
+				      devRxStats->mcastBytesRxOK +
+				      devRxStats->bcastBytesRxOK;
 
+		net_stats->rx_errors += devRxStats->pktsRxError;
+		net_stats->rx_dropped += drvRxStats->drop_total;
+		net_stats->multicast +=  devRxStats->mcastPktsRxOK;
+	}
 	return net_stats;
 }
 
 static int
 vmxnet3_get_sset_count(struct net_device *netdev, int sset)
 {
+	struct vmxnet3_adapter *adapter = netdev_priv(netdev);
 	switch (sset) {
 	case ETH_SS_STATS:
-		return ARRAY_SIZE(vmxnet3_tq_dev_stats) +
-			ARRAY_SIZE(vmxnet3_tq_driver_stats) +
-			ARRAY_SIZE(vmxnet3_rq_dev_stats) +
-			ARRAY_SIZE(vmxnet3_rq_driver_stats) +
+		return (ARRAY_SIZE(vmxnet3_tq_dev_stats) +
+			ARRAY_SIZE(vmxnet3_tq_driver_stats)) *
+		       adapter->num_tx_queues +
+		       (ARRAY_SIZE(vmxnet3_rq_dev_stats) +
+			ARRAY_SIZE(vmxnet3_rq_driver_stats)) *
+		       adapter->num_rx_queues +
 			ARRAY_SIZE(vmxnet3_global_stats);
 	default:
 		return -EOPNOTSUPP;
@@ -208,10 +217,16 @@ vmxnet3_get_sset_count(struct net_device
 }
 
 
+/* Should be multiple of 4 */
+#define NUM_TX_REGS	8
+#define NUM_RX_REGS	12
+
 static int
 vmxnet3_get_regs_len(struct net_device *netdev)
 {
-	return 20 * sizeof(u32);
+	struct vmxnet3_adapter *adapter = netdev_priv(netdev);
+	return (adapter->num_tx_queues * NUM_TX_REGS * sizeof(u32) +
+		adapter->num_rx_queues * NUM_RX_REGS * sizeof(u32));
 }
 
 
@@ -242,29 +257,37 @@ vmxnet3_get_drvinfo(struct net_device *n
 static void
 vmxnet3_get_strings(struct net_device *netdev, u32 stringset, u8 *buf)
 {
+	 struct vmxnet3_adapter *adapter = netdev_priv(netdev);
 	if (stringset == ETH_SS_STATS) {
-		int i;
-
-		for (i = 0; i < ARRAY_SIZE(vmxnet3_tq_dev_stats); i++) {
-			memcpy(buf, vmxnet3_tq_dev_stats[i].desc,
-			       ETH_GSTRING_LEN);
-			buf += ETH_GSTRING_LEN;
-		}
-		for (i = 0; i < ARRAY_SIZE(vmxnet3_tq_driver_stats); i++) {
-			memcpy(buf, vmxnet3_tq_driver_stats[i].desc,
-			       ETH_GSTRING_LEN);
-			buf += ETH_GSTRING_LEN;
-		}
-		for (i = 0; i < ARRAY_SIZE(vmxnet3_rq_dev_stats); i++) {
-			memcpy(buf, vmxnet3_rq_dev_stats[i].desc,
-			       ETH_GSTRING_LEN);
-			buf += ETH_GSTRING_LEN;
+		int i, j;
+		for (j = 0; j < adapter->num_tx_queues; j++) {
+			for (i = 0; i < ARRAY_SIZE(vmxnet3_tq_dev_stats); i++) {
+				memcpy(buf, vmxnet3_tq_dev_stats[i].desc,
+				       ETH_GSTRING_LEN);
+				buf += ETH_GSTRING_LEN;
+			}
+			for (i = 0; i < ARRAY_SIZE(vmxnet3_tq_driver_stats);
+			     i++) {
+				memcpy(buf, vmxnet3_tq_driver_stats[i].desc,
+				       ETH_GSTRING_LEN);
+				buf += ETH_GSTRING_LEN;
+			}
 		}
-		for (i = 0; i < ARRAY_SIZE(vmxnet3_rq_driver_stats); i++) {
-			memcpy(buf, vmxnet3_rq_driver_stats[i].desc,
-			       ETH_GSTRING_LEN);
-			buf += ETH_GSTRING_LEN;
+
+		for (j = 0; j < adapter->num_rx_queues; j++) {
+			for (i = 0; i < ARRAY_SIZE(vmxnet3_rq_dev_stats); i++) {
+				memcpy(buf, vmxnet3_rq_dev_stats[i].desc,
+				       ETH_GSTRING_LEN);
+				buf += ETH_GSTRING_LEN;
+			}
+			for (i = 0; i < ARRAY_SIZE(vmxnet3_rq_driver_stats);
+			     i++) {
+				memcpy(buf, vmxnet3_rq_driver_stats[i].desc,
+				       ETH_GSTRING_LEN);
+				buf += ETH_GSTRING_LEN;
+			}
 		}
+
 		for (i = 0; i < ARRAY_SIZE(vmxnet3_global_stats); i++) {
 			memcpy(buf, vmxnet3_global_stats[i].desc,
 				ETH_GSTRING_LEN);
@@ -279,6 +302,7 @@ vmxnet3_set_flags(struct net_device *net
 	struct vmxnet3_adapter *adapter = netdev_priv(netdev);
 	u8 lro_requested = (data & ETH_FLAG_LRO) == 0 ? 0 : 1;
 	u8 lro_present = (netdev->features & NETIF_F_LRO) == 0 ? 0 : 1;
+	unsigned long flags;
 
 	if (data & ~ETH_FLAG_LRO)
 		return -EOPNOTSUPP;
@@ -294,8 +318,10 @@ vmxnet3_set_flags(struct net_device *net
 		else
 			adapter->shared->devRead.misc.uptFeatures &=
 							~UPT1_F_LRO;
+		spin_lock_irqsave(&adapter->cmd_lock, flags);
 		VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
 				       VMXNET3_CMD_UPDATE_FEATURE);
+		spin_unlock_irqrestore(&adapter->cmd_lock, flags);
 	}
 	return 0;
 }
@@ -305,28 +331,41 @@ vmxnet3_get_ethtool_stats(struct net_dev
 			  struct ethtool_stats *stats, u64  *buf)
 {
 	struct vmxnet3_adapter *adapter = netdev_priv(netdev);
+	unsigned long flags;
 	u8 *base;
 	int i;
+	int j = 0;
 
+	spin_lock_irqsave(&adapter->cmd_lock, flags);
 	VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD, VMXNET3_CMD_GET_STATS);
+	spin_unlock_irqrestore(&adapter->cmd_lock, flags);
 
 	/* this does assume each counter is 64-bit wide */
+	for (j = 0; j < adapter->num_tx_queues; j++) {
+		base = (u8 *)&adapter->tqd_start[j].stats;
+		*buf++ = (u64)j;
+		for (i = 1; i < ARRAY_SIZE(vmxnet3_tq_dev_stats); i++)
+			*buf++ = *(u64 *)(base +
+					  vmxnet3_tq_dev_stats[i].offset);
 
-	base = (u8 *)&adapter->tqd_start->stats;
-	for (i = 0; i < ARRAY_SIZE(vmxnet3_tq_dev_stats); i++)
-		*buf++ = *(u64 *)(base + vmxnet3_tq_dev_stats[i].offset);
-
-	base = (u8 *)&adapter->tx_queue.stats;
-	for (i = 0; i < ARRAY_SIZE(vmxnet3_tq_driver_stats); i++)
-		*buf++ = *(u64 *)(base + vmxnet3_tq_driver_stats[i].offset);
+		base = (u8 *)&adapter->tx_queue[j].stats;
+		for (i = 0; i < ARRAY_SIZE(vmxnet3_tq_driver_stats); i++)
+			*buf++ = *(u64 *)(base +
+					  vmxnet3_tq_driver_stats[i].offset);
+	}
 
-	base = (u8 *)&adapter->rqd_start->stats;
-	for (i = 0; i < ARRAY_SIZE(vmxnet3_rq_dev_stats); i++)
-		*buf++ = *(u64 *)(base + vmxnet3_rq_dev_stats[i].offset);
+	for (j = 0; j < adapter->num_tx_queues; j++) {
+		base = (u8 *)&adapter->rqd_start[j].stats;
+		*buf++ = (u64) j;
+		for (i = 1; i < ARRAY_SIZE(vmxnet3_rq_dev_stats); i++)
+			*buf++ = *(u64 *)(base +
+					  vmxnet3_rq_dev_stats[i].offset);
 
-	base = (u8 *)&adapter->rx_queue.stats;
-	for (i = 0; i < ARRAY_SIZE(vmxnet3_rq_driver_stats); i++)
-		*buf++ = *(u64 *)(base + vmxnet3_rq_driver_stats[i].offset);
+		base = (u8 *)&adapter->rx_queue[j].stats;
+		for (i = 0; i < ARRAY_SIZE(vmxnet3_rq_driver_stats); i++)
+			*buf++ = *(u64 *)(base +
+					  vmxnet3_rq_driver_stats[i].offset);
+	}
 
 	base = (u8 *)adapter;
 	for (i = 0; i < ARRAY_SIZE(vmxnet3_global_stats); i++)
@@ -339,6 +378,7 @@ vmxnet3_get_regs(struct net_device *netd
 {
 	struct vmxnet3_adapter *adapter = netdev_priv(netdev);
 	u32 *buf = p;
+	int i = 0, j = 0;
 
 	memset(p, 0, vmxnet3_get_regs_len(netdev));
 
@@ -347,30 +387,35 @@ vmxnet3_get_regs(struct net_device *netd
 	/* Update vmxnet3_get_regs_len if we want to dump more registers */
 
 	/* make each ring use multiple of 16 bytes */
-	buf[0] = adapter->tx_queue.tx_ring.next2fill;
-	buf[1] = adapter->tx_queue.tx_ring.next2comp;
-	buf[2] = adapter->tx_queue.tx_ring.gen;
-	buf[3] = 0;
+	for (i = 0; i < adapter->num_tx_queues; i++) {
+		buf[j++] = adapter->tx_queue[i].tx_ring.next2fill;
+		buf[j++] = adapter->tx_queue[i].tx_ring.next2comp;
+		buf[j++] = adapter->tx_queue[i].tx_ring.gen;
+		buf[j++] = 0;
 
-	buf[4] = adapter->tx_queue.comp_ring.next2proc;
-	buf[5] = adapter->tx_queue.comp_ring.gen;
-	buf[6] = adapter->tx_queue.stopped;
-	buf[7] = 0;
+		buf[j++] = adapter->tx_queue[i].comp_ring.next2proc;
+		buf[j++] = adapter->tx_queue[i].comp_ring.gen;
+		buf[j++] = adapter->tx_queue[i].stopped;
+		buf[j++] = 0;
+	}
 
-	buf[8] = adapter->rx_queue.rx_ring[0].next2fill;
-	buf[9] = adapter->rx_queue.rx_ring[0].next2comp;
-	buf[10] = adapter->rx_queue.rx_ring[0].gen;
-	buf[11] = 0;
+	for (i = 0; i < adapter->num_rx_queues; i++) {
+		buf[j++] = adapter->rx_queue[i].rx_ring[0].next2fill;
+		buf[j++] = adapter->rx_queue[i].rx_ring[0].next2comp;
+		buf[j++] = adapter->rx_queue[i].rx_ring[0].gen;
+		buf[j++] = 0;
 
-	buf[12] = adapter->rx_queue.rx_ring[1].next2fill;
-	buf[13] = adapter->rx_queue.rx_ring[1].next2comp;
-	buf[14] = adapter->rx_queue.rx_ring[1].gen;
-	buf[15] = 0;
+		buf[j++] = adapter->rx_queue[i].rx_ring[1].next2fill;
+		buf[j++] = adapter->rx_queue[i].rx_ring[1].next2comp;
+		buf[j++] = adapter->rx_queue[i].rx_ring[1].gen;
+		buf[j++] = 0;
+
+		buf[j++] = adapter->rx_queue[i].comp_ring.next2proc;
+		buf[j++] = adapter->rx_queue[i].comp_ring.gen;
+		buf[j++] = 0;
+		buf[j++] = 0;
+	}
 
-	buf[16] = adapter->rx_queue.comp_ring.next2proc;
-	buf[17] = adapter->rx_queue.comp_ring.gen;
-	buf[18] = 0;
-	buf[19] = 0;
 }
 
 
@@ -435,8 +480,10 @@ vmxnet3_get_ringparam(struct net_device
 	param->rx_mini_max_pending = 0;
 	param->rx_jumbo_max_pending = 0;
 
-	param->rx_pending = adapter->rx_queue.rx_ring[0].size;
-	param->tx_pending = adapter->tx_queue.tx_ring.size;
+	param->rx_pending = adapter->rx_queue[0].rx_ring[0].size *
+			    adapter->num_rx_queues;
+	param->tx_pending = adapter->tx_queue[0].tx_ring.size *
+			    adapter->num_tx_queues;
 	param->rx_mini_pending = 0;
 	param->rx_jumbo_pending = 0;
 }
@@ -480,8 +527,8 @@ vmxnet3_set_ringparam(struct net_device
 							   sz) != 0)
 		return -EINVAL;
 
-	if (new_tx_ring_size == adapter->tx_queue.tx_ring.size &&
-			new_rx_ring_size == adapter->rx_queue.rx_ring[0].size) {
+	if (new_tx_ring_size == adapter->tx_queue[0].tx_ring.size &&
+	    new_rx_ring_size == adapter->rx_queue[0].rx_ring[0].size) {
 		return 0;
 	}
 
@@ -498,11 +545,12 @@ vmxnet3_set_ringparam(struct net_device
 
 		/* recreate the rx queue and the tx queue based on the
 		 * new sizes */
-		vmxnet3_tq_destroy(&adapter->tx_queue, adapter);
-		vmxnet3_rq_destroy(&adapter->rx_queue, adapter);
+		vmxnet3_tq_destroy_all(adapter);
+		vmxnet3_rq_destroy_all(adapter);
 
 		err = vmxnet3_create_queues(adapter, new_tx_ring_size,
 			new_rx_ring_size, VMXNET3_DEF_RX_RING_SIZE);
+
 		if (err) {
 			/* failed, most likely because of OOM, try default
 			 * size */
@@ -535,6 +583,69 @@ out:
 }
 
 
+static int
+vmxnet3_get_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *info,
+		  void *rules)
+{
+	struct vmxnet3_adapter *adapter = netdev_priv(netdev);
+	switch (info->cmd) {
+	case ETHTOOL_GRXRINGS:
+		info->data = adapter->num_rx_queues;
+		return 0;
+	}
+	return -EOPNOTSUPP;
+}
+
+#ifdef VMXNET3_RSS
+static int
+vmxnet3_get_rss_indir(struct net_device *netdev,
+		      struct ethtool_rxfh_indir *p)
+{
+	struct vmxnet3_adapter *adapter = netdev_priv(netdev);
+	struct UPT1_RSSConf *rssConf = adapter->rss_conf;
+	unsigned int n = min_t(unsigned int, p->size, rssConf->indTableSize);
+
+	p->size = rssConf->indTableSize;
+	while (n--)
+		p->ring_index[n] = rssConf->indTable[n];
+	return 0;
+
+}
+
+static int
+vmxnet3_set_rss_indir(struct net_device *netdev,
+		      const struct ethtool_rxfh_indir *p)
+{
+	unsigned int i;
+	unsigned long flags;
+	struct vmxnet3_adapter *adapter = netdev_priv(netdev);
+	struct UPT1_RSSConf *rssConf = adapter->rss_conf;
+
+	if (p->size != rssConf->indTableSize)
+		return -EINVAL;
+	for (i = 0; i < rssConf->indTableSize; i++) {
+		/*
+		 * Return with error code if any of the queue indices
+		 * is out of range
+		 */
+		if (p->ring_index[i] < 0 ||
+		    p->ring_index[i] >= adapter->num_rx_queues)
+			return -EINVAL;
+	}
+
+	for (i = 0; i < rssConf->indTableSize; i++)
+		rssConf->indTable[i] = p->ring_index[i];
+
+	spin_lock_irqsave(&adapter->cmd_lock, flags);
+	VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
+			       VMXNET3_CMD_UPDATE_RSSIDT);
+	spin_unlock_irqrestore(&adapter->cmd_lock, flags);
+
+	return 0;
+
+}
+#endif
+
 static struct ethtool_ops vmxnet3_ethtool_ops = {
 	.get_settings      = vmxnet3_get_settings,
 	.get_drvinfo       = vmxnet3_get_drvinfo,
@@ -558,6 +669,11 @@ static struct ethtool_ops vmxnet3_ethtoo
 	.get_ethtool_stats = vmxnet3_get_ethtool_stats,
 	.get_ringparam     = vmxnet3_get_ringparam,
 	.set_ringparam     = vmxnet3_set_ringparam,
+	.get_rxnfc         = vmxnet3_get_rxnfc,
+#ifdef VMXNET3_RSS
+	.get_rxfh_indir    = vmxnet3_get_rss_indir,
+	.set_rxfh_indir    = vmxnet3_set_rss_indir,
+#endif
 };
 
 void vmxnet3_set_ethtool_ops(struct net_device *netdev)
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/vmxnet3/vmxnet3_int.h linux-libre-2.6.38-gnu1/drivers/net/vmxnet3/vmxnet3_int.h
--- linux-libre-2.6.37-gnu1/drivers/net/vmxnet3/vmxnet3_int.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/vmxnet3/vmxnet3_int.h	2011-03-14 21:20:32.000000000 -0400
@@ -68,11 +68,15 @@
 /*
  * Version numbers
  */
-#define VMXNET3_DRIVER_VERSION_STRING   "1.0.14.0-k"
+#define VMXNET3_DRIVER_VERSION_STRING   "1.0.25.0-k"
 
 /* a 32-bit int, each byte encode a verion number in VMXNET3_DRIVER_VERSION */
-#define VMXNET3_DRIVER_VERSION_NUM      0x01000E00
+#define VMXNET3_DRIVER_VERSION_NUM      0x01001900
 
+#if defined(CONFIG_PCI_MSI)
+	/* RSS only makes sense if MSI-X is supported. */
+	#define VMXNET3_RSS
+#endif
 
 /*
  * Capabilities
@@ -218,16 +222,19 @@ struct vmxnet3_tx_ctx {
 };
 
 struct vmxnet3_tx_queue {
+	char			name[IFNAMSIZ+8]; /* To identify interrupt */
+	struct vmxnet3_adapter		*adapter;
 	spinlock_t                      tx_lock;
 	struct vmxnet3_cmd_ring         tx_ring;
-	struct vmxnet3_tx_buf_info     *buf_info;
+	struct vmxnet3_tx_buf_info      *buf_info;
 	struct vmxnet3_tx_data_ring     data_ring;
 	struct vmxnet3_comp_ring        comp_ring;
-	struct Vmxnet3_TxQueueCtrl            *shared;
+	struct Vmxnet3_TxQueueCtrl      *shared;
 	struct vmxnet3_tq_driver_stats  stats;
 	bool                            stopped;
 	int                             num_stop;  /* # of times the queue is
 						    * stopped */
+	int				qid;
 } __attribute__((__aligned__(SMP_CACHE_BYTES)));
 
 enum vmxnet3_rx_buf_type {
@@ -259,6 +266,9 @@ struct vmxnet3_rq_driver_stats {
 };
 
 struct vmxnet3_rx_queue {
+	char			name[IFNAMSIZ + 8]; /* To identify interrupt */
+	struct vmxnet3_adapter	  *adapter;
+	struct napi_struct        napi;
 	struct vmxnet3_cmd_ring   rx_ring[2];
 	struct vmxnet3_comp_ring  comp_ring;
 	struct vmxnet3_rx_ctx     rx_ctx;
@@ -271,7 +281,16 @@ struct vmxnet3_rx_queue {
 	struct vmxnet3_rq_driver_stats  stats;
 } __attribute__((__aligned__(SMP_CACHE_BYTES)));
 
-#define VMXNET3_LINUX_MAX_MSIX_VECT     1
+#define VMXNET3_DEVICE_MAX_TX_QUEUES 8
+#define VMXNET3_DEVICE_MAX_RX_QUEUES 8   /* Keep this value as a power of 2 */
+
+/* Should be less than UPT1_RSS_MAX_IND_TABLE_SIZE */
+#define VMXNET3_RSS_IND_TABLE_SIZE (VMXNET3_DEVICE_MAX_RX_QUEUES * 4)
+
+#define VMXNET3_LINUX_MAX_MSIX_VECT     (VMXNET3_DEVICE_MAX_TX_QUEUES + \
+					 VMXNET3_DEVICE_MAX_RX_QUEUES + 1)
+#define VMXNET3_LINUX_MIN_MSIX_VECT     2 /* 1 for tx-rx pair and 1 for event */
+
 
 struct vmxnet3_intr {
 	enum vmxnet3_intr_mask_mode  mask_mode;
@@ -279,27 +298,33 @@ struct vmxnet3_intr {
 	u8  num_intrs;			/* # of intr vectors */
 	u8  event_intr_idx;		/* idx of the intr vector for event */
 	u8  mod_levels[VMXNET3_LINUX_MAX_MSIX_VECT]; /* moderation level */
+	char	event_msi_vector_name[IFNAMSIZ+11];
 #ifdef CONFIG_PCI_MSI
 	struct msix_entry msix_entries[VMXNET3_LINUX_MAX_MSIX_VECT];
 #endif
 };
 
+/* Interrupt sharing schemes, share_intr */
+#define VMXNET3_INTR_BUDDYSHARE 0    /* Corresponding tx,rx queues share irq */
+#define VMXNET3_INTR_TXSHARE 1	     /* All tx queues share one irq */
+#define VMXNET3_INTR_DONTSHARE 2     /* each queue has its own irq */
+
+
 #define VMXNET3_STATE_BIT_RESETTING   0
 #define VMXNET3_STATE_BIT_QUIESCED    1
 struct vmxnet3_adapter {
-	struct vmxnet3_tx_queue         tx_queue;
-	struct vmxnet3_rx_queue         rx_queue;
-	struct napi_struct              napi;
-	struct vlan_group              *vlan_grp;
-
-	struct vmxnet3_intr             intr;
-
-	struct Vmxnet3_DriverShared    *shared;
-	struct Vmxnet3_PMConf          *pm_conf;
-	struct Vmxnet3_TxQueueDesc     *tqd_start;     /* first tx queue desc */
-	struct Vmxnet3_RxQueueDesc     *rqd_start;     /* first rx queue desc */
-	struct net_device              *netdev;
-	struct pci_dev                 *pdev;
+	struct vmxnet3_tx_queue		tx_queue[VMXNET3_DEVICE_MAX_TX_QUEUES];
+	struct vmxnet3_rx_queue		rx_queue[VMXNET3_DEVICE_MAX_RX_QUEUES];
+	struct vlan_group		*vlan_grp;
+	struct vmxnet3_intr		intr;
+	spinlock_t			cmd_lock;
+	struct Vmxnet3_DriverShared	*shared;
+	struct Vmxnet3_PMConf		*pm_conf;
+	struct Vmxnet3_TxQueueDesc	*tqd_start;     /* all tx queue desc */
+	struct Vmxnet3_RxQueueDesc	*rqd_start;	/* all rx queue desc */
+	struct net_device		*netdev;
+	struct net_device_stats		net_stats;
+	struct pci_dev			*pdev;
 
 	u8			__iomem *hw_addr0; /* for BAR 0 */
 	u8			__iomem *hw_addr1; /* for BAR 1 */
@@ -308,6 +333,12 @@ struct vmxnet3_adapter {
 	bool				rxcsum;
 	bool				lro;
 	bool				jumbo_frame;
+#ifdef VMXNET3_RSS
+	struct UPT1_RSSConf		*rss_conf;
+	bool				rss;
+#endif
+	u32				num_rx_queues;
+	u32				num_tx_queues;
 
 	/* rx buffer related */
 	unsigned			skb_buf_size;
@@ -327,6 +358,7 @@ struct vmxnet3_adapter {
 	unsigned long  state;    /* VMXNET3_STATE_BIT_xxx */
 
 	int dev_number;
+	int share_intr;
 };
 
 #define VMXNET3_WRITE_BAR0_REG(adapter, reg, val)  \
@@ -366,12 +398,10 @@ void
 vmxnet3_reset_dev(struct vmxnet3_adapter *adapter);
 
 void
-vmxnet3_tq_destroy(struct vmxnet3_tx_queue *tq,
-		   struct vmxnet3_adapter *adapter);
+vmxnet3_tq_destroy_all(struct vmxnet3_adapter *adapter);
 
 void
-vmxnet3_rq_destroy(struct vmxnet3_rx_queue *rq,
-		   struct vmxnet3_adapter *adapter);
+vmxnet3_rq_destroy_all(struct vmxnet3_adapter *adapter);
 
 int
 vmxnet3_create_queues(struct vmxnet3_adapter *adapter,
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/vxge/vxge-config.c linux-libre-2.6.38-gnu1/drivers/net/vxge/vxge-config.c
--- linux-libre-2.6.37-gnu1/drivers/net/vxge/vxge-config.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/vxge/vxge-config.c	2011-03-14 21:20:32.000000000 -0400
@@ -19,109 +19,128 @@
 
 #include "vxge-traffic.h"
 #include "vxge-config.h"
+#include "vxge-main.h"
 
-static enum vxge_hw_status
-__vxge_hw_fifo_create(
-	struct __vxge_hw_vpath_handle *vpath_handle,
-	struct vxge_hw_fifo_attr *attr);
-
-static enum vxge_hw_status
-__vxge_hw_fifo_abort(
-	struct __vxge_hw_fifo *fifoh);
-
-static enum vxge_hw_status
-__vxge_hw_fifo_reset(
-	struct __vxge_hw_fifo *ringh);
-
-static enum vxge_hw_status
-__vxge_hw_fifo_delete(
-	struct __vxge_hw_vpath_handle *vpath_handle);
-
-static struct __vxge_hw_blockpool_entry *
-__vxge_hw_blockpool_block_allocate(struct __vxge_hw_device *hldev,
-			u32 size);
+#define VXGE_HW_VPATH_STATS_PIO_READ(offset) {				\
+	status = __vxge_hw_vpath_stats_access(vpath,			\
+					      VXGE_HW_STATS_OP_READ,	\
+					      offset,			\
+					      &val64);			\
+	if (status != VXGE_HW_OK)					\
+		return status;						\
+}
 
 static void
-__vxge_hw_blockpool_block_free(struct __vxge_hw_device *hldev,
-			struct __vxge_hw_blockpool_entry *entry);
-
-static void vxge_hw_blockpool_block_add(struct __vxge_hw_device *devh,
-					void *block_addr,
-					u32 length,
-					struct pci_dev *dma_h,
-					struct pci_dev *acc_handle);
-
-static enum vxge_hw_status
-__vxge_hw_blockpool_create(struct __vxge_hw_device *hldev,
-			struct __vxge_hw_blockpool  *blockpool,
-			u32 pool_size,
-			u32 pool_max);
+vxge_hw_vpath_set_zero_rx_frm_len(struct vxge_hw_vpath_reg __iomem *vp_reg)
+{
+	u64 val64;
 
-static void
-__vxge_hw_blockpool_destroy(struct __vxge_hw_blockpool  *blockpool);
+	val64 = readq(&vp_reg->rxmac_vcfg0);
+	val64 &= ~VXGE_HW_RXMAC_VCFG0_RTS_MAX_FRM_LEN(0x3fff);
+	writeq(val64, &vp_reg->rxmac_vcfg0);
+	val64 = readq(&vp_reg->rxmac_vcfg0);
+}
 
-static void *
-__vxge_hw_blockpool_malloc(struct __vxge_hw_device *hldev,
-			u32 size,
-			struct vxge_hw_mempool_dma *dma_object);
+/*
+ * vxge_hw_vpath_wait_receive_idle - Wait for Rx to become idle
+ */
+int vxge_hw_vpath_wait_receive_idle(struct __vxge_hw_device *hldev, u32 vp_id)
+{
+	struct vxge_hw_vpath_reg __iomem *vp_reg;
+	struct __vxge_hw_virtualpath *vpath;
+	u64 val64, rxd_count, rxd_spat;
+	int count = 0, total_count = 0;
 
-static void
-__vxge_hw_blockpool_free(struct __vxge_hw_device *hldev,
-			void *memblock,
-			u32 size,
-			struct vxge_hw_mempool_dma *dma_object);
+	vpath = &hldev->virtual_paths[vp_id];
+	vp_reg = vpath->vp_reg;
 
+	vxge_hw_vpath_set_zero_rx_frm_len(vp_reg);
 
-static struct __vxge_hw_channel*
-__vxge_hw_channel_allocate(struct __vxge_hw_vpath_handle *vph,
-			enum __vxge_hw_channel_type type, u32 length,
-			u32 per_dtr_space, void *userdata);
+	/* Check that the ring controller for this vpath has enough free RxDs
+	 * to send frames to the host.  This is done by reading the
+	 * PRC_RXD_DOORBELL_VPn register and comparing the read value to the
+	 * RXD_SPAT value for the vpath.
+	 */
+	val64 = readq(&vp_reg->prc_cfg6);
+	rxd_spat = VXGE_HW_PRC_CFG6_GET_RXD_SPAT(val64) + 1;
+	/* Use a factor of 2 when comparing rxd_count against rxd_spat for some
+	 * leg room.
+	 */
+	rxd_spat *= 2;
 
-static void
-__vxge_hw_channel_free(
-	struct __vxge_hw_channel *channel);
+	do {
+		mdelay(1);
 
-static enum vxge_hw_status
-__vxge_hw_channel_initialize(
-	struct __vxge_hw_channel *channel);
+		rxd_count = readq(&vp_reg->prc_rxd_doorbell);
 
-static enum vxge_hw_status
-__vxge_hw_channel_reset(
-	struct __vxge_hw_channel *channel);
+		/* Check that the ring controller for this vpath does
+		 * not have any frame in its pipeline.
+		 */
+		val64 = readq(&vp_reg->frm_in_progress_cnt);
+		if ((rxd_count <= rxd_spat) || (val64 > 0))
+			count = 0;
+		else
+			count++;
+		total_count++;
+	} while ((count < VXGE_HW_MIN_SUCCESSIVE_IDLE_COUNT) &&
+			(total_count < VXGE_HW_MAX_POLLING_COUNT));
 
-static enum vxge_hw_status __vxge_hw_ring_delete(struct __vxge_hw_vpath_handle *vp);
+	if (total_count >= VXGE_HW_MAX_POLLING_COUNT)
+		printk(KERN_ALERT "%s: Still Receiving traffic. Abort wait\n",
+			__func__);
 
-static enum vxge_hw_status
-__vxge_hw_device_fifo_config_check(struct vxge_hw_fifo_config *fifo_config);
+	return total_count;
+}
 
-static enum vxge_hw_status
-__vxge_hw_device_config_check(struct vxge_hw_device_config *new_config);
+/* vxge_hw_device_wait_receive_idle - This function waits until all frames
+ * stored in the frame buffer for each vpath assigned to the given
+ * function (hldev) have been sent to the host.
+ */
+void vxge_hw_device_wait_receive_idle(struct __vxge_hw_device *hldev)
+{
+	int i, total_count = 0;
 
-static void
-__vxge_hw_device_id_get(struct __vxge_hw_device *hldev);
+	for (i = 0; i < VXGE_HW_MAX_VIRTUAL_PATHS; i++) {
+		if (!(hldev->vpaths_deployed & vxge_mBIT(i)))
+			continue;
 
-static void
-__vxge_hw_device_host_info_get(struct __vxge_hw_device *hldev);
+		total_count += vxge_hw_vpath_wait_receive_idle(hldev, i);
+		if (total_count >= VXGE_HW_MAX_POLLING_COUNT)
+			break;
+	}
+}
 
+/*
+ * __vxge_hw_device_register_poll
+ * Will poll certain register for specified amount of time.
+ * Will poll until masked bit is not cleared.
+ */
 static enum vxge_hw_status
-__vxge_hw_vpath_card_info_get(
-	u32 vp_id,
-	struct vxge_hw_vpath_reg __iomem *vpath_reg,
-	struct vxge_hw_device_hw_info *hw_info);
+__vxge_hw_device_register_poll(void __iomem *reg, u64 mask, u32 max_millis)
+{
+	u64 val64;
+	u32 i = 0;
+	enum vxge_hw_status ret = VXGE_HW_FAIL;
 
-static enum vxge_hw_status
-__vxge_hw_device_initialize(struct __vxge_hw_device *hldev);
+	udelay(10);
 
-static void
-__vxge_hw_device_pci_e_init(struct __vxge_hw_device *hldev);
+	do {
+		val64 = readq(reg);
+		if (!(val64 & mask))
+			return VXGE_HW_OK;
+		udelay(100);
+	} while (++i <= 9);
 
-static enum vxge_hw_status
-__vxge_hw_device_reg_addr_get(struct __vxge_hw_device *hldev);
+	i = 0;
+	do {
+		val64 = readq(reg);
+		if (!(val64 & mask))
+			return VXGE_HW_OK;
+		mdelay(1);
+	} while (++i <= max_millis);
 
-static enum vxge_hw_status
-__vxge_hw_device_register_poll(
-	void __iomem	*reg,
-	u64 mask, u32 max_millis);
+	return ret;
+}
 
 static inline enum vxge_hw_status
 __vxge_hw_pio_mem_write64(u64 val64, void __iomem *addr,
@@ -129,139 +148,258 @@ __vxge_hw_pio_mem_write64(u64 val64, voi
 {
 	__vxge_hw_pio_mem_write32_lower((u32)vxge_bVALn(val64, 32, 32), addr);
 	wmb();
-
 	__vxge_hw_pio_mem_write32_upper((u32)vxge_bVALn(val64, 0, 32), addr);
 	wmb();
 
-	return  __vxge_hw_device_register_poll(addr, mask, max_millis);
+	return __vxge_hw_device_register_poll(addr, mask, max_millis);
 }
 
-static struct vxge_hw_mempool*
-__vxge_hw_mempool_create(struct __vxge_hw_device *devh, u32 memblock_size,
-			 u32 item_size,	u32 private_size, u32 items_initial,
-			 u32 items_max,	struct vxge_hw_mempool_cbs *mp_callback,
-			 void *userdata);
-static void __vxge_hw_mempool_destroy(struct vxge_hw_mempool *mempool);
-
 static enum vxge_hw_status
-__vxge_hw_vpath_stats_get(struct __vxge_hw_virtualpath *vpath,
-			  struct vxge_hw_vpath_stats_hw_info *hw_stats);
+vxge_hw_vpath_fw_api(struct __vxge_hw_virtualpath *vpath, u32 action,
+		     u32 fw_memo, u32 offset, u64 *data0, u64 *data1,
+		     u64 *steer_ctrl)
+{
+	struct vxge_hw_vpath_reg __iomem *vp_reg;
+	enum vxge_hw_status status;
+	u64 val64;
+	u32 retry = 0, max_retry = 100;
 
-static enum vxge_hw_status
-vxge_hw_vpath_stats_enable(struct __vxge_hw_vpath_handle *vpath_handle);
+	vp_reg = vpath->vp_reg;
 
-static enum vxge_hw_status
-__vxge_hw_legacy_swapper_set(struct vxge_hw_legacy_reg __iomem *legacy_reg);
+	if (vpath->vp_open) {
+		max_retry = 3;
+		spin_lock(&vpath->lock);
+	}
 
-static u64
-__vxge_hw_vpath_pci_func_mode_get(u32  vp_id,
-				  struct vxge_hw_vpath_reg __iomem *vpath_reg);
+	writeq(*data0, &vp_reg->rts_access_steer_data0);
+	writeq(*data1, &vp_reg->rts_access_steer_data1);
+	wmb();
 
-static u32
-__vxge_hw_vpath_func_id_get(u32 vp_id, struct vxge_hw_vpmgmt_reg __iomem *vpmgmt_reg);
+	val64 = VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION(action) |
+		VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL(fw_memo) |
+		VXGE_HW_RTS_ACCESS_STEER_CTRL_OFFSET(offset) |
+		VXGE_HW_RTS_ACCESS_STEER_CTRL_STROBE |
+		*steer_ctrl;
 
-static enum vxge_hw_status
-__vxge_hw_vpath_addr_get(u32 vp_id, struct vxge_hw_vpath_reg __iomem *vpath_reg,
-			 u8 (macaddr)[ETH_ALEN], u8 (macaddr_mask)[ETH_ALEN]);
+	status = __vxge_hw_pio_mem_write64(val64,
+					   &vp_reg->rts_access_steer_ctrl,
+					   VXGE_HW_RTS_ACCESS_STEER_CTRL_STROBE,
+					   VXGE_HW_DEF_DEVICE_POLL_MILLIS);
 
-static enum vxge_hw_status
-__vxge_hw_vpath_reset_check(struct __vxge_hw_virtualpath *vpath);
+	/* The __vxge_hw_device_register_poll can udelay for a significant
+	 * amount of time, blocking other proccess from the CPU.  If it delays
+	 * for ~5secs, a NMI error can occur.  A way around this is to give up
+	 * the processor via msleep, but this is not allowed is under lock.
+	 * So, only allow it to sleep for ~4secs if open.  Otherwise, delay for
+	 * 1sec and sleep for 10ms until the firmware operation has completed
+	 * or timed-out.
+	 */
+	while ((status != VXGE_HW_OK) && retry++ < max_retry) {
+		if (!vpath->vp_open)
+			msleep(20);
+		status = __vxge_hw_device_register_poll(
+					&vp_reg->rts_access_steer_ctrl,
+					VXGE_HW_RTS_ACCESS_STEER_CTRL_STROBE,
+					VXGE_HW_DEF_DEVICE_POLL_MILLIS);
+	}
 
+	if (status != VXGE_HW_OK)
+		goto out;
 
-static enum vxge_hw_status
-__vxge_hw_vpath_sw_reset(struct __vxge_hw_device *devh, u32 vp_id);
+	val64 = readq(&vp_reg->rts_access_steer_ctrl);
+	if (val64 & VXGE_HW_RTS_ACCESS_STEER_CTRL_RMACJ_STATUS) {
+		*data0 = readq(&vp_reg->rts_access_steer_data0);
+		*data1 = readq(&vp_reg->rts_access_steer_data1);
+		*steer_ctrl = val64;
+	} else
+		status = VXGE_HW_FAIL;
 
-static enum vxge_hw_status
-__vxge_hw_vpath_fw_ver_get(u32 vp_id, struct vxge_hw_vpath_reg __iomem *vpath_reg,
-			   struct vxge_hw_device_hw_info *hw_info);
+out:
+	if (vpath->vp_open)
+		spin_unlock(&vpath->lock);
+	return status;
+}
 
-static enum vxge_hw_status
-__vxge_hw_vpath_mac_configure(struct __vxge_hw_device *devh, u32 vp_id);
+enum vxge_hw_status
+vxge_hw_upgrade_read_version(struct __vxge_hw_device *hldev, u32 *major,
+			     u32 *minor, u32 *build)
+{
+	u64 data0 = 0, data1 = 0, steer_ctrl = 0;
+	struct __vxge_hw_virtualpath *vpath;
+	enum vxge_hw_status status;
 
-static void
-__vxge_hw_vp_terminate(struct __vxge_hw_device *devh, u32 vp_id);
+	vpath = &hldev->virtual_paths[hldev->first_vp_id];
 
-static enum vxge_hw_status
-__vxge_hw_vpath_stats_access(struct __vxge_hw_virtualpath *vpath,
-			     u32 operation, u32 offset,	u64 *stat);
+	status = vxge_hw_vpath_fw_api(vpath,
+				      VXGE_HW_FW_UPGRADE_ACTION,
+				      VXGE_HW_FW_UPGRADE_MEMO,
+				      VXGE_HW_FW_UPGRADE_OFFSET_READ,
+				      &data0, &data1, &steer_ctrl);
+	if (status != VXGE_HW_OK)
+		return status;
 
-static enum vxge_hw_status
-__vxge_hw_vpath_xmac_tx_stats_get(struct __vxge_hw_virtualpath	*vpath,
-				  struct vxge_hw_xmac_vpath_tx_stats *vpath_tx_stats);
+	*major = VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_FW_VER_MAJOR(data0);
+	*minor = VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_FW_VER_MINOR(data0);
+	*build = VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_FW_VER_BUILD(data0);
 
-static enum vxge_hw_status
-__vxge_hw_vpath_xmac_rx_stats_get(struct __vxge_hw_virtualpath	*vpath,
-				  struct vxge_hw_xmac_vpath_rx_stats *vpath_rx_stats);
+	return status;
+}
 
-/*
- * __vxge_hw_channel_allocate - Allocate memory for channel
- * This function allocates required memory for the channel and various arrays
- * in the channel
- */
-struct __vxge_hw_channel*
-__vxge_hw_channel_allocate(struct __vxge_hw_vpath_handle *vph,
-			   enum __vxge_hw_channel_type type,
-	u32 length, u32 per_dtr_space, void *userdata)
+enum vxge_hw_status vxge_hw_flash_fw(struct __vxge_hw_device *hldev)
 {
-	struct __vxge_hw_channel *channel;
-	struct __vxge_hw_device *hldev;
-	int size = 0;
-	u32 vp_id;
+	u64 data0 = 0, data1 = 0, steer_ctrl = 0;
+	struct __vxge_hw_virtualpath *vpath;
+	enum vxge_hw_status status;
+	u32 ret;
 
-	hldev = vph->vpath->hldev;
-	vp_id = vph->vpath->vp_id;
+	vpath = &hldev->virtual_paths[hldev->first_vp_id];
 
-	switch (type) {
-	case VXGE_HW_CHANNEL_TYPE_FIFO:
-		size = sizeof(struct __vxge_hw_fifo);
-		break;
-	case VXGE_HW_CHANNEL_TYPE_RING:
-		size = sizeof(struct __vxge_hw_ring);
-		break;
-	default:
-		break;
+	status = vxge_hw_vpath_fw_api(vpath,
+				      VXGE_HW_FW_UPGRADE_ACTION,
+				      VXGE_HW_FW_UPGRADE_MEMO,
+				      VXGE_HW_FW_UPGRADE_OFFSET_COMMIT,
+				      &data0, &data1, &steer_ctrl);
+	if (status != VXGE_HW_OK) {
+		vxge_debug_init(VXGE_ERR, "%s: FW upgrade failed", __func__);
+		goto exit;
 	}
 
-	channel = kzalloc(size, GFP_KERNEL);
-	if (channel == NULL)
-		goto exit0;
-	INIT_LIST_HEAD(&channel->item);
+	ret = VXGE_HW_RTS_ACCESS_STEER_CTRL_GET_ACTION(steer_ctrl) & 0x7F;
+	if (ret != 1) {
+		vxge_debug_init(VXGE_ERR, "%s: FW commit failed with error %d",
+				__func__, ret);
+		status = VXGE_HW_FAIL;
+	}
 
-	channel->common_reg = hldev->common_reg;
-	channel->first_vp_id = hldev->first_vp_id;
-	channel->type = type;
-	channel->devh = hldev;
-	channel->vph = vph;
-	channel->userdata = userdata;
-	channel->per_dtr_space = per_dtr_space;
-	channel->length = length;
-	channel->vp_id = vp_id;
+exit:
+	return status;
+}
 
-	channel->work_arr = kzalloc(sizeof(void *)*length, GFP_KERNEL);
-	if (channel->work_arr == NULL)
-		goto exit1;
+enum vxge_hw_status
+vxge_update_fw_image(struct __vxge_hw_device *hldev, const u8 *fwdata, int size)
+{
+	u64 data0 = 0, data1 = 0, steer_ctrl = 0;
+	struct __vxge_hw_virtualpath *vpath;
+	enum vxge_hw_status status;
+	int ret_code, sec_code;
 
-	channel->free_arr = kzalloc(sizeof(void *)*length, GFP_KERNEL);
-	if (channel->free_arr == NULL)
-		goto exit1;
-	channel->free_ptr = length;
+	vpath = &hldev->virtual_paths[hldev->first_vp_id];
 
-	channel->reserve_arr = kzalloc(sizeof(void *)*length, GFP_KERNEL);
-	if (channel->reserve_arr == NULL)
-		goto exit1;
-	channel->reserve_ptr = length;
-	channel->reserve_top = 0;
+	/* send upgrade start command */
+	status = vxge_hw_vpath_fw_api(vpath,
+				      VXGE_HW_FW_UPGRADE_ACTION,
+				      VXGE_HW_FW_UPGRADE_MEMO,
+				      VXGE_HW_FW_UPGRADE_OFFSET_START,
+				      &data0, &data1, &steer_ctrl);
+	if (status != VXGE_HW_OK) {
+		vxge_debug_init(VXGE_ERR, " %s: Upgrade start cmd failed",
+				__func__);
+		return status;
+	}
 
-	channel->orig_arr = kzalloc(sizeof(void *)*length, GFP_KERNEL);
-	if (channel->orig_arr == NULL)
-		goto exit1;
+	/* Transfer fw image to adapter 16 bytes at a time */
+	for (; size > 0; size -= VXGE_HW_FW_UPGRADE_BLK_SIZE) {
+		steer_ctrl = 0;
 
-	return channel;
-exit1:
-	__vxge_hw_channel_free(channel);
+		/* The next 128bits of fwdata to be loaded onto the adapter */
+		data0 = *((u64 *)fwdata);
+		data1 = *((u64 *)fwdata + 1);
 
-exit0:
-	return NULL;
+		status = vxge_hw_vpath_fw_api(vpath,
+					      VXGE_HW_FW_UPGRADE_ACTION,
+					      VXGE_HW_FW_UPGRADE_MEMO,
+					      VXGE_HW_FW_UPGRADE_OFFSET_SEND,
+					      &data0, &data1, &steer_ctrl);
+		if (status != VXGE_HW_OK) {
+			vxge_debug_init(VXGE_ERR, "%s: Upgrade send failed",
+					__func__);
+			goto out;
+		}
+
+		ret_code = VXGE_HW_UPGRADE_GET_RET_ERR_CODE(data0);
+		switch (ret_code) {
+		case VXGE_HW_FW_UPGRADE_OK:
+			/* All OK, send next 16 bytes. */
+			break;
+		case VXGE_FW_UPGRADE_BYTES2SKIP:
+			/* skip bytes in the stream */
+			fwdata += (data0 >> 8) & 0xFFFFFFFF;
+			break;
+		case VXGE_HW_FW_UPGRADE_DONE:
+			goto out;
+		case VXGE_HW_FW_UPGRADE_ERR:
+			sec_code = VXGE_HW_UPGRADE_GET_SEC_ERR_CODE(data0);
+			switch (sec_code) {
+			case VXGE_HW_FW_UPGRADE_ERR_CORRUPT_DATA_1:
+			case VXGE_HW_FW_UPGRADE_ERR_CORRUPT_DATA_7:
+				printk(KERN_ERR
+				       "corrupted data from .ncf file\n");
+				break;
+			case VXGE_HW_FW_UPGRADE_ERR_INV_NCF_FILE_3:
+			case VXGE_HW_FW_UPGRADE_ERR_INV_NCF_FILE_4:
+			case VXGE_HW_FW_UPGRADE_ERR_INV_NCF_FILE_5:
+			case VXGE_HW_FW_UPGRADE_ERR_INV_NCF_FILE_6:
+			case VXGE_HW_FW_UPGRADE_ERR_INV_NCF_FILE_8:
+				printk(KERN_ERR "invalid .ncf file\n");
+				break;
+			case VXGE_HW_FW_UPGRADE_ERR_BUFFER_OVERFLOW:
+				printk(KERN_ERR "buffer overflow\n");
+				break;
+			case VXGE_HW_FW_UPGRADE_ERR_FAILED_TO_FLASH:
+				printk(KERN_ERR "failed to flash the image\n");
+				break;
+			case VXGE_HW_FW_UPGRADE_ERR_GENERIC_ERROR_UNKNOWN:
+				printk(KERN_ERR
+				       "generic error. Unknown error type\n");
+				break;
+			default:
+				printk(KERN_ERR "Unknown error of type %d\n",
+				       sec_code);
+				break;
+			}
+			status = VXGE_HW_FAIL;
+			goto out;
+		default:
+			printk(KERN_ERR "Unknown FW error: %d\n", ret_code);
+			status = VXGE_HW_FAIL;
+			goto out;
+		}
+		/* point to next 16 bytes */
+		fwdata += VXGE_HW_FW_UPGRADE_BLK_SIZE;
+	}
+out:
+	return status;
+}
+
+enum vxge_hw_status
+vxge_hw_vpath_eprom_img_ver_get(struct __vxge_hw_device *hldev,
+				struct eprom_image *img)
+{
+	u64 data0 = 0, data1 = 0, steer_ctrl = 0;
+	struct __vxge_hw_virtualpath *vpath;
+	enum vxge_hw_status status;
+	int i;
+
+	vpath = &hldev->virtual_paths[hldev->first_vp_id];
+
+	for (i = 0; i < VXGE_HW_MAX_ROM_IMAGES; i++) {
+		data0 = VXGE_HW_RTS_ACCESS_STEER_ROM_IMAGE_INDEX(i);
+		data1 = steer_ctrl = 0;
+
+		status = vxge_hw_vpath_fw_api(vpath,
+			VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_FW_MEMO,
+			VXGE_HW_FW_API_GET_EPROM_REV,
+			0, &data0, &data1, &steer_ctrl);
+		if (status != VXGE_HW_OK)
+			break;
+
+		img[i].is_valid = VXGE_HW_GET_EPROM_IMAGE_VALID(data0);
+		img[i].index = VXGE_HW_GET_EPROM_IMAGE_INDEX(data0);
+		img[i].type = VXGE_HW_GET_EPROM_IMAGE_TYPE(data0);
+		img[i].version = VXGE_HW_GET_EPROM_IMAGE_REV(data0);
+	}
+
+	return status;
 }
 
 /*
@@ -269,7 +407,7 @@ exit0:
  * This function deallocates memory from the channel and various arrays
  * in the channel
  */
-void __vxge_hw_channel_free(struct __vxge_hw_channel *channel)
+static void __vxge_hw_channel_free(struct __vxge_hw_channel *channel)
 {
 	kfree(channel->work_arr);
 	kfree(channel->free_arr);
@@ -283,7 +421,7 @@ void __vxge_hw_channel_free(struct __vxg
  * This function initializes a channel by properly setting the
  * various references
  */
-enum vxge_hw_status
+static enum vxge_hw_status
 __vxge_hw_channel_initialize(struct __vxge_hw_channel *channel)
 {
 	u32 i;
@@ -318,7 +456,7 @@ __vxge_hw_channel_initialize(struct __vx
  * __vxge_hw_channel_reset - Resets a channel
  * This function resets a channel by properly setting the various references
  */
-enum vxge_hw_status
+static enum vxge_hw_status
 __vxge_hw_channel_reset(struct __vxge_hw_channel *channel)
 {
 	u32 i;
@@ -345,8 +483,7 @@ __vxge_hw_channel_reset(struct __vxge_hw
  * Initialize certain PCI/PCI-X configuration registers
  * with recommended values. Save config space for future hw resets.
  */
-void
-__vxge_hw_device_pci_e_init(struct __vxge_hw_device *hldev)
+static void __vxge_hw_device_pci_e_init(struct __vxge_hw_device *hldev)
 {
 	u16 cmd = 0;
 
@@ -358,39 +495,7 @@ __vxge_hw_device_pci_e_init(struct __vxg
 	pci_save_state(hldev->pdev);
 }
 
-/*
- * __vxge_hw_device_register_poll
- * Will poll certain register for specified amount of time.
- * Will poll until masked bit is not cleared.
- */
-static enum vxge_hw_status
-__vxge_hw_device_register_poll(void __iomem *reg, u64 mask, u32 max_millis)
-{
-	u64 val64;
-	u32 i = 0;
-	enum vxge_hw_status ret = VXGE_HW_FAIL;
-
-	udelay(10);
-
-	do {
-		val64 = readq(reg);
-		if (!(val64 & mask))
-			return VXGE_HW_OK;
-		udelay(100);
-	} while (++i <= 9);
-
-	i = 0;
-	do {
-		val64 = readq(reg);
-		if (!(val64 & mask))
-			return VXGE_HW_OK;
-		mdelay(1);
-	} while (++i <= max_millis);
-
-	return ret;
-}
-
- /* __vxge_hw_device_vpath_reset_in_prog_check - Check if vpath reset
+/* __vxge_hw_device_vpath_reset_in_prog_check - Check if vpath reset
  * in progress
  * This routine checks the vpath reset in progress register is turned zero
  */
@@ -405,6 +510,60 @@ __vxge_hw_device_vpath_reset_in_prog_che
 }
 
 /*
+ * _hw_legacy_swapper_set - Set the swapper bits for the legacy secion.
+ * Set the swapper bits appropriately for the lagacy section.
+ */
+static enum vxge_hw_status
+__vxge_hw_legacy_swapper_set(struct vxge_hw_legacy_reg __iomem *legacy_reg)
+{
+	u64 val64;
+	enum vxge_hw_status status = VXGE_HW_OK;
+
+	val64 = readq(&legacy_reg->toc_swapper_fb);
+
+	wmb();
+
+	switch (val64) {
+	case VXGE_HW_SWAPPER_INITIAL_VALUE:
+		return status;
+
+	case VXGE_HW_SWAPPER_BYTE_SWAPPED_BIT_FLIPPED:
+		writeq(VXGE_HW_SWAPPER_READ_BYTE_SWAP_ENABLE,
+			&legacy_reg->pifm_rd_swap_en);
+		writeq(VXGE_HW_SWAPPER_READ_BIT_FLAP_ENABLE,
+			&legacy_reg->pifm_rd_flip_en);
+		writeq(VXGE_HW_SWAPPER_WRITE_BYTE_SWAP_ENABLE,
+			&legacy_reg->pifm_wr_swap_en);
+		writeq(VXGE_HW_SWAPPER_WRITE_BIT_FLAP_ENABLE,
+			&legacy_reg->pifm_wr_flip_en);
+		break;
+
+	case VXGE_HW_SWAPPER_BYTE_SWAPPED:
+		writeq(VXGE_HW_SWAPPER_READ_BYTE_SWAP_ENABLE,
+			&legacy_reg->pifm_rd_swap_en);
+		writeq(VXGE_HW_SWAPPER_WRITE_BYTE_SWAP_ENABLE,
+			&legacy_reg->pifm_wr_swap_en);
+		break;
+
+	case VXGE_HW_SWAPPER_BIT_FLIPPED:
+		writeq(VXGE_HW_SWAPPER_READ_BIT_FLAP_ENABLE,
+			&legacy_reg->pifm_rd_flip_en);
+		writeq(VXGE_HW_SWAPPER_WRITE_BIT_FLAP_ENABLE,
+			&legacy_reg->pifm_wr_flip_en);
+		break;
+	}
+
+	wmb();
+
+	val64 = readq(&legacy_reg->toc_swapper_fb);
+
+	if (val64 != VXGE_HW_SWAPPER_INITIAL_VALUE)
+		status = VXGE_HW_ERR_SWAPPER_CTRL;
+
+	return status;
+}
+
+/*
  * __vxge_hw_device_toc_get
  * This routine sets the swapper and reads the toc pointer and returns the
  * memory mapped address of the toc
@@ -435,7 +594,7 @@ exit:
  * register location pointers in the device object. It waits until the ric is
  * completed initializing registers.
  */
-enum vxge_hw_status
+static enum vxge_hw_status
 __vxge_hw_device_reg_addr_get(struct __vxge_hw_device *hldev)
 {
 	u64 val64;
@@ -496,26 +655,6 @@ exit:
 }
 
 /*
- * __vxge_hw_device_id_get
- * This routine returns sets the device id and revision numbers into the device
- * structure
- */
-void __vxge_hw_device_id_get(struct __vxge_hw_device *hldev)
-{
-	u64 val64;
-
-	val64 = readq(&hldev->common_reg->titan_asic_id);
-	hldev->device_id =
-		(u16)VXGE_HW_TITAN_ASIC_ID_GET_INITIAL_DEVICE_ID(val64);
-
-	hldev->major_revision =
-		(u8)VXGE_HW_TITAN_ASIC_ID_GET_INITIAL_MAJOR_REVISION(val64);
-
-	hldev->minor_revision =
-		(u8)VXGE_HW_TITAN_ASIC_ID_GET_INITIAL_MINOR_REVISION(val64);
-}
-
-/*
  * __vxge_hw_device_access_rights_get: Get Access Rights of the driver
  * This routine returns the Access Rights of the driver
  */
@@ -568,10 +707,25 @@ __vxge_hw_device_is_privilaged(u32 host_
 }
 
 /*
+ * __vxge_hw_vpath_func_id_get - Get the function id of the vpath.
+ * Returns the function number of the vpath.
+ */
+static u32
+__vxge_hw_vpath_func_id_get(struct vxge_hw_vpmgmt_reg __iomem *vpmgmt_reg)
+{
+	u64 val64;
+
+	val64 = readq(&vpmgmt_reg->vpath_to_func_map_cfg1);
+
+	return
+	 (u32)VXGE_HW_VPATH_TO_FUNC_MAP_CFG1_GET_VPATH_TO_FUNC_MAP_CFG1(val64);
+}
+
+/*
  * __vxge_hw_device_host_info_get
  * This routine returns the host type assignments
  */
-void __vxge_hw_device_host_info_get(struct __vxge_hw_device *hldev)
+static void __vxge_hw_device_host_info_get(struct __vxge_hw_device *hldev)
 {
 	u64 val64;
 	u32 i;
@@ -584,16 +738,18 @@ void __vxge_hw_device_host_info_get(stru
 	hldev->vpath_assignments = readq(&hldev->common_reg->vpath_assignments);
 
 	for (i = 0; i < VXGE_HW_MAX_VIRTUAL_PATHS; i++) {
-
 		if (!(hldev->vpath_assignments & vxge_mBIT(i)))
 			continue;
 
 		hldev->func_id =
-			__vxge_hw_vpath_func_id_get(i, hldev->vpmgmt_reg[i]);
+			__vxge_hw_vpath_func_id_get(hldev->vpmgmt_reg[i]);
 
 		hldev->access_rights = __vxge_hw_device_access_rights_get(
 			hldev->host_type, hldev->func_id);
 
+		hldev->virtual_paths[i].vp_open = VXGE_HW_VP_NOT_OPEN;
+		hldev->virtual_paths[i].vp_reg = hldev->vpath_reg[i];
+
 		hldev->first_vp_id = i;
 		break;
 	}
@@ -634,7 +790,8 @@ __vxge_hw_verify_pci_e_info(struct __vxg
  * __vxge_hw_device_initialize
  * Initialize Titan-V hardware.
  */
-enum vxge_hw_status __vxge_hw_device_initialize(struct __vxge_hw_device *hldev)
+static enum vxge_hw_status
+__vxge_hw_device_initialize(struct __vxge_hw_device *hldev)
 {
 	enum vxge_hw_status status = VXGE_HW_OK;
 
@@ -650,6 +807,196 @@ exit:
 	return status;
 }
 
+/*
+ * __vxge_hw_vpath_fw_ver_get - Get the fw version
+ * Returns FW Version
+ */
+static enum vxge_hw_status
+__vxge_hw_vpath_fw_ver_get(struct __vxge_hw_virtualpath *vpath,
+			   struct vxge_hw_device_hw_info *hw_info)
+{
+	struct vxge_hw_device_version *fw_version = &hw_info->fw_version;
+	struct vxge_hw_device_date *fw_date = &hw_info->fw_date;
+	struct vxge_hw_device_version *flash_version = &hw_info->flash_version;
+	struct vxge_hw_device_date *flash_date = &hw_info->flash_date;
+	u64 data0, data1 = 0, steer_ctrl = 0;
+	enum vxge_hw_status status;
+
+	status = vxge_hw_vpath_fw_api(vpath,
+			VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION_READ_ENTRY,
+			VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_FW_MEMO,
+			0, &data0, &data1, &steer_ctrl);
+	if (status != VXGE_HW_OK)
+		goto exit;
+
+	fw_date->day =
+	    (u32) VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_FW_VER_DAY(data0);
+	fw_date->month =
+	    (u32) VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_FW_VER_MONTH(data0);
+	fw_date->year =
+	    (u32) VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_FW_VER_YEAR(data0);
+
+	snprintf(fw_date->date, VXGE_HW_FW_STRLEN, "%2.2d/%2.2d/%4.4d",
+		 fw_date->month, fw_date->day, fw_date->year);
+
+	fw_version->major =
+	    (u32) VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_FW_VER_MAJOR(data0);
+	fw_version->minor =
+	    (u32) VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_FW_VER_MINOR(data0);
+	fw_version->build =
+	    (u32) VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_FW_VER_BUILD(data0);
+
+	snprintf(fw_version->version, VXGE_HW_FW_STRLEN, "%d.%d.%d",
+		 fw_version->major, fw_version->minor, fw_version->build);
+
+	flash_date->day =
+	    (u32) VXGE_HW_RTS_ACCESS_STEER_DATA1_GET_FLASH_VER_DAY(data1);
+	flash_date->month =
+	    (u32) VXGE_HW_RTS_ACCESS_STEER_DATA1_GET_FLASH_VER_MONTH(data1);
+	flash_date->year =
+	    (u32) VXGE_HW_RTS_ACCESS_STEER_DATA1_GET_FLASH_VER_YEAR(data1);
+
+	snprintf(flash_date->date, VXGE_HW_FW_STRLEN, "%2.2d/%2.2d/%4.4d",
+		 flash_date->month, flash_date->day, flash_date->year);
+
+	flash_version->major =
+	    (u32) VXGE_HW_RTS_ACCESS_STEER_DATA1_GET_FLASH_VER_MAJOR(data1);
+	flash_version->minor =
+	    (u32) VXGE_HW_RTS_ACCESS_STEER_DATA1_GET_FLASH_VER_MINOR(data1);
+	flash_version->build =
+	    (u32) VXGE_HW_RTS_ACCESS_STEER_DATA1_GET_FLASH_VER_BUILD(data1);
+
+	snprintf(flash_version->version, VXGE_HW_FW_STRLEN, "%d.%d.%d",
+		 flash_version->major, flash_version->minor,
+		 flash_version->build);
+
+exit:
+	return status;
+}
+
+/*
+ * __vxge_hw_vpath_card_info_get - Get the serial numbers,
+ * part number and product description.
+ */
+static enum vxge_hw_status
+__vxge_hw_vpath_card_info_get(struct __vxge_hw_virtualpath *vpath,
+			      struct vxge_hw_device_hw_info *hw_info)
+{
+	enum vxge_hw_status status;
+	u64 data0, data1 = 0, steer_ctrl = 0;
+	u8 *serial_number = hw_info->serial_number;
+	u8 *part_number = hw_info->part_number;
+	u8 *product_desc = hw_info->product_desc;
+	u32 i, j = 0;
+
+	data0 = VXGE_HW_RTS_ACCESS_STEER_DATA0_MEMO_ITEM_SERIAL_NUMBER;
+
+	status = vxge_hw_vpath_fw_api(vpath,
+			VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION_READ_MEMO_ENTRY,
+			VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_FW_MEMO,
+			0, &data0, &data1, &steer_ctrl);
+	if (status != VXGE_HW_OK)
+		return status;
+
+	((u64 *)serial_number)[0] = be64_to_cpu(data0);
+	((u64 *)serial_number)[1] = be64_to_cpu(data1);
+
+	data0 = VXGE_HW_RTS_ACCESS_STEER_DATA0_MEMO_ITEM_PART_NUMBER;
+	data1 = steer_ctrl = 0;
+
+	status = vxge_hw_vpath_fw_api(vpath,
+			VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION_READ_MEMO_ENTRY,
+			VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_FW_MEMO,
+			0, &data0, &data1, &steer_ctrl);
+	if (status != VXGE_HW_OK)
+		return status;
+
+	((u64 *)part_number)[0] = be64_to_cpu(data0);
+	((u64 *)part_number)[1] = be64_to_cpu(data1);
+
+	for (i = VXGE_HW_RTS_ACCESS_STEER_DATA0_MEMO_ITEM_DESC_0;
+	     i <= VXGE_HW_RTS_ACCESS_STEER_DATA0_MEMO_ITEM_DESC_3; i++) {
+		data0 = i;
+		data1 = steer_ctrl = 0;
+
+		status = vxge_hw_vpath_fw_api(vpath,
+			VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION_READ_MEMO_ENTRY,
+			VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_FW_MEMO,
+			0, &data0, &data1, &steer_ctrl);
+		if (status != VXGE_HW_OK)
+			return status;
+
+		((u64 *)product_desc)[j++] = be64_to_cpu(data0);
+		((u64 *)product_desc)[j++] = be64_to_cpu(data1);
+	}
+
+	return status;
+}
+
+/*
+ * __vxge_hw_vpath_pci_func_mode_get - Get the pci mode
+ * Returns pci function mode
+ */
+static enum vxge_hw_status
+__vxge_hw_vpath_pci_func_mode_get(struct __vxge_hw_virtualpath *vpath,
+				  struct vxge_hw_device_hw_info *hw_info)
+{
+	u64 data0, data1 = 0, steer_ctrl = 0;
+	enum vxge_hw_status status;
+
+	data0 = 0;
+
+	status = vxge_hw_vpath_fw_api(vpath,
+			VXGE_HW_FW_API_GET_FUNC_MODE,
+			VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_FW_MEMO,
+			0, &data0, &data1, &steer_ctrl);
+	if (status != VXGE_HW_OK)
+		return status;
+
+	hw_info->function_mode = VXGE_HW_GET_FUNC_MODE_VAL(data0);
+	return status;
+}
+
+/*
+ * __vxge_hw_vpath_addr_get - Get the hw address entry for this vpath
+ *               from MAC address table.
+ */
+static enum vxge_hw_status
+__vxge_hw_vpath_addr_get(struct __vxge_hw_virtualpath *vpath,
+			 u8 *macaddr, u8 *macaddr_mask)
+{
+	u64 action = VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION_LIST_FIRST_ENTRY,
+	    data0 = 0, data1 = 0, steer_ctrl = 0;
+	enum vxge_hw_status status;
+	int i;
+
+	do {
+		status = vxge_hw_vpath_fw_api(vpath, action,
+			VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_DA,
+			0, &data0, &data1, &steer_ctrl);
+		if (status != VXGE_HW_OK)
+			goto exit;
+
+		data0 = VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_DA_MAC_ADDR(data0);
+		data1 = VXGE_HW_RTS_ACCESS_STEER_DATA1_GET_DA_MAC_ADDR_MASK(
+									data1);
+
+		for (i = ETH_ALEN; i > 0; i--) {
+			macaddr[i - 1] = (u8) (data0 & 0xFF);
+			data0 >>= 8;
+
+			macaddr_mask[i - 1] = (u8) (data1 & 0xFF);
+			data1 >>= 8;
+		}
+
+		action = VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION_LIST_NEXT_ENTRY;
+		data0 = 0, data1 = 0, steer_ctrl = 0;
+
+	} while (!is_valid_ether_addr(macaddr));
+exit:
+	return status;
+}
+
 /**
  * vxge_hw_device_hw_info_get - Get the hw information
  * Returns the vpath mask that has the bits set for each vpath allocated
@@ -665,9 +1012,9 @@ vxge_hw_device_hw_info_get(void __iomem
 	struct vxge_hw_toc_reg __iomem *toc;
 	struct vxge_hw_mrpcim_reg __iomem *mrpcim_reg;
 	struct vxge_hw_common_reg __iomem *common_reg;
-	struct vxge_hw_vpath_reg __iomem *vpath_reg;
 	struct vxge_hw_vpmgmt_reg __iomem *vpmgmt_reg;
 	enum vxge_hw_status status;
+	struct __vxge_hw_virtualpath vpath;
 
 	memset(hw_info, 0, sizeof(struct vxge_hw_device_hw_info));
 
@@ -693,7 +1040,6 @@ vxge_hw_device_hw_info_get(void __iomem
 	   (u32)VXGE_HW_HOST_TYPE_ASSIGNMENTS_GET_HOST_TYPE_ASSIGNMENTS(val64);
 
 	for (i = 0; i < VXGE_HW_MAX_VIRTUAL_PATHS; i++) {
-
 		if (!((hw_info->vpath_mask) & vxge_mBIT(i)))
 			continue;
 
@@ -702,7 +1048,7 @@ vxge_hw_device_hw_info_get(void __iomem
 		vpmgmt_reg = (struct vxge_hw_vpmgmt_reg __iomem *)
 				(bar0 + val64);
 
-		hw_info->func_id = __vxge_hw_vpath_func_id_get(i, vpmgmt_reg);
+		hw_info->func_id = __vxge_hw_vpath_func_id_get(vpmgmt_reg);
 		if (__vxge_hw_device_access_rights_get(hw_info->host_type,
 			hw_info->func_id) &
 			VXGE_HW_DEVICE_ACCESS_RIGHT_MRPCIM) {
@@ -718,16 +1064,19 @@ vxge_hw_device_hw_info_get(void __iomem
 
 		val64 = readq(&toc->toc_vpath_pointer[i]);
 
-		vpath_reg = (struct vxge_hw_vpath_reg __iomem *)(bar0 + val64);
+		vpath.vp_reg = (struct vxge_hw_vpath_reg __iomem *)
+			       (bar0 + val64);
+		vpath.vp_open = 0;
 
-		hw_info->function_mode =
-			__vxge_hw_vpath_pci_func_mode_get(i, vpath_reg);
+		status = __vxge_hw_vpath_pci_func_mode_get(&vpath, hw_info);
+		if (status != VXGE_HW_OK)
+			goto exit;
 
-		status = __vxge_hw_vpath_fw_ver_get(i, vpath_reg, hw_info);
+		status = __vxge_hw_vpath_fw_ver_get(&vpath, hw_info);
 		if (status != VXGE_HW_OK)
 			goto exit;
 
-		status = __vxge_hw_vpath_card_info_get(i, vpath_reg, hw_info);
+		status = __vxge_hw_vpath_card_info_get(&vpath, hw_info);
 		if (status != VXGE_HW_OK)
 			goto exit;
 
@@ -735,14 +1084,15 @@ vxge_hw_device_hw_info_get(void __iomem
 	}
 
 	for (i = 0; i < VXGE_HW_MAX_VIRTUAL_PATHS; i++) {
-
 		if (!((hw_info->vpath_mask) & vxge_mBIT(i)))
 			continue;
 
 		val64 = readq(&toc->toc_vpath_pointer[i]);
-		vpath_reg = (struct vxge_hw_vpath_reg __iomem *)(bar0 + val64);
+		vpath.vp_reg = (struct vxge_hw_vpath_reg __iomem *)
+			       (bar0 + val64);
+		vpath.vp_open = 0;
 
-		status =  __vxge_hw_vpath_addr_get(i, vpath_reg,
+		status =  __vxge_hw_vpath_addr_get(&vpath,
 				hw_info->mac_addrs[i],
 				hw_info->mac_addr_masks[i]);
 		if (status != VXGE_HW_OK)
@@ -753,6 +1103,218 @@ exit:
 }
 
 /*
+ * __vxge_hw_blockpool_destroy - Deallocates the block pool
+ */
+static void __vxge_hw_blockpool_destroy(struct __vxge_hw_blockpool *blockpool)
+{
+	struct __vxge_hw_device *hldev;
+	struct list_head *p, *n;
+	u16 ret;
+
+	if (blockpool == NULL) {
+		ret = 1;
+		goto exit;
+	}
+
+	hldev = blockpool->hldev;
+
+	list_for_each_safe(p, n, &blockpool->free_block_list) {
+		pci_unmap_single(hldev->pdev,
+			((struct __vxge_hw_blockpool_entry *)p)->dma_addr,
+			((struct __vxge_hw_blockpool_entry *)p)->length,
+			PCI_DMA_BIDIRECTIONAL);
+
+		vxge_os_dma_free(hldev->pdev,
+			((struct __vxge_hw_blockpool_entry *)p)->memblock,
+			&((struct __vxge_hw_blockpool_entry *)p)->acc_handle);
+
+		list_del(&((struct __vxge_hw_blockpool_entry *)p)->item);
+		kfree(p);
+		blockpool->pool_size--;
+	}
+
+	list_for_each_safe(p, n, &blockpool->free_entry_list) {
+		list_del(&((struct __vxge_hw_blockpool_entry *)p)->item);
+		kfree((void *)p);
+	}
+	ret = 0;
+exit:
+	return;
+}
+
+/*
+ * __vxge_hw_blockpool_create - Create block pool
+ */
+static enum vxge_hw_status
+__vxge_hw_blockpool_create(struct __vxge_hw_device *hldev,
+			   struct __vxge_hw_blockpool *blockpool,
+			   u32 pool_size,
+			   u32 pool_max)
+{
+	u32 i;
+	struct __vxge_hw_blockpool_entry *entry = NULL;
+	void *memblock;
+	dma_addr_t dma_addr;
+	struct pci_dev *dma_handle;
+	struct pci_dev *acc_handle;
+	enum vxge_hw_status status = VXGE_HW_OK;
+
+	if (blockpool == NULL) {
+		status = VXGE_HW_FAIL;
+		goto blockpool_create_exit;
+	}
+
+	blockpool->hldev = hldev;
+	blockpool->block_size = VXGE_HW_BLOCK_SIZE;
+	blockpool->pool_size = 0;
+	blockpool->pool_max = pool_max;
+	blockpool->req_out = 0;
+
+	INIT_LIST_HEAD(&blockpool->free_block_list);
+	INIT_LIST_HEAD(&blockpool->free_entry_list);
+
+	for (i = 0; i < pool_size + pool_max; i++) {
+		entry = kzalloc(sizeof(struct __vxge_hw_blockpool_entry),
+				GFP_KERNEL);
+		if (entry == NULL) {
+			__vxge_hw_blockpool_destroy(blockpool);
+			status = VXGE_HW_ERR_OUT_OF_MEMORY;
+			goto blockpool_create_exit;
+		}
+		list_add(&entry->item, &blockpool->free_entry_list);
+	}
+
+	for (i = 0; i < pool_size; i++) {
+		memblock = vxge_os_dma_malloc(
+				hldev->pdev,
+				VXGE_HW_BLOCK_SIZE,
+				&dma_handle,
+				&acc_handle);
+		if (memblock == NULL) {
+			__vxge_hw_blockpool_destroy(blockpool);
+			status = VXGE_HW_ERR_OUT_OF_MEMORY;
+			goto blockpool_create_exit;
+		}
+
+		dma_addr = pci_map_single(hldev->pdev, memblock,
+				VXGE_HW_BLOCK_SIZE, PCI_DMA_BIDIRECTIONAL);
+		if (unlikely(pci_dma_mapping_error(hldev->pdev,
+				dma_addr))) {
+			vxge_os_dma_free(hldev->pdev, memblock, &acc_handle);
+			__vxge_hw_blockpool_destroy(blockpool);
+			status = VXGE_HW_ERR_OUT_OF_MEMORY;
+			goto blockpool_create_exit;
+		}
+
+		if (!list_empty(&blockpool->free_entry_list))
+			entry = (struct __vxge_hw_blockpool_entry *)
+				list_first_entry(&blockpool->free_entry_list,
+					struct __vxge_hw_blockpool_entry,
+					item);
+
+		if (entry == NULL)
+			entry =
+			    kzalloc(sizeof(struct __vxge_hw_blockpool_entry),
+					GFP_KERNEL);
+		if (entry != NULL) {
+			list_del(&entry->item);
+			entry->length = VXGE_HW_BLOCK_SIZE;
+			entry->memblock = memblock;
+			entry->dma_addr = dma_addr;
+			entry->acc_handle = acc_handle;
+			entry->dma_handle = dma_handle;
+			list_add(&entry->item,
+					  &blockpool->free_block_list);
+			blockpool->pool_size++;
+		} else {
+			__vxge_hw_blockpool_destroy(blockpool);
+			status = VXGE_HW_ERR_OUT_OF_MEMORY;
+			goto blockpool_create_exit;
+		}
+	}
+
+blockpool_create_exit:
+	return status;
+}
+
+/*
+ * __vxge_hw_device_fifo_config_check - Check fifo configuration.
+ * Check the fifo configuration
+ */
+static enum vxge_hw_status
+__vxge_hw_device_fifo_config_check(struct vxge_hw_fifo_config *fifo_config)
+{
+	if ((fifo_config->fifo_blocks < VXGE_HW_MIN_FIFO_BLOCKS) ||
+	    (fifo_config->fifo_blocks > VXGE_HW_MAX_FIFO_BLOCKS))
+		return VXGE_HW_BADCFG_FIFO_BLOCKS;
+
+	return VXGE_HW_OK;
+}
+
+/*
+ * __vxge_hw_device_vpath_config_check - Check vpath configuration.
+ * Check the vpath configuration
+ */
+static enum vxge_hw_status
+__vxge_hw_device_vpath_config_check(struct vxge_hw_vp_config *vp_config)
+{
+	enum vxge_hw_status status;
+
+	if ((vp_config->min_bandwidth < VXGE_HW_VPATH_BANDWIDTH_MIN) ||
+	    (vp_config->min_bandwidth >	VXGE_HW_VPATH_BANDWIDTH_MAX))
+		return VXGE_HW_BADCFG_VPATH_MIN_BANDWIDTH;
+
+	status = __vxge_hw_device_fifo_config_check(&vp_config->fifo);
+	if (status != VXGE_HW_OK)
+		return status;
+
+	if ((vp_config->mtu != VXGE_HW_VPATH_USE_FLASH_DEFAULT_INITIAL_MTU) &&
+		((vp_config->mtu < VXGE_HW_VPATH_MIN_INITIAL_MTU) ||
+		(vp_config->mtu > VXGE_HW_VPATH_MAX_INITIAL_MTU)))
+		return VXGE_HW_BADCFG_VPATH_MTU;
+
+	if ((vp_config->rpa_strip_vlan_tag !=
+		VXGE_HW_VPATH_RPA_STRIP_VLAN_TAG_USE_FLASH_DEFAULT) &&
+		(vp_config->rpa_strip_vlan_tag !=
+		VXGE_HW_VPATH_RPA_STRIP_VLAN_TAG_ENABLE) &&
+		(vp_config->rpa_strip_vlan_tag !=
+		VXGE_HW_VPATH_RPA_STRIP_VLAN_TAG_DISABLE))
+		return VXGE_HW_BADCFG_VPATH_RPA_STRIP_VLAN_TAG;
+
+	return VXGE_HW_OK;
+}
+
+/*
+ * __vxge_hw_device_config_check - Check device configuration.
+ * Check the device configuration
+ */
+static enum vxge_hw_status
+__vxge_hw_device_config_check(struct vxge_hw_device_config *new_config)
+{
+	u32 i;
+	enum vxge_hw_status status;
+
+	if ((new_config->intr_mode != VXGE_HW_INTR_MODE_IRQLINE) &&
+	    (new_config->intr_mode != VXGE_HW_INTR_MODE_MSIX) &&
+	    (new_config->intr_mode != VXGE_HW_INTR_MODE_MSIX_ONE_SHOT) &&
+	    (new_config->intr_mode != VXGE_HW_INTR_MODE_DEF))
+		return VXGE_HW_BADCFG_INTR_MODE;
+
+	if ((new_config->rts_mac_en != VXGE_HW_RTS_MAC_DISABLE) &&
+	    (new_config->rts_mac_en != VXGE_HW_RTS_MAC_ENABLE))
+		return VXGE_HW_BADCFG_RTS_MAC_EN;
+
+	for (i = 0; i < VXGE_HW_MAX_VIRTUAL_PATHS; i++) {
+		status = __vxge_hw_device_vpath_config_check(
+				&new_config->vp_config[i]);
+		if (status != VXGE_HW_OK)
+			return status;
+	}
+
+	return VXGE_HW_OK;
+}
+
+/*
  * vxge_hw_device_initialize - Initialize Titan device.
  * Initialize Titan device. Note that all the arguments of this public API
  * are 'IN', including @hldev. Driver cooperates with
@@ -776,14 +1338,12 @@ vxge_hw_device_initialize(
 	if (status != VXGE_HW_OK)
 		goto exit;
 
-	hldev = (struct __vxge_hw_device *)
-			vmalloc(sizeof(struct __vxge_hw_device));
+	hldev = vzalloc(sizeof(struct __vxge_hw_device));
 	if (hldev == NULL) {
 		status = VXGE_HW_ERR_OUT_OF_MEMORY;
 		goto exit;
 	}
 
-	memset(hldev, 0, sizeof(struct __vxge_hw_device));
 	hldev->magic = VXGE_HW_DEVICE_MAGIC;
 
 	vxge_hw_device_debug_set(hldev, VXGE_ERR, VXGE_COMPONENT_ALL);
@@ -806,7 +1366,6 @@ vxge_hw_device_initialize(
 		vfree(hldev);
 		goto exit;
 	}
-	__vxge_hw_device_id_get(hldev);
 
 	__vxge_hw_device_host_info_get(hldev);
 
@@ -814,7 +1373,6 @@ vxge_hw_device_initialize(
 	nblocks++;
 
 	for (i = 0; i < VXGE_HW_MAX_VIRTUAL_PATHS; i++) {
-
 		if (!(hldev->vpath_assignments & vxge_mBIT(i)))
 			continue;
 
@@ -839,7 +1397,6 @@ vxge_hw_device_initialize(
 	}
 
 	status = __vxge_hw_device_initialize(hldev);
-
 	if (status != VXGE_HW_OK) {
 		vxge_hw_device_terminate(hldev);
 		goto exit;
@@ -865,6 +1422,242 @@ vxge_hw_device_terminate(struct __vxge_h
 }
 
 /*
+ * __vxge_hw_vpath_stats_access - Get the statistics from the given location
+ *                           and offset and perform an operation
+ */
+static enum vxge_hw_status
+__vxge_hw_vpath_stats_access(struct __vxge_hw_virtualpath *vpath,
+			     u32 operation, u32 offset, u64 *stat)
+{
+	u64 val64;
+	enum vxge_hw_status status = VXGE_HW_OK;
+	struct vxge_hw_vpath_reg __iomem *vp_reg;
+
+	if (vpath->vp_open == VXGE_HW_VP_NOT_OPEN) {
+		status = VXGE_HW_ERR_VPATH_NOT_OPEN;
+		goto vpath_stats_access_exit;
+	}
+
+	vp_reg = vpath->vp_reg;
+
+	val64 =  VXGE_HW_XMAC_STATS_ACCESS_CMD_OP(operation) |
+		 VXGE_HW_XMAC_STATS_ACCESS_CMD_STROBE |
+		 VXGE_HW_XMAC_STATS_ACCESS_CMD_OFFSET_SEL(offset);
+
+	status = __vxge_hw_pio_mem_write64(val64,
+				&vp_reg->xmac_stats_access_cmd,
+				VXGE_HW_XMAC_STATS_ACCESS_CMD_STROBE,
+				vpath->hldev->config.device_poll_millis);
+	if ((status == VXGE_HW_OK) && (operation == VXGE_HW_STATS_OP_READ))
+		*stat = readq(&vp_reg->xmac_stats_access_data);
+	else
+		*stat = 0;
+
+vpath_stats_access_exit:
+	return status;
+}
+
+/*
+ * __vxge_hw_vpath_xmac_tx_stats_get - Get the TX Statistics of a vpath
+ */
+static enum vxge_hw_status
+__vxge_hw_vpath_xmac_tx_stats_get(struct __vxge_hw_virtualpath *vpath,
+			struct vxge_hw_xmac_vpath_tx_stats *vpath_tx_stats)
+{
+	u64 *val64;
+	int i;
+	u32 offset = VXGE_HW_STATS_VPATH_TX_OFFSET;
+	enum vxge_hw_status status = VXGE_HW_OK;
+
+	val64 = (u64 *)vpath_tx_stats;
+
+	if (vpath->vp_open == VXGE_HW_VP_NOT_OPEN) {
+		status = VXGE_HW_ERR_VPATH_NOT_OPEN;
+		goto exit;
+	}
+
+	for (i = 0; i < sizeof(struct vxge_hw_xmac_vpath_tx_stats) / 8; i++) {
+		status = __vxge_hw_vpath_stats_access(vpath,
+					VXGE_HW_STATS_OP_READ,
+					offset, val64);
+		if (status != VXGE_HW_OK)
+			goto exit;
+		offset++;
+		val64++;
+	}
+exit:
+	return status;
+}
+
+/*
+ * __vxge_hw_vpath_xmac_rx_stats_get - Get the RX Statistics of a vpath
+ */
+static enum vxge_hw_status
+__vxge_hw_vpath_xmac_rx_stats_get(struct __vxge_hw_virtualpath *vpath,
+			struct vxge_hw_xmac_vpath_rx_stats *vpath_rx_stats)
+{
+	u64 *val64;
+	enum vxge_hw_status status = VXGE_HW_OK;
+	int i;
+	u32 offset = VXGE_HW_STATS_VPATH_RX_OFFSET;
+	val64 = (u64 *) vpath_rx_stats;
+
+	if (vpath->vp_open == VXGE_HW_VP_NOT_OPEN) {
+		status = VXGE_HW_ERR_VPATH_NOT_OPEN;
+		goto exit;
+	}
+	for (i = 0; i < sizeof(struct vxge_hw_xmac_vpath_rx_stats) / 8; i++) {
+		status = __vxge_hw_vpath_stats_access(vpath,
+					VXGE_HW_STATS_OP_READ,
+					offset >> 3, val64);
+		if (status != VXGE_HW_OK)
+			goto exit;
+
+		offset += 8;
+		val64++;
+	}
+exit:
+	return status;
+}
+
+/*
+ * __vxge_hw_vpath_stats_get - Get the vpath hw statistics.
+ */
+static enum vxge_hw_status
+__vxge_hw_vpath_stats_get(struct __vxge_hw_virtualpath *vpath,
+			  struct vxge_hw_vpath_stats_hw_info *hw_stats)
+{
+	u64 val64;
+	enum vxge_hw_status status = VXGE_HW_OK;
+	struct vxge_hw_vpath_reg __iomem *vp_reg;
+
+	if (vpath->vp_open == VXGE_HW_VP_NOT_OPEN) {
+		status = VXGE_HW_ERR_VPATH_NOT_OPEN;
+		goto exit;
+	}
+	vp_reg = vpath->vp_reg;
+
+	val64 = readq(&vp_reg->vpath_debug_stats0);
+	hw_stats->ini_num_mwr_sent =
+		(u32)VXGE_HW_VPATH_DEBUG_STATS0_GET_INI_NUM_MWR_SENT(val64);
+
+	val64 = readq(&vp_reg->vpath_debug_stats1);
+	hw_stats->ini_num_mrd_sent =
+		(u32)VXGE_HW_VPATH_DEBUG_STATS1_GET_INI_NUM_MRD_SENT(val64);
+
+	val64 = readq(&vp_reg->vpath_debug_stats2);
+	hw_stats->ini_num_cpl_rcvd =
+		(u32)VXGE_HW_VPATH_DEBUG_STATS2_GET_INI_NUM_CPL_RCVD(val64);
+
+	val64 = readq(&vp_reg->vpath_debug_stats3);
+	hw_stats->ini_num_mwr_byte_sent =
+		VXGE_HW_VPATH_DEBUG_STATS3_GET_INI_NUM_MWR_BYTE_SENT(val64);
+
+	val64 = readq(&vp_reg->vpath_debug_stats4);
+	hw_stats->ini_num_cpl_byte_rcvd =
+		VXGE_HW_VPATH_DEBUG_STATS4_GET_INI_NUM_CPL_BYTE_RCVD(val64);
+
+	val64 = readq(&vp_reg->vpath_debug_stats5);
+	hw_stats->wrcrdtarb_xoff =
+		(u32)VXGE_HW_VPATH_DEBUG_STATS5_GET_WRCRDTARB_XOFF(val64);
+
+	val64 = readq(&vp_reg->vpath_debug_stats6);
+	hw_stats->rdcrdtarb_xoff =
+		(u32)VXGE_HW_VPATH_DEBUG_STATS6_GET_RDCRDTARB_XOFF(val64);
+
+	val64 = readq(&vp_reg->vpath_genstats_count01);
+	hw_stats->vpath_genstats_count0 =
+	(u32)VXGE_HW_VPATH_GENSTATS_COUNT01_GET_PPIF_VPATH_GENSTATS_COUNT0(
+		val64);
+
+	val64 = readq(&vp_reg->vpath_genstats_count01);
+	hw_stats->vpath_genstats_count1 =
+	(u32)VXGE_HW_VPATH_GENSTATS_COUNT01_GET_PPIF_VPATH_GENSTATS_COUNT1(
+		val64);
+
+	val64 = readq(&vp_reg->vpath_genstats_count23);
+	hw_stats->vpath_genstats_count2 =
+	(u32)VXGE_HW_VPATH_GENSTATS_COUNT23_GET_PPIF_VPATH_GENSTATS_COUNT2(
+		val64);
+
+	val64 = readq(&vp_reg->vpath_genstats_count01);
+	hw_stats->vpath_genstats_count3 =
+	(u32)VXGE_HW_VPATH_GENSTATS_COUNT23_GET_PPIF_VPATH_GENSTATS_COUNT3(
+		val64);
+
+	val64 = readq(&vp_reg->vpath_genstats_count4);
+	hw_stats->vpath_genstats_count4 =
+	(u32)VXGE_HW_VPATH_GENSTATS_COUNT4_GET_PPIF_VPATH_GENSTATS_COUNT4(
+		val64);
+
+	val64 = readq(&vp_reg->vpath_genstats_count5);
+	hw_stats->vpath_genstats_count5 =
+	(u32)VXGE_HW_VPATH_GENSTATS_COUNT5_GET_PPIF_VPATH_GENSTATS_COUNT5(
+		val64);
+
+	status = __vxge_hw_vpath_xmac_tx_stats_get(vpath, &hw_stats->tx_stats);
+	if (status != VXGE_HW_OK)
+		goto exit;
+
+	status = __vxge_hw_vpath_xmac_rx_stats_get(vpath, &hw_stats->rx_stats);
+	if (status != VXGE_HW_OK)
+		goto exit;
+
+	VXGE_HW_VPATH_STATS_PIO_READ(
+		VXGE_HW_STATS_VPATH_PROG_EVENT_VNUM0_OFFSET);
+
+	hw_stats->prog_event_vnum0 =
+			(u32)VXGE_HW_STATS_GET_VPATH_PROG_EVENT_VNUM0(val64);
+
+	hw_stats->prog_event_vnum1 =
+			(u32)VXGE_HW_STATS_GET_VPATH_PROG_EVENT_VNUM1(val64);
+
+	VXGE_HW_VPATH_STATS_PIO_READ(
+		VXGE_HW_STATS_VPATH_PROG_EVENT_VNUM2_OFFSET);
+
+	hw_stats->prog_event_vnum2 =
+			(u32)VXGE_HW_STATS_GET_VPATH_PROG_EVENT_VNUM2(val64);
+
+	hw_stats->prog_event_vnum3 =
+			(u32)VXGE_HW_STATS_GET_VPATH_PROG_EVENT_VNUM3(val64);
+
+	val64 = readq(&vp_reg->rx_multi_cast_stats);
+	hw_stats->rx_multi_cast_frame_discard =
+		(u16)VXGE_HW_RX_MULTI_CAST_STATS_GET_FRAME_DISCARD(val64);
+
+	val64 = readq(&vp_reg->rx_frm_transferred);
+	hw_stats->rx_frm_transferred =
+		(u32)VXGE_HW_RX_FRM_TRANSFERRED_GET_RX_FRM_TRANSFERRED(val64);
+
+	val64 = readq(&vp_reg->rxd_returned);
+	hw_stats->rxd_returned =
+		(u16)VXGE_HW_RXD_RETURNED_GET_RXD_RETURNED(val64);
+
+	val64 = readq(&vp_reg->dbg_stats_rx_mpa);
+	hw_stats->rx_mpa_len_fail_frms =
+		(u16)VXGE_HW_DBG_STATS_GET_RX_MPA_LEN_FAIL_FRMS(val64);
+	hw_stats->rx_mpa_mrk_fail_frms =
+		(u16)VXGE_HW_DBG_STATS_GET_RX_MPA_MRK_FAIL_FRMS(val64);
+	hw_stats->rx_mpa_crc_fail_frms =
+		(u16)VXGE_HW_DBG_STATS_GET_RX_MPA_CRC_FAIL_FRMS(val64);
+
+	val64 = readq(&vp_reg->dbg_stats_rx_fau);
+	hw_stats->rx_permitted_frms =
+		(u16)VXGE_HW_DBG_STATS_GET_RX_FAU_RX_PERMITTED_FRMS(val64);
+	hw_stats->rx_vp_reset_discarded_frms =
+	(u16)VXGE_HW_DBG_STATS_GET_RX_FAU_RX_VP_RESET_DISCARDED_FRMS(val64);
+	hw_stats->rx_wol_frms =
+		(u16)VXGE_HW_DBG_STATS_GET_RX_FAU_RX_WOL_FRMS(val64);
+
+	val64 = readq(&vp_reg->tx_vp_reset_discarded_frms);
+	hw_stats->tx_vp_reset_discarded_frms =
+	(u16)VXGE_HW_TX_VP_RESET_DISCARDED_FRMS_GET_TX_VP_RESET_DISCARDED_FRMS(
+		val64);
+exit:
+	return status;
+}
+
+/*
  * vxge_hw_device_stats_get - Get the device hw statistics.
  * Returns the vpath h/w stats for the device.
  */
@@ -876,7 +1669,6 @@ vxge_hw_device_stats_get(struct __vxge_h
 	enum vxge_hw_status status = VXGE_HW_OK;
 
 	for (i = 0; i < VXGE_HW_MAX_VIRTUAL_PATHS; i++) {
-
 		if (!(hldev->vpaths_deployed & vxge_mBIT(i)) ||
 			(hldev->virtual_paths[i].vp_open ==
 				VXGE_HW_VP_NOT_OPEN))
@@ -1031,7 +1823,6 @@ vxge_hw_device_xmac_stats_get(struct __v
 
 	status = vxge_hw_device_xmac_aggr_stats_get(hldev,
 					0, &xmac_stats->aggr_stats[0]);
-
 	if (status != VXGE_HW_OK)
 		goto exit;
 
@@ -1165,7 +1956,6 @@ exit:
  * It can be used to set or reset Pause frame generation or reception
  * support of the NIC.
  */
-
 enum vxge_hw_status vxge_hw_device_setpause_data(struct __vxge_hw_device *hldev,
 						 u32 port, u32 tx, u32 rx)
 {
@@ -1407,190 +2197,359 @@ exit:
 }
 
 /*
- * __vxge_hw_ring_create - Create a Ring
- * This function creates Ring and initializes it.
- *
+ * __vxge_hw_channel_allocate - Allocate memory for channel
+ * This function allocates required memory for the channel and various arrays
+ * in the channel
  */
-static enum vxge_hw_status
-__vxge_hw_ring_create(struct __vxge_hw_vpath_handle *vp,
-		      struct vxge_hw_ring_attr *attr)
+static struct __vxge_hw_channel *
+__vxge_hw_channel_allocate(struct __vxge_hw_vpath_handle *vph,
+			   enum __vxge_hw_channel_type type,
+			   u32 length, u32 per_dtr_space,
+			   void *userdata)
 {
-	enum vxge_hw_status status = VXGE_HW_OK;
-	struct __vxge_hw_ring *ring;
-	u32 ring_length;
-	struct vxge_hw_ring_config *config;
+	struct __vxge_hw_channel *channel;
 	struct __vxge_hw_device *hldev;
+	int size = 0;
 	u32 vp_id;
-	struct vxge_hw_mempool_cbs ring_mp_callback;
 
-	if ((vp == NULL) || (attr == NULL)) {
+	hldev = vph->vpath->hldev;
+	vp_id = vph->vpath->vp_id;
+
+	switch (type) {
+	case VXGE_HW_CHANNEL_TYPE_FIFO:
+		size = sizeof(struct __vxge_hw_fifo);
+		break;
+	case VXGE_HW_CHANNEL_TYPE_RING:
+		size = sizeof(struct __vxge_hw_ring);
+		break;
+	default:
+		break;
+	}
+
+	channel = kzalloc(size, GFP_KERNEL);
+	if (channel == NULL)
+		goto exit0;
+	INIT_LIST_HEAD(&channel->item);
+
+	channel->common_reg = hldev->common_reg;
+	channel->first_vp_id = hldev->first_vp_id;
+	channel->type = type;
+	channel->devh = hldev;
+	channel->vph = vph;
+	channel->userdata = userdata;
+	channel->per_dtr_space = per_dtr_space;
+	channel->length = length;
+	channel->vp_id = vp_id;
+
+	channel->work_arr = kzalloc(sizeof(void *)*length, GFP_KERNEL);
+	if (channel->work_arr == NULL)
+		goto exit1;
+
+	channel->free_arr = kzalloc(sizeof(void *)*length, GFP_KERNEL);
+	if (channel->free_arr == NULL)
+		goto exit1;
+	channel->free_ptr = length;
+
+	channel->reserve_arr = kzalloc(sizeof(void *)*length, GFP_KERNEL);
+	if (channel->reserve_arr == NULL)
+		goto exit1;
+	channel->reserve_ptr = length;
+	channel->reserve_top = 0;
+
+	channel->orig_arr = kzalloc(sizeof(void *)*length, GFP_KERNEL);
+	if (channel->orig_arr == NULL)
+		goto exit1;
+
+	return channel;
+exit1:
+	__vxge_hw_channel_free(channel);
+
+exit0:
+	return NULL;
+}
+
+/*
+ * vxge_hw_blockpool_block_add - callback for vxge_os_dma_malloc_async
+ * Adds a block to block pool
+ */
+static void vxge_hw_blockpool_block_add(struct __vxge_hw_device *devh,
+					void *block_addr,
+					u32 length,
+					struct pci_dev *dma_h,
+					struct pci_dev *acc_handle)
+{
+	struct __vxge_hw_blockpool *blockpool;
+	struct __vxge_hw_blockpool_entry *entry = NULL;
+	dma_addr_t dma_addr;
+	enum vxge_hw_status status = VXGE_HW_OK;
+	u32 req_out;
+
+	blockpool = &devh->block_pool;
+
+	if (block_addr == NULL) {
+		blockpool->req_out--;
 		status = VXGE_HW_FAIL;
 		goto exit;
 	}
 
-	hldev = vp->vpath->hldev;
-	vp_id = vp->vpath->vp_id;
+	dma_addr = pci_map_single(devh->pdev, block_addr, length,
+				PCI_DMA_BIDIRECTIONAL);
 
-	config = &hldev->config.vp_config[vp_id].ring;
+	if (unlikely(pci_dma_mapping_error(devh->pdev, dma_addr))) {
+		vxge_os_dma_free(devh->pdev, block_addr, &acc_handle);
+		blockpool->req_out--;
+		status = VXGE_HW_FAIL;
+		goto exit;
+	}
 
-	ring_length = config->ring_blocks *
-			vxge_hw_ring_rxds_per_block_get(config->buffer_mode);
+	if (!list_empty(&blockpool->free_entry_list))
+		entry = (struct __vxge_hw_blockpool_entry *)
+			list_first_entry(&blockpool->free_entry_list,
+				struct __vxge_hw_blockpool_entry,
+				item);
 
-	ring = (struct __vxge_hw_ring *)__vxge_hw_channel_allocate(vp,
-						VXGE_HW_CHANNEL_TYPE_RING,
-						ring_length,
-						attr->per_rxd_space,
-						attr->userdata);
+	if (entry == NULL)
+		entry =	vmalloc(sizeof(struct __vxge_hw_blockpool_entry));
+	else
+		list_del(&entry->item);
 
-	if (ring == NULL) {
+	if (entry != NULL) {
+		entry->length = length;
+		entry->memblock = block_addr;
+		entry->dma_addr = dma_addr;
+		entry->acc_handle = acc_handle;
+		entry->dma_handle = dma_h;
+		list_add(&entry->item, &blockpool->free_block_list);
+		blockpool->pool_size++;
+		status = VXGE_HW_OK;
+	} else
 		status = VXGE_HW_ERR_OUT_OF_MEMORY;
-		goto exit;
-	}
 
-	vp->vpath->ringh = ring;
-	ring->vp_id = vp_id;
-	ring->vp_reg = vp->vpath->vp_reg;
-	ring->common_reg = hldev->common_reg;
-	ring->stats = &vp->vpath->sw_stats->ring_stats;
-	ring->config = config;
-	ring->callback = attr->callback;
-	ring->rxd_init = attr->rxd_init;
-	ring->rxd_term = attr->rxd_term;
-	ring->buffer_mode = config->buffer_mode;
-	ring->rxds_limit = config->rxds_limit;
+	blockpool->req_out--;
 
-	ring->rxd_size = vxge_hw_ring_rxd_size_get(config->buffer_mode);
-	ring->rxd_priv_size =
-		sizeof(struct __vxge_hw_ring_rxd_priv) + attr->per_rxd_space;
-	ring->per_rxd_space = attr->per_rxd_space;
+	req_out = blockpool->req_out;
+exit:
+	return;
+}
 
-	ring->rxd_priv_size =
-		((ring->rxd_priv_size + VXGE_CACHE_LINE_SIZE - 1) /
-		VXGE_CACHE_LINE_SIZE) * VXGE_CACHE_LINE_SIZE;
+static inline void
+vxge_os_dma_malloc_async(struct pci_dev *pdev, void *devh, unsigned long size)
+{
+	gfp_t flags;
+	void *vaddr;
 
-	/* how many RxDs can fit into one block. Depends on configured
-	 * buffer_mode. */
-	ring->rxds_per_block =
-		vxge_hw_ring_rxds_per_block_get(config->buffer_mode);
+	if (in_interrupt())
+		flags = GFP_ATOMIC | GFP_DMA;
+	else
+		flags = GFP_KERNEL | GFP_DMA;
 
-	/* calculate actual RxD block private size */
-	ring->rxdblock_priv_size = ring->rxd_priv_size * ring->rxds_per_block;
-	ring_mp_callback.item_func_alloc = __vxge_hw_ring_mempool_item_alloc;
-	ring->mempool = __vxge_hw_mempool_create(hldev,
-				VXGE_HW_BLOCK_SIZE,
-				VXGE_HW_BLOCK_SIZE,
-				ring->rxdblock_priv_size,
-				ring->config->ring_blocks,
-				ring->config->ring_blocks,
-				&ring_mp_callback,
-				ring);
+	vaddr = kmalloc((size), flags);
 
-	if (ring->mempool == NULL) {
-		__vxge_hw_ring_delete(vp);
-		return VXGE_HW_ERR_OUT_OF_MEMORY;
-	}
+	vxge_hw_blockpool_block_add(devh, vaddr, size, pdev, pdev);
+}
 
-	status = __vxge_hw_channel_initialize(&ring->channel);
-	if (status != VXGE_HW_OK) {
-		__vxge_hw_ring_delete(vp);
-		goto exit;
+/*
+ * __vxge_hw_blockpool_blocks_add - Request additional blocks
+ */
+static
+void __vxge_hw_blockpool_blocks_add(struct __vxge_hw_blockpool *blockpool)
+{
+	u32 nreq = 0, i;
+
+	if ((blockpool->pool_size  +  blockpool->req_out) <
+		VXGE_HW_MIN_DMA_BLOCK_POOL_SIZE) {
+		nreq = VXGE_HW_INCR_DMA_BLOCK_POOL_SIZE;
+		blockpool->req_out += nreq;
 	}
 
-	/* Note:
-	 * Specifying rxd_init callback means two things:
-	 * 1) rxds need to be initialized by driver at channel-open time;
-	 * 2) rxds need to be posted at channel-open time
-	 *    (that's what the initial_replenish() below does)
-	 * Currently we don't have a case when the 1) is done without the 2).
-	 */
-	if (ring->rxd_init) {
-		status = vxge_hw_ring_replenish(ring);
-		if (status != VXGE_HW_OK) {
-			__vxge_hw_ring_delete(vp);
+	for (i = 0; i < nreq; i++)
+		vxge_os_dma_malloc_async(
+			((struct __vxge_hw_device *)blockpool->hldev)->pdev,
+			blockpool->hldev, VXGE_HW_BLOCK_SIZE);
+}
+
+/*
+ * __vxge_hw_blockpool_malloc - Allocate a memory block from pool
+ * Allocates a block of memory of given size, either from block pool
+ * or by calling vxge_os_dma_malloc()
+ */
+static void *__vxge_hw_blockpool_malloc(struct __vxge_hw_device *devh, u32 size,
+					struct vxge_hw_mempool_dma *dma_object)
+{
+	struct __vxge_hw_blockpool_entry *entry = NULL;
+	struct __vxge_hw_blockpool  *blockpool;
+	void *memblock = NULL;
+	enum vxge_hw_status status = VXGE_HW_OK;
+
+	blockpool = &devh->block_pool;
+
+	if (size != blockpool->block_size) {
+
+		memblock = vxge_os_dma_malloc(devh->pdev, size,
+						&dma_object->handle,
+						&dma_object->acc_handle);
+
+		if (memblock == NULL) {
+			status = VXGE_HW_ERR_OUT_OF_MEMORY;
 			goto exit;
 		}
-	}
 
-	/* initial replenish will increment the counter in its post() routine,
-	 * we have to reset it */
-	ring->stats->common_stats.usage_cnt = 0;
+		dma_object->addr = pci_map_single(devh->pdev, memblock, size,
+					PCI_DMA_BIDIRECTIONAL);
+
+		if (unlikely(pci_dma_mapping_error(devh->pdev,
+				dma_object->addr))) {
+			vxge_os_dma_free(devh->pdev, memblock,
+				&dma_object->acc_handle);
+			status = VXGE_HW_ERR_OUT_OF_MEMORY;
+			goto exit;
+		}
+
+	} else {
+
+		if (!list_empty(&blockpool->free_block_list))
+			entry = (struct __vxge_hw_blockpool_entry *)
+				list_first_entry(&blockpool->free_block_list,
+					struct __vxge_hw_blockpool_entry,
+					item);
+
+		if (entry != NULL) {
+			list_del(&entry->item);
+			dma_object->addr = entry->dma_addr;
+			dma_object->handle = entry->dma_handle;
+			dma_object->acc_handle = entry->acc_handle;
+			memblock = entry->memblock;
+
+			list_add(&entry->item,
+				&blockpool->free_entry_list);
+			blockpool->pool_size--;
+		}
+
+		if (memblock != NULL)
+			__vxge_hw_blockpool_blocks_add(blockpool);
+	}
 exit:
-	return status;
+	return memblock;
 }
 
 /*
- * __vxge_hw_ring_abort - Returns the RxD
- * This function terminates the RxDs of ring
+ * __vxge_hw_blockpool_blocks_remove - Free additional blocks
  */
-static enum vxge_hw_status __vxge_hw_ring_abort(struct __vxge_hw_ring *ring)
+static void
+__vxge_hw_blockpool_blocks_remove(struct __vxge_hw_blockpool *blockpool)
 {
-	void *rxdh;
-	struct __vxge_hw_channel *channel;
-
-	channel = &ring->channel;
+	struct list_head *p, *n;
 
-	for (;;) {
-		vxge_hw_channel_dtr_try_complete(channel, &rxdh);
+	list_for_each_safe(p, n, &blockpool->free_block_list) {
 
-		if (rxdh == NULL)
+		if (blockpool->pool_size < blockpool->pool_max)
 			break;
 
-		vxge_hw_channel_dtr_complete(channel);
+		pci_unmap_single(
+			((struct __vxge_hw_device *)blockpool->hldev)->pdev,
+			((struct __vxge_hw_blockpool_entry *)p)->dma_addr,
+			((struct __vxge_hw_blockpool_entry *)p)->length,
+			PCI_DMA_BIDIRECTIONAL);
 
-		if (ring->rxd_term)
-			ring->rxd_term(rxdh, VXGE_HW_RXD_STATE_POSTED,
-				channel->userdata);
+		vxge_os_dma_free(
+			((struct __vxge_hw_device *)blockpool->hldev)->pdev,
+			((struct __vxge_hw_blockpool_entry *)p)->memblock,
+			&((struct __vxge_hw_blockpool_entry *)p)->acc_handle);
 
-		vxge_hw_channel_dtr_free(channel, rxdh);
-	}
+		list_del(&((struct __vxge_hw_blockpool_entry *)p)->item);
 
-	return VXGE_HW_OK;
+		list_add(p, &blockpool->free_entry_list);
+
+		blockpool->pool_size--;
+
+	}
 }
 
 /*
- * __vxge_hw_ring_reset - Resets the ring
- * This function resets the ring during vpath reset operation
+ * __vxge_hw_blockpool_free - Frees the memory allcoated with
+ *				__vxge_hw_blockpool_malloc
  */
-static enum vxge_hw_status __vxge_hw_ring_reset(struct __vxge_hw_ring *ring)
+static void __vxge_hw_blockpool_free(struct __vxge_hw_device *devh,
+				     void *memblock, u32 size,
+				     struct vxge_hw_mempool_dma *dma_object)
 {
+	struct __vxge_hw_blockpool_entry *entry = NULL;
+	struct __vxge_hw_blockpool  *blockpool;
 	enum vxge_hw_status status = VXGE_HW_OK;
-	struct __vxge_hw_channel *channel;
 
-	channel = &ring->channel;
+	blockpool = &devh->block_pool;
 
-	__vxge_hw_ring_abort(ring);
+	if (size != blockpool->block_size) {
+		pci_unmap_single(devh->pdev, dma_object->addr, size,
+			PCI_DMA_BIDIRECTIONAL);
+		vxge_os_dma_free(devh->pdev, memblock, &dma_object->acc_handle);
+	} else {
 
-	status = __vxge_hw_channel_reset(channel);
+		if (!list_empty(&blockpool->free_entry_list))
+			entry = (struct __vxge_hw_blockpool_entry *)
+				list_first_entry(&blockpool->free_entry_list,
+					struct __vxge_hw_blockpool_entry,
+					item);
 
-	if (status != VXGE_HW_OK)
-		goto exit;
+		if (entry == NULL)
+			entry =	vmalloc(sizeof(
+					struct __vxge_hw_blockpool_entry));
+		else
+			list_del(&entry->item);
 
-	if (ring->rxd_init) {
-		status = vxge_hw_ring_replenish(ring);
-		if (status != VXGE_HW_OK)
-			goto exit;
+		if (entry != NULL) {
+			entry->length = size;
+			entry->memblock = memblock;
+			entry->dma_addr = dma_object->addr;
+			entry->acc_handle = dma_object->acc_handle;
+			entry->dma_handle = dma_object->handle;
+			list_add(&entry->item,
+					&blockpool->free_block_list);
+			blockpool->pool_size++;
+			status = VXGE_HW_OK;
+		} else
+			status = VXGE_HW_ERR_OUT_OF_MEMORY;
+
+		if (status == VXGE_HW_OK)
+			__vxge_hw_blockpool_blocks_remove(blockpool);
 	}
-exit:
-	return status;
 }
 
 /*
- * __vxge_hw_ring_delete - Removes the ring
- * This function freeup the memory pool and removes the ring
+ * vxge_hw_mempool_destroy
  */
-static enum vxge_hw_status __vxge_hw_ring_delete(struct __vxge_hw_vpath_handle *vp)
+static void __vxge_hw_mempool_destroy(struct vxge_hw_mempool *mempool)
 {
-	struct __vxge_hw_ring *ring = vp->vpath->ringh;
+	u32 i, j;
+	struct __vxge_hw_device *devh = mempool->devh;
 
-	__vxge_hw_ring_abort(ring);
+	for (i = 0; i < mempool->memblocks_allocated; i++) {
+		struct vxge_hw_mempool_dma *dma_object;
 
-	if (ring->mempool)
-		__vxge_hw_mempool_destroy(ring->mempool);
+		vxge_assert(mempool->memblocks_arr[i]);
+		vxge_assert(mempool->memblocks_dma_arr + i);
 
-	vp->vpath->ringh = NULL;
-	__vxge_hw_channel_free(&ring->channel);
+		dma_object = mempool->memblocks_dma_arr + i;
 
-	return VXGE_HW_OK;
+		for (j = 0; j < mempool->items_per_memblock; j++) {
+			u32 index = i * mempool->items_per_memblock + j;
+
+			/* to skip last partially filled(if any) memblock */
+			if (index >= mempool->items_current)
+				break;
+		}
+
+		vfree(mempool->memblocks_priv_arr[i]);
+
+		__vxge_hw_blockpool_free(devh, mempool->memblocks_arr[i],
+				mempool->memblock_size, dma_object);
+	}
+
+	vfree(mempool->items_arr);
+	vfree(mempool->memblocks_dma_arr);
+	vfree(mempool->memblocks_priv_arr);
+	vfree(mempool->memblocks_arr);
+	vfree(mempool);
 }
 
 /*
@@ -1627,15 +2586,12 @@ __vxge_hw_mempool_grow(struct vxge_hw_me
 		 * allocate new memblock and its private part at once.
 		 * This helps to minimize memory usage a lot. */
 		mempool->memblocks_priv_arr[i] =
-				vmalloc(mempool->items_priv_size * n_items);
+				vzalloc(mempool->items_priv_size * n_items);
 		if (mempool->memblocks_priv_arr[i] == NULL) {
 			status = VXGE_HW_ERR_OUT_OF_MEMORY;
 			goto exit;
 		}
 
-		memset(mempool->memblocks_priv_arr[i], 0,
-			     mempool->items_priv_size * n_items);
-
 		/* allocate DMA-capable memblock */
 		mempool->memblocks_arr[i] =
 			__vxge_hw_blockpool_malloc(mempool->devh,
@@ -1686,16 +2642,15 @@ exit:
  * with size enough to hold %items_initial number of items. Memory is
  * DMA-able but client must map/unmap before interoperating with the device.
  */
-static struct vxge_hw_mempool*
-__vxge_hw_mempool_create(
-	struct __vxge_hw_device *devh,
-	u32 memblock_size,
-	u32 item_size,
-	u32 items_priv_size,
-	u32 items_initial,
-	u32 items_max,
-	struct vxge_hw_mempool_cbs *mp_callback,
-	void *userdata)
+static struct vxge_hw_mempool *
+__vxge_hw_mempool_create(struct __vxge_hw_device *devh,
+			 u32 memblock_size,
+			 u32 item_size,
+			 u32 items_priv_size,
+			 u32 items_initial,
+			 u32 items_max,
+			 struct vxge_hw_mempool_cbs *mp_callback,
+			 void *userdata)
 {
 	enum vxge_hw_status status = VXGE_HW_OK;
 	u32 memblocks_to_allocate;
@@ -1707,13 +2662,11 @@ __vxge_hw_mempool_create(
 		goto exit;
 	}
 
-	mempool = (struct vxge_hw_mempool *)
-			vmalloc(sizeof(struct vxge_hw_mempool));
+	mempool = vzalloc(sizeof(struct vxge_hw_mempool));
 	if (mempool == NULL) {
 		status = VXGE_HW_ERR_OUT_OF_MEMORY;
 		goto exit;
 	}
-	memset(mempool, 0, sizeof(struct vxge_hw_mempool));
 
 	mempool->devh			= devh;
 	mempool->memblock_size		= memblock_size;
@@ -1733,53 +2686,43 @@ __vxge_hw_mempool_create(
 
 	/* allocate array of memblocks */
 	mempool->memblocks_arr =
-		(void **) vmalloc(sizeof(void *) * mempool->memblocks_max);
+		vzalloc(sizeof(void *) * mempool->memblocks_max);
 	if (mempool->memblocks_arr == NULL) {
 		__vxge_hw_mempool_destroy(mempool);
 		status = VXGE_HW_ERR_OUT_OF_MEMORY;
 		mempool = NULL;
 		goto exit;
 	}
-	memset(mempool->memblocks_arr, 0,
-		sizeof(void *) * mempool->memblocks_max);
 
 	/* allocate array of private parts of items per memblocks */
 	mempool->memblocks_priv_arr =
-		(void **) vmalloc(sizeof(void *) * mempool->memblocks_max);
+		vzalloc(sizeof(void *) * mempool->memblocks_max);
 	if (mempool->memblocks_priv_arr == NULL) {
 		__vxge_hw_mempool_destroy(mempool);
 		status = VXGE_HW_ERR_OUT_OF_MEMORY;
 		mempool = NULL;
 		goto exit;
 	}
-	memset(mempool->memblocks_priv_arr, 0,
-		    sizeof(void *) * mempool->memblocks_max);
 
 	/* allocate array of memblocks DMA objects */
-	mempool->memblocks_dma_arr = (struct vxge_hw_mempool_dma *)
-		vmalloc(sizeof(struct vxge_hw_mempool_dma) *
+	mempool->memblocks_dma_arr =
+		vzalloc(sizeof(struct vxge_hw_mempool_dma) *
 			mempool->memblocks_max);
-
 	if (mempool->memblocks_dma_arr == NULL) {
 		__vxge_hw_mempool_destroy(mempool);
 		status = VXGE_HW_ERR_OUT_OF_MEMORY;
 		mempool = NULL;
 		goto exit;
 	}
-	memset(mempool->memblocks_dma_arr, 0,
-			sizeof(struct vxge_hw_mempool_dma) *
-			mempool->memblocks_max);
 
 	/* allocate hash array of items */
-	mempool->items_arr =
-		(void **) vmalloc(sizeof(void *) * mempool->items_max);
+	mempool->items_arr = vzalloc(sizeof(void *) * mempool->items_max);
 	if (mempool->items_arr == NULL) {
 		__vxge_hw_mempool_destroy(mempool);
 		status = VXGE_HW_ERR_OUT_OF_MEMORY;
 		mempool = NULL;
 		goto exit;
 	}
-	memset(mempool->items_arr, 0, sizeof(void *) * mempool->items_max);
 
 	/* calculate initial number of memblocks */
 	memblocks_to_allocate = (mempool->items_initial +
@@ -1801,122 +2744,188 @@ exit:
 }
 
 /*
- * vxge_hw_mempool_destroy
+ * __vxge_hw_ring_abort - Returns the RxD
+ * This function terminates the RxDs of ring
  */
-static void __vxge_hw_mempool_destroy(struct vxge_hw_mempool *mempool)
+static enum vxge_hw_status __vxge_hw_ring_abort(struct __vxge_hw_ring *ring)
 {
-	u32 i, j;
-	struct __vxge_hw_device *devh = mempool->devh;
-
-	for (i = 0; i < mempool->memblocks_allocated; i++) {
-		struct vxge_hw_mempool_dma *dma_object;
+	void *rxdh;
+	struct __vxge_hw_channel *channel;
 
-		vxge_assert(mempool->memblocks_arr[i]);
-		vxge_assert(mempool->memblocks_dma_arr + i);
+	channel = &ring->channel;
 
-		dma_object = mempool->memblocks_dma_arr + i;
+	for (;;) {
+		vxge_hw_channel_dtr_try_complete(channel, &rxdh);
 
-		for (j = 0; j < mempool->items_per_memblock; j++) {
-			u32 index = i * mempool->items_per_memblock + j;
+		if (rxdh == NULL)
+			break;
 
-			/* to skip last partially filled(if any) memblock */
-			if (index >= mempool->items_current)
-				break;
-		}
+		vxge_hw_channel_dtr_complete(channel);
 
-		vfree(mempool->memblocks_priv_arr[i]);
+		if (ring->rxd_term)
+			ring->rxd_term(rxdh, VXGE_HW_RXD_STATE_POSTED,
+				channel->userdata);
 
-		__vxge_hw_blockpool_free(devh, mempool->memblocks_arr[i],
-				mempool->memblock_size, dma_object);
+		vxge_hw_channel_dtr_free(channel, rxdh);
 	}
 
-	vfree(mempool->items_arr);
+	return VXGE_HW_OK;
+}
 
-	vfree(mempool->memblocks_dma_arr);
+/*
+ * __vxge_hw_ring_reset - Resets the ring
+ * This function resets the ring during vpath reset operation
+ */
+static enum vxge_hw_status __vxge_hw_ring_reset(struct __vxge_hw_ring *ring)
+{
+	enum vxge_hw_status status = VXGE_HW_OK;
+	struct __vxge_hw_channel *channel;
 
-	vfree(mempool->memblocks_priv_arr);
+	channel = &ring->channel;
 
-	vfree(mempool->memblocks_arr);
+	__vxge_hw_ring_abort(ring);
 
-	vfree(mempool);
+	status = __vxge_hw_channel_reset(channel);
+
+	if (status != VXGE_HW_OK)
+		goto exit;
+
+	if (ring->rxd_init) {
+		status = vxge_hw_ring_replenish(ring);
+		if (status != VXGE_HW_OK)
+			goto exit;
+	}
+exit:
+	return status;
 }
 
 /*
- * __vxge_hw_device_fifo_config_check - Check fifo configuration.
- * Check the fifo configuration
+ * __vxge_hw_ring_delete - Removes the ring
+ * This function freeup the memory pool and removes the ring
  */
-enum vxge_hw_status
-__vxge_hw_device_fifo_config_check(struct vxge_hw_fifo_config *fifo_config)
+static enum vxge_hw_status
+__vxge_hw_ring_delete(struct __vxge_hw_vpath_handle *vp)
 {
-	if ((fifo_config->fifo_blocks < VXGE_HW_MIN_FIFO_BLOCKS) ||
-	     (fifo_config->fifo_blocks > VXGE_HW_MAX_FIFO_BLOCKS))
-		return VXGE_HW_BADCFG_FIFO_BLOCKS;
+	struct __vxge_hw_ring *ring = vp->vpath->ringh;
+
+	__vxge_hw_ring_abort(ring);
+
+	if (ring->mempool)
+		__vxge_hw_mempool_destroy(ring->mempool);
+
+	vp->vpath->ringh = NULL;
+	__vxge_hw_channel_free(&ring->channel);
 
 	return VXGE_HW_OK;
 }
 
 /*
- * __vxge_hw_device_vpath_config_check - Check vpath configuration.
- * Check the vpath configuration
+ * __vxge_hw_ring_create - Create a Ring
+ * This function creates Ring and initializes it.
  */
 static enum vxge_hw_status
-__vxge_hw_device_vpath_config_check(struct vxge_hw_vp_config *vp_config)
+__vxge_hw_ring_create(struct __vxge_hw_vpath_handle *vp,
+		      struct vxge_hw_ring_attr *attr)
 {
-	enum vxge_hw_status status;
+	enum vxge_hw_status status = VXGE_HW_OK;
+	struct __vxge_hw_ring *ring;
+	u32 ring_length;
+	struct vxge_hw_ring_config *config;
+	struct __vxge_hw_device *hldev;
+	u32 vp_id;
+	struct vxge_hw_mempool_cbs ring_mp_callback;
 
-	if ((vp_config->min_bandwidth < VXGE_HW_VPATH_BANDWIDTH_MIN) ||
-		(vp_config->min_bandwidth >
-					VXGE_HW_VPATH_BANDWIDTH_MAX))
-		return VXGE_HW_BADCFG_VPATH_MIN_BANDWIDTH;
+	if ((vp == NULL) || (attr == NULL)) {
+		status = VXGE_HW_FAIL;
+		goto exit;
+	}
 
-	status = __vxge_hw_device_fifo_config_check(&vp_config->fifo);
-	if (status != VXGE_HW_OK)
-		return status;
+	hldev = vp->vpath->hldev;
+	vp_id = vp->vpath->vp_id;
 
-	if ((vp_config->mtu != VXGE_HW_VPATH_USE_FLASH_DEFAULT_INITIAL_MTU) &&
-		((vp_config->mtu < VXGE_HW_VPATH_MIN_INITIAL_MTU) ||
-		(vp_config->mtu > VXGE_HW_VPATH_MAX_INITIAL_MTU)))
-		return VXGE_HW_BADCFG_VPATH_MTU;
+	config = &hldev->config.vp_config[vp_id].ring;
 
-	if ((vp_config->rpa_strip_vlan_tag !=
-		VXGE_HW_VPATH_RPA_STRIP_VLAN_TAG_USE_FLASH_DEFAULT) &&
-		(vp_config->rpa_strip_vlan_tag !=
-		VXGE_HW_VPATH_RPA_STRIP_VLAN_TAG_ENABLE) &&
-		(vp_config->rpa_strip_vlan_tag !=
-		VXGE_HW_VPATH_RPA_STRIP_VLAN_TAG_DISABLE))
-		return VXGE_HW_BADCFG_VPATH_RPA_STRIP_VLAN_TAG;
+	ring_length = config->ring_blocks *
+			vxge_hw_ring_rxds_per_block_get(config->buffer_mode);
 
-	return VXGE_HW_OK;
-}
+	ring = (struct __vxge_hw_ring *)__vxge_hw_channel_allocate(vp,
+						VXGE_HW_CHANNEL_TYPE_RING,
+						ring_length,
+						attr->per_rxd_space,
+						attr->userdata);
+	if (ring == NULL) {
+		status = VXGE_HW_ERR_OUT_OF_MEMORY;
+		goto exit;
+	}
 
-/*
- * __vxge_hw_device_config_check - Check device configuration.
- * Check the device configuration
- */
-enum vxge_hw_status
-__vxge_hw_device_config_check(struct vxge_hw_device_config *new_config)
-{
-	u32 i;
-	enum vxge_hw_status status;
+	vp->vpath->ringh = ring;
+	ring->vp_id = vp_id;
+	ring->vp_reg = vp->vpath->vp_reg;
+	ring->common_reg = hldev->common_reg;
+	ring->stats = &vp->vpath->sw_stats->ring_stats;
+	ring->config = config;
+	ring->callback = attr->callback;
+	ring->rxd_init = attr->rxd_init;
+	ring->rxd_term = attr->rxd_term;
+	ring->buffer_mode = config->buffer_mode;
+	ring->rxds_limit = config->rxds_limit;
 
-	if ((new_config->intr_mode != VXGE_HW_INTR_MODE_IRQLINE) &&
-	   (new_config->intr_mode != VXGE_HW_INTR_MODE_MSIX) &&
-	   (new_config->intr_mode != VXGE_HW_INTR_MODE_MSIX_ONE_SHOT) &&
-	   (new_config->intr_mode != VXGE_HW_INTR_MODE_DEF))
-		return VXGE_HW_BADCFG_INTR_MODE;
+	ring->rxd_size = vxge_hw_ring_rxd_size_get(config->buffer_mode);
+	ring->rxd_priv_size =
+		sizeof(struct __vxge_hw_ring_rxd_priv) + attr->per_rxd_space;
+	ring->per_rxd_space = attr->per_rxd_space;
 
-	if ((new_config->rts_mac_en != VXGE_HW_RTS_MAC_DISABLE) &&
-	   (new_config->rts_mac_en != VXGE_HW_RTS_MAC_ENABLE))
-		return VXGE_HW_BADCFG_RTS_MAC_EN;
+	ring->rxd_priv_size =
+		((ring->rxd_priv_size + VXGE_CACHE_LINE_SIZE - 1) /
+		VXGE_CACHE_LINE_SIZE) * VXGE_CACHE_LINE_SIZE;
 
-	for (i = 0; i < VXGE_HW_MAX_VIRTUAL_PATHS; i++) {
-		status = __vxge_hw_device_vpath_config_check(
-				&new_config->vp_config[i]);
-		if (status != VXGE_HW_OK)
-			return status;
+	/* how many RxDs can fit into one block. Depends on configured
+	 * buffer_mode. */
+	ring->rxds_per_block =
+		vxge_hw_ring_rxds_per_block_get(config->buffer_mode);
+
+	/* calculate actual RxD block private size */
+	ring->rxdblock_priv_size = ring->rxd_priv_size * ring->rxds_per_block;
+	ring_mp_callback.item_func_alloc = __vxge_hw_ring_mempool_item_alloc;
+	ring->mempool = __vxge_hw_mempool_create(hldev,
+				VXGE_HW_BLOCK_SIZE,
+				VXGE_HW_BLOCK_SIZE,
+				ring->rxdblock_priv_size,
+				ring->config->ring_blocks,
+				ring->config->ring_blocks,
+				&ring_mp_callback,
+				ring);
+	if (ring->mempool == NULL) {
+		__vxge_hw_ring_delete(vp);
+		return VXGE_HW_ERR_OUT_OF_MEMORY;
 	}
 
-	return VXGE_HW_OK;
+	status = __vxge_hw_channel_initialize(&ring->channel);
+	if (status != VXGE_HW_OK) {
+		__vxge_hw_ring_delete(vp);
+		goto exit;
+	}
+
+	/* Note:
+	 * Specifying rxd_init callback means two things:
+	 * 1) rxds need to be initialized by driver at channel-open time;
+	 * 2) rxds need to be posted at channel-open time
+	 *    (that's what the initial_replenish() below does)
+	 * Currently we don't have a case when the 1) is done without the 2).
+	 */
+	if (ring->rxd_init) {
+		status = vxge_hw_ring_replenish(ring);
+		if (status != VXGE_HW_OK) {
+			__vxge_hw_ring_delete(vp);
+			goto exit;
+		}
+	}
+
+	/* initial replenish will increment the counter in its post() routine,
+	 * we have to reset it */
+	ring->stats->common_stats.usage_cnt = 0;
+exit:
+	return status;
 }
 
 /*
@@ -1938,7 +2947,6 @@ vxge_hw_device_config_default_get(struct
 	device_config->rts_mac_en =  VXGE_HW_RTS_MAC_DEFAULT;
 
 	for (i = 0; i < VXGE_HW_MAX_VIRTUAL_PATHS; i++) {
-
 		device_config->vp_config[i].vp_id = i;
 
 		device_config->vp_config[i].min_bandwidth =
@@ -2078,61 +3086,6 @@ vxge_hw_device_config_default_get(struct
 }
 
 /*
- * _hw_legacy_swapper_set - Set the swapper bits for the legacy secion.
- * Set the swapper bits appropriately for the lagacy section.
- */
-static enum vxge_hw_status
-__vxge_hw_legacy_swapper_set(struct vxge_hw_legacy_reg __iomem *legacy_reg)
-{
-	u64 val64;
-	enum vxge_hw_status status = VXGE_HW_OK;
-
-	val64 = readq(&legacy_reg->toc_swapper_fb);
-
-	wmb();
-
-	switch (val64) {
-
-	case VXGE_HW_SWAPPER_INITIAL_VALUE:
-		return status;
-
-	case VXGE_HW_SWAPPER_BYTE_SWAPPED_BIT_FLIPPED:
-		writeq(VXGE_HW_SWAPPER_READ_BYTE_SWAP_ENABLE,
-			&legacy_reg->pifm_rd_swap_en);
-		writeq(VXGE_HW_SWAPPER_READ_BIT_FLAP_ENABLE,
-			&legacy_reg->pifm_rd_flip_en);
-		writeq(VXGE_HW_SWAPPER_WRITE_BYTE_SWAP_ENABLE,
-			&legacy_reg->pifm_wr_swap_en);
-		writeq(VXGE_HW_SWAPPER_WRITE_BIT_FLAP_ENABLE,
-			&legacy_reg->pifm_wr_flip_en);
-		break;
-
-	case VXGE_HW_SWAPPER_BYTE_SWAPPED:
-		writeq(VXGE_HW_SWAPPER_READ_BYTE_SWAP_ENABLE,
-			&legacy_reg->pifm_rd_swap_en);
-		writeq(VXGE_HW_SWAPPER_WRITE_BYTE_SWAP_ENABLE,
-			&legacy_reg->pifm_wr_swap_en);
-		break;
-
-	case VXGE_HW_SWAPPER_BIT_FLIPPED:
-		writeq(VXGE_HW_SWAPPER_READ_BIT_FLAP_ENABLE,
-			&legacy_reg->pifm_rd_flip_en);
-		writeq(VXGE_HW_SWAPPER_WRITE_BIT_FLAP_ENABLE,
-			&legacy_reg->pifm_wr_flip_en);
-		break;
-	}
-
-	wmb();
-
-	val64 = readq(&legacy_reg->toc_swapper_fb);
-
-	if (val64 != VXGE_HW_SWAPPER_INITIAL_VALUE)
-		status = VXGE_HW_ERR_SWAPPER_CTRL;
-
-	return status;
-}
-
-/*
  * __vxge_hw_vpath_swapper_set - Set the swapper bits for the vpath.
  * Set the swapper bits appropriately for the vpath.
  */
@@ -2156,9 +3109,8 @@ __vxge_hw_vpath_swapper_set(struct vxge_
  * Set the swapper bits appropriately for the vpath.
  */
 static enum vxge_hw_status
-__vxge_hw_kdfc_swapper_set(
-	struct vxge_hw_legacy_reg __iomem *legacy_reg,
-	struct vxge_hw_vpath_reg __iomem *vpath_reg)
+__vxge_hw_kdfc_swapper_set(struct vxge_hw_legacy_reg __iomem *legacy_reg,
+			   struct vxge_hw_vpath_reg __iomem *vpath_reg)
 {
 	u64 val64;
 
@@ -2408,6 +3360,69 @@ exit:
 }
 
 /*
+ * __vxge_hw_fifo_abort - Returns the TxD
+ * This function terminates the TxDs of fifo
+ */
+static enum vxge_hw_status __vxge_hw_fifo_abort(struct __vxge_hw_fifo *fifo)
+{
+	void *txdlh;
+
+	for (;;) {
+		vxge_hw_channel_dtr_try_complete(&fifo->channel, &txdlh);
+
+		if (txdlh == NULL)
+			break;
+
+		vxge_hw_channel_dtr_complete(&fifo->channel);
+
+		if (fifo->txdl_term) {
+			fifo->txdl_term(txdlh,
+			VXGE_HW_TXDL_STATE_POSTED,
+			fifo->channel.userdata);
+		}
+
+		vxge_hw_channel_dtr_free(&fifo->channel, txdlh);
+	}
+
+	return VXGE_HW_OK;
+}
+
+/*
+ * __vxge_hw_fifo_reset - Resets the fifo
+ * This function resets the fifo during vpath reset operation
+ */
+static enum vxge_hw_status __vxge_hw_fifo_reset(struct __vxge_hw_fifo *fifo)
+{
+	enum vxge_hw_status status = VXGE_HW_OK;
+
+	__vxge_hw_fifo_abort(fifo);
+	status = __vxge_hw_channel_reset(&fifo->channel);
+
+	return status;
+}
+
+/*
+ * __vxge_hw_fifo_delete - Removes the FIFO
+ * This function freeup the memory pool and removes the FIFO
+ */
+static enum vxge_hw_status
+__vxge_hw_fifo_delete(struct __vxge_hw_vpath_handle *vp)
+{
+	struct __vxge_hw_fifo *fifo = vp->vpath->fifoh;
+
+	__vxge_hw_fifo_abort(fifo);
+
+	if (fifo->mempool)
+		__vxge_hw_mempool_destroy(fifo->mempool);
+
+	vp->vpath->fifoh = NULL;
+
+	__vxge_hw_channel_free(&fifo->channel);
+
+	return VXGE_HW_OK;
+}
+
+/*
  * __vxge_hw_fifo_mempool_item_alloc - Allocate List blocks for TxD
  * list callback
  * This function is callback passed to __vxge_hw_mempool_create to create memory
@@ -2453,7 +3468,7 @@ __vxge_hw_fifo_mempool_item_alloc(
  * __vxge_hw_fifo_create - Create a FIFO
  * This function creates FIFO and initializes it.
  */
-enum vxge_hw_status
+static enum vxge_hw_status
 __vxge_hw_fifo_create(struct __vxge_hw_vpath_handle *vp,
 		      struct vxge_hw_fifo_attr *attr)
 {
@@ -2572,68 +3587,6 @@ exit:
 }
 
 /*
- * __vxge_hw_fifo_abort - Returns the TxD
- * This function terminates the TxDs of fifo
- */
-static enum vxge_hw_status __vxge_hw_fifo_abort(struct __vxge_hw_fifo *fifo)
-{
-	void *txdlh;
-
-	for (;;) {
-		vxge_hw_channel_dtr_try_complete(&fifo->channel, &txdlh);
-
-		if (txdlh == NULL)
-			break;
-
-		vxge_hw_channel_dtr_complete(&fifo->channel);
-
-		if (fifo->txdl_term) {
-			fifo->txdl_term(txdlh,
-			VXGE_HW_TXDL_STATE_POSTED,
-			fifo->channel.userdata);
-		}
-
-		vxge_hw_channel_dtr_free(&fifo->channel, txdlh);
-	}
-
-	return VXGE_HW_OK;
-}
-
-/*
- * __vxge_hw_fifo_reset - Resets the fifo
- * This function resets the fifo during vpath reset operation
- */
-static enum vxge_hw_status __vxge_hw_fifo_reset(struct __vxge_hw_fifo *fifo)
-{
-	enum vxge_hw_status status = VXGE_HW_OK;
-
-	__vxge_hw_fifo_abort(fifo);
-	status = __vxge_hw_channel_reset(&fifo->channel);
-
-	return status;
-}
-
-/*
- * __vxge_hw_fifo_delete - Removes the FIFO
- * This function freeup the memory pool and removes the FIFO
- */
-enum vxge_hw_status __vxge_hw_fifo_delete(struct __vxge_hw_vpath_handle *vp)
-{
-	struct __vxge_hw_fifo *fifo = vp->vpath->fifoh;
-
-	__vxge_hw_fifo_abort(fifo);
-
-	if (fifo->mempool)
-		__vxge_hw_mempool_destroy(fifo->mempool);
-
-	vp->vpath->fifoh = NULL;
-
-	__vxge_hw_channel_free(&fifo->channel);
-
-	return VXGE_HW_OK;
-}
-
-/*
  * __vxge_hw_vpath_pci_read - Read the content of given address
  *                          in pci config space.
  * Read from the vpath pci config space.
@@ -2675,297 +3628,6 @@ exit:
 	return status;
 }
 
-/*
- * __vxge_hw_vpath_func_id_get - Get the function id of the vpath.
- * Returns the function number of the vpath.
- */
-static u32
-__vxge_hw_vpath_func_id_get(u32 vp_id,
-	struct vxge_hw_vpmgmt_reg __iomem *vpmgmt_reg)
-{
-	u64 val64;
-
-	val64 = readq(&vpmgmt_reg->vpath_to_func_map_cfg1);
-
-	return
-	 (u32)VXGE_HW_VPATH_TO_FUNC_MAP_CFG1_GET_VPATH_TO_FUNC_MAP_CFG1(val64);
-}
-
-/*
- * __vxge_hw_read_rts_ds - Program RTS steering critieria
- */
-static inline void
-__vxge_hw_read_rts_ds(struct vxge_hw_vpath_reg __iomem *vpath_reg,
-		      u64 dta_struct_sel)
-{
-	writeq(0, &vpath_reg->rts_access_steer_ctrl);
-	wmb();
-	writeq(dta_struct_sel, &vpath_reg->rts_access_steer_data0);
-	writeq(0, &vpath_reg->rts_access_steer_data1);
-	wmb();
-}
-
-
-/*
- * __vxge_hw_vpath_card_info_get - Get the serial numbers,
- * part number and product description.
- */
-static enum vxge_hw_status
-__vxge_hw_vpath_card_info_get(
-	u32 vp_id,
-	struct vxge_hw_vpath_reg __iomem *vpath_reg,
-	struct vxge_hw_device_hw_info *hw_info)
-{
-	u32 i, j;
-	u64 val64;
-	u64 data1 = 0ULL;
-	u64 data2 = 0ULL;
-	enum vxge_hw_status status = VXGE_HW_OK;
-	u8 *serial_number = hw_info->serial_number;
-	u8 *part_number = hw_info->part_number;
-	u8 *product_desc = hw_info->product_desc;
-
-	__vxge_hw_read_rts_ds(vpath_reg,
-		VXGE_HW_RTS_ACCESS_STEER_DATA0_MEMO_ITEM_SERIAL_NUMBER);
-
-	val64 = VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION(
-			VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION_READ_MEMO_ENTRY) |
-		VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL(
-			VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_FW_MEMO) |
-		VXGE_HW_RTS_ACCESS_STEER_CTRL_STROBE |
-		VXGE_HW_RTS_ACCESS_STEER_CTRL_OFFSET(0);
-
-	status = __vxge_hw_pio_mem_write64(val64,
-				&vpath_reg->rts_access_steer_ctrl,
-				VXGE_HW_RTS_ACCESS_STEER_CTRL_STROBE,
-				VXGE_HW_DEF_DEVICE_POLL_MILLIS);
-
-	if (status != VXGE_HW_OK)
-		return status;
-
-	val64 = readq(&vpath_reg->rts_access_steer_ctrl);
-
-	if (val64 & VXGE_HW_RTS_ACCESS_STEER_CTRL_RMACJ_STATUS) {
-		data1 = readq(&vpath_reg->rts_access_steer_data0);
-		((u64 *)serial_number)[0] = be64_to_cpu(data1);
-
-		data2 = readq(&vpath_reg->rts_access_steer_data1);
-		((u64 *)serial_number)[1] = be64_to_cpu(data2);
-		status = VXGE_HW_OK;
-	} else
-		*serial_number = 0;
-
-	__vxge_hw_read_rts_ds(vpath_reg,
-			VXGE_HW_RTS_ACCESS_STEER_DATA0_MEMO_ITEM_PART_NUMBER);
-
-	val64 = VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION(
-			VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION_READ_MEMO_ENTRY) |
-		VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL(
-			VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_FW_MEMO) |
-		VXGE_HW_RTS_ACCESS_STEER_CTRL_STROBE |
-		VXGE_HW_RTS_ACCESS_STEER_CTRL_OFFSET(0);
-
-	status = __vxge_hw_pio_mem_write64(val64,
-				&vpath_reg->rts_access_steer_ctrl,
-				VXGE_HW_RTS_ACCESS_STEER_CTRL_STROBE,
-				VXGE_HW_DEF_DEVICE_POLL_MILLIS);
-
-	if (status != VXGE_HW_OK)
-		return status;
-
-	val64 = readq(&vpath_reg->rts_access_steer_ctrl);
-
-	if (val64 & VXGE_HW_RTS_ACCESS_STEER_CTRL_RMACJ_STATUS) {
-
-		data1 = readq(&vpath_reg->rts_access_steer_data0);
-		((u64 *)part_number)[0] = be64_to_cpu(data1);
-
-		data2 = readq(&vpath_reg->rts_access_steer_data1);
-		((u64 *)part_number)[1] = be64_to_cpu(data2);
-
-		status = VXGE_HW_OK;
-
-	} else
-		*part_number = 0;
-
-	j = 0;
-
-	for (i = VXGE_HW_RTS_ACCESS_STEER_DATA0_MEMO_ITEM_DESC_0;
-	     i <= VXGE_HW_RTS_ACCESS_STEER_DATA0_MEMO_ITEM_DESC_3; i++) {
-
-		__vxge_hw_read_rts_ds(vpath_reg, i);
-
-		val64 = VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION(
-			VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION_READ_MEMO_ENTRY) |
-			VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL(
-			VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_FW_MEMO) |
-			VXGE_HW_RTS_ACCESS_STEER_CTRL_STROBE |
-			VXGE_HW_RTS_ACCESS_STEER_CTRL_OFFSET(0);
-
-		status = __vxge_hw_pio_mem_write64(val64,
-				&vpath_reg->rts_access_steer_ctrl,
-				VXGE_HW_RTS_ACCESS_STEER_CTRL_STROBE,
-				VXGE_HW_DEF_DEVICE_POLL_MILLIS);
-
-		if (status != VXGE_HW_OK)
-			return status;
-
-		val64 = readq(&vpath_reg->rts_access_steer_ctrl);
-
-		if (val64 & VXGE_HW_RTS_ACCESS_STEER_CTRL_RMACJ_STATUS) {
-
-			data1 = readq(&vpath_reg->rts_access_steer_data0);
-			((u64 *)product_desc)[j++] = be64_to_cpu(data1);
-
-			data2 = readq(&vpath_reg->rts_access_steer_data1);
-			((u64 *)product_desc)[j++] = be64_to_cpu(data2);
-
-			status = VXGE_HW_OK;
-		} else
-			*product_desc = 0;
-	}
-
-	return status;
-}
-
-/*
- * __vxge_hw_vpath_fw_ver_get - Get the fw version
- * Returns FW Version
- */
-static enum vxge_hw_status
-__vxge_hw_vpath_fw_ver_get(
-	u32 vp_id,
-	struct vxge_hw_vpath_reg __iomem *vpath_reg,
-	struct vxge_hw_device_hw_info *hw_info)
-{
-	u64 val64;
-	u64 data1 = 0ULL;
-	u64 data2 = 0ULL;
-	struct vxge_hw_device_version *fw_version = &hw_info->fw_version;
-	struct vxge_hw_device_date *fw_date = &hw_info->fw_date;
-	struct vxge_hw_device_version *flash_version = &hw_info->flash_version;
-	struct vxge_hw_device_date *flash_date = &hw_info->flash_date;
-	enum vxge_hw_status status = VXGE_HW_OK;
-
-	val64 = VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION(
-		VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION_READ_ENTRY) |
-		VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL(
-		VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_FW_MEMO) |
-		VXGE_HW_RTS_ACCESS_STEER_CTRL_STROBE |
-		VXGE_HW_RTS_ACCESS_STEER_CTRL_OFFSET(0);
-
-	status = __vxge_hw_pio_mem_write64(val64,
-				&vpath_reg->rts_access_steer_ctrl,
-				VXGE_HW_RTS_ACCESS_STEER_CTRL_STROBE,
-				VXGE_HW_DEF_DEVICE_POLL_MILLIS);
-
-	if (status != VXGE_HW_OK)
-		goto exit;
-
-	val64 = readq(&vpath_reg->rts_access_steer_ctrl);
-
-	if (val64 & VXGE_HW_RTS_ACCESS_STEER_CTRL_RMACJ_STATUS) {
-
-		data1 = readq(&vpath_reg->rts_access_steer_data0);
-		data2 = readq(&vpath_reg->rts_access_steer_data1);
-
-		fw_date->day =
-			(u32)VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_FW_VER_DAY(
-						data1);
-		fw_date->month =
-			(u32)VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_FW_VER_MONTH(
-						data1);
-		fw_date->year =
-			(u32)VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_FW_VER_YEAR(
-						data1);
-
-		snprintf(fw_date->date, VXGE_HW_FW_STRLEN, "%2.2d/%2.2d/%4.4d",
-			fw_date->month, fw_date->day, fw_date->year);
-
-		fw_version->major =
-		    (u32)VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_FW_VER_MAJOR(data1);
-		fw_version->minor =
-		    (u32)VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_FW_VER_MINOR(data1);
-		fw_version->build =
-		    (u32)VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_FW_VER_BUILD(data1);
-
-		snprintf(fw_version->version, VXGE_HW_FW_STRLEN, "%d.%d.%d",
-		    fw_version->major, fw_version->minor, fw_version->build);
-
-		flash_date->day =
-		  (u32)VXGE_HW_RTS_ACCESS_STEER_DATA1_GET_FLASH_VER_DAY(data2);
-		flash_date->month =
-		 (u32)VXGE_HW_RTS_ACCESS_STEER_DATA1_GET_FLASH_VER_MONTH(data2);
-		flash_date->year =
-		 (u32)VXGE_HW_RTS_ACCESS_STEER_DATA1_GET_FLASH_VER_YEAR(data2);
-
-		snprintf(flash_date->date, VXGE_HW_FW_STRLEN,
-			"%2.2d/%2.2d/%4.4d",
-			flash_date->month, flash_date->day, flash_date->year);
-
-		flash_version->major =
-		 (u32)VXGE_HW_RTS_ACCESS_STEER_DATA1_GET_FLASH_VER_MAJOR(data2);
-		flash_version->minor =
-		 (u32)VXGE_HW_RTS_ACCESS_STEER_DATA1_GET_FLASH_VER_MINOR(data2);
-		flash_version->build =
-		 (u32)VXGE_HW_RTS_ACCESS_STEER_DATA1_GET_FLASH_VER_BUILD(data2);
-
-		snprintf(flash_version->version, VXGE_HW_FW_STRLEN, "%d.%d.%d",
-			flash_version->major, flash_version->minor,
-			flash_version->build);
-
-		status = VXGE_HW_OK;
-
-	} else
-		status = VXGE_HW_FAIL;
-exit:
-	return status;
-}
-
-/*
- * __vxge_hw_vpath_pci_func_mode_get - Get the pci mode
- * Returns pci function mode
- */
-static u64
-__vxge_hw_vpath_pci_func_mode_get(
-	u32  vp_id,
-	struct vxge_hw_vpath_reg __iomem *vpath_reg)
-{
-	u64 val64;
-	u64 data1 = 0ULL;
-	enum vxge_hw_status status = VXGE_HW_OK;
-
-	__vxge_hw_read_rts_ds(vpath_reg,
-		VXGE_HW_RTS_ACCESS_STEER_DATA0_MEMO_ITEM_PCI_MODE);
-
-	val64 = VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION(
-			VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION_READ_MEMO_ENTRY) |
-		VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL(
-			VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_FW_MEMO) |
-		VXGE_HW_RTS_ACCESS_STEER_CTRL_STROBE |
-		VXGE_HW_RTS_ACCESS_STEER_CTRL_OFFSET(0);
-
-	status = __vxge_hw_pio_mem_write64(val64,
-				&vpath_reg->rts_access_steer_ctrl,
-				VXGE_HW_RTS_ACCESS_STEER_CTRL_STROBE,
-				VXGE_HW_DEF_DEVICE_POLL_MILLIS);
-
-	if (status != VXGE_HW_OK)
-		goto exit;
-
-	val64 = readq(&vpath_reg->rts_access_steer_ctrl);
-
-	if (val64 & VXGE_HW_RTS_ACCESS_STEER_CTRL_RMACJ_STATUS) {
-		data1 = readq(&vpath_reg->rts_access_steer_data0);
-		status = VXGE_HW_OK;
-	} else {
-		data1 = 0;
-		status = VXGE_HW_FAIL;
-	}
-exit:
-	return data1;
-}
-
 /**
  * vxge_hw_device_flick_link_led - Flick (blink) link LED.
  * @hldev: HW device.
@@ -2974,37 +3636,24 @@ exit:
  * Flicker the link LED.
  */
 enum vxge_hw_status
-vxge_hw_device_flick_link_led(struct __vxge_hw_device *hldev,
-			       u64 on_off)
+vxge_hw_device_flick_link_led(struct __vxge_hw_device *hldev, u64 on_off)
 {
-	u64 val64;
-	enum vxge_hw_status status = VXGE_HW_OK;
-	struct vxge_hw_vpath_reg __iomem *vp_reg;
+	struct __vxge_hw_virtualpath *vpath;
+	u64 data0, data1 = 0, steer_ctrl = 0;
+	enum vxge_hw_status status;
 
 	if (hldev == NULL) {
 		status = VXGE_HW_ERR_INVALID_DEVICE;
 		goto exit;
 	}
 
-	vp_reg = hldev->vpath_reg[hldev->first_vp_id];
-
-	writeq(0, &vp_reg->rts_access_steer_ctrl);
-	wmb();
-	writeq(on_off, &vp_reg->rts_access_steer_data0);
-	writeq(0, &vp_reg->rts_access_steer_data1);
-	wmb();
-
-	val64 = VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION(
-			VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION_LED_CONTROL) |
-		VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL(
-			VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_FW_MEMO) |
-		VXGE_HW_RTS_ACCESS_STEER_CTRL_STROBE |
-		VXGE_HW_RTS_ACCESS_STEER_CTRL_OFFSET(0);
+	vpath = &hldev->virtual_paths[hldev->first_vp_id];
 
-	status = __vxge_hw_pio_mem_write64(val64,
-				&vp_reg->rts_access_steer_ctrl,
-				VXGE_HW_RTS_ACCESS_STEER_CTRL_STROBE,
-				VXGE_HW_DEF_DEVICE_POLL_MILLIS);
+	data0 = on_off;
+	status = vxge_hw_vpath_fw_api(vpath,
+			VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION_LED_CONTROL,
+			VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_FW_MEMO,
+			0, &data0, &data1, &steer_ctrl);
 exit:
 	return status;
 }
@@ -3013,63 +3662,38 @@ exit:
  * __vxge_hw_vpath_rts_table_get - Get the entries from RTS access tables
  */
 enum vxge_hw_status
-__vxge_hw_vpath_rts_table_get(
-	struct __vxge_hw_vpath_handle *vp,
-	u32 action, u32 rts_table, u32 offset, u64 *data1, u64 *data2)
+__vxge_hw_vpath_rts_table_get(struct __vxge_hw_vpath_handle *vp,
+			      u32 action, u32 rts_table, u32 offset,
+			      u64 *data0, u64 *data1)
 {
-	u64 val64;
-	struct __vxge_hw_virtualpath *vpath;
-	struct vxge_hw_vpath_reg __iomem *vp_reg;
-
-	enum vxge_hw_status status = VXGE_HW_OK;
+	enum vxge_hw_status status;
+	u64 steer_ctrl = 0;
 
 	if (vp == NULL) {
 		status = VXGE_HW_ERR_INVALID_HANDLE;
 		goto exit;
 	}
 
-	vpath = vp->vpath;
-	vp_reg = vpath->vp_reg;
-
-	val64 = VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION(action) |
-		VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL(rts_table) |
-		VXGE_HW_RTS_ACCESS_STEER_CTRL_STROBE |
-		VXGE_HW_RTS_ACCESS_STEER_CTRL_OFFSET(offset);
-
 	if ((rts_table ==
-		VXGE_HW_RTS_ACS_STEER_CTRL_DATA_STRUCT_SEL_RTH_SOLO_IT) ||
+	     VXGE_HW_RTS_ACS_STEER_CTRL_DATA_STRUCT_SEL_RTH_SOLO_IT) ||
 	    (rts_table ==
-		VXGE_HW_RTS_ACS_STEER_CTRL_DATA_STRUCT_SEL_RTH_MULTI_IT) ||
+	     VXGE_HW_RTS_ACS_STEER_CTRL_DATA_STRUCT_SEL_RTH_MULTI_IT) ||
 	    (rts_table ==
-		VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_RTH_MASK) ||
+	     VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_RTH_MASK) ||
 	    (rts_table ==
-		VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_RTH_KEY)) {
-		val64 = val64 |	VXGE_HW_RTS_ACCESS_STEER_CTRL_TABLE_SEL;
+	     VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_RTH_KEY)) {
+		steer_ctrl = VXGE_HW_RTS_ACCESS_STEER_CTRL_TABLE_SEL;
 	}
 
-	status = __vxge_hw_pio_mem_write64(val64,
-				&vp_reg->rts_access_steer_ctrl,
-				VXGE_HW_RTS_ACCESS_STEER_CTRL_STROBE,
-				vpath->hldev->config.device_poll_millis);
-
+	status = vxge_hw_vpath_fw_api(vp->vpath, action, rts_table, offset,
+				      data0, data1, &steer_ctrl);
 	if (status != VXGE_HW_OK)
 		goto exit;
 
-	val64 = readq(&vp_reg->rts_access_steer_ctrl);
-
-	if (val64 & VXGE_HW_RTS_ACCESS_STEER_CTRL_RMACJ_STATUS) {
-
-		*data1 = readq(&vp_reg->rts_access_steer_data0);
-
-		if ((rts_table ==
-		VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_DA) ||
-		(rts_table ==
-		VXGE_HW_RTS_ACS_STEER_CTRL_DATA_STRUCT_SEL_RTH_MULTI_IT)) {
-			*data2 = readq(&vp_reg->rts_access_steer_data1);
-		}
-		status = VXGE_HW_OK;
-	} else
-		status = VXGE_HW_FAIL;
+	if ((rts_table != VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_DA) &&
+	    (rts_table !=
+	     VXGE_HW_RTS_ACS_STEER_CTRL_DATA_STRUCT_SEL_RTH_MULTI_IT))
+		*data1 = 0;
 exit:
 	return status;
 }
@@ -3078,107 +3702,27 @@ exit:
  * __vxge_hw_vpath_rts_table_set - Set the entries of RTS access tables
  */
 enum vxge_hw_status
-__vxge_hw_vpath_rts_table_set(
-	struct __vxge_hw_vpath_handle *vp, u32 action, u32 rts_table,
-	u32 offset, u64 data1, u64 data2)
+__vxge_hw_vpath_rts_table_set(struct __vxge_hw_vpath_handle *vp, u32 action,
+			      u32 rts_table, u32 offset, u64 steer_data0,
+			      u64 steer_data1)
 {
-	u64 val64;
-	struct __vxge_hw_virtualpath *vpath;
-	enum vxge_hw_status status = VXGE_HW_OK;
-	struct vxge_hw_vpath_reg __iomem *vp_reg;
+	u64 data0, data1 = 0, steer_ctrl = 0;
+	enum vxge_hw_status status;
 
 	if (vp == NULL) {
 		status = VXGE_HW_ERR_INVALID_HANDLE;
 		goto exit;
 	}
 
-	vpath = vp->vpath;
-	vp_reg = vpath->vp_reg;
-
-	writeq(data1, &vp_reg->rts_access_steer_data0);
-	wmb();
+	data0 = steer_data0;
 
 	if ((rts_table == VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_DA) ||
 	    (rts_table ==
-		VXGE_HW_RTS_ACS_STEER_CTRL_DATA_STRUCT_SEL_RTH_MULTI_IT)) {
-		writeq(data2, &vp_reg->rts_access_steer_data1);
-		wmb();
-	}
-
-	val64 = VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION(action) |
-		VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL(rts_table) |
-		VXGE_HW_RTS_ACCESS_STEER_CTRL_STROBE |
-		VXGE_HW_RTS_ACCESS_STEER_CTRL_OFFSET(offset);
-
-	status = __vxge_hw_pio_mem_write64(val64,
-				&vp_reg->rts_access_steer_ctrl,
-				VXGE_HW_RTS_ACCESS_STEER_CTRL_STROBE,
-				vpath->hldev->config.device_poll_millis);
-
-	if (status != VXGE_HW_OK)
-		goto exit;
-
-	val64 = readq(&vp_reg->rts_access_steer_ctrl);
-
-	if (val64 & VXGE_HW_RTS_ACCESS_STEER_CTRL_RMACJ_STATUS)
-		status = VXGE_HW_OK;
-	else
-		status = VXGE_HW_FAIL;
-exit:
-	return status;
-}
-
-/*
- * __vxge_hw_vpath_addr_get - Get the hw address entry for this vpath
- *               from MAC address table.
- */
-static enum vxge_hw_status
-__vxge_hw_vpath_addr_get(
-	u32 vp_id, struct vxge_hw_vpath_reg __iomem *vpath_reg,
-	u8 (macaddr)[ETH_ALEN], u8 (macaddr_mask)[ETH_ALEN])
-{
-	u32 i;
-	u64 val64;
-	u64 data1 = 0ULL;
-	u64 data2 = 0ULL;
-	enum vxge_hw_status status = VXGE_HW_OK;
-
-	val64 = VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION(
-		VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION_LIST_FIRST_ENTRY) |
-		VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL(
-		VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_DA) |
-		VXGE_HW_RTS_ACCESS_STEER_CTRL_STROBE |
-		VXGE_HW_RTS_ACCESS_STEER_CTRL_OFFSET(0);
-
-	status = __vxge_hw_pio_mem_write64(val64,
-				&vpath_reg->rts_access_steer_ctrl,
-				VXGE_HW_RTS_ACCESS_STEER_CTRL_STROBE,
-				VXGE_HW_DEF_DEVICE_POLL_MILLIS);
-
-	if (status != VXGE_HW_OK)
-		goto exit;
-
-	val64 = readq(&vpath_reg->rts_access_steer_ctrl);
-
-	if (val64 & VXGE_HW_RTS_ACCESS_STEER_CTRL_RMACJ_STATUS) {
-
-		data1 = readq(&vpath_reg->rts_access_steer_data0);
-		data2 = readq(&vpath_reg->rts_access_steer_data1);
-
-		data1 = VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_DA_MAC_ADDR(data1);
-		data2 = VXGE_HW_RTS_ACCESS_STEER_DATA1_GET_DA_MAC_ADDR_MASK(
-							data2);
-
-		for (i = ETH_ALEN; i > 0; i--) {
-			macaddr[i-1] = (u8)(data1 & 0xFF);
-			data1 >>= 8;
+	     VXGE_HW_RTS_ACS_STEER_CTRL_DATA_STRUCT_SEL_RTH_MULTI_IT))
+		data1 = steer_data1;
 
-			macaddr_mask[i-1] = (u8)(data2 & 0xFF);
-			data2 >>= 8;
-		}
-		status = VXGE_HW_OK;
-	} else
-		status = VXGE_HW_FAIL;
+	status = vxge_hw_vpath_fw_api(vp->vpath, action, rts_table, offset,
+				      &data0, &data1, &steer_ctrl);
 exit:
 	return status;
 }
@@ -3204,6 +3748,8 @@ enum vxge_hw_status vxge_hw_vpath_rts_rt
 		     VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION_READ_ENTRY,
 		     VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_RTH_GEN_CFG,
 			0, &data0, &data1);
+	if (status != VXGE_HW_OK)
+		goto exit;
 
 	data0 &= ~(VXGE_HW_RTS_ACCESS_STEER_DATA0_RTH_GEN_BUCKET_SIZE(0xf) |
 			VXGE_HW_RTS_ACCESS_STEER_DATA0_RTH_GEN_ALG_SEL(0x3));
@@ -3771,10 +4317,10 @@ __vxge_hw_vpath_tim_configure(struct __v
 	vp_reg = vpath->vp_reg;
 	config = vpath->vp_config;
 
-	writeq((u64)0, &vp_reg->tim_dest_addr);
-	writeq((u64)0, &vp_reg->tim_vpath_map);
-	writeq((u64)0, &vp_reg->tim_bitmap);
-	writeq((u64)0, &vp_reg->tim_remap);
+	writeq(0, &vp_reg->tim_dest_addr);
+	writeq(0, &vp_reg->tim_vpath_map);
+	writeq(0, &vp_reg->tim_bitmap);
+	writeq(0, &vp_reg->tim_remap);
 
 	if (config->ring.enable == VXGE_HW_RING_ENABLE)
 		writeq(VXGE_HW_TIM_RING_ASSN_INT_NUM(
@@ -3876,8 +4422,7 @@ __vxge_hw_vpath_tim_configure(struct __v
 
 		if (config->tti.util_sel != VXGE_HW_USE_FLASH_DEFAULT) {
 			val64 &= ~VXGE_HW_TIM_CFG3_INT_NUM_UTIL_SEL(0x3f);
-			val64 |= VXGE_HW_TIM_CFG3_INT_NUM_UTIL_SEL(
-					config->tti.util_sel);
+			val64 |= VXGE_HW_TIM_CFG3_INT_NUM_UTIL_SEL(vp_id);
 		}
 
 		if (config->tti.ltimer_val != VXGE_HW_USE_FLASH_DEFAULT) {
@@ -3981,8 +4526,7 @@ __vxge_hw_vpath_tim_configure(struct __v
 
 		if (config->rti.util_sel != VXGE_HW_USE_FLASH_DEFAULT) {
 			val64 &= ~VXGE_HW_TIM_CFG3_INT_NUM_UTIL_SEL(0x3f);
-			val64 |= VXGE_HW_TIM_CFG3_INT_NUM_UTIL_SEL(
-					config->rti.util_sel);
+			val64 |= VXGE_HW_TIM_CFG3_INT_NUM_UTIL_SEL(vp_id);
 		}
 
 		if (config->rti.ltimer_val != VXGE_HW_USE_FLASH_DEFAULT) {
@@ -4003,11 +4547,15 @@ __vxge_hw_vpath_tim_configure(struct __v
 	writeq(val64, &vp_reg->tim_cfg2_int_num[VXGE_HW_VPATH_INTR_BMAP]);
 	writeq(val64, &vp_reg->tim_cfg3_int_num[VXGE_HW_VPATH_INTR_BMAP]);
 
+	val64 = VXGE_HW_TIM_WRKLD_CLC_WRKLD_EVAL_PRD(150);
+	val64 |= VXGE_HW_TIM_WRKLD_CLC_WRKLD_EVAL_DIV(0);
+	val64 |= VXGE_HW_TIM_WRKLD_CLC_CNT_RX_TX(3);
+	writeq(val64, &vp_reg->tim_wrkld_clc);
+
 	return status;
 }
 
-void
-vxge_hw_vpath_tti_ci_set(struct __vxge_hw_device *hldev, u32 vp_id)
+void vxge_hw_vpath_tti_ci_set(struct __vxge_hw_device *hldev, u32 vp_id)
 {
 	struct __vxge_hw_virtualpath *vpath;
 	struct vxge_hw_vpath_reg __iomem *vp_reg;
@@ -4018,17 +4566,15 @@ vxge_hw_vpath_tti_ci_set(struct __vxge_h
 	vp_reg = vpath->vp_reg;
 	config = vpath->vp_config;
 
-	if (config->fifo.enable == VXGE_HW_FIFO_ENABLE) {
+	if (config->fifo.enable == VXGE_HW_FIFO_ENABLE &&
+	    config->tti.timer_ci_en != VXGE_HW_TIM_TIMER_CI_ENABLE) {
+		config->tti.timer_ci_en = VXGE_HW_TIM_TIMER_CI_ENABLE;
 		val64 = readq(&vp_reg->tim_cfg1_int_num[VXGE_HW_VPATH_INTR_TX]);
-
-		if (config->tti.timer_ci_en != VXGE_HW_TIM_TIMER_CI_ENABLE) {
-			config->tti.timer_ci_en = VXGE_HW_TIM_TIMER_CI_ENABLE;
-			val64 |= VXGE_HW_TIM_CFG1_INT_NUM_TIMER_CI;
-			writeq(val64,
-			&vp_reg->tim_cfg1_int_num[VXGE_HW_VPATH_INTR_TX]);
-		}
+		val64 |= VXGE_HW_TIM_CFG1_INT_NUM_TIMER_CI;
+		writeq(val64, &vp_reg->tim_cfg1_int_num[VXGE_HW_VPATH_INTR_TX]);
 	}
 }
+
 /*
  * __vxge_hw_vpath_initialize
  * This routine is the final phase of init which initializes the
@@ -4052,22 +4598,18 @@ __vxge_hw_vpath_initialize(struct __vxge
 	vp_reg = vpath->vp_reg;
 
 	status =  __vxge_hw_vpath_swapper_set(vpath->vp_reg);
-
 	if (status != VXGE_HW_OK)
 		goto exit;
 
 	status =  __vxge_hw_vpath_mac_configure(hldev, vp_id);
-
 	if (status != VXGE_HW_OK)
 		goto exit;
 
 	status =  __vxge_hw_vpath_kdfc_configure(hldev, vp_id);
-
 	if (status != VXGE_HW_OK)
 		goto exit;
 
 	status = __vxge_hw_vpath_tim_configure(hldev, vp_id);
-
 	if (status != VXGE_HW_OK)
 		goto exit;
 
@@ -4075,7 +4617,6 @@ __vxge_hw_vpath_initialize(struct __vxge
 
 	/* Get MRRS value from device control */
 	status  = __vxge_hw_vpath_pci_read(vpath, 1, 0x78, &val32);
-
 	if (status == VXGE_HW_OK) {
 		val32 = (val32 & VXGE_HW_PCI_EXP_DEVCTL_READRQ) >> 12;
 		val64 &=
@@ -4099,6 +4640,28 @@ exit:
 }
 
 /*
+ * __vxge_hw_vp_terminate - Terminate Virtual Path structure
+ * This routine closes all channels it opened and freeup memory
+ */
+static void __vxge_hw_vp_terminate(struct __vxge_hw_device *hldev, u32 vp_id)
+{
+	struct __vxge_hw_virtualpath *vpath;
+
+	vpath = &hldev->virtual_paths[vp_id];
+
+	if (vpath->vp_open == VXGE_HW_VP_NOT_OPEN)
+		goto exit;
+
+	VXGE_HW_DEVICE_TIM_INT_MASK_RESET(vpath->hldev->tim_int_mask0,
+		vpath->hldev->tim_int_mask1, vpath->vp_id);
+	hldev->stats.hw_dev_info_stats.vpath_info[vpath->vp_id] = NULL;
+
+	memset(vpath, 0, sizeof(struct __vxge_hw_virtualpath));
+exit:
+	return;
+}
+
+/*
  * __vxge_hw_vp_initialize - Initialize Virtual Path structure
  * This routine is the initial phase of init which resets the vpath and
  * initializes the software support structures.
@@ -4117,6 +4680,7 @@ __vxge_hw_vp_initialize(struct __vxge_hw
 
 	vpath = &hldev->virtual_paths[vp_id];
 
+	spin_lock_init(&hldev->virtual_paths[vp_id].lock);
 	vpath->vp_id = vp_id;
 	vpath->vp_open = VXGE_HW_VP_OPEN;
 	vpath->hldev = hldev;
@@ -4127,14 +4691,12 @@ __vxge_hw_vp_initialize(struct __vxge_hw
 	__vxge_hw_vpath_reset(hldev, vp_id);
 
 	status = __vxge_hw_vpath_reset_check(vpath);
-
 	if (status != VXGE_HW_OK) {
 		memset(vpath, 0, sizeof(struct __vxge_hw_virtualpath));
 		goto exit;
 	}
 
 	status = __vxge_hw_vpath_mgmt_read(hldev, vpath);
-
 	if (status != VXGE_HW_OK) {
 		memset(vpath, 0, sizeof(struct __vxge_hw_virtualpath));
 		goto exit;
@@ -4148,7 +4710,6 @@ __vxge_hw_vp_initialize(struct __vxge_hw
 		hldev->tim_int_mask1, vp_id);
 
 	status = __vxge_hw_vpath_initialize(hldev, vp_id);
-
 	if (status != VXGE_HW_OK)
 		__vxge_hw_vp_terminate(hldev, vp_id);
 exit:
@@ -4156,29 +4717,6 @@ exit:
 }
 
 /*
- * __vxge_hw_vp_terminate - Terminate Virtual Path structure
- * This routine closes all channels it opened and freeup memory
- */
-static void
-__vxge_hw_vp_terminate(struct __vxge_hw_device *hldev, u32 vp_id)
-{
-	struct __vxge_hw_virtualpath *vpath;
-
-	vpath = &hldev->virtual_paths[vp_id];
-
-	if (vpath->vp_open == VXGE_HW_VP_NOT_OPEN)
-		goto exit;
-
-	VXGE_HW_DEVICE_TIM_INT_MASK_RESET(vpath->hldev->tim_int_mask0,
-		vpath->hldev->tim_int_mask1, vpath->vp_id);
-	hldev->stats.hw_dev_info_stats.vpath_info[vpath->vp_id] = NULL;
-
-	memset(vpath, 0, sizeof(struct __vxge_hw_virtualpath));
-exit:
-	return;
-}
-
-/*
  * vxge_hw_vpath_mtu_set - Set MTU.
  * Set new MTU value. Example, to use jumbo frames:
  * vxge_hw_vpath_mtu_set(my_device, 9600);
@@ -4215,6 +4753,64 @@ exit:
 }
 
 /*
+ * vxge_hw_vpath_stats_enable - Enable vpath h/wstatistics.
+ * Enable the DMA vpath statistics. The function is to be called to re-enable
+ * the adapter to update stats into the host memory
+ */
+static enum vxge_hw_status
+vxge_hw_vpath_stats_enable(struct __vxge_hw_vpath_handle *vp)
+{
+	enum vxge_hw_status status = VXGE_HW_OK;
+	struct __vxge_hw_virtualpath *vpath;
+
+	vpath = vp->vpath;
+
+	if (vpath->vp_open == VXGE_HW_VP_NOT_OPEN) {
+		status = VXGE_HW_ERR_VPATH_NOT_OPEN;
+		goto exit;
+	}
+
+	memcpy(vpath->hw_stats_sav, vpath->hw_stats,
+			sizeof(struct vxge_hw_vpath_stats_hw_info));
+
+	status = __vxge_hw_vpath_stats_get(vpath, vpath->hw_stats);
+exit:
+	return status;
+}
+
+/*
+ * __vxge_hw_blockpool_block_allocate - Allocates a block from block pool
+ * This function allocates a block from block pool or from the system
+ */
+static struct __vxge_hw_blockpool_entry *
+__vxge_hw_blockpool_block_allocate(struct __vxge_hw_device *devh, u32 size)
+{
+	struct __vxge_hw_blockpool_entry *entry = NULL;
+	struct __vxge_hw_blockpool  *blockpool;
+
+	blockpool = &devh->block_pool;
+
+	if (size == blockpool->block_size) {
+
+		if (!list_empty(&blockpool->free_block_list))
+			entry = (struct __vxge_hw_blockpool_entry *)
+				list_first_entry(&blockpool->free_block_list,
+					struct __vxge_hw_blockpool_entry,
+					item);
+
+		if (entry != NULL) {
+			list_del(&entry->item);
+			blockpool->pool_size--;
+		}
+	}
+
+	if (entry != NULL)
+		__vxge_hw_blockpool_blocks_add(blockpool);
+
+	return entry;
+}
+
+/*
  * vxge_hw_vpath_open - Open a virtual path on a given adapter
  * This function is used to open access to virtual path of an
  * adapter for offload, GRO operations. This function returns
@@ -4238,19 +4834,15 @@ vxge_hw_vpath_open(struct __vxge_hw_devi
 
 	status = __vxge_hw_vp_initialize(hldev, attr->vp_id,
 			&hldev->config.vp_config[attr->vp_id]);
-
 	if (status != VXGE_HW_OK)
 		goto vpath_open_exit1;
 
-	vp = (struct __vxge_hw_vpath_handle *)
-		vmalloc(sizeof(struct __vxge_hw_vpath_handle));
+	vp = vzalloc(sizeof(struct __vxge_hw_vpath_handle));
 	if (vp == NULL) {
 		status = VXGE_HW_ERR_OUT_OF_MEMORY;
 		goto vpath_open_exit2;
 	}
 
-	memset(vp, 0, sizeof(struct __vxge_hw_vpath_handle));
-
 	vp->vpath = vpath;
 
 	if (vpath->vp_config->fifo.enable == VXGE_HW_FIFO_ENABLE) {
@@ -4273,7 +4865,6 @@ vxge_hw_vpath_open(struct __vxge_hw_devi
 
 	vpath->stats_block = __vxge_hw_blockpool_block_allocate(hldev,
 				VXGE_HW_BLOCK_SIZE);
-
 	if (vpath->stats_block == NULL) {
 		status = VXGE_HW_ERR_OUT_OF_MEMORY;
 		goto vpath_open_exit8;
@@ -4332,19 +4923,20 @@ vpath_open_exit1:
  * This function is used to close access to virtual path opened
  * earlier.
  */
-void
-vxge_hw_vpath_rx_doorbell_init(struct __vxge_hw_vpath_handle *vp)
+void vxge_hw_vpath_rx_doorbell_init(struct __vxge_hw_vpath_handle *vp)
 {
-	struct __vxge_hw_virtualpath *vpath = NULL;
+	struct __vxge_hw_virtualpath *vpath = vp->vpath;
+	struct __vxge_hw_ring *ring = vpath->ringh;
+	struct vxgedev *vdev = netdev_priv(vpath->hldev->ndev);
 	u64 new_count, val64, val164;
-	struct __vxge_hw_ring *ring;
 
-	vpath = vp->vpath;
-	ring = vpath->ringh;
+	if (vdev->titan1) {
+		new_count = readq(&vpath->vp_reg->rxdmem_size);
+		new_count &= 0x1fff;
+	} else
+		new_count = ring->config->ring_blocks * VXGE_HW_BLOCK_SIZE / 8;
 
-	new_count = readq(&vpath->vp_reg->rxdmem_size);
-	new_count &= 0x1fff;
-	val164 = (VXGE_HW_RXDMEM_SIZE_PRC_RXDMEM_SIZE(new_count));
+	val164 = VXGE_HW_RXDMEM_SIZE_PRC_RXDMEM_SIZE(new_count);
 
 	writeq(VXGE_HW_PRC_RXD_DOORBELL_NEW_QW_CNT(val164),
 		&vpath->vp_reg->prc_rxd_doorbell);
@@ -4367,6 +4959,29 @@ vxge_hw_vpath_rx_doorbell_init(struct __
 }
 
 /*
+ * __vxge_hw_blockpool_block_free - Frees a block from block pool
+ * @devh: Hal device
+ * @entry: Entry of block to be freed
+ *
+ * This function frees a block from block pool
+ */
+static void
+__vxge_hw_blockpool_block_free(struct __vxge_hw_device *devh,
+			       struct __vxge_hw_blockpool_entry *entry)
+{
+	struct __vxge_hw_blockpool  *blockpool;
+
+	blockpool = &devh->block_pool;
+
+	if (entry->length == blockpool->block_size) {
+		list_add(&entry->item, &blockpool->free_block_list);
+		blockpool->pool_size++;
+	}
+
+	__vxge_hw_blockpool_blocks_remove(blockpool);
+}
+
+/*
  * vxge_hw_vpath_close - Close the handle got from previous vpath (vpath) open
  * This function is used to close access to virtual path opened
  * earlier.
@@ -4414,7 +5029,9 @@ enum vxge_hw_status vxge_hw_vpath_close(
 
 	__vxge_hw_vp_terminate(devh, vp_id);
 
+	spin_lock(&vpath->lock);
 	vpath->vp_open = VXGE_HW_VP_NOT_OPEN;
+	spin_unlock(&vpath->lock);
 
 vpath_close_exit:
 	return status;
@@ -4515,730 +5132,3 @@ vxge_hw_vpath_enable(struct __vxge_hw_vp
 	__vxge_hw_pio_mem_write32_upper((u32)vxge_bVALn(val64, 0, 32),
 		&hldev->common_reg->cmn_rsthdlr_cfg1);
 }
-
-/*
- * vxge_hw_vpath_stats_enable - Enable vpath h/wstatistics.
- * Enable the DMA vpath statistics. The function is to be called to re-enable
- * the adapter to update stats into the host memory
- */
-static enum vxge_hw_status
-vxge_hw_vpath_stats_enable(struct __vxge_hw_vpath_handle *vp)
-{
-	enum vxge_hw_status status = VXGE_HW_OK;
-	struct __vxge_hw_virtualpath *vpath;
-
-	vpath = vp->vpath;
-
-	if (vpath->vp_open == VXGE_HW_VP_NOT_OPEN) {
-		status = VXGE_HW_ERR_VPATH_NOT_OPEN;
-		goto exit;
-	}
-
-	memcpy(vpath->hw_stats_sav, vpath->hw_stats,
-			sizeof(struct vxge_hw_vpath_stats_hw_info));
-
-	status = __vxge_hw_vpath_stats_get(vpath, vpath->hw_stats);
-exit:
-	return status;
-}
-
-/*
- * __vxge_hw_vpath_stats_access - Get the statistics from the given location
- *                           and offset and perform an operation
- */
-static enum vxge_hw_status
-__vxge_hw_vpath_stats_access(struct __vxge_hw_virtualpath *vpath,
-			     u32 operation, u32 offset, u64 *stat)
-{
-	u64 val64;
-	enum vxge_hw_status status = VXGE_HW_OK;
-	struct vxge_hw_vpath_reg __iomem *vp_reg;
-
-	if (vpath->vp_open == VXGE_HW_VP_NOT_OPEN) {
-		status = VXGE_HW_ERR_VPATH_NOT_OPEN;
-		goto vpath_stats_access_exit;
-	}
-
-	vp_reg = vpath->vp_reg;
-
-	val64 =  VXGE_HW_XMAC_STATS_ACCESS_CMD_OP(operation) |
-		 VXGE_HW_XMAC_STATS_ACCESS_CMD_STROBE |
-		 VXGE_HW_XMAC_STATS_ACCESS_CMD_OFFSET_SEL(offset);
-
-	status = __vxge_hw_pio_mem_write64(val64,
-				&vp_reg->xmac_stats_access_cmd,
-				VXGE_HW_XMAC_STATS_ACCESS_CMD_STROBE,
-				vpath->hldev->config.device_poll_millis);
-
-	if ((status == VXGE_HW_OK) && (operation == VXGE_HW_STATS_OP_READ))
-		*stat = readq(&vp_reg->xmac_stats_access_data);
-	else
-		*stat = 0;
-
-vpath_stats_access_exit:
-	return status;
-}
-
-/*
- * __vxge_hw_vpath_xmac_tx_stats_get - Get the TX Statistics of a vpath
- */
-static enum vxge_hw_status
-__vxge_hw_vpath_xmac_tx_stats_get(
-	struct __vxge_hw_virtualpath *vpath,
-	struct vxge_hw_xmac_vpath_tx_stats *vpath_tx_stats)
-{
-	u64 *val64;
-	int i;
-	u32 offset = VXGE_HW_STATS_VPATH_TX_OFFSET;
-	enum vxge_hw_status status = VXGE_HW_OK;
-
-	val64 = (u64 *) vpath_tx_stats;
-
-	if (vpath->vp_open == VXGE_HW_VP_NOT_OPEN) {
-		status = VXGE_HW_ERR_VPATH_NOT_OPEN;
-		goto exit;
-	}
-
-	for (i = 0; i < sizeof(struct vxge_hw_xmac_vpath_tx_stats) / 8; i++) {
-		status = __vxge_hw_vpath_stats_access(vpath,
-					VXGE_HW_STATS_OP_READ,
-					offset, val64);
-		if (status != VXGE_HW_OK)
-			goto exit;
-		offset++;
-		val64++;
-	}
-exit:
-	return status;
-}
-
-/*
- * __vxge_hw_vpath_xmac_rx_stats_get - Get the RX Statistics of a vpath
- */
-static enum vxge_hw_status
-__vxge_hw_vpath_xmac_rx_stats_get(struct __vxge_hw_virtualpath *vpath,
-				  struct vxge_hw_xmac_vpath_rx_stats *vpath_rx_stats)
-{
-	u64 *val64;
-	enum vxge_hw_status status = VXGE_HW_OK;
-	int i;
-	u32 offset = VXGE_HW_STATS_VPATH_RX_OFFSET;
-	val64 = (u64 *) vpath_rx_stats;
-
-	if (vpath->vp_open == VXGE_HW_VP_NOT_OPEN) {
-		status = VXGE_HW_ERR_VPATH_NOT_OPEN;
-		goto exit;
-	}
-	for (i = 0; i < sizeof(struct vxge_hw_xmac_vpath_rx_stats) / 8; i++) {
-		status = __vxge_hw_vpath_stats_access(vpath,
-					VXGE_HW_STATS_OP_READ,
-					offset >> 3, val64);
-		if (status != VXGE_HW_OK)
-			goto exit;
-
-		offset += 8;
-		val64++;
-	}
-exit:
-	return status;
-}
-
-/*
- * __vxge_hw_vpath_stats_get - Get the vpath hw statistics.
- */
-static enum vxge_hw_status
-__vxge_hw_vpath_stats_get(struct __vxge_hw_virtualpath *vpath,
-			  struct vxge_hw_vpath_stats_hw_info *hw_stats)
-{
-	u64 val64;
-	enum vxge_hw_status status = VXGE_HW_OK;
-	struct vxge_hw_vpath_reg __iomem *vp_reg;
-
-	if (vpath->vp_open == VXGE_HW_VP_NOT_OPEN) {
-		status = VXGE_HW_ERR_VPATH_NOT_OPEN;
-		goto exit;
-	}
-	vp_reg = vpath->vp_reg;
-
-	val64 = readq(&vp_reg->vpath_debug_stats0);
-	hw_stats->ini_num_mwr_sent =
-		(u32)VXGE_HW_VPATH_DEBUG_STATS0_GET_INI_NUM_MWR_SENT(val64);
-
-	val64 = readq(&vp_reg->vpath_debug_stats1);
-	hw_stats->ini_num_mrd_sent =
-		(u32)VXGE_HW_VPATH_DEBUG_STATS1_GET_INI_NUM_MRD_SENT(val64);
-
-	val64 = readq(&vp_reg->vpath_debug_stats2);
-	hw_stats->ini_num_cpl_rcvd =
-		(u32)VXGE_HW_VPATH_DEBUG_STATS2_GET_INI_NUM_CPL_RCVD(val64);
-
-	val64 = readq(&vp_reg->vpath_debug_stats3);
-	hw_stats->ini_num_mwr_byte_sent =
-		VXGE_HW_VPATH_DEBUG_STATS3_GET_INI_NUM_MWR_BYTE_SENT(val64);
-
-	val64 = readq(&vp_reg->vpath_debug_stats4);
-	hw_stats->ini_num_cpl_byte_rcvd =
-		VXGE_HW_VPATH_DEBUG_STATS4_GET_INI_NUM_CPL_BYTE_RCVD(val64);
-
-	val64 = readq(&vp_reg->vpath_debug_stats5);
-	hw_stats->wrcrdtarb_xoff =
-		(u32)VXGE_HW_VPATH_DEBUG_STATS5_GET_WRCRDTARB_XOFF(val64);
-
-	val64 = readq(&vp_reg->vpath_debug_stats6);
-	hw_stats->rdcrdtarb_xoff =
-		(u32)VXGE_HW_VPATH_DEBUG_STATS6_GET_RDCRDTARB_XOFF(val64);
-
-	val64 = readq(&vp_reg->vpath_genstats_count01);
-	hw_stats->vpath_genstats_count0 =
-	(u32)VXGE_HW_VPATH_GENSTATS_COUNT01_GET_PPIF_VPATH_GENSTATS_COUNT0(
-		val64);
-
-	val64 = readq(&vp_reg->vpath_genstats_count01);
-	hw_stats->vpath_genstats_count1 =
-	(u32)VXGE_HW_VPATH_GENSTATS_COUNT01_GET_PPIF_VPATH_GENSTATS_COUNT1(
-		val64);
-
-	val64 = readq(&vp_reg->vpath_genstats_count23);
-	hw_stats->vpath_genstats_count2 =
-	(u32)VXGE_HW_VPATH_GENSTATS_COUNT23_GET_PPIF_VPATH_GENSTATS_COUNT2(
-		val64);
-
-	val64 = readq(&vp_reg->vpath_genstats_count01);
-	hw_stats->vpath_genstats_count3 =
-	(u32)VXGE_HW_VPATH_GENSTATS_COUNT23_GET_PPIF_VPATH_GENSTATS_COUNT3(
-		val64);
-
-	val64 = readq(&vp_reg->vpath_genstats_count4);
-	hw_stats->vpath_genstats_count4 =
-	(u32)VXGE_HW_VPATH_GENSTATS_COUNT4_GET_PPIF_VPATH_GENSTATS_COUNT4(
-		val64);
-
-	val64 = readq(&vp_reg->vpath_genstats_count5);
-	hw_stats->vpath_genstats_count5 =
-	(u32)VXGE_HW_VPATH_GENSTATS_COUNT5_GET_PPIF_VPATH_GENSTATS_COUNT5(
-		val64);
-
-	status = __vxge_hw_vpath_xmac_tx_stats_get(vpath, &hw_stats->tx_stats);
-	if (status != VXGE_HW_OK)
-		goto exit;
-
-	status = __vxge_hw_vpath_xmac_rx_stats_get(vpath, &hw_stats->rx_stats);
-	if (status != VXGE_HW_OK)
-		goto exit;
-
-	VXGE_HW_VPATH_STATS_PIO_READ(
-		VXGE_HW_STATS_VPATH_PROG_EVENT_VNUM0_OFFSET);
-
-	hw_stats->prog_event_vnum0 =
-			(u32)VXGE_HW_STATS_GET_VPATH_PROG_EVENT_VNUM0(val64);
-
-	hw_stats->prog_event_vnum1 =
-			(u32)VXGE_HW_STATS_GET_VPATH_PROG_EVENT_VNUM1(val64);
-
-	VXGE_HW_VPATH_STATS_PIO_READ(
-		VXGE_HW_STATS_VPATH_PROG_EVENT_VNUM2_OFFSET);
-
-	hw_stats->prog_event_vnum2 =
-			(u32)VXGE_HW_STATS_GET_VPATH_PROG_EVENT_VNUM2(val64);
-
-	hw_stats->prog_event_vnum3 =
-			(u32)VXGE_HW_STATS_GET_VPATH_PROG_EVENT_VNUM3(val64);
-
-	val64 = readq(&vp_reg->rx_multi_cast_stats);
-	hw_stats->rx_multi_cast_frame_discard =
-		(u16)VXGE_HW_RX_MULTI_CAST_STATS_GET_FRAME_DISCARD(val64);
-
-	val64 = readq(&vp_reg->rx_frm_transferred);
-	hw_stats->rx_frm_transferred =
-		(u32)VXGE_HW_RX_FRM_TRANSFERRED_GET_RX_FRM_TRANSFERRED(val64);
-
-	val64 = readq(&vp_reg->rxd_returned);
-	hw_stats->rxd_returned =
-		(u16)VXGE_HW_RXD_RETURNED_GET_RXD_RETURNED(val64);
-
-	val64 = readq(&vp_reg->dbg_stats_rx_mpa);
-	hw_stats->rx_mpa_len_fail_frms =
-		(u16)VXGE_HW_DBG_STATS_GET_RX_MPA_LEN_FAIL_FRMS(val64);
-	hw_stats->rx_mpa_mrk_fail_frms =
-		(u16)VXGE_HW_DBG_STATS_GET_RX_MPA_MRK_FAIL_FRMS(val64);
-	hw_stats->rx_mpa_crc_fail_frms =
-		(u16)VXGE_HW_DBG_STATS_GET_RX_MPA_CRC_FAIL_FRMS(val64);
-
-	val64 = readq(&vp_reg->dbg_stats_rx_fau);
-	hw_stats->rx_permitted_frms =
-		(u16)VXGE_HW_DBG_STATS_GET_RX_FAU_RX_PERMITTED_FRMS(val64);
-	hw_stats->rx_vp_reset_discarded_frms =
-	(u16)VXGE_HW_DBG_STATS_GET_RX_FAU_RX_VP_RESET_DISCARDED_FRMS(val64);
-	hw_stats->rx_wol_frms =
-		(u16)VXGE_HW_DBG_STATS_GET_RX_FAU_RX_WOL_FRMS(val64);
-
-	val64 = readq(&vp_reg->tx_vp_reset_discarded_frms);
-	hw_stats->tx_vp_reset_discarded_frms =
-	(u16)VXGE_HW_TX_VP_RESET_DISCARDED_FRMS_GET_TX_VP_RESET_DISCARDED_FRMS(
-		val64);
-exit:
-	return status;
-}
-
-
-static void vxge_os_dma_malloc_async(struct pci_dev *pdev, void *devh,
-					unsigned long size)
-{
-	gfp_t flags;
-	void *vaddr;
-
-	if (in_interrupt())
-		flags = GFP_ATOMIC | GFP_DMA;
-	else
-		flags = GFP_KERNEL | GFP_DMA;
-
-	vaddr = kmalloc((size), flags);
-
-	vxge_hw_blockpool_block_add(devh, vaddr, size, pdev, pdev);
-}
-
-static void vxge_os_dma_free(struct pci_dev *pdev, const void *vaddr,
-			     struct pci_dev **p_dma_acch)
-{
-	unsigned long misaligned = *(unsigned long *)p_dma_acch;
-	u8 *tmp = (u8 *)vaddr;
-	tmp -= misaligned;
-	kfree((void *)tmp);
-}
-
-/*
- * __vxge_hw_blockpool_create - Create block pool
- */
-
-enum vxge_hw_status
-__vxge_hw_blockpool_create(struct __vxge_hw_device *hldev,
-			   struct __vxge_hw_blockpool *blockpool,
-			   u32 pool_size,
-			   u32 pool_max)
-{
-	u32 i;
-	struct __vxge_hw_blockpool_entry *entry = NULL;
-	void *memblock;
-	dma_addr_t dma_addr;
-	struct pci_dev *dma_handle;
-	struct pci_dev *acc_handle;
-	enum vxge_hw_status status = VXGE_HW_OK;
-
-	if (blockpool == NULL) {
-		status = VXGE_HW_FAIL;
-		goto blockpool_create_exit;
-	}
-
-	blockpool->hldev = hldev;
-	blockpool->block_size = VXGE_HW_BLOCK_SIZE;
-	blockpool->pool_size = 0;
-	blockpool->pool_max = pool_max;
-	blockpool->req_out = 0;
-
-	INIT_LIST_HEAD(&blockpool->free_block_list);
-	INIT_LIST_HEAD(&blockpool->free_entry_list);
-
-	for (i = 0; i < pool_size + pool_max; i++) {
-		entry = kzalloc(sizeof(struct __vxge_hw_blockpool_entry),
-				GFP_KERNEL);
-		if (entry == NULL) {
-			__vxge_hw_blockpool_destroy(blockpool);
-			status = VXGE_HW_ERR_OUT_OF_MEMORY;
-			goto blockpool_create_exit;
-		}
-		list_add(&entry->item, &blockpool->free_entry_list);
-	}
-
-	for (i = 0; i < pool_size; i++) {
-
-		memblock = vxge_os_dma_malloc(
-				hldev->pdev,
-				VXGE_HW_BLOCK_SIZE,
-				&dma_handle,
-				&acc_handle);
-
-		if (memblock == NULL) {
-			__vxge_hw_blockpool_destroy(blockpool);
-			status = VXGE_HW_ERR_OUT_OF_MEMORY;
-			goto blockpool_create_exit;
-		}
-
-		dma_addr = pci_map_single(hldev->pdev, memblock,
-				VXGE_HW_BLOCK_SIZE, PCI_DMA_BIDIRECTIONAL);
-
-		if (unlikely(pci_dma_mapping_error(hldev->pdev,
-				dma_addr))) {
-
-			vxge_os_dma_free(hldev->pdev, memblock, &acc_handle);
-			__vxge_hw_blockpool_destroy(blockpool);
-			status = VXGE_HW_ERR_OUT_OF_MEMORY;
-			goto blockpool_create_exit;
-		}
-
-		if (!list_empty(&blockpool->free_entry_list))
-			entry = (struct __vxge_hw_blockpool_entry *)
-				list_first_entry(&blockpool->free_entry_list,
-					struct __vxge_hw_blockpool_entry,
-					item);
-
-		if (entry == NULL)
-			entry =
-			    kzalloc(sizeof(struct __vxge_hw_blockpool_entry),
-					GFP_KERNEL);
-		if (entry != NULL) {
-			list_del(&entry->item);
-			entry->length = VXGE_HW_BLOCK_SIZE;
-			entry->memblock = memblock;
-			entry->dma_addr = dma_addr;
-			entry->acc_handle = acc_handle;
-			entry->dma_handle = dma_handle;
-			list_add(&entry->item,
-					  &blockpool->free_block_list);
-			blockpool->pool_size++;
-		} else {
-			__vxge_hw_blockpool_destroy(blockpool);
-			status = VXGE_HW_ERR_OUT_OF_MEMORY;
-			goto blockpool_create_exit;
-		}
-	}
-
-blockpool_create_exit:
-	return status;
-}
-
-/*
- * __vxge_hw_blockpool_destroy - Deallocates the block pool
- */
-
-void __vxge_hw_blockpool_destroy(struct __vxge_hw_blockpool *blockpool)
-{
-
-	struct __vxge_hw_device *hldev;
-	struct list_head *p, *n;
-	u16 ret;
-
-	if (blockpool == NULL) {
-		ret = 1;
-		goto exit;
-	}
-
-	hldev = blockpool->hldev;
-
-	list_for_each_safe(p, n, &blockpool->free_block_list) {
-
-		pci_unmap_single(hldev->pdev,
-			((struct __vxge_hw_blockpool_entry *)p)->dma_addr,
-			((struct __vxge_hw_blockpool_entry *)p)->length,
-			PCI_DMA_BIDIRECTIONAL);
-
-		vxge_os_dma_free(hldev->pdev,
-			((struct __vxge_hw_blockpool_entry *)p)->memblock,
-			&((struct __vxge_hw_blockpool_entry *) p)->acc_handle);
-
-		list_del(
-			&((struct __vxge_hw_blockpool_entry *)p)->item);
-		kfree(p);
-		blockpool->pool_size--;
-	}
-
-	list_for_each_safe(p, n, &blockpool->free_entry_list) {
-		list_del(
-			&((struct __vxge_hw_blockpool_entry *)p)->item);
-		kfree((void *)p);
-	}
-	ret = 0;
-exit:
-	return;
-}
-
-/*
- * __vxge_hw_blockpool_blocks_add - Request additional blocks
- */
-static
-void __vxge_hw_blockpool_blocks_add(struct __vxge_hw_blockpool *blockpool)
-{
-	u32 nreq = 0, i;
-
-	if ((blockpool->pool_size  +  blockpool->req_out) <
-		VXGE_HW_MIN_DMA_BLOCK_POOL_SIZE) {
-		nreq = VXGE_HW_INCR_DMA_BLOCK_POOL_SIZE;
-		blockpool->req_out += nreq;
-	}
-
-	for (i = 0; i < nreq; i++)
-		vxge_os_dma_malloc_async(
-			((struct __vxge_hw_device *)blockpool->hldev)->pdev,
-			blockpool->hldev, VXGE_HW_BLOCK_SIZE);
-}
-
-/*
- * __vxge_hw_blockpool_blocks_remove - Free additional blocks
- */
-static
-void __vxge_hw_blockpool_blocks_remove(struct __vxge_hw_blockpool *blockpool)
-{
-	struct list_head *p, *n;
-
-	list_for_each_safe(p, n, &blockpool->free_block_list) {
-
-		if (blockpool->pool_size < blockpool->pool_max)
-			break;
-
-		pci_unmap_single(
-			((struct __vxge_hw_device *)blockpool->hldev)->pdev,
-			((struct __vxge_hw_blockpool_entry *)p)->dma_addr,
-			((struct __vxge_hw_blockpool_entry *)p)->length,
-			PCI_DMA_BIDIRECTIONAL);
-
-		vxge_os_dma_free(
-			((struct __vxge_hw_device *)blockpool->hldev)->pdev,
-			((struct __vxge_hw_blockpool_entry *)p)->memblock,
-			&((struct __vxge_hw_blockpool_entry *)p)->acc_handle);
-
-		list_del(&((struct __vxge_hw_blockpool_entry *)p)->item);
-
-		list_add(p, &blockpool->free_entry_list);
-
-		blockpool->pool_size--;
-
-	}
-}
-
-/*
- * vxge_hw_blockpool_block_add - callback for vxge_os_dma_malloc_async
- * Adds a block to block pool
- */
-static void vxge_hw_blockpool_block_add(struct __vxge_hw_device *devh,
-					void *block_addr,
-					u32 length,
-					struct pci_dev *dma_h,
-					struct pci_dev *acc_handle)
-{
-	struct __vxge_hw_blockpool  *blockpool;
-	struct __vxge_hw_blockpool_entry  *entry = NULL;
-	dma_addr_t dma_addr;
-	enum vxge_hw_status status = VXGE_HW_OK;
-	u32 req_out;
-
-	blockpool = &devh->block_pool;
-
-	if (block_addr == NULL) {
-		blockpool->req_out--;
-		status = VXGE_HW_FAIL;
-		goto exit;
-	}
-
-	dma_addr = pci_map_single(devh->pdev, block_addr, length,
-				PCI_DMA_BIDIRECTIONAL);
-
-	if (unlikely(pci_dma_mapping_error(devh->pdev, dma_addr))) {
-
-		vxge_os_dma_free(devh->pdev, block_addr, &acc_handle);
-		blockpool->req_out--;
-		status = VXGE_HW_FAIL;
-		goto exit;
-	}
-
-
-	if (!list_empty(&blockpool->free_entry_list))
-		entry = (struct __vxge_hw_blockpool_entry *)
-			list_first_entry(&blockpool->free_entry_list,
-				struct __vxge_hw_blockpool_entry,
-				item);
-
-	if (entry == NULL)
-		entry = (struct __vxge_hw_blockpool_entry *)
-			vmalloc(sizeof(struct __vxge_hw_blockpool_entry));
-	else
-		list_del(&entry->item);
-
-	if (entry != NULL) {
-		entry->length = length;
-		entry->memblock = block_addr;
-		entry->dma_addr = dma_addr;
-		entry->acc_handle = acc_handle;
-		entry->dma_handle = dma_h;
-		list_add(&entry->item, &blockpool->free_block_list);
-		blockpool->pool_size++;
-		status = VXGE_HW_OK;
-	} else
-		status = VXGE_HW_ERR_OUT_OF_MEMORY;
-
-	blockpool->req_out--;
-
-	req_out = blockpool->req_out;
-exit:
-	return;
-}
-
-/*
- * __vxge_hw_blockpool_malloc - Allocate a memory block from pool
- * Allocates a block of memory of given size, either from block pool
- * or by calling vxge_os_dma_malloc()
- */
-void *
-__vxge_hw_blockpool_malloc(struct __vxge_hw_device *devh, u32 size,
-				struct vxge_hw_mempool_dma *dma_object)
-{
-	struct __vxge_hw_blockpool_entry *entry = NULL;
-	struct __vxge_hw_blockpool  *blockpool;
-	void *memblock = NULL;
-	enum vxge_hw_status status = VXGE_HW_OK;
-
-	blockpool = &devh->block_pool;
-
-	if (size != blockpool->block_size) {
-
-		memblock = vxge_os_dma_malloc(devh->pdev, size,
-						&dma_object->handle,
-						&dma_object->acc_handle);
-
-		if (memblock == NULL) {
-			status = VXGE_HW_ERR_OUT_OF_MEMORY;
-			goto exit;
-		}
-
-		dma_object->addr = pci_map_single(devh->pdev, memblock, size,
-					PCI_DMA_BIDIRECTIONAL);
-
-		if (unlikely(pci_dma_mapping_error(devh->pdev,
-				dma_object->addr))) {
-			vxge_os_dma_free(devh->pdev, memblock,
-				&dma_object->acc_handle);
-			status = VXGE_HW_ERR_OUT_OF_MEMORY;
-			goto exit;
-		}
-
-	} else {
-
-		if (!list_empty(&blockpool->free_block_list))
-			entry = (struct __vxge_hw_blockpool_entry *)
-				list_first_entry(&blockpool->free_block_list,
-					struct __vxge_hw_blockpool_entry,
-					item);
-
-		if (entry != NULL) {
-			list_del(&entry->item);
-			dma_object->addr = entry->dma_addr;
-			dma_object->handle = entry->dma_handle;
-			dma_object->acc_handle = entry->acc_handle;
-			memblock = entry->memblock;
-
-			list_add(&entry->item,
-				&blockpool->free_entry_list);
-			blockpool->pool_size--;
-		}
-
-		if (memblock != NULL)
-			__vxge_hw_blockpool_blocks_add(blockpool);
-	}
-exit:
-	return memblock;
-}
-
-/*
- * __vxge_hw_blockpool_free - Frees the memory allcoated with
-				__vxge_hw_blockpool_malloc
- */
-void
-__vxge_hw_blockpool_free(struct __vxge_hw_device *devh,
-			void *memblock, u32 size,
-			struct vxge_hw_mempool_dma *dma_object)
-{
-	struct __vxge_hw_blockpool_entry *entry = NULL;
-	struct __vxge_hw_blockpool  *blockpool;
-	enum vxge_hw_status status = VXGE_HW_OK;
-
-	blockpool = &devh->block_pool;
-
-	if (size != blockpool->block_size) {
-		pci_unmap_single(devh->pdev, dma_object->addr, size,
-			PCI_DMA_BIDIRECTIONAL);
-		vxge_os_dma_free(devh->pdev, memblock, &dma_object->acc_handle);
-	} else {
-
-		if (!list_empty(&blockpool->free_entry_list))
-			entry = (struct __vxge_hw_blockpool_entry *)
-				list_first_entry(&blockpool->free_entry_list,
-					struct __vxge_hw_blockpool_entry,
-					item);
-
-		if (entry == NULL)
-			entry = (struct __vxge_hw_blockpool_entry *)
-				vmalloc(sizeof(
-					struct __vxge_hw_blockpool_entry));
-		else
-			list_del(&entry->item);
-
-		if (entry != NULL) {
-			entry->length = size;
-			entry->memblock = memblock;
-			entry->dma_addr = dma_object->addr;
-			entry->acc_handle = dma_object->acc_handle;
-			entry->dma_handle = dma_object->handle;
-			list_add(&entry->item,
-					&blockpool->free_block_list);
-			blockpool->pool_size++;
-			status = VXGE_HW_OK;
-		} else
-			status = VXGE_HW_ERR_OUT_OF_MEMORY;
-
-		if (status == VXGE_HW_OK)
-			__vxge_hw_blockpool_blocks_remove(blockpool);
-	}
-}
-
-/*
- * __vxge_hw_blockpool_block_allocate - Allocates a block from block pool
- * This function allocates a block from block pool or from the system
- */
-struct __vxge_hw_blockpool_entry *
-__vxge_hw_blockpool_block_allocate(struct __vxge_hw_device *devh, u32 size)
-{
-	struct __vxge_hw_blockpool_entry *entry = NULL;
-	struct __vxge_hw_blockpool  *blockpool;
-
-	blockpool = &devh->block_pool;
-
-	if (size == blockpool->block_size) {
-
-		if (!list_empty(&blockpool->free_block_list))
-			entry = (struct __vxge_hw_blockpool_entry *)
-				list_first_entry(&blockpool->free_block_list,
-					struct __vxge_hw_blockpool_entry,
-					item);
-
-		if (entry != NULL) {
-			list_del(&entry->item);
-			blockpool->pool_size--;
-		}
-	}
-
-	if (entry != NULL)
-		__vxge_hw_blockpool_blocks_add(blockpool);
-
-	return entry;
-}
-
-/*
- * __vxge_hw_blockpool_block_free - Frees a block from block pool
- * @devh: Hal device
- * @entry: Entry of block to be freed
- *
- * This function frees a block from block pool
- */
-void
-__vxge_hw_blockpool_block_free(struct __vxge_hw_device *devh,
-			struct __vxge_hw_blockpool_entry *entry)
-{
-	struct __vxge_hw_blockpool  *blockpool;
-
-	blockpool = &devh->block_pool;
-
-	if (entry->length == blockpool->block_size) {
-		list_add(&entry->item, &blockpool->free_block_list);
-		blockpool->pool_size++;
-	}
-
-	__vxge_hw_blockpool_blocks_remove(blockpool);
-}
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/vxge/vxge-config.h linux-libre-2.6.38-gnu1/drivers/net/vxge/vxge-config.h
--- linux-libre-2.6.37-gnu1/drivers/net/vxge/vxge-config.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/vxge/vxge-config.h	2011-03-14 21:20:32.000000000 -0400
@@ -20,13 +20,6 @@
 #define VXGE_CACHE_LINE_SIZE 128
 #endif
 
-#define vxge_os_vaprintf(level, mask, fmt, ...) { \
-	char buff[255]; \
-		snprintf(buff, 255, fmt, __VA_ARGS__); \
-		printk(buff); \
-		printk("\n"); \
-}
-
 #ifndef VXGE_ALIGN
 #define VXGE_ALIGN(adrs, size) \
 	(((size) - (((u64)adrs) & ((size)-1))) & ((size)-1))
@@ -36,8 +29,16 @@
 #define VXGE_HW_MAX_MTU				9600
 #define VXGE_HW_DEFAULT_MTU			1500
 
-#ifdef VXGE_DEBUG_ASSERT
+#define VXGE_HW_MAX_ROM_IMAGES			8
+
+struct eprom_image {
+	u8 is_valid:1;
+	u8 index;
+	u8 type;
+	u16 version;
+};
 
+#ifdef VXGE_DEBUG_ASSERT
 /**
  * vxge_assert
  * @test: C-condition to check
@@ -48,16 +49,13 @@
  * compilation
  * time.
  */
-#define vxge_assert(test) { \
-	if (!(test)) \
-		vxge_os_bug("bad cond: "#test" at %s:%d\n", \
-				__FILE__, __LINE__); }
+#define vxge_assert(test) BUG_ON(!(test))
 #else
 #define vxge_assert(test)
 #endif /* end of VXGE_DEBUG_ASSERT */
 
 /**
- * enum enum vxge_debug_level
+ * enum vxge_debug_level
  * @VXGE_NONE: debug disabled
  * @VXGE_ERR: all errors going to be logged out
  * @VXGE_TRACE: all errors plus all kind of verbose tracing print outs
@@ -159,6 +157,47 @@ enum vxge_hw_device_link_state {
 };
 
 /**
+ * enum enum vxge_hw_fw_upgrade_code - FW upgrade return codes.
+ * @VXGE_HW_FW_UPGRADE_OK: All OK send next 16 bytes
+ * @VXGE_HW_FW_UPGRADE_DONE:  upload completed
+ * @VXGE_HW_FW_UPGRADE_ERR:  upload error
+ * @VXGE_FW_UPGRADE_BYTES2SKIP:  skip bytes in the stream
+ *
+ */
+enum vxge_hw_fw_upgrade_code {
+	VXGE_HW_FW_UPGRADE_OK		= 0,
+	VXGE_HW_FW_UPGRADE_DONE		= 1,
+	VXGE_HW_FW_UPGRADE_ERR		= 2,
+	VXGE_FW_UPGRADE_BYTES2SKIP	= 3
+};
+
+/**
+ * enum enum vxge_hw_fw_upgrade_err_code - FW upgrade error codes.
+ * @VXGE_HW_FW_UPGRADE_ERR_CORRUPT_DATA_1: corrupt data
+ * @VXGE_HW_FW_UPGRADE_ERR_BUFFER_OVERFLOW: buffer overflow
+ * @VXGE_HW_FW_UPGRADE_ERR_INV_NCF_FILE_3: invalid .ncf file
+ * @VXGE_HW_FW_UPGRADE_ERR_INV_NCF_FILE_4: invalid .ncf file
+ * @VXGE_HW_FW_UPGRADE_ERR_INV_NCF_FILE_5: invalid .ncf file
+ * @VXGE_HW_FW_UPGRADE_ERR_INV_NCF_FILE_6: invalid .ncf file
+ * @VXGE_HW_FW_UPGRADE_ERR_CORRUPT_DATA_7: corrupt data
+ * @VXGE_HW_FW_UPGRADE_ERR_INV_NCF_FILE_8: invalid .ncf file
+ * @VXGE_HW_FW_UPGRADE_ERR_GENERIC_ERROR_UNKNOWN: generic error unknown type
+ * @VXGE_HW_FW_UPGRADE_ERR_FAILED_TO_FLASH: failed to flash image check failed
+ */
+enum vxge_hw_fw_upgrade_err_code {
+	VXGE_HW_FW_UPGRADE_ERR_CORRUPT_DATA_1		= 1,
+	VXGE_HW_FW_UPGRADE_ERR_BUFFER_OVERFLOW		= 2,
+	VXGE_HW_FW_UPGRADE_ERR_INV_NCF_FILE_3		= 3,
+	VXGE_HW_FW_UPGRADE_ERR_INV_NCF_FILE_4		= 4,
+	VXGE_HW_FW_UPGRADE_ERR_INV_NCF_FILE_5		= 5,
+	VXGE_HW_FW_UPGRADE_ERR_INV_NCF_FILE_6		= 6,
+	VXGE_HW_FW_UPGRADE_ERR_CORRUPT_DATA_7		= 7,
+	VXGE_HW_FW_UPGRADE_ERR_INV_NCF_FILE_8		= 8,
+	VXGE_HW_FW_UPGRADE_ERR_GENERIC_ERROR_UNKNOWN	= 9,
+	VXGE_HW_FW_UPGRADE_ERR_FAILED_TO_FLASH		= 10
+};
+
+/**
  * struct vxge_hw_device_date - Date Format
  * @day: Day
  * @month: Month
@@ -275,9 +314,9 @@ struct vxge_hw_ring_config {
 #define VXGE_HW_RING_DEFAULT					1
 
 	u32				ring_blocks;
-#define VXGE_HW_MIN_RING_BLOCKS				1
-#define VXGE_HW_MAX_RING_BLOCKS				128
-#define VXGE_HW_DEF_RING_BLOCKS				2
+#define VXGE_HW_MIN_RING_BLOCKS					1
+#define VXGE_HW_MAX_RING_BLOCKS					128
+#define VXGE_HW_DEF_RING_BLOCKS					2
 
 	u32				buffer_mode;
 #define VXGE_HW_RING_RXD_BUFFER_MODE_1				1
@@ -465,7 +504,6 @@ struct vxge_hw_device_config {
  * See also: vxge_hw_driver_initialize().
  */
 struct vxge_hw_uld_cbs {
-
 	void (*link_up)(struct __vxge_hw_device *devh);
 	void (*link_down)(struct __vxge_hw_device *devh);
 	void (*crit_err)(struct __vxge_hw_device *devh,
@@ -652,6 +690,7 @@ struct __vxge_hw_virtualpath {
 	struct vxge_hw_vpath_stats_hw_info	*hw_stats;
 	struct vxge_hw_vpath_stats_hw_info	*hw_stats_sav;
 	struct vxge_hw_vpath_stats_sw_info	*sw_stats;
+	spinlock_t lock;
 };
 
 /*
@@ -661,7 +700,7 @@ struct __vxge_hw_virtualpath {
  *
  * This structure is used to store the callback information.
  */
-struct __vxge_hw_vpath_handle{
+struct __vxge_hw_vpath_handle {
 	struct list_head	item;
 	struct __vxge_hw_virtualpath	*vpath;
 };
@@ -674,9 +713,6 @@ struct __vxge_hw_vpath_handle{
 /**
  * struct __vxge_hw_device  - Hal device object
  * @magic: Magic Number
- * @device_id: PCI Device Id of the adapter
- * @major_revision: PCI Device major revision
- * @minor_revision: PCI Device minor revision
  * @bar0: BAR0 virtual address.
  * @pdev: Physical device handle
  * @config: Confguration passed by the LL driver at initialization
@@ -688,9 +724,6 @@ struct __vxge_hw_device {
 	u32				magic;
 #define VXGE_HW_DEVICE_MAGIC		0x12345678
 #define VXGE_HW_DEVICE_DEAD		0xDEADDEAD
-	u16				device_id;
-	u8				major_revision;
-	u8				minor_revision;
 	void __iomem			*bar0;
 	struct pci_dev			*pdev;
 	struct net_device		*ndev;
@@ -731,6 +764,7 @@ struct __vxge_hw_device {
 	u32				debug_level;
 	u32				level_err;
 	u32				level_trace;
+	u16 eprom_versions[VXGE_HW_MAX_ROM_IMAGES];
 };
 
 #define VXGE_HW_INFO_LEN	64
@@ -781,8 +815,8 @@ struct vxge_hw_device_hw_info {
 	u8		serial_number[VXGE_HW_INFO_LEN];
 	u8		part_number[VXGE_HW_INFO_LEN];
 	u8		product_desc[VXGE_HW_INFO_LEN];
-	u8 (mac_addrs)[VXGE_HW_MAX_VIRTUAL_PATHS][ETH_ALEN];
-	u8 (mac_addr_masks)[VXGE_HW_MAX_VIRTUAL_PATHS][ETH_ALEN];
+	u8 mac_addrs[VXGE_HW_MAX_VIRTUAL_PATHS][ETH_ALEN];
+	u8 mac_addr_masks[VXGE_HW_MAX_VIRTUAL_PATHS][ETH_ALEN];
 };
 
 /**
@@ -829,20 +863,10 @@ struct vxge_hw_device_attr {
 				loc, \
 				offset, \
 				&val64);			\
-								\
 	if (status != VXGE_HW_OK)				\
 		return status;						\
 }
 
-#define VXGE_HW_VPATH_STATS_PIO_READ(offset) {				\
-	status = __vxge_hw_vpath_stats_access(vpath, \
-			VXGE_HW_STATS_OP_READ, \
-			offset, \
-			&val64);					\
-	if (status != VXGE_HW_OK)					\
-		return status;						\
-}
-
 /*
  * struct __vxge_hw_ring - Ring channel.
  * @channel: Channel "base" of this ring, the common part of all HW
@@ -1114,7 +1138,7 @@ struct __vxge_hw_non_offload_db_wrapper
  *             lookup to determine the transmit port.
  *             01: Send on physical Port1.
  *             10: Send on physical Port0.
-	*	       11: Send on both ports.
+ *	       11: Send on both ports.
  *             Bits 18 to 21 - Reserved
  *             Bits 22 to 23 - Gather_Code. This field is set by the host and
  *             is used to describe how individual buffers comprise a frame.
@@ -1413,12 +1437,12 @@ enum vxge_hw_rth_algoritms {
  * See also: vxge_hw_vpath_rts_rth_set(), vxge_hw_vpath_rts_rth_get().
  */
 struct vxge_hw_rth_hash_types {
-	u8 hash_type_tcpipv4_en;
-	u8 hash_type_ipv4_en;
-	u8 hash_type_tcpipv6_en;
-	u8 hash_type_ipv6_en;
-	u8 hash_type_tcpipv6ex_en;
-	u8 hash_type_ipv6ex_en;
+	u8 hash_type_tcpipv4_en:1,
+	   hash_type_ipv4_en:1,
+	   hash_type_tcpipv6_en:1,
+	   hash_type_ipv6_en:1,
+	   hash_type_tcpipv6ex_en:1,
+	   hash_type_ipv6ex_en:1;
 };
 
 void vxge_hw_device_debug_set(
@@ -1893,6 +1917,15 @@ out:
 	return vaddr;
 }
 
+static inline void vxge_os_dma_free(struct pci_dev *pdev, const void *vaddr,
+			struct pci_dev **p_dma_acch)
+{
+	unsigned long misaligned = *(unsigned long *)p_dma_acch;
+	u8 *tmp = (u8 *)vaddr;
+	tmp -= misaligned;
+	kfree((void *)tmp);
+}
+
 /*
  * __vxge_hw_mempool_item_priv - will return pointer on per item private space
  */
@@ -1962,7 +1995,6 @@ enum vxge_hw_status vxge_hw_vpath_mtu_se
 void
 vxge_hw_vpath_rx_doorbell_init(struct __vxge_hw_vpath_handle *vp);
 
-
 #ifndef readq
 static inline u64 readq(void __iomem *addr)
 {
@@ -2000,7 +2032,7 @@ enum vxge_hw_status
 vxge_hw_vpath_strip_fcs_check(struct __vxge_hw_device *hldev, u64 vpath_mask);
 
 /**
- * vxge_debug
+ * vxge_debug_ll
  * @level: level of debug verbosity.
  * @mask: mask for the debug
  * @buf: Circular buffer for tracing
@@ -2012,26 +2044,13 @@ vxge_hw_vpath_strip_fcs_check(struct __v
  * may be compiled out if DEBUG macro was never defined.
  * See also: enum vxge_debug_level{}.
  */
-
-#define vxge_trace_aux(level, mask, fmt, ...) \
-{\
-		vxge_os_vaprintf(level, mask, fmt, __VA_ARGS__);\
-}
-
-#define vxge_debug(module, level, mask, fmt, ...) { \
-if ((level >= VXGE_TRACE && ((module & VXGE_DEBUG_TRACE_MASK) == module)) || \
-	(level >= VXGE_ERR && ((module & VXGE_DEBUG_ERR_MASK) == module))) {\
-	if ((mask & VXGE_DEBUG_MASK) == mask)\
-		vxge_trace_aux(level, mask, fmt, __VA_ARGS__); \
-} \
-}
-
 #if (VXGE_COMPONENT_LL & VXGE_DEBUG_MODULE_MASK)
-#define vxge_debug_ll(level, mask, fmt, ...) \
-{\
-	vxge_debug(VXGE_COMPONENT_LL, level, mask, fmt, __VA_ARGS__);\
-}
-
+#define vxge_debug_ll(level, mask, fmt, ...) do {			       \
+	if ((level >= VXGE_ERR && VXGE_COMPONENT_LL & VXGE_DEBUG_ERR_MASK) ||  \
+	    (level >= VXGE_TRACE && VXGE_COMPONENT_LL & VXGE_DEBUG_TRACE_MASK))\
+		if ((mask & VXGE_DEBUG_MASK) == mask)			       \
+			printk(fmt "\n", __VA_ARGS__);			       \
+} while (0)
 #else
 #define vxge_debug_ll(level, mask, fmt, ...)
 #endif
@@ -2051,4 +2070,26 @@ enum vxge_hw_status vxge_hw_vpath_rts_rt
 
 enum vxge_hw_status
 __vxge_hw_device_is_privilaged(u32 host_type, u32 func_id);
+
+#define VXGE_HW_MIN_SUCCESSIVE_IDLE_COUNT 5
+#define VXGE_HW_MAX_POLLING_COUNT 100
+
+void
+vxge_hw_device_wait_receive_idle(struct __vxge_hw_device *hldev);
+
+enum vxge_hw_status
+vxge_hw_upgrade_read_version(struct __vxge_hw_device *hldev, u32 *major,
+			     u32 *minor, u32 *build);
+
+enum vxge_hw_status vxge_hw_flash_fw(struct __vxge_hw_device *hldev);
+
+enum vxge_hw_status
+vxge_update_fw_image(struct __vxge_hw_device *hldev, const u8 *filebuf,
+		     int size);
+
+enum vxge_hw_status
+vxge_hw_vpath_eprom_img_ver_get(struct __vxge_hw_device *hldev,
+				struct eprom_image *eprom_image_data);
+
+int vxge_hw_vpath_wait_receive_idle(struct __vxge_hw_device *hldev, u32 vp_id);
 #endif
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/vxge/vxge-ethtool.c linux-libre-2.6.38-gnu1/drivers/net/vxge/vxge-ethtool.c
--- linux-libre-2.6.37-gnu1/drivers/net/vxge/vxge-ethtool.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/vxge/vxge-ethtool.c	2011-03-14 21:20:32.000000000 -0400
@@ -11,7 +11,7 @@
  *                 Virtualized Server Adapter.
  * Copyright(c) 2002-2010 Exar Corp.
  ******************************************************************************/
-#include<linux/ethtool.h>
+#include <linux/ethtool.h>
 #include <linux/slab.h>
 #include <linux/pci.h>
 #include <linux/etherdevice.h>
@@ -29,7 +29,6 @@
  * Return value:
  * 0 on success.
  */
-
 static int vxge_ethtool_sset(struct net_device *dev, struct ethtool_cmd *info)
 {
 	/* We currently only support 10Gb/FULL */
@@ -79,10 +78,9 @@ static int vxge_ethtool_gset(struct net_
  * Returns driver specefic information like name, version etc.. to ethtool.
  */
 static void vxge_ethtool_gdrvinfo(struct net_device *dev,
-			struct ethtool_drvinfo *info)
+				  struct ethtool_drvinfo *info)
 {
-	struct vxgedev *vdev;
-	vdev = (struct vxgedev *)netdev_priv(dev);
+	struct vxgedev *vdev = netdev_priv(dev);
 	strlcpy(info->driver, VXGE_DRIVER_NAME, sizeof(VXGE_DRIVER_NAME));
 	strlcpy(info->version, DRV_VERSION, sizeof(DRV_VERSION));
 	strlcpy(info->fw_version, vdev->fw_version, VXGE_HW_FW_STRLEN);
@@ -104,15 +102,14 @@ static void vxge_ethtool_gdrvinfo(struct
  * buffer area.
  */
 static void vxge_ethtool_gregs(struct net_device *dev,
-			struct ethtool_regs *regs, void *space)
+			       struct ethtool_regs *regs, void *space)
 {
 	int index, offset;
 	enum vxge_hw_status status;
 	u64 reg;
-	u64 *reg_space = (u64 *) space;
-	struct vxgedev *vdev = (struct vxgedev *)netdev_priv(dev);
-	struct __vxge_hw_device  *hldev = (struct __vxge_hw_device *)
-					pci_get_drvdata(vdev->pdev);
+	u64 *reg_space = (u64 *)space;
+	struct vxgedev *vdev = netdev_priv(dev);
+	struct __vxge_hw_device *hldev = vdev->devh;
 
 	regs->len = sizeof(struct vxge_hw_vpath_reg) * vdev->no_of_vpath;
 	regs->version = vdev->pdev->subsystem_device;
@@ -147,9 +144,8 @@ static void vxge_ethtool_gregs(struct ne
  */
 static int vxge_ethtool_idnic(struct net_device *dev, u32 data)
 {
-	struct vxgedev *vdev = (struct vxgedev *)netdev_priv(dev);
-	struct __vxge_hw_device  *hldev = (struct __vxge_hw_device  *)
-			pci_get_drvdata(vdev->pdev);
+	struct vxgedev *vdev = netdev_priv(dev);
+	struct __vxge_hw_device *hldev = vdev->devh;
 
 	vxge_hw_device_flick_link_led(hldev, VXGE_FLICKER_ON);
 	msleep_interruptible(data ? (data * HZ) : VXGE_MAX_FLICKER_TIME);
@@ -168,11 +164,10 @@ static int vxge_ethtool_idnic(struct net
  *  void
  */
 static void vxge_ethtool_getpause_data(struct net_device *dev,
-					struct ethtool_pauseparam *ep)
+				       struct ethtool_pauseparam *ep)
 {
-	struct vxgedev *vdev = (struct vxgedev *)netdev_priv(dev);
-	struct __vxge_hw_device  *hldev = (struct __vxge_hw_device  *)
-			pci_get_drvdata(vdev->pdev);
+	struct vxgedev *vdev = netdev_priv(dev);
+	struct __vxge_hw_device *hldev = vdev->devh;
 
 	vxge_hw_device_getpause_data(hldev, 0, &ep->tx_pause, &ep->rx_pause);
 }
@@ -188,11 +183,10 @@ static void vxge_ethtool_getpause_data(s
  * int, returns 0 on Success
  */
 static int vxge_ethtool_setpause_data(struct net_device *dev,
-					struct ethtool_pauseparam *ep)
+				      struct ethtool_pauseparam *ep)
 {
-	struct vxgedev *vdev = (struct vxgedev *)netdev_priv(dev);
-	struct __vxge_hw_device  *hldev = (struct __vxge_hw_device  *)
-			pci_get_drvdata(vdev->pdev);
+	struct vxgedev *vdev = netdev_priv(dev);
+	struct __vxge_hw_device *hldev = vdev->devh;
 
 	vxge_hw_device_setpause_data(hldev, 0, ep->tx_pause, ep->rx_pause);
 
@@ -209,9 +203,8 @@ static void vxge_get_ethtool_stats(struc
 	enum vxge_hw_status status;
 	enum vxge_hw_status swstatus;
 	struct vxge_vpath *vpath = NULL;
-
-	struct vxgedev *vdev = (struct vxgedev *)netdev_priv(dev);
-	struct __vxge_hw_device  *hldev = vdev->devh;
+	struct vxgedev *vdev = netdev_priv(dev);
+	struct __vxge_hw_device *hldev = vdev->devh;
 	struct vxge_hw_xmac_stats *xmac_stats;
 	struct vxge_hw_device_stats_sw_info *sw_stats;
 	struct vxge_hw_device_stats_hw_info *hw_stats;
@@ -574,12 +567,12 @@ static void vxge_get_ethtool_stats(struc
 	kfree(hw_stats);
 }
 
-static void vxge_ethtool_get_strings(struct net_device *dev,
-			      u32 stringset, u8 *data)
+static void vxge_ethtool_get_strings(struct net_device *dev, u32 stringset,
+				     u8 *data)
 {
 	int stat_size = 0;
 	int i, j;
-	struct vxgedev *vdev = (struct vxgedev *)netdev_priv(dev);
+	struct vxgedev *vdev = netdev_priv(dev);
 	switch (stringset) {
 	case ETH_SS_STATS:
 		vxge_add_string("VPATH STATISTICS%s\t\t\t",
@@ -1066,21 +1059,21 @@ static void vxge_ethtool_get_strings(str
 
 static int vxge_ethtool_get_regs_len(struct net_device *dev)
 {
-	struct vxgedev *vdev = (struct vxgedev *)netdev_priv(dev);
+	struct vxgedev *vdev = netdev_priv(dev);
 
 	return sizeof(struct vxge_hw_vpath_reg) * vdev->no_of_vpath;
 }
 
 static u32 vxge_get_rx_csum(struct net_device *dev)
 {
-	struct vxgedev *vdev = (struct vxgedev *)netdev_priv(dev);
+	struct vxgedev *vdev = netdev_priv(dev);
 
 	return vdev->rx_csum;
 }
 
 static int vxge_set_rx_csum(struct net_device *dev, u32 data)
 {
-	struct vxgedev *vdev = (struct vxgedev *)netdev_priv(dev);
+	struct vxgedev *vdev = netdev_priv(dev);
 
 	if (data)
 		vdev->rx_csum = 1;
@@ -1102,7 +1095,7 @@ static int vxge_ethtool_op_set_tso(struc
 
 static int vxge_ethtool_get_sset_count(struct net_device *dev, int sset)
 {
-	struct vxgedev *vdev = (struct vxgedev *)netdev_priv(dev);
+	struct vxgedev *vdev = netdev_priv(dev);
 
 	switch (sset) {
 	case ETH_SS_STATS:
@@ -1119,6 +1112,59 @@ static int vxge_ethtool_get_sset_count(s
 	}
 }
 
+static int vxge_set_flags(struct net_device *dev, u32 data)
+{
+	struct vxgedev *vdev = netdev_priv(dev);
+	enum vxge_hw_status status;
+
+	if (data & ~ETH_FLAG_RXHASH)
+		return -EOPNOTSUPP;
+
+	if (!!(data & ETH_FLAG_RXHASH) == vdev->devh->config.rth_en)
+		return 0;
+
+	if (netif_running(dev) || (vdev->config.rth_steering == NO_STEERING))
+		return -EINVAL;
+
+	vdev->devh->config.rth_en = !!(data & ETH_FLAG_RXHASH);
+
+	/* Enabling RTH requires some of the logic in vxge_device_register and a
+	 * vpath reset.  Due to these restrictions, only allow modification
+	 * while the interface is down.
+	 */
+	status = vxge_reset_all_vpaths(vdev);
+	if (status != VXGE_HW_OK) {
+		vdev->devh->config.rth_en = !vdev->devh->config.rth_en;
+		return -EFAULT;
+	}
+
+	if (vdev->devh->config.rth_en)
+		dev->features |= NETIF_F_RXHASH;
+	else
+		dev->features &= ~NETIF_F_RXHASH;
+
+	return 0;
+}
+
+static int vxge_fw_flash(struct net_device *dev, struct ethtool_flash *parms)
+{
+	struct vxgedev *vdev = netdev_priv(dev);
+
+	if (vdev->max_vpath_supported != VXGE_HW_MAX_VIRTUAL_PATHS) {
+		printk(KERN_INFO "Single Function Mode is required to flash the"
+		       " firmware\n");
+		return -EINVAL;
+	}
+
+	if (netif_running(dev)) {
+		printk(KERN_INFO "Interface %s must be down to flash the "
+		       "firmware\n", dev->name);
+		return -EBUSY;
+	}
+
+	return vxge_fw_upgrade(vdev, parms->data, 1);
+}
+
 static const struct ethtool_ops vxge_ethtool_ops = {
 	.get_settings		= vxge_ethtool_gset,
 	.set_settings		= vxge_ethtool_sset,
@@ -1131,7 +1177,7 @@ static const struct ethtool_ops vxge_eth
 	.get_rx_csum		= vxge_get_rx_csum,
 	.set_rx_csum		= vxge_set_rx_csum,
 	.get_tx_csum		= ethtool_op_get_tx_csum,
-	.set_tx_csum		= ethtool_op_set_tx_hw_csum,
+	.set_tx_csum		= ethtool_op_set_tx_ipv6_csum,
 	.get_sg			= ethtool_op_get_sg,
 	.set_sg			= ethtool_op_set_sg,
 	.get_tso		= ethtool_op_get_tso,
@@ -1140,6 +1186,8 @@ static const struct ethtool_ops vxge_eth
 	.phys_id		= vxge_ethtool_idnic,
 	.get_sset_count		= vxge_ethtool_get_sset_count,
 	.get_ethtool_stats	= vxge_get_ethtool_stats,
+	.set_flags		= vxge_set_flags,
+	.flash_device		= vxge_fw_flash,
 };
 
 void vxge_initialize_ethtool_ops(struct net_device *ndev)
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/vxge/vxge-main.c linux-libre-2.6.38-gnu1/drivers/net/vxge/vxge-main.c
--- linux-libre-2.6.37-gnu1/drivers/net/vxge/vxge-main.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/vxge/vxge-main.c	2013-05-03 01:59:34.000000000 -0400
@@ -50,6 +50,8 @@
 #include <net/ip.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
+#include <linux/firmware.h>
+#include <linux/net_tstamp.h>
 #include "vxge-main.h"
 #include "vxge-reg.h"
 
@@ -82,16 +84,6 @@ module_param_array(bw_percentage, uint,
 
 static struct vxge_drv_config *driver_config;
 
-static enum vxge_hw_status vxge_add_mac_addr(struct vxgedev *vdev,
-					     struct macInfo *mac);
-static enum vxge_hw_status vxge_del_mac_addr(struct vxgedev *vdev,
-					     struct macInfo *mac);
-static int vxge_mac_list_add(struct vxge_vpath *vpath, struct macInfo *mac);
-static int vxge_mac_list_del(struct vxge_vpath *vpath, struct macInfo *mac);
-static enum vxge_hw_status vxge_restore_vpath_vid_table(struct vxge_vpath *vpath);
-static enum vxge_hw_status vxge_restore_vpath_mac_addr(struct vxge_vpath *vpath);
-static enum vxge_hw_status vxge_reset_all_vpaths(struct vxgedev *vdev);
-
 static inline int is_vxge_card_up(struct vxgedev *vdev)
 {
 	return test_bit(__VXGE_STATE_CARD_UP, &vdev->state);
@@ -148,11 +140,10 @@ static inline void VXGE_COMPLETE_ALL_RX(
  * This function is called during interrupt context to notify link up state
  * change.
  */
-static void
-vxge_callback_link_up(struct __vxge_hw_device *hldev)
+static void vxge_callback_link_up(struct __vxge_hw_device *hldev)
 {
 	struct net_device *dev = hldev->ndev;
-	struct vxgedev *vdev = (struct vxgedev *)netdev_priv(dev);
+	struct vxgedev *vdev = netdev_priv(dev);
 
 	vxge_debug_entryexit(VXGE_TRACE, "%s: %s:%d",
 		vdev->ndev->name, __func__, __LINE__);
@@ -172,11 +163,10 @@ vxge_callback_link_up(struct __vxge_hw_d
  * This function is called during interrupt context to notify link down state
  * change.
  */
-static void
-vxge_callback_link_down(struct __vxge_hw_device *hldev)
+static void vxge_callback_link_down(struct __vxge_hw_device *hldev)
 {
 	struct net_device *dev = hldev->ndev;
-	struct vxgedev *vdev = (struct vxgedev *)netdev_priv(dev);
+	struct vxgedev *vdev = netdev_priv(dev);
 
 	vxge_debug_entryexit(VXGE_TRACE,
 		"%s: %s:%d", vdev->ndev->name, __func__, __LINE__);
@@ -195,7 +185,7 @@ vxge_callback_link_down(struct __vxge_hw
  *
  * Allocate SKB.
  */
-static struct sk_buff*
+static struct sk_buff *
 vxge_rx_alloc(void *dtrh, struct vxge_ring *ring, const int skb_size)
 {
 	struct net_device    *dev;
@@ -369,7 +359,7 @@ vxge_rx_1b_compl(struct __vxge_hw_ring *
 		 u8 t_code, void *userdata)
 {
 	struct vxge_ring *ring = (struct vxge_ring *)userdata;
-	struct  net_device *dev = ring->ndev;
+	struct net_device *dev = ring->ndev;
 	unsigned int dma_sizes;
 	void *first_dtr = NULL;
 	int dtr_cnt = 0;
@@ -413,7 +403,6 @@ vxge_rx_1b_compl(struct __vxge_hw_ring *
 
 		prefetch((char *)skb + L1_CACHE_BYTES);
 		if (unlikely(t_code)) {
-
 			if (vxge_hw_ring_handle_tcode(ringh, dtr, t_code) !=
 				VXGE_HW_OK) {
 
@@ -436,9 +425,7 @@ vxge_rx_1b_compl(struct __vxge_hw_ring *
 		}
 
 		if (pkt_length > VXGE_LL_RX_COPY_THRESHOLD) {
-
 			if (vxge_rx_alloc(dtr, ring, data_size) != NULL) {
-
 				if (!vxge_rx_map(dtr, ring)) {
 					skb_put(skb, pkt_length);
 
@@ -513,6 +500,23 @@ vxge_rx_1b_compl(struct __vxge_hw_ring *
 		else
 			skb_checksum_none_assert(skb);
 
+
+		if (ring->rx_hwts) {
+			struct skb_shared_hwtstamps *skb_hwts;
+			u32 ns = *(u32 *)(skb->head + pkt_length);
+
+			skb_hwts = skb_hwtstamps(skb);
+			skb_hwts->hwtstamp = ns_to_ktime(ns);
+			skb_hwts->syststamp.tv64 = 0;
+		}
+
+		/* rth_hash_type and rth_it_hit are non-zero regardless of
+		 * whether rss is enabled.  Only the rth_value is zero/non-zero
+		 * if rss is disabled/enabled, so key off of that.
+		 */
+		if (ext_info.rth_value)
+			skb->rxhash = ext_info.rth_value;
+
 		vxge_rx_complete(ring, skb, ext_info.vlan,
 			pkt_length, &ext_info);
 
@@ -660,6 +664,65 @@ static enum vxge_hw_status vxge_search_m
 	return FALSE;
 }
 
+static int vxge_mac_list_add(struct vxge_vpath *vpath, struct macInfo *mac)
+{
+	struct vxge_mac_addrs *new_mac_entry;
+	u8 *mac_address = NULL;
+
+	if (vpath->mac_addr_cnt >= VXGE_MAX_LEARN_MAC_ADDR_CNT)
+		return TRUE;
+
+	new_mac_entry = kzalloc(sizeof(struct vxge_mac_addrs), GFP_ATOMIC);
+	if (!new_mac_entry) {
+		vxge_debug_mem(VXGE_ERR,
+			"%s: memory allocation failed",
+			VXGE_DRIVER_NAME);
+		return FALSE;
+	}
+
+	list_add(&new_mac_entry->item, &vpath->mac_addr_list);
+
+	/* Copy the new mac address to the list */
+	mac_address = (u8 *)&new_mac_entry->macaddr;
+	memcpy(mac_address, mac->macaddr, ETH_ALEN);
+
+	new_mac_entry->state = mac->state;
+	vpath->mac_addr_cnt++;
+
+	/* Is this a multicast address */
+	if (0x01 & mac->macaddr[0])
+		vpath->mcast_addr_cnt++;
+
+	return TRUE;
+}
+
+/* Add a mac address to DA table */
+static enum vxge_hw_status
+vxge_add_mac_addr(struct vxgedev *vdev, struct macInfo *mac)
+{
+	enum vxge_hw_status status = VXGE_HW_OK;
+	struct vxge_vpath *vpath;
+	enum vxge_hw_vpath_mac_addr_add_mode duplicate_mode;
+
+	if (0x01 & mac->macaddr[0]) /* multicast address */
+		duplicate_mode = VXGE_HW_VPATH_MAC_ADDR_ADD_DUPLICATE;
+	else
+		duplicate_mode = VXGE_HW_VPATH_MAC_ADDR_REPLACE_DUPLICATE;
+
+	vpath = &vdev->vpaths[mac->vpath_no];
+	status = vxge_hw_vpath_mac_addr_add(vpath->handle, mac->macaddr,
+						mac->macmask, duplicate_mode);
+	if (status != VXGE_HW_OK) {
+		vxge_debug_init(VXGE_ERR,
+			"DA config add entry failed for vpath:%d",
+			vpath->device_id);
+	} else
+		if (FALSE == vxge_mac_list_add(vpath, mac))
+			status = -EPERM;
+
+	return status;
+}
+
 static int vxge_learn_mac(struct vxgedev *vdev, u8 *mac_header)
 {
 	struct macInfo mac_info;
@@ -670,7 +733,7 @@ static int vxge_learn_mac(struct vxgedev
 	struct vxge_vpath *vpath = NULL;
 	struct __vxge_hw_device *hldev;
 
-	hldev = (struct __vxge_hw_device *) pci_get_drvdata(vdev->pdev);
+	hldev = pci_get_drvdata(vdev->pdev);
 
 	mac_address = (u8 *)&mac_addr;
 	memcpy(mac_address, mac_header, ETH_ALEN);
@@ -769,7 +832,7 @@ vxge_xmit(struct sk_buff *skb, struct ne
 		return NETDEV_TX_OK;
 	}
 
-	vdev = (struct vxgedev *)netdev_priv(dev);
+	vdev = netdev_priv(dev);
 
 	if (unlikely(!is_vxge_card_up(vdev))) {
 		vxge_debug_tx(VXGE_ERR,
@@ -1005,6 +1068,50 @@ vxge_tx_term(void *dtrh, enum vxge_hw_tx
 		"%s:%d  Exiting...", __func__, __LINE__);
 }
 
+static int vxge_mac_list_del(struct vxge_vpath *vpath, struct macInfo *mac)
+{
+	struct list_head *entry, *next;
+	u64 del_mac = 0;
+	u8 *mac_address = (u8 *) (&del_mac);
+
+	/* Copy the mac address to delete from the list */
+	memcpy(mac_address, mac->macaddr, ETH_ALEN);
+
+	list_for_each_safe(entry, next, &vpath->mac_addr_list) {
+		if (((struct vxge_mac_addrs *)entry)->macaddr == del_mac) {
+			list_del(entry);
+			kfree((struct vxge_mac_addrs *)entry);
+			vpath->mac_addr_cnt--;
+
+			/* Is this a multicast address */
+			if (0x01 & mac->macaddr[0])
+				vpath->mcast_addr_cnt--;
+			return TRUE;
+		}
+	}
+
+	return FALSE;
+}
+
+/* delete a mac address from DA table */
+static enum vxge_hw_status
+vxge_del_mac_addr(struct vxgedev *vdev, struct macInfo *mac)
+{
+	enum vxge_hw_status status = VXGE_HW_OK;
+	struct vxge_vpath *vpath;
+
+	vpath = &vdev->vpaths[mac->vpath_no];
+	status = vxge_hw_vpath_mac_addr_delete(vpath->handle, mac->macaddr,
+						mac->macmask);
+	if (status != VXGE_HW_OK) {
+		vxge_debug_init(VXGE_ERR,
+			"DA config delete entry failed for vpath:%d",
+			vpath->device_id);
+	} else
+		vxge_mac_list_del(vpath, mac);
+	return status;
+}
+
 /**
  * vxge_set_multicast
  * @dev: pointer to the device structure
@@ -1034,7 +1141,7 @@ static void vxge_set_multicast(struct ne
 	vxge_debug_entryexit(VXGE_TRACE,
 		"%s:%d", __func__, __LINE__);
 
-	vdev = (struct vxgedev *)netdev_priv(dev);
+	vdev = netdev_priv(dev);
 	hldev = (struct __vxge_hw_device  *)vdev->devh;
 
 	if (unlikely(!is_vxge_card_up(vdev)))
@@ -1094,7 +1201,7 @@ static void vxge_set_multicast(struct ne
 		/* Delete previous MC's */
 		for (i = 0; i < mcast_cnt; i++) {
 			list_for_each_safe(entry, next, list_head) {
-				mac_entry = (struct vxge_mac_addrs *) entry;
+				mac_entry = (struct vxge_mac_addrs *)entry;
 				/* Copy the mac address to delete */
 				mac_address = (u8 *)&mac_entry->macaddr;
 				memcpy(mac_info.macaddr, mac_address, ETH_ALEN);
@@ -1137,7 +1244,7 @@ _set_all_mcast:
 		/* Delete previous MC's */
 		for (i = 0; i < mcast_cnt; i++) {
 			list_for_each_safe(entry, next, list_head) {
-				mac_entry = (struct vxge_mac_addrs *) entry;
+				mac_entry = (struct vxge_mac_addrs *)entry;
 				/* Copy the mac address to delete */
 				mac_address = (u8 *)&mac_entry->macaddr;
 				memcpy(mac_info.macaddr, mac_address, ETH_ALEN);
@@ -1184,14 +1291,14 @@ static int vxge_set_mac_addr(struct net_
 {
 	struct sockaddr *addr = p;
 	struct vxgedev *vdev;
-	struct __vxge_hw_device  *hldev;
+	struct __vxge_hw_device *hldev;
 	enum vxge_hw_status status = VXGE_HW_OK;
 	struct macInfo mac_info_new, mac_info_old;
 	int vpath_idx = 0;
 
 	vxge_debug_entryexit(VXGE_TRACE, "%s:%d", __func__, __LINE__);
 
-	vdev = (struct vxgedev *)netdev_priv(dev);
+	vdev = netdev_priv(dev);
 	hldev = vdev->devh;
 
 	if (!is_valid_ether_addr(addr->sa_data))
@@ -1292,8 +1399,13 @@ static void vxge_vpath_intr_enable(struc
 static void vxge_vpath_intr_disable(struct vxgedev *vdev, int vp_id)
 {
 	struct vxge_vpath *vpath = &vdev->vpaths[vp_id];
+	struct __vxge_hw_device *hldev;
 	int msix_id;
 
+	hldev = pci_get_drvdata(vdev->pdev);
+
+	vxge_hw_vpath_wait_receive_idle(hldev, vpath->device_id);
+
 	vxge_hw_vpath_intr_disable(vpath->handle);
 
 	if (vdev->config.intr_type == INTA)
@@ -1310,6 +1422,95 @@ static void vxge_vpath_intr_disable(stru
 	}
 }
 
+/* list all mac addresses from DA table */
+static enum vxge_hw_status
+vxge_search_mac_addr_in_da_table(struct vxge_vpath *vpath, struct macInfo *mac)
+{
+	enum vxge_hw_status status = VXGE_HW_OK;
+	unsigned char macmask[ETH_ALEN];
+	unsigned char macaddr[ETH_ALEN];
+
+	status = vxge_hw_vpath_mac_addr_get(vpath->handle,
+				macaddr, macmask);
+	if (status != VXGE_HW_OK) {
+		vxge_debug_init(VXGE_ERR,
+			"DA config list entry failed for vpath:%d",
+			vpath->device_id);
+		return status;
+	}
+
+	while (memcmp(mac->macaddr, macaddr, ETH_ALEN)) {
+		status = vxge_hw_vpath_mac_addr_get_next(vpath->handle,
+				macaddr, macmask);
+		if (status != VXGE_HW_OK)
+			break;
+	}
+
+	return status;
+}
+
+/* Store all mac addresses from the list to the DA table */
+static enum vxge_hw_status vxge_restore_vpath_mac_addr(struct vxge_vpath *vpath)
+{
+	enum vxge_hw_status status = VXGE_HW_OK;
+	struct macInfo mac_info;
+	u8 *mac_address = NULL;
+	struct list_head *entry, *next;
+
+	memset(&mac_info, 0, sizeof(struct macInfo));
+
+	if (vpath->is_open) {
+		list_for_each_safe(entry, next, &vpath->mac_addr_list) {
+			mac_address =
+				(u8 *)&
+				((struct vxge_mac_addrs *)entry)->macaddr;
+			memcpy(mac_info.macaddr, mac_address, ETH_ALEN);
+			((struct vxge_mac_addrs *)entry)->state =
+				VXGE_LL_MAC_ADDR_IN_DA_TABLE;
+			/* does this mac address already exist in da table? */
+			status = vxge_search_mac_addr_in_da_table(vpath,
+				&mac_info);
+			if (status != VXGE_HW_OK) {
+				/* Add this mac address to the DA table */
+				status = vxge_hw_vpath_mac_addr_add(
+					vpath->handle, mac_info.macaddr,
+					mac_info.macmask,
+				    VXGE_HW_VPATH_MAC_ADDR_ADD_DUPLICATE);
+				if (status != VXGE_HW_OK) {
+					vxge_debug_init(VXGE_ERR,
+					    "DA add entry failed for vpath:%d",
+					    vpath->device_id);
+					((struct vxge_mac_addrs *)entry)->state
+						= VXGE_LL_MAC_ADDR_IN_LIST;
+				}
+			}
+		}
+	}
+
+	return status;
+}
+
+/* Store all vlan ids from the list to the vid table */
+static enum vxge_hw_status
+vxge_restore_vpath_vid_table(struct vxge_vpath *vpath)
+{
+	enum vxge_hw_status status = VXGE_HW_OK;
+	struct vxgedev *vdev = vpath->vdev;
+	u16 vid;
+
+	if (vdev->vlgrp && vpath->is_open) {
+
+		for (vid = 0; vid < VLAN_N_VID; vid++) {
+			if (!vlan_group_get_device(vdev->vlgrp, vid))
+				continue;
+			/* Add these vlan to the vid table */
+			status = vxge_hw_vpath_vid_add(vpath->handle, vid);
+		}
+	}
+
+	return status;
+}
+
 /*
  * vxge_reset_vpath
  * @vdev: pointer to vdev
@@ -1405,12 +1606,16 @@ static int do_vxge_reset(struct vxgedev
 	}
 
 	if (event == VXGE_LL_FULL_RESET) {
+		netif_carrier_off(vdev->ndev);
+
 		/* wait for all the vpath reset to complete */
 		for (vp_id = 0; vp_id < vdev->no_of_vpath; vp_id++) {
 			while (test_bit(vp_id, &vdev->vp_reset))
 				msleep(50);
 		}
 
+		netif_carrier_on(vdev->ndev);
+
 		/* if execution mode is set to debug, don't reset the adapter */
 		if (unlikely(vdev->exec_mode)) {
 			vxge_debug_init(VXGE_ERR,
@@ -1423,6 +1628,7 @@ static int do_vxge_reset(struct vxgedev
 	}
 
 	if (event == VXGE_LL_FULL_RESET) {
+		vxge_hw_device_wait_receive_idle(vdev->devh);
 		vxge_hw_device_intr_disable(vdev->devh);
 
 		switch (vdev->cric_err_event) {
@@ -1563,9 +1769,14 @@ out:
  *
  * driver may reset the chip on events of serr, eccerr, etc
  */
-static int vxge_reset(struct vxgedev *vdev)
+static void vxge_reset(struct work_struct *work)
 {
-	return do_vxge_reset(vdev, VXGE_LL_FULL_RESET);
+	struct vxgedev *vdev = container_of(work, struct vxgedev, reset_task);
+
+	if (!netif_running(vdev->ndev))
+		return;
+
+	do_vxge_reset(vdev, VXGE_LL_FULL_RESET);
 }
 
 /**
@@ -1608,8 +1819,7 @@ static int vxge_poll_inta(struct napi_st
 	int budget_org = budget;
 	struct vxge_ring *ring;
 
-	struct __vxge_hw_device  *hldev = (struct __vxge_hw_device *)
-		pci_get_drvdata(vdev->pdev);
+	struct __vxge_hw_device *hldev = pci_get_drvdata(vdev->pdev);
 
 	for (i = 0; i < vdev->no_of_vpath; i++) {
 		ring = &vdev->vpaths[i].ring;
@@ -1645,11 +1855,11 @@ static int vxge_poll_inta(struct napi_st
  */
 static void vxge_netpoll(struct net_device *dev)
 {
-	struct __vxge_hw_device  *hldev;
+	struct __vxge_hw_device *hldev;
 	struct vxgedev *vdev;
 
-	vdev = (struct vxgedev *)netdev_priv(dev);
-	hldev = (struct __vxge_hw_device  *)pci_get_drvdata(vdev->pdev);
+	vdev = netdev_priv(dev);
+	hldev = pci_get_drvdata(vdev->pdev);
 
 	vxge_debug_entryexit(VXGE_TRACE, "%s:%d", __func__, __LINE__);
 
@@ -1689,15 +1899,6 @@ static enum vxge_hw_status vxge_rth_conf
 		mtable[index] = index % vdev->no_of_vpath;
 	}
 
-	/* Fill RTH hash types */
-	hash_types.hash_type_tcpipv4_en   = vdev->config.rth_hash_type_tcpipv4;
-	hash_types.hash_type_ipv4_en      = vdev->config.rth_hash_type_ipv4;
-	hash_types.hash_type_tcpipv6_en   = vdev->config.rth_hash_type_tcpipv6;
-	hash_types.hash_type_ipv6_en      = vdev->config.rth_hash_type_ipv6;
-	hash_types.hash_type_tcpipv6ex_en =
-					vdev->config.rth_hash_type_tcpipv6ex;
-	hash_types.hash_type_ipv6ex_en    = vdev->config.rth_hash_type_ipv6ex;
-
 	/* set indirection table, bucket-to-vpath mapping */
 	status = vxge_hw_vpath_rts_rth_itable_set(vdev->vp_handles,
 						vdev->no_of_vpath,
@@ -1710,19 +1911,27 @@ static enum vxge_hw_status vxge_rth_conf
 		return status;
 	}
 
+	/* Fill RTH hash types */
+	hash_types.hash_type_tcpipv4_en   = vdev->config.rth_hash_type_tcpipv4;
+	hash_types.hash_type_ipv4_en      = vdev->config.rth_hash_type_ipv4;
+	hash_types.hash_type_tcpipv6_en   = vdev->config.rth_hash_type_tcpipv6;
+	hash_types.hash_type_ipv6_en      = vdev->config.rth_hash_type_ipv6;
+	hash_types.hash_type_tcpipv6ex_en =
+					vdev->config.rth_hash_type_tcpipv6ex;
+	hash_types.hash_type_ipv6ex_en    = vdev->config.rth_hash_type_ipv6ex;
+
 	/*
-	* Because the itable_set() method uses the active_table field
-	* for the target virtual path the RTH config should be updated
-	* for all VPATHs. The h/w only uses the lowest numbered VPATH
-	* when steering frames.
-	*/
+	 * Because the itable_set() method uses the active_table field
+	 * for the target virtual path the RTH config should be updated
+	 * for all VPATHs. The h/w only uses the lowest numbered VPATH
+	 * when steering frames.
+	 */
 	 for (index = 0; index < vdev->no_of_vpath; index++) {
 		status = vxge_hw_vpath_rts_rth_set(
 				vdev->vpaths[index].handle,
 				vdev->config.rth_algorithm,
 				&hash_types,
 				vdev->config.rth_bkt_sz);
-
 		 if (status != VXGE_HW_OK) {
 			vxge_debug_init(VXGE_ERR,
 				"RTH configuration failed for vpath:%d",
@@ -1734,201 +1943,8 @@ static enum vxge_hw_status vxge_rth_conf
 	return status;
 }
 
-static int vxge_mac_list_add(struct vxge_vpath *vpath, struct macInfo *mac)
-{
-	struct vxge_mac_addrs *new_mac_entry;
-	u8 *mac_address = NULL;
-
-	if (vpath->mac_addr_cnt >= VXGE_MAX_LEARN_MAC_ADDR_CNT)
-		return TRUE;
-
-	new_mac_entry = kzalloc(sizeof(struct vxge_mac_addrs), GFP_ATOMIC);
-	if (!new_mac_entry) {
-		vxge_debug_mem(VXGE_ERR,
-			"%s: memory allocation failed",
-			VXGE_DRIVER_NAME);
-		return FALSE;
-	}
-
-	list_add(&new_mac_entry->item, &vpath->mac_addr_list);
-
-	/* Copy the new mac address to the list */
-	mac_address = (u8 *)&new_mac_entry->macaddr;
-	memcpy(mac_address, mac->macaddr, ETH_ALEN);
-
-	new_mac_entry->state = mac->state;
-	vpath->mac_addr_cnt++;
-
-	/* Is this a multicast address */
-	if (0x01 & mac->macaddr[0])
-		vpath->mcast_addr_cnt++;
-
-	return TRUE;
-}
-
-/* Add a mac address to DA table */
-static enum vxge_hw_status vxge_add_mac_addr(struct vxgedev *vdev,
-					     struct macInfo *mac)
-{
-	enum vxge_hw_status status = VXGE_HW_OK;
-	struct vxge_vpath *vpath;
-	enum vxge_hw_vpath_mac_addr_add_mode duplicate_mode;
-
-	if (0x01 & mac->macaddr[0]) /* multicast address */
-		duplicate_mode = VXGE_HW_VPATH_MAC_ADDR_ADD_DUPLICATE;
-	else
-		duplicate_mode = VXGE_HW_VPATH_MAC_ADDR_REPLACE_DUPLICATE;
-
-	vpath = &vdev->vpaths[mac->vpath_no];
-	status = vxge_hw_vpath_mac_addr_add(vpath->handle, mac->macaddr,
-						mac->macmask, duplicate_mode);
-	if (status != VXGE_HW_OK) {
-		vxge_debug_init(VXGE_ERR,
-			"DA config add entry failed for vpath:%d",
-			vpath->device_id);
-	} else
-		if (FALSE == vxge_mac_list_add(vpath, mac))
-			status = -EPERM;
-
-	return status;
-}
-
-static int vxge_mac_list_del(struct vxge_vpath *vpath, struct macInfo *mac)
-{
-	struct list_head *entry, *next;
-	u64 del_mac = 0;
-	u8 *mac_address = (u8 *) (&del_mac);
-
-	/* Copy the mac address to delete from the list */
-	memcpy(mac_address, mac->macaddr, ETH_ALEN);
-
-	list_for_each_safe(entry, next, &vpath->mac_addr_list) {
-		if (((struct vxge_mac_addrs *)entry)->macaddr == del_mac) {
-			list_del(entry);
-			kfree((struct vxge_mac_addrs *)entry);
-			vpath->mac_addr_cnt--;
-
-			/* Is this a multicast address */
-			if (0x01 & mac->macaddr[0])
-				vpath->mcast_addr_cnt--;
-			return TRUE;
-		}
-	}
-
-	return FALSE;
-}
-/* delete a mac address from DA table */
-static enum vxge_hw_status vxge_del_mac_addr(struct vxgedev *vdev,
-					     struct macInfo *mac)
-{
-	enum vxge_hw_status status = VXGE_HW_OK;
-	struct vxge_vpath *vpath;
-
-	vpath = &vdev->vpaths[mac->vpath_no];
-	status = vxge_hw_vpath_mac_addr_delete(vpath->handle, mac->macaddr,
-						mac->macmask);
-	if (status != VXGE_HW_OK) {
-		vxge_debug_init(VXGE_ERR,
-			"DA config delete entry failed for vpath:%d",
-			vpath->device_id);
-	} else
-		vxge_mac_list_del(vpath, mac);
-	return status;
-}
-
-/* list all mac addresses from DA table */
-enum vxge_hw_status
-static vxge_search_mac_addr_in_da_table(struct vxge_vpath *vpath,
-					struct macInfo *mac)
-{
-	enum vxge_hw_status status = VXGE_HW_OK;
-	unsigned char macmask[ETH_ALEN];
-	unsigned char macaddr[ETH_ALEN];
-
-	status = vxge_hw_vpath_mac_addr_get(vpath->handle,
-				macaddr, macmask);
-	if (status != VXGE_HW_OK) {
-		vxge_debug_init(VXGE_ERR,
-			"DA config list entry failed for vpath:%d",
-			vpath->device_id);
-		return status;
-	}
-
-	while (memcmp(mac->macaddr, macaddr, ETH_ALEN)) {
-
-		status = vxge_hw_vpath_mac_addr_get_next(vpath->handle,
-				macaddr, macmask);
-		if (status != VXGE_HW_OK)
-			break;
-	}
-
-	return status;
-}
-
-/* Store all vlan ids from the list to the vid table */
-static enum vxge_hw_status vxge_restore_vpath_vid_table(struct vxge_vpath *vpath)
-{
-	enum vxge_hw_status status = VXGE_HW_OK;
-	struct vxgedev *vdev = vpath->vdev;
-	u16 vid;
-
-	if (vdev->vlgrp && vpath->is_open) {
-
-		for (vid = 0; vid < VLAN_N_VID; vid++) {
-			if (!vlan_group_get_device(vdev->vlgrp, vid))
-				continue;
-			/* Add these vlan to the vid table */
-			status = vxge_hw_vpath_vid_add(vpath->handle, vid);
-		}
-	}
-
-	return status;
-}
-
-/* Store all mac addresses from the list to the DA table */
-static enum vxge_hw_status vxge_restore_vpath_mac_addr(struct vxge_vpath *vpath)
-{
-	enum vxge_hw_status status = VXGE_HW_OK;
-	struct macInfo mac_info;
-	u8 *mac_address = NULL;
-	struct list_head *entry, *next;
-
-	memset(&mac_info, 0, sizeof(struct macInfo));
-
-	if (vpath->is_open) {
-
-		list_for_each_safe(entry, next, &vpath->mac_addr_list) {
-			mac_address =
-				(u8 *)&
-				((struct vxge_mac_addrs *)entry)->macaddr;
-			memcpy(mac_info.macaddr, mac_address, ETH_ALEN);
-			((struct vxge_mac_addrs *)entry)->state =
-				VXGE_LL_MAC_ADDR_IN_DA_TABLE;
-			/* does this mac address already exist in da table? */
-			status = vxge_search_mac_addr_in_da_table(vpath,
-				&mac_info);
-			if (status != VXGE_HW_OK) {
-				/* Add this mac address to the DA table */
-				status = vxge_hw_vpath_mac_addr_add(
-					vpath->handle, mac_info.macaddr,
-					mac_info.macmask,
-				    VXGE_HW_VPATH_MAC_ADDR_ADD_DUPLICATE);
-				if (status != VXGE_HW_OK) {
-					vxge_debug_init(VXGE_ERR,
-					    "DA add entry failed for vpath:%d",
-					    vpath->device_id);
-					((struct vxge_mac_addrs *)entry)->state
-						= VXGE_LL_MAC_ADDR_IN_LIST;
-				}
-			}
-		}
-	}
-
-	return status;
-}
-
 /* reset vpaths */
-static enum vxge_hw_status vxge_reset_all_vpaths(struct vxgedev *vdev)
+enum vxge_hw_status vxge_reset_all_vpaths(struct vxgedev *vdev)
 {
 	enum vxge_hw_status status = VXGE_HW_OK;
 	struct vxge_vpath *vpath;
@@ -1988,8 +2004,23 @@ static int vxge_open_vpaths(struct vxged
 
 	for (i = 0; i < vdev->no_of_vpath; i++) {
 		vpath = &vdev->vpaths[i];
-
 		vxge_assert(vpath->is_configured);
+
+		if (!vdev->titan1) {
+			struct vxge_hw_vp_config *vcfg;
+			vcfg = &vdev->devh->config.vp_config[vpath->device_id];
+
+			vcfg->rti.urange_a = RTI_T1A_RX_URANGE_A;
+			vcfg->rti.urange_b = RTI_T1A_RX_URANGE_B;
+			vcfg->rti.urange_c = RTI_T1A_RX_URANGE_C;
+			vcfg->tti.uec_a = TTI_T1A_TX_UFC_A;
+			vcfg->tti.uec_b = TTI_T1A_TX_UFC_B;
+			vcfg->tti.uec_c = TTI_T1A_TX_UFC_C(vdev->mtu);
+			vcfg->tti.uec_d = TTI_T1A_TX_UFC_D(vdev->mtu);
+			vcfg->tti.ltimer_val = VXGE_T1A_TTI_LTIMER_VAL;
+			vcfg->tti.rtimer_val = VXGE_T1A_TTI_RTIMER_VAL;
+		}
+
 		attr.vp_id = vpath->device_id;
 		attr.fifo_attr.callback = vxge_xmit_compl;
 		attr.fifo_attr.txdl_term = vxge_tx_term;
@@ -2004,6 +2035,7 @@ static int vxge_open_vpaths(struct vxged
 
 		vpath->ring.ndev = vdev->ndev;
 		vpath->ring.pdev = vdev->pdev;
+
 		status = vxge_hw_vpath_open(vdev->devh, &attr, &vpath->handle);
 		if (status == VXGE_HW_OK) {
 			vpath->fifo.handle =
@@ -2024,6 +2056,7 @@ static int vxge_open_vpaths(struct vxged
 				vdev->config.fifo_indicate_max_pkts;
 			vpath->ring.rx_vector_no = 0;
 			vpath->ring.rx_csum = vdev->rx_csum;
+			vpath->ring.rx_hwts = vdev->rx_hwts;
 			vpath->is_open = 1;
 			vdev->vp_handles[i] = vpath->handle;
 			vpath->ring.gro_enable = vdev->config.gro_enable;
@@ -2031,11 +2064,10 @@ static int vxge_open_vpaths(struct vxged
 			vdev->stats.vpaths_open++;
 		} else {
 			vdev->stats.vpath_open_fail++;
-			vxge_debug_init(VXGE_ERR,
-				"%s: vpath: %d failed to open "
-				"with status: %d",
-			    vdev->ndev->name, vpath->device_id,
-				status);
+			vxge_debug_init(VXGE_ERR, "%s: vpath: %d failed to "
+					"open with status: %d",
+					vdev->ndev->name, vpath->device_id,
+					status);
 			vxge_close_vpaths(vdev, 0);
 			return -EPERM;
 		}
@@ -2043,6 +2075,7 @@ static int vxge_open_vpaths(struct vxged
 		vp_id = vpath->handle->vpath->vp_id;
 		vdev->vpaths_deployed |= vxge_mBIT(vp_id);
 	}
+
 	return VXGE_HW_OK;
 }
 
@@ -2062,21 +2095,20 @@ static irqreturn_t vxge_isr_napi(int irq
 	struct __vxge_hw_device *hldev;
 	u64 reason;
 	enum vxge_hw_status status;
-	struct vxgedev *vdev = (struct vxgedev *) dev_id;;
+	struct vxgedev *vdev = (struct vxgedev *)dev_id;
 
 	vxge_debug_intr(VXGE_TRACE, "%s:%d", __func__, __LINE__);
 
 	dev = vdev->ndev;
-	hldev = (struct __vxge_hw_device *)pci_get_drvdata(vdev->pdev);
+	hldev = pci_get_drvdata(vdev->pdev);
 
 	if (pci_channel_offline(vdev->pdev))
 		return IRQ_NONE;
 
 	if (unlikely(!is_vxge_card_up(vdev)))
-		return IRQ_NONE;
+		return IRQ_HANDLED;
 
-	status = vxge_hw_device_begin_irq(hldev, vdev->exec_mode,
-			&reason);
+	status = vxge_hw_device_begin_irq(hldev, vdev->exec_mode, &reason);
 	if (status == VXGE_HW_OK) {
 		vxge_hw_device_mask_all(hldev);
 
@@ -2301,8 +2333,8 @@ static void vxge_rem_msix_isr(struct vxg
 
 static void vxge_rem_isr(struct vxgedev *vdev)
 {
-	struct __vxge_hw_device  *hldev;
-	hldev = (struct __vxge_hw_device  *) pci_get_drvdata(vdev->pdev);
+	struct __vxge_hw_device *hldev;
+	hldev = pci_get_drvdata(vdev->pdev);
 
 #ifdef CONFIG_PCI_MSI
 	if (vdev->config.intr_type == MSI_X) {
@@ -2529,8 +2561,7 @@ static void vxge_poll_vp_lockup(unsigned
  * Return value: '0' on success and an appropriate (-)ve integer as
  * defined in errno.h file on failure.
  */
-static int
-vxge_open(struct net_device *dev)
+static int vxge_open(struct net_device *dev)
 {
 	enum vxge_hw_status status;
 	struct vxgedev *vdev;
@@ -2539,11 +2570,12 @@ vxge_open(struct net_device *dev)
 	int ret = 0;
 	int i;
 	u64 val64, function_mode;
+
 	vxge_debug_entryexit(VXGE_TRACE,
 		"%s: %s:%d", dev->name, __func__, __LINE__);
 
-	vdev = (struct vxgedev *)netdev_priv(dev);
-	hldev = (struct __vxge_hw_device *) pci_get_drvdata(vdev->pdev);
+	vdev = netdev_priv(dev);
+	hldev = pci_get_drvdata(vdev->pdev);
 	function_mode = vdev->config.device_hw_info.function_mode;
 
 	/* make sure you have link off by default every time Nic is
@@ -2598,6 +2630,8 @@ vxge_open(struct net_device *dev)
 			goto out2;
 		}
 	}
+	printk(KERN_INFO "%s: Receive Hashing Offload %s\n", dev->name,
+	       hldev->config.rth_en ? "enabled" : "disabled");
 
 	for (i = 0; i < vdev->no_of_vpath; i++) {
 		vpath = &vdev->vpaths[i];
@@ -2683,9 +2717,10 @@ vxge_open(struct net_device *dev)
 		vxge_os_timer(vdev->vp_reset_timer,
 			vxge_poll_vp_reset, vdev, (HZ/2));
 
-	if (vdev->vp_lockup_timer.function == NULL)
-		vxge_os_timer(vdev->vp_lockup_timer,
-			vxge_poll_vp_lockup, vdev, (HZ/2));
+	/* There is no need to check for RxD leak and RxD lookup on Titan1A */
+	if (vdev->titan1 && vdev->vp_lockup_timer.function == NULL)
+		vxge_os_timer(vdev->vp_lockup_timer, vxge_poll_vp_lockup, vdev,
+			      HZ / 2);
 
 	set_bit(__VXGE_STATE_CARD_UP, &vdev->state);
 
@@ -2767,8 +2802,8 @@ static int do_vxge_close(struct net_devi
 	vxge_debug_entryexit(VXGE_TRACE, "%s: %s:%d",
 		dev->name, __func__, __LINE__);
 
-	vdev = (struct vxgedev *)netdev_priv(dev);
-	hldev = (struct __vxge_hw_device *) pci_get_drvdata(vdev->pdev);
+	vdev = netdev_priv(dev);
+	hldev = pci_get_drvdata(vdev->pdev);
 
 	if (unlikely(!is_vxge_card_up(vdev)))
 		return 0;
@@ -2778,7 +2813,6 @@ static int do_vxge_close(struct net_devi
 	while (test_and_set_bit(__VXGE_STATE_RESET_CARD, &vdev->state))
 		msleep(50);
 
-	clear_bit(__VXGE_STATE_CARD_UP, &vdev->state);
 	if (do_io) {
 		/* Put the vpath back in normal mode */
 		vpath_vector = vxge_mBIT(vdev->vpaths[0].device_id);
@@ -2789,7 +2823,6 @@ static int do_vxge_close(struct net_devi
 					struct vxge_hw_mrpcim_reg,
 					rts_mgr_cbasin_cfg),
 				&val64);
-
 		if (status == VXGE_HW_OK) {
 			val64 &= ~vpath_vector;
 			status = vxge_hw_mgmt_reg_write(vdev->devh,
@@ -2818,10 +2851,17 @@ static int do_vxge_close(struct net_devi
 
 		smp_wmb();
 	}
-	del_timer_sync(&vdev->vp_lockup_timer);
+
+	if (vdev->titan1)
+		del_timer_sync(&vdev->vp_lockup_timer);
 
 	del_timer_sync(&vdev->vp_reset_timer);
 
+	if (do_io)
+		vxge_hw_device_wait_receive_idle(hldev);
+
+	clear_bit(__VXGE_STATE_CARD_UP, &vdev->state);
+
 	/* Disable napi */
 	if (vdev->config.intr_type != MSI_X)
 		napi_disable(&vdev->napi);
@@ -2838,8 +2878,6 @@ static int do_vxge_close(struct net_devi
 	if (do_io)
 		vxge_hw_device_intr_disable(vdev->devh);
 
-	mdelay(1000);
-
 	vxge_rem_isr(vdev);
 
 	vxge_napi_del_all(vdev);
@@ -2868,8 +2906,7 @@ static int do_vxge_close(struct net_devi
  * Return value: '0' on success and an appropriate (-)ve integer as
  * defined in errno.h file on failure.
  */
-static int
-vxge_close(struct net_device *dev)
+static int vxge_close(struct net_device *dev)
 {
 	do_vxge_close(dev, 1);
 	return 0;
@@ -2943,9 +2980,7 @@ vxge_get_stats64(struct net_device *dev,
 		net_stats->rx_bytes += vdev->vpaths[k].ring.stats.rx_bytes;
 		net_stats->rx_errors += vdev->vpaths[k].ring.stats.rx_errors;
 		net_stats->multicast += vdev->vpaths[k].ring.stats.rx_mcast;
-		net_stats->rx_dropped +=
-			vdev->vpaths[k].ring.stats.rx_dropped;
-
+		net_stats->rx_dropped += vdev->vpaths[k].ring.stats.rx_dropped;
 		net_stats->tx_packets += vdev->vpaths[k].fifo.stats.tx_frms;
 		net_stats->tx_bytes += vdev->vpaths[k].fifo.stats.tx_bytes;
 		net_stats->tx_errors += vdev->vpaths[k].fifo.stats.tx_errors;
@@ -2954,6 +2989,101 @@ vxge_get_stats64(struct net_device *dev,
 	return net_stats;
 }
 
+static enum vxge_hw_status vxge_timestamp_config(struct vxgedev *vdev,
+						 int enable)
+{
+	enum vxge_hw_status status;
+	u64 val64;
+
+	/* Timestamp is passed to the driver via the FCS, therefore we
+	 * must disable the FCS stripping by the adapter.  Since this is
+	 * required for the driver to load (due to a hardware bug),
+	 * there is no need to do anything special here.
+	 */
+	if (enable)
+		val64 = VXGE_HW_XMAC_TIMESTAMP_EN |
+			VXGE_HW_XMAC_TIMESTAMP_USE_LINK_ID(0) |
+			VXGE_HW_XMAC_TIMESTAMP_INTERVAL(0);
+	else
+		val64 = 0;
+
+	status = vxge_hw_mgmt_reg_write(vdev->devh,
+					vxge_hw_mgmt_reg_type_mrpcim,
+					0,
+					offsetof(struct vxge_hw_mrpcim_reg,
+						 xmac_timestamp),
+					val64);
+	vxge_hw_device_flush_io(vdev->devh);
+	return status;
+}
+
+static int vxge_hwtstamp_ioctl(struct vxgedev *vdev, void __user *data)
+{
+	struct hwtstamp_config config;
+	enum vxge_hw_status status;
+	int i;
+
+	if (copy_from_user(&config, data, sizeof(config)))
+		return -EFAULT;
+
+	/* reserved for future extensions */
+	if (config.flags)
+		return -EINVAL;
+
+	/* Transmit HW Timestamp not supported */
+	switch (config.tx_type) {
+	case HWTSTAMP_TX_OFF:
+		break;
+	case HWTSTAMP_TX_ON:
+	default:
+		return -ERANGE;
+	}
+
+	switch (config.rx_filter) {
+	case HWTSTAMP_FILTER_NONE:
+		status = vxge_timestamp_config(vdev, 0);
+		if (status != VXGE_HW_OK)
+			return -EFAULT;
+
+		vdev->rx_hwts = 0;
+		config.rx_filter = HWTSTAMP_FILTER_NONE;
+		break;
+
+	case HWTSTAMP_FILTER_ALL:
+	case HWTSTAMP_FILTER_SOME:
+	case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
+	case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
+	case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
+	case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
+	case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
+	case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
+	case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
+	case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
+	case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
+	case HWTSTAMP_FILTER_PTP_V2_EVENT:
+	case HWTSTAMP_FILTER_PTP_V2_SYNC:
+	case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
+		status = vxge_timestamp_config(vdev, 1);
+		if (status != VXGE_HW_OK)
+			return -EFAULT;
+
+		vdev->rx_hwts = 1;
+		config.rx_filter = HWTSTAMP_FILTER_ALL;
+		break;
+
+	default:
+		 return -ERANGE;
+	}
+
+	for (i = 0; i < vdev->no_of_vpath; i++)
+		vdev->vpaths[i].ring.rx_hwts = vdev->rx_hwts;
+
+	if (copy_to_user(data, &config, sizeof(config)))
+		return -EFAULT;
+
+	return 0;
+}
+
 /**
  * vxge_ioctl
  * @dev: Device pointer.
@@ -2966,7 +3096,20 @@ vxge_get_stats64(struct net_device *dev,
  */
 static int vxge_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
-	return -EOPNOTSUPP;
+	struct vxgedev *vdev = netdev_priv(dev);
+	int ret;
+
+	switch (cmd) {
+	case SIOCSHWTSTAMP:
+		ret = vxge_hwtstamp_ioctl(vdev, rq->ifr_data);
+		if (ret)
+			return ret;
+		break;
+	default:
+		return -EOPNOTSUPP;
+	}
+
+	return 0;
 }
 
 /**
@@ -2977,18 +3120,17 @@ static int vxge_ioctl(struct net_device
  * This function is triggered if the Tx Queue is stopped
  * for a pre-defined amount of time when the Interface is still up.
  */
-static void
-vxge_tx_watchdog(struct net_device *dev)
+static void vxge_tx_watchdog(struct net_device *dev)
 {
 	struct vxgedev *vdev;
 
 	vxge_debug_entryexit(VXGE_TRACE, "%s:%d", __func__, __LINE__);
 
-	vdev = (struct vxgedev *)netdev_priv(dev);
+	vdev = netdev_priv(dev);
 
 	vdev->cric_err_event = VXGE_HW_EVENT_RESET_START;
 
-	vxge_reset(vdev);
+	schedule_work(&vdev->reset_task);
 	vxge_debug_entryexit(VXGE_TRACE,
 		"%s:%d  Exiting...", __func__, __LINE__);
 }
@@ -3012,7 +3154,7 @@ vxge_vlan_rx_register(struct net_device
 
 	vxge_debug_entryexit(VXGE_TRACE, "%s:%d", __func__, __LINE__);
 
-	vdev = (struct vxgedev *)netdev_priv(dev);
+	vdev = netdev_priv(dev);
 
 	vpath = &vdev->vpaths[0];
 	if ((NULL == grp) && (vpath->is_open)) {
@@ -3061,7 +3203,7 @@ vxge_vlan_rx_add_vid(struct net_device *
 	struct vxge_vpath *vpath;
 	int vp_id;
 
-	vdev = (struct vxgedev *)netdev_priv(dev);
+	vdev = netdev_priv(dev);
 
 	/* Add these vlan to the vid table */
 	for (vp_id = 0; vp_id < vdev->no_of_vpath; vp_id++) {
@@ -3088,7 +3230,7 @@ vxge_vlan_rx_kill_vid(struct net_device
 
 	vxge_debug_entryexit(VXGE_TRACE, "%s:%d", __func__, __LINE__);
 
-	vdev = (struct vxgedev *)netdev_priv(dev);
+	vdev = netdev_priv(dev);
 
 	vlan_group_set_device(vdev->vlgrp, vid, NULL);
 
@@ -3110,21 +3252,31 @@ static const struct net_device_ops vxge_
 	.ndo_start_xmit         = vxge_xmit,
 	.ndo_validate_addr      = eth_validate_addr,
 	.ndo_set_multicast_list = vxge_set_multicast,
-
 	.ndo_do_ioctl           = vxge_ioctl,
-
 	.ndo_set_mac_address    = vxge_set_mac_addr,
 	.ndo_change_mtu         = vxge_change_mtu,
 	.ndo_vlan_rx_register   = vxge_vlan_rx_register,
 	.ndo_vlan_rx_kill_vid   = vxge_vlan_rx_kill_vid,
 	.ndo_vlan_rx_add_vid	= vxge_vlan_rx_add_vid,
-
 	.ndo_tx_timeout         = vxge_tx_watchdog,
 #ifdef CONFIG_NET_POLL_CONTROLLER
 	.ndo_poll_controller    = vxge_netpoll,
 #endif
 };
 
+static int __devinit vxge_device_revision(struct vxgedev *vdev)
+{
+	int ret;
+	u8 revision;
+
+	ret = pci_read_config_byte(vdev->pdev, PCI_REVISION_ID, &revision);
+	if (ret)
+		return -EIO;
+
+	vdev->titan1 = (revision == VXGE_HW_TITAN1_PCI_REVISION);
+	return 0;
+}
+
 static int __devinit vxge_device_register(struct __vxge_hw_device *hldev,
 					  struct vxge_config *config,
 					  int high_dma, int no_of_vpath,
@@ -3163,6 +3315,11 @@ static int __devinit vxge_device_registe
 	vdev->pdev = hldev->pdev;
 	memcpy(&vdev->config, config, sizeof(struct vxge_config));
 	vdev->rx_csum = 1;	/* Enable Rx CSUM by default. */
+	vdev->rx_hwts = 0;
+
+	ret = vxge_device_revision(vdev);
+	if (ret < 0)
+		goto _out1;
 
 	SET_NETDEV_DEV(ndev, &vdev->pdev->dev);
 
@@ -3175,9 +3332,15 @@ static int __devinit vxge_device_registe
 	ndev->netdev_ops = &vxge_netdev_ops;
 
 	ndev->watchdog_timeo = VXGE_LL_WATCH_DOG_TIMEOUT;
+	INIT_WORK(&vdev->reset_task, vxge_reset);
 
 	vxge_initialize_ethtool_ops(ndev);
 
+	if (vdev->config.rth_steering != NO_STEERING) {
+		ndev->features |= NETIF_F_RXHASH;
+		hldev->config.rth_en = VXGE_HW_RTH_ENABLE;
+	}
+
 	/* Allocate memory for vpath */
 	vdev->vpaths = kzalloc((sizeof(struct vxge_vpath)) *
 				no_of_vpath, GFP_KERNEL);
@@ -3191,7 +3354,7 @@ static int __devinit vxge_device_registe
 
 	ndev->features |= NETIF_F_SG;
 
-	ndev->features |= NETIF_F_HW_CSUM;
+	ndev->features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
 	vxge_debug_init(vxge_hw_device_trace_level_get(hldev),
 		"%s : checksuming enabled", __func__);
 
@@ -3227,6 +3390,7 @@ static int __devinit vxge_device_registe
 		"%s: Ethernet device registered",
 		ndev->name);
 
+	hldev->ndev = ndev;
 	*vdev_out = vdev;
 
 	/* Resetting the Device stats */
@@ -3261,36 +3425,29 @@ _out0:
  *
  * This function will unregister and free network device
  */
-static void
-vxge_device_unregister(struct __vxge_hw_device *hldev)
+static void vxge_device_unregister(struct __vxge_hw_device *hldev)
 {
 	struct vxgedev *vdev;
 	struct net_device *dev;
 	char buf[IFNAMSIZ];
-#if ((VXGE_DEBUG_INIT & VXGE_DEBUG_MASK) || \
-	(VXGE_DEBUG_ENTRYEXIT & VXGE_DEBUG_MASK))
-	u32 level_trace;
-#endif
 
 	dev = hldev->ndev;
 	vdev = netdev_priv(dev);
-#if ((VXGE_DEBUG_INIT & VXGE_DEBUG_MASK) || \
-	(VXGE_DEBUG_ENTRYEXIT & VXGE_DEBUG_MASK))
-	level_trace = vdev->level_trace;
-#endif
-	vxge_debug_entryexit(level_trace,
-		"%s: %s:%d", vdev->ndev->name, __func__, __LINE__);
 
-	memcpy(buf, vdev->ndev->name, IFNAMSIZ);
+	vxge_debug_entryexit(vdev->level_trace,	"%s: %s:%d", vdev->ndev->name,
+			     __func__, __LINE__);
+
+	strncpy(buf, dev->name, IFNAMSIZ);
+
+	flush_work_sync(&vdev->reset_task);
 
 	/* in 2.6 will call stop() if device is up */
 	unregister_netdev(dev);
 
-	flush_scheduled_work();
-
-	vxge_debug_init(level_trace, "%s: ethernet device unregistered", buf);
-	vxge_debug_entryexit(level_trace,
-		"%s: %s:%d  Exiting...", buf, __func__, __LINE__);
+	vxge_debug_init(vdev->level_trace, "%s: ethernet device unregistered",
+			buf);
+	vxge_debug_entryexit(vdev->level_trace,	"%s: %s:%d  Exiting...", buf,
+			     __func__, __LINE__);
 }
 
 /*
@@ -3304,7 +3461,7 @@ vxge_callback_crit_err(struct __vxge_hw_
 			enum vxge_hw_event type, u64 vp_id)
 {
 	struct net_device *dev = hldev->ndev;
-	struct vxgedev *vdev = (struct vxgedev *)netdev_priv(dev);
+	struct vxgedev *vdev = netdev_priv(dev);
 	struct vxge_vpath *vpath = NULL;
 	int vpath_idx;
 
@@ -3527,9 +3684,9 @@ static int __devinit vxge_config_vpaths(
 		device_config->vp_config[i].tti.timer_ac_en =
 				VXGE_HW_TIM_TIMER_AC_ENABLE;
 
-		/* For msi-x with napi (each vector
-		has a handler of its own) -
-		Set CI to OFF for all vpaths */
+		/* For msi-x with napi (each vector has a handler of its own) -
+		 * Set CI to OFF for all vpaths
+		 */
 		device_config->vp_config[i].tti.timer_ci_en =
 			VXGE_HW_TIM_TIMER_CI_DISABLE;
 
@@ -3559,10 +3716,13 @@ static int __devinit vxge_config_vpaths(
 
 		device_config->vp_config[i].ring.ring_blocks  =
 						VXGE_HW_DEF_RING_BLOCKS;
+
 		device_config->vp_config[i].ring.buffer_mode =
 			VXGE_HW_RING_RXD_BUFFER_MODE_1;
+
 		device_config->vp_config[i].ring.rxds_limit  =
 				VXGE_HW_DEF_RING_RXDS_LIMIT;
+
 		device_config->vp_config[i].ring.scatter_mode =
 					VXGE_HW_RING_SCATTER_MODE_A;
 
@@ -3642,6 +3802,7 @@ static void __devinit vxge_device_config
 		device_config->intr_mode = VXGE_HW_INTR_MODE_MSIX;
 		break;
 	}
+
 	/* Timer period between device poll */
 	device_config->device_poll_millis = VXGE_TIMER_DELAY;
 
@@ -3653,16 +3814,10 @@ static void __devinit vxge_device_config
 
 	vxge_debug_ll_config(VXGE_TRACE, "%s : Device Config Params ",
 			__func__);
-	vxge_debug_ll_config(VXGE_TRACE, "dma_blockpool_initial : %d",
-			device_config->dma_blockpool_initial);
-	vxge_debug_ll_config(VXGE_TRACE, "dma_blockpool_max : %d",
-			device_config->dma_blockpool_max);
 	vxge_debug_ll_config(VXGE_TRACE, "intr_mode : %d",
 			device_config->intr_mode);
 	vxge_debug_ll_config(VXGE_TRACE, "device_poll_millis : %d",
 			device_config->device_poll_millis);
-	vxge_debug_ll_config(VXGE_TRACE, "rts_mac_en : %d",
-			device_config->rts_mac_en);
 	vxge_debug_ll_config(VXGE_TRACE, "rth_en : %d",
 			device_config->rth_en);
 	vxge_debug_ll_config(VXGE_TRACE, "rth_it_type : %d",
@@ -3751,9 +3906,6 @@ static void __devinit vxge_print_parm(st
 		vxge_debug_init(VXGE_TRACE,
 			"%s: MAC Address learning enabled", vdev->ndev->name);
 
-	vxge_debug_init(VXGE_TRACE,
-		"%s: Rx doorbell mode enabled", vdev->ndev->name);
-
 	for (i = 0; i < VXGE_HW_MAX_VIRTUAL_PATHS; i++) {
 		if (!vxge_bVALn(vpath_mask, i, 1))
 			continue;
@@ -3766,14 +3918,6 @@ static void __devinit vxge_print_parm(st
 			((struct __vxge_hw_device  *)(vdev->devh))->
 				config.vp_config[i].rpa_strip_vlan_tag
 			? "Enabled" : "Disabled");
-		vxge_debug_init(VXGE_TRACE,
-			"%s: Ring blocks : %d", vdev->ndev->name,
-			((struct __vxge_hw_device  *)(vdev->devh))->
-				config.vp_config[i].ring.ring_blocks);
-		vxge_debug_init(VXGE_TRACE,
-			"%s: Fifo blocks : %d", vdev->ndev->name,
-			((struct __vxge_hw_device  *)(vdev->devh))->
-				config.vp_config[i].fifo.fifo_blocks);
 		vxge_debug_ll_config(VXGE_TRACE,
 			"%s: Max frags : %d", vdev->ndev->name,
 			((struct __vxge_hw_device  *)(vdev->devh))->
@@ -3813,8 +3957,7 @@ static int vxge_pm_resume(struct pci_dev
 static pci_ers_result_t vxge_io_error_detected(struct pci_dev *pdev,
 						pci_channel_state_t state)
 {
-	struct __vxge_hw_device  *hldev =
-		(struct __vxge_hw_device  *) pci_get_drvdata(pdev);
+	struct __vxge_hw_device *hldev = pci_get_drvdata(pdev);
 	struct net_device *netdev = hldev->ndev;
 
 	netif_device_detach(netdev);
@@ -3843,8 +3986,7 @@ static pci_ers_result_t vxge_io_error_de
  */
 static pci_ers_result_t vxge_io_slot_reset(struct pci_dev *pdev)
 {
-	struct __vxge_hw_device  *hldev =
-		(struct __vxge_hw_device  *) pci_get_drvdata(pdev);
+	struct __vxge_hw_device *hldev = pci_get_drvdata(pdev);
 	struct net_device *netdev = hldev->ndev;
 
 	struct vxgedev *vdev = netdev_priv(netdev);
@@ -3855,7 +3997,7 @@ static pci_ers_result_t vxge_io_slot_res
 	}
 
 	pci_set_master(pdev);
-	vxge_reset(vdev);
+	do_vxge_reset(vdev, VXGE_LL_FULL_RESET);
 
 	return PCI_ERS_RESULT_RECOVERED;
 }
@@ -3869,8 +4011,7 @@ static pci_ers_result_t vxge_io_slot_res
  */
 static void vxge_io_resume(struct pci_dev *pdev)
 {
-	struct __vxge_hw_device  *hldev =
-		(struct __vxge_hw_device  *) pci_get_drvdata(pdev);
+	struct __vxge_hw_device *hldev = pci_get_drvdata(pdev);
 	struct net_device *netdev = hldev->ndev;
 
 	if (netif_running(netdev)) {
@@ -3914,6 +4055,157 @@ static inline u32 vxge_get_num_vfs(u64 f
 	return num_functions;
 }
 
+int vxge_fw_upgrade(struct vxgedev *vdev, char *fw_name, int override)
+{
+	struct __vxge_hw_device *hldev = vdev->devh;
+	u32 maj, min, bld, cmaj, cmin, cbld;
+	enum vxge_hw_status status;
+	const struct firmware *fw;
+	int ret;
+
+	ret = reject_firmware(&fw, fw_name, &vdev->pdev->dev);
+	if (ret) {
+		vxge_debug_init(VXGE_ERR, "%s: Firmware file '%s' not found",
+				VXGE_DRIVER_NAME, fw_name);
+		goto out;
+	}
+
+	/* Load the new firmware onto the adapter */
+	status = vxge_update_fw_image(hldev, fw->data, fw->size);
+	if (status != VXGE_HW_OK) {
+		vxge_debug_init(VXGE_ERR,
+				"%s: FW image download to adapter failed '%s'.",
+				VXGE_DRIVER_NAME, fw_name);
+		ret = -EIO;
+		goto out;
+	}
+
+	/* Read the version of the new firmware */
+	status = vxge_hw_upgrade_read_version(hldev, &maj, &min, &bld);
+	if (status != VXGE_HW_OK) {
+		vxge_debug_init(VXGE_ERR,
+				"%s: Upgrade read version failed '%s'.",
+				VXGE_DRIVER_NAME, fw_name);
+		ret = -EIO;
+		goto out;
+	}
+
+	cmaj = vdev->config.device_hw_info.fw_version.major;
+	cmin = vdev->config.device_hw_info.fw_version.minor;
+	cbld = vdev->config.device_hw_info.fw_version.build;
+	/* It's possible the version in /lib/firmware is not the latest version.
+	 * If so, we could get into a loop of trying to upgrade to the latest
+	 * and flashing the older version.
+	 */
+	if (VXGE_FW_VER(maj, min, bld) == VXGE_FW_VER(cmaj, cmin, cbld) &&
+	    !override) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	printk(KERN_NOTICE "Upgrade to firmware version %d.%d.%d commencing\n",
+	       maj, min, bld);
+
+	/* Flash the adapter with the new firmware */
+	status = vxge_hw_flash_fw(hldev);
+	if (status != VXGE_HW_OK) {
+		vxge_debug_init(VXGE_ERR, "%s: Upgrade commit failed '%s'.",
+				VXGE_DRIVER_NAME, fw_name);
+		ret = -EIO;
+		goto out;
+	}
+
+	printk(KERN_NOTICE "Upgrade of firmware successful!  Adapter must be "
+	       "hard reset before using, thus requiring a system reboot or a "
+	       "hotplug event.\n");
+
+out:
+	release_firmware(fw);
+	return ret;
+}
+
+static int vxge_probe_fw_update(struct vxgedev *vdev)
+{
+	u32 maj, min, bld;
+	int ret, gpxe = 0;
+	char *fw_name;
+
+	maj = vdev->config.device_hw_info.fw_version.major;
+	min = vdev->config.device_hw_info.fw_version.minor;
+	bld = vdev->config.device_hw_info.fw_version.build;
+
+	if (VXGE_FW_VER(maj, min, bld) == VXGE_CERT_FW_VER)
+		return 0;
+
+	/* Ignore the build number when determining if the current firmware is
+	 * "too new" to load the driver
+	 */
+	if (VXGE_FW_VER(maj, min, 0) > VXGE_CERT_FW_VER) {
+		vxge_debug_init(VXGE_ERR, "%s: Firmware newer than last known "
+				"version, unable to load driver\n",
+				VXGE_DRIVER_NAME);
+		return -EINVAL;
+	}
+
+	/* Firmware 1.4.4 and older cannot be upgraded, and is too ancient to
+	 * work with this driver.
+	 */
+	if (VXGE_FW_VER(maj, min, bld) <= VXGE_FW_DEAD_VER) {
+		vxge_debug_init(VXGE_ERR, "%s: Firmware %d.%d.%d cannot be "
+				"upgraded\n", VXGE_DRIVER_NAME, maj, min, bld);
+		return -EINVAL;
+	}
+
+	/* If file not specified, determine gPXE or not */
+	if (VXGE_FW_VER(maj, min, bld) >= VXGE_EPROM_FW_VER) {
+		int i;
+		for (i = 0; i < VXGE_HW_MAX_ROM_IMAGES; i++)
+			if (vdev->devh->eprom_versions[i]) {
+				gpxe = 1;
+				break;
+			}
+	}
+	if (gpxe)
+		fw_name = "/*(DEBLOBBED)*/";
+	else
+		fw_name = "/*(DEBLOBBED)*/";
+
+	ret = vxge_fw_upgrade(vdev, fw_name, 0);
+	/* -EINVAL and -ENOENT are not fatal errors for flashing firmware on
+	 * probe, so ignore them
+	 */
+	if (ret != -EINVAL && ret != -ENOENT)
+		return -EIO;
+	else
+		ret = 0;
+
+	if (VXGE_FW_VER(VXGE_CERT_FW_VER_MAJOR, VXGE_CERT_FW_VER_MINOR, 0) >
+	    VXGE_FW_VER(maj, min, 0)) {
+		vxge_debug_init(VXGE_ERR, "%s: Firmware %d.%d.%d is too old to"
+				" be used with this driver.\n"
+				"Please get the latest version from "
+				"ftp://ftp.s2io.com/pub/X3100-Drivers/FIRMWARE",
+				VXGE_DRIVER_NAME, maj, min, bld);
+		return -EINVAL;
+	}
+
+	return ret;
+}
+
+static int __devinit is_sriov_initialized(struct pci_dev *pdev)
+{
+	int pos;
+	u16 ctrl;
+
+	pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_SRIOV);
+	if (pos) {
+		pci_read_config_word(pdev, pos + PCI_SRIOV_CTRL, &ctrl);
+		if (ctrl & PCI_SRIOV_CTRL_VFE)
+			return 1;
+	}
+	return 0;
+}
+
 /**
  * vxge_probe
  * @pdev : structure containing the PCI related information of the device.
@@ -3928,7 +4220,7 @@ static inline u32 vxge_get_num_vfs(u64 f
 static int __devinit
 vxge_probe(struct pci_dev *pdev, const struct pci_device_id *pre)
 {
-	struct __vxge_hw_device  *hldev;
+	struct __vxge_hw_device *hldev;
 	enum vxge_hw_status status;
 	int ret;
 	int high_dma = 0;
@@ -3951,9 +4243,10 @@ vxge_probe(struct pci_dev *pdev, const s
 	attr.pdev = pdev;
 
 	/* In SRIOV-17 mode, functions of the same adapter
-	 * can be deployed on different buses */
-	if ((!pdev->is_virtfn) && ((bus != pdev->bus->number) ||
-		(device != PCI_SLOT(pdev->devfn))))
+	 * can be deployed on different buses
+	 */
+	if (((bus != pdev->bus->number) || (device != PCI_SLOT(pdev->devfn))) &&
+	    !pdev->is_virtfn)
 		new_device = 1;
 
 	bus = pdev->bus->number;
@@ -3971,6 +4264,7 @@ vxge_probe(struct pci_dev *pdev, const s
 		driver_config->config_dev_cnt = 0;
 		driver_config->total_dev_cnt = 0;
 	}
+
 	/* Now making the CPU based no of vpath calculation
 	 * applicable for individual functions as well.
 	 */
@@ -3993,11 +4287,11 @@ vxge_probe(struct pci_dev *pdev, const s
 		goto _exit0;
 	}
 
-	ll_config = kzalloc(sizeof(*ll_config), GFP_KERNEL);
+	ll_config = kzalloc(sizeof(struct vxge_config), GFP_KERNEL);
 	if (!ll_config) {
 		ret = -ENOMEM;
 		vxge_debug_init(VXGE_ERR,
-			"ll_config : malloc failed %s %d",
+			"device_config : malloc failed %s %d",
 			__FILE__, __LINE__);
 		goto _exit0;
 	}
@@ -4041,7 +4335,7 @@ vxge_probe(struct pci_dev *pdev, const s
 		goto _exit1;
 	}
 
-	if (pci_request_regions(pdev, VXGE_DRIVER_NAME)) {
+	if (pci_request_region(pdev, 0, VXGE_DRIVER_NAME)) {
 		vxge_debug_init(VXGE_ERR,
 			"%s : request regions failed", __func__);
 		ret = -ENODEV;
@@ -4072,16 +4366,6 @@ vxge_probe(struct pci_dev *pdev, const s
 		goto _exit3;
 	}
 
-	if (ll_config->device_hw_info.fw_version.major !=
-		VXGE_DRIVER_FW_VERSION_MAJOR) {
-		vxge_debug_init(VXGE_ERR,
-			"%s: Incorrect firmware version."
-			"Please upgrade the firmware to version 1.x.x",
-			VXGE_DRIVER_NAME);
-		ret = -EINVAL;
-		goto _exit3;
-	}
-
 	vpath_mask = ll_config->device_hw_info.vpath_mask;
 	if (vpath_mask == 0) {
 		vxge_debug_ll_config(VXGE_TRACE,
@@ -4110,14 +4394,13 @@ vxge_probe(struct pci_dev *pdev, const s
 		num_vfs = vxge_get_num_vfs(function_mode) - 1;
 
 	/* Enable SRIOV mode, if firmware has SRIOV support and if it is a PF */
-	if (is_sriov(function_mode) && (max_config_dev > 1) &&
-		(ll_config->intr_type != INTA) &&
-		(is_privileged == VXGE_HW_OK)) {
-		ret = pci_enable_sriov(pdev, ((max_config_dev - 1) < num_vfs)
-			? (max_config_dev - 1) : num_vfs);
+	if (is_sriov(function_mode) && !is_sriov_initialized(pdev) &&
+	   (ll_config->intr_type != INTA)) {
+		ret = pci_enable_sriov(pdev, num_vfs);
 		if (ret)
 			vxge_debug_ll_config(VXGE_ERR,
 				"Failed in enabling SRIOV mode: %d\n", ret);
+			/* No need to fail out, as an error here is non-fatal */
 	}
 
 	/*
@@ -4145,11 +4428,37 @@ vxge_probe(struct pci_dev *pdev, const s
 			goto _exit3;
 	}
 
+	if (VXGE_FW_VER(ll_config->device_hw_info.fw_version.major,
+			ll_config->device_hw_info.fw_version.minor,
+			ll_config->device_hw_info.fw_version.build) >=
+	    VXGE_EPROM_FW_VER) {
+		struct eprom_image img[VXGE_HW_MAX_ROM_IMAGES];
+
+		status = vxge_hw_vpath_eprom_img_ver_get(hldev, img);
+		if (status != VXGE_HW_OK) {
+			vxge_debug_init(VXGE_ERR, "%s: Reading of EPROM failed",
+					VXGE_DRIVER_NAME);
+			/* This is a non-fatal error, continue */
+		}
+
+		for (i = 0; i < VXGE_HW_MAX_ROM_IMAGES; i++) {
+			hldev->eprom_versions[i] = img[i].version;
+			if (!img[i].is_valid)
+				break;
+			vxge_debug_init(VXGE_TRACE, "%s: EPROM %d, version "
+					"%d.%d.%d.%d\n", VXGE_DRIVER_NAME, i,
+					VXGE_EPROM_IMG_MAJOR(img[i].version),
+					VXGE_EPROM_IMG_MINOR(img[i].version),
+					VXGE_EPROM_IMG_FIX(img[i].version),
+					VXGE_EPROM_IMG_BUILD(img[i].version));
+		}
+	}
+
 	/* if FCS stripping is not disabled in MAC fail driver load */
-	if (vxge_hw_vpath_strip_fcs_check(hldev, vpath_mask) != VXGE_HW_OK) {
-		vxge_debug_init(VXGE_ERR,
-			"%s: FCS stripping is not disabled in MAC"
-			" failing driver load", VXGE_DRIVER_NAME);
+	status = vxge_hw_vpath_strip_fcs_check(hldev, vpath_mask);
+	if (status != VXGE_HW_OK) {
+		vxge_debug_init(VXGE_ERR, "%s: FCS stripping is enabled in MAC"
+				" failing driver load", VXGE_DRIVER_NAME);
 		ret = -EINVAL;
 		goto _exit4;
 	}
@@ -4163,28 +4472,32 @@ vxge_probe(struct pci_dev *pdev, const s
 	ll_config->fifo_indicate_max_pkts = VXGE_FIFO_INDICATE_MAX_PKTS;
 	ll_config->addr_learn_en = addr_learn_en;
 	ll_config->rth_algorithm = RTH_ALG_JENKINS;
-	ll_config->rth_hash_type_tcpipv4 = VXGE_HW_RING_HASH_TYPE_TCP_IPV4;
-	ll_config->rth_hash_type_ipv4 = VXGE_HW_RING_HASH_TYPE_NONE;
-	ll_config->rth_hash_type_tcpipv6 = VXGE_HW_RING_HASH_TYPE_NONE;
-	ll_config->rth_hash_type_ipv6 = VXGE_HW_RING_HASH_TYPE_NONE;
-	ll_config->rth_hash_type_tcpipv6ex = VXGE_HW_RING_HASH_TYPE_NONE;
-	ll_config->rth_hash_type_ipv6ex = VXGE_HW_RING_HASH_TYPE_NONE;
+	ll_config->rth_hash_type_tcpipv4 = 1;
+	ll_config->rth_hash_type_ipv4 = 0;
+	ll_config->rth_hash_type_tcpipv6 = 0;
+	ll_config->rth_hash_type_ipv6 = 0;
+	ll_config->rth_hash_type_tcpipv6ex = 0;
+	ll_config->rth_hash_type_ipv6ex = 0;
 	ll_config->rth_bkt_sz = RTH_BUCKET_SIZE;
 	ll_config->tx_pause_enable = VXGE_PAUSE_CTRL_ENABLE;
 	ll_config->rx_pause_enable = VXGE_PAUSE_CTRL_ENABLE;
 
-	if (vxge_device_register(hldev, ll_config, high_dma, no_of_vpath,
-		&vdev)) {
+	ret = vxge_device_register(hldev, ll_config, high_dma, no_of_vpath,
+				   &vdev);
+	if (ret) {
 		ret = -EINVAL;
 		goto _exit4;
 	}
 
+	ret = vxge_probe_fw_update(vdev);
+	if (ret)
+		goto _exit5;
+
 	vxge_hw_device_debug_set(hldev, VXGE_TRACE, VXGE_COMPONENT_LL);
 	VXGE_COPY_DEBUG_INFO_TO_LL(vdev, vxge_hw_device_error_level_get(hldev),
 		vxge_hw_device_trace_level_get(hldev));
 
 	/* set private HW device info */
-	hldev->ndev = vdev->ndev;
 	vdev->mtu = VXGE_HW_DEFAULT_MTU;
 	vdev->bar0 = attr.bar0;
 	vdev->max_vpath_supported = max_vpath_supported;
@@ -4278,15 +4591,13 @@ vxge_probe(struct pci_dev *pdev, const s
 
 	/* Copy the station mac address to the list */
 	for (i = 0; i < vdev->no_of_vpath; i++) {
-		entry =	(struct vxge_mac_addrs *)
-				kzalloc(sizeof(struct vxge_mac_addrs),
-					GFP_KERNEL);
+		entry =	kzalloc(sizeof(struct vxge_mac_addrs), GFP_KERNEL);
 		if (NULL == entry) {
 			vxge_debug_init(VXGE_ERR,
 				"%s: mac_addr_list : memory allocation failed",
 				vdev->ndev->name);
 			ret = -EPERM;
-			goto _exit5;
+			goto _exit6;
 		}
 		macaddr = (u8 *)&entry->macaddr;
 		memcpy(macaddr, vdev->ndev->dev_addr, ETH_ALEN);
@@ -4326,10 +4637,10 @@ vxge_probe(struct pci_dev *pdev, const s
 	kfree(ll_config);
 	return 0;
 
-_exit5:
+_exit6:
 	for (i = 0; i < vdev->no_of_vpath; i++)
 		vxge_free_mac_add_list(&vdev->vpaths[i]);
-
+_exit5:
 	vxge_device_unregister(hldev);
 _exit4:
 	pci_disable_sriov(pdev);
@@ -4337,7 +4648,7 @@ _exit4:
 _exit3:
 	iounmap(attr.bar0);
 _exit2:
-	pci_release_regions(pdev);
+	pci_release_region(pdev, 0);
 _exit1:
 	pci_disable_device(pdev);
 _exit0:
@@ -4354,34 +4665,25 @@ _exit0:
  * Description: This function is called by the Pci subsystem to release a
  * PCI device and free up all resource held up by the device.
  */
-static void __devexit
-vxge_remove(struct pci_dev *pdev)
+static void __devexit vxge_remove(struct pci_dev *pdev)
 {
-	struct __vxge_hw_device  *hldev;
+	struct __vxge_hw_device *hldev;
 	struct vxgedev *vdev = NULL;
 	struct net_device *dev;
 	int i = 0;
-#if ((VXGE_DEBUG_INIT & VXGE_DEBUG_MASK) || \
-	(VXGE_DEBUG_ENTRYEXIT & VXGE_DEBUG_MASK))
-	u32 level_trace;
-#endif
 
-	hldev = (struct __vxge_hw_device  *) pci_get_drvdata(pdev);
+	hldev = pci_get_drvdata(pdev);
 
 	if (hldev == NULL)
 		return;
+
 	dev = hldev->ndev;
 	vdev = netdev_priv(dev);
 
-#if ((VXGE_DEBUG_INIT & VXGE_DEBUG_MASK) || \
-	(VXGE_DEBUG_ENTRYEXIT & VXGE_DEBUG_MASK))
-	level_trace = vdev->level_trace;
-#endif
-	vxge_debug_entryexit(level_trace,
-		"%s:%d", __func__, __LINE__);
+	vxge_debug_entryexit(vdev->level_trace,	"%s:%d", __func__, __LINE__);
 
-	vxge_debug_init(level_trace,
-		"%s : removing PCI device...", __func__);
+	vxge_debug_init(vdev->level_trace, "%s : removing PCI device...",
+			__func__);
 	vxge_device_unregister(hldev);
 
 	for (i = 0; i < vdev->no_of_vpath; i++) {
@@ -4394,21 +4696,19 @@ vxge_remove(struct pci_dev *pdev)
 
 	iounmap(vdev->bar0);
 
-	pci_disable_sriov(pdev);
-
 	/* we are safe to free it now */
 	free_netdev(dev);
 
-	vxge_debug_init(level_trace,
-		"%s:%d  Device unregistered", __func__, __LINE__);
+	vxge_debug_init(vdev->level_trace, "%s:%d Device unregistered",
+			__func__, __LINE__);
 
 	vxge_hw_device_terminate(hldev);
 
 	pci_disable_device(pdev);
-	pci_release_regions(pdev);
+	pci_release_region(pdev, 0);
 	pci_set_drvdata(pdev, NULL);
-	vxge_debug_entryexit(level_trace,
-		"%s:%d  Exiting...", __func__, __LINE__);
+	vxge_debug_entryexit(vdev->level_trace,	"%s:%d  Exiting...", __func__,
+			     __LINE__);
 }
 
 static struct pci_error_handlers vxge_err_handler = {
@@ -4444,6 +4744,10 @@ vxge_starter(void)
 		return -ENOMEM;
 
 	ret = pci_register_driver(&vxge_driver);
+	if (ret) {
+		kfree(driver_config);
+		goto err;
+	}
 
 	if (driver_config->config_dev_cnt &&
 	   (driver_config->config_dev_cnt != driver_config->total_dev_cnt))
@@ -4451,10 +4755,7 @@ vxge_starter(void)
 			"%s: Configured %d of %d devices",
 			VXGE_DRIVER_NAME, driver_config->config_dev_cnt,
 			driver_config->total_dev_cnt);
-
-	if (ret)
-		kfree(driver_config);
-
+err:
 	return ret;
 }
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/vxge/vxge-main.h linux-libre-2.6.38-gnu1/drivers/net/vxge/vxge-main.h
--- linux-libre-2.6.37-gnu1/drivers/net/vxge/vxge-main.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/vxge/vxge-main.h	2011-03-14 21:20:32.000000000 -0400
@@ -29,6 +29,9 @@
 
 #define PCI_DEVICE_ID_TITAN_WIN		0x5733
 #define PCI_DEVICE_ID_TITAN_UNI		0x5833
+#define VXGE_HW_TITAN1_PCI_REVISION	1
+#define VXGE_HW_TITAN1A_PCI_REVISION	2
+
 #define	VXGE_USE_DEFAULT		0xffffffff
 #define VXGE_HW_VPATH_MSIX_ACTIVE	4
 #define VXGE_ALARM_MSIX_ID		2
@@ -53,11 +56,13 @@
 
 #define VXGE_TTI_BTIMER_VAL 250000
 
-#define VXGE_TTI_LTIMER_VAL 1000
-#define VXGE_TTI_RTIMER_VAL 0
-#define VXGE_RTI_BTIMER_VAL 250
-#define VXGE_RTI_LTIMER_VAL 100
-#define VXGE_RTI_RTIMER_VAL 0
+#define VXGE_TTI_LTIMER_VAL	1000
+#define VXGE_T1A_TTI_LTIMER_VAL	80
+#define VXGE_TTI_RTIMER_VAL	0
+#define VXGE_T1A_TTI_RTIMER_VAL	400
+#define VXGE_RTI_BTIMER_VAL	250
+#define VXGE_RTI_LTIMER_VAL	100
+#define VXGE_RTI_RTIMER_VAL	0
 #define VXGE_FIFO_INDICATE_MAX_PKTS VXGE_DEF_FIFO_LENGTH
 #define VXGE_ISR_POLLING_CNT 	8
 #define VXGE_MAX_CONFIG_DEV	0xFF
@@ -76,14 +81,32 @@
 #define TTI_TX_UFC_B	40
 #define TTI_TX_UFC_C	60
 #define TTI_TX_UFC_D	100
+#define TTI_T1A_TX_UFC_A	30
+#define TTI_T1A_TX_UFC_B	80
+/* Slope - (max_mtu - min_mtu)/(max_mtu_ufc - min_mtu_ufc) */
+/* Slope - 93 */
+/* 60 - 9k Mtu, 140 - 1.5k mtu */
+#define TTI_T1A_TX_UFC_C(mtu)	(60 + ((VXGE_HW_MAX_MTU - mtu) / 93))
+
+/* Slope - 37 */
+/* 100 - 9k Mtu, 300 - 1.5k mtu */
+#define TTI_T1A_TX_UFC_D(mtu)	(100 + ((VXGE_HW_MAX_MTU - mtu) / 37))
+
+
+#define RTI_RX_URANGE_A		5
+#define RTI_RX_URANGE_B		15
+#define RTI_RX_URANGE_C		40
+#define RTI_T1A_RX_URANGE_A	1
+#define RTI_T1A_RX_URANGE_B	20
+#define RTI_T1A_RX_URANGE_C	50
+#define RTI_RX_UFC_A		1
+#define RTI_RX_UFC_B		5
+#define RTI_RX_UFC_C		10
+#define RTI_RX_UFC_D		15
+#define RTI_T1A_RX_UFC_B	20
+#define RTI_T1A_RX_UFC_C	50
+#define RTI_T1A_RX_UFC_D	60
 
-#define RTI_RX_URANGE_A	5
-#define RTI_RX_URANGE_B	15
-#define RTI_RX_URANGE_C	40
-#define RTI_RX_UFC_A	1
-#define RTI_RX_UFC_B	5
-#define RTI_RX_UFC_C	10
-#define RTI_RX_UFC_D	15
 
 /* Milli secs timer period */
 #define VXGE_TIMER_DELAY		10000
@@ -145,15 +168,15 @@ struct vxge_config {
 
 	int		addr_learn_en;
 
-	int		rth_steering;
-	int		rth_algorithm;
-	int		rth_hash_type_tcpipv4;
-	int		rth_hash_type_ipv4;
-	int		rth_hash_type_tcpipv6;
-	int		rth_hash_type_ipv6;
-	int		rth_hash_type_tcpipv6ex;
-	int		rth_hash_type_ipv6ex;
-	int		rth_bkt_sz;
+	u32		rth_steering:2,
+			rth_algorithm:2,
+			rth_hash_type_tcpipv4:1,
+			rth_hash_type_ipv4:1,
+			rth_hash_type_tcpipv6:1,
+			rth_hash_type_ipv6:1,
+			rth_hash_type_tcpipv6ex:1,
+			rth_hash_type_ipv6ex:1,
+			rth_bkt_sz:8;
 	int		rth_jhash_golden_ratio;
 	int		tx_steering_type;
 	int 	fifo_indicate_max_pkts;
@@ -248,8 +271,9 @@ struct vxge_ring {
 	 */
 	int driver_id;
 
-	 /* copy of the flag indicating whether rx_csum is to be used */
-	u32 rx_csum;
+	/* copy of the flag indicating whether rx_csum is to be used */
+	u32 rx_csum:1,
+	    rx_hwts:1;
 
 	int pkts_processed;
 	int budget;
@@ -281,8 +305,8 @@ struct vxge_vpath {
 	int is_configured;
 	int is_open;
 	struct vxgedev *vdev;
-	u8 (macaddr)[ETH_ALEN];
-	u8 (macmask)[ETH_ALEN];
+	u8 macaddr[ETH_ALEN];
+	u8 macmask[ETH_ALEN];
 
 #define VXGE_MAX_LEARN_MAC_ADDR_CNT	2048
 	/* mac addresses currently programmed into NIC */
@@ -327,7 +351,9 @@ struct vxgedev {
 	u16		all_multi_flg;
 
 	 /* A flag indicating whether rx_csum is to be used or not. */
-	u32	rx_csum;
+	u32	rx_csum:1,
+		rx_hwts:1,
+		titan1:1;
 
 	struct vxge_msix_entry *vxge_entries;
 	struct msix_entry *entries;
@@ -369,6 +395,7 @@ struct vxgedev {
 	u32 		level_err;
 	u32 		level_trace;
 	char		fw_version[VXGE_HW_FW_STRLEN];
+	struct work_struct reset_task;
 };
 
 struct vxge_rx_priv {
@@ -387,8 +414,6 @@ struct vxge_tx_priv {
 	static int p = val; \
 	module_param(p, int, 0)
 
-#define vxge_os_bug(fmt...)		{ printk(fmt); BUG(); }
-
 #define vxge_os_timer(timer, handle, arg, exp) do { \
 		init_timer(&timer); \
 		timer.function = handle; \
@@ -396,7 +421,10 @@ struct vxge_tx_priv {
 		mod_timer(&timer, (jiffies + exp)); \
 	} while (0);
 
-extern void vxge_initialize_ethtool_ops(struct net_device *ndev);
+void vxge_initialize_ethtool_ops(struct net_device *ndev);
+enum vxge_hw_status vxge_reset_all_vpaths(struct vxgedev *vdev);
+int vxge_fw_upgrade(struct vxgedev *vdev, char *fw_name, int override);
+
 /**
  * #define VXGE_DEBUG_INIT: debug for initialization functions
  * #define VXGE_DEBUG_TX	 : debug transmit related functions
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/vxge/vxge-reg.h linux-libre-2.6.38-gnu1/drivers/net/vxge/vxge-reg.h
--- linux-libre-2.6.37-gnu1/drivers/net/vxge/vxge-reg.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/vxge/vxge-reg.h	2011-03-14 21:20:32.000000000 -0400
@@ -49,6 +49,33 @@
 #define VXGE_HW_TITAN_VPMGMT_REG_SPACES			17
 #define VXGE_HW_TITAN_VPATH_REG_SPACES			17
 
+#define VXGE_HW_FW_API_GET_EPROM_REV			31
+
+#define VXGE_EPROM_IMG_MAJOR(val)		(u32) vxge_bVALn(val, 48, 4)
+#define VXGE_EPROM_IMG_MINOR(val)		(u32) vxge_bVALn(val, 52, 4)
+#define VXGE_EPROM_IMG_FIX(val)			(u32) vxge_bVALn(val, 56, 4)
+#define VXGE_EPROM_IMG_BUILD(val)		(u32) vxge_bVALn(val, 60, 4)
+
+#define VXGE_HW_GET_EPROM_IMAGE_INDEX(val)		vxge_bVALn(val, 16, 8)
+#define VXGE_HW_GET_EPROM_IMAGE_VALID(val)		vxge_bVALn(val, 31, 1)
+#define VXGE_HW_GET_EPROM_IMAGE_TYPE(val)		vxge_bVALn(val, 40, 8)
+#define VXGE_HW_GET_EPROM_IMAGE_REV(val)		vxge_bVALn(val, 48, 16)
+#define VXGE_HW_RTS_ACCESS_STEER_ROM_IMAGE_INDEX(val)	vxge_vBIT(val, 16, 8)
+
+#define VXGE_HW_FW_API_GET_FUNC_MODE			29
+#define VXGE_HW_GET_FUNC_MODE_VAL(val)			(val & 0xFF)
+
+#define VXGE_HW_FW_UPGRADE_MEMO				13
+#define VXGE_HW_FW_UPGRADE_ACTION			16
+#define VXGE_HW_FW_UPGRADE_OFFSET_START			2
+#define VXGE_HW_FW_UPGRADE_OFFSET_SEND			3
+#define VXGE_HW_FW_UPGRADE_OFFSET_COMMIT		4
+#define VXGE_HW_FW_UPGRADE_OFFSET_READ			5
+
+#define VXGE_HW_FW_UPGRADE_BLK_SIZE			16
+#define VXGE_HW_UPGRADE_GET_RET_ERR_CODE(val)		(val & 0xff)
+#define VXGE_HW_UPGRADE_GET_SEC_ERR_CODE(val)		((val >> 8) & 0xff)
+
 #define VXGE_HW_ASIC_MODE_RESERVED				0
 #define VXGE_HW_ASIC_MODE_NO_IOV				1
 #define VXGE_HW_ASIC_MODE_SR_IOV				2
@@ -165,13 +192,13 @@
 #define	VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_ETYPE		2
 #define	VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_PN		3
 #define	VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_RTH_GEN_CFG	5
-#define	VXGE_HW_RTS_ACS_STEER_CTRL_DATA_STRUCT_SEL_RTH_SOLO_IT	6
+#define	VXGE_HW_RTS_ACS_STEER_CTRL_DATA_STRUCT_SEL_RTH_SOLO_IT		6
 #define	VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_RTH_JHASH_CFG	7
 #define	VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_RTH_MASK		8
 #define	VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_RTH_KEY		9
 #define	VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_QOS		10
 #define	VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_DS		11
-#define	VXGE_HW_RTS_ACS_STEER_CTRL_DATA_STRUCT_SEL_RTH_MULTI_IT	12
+#define	VXGE_HW_RTS_ACS_STEER_CTRL_DATA_STRUCT_SEL_RTH_MULTI_IT		12
 #define	VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_FW_MEMO		13
 
 #define	VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_DA_MAC_ADDR(bits) \
@@ -437,6 +464,7 @@
 #define VXGE_HW_RTS_ACCESS_STEER_DATA1_GET_FLASH_VER_BUILD(bits) \
 							vxge_bVALn(bits, 48, 16)
 #define VXGE_HW_RTS_ACCESS_STEER_DATA1_FLASH_VER_BUILD vxge_vBIT(val, 48, 16)
+#define VXGE_HW_RTS_ACCESS_STEER_CTRL_GET_ACTION(bits) vxge_bVALn(bits, 0, 8)
 
 #define	VXGE_HW_SRPCIM_TO_VPATH_ALARM_REG_GET_PPIF_SRPCIM_TO_VPATH_ALARM(bits)\
 							vxge_bVALn(bits, 0, 18)
@@ -3998,6 +4026,7 @@ struct vxge_hw_vpath_reg {
 #define	VXGE_HW_PRC_CFG6_L4_CPC_TRSFR_CODE_EN	vxge_mBIT(9)
 #define VXGE_HW_PRC_CFG6_RXD_CRXDT(val) vxge_vBIT(val, 23, 9)
 #define VXGE_HW_PRC_CFG6_RXD_SPAT(val) vxge_vBIT(val, 36, 9)
+#define VXGE_HW_PRC_CFG6_GET_RXD_SPAT(val)	vxge_bVALn(val, 36, 9)
 /*0x00a78*/	u64	prc_cfg7;
 #define VXGE_HW_PRC_CFG7_SCATTER_MODE(val) vxge_vBIT(val, 6, 2)
 #define	VXGE_HW_PRC_CFG7_SMART_SCAT_EN	vxge_mBIT(11)
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/vxge/vxge-traffic.c linux-libre-2.6.38-gnu1/drivers/net/vxge/vxge-traffic.c
--- linux-libre-2.6.37-gnu1/drivers/net/vxge/vxge-traffic.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/vxge/vxge-traffic.c	2011-03-14 21:20:32.000000000 -0400
@@ -17,13 +17,6 @@
 #include "vxge-config.h"
 #include "vxge-main.h"
 
-static enum vxge_hw_status
-__vxge_hw_device_handle_error(struct __vxge_hw_device *hldev,
-			      u32 vp_id, enum vxge_hw_event type);
-static enum vxge_hw_status
-__vxge_hw_vpath_alarm_process(struct __vxge_hw_virtualpath *vpath,
-			      u32 skip_alarms);
-
 /*
  * vxge_hw_vpath_intr_enable - Enable vpath interrupts.
  * @vp: Virtual Path handle.
@@ -419,6 +412,384 @@ void vxge_hw_device_flush_io(struct __vx
 }
 
 /**
+ * __vxge_hw_device_handle_error - Handle error
+ * @hldev: HW device
+ * @vp_id: Vpath Id
+ * @type: Error type. Please see enum vxge_hw_event{}
+ *
+ * Handle error.
+ */
+static enum vxge_hw_status
+__vxge_hw_device_handle_error(struct __vxge_hw_device *hldev, u32 vp_id,
+			      enum vxge_hw_event type)
+{
+	switch (type) {
+	case VXGE_HW_EVENT_UNKNOWN:
+		break;
+	case VXGE_HW_EVENT_RESET_START:
+	case VXGE_HW_EVENT_RESET_COMPLETE:
+	case VXGE_HW_EVENT_LINK_DOWN:
+	case VXGE_HW_EVENT_LINK_UP:
+		goto out;
+	case VXGE_HW_EVENT_ALARM_CLEARED:
+		goto out;
+	case VXGE_HW_EVENT_ECCERR:
+	case VXGE_HW_EVENT_MRPCIM_ECCERR:
+		goto out;
+	case VXGE_HW_EVENT_FIFO_ERR:
+	case VXGE_HW_EVENT_VPATH_ERR:
+	case VXGE_HW_EVENT_CRITICAL_ERR:
+	case VXGE_HW_EVENT_SERR:
+		break;
+	case VXGE_HW_EVENT_SRPCIM_SERR:
+	case VXGE_HW_EVENT_MRPCIM_SERR:
+		goto out;
+	case VXGE_HW_EVENT_SLOT_FREEZE:
+		break;
+	default:
+		vxge_assert(0);
+		goto out;
+	}
+
+	/* notify driver */
+	if (hldev->uld_callbacks.crit_err)
+		hldev->uld_callbacks.crit_err(
+			(struct __vxge_hw_device *)hldev,
+			type, vp_id);
+out:
+
+	return VXGE_HW_OK;
+}
+
+/*
+ * __vxge_hw_device_handle_link_down_ind
+ * @hldev: HW device handle.
+ *
+ * Link down indication handler. The function is invoked by HW when
+ * Titan indicates that the link is down.
+ */
+static enum vxge_hw_status
+__vxge_hw_device_handle_link_down_ind(struct __vxge_hw_device *hldev)
+{
+	/*
+	 * If the previous link state is not down, return.
+	 */
+	if (hldev->link_state == VXGE_HW_LINK_DOWN)
+		goto exit;
+
+	hldev->link_state = VXGE_HW_LINK_DOWN;
+
+	/* notify driver */
+	if (hldev->uld_callbacks.link_down)
+		hldev->uld_callbacks.link_down(hldev);
+exit:
+	return VXGE_HW_OK;
+}
+
+/*
+ * __vxge_hw_device_handle_link_up_ind
+ * @hldev: HW device handle.
+ *
+ * Link up indication handler. The function is invoked by HW when
+ * Titan indicates that the link is up for programmable amount of time.
+ */
+static enum vxge_hw_status
+__vxge_hw_device_handle_link_up_ind(struct __vxge_hw_device *hldev)
+{
+	/*
+	 * If the previous link state is not down, return.
+	 */
+	if (hldev->link_state == VXGE_HW_LINK_UP)
+		goto exit;
+
+	hldev->link_state = VXGE_HW_LINK_UP;
+
+	/* notify driver */
+	if (hldev->uld_callbacks.link_up)
+		hldev->uld_callbacks.link_up(hldev);
+exit:
+	return VXGE_HW_OK;
+}
+
+/*
+ * __vxge_hw_vpath_alarm_process - Process Alarms.
+ * @vpath: Virtual Path.
+ * @skip_alarms: Do not clear the alarms
+ *
+ * Process vpath alarms.
+ *
+ */
+static enum vxge_hw_status
+__vxge_hw_vpath_alarm_process(struct __vxge_hw_virtualpath *vpath,
+			      u32 skip_alarms)
+{
+	u64 val64;
+	u64 alarm_status;
+	u64 pic_status;
+	struct __vxge_hw_device *hldev = NULL;
+	enum vxge_hw_event alarm_event = VXGE_HW_EVENT_UNKNOWN;
+	u64 mask64;
+	struct vxge_hw_vpath_stats_sw_info *sw_stats;
+	struct vxge_hw_vpath_reg __iomem *vp_reg;
+
+	if (vpath == NULL) {
+		alarm_event = VXGE_HW_SET_LEVEL(VXGE_HW_EVENT_UNKNOWN,
+			alarm_event);
+		goto out2;
+	}
+
+	hldev = vpath->hldev;
+	vp_reg = vpath->vp_reg;
+	alarm_status = readq(&vp_reg->vpath_general_int_status);
+
+	if (alarm_status == VXGE_HW_ALL_FOXES) {
+		alarm_event = VXGE_HW_SET_LEVEL(VXGE_HW_EVENT_SLOT_FREEZE,
+			alarm_event);
+		goto out;
+	}
+
+	sw_stats = vpath->sw_stats;
+
+	if (alarm_status & ~(
+		VXGE_HW_VPATH_GENERAL_INT_STATUS_PIC_INT |
+		VXGE_HW_VPATH_GENERAL_INT_STATUS_PCI_INT |
+		VXGE_HW_VPATH_GENERAL_INT_STATUS_WRDMA_INT |
+		VXGE_HW_VPATH_GENERAL_INT_STATUS_XMAC_INT)) {
+		sw_stats->error_stats.unknown_alarms++;
+
+		alarm_event = VXGE_HW_SET_LEVEL(VXGE_HW_EVENT_UNKNOWN,
+			alarm_event);
+		goto out;
+	}
+
+	if (alarm_status & VXGE_HW_VPATH_GENERAL_INT_STATUS_XMAC_INT) {
+
+		val64 = readq(&vp_reg->xgmac_vp_int_status);
+
+		if (val64 &
+		VXGE_HW_XGMAC_VP_INT_STATUS_ASIC_NTWK_VP_ERR_ASIC_NTWK_VP_INT) {
+
+			val64 = readq(&vp_reg->asic_ntwk_vp_err_reg);
+
+			if (((val64 &
+			      VXGE_HW_ASIC_NW_VP_ERR_REG_XMACJ_STN_FLT) &&
+			     (!(val64 &
+				VXGE_HW_ASIC_NW_VP_ERR_REG_XMACJ_STN_OK))) ||
+			    ((val64 &
+			     VXGE_HW_ASIC_NW_VP_ERR_REG_XMACJ_STN_FLT_OCCURR) &&
+			     (!(val64 &
+				VXGE_HW_ASIC_NW_VP_ERR_REG_XMACJ_STN_OK_OCCURR)
+				     ))) {
+				sw_stats->error_stats.network_sustained_fault++;
+
+				writeq(
+				VXGE_HW_ASIC_NW_VP_ERR_REG_XMACJ_STN_FLT,
+					&vp_reg->asic_ntwk_vp_err_mask);
+
+				__vxge_hw_device_handle_link_down_ind(hldev);
+				alarm_event = VXGE_HW_SET_LEVEL(
+					VXGE_HW_EVENT_LINK_DOWN, alarm_event);
+			}
+
+			if (((val64 &
+			      VXGE_HW_ASIC_NW_VP_ERR_REG_XMACJ_STN_OK) &&
+			     (!(val64 &
+				VXGE_HW_ASIC_NW_VP_ERR_REG_XMACJ_STN_FLT))) ||
+			    ((val64 &
+			      VXGE_HW_ASIC_NW_VP_ERR_REG_XMACJ_STN_OK_OCCURR) &&
+			     (!(val64 &
+				VXGE_HW_ASIC_NW_VP_ERR_REG_XMACJ_STN_FLT_OCCURR)
+				     ))) {
+
+				sw_stats->error_stats.network_sustained_ok++;
+
+				writeq(
+				VXGE_HW_ASIC_NW_VP_ERR_REG_XMACJ_STN_OK,
+					&vp_reg->asic_ntwk_vp_err_mask);
+
+				__vxge_hw_device_handle_link_up_ind(hldev);
+				alarm_event = VXGE_HW_SET_LEVEL(
+					VXGE_HW_EVENT_LINK_UP, alarm_event);
+			}
+
+			writeq(VXGE_HW_INTR_MASK_ALL,
+				&vp_reg->asic_ntwk_vp_err_reg);
+
+			alarm_event = VXGE_HW_SET_LEVEL(
+				VXGE_HW_EVENT_ALARM_CLEARED, alarm_event);
+
+			if (skip_alarms)
+				return VXGE_HW_OK;
+		}
+	}
+
+	if (alarm_status & VXGE_HW_VPATH_GENERAL_INT_STATUS_PIC_INT) {
+
+		pic_status = readq(&vp_reg->vpath_ppif_int_status);
+
+		if (pic_status &
+		    VXGE_HW_VPATH_PPIF_INT_STATUS_GENERAL_ERRORS_GENERAL_INT) {
+
+			val64 = readq(&vp_reg->general_errors_reg);
+			mask64 = readq(&vp_reg->general_errors_mask);
+
+			if ((val64 &
+				VXGE_HW_GENERAL_ERRORS_REG_INI_SERR_DET) &
+				~mask64) {
+				sw_stats->error_stats.ini_serr_det++;
+
+				alarm_event = VXGE_HW_SET_LEVEL(
+					VXGE_HW_EVENT_SERR, alarm_event);
+			}
+
+			if ((val64 &
+			    VXGE_HW_GENERAL_ERRORS_REG_DBLGEN_FIFO0_OVRFLOW) &
+				~mask64) {
+				sw_stats->error_stats.dblgen_fifo0_overflow++;
+
+				alarm_event = VXGE_HW_SET_LEVEL(
+					VXGE_HW_EVENT_FIFO_ERR, alarm_event);
+			}
+
+			if ((val64 &
+			    VXGE_HW_GENERAL_ERRORS_REG_STATSB_PIF_CHAIN_ERR) &
+				~mask64)
+				sw_stats->error_stats.statsb_pif_chain_error++;
+
+			if ((val64 &
+			   VXGE_HW_GENERAL_ERRORS_REG_STATSB_DROP_TIMEOUT_REQ) &
+				~mask64)
+				sw_stats->error_stats.statsb_drop_timeout++;
+
+			if ((val64 &
+				VXGE_HW_GENERAL_ERRORS_REG_TGT_ILLEGAL_ACCESS) &
+				~mask64)
+				sw_stats->error_stats.target_illegal_access++;
+
+			if (!skip_alarms) {
+				writeq(VXGE_HW_INTR_MASK_ALL,
+					&vp_reg->general_errors_reg);
+				alarm_event = VXGE_HW_SET_LEVEL(
+					VXGE_HW_EVENT_ALARM_CLEARED,
+					alarm_event);
+			}
+		}
+
+		if (pic_status &
+		    VXGE_HW_VPATH_PPIF_INT_STATUS_KDFCCTL_ERRORS_KDFCCTL_INT) {
+
+			val64 = readq(&vp_reg->kdfcctl_errors_reg);
+			mask64 = readq(&vp_reg->kdfcctl_errors_mask);
+
+			if ((val64 &
+			    VXGE_HW_KDFCCTL_ERRORS_REG_KDFCCTL_FIFO0_OVRWR) &
+				~mask64) {
+				sw_stats->error_stats.kdfcctl_fifo0_overwrite++;
+
+				alarm_event = VXGE_HW_SET_LEVEL(
+					VXGE_HW_EVENT_FIFO_ERR,
+					alarm_event);
+			}
+
+			if ((val64 &
+			    VXGE_HW_KDFCCTL_ERRORS_REG_KDFCCTL_FIFO0_POISON) &
+				~mask64) {
+				sw_stats->error_stats.kdfcctl_fifo0_poison++;
+
+				alarm_event = VXGE_HW_SET_LEVEL(
+					VXGE_HW_EVENT_FIFO_ERR,
+					alarm_event);
+			}
+
+			if ((val64 &
+			    VXGE_HW_KDFCCTL_ERRORS_REG_KDFCCTL_FIFO0_DMA_ERR) &
+				~mask64) {
+				sw_stats->error_stats.kdfcctl_fifo0_dma_error++;
+
+				alarm_event = VXGE_HW_SET_LEVEL(
+					VXGE_HW_EVENT_FIFO_ERR,
+					alarm_event);
+			}
+
+			if (!skip_alarms) {
+				writeq(VXGE_HW_INTR_MASK_ALL,
+					&vp_reg->kdfcctl_errors_reg);
+				alarm_event = VXGE_HW_SET_LEVEL(
+					VXGE_HW_EVENT_ALARM_CLEARED,
+					alarm_event);
+			}
+		}
+
+	}
+
+	if (alarm_status & VXGE_HW_VPATH_GENERAL_INT_STATUS_WRDMA_INT) {
+
+		val64 = readq(&vp_reg->wrdma_alarm_status);
+
+		if (val64 & VXGE_HW_WRDMA_ALARM_STATUS_PRC_ALARM_PRC_INT) {
+
+			val64 = readq(&vp_reg->prc_alarm_reg);
+			mask64 = readq(&vp_reg->prc_alarm_mask);
+
+			if ((val64 & VXGE_HW_PRC_ALARM_REG_PRC_RING_BUMP)&
+				~mask64)
+				sw_stats->error_stats.prc_ring_bumps++;
+
+			if ((val64 & VXGE_HW_PRC_ALARM_REG_PRC_RXDCM_SC_ERR) &
+				~mask64) {
+				sw_stats->error_stats.prc_rxdcm_sc_err++;
+
+				alarm_event = VXGE_HW_SET_LEVEL(
+					VXGE_HW_EVENT_VPATH_ERR,
+					alarm_event);
+			}
+
+			if ((val64 & VXGE_HW_PRC_ALARM_REG_PRC_RXDCM_SC_ABORT)
+				& ~mask64) {
+				sw_stats->error_stats.prc_rxdcm_sc_abort++;
+
+				alarm_event = VXGE_HW_SET_LEVEL(
+						VXGE_HW_EVENT_VPATH_ERR,
+						alarm_event);
+			}
+
+			if ((val64 & VXGE_HW_PRC_ALARM_REG_PRC_QUANTA_SIZE_ERR)
+				 & ~mask64) {
+				sw_stats->error_stats.prc_quanta_size_err++;
+
+				alarm_event = VXGE_HW_SET_LEVEL(
+					VXGE_HW_EVENT_VPATH_ERR,
+					alarm_event);
+			}
+
+			if (!skip_alarms) {
+				writeq(VXGE_HW_INTR_MASK_ALL,
+					&vp_reg->prc_alarm_reg);
+				alarm_event = VXGE_HW_SET_LEVEL(
+						VXGE_HW_EVENT_ALARM_CLEARED,
+						alarm_event);
+			}
+		}
+	}
+out:
+	hldev->stats.sw_dev_err_stats.vpath_alarms++;
+out2:
+	if ((alarm_event == VXGE_HW_EVENT_ALARM_CLEARED) ||
+		(alarm_event == VXGE_HW_EVENT_UNKNOWN))
+		return VXGE_HW_OK;
+
+	__vxge_hw_device_handle_error(hldev, vpath->vp_id, alarm_event);
+
+	if (alarm_event == VXGE_HW_EVENT_SERR)
+		return VXGE_HW_ERR_CRITICAL;
+
+	return (alarm_event == VXGE_HW_EVENT_SLOT_FREEZE) ?
+		VXGE_HW_ERR_SLOT_FREEZE :
+		(alarm_event == VXGE_HW_EVENT_FIFO_ERR) ? VXGE_HW_ERR_FIFO :
+		VXGE_HW_ERR_VPATH;
+}
+
+/**
  * vxge_hw_device_begin_irq - Begin IRQ processing.
  * @hldev: HW device handle.
  * @skip_alarms: Do not clear the alarms
@@ -513,108 +884,6 @@ exit:
 	return ret;
 }
 
-/*
- * __vxge_hw_device_handle_link_up_ind
- * @hldev: HW device handle.
- *
- * Link up indication handler. The function is invoked by HW when
- * Titan indicates that the link is up for programmable amount of time.
- */
-static enum vxge_hw_status
-__vxge_hw_device_handle_link_up_ind(struct __vxge_hw_device *hldev)
-{
-	/*
-	 * If the previous link state is not down, return.
-	 */
-	if (hldev->link_state == VXGE_HW_LINK_UP)
-		goto exit;
-
-	hldev->link_state = VXGE_HW_LINK_UP;
-
-	/* notify driver */
-	if (hldev->uld_callbacks.link_up)
-		hldev->uld_callbacks.link_up(hldev);
-exit:
-	return VXGE_HW_OK;
-}
-
-/*
- * __vxge_hw_device_handle_link_down_ind
- * @hldev: HW device handle.
- *
- * Link down indication handler. The function is invoked by HW when
- * Titan indicates that the link is down.
- */
-static enum vxge_hw_status
-__vxge_hw_device_handle_link_down_ind(struct __vxge_hw_device *hldev)
-{
-	/*
-	 * If the previous link state is not down, return.
-	 */
-	if (hldev->link_state == VXGE_HW_LINK_DOWN)
-		goto exit;
-
-	hldev->link_state = VXGE_HW_LINK_DOWN;
-
-	/* notify driver */
-	if (hldev->uld_callbacks.link_down)
-		hldev->uld_callbacks.link_down(hldev);
-exit:
-	return VXGE_HW_OK;
-}
-
-/**
- * __vxge_hw_device_handle_error - Handle error
- * @hldev: HW device
- * @vp_id: Vpath Id
- * @type: Error type. Please see enum vxge_hw_event{}
- *
- * Handle error.
- */
-static enum vxge_hw_status
-__vxge_hw_device_handle_error(
-		struct __vxge_hw_device *hldev,
-		u32 vp_id,
-		enum vxge_hw_event type)
-{
-	switch (type) {
-	case VXGE_HW_EVENT_UNKNOWN:
-		break;
-	case VXGE_HW_EVENT_RESET_START:
-	case VXGE_HW_EVENT_RESET_COMPLETE:
-	case VXGE_HW_EVENT_LINK_DOWN:
-	case VXGE_HW_EVENT_LINK_UP:
-		goto out;
-	case VXGE_HW_EVENT_ALARM_CLEARED:
-		goto out;
-	case VXGE_HW_EVENT_ECCERR:
-	case VXGE_HW_EVENT_MRPCIM_ECCERR:
-		goto out;
-	case VXGE_HW_EVENT_FIFO_ERR:
-	case VXGE_HW_EVENT_VPATH_ERR:
-	case VXGE_HW_EVENT_CRITICAL_ERR:
-	case VXGE_HW_EVENT_SERR:
-		break;
-	case VXGE_HW_EVENT_SRPCIM_SERR:
-	case VXGE_HW_EVENT_MRPCIM_SERR:
-		goto out;
-	case VXGE_HW_EVENT_SLOT_FREEZE:
-		break;
-	default:
-		vxge_assert(0);
-		goto out;
-	}
-
-	/* notify driver */
-	if (hldev->uld_callbacks.crit_err)
-		hldev->uld_callbacks.crit_err(
-			(struct __vxge_hw_device *)hldev,
-			type, vp_id);
-out:
-
-	return VXGE_HW_OK;
-}
-
 /**
  * vxge_hw_device_clear_tx_rx - Acknowledge (that is, clear) the
  * condition that has caused the Tx and RX interrupt.
@@ -699,8 +968,8 @@ _alloc_after_swap:
  * Posts a dtr to work array.
  *
  */
-static void vxge_hw_channel_dtr_post(struct __vxge_hw_channel *channel,
-				     void *dtrh)
+static void
+vxge_hw_channel_dtr_post(struct __vxge_hw_channel *channel, void *dtrh)
 {
 	vxge_assert(channel->work_arr[channel->post_index] == NULL);
 
@@ -911,10 +1180,6 @@ void vxge_hw_ring_rxd_post(struct __vxge
  */
 void vxge_hw_ring_rxd_post_post_wmb(struct __vxge_hw_ring *ring, void *rxdh)
 {
-	struct __vxge_hw_channel *channel;
-
-	channel = &ring->channel;
-
 	wmb();
 	vxge_hw_ring_rxd_post_post(ring, rxdh);
 }
@@ -975,7 +1240,7 @@ enum vxge_hw_status vxge_hw_ring_rxd_nex
 	*t_code	= (u8)VXGE_HW_RING_RXD_T_CODE_GET(control_0);
 
 	/* check whether it is not the end */
-	if (!own || ((*t_code == VXGE_HW_RING_T_CODE_FRM_DROP) && own)) {
+	if (!own || *t_code == VXGE_HW_RING_T_CODE_FRM_DROP) {
 
 		vxge_assert(((struct vxge_hw_ring_rxd_1 *)rxdp)->host_control !=
 				0);
@@ -1868,284 +2133,6 @@ exit:
 }
 
 /*
- * __vxge_hw_vpath_alarm_process - Process Alarms.
- * @vpath: Virtual Path.
- * @skip_alarms: Do not clear the alarms
- *
- * Process vpath alarms.
- *
- */
-static enum vxge_hw_status
-__vxge_hw_vpath_alarm_process(struct __vxge_hw_virtualpath *vpath,
-			      u32 skip_alarms)
-{
-	u64 val64;
-	u64 alarm_status;
-	u64 pic_status;
-	struct __vxge_hw_device *hldev = NULL;
-	enum vxge_hw_event alarm_event = VXGE_HW_EVENT_UNKNOWN;
-	u64 mask64;
-	struct vxge_hw_vpath_stats_sw_info *sw_stats;
-	struct vxge_hw_vpath_reg __iomem *vp_reg;
-
-	if (vpath == NULL) {
-		alarm_event = VXGE_HW_SET_LEVEL(VXGE_HW_EVENT_UNKNOWN,
-			alarm_event);
-		goto out2;
-	}
-
-	hldev = vpath->hldev;
-	vp_reg = vpath->vp_reg;
-	alarm_status = readq(&vp_reg->vpath_general_int_status);
-
-	if (alarm_status == VXGE_HW_ALL_FOXES) {
-		alarm_event = VXGE_HW_SET_LEVEL(VXGE_HW_EVENT_SLOT_FREEZE,
-			alarm_event);
-		goto out;
-	}
-
-	sw_stats = vpath->sw_stats;
-
-	if (alarm_status & ~(
-		VXGE_HW_VPATH_GENERAL_INT_STATUS_PIC_INT |
-		VXGE_HW_VPATH_GENERAL_INT_STATUS_PCI_INT |
-		VXGE_HW_VPATH_GENERAL_INT_STATUS_WRDMA_INT |
-		VXGE_HW_VPATH_GENERAL_INT_STATUS_XMAC_INT)) {
-		sw_stats->error_stats.unknown_alarms++;
-
-		alarm_event = VXGE_HW_SET_LEVEL(VXGE_HW_EVENT_UNKNOWN,
-			alarm_event);
-		goto out;
-	}
-
-	if (alarm_status & VXGE_HW_VPATH_GENERAL_INT_STATUS_XMAC_INT) {
-
-		val64 = readq(&vp_reg->xgmac_vp_int_status);
-
-		if (val64 &
-		VXGE_HW_XGMAC_VP_INT_STATUS_ASIC_NTWK_VP_ERR_ASIC_NTWK_VP_INT) {
-
-			val64 = readq(&vp_reg->asic_ntwk_vp_err_reg);
-
-			if (((val64 &
-			      VXGE_HW_ASIC_NW_VP_ERR_REG_XMACJ_STN_FLT) &&
-			     (!(val64 &
-				VXGE_HW_ASIC_NW_VP_ERR_REG_XMACJ_STN_OK))) ||
-			    ((val64 &
-			      VXGE_HW_ASIC_NW_VP_ERR_REG_XMACJ_STN_FLT_OCCURR) &&
-			     (!(val64 &
-				VXGE_HW_ASIC_NW_VP_ERR_REG_XMACJ_STN_OK_OCCURR)
-				     ))) {
-				sw_stats->error_stats.network_sustained_fault++;
-
-				writeq(
-				VXGE_HW_ASIC_NW_VP_ERR_REG_XMACJ_STN_FLT,
-					&vp_reg->asic_ntwk_vp_err_mask);
-
-				__vxge_hw_device_handle_link_down_ind(hldev);
-				alarm_event = VXGE_HW_SET_LEVEL(
-					VXGE_HW_EVENT_LINK_DOWN, alarm_event);
-			}
-
-			if (((val64 &
-			      VXGE_HW_ASIC_NW_VP_ERR_REG_XMACJ_STN_OK) &&
-			     (!(val64 &
-				VXGE_HW_ASIC_NW_VP_ERR_REG_XMACJ_STN_FLT))) ||
-			    ((val64 &
-			      VXGE_HW_ASIC_NW_VP_ERR_REG_XMACJ_STN_OK_OCCURR) &&
-			     (!(val64 &
-				VXGE_HW_ASIC_NW_VP_ERR_REG_XMACJ_STN_FLT_OCCURR)
-				     ))) {
-
-				sw_stats->error_stats.network_sustained_ok++;
-
-				writeq(
-				VXGE_HW_ASIC_NW_VP_ERR_REG_XMACJ_STN_OK,
-					&vp_reg->asic_ntwk_vp_err_mask);
-
-				__vxge_hw_device_handle_link_up_ind(hldev);
-				alarm_event = VXGE_HW_SET_LEVEL(
-					VXGE_HW_EVENT_LINK_UP, alarm_event);
-			}
-
-			writeq(VXGE_HW_INTR_MASK_ALL,
-				&vp_reg->asic_ntwk_vp_err_reg);
-
-			alarm_event = VXGE_HW_SET_LEVEL(
-				VXGE_HW_EVENT_ALARM_CLEARED, alarm_event);
-
-			if (skip_alarms)
-				return VXGE_HW_OK;
-		}
-	}
-
-	if (alarm_status & VXGE_HW_VPATH_GENERAL_INT_STATUS_PIC_INT) {
-
-		pic_status = readq(&vp_reg->vpath_ppif_int_status);
-
-		if (pic_status &
-		    VXGE_HW_VPATH_PPIF_INT_STATUS_GENERAL_ERRORS_GENERAL_INT) {
-
-			val64 = readq(&vp_reg->general_errors_reg);
-			mask64 = readq(&vp_reg->general_errors_mask);
-
-			if ((val64 &
-				VXGE_HW_GENERAL_ERRORS_REG_INI_SERR_DET) &
-				~mask64) {
-				sw_stats->error_stats.ini_serr_det++;
-
-				alarm_event = VXGE_HW_SET_LEVEL(
-					VXGE_HW_EVENT_SERR, alarm_event);
-			}
-
-			if ((val64 &
-			    VXGE_HW_GENERAL_ERRORS_REG_DBLGEN_FIFO0_OVRFLOW) &
-				~mask64) {
-				sw_stats->error_stats.dblgen_fifo0_overflow++;
-
-				alarm_event = VXGE_HW_SET_LEVEL(
-					VXGE_HW_EVENT_FIFO_ERR, alarm_event);
-			}
-
-			if ((val64 &
-			    VXGE_HW_GENERAL_ERRORS_REG_STATSB_PIF_CHAIN_ERR) &
-				~mask64)
-				sw_stats->error_stats.statsb_pif_chain_error++;
-
-			if ((val64 &
-			   VXGE_HW_GENERAL_ERRORS_REG_STATSB_DROP_TIMEOUT_REQ) &
-				~mask64)
-				sw_stats->error_stats.statsb_drop_timeout++;
-
-			if ((val64 &
-				VXGE_HW_GENERAL_ERRORS_REG_TGT_ILLEGAL_ACCESS) &
-				~mask64)
-				sw_stats->error_stats.target_illegal_access++;
-
-			if (!skip_alarms) {
-				writeq(VXGE_HW_INTR_MASK_ALL,
-					&vp_reg->general_errors_reg);
-				alarm_event = VXGE_HW_SET_LEVEL(
-					VXGE_HW_EVENT_ALARM_CLEARED,
-					alarm_event);
-			}
-		}
-
-		if (pic_status &
-		    VXGE_HW_VPATH_PPIF_INT_STATUS_KDFCCTL_ERRORS_KDFCCTL_INT) {
-
-			val64 = readq(&vp_reg->kdfcctl_errors_reg);
-			mask64 = readq(&vp_reg->kdfcctl_errors_mask);
-
-			if ((val64 &
-			    VXGE_HW_KDFCCTL_ERRORS_REG_KDFCCTL_FIFO0_OVRWR) &
-				~mask64) {
-				sw_stats->error_stats.kdfcctl_fifo0_overwrite++;
-
-				alarm_event = VXGE_HW_SET_LEVEL(
-					VXGE_HW_EVENT_FIFO_ERR,
-					alarm_event);
-			}
-
-			if ((val64 &
-			    VXGE_HW_KDFCCTL_ERRORS_REG_KDFCCTL_FIFO0_POISON) &
-				~mask64) {
-				sw_stats->error_stats.kdfcctl_fifo0_poison++;
-
-				alarm_event = VXGE_HW_SET_LEVEL(
-					VXGE_HW_EVENT_FIFO_ERR,
-					alarm_event);
-			}
-
-			if ((val64 &
-			    VXGE_HW_KDFCCTL_ERRORS_REG_KDFCCTL_FIFO0_DMA_ERR) &
-				~mask64) {
-				sw_stats->error_stats.kdfcctl_fifo0_dma_error++;
-
-				alarm_event = VXGE_HW_SET_LEVEL(
-					VXGE_HW_EVENT_FIFO_ERR,
-					alarm_event);
-			}
-
-			if (!skip_alarms) {
-				writeq(VXGE_HW_INTR_MASK_ALL,
-					&vp_reg->kdfcctl_errors_reg);
-				alarm_event = VXGE_HW_SET_LEVEL(
-					VXGE_HW_EVENT_ALARM_CLEARED,
-					alarm_event);
-			}
-		}
-
-	}
-
-	if (alarm_status & VXGE_HW_VPATH_GENERAL_INT_STATUS_WRDMA_INT) {
-
-		val64 = readq(&vp_reg->wrdma_alarm_status);
-
-		if (val64 & VXGE_HW_WRDMA_ALARM_STATUS_PRC_ALARM_PRC_INT) {
-
-			val64 = readq(&vp_reg->prc_alarm_reg);
-			mask64 = readq(&vp_reg->prc_alarm_mask);
-
-			if ((val64 & VXGE_HW_PRC_ALARM_REG_PRC_RING_BUMP)&
-				~mask64)
-				sw_stats->error_stats.prc_ring_bumps++;
-
-			if ((val64 & VXGE_HW_PRC_ALARM_REG_PRC_RXDCM_SC_ERR) &
-				~mask64) {
-				sw_stats->error_stats.prc_rxdcm_sc_err++;
-
-				alarm_event = VXGE_HW_SET_LEVEL(
-					VXGE_HW_EVENT_VPATH_ERR,
-					alarm_event);
-			}
-
-			if ((val64 & VXGE_HW_PRC_ALARM_REG_PRC_RXDCM_SC_ABORT)
-				& ~mask64) {
-				sw_stats->error_stats.prc_rxdcm_sc_abort++;
-
-				alarm_event = VXGE_HW_SET_LEVEL(
-						VXGE_HW_EVENT_VPATH_ERR,
-						alarm_event);
-			}
-
-			if ((val64 & VXGE_HW_PRC_ALARM_REG_PRC_QUANTA_SIZE_ERR)
-				 & ~mask64) {
-				sw_stats->error_stats.prc_quanta_size_err++;
-
-				alarm_event = VXGE_HW_SET_LEVEL(
-					VXGE_HW_EVENT_VPATH_ERR,
-					alarm_event);
-			}
-
-			if (!skip_alarms) {
-				writeq(VXGE_HW_INTR_MASK_ALL,
-					&vp_reg->prc_alarm_reg);
-				alarm_event = VXGE_HW_SET_LEVEL(
-						VXGE_HW_EVENT_ALARM_CLEARED,
-						alarm_event);
-			}
-		}
-	}
-out:
-	hldev->stats.sw_dev_err_stats.vpath_alarms++;
-out2:
-	if ((alarm_event == VXGE_HW_EVENT_ALARM_CLEARED) ||
-		(alarm_event == VXGE_HW_EVENT_UNKNOWN))
-		return VXGE_HW_OK;
-
-	__vxge_hw_device_handle_error(hldev, vpath->vp_id, alarm_event);
-
-	if (alarm_event == VXGE_HW_EVENT_SERR)
-		return VXGE_HW_ERR_CRITICAL;
-
-	return (alarm_event == VXGE_HW_EVENT_SLOT_FREEZE) ?
-		VXGE_HW_ERR_SLOT_FREEZE :
-		(alarm_event == VXGE_HW_EVENT_FIFO_ERR) ? VXGE_HW_ERR_FIFO :
-		VXGE_HW_ERR_VPATH;
-}
-
-/*
  * vxge_hw_vpath_alarm_process - Process Alarms.
  * @vpath: Virtual Path.
  * @skip_alarms: Do not clear the alarms
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/vxge/vxge-traffic.h linux-libre-2.6.38-gnu1/drivers/net/vxge/vxge-traffic.h
--- linux-libre-2.6.37-gnu1/drivers/net/vxge/vxge-traffic.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/vxge/vxge-traffic.h	2011-03-14 21:20:32.000000000 -0400
@@ -1695,7 +1695,7 @@ struct vxge_hw_device_stats_sw_err {
  * struct vxge_hw_device_stats - Contains HW per-device statistics,
  * including hw.
  * @devh: HW device handle.
- * @dma_addr: DMA addres of the %hw_info. Given to device to fill-in the stats.
+ * @dma_addr: DMA address of the %hw_info. Given to device to fill-in the stats.
  * @hw_info_dmah: DMA handle used to map hw statistics onto the device memory
  *                space.
  * @hw_info_dma_acch: One more DMA handle used subsequently to free the
@@ -1904,34 +1904,6 @@ enum vxge_hw_ring_tcode {
 	VXGE_HW_RING_T_CODE_MULTI_ERR			= 0xF
 };
 
-/**
- * enum enum vxge_hw_ring_hash_type - RTH hash types
- * @VXGE_HW_RING_HASH_TYPE_NONE: No Hash
- * @VXGE_HW_RING_HASH_TYPE_TCP_IPV4: TCP IPv4
- * @VXGE_HW_RING_HASH_TYPE_UDP_IPV4: UDP IPv4
- * @VXGE_HW_RING_HASH_TYPE_IPV4: IPv4
- * @VXGE_HW_RING_HASH_TYPE_TCP_IPV6: TCP IPv6
- * @VXGE_HW_RING_HASH_TYPE_UDP_IPV6: UDP IPv6
- * @VXGE_HW_RING_HASH_TYPE_IPV6: IPv6
- * @VXGE_HW_RING_HASH_TYPE_TCP_IPV6_EX: TCP IPv6 extension
- * @VXGE_HW_RING_HASH_TYPE_UDP_IPV6_EX: UDP IPv6 extension
- * @VXGE_HW_RING_HASH_TYPE_IPV6_EX: IPv6 extension
- *
- * RTH hash types
- */
-enum vxge_hw_ring_hash_type {
-	VXGE_HW_RING_HASH_TYPE_NONE			= 0x0,
-	VXGE_HW_RING_HASH_TYPE_TCP_IPV4		= 0x1,
-	VXGE_HW_RING_HASH_TYPE_UDP_IPV4		= 0x2,
-	VXGE_HW_RING_HASH_TYPE_IPV4			= 0x3,
-	VXGE_HW_RING_HASH_TYPE_TCP_IPV6		= 0x4,
-	VXGE_HW_RING_HASH_TYPE_UDP_IPV6		= 0x5,
-	VXGE_HW_RING_HASH_TYPE_IPV6			= 0x6,
-	VXGE_HW_RING_HASH_TYPE_TCP_IPV6_EX	= 0x7,
-	VXGE_HW_RING_HASH_TYPE_UDP_IPV6_EX	= 0x8,
-	VXGE_HW_RING_HASH_TYPE_IPV6_EX		= 0x9
-};
-
 enum vxge_hw_status vxge_hw_ring_rxd_reserve(
 	struct __vxge_hw_ring *ring_handle,
 	void **rxdh);
@@ -2109,10 +2081,6 @@ struct __vxge_hw_ring_rxd_priv {
 #endif
 };
 
-/* ========================= FIFO PRIVATE API ============================= */
-
-struct vxge_hw_fifo_attr;
-
 struct vxge_hw_mempool_cbs {
 	void (*item_func_alloc)(
 			struct vxge_hw_mempool *mempoolh,
@@ -2186,27 +2154,27 @@ enum vxge_hw_vpath_mac_addr_add_mode {
 enum vxge_hw_status
 vxge_hw_vpath_mac_addr_add(
 	struct __vxge_hw_vpath_handle *vpath_handle,
-	u8 (macaddr)[ETH_ALEN],
-	u8 (macaddr_mask)[ETH_ALEN],
+	u8 *macaddr,
+	u8 *macaddr_mask,
 	enum vxge_hw_vpath_mac_addr_add_mode duplicate_mode);
 
 enum vxge_hw_status
 vxge_hw_vpath_mac_addr_get(
 	struct __vxge_hw_vpath_handle *vpath_handle,
-	u8 (macaddr)[ETH_ALEN],
-	u8 (macaddr_mask)[ETH_ALEN]);
+	u8 *macaddr,
+	u8 *macaddr_mask);
 
 enum vxge_hw_status
 vxge_hw_vpath_mac_addr_get_next(
 	struct __vxge_hw_vpath_handle *vpath_handle,
-	u8 (macaddr)[ETH_ALEN],
-	u8 (macaddr_mask)[ETH_ALEN]);
+	u8 *macaddr,
+	u8 *macaddr_mask);
 
 enum vxge_hw_status
 vxge_hw_vpath_mac_addr_delete(
 	struct __vxge_hw_vpath_handle *vpath_handle,
-	u8 (macaddr)[ETH_ALEN],
-	u8 (macaddr_mask)[ETH_ALEN]);
+	u8 *macaddr,
+	u8 *macaddr_mask);
 
 enum vxge_hw_status
 vxge_hw_vpath_vid_add(
@@ -2313,6 +2281,7 @@ vxge_hw_channel_dtr_free(struct __vxge_h
 
 int
 vxge_hw_channel_dtr_count(struct __vxge_hw_channel *channel);
+
 void
 vxge_hw_vpath_tti_ci_set(struct __vxge_hw_device *hldev, u32 vp_id);
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/vxge/vxge-version.h linux-libre-2.6.38-gnu1/drivers/net/vxge/vxge-version.h
--- linux-libre-2.6.37-gnu1/drivers/net/vxge/vxge-version.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/vxge/vxge-version.h	2011-03-14 21:20:32.000000000 -0400
@@ -15,8 +15,35 @@
 #define VXGE_VERSION_H
 
 #define VXGE_VERSION_MAJOR	"2"
-#define VXGE_VERSION_MINOR	"0"
-#define VXGE_VERSION_FIX	"9"
-#define VXGE_VERSION_BUILD	"20840"
+#define VXGE_VERSION_MINOR	"5"
+#define VXGE_VERSION_FIX	"1"
+#define VXGE_VERSION_BUILD	"22082"
 #define VXGE_VERSION_FOR	"k"
+
+#define VXGE_FW_VER(maj, min, bld) (((maj) << 16) + ((min) << 8) + (bld))
+
+#define VXGE_DEAD_FW_VER_MAJOR	1
+#define VXGE_DEAD_FW_VER_MINOR	4
+#define VXGE_DEAD_FW_VER_BUILD	4
+
+#define VXGE_FW_DEAD_VER VXGE_FW_VER(VXGE_DEAD_FW_VER_MAJOR, \
+				     VXGE_DEAD_FW_VER_MINOR, \
+				     VXGE_DEAD_FW_VER_BUILD)
+
+#define VXGE_EPROM_FW_VER_MAJOR	1
+#define VXGE_EPROM_FW_VER_MINOR	6
+#define VXGE_EPROM_FW_VER_BUILD	1
+
+#define VXGE_EPROM_FW_VER VXGE_FW_VER(VXGE_EPROM_FW_VER_MAJOR, \
+				      VXGE_EPROM_FW_VER_MINOR, \
+				      VXGE_EPROM_FW_VER_BUILD)
+
+#define VXGE_CERT_FW_VER_MAJOR	1
+#define VXGE_CERT_FW_VER_MINOR	8
+#define VXGE_CERT_FW_VER_BUILD	1
+
+#define VXGE_CERT_FW_VER VXGE_FW_VER(VXGE_CERT_FW_VER_MAJOR, \
+				     VXGE_CERT_FW_VER_MINOR, \
+				     VXGE_CERT_FW_VER_BUILD)
+
 #endif
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wan/dscc4.c linux-libre-2.6.38-gnu1/drivers/net/wan/dscc4.c
--- linux-libre-2.6.37-gnu1/drivers/net/wan/dscc4.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wan/dscc4.c	2011-03-14 21:20:32.000000000 -0400
@@ -125,7 +125,7 @@ static u32 dscc4_pci_config_store[16];
 /* Module parameters */
 
 MODULE_AUTHOR("Maintainer: Francois Romieu <romieu@cogenit.fr>");
-MODULE_DESCRIPTION("Siemens PEB20534 PCI Controler");
+MODULE_DESCRIPTION("Siemens PEB20534 PCI Controller");
 MODULE_LICENSE("GPL");
 module_param(debug, int, 0);
 MODULE_PARM_DESC(debug,"Enable/disable extra messages");
@@ -1358,7 +1358,7 @@ static int dscc4_ioctl(struct net_device
 	return ret;
 }
 
-static int dscc4_match(struct thingie *p, int value)
+static int dscc4_match(const struct thingie *p, int value)
 {
 	int i;
 
@@ -1403,7 +1403,7 @@ done:
 static int dscc4_encoding_setting(struct dscc4_dev_priv *dpriv,
 				  struct net_device *dev)
 {
-	struct thingie encoding[] = {
+	static const struct thingie encoding[] = {
 		{ ENCODING_NRZ,		0x00000000 },
 		{ ENCODING_NRZI,	0x00200000 },
 		{ ENCODING_FM_MARK,	0x00400000 },
@@ -1442,7 +1442,7 @@ static int dscc4_loopback_setting(struct
 static int dscc4_crc_setting(struct dscc4_dev_priv *dpriv,
 			     struct net_device *dev)
 {
-	struct thingie crc[] = {
+	static const struct thingie crc[] = {
 		{ PARITY_CRC16_PR0_CCITT,	0x00000010 },
 		{ PARITY_CRC16_PR1_CCITT,	0x00000000 },
 		{ PARITY_CRC32_PR0_CCITT,	0x00000011 },
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wd.c linux-libre-2.6.38-gnu1/drivers/net/wd.c
--- linux-libre-2.6.37-gnu1/drivers/net/wd.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wd.c	2011-03-14 21:20:32.000000000 -0400
@@ -275,7 +275,7 @@ static int __init wd_probe1(struct net_d
 	dev->base_addr = ioaddr+WD_NIC_OFFSET;
 
 	if (dev->irq < 2) {
-		int irqmap[] = {9,3,5,7,10,11,15,4};
+		static const int irqmap[] = {9, 3, 5, 7, 10, 11, 15, 4};
 		int reg1 = inb(ioaddr+1);
 		int reg4 = inb(ioaddr+4);
 		if (ancient || reg1 == 0xff) {	/* Ack!! No way to read the IRQ! */
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wimax/i2400m/driver.c linux-libre-2.6.38-gnu1/drivers/net/wimax/i2400m/driver.c
--- linux-libre-2.6.37-gnu1/drivers/net/wimax/i2400m/driver.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wimax/i2400m/driver.c	2011-03-14 21:20:32.000000000 -0400
@@ -92,54 +92,6 @@ MODULE_PARM_DESC(barkers,
 		 "signal; values are appended to a list--setting one value "
 		 "as zero cleans the existing list and starts a new one.");
 
-static
-struct i2400m_work *__i2400m_work_setup(
-	struct i2400m *i2400m, void (*fn)(struct work_struct *),
-	gfp_t gfp_flags, const void *pl, size_t pl_size)
-{
-	struct i2400m_work *iw;
-
-	iw = kzalloc(sizeof(*iw) + pl_size, gfp_flags);
-	if (iw == NULL)
-		return NULL;
-	iw->i2400m = i2400m_get(i2400m);
-	iw->pl_size = pl_size;
-	memcpy(iw->pl, pl, pl_size);
-	INIT_WORK(&iw->ws, fn);
-	return iw;
-}
-
-
-/*
- * Schedule i2400m's specific work on the system's queue.
- *
- * Used for a few cases where we really need it; otherwise, identical
- * to i2400m_queue_work().
- *
- * Returns < 0 errno code on error, 1 if ok.
- *
- * If it returns zero, something really bad happened, as it means the
- * works struct was already queued, but we have just allocated it, so
- * it should not happen.
- */
-static int i2400m_schedule_work(struct i2400m *i2400m,
-			 void (*fn)(struct work_struct *), gfp_t gfp_flags,
-			 const void *pl, size_t pl_size)
-{
-	int result;
-	struct i2400m_work *iw;
-
-	result = -ENOMEM;
-	iw = __i2400m_work_setup(i2400m, fn, gfp_flags, pl, pl_size);
-	if (iw != NULL) {
-		result = schedule_work(&iw->ws);
-		if (WARN_ON(result == 0))
-			result = -ENXIO;
-	}
-	return result;
-}
-
-
 /*
  * WiMAX stack operation: relay a message from user space
  *
@@ -280,7 +232,7 @@ int i2400m_check_mac_addr(struct i2400m
 			result);
 		goto error;
 	}
-	/* Extract MAC addresss */
+	/* Extract MAC address */
 	ddi = (void *) skb->data;
 	BUILD_BUG_ON(ETH_ALEN != sizeof(ddi->mac_address));
 	d_printf(2, dev, "GET DEVICE INFO: mac addr %pM\n",
@@ -648,17 +600,11 @@ EXPORT_SYMBOL_GPL(i2400m_post_reset);
 static
 void __i2400m_dev_reset_handle(struct work_struct *ws)
 {
-	int result;
-	struct i2400m_work *iw = container_of(ws, struct i2400m_work, ws);
-	const char *reason;
-	struct i2400m *i2400m = iw->i2400m;
+	struct i2400m *i2400m = container_of(ws, struct i2400m, reset_ws);
+	const char *reason = i2400m->reset_reason;
 	struct device *dev = i2400m_dev(i2400m);
 	struct i2400m_reset_ctx *ctx = i2400m->reset_ctx;
-
-	if (WARN_ON(iw->pl_size != sizeof(reason)))
-		reason = "SW BUG: reason n/a";
-	else
-		memcpy(&reason, iw->pl, sizeof(reason));
+	int result;
 
 	d_fnstart(3, dev, "(ws %p i2400m %p reason %s)\n", ws, i2400m, reason);
 
@@ -733,8 +679,6 @@ void __i2400m_dev_reset_handle(struct wo
 		}
 	}
 out:
-	i2400m_put(i2400m);
-	kfree(iw);
 	d_fnend(3, dev, "(ws %p i2400m %p reason %s) = void\n",
 		ws, i2400m, reason);
 }
@@ -754,8 +698,8 @@ out:
  */
 int i2400m_dev_reset_handle(struct i2400m *i2400m, const char *reason)
 {
-	return i2400m_schedule_work(i2400m, __i2400m_dev_reset_handle,
-				    GFP_ATOMIC, &reason, sizeof(reason));
+	i2400m->reset_reason = reason;
+	return schedule_work(&i2400m->reset_ws);
 }
 EXPORT_SYMBOL_GPL(i2400m_dev_reset_handle);
 
@@ -768,14 +712,9 @@ EXPORT_SYMBOL_GPL(i2400m_dev_reset_handl
 static
 void __i2400m_error_recovery(struct work_struct *ws)
 {
-	struct i2400m_work *iw = container_of(ws, struct i2400m_work, ws);
-	struct i2400m *i2400m = iw->i2400m;
+	struct i2400m *i2400m = container_of(ws, struct i2400m, recovery_ws);
 
 	i2400m_reset(i2400m, I2400M_RT_BUS);
-
-	i2400m_put(i2400m);
-	kfree(iw);
-	return;
 }
 
 /*
@@ -805,18 +744,10 @@ void __i2400m_error_recovery(struct work
  */
 void i2400m_error_recovery(struct i2400m *i2400m)
 {
-	struct device *dev = i2400m_dev(i2400m);
-
-	if (atomic_add_return(1, &i2400m->error_recovery) == 1) {
-		if (i2400m_schedule_work(i2400m, __i2400m_error_recovery,
-			GFP_ATOMIC, NULL, 0) < 0) {
-			dev_err(dev, "run out of memory for "
-				"scheduling an error recovery ?\n");
-			atomic_dec(&i2400m->error_recovery);
-		}
-	} else
+	if (atomic_add_return(1, &i2400m->error_recovery) == 1)
+		schedule_work(&i2400m->recovery_ws);
+	else
 		atomic_dec(&i2400m->error_recovery);
-	return;
 }
 EXPORT_SYMBOL_GPL(i2400m_error_recovery);
 
@@ -886,6 +817,10 @@ void i2400m_init(struct i2400m *i2400m)
 
 	mutex_init(&i2400m->init_mutex);
 	/* wake_tx_ws is initialized in i2400m_tx_setup() */
+
+	INIT_WORK(&i2400m->reset_ws, __i2400m_dev_reset_handle);
+	INIT_WORK(&i2400m->recovery_ws, __i2400m_error_recovery);
+
 	atomic_set(&i2400m->bus_reset_retries, 0);
 
 	i2400m->alive = 0;
@@ -1040,6 +975,9 @@ void i2400m_release(struct i2400m *i2400
 
 	i2400m_dev_stop(i2400m);
 
+	cancel_work_sync(&i2400m->reset_ws);
+	cancel_work_sync(&i2400m->recovery_ws);
+
 	i2400m_debugfs_rm(i2400m);
 	sysfs_remove_group(&i2400m->wimax_dev.net_dev->dev.kobj,
 			   &i2400m_dev_attr_group);
@@ -1083,8 +1021,6 @@ module_init(i2400m_driver_init);
 static
 void __exit i2400m_driver_exit(void)
 {
-	/* for scheds i2400m_dev_reset_handle() */
-	flush_scheduled_work();
 	i2400m_barker_db_exit();
 }
 module_exit(i2400m_driver_exit);
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wimax/i2400m/i2400m.h linux-libre-2.6.38-gnu1/drivers/net/wimax/i2400m/i2400m.h
--- linux-libre-2.6.37-gnu1/drivers/net/wimax/i2400m/i2400m.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wimax/i2400m/i2400m.h	2011-03-14 21:20:32.000000000 -0400
@@ -186,7 +186,7 @@ enum {
  * struct i2400m_poke_table - Hardware poke table for the Intel 2400m
  *
  * This structure will be used to create a device specific poke table
- * to put the device in a consistant state at boot time.
+ * to put the device in a consistent state at boot time.
  *
  * @address: The device address to poke
  *
@@ -632,6 +632,11 @@ struct i2400m {
 	struct work_struct wake_tx_ws;
 	struct sk_buff *wake_tx_skb;
 
+	struct work_struct reset_ws;
+	const char *reset_reason;
+
+	struct work_struct recovery_ws;
+
 	struct dentry *debugfs_dentry;
 	const char *fw_name;		/* name of the current firmware image */
 	unsigned long fw_version;	/* version of the firmware interface */
@@ -698,7 +703,7 @@ enum i2400m_bm_cmd_flags {
  * @I2400M_BRI_MAC_REINIT: We need to reinitialize the boot
  *     rom after reading the MAC address. This is quite a dirty hack,
  *     if you ask me -- the device requires the bootrom to be
- *     intialized after reading the MAC address.
+ *     initialized after reading the MAC address.
  */
 enum i2400m_bri {
 	I2400M_BRI_SOFT       = 1 << 1,
@@ -896,20 +901,6 @@ struct device *i2400m_dev(struct i2400m
 	return i2400m->wimax_dev.net_dev->dev.parent;
 }
 
-/*
- * Helper for scheduling simple work functions
- *
- * This struct can get any kind of payload attached (normally in the
- * form of a struct where you pack the stuff you want to pass to the
- * _work function).
- */
-struct i2400m_work {
-	struct work_struct ws;
-	struct i2400m *i2400m;
-	size_t pl_size;
-	u8 pl[0];
-};
-
 extern int i2400m_msg_check_status(const struct i2400m_l3l4_hdr *,
 				   char *, size_t);
 extern int i2400m_msg_size_check(struct i2400m *,
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wimax/i2400m/sdio.c linux-libre-2.6.38-gnu1/drivers/net/wimax/i2400m/sdio.c
--- linux-libre-2.6.37-gnu1/drivers/net/wimax/i2400m/sdio.c	2013-05-03 04:02:55.000000000 -0400
+++ linux-libre-2.6.38-gnu1/drivers/net/wimax/i2400m/sdio.c	2013-05-03 02:03:57.000000000 -0400
@@ -590,7 +590,6 @@ module_init(i2400ms_driver_init);
 static
 void __exit i2400ms_driver_exit(void)
 {
-	flush_scheduled_work();	/* for the stuff we schedule */
 	sdio_unregister_driver(&i2400m_sdio_driver);
 }
 module_exit(i2400ms_driver_exit);
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wimax/i2400m/usb.c linux-libre-2.6.38-gnu1/drivers/net/wimax/i2400m/usb.c
--- linux-libre-2.6.37-gnu1/drivers/net/wimax/i2400m/usb.c	2013-05-03 04:02:57.000000000 -0400
+++ linux-libre-2.6.38-gnu1/drivers/net/wimax/i2400m/usb.c	2013-05-03 02:04:00.000000000 -0400
@@ -514,7 +514,7 @@ int i2400mu_probe(struct usb_interface *
 #ifdef CONFIG_PM
 	iface->needs_remote_wakeup = 1;		/* autosuspend (15s delay) */
 	device_init_wakeup(dev, 1);
-	usb_dev->autosuspend_delay = 15 * HZ;
+	pm_runtime_set_autosuspend_delay(&usb_dev->dev, 15000);
 	usb_enable_autosuspend(usb_dev);
 #endif
 
@@ -780,7 +780,6 @@ module_init(i2400mu_driver_init);
 static
 void __exit i2400mu_driver_exit(void)
 {
-	flush_scheduled_work();	/* for the stuff we schedule from sysfs.c */
 	usb_deregister(&i2400mu_driver);
 }
 module_exit(i2400mu_driver_exit);
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/airo.c linux-libre-2.6.38-gnu1/drivers/net/wireless/airo.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/airo.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/airo.c	2011-03-14 21:20:32.000000000 -0400
@@ -4652,24 +4652,18 @@ static ssize_t proc_write( struct file *
 			   size_t len,
 			   loff_t *offset )
 {
-	loff_t pos = *offset;
+	ssize_t ret;
 	struct proc_data *priv = file->private_data;
 
 	if (!priv->wbuffer)
 		return -EINVAL;
 
-	if (pos < 0)
-		return -EINVAL;
-	if (pos >= priv->maxwritelen)
-		return 0;
-	if (len > priv->maxwritelen - pos)
-		len = priv->maxwritelen - pos;
-	if (copy_from_user(priv->wbuffer + pos, buffer, len))
-		return -EFAULT;
-	if ( pos + len > priv->writelen )
-		priv->writelen = len + file->f_pos;
-	*offset = pos + len;
-	return len;
+	ret = simple_write_to_buffer(priv->wbuffer, priv->maxwritelen, offset,
+					buffer, len);
+	if (ret > 0)
+		priv->writelen = max_t(int, priv->writelen, *offset);
+
+	return ret;
 }
 
 static int proc_status_open(struct inode *inode, struct file *file)
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ar9170/cmd.c linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ar9170/cmd.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ar9170/cmd.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ar9170/cmd.c	2011-03-14 21:20:32.000000000 -0400
@@ -54,7 +54,7 @@ int ar9170_write_mem(struct ar9170 *ar,
 
 int ar9170_write_reg(struct ar9170 *ar, const u32 reg, const u32 val)
 {
-	__le32 buf[2] = {
+	const __le32 buf[2] = {
 		cpu_to_le32(reg),
 		cpu_to_le32(val),
 	};
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ar9170/usb.c linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ar9170/usb.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ar9170/usb.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ar9170/usb.c	2011-03-14 21:20:32.000000000 -0400
@@ -161,8 +161,7 @@ static void ar9170_usb_submit_urb(struct
 static void ar9170_usb_tx_urb_complete_frame(struct urb *urb)
 {
 	struct sk_buff *skb = urb->context;
-	struct ar9170_usb *aru = (struct ar9170_usb *)
-	      usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0));
+	struct ar9170_usb *aru = usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0));
 
 	if (unlikely(!aru)) {
 		dev_kfree_skb_irq(skb);
@@ -219,8 +218,7 @@ free:
 static void ar9170_usb_rx_completed(struct urb *urb)
 {
 	struct sk_buff *skb = urb->context;
-	struct ar9170_usb *aru = (struct ar9170_usb *)
-		usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0));
+	struct ar9170_usb *aru = usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0));
 	int err;
 
 	if (!aru)
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath5k/ahb.c linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath5k/ahb.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath5k/ahb.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath5k/ahb.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,219 @@
+/*
+ * Copyright (c) 2008-2009 Atheros Communications Inc.
+ * Copyright (c) 2009 Gabor Juhos <juhosg@openwrt.org>
+ * Copyright (c) 2009 Imre Kaloz <kaloz@openwrt.org>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/nl80211.h>
+#include <linux/platform_device.h>
+#include <ar231x_platform.h>
+#include "ath5k.h"
+#include "debug.h"
+#include "base.h"
+#include "reg.h"
+#include "debug.h"
+
+/* return bus cachesize in 4B word units */
+static void ath5k_ahb_read_cachesize(struct ath_common *common, int *csz)
+{
+	*csz = L1_CACHE_BYTES >> 2;
+}
+
+bool ath5k_ahb_eeprom_read(struct ath_common *common, u32 off, u16 *data)
+{
+	struct ath5k_softc *sc = common->priv;
+	struct platform_device *pdev = to_platform_device(sc->dev);
+	struct ar231x_board_config *bcfg = pdev->dev.platform_data;
+	u16 *eeprom, *eeprom_end;
+
+
+
+	bcfg = pdev->dev.platform_data;
+	eeprom = (u16 *) bcfg->radio;
+	eeprom_end = ((void *) bcfg->config) + BOARD_CONFIG_BUFSZ;
+
+	eeprom += off;
+	if (eeprom > eeprom_end)
+		return -EINVAL;
+
+	*data = *eeprom;
+	return 0;
+}
+
+int ath5k_hw_read_srev(struct ath5k_hw *ah)
+{
+	struct ath5k_softc *sc = ah->ah_sc;
+	struct platform_device *pdev = to_platform_device(sc->dev);
+	struct ar231x_board_config *bcfg = pdev->dev.platform_data;
+	ah->ah_mac_srev = bcfg->devid;
+	return 0;
+}
+
+static const struct ath_bus_ops ath_ahb_bus_ops = {
+	.ath_bus_type = ATH_AHB,
+	.read_cachesize = ath5k_ahb_read_cachesize,
+	.eeprom_read = ath5k_ahb_eeprom_read,
+};
+
+/*Initialization*/
+static int ath_ahb_probe(struct platform_device *pdev)
+{
+	struct ar231x_board_config *bcfg = pdev->dev.platform_data;
+	struct ath5k_softc *sc;
+	struct ieee80211_hw *hw;
+	struct resource *res;
+	void __iomem *mem;
+	int irq;
+	int ret = 0;
+	u32 reg;
+
+	if (!pdev->dev.platform_data) {
+		dev_err(&pdev->dev, "no platform data specified\n");
+		ret = -EINVAL;
+		goto err_out;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (res == NULL) {
+		dev_err(&pdev->dev, "no memory resource found\n");
+		ret = -ENXIO;
+		goto err_out;
+	}
+
+	mem = ioremap_nocache(res->start, res->end - res->start + 1);
+	if (mem == NULL) {
+		dev_err(&pdev->dev, "ioremap failed\n");
+		ret = -ENOMEM;
+		goto err_out;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (res == NULL) {
+		dev_err(&pdev->dev, "no IRQ resource found\n");
+		ret = -ENXIO;
+		goto err_out;
+	}
+
+	irq = res->start;
+
+	hw = ieee80211_alloc_hw(sizeof(struct ath5k_softc), &ath5k_hw_ops);
+	if (hw == NULL) {
+		dev_err(&pdev->dev, "no memory for ieee80211_hw\n");
+		ret = -ENOMEM;
+		goto err_out;
+	}
+
+	sc = hw->priv;
+	sc->hw = hw;
+	sc->dev = &pdev->dev;
+	sc->iobase = mem;
+	sc->irq = irq;
+	sc->devid = bcfg->devid;
+
+	if (bcfg->devid >= AR5K_SREV_AR2315_R6) {
+		/* Enable WMAC AHB arbitration */
+		reg = __raw_readl((void __iomem *) AR5K_AR2315_AHB_ARB_CTL);
+		reg |= AR5K_AR2315_AHB_ARB_CTL_WLAN;
+		__raw_writel(reg, (void __iomem *) AR5K_AR2315_AHB_ARB_CTL);
+
+		/* Enable global WMAC swapping */
+		reg = __raw_readl((void __iomem *) AR5K_AR2315_BYTESWAP);
+		reg |= AR5K_AR2315_BYTESWAP_WMAC;
+		__raw_writel(reg, (void __iomem *) AR5K_AR2315_BYTESWAP);
+	} else {
+		/* Enable WMAC DMA access (assuming 5312 or 231x*/
+		/* TODO: check other platforms */
+		reg = __raw_readl((void __iomem *) AR5K_AR5312_ENABLE);
+		if (to_platform_device(sc->dev)->id == 0)
+			reg |= AR5K_AR5312_ENABLE_WLAN0;
+		else
+			reg |= AR5K_AR5312_ENABLE_WLAN1;
+		__raw_writel(reg, (void __iomem *) AR5K_AR5312_ENABLE);
+	}
+
+	ret = ath5k_init_softc(sc, &ath_ahb_bus_ops);
+	if (ret != 0) {
+		dev_err(&pdev->dev, "failed to attach device, err=%d\n", ret);
+		ret = -ENODEV;
+		goto err_free_hw;
+	}
+
+	platform_set_drvdata(pdev, hw);
+
+	return 0;
+
+ err_free_hw:
+	ieee80211_free_hw(hw);
+	platform_set_drvdata(pdev, NULL);
+ err_out:
+	return ret;
+}
+
+static int ath_ahb_remove(struct platform_device *pdev)
+{
+	struct ar231x_board_config *bcfg = pdev->dev.platform_data;
+	struct ieee80211_hw *hw = platform_get_drvdata(pdev);
+	struct ath5k_softc *sc;
+	u32 reg;
+
+	if (!hw)
+		return 0;
+
+	sc = hw->priv;
+
+	if (bcfg->devid >= AR5K_SREV_AR2315_R6) {
+		/* Disable WMAC AHB arbitration */
+		reg = __raw_readl((void __iomem *) AR5K_AR2315_AHB_ARB_CTL);
+		reg &= ~AR5K_AR2315_AHB_ARB_CTL_WLAN;
+		__raw_writel(reg, (void __iomem *) AR5K_AR2315_AHB_ARB_CTL);
+	} else {
+		/*Stop DMA access */
+		reg = __raw_readl((void __iomem *) AR5K_AR5312_ENABLE);
+		if (to_platform_device(sc->dev)->id == 0)
+			reg &= ~AR5K_AR5312_ENABLE_WLAN0;
+		else
+			reg &= ~AR5K_AR5312_ENABLE_WLAN1;
+		__raw_writel(reg, (void __iomem *) AR5K_AR5312_ENABLE);
+	}
+
+	ath5k_deinit_softc(sc);
+	platform_set_drvdata(pdev, NULL);
+
+	return 0;
+}
+
+static struct platform_driver ath_ahb_driver = {
+	.probe      = ath_ahb_probe,
+	.remove     = ath_ahb_remove,
+	.driver		= {
+		.name	= "ar231x-wmac",
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init
+ath5k_ahb_init(void)
+{
+	return platform_driver_register(&ath_ahb_driver);
+}
+
+static void __exit
+ath5k_ahb_exit(void)
+{
+	platform_driver_unregister(&ath_ahb_driver);
+}
+
+module_init(ath5k_ahb_init);
+module_exit(ath5k_ahb_exit);
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath5k/ani.c linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath5k/ani.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath5k/ani.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath5k/ani.c	2011-03-14 21:20:32.000000000 -0400
@@ -58,20 +58,20 @@ ath5k_ani_set_noise_immunity_level(struc
 {
 	/* TODO:
 	 * ANI documents suggest the following five levels to use, but the HAL
-	 * and ath9k use only use the last two levels, making this
+	 * and ath9k use only the last two levels, making this
 	 * essentially an on/off option. There *may* be a reason for this (???),
 	 * so i stick with the HAL version for now...
 	 */
 #if 0
-	const s8 hi[] = { -18, -18, -16, -14, -12 };
-	const s8 lo[] = { -52, -56, -60, -64, -70 };
-	const s8 sz[] = { -34, -41, -48, -55, -62 };
-	const s8 fr[] = { -70, -72, -75, -78, -80 };
+	static const s8 lo[] = { -52, -56, -60, -64, -70 };
+	static const s8 hi[] = { -18, -18, -16, -14, -12 };
+	static const s8 sz[] = { -34, -41, -48, -55, -62 };
+	static const s8 fr[] = { -70, -72, -75, -78, -80 };
 #else
-	const s8 sz[] = { -55, -62 };
-	const s8 lo[] = { -64, -70 };
-	const s8 hi[] = { -14, -12 };
-	const s8 fr[] = { -78, -80 };
+	static const s8 lo[] = { -64, -70 };
+	static const s8 hi[] = { -14, -12 };
+	static const s8 sz[] = { -55, -62 };
+	static const s8 fr[] = { -78, -80 };
 #endif
 	if (level < 0 || level >= ARRAY_SIZE(sz)) {
 		ATH5K_ERR(ah->ah_sc, "noise immuniy level %d out of range",
@@ -102,7 +102,7 @@ ath5k_ani_set_noise_immunity_level(struc
 void
 ath5k_ani_set_spur_immunity_level(struct ath5k_hw *ah, int level)
 {
-	const int val[] = { 2, 4, 6, 8, 10, 12, 14, 16 };
+	static const int val[] = { 2, 4, 6, 8, 10, 12, 14, 16 };
 
 	if (level < 0 || level >= ARRAY_SIZE(val) ||
 	    level > ah->ah_sc->ani_state.max_spur_level) {
@@ -127,7 +127,7 @@ ath5k_ani_set_spur_immunity_level(struct
 void
 ath5k_ani_set_firstep_level(struct ath5k_hw *ah, int level)
 {
-	const int val[] = { 0, 4, 8 };
+	static const int val[] = { 0, 4, 8 };
 
 	if (level < 0 || level >= ARRAY_SIZE(val)) {
 		ATH5K_ERR(ah->ah_sc, "firstep level %d out of range", level);
@@ -151,12 +151,12 @@ ath5k_ani_set_firstep_level(struct ath5k
 void
 ath5k_ani_set_ofdm_weak_signal_detection(struct ath5k_hw *ah, bool on)
 {
-	const int m1l[] = { 127, 50 };
-	const int m2l[] = { 127, 40 };
-	const int m1[] = { 127, 0x4d };
-	const int m2[] = { 127, 0x40 };
-	const int m2cnt[] = { 31, 16 };
-	const int m2lcnt[] = { 63, 48 };
+	static const int m1l[] = { 127, 50 };
+	static const int m2l[] = { 127, 40 };
+	static const int m1[] = { 127, 0x4d };
+	static const int m2[] = { 127, 0x40 };
+	static const int m2cnt[] = { 31, 16 };
+	static const int m2lcnt[] = { 63, 48 };
 
 	AR5K_REG_WRITE_BITS(ah, AR5K_PHY_WEAK_OFDM_LOW_THR,
 				AR5K_PHY_WEAK_OFDM_LOW_THR_M1, m1l[on]);
@@ -192,7 +192,7 @@ ath5k_ani_set_ofdm_weak_signal_detection
 void
 ath5k_ani_set_cck_weak_signal_detection(struct ath5k_hw *ah, bool on)
 {
-	const int val[] = { 8, 6 };
+	static const int val[] = { 8, 6 };
 	AR5K_REG_WRITE_BITS(ah, AR5K_PHY_CCK_CROSSCORR,
 				AR5K_PHY_CCK_CROSSCORR_WEAK_SIG_THR, val[on]);
 	ah->ah_sc->ani_state.cck_weak_sig = on;
@@ -216,7 +216,7 @@ static void
 ath5k_ani_raise_immunity(struct ath5k_hw *ah, struct ath5k_ani_state *as,
 			 bool ofdm_trigger)
 {
-	int rssi = ah->ah_beacon_rssi_avg.avg;
+	int rssi = ewma_read(&ah->ah_beacon_rssi_avg);
 
 	ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, "raise immunity (%s)",
 		ofdm_trigger ? "ODFM" : "CCK");
@@ -301,7 +301,7 @@ ath5k_ani_raise_immunity(struct ath5k_hw
 static void
 ath5k_ani_lower_immunity(struct ath5k_hw *ah, struct ath5k_ani_state *as)
 {
-	int rssi = ah->ah_beacon_rssi_avg.avg;
+	int rssi = ewma_read(&ah->ah_beacon_rssi_avg);
 
 	ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, "lower immunity");
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath5k/ath5k.h linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath5k/ath5k.h
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath5k/ath5k.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath5k/ath5k.h	2011-03-14 21:20:32.000000000 -0400
@@ -25,6 +25,7 @@
 
 #include <linux/io.h>
 #include <linux/types.h>
+#include <linux/average.h>
 #include <net/mac80211.h>
 
 /* RX/TX descriptor hw structs
@@ -153,19 +154,6 @@
 		udelay(1);						\
 } while (0)
 
-/* Register dumps are done per operation mode */
-#define AR5K_INI_RFGAIN_5GHZ		0
-#define AR5K_INI_RFGAIN_2GHZ		1
-
-/* TODO: Clean this up */
-#define AR5K_INI_VAL_11A		0
-#define AR5K_INI_VAL_11A_TURBO		1
-#define AR5K_INI_VAL_11B		2
-#define AR5K_INI_VAL_11G		3
-#define AR5K_INI_VAL_11G_TURBO		4
-#define AR5K_INI_VAL_XR			0
-#define AR5K_INI_VAL_MAX		5
-
 /*
  * Some tuneable values (these should be changeable by the user)
  * TODO: Make use of them and add more options OR use debug/configfs
@@ -221,42 +209,66 @@
 
 /* Initial values */
 #define	AR5K_INIT_CYCRSSI_THR1			2
-#define AR5K_INIT_TX_LATENCY			502
-#define AR5K_INIT_USEC				39
-#define AR5K_INIT_USEC_TURBO			79
-#define AR5K_INIT_USEC_32			31
-#define AR5K_INIT_SLOT_TIME			396
-#define AR5K_INIT_SLOT_TIME_TURBO		480
-#define AR5K_INIT_ACK_CTS_TIMEOUT		1024
-#define AR5K_INIT_ACK_CTS_TIMEOUT_TURBO		0x08000800
-#define AR5K_INIT_PROG_IFS			920
-#define AR5K_INIT_PROG_IFS_TURBO		960
-#define AR5K_INIT_EIFS				3440
-#define AR5K_INIT_EIFS_TURBO			6880
-#define AR5K_INIT_SIFS				560
-#define AR5K_INIT_SIFS_TURBO			480
+
+/* Tx retry limits */
 #define AR5K_INIT_SH_RETRY			10
 #define AR5K_INIT_LG_RETRY			AR5K_INIT_SH_RETRY
+/* For station mode */
 #define AR5K_INIT_SSH_RETRY			32
 #define AR5K_INIT_SLG_RETRY			AR5K_INIT_SSH_RETRY
 #define AR5K_INIT_TX_RETRY			10
 
-#define AR5K_INIT_TRANSMIT_LATENCY		(			\
-	(AR5K_INIT_TX_LATENCY << 14) | (AR5K_INIT_USEC_32 << 7) |	\
-	(AR5K_INIT_USEC)						\
-)
-#define AR5K_INIT_TRANSMIT_LATENCY_TURBO	(			\
-	(AR5K_INIT_TX_LATENCY << 14) | (AR5K_INIT_USEC_32 << 7) |	\
-	(AR5K_INIT_USEC_TURBO)						\
-)
-#define AR5K_INIT_PROTO_TIME_CNTRL		(			\
-	(AR5K_INIT_CARR_SENSE_EN << 26) | (AR5K_INIT_EIFS << 12) |	\
-	(AR5K_INIT_PROG_IFS)						\
-)
-#define AR5K_INIT_PROTO_TIME_CNTRL_TURBO	(			\
-	(AR5K_INIT_CARR_SENSE_EN << 26) | (AR5K_INIT_EIFS_TURBO << 12) | \
-	(AR5K_INIT_PROG_IFS_TURBO)					\
-)
+
+/* Slot time */
+#define AR5K_INIT_SLOT_TIME_TURBO		6
+#define AR5K_INIT_SLOT_TIME_DEFAULT		9
+#define	AR5K_INIT_SLOT_TIME_HALF_RATE		13
+#define	AR5K_INIT_SLOT_TIME_QUARTER_RATE	21
+#define	AR5K_INIT_SLOT_TIME_B			20
+#define AR5K_SLOT_TIME_MAX			0xffff
+
+/* SIFS */
+#define	AR5K_INIT_SIFS_TURBO			6
+/* XXX: 8 from initvals 10 from standard */
+#define	AR5K_INIT_SIFS_DEFAULT_BG		8
+#define	AR5K_INIT_SIFS_DEFAULT_A		16
+#define	AR5K_INIT_SIFS_HALF_RATE		32
+#define AR5K_INIT_SIFS_QUARTER_RATE		64
+
+/* Used to calculate tx time for non 5/10/40MHz
+ * operation */
+/* It's preamble time + signal time (16 + 4) */
+#define	AR5K_INIT_OFDM_PREAMPLE_TIME		20
+/* Preamble time for 40MHz (turbo) operation (min ?) */
+#define	AR5K_INIT_OFDM_PREAMBLE_TIME_MIN	14
+#define	AR5K_INIT_OFDM_SYMBOL_TIME		4
+#define	AR5K_INIT_OFDM_PLCP_BITS		22
+
+/* Rx latency for 5 and 10MHz operation (max ?) */
+#define AR5K_INIT_RX_LAT_MAX			63
+/* Tx latencies from initvals (5212 only but no problem
+ * because we only tweak them on 5212) */
+#define	AR5K_INIT_TX_LAT_A			54
+#define	AR5K_INIT_TX_LAT_BG			384
+/* Tx latency for 40MHz (turbo) operation (min ?) */
+#define	AR5K_INIT_TX_LAT_MIN			32
+/* Default Tx/Rx latencies (same for 5211)*/
+#define AR5K_INIT_TX_LATENCY_5210		54
+#define	AR5K_INIT_RX_LATENCY_5210		29
+
+/* Tx frame to Tx data start delay */
+#define AR5K_INIT_TXF2TXD_START_DEFAULT		14
+#define AR5K_INIT_TXF2TXD_START_DELAY_10MHZ	12
+#define AR5K_INIT_TXF2TXD_START_DELAY_5MHZ	13
+
+/* We need to increase PHY switch and agc settling time
+ * on turbo mode */
+#define	AR5K_SWITCH_SETTLING			5760
+#define	AR5K_SWITCH_SETTLING_TURBO		7168
+
+#define	AR5K_AGC_SETTLING			28
+/* 38 on 5210 but shouldn't matter */
+#define	AR5K_AGC_SETTLING_TURBO			37
 
 
 /* GENERIC CHIPSET DEFINITIONS */
@@ -303,12 +315,19 @@ struct ath5k_srev_name {
 #define AR5K_SREV_AR5311B	0x30 /* Spirit */
 #define AR5K_SREV_AR5211	0x40 /* Oahu */
 #define AR5K_SREV_AR5212	0x50 /* Venice */
+#define AR5K_SREV_AR5312_R2	0x52 /* AP31 */
 #define AR5K_SREV_AR5212_V4	0x54 /* ??? */
 #define AR5K_SREV_AR5213	0x55 /* ??? */
+#define AR5K_SREV_AR5312_R7	0x57 /* AP30 */
+#define AR5K_SREV_AR2313_R8	0x58 /* AP43 */
 #define AR5K_SREV_AR5213A	0x59 /* Hainan */
 #define AR5K_SREV_AR2413	0x78 /* Griffin lite */
 #define AR5K_SREV_AR2414	0x70 /* Griffin */
+#define AR5K_SREV_AR2315_R6 0x86 /* AP51-Light */
+#define AR5K_SREV_AR2315_R7 0x87 /* AP51-Full */
 #define AR5K_SREV_AR5424	0x90 /* Condor */
+#define AR5K_SREV_AR2317_R1 0x90 /* AP61-Light */
+#define AR5K_SREV_AR2317_R2 0x91 /* AP61-Full */
 #define AR5K_SREV_AR5413	0xa4 /* Eagle lite */
 #define AR5K_SREV_AR5414	0xa0 /* Eagle */
 #define AR5K_SREV_AR2415	0xb0 /* Talon */
@@ -404,12 +423,10 @@ struct ath5k_srev_name {
 
 enum ath5k_driver_mode {
 	AR5K_MODE_11A		=	0,
-	AR5K_MODE_11A_TURBO	=	1,
-	AR5K_MODE_11B		=	2,
-	AR5K_MODE_11G		=	3,
-	AR5K_MODE_11G_TURBO	=	4,
+	AR5K_MODE_11B		=	1,
+	AR5K_MODE_11G		=	2,
 	AR5K_MODE_XR		=	0,
-	AR5K_MODE_MAX		=	5
+	AR5K_MODE_MAX		=	3
 };
 
 enum ath5k_ant_mode {
@@ -423,6 +440,12 @@ enum ath5k_ant_mode {
 	AR5K_ANTMODE_MAX,
 };
 
+enum ath5k_bw_mode {
+	AR5K_BWMODE_DEFAULT	= 0,	/* 20MHz, default operation */
+	AR5K_BWMODE_5MHZ	= 1,	/* Quarter rate */
+	AR5K_BWMODE_10MHZ	= 2,	/* Half rate */
+	AR5K_BWMODE_40MHZ	= 3	/* Turbo */
+};
 
 /****************\
   TX DEFINITIONS
@@ -655,7 +678,6 @@ struct ath5k_gain {
 
 /* channel_flags */
 #define	CHANNEL_CW_INT	0x0008	/* Contention Window interference detected */
-#define	CHANNEL_TURBO	0x0010	/* Turbo Channel */
 #define	CHANNEL_CCK	0x0020	/* CCK channel */
 #define	CHANNEL_OFDM	0x0040	/* OFDM channel */
 #define	CHANNEL_2GHZ	0x0080	/* 2GHz channel. */
@@ -667,16 +689,10 @@ struct ath5k_gain {
 #define	CHANNEL_A	(CHANNEL_5GHZ|CHANNEL_OFDM)
 #define	CHANNEL_B	(CHANNEL_2GHZ|CHANNEL_CCK)
 #define	CHANNEL_G	(CHANNEL_2GHZ|CHANNEL_OFDM)
-#define	CHANNEL_T	(CHANNEL_5GHZ|CHANNEL_OFDM|CHANNEL_TURBO)
-#define	CHANNEL_TG	(CHANNEL_2GHZ|CHANNEL_OFDM|CHANNEL_TURBO)
-#define	CHANNEL_108A	CHANNEL_T
-#define	CHANNEL_108G	CHANNEL_TG
 #define	CHANNEL_X	(CHANNEL_5GHZ|CHANNEL_OFDM|CHANNEL_XR)
 
-#define	CHANNEL_ALL 	(CHANNEL_OFDM|CHANNEL_CCK|CHANNEL_2GHZ|CHANNEL_5GHZ| \
-		CHANNEL_TURBO)
+#define	CHANNEL_ALL	(CHANNEL_OFDM|CHANNEL_CCK|CHANNEL_2GHZ|CHANNEL_5GHZ)
 
-#define	CHANNEL_ALL_NOTURBO 	(CHANNEL_ALL & ~CHANNEL_TURBO)
 #define CHANNEL_MODES		CHANNEL_ALL
 
 /*
@@ -1025,7 +1041,6 @@ struct ath5k_hw {
 	enum ath5k_int		ah_imr;
 
 	struct ieee80211_channel *ah_current_channel;
-	bool			ah_turbo;
 	bool			ah_calibration;
 	bool			ah_single_chip;
 
@@ -1034,6 +1049,7 @@ struct ath5k_hw {
 	u32			ah_phy;
 	u32			ah_mac_srev;
 	u16			ah_mac_version;
+	u16			ah_mac_revision;
 	u16			ah_phy_revision;
 	u16			ah_radio_5ghz_revision;
 	u16			ah_radio_2ghz_revision;
@@ -1043,6 +1059,8 @@ struct ath5k_hw {
 
 	u32			ah_limit_tx_retries;
 	u8			ah_coverage_class;
+	bool			ah_ack_bitrate_high;
+	u8			ah_bwmode;
 
 	/* Antenna Control */
 	u32			ah_ant_ctl[AR5K_EEPROM_N_MODES][AR5K_ANT_MAX];
@@ -1085,12 +1103,14 @@ struct ath5k_hw {
 		/* Values in 0.25dB units */
 		s16		txp_min_pwr;
 		s16		txp_max_pwr;
+		s16		txp_cur_pwr;
 		/* Values in 0.5dB units */
 		s16		txp_offset;
 		s16		txp_ofdm;
 		s16		txp_cck_ofdm_gainf_delta;
 		/* Value in dB units */
 		s16		txp_cck_ofdm_pwr_delta;
+		bool		txp_setup;
 	} ah_txpower;
 
 	struct {
@@ -1102,7 +1122,7 @@ struct ath5k_hw {
 	struct ath5k_nfcal_hist ah_nfcal_hist;
 
 	/* average beacon RSSI in our BSS (used by ANI) */
-	struct ath5k_avg_val	ah_beacon_rssi_avg;
+	struct ewma		ah_beacon_rssi_avg;
 
 	/* noise floor from last periodic calibration */
 	s32			ah_noise_floor;
@@ -1131,36 +1151,50 @@ struct ath5k_hw {
 /*
  * Prototypes
  */
+extern const struct ieee80211_ops ath5k_hw_ops;
 
-/* Attach/Detach Functions */
-int ath5k_hw_attach(struct ath5k_softc *sc);
-void ath5k_hw_detach(struct ath5k_hw *ah);
+/* Initialization and detach functions */
+int ath5k_init_softc(struct ath5k_softc *sc, const struct ath_bus_ops *bus_ops);
+void ath5k_deinit_softc(struct ath5k_softc *sc);
+int ath5k_hw_init(struct ath5k_softc *sc);
+void ath5k_hw_deinit(struct ath5k_hw *ah);
 
 int ath5k_sysfs_register(struct ath5k_softc *sc);
 void ath5k_sysfs_unregister(struct ath5k_softc *sc);
 
+/*Chip id helper functions */
+const char *ath5k_chip_name(enum ath5k_srev_type type, u_int16_t val);
+int ath5k_hw_read_srev(struct ath5k_hw *ah);
+
 /* LED functions */
 int ath5k_init_leds(struct ath5k_softc *sc);
 void ath5k_led_enable(struct ath5k_softc *sc);
 void ath5k_led_off(struct ath5k_softc *sc);
 void ath5k_unregister_leds(struct ath5k_softc *sc);
 
+
 /* Reset Functions */
 int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial);
 int ath5k_hw_on_hold(struct ath5k_hw *ah);
 int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
-		   struct ieee80211_channel *channel, bool change_channel);
+	   struct ieee80211_channel *channel, bool fast, bool skip_pcu);
 int ath5k_hw_register_timeout(struct ath5k_hw *ah, u32 reg, u32 flag, u32 val,
 			      bool is_set);
 /* Power management functions */
 
+
+/* Clock rate related functions */
+unsigned int ath5k_hw_htoclock(struct ath5k_hw *ah, unsigned int usec);
+unsigned int ath5k_hw_clocktoh(struct ath5k_hw *ah, unsigned int clock);
+void ath5k_hw_set_clockrate(struct ath5k_hw *ah);
+
+
 /* DMA Related Functions */
 void ath5k_hw_start_rx_dma(struct ath5k_hw *ah);
-int ath5k_hw_stop_rx_dma(struct ath5k_hw *ah);
 u32 ath5k_hw_get_rxdp(struct ath5k_hw *ah);
-void ath5k_hw_set_rxdp(struct ath5k_hw *ah, u32 phys_addr);
+int ath5k_hw_set_rxdp(struct ath5k_hw *ah, u32 phys_addr);
 int ath5k_hw_start_tx_dma(struct ath5k_hw *ah, unsigned int queue);
-int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue);
+int ath5k_hw_stop_beacon_queue(struct ath5k_hw *ah, unsigned int queue);
 u32 ath5k_hw_get_txdp(struct ath5k_hw *ah, unsigned int queue);
 int ath5k_hw_set_txdp(struct ath5k_hw *ah, unsigned int queue,
 				u32 phys_addr);
@@ -1170,38 +1204,43 @@ bool ath5k_hw_is_intr_pending(struct ath
 int ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask);
 enum ath5k_int ath5k_hw_set_imr(struct ath5k_hw *ah, enum ath5k_int new_mask);
 void ath5k_hw_update_mib_counters(struct ath5k_hw *ah);
+/* Init/Stop functions */
+void ath5k_hw_dma_init(struct ath5k_hw *ah);
+int ath5k_hw_dma_stop(struct ath5k_hw *ah);
 
 /* EEPROM access functions */
 int ath5k_eeprom_init(struct ath5k_hw *ah);
 void ath5k_eeprom_detach(struct ath5k_hw *ah);
 int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac);
 
+
 /* Protocol Control Unit Functions */
+/* Helpers */
+int ath5k_hw_get_frame_duration(struct ath5k_hw *ah,
+		int len, struct ieee80211_rate *rate);
+unsigned int ath5k_hw_get_default_slottime(struct ath5k_hw *ah);
+unsigned int ath5k_hw_get_default_sifs(struct ath5k_hw *ah);
 extern int ath5k_hw_set_opmode(struct ath5k_hw *ah, enum nl80211_iftype opmode);
 void ath5k_hw_set_coverage_class(struct ath5k_hw *ah, u8 coverage_class);
-/* BSSID Functions */
+/* RX filter control*/
 int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac);
 void ath5k_hw_set_bssid(struct ath5k_hw *ah);
 void ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask);
-/* Receive start/stop functions */
-void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah);
-void ath5k_hw_stop_rx_pcu(struct ath5k_hw *ah);
-/* RX Filter functions */
 void ath5k_hw_set_mcast_filter(struct ath5k_hw *ah, u32 filter0, u32 filter1);
 u32 ath5k_hw_get_rx_filter(struct ath5k_hw *ah);
 void ath5k_hw_set_rx_filter(struct ath5k_hw *ah, u32 filter);
+/* Receive (DRU) start/stop functions */
+void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah);
+void ath5k_hw_stop_rx_pcu(struct ath5k_hw *ah);
 /* Beacon control functions */
 u64 ath5k_hw_get_tsf64(struct ath5k_hw *ah);
 void ath5k_hw_set_tsf64(struct ath5k_hw *ah, u64 tsf64);
 void ath5k_hw_reset_tsf(struct ath5k_hw *ah);
 void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval);
 bool ath5k_hw_check_beacon_timers(struct ath5k_hw *ah, int intval);
-/* ACK bit rate */
-void ath5k_hw_set_ack_bitrate_high(struct ath5k_hw *ah, bool high);
-/* Clock rate related functions */
-unsigned int ath5k_hw_htoclock(struct ath5k_hw *ah, unsigned int usec);
-unsigned int ath5k_hw_clocktoh(struct ath5k_hw *ah, unsigned int clock);
-void ath5k_hw_set_clockrate(struct ath5k_hw *ah);
+/* Init function */
+void ath5k_hw_pcu_init(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
+								u8 mode);
 
 /* Queue Control Unit, DFS Control Unit Functions */
 int ath5k_hw_get_tx_queueprops(struct ath5k_hw *ah, int queue,
@@ -1214,7 +1253,9 @@ int ath5k_hw_setup_tx_queue(struct ath5k
 u32 ath5k_hw_num_tx_pending(struct ath5k_hw *ah, unsigned int queue);
 void ath5k_hw_release_tx_queue(struct ath5k_hw *ah, unsigned int queue);
 int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue);
-int ath5k_hw_set_slot_time(struct ath5k_hw *ah, unsigned int slot_time);
+int ath5k_hw_set_ifs_intervals(struct ath5k_hw *ah, unsigned int slot_time);
+/* Init function */
+int ath5k_hw_init_queues(struct ath5k_hw *ah);
 
 /* Hardware Descriptor Functions */
 int ath5k_hw_init_desc_functions(struct ath5k_hw *ah);
@@ -1224,6 +1265,7 @@ int ath5k_hw_setup_mrr_tx_desc(struct at
 	unsigned int tx_rate1, u_int tx_tries1, u_int tx_rate2,
 	u_int tx_tries2, unsigned int tx_rate3, u_int tx_tries3);
 
+
 /* GPIO Functions */
 void ath5k_hw_set_ledstate(struct ath5k_hw *ah, unsigned int state);
 int ath5k_hw_set_gpio_input(struct ath5k_hw *ah, u32 gpio);
@@ -1233,11 +1275,13 @@ int ath5k_hw_set_gpio(struct ath5k_hw *a
 void ath5k_hw_set_gpio_intr(struct ath5k_hw *ah, unsigned int gpio,
 			    u32 interrupt_level);
 
-/* rfkill Functions */
+
+/* RFkill Functions */
 void ath5k_rfkill_hw_start(struct ath5k_hw *ah);
 void ath5k_rfkill_hw_stop(struct ath5k_hw *ah);
 
-/* Misc functions */
+
+/* Misc functions TODO: Cleanup */
 int ath5k_hw_set_capabilities(struct ath5k_hw *ah);
 int ath5k_hw_get_capability(struct ath5k_hw *ah,
 			    enum ath5k_capability_type cap_type, u32 capability,
@@ -1245,19 +1289,20 @@ int ath5k_hw_get_capability(struct ath5k
 int ath5k_hw_enable_pspoll(struct ath5k_hw *ah, u8 *bssid, u16 assoc_id);
 int ath5k_hw_disable_pspoll(struct ath5k_hw *ah);
 
+
 /* Initial register settings functions */
 int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool change_channel);
 
-/* Initialize RF */
-int ath5k_hw_rfregs_init(struct ath5k_hw *ah,
-			 struct ieee80211_channel *channel,
-			 unsigned int mode);
-int ath5k_hw_rfgain_init(struct ath5k_hw *ah, unsigned int freq);
+
+/* PHY functions */
+/* Misc PHY functions */
+u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan);
+int ath5k_hw_phy_disable(struct ath5k_hw *ah);
+/* Gain_F optimization */
 enum ath5k_rfgain ath5k_hw_gainf_calibrate(struct ath5k_hw *ah);
 int ath5k_hw_rfgain_opt_init(struct ath5k_hw *ah);
 /* PHY/RF channel functions */
 bool ath5k_channel_ok(struct ath5k_hw *ah, u16 freq, unsigned int flags);
-int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel);
 /* PHY calibration */
 void ath5k_hw_init_nfcal_hist(struct ath5k_hw *ah);
 int ath5k_hw_phy_calibrate(struct ath5k_hw *ah,
@@ -1266,18 +1311,14 @@ void ath5k_hw_update_noise_floor(struct
 /* Spur mitigation */
 bool ath5k_hw_chan_has_spur_noise(struct ath5k_hw *ah,
 				  struct ieee80211_channel *channel);
-void ath5k_hw_set_spur_mitigation_filter(struct ath5k_hw *ah,
-					 struct ieee80211_channel *channel);
-/* Misc PHY functions */
-u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan);
-int ath5k_hw_phy_disable(struct ath5k_hw *ah);
 /* Antenna control */
 void ath5k_hw_set_antenna_mode(struct ath5k_hw *ah, u8 ant_mode);
 void ath5k_hw_set_antenna_switch(struct ath5k_hw *ah, u8 ee_mode);
 /* TX power setup */
-int ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel,
-		     u8 ee_mode, u8 txpower);
 int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 txpower);
+/* Init function */
+int ath5k_hw_phy_init(struct ath5k_hw *ah, struct ieee80211_channel *channel,
+				u8 mode, bool fast);
 
 /*
  * Functions used internaly
@@ -1293,6 +1334,32 @@ static inline struct ath_regulatory *ath
         return &(ath5k_hw_common(ah)->regulatory);
 }
 
+#ifdef CONFIG_ATHEROS_AR231X
+#define AR5K_AR2315_PCI_BASE	((void __iomem *)0xb0100000)
+
+static inline void __iomem *ath5k_ahb_reg(struct ath5k_hw *ah, u16 reg)
+{
+	/* On AR2315 and AR2317 the PCI clock domain registers
+	 * are outside of the WMAC register space */
+	if (unlikely((reg >= 0x4000) && (reg < 0x5000) &&
+		(ah->ah_mac_srev >= AR5K_SREV_AR2315_R6)))
+		return AR5K_AR2315_PCI_BASE + reg;
+
+	return ah->ah_iobase + reg;
+}
+
+static inline u32 ath5k_hw_reg_read(struct ath5k_hw *ah, u16 reg)
+{
+	return __raw_readl(ath5k_ahb_reg(ah, reg));
+}
+
+static inline void ath5k_hw_reg_write(struct ath5k_hw *ah, u32 val, u16 reg)
+{
+	__raw_writel(val, ath5k_ahb_reg(ah, reg));
+}
+
+#else
+
 static inline u32 ath5k_hw_reg_read(struct ath5k_hw *ah, u16 reg)
 {
 	return ioread32(ah->ah_iobase + reg);
@@ -1303,6 +1370,24 @@ static inline void ath5k_hw_reg_write(st
 	iowrite32(val, ah->ah_iobase + reg);
 }
 
+#endif
+
+static inline enum ath_bus_type ath5k_get_bus_type(struct ath5k_hw *ah)
+{
+	return ath5k_hw_common(ah)->bus_ops->ath_bus_type;
+}
+
+static inline void ath5k_read_cachesize(struct ath_common *common, int *csz)
+{
+	common->bus_ops->read_cachesize(common, csz);
+}
+
+static inline bool ath5k_hw_nvram_read(struct ath5k_hw *ah, u32 off, u16 *data)
+{
+	struct ath_common *common = ath5k_hw_common(ah);
+	return common->bus_ops->eeprom_read(common, off, data);
+}
+
 static inline u32 ath5k_hw_bitswap(u32 val, unsigned int bits)
 {
 	u32 retval = 0, bit, i;
@@ -1315,27 +1400,4 @@ static inline u32 ath5k_hw_bitswap(u32 v
 	return retval;
 }
 
-#define AVG_SAMPLES	8
-#define AVG_FACTOR	1000
-
-/**
- * ath5k_moving_average -  Exponentially weighted moving average
- * @avg: average structure
- * @val: current value
- *
- * This implementation make use of a struct ath5k_avg_val to prevent rounding
- * errors.
- */
-static inline struct ath5k_avg_val
-ath5k_moving_average(const struct ath5k_avg_val avg, const int val)
-{
-	struct ath5k_avg_val new;
-	new.avg_weight = avg.avg_weight  ?
-		(((avg.avg_weight * ((AVG_SAMPLES) - 1)) +
-			(val * (AVG_FACTOR))) / (AVG_SAMPLES)) :
-		(val * (AVG_FACTOR));
-	new.avg = new.avg_weight / (AVG_FACTOR);
-	return new;
-}
-
 #endif
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath5k/attach.c linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath5k/attach.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath5k/attach.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath5k/attach.c	2011-03-14 21:20:32.000000000 -0400
@@ -93,16 +93,16 @@ static int ath5k_hw_post(struct ath5k_hw
 }
 
 /**
- * ath5k_hw_attach - Check if hw is supported and init the needed structs
+ * ath5k_hw_init - Check if hw is supported and init the needed structs
  *
- * @sc: The &struct ath5k_softc we got from the driver's attach function
+ * @sc: The &struct ath5k_softc we got from the driver's init_softc function
  *
  * Check if the device is supported, perform a POST and initialize the needed
  * structs. Returns -ENOMEM if we don't have memory for the needed structs,
  * -ENODEV if the device is not supported or prints an error msg if something
  * else went wrong.
  */
-int ath5k_hw_attach(struct ath5k_softc *sc)
+int ath5k_hw_init(struct ath5k_softc *sc)
 {
 	struct ath5k_hw *ah = sc->ah;
 	struct ath_common *common = ath5k_hw_common(ah);
@@ -115,7 +115,7 @@ int ath5k_hw_attach(struct ath5k_softc *
 	 * HW information
 	 */
 	ah->ah_radar.r_enabled = AR5K_TUNE_RADAR_ALERT;
-	ah->ah_turbo = false;
+	ah->ah_bwmode = AR5K_BWMODE_DEFAULT;
 	ah->ah_txpower.txp_tpc = AR5K_TUNE_TPC_TXPOWER;
 	ah->ah_imr = 0;
 	ah->ah_limit_tx_retries = AR5K_INIT_TX_RETRY;
@@ -128,7 +128,8 @@ int ath5k_hw_attach(struct ath5k_softc *
 	/*
 	 * Find the mac version
 	 */
-	srev = ath5k_hw_reg_read(ah, AR5K_SREV);
+	ath5k_hw_read_srev(ah);
+	srev = ah->ah_mac_srev;
 	if (srev < AR5K_SREV_AR5311)
 		ah->ah_version = AR5K_AR5210;
 	else if (srev < AR5K_SREV_AR5212)
@@ -136,6 +137,10 @@ int ath5k_hw_attach(struct ath5k_softc *
 	else
 		ah->ah_version = AR5K_AR5212;
 
+	/* Get the MAC revision */
+	ah->ah_mac_version = AR5K_REG_MS(srev, AR5K_SREV_VER);
+	ah->ah_mac_revision = AR5K_REG_MS(srev, AR5K_SREV_REV);
+
 	/* Fill the ath5k_hw struct with the needed functions */
 	ret = ath5k_hw_init_desc_functions(ah);
 	if (ret)
@@ -146,9 +151,7 @@ int ath5k_hw_attach(struct ath5k_softc *
 	if (ret)
 		goto err;
 
-	/* Get MAC, PHY and RADIO revisions */
-	ah->ah_mac_srev = srev;
-	ah->ah_mac_version = AR5K_REG_MS(srev, AR5K_SREV_VER);
+	/* Get PHY and RADIO revisions */
 	ah->ah_phy_revision = ath5k_hw_reg_read(ah, AR5K_PHY_CHIP_ID) &
 			0xffffffff;
 	ah->ah_radio_5ghz_revision = ath5k_hw_radio_revision(ah,
@@ -273,7 +276,7 @@ int ath5k_hw_attach(struct ath5k_softc *
 	/*
 	 * Write PCI-E power save settings
 	 */
-	if ((ah->ah_version == AR5K_AR5212) && (pdev->is_pcie)) {
+	if ((ah->ah_version == AR5K_AR5212) && pdev && (pci_is_pcie(pdev))) {
 		ath5k_hw_reg_write(ah, 0x9248fc00, AR5K_PCIE_SERDES);
 		ath5k_hw_reg_write(ah, 0x24924924, AR5K_PCIE_SERDES);
 
@@ -305,8 +308,7 @@ int ath5k_hw_attach(struct ath5k_softc *
 	/* Get misc capabilities */
 	ret = ath5k_hw_set_capabilities(ah);
 	if (ret) {
-		ATH5K_ERR(sc, "unable to get device capabilities: 0x%04x\n",
-			sc->pdev->device);
+		ATH5K_ERR(sc, "unable to get device capabilities\n");
 		goto err;
 	}
 
@@ -346,11 +348,11 @@ err:
 }
 
 /**
- * ath5k_hw_detach - Free the ath5k_hw struct
+ * ath5k_hw_deinit - Free the ath5k_hw struct
  *
  * @ah: The &struct ath5k_hw
  */
-void ath5k_hw_detach(struct ath5k_hw *ah)
+void ath5k_hw_deinit(struct ath5k_hw *ah)
 {
 	__set_bit(ATH_STAT_INVALID, ah->ah_sc->status);
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath5k/base.c linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath5k/base.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath5k/base.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath5k/base.c	2011-03-14 21:20:32.000000000 -0400
@@ -47,8 +47,6 @@
 #include <linux/io.h>
 #include <linux/netdevice.h>
 #include <linux/cache.h>
-#include <linux/pci.h>
-#include <linux/pci-aspm.h>
 #include <linux/ethtool.h>
 #include <linux/uaccess.h>
 #include <linux/slab.h>
@@ -62,10 +60,9 @@
 #include "reg.h"
 #include "debug.h"
 #include "ani.h"
-#include "../debug.h"
 
-static int modparam_nohwcrypt;
-module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO);
+int ath5k_modparam_nohwcrypt;
+module_param_named(nohwcrypt, ath5k_modparam_nohwcrypt, bool, S_IRUGO);
 MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption.");
 
 static int modparam_all_channels;
@@ -78,39 +75,24 @@ MODULE_AUTHOR("Nick Kossifidis");
 MODULE_DESCRIPTION("Support for 5xxx series of Atheros 802.11 wireless LAN cards.");
 MODULE_SUPPORTED_DEVICE("Atheros 5xxx WLAN cards");
 MODULE_LICENSE("Dual BSD/GPL");
-MODULE_VERSION("0.6.0 (EXPERIMENTAL)");
-
-static int ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan);
-static int ath5k_beacon_update(struct ieee80211_hw *hw,
-		struct ieee80211_vif *vif);
-static void ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf);
 
-/* Known PCI ids */
-static DEFINE_PCI_DEVICE_TABLE(ath5k_pci_id_table) = {
-	{ PCI_VDEVICE(ATHEROS, 0x0207) }, /* 5210 early */
-	{ PCI_VDEVICE(ATHEROS, 0x0007) }, /* 5210 */
-	{ PCI_VDEVICE(ATHEROS, 0x0011) }, /* 5311 - this is on AHB bus !*/
-	{ PCI_VDEVICE(ATHEROS, 0x0012) }, /* 5211 */
-	{ PCI_VDEVICE(ATHEROS, 0x0013) }, /* 5212 */
-	{ PCI_VDEVICE(3COM_2,  0x0013) }, /* 3com 5212 */
-	{ PCI_VDEVICE(3COM,    0x0013) }, /* 3com 3CRDAG675 5212 */
-	{ PCI_VDEVICE(ATHEROS, 0x1014) }, /* IBM minipci 5212 */
-	{ PCI_VDEVICE(ATHEROS, 0x0014) }, /* 5212 combatible */
-	{ PCI_VDEVICE(ATHEROS, 0x0015) }, /* 5212 combatible */
-	{ PCI_VDEVICE(ATHEROS, 0x0016) }, /* 5212 combatible */
-	{ PCI_VDEVICE(ATHEROS, 0x0017) }, /* 5212 combatible */
-	{ PCI_VDEVICE(ATHEROS, 0x0018) }, /* 5212 combatible */
-	{ PCI_VDEVICE(ATHEROS, 0x0019) }, /* 5212 combatible */
-	{ PCI_VDEVICE(ATHEROS, 0x001a) }, /* 2413 Griffin-lite */
-	{ PCI_VDEVICE(ATHEROS, 0x001b) }, /* 5413 Eagle */
-	{ PCI_VDEVICE(ATHEROS, 0x001c) }, /* PCI-E cards */
-	{ PCI_VDEVICE(ATHEROS, 0x001d) }, /* 2417 Nala */
-	{ 0 }
-};
-MODULE_DEVICE_TABLE(pci, ath5k_pci_id_table);
+static int ath5k_init(struct ieee80211_hw *hw);
+static int ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan,
+								bool skip_pcu);
+int ath5k_beacon_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
+void ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf);
 
 /* Known SREVs */
 static const struct ath5k_srev_name srev_names[] = {
+#ifdef CONFIG_ATHEROS_AR231X
+	{ "5312",	AR5K_VERSION_MAC,	AR5K_SREV_AR5312_R2 },
+	{ "5312",	AR5K_VERSION_MAC,	AR5K_SREV_AR5312_R7 },
+	{ "2313",	AR5K_VERSION_MAC,	AR5K_SREV_AR2313_R8 },
+	{ "2315",	AR5K_VERSION_MAC,	AR5K_SREV_AR2315_R6 },
+	{ "2315",	AR5K_VERSION_MAC,	AR5K_SREV_AR2315_R7 },
+	{ "2317",	AR5K_VERSION_MAC,	AR5K_SREV_AR2317_R1 },
+	{ "2317",	AR5K_VERSION_MAC,	AR5K_SREV_AR2317_R2 },
+#else
 	{ "5210",	AR5K_VERSION_MAC,	AR5K_SREV_AR5210 },
 	{ "5311",	AR5K_VERSION_MAC,	AR5K_SREV_AR5311 },
 	{ "5311A",	AR5K_VERSION_MAC,	AR5K_SREV_AR5311A },
@@ -129,6 +111,7 @@ static const struct ath5k_srev_name srev
 	{ "5418",	AR5K_VERSION_MAC,	AR5K_SREV_AR5418 },
 	{ "2425",	AR5K_VERSION_MAC,	AR5K_SREV_AR2425 },
 	{ "2417",	AR5K_VERSION_MAC,	AR5K_SREV_AR2417 },
+#endif
 	{ "xxxxx",	AR5K_VERSION_MAC,	AR5K_SREV_UNKNOWN },
 	{ "5110",	AR5K_VERSION_RAD,	AR5K_SREV_RAD_5110 },
 	{ "5111",	AR5K_VERSION_RAD,	AR5K_SREV_RAD_5111 },
@@ -142,10 +125,12 @@ static const struct ath5k_srev_name srev
 	{ "2112B",	AR5K_VERSION_RAD,	AR5K_SREV_RAD_2112B },
 	{ "2413",	AR5K_VERSION_RAD,	AR5K_SREV_RAD_2413 },
 	{ "5413",	AR5K_VERSION_RAD,	AR5K_SREV_RAD_5413 },
-	{ "2316",	AR5K_VERSION_RAD,	AR5K_SREV_RAD_2316 },
-	{ "2317",	AR5K_VERSION_RAD,	AR5K_SREV_RAD_2317 },
 	{ "5424",	AR5K_VERSION_RAD,	AR5K_SREV_RAD_5424 },
 	{ "5133",	AR5K_VERSION_RAD,	AR5K_SREV_RAD_5133 },
+#ifdef CONFIG_ATHEROS_AR231X
+	{ "2316",	AR5K_VERSION_RAD,	AR5K_SREV_RAD_2316 },
+	{ "2317",	AR5K_VERSION_RAD,	AR5K_SREV_RAD_2317 },
+#endif
 	{ "xxxxx",	AR5K_VERSION_RAD,	AR5K_SREV_UNKNOWN },
 };
 
@@ -191,38 +176,6 @@ static const struct ieee80211_rate ath5k
 	/* XR missing */
 };
 
-static inline void ath5k_txbuf_free_skb(struct ath5k_softc *sc,
-				struct ath5k_buf *bf)
-{
-	BUG_ON(!bf);
-	if (!bf->skb)
-		return;
-	pci_unmap_single(sc->pdev, bf->skbaddr, bf->skb->len,
-			PCI_DMA_TODEVICE);
-	dev_kfree_skb_any(bf->skb);
-	bf->skb = NULL;
-	bf->skbaddr = 0;
-	bf->desc->ds_data = 0;
-}
-
-static inline void ath5k_rxbuf_free_skb(struct ath5k_softc *sc,
-				struct ath5k_buf *bf)
-{
-	struct ath5k_hw *ah = sc->ah;
-	struct ath_common *common = ath5k_hw_common(ah);
-
-	BUG_ON(!bf);
-	if (!bf->skb)
-		return;
-	pci_unmap_single(sc->pdev, bf->skbaddr, common->rx_bufsize,
-			PCI_DMA_FROMDEVICE);
-	dev_kfree_skb_any(bf->skb);
-	bf->skb = NULL;
-	bf->skbaddr = 0;
-	bf->desc->ds_data = 0;
-}
-
-
 static inline u64 ath5k_extend_tsf(struct ath5k_hw *ah, u32 rstamp)
 {
 	u64 tsf = ath5k_hw_get_tsf64(ah);
@@ -233,7 +186,7 @@ static inline u64 ath5k_extend_tsf(struc
 	return (tsf & ~0x7fff) | rstamp;
 }
 
-static const char *
+const char *
 ath5k_chip_name(enum ath5k_srev_type type, u_int16_t val)
 {
 	const char *name = "xxxxx";
@@ -327,14 +280,12 @@ ath5k_copy_channels(struct ath5k_hw *ah,
 
 	switch (mode) {
 	case AR5K_MODE_11A:
-	case AR5K_MODE_11A_TURBO:
 		/* 1..220, but 2GHz frequencies are filtered by check_channel */
 		size = 220 ;
 		chfreq = CHANNEL_5GHZ;
 		break;
 	case AR5K_MODE_11B:
 	case AR5K_MODE_11G:
-	case AR5K_MODE_11G_TURBO:
 		size = 26;
 		chfreq = CHANNEL_2GHZ;
 		break;
@@ -363,11 +314,6 @@ ath5k_copy_channels(struct ath5k_hw *ah,
 		case AR5K_MODE_11G:
 			channels[count].hw_value = chfreq | CHANNEL_OFDM;
 			break;
-		case AR5K_MODE_11A_TURBO:
-		case AR5K_MODE_11G_TURBO:
-			channels[count].hw_value = chfreq |
-				CHANNEL_OFDM | CHANNEL_TURBO;
-			break;
 		case AR5K_MODE_11B:
 			channels[count].hw_value = CHANNEL_B;
 		}
@@ -483,7 +429,7 @@ ath5k_setup_bands(struct ieee80211_hw *h
  *
  * Called with sc->lock.
  */
-static int
+int
 ath5k_chan_set(struct ath5k_softc *sc, struct ieee80211_channel *chan)
 {
 	ATH5K_DBG(sc, ATH5K_DEBUG_RESET,
@@ -496,7 +442,7 @@ ath5k_chan_set(struct ath5k_softc *sc, s
 	 * hardware at the new frequency, and then re-enable
 	 * the relevant bits of the h/w.
 	 */
-	return ath5k_reset(sc, chan);
+	return ath5k_reset(sc, chan, true);
 }
 
 static void
@@ -549,7 +495,7 @@ static void ath_vif_iter(void *data, u8
 	/* Calculate combined mode - when APs are active, operate in AP mode.
 	 * Otherwise use the mode of the new interface. This can currently
 	 * only deal with combinations of APs and STAs. Only one ad-hoc
-	 * interfaces is allowed above.
+	 * interfaces is allowed.
 	 */
 	if (avf->opmode == NL80211_IFTYPE_AP)
 		iter_data->opmode = NL80211_IFTYPE_AP;
@@ -558,16 +504,9 @@ static void ath_vif_iter(void *data, u8
 			iter_data->opmode = avf->opmode;
 }
 
-static void ath_do_set_opmode(struct ath5k_softc *sc)
-{
-	struct ath5k_hw *ah = sc->ah;
-	ath5k_hw_set_opmode(ah, sc->opmode);
-	ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "mode setup opmode %d (%s)\n",
-		  sc->opmode, ath_opmode_to_string(sc->opmode));
-}
-
-void ath5k_update_bssid_mask_and_opmode(struct ath5k_softc *sc,
-					struct ieee80211_vif *vif)
+void
+ath5k_update_bssid_mask_and_opmode(struct ath5k_softc *sc,
+				   struct ieee80211_vif *vif)
 {
 	struct ath_common *common = ath5k_hw_common(sc->ah);
 	struct ath_vif_iter_data iter_data;
@@ -595,7 +534,9 @@ void ath5k_update_bssid_mask_and_opmode(
 		/* Nothing active, default to station mode */
 		sc->opmode = NL80211_IFTYPE_STATION;
 
-	ath_do_set_opmode(sc);
+	ath5k_hw_set_opmode(sc->ah, sc->opmode);
+	ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "mode setup opmode %d (%s)\n",
+		  sc->opmode, ath_opmode_to_string(sc->opmode));
 
 	if (iter_data.need_set_hw_addr && iter_data.found_active)
 		ath5k_hw_set_lladdr(sc->ah, iter_data.active_mac);
@@ -604,7 +545,7 @@ void ath5k_update_bssid_mask_and_opmode(
 		ath5k_hw_set_bssid_mask(sc->ah, sc->bssidmask);
 }
 
-static void
+void
 ath5k_mode_setup(struct ath5k_softc *sc, struct ieee80211_vif *vif)
 {
 	struct ath5k_hw *ah = sc->ah;
@@ -659,10 +600,11 @@ struct sk_buff *ath5k_rx_skb_alloc(struc
 		return NULL;
 	}
 
-	*skb_addr = pci_map_single(sc->pdev,
+	*skb_addr = dma_map_single(sc->dev,
 				   skb->data, common->rx_bufsize,
-				   PCI_DMA_FROMDEVICE);
-	if (unlikely(pci_dma_mapping_error(sc->pdev, *skb_addr))) {
+				   DMA_FROM_DEVICE);
+
+	if (unlikely(dma_mapping_error(sc->dev, *skb_addr))) {
 		ATH5K_ERR(sc, "%s: DMA mapping failed\n", __func__);
 		dev_kfree_skb(skb);
 		return NULL;
@@ -758,8 +700,8 @@ ath5k_txbuf_setup(struct ath5k_softc *sc
 	flags = AR5K_TXDESC_INTREQ | AR5K_TXDESC_CLRDMASK;
 
 	/* XXX endianness */
-	bf->skbaddr = pci_map_single(sc->pdev, skb->data, skb->len,
-			PCI_DMA_TODEVICE);
+	bf->skbaddr = dma_map_single(sc->dev, skb->data, skb->len,
+			DMA_TO_DEVICE);
 
 	rate = ieee80211_get_tx_rate(sc->hw, info);
 	if (!rate) {
@@ -839,7 +781,7 @@ ath5k_txbuf_setup(struct ath5k_softc *sc
 
 	return 0;
 err_unmap:
-	pci_unmap_single(sc->pdev, bf->skbaddr, skb->len, PCI_DMA_TODEVICE);
+	dma_unmap_single(sc->dev, bf->skbaddr, skb->len, DMA_TO_DEVICE);
 	return ret;
 }
 
@@ -848,7 +790,7 @@ err_unmap:
 \*******************/
 
 static int
-ath5k_desc_alloc(struct ath5k_softc *sc, struct pci_dev *pdev)
+ath5k_desc_alloc(struct ath5k_softc *sc)
 {
 	struct ath5k_desc *ds;
 	struct ath5k_buf *bf;
@@ -859,7 +801,9 @@ ath5k_desc_alloc(struct ath5k_softc *sc,
 	/* allocate descriptors */
 	sc->desc_len = sizeof(struct ath5k_desc) *
 			(ATH_TXBUF + ATH_RXBUF + ATH_BCBUF + 1);
-	sc->desc = pci_alloc_consistent(pdev, sc->desc_len, &sc->desc_daddr);
+
+	sc->desc = dma_alloc_coherent(sc->dev, sc->desc_len,
+				&sc->desc_daddr, GFP_KERNEL);
 	if (sc->desc == NULL) {
 		ATH5K_ERR(sc, "can't allocate descriptors\n");
 		ret = -ENOMEM;
@@ -905,14 +849,45 @@ ath5k_desc_alloc(struct ath5k_softc *sc,
 
 	return 0;
 err_free:
-	pci_free_consistent(pdev, sc->desc_len, sc->desc, sc->desc_daddr);
+	dma_free_coherent(sc->dev, sc->desc_len, sc->desc, sc->desc_daddr);
 err:
 	sc->desc = NULL;
 	return ret;
 }
 
+void
+ath5k_txbuf_free_skb(struct ath5k_softc *sc, struct ath5k_buf *bf)
+{
+	BUG_ON(!bf);
+	if (!bf->skb)
+		return;
+	dma_unmap_single(sc->dev, bf->skbaddr, bf->skb->len,
+			DMA_TO_DEVICE);
+	dev_kfree_skb_any(bf->skb);
+	bf->skb = NULL;
+	bf->skbaddr = 0;
+	bf->desc->ds_data = 0;
+}
+
+void
+ath5k_rxbuf_free_skb(struct ath5k_softc *sc, struct ath5k_buf *bf)
+{
+	struct ath5k_hw *ah = sc->ah;
+	struct ath_common *common = ath5k_hw_common(ah);
+
+	BUG_ON(!bf);
+	if (!bf->skb)
+		return;
+	dma_unmap_single(sc->dev, bf->skbaddr, common->rx_bufsize,
+			DMA_FROM_DEVICE);
+	dev_kfree_skb_any(bf->skb);
+	bf->skb = NULL;
+	bf->skbaddr = 0;
+	bf->desc->ds_data = 0;
+}
+
 static void
-ath5k_desc_free(struct ath5k_softc *sc, struct pci_dev *pdev)
+ath5k_desc_free(struct ath5k_softc *sc)
 {
 	struct ath5k_buf *bf;
 
@@ -924,7 +899,7 @@ ath5k_desc_free(struct ath5k_softc *sc,
 		ath5k_txbuf_free_skb(sc, bf);
 
 	/* Free memory associated with all descriptors */
-	pci_free_consistent(pdev, sc->desc_len, sc->desc, sc->desc_daddr);
+	dma_free_coherent(sc->dev, sc->desc_len, sc->desc, sc->desc_daddr);
 	sc->desc = NULL;
 	sc->desc_daddr = 0;
 
@@ -1069,62 +1044,44 @@ err:
 	return ret;
 }
 
+/**
+ * ath5k_drain_tx_buffs - Empty tx buffers
+ *
+ * @sc The &struct ath5k_softc
+ *
+ * Empty tx buffers from all queues in preparation
+ * of a reset or during shutdown.
+ *
+ * NB:	this assumes output has been stopped and
+ *	we do not need to block ath5k_tx_tasklet
+ */
 static void
-ath5k_txq_drainq(struct ath5k_softc *sc, struct ath5k_txq *txq)
+ath5k_drain_tx_buffs(struct ath5k_softc *sc)
 {
+	struct ath5k_txq *txq;
 	struct ath5k_buf *bf, *bf0;
+	int i;
 
-	/*
-	 * NB: this assumes output has been stopped and
-	 *     we do not need to block ath5k_tx_tasklet
-	 */
-	spin_lock_bh(&txq->lock);
-	list_for_each_entry_safe(bf, bf0, &txq->q, list) {
-		ath5k_debug_printtxbuf(sc, bf);
-
-		ath5k_txbuf_free_skb(sc, bf);
-
-		spin_lock_bh(&sc->txbuflock);
-		list_move_tail(&bf->list, &sc->txbuf);
-		sc->txbuf_len++;
-		txq->txq_len--;
-		spin_unlock_bh(&sc->txbuflock);
-	}
-	txq->link = NULL;
-	txq->txq_poll_mark = false;
-	spin_unlock_bh(&txq->lock);
-}
+	for (i = 0; i < ARRAY_SIZE(sc->txqs); i++) {
+		if (sc->txqs[i].setup) {
+			txq = &sc->txqs[i];
+			spin_lock_bh(&txq->lock);
+			list_for_each_entry_safe(bf, bf0, &txq->q, list) {
+				ath5k_debug_printtxbuf(sc, bf);
 
-/*
- * Drain the transmit queues and reclaim resources.
- */
-static void
-ath5k_txq_cleanup(struct ath5k_softc *sc)
-{
-	struct ath5k_hw *ah = sc->ah;
-	unsigned int i;
+				ath5k_txbuf_free_skb(sc, bf);
 
-	/* XXX return value */
-	if (likely(!test_bit(ATH_STAT_INVALID, sc->status))) {
-		/* don't touch the hardware if marked invalid */
-		ath5k_hw_stop_tx_dma(ah, sc->bhalq);
-		ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "beacon queue %x\n",
-			ath5k_hw_get_txdp(ah, sc->bhalq));
-		for (i = 0; i < ARRAY_SIZE(sc->txqs); i++)
-			if (sc->txqs[i].setup) {
-				ath5k_hw_stop_tx_dma(ah, sc->txqs[i].qnum);
-				ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "txq [%u] %x, "
-					"link %p\n",
-					sc->txqs[i].qnum,
-					ath5k_hw_get_txdp(ah,
-							sc->txqs[i].qnum),
-					sc->txqs[i].link);
+				spin_lock_bh(&sc->txbuflock);
+				list_move_tail(&bf->list, &sc->txbuf);
+				sc->txbuf_len++;
+				txq->txq_len--;
+				spin_unlock_bh(&sc->txbuflock);
 			}
+			txq->link = NULL;
+			txq->txq_poll_mark = false;
+			spin_unlock_bh(&txq->lock);
+		}
 	}
-
-	for (i = 0; i < ARRAY_SIZE(sc->txqs); i++)
-		if (sc->txqs[i].setup)
-			ath5k_txq_drainq(sc, &sc->txqs[i]);
 }
 
 static void
@@ -1184,16 +1141,19 @@ err:
 }
 
 /*
- * Disable the receive h/w in preparation for a reset.
+ * Disable the receive logic on PCU (DRU)
+ * In preparation for a shutdown.
+ *
+ * Note: Doesn't stop rx DMA, ath5k_hw_dma_stop
+ * does.
  */
 static void
 ath5k_rx_stop(struct ath5k_softc *sc)
 {
 	struct ath5k_hw *ah = sc->ah;
 
-	ath5k_hw_stop_rx_pcu(ah);	/* disable PCU */
 	ath5k_hw_set_rx_filter(ah, 0);	/* clear recv filter */
-	ath5k_hw_stop_rx_dma(ah);	/* disable DMA engine */
+	ath5k_hw_stop_rx_pcu(ah);	/* disable PCU */
 
 	ath5k_debug_printrxbuffs(sc, ah);
 }
@@ -1307,8 +1267,7 @@ ath5k_update_beacon_rssi(struct ath5k_so
 	    memcmp(mgmt->bssid, common->curbssid, ETH_ALEN) != 0)
 		return;
 
-	ah->ah_beacon_rssi_avg = ath5k_moving_average(ah->ah_beacon_rssi_avg,
-						      rssi);
+	ewma_add(&ah->ah_beacon_rssi_avg, rssi);
 
 	/* in IBSS mode we should keep RSSI statistics per neighbour */
 	/* le16_to_cpu(mgmt->u.beacon.capab_info) & WLAN_CAPABILITY_IBSS */
@@ -1551,9 +1510,9 @@ ath5k_tasklet_rx(unsigned long data)
 			if (!next_skb)
 				goto next;
 
-			pci_unmap_single(sc->pdev, bf->skbaddr,
+			dma_unmap_single(sc->dev, bf->skbaddr,
 					 common->rx_bufsize,
-					 PCI_DMA_FROMDEVICE);
+					 DMA_FROM_DEVICE);
 
 			skb_put(skb, rs.rs_datalen);
 
@@ -1574,8 +1533,9 @@ unlock:
 * TX Handling *
 \*************/
 
-static int ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb,
-			  struct ath5k_txq *txq)
+int
+ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb,
+	       struct ath5k_txq *txq)
 {
 	struct ath5k_softc *sc = hw->priv;
 	struct ath5k_buf *bf;
@@ -1716,8 +1676,9 @@ ath5k_tx_processq(struct ath5k_softc *sc
 
 			skb = bf->skb;
 			bf->skb = NULL;
-			pci_unmap_single(sc->pdev, bf->skbaddr, skb->len,
-					PCI_DMA_TODEVICE);
+
+			dma_unmap_single(sc->dev, bf->skbaddr, skb->len,
+					DMA_TO_DEVICE);
 			ath5k_tx_frame_completed(sc, skb, &ts);
 		}
 
@@ -1771,12 +1732,13 @@ ath5k_beacon_setup(struct ath5k_softc *s
 	u32 flags;
 	const int padsize = 0;
 
-	bf->skbaddr = pci_map_single(sc->pdev, skb->data, skb->len,
-			PCI_DMA_TODEVICE);
+	bf->skbaddr = dma_map_single(sc->dev, skb->data, skb->len,
+			DMA_TO_DEVICE);
 	ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, "skb %p [data %p len %u] "
 			"skbaddr %llx\n", skb, skb->data, skb->len,
 			(unsigned long long)bf->skbaddr);
-	if (pci_dma_mapping_error(sc->pdev, bf->skbaddr)) {
+
+	if (dma_mapping_error(sc->dev, bf->skbaddr)) {
 		ATH5K_ERR(sc, "beacon DMA mapping failed\n");
 		return -EIO;
 	}
@@ -1828,7 +1790,7 @@ ath5k_beacon_setup(struct ath5k_softc *s
 
 	return 0;
 err_unmap:
-	pci_unmap_single(sc->pdev, bf->skbaddr, skb->len, PCI_DMA_TODEVICE);
+	dma_unmap_single(sc->dev, bf->skbaddr, skb->len, DMA_TO_DEVICE);
 	return ret;
 }
 
@@ -1839,7 +1801,7 @@ err_unmap:
  *
  * Called with the beacon lock.
  */
-static int
+int
 ath5k_beacon_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
 {
 	int ret;
@@ -1945,7 +1907,7 @@ ath5k_beacon_send(struct ath5k_softc *sc
 	 * This should never fail since we check above that no frames
 	 * are still pending on the queue.
 	 */
-	if (unlikely(ath5k_hw_stop_tx_dma(ah, sc->bhalq))) {
+	if (unlikely(ath5k_hw_stop_beacon_queue(ah, sc->bhalq))) {
 		ATH5K_WARN(sc, "beacon queue %u didn't start/stop ?\n", sc->bhalq);
 		/* NB: hw still stops DMA, so proceed */
 	}
@@ -1985,7 +1947,7 @@ ath5k_beacon_send(struct ath5k_softc *sc
  * when we otherwise know we have to update the timers, but we keep it in this
  * function to have it all together in one place.
  */
-static void
+void
 ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf)
 {
 	struct ath5k_hw *ah = sc->ah;
@@ -2087,7 +2049,7 @@ ath5k_beacon_update_timers(struct ath5k_
  * In IBSS mode we use a self-linked tx descriptor if possible. We enable SWBA
  * interrupts to detect TSF updates only.
  */
-static void
+void
 ath5k_beacon_config(struct ath5k_softc *sc)
 {
 	struct ath5k_hw *ah = sc->ah;
@@ -2115,7 +2077,7 @@ ath5k_beacon_config(struct ath5k_softc *
 		} else
 			ath5k_beacon_update_timers(sc, -1);
 	} else {
-		ath5k_hw_stop_tx_dma(sc->ah, sc->bhalq);
+		ath5k_hw_stop_beacon_queue(sc->ah, sc->bhalq);
 	}
 
 	ath5k_hw_set_imr(ah, sc->imask);
@@ -2177,7 +2139,7 @@ ath5k_intr_calibration_poll(struct ath5k
 	 * AR5K_REG_ENABLE_BITS(ah, AR5K_CR, AR5K_CR_SWI); */
 }
 
-static irqreturn_t
+irqreturn_t
 ath5k_intr(int irq, void *dev_id)
 {
 	struct ath5k_softc *sc = dev_id;
@@ -2186,7 +2148,8 @@ ath5k_intr(int irq, void *dev_id)
 	unsigned int counter = 1000;
 
 	if (unlikely(test_bit(ATH_STAT_INVALID, sc->status) ||
-				!ath5k_hw_is_intr_pending(ah)))
+		((ath5k_get_bus_type(ah) != ATH_AHB) &&
+				!ath5k_hw_is_intr_pending(ah))))
 		return IRQ_NONE;
 
 	do {
@@ -2252,6 +2215,10 @@ ath5k_intr(int irq, void *dev_id)
 				tasklet_schedule(&sc->rf_kill.toggleq);
 
 		}
+
+		if (ath5k_get_bus_type(ah) == ATH_AHB)
+			break;
+
 	} while (ath5k_hw_is_intr_pending(ah) && --counter > 0);
 
 	if (unlikely(!counter))
@@ -2327,6 +2294,8 @@ ath5k_tx_complete_poll_work(struct work_
 	int i;
 	bool needreset = false;
 
+	mutex_lock(&sc->lock);
+
 	for (i = 0; i < ARRAY_SIZE(sc->txqs); i++) {
 		if (sc->txqs[i].setup) {
 			txq = &sc->txqs[i];
@@ -2351,9 +2320,11 @@ ath5k_tx_complete_poll_work(struct work_
 	if (needreset) {
 		ATH5K_DBG(sc, ATH5K_DEBUG_RESET,
 			  "TX queues stuck, resetting\n");
-		ath5k_reset(sc, sc->curchan);
+		ath5k_reset(sc, NULL, true);
 	}
 
+	mutex_unlock(&sc->lock);
+
 	ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work,
 		msecs_to_jiffies(ATH5K_TX_COMPLETE_POLL_INT));
 }
@@ -2363,6 +2334,163 @@ ath5k_tx_complete_poll_work(struct work_
 * Initialization routines *
 \*************************/
 
+int
+ath5k_init_softc(struct ath5k_softc *sc, const struct ath_bus_ops *bus_ops)
+{
+	struct ieee80211_hw *hw = sc->hw;
+	struct ath_common *common;
+	int ret;
+	int csz;
+
+	/* Initialize driver private data */
+	SET_IEEE80211_DEV(hw, sc->dev);
+	hw->flags = IEEE80211_HW_RX_INCLUDES_FCS |
+			IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
+			IEEE80211_HW_SIGNAL_DBM |
+			IEEE80211_HW_REPORTS_TX_ACK_STATUS;
+
+	hw->wiphy->interface_modes =
+		BIT(NL80211_IFTYPE_AP) |
+		BIT(NL80211_IFTYPE_STATION) |
+		BIT(NL80211_IFTYPE_ADHOC) |
+		BIT(NL80211_IFTYPE_MESH_POINT);
+
+	/* both antennas can be configured as RX or TX */
+	hw->wiphy->available_antennas_tx = 0x3;
+	hw->wiphy->available_antennas_rx = 0x3;
+
+	hw->extra_tx_headroom = 2;
+	hw->channel_change_time = 5000;
+
+	/*
+	 * Mark the device as detached to avoid processing
+	 * interrupts until setup is complete.
+	 */
+	__set_bit(ATH_STAT_INVALID, sc->status);
+
+	sc->opmode = NL80211_IFTYPE_STATION;
+	sc->bintval = 1000;
+	mutex_init(&sc->lock);
+	spin_lock_init(&sc->rxbuflock);
+	spin_lock_init(&sc->txbuflock);
+	spin_lock_init(&sc->block);
+
+
+	/* Setup interrupt handler */
+	ret = request_irq(sc->irq, ath5k_intr, IRQF_SHARED, "ath", sc);
+	if (ret) {
+		ATH5K_ERR(sc, "request_irq failed\n");
+		goto err;
+	}
+
+	/* If we passed the test, malloc an ath5k_hw struct */
+	sc->ah = kzalloc(sizeof(struct ath5k_hw), GFP_KERNEL);
+	if (!sc->ah) {
+		ret = -ENOMEM;
+		ATH5K_ERR(sc, "out of memory\n");
+		goto err_irq;
+	}
+
+	sc->ah->ah_sc = sc;
+	sc->ah->ah_iobase = sc->iobase;
+	common = ath5k_hw_common(sc->ah);
+	common->ops = &ath5k_common_ops;
+	common->bus_ops = bus_ops;
+	common->ah = sc->ah;
+	common->hw = hw;
+	common->priv = sc;
+
+	/*
+	 * Cache line size is used to size and align various
+	 * structures used to communicate with the hardware.
+	 */
+	ath5k_read_cachesize(common, &csz);
+	common->cachelsz = csz << 2; /* convert to bytes */
+
+	spin_lock_init(&common->cc_lock);
+
+	/* Initialize device */
+	ret = ath5k_hw_init(sc);
+	if (ret)
+		goto err_free_ah;
+
+	/* set up multi-rate retry capabilities */
+	if (sc->ah->ah_version == AR5K_AR5212) {
+		hw->max_rates = 4;
+		hw->max_rate_tries = 11;
+	}
+
+	hw->vif_data_size = sizeof(struct ath5k_vif);
+
+	/* Finish private driver data initialization */
+	ret = ath5k_init(hw);
+	if (ret)
+		goto err_ah;
+
+	ATH5K_INFO(sc, "Atheros AR%s chip found (MAC: 0x%x, PHY: 0x%x)\n",
+			ath5k_chip_name(AR5K_VERSION_MAC, sc->ah->ah_mac_srev),
+					sc->ah->ah_mac_srev,
+					sc->ah->ah_phy_revision);
+
+	if (!sc->ah->ah_single_chip) {
+		/* Single chip radio (!RF5111) */
+		if (sc->ah->ah_radio_5ghz_revision &&
+			!sc->ah->ah_radio_2ghz_revision) {
+			/* No 5GHz support -> report 2GHz radio */
+			if (!test_bit(AR5K_MODE_11A,
+				sc->ah->ah_capabilities.cap_mode)) {
+				ATH5K_INFO(sc, "RF%s 2GHz radio found (0x%x)\n",
+					ath5k_chip_name(AR5K_VERSION_RAD,
+						sc->ah->ah_radio_5ghz_revision),
+						sc->ah->ah_radio_5ghz_revision);
+			/* No 2GHz support (5110 and some
+			 * 5Ghz only cards) -> report 5Ghz radio */
+			} else if (!test_bit(AR5K_MODE_11B,
+				sc->ah->ah_capabilities.cap_mode)) {
+				ATH5K_INFO(sc, "RF%s 5GHz radio found (0x%x)\n",
+					ath5k_chip_name(AR5K_VERSION_RAD,
+						sc->ah->ah_radio_5ghz_revision),
+						sc->ah->ah_radio_5ghz_revision);
+			/* Multiband radio */
+			} else {
+				ATH5K_INFO(sc, "RF%s multiband radio found"
+					" (0x%x)\n",
+					ath5k_chip_name(AR5K_VERSION_RAD,
+						sc->ah->ah_radio_5ghz_revision),
+						sc->ah->ah_radio_5ghz_revision);
+			}
+		}
+		/* Multi chip radio (RF5111 - RF2111) ->
+		 * report both 2GHz/5GHz radios */
+		else if (sc->ah->ah_radio_5ghz_revision &&
+				sc->ah->ah_radio_2ghz_revision){
+			ATH5K_INFO(sc, "RF%s 5GHz radio found (0x%x)\n",
+				ath5k_chip_name(AR5K_VERSION_RAD,
+					sc->ah->ah_radio_5ghz_revision),
+					sc->ah->ah_radio_5ghz_revision);
+			ATH5K_INFO(sc, "RF%s 2GHz radio found (0x%x)\n",
+				ath5k_chip_name(AR5K_VERSION_RAD,
+					sc->ah->ah_radio_2ghz_revision),
+					sc->ah->ah_radio_2ghz_revision);
+		}
+	}
+
+	ath5k_debug_init_device(sc);
+
+	/* ready to process interrupts */
+	__clear_bit(ATH_STAT_INVALID, sc->status);
+
+	return 0;
+err_ah:
+	ath5k_hw_deinit(sc->ah);
+err_free_ah:
+	kfree(sc->ah);
+err_irq:
+	free_irq(sc->irq, sc);
+err:
+	return ret;
+}
+
 static int
 ath5k_stop_locked(struct ath5k_softc *sc)
 {
@@ -2391,19 +2519,18 @@ ath5k_stop_locked(struct ath5k_softc *sc
 	if (!test_bit(ATH_STAT_INVALID, sc->status)) {
 		ath5k_led_off(sc);
 		ath5k_hw_set_imr(ah, 0);
-		synchronize_irq(sc->pdev->irq);
-	}
-	ath5k_txq_cleanup(sc);
-	if (!test_bit(ATH_STAT_INVALID, sc->status)) {
+		synchronize_irq(sc->irq);
 		ath5k_rx_stop(sc);
+		ath5k_hw_dma_stop(ah);
+		ath5k_drain_tx_buffs(sc);
 		ath5k_hw_phy_disable(ah);
 	}
 
 	return 0;
 }
 
-static int
-ath5k_init(struct ath5k_softc *sc)
+int
+ath5k_init_hw(struct ath5k_softc *sc)
 {
 	struct ath5k_hw *ah = sc->ah;
 	struct ath_common *common = ath5k_hw_common(ah);
@@ -2432,7 +2559,7 @@ ath5k_init(struct ath5k_softc *sc)
 		AR5K_INT_RXORN | AR5K_INT_TXDESC | AR5K_INT_TXEOL |
 		AR5K_INT_FATAL | AR5K_INT_GLOBAL | AR5K_INT_MIB;
 
-	ret = ath5k_reset(sc, NULL);
+	ret = ath5k_reset(sc, NULL, false);
 	if (ret)
 		goto done;
 
@@ -2445,7 +2572,9 @@ ath5k_init(struct ath5k_softc *sc)
 	for (i = 0; i < common->keymax; i++)
 		ath_hw_keyreset(common, (u16) i);
 
-	ath5k_hw_set_ack_bitrate_high(ah, true);
+	/* Use higher rates for acks instead of base
+	 * rate */
+	ah->ah_ack_bitrate_high = true;
 
 	for (i = 0; i < ARRAY_SIZE(sc->bslot); i++)
 		sc->bslot[i] = NULL;
@@ -2476,7 +2605,7 @@ static void stop_tasklets(struct ath5k_s
  * if another thread does a system call and the thread doing the
  * stop is preempted).
  */
-static int
+int
 ath5k_stop_hw(struct ath5k_softc *sc)
 {
 	int ret;
@@ -2529,25 +2658,35 @@ ath5k_stop_hw(struct ath5k_softc *sc)
  * This should be called with sc->lock.
  */
 static int
-ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan)
+ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan,
+							bool skip_pcu)
 {
 	struct ath5k_hw *ah = sc->ah;
-	int ret;
+	struct ath_common *common = ath5k_hw_common(ah);
+	int ret, ani_mode;
 
 	ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "resetting\n");
 
 	ath5k_hw_set_imr(ah, 0);
-	synchronize_irq(sc->pdev->irq);
+	synchronize_irq(sc->irq);
 	stop_tasklets(sc);
 
-	if (chan) {
-		ath5k_txq_cleanup(sc);
-		ath5k_rx_stop(sc);
+	/* Save ani mode and disable ANI durring
+	 * reset. If we don't we might get false
+	 * PHY error interrupts. */
+	ani_mode = ah->ah_sc->ani_state.ani_mode;
+	ath5k_ani_init(ah, ATH5K_ANI_MODE_OFF);
 
+	/* We are going to empty hw queues
+	 * so we should also free any remaining
+	 * tx buffers */
+	ath5k_drain_tx_buffs(sc);
+	if (chan) {
 		sc->curchan = chan;
 		sc->curband = &sc->sbands[chan->band];
 	}
-	ret = ath5k_hw_reset(ah, sc->opmode, sc->curchan, chan != NULL);
+	ret = ath5k_hw_reset(ah, sc->opmode, sc->curchan, chan != NULL,
+								skip_pcu);
 	if (ret) {
 		ATH5K_ERR(sc, "can't reset hardware (%d)\n", ret);
 		goto err;
@@ -2559,11 +2698,20 @@ ath5k_reset(struct ath5k_softc *sc, stru
 		goto err;
 	}
 
-	ath5k_ani_init(ah, ah->ah_sc->ani_state.ani_mode);
+	ath5k_ani_init(ah, ani_mode);
 
 	ah->ah_cal_next_full = jiffies;
 	ah->ah_cal_next_ani = jiffies;
 	ah->ah_cal_next_nf = jiffies;
+	ewma_init(&ah->ah_beacon_rssi_avg, 1024, 8);
+
+	/* clear survey data and cycle counters */
+	memset(&sc->survey, 0, sizeof(sc->survey));
+	spin_lock_bh(&common->cc_lock);
+	ath_hw_cycle_counters_update(common);
+	memset(&common->cc_survey, 0, sizeof(common->cc_survey));
+	memset(&common->cc_ani, 0, sizeof(common->cc_ani));
+	spin_unlock_bh(&common->cc_lock);
 
 	/*
 	 * Change channels and update the h/w rate map if we're switching;
@@ -2592,13 +2740,14 @@ static void ath5k_reset_work(struct work
 		reset_work);
 
 	mutex_lock(&sc->lock);
-	ath5k_reset(sc, sc->curchan);
+	ath5k_reset(sc, NULL, true);
 	mutex_unlock(&sc->lock);
 }
 
 static int
-ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw)
+ath5k_init(struct ieee80211_hw *hw)
 {
+
 	struct ath5k_softc *sc = hw->priv;
 	struct ath5k_hw *ah = sc->ah;
 	struct ath_regulatory *regulatory = ath5k_hw_regulatory(ah);
@@ -2606,7 +2755,6 @@ ath5k_attach(struct pci_dev *pdev, struc
 	u8 mac[ETH_ALEN] = {};
 	int ret;
 
-	ATH5K_DBG(sc, ATH5K_DEBUG_ANY, "devid 0x%x\n", pdev->device);
 
 	/*
 	 * Check if the MAC has multi-rate retry support.
@@ -2643,7 +2791,7 @@ ath5k_attach(struct pci_dev *pdev, struc
 	/*
 	 * Allocate tx+rx descriptors and populate the lists.
 	 */
-	ret = ath5k_desc_alloc(sc, pdev);
+	ret = ath5k_desc_alloc(sc);
 	if (ret) {
 		ATH5K_ERR(sc, "can't allocate descriptors\n");
 		goto err;
@@ -2668,33 +2816,46 @@ ath5k_attach(struct pci_dev *pdev, struc
 		goto err_bhal;
 	}
 
-	/* This order matches mac80211's queue priority, so we can
-	 * directly use the mac80211 queue number without any mapping */
-	txq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_VO);
-	if (IS_ERR(txq)) {
-		ATH5K_ERR(sc, "can't setup xmit queue\n");
-		ret = PTR_ERR(txq);
-		goto err_queues;
-	}
-	txq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_VI);
-	if (IS_ERR(txq)) {
-		ATH5K_ERR(sc, "can't setup xmit queue\n");
-		ret = PTR_ERR(txq);
-		goto err_queues;
-	}
-	txq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_BE);
-	if (IS_ERR(txq)) {
-		ATH5K_ERR(sc, "can't setup xmit queue\n");
-		ret = PTR_ERR(txq);
-		goto err_queues;
-	}
-	txq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_BK);
-	if (IS_ERR(txq)) {
-		ATH5K_ERR(sc, "can't setup xmit queue\n");
-		ret = PTR_ERR(txq);
-		goto err_queues;
+	/* 5211 and 5212 usually support 10 queues but we better rely on the
+	 * capability information */
+	if (ah->ah_capabilities.cap_queues.q_tx_num >= 6) {
+		/* This order matches mac80211's queue priority, so we can
+		* directly use the mac80211 queue number without any mapping */
+		txq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_VO);
+		if (IS_ERR(txq)) {
+			ATH5K_ERR(sc, "can't setup xmit queue\n");
+			ret = PTR_ERR(txq);
+			goto err_queues;
+		}
+		txq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_VI);
+		if (IS_ERR(txq)) {
+			ATH5K_ERR(sc, "can't setup xmit queue\n");
+			ret = PTR_ERR(txq);
+			goto err_queues;
+		}
+		txq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_BE);
+		if (IS_ERR(txq)) {
+			ATH5K_ERR(sc, "can't setup xmit queue\n");
+			ret = PTR_ERR(txq);
+			goto err_queues;
+		}
+		txq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_BK);
+		if (IS_ERR(txq)) {
+			ATH5K_ERR(sc, "can't setup xmit queue\n");
+			ret = PTR_ERR(txq);
+			goto err_queues;
+		}
+		hw->queues = 4;
+	} else {
+		/* older hardware (5210) can only support one data queue */
+		txq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_BE);
+		if (IS_ERR(txq)) {
+			ATH5K_ERR(sc, "can't setup xmit queue\n");
+			ret = PTR_ERR(txq);
+			goto err_queues;
+		}
+		hw->queues = 1;
 	}
-	hw->queues = 4;
 
 	tasklet_init(&sc->rxtq, ath5k_tasklet_rx, (unsigned long)sc);
 	tasklet_init(&sc->txtq, ath5k_tasklet_tx, (unsigned long)sc);
@@ -2707,8 +2868,7 @@ ath5k_attach(struct pci_dev *pdev, struc
 
 	ret = ath5k_eeprom_read_mac(ah, mac);
 	if (ret) {
-		ATH5K_ERR(sc, "unable to read address from EEPROM: 0x%04x\n",
-			sc->pdev->device);
+		ATH5K_ERR(sc, "unable to read address from EEPROM\n");
 		goto err_queues;
 	}
 
@@ -2743,15 +2903,15 @@ err_queues:
 err_bhal:
 	ath5k_hw_release_tx_queue(ah, sc->bhalq);
 err_desc:
-	ath5k_desc_free(sc, pdev);
+	ath5k_desc_free(sc);
 err:
 	return ret;
 }
 
-static void
-ath5k_detach(struct pci_dev *pdev, struct ieee80211_hw *hw)
+void
+ath5k_deinit_softc(struct ath5k_softc *sc)
 {
-	struct ath5k_softc *sc = hw->priv;
+	struct ieee80211_hw *hw = sc->hw;
 
 	/*
 	 * NB: the order of these is important:
@@ -2766,8 +2926,9 @@ ath5k_detach(struct pci_dev *pdev, struc
 	 * XXX: ??? detach ath5k_hw ???
 	 * Other than that, it's straightforward...
 	 */
+	ath5k_debug_finish_device(sc);
 	ieee80211_unregister_hw(hw);
-	ath5k_desc_free(sc, pdev);
+	ath5k_desc_free(sc);
 	ath5k_txq_release(sc);
 	ath5k_hw_release_tx_queue(sc->ah, sc->bhalq);
 	ath5k_unregister_leds(sc);
@@ -2778,232 +2939,12 @@ ath5k_detach(struct pci_dev *pdev, struc
 	 * returns because we'll get called back to reclaim node
 	 * state and potentially want to use them.
 	 */
+	ath5k_hw_deinit(sc->ah);
+	free_irq(sc->irq, sc);
 }
 
-/********************\
-* Mac80211 functions *
-\********************/
-
-static int
-ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
-{
-	struct ath5k_softc *sc = hw->priv;
-	u16 qnum = skb_get_queue_mapping(skb);
-
-	if (WARN_ON(qnum >= sc->ah->ah_capabilities.cap_queues.q_tx_num)) {
-		dev_kfree_skb_any(skb);
-		return 0;
-	}
-
-	return ath5k_tx_queue(hw, skb, &sc->txqs[qnum]);
-}
-
-static int ath5k_start(struct ieee80211_hw *hw)
-{
-	return ath5k_init(hw->priv);
-}
-
-static void ath5k_stop(struct ieee80211_hw *hw)
-{
-	ath5k_stop_hw(hw->priv);
-}
-
-static int ath5k_add_interface(struct ieee80211_hw *hw,
-		struct ieee80211_vif *vif)
-{
-	struct ath5k_softc *sc = hw->priv;
-	int ret;
-	struct ath5k_vif *avf = (void *)vif->drv_priv;
-
-	mutex_lock(&sc->lock);
-
-	if ((vif->type == NL80211_IFTYPE_AP ||
-	     vif->type == NL80211_IFTYPE_ADHOC)
-	    && (sc->num_ap_vifs + sc->num_adhoc_vifs) >= ATH_BCBUF) {
-		ret = -ELNRNG;
-		goto end;
-	}
-
-	/* Don't allow other interfaces if one ad-hoc is configured.
-	 * TODO: Fix the problems with ad-hoc and multiple other interfaces.
-	 * We would need to operate the HW in ad-hoc mode to allow TSF updates
-	 * for the IBSS, but this breaks with additional AP or STA interfaces
-	 * at the moment. */
-	if (sc->num_adhoc_vifs ||
-	    (sc->nvifs && vif->type == NL80211_IFTYPE_ADHOC)) {
-		ATH5K_ERR(sc, "Only one single ad-hoc interface is allowed.\n");
-		ret = -ELNRNG;
-		goto end;
-	}
-
-	switch (vif->type) {
-	case NL80211_IFTYPE_AP:
-	case NL80211_IFTYPE_STATION:
-	case NL80211_IFTYPE_ADHOC:
-	case NL80211_IFTYPE_MESH_POINT:
-		avf->opmode = vif->type;
-		break;
-	default:
-		ret = -EOPNOTSUPP;
-		goto end;
-	}
-
-	sc->nvifs++;
-	ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "add interface mode %d\n", avf->opmode);
-
-	/* Assign the vap/adhoc to a beacon xmit slot. */
-	if ((avf->opmode == NL80211_IFTYPE_AP) ||
-	    (avf->opmode == NL80211_IFTYPE_ADHOC) ||
-	    (avf->opmode == NL80211_IFTYPE_MESH_POINT)) {
-		int slot;
-
-		WARN_ON(list_empty(&sc->bcbuf));
-		avf->bbuf = list_first_entry(&sc->bcbuf, struct ath5k_buf,
-					     list);
-		list_del(&avf->bbuf->list);
-
-		avf->bslot = 0;
-		for (slot = 0; slot < ATH_BCBUF; slot++) {
-			if (!sc->bslot[slot]) {
-				avf->bslot = slot;
-				break;
-			}
-		}
-		BUG_ON(sc->bslot[avf->bslot] != NULL);
-		sc->bslot[avf->bslot] = vif;
-		if (avf->opmode == NL80211_IFTYPE_AP)
-			sc->num_ap_vifs++;
-		else if (avf->opmode == NL80211_IFTYPE_ADHOC)
-			sc->num_adhoc_vifs++;
-	}
-
-	/* Any MAC address is fine, all others are included through the
-	 * filter.
-	 */
-	memcpy(&sc->lladdr, vif->addr, ETH_ALEN);
-	ath5k_hw_set_lladdr(sc->ah, vif->addr);
-
-	memcpy(&avf->lladdr, vif->addr, ETH_ALEN);
-
-	ath5k_mode_setup(sc, vif);
-
-	ret = 0;
-end:
-	mutex_unlock(&sc->lock);
-	return ret;
-}
-
-static void
-ath5k_remove_interface(struct ieee80211_hw *hw,
-			struct ieee80211_vif *vif)
-{
-	struct ath5k_softc *sc = hw->priv;
-	struct ath5k_vif *avf = (void *)vif->drv_priv;
-	unsigned int i;
-
-	mutex_lock(&sc->lock);
-	sc->nvifs--;
-
-	if (avf->bbuf) {
-		ath5k_txbuf_free_skb(sc, avf->bbuf);
-		list_add_tail(&avf->bbuf->list, &sc->bcbuf);
-		for (i = 0; i < ATH_BCBUF; i++) {
-			if (sc->bslot[i] == vif) {
-				sc->bslot[i] = NULL;
-				break;
-			}
-		}
-		avf->bbuf = NULL;
-	}
-	if (avf->opmode == NL80211_IFTYPE_AP)
-		sc->num_ap_vifs--;
-	else if (avf->opmode == NL80211_IFTYPE_ADHOC)
-		sc->num_adhoc_vifs--;
-
-	ath5k_update_bssid_mask_and_opmode(sc, NULL);
-	mutex_unlock(&sc->lock);
-}
-
-/*
- * TODO: Phy disable/diversity etc
- */
-static int
-ath5k_config(struct ieee80211_hw *hw, u32 changed)
-{
-	struct ath5k_softc *sc = hw->priv;
-	struct ath5k_hw *ah = sc->ah;
-	struct ieee80211_conf *conf = &hw->conf;
-	int ret = 0;
-
-	mutex_lock(&sc->lock);
-
-	if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
-		ret = ath5k_chan_set(sc, conf->channel);
-		if (ret < 0)
-			goto unlock;
-	}
-
-	if ((changed & IEEE80211_CONF_CHANGE_POWER) &&
-	(sc->power_level != conf->power_level)) {
-		sc->power_level = conf->power_level;
-
-		/* Half dB steps */
-		ath5k_hw_set_txpower_limit(ah, (conf->power_level * 2));
-	}
-
-	/* TODO:
-	 * 1) Move this on config_interface and handle each case
-	 * separately eg. when we have only one STA vif, use
-	 * AR5K_ANTMODE_SINGLE_AP
-	 *
-	 * 2) Allow the user to change antenna mode eg. when only
-	 * one antenna is present
-	 *
-	 * 3) Allow the user to set default/tx antenna when possible
-	 *
-	 * 4) Default mode should handle 90% of the cases, together
-	 * with fixed a/b and single AP modes we should be able to
-	 * handle 99%. Sectored modes are extreme cases and i still
-	 * haven't found a usage for them. If we decide to support them,
-	 * then we must allow the user to set how many tx antennas we
-	 * have available
-	 */
-	ath5k_hw_set_antenna_mode(ah, ah->ah_ant_mode);
-
-unlock:
-	mutex_unlock(&sc->lock);
-	return ret;
-}
-
-static u64 ath5k_prepare_multicast(struct ieee80211_hw *hw,
-				   struct netdev_hw_addr_list *mc_list)
-{
-	u32 mfilt[2], val;
-	u8 pos;
-	struct netdev_hw_addr *ha;
-
-	mfilt[0] = 0;
-	mfilt[1] = 1;
-
-	netdev_hw_addr_list_for_each(ha, mc_list) {
-		/* calculate XOR of eight 6-bit values */
-		val = get_unaligned_le32(ha->addr + 0);
-		pos = (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val;
-		val = get_unaligned_le32(ha->addr + 3);
-		pos ^= (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val;
-		pos &= 0x3f;
-		mfilt[pos / 32] |= (1 << (pos % 32));
-		/* XXX: we might be able to just do this instead,
-		* but not sure, needs testing, if we do use this we'd
-		* neet to inform below to not reset the mcast */
-		/* ath5k_hw_set_mcast_filterindex(ah,
-		 *      ha->addr[5]); */
-	}
-
-	return ((u64)(mfilt[1]) << 32) | mfilt[0];
-}
-
-static bool ath_any_vif_assoc(struct ath5k_softc *sc)
+bool
+ath_any_vif_assoc(struct ath5k_softc *sc)
 {
 	struct ath_vif_iter_data iter_data;
 	iter_data.hw_macaddr = NULL;
@@ -3016,242 +2957,7 @@ static bool ath_any_vif_assoc(struct ath
 	return iter_data.any_assoc;
 }
 
-#define SUPPORTED_FIF_FLAGS \
-	FIF_PROMISC_IN_BSS |  FIF_ALLMULTI | FIF_FCSFAIL | \
-	FIF_PLCPFAIL | FIF_CONTROL | FIF_OTHER_BSS | \
-	FIF_BCN_PRBRESP_PROMISC
-/*
- * o always accept unicast, broadcast, and multicast traffic
- * o multicast traffic for all BSSIDs will be enabled if mac80211
- *   says it should be
- * o maintain current state of phy ofdm or phy cck error reception.
- *   If the hardware detects any of these type of errors then
- *   ath5k_hw_get_rx_filter() will pass to us the respective
- *   hardware filters to be able to receive these type of frames.
- * o probe request frames are accepted only when operating in
- *   hostap, adhoc, or monitor modes
- * o enable promiscuous mode according to the interface state
- * o accept beacons:
- *   - when operating in adhoc mode so the 802.11 layer creates
- *     node table entries for peers,
- *   - when operating in station mode for collecting rssi data when
- *     the station is otherwise quiet, or
- *   - when scanning
- */
-static void ath5k_configure_filter(struct ieee80211_hw *hw,
-		unsigned int changed_flags,
-		unsigned int *new_flags,
-		u64 multicast)
-{
-	struct ath5k_softc *sc = hw->priv;
-	struct ath5k_hw *ah = sc->ah;
-	u32 mfilt[2], rfilt;
-
-	mutex_lock(&sc->lock);
-
-	mfilt[0] = multicast;
-	mfilt[1] = multicast >> 32;
-
-	/* Only deal with supported flags */
-	changed_flags &= SUPPORTED_FIF_FLAGS;
-	*new_flags &= SUPPORTED_FIF_FLAGS;
-
-	/* If HW detects any phy or radar errors, leave those filters on.
-	 * Also, always enable Unicast, Broadcasts and Multicast
-	 * XXX: move unicast, bssid broadcasts and multicast to mac80211 */
-	rfilt = (ath5k_hw_get_rx_filter(ah) & (AR5K_RX_FILTER_PHYERR)) |
-		(AR5K_RX_FILTER_UCAST | AR5K_RX_FILTER_BCAST |
-		AR5K_RX_FILTER_MCAST);
-
-	if (changed_flags & (FIF_PROMISC_IN_BSS | FIF_OTHER_BSS)) {
-		if (*new_flags & FIF_PROMISC_IN_BSS) {
-			__set_bit(ATH_STAT_PROMISC, sc->status);
-		} else {
-			__clear_bit(ATH_STAT_PROMISC, sc->status);
-		}
-	}
-
-	if (test_bit(ATH_STAT_PROMISC, sc->status))
-		rfilt |= AR5K_RX_FILTER_PROM;
-
-	/* Note, AR5K_RX_FILTER_MCAST is already enabled */
-	if (*new_flags & FIF_ALLMULTI) {
-		mfilt[0] =  ~0;
-		mfilt[1] =  ~0;
-	}
-
-	/* This is the best we can do */
-	if (*new_flags & (FIF_FCSFAIL | FIF_PLCPFAIL))
-		rfilt |= AR5K_RX_FILTER_PHYERR;
-
-	/* FIF_BCN_PRBRESP_PROMISC really means to enable beacons
-	* and probes for any BSSID */
-	if ((*new_flags & FIF_BCN_PRBRESP_PROMISC) || (sc->nvifs > 1))
-		rfilt |= AR5K_RX_FILTER_BEACON;
-
-	/* FIF_CONTROL doc says that if FIF_PROMISC_IN_BSS is not
-	 * set we should only pass on control frames for this
-	 * station. This needs testing. I believe right now this
-	 * enables *all* control frames, which is OK.. but
-	 * but we should see if we can improve on granularity */
-	if (*new_flags & FIF_CONTROL)
-		rfilt |= AR5K_RX_FILTER_CONTROL;
-
-	/* Additional settings per mode -- this is per ath5k */
-
-	/* XXX move these to mac80211, and add a beacon IFF flag to mac80211 */
-
-	switch (sc->opmode) {
-	case NL80211_IFTYPE_MESH_POINT:
-		rfilt |= AR5K_RX_FILTER_CONTROL |
-			 AR5K_RX_FILTER_BEACON |
-			 AR5K_RX_FILTER_PROBEREQ |
-			 AR5K_RX_FILTER_PROM;
-		break;
-	case NL80211_IFTYPE_AP:
-	case NL80211_IFTYPE_ADHOC:
-		rfilt |= AR5K_RX_FILTER_PROBEREQ |
-			 AR5K_RX_FILTER_BEACON;
-		break;
-	case NL80211_IFTYPE_STATION:
-		if (sc->assoc)
-			rfilt |= AR5K_RX_FILTER_BEACON;
-	default:
-		break;
-	}
-
-	/* Set filters */
-	ath5k_hw_set_rx_filter(ah, rfilt);
-
-	/* Set multicast bits */
-	ath5k_hw_set_mcast_filter(ah, mfilt[0], mfilt[1]);
-	/* Set the cached hw filter flags, this will later actually
-	 * be set in HW */
-	sc->filter_flags = rfilt;
-
-	mutex_unlock(&sc->lock);
-}
-
-static int
-ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
-	      struct ieee80211_vif *vif, struct ieee80211_sta *sta,
-	      struct ieee80211_key_conf *key)
-{
-	struct ath5k_softc *sc = hw->priv;
-	struct ath5k_hw *ah = sc->ah;
-	struct ath_common *common = ath5k_hw_common(ah);
-	int ret = 0;
-
-	if (modparam_nohwcrypt)
-		return -EOPNOTSUPP;
-
-	switch (key->cipher) {
-	case WLAN_CIPHER_SUITE_WEP40:
-	case WLAN_CIPHER_SUITE_WEP104:
-	case WLAN_CIPHER_SUITE_TKIP:
-		break;
-	case WLAN_CIPHER_SUITE_CCMP:
-		if (common->crypt_caps & ATH_CRYPT_CAP_CIPHER_AESCCM)
-			break;
-		return -EOPNOTSUPP;
-	default:
-		WARN_ON(1);
-		return -EINVAL;
-	}
-
-	mutex_lock(&sc->lock);
-
-	switch (cmd) {
-	case SET_KEY:
-		ret = ath_key_config(common, vif, sta, key);
-		if (ret >= 0) {
-			key->hw_key_idx = ret;
-			/* push IV and Michael MIC generation to stack */
-			key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
-			if (key->cipher == WLAN_CIPHER_SUITE_TKIP)
-				key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
-			if (key->cipher == WLAN_CIPHER_SUITE_CCMP)
-				key->flags |= IEEE80211_KEY_FLAG_SW_MGMT;
-			ret = 0;
-		}
-		break;
-	case DISABLE_KEY:
-		ath_key_delete(common, key);
-		break;
-	default:
-		ret = -EINVAL;
-	}
-
-	mmiowb();
-	mutex_unlock(&sc->lock);
-	return ret;
-}
-
-static int
-ath5k_get_stats(struct ieee80211_hw *hw,
-		struct ieee80211_low_level_stats *stats)
-{
-	struct ath5k_softc *sc = hw->priv;
-
-	/* Force update */
-	ath5k_hw_update_mib_counters(sc->ah);
-
-	stats->dot11ACKFailureCount = sc->stats.ack_fail;
-	stats->dot11RTSFailureCount = sc->stats.rts_fail;
-	stats->dot11RTSSuccessCount = sc->stats.rts_ok;
-	stats->dot11FCSErrorCount = sc->stats.fcs_error;
-
-	return 0;
-}
-
-static int ath5k_get_survey(struct ieee80211_hw *hw, int idx,
-		struct survey_info *survey)
-{
-	struct ath5k_softc *sc = hw->priv;
-	struct ieee80211_conf *conf = &hw->conf;
-
-	 if (idx != 0)
-		return -ENOENT;
-
-	survey->channel = conf->channel;
-	survey->filled = SURVEY_INFO_NOISE_DBM;
-	survey->noise = sc->ah->ah_noise_floor;
-
-	return 0;
-}
-
-static u64
-ath5k_get_tsf(struct ieee80211_hw *hw)
-{
-	struct ath5k_softc *sc = hw->priv;
-
-	return ath5k_hw_get_tsf64(sc->ah);
-}
-
-static void
-ath5k_set_tsf(struct ieee80211_hw *hw, u64 tsf)
-{
-	struct ath5k_softc *sc = hw->priv;
-
-	ath5k_hw_set_tsf64(sc->ah, tsf);
-}
-
-static void
-ath5k_reset_tsf(struct ieee80211_hw *hw)
-{
-	struct ath5k_softc *sc = hw->priv;
-
-	/*
-	 * in IBSS mode we need to update the beacon timers too.
-	 * this will also reset the TSF if we call it with 0
-	 */
-	if (sc->opmode == NL80211_IFTYPE_ADHOC)
-		ath5k_beacon_update_timers(sc, 0);
-	else
-		ath5k_hw_reset_tsf(sc->ah);
-}
-
-static void
+void
 set_beacon_filter(struct ieee80211_hw *hw, bool enable)
 {
 	struct ath5k_softc *sc = hw->priv;
@@ -3265,494 +2971,3 @@ set_beacon_filter(struct ieee80211_hw *h
 	ath5k_hw_set_rx_filter(ah, rfilt);
 	sc->filter_flags = rfilt;
 }
-
-static void ath5k_bss_info_changed(struct ieee80211_hw *hw,
-				    struct ieee80211_vif *vif,
-				    struct ieee80211_bss_conf *bss_conf,
-				    u32 changes)
-{
-	struct ath5k_vif *avf = (void *)vif->drv_priv;
-	struct ath5k_softc *sc = hw->priv;
-	struct ath5k_hw *ah = sc->ah;
-	struct ath_common *common = ath5k_hw_common(ah);
-	unsigned long flags;
-
-	mutex_lock(&sc->lock);
-
-	if (changes & BSS_CHANGED_BSSID) {
-		/* Cache for later use during resets */
-		memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN);
-		common->curaid = 0;
-		ath5k_hw_set_bssid(ah);
-		mmiowb();
-	}
-
-	if (changes & BSS_CHANGED_BEACON_INT)
-		sc->bintval = bss_conf->beacon_int;
-
-	if (changes & BSS_CHANGED_ASSOC) {
-		avf->assoc = bss_conf->assoc;
-		if (bss_conf->assoc)
-			sc->assoc = bss_conf->assoc;
-		else
-			sc->assoc = ath_any_vif_assoc(sc);
-
-		if (sc->opmode == NL80211_IFTYPE_STATION)
-			set_beacon_filter(hw, sc->assoc);
-		ath5k_hw_set_ledstate(sc->ah, sc->assoc ?
-			AR5K_LED_ASSOC : AR5K_LED_INIT);
-		if (bss_conf->assoc) {
-			ATH5K_DBG(sc, ATH5K_DEBUG_ANY,
-				  "Bss Info ASSOC %d, bssid: %pM\n",
-				  bss_conf->aid, common->curbssid);
-			common->curaid = bss_conf->aid;
-			ath5k_hw_set_bssid(ah);
-			/* Once ANI is available you would start it here */
-		}
-	}
-
-	if (changes & BSS_CHANGED_BEACON) {
-		spin_lock_irqsave(&sc->block, flags);
-		ath5k_beacon_update(hw, vif);
-		spin_unlock_irqrestore(&sc->block, flags);
-	}
-
-	if (changes & BSS_CHANGED_BEACON_ENABLED)
-		sc->enable_beacon = bss_conf->enable_beacon;
-
-	if (changes & (BSS_CHANGED_BEACON | BSS_CHANGED_BEACON_ENABLED |
-		       BSS_CHANGED_BEACON_INT))
-		ath5k_beacon_config(sc);
-
-	mutex_unlock(&sc->lock);
-}
-
-static void ath5k_sw_scan_start(struct ieee80211_hw *hw)
-{
-	struct ath5k_softc *sc = hw->priv;
-	if (!sc->assoc)
-		ath5k_hw_set_ledstate(sc->ah, AR5K_LED_SCAN);
-}
-
-static void ath5k_sw_scan_complete(struct ieee80211_hw *hw)
-{
-	struct ath5k_softc *sc = hw->priv;
-	ath5k_hw_set_ledstate(sc->ah, sc->assoc ?
-		AR5K_LED_ASSOC : AR5K_LED_INIT);
-}
-
-/**
- * ath5k_set_coverage_class - Set IEEE 802.11 coverage class
- *
- * @hw: struct ieee80211_hw pointer
- * @coverage_class: IEEE 802.11 coverage class number
- *
- * Mac80211 callback. Sets slot time, ACK timeout and CTS timeout for given
- * coverage class. The values are persistent, they are restored after device
- * reset.
- */
-static void ath5k_set_coverage_class(struct ieee80211_hw *hw, u8 coverage_class)
-{
-	struct ath5k_softc *sc = hw->priv;
-
-	mutex_lock(&sc->lock);
-	ath5k_hw_set_coverage_class(sc->ah, coverage_class);
-	mutex_unlock(&sc->lock);
-}
-
-static int ath5k_conf_tx(struct ieee80211_hw *hw, u16 queue,
-			 const struct ieee80211_tx_queue_params *params)
-{
-	struct ath5k_softc *sc = hw->priv;
-	struct ath5k_hw *ah = sc->ah;
-	struct ath5k_txq_info qi;
-	int ret = 0;
-
-	if (queue >= ah->ah_capabilities.cap_queues.q_tx_num)
-		return 0;
-
-	mutex_lock(&sc->lock);
-
-	ath5k_hw_get_tx_queueprops(ah, queue, &qi);
-
-	qi.tqi_aifs = params->aifs;
-	qi.tqi_cw_min = params->cw_min;
-	qi.tqi_cw_max = params->cw_max;
-	qi.tqi_burst_time = params->txop;
-
-	ATH5K_DBG(sc, ATH5K_DEBUG_ANY,
-		  "Configure tx [queue %d],  "
-		  "aifs: %d, cw_min: %d, cw_max: %d, txop: %d\n",
-		  queue, params->aifs, params->cw_min,
-		  params->cw_max, params->txop);
-
-	if (ath5k_hw_set_tx_queueprops(ah, queue, &qi)) {
-		ATH5K_ERR(sc,
-			  "Unable to update hardware queue %u!\n", queue);
-		ret = -EIO;
-	} else
-		ath5k_hw_reset_tx_queue(ah, queue);
-
-	mutex_unlock(&sc->lock);
-
-	return ret;
-}
-
-static const struct ieee80211_ops ath5k_hw_ops = {
-	.tx 		= ath5k_tx,
-	.start 		= ath5k_start,
-	.stop 		= ath5k_stop,
-	.add_interface 	= ath5k_add_interface,
-	.remove_interface = ath5k_remove_interface,
-	.config 	= ath5k_config,
-	.prepare_multicast = ath5k_prepare_multicast,
-	.configure_filter = ath5k_configure_filter,
-	.set_key 	= ath5k_set_key,
-	.get_stats 	= ath5k_get_stats,
-	.get_survey	= ath5k_get_survey,
-	.conf_tx	= ath5k_conf_tx,
-	.get_tsf 	= ath5k_get_tsf,
-	.set_tsf 	= ath5k_set_tsf,
-	.reset_tsf 	= ath5k_reset_tsf,
-	.bss_info_changed = ath5k_bss_info_changed,
-	.sw_scan_start	= ath5k_sw_scan_start,
-	.sw_scan_complete = ath5k_sw_scan_complete,
-	.set_coverage_class = ath5k_set_coverage_class,
-};
-
-/********************\
-* PCI Initialization *
-\********************/
-
-static int __devinit
-ath5k_pci_probe(struct pci_dev *pdev,
-		const struct pci_device_id *id)
-{
-	void __iomem *mem;
-	struct ath5k_softc *sc;
-	struct ath_common *common;
-	struct ieee80211_hw *hw;
-	int ret;
-	u8 csz;
-
-	/*
-	 * L0s needs to be disabled on all ath5k cards.
-	 *
-	 * For distributions shipping with CONFIG_PCIEASPM (this will be enabled
-	 * by default in the future in 2.6.36) this will also mean both L1 and
-	 * L0s will be disabled when a pre 1.1 PCIe device is detected. We do
-	 * know L1 works correctly even for all ath5k pre 1.1 PCIe devices
-	 * though but cannot currently undue the effect of a blacklist, for
-	 * details you can read pcie_aspm_sanity_check() and see how it adjusts
-	 * the device link capability.
-	 *
-	 * It may be possible in the future to implement some PCI API to allow
-	 * drivers to override blacklists for pre 1.1 PCIe but for now it is
-	 * best to accept that both L0s and L1 will be disabled completely for
-	 * distributions shipping with CONFIG_PCIEASPM rather than having this
-	 * issue present. Motivation for adding this new API will be to help
-	 * with power consumption for some of these devices.
-	 */
-	pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S);
-
-	ret = pci_enable_device(pdev);
-	if (ret) {
-		dev_err(&pdev->dev, "can't enable device\n");
-		goto err;
-	}
-
-	/* XXX 32-bit addressing only */
-	ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
-	if (ret) {
-		dev_err(&pdev->dev, "32-bit DMA not available\n");
-		goto err_dis;
-	}
-
-	/*
-	 * Cache line size is used to size and align various
-	 * structures used to communicate with the hardware.
-	 */
-	pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &csz);
-	if (csz == 0) {
-		/*
-		 * Linux 2.4.18 (at least) writes the cache line size
-		 * register as a 16-bit wide register which is wrong.
-		 * We must have this setup properly for rx buffer
-		 * DMA to work so force a reasonable value here if it
-		 * comes up zero.
-		 */
-		csz = L1_CACHE_BYTES >> 2;
-		pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, csz);
-	}
-	/*
-	 * The default setting of latency timer yields poor results,
-	 * set it to the value used by other systems.  It may be worth
-	 * tweaking this setting more.
-	 */
-	pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0xa8);
-
-	/* Enable bus mastering */
-	pci_set_master(pdev);
-
-	/*
-	 * Disable the RETRY_TIMEOUT register (0x41) to keep
-	 * PCI Tx retries from interfering with C3 CPU state.
-	 */
-	pci_write_config_byte(pdev, 0x41, 0);
-
-	ret = pci_request_region(pdev, 0, "ath5k");
-	if (ret) {
-		dev_err(&pdev->dev, "cannot reserve PCI memory region\n");
-		goto err_dis;
-	}
-
-	mem = pci_iomap(pdev, 0, 0);
-	if (!mem) {
-		dev_err(&pdev->dev, "cannot remap PCI memory region\n") ;
-		ret = -EIO;
-		goto err_reg;
-	}
-
-	/*
-	 * Allocate hw (mac80211 main struct)
-	 * and hw->priv (driver private data)
-	 */
-	hw = ieee80211_alloc_hw(sizeof(*sc), &ath5k_hw_ops);
-	if (hw == NULL) {
-		dev_err(&pdev->dev, "cannot allocate ieee80211_hw\n");
-		ret = -ENOMEM;
-		goto err_map;
-	}
-
-	dev_info(&pdev->dev, "registered as '%s'\n", wiphy_name(hw->wiphy));
-
-	/* Initialize driver private data */
-	SET_IEEE80211_DEV(hw, &pdev->dev);
-	hw->flags = IEEE80211_HW_RX_INCLUDES_FCS |
-		    IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
-		    IEEE80211_HW_SIGNAL_DBM;
-
-	hw->wiphy->interface_modes =
-		BIT(NL80211_IFTYPE_AP) |
-		BIT(NL80211_IFTYPE_STATION) |
-		BIT(NL80211_IFTYPE_ADHOC) |
-		BIT(NL80211_IFTYPE_MESH_POINT);
-
-	hw->extra_tx_headroom = 2;
-	hw->channel_change_time = 5000;
-	sc = hw->priv;
-	sc->hw = hw;
-	sc->pdev = pdev;
-
-	/*
-	 * Mark the device as detached to avoid processing
-	 * interrupts until setup is complete.
-	 */
-	__set_bit(ATH_STAT_INVALID, sc->status);
-
-	sc->iobase = mem; /* So we can unmap it on detach */
-	sc->opmode = NL80211_IFTYPE_STATION;
-	sc->bintval = 1000;
-	mutex_init(&sc->lock);
-	spin_lock_init(&sc->rxbuflock);
-	spin_lock_init(&sc->txbuflock);
-	spin_lock_init(&sc->block);
-
-	/* Set private data */
-	pci_set_drvdata(pdev, sc);
-
-	/* Setup interrupt handler */
-	ret = request_irq(pdev->irq, ath5k_intr, IRQF_SHARED, "ath", sc);
-	if (ret) {
-		ATH5K_ERR(sc, "request_irq failed\n");
-		goto err_free;
-	}
-
-	/* If we passed the test, malloc an ath5k_hw struct */
-	sc->ah = kzalloc(sizeof(struct ath5k_hw), GFP_KERNEL);
-	if (!sc->ah) {
-		ret = -ENOMEM;
-		ATH5K_ERR(sc, "out of memory\n");
-		goto err_irq;
-	}
-
-	sc->ah->ah_sc = sc;
-	sc->ah->ah_iobase = sc->iobase;
-	common = ath5k_hw_common(sc->ah);
-	common->ops = &ath5k_common_ops;
-	common->ah = sc->ah;
-	common->hw = hw;
-	common->cachelsz = csz << 2; /* convert to bytes */
-	spin_lock_init(&common->cc_lock);
-
-	/* Initialize device */
-	ret = ath5k_hw_attach(sc);
-	if (ret) {
-		goto err_free_ah;
-	}
-
-	/* set up multi-rate retry capabilities */
-	if (sc->ah->ah_version == AR5K_AR5212) {
-		hw->max_rates = 4;
-		hw->max_rate_tries = 11;
-	}
-
-	hw->vif_data_size = sizeof(struct ath5k_vif);
-
-	/* Finish private driver data initialization */
-	ret = ath5k_attach(pdev, hw);
-	if (ret)
-		goto err_ah;
-
-	ATH5K_INFO(sc, "Atheros AR%s chip found (MAC: 0x%x, PHY: 0x%x)\n",
-			ath5k_chip_name(AR5K_VERSION_MAC, sc->ah->ah_mac_srev),
-					sc->ah->ah_mac_srev,
-					sc->ah->ah_phy_revision);
-
-	if (!sc->ah->ah_single_chip) {
-		/* Single chip radio (!RF5111) */
-		if (sc->ah->ah_radio_5ghz_revision &&
-			!sc->ah->ah_radio_2ghz_revision) {
-			/* No 5GHz support -> report 2GHz radio */
-			if (!test_bit(AR5K_MODE_11A,
-				sc->ah->ah_capabilities.cap_mode)) {
-				ATH5K_INFO(sc, "RF%s 2GHz radio found (0x%x)\n",
-					ath5k_chip_name(AR5K_VERSION_RAD,
-						sc->ah->ah_radio_5ghz_revision),
-						sc->ah->ah_radio_5ghz_revision);
-			/* No 2GHz support (5110 and some
-			 * 5Ghz only cards) -> report 5Ghz radio */
-			} else if (!test_bit(AR5K_MODE_11B,
-				sc->ah->ah_capabilities.cap_mode)) {
-				ATH5K_INFO(sc, "RF%s 5GHz radio found (0x%x)\n",
-					ath5k_chip_name(AR5K_VERSION_RAD,
-						sc->ah->ah_radio_5ghz_revision),
-						sc->ah->ah_radio_5ghz_revision);
-			/* Multiband radio */
-			} else {
-				ATH5K_INFO(sc, "RF%s multiband radio found"
-					" (0x%x)\n",
-					ath5k_chip_name(AR5K_VERSION_RAD,
-						sc->ah->ah_radio_5ghz_revision),
-						sc->ah->ah_radio_5ghz_revision);
-			}
-		}
-		/* Multi chip radio (RF5111 - RF2111) ->
-		 * report both 2GHz/5GHz radios */
-		else if (sc->ah->ah_radio_5ghz_revision &&
-				sc->ah->ah_radio_2ghz_revision){
-			ATH5K_INFO(sc, "RF%s 5GHz radio found (0x%x)\n",
-				ath5k_chip_name(AR5K_VERSION_RAD,
-					sc->ah->ah_radio_5ghz_revision),
-					sc->ah->ah_radio_5ghz_revision);
-			ATH5K_INFO(sc, "RF%s 2GHz radio found (0x%x)\n",
-				ath5k_chip_name(AR5K_VERSION_RAD,
-					sc->ah->ah_radio_2ghz_revision),
-					sc->ah->ah_radio_2ghz_revision);
-		}
-	}
-
-	ath5k_debug_init_device(sc);
-
-	/* ready to process interrupts */
-	__clear_bit(ATH_STAT_INVALID, sc->status);
-
-	return 0;
-err_ah:
-	ath5k_hw_detach(sc->ah);
-err_free_ah:
-	kfree(sc->ah);
-err_irq:
-	free_irq(pdev->irq, sc);
-err_free:
-	ieee80211_free_hw(hw);
-err_map:
-	pci_iounmap(pdev, mem);
-err_reg:
-	pci_release_region(pdev, 0);
-err_dis:
-	pci_disable_device(pdev);
-err:
-	return ret;
-}
-
-static void __devexit
-ath5k_pci_remove(struct pci_dev *pdev)
-{
-	struct ath5k_softc *sc = pci_get_drvdata(pdev);
-
-	ath5k_debug_finish_device(sc);
-	ath5k_detach(pdev, sc->hw);
-	ath5k_hw_detach(sc->ah);
-	kfree(sc->ah);
-	free_irq(pdev->irq, sc);
-	pci_iounmap(pdev, sc->iobase);
-	pci_release_region(pdev, 0);
-	pci_disable_device(pdev);
-	ieee80211_free_hw(sc->hw);
-}
-
-#ifdef CONFIG_PM_SLEEP
-static int ath5k_pci_suspend(struct device *dev)
-{
-	struct ath5k_softc *sc = pci_get_drvdata(to_pci_dev(dev));
-
-	ath5k_led_off(sc);
-	return 0;
-}
-
-static int ath5k_pci_resume(struct device *dev)
-{
-	struct pci_dev *pdev = to_pci_dev(dev);
-	struct ath5k_softc *sc = pci_get_drvdata(pdev);
-
-	/*
-	 * Suspend/Resume resets the PCI configuration space, so we have to
-	 * re-disable the RETRY_TIMEOUT register (0x41) to keep
-	 * PCI Tx retries from interfering with C3 CPU state
-	 */
-	pci_write_config_byte(pdev, 0x41, 0);
-
-	ath5k_led_enable(sc);
-	return 0;
-}
-
-static SIMPLE_DEV_PM_OPS(ath5k_pm_ops, ath5k_pci_suspend, ath5k_pci_resume);
-#define ATH5K_PM_OPS	(&ath5k_pm_ops)
-#else
-#define ATH5K_PM_OPS	NULL
-#endif /* CONFIG_PM_SLEEP */
-
-static struct pci_driver ath5k_pci_driver = {
-	.name		= KBUILD_MODNAME,
-	.id_table	= ath5k_pci_id_table,
-	.probe		= ath5k_pci_probe,
-	.remove		= __devexit_p(ath5k_pci_remove),
-	.driver.pm	= ATH5K_PM_OPS,
-};
-
-/*
- * Module init/exit functions
- */
-static int __init
-init_ath5k_pci(void)
-{
-	int ret;
-
-	ret = pci_register_driver(&ath5k_pci_driver);
-	if (ret) {
-		printk(KERN_ERR "ath5k_pci: can't register pci driver\n");
-		return ret;
-	}
-
-	return 0;
-}
-
-static void __exit
-exit_ath5k_pci(void)
-{
-	pci_unregister_driver(&ath5k_pci_driver);
-}
-
-module_init(init_ath5k_pci);
-module_exit(exit_ath5k_pci);
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath5k/base.h linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath5k/base.h
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath5k/base.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath5k/base.h	2011-03-14 21:20:32.000000000 -0400
@@ -169,7 +169,10 @@ struct ath5k_vif {
 /* Software Carrier, keeps track of the driver state
  * associated with an instance of a device */
 struct ath5k_softc {
-	struct pci_dev		*pdev;		/* for dma mapping */
+	struct pci_dev		*pdev;
+	struct device		*dev;		/* for dma mapping */
+	int irq;
+	u16 devid;
 	void __iomem		*iobase;	/* address of the device */
 	struct mutex		lock;		/* dev-level lock */
 	struct ieee80211_hw	*hw;		/* IEEE 802.11 common */
@@ -255,6 +258,8 @@ struct ath5k_softc {
 	struct tasklet_struct	ani_tasklet;	/* ANI calibration */
 
 	struct delayed_work	tx_complete_work;
+
+	struct survey_info	survey;		/* collected survey info */
 };
 
 #define ath5k_hw_hasbssidmask(_ah) \
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath5k/caps.c linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath5k/caps.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath5k/caps.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath5k/caps.c	2011-03-14 21:20:32.000000000 -0400
@@ -49,7 +49,6 @@ int ath5k_hw_set_capabilities(struct ath
 
 		/* Set supported modes */
 		__set_bit(AR5K_MODE_11A, ah->ah_capabilities.cap_mode);
-		__set_bit(AR5K_MODE_11A_TURBO, ah->ah_capabilities.cap_mode);
 	} else {
 		/*
 		 * XXX The tranceiver supports frequencies from 4920 to 6100GHz
@@ -74,11 +73,6 @@ int ath5k_hw_set_capabilities(struct ath
 			/* Set supported modes */
 			__set_bit(AR5K_MODE_11A,
 					ah->ah_capabilities.cap_mode);
-			__set_bit(AR5K_MODE_11A_TURBO,
-					ah->ah_capabilities.cap_mode);
-			if (ah->ah_version == AR5K_AR5212)
-				__set_bit(AR5K_MODE_11G_TURBO,
-						ah->ah_capabilities.cap_mode);
 		}
 
 		/* Enable  802.11b if a 2GHz capable radio (2111/5112) is
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath5k/debug.c linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath5k/debug.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath5k/debug.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath5k/debug.c	2011-03-14 21:20:32.000000000 -0400
@@ -60,7 +60,6 @@
 
 #include "base.h"
 #include "debug.h"
-#include "../debug.h"
 
 static unsigned int ath5k_debug;
 module_param_named(debug, ath5k_debug, uint, 0);
@@ -312,6 +311,7 @@ static const struct {
 	{ ATH5K_DEBUG_DUMP_RX,	"dumprx",	"print received skb content" },
 	{ ATH5K_DEBUG_DUMP_TX,	"dumptx",	"print transmit skb content" },
 	{ ATH5K_DEBUG_DUMPBANDS, "dumpbands",	"dump bands" },
+	{ ATH5K_DEBUG_DMA,	"dma",		"dma start/stop" },
 	{ ATH5K_DEBUG_ANI,	"ani",		"adaptive noise immunity" },
 	{ ATH5K_DEBUG_DESC,	"desc",		"descriptor chains" },
 	{ ATH5K_DEBUG_ANY,	"all",		"show all debug levels" },
@@ -554,63 +554,63 @@ static ssize_t read_file_frameerrors(str
 
 	len += snprintf(buf+len, sizeof(buf)-len,
 			"RX\n---------------------\n");
-	len += snprintf(buf+len, sizeof(buf)-len, "CRC\t%d\t(%d%%)\n",
+	len += snprintf(buf+len, sizeof(buf)-len, "CRC\t%u\t(%u%%)\n",
 			st->rxerr_crc,
 			st->rx_all_count > 0 ?
 				st->rxerr_crc*100/st->rx_all_count : 0);
-	len += snprintf(buf+len, sizeof(buf)-len, "PHY\t%d\t(%d%%)\n",
+	len += snprintf(buf+len, sizeof(buf)-len, "PHY\t%u\t(%u%%)\n",
 			st->rxerr_phy,
 			st->rx_all_count > 0 ?
 				st->rxerr_phy*100/st->rx_all_count : 0);
 	for (i = 0; i < 32; i++) {
 		if (st->rxerr_phy_code[i])
 			len += snprintf(buf+len, sizeof(buf)-len,
-				" phy_err[%d]\t%d\n",
+				" phy_err[%u]\t%u\n",
 				i, st->rxerr_phy_code[i]);
 	}
 
-	len += snprintf(buf+len, sizeof(buf)-len, "FIFO\t%d\t(%d%%)\n",
+	len += snprintf(buf+len, sizeof(buf)-len, "FIFO\t%u\t(%u%%)\n",
 			st->rxerr_fifo,
 			st->rx_all_count > 0 ?
 				st->rxerr_fifo*100/st->rx_all_count : 0);
-	len += snprintf(buf+len, sizeof(buf)-len, "decrypt\t%d\t(%d%%)\n",
+	len += snprintf(buf+len, sizeof(buf)-len, "decrypt\t%u\t(%u%%)\n",
 			st->rxerr_decrypt,
 			st->rx_all_count > 0 ?
 				st->rxerr_decrypt*100/st->rx_all_count : 0);
-	len += snprintf(buf+len, sizeof(buf)-len, "MIC\t%d\t(%d%%)\n",
+	len += snprintf(buf+len, sizeof(buf)-len, "MIC\t%u\t(%u%%)\n",
 			st->rxerr_mic,
 			st->rx_all_count > 0 ?
 				st->rxerr_mic*100/st->rx_all_count : 0);
-	len += snprintf(buf+len, sizeof(buf)-len, "process\t%d\t(%d%%)\n",
+	len += snprintf(buf+len, sizeof(buf)-len, "process\t%u\t(%u%%)\n",
 			st->rxerr_proc,
 			st->rx_all_count > 0 ?
 				st->rxerr_proc*100/st->rx_all_count : 0);
-	len += snprintf(buf+len, sizeof(buf)-len, "jumbo\t%d\t(%d%%)\n",
+	len += snprintf(buf+len, sizeof(buf)-len, "jumbo\t%u\t(%u%%)\n",
 			st->rxerr_jumbo,
 			st->rx_all_count > 0 ?
 				st->rxerr_jumbo*100/st->rx_all_count : 0);
-	len += snprintf(buf+len, sizeof(buf)-len, "[RX all\t%d]\n",
+	len += snprintf(buf+len, sizeof(buf)-len, "[RX all\t%u]\n",
 			st->rx_all_count);
-	len += snprintf(buf+len, sizeof(buf)-len, "RX-all-bytes\t%d\n",
+	len += snprintf(buf+len, sizeof(buf)-len, "RX-all-bytes\t%u\n",
 			st->rx_bytes_count);
 
 	len += snprintf(buf+len, sizeof(buf)-len,
 			"\nTX\n---------------------\n");
-	len += snprintf(buf+len, sizeof(buf)-len, "retry\t%d\t(%d%%)\n",
+	len += snprintf(buf+len, sizeof(buf)-len, "retry\t%u\t(%u%%)\n",
 			st->txerr_retry,
 			st->tx_all_count > 0 ?
 				st->txerr_retry*100/st->tx_all_count : 0);
-	len += snprintf(buf+len, sizeof(buf)-len, "FIFO\t%d\t(%d%%)\n",
+	len += snprintf(buf+len, sizeof(buf)-len, "FIFO\t%u\t(%u%%)\n",
 			st->txerr_fifo,
 			st->tx_all_count > 0 ?
 				st->txerr_fifo*100/st->tx_all_count : 0);
-	len += snprintf(buf+len, sizeof(buf)-len, "filter\t%d\t(%d%%)\n",
+	len += snprintf(buf+len, sizeof(buf)-len, "filter\t%u\t(%u%%)\n",
 			st->txerr_filt,
 			st->tx_all_count > 0 ?
 				st->txerr_filt*100/st->tx_all_count : 0);
-	len += snprintf(buf+len, sizeof(buf)-len, "[TX all\t%d]\n",
+	len += snprintf(buf+len, sizeof(buf)-len, "[TX all\t%u]\n",
 			st->tx_all_count);
-	len += snprintf(buf+len, sizeof(buf)-len, "TX-all-bytes\t%d\n",
+	len += snprintf(buf+len, sizeof(buf)-len, "TX-all-bytes\t%u\n",
 			st->tx_bytes_count);
 
 	if (len > sizeof(buf))
@@ -719,7 +719,7 @@ static ssize_t read_file_ani(struct file
 			st->mib_intr);
 	len += snprintf(buf+len, sizeof(buf)-len,
 			"beacon RSSI average:\t%d\n",
-			sc->ah->ah_beacon_rssi_avg.avg);
+			(int)ewma_read(&sc->ah->ah_beacon_rssi_avg));
 
 #define CC_PRINT(_struct, _field) \
 	_struct._field, \
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath5k/debug.h linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath5k/debug.h
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath5k/debug.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath5k/debug.h	2011-03-14 21:20:32.000000000 -0400
@@ -95,6 +95,7 @@ struct ath5k_dbg_info {
  * @ATH5K_DEBUG_DUMP_RX: print received skb content
  * @ATH5K_DEBUG_DUMP_TX: print transmit skb content
  * @ATH5K_DEBUG_DUMPBANDS: dump bands
+ * @ATH5K_DEBUG_DMA: debug dma start/stop
  * @ATH5K_DEBUG_TRACE: trace function calls
  * @ATH5K_DEBUG_DESC: descriptor setup
  * @ATH5K_DEBUG_ANY: show at any debug level
@@ -118,6 +119,7 @@ enum ath5k_debug_level {
 	ATH5K_DEBUG_DUMP_RX	= 0x00000100,
 	ATH5K_DEBUG_DUMP_TX	= 0x00000200,
 	ATH5K_DEBUG_DUMPBANDS	= 0x00000400,
+	ATH5K_DEBUG_DMA		= 0x00000800,
 	ATH5K_DEBUG_ANI		= 0x00002000,
 	ATH5K_DEBUG_DESC	= 0x00004000,
 	ATH5K_DEBUG_ANY		= 0xffffffff
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath5k/desc.c linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath5k/desc.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath5k/desc.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath5k/desc.c	2011-03-14 21:20:32.000000000 -0400
@@ -26,9 +26,10 @@
 #include "debug.h"
 #include "base.h"
 
-/*
- * TX Descriptors
- */
+
+/************************\
+* TX Control descriptors *
+\************************/
 
 /*
  * Initialize the 2-word tx control descriptor on 5210/5211
@@ -335,6 +336,11 @@ ath5k_hw_setup_mrr_tx_desc(struct ath5k_
 	return 0;
 }
 
+
+/***********************\
+* TX Status descriptors *
+\***********************/
+
 /*
  * Proccess the tx status descriptor on 5210/5211
  */
@@ -476,9 +482,10 @@ static int ath5k_hw_proc_4word_tx_status
 	return 0;
 }
 
-/*
- * RX Descriptors
- */
+
+/****************\
+* RX Descriptors *
+\****************/
 
 /*
  * Initialize an rx control descriptor
@@ -666,6 +673,11 @@ static int ath5k_hw_proc_5212_rx_status(
 	return 0;
 }
 
+
+/********\
+* Attach *
+\********/
+
 /*
  * Init function pointers inside ath5k_hw struct
  */
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath5k/desc.h linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath5k/desc.h
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath5k/desc.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath5k/desc.h	2011-03-14 21:20:32.000000000 -0400
@@ -26,7 +26,7 @@
 struct ath5k_hw_rx_ctl {
 	u32	rx_control_0; /* RX control word 0 */
 	u32	rx_control_1; /* RX control word 1 */
-} __packed;
+} __packed __aligned(4);
 
 /* RX control word 1 fields/flags */
 #define AR5K_DESC_RX_CTL1_BUF_LEN		0x00000fff /* data buffer length */
@@ -39,7 +39,7 @@ struct ath5k_hw_rx_ctl {
 struct ath5k_hw_rx_status {
 	u32	rx_status_0; /* RX status word 0 */
 	u32	rx_status_1; /* RX status word 1 */
-} __packed;
+} __packed __aligned(4);
 
 /* 5210/5211 */
 /* RX status word 0 fields/flags */
@@ -129,7 +129,7 @@ enum ath5k_phy_error_code {
 struct ath5k_hw_2w_tx_ctl {
 	u32	tx_control_0; /* TX control word 0 */
 	u32	tx_control_1; /* TX control word 1 */
-} __packed;
+} __packed __aligned(4);
 
 /* TX control word 0 fields/flags */
 #define AR5K_2W_TX_DESC_CTL0_FRAME_LEN		0x00000fff /* frame length */
@@ -185,7 +185,7 @@ struct ath5k_hw_4w_tx_ctl {
 	u32	tx_control_1; /* TX control word 1 */
 	u32	tx_control_2; /* TX control word 2 */
 	u32	tx_control_3; /* TX control word 3 */
-} __packed;
+} __packed __aligned(4);
 
 /* TX control word 0 fields/flags */
 #define AR5K_4W_TX_DESC_CTL0_FRAME_LEN		0x00000fff /* frame length */
@@ -244,7 +244,7 @@ struct ath5k_hw_4w_tx_ctl {
 struct ath5k_hw_tx_status {
 	u32	tx_status_0; /* TX status word 0 */
 	u32	tx_status_1; /* TX status word 1 */
-} __packed;
+} __packed __aligned(4);
 
 /* TX status word 0 fields/flags */
 #define AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK	0x00000001 /* TX success */
@@ -282,7 +282,7 @@ struct ath5k_hw_tx_status {
 struct ath5k_hw_5210_tx_desc {
 	struct ath5k_hw_2w_tx_ctl	tx_ctl;
 	struct ath5k_hw_tx_status	tx_stat;
-} __packed;
+} __packed __aligned(4);
 
 /*
  * 5212 hardware TX descriptor
@@ -290,7 +290,7 @@ struct ath5k_hw_5210_tx_desc {
 struct ath5k_hw_5212_tx_desc {
 	struct ath5k_hw_4w_tx_ctl	tx_ctl;
 	struct ath5k_hw_tx_status	tx_stat;
-} __packed;
+} __packed __aligned(4);
 
 /*
  * Common hardware RX descriptor
@@ -298,7 +298,7 @@ struct ath5k_hw_5212_tx_desc {
 struct ath5k_hw_all_rx_desc {
 	struct ath5k_hw_rx_ctl		rx_ctl;
 	struct ath5k_hw_rx_status	rx_stat;
-} __packed;
+} __packed __aligned(4);
 
 /*
  * Atheros hardware DMA descriptor
@@ -313,7 +313,7 @@ struct ath5k_desc {
 		struct ath5k_hw_5212_tx_desc	ds_tx5212;
 		struct ath5k_hw_all_rx_desc	ds_rx;
 	} ud;
-} __packed;
+} __packed __aligned(4);
 
 #define AR5K_RXDESC_INTREQ	0x0020
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath5k/dma.c linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath5k/dma.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath5k/dma.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath5k/dma.c	2011-03-14 21:20:32.000000000 -0400
@@ -37,6 +37,7 @@
 #include "debug.h"
 #include "base.h"
 
+
 /*********\
 * Receive *
 \*********/
@@ -57,7 +58,7 @@ void ath5k_hw_start_rx_dma(struct ath5k_
  *
  * @ah:	The &struct ath5k_hw
  */
-int ath5k_hw_stop_rx_dma(struct ath5k_hw *ah)
+static int ath5k_hw_stop_rx_dma(struct ath5k_hw *ah)
 {
 	unsigned int i;
 
@@ -69,7 +70,11 @@ int ath5k_hw_stop_rx_dma(struct ath5k_hw
 	for (i = 1000; i > 0 &&
 			(ath5k_hw_reg_read(ah, AR5K_CR) & AR5K_CR_RXE) != 0;
 			i--)
-		udelay(10);
+		udelay(100);
+
+	if (!i)
+		ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_DMA,
+				"failed to stop RX DMA !\n");
 
 	return i ? 0 : -EBUSY;
 }
@@ -90,11 +95,18 @@ u32 ath5k_hw_get_rxdp(struct ath5k_hw *a
  * @ah: The &struct ath5k_hw
  * @phys_addr: RX descriptor address
  *
- * XXX: Should we check if rx is enabled before setting rxdp ?
+ * Returns -EIO if rx is active
  */
-void ath5k_hw_set_rxdp(struct ath5k_hw *ah, u32 phys_addr)
+int ath5k_hw_set_rxdp(struct ath5k_hw *ah, u32 phys_addr)
 {
+	if (ath5k_hw_reg_read(ah, AR5K_CR) & AR5K_CR_RXE) {
+		ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_DMA,
+				"tried to set RXDP while rx was active !\n");
+		return -EIO;
+	}
+
 	ath5k_hw_reg_write(ah, phys_addr, AR5K_RXDP);
+	return 0;
 }
 
 
@@ -125,7 +137,7 @@ int ath5k_hw_start_tx_dma(struct ath5k_h
 
 	/* Return if queue is declared inactive */
 	if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE)
-		return -EIO;
+		return -EINVAL;
 
 	if (ah->ah_version == AR5K_AR5210) {
 		tx_queue = ath5k_hw_reg_read(ah, AR5K_CR);
@@ -173,10 +185,10 @@ int ath5k_hw_start_tx_dma(struct ath5k_h
  *
  * Stop DMA transmit on a specific hw queue and drain queue so we don't
  * have any pending frames. Returns -EBUSY if we still have pending frames,
- * -EINVAL if queue number is out of range.
+ * -EINVAL if queue number is out of range or inactive.
  *
  */
-int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue)
+static int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue)
 {
 	unsigned int i = 40;
 	u32 tx_queue, pending;
@@ -185,7 +197,7 @@ int ath5k_hw_stop_tx_dma(struct ath5k_hw
 
 	/* Return if queue is declared inactive */
 	if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE)
-		return -EIO;
+		return -EINVAL;
 
 	if (ah->ah_version == AR5K_AR5210) {
 		tx_queue = ath5k_hw_reg_read(ah, AR5K_CR);
@@ -211,12 +223,31 @@ int ath5k_hw_stop_tx_dma(struct ath5k_hw
 		ath5k_hw_reg_write(ah, tx_queue, AR5K_CR);
 		ath5k_hw_reg_read(ah, AR5K_CR);
 	} else {
+
+		/*
+		 * Enable DCU early termination to quickly
+		 * flush any pending frames from QCU
+		 */
+		AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
+					AR5K_QCU_MISC_DCU_EARLY);
+
 		/*
 		 * Schedule TX disable and wait until queue is empty
 		 */
 		AR5K_REG_WRITE_Q(ah, AR5K_QCU_TXD, queue);
 
-		/*Check for pending frames*/
+		/* Wait for queue to stop */
+		for (i = 1000; i > 0 &&
+		(AR5K_REG_READ_Q(ah, AR5K_QCU_TXE, queue) != 0);
+		i--)
+			udelay(100);
+
+		if (AR5K_REG_READ_Q(ah, AR5K_QCU_TXE, queue))
+			ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_DMA,
+				"queue %i didn't stop !\n", queue);
+
+		/* Check for pending frames */
+		i = 1000;
 		do {
 			pending = ath5k_hw_reg_read(ah,
 				AR5K_QUEUE_STATUS(queue)) &
@@ -247,12 +278,12 @@ int ath5k_hw_stop_tx_dma(struct ath5k_hw
 					AR5K_DIAG_SW_CHANNEL_IDLE_HIGH);
 
 			/* Wait a while and disable mechanism */
-			udelay(200);
+			udelay(400);
 			AR5K_REG_DISABLE_BITS(ah, AR5K_QUIET_CTL1,
 						AR5K_QUIET_CTL1_QT_EN);
 
 			/* Re-check for pending frames */
-			i = 40;
+			i = 100;
 			do {
 				pending = ath5k_hw_reg_read(ah,
 					AR5K_QUEUE_STATUS(queue)) &
@@ -262,12 +293,27 @@ int ath5k_hw_stop_tx_dma(struct ath5k_hw
 
 			AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW_5211,
 					AR5K_DIAG_SW_CHANNEL_IDLE_HIGH);
+
+			if (pending)
+				ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_DMA,
+					"quiet mechanism didn't work q:%i !\n",
+					queue);
 		}
 
+		/*
+		 * Disable DCU early termination
+		 */
+		AR5K_REG_DISABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
+					AR5K_QCU_MISC_DCU_EARLY);
+
 		/* Clear register */
 		ath5k_hw_reg_write(ah, 0, AR5K_QCU_TXD);
-		if (pending)
+		if (pending) {
+			ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_DMA,
+					"tx dma didn't stop (q:%i, frm:%i) !\n",
+					queue, pending);
 			return -EBUSY;
+		}
 	}
 
 	/* TODO: Check for success on 5210 else return error */
@@ -275,6 +321,26 @@ int ath5k_hw_stop_tx_dma(struct ath5k_hw
 }
 
 /**
+ * ath5k_hw_stop_beacon_queue - Stop beacon queue
+ *
+ * @ah The &struct ath5k_hw
+ * @queue The queue number
+ *
+ * Returns -EIO if queue didn't stop
+ */
+int ath5k_hw_stop_beacon_queue(struct ath5k_hw *ah, unsigned int queue)
+{
+	int ret;
+	ret = ath5k_hw_stop_tx_dma(ah, queue);
+	if (ret) {
+		ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_DMA,
+				"beacon queue didn't stop !\n");
+		return -EIO;
+	}
+	return 0;
+}
+
+/**
  * ath5k_hw_get_txdp - Get TX Descriptor's address for a specific queue
  *
  * @ah: The &struct ath5k_hw
@@ -427,6 +493,7 @@ done:
 	return ret;
 }
 
+
 /*******************\
 * Interrupt masking *
 \*******************/
@@ -688,3 +755,92 @@ enum ath5k_int ath5k_hw_set_imr(struct a
 	return old_mask;
 }
 
+
+/********************\
+ Init/Stop functions
+\********************/
+
+/**
+ * ath5k_hw_dma_init - Initialize DMA unit
+ *
+ * @ah: The &struct ath5k_hw
+ *
+ * Set DMA size and pre-enable interrupts
+ * (driver handles tx/rx buffer setup and
+ * dma start/stop)
+ *
+ * XXX: Save/restore RXDP/TXDP registers ?
+ */
+void ath5k_hw_dma_init(struct ath5k_hw *ah)
+{
+	/*
+	 * Set Rx/Tx DMA Configuration
+	 *
+	 * Set standard DMA size (128). Note that
+	 * a DMA size of 512 causes rx overruns and tx errors
+	 * on pci-e cards (tested on 5424 but since rx overruns
+	 * also occur on 5416/5418 with madwifi we set 128
+	 * for all PCI-E cards to be safe).
+	 *
+	 * XXX: need to check 5210 for this
+	 * TODO: Check out tx triger level, it's always 64 on dumps but I
+	 * guess we can tweak it and see how it goes ;-)
+	 */
+	if (ah->ah_version != AR5K_AR5210) {
+		AR5K_REG_WRITE_BITS(ah, AR5K_TXCFG,
+			AR5K_TXCFG_SDMAMR, AR5K_DMASIZE_128B);
+		AR5K_REG_WRITE_BITS(ah, AR5K_RXCFG,
+			AR5K_RXCFG_SDMAMW, AR5K_DMASIZE_128B);
+	}
+
+	/* Pre-enable interrupts on 5211/5212*/
+	if (ah->ah_version != AR5K_AR5210)
+		ath5k_hw_set_imr(ah, ah->ah_imr);
+
+}
+
+/**
+ * ath5k_hw_dma_stop - stop DMA unit
+ *
+ * @ah: The &struct ath5k_hw
+ *
+ * Stop tx/rx DMA and interrupts. Returns
+ * -EBUSY if tx or rx dma failed to stop.
+ *
+ * XXX: Sometimes DMA unit hangs and we have
+ * stuck frames on tx queues, only a reset
+ * can fix that.
+ */
+int ath5k_hw_dma_stop(struct ath5k_hw *ah)
+{
+	int i, qmax, err;
+	err = 0;
+
+	/* Disable interrupts */
+	ath5k_hw_set_imr(ah, 0);
+
+	/* Stop rx dma */
+	err = ath5k_hw_stop_rx_dma(ah);
+	if (err)
+		return err;
+
+	/* Clear any pending interrupts
+	 * and disable tx dma */
+	if (ah->ah_version != AR5K_AR5210) {
+		ath5k_hw_reg_write(ah, 0xffffffff, AR5K_PISR);
+		qmax = AR5K_NUM_TX_QUEUES;
+	} else {
+		/* PISR/SISR Not available on 5210 */
+		ath5k_hw_reg_read(ah, AR5K_ISR);
+		qmax = AR5K_NUM_TX_QUEUES_NOQCU;
+	}
+
+	for (i = 0; i < qmax; i++) {
+		err = ath5k_hw_stop_tx_dma(ah, i);
+		/* -EINVAL -> queue inactive */
+		if (err && err != -EINVAL)
+			return err;
+	}
+
+	return 0;
+}
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath5k/eeprom.c linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath5k/eeprom.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath5k/eeprom.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath5k/eeprom.c	2011-03-14 21:20:32.000000000 -0400
@@ -28,45 +28,16 @@
 #include "debug.h"
 #include "base.h"
 
-/*
- * Read from eeprom
- */
-static int ath5k_hw_eeprom_read(struct ath5k_hw *ah, u32 offset, u16 *data)
-{
-	u32 status, timeout;
-
-	/*
-	 * Initialize EEPROM access
-	 */
-	if (ah->ah_version == AR5K_AR5210) {
-		AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, AR5K_PCICFG_EEAE);
-		(void)ath5k_hw_reg_read(ah, AR5K_EEPROM_BASE + (4 * offset));
-	} else {
-		ath5k_hw_reg_write(ah, offset, AR5K_EEPROM_BASE);
-		AR5K_REG_ENABLE_BITS(ah, AR5K_EEPROM_CMD,
-				AR5K_EEPROM_CMD_READ);
-	}
 
-	for (timeout = AR5K_TUNE_REGISTER_TIMEOUT; timeout > 0; timeout--) {
-		status = ath5k_hw_reg_read(ah, AR5K_EEPROM_STATUS);
-		if (status & AR5K_EEPROM_STAT_RDDONE) {
-			if (status & AR5K_EEPROM_STAT_RDERR)
-				return -EIO;
-			*data = (u16)(ath5k_hw_reg_read(ah, AR5K_EEPROM_DATA) &
-					0xffff);
-			return 0;
-		}
-		udelay(15);
-	}
-
-	return -ETIMEDOUT;
-}
+/******************\
+* Helper functions *
+\******************/
 
 /*
  * Translate binary channel representation in EEPROM to frequency
  */
 static u16 ath5k_eeprom_bin2freq(struct ath5k_eeprom_info *ee, u16 bin,
-                                 unsigned int mode)
+							unsigned int mode)
 {
 	u16 val;
 
@@ -89,6 +60,11 @@ static u16 ath5k_eeprom_bin2freq(struct
 	return val;
 }
 
+
+/*********\
+* Parsers *
+\*********/
+
 /*
  * Initialize eeprom & capabilities structs
  */
@@ -198,7 +174,7 @@ ath5k_eeprom_init_header(struct ath5k_hw
 	 *
 	 * XXX: Serdes values seem to be fixed so
 	 * no need to read them here, we write them
-	 * during ath5k_hw_attach */
+	 * during ath5k_hw_init */
 	AR5K_EEPROM_READ(AR5K_EEPROM_PCIE_OFFSET, val);
 	ee->ee_serdes = (val == AR5K_EEPROM_PCIE_SERDES_SECTION) ?
 							true : false;
@@ -647,6 +623,7 @@ ath5k_eeprom_init_11bg_2413(struct ath5k
 	return 0;
 }
 
+
 /*
  * Read power calibration for RF5111 chips
  *
@@ -1514,6 +1491,7 @@ ath5k_eeprom_read_target_rate_pwr_info(s
 	return 0;
 }
 
+
 /*
  * Read per channel calibration info from EEPROM
  *
@@ -1607,15 +1585,6 @@ ath5k_eeprom_free_pcal_info(struct ath5k
 	return 0;
 }
 
-void
-ath5k_eeprom_detach(struct ath5k_hw *ah)
-{
-	u8 mode;
-
-	for (mode = AR5K_EEPROM_MODE_11A; mode <= AR5K_EEPROM_MODE_11G; mode++)
-		ath5k_eeprom_free_pcal_info(ah, mode);
-}
-
 /* Read conformance test limits used for regulatory control */
 static int
 ath5k_eeprom_read_ctl_info(struct ath5k_hw *ah)
@@ -1757,6 +1726,44 @@ ath5k_eeprom_read_spur_chans(struct ath5
 }
 
 /*
+ * Read the MAC address from eeprom
+ */
+int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac)
+{
+	u8 mac_d[ETH_ALEN] = {};
+	u32 total, offset;
+	u16 data;
+	int octet, ret;
+
+	ret = ath5k_hw_nvram_read(ah, 0x20, &data);
+	if (ret)
+		return ret;
+
+	for (offset = 0x1f, octet = 0, total = 0; offset >= 0x1d; offset--) {
+		ret = ath5k_hw_nvram_read(ah, offset, &data);
+		if (ret)
+			return ret;
+
+		total += data;
+		mac_d[octet + 1] = data & 0xff;
+		mac_d[octet] = data >> 8;
+		octet += 2;
+	}
+
+	if (!total || total == 3 * 0xffff)
+		return -EINVAL;
+
+	memcpy(mac, mac_d, ETH_ALEN);
+
+	return 0;
+}
+
+
+/***********************\
+* Init/Detach functions *
+\***********************/
+
+/*
  * Initialize eeprom data structure
  */
 int
@@ -1787,35 +1794,27 @@ ath5k_eeprom_init(struct ath5k_hw *ah)
 	return 0;
 }
 
-/*
- * Read the MAC address from eeprom
- */
-int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac)
+void
+ath5k_eeprom_detach(struct ath5k_hw *ah)
 {
-	u8 mac_d[ETH_ALEN] = {};
-	u32 total, offset;
-	u16 data;
-	int octet, ret;
-
-	ret = ath5k_hw_eeprom_read(ah, 0x20, &data);
-	if (ret)
-		return ret;
+	u8 mode;
 
-	for (offset = 0x1f, octet = 0, total = 0; offset >= 0x1d; offset--) {
-		ret = ath5k_hw_eeprom_read(ah, offset, &data);
-		if (ret)
-			return ret;
+	for (mode = AR5K_EEPROM_MODE_11A; mode <= AR5K_EEPROM_MODE_11G; mode++)
+		ath5k_eeprom_free_pcal_info(ah, mode);
+}
 
-		total += data;
-		mac_d[octet + 1] = data & 0xff;
-		mac_d[octet] = data >> 8;
-		octet += 2;
+int
+ath5k_eeprom_mode_from_channel(struct ieee80211_channel *channel)
+{
+	switch (channel->hw_value & CHANNEL_MODES) {
+	case CHANNEL_A:
+	case CHANNEL_XR:
+		return AR5K_EEPROM_MODE_11A;
+	case CHANNEL_G:
+		return AR5K_EEPROM_MODE_11G;
+	case CHANNEL_B:
+		return AR5K_EEPROM_MODE_11B;
+	default:
+		return -1;
 	}
-
-	if (!total || total == 3 * 0xffff)
-		return -EINVAL;
-
-	memcpy(mac, mac_d, ETH_ALEN);
-
-	return 0;
 }
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath5k/eeprom.h linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath5k/eeprom.h
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath5k/eeprom.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath5k/eeprom.h	2011-03-14 21:20:32.000000000 -0400
@@ -241,7 +241,7 @@ enum ath5k_eeprom_freq_bands{
 #define	AR5K_SPUR_SYMBOL_WIDTH_TURBO_100Hz	6250
 
 #define AR5K_EEPROM_READ(_o, _v) do {			\
-	ret = ath5k_hw_eeprom_read(ah, (_o), &(_v));	\
+	ret = ath5k_hw_nvram_read(ah, (_o), &(_v));	\
 	if (ret)					\
 		return ret;				\
 } while (0)
@@ -517,3 +517,5 @@ struct ath5k_eeprom_info {
 	u32	ee_antenna[AR5K_EEPROM_N_MODES][AR5K_ANT_MAX];
 };
 
+int
+ath5k_eeprom_mode_from_channel(struct ieee80211_channel *channel);
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath5k/initvals.c linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath5k/initvals.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath5k/initvals.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath5k/initvals.c	2011-03-14 21:20:32.000000000 -0400
@@ -44,7 +44,7 @@ struct ath5k_ini {
 
 struct ath5k_ini_mode {
 	u16	mode_register;
-	u32	mode_value[5];
+	u32	mode_value[3];
 };
 
 /* Initial register settings for AR5210 */
@@ -391,76 +391,74 @@ static const struct ath5k_ini ar5211_ini
  */
 static const struct ath5k_ini_mode ar5211_ini_mode[] = {
 	{ AR5K_TXCFG,
-	/*	  a	    aTurbo	  b	  g (OFDM)    */
-	   { 0x00000015, 0x00000015, 0x0000001d, 0x00000015 } },
+	/*	A/XR          B           G       */
+	   { 0x00000015, 0x0000001d, 0x00000015 } },
 	{ AR5K_QUEUE_DFS_LOCAL_IFS(0),
-	   { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
+	   { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
 	{ AR5K_QUEUE_DFS_LOCAL_IFS(1),
-	   { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
+	   { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
 	{ AR5K_QUEUE_DFS_LOCAL_IFS(2),
-	   { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
+	   { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
 	{ AR5K_QUEUE_DFS_LOCAL_IFS(3),
-	   { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
+	   { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
 	{ AR5K_QUEUE_DFS_LOCAL_IFS(4),
-	   { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
+	   { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
 	{ AR5K_QUEUE_DFS_LOCAL_IFS(5),
-	   { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
+	   { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
 	{ AR5K_QUEUE_DFS_LOCAL_IFS(6),
-	   { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
+	   { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
 	{ AR5K_QUEUE_DFS_LOCAL_IFS(7),
-	   { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
+	   { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
 	{ AR5K_QUEUE_DFS_LOCAL_IFS(8),
-	   { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
+	   { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
 	{ AR5K_QUEUE_DFS_LOCAL_IFS(9),
-	   { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
+	   { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
 	{ AR5K_DCU_GBL_IFS_SLOT,
-	   { 0x00000168, 0x000001e0, 0x000001b8, 0x00000168 } },
+	   { 0x00000168, 0x000001b8, 0x00000168 } },
 	{ AR5K_DCU_GBL_IFS_SIFS,
-	   { 0x00000230, 0x000001e0, 0x000000b0, 0x00000230 } },
+	   { 0x00000230, 0x000000b0, 0x00000230 } },
 	{ AR5K_DCU_GBL_IFS_EIFS,
-	   { 0x00000d98, 0x00001180, 0x00001f48, 0x00000d98 } },
+	   { 0x00000d98, 0x00001f48, 0x00000d98 } },
 	{ AR5K_DCU_GBL_IFS_MISC,
-	   { 0x0000a0e0, 0x00014068, 0x00005880, 0x0000a0e0 } },
+	   { 0x0000a0e0, 0x00005880, 0x0000a0e0 } },
 	{ AR5K_TIME_OUT,
-	   { 0x04000400, 0x08000800, 0x20003000, 0x04000400 } },
+	   { 0x04000400, 0x20003000, 0x04000400 } },
 	{ AR5K_USEC_5211,
-	   { 0x0e8d8fa7, 0x0e8d8fcf, 0x01608f95, 0x0e8d8fa7 } },
-	{ AR5K_PHY_TURBO,
-	   { 0x00000000, 0x00000003, 0x00000000, 0x00000000 } },
+	   { 0x0e8d8fa7, 0x01608f95, 0x0e8d8fa7 } },
 	{ AR5K_PHY(8),
-	   { 0x02020200, 0x02020200, 0x02010200, 0x02020200 } },
-	{ AR5K_PHY(9),
-	   { 0x00000e0e, 0x00000e0e, 0x00000707, 0x00000e0e } },
-	{ AR5K_PHY(10),
-	   { 0x0a020001, 0x0a020001, 0x05010000, 0x0a020001 } },
-	{ AR5K_PHY(13),
-	   { 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e } },
-	{ AR5K_PHY(14),
-	   { 0x00000007, 0x00000007, 0x0000000b, 0x0000000b } },
-	{ AR5K_PHY(17),
-	   { 0x1372169c, 0x137216a5, 0x137216a8, 0x1372169c } },
-	{ AR5K_PHY(18),
-	   { 0x0018ba67, 0x0018ba67, 0x0018ba69, 0x0018ba69 } },
-	{ AR5K_PHY(20),
-	   { 0x0c28b4e0, 0x0c28b4e0, 0x0c28b4e0, 0x0c28b4e0 } },
+	   { 0x02020200, 0x02010200, 0x02020200 } },
+	{ AR5K_PHY_RF_CTL2,
+	   { 0x00000e0e, 0x00000707, 0x00000e0e } },
+	{ AR5K_PHY_RF_CTL3,
+	   { 0x0a020001, 0x05010000, 0x0a020001 } },
+	{ AR5K_PHY_RF_CTL4,
+	   { 0x00000e0e, 0x00000e0e, 0x00000e0e } },
+	{ AR5K_PHY_PA_CTL,
+	   { 0x00000007, 0x0000000b, 0x0000000b } },
+	{ AR5K_PHY_SETTLING,
+	   { 0x1372169c, 0x137216a8, 0x1372169c } },
+	{ AR5K_PHY_GAIN,
+	   { 0x0018ba67, 0x0018ba69, 0x0018ba69 } },
+	{ AR5K_PHY_DESIRED_SIZE,
+	   { 0x0c28b4e0, 0x0c28b4e0, 0x0c28b4e0 } },
 	{ AR5K_PHY_SIG,
-	   { 0x7e800d2e, 0x7e800d2e, 0x7ec00d2e, 0x7e800d2e } },
+	   { 0x7e800d2e, 0x7ec00d2e, 0x7e800d2e } },
 	{ AR5K_PHY_AGCCOARSE,
-	   { 0x31375d5e, 0x31375d5e, 0x313a5d5e, 0x31375d5e } },
+	   { 0x31375d5e, 0x313a5d5e, 0x31375d5e } },
 	{ AR5K_PHY_AGCCTL,
-	   { 0x0000bd10, 0x0000bd10, 0x0000bd38, 0x0000bd10 } },
+	   { 0x0000bd10, 0x0000bd38, 0x0000bd10 } },
 	{ AR5K_PHY_NF,
-	   { 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 } },
+	   { 0x0001ce00, 0x0001ce00, 0x0001ce00 } },
 	{ AR5K_PHY_RX_DELAY,
-	   { 0x00002710, 0x00002710, 0x0000157c, 0x00002710 } },
+	   { 0x00002710, 0x0000157c, 0x00002710 } },
 	{ AR5K_PHY(70),
-	   { 0x00000190, 0x00000190, 0x00000084, 0x00000190 } },
+	   { 0x00000190, 0x00000084, 0x00000190 } },
 	{ AR5K_PHY_FRAME_CTL_5211,
-	   { 0x6fe01020, 0x6fe01020, 0x6fe00920, 0x6fe01020 } },
+	   { 0x6fe01020, 0x6fe00920, 0x6fe01020 } },
 	{ AR5K_PHY_PCDAC_TXPOWER_BASE,
-	   { 0x05ff14ff, 0x05ff14ff, 0x05ff14ff, 0x05ff19ff } },
+	   { 0x05ff14ff, 0x05ff14ff, 0x05ff19ff } },
 	{ AR5K_RF_BUFFER_CONTROL_4,
-	   { 0x00000010, 0x00000014, 0x00000010, 0x00000010 } },
+	   { 0x00000010, 0x00000010, 0x00000010 } },
 };
 
 /* Initial register settings for AR5212 */
@@ -677,89 +675,87 @@ static const struct ath5k_ini ar5212_ini
 /* Initial mode-specific settings for AR5212 (Written before ar5212_ini) */
 static const struct ath5k_ini_mode ar5212_ini_mode_start[] = {
 	{ AR5K_QUEUE_DFS_LOCAL_IFS(0),
-	/*	a/XR	   aTurbo	  b	   g (DYN)     gTurbo     */
-	   { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } },
+	/*	A/XR          B           G       */
+	   { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
 	{ AR5K_QUEUE_DFS_LOCAL_IFS(1),
-	   { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } },
+	   { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
 	{ AR5K_QUEUE_DFS_LOCAL_IFS(2),
-	   { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } },
+	   { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
 	{ AR5K_QUEUE_DFS_LOCAL_IFS(3),
-	   { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } },
+	   { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
 	{ AR5K_QUEUE_DFS_LOCAL_IFS(4),
-	   { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } },
+	   { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
 	{ AR5K_QUEUE_DFS_LOCAL_IFS(5),
-	   { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } },
+	   { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
 	{ AR5K_QUEUE_DFS_LOCAL_IFS(6),
-	   { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } },
+	   { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
 	{ AR5K_QUEUE_DFS_LOCAL_IFS(7),
-	   { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } },
+	   { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
 	{ AR5K_QUEUE_DFS_LOCAL_IFS(8),
-	   { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } },
+	   { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
 	{ AR5K_QUEUE_DFS_LOCAL_IFS(9),
-	   { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } },
+	   { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
 	{ AR5K_DCU_GBL_IFS_SIFS,
-	   { 0x00000230, 0x000001e0, 0x000000b0, 0x00000160, 0x000001e0 } },
+	   { 0x00000230, 0x000000b0, 0x00000160 } },
 	{ AR5K_DCU_GBL_IFS_SLOT,
-	   { 0x00000168, 0x000001e0, 0x000001b8, 0x0000018c, 0x000001e0 } },
+	   { 0x00000168, 0x000001b8, 0x0000018c } },
 	{ AR5K_DCU_GBL_IFS_EIFS,
-	   { 0x00000e60, 0x00001180, 0x00001f1c, 0x00003e38, 0x00001180 } },
+	   { 0x00000e60, 0x00001f1c, 0x00003e38 } },
 	{ AR5K_DCU_GBL_IFS_MISC,
-	   { 0x0000a0e0, 0x00014068, 0x00005880, 0x0000b0e0, 0x00014068 } },
+	   { 0x0000a0e0, 0x00005880, 0x0000b0e0 } },
 	{ AR5K_TIME_OUT,
-	   { 0x03e803e8, 0x06e006e0, 0x04200420, 0x08400840, 0x06e006e0 } },
-	{ AR5K_PHY_TURBO,
-	   { 0x00000000, 0x00000003, 0x00000000, 0x00000000, 0x00000003 } },
+	   { 0x03e803e8, 0x04200420, 0x08400840 } },
 	{ AR5K_PHY(8),
-	   { 0x02020200, 0x02020200, 0x02010200, 0x02020200, 0x02020200 } },
+	   { 0x02020200, 0x02010200, 0x02020200 } },
 	{ AR5K_PHY_RF_CTL2,
-	   { 0x00000e0e, 0x00000e0e, 0x00000707, 0x00000e0e, 0x00000e0e } },
+	   { 0x00000e0e, 0x00000707, 0x00000e0e } },
 	{ AR5K_PHY_SETTLING,
-	   { 0x1372161c, 0x13721c25, 0x13721722, 0x137216a2, 0x13721c25 } },
+	   { 0x1372161c, 0x13721722, 0x137216a2 } },
 	{ AR5K_PHY_AGCCTL,
-	   { 0x00009d10, 0x00009d10, 0x00009d18, 0x00009d18, 0x00009d10 } },
+	   { 0x00009d10, 0x00009d18, 0x00009d18 } },
 	{ AR5K_PHY_NF,
-	   { 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 } },
+	   { 0x0001ce00, 0x0001ce00, 0x0001ce00 } },
 	{ AR5K_PHY_WEAK_OFDM_HIGH_THR,
-	   { 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190 } },
+	   { 0x409a4190, 0x409a4190, 0x409a4190 } },
 	{ AR5K_PHY(70),
-	   { 0x000001b8, 0x000001b8, 0x00000084, 0x00000108, 0x000001b8 } },
+	   { 0x000001b8, 0x00000084, 0x00000108 } },
 	{ AR5K_PHY_OFDM_SELFCORR,
-	   { 0x10058a05, 0x10058a05, 0x10058a05, 0x10058a05, 0x10058a05 } },
+	   { 0x10058a05, 0x10058a05, 0x10058a05 } },
 	{ 0xa230,
-	   { 0x00000000, 0x00000000, 0x00000000, 0x00000108, 0x00000000 } },
+	   { 0x00000000, 0x00000000, 0x00000108 } },
 };
 
 /* Initial mode-specific settings for AR5212 + RF5111 (Written after ar5212_ini) */
 static const struct ath5k_ini_mode rf5111_ini_mode_end[] = {
 	{ AR5K_TXCFG,
-	/*	a/XR	   aTurbo	  b	   g (DYN)     gTurbo     */
-	   { 0x00008015, 0x00008015, 0x00008015, 0x00008015, 0x00008015 } },
+	/*	A/XR          B           G       */
+	   { 0x00008015, 0x00008015, 0x00008015 } },
 	{ AR5K_USEC_5211,
-	   { 0x128d8fa7, 0x09880fcf, 0x04e00f95, 0x12e00fab, 0x09880fcf } },
+	   { 0x128d8fa7, 0x04e00f95, 0x12e00fab } },
 	{ AR5K_PHY_RF_CTL3,
-	   { 0x0a020001, 0x0a020001, 0x05010100, 0x0a020001, 0x0a020001 } },
+	   { 0x0a020001, 0x05010100, 0x0a020001 } },
 	{ AR5K_PHY_RF_CTL4,
-	   { 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e } },
+	   { 0x00000e0e, 0x00000e0e, 0x00000e0e } },
 	{ AR5K_PHY_PA_CTL,
-	   { 0x00000007, 0x00000007, 0x0000000b, 0x0000000b, 0x0000000b } },
+	   { 0x00000007, 0x0000000b, 0x0000000b } },
 	{ AR5K_PHY_GAIN,
-	   { 0x0018da5a, 0x0018da5a, 0x0018ca69, 0x0018ca69, 0x0018ca69 } },
+	   { 0x0018da5a, 0x0018ca69, 0x0018ca69 } },
 	{ AR5K_PHY_DESIRED_SIZE,
-	   { 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0 } },
+	   { 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0 } },
 	{ AR5K_PHY_SIG,
-	   { 0x7e800d2e, 0x7e800d2e, 0x7ee84d2e, 0x7ee84d2e, 0x7e800d2e } },
+	   { 0x7e800d2e, 0x7ee84d2e, 0x7ee84d2e } },
 	{ AR5K_PHY_AGCCOARSE,
-	   { 0x3137665e, 0x3137665e, 0x3137665e, 0x3137665e, 0x3137615e } },
+	   { 0x3137665e, 0x3137665e, 0x3137665e } },
 	{ AR5K_PHY_WEAK_OFDM_LOW_THR,
-	   { 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb080, 0x050cb080 } },
+	   { 0x050cb081, 0x050cb081, 0x050cb080 } },
 	{ AR5K_PHY_RX_DELAY,
-	   { 0x00002710, 0x00002710, 0x0000157c, 0x00002af8, 0x00002710 } },
+	   { 0x00002710, 0x0000157c, 0x00002af8 } },
 	{ AR5K_PHY_FRAME_CTL_5211,
-	   { 0xf7b81020, 0xf7b81020, 0xf7b80d20, 0xf7b81020, 0xf7b81020 } },
+	   { 0xf7b81020, 0xf7b80d20, 0xf7b81020 } },
 	{ AR5K_PHY_GAIN_2GHZ,
-	   { 0x642c416a, 0x642c416a, 0x6440416a, 0x6440416a, 0x6440416a } },
+	   { 0x642c416a, 0x6440416a, 0x6440416a } },
 	{ AR5K_PHY_CCK_RX_CTL_4,
-	   { 0x1883800a, 0x1883800a, 0x1873800a, 0x1883800a, 0x1883800a } },
+	   { 0x1883800a, 0x1873800a, 0x1883800a } },
 };
 
 static const struct ath5k_ini rf5111_ini_common_end[] = {
@@ -782,38 +778,38 @@ static const struct ath5k_ini rf5111_ini
 /* Initial mode-specific settings for AR5212 + RF5112 (Written after ar5212_ini) */
 static const struct ath5k_ini_mode rf5112_ini_mode_end[] = {
 	{ AR5K_TXCFG,
-	/*	a/XR	   aTurbo	  b	   g (DYN)     gTurbo     */
-	   { 0x00008015, 0x00008015, 0x00008015, 0x00008015, 0x00008015 } },
+	/*	A/XR          B           G       */
+	   { 0x00008015, 0x00008015, 0x00008015 } },
 	{ AR5K_USEC_5211,
-	   { 0x128d93a7, 0x098813cf, 0x04e01395, 0x12e013ab, 0x098813cf } },
+	   { 0x128d93a7, 0x04e01395, 0x12e013ab } },
 	{ AR5K_PHY_RF_CTL3,
-	   { 0x0a020001, 0x0a020001, 0x05020100, 0x0a020001, 0x0a020001 } },
+	   { 0x0a020001, 0x05020100, 0x0a020001 } },
 	{ AR5K_PHY_RF_CTL4,
-	   { 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e } },
+	   { 0x00000e0e, 0x00000e0e, 0x00000e0e } },
 	{ AR5K_PHY_PA_CTL,
-	   { 0x00000007, 0x00000007, 0x0000000b, 0x0000000b, 0x0000000b } },
+	   { 0x00000007, 0x0000000b, 0x0000000b } },
 	{ AR5K_PHY_GAIN,
-	   { 0x0018da6d, 0x0018da6d, 0x0018ca75, 0x0018ca75, 0x0018ca75 } },
+	   { 0x0018da6d, 0x0018ca75, 0x0018ca75 } },
 	{ AR5K_PHY_DESIRED_SIZE,
-	   { 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0 } },
+	   { 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0 } },
 	{ AR5K_PHY_SIG,
-	   { 0x7e800d2e, 0x7e800d2e, 0x7ee80d2e, 0x7ee80d2e, 0x7e800d2e } },
+	   { 0x7e800d2e, 0x7ee80d2e, 0x7ee80d2e } },
 	{ AR5K_PHY_AGCCOARSE,
-	   { 0x3137665e, 0x3137665e, 0x3137665e, 0x3137665e, 0x3137665e } },
+	   { 0x3137665e, 0x3137665e, 0x3137665e } },
 	{ AR5K_PHY_WEAK_OFDM_LOW_THR,
-	   { 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 } },
+	   { 0x050cb081, 0x050cb081, 0x050cb081 } },
 	{ AR5K_PHY_RX_DELAY,
-	   { 0x000007d0, 0x000007d0, 0x0000044c, 0x00000898, 0x000007d0 } },
+	   { 0x000007d0, 0x0000044c, 0x00000898 } },
 	{ AR5K_PHY_FRAME_CTL_5211,
-	   { 0xf7b81020, 0xf7b81020, 0xf7b80d10, 0xf7b81010, 0xf7b81010 } },
+	   { 0xf7b81020, 0xf7b80d10, 0xf7b81010 } },
 	{ AR5K_PHY_CCKTXCTL,
-	   { 0x00000000, 0x00000000, 0x00000008, 0x00000008, 0x00000008 } },
+	   { 0x00000000, 0x00000008, 0x00000008 } },
 	{ AR5K_PHY_CCK_CROSSCORR,
-	   { 0xd6be6788, 0xd6be6788, 0xd03e6788, 0xd03e6788, 0xd03e6788 } },
+	   { 0xd6be6788, 0xd03e6788, 0xd03e6788 } },
 	{ AR5K_PHY_GAIN_2GHZ,
-	   { 0x642c0140, 0x642c0140, 0x6442c160, 0x6442c160, 0x6442c160 } },
+	   { 0x642c0140, 0x6442c160, 0x6442c160 } },
 	{ AR5K_PHY_CCK_RX_CTL_4,
-	   { 0x1883800a, 0x1883800a, 0x1873800a, 0x1883800a, 0x1883800a } },
+	   { 0x1883800a, 0x1873800a, 0x1883800a } },
 };
 
 static const struct ath5k_ini rf5112_ini_common_end[] = {
@@ -833,66 +829,66 @@ static const struct ath5k_ini rf5112_ini
 /* Initial mode-specific settings for RF5413/5414 (Written after ar5212_ini) */
 static const struct ath5k_ini_mode rf5413_ini_mode_end[] = {
 	{ AR5K_TXCFG,
-	/*	a/XR	   aTurbo	  b	   g (DYN)     gTurbo     */
-	   { 0x00000015, 0x00000015, 0x00000015, 0x00000015, 0x00000015 } },
+	/*	A/XR          B           G       */
+	   { 0x00000015, 0x00000015, 0x00000015 } },
 	{ AR5K_USEC_5211,
-	   { 0x128d93a7, 0x098813cf, 0x04e01395, 0x12e013ab, 0x098813cf } },
+	   { 0x128d93a7, 0x04e01395, 0x12e013ab } },
 	{ AR5K_PHY_RF_CTL3,
-	   { 0x0a020001, 0x0a020001, 0x05020100, 0x0a020001, 0x0a020001 } },
+	   { 0x0a020001, 0x05020100, 0x0a020001 } },
 	{ AR5K_PHY_RF_CTL4,
-	   { 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e } },
+	   { 0x00000e0e, 0x00000e0e, 0x00000e0e } },
 	{ AR5K_PHY_PA_CTL,
-	   { 0x00000007, 0x00000007, 0x0000000b, 0x0000000b, 0x0000000b } },
+	   { 0x00000007, 0x0000000b, 0x0000000b } },
 	{ AR5K_PHY_GAIN,
-	   { 0x0018fa61, 0x0018fa61, 0x001a1a63, 0x001a1a63, 0x001a1a63 } },
+	   { 0x0018fa61, 0x001a1a63, 0x001a1a63 } },
 	{ AR5K_PHY_DESIRED_SIZE,
-	   { 0x0c98b4e0, 0x0c98b4e0, 0x0c98b0da, 0x0c98b0da, 0x0c98b0da } },
+	   { 0x0c98b4e0, 0x0c98b0da, 0x0c98b0da } },
 	{ AR5K_PHY_SIG,
-	   { 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e } },
+	   { 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e } },
 	{ AR5K_PHY_AGCCOARSE,
-	   { 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e } },
+	   { 0x3139605e, 0x3139605e, 0x3139605e } },
 	{ AR5K_PHY_WEAK_OFDM_LOW_THR,
-	   { 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 } },
+	   { 0x050cb081, 0x050cb081, 0x050cb081 } },
 	{ AR5K_PHY_RX_DELAY,
-	   { 0x000007d0, 0x000007d0, 0x0000044c, 0x00000898, 0x000007d0 } },
+	   { 0x000007d0, 0x0000044c, 0x00000898 } },
 	{ AR5K_PHY_FRAME_CTL_5211,
-	   { 0xf7b81000, 0xf7b81000, 0xf7b80d00, 0xf7b81000, 0xf7b81000 } },
+	   { 0xf7b81000, 0xf7b80d00, 0xf7b81000 } },
 	{ AR5K_PHY_CCKTXCTL,
-	   { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+	   { 0x00000000, 0x00000000, 0x00000000 } },
 	{ AR5K_PHY_CCK_CROSSCORR,
-	   { 0xd6be6788, 0xd6be6788, 0xd03e6788, 0xd03e6788, 0xd03e6788 } },
+	   { 0xd6be6788, 0xd03e6788, 0xd03e6788 } },
 	{ AR5K_PHY_GAIN_2GHZ,
-	   { 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120, 0x002ac120 } },
+	   { 0x002ec1e0, 0x002ac120, 0x002ac120 } },
 	{ AR5K_PHY_CCK_RX_CTL_4,
-	   { 0x1883800a, 0x1883800a, 0x1863800a, 0x1883800a, 0x1883800a } },
+	   { 0x1883800a, 0x1863800a, 0x1883800a } },
 	{ 0xa300,
-	   { 0x18010000, 0x18010000, 0x18010000, 0x18010000, 0x18010000 } },
+	   { 0x18010000, 0x18010000, 0x18010000 } },
 	{ 0xa304,
-	   { 0x30032602, 0x30032602, 0x30032602, 0x30032602, 0x30032602 } },
+	   { 0x30032602, 0x30032602, 0x30032602 } },
 	{ 0xa308,
-	   { 0x48073e06, 0x48073e06, 0x48073e06, 0x48073e06, 0x48073e06 } },
+	   { 0x48073e06, 0x48073e06, 0x48073e06 } },
 	{ 0xa30c,
-	   { 0x560b4c0a, 0x560b4c0a, 0x560b4c0a, 0x560b4c0a, 0x560b4c0a } },
+	   { 0x560b4c0a, 0x560b4c0a, 0x560b4c0a } },
 	{ 0xa310,
-	   { 0x641a600f, 0x641a600f, 0x641a600f, 0x641a600f, 0x641a600f } },
+	   { 0x641a600f, 0x641a600f, 0x641a600f } },
 	{ 0xa314,
-	   { 0x784f6e1b, 0x784f6e1b, 0x784f6e1b, 0x784f6e1b, 0x784f6e1b } },
+	   { 0x784f6e1b, 0x784f6e1b, 0x784f6e1b } },
 	{ 0xa318,
-	   { 0x868f7c5a, 0x868f7c5a, 0x868f7c5a, 0x868f7c5a, 0x868f7c5a } },
+	   { 0x868f7c5a, 0x868f7c5a, 0x868f7c5a } },
 	{ 0xa31c,
-	   { 0x90cf865b, 0x90cf865b, 0x8ecf865b, 0x8ecf865b, 0x8ecf865b } },
+	   { 0x90cf865b, 0x8ecf865b, 0x8ecf865b } },
 	{ 0xa320,
-	   { 0x9d4f970f, 0x9d4f970f, 0x9b4f970f, 0x9b4f970f, 0x9b4f970f } },
+	   { 0x9d4f970f, 0x9b4f970f, 0x9b4f970f } },
 	{ 0xa324,
-	   { 0xa7cfa38f, 0xa7cfa38f, 0xa3cf9f8f, 0xa3cf9f8f, 0xa3cf9f8f } },
+	   { 0xa7cfa38f, 0xa3cf9f8f, 0xa3cf9f8f } },
 	{ 0xa328,
-	   { 0xb55faf1f, 0xb55faf1f, 0xb35faf1f, 0xb35faf1f, 0xb35faf1f } },
+	   { 0xb55faf1f, 0xb35faf1f, 0xb35faf1f } },
 	{ 0xa32c,
-	   { 0xbddfb99f, 0xbddfb99f, 0xbbdfb99f, 0xbbdfb99f, 0xbbdfb99f } },
+	   { 0xbddfb99f, 0xbbdfb99f, 0xbbdfb99f } },
 	{ 0xa330,
-	   { 0xcb7fc53f, 0xcb7fc53f, 0xcb7fc73f, 0xcb7fc73f, 0xcb7fc73f } },
+	   { 0xcb7fc53f, 0xcb7fc73f, 0xcb7fc73f } },
 	{ 0xa334,
-	   { 0xd5ffd1bf, 0xd5ffd1bf, 0xd3ffd1bf, 0xd3ffd1bf, 0xd3ffd1bf } },
+	   { 0xd5ffd1bf, 0xd3ffd1bf, 0xd3ffd1bf } },
 };
 
 static const struct ath5k_ini rf5413_ini_common_end[] = {
@@ -972,38 +968,38 @@ static const struct ath5k_ini rf5413_ini
 /* XXX: a mode ? */
 static const struct ath5k_ini_mode rf2413_ini_mode_end[] = {
 	{ AR5K_TXCFG,
-	/*	a/XR	   aTurbo	  b	   g (DYN)     gTurbo     */
-	   { 0x00000015, 0x00000015, 0x00000015, 0x00000015, 0x00000015 } },
+	/*	A/XR          B           G       */
+	   { 0x00000015, 0x00000015, 0x00000015 } },
 	{ AR5K_USEC_5211,
-	   { 0x128d93a7, 0x098813cf, 0x04e01395, 0x12e013ab, 0x098813cf } },
+	   { 0x128d93a7, 0x04e01395, 0x12e013ab } },
 	{ AR5K_PHY_RF_CTL3,
-	   { 0x0a020001, 0x0a020001, 0x05020000, 0x0a020001, 0x0a020001 } },
+	   { 0x0a020001, 0x05020000, 0x0a020001 } },
 	{ AR5K_PHY_RF_CTL4,
-	   { 0x00000e00, 0x00000e00, 0x00000e00, 0x00000e00, 0x00000e00 } },
+	   { 0x00000e00, 0x00000e00, 0x00000e00 } },
 	{ AR5K_PHY_PA_CTL,
-	   { 0x00000002, 0x00000002, 0x0000000a, 0x0000000a, 0x0000000a } },
+	   { 0x00000002, 0x0000000a, 0x0000000a } },
 	{ AR5K_PHY_GAIN,
-	   { 0x0018da6d, 0x0018da6d, 0x001a6a64, 0x001a6a64, 0x001a6a64 } },
+	   { 0x0018da6d, 0x001a6a64, 0x001a6a64 } },
 	{ AR5K_PHY_DESIRED_SIZE,
-	   { 0x0de8b4e0, 0x0de8b4e0, 0x0de8b0da, 0x0c98b0da, 0x0de8b0da } },
+	   { 0x0de8b4e0, 0x0de8b0da, 0x0c98b0da } },
 	{ AR5K_PHY_SIG,
-	   { 0x7e800d2e, 0x7e800d2e, 0x7ee80d2e, 0x7ec80d2e, 0x7e800d2e } },
+	   { 0x7e800d2e, 0x7ee80d2e, 0x7ec80d2e } },
 	{ AR5K_PHY_AGCCOARSE,
-	   { 0x3137665e, 0x3137665e, 0x3137665e, 0x3139605e, 0x3137665e } },
+	   { 0x3137665e, 0x3137665e, 0x3139605e } },
 	{ AR5K_PHY_WEAK_OFDM_LOW_THR,
-	   { 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 } },
+	   { 0x050cb081, 0x050cb081, 0x050cb081 } },
 	{ AR5K_PHY_RX_DELAY,
-	   { 0x000007d0, 0x000007d0, 0x0000044c, 0x00000898, 0x000007d0 } },
+	   { 0x000007d0, 0x0000044c, 0x00000898 } },
 	{ AR5K_PHY_FRAME_CTL_5211,
-	   { 0xf7b81000, 0xf7b81000, 0xf7b80d00, 0xf7b81000, 0xf7b81000 } },
+	   { 0xf7b81000, 0xf7b80d00, 0xf7b81000 } },
 	{ AR5K_PHY_CCKTXCTL,
-	   { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+	   { 0x00000000, 0x00000000, 0x00000000 } },
 	{ AR5K_PHY_CCK_CROSSCORR,
-	   { 0xd6be6788, 0xd6be6788, 0xd03e6788, 0xd03e6788, 0xd03e6788 } },
+	   { 0xd6be6788, 0xd03e6788, 0xd03e6788 } },
 	{ AR5K_PHY_GAIN_2GHZ,
-	   { 0x002c0140, 0x002c0140, 0x0042c140, 0x0042c140, 0x0042c140 } },
+	   { 0x002c0140, 0x0042c140, 0x0042c140 } },
 	{ AR5K_PHY_CCK_RX_CTL_4,
-	   { 0x1883800a, 0x1883800a, 0x1863800a, 0x1883800a, 0x1883800a } },
+	   { 0x1883800a, 0x1863800a, 0x1883800a } },
 };
 
 static const struct ath5k_ini rf2413_ini_common_end[] = {
@@ -1094,52 +1090,50 @@ static const struct ath5k_ini rf2413_ini
 /* XXX: a mode ? */
 static const struct ath5k_ini_mode rf2425_ini_mode_end[] = {
 	{ AR5K_TXCFG,
-	/*	a/XR	   aTurbo	  b	   g (DYN)     gTurbo     */
-	   { 0x00000015, 0x00000015, 0x00000015, 0x00000015, 0x00000015 } },
+	/*	A/XR          B           G       */
+	   { 0x00000015, 0x00000015, 0x00000015 } },
 	{ AR5K_USEC_5211,
-	   { 0x128d93a7, 0x098813cf, 0x04e01395, 0x12e013ab, 0x098813cf } },
-	{ AR5K_PHY_TURBO,
-	   { 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000001 } },
+	   { 0x128d93a7, 0x04e01395, 0x12e013ab } },
 	{ AR5K_PHY_RF_CTL3,
-	   { 0x0a020001, 0x0a020001, 0x05020100, 0x0a020001, 0x0a020001 } },
+	   { 0x0a020001, 0x05020100, 0x0a020001 } },
 	{ AR5K_PHY_RF_CTL4,
-	   { 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e } },
+	   { 0x00000e0e, 0x00000e0e, 0x00000e0e } },
 	{ AR5K_PHY_PA_CTL,
-	   { 0x00000003, 0x00000003, 0x0000000b, 0x0000000b, 0x0000000b } },
+	   { 0x00000003, 0x0000000b, 0x0000000b } },
 	{ AR5K_PHY_SETTLING,
-	   { 0x1372161c, 0x13721c25, 0x13721722, 0x13721422, 0x13721c25 } },
+	   { 0x1372161c, 0x13721722, 0x13721422 } },
 	{ AR5K_PHY_GAIN,
-	   { 0x0018fa61, 0x0018fa61, 0x00199a65, 0x00199a65, 0x00199a65 } },
+	   { 0x0018fa61, 0x00199a65, 0x00199a65 } },
 	{ AR5K_PHY_DESIRED_SIZE,
-	   { 0x0c98b4e0, 0x0c98b4e0, 0x0c98b0da, 0x0c98b0da, 0x0c98b0da } },
+	   { 0x0c98b4e0, 0x0c98b0da, 0x0c98b0da } },
 	{ AR5K_PHY_SIG,
-	   { 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e } },
+	   { 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e } },
 	{ AR5K_PHY_AGCCOARSE,
-	   { 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e } },
+	   { 0x3139605e, 0x3139605e, 0x3139605e } },
 	{ AR5K_PHY_WEAK_OFDM_LOW_THR,
-	   { 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 } },
+	   { 0x050cb081, 0x050cb081, 0x050cb081 } },
 	{ AR5K_PHY_RX_DELAY,
-	   { 0x000007d0, 0x000007d0, 0x0000044c, 0x00000898, 0x000007d0 } },
+	   { 0x000007d0, 0x0000044c, 0x00000898 } },
 	{ AR5K_PHY_FRAME_CTL_5211,
-	   { 0xf7b81000, 0xf7b81000, 0xf7b80d00, 0xf7b81000, 0xf7b81000 } },
+	   { 0xf7b81000, 0xf7b80d00, 0xf7b81000 } },
 	{ AR5K_PHY_CCKTXCTL,
-	   { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+	   { 0x00000000, 0x00000000, 0x00000000 } },
 	{ AR5K_PHY_CCK_CROSSCORR,
-	   { 0xd6be6788, 0xd6be6788, 0xd03e6788, 0xd03e6788, 0xd03e6788 } },
+	   { 0xd6be6788, 0xd03e6788, 0xd03e6788 } },
 	{ AR5K_PHY_GAIN_2GHZ,
-	   { 0x00000140, 0x00000140, 0x0052c140, 0x0052c140, 0x0052c140 } },
+	   { 0x00000140, 0x0052c140, 0x0052c140 } },
 	{ AR5K_PHY_CCK_RX_CTL_4,
-	   { 0x1883800a, 0x1883800a, 0x1863800a, 0x1883800a, 0x1883800a } },
+	   { 0x1883800a, 0x1863800a, 0x1883800a } },
 	{ 0xa324,
-	   { 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf } },
+	   { 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf } },
 	{ 0xa328,
-	   { 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf } },
+	   { 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf } },
 	{ 0xa32c,
-	   { 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf } },
+	   { 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf } },
 	{ 0xa330,
-	   { 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf } },
+	   { 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf } },
 	{ 0xa334,
-	   { 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf } },
+	   { 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf } },
 };
 
 static const struct ath5k_ini rf2425_ini_common_end[] = {
@@ -1368,15 +1362,15 @@ static const struct ath5k_ini rf5112_ini
  * Write initial register dump
  */
 static void ath5k_hw_ini_registers(struct ath5k_hw *ah, unsigned int size,
-		const struct ath5k_ini *ini_regs, bool change_channel)
+		const struct ath5k_ini *ini_regs, bool skip_pcu)
 {
 	unsigned int i;
 
 	/* Write initial registers */
 	for (i = 0; i < size; i++) {
-		/* On channel change there is
-		 * no need to mess with PCU */
-		if (change_channel &&
+		/* Skip PCU registers if
+		 * requested */
+		if (skip_pcu &&
 				ini_regs[i].ini_register >= AR5K_PCU_MIN &&
 				ini_regs[i].ini_register <= AR5K_PCU_MAX)
 			continue;
@@ -1409,7 +1403,7 @@ static void ath5k_hw_ini_mode_registers(
 
 }
 
-int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool change_channel)
+int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool skip_pcu)
 {
 	/*
 	 * Write initial register settings
@@ -1427,7 +1421,7 @@ int ath5k_hw_write_initvals(struct ath5k
 		 * Write initial settings common for all modes
 		 */
 		ath5k_hw_ini_registers(ah, ARRAY_SIZE(ar5212_ini_common_start),
-				ar5212_ini_common_start, change_channel);
+				ar5212_ini_common_start, skip_pcu);
 
 		/* Second set of mode-specific settings */
 		switch (ah->ah_radio) {
@@ -1439,12 +1433,12 @@ int ath5k_hw_write_initvals(struct ath5k
 
 			ath5k_hw_ini_registers(ah,
 					ARRAY_SIZE(rf5111_ini_common_end),
-					rf5111_ini_common_end, change_channel);
+					rf5111_ini_common_end, skip_pcu);
 
 			/* Baseband gain table */
 			ath5k_hw_ini_registers(ah,
 					ARRAY_SIZE(rf5111_ini_bbgain),
-					rf5111_ini_bbgain, change_channel);
+					rf5111_ini_bbgain, skip_pcu);
 
 			break;
 		case AR5K_RF5112:
@@ -1455,11 +1449,11 @@ int ath5k_hw_write_initvals(struct ath5k
 
 			ath5k_hw_ini_registers(ah,
 					ARRAY_SIZE(rf5112_ini_common_end),
-					rf5112_ini_common_end, change_channel);
+					rf5112_ini_common_end, skip_pcu);
 
 			ath5k_hw_ini_registers(ah,
 					ARRAY_SIZE(rf5112_ini_bbgain),
-					rf5112_ini_bbgain, change_channel);
+					rf5112_ini_bbgain, skip_pcu);
 
 			break;
 		case AR5K_RF5413:
@@ -1470,11 +1464,11 @@ int ath5k_hw_write_initvals(struct ath5k
 
 			ath5k_hw_ini_registers(ah,
 					ARRAY_SIZE(rf5413_ini_common_end),
-					rf5413_ini_common_end, change_channel);
+					rf5413_ini_common_end, skip_pcu);
 
 			ath5k_hw_ini_registers(ah,
 					ARRAY_SIZE(rf5112_ini_bbgain),
-					rf5112_ini_bbgain, change_channel);
+					rf5112_ini_bbgain, skip_pcu);
 
 			break;
 		case AR5K_RF2316:
@@ -1486,7 +1480,7 @@ int ath5k_hw_write_initvals(struct ath5k
 
 			ath5k_hw_ini_registers(ah,
 					ARRAY_SIZE(rf2413_ini_common_end),
-					rf2413_ini_common_end, change_channel);
+					rf2413_ini_common_end, skip_pcu);
 
 			/* Override settings from rf2413_ini_common_end */
 			if (ah->ah_radio == AR5K_RF2316) {
@@ -1498,9 +1492,32 @@ int ath5k_hw_write_initvals(struct ath5k
 
 			ath5k_hw_ini_registers(ah,
 					ARRAY_SIZE(rf5112_ini_bbgain),
-					rf5112_ini_bbgain, change_channel);
+					rf5112_ini_bbgain, skip_pcu);
 			break;
 		case AR5K_RF2317:
+
+			ath5k_hw_ini_mode_registers(ah,
+					ARRAY_SIZE(rf2413_ini_mode_end),
+					rf2413_ini_mode_end, mode);
+
+			ath5k_hw_ini_registers(ah,
+					ARRAY_SIZE(rf2425_ini_common_end),
+					rf2425_ini_common_end, skip_pcu);
+
+			/* Override settings from rf2413_ini_mode_end */
+			ath5k_hw_reg_write(ah, 0x00180a65, AR5K_PHY_GAIN);
+
+			/* Override settings from rf2413_ini_common_end */
+			ath5k_hw_reg_write(ah, 0x00004000, AR5K_PHY_AGC);
+			AR5K_REG_WRITE_BITS(ah, AR5K_PHY_TPC_RG5,
+				AR5K_PHY_TPC_RG5_PD_GAIN_OVERLAP, 0xa);
+			ath5k_hw_reg_write(ah, 0x800000a8, 0x8140);
+			ath5k_hw_reg_write(ah, 0x000000ff, 0x9958);
+
+			ath5k_hw_ini_registers(ah,
+					ARRAY_SIZE(rf5112_ini_bbgain),
+					rf5112_ini_bbgain, skip_pcu);
+			break;
 		case AR5K_RF2425:
 
 			ath5k_hw_ini_mode_registers(ah,
@@ -1509,11 +1526,11 @@ int ath5k_hw_write_initvals(struct ath5k
 
 			ath5k_hw_ini_registers(ah,
 					ARRAY_SIZE(rf2425_ini_common_end),
-					rf2425_ini_common_end, change_channel);
+					rf2425_ini_common_end, skip_pcu);
 
 			ath5k_hw_ini_registers(ah,
 					ARRAY_SIZE(rf5112_ini_bbgain),
-					rf5112_ini_bbgain, change_channel);
+					rf5112_ini_bbgain, skip_pcu);
 			break;
 		default:
 			return -EINVAL;
@@ -1538,17 +1555,17 @@ int ath5k_hw_write_initvals(struct ath5k
 		 * Write initial settings common for all modes
 		 */
 		ath5k_hw_ini_registers(ah, ARRAY_SIZE(ar5211_ini),
-				ar5211_ini, change_channel);
+				ar5211_ini, skip_pcu);
 
 		/* AR5211 only comes with 5111 */
 
 		/* Baseband gain table */
 		ath5k_hw_ini_registers(ah, ARRAY_SIZE(rf5111_ini_bbgain),
-				rf5111_ini_bbgain, change_channel);
+				rf5111_ini_bbgain, skip_pcu);
 	/* For AR5210 (for mode settings check out ath5k_hw_reset_tx_queue) */
 	} else if (ah->ah_version == AR5K_AR5210) {
 		ath5k_hw_ini_registers(ah, ARRAY_SIZE(ar5210_ini),
-				ar5210_ini, change_channel);
+				ar5210_ini, skip_pcu);
 	}
 
 	return 0;
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath5k/Kconfig linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath5k/Kconfig
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath5k/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath5k/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -1,9 +1,12 @@
 config ATH5K
 	tristate "Atheros 5xxx wireless cards support"
-	depends on PCI && MAC80211
+	depends on (PCI || ATHEROS_AR231X) && MAC80211
 	select MAC80211_LEDS
 	select LEDS_CLASS
 	select NEW_LEDS
+	select AVERAGE
+	select ATH5K_AHB if (ATHEROS_AR231X && !PCI)
+	select ATH5K_PCI if (!ATHEROS_AR231X && PCI)
 	---help---
 	  This module adds support for wireless adapters based on
 	  Atheros 5xxx chipset.
@@ -37,3 +40,16 @@ config ATH5K_DEBUG
 
 	  modprobe ath5k debug=0x00000400
 
+config ATH5K_AHB
+	bool "Atheros 5xxx AHB bus support"
+	depends on (ATHEROS_AR231X && !PCI)
+	---help---
+	  This adds support for WiSoC type chipsets of the 5xxx Atheros
+	  family.
+
+config ATH5K_PCI
+	bool "Atheros 5xxx PCI bus support"
+	depends on (!ATHEROS_AR231X && PCI)
+	---help---
+	  This adds support for PCI type chipsets of the 5xxx Atheros
+	  family.
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath5k/led.c linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath5k/led.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath5k/led.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath5k/led.c	2011-03-14 21:20:32.000000000 -0400
@@ -133,7 +133,7 @@ ath5k_register_led(struct ath5k_softc *s
 	led->led_dev.default_trigger = trigger;
 	led->led_dev.brightness_set = ath5k_led_brightness_set;
 
-	err = led_classdev_register(&sc->pdev->dev, &led->led_dev);
+	err = led_classdev_register(sc->dev, &led->led_dev);
 	if (err) {
 		ATH5K_WARN(sc, "could not register LED %s\n", name);
 		led->sc = NULL;
@@ -161,11 +161,20 @@ int ath5k_init_leds(struct ath5k_softc *
 {
 	int ret = 0;
 	struct ieee80211_hw *hw = sc->hw;
+#ifndef CONFIG_ATHEROS_AR231X
 	struct pci_dev *pdev = sc->pdev;
+#endif
 	char name[ATH5K_LED_MAX_NAME_LEN + 1];
 	const struct pci_device_id *match;
 
+	if (!sc->pdev)
+		return 0;
+
+#ifdef CONFIG_ATHEROS_AR231X
+	match = NULL;
+#else
 	match = pci_match_id(&ath5k_led_devices[0], pdev);
+#endif
 	if (match) {
 		__set_bit(ATH_STAT_LEDSOFT, sc->status);
 		sc->led_pin = ATH_PIN(match->driver_data);
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath5k/mac80211-ops.c linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath5k/mac80211-ops.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath5k/mac80211-ops.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath5k/mac80211-ops.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,774 @@
+/*-
+ * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
+ * Copyright (c) 2004-2005 Atheros Communications, Inc.
+ * Copyright (c) 2006 Devicescape Software, Inc.
+ * Copyright (c) 2007 Jiri Slaby <jirislaby@gmail.com>
+ * Copyright (c) 2007 Luis R. Rodriguez <mcgrof@winlab.rutgers.edu>
+ * Copyright (c) 2010 Bruno Randolf <br1@einfach.org>
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer,
+ *    without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
+ *    redistribution must be conditioned upon including a substantially
+ *    similar Disclaimer requirement for further binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ *    of any 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") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ *
+ */
+
+#include <asm/unaligned.h>
+
+#include "base.h"
+#include "reg.h"
+
+extern int ath5k_modparam_nohwcrypt;
+
+/* functions used from base.c */
+void set_beacon_filter(struct ieee80211_hw *hw, bool enable);
+bool ath_any_vif_assoc(struct ath5k_softc *sc);
+int ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb,
+		   struct ath5k_txq *txq);
+int ath5k_init_hw(struct ath5k_softc *sc);
+int ath5k_stop_hw(struct ath5k_softc *sc);
+void ath5k_mode_setup(struct ath5k_softc *sc, struct ieee80211_vif *vif);
+void ath5k_update_bssid_mask_and_opmode(struct ath5k_softc *sc,
+					struct ieee80211_vif *vif);
+int ath5k_chan_set(struct ath5k_softc *sc, struct ieee80211_channel *chan);
+void ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf);
+int ath5k_beacon_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
+void ath5k_beacon_config(struct ath5k_softc *sc);
+void ath5k_txbuf_free_skb(struct ath5k_softc *sc, struct ath5k_buf *bf);
+void ath5k_rxbuf_free_skb(struct ath5k_softc *sc, struct ath5k_buf *bf);
+
+/********************\
+* Mac80211 functions *
+\********************/
+
+static int
+ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
+{
+	struct ath5k_softc *sc = hw->priv;
+	u16 qnum = skb_get_queue_mapping(skb);
+
+	if (WARN_ON(qnum >= sc->ah->ah_capabilities.cap_queues.q_tx_num)) {
+		dev_kfree_skb_any(skb);
+		return 0;
+	}
+
+	return ath5k_tx_queue(hw, skb, &sc->txqs[qnum]);
+}
+
+
+static int
+ath5k_start(struct ieee80211_hw *hw)
+{
+	return ath5k_init_hw(hw->priv);
+}
+
+
+static void
+ath5k_stop(struct ieee80211_hw *hw)
+{
+	ath5k_stop_hw(hw->priv);
+}
+
+
+static int
+ath5k_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
+{
+	struct ath5k_softc *sc = hw->priv;
+	int ret;
+	struct ath5k_vif *avf = (void *)vif->drv_priv;
+
+	mutex_lock(&sc->lock);
+
+	if ((vif->type == NL80211_IFTYPE_AP ||
+	     vif->type == NL80211_IFTYPE_ADHOC)
+	    && (sc->num_ap_vifs + sc->num_adhoc_vifs) >= ATH_BCBUF) {
+		ret = -ELNRNG;
+		goto end;
+	}
+
+	/* Don't allow other interfaces if one ad-hoc is configured.
+	 * TODO: Fix the problems with ad-hoc and multiple other interfaces.
+	 * We would need to operate the HW in ad-hoc mode to allow TSF updates
+	 * for the IBSS, but this breaks with additional AP or STA interfaces
+	 * at the moment. */
+	if (sc->num_adhoc_vifs ||
+	    (sc->nvifs && vif->type == NL80211_IFTYPE_ADHOC)) {
+		ATH5K_ERR(sc, "Only one single ad-hoc interface is allowed.\n");
+		ret = -ELNRNG;
+		goto end;
+	}
+
+	switch (vif->type) {
+	case NL80211_IFTYPE_AP:
+	case NL80211_IFTYPE_STATION:
+	case NL80211_IFTYPE_ADHOC:
+	case NL80211_IFTYPE_MESH_POINT:
+		avf->opmode = vif->type;
+		break;
+	default:
+		ret = -EOPNOTSUPP;
+		goto end;
+	}
+
+	sc->nvifs++;
+	ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "add interface mode %d\n", avf->opmode);
+
+	/* Assign the vap/adhoc to a beacon xmit slot. */
+	if ((avf->opmode == NL80211_IFTYPE_AP) ||
+	    (avf->opmode == NL80211_IFTYPE_ADHOC) ||
+	    (avf->opmode == NL80211_IFTYPE_MESH_POINT)) {
+		int slot;
+
+		WARN_ON(list_empty(&sc->bcbuf));
+		avf->bbuf = list_first_entry(&sc->bcbuf, struct ath5k_buf,
+					     list);
+		list_del(&avf->bbuf->list);
+
+		avf->bslot = 0;
+		for (slot = 0; slot < ATH_BCBUF; slot++) {
+			if (!sc->bslot[slot]) {
+				avf->bslot = slot;
+				break;
+			}
+		}
+		BUG_ON(sc->bslot[avf->bslot] != NULL);
+		sc->bslot[avf->bslot] = vif;
+		if (avf->opmode == NL80211_IFTYPE_AP)
+			sc->num_ap_vifs++;
+		else if (avf->opmode == NL80211_IFTYPE_ADHOC)
+			sc->num_adhoc_vifs++;
+	}
+
+	/* Any MAC address is fine, all others are included through the
+	 * filter.
+	 */
+	memcpy(&sc->lladdr, vif->addr, ETH_ALEN);
+	ath5k_hw_set_lladdr(sc->ah, vif->addr);
+
+	memcpy(&avf->lladdr, vif->addr, ETH_ALEN);
+
+	ath5k_mode_setup(sc, vif);
+
+	ret = 0;
+end:
+	mutex_unlock(&sc->lock);
+	return ret;
+}
+
+
+static void
+ath5k_remove_interface(struct ieee80211_hw *hw,
+		       struct ieee80211_vif *vif)
+{
+	struct ath5k_softc *sc = hw->priv;
+	struct ath5k_vif *avf = (void *)vif->drv_priv;
+	unsigned int i;
+
+	mutex_lock(&sc->lock);
+	sc->nvifs--;
+
+	if (avf->bbuf) {
+		ath5k_txbuf_free_skb(sc, avf->bbuf);
+		list_add_tail(&avf->bbuf->list, &sc->bcbuf);
+		for (i = 0; i < ATH_BCBUF; i++) {
+			if (sc->bslot[i] == vif) {
+				sc->bslot[i] = NULL;
+				break;
+			}
+		}
+		avf->bbuf = NULL;
+	}
+	if (avf->opmode == NL80211_IFTYPE_AP)
+		sc->num_ap_vifs--;
+	else if (avf->opmode == NL80211_IFTYPE_ADHOC)
+		sc->num_adhoc_vifs--;
+
+	ath5k_update_bssid_mask_and_opmode(sc, NULL);
+	mutex_unlock(&sc->lock);
+}
+
+
+/*
+ * TODO: Phy disable/diversity etc
+ */
+static int
+ath5k_config(struct ieee80211_hw *hw, u32 changed)
+{
+	struct ath5k_softc *sc = hw->priv;
+	struct ath5k_hw *ah = sc->ah;
+	struct ieee80211_conf *conf = &hw->conf;
+	int ret = 0;
+
+	mutex_lock(&sc->lock);
+
+	if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
+		ret = ath5k_chan_set(sc, conf->channel);
+		if (ret < 0)
+			goto unlock;
+	}
+
+	if ((changed & IEEE80211_CONF_CHANGE_POWER) &&
+	(sc->power_level != conf->power_level)) {
+		sc->power_level = conf->power_level;
+
+		/* Half dB steps */
+		ath5k_hw_set_txpower_limit(ah, (conf->power_level * 2));
+	}
+
+	/* TODO:
+	 * 1) Move this on config_interface and handle each case
+	 * separately eg. when we have only one STA vif, use
+	 * AR5K_ANTMODE_SINGLE_AP
+	 *
+	 * 2) Allow the user to change antenna mode eg. when only
+	 * one antenna is present
+	 *
+	 * 3) Allow the user to set default/tx antenna when possible
+	 *
+	 * 4) Default mode should handle 90% of the cases, together
+	 * with fixed a/b and single AP modes we should be able to
+	 * handle 99%. Sectored modes are extreme cases and i still
+	 * haven't found a usage for them. If we decide to support them,
+	 * then we must allow the user to set how many tx antennas we
+	 * have available
+	 */
+	ath5k_hw_set_antenna_mode(ah, ah->ah_ant_mode);
+
+unlock:
+	mutex_unlock(&sc->lock);
+	return ret;
+}
+
+
+static void
+ath5k_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+		       struct ieee80211_bss_conf *bss_conf, u32 changes)
+{
+	struct ath5k_vif *avf = (void *)vif->drv_priv;
+	struct ath5k_softc *sc = hw->priv;
+	struct ath5k_hw *ah = sc->ah;
+	struct ath_common *common = ath5k_hw_common(ah);
+	unsigned long flags;
+
+	mutex_lock(&sc->lock);
+
+	if (changes & BSS_CHANGED_BSSID) {
+		/* Cache for later use during resets */
+		memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN);
+		common->curaid = 0;
+		ath5k_hw_set_bssid(ah);
+		mmiowb();
+	}
+
+	if (changes & BSS_CHANGED_BEACON_INT)
+		sc->bintval = bss_conf->beacon_int;
+
+	if (changes & BSS_CHANGED_ASSOC) {
+		avf->assoc = bss_conf->assoc;
+		if (bss_conf->assoc)
+			sc->assoc = bss_conf->assoc;
+		else
+			sc->assoc = ath_any_vif_assoc(sc);
+
+		if (sc->opmode == NL80211_IFTYPE_STATION)
+			set_beacon_filter(hw, sc->assoc);
+		ath5k_hw_set_ledstate(sc->ah, sc->assoc ?
+			AR5K_LED_ASSOC : AR5K_LED_INIT);
+		if (bss_conf->assoc) {
+			ATH5K_DBG(sc, ATH5K_DEBUG_ANY,
+				  "Bss Info ASSOC %d, bssid: %pM\n",
+				  bss_conf->aid, common->curbssid);
+			common->curaid = bss_conf->aid;
+			ath5k_hw_set_bssid(ah);
+			/* Once ANI is available you would start it here */
+		}
+	}
+
+	if (changes & BSS_CHANGED_BEACON) {
+		spin_lock_irqsave(&sc->block, flags);
+		ath5k_beacon_update(hw, vif);
+		spin_unlock_irqrestore(&sc->block, flags);
+	}
+
+	if (changes & BSS_CHANGED_BEACON_ENABLED)
+		sc->enable_beacon = bss_conf->enable_beacon;
+
+	if (changes & (BSS_CHANGED_BEACON | BSS_CHANGED_BEACON_ENABLED |
+		       BSS_CHANGED_BEACON_INT))
+		ath5k_beacon_config(sc);
+
+	mutex_unlock(&sc->lock);
+}
+
+
+static u64
+ath5k_prepare_multicast(struct ieee80211_hw *hw,
+			struct netdev_hw_addr_list *mc_list)
+{
+	u32 mfilt[2], val;
+	u8 pos;
+	struct netdev_hw_addr *ha;
+
+	mfilt[0] = 0;
+	mfilt[1] = 1;
+
+	netdev_hw_addr_list_for_each(ha, mc_list) {
+		/* calculate XOR of eight 6-bit values */
+		val = get_unaligned_le32(ha->addr + 0);
+		pos = (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val;
+		val = get_unaligned_le32(ha->addr + 3);
+		pos ^= (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val;
+		pos &= 0x3f;
+		mfilt[pos / 32] |= (1 << (pos % 32));
+		/* XXX: we might be able to just do this instead,
+		* but not sure, needs testing, if we do use this we'd
+		* neet to inform below to not reset the mcast */
+		/* ath5k_hw_set_mcast_filterindex(ah,
+		 *      ha->addr[5]); */
+	}
+
+	return ((u64)(mfilt[1]) << 32) | mfilt[0];
+}
+
+
+/*
+ * o always accept unicast, broadcast, and multicast traffic
+ * o multicast traffic for all BSSIDs will be enabled if mac80211
+ *   says it should be
+ * o maintain current state of phy ofdm or phy cck error reception.
+ *   If the hardware detects any of these type of errors then
+ *   ath5k_hw_get_rx_filter() will pass to us the respective
+ *   hardware filters to be able to receive these type of frames.
+ * o probe request frames are accepted only when operating in
+ *   hostap, adhoc, or monitor modes
+ * o enable promiscuous mode according to the interface state
+ * o accept beacons:
+ *   - when operating in adhoc mode so the 802.11 layer creates
+ *     node table entries for peers,
+ *   - when operating in station mode for collecting rssi data when
+ *     the station is otherwise quiet, or
+ *   - when scanning
+ */
+static void
+ath5k_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags,
+		       unsigned int *new_flags, u64 multicast)
+{
+#define SUPPORTED_FIF_FLAGS \
+	(FIF_PROMISC_IN_BSS |  FIF_ALLMULTI | FIF_FCSFAIL | \
+	FIF_PLCPFAIL | FIF_CONTROL | FIF_OTHER_BSS | \
+	FIF_BCN_PRBRESP_PROMISC)
+
+	struct ath5k_softc *sc = hw->priv;
+	struct ath5k_hw *ah = sc->ah;
+	u32 mfilt[2], rfilt;
+
+	mutex_lock(&sc->lock);
+
+	mfilt[0] = multicast;
+	mfilt[1] = multicast >> 32;
+
+	/* Only deal with supported flags */
+	changed_flags &= SUPPORTED_FIF_FLAGS;
+	*new_flags &= SUPPORTED_FIF_FLAGS;
+
+	/* If HW detects any phy or radar errors, leave those filters on.
+	 * Also, always enable Unicast, Broadcasts and Multicast
+	 * XXX: move unicast, bssid broadcasts and multicast to mac80211 */
+	rfilt = (ath5k_hw_get_rx_filter(ah) & (AR5K_RX_FILTER_PHYERR)) |
+		(AR5K_RX_FILTER_UCAST | AR5K_RX_FILTER_BCAST |
+		AR5K_RX_FILTER_MCAST);
+
+	if (changed_flags & (FIF_PROMISC_IN_BSS | FIF_OTHER_BSS)) {
+		if (*new_flags & FIF_PROMISC_IN_BSS)
+			__set_bit(ATH_STAT_PROMISC, sc->status);
+		else
+			__clear_bit(ATH_STAT_PROMISC, sc->status);
+	}
+
+	if (test_bit(ATH_STAT_PROMISC, sc->status))
+		rfilt |= AR5K_RX_FILTER_PROM;
+
+	/* Note, AR5K_RX_FILTER_MCAST is already enabled */
+	if (*new_flags & FIF_ALLMULTI) {
+		mfilt[0] =  ~0;
+		mfilt[1] =  ~0;
+	}
+
+	/* This is the best we can do */
+	if (*new_flags & (FIF_FCSFAIL | FIF_PLCPFAIL))
+		rfilt |= AR5K_RX_FILTER_PHYERR;
+
+	/* FIF_BCN_PRBRESP_PROMISC really means to enable beacons
+	* and probes for any BSSID */
+	if ((*new_flags & FIF_BCN_PRBRESP_PROMISC) || (sc->nvifs > 1))
+		rfilt |= AR5K_RX_FILTER_BEACON;
+
+	/* FIF_CONTROL doc says that if FIF_PROMISC_IN_BSS is not
+	 * set we should only pass on control frames for this
+	 * station. This needs testing. I believe right now this
+	 * enables *all* control frames, which is OK.. but
+	 * but we should see if we can improve on granularity */
+	if (*new_flags & FIF_CONTROL)
+		rfilt |= AR5K_RX_FILTER_CONTROL;
+
+	/* Additional settings per mode -- this is per ath5k */
+
+	/* XXX move these to mac80211, and add a beacon IFF flag to mac80211 */
+
+	switch (sc->opmode) {
+	case NL80211_IFTYPE_MESH_POINT:
+		rfilt |= AR5K_RX_FILTER_CONTROL |
+			 AR5K_RX_FILTER_BEACON |
+			 AR5K_RX_FILTER_PROBEREQ |
+			 AR5K_RX_FILTER_PROM;
+		break;
+	case NL80211_IFTYPE_AP:
+	case NL80211_IFTYPE_ADHOC:
+		rfilt |= AR5K_RX_FILTER_PROBEREQ |
+			 AR5K_RX_FILTER_BEACON;
+		break;
+	case NL80211_IFTYPE_STATION:
+		if (sc->assoc)
+			rfilt |= AR5K_RX_FILTER_BEACON;
+	default:
+		break;
+	}
+
+	/* Set filters */
+	ath5k_hw_set_rx_filter(ah, rfilt);
+
+	/* Set multicast bits */
+	ath5k_hw_set_mcast_filter(ah, mfilt[0], mfilt[1]);
+	/* Set the cached hw filter flags, this will later actually
+	 * be set in HW */
+	sc->filter_flags = rfilt;
+
+	mutex_unlock(&sc->lock);
+}
+
+
+static int
+ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
+	      struct ieee80211_vif *vif, struct ieee80211_sta *sta,
+	      struct ieee80211_key_conf *key)
+{
+	struct ath5k_softc *sc = hw->priv;
+	struct ath5k_hw *ah = sc->ah;
+	struct ath_common *common = ath5k_hw_common(ah);
+	int ret = 0;
+
+	if (ath5k_modparam_nohwcrypt)
+		return -EOPNOTSUPP;
+
+	switch (key->cipher) {
+	case WLAN_CIPHER_SUITE_WEP40:
+	case WLAN_CIPHER_SUITE_WEP104:
+	case WLAN_CIPHER_SUITE_TKIP:
+		break;
+	case WLAN_CIPHER_SUITE_CCMP:
+		if (common->crypt_caps & ATH_CRYPT_CAP_CIPHER_AESCCM)
+			break;
+		return -EOPNOTSUPP;
+	default:
+		WARN_ON(1);
+		return -EINVAL;
+	}
+
+	mutex_lock(&sc->lock);
+
+	switch (cmd) {
+	case SET_KEY:
+		ret = ath_key_config(common, vif, sta, key);
+		if (ret >= 0) {
+			key->hw_key_idx = ret;
+			/* push IV and Michael MIC generation to stack */
+			key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
+			if (key->cipher == WLAN_CIPHER_SUITE_TKIP)
+				key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
+			if (key->cipher == WLAN_CIPHER_SUITE_CCMP)
+				key->flags |= IEEE80211_KEY_FLAG_SW_MGMT;
+			ret = 0;
+		}
+		break;
+	case DISABLE_KEY:
+		ath_key_delete(common, key);
+		break;
+	default:
+		ret = -EINVAL;
+	}
+
+	mmiowb();
+	mutex_unlock(&sc->lock);
+	return ret;
+}
+
+
+static void
+ath5k_sw_scan_start(struct ieee80211_hw *hw)
+{
+	struct ath5k_softc *sc = hw->priv;
+	if (!sc->assoc)
+		ath5k_hw_set_ledstate(sc->ah, AR5K_LED_SCAN);
+}
+
+
+static void
+ath5k_sw_scan_complete(struct ieee80211_hw *hw)
+{
+	struct ath5k_softc *sc = hw->priv;
+	ath5k_hw_set_ledstate(sc->ah, sc->assoc ?
+		AR5K_LED_ASSOC : AR5K_LED_INIT);
+}
+
+
+static int
+ath5k_get_stats(struct ieee80211_hw *hw,
+		struct ieee80211_low_level_stats *stats)
+{
+	struct ath5k_softc *sc = hw->priv;
+
+	/* Force update */
+	ath5k_hw_update_mib_counters(sc->ah);
+
+	stats->dot11ACKFailureCount = sc->stats.ack_fail;
+	stats->dot11RTSFailureCount = sc->stats.rts_fail;
+	stats->dot11RTSSuccessCount = sc->stats.rts_ok;
+	stats->dot11FCSErrorCount = sc->stats.fcs_error;
+
+	return 0;
+}
+
+
+static int
+ath5k_conf_tx(struct ieee80211_hw *hw, u16 queue,
+	      const struct ieee80211_tx_queue_params *params)
+{
+	struct ath5k_softc *sc = hw->priv;
+	struct ath5k_hw *ah = sc->ah;
+	struct ath5k_txq_info qi;
+	int ret = 0;
+
+	if (queue >= ah->ah_capabilities.cap_queues.q_tx_num)
+		return 0;
+
+	mutex_lock(&sc->lock);
+
+	ath5k_hw_get_tx_queueprops(ah, queue, &qi);
+
+	qi.tqi_aifs = params->aifs;
+	qi.tqi_cw_min = params->cw_min;
+	qi.tqi_cw_max = params->cw_max;
+	qi.tqi_burst_time = params->txop;
+
+	ATH5K_DBG(sc, ATH5K_DEBUG_ANY,
+		  "Configure tx [queue %d],  "
+		  "aifs: %d, cw_min: %d, cw_max: %d, txop: %d\n",
+		  queue, params->aifs, params->cw_min,
+		  params->cw_max, params->txop);
+
+	if (ath5k_hw_set_tx_queueprops(ah, queue, &qi)) {
+		ATH5K_ERR(sc,
+			  "Unable to update hardware queue %u!\n", queue);
+		ret = -EIO;
+	} else
+		ath5k_hw_reset_tx_queue(ah, queue);
+
+	mutex_unlock(&sc->lock);
+
+	return ret;
+}
+
+
+static u64
+ath5k_get_tsf(struct ieee80211_hw *hw)
+{
+	struct ath5k_softc *sc = hw->priv;
+
+	return ath5k_hw_get_tsf64(sc->ah);
+}
+
+
+static void
+ath5k_set_tsf(struct ieee80211_hw *hw, u64 tsf)
+{
+	struct ath5k_softc *sc = hw->priv;
+
+	ath5k_hw_set_tsf64(sc->ah, tsf);
+}
+
+
+static void
+ath5k_reset_tsf(struct ieee80211_hw *hw)
+{
+	struct ath5k_softc *sc = hw->priv;
+
+	/*
+	 * in IBSS mode we need to update the beacon timers too.
+	 * this will also reset the TSF if we call it with 0
+	 */
+	if (sc->opmode == NL80211_IFTYPE_ADHOC)
+		ath5k_beacon_update_timers(sc, 0);
+	else
+		ath5k_hw_reset_tsf(sc->ah);
+}
+
+
+static int
+ath5k_get_survey(struct ieee80211_hw *hw, int idx, struct survey_info *survey)
+{
+	struct ath5k_softc *sc = hw->priv;
+	struct ieee80211_conf *conf = &hw->conf;
+	struct ath_common *common = ath5k_hw_common(sc->ah);
+	struct ath_cycle_counters *cc = &common->cc_survey;
+	unsigned int div = common->clockrate * 1000;
+
+	if (idx != 0)
+		return -ENOENT;
+
+	spin_lock_bh(&common->cc_lock);
+	ath_hw_cycle_counters_update(common);
+	if (cc->cycles > 0) {
+		sc->survey.channel_time += cc->cycles / div;
+		sc->survey.channel_time_busy += cc->rx_busy / div;
+		sc->survey.channel_time_rx += cc->rx_frame / div;
+		sc->survey.channel_time_tx += cc->tx_frame / div;
+	}
+	memset(cc, 0, sizeof(*cc));
+	spin_unlock_bh(&common->cc_lock);
+
+	memcpy(survey, &sc->survey, sizeof(*survey));
+
+	survey->channel = conf->channel;
+	survey->noise = sc->ah->ah_noise_floor;
+	survey->filled = SURVEY_INFO_NOISE_DBM |
+			SURVEY_INFO_CHANNEL_TIME |
+			SURVEY_INFO_CHANNEL_TIME_BUSY |
+			SURVEY_INFO_CHANNEL_TIME_RX |
+			SURVEY_INFO_CHANNEL_TIME_TX;
+
+	return 0;
+}
+
+
+/**
+ * ath5k_set_coverage_class - Set IEEE 802.11 coverage class
+ *
+ * @hw: struct ieee80211_hw pointer
+ * @coverage_class: IEEE 802.11 coverage class number
+ *
+ * Mac80211 callback. Sets slot time, ACK timeout and CTS timeout for given
+ * coverage class. The values are persistent, they are restored after device
+ * reset.
+ */
+static void
+ath5k_set_coverage_class(struct ieee80211_hw *hw, u8 coverage_class)
+{
+	struct ath5k_softc *sc = hw->priv;
+
+	mutex_lock(&sc->lock);
+	ath5k_hw_set_coverage_class(sc->ah, coverage_class);
+	mutex_unlock(&sc->lock);
+}
+
+
+static int
+ath5k_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant)
+{
+	struct ath5k_softc *sc = hw->priv;
+
+	if (tx_ant == 1 && rx_ant == 1)
+		ath5k_hw_set_antenna_mode(sc->ah, AR5K_ANTMODE_FIXED_A);
+	else if (tx_ant == 2 && rx_ant == 2)
+		ath5k_hw_set_antenna_mode(sc->ah, AR5K_ANTMODE_FIXED_B);
+	else if ((tx_ant & 3) == 3 && (rx_ant & 3) == 3)
+		ath5k_hw_set_antenna_mode(sc->ah, AR5K_ANTMODE_DEFAULT);
+	else
+		return -EINVAL;
+	return 0;
+}
+
+
+static int
+ath5k_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant)
+{
+	struct ath5k_softc *sc = hw->priv;
+
+	switch (sc->ah->ah_ant_mode) {
+	case AR5K_ANTMODE_FIXED_A:
+		*tx_ant = 1; *rx_ant = 1; break;
+	case AR5K_ANTMODE_FIXED_B:
+		*tx_ant = 2; *rx_ant = 2; break;
+	case AR5K_ANTMODE_DEFAULT:
+		*tx_ant = 3; *rx_ant = 3; break;
+	}
+	return 0;
+}
+
+
+const struct ieee80211_ops ath5k_hw_ops = {
+	.tx			= ath5k_tx,
+	.start			= ath5k_start,
+	.stop			= ath5k_stop,
+	.add_interface		= ath5k_add_interface,
+	/* .change_interface	= not implemented */
+	.remove_interface	= ath5k_remove_interface,
+	.config			= ath5k_config,
+	.bss_info_changed	= ath5k_bss_info_changed,
+	.prepare_multicast	= ath5k_prepare_multicast,
+	.configure_filter	= ath5k_configure_filter,
+	/* .set_tim		= not implemented */
+	.set_key		= ath5k_set_key,
+	/* .update_tkip_key	= not implemented */
+	/* .hw_scan		= not implemented */
+	.sw_scan_start		= ath5k_sw_scan_start,
+	.sw_scan_complete	= ath5k_sw_scan_complete,
+	.get_stats		= ath5k_get_stats,
+	/* .get_tkip_seq	= not implemented */
+	/* .set_frag_threshold	= not implemented */
+	/* .set_rts_threshold	= not implemented */
+	/* .sta_add		= not implemented */
+	/* .sta_remove		= not implemented */
+	/* .sta_notify		= not implemented */
+	.conf_tx		= ath5k_conf_tx,
+	.get_tsf		= ath5k_get_tsf,
+	.set_tsf		= ath5k_set_tsf,
+	.reset_tsf		= ath5k_reset_tsf,
+	/* .tx_last_beacon	= not implemented */
+	/* .ampdu_action	= not needed */
+	.get_survey		= ath5k_get_survey,
+	.set_coverage_class	= ath5k_set_coverage_class,
+	/* .rfkill_poll		= not implemented */
+	/* .flush		= not implemented */
+	/* .channel_switch	= not implemented */
+	/* .napi_poll		= not implemented */
+	.set_antenna		= ath5k_set_antenna,
+	.get_antenna		= ath5k_get_antenna,
+};
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath5k/Makefile linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath5k/Makefile
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath5k/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath5k/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -14,5 +14,8 @@ ath5k-y				+= led.o
 ath5k-y				+= rfkill.o
 ath5k-y				+= ani.o
 ath5k-y				+= sysfs.o
+ath5k-y				+= mac80211-ops.o
 ath5k-$(CONFIG_ATH5K_DEBUG)	+= debug.o
+ath5k-$(CONFIG_ATH5K_AHB)	+= ahb.o
+ath5k-$(CONFIG_ATH5K_PCI)	+= pci.o
 obj-$(CONFIG_ATH5K)		+= ath5k.o
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath5k/pci.c linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath5k/pci.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath5k/pci.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath5k/pci.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,327 @@
+/*
+ * Copyright (c) 2008-2009 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/nl80211.h>
+#include <linux/pci.h>
+#include <linux/pci-aspm.h>
+#include "../ath.h"
+#include "ath5k.h"
+#include "debug.h"
+#include "base.h"
+#include "reg.h"
+
+/* Known PCI ids */
+static DEFINE_PCI_DEVICE_TABLE(ath5k_pci_id_table) = {
+	{ PCI_VDEVICE(ATHEROS, 0x0207) }, /* 5210 early */
+	{ PCI_VDEVICE(ATHEROS, 0x0007) }, /* 5210 */
+	{ PCI_VDEVICE(ATHEROS, 0x0011) }, /* 5311 - this is on AHB bus !*/
+	{ PCI_VDEVICE(ATHEROS, 0x0012) }, /* 5211 */
+	{ PCI_VDEVICE(ATHEROS, 0x0013) }, /* 5212 */
+	{ PCI_VDEVICE(3COM_2,  0x0013) }, /* 3com 5212 */
+	{ PCI_VDEVICE(3COM,    0x0013) }, /* 3com 3CRDAG675 5212 */
+	{ PCI_VDEVICE(ATHEROS, 0x1014) }, /* IBM minipci 5212 */
+	{ PCI_VDEVICE(ATHEROS, 0x0014) }, /* 5212 combatible */
+	{ PCI_VDEVICE(ATHEROS, 0x0015) }, /* 5212 combatible */
+	{ PCI_VDEVICE(ATHEROS, 0x0016) }, /* 5212 combatible */
+	{ PCI_VDEVICE(ATHEROS, 0x0017) }, /* 5212 combatible */
+	{ PCI_VDEVICE(ATHEROS, 0x0018) }, /* 5212 combatible */
+	{ PCI_VDEVICE(ATHEROS, 0x0019) }, /* 5212 combatible */
+	{ PCI_VDEVICE(ATHEROS, 0x001a) }, /* 2413 Griffin-lite */
+	{ PCI_VDEVICE(ATHEROS, 0x001b) }, /* 5413 Eagle */
+	{ PCI_VDEVICE(ATHEROS, 0x001c) }, /* PCI-E cards */
+	{ PCI_VDEVICE(ATHEROS, 0x001d) }, /* 2417 Nala */
+	{ 0 }
+};
+MODULE_DEVICE_TABLE(pci, ath5k_pci_id_table);
+
+/* return bus cachesize in 4B word units */
+static void ath5k_pci_read_cachesize(struct ath_common *common, int *csz)
+{
+	struct ath5k_softc *sc = (struct ath5k_softc *) common->priv;
+	u8 u8tmp;
+
+	pci_read_config_byte(sc->pdev, PCI_CACHE_LINE_SIZE, &u8tmp);
+	*csz = (int)u8tmp;
+
+	/*
+	 * This check was put in to avoid "unplesant" consequences if
+	 * the bootrom has not fully initialized all PCI devices.
+	 * Sometimes the cache line size register is not set
+	 */
+
+	if (*csz == 0)
+		*csz = L1_CACHE_BYTES >> 2;   /* Use the default size */
+}
+
+/*
+ * Read from eeprom
+ */
+bool ath5k_pci_eeprom_read(struct ath_common *common, u32 offset, u16 *data)
+{
+	struct ath5k_hw *ah = (struct ath5k_hw *) common->ah;
+	u32 status, timeout;
+
+	/*
+	 * Initialize EEPROM access
+	 */
+	if (ah->ah_version == AR5K_AR5210) {
+		AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, AR5K_PCICFG_EEAE);
+		(void)ath5k_hw_reg_read(ah, AR5K_EEPROM_BASE + (4 * offset));
+	} else {
+		ath5k_hw_reg_write(ah, offset, AR5K_EEPROM_BASE);
+		AR5K_REG_ENABLE_BITS(ah, AR5K_EEPROM_CMD,
+				AR5K_EEPROM_CMD_READ);
+	}
+
+	for (timeout = AR5K_TUNE_REGISTER_TIMEOUT; timeout > 0; timeout--) {
+		status = ath5k_hw_reg_read(ah, AR5K_EEPROM_STATUS);
+		if (status & AR5K_EEPROM_STAT_RDDONE) {
+			if (status & AR5K_EEPROM_STAT_RDERR)
+				return -EIO;
+			*data = (u16)(ath5k_hw_reg_read(ah, AR5K_EEPROM_DATA) &
+					0xffff);
+			return 0;
+		}
+		udelay(15);
+	}
+
+	return -ETIMEDOUT;
+}
+
+int ath5k_hw_read_srev(struct ath5k_hw *ah)
+{
+	ah->ah_mac_srev = ath5k_hw_reg_read(ah, AR5K_SREV);
+	return 0;
+}
+
+/* Common ath_bus_opts structure */
+static const struct ath_bus_ops ath_pci_bus_ops = {
+	.ath_bus_type = ATH_PCI,
+	.read_cachesize = ath5k_pci_read_cachesize,
+	.eeprom_read = ath5k_pci_eeprom_read,
+};
+
+/********************\
+* PCI Initialization *
+\********************/
+
+static int __devinit
+ath5k_pci_probe(struct pci_dev *pdev,
+		const struct pci_device_id *id)
+{
+	void __iomem *mem;
+	struct ath5k_softc *sc;
+	struct ieee80211_hw *hw;
+	int ret;
+	u8 csz;
+
+	/*
+	 * L0s needs to be disabled on all ath5k cards.
+	 *
+	 * For distributions shipping with CONFIG_PCIEASPM (this will be enabled
+	 * by default in the future in 2.6.36) this will also mean both L1 and
+	 * L0s will be disabled when a pre 1.1 PCIe device is detected. We do
+	 * know L1 works correctly even for all ath5k pre 1.1 PCIe devices
+	 * though but cannot currently undue the effect of a blacklist, for
+	 * details you can read pcie_aspm_sanity_check() and see how it adjusts
+	 * the device link capability.
+	 *
+	 * It may be possible in the future to implement some PCI API to allow
+	 * drivers to override blacklists for pre 1.1 PCIe but for now it is
+	 * best to accept that both L0s and L1 will be disabled completely for
+	 * distributions shipping with CONFIG_PCIEASPM rather than having this
+	 * issue present. Motivation for adding this new API will be to help
+	 * with power consumption for some of these devices.
+	 */
+	pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S);
+
+	ret = pci_enable_device(pdev);
+	if (ret) {
+		dev_err(&pdev->dev, "can't enable device\n");
+		goto err;
+	}
+
+	/* XXX 32-bit addressing only */
+	ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
+	if (ret) {
+		dev_err(&pdev->dev, "32-bit DMA not available\n");
+		goto err_dis;
+	}
+
+	/*
+	 * Cache line size is used to size and align various
+	 * structures used to communicate with the hardware.
+	 */
+	pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &csz);
+	if (csz == 0) {
+		/*
+		 * Linux 2.4.18 (at least) writes the cache line size
+		 * register as a 16-bit wide register which is wrong.
+		 * We must have this setup properly for rx buffer
+		 * DMA to work so force a reasonable value here if it
+		 * comes up zero.
+		 */
+		csz = L1_CACHE_BYTES >> 2;
+		pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, csz);
+	}
+	/*
+	 * The default setting of latency timer yields poor results,
+	 * set it to the value used by other systems.  It may be worth
+	 * tweaking this setting more.
+	 */
+	pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0xa8);
+
+	/* Enable bus mastering */
+	pci_set_master(pdev);
+
+	/*
+	 * Disable the RETRY_TIMEOUT register (0x41) to keep
+	 * PCI Tx retries from interfering with C3 CPU state.
+	 */
+	pci_write_config_byte(pdev, 0x41, 0);
+
+	ret = pci_request_region(pdev, 0, "ath5k");
+	if (ret) {
+		dev_err(&pdev->dev, "cannot reserve PCI memory region\n");
+		goto err_dis;
+	}
+
+	mem = pci_iomap(pdev, 0, 0);
+	if (!mem) {
+		dev_err(&pdev->dev, "cannot remap PCI memory region\n") ;
+		ret = -EIO;
+		goto err_reg;
+	}
+
+	/*
+	 * Allocate hw (mac80211 main struct)
+	 * and hw->priv (driver private data)
+	 */
+	hw = ieee80211_alloc_hw(sizeof(*sc), &ath5k_hw_ops);
+	if (hw == NULL) {
+		dev_err(&pdev->dev, "cannot allocate ieee80211_hw\n");
+		ret = -ENOMEM;
+		goto err_map;
+	}
+
+	dev_info(&pdev->dev, "registered as '%s'\n", wiphy_name(hw->wiphy));
+
+	sc = hw->priv;
+	sc->hw = hw;
+	sc->pdev = pdev;
+	sc->dev = &pdev->dev;
+	sc->irq = pdev->irq;
+	sc->devid = id->device;
+	sc->iobase = mem; /* So we can unmap it on detach */
+
+	/* Initialize */
+	ret = ath5k_init_softc(sc, &ath_pci_bus_ops);
+	if (ret)
+		goto err_free;
+
+	/* Set private data */
+	pci_set_drvdata(pdev, hw);
+
+	return 0;
+err_free:
+	ieee80211_free_hw(hw);
+err_map:
+	pci_iounmap(pdev, mem);
+err_reg:
+	pci_release_region(pdev, 0);
+err_dis:
+	pci_disable_device(pdev);
+err:
+	return ret;
+}
+
+static void __devexit
+ath5k_pci_remove(struct pci_dev *pdev)
+{
+	struct ieee80211_hw *hw = pci_get_drvdata(pdev);
+	struct ath5k_softc *sc = hw->priv;
+
+	ath5k_deinit_softc(sc);
+	pci_iounmap(pdev, sc->iobase);
+	pci_release_region(pdev, 0);
+	pci_disable_device(pdev);
+	ieee80211_free_hw(hw);
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int ath5k_pci_suspend(struct device *dev)
+{
+	struct ath5k_softc *sc = pci_get_drvdata(to_pci_dev(dev));
+
+	ath5k_led_off(sc);
+	return 0;
+}
+
+static int ath5k_pci_resume(struct device *dev)
+{
+	struct pci_dev *pdev = to_pci_dev(dev);
+	struct ath5k_softc *sc = pci_get_drvdata(pdev);
+
+	/*
+	 * Suspend/Resume resets the PCI configuration space, so we have to
+	 * re-disable the RETRY_TIMEOUT register (0x41) to keep
+	 * PCI Tx retries from interfering with C3 CPU state
+	 */
+	pci_write_config_byte(pdev, 0x41, 0);
+
+	ath5k_led_enable(sc);
+	return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(ath5k_pm_ops, ath5k_pci_suspend, ath5k_pci_resume);
+#define ATH5K_PM_OPS	(&ath5k_pm_ops)
+#else
+#define ATH5K_PM_OPS	NULL
+#endif /* CONFIG_PM_SLEEP */
+
+static struct pci_driver ath5k_pci_driver = {
+	.name		= KBUILD_MODNAME,
+	.id_table	= ath5k_pci_id_table,
+	.probe		= ath5k_pci_probe,
+	.remove		= __devexit_p(ath5k_pci_remove),
+	.driver.pm	= ATH5K_PM_OPS,
+};
+
+/*
+ * Module init/exit functions
+ */
+static int __init
+init_ath5k_pci(void)
+{
+	int ret;
+
+	ret = pci_register_driver(&ath5k_pci_driver);
+	if (ret) {
+		printk(KERN_ERR "ath5k_pci: can't register pci driver\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static void __exit
+exit_ath5k_pci(void)
+{
+	pci_unregister_driver(&ath5k_pci_driver);
+}
+
+module_init(init_ath5k_pci);
+module_exit(exit_ath5k_pci);
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath5k/pcu.c linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath5k/pcu.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath5k/pcu.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath5k/pcu.c	2011-03-14 21:20:32.000000000 -0400
@@ -31,87 +31,163 @@
 #include "debug.h"
 #include "base.h"
 
+/*
+ * AR5212+ can use higher rates for ack transmition
+ * based on current tx rate instead of the base rate.
+ * It does this to better utilize channel usage.
+ * This is a mapping between G rates (that cover both
+ * CCK and OFDM) and ack rates that we use when setting
+ * rate -> duration table. This mapping is hw-based so
+ * don't change anything.
+ *
+ * To enable this functionality we must set
+ * ah->ah_ack_bitrate_high to true else base rate is
+ * used (1Mb for CCK, 6Mb for OFDM).
+ */
+static const unsigned int ack_rates_high[] =
+/* Tx	-> ACK	*/
+/* 1Mb	-> 1Mb	*/	{ 0,
+/* 2MB	-> 2Mb	*/	1,
+/* 5.5Mb -> 2Mb	*/	1,
+/* 11Mb	-> 2Mb	*/	1,
+/* 6Mb	-> 6Mb	*/	4,
+/* 9Mb	-> 6Mb	*/	4,
+/* 12Mb	-> 12Mb	*/	6,
+/* 18Mb	-> 12Mb	*/	6,
+/* 24Mb	-> 24Mb	*/	8,
+/* 36Mb	-> 24Mb	*/	8,
+/* 48Mb	-> 24Mb	*/	8,
+/* 54Mb	-> 24Mb	*/	8 };
+
 /*******************\
-* Generic functions *
+* Helper functions *
 \*******************/
 
 /**
- * ath5k_hw_set_opmode - Set PCU operating mode
+ * ath5k_hw_get_frame_duration - Get tx time of a frame
  *
  * @ah: The &struct ath5k_hw
- * @op_mode: &enum nl80211_iftype operating mode
+ * @len: Frame's length in bytes
+ * @rate: The @struct ieee80211_rate
  *
- * Initialize PCU for the various operating modes (AP/STA etc)
+ * Calculate tx duration of a frame given it's rate and length
+ * It extends ieee80211_generic_frame_duration for non standard
+ * bwmodes.
  */
-int ath5k_hw_set_opmode(struct ath5k_hw *ah, enum nl80211_iftype op_mode)
+int ath5k_hw_get_frame_duration(struct ath5k_hw *ah,
+		int len, struct ieee80211_rate *rate)
 {
-	struct ath_common *common = ath5k_hw_common(ah);
-	u32 pcu_reg, beacon_reg, low_id, high_id;
-
-	ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_MODE, "mode %d\n", op_mode);
+	struct ath5k_softc *sc = ah->ah_sc;
+	int sifs, preamble, plcp_bits, sym_time;
+	int bitrate, bits, symbols, symbol_bits;
+	int dur;
 
-	/* Preserve rest settings */
-	pcu_reg = ath5k_hw_reg_read(ah, AR5K_STA_ID1) & 0xffff0000;
-	pcu_reg &= ~(AR5K_STA_ID1_ADHOC | AR5K_STA_ID1_AP
-			| AR5K_STA_ID1_KEYSRCH_MODE
-			| (ah->ah_version == AR5K_AR5210 ?
-			(AR5K_STA_ID1_PWR_SV | AR5K_STA_ID1_NO_PSPOLL) : 0));
+	/* Fallback */
+	if (!ah->ah_bwmode) {
+		dur = ieee80211_generic_frame_duration(sc->hw,
+						NULL, len, rate);
+		return le16_to_cpu(dur);
+	}
 
-	beacon_reg = 0;
+	bitrate = rate->bitrate;
+	preamble = AR5K_INIT_OFDM_PREAMPLE_TIME;
+	plcp_bits = AR5K_INIT_OFDM_PLCP_BITS;
+	sym_time = AR5K_INIT_OFDM_SYMBOL_TIME;
 
-	switch (op_mode) {
-	case NL80211_IFTYPE_ADHOC:
-		pcu_reg |= AR5K_STA_ID1_ADHOC | AR5K_STA_ID1_KEYSRCH_MODE;
-		beacon_reg |= AR5K_BCR_ADHOC;
-		if (ah->ah_version == AR5K_AR5210)
-			pcu_reg |= AR5K_STA_ID1_NO_PSPOLL;
-		else
-			AR5K_REG_ENABLE_BITS(ah, AR5K_CFG, AR5K_CFG_IBSS);
+	switch (ah->ah_bwmode) {
+	case AR5K_BWMODE_40MHZ:
+		sifs = AR5K_INIT_SIFS_TURBO;
+		preamble = AR5K_INIT_OFDM_PREAMBLE_TIME_MIN;
 		break;
-
-	case NL80211_IFTYPE_AP:
-	case NL80211_IFTYPE_MESH_POINT:
-		pcu_reg |= AR5K_STA_ID1_AP | AR5K_STA_ID1_KEYSRCH_MODE;
-		beacon_reg |= AR5K_BCR_AP;
-		if (ah->ah_version == AR5K_AR5210)
-			pcu_reg |= AR5K_STA_ID1_NO_PSPOLL;
-		else
-			AR5K_REG_DISABLE_BITS(ah, AR5K_CFG, AR5K_CFG_IBSS);
+	case AR5K_BWMODE_10MHZ:
+		sifs = AR5K_INIT_SIFS_HALF_RATE;
+		preamble *= 2;
+		sym_time *= 2;
 		break;
-
-	case NL80211_IFTYPE_STATION:
-		pcu_reg |= AR5K_STA_ID1_KEYSRCH_MODE
-			| (ah->ah_version == AR5K_AR5210 ?
-				AR5K_STA_ID1_PWR_SV : 0);
-	case NL80211_IFTYPE_MONITOR:
-		pcu_reg |= AR5K_STA_ID1_KEYSRCH_MODE
-			| (ah->ah_version == AR5K_AR5210 ?
-				AR5K_STA_ID1_NO_PSPOLL : 0);
+	case AR5K_BWMODE_5MHZ:
+		sifs = AR5K_INIT_SIFS_QUARTER_RATE;
+		preamble *= 4;
+		sym_time *= 4;
+		break;
+	default:
+		sifs = AR5K_INIT_SIFS_DEFAULT_BG;
 		break;
+	}
+
+	bits = plcp_bits + (len << 3);
+	/* Bit rate is in 100Kbits */
+	symbol_bits = bitrate * sym_time;
+	symbols = DIV_ROUND_UP(bits * 10, symbol_bits);
+
+	dur = sifs + preamble + (sym_time * symbols);
+
+	return dur;
+}
 
+/**
+ * ath5k_hw_get_default_slottime - Get the default slot time for current mode
+ *
+ * @ah: The &struct ath5k_hw
+ */
+unsigned int ath5k_hw_get_default_slottime(struct ath5k_hw *ah)
+{
+	struct ieee80211_channel *channel = ah->ah_current_channel;
+	unsigned int slot_time;
+
+	switch (ah->ah_bwmode) {
+	case AR5K_BWMODE_40MHZ:
+		slot_time = AR5K_INIT_SLOT_TIME_TURBO;
+		break;
+	case AR5K_BWMODE_10MHZ:
+		slot_time = AR5K_INIT_SLOT_TIME_HALF_RATE;
+		break;
+	case AR5K_BWMODE_5MHZ:
+		slot_time = AR5K_INIT_SLOT_TIME_QUARTER_RATE;
+		break;
+	case AR5K_BWMODE_DEFAULT:
+		slot_time = AR5K_INIT_SLOT_TIME_DEFAULT;
 	default:
-		return -EINVAL;
+		if (channel->hw_value & CHANNEL_CCK)
+			slot_time = AR5K_INIT_SLOT_TIME_B;
+		break;
 	}
 
-	/*
-	 * Set PCU registers
-	 */
-	low_id = get_unaligned_le32(common->macaddr);
-	high_id = get_unaligned_le16(common->macaddr + 4);
-	ath5k_hw_reg_write(ah, low_id, AR5K_STA_ID0);
-	ath5k_hw_reg_write(ah, pcu_reg | high_id, AR5K_STA_ID1);
+	return slot_time;
+}
 
-	/*
-	 * Set Beacon Control Register on 5210
-	 */
-	if (ah->ah_version == AR5K_AR5210)
-		ath5k_hw_reg_write(ah, beacon_reg, AR5K_BCR);
+/**
+ * ath5k_hw_get_default_sifs - Get the default SIFS for current mode
+ *
+ * @ah: The &struct ath5k_hw
+ */
+unsigned int ath5k_hw_get_default_sifs(struct ath5k_hw *ah)
+{
+	struct ieee80211_channel *channel = ah->ah_current_channel;
+	unsigned int sifs;
 
-	return 0;
+	switch (ah->ah_bwmode) {
+	case AR5K_BWMODE_40MHZ:
+		sifs = AR5K_INIT_SIFS_TURBO;
+		break;
+	case AR5K_BWMODE_10MHZ:
+		sifs = AR5K_INIT_SIFS_HALF_RATE;
+		break;
+	case AR5K_BWMODE_5MHZ:
+		sifs = AR5K_INIT_SIFS_QUARTER_RATE;
+		break;
+	case AR5K_BWMODE_DEFAULT:
+		sifs = AR5K_INIT_SIFS_DEFAULT_BG;
+	default:
+		if (channel->hw_value & CHANNEL_5GHZ)
+			sifs = AR5K_INIT_SIFS_DEFAULT_A;
+		break;
+	}
+
+	return sifs;
 }
 
 /**
- * ath5k_hw_update - Update MIB counters (mac layer statistics)
+ * ath5k_hw_update_mib_counters - Update MIB counters (mac layer statistics)
  *
  * @ah: The &struct ath5k_hw
  *
@@ -133,35 +209,85 @@ void ath5k_hw_update_mib_counters(struct
 	stats->beacons += ath5k_hw_reg_read(ah, AR5K_BEACON_CNT);
 }
 
+
+/******************\
+* ACK/CTS Timeouts *
+\******************/
+
 /**
- * ath5k_hw_set_ack_bitrate - set bitrate for ACKs
+ * ath5k_hw_write_rate_duration - fill rate code to duration table
  *
- * @ah: The &struct ath5k_hw
- * @high: Flag to determine if we want to use high transmission rate
- * for ACKs or not
+ * @ah: the &struct ath5k_hw
+ * @mode: one of enum ath5k_driver_mode
+ *
+ * Write the rate code to duration table upon hw reset. This is a helper for
+ * ath5k_hw_pcu_init(). It seems all this is doing is setting an ACK timeout on
+ * the hardware, based on current mode, for each rate. The rates which are
+ * capable of short preamble (802.11b rates 2Mbps, 5.5Mbps, and 11Mbps) have
+ * different rate code so we write their value twice (one for long preamble
+ * and one for short).
+ *
+ * Note: Band doesn't matter here, if we set the values for OFDM it works
+ * on both a and g modes. So all we have to do is set values for all g rates
+ * that include all OFDM and CCK rates.
  *
- * If high flag is set, we tell hw to use a set of control rates based on
- * the current transmission rate (check out control_rates array inside reset.c).
- * If not hw just uses the lowest rate available for the current modulation
- * scheme being used (1Mbit for CCK and 6Mbits for OFDM).
  */
-void ath5k_hw_set_ack_bitrate_high(struct ath5k_hw *ah, bool high)
+static inline void ath5k_hw_write_rate_duration(struct ath5k_hw *ah)
 {
-	if (ah->ah_version != AR5K_AR5212)
-		return;
-	else {
-		u32 val = AR5K_STA_ID1_BASE_RATE_11B | AR5K_STA_ID1_ACKCTS_6MB;
-		if (high)
-			AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, val);
+	struct ath5k_softc *sc = ah->ah_sc;
+	struct ieee80211_rate *rate;
+	unsigned int i;
+	/* 802.11g covers both OFDM and CCK */
+	u8 band = IEEE80211_BAND_2GHZ;
+
+	/* Write rate duration table */
+	for (i = 0; i < sc->sbands[band].n_bitrates; i++) {
+		u32 reg;
+		u16 tx_time;
+
+		if (ah->ah_ack_bitrate_high)
+			rate = &sc->sbands[band].bitrates[ack_rates_high[i]];
+		/* CCK -> 1Mb */
+		else if (i < 4)
+			rate = &sc->sbands[band].bitrates[0];
+		/* OFDM -> 6Mb */
 		else
-			AR5K_REG_ENABLE_BITS(ah, AR5K_STA_ID1, val);
-	}
-}
+			rate = &sc->sbands[band].bitrates[4];
 
+		/* Set ACK timeout */
+		reg = AR5K_RATE_DUR(rate->hw_value);
 
-/******************\
-* ACK/CTS Timeouts *
-\******************/
+		/* An ACK frame consists of 10 bytes. If you add the FCS,
+		 * which ieee80211_generic_frame_duration() adds,
+		 * its 14 bytes. Note we use the control rate and not the
+		 * actual rate for this rate. See mac80211 tx.c
+		 * ieee80211_duration() for a brief description of
+		 * what rate we should choose to TX ACKs. */
+		tx_time = ath5k_hw_get_frame_duration(ah, 10, rate);
+
+		ath5k_hw_reg_write(ah, tx_time, reg);
+
+		if (!(rate->flags & IEEE80211_RATE_SHORT_PREAMBLE))
+			continue;
+
+		/*
+		 * We're not distinguishing short preamble here,
+		 * This is true, all we'll get is a longer value here
+		 * which is not necessarilly bad. We could use
+		 * export ieee80211_frame_duration() but that needs to be
+		 * fixed first to be properly used by mac802111 drivers:
+		 *
+		 *  - remove erp stuff and let the routine figure ofdm
+		 *    erp rates
+		 *  - remove passing argument ieee80211_local as
+		 *    drivers don't have access to it
+		 *  - move drivers using ieee80211_generic_frame_duration()
+		 *    to this
+		 */
+		ath5k_hw_reg_write(ah, tx_time,
+			reg + (AR5K_SET_SHORT_PREAMBLE << 2));
+	}
+}
 
 /**
  * ath5k_hw_set_ack_timeout - Set ACK timeout on PCU
@@ -199,88 +325,10 @@ static int ath5k_hw_set_cts_timeout(stru
 	return 0;
 }
 
-/**
- * ath5k_hw_htoclock - Translate usec to hw clock units
- *
- * @ah: The &struct ath5k_hw
- * @usec: value in microseconds
- */
-unsigned int ath5k_hw_htoclock(struct ath5k_hw *ah, unsigned int usec)
-{
-	struct ath_common *common = ath5k_hw_common(ah);
-	return usec * common->clockrate;
-}
-
-/**
- * ath5k_hw_clocktoh - Translate hw clock units to usec
- * @clock: value in hw clock units
- */
-unsigned int ath5k_hw_clocktoh(struct ath5k_hw *ah, unsigned int clock)
-{
-	struct ath_common *common = ath5k_hw_common(ah);
-	return clock / common->clockrate;
-}
-
-/**
- * ath5k_hw_set_clockrate - Set common->clockrate for the current channel
- *
- * @ah: The &struct ath5k_hw
- */
-void ath5k_hw_set_clockrate(struct ath5k_hw *ah)
-{
-	struct ieee80211_channel *channel = ah->ah_current_channel;
-	struct ath_common *common = ath5k_hw_common(ah);
-	int clock;
-
-	if (channel->hw_value & CHANNEL_5GHZ)
-		clock = 40; /* 802.11a */
-	else if (channel->hw_value & CHANNEL_CCK)
-		clock = 22; /* 802.11b */
-	else
-		clock = 44; /* 802.11g */
-
-	/* Clock rate in turbo modes is twice the normal rate */
-	if (channel->hw_value & CHANNEL_TURBO)
-		clock *= 2;
-
-	common->clockrate = clock;
-}
-
-/**
- * ath5k_hw_get_default_slottime - Get the default slot time for current mode
- *
- * @ah: The &struct ath5k_hw
- */
-static unsigned int ath5k_hw_get_default_slottime(struct ath5k_hw *ah)
-{
-	struct ieee80211_channel *channel = ah->ah_current_channel;
-
-	if (channel->hw_value & CHANNEL_TURBO)
-		return 6; /* both turbo modes */
-
-	if (channel->hw_value & CHANNEL_CCK)
-		return 20; /* 802.11b */
-
-	return 9; /* 802.11 a/g */
-}
-
-/**
- * ath5k_hw_get_default_sifs - Get the default SIFS for current mode
- *
- * @ah: The &struct ath5k_hw
- */
-static unsigned int ath5k_hw_get_default_sifs(struct ath5k_hw *ah)
-{
-	struct ieee80211_channel *channel = ah->ah_current_channel;
-
-	if (channel->hw_value & CHANNEL_TURBO)
-		return 8; /* both turbo modes */
-
-	if (channel->hw_value & CHANNEL_5GHZ)
-		return 16; /* 802.11a */
 
-	return 10; /* 802.11 b/g */
-}
+/*******************\
+* RX filter Control *
+\*******************/
 
 /**
  * ath5k_hw_set_lladdr - Set station id
@@ -362,39 +410,6 @@ void ath5k_hw_set_bssid_mask(struct ath5
 		ath_hw_setbssidmask(common);
 }
 
-/************\
-* RX Control *
-\************/
-
-/**
- * ath5k_hw_start_rx_pcu - Start RX engine
- *
- * @ah: The &struct ath5k_hw
- *
- * Starts RX engine on PCU so that hw can process RXed frames
- * (ACK etc).
- *
- * NOTE: RX DMA should be already enabled using ath5k_hw_start_rx_dma
- */
-void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah)
-{
-	AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX);
-}
-
-/**
- * at5k_hw_stop_rx_pcu - Stop RX engine
- *
- * @ah: The &struct ath5k_hw
- *
- * Stops RX engine on PCU
- *
- * TODO: Detach ANI here
- */
-void ath5k_hw_stop_rx_pcu(struct ath5k_hw *ah)
-{
-	AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX);
-}
-
 /*
  * Set multicast filter
  */
@@ -746,7 +761,7 @@ ath5k_hw_check_beacon_timers(struct ath5
  * @ah: The &struct ath5k_hw
  * @coverage_class: IEEE 802.11 coverage class number
  *
- * Sets slot time, ACK timeout and CTS timeout for given coverage class.
+ * Sets IFS intervals and ACK/CTS timeouts for given coverage class.
  */
 void ath5k_hw_set_coverage_class(struct ath5k_hw *ah, u8 coverage_class)
 {
@@ -755,9 +770,175 @@ void ath5k_hw_set_coverage_class(struct
 	int ack_timeout = ath5k_hw_get_default_sifs(ah) + slot_time;
 	int cts_timeout = ack_timeout;
 
-	ath5k_hw_set_slot_time(ah, slot_time);
+	ath5k_hw_set_ifs_intervals(ah, slot_time);
 	ath5k_hw_set_ack_timeout(ah, ack_timeout);
 	ath5k_hw_set_cts_timeout(ah, cts_timeout);
 
 	ah->ah_coverage_class = coverage_class;
 }
+
+/***************************\
+* Init/Start/Stop functions *
+\***************************/
+
+/**
+ * ath5k_hw_start_rx_pcu - Start RX engine
+ *
+ * @ah: The &struct ath5k_hw
+ *
+ * Starts RX engine on PCU so that hw can process RXed frames
+ * (ACK etc).
+ *
+ * NOTE: RX DMA should be already enabled using ath5k_hw_start_rx_dma
+ */
+void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah)
+{
+	AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX);
+}
+
+/**
+ * at5k_hw_stop_rx_pcu - Stop RX engine
+ *
+ * @ah: The &struct ath5k_hw
+ *
+ * Stops RX engine on PCU
+ */
+void ath5k_hw_stop_rx_pcu(struct ath5k_hw *ah)
+{
+	AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX);
+}
+
+/**
+ * ath5k_hw_set_opmode - Set PCU operating mode
+ *
+ * @ah: The &struct ath5k_hw
+ * @op_mode: &enum nl80211_iftype operating mode
+ *
+ * Configure PCU for the various operating modes (AP/STA etc)
+ */
+int ath5k_hw_set_opmode(struct ath5k_hw *ah, enum nl80211_iftype op_mode)
+{
+	struct ath_common *common = ath5k_hw_common(ah);
+	u32 pcu_reg, beacon_reg, low_id, high_id;
+
+	ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_MODE, "mode %d\n", op_mode);
+
+	/* Preserve rest settings */
+	pcu_reg = ath5k_hw_reg_read(ah, AR5K_STA_ID1) & 0xffff0000;
+	pcu_reg &= ~(AR5K_STA_ID1_ADHOC | AR5K_STA_ID1_AP
+			| AR5K_STA_ID1_KEYSRCH_MODE
+			| (ah->ah_version == AR5K_AR5210 ?
+			(AR5K_STA_ID1_PWR_SV | AR5K_STA_ID1_NO_PSPOLL) : 0));
+
+	beacon_reg = 0;
+
+	switch (op_mode) {
+	case NL80211_IFTYPE_ADHOC:
+		pcu_reg |= AR5K_STA_ID1_ADHOC | AR5K_STA_ID1_KEYSRCH_MODE;
+		beacon_reg |= AR5K_BCR_ADHOC;
+		if (ah->ah_version == AR5K_AR5210)
+			pcu_reg |= AR5K_STA_ID1_NO_PSPOLL;
+		else
+			AR5K_REG_ENABLE_BITS(ah, AR5K_CFG, AR5K_CFG_IBSS);
+		break;
+
+	case NL80211_IFTYPE_AP:
+	case NL80211_IFTYPE_MESH_POINT:
+		pcu_reg |= AR5K_STA_ID1_AP | AR5K_STA_ID1_KEYSRCH_MODE;
+		beacon_reg |= AR5K_BCR_AP;
+		if (ah->ah_version == AR5K_AR5210)
+			pcu_reg |= AR5K_STA_ID1_NO_PSPOLL;
+		else
+			AR5K_REG_DISABLE_BITS(ah, AR5K_CFG, AR5K_CFG_IBSS);
+		break;
+
+	case NL80211_IFTYPE_STATION:
+		pcu_reg |= AR5K_STA_ID1_KEYSRCH_MODE
+			| (ah->ah_version == AR5K_AR5210 ?
+				AR5K_STA_ID1_PWR_SV : 0);
+	case NL80211_IFTYPE_MONITOR:
+		pcu_reg |= AR5K_STA_ID1_KEYSRCH_MODE
+			| (ah->ah_version == AR5K_AR5210 ?
+				AR5K_STA_ID1_NO_PSPOLL : 0);
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	/*
+	 * Set PCU registers
+	 */
+	low_id = get_unaligned_le32(common->macaddr);
+	high_id = get_unaligned_le16(common->macaddr + 4);
+	ath5k_hw_reg_write(ah, low_id, AR5K_STA_ID0);
+	ath5k_hw_reg_write(ah, pcu_reg | high_id, AR5K_STA_ID1);
+
+	/*
+	 * Set Beacon Control Register on 5210
+	 */
+	if (ah->ah_version == AR5K_AR5210)
+		ath5k_hw_reg_write(ah, beacon_reg, AR5K_BCR);
+
+	return 0;
+}
+
+void ath5k_hw_pcu_init(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
+								u8 mode)
+{
+	/* Set bssid and bssid mask */
+	ath5k_hw_set_bssid(ah);
+
+	/* Set PCU config */
+	ath5k_hw_set_opmode(ah, op_mode);
+
+	/* Write rate duration table only on AR5212 and if
+	 * virtual interface has already been brought up
+	 * XXX: rethink this after new mode changes to
+	 * mac80211 are integrated */
+	if (ah->ah_version == AR5K_AR5212 &&
+		ah->ah_sc->nvifs)
+		ath5k_hw_write_rate_duration(ah);
+
+	/* Set RSSI/BRSSI thresholds
+	 *
+	 * Note: If we decide to set this value
+	 * dynamicaly, have in mind that when AR5K_RSSI_THR
+	 * register is read it might return 0x40 if we haven't
+	 * wrote anything to it plus BMISS RSSI threshold is zeroed.
+	 * So doing a save/restore procedure here isn't the right
+	 * choice. Instead store it on ath5k_hw */
+	ath5k_hw_reg_write(ah, (AR5K_TUNE_RSSI_THRES |
+				AR5K_TUNE_BMISS_THRES <<
+				AR5K_RSSI_THR_BMISS_S),
+				AR5K_RSSI_THR);
+
+	/* MIC QoS support */
+	if (ah->ah_mac_srev >= AR5K_SREV_AR2413) {
+		ath5k_hw_reg_write(ah, 0x000100aa, AR5K_MIC_QOS_CTL);
+		ath5k_hw_reg_write(ah, 0x00003210, AR5K_MIC_QOS_SEL);
+	}
+
+	/* QoS NOACK Policy */
+	if (ah->ah_version == AR5K_AR5212) {
+		ath5k_hw_reg_write(ah,
+			AR5K_REG_SM(2, AR5K_QOS_NOACK_2BIT_VALUES) |
+			AR5K_REG_SM(5, AR5K_QOS_NOACK_BIT_OFFSET)  |
+			AR5K_REG_SM(0, AR5K_QOS_NOACK_BYTE_OFFSET),
+			AR5K_QOS_NOACK);
+	}
+
+	/* Restore slot time and ACK timeouts */
+	if (ah->ah_coverage_class > 0)
+		ath5k_hw_set_coverage_class(ah, ah->ah_coverage_class);
+
+	/* Set ACK bitrate mode (see ack_rates_high) */
+	if (ah->ah_version == AR5K_AR5212) {
+		u32 val = AR5K_STA_ID1_BASE_RATE_11B | AR5K_STA_ID1_ACKCTS_6MB;
+		if (ah->ah_ack_bitrate_high)
+			AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, val);
+		else
+			AR5K_REG_ENABLE_BITS(ah, AR5K_STA_ID1, val);
+	}
+	return;
+}
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath5k/phy.c linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath5k/phy.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath5k/phy.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath5k/phy.c	2011-03-14 21:20:32.000000000 -0400
@@ -29,6 +29,95 @@
 #include "rfbuffer.h"
 #include "rfgain.h"
 
+
+/******************\
+* Helper functions *
+\******************/
+
+/*
+ * Get the PHY Chip revision
+ */
+u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan)
+{
+	unsigned int i;
+	u32 srev;
+	u16 ret;
+
+	/*
+	 * Set the radio chip access register
+	 */
+	switch (chan) {
+	case CHANNEL_2GHZ:
+		ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_2GHZ, AR5K_PHY(0));
+		break;
+	case CHANNEL_5GHZ:
+		ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ, AR5K_PHY(0));
+		break;
+	default:
+		return 0;
+	}
+
+	mdelay(2);
+
+	/* ...wait until PHY is ready and read the selected radio revision */
+	ath5k_hw_reg_write(ah, 0x00001c16, AR5K_PHY(0x34));
+
+	for (i = 0; i < 8; i++)
+		ath5k_hw_reg_write(ah, 0x00010000, AR5K_PHY(0x20));
+
+	if (ah->ah_version == AR5K_AR5210) {
+		srev = ath5k_hw_reg_read(ah, AR5K_PHY(256) >> 28) & 0xf;
+		ret = (u16)ath5k_hw_bitswap(srev, 4) + 1;
+	} else {
+		srev = (ath5k_hw_reg_read(ah, AR5K_PHY(0x100)) >> 24) & 0xff;
+		ret = (u16)ath5k_hw_bitswap(((srev & 0xf0) >> 4) |
+				((srev & 0x0f) << 4), 8);
+	}
+
+	/* Reset to the 5GHz mode */
+	ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ, AR5K_PHY(0));
+
+	return ret;
+}
+
+/*
+ * Check if a channel is supported
+ */
+bool ath5k_channel_ok(struct ath5k_hw *ah, u16 freq, unsigned int flags)
+{
+	/* Check if the channel is in our supported range */
+	if (flags & CHANNEL_2GHZ) {
+		if ((freq >= ah->ah_capabilities.cap_range.range_2ghz_min) &&
+		    (freq <= ah->ah_capabilities.cap_range.range_2ghz_max))
+			return true;
+	} else if (flags & CHANNEL_5GHZ)
+		if ((freq >= ah->ah_capabilities.cap_range.range_5ghz_min) &&
+		    (freq <= ah->ah_capabilities.cap_range.range_5ghz_max))
+			return true;
+
+	return false;
+}
+
+bool ath5k_hw_chan_has_spur_noise(struct ath5k_hw *ah,
+				struct ieee80211_channel *channel)
+{
+	u8 refclk_freq;
+
+	if ((ah->ah_radio == AR5K_RF5112) ||
+	(ah->ah_radio == AR5K_RF5413) ||
+	(ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4)))
+		refclk_freq = 40;
+	else
+		refclk_freq = 32;
+
+	if ((channel->center_freq % refclk_freq != 0) &&
+	((channel->center_freq % refclk_freq < 10) ||
+	(channel->center_freq % refclk_freq > 22)))
+		return true;
+	else
+		return false;
+}
+
 /*
  * Used to modify RF Banks before writing them to AR5K_RF_BUFFER
  */
@@ -110,6 +199,118 @@ static unsigned int ath5k_hw_rfb_op(stru
 	return data;
 }
 
+/**
+ * ath5k_hw_write_ofdm_timings - set OFDM timings on AR5212
+ *
+ * @ah: the &struct ath5k_hw
+ * @channel: the currently set channel upon reset
+ *
+ * Write the delta slope coefficient (used on pilot tracking ?) for OFDM
+ * operation on the AR5212 upon reset. This is a helper for ath5k_hw_phy_init.
+ *
+ * Since delta slope is floating point we split it on its exponent and
+ * mantissa and provide these values on hw.
+ *
+ * For more infos i think this patent is related
+ * http://www.freepatentsonline.com/7184495.html
+ */
+static inline int ath5k_hw_write_ofdm_timings(struct ath5k_hw *ah,
+	struct ieee80211_channel *channel)
+{
+	/* Get exponent and mantissa and set it */
+	u32 coef_scaled, coef_exp, coef_man,
+		ds_coef_exp, ds_coef_man, clock;
+
+	BUG_ON(!(ah->ah_version == AR5K_AR5212) ||
+		!(channel->hw_value & CHANNEL_OFDM));
+
+	/* Get coefficient
+	 * ALGO: coef = (5 * clock / carrier_freq) / 2
+	 * we scale coef by shifting clock value by 24 for
+	 * better precision since we use integers */
+	switch (ah->ah_bwmode) {
+	case AR5K_BWMODE_40MHZ:
+		clock = 40 * 2;
+		break;
+	case AR5K_BWMODE_10MHZ:
+		clock = 40 / 2;
+		break;
+	case AR5K_BWMODE_5MHZ:
+		clock = 40 / 4;
+		break;
+	default:
+		clock = 40;
+		break;
+	}
+	coef_scaled = ((5 * (clock << 24)) / 2) / channel->center_freq;
+
+	/* Get exponent
+	 * ALGO: coef_exp = 14 - highest set bit position */
+	coef_exp = ilog2(coef_scaled);
+
+	/* Doesn't make sense if it's zero*/
+	if (!coef_scaled || !coef_exp)
+		return -EINVAL;
+
+	/* Note: we've shifted coef_scaled by 24 */
+	coef_exp = 14 - (coef_exp - 24);
+
+
+	/* Get mantissa (significant digits)
+	 * ALGO: coef_mant = floor(coef_scaled* 2^coef_exp+0.5) */
+	coef_man = coef_scaled +
+		(1 << (24 - coef_exp - 1));
+
+	/* Calculate delta slope coefficient exponent
+	 * and mantissa (remove scaling) and set them on hw */
+	ds_coef_man = coef_man >> (24 - coef_exp);
+	ds_coef_exp = coef_exp - 16;
+
+	AR5K_REG_WRITE_BITS(ah, AR5K_PHY_TIMING_3,
+		AR5K_PHY_TIMING_3_DSC_MAN, ds_coef_man);
+	AR5K_REG_WRITE_BITS(ah, AR5K_PHY_TIMING_3,
+		AR5K_PHY_TIMING_3_DSC_EXP, ds_coef_exp);
+
+	return 0;
+}
+
+int ath5k_hw_phy_disable(struct ath5k_hw *ah)
+{
+	/*Just a try M.F.*/
+	ath5k_hw_reg_write(ah, AR5K_PHY_ACT_DISABLE, AR5K_PHY_ACT);
+
+	return 0;
+}
+
+/*
+ * Wait for synth to settle
+ */
+static void ath5k_hw_wait_for_synth(struct ath5k_hw *ah,
+			struct ieee80211_channel *channel)
+{
+	/*
+	 * On 5211+ read activation -> rx delay
+	 * and use it (100ns steps).
+	 */
+	if (ah->ah_version != AR5K_AR5210) {
+		u32 delay;
+		delay = ath5k_hw_reg_read(ah, AR5K_PHY_RX_DELAY) &
+			AR5K_PHY_RX_DELAY_M;
+		delay = (channel->hw_value & CHANNEL_CCK) ?
+			((delay << 2) / 22) : (delay / 10);
+		if (ah->ah_bwmode == AR5K_BWMODE_10MHZ)
+			delay = delay << 1;
+		if (ah->ah_bwmode == AR5K_BWMODE_5MHZ)
+			delay = delay << 2;
+		/* XXX: /2 on turbo ? Let's be safe
+		 * for now */
+		udelay(100 + delay);
+	} else {
+		mdelay(1);
+	}
+}
+
+
 /**********************\
 * RF Gain optimization *
 \**********************/
@@ -436,10 +637,10 @@ done:
 /* Write initial RF gain table to set the RF sensitivity
  * this one works on all RF chips and has nothing to do
  * with gain_F calibration */
-int ath5k_hw_rfgain_init(struct ath5k_hw *ah, unsigned int freq)
+static int ath5k_hw_rfgain_init(struct ath5k_hw *ah, enum ieee80211_band band)
 {
 	const struct ath5k_ini_rfgain *ath5k_rfg;
-	unsigned int i, size;
+	unsigned int i, size, index;
 
 	switch (ah->ah_radio) {
 	case AR5K_RF5111:
@@ -471,17 +672,11 @@ int ath5k_hw_rfgain_init(struct ath5k_hw
 		return -EINVAL;
 	}
 
-	switch (freq) {
-	case AR5K_INI_RFGAIN_2GHZ:
-	case AR5K_INI_RFGAIN_5GHZ:
-		break;
-	default:
-		return -EINVAL;
-	}
+	index = (band == IEEE80211_BAND_2GHZ) ? 1 : 0;
 
 	for (i = 0; i < size; i++) {
 		AR5K_REG_WAIT(i);
-		ath5k_hw_reg_write(ah, ath5k_rfg[i].rfg_value[freq],
+		ath5k_hw_reg_write(ah, ath5k_rfg[i].rfg_value[index],
 			(u32)ath5k_rfg[i].rfg_register);
 	}
 
@@ -494,12 +689,11 @@ int ath5k_hw_rfgain_init(struct ath5k_hw
 * RF Registers setup *
 \********************/
 
-
 /*
  * Setup RF registers by writing RF buffer on hw
  */
-int ath5k_hw_rfregs_init(struct ath5k_hw *ah, struct ieee80211_channel *channel,
-		unsigned int mode)
+static int ath5k_hw_rfregs_init(struct ath5k_hw *ah,
+	struct ieee80211_channel *channel, unsigned int mode)
 {
 	const struct ath5k_rf_reg *rf_regs;
 	const struct ath5k_ini_rfbuffer *ini_rfb;
@@ -652,6 +846,11 @@ int ath5k_hw_rfregs_init(struct ath5k_hw
 
 	g_step = &go->go_step[ah->ah_gain.g_step_idx];
 
+	/* Set turbo mode (N/A on RF5413) */
+	if ((ah->ah_bwmode == AR5K_BWMODE_40MHZ) &&
+	(ah->ah_radio != AR5K_RF5413))
+		ath5k_hw_rfb_op(ah, rf_regs, 1, AR5K_RF_TURBO, false);
+
 	/* Bank Modifications (chip-specific) */
 	if (ah->ah_radio == AR5K_RF5111) {
 
@@ -691,7 +890,23 @@ int ath5k_hw_rfregs_init(struct ath5k_hw
 		ath5k_hw_rfb_op(ah, rf_regs, ee->ee_xpd[ee_mode],
 						AR5K_RF_PLO_SEL, true);
 
-		/* TODO: Half/quarter channel support */
+		/* Tweak power detectors for half/quarter rate support */
+		if (ah->ah_bwmode == AR5K_BWMODE_5MHZ ||
+		ah->ah_bwmode == AR5K_BWMODE_10MHZ) {
+			u8 wait_i;
+
+			ath5k_hw_rfb_op(ah, rf_regs, 0x1f,
+						AR5K_RF_WAIT_S, true);
+
+			wait_i = (ah->ah_bwmode == AR5K_BWMODE_5MHZ) ?
+							0x1f : 0x10;
+
+			ath5k_hw_rfb_op(ah, rf_regs, wait_i,
+						AR5K_RF_WAIT_I, true);
+			ath5k_hw_rfb_op(ah, rf_regs, 3,
+						AR5K_RF_MAX_TIME, true);
+
+		}
 	}
 
 	if (ah->ah_radio == AR5K_RF5112) {
@@ -789,8 +1004,20 @@ int ath5k_hw_rfregs_init(struct ath5k_hw
 		ath5k_hw_rfb_op(ah, rf_regs, ee->ee_i_gain[ee_mode],
 						AR5K_RF_GAIN_I, true);
 
-		/* TODO: Half/quarter channel support */
+		/* Tweak power detector for half/quarter rates */
+		if (ah->ah_bwmode == AR5K_BWMODE_5MHZ ||
+		ah->ah_bwmode == AR5K_BWMODE_10MHZ) {
+			u8 pd_delay;
+
+			pd_delay = (ah->ah_bwmode == AR5K_BWMODE_5MHZ) ?
+							0xf : 0x8;
 
+			ath5k_hw_rfb_op(ah, rf_regs, pd_delay,
+						AR5K_RF_PD_PERIOD_A, true);
+			ath5k_hw_rfb_op(ah, rf_regs, 0xf,
+						AR5K_RF_PD_DELAY_A, true);
+
+		}
 	}
 
 	if (ah->ah_radio == AR5K_RF5413 &&
@@ -822,24 +1049,6 @@ int ath5k_hw_rfregs_init(struct ath5k_hw
 \**************************/
 
 /*
- * Check if a channel is supported
- */
-bool ath5k_channel_ok(struct ath5k_hw *ah, u16 freq, unsigned int flags)
-{
-	/* Check if the channel is in our supported range */
-	if (flags & CHANNEL_2GHZ) {
-		if ((freq >= ah->ah_capabilities.cap_range.range_2ghz_min) &&
-		    (freq <= ah->ah_capabilities.cap_range.range_2ghz_max))
-			return true;
-	} else if (flags & CHANNEL_5GHZ)
-		if ((freq >= ah->ah_capabilities.cap_range.range_5ghz_min) &&
-		    (freq <= ah->ah_capabilities.cap_range.range_5ghz_max))
-			return true;
-
-	return false;
-}
-
-/*
  * Convertion needed for RF5110
  */
 static u32 ath5k_hw_rf5110_chan2athchan(struct ieee80211_channel *channel)
@@ -1045,7 +1254,8 @@ static int ath5k_hw_rf2425_channel(struc
 /*
  * Set a channel on the radio chip
  */
-int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel)
+static int ath5k_hw_channel(struct ath5k_hw *ah,
+		struct ieee80211_channel *channel)
 {
 	int ret;
 	/*
@@ -1071,6 +1281,7 @@ int ath5k_hw_channel(struct ath5k_hw *ah
 	case AR5K_RF5111:
 		ret = ath5k_hw_rf5111_channel(ah, channel);
 		break;
+	case AR5K_RF2317:
 	case AR5K_RF2425:
 		ret = ath5k_hw_rf2425_channel(ah, channel);
 		break;
@@ -1092,8 +1303,6 @@ int ath5k_hw_channel(struct ath5k_hw *ah
 	}
 
 	ah->ah_current_channel = channel;
-	ah->ah_turbo = channel->hw_value == CHANNEL_T ? true : false;
-	ath5k_hw_set_clockrate(ah);
 
 	return 0;
 }
@@ -1102,18 +1311,12 @@ int ath5k_hw_channel(struct ath5k_hw *ah
   PHY calibration
 \*****************/
 
-static int sign_extend(int val, const int nbits)
-{
-	int order = BIT(nbits-1);
-	return (val ^ order) - order;
-}
-
 static s32 ath5k_hw_read_measured_noise_floor(struct ath5k_hw *ah)
 {
 	s32 val;
 
 	val = ath5k_hw_reg_read(ah, AR5K_PHY_NF);
-	return sign_extend(AR5K_REG_MS(val, AR5K_PHY_NF_MINCCA_PWR), 9);
+	return sign_extend32(AR5K_REG_MS(val, AR5K_PHY_NF_MINCCA_PWR), 8);
 }
 
 void ath5k_hw_init_nfcal_hist(struct ath5k_hw *ah)
@@ -1181,22 +1384,7 @@ void ath5k_hw_update_noise_floor(struct
 		return;
 	}
 
-	switch (ah->ah_current_channel->hw_value & CHANNEL_MODES) {
-	case CHANNEL_A:
-	case CHANNEL_T:
-	case CHANNEL_XR:
-		ee_mode = AR5K_EEPROM_MODE_11A;
-		break;
-	case CHANNEL_G:
-	case CHANNEL_TG:
-		ee_mode = AR5K_EEPROM_MODE_11G;
-		break;
-	default:
-	case CHANNEL_B:
-		ee_mode = AR5K_EEPROM_MODE_11B;
-		break;
-	}
-
+	ee_mode = ath5k_eeprom_mode_from_channel(ah->ah_current_channel);
 
 	/* completed NF calibration, test threshold */
 	nf = ath5k_hw_read_measured_noise_floor(ah);
@@ -1425,31 +1613,12 @@ int ath5k_hw_phy_calibrate(struct ath5k_
 	return ret;
 }
 
+
 /***************************\
 * Spur mitigation functions *
 \***************************/
 
-bool ath5k_hw_chan_has_spur_noise(struct ath5k_hw *ah,
-				struct ieee80211_channel *channel)
-{
-	u8 refclk_freq;
-
-	if ((ah->ah_radio == AR5K_RF5112) ||
-	(ah->ah_radio == AR5K_RF5413) ||
-	(ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4)))
-		refclk_freq = 40;
-	else
-		refclk_freq = 32;
-
-	if ((channel->center_freq % refclk_freq != 0) &&
-	((channel->center_freq % refclk_freq < 10) ||
-	(channel->center_freq % refclk_freq > 22)))
-		return true;
-	else
-		return false;
-}
-
-void
+static void
 ath5k_hw_set_spur_mitigation_filter(struct ath5k_hw *ah,
 				struct ieee80211_channel *channel)
 {
@@ -1478,7 +1647,7 @@ ath5k_hw_set_spur_mitigation_filter(stru
 	spur_chan_fbin = AR5K_EEPROM_NO_SPUR;
 	spur_detection_window = AR5K_SPUR_CHAN_WIDTH;
 	/* XXX: Half/Quarter channels ?*/
-	if (channel->hw_value & CHANNEL_TURBO)
+	if (ah->ah_bwmode == AR5K_BWMODE_40MHZ)
 		spur_detection_window *= 2;
 
 	for (i = 0; i < AR5K_EEPROM_N_SPUR_CHANS; i++) {
@@ -1507,32 +1676,43 @@ ath5k_hw_set_spur_mitigation_filter(stru
 		 * Calculate deltas:
 		 * spur_freq_sigma_delta -> spur_offset / sample_freq << 21
 		 * spur_delta_phase -> spur_offset / chip_freq << 11
-		 * Note: Both values have 100KHz resolution
+		 * Note: Both values have 100Hz resolution
 		 */
-		/* XXX: Half/Quarter rate channels ? */
-		switch (channel->hw_value) {
-		case CHANNEL_A:
-			/* Both sample_freq and chip_freq are 40MHz */
-			spur_delta_phase = (spur_offset << 17) / 25;
-			spur_freq_sigma_delta = (spur_delta_phase >> 10);
-			symbol_width = AR5K_SPUR_SYMBOL_WIDTH_BASE_100Hz;
-			break;
-		case CHANNEL_G:
-			/* sample_freq -> 40MHz chip_freq -> 44MHz
-			 * (for b compatibility) */
-			spur_freq_sigma_delta = (spur_offset << 8) / 55;
-			spur_delta_phase = (spur_offset << 17) / 25;
-			symbol_width = AR5K_SPUR_SYMBOL_WIDTH_BASE_100Hz;
-			break;
-		case CHANNEL_T:
-		case CHANNEL_TG:
+		switch (ah->ah_bwmode) {
+		case AR5K_BWMODE_40MHZ:
 			/* Both sample_freq and chip_freq are 80MHz */
 			spur_delta_phase = (spur_offset << 16) / 25;
 			spur_freq_sigma_delta = (spur_delta_phase >> 10);
-			symbol_width = AR5K_SPUR_SYMBOL_WIDTH_TURBO_100Hz;
+			symbol_width = AR5K_SPUR_SYMBOL_WIDTH_BASE_100Hz * 2;
 			break;
+		case AR5K_BWMODE_10MHZ:
+			/* Both sample_freq and chip_freq are 20MHz (?) */
+			spur_delta_phase = (spur_offset << 18) / 25;
+			spur_freq_sigma_delta = (spur_delta_phase >> 10);
+			symbol_width = AR5K_SPUR_SYMBOL_WIDTH_BASE_100Hz / 2;
+		case AR5K_BWMODE_5MHZ:
+			/* Both sample_freq and chip_freq are 10MHz (?) */
+			spur_delta_phase = (spur_offset << 19) / 25;
+			spur_freq_sigma_delta = (spur_delta_phase >> 10);
+			symbol_width = AR5K_SPUR_SYMBOL_WIDTH_BASE_100Hz / 4;
 		default:
-			return;
+			if (channel->hw_value == CHANNEL_A) {
+				/* Both sample_freq and chip_freq are 40MHz */
+				spur_delta_phase = (spur_offset << 17) / 25;
+				spur_freq_sigma_delta =
+						(spur_delta_phase >> 10);
+				symbol_width =
+					AR5K_SPUR_SYMBOL_WIDTH_BASE_100Hz;
+			} else {
+				/* sample_freq -> 40MHz chip_freq -> 44MHz
+				 * (for b compatibility) */
+				spur_delta_phase = (spur_offset << 17) / 25;
+				spur_freq_sigma_delta =
+						(spur_offset << 8) / 55;
+				symbol_width =
+					AR5K_SPUR_SYMBOL_WIDTH_BASE_100Hz;
+			}
+			break;
 		}
 
 		/* Calculate pilot and magnitude masks */
@@ -1672,63 +1852,6 @@ ath5k_hw_set_spur_mitigation_filter(stru
 	}
 }
 
-/********************\
-  Misc PHY functions
-\********************/
-
-int ath5k_hw_phy_disable(struct ath5k_hw *ah)
-{
-	/*Just a try M.F.*/
-	ath5k_hw_reg_write(ah, AR5K_PHY_ACT_DISABLE, AR5K_PHY_ACT);
-
-	return 0;
-}
-
-/*
- * Get the PHY Chip revision
- */
-u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan)
-{
-	unsigned int i;
-	u32 srev;
-	u16 ret;
-
-	/*
-	 * Set the radio chip access register
-	 */
-	switch (chan) {
-	case CHANNEL_2GHZ:
-		ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_2GHZ, AR5K_PHY(0));
-		break;
-	case CHANNEL_5GHZ:
-		ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ, AR5K_PHY(0));
-		break;
-	default:
-		return 0;
-	}
-
-	mdelay(2);
-
-	/* ...wait until PHY is ready and read the selected radio revision */
-	ath5k_hw_reg_write(ah, 0x00001c16, AR5K_PHY(0x34));
-
-	for (i = 0; i < 8; i++)
-		ath5k_hw_reg_write(ah, 0x00010000, AR5K_PHY(0x20));
-
-	if (ah->ah_version == AR5K_AR5210) {
-		srev = ath5k_hw_reg_read(ah, AR5K_PHY(256) >> 28) & 0xf;
-		ret = (u16)ath5k_hw_bitswap(srev, 4) + 1;
-	} else {
-		srev = (ath5k_hw_reg_read(ah, AR5K_PHY(0x100)) >> 24) & 0xff;
-		ret = (u16)ath5k_hw_bitswap(((srev & 0xf0) >> 4) |
-				((srev & 0x0f) << 4), 8);
-	}
-
-	/* Reset to the 5GHz mode */
-	ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ, AR5K_PHY(0));
-
-	return ret;
-}
 
 /*****************\
 * Antenna control *
@@ -1822,7 +1945,8 @@ ath5k_hw_set_antenna_mode(struct ath5k_h
 	struct ieee80211_channel *channel = ah->ah_current_channel;
 	bool use_def_for_tx, update_def_on_tx, use_def_for_rts, fast_div;
 	bool use_def_for_sg;
-	u8 def_ant, tx_ant, ee_mode;
+	int ee_mode;
+	u8 def_ant, tx_ant;
 	u32 sta_id1 = 0;
 
 	/* if channel is not initialized yet we can't set the antennas
@@ -1834,20 +1958,8 @@ ath5k_hw_set_antenna_mode(struct ath5k_h
 
 	def_ant = ah->ah_def_ant;
 
-	switch (channel->hw_value & CHANNEL_MODES) {
-	case CHANNEL_A:
-	case CHANNEL_T:
-	case CHANNEL_XR:
-		ee_mode = AR5K_EEPROM_MODE_11A;
-		break;
-	case CHANNEL_G:
-	case CHANNEL_TG:
-		ee_mode = AR5K_EEPROM_MODE_11G;
-		break;
-	case CHANNEL_B:
-		ee_mode = AR5K_EEPROM_MODE_11B;
-		break;
-	default:
+	ee_mode = ath5k_eeprom_mode_from_channel(channel);
+	if (ee_mode < 0) {
 		ATH5K_ERR(ah->ah_sc,
 			"invalid channel: %d\n", channel->center_freq);
 		return;
@@ -2275,20 +2387,20 @@ ath5k_get_max_ctl_power(struct ath5k_hw
 
 	switch (channel->hw_value & CHANNEL_MODES) {
 	case CHANNEL_A:
-		ctl_mode |= AR5K_CTL_11A;
+		if (ah->ah_bwmode == AR5K_BWMODE_40MHZ)
+			ctl_mode |= AR5K_CTL_TURBO;
+		else
+			ctl_mode |= AR5K_CTL_11A;
 		break;
 	case CHANNEL_G:
-		ctl_mode |= AR5K_CTL_11G;
+		if (ah->ah_bwmode == AR5K_BWMODE_40MHZ)
+			ctl_mode |= AR5K_CTL_TURBOG;
+		else
+			ctl_mode |= AR5K_CTL_11G;
 		break;
 	case CHANNEL_B:
 		ctl_mode |= AR5K_CTL_11B;
 		break;
-	case CHANNEL_T:
-		ctl_mode |= AR5K_CTL_TURBO;
-		break;
-	case CHANNEL_TG:
-		ctl_mode |= AR5K_CTL_TURBOG;
-		break;
 	case CHANNEL_XR:
 		/* Fall through */
 	default:
@@ -2482,7 +2594,7 @@ ath5k_combine_linear_pcdac_curves(struct
 
 /* Write PCDAC values on hw */
 static void
-ath5k_setup_pcdac_table(struct ath5k_hw *ah)
+ath5k_write_pcdac_table(struct ath5k_hw *ah)
 {
 	u8 	*pcdac_out = ah->ah_txpower.txp_pd_table;
 	int	i;
@@ -2631,10 +2743,12 @@ ath5k_combine_pwr_to_pdadc_curves(struct
 
 /* Write PDADC values on hw */
 static void
-ath5k_setup_pwr_to_pdadc_table(struct ath5k_hw *ah,
-			u8 pdcurves, u8 *pdg_to_idx)
+ath5k_write_pwr_to_pdadc_table(struct ath5k_hw *ah, u8 ee_mode)
 {
+	struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
 	u8 *pdadc_out = ah->ah_txpower.txp_pd_table;
+	u8 *pdg_to_idx = ee->ee_pdc_to_idx[ee_mode];
+	u8 pdcurves = ee->ee_pd_gains[ee_mode];
 	u32 reg;
 	u8 i;
 
@@ -2844,8 +2958,7 @@ ath5k_setup_channel_powertable(struct at
 					(s16) pcinfo_R->freq,
 					pcinfo_L->max_pwr, pcinfo_R->max_pwr);
 
-	/* We are ready to go, fill PCDAC/PDADC
-	 * table and write settings on hardware */
+	/* Fill PCDAC/PDADC table */
 	switch (type) {
 	case AR5K_PWRTABLE_LINEAR_PCDAC:
 		/* For RF5112 we can have one or two curves
@@ -2858,9 +2971,6 @@ ath5k_setup_channel_powertable(struct at
 		 * match max power value with max
 		 * table index */
 		ah->ah_txpower.txp_offset = 64 - (table_max[0] / 2);
-
-		/* Write settings on hw */
-		ath5k_setup_pcdac_table(ah);
 		break;
 	case AR5K_PWRTABLE_PWR_TO_PCDAC:
 		/* We are done for RF5111 since it has only
@@ -2870,9 +2980,6 @@ ath5k_setup_channel_powertable(struct at
 		/* No rate powertable adjustment for RF5111 */
 		ah->ah_txpower.txp_min_idx = 0;
 		ah->ah_txpower.txp_offset = 0;
-
-		/* Write settings on hw */
-		ath5k_setup_pcdac_table(ah);
 		break;
 	case AR5K_PWRTABLE_PWR_TO_PDADC:
 		/* Set PDADC boundaries and fill
@@ -2880,9 +2987,6 @@ ath5k_setup_channel_powertable(struct at
 		ath5k_combine_pwr_to_pdadc_curves(ah, table_min, table_max,
 						ee->ee_pd_gains[ee_mode]);
 
-		/* Write settings on hw */
-		ath5k_setup_pwr_to_pdadc_table(ah, pdg, pdg_curve_to_idx);
-
 		/* Set txp.offset, note that table_min
 		 * can be negative */
 		ah->ah_txpower.txp_offset = table_min[0];
@@ -2891,9 +2995,20 @@ ath5k_setup_channel_powertable(struct at
 		return -EINVAL;
 	}
 
+	ah->ah_txpower.txp_setup = true;
+
 	return 0;
 }
 
+/* Write power table for current channel to hw */
+static void
+ath5k_write_channel_powertable(struct ath5k_hw *ah, u8 ee_mode, u8 type)
+{
+	if (type == AR5K_PWRTABLE_PWR_TO_PDADC)
+		ath5k_write_pwr_to_pdadc_table(ah, ee_mode);
+	else
+		ath5k_write_pcdac_table(ah);
+}
 
 /*
  * Per-rate tx power setting
@@ -2982,7 +3097,7 @@ ath5k_setup_rate_powertable(struct ath5k
 
 	/* Min/max in 0.25dB units */
 	ah->ah_txpower.txp_min_pwr = 2 * rates[7];
-	ah->ah_txpower.txp_max_pwr = 2 * rates[0];
+	ah->ah_txpower.txp_cur_pwr = 2 * rates[0];
 	ah->ah_txpower.txp_ofdm = rates[7];
 }
 
@@ -2990,11 +3105,13 @@ ath5k_setup_rate_powertable(struct ath5k
 /*
  * Set transmission power
  */
-int
+static int
 ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel,
-		u8 ee_mode, u8 txpower)
+		 u8 txpower)
 {
 	struct ath5k_rate_pcal_info rate_info;
+	struct ieee80211_channel *curr_channel = ah->ah_current_channel;
+	int ee_mode;
 	u8 type;
 	int ret;
 
@@ -3003,14 +3120,18 @@ ath5k_hw_txpower(struct ath5k_hw *ah, st
 		return -EINVAL;
 	}
 
-	/* Reset TX power values */
-	memset(&ah->ah_txpower, 0, sizeof(ah->ah_txpower));
-	ah->ah_txpower.txp_tpc = AR5K_TUNE_TPC_TXPOWER;
-	ah->ah_txpower.txp_min_pwr = 0;
-	ah->ah_txpower.txp_max_pwr = AR5K_TUNE_MAX_TXPOWER;
+	ee_mode = ath5k_eeprom_mode_from_channel(channel);
+	if (ee_mode < 0) {
+		ATH5K_ERR(ah->ah_sc,
+			"invalid channel: %d\n", channel->center_freq);
+		return -EINVAL;
+	}
 
 	/* Initialize TX power table */
 	switch (ah->ah_radio) {
+	case AR5K_RF5110:
+		/* TODO */
+		return 0;
 	case AR5K_RF5111:
 		type = AR5K_PWRTABLE_PWR_TO_PCDAC;
 		break;
@@ -3028,10 +3149,26 @@ ath5k_hw_txpower(struct ath5k_hw *ah, st
 		return -EINVAL;
 	}
 
-	/* FIXME: Only on channel/mode change */
-	ret = ath5k_setup_channel_powertable(ah, channel, ee_mode, type);
-	if (ret)
-		return ret;
+	/*
+	 * If we don't change channel/mode skip tx powertable calculation
+	 * and use the cached one.
+	 */
+	if (!ah->ah_txpower.txp_setup ||
+	    (channel->hw_value != curr_channel->hw_value) ||
+	    (channel->center_freq != curr_channel->center_freq)) {
+		/* Reset TX power values */
+		memset(&ah->ah_txpower, 0, sizeof(ah->ah_txpower));
+		ah->ah_txpower.txp_tpc = AR5K_TUNE_TPC_TXPOWER;
+
+		/* Calculate the powertable */
+		ret = ath5k_setup_channel_powertable(ah, channel,
+							ee_mode, type);
+		if (ret)
+			return ret;
+	}
+
+	/* Write table on hw */
+	ath5k_write_channel_powertable(ah, ee_mode, type);
 
 	/* Limit max power if we have a CTL available */
 	ath5k_get_max_ctl_power(ah, channel);
@@ -3086,31 +3223,223 @@ ath5k_hw_txpower(struct ath5k_hw *ah, st
 
 int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 txpower)
 {
-	/*Just a try M.F.*/
-	struct ieee80211_channel *channel = ah->ah_current_channel;
-	u8 ee_mode;
+	ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_TXPOWER,
+		"changing txpower to %d\n", txpower);
 
-	switch (channel->hw_value & CHANNEL_MODES) {
-	case CHANNEL_A:
-	case CHANNEL_T:
-	case CHANNEL_XR:
-		ee_mode = AR5K_EEPROM_MODE_11A;
-		break;
-	case CHANNEL_G:
-	case CHANNEL_TG:
-		ee_mode = AR5K_EEPROM_MODE_11G;
-		break;
-	case CHANNEL_B:
-		ee_mode = AR5K_EEPROM_MODE_11B;
-		break;
-	default:
-		ATH5K_ERR(ah->ah_sc,
-			"invalid channel: %d\n", channel->center_freq);
+	return ath5k_hw_txpower(ah, ah->ah_current_channel, txpower);
+}
+
+/*************\
+ Init function
+\*************/
+
+int ath5k_hw_phy_init(struct ath5k_hw *ah, struct ieee80211_channel *channel,
+		      u8 mode, bool fast)
+{
+	struct ieee80211_channel *curr_channel;
+	int ret, i;
+	u32 phy_tst1;
+	ret = 0;
+
+	/*
+	 * Sanity check for fast flag
+	 * Don't try fast channel change when changing modulation
+	 * mode/band. We check for chip compatibility on
+	 * ath5k_hw_reset.
+	 */
+	curr_channel = ah->ah_current_channel;
+	if (fast && (channel->hw_value != curr_channel->hw_value))
 		return -EINVAL;
+
+	/*
+	 * On fast channel change we only set the synth parameters
+	 * while PHY is running, enable calibration and skip the rest.
+	 */
+	if (fast) {
+		AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_RFBUS_REQ,
+				    AR5K_PHY_RFBUS_REQ_REQUEST);
+		for (i = 0; i < 100; i++) {
+			if (ath5k_hw_reg_read(ah, AR5K_PHY_RFBUS_GRANT))
+				break;
+			udelay(5);
+		}
+		/* Failed */
+		if (i >= 100)
+			return -EIO;
+
+		/* Set channel and wait for synth */
+		ret = ath5k_hw_channel(ah, channel);
+		if (ret)
+			return ret;
+
+		ath5k_hw_wait_for_synth(ah, channel);
 	}
 
-	ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_TXPOWER,
-		"changing txpower to %d\n", txpower);
+	/*
+	 * Set TX power
+	 *
+	 * Note: We need to do that before we set
+	 * RF buffer settings on 5211/5212+ so that we
+	 * properly set curve indices.
+	 */
+	ret = ath5k_hw_txpower(ah, channel, ah->ah_txpower.txp_cur_pwr ?
+			ah->ah_txpower.txp_cur_pwr / 2 : AR5K_TUNE_MAX_TXPOWER);
+	if (ret)
+		return ret;
 
-	return ath5k_hw_txpower(ah, channel, ee_mode, txpower);
+	/* Write OFDM timings on 5212*/
+	if (ah->ah_version == AR5K_AR5212 &&
+		channel->hw_value & CHANNEL_OFDM) {
+
+		ret = ath5k_hw_write_ofdm_timings(ah, channel);
+		if (ret)
+			return ret;
+
+		/* Spur info is available only from EEPROM versions
+		 * greater than 5.3, but the EEPROM routines will use
+		 * static values for older versions */
+		if (ah->ah_mac_srev >= AR5K_SREV_AR5424)
+			ath5k_hw_set_spur_mitigation_filter(ah,
+							    channel);
+	}
+
+	/* If we used fast channel switching
+	 * we are done, release RF bus and
+	 * fire up NF calibration.
+	 *
+	 * Note: Only NF calibration due to
+	 * channel change, not AGC calibration
+	 * since AGC is still running !
+	 */
+	if (fast) {
+		/*
+		 * Release RF Bus grant
+		 */
+		AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_RFBUS_REQ,
+				    AR5K_PHY_RFBUS_REQ_REQUEST);
+
+		/*
+		 * Start NF calibration
+		 */
+		AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL,
+					AR5K_PHY_AGCCTL_NF);
+
+		return ret;
+	}
+
+	/*
+	 * For 5210 we do all initialization using
+	 * initvals, so we don't have to modify
+	 * any settings (5210 also only supports
+	 * a/aturbo modes)
+	 */
+	if (ah->ah_version != AR5K_AR5210) {
+
+		/*
+		 * Write initial RF gain settings
+		 * This should work for both 5111/5112
+		 */
+		ret = ath5k_hw_rfgain_init(ah, channel->band);
+		if (ret)
+			return ret;
+
+		mdelay(1);
+
+		/*
+		 * Write RF buffer
+		 */
+		ret = ath5k_hw_rfregs_init(ah, channel, mode);
+		if (ret)
+			return ret;
+
+		/*Enable/disable 802.11b mode on 5111
+		(enable 2111 frequency converter + CCK)*/
+		if (ah->ah_radio == AR5K_RF5111) {
+			if (mode == AR5K_MODE_11B)
+				AR5K_REG_ENABLE_BITS(ah, AR5K_TXCFG,
+				    AR5K_TXCFG_B_MODE);
+			else
+				AR5K_REG_DISABLE_BITS(ah, AR5K_TXCFG,
+				    AR5K_TXCFG_B_MODE);
+		}
+
+	} else if (ah->ah_version == AR5K_AR5210) {
+		mdelay(1);
+		/* Disable phy and wait */
+		ath5k_hw_reg_write(ah, AR5K_PHY_ACT_DISABLE, AR5K_PHY_ACT);
+		mdelay(1);
+	}
+
+	/* Set channel on PHY */
+	ret = ath5k_hw_channel(ah, channel);
+	if (ret)
+		return ret;
+
+	/*
+	 * Enable the PHY and wait until completion
+	 * This includes BaseBand and Synthesizer
+	 * activation.
+	 */
+	ath5k_hw_reg_write(ah, AR5K_PHY_ACT_ENABLE, AR5K_PHY_ACT);
+
+	ath5k_hw_wait_for_synth(ah, channel);
+
+	/*
+	 * Perform ADC test to see if baseband is ready
+	 * Set tx hold and check adc test register
+	 */
+	phy_tst1 = ath5k_hw_reg_read(ah, AR5K_PHY_TST1);
+	ath5k_hw_reg_write(ah, AR5K_PHY_TST1_TXHOLD, AR5K_PHY_TST1);
+	for (i = 0; i <= 20; i++) {
+		if (!(ath5k_hw_reg_read(ah, AR5K_PHY_ADC_TEST) & 0x10))
+			break;
+		udelay(200);
+	}
+	ath5k_hw_reg_write(ah, phy_tst1, AR5K_PHY_TST1);
+
+	/*
+	 * Start automatic gain control calibration
+	 *
+	 * During AGC calibration RX path is re-routed to
+	 * a power detector so we don't receive anything.
+	 *
+	 * This method is used to calibrate some static offsets
+	 * used together with on-the fly I/Q calibration (the
+	 * one performed via ath5k_hw_phy_calibrate), which doesn't
+	 * interrupt rx path.
+	 *
+	 * While rx path is re-routed to the power detector we also
+	 * start a noise floor calibration to measure the
+	 * card's noise floor (the noise we measure when we are not
+	 * transmitting or receiving anything).
+	 *
+	 * If we are in a noisy environment, AGC calibration may time
+	 * out and/or noise floor calibration might timeout.
+	 */
+	AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL,
+				AR5K_PHY_AGCCTL_CAL | AR5K_PHY_AGCCTL_NF);
+
+	/* At the same time start I/Q calibration for QAM constellation
+	 * -no need for CCK- */
+	ah->ah_calibration = false;
+	if (!(mode == AR5K_MODE_11B)) {
+		ah->ah_calibration = true;
+		AR5K_REG_WRITE_BITS(ah, AR5K_PHY_IQ,
+				AR5K_PHY_IQ_CAL_NUM_LOG_MAX, 15);
+		AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ,
+				AR5K_PHY_IQ_RUN);
+	}
+
+	/* Wait for gain calibration to finish (we check for I/Q calibration
+	 * during ath5k_phy_calibrate) */
+	if (ath5k_hw_register_timeout(ah, AR5K_PHY_AGCCTL,
+			AR5K_PHY_AGCCTL_CAL, 0, false)) {
+		ATH5K_ERR(ah->ah_sc, "gain calibration timeout (%uMHz)\n",
+			channel->center_freq);
+	}
+
+	/* Restore antenna mode */
+	ath5k_hw_set_antenna_mode(ah, ah->ah_ant_mode);
+
+	return ret;
 }
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath5k/qcu.c linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath5k/qcu.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath5k/qcu.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath5k/qcu.c	2011-03-14 21:20:32.000000000 -0400
@@ -25,14 +25,52 @@ Queue Control Unit, DFS Control Unit Fun
 #include "debug.h"
 #include "base.h"
 
+
+/******************\
+* Helper functions *
+\******************/
+
 /*
- * Get properties for a transmit queue
+ * Get number of pending frames
+ * for a specific queue [5211+]
  */
-int ath5k_hw_get_tx_queueprops(struct ath5k_hw *ah, int queue,
-		struct ath5k_txq_info *queue_info)
+u32 ath5k_hw_num_tx_pending(struct ath5k_hw *ah, unsigned int queue)
 {
-	memcpy(queue_info, &ah->ah_txq[queue], sizeof(struct ath5k_txq_info));
-	return 0;
+	u32 pending;
+	AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
+
+	/* Return if queue is declared inactive */
+	if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE)
+		return false;
+
+	/* XXX: How about AR5K_CFG_TXCNT ? */
+	if (ah->ah_version == AR5K_AR5210)
+		return false;
+
+	pending = ath5k_hw_reg_read(ah, AR5K_QUEUE_STATUS(queue));
+	pending &= AR5K_QCU_STS_FRMPENDCNT;
+
+	/* It's possible to have no frames pending even if TXE
+	 * is set. To indicate that q has not stopped return
+	 * true */
+	if (!pending && AR5K_REG_READ_Q(ah, AR5K_QCU_TXE, queue))
+		return true;
+
+	return pending;
+}
+
+/*
+ * Set a transmit queue inactive
+ */
+void ath5k_hw_release_tx_queue(struct ath5k_hw *ah, unsigned int queue)
+{
+	if (WARN_ON(queue >= ah->ah_capabilities.cap_queues.q_tx_num))
+		return;
+
+	/* This queue will be skipped in further operations */
+	ah->ah_txq[queue].tqi_type = AR5K_TX_QUEUE_INACTIVE;
+	/*For SIMR setup*/
+	AR5K_Q_DISABLE_BITS(ah->ah_txq_status, queue);
 }
 
 /*
@@ -50,6 +88,16 @@ static u16 ath5k_cw_validate(u16 cw_req)
 }
 
 /*
+ * Get properties for a transmit queue
+ */
+int ath5k_hw_get_tx_queueprops(struct ath5k_hw *ah, int queue,
+		struct ath5k_txq_info *queue_info)
+{
+	memcpy(queue_info, &ah->ah_txq[queue], sizeof(struct ath5k_txq_info));
+	return 0;
+}
+
+/*
  * Set properties for a transmit queue
  */
 int ath5k_hw_set_tx_queueprops(struct ath5k_hw *ah, int queue,
@@ -104,8 +152,8 @@ int ath5k_hw_setup_tx_queue(struct ath5k
 	/*
 	 * Get queue by type
 	 */
-	/*5210 only has 2 queues*/
-	if (ah->ah_version == AR5K_AR5210) {
+	/* 5210 only has 2 queues */
+	if (ah->ah_capabilities.cap_queues.q_tx_num == 2) {
 		switch (queue_type) {
 		case AR5K_TX_QUEUE_DATA:
 			queue = AR5K_TX_QUEUE_ID_NOQCU_DATA;
@@ -172,113 +220,18 @@ int ath5k_hw_setup_tx_queue(struct ath5k
 	return queue;
 }
 
-/*
- * Get number of pending frames
- * for a specific queue [5211+]
- */
-u32 ath5k_hw_num_tx_pending(struct ath5k_hw *ah, unsigned int queue)
-{
-	u32 pending;
-	AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
-
-	/* Return if queue is declared inactive */
-	if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE)
-		return false;
-
-	/* XXX: How about AR5K_CFG_TXCNT ? */
-	if (ah->ah_version == AR5K_AR5210)
-		return false;
 
-	pending = ath5k_hw_reg_read(ah, AR5K_QUEUE_STATUS(queue));
-	pending &= AR5K_QCU_STS_FRMPENDCNT;
-
-	/* It's possible to have no frames pending even if TXE
-	 * is set. To indicate that q has not stopped return
-	 * true */
-	if (!pending && AR5K_REG_READ_Q(ah, AR5K_QCU_TXE, queue))
-		return true;
-
-	return pending;
-}
-
-/*
- * Set a transmit queue inactive
- */
-void ath5k_hw_release_tx_queue(struct ath5k_hw *ah, unsigned int queue)
-{
-	if (WARN_ON(queue >= ah->ah_capabilities.cap_queues.q_tx_num))
-		return;
-
-	/* This queue will be skipped in further operations */
-	ah->ah_txq[queue].tqi_type = AR5K_TX_QUEUE_INACTIVE;
-	/*For SIMR setup*/
-	AR5K_Q_DISABLE_BITS(ah->ah_txq_status, queue);
-}
+/*******************************\
+* Single QCU/DCU initialization *
+\*******************************/
 
 /*
- * Set DFS properties for a transmit queue on DCU
+ * Set tx retry limits on DCU
  */
-int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue)
+static void ath5k_hw_set_tx_retry_limits(struct ath5k_hw *ah,
+					unsigned int queue)
 {
 	u32 retry_lg, retry_sh;
-	struct ath5k_txq_info *tq = &ah->ah_txq[queue];
-
-	AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
-
-	tq = &ah->ah_txq[queue];
-
-	if (tq->tqi_type == AR5K_TX_QUEUE_INACTIVE)
-		return 0;
-
-	if (ah->ah_version == AR5K_AR5210) {
-		/* Only handle data queues, others will be ignored */
-		if (tq->tqi_type != AR5K_TX_QUEUE_DATA)
-			return 0;
-
-		/* Set Slot time */
-		ath5k_hw_reg_write(ah, ah->ah_turbo ?
-			AR5K_INIT_SLOT_TIME_TURBO : AR5K_INIT_SLOT_TIME,
-			AR5K_SLOT_TIME);
-		/* Set ACK_CTS timeout */
-		ath5k_hw_reg_write(ah, ah->ah_turbo ?
-			AR5K_INIT_ACK_CTS_TIMEOUT_TURBO :
-			AR5K_INIT_ACK_CTS_TIMEOUT, AR5K_SLOT_TIME);
-		/* Set Transmit Latency */
-		ath5k_hw_reg_write(ah, ah->ah_turbo ?
-			AR5K_INIT_TRANSMIT_LATENCY_TURBO :
-			AR5K_INIT_TRANSMIT_LATENCY, AR5K_USEC_5210);
-
-		/* Set IFS0 */
-		if (ah->ah_turbo) {
-			 ath5k_hw_reg_write(ah, ((AR5K_INIT_SIFS_TURBO +
-				tq->tqi_aifs * AR5K_INIT_SLOT_TIME_TURBO) <<
-				AR5K_IFS0_DIFS_S) | AR5K_INIT_SIFS_TURBO,
-				AR5K_IFS0);
-		} else {
-			ath5k_hw_reg_write(ah, ((AR5K_INIT_SIFS +
-				tq->tqi_aifs * AR5K_INIT_SLOT_TIME) <<
-				AR5K_IFS0_DIFS_S) |
-				AR5K_INIT_SIFS, AR5K_IFS0);
-		}
-
-		/* Set IFS1 */
-		ath5k_hw_reg_write(ah, ah->ah_turbo ?
-			AR5K_INIT_PROTO_TIME_CNTRL_TURBO :
-			AR5K_INIT_PROTO_TIME_CNTRL, AR5K_IFS1);
-		/* Set AR5K_PHY_SETTLING */
-		ath5k_hw_reg_write(ah, ah->ah_turbo ?
-			(ath5k_hw_reg_read(ah, AR5K_PHY_SETTLING) & ~0x7F)
-			| 0x38 :
-			(ath5k_hw_reg_read(ah, AR5K_PHY_SETTLING) & ~0x7F)
-			| 0x1C,
-			AR5K_PHY_SETTLING);
-		/* Set Frame Control Register */
-		ath5k_hw_reg_write(ah, ah->ah_turbo ?
-			(AR5K_PHY_FRAME_CTL_INI | AR5K_PHY_TURBO_MODE |
-			AR5K_PHY_TURBO_SHORT | 0x2020) :
-			(AR5K_PHY_FRAME_CTL_INI | 0x1020),
-			AR5K_PHY_FRAME_CTL_5210);
-	}
 
 	/*
 	 * Calculate and set retry limits
@@ -293,8 +246,13 @@ int ath5k_hw_reset_tx_queue(struct ath5k
 		retry_sh = AR5K_INIT_SH_RETRY;
 	}
 
-	/*No QCU/DCU [5210]*/
+	/* Single data queue on AR5210 */
 	if (ah->ah_version == AR5K_AR5210) {
+		struct ath5k_txq_info *tq = &ah->ah_txq[queue];
+
+		if (queue > 0)
+			return;
+
 		ath5k_hw_reg_write(ah,
 			(tq->tqi_cw_min << AR5K_NODCU_RETRY_LMT_CW_MIN_S)
 			| AR5K_REG_SM(AR5K_INIT_SLG_RETRY,
@@ -304,8 +262,8 @@ int ath5k_hw_reset_tx_queue(struct ath5k
 			| AR5K_REG_SM(retry_lg, AR5K_NODCU_RETRY_LMT_LG_RETRY)
 			| AR5K_REG_SM(retry_sh, AR5K_NODCU_RETRY_LMT_SH_RETRY),
 			AR5K_NODCU_RETRY_LMT);
+	/* DCU on AR5211+ */
 	} else {
-		/*QCU/DCU [5211+]*/
 		ath5k_hw_reg_write(ah,
 			AR5K_REG_SM(AR5K_INIT_SLG_RETRY,
 				AR5K_DCU_RETRY_LMT_SLG_RETRY) |
@@ -314,219 +272,393 @@ int ath5k_hw_reset_tx_queue(struct ath5k
 			AR5K_REG_SM(retry_lg, AR5K_DCU_RETRY_LMT_LG_RETRY) |
 			AR5K_REG_SM(retry_sh, AR5K_DCU_RETRY_LMT_SH_RETRY),
 			AR5K_QUEUE_DFS_RETRY_LIMIT(queue));
+	}
+	return;
+}
 
-	/*===Rest is also for QCU/DCU only [5211+]===*/
+/**
+ * ath5k_hw_reset_tx_queue - Initialize a single hw queue
+ *
+ * @ah The &struct ath5k_hw
+ * @queue The hw queue number
+ *
+ * Set DFS properties for the given transmit queue on DCU
+ * and configures all queue-specific parameters.
+ */
+int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue)
+{
+	struct ath5k_txq_info *tq = &ah->ah_txq[queue];
 
-		/*
-		 * Set contention window (cw_min/cw_max)
-		 * and arbitrated interframe space (aifs)...
-		 */
-		ath5k_hw_reg_write(ah,
-			AR5K_REG_SM(tq->tqi_cw_min, AR5K_DCU_LCL_IFS_CW_MIN) |
-			AR5K_REG_SM(tq->tqi_cw_max, AR5K_DCU_LCL_IFS_CW_MAX) |
-			AR5K_REG_SM(tq->tqi_aifs, AR5K_DCU_LCL_IFS_AIFS),
-			AR5K_QUEUE_DFS_LOCAL_IFS(queue));
+	AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
 
-		/*
-		 * Set misc registers
-		 */
-		/* Enable DCU early termination for this queue */
-		AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
-					AR5K_QCU_MISC_DCU_EARLY);
+	tq = &ah->ah_txq[queue];
 
-		/* Enable DCU to wait for next fragment from QCU */
+	/* Skip if queue inactive or if we are on AR5210
+	 * that doesn't have QCU/DCU */
+	if ((ah->ah_version == AR5K_AR5210) ||
+	(tq->tqi_type == AR5K_TX_QUEUE_INACTIVE))
+		return 0;
+
+	/*
+	 * Set contention window (cw_min/cw_max)
+	 * and arbitrated interframe space (aifs)...
+	 */
+	ath5k_hw_reg_write(ah,
+		AR5K_REG_SM(tq->tqi_cw_min, AR5K_DCU_LCL_IFS_CW_MIN) |
+		AR5K_REG_SM(tq->tqi_cw_max, AR5K_DCU_LCL_IFS_CW_MAX) |
+		AR5K_REG_SM(tq->tqi_aifs, AR5K_DCU_LCL_IFS_AIFS),
+		AR5K_QUEUE_DFS_LOCAL_IFS(queue));
+
+	/*
+	 * Set tx retry limits for this queue
+	 */
+	ath5k_hw_set_tx_retry_limits(ah, queue);
+
+
+	/*
+	 * Set misc registers
+	 */
+
+	/* Enable DCU to wait for next fragment from QCU */
+	AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue),
+				AR5K_DCU_MISC_FRAG_WAIT);
+
+	/* On Maui and Spirit use the global seqnum on DCU */
+	if (ah->ah_mac_version < AR5K_SREV_AR5211)
 		AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue),
-					AR5K_DCU_MISC_FRAG_WAIT);
+					AR5K_DCU_MISC_SEQNUM_CTL);
 
-		/* On Maui and Spirit use the global seqnum on DCU */
-		if (ah->ah_mac_version < AR5K_SREV_AR5211)
-			AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue),
-						AR5K_DCU_MISC_SEQNUM_CTL);
+	/* Constant bit rate period */
+	if (tq->tqi_cbr_period) {
+		ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_cbr_period,
+					AR5K_QCU_CBRCFG_INTVAL) |
+					AR5K_REG_SM(tq->tqi_cbr_overflow_limit,
+					AR5K_QCU_CBRCFG_ORN_THRES),
+					AR5K_QUEUE_CBRCFG(queue));
 
-		if (tq->tqi_cbr_period) {
-			ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_cbr_period,
-				AR5K_QCU_CBRCFG_INTVAL) |
-				AR5K_REG_SM(tq->tqi_cbr_overflow_limit,
-				AR5K_QCU_CBRCFG_ORN_THRES),
-				AR5K_QUEUE_CBRCFG(queue));
+		AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
+					AR5K_QCU_MISC_FRSHED_CBR);
+
+		if (tq->tqi_cbr_overflow_limit)
 			AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
-				AR5K_QCU_MISC_FRSHED_CBR);
-			if (tq->tqi_cbr_overflow_limit)
-				AR5K_REG_ENABLE_BITS(ah,
-					AR5K_QUEUE_MISC(queue),
 					AR5K_QCU_MISC_CBR_THRES_ENABLE);
-		}
+	}
 
-		if (tq->tqi_ready_time &&
-		(tq->tqi_type != AR5K_TX_QUEUE_CAB))
-			ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_ready_time,
-				AR5K_QCU_RDYTIMECFG_INTVAL) |
-				AR5K_QCU_RDYTIMECFG_ENABLE,
-				AR5K_QUEUE_RDYTIMECFG(queue));
+	/* Ready time interval */
+	if (tq->tqi_ready_time && (tq->tqi_type != AR5K_TX_QUEUE_CAB))
+		ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_ready_time,
+					AR5K_QCU_RDYTIMECFG_INTVAL) |
+					AR5K_QCU_RDYTIMECFG_ENABLE,
+					AR5K_QUEUE_RDYTIMECFG(queue));
 
-		if (tq->tqi_burst_time) {
-			ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_burst_time,
-				AR5K_DCU_CHAN_TIME_DUR) |
-				AR5K_DCU_CHAN_TIME_ENABLE,
-				AR5K_QUEUE_DFS_CHANNEL_TIME(queue));
+	if (tq->tqi_burst_time) {
+		ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_burst_time,
+					AR5K_DCU_CHAN_TIME_DUR) |
+					AR5K_DCU_CHAN_TIME_ENABLE,
+					AR5K_QUEUE_DFS_CHANNEL_TIME(queue));
 
-			if (tq->tqi_flags
-			& AR5K_TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE)
-				AR5K_REG_ENABLE_BITS(ah,
-					AR5K_QUEUE_MISC(queue),
+		if (tq->tqi_flags & AR5K_TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE)
+			AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
 					AR5K_QCU_MISC_RDY_VEOL_POLICY);
-		}
+	}
 
-		if (tq->tqi_flags & AR5K_TXQ_FLAG_BACKOFF_DISABLE)
-			ath5k_hw_reg_write(ah, AR5K_DCU_MISC_POST_FR_BKOFF_DIS,
-				AR5K_QUEUE_DFS_MISC(queue));
+	/* Enable/disable Post frame backoff */
+	if (tq->tqi_flags & AR5K_TXQ_FLAG_BACKOFF_DISABLE)
+		ath5k_hw_reg_write(ah, AR5K_DCU_MISC_POST_FR_BKOFF_DIS,
+					AR5K_QUEUE_DFS_MISC(queue));
 
-		if (tq->tqi_flags & AR5K_TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE)
-			ath5k_hw_reg_write(ah, AR5K_DCU_MISC_BACKOFF_FRAG,
-				AR5K_QUEUE_DFS_MISC(queue));
+	/* Enable/disable fragmentation burst backoff */
+	if (tq->tqi_flags & AR5K_TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE)
+		ath5k_hw_reg_write(ah, AR5K_DCU_MISC_BACKOFF_FRAG,
+					AR5K_QUEUE_DFS_MISC(queue));
 
-		/*
-		 * Set registers by queue type
-		 */
-		switch (tq->tqi_type) {
-		case AR5K_TX_QUEUE_BEACON:
-			AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
+	/*
+	 * Set registers by queue type
+	 */
+	switch (tq->tqi_type) {
+	case AR5K_TX_QUEUE_BEACON:
+		AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
 				AR5K_QCU_MISC_FRSHED_DBA_GT |
 				AR5K_QCU_MISC_CBREXP_BCN_DIS |
 				AR5K_QCU_MISC_BCN_ENABLE);
 
-			AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue),
+		AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue),
 				(AR5K_DCU_MISC_ARBLOCK_CTL_GLOBAL <<
 				AR5K_DCU_MISC_ARBLOCK_CTL_S) |
 				AR5K_DCU_MISC_ARBLOCK_IGNORE |
 				AR5K_DCU_MISC_POST_FR_BKOFF_DIS |
 				AR5K_DCU_MISC_BCN_ENABLE);
-			break;
+		break;
 
-		case AR5K_TX_QUEUE_CAB:
-			/* XXX: use BCN_SENT_GT, if we can figure out how */
-			AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
-				AR5K_QCU_MISC_FRSHED_DBA_GT |
-				AR5K_QCU_MISC_CBREXP_DIS |
-				AR5K_QCU_MISC_CBREXP_BCN_DIS);
+	case AR5K_TX_QUEUE_CAB:
+		/* XXX: use BCN_SENT_GT, if we can figure out how */
+		AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
+					AR5K_QCU_MISC_FRSHED_DBA_GT |
+					AR5K_QCU_MISC_CBREXP_DIS |
+					AR5K_QCU_MISC_CBREXP_BCN_DIS);
 
-			ath5k_hw_reg_write(ah, ((tq->tqi_ready_time -
-				(AR5K_TUNE_SW_BEACON_RESP -
-				AR5K_TUNE_DMA_BEACON_RESP) -
+		ath5k_hw_reg_write(ah, ((tq->tqi_ready_time -
+					(AR5K_TUNE_SW_BEACON_RESP -
+					AR5K_TUNE_DMA_BEACON_RESP) -
 				AR5K_TUNE_ADDITIONAL_SWBA_BACKOFF) * 1024) |
-				AR5K_QCU_RDYTIMECFG_ENABLE,
-				AR5K_QUEUE_RDYTIMECFG(queue));
+					AR5K_QCU_RDYTIMECFG_ENABLE,
+					AR5K_QUEUE_RDYTIMECFG(queue));
 
-			AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue),
-				(AR5K_DCU_MISC_ARBLOCK_CTL_GLOBAL <<
-				AR5K_DCU_MISC_ARBLOCK_CTL_S));
-			break;
+		AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue),
+					(AR5K_DCU_MISC_ARBLOCK_CTL_GLOBAL <<
+					AR5K_DCU_MISC_ARBLOCK_CTL_S));
+		break;
 
-		case AR5K_TX_QUEUE_UAPSD:
-			AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
-				AR5K_QCU_MISC_CBREXP_DIS);
-			break;
+	case AR5K_TX_QUEUE_UAPSD:
+		AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
+					AR5K_QCU_MISC_CBREXP_DIS);
+		break;
 
-		case AR5K_TX_QUEUE_DATA:
-		default:
+	case AR5K_TX_QUEUE_DATA:
+	default:
 			break;
-		}
+	}
 
-		/* TODO: Handle frame compression */
+	/* TODO: Handle frame compression */
 
-		/*
-		 * Enable interrupts for this tx queue
-		 * in the secondary interrupt mask registers
-		 */
-		if (tq->tqi_flags & AR5K_TXQ_FLAG_TXOKINT_ENABLE)
-			AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txok, queue);
+	/*
+	 * Enable interrupts for this tx queue
+	 * in the secondary interrupt mask registers
+	 */
+	if (tq->tqi_flags & AR5K_TXQ_FLAG_TXOKINT_ENABLE)
+		AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txok, queue);
 
-		if (tq->tqi_flags & AR5K_TXQ_FLAG_TXERRINT_ENABLE)
-			AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txerr, queue);
+	if (tq->tqi_flags & AR5K_TXQ_FLAG_TXERRINT_ENABLE)
+		AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txerr, queue);
 
-		if (tq->tqi_flags & AR5K_TXQ_FLAG_TXURNINT_ENABLE)
-			AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txurn, queue);
+	if (tq->tqi_flags & AR5K_TXQ_FLAG_TXURNINT_ENABLE)
+		AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txurn, queue);
 
-		if (tq->tqi_flags & AR5K_TXQ_FLAG_TXDESCINT_ENABLE)
-			AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txdesc, queue);
+	if (tq->tqi_flags & AR5K_TXQ_FLAG_TXDESCINT_ENABLE)
+		AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txdesc, queue);
 
-		if (tq->tqi_flags & AR5K_TXQ_FLAG_TXEOLINT_ENABLE)
-			AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txeol, queue);
+	if (tq->tqi_flags & AR5K_TXQ_FLAG_TXEOLINT_ENABLE)
+		AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txeol, queue);
 
-		if (tq->tqi_flags & AR5K_TXQ_FLAG_CBRORNINT_ENABLE)
-			AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_cbrorn, queue);
+	if (tq->tqi_flags & AR5K_TXQ_FLAG_CBRORNINT_ENABLE)
+		AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_cbrorn, queue);
 
-		if (tq->tqi_flags & AR5K_TXQ_FLAG_CBRURNINT_ENABLE)
-			AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_cbrurn, queue);
+	if (tq->tqi_flags & AR5K_TXQ_FLAG_CBRURNINT_ENABLE)
+		AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_cbrurn, queue);
 
-		if (tq->tqi_flags & AR5K_TXQ_FLAG_QTRIGINT_ENABLE)
-			AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_qtrig, queue);
+	if (tq->tqi_flags & AR5K_TXQ_FLAG_QTRIGINT_ENABLE)
+		AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_qtrig, queue);
 
-		if (tq->tqi_flags & AR5K_TXQ_FLAG_TXNOFRMINT_ENABLE)
-			AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_nofrm, queue);
+	if (tq->tqi_flags & AR5K_TXQ_FLAG_TXNOFRMINT_ENABLE)
+		AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_nofrm, queue);
 
-		/* Update secondary interrupt mask registers */
+	/* Update secondary interrupt mask registers */
 
-		/* Filter out inactive queues */
-		ah->ah_txq_imr_txok &= ah->ah_txq_status;
-		ah->ah_txq_imr_txerr &= ah->ah_txq_status;
-		ah->ah_txq_imr_txurn &= ah->ah_txq_status;
-		ah->ah_txq_imr_txdesc &= ah->ah_txq_status;
-		ah->ah_txq_imr_txeol &= ah->ah_txq_status;
-		ah->ah_txq_imr_cbrorn &= ah->ah_txq_status;
-		ah->ah_txq_imr_cbrurn &= ah->ah_txq_status;
-		ah->ah_txq_imr_qtrig &= ah->ah_txq_status;
-		ah->ah_txq_imr_nofrm &= ah->ah_txq_status;
+	/* Filter out inactive queues */
+	ah->ah_txq_imr_txok &= ah->ah_txq_status;
+	ah->ah_txq_imr_txerr &= ah->ah_txq_status;
+	ah->ah_txq_imr_txurn &= ah->ah_txq_status;
+	ah->ah_txq_imr_txdesc &= ah->ah_txq_status;
+	ah->ah_txq_imr_txeol &= ah->ah_txq_status;
+	ah->ah_txq_imr_cbrorn &= ah->ah_txq_status;
+	ah->ah_txq_imr_cbrurn &= ah->ah_txq_status;
+	ah->ah_txq_imr_qtrig &= ah->ah_txq_status;
+	ah->ah_txq_imr_nofrm &= ah->ah_txq_status;
 
-		ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_txok,
-			AR5K_SIMR0_QCU_TXOK) |
-			AR5K_REG_SM(ah->ah_txq_imr_txdesc,
-			AR5K_SIMR0_QCU_TXDESC), AR5K_SIMR0);
-		ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_txerr,
-			AR5K_SIMR1_QCU_TXERR) |
-			AR5K_REG_SM(ah->ah_txq_imr_txeol,
-			AR5K_SIMR1_QCU_TXEOL), AR5K_SIMR1);
-		/* Update simr2 but don't overwrite rest simr2 settings */
-		AR5K_REG_DISABLE_BITS(ah, AR5K_SIMR2, AR5K_SIMR2_QCU_TXURN);
-		AR5K_REG_ENABLE_BITS(ah, AR5K_SIMR2,
-			AR5K_REG_SM(ah->ah_txq_imr_txurn,
-			AR5K_SIMR2_QCU_TXURN));
-		ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_cbrorn,
-			AR5K_SIMR3_QCBRORN) |
-			AR5K_REG_SM(ah->ah_txq_imr_cbrurn,
-			AR5K_SIMR3_QCBRURN), AR5K_SIMR3);
-		ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_qtrig,
-			AR5K_SIMR4_QTRIG), AR5K_SIMR4);
-		/* Set TXNOFRM_QCU for the queues with TXNOFRM enabled */
-		ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_nofrm,
-			AR5K_TXNOFRM_QCU), AR5K_TXNOFRM);
-		/* No queue has TXNOFRM enabled, disable the interrupt
-		 * by setting AR5K_TXNOFRM to zero */
-		if (ah->ah_txq_imr_nofrm == 0)
-			ath5k_hw_reg_write(ah, 0, AR5K_TXNOFRM);
+	ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_txok,
+					AR5K_SIMR0_QCU_TXOK) |
+					AR5K_REG_SM(ah->ah_txq_imr_txdesc,
+					AR5K_SIMR0_QCU_TXDESC),
+					AR5K_SIMR0);
 
-		/* Set QCU mask for this DCU to save power */
-		AR5K_REG_WRITE_Q(ah, AR5K_QUEUE_QCUMASK(queue), queue);
-	}
+	ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_txerr,
+					AR5K_SIMR1_QCU_TXERR) |
+					AR5K_REG_SM(ah->ah_txq_imr_txeol,
+					AR5K_SIMR1_QCU_TXEOL),
+					AR5K_SIMR1);
+
+	/* Update SIMR2 but don't overwrite rest simr2 settings */
+	AR5K_REG_DISABLE_BITS(ah, AR5K_SIMR2, AR5K_SIMR2_QCU_TXURN);
+	AR5K_REG_ENABLE_BITS(ah, AR5K_SIMR2,
+				AR5K_REG_SM(ah->ah_txq_imr_txurn,
+				AR5K_SIMR2_QCU_TXURN));
+
+	ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_cbrorn,
+				AR5K_SIMR3_QCBRORN) |
+				AR5K_REG_SM(ah->ah_txq_imr_cbrurn,
+				AR5K_SIMR3_QCBRURN),
+				AR5K_SIMR3);
+
+	ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_qtrig,
+				AR5K_SIMR4_QTRIG), AR5K_SIMR4);
+
+	/* Set TXNOFRM_QCU for the queues with TXNOFRM enabled */
+	ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_nofrm,
+				AR5K_TXNOFRM_QCU), AR5K_TXNOFRM);
+
+	/* No queue has TXNOFRM enabled, disable the interrupt
+	 * by setting AR5K_TXNOFRM to zero */
+	if (ah->ah_txq_imr_nofrm == 0)
+		ath5k_hw_reg_write(ah, 0, AR5K_TXNOFRM);
+
+	/* Set QCU mask for this DCU to save power */
+	AR5K_REG_WRITE_Q(ah, AR5K_QUEUE_QCUMASK(queue), queue);
 
 	return 0;
 }
 
-/*
- * Set slot time on DCU
+
+/**************************\
+* Global QCU/DCU functions *
+\**************************/
+
+/**
+ * ath5k_hw_set_ifs_intervals  - Set global inter-frame spaces on DCU
+ *
+ * @ah The &struct ath5k_hw
+ * @slot_time Slot time in us
+ *
+ * Sets the global IFS intervals on DCU (also works on AR5210) for
+ * the given slot time and the current bwmode.
  */
-int ath5k_hw_set_slot_time(struct ath5k_hw *ah, unsigned int slot_time)
+int ath5k_hw_set_ifs_intervals(struct ath5k_hw *ah, unsigned int slot_time)
 {
+	struct ieee80211_channel *channel = ah->ah_current_channel;
+	struct ath5k_softc *sc = ah->ah_sc;
+	struct ieee80211_rate *rate;
+	u32 ack_tx_time, eifs, eifs_clock, sifs, sifs_clock;
 	u32 slot_time_clock = ath5k_hw_htoclock(ah, slot_time);
 
 	if (slot_time < 6 || slot_time_clock > AR5K_SLOT_TIME_MAX)
 		return -EINVAL;
 
-	if (ah->ah_version == AR5K_AR5210)
-		ath5k_hw_reg_write(ah, slot_time_clock, AR5K_SLOT_TIME);
+	sifs = ath5k_hw_get_default_sifs(ah);
+	sifs_clock = ath5k_hw_htoclock(ah, sifs);
+
+	/* EIFS
+	 * Txtime of ack at lowest rate + SIFS + DIFS
+	 * (DIFS = SIFS + 2 * Slot time)
+	 *
+	 * Note: HAL has some predefined values for EIFS
+	 * Turbo:   (37 + 2 * 6)
+	 * Default: (74 + 2 * 9)
+	 * Half:    (149 + 2 * 13)
+	 * Quarter: (298 + 2 * 21)
+	 *
+	 * (74 + 2 * 6) for AR5210 default and turbo !
+	 *
+	 * According to the formula we have
+	 * ack_tx_time = 25 for turbo and
+	 * ack_tx_time = 42.5 * clock multiplier
+	 * for default/half/quarter.
+	 *
+	 * This can't be right, 42 is what we would get
+	 * from ath5k_hw_get_frame_dur_for_bwmode or
+	 * ieee80211_generic_frame_duration for zero frame
+	 * length and without SIFS !
+	 *
+	 * Also we have different lowest rate for 802.11a
+	 */
+	if (channel->hw_value & CHANNEL_5GHZ)
+		rate = &sc->sbands[IEEE80211_BAND_5GHZ].bitrates[0];
 	else
-		ath5k_hw_reg_write(ah, slot_time_clock, AR5K_DCU_GBL_IFS_SLOT);
+		rate = &sc->sbands[IEEE80211_BAND_2GHZ].bitrates[0];
+
+	ack_tx_time = ath5k_hw_get_frame_duration(ah, 10, rate);
+
+	/* ack_tx_time includes an SIFS already */
+	eifs = ack_tx_time + sifs + 2 * slot_time;
+	eifs_clock = ath5k_hw_htoclock(ah, eifs);
+
+	/* Set IFS settings on AR5210 */
+	if (ah->ah_version == AR5K_AR5210) {
+		u32 pifs, pifs_clock, difs, difs_clock;
+
+		/* Set slot time */
+		ath5k_hw_reg_write(ah, slot_time_clock, AR5K_SLOT_TIME);
+
+		/* Set EIFS */
+		eifs_clock = AR5K_REG_SM(eifs_clock, AR5K_IFS1_EIFS);
+
+		/* PIFS = Slot time + SIFS */
+		pifs = slot_time + sifs;
+		pifs_clock = ath5k_hw_htoclock(ah, pifs);
+		pifs_clock = AR5K_REG_SM(pifs_clock, AR5K_IFS1_PIFS);
+
+		/* DIFS = SIFS + 2 * Slot time */
+		difs = sifs + 2 * slot_time;
+		difs_clock = ath5k_hw_htoclock(ah, difs);
+
+		/* Set SIFS/DIFS */
+		ath5k_hw_reg_write(ah, (difs_clock <<
+				AR5K_IFS0_DIFS_S) | sifs_clock,
+				AR5K_IFS0);
+
+		/* Set PIFS/EIFS and preserve AR5K_INIT_CARR_SENSE_EN */
+		ath5k_hw_reg_write(ah, pifs_clock | eifs_clock |
+				(AR5K_INIT_CARR_SENSE_EN << AR5K_IFS1_CS_EN_S),
+				AR5K_IFS1);
+
+		return 0;
+	}
+
+	/* Set IFS slot time */
+	ath5k_hw_reg_write(ah, slot_time_clock, AR5K_DCU_GBL_IFS_SLOT);
+
+	/* Set EIFS interval */
+	ath5k_hw_reg_write(ah, eifs_clock, AR5K_DCU_GBL_IFS_EIFS);
+
+	/* Set SIFS interval in usecs */
+	AR5K_REG_WRITE_BITS(ah, AR5K_DCU_GBL_IFS_MISC,
+				AR5K_DCU_GBL_IFS_MISC_SIFS_DUR_USEC,
+				sifs);
+
+	/* Set SIFS interval in clock cycles */
+	ath5k_hw_reg_write(ah, sifs_clock, AR5K_DCU_GBL_IFS_SIFS);
 
 	return 0;
 }
 
+
+int ath5k_hw_init_queues(struct ath5k_hw *ah)
+{
+	int i, ret;
+
+	/* TODO: HW Compression support for data queues */
+	/* TODO: Burst prefetch for data queues */
+
+	/*
+	 * Reset queues and start beacon timers at the end of the reset routine
+	 * This also sets QCU mask on each DCU for 1:1 qcu to dcu mapping
+	 * Note: If we want we can assign multiple qcus on one dcu.
+	 */
+	if (ah->ah_version != AR5K_AR5210)
+		for (i = 0; i < ah->ah_capabilities.cap_queues.q_tx_num; i++) {
+			ret = ath5k_hw_reset_tx_queue(ah, i);
+			if (ret) {
+				ATH5K_ERR(ah->ah_sc,
+					"failed to reset TX queue #%d\n", i);
+				return ret;
+			}
+		}
+	else
+		/* No QCU/DCU on AR5210, just set tx
+		 * retry limits. We set IFS parameters
+		 * on ath5k_hw_set_ifs_intervals */
+		ath5k_hw_set_tx_retry_limits(ah, 0);
+
+	/* Set the turbo flag when operating on 40MHz */
+	if (ah->ah_bwmode == AR5K_BWMODE_40MHZ)
+		AR5K_REG_ENABLE_BITS(ah, AR5K_DCU_GBL_IFS_MISC,
+				AR5K_DCU_GBL_IFS_MISC_TURBO_MODE);
+
+	/* If we didn't set IFS timings through
+	 * ath5k_hw_set_coverage_class make sure
+	 * we set them here */
+	if (!ah->ah_coverage_class) {
+		unsigned int slot_time = ath5k_hw_get_default_slottime(ah);
+		ath5k_hw_set_ifs_intervals(ah, slot_time);
+	}
+
+	return 0;
+}
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath5k/reg.h linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath5k/reg.h
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath5k/reg.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath5k/reg.h	2011-03-14 21:20:32.000000000 -0400
@@ -787,6 +787,7 @@
 #define	AR5K_DCU_GBL_IFS_MISC_LFSR_SLICE	0x00000007	/* LFSR Slice Select */
 #define	AR5K_DCU_GBL_IFS_MISC_TURBO_MODE	0x00000008	/* Turbo mode */
 #define	AR5K_DCU_GBL_IFS_MISC_SIFS_DUR_USEC	0x000003f0	/* SIFS Duration mask */
+#define	AR5K_DCU_GBL_IFS_MISC_SIFS_DUR_USEC_S	4
 #define	AR5K_DCU_GBL_IFS_MISC_USEC_DUR		0x000ffc00	/* USEC Duration mask */
 #define	AR5K_DCU_GBL_IFS_MISC_USEC_DUR_S	10
 #define	AR5K_DCU_GBL_IFS_MISC_DCU_ARB_DELAY	0x00300000	/* DCU Arbiter delay mask */
@@ -1063,7 +1064,7 @@
 /*
  * EEPROM command register
  */
-#define AR5K_EEPROM_CMD		0x6008			/* Register Addres */
+#define AR5K_EEPROM_CMD		0x6008			/* Register Address */
 #define AR5K_EEPROM_CMD_READ	0x00000001	/* EEPROM read */
 #define AR5K_EEPROM_CMD_WRITE	0x00000002	/* EEPROM write */
 #define AR5K_EEPROM_CMD_RESET	0x00000004	/* EEPROM reset */
@@ -1083,7 +1084,7 @@
 /*
  * EEPROM config register
  */
-#define AR5K_EEPROM_CFG			0x6010			/* Register Addres */
+#define AR5K_EEPROM_CFG			0x6010			/* Register Address */
 #define AR5K_EEPROM_CFG_SIZE		0x00000003		/* Size determination override */
 #define AR5K_EEPROM_CFG_SIZE_AUTO	0
 #define AR5K_EEPROM_CFG_SIZE_4KBIT	1
@@ -1125,7 +1126,7 @@
  * Second station id register (Upper 16 bits of MAC address + PCU settings)
  */
 #define AR5K_STA_ID1			0x8004			/* Register Address */
-#define	AR5K_STA_ID1_ADDR_U16		0x0000ffff	/* Upper 16 bits of MAC addres */
+#define	AR5K_STA_ID1_ADDR_U16		0x0000ffff	/* Upper 16 bits of MAC address */
 #define AR5K_STA_ID1_AP			0x00010000	/* Set AP mode */
 #define AR5K_STA_ID1_ADHOC		0x00020000	/* Set Ad-Hoc mode */
 #define AR5K_STA_ID1_PWR_SV		0x00040000	/* Power save reporting */
@@ -1311,7 +1312,7 @@
 #define AR5K_IFS1_EIFS		0x03fff000
 #define AR5K_IFS1_EIFS_S	12
 #define AR5K_IFS1_CS_EN		0x04000000
-
+#define AR5K_IFS1_CS_EN_S	26
 
 /*
  * CFP duration register
@@ -2058,6 +2059,7 @@
 
 #define AR5K_PHY_SCAL			0x9878
 #define AR5K_PHY_SCAL_32MHZ		0x0000000e
+#define	AR5K_PHY_SCAL_32MHZ_5311	0x00000008
 #define	AR5K_PHY_SCAL_32MHZ_2417	0x0000000a
 #define	AR5K_PHY_SCAL_32MHZ_HB63	0x00000032
 
@@ -2244,6 +2246,8 @@
 #define	AR5K_PHY_FRAME_CTL		(ah->ah_version == AR5K_AR5210 ? \
 					AR5K_PHY_FRAME_CTL_5210 : AR5K_PHY_FRAME_CTL_5211)
 /*---[5111+]---*/
+#define	AR5K_PHY_FRAME_CTL_WIN_LEN	0x00000003	/* Force window length (?) */
+#define	AR5K_PHY_FRAME_CTL_WIN_LEN_S	0
 #define	AR5K_PHY_FRAME_CTL_TX_CLIP	0x00000038	/* Mask for tx clip (?) */
 #define	AR5K_PHY_FRAME_CTL_TX_CLIP_S	3
 #define	AR5K_PHY_FRAME_CTL_PREP_CHINFO	0x00010000	/* Prepend chan info */
@@ -2558,3 +2562,28 @@
  */
 #define AR5K_PHY_PDADC_TXPOWER_BASE	0xa280
 #define	AR5K_PHY_PDADC_TXPOWER(_n)	(AR5K_PHY_PDADC_TXPOWER_BASE + ((_n) << 2))
+
+/*
+ * Platform registers for WiSoC
+ */
+#define AR5K_AR5312_RESET		0xbc003020
+#define AR5K_AR5312_RESET_BB0_COLD	0x00000004
+#define AR5K_AR5312_RESET_BB1_COLD	0x00000200
+#define AR5K_AR5312_RESET_WMAC0		0x00002000
+#define AR5K_AR5312_RESET_BB0_WARM	0x00004000
+#define AR5K_AR5312_RESET_WMAC1		0x00020000
+#define AR5K_AR5312_RESET_BB1_WARM	0x00040000
+
+#define AR5K_AR5312_ENABLE		0xbc003080
+#define AR5K_AR5312_ENABLE_WLAN0    0x00000001
+#define AR5K_AR5312_ENABLE_WLAN1    0x00000008
+
+#define AR5K_AR2315_RESET		0xb1000004
+#define AR5K_AR2315_RESET_WMAC		0x00000001
+#define AR5K_AR2315_RESET_BB_WARM	0x00000002
+
+#define AR5K_AR2315_AHB_ARB_CTL		0xb1000008
+#define AR5K_AR2315_AHB_ARB_CTL_WLAN	0x00000002
+
+#define AR5K_AR2315_BYTESWAP	0xb100000c
+#define AR5K_AR2315_BYTESWAP_WMAC	0x00000002
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath5k/reset.c linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath5k/reset.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath5k/reset.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath5k/reset.c	2011-03-14 21:20:32.000000000 -0400
@@ -27,11 +27,17 @@
 
 #include <linux/pci.h> 		/* To determine if a card is pci-e */
 #include <linux/log2.h>
+#include <linux/platform_device.h>
 #include "ath5k.h"
 #include "reg.h"
 #include "base.h"
 #include "debug.h"
 
+
+/******************\
+* Helper functions *
+\******************/
+
 /*
  * Check if a register write has been completed
  */
@@ -53,146 +59,267 @@ int ath5k_hw_register_timeout(struct ath
 	return (i <= 0) ? -EAGAIN : 0;
 }
 
+
+/*************************\
+* Clock related functions *
+\*************************/
+
 /**
- * ath5k_hw_write_ofdm_timings - set OFDM timings on AR5212
- *
- * @ah: the &struct ath5k_hw
- * @channel: the currently set channel upon reset
+ * ath5k_hw_htoclock - Translate usec to hw clock units
  *
- * Write the delta slope coefficient (used on pilot tracking ?) for OFDM
- * operation on the AR5212 upon reset. This is a helper for ath5k_hw_reset().
+ * @ah: The &struct ath5k_hw
+ * @usec: value in microseconds
+ */
+unsigned int ath5k_hw_htoclock(struct ath5k_hw *ah, unsigned int usec)
+{
+	struct ath_common *common = ath5k_hw_common(ah);
+	return usec * common->clockrate;
+}
+
+/**
+ * ath5k_hw_clocktoh - Translate hw clock units to usec
+ * @clock: value in hw clock units
+ */
+unsigned int ath5k_hw_clocktoh(struct ath5k_hw *ah, unsigned int clock)
+{
+	struct ath_common *common = ath5k_hw_common(ah);
+	return clock / common->clockrate;
+}
+
+/**
+ * ath5k_hw_init_core_clock - Initialize core clock
  *
- * Since delta slope is floating point we split it on its exponent and
- * mantissa and provide these values on hw.
+ * @ah The &struct ath5k_hw
  *
- * For more infos i think this patent is related
- * http://www.freepatentsonline.com/7184495.html
+ * Initialize core clock parameters (usec, usec32, latencies etc).
  */
-static inline int ath5k_hw_write_ofdm_timings(struct ath5k_hw *ah,
-	struct ieee80211_channel *channel)
+static void ath5k_hw_init_core_clock(struct ath5k_hw *ah)
 {
-	/* Get exponent and mantissa and set it */
-	u32 coef_scaled, coef_exp, coef_man,
-		ds_coef_exp, ds_coef_man, clock;
+	struct ieee80211_channel *channel = ah->ah_current_channel;
+	struct ath_common *common = ath5k_hw_common(ah);
+	u32 usec_reg, txlat, rxlat, usec, clock, sclock, txf2txs;
 
-	BUG_ON(!(ah->ah_version == AR5K_AR5212) ||
-		!(channel->hw_value & CHANNEL_OFDM));
+	/*
+	 * Set core clock frequency
+	 */
+	if (channel->hw_value & CHANNEL_5GHZ)
+		clock = 40; /* 802.11a */
+	else if (channel->hw_value & CHANNEL_CCK)
+		clock = 22; /* 802.11b */
+	else
+		clock = 44; /* 802.11g */
 
-	/* Get coefficient
-	 * ALGO: coef = (5 * clock / carrier_freq) / 2
-	 * we scale coef by shifting clock value by 24 for
-	 * better precision since we use integers */
-	/* TODO: Half/quarter rate */
-	clock =  (channel->hw_value & CHANNEL_TURBO) ? 80 : 40;
-	coef_scaled = ((5 * (clock << 24)) / 2) / channel->center_freq;
+	/* Use clock multiplier for non-default
+	 * bwmode */
+	switch (ah->ah_bwmode) {
+	case AR5K_BWMODE_40MHZ:
+		clock *= 2;
+		break;
+	case AR5K_BWMODE_10MHZ:
+		clock /= 2;
+		break;
+	case AR5K_BWMODE_5MHZ:
+		clock /= 4;
+		break;
+	default:
+		break;
+	}
 
-	/* Get exponent
-	 * ALGO: coef_exp = 14 - highest set bit position */
-	coef_exp = ilog2(coef_scaled);
+	common->clockrate = clock;
 
-	/* Doesn't make sense if it's zero*/
-	if (!coef_scaled || !coef_exp)
-		return -EINVAL;
+	/*
+	 * Set USEC parameters
+	 */
+	/* Set USEC counter on PCU*/
+	usec = clock - 1;
+	usec = AR5K_REG_SM(usec, AR5K_USEC_1);
 
-	/* Note: we've shifted coef_scaled by 24 */
-	coef_exp = 14 - (coef_exp - 24);
+	/* Set usec duration on DCU */
+	if (ah->ah_version != AR5K_AR5210)
+		AR5K_REG_WRITE_BITS(ah, AR5K_DCU_GBL_IFS_MISC,
+					AR5K_DCU_GBL_IFS_MISC_USEC_DUR,
+					clock);
 
+	/* Set 32MHz USEC counter */
+	if ((ah->ah_radio == AR5K_RF5112) ||
+		(ah->ah_radio == AR5K_RF5413) ||
+		(ah->ah_radio == AR5K_RF2316) ||
+		(ah->ah_radio == AR5K_RF2317))
+	/* Remain on 40MHz clock ? */
+		sclock = 40 - 1;
+	else
+		sclock = 32 - 1;
+	sclock = AR5K_REG_SM(sclock, AR5K_USEC_32);
 
-	/* Get mantissa (significant digits)
-	 * ALGO: coef_mant = floor(coef_scaled* 2^coef_exp+0.5) */
-	coef_man = coef_scaled +
-		(1 << (24 - coef_exp - 1));
+	/*
+	 * Set tx/rx latencies
+	 */
+	usec_reg = ath5k_hw_reg_read(ah, AR5K_USEC_5211);
+	txlat = AR5K_REG_MS(usec_reg, AR5K_USEC_TX_LATENCY_5211);
+	rxlat = AR5K_REG_MS(usec_reg, AR5K_USEC_RX_LATENCY_5211);
 
-	/* Calculate delta slope coefficient exponent
-	 * and mantissa (remove scaling) and set them on hw */
-	ds_coef_man = coef_man >> (24 - coef_exp);
-	ds_coef_exp = coef_exp - 16;
+	/*
+	 * 5210 initvals don't include usec settings
+	 * so we need to use magic values here for
+	 * tx/rx latencies
+	 */
+	if (ah->ah_version == AR5K_AR5210) {
+		/* same for turbo */
+		txlat = AR5K_INIT_TX_LATENCY_5210;
+		rxlat = AR5K_INIT_RX_LATENCY_5210;
+	}
 
-	AR5K_REG_WRITE_BITS(ah, AR5K_PHY_TIMING_3,
-		AR5K_PHY_TIMING_3_DSC_MAN, ds_coef_man);
-	AR5K_REG_WRITE_BITS(ah, AR5K_PHY_TIMING_3,
-		AR5K_PHY_TIMING_3_DSC_EXP, ds_coef_exp);
+	if (ah->ah_mac_srev < AR5K_SREV_AR5211) {
+		/* 5311 has different tx/rx latency masks
+		 * from 5211, since we deal 5311 the same
+		 * as 5211 when setting initvals, shift
+		 * values here to their proper locations
+		 *
+		 * Note: Initvals indicate tx/rx/ latencies
+		 * are the same for turbo mode */
+		txlat = AR5K_REG_SM(txlat, AR5K_USEC_TX_LATENCY_5210);
+		rxlat = AR5K_REG_SM(rxlat, AR5K_USEC_RX_LATENCY_5210);
+	} else
+	switch (ah->ah_bwmode) {
+	case AR5K_BWMODE_10MHZ:
+		txlat = AR5K_REG_SM(txlat * 2,
+				AR5K_USEC_TX_LATENCY_5211);
+		rxlat = AR5K_REG_SM(AR5K_INIT_RX_LAT_MAX,
+				AR5K_USEC_RX_LATENCY_5211);
+		txf2txs = AR5K_INIT_TXF2TXD_START_DELAY_10MHZ;
+		break;
+	case AR5K_BWMODE_5MHZ:
+		txlat = AR5K_REG_SM(txlat * 4,
+				AR5K_USEC_TX_LATENCY_5211);
+		rxlat = AR5K_REG_SM(AR5K_INIT_RX_LAT_MAX,
+				AR5K_USEC_RX_LATENCY_5211);
+		txf2txs = AR5K_INIT_TXF2TXD_START_DELAY_5MHZ;
+		break;
+	case AR5K_BWMODE_40MHZ:
+		txlat = AR5K_INIT_TX_LAT_MIN;
+		rxlat = AR5K_REG_SM(rxlat / 2,
+				AR5K_USEC_RX_LATENCY_5211);
+		txf2txs = AR5K_INIT_TXF2TXD_START_DEFAULT;
+		break;
+	default:
+		break;
+	}
 
-	return 0;
-}
+	usec_reg = (usec | sclock | txlat | rxlat);
+	ath5k_hw_reg_write(ah, usec_reg, AR5K_USEC);
 
+	/* On 5112 set tx frane to tx data start delay */
+	if (ah->ah_radio == AR5K_RF5112) {
+		AR5K_REG_WRITE_BITS(ah, AR5K_PHY_RF_CTL2,
+					AR5K_PHY_RF_CTL2_TXF2TXD_START,
+					txf2txs);
+	}
+}
 
 /*
- * index into rates for control rates, we can set it up like this because
- * this is only used for AR5212 and we know it supports G mode
- */
-static const unsigned int control_rates[] =
-	{ 0, 1, 1, 1, 4, 4, 6, 6, 8, 8, 8, 8 };
-
-/**
- * ath5k_hw_write_rate_duration - fill rate code to duration table
- *
- * @ah: the &struct ath5k_hw
- * @mode: one of enum ath5k_driver_mode
- *
- * Write the rate code to duration table upon hw reset. This is a helper for
- * ath5k_hw_reset(). It seems all this is doing is setting an ACK timeout on
- * the hardware, based on current mode, for each rate. The rates which are
- * capable of short preamble (802.11b rates 2Mbps, 5.5Mbps, and 11Mbps) have
- * different rate code so we write their value twice (one for long preample
- * and one for short).
+ * If there is an external 32KHz crystal available, use it
+ * as ref. clock instead of 32/40MHz clock and baseband clocks
+ * to save power during sleep or restore normal 32/40MHz
+ * operation.
  *
- * Note: Band doesn't matter here, if we set the values for OFDM it works
- * on both a and g modes. So all we have to do is set values for all g rates
- * that include all OFDM and CCK rates. If we operate in turbo or xr/half/
- * quarter rate mode, we need to use another set of bitrates (that's why we
- * need the mode parameter) but we don't handle these proprietary modes yet.
+ * XXX: When operating on 32KHz certain PHY registers (27 - 31,
+ *	123 - 127) require delay on access.
  */
-static inline void ath5k_hw_write_rate_duration(struct ath5k_hw *ah,
-       unsigned int mode)
+static void ath5k_hw_set_sleep_clock(struct ath5k_hw *ah, bool enable)
 {
-	struct ath5k_softc *sc = ah->ah_sc;
-	struct ieee80211_rate *rate;
-	unsigned int i;
+	struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+	u32 scal, spending;
 
-	/* Write rate duration table */
-	for (i = 0; i < sc->sbands[IEEE80211_BAND_2GHZ].n_bitrates; i++) {
-		u32 reg;
-		u16 tx_time;
+	/* Only set 32KHz settings if we have an external
+	 * 32KHz crystal present */
+	if ((AR5K_EEPROM_HAS32KHZCRYSTAL(ee->ee_misc1) ||
+	AR5K_EEPROM_HAS32KHZCRYSTAL_OLD(ee->ee_misc1)) &&
+	enable) {
 
-		rate = &sc->sbands[IEEE80211_BAND_2GHZ].bitrates[control_rates[i]];
+		/* 1 usec/cycle */
+		AR5K_REG_WRITE_BITS(ah, AR5K_USEC_5211, AR5K_USEC_32, 1);
+		/* Set up tsf increment on each cycle */
+		AR5K_REG_WRITE_BITS(ah, AR5K_TSF_PARM, AR5K_TSF_PARM_INC, 61);
 
-		/* Set ACK timeout */
-		reg = AR5K_RATE_DUR(rate->hw_value);
+		/* Set baseband sleep control registers
+		 * and sleep control rate */
+		ath5k_hw_reg_write(ah, 0x1f, AR5K_PHY_SCR);
 
-		/* An ACK frame consists of 10 bytes. If you add the FCS,
-		 * which ieee80211_generic_frame_duration() adds,
-		 * its 14 bytes. Note we use the control rate and not the
-		 * actual rate for this rate. See mac80211 tx.c
-		 * ieee80211_duration() for a brief description of
-		 * what rate we should choose to TX ACKs. */
-		tx_time = le16_to_cpu(ieee80211_generic_frame_duration(sc->hw,
-							NULL, 10, rate));
+		if ((ah->ah_radio == AR5K_RF5112) ||
+		(ah->ah_radio == AR5K_RF5413) ||
+		(ah->ah_radio == AR5K_RF2316) ||
+		(ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4)))
+			spending = 0x14;
+		else
+			spending = 0x18;
+		ath5k_hw_reg_write(ah, spending, AR5K_PHY_SPENDING);
 
-		ath5k_hw_reg_write(ah, tx_time, reg);
+		if ((ah->ah_radio == AR5K_RF5112) ||
+		(ah->ah_radio == AR5K_RF5413) ||
+		(ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))) {
+			ath5k_hw_reg_write(ah, 0x26, AR5K_PHY_SLMT);
+			ath5k_hw_reg_write(ah, 0x0d, AR5K_PHY_SCAL);
+			ath5k_hw_reg_write(ah, 0x07, AR5K_PHY_SCLOCK);
+			ath5k_hw_reg_write(ah, 0x3f, AR5K_PHY_SDELAY);
+			AR5K_REG_WRITE_BITS(ah, AR5K_PCICFG,
+				AR5K_PCICFG_SLEEP_CLOCK_RATE, 0x02);
+		} else {
+			ath5k_hw_reg_write(ah, 0x0a, AR5K_PHY_SLMT);
+			ath5k_hw_reg_write(ah, 0x0c, AR5K_PHY_SCAL);
+			ath5k_hw_reg_write(ah, 0x03, AR5K_PHY_SCLOCK);
+			ath5k_hw_reg_write(ah, 0x20, AR5K_PHY_SDELAY);
+			AR5K_REG_WRITE_BITS(ah, AR5K_PCICFG,
+				AR5K_PCICFG_SLEEP_CLOCK_RATE, 0x03);
+		}
 
-		if (!(rate->flags & IEEE80211_RATE_SHORT_PREAMBLE))
-			continue;
+		/* Enable sleep clock operation */
+		AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG,
+				AR5K_PCICFG_SLEEP_CLOCK_EN);
 
-		/*
-		 * We're not distinguishing short preamble here,
-		 * This is true, all we'll get is a longer value here
-		 * which is not necessarilly bad. We could use
-		 * export ieee80211_frame_duration() but that needs to be
-		 * fixed first to be properly used by mac802111 drivers:
-		 *
-		 *  - remove erp stuff and let the routine figure ofdm
-		 *    erp rates
-		 *  - remove passing argument ieee80211_local as
-		 *    drivers don't have access to it
-		 *  - move drivers using ieee80211_generic_frame_duration()
-		 *    to this
-		 */
-		ath5k_hw_reg_write(ah, tx_time,
-			reg + (AR5K_SET_SHORT_PREAMBLE << 2));
+	} else {
+
+		/* Disable sleep clock operation and
+		 * restore default parameters */
+		AR5K_REG_DISABLE_BITS(ah, AR5K_PCICFG,
+				AR5K_PCICFG_SLEEP_CLOCK_EN);
+
+		AR5K_REG_WRITE_BITS(ah, AR5K_PCICFG,
+				AR5K_PCICFG_SLEEP_CLOCK_RATE, 0);
+
+		/* Set DAC/ADC delays */
+		ath5k_hw_reg_write(ah, 0x1f, AR5K_PHY_SCR);
+		ath5k_hw_reg_write(ah, AR5K_PHY_SLMT_32MHZ, AR5K_PHY_SLMT);
+
+		if (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))
+			scal = AR5K_PHY_SCAL_32MHZ_2417;
+		else if (ee->ee_is_hb63)
+			scal = AR5K_PHY_SCAL_32MHZ_HB63;
+		else
+			scal = AR5K_PHY_SCAL_32MHZ;
+		ath5k_hw_reg_write(ah, scal, AR5K_PHY_SCAL);
+
+		ath5k_hw_reg_write(ah, AR5K_PHY_SCLOCK_32MHZ, AR5K_PHY_SCLOCK);
+		ath5k_hw_reg_write(ah, AR5K_PHY_SDELAY_32MHZ, AR5K_PHY_SDELAY);
+
+		if ((ah->ah_radio == AR5K_RF5112) ||
+		(ah->ah_radio == AR5K_RF5413) ||
+		(ah->ah_radio == AR5K_RF2316) ||
+		(ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4)))
+			spending = 0x14;
+		else
+			spending = 0x18;
+		ath5k_hw_reg_write(ah, spending, AR5K_PHY_SPENDING);
+
+		/* Set up tsf increment on each cycle */
+		AR5K_REG_WRITE_BITS(ah, AR5K_TSF_PARM, AR5K_TSF_PARM_INC, 1);
 	}
 }
 
+
+/*********************\
+* Reset/Sleep control *
+\*********************/
+
 /*
  * Reset chipset
  */
@@ -236,6 +363,64 @@ static int ath5k_hw_nic_reset(struct ath
 }
 
 /*
+ * Reset AHB chipset
+ * AR5K_RESET_CTL_PCU flag resets WMAC
+ * AR5K_RESET_CTL_BASEBAND flag resets WBB
+ */
+static int ath5k_hw_wisoc_reset(struct ath5k_hw *ah, u32 flags)
+{
+	u32 mask = flags ? flags : ~0U;
+	volatile u32 *reg;
+	u32 regval;
+	u32 val = 0;
+
+	/* ah->ah_mac_srev is not available at this point yet */
+	if (ah->ah_sc->devid >= AR5K_SREV_AR2315_R6) {
+		reg = (u32 *) AR5K_AR2315_RESET;
+		if (mask & AR5K_RESET_CTL_PCU)
+			val |= AR5K_AR2315_RESET_WMAC;
+		if (mask & AR5K_RESET_CTL_BASEBAND)
+			val |= AR5K_AR2315_RESET_BB_WARM;
+	} else {
+		reg = (u32 *) AR5K_AR5312_RESET;
+		if (to_platform_device(ah->ah_sc->dev)->id == 0) {
+			if (mask & AR5K_RESET_CTL_PCU)
+				val |= AR5K_AR5312_RESET_WMAC0;
+			if (mask & AR5K_RESET_CTL_BASEBAND)
+				val |= AR5K_AR5312_RESET_BB0_COLD |
+				       AR5K_AR5312_RESET_BB0_WARM;
+		} else {
+			if (mask & AR5K_RESET_CTL_PCU)
+				val |= AR5K_AR5312_RESET_WMAC1;
+			if (mask & AR5K_RESET_CTL_BASEBAND)
+				val |= AR5K_AR5312_RESET_BB1_COLD |
+				       AR5K_AR5312_RESET_BB1_WARM;
+		}
+	}
+
+	/* Put BB/MAC into reset */
+	regval = __raw_readl(reg);
+	__raw_writel(regval | val, reg);
+	regval = __raw_readl(reg);
+	udelay(100);
+
+	/* Bring BB/MAC out of reset */
+	__raw_writel(regval & ~val, reg);
+	regval = __raw_readl(reg);
+
+	/*
+	 * Reset configuration register (for hw byte-swap). Note that this
+	 * is only set for big endian. We do the necessary magic in
+	 * AR5K_INIT_CFG.
+	 */
+	if ((flags & AR5K_RESET_CTL_PCU) == 0)
+		ath5k_hw_reg_write(ah, AR5K_INIT_CFG, AR5K_CFG);
+
+	return 0;
+}
+
+
+/*
  * Sleep control
  */
 static int ath5k_hw_set_power(struct ath5k_hw *ah, enum ath5k_power_mode mode,
@@ -334,6 +519,9 @@ int ath5k_hw_on_hold(struct ath5k_hw *ah
 	u32 bus_flags;
 	int ret;
 
+	if (ath5k_get_bus_type(ah) == ATH_AHB)
+		return 0;
+
 	/* Make sure device is awake */
 	ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0);
 	if (ret) {
@@ -349,7 +537,7 @@ int ath5k_hw_on_hold(struct ath5k_hw *ah
 	 * we ingore that flag for PCI-E cards. On PCI cards
 	 * this flag gets cleared after 64 PCI clocks.
 	 */
-	bus_flags = (pdev->is_pcie) ? 0 : AR5K_RESET_CTL_PCI;
+	bus_flags = (pdev && pci_is_pcie(pdev)) ? 0 : AR5K_RESET_CTL_PCI;
 
 	if (ah->ah_version == AR5K_AR5210) {
 		ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU |
@@ -378,7 +566,6 @@ int ath5k_hw_on_hold(struct ath5k_hw *ah
 
 /*
  * Bring up MAC + PHY Chips and program PLL
- * TODO: Half/Quarter rate support
  */
 int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial)
 {
@@ -390,11 +577,13 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw
 	mode = 0;
 	clock = 0;
 
-	/* Wakeup the device */
-	ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0);
-	if (ret) {
-		ATH5K_ERR(ah->ah_sc, "failed to wakeup the MAC Chip\n");
-		return ret;
+	if ((ath5k_get_bus_type(ah) != ATH_AHB) || !initial) {
+		/* Wakeup the device */
+		ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0);
+		if (ret) {
+			ATH5K_ERR(ah->ah_sc, "failed to wakeup the MAC Chip\n");
+			return ret;
+		}
 	}
 
 	/*
@@ -405,7 +594,7 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw
 	 * we ingore that flag for PCI-E cards. On PCI cards
 	 * this flag gets cleared after 64 PCI clocks.
 	 */
-	bus_flags = (pdev->is_pcie) ? 0 : AR5K_RESET_CTL_PCI;
+	bus_flags = (pdev && pci_is_pcie(pdev)) ? 0 : AR5K_RESET_CTL_PCI;
 
 	if (ah->ah_version == AR5K_AR5210) {
 		ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU |
@@ -413,8 +602,12 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw
 			AR5K_RESET_CTL_PHY | AR5K_RESET_CTL_PCI);
 			mdelay(2);
 	} else {
-		ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU |
-			AR5K_RESET_CTL_BASEBAND | bus_flags);
+		if (ath5k_get_bus_type(ah) == ATH_AHB)
+			ret = ath5k_hw_wisoc_reset(ah, AR5K_RESET_CTL_PCU |
+				AR5K_RESET_CTL_BASEBAND);
+		else
+			ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU |
+				AR5K_RESET_CTL_BASEBAND | bus_flags);
 	}
 
 	if (ret) {
@@ -429,9 +622,15 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw
 		return ret;
 	}
 
-	/* ...clear reset control register and pull device out of
-	 * warm reset */
-	if (ath5k_hw_nic_reset(ah, 0)) {
+	/* ...reset configuration regiter on Wisoc ...
+	 * ...clear reset control register and pull device out of
+	 * warm reset on others */
+	if (ath5k_get_bus_type(ah) == ATH_AHB)
+		ret = ath5k_hw_wisoc_reset(ah, 0);
+	else
+		ret = ath5k_hw_nic_reset(ah, 0);
+
+	if (ret) {
 		ATH5K_ERR(ah->ah_sc, "failed to warm reset the MAC Chip\n");
 		return -EIO;
 	}
@@ -466,7 +665,8 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw
 				 * CCK headers) operation. We need to test
 				 * this, 5211 might support ofdm-only g after
 				 * all, there are also initial register values
-				 * in the code for g mode (see initvals.c). */
+				 * in the code for g mode (see initvals.c).
+				 */
 				if (ah->ah_version == AR5K_AR5211)
 					mode |= AR5K_PHY_MODE_MOD_OFDM;
 				else
@@ -479,6 +679,7 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw
 		} else if (flags & CHANNEL_5GHZ) {
 			mode |= AR5K_PHY_MODE_FREQ_5GHZ;
 
+			/* Different PLL setting for 5413 */
 			if (ah->ah_radio == AR5K_RF5413)
 				clock = AR5K_PHY_PLL_40MHZ_5413;
 			else
@@ -496,12 +697,29 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw
 			return -EINVAL;
 		}
 
-		if (flags & CHANNEL_TURBO)
-			turbo = AR5K_PHY_TURBO_MODE | AR5K_PHY_TURBO_SHORT;
+		/*XXX: Can bwmode be used with dynamic mode ?
+		 * (I don't think it supports 44MHz) */
+		/* On 2425 initvals TURBO_SHORT is not pressent */
+		if (ah->ah_bwmode == AR5K_BWMODE_40MHZ) {
+			turbo = AR5K_PHY_TURBO_MODE |
+				(ah->ah_radio == AR5K_RF2425) ? 0 :
+				AR5K_PHY_TURBO_SHORT;
+		} else if (ah->ah_bwmode != AR5K_BWMODE_DEFAULT) {
+			if (ah->ah_radio == AR5K_RF5413) {
+				mode |= (ah->ah_bwmode == AR5K_BWMODE_10MHZ) ?
+					AR5K_PHY_MODE_HALF_RATE :
+					AR5K_PHY_MODE_QUARTER_RATE;
+			} else if (ah->ah_version == AR5K_AR5212) {
+				clock |= (ah->ah_bwmode == AR5K_BWMODE_10MHZ) ?
+					AR5K_PHY_PLL_HALF_RATE :
+					AR5K_PHY_PLL_QUARTER_RATE;
+			}
+		}
+
 	} else { /* Reset the device */
 
 		/* ...enable Atheros turbo mode if requested */
-		if (flags & CHANNEL_TURBO)
+		if (ah->ah_bwmode == AR5K_BWMODE_40MHZ)
 			ath5k_hw_reg_write(ah, AR5K_PHY_TURBO_MODE,
 					AR5K_PHY_TURBO);
 	}
@@ -522,107 +740,10 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw
 	return 0;
 }
 
-/*
- * If there is an external 32KHz crystal available, use it
- * as ref. clock instead of 32/40MHz clock and baseband clocks
- * to save power during sleep or restore normal 32/40MHz
- * operation.
- *
- * XXX: When operating on 32KHz certain PHY registers (27 - 31,
- * 	123 - 127) require delay on access.
- */
-static void ath5k_hw_set_sleep_clock(struct ath5k_hw *ah, bool enable)
-{
-	struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
-	u32 scal, spending, usec32;
-
-	/* Only set 32KHz settings if we have an external
-	 * 32KHz crystal present */
-	if ((AR5K_EEPROM_HAS32KHZCRYSTAL(ee->ee_misc1) ||
-	AR5K_EEPROM_HAS32KHZCRYSTAL_OLD(ee->ee_misc1)) &&
-	enable) {
-
-		/* 1 usec/cycle */
-		AR5K_REG_WRITE_BITS(ah, AR5K_USEC_5211, AR5K_USEC_32, 1);
-		/* Set up tsf increment on each cycle */
-		AR5K_REG_WRITE_BITS(ah, AR5K_TSF_PARM, AR5K_TSF_PARM_INC, 61);
-
-		/* Set baseband sleep control registers
-		 * and sleep control rate */
-		ath5k_hw_reg_write(ah, 0x1f, AR5K_PHY_SCR);
-
-		if ((ah->ah_radio == AR5K_RF5112) ||
-		(ah->ah_radio == AR5K_RF5413) ||
-		(ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4)))
-			spending = 0x14;
-		else
-			spending = 0x18;
-		ath5k_hw_reg_write(ah, spending, AR5K_PHY_SPENDING);
-
-		if ((ah->ah_radio == AR5K_RF5112) ||
-		(ah->ah_radio == AR5K_RF5413) ||
-		(ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))) {
-			ath5k_hw_reg_write(ah, 0x26, AR5K_PHY_SLMT);
-			ath5k_hw_reg_write(ah, 0x0d, AR5K_PHY_SCAL);
-			ath5k_hw_reg_write(ah, 0x07, AR5K_PHY_SCLOCK);
-			ath5k_hw_reg_write(ah, 0x3f, AR5K_PHY_SDELAY);
-			AR5K_REG_WRITE_BITS(ah, AR5K_PCICFG,
-				AR5K_PCICFG_SLEEP_CLOCK_RATE, 0x02);
-		} else {
-			ath5k_hw_reg_write(ah, 0x0a, AR5K_PHY_SLMT);
-			ath5k_hw_reg_write(ah, 0x0c, AR5K_PHY_SCAL);
-			ath5k_hw_reg_write(ah, 0x03, AR5K_PHY_SCLOCK);
-			ath5k_hw_reg_write(ah, 0x20, AR5K_PHY_SDELAY);
-			AR5K_REG_WRITE_BITS(ah, AR5K_PCICFG,
-				AR5K_PCICFG_SLEEP_CLOCK_RATE, 0x03);
-		}
-
-		/* Enable sleep clock operation */
-		AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG,
-				AR5K_PCICFG_SLEEP_CLOCK_EN);
-
-	} else {
 
-		/* Disable sleep clock operation and
-		 * restore default parameters */
-		AR5K_REG_DISABLE_BITS(ah, AR5K_PCICFG,
-				AR5K_PCICFG_SLEEP_CLOCK_EN);
-
-		AR5K_REG_WRITE_BITS(ah, AR5K_PCICFG,
-				AR5K_PCICFG_SLEEP_CLOCK_RATE, 0);
-
-		ath5k_hw_reg_write(ah, 0x1f, AR5K_PHY_SCR);
-		ath5k_hw_reg_write(ah, AR5K_PHY_SLMT_32MHZ, AR5K_PHY_SLMT);
-
-		if (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))
-			scal = AR5K_PHY_SCAL_32MHZ_2417;
-		else if (ee->ee_is_hb63)
-			scal = AR5K_PHY_SCAL_32MHZ_HB63;
-		else
-			scal = AR5K_PHY_SCAL_32MHZ;
-		ath5k_hw_reg_write(ah, scal, AR5K_PHY_SCAL);
-
-		ath5k_hw_reg_write(ah, AR5K_PHY_SCLOCK_32MHZ, AR5K_PHY_SCLOCK);
-		ath5k_hw_reg_write(ah, AR5K_PHY_SDELAY_32MHZ, AR5K_PHY_SDELAY);
-
-		if ((ah->ah_radio == AR5K_RF5112) ||
-		(ah->ah_radio == AR5K_RF5413) ||
-		(ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4)))
-			spending = 0x14;
-		else
-			spending = 0x18;
-		ath5k_hw_reg_write(ah, spending, AR5K_PHY_SPENDING);
-
-		if ((ah->ah_radio == AR5K_RF5112) ||
-		(ah->ah_radio == AR5K_RF5413))
-			usec32 = 39;
-		else
-			usec32 = 31;
-		AR5K_REG_WRITE_BITS(ah, AR5K_USEC_5211, AR5K_USEC_32, usec32);
-
-		AR5K_REG_WRITE_BITS(ah, AR5K_TSF_PARM, AR5K_TSF_PARM_INC, 1);
-	}
-}
+/**************************************\
+* Post-initvals register modifications *
+\**************************************/
 
 /* TODO: Half/Quarter rate */
 static void ath5k_hw_tweak_initval_settings(struct ath5k_hw *ah,
@@ -663,22 +784,10 @@ static void ath5k_hw_tweak_initval_setti
 		AR5K_REG_DISABLE_BITS(ah, AR5K_TXCFG,
 				AR5K_TXCFG_DCU_DBL_BUF_DIS);
 
-	/* Set DAC/ADC delays */
-	if (ah->ah_version == AR5K_AR5212) {
-		u32 scal;
-		struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
-		if (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))
-			scal = AR5K_PHY_SCAL_32MHZ_2417;
-		else if (ee->ee_is_hb63)
-			scal = AR5K_PHY_SCAL_32MHZ_HB63;
-		else
-			scal = AR5K_PHY_SCAL_32MHZ;
-		ath5k_hw_reg_write(ah, scal, AR5K_PHY_SCAL);
-	}
-
 	/* Set fast ADC */
 	if ((ah->ah_radio == AR5K_RF5413) ||
-	(ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))) {
+		(ah->ah_radio == AR5K_RF2317) ||
+		(ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))) {
 		u32 fast_adc = true;
 
 		if (channel->center_freq == 2462 ||
@@ -706,33 +815,68 @@ static void ath5k_hw_tweak_initval_setti
 	}
 
 	if (ah->ah_mac_srev < AR5K_SREV_AR5211) {
-		u32 usec_reg;
-		/* 5311 has different tx/rx latency masks
-		 * from 5211, since we deal 5311 the same
-		 * as 5211 when setting initvals, shift
-		 * values here to their proper locations */
-		usec_reg = ath5k_hw_reg_read(ah, AR5K_USEC_5211);
-		ath5k_hw_reg_write(ah, usec_reg & (AR5K_USEC_1 |
-				AR5K_USEC_32 |
-				AR5K_USEC_TX_LATENCY_5211 |
-				AR5K_REG_SM(29,
-				AR5K_USEC_RX_LATENCY_5210)),
-				AR5K_USEC_5211);
 		/* Clear QCU/DCU clock gating register */
 		ath5k_hw_reg_write(ah, 0, AR5K_QCUDCU_CLKGT);
 		/* Set DAC/ADC delays */
-		ath5k_hw_reg_write(ah, 0x08, AR5K_PHY_SCAL);
+		ath5k_hw_reg_write(ah, AR5K_PHY_SCAL_32MHZ_5311,
+						AR5K_PHY_SCAL);
 		/* Enable PCU FIFO corruption ECO */
 		AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW_5211,
 					AR5K_DIAG_SW_ECO_ENABLE);
 	}
+
+	if (ah->ah_bwmode) {
+		/* Increase PHY switch and AGC settling time
+		 * on turbo mode (ath5k_hw_commit_eeprom_settings
+		 * will override settling time if available) */
+		if (ah->ah_bwmode == AR5K_BWMODE_40MHZ) {
+
+			AR5K_REG_WRITE_BITS(ah, AR5K_PHY_SETTLING,
+						AR5K_PHY_SETTLING_AGC,
+						AR5K_AGC_SETTLING_TURBO);
+
+			/* XXX: Initvals indicate we only increase
+			 * switch time on AR5212, 5211 and 5210
+			 * only change agc time (bug?) */
+			if (ah->ah_version == AR5K_AR5212)
+				AR5K_REG_WRITE_BITS(ah, AR5K_PHY_SETTLING,
+						AR5K_PHY_SETTLING_SWITCH,
+						AR5K_SWITCH_SETTLING_TURBO);
+
+			if (ah->ah_version == AR5K_AR5210) {
+				/* Set Frame Control Register */
+				ath5k_hw_reg_write(ah,
+					(AR5K_PHY_FRAME_CTL_INI |
+					AR5K_PHY_TURBO_MODE |
+					AR5K_PHY_TURBO_SHORT | 0x2020),
+					AR5K_PHY_FRAME_CTL_5210);
+			}
+		/* On 5413 PHY force window length for half/quarter rate*/
+		} else if ((ah->ah_mac_srev >= AR5K_SREV_AR5424) &&
+		(ah->ah_mac_srev <= AR5K_SREV_AR5414)) {
+			AR5K_REG_WRITE_BITS(ah, AR5K_PHY_FRAME_CTL_5211,
+						AR5K_PHY_FRAME_CTL_WIN_LEN,
+						3);
+		}
+	} else if (ah->ah_version == AR5K_AR5210) {
+		/* Set Frame Control Register for normal operation */
+		ath5k_hw_reg_write(ah, (AR5K_PHY_FRAME_CTL_INI | 0x1020),
+						AR5K_PHY_FRAME_CTL_5210);
+	}
 }
 
 static void ath5k_hw_commit_eeprom_settings(struct ath5k_hw *ah,
-		struct ieee80211_channel *channel, u8 ee_mode)
+		struct ieee80211_channel *channel)
 {
 	struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
 	s16 cck_ofdm_pwr_delta;
+	u8 ee_mode;
+
+	/* TODO: Add support for AR5210 EEPROM */
+	if (ah->ah_version == AR5K_AR5210)
+		return;
+
+	ee_mode = ath5k_eeprom_mode_from_channel(channel);
 
 	/* Adjust power delta for channel 14 */
 	if (channel->center_freq == 2484)
@@ -772,7 +916,7 @@ static void ath5k_hw_commit_eeprom_setti
 		AR5K_PHY_NF_SVAL(ee->ee_noise_floor_thr[ee_mode]),
 		AR5K_PHY_NFTHRES);
 
-	if ((channel->hw_value & CHANNEL_TURBO) &&
+	if ((ah->ah_bwmode == AR5K_BWMODE_40MHZ) &&
 	(ah->ah_ee_version >= AR5K_EEPROM_VERSION_5_0)) {
 		/* Switch settling time (Turbo) */
 		AR5K_REG_WRITE_BITS(ah, AR5K_PHY_SETTLING,
@@ -870,143 +1014,172 @@ static void ath5k_hw_commit_eeprom_setti
 		ath5k_hw_reg_write(ah, 0, AR5K_PHY_HEAVY_CLIP_ENABLE);
 }
 
-/*
- * Main reset function
- */
+
+/*********************\
+* Main reset function *
+\*********************/
+
 int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
-	struct ieee80211_channel *channel, bool change_channel)
+		struct ieee80211_channel *channel, bool fast, bool skip_pcu)
 {
-	struct ath_common *common = ath5k_hw_common(ah);
-	u32 s_seq[10], s_led[3], staid1_flags, tsf_up, tsf_lo;
-	u32 phy_tst1;
-	u8 mode, freq, ee_mode;
+	u32 s_seq[10], s_led[3], tsf_up, tsf_lo;
+	u8 mode;
 	int i, ret;
 
-	ee_mode = 0;
-	staid1_flags = 0;
 	tsf_up = 0;
 	tsf_lo = 0;
-	freq = 0;
 	mode = 0;
 
 	/*
-	 * Save some registers before a reset
+	 * Sanity check for fast flag
+	 * Fast channel change only available
+	 * on AR2413/AR5413.
 	 */
-	/*DCU/Antenna selection not available on 5210*/
-	if (ah->ah_version != AR5K_AR5210) {
+	if (fast && (ah->ah_radio != AR5K_RF2413) &&
+	(ah->ah_radio != AR5K_RF5413))
+		fast = 0;
 
-		switch (channel->hw_value & CHANNEL_MODES) {
-		case CHANNEL_A:
-			mode = AR5K_MODE_11A;
-			freq = AR5K_INI_RFGAIN_5GHZ;
-			ee_mode = AR5K_EEPROM_MODE_11A;
-			break;
-		case CHANNEL_G:
-			mode = AR5K_MODE_11G;
-			freq = AR5K_INI_RFGAIN_2GHZ;
-			ee_mode = AR5K_EEPROM_MODE_11G;
-			break;
-		case CHANNEL_B:
-			mode = AR5K_MODE_11B;
-			freq = AR5K_INI_RFGAIN_2GHZ;
-			ee_mode = AR5K_EEPROM_MODE_11B;
-			break;
-		case CHANNEL_T:
-			mode = AR5K_MODE_11A_TURBO;
-			freq = AR5K_INI_RFGAIN_5GHZ;
-			ee_mode = AR5K_EEPROM_MODE_11A;
-			break;
-		case CHANNEL_TG:
-			if (ah->ah_version == AR5K_AR5211) {
-				ATH5K_ERR(ah->ah_sc,
-					"TurboG mode not available on 5211");
-				return -EINVAL;
-			}
-			mode = AR5K_MODE_11G_TURBO;
-			freq = AR5K_INI_RFGAIN_2GHZ;
-			ee_mode = AR5K_EEPROM_MODE_11G;
-			break;
-		case CHANNEL_XR:
-			if (ah->ah_version == AR5K_AR5211) {
-				ATH5K_ERR(ah->ah_sc,
-					"XR mode not available on 5211");
-				return -EINVAL;
-			}
-			mode = AR5K_MODE_XR;
-			freq = AR5K_INI_RFGAIN_5GHZ;
-			ee_mode = AR5K_EEPROM_MODE_11A;
-			break;
-		default:
+	/* Disable sleep clock operation
+	 * to avoid register access delay on certain
+	 * PHY registers */
+	if (ah->ah_version == AR5K_AR5212)
+		ath5k_hw_set_sleep_clock(ah, false);
+
+	/*
+	 * Stop PCU
+	 */
+	ath5k_hw_stop_rx_pcu(ah);
+
+	/*
+	 * Stop DMA
+	 *
+	 * Note: If DMA didn't stop continue
+	 * since only a reset will fix it.
+	 */
+	ret = ath5k_hw_dma_stop(ah);
+
+	/* RF Bus grant won't work if we have pending
+	 * frames */
+	if (ret && fast) {
+		ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_RESET,
+			"DMA didn't stop, falling back to normal reset\n");
+		fast = 0;
+		/* Non fatal, just continue with
+		 * normal reset */
+		ret = 0;
+	}
+
+	switch (channel->hw_value & CHANNEL_MODES) {
+	case CHANNEL_A:
+		mode = AR5K_MODE_11A;
+		break;
+	case CHANNEL_G:
+
+		if (ah->ah_version <= AR5K_AR5211) {
 			ATH5K_ERR(ah->ah_sc,
-				"invalid channel: %d\n", channel->center_freq);
+				"G mode not available on 5210/5211");
 			return -EINVAL;
 		}
 
-		if (change_channel) {
-			/*
-			 * Save frame sequence count
-			 * For revs. after Oahu, only save
-			 * seq num for DCU 0 (Global seq num)
-			 */
-			if (ah->ah_mac_srev < AR5K_SREV_AR5211) {
-
-				for (i = 0; i < 10; i++)
-					s_seq[i] = ath5k_hw_reg_read(ah,
-						AR5K_QUEUE_DCU_SEQNUM(i));
+		mode = AR5K_MODE_11G;
+		break;
+	case CHANNEL_B:
 
-			} else {
-				s_seq[0] = ath5k_hw_reg_read(ah,
-						AR5K_QUEUE_DCU_SEQNUM(0));
-			}
+		if (ah->ah_version < AR5K_AR5211) {
+			ATH5K_ERR(ah->ah_sc,
+				"B mode not available on 5210");
+			return -EINVAL;
+		}
 
-			/* TSF accelerates on AR5211 during reset
-			 * As a workaround save it here and restore
-			 * it later so that it's back in time after
-			 * reset. This way it'll get re-synced on the
-			 * next beacon without breaking ad-hoc.
-			 *
-			 * On AR5212 TSF is almost preserved across a
-			 * reset so it stays back in time anyway and
-			 * we don't have to save/restore it.
-			 *
-			 * XXX: Since this breaks power saving we have
-			 * to disable power saving until we receive the
-			 * next beacon, so we can resync beacon timers */
-			if (ah->ah_version == AR5K_AR5211) {
-				tsf_up = ath5k_hw_reg_read(ah, AR5K_TSF_U32);
-				tsf_lo = ath5k_hw_reg_read(ah, AR5K_TSF_L32);
-			}
+		mode = AR5K_MODE_11B;
+		break;
+	case CHANNEL_XR:
+		if (ah->ah_version == AR5K_AR5211) {
+			ATH5K_ERR(ah->ah_sc,
+				"XR mode not available on 5211");
+			return -EINVAL;
 		}
+		mode = AR5K_MODE_XR;
+		break;
+	default:
+		ATH5K_ERR(ah->ah_sc,
+			"invalid channel: %d\n", channel->center_freq);
+		return -EINVAL;
+	}
 
-		if (ah->ah_version == AR5K_AR5212) {
-			/* Restore normal 32/40MHz clock operation
-			 * to avoid register access delay on certain
-			 * PHY registers */
-			ath5k_hw_set_sleep_clock(ah, false);
+	/*
+	 * If driver requested fast channel change and DMA has stopped
+	 * go on. If it fails continue with a normal reset.
+	 */
+	if (fast) {
+		ret = ath5k_hw_phy_init(ah, channel, mode, true);
+		if (ret) {
+			ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_RESET,
+				"fast chan change failed, falling back to normal reset\n");
+			/* Non fatal, can happen eg.
+			 * on mode change */
+			ret = 0;
+		} else
+			return 0;
+	}
 
-			/* Since we are going to write rf buffer
-			 * check if we have any pending gain_F
-			 * optimization settings */
-			if (change_channel && ah->ah_rf_banks != NULL)
-				ath5k_hw_gainf_calibrate(ah);
+	/*
+	 * Save some registers before a reset
+	 */
+	if (ah->ah_version != AR5K_AR5210) {
+		/*
+		 * Save frame sequence count
+		 * For revs. after Oahu, only save
+		 * seq num for DCU 0 (Global seq num)
+		 */
+		if (ah->ah_mac_srev < AR5K_SREV_AR5211) {
+
+			for (i = 0; i < 10; i++)
+				s_seq[i] = ath5k_hw_reg_read(ah,
+					AR5K_QUEUE_DCU_SEQNUM(i));
+
+		} else {
+			s_seq[0] = ath5k_hw_reg_read(ah,
+					AR5K_QUEUE_DCU_SEQNUM(0));
+		}
+
+		/* TSF accelerates on AR5211 during reset
+		 * As a workaround save it here and restore
+		 * it later so that it's back in time after
+		 * reset. This way it'll get re-synced on the
+		 * next beacon without breaking ad-hoc.
+		 *
+		 * On AR5212 TSF is almost preserved across a
+		 * reset so it stays back in time anyway and
+		 * we don't have to save/restore it.
+		 *
+		 * XXX: Since this breaks power saving we have
+		 * to disable power saving until we receive the
+		 * next beacon, so we can resync beacon timers */
+		if (ah->ah_version == AR5K_AR5211) {
+			tsf_up = ath5k_hw_reg_read(ah, AR5K_TSF_U32);
+			tsf_lo = ath5k_hw_reg_read(ah, AR5K_TSF_L32);
 		}
 	}
 
+
 	/*GPIOs*/
 	s_led[0] = ath5k_hw_reg_read(ah, AR5K_PCICFG) &
 					AR5K_PCICFG_LEDSTATE;
 	s_led[1] = ath5k_hw_reg_read(ah, AR5K_GPIOCR);
 	s_led[2] = ath5k_hw_reg_read(ah, AR5K_GPIODO);
 
-	/* AR5K_STA_ID1 flags, only preserve antenna
-	 * settings and ack/cts rate mode */
-	staid1_flags = ath5k_hw_reg_read(ah, AR5K_STA_ID1) &
-			(AR5K_STA_ID1_DEFAULT_ANTENNA |
-			AR5K_STA_ID1_DESC_ANTENNA |
-			AR5K_STA_ID1_RTS_DEF_ANTENNA |
-			AR5K_STA_ID1_ACKCTS_6MB |
-			AR5K_STA_ID1_BASE_RATE_11B |
-			AR5K_STA_ID1_SELFGEN_DEF_ANT);
+
+	/*
+	 * Since we are going to write rf buffer
+	 * check if we have any pending gain_F
+	 * optimization settings
+	 */
+	if (ah->ah_version == AR5K_AR5212 &&
+	(ah->ah_radio <= AR5K_RF5112)) {
+		if (!fast && ah->ah_rf_banks != NULL)
+				ath5k_hw_gainf_calibrate(ah);
+	}
 
 	/* Wakeup the device */
 	ret = ath5k_hw_nic_wakeup(ah, channel->hw_value, false);
@@ -1021,121 +1194,42 @@ int ath5k_hw_reset(struct ath5k_hw *ah,
 							AR5K_PHY(0));
 
 	/* Write initial settings */
-	ret = ath5k_hw_write_initvals(ah, mode, change_channel);
+	ret = ath5k_hw_write_initvals(ah, mode, skip_pcu);
 	if (ret)
 		return ret;
 
+	/* Initialize core clock settings */
+	ath5k_hw_init_core_clock(ah);
+
 	/*
-	 * 5211/5212 Specific
+	 * Tweak initval settings for revised
+	 * chipsets and add some more config
+	 * bits
 	 */
-	if (ah->ah_version != AR5K_AR5210) {
-
-		/*
-		 * Write initial RF gain settings
-		 * This should work for both 5111/5112
-		 */
-		ret = ath5k_hw_rfgain_init(ah, freq);
-		if (ret)
-			return ret;
-
-		mdelay(1);
-
-		/*
-		 * Tweak initval settings for revised
-		 * chipsets and add some more config
-		 * bits
-		 */
-		ath5k_hw_tweak_initval_settings(ah, channel);
-
-		/*
-		 * Set TX power
-		 */
-		ret = ath5k_hw_txpower(ah, channel, ee_mode,
-					ah->ah_txpower.txp_max_pwr / 2);
-		if (ret)
-			return ret;
-
-		/* Write rate duration table only on AR5212 and if
-		 * virtual interface has already been brought up
-		 * XXX: rethink this after new mode changes to
-		 * mac80211 are integrated */
-		if (ah->ah_version == AR5K_AR5212 &&
-			ah->ah_sc->nvifs)
-			ath5k_hw_write_rate_duration(ah, mode);
-
-		/*
-		 * Write RF buffer
-		 */
-		ret = ath5k_hw_rfregs_init(ah, channel, mode);
-		if (ret)
-			return ret;
-
-
-		/* Write OFDM timings on 5212*/
-		if (ah->ah_version == AR5K_AR5212 &&
-			channel->hw_value & CHANNEL_OFDM) {
-
-			ret = ath5k_hw_write_ofdm_timings(ah, channel);
-			if (ret)
-				return ret;
-
-			/* Spur info is available only from EEPROM versions
-			 * greater than 5.3, but the EEPROM routines will use
-			 * static values for older versions */
-			if (ah->ah_mac_srev >= AR5K_SREV_AR5424)
-				ath5k_hw_set_spur_mitigation_filter(ah,
-								    channel);
-		}
-
-		/*Enable/disable 802.11b mode on 5111
-		(enable 2111 frequency converter + CCK)*/
-		if (ah->ah_radio == AR5K_RF5111) {
-			if (mode == AR5K_MODE_11B)
-				AR5K_REG_ENABLE_BITS(ah, AR5K_TXCFG,
-				    AR5K_TXCFG_B_MODE);
-			else
-				AR5K_REG_DISABLE_BITS(ah, AR5K_TXCFG,
-				    AR5K_TXCFG_B_MODE);
-		}
+	ath5k_hw_tweak_initval_settings(ah, channel);
 
-		/* Commit values from EEPROM */
-		ath5k_hw_commit_eeprom_settings(ah, channel, ee_mode);
+	/* Commit values from EEPROM */
+	ath5k_hw_commit_eeprom_settings(ah, channel);
 
-	} else {
-		/*
-		 * For 5210 we do all initialization using
-		 * initvals, so we don't have to modify
-		 * any settings (5210 also only supports
-		 * a/aturbo modes)
-		 */
-		mdelay(1);
-		/* Disable phy and wait */
-		ath5k_hw_reg_write(ah, AR5K_PHY_ACT_DISABLE, AR5K_PHY_ACT);
-		mdelay(1);
-	}
 
 	/*
 	 * Restore saved values
 	 */
 
-	/*DCU/Antenna selection not available on 5210*/
+	/* Seqnum, TSF */
 	if (ah->ah_version != AR5K_AR5210) {
+		if (ah->ah_mac_srev < AR5K_SREV_AR5211) {
+			for (i = 0; i < 10; i++)
+				ath5k_hw_reg_write(ah, s_seq[i],
+					AR5K_QUEUE_DCU_SEQNUM(i));
+		} else {
+			ath5k_hw_reg_write(ah, s_seq[0],
+				AR5K_QUEUE_DCU_SEQNUM(0));
+		}
 
-		if (change_channel) {
-			if (ah->ah_mac_srev < AR5K_SREV_AR5211) {
-				for (i = 0; i < 10; i++)
-					ath5k_hw_reg_write(ah, s_seq[i],
-						AR5K_QUEUE_DCU_SEQNUM(i));
-			} else {
-				ath5k_hw_reg_write(ah, s_seq[0],
-					AR5K_QUEUE_DCU_SEQNUM(0));
-			}
-
-
-			if (ah->ah_version == AR5K_AR5211) {
-				ath5k_hw_reg_write(ah, tsf_up, AR5K_TSF_U32);
-				ath5k_hw_reg_write(ah, tsf_lo, AR5K_TSF_L32);
-			}
+		if (ah->ah_version == AR5K_AR5211) {
+			ath5k_hw_reg_write(ah, tsf_up, AR5K_TSF_U32);
+			ath5k_hw_reg_write(ah, tsf_lo, AR5K_TSF_L32);
 		}
 	}
 
@@ -1146,203 +1240,34 @@ int ath5k_hw_reset(struct ath5k_hw *ah,
 	ath5k_hw_reg_write(ah, s_led[1], AR5K_GPIOCR);
 	ath5k_hw_reg_write(ah, s_led[2], AR5K_GPIODO);
 
-	/* Restore sta_id flags and preserve our mac address*/
-	ath5k_hw_reg_write(ah,
-			   get_unaligned_le32(common->macaddr),
-			   AR5K_STA_ID0);
-	ath5k_hw_reg_write(ah,
-			   staid1_flags | get_unaligned_le16(common->macaddr + 4),
-			   AR5K_STA_ID1);
-
-
 	/*
-	 * Configure PCU
+	 * Initialize PCU
 	 */
-
-	/* Restore bssid and bssid mask */
-	ath5k_hw_set_bssid(ah);
-
-	/* Set PCU config */
-	ath5k_hw_set_opmode(ah, op_mode);
-
-	/* Clear any pending interrupts
-	 * PISR/SISR Not available on 5210 */
-	if (ah->ah_version != AR5K_AR5210)
-		ath5k_hw_reg_write(ah, 0xffffffff, AR5K_PISR);
-
-	/* Set RSSI/BRSSI thresholds
-	 *
-	 * Note: If we decide to set this value
-	 * dynamically, keep in mind that when AR5K_RSSI_THR
-	 * register is read, it might return 0x40 if we haven't
-	 * written anything to it.  Also, BMISS RSSI threshold is zeroed.
-	 * So doing a save/restore procedure here isn't the right
-	 * choice. Instead, store it in ath5k_hw */
-	ath5k_hw_reg_write(ah, (AR5K_TUNE_RSSI_THRES |
-				AR5K_TUNE_BMISS_THRES <<
-				AR5K_RSSI_THR_BMISS_S),
-				AR5K_RSSI_THR);
-
-	/* MIC QoS support */
-	if (ah->ah_mac_srev >= AR5K_SREV_AR2413) {
-		ath5k_hw_reg_write(ah, 0x000100aa, AR5K_MIC_QOS_CTL);
-		ath5k_hw_reg_write(ah, 0x00003210, AR5K_MIC_QOS_SEL);
-	}
-
-	/* QoS NOACK Policy */
-	if (ah->ah_version == AR5K_AR5212) {
-		ath5k_hw_reg_write(ah,
-			AR5K_REG_SM(2, AR5K_QOS_NOACK_2BIT_VALUES) |
-			AR5K_REG_SM(5, AR5K_QOS_NOACK_BIT_OFFSET)  |
-			AR5K_REG_SM(0, AR5K_QOS_NOACK_BYTE_OFFSET),
-			AR5K_QOS_NOACK);
-	}
-
+	ath5k_hw_pcu_init(ah, op_mode, mode);
 
 	/*
-	 * Configure PHY
+	 * Initialize PHY
 	 */
-
-	/* Set channel on PHY */
-	ret = ath5k_hw_channel(ah, channel);
-	if (ret)
+	ret = ath5k_hw_phy_init(ah, channel, mode, false);
+	if (ret) {
+		ATH5K_ERR(ah->ah_sc,
+			"failed to initialize PHY (%i) !\n", ret);
 		return ret;
-
-	/*
-	 * Enable the PHY and wait until completion
-	 * This includes BaseBand and Synthesizer
-	 * activation.
-	 */
-	ath5k_hw_reg_write(ah, AR5K_PHY_ACT_ENABLE, AR5K_PHY_ACT);
-
-	/*
-	 * On 5211+ read activation -> rx delay
-	 * and use it.
-	 *
-	 * TODO: Half/quarter rate support
-	 */
-	if (ah->ah_version != AR5K_AR5210) {
-		u32 delay;
-		delay = ath5k_hw_reg_read(ah, AR5K_PHY_RX_DELAY) &
-			AR5K_PHY_RX_DELAY_M;
-		delay = (channel->hw_value & CHANNEL_CCK) ?
-			((delay << 2) / 22) : (delay / 10);
-
-		udelay(100 + (2 * delay));
-	} else {
-		mdelay(1);
 	}
 
 	/*
-	 * Perform ADC test to see if baseband is ready
-	 * Set TX hold and check ADC test register
-	 */
-	phy_tst1 = ath5k_hw_reg_read(ah, AR5K_PHY_TST1);
-	ath5k_hw_reg_write(ah, AR5K_PHY_TST1_TXHOLD, AR5K_PHY_TST1);
-	for (i = 0; i <= 20; i++) {
-		if (!(ath5k_hw_reg_read(ah, AR5K_PHY_ADC_TEST) & 0x10))
-			break;
-		udelay(200);
-	}
-	ath5k_hw_reg_write(ah, phy_tst1, AR5K_PHY_TST1);
-
-	/*
-	 * Start automatic gain control calibration
-	 *
-	 * During AGC calibration RX path is re-routed to
-	 * a power detector so we don't receive anything.
-	 *
-	 * This method is used to calibrate some static offsets
-	 * used together with on-the fly I/Q calibration (the
-	 * one performed via ath5k_hw_phy_calibrate), which doesn't
-	 * interrupt rx path.
-	 *
-	 * While rx path is re-routed to the power detector we also
-	 * start a noise floor calibration to measure the
-	 * card's noise floor (the noise we measure when we are not
-	 * transmitting or receiving anything).
-	 *
-	 * If we are in a noisy environment, AGC calibration may time
-	 * out and/or noise floor calibration might timeout.
-	 */
-	AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL,
-				AR5K_PHY_AGCCTL_CAL | AR5K_PHY_AGCCTL_NF);
-
-	/* At the same time start I/Q calibration for QAM constellation
-	 * -no need for CCK- */
-	ah->ah_calibration = false;
-	if (!(mode == AR5K_MODE_11B)) {
-		ah->ah_calibration = true;
-		AR5K_REG_WRITE_BITS(ah, AR5K_PHY_IQ,
-				AR5K_PHY_IQ_CAL_NUM_LOG_MAX, 15);
-		AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ,
-				AR5K_PHY_IQ_RUN);
-	}
-
-	/* Wait for gain calibration to finish (we check for I/Q calibration
-	 * during ath5k_phy_calibrate) */
-	if (ath5k_hw_register_timeout(ah, AR5K_PHY_AGCCTL,
-			AR5K_PHY_AGCCTL_CAL, 0, false)) {
-		ATH5K_ERR(ah->ah_sc, "gain calibration timeout (%uMHz)\n",
-			channel->center_freq);
-	}
-
-	/* Restore antenna mode */
-	ath5k_hw_set_antenna_mode(ah, ah->ah_ant_mode);
-
-	/* Restore slot time and ACK timeouts */
-	if (ah->ah_coverage_class > 0)
-		ath5k_hw_set_coverage_class(ah, ah->ah_coverage_class);
-
-	/*
 	 * Configure QCUs/DCUs
 	 */
+	ret = ath5k_hw_init_queues(ah);
+	if (ret)
+		return ret;
 
-	/* TODO: HW Compression support for data queues */
-	/* TODO: Burst prefetch for data queues */
-
-	/*
-	 * Reset queues and start beacon timers at the end of the reset routine
-	 * This also sets QCU mask on each DCU for 1:1 qcu to dcu mapping
-	 * Note: If we want we can assign multiple qcus on one dcu.
-	 */
-	for (i = 0; i < ah->ah_capabilities.cap_queues.q_tx_num; i++) {
-		ret = ath5k_hw_reset_tx_queue(ah, i);
-		if (ret) {
-			ATH5K_ERR(ah->ah_sc,
-				"failed to reset TX queue #%d\n", i);
-			return ret;
-		}
-	}
-
-
-	/*
-	 * Configure DMA/Interrupts
-	 */
 
 	/*
-	 * Set Rx/Tx DMA Configuration
-	 *
-	 * Set standard DMA size (128). Note that
-	 * a DMA size of 512 causes rx overruns and tx errors
-	 * on pci-e cards (tested on 5424 but since rx overruns
-	 * also occur on 5416/5418 with madwifi we set 128
-	 * for all PCI-E cards to be safe).
-	 *
-	 * XXX: need to check 5210 for this
-	 * TODO: Check out tx triger level, it's always 64 on dumps but I
-	 * guess we can tweak it and see how it goes ;-)
+	 * Initialize DMA/Interrupts
 	 */
-	if (ah->ah_version != AR5K_AR5210) {
-		AR5K_REG_WRITE_BITS(ah, AR5K_TXCFG,
-			AR5K_TXCFG_SDMAMR, AR5K_DMASIZE_128B);
-		AR5K_REG_WRITE_BITS(ah, AR5K_RXCFG,
-			AR5K_RXCFG_SDMAMW, AR5K_DMASIZE_128B);
-	}
+	ath5k_hw_dma_init(ah);
 
-	/* Pre-enable interrupts on 5211/5212*/
-	if (ah->ah_version != AR5K_AR5210)
-		ath5k_hw_set_imr(ah, ah->ah_imr);
 
 	/* Enable 32KHz clock function for AR5212+ chips
 	 * Set clocks to 32KHz operation and use an
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath5k/rfbuffer.h linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath5k/rfbuffer.h
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath5k/rfbuffer.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath5k/rfbuffer.h	2011-03-14 21:20:32.000000000 -0400
@@ -51,7 +51,7 @@
 struct ath5k_ini_rfbuffer {
 	u8	rfb_bank;		/* RF Bank number */
 	u16	rfb_ctrl_register;	/* RF Buffer control register */
-	u32	rfb_mode_data[5];	/* RF Buffer data for each mode */
+	u32	rfb_mode_data[3];	/* RF Buffer data for each mode */
 };
 
 /*
@@ -79,8 +79,10 @@ struct ath5k_rf_reg {
  * life easier by using an index for each register
  * instead of a full rfb_field */
 enum ath5k_rf_regs_idx {
+	/* BANK 2 */
+	AR5K_RF_TURBO = 0,
 	/* BANK 6 */
-	AR5K_RF_OB_2GHZ = 0,
+	AR5K_RF_OB_2GHZ,
 	AR5K_RF_OB_5GHZ,
 	AR5K_RF_DB_2GHZ,
 	AR5K_RF_DB_5GHZ,
@@ -134,6 +136,9 @@ enum ath5k_rf_regs_idx {
 * RF5111 (Sombrero) *
 \*******************/
 
+/* BANK 2				len  pos col */
+#define	AR5K_RF5111_RF_TURBO		{ 1, 3,   0 }
+
 /* BANK 6				len  pos col */
 #define	AR5K_RF5111_OB_2GHZ		{ 3, 119, 0 }
 #define	AR5K_RF5111_DB_2GHZ		{ 3, 122, 0 }
@@ -158,6 +163,7 @@ enum ath5k_rf_regs_idx {
 #define	AR5K_RF5111_MAX_TIME		{ 2, 49,  0 }
 
 static const struct ath5k_rf_reg rf_regs_5111[] = {
+	{2, AR5K_RF_TURBO,		AR5K_RF5111_RF_TURBO},
 	{6, AR5K_RF_OB_2GHZ,		AR5K_RF5111_OB_2GHZ},
 	{6, AR5K_RF_DB_2GHZ,		AR5K_RF5111_DB_2GHZ},
 	{6, AR5K_RF_OB_5GHZ,		AR5K_RF5111_OB_5GHZ},
@@ -177,97 +183,52 @@ static const struct ath5k_rf_reg rf_regs
 
 /* Default mode specific settings */
 static const struct ath5k_ini_rfbuffer rfb_5111[] = {
-	{ 0, 0x989c,
-	/*     mode a/XR  mode aTurbo    mode b     mode g    mode gTurbo */
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 0, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 0, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 0, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 0, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 0, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 0, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 0, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 0, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 0, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 0, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 0, 0x989c,
-	    { 0x00380000, 0x00380000, 0x00380000, 0x00380000, 0x00380000 } },
-	{ 0, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 0, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 0, 0x989c,
-	    { 0x00000000, 0x00000000, 0x000000c0, 0x00000080, 0x00000080 } },
-	{ 0, 0x989c,
-	    { 0x000400f9, 0x000400f9, 0x000400ff, 0x000400fd, 0x000400fd } },
-	{ 0, 0x98d4,
-	    { 0x00000000, 0x00000000, 0x00000004, 0x00000004, 0x00000004 } },
-	{ 1, 0x98d4,
-	    { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } },
-	{ 2, 0x98d4,
-	    { 0x00000010, 0x00000014, 0x00000010, 0x00000010, 0x00000014 } },
-	{ 3, 0x98d8,
-	    { 0x00601068, 0x00601068, 0x00601068, 0x00601068, 0x00601068 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x10000000, 0x10000000, 0x10000000, 0x10000000, 0x10000000 } },
-	{ 6, 0x989c,
-	    { 0x04000000, 0x04000000, 0x04000000, 0x04000000, 0x04000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x0a000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x003800c0, 0x00380080, 0x023800c0, 0x003800c0, 0x003800c0 } },
-	{ 6, 0x989c,
-	    { 0x00020006, 0x00020006, 0x00000006, 0x00020006, 0x00020006 } },
-	{ 6, 0x989c,
-	    { 0x00000089, 0x00000089, 0x00000089, 0x00000089, 0x00000089 } },
-	{ 6, 0x989c,
-	    { 0x000000a0, 0x000000a0, 0x000000a0, 0x000000a0, 0x000000a0 } },
-	{ 6, 0x989c,
-	    { 0x00040007, 0x00040007, 0x00040007, 0x00040007, 0x00040007 } },
-	{ 6, 0x98d4,
-	    { 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a } },
-	{ 7, 0x989c,
-	    { 0x00000040, 0x00000048, 0x00000040, 0x00000040, 0x00000040 } },
-	{ 7, 0x989c,
-	    { 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010 } },
-	{ 7, 0x989c,
-	    { 0x00000008, 0x00000008, 0x00000008, 0x00000008, 0x00000008 } },
-	{ 7, 0x989c,
-	    { 0x0000004f, 0x0000004f, 0x0000004f, 0x0000004f, 0x0000004f } },
-	{ 7, 0x989c,
-	    { 0x000000f1, 0x000000f1, 0x00000061, 0x000000f1, 0x000000f1 } },
-	{ 7, 0x989c,
-	    { 0x0000904f, 0x0000904f, 0x0000904c, 0x0000904f, 0x0000904f } },
-	{ 7, 0x989c,
-	    { 0x0000125a, 0x0000125a, 0x0000129a, 0x0000125a, 0x0000125a } },
-	{ 7, 0x98cc,
-	    { 0x0000000e, 0x0000000e, 0x0000000f, 0x0000000e, 0x0000000e } },
+	/* BANK / C.R.     A/XR         B           G      */
+	{ 0, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+	{ 0, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+	{ 0, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+	{ 0, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+	{ 0, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+	{ 0, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+	{ 0, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+	{ 0, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+	{ 0, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+	{ 0, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+	{ 0, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+	{ 0, 0x989c, { 0x00380000, 0x00380000, 0x00380000 } },
+	{ 0, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+	{ 0, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+	{ 0, 0x989c, { 0x00000000, 0x000000c0, 0x00000080 } },
+	{ 0, 0x989c, { 0x000400f9, 0x000400ff, 0x000400fd } },
+	{ 0, 0x98d4, { 0x00000000, 0x00000004, 0x00000004 } },
+	{ 1, 0x98d4, { 0x00000020, 0x00000020, 0x00000020 } },
+	{ 2, 0x98d4, { 0x00000010, 0x00000010, 0x00000010 } },
+	{ 3, 0x98d8, { 0x00601068, 0x00601068, 0x00601068 } },
+	{ 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c, { 0x10000000, 0x10000000, 0x10000000 } },
+	{ 6, 0x989c, { 0x04000000, 0x04000000, 0x04000000 } },
+	{ 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c, { 0x00000000, 0x0a000000, 0x00000000 } },
+	{ 6, 0x989c, { 0x003800c0, 0x023800c0, 0x003800c0 } },
+	{ 6, 0x989c, { 0x00020006, 0x00000006, 0x00020006 } },
+	{ 6, 0x989c, { 0x00000089, 0x00000089, 0x00000089 } },
+	{ 6, 0x989c, { 0x000000a0, 0x000000a0, 0x000000a0 } },
+	{ 6, 0x989c, { 0x00040007, 0x00040007, 0x00040007 } },
+	{ 6, 0x98d4, { 0x0000001a, 0x0000001a, 0x0000001a } },
+	{ 7, 0x989c, { 0x00000040, 0x00000040, 0x00000040 } },
+	{ 7, 0x989c, { 0x00000010, 0x00000010, 0x00000010 } },
+	{ 7, 0x989c, { 0x00000008, 0x00000008, 0x00000008 } },
+	{ 7, 0x989c, { 0x0000004f, 0x0000004f, 0x0000004f } },
+	{ 7, 0x989c, { 0x000000f1, 0x00000061, 0x000000f1 } },
+	{ 7, 0x989c, { 0x0000904f, 0x0000904c, 0x0000904f } },
+	{ 7, 0x989c, { 0x0000125a, 0x0000129a, 0x0000125a } },
+	{ 7, 0x98cc, { 0x0000000e, 0x0000000f, 0x0000000e } },
 };
 
 
@@ -276,6 +237,9 @@ static const struct ath5k_ini_rfbuffer r
 * RF5112/RF2112 (Derby) *
 \***********************/
 
+/* BANK 2 (Common)			len  pos col */
+#define	AR5K_RF5112X_RF_TURBO		{ 1, 1,   2 }
+
 /* BANK 7 (Common)			len  pos col */
 #define	AR5K_RF5112X_GAIN_I		{ 6, 14,  0 }
 #define	AR5K_RF5112X_MIXVGA_OVR		{ 1, 36,  0 }
@@ -307,6 +271,7 @@ static const struct ath5k_ini_rfbuffer r
 #define AR5K_RF5112_PWD(_n)		{ 1, (302 - _n), 3 }
 
 static const struct ath5k_rf_reg rf_regs_5112[] = {
+	{2, AR5K_RF_TURBO,		AR5K_RF5112X_RF_TURBO},
 	{6, AR5K_RF_OB_2GHZ,		AR5K_RF5112_OB_2GHZ},
 	{6, AR5K_RF_DB_2GHZ,		AR5K_RF5112_DB_2GHZ},
 	{6, AR5K_RF_OB_5GHZ,		AR5K_RF5112_OB_5GHZ},
@@ -335,115 +300,61 @@ static const struct ath5k_rf_reg rf_regs
 
 /* Default mode specific settings */
 static const struct ath5k_ini_rfbuffer rfb_5112[] = {
-	{ 1, 0x98d4,
-	/*     mode a/XR  mode aTurbo    mode b     mode g    mode gTurbo */
-	    { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } },
-	{ 2, 0x98d0,
-	    { 0x03060408, 0x03070408, 0x03060408, 0x03060408, 0x03070408 } },
-	{ 3, 0x98dc,
-	    { 0x00a0c0c0, 0x00a0c0c0, 0x00e0c0c0, 0x00e0c0c0, 0x00e0c0c0 } },
-	{ 6, 0x989c,
-	    { 0x00a00000, 0x00a00000, 0x00a00000, 0x00a00000, 0x00a00000 } },
-	{ 6, 0x989c,
-	    { 0x000a0000, 0x000a0000, 0x000a0000, 0x000a0000, 0x000a0000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00660000, 0x00660000, 0x00660000, 0x00660000, 0x00660000 } },
-	{ 6, 0x989c,
-	    { 0x00db0000, 0x00db0000, 0x00db0000, 0x00db0000, 0x00db0000 } },
-	{ 6, 0x989c,
-	    { 0x00f10000, 0x00f10000, 0x00f10000, 0x00f10000, 0x00f10000 } },
-	{ 6, 0x989c,
-	    { 0x00120000, 0x00120000, 0x00120000, 0x00120000, 0x00120000 } },
-	{ 6, 0x989c,
-	    { 0x00120000, 0x00120000, 0x00120000, 0x00120000, 0x00120000 } },
-	{ 6, 0x989c,
-	    { 0x00730000, 0x00730000, 0x00730000, 0x00730000, 0x00730000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000 } },
-	{ 6, 0x989c,
-	    { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } },
-	{ 6, 0x989c,
-	    { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } },
-	{ 6, 0x989c,
-	    { 0x008b0000, 0x008b0000, 0x008b0000, 0x008b0000, 0x008b0000 } },
-	{ 6, 0x989c,
-	    { 0x00600000, 0x00600000, 0x00600000, 0x00600000, 0x00600000 } },
-	{ 6, 0x989c,
-	    { 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000 } },
-	{ 6, 0x989c,
-	    { 0x00840000, 0x00840000, 0x00840000, 0x00840000, 0x00840000 } },
-	{ 6, 0x989c,
-	    { 0x00640000, 0x00640000, 0x00640000, 0x00640000, 0x00640000 } },
-	{ 6, 0x989c,
-	    { 0x00200000, 0x00200000, 0x00200000, 0x00200000, 0x00200000 } },
-	{ 6, 0x989c,
-	    { 0x00240000, 0x00240000, 0x00240000, 0x00240000, 0x00240000 } },
-	{ 6, 0x989c,
-	    { 0x00250000, 0x00250000, 0x00250000, 0x00250000, 0x00250000 } },
-	{ 6, 0x989c,
-	    { 0x00110000, 0x00110000, 0x00110000, 0x00110000, 0x00110000 } },
-	{ 6, 0x989c,
-	    { 0x00110000, 0x00110000, 0x00110000, 0x00110000, 0x00110000 } },
-	{ 6, 0x989c,
-	    { 0x00510000, 0x00510000, 0x00510000, 0x00510000, 0x00510000 } },
-	{ 6, 0x989c,
-	    { 0x1c040000, 0x1c040000, 0x1c040000, 0x1c040000, 0x1c040000 } },
-	{ 6, 0x989c,
-	    { 0x000a0000, 0x000a0000, 0x000a0000, 0x000a0000, 0x000a0000 } },
-	{ 6, 0x989c,
-	    { 0x00a10000, 0x00a10000, 0x00a10000, 0x00a10000, 0x00a10000 } },
-	{ 6, 0x989c,
-	    { 0x00400000, 0x00400000, 0x00400000, 0x00400000, 0x00400000 } },
-	{ 6, 0x989c,
-	    { 0x03090000, 0x03090000, 0x03090000, 0x03090000, 0x03090000 } },
-	{ 6, 0x989c,
-	    { 0x06000000, 0x06000000, 0x06000000, 0x06000000, 0x06000000 } },
-	{ 6, 0x989c,
-	    { 0x000000b0, 0x000000b0, 0x000000a8, 0x000000a8, 0x000000a8 } },
-	{ 6, 0x989c,
-	    { 0x0000002e, 0x0000002e, 0x0000002e, 0x0000002e, 0x0000002e } },
-	{ 6, 0x989c,
-	    { 0x006c4a41, 0x006c4a41, 0x006c4af1, 0x006c4a61, 0x006c4a61 } },
-	{ 6, 0x989c,
-	    { 0x0050892a, 0x0050892a, 0x0050892b, 0x0050892b, 0x0050892b } },
-	{ 6, 0x989c,
-	    { 0x00842400, 0x00842400, 0x00842400, 0x00842400, 0x00842400 } },
-	{ 6, 0x989c,
-	    { 0x00c69200, 0x00c69200, 0x00c69200, 0x00c69200, 0x00c69200 } },
-	{ 6, 0x98d0,
-	    { 0x0002000c, 0x0002000c, 0x0002000c, 0x0002000c, 0x0002000c } },
-	{ 7, 0x989c,
-	    { 0x00000094, 0x00000094, 0x00000094, 0x00000094, 0x00000094 } },
-	{ 7, 0x989c,
-	    { 0x00000091, 0x00000091, 0x00000091, 0x00000091, 0x00000091 } },
-	{ 7, 0x989c,
-	    { 0x0000000a, 0x0000000a, 0x00000012, 0x00000012, 0x00000012 } },
-	{ 7, 0x989c,
-	    { 0x00000080, 0x00000080, 0x00000080, 0x00000080, 0x00000080 } },
-	{ 7, 0x989c,
-	    { 0x000000c1, 0x000000c1, 0x000000c1, 0x000000c1, 0x000000c1 } },
-	{ 7, 0x989c,
-	    { 0x00000060, 0x00000060, 0x00000060, 0x00000060, 0x00000060 } },
-	{ 7, 0x989c,
-	    { 0x000000f0, 0x000000f0, 0x000000f0, 0x000000f0, 0x000000f0 } },
-	{ 7, 0x989c,
-	    { 0x00000022, 0x00000022, 0x00000022, 0x00000022, 0x00000022 } },
-	{ 7, 0x989c,
-	    { 0x00000092, 0x00000092, 0x00000092, 0x00000092, 0x00000092 } },
-	{ 7, 0x989c,
-	    { 0x000000d4, 0x000000d4, 0x000000d4, 0x000000d4, 0x000000d4 } },
-	{ 7, 0x989c,
-	    { 0x000014cc, 0x000014cc, 0x000014cc, 0x000014cc, 0x000014cc } },
-	{ 7, 0x989c,
-	    { 0x0000048c, 0x0000048c, 0x0000048c, 0x0000048c, 0x0000048c } },
-	{ 7, 0x98c4,
-	    { 0x00000003, 0x00000003, 0x00000003, 0x00000003, 0x00000003 } },
+	/* BANK / C.R.     A/XR         B           G      */
+	{ 1, 0x98d4, { 0x00000020, 0x00000020, 0x00000020 } },
+	{ 2, 0x98d0, { 0x03060408, 0x03060408, 0x03060408 } },
+	{ 3, 0x98dc, { 0x00a0c0c0, 0x00e0c0c0, 0x00e0c0c0 } },
+	{ 6, 0x989c, { 0x00a00000, 0x00a00000, 0x00a00000 } },
+	{ 6, 0x989c, { 0x000a0000, 0x000a0000, 0x000a0000 } },
+	{ 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c, { 0x00660000, 0x00660000, 0x00660000 } },
+	{ 6, 0x989c, { 0x00db0000, 0x00db0000, 0x00db0000 } },
+	{ 6, 0x989c, { 0x00f10000, 0x00f10000, 0x00f10000 } },
+	{ 6, 0x989c, { 0x00120000, 0x00120000, 0x00120000 } },
+	{ 6, 0x989c, { 0x00120000, 0x00120000, 0x00120000 } },
+	{ 6, 0x989c, { 0x00730000, 0x00730000, 0x00730000 } },
+	{ 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c, { 0x000c0000, 0x000c0000, 0x000c0000 } },
+	{ 6, 0x989c, { 0x00ff0000, 0x00ff0000, 0x00ff0000 } },
+	{ 6, 0x989c, { 0x00ff0000, 0x00ff0000, 0x00ff0000 } },
+	{ 6, 0x989c, { 0x008b0000, 0x008b0000, 0x008b0000 } },
+	{ 6, 0x989c, { 0x00600000, 0x00600000, 0x00600000 } },
+	{ 6, 0x989c, { 0x000c0000, 0x000c0000, 0x000c0000 } },
+	{ 6, 0x989c, { 0x00840000, 0x00840000, 0x00840000 } },
+	{ 6, 0x989c, { 0x00640000, 0x00640000, 0x00640000 } },
+	{ 6, 0x989c, { 0x00200000, 0x00200000, 0x00200000 } },
+	{ 6, 0x989c, { 0x00240000, 0x00240000, 0x00240000 } },
+	{ 6, 0x989c, { 0x00250000, 0x00250000, 0x00250000 } },
+	{ 6, 0x989c, { 0x00110000, 0x00110000, 0x00110000 } },
+	{ 6, 0x989c, { 0x00110000, 0x00110000, 0x00110000 } },
+	{ 6, 0x989c, { 0x00510000, 0x00510000, 0x00510000 } },
+	{ 6, 0x989c, { 0x1c040000, 0x1c040000, 0x1c040000 } },
+	{ 6, 0x989c, { 0x000a0000, 0x000a0000, 0x000a0000 } },
+	{ 6, 0x989c, { 0x00a10000, 0x00a10000, 0x00a10000 } },
+	{ 6, 0x989c, { 0x00400000, 0x00400000, 0x00400000 } },
+	{ 6, 0x989c, { 0x03090000, 0x03090000, 0x03090000 } },
+	{ 6, 0x989c, { 0x06000000, 0x06000000, 0x06000000 } },
+	{ 6, 0x989c, { 0x000000b0, 0x000000a8, 0x000000a8 } },
+	{ 6, 0x989c, { 0x0000002e, 0x0000002e, 0x0000002e } },
+	{ 6, 0x989c, { 0x006c4a41, 0x006c4af1, 0x006c4a61 } },
+	{ 6, 0x989c, { 0x0050892a, 0x0050892b, 0x0050892b } },
+	{ 6, 0x989c, { 0x00842400, 0x00842400, 0x00842400 } },
+	{ 6, 0x989c, { 0x00c69200, 0x00c69200, 0x00c69200 } },
+	{ 6, 0x98d0, { 0x0002000c, 0x0002000c, 0x0002000c } },
+	{ 7, 0x989c, { 0x00000094, 0x00000094, 0x00000094 } },
+	{ 7, 0x989c, { 0x00000091, 0x00000091, 0x00000091 } },
+	{ 7, 0x989c, { 0x0000000a, 0x00000012, 0x00000012 } },
+	{ 7, 0x989c, { 0x00000080, 0x00000080, 0x00000080 } },
+	{ 7, 0x989c, { 0x000000c1, 0x000000c1, 0x000000c1 } },
+	{ 7, 0x989c, { 0x00000060, 0x00000060, 0x00000060 } },
+	{ 7, 0x989c, { 0x000000f0, 0x000000f0, 0x000000f0 } },
+	{ 7, 0x989c, { 0x00000022, 0x00000022, 0x00000022 } },
+	{ 7, 0x989c, { 0x00000092, 0x00000092, 0x00000092 } },
+	{ 7, 0x989c, { 0x000000d4, 0x000000d4, 0x000000d4 } },
+	{ 7, 0x989c, { 0x000014cc, 0x000014cc, 0x000014cc } },
+	{ 7, 0x989c, { 0x0000048c, 0x0000048c, 0x0000048c } },
+	{ 7, 0x98c4, { 0x00000003, 0x00000003, 0x00000003 } },
 };
 
 /* RFX112A (Derby 2) */
@@ -477,6 +388,7 @@ static const struct ath5k_ini_rfbuffer r
 #define	AR5K_RF5112A_XB5_LVL		{ 2, 3,	  3 }
 
 static const struct ath5k_rf_reg rf_regs_5112a[] = {
+	{2, AR5K_RF_TURBO,		AR5K_RF5112X_RF_TURBO},
 	{6, AR5K_RF_OB_2GHZ,		AR5K_RF5112A_OB_2GHZ},
 	{6, AR5K_RF_DB_2GHZ,		AR5K_RF5112A_DB_2GHZ},
 	{6, AR5K_RF_OB_5GHZ,		AR5K_RF5112A_OB_5GHZ},
@@ -515,119 +427,63 @@ static const struct ath5k_rf_reg rf_regs
 
 /* Default mode specific settings */
 static const struct ath5k_ini_rfbuffer rfb_5112a[] = {
-	{ 1, 0x98d4,
-	/*     mode a/XR  mode aTurbo    mode b     mode g    mode gTurbo */
-	    { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } },
-	{ 2, 0x98d0,
-	    { 0x03060408, 0x03070408, 0x03060408, 0x03060408, 0x03070408 } },
-	{ 3, 0x98dc,
-	    { 0x00a020c0, 0x00a020c0, 0x00e020c0, 0x00e020c0, 0x00e020c0 } },
-	{ 6, 0x989c,
-	    { 0x0f000000, 0x0f000000, 0x0f000000, 0x0f000000, 0x0f000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00800000, 0x00800000, 0x00800000, 0x00800000, 0x00800000 } },
-	{ 6, 0x989c,
-	    { 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000 } },
-	{ 6, 0x989c,
-	    { 0x00010000, 0x00010000, 0x00010000, 0x00010000, 0x00010000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00180000, 0x00180000, 0x00180000, 0x00180000, 0x00180000 } },
-	{ 6, 0x989c,
-	    { 0x00600000, 0x00600000, 0x006e0000, 0x006e0000, 0x006e0000 } },
-	{ 6, 0x989c,
-	    { 0x00c70000, 0x00c70000, 0x00c70000, 0x00c70000, 0x00c70000 } },
-	{ 6, 0x989c,
-	    { 0x004b0000, 0x004b0000, 0x004b0000, 0x004b0000, 0x004b0000 } },
-	{ 6, 0x989c,
-	    { 0x04480000, 0x04480000, 0x04480000, 0x04480000, 0x04480000 } },
-	{ 6, 0x989c,
-	    { 0x004c0000, 0x004c0000, 0x004c0000, 0x004c0000, 0x004c0000 } },
-	{ 6, 0x989c,
-	    { 0x00e40000, 0x00e40000, 0x00e40000, 0x00e40000, 0x00e40000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00fc0000, 0x00fc0000, 0x00fc0000, 0x00fc0000, 0x00fc0000 } },
-	{ 6, 0x989c,
-	    { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } },
-	{ 6, 0x989c,
-	    { 0x043f0000, 0x043f0000, 0x043f0000, 0x043f0000, 0x043f0000 } },
-	{ 6, 0x989c,
-	    { 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000 } },
-	{ 6, 0x989c,
-	    { 0x02190000, 0x02190000, 0x02190000, 0x02190000, 0x02190000 } },
-	{ 6, 0x989c,
-	    { 0x00240000, 0x00240000, 0x00240000, 0x00240000, 0x00240000 } },
-	{ 6, 0x989c,
-	    { 0x00b40000, 0x00b40000, 0x00b40000, 0x00b40000, 0x00b40000 } },
-	{ 6, 0x989c,
-	    { 0x00990000, 0x00990000, 0x00990000, 0x00990000, 0x00990000 } },
-	{ 6, 0x989c,
-	    { 0x00500000, 0x00500000, 0x00500000, 0x00500000, 0x00500000 } },
-	{ 6, 0x989c,
-	    { 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000 } },
-	{ 6, 0x989c,
-	    { 0x00120000, 0x00120000, 0x00120000, 0x00120000, 0x00120000 } },
-	{ 6, 0x989c,
-	    { 0xc0320000, 0xc0320000, 0xc0320000, 0xc0320000, 0xc0320000 } },
-	{ 6, 0x989c,
-	    { 0x01740000, 0x01740000, 0x01740000, 0x01740000, 0x01740000 } },
-	{ 6, 0x989c,
-	    { 0x00110000, 0x00110000, 0x00110000, 0x00110000, 0x00110000 } },
-	{ 6, 0x989c,
-	    { 0x86280000, 0x86280000, 0x86280000, 0x86280000, 0x86280000 } },
-	{ 6, 0x989c,
-	    { 0x31840000, 0x31840000, 0x31840000, 0x31840000, 0x31840000 } },
-	{ 6, 0x989c,
-	    { 0x00f20080, 0x00f20080, 0x00f20080, 0x00f20080, 0x00f20080 } },
-	{ 6, 0x989c,
-	    { 0x00270019, 0x00270019, 0x00270019, 0x00270019, 0x00270019 } },
-	{ 6, 0x989c,
-	    { 0x00000003, 0x00000003, 0x00000003, 0x00000003, 0x00000003 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x000000b2, 0x000000b2, 0x000000b2, 0x000000b2, 0x000000b2 } },
-	{ 6, 0x989c,
-	    { 0x00b02084, 0x00b02084, 0x00b02084, 0x00b02084, 0x00b02084 } },
-	{ 6, 0x989c,
-	    { 0x004125a4, 0x004125a4, 0x004125a4, 0x004125a4, 0x004125a4 } },
-	{ 6, 0x989c,
-	    { 0x00119220, 0x00119220, 0x00119220, 0x00119220, 0x00119220 } },
-	{ 6, 0x989c,
-	    { 0x001a4800, 0x001a4800, 0x001a4800, 0x001a4800, 0x001a4800 } },
-	{ 6, 0x98d8,
-	    { 0x000b0230, 0x000b0230, 0x000b0230, 0x000b0230, 0x000b0230 } },
-	{ 7, 0x989c,
-	    { 0x00000094, 0x00000094, 0x00000094, 0x00000094, 0x00000094 } },
-	{ 7, 0x989c,
-	    { 0x00000091, 0x00000091, 0x00000091, 0x00000091, 0x00000091 } },
-	{ 7, 0x989c,
-	    { 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012 } },
-	{ 7, 0x989c,
-	    { 0x00000080, 0x00000080, 0x00000080, 0x00000080, 0x00000080 } },
-	{ 7, 0x989c,
-	    { 0x000000d9, 0x000000d9, 0x000000d9, 0x000000d9, 0x000000d9 } },
-	{ 7, 0x989c,
-	    { 0x00000060, 0x00000060, 0x00000060, 0x00000060, 0x00000060 } },
-	{ 7, 0x989c,
-	    { 0x000000f0, 0x000000f0, 0x000000f0, 0x000000f0, 0x000000f0 } },
-	{ 7, 0x989c,
-	    { 0x000000a2, 0x000000a2, 0x000000a2, 0x000000a2, 0x000000a2 } },
-	{ 7, 0x989c,
-	    { 0x00000052, 0x00000052, 0x00000052, 0x00000052, 0x00000052 } },
-	{ 7, 0x989c,
-	    { 0x000000d4, 0x000000d4, 0x000000d4, 0x000000d4, 0x000000d4 } },
-	{ 7, 0x989c,
-	    { 0x000014cc, 0x000014cc, 0x000014cc, 0x000014cc, 0x000014cc } },
-	{ 7, 0x989c,
-	    { 0x0000048c, 0x0000048c, 0x0000048c, 0x0000048c, 0x0000048c } },
-	{ 7, 0x98c4,
-	    { 0x00000003, 0x00000003, 0x00000003, 0x00000003, 0x00000003 } },
+	/* BANK / C.R.     A/XR         B           G      */
+	{ 1, 0x98d4, { 0x00000020, 0x00000020, 0x00000020 } },
+	{ 2, 0x98d0, { 0x03060408, 0x03060408, 0x03060408 } },
+	{ 3, 0x98dc, { 0x00a020c0, 0x00e020c0, 0x00e020c0 } },
+	{ 6, 0x989c, { 0x0f000000, 0x0f000000, 0x0f000000 } },
+	{ 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c, { 0x00800000, 0x00800000, 0x00800000 } },
+	{ 6, 0x989c, { 0x002a0000, 0x002a0000, 0x002a0000 } },
+	{ 6, 0x989c, { 0x00010000, 0x00010000, 0x00010000 } },
+	{ 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c, { 0x00180000, 0x00180000, 0x00180000 } },
+	{ 6, 0x989c, { 0x00600000, 0x006e0000, 0x006e0000 } },
+	{ 6, 0x989c, { 0x00c70000, 0x00c70000, 0x00c70000 } },
+	{ 6, 0x989c, { 0x004b0000, 0x004b0000, 0x004b0000 } },
+	{ 6, 0x989c, { 0x04480000, 0x04480000, 0x04480000 } },
+	{ 6, 0x989c, { 0x004c0000, 0x004c0000, 0x004c0000 } },
+	{ 6, 0x989c, { 0x00e40000, 0x00e40000, 0x00e40000 } },
+	{ 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c, { 0x00fc0000, 0x00fc0000, 0x00fc0000 } },
+	{ 6, 0x989c, { 0x00ff0000, 0x00ff0000, 0x00ff0000 } },
+	{ 6, 0x989c, { 0x043f0000, 0x043f0000, 0x043f0000 } },
+	{ 6, 0x989c, { 0x000c0000, 0x000c0000, 0x000c0000 } },
+	{ 6, 0x989c, { 0x02190000, 0x02190000, 0x02190000 } },
+	{ 6, 0x989c, { 0x00240000, 0x00240000, 0x00240000 } },
+	{ 6, 0x989c, { 0x00b40000, 0x00b40000, 0x00b40000 } },
+	{ 6, 0x989c, { 0x00990000, 0x00990000, 0x00990000 } },
+	{ 6, 0x989c, { 0x00500000, 0x00500000, 0x00500000 } },
+	{ 6, 0x989c, { 0x002a0000, 0x002a0000, 0x002a0000 } },
+	{ 6, 0x989c, { 0x00120000, 0x00120000, 0x00120000 } },
+	{ 6, 0x989c, { 0xc0320000, 0xc0320000, 0xc0320000 } },
+	{ 6, 0x989c, { 0x01740000, 0x01740000, 0x01740000 } },
+	{ 6, 0x989c, { 0x00110000, 0x00110000, 0x00110000 } },
+	{ 6, 0x989c, { 0x86280000, 0x86280000, 0x86280000 } },
+	{ 6, 0x989c, { 0x31840000, 0x31840000, 0x31840000 } },
+	{ 6, 0x989c, { 0x00f20080, 0x00f20080, 0x00f20080 } },
+	{ 6, 0x989c, { 0x00270019, 0x00270019, 0x00270019 } },
+	{ 6, 0x989c, { 0x00000003, 0x00000003, 0x00000003 } },
+	{ 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c, { 0x000000b2, 0x000000b2, 0x000000b2 } },
+	{ 6, 0x989c, { 0x00b02084, 0x00b02084, 0x00b02084 } },
+	{ 6, 0x989c, { 0x004125a4, 0x004125a4, 0x004125a4 } },
+	{ 6, 0x989c, { 0x00119220, 0x00119220, 0x00119220 } },
+	{ 6, 0x989c, { 0x001a4800, 0x001a4800, 0x001a4800 } },
+	{ 6, 0x98d8, { 0x000b0230, 0x000b0230, 0x000b0230 } },
+	{ 7, 0x989c, { 0x00000094, 0x00000094, 0x00000094 } },
+	{ 7, 0x989c, { 0x00000091, 0x00000091, 0x00000091 } },
+	{ 7, 0x989c, { 0x00000012, 0x00000012, 0x00000012 } },
+	{ 7, 0x989c, { 0x00000080, 0x00000080, 0x00000080 } },
+	{ 7, 0x989c, { 0x000000d9, 0x000000d9, 0x000000d9 } },
+	{ 7, 0x989c, { 0x00000060, 0x00000060, 0x00000060 } },
+	{ 7, 0x989c, { 0x000000f0, 0x000000f0, 0x000000f0 } },
+	{ 7, 0x989c, { 0x000000a2, 0x000000a2, 0x000000a2 } },
+	{ 7, 0x989c, { 0x00000052, 0x00000052, 0x00000052 } },
+	{ 7, 0x989c, { 0x000000d4, 0x000000d4, 0x000000d4 } },
+	{ 7, 0x989c, { 0x000014cc, 0x000014cc, 0x000014cc } },
+	{ 7, 0x989c, { 0x0000048c, 0x0000048c, 0x0000048c } },
+	{ 7, 0x98c4, { 0x00000003, 0x00000003, 0x00000003 } },
 };
 
 
@@ -636,11 +492,15 @@ static const struct ath5k_ini_rfbuffer r
 * RF2413 (Griffin) *
 \******************/
 
+/* BANK 2				len  pos col */
+#define AR5K_RF2413_RF_TURBO		{ 1, 1,   2 }
+
 /* BANK 6 				len  pos col */
 #define	AR5K_RF2413_OB_2GHZ		{ 3, 168, 0 }
 #define	AR5K_RF2413_DB_2GHZ		{ 3, 165, 0 }
 
 static const struct ath5k_rf_reg rf_regs_2413[] = {
+	{2, AR5K_RF_TURBO,		AR5K_RF2413_RF_TURBO},
 	{6, AR5K_RF_OB_2GHZ,		AR5K_RF2413_OB_2GHZ},
 	{6, AR5K_RF_DB_2GHZ,		AR5K_RF2413_DB_2GHZ},
 };
@@ -649,73 +509,40 @@ static const struct ath5k_rf_reg rf_regs
  * XXX: a/aTurbo ???
  */
 static const struct ath5k_ini_rfbuffer rfb_2413[] = {
-	{ 1, 0x98d4,
-	/*     mode a/XR  mode aTurbo    mode b     mode g    mode gTurbo */
-	    { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } },
-	{ 2, 0x98d0,
-	    { 0x02001408, 0x02011408, 0x02001408, 0x02001408, 0x02011408 } },
-	{ 3, 0x98dc,
-	    { 0x00a020c0, 0x00a020c0, 0x00e020c0, 0x00e020c0, 0x00e020c0 } },
-	{ 6, 0x989c,
-	    { 0xf0000000, 0xf0000000, 0xf0000000, 0xf0000000, 0xf0000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x03000000, 0x03000000, 0x03000000, 0x03000000, 0x03000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x40400000, 0x40400000, 0x40400000, 0x40400000, 0x40400000 } },
-	{ 6, 0x989c,
-	    { 0x65050000, 0x65050000, 0x65050000, 0x65050000, 0x65050000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00420000, 0x00420000, 0x00420000, 0x00420000, 0x00420000 } },
-	{ 6, 0x989c,
-	    { 0x00b50000, 0x00b50000, 0x00b50000, 0x00b50000, 0x00b50000 } },
-	{ 6, 0x989c,
-	    { 0x00030000, 0x00030000, 0x00030000, 0x00030000, 0x00030000 } },
-	{ 6, 0x989c,
-	    { 0x00f70000, 0x00f70000, 0x00f70000, 0x00f70000, 0x00f70000 } },
-	{ 6, 0x989c,
-	    { 0x009d0000, 0x009d0000, 0x009d0000, 0x009d0000, 0x009d0000 } },
-	{ 6, 0x989c,
-	    { 0x00220000, 0x00220000, 0x00220000, 0x00220000, 0x00220000 } },
-	{ 6, 0x989c,
-	    { 0x04220000, 0x04220000, 0x04220000, 0x04220000, 0x04220000 } },
-	{ 6, 0x989c,
-	    { 0x00230018, 0x00230018, 0x00230018, 0x00230018, 0x00230018 } },
-	{ 6, 0x989c,
-	    { 0x00280000, 0x00280000, 0x00280060, 0x00280060, 0x00280060 } },
-	{ 6, 0x989c,
-	    { 0x005000c0, 0x005000c0, 0x005000c3, 0x005000c3, 0x005000c3 } },
-	{ 6, 0x989c,
-	    { 0x0004007f, 0x0004007f, 0x0004007f, 0x0004007f, 0x0004007f } },
-	{ 6, 0x989c,
-	    { 0x00000458, 0x00000458, 0x00000458, 0x00000458, 0x00000458 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x0000c000, 0x0000c000, 0x0000c000, 0x0000c000, 0x0000c000 } },
-	{ 6, 0x98d8,
-	    { 0x00400230, 0x00400230, 0x00400230, 0x00400230, 0x00400230 } },
-	{ 7, 0x989c,
-	    { 0x00006400, 0x00006400, 0x00006400, 0x00006400, 0x00006400 } },
-	{ 7, 0x989c,
-	    { 0x00000800, 0x00000800, 0x00000800, 0x00000800, 0x00000800 } },
-	{ 7, 0x98cc,
-	    { 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e } },
+	/* BANK / C.R.     A/XR         B           G      */
+	{ 1, 0x98d4, { 0x00000020, 0x00000020, 0x00000020 } },
+	{ 2, 0x98d0, { 0x02001408, 0x02001408, 0x02001408 } },
+	{ 3, 0x98dc, { 0x00a020c0, 0x00e020c0, 0x00e020c0 } },
+	{ 6, 0x989c, { 0xf0000000, 0xf0000000, 0xf0000000 } },
+	{ 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c, { 0x03000000, 0x03000000, 0x03000000 } },
+	{ 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c, { 0x40400000, 0x40400000, 0x40400000 } },
+	{ 6, 0x989c, { 0x65050000, 0x65050000, 0x65050000 } },
+	{ 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c, { 0x00420000, 0x00420000, 0x00420000 } },
+	{ 6, 0x989c, { 0x00b50000, 0x00b50000, 0x00b50000 } },
+	{ 6, 0x989c, { 0x00030000, 0x00030000, 0x00030000 } },
+	{ 6, 0x989c, { 0x00f70000, 0x00f70000, 0x00f70000 } },
+	{ 6, 0x989c, { 0x009d0000, 0x009d0000, 0x009d0000 } },
+	{ 6, 0x989c, { 0x00220000, 0x00220000, 0x00220000 } },
+	{ 6, 0x989c, { 0x04220000, 0x04220000, 0x04220000 } },
+	{ 6, 0x989c, { 0x00230018, 0x00230018, 0x00230018 } },
+	{ 6, 0x989c, { 0x00280000, 0x00280060, 0x00280060 } },
+	{ 6, 0x989c, { 0x005000c0, 0x005000c3, 0x005000c3 } },
+	{ 6, 0x989c, { 0x0004007f, 0x0004007f, 0x0004007f } },
+	{ 6, 0x989c, { 0x00000458, 0x00000458, 0x00000458 } },
+	{ 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c, { 0x0000c000, 0x0000c000, 0x0000c000 } },
+	{ 6, 0x98d8, { 0x00400230, 0x00400230, 0x00400230 } },
+	{ 7, 0x989c, { 0x00006400, 0x00006400, 0x00006400 } },
+	{ 7, 0x989c, { 0x00000800, 0x00000800, 0x00000800 } },
+	{ 7, 0x98cc, { 0x0000000e, 0x0000000e, 0x0000000e } },
 };
 
 
@@ -724,88 +551,57 @@ static const struct ath5k_ini_rfbuffer r
 * RF2315/RF2316 (Cobra SoC) *
 \***************************/
 
+/* BANK 2				len  pos col */
+#define	AR5K_RF2316_RF_TURBO		{ 1, 1,   2 }
+
 /* BANK 6				len  pos col */
 #define	AR5K_RF2316_OB_2GHZ		{ 3, 178, 0 }
 #define	AR5K_RF2316_DB_2GHZ		{ 3, 175, 0 }
 
 static const struct ath5k_rf_reg rf_regs_2316[] = {
+	{2, AR5K_RF_TURBO,		AR5K_RF2316_RF_TURBO},
 	{6, AR5K_RF_OB_2GHZ,		AR5K_RF2316_OB_2GHZ},
 	{6, AR5K_RF_DB_2GHZ,		AR5K_RF2316_DB_2GHZ},
 };
 
 /* Default mode specific settings */
 static const struct ath5k_ini_rfbuffer rfb_2316[] = {
-	{ 1, 0x98d4,
-	/*     mode a/XR  mode aTurbo    mode b     mode g    mode gTurbo */
-	    { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } },
-	{ 2, 0x98d0,
-	    { 0x02001408, 0x02011408, 0x02001408, 0x02001408, 0x02011408 } },
-	{ 3, 0x98dc,
-	    { 0x00a020c0, 0x00a020c0, 0x00e020c0, 0x00e020c0, 0x00e020c0 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0xc0000000, 0xc0000000, 0xc0000000, 0xc0000000, 0xc0000000 } },
-	{ 6, 0x989c,
-	    { 0x0f000000, 0x0f000000, 0x0f000000, 0x0f000000, 0x0f000000 } },
-	{ 6, 0x989c,
-	    { 0x02000000, 0x02000000, 0x02000000, 0x02000000, 0x02000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0xf8000000, 0xf8000000, 0xf8000000, 0xf8000000, 0xf8000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x95150000, 0x95150000, 0x95150000, 0x95150000, 0x95150000 } },
-	{ 6, 0x989c,
-	    { 0xc1000000, 0xc1000000, 0xc1000000, 0xc1000000, 0xc1000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00080000, 0x00080000, 0x00080000, 0x00080000, 0x00080000 } },
-	{ 6, 0x989c,
-	    { 0x00d50000, 0x00d50000, 0x00d50000, 0x00d50000, 0x00d50000 } },
-	{ 6, 0x989c,
-	    { 0x000e0000, 0x000e0000, 0x000e0000, 0x000e0000, 0x000e0000 } },
-	{ 6, 0x989c,
-	    { 0x00dc0000, 0x00dc0000, 0x00dc0000, 0x00dc0000, 0x00dc0000 } },
-	{ 6, 0x989c,
-	    { 0x00770000, 0x00770000, 0x00770000, 0x00770000, 0x00770000 } },
-	{ 6, 0x989c,
-	    { 0x008a0000, 0x008a0000, 0x008a0000, 0x008a0000, 0x008a0000 } },
-	{ 6, 0x989c,
-	    { 0x10880000, 0x10880000, 0x10880000, 0x10880000, 0x10880000 } },
-	{ 6, 0x989c,
-	    { 0x008c0060, 0x008c0060, 0x008c0060, 0x008c0060, 0x008c0060 } },
-	{ 6, 0x989c,
-	    { 0x00a00000, 0x00a00000, 0x00a00080, 0x00a00080, 0x00a00080 } },
-	{ 6, 0x989c,
-	    { 0x00400000, 0x00400000, 0x0040000d, 0x0040000d, 0x0040000d } },
-	{ 6, 0x989c,
-	    { 0x00110400, 0x00110400, 0x00110400, 0x00110400, 0x00110400 } },
-	{ 6, 0x989c,
-	    { 0x00000060, 0x00000060, 0x00000060, 0x00000060, 0x00000060 } },
-	{ 6, 0x989c,
-	    { 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001 } },
-	{ 6, 0x989c,
-	    { 0x00000b00, 0x00000b00, 0x00000b00, 0x00000b00, 0x00000b00 } },
-	{ 6, 0x989c,
-	    { 0x00000be8, 0x00000be8, 0x00000be8, 0x00000be8, 0x00000be8 } },
-	{ 6, 0x98c0,
-	    { 0x00010000, 0x00010000, 0x00010000, 0x00010000, 0x00010000 } },
-	{ 7, 0x989c,
-	    { 0x00006400, 0x00006400, 0x00006400, 0x00006400, 0x00006400 } },
-	{ 7, 0x989c,
-	    { 0x00000800, 0x00000800, 0x00000800, 0x00000800, 0x00000800 } },
-	{ 7, 0x98cc,
-	    { 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e } },
+	/* BANK / C.R.     A/XR         B           G      */
+	{ 1, 0x98d4, { 0x00000020, 0x00000020, 0x00000020 } },
+	{ 2, 0x98d0, { 0x02001408, 0x02001408, 0x02001408 } },
+	{ 3, 0x98dc, { 0x00a020c0, 0x00e020c0, 0x00e020c0 } },
+	{ 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c, { 0xc0000000, 0xc0000000, 0xc0000000 } },
+	{ 6, 0x989c, { 0x0f000000, 0x0f000000, 0x0f000000 } },
+	{ 6, 0x989c, { 0x02000000, 0x02000000, 0x02000000 } },
+	{ 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c, { 0xf8000000, 0xf8000000, 0xf8000000 } },
+	{ 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c, { 0x95150000, 0x95150000, 0x95150000 } },
+	{ 6, 0x989c, { 0xc1000000, 0xc1000000, 0xc1000000 } },
+	{ 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c, { 0x00080000, 0x00080000, 0x00080000 } },
+	{ 6, 0x989c, { 0x00d50000, 0x00d50000, 0x00d50000 } },
+	{ 6, 0x989c, { 0x000e0000, 0x000e0000, 0x000e0000 } },
+	{ 6, 0x989c, { 0x00dc0000, 0x00dc0000, 0x00dc0000 } },
+	{ 6, 0x989c, { 0x00770000, 0x00770000, 0x00770000 } },
+	{ 6, 0x989c, { 0x008a0000, 0x008a0000, 0x008a0000 } },
+	{ 6, 0x989c, { 0x10880000, 0x10880000, 0x10880000 } },
+	{ 6, 0x989c, { 0x008c0060, 0x008c0060, 0x008c0060 } },
+	{ 6, 0x989c, { 0x00a00000, 0x00a00080, 0x00a00080 } },
+	{ 6, 0x989c, { 0x00400000, 0x0040000d, 0x0040000d } },
+	{ 6, 0x989c, { 0x00110400, 0x00110400, 0x00110400 } },
+	{ 6, 0x989c, { 0x00000060, 0x00000060, 0x00000060 } },
+	{ 6, 0x989c, { 0x00000001, 0x00000001, 0x00000001 } },
+	{ 6, 0x989c, { 0x00000b00, 0x00000b00, 0x00000b00 } },
+	{ 6, 0x989c, { 0x00000be8, 0x00000be8, 0x00000be8 } },
+	{ 6, 0x98c0, { 0x00010000, 0x00010000, 0x00010000 } },
+	{ 7, 0x989c, { 0x00006400, 0x00006400, 0x00006400 } },
+	{ 7, 0x989c, { 0x00000800, 0x00000800, 0x00000800 } },
+	{ 7, 0x98cc, { 0x0000000e, 0x0000000e, 0x0000000e } },
 };
 
 
@@ -835,93 +631,50 @@ static const struct ath5k_rf_reg rf_regs
 
 /* Default mode specific settings */
 static const struct ath5k_ini_rfbuffer rfb_5413[] = {
-	{ 1, 0x98d4,
-	/*     mode a/XR  mode aTurbo    mode b     mode g    mode gTurbo */
-	    { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } },
-	{ 2, 0x98d0,
-	    { 0x00000008, 0x00000008, 0x00000008, 0x00000008, 0x00000008 } },
-	{ 3, 0x98dc,
-	    { 0x00a000c0, 0x00a000c0, 0x00e000c0, 0x00e000c0, 0x00e000c0 } },
-	{ 6, 0x989c,
-	    { 0x33000000, 0x33000000, 0x33000000, 0x33000000, 0x33000000 } },
-	{ 6, 0x989c,
-	    { 0x01000000, 0x01000000, 0x01000000, 0x01000000, 0x01000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x1f000000, 0x1f000000, 0x1f000000, 0x1f000000, 0x1f000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00b80000, 0x00b80000, 0x00b80000, 0x00b80000, 0x00b80000 } },
-	{ 6, 0x989c,
-	    { 0x00b70000, 0x00b70000, 0x00b70000, 0x00b70000, 0x00b70000 } },
-	{ 6, 0x989c,
-	    { 0x00840000, 0x00840000, 0x00840000, 0x00840000, 0x00840000 } },
-	{ 6, 0x989c,
-	    { 0x00980000, 0x00980000, 0x00980000, 0x00980000, 0x00980000 } },
-	{ 6, 0x989c,
-	    { 0x00c00000, 0x00c00000, 0x00c00000, 0x00c00000, 0x00c00000 } },
-	{ 6, 0x989c,
-	    { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } },
-	{ 6, 0x989c,
-	    { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } },
-	{ 6, 0x989c,
-	    { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } },
-	{ 6, 0x989c,
-	    { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } },
-	{ 6, 0x989c,
-	    { 0x00d70000, 0x00d70000, 0x00d70000, 0x00d70000, 0x00d70000 } },
-	{ 6, 0x989c,
-	    { 0x00610000, 0x00610000, 0x00610000, 0x00610000, 0x00610000 } },
-	{ 6, 0x989c,
-	    { 0x00fe0000, 0x00fe0000, 0x00fe0000, 0x00fe0000, 0x00fe0000 } },
-	{ 6, 0x989c,
-	    { 0x00de0000, 0x00de0000, 0x00de0000, 0x00de0000, 0x00de0000 } },
-	{ 6, 0x989c,
-	    { 0x007f0000, 0x007f0000, 0x007f0000, 0x007f0000, 0x007f0000 } },
-	{ 6, 0x989c,
-	    { 0x043d0000, 0x043d0000, 0x043d0000, 0x043d0000, 0x043d0000 } },
-	{ 6, 0x989c,
-	    { 0x00770000, 0x00770000, 0x00770000, 0x00770000, 0x00770000 } },
-	{ 6, 0x989c,
-	    { 0x00440000, 0x00440000, 0x00440000, 0x00440000, 0x00440000 } },
-	{ 6, 0x989c,
-	    { 0x00980000, 0x00980000, 0x00980000, 0x00980000, 0x00980000 } },
-	{ 6, 0x989c,
-	    { 0x00100080, 0x00100080, 0x00100080, 0x00100080, 0x00100080 } },
-	{ 6, 0x989c,
-	    { 0x0005c034, 0x0005c034, 0x0005c034, 0x0005c034, 0x0005c034 } },
-	{ 6, 0x989c,
-	    { 0x003100f0, 0x003100f0, 0x003100f0, 0x003100f0, 0x003100f0 } },
-	{ 6, 0x989c,
-	    { 0x000c011f, 0x000c011f, 0x000c011f, 0x000c011f, 0x000c011f } },
-	{ 6, 0x989c,
-	    { 0x00510040, 0x00510040, 0x00510040, 0x00510040, 0x00510040 } },
-	{ 6, 0x989c,
-	    { 0x005000da, 0x005000da, 0x005000da, 0x005000da, 0x005000da } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00004044, 0x00004044, 0x00004044, 0x00004044, 0x00004044 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x000060c0, 0x000060c0, 0x000060c0, 0x000060c0, 0x000060c0 } },
-	{ 6, 0x989c,
-	    { 0x00002c00, 0x00002c00, 0x00003600, 0x00003600, 0x00002c00 } },
-	{ 6, 0x98c8,
-	    { 0x00000403, 0x00000403, 0x00040403, 0x00040403, 0x00040403 } },
-	{ 7, 0x989c,
-	    { 0x00006400, 0x00006400, 0x00006400, 0x00006400, 0x00006400 } },
-	{ 7, 0x989c,
-	    { 0x00000800, 0x00000800, 0x00000800, 0x00000800, 0x00000800 } },
-	{ 7, 0x98cc,
-	    { 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e } },
+	/* BANK / C.R.     A/XR         B           G      */
+	{ 1, 0x98d4, { 0x00000020, 0x00000020, 0x00000020 } },
+	{ 2, 0x98d0, { 0x00000008, 0x00000008, 0x00000008 } },
+	{ 3, 0x98dc, { 0x00a000c0, 0x00e000c0, 0x00e000c0 } },
+	{ 6, 0x989c, { 0x33000000, 0x33000000, 0x33000000 } },
+	{ 6, 0x989c, { 0x01000000, 0x01000000, 0x01000000 } },
+	{ 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c, { 0x1f000000, 0x1f000000, 0x1f000000 } },
+	{ 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c, { 0x00b80000, 0x00b80000, 0x00b80000 } },
+	{ 6, 0x989c, { 0x00b70000, 0x00b70000, 0x00b70000 } },
+	{ 6, 0x989c, { 0x00840000, 0x00840000, 0x00840000 } },
+	{ 6, 0x989c, { 0x00980000, 0x00980000, 0x00980000 } },
+	{ 6, 0x989c, { 0x00c00000, 0x00c00000, 0x00c00000 } },
+	{ 6, 0x989c, { 0x00ff0000, 0x00ff0000, 0x00ff0000 } },
+	{ 6, 0x989c, { 0x00ff0000, 0x00ff0000, 0x00ff0000 } },
+	{ 6, 0x989c, { 0x00ff0000, 0x00ff0000, 0x00ff0000 } },
+	{ 6, 0x989c, { 0x00ff0000, 0x00ff0000, 0x00ff0000 } },
+	{ 6, 0x989c, { 0x00d70000, 0x00d70000, 0x00d70000 } },
+	{ 6, 0x989c, { 0x00610000, 0x00610000, 0x00610000 } },
+	{ 6, 0x989c, { 0x00fe0000, 0x00fe0000, 0x00fe0000 } },
+	{ 6, 0x989c, { 0x00de0000, 0x00de0000, 0x00de0000 } },
+	{ 6, 0x989c, { 0x007f0000, 0x007f0000, 0x007f0000 } },
+	{ 6, 0x989c, { 0x043d0000, 0x043d0000, 0x043d0000 } },
+	{ 6, 0x989c, { 0x00770000, 0x00770000, 0x00770000 } },
+	{ 6, 0x989c, { 0x00440000, 0x00440000, 0x00440000 } },
+	{ 6, 0x989c, { 0x00980000, 0x00980000, 0x00980000 } },
+	{ 6, 0x989c, { 0x00100080, 0x00100080, 0x00100080 } },
+	{ 6, 0x989c, { 0x0005c034, 0x0005c034, 0x0005c034 } },
+	{ 6, 0x989c, { 0x003100f0, 0x003100f0, 0x003100f0 } },
+	{ 6, 0x989c, { 0x000c011f, 0x000c011f, 0x000c011f } },
+	{ 6, 0x989c, { 0x00510040, 0x00510040, 0x00510040 } },
+	{ 6, 0x989c, { 0x005000da, 0x005000da, 0x005000da } },
+	{ 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c, { 0x00004044, 0x00004044, 0x00004044 } },
+	{ 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c, { 0x000060c0, 0x000060c0, 0x000060c0 } },
+	{ 6, 0x989c, { 0x00002c00, 0x00003600, 0x00003600 } },
+	{ 6, 0x98c8, { 0x00000403, 0x00040403, 0x00040403 } },
+	{ 7, 0x989c, { 0x00006400, 0x00006400, 0x00006400 } },
+	{ 7, 0x989c, { 0x00000800, 0x00000800, 0x00000800 } },
+	{ 7, 0x98cc, { 0x0000000e, 0x0000000e, 0x0000000e } },
 };
 
 
@@ -931,92 +684,59 @@ static const struct ath5k_ini_rfbuffer r
 * AR2317 (Spider SoC)       *
 \***************************/
 
+/* BANK 2				len  pos col */
+#define AR5K_RF2425_RF_TURBO		{ 1, 1,   2 }
+
 /* BANK 6				len  pos col */
 #define	AR5K_RF2425_OB_2GHZ		{ 3, 193, 0 }
 #define	AR5K_RF2425_DB_2GHZ		{ 3, 190, 0 }
 
 static const struct ath5k_rf_reg rf_regs_2425[] = {
+	{2, AR5K_RF_TURBO,		AR5K_RF2425_RF_TURBO},
 	{6, AR5K_RF_OB_2GHZ,		AR5K_RF2425_OB_2GHZ},
 	{6, AR5K_RF_DB_2GHZ,		AR5K_RF2425_DB_2GHZ},
 };
 
 /* Default mode specific settings
- * XXX: a/aTurbo ?
  */
 static const struct ath5k_ini_rfbuffer rfb_2425[] = {
-	{ 1, 0x98d4,
-	/*     mode a/XR  mode aTurbo    mode b     mode g    mode gTurbo */
-	    { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } },
-	{ 2, 0x98d0,
-	    { 0x02001408, 0x02001408, 0x02001408, 0x02001408, 0x02001408 } },
-	{ 3, 0x98dc,
-	    { 0x00a020c0, 0x00a020c0, 0x00e020c0, 0x00e020c0, 0x00e020c0 } },
-	{ 6, 0x989c,
-	    { 0x10000000, 0x10000000, 0x10000000, 0x10000000, 0x10000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00100000, 0x00100000, 0x00100000, 0x00100000, 0x00100000 } },
-	{ 6, 0x989c,
-	    { 0x00020000, 0x00020000, 0x00020000, 0x00020000, 0x00020000 } },
-	{ 6, 0x989c,
-	    { 0x00730000, 0x00730000, 0x00730000, 0x00730000, 0x00730000 } },
-	{ 6, 0x989c,
-	    { 0x00f80000, 0x00f80000, 0x00f80000, 0x00f80000, 0x00f80000 } },
-	{ 6, 0x989c,
-	    { 0x00e70000, 0x00e70000, 0x00e70000, 0x00e70000, 0x00e70000 } },
-	{ 6, 0x989c,
-	    { 0x00140000, 0x00140000, 0x00140000, 0x00140000, 0x00140000 } },
-	{ 6, 0x989c,
-	    { 0x00910040, 0x00910040, 0x00910040, 0x00910040, 0x00910040 } },
-	{ 6, 0x989c,
-	    { 0x0007001a, 0x0007001a, 0x0007001a, 0x0007001a, 0x0007001a } },
-	{ 6, 0x989c,
-	    { 0x00410000, 0x00410000, 0x00410000, 0x00410000, 0x00410000 } },
-	{ 6, 0x989c,
-	    { 0x00810000, 0x00810000, 0x00810060, 0x00810060, 0x00810060 } },
-	{ 6, 0x989c,
-	    { 0x00020800, 0x00020800, 0x00020803, 0x00020803, 0x00020803 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00001660, 0x00001660, 0x00001660, 0x00001660, 0x00001660 } },
-	{ 6, 0x989c,
-	    { 0x00001688, 0x00001688, 0x00001688, 0x00001688, 0x00001688 } },
-	{ 6, 0x98c4,
-	    { 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001 } },
-	{ 7, 0x989c,
-	    { 0x00006400, 0x00006400, 0x00006400, 0x00006400, 0x00006400 } },
-	{ 7, 0x989c,
-	    { 0x00000800, 0x00000800, 0x00000800, 0x00000800, 0x00000800 } },
-	{ 7, 0x98cc,
-	    { 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e } },
+	/* BANK / C.R.     A/XR         B           G      */
+	{ 1, 0x98d4, { 0x00000020, 0x00000020, 0x00000020 } },
+	{ 2, 0x98d0, { 0x02001408, 0x02001408, 0x02001408 } },
+	{ 3, 0x98dc, { 0x00a020c0, 0x00e020c0, 0x00e020c0 } },
+	{ 6, 0x989c, { 0x10000000, 0x10000000, 0x10000000 } },
+	{ 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c, { 0x002a0000, 0x002a0000, 0x002a0000 } },
+	{ 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c, { 0x00100000, 0x00100000, 0x00100000 } },
+	{ 6, 0x989c, { 0x00020000, 0x00020000, 0x00020000 } },
+	{ 6, 0x989c, { 0x00730000, 0x00730000, 0x00730000 } },
+	{ 6, 0x989c, { 0x00f80000, 0x00f80000, 0x00f80000 } },
+	{ 6, 0x989c, { 0x00e70000, 0x00e70000, 0x00e70000 } },
+	{ 6, 0x989c, { 0x00140000, 0x00140000, 0x00140000 } },
+	{ 6, 0x989c, { 0x00910040, 0x00910040, 0x00910040 } },
+	{ 6, 0x989c, { 0x0007001a, 0x0007001a, 0x0007001a } },
+	{ 6, 0x989c, { 0x00410000, 0x00410000, 0x00410000 } },
+	{ 6, 0x989c, { 0x00810000, 0x00810060, 0x00810060 } },
+	{ 6, 0x989c, { 0x00020800, 0x00020803, 0x00020803 } },
+	{ 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c, { 0x00001660, 0x00001660, 0x00001660 } },
+	{ 6, 0x989c, { 0x00001688, 0x00001688, 0x00001688 } },
+	{ 6, 0x98c4, { 0x00000001, 0x00000001, 0x00000001 } },
+	{ 7, 0x989c, { 0x00006400, 0x00006400, 0x00006400 } },
+	{ 7, 0x989c, { 0x00000800, 0x00000800, 0x00000800 } },
+	{ 7, 0x98cc, { 0x0000000e, 0x0000000e, 0x0000000e } },
 };
 
 /*
@@ -1024,158 +744,85 @@ static const struct ath5k_ini_rfbuffer r
  * bank modification and get rid of this
  */
 static const struct ath5k_ini_rfbuffer rfb_2317[] = {
-	{ 1, 0x98d4,
-	/*     mode a/XR  mode aTurbo    mode b     mode g    mode gTurbo */
-	    { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } },
-	{ 2, 0x98d0,
-	    { 0x02001408, 0x02011408, 0x02001408, 0x02001408, 0x02011408 } },
-	{ 3, 0x98dc,
-	    { 0x00a020c0, 0x00a020c0, 0x00e020c0, 0x00e020c0, 0x00e020c0 } },
-	{ 6, 0x989c,
-	    { 0x10000000, 0x10000000, 0x10000000, 0x10000000, 0x10000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00100000, 0x00100000, 0x00100000, 0x00100000, 0x00100000 } },
-	{ 6, 0x989c,
-	    { 0x00020000, 0x00020000, 0x00020000, 0x00020000, 0x00020000 } },
-	{ 6, 0x989c,
-	    { 0x00730000, 0x00730000, 0x00730000, 0x00730000, 0x00730000 } },
-	{ 6, 0x989c,
-	    { 0x00f80000, 0x00f80000, 0x00f80000, 0x00f80000, 0x00f80000 } },
-	{ 6, 0x989c,
-	    { 0x00e70000, 0x00e70000, 0x00e70000, 0x00e70000, 0x00e70000 } },
-	{ 6, 0x989c,
-	    { 0x00140100, 0x00140100, 0x00140100, 0x00140100, 0x00140100 } },
-	{ 6, 0x989c,
-	    { 0x00910040, 0x00910040, 0x00910040, 0x00910040, 0x00910040 } },
-	{ 6, 0x989c,
-	    { 0x0007001a, 0x0007001a, 0x0007001a, 0x0007001a, 0x0007001a } },
-	{ 6, 0x989c,
-	    { 0x00410000, 0x00410000, 0x00410000, 0x00410000, 0x00410000 } },
-	{ 6, 0x989c,
-	    { 0x00810000, 0x00810000, 0x00810060, 0x00810060, 0x00810060 } },
-	{ 6, 0x989c,
-	    { 0x00020800, 0x00020800, 0x00020803, 0x00020803, 0x00020803 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00001660, 0x00001660, 0x00001660, 0x00001660, 0x00001660 } },
-	{ 6, 0x989c,
-	    { 0x00009688, 0x00009688, 0x00009688, 0x00009688, 0x00009688 } },
-	{ 6, 0x98c4,
-	    { 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001 } },
-	{ 7, 0x989c,
-	    { 0x00006400, 0x00006400, 0x00006400, 0x00006400, 0x00006400 } },
-	{ 7, 0x989c,
-	    { 0x00000800, 0x00000800, 0x00000800, 0x00000800, 0x00000800 } },
-	{ 7, 0x98cc,
-	    { 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e } },
+	/* BANK / C.R.     A/XR         B           G      */
+	{ 1, 0x98d4, { 0x00000020, 0x00000020, 0x00000020 } },
+	{ 2, 0x98d0, { 0x02001408, 0x02001408, 0x02001408 } },
+	{ 3, 0x98dc, { 0x00a020c0, 0x00e020c0, 0x00e020c0 } },
+	{ 6, 0x989c, { 0x10000000, 0x10000000, 0x10000000 } },
+	{ 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c, { 0x002a0000, 0x002a0000, 0x002a0000 } },
+	{ 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c, { 0x00100000, 0x00100000, 0x00100000 } },
+	{ 6, 0x989c, { 0x00020000, 0x00020000, 0x00020000 } },
+	{ 6, 0x989c, { 0x00730000, 0x00730000, 0x00730000 } },
+	{ 6, 0x989c, { 0x00f80000, 0x00f80000, 0x00f80000 } },
+	{ 6, 0x989c, { 0x00e70000, 0x00e70000, 0x00e70000 } },
+	{ 6, 0x989c, { 0x00140100, 0x00140100, 0x00140100 } },
+	{ 6, 0x989c, { 0x00910040, 0x00910040, 0x00910040 } },
+	{ 6, 0x989c, { 0x0007001a, 0x0007001a, 0x0007001a } },
+	{ 6, 0x989c, { 0x00410000, 0x00410000, 0x00410000 } },
+	{ 6, 0x989c, { 0x00810000, 0x00810060, 0x00810060 } },
+	{ 6, 0x989c, { 0x00020800, 0x00020803, 0x00020803 } },
+	{ 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c, { 0x00001660, 0x00001660, 0x00001660 } },
+	{ 6, 0x989c, { 0x00009688, 0x00009688, 0x00009688 } },
+	{ 6, 0x98c4, { 0x00000001, 0x00000001, 0x00000001 } },
+	{ 7, 0x989c, { 0x00006400, 0x00006400, 0x00006400 } },
+	{ 7, 0x989c, { 0x00000800, 0x00000800, 0x00000800 } },
+	{ 7, 0x98cc, { 0x0000000e, 0x0000000e, 0x0000000e } },
 };
 
 /*
  * TODO: Handle the few differences with swan during
  * bank modification and get rid of this
- * XXX: a/aTurbo ?
  */
 static const struct ath5k_ini_rfbuffer rfb_2417[] = {
-	{ 1, 0x98d4,
-	/*     mode a/XR  mode aTurbo    mode b     mode g    mode gTurbo */
-	    { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } },
-	{ 2, 0x98d0,
-	    { 0x02001408, 0x02001408, 0x02001408, 0x02001408, 0x02001408 } },
-	{ 3, 0x98dc,
-	    { 0x00a020c0, 0x00a020c0, 0x00e020c0, 0x00e020c0, 0x00e020c0 } },
-	{ 6, 0x989c,
-	    { 0x10000000, 0x10000000, 0x10000000, 0x10000000, 0x10000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00100000, 0x00100000, 0x00100000, 0x00100000, 0x00100000 } },
-	{ 6, 0x989c,
-	    { 0x00020000, 0x00020000, 0x00020000, 0x00020000, 0x00020000 } },
-	{ 6, 0x989c,
-	    { 0x00730000, 0x00730000, 0x00730000, 0x00730000, 0x00730000 } },
-	{ 6, 0x989c,
-	    { 0x00f80000, 0x00f80000, 0x00f80000, 0x00f80000, 0x00f80000 } },
-	{ 6, 0x989c,
-	    { 0x00e70000, 0x00e70000, 0x80e70000, 0x80e70000, 0x00e70000 } },
-	{ 6, 0x989c,
-	    { 0x00140000, 0x00140000, 0x00140000, 0x00140000, 0x00140000 } },
-	{ 6, 0x989c,
-	    { 0x00910040, 0x00910040, 0x00910040, 0x00910040, 0x00910040 } },
-	{ 6, 0x989c,
-	    { 0x0007001a, 0x0007001a, 0x0207001a, 0x0207001a, 0x0007001a } },
-	{ 6, 0x989c,
-	    { 0x00410000, 0x00410000, 0x00410000, 0x00410000, 0x00410000 } },
-	{ 6, 0x989c,
-	    { 0x00810000, 0x00810000, 0x00810060, 0x00810060, 0x00810060 } },
-	{ 6, 0x989c,
-	    { 0x00020800, 0x00020800, 0x00020803, 0x00020803, 0x00020803 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00001660, 0x00001660, 0x00001660, 0x00001660, 0x00001660 } },
-	{ 6, 0x989c,
-	    { 0x00001688, 0x00001688, 0x00001688, 0x00001688, 0x00001688 } },
-	{ 6, 0x98c4,
-	    { 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001 } },
-	{ 7, 0x989c,
-	    { 0x00006400, 0x00006400, 0x00006400, 0x00006400, 0x00006400 } },
-	{ 7, 0x989c,
-	    { 0x00000800, 0x00000800, 0x00000800, 0x00000800, 0x00000800 } },
-	{ 7, 0x98cc,
-	    { 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e } },
+	/* BANK / C.R.     A/XR         B           G      */
+	{ 1, 0x98d4, { 0x00000020, 0x00000020, 0x00000020 } },
+	{ 2, 0x98d0, { 0x02001408, 0x02001408, 0x02001408 } },
+	{ 3, 0x98dc, { 0x00a020c0, 0x00e020c0, 0x00e020c0 } },
+	{ 6, 0x989c, { 0x10000000, 0x10000000, 0x10000000 } },
+	{ 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c, { 0x002a0000, 0x002a0000, 0x002a0000 } },
+	{ 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c, { 0x00100000, 0x00100000, 0x00100000 } },
+	{ 6, 0x989c, { 0x00020000, 0x00020000, 0x00020000 } },
+	{ 6, 0x989c, { 0x00730000, 0x00730000, 0x00730000 } },
+	{ 6, 0x989c, { 0x00f80000, 0x00f80000, 0x00f80000 } },
+	{ 6, 0x989c, { 0x00e70000, 0x80e70000, 0x80e70000 } },
+	{ 6, 0x989c, { 0x00140000, 0x00140000, 0x00140000 } },
+	{ 6, 0x989c, { 0x00910040, 0x00910040, 0x00910040 } },
+	{ 6, 0x989c, { 0x0007001a, 0x0207001a, 0x0207001a } },
+	{ 6, 0x989c, { 0x00410000, 0x00410000, 0x00410000 } },
+	{ 6, 0x989c, { 0x00810000, 0x00810060, 0x00810060 } },
+	{ 6, 0x989c, { 0x00020800, 0x00020803, 0x00020803 } },
+	{ 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c, { 0x00001660, 0x00001660, 0x00001660 } },
+	{ 6, 0x989c, { 0x00001688, 0x00001688, 0x00001688 } },
+	{ 6, 0x98c4, { 0x00000001, 0x00000001, 0x00000001 } },
+	{ 7, 0x989c, { 0x00006400, 0x00006400, 0x00006400 } },
+	{ 7, 0x989c, { 0x00000800, 0x00000800, 0x00000800 } },
+	{ 7, 0x98cc, { 0x0000000e, 0x0000000e, 0x0000000e } },
 };
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath5k/sysfs.c linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath5k/sysfs.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath5k/sysfs.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath5k/sysfs.c	2011-03-14 21:20:32.000000000 -0400
@@ -95,7 +95,7 @@ static struct attribute_group ath5k_attr
 int
 ath5k_sysfs_register(struct ath5k_softc *sc)
 {
-	struct device *dev = &sc->pdev->dev;
+	struct device *dev = sc->dev;
 	int err;
 
 	err = sysfs_create_group(&dev->kobj, &ath5k_attribute_group_ani);
@@ -110,7 +110,7 @@ ath5k_sysfs_register(struct ath5k_softc
 void
 ath5k_sysfs_unregister(struct ath5k_softc *sc)
 {
-	struct device *dev = &sc->pdev->dev;
+	struct device *dev = sc->dev;
 
 	sysfs_remove_group(&dev->kobj, &ath5k_attribute_group_ani);
 }
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/ahb.c linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/ahb.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/ahb.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/ahb.c	2011-03-14 21:20:32.000000000 -0400
@@ -35,10 +35,9 @@ static bool ath_ahb_eeprom_read(struct a
 
 	pdata = (struct ath9k_platform_data *) pdev->dev.platform_data;
 	if (off >= (ARRAY_SIZE(pdata->eeprom_data))) {
-		ath_print(common, ATH_DBG_FATAL,
-			  "%s: flash read failed, offset %08x "
-			  "is out of range\n",
-			  __func__, off);
+		ath_err(common,
+			"%s: flash read failed, offset %08x is out of range\n",
+			__func__, off);
 		return false;
 	}
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/ani.c linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/ani.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/ani.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/ani.c	2011-03-14 21:20:32.000000000 -0400
@@ -135,8 +135,8 @@ static void ath9k_ani_restart(struct ath
 		cck_base = AR_PHY_COUNTMAX - ah->config.cck_trig_high;
 	}
 
-	ath_print(common, ATH_DBG_ANI,
-		  "Writing ofdmbase=%u   cckbase=%u\n", ofdm_base, cck_base);
+	ath_dbg(common, ATH_DBG_ANI,
+		"Writing ofdmbase=%u   cckbase=%u\n", ofdm_base, cck_base);
 
 	ENABLE_REGWRITE_BUFFER(ah);
 
@@ -267,11 +267,11 @@ static void ath9k_hw_set_ofdm_nil(struct
 
 	aniState->noiseFloor = BEACON_RSSI(ah);
 
-	ath_print(common, ATH_DBG_ANI,
-		  "**** ofdmlevel %d=>%d, rssi=%d[lo=%d hi=%d]\n",
-		  aniState->ofdmNoiseImmunityLevel,
-		  immunityLevel, aniState->noiseFloor,
-		  aniState->rssiThrLow, aniState->rssiThrHigh);
+	ath_dbg(common, ATH_DBG_ANI,
+		"**** ofdmlevel %d=>%d, rssi=%d[lo=%d hi=%d]\n",
+		aniState->ofdmNoiseImmunityLevel,
+		immunityLevel, aniState->noiseFloor,
+		aniState->rssiThrLow, aniState->rssiThrHigh);
 
 	aniState->ofdmNoiseImmunityLevel = immunityLevel;
 
@@ -334,11 +334,11 @@ static void ath9k_hw_set_cck_nil(struct
 	const struct ani_cck_level_entry *entry_cck;
 
 	aniState->noiseFloor = BEACON_RSSI(ah);
-	ath_print(common, ATH_DBG_ANI,
-		  "**** ccklevel %d=>%d, rssi=%d[lo=%d hi=%d]\n",
-		  aniState->cckNoiseImmunityLevel, immunityLevel,
-		  aniState->noiseFloor, aniState->rssiThrLow,
-		  aniState->rssiThrHigh);
+	ath_dbg(common, ATH_DBG_ANI,
+		"**** ccklevel %d=>%d, rssi=%d[lo=%d hi=%d]\n",
+		aniState->cckNoiseImmunityLevel, immunityLevel,
+		aniState->noiseFloor, aniState->rssiThrLow,
+		aniState->rssiThrHigh);
 
 	if ((ah->opmode == NL80211_IFTYPE_STATION ||
 	     ah->opmode == NL80211_IFTYPE_ADHOC) &&
@@ -358,7 +358,7 @@ static void ath9k_hw_set_cck_nil(struct
 				     entry_cck->fir_step_level);
 
 	/* Skip MRC CCK for pre AR9003 families */
-	if (!AR_SREV_9300_20_OR_LATER(ah))
+	if (!AR_SREV_9300_20_OR_LATER(ah) || AR_SREV_9485(ah))
 		return;
 
 	if (aniState->mrcCCKOff == entry_cck->mrc_cck_on)
@@ -478,8 +478,8 @@ static void ath9k_ani_reset_old(struct a
 
 	if (ah->opmode != NL80211_IFTYPE_STATION
 	    && ah->opmode != NL80211_IFTYPE_ADHOC) {
-		ath_print(common, ATH_DBG_ANI,
-			  "Reset ANI state opmode %u\n", ah->opmode);
+		ath_dbg(common, ATH_DBG_ANI,
+			"Reset ANI state opmode %u\n", ah->opmode);
 		ah->stats.ast_ani_reset++;
 
 		if (ah->opmode == NL80211_IFTYPE_AP) {
@@ -584,16 +584,14 @@ void ath9k_ani_reset(struct ath_hw *ah,
 		    ATH9K_ANI_OFDM_DEF_LEVEL ||
 		    aniState->cckNoiseImmunityLevel !=
 		    ATH9K_ANI_CCK_DEF_LEVEL) {
-			ath_print(common, ATH_DBG_ANI,
-				  "Restore defaults: opmode %u "
-				  "chan %d Mhz/0x%x is_scanning=%d "
-				  "ofdm:%d cck:%d\n",
-				  ah->opmode,
-				  chan->channel,
-				  chan->channelFlags,
-				  is_scanning,
-				  aniState->ofdmNoiseImmunityLevel,
-				  aniState->cckNoiseImmunityLevel);
+			ath_dbg(common, ATH_DBG_ANI,
+				"Restore defaults: opmode %u chan %d Mhz/0x%x is_scanning=%d ofdm:%d cck:%d\n",
+				ah->opmode,
+				chan->channel,
+				chan->channelFlags,
+				is_scanning,
+				aniState->ofdmNoiseImmunityLevel,
+				aniState->cckNoiseImmunityLevel);
 
 			ath9k_hw_set_ofdm_nil(ah, ATH9K_ANI_OFDM_DEF_LEVEL);
 			ath9k_hw_set_cck_nil(ah, ATH9K_ANI_CCK_DEF_LEVEL);
@@ -602,16 +600,14 @@ void ath9k_ani_reset(struct ath_hw *ah,
 		/*
 		 * restore historical levels for this channel
 		 */
-		ath_print(common, ATH_DBG_ANI,
-			  "Restore history: opmode %u "
-			  "chan %d Mhz/0x%x is_scanning=%d "
-			  "ofdm:%d cck:%d\n",
-			  ah->opmode,
-			  chan->channel,
-			  chan->channelFlags,
-			  is_scanning,
-			  aniState->ofdmNoiseImmunityLevel,
-			  aniState->cckNoiseImmunityLevel);
+		ath_dbg(common, ATH_DBG_ANI,
+			"Restore history: opmode %u chan %d Mhz/0x%x is_scanning=%d ofdm:%d cck:%d\n",
+			ah->opmode,
+			chan->channel,
+			chan->channelFlags,
+			is_scanning,
+			aniState->ofdmNoiseImmunityLevel,
+			aniState->cckNoiseImmunityLevel);
 
 			ath9k_hw_set_ofdm_nil(ah,
 					      aniState->ofdmNoiseImmunityLevel);
@@ -666,19 +662,17 @@ static bool ath9k_hw_ani_read_counters(s
 
 	if (!use_new_ani(ah) && (phyCnt1 < ofdm_base || phyCnt2 < cck_base)) {
 		if (phyCnt1 < ofdm_base) {
-			ath_print(common, ATH_DBG_ANI,
-				  "phyCnt1 0x%x, resetting "
-				  "counter value to 0x%x\n",
-				  phyCnt1, ofdm_base);
+			ath_dbg(common, ATH_DBG_ANI,
+				"phyCnt1 0x%x, resetting counter value to 0x%x\n",
+				phyCnt1, ofdm_base);
 			REG_WRITE(ah, AR_PHY_ERR_1, ofdm_base);
 			REG_WRITE(ah, AR_PHY_ERR_MASK_1,
 				  AR_PHY_ERR_OFDM_TIMING);
 		}
 		if (phyCnt2 < cck_base) {
-			ath_print(common, ATH_DBG_ANI,
-				  "phyCnt2 0x%x, resetting "
-				  "counter value to 0x%x\n",
-				  phyCnt2, cck_base);
+			ath_dbg(common, ATH_DBG_ANI,
+				"phyCnt2 0x%x, resetting counter value to 0x%x\n",
+				phyCnt2, cck_base);
 			REG_WRITE(ah, AR_PHY_ERR_2, cck_base);
 			REG_WRITE(ah, AR_PHY_ERR_MASK_2,
 				  AR_PHY_ERR_CCK_TIMING);
@@ -719,13 +713,12 @@ void ath9k_hw_ani_monitor(struct ath_hw
 	cckPhyErrRate =  aniState->cckPhyErrCount * 1000 /
 			 aniState->listenTime;
 
-	ath_print(common, ATH_DBG_ANI,
-		  "listenTime=%d OFDM:%d errs=%d/s CCK:%d "
-		  "errs=%d/s ofdm_turn=%d\n",
-		  aniState->listenTime,
-		  aniState->ofdmNoiseImmunityLevel,
-		  ofdmPhyErrRate, aniState->cckNoiseImmunityLevel,
-		  cckPhyErrRate, aniState->ofdmsTurn);
+	ath_dbg(common, ATH_DBG_ANI,
+		"listenTime=%d OFDM:%d errs=%d/s CCK:%d errs=%d/s ofdm_turn=%d\n",
+		aniState->listenTime,
+		aniState->ofdmNoiseImmunityLevel,
+		ofdmPhyErrRate, aniState->cckNoiseImmunityLevel,
+		cckPhyErrRate, aniState->ofdmsTurn);
 
 	if (aniState->listenTime > 5 * ah->aniperiod) {
 		if (ofdmPhyErrRate <= ah->config.ofdm_trig_low &&
@@ -755,7 +748,7 @@ void ath9k_enable_mib_counters(struct at
 {
 	struct ath_common *common = ath9k_hw_common(ah);
 
-	ath_print(common, ATH_DBG_ANI, "Enable MIB counters\n");
+	ath_dbg(common, ATH_DBG_ANI, "Enable MIB counters\n");
 
 	ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
 
@@ -777,7 +770,7 @@ void ath9k_hw_disable_mib_counters(struc
 {
 	struct ath_common *common = ath9k_hw_common(ah);
 
-	ath_print(common, ATH_DBG_ANI, "Disable MIB counters\n");
+	ath_dbg(common, ATH_DBG_ANI, "Disable MIB counters\n");
 
 	REG_WRITE(ah, AR_MIBC, AR_MIBC_FMC);
 	ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
@@ -834,10 +827,10 @@ void ath9k_hw_ani_setup(struct ath_hw *a
 {
 	int i;
 
-	const int totalSizeDesired[] = { -55, -55, -55, -55, -62 };
-	const int coarseHigh[] = { -14, -14, -14, -14, -12 };
-	const int coarseLow[] = { -64, -64, -64, -64, -70 };
-	const int firpwr[] = { -78, -78, -78, -78, -80 };
+	static const int totalSizeDesired[] = { -55, -55, -55, -55, -62 };
+	static const int coarseHigh[] = { -14, -14, -14, -14, -12 };
+	static const int coarseLow[] = { -64, -64, -64, -64, -70 };
+	static const int firpwr[] = { -78, -78, -78, -78, -80 };
 
 	for (i = 0; i < 5; i++) {
 		ah->totalSizeDesired[i] = totalSizeDesired[i];
@@ -852,7 +845,7 @@ void ath9k_hw_ani_init(struct ath_hw *ah
 	struct ath_common *common = ath9k_hw_common(ah);
 	int i;
 
-	ath_print(common, ATH_DBG_ANI, "Initialize ANI\n");
+	ath_dbg(common, ATH_DBG_ANI, "Initialize ANI\n");
 
 	if (use_new_ani(ah)) {
 		ah->config.ofdm_trig_high = ATH9K_ANI_OFDM_TRIG_HIGH_NEW;
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/ar5008_phy.c linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/ar5008_phy.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/ar5008_phy.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/ar5008_phy.c	2011-03-14 21:20:32.000000000 -0400
@@ -130,9 +130,8 @@ static void ar5008_hw_force_bias(struct
 	/* pre-reverse this field */
 	tmp_reg = ath9k_hw_reverse_bits(new_bias, 3);
 
-	ath_print(common, ATH_DBG_CONFIG,
-		  "Force rf_pwd_icsyndiv to %1d on %4d\n",
-		  new_bias, synth_freq);
+	ath_dbg(common, ATH_DBG_CONFIG, "Force rf_pwd_icsyndiv to %1d on %4d\n",
+		new_bias, synth_freq);
 
 	/* swizzle rf_pwd_icsyndiv */
 	ar5008_hw_phy_modify_rx_buffer(ah->analogBank6Data, tmp_reg, 3, 181, 3);
@@ -173,8 +172,7 @@ static int ar5008_hw_set_channel(struct
 			channelSel = ((freq - 704) * 2 - 3040) / 10;
 			bModeSynth = 1;
 		} else {
-			ath_print(common, ATH_DBG_FATAL,
-				  "Invalid channel %u MHz\n", freq);
+			ath_err(common, "Invalid channel %u MHz\n", freq);
 			return -EINVAL;
 		}
 
@@ -206,8 +204,7 @@ static int ar5008_hw_set_channel(struct
 		channelSel = ath9k_hw_reverse_bits((freq - 4800) / 5, 8);
 		aModeRefSel = ath9k_hw_reverse_bits(1, 2);
 	} else {
-		ath_print(common, ATH_DBG_FATAL,
-			  "Invalid channel %u MHz\n", freq);
+		ath_err(common, "Invalid channel %u MHz\n", freq);
 		return -EINVAL;
 	}
 
@@ -244,13 +241,15 @@ static void ar5008_hw_spur_mitigate(stru
 	int upper, lower, cur_vit_mask;
 	int tmp, new;
 	int i;
-	int pilot_mask_reg[4] = { AR_PHY_TIMING7, AR_PHY_TIMING8,
-			  AR_PHY_PILOT_MASK_01_30, AR_PHY_PILOT_MASK_31_60
+	static int pilot_mask_reg[4] = {
+		AR_PHY_TIMING7, AR_PHY_TIMING8,
+		AR_PHY_PILOT_MASK_01_30, AR_PHY_PILOT_MASK_31_60
 	};
-	int chan_mask_reg[4] = { AR_PHY_TIMING9, AR_PHY_TIMING10,
-			 AR_PHY_CHANNEL_MASK_01_30, AR_PHY_CHANNEL_MASK_31_60
+	static int chan_mask_reg[4] = {
+		AR_PHY_TIMING9, AR_PHY_TIMING10,
+		AR_PHY_CHANNEL_MASK_01_30, AR_PHY_CHANNEL_MASK_31_60
 	};
-	int inc[4] = { 0, 100, 0, 0 };
+	static int inc[4] = { 0, 100, 0, 0 };
 
 	int8_t mask_m[123];
 	int8_t mask_p[123];
@@ -446,8 +445,7 @@ static int ar5008_hw_rf_alloc_ext_banks(
 #define ATH_ALLOC_BANK(bank, size) do { \
 		bank = kzalloc((sizeof(u32) * size), GFP_KERNEL); \
 		if (!bank) { \
-			ath_print(common, ATH_DBG_FATAL, \
-				  "Cannot allocate RF banks\n"); \
+			ath_err(common, "Cannot allocate RF banks\n"); \
 			return -ENOMEM; \
 		} \
 	} while (0);
@@ -873,12 +871,11 @@ static int ar5008_hw_process_ini(struct
 				 channel->max_antenna_gain * 2,
 				 channel->max_power * 2,
 				 min((u32) MAX_RATE_POWER,
-				 (u32) regulatory->power_limit));
+				 (u32) regulatory->power_limit), false);
 
 	/* Write analog registers */
 	if (!ath9k_hw_set_rf_regs(ah, chan, freqIndex)) {
-		ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL,
-			  "ar5416SetRfRegs failed\n");
+		ath_err(ath9k_hw_common(ah), "ar5416SetRfRegs failed\n");
 		return -EIO;
 	}
 
@@ -964,18 +961,6 @@ static void ar5008_hw_rfbus_done(struct
 	REG_WRITE(ah, AR_PHY_RFBUS_REQ, 0);
 }
 
-static void ar5008_hw_enable_rfkill(struct ath_hw *ah)
-{
-	REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL,
-		    AR_GPIO_INPUT_EN_VAL_RFSILENT_BB);
-
-	REG_CLR_BIT(ah, AR_GPIO_INPUT_MUX2,
-		    AR_GPIO_INPUT_MUX2_RFSILENT);
-
-	ath9k_hw_cfg_gpio_input(ah, ah->rfkill_gpio);
-	REG_SET_BIT(ah, AR_PHY_TEST, RFSILENT_BB);
-}
-
 static void ar5008_restore_chainmask(struct ath_hw *ah)
 {
 	int rx_chainmask = ah->rxchainmask;
@@ -1056,10 +1041,9 @@ static bool ar5008_hw_ani_control_old(st
 		u32 level = param;
 
 		if (level >= ARRAY_SIZE(ah->totalSizeDesired)) {
-			ath_print(common, ATH_DBG_ANI,
-				  "level out of range (%u > %u)\n",
-				  level,
-				  (unsigned)ARRAY_SIZE(ah->totalSizeDesired));
+			ath_dbg(common, ATH_DBG_ANI,
+				"level out of range (%u > %zu)\n",
+				level, ARRAY_SIZE(ah->totalSizeDesired));
 			return false;
 		}
 
@@ -1084,12 +1068,12 @@ static bool ar5008_hw_ani_control_old(st
 		break;
 	}
 	case ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION:{
-		const int m1ThreshLow[] = { 127, 50 };
-		const int m2ThreshLow[] = { 127, 40 };
-		const int m1Thresh[] = { 127, 0x4d };
-		const int m2Thresh[] = { 127, 0x40 };
-		const int m2CountThr[] = { 31, 16 };
-		const int m2CountThrLow[] = { 63, 48 };
+		static const int m1ThreshLow[] = { 127, 50 };
+		static const int m2ThreshLow[] = { 127, 40 };
+		static const int m1Thresh[] = { 127, 0x4d };
+		static const int m2Thresh[] = { 127, 0x40 };
+		static const int m2CountThr[] = { 31, 16 };
+		static const int m2CountThrLow[] = { 63, 48 };
 		u32 on = param ? 1 : 0;
 
 		REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
@@ -1141,7 +1125,7 @@ static bool ar5008_hw_ani_control_old(st
 		break;
 	}
 	case ATH9K_ANI_CCK_WEAK_SIGNAL_THR:{
-		const int weakSigThrCck[] = { 8, 6 };
+		static const int weakSigThrCck[] = { 8, 6 };
 		u32 high = param ? 1 : 0;
 
 		REG_RMW_FIELD(ah, AR_PHY_CCK_DETECT,
@@ -1157,14 +1141,13 @@ static bool ar5008_hw_ani_control_old(st
 		break;
 	}
 	case ATH9K_ANI_FIRSTEP_LEVEL:{
-		const int firstep[] = { 0, 4, 8 };
+		static const int firstep[] = { 0, 4, 8 };
 		u32 level = param;
 
 		if (level >= ARRAY_SIZE(firstep)) {
-			ath_print(common, ATH_DBG_ANI,
-				  "level out of range (%u > %u)\n",
-				  level,
-				  (unsigned) ARRAY_SIZE(firstep));
+			ath_dbg(common, ATH_DBG_ANI,
+				"level out of range (%u > %zu)\n",
+				level, ARRAY_SIZE(firstep));
 			return false;
 		}
 		REG_RMW_FIELD(ah, AR_PHY_FIND_SIG,
@@ -1178,14 +1161,13 @@ static bool ar5008_hw_ani_control_old(st
 		break;
 	}
 	case ATH9K_ANI_SPUR_IMMUNITY_LEVEL:{
-		const int cycpwrThr1[] = { 2, 4, 6, 8, 10, 12, 14, 16 };
+		static const int cycpwrThr1[] = { 2, 4, 6, 8, 10, 12, 14, 16 };
 		u32 level = param;
 
 		if (level >= ARRAY_SIZE(cycpwrThr1)) {
-			ath_print(common, ATH_DBG_ANI,
-				  "level out of range (%u > %u)\n",
-				  level,
-				  (unsigned) ARRAY_SIZE(cycpwrThr1));
+			ath_dbg(common, ATH_DBG_ANI,
+				"level out of range (%u > %zu)\n",
+				level, ARRAY_SIZE(cycpwrThr1));
 			return false;
 		}
 		REG_RMW_FIELD(ah, AR_PHY_TIMING5,
@@ -1201,25 +1183,22 @@ static bool ar5008_hw_ani_control_old(st
 	case ATH9K_ANI_PRESENT:
 		break;
 	default:
-		ath_print(common, ATH_DBG_ANI,
-			  "invalid cmd %u\n", cmd);
+		ath_dbg(common, ATH_DBG_ANI, "invalid cmd %u\n", cmd);
 		return false;
 	}
 
-	ath_print(common, ATH_DBG_ANI, "ANI parameters:\n");
-	ath_print(common, ATH_DBG_ANI,
-		  "noiseImmunityLevel=%d, spurImmunityLevel=%d, "
-		  "ofdmWeakSigDetectOff=%d\n",
-		  aniState->noiseImmunityLevel,
-		  aniState->spurImmunityLevel,
-		  !aniState->ofdmWeakSigDetectOff);
-	ath_print(common, ATH_DBG_ANI,
-		  "cckWeakSigThreshold=%d, "
-		  "firstepLevel=%d, listenTime=%d\n",
-		  aniState->cckWeakSigThreshold,
-		  aniState->firstepLevel,
-		  aniState->listenTime);
-	ath_print(common, ATH_DBG_ANI,
+	ath_dbg(common, ATH_DBG_ANI, "ANI parameters:\n");
+	ath_dbg(common, ATH_DBG_ANI,
+		"noiseImmunityLevel=%d, spurImmunityLevel=%d, ofdmWeakSigDetectOff=%d\n",
+		aniState->noiseImmunityLevel,
+		aniState->spurImmunityLevel,
+		!aniState->ofdmWeakSigDetectOff);
+	ath_dbg(common, ATH_DBG_ANI,
+		"cckWeakSigThreshold=%d, firstepLevel=%d, listenTime=%d\n",
+		aniState->cckWeakSigThreshold,
+		aniState->firstepLevel,
+		aniState->listenTime);
+	ath_dbg(common, ATH_DBG_ANI,
 		"ofdmPhyErrCount=%d, cckPhyErrCount=%d\n\n",
 		aniState->ofdmPhyErrCount,
 		aniState->cckPhyErrCount);
@@ -1304,12 +1283,12 @@ static bool ar5008_hw_ani_control_new(st
 				    AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
 
 		if (!on != aniState->ofdmWeakSigDetectOff) {
-			ath_print(common, ATH_DBG_ANI,
-				  "** ch %d: ofdm weak signal: %s=>%s\n",
-				  chan->channel,
-				  !aniState->ofdmWeakSigDetectOff ?
-					"on" : "off",
-				  on ? "on" : "off");
+			ath_dbg(common, ATH_DBG_ANI,
+				"** ch %d: ofdm weak signal: %s=>%s\n",
+				chan->channel,
+				!aniState->ofdmWeakSigDetectOff ?
+				"on" : "off",
+				on ? "on" : "off");
 			if (on)
 				ah->stats.ast_ani_ofdmon++;
 			else
@@ -1322,11 +1301,9 @@ static bool ar5008_hw_ani_control_new(st
 		u32 level = param;
 
 		if (level >= ARRAY_SIZE(firstep_table)) {
-			ath_print(common, ATH_DBG_ANI,
-				  "ATH9K_ANI_FIRSTEP_LEVEL: level "
-				  "out of range (%u > %u)\n",
-				  level,
-				  (unsigned) ARRAY_SIZE(firstep_table));
+			ath_dbg(common, ATH_DBG_ANI,
+				"ATH9K_ANI_FIRSTEP_LEVEL: level out of range (%u > %zu)\n",
+				level, ARRAY_SIZE(firstep_table));
 			return false;
 		}
 
@@ -1361,24 +1338,22 @@ static bool ar5008_hw_ani_control_new(st
 			      AR_PHY_FIND_SIG_FIRSTEP_LOW, value2);
 
 		if (level != aniState->firstepLevel) {
-			ath_print(common, ATH_DBG_ANI,
-				  "** ch %d: level %d=>%d[def:%d] "
-				  "firstep[level]=%d ini=%d\n",
-				  chan->channel,
-				  aniState->firstepLevel,
-				  level,
-				  ATH9K_ANI_FIRSTEP_LVL_NEW,
-				  value,
-				  aniState->iniDef.firstep);
-			ath_print(common, ATH_DBG_ANI,
-				  "** ch %d: level %d=>%d[def:%d] "
-				  "firstep_low[level]=%d ini=%d\n",
-				  chan->channel,
-				  aniState->firstepLevel,
-				  level,
-				  ATH9K_ANI_FIRSTEP_LVL_NEW,
-				  value2,
-				  aniState->iniDef.firstepLow);
+			ath_dbg(common, ATH_DBG_ANI,
+				"** ch %d: level %d=>%d[def:%d] firstep[level]=%d ini=%d\n",
+				chan->channel,
+				aniState->firstepLevel,
+				level,
+				ATH9K_ANI_FIRSTEP_LVL_NEW,
+				value,
+				aniState->iniDef.firstep);
+			ath_dbg(common, ATH_DBG_ANI,
+				"** ch %d: level %d=>%d[def:%d] firstep_low[level]=%d ini=%d\n",
+				chan->channel,
+				aniState->firstepLevel,
+				level,
+				ATH9K_ANI_FIRSTEP_LVL_NEW,
+				value2,
+				aniState->iniDef.firstepLow);
 			if (level > aniState->firstepLevel)
 				ah->stats.ast_ani_stepup++;
 			else if (level < aniState->firstepLevel)
@@ -1391,11 +1366,9 @@ static bool ar5008_hw_ani_control_new(st
 		u32 level = param;
 
 		if (level >= ARRAY_SIZE(cycpwrThr1_table)) {
-			ath_print(common, ATH_DBG_ANI,
-				  "ATH9K_ANI_SPUR_IMMUNITY_LEVEL: level "
-				  "out of range (%u > %u)\n",
-				  level,
-				  (unsigned) ARRAY_SIZE(cycpwrThr1_table));
+			ath_dbg(common, ATH_DBG_ANI,
+				"ATH9K_ANI_SPUR_IMMUNITY_LEVEL: level out of range (%u > %zu)\n",
+				level, ARRAY_SIZE(cycpwrThr1_table));
 			return false;
 		}
 		/*
@@ -1429,24 +1402,22 @@ static bool ar5008_hw_ani_control_new(st
 			      AR_PHY_EXT_TIMING5_CYCPWR_THR1, value2);
 
 		if (level != aniState->spurImmunityLevel) {
-			ath_print(common, ATH_DBG_ANI,
-				  "** ch %d: level %d=>%d[def:%d] "
-				  "cycpwrThr1[level]=%d ini=%d\n",
-				  chan->channel,
-				  aniState->spurImmunityLevel,
-				  level,
-				  ATH9K_ANI_SPUR_IMMUNE_LVL_NEW,
-				  value,
-				  aniState->iniDef.cycpwrThr1);
-			ath_print(common, ATH_DBG_ANI,
-				  "** ch %d: level %d=>%d[def:%d] "
-				  "cycpwrThr1Ext[level]=%d ini=%d\n",
-				  chan->channel,
-				  aniState->spurImmunityLevel,
-				  level,
-				  ATH9K_ANI_SPUR_IMMUNE_LVL_NEW,
-				  value2,
-				  aniState->iniDef.cycpwrThr1Ext);
+			ath_dbg(common, ATH_DBG_ANI,
+				"** ch %d: level %d=>%d[def:%d] cycpwrThr1[level]=%d ini=%d\n",
+				chan->channel,
+				aniState->spurImmunityLevel,
+				level,
+				ATH9K_ANI_SPUR_IMMUNE_LVL_NEW,
+				value,
+				aniState->iniDef.cycpwrThr1);
+			ath_dbg(common, ATH_DBG_ANI,
+				"** ch %d: level %d=>%d[def:%d] cycpwrThr1Ext[level]=%d ini=%d\n",
+				chan->channel,
+				aniState->spurImmunityLevel,
+				level,
+				ATH9K_ANI_SPUR_IMMUNE_LVL_NEW,
+				value2,
+				aniState->iniDef.cycpwrThr1Ext);
 			if (level > aniState->spurImmunityLevel)
 				ah->stats.ast_ani_spurup++;
 			else if (level < aniState->spurImmunityLevel)
@@ -1465,22 +1436,19 @@ static bool ar5008_hw_ani_control_new(st
 	case ATH9K_ANI_PRESENT:
 		break;
 	default:
-		ath_print(common, ATH_DBG_ANI,
-			  "invalid cmd %u\n", cmd);
+		ath_dbg(common, ATH_DBG_ANI, "invalid cmd %u\n", cmd);
 		return false;
 	}
 
-	ath_print(common, ATH_DBG_ANI,
-		  "ANI parameters: SI=%d, ofdmWS=%s FS=%d "
-		  "MRCcck=%s listenTime=%d "
-		  "ofdmErrs=%d cckErrs=%d\n",
-		  aniState->spurImmunityLevel,
-		  !aniState->ofdmWeakSigDetectOff ? "on" : "off",
-		  aniState->firstepLevel,
-		  !aniState->mrcCCKOff ? "on" : "off",
-		  aniState->listenTime,
-		  aniState->ofdmPhyErrCount,
-		  aniState->cckPhyErrCount);
+	ath_dbg(common, ATH_DBG_ANI,
+		"ANI parameters: SI=%d, ofdmWS=%s FS=%d MRCcck=%s listenTime=%d ofdmErrs=%d cckErrs=%d\n",
+		aniState->spurImmunityLevel,
+		!aniState->ofdmWeakSigDetectOff ? "on" : "off",
+		aniState->firstepLevel,
+		!aniState->mrcCCKOff ? "on" : "off",
+		aniState->listenTime,
+		aniState->ofdmPhyErrCount,
+		aniState->cckPhyErrCount);
 	return true;
 }
 
@@ -1490,25 +1458,25 @@ static void ar5008_hw_do_getnf(struct at
 	int16_t nf;
 
 	nf = MS(REG_READ(ah, AR_PHY_CCA), AR_PHY_MINCCA_PWR);
-	nfarray[0] = sign_extend(nf, 9);
+	nfarray[0] = sign_extend32(nf, 8);
 
 	nf = MS(REG_READ(ah, AR_PHY_CH1_CCA), AR_PHY_CH1_MINCCA_PWR);
-	nfarray[1] = sign_extend(nf, 9);
+	nfarray[1] = sign_extend32(nf, 8);
 
 	nf = MS(REG_READ(ah, AR_PHY_CH2_CCA), AR_PHY_CH2_MINCCA_PWR);
-	nfarray[2] = sign_extend(nf, 9);
+	nfarray[2] = sign_extend32(nf, 8);
 
 	if (!IS_CHAN_HT40(ah->curchan))
 		return;
 
 	nf = MS(REG_READ(ah, AR_PHY_EXT_CCA), AR_PHY_EXT_MINCCA_PWR);
-	nfarray[3] = sign_extend(nf, 9);
+	nfarray[3] = sign_extend32(nf, 8);
 
 	nf = MS(REG_READ(ah, AR_PHY_CH1_EXT_CCA), AR_PHY_CH1_EXT_MINCCA_PWR);
-	nfarray[4] = sign_extend(nf, 9);
+	nfarray[4] = sign_extend32(nf, 8);
 
 	nf = MS(REG_READ(ah, AR_PHY_CH2_EXT_CCA), AR_PHY_CH2_EXT_MINCCA_PWR);
-	nfarray[5] = sign_extend(nf, 9);
+	nfarray[5] = sign_extend32(nf, 8);
 }
 
 /*
@@ -1526,13 +1494,12 @@ static void ar5008_hw_ani_cache_ini_regs
 
 	iniDef = &aniState->iniDef;
 
-	ath_print(common, ATH_DBG_ANI,
-		  "ver %d.%d opmode %u chan %d Mhz/0x%x\n",
-		  ah->hw_version.macVersion,
-		  ah->hw_version.macRev,
-		  ah->opmode,
-		  chan->channel,
-		  chan->channelFlags);
+	ath_dbg(common, ATH_DBG_ANI, "ver %d.%d opmode %u chan %d Mhz/0x%x\n",
+		ah->hw_version.macVersion,
+		ah->hw_version.macRev,
+		ah->opmode,
+		chan->channel,
+		chan->channelFlags);
 
 	val = REG_READ(ah, AR_PHY_SFCORR);
 	iniDef->m1Thresh = MS(val, AR_PHY_SFCORR_M1_THRESH);
@@ -1579,10 +1546,55 @@ static void ar5008_hw_set_nf_limits(stru
 	ah->nf_5g.nominal = AR_PHY_CCA_NOM_VAL_5416_5GHZ;
 }
 
+static void ar5008_hw_set_radar_params(struct ath_hw *ah,
+				       struct ath_hw_radar_conf *conf)
+{
+	u32 radar_0 = 0, radar_1 = 0;
+
+	if (!conf) {
+		REG_CLR_BIT(ah, AR_PHY_RADAR_0, AR_PHY_RADAR_0_ENA);
+		return;
+	}
+
+	radar_0 |= AR_PHY_RADAR_0_ENA | AR_PHY_RADAR_0_FFT_ENA;
+	radar_0 |= SM(conf->fir_power, AR_PHY_RADAR_0_FIRPWR);
+	radar_0 |= SM(conf->radar_rssi, AR_PHY_RADAR_0_RRSSI);
+	radar_0 |= SM(conf->pulse_height, AR_PHY_RADAR_0_HEIGHT);
+	radar_0 |= SM(conf->pulse_rssi, AR_PHY_RADAR_0_PRSSI);
+	radar_0 |= SM(conf->pulse_inband, AR_PHY_RADAR_0_INBAND);
+
+	radar_1 |= AR_PHY_RADAR_1_MAX_RRSSI;
+	radar_1 |= AR_PHY_RADAR_1_BLOCK_CHECK;
+	radar_1 |= SM(conf->pulse_maxlen, AR_PHY_RADAR_1_MAXLEN);
+	radar_1 |= SM(conf->pulse_inband_step, AR_PHY_RADAR_1_RELSTEP_THRESH);
+	radar_1 |= SM(conf->radar_inband, AR_PHY_RADAR_1_RELPWR_THRESH);
+
+	REG_WRITE(ah, AR_PHY_RADAR_0, radar_0);
+	REG_WRITE(ah, AR_PHY_RADAR_1, radar_1);
+	if (conf->ext_channel)
+		REG_SET_BIT(ah, AR_PHY_RADAR_EXT, AR_PHY_RADAR_EXT_ENA);
+	else
+		REG_CLR_BIT(ah, AR_PHY_RADAR_EXT, AR_PHY_RADAR_EXT_ENA);
+}
+
+static void ar5008_hw_set_radar_conf(struct ath_hw *ah)
+{
+	struct ath_hw_radar_conf *conf = &ah->radar_conf;
+
+	conf->fir_power = -33;
+	conf->radar_rssi = 20;
+	conf->pulse_height = 10;
+	conf->pulse_rssi = 24;
+	conf->pulse_inband = 15;
+	conf->pulse_maxlen = 255;
+	conf->pulse_inband_step = 12;
+	conf->radar_inband = 8;
+}
+
 void ar5008_hw_attach_phy_ops(struct ath_hw *ah)
 {
 	struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
-	const u32 ar5416_cca_regs[6] = {
+	static const u32 ar5416_cca_regs[6] = {
 		AR_PHY_CCA,
 		AR_PHY_CH1_CCA,
 		AR_PHY_CH2_CCA,
@@ -1605,10 +1617,10 @@ void ar5008_hw_attach_phy_ops(struct ath
 	priv_ops->set_delta_slope = ar5008_hw_set_delta_slope;
 	priv_ops->rfbus_req = ar5008_hw_rfbus_req;
 	priv_ops->rfbus_done = ar5008_hw_rfbus_done;
-	priv_ops->enable_rfkill = ar5008_hw_enable_rfkill;
 	priv_ops->restore_chainmask = ar5008_restore_chainmask;
 	priv_ops->set_diversity = ar5008_set_diversity;
 	priv_ops->do_getnf = ar5008_hw_do_getnf;
+	priv_ops->set_radar_params = ar5008_hw_set_radar_params;
 
 	if (modparam_force_new_ani) {
 		priv_ops->ani_control = ar5008_hw_ani_control_new;
@@ -1624,5 +1636,6 @@ void ar5008_hw_attach_phy_ops(struct ath
 		priv_ops->compute_pll_control = ar5008_hw_compute_pll_control;
 
 	ar5008_hw_set_nf_limits(ah);
+	ar5008_hw_set_radar_conf(ah);
 	memcpy(ah->nf_regs, ar5416_cca_regs, sizeof(ah->nf_regs));
 }
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/ar9002_calib.c linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/ar9002_calib.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/ar9002_calib.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/ar9002_calib.c	2011-03-14 21:20:32.000000000 -0400
@@ -39,18 +39,18 @@ static void ar9002_hw_setup_calibration(
 	switch (currCal->calData->calType) {
 	case IQ_MISMATCH_CAL:
 		REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_IQ);
-		ath_print(common, ATH_DBG_CALIBRATE,
-			  "starting IQ Mismatch Calibration\n");
+		ath_dbg(common, ATH_DBG_CALIBRATE,
+			"starting IQ Mismatch Calibration\n");
 		break;
 	case ADC_GAIN_CAL:
 		REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_GAIN);
-		ath_print(common, ATH_DBG_CALIBRATE,
-			  "starting ADC Gain Calibration\n");
+		ath_dbg(common, ATH_DBG_CALIBRATE,
+			"starting ADC Gain Calibration\n");
 		break;
 	case ADC_DC_CAL:
 		REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_PER);
-		ath_print(common, ATH_DBG_CALIBRATE,
-			  "starting ADC DC Calibration\n");
+		ath_dbg(common, ATH_DBG_CALIBRATE,
+			"starting ADC DC Calibration\n");
 		break;
 	}
 
@@ -107,11 +107,11 @@ static void ar9002_hw_iqcal_collect(stru
 			REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
 		ah->totalIqCorrMeas[i] +=
 			(int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
-		ath_print(ath9k_hw_common(ah), ATH_DBG_CALIBRATE,
-			  "%d: Chn %d pmi=0x%08x;pmq=0x%08x;iqcm=0x%08x;\n",
-			  ah->cal_samples, i, ah->totalPowerMeasI[i],
-			  ah->totalPowerMeasQ[i],
-			  ah->totalIqCorrMeas[i]);
+		ath_dbg(ath9k_hw_common(ah), ATH_DBG_CALIBRATE,
+			"%d: Chn %d pmi=0x%08x;pmq=0x%08x;iqcm=0x%08x;\n",
+			ah->cal_samples, i, ah->totalPowerMeasI[i],
+			ah->totalPowerMeasQ[i],
+			ah->totalIqCorrMeas[i]);
 	}
 }
 
@@ -129,14 +129,13 @@ static void ar9002_hw_adc_gaincal_collec
 		ah->totalAdcQEvenPhase[i] +=
 			REG_READ(ah, AR_PHY_CAL_MEAS_3(i));
 
-		ath_print(ath9k_hw_common(ah), ATH_DBG_CALIBRATE,
-			  "%d: Chn %d oddi=0x%08x; eveni=0x%08x; "
-			  "oddq=0x%08x; evenq=0x%08x;\n",
-			  ah->cal_samples, i,
-			  ah->totalAdcIOddPhase[i],
-			  ah->totalAdcIEvenPhase[i],
-			  ah->totalAdcQOddPhase[i],
-			  ah->totalAdcQEvenPhase[i]);
+		ath_dbg(ath9k_hw_common(ah), ATH_DBG_CALIBRATE,
+			"%d: Chn %d oddi=0x%08x; eveni=0x%08x; oddq=0x%08x; evenq=0x%08x;\n",
+			ah->cal_samples, i,
+			ah->totalAdcIOddPhase[i],
+			ah->totalAdcIEvenPhase[i],
+			ah->totalAdcQOddPhase[i],
+			ah->totalAdcQEvenPhase[i]);
 	}
 }
 
@@ -154,14 +153,13 @@ static void ar9002_hw_adc_dccal_collect(
 		ah->totalAdcDcOffsetQEvenPhase[i] +=
 			(int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_3(i));
 
-		ath_print(ath9k_hw_common(ah), ATH_DBG_CALIBRATE,
-			  "%d: Chn %d oddi=0x%08x; eveni=0x%08x; "
-			  "oddq=0x%08x; evenq=0x%08x;\n",
-			  ah->cal_samples, i,
-			  ah->totalAdcDcOffsetIOddPhase[i],
-			  ah->totalAdcDcOffsetIEvenPhase[i],
-			  ah->totalAdcDcOffsetQOddPhase[i],
-			  ah->totalAdcDcOffsetQEvenPhase[i]);
+		ath_dbg(ath9k_hw_common(ah), ATH_DBG_CALIBRATE,
+			"%d: Chn %d oddi=0x%08x; eveni=0x%08x; oddq=0x%08x; evenq=0x%08x;\n",
+			ah->cal_samples, i,
+			ah->totalAdcDcOffsetIOddPhase[i],
+			ah->totalAdcDcOffsetIEvenPhase[i],
+			ah->totalAdcDcOffsetQOddPhase[i],
+			ah->totalAdcDcOffsetQEvenPhase[i]);
 	}
 }
 
@@ -178,13 +176,13 @@ static void ar9002_hw_iqcalibrate(struct
 		powerMeasQ = ah->totalPowerMeasQ[i];
 		iqCorrMeas = ah->totalIqCorrMeas[i];
 
-		ath_print(common, ATH_DBG_CALIBRATE,
-			  "Starting IQ Cal and Correction for Chain %d\n",
-			  i);
+		ath_dbg(common, ATH_DBG_CALIBRATE,
+			"Starting IQ Cal and Correction for Chain %d\n",
+			i);
 
-		ath_print(common, ATH_DBG_CALIBRATE,
-			  "Orignal: Chn %diq_corr_meas = 0x%08x\n",
-			  i, ah->totalIqCorrMeas[i]);
+		ath_dbg(common, ATH_DBG_CALIBRATE,
+			"Orignal: Chn %diq_corr_meas = 0x%08x\n",
+			i, ah->totalIqCorrMeas[i]);
 
 		iqCorrNeg = 0;
 
@@ -193,12 +191,12 @@ static void ar9002_hw_iqcalibrate(struct
 			iqCorrNeg = 1;
 		}
 
-		ath_print(common, ATH_DBG_CALIBRATE,
-			  "Chn %d pwr_meas_i = 0x%08x\n", i, powerMeasI);
-		ath_print(common, ATH_DBG_CALIBRATE,
-			  "Chn %d pwr_meas_q = 0x%08x\n", i, powerMeasQ);
-		ath_print(common, ATH_DBG_CALIBRATE, "iqCorrNeg is 0x%08x\n",
-			  iqCorrNeg);
+		ath_dbg(common, ATH_DBG_CALIBRATE,
+			"Chn %d pwr_meas_i = 0x%08x\n", i, powerMeasI);
+		ath_dbg(common, ATH_DBG_CALIBRATE,
+			"Chn %d pwr_meas_q = 0x%08x\n", i, powerMeasQ);
+		ath_dbg(common, ATH_DBG_CALIBRATE, "iqCorrNeg is 0x%08x\n",
+			iqCorrNeg);
 
 		iCoffDenom = (powerMeasI / 2 + powerMeasQ / 2) / 128;
 		qCoffDenom = powerMeasQ / 64;
@@ -207,14 +205,14 @@ static void ar9002_hw_iqcalibrate(struct
 		    (qCoffDenom != 0)) {
 			iCoff = iqCorrMeas / iCoffDenom;
 			qCoff = powerMeasI / qCoffDenom - 64;
-			ath_print(common, ATH_DBG_CALIBRATE,
-				  "Chn %d iCoff = 0x%08x\n", i, iCoff);
-			ath_print(common, ATH_DBG_CALIBRATE,
-				  "Chn %d qCoff = 0x%08x\n", i, qCoff);
+			ath_dbg(common, ATH_DBG_CALIBRATE,
+				"Chn %d iCoff = 0x%08x\n", i, iCoff);
+			ath_dbg(common, ATH_DBG_CALIBRATE,
+				"Chn %d qCoff = 0x%08x\n", i, qCoff);
 
 			iCoff = iCoff & 0x3f;
-			ath_print(common, ATH_DBG_CALIBRATE,
-				  "New: Chn %d iCoff = 0x%08x\n", i, iCoff);
+			ath_dbg(common, ATH_DBG_CALIBRATE,
+				"New: Chn %d iCoff = 0x%08x\n", i, iCoff);
 			if (iqCorrNeg == 0x0)
 				iCoff = 0x40 - iCoff;
 
@@ -223,9 +221,9 @@ static void ar9002_hw_iqcalibrate(struct
 			else if (qCoff <= -16)
 				qCoff = -16;
 
-			ath_print(common, ATH_DBG_CALIBRATE,
-				  "Chn %d : iCoff = 0x%x  qCoff = 0x%x\n",
-				  i, iCoff, qCoff);
+			ath_dbg(common, ATH_DBG_CALIBRATE,
+				"Chn %d : iCoff = 0x%x  qCoff = 0x%x\n",
+				i, iCoff, qCoff);
 
 			REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(i),
 				      AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF,
@@ -233,9 +231,9 @@ static void ar9002_hw_iqcalibrate(struct
 			REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(i),
 				      AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF,
 				      qCoff);
-			ath_print(common, ATH_DBG_CALIBRATE,
-				  "IQ Cal and Correction done for Chain %d\n",
-				  i);
+			ath_dbg(common, ATH_DBG_CALIBRATE,
+				"IQ Cal and Correction done for Chain %d\n",
+				i);
 		}
 	}
 
@@ -255,21 +253,21 @@ static void ar9002_hw_adc_gaincal_calibr
 		qOddMeasOffset = ah->totalAdcQOddPhase[i];
 		qEvenMeasOffset = ah->totalAdcQEvenPhase[i];
 
-		ath_print(common, ATH_DBG_CALIBRATE,
-			  "Starting ADC Gain Cal for Chain %d\n", i);
+		ath_dbg(common, ATH_DBG_CALIBRATE,
+			"Starting ADC Gain Cal for Chain %d\n", i);
 
-		ath_print(common, ATH_DBG_CALIBRATE,
-			  "Chn %d pwr_meas_odd_i = 0x%08x\n", i,
-			  iOddMeasOffset);
-		ath_print(common, ATH_DBG_CALIBRATE,
-			  "Chn %d pwr_meas_even_i = 0x%08x\n", i,
-			  iEvenMeasOffset);
-		ath_print(common, ATH_DBG_CALIBRATE,
-			  "Chn %d pwr_meas_odd_q = 0x%08x\n", i,
-			  qOddMeasOffset);
-		ath_print(common, ATH_DBG_CALIBRATE,
-			  "Chn %d pwr_meas_even_q = 0x%08x\n", i,
-			  qEvenMeasOffset);
+		ath_dbg(common, ATH_DBG_CALIBRATE,
+			"Chn %d pwr_meas_odd_i = 0x%08x\n", i,
+			iOddMeasOffset);
+		ath_dbg(common, ATH_DBG_CALIBRATE,
+			"Chn %d pwr_meas_even_i = 0x%08x\n", i,
+			iEvenMeasOffset);
+		ath_dbg(common, ATH_DBG_CALIBRATE,
+			"Chn %d pwr_meas_odd_q = 0x%08x\n", i,
+			qOddMeasOffset);
+		ath_dbg(common, ATH_DBG_CALIBRATE,
+			"Chn %d pwr_meas_even_q = 0x%08x\n", i,
+			qEvenMeasOffset);
 
 		if (iOddMeasOffset != 0 && qEvenMeasOffset != 0) {
 			iGainMismatch =
@@ -279,20 +277,20 @@ static void ar9002_hw_adc_gaincal_calibr
 				((qOddMeasOffset * 32) /
 				 qEvenMeasOffset) & 0x3f;
 
-			ath_print(common, ATH_DBG_CALIBRATE,
-				  "Chn %d gain_mismatch_i = 0x%08x\n", i,
-				  iGainMismatch);
-			ath_print(common, ATH_DBG_CALIBRATE,
-				  "Chn %d gain_mismatch_q = 0x%08x\n", i,
-				  qGainMismatch);
+			ath_dbg(common, ATH_DBG_CALIBRATE,
+				"Chn %d gain_mismatch_i = 0x%08x\n", i,
+				iGainMismatch);
+			ath_dbg(common, ATH_DBG_CALIBRATE,
+				"Chn %d gain_mismatch_q = 0x%08x\n", i,
+				qGainMismatch);
 
 			val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i));
 			val &= 0xfffff000;
 			val |= (qGainMismatch) | (iGainMismatch << 6);
 			REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val);
 
-			ath_print(common, ATH_DBG_CALIBRATE,
-				  "ADC Gain Cal done for Chain %d\n", i);
+			ath_dbg(common, ATH_DBG_CALIBRATE,
+				"ADC Gain Cal done for Chain %d\n", i);
 		}
 	}
 
@@ -317,41 +315,41 @@ static void ar9002_hw_adc_dccal_calibrat
 		qOddMeasOffset = ah->totalAdcDcOffsetQOddPhase[i];
 		qEvenMeasOffset = ah->totalAdcDcOffsetQEvenPhase[i];
 
-		ath_print(common, ATH_DBG_CALIBRATE,
-			   "Starting ADC DC Offset Cal for Chain %d\n", i);
+		ath_dbg(common, ATH_DBG_CALIBRATE,
+			"Starting ADC DC Offset Cal for Chain %d\n", i);
 
-		ath_print(common, ATH_DBG_CALIBRATE,
-			  "Chn %d pwr_meas_odd_i = %d\n", i,
-			  iOddMeasOffset);
-		ath_print(common, ATH_DBG_CALIBRATE,
-			  "Chn %d pwr_meas_even_i = %d\n", i,
-			  iEvenMeasOffset);
-		ath_print(common, ATH_DBG_CALIBRATE,
-			  "Chn %d pwr_meas_odd_q = %d\n", i,
-			  qOddMeasOffset);
-		ath_print(common, ATH_DBG_CALIBRATE,
-			  "Chn %d pwr_meas_even_q = %d\n", i,
-			  qEvenMeasOffset);
+		ath_dbg(common, ATH_DBG_CALIBRATE,
+			"Chn %d pwr_meas_odd_i = %d\n", i,
+			iOddMeasOffset);
+		ath_dbg(common, ATH_DBG_CALIBRATE,
+			"Chn %d pwr_meas_even_i = %d\n", i,
+			iEvenMeasOffset);
+		ath_dbg(common, ATH_DBG_CALIBRATE,
+			"Chn %d pwr_meas_odd_q = %d\n", i,
+			qOddMeasOffset);
+		ath_dbg(common, ATH_DBG_CALIBRATE,
+			"Chn %d pwr_meas_even_q = %d\n", i,
+			qEvenMeasOffset);
 
 		iDcMismatch = (((iEvenMeasOffset - iOddMeasOffset) * 2) /
 			       numSamples) & 0x1ff;
 		qDcMismatch = (((qOddMeasOffset - qEvenMeasOffset) * 2) /
 			       numSamples) & 0x1ff;
 
-		ath_print(common, ATH_DBG_CALIBRATE,
-			  "Chn %d dc_offset_mismatch_i = 0x%08x\n", i,
-			  iDcMismatch);
-		ath_print(common, ATH_DBG_CALIBRATE,
-			  "Chn %d dc_offset_mismatch_q = 0x%08x\n", i,
-			  qDcMismatch);
+		ath_dbg(common, ATH_DBG_CALIBRATE,
+			"Chn %d dc_offset_mismatch_i = 0x%08x\n", i,
+			iDcMismatch);
+		ath_dbg(common, ATH_DBG_CALIBRATE,
+			"Chn %d dc_offset_mismatch_q = 0x%08x\n", i,
+			qDcMismatch);
 
 		val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i));
 		val &= 0xc0000fff;
 		val |= (qDcMismatch << 12) | (iDcMismatch << 21);
 		REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val);
 
-		ath_print(common, ATH_DBG_CALIBRATE,
-			  "ADC DC Offset Cal done for Chain %d\n", i);
+		ath_dbg(common, ATH_DBG_CALIBRATE,
+			"ADC DC Offset Cal done for Chain %d\n", i);
 	}
 
 	REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0),
@@ -540,7 +538,7 @@ static inline void ar9285_hw_pa_cal(stru
 		{ 0x7838, 0 },
 	};
 
-	ath_print(common, ATH_DBG_CALIBRATE, "Running PA Calibration\n");
+	ath_dbg(common, ATH_DBG_CALIBRATE, "Running PA Calibration\n");
 
 	/* PA CAL is not needed for high power solution */
 	if (ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE) ==
@@ -681,10 +679,6 @@ static bool ar9002_hw_calibrate(struct a
 
 	/* Do NF cal only at longer intervals */
 	if (longcal || nfcal_pending) {
-		/* Do periodic PAOffset Cal */
-		ar9002_hw_pa_cal(ah, false);
-		ar9002_hw_olc_temp_compensation(ah);
-
 		/*
 		 * Get the value from the previous NF cal and update
 		 * history buffer.
@@ -699,8 +693,12 @@ static bool ar9002_hw_calibrate(struct a
 			ath9k_hw_loadnf(ah, ah->curchan);
 		}
 
-		if (longcal)
+		if (longcal) {
 			ath9k_hw_start_nfcal(ah, false);
+			/* Do periodic PAOffset Cal */
+			ar9002_hw_pa_cal(ah, false);
+			ar9002_hw_olc_temp_compensation(ah);
+		}
 	}
 
 	return iscaldone;
@@ -721,9 +719,8 @@ static bool ar9285_hw_cl_cal(struct ath_
 		REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL);
 		if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL,
 				  AR_PHY_AGC_CONTROL_CAL, 0, AH_WAIT_TIMEOUT)) {
-			ath_print(common, ATH_DBG_CALIBRATE, "offset "
-				  "calibration failed to complete in "
-				  "1ms; noisy ??\n");
+			ath_dbg(common, ATH_DBG_CALIBRATE,
+				"offset calibration failed to complete in 1ms; noisy environment?\n");
 			return false;
 		}
 		REG_CLR_BIT(ah, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN);
@@ -736,8 +733,8 @@ static bool ar9285_hw_cl_cal(struct ath_
 	REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL);
 	if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL,
 			  0, AH_WAIT_TIMEOUT)) {
-		ath_print(common, ATH_DBG_CALIBRATE, "offset calibration "
-			  "failed to complete in 1ms; noisy ??\n");
+		ath_dbg(common, ATH_DBG_CALIBRATE,
+			"offset calibration failed to complete in 1ms; noisy environment?\n");
 		return false;
 	}
 
@@ -829,9 +826,8 @@ static bool ar9002_hw_init_cal(struct at
 		if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL,
 				   AR_PHY_AGC_CONTROL_CAL,
 				   0, AH_WAIT_TIMEOUT)) {
-			ath_print(common, ATH_DBG_CALIBRATE,
-				  "offset calibration failed to "
-				  "complete in 1ms; noisy environment?\n");
+			ath_dbg(common, ATH_DBG_CALIBRATE,
+				"offset calibration failed to complete in 1ms; noisy environment?\n");
 			return false;
 		}
 
@@ -866,19 +862,19 @@ static bool ar9002_hw_init_cal(struct at
 
 			INIT_CAL(&ah->adcgain_caldata);
 			INSERT_CAL(ah, &ah->adcgain_caldata);
-			ath_print(common, ATH_DBG_CALIBRATE,
-				  "enabling ADC Gain Calibration.\n");
+			ath_dbg(common, ATH_DBG_CALIBRATE,
+				"enabling ADC Gain Calibration.\n");
 
 			INIT_CAL(&ah->adcdc_caldata);
 			INSERT_CAL(ah, &ah->adcdc_caldata);
-			ath_print(common, ATH_DBG_CALIBRATE,
-				  "enabling ADC DC Calibration.\n");
+			ath_dbg(common, ATH_DBG_CALIBRATE,
+				"enabling ADC DC Calibration.\n");
 		}
 
 		INIT_CAL(&ah->iq_caldata);
 		INSERT_CAL(ah, &ah->iq_caldata);
-		ath_print(common, ATH_DBG_CALIBRATE,
-			  "enabling IQ Calibration.\n");
+		ath_dbg(common, ATH_DBG_CALIBRATE,
+			"enabling IQ Calibration.\n");
 
 		ah->cal_list_curr = ah->cal_list;
 
@@ -958,6 +954,9 @@ static void ar9002_hw_init_cal_settings(
 				&adc_dc_cal_multi_sample;
 		}
 		ah->supp_cals = ADC_GAIN_CAL | ADC_DC_CAL | IQ_MISMATCH_CAL;
+
+		if (AR_SREV_9287(ah))
+			ah->supp_cals &= ~ADC_GAIN_CAL;
 	}
 }
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/ar9002_hw.c linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/ar9002_hw.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/ar9002_hw.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/ar9002_hw.c	2011-03-14 21:20:32.000000000 -0400
@@ -22,28 +22,10 @@
 
 int modparam_force_new_ani;
 module_param_named(force_new_ani, modparam_force_new_ani, int, 0444);
-MODULE_PARM_DESC(nohwcrypt, "Force new ANI for AR5008, AR9001, AR9002");
+MODULE_PARM_DESC(force_new_ani, "Force new ANI for AR5008, AR9001, AR9002");
 
 /* General hardware code for the A5008/AR9001/AR9002 hadware families */
 
-static bool ar9002_hw_macversion_supported(u32 macversion)
-{
-	switch (macversion) {
-	case AR_SREV_VERSION_5416_PCI:
-	case AR_SREV_VERSION_5416_PCIE:
-	case AR_SREV_VERSION_9160:
-	case AR_SREV_VERSION_9100:
-	case AR_SREV_VERSION_9280:
-	case AR_SREV_VERSION_9285:
-	case AR_SREV_VERSION_9287:
-	case AR_SREV_VERSION_9271:
-		return true;
-	default:
-		break;
-	}
-	return false;
-}
-
 static void ar9002_hw_init_mode_regs(struct ath_hw *ah)
 {
 	if (AR_SREV_9271(ah)) {
@@ -444,9 +426,8 @@ static void ar9002_hw_configpcipowersave
 		}
 
 		/* WAR for ASPM system hang */
-		if (AR_SREV_9280(ah) || AR_SREV_9285(ah) || AR_SREV_9287(ah)) {
+		if (AR_SREV_9285(ah) || AR_SREV_9287(ah))
 			val |= (AR_WA_BIT6 | AR_WA_BIT7);
-		}
 
 		if (AR_SREV_9285E_20(ah))
 			val |= AR_WA_BIT23;
@@ -494,9 +475,9 @@ int ar9002_hw_rf_claim(struct ath_hw *ah
 	case AR_RAD2122_SREV_MAJOR:
 		break;
 	default:
-		ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL,
-			  "Radio Chip Rev 0x%02X not supported\n",
-			  val & AR_RADIO_SREV_MAJOR);
+		ath_err(ath9k_hw_common(ah),
+			"Radio Chip Rev 0x%02X not supported\n",
+			val & AR_RADIO_SREV_MAJOR);
 		return -EOPNOTSUPP;
 	}
 
@@ -565,7 +546,6 @@ void ar9002_hw_attach_ops(struct ath_hw
 
 	priv_ops->init_mode_regs = ar9002_hw_init_mode_regs;
 	priv_ops->init_mode_gain_regs = ar9002_hw_init_mode_gain_regs;
-	priv_ops->macversion_supported = ar9002_hw_macversion_supported;
 
 	ops->config_pci_powersave = ar9002_hw_configpcipowersave;
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/ar9002_mac.c linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/ar9002_mac.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/ar9002_mac.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/ar9002_mac.c	2011-03-14 21:20:32.000000000 -0400
@@ -90,13 +90,10 @@ static bool ar9002_hw_get_isr(struct ath
 
 		*masked = isr & ATH9K_INT_COMMON;
 
-		if (ah->config.rx_intr_mitigation) {
-			if (isr & (AR_ISR_RXMINTR | AR_ISR_RXINTM))
-				*masked |= ATH9K_INT_RX;
-		}
-
-		if (isr & (AR_ISR_RXOK | AR_ISR_RXERR))
+		if (isr & (AR_ISR_RXMINTR | AR_ISR_RXINTM |
+			   AR_ISR_RXOK | AR_ISR_RXERR))
 			*masked |= ATH9K_INT_RX;
+
 		if (isr &
 		    (AR_ISR_TXOK | AR_ISR_TXDESC | AR_ISR_TXERR |
 		     AR_ISR_TXEOL)) {
@@ -114,16 +111,8 @@ static bool ar9002_hw_get_isr(struct ath
 		}
 
 		if (isr & AR_ISR_RXORN) {
-			ath_print(common, ATH_DBG_INTERRUPT,
-				  "receive FIFO overrun interrupt\n");
-		}
-
-		if (!AR_SREV_9100(ah)) {
-			if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) {
-				u32 isr5 = REG_READ(ah, AR_ISR_S5_S);
-				if (isr5 & AR_ISR_S5_TIM_TIMER)
-					*masked |= ATH9K_INT_TIM_TIMER;
-			}
+			ath_dbg(common, ATH_DBG_INTERRUPT,
+				"receive FIFO overrun interrupt\n");
 		}
 
 		*masked |= mask2;
@@ -136,17 +125,18 @@ static bool ar9002_hw_get_isr(struct ath
 		u32 s5_s;
 
 		s5_s = REG_READ(ah, AR_ISR_S5_S);
-		if (isr & AR_ISR_GENTMR) {
-			ah->intr_gen_timer_trigger =
+		ah->intr_gen_timer_trigger =
 				MS(s5_s, AR_ISR_S5_GENTIMER_TRIG);
 
-			ah->intr_gen_timer_thresh =
-				MS(s5_s, AR_ISR_S5_GENTIMER_THRESH);
+		ah->intr_gen_timer_thresh =
+			MS(s5_s, AR_ISR_S5_GENTIMER_THRESH);
 
-			if (ah->intr_gen_timer_trigger)
-				*masked |= ATH9K_INT_GENTIMER;
+		if (ah->intr_gen_timer_trigger)
+			*masked |= ATH9K_INT_GENTIMER;
 
-		}
+		if ((s5_s & AR_ISR_S5_TIM_TIMER) &&
+		    !(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP))
+			*masked |= ATH9K_INT_TIM_TIMER;
 	}
 
 	if (sync_cause) {
@@ -157,25 +147,25 @@ static bool ar9002_hw_get_isr(struct ath
 
 		if (fatal_int) {
 			if (sync_cause & AR_INTR_SYNC_HOST1_FATAL) {
-				ath_print(common, ATH_DBG_ANY,
-					  "received PCI FATAL interrupt\n");
+				ath_dbg(common, ATH_DBG_ANY,
+					"received PCI FATAL interrupt\n");
 			}
 			if (sync_cause & AR_INTR_SYNC_HOST1_PERR) {
-				ath_print(common, ATH_DBG_ANY,
-					  "received PCI PERR interrupt\n");
+				ath_dbg(common, ATH_DBG_ANY,
+					"received PCI PERR interrupt\n");
 			}
 			*masked |= ATH9K_INT_FATAL;
 		}
 		if (sync_cause & AR_INTR_SYNC_RADM_CPL_TIMEOUT) {
-			ath_print(common, ATH_DBG_INTERRUPT,
-				  "AR_INTR_SYNC_RADM_CPL_TIMEOUT\n");
+			ath_dbg(common, ATH_DBG_INTERRUPT,
+				"AR_INTR_SYNC_RADM_CPL_TIMEOUT\n");
 			REG_WRITE(ah, AR_RC, AR_RC_HOSTIF);
 			REG_WRITE(ah, AR_RC, 0);
 			*masked |= ATH9K_INT_FATAL;
 		}
 		if (sync_cause & AR_INTR_SYNC_LOCAL_TIMEOUT) {
-			ath_print(common, ATH_DBG_INTERRUPT,
-				  "AR_INTR_SYNC_LOCAL_TIMEOUT\n");
+			ath_dbg(common, ATH_DBG_INTERRUPT,
+				"AR_INTR_SYNC_LOCAL_TIMEOUT\n");
 		}
 
 		REG_WRITE(ah, AR_INTR_SYNC_CAUSE_CLR, sync_cause);
@@ -218,77 +208,70 @@ static int ar9002_hw_proc_txdesc(struct
 				 struct ath_tx_status *ts)
 {
 	struct ar5416_desc *ads = AR5416DESC(ds);
+	u32 status;
 
-	if ((ads->ds_txstatus9 & AR_TxDone) == 0)
+	status = ACCESS_ONCE(ads->ds_txstatus9);
+	if ((status & AR_TxDone) == 0)
 		return -EINPROGRESS;
 
-	ts->ts_seqnum = MS(ads->ds_txstatus9, AR_SeqNum);
 	ts->ts_tstamp = ads->AR_SendTimestamp;
 	ts->ts_status = 0;
 	ts->ts_flags = 0;
 
-	if (ads->ds_txstatus1 & AR_FrmXmitOK)
+	if (status & AR_TxOpExceeded)
+		ts->ts_status |= ATH9K_TXERR_XTXOP;
+	ts->tid = MS(status, AR_TxTid);
+	ts->ts_rateindex = MS(status, AR_FinalTxIdx);
+	ts->ts_seqnum = MS(status, AR_SeqNum);
+
+	status = ACCESS_ONCE(ads->ds_txstatus0);
+	ts->ts_rssi_ctl0 = MS(status, AR_TxRSSIAnt00);
+	ts->ts_rssi_ctl1 = MS(status, AR_TxRSSIAnt01);
+	ts->ts_rssi_ctl2 = MS(status, AR_TxRSSIAnt02);
+	if (status & AR_TxBaStatus) {
+		ts->ts_flags |= ATH9K_TX_BA;
+		ts->ba_low = ads->AR_BaBitmapLow;
+		ts->ba_high = ads->AR_BaBitmapHigh;
+	}
+
+	status = ACCESS_ONCE(ads->ds_txstatus1);
+	if (status & AR_FrmXmitOK)
 		ts->ts_status |= ATH9K_TX_ACKED;
-	if (ads->ds_txstatus1 & AR_ExcessiveRetries)
-		ts->ts_status |= ATH9K_TXERR_XRETRY;
-	if (ads->ds_txstatus1 & AR_Filtered)
-		ts->ts_status |= ATH9K_TXERR_FILT;
-	if (ads->ds_txstatus1 & AR_FIFOUnderrun) {
-		ts->ts_status |= ATH9K_TXERR_FIFO;
-		ath9k_hw_updatetxtriglevel(ah, true);
+	else {
+		if (status & AR_ExcessiveRetries)
+			ts->ts_status |= ATH9K_TXERR_XRETRY;
+		if (status & AR_Filtered)
+			ts->ts_status |= ATH9K_TXERR_FILT;
+		if (status & AR_FIFOUnderrun) {
+			ts->ts_status |= ATH9K_TXERR_FIFO;
+			ath9k_hw_updatetxtriglevel(ah, true);
+		}
 	}
-	if (ads->ds_txstatus9 & AR_TxOpExceeded)
-		ts->ts_status |= ATH9K_TXERR_XTXOP;
-	if (ads->ds_txstatus1 & AR_TxTimerExpired)
+	if (status & AR_TxTimerExpired)
 		ts->ts_status |= ATH9K_TXERR_TIMER_EXPIRED;
-
-	if (ads->ds_txstatus1 & AR_DescCfgErr)
+	if (status & AR_DescCfgErr)
 		ts->ts_flags |= ATH9K_TX_DESC_CFG_ERR;
-	if (ads->ds_txstatus1 & AR_TxDataUnderrun) {
+	if (status & AR_TxDataUnderrun) {
 		ts->ts_flags |= ATH9K_TX_DATA_UNDERRUN;
 		ath9k_hw_updatetxtriglevel(ah, true);
 	}
-	if (ads->ds_txstatus1 & AR_TxDelimUnderrun) {
+	if (status & AR_TxDelimUnderrun) {
 		ts->ts_flags |= ATH9K_TX_DELIM_UNDERRUN;
 		ath9k_hw_updatetxtriglevel(ah, true);
 	}
-	if (ads->ds_txstatus0 & AR_TxBaStatus) {
-		ts->ts_flags |= ATH9K_TX_BA;
-		ts->ba_low = ads->AR_BaBitmapLow;
-		ts->ba_high = ads->AR_BaBitmapHigh;
-	}
+	ts->ts_shortretry = MS(status, AR_RTSFailCnt);
+	ts->ts_longretry = MS(status, AR_DataFailCnt);
+	ts->ts_virtcol = MS(status, AR_VirtRetryCnt);
 
-	ts->ts_rateindex = MS(ads->ds_txstatus9, AR_FinalTxIdx);
-	switch (ts->ts_rateindex) {
-	case 0:
-		ts->ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate0);
-		break;
-	case 1:
-		ts->ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate1);
-		break;
-	case 2:
-		ts->ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate2);
-		break;
-	case 3:
-		ts->ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate3);
-		break;
-	}
+	status = ACCESS_ONCE(ads->ds_txstatus5);
+	ts->ts_rssi = MS(status, AR_TxRSSICombined);
+	ts->ts_rssi_ext0 = MS(status, AR_TxRSSIAnt10);
+	ts->ts_rssi_ext1 = MS(status, AR_TxRSSIAnt11);
+	ts->ts_rssi_ext2 = MS(status, AR_TxRSSIAnt12);
 
-	ts->ts_rssi = MS(ads->ds_txstatus5, AR_TxRSSICombined);
-	ts->ts_rssi_ctl0 = MS(ads->ds_txstatus0, AR_TxRSSIAnt00);
-	ts->ts_rssi_ctl1 = MS(ads->ds_txstatus0, AR_TxRSSIAnt01);
-	ts->ts_rssi_ctl2 = MS(ads->ds_txstatus0, AR_TxRSSIAnt02);
-	ts->ts_rssi_ext0 = MS(ads->ds_txstatus5, AR_TxRSSIAnt10);
-	ts->ts_rssi_ext1 = MS(ads->ds_txstatus5, AR_TxRSSIAnt11);
-	ts->ts_rssi_ext2 = MS(ads->ds_txstatus5, AR_TxRSSIAnt12);
 	ts->evm0 = ads->AR_TxEVM0;
 	ts->evm1 = ads->AR_TxEVM1;
 	ts->evm2 = ads->AR_TxEVM2;
-	ts->ts_shortretry = MS(ads->ds_txstatus1, AR_RTSFailCnt);
-	ts->ts_longretry = MS(ads->ds_txstatus1, AR_DataFailCnt);
-	ts->ts_virtcol = MS(ads->ds_txstatus1, AR_VirtRetryCnt);
-	ts->tid = MS(ads->ds_txstatus9, AR_TxTid);
-	ts->ts_antenna = 0;
 
 	return 0;
 }
@@ -300,7 +283,6 @@ static void ar9002_hw_set11n_txdesc(stru
 {
 	struct ar5416_desc *ads = AR5416DESC(ds);
 
-	txPower += ah->txpower_indexoffset;
 	if (txPower > 63)
 		txPower = 63;
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/ar9002_phy.c linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/ar9002_phy.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/ar9002_phy.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/ar9002_phy.c	2011-03-14 21:20:32.000000000 -0400
@@ -175,13 +175,15 @@ static void ar9002_hw_spur_mitigate(stru
 	int upper, lower, cur_vit_mask;
 	int tmp, newVal;
 	int i;
-	int pilot_mask_reg[4] = { AR_PHY_TIMING7, AR_PHY_TIMING8,
-			  AR_PHY_PILOT_MASK_01_30, AR_PHY_PILOT_MASK_31_60
+	static const int pilot_mask_reg[4] = {
+		AR_PHY_TIMING7, AR_PHY_TIMING8,
+		AR_PHY_PILOT_MASK_01_30, AR_PHY_PILOT_MASK_31_60
 	};
-	int chan_mask_reg[4] = { AR_PHY_TIMING9, AR_PHY_TIMING10,
-			 AR_PHY_CHANNEL_MASK_01_30, AR_PHY_CHANNEL_MASK_31_60
+	static const int chan_mask_reg[4] = {
+		AR_PHY_TIMING9, AR_PHY_TIMING10,
+		AR_PHY_CHANNEL_MASK_01_30, AR_PHY_CHANNEL_MASK_31_60
 	};
-	int inc[4] = { 0, 100, 0, 0 };
+	static const int inc[4] = { 0, 100, 0, 0 };
 	struct chan_centers centers;
 
 	int8_t mask_m[123];
@@ -201,13 +203,14 @@ static void ar9002_hw_spur_mitigate(stru
 	for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) {
 		cur_bb_spur = ah->eep_ops->get_spur_channel(ah, i, is2GHz);
 
+		if (AR_NO_SPUR == cur_bb_spur)
+			break;
+
 		if (is2GHz)
 			cur_bb_spur = (cur_bb_spur / 10) + AR_BASE_FREQ_2GHZ;
 		else
 			cur_bb_spur = (cur_bb_spur / 10) + AR_BASE_FREQ_5GHZ;
 
-		if (AR_NO_SPUR == cur_bb_spur)
-			break;
 		cur_bb_spur = cur_bb_spur - freq;
 
 		if (IS_CHAN_HT40(chan)) {
@@ -473,21 +476,21 @@ static void ar9002_hw_do_getnf(struct at
 	int16_t nf;
 
 	nf = MS(REG_READ(ah, AR_PHY_CCA), AR9280_PHY_MINCCA_PWR);
-	nfarray[0] = sign_extend(nf, 9);
+	nfarray[0] = sign_extend32(nf, 8);
 
 	nf = MS(REG_READ(ah, AR_PHY_EXT_CCA), AR9280_PHY_EXT_MINCCA_PWR);
 	if (IS_CHAN_HT40(ah->curchan))
-		nfarray[3] = sign_extend(nf, 9);
+		nfarray[3] = sign_extend32(nf, 8);
 
 	if (AR_SREV_9285(ah) || AR_SREV_9271(ah))
 		return;
 
 	nf = MS(REG_READ(ah, AR_PHY_CH1_CCA), AR9280_PHY_CH1_MINCCA_PWR);
-	nfarray[1] = sign_extend(nf, 9);
+	nfarray[1] = sign_extend32(nf, 8);
 
 	nf = MS(REG_READ(ah, AR_PHY_CH1_EXT_CCA), AR9280_PHY_CH1_EXT_MINCCA_PWR);
 	if (IS_CHAN_HT40(ah->curchan))
-		nfarray[4] = sign_extend(nf, 9);
+		nfarray[4] = sign_extend32(nf, 8);
 }
 
 static void ar9002_hw_set_nf_limits(struct ath_hw *ah)
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h	2011-03-14 21:20:32.000000000 -0400
@@ -34,9 +34,9 @@ static const u32 ar9300_2p2_radio_postam
 
 static const u32 ar9300Modes_lowest_ob_db_tx_gain_table_2p2[][5] = {
 	/* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
-	{0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x00637800, 0x00637800},
-	{0x0000a2e0, 0x0000f800, 0x0000f800, 0x03838000, 0x03838000},
-	{0x0000a2e4, 0x03ff0000, 0x03ff0000, 0x03fc0000, 0x03fc0000},
+	{0x0000a2dc, 0x00033800, 0x00033800, 0x00637800, 0x00637800},
+	{0x0000a2e0, 0x0003c000, 0x0003c000, 0x03838000, 0x03838000},
+	{0x0000a2e4, 0x03fc0000, 0x03fc0000, 0x03fc0000, 0x03fc0000},
 	{0x0000a2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
 	{0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9},
 	{0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
@@ -56,21 +56,21 @@ static const u32 ar9300Modes_lowest_ob_d
 	{0x0000a538, 0x4702244a, 0x4702244a, 0x34000e24, 0x34000e24},
 	{0x0000a53c, 0x4b02244c, 0x4b02244c, 0x38001640, 0x38001640},
 	{0x0000a540, 0x4e02246c, 0x4e02246c, 0x3c001660, 0x3c001660},
-	{0x0000a544, 0x5302266c, 0x5302266c, 0x3f001861, 0x3f001861},
-	{0x0000a548, 0x5702286c, 0x5702286c, 0x43001a81, 0x43001a81},
-	{0x0000a54c, 0x5c02486b, 0x5c02486b, 0x47001a83, 0x47001a83},
-	{0x0000a550, 0x61024a6c, 0x61024a6c, 0x4a001c84, 0x4a001c84},
-	{0x0000a554, 0x66026a6c, 0x66026a6c, 0x4e001ce3, 0x4e001ce3},
-	{0x0000a558, 0x6b026e6c, 0x6b026e6c, 0x52001ce5, 0x52001ce5},
-	{0x0000a55c, 0x7002708c, 0x7002708c, 0x56001ce9, 0x56001ce9},
-	{0x0000a560, 0x7302b08a, 0x7302b08a, 0x5a001ceb, 0x5a001ceb},
-	{0x0000a564, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec},
-	{0x0000a568, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec},
-	{0x0000a56c, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec},
-	{0x0000a570, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec},
-	{0x0000a574, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec},
-	{0x0000a578, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec},
-	{0x0000a57c, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec},
+	{0x0000a544, 0x52022470, 0x52022470, 0x3f001861, 0x3f001861},
+	{0x0000a548, 0x55022490, 0x55022490, 0x43001a81, 0x43001a81},
+	{0x0000a54c, 0x59022492, 0x59022492, 0x47001a83, 0x47001a83},
+	{0x0000a550, 0x5d022692, 0x5d022692, 0x4a001c84, 0x4a001c84},
+	{0x0000a554, 0x61022892, 0x61022892, 0x4e001ce3, 0x4e001ce3},
+	{0x0000a558, 0x65024890, 0x65024890, 0x52001ce5, 0x52001ce5},
+	{0x0000a55c, 0x69024892, 0x69024892, 0x56001ce9, 0x56001ce9},
+	{0x0000a560, 0x6e024c92, 0x6e024c92, 0x5a001ceb, 0x5a001ceb},
+	{0x0000a564, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
+	{0x0000a568, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
+	{0x0000a56c, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
+	{0x0000a570, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
+	{0x0000a574, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
+	{0x0000a578, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
+	{0x0000a57c, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
 	{0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000},
 	{0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002},
 	{0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004},
@@ -88,44 +88,44 @@ static const u32 ar9300Modes_lowest_ob_d
 	{0x0000a5b8, 0x4782244a, 0x4782244a, 0x34800e24, 0x34800e24},
 	{0x0000a5bc, 0x4b82244c, 0x4b82244c, 0x38801640, 0x38801640},
 	{0x0000a5c0, 0x4e82246c, 0x4e82246c, 0x3c801660, 0x3c801660},
-	{0x0000a5c4, 0x5382266c, 0x5382266c, 0x3f801861, 0x3f801861},
-	{0x0000a5c8, 0x5782286c, 0x5782286c, 0x43801a81, 0x43801a81},
-	{0x0000a5cc, 0x5c82486b, 0x5c82486b, 0x47801a83, 0x47801a83},
-	{0x0000a5d0, 0x61824a6c, 0x61824a6c, 0x4a801c84, 0x4a801c84},
-	{0x0000a5d4, 0x66826a6c, 0x66826a6c, 0x4e801ce3, 0x4e801ce3},
-	{0x0000a5d8, 0x6b826e6c, 0x6b826e6c, 0x52801ce5, 0x52801ce5},
-	{0x0000a5dc, 0x7082708c, 0x7082708c, 0x56801ce9, 0x56801ce9},
-	{0x0000a5e0, 0x7382b08a, 0x7382b08a, 0x5a801ceb, 0x5a801ceb},
-	{0x0000a5e4, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec},
-	{0x0000a5e8, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec},
-	{0x0000a5ec, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec},
-	{0x0000a5f0, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec},
-	{0x0000a5f4, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec},
-	{0x0000a5f8, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec},
-	{0x0000a5fc, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec},
+	{0x0000a5c4, 0x52822470, 0x52822470, 0x3f801861, 0x3f801861},
+	{0x0000a5c8, 0x55822490, 0x55822490, 0x43801a81, 0x43801a81},
+	{0x0000a5cc, 0x59822492, 0x59822492, 0x47801a83, 0x47801a83},
+	{0x0000a5d0, 0x5d822692, 0x5d822692, 0x4a801c84, 0x4a801c84},
+	{0x0000a5d4, 0x61822892, 0x61822892, 0x4e801ce3, 0x4e801ce3},
+	{0x0000a5d8, 0x65824890, 0x65824890, 0x52801ce5, 0x52801ce5},
+	{0x0000a5dc, 0x69824892, 0x69824892, 0x56801ce9, 0x56801ce9},
+	{0x0000a5e0, 0x6e824c92, 0x6e824c92, 0x5a801ceb, 0x5a801ceb},
+	{0x0000a5e4, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
+	{0x0000a5e8, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
+	{0x0000a5ec, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
+	{0x0000a5f0, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
+	{0x0000a5f4, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
+	{0x0000a5f8, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
+	{0x0000a5fc, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
 	{0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
 	{0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
 	{0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
 	{0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
 	{0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-	{0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000},
-	{0x0000a618, 0x01404501, 0x01404501, 0x01404501, 0x01404501},
-	{0x0000a61c, 0x02008802, 0x02008802, 0x02008501, 0x02008501},
-	{0x0000a620, 0x0300cc03, 0x0300cc03, 0x0280ca03, 0x0280ca03},
-	{0x0000a624, 0x0300cc03, 0x0300cc03, 0x03010c04, 0x03010c04},
-	{0x0000a628, 0x0300cc03, 0x0300cc03, 0x04014c04, 0x04014c04},
-	{0x0000a62c, 0x03810c03, 0x03810c03, 0x04015005, 0x04015005},
-	{0x0000a630, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
-	{0x0000a634, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
-	{0x0000a638, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
-	{0x0000a63c, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
-	{0x0000b2dc, 0x0380c7fc, 0x0380c7fc, 0x00637800, 0x00637800},
-	{0x0000b2e0, 0x0000f800, 0x0000f800, 0x03838000, 0x03838000},
-	{0x0000b2e4, 0x03ff0000, 0x03ff0000, 0x03fc0000, 0x03fc0000},
+	{0x0000a614, 0x02004000, 0x02004000, 0x01404000, 0x01404000},
+	{0x0000a618, 0x02004801, 0x02004801, 0x01404501, 0x01404501},
+	{0x0000a61c, 0x02808a02, 0x02808a02, 0x02008501, 0x02008501},
+	{0x0000a620, 0x0380ce03, 0x0380ce03, 0x0280ca03, 0x0280ca03},
+	{0x0000a624, 0x04411104, 0x04411104, 0x03010c04, 0x03010c04},
+	{0x0000a628, 0x04411104, 0x04411104, 0x04014c04, 0x04014c04},
+	{0x0000a62c, 0x04411104, 0x04411104, 0x04015005, 0x04015005},
+	{0x0000a630, 0x04411104, 0x04411104, 0x04015005, 0x04015005},
+	{0x0000a634, 0x04411104, 0x04411104, 0x04015005, 0x04015005},
+	{0x0000a638, 0x04411104, 0x04411104, 0x04015005, 0x04015005},
+	{0x0000a63c, 0x04411104, 0x04411104, 0x04015005, 0x04015005},
+	{0x0000b2dc, 0x00033800, 0x00033800, 0x00637800, 0x00637800},
+	{0x0000b2e0, 0x0003c000, 0x0003c000, 0x03838000, 0x03838000},
+	{0x0000b2e4, 0x03fc0000, 0x03fc0000, 0x03fc0000, 0x03fc0000},
 	{0x0000b2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-	{0x0000c2dc, 0x0380c7fc, 0x0380c7fc, 0x00637800, 0x00637800},
-	{0x0000c2e0, 0x0000f800, 0x0000f800, 0x03838000, 0x03838000},
-	{0x0000c2e4, 0x03ff0000, 0x03ff0000, 0x03fc0000, 0x03fc0000},
+	{0x0000c2dc, 0x00033800, 0x00033800, 0x00637800, 0x00637800},
+	{0x0000c2e0, 0x0003c000, 0x0003c000, 0x03838000, 0x03838000},
+	{0x0000c2e4, 0x03fc0000, 0x03fc0000, 0x03fc0000, 0x03fc0000},
 	{0x0000c2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
 	{0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
 	{0x00016048, 0x62480001, 0x62480001, 0x62480001, 0x62480001},
@@ -638,6 +638,7 @@ static const u32 ar9300_2p2_baseband_pos
 	{0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000},
 	{0x0000a204, 0x000037c0, 0x000037c4, 0x000037c4, 0x000037c0},
 	{0x0000a208, 0x00000104, 0x00000104, 0x00000004, 0x00000004},
+	{0x0000a22c, 0x01026a2f, 0x01026a2f, 0x01026a2f, 0x01026a2f},
 	{0x0000a230, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b},
 	{0x0000a234, 0x00000fff, 0x10000fff, 0x10000fff, 0x00000fff},
 	{0x0000a238, 0xffb81018, 0xffb81018, 0xffb81018, 0xffb81018},
@@ -680,7 +681,7 @@ static const u32 ar9300_2p2_baseband_cor
 	{0x0000981c, 0x00020028},
 	{0x00009834, 0x6400a290},
 	{0x00009838, 0x0108ecff},
-	{0x0000983c, 0x14750600},
+	{0x0000983c, 0x0d000600},
 	{0x00009880, 0x201fff00},
 	{0x00009884, 0x00001042},
 	{0x000098a4, 0x00200400},
@@ -722,7 +723,6 @@ static const u32 ar9300_2p2_baseband_cor
 	{0x0000a220, 0x00000000},
 	{0x0000a224, 0x00000000},
 	{0x0000a228, 0x10002310},
-	{0x0000a22c, 0x01036a27},
 	{0x0000a23c, 0x00000000},
 	{0x0000a244, 0x0c000000},
 	{0x0000a2a0, 0x00000001},
@@ -1842,7 +1842,7 @@ static const u32 ar9300_2p2_soc_preamble
 
 static const u32 ar9300PciePhy_pll_on_clkreq_disable_L1_2p2[][2] = {
 	/* Addr      allmodes  */
-	{0x00004040, 0x08212e5e},
+	{0x00004040, 0x0821265e},
 	{0x00004040, 0x0008003b},
 	{0x00004044, 0x00000000},
 };
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/ar9003_calib.c linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/ar9003_calib.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/ar9003_calib.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/ar9003_calib.c	2011-03-14 21:20:32.000000000 -0400
@@ -18,6 +18,16 @@
 #include "hw-ops.h"
 #include "ar9003_phy.h"
 
+#define MPASS	3
+#define MAX_MEASUREMENT	8
+#define MAX_DIFFERENCE	10
+
+struct coeff {
+	int mag_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT][MPASS];
+	int phs_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT][MPASS];
+	int iqc_coeff[2];
+};
+
 enum ar9003_cal_types {
 	IQ_MISMATCH_CAL = BIT(0),
 	TEMP_COMP_CAL = BIT(1),
@@ -40,8 +50,8 @@ static void ar9003_hw_setup_calibration(
 		currCal->calData->calCountMax);
 		REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_IQ);
 
-		ath_print(common, ATH_DBG_CALIBRATE,
-			  "starting IQ Mismatch Calibration\n");
+		ath_dbg(common, ATH_DBG_CALIBRATE,
+			"starting IQ Mismatch Calibration\n");
 
 		/* Kick-off cal */
 		REG_SET_BIT(ah, AR_PHY_TIMING4, AR_PHY_TIMING4_DO_CAL);
@@ -52,8 +62,8 @@ static void ar9003_hw_setup_calibration(
 		REG_RMW_FIELD(ah, AR_PHY_65NM_CH0_THERM,
 			      AR_PHY_65NM_CH0_THERM_START, 1);
 
-		ath_print(common, ATH_DBG_CALIBRATE,
-			  "starting Temperature Compensation Calibration\n");
+		ath_dbg(common, ATH_DBG_CALIBRATE,
+			"starting Temperature Compensation Calibration\n");
 		break;
 	}
 }
@@ -181,11 +191,11 @@ static void ar9003_hw_iqcal_collect(stru
 			REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
 		ah->totalIqCorrMeas[i] +=
 			(int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
-		ath_print(ath9k_hw_common(ah), ATH_DBG_CALIBRATE,
-			  "%d: Chn %d pmi=0x%08x;pmq=0x%08x;iqcm=0x%08x;\n",
-			  ah->cal_samples, i, ah->totalPowerMeasI[i],
-			  ah->totalPowerMeasQ[i],
-			  ah->totalIqCorrMeas[i]);
+		ath_dbg(ath9k_hw_common(ah), ATH_DBG_CALIBRATE,
+			"%d: Chn %d pmi=0x%08x;pmq=0x%08x;iqcm=0x%08x;\n",
+			ah->cal_samples, i, ah->totalPowerMeasI[i],
+			ah->totalPowerMeasQ[i],
+			ah->totalIqCorrMeas[i]);
 	}
 }
 
@@ -196,7 +206,7 @@ static void ar9003_hw_iqcalibrate(struct
 	u32 qCoffDenom, iCoffDenom;
 	int32_t qCoff, iCoff;
 	int iqCorrNeg, i;
-	const u_int32_t offset_array[3] = {
+	static const u_int32_t offset_array[3] = {
 		AR_PHY_RX_IQCAL_CORR_B0,
 		AR_PHY_RX_IQCAL_CORR_B1,
 		AR_PHY_RX_IQCAL_CORR_B2,
@@ -207,13 +217,13 @@ static void ar9003_hw_iqcalibrate(struct
 		powerMeasQ = ah->totalPowerMeasQ[i];
 		iqCorrMeas = ah->totalIqCorrMeas[i];
 
-		ath_print(common, ATH_DBG_CALIBRATE,
-			  "Starting IQ Cal and Correction for Chain %d\n",
-			  i);
+		ath_dbg(common, ATH_DBG_CALIBRATE,
+			"Starting IQ Cal and Correction for Chain %d\n",
+			i);
 
-		ath_print(common, ATH_DBG_CALIBRATE,
-			  "Orignal: Chn %diq_corr_meas = 0x%08x\n",
-			  i, ah->totalIqCorrMeas[i]);
+		ath_dbg(common, ATH_DBG_CALIBRATE,
+			"Orignal: Chn %diq_corr_meas = 0x%08x\n",
+			i, ah->totalIqCorrMeas[i]);
 
 		iqCorrNeg = 0;
 
@@ -222,12 +232,12 @@ static void ar9003_hw_iqcalibrate(struct
 			iqCorrNeg = 1;
 		}
 
-		ath_print(common, ATH_DBG_CALIBRATE,
-			  "Chn %d pwr_meas_i = 0x%08x\n", i, powerMeasI);
-		ath_print(common, ATH_DBG_CALIBRATE,
-			  "Chn %d pwr_meas_q = 0x%08x\n", i, powerMeasQ);
-		ath_print(common, ATH_DBG_CALIBRATE, "iqCorrNeg is 0x%08x\n",
-			  iqCorrNeg);
+		ath_dbg(common, ATH_DBG_CALIBRATE,
+			"Chn %d pwr_meas_i = 0x%08x\n", i, powerMeasI);
+		ath_dbg(common, ATH_DBG_CALIBRATE,
+			"Chn %d pwr_meas_q = 0x%08x\n", i, powerMeasQ);
+		ath_dbg(common, ATH_DBG_CALIBRATE, "iqCorrNeg is 0x%08x\n",
+			iqCorrNeg);
 
 		iCoffDenom = (powerMeasI / 2 + powerMeasQ / 2) / 256;
 		qCoffDenom = powerMeasQ / 64;
@@ -235,10 +245,10 @@ static void ar9003_hw_iqcalibrate(struct
 		if ((iCoffDenom != 0) && (qCoffDenom != 0)) {
 			iCoff = iqCorrMeas / iCoffDenom;
 			qCoff = powerMeasI / qCoffDenom - 64;
-			ath_print(common, ATH_DBG_CALIBRATE,
-				  "Chn %d iCoff = 0x%08x\n", i, iCoff);
-			ath_print(common, ATH_DBG_CALIBRATE,
-				  "Chn %d qCoff = 0x%08x\n", i, qCoff);
+			ath_dbg(common, ATH_DBG_CALIBRATE,
+				"Chn %d iCoff = 0x%08x\n", i, iCoff);
+			ath_dbg(common, ATH_DBG_CALIBRATE,
+				"Chn %d qCoff = 0x%08x\n", i, qCoff);
 
 			/* Force bounds on iCoff */
 			if (iCoff >= 63)
@@ -259,14 +269,13 @@ static void ar9003_hw_iqcalibrate(struct
 			iCoff = iCoff & 0x7f;
 			qCoff = qCoff & 0x7f;
 
-			ath_print(common, ATH_DBG_CALIBRATE,
-				  "Chn %d : iCoff = 0x%x  qCoff = 0x%x\n",
-				  i, iCoff, qCoff);
-			ath_print(common, ATH_DBG_CALIBRATE,
-				  "Register offset (0x%04x) "
-				  "before update = 0x%x\n",
-				  offset_array[i],
-				  REG_READ(ah, offset_array[i]));
+			ath_dbg(common, ATH_DBG_CALIBRATE,
+				"Chn %d : iCoff = 0x%x  qCoff = 0x%x\n",
+				i, iCoff, qCoff);
+			ath_dbg(common, ATH_DBG_CALIBRATE,
+				"Register offset (0x%04x) before update = 0x%x\n",
+				offset_array[i],
+				REG_READ(ah, offset_array[i]));
 
 			REG_RMW_FIELD(ah, offset_array[i],
 				      AR_PHY_RX_IQCAL_CORR_IQCORR_Q_I_COFF,
@@ -274,33 +283,29 @@ static void ar9003_hw_iqcalibrate(struct
 			REG_RMW_FIELD(ah, offset_array[i],
 				      AR_PHY_RX_IQCAL_CORR_IQCORR_Q_Q_COFF,
 				      qCoff);
-			ath_print(common, ATH_DBG_CALIBRATE,
-				  "Register offset (0x%04x) QI COFF "
-				  "(bitfields 0x%08x) after update = 0x%x\n",
-				  offset_array[i],
-				  AR_PHY_RX_IQCAL_CORR_IQCORR_Q_I_COFF,
-				  REG_READ(ah, offset_array[i]));
-			ath_print(common, ATH_DBG_CALIBRATE,
-				  "Register offset (0x%04x) QQ COFF "
-				  "(bitfields 0x%08x) after update = 0x%x\n",
-				  offset_array[i],
-				  AR_PHY_RX_IQCAL_CORR_IQCORR_Q_Q_COFF,
-				  REG_READ(ah, offset_array[i]));
+			ath_dbg(common, ATH_DBG_CALIBRATE,
+				"Register offset (0x%04x) QI COFF (bitfields 0x%08x) after update = 0x%x\n",
+				offset_array[i],
+				AR_PHY_RX_IQCAL_CORR_IQCORR_Q_I_COFF,
+				REG_READ(ah, offset_array[i]));
+			ath_dbg(common, ATH_DBG_CALIBRATE,
+				"Register offset (0x%04x) QQ COFF (bitfields 0x%08x) after update = 0x%x\n",
+				offset_array[i],
+				AR_PHY_RX_IQCAL_CORR_IQCORR_Q_Q_COFF,
+				REG_READ(ah, offset_array[i]));
 
-			ath_print(common, ATH_DBG_CALIBRATE,
-				  "IQ Cal and Correction done for Chain %d\n",
-				  i);
+			ath_dbg(common, ATH_DBG_CALIBRATE,
+				"IQ Cal and Correction done for Chain %d\n", i);
 		}
 	}
 
 	REG_SET_BIT(ah, AR_PHY_RX_IQCAL_CORR_B0,
 		    AR_PHY_RX_IQCAL_CORR_IQCORR_ENABLE);
-	ath_print(common, ATH_DBG_CALIBRATE,
-		  "IQ Cal and Correction (offset 0x%04x) enabled "
-		  "(bit position 0x%08x). New Value 0x%08x\n",
-		  (unsigned) (AR_PHY_RX_IQCAL_CORR_B0),
-		  AR_PHY_RX_IQCAL_CORR_IQCORR_ENABLE,
-		  REG_READ(ah, AR_PHY_RX_IQCAL_CORR_B0));
+	ath_dbg(common, ATH_DBG_CALIBRATE,
+		"IQ Cal and Correction (offset 0x%04x) enabled (bit position 0x%08x). New Value 0x%08x\n",
+		(unsigned) (AR_PHY_RX_IQCAL_CORR_B0),
+		AR_PHY_RX_IQCAL_CORR_IQCORR_ENABLE,
+		REG_READ(ah, AR_PHY_RX_IQCAL_CORR_B0));
 }
 
 static const struct ath9k_percal_data iq_cal_single_sample = {
@@ -340,7 +345,7 @@ static bool ar9003_hw_solve_iq_cal(struc
 	f2 = (f1 * f1 + f3 * f3) / result_shift;
 
 	if (!f2) {
-		ath_print(common, ATH_DBG_CALIBRATE, "Divide by 0\n");
+		ath_dbg(common, ATH_DBG_CALIBRATE, "Divide by 0\n");
 		return false;
 	}
 
@@ -461,11 +466,14 @@ static bool ar9003_hw_calc_iq_corr(struc
 
 	if ((i2_p_q2_a0_d0 == 0) || (i2_p_q2_a0_d1 == 0) ||
 	    (i2_p_q2_a1_d0 == 0) || (i2_p_q2_a1_d1 == 0)) {
-		ath_print(common, ATH_DBG_CALIBRATE,
-			  "Divide by 0:\na0_d0=%d\n"
-			  "a0_d1=%d\na2_d0=%d\na1_d1=%d\n",
-			  i2_p_q2_a0_d0, i2_p_q2_a0_d1,
-			  i2_p_q2_a1_d0, i2_p_q2_a1_d1);
+		ath_dbg(common, ATH_DBG_CALIBRATE,
+			"Divide by 0:\n"
+			"a0_d0=%d\n"
+			"a0_d1=%d\n"
+			"a2_d0=%d\n"
+			"a1_d1=%d\n",
+			i2_p_q2_a0_d0, i2_p_q2_a0_d1,
+			i2_p_q2_a1_d0, i2_p_q2_a1_d1);
 		return false;
 	}
 
@@ -498,9 +506,9 @@ static bool ar9003_hw_calc_iq_corr(struc
 	mag2 = ar9003_hw_find_mag_approx(ah, cos_2phi_2, sin_2phi_2);
 
 	if ((mag1 == 0) || (mag2 == 0)) {
-		ath_print(common, ATH_DBG_CALIBRATE,
-			  "Divide by 0: mag1=%d, mag2=%d\n",
-			  mag1, mag2);
+		ath_dbg(common, ATH_DBG_CALIBRATE,
+			"Divide by 0: mag1=%d, mag2=%d\n",
+			mag1, mag2);
 		return false;
 	}
 
@@ -517,8 +525,8 @@ static bool ar9003_hw_calc_iq_corr(struc
 			     mag_a0_d0, phs_a0_d0,
 			     mag_a1_d0,
 			     phs_a1_d0, solved_eq)) {
-		ath_print(common, ATH_DBG_CALIBRATE,
-			  "Call to ar9003_hw_solve_iq_cal() failed.\n");
+		ath_dbg(common, ATH_DBG_CALIBRATE,
+			"Call to ar9003_hw_solve_iq_cal() failed.\n");
 		return false;
 	}
 
@@ -527,14 +535,14 @@ static bool ar9003_hw_calc_iq_corr(struc
 	mag_rx = solved_eq[2];
 	phs_rx = solved_eq[3];
 
-	ath_print(common, ATH_DBG_CALIBRATE,
-		  "chain %d: mag mismatch=%d phase mismatch=%d\n",
-		  chain_idx, mag_tx/res_scale, phs_tx/res_scale);
+	ath_dbg(common, ATH_DBG_CALIBRATE,
+		"chain %d: mag mismatch=%d phase mismatch=%d\n",
+		chain_idx, mag_tx/res_scale, phs_tx/res_scale);
 
 	if (res_scale == mag_tx) {
-		ath_print(common, ATH_DBG_CALIBRATE,
-			  "Divide by 0: mag_tx=%d, res_scale=%d\n",
-			  mag_tx, res_scale);
+		ath_dbg(common, ATH_DBG_CALIBRATE,
+			"Divide by 0: mag_tx=%d, res_scale=%d\n",
+			mag_tx, res_scale);
 		return false;
 	}
 
@@ -545,9 +553,9 @@ static bool ar9003_hw_calc_iq_corr(struc
 	q_q_coff = (mag_corr_tx * 128 / res_scale);
 	q_i_coff = (phs_corr_tx * 256 / res_scale);
 
-	ath_print(common, ATH_DBG_CALIBRATE,
-		  "tx chain %d: mag corr=%d  phase corr=%d\n",
-		  chain_idx, q_q_coff, q_i_coff);
+	ath_dbg(common, ATH_DBG_CALIBRATE,
+		"tx chain %d: mag corr=%d  phase corr=%d\n",
+		chain_idx, q_q_coff, q_i_coff);
 
 	if (q_i_coff < -63)
 		q_i_coff = -63;
@@ -560,14 +568,14 @@ static bool ar9003_hw_calc_iq_corr(struc
 
 	iqc_coeff[0] = (q_q_coff * 128) + q_i_coff;
 
-	ath_print(common, ATH_DBG_CALIBRATE,
-		  "tx chain %d: iq corr coeff=%x\n",
-		  chain_idx, iqc_coeff[0]);
+	ath_dbg(common, ATH_DBG_CALIBRATE,
+		"tx chain %d: iq corr coeff=%x\n",
+		chain_idx, iqc_coeff[0]);
 
 	if (-mag_rx == res_scale) {
-		ath_print(common, ATH_DBG_CALIBRATE,
-			  "Divide by 0: mag_rx=%d, res_scale=%d\n",
-			  mag_rx, res_scale);
+		ath_dbg(common, ATH_DBG_CALIBRATE,
+			"Divide by 0: mag_rx=%d, res_scale=%d\n",
+			mag_rx, res_scale);
 		return false;
 	}
 
@@ -578,9 +586,9 @@ static bool ar9003_hw_calc_iq_corr(struc
 	q_q_coff = (mag_corr_rx * 128 / res_scale);
 	q_i_coff = (phs_corr_rx * 256 / res_scale);
 
-	ath_print(common, ATH_DBG_CALIBRATE,
-		  "rx chain %d: mag corr=%d  phase corr=%d\n",
-		  chain_idx, q_q_coff, q_i_coff);
+	ath_dbg(common, ATH_DBG_CALIBRATE,
+		"rx chain %d: mag corr=%d  phase corr=%d\n",
+		chain_idx, q_q_coff, q_i_coff);
 
 	if (q_i_coff < -63)
 		q_i_coff = -63;
@@ -593,140 +601,367 @@ static bool ar9003_hw_calc_iq_corr(struc
 
 	iqc_coeff[1] = (q_q_coff * 128) + q_i_coff;
 
-	ath_print(common, ATH_DBG_CALIBRATE,
-		  "rx chain %d: iq corr coeff=%x\n",
-		  chain_idx, iqc_coeff[1]);
+	ath_dbg(common, ATH_DBG_CALIBRATE,
+		"rx chain %d: iq corr coeff=%x\n",
+		chain_idx, iqc_coeff[1]);
+
+	return true;
+}
+
+static bool ar9003_hw_compute_closest_pass_and_avg(int *mp_coeff, int *mp_avg)
+{
+	int diff[MPASS];
+
+	diff[0] = abs(mp_coeff[0] - mp_coeff[1]);
+	diff[1] = abs(mp_coeff[1] - mp_coeff[2]);
+	diff[2] = abs(mp_coeff[2] - mp_coeff[0]);
+
+	if (diff[0] > MAX_DIFFERENCE &&
+	    diff[1] > MAX_DIFFERENCE &&
+	    diff[2] > MAX_DIFFERENCE)
+		return false;
+
+	if (diff[0] <= diff[1] && diff[0] <= diff[2])
+		*mp_avg = (mp_coeff[0] + mp_coeff[1]) / 2;
+	else if (diff[1] <= diff[2])
+		*mp_avg = (mp_coeff[1] + mp_coeff[2]) / 2;
+	else
+		*mp_avg = (mp_coeff[2] + mp_coeff[0]) / 2;
 
 	return true;
 }
 
+static void ar9003_hw_tx_iqcal_load_avg_2_passes(struct ath_hw *ah,
+						 u8 num_chains,
+						 struct coeff *coeff)
+{
+	struct ath_common *common = ath9k_hw_common(ah);
+	int i, im, nmeasurement;
+	int magnitude, phase;
+	u32 tx_corr_coeff[MAX_MEASUREMENT][AR9300_MAX_CHAINS];
+
+	memset(tx_corr_coeff, 0, sizeof(tx_corr_coeff));
+	for (i = 0; i < MAX_MEASUREMENT / 2; i++) {
+		tx_corr_coeff[i * 2][0] = tx_corr_coeff[(i * 2) + 1][0] =
+					AR_PHY_TX_IQCAL_CORR_COEFF_B0(i);
+		if (!AR_SREV_9485(ah)) {
+			tx_corr_coeff[i * 2][1] =
+			tx_corr_coeff[(i * 2) + 1][1] =
+					AR_PHY_TX_IQCAL_CORR_COEFF_B1(i);
+
+			tx_corr_coeff[i * 2][2] =
+			tx_corr_coeff[(i * 2) + 1][2] =
+					AR_PHY_TX_IQCAL_CORR_COEFF_B2(i);
+		}
+	}
+
+	/* Load the average of 2 passes */
+	for (i = 0; i < num_chains; i++) {
+		if (AR_SREV_9485(ah))
+			nmeasurement = REG_READ_FIELD(ah,
+					AR_PHY_TX_IQCAL_STATUS_B0_9485,
+					AR_PHY_CALIBRATED_GAINS_0);
+		else
+			nmeasurement = REG_READ_FIELD(ah,
+					AR_PHY_TX_IQCAL_STATUS_B0,
+					AR_PHY_CALIBRATED_GAINS_0);
+
+		if (nmeasurement > MAX_MEASUREMENT)
+			nmeasurement = MAX_MEASUREMENT;
+
+		for (im = 0; im < nmeasurement; im++) {
+			/*
+			 * Determine which 2 passes are closest and compute avg
+			 * magnitude
+			 */
+			if (!ar9003_hw_compute_closest_pass_and_avg(coeff->mag_coeff[i][im],
+								    &magnitude))
+				goto disable_txiqcal;
+
+			/*
+			 * Determine which 2 passes are closest and compute avg
+			 * phase
+			 */
+			if (!ar9003_hw_compute_closest_pass_and_avg(coeff->phs_coeff[i][im],
+								    &phase))
+				goto disable_txiqcal;
+
+			coeff->iqc_coeff[0] = (magnitude & 0x7f) |
+					      ((phase & 0x7f) << 7);
+
+			if ((im % 2) == 0)
+				REG_RMW_FIELD(ah, tx_corr_coeff[im][i],
+					AR_PHY_TX_IQCAL_CORR_COEFF_00_COEFF_TABLE,
+					coeff->iqc_coeff[0]);
+			else
+				REG_RMW_FIELD(ah, tx_corr_coeff[im][i],
+					AR_PHY_TX_IQCAL_CORR_COEFF_01_COEFF_TABLE,
+					coeff->iqc_coeff[0]);
+		}
+	}
+
+	REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_3,
+		      AR_PHY_TX_IQCAL_CONTROL_3_IQCORR_EN, 0x1);
+	REG_RMW_FIELD(ah, AR_PHY_RX_IQCAL_CORR_B0,
+		      AR_PHY_RX_IQCAL_CORR_B0_LOOPBACK_IQCORR_EN, 0x1);
+
+	return;
+
+disable_txiqcal:
+	REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_3,
+		      AR_PHY_TX_IQCAL_CONTROL_3_IQCORR_EN, 0x0);
+	REG_RMW_FIELD(ah, AR_PHY_RX_IQCAL_CORR_B0,
+		      AR_PHY_RX_IQCAL_CORR_B0_LOOPBACK_IQCORR_EN, 0x0);
+
+	ath_dbg(common, ATH_DBG_CALIBRATE, "TX IQ Cal disabled\n");
+}
+
 static void ar9003_hw_tx_iq_cal(struct ath_hw *ah)
 {
 	struct ath_common *common = ath9k_hw_common(ah);
-	const u32 txiqcal_status[AR9300_MAX_CHAINS] = {
+	static const u32 txiqcal_status[AR9300_MAX_CHAINS] = {
 		AR_PHY_TX_IQCAL_STATUS_B0,
 		AR_PHY_TX_IQCAL_STATUS_B1,
 		AR_PHY_TX_IQCAL_STATUS_B2,
 	};
-	const u32 tx_corr_coeff[AR9300_MAX_CHAINS] = {
-		AR_PHY_TX_IQCAL_CORR_COEFF_01_B0,
-		AR_PHY_TX_IQCAL_CORR_COEFF_01_B1,
-		AR_PHY_TX_IQCAL_CORR_COEFF_01_B2,
+	static const u32 chan_info_tab[] = {
+		AR_PHY_CHAN_INFO_TAB_0,
+		AR_PHY_CHAN_INFO_TAB_1,
+		AR_PHY_CHAN_INFO_TAB_2,
 	};
-	const u32 rx_corr[AR9300_MAX_CHAINS] = {
-		AR_PHY_RX_IQCAL_CORR_B0,
-		AR_PHY_RX_IQCAL_CORR_B1,
-		AR_PHY_RX_IQCAL_CORR_B2,
+	struct coeff coeff;
+	s32 iq_res[6];
+	s32 i, j, ip, im, nmeasurement;
+	u8 nchains = get_streams(common->tx_chainmask);
+
+	for (ip = 0; ip < MPASS; ip++) {
+		REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_1,
+			      AR_PHY_TX_IQCAQL_CONTROL_1_IQCORR_I_Q_COFF_DELPT,
+			      DELPT);
+		REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_START,
+			      AR_PHY_TX_IQCAL_START_DO_CAL,
+			      AR_PHY_TX_IQCAL_START_DO_CAL);
+
+		if (!ath9k_hw_wait(ah, AR_PHY_TX_IQCAL_START,
+				   AR_PHY_TX_IQCAL_START_DO_CAL,
+				   0, AH_WAIT_TIMEOUT)) {
+			ath_dbg(common, ATH_DBG_CALIBRATE,
+				"Tx IQ Cal not complete.\n");
+			goto TX_IQ_CAL_FAILED;
+		}
+
+		nmeasurement = REG_READ_FIELD(ah, AR_PHY_TX_IQCAL_STATUS_B0,
+					      AR_PHY_CALIBRATED_GAINS_0);
+			if (nmeasurement > MAX_MEASUREMENT)
+				nmeasurement = MAX_MEASUREMENT;
+
+		for (i = 0; i < nchains; i++) {
+			ath_dbg(common, ATH_DBG_CALIBRATE,
+				"Doing Tx IQ Cal for chain %d.\n", i);
+			for (im = 0; im < nmeasurement; im++) {
+				if (REG_READ(ah, txiqcal_status[i]) &
+					     AR_PHY_TX_IQCAL_STATUS_FAILED) {
+					ath_dbg(common, ATH_DBG_CALIBRATE,
+						"Tx IQ Cal failed for chain %d.\n", i);
+					goto TX_IQ_CAL_FAILED;
+				}
+
+				for (j = 0; j < 3; j++) {
+					u8 idx = 2 * j,
+					   offset = 4 * (3 * im + j);
+
+					REG_RMW_FIELD(ah, AR_PHY_CHAN_INFO_MEMORY,
+						      AR_PHY_CHAN_INFO_TAB_S2_READ,
+						      0);
+
+					/* 32 bits */
+					iq_res[idx] = REG_READ(ah,
+							chan_info_tab[i] +
+							offset);
+
+					REG_RMW_FIELD(ah, AR_PHY_CHAN_INFO_MEMORY,
+						      AR_PHY_CHAN_INFO_TAB_S2_READ,
+						      1);
+
+					/* 16 bits */
+					iq_res[idx+1] = 0xffff & REG_READ(ah,
+								chan_info_tab[i] +
+								offset);
+
+					ath_dbg(common, ATH_DBG_CALIBRATE,
+						"IQ RES[%d]=0x%x IQ_RES[%d]=0x%x\n",
+						idx, iq_res[idx], idx+1, iq_res[idx+1]);
+				}
+
+				if (!ar9003_hw_calc_iq_corr(ah, i, iq_res,
+							    coeff.iqc_coeff)) {
+					ath_dbg(common, ATH_DBG_CALIBRATE,
+						"Failed in calculation of IQ correction.\n");
+					goto TX_IQ_CAL_FAILED;
+				}
+				coeff.mag_coeff[i][im][ip] =
+						coeff.iqc_coeff[0] & 0x7f;
+				coeff.phs_coeff[i][im][ip] =
+						(coeff.iqc_coeff[0] >> 7) & 0x7f;
+
+				if (coeff.mag_coeff[i][im][ip] > 63)
+					coeff.mag_coeff[i][im][ip] -= 128;
+				if (coeff.phs_coeff[i][im][ip] > 63)
+					coeff.phs_coeff[i][im][ip] -= 128;
+
+			}
+		}
+	}
+
+	ar9003_hw_tx_iqcal_load_avg_2_passes(ah, nchains, &coeff);
+
+	return;
+
+TX_IQ_CAL_FAILED:
+	ath_dbg(common, ATH_DBG_CALIBRATE, "Tx IQ Cal failed\n");
+}
+
+static void ar9003_hw_tx_iq_cal_run(struct ath_hw *ah)
+{
+	u8 tx_gain_forced;
+
+	REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_1_9485,
+		      AR_PHY_TX_IQCAQL_CONTROL_1_IQCORR_I_Q_COFF_DELPT, DELPT);
+	tx_gain_forced = REG_READ_FIELD(ah, AR_PHY_TX_FORCED_GAIN,
+					AR_PHY_TXGAIN_FORCE);
+	if (tx_gain_forced)
+		REG_RMW_FIELD(ah, AR_PHY_TX_FORCED_GAIN,
+			      AR_PHY_TXGAIN_FORCE, 0);
+
+	REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_START_9485,
+		      AR_PHY_TX_IQCAL_START_DO_CAL_9485, 1);
+}
+
+static void ar9003_hw_tx_iq_cal_post_proc(struct ath_hw *ah)
+{
+	struct ath_common *common = ath9k_hw_common(ah);
+	const u32 txiqcal_status[AR9300_MAX_CHAINS] = {
+		AR_PHY_TX_IQCAL_STATUS_B0_9485,
+		AR_PHY_TX_IQCAL_STATUS_B1,
+		AR_PHY_TX_IQCAL_STATUS_B2,
 	};
 	const u_int32_t chan_info_tab[] = {
 		AR_PHY_CHAN_INFO_TAB_0,
 		AR_PHY_CHAN_INFO_TAB_1,
 		AR_PHY_CHAN_INFO_TAB_2,
 	};
+	struct coeff coeff;
 	s32 iq_res[6];
-	s32 iqc_coeff[2];
-	s32 i, j;
-	u32 num_chains = 0;
+	u8 num_chains = 0;
+	int i, ip, im, j;
+	int nmeasurement;
 
 	for (i = 0; i < AR9300_MAX_CHAINS; i++) {
 		if (ah->txchainmask & (1 << i))
 			num_chains++;
 	}
 
-	REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_1,
-		      AR_PHY_TX_IQCAQL_CONTROL_1_IQCORR_I_Q_COFF_DELPT,
-		      DELPT);
-	REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_START,
-		      AR_PHY_TX_IQCAL_START_DO_CAL,
-		      AR_PHY_TX_IQCAL_START_DO_CAL);
-
-	if (!ath9k_hw_wait(ah, AR_PHY_TX_IQCAL_START,
-			   AR_PHY_TX_IQCAL_START_DO_CAL,
-			   0, AH_WAIT_TIMEOUT)) {
-		ath_print(common, ATH_DBG_CALIBRATE,
-			  "Tx IQ Cal not complete.\n");
-		goto TX_IQ_CAL_FAILED;
-	}
+	for (ip = 0; ip < MPASS; ip++) {
+		for (i = 0; i < num_chains; i++) {
+			nmeasurement = REG_READ_FIELD(ah,
+					AR_PHY_TX_IQCAL_STATUS_B0_9485,
+					AR_PHY_CALIBRATED_GAINS_0);
+			if (nmeasurement > MAX_MEASUREMENT)
+				nmeasurement = MAX_MEASUREMENT;
 
-	for (i = 0; i < num_chains; i++) {
-		ath_print(common, ATH_DBG_CALIBRATE,
-			  "Doing Tx IQ Cal for chain %d.\n", i);
+			for (im = 0; im < nmeasurement; im++) {
+				ath_dbg(common, ATH_DBG_CALIBRATE,
+					"Doing Tx IQ Cal for chain %d.\n", i);
 
-		if (REG_READ(ah, txiqcal_status[i]) &
-			     AR_PHY_TX_IQCAL_STATUS_FAILED) {
-			ath_print(common, ATH_DBG_CALIBRATE,
-				  "Tx IQ Cal failed for chain %d.\n", i);
-			goto TX_IQ_CAL_FAILED;
-		}
+				if (REG_READ(ah, txiqcal_status[i]) &
+				    AR_PHY_TX_IQCAL_STATUS_FAILED) {
+					ath_dbg(common, ATH_DBG_CALIBRATE,
+					"Tx IQ Cal failed for chain %d.\n", i);
+					goto tx_iqcal_fail;
+				}
 
-		for (j = 0; j < 3; j++) {
-			u_int8_t idx = 2 * j,
-			offset = 4 * j;
+				for (j = 0; j < 3; j++) {
+					u32 idx = 2 * j, offset = 4 * (3 * im + j);
 
-			REG_RMW_FIELD(ah, AR_PHY_CHAN_INFO_MEMORY,
-				      AR_PHY_CHAN_INFO_TAB_S2_READ, 0);
+					REG_RMW_FIELD(ah,
+						AR_PHY_CHAN_INFO_MEMORY,
+						AR_PHY_CHAN_INFO_TAB_S2_READ,
+						0);
 
-			/* 32 bits */
-			iq_res[idx] = REG_READ(ah, chan_info_tab[i] + offset);
+					/* 32 bits */
+					iq_res[idx] = REG_READ(ah,
+							chan_info_tab[i] +
+							offset);
 
-			REG_RMW_FIELD(ah, AR_PHY_CHAN_INFO_MEMORY,
-				      AR_PHY_CHAN_INFO_TAB_S2_READ, 1);
+					REG_RMW_FIELD(ah,
+						AR_PHY_CHAN_INFO_MEMORY,
+						AR_PHY_CHAN_INFO_TAB_S2_READ,
+						1);
 
-			/* 16 bits */
-			iq_res[idx+1] = 0xffff & REG_READ(ah,
-							  chan_info_tab[i] +
-							  offset);
+					/* 16 bits */
+					iq_res[idx + 1] = 0xffff & REG_READ(ah,
+							  chan_info_tab[i] + offset);
 
-			ath_print(common, ATH_DBG_CALIBRATE,
-				  "IQ RES[%d]=0x%x IQ_RES[%d]=0x%x\n",
-				  idx, iq_res[idx], idx+1, iq_res[idx+1]);
-		}
+					ath_dbg(common, ATH_DBG_CALIBRATE,
+						"IQ RES[%d]=0x%x"
+						"IQ_RES[%d]=0x%x\n",
+						idx, iq_res[idx], idx + 1,
+						iq_res[idx + 1]);
+				}
 
-		if (!ar9003_hw_calc_iq_corr(ah, i, iq_res, iqc_coeff)) {
-			ath_print(common, ATH_DBG_CALIBRATE,
-				  "Failed in calculation of IQ correction.\n");
-			goto TX_IQ_CAL_FAILED;
-		}
+				if (!ar9003_hw_calc_iq_corr(ah, i, iq_res,
+							    coeff.iqc_coeff)) {
+					ath_dbg(common, ATH_DBG_CALIBRATE,
+					 "Failed in calculation of IQ correction.\n");
+					goto tx_iqcal_fail;
+				}
 
-		ath_print(common, ATH_DBG_CALIBRATE,
-			  "IQ_COEFF[0] = 0x%x IQ_COEFF[1] = 0x%x\n",
-			  iqc_coeff[0], iqc_coeff[1]);
+				coeff.mag_coeff[i][im][ip] =
+						coeff.iqc_coeff[0] & 0x7f;
+				coeff.phs_coeff[i][im][ip] =
+						(coeff.iqc_coeff[0] >> 7) & 0x7f;
 
-		REG_RMW_FIELD(ah, tx_corr_coeff[i],
-			      AR_PHY_TX_IQCAL_CORR_COEFF_01_COEFF_TABLE,
-			      iqc_coeff[0]);
-		REG_RMW_FIELD(ah, rx_corr[i],
-			      AR_PHY_RX_IQCAL_CORR_LOOPBACK_IQCORR_Q_Q_COFF,
-			      iqc_coeff[1] >> 7);
-		REG_RMW_FIELD(ah, rx_corr[i],
-			      AR_PHY_RX_IQCAL_CORR_LOOPBACK_IQCORR_Q_I_COFF,
-			      iqc_coeff[1]);
+				if (coeff.mag_coeff[i][im][ip] > 63)
+					coeff.mag_coeff[i][im][ip] -= 128;
+				if (coeff.phs_coeff[i][im][ip] > 63)
+					coeff.phs_coeff[i][im][ip] -= 128;
+			}
+		}
 	}
-
-	REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_3,
-		      AR_PHY_TX_IQCAL_CONTROL_3_IQCORR_EN, 0x1);
-	REG_RMW_FIELD(ah, AR_PHY_RX_IQCAL_CORR_B0,
-		      AR_PHY_RX_IQCAL_CORR_B0_LOOPBACK_IQCORR_EN, 0x1);
+	ar9003_hw_tx_iqcal_load_avg_2_passes(ah, num_chains, &coeff);
 
 	return;
 
-TX_IQ_CAL_FAILED:
-	ath_print(common, ATH_DBG_CALIBRATE, "Tx IQ Cal failed\n");
+tx_iqcal_fail:
+	ath_dbg(common, ATH_DBG_CALIBRATE, "Tx IQ Cal failed\n");
+	return;
 }
-
 static bool ar9003_hw_init_cal(struct ath_hw *ah,
 			       struct ath9k_channel *chan)
 {
 	struct ath_common *common = ath9k_hw_common(ah);
+	int val;
 
-	/*
-	 * 0x7 = 0b111 , AR9003 needs to be configured for 3-chain mode before
-	 * running AGC/TxIQ cals
-	 */
-	ar9003_hw_set_chain_masks(ah, 0x7, 0x7);
+	val = REG_READ(ah, AR_ENT_OTP);
+	ath_dbg(common, ATH_DBG_CALIBRATE, "ath9k: AR_ENT_OTP 0x%x\n", val);
+
+	if (AR_SREV_9485(ah))
+		ar9003_hw_set_chain_masks(ah, 0x1, 0x1);
+	else if (val & AR_ENT_OTP_CHAIN2_DISABLE)
+		ar9003_hw_set_chain_masks(ah, 0x3, 0x3);
+	else
+		/*
+		 * 0x7 = 0b111 , AR9003 needs to be configured for 3-chain
+		 * mode before running AGC/TxIQ cals
+		 */
+		ar9003_hw_set_chain_masks(ah, 0x7, 0x7);
 
 	/* Do Tx IQ Calibration */
-	ar9003_hw_tx_iq_cal(ah);
+	if (AR_SREV_9485(ah))
+		ar9003_hw_tx_iq_cal_run(ah);
+	else
+		ar9003_hw_tx_iq_cal(ah);
+
 	REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS);
 	udelay(5);
 	REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN);
@@ -739,12 +974,14 @@ static bool ar9003_hw_init_cal(struct at
 	/* Poll for offset calibration complete */
 	if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL,
 			   0, AH_WAIT_TIMEOUT)) {
-		ath_print(common, ATH_DBG_CALIBRATE,
-			  "offset calibration failed to "
-			  "complete in 1ms; noisy environment?\n");
+		ath_dbg(common, ATH_DBG_CALIBRATE,
+			"offset calibration failed to complete in 1ms; noisy environment?\n");
 		return false;
 	}
 
+	if (AR_SREV_9485(ah))
+		ar9003_hw_tx_iq_cal_post_proc(ah);
+
 	/* Revert chainmasks to their original values before NF cal */
 	ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask);
 
@@ -757,15 +994,15 @@ static bool ar9003_hw_init_cal(struct at
 	if (ah->supp_cals & IQ_MISMATCH_CAL) {
 		INIT_CAL(&ah->iq_caldata);
 		INSERT_CAL(ah, &ah->iq_caldata);
-		ath_print(common, ATH_DBG_CALIBRATE,
-			  "enabling IQ Calibration.\n");
+		ath_dbg(common, ATH_DBG_CALIBRATE,
+			"enabling IQ Calibration.\n");
 	}
 
 	if (ah->supp_cals & TEMP_COMP_CAL) {
 		INIT_CAL(&ah->tempCompCalData);
 		INSERT_CAL(ah, &ah->tempCompCalData);
-		ath_print(common, ATH_DBG_CALIBRATE,
-			  "enabling Temperature Compensation Calibration.\n");
+		ath_dbg(common, ATH_DBG_CALIBRATE,
+			"enabling Temperature Compensation Calibration.\n");
 	}
 
 	/* Initialize current pointer to first element in list */
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c	2011-03-14 21:20:32.000000000 -0400
@@ -22,12 +22,14 @@
 #define COMP_CKSUM_LEN 2
 
 #define AR_CH0_TOP (0x00016288)
-#define AR_CH0_TOP_XPABIASLVL (0x3)
+#define AR_CH0_TOP_XPABIASLVL (0x300)
 #define AR_CH0_TOP_XPABIASLVL_S (8)
 
 #define AR_CH0_THERM (0x00016290)
-#define AR_CH0_THERM_SPARE (0x3f)
-#define AR_CH0_THERM_SPARE_S (0)
+#define AR_CH0_THERM_XPABIASLVL_MSB 0x3
+#define AR_CH0_THERM_XPABIASLVL_MSB_S 0
+#define AR_CH0_THERM_XPASHORT2GND 0x4
+#define AR_CH0_THERM_XPASHORT2GND_S 2
 
 #define AR_SWITCH_TABLE_COM_ALL (0xffff)
 #define AR_SWITCH_TABLE_COM_ALL_S (0)
@@ -57,6 +59,12 @@
 
 #define CTL(_tpower, _flag) ((_tpower) | ((_flag) << 6))
 
+#define EEPROM_DATA_LEN_9485	1088
+
+static int ar9003_hw_power_interpolate(int32_t x,
+				       int32_t *px, int32_t *py, u_int16_t np);
+
+
 static const struct ar9300_eeprom ar9300_default = {
 	.eepromVersion = 2,
 	.templateVersion = 2,
@@ -67,7 +75,7 @@ static const struct ar9300_eeprom ar9300
 		.regDmn = { LE16(0), LE16(0x1f) },
 		.txrxMask =  0x77, /* 4 bits tx and 4 bits rx */
 		.opCapFlags = {
-			.opFlags = AR9300_OPFLAGS_11G | AR9300_OPFLAGS_11A,
+			.opFlags = AR5416_OPFLAGS_11G | AR5416_OPFLAGS_11A,
 			.eepMisc = 0,
 		},
 		.rfSilent = 0,
@@ -146,13 +154,16 @@ static const struct ar9300_eeprom ar9300
 		.txEndToRxOn = 0x2,
 		.txFrameToXpaOn = 0xe,
 		.thresh62 = 28,
-		.papdRateMaskHt20 = LE32(0x80c080),
-		.papdRateMaskHt40 = LE32(0x80c080),
+		.papdRateMaskHt20 = LE32(0x0cf0e0e0),
+		.papdRateMaskHt40 = LE32(0x6cf0e0e0),
 		.futureModal = {
-			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,
 		},
 	 },
+	.base_ext1 = {
+		.ant_div_control = 0,
+		.future = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
+	},
 	.calFreqPier2G = {
 		FREQ2FBIN(2412, 1),
 		FREQ2FBIN(2437, 1),
@@ -287,8 +298,7 @@ static const struct ar9300_eeprom ar9300
 			/* Data[11].ctlEdges[0].bChannel */ FREQ2FBIN(2422, 1),
 			/* Data[11].ctlEdges[1].bChannel */ FREQ2FBIN(2427, 1),
 			/* Data[11].ctlEdges[2].bChannel */ FREQ2FBIN(2447, 1),
-			/* Data[11].ctlEdges[3].bChannel */
-			FREQ2FBIN(2462, 1),
+			/* Data[11].ctlEdges[3].bChannel */ FREQ2FBIN(2462, 1),
 		}
 	 },
 	.ctlPowerData_2G = {
@@ -346,13 +356,20 @@ static const struct ar9300_eeprom ar9300
 		.txEndToRxOn = 0x2,
 		.txFrameToXpaOn = 0xe,
 		.thresh62 = 28,
-		.papdRateMaskHt20 = LE32(0xf0e0e0),
-		.papdRateMaskHt40 = LE32(0xf0e0e0),
+		.papdRateMaskHt20 = LE32(0x0c80c080),
+		.papdRateMaskHt40 = LE32(0x0080c080),
 		.futureModal = {
-			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,
 		},
 	 },
+	.base_ext2 = {
+		.tempSlopeLow = 0,
+		.tempSlopeHigh = 0,
+		.xatten1DBLow = {0, 0, 0},
+		.xatten1MarginLow = {0, 0, 0},
+		.xatten1DBHigh = {0, 0, 0},
+		.xatten1MarginHigh = {0, 0, 0}
+	},
 	.calFreqPier5G = {
 		FREQ2FBIN(5180, 0),
 		FREQ2FBIN(5220, 0),
@@ -626,9 +643,2341 @@ static const struct ar9300_eeprom ar9300
 	 }
 };
 
+static const struct ar9300_eeprom ar9300_x113 = {
+	.eepromVersion = 2,
+	.templateVersion = 6,
+	.macAddr = {0x00, 0x03, 0x7f, 0x0, 0x0, 0x0},
+	.custData = {"x113-023-f0000"},
+	.baseEepHeader = {
+		.regDmn = { LE16(0), LE16(0x1f) },
+		.txrxMask =  0x77, /* 4 bits tx and 4 bits rx */
+		.opCapFlags = {
+			.opFlags = AR5416_OPFLAGS_11G | AR5416_OPFLAGS_11A,
+			.eepMisc = 0,
+		},
+		.rfSilent = 0,
+		.blueToothOptions = 0,
+		.deviceCap = 0,
+		.deviceType = 5, /* takes lower byte in eeprom location */
+		.pwrTableOffset = AR9300_PWR_TABLE_OFFSET,
+		.params_for_tuning_caps = {0, 0},
+		.featureEnable = 0x0d,
+		 /*
+		  * bit0 - enable tx temp comp - disabled
+		  * bit1 - enable tx volt comp - disabled
+		  * bit2 - enable fastClock - enabled
+		  * bit3 - enable doubling - enabled
+		  * bit4 - enable internal regulator - disabled
+		  * bit5 - enable pa predistortion - disabled
+		  */
+		.miscConfiguration = 0, /* bit0 - turn down drivestrength */
+		.eepromWriteEnableGpio = 6,
+		.wlanDisableGpio = 0,
+		.wlanLedGpio = 8,
+		.rxBandSelectGpio = 0xff,
+		.txrxgain = 0x21,
+		.swreg = 0,
+	 },
+	.modalHeader2G = {
+	/* ar9300_modal_eep_header  2g */
+		/* 4 idle,t1,t2,b(4 bits per setting) */
+		.antCtrlCommon = LE32(0x110),
+		/* 4 ra1l1, ra2l1, ra1l2, ra2l2, ra12 */
+		.antCtrlCommon2 = LE32(0x44444),
+
+		/*
+		 * antCtrlChain[AR9300_MAX_CHAINS]; 6 idle, t, r,
+		 * rx1, rx12, b (2 bits each)
+		 */
+		.antCtrlChain = { LE16(0x150), LE16(0x150), LE16(0x150) },
+
+		/*
+		 * xatten1DB[AR9300_MAX_CHAINS];  3 xatten1_db
+		 * for ar9280 (0xa20c/b20c 5:0)
+		 */
+		.xatten1DB = {0, 0, 0},
+
+		/*
+		 * xatten1Margin[AR9300_MAX_CHAINS]; 3 xatten1_margin
+		 * for ar9280 (0xa20c/b20c 16:12
+		 */
+		.xatten1Margin = {0, 0, 0},
+		.tempSlope = 25,
+		.voltSlope = 0,
+
+		/*
+		 * spurChans[OSPREY_EEPROM_MODAL_SPURS]; spur
+		 * channels in usual fbin coding format
+		 */
+		.spurChans = {FREQ2FBIN(2464, 1), 0, 0, 0, 0},
+
+		/*
+		 * noiseFloorThreshCh[AR9300_MAX_CHAINS]; 3 Check
+		 * if the register is per chain
+		 */
+		.noiseFloorThreshCh = {-1, 0, 0},
+		.ob = {1, 1, 1},/* 3 chain */
+		.db_stage2 = {1, 1, 1}, /* 3 chain  */
+		.db_stage3 = {0, 0, 0},
+		.db_stage4 = {0, 0, 0},
+		.xpaBiasLvl = 0,
+		.txFrameToDataStart = 0x0e,
+		.txFrameToPaOn = 0x0e,
+		.txClip = 3, /* 4 bits tx_clip, 4 bits dac_scale_cck */
+		.antennaGain = 0,
+		.switchSettling = 0x2c,
+		.adcDesiredSize = -30,
+		.txEndToXpaOff = 0,
+		.txEndToRxOn = 0x2,
+		.txFrameToXpaOn = 0xe,
+		.thresh62 = 28,
+		.papdRateMaskHt20 = LE32(0x0c80c080),
+		.papdRateMaskHt40 = LE32(0x0080c080),
+		.futureModal = {
+			0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+		},
+	 },
+	 .base_ext1 = {
+		.ant_div_control = 0,
+		.future = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
+	 },
+	.calFreqPier2G = {
+		FREQ2FBIN(2412, 1),
+		FREQ2FBIN(2437, 1),
+		FREQ2FBIN(2472, 1),
+	 },
+	/* ar9300_cal_data_per_freq_op_loop 2g */
+	.calPierData2G = {
+		{ {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} },
+	 },
+	.calTarget_freqbin_Cck = {
+		FREQ2FBIN(2412, 1),
+		FREQ2FBIN(2472, 1),
+	 },
+	.calTarget_freqbin_2G = {
+		FREQ2FBIN(2412, 1),
+		FREQ2FBIN(2437, 1),
+		FREQ2FBIN(2472, 1)
+	 },
+	.calTarget_freqbin_2GHT20 = {
+		FREQ2FBIN(2412, 1),
+		FREQ2FBIN(2437, 1),
+		FREQ2FBIN(2472, 1)
+	 },
+	.calTarget_freqbin_2GHT40 = {
+		FREQ2FBIN(2412, 1),
+		FREQ2FBIN(2437, 1),
+		FREQ2FBIN(2472, 1)
+	 },
+	.calTargetPowerCck = {
+		 /* 1L-5L,5S,11L,11S */
+		 { {34, 34, 34, 34} },
+		 { {34, 34, 34, 34} },
+	},
+	.calTargetPower2G = {
+		 /* 6-24,36,48,54 */
+		 { {34, 34, 32, 32} },
+		 { {34, 34, 32, 32} },
+		 { {34, 34, 32, 32} },
+	},
+	.calTargetPower2GHT20 = {
+		{ {32, 32, 32, 32, 32, 28, 32, 32, 30, 28, 0, 0, 0, 0} },
+		{ {32, 32, 32, 32, 32, 28, 32, 32, 30, 28, 0, 0, 0, 0} },
+		{ {32, 32, 32, 32, 32, 28, 32, 32, 30, 28, 0, 0, 0, 0} },
+	},
+	.calTargetPower2GHT40 = {
+		{ {30, 30, 30, 30, 30, 28, 30, 30, 28, 26, 0, 0, 0, 0} },
+		{ {30, 30, 30, 30, 30, 28, 30, 30, 28, 26, 0, 0, 0, 0} },
+		{ {30, 30, 30, 30, 30, 28, 30, 30, 28, 26, 0, 0, 0, 0} },
+	},
+	.ctlIndex_2G =  {
+		0x11, 0x12, 0x15, 0x17, 0x41, 0x42,
+		0x45, 0x47, 0x31, 0x32, 0x35, 0x37,
+	},
+	.ctl_freqbin_2G = {
+		{
+			FREQ2FBIN(2412, 1),
+			FREQ2FBIN(2417, 1),
+			FREQ2FBIN(2457, 1),
+			FREQ2FBIN(2462, 1)
+		},
+		{
+			FREQ2FBIN(2412, 1),
+			FREQ2FBIN(2417, 1),
+			FREQ2FBIN(2462, 1),
+			0xFF,
+		},
+
+		{
+			FREQ2FBIN(2412, 1),
+			FREQ2FBIN(2417, 1),
+			FREQ2FBIN(2462, 1),
+			0xFF,
+		},
+		{
+			FREQ2FBIN(2422, 1),
+			FREQ2FBIN(2427, 1),
+			FREQ2FBIN(2447, 1),
+			FREQ2FBIN(2452, 1)
+		},
+
+		{
+			/* Data[4].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
+			/* Data[4].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
+			/* Data[4].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
+			/* Data[4].ctlEdges[3].bChannel */ FREQ2FBIN(2484, 1),
+		},
+
+		{
+			/* Data[5].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
+			/* Data[5].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
+			/* Data[5].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
+			0,
+		},
+
+		{
+			/* Data[6].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
+			/* Data[6].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
+			FREQ2FBIN(2472, 1),
+			0,
+		},
+
+		{
+			/* Data[7].ctlEdges[0].bChannel */ FREQ2FBIN(2422, 1),
+			/* Data[7].ctlEdges[1].bChannel */ FREQ2FBIN(2427, 1),
+			/* Data[7].ctlEdges[2].bChannel */ FREQ2FBIN(2447, 1),
+			/* Data[7].ctlEdges[3].bChannel */ FREQ2FBIN(2462, 1),
+		},
+
+		{
+			/* Data[8].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
+			/* Data[8].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
+			/* Data[8].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
+		},
+
+		{
+			/* Data[9].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
+			/* Data[9].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
+			/* Data[9].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
+			0
+		},
+
+		{
+			/* Data[10].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
+			/* Data[10].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
+			/* Data[10].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
+			0
+		},
+
+		{
+			/* Data[11].ctlEdges[0].bChannel */ FREQ2FBIN(2422, 1),
+			/* Data[11].ctlEdges[1].bChannel */ FREQ2FBIN(2427, 1),
+			/* Data[11].ctlEdges[2].bChannel */ FREQ2FBIN(2447, 1),
+			/* Data[11].ctlEdges[3].bChannel */ FREQ2FBIN(2462, 1),
+		}
+	 },
+	.ctlPowerData_2G = {
+		 { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+		 { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+		 { { CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 1) } },
+
+		 { { CTL(60, 1), CTL(60, 0), CTL(0, 0), CTL(0, 0) } },
+		 { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+		 { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+
+		 { { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 0) } },
+		 { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+		 { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+
+		 { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+		 { { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 1) } },
+		 { { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 1) } },
+	 },
+	.modalHeader5G = {
+		/* 4 idle,t1,t2,b (4 bits per setting) */
+		.antCtrlCommon = LE32(0x220),
+		/* 4 ra1l1, ra2l1, ra1l2,ra2l2,ra12 */
+		.antCtrlCommon2 = LE32(0x11111),
+		 /* antCtrlChain 6 idle, t,r,rx1,rx12,b (2 bits each) */
+		.antCtrlChain = {
+			LE16(0x150), LE16(0x150), LE16(0x150),
+		},
+		 /* xatten1DB 3 xatten1_db for AR9280 (0xa20c/b20c 5:0) */
+		.xatten1DB = {0, 0, 0},
+
+		/*
+		 * xatten1Margin[AR9300_MAX_CHAINS]; 3 xatten1_margin
+		 * for merlin (0xa20c/b20c 16:12
+		 */
+		.xatten1Margin = {0, 0, 0},
+		.tempSlope = 68,
+		.voltSlope = 0,
+		/* spurChans spur channels in usual fbin coding format */
+		.spurChans = {FREQ2FBIN(5500, 0), 0, 0, 0, 0},
+		/* noiseFloorThreshCh Check if the register is per chain */
+		.noiseFloorThreshCh = {-1, 0, 0},
+		.ob = {3, 3, 3}, /* 3 chain */
+		.db_stage2 = {3, 3, 3}, /* 3 chain */
+		.db_stage3 = {3, 3, 3}, /* doesn't exist for 2G */
+		.db_stage4 = {3, 3, 3},	 /* don't exist for 2G */
+		.xpaBiasLvl = 0,
+		.txFrameToDataStart = 0x0e,
+		.txFrameToPaOn = 0x0e,
+		.txClip = 3, /* 4 bits tx_clip, 4 bits dac_scale_cck */
+		.antennaGain = 0,
+		.switchSettling = 0x2d,
+		.adcDesiredSize = -30,
+		.txEndToXpaOff = 0,
+		.txEndToRxOn = 0x2,
+		.txFrameToXpaOn = 0xe,
+		.thresh62 = 28,
+		.papdRateMaskHt20 = LE32(0x0cf0e0e0),
+		.papdRateMaskHt40 = LE32(0x6cf0e0e0),
+		.futureModal = {
+			0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+		},
+	 },
+	.base_ext2 = {
+		.tempSlopeLow = 72,
+		.tempSlopeHigh = 105,
+		.xatten1DBLow = {0, 0, 0},
+		.xatten1MarginLow = {0, 0, 0},
+		.xatten1DBHigh = {0, 0, 0},
+		.xatten1MarginHigh = {0, 0, 0}
+	 },
+	.calFreqPier5G = {
+		FREQ2FBIN(5180, 0),
+		FREQ2FBIN(5240, 0),
+		FREQ2FBIN(5320, 0),
+		FREQ2FBIN(5400, 0),
+		FREQ2FBIN(5500, 0),
+		FREQ2FBIN(5600, 0),
+		FREQ2FBIN(5745, 0),
+		FREQ2FBIN(5785, 0)
+	},
+	.calPierData5G = {
+			{
+				{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, 0, 0, 0},
+				{0, 0, 0, 0, 0},
+			},
+
+	},
+	.calTarget_freqbin_5G = {
+		FREQ2FBIN(5180, 0),
+		FREQ2FBIN(5220, 0),
+		FREQ2FBIN(5320, 0),
+		FREQ2FBIN(5400, 0),
+		FREQ2FBIN(5500, 0),
+		FREQ2FBIN(5600, 0),
+		FREQ2FBIN(5745, 0),
+		FREQ2FBIN(5785, 0)
+	},
+	.calTarget_freqbin_5GHT20 = {
+		FREQ2FBIN(5180, 0),
+		FREQ2FBIN(5240, 0),
+		FREQ2FBIN(5320, 0),
+		FREQ2FBIN(5400, 0),
+		FREQ2FBIN(5500, 0),
+		FREQ2FBIN(5700, 0),
+		FREQ2FBIN(5745, 0),
+		FREQ2FBIN(5825, 0)
+	},
+	.calTarget_freqbin_5GHT40 = {
+		FREQ2FBIN(5190, 0),
+		FREQ2FBIN(5230, 0),
+		FREQ2FBIN(5320, 0),
+		FREQ2FBIN(5410, 0),
+		FREQ2FBIN(5510, 0),
+		FREQ2FBIN(5670, 0),
+		FREQ2FBIN(5755, 0),
+		FREQ2FBIN(5825, 0)
+	 },
+	.calTargetPower5G = {
+		/* 6-24,36,48,54 */
+		{ {42, 40, 40, 34} },
+		{ {42, 40, 40, 34} },
+		{ {42, 40, 40, 34} },
+		{ {42, 40, 40, 34} },
+		{ {42, 40, 40, 34} },
+		{ {42, 40, 40, 34} },
+		{ {42, 40, 40, 34} },
+		{ {42, 40, 40, 34} },
+	 },
+	.calTargetPower5GHT20 = {
+		/*
+		 * 0_8_16,1-3_9-11_17-19,
+		 * 4,5,6,7,12,13,14,15,20,21,22,23
+		 */
+		{ {40, 40, 40, 40, 32, 28, 40, 40, 32, 28, 40, 40, 32, 20} },
+		{ {40, 40, 40, 40, 32, 28, 40, 40, 32, 28, 40, 40, 32, 20} },
+		{ {40, 40, 40, 40, 32, 28, 40, 40, 32, 28, 40, 40, 32, 20} },
+		{ {40, 40, 40, 40, 32, 28, 40, 40, 32, 28, 40, 40, 32, 20} },
+		{ {40, 40, 40, 40, 32, 28, 40, 40, 32, 28, 40, 40, 32, 20} },
+		{ {40, 40, 40, 40, 32, 28, 40, 40, 32, 28, 40, 40, 32, 20} },
+		{ {38, 38, 38, 38, 32, 28, 38, 38, 32, 28, 38, 38, 32, 26} },
+		{ {36, 36, 36, 36, 32, 28, 36, 36, 32, 28, 36, 36, 32, 26} },
+	 },
+	.calTargetPower5GHT40 =  {
+		/*
+		 * 0_8_16,1-3_9-11_17-19,
+		 * 4,5,6,7,12,13,14,15,20,21,22,23
+		 */
+		{ {40, 40, 40, 38, 30, 26, 40, 40, 30, 26, 40, 40, 30, 24} },
+		{ {40, 40, 40, 38, 30, 26, 40, 40, 30, 26, 40, 40, 30, 24} },
+		{ {40, 40, 40, 38, 30, 26, 40, 40, 30, 26, 40, 40, 30, 24} },
+		{ {40, 40, 40, 38, 30, 26, 40, 40, 30, 26, 40, 40, 30, 24} },
+		{ {40, 40, 40, 38, 30, 26, 40, 40, 30, 26, 40, 40, 30, 24} },
+		{ {40, 40, 40, 38, 30, 26, 40, 40, 30, 26, 40, 40, 30, 24} },
+		{ {36, 36, 36, 36, 30, 26, 36, 36, 30, 26, 36, 36, 30, 24} },
+		{ {34, 34, 34, 34, 30, 26, 34, 34, 30, 26, 34, 34, 30, 24} },
+	 },
+	.ctlIndex_5G =  {
+		0x10, 0x16, 0x18, 0x40, 0x46,
+		0x48, 0x30, 0x36, 0x38
+	},
+	.ctl_freqbin_5G =  {
+		{
+			/* Data[0].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
+			/* Data[0].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0),
+			/* Data[0].ctlEdges[2].bChannel */ FREQ2FBIN(5280, 0),
+			/* Data[0].ctlEdges[3].bChannel */ FREQ2FBIN(5500, 0),
+			/* Data[0].ctlEdges[4].bChannel */ FREQ2FBIN(5600, 0),
+			/* Data[0].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0),
+			/* Data[0].ctlEdges[6].bChannel */ FREQ2FBIN(5745, 0),
+			/* Data[0].ctlEdges[7].bChannel */ FREQ2FBIN(5825, 0)
+		},
+		{
+			/* Data[1].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
+			/* Data[1].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0),
+			/* Data[1].ctlEdges[2].bChannel */ FREQ2FBIN(5280, 0),
+			/* Data[1].ctlEdges[3].bChannel */ FREQ2FBIN(5500, 0),
+			/* Data[1].ctlEdges[4].bChannel */ FREQ2FBIN(5520, 0),
+			/* Data[1].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0),
+			/* Data[1].ctlEdges[6].bChannel */ FREQ2FBIN(5745, 0),
+			/* Data[1].ctlEdges[7].bChannel */ FREQ2FBIN(5825, 0)
+		},
+
+		{
+			/* Data[2].ctlEdges[0].bChannel */ FREQ2FBIN(5190, 0),
+			/* Data[2].ctlEdges[1].bChannel */ FREQ2FBIN(5230, 0),
+			/* Data[2].ctlEdges[2].bChannel */ FREQ2FBIN(5270, 0),
+			/* Data[2].ctlEdges[3].bChannel */ FREQ2FBIN(5310, 0),
+			/* Data[2].ctlEdges[4].bChannel */ FREQ2FBIN(5510, 0),
+			/* Data[2].ctlEdges[5].bChannel */ FREQ2FBIN(5550, 0),
+			/* Data[2].ctlEdges[6].bChannel */ FREQ2FBIN(5670, 0),
+			/* Data[2].ctlEdges[7].bChannel */ FREQ2FBIN(5755, 0)
+		},
+
+		{
+			/* Data[3].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
+			/* Data[3].ctlEdges[1].bChannel */ FREQ2FBIN(5200, 0),
+			/* Data[3].ctlEdges[2].bChannel */ FREQ2FBIN(5260, 0),
+			/* Data[3].ctlEdges[3].bChannel */ FREQ2FBIN(5320, 0),
+			/* Data[3].ctlEdges[4].bChannel */ FREQ2FBIN(5500, 0),
+			/* Data[3].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0),
+			/* Data[3].ctlEdges[6].bChannel */ 0xFF,
+			/* Data[3].ctlEdges[7].bChannel */ 0xFF,
+		},
+
+		{
+			/* Data[4].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
+			/* Data[4].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0),
+			/* Data[4].ctlEdges[2].bChannel */ FREQ2FBIN(5500, 0),
+			/* Data[4].ctlEdges[3].bChannel */ FREQ2FBIN(5700, 0),
+			/* Data[4].ctlEdges[4].bChannel */ 0xFF,
+			/* Data[4].ctlEdges[5].bChannel */ 0xFF,
+			/* Data[4].ctlEdges[6].bChannel */ 0xFF,
+			/* Data[4].ctlEdges[7].bChannel */ 0xFF,
+		},
+
+		{
+			/* Data[5].ctlEdges[0].bChannel */ FREQ2FBIN(5190, 0),
+			/* Data[5].ctlEdges[1].bChannel */ FREQ2FBIN(5270, 0),
+			/* Data[5].ctlEdges[2].bChannel */ FREQ2FBIN(5310, 0),
+			/* Data[5].ctlEdges[3].bChannel */ FREQ2FBIN(5510, 0),
+			/* Data[5].ctlEdges[4].bChannel */ FREQ2FBIN(5590, 0),
+			/* Data[5].ctlEdges[5].bChannel */ FREQ2FBIN(5670, 0),
+			/* Data[5].ctlEdges[6].bChannel */ 0xFF,
+			/* Data[5].ctlEdges[7].bChannel */ 0xFF
+		},
+
+		{
+			/* Data[6].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
+			/* Data[6].ctlEdges[1].bChannel */ FREQ2FBIN(5200, 0),
+			/* Data[6].ctlEdges[2].bChannel */ FREQ2FBIN(5220, 0),
+			/* Data[6].ctlEdges[3].bChannel */ FREQ2FBIN(5260, 0),
+			/* Data[6].ctlEdges[4].bChannel */ FREQ2FBIN(5500, 0),
+			/* Data[6].ctlEdges[5].bChannel */ FREQ2FBIN(5600, 0),
+			/* Data[6].ctlEdges[6].bChannel */ FREQ2FBIN(5700, 0),
+			/* Data[6].ctlEdges[7].bChannel */ FREQ2FBIN(5745, 0)
+		},
+
+		{
+			/* Data[7].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
+			/* Data[7].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0),
+			/* Data[7].ctlEdges[2].bChannel */ FREQ2FBIN(5320, 0),
+			/* Data[7].ctlEdges[3].bChannel */ FREQ2FBIN(5500, 0),
+			/* Data[7].ctlEdges[4].bChannel */ FREQ2FBIN(5560, 0),
+			/* Data[7].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0),
+			/* Data[7].ctlEdges[6].bChannel */ FREQ2FBIN(5745, 0),
+			/* Data[7].ctlEdges[7].bChannel */ FREQ2FBIN(5825, 0)
+		},
+
+		{
+			/* Data[8].ctlEdges[0].bChannel */ FREQ2FBIN(5190, 0),
+			/* Data[8].ctlEdges[1].bChannel */ FREQ2FBIN(5230, 0),
+			/* Data[8].ctlEdges[2].bChannel */ FREQ2FBIN(5270, 0),
+			/* Data[8].ctlEdges[3].bChannel */ FREQ2FBIN(5510, 0),
+			/* Data[8].ctlEdges[4].bChannel */ FREQ2FBIN(5550, 0),
+			/* Data[8].ctlEdges[5].bChannel */ FREQ2FBIN(5670, 0),
+			/* Data[8].ctlEdges[6].bChannel */ FREQ2FBIN(5755, 0),
+			/* Data[8].ctlEdges[7].bChannel */ FREQ2FBIN(5795, 0)
+		}
+	 },
+	.ctlPowerData_5G = {
+		{
+			{
+				CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+				CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0),
+			}
+		},
+		{
+			{
+				CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+				CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0),
+			}
+		},
+		{
+			{
+				CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 1),
+				CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+			}
+		},
+		{
+			{
+				CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 0),
+				CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 0),
+			}
+		},
+		{
+			{
+				CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0),
+				CTL(60, 0), CTL(60, 0), CTL(60, 0), CTL(60, 0),
+			}
+		},
+		{
+			{
+				CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+				CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 0),
+			}
+		},
+		{
+			{
+				CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+				CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+			}
+		},
+		{
+			{
+				CTL(60, 1), CTL(60, 1), CTL(60, 0), CTL(60, 1),
+				CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0),
+			}
+		},
+		{
+			{
+				CTL(60, 1), CTL(60, 0), CTL(60, 1), CTL(60, 1),
+				CTL(60, 1), CTL(60, 1), CTL(60, 0), CTL(60, 1),
+			}
+		},
+	 }
+};
+
+
+static const struct ar9300_eeprom ar9300_h112 = {
+	.eepromVersion = 2,
+	.templateVersion = 3,
+	.macAddr = {0x00, 0x03, 0x7f, 0x0, 0x0, 0x0},
+	.custData = {"h112-241-f0000"},
+	.baseEepHeader = {
+		.regDmn = { LE16(0), LE16(0x1f) },
+		.txrxMask =  0x77, /* 4 bits tx and 4 bits rx */
+		.opCapFlags = {
+			.opFlags = AR5416_OPFLAGS_11G | AR5416_OPFLAGS_11A,
+			.eepMisc = 0,
+		},
+		.rfSilent = 0,
+		.blueToothOptions = 0,
+		.deviceCap = 0,
+		.deviceType = 5, /* takes lower byte in eeprom location */
+		.pwrTableOffset = AR9300_PWR_TABLE_OFFSET,
+		.params_for_tuning_caps = {0, 0},
+		.featureEnable = 0x0d,
+		/*
+		 * bit0 - enable tx temp comp - disabled
+		 * bit1 - enable tx volt comp - disabled
+		 * bit2 - enable fastClock - enabled
+		 * bit3 - enable doubling - enabled
+		 * bit4 - enable internal regulator - disabled
+		 * bit5 - enable pa predistortion - disabled
+		 */
+		.miscConfiguration = 0, /* bit0 - turn down drivestrength */
+		.eepromWriteEnableGpio = 6,
+		.wlanDisableGpio = 0,
+		.wlanLedGpio = 8,
+		.rxBandSelectGpio = 0xff,
+		.txrxgain = 0x10,
+		.swreg = 0,
+	},
+	.modalHeader2G = {
+		/* ar9300_modal_eep_header  2g */
+		/* 4 idle,t1,t2,b(4 bits per setting) */
+		.antCtrlCommon = LE32(0x110),
+		/* 4 ra1l1, ra2l1, ra1l2, ra2l2, ra12 */
+		.antCtrlCommon2 = LE32(0x44444),
+
+		/*
+		 * antCtrlChain[AR9300_MAX_CHAINS]; 6 idle, t, r,
+		 * rx1, rx12, b (2 bits each)
+		 */
+		.antCtrlChain = { LE16(0x150), LE16(0x150), LE16(0x150) },
+
+		/*
+		 * xatten1DB[AR9300_MAX_CHAINS];  3 xatten1_db
+		 * for ar9280 (0xa20c/b20c 5:0)
+		 */
+		.xatten1DB = {0, 0, 0},
+
+		/*
+		 * xatten1Margin[AR9300_MAX_CHAINS]; 3 xatten1_margin
+		 * for ar9280 (0xa20c/b20c 16:12
+		 */
+		.xatten1Margin = {0, 0, 0},
+		.tempSlope = 25,
+		.voltSlope = 0,
+
+		/*
+		 * spurChans[OSPREY_EEPROM_MODAL_SPURS]; spur
+		 * channels in usual fbin coding format
+		 */
+		.spurChans = {FREQ2FBIN(2464, 1), 0, 0, 0, 0},
+
+		/*
+		 * noiseFloorThreshCh[AR9300_MAX_CHAINS]; 3 Check
+		 * if the register is per chain
+		 */
+		.noiseFloorThreshCh = {-1, 0, 0},
+		.ob = {1, 1, 1},/* 3 chain */
+		.db_stage2 = {1, 1, 1}, /* 3 chain  */
+		.db_stage3 = {0, 0, 0},
+		.db_stage4 = {0, 0, 0},
+		.xpaBiasLvl = 0,
+		.txFrameToDataStart = 0x0e,
+		.txFrameToPaOn = 0x0e,
+		.txClip = 3, /* 4 bits tx_clip, 4 bits dac_scale_cck */
+		.antennaGain = 0,
+		.switchSettling = 0x2c,
+		.adcDesiredSize = -30,
+		.txEndToXpaOff = 0,
+		.txEndToRxOn = 0x2,
+		.txFrameToXpaOn = 0xe,
+		.thresh62 = 28,
+		.papdRateMaskHt20 = LE32(0x80c080),
+		.papdRateMaskHt40 = LE32(0x80c080),
+		.futureModal = {
+			0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+		},
+	},
+	.base_ext1 = {
+		.ant_div_control = 0,
+		.future = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
+	},
+	.calFreqPier2G = {
+		FREQ2FBIN(2412, 1),
+		FREQ2FBIN(2437, 1),
+		FREQ2FBIN(2472, 1),
+	},
+	/* ar9300_cal_data_per_freq_op_loop 2g */
+	.calPierData2G = {
+		{ {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} },
+	},
+	.calTarget_freqbin_Cck = {
+		FREQ2FBIN(2412, 1),
+		FREQ2FBIN(2484, 1),
+	},
+	.calTarget_freqbin_2G = {
+		FREQ2FBIN(2412, 1),
+		FREQ2FBIN(2437, 1),
+		FREQ2FBIN(2472, 1)
+	},
+	.calTarget_freqbin_2GHT20 = {
+		FREQ2FBIN(2412, 1),
+		FREQ2FBIN(2437, 1),
+		FREQ2FBIN(2472, 1)
+	},
+	.calTarget_freqbin_2GHT40 = {
+		FREQ2FBIN(2412, 1),
+		FREQ2FBIN(2437, 1),
+		FREQ2FBIN(2472, 1)
+	},
+	.calTargetPowerCck = {
+		/* 1L-5L,5S,11L,11S */
+		{ {34, 34, 34, 34} },
+		{ {34, 34, 34, 34} },
+	},
+	.calTargetPower2G = {
+		/* 6-24,36,48,54 */
+		{ {34, 34, 32, 32} },
+		{ {34, 34, 32, 32} },
+		{ {34, 34, 32, 32} },
+	},
+	.calTargetPower2GHT20 = {
+		{ {32, 32, 32, 32, 32, 30, 32, 32, 30, 28, 28, 28, 28, 24} },
+		{ {32, 32, 32, 32, 32, 30, 32, 32, 30, 28, 28, 28, 28, 24} },
+		{ {32, 32, 32, 32, 32, 30, 32, 32, 30, 28, 28, 28, 28, 24} },
+	},
+	.calTargetPower2GHT40 = {
+		{ {30, 30, 30, 30, 30, 28, 30, 30, 28, 26, 26, 26, 26, 22} },
+		{ {30, 30, 30, 30, 30, 28, 30, 30, 28, 26, 26, 26, 26, 22} },
+		{ {30, 30, 30, 30, 30, 28, 30, 30, 28, 26, 26, 26, 26, 22} },
+	},
+	.ctlIndex_2G =  {
+		0x11, 0x12, 0x15, 0x17, 0x41, 0x42,
+		0x45, 0x47, 0x31, 0x32, 0x35, 0x37,
+	},
+	.ctl_freqbin_2G = {
+		{
+			FREQ2FBIN(2412, 1),
+			FREQ2FBIN(2417, 1),
+			FREQ2FBIN(2457, 1),
+			FREQ2FBIN(2462, 1)
+		},
+		{
+			FREQ2FBIN(2412, 1),
+			FREQ2FBIN(2417, 1),
+			FREQ2FBIN(2462, 1),
+			0xFF,
+		},
+
+		{
+			FREQ2FBIN(2412, 1),
+			FREQ2FBIN(2417, 1),
+			FREQ2FBIN(2462, 1),
+			0xFF,
+		},
+		{
+			FREQ2FBIN(2422, 1),
+			FREQ2FBIN(2427, 1),
+			FREQ2FBIN(2447, 1),
+			FREQ2FBIN(2452, 1)
+		},
+
+		{
+			/* Data[4].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
+			/* Data[4].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
+			/* Data[4].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
+			/* Data[4].ctlEdges[3].bChannel */ FREQ2FBIN(2484, 1),
+		},
+
+		{
+			/* Data[5].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
+			/* Data[5].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
+			/* Data[5].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
+			0,
+		},
+
+		{
+			/* Data[6].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
+			/* Data[6].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
+			FREQ2FBIN(2472, 1),
+			0,
+		},
+
+		{
+			/* Data[7].ctlEdges[0].bChannel */ FREQ2FBIN(2422, 1),
+			/* Data[7].ctlEdges[1].bChannel */ FREQ2FBIN(2427, 1),
+			/* Data[7].ctlEdges[2].bChannel */ FREQ2FBIN(2447, 1),
+			/* Data[7].ctlEdges[3].bChannel */ FREQ2FBIN(2462, 1),
+		},
+
+		{
+			/* Data[8].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
+			/* Data[8].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
+			/* Data[8].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
+		},
+
+		{
+			/* Data[9].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
+			/* Data[9].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
+			/* Data[9].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
+			0
+		},
+
+		{
+			/* Data[10].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
+			/* Data[10].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
+			/* Data[10].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
+			0
+		},
+
+		{
+			/* Data[11].ctlEdges[0].bChannel */ FREQ2FBIN(2422, 1),
+			/* Data[11].ctlEdges[1].bChannel */ FREQ2FBIN(2427, 1),
+			/* Data[11].ctlEdges[2].bChannel */ FREQ2FBIN(2447, 1),
+			/* Data[11].ctlEdges[3].bChannel */ FREQ2FBIN(2462, 1),
+		}
+	},
+	.ctlPowerData_2G = {
+		{ { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+		{ { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+		{ { CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 1) } },
+
+		{ { CTL(60, 1), CTL(60, 0), CTL(0, 0), CTL(0, 0) } },
+		{ { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+		{ { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+
+		{ { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 0) } },
+		{ { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+		{ { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+
+		{ { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+		{ { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 1) } },
+		{ { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 1) } },
+	},
+	.modalHeader5G = {
+		/* 4 idle,t1,t2,b (4 bits per setting) */
+		.antCtrlCommon = LE32(0x220),
+		/* 4 ra1l1, ra2l1, ra1l2,ra2l2,ra12 */
+		.antCtrlCommon2 = LE32(0x44444),
+		/* antCtrlChain 6 idle, t,r,rx1,rx12,b (2 bits each) */
+		.antCtrlChain = {
+			LE16(0x150), LE16(0x150), LE16(0x150),
+		},
+		/* xatten1DB 3 xatten1_db for AR9280 (0xa20c/b20c 5:0) */
+		.xatten1DB = {0, 0, 0},
+
+		/*
+		 * xatten1Margin[AR9300_MAX_CHAINS]; 3 xatten1_margin
+		 * for merlin (0xa20c/b20c 16:12
+		 */
+		.xatten1Margin = {0, 0, 0},
+		.tempSlope = 45,
+		.voltSlope = 0,
+		/* spurChans spur channels in usual fbin coding format */
+		.spurChans = {0, 0, 0, 0, 0},
+		/* noiseFloorThreshCh Check if the register is per chain */
+		.noiseFloorThreshCh = {-1, 0, 0},
+		.ob = {3, 3, 3}, /* 3 chain */
+		.db_stage2 = {3, 3, 3}, /* 3 chain */
+		.db_stage3 = {3, 3, 3}, /* doesn't exist for 2G */
+		.db_stage4 = {3, 3, 3},	 /* don't exist for 2G */
+		.xpaBiasLvl = 0,
+		.txFrameToDataStart = 0x0e,
+		.txFrameToPaOn = 0x0e,
+		.txClip = 3, /* 4 bits tx_clip, 4 bits dac_scale_cck */
+		.antennaGain = 0,
+		.switchSettling = 0x2d,
+		.adcDesiredSize = -30,
+		.txEndToXpaOff = 0,
+		.txEndToRxOn = 0x2,
+		.txFrameToXpaOn = 0xe,
+		.thresh62 = 28,
+		.papdRateMaskHt20 = LE32(0x0cf0e0e0),
+		.papdRateMaskHt40 = LE32(0x6cf0e0e0),
+		.futureModal = {
+			0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+		},
+	},
+	.base_ext2 = {
+		.tempSlopeLow = 40,
+		.tempSlopeHigh = 50,
+		.xatten1DBLow = {0, 0, 0},
+		.xatten1MarginLow = {0, 0, 0},
+		.xatten1DBHigh = {0, 0, 0},
+		.xatten1MarginHigh = {0, 0, 0}
+	},
+	.calFreqPier5G = {
+		FREQ2FBIN(5180, 0),
+		FREQ2FBIN(5220, 0),
+		FREQ2FBIN(5320, 0),
+		FREQ2FBIN(5400, 0),
+		FREQ2FBIN(5500, 0),
+		FREQ2FBIN(5600, 0),
+		FREQ2FBIN(5700, 0),
+		FREQ2FBIN(5825, 0)
+	},
+	.calPierData5G = {
+		{
+			{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, 0, 0, 0},
+			{0, 0, 0, 0, 0},
+		},
+
+	},
+	.calTarget_freqbin_5G = {
+		FREQ2FBIN(5180, 0),
+		FREQ2FBIN(5240, 0),
+		FREQ2FBIN(5320, 0),
+		FREQ2FBIN(5400, 0),
+		FREQ2FBIN(5500, 0),
+		FREQ2FBIN(5600, 0),
+		FREQ2FBIN(5700, 0),
+		FREQ2FBIN(5825, 0)
+	},
+	.calTarget_freqbin_5GHT20 = {
+		FREQ2FBIN(5180, 0),
+		FREQ2FBIN(5240, 0),
+		FREQ2FBIN(5320, 0),
+		FREQ2FBIN(5400, 0),
+		FREQ2FBIN(5500, 0),
+		FREQ2FBIN(5700, 0),
+		FREQ2FBIN(5745, 0),
+		FREQ2FBIN(5825, 0)
+	},
+	.calTarget_freqbin_5GHT40 = {
+		FREQ2FBIN(5180, 0),
+		FREQ2FBIN(5240, 0),
+		FREQ2FBIN(5320, 0),
+		FREQ2FBIN(5400, 0),
+		FREQ2FBIN(5500, 0),
+		FREQ2FBIN(5700, 0),
+		FREQ2FBIN(5745, 0),
+		FREQ2FBIN(5825, 0)
+	},
+	.calTargetPower5G = {
+		/* 6-24,36,48,54 */
+		{ {30, 30, 28, 24} },
+		{ {30, 30, 28, 24} },
+		{ {30, 30, 28, 24} },
+		{ {30, 30, 28, 24} },
+		{ {30, 30, 28, 24} },
+		{ {30, 30, 28, 24} },
+		{ {30, 30, 28, 24} },
+		{ {30, 30, 28, 24} },
+	},
+	.calTargetPower5GHT20 = {
+		/*
+		 * 0_8_16,1-3_9-11_17-19,
+		 * 4,5,6,7,12,13,14,15,20,21,22,23
+		 */
+		{ {30, 30, 30, 28, 24, 20, 30, 28, 24, 20, 20, 20, 20, 16} },
+		{ {30, 30, 30, 28, 24, 20, 30, 28, 24, 20, 20, 20, 20, 16} },
+		{ {30, 30, 30, 26, 22, 18, 30, 26, 22, 18, 18, 18, 18, 16} },
+		{ {30, 30, 30, 26, 22, 18, 30, 26, 22, 18, 18, 18, 18, 16} },
+		{ {30, 30, 30, 24, 20, 16, 30, 24, 20, 16, 16, 16, 16, 14} },
+		{ {30, 30, 30, 24, 20, 16, 30, 24, 20, 16, 16, 16, 16, 14} },
+		{ {30, 30, 30, 22, 18, 14, 30, 22, 18, 14, 14, 14, 14, 12} },
+		{ {30, 30, 30, 22, 18, 14, 30, 22, 18, 14, 14, 14, 14, 12} },
+	},
+	.calTargetPower5GHT40 =  {
+		/*
+		 * 0_8_16,1-3_9-11_17-19,
+		 * 4,5,6,7,12,13,14,15,20,21,22,23
+		 */
+		{ {28, 28, 28, 26, 22, 18, 28, 26, 22, 18, 18, 18, 18, 14} },
+		{ {28, 28, 28, 26, 22, 18, 28, 26, 22, 18, 18, 18, 18, 14} },
+		{ {28, 28, 28, 24, 20, 16, 28, 24, 20, 16, 16, 16, 16, 12} },
+		{ {28, 28, 28, 24, 20, 16, 28, 24, 20, 16, 16, 16, 16, 12} },
+		{ {28, 28, 28, 22, 18, 14, 28, 22, 18, 14, 14, 14, 14, 10} },
+		{ {28, 28, 28, 22, 18, 14, 28, 22, 18, 14, 14, 14, 14, 10} },
+		{ {28, 28, 28, 20, 16, 12, 28, 20, 16, 12, 12, 12, 12, 8} },
+		{ {28, 28, 28, 20, 16, 12, 28, 20, 16, 12, 12, 12, 12, 8} },
+	},
+	.ctlIndex_5G =  {
+		0x10, 0x16, 0x18, 0x40, 0x46,
+		0x48, 0x30, 0x36, 0x38
+	},
+	.ctl_freqbin_5G =  {
+		{
+			/* Data[0].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
+			/* Data[0].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0),
+			/* Data[0].ctlEdges[2].bChannel */ FREQ2FBIN(5280, 0),
+			/* Data[0].ctlEdges[3].bChannel */ FREQ2FBIN(5500, 0),
+			/* Data[0].ctlEdges[4].bChannel */ FREQ2FBIN(5600, 0),
+			/* Data[0].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0),
+			/* Data[0].ctlEdges[6].bChannel */ FREQ2FBIN(5745, 0),
+			/* Data[0].ctlEdges[7].bChannel */ FREQ2FBIN(5825, 0)
+		},
+		{
+			/* Data[1].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
+			/* Data[1].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0),
+			/* Data[1].ctlEdges[2].bChannel */ FREQ2FBIN(5280, 0),
+			/* Data[1].ctlEdges[3].bChannel */ FREQ2FBIN(5500, 0),
+			/* Data[1].ctlEdges[4].bChannel */ FREQ2FBIN(5520, 0),
+			/* Data[1].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0),
+			/* Data[1].ctlEdges[6].bChannel */ FREQ2FBIN(5745, 0),
+			/* Data[1].ctlEdges[7].bChannel */ FREQ2FBIN(5825, 0)
+		},
+
+		{
+			/* Data[2].ctlEdges[0].bChannel */ FREQ2FBIN(5190, 0),
+			/* Data[2].ctlEdges[1].bChannel */ FREQ2FBIN(5230, 0),
+			/* Data[2].ctlEdges[2].bChannel */ FREQ2FBIN(5270, 0),
+			/* Data[2].ctlEdges[3].bChannel */ FREQ2FBIN(5310, 0),
+			/* Data[2].ctlEdges[4].bChannel */ FREQ2FBIN(5510, 0),
+			/* Data[2].ctlEdges[5].bChannel */ FREQ2FBIN(5550, 0),
+			/* Data[2].ctlEdges[6].bChannel */ FREQ2FBIN(5670, 0),
+			/* Data[2].ctlEdges[7].bChannel */ FREQ2FBIN(5755, 0)
+		},
+
+		{
+			/* Data[3].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
+			/* Data[3].ctlEdges[1].bChannel */ FREQ2FBIN(5200, 0),
+			/* Data[3].ctlEdges[2].bChannel */ FREQ2FBIN(5260, 0),
+			/* Data[3].ctlEdges[3].bChannel */ FREQ2FBIN(5320, 0),
+			/* Data[3].ctlEdges[4].bChannel */ FREQ2FBIN(5500, 0),
+			/* Data[3].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0),
+			/* Data[3].ctlEdges[6].bChannel */ 0xFF,
+			/* Data[3].ctlEdges[7].bChannel */ 0xFF,
+		},
+
+		{
+			/* Data[4].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
+			/* Data[4].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0),
+			/* Data[4].ctlEdges[2].bChannel */ FREQ2FBIN(5500, 0),
+			/* Data[4].ctlEdges[3].bChannel */ FREQ2FBIN(5700, 0),
+			/* Data[4].ctlEdges[4].bChannel */ 0xFF,
+			/* Data[4].ctlEdges[5].bChannel */ 0xFF,
+			/* Data[4].ctlEdges[6].bChannel */ 0xFF,
+			/* Data[4].ctlEdges[7].bChannel */ 0xFF,
+		},
+
+		{
+			/* Data[5].ctlEdges[0].bChannel */ FREQ2FBIN(5190, 0),
+			/* Data[5].ctlEdges[1].bChannel */ FREQ2FBIN(5270, 0),
+			/* Data[5].ctlEdges[2].bChannel */ FREQ2FBIN(5310, 0),
+			/* Data[5].ctlEdges[3].bChannel */ FREQ2FBIN(5510, 0),
+			/* Data[5].ctlEdges[4].bChannel */ FREQ2FBIN(5590, 0),
+			/* Data[5].ctlEdges[5].bChannel */ FREQ2FBIN(5670, 0),
+			/* Data[5].ctlEdges[6].bChannel */ 0xFF,
+			/* Data[5].ctlEdges[7].bChannel */ 0xFF
+		},
+
+		{
+			/* Data[6].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
+			/* Data[6].ctlEdges[1].bChannel */ FREQ2FBIN(5200, 0),
+			/* Data[6].ctlEdges[2].bChannel */ FREQ2FBIN(5220, 0),
+			/* Data[6].ctlEdges[3].bChannel */ FREQ2FBIN(5260, 0),
+			/* Data[6].ctlEdges[4].bChannel */ FREQ2FBIN(5500, 0),
+			/* Data[6].ctlEdges[5].bChannel */ FREQ2FBIN(5600, 0),
+			/* Data[6].ctlEdges[6].bChannel */ FREQ2FBIN(5700, 0),
+			/* Data[6].ctlEdges[7].bChannel */ FREQ2FBIN(5745, 0)
+		},
+
+		{
+			/* Data[7].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
+			/* Data[7].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0),
+			/* Data[7].ctlEdges[2].bChannel */ FREQ2FBIN(5320, 0),
+			/* Data[7].ctlEdges[3].bChannel */ FREQ2FBIN(5500, 0),
+			/* Data[7].ctlEdges[4].bChannel */ FREQ2FBIN(5560, 0),
+			/* Data[7].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0),
+			/* Data[7].ctlEdges[6].bChannel */ FREQ2FBIN(5745, 0),
+			/* Data[7].ctlEdges[7].bChannel */ FREQ2FBIN(5825, 0)
+		},
+
+		{
+			/* Data[8].ctlEdges[0].bChannel */ FREQ2FBIN(5190, 0),
+			/* Data[8].ctlEdges[1].bChannel */ FREQ2FBIN(5230, 0),
+			/* Data[8].ctlEdges[2].bChannel */ FREQ2FBIN(5270, 0),
+			/* Data[8].ctlEdges[3].bChannel */ FREQ2FBIN(5510, 0),
+			/* Data[8].ctlEdges[4].bChannel */ FREQ2FBIN(5550, 0),
+			/* Data[8].ctlEdges[5].bChannel */ FREQ2FBIN(5670, 0),
+			/* Data[8].ctlEdges[6].bChannel */ FREQ2FBIN(5755, 0),
+			/* Data[8].ctlEdges[7].bChannel */ FREQ2FBIN(5795, 0)
+		}
+	},
+	.ctlPowerData_5G = {
+		{
+			{
+				CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+				CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0),
+			}
+		},
+		{
+			{
+				CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+				CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0),
+			}
+		},
+		{
+			{
+				CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 1),
+				CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+			}
+		},
+		{
+			{
+				CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 0),
+				CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 0),
+			}
+		},
+		{
+			{
+				CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0),
+				CTL(60, 0), CTL(60, 0), CTL(60, 0), CTL(60, 0),
+			}
+		},
+		{
+			{
+				CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+				CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 0),
+			}
+		},
+		{
+			{
+				CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+				CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+			}
+		},
+		{
+			{
+				CTL(60, 1), CTL(60, 1), CTL(60, 0), CTL(60, 1),
+				CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0),
+			}
+		},
+		{
+			{
+				CTL(60, 1), CTL(60, 0), CTL(60, 1), CTL(60, 1),
+				CTL(60, 1), CTL(60, 1), CTL(60, 0), CTL(60, 1),
+			}
+		},
+	}
+};
+
+
+static const struct ar9300_eeprom ar9300_x112 = {
+	.eepromVersion = 2,
+	.templateVersion = 5,
+	.macAddr = {0x00, 0x03, 0x7f, 0x0, 0x0, 0x0},
+	.custData = {"x112-041-f0000"},
+	.baseEepHeader = {
+		.regDmn = { LE16(0), LE16(0x1f) },
+		.txrxMask =  0x77, /* 4 bits tx and 4 bits rx */
+		.opCapFlags = {
+			.opFlags = AR5416_OPFLAGS_11G | AR5416_OPFLAGS_11A,
+			.eepMisc = 0,
+		},
+		.rfSilent = 0,
+		.blueToothOptions = 0,
+		.deviceCap = 0,
+		.deviceType = 5, /* takes lower byte in eeprom location */
+		.pwrTableOffset = AR9300_PWR_TABLE_OFFSET,
+		.params_for_tuning_caps = {0, 0},
+		.featureEnable = 0x0d,
+		/*
+		 * bit0 - enable tx temp comp - disabled
+		 * bit1 - enable tx volt comp - disabled
+		 * bit2 - enable fastclock - enabled
+		 * bit3 - enable doubling - enabled
+		 * bit4 - enable internal regulator - disabled
+		 * bit5 - enable pa predistortion - disabled
+		 */
+		.miscConfiguration = 0, /* bit0 - turn down drivestrength */
+		.eepromWriteEnableGpio = 6,
+		.wlanDisableGpio = 0,
+		.wlanLedGpio = 8,
+		.rxBandSelectGpio = 0xff,
+		.txrxgain = 0x0,
+		.swreg = 0,
+	},
+	.modalHeader2G = {
+		/* ar9300_modal_eep_header  2g */
+		/* 4 idle,t1,t2,b(4 bits per setting) */
+		.antCtrlCommon = LE32(0x110),
+		/* 4 ra1l1, ra2l1, ra1l2, ra2l2, ra12 */
+		.antCtrlCommon2 = LE32(0x22222),
+
+		/*
+		 * antCtrlChain[ar9300_max_chains]; 6 idle, t, r,
+		 * rx1, rx12, b (2 bits each)
+		 */
+		.antCtrlChain = { LE16(0x10), LE16(0x10), LE16(0x10) },
+
+		/*
+		 * xatten1DB[AR9300_max_chains];  3 xatten1_db
+		 * for ar9280 (0xa20c/b20c 5:0)
+		 */
+		.xatten1DB = {0x1b, 0x1b, 0x1b},
+
+		/*
+		 * xatten1Margin[ar9300_max_chains]; 3 xatten1_margin
+		 * for ar9280 (0xa20c/b20c 16:12
+		 */
+		.xatten1Margin = {0x15, 0x15, 0x15},
+		.tempSlope = 50,
+		.voltSlope = 0,
+
+		/*
+		 * spurChans[OSPrey_eeprom_modal_sPURS]; spur
+		 * channels in usual fbin coding format
+		 */
+		.spurChans = {FREQ2FBIN(2464, 1), 0, 0, 0, 0},
+
+		/*
+		 * noiseFloorThreshch[ar9300_max_cHAINS]; 3 Check
+		 * if the register is per chain
+		 */
+		.noiseFloorThreshCh = {-1, 0, 0},
+		.ob = {1, 1, 1},/* 3 chain */
+		.db_stage2 = {1, 1, 1}, /* 3 chain  */
+		.db_stage3 = {0, 0, 0},
+		.db_stage4 = {0, 0, 0},
+		.xpaBiasLvl = 0,
+		.txFrameToDataStart = 0x0e,
+		.txFrameToPaOn = 0x0e,
+		.txClip = 3, /* 4 bits tx_clip, 4 bits dac_scale_cck */
+		.antennaGain = 0,
+		.switchSettling = 0x2c,
+		.adcDesiredSize = -30,
+		.txEndToXpaOff = 0,
+		.txEndToRxOn = 0x2,
+		.txFrameToXpaOn = 0xe,
+		.thresh62 = 28,
+		.papdRateMaskHt20 = LE32(0x0c80c080),
+		.papdRateMaskHt40 = LE32(0x0080c080),
+		.futureModal = {
+			0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+		},
+	},
+	.base_ext1 = {
+		.ant_div_control = 0,
+		.future = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
+	},
+	.calFreqPier2G = {
+		FREQ2FBIN(2412, 1),
+		FREQ2FBIN(2437, 1),
+		FREQ2FBIN(2472, 1),
+	},
+	/* ar9300_cal_data_per_freq_op_loop 2g */
+	.calPierData2G = {
+		{ {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} },
+	},
+	.calTarget_freqbin_Cck = {
+		FREQ2FBIN(2412, 1),
+		FREQ2FBIN(2472, 1),
+	},
+	.calTarget_freqbin_2G = {
+		FREQ2FBIN(2412, 1),
+		FREQ2FBIN(2437, 1),
+		FREQ2FBIN(2472, 1)
+	},
+	.calTarget_freqbin_2GHT20 = {
+		FREQ2FBIN(2412, 1),
+		FREQ2FBIN(2437, 1),
+		FREQ2FBIN(2472, 1)
+	},
+	.calTarget_freqbin_2GHT40 = {
+		FREQ2FBIN(2412, 1),
+		FREQ2FBIN(2437, 1),
+		FREQ2FBIN(2472, 1)
+	},
+	.calTargetPowerCck = {
+		/* 1L-5L,5S,11L,11s */
+		{ {38, 38, 38, 38} },
+		{ {38, 38, 38, 38} },
+	},
+	.calTargetPower2G = {
+		/* 6-24,36,48,54 */
+		{ {38, 38, 36, 34} },
+		{ {38, 38, 36, 34} },
+		{ {38, 38, 34, 32} },
+	},
+	.calTargetPower2GHT20 = {
+		{ {36, 36, 36, 36, 36, 34, 34, 32, 30, 28, 28, 28, 28, 26} },
+		{ {36, 36, 36, 36, 36, 34, 36, 34, 32, 30, 30, 30, 28, 26} },
+		{ {36, 36, 36, 36, 36, 34, 34, 32, 30, 28, 28, 28, 28, 26} },
+	},
+	.calTargetPower2GHT40 = {
+		{ {36, 36, 36, 36, 34, 32, 32, 30, 28, 26, 26, 26, 26, 24} },
+		{ {36, 36, 36, 36, 34, 32, 34, 32, 30, 28, 28, 28, 28, 24} },
+		{ {36, 36, 36, 36, 34, 32, 32, 30, 28, 26, 26, 26, 26, 24} },
+	},
+	.ctlIndex_2G =  {
+		0x11, 0x12, 0x15, 0x17, 0x41, 0x42,
+		0x45, 0x47, 0x31, 0x32, 0x35, 0x37,
+	},
+	.ctl_freqbin_2G = {
+		{
+			FREQ2FBIN(2412, 1),
+			FREQ2FBIN(2417, 1),
+			FREQ2FBIN(2457, 1),
+			FREQ2FBIN(2462, 1)
+		},
+		{
+			FREQ2FBIN(2412, 1),
+			FREQ2FBIN(2417, 1),
+			FREQ2FBIN(2462, 1),
+			0xFF,
+		},
+
+		{
+			FREQ2FBIN(2412, 1),
+			FREQ2FBIN(2417, 1),
+			FREQ2FBIN(2462, 1),
+			0xFF,
+		},
+		{
+			FREQ2FBIN(2422, 1),
+			FREQ2FBIN(2427, 1),
+			FREQ2FBIN(2447, 1),
+			FREQ2FBIN(2452, 1)
+		},
+
+		{
+			/* Data[4].ctledges[0].bchannel */ FREQ2FBIN(2412, 1),
+			/* Data[4].ctledges[1].bchannel */ FREQ2FBIN(2417, 1),
+			/* Data[4].ctledges[2].bchannel */ FREQ2FBIN(2472, 1),
+			/* Data[4].ctledges[3].bchannel */ FREQ2FBIN(2484, 1),
+		},
+
+		{
+			/* Data[5].ctledges[0].bchannel */ FREQ2FBIN(2412, 1),
+			/* Data[5].ctledges[1].bchannel */ FREQ2FBIN(2417, 1),
+			/* Data[5].ctledges[2].bchannel */ FREQ2FBIN(2472, 1),
+			0,
+		},
+
+		{
+			/* Data[6].ctledges[0].bchannel */ FREQ2FBIN(2412, 1),
+			/* Data[6].ctledges[1].bchannel */ FREQ2FBIN(2417, 1),
+			FREQ2FBIN(2472, 1),
+			0,
+		},
+
+		{
+			/* Data[7].ctledges[0].bchannel */ FREQ2FBIN(2422, 1),
+			/* Data[7].ctledges[1].bchannel */ FREQ2FBIN(2427, 1),
+			/* Data[7].ctledges[2].bchannel */ FREQ2FBIN(2447, 1),
+			/* Data[7].ctledges[3].bchannel */ FREQ2FBIN(2462, 1),
+		},
+
+		{
+			/* Data[8].ctledges[0].bchannel */ FREQ2FBIN(2412, 1),
+			/* Data[8].ctledges[1].bchannel */ FREQ2FBIN(2417, 1),
+			/* Data[8].ctledges[2].bchannel */ FREQ2FBIN(2472, 1),
+		},
+
+		{
+			/* Data[9].ctledges[0].bchannel */ FREQ2FBIN(2412, 1),
+			/* Data[9].ctledges[1].bchannel */ FREQ2FBIN(2417, 1),
+			/* Data[9].ctledges[2].bchannel */ FREQ2FBIN(2472, 1),
+			0
+		},
+
+		{
+			/* Data[10].ctledges[0].bchannel */ FREQ2FBIN(2412, 1),
+			/* Data[10].ctledges[1].bchannel */ FREQ2FBIN(2417, 1),
+			/* Data[10].ctledges[2].bchannel */ FREQ2FBIN(2472, 1),
+			0
+		},
+
+		{
+			/* Data[11].ctledges[0].bchannel */ FREQ2FBIN(2422, 1),
+			/* Data[11].ctledges[1].bchannel */ FREQ2FBIN(2427, 1),
+			/* Data[11].ctledges[2].bchannel */ FREQ2FBIN(2447, 1),
+			/* Data[11].ctledges[3].bchannel */ FREQ2FBIN(2462, 1),
+		}
+	},
+	.ctlPowerData_2G = {
+		{ { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+		{ { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+		{ { CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 1) } },
+
+		{ { CTL(60, 1), CTL(60, 0), CTL(0, 0), CTL(0, 0) } },
+		{ { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+		{ { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+
+		{ { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 0) } },
+		{ { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+		{ { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+
+		{ { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+		{ { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 1) } },
+		{ { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 1) } },
+	},
+	.modalHeader5G = {
+		/* 4 idle,t1,t2,b (4 bits per setting) */
+		.antCtrlCommon = LE32(0x110),
+		/* 4 ra1l1, ra2l1, ra1l2,ra2l2,ra12 */
+		.antCtrlCommon2 = LE32(0x22222),
+		/* antCtrlChain 6 idle, t,r,rx1,rx12,b (2 bits each) */
+		.antCtrlChain = {
+			LE16(0x0), LE16(0x0), LE16(0x0),
+		},
+		/* xatten1DB 3 xatten1_db for ar9280 (0xa20c/b20c 5:0) */
+		.xatten1DB = {0x13, 0x19, 0x17},
+
+		/*
+		 * xatten1Margin[ar9300_max_chains]; 3 xatten1_margin
+		 * for merlin (0xa20c/b20c 16:12
+		 */
+		.xatten1Margin = {0x19, 0x19, 0x19},
+		.tempSlope = 70,
+		.voltSlope = 15,
+		/* spurChans spur channels in usual fbin coding format */
+		.spurChans = {0, 0, 0, 0, 0},
+		/* noiseFloorThreshch check if the register is per chain */
+		.noiseFloorThreshCh = {-1, 0, 0},
+		.ob = {3, 3, 3}, /* 3 chain */
+		.db_stage2 = {3, 3, 3}, /* 3 chain */
+		.db_stage3 = {3, 3, 3}, /* doesn't exist for 2G */
+		.db_stage4 = {3, 3, 3},	 /* don't exist for 2G */
+		.xpaBiasLvl = 0,
+		.txFrameToDataStart = 0x0e,
+		.txFrameToPaOn = 0x0e,
+		.txClip = 3, /* 4 bits tx_clip, 4 bits dac_scale_cck */
+		.antennaGain = 0,
+		.switchSettling = 0x2d,
+		.adcDesiredSize = -30,
+		.txEndToXpaOff = 0,
+		.txEndToRxOn = 0x2,
+		.txFrameToXpaOn = 0xe,
+		.thresh62 = 28,
+		.papdRateMaskHt20 = LE32(0x0cf0e0e0),
+		.papdRateMaskHt40 = LE32(0x6cf0e0e0),
+		.futureModal = {
+			0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+		},
+	},
+	.base_ext2 = {
+		.tempSlopeLow = 72,
+		.tempSlopeHigh = 105,
+		.xatten1DBLow = {0x10, 0x14, 0x10},
+		.xatten1MarginLow = {0x19, 0x19 , 0x19},
+		.xatten1DBHigh = {0x1d, 0x20, 0x24},
+		.xatten1MarginHigh = {0x10, 0x10, 0x10}
+	},
+	.calFreqPier5G = {
+		FREQ2FBIN(5180, 0),
+		FREQ2FBIN(5220, 0),
+		FREQ2FBIN(5320, 0),
+		FREQ2FBIN(5400, 0),
+		FREQ2FBIN(5500, 0),
+		FREQ2FBIN(5600, 0),
+		FREQ2FBIN(5700, 0),
+		FREQ2FBIN(5785, 0)
+	},
+	.calPierData5G = {
+		{
+			{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, 0, 0, 0},
+			{0, 0, 0, 0, 0},
+		},
+
+	},
+	.calTarget_freqbin_5G = {
+		FREQ2FBIN(5180, 0),
+		FREQ2FBIN(5220, 0),
+		FREQ2FBIN(5320, 0),
+		FREQ2FBIN(5400, 0),
+		FREQ2FBIN(5500, 0),
+		FREQ2FBIN(5600, 0),
+		FREQ2FBIN(5725, 0),
+		FREQ2FBIN(5825, 0)
+	},
+	.calTarget_freqbin_5GHT20 = {
+		FREQ2FBIN(5180, 0),
+		FREQ2FBIN(5220, 0),
+		FREQ2FBIN(5320, 0),
+		FREQ2FBIN(5400, 0),
+		FREQ2FBIN(5500, 0),
+		FREQ2FBIN(5600, 0),
+		FREQ2FBIN(5725, 0),
+		FREQ2FBIN(5825, 0)
+	},
+	.calTarget_freqbin_5GHT40 = {
+		FREQ2FBIN(5180, 0),
+		FREQ2FBIN(5220, 0),
+		FREQ2FBIN(5320, 0),
+		FREQ2FBIN(5400, 0),
+		FREQ2FBIN(5500, 0),
+		FREQ2FBIN(5600, 0),
+		FREQ2FBIN(5725, 0),
+		FREQ2FBIN(5825, 0)
+	},
+	.calTargetPower5G = {
+		/* 6-24,36,48,54 */
+		{ {32, 32, 28, 26} },
+		{ {32, 32, 28, 26} },
+		{ {32, 32, 28, 26} },
+		{ {32, 32, 26, 24} },
+		{ {32, 32, 26, 24} },
+		{ {32, 32, 24, 22} },
+		{ {30, 30, 24, 22} },
+		{ {30, 30, 24, 22} },
+	},
+	.calTargetPower5GHT20 = {
+		/*
+		 * 0_8_16,1-3_9-11_17-19,
+		 * 4,5,6,7,12,13,14,15,20,21,22,23
+		 */
+		{ {32, 32, 32, 32, 28, 26, 32, 28, 26, 24, 24, 24, 22, 22} },
+		{ {32, 32, 32, 32, 28, 26, 32, 28, 26, 24, 24, 24, 22, 22} },
+		{ {32, 32, 32, 32, 28, 26, 32, 28, 26, 24, 24, 24, 22, 22} },
+		{ {32, 32, 32, 32, 28, 26, 32, 26, 24, 22, 22, 22, 20, 20} },
+		{ {32, 32, 32, 32, 28, 26, 32, 26, 24, 22, 20, 18, 16, 16} },
+		{ {32, 32, 32, 32, 28, 26, 32, 24, 20, 16, 18, 16, 14, 14} },
+		{ {30, 30, 30, 30, 28, 26, 30, 24, 20, 16, 18, 16, 14, 14} },
+		{ {30, 30, 30, 30, 28, 26, 30, 24, 20, 16, 18, 16, 14, 14} },
+	},
+	.calTargetPower5GHT40 =  {
+		/*
+		 * 0_8_16,1-3_9-11_17-19,
+		 * 4,5,6,7,12,13,14,15,20,21,22,23
+		 */
+		{ {32, 32, 32, 30, 28, 26, 30, 28, 26, 24, 24, 24, 22, 22} },
+		{ {32, 32, 32, 30, 28, 26, 30, 28, 26, 24, 24, 24, 22, 22} },
+		{ {32, 32, 32, 30, 28, 26, 30, 28, 26, 24, 24, 24, 22, 22} },
+		{ {32, 32, 32, 30, 28, 26, 30, 26, 24, 22, 22, 22, 20, 20} },
+		{ {32, 32, 32, 30, 28, 26, 30, 26, 24, 22, 20, 18, 16, 16} },
+		{ {32, 32, 32, 30, 28, 26, 30, 22, 20, 16, 18, 16, 14, 14} },
+		{ {30, 30, 30, 30, 28, 26, 30, 22, 20, 16, 18, 16, 14, 14} },
+		{ {30, 30, 30, 30, 28, 26, 30, 22, 20, 16, 18, 16, 14, 14} },
+	},
+	.ctlIndex_5G =  {
+		0x10, 0x16, 0x18, 0x40, 0x46,
+		0x48, 0x30, 0x36, 0x38
+	},
+	.ctl_freqbin_5G =  {
+		{
+			/* Data[0].ctledges[0].bchannel */ FREQ2FBIN(5180, 0),
+			/* Data[0].ctledges[1].bchannel */ FREQ2FBIN(5260, 0),
+			/* Data[0].ctledges[2].bchannel */ FREQ2FBIN(5280, 0),
+			/* Data[0].ctledges[3].bchannel */ FREQ2FBIN(5500, 0),
+			/* Data[0].ctledges[4].bchannel */ FREQ2FBIN(5600, 0),
+			/* Data[0].ctledges[5].bchannel */ FREQ2FBIN(5700, 0),
+			/* Data[0].ctledges[6].bchannel */ FREQ2FBIN(5745, 0),
+			/* Data[0].ctledges[7].bchannel */ FREQ2FBIN(5825, 0)
+		},
+		{
+			/* Data[1].ctledges[0].bchannel */ FREQ2FBIN(5180, 0),
+			/* Data[1].ctledges[1].bchannel */ FREQ2FBIN(5260, 0),
+			/* Data[1].ctledges[2].bchannel */ FREQ2FBIN(5280, 0),
+			/* Data[1].ctledges[3].bchannel */ FREQ2FBIN(5500, 0),
+			/* Data[1].ctledges[4].bchannel */ FREQ2FBIN(5520, 0),
+			/* Data[1].ctledges[5].bchannel */ FREQ2FBIN(5700, 0),
+			/* Data[1].ctledges[6].bchannel */ FREQ2FBIN(5745, 0),
+			/* Data[1].ctledges[7].bchannel */ FREQ2FBIN(5825, 0)
+		},
+
+		{
+			/* Data[2].ctledges[0].bchannel */ FREQ2FBIN(5190, 0),
+			/* Data[2].ctledges[1].bchannel */ FREQ2FBIN(5230, 0),
+			/* Data[2].ctledges[2].bchannel */ FREQ2FBIN(5270, 0),
+			/* Data[2].ctledges[3].bchannel */ FREQ2FBIN(5310, 0),
+			/* Data[2].ctledges[4].bchannel */ FREQ2FBIN(5510, 0),
+			/* Data[2].ctledges[5].bchannel */ FREQ2FBIN(5550, 0),
+			/* Data[2].ctledges[6].bchannel */ FREQ2FBIN(5670, 0),
+			/* Data[2].ctledges[7].bchannel */ FREQ2FBIN(5755, 0)
+		},
+
+		{
+			/* Data[3].ctledges[0].bchannel */ FREQ2FBIN(5180, 0),
+			/* Data[3].ctledges[1].bchannel */ FREQ2FBIN(5200, 0),
+			/* Data[3].ctledges[2].bchannel */ FREQ2FBIN(5260, 0),
+			/* Data[3].ctledges[3].bchannel */ FREQ2FBIN(5320, 0),
+			/* Data[3].ctledges[4].bchannel */ FREQ2FBIN(5500, 0),
+			/* Data[3].ctledges[5].bchannel */ FREQ2FBIN(5700, 0),
+			/* Data[3].ctledges[6].bchannel */ 0xFF,
+			/* Data[3].ctledges[7].bchannel */ 0xFF,
+		},
+
+		{
+			/* Data[4].ctledges[0].bchannel */ FREQ2FBIN(5180, 0),
+			/* Data[4].ctledges[1].bchannel */ FREQ2FBIN(5260, 0),
+			/* Data[4].ctledges[2].bchannel */ FREQ2FBIN(5500, 0),
+			/* Data[4].ctledges[3].bchannel */ FREQ2FBIN(5700, 0),
+			/* Data[4].ctledges[4].bchannel */ 0xFF,
+			/* Data[4].ctledges[5].bchannel */ 0xFF,
+			/* Data[4].ctledges[6].bchannel */ 0xFF,
+			/* Data[4].ctledges[7].bchannel */ 0xFF,
+		},
+
+		{
+			/* Data[5].ctledges[0].bchannel */ FREQ2FBIN(5190, 0),
+			/* Data[5].ctledges[1].bchannel */ FREQ2FBIN(5270, 0),
+			/* Data[5].ctledges[2].bchannel */ FREQ2FBIN(5310, 0),
+			/* Data[5].ctledges[3].bchannel */ FREQ2FBIN(5510, 0),
+			/* Data[5].ctledges[4].bchannel */ FREQ2FBIN(5590, 0),
+			/* Data[5].ctledges[5].bchannel */ FREQ2FBIN(5670, 0),
+			/* Data[5].ctledges[6].bchannel */ 0xFF,
+			/* Data[5].ctledges[7].bchannel */ 0xFF
+		},
+
+		{
+			/* Data[6].ctledges[0].bchannel */ FREQ2FBIN(5180, 0),
+			/* Data[6].ctledges[1].bchannel */ FREQ2FBIN(5200, 0),
+			/* Data[6].ctledges[2].bchannel */ FREQ2FBIN(5220, 0),
+			/* Data[6].ctledges[3].bchannel */ FREQ2FBIN(5260, 0),
+			/* Data[6].ctledges[4].bchannel */ FREQ2FBIN(5500, 0),
+			/* Data[6].ctledges[5].bchannel */ FREQ2FBIN(5600, 0),
+			/* Data[6].ctledges[6].bchannel */ FREQ2FBIN(5700, 0),
+			/* Data[6].ctledges[7].bchannel */ FREQ2FBIN(5745, 0)
+		},
+
+		{
+			/* Data[7].ctledges[0].bchannel */ FREQ2FBIN(5180, 0),
+			/* Data[7].ctledges[1].bchannel */ FREQ2FBIN(5260, 0),
+			/* Data[7].ctledges[2].bchannel */ FREQ2FBIN(5320, 0),
+			/* Data[7].ctledges[3].bchannel */ FREQ2FBIN(5500, 0),
+			/* Data[7].ctledges[4].bchannel */ FREQ2FBIN(5560, 0),
+			/* Data[7].ctledges[5].bchannel */ FREQ2FBIN(5700, 0),
+			/* Data[7].ctledges[6].bchannel */ FREQ2FBIN(5745, 0),
+			/* Data[7].ctledges[7].bchannel */ FREQ2FBIN(5825, 0)
+		},
+
+		{
+			/* Data[8].ctledges[0].bchannel */ FREQ2FBIN(5190, 0),
+			/* Data[8].ctledges[1].bchannel */ FREQ2FBIN(5230, 0),
+			/* Data[8].ctledges[2].bchannel */ FREQ2FBIN(5270, 0),
+			/* Data[8].ctledges[3].bchannel */ FREQ2FBIN(5510, 0),
+			/* Data[8].ctledges[4].bchannel */ FREQ2FBIN(5550, 0),
+			/* Data[8].ctledges[5].bchannel */ FREQ2FBIN(5670, 0),
+			/* Data[8].ctledges[6].bchannel */ FREQ2FBIN(5755, 0),
+			/* Data[8].ctledges[7].bchannel */ FREQ2FBIN(5795, 0)
+		}
+	},
+	.ctlPowerData_5G = {
+		{
+			{
+				CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+				CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0),
+			}
+		},
+		{
+			{
+				CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+				CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0),
+			}
+		},
+		{
+			{
+				CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 1),
+				CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+			}
+		},
+		{
+			{
+				CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 0),
+				CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 0),
+			}
+		},
+		{
+			{
+				CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0),
+				CTL(60, 0), CTL(60, 0), CTL(60, 0), CTL(60, 0),
+			}
+		},
+		{
+			{
+				CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+				CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 0),
+			}
+		},
+		{
+			{
+				CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+				CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+			}
+		},
+		{
+			{
+				CTL(60, 1), CTL(60, 1), CTL(60, 0), CTL(60, 1),
+				CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0),
+			}
+		},
+		{
+			{
+				CTL(60, 1), CTL(60, 0), CTL(60, 1), CTL(60, 1),
+				CTL(60, 1), CTL(60, 1), CTL(60, 0), CTL(60, 1),
+			}
+		},
+	}
+};
+
+static const struct ar9300_eeprom ar9300_h116 = {
+	.eepromVersion = 2,
+	.templateVersion = 4,
+	.macAddr = {0x00, 0x03, 0x7f, 0x0, 0x0, 0x0},
+	.custData = {"h116-041-f0000"},
+	.baseEepHeader = {
+		.regDmn = { LE16(0), LE16(0x1f) },
+		.txrxMask =  0x33, /* 4 bits tx and 4 bits rx */
+		.opCapFlags = {
+			.opFlags = AR5416_OPFLAGS_11G | AR5416_OPFLAGS_11A,
+			.eepMisc = 0,
+		},
+		.rfSilent = 0,
+		.blueToothOptions = 0,
+		.deviceCap = 0,
+		.deviceType = 5, /* takes lower byte in eeprom location */
+		.pwrTableOffset = AR9300_PWR_TABLE_OFFSET,
+		.params_for_tuning_caps = {0, 0},
+		.featureEnable = 0x0d,
+		 /*
+		  * bit0 - enable tx temp comp - disabled
+		  * bit1 - enable tx volt comp - disabled
+		  * bit2 - enable fastClock - enabled
+		  * bit3 - enable doubling - enabled
+		  * bit4 - enable internal regulator - disabled
+		  * bit5 - enable pa predistortion - disabled
+		  */
+		.miscConfiguration = 0, /* bit0 - turn down drivestrength */
+		.eepromWriteEnableGpio = 6,
+		.wlanDisableGpio = 0,
+		.wlanLedGpio = 8,
+		.rxBandSelectGpio = 0xff,
+		.txrxgain = 0x10,
+		.swreg = 0,
+	 },
+	.modalHeader2G = {
+	/* ar9300_modal_eep_header  2g */
+		/* 4 idle,t1,t2,b(4 bits per setting) */
+		.antCtrlCommon = LE32(0x110),
+		/* 4 ra1l1, ra2l1, ra1l2, ra2l2, ra12 */
+		.antCtrlCommon2 = LE32(0x44444),
+
+		/*
+		 * antCtrlChain[AR9300_MAX_CHAINS]; 6 idle, t, r,
+		 * rx1, rx12, b (2 bits each)
+		 */
+		.antCtrlChain = { LE16(0x10), LE16(0x10), LE16(0x10) },
+
+		/*
+		 * xatten1DB[AR9300_MAX_CHAINS];  3 xatten1_db
+		 * for ar9280 (0xa20c/b20c 5:0)
+		 */
+		.xatten1DB = {0x1f, 0x1f, 0x1f},
+
+		/*
+		 * xatten1Margin[AR9300_MAX_CHAINS]; 3 xatten1_margin
+		 * for ar9280 (0xa20c/b20c 16:12
+		 */
+		.xatten1Margin = {0x12, 0x12, 0x12},
+		.tempSlope = 25,
+		.voltSlope = 0,
+
+		/*
+		 * spurChans[OSPREY_EEPROM_MODAL_SPURS]; spur
+		 * channels in usual fbin coding format
+		 */
+		.spurChans = {FREQ2FBIN(2464, 1), 0, 0, 0, 0},
+
+		/*
+		 * noiseFloorThreshCh[AR9300_MAX_CHAINS]; 3 Check
+		 * if the register is per chain
+		 */
+		.noiseFloorThreshCh = {-1, 0, 0},
+		.ob = {1, 1, 1},/* 3 chain */
+		.db_stage2 = {1, 1, 1}, /* 3 chain  */
+		.db_stage3 = {0, 0, 0},
+		.db_stage4 = {0, 0, 0},
+		.xpaBiasLvl = 0,
+		.txFrameToDataStart = 0x0e,
+		.txFrameToPaOn = 0x0e,
+		.txClip = 3, /* 4 bits tx_clip, 4 bits dac_scale_cck */
+		.antennaGain = 0,
+		.switchSettling = 0x2c,
+		.adcDesiredSize = -30,
+		.txEndToXpaOff = 0,
+		.txEndToRxOn = 0x2,
+		.txFrameToXpaOn = 0xe,
+		.thresh62 = 28,
+		.papdRateMaskHt20 = LE32(0x0c80C080),
+		.papdRateMaskHt40 = LE32(0x0080C080),
+		.futureModal = {
+			0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+		},
+	 },
+	 .base_ext1 = {
+		.ant_div_control = 0,
+		.future = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
+	 },
+	.calFreqPier2G = {
+		FREQ2FBIN(2412, 1),
+		FREQ2FBIN(2437, 1),
+		FREQ2FBIN(2472, 1),
+	 },
+	/* ar9300_cal_data_per_freq_op_loop 2g */
+	.calPierData2G = {
+		{ {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} },
+	 },
+	.calTarget_freqbin_Cck = {
+		FREQ2FBIN(2412, 1),
+		FREQ2FBIN(2472, 1),
+	 },
+	.calTarget_freqbin_2G = {
+		FREQ2FBIN(2412, 1),
+		FREQ2FBIN(2437, 1),
+		FREQ2FBIN(2472, 1)
+	 },
+	.calTarget_freqbin_2GHT20 = {
+		FREQ2FBIN(2412, 1),
+		FREQ2FBIN(2437, 1),
+		FREQ2FBIN(2472, 1)
+	 },
+	.calTarget_freqbin_2GHT40 = {
+		FREQ2FBIN(2412, 1),
+		FREQ2FBIN(2437, 1),
+		FREQ2FBIN(2472, 1)
+	 },
+	.calTargetPowerCck = {
+		 /* 1L-5L,5S,11L,11S */
+		 { {34, 34, 34, 34} },
+		 { {34, 34, 34, 34} },
+	},
+	.calTargetPower2G = {
+		 /* 6-24,36,48,54 */
+		 { {34, 34, 32, 32} },
+		 { {34, 34, 32, 32} },
+		 { {34, 34, 32, 32} },
+	},
+	.calTargetPower2GHT20 = {
+		{ {32, 32, 32, 32, 32, 30, 32, 32, 30, 28, 0, 0, 0, 0} },
+		{ {32, 32, 32, 32, 32, 30, 32, 32, 30, 28, 0, 0, 0, 0} },
+		{ {32, 32, 32, 32, 32, 30, 32, 32, 30, 28, 0, 0, 0, 0} },
+	},
+	.calTargetPower2GHT40 = {
+		{ {30, 30, 30, 30, 30, 28, 30, 30, 28, 26, 0, 0, 0, 0} },
+		{ {30, 30, 30, 30, 30, 28, 30, 30, 28, 26, 0, 0, 0, 0} },
+		{ {30, 30, 30, 30, 30, 28, 30, 30, 28, 26, 0, 0, 0, 0} },
+	},
+	.ctlIndex_2G =  {
+		0x11, 0x12, 0x15, 0x17, 0x41, 0x42,
+		0x45, 0x47, 0x31, 0x32, 0x35, 0x37,
+	},
+	.ctl_freqbin_2G = {
+		{
+			FREQ2FBIN(2412, 1),
+			FREQ2FBIN(2417, 1),
+			FREQ2FBIN(2457, 1),
+			FREQ2FBIN(2462, 1)
+		},
+		{
+			FREQ2FBIN(2412, 1),
+			FREQ2FBIN(2417, 1),
+			FREQ2FBIN(2462, 1),
+			0xFF,
+		},
+
+		{
+			FREQ2FBIN(2412, 1),
+			FREQ2FBIN(2417, 1),
+			FREQ2FBIN(2462, 1),
+			0xFF,
+		},
+		{
+			FREQ2FBIN(2422, 1),
+			FREQ2FBIN(2427, 1),
+			FREQ2FBIN(2447, 1),
+			FREQ2FBIN(2452, 1)
+		},
+
+		{
+			/* Data[4].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
+			/* Data[4].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
+			/* Data[4].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
+			/* Data[4].ctlEdges[3].bChannel */ FREQ2FBIN(2484, 1),
+		},
+
+		{
+			/* Data[5].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
+			/* Data[5].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
+			/* Data[5].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
+			0,
+		},
+
+		{
+			/* Data[6].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
+			/* Data[6].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
+			FREQ2FBIN(2472, 1),
+			0,
+		},
+
+		{
+			/* Data[7].ctlEdges[0].bChannel */ FREQ2FBIN(2422, 1),
+			/* Data[7].ctlEdges[1].bChannel */ FREQ2FBIN(2427, 1),
+			/* Data[7].ctlEdges[2].bChannel */ FREQ2FBIN(2447, 1),
+			/* Data[7].ctlEdges[3].bChannel */ FREQ2FBIN(2462, 1),
+		},
+
+		{
+			/* Data[8].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
+			/* Data[8].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
+			/* Data[8].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
+		},
+
+		{
+			/* Data[9].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
+			/* Data[9].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
+			/* Data[9].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
+			0
+		},
+
+		{
+			/* Data[10].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
+			/* Data[10].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
+			/* Data[10].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
+			0
+		},
+
+		{
+			/* Data[11].ctlEdges[0].bChannel */ FREQ2FBIN(2422, 1),
+			/* Data[11].ctlEdges[1].bChannel */ FREQ2FBIN(2427, 1),
+			/* Data[11].ctlEdges[2].bChannel */ FREQ2FBIN(2447, 1),
+			/* Data[11].ctlEdges[3].bChannel */ FREQ2FBIN(2462, 1),
+		}
+	 },
+	.ctlPowerData_2G = {
+		 { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+		 { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+		 { { CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 1) } },
+
+		 { { CTL(60, 1), CTL(60, 0), CTL(0, 0), CTL(0, 0) } },
+		 { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+		 { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+
+		 { { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 0) } },
+		 { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+		 { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+
+		 { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+		 { { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 1) } },
+		 { { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 1) } },
+	 },
+	.modalHeader5G = {
+		/* 4 idle,t1,t2,b (4 bits per setting) */
+		.antCtrlCommon = LE32(0x220),
+		/* 4 ra1l1, ra2l1, ra1l2,ra2l2,ra12 */
+		.antCtrlCommon2 = LE32(0x44444),
+		 /* antCtrlChain 6 idle, t,r,rx1,rx12,b (2 bits each) */
+		.antCtrlChain = {
+			LE16(0x150), LE16(0x150), LE16(0x150),
+		},
+		 /* xatten1DB 3 xatten1_db for AR9280 (0xa20c/b20c 5:0) */
+		.xatten1DB = {0x19, 0x19, 0x19},
+
+		/*
+		 * xatten1Margin[AR9300_MAX_CHAINS]; 3 xatten1_margin
+		 * for merlin (0xa20c/b20c 16:12
+		 */
+		.xatten1Margin = {0x14, 0x14, 0x14},
+		.tempSlope = 70,
+		.voltSlope = 0,
+		/* spurChans spur channels in usual fbin coding format */
+		.spurChans = {0, 0, 0, 0, 0},
+		/* noiseFloorThreshCh Check if the register is per chain */
+		.noiseFloorThreshCh = {-1, 0, 0},
+		.ob = {3, 3, 3}, /* 3 chain */
+		.db_stage2 = {3, 3, 3}, /* 3 chain */
+		.db_stage3 = {3, 3, 3}, /* doesn't exist for 2G */
+		.db_stage4 = {3, 3, 3},	 /* don't exist for 2G */
+		.xpaBiasLvl = 0,
+		.txFrameToDataStart = 0x0e,
+		.txFrameToPaOn = 0x0e,
+		.txClip = 3, /* 4 bits tx_clip, 4 bits dac_scale_cck */
+		.antennaGain = 0,
+		.switchSettling = 0x2d,
+		.adcDesiredSize = -30,
+		.txEndToXpaOff = 0,
+		.txEndToRxOn = 0x2,
+		.txFrameToXpaOn = 0xe,
+		.thresh62 = 28,
+		.papdRateMaskHt20 = LE32(0x0cf0e0e0),
+		.papdRateMaskHt40 = LE32(0x6cf0e0e0),
+		.futureModal = {
+			0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+		},
+	 },
+	.base_ext2 = {
+		.tempSlopeLow = 35,
+		.tempSlopeHigh = 50,
+		.xatten1DBLow = {0, 0, 0},
+		.xatten1MarginLow = {0, 0, 0},
+		.xatten1DBHigh = {0, 0, 0},
+		.xatten1MarginHigh = {0, 0, 0}
+	 },
+	.calFreqPier5G = {
+		FREQ2FBIN(5180, 0),
+		FREQ2FBIN(5220, 0),
+		FREQ2FBIN(5320, 0),
+		FREQ2FBIN(5400, 0),
+		FREQ2FBIN(5500, 0),
+		FREQ2FBIN(5600, 0),
+		FREQ2FBIN(5700, 0),
+		FREQ2FBIN(5785, 0)
+	},
+	.calPierData5G = {
+			{
+				{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, 0, 0, 0},
+				{0, 0, 0, 0, 0},
+			},
+
+	},
+	.calTarget_freqbin_5G = {
+		FREQ2FBIN(5180, 0),
+		FREQ2FBIN(5240, 0),
+		FREQ2FBIN(5320, 0),
+		FREQ2FBIN(5400, 0),
+		FREQ2FBIN(5500, 0),
+		FREQ2FBIN(5600, 0),
+		FREQ2FBIN(5700, 0),
+		FREQ2FBIN(5825, 0)
+	},
+	.calTarget_freqbin_5GHT20 = {
+		FREQ2FBIN(5180, 0),
+		FREQ2FBIN(5240, 0),
+		FREQ2FBIN(5320, 0),
+		FREQ2FBIN(5400, 0),
+		FREQ2FBIN(5500, 0),
+		FREQ2FBIN(5700, 0),
+		FREQ2FBIN(5745, 0),
+		FREQ2FBIN(5825, 0)
+	},
+	.calTarget_freqbin_5GHT40 = {
+		FREQ2FBIN(5180, 0),
+		FREQ2FBIN(5240, 0),
+		FREQ2FBIN(5320, 0),
+		FREQ2FBIN(5400, 0),
+		FREQ2FBIN(5500, 0),
+		FREQ2FBIN(5700, 0),
+		FREQ2FBIN(5745, 0),
+		FREQ2FBIN(5825, 0)
+	 },
+	.calTargetPower5G = {
+		/* 6-24,36,48,54 */
+		{ {30, 30, 28, 24} },
+		{ {30, 30, 28, 24} },
+		{ {30, 30, 28, 24} },
+		{ {30, 30, 28, 24} },
+		{ {30, 30, 28, 24} },
+		{ {30, 30, 28, 24} },
+		{ {30, 30, 28, 24} },
+		{ {30, 30, 28, 24} },
+	 },
+	.calTargetPower5GHT20 = {
+		/*
+		 * 0_8_16,1-3_9-11_17-19,
+		 * 4,5,6,7,12,13,14,15,20,21,22,23
+		 */
+		{ {30, 30, 30, 28, 24, 20, 30, 28, 24, 20, 0, 0, 0, 0} },
+		{ {30, 30, 30, 28, 24, 20, 30, 28, 24, 20, 0, 0, 0, 0} },
+		{ {30, 30, 30, 26, 22, 18, 30, 26, 22, 18, 0, 0, 0, 0} },
+		{ {30, 30, 30, 26, 22, 18, 30, 26, 22, 18, 0, 0, 0, 0} },
+		{ {30, 30, 30, 24, 20, 16, 30, 24, 20, 16, 0, 0, 0, 0} },
+		{ {30, 30, 30, 24, 20, 16, 30, 24, 20, 16, 0, 0, 0, 0} },
+		{ {30, 30, 30, 22, 18, 14, 30, 22, 18, 14, 0, 0, 0, 0} },
+		{ {30, 30, 30, 22, 18, 14, 30, 22, 18, 14, 0, 0, 0, 0} },
+	 },
+	.calTargetPower5GHT40 =  {
+		/*
+		 * 0_8_16,1-3_9-11_17-19,
+		 * 4,5,6,7,12,13,14,15,20,21,22,23
+		 */
+		{ {28, 28, 28, 26, 22, 18, 28, 26, 22, 18, 0, 0, 0, 0} },
+		{ {28, 28, 28, 26, 22, 18, 28, 26, 22, 18, 0, 0, 0, 0} },
+		{ {28, 28, 28, 24, 20, 16, 28, 24, 20, 16, 0, 0, 0, 0} },
+		{ {28, 28, 28, 24, 20, 16, 28, 24, 20, 16, 0, 0, 0, 0} },
+		{ {28, 28, 28, 22, 18, 14, 28, 22, 18, 14, 0, 0, 0, 0} },
+		{ {28, 28, 28, 22, 18, 14, 28, 22, 18, 14, 0, 0, 0, 0} },
+		{ {28, 28, 28, 20, 16, 12, 28, 20, 16, 12, 0, 0, 0, 0} },
+		{ {28, 28, 28, 20, 16, 12, 28, 20, 16, 12, 0, 0, 0, 0} },
+	 },
+	.ctlIndex_5G =  {
+		0x10, 0x16, 0x18, 0x40, 0x46,
+		0x48, 0x30, 0x36, 0x38
+	},
+	.ctl_freqbin_5G =  {
+		{
+			/* Data[0].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
+			/* Data[0].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0),
+			/* Data[0].ctlEdges[2].bChannel */ FREQ2FBIN(5280, 0),
+			/* Data[0].ctlEdges[3].bChannel */ FREQ2FBIN(5500, 0),
+			/* Data[0].ctlEdges[4].bChannel */ FREQ2FBIN(5600, 0),
+			/* Data[0].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0),
+			/* Data[0].ctlEdges[6].bChannel */ FREQ2FBIN(5745, 0),
+			/* Data[0].ctlEdges[7].bChannel */ FREQ2FBIN(5825, 0)
+		},
+		{
+			/* Data[1].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
+			/* Data[1].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0),
+			/* Data[1].ctlEdges[2].bChannel */ FREQ2FBIN(5280, 0),
+			/* Data[1].ctlEdges[3].bChannel */ FREQ2FBIN(5500, 0),
+			/* Data[1].ctlEdges[4].bChannel */ FREQ2FBIN(5520, 0),
+			/* Data[1].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0),
+			/* Data[1].ctlEdges[6].bChannel */ FREQ2FBIN(5745, 0),
+			/* Data[1].ctlEdges[7].bChannel */ FREQ2FBIN(5825, 0)
+		},
+
+		{
+			/* Data[2].ctlEdges[0].bChannel */ FREQ2FBIN(5190, 0),
+			/* Data[2].ctlEdges[1].bChannel */ FREQ2FBIN(5230, 0),
+			/* Data[2].ctlEdges[2].bChannel */ FREQ2FBIN(5270, 0),
+			/* Data[2].ctlEdges[3].bChannel */ FREQ2FBIN(5310, 0),
+			/* Data[2].ctlEdges[4].bChannel */ FREQ2FBIN(5510, 0),
+			/* Data[2].ctlEdges[5].bChannel */ FREQ2FBIN(5550, 0),
+			/* Data[2].ctlEdges[6].bChannel */ FREQ2FBIN(5670, 0),
+			/* Data[2].ctlEdges[7].bChannel */ FREQ2FBIN(5755, 0)
+		},
+
+		{
+			/* Data[3].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
+			/* Data[3].ctlEdges[1].bChannel */ FREQ2FBIN(5200, 0),
+			/* Data[3].ctlEdges[2].bChannel */ FREQ2FBIN(5260, 0),
+			/* Data[3].ctlEdges[3].bChannel */ FREQ2FBIN(5320, 0),
+			/* Data[3].ctlEdges[4].bChannel */ FREQ2FBIN(5500, 0),
+			/* Data[3].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0),
+			/* Data[3].ctlEdges[6].bChannel */ 0xFF,
+			/* Data[3].ctlEdges[7].bChannel */ 0xFF,
+		},
+
+		{
+			/* Data[4].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
+			/* Data[4].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0),
+			/* Data[4].ctlEdges[2].bChannel */ FREQ2FBIN(5500, 0),
+			/* Data[4].ctlEdges[3].bChannel */ FREQ2FBIN(5700, 0),
+			/* Data[4].ctlEdges[4].bChannel */ 0xFF,
+			/* Data[4].ctlEdges[5].bChannel */ 0xFF,
+			/* Data[4].ctlEdges[6].bChannel */ 0xFF,
+			/* Data[4].ctlEdges[7].bChannel */ 0xFF,
+		},
+
+		{
+			/* Data[5].ctlEdges[0].bChannel */ FREQ2FBIN(5190, 0),
+			/* Data[5].ctlEdges[1].bChannel */ FREQ2FBIN(5270, 0),
+			/* Data[5].ctlEdges[2].bChannel */ FREQ2FBIN(5310, 0),
+			/* Data[5].ctlEdges[3].bChannel */ FREQ2FBIN(5510, 0),
+			/* Data[5].ctlEdges[4].bChannel */ FREQ2FBIN(5590, 0),
+			/* Data[5].ctlEdges[5].bChannel */ FREQ2FBIN(5670, 0),
+			/* Data[5].ctlEdges[6].bChannel */ 0xFF,
+			/* Data[5].ctlEdges[7].bChannel */ 0xFF
+		},
+
+		{
+			/* Data[6].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
+			/* Data[6].ctlEdges[1].bChannel */ FREQ2FBIN(5200, 0),
+			/* Data[6].ctlEdges[2].bChannel */ FREQ2FBIN(5220, 0),
+			/* Data[6].ctlEdges[3].bChannel */ FREQ2FBIN(5260, 0),
+			/* Data[6].ctlEdges[4].bChannel */ FREQ2FBIN(5500, 0),
+			/* Data[6].ctlEdges[5].bChannel */ FREQ2FBIN(5600, 0),
+			/* Data[6].ctlEdges[6].bChannel */ FREQ2FBIN(5700, 0),
+			/* Data[6].ctlEdges[7].bChannel */ FREQ2FBIN(5745, 0)
+		},
+
+		{
+			/* Data[7].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
+			/* Data[7].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0),
+			/* Data[7].ctlEdges[2].bChannel */ FREQ2FBIN(5320, 0),
+			/* Data[7].ctlEdges[3].bChannel */ FREQ2FBIN(5500, 0),
+			/* Data[7].ctlEdges[4].bChannel */ FREQ2FBIN(5560, 0),
+			/* Data[7].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0),
+			/* Data[7].ctlEdges[6].bChannel */ FREQ2FBIN(5745, 0),
+			/* Data[7].ctlEdges[7].bChannel */ FREQ2FBIN(5825, 0)
+		},
+
+		{
+			/* Data[8].ctlEdges[0].bChannel */ FREQ2FBIN(5190, 0),
+			/* Data[8].ctlEdges[1].bChannel */ FREQ2FBIN(5230, 0),
+			/* Data[8].ctlEdges[2].bChannel */ FREQ2FBIN(5270, 0),
+			/* Data[8].ctlEdges[3].bChannel */ FREQ2FBIN(5510, 0),
+			/* Data[8].ctlEdges[4].bChannel */ FREQ2FBIN(5550, 0),
+			/* Data[8].ctlEdges[5].bChannel */ FREQ2FBIN(5670, 0),
+			/* Data[8].ctlEdges[6].bChannel */ FREQ2FBIN(5755, 0),
+			/* Data[8].ctlEdges[7].bChannel */ FREQ2FBIN(5795, 0)
+		}
+	 },
+	.ctlPowerData_5G = {
+		{
+			{
+				CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+				CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0),
+			}
+		},
+		{
+			{
+				CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+				CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0),
+			}
+		},
+		{
+			{
+				CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 1),
+				CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+			}
+		},
+		{
+			{
+				CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 0),
+				CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 0),
+			}
+		},
+		{
+			{
+				CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0),
+				CTL(60, 0), CTL(60, 0), CTL(60, 0), CTL(60, 0),
+			}
+		},
+		{
+			{
+				CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+				CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 0),
+			}
+		},
+		{
+			{
+				CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+				CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+			}
+		},
+		{
+			{
+				CTL(60, 1), CTL(60, 1), CTL(60, 0), CTL(60, 1),
+				CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0),
+			}
+		},
+		{
+			{
+				CTL(60, 1), CTL(60, 0), CTL(60, 1), CTL(60, 1),
+				CTL(60, 1), CTL(60, 1), CTL(60, 0), CTL(60, 1),
+			}
+		},
+	 }
+};
+
+
+static const struct ar9300_eeprom *ar9300_eep_templates[] = {
+	&ar9300_default,
+	&ar9300_x112,
+	&ar9300_h116,
+	&ar9300_h112,
+	&ar9300_x113,
+};
+
+static const struct ar9300_eeprom *ar9003_eeprom_struct_find_by_id(int id)
+{
+#define N_LOOP (sizeof(ar9300_eep_templates) / sizeof(ar9300_eep_templates[0]))
+	int it;
+
+	for (it = 0; it < N_LOOP; it++)
+		if (ar9300_eep_templates[it]->templateVersion == id)
+			return ar9300_eep_templates[it];
+	return NULL;
+#undef N_LOOP
+}
+
+
 static u16 ath9k_hw_fbin2freq(u8 fbin, bool is2GHz)
 {
-	if (fbin == AR9300_BCHAN_UNUSED)
+	if (fbin == AR5416_BCHAN_UNUSED)
 		return fbin;
 
 	return (u16) ((is2GHz) ? (2300 + fbin) : (4800 + 5 * fbin));
@@ -639,6 +2988,16 @@ static int ath9k_hw_ar9300_check_eeprom(
 	return 0;
 }
 
+static int interpolate(int x, int xa, int xb, int ya, int yb)
+{
+	int bf, factor, plus;
+
+	bf = 2 * (yb - ya) * (x - xa) / (xb - xa);
+	factor = bf / 2;
+	plus = bf % 2;
+	return ya + factor + plus;
+}
+
 static u32 ath9k_hw_ar9300_get_eeprom(struct ath_hw *ah,
 				      enum eeprom_param param)
 {
@@ -676,6 +3035,10 @@ static u32 ath9k_hw_ar9300_get_eeprom(st
 		return le32_to_cpu(pBase->swreg);
 	case EEP_PAPRD:
 		return !!(pBase->featureEnable & BIT(5));
+	case EEP_CHAIN_MASK_REDUCE:
+		return (pBase->miscConfiguration >> 0x3) & 0x1;
+	case EEP_ANT_DIV_CTL1:
+		return le32_to_cpu(eep->base_ext1.ant_div_control);
 	default:
 		return 0;
 	}
@@ -714,8 +3077,8 @@ static bool ar9300_read_eeprom(struct at
 	int i;
 
 	if ((address < 0) || ((address + count) / 2 > AR9300_EEPROM_SIZE - 1)) {
-		ath_print(common, ATH_DBG_EEPROM,
-			  "eeprom address not in range\n");
+		ath_dbg(common, ATH_DBG_EEPROM,
+			"eeprom address not in range\n");
 		return false;
 	}
 
@@ -746,11 +3109,41 @@ static bool ar9300_read_eeprom(struct at
 	return true;
 
 error:
-	ath_print(common, ATH_DBG_EEPROM,
-		  "unable to read eeprom region at offset %d\n", address);
+	ath_dbg(common, ATH_DBG_EEPROM,
+		"unable to read eeprom region at offset %d\n", address);
 	return false;
 }
 
+static bool ar9300_otp_read_word(struct ath_hw *ah, int addr, u32 *data)
+{
+	REG_READ(ah, AR9300_OTP_BASE + (4 * addr));
+
+	if (!ath9k_hw_wait(ah, AR9300_OTP_STATUS, AR9300_OTP_STATUS_TYPE,
+			   AR9300_OTP_STATUS_VALID, 1000))
+		return false;
+
+	*data = REG_READ(ah, AR9300_OTP_READ_DATA);
+	return true;
+}
+
+static bool ar9300_read_otp(struct ath_hw *ah, int address, u8 *buffer,
+			    int count)
+{
+	u32 data;
+	int i;
+
+	for (i = 0; i < count; i++) {
+		int offset = 8 * ((address - i) % 4);
+		if (!ar9300_otp_read_word(ah, (address - i) / 4, &data))
+			return false;
+
+		buffer[i] = (data >> offset) & 0xff;
+	}
+
+	return true;
+}
+
+
 static void ar9300_comp_hdr_unpack(u8 *best, int *code, int *reference,
 				   int *length, int *major, int *minor)
 {
@@ -801,17 +3194,15 @@ static bool ar9300_uncompress_block(stru
 		length &= 0xff;
 
 		if (length > 0 && spot >= 0 && spot+length <= mdataSize) {
-			ath_print(common, ATH_DBG_EEPROM,
-				  "Restore at %d: spot=%d "
-				  "offset=%d length=%d\n",
-				   it, spot, offset, length);
+			ath_dbg(common, ATH_DBG_EEPROM,
+				"Restore at %d: spot=%d offset=%d length=%d\n",
+				it, spot, offset, length);
 			memcpy(&mptr[spot], &block[it+2], length);
 			spot += length;
 		} else if (length > 0) {
-			ath_print(common, ATH_DBG_EEPROM,
-				  "Bad restore at %d: spot=%d "
-				  "offset=%d length=%d\n",
-				  it, spot, offset, length);
+			ath_dbg(common, ATH_DBG_EEPROM,
+				"Bad restore at %d: spot=%d offset=%d length=%d\n",
+				it, spot, offset, length);
 			return false;
 		}
 	}
@@ -827,45 +3218,80 @@ static int ar9300_compress_decision(stru
 {
 	struct ath_common *common = ath9k_hw_common(ah);
 	u8 *dptr;
+	const struct ar9300_eeprom *eep = NULL;
 
 	switch (code) {
 	case _CompressNone:
 		if (length != mdata_size) {
-			ath_print(common, ATH_DBG_EEPROM,
-				  "EEPROM structure size mismatch"
-				  "memory=%d eeprom=%d\n", mdata_size, length);
+			ath_dbg(common, ATH_DBG_EEPROM,
+				"EEPROM structure size mismatch memory=%d eeprom=%d\n",
+				mdata_size, length);
 			return -1;
 		}
 		memcpy(mptr, (u8 *) (word + COMP_HDR_LEN), length);
-		ath_print(common, ATH_DBG_EEPROM, "restored eeprom %d:"
-			  " uncompressed, length %d\n", it, length);
+		ath_dbg(common, ATH_DBG_EEPROM,
+			"restored eeprom %d: uncompressed, length %d\n",
+			it, length);
 		break;
 	case _CompressBlock:
 		if (reference == 0) {
 			dptr = mptr;
 		} else {
-			if (reference != 2) {
-				ath_print(common, ATH_DBG_EEPROM,
-					  "cant find reference eeprom"
-					  "struct %d\n", reference);
+			eep = ar9003_eeprom_struct_find_by_id(reference);
+			if (eep == NULL) {
+				ath_dbg(common, ATH_DBG_EEPROM,
+					"cant find reference eeprom struct %d\n",
+					reference);
 				return -1;
 			}
-			memcpy(mptr, &ar9300_default, mdata_size);
+			memcpy(mptr, eep, mdata_size);
 		}
-		ath_print(common, ATH_DBG_EEPROM,
-			  "restore eeprom %d: block, reference %d,"
-			  " length %d\n", it, reference, length);
+		ath_dbg(common, ATH_DBG_EEPROM,
+			"restore eeprom %d: block, reference %d, length %d\n",
+			it, reference, length);
 		ar9300_uncompress_block(ah, mptr, mdata_size,
 					(u8 *) (word + COMP_HDR_LEN), length);
 		break;
 	default:
-		ath_print(common, ATH_DBG_EEPROM, "unknown compression"
-			  " code %d\n", code);
+		ath_dbg(common, ATH_DBG_EEPROM,
+			"unknown compression code %d\n", code);
 		return -1;
 	}
 	return 0;
 }
 
+typedef bool (*eeprom_read_op)(struct ath_hw *ah, int address, u8 *buffer,
+			       int count);
+
+static bool ar9300_check_header(void *data)
+{
+	u32 *word = data;
+	return !(*word == 0 || *word == ~0);
+}
+
+static bool ar9300_check_eeprom_header(struct ath_hw *ah, eeprom_read_op read,
+				       int base_addr)
+{
+	u8 header[4];
+
+	if (!read(ah, base_addr, header, 4))
+		return false;
+
+	return ar9300_check_header(header);
+}
+
+static int ar9300_eeprom_restore_flash(struct ath_hw *ah, u8 *mptr,
+				       int mdata_size)
+{
+	struct ath_common *common = ath9k_hw_common(ah);
+	u16 *data = (u16 *) mptr;
+	int i;
+
+	for (i = 0; i < mdata_size / 2; i++, data++)
+		ath9k_hw_nvram_read(common, i, data);
+
+	return 0;
+}
 /*
  * Read the configuration data from the eeprom.
  * The data can be put in any specified memory buffer.
@@ -886,6 +3312,10 @@ static int ar9300_eeprom_restore_interna
 	int it;
 	u16 checksum, mchecksum;
 	struct ath_common *common = ath9k_hw_common(ah);
+	eeprom_read_op read;
+
+	if (ath9k_hw_use_flash(ah))
+		return ar9300_eeprom_restore_flash(ah, mptr, mdata_size);
 
 	word = kzalloc(2048, GFP_KERNEL);
 	if (!word)
@@ -893,43 +3323,73 @@ static int ar9300_eeprom_restore_interna
 
 	memcpy(mptr, &ar9300_default, mdata_size);
 
+	read = ar9300_read_eeprom;
+	if (AR_SREV_9485(ah))
+		cptr = AR9300_BASE_ADDR_4K;
+	else
+		cptr = AR9300_BASE_ADDR;
+	ath_dbg(common, ATH_DBG_EEPROM,
+		"Trying EEPROM accesss at Address 0x%04x\n", cptr);
+	if (ar9300_check_eeprom_header(ah, read, cptr))
+		goto found;
+
+	cptr = AR9300_BASE_ADDR_512;
+	ath_dbg(common, ATH_DBG_EEPROM,
+		"Trying EEPROM accesss at Address 0x%04x\n", cptr);
+	if (ar9300_check_eeprom_header(ah, read, cptr))
+		goto found;
+
+	read = ar9300_read_otp;
 	cptr = AR9300_BASE_ADDR;
+	ath_dbg(common, ATH_DBG_EEPROM,
+		"Trying OTP accesss at Address 0x%04x\n", cptr);
+	if (ar9300_check_eeprom_header(ah, read, cptr))
+		goto found;
+
+	cptr = AR9300_BASE_ADDR_512;
+	ath_dbg(common, ATH_DBG_EEPROM,
+		"Trying OTP accesss at Address 0x%04x\n", cptr);
+	if (ar9300_check_eeprom_header(ah, read, cptr))
+		goto found;
+
+	goto fail;
+
+found:
+	ath_dbg(common, ATH_DBG_EEPROM, "Found valid EEPROM data\n");
+
 	for (it = 0; it < MSTATE; it++) {
-		if (!ar9300_read_eeprom(ah, cptr, word, COMP_HDR_LEN))
+		if (!read(ah, cptr, word, COMP_HDR_LEN))
 			goto fail;
 
-		if ((word[0] == 0 && word[1] == 0 && word[2] == 0 &&
-		     word[3] == 0) || (word[0] == 0xff && word[1] == 0xff
-				       && word[2] == 0xff && word[3] == 0xff))
+		if (!ar9300_check_header(word))
 			break;
 
 		ar9300_comp_hdr_unpack(word, &code, &reference,
 				       &length, &major, &minor);
-		ath_print(common, ATH_DBG_EEPROM,
-			  "Found block at %x: code=%d ref=%d"
-			  "length=%d major=%d minor=%d\n", cptr, code,
-			  reference, length, major, minor);
-		if (length >= 1024) {
-			ath_print(common, ATH_DBG_EEPROM,
-				  "Skipping bad header\n");
+		ath_dbg(common, ATH_DBG_EEPROM,
+			"Found block at %x: code=%d ref=%d length=%d major=%d minor=%d\n",
+			cptr, code, reference, length, major, minor);
+		if ((!AR_SREV_9485(ah) && length >= 1024) ||
+		    (AR_SREV_9485(ah) && length > EEPROM_DATA_LEN_9485)) {
+			ath_dbg(common, ATH_DBG_EEPROM,
+				"Skipping bad header\n");
 			cptr -= COMP_HDR_LEN;
 			continue;
 		}
 
 		osize = length;
-		ar9300_read_eeprom(ah, cptr, word,
-				   COMP_HDR_LEN + osize + COMP_CKSUM_LEN);
+		read(ah, cptr, word, COMP_HDR_LEN + osize + COMP_CKSUM_LEN);
 		checksum = ar9300_comp_cksum(&word[COMP_HDR_LEN], length);
 		mchecksum = word[COMP_HDR_LEN + osize] |
 		    (word[COMP_HDR_LEN + osize + 1] << 8);
-		ath_print(common, ATH_DBG_EEPROM,
-			  "checksum %x %x\n", checksum, mchecksum);
+		ath_dbg(common, ATH_DBG_EEPROM,
+			"checksum %x %x\n", checksum, mchecksum);
 		if (checksum == mchecksum) {
 			ar9300_compress_decision(ah, it, code, reference, mptr,
 						 word, length, mdata_size);
 		} else {
-			ath_print(common, ATH_DBG_EEPROM,
-				  "skipping block with bad checksum\n");
+			ath_dbg(common, ATH_DBG_EEPROM,
+				"skipping block with bad checksum\n");
 		}
 		cptr -= (COMP_HDR_LEN + osize + COMP_CKSUM_LEN);
 	}
@@ -970,18 +3430,6 @@ static int ath9k_hw_ar9300_get_eeprom_re
 	return 0;
 }
 
-static u8 ath9k_hw_ar9300_get_num_ant_config(struct ath_hw *ah,
-					     enum ath9k_hal_freq_band freq_band)
-{
-	return 1;
-}
-
-static u32 ath9k_hw_ar9300_get_eeprom_antenna_cfg(struct ath_hw *ah,
-						  struct ath9k_channel *chan)
-{
-	return -EINVAL;
-}
-
 static s32 ar9003_hw_xpa_bias_level_get(struct ath_hw *ah, bool is2ghz)
 {
 	struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
@@ -995,9 +3443,15 @@ static s32 ar9003_hw_xpa_bias_level_get(
 static void ar9003_hw_xpa_bias_level_apply(struct ath_hw *ah, bool is2ghz)
 {
 	int bias = ar9003_hw_xpa_bias_level_get(ah, is2ghz);
-	REG_RMW_FIELD(ah, AR_CH0_TOP, AR_CH0_TOP_XPABIASLVL, (bias & 0x3));
-	REG_RMW_FIELD(ah, AR_CH0_THERM, AR_CH0_THERM_SPARE,
-		      ((bias >> 2) & 0x3));
+
+	if (AR_SREV_9485(ah))
+		REG_RMW_FIELD(ah, AR_CH0_TOP2, AR_CH0_TOP2_XPABIASLVL, bias);
+	else {
+		REG_RMW_FIELD(ah, AR_CH0_TOP, AR_CH0_TOP_XPABIASLVL, bias);
+		REG_RMW_FIELD(ah, AR_CH0_THERM, AR_CH0_THERM_XPABIASLVL_MSB,
+			      bias >> 2);
+		REG_RMW_FIELD(ah, AR_CH0_THERM, AR_CH0_THERM_XPASHORT2GND, 1);
+	}
 }
 
 static u32 ar9003_hw_ant_ctrl_common_get(struct ath_hw *ah, bool is2ghz)
@@ -1052,11 +3506,25 @@ static void ar9003_hw_ant_ctrl_apply(str
 	value = ar9003_hw_ant_ctrl_chain_get(ah, 0, is2ghz);
 	REG_RMW_FIELD(ah, AR_PHY_SWITCH_CHAIN_0, AR_SWITCH_TABLE_ALL, value);
 
-	value = ar9003_hw_ant_ctrl_chain_get(ah, 1, is2ghz);
-	REG_RMW_FIELD(ah, AR_PHY_SWITCH_CHAIN_1, AR_SWITCH_TABLE_ALL, value);
+	if (!AR_SREV_9485(ah)) {
+		value = ar9003_hw_ant_ctrl_chain_get(ah, 1, is2ghz);
+		REG_RMW_FIELD(ah, AR_PHY_SWITCH_CHAIN_1, AR_SWITCH_TABLE_ALL,
+			      value);
 
-	value = ar9003_hw_ant_ctrl_chain_get(ah, 2, is2ghz);
-	REG_RMW_FIELD(ah, AR_PHY_SWITCH_CHAIN_2, AR_SWITCH_TABLE_ALL, value);
+		value = ar9003_hw_ant_ctrl_chain_get(ah, 2, is2ghz);
+		REG_RMW_FIELD(ah, AR_PHY_SWITCH_CHAIN_2, AR_SWITCH_TABLE_ALL,
+			      value);
+	}
+
+	if (AR_SREV_9485(ah)) {
+		value = ath9k_hw_ar9300_get_eeprom(ah, EEP_ANT_DIV_CTL1);
+		REG_RMW_FIELD(ah, AR_PHY_MC_GAIN_CTRL, AR_ANT_DIV_CTRL_ALL,
+			      value);
+		REG_RMW_FIELD(ah, AR_PHY_MC_GAIN_CTRL, AR_ANT_DIV_ENABLE,
+			      value >> 6);
+		REG_RMW_FIELD(ah, AR_PHY_CCK_DETECT, AR_FAST_DIV_ENABLE,
+			      value >> 7);
+	}
 }
 
 static void ar9003_hw_drive_strength_apply(struct ath_hw *ah)
@@ -1100,28 +3568,177 @@ static void ar9003_hw_drive_strength_app
 	REG_WRITE(ah, AR_PHY_65NM_CH0_BIAS4, reg);
 }
 
+static u16 ar9003_hw_atten_chain_get(struct ath_hw *ah, int chain,
+				     struct ath9k_channel *chan)
+{
+	int f[3], t[3];
+	u16 value;
+	struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
+
+	if (chain >= 0 && chain < 3) {
+		if (IS_CHAN_2GHZ(chan))
+			return eep->modalHeader2G.xatten1DB[chain];
+		else if (eep->base_ext2.xatten1DBLow[chain] != 0) {
+			t[0] = eep->base_ext2.xatten1DBLow[chain];
+			f[0] = 5180;
+			t[1] = eep->modalHeader5G.xatten1DB[chain];
+			f[1] = 5500;
+			t[2] = eep->base_ext2.xatten1DBHigh[chain];
+			f[2] = 5785;
+			value = ar9003_hw_power_interpolate((s32) chan->channel,
+							    f, t, 3);
+			return value;
+		} else
+			return eep->modalHeader5G.xatten1DB[chain];
+	}
+
+	return 0;
+}
+
+
+static u16 ar9003_hw_atten_chain_get_margin(struct ath_hw *ah, int chain,
+					    struct ath9k_channel *chan)
+{
+	int f[3], t[3];
+	u16 value;
+	struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
+
+	if (chain >= 0 && chain < 3) {
+		if (IS_CHAN_2GHZ(chan))
+			return eep->modalHeader2G.xatten1Margin[chain];
+		else if (eep->base_ext2.xatten1MarginLow[chain] != 0) {
+			t[0] = eep->base_ext2.xatten1MarginLow[chain];
+			f[0] = 5180;
+			t[1] = eep->modalHeader5G.xatten1Margin[chain];
+			f[1] = 5500;
+			t[2] = eep->base_ext2.xatten1MarginHigh[chain];
+			f[2] = 5785;
+			value = ar9003_hw_power_interpolate((s32) chan->channel,
+							    f, t, 3);
+			return value;
+		} else
+			return eep->modalHeader5G.xatten1Margin[chain];
+	}
+
+	return 0;
+}
+
+static void ar9003_hw_atten_apply(struct ath_hw *ah, struct ath9k_channel *chan)
+{
+	int i;
+	u16 value;
+	unsigned long ext_atten_reg[3] = {AR_PHY_EXT_ATTEN_CTL_0,
+					  AR_PHY_EXT_ATTEN_CTL_1,
+					  AR_PHY_EXT_ATTEN_CTL_2,
+					 };
+
+	/* Test value. if 0 then attenuation is unused. Don't load anything. */
+	for (i = 0; i < 3; i++) {
+		value = ar9003_hw_atten_chain_get(ah, i, chan);
+		REG_RMW_FIELD(ah, ext_atten_reg[i],
+			      AR_PHY_EXT_ATTEN_CTL_XATTEN1_DB, value);
+
+		value = ar9003_hw_atten_chain_get_margin(ah, i, chan);
+		REG_RMW_FIELD(ah, ext_atten_reg[i],
+			      AR_PHY_EXT_ATTEN_CTL_XATTEN1_MARGIN, value);
+	}
+}
+
+static bool is_pmu_set(struct ath_hw *ah, u32 pmu_reg, int pmu_set)
+{
+	int timeout = 100;
+
+	while (pmu_set != REG_READ(ah, pmu_reg)) {
+		if (timeout-- == 0)
+			return false;
+		REG_WRITE(ah, pmu_reg, pmu_set);
+		udelay(10);
+	}
+
+	return true;
+}
+
 static void ar9003_hw_internal_regulator_apply(struct ath_hw *ah)
 {
 	int internal_regulator =
 		ath9k_hw_ar9300_get_eeprom(ah, EEP_INTERNAL_REGULATOR);
 
 	if (internal_regulator) {
-		/* Internal regulator is ON. Write swreg register. */
-		int swreg = ath9k_hw_ar9300_get_eeprom(ah, EEP_SWREG);
-		REG_WRITE(ah, AR_RTC_REG_CONTROL1,
-		REG_READ(ah, AR_RTC_REG_CONTROL1) &
-			 (~AR_RTC_REG_CONTROL1_SWREG_PROGRAM));
-		REG_WRITE(ah, AR_RTC_REG_CONTROL0, swreg);
-		/* Set REG_CONTROL1.SWREG_PROGRAM */
-		REG_WRITE(ah, AR_RTC_REG_CONTROL1,
-			  REG_READ(ah,
-				   AR_RTC_REG_CONTROL1) |
-				   AR_RTC_REG_CONTROL1_SWREG_PROGRAM);
+		if (AR_SREV_9485(ah)) {
+			int reg_pmu_set;
+
+			reg_pmu_set = REG_READ(ah, AR_PHY_PMU2) & ~AR_PHY_PMU2_PGM;
+			REG_WRITE(ah, AR_PHY_PMU2, reg_pmu_set);
+			if (!is_pmu_set(ah, AR_PHY_PMU2, reg_pmu_set))
+				return;
+
+			reg_pmu_set = (5 << 1) | (7 << 4) | (1 << 8) |
+				      (7 << 14) | (6 << 17) | (1 << 20) |
+				      (3 << 24) | (1 << 28);
+
+			REG_WRITE(ah, AR_PHY_PMU1, reg_pmu_set);
+			if (!is_pmu_set(ah, AR_PHY_PMU1, reg_pmu_set))
+				return;
+
+			reg_pmu_set = (REG_READ(ah, AR_PHY_PMU2) & ~0xFFC00000)
+					| (4 << 26);
+			REG_WRITE(ah, AR_PHY_PMU2, reg_pmu_set);
+			if (!is_pmu_set(ah, AR_PHY_PMU2, reg_pmu_set))
+				return;
+
+			reg_pmu_set = (REG_READ(ah, AR_PHY_PMU2) & ~0x00200000)
+					| (1 << 21);
+			REG_WRITE(ah, AR_PHY_PMU2, reg_pmu_set);
+			if (!is_pmu_set(ah, AR_PHY_PMU2, reg_pmu_set))
+				return;
+		} else {
+			/* Internal regulator is ON. Write swreg register. */
+			int swreg = ath9k_hw_ar9300_get_eeprom(ah, EEP_SWREG);
+			REG_WRITE(ah, AR_RTC_REG_CONTROL1,
+				  REG_READ(ah, AR_RTC_REG_CONTROL1) &
+				  (~AR_RTC_REG_CONTROL1_SWREG_PROGRAM));
+			REG_WRITE(ah, AR_RTC_REG_CONTROL0, swreg);
+			/* Set REG_CONTROL1.SWREG_PROGRAM */
+			REG_WRITE(ah, AR_RTC_REG_CONTROL1,
+				  REG_READ(ah,
+					   AR_RTC_REG_CONTROL1) |
+					   AR_RTC_REG_CONTROL1_SWREG_PROGRAM);
+		}
 	} else {
-		REG_WRITE(ah, AR_RTC_SLEEP_CLK,
-			  (REG_READ(ah,
-				    AR_RTC_SLEEP_CLK) |
-				    AR_RTC_FORCE_SWREG_PRD));
+		if (AR_SREV_9485(ah)) {
+			REG_RMW_FIELD(ah, AR_PHY_PMU2, AR_PHY_PMU2_PGM, 0);
+			while (REG_READ_FIELD(ah, AR_PHY_PMU2,
+					      AR_PHY_PMU2_PGM))
+				udelay(10);
+
+			REG_RMW_FIELD(ah, AR_PHY_PMU1, AR_PHY_PMU1_PWD, 0x1);
+			while (!REG_READ_FIELD(ah, AR_PHY_PMU1,
+					       AR_PHY_PMU1_PWD))
+				udelay(10);
+			REG_RMW_FIELD(ah, AR_PHY_PMU2, AR_PHY_PMU2_PGM, 0x1);
+			while (!REG_READ_FIELD(ah, AR_PHY_PMU2,
+					      AR_PHY_PMU2_PGM))
+				udelay(10);
+		} else
+			REG_WRITE(ah, AR_RTC_SLEEP_CLK,
+				  (REG_READ(ah,
+				   AR_RTC_SLEEP_CLK) |
+				   AR_RTC_FORCE_SWREG_PRD));
+	}
+
+}
+
+static void ar9003_hw_apply_tuning_caps(struct ath_hw *ah)
+{
+	struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
+	u8 tuning_caps_param = eep->baseEepHeader.params_for_tuning_caps[0];
+
+	if (eep->baseEepHeader.featureEnable & 0x40) {
+		tuning_caps_param &= 0x7f;
+		REG_RMW_FIELD(ah, AR_CH0_XTAL, AR_CH0_XTAL_CAPINDAC,
+			      tuning_caps_param);
+		REG_RMW_FIELD(ah, AR_CH0_XTAL, AR_CH0_XTAL_CAPOUTDAC,
+			      tuning_caps_param);
 	}
 }
 
@@ -1131,7 +3748,10 @@ static void ath9k_hw_ar9300_set_board_va
 	ar9003_hw_xpa_bias_level_apply(ah, IS_CHAN_2GHZ(chan));
 	ar9003_hw_ant_ctrl_apply(ah, IS_CHAN_2GHZ(chan));
 	ar9003_hw_drive_strength_apply(ah);
+	ar9003_hw_atten_apply(ah, chan);
 	ar9003_hw_internal_regulator_apply(ah);
+	if (AR_SREV_9485(ah))
+		ar9003_hw_apply_tuning_caps(ah);
 }
 
 static void ath9k_hw_ar9300_set_addac(struct ath_hw *ah,
@@ -1192,7 +3812,7 @@ static int ar9003_hw_power_interpolate(i
 			if (hx == lx)
 				y = ly;
 			else	/* interpolate  */
-				y = ly + (((x - lx) * (hy - ly)) / (hx - lx));
+				y = interpolate(x, lx, hx, ly, hy);
 		} else		/* only low is good, use it */
 			y = ly;
 	} else if (hhave)	/* only high is good, use it */
@@ -1561,22 +4181,9 @@ static void ar9003_hw_set_target_power_e
 	    ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_23, freq,
 					      is2GHz) + ht40PowerIncForPdadc;
 
-	while (i < ar9300RateSize) {
-		ath_print(common, ATH_DBG_EEPROM,
-			  "TPC[%02d] 0x%08x ", i, targetPowerValT2[i]);
-		i++;
-
-		ath_print(common, ATH_DBG_EEPROM,
-			  "TPC[%02d] 0x%08x ", i, targetPowerValT2[i]);
-		i++;
-
-		ath_print(common, ATH_DBG_EEPROM,
-			  "TPC[%02d] 0x%08x ", i, targetPowerValT2[i]);
-		i++;
-
-		ath_print(common, ATH_DBG_EEPROM,
-			  "TPC[%02d] 0x%08x\n", i, targetPowerValT2[i]);
-		i++;
+	for (i = 0; i < ar9300RateSize; i++) {
+		ath_dbg(common, ATH_DBG_EEPROM,
+			"TPC[%02d] 0x%08x\n", i, targetPowerValT2[i]);
 	}
 }
 
@@ -1595,18 +4202,17 @@ static int ar9003_hw_cal_pier_get(struct
 	struct ath_common *common = ath9k_hw_common(ah);
 
 	if (ichain >= AR9300_MAX_CHAINS) {
-		ath_print(common, ATH_DBG_EEPROM,
-			  "Invalid chain index, must be less than %d\n",
-			  AR9300_MAX_CHAINS);
+		ath_dbg(common, ATH_DBG_EEPROM,
+			"Invalid chain index, must be less than %d\n",
+			AR9300_MAX_CHAINS);
 		return -1;
 	}
 
 	if (mode) {		/* 5GHz */
 		if (ipier >= AR9300_NUM_5G_CAL_PIERS) {
-			ath_print(common, ATH_DBG_EEPROM,
-				  "Invalid 5GHz cal pier index, must "
-				  "be less than %d\n",
-				  AR9300_NUM_5G_CAL_PIERS);
+			ath_dbg(common, ATH_DBG_EEPROM,
+				"Invalid 5GHz cal pier index, must be less than %d\n",
+				AR9300_NUM_5G_CAL_PIERS);
 			return -1;
 		}
 		pCalPier = &(eep->calFreqPier5G[ipier]);
@@ -1614,9 +4220,9 @@ static int ar9003_hw_cal_pier_get(struct
 		is2GHz = 0;
 	} else {
 		if (ipier >= AR9300_NUM_2G_CAL_PIERS) {
-			ath_print(common, ATH_DBG_EEPROM,
-				  "Invalid 2GHz cal pier index, must "
-				  "be less than %d\n", AR9300_NUM_2G_CAL_PIERS);
+			ath_dbg(common, ATH_DBG_EEPROM,
+				"Invalid 2GHz cal pier index, must be less than %d\n",
+				AR9300_NUM_2G_CAL_PIERS);
 			return -1;
 		}
 
@@ -1640,27 +4246,32 @@ static int ar9003_hw_power_control_overr
 {
 	int tempSlope = 0;
 	struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
+	int f[3], t[3];
 
 	REG_RMW(ah, AR_PHY_TPC_11_B0,
 		(correction[0] << AR_PHY_TPC_OLPC_GAIN_DELTA_S),
 		AR_PHY_TPC_OLPC_GAIN_DELTA);
-	REG_RMW(ah, AR_PHY_TPC_11_B1,
-		(correction[1] << AR_PHY_TPC_OLPC_GAIN_DELTA_S),
-		AR_PHY_TPC_OLPC_GAIN_DELTA);
-	REG_RMW(ah, AR_PHY_TPC_11_B2,
-		(correction[2] << AR_PHY_TPC_OLPC_GAIN_DELTA_S),
-		AR_PHY_TPC_OLPC_GAIN_DELTA);
+	if (ah->caps.tx_chainmask & BIT(1))
+		REG_RMW(ah, AR_PHY_TPC_11_B1,
+			(correction[1] << AR_PHY_TPC_OLPC_GAIN_DELTA_S),
+			AR_PHY_TPC_OLPC_GAIN_DELTA);
+	if (ah->caps.tx_chainmask & BIT(2))
+		REG_RMW(ah, AR_PHY_TPC_11_B2,
+			(correction[2] << AR_PHY_TPC_OLPC_GAIN_DELTA_S),
+			AR_PHY_TPC_OLPC_GAIN_DELTA);
 
 	/* enable open loop power control on chip */
 	REG_RMW(ah, AR_PHY_TPC_6_B0,
 		(3 << AR_PHY_TPC_6_ERROR_EST_MODE_S),
 		AR_PHY_TPC_6_ERROR_EST_MODE);
-	REG_RMW(ah, AR_PHY_TPC_6_B1,
-		(3 << AR_PHY_TPC_6_ERROR_EST_MODE_S),
-		AR_PHY_TPC_6_ERROR_EST_MODE);
-	REG_RMW(ah, AR_PHY_TPC_6_B2,
-		(3 << AR_PHY_TPC_6_ERROR_EST_MODE_S),
-		AR_PHY_TPC_6_ERROR_EST_MODE);
+	if (ah->caps.tx_chainmask & BIT(1))
+		REG_RMW(ah, AR_PHY_TPC_6_B1,
+			(3 << AR_PHY_TPC_6_ERROR_EST_MODE_S),
+			AR_PHY_TPC_6_ERROR_EST_MODE);
+	if (ah->caps.tx_chainmask & BIT(2))
+		REG_RMW(ah, AR_PHY_TPC_6_B2,
+			(3 << AR_PHY_TPC_6_ERROR_EST_MODE_S),
+			AR_PHY_TPC_6_ERROR_EST_MODE);
 
 	/*
 	 * enable temperature compensation
@@ -1668,7 +4279,16 @@ static int ar9003_hw_power_control_overr
 	 */
 	if (frequency < 4000)
 		tempSlope = eep->modalHeader2G.tempSlope;
-	else
+	else if (eep->base_ext2.tempSlopeLow != 0) {
+		t[0] = eep->base_ext2.tempSlopeLow;
+		f[0] = 5180;
+		t[1] = eep->modalHeader5G.tempSlope;
+		f[1] = 5500;
+		t[2] = eep->base_ext2.tempSlopeHigh;
+		f[2] = 5785;
+		tempSlope = ar9003_hw_power_interpolate((s32) frequency,
+							f, t, 3);
+	} else
 		tempSlope = eep->modalHeader5G.tempSlope;
 
 	REG_RMW_FIELD(ah, AR_PHY_TPC_19, AR_PHY_TPC_19_ALPHA_THERM, tempSlope);
@@ -1756,11 +4376,11 @@ static int ar9003_hw_calibration_apply(s
 
 	/* interpolate  */
 	for (ichain = 0; ichain < AR9300_MAX_CHAINS; ichain++) {
-		ath_print(common, ATH_DBG_EEPROM,
-			  "ch=%d f=%d low=%d %d h=%d %d\n",
-			  ichain, frequency, lfrequency[ichain],
-			  lcorrection[ichain], hfrequency[ichain],
-			  hcorrection[ichain]);
+		ath_dbg(common, ATH_DBG_EEPROM,
+			"ch=%d f=%d low=%d %d h=%d %d\n",
+			ichain, frequency, lfrequency[ichain],
+			lcorrection[ichain], hfrequency[ichain],
+			hcorrection[ichain]);
 		/* they're the same, so just pick one */
 		if (hfrequency[ichain] == lfrequency[ichain]) {
 			correction[ichain] = lcorrection[ichain];
@@ -1772,25 +4392,23 @@ static int ar9003_hw_calibration_apply(s
 			/* so is the high frequency, interpolate */
 			if (hfrequency[ichain] - frequency < 1000) {
 
-				correction[ichain] = lcorrection[ichain] +
-				    (((frequency - lfrequency[ichain]) *
-				      (hcorrection[ichain] -
-				       lcorrection[ichain])) /
-				     (hfrequency[ichain] - lfrequency[ichain]));
+				correction[ichain] = interpolate(frequency,
+						lfrequency[ichain],
+						hfrequency[ichain],
+						lcorrection[ichain],
+						hcorrection[ichain]);
 
-				temperature[ichain] = ltemperature[ichain] +
-				    (((frequency - lfrequency[ichain]) *
-				      (htemperature[ichain] -
-				       ltemperature[ichain])) /
-				     (hfrequency[ichain] - lfrequency[ichain]));
+				temperature[ichain] = interpolate(frequency,
+						lfrequency[ichain],
+						hfrequency[ichain],
+						ltemperature[ichain],
+						htemperature[ichain]);
 
-				voltage[ichain] =
-				    lvoltage[ichain] +
-				    (((frequency -
-				       lfrequency[ichain]) * (hvoltage[ichain] -
-							      lvoltage[ichain]))
-				     / (hfrequency[ichain] -
-					lfrequency[ichain]));
+				voltage[ichain] = interpolate(frequency,
+						lfrequency[ichain],
+						hfrequency[ichain],
+						lvoltage[ichain],
+						hvoltage[ichain]);
 			}
 			/* only low is good, use it */
 			else {
@@ -1814,9 +4432,9 @@ static int ar9003_hw_calibration_apply(s
 	ar9003_hw_power_control_override(ah, frequency, correction, voltage,
 					 temperature);
 
-	ath_print(common, ATH_DBG_EEPROM,
-		  "for frequency=%d, calibration correction = %d %d %d\n",
-		  frequency, correction[0], correction[1], correction[2]);
+	ath_dbg(common, ATH_DBG_EEPROM,
+		"for frequency=%d, calibration correction = %d %d %d\n",
+		frequency, correction[0], correction[1], correction[2]);
 
 	return 0;
 }
@@ -1858,7 +4476,7 @@ static u16 ar9003_hw_get_indirect_edge_p
 			return CTL_EDGE_TPOWER(ctl_5g[idx].ctlEdges[edge - 1]);
 	}
 
-	return AR9300_MAX_RATE_POWER;
+	return MAX_RATE_POWER;
 }
 
 /*
@@ -1867,7 +4485,7 @@ static u16 ar9003_hw_get_indirect_edge_p
 static u16 ar9003_hw_get_max_edge_power(struct ar9300_eeprom *eep,
 					u16 freq, int idx, bool is2GHz)
 {
-	u16 twiceMaxEdgePower = AR9300_MAX_RATE_POWER;
+	u16 twiceMaxEdgePower = MAX_RATE_POWER;
 	u8 *ctl_freqbin = is2GHz ?
 		&eep->ctl_freqbin_2G[idx][0] :
 		&eep->ctl_freqbin_5G[idx][0];
@@ -1877,7 +4495,7 @@ static u16 ar9003_hw_get_max_edge_power(
 
 	/* Get the edge power */
 	for (edge = 0;
-	     (edge < num_edges) && (ctl_freqbin[edge] != AR9300_BCHAN_UNUSED);
+	     (edge < num_edges) && (ctl_freqbin[edge] != AR5416_BCHAN_UNUSED);
 	     edge++) {
 		/*
 		 * If there's an exact channel match or an inband flag set
@@ -1915,21 +4533,23 @@ static void ar9003_hw_set_power_per_rate
 	struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
 	struct ath_common *common = ath9k_hw_common(ah);
 	struct ar9300_eeprom *pEepData = &ah->eeprom.ar9300_eep;
-	u16 twiceMaxEdgePower = AR9300_MAX_RATE_POWER;
+	u16 twiceMaxEdgePower = MAX_RATE_POWER;
 	static const u16 tpScaleReductionTable[5] = {
-		0, 3, 6, 9, AR9300_MAX_RATE_POWER
+		0, 3, 6, 9, MAX_RATE_POWER
 	};
 	int i;
 	int16_t  twiceLargestAntenna;
 	u16 scaledPower = 0, minCtlPower, maxRegAllowedPower;
-	u16 ctlModesFor11a[] = {
+	static const u16 ctlModesFor11a[] = {
 		CTL_11A, CTL_5GHT20, CTL_11A_EXT, CTL_5GHT40
 	};
-	u16 ctlModesFor11g[] = {
+	static const u16 ctlModesFor11g[] = {
 		CTL_11B, CTL_11G, CTL_2GHT20, CTL_11B_EXT,
 		CTL_11G_EXT, CTL_2GHT40
 	};
-	u16 numCtlModes, *pCtlMode, ctlMode, freq;
+	u16 numCtlModes;
+	const u16 *pCtlMode;
+	u16 ctlMode, freq;
 	struct chan_centers centers;
 	u8 *ctlIndex;
 	u8 ctlNum;
@@ -2019,11 +4639,10 @@ static void ar9003_hw_set_power_per_rate
 		else
 			freq = centers.ctl_center;
 
-		ath_print(common, ATH_DBG_REGULATORY,
-			  "LOOP-Mode ctlMode %d < %d, isHt40CtlMode %d, "
-			  "EXT_ADDITIVE %d\n",
-			  ctlMode, numCtlModes, isHt40CtlMode,
-			  (pCtlMode[ctlMode] & EXT_ADDITIVE));
+		ath_dbg(common, ATH_DBG_REGULATORY,
+			"LOOP-Mode ctlMode %d < %d, isHt40CtlMode %d, EXT_ADDITIVE %d\n",
+			ctlMode, numCtlModes, isHt40CtlMode,
+			(pCtlMode[ctlMode] & EXT_ADDITIVE));
 
 		/* walk through each CTL index stored in EEPROM */
 		if (is2ghz) {
@@ -2035,12 +4654,10 @@ static void ar9003_hw_set_power_per_rate
 		}
 
 		for (i = 0; (i < ctlNum) && ctlIndex[i]; i++) {
-			ath_print(common, ATH_DBG_REGULATORY,
-				  "LOOP-Ctlidx %d: cfgCtl 0x%2.2x "
-				  "pCtlMode 0x%2.2x ctlIndex 0x%2.2x "
-				  "chan %dn",
-				  i, cfgCtl, pCtlMode[ctlMode], ctlIndex[i],
-				  chan->channel);
+			ath_dbg(common, ATH_DBG_REGULATORY,
+				"LOOP-Ctlidx %d: cfgCtl 0x%2.2x pCtlMode 0x%2.2x ctlIndex 0x%2.2x chan %d\n",
+				i, cfgCtl, pCtlMode[ctlMode], ctlIndex[i],
+				chan->channel);
 
 				/*
 				 * compare test group from regulatory
@@ -2079,11 +4696,10 @@ static void ar9003_hw_set_power_per_rate
 
 			minCtlPower = (u8)min(twiceMaxEdgePower, scaledPower);
 
-			ath_print(common, ATH_DBG_REGULATORY,
-				  "SEL-Min ctlMode %d pCtlMode %d 2xMaxEdge %d "
-				  "sP %d minCtlPwr %d\n",
-				  ctlMode, pCtlMode[ctlMode], twiceMaxEdgePower,
-				  scaledPower, minCtlPower);
+			ath_dbg(common, ATH_DBG_REGULATORY,
+				"SEL-Min ctlMode %d pCtlMode %d 2xMaxEdge %d sP %d minCtlPwr %d\n",
+				ctlMode, pCtlMode[ctlMode], twiceMaxEdgePower,
+				scaledPower, minCtlPower);
 
 			/* Apply ctl mode to correct target power set */
 			switch (pCtlMode[ctlMode]) {
@@ -2130,40 +4746,101 @@ static void ar9003_hw_set_power_per_rate
 	} /* end ctl mode checking */
 }
 
+static inline u8 mcsidx_to_tgtpwridx(unsigned int mcs_idx, u8 base_pwridx)
+{
+	u8 mod_idx = mcs_idx % 8;
+
+	if (mod_idx <= 3)
+		return mod_idx ? (base_pwridx + 1) : base_pwridx;
+	else
+		return base_pwridx + 4 * (mcs_idx / 8) + mod_idx - 2;
+}
+
 static void ath9k_hw_ar9300_set_txpower(struct ath_hw *ah,
 					struct ath9k_channel *chan, u16 cfgCtl,
 					u8 twiceAntennaReduction,
 					u8 twiceMaxRegulatoryPower,
-					u8 powerLimit)
+					u8 powerLimit, bool test)
 {
+	struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
 	struct ath_common *common = ath9k_hw_common(ah);
+	struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
+	struct ar9300_modal_eep_header *modal_hdr;
 	u8 targetPowerValT2[ar9300RateSize];
-	unsigned int i = 0;
+	u8 target_power_val_t2_eep[ar9300RateSize];
+	unsigned int i = 0, paprd_scale_factor = 0;
+	u8 pwr_idx, min_pwridx = 0;
 
 	ar9003_hw_set_target_power_eeprom(ah, chan->channel, targetPowerValT2);
+
+	if (ah->eep_ops->get_eeprom(ah, EEP_PAPRD)) {
+		if (IS_CHAN_2GHZ(chan))
+			modal_hdr = &eep->modalHeader2G;
+		else
+			modal_hdr = &eep->modalHeader5G;
+
+		ah->paprd_ratemask =
+			le32_to_cpu(modal_hdr->papdRateMaskHt20) &
+			AR9300_PAPRD_RATE_MASK;
+
+		ah->paprd_ratemask_ht40 =
+			le32_to_cpu(modal_hdr->papdRateMaskHt40) &
+			AR9300_PAPRD_RATE_MASK;
+
+		paprd_scale_factor = ar9003_get_paprd_scale_factor(ah, chan);
+		min_pwridx = IS_CHAN_HT40(chan) ? ALL_TARGET_HT40_0_8_16 :
+						  ALL_TARGET_HT20_0_8_16;
+
+		if (!ah->paprd_table_write_done) {
+			memcpy(target_power_val_t2_eep, targetPowerValT2,
+			       sizeof(targetPowerValT2));
+			for (i = 0; i < 24; i++) {
+				pwr_idx = mcsidx_to_tgtpwridx(i, min_pwridx);
+				if (ah->paprd_ratemask & (1 << i)) {
+					if (targetPowerValT2[pwr_idx] &&
+					    targetPowerValT2[pwr_idx] ==
+					    target_power_val_t2_eep[pwr_idx])
+						targetPowerValT2[pwr_idx] -=
+							paprd_scale_factor;
+				}
+			}
+		}
+		memcpy(target_power_val_t2_eep, targetPowerValT2,
+		       sizeof(targetPowerValT2));
+	}
+
 	ar9003_hw_set_power_per_rate_table(ah, chan,
 					   targetPowerValT2, cfgCtl,
 					   twiceAntennaReduction,
 					   twiceMaxRegulatoryPower,
 					   powerLimit);
 
-	while (i < ar9300RateSize) {
-		ath_print(common, ATH_DBG_EEPROM,
-			  "TPC[%02d] 0x%08x ", i, targetPowerValT2[i]);
-		i++;
-		ath_print(common, ATH_DBG_EEPROM,
-			  "TPC[%02d] 0x%08x ", i, targetPowerValT2[i]);
-		i++;
-		ath_print(common, ATH_DBG_EEPROM,
-			  "TPC[%02d] 0x%08x ", i, targetPowerValT2[i]);
-		i++;
-		ath_print(common, ATH_DBG_EEPROM,
-			  "TPC[%02d] 0x%08x\n\n", i, targetPowerValT2[i]);
-		i++;
+	if (ah->eep_ops->get_eeprom(ah, EEP_PAPRD)) {
+		for (i = 0; i < ar9300RateSize; i++) {
+			if ((ah->paprd_ratemask & (1 << i)) &&
+			    (abs(targetPowerValT2[i] -
+				target_power_val_t2_eep[i]) >
+			    paprd_scale_factor)) {
+				ah->paprd_ratemask &= ~(1 << i);
+				ath_dbg(common, ATH_DBG_EEPROM,
+					"paprd disabled for mcs %d\n", i);
+			}
+		}
 	}
 
-	/* Write target power array to registers */
-	ar9003_hw_tx_power_regwrite(ah, targetPowerValT2);
+	regulatory->max_power_level = 0;
+	for (i = 0; i < ar9300RateSize; i++) {
+		if (targetPowerValT2[i] > regulatory->max_power_level)
+			regulatory->max_power_level = targetPowerValT2[i];
+	}
+
+	if (test)
+		return;
+
+	for (i = 0; i < ar9300RateSize; i++) {
+		ath_dbg(common, ATH_DBG_EEPROM,
+			"TPC[%02d] 0x%08x\n", i, targetPowerValT2[i]);
+	}
 
 	/*
 	 * This is the TX power we send back to driver core,
@@ -2183,8 +4860,24 @@ static void ath9k_hw_ar9300_set_txpower(
 		i = ALL_TARGET_HT20_0_8_16; /* ht20 */
 
 	ah->txpower_limit = targetPowerValT2[i];
+	regulatory->max_power_level = targetPowerValT2[i];
 
+	/* Write target power array to registers */
+	ar9003_hw_tx_power_regwrite(ah, targetPowerValT2);
 	ar9003_hw_calibration_apply(ah, chan->channel);
+
+	if (IS_CHAN_2GHZ(chan)) {
+		if (IS_CHAN_HT40(chan))
+			i = ALL_TARGET_HT40_0_8_16;
+		else
+			i = ALL_TARGET_HT20_0_8_16;
+	} else {
+		if (IS_CHAN_HT40(chan))
+			i = ALL_TARGET_HT40_7;
+		else
+			i = ALL_TARGET_HT20_7;
+	}
+	ah->paprd_target_power = targetPowerValT2[i];
 }
 
 static u16 ath9k_hw_ar9300_get_spur_channel(struct ath_hw *ah,
@@ -2207,14 +4900,43 @@ s32 ar9003_hw_get_rx_gain_idx(struct ath
 	return (eep->baseEepHeader.txrxgain) & 0xf; /* bits 3:0 */
 }
 
+u8 *ar9003_get_spur_chan_ptr(struct ath_hw *ah, bool is_2ghz)
+{
+	struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
+
+	if (is_2ghz)
+		return eep->modalHeader2G.spurChans;
+	else
+		return eep->modalHeader5G.spurChans;
+}
+
+unsigned int ar9003_get_paprd_scale_factor(struct ath_hw *ah,
+					   struct ath9k_channel *chan)
+{
+	struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
+
+	if (IS_CHAN_2GHZ(chan))
+		return MS(le32_to_cpu(eep->modalHeader2G.papdRateMaskHt20),
+			  AR9300_PAPRD_SCALE_1);
+	else {
+		if (chan->channel >= 5700)
+		return MS(le32_to_cpu(eep->modalHeader5G.papdRateMaskHt20),
+			  AR9300_PAPRD_SCALE_1);
+		else if (chan->channel >= 5400)
+			return MS(le32_to_cpu(eep->modalHeader5G.papdRateMaskHt40),
+				   AR9300_PAPRD_SCALE_2);
+		else
+			return MS(le32_to_cpu(eep->modalHeader5G.papdRateMaskHt40),
+				  AR9300_PAPRD_SCALE_1);
+	}
+}
+
 const struct eeprom_ops eep_ar9300_ops = {
 	.check_eeprom = ath9k_hw_ar9300_check_eeprom,
 	.get_eeprom = ath9k_hw_ar9300_get_eeprom,
 	.fill_eeprom = ath9k_hw_ar9300_fill_eeprom,
 	.get_eeprom_ver = ath9k_hw_ar9300_get_eeprom_ver,
 	.get_eeprom_rev = ath9k_hw_ar9300_get_eeprom_rev,
-	.get_num_ant_config = ath9k_hw_ar9300_get_num_ant_config,
-	.get_eeprom_antenna_cfg = ath9k_hw_ar9300_get_eeprom_antenna_cfg,
 	.set_board_values = ath9k_hw_ar9300_set_board_values,
 	.set_addac = ath9k_hw_ar9300_set_addac,
 	.set_txpower = ath9k_hw_ar9300_set_txpower,
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h	2011-03-14 21:20:32.000000000 -0400
@@ -20,47 +20,22 @@
 /* #define AR9300_NUM_CTLS              21 */
 #define AR9300_NUM_CTLS_5G           9
 #define AR9300_NUM_CTLS_2G           12
-#define AR9300_CTL_MODE_M            0xF
 #define AR9300_NUM_BAND_EDGES_5G     8
 #define AR9300_NUM_BAND_EDGES_2G     4
-#define AR9300_NUM_PD_GAINS          4
-#define AR9300_PD_GAINS_IN_MASK      4
-#define AR9300_PD_GAIN_ICEPTS        5
-#define AR9300_EEPROM_MODAL_SPURS    5
-#define AR9300_MAX_RATE_POWER        63
-#define AR9300_NUM_PDADC_VALUES      128
-#define AR9300_NUM_RATES             16
-#define AR9300_BCHAN_UNUSED          0xFF
-#define AR9300_MAX_PWR_RANGE_IN_HALF_DB 64
-#define AR9300_OPFLAGS_11A           0x01
-#define AR9300_OPFLAGS_11G           0x02
-#define AR9300_OPFLAGS_5G_HT40       0x04
-#define AR9300_OPFLAGS_2G_HT40       0x08
-#define AR9300_OPFLAGS_5G_HT20       0x10
-#define AR9300_OPFLAGS_2G_HT20       0x20
 #define AR9300_EEPMISC_BIG_ENDIAN    0x01
 #define AR9300_EEPMISC_WOW           0x02
 #define AR9300_CUSTOMER_DATA_SIZE    20
 
-#define FREQ2FBIN(x, y) ((y) ? ((x) - 2300) : (((x) - 4800) / 5))
 #define FBIN2FREQ(x, y) ((y) ? (2300 + x) : (4800 + 5 * x))
 #define AR9300_MAX_CHAINS            3
 #define AR9300_ANT_16S               25
 #define AR9300_FUTURE_MODAL_SZ       6
 
-#define AR9300_NUM_ANT_CHAIN_FIELDS     7
-#define AR9300_NUM_ANT_COMMON_FIELDS    4
-#define AR9300_SIZE_ANT_CHAIN_FIELD     3
-#define AR9300_SIZE_ANT_COMMON_FIELD    4
-#define AR9300_ANT_CHAIN_MASK           0x7
-#define AR9300_ANT_COMMON_MASK          0xf
-#define AR9300_CHAIN_0_IDX              0
-#define AR9300_CHAIN_1_IDX              1
-#define AR9300_CHAIN_2_IDX              2
-
-#define AR928X_NUM_ANT_CHAIN_FIELDS     6
-#define AR928X_SIZE_ANT_CHAIN_FIELD     2
-#define AR928X_ANT_CHAIN_MASK           0x3
+#define AR9300_PAPRD_RATE_MASK		0x01ffffff
+#define AR9300_PAPRD_SCALE_1		0x0e000000
+#define AR9300_PAPRD_SCALE_1_S		25
+#define AR9300_PAPRD_SCALE_2		0x70000000
+#define AR9300_PAPRD_SCALE_2_S		28
 
 /* Delta from which to start power to pdadc table */
 /* This offset is used in both open loop and closed loop power control
@@ -71,14 +46,20 @@
  */
 #define AR9300_PWR_TABLE_OFFSET  0
 
-/* enable flags for voltage and temp compensation */
-#define ENABLE_TEMP_COMPENSATION 0x01
-#define ENABLE_VOLT_COMPENSATION 0x02
 /* byte addressable */
 #define AR9300_EEPROM_SIZE (16*1024)
-#define FIXED_CCA_THRESHOLD 15
 
+#define AR9300_BASE_ADDR_4K 0xfff
 #define AR9300_BASE_ADDR 0x3ff
+#define AR9300_BASE_ADDR_512 0x1ff
+
+#define AR9300_OTP_BASE			0x14000
+#define AR9300_OTP_STATUS		0x15f18
+#define AR9300_OTP_STATUS_TYPE		0x7
+#define AR9300_OTP_STATUS_VALID		0x4
+#define AR9300_OTP_STATUS_ACCESS_BUSY	0x2
+#define AR9300_OTP_STATUS_SM_BUSY	0x1
+#define AR9300_OTP_READ_DATA		0x15f1c
 
 enum targetPowerHTRates {
 	HT_TARGET_RATE_0_8_16,
@@ -216,7 +197,7 @@ struct ar9300_modal_eep_header {
 	int8_t tempSlope;
 	int8_t voltSlope;
 	/* spur channels in usual fbin coding format */
-	u8 spurChans[AR9300_EEPROM_MODAL_SPURS];
+	u8 spurChans[AR_EEPROM_MODAL_SPURS];
 	/* 3  Check if the register is per chain */
 	int8_t noiseFloorThreshCh[AR9300_MAX_CHAINS];
 	u8 ob[AR9300_MAX_CHAINS];
@@ -236,7 +217,7 @@ struct ar9300_modal_eep_header {
 	u8 thresh62;
 	__le32 papdRateMaskHt20;
 	__le32 papdRateMaskHt40;
-	u8 futureModal[24];
+	u8 futureModal[10];
 } __packed;
 
 struct ar9300_cal_data_per_freq_op_loop {
@@ -269,6 +250,20 @@ struct cal_ctl_data_5g {
 	u8 ctlEdges[AR9300_NUM_BAND_EDGES_5G];
 } __packed;
 
+struct ar9300_BaseExtension_1 {
+	u8 ant_div_control;
+	u8 future[13];
+} __packed;
+
+struct ar9300_BaseExtension_2 {
+	int8_t    tempSlopeLow;
+	int8_t    tempSlopeHigh;
+	u8   xatten1DBLow[AR9300_MAX_CHAINS];
+	u8   xatten1MarginLow[AR9300_MAX_CHAINS];
+	u8   xatten1DBHigh[AR9300_MAX_CHAINS];
+	u8   xatten1MarginHigh[AR9300_MAX_CHAINS];
+} __packed;
+
 struct ar9300_eeprom {
 	u8 eepromVersion;
 	u8 templateVersion;
@@ -278,6 +273,7 @@ struct ar9300_eeprom {
 	struct ar9300_base_eep_hdr baseEepHeader;
 
 	struct ar9300_modal_eep_header modalHeader2G;
+	struct ar9300_BaseExtension_1 base_ext1;
 	u8 calFreqPier2G[AR9300_NUM_2G_CAL_PIERS];
 	struct ar9300_cal_data_per_freq_op_loop
 	 calPierData2G[AR9300_MAX_CHAINS][AR9300_NUM_2G_CAL_PIERS];
@@ -297,6 +293,7 @@ struct ar9300_eeprom {
 	u8 ctl_freqbin_2G[AR9300_NUM_CTLS_2G][AR9300_NUM_BAND_EDGES_2G];
 	struct cal_ctl_data_2g ctlPowerData_2G[AR9300_NUM_CTLS_2G];
 	struct ar9300_modal_eep_header modalHeader5G;
+	struct ar9300_BaseExtension_2 base_ext2;
 	u8 calFreqPier5G[AR9300_NUM_5G_CAL_PIERS];
 	struct ar9300_cal_data_per_freq_op_loop
 	 calPierData5G[AR9300_MAX_CHAINS][AR9300_NUM_5G_CAL_PIERS];
@@ -317,4 +314,8 @@ struct ar9300_eeprom {
 s32 ar9003_hw_get_tx_gain_idx(struct ath_hw *ah);
 s32 ar9003_hw_get_rx_gain_idx(struct ath_hw *ah);
 
+u8 *ar9003_get_spur_chan_ptr(struct ath_hw *ah, bool is_2ghz);
+
+unsigned int ar9003_get_paprd_scale_factor(struct ath_hw *ah,
+					   struct ath9k_channel *chan);
 #endif
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/ar9003_hw.c linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/ar9003_hw.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/ar9003_hw.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/ar9003_hw.c	2011-03-14 21:20:32.000000000 -0400
@@ -17,20 +17,10 @@
 #include "hw.h"
 #include "ar9003_mac.h"
 #include "ar9003_2p2_initvals.h"
+#include "ar9485_initvals.h"
 
 /* General hardware code for the AR9003 hadware family */
 
-static bool ar9003_hw_macversion_supported(u32 macversion)
-{
-	switch (macversion) {
-	case AR_SREV_VERSION_9300:
-		return true;
-	default:
-		break;
-	}
-	return false;
-}
-
 /*
  * The AR9003 family uses a new INI format (pre, core, post
  * arrays per subsystem). This provides support for the
@@ -38,72 +28,134 @@ static bool ar9003_hw_macversion_support
  */
 static void ar9003_hw_init_mode_regs(struct ath_hw *ah)
 {
-	/* mac */
-	INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0);
-	INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE],
-		       ar9300_2p2_mac_core,
-		       ARRAY_SIZE(ar9300_2p2_mac_core), 2);
-	INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST],
-		       ar9300_2p2_mac_postamble,
-		       ARRAY_SIZE(ar9300_2p2_mac_postamble), 5);
+	if (AR_SREV_9485(ah)) {
+		/* mac */
+		INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0);
+		INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE],
+				ar9485_1_0_mac_core,
+				ARRAY_SIZE(ar9485_1_0_mac_core), 2);
+		INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST],
+				ar9485_1_0_mac_postamble,
+				ARRAY_SIZE(ar9485_1_0_mac_postamble), 5);
 
-	/* bb */
-	INIT_INI_ARRAY(&ah->iniBB[ATH_INI_PRE], NULL, 0, 0);
-	INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE],
-		       ar9300_2p2_baseband_core,
-		       ARRAY_SIZE(ar9300_2p2_baseband_core), 2);
-	INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST],
-		       ar9300_2p2_baseband_postamble,
-		       ARRAY_SIZE(ar9300_2p2_baseband_postamble), 5);
+		/* bb */
+		INIT_INI_ARRAY(&ah->iniBB[ATH_INI_PRE], ar9485_1_0,
+				ARRAY_SIZE(ar9485_1_0), 2);
+		INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE],
+				ar9485_1_0_baseband_core,
+				ARRAY_SIZE(ar9485_1_0_baseband_core), 2);
+		INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST],
+				ar9485_1_0_baseband_postamble,
+				ARRAY_SIZE(ar9485_1_0_baseband_postamble), 5);
 
-	/* radio */
-	INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_PRE], NULL, 0, 0);
-	INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE],
-		       ar9300_2p2_radio_core,
-		       ARRAY_SIZE(ar9300_2p2_radio_core), 2);
-	INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST],
-		       ar9300_2p2_radio_postamble,
-		       ARRAY_SIZE(ar9300_2p2_radio_postamble), 5);
+		/* radio */
+		INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_PRE], NULL, 0, 0);
+		INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE],
+				ar9485_1_0_radio_core,
+				ARRAY_SIZE(ar9485_1_0_radio_core), 2);
+		INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST],
+				ar9485_1_0_radio_postamble,
+				ARRAY_SIZE(ar9485_1_0_radio_postamble), 2);
 
-	/* soc */
-	INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_PRE],
-		       ar9300_2p2_soc_preamble,
-		       ARRAY_SIZE(ar9300_2p2_soc_preamble), 2);
-	INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_CORE], NULL, 0, 0);
-	INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST],
-		       ar9300_2p2_soc_postamble,
-		       ARRAY_SIZE(ar9300_2p2_soc_postamble), 5);
+		/* soc */
+		INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_PRE],
+				ar9485_1_0_soc_preamble,
+				ARRAY_SIZE(ar9485_1_0_soc_preamble), 2);
+		INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_CORE], NULL, 0, 0);
+		INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST], NULL, 0, 0);
 
-	/* rx/tx gain */
-	INIT_INI_ARRAY(&ah->iniModesRxGain,
-		       ar9300Common_rx_gain_table_2p2,
-		       ARRAY_SIZE(ar9300Common_rx_gain_table_2p2), 2);
-	INIT_INI_ARRAY(&ah->iniModesTxGain,
-		       ar9300Modes_lowest_ob_db_tx_gain_table_2p2,
-		       ARRAY_SIZE(ar9300Modes_lowest_ob_db_tx_gain_table_2p2),
-		       5);
+		/* rx/tx gain */
+		INIT_INI_ARRAY(&ah->iniModesRxGain,
+				ar9485Common_rx_gain_1_0,
+				ARRAY_SIZE(ar9485Common_rx_gain_1_0), 2);
+		INIT_INI_ARRAY(&ah->iniModesTxGain,
+				ar9485Modes_lowest_ob_db_tx_gain_1_0,
+				ARRAY_SIZE(ar9485Modes_lowest_ob_db_tx_gain_1_0),
+				5);
 
-	/* Load PCIE SERDES settings from INI */
+		/* Load PCIE SERDES settings from INI */
 
-	/* Awake Setting */
+		/* Awake Setting */
 
-	INIT_INI_ARRAY(&ah->iniPcieSerdes,
-		       ar9300PciePhy_pll_on_clkreq_disable_L1_2p2,
-		       ARRAY_SIZE(ar9300PciePhy_pll_on_clkreq_disable_L1_2p2),
-		       2);
+		INIT_INI_ARRAY(&ah->iniPcieSerdes,
+				ar9485_1_0_pcie_phy_pll_on_clkreq_disable_L1,
+				ARRAY_SIZE(ar9485_1_0_pcie_phy_pll_on_clkreq_disable_L1),
+				2);
 
-	/* Sleep Setting */
+		/* Sleep Setting */
 
-	INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower,
-		       ar9300PciePhy_clkreq_enable_L1_2p2,
-		       ARRAY_SIZE(ar9300PciePhy_clkreq_enable_L1_2p2),
-		       2);
+		INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower,
+				ar9485_1_0_pcie_phy_pll_on_clkreq_enable_L1,
+				ARRAY_SIZE(ar9485_1_0_pcie_phy_pll_on_clkreq_enable_L1),
+				2);
+	} else {
+		/* mac */
+		INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0);
+		INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE],
+				ar9300_2p2_mac_core,
+				ARRAY_SIZE(ar9300_2p2_mac_core), 2);
+		INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST],
+				ar9300_2p2_mac_postamble,
+				ARRAY_SIZE(ar9300_2p2_mac_postamble), 5);
 
-	/* Fast clock modal settings */
-	INIT_INI_ARRAY(&ah->iniModesAdditional,
-		       ar9300Modes_fast_clock_2p2,
-		       ARRAY_SIZE(ar9300Modes_fast_clock_2p2),
-		       3);
+		/* bb */
+		INIT_INI_ARRAY(&ah->iniBB[ATH_INI_PRE], NULL, 0, 0);
+		INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE],
+				ar9300_2p2_baseband_core,
+				ARRAY_SIZE(ar9300_2p2_baseband_core), 2);
+		INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST],
+				ar9300_2p2_baseband_postamble,
+				ARRAY_SIZE(ar9300_2p2_baseband_postamble), 5);
+
+		/* radio */
+		INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_PRE], NULL, 0, 0);
+		INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE],
+				ar9300_2p2_radio_core,
+				ARRAY_SIZE(ar9300_2p2_radio_core), 2);
+		INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST],
+				ar9300_2p2_radio_postamble,
+				ARRAY_SIZE(ar9300_2p2_radio_postamble), 5);
+
+		/* soc */
+		INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_PRE],
+				ar9300_2p2_soc_preamble,
+				ARRAY_SIZE(ar9300_2p2_soc_preamble), 2);
+		INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_CORE], NULL, 0, 0);
+		INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST],
+				ar9300_2p2_soc_postamble,
+				ARRAY_SIZE(ar9300_2p2_soc_postamble), 5);
+
+		/* rx/tx gain */
+		INIT_INI_ARRAY(&ah->iniModesRxGain,
+				ar9300Common_rx_gain_table_2p2,
+				ARRAY_SIZE(ar9300Common_rx_gain_table_2p2), 2);
+		INIT_INI_ARRAY(&ah->iniModesTxGain,
+				ar9300Modes_lowest_ob_db_tx_gain_table_2p2,
+				ARRAY_SIZE(ar9300Modes_lowest_ob_db_tx_gain_table_2p2),
+				5);
+
+		/* Load PCIE SERDES settings from INI */
+
+		/* Awake Setting */
+
+		INIT_INI_ARRAY(&ah->iniPcieSerdes,
+				ar9300PciePhy_pll_on_clkreq_disable_L1_2p2,
+				ARRAY_SIZE(ar9300PciePhy_pll_on_clkreq_disable_L1_2p2),
+				2);
+
+		/* Sleep Setting */
+
+		INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower,
+				ar9300PciePhy_pll_on_clkreq_disable_L1_2p2,
+				ARRAY_SIZE(ar9300PciePhy_pll_on_clkreq_disable_L1_2p2),
+				2);
+
+		/* Fast clock modal settings */
+		INIT_INI_ARRAY(&ah->iniModesAdditional,
+				ar9300Modes_fast_clock_2p2,
+				ARRAY_SIZE(ar9300Modes_fast_clock_2p2),
+				3);
+	}
 }
 
 static void ar9003_tx_gain_table_apply(struct ath_hw *ah)
@@ -111,22 +163,52 @@ static void ar9003_tx_gain_table_apply(s
 	switch (ar9003_hw_get_tx_gain_idx(ah)) {
 	case 0:
 	default:
-		INIT_INI_ARRAY(&ah->iniModesTxGain,
-			       ar9300Modes_lowest_ob_db_tx_gain_table_2p2,
-			       ARRAY_SIZE(ar9300Modes_lowest_ob_db_tx_gain_table_2p2),
-			       5);
+		if (AR_SREV_9485(ah))
+			INIT_INI_ARRAY(&ah->iniModesTxGain,
+				       ar9485Modes_lowest_ob_db_tx_gain_1_0,
+				       ARRAY_SIZE(ar9485Modes_lowest_ob_db_tx_gain_1_0),
+				       5);
+		else
+			INIT_INI_ARRAY(&ah->iniModesTxGain,
+				       ar9300Modes_lowest_ob_db_tx_gain_table_2p2,
+				       ARRAY_SIZE(ar9300Modes_lowest_ob_db_tx_gain_table_2p2),
+				       5);
 		break;
 	case 1:
-		INIT_INI_ARRAY(&ah->iniModesTxGain,
-			       ar9300Modes_high_ob_db_tx_gain_table_2p2,
-			       ARRAY_SIZE(ar9300Modes_high_ob_db_tx_gain_table_2p2),
-			       5);
+		if (AR_SREV_9485(ah))
+			INIT_INI_ARRAY(&ah->iniModesTxGain,
+				       ar9485Modes_high_ob_db_tx_gain_1_0,
+				       ARRAY_SIZE(ar9485Modes_lowest_ob_db_tx_gain_1_0),
+				       5);
+		else
+			INIT_INI_ARRAY(&ah->iniModesTxGain,
+				       ar9300Modes_high_ob_db_tx_gain_table_2p2,
+				       ARRAY_SIZE(ar9300Modes_high_ob_db_tx_gain_table_2p2),
+				       5);
 		break;
 	case 2:
-		INIT_INI_ARRAY(&ah->iniModesTxGain,
-			       ar9300Modes_low_ob_db_tx_gain_table_2p2,
-			       ARRAY_SIZE(ar9300Modes_low_ob_db_tx_gain_table_2p2),
-			       5);
+		if (AR_SREV_9485(ah))
+			INIT_INI_ARRAY(&ah->iniModesTxGain,
+				       ar9485Modes_low_ob_db_tx_gain_1_0,
+				       ARRAY_SIZE(ar9485Modes_lowest_ob_db_tx_gain_1_0),
+				       5);
+		else
+			INIT_INI_ARRAY(&ah->iniModesTxGain,
+				       ar9300Modes_low_ob_db_tx_gain_table_2p2,
+				       ARRAY_SIZE(ar9300Modes_low_ob_db_tx_gain_table_2p2),
+				       5);
+		break;
+	case 3:
+		if (AR_SREV_9485(ah))
+			INIT_INI_ARRAY(&ah->iniModesTxGain,
+				       ar9485Modes_high_power_tx_gain_1_0,
+				       ARRAY_SIZE(ar9485Modes_high_power_tx_gain_1_0),
+				       5);
+		else
+			INIT_INI_ARRAY(&ah->iniModesTxGain,
+				       ar9300Modes_high_power_tx_gain_table_2p2,
+				       ARRAY_SIZE(ar9300Modes_high_power_tx_gain_table_2p2),
+				       5);
 		break;
 	}
 }
@@ -136,16 +218,28 @@ static void ar9003_rx_gain_table_apply(s
 	switch (ar9003_hw_get_rx_gain_idx(ah)) {
 	case 0:
 	default:
-		INIT_INI_ARRAY(&ah->iniModesRxGain,
-			       ar9300Common_rx_gain_table_2p2,
-			       ARRAY_SIZE(ar9300Common_rx_gain_table_2p2),
-			       2);
+		if (AR_SREV_9485(ah))
+			INIT_INI_ARRAY(&ah->iniModesRxGain,
+				       ar9485Common_rx_gain_1_0,
+				       ARRAY_SIZE(ar9485Common_rx_gain_1_0),
+				       2);
+		else
+			INIT_INI_ARRAY(&ah->iniModesRxGain,
+				       ar9300Common_rx_gain_table_2p2,
+				       ARRAY_SIZE(ar9300Common_rx_gain_table_2p2),
+				       2);
 		break;
 	case 1:
-		INIT_INI_ARRAY(&ah->iniModesRxGain,
-			       ar9300Common_wo_xlna_rx_gain_table_2p2,
-			       ARRAY_SIZE(ar9300Common_wo_xlna_rx_gain_table_2p2),
-			       2);
+		if (AR_SREV_9485(ah))
+			INIT_INI_ARRAY(&ah->iniModesRxGain,
+				       ar9485Common_wo_xlna_rx_gain_1_0,
+				       ARRAY_SIZE(ar9485Common_wo_xlna_rx_gain_1_0),
+				       2);
+		else
+			INIT_INI_ARRAY(&ah->iniModesRxGain,
+				       ar9300Common_wo_xlna_rx_gain_table_2p2,
+				       ARRAY_SIZE(ar9300Common_wo_xlna_rx_gain_table_2p2),
+				       2);
 		break;
 	}
 }
@@ -216,7 +310,6 @@ void ar9003_hw_attach_ops(struct ath_hw
 
 	priv_ops->init_mode_regs = ar9003_hw_init_mode_regs;
 	priv_ops->init_mode_gain_regs = ar9003_hw_init_mode_gain_regs;
-	priv_ops->macversion_supported = ar9003_hw_macversion_supported;
 
 	ops->config_pci_powersave = ar9003_hw_configpcipowersave;
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/ar9003_mac.c linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/ar9003_mac.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/ar9003_mac.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/ar9003_mac.c	2011-03-14 21:20:32.000000000 -0400
@@ -182,8 +182,8 @@ static bool ar9003_hw_get_isr(struct ath
 		}
 
 		if (sync_cause & AR_INTR_SYNC_LOCAL_TIMEOUT)
-			ath_print(common, ATH_DBG_INTERRUPT,
-				  "AR_INTR_SYNC_LOCAL_TIMEOUT\n");
+			ath_dbg(common, ATH_DBG_INTERRUPT,
+				"AR_INTR_SYNC_LOCAL_TIMEOUT\n");
 
 		REG_WRITE(ah, AR_INTR_SYNC_CAUSE_CLR, sync_cause);
 		(void) REG_READ(ah, AR_INTR_SYNC_CAUSE_CLR);
@@ -237,73 +237,76 @@ static int ar9003_hw_proc_txdesc(struct
 				 struct ath_tx_status *ts)
 {
 	struct ar9003_txs *ads;
+	u32 status;
 
 	ads = &ah->ts_ring[ah->ts_tail];
 
-	if ((ads->status8 & AR_TxDone) == 0)
+	status = ACCESS_ONCE(ads->status8);
+	if ((status & AR_TxDone) == 0)
 		return -EINPROGRESS;
 
 	ah->ts_tail = (ah->ts_tail + 1) % ah->ts_size;
 
 	if ((MS(ads->ds_info, AR_DescId) != ATHEROS_VENDOR_ID) ||
 	    (MS(ads->ds_info, AR_TxRxDesc) != 1)) {
-		ath_print(ath9k_hw_common(ah), ATH_DBG_XMIT,
-			  "Tx Descriptor error %x\n", ads->ds_info);
+		ath_dbg(ath9k_hw_common(ah), ATH_DBG_XMIT,
+			"Tx Descriptor error %x\n", ads->ds_info);
 		memset(ads, 0, sizeof(*ads));
 		return -EIO;
 	}
 
+	if (status & AR_TxOpExceeded)
+		ts->ts_status |= ATH9K_TXERR_XTXOP;
+	ts->ts_rateindex = MS(status, AR_FinalTxIdx);
+	ts->ts_seqnum = MS(status, AR_SeqNum);
+	ts->tid = MS(status, AR_TxTid);
+
 	ts->qid = MS(ads->ds_info, AR_TxQcuNum);
 	ts->desc_id = MS(ads->status1, AR_TxDescId);
-	ts->ts_seqnum = MS(ads->status8, AR_SeqNum);
 	ts->ts_tstamp = ads->status4;
 	ts->ts_status = 0;
 	ts->ts_flags  = 0;
 
-	if (ads->status3 & AR_ExcessiveRetries)
+	status = ACCESS_ONCE(ads->status2);
+	ts->ts_rssi_ctl0 = MS(status, AR_TxRSSIAnt00);
+	ts->ts_rssi_ctl1 = MS(status, AR_TxRSSIAnt01);
+	ts->ts_rssi_ctl2 = MS(status, AR_TxRSSIAnt02);
+	if (status & AR_TxBaStatus) {
+		ts->ts_flags |= ATH9K_TX_BA;
+		ts->ba_low = ads->status5;
+		ts->ba_high = ads->status6;
+	}
+
+	status = ACCESS_ONCE(ads->status3);
+	if (status & AR_ExcessiveRetries)
 		ts->ts_status |= ATH9K_TXERR_XRETRY;
-	if (ads->status3 & AR_Filtered)
+	if (status & AR_Filtered)
 		ts->ts_status |= ATH9K_TXERR_FILT;
-	if (ads->status3 & AR_FIFOUnderrun) {
+	if (status & AR_FIFOUnderrun) {
 		ts->ts_status |= ATH9K_TXERR_FIFO;
 		ath9k_hw_updatetxtriglevel(ah, true);
 	}
-	if (ads->status8 & AR_TxOpExceeded)
-		ts->ts_status |= ATH9K_TXERR_XTXOP;
-	if (ads->status3 & AR_TxTimerExpired)
+	if (status & AR_TxTimerExpired)
 		ts->ts_status |= ATH9K_TXERR_TIMER_EXPIRED;
-
-	if (ads->status3 & AR_DescCfgErr)
+	if (status & AR_DescCfgErr)
 		ts->ts_flags |= ATH9K_TX_DESC_CFG_ERR;
-	if (ads->status3 & AR_TxDataUnderrun) {
+	if (status & AR_TxDataUnderrun) {
 		ts->ts_flags |= ATH9K_TX_DATA_UNDERRUN;
 		ath9k_hw_updatetxtriglevel(ah, true);
 	}
-	if (ads->status3 & AR_TxDelimUnderrun) {
+	if (status & AR_TxDelimUnderrun) {
 		ts->ts_flags |= ATH9K_TX_DELIM_UNDERRUN;
 		ath9k_hw_updatetxtriglevel(ah, true);
 	}
-	if (ads->status2 & AR_TxBaStatus) {
-		ts->ts_flags |= ATH9K_TX_BA;
-		ts->ba_low = ads->status5;
-		ts->ba_high = ads->status6;
-	}
-
-	ts->ts_rateindex = MS(ads->status8, AR_FinalTxIdx);
-
-	ts->ts_rssi = MS(ads->status7, AR_TxRSSICombined);
-	ts->ts_rssi_ctl0 = MS(ads->status2, AR_TxRSSIAnt00);
-	ts->ts_rssi_ctl1 = MS(ads->status2, AR_TxRSSIAnt01);
-	ts->ts_rssi_ctl2 = MS(ads->status2, AR_TxRSSIAnt02);
-	ts->ts_rssi_ext0 = MS(ads->status7, AR_TxRSSIAnt10);
-	ts->ts_rssi_ext1 = MS(ads->status7, AR_TxRSSIAnt11);
-	ts->ts_rssi_ext2 = MS(ads->status7, AR_TxRSSIAnt12);
-	ts->ts_shortretry = MS(ads->status3, AR_RTSFailCnt);
-	ts->ts_longretry = MS(ads->status3, AR_DataFailCnt);
-	ts->ts_virtcol = MS(ads->status3, AR_VirtRetryCnt);
-	ts->ts_antenna = 0;
+	ts->ts_shortretry = MS(status, AR_RTSFailCnt);
+	ts->ts_longretry = MS(status, AR_DataFailCnt);
+	ts->ts_virtcol = MS(status, AR_VirtRetryCnt);
 
-	ts->tid = MS(ads->status8, AR_TxTid);
+	status = ACCESS_ONCE(ads->status7);
+	ts->ts_rssi = MS(status, AR_TxRSSICombined);
+	ts->ts_rssi_ext0 = MS(status, AR_TxRSSIAnt10);
+	ts->ts_rssi_ext1 = MS(status, AR_TxRSSIAnt11);
+	ts->ts_rssi_ext2 = MS(status, AR_TxRSSIAnt12);
 
 	memset(ads, 0, sizeof(*ads));
 
@@ -319,7 +322,6 @@ static void ar9003_hw_set11n_txdesc(stru
 	if (txpower > ah->txpower_limit)
 		txpower = ah->txpower_limit;
 
-	txpower += ah->txpower_indexoffset;
 	if (txpower > 63)
 		txpower = 63;
 
@@ -407,12 +409,36 @@ static void ar9003_hw_set11n_ratescenari
 static void ar9003_hw_set11n_aggr_first(struct ath_hw *ah, void *ds,
 					u32 aggrLen)
 {
+#define FIRST_DESC_NDELIMS 60
 	struct ar9003_txc *ads = (struct ar9003_txc *) ds;
 
 	ads->ctl12 |= (AR_IsAggr | AR_MoreAggr);
 
-	ads->ctl17 &= ~AR_AggrLen;
-	ads->ctl17 |= SM(aggrLen, AR_AggrLen);
+	if (ah->ent_mode & AR_ENT_OTP_MPSD) {
+		u32 ctl17, ndelim;
+		/*
+		 * Add delimiter when using RTS/CTS with aggregation
+		 * and non enterprise AR9003 card
+		 */
+		ctl17 = ads->ctl17;
+		ndelim = MS(ctl17, AR_PadDelim);
+
+		if (ndelim < FIRST_DESC_NDELIMS) {
+			aggrLen += (FIRST_DESC_NDELIMS - ndelim) * 4;
+			ndelim = FIRST_DESC_NDELIMS;
+		}
+
+		ctl17 &= ~AR_AggrLen;
+		ctl17 |= SM(aggrLen, AR_AggrLen);
+
+		ctl17 &= ~AR_PadDelim;
+		ctl17 |= SM(ndelim, AR_PadDelim);
+
+		ads->ctl17 = ctl17;
+	} else {
+		ads->ctl17 &= ~AR_AggrLen;
+		ads->ctl17 |= SM(aggrLen, AR_AggrLen);
+	}
 }
 
 static void ar9003_hw_set11n_aggr_middle(struct ath_hw *ah, void *ds,
@@ -587,9 +613,9 @@ int ath9k_hw_process_rxdesc_edma(struct
 		 * possibly be reviewing the last subframe. AR_CRCErr
 		 * is the CRC of the actual data.
 		 */
-		if (rxsp->status11 & AR_CRCErr) {
+		if (rxsp->status11 & AR_CRCErr)
 			rxs->rs_status |= ATH9K_RXERR_CRC;
-		} else if (rxsp->status11 & AR_PHYErr) {
+		if (rxsp->status11 & AR_PHYErr) {
 			phyerr = MS(rxsp->status11, AR_PHYErrCode);
 			/*
 			 * If we reach a point here where AR_PostDelimCRCErr is
@@ -612,11 +638,12 @@ int ath9k_hw_process_rxdesc_edma(struct
 				rxs->rs_phyerr = phyerr;
 			}
 
-		} else if (rxsp->status11 & AR_DecryptCRCErr) {
+		}
+		if (rxsp->status11 & AR_DecryptCRCErr)
 			rxs->rs_status |= ATH9K_RXERR_DECRYPT;
-		} else if (rxsp->status11 & AR_MichaelErr) {
+		if (rxsp->status11 & AR_MichaelErr)
 			rxs->rs_status |= ATH9K_RXERR_MIC;
-		} else if (rxsp->status11 & AR_KeyMiss)
+		if (rxsp->status11 & AR_KeyMiss)
 			rxs->rs_status |= ATH9K_RXERR_DECRYPT;
 	}
 
@@ -631,10 +658,10 @@ void ath9k_hw_reset_txstatus_ring(struct
 	memset((void *) ah->ts_ring, 0,
 		ah->ts_size * sizeof(struct ar9003_txs));
 
-	ath_print(ath9k_hw_common(ah), ATH_DBG_XMIT,
-		  "TS Start 0x%x End 0x%x Virt %p, Size %d\n",
-		   ah->ts_paddr_start, ah->ts_paddr_end,
-		   ah->ts_ring, ah->ts_size);
+	ath_dbg(ath9k_hw_common(ah), ATH_DBG_XMIT,
+		"TS Start 0x%x End 0x%x Virt %p, Size %d\n",
+		ah->ts_paddr_start, ah->ts_paddr_end,
+		ah->ts_ring, ah->ts_size);
 
 	REG_WRITE(ah, AR_Q_STATUS_RING_START, ah->ts_paddr_start);
 	REG_WRITE(ah, AR_Q_STATUS_RING_END, ah->ts_paddr_end);
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/ar9003_mac.h linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/ar9003_mac.h
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/ar9003_mac.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/ar9003_mac.h	2011-03-14 21:20:32.000000000 -0400
@@ -65,7 +65,7 @@ struct ar9003_rxs {
 	u32 status9;
 	u32 status10;
 	u32 status11;
-} __packed;
+} __packed __aligned(4);
 
 /* Transmit Control Descriptor */
 struct ar9003_txc {
@@ -93,7 +93,7 @@ struct ar9003_txc {
 	u32 ctl21;  /* DMA control 21 */
 	u32 ctl22;  /* DMA control 22 */
 	u32 pad[9]; /* pad to cache line (128 bytes/32 dwords) */
-} __packed;
+} __packed __aligned(4);
 
 struct ar9003_txs {
 	u32 ds_info;
@@ -105,7 +105,7 @@ struct ar9003_txs {
 	u32 status6;
 	u32 status7;
 	u32 status8;
-} __packed;
+} __packed __aligned(4);
 
 void ar9003_hw_attach_mac_ops(struct ath_hw *hw);
 void ath9k_hw_set_rx_bufsize(struct ath_hw *ah, u16 buf_size);
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/ar9003_paprd.c linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/ar9003_paprd.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/ar9003_paprd.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/ar9003_paprd.c	2011-03-14 21:20:32.000000000 -0400
@@ -19,45 +19,124 @@
 
 void ar9003_paprd_enable(struct ath_hw *ah, bool val)
 {
+	struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
+	struct ath9k_channel *chan = ah->curchan;
+
+	if (val) {
+		ah->paprd_table_write_done = true;
+
+		ah->eep_ops->set_txpower(ah, chan,
+				ath9k_regd_get_ctl(regulatory, chan),
+				chan->chan->max_antenna_gain * 2,
+				chan->chan->max_power * 2,
+				min((u32) MAX_RATE_POWER,
+				(u32) regulatory->power_limit), false);
+	}
+
 	REG_RMW_FIELD(ah, AR_PHY_PAPRD_CTRL0_B0,
 		      AR_PHY_PAPRD_CTRL0_PAPRD_ENABLE, !!val);
-	REG_RMW_FIELD(ah, AR_PHY_PAPRD_CTRL0_B1,
-		      AR_PHY_PAPRD_CTRL0_PAPRD_ENABLE, !!val);
-	REG_RMW_FIELD(ah, AR_PHY_PAPRD_CTRL0_B2,
-		      AR_PHY_PAPRD_CTRL0_PAPRD_ENABLE, !!val);
+	if (ah->caps.tx_chainmask & BIT(1))
+		REG_RMW_FIELD(ah, AR_PHY_PAPRD_CTRL0_B1,
+			      AR_PHY_PAPRD_CTRL0_PAPRD_ENABLE, !!val);
+	if (ah->caps.tx_chainmask & BIT(2))
+		REG_RMW_FIELD(ah, AR_PHY_PAPRD_CTRL0_B2,
+			      AR_PHY_PAPRD_CTRL0_PAPRD_ENABLE, !!val);
 }
 EXPORT_SYMBOL(ar9003_paprd_enable);
 
-static void ar9003_paprd_setup_single_table(struct ath_hw *ah)
+static int ar9003_get_training_power_2g(struct ath_hw *ah)
 {
 	struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
-	struct ar9300_modal_eep_header *hdr;
-	const u32 ctrl0[3] = {
+	struct ar9300_modal_eep_header *hdr = &eep->modalHeader2G;
+	unsigned int power, scale, delta;
+
+	scale = MS(le32_to_cpu(hdr->papdRateMaskHt20), AR9300_PAPRD_SCALE_1);
+	power = REG_READ_FIELD(ah, AR_PHY_POWERTX_RATE5,
+			       AR_PHY_POWERTX_RATE5_POWERTXHT20_0);
+
+	delta = abs((int) ah->paprd_target_power - (int) power);
+	if (delta > scale)
+		return -1;
+
+	if (delta < 4)
+		power -= 4 - delta;
+
+	return power;
+}
+
+static int ar9003_get_training_power_5g(struct ath_hw *ah)
+{
+	struct ath_common *common = ath9k_hw_common(ah);
+	struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
+	struct ar9300_modal_eep_header *hdr = &eep->modalHeader5G;
+	struct ath9k_channel *chan = ah->curchan;
+	unsigned int power, scale, delta;
+
+	if (chan->channel >= 5700)
+		scale = MS(le32_to_cpu(hdr->papdRateMaskHt20),
+			   AR9300_PAPRD_SCALE_1);
+	else if (chan->channel >= 5400)
+		scale = MS(le32_to_cpu(hdr->papdRateMaskHt40),
+			   AR9300_PAPRD_SCALE_2);
+	else
+		scale = MS(le32_to_cpu(hdr->papdRateMaskHt40),
+			   AR9300_PAPRD_SCALE_1);
+
+	if (IS_CHAN_HT40(chan))
+		power = REG_READ_FIELD(ah, AR_PHY_POWERTX_RATE8,
+			AR_PHY_POWERTX_RATE8_POWERTXHT40_5);
+	else
+		power = REG_READ_FIELD(ah, AR_PHY_POWERTX_RATE6,
+			AR_PHY_POWERTX_RATE6_POWERTXHT20_5);
+
+	power += scale;
+	delta = abs((int) ah->paprd_target_power - (int) power);
+	if (delta > scale)
+		return -1;
+
+	power += 2 * get_streams(common->tx_chainmask);
+	return power;
+}
+
+static int ar9003_paprd_setup_single_table(struct ath_hw *ah)
+{
+	struct ath_common *common = ath9k_hw_common(ah);
+	static const u32 ctrl0[3] = {
 		AR_PHY_PAPRD_CTRL0_B0,
 		AR_PHY_PAPRD_CTRL0_B1,
 		AR_PHY_PAPRD_CTRL0_B2
 	};
-	const u32 ctrl1[3] = {
+	static const u32 ctrl1[3] = {
 		AR_PHY_PAPRD_CTRL1_B0,
 		AR_PHY_PAPRD_CTRL1_B1,
 		AR_PHY_PAPRD_CTRL1_B2
 	};
-	u32 am_mask, ht40_mask;
+	int training_power;
 	int i;
 
-	if (ah->curchan && IS_CHAN_5GHZ(ah->curchan))
-		hdr = &eep->modalHeader5G;
+	if (IS_CHAN_2GHZ(ah->curchan))
+		training_power = ar9003_get_training_power_2g(ah);
 	else
-		hdr = &eep->modalHeader2G;
+		training_power = ar9003_get_training_power_5g(ah);
 
-	am_mask = le32_to_cpu(hdr->papdRateMaskHt20);
-	ht40_mask = le32_to_cpu(hdr->papdRateMaskHt40);
+	if (training_power < 0) {
+		ath_dbg(common, ATH_DBG_CALIBRATE,
+			"PAPRD target power delta out of range");
+		return -ERANGE;
+	}
+	ah->paprd_training_power = training_power;
+	ath_dbg(common, ATH_DBG_CALIBRATE,
+		"Training power: %d, Target power: %d\n",
+		ah->paprd_training_power, ah->paprd_target_power);
 
-	REG_RMW_FIELD(ah, AR_PHY_PAPRD_AM2AM, AR_PHY_PAPRD_AM2AM_MASK, am_mask);
-	REG_RMW_FIELD(ah, AR_PHY_PAPRD_AM2PM, AR_PHY_PAPRD_AM2PM_MASK, am_mask);
-	REG_RMW_FIELD(ah, AR_PHY_PAPRD_HT40, AR_PHY_PAPRD_HT40_MASK, ht40_mask);
+	REG_RMW_FIELD(ah, AR_PHY_PAPRD_AM2AM, AR_PHY_PAPRD_AM2AM_MASK,
+		      ah->paprd_ratemask);
+	REG_RMW_FIELD(ah, AR_PHY_PAPRD_AM2PM, AR_PHY_PAPRD_AM2PM_MASK,
+		      ah->paprd_ratemask);
+	REG_RMW_FIELD(ah, AR_PHY_PAPRD_HT40, AR_PHY_PAPRD_HT40_MASK,
+		      ah->paprd_ratemask_ht40);
 
-	for (i = 0; i < 3; i++) {
+	for (i = 0; i < ah->caps.max_txchains; i++) {
 		REG_RMW_FIELD(ah, ctrl0[i],
 			      AR_PHY_PAPRD_CTRL0_USE_SINGLE_TABLE_MASK, 1);
 		REG_RMW_FIELD(ah, ctrl1[i],
@@ -102,8 +181,14 @@ static void ar9003_paprd_setup_single_ta
 		      AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_NUM_CORR_STAGES, 7);
 	REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3,
 		      AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_MIN_LOOPBACK_DEL, 1);
-	REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3,
-		      AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_QUICK_DROP, -6);
+	if (AR_SREV_9485(ah))
+		REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3,
+			      AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_QUICK_DROP,
+			      -3);
+	else
+		REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3,
+			      AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_QUICK_DROP,
+			      -6);
 	REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3,
 		      AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_ADC_DESIRED_SIZE,
 		      -15);
@@ -132,6 +217,7 @@ static void ar9003_paprd_setup_single_ta
 		      AR_PHY_PAPRD_PRE_POST_SCALING, 185706);
 	REG_RMW_FIELD(ah, AR_PHY_PAPRD_PRE_POST_SCALE_7_B0,
 		      AR_PHY_PAPRD_PRE_POST_SCALING, 175487);
+	return 0;
 }
 
 static void ar9003_paprd_get_gain_table(struct ath_hw *ah)
@@ -586,15 +672,10 @@ void ar9003_paprd_populate_single_table(
 {
 	u32 *paprd_table_val = caldata->pa_table[chain];
 	u32 small_signal_gain = caldata->small_signal_gain[chain];
-	u32 training_power;
+	u32 training_power = ah->paprd_training_power;
 	u32 reg = 0;
 	int i;
 
-	training_power =
-	    REG_READ_FIELD(ah, AR_PHY_POWERTX_RATE5,
-			   AR_PHY_POWERTX_RATE5_POWERTXHT20_0);
-	training_power -= 4;
-
 	if (chain == 0)
 		reg = AR_PHY_PAPRD_MEM_TAB_B0;
 	else if (chain == 1)
@@ -620,26 +701,22 @@ void ar9003_paprd_populate_single_table(
 		      AR_PHY_PAPRD_CTRL1_PAPRD_POWER_AT_AM2AM_CAL,
 		      training_power);
 
-	REG_RMW_FIELD(ah, AR_PHY_PAPRD_CTRL1_B1,
-		      AR_PHY_PAPRD_CTRL1_PAPRD_POWER_AT_AM2AM_CAL,
-		      training_power);
+	if (ah->caps.tx_chainmask & BIT(1))
+		REG_RMW_FIELD(ah, AR_PHY_PAPRD_CTRL1_B1,
+			      AR_PHY_PAPRD_CTRL1_PAPRD_POWER_AT_AM2AM_CAL,
+			      training_power);
 
-	REG_RMW_FIELD(ah, AR_PHY_PAPRD_CTRL1_B2,
-		      AR_PHY_PAPRD_CTRL1_PAPRD_POWER_AT_AM2AM_CAL,
-		      training_power);
+	if (ah->caps.tx_chainmask & BIT(2))
+		REG_RMW_FIELD(ah, AR_PHY_PAPRD_CTRL1_B2,
+			      AR_PHY_PAPRD_CTRL1_PAPRD_POWER_AT_AM2AM_CAL,
+			      training_power);
 }
 EXPORT_SYMBOL(ar9003_paprd_populate_single_table);
 
 int ar9003_paprd_setup_gain_table(struct ath_hw *ah, int chain)
 {
-
 	unsigned int i, desired_gain, gain_index;
-	unsigned int train_power;
-
-	train_power = REG_READ_FIELD(ah, AR_PHY_POWERTX_RATE5,
-				     AR_PHY_POWERTX_RATE5_POWERTXHT20_0);
-
-	train_power = train_power - 4;
+	unsigned int train_power = ah->paprd_training_power;
 
 	desired_gain = ar9003_get_desired_gain(ah, chain, train_power);
 
@@ -705,7 +782,12 @@ EXPORT_SYMBOL(ar9003_paprd_create_curve)
 
 int ar9003_paprd_init_table(struct ath_hw *ah)
 {
-	ar9003_paprd_setup_single_table(ah);
+	int ret;
+
+	ret = ar9003_paprd_setup_single_table(ah);
+	if (ret < 0)
+	    return ret;
+
 	ar9003_paprd_get_gain_table(ah);
 	return 0;
 }
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/ar9003_phy.c linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/ar9003_phy.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/ar9003_phy.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/ar9003_phy.c	2011-03-14 21:20:32.000000000 -0400
@@ -75,7 +75,10 @@ static int ar9003_hw_set_channel(struct
 	freq = centers.synth_center;
 
 	if (freq < 4800) {     /* 2 GHz, fractional mode */
-		channelSel = CHANSEL_2G(freq);
+		if (AR_SREV_9485(ah))
+			channelSel = CHANSEL_2G_9485(freq);
+		else
+			channelSel = CHANSEL_2G(freq);
 		/* Set to 2G mode */
 		bMode = 1;
 	} else {
@@ -128,24 +131,53 @@ static int ar9003_hw_set_channel(struct
 static void ar9003_hw_spur_mitigate_mrc_cck(struct ath_hw *ah,
 					    struct ath9k_channel *chan)
 {
-	u32 spur_freq[4] = { 2420, 2440, 2464, 2480 };
+	static const u32 spur_freq[4] = { 2420, 2440, 2464, 2480 };
 	int cur_bb_spur, negative = 0, cck_spur_freq;
 	int i;
+	int range, max_spur_cnts, synth_freq;
+	u8 *spur_fbin_ptr = NULL;
 
 	/*
 	 * Need to verify range +/- 10 MHz in control channel, otherwise spur
 	 * is out-of-band and can be ignored.
 	 */
 
-	for (i = 0; i < 4; i++) {
+	if (AR_SREV_9485(ah)) {
+		spur_fbin_ptr = ar9003_get_spur_chan_ptr(ah,
+							 IS_CHAN_2GHZ(chan));
+		if (spur_fbin_ptr[0] == 0) /* No spur */
+			return;
+		max_spur_cnts = 5;
+		if (IS_CHAN_HT40(chan)) {
+			range = 19;
+			if (REG_READ_FIELD(ah, AR_PHY_GEN_CTRL,
+					   AR_PHY_GC_DYN2040_PRI_CH) == 0)
+				synth_freq = chan->channel + 10;
+			else
+				synth_freq = chan->channel - 10;
+		} else {
+			range = 10;
+			synth_freq = chan->channel;
+		}
+	} else {
+		range = 10;
+		max_spur_cnts = 4;
+		synth_freq = chan->channel;
+	}
+
+	for (i = 0; i < max_spur_cnts; i++) {
 		negative = 0;
-		cur_bb_spur = spur_freq[i] - chan->channel;
+		if (AR_SREV_9485(ah))
+			cur_bb_spur = FBIN2FREQ(spur_fbin_ptr[i],
+					IS_CHAN_2GHZ(chan)) - synth_freq;
+		else
+			cur_bb_spur = spur_freq[i] - synth_freq;
 
 		if (cur_bb_spur < 0) {
 			negative = 1;
 			cur_bb_spur = -cur_bb_spur;
 		}
-		if (cur_bb_spur < 10) {
+		if (cur_bb_spur < range) {
 			cck_spur_freq = (int)((cur_bb_spur << 19) / 11);
 
 			if (negative == 1)
@@ -487,7 +519,11 @@ void ar9003_hw_set_chain_masks(struct at
 		break;
 	}
 
-	REG_WRITE(ah, AR_SELFGEN_MASK, tx);
+	if ((ah->caps.hw_caps & ATH9K_HW_CAP_APM) && (tx == 0x7))
+		REG_WRITE(ah, AR_SELFGEN_MASK, 0x3);
+	else
+		REG_WRITE(ah, AR_SELFGEN_MASK, tx);
+
 	if (tx == 0x5) {
 		REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP,
 			    AR_PHY_SWAP_ALT_CHAIN);
@@ -542,10 +578,7 @@ static void ar9003_hw_prog_ini(struct at
 		u32 reg = INI_RA(iniArr, i, 0);
 		u32 val = INI_RA(iniArr, i, column);
 
-		if (reg >= 0x16000 && reg < 0x17000)
-			ath9k_hw_analog_shift_regwrite(ah, reg, val);
-		else
-			REG_WRITE(ah, reg, val);
+		REG_WRITE(ah, reg, val);
 
 		DO_DELAY(regWrites);
 	}
@@ -614,7 +647,7 @@ static int ar9003_hw_process_ini(struct
 				 channel->max_antenna_gain * 2,
 				 channel->max_power * 2,
 				 min((u32) MAX_RATE_POWER,
-				 (u32) regulatory->power_limit));
+				 (u32) regulatory->power_limit), false);
 
 	return 0;
 }
@@ -712,28 +745,6 @@ static void ar9003_hw_rfbus_done(struct
 	REG_WRITE(ah, AR_PHY_RFBUS_REQ, 0);
 }
 
-/*
- * Set the interrupt and GPIO values so the ISR can disable RF
- * on a switch signal.  Assumes GPIO port and interrupt polarity
- * are set prior to call.
- */
-static void ar9003_hw_enable_rfkill(struct ath_hw *ah)
-{
-	/* Connect rfsilent_bb_l to baseband */
-	REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL,
-		    AR_GPIO_INPUT_EN_VAL_RFSILENT_BB);
-	/* Set input mux for rfsilent_bb_l to GPIO #0 */
-	REG_CLR_BIT(ah, AR_GPIO_INPUT_MUX2,
-		    AR_GPIO_INPUT_MUX2_RFSILENT);
-
-	/*
-	 * Configure the desired GPIO port for input and
-	 * enable baseband rf silence.
-	 */
-	ath9k_hw_cfg_gpio_input(ah, ah->rfkill_gpio);
-	REG_SET_BIT(ah, AR_PHY_TEST, RFSILENT_BB);
-}
-
 static void ar9003_hw_set_diversity(struct ath_hw *ah, bool value)
 {
 	u32 v = REG_READ(ah, AR_PHY_CCK_DETECT);
@@ -820,12 +831,12 @@ static bool ar9003_hw_ani_control(struct
 				    AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
 
 		if (!on != aniState->ofdmWeakSigDetectOff) {
-			ath_print(common, ATH_DBG_ANI,
-				  "** ch %d: ofdm weak signal: %s=>%s\n",
-				  chan->channel,
-				  !aniState->ofdmWeakSigDetectOff ?
-					"on" : "off",
-				  on ? "on" : "off");
+			ath_dbg(common, ATH_DBG_ANI,
+				"** ch %d: ofdm weak signal: %s=>%s\n",
+				chan->channel,
+				!aniState->ofdmWeakSigDetectOff ?
+				"on" : "off",
+				on ? "on" : "off");
 			if (on)
 				ah->stats.ast_ani_ofdmon++;
 			else
@@ -838,11 +849,9 @@ static bool ar9003_hw_ani_control(struct
 		u32 level = param;
 
 		if (level >= ARRAY_SIZE(firstep_table)) {
-			ath_print(common, ATH_DBG_ANI,
-				  "ATH9K_ANI_FIRSTEP_LEVEL: level "
-				  "out of range (%u > %u)\n",
-				  level,
-				  (unsigned) ARRAY_SIZE(firstep_table));
+			ath_dbg(common, ATH_DBG_ANI,
+				"ATH9K_ANI_FIRSTEP_LEVEL: level out of range (%u > %zu)\n",
+				level, ARRAY_SIZE(firstep_table));
 			return false;
 		}
 
@@ -877,24 +886,22 @@ static bool ar9003_hw_ani_control(struct
 			      AR_PHY_FIND_SIG_LOW_FIRSTEP_LOW, value2);
 
 		if (level != aniState->firstepLevel) {
-			ath_print(common, ATH_DBG_ANI,
-				  "** ch %d: level %d=>%d[def:%d] "
-				  "firstep[level]=%d ini=%d\n",
-				  chan->channel,
-				  aniState->firstepLevel,
-				  level,
-				  ATH9K_ANI_FIRSTEP_LVL_NEW,
-				  value,
-				  aniState->iniDef.firstep);
-			ath_print(common, ATH_DBG_ANI,
-				  "** ch %d: level %d=>%d[def:%d] "
-				  "firstep_low[level]=%d ini=%d\n",
-				  chan->channel,
-				  aniState->firstepLevel,
-				  level,
-				  ATH9K_ANI_FIRSTEP_LVL_NEW,
-				  value2,
-				  aniState->iniDef.firstepLow);
+			ath_dbg(common, ATH_DBG_ANI,
+				"** ch %d: level %d=>%d[def:%d] firstep[level]=%d ini=%d\n",
+				chan->channel,
+				aniState->firstepLevel,
+				level,
+				ATH9K_ANI_FIRSTEP_LVL_NEW,
+				value,
+				aniState->iniDef.firstep);
+			ath_dbg(common, ATH_DBG_ANI,
+				"** ch %d: level %d=>%d[def:%d] firstep_low[level]=%d ini=%d\n",
+				chan->channel,
+				aniState->firstepLevel,
+				level,
+				ATH9K_ANI_FIRSTEP_LVL_NEW,
+				value2,
+				aniState->iniDef.firstepLow);
 			if (level > aniState->firstepLevel)
 				ah->stats.ast_ani_stepup++;
 			else if (level < aniState->firstepLevel)
@@ -907,11 +914,9 @@ static bool ar9003_hw_ani_control(struct
 		u32 level = param;
 
 		if (level >= ARRAY_SIZE(cycpwrThr1_table)) {
-			ath_print(common, ATH_DBG_ANI,
-				  "ATH9K_ANI_SPUR_IMMUNITY_LEVEL: level "
-				  "out of range (%u > %u)\n",
-				  level,
-				  (unsigned) ARRAY_SIZE(cycpwrThr1_table));
+			ath_dbg(common, ATH_DBG_ANI,
+				"ATH9K_ANI_SPUR_IMMUNITY_LEVEL: level out of range (%u > %zu)\n",
+				level, ARRAY_SIZE(cycpwrThr1_table));
 			return false;
 		}
 		/*
@@ -945,24 +950,22 @@ static bool ar9003_hw_ani_control(struct
 			      AR_PHY_EXT_CYCPWR_THR1, value2);
 
 		if (level != aniState->spurImmunityLevel) {
-			ath_print(common, ATH_DBG_ANI,
-				  "** ch %d: level %d=>%d[def:%d] "
-				  "cycpwrThr1[level]=%d ini=%d\n",
-				  chan->channel,
-				  aniState->spurImmunityLevel,
-				  level,
-				  ATH9K_ANI_SPUR_IMMUNE_LVL_NEW,
-				  value,
-				  aniState->iniDef.cycpwrThr1);
-			ath_print(common, ATH_DBG_ANI,
-				  "** ch %d: level %d=>%d[def:%d] "
-				  "cycpwrThr1Ext[level]=%d ini=%d\n",
-				  chan->channel,
-				  aniState->spurImmunityLevel,
-				  level,
-				  ATH9K_ANI_SPUR_IMMUNE_LVL_NEW,
-				  value2,
-				  aniState->iniDef.cycpwrThr1Ext);
+			ath_dbg(common, ATH_DBG_ANI,
+				"** ch %d: level %d=>%d[def:%d] cycpwrThr1[level]=%d ini=%d\n",
+				chan->channel,
+				aniState->spurImmunityLevel,
+				level,
+				ATH9K_ANI_SPUR_IMMUNE_LVL_NEW,
+				value,
+				aniState->iniDef.cycpwrThr1);
+			ath_dbg(common, ATH_DBG_ANI,
+				"** ch %d: level %d=>%d[def:%d] cycpwrThr1Ext[level]=%d ini=%d\n",
+				chan->channel,
+				aniState->spurImmunityLevel,
+				level,
+				ATH9K_ANI_SPUR_IMMUNE_LVL_NEW,
+				value2,
+				aniState->iniDef.cycpwrThr1Ext);
 			if (level > aniState->spurImmunityLevel)
 				ah->stats.ast_ani_spurup++;
 			else if (level < aniState->spurImmunityLevel)
@@ -982,11 +985,11 @@ static bool ar9003_hw_ani_control(struct
 		REG_RMW_FIELD(ah, AR_PHY_MRC_CCK_CTRL,
 			      AR_PHY_MRC_CCK_MUX_REG, is_on);
 		if (!is_on != aniState->mrcCCKOff) {
-			ath_print(common, ATH_DBG_ANI,
-				  "** ch %d: MRC CCK: %s=>%s\n",
-				  chan->channel,
-				  !aniState->mrcCCKOff ? "on" : "off",
-				  is_on ? "on" : "off");
+			ath_dbg(common, ATH_DBG_ANI,
+				"** ch %d: MRC CCK: %s=>%s\n",
+				chan->channel,
+				!aniState->mrcCCKOff ? "on" : "off",
+				is_on ? "on" : "off");
 		if (is_on)
 			ah->stats.ast_ani_ccklow++;
 		else
@@ -998,22 +1001,19 @@ static bool ar9003_hw_ani_control(struct
 	case ATH9K_ANI_PRESENT:
 		break;
 	default:
-		ath_print(common, ATH_DBG_ANI,
-			  "invalid cmd %u\n", cmd);
+		ath_dbg(common, ATH_DBG_ANI, "invalid cmd %u\n", cmd);
 		return false;
 	}
 
-	ath_print(common, ATH_DBG_ANI,
-		  "ANI parameters: SI=%d, ofdmWS=%s FS=%d "
-		  "MRCcck=%s listenTime=%d "
-		  "ofdmErrs=%d cckErrs=%d\n",
-		  aniState->spurImmunityLevel,
-		  !aniState->ofdmWeakSigDetectOff ? "on" : "off",
-		  aniState->firstepLevel,
-		  !aniState->mrcCCKOff ? "on" : "off",
-		  aniState->listenTime,
-		  aniState->ofdmPhyErrCount,
-		  aniState->cckPhyErrCount);
+	ath_dbg(common, ATH_DBG_ANI,
+		"ANI parameters: SI=%d, ofdmWS=%s FS=%d MRCcck=%s listenTime=%d ofdmErrs=%d cckErrs=%d\n",
+		aniState->spurImmunityLevel,
+		!aniState->ofdmWeakSigDetectOff ? "on" : "off",
+		aniState->firstepLevel,
+		!aniState->mrcCCKOff ? "on" : "off",
+		aniState->listenTime,
+		aniState->ofdmPhyErrCount,
+		aniState->cckPhyErrCount);
 	return true;
 }
 
@@ -1023,25 +1023,25 @@ static void ar9003_hw_do_getnf(struct at
 	int16_t nf;
 
 	nf = MS(REG_READ(ah, AR_PHY_CCA_0), AR_PHY_MINCCA_PWR);
-	nfarray[0] = sign_extend(nf, 9);
+	nfarray[0] = sign_extend32(nf, 8);
 
 	nf = MS(REG_READ(ah, AR_PHY_CCA_1), AR_PHY_CH1_MINCCA_PWR);
-	nfarray[1] = sign_extend(nf, 9);
+	nfarray[1] = sign_extend32(nf, 8);
 
 	nf = MS(REG_READ(ah, AR_PHY_CCA_2), AR_PHY_CH2_MINCCA_PWR);
-	nfarray[2] = sign_extend(nf, 9);
+	nfarray[2] = sign_extend32(nf, 8);
 
 	if (!IS_CHAN_HT40(ah->curchan))
 		return;
 
 	nf = MS(REG_READ(ah, AR_PHY_EXT_CCA), AR_PHY_EXT_MINCCA_PWR);
-	nfarray[3] = sign_extend(nf, 9);
+	nfarray[3] = sign_extend32(nf, 8);
 
 	nf = MS(REG_READ(ah, AR_PHY_EXT_CCA_1), AR_PHY_CH1_EXT_MINCCA_PWR);
-	nfarray[4] = sign_extend(nf, 9);
+	nfarray[4] = sign_extend32(nf, 8);
 
 	nf = MS(REG_READ(ah, AR_PHY_EXT_CCA_2), AR_PHY_CH2_EXT_MINCCA_PWR);
-	nfarray[5] = sign_extend(nf, 9);
+	nfarray[5] = sign_extend32(nf, 8);
 }
 
 static void ar9003_hw_set_nf_limits(struct ath_hw *ah)
@@ -1070,13 +1070,13 @@ static void ar9003_hw_ani_cache_ini_regs
 	aniState = &ah->curchan->ani;
 	iniDef = &aniState->iniDef;
 
-	ath_print(common, ATH_DBG_ANI,
-		  "ver %d.%d opmode %u chan %d Mhz/0x%x\n",
-		  ah->hw_version.macVersion,
-		  ah->hw_version.macRev,
-		  ah->opmode,
-		  chan->channel,
-		  chan->channelFlags);
+	ath_dbg(common, ATH_DBG_ANI,
+		"ver %d.%d opmode %u chan %d Mhz/0x%x\n",
+		ah->hw_version.macVersion,
+		ah->hw_version.macRev,
+		ah->opmode,
+		chan->channel,
+		chan->channelFlags);
 
 	val = REG_READ(ah, AR_PHY_SFCORR);
 	iniDef->m1Thresh = MS(val, AR_PHY_SFCORR_M1_THRESH);
@@ -1113,10 +1113,55 @@ static void ar9003_hw_ani_cache_ini_regs
 	aniState->mrcCCKOff = !ATH9K_ANI_ENABLE_MRC_CCK;
 }
 
+static void ar9003_hw_set_radar_params(struct ath_hw *ah,
+				       struct ath_hw_radar_conf *conf)
+{
+	u32 radar_0 = 0, radar_1 = 0;
+
+	if (!conf) {
+		REG_CLR_BIT(ah, AR_PHY_RADAR_0, AR_PHY_RADAR_0_ENA);
+		return;
+	}
+
+	radar_0 |= AR_PHY_RADAR_0_ENA | AR_PHY_RADAR_0_FFT_ENA;
+	radar_0 |= SM(conf->fir_power, AR_PHY_RADAR_0_FIRPWR);
+	radar_0 |= SM(conf->radar_rssi, AR_PHY_RADAR_0_RRSSI);
+	radar_0 |= SM(conf->pulse_height, AR_PHY_RADAR_0_HEIGHT);
+	radar_0 |= SM(conf->pulse_rssi, AR_PHY_RADAR_0_PRSSI);
+	radar_0 |= SM(conf->pulse_inband, AR_PHY_RADAR_0_INBAND);
+
+	radar_1 |= AR_PHY_RADAR_1_MAX_RRSSI;
+	radar_1 |= AR_PHY_RADAR_1_BLOCK_CHECK;
+	radar_1 |= SM(conf->pulse_maxlen, AR_PHY_RADAR_1_MAXLEN);
+	radar_1 |= SM(conf->pulse_inband_step, AR_PHY_RADAR_1_RELSTEP_THRESH);
+	radar_1 |= SM(conf->radar_inband, AR_PHY_RADAR_1_RELPWR_THRESH);
+
+	REG_WRITE(ah, AR_PHY_RADAR_0, radar_0);
+	REG_WRITE(ah, AR_PHY_RADAR_1, radar_1);
+	if (conf->ext_channel)
+		REG_SET_BIT(ah, AR_PHY_RADAR_EXT, AR_PHY_RADAR_EXT_ENA);
+	else
+		REG_CLR_BIT(ah, AR_PHY_RADAR_EXT, AR_PHY_RADAR_EXT_ENA);
+}
+
+static void ar9003_hw_set_radar_conf(struct ath_hw *ah)
+{
+	struct ath_hw_radar_conf *conf = &ah->radar_conf;
+
+	conf->fir_power = -28;
+	conf->radar_rssi = 0;
+	conf->pulse_height = 10;
+	conf->pulse_rssi = 24;
+	conf->pulse_inband = 8;
+	conf->pulse_maxlen = 255;
+	conf->pulse_inband_step = 12;
+	conf->radar_inband = 8;
+}
+
 void ar9003_hw_attach_phy_ops(struct ath_hw *ah)
 {
 	struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
-	const u32 ar9300_cca_regs[6] = {
+	static const u32 ar9300_cca_regs[6] = {
 		AR_PHY_CCA_0,
 		AR_PHY_CCA_1,
 		AR_PHY_CCA_2,
@@ -1136,13 +1181,14 @@ void ar9003_hw_attach_phy_ops(struct ath
 	priv_ops->set_delta_slope = ar9003_hw_set_delta_slope;
 	priv_ops->rfbus_req = ar9003_hw_rfbus_req;
 	priv_ops->rfbus_done = ar9003_hw_rfbus_done;
-	priv_ops->enable_rfkill = ar9003_hw_enable_rfkill;
 	priv_ops->set_diversity = ar9003_hw_set_diversity;
 	priv_ops->ani_control = ar9003_hw_ani_control;
 	priv_ops->do_getnf = ar9003_hw_do_getnf;
 	priv_ops->ani_cache_ini_regs = ar9003_hw_ani_cache_ini_regs;
+	priv_ops->set_radar_params = ar9003_hw_set_radar_params;
 
 	ar9003_hw_set_nf_limits(ah);
+	ar9003_hw_set_radar_conf(ah);
 	memcpy(ah->nf_regs, ar9300_cca_regs, sizeof(ah->nf_regs));
 }
 
@@ -1165,7 +1211,7 @@ void ar9003_hw_bb_watchdog_config(struct
 			  ~(AR_PHY_WATCHDOG_NON_IDLE_ENABLE |
 			    AR_PHY_WATCHDOG_IDLE_ENABLE));
 
-		ath_print(common, ATH_DBG_RESET, "Disabled BB Watchdog\n");
+		ath_dbg(common, ATH_DBG_RESET, "Disabled BB Watchdog\n");
 		return;
 	}
 
@@ -1201,9 +1247,9 @@ void ar9003_hw_bb_watchdog_config(struct
 		  AR_PHY_WATCHDOG_IDLE_MASK |
 		  (AR_PHY_WATCHDOG_NON_IDLE_MASK & (idle_count << 2)));
 
-	ath_print(common, ATH_DBG_RESET,
-		  "Enabled BB Watchdog timeout (%u ms)\n",
-		  idle_tmo_ms);
+	ath_dbg(common, ATH_DBG_RESET,
+		"Enabled BB Watchdog timeout (%u ms)\n",
+		idle_tmo_ms);
 }
 
 void ar9003_hw_bb_watchdog_read(struct ath_hw *ah)
@@ -1231,37 +1277,35 @@ void ar9003_hw_bb_watchdog_dbg_info(stru
 		return;
 
 	status = ah->bb_watchdog_last_status;
-	ath_print(common, ATH_DBG_RESET,
-		  "\n==== BB update: BB status=0x%08x ====\n", status);
-	ath_print(common, ATH_DBG_RESET,
-		  "** BB state: wd=%u det=%u rdar=%u rOFDM=%d "
-		  "rCCK=%u tOFDM=%u tCCK=%u agc=%u src=%u **\n",
-		  MS(status, AR_PHY_WATCHDOG_INFO),
-		  MS(status, AR_PHY_WATCHDOG_DET_HANG),
-		  MS(status, AR_PHY_WATCHDOG_RADAR_SM),
-		  MS(status, AR_PHY_WATCHDOG_RX_OFDM_SM),
-		  MS(status, AR_PHY_WATCHDOG_RX_CCK_SM),
-		  MS(status, AR_PHY_WATCHDOG_TX_OFDM_SM),
-		  MS(status, AR_PHY_WATCHDOG_TX_CCK_SM),
-		  MS(status, AR_PHY_WATCHDOG_AGC_SM),
-		  MS(status,AR_PHY_WATCHDOG_SRCH_SM));
+	ath_dbg(common, ATH_DBG_RESET,
+		"\n==== BB update: BB status=0x%08x ====\n", status);
+	ath_dbg(common, ATH_DBG_RESET,
+		"** BB state: wd=%u det=%u rdar=%u rOFDM=%d rCCK=%u tOFDM=%u tCCK=%u agc=%u src=%u **\n",
+		MS(status, AR_PHY_WATCHDOG_INFO),
+		MS(status, AR_PHY_WATCHDOG_DET_HANG),
+		MS(status, AR_PHY_WATCHDOG_RADAR_SM),
+		MS(status, AR_PHY_WATCHDOG_RX_OFDM_SM),
+		MS(status, AR_PHY_WATCHDOG_RX_CCK_SM),
+		MS(status, AR_PHY_WATCHDOG_TX_OFDM_SM),
+		MS(status, AR_PHY_WATCHDOG_TX_CCK_SM),
+		MS(status, AR_PHY_WATCHDOG_AGC_SM),
+		MS(status, AR_PHY_WATCHDOG_SRCH_SM));
 
-	ath_print(common, ATH_DBG_RESET,
-		  "** BB WD cntl: cntl1=0x%08x cntl2=0x%08x **\n",
-		  REG_READ(ah, AR_PHY_WATCHDOG_CTL_1),
-		  REG_READ(ah, AR_PHY_WATCHDOG_CTL_2));
-	ath_print(common, ATH_DBG_RESET,
-		  "** BB mode: BB_gen_controls=0x%08x **\n",
-		  REG_READ(ah, AR_PHY_GEN_CTRL));
+	ath_dbg(common, ATH_DBG_RESET,
+		"** BB WD cntl: cntl1=0x%08x cntl2=0x%08x **\n",
+		REG_READ(ah, AR_PHY_WATCHDOG_CTL_1),
+		REG_READ(ah, AR_PHY_WATCHDOG_CTL_2));
+	ath_dbg(common, ATH_DBG_RESET,
+		"** BB mode: BB_gen_controls=0x%08x **\n",
+		REG_READ(ah, AR_PHY_GEN_CTRL));
 
 #define PCT(_field) (common->cc_survey._field * 100 / common->cc_survey.cycles)
 	if (common->cc_survey.cycles)
-		ath_print(common, ATH_DBG_RESET,
-			  "** BB busy times: rx_clear=%d%%, "
-			  "rx_frame=%d%%, tx_frame=%d%% **\n",
-			  PCT(rx_busy), PCT(rx_frame), PCT(tx_frame));
+		ath_dbg(common, ATH_DBG_RESET,
+			"** BB busy times: rx_clear=%d%%, rx_frame=%d%%, tx_frame=%d%% **\n",
+			PCT(rx_busy), PCT(rx_frame), PCT(tx_frame));
 
-	ath_print(common, ATH_DBG_RESET,
-		  "==== BB update: done ====\n\n");
+	ath_dbg(common, ATH_DBG_RESET,
+		"==== BB update: done ====\n\n");
 }
 EXPORT_SYMBOL(ar9003_hw_bb_watchdog_dbg_info);
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/ar9003_phy.h linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/ar9003_phy.h
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/ar9003_phy.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/ar9003_phy.h	2011-03-14 21:20:32.000000000 -0400
@@ -260,7 +260,13 @@
 #define AR_PHY_CCA_0            (AR_AGC_BASE + 0x1c)
 #define AR_PHY_EXT_CCA0         (AR_AGC_BASE + 0x20)
 #define AR_PHY_RESTART          (AR_AGC_BASE + 0x24)
+
 #define AR_PHY_MC_GAIN_CTRL     (AR_AGC_BASE + 0x28)
+#define AR_ANT_DIV_CTRL_ALL	0x7e000000
+#define AR_ANT_DIV_CTRL_ALL_S	25
+#define AR_ANT_DIV_ENABLE	0x1000000
+#define AR_ANT_DIV_ENABLE_S	24
+
 #define AR_PHY_EXTCHN_PWRTHR1   (AR_AGC_BASE + 0x2c)
 #define AR_PHY_EXT_CHN_WIN      (AR_AGC_BASE + 0x30)
 #define AR_PHY_20_40_DET_THR    (AR_AGC_BASE + 0x34)
@@ -271,7 +277,11 @@
 #define AR_PHY_RX_GAIN_BOUNDS_2 (AR_AGC_BASE + 0x48)
 #define AR_PHY_RSSI_0           (AR_AGC_BASE + 0x180)
 #define AR_PHY_SPUR_CCK_REP0    (AR_AGC_BASE + 0x184)
+
 #define AR_PHY_CCK_DETECT       (AR_AGC_BASE + 0x1c0)
+#define AR_FAST_DIV_ENABLE	0x2000
+#define AR_FAST_DIV_ENABLE_S	13
+
 #define AR_PHY_DAG_CTRLCCK      (AR_AGC_BASE + 0x1c4)
 #define AR_PHY_IQCORR_CTRL_CCK  (AR_AGC_BASE + 0x1c8)
 
@@ -536,10 +546,18 @@
 
 #define AR_PHY_TXGAIN_TABLE      (AR_SM_BASE + 0x300)
 
+#define AR_PHY_TX_IQCAL_START_9485		(AR_SM_BASE + 0x3c4)
+#define AR_PHY_TX_IQCAL_START_DO_CAL_9485	0x80000000
+#define AR_PHY_TX_IQCAL_START_DO_CAL_9485_S	31
+#define AR_PHY_TX_IQCAL_CONTROL_1_9485		(AR_SM_BASE + 0x3c8)
+#define AR_PHY_TX_IQCAL_STATUS_B0_9485		(AR_SM_BASE + 0x3f0)
+
 #define AR_PHY_TX_IQCAL_CONTROL_1   (AR_SM_BASE + 0x448)
 #define AR_PHY_TX_IQCAL_START       (AR_SM_BASE + 0x440)
 #define AR_PHY_TX_IQCAL_STATUS_B0   (AR_SM_BASE + 0x48c)
-#define AR_PHY_TX_IQCAL_CORR_COEFF_01_B0    (AR_SM_BASE + 0x450)
+#define AR_PHY_TX_IQCAL_CORR_COEFF_B0(_i)    (AR_SM_BASE + \
+					     (AR_SREV_9485(ah) ? \
+					      0x3d0 : 0x450) + ((_i) << 2))
 
 #define AR_PHY_WATCHDOG_STATUS      (AR_SM_BASE + 0x5c0)
 #define AR_PHY_WATCHDOG_CTL_1       (AR_SM_BASE + 0x5c4)
@@ -568,7 +586,7 @@
 #define AR_PHY_65NM_CH0_BIAS2       0x160c4
 #define AR_PHY_65NM_CH0_BIAS4       0x160cc
 #define AR_PHY_65NM_CH0_RXTX4       0x1610c
-#define AR_PHY_65NM_CH0_THERM       0x16290
+#define AR_PHY_65NM_CH0_THERM       (AR_SREV_9485(ah) ? 0x1628c : 0x16290)
 
 #define AR_PHY_65NM_CH0_THERM_LOCAL   0x80000000
 #define AR_PHY_65NM_CH0_THERM_LOCAL_S 31
@@ -584,6 +602,24 @@
 #define AR_PHY_65NM_CH2_RXTX1       0x16900
 #define AR_PHY_65NM_CH2_RXTX2       0x16904
 
+#define AR_CH0_TOP2 (AR_SREV_9485(ah) ? 0x00016284 : 0x0001628c)
+#define AR_CH0_TOP2_XPABIASLVL		0xf000
+#define AR_CH0_TOP2_XPABIASLVL_S	12
+
+#define AR_CH0_XTAL		(AR_SREV_9485(ah) ? 0x16290 : 0x16294)
+#define AR_CH0_XTAL_CAPINDAC	0x7f000000
+#define AR_CH0_XTAL_CAPINDAC_S	24
+#define AR_CH0_XTAL_CAPOUTDAC	0x00fe0000
+#define AR_CH0_XTAL_CAPOUTDAC_S	17
+
+#define AR_PHY_PMU1		0x16c40
+#define AR_PHY_PMU1_PWD		0x1
+#define AR_PHY_PMU1_PWD_S	0
+
+#define AR_PHY_PMU2		0x16c44
+#define AR_PHY_PMU2_PGM		0x00200000
+#define AR_PHY_PMU2_PGM_S	21
+
 #define AR_PHY_RX1DB_BIQUAD_LONG_SHIFT		0x00380000
 #define AR_PHY_RX1DB_BIQUAD_LONG_SHIFT_S	19
 #define AR_PHY_RX6DB_BIQUAD_LONG_SHIFT		0x00c00000
@@ -683,6 +719,7 @@
 #define AR_PHY_TPCGR1_FORCED_DAC_GAIN_S 1
 #define AR_PHY_TPCGR1_FORCE_DAC_GAIN    0x00000001
 #define AR_PHY_TXGAIN_FORCE               0x00000001
+#define AR_PHY_TXGAIN_FORCE_S		  0
 #define AR_PHY_TXGAIN_FORCED_PADVGNRA     0x00003c00
 #define AR_PHY_TXGAIN_FORCED_PADVGNRA_S   10
 #define AR_PHY_TXGAIN_FORCED_PADVGNRB     0x0003c000
@@ -725,8 +762,13 @@
 #define AR_PHY_TX_IQCAL_START_DO_CAL_S      0
 
 #define AR_PHY_TX_IQCAL_STATUS_FAILED    0x00000001
-#define AR_PHY_TX_IQCAL_CORR_COEFF_01_COEFF_TABLE      0x00003fff
-#define AR_PHY_TX_IQCAL_CORR_COEFF_01_COEFF_TABLE_S    0
+#define AR_PHY_CALIBRATED_GAINS_0	 0x3e
+#define AR_PHY_CALIBRATED_GAINS_0_S	 1
+
+#define AR_PHY_TX_IQCAL_CORR_COEFF_00_COEFF_TABLE      0x00003fff
+#define AR_PHY_TX_IQCAL_CORR_COEFF_00_COEFF_TABLE_S    0
+#define AR_PHY_TX_IQCAL_CORR_COEFF_01_COEFF_TABLE      0x0fffc000
+#define AR_PHY_TX_IQCAL_CORR_COEFF_01_COEFF_TABLE_S    14
 
 #define AR_PHY_65NM_CH0_RXTX4_THERM_ON          0x10000000
 #define AR_PHY_65NM_CH0_RXTX4_THERM_ON_S        28
@@ -785,7 +827,7 @@
 #define AR_PHY_TPC_11_B1         (AR_SM1_BASE + 0x220)
 #define AR_PHY_PDADC_TAB_1       (AR_SM1_BASE + 0x240)
 #define AR_PHY_TX_IQCAL_STATUS_B1   (AR_SM1_BASE + 0x48c)
-#define AR_PHY_TX_IQCAL_CORR_COEFF_01_B1    (AR_SM1_BASE + 0x450)
+#define AR_PHY_TX_IQCAL_CORR_COEFF_B1(_i)    (AR_SM_BASE + 0x450 + ((_i) << 2))
 
 /*
  * Channel 2 Register Map
@@ -838,7 +880,7 @@
 #define AR_PHY_TPC_11_B2         (AR_SM2_BASE + 0x220)
 #define AR_PHY_PDADC_TAB_2       (AR_SM2_BASE + 0x240)
 #define AR_PHY_TX_IQCAL_STATUS_B2   (AR_SM2_BASE + 0x48c)
-#define AR_PHY_TX_IQCAL_CORR_COEFF_01_B2    (AR_SM2_BASE + 0x450)
+#define AR_PHY_TX_IQCAL_CORR_COEFF_B2(_i)    (AR_SM2_BASE + 0x450 + ((_i) << 2))
 
 #define AR_PHY_TX_IQCAL_STATUS_B2_FAILED    0x00000001
 
@@ -945,7 +987,9 @@
 #define AR_PHY_PAPRD_CTRL1_PAPRD_MAG_SCALE_FACT		0x0ffe0000
 #define AR_PHY_PAPRD_CTRL1_PAPRD_MAG_SCALE_FACT_S	17
 
-#define AR_PHY_PAPRD_TRAINER_CNTL1				(AR_SM_BASE + 0x490)
+#define AR_PHY_PAPRD_TRAINER_CNTL1				(AR_SM_BASE + \
+								 (AR_SREV_9485(ah) ? \
+								  0x580 : 0x490))
 #define AR_PHY_PAPRD_TRAINER_CNTL1_CF_CF_PAPRD_TRAIN_ENABLE	0x00000001
 #define AR_PHY_PAPRD_TRAINER_CNTL1_CF_CF_PAPRD_TRAIN_ENABLE_S	0
 #define AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_AGC2_SETTLING	0x0000007e
@@ -961,11 +1005,15 @@
 #define AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_LB_SKIP		0x0003f000
 #define AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_LB_SKIP_S		12
 
-#define AR_PHY_PAPRD_TRAINER_CNTL2				(AR_SM_BASE + 0x494)
+#define AR_PHY_PAPRD_TRAINER_CNTL2				(AR_SM_BASE + \
+								 (AR_SREV_9485(ah) ? \
+								  0x584 : 0x494))
 #define AR_PHY_PAPRD_TRAINER_CNTL2_CF_PAPRD_INIT_RX_BB_GAIN	0xFFFFFFFF
 #define AR_PHY_PAPRD_TRAINER_CNTL2_CF_PAPRD_INIT_RX_BB_GAIN_S	0
 
-#define AR_PHY_PAPRD_TRAINER_CNTL3				(AR_SM_BASE + 0x498)
+#define AR_PHY_PAPRD_TRAINER_CNTL3				(AR_SM_BASE + \
+								 (AR_SREV_9485(ah) ? \
+								  0x588 : 0x498))
 #define AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_ADC_DESIRED_SIZE	0x0000003f
 #define AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_ADC_DESIRED_SIZE_S	0
 #define AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_QUICK_DROP		0x00000fc0
@@ -981,7 +1029,9 @@
 #define AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_BBTXMIX_DISABLE	0x20000000
 #define AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_BBTXMIX_DISABLE_S	29
 
-#define AR_PHY_PAPRD_TRAINER_CNTL4				(AR_SM_BASE + 0x49c)
+#define AR_PHY_PAPRD_TRAINER_CNTL4				(AR_SM_BASE + \
+								 (AR_SREV_9485(ah) ? \
+								  0x58c : 0x49c))
 #define AR_PHY_PAPRD_TRAINER_CNTL4_CF_PAPRD_NUM_TRAIN_SAMPLES	0x03ff0000
 #define AR_PHY_PAPRD_TRAINER_CNTL4_CF_PAPRD_NUM_TRAIN_SAMPLES_S	16
 #define AR_PHY_PAPRD_TRAINER_CNTL4_CF_PAPRD_SAFETY_DELTA	0x0000f000
@@ -1040,6 +1090,14 @@
 #define AR_PHY_POWERTX_RATE5_POWERTXHT20_0	0x3F
 #define AR_PHY_POWERTX_RATE5_POWERTXHT20_0_S	0
 
+#define AR_PHY_POWERTX_RATE6			(AR_SM_BASE + 0x1d4)
+#define AR_PHY_POWERTX_RATE6_POWERTXHT20_5	0x3F00
+#define AR_PHY_POWERTX_RATE6_POWERTXHT20_5_S	8
+
+#define AR_PHY_POWERTX_RATE8			(AR_SM_BASE + 0x1dc)
+#define AR_PHY_POWERTX_RATE8_POWERTXHT40_5	0x3F00
+#define AR_PHY_POWERTX_RATE8_POWERTXHT40_5_S	8
+
 void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx);
 
 #endif  /* AR9003_PHY_H */
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/ar9485_initvals.h linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/ar9485_initvals.h
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/ar9485_initvals.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/ar9485_initvals.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,943 @@
+/*
+ * Copyright (c) 2010 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef INITVALS_9485_H
+#define INITVALS_9485_H
+
+static const u32 ar9485Common_1_0[][2] = {
+	/*   Addr     allmodes */
+	{0x00007010, 0x00000022},
+	{0x00007020, 0x00000000},
+	{0x00007034, 0x00000002},
+	{0x00007038, 0x000004c2},
+};
+
+static const u32 ar9485_1_0_mac_postamble[][5] = {
+	/* Addr     5G_HT20     5G_HT40     2G_HT40     2G_HT20    */
+	{0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160},
+	{0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c},
+	{0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38},
+	{0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00},
+	{0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b},
+	{0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810},
+	{0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a},
+	{0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440},
+};
+
+static const u32 ar9485_1_0_pcie_phy_pll_on_clkreq_disable_L1[][2] = {
+	/*   Addr     allmodes */
+	{0x00018c00, 0x10212e5e},
+	{0x00018c04, 0x000801d8},
+	{0x00018c08, 0x0000580c},
+};
+
+static const u32 ar9485Common_wo_xlna_rx_gain_1_0[][2] = {
+	/*   Addr     allmodes */
+	{0x0000a000, 0x00010000},
+	{0x0000a004, 0x00030002},
+	{0x0000a008, 0x00050004},
+	{0x0000a00c, 0x00810080},
+	{0x0000a010, 0x01800082},
+	{0x0000a014, 0x01820181},
+	{0x0000a018, 0x01840183},
+	{0x0000a01c, 0x01880185},
+	{0x0000a020, 0x018a0189},
+	{0x0000a024, 0x02850284},
+	{0x0000a028, 0x02890288},
+	{0x0000a02c, 0x03850384},
+	{0x0000a030, 0x03890388},
+	{0x0000a034, 0x038b038a},
+	{0x0000a038, 0x038d038c},
+	{0x0000a03c, 0x03910390},
+	{0x0000a040, 0x03930392},
+	{0x0000a044, 0x03950394},
+	{0x0000a048, 0x00000396},
+	{0x0000a04c, 0x00000000},
+	{0x0000a050, 0x00000000},
+	{0x0000a054, 0x00000000},
+	{0x0000a058, 0x00000000},
+	{0x0000a05c, 0x00000000},
+	{0x0000a060, 0x00000000},
+	{0x0000a064, 0x00000000},
+	{0x0000a068, 0x00000000},
+	{0x0000a06c, 0x00000000},
+	{0x0000a070, 0x00000000},
+	{0x0000a074, 0x00000000},
+	{0x0000a078, 0x00000000},
+	{0x0000a07c, 0x00000000},
+	{0x0000a080, 0x28282828},
+	{0x0000a084, 0x28282828},
+	{0x0000a088, 0x28282828},
+	{0x0000a08c, 0x28282828},
+	{0x0000a090, 0x28282828},
+	{0x0000a094, 0x21212128},
+	{0x0000a098, 0x171c1c1c},
+	{0x0000a09c, 0x02020212},
+	{0x0000a0a0, 0x00000202},
+	{0x0000a0a4, 0x00000000},
+	{0x0000a0a8, 0x00000000},
+	{0x0000a0ac, 0x00000000},
+	{0x0000a0b0, 0x00000000},
+	{0x0000a0b4, 0x00000000},
+	{0x0000a0b8, 0x00000000},
+	{0x0000a0bc, 0x00000000},
+	{0x0000a0c0, 0x001f0000},
+	{0x0000a0c4, 0x111f1100},
+	{0x0000a0c8, 0x111d111e},
+	{0x0000a0cc, 0x111b111c},
+	{0x0000a0d0, 0x22032204},
+	{0x0000a0d4, 0x22012202},
+	{0x0000a0d8, 0x221f2200},
+	{0x0000a0dc, 0x221d221e},
+	{0x0000a0e0, 0x33013302},
+	{0x0000a0e4, 0x331f3300},
+	{0x0000a0e8, 0x4402331e},
+	{0x0000a0ec, 0x44004401},
+	{0x0000a0f0, 0x441e441f},
+	{0x0000a0f4, 0x55015502},
+	{0x0000a0f8, 0x551f5500},
+	{0x0000a0fc, 0x6602551e},
+	{0x0000a100, 0x66006601},
+	{0x0000a104, 0x661e661f},
+	{0x0000a108, 0x7703661d},
+	{0x0000a10c, 0x77017702},
+	{0x0000a110, 0x00007700},
+	{0x0000a114, 0x00000000},
+	{0x0000a118, 0x00000000},
+	{0x0000a11c, 0x00000000},
+	{0x0000a120, 0x00000000},
+	{0x0000a124, 0x00000000},
+	{0x0000a128, 0x00000000},
+	{0x0000a12c, 0x00000000},
+	{0x0000a130, 0x00000000},
+	{0x0000a134, 0x00000000},
+	{0x0000a138, 0x00000000},
+	{0x0000a13c, 0x00000000},
+	{0x0000a140, 0x001f0000},
+	{0x0000a144, 0x111f1100},
+	{0x0000a148, 0x111d111e},
+	{0x0000a14c, 0x111b111c},
+	{0x0000a150, 0x22032204},
+	{0x0000a154, 0x22012202},
+	{0x0000a158, 0x221f2200},
+	{0x0000a15c, 0x221d221e},
+	{0x0000a160, 0x33013302},
+	{0x0000a164, 0x331f3300},
+	{0x0000a168, 0x4402331e},
+	{0x0000a16c, 0x44004401},
+	{0x0000a170, 0x441e441f},
+	{0x0000a174, 0x55015502},
+	{0x0000a178, 0x551f5500},
+	{0x0000a17c, 0x6602551e},
+	{0x0000a180, 0x66006601},
+	{0x0000a184, 0x661e661f},
+	{0x0000a188, 0x7703661d},
+	{0x0000a18c, 0x77017702},
+	{0x0000a190, 0x00007700},
+	{0x0000a194, 0x00000000},
+	{0x0000a198, 0x00000000},
+	{0x0000a19c, 0x00000000},
+	{0x0000a1a0, 0x00000000},
+	{0x0000a1a4, 0x00000000},
+	{0x0000a1a8, 0x00000000},
+	{0x0000a1ac, 0x00000000},
+	{0x0000a1b0, 0x00000000},
+	{0x0000a1b4, 0x00000000},
+	{0x0000a1b8, 0x00000000},
+	{0x0000a1bc, 0x00000000},
+	{0x0000a1c0, 0x00000000},
+	{0x0000a1c4, 0x00000000},
+	{0x0000a1c8, 0x00000000},
+	{0x0000a1cc, 0x00000000},
+	{0x0000a1d0, 0x00000000},
+	{0x0000a1d4, 0x00000000},
+	{0x0000a1d8, 0x00000000},
+	{0x0000a1dc, 0x00000000},
+	{0x0000a1e0, 0x00000000},
+	{0x0000a1e4, 0x00000000},
+	{0x0000a1e8, 0x00000000},
+	{0x0000a1ec, 0x00000000},
+	{0x0000a1f0, 0x00000396},
+	{0x0000a1f4, 0x00000396},
+	{0x0000a1f8, 0x00000396},
+	{0x0000a1fc, 0x00000296},
+};
+
+static const u32 ar9485Modes_high_power_tx_gain_1_0[][5] = {
+	/*   Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20 */
+	{0x0000a410, 0x000050d9, 0x000050d9, 0x000050d8, 0x000050d8},
+	{0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
+	{0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
+	{0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
+	{0x0000a50c, 0x11062202, 0x11062202, 0x0d000200, 0x0d000200},
+	{0x0000a510, 0x17022e00, 0x17022e00, 0x11000202, 0x11000202},
+	{0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x15000400, 0x15000400},
+	{0x0000a518, 0x25020ec0, 0x25020ec0, 0x19000402, 0x19000402},
+	{0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x1d000404, 0x1d000404},
+	{0x0000a520, 0x2f001f04, 0x2f001f04, 0x21000603, 0x21000603},
+	{0x0000a524, 0x35001fc4, 0x35001fc4, 0x25000605, 0x25000605},
+	{0x0000a528, 0x3c022f04, 0x3c022f04, 0x2a000a03, 0x2a000a03},
+	{0x0000a52c, 0x41023e85, 0x41023e85, 0x2c000a04, 0x2c000a04},
+	{0x0000a530, 0x48023ec6, 0x48023ec6, 0x2e000a20, 0x2e000a20},
+	{0x0000a534, 0x4d023f01, 0x4d023f01, 0x34000e20, 0x34000e20},
+	{0x0000a538, 0x53023f4b, 0x53023f4b, 0x38000e22, 0x38000e22},
+	{0x0000a53c, 0x5a027f09, 0x5a027f09, 0x3c000e24, 0x3c000e24},
+	{0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x40000e26, 0x40000e26},
+	{0x0000a544, 0x6502feca, 0x6502feca, 0x43001640, 0x43001640},
+	{0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x46001660, 0x46001660},
+	{0x0000a54c, 0x7203feca, 0x7203feca, 0x49001861, 0x49001861},
+	{0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x4c001a81, 0x4c001a81},
+	{0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x4f001a83, 0x4f001a83},
+	{0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x54001c85, 0x54001c85},
+	{0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x58001ce5, 0x58001ce5},
+	{0x0000a560, 0x900fff0b, 0x900fff0b, 0x5b001ce9, 0x5b001ce9},
+	{0x0000a564, 0x960fffcb, 0x960fffcb, 0x60001eeb, 0x60001eeb},
+	{0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb},
+	{0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb},
+	{0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb},
+	{0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb},
+	{0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb},
+	{0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb},
+	{0x00016044, 0x05b6b2db, 0x05b6b2db, 0x05b6b2db, 0x05b6b2db},
+};
+
+static const u32 ar9485_1_0[][2] = {
+	/*  Addr      allmodes */
+	{0x0000a580, 0x00000000},
+	{0x0000a584, 0x00000000},
+	{0x0000a588, 0x00000000},
+	{0x0000a58c, 0x00000000},
+	{0x0000a590, 0x00000000},
+	{0x0000a594, 0x00000000},
+	{0x0000a598, 0x00000000},
+	{0x0000a59c, 0x00000000},
+	{0x0000a5a0, 0x00000000},
+	{0x0000a5a4, 0x00000000},
+	{0x0000a5a8, 0x00000000},
+	{0x0000a5ac, 0x00000000},
+	{0x0000a5b0, 0x00000000},
+	{0x0000a5b4, 0x00000000},
+	{0x0000a5b8, 0x00000000},
+	{0x0000a5bc, 0x00000000},
+};
+
+static const u32 ar9485_1_0_radio_core[][2] = {
+	/*   Addr     allmodes */
+	{0x00016000, 0x36db6db6},
+	{0x00016004, 0x6db6db40},
+	{0x00016008, 0x73800000},
+	{0x0001600c, 0x00000000},
+	{0x00016040, 0x7f80fff8},
+	{0x00016048, 0x6c92426e},
+	{0x0001604c, 0x000f0278},
+	{0x00016050, 0x6db6db6c},
+	{0x00016054, 0x6db60000},
+	{0x00016080, 0x00080000},
+	{0x00016084, 0x0e48048c},
+	{0x00016088, 0x14214514},
+	{0x0001608c, 0x119f081e},
+	{0x00016090, 0x24926490},
+	{0x00016098, 0xd28b3330},
+	{0x000160a0, 0xc2108ffe},
+	{0x000160a4, 0x812fc370},
+	{0x000160a8, 0x423c8000},
+	{0x000160b4, 0x92480040},
+	{0x000160c0, 0x006db6db},
+	{0x000160c4, 0x0186db60},
+	{0x000160c8, 0x6db6db6c},
+	{0x000160cc, 0x6de6fbe0},
+	{0x000160d0, 0xf7dfcf3c},
+	{0x00016100, 0x04cb0001},
+	{0x00016104, 0xfff80015},
+	{0x00016108, 0x00080010},
+	{0x00016144, 0x01884080},
+	{0x00016148, 0x00008040},
+	{0x00016180, 0x08453333},
+	{0x00016184, 0x18e82f01},
+	{0x00016188, 0x00000000},
+	{0x0001618c, 0x00000000},
+	{0x00016240, 0x08400000},
+	{0x00016244, 0x1bf90f00},
+	{0x00016248, 0x00000000},
+	{0x0001624c, 0x00000000},
+	{0x00016280, 0x01000015},
+	{0x00016284, 0x00d30000},
+	{0x00016288, 0x00318000},
+	{0x0001628c, 0x50000000},
+	{0x00016290, 0x4b96210f},
+	{0x00016380, 0x00000000},
+	{0x00016384, 0x00000000},
+	{0x00016388, 0x00800700},
+	{0x0001638c, 0x00800700},
+	{0x00016390, 0x00800700},
+	{0x00016394, 0x00000000},
+	{0x00016398, 0x00000000},
+	{0x0001639c, 0x00000000},
+	{0x000163a0, 0x00000001},
+	{0x000163a4, 0x00000001},
+	{0x000163a8, 0x00000000},
+	{0x000163ac, 0x00000000},
+	{0x000163b0, 0x00000000},
+	{0x000163b4, 0x00000000},
+	{0x000163b8, 0x00000000},
+	{0x000163bc, 0x00000000},
+	{0x000163c0, 0x000000a0},
+	{0x000163c4, 0x000c0000},
+	{0x000163c8, 0x14021402},
+	{0x000163cc, 0x00001402},
+	{0x000163d0, 0x00000000},
+	{0x000163d4, 0x00000000},
+	{0x00016c40, 0x1319c178},
+	{0x00016c44, 0x10000000},
+};
+
+static const u32 ar9485Modes_lowest_ob_db_tx_gain_1_0[][5] = {
+	/*  Addr       5G_HT20     5G_HT40     2G_HT40     2G_HT20 */
+	{0x0000a410, 0x000050d9, 0x000050d9, 0x000050d8, 0x000050d8},
+	{0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
+	{0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
+	{0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
+	{0x0000a50c, 0x11062202, 0x11062202, 0x0d000200, 0x0d000200},
+	{0x0000a510, 0x17022e00, 0x17022e00, 0x11000202, 0x11000202},
+	{0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x15000400, 0x15000400},
+	{0x0000a518, 0x25020ec0, 0x25020ec0, 0x19000402, 0x19000402},
+	{0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x1d000404, 0x1d000404},
+	{0x0000a520, 0x2f001f04, 0x2f001f04, 0x21000603, 0x21000603},
+	{0x0000a524, 0x35001fc4, 0x35001fc4, 0x25000605, 0x25000605},
+	{0x0000a528, 0x3c022f04, 0x3c022f04, 0x2a000a03, 0x2a000a03},
+	{0x0000a52c, 0x41023e85, 0x41023e85, 0x2c000a04, 0x2c000a04},
+	{0x0000a530, 0x48023ec6, 0x48023ec6, 0x2e000a20, 0x2e000a20},
+	{0x0000a534, 0x4d023f01, 0x4d023f01, 0x34000e20, 0x34000e20},
+	{0x0000a538, 0x53023f4b, 0x53023f4b, 0x38000e22, 0x38000e22},
+	{0x0000a53c, 0x5a027f09, 0x5a027f09, 0x3c000e24, 0x3c000e24},
+	{0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x40000e26, 0x40000e26},
+	{0x0000a544, 0x6502feca, 0x6502feca, 0x43001640, 0x43001640},
+	{0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x46001660, 0x46001660},
+	{0x0000a54c, 0x7203feca, 0x7203feca, 0x49001861, 0x49001861},
+	{0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x4c001a81, 0x4c001a81},
+	{0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x4f001a83, 0x4f001a83},
+	{0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x54001c85, 0x54001c85},
+	{0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x58001ce5, 0x58001ce5},
+	{0x0000a560, 0x900fff0b, 0x900fff0b, 0x5b001ce9, 0x5b001ce9},
+	{0x0000a564, 0x960fffcb, 0x960fffcb, 0x60001eeb, 0x60001eeb},
+	{0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb},
+	{0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb},
+	{0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb},
+	{0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb},
+	{0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb},
+	{0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb},
+	{0x00016044, 0x05b6b2db, 0x05b6b2db, 0x05b6b2db, 0x05b6b2db},
+};
+
+static const u32 ar9485_1_0_baseband_core[][2] = {
+	/* Addr      allmodes  */
+	{0x00009800, 0xafe68e30},
+	{0x00009804, 0xfd14e000},
+	{0x00009808, 0x9c0a8f6b},
+	{0x0000980c, 0x04800000},
+	{0x00009814, 0x9280c00a},
+	{0x00009818, 0x00000000},
+	{0x0000981c, 0x00020028},
+	{0x00009834, 0x5f3ca3de},
+	{0x00009838, 0x0108ecff},
+	{0x0000983c, 0x14750600},
+	{0x00009880, 0x201fff00},
+	{0x00009884, 0x00001042},
+	{0x000098a4, 0x00200400},
+	{0x000098b0, 0x52440bbe},
+	{0x000098bc, 0x00000002},
+	{0x000098d0, 0x004b6a8e},
+	{0x000098d4, 0x00000820},
+	{0x000098dc, 0x00000000},
+	{0x000098f0, 0x00000000},
+	{0x000098f4, 0x00000000},
+	{0x00009c04, 0x00000000},
+	{0x00009c08, 0x03200000},
+	{0x00009c0c, 0x00000000},
+	{0x00009c10, 0x00000000},
+	{0x00009c14, 0x00046384},
+	{0x00009c18, 0x05b6b440},
+	{0x00009c1c, 0x00b6b440},
+	{0x00009d00, 0xc080a333},
+	{0x00009d04, 0x40206c10},
+	{0x00009d08, 0x009c4060},
+	{0x00009d0c, 0x1883800a},
+	{0x00009d10, 0x01834061},
+	{0x00009d14, 0x00c00400},
+	{0x00009d18, 0x00000000},
+	{0x00009d1c, 0x00000000},
+	{0x00009e08, 0x0038233c},
+	{0x00009e24, 0x990bb515},
+	{0x00009e28, 0x0a6f0000},
+	{0x00009e30, 0x06336f77},
+	{0x00009e34, 0x6af6532f},
+	{0x00009e38, 0x0cc80c00},
+	{0x00009e40, 0x0d261820},
+	{0x00009e4c, 0x00001004},
+	{0x00009e50, 0x00ff03f1},
+	{0x00009fc0, 0x80be4788},
+	{0x00009fc4, 0x0001efb5},
+	{0x00009fcc, 0x40000014},
+	{0x0000a20c, 0x00000000},
+	{0x0000a210, 0x00000000},
+	{0x0000a220, 0x00000000},
+	{0x0000a224, 0x00000000},
+	{0x0000a228, 0x10002310},
+	{0x0000a23c, 0x00000000},
+	{0x0000a244, 0x0c000000},
+	{0x0000a2a0, 0x00000001},
+	{0x0000a2c0, 0x00000001},
+	{0x0000a2c8, 0x00000000},
+	{0x0000a2cc, 0x18c43433},
+	{0x0000a2d4, 0x00000000},
+	{0x0000a2dc, 0x00000000},
+	{0x0000a2e0, 0x00000000},
+	{0x0000a2e4, 0x00000000},
+	{0x0000a2e8, 0x00000000},
+	{0x0000a2ec, 0x00000000},
+	{0x0000a2f0, 0x00000000},
+	{0x0000a2f4, 0x00000000},
+	{0x0000a2f8, 0x00000000},
+	{0x0000a344, 0x00000000},
+	{0x0000a34c, 0x00000000},
+	{0x0000a350, 0x0000a000},
+	{0x0000a364, 0x00000000},
+	{0x0000a370, 0x00000000},
+	{0x0000a390, 0x00000001},
+	{0x0000a394, 0x00000444},
+	{0x0000a398, 0x001f0e0f},
+	{0x0000a39c, 0x0075393f},
+	{0x0000a3a0, 0xb79f6427},
+	{0x0000a3a4, 0x00000000},
+	{0x0000a3a8, 0xaaaaaaaa},
+	{0x0000a3ac, 0x3c466478},
+	{0x0000a3c0, 0x20202020},
+	{0x0000a3c4, 0x22222220},
+	{0x0000a3c8, 0x20200020},
+	{0x0000a3cc, 0x20202020},
+	{0x0000a3d0, 0x20202020},
+	{0x0000a3d4, 0x20202020},
+	{0x0000a3d8, 0x20202020},
+	{0x0000a3dc, 0x20202020},
+	{0x0000a3e0, 0x20202020},
+	{0x0000a3e4, 0x20202020},
+	{0x0000a3e8, 0x20202020},
+	{0x0000a3ec, 0x20202020},
+	{0x0000a3f0, 0x00000000},
+	{0x0000a3f4, 0x00000006},
+	{0x0000a3f8, 0x0cdbd380},
+	{0x0000a3fc, 0x000f0f01},
+	{0x0000a400, 0x8fa91f01},
+	{0x0000a404, 0x00000000},
+	{0x0000a408, 0x0e79e5c6},
+	{0x0000a40c, 0x00820820},
+	{0x0000a414, 0x1ce739ce},
+	{0x0000a418, 0x2d0011ce},
+	{0x0000a41c, 0x1ce739ce},
+	{0x0000a420, 0x000001ce},
+	{0x0000a424, 0x1ce739ce},
+	{0x0000a428, 0x000001ce},
+	{0x0000a42c, 0x1ce739ce},
+	{0x0000a430, 0x1ce739ce},
+	{0x0000a434, 0x00000000},
+	{0x0000a438, 0x00001801},
+	{0x0000a43c, 0x00000000},
+	{0x0000a440, 0x00000000},
+	{0x0000a444, 0x00000000},
+	{0x0000a448, 0x04000000},
+	{0x0000a44c, 0x00000001},
+	{0x0000a450, 0x00010000},
+	{0x0000a458, 0x00000000},
+	{0x0000a5c4, 0x3fad9d74},
+	{0x0000a5c8, 0x0048060a},
+	{0x0000a5cc, 0x00000637},
+	{0x0000a760, 0x03020100},
+	{0x0000a764, 0x09080504},
+	{0x0000a768, 0x0d0c0b0a},
+	{0x0000a76c, 0x13121110},
+	{0x0000a770, 0x31301514},
+	{0x0000a774, 0x35343332},
+	{0x0000a778, 0x00000036},
+	{0x0000a780, 0x00000838},
+	{0x0000a7c0, 0x00000000},
+	{0x0000a7c4, 0xfffffffc},
+	{0x0000a7c8, 0x00000000},
+	{0x0000a7cc, 0x00000000},
+	{0x0000a7d0, 0x00000000},
+	{0x0000a7d4, 0x00000004},
+	{0x0000a7dc, 0x00000001},
+};
+
+static const u32 ar9485Modes_high_ob_db_tx_gain_1_0[][5] = {
+	/* Addr        5G_HT20     5G_HT40     2G_HT40    2G_HT20  */
+	{0x0000a410, 0x000050d9, 0x000050d9, 0x000050d8, 0x000050d8},
+	{0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
+	{0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
+	{0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
+	{0x0000a50c, 0x11062202, 0x11062202, 0x0d000200, 0x0d000200},
+	{0x0000a510, 0x17022e00, 0x17022e00, 0x11000202, 0x11000202},
+	{0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x15000400, 0x15000400},
+	{0x0000a518, 0x25020ec0, 0x25020ec0, 0x19000402, 0x19000402},
+	{0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x1d000404, 0x1d000404},
+	{0x0000a520, 0x2f001f04, 0x2f001f04, 0x21000603, 0x21000603},
+	{0x0000a524, 0x35001fc4, 0x35001fc4, 0x25000605, 0x25000605},
+	{0x0000a528, 0x3c022f04, 0x3c022f04, 0x2a000a03, 0x2a000a03},
+	{0x0000a52c, 0x41023e85, 0x41023e85, 0x2c000a04, 0x2c000a04},
+	{0x0000a530, 0x48023ec6, 0x48023ec6, 0x2e000a20, 0x2e000a20},
+	{0x0000a534, 0x4d023f01, 0x4d023f01, 0x34000e20, 0x34000e20},
+	{0x0000a538, 0x53023f4b, 0x53023f4b, 0x38000e22, 0x38000e22},
+	{0x0000a53c, 0x5a027f09, 0x5a027f09, 0x3c000e24, 0x3c000e24},
+	{0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x40000e26, 0x40000e26},
+	{0x0000a544, 0x6502feca, 0x6502feca, 0x43001640, 0x43001640},
+	{0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x46001660, 0x46001660},
+	{0x0000a54c, 0x7203feca, 0x7203feca, 0x49001861, 0x49001861},
+	{0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x4c001a81, 0x4c001a81},
+	{0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x4f001a83, 0x4f001a83},
+	{0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x54001c85, 0x54001c85},
+	{0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x58001ce5, 0x58001ce5},
+	{0x0000a560, 0x900fff0b, 0x900fff0b, 0x5b001ce9, 0x5b001ce9},
+	{0x0000a564, 0x960fffcb, 0x960fffcb, 0x60001eeb, 0x60001eeb},
+	{0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb},
+	{0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb},
+	{0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb},
+	{0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb},
+	{0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb},
+	{0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb},
+	{0x00016044, 0x05b6b2db, 0x05b6b2db, 0x05b6b2db, 0x05b6b2db},
+};
+
+static const u32 ar9485Common_rx_gain_1_0[][2] = {
+	/* Addr      allmodes  */
+	{0x0000a000, 0x00010000},
+	{0x0000a004, 0x00030002},
+	{0x0000a008, 0x00050004},
+	{0x0000a00c, 0x00810080},
+	{0x0000a010, 0x01800082},
+	{0x0000a014, 0x01820181},
+	{0x0000a018, 0x01840183},
+	{0x0000a01c, 0x01880185},
+	{0x0000a020, 0x018a0189},
+	{0x0000a024, 0x02850284},
+	{0x0000a028, 0x02890288},
+	{0x0000a02c, 0x03850384},
+	{0x0000a030, 0x03890388},
+	{0x0000a034, 0x038b038a},
+	{0x0000a038, 0x038d038c},
+	{0x0000a03c, 0x03910390},
+	{0x0000a040, 0x03930392},
+	{0x0000a044, 0x03950394},
+	{0x0000a048, 0x00000396},
+	{0x0000a04c, 0x00000000},
+	{0x0000a050, 0x00000000},
+	{0x0000a054, 0x00000000},
+	{0x0000a058, 0x00000000},
+	{0x0000a05c, 0x00000000},
+	{0x0000a060, 0x00000000},
+	{0x0000a064, 0x00000000},
+	{0x0000a068, 0x00000000},
+	{0x0000a06c, 0x00000000},
+	{0x0000a070, 0x00000000},
+	{0x0000a074, 0x00000000},
+	{0x0000a078, 0x00000000},
+	{0x0000a07c, 0x00000000},
+	{0x0000a080, 0x28282828},
+	{0x0000a084, 0x28282828},
+	{0x0000a088, 0x28282828},
+	{0x0000a08c, 0x28282828},
+	{0x0000a090, 0x28282828},
+	{0x0000a094, 0x21212128},
+	{0x0000a098, 0x171c1c1c},
+	{0x0000a09c, 0x02020212},
+	{0x0000a0a0, 0x00000202},
+	{0x0000a0a4, 0x00000000},
+	{0x0000a0a8, 0x00000000},
+	{0x0000a0ac, 0x00000000},
+	{0x0000a0b0, 0x00000000},
+	{0x0000a0b4, 0x00000000},
+	{0x0000a0b8, 0x00000000},
+	{0x0000a0bc, 0x00000000},
+	{0x0000a0c0, 0x001f0000},
+	{0x0000a0c4, 0x111f1100},
+	{0x0000a0c8, 0x111d111e},
+	{0x0000a0cc, 0x111b111c},
+	{0x0000a0d0, 0x22032204},
+	{0x0000a0d4, 0x22012202},
+	{0x0000a0d8, 0x221f2200},
+	{0x0000a0dc, 0x221d221e},
+	{0x0000a0e0, 0x33013302},
+	{0x0000a0e4, 0x331f3300},
+	{0x0000a0e8, 0x4402331e},
+	{0x0000a0ec, 0x44004401},
+	{0x0000a0f0, 0x441e441f},
+	{0x0000a0f4, 0x55015502},
+	{0x0000a0f8, 0x551f5500},
+	{0x0000a0fc, 0x6602551e},
+	{0x0000a100, 0x66006601},
+	{0x0000a104, 0x661e661f},
+	{0x0000a108, 0x7703661d},
+	{0x0000a10c, 0x77017702},
+	{0x0000a110, 0x00007700},
+	{0x0000a114, 0x00000000},
+	{0x0000a118, 0x00000000},
+	{0x0000a11c, 0x00000000},
+	{0x0000a120, 0x00000000},
+	{0x0000a124, 0x00000000},
+	{0x0000a128, 0x00000000},
+	{0x0000a12c, 0x00000000},
+	{0x0000a130, 0x00000000},
+	{0x0000a134, 0x00000000},
+	{0x0000a138, 0x00000000},
+	{0x0000a13c, 0x00000000},
+	{0x0000a140, 0x001f0000},
+	{0x0000a144, 0x111f1100},
+	{0x0000a148, 0x111d111e},
+	{0x0000a14c, 0x111b111c},
+	{0x0000a150, 0x22032204},
+	{0x0000a154, 0x22012202},
+	{0x0000a158, 0x221f2200},
+	{0x0000a15c, 0x221d221e},
+	{0x0000a160, 0x33013302},
+	{0x0000a164, 0x331f3300},
+	{0x0000a168, 0x4402331e},
+	{0x0000a16c, 0x44004401},
+	{0x0000a170, 0x441e441f},
+	{0x0000a174, 0x55015502},
+	{0x0000a178, 0x551f5500},
+	{0x0000a17c, 0x6602551e},
+	{0x0000a180, 0x66006601},
+	{0x0000a184, 0x661e661f},
+	{0x0000a188, 0x7703661d},
+	{0x0000a18c, 0x77017702},
+	{0x0000a190, 0x00007700},
+	{0x0000a194, 0x00000000},
+	{0x0000a198, 0x00000000},
+	{0x0000a19c, 0x00000000},
+	{0x0000a1a0, 0x00000000},
+	{0x0000a1a4, 0x00000000},
+	{0x0000a1a8, 0x00000000},
+	{0x0000a1ac, 0x00000000},
+	{0x0000a1b0, 0x00000000},
+	{0x0000a1b4, 0x00000000},
+	{0x0000a1b8, 0x00000000},
+	{0x0000a1bc, 0x00000000},
+	{0x0000a1c0, 0x00000000},
+	{0x0000a1c4, 0x00000000},
+	{0x0000a1c8, 0x00000000},
+	{0x0000a1cc, 0x00000000},
+	{0x0000a1d0, 0x00000000},
+	{0x0000a1d4, 0x00000000},
+	{0x0000a1d8, 0x00000000},
+	{0x0000a1dc, 0x00000000},
+	{0x0000a1e0, 0x00000000},
+	{0x0000a1e4, 0x00000000},
+	{0x0000a1e8, 0x00000000},
+	{0x0000a1ec, 0x00000000},
+	{0x0000a1f0, 0x00000396},
+	{0x0000a1f4, 0x00000396},
+	{0x0000a1f8, 0x00000396},
+	{0x0000a1fc, 0x00000296},
+};
+
+static const u32 ar9485_1_0_pcie_phy_pll_on_clkreq_enable_L1[][2] = {
+	/*   Addr    allmodes  */
+	{0x00018c00, 0x10252e5e},
+	{0x00018c04, 0x000801d8},
+	{0x00018c08, 0x0000580c},
+};
+
+static const u32 ar9485_1_0_pcie_phy_clkreq_enable_L1[][2] = {
+	/*  Addr    allmodes   */
+	{0x00018c00, 0x10253e5e},
+	{0x00018c04, 0x000801d8},
+	{0x00018c08, 0x0000580c},
+};
+
+static const u32 ar9485_1_0_soc_preamble[][2] = {
+	/*   Addr     allmodes */
+	{0x000040a4, 0x00a0c9c9},
+	{0x00007048, 0x00000004},
+};
+
+static const u32 ar9485_fast_clock_1_0_baseband_postamble[][3] = {
+	/*   Addr      5G_HT20     5G_HT40 */
+	{0x00009e00, 0x03721821, 0x03721821},
+	{0x0000a230, 0x0000400b, 0x00004016},
+	{0x0000a254, 0x00000898, 0x00001130},
+};
+
+static const u32 ar9485_1_0_baseband_postamble[][5] = {
+	/* Addr        5G_HT20     5G_HT40     2G_HT40     2G_HT20 */
+	{0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8005, 0xd00a8005},
+	{0x00009820, 0x206a002e, 0x206a002e, 0x206a002e, 0x206a002e},
+	{0x00009824, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0},
+	{0x00009828, 0x06903081, 0x06903081, 0x06903881, 0x06903881},
+	{0x0000982c, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4},
+	{0x00009830, 0x0000059c, 0x0000059c, 0x0000059c, 0x0000059c},
+	{0x00009c00, 0x00000044, 0x00000044, 0x00000044, 0x00000044},
+	{0x00009e00, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0},
+	{0x00009e04, 0x00182020, 0x00182020, 0x00182020, 0x00182020},
+	{0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000e2},
+	{0x00009e10, 0x7ec88d2e, 0x7ec88d2e, 0x7ec80d2e, 0x7ec80d2e},
+	{0x00009e14, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e},
+	{0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c},
+	{0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce},
+	{0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021},
+	{0x00009e3c, 0xcf946220, 0xcf946220, 0xcf946222, 0xcf946222},
+	{0x00009e44, 0x02321e27, 0x02321e27, 0x02282324, 0x02282324},
+	{0x00009e48, 0x5030201a, 0x5030201a, 0x50302010, 0x50302010},
+	{0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000},
+	{0x0000a204, 0x01303fc0, 0x01303fc4, 0x01303fc4, 0x01303fc0},
+	{0x0000a208, 0x00000104, 0x00000104, 0x00000004, 0x00000004},
+	{0x0000a230, 0x0000400a, 0x00004014, 0x00004016, 0x0000400b},
+	{0x0000a234, 0x10000fff, 0x10000fff, 0x10000fff, 0x10000fff},
+	{0x0000a238, 0xffb81018, 0xffb81018, 0xffb81018, 0xffb81018},
+	{0x0000a250, 0x00000000, 0x00000000, 0x00000210, 0x00000108},
+	{0x0000a254, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898},
+	{0x0000a258, 0x02020002, 0x02020002, 0x02020002, 0x02020002},
+	{0x0000a25c, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e},
+	{0x0000a260, 0x3a021501, 0x3a021501, 0x3a021501, 0x3a021501},
+	{0x0000a264, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
+	{0x0000a280, 0x00000007, 0x00000007, 0x0000000b, 0x0000000b},
+	{0x0000a284, 0x00000000, 0x00000000, 0x000002a0, 0x000002a0},
+	{0x0000a288, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000a28c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18},
+	{0x0000a2d0, 0x00071981, 0x00071981, 0x00071981, 0x00071982},
+	{0x0000a2d8, 0xf999a83a, 0xf999a83a, 0xf999a83a, 0xf999a83a},
+	{0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000be04, 0x00802020, 0x00802020, 0x00802020, 0x00802020},
+	{0x0000be18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+};
+
+static const u32 ar9485Modes_low_ob_db_tx_gain_1_0[][5] = {
+	/*  Addr      5G_HT20    5G_HT40     2G_HT40     2G_HT20   */
+	{0x0000a410, 0x000050d9, 0x000050d9, 0x000050d8, 0x000050d8},
+	{0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
+	{0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
+	{0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
+	{0x0000a50c, 0x11062202, 0x11062202, 0x0d000200, 0x0d000200},
+	{0x0000a510, 0x17022e00, 0x17022e00, 0x11000202, 0x11000202},
+	{0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x15000400, 0x15000400},
+	{0x0000a518, 0x25020ec0, 0x25020ec0, 0x19000402, 0x19000402},
+	{0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x1d000404, 0x1d000404},
+	{0x0000a520, 0x2f001f04, 0x2f001f04, 0x21000603, 0x21000603},
+	{0x0000a524, 0x35001fc4, 0x35001fc4, 0x25000605, 0x25000605},
+	{0x0000a528, 0x3c022f04, 0x3c022f04, 0x2a000a03, 0x2a000a03},
+	{0x0000a52c, 0x41023e85, 0x41023e85, 0x2c000a04, 0x2c000a04},
+	{0x0000a530, 0x48023ec6, 0x48023ec6, 0x2e000a20, 0x2e000a20},
+	{0x0000a534, 0x4d023f01, 0x4d023f01, 0x34000e20, 0x34000e20},
+	{0x0000a538, 0x53023f4b, 0x53023f4b, 0x38000e22, 0x38000e22},
+	{0x0000a53c, 0x5a027f09, 0x5a027f09, 0x3c000e24, 0x3c000e24},
+	{0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x40000e26, 0x40000e26},
+	{0x0000a544, 0x6502feca, 0x6502feca, 0x43001640, 0x43001640},
+	{0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x46001660, 0x46001660},
+	{0x0000a54c, 0x7203feca, 0x7203feca, 0x49001861, 0x49001861},
+	{0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x4c001a81, 0x4c001a81},
+	{0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x4f001a83, 0x4f001a83},
+	{0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x54001c85, 0x54001c85},
+	{0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x58001ce5, 0x58001ce5},
+	{0x0000a560, 0x900fff0b, 0x900fff0b, 0x5b001ce9, 0x5b001ce9},
+	{0x0000a564, 0x960fffcb, 0x960fffcb, 0x60001eeb, 0x60001eeb},
+	{0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb},
+	{0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb},
+	{0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb},
+	{0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb},
+	{0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb},
+	{0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb},
+	{0x00016044, 0x05b6b2db, 0x05b6b2db, 0x05b6b2db, 0x05b6b2db},
+};
+
+static const u32 ar9485_1_0_pcie_phy_clkreq_disable_L1[][2] = {
+	/*   Addr     allmodes */
+	{0x00018c00, 0x10213e5e},
+	{0x00018c04, 0x000801d8},
+	{0x00018c08, 0x0000580c},
+};
+
+static const u32 ar9485_1_0_radio_postamble[][2] = {
+	/*   Addr     allmodes */
+	{0x0001609c, 0x0b283f31},
+	{0x000160ac, 0x24611800},
+	{0x000160b0, 0x03284f3e},
+	{0x0001610c, 0x00170000},
+	{0x00016140, 0x10804008},
+};
+
+static const u32 ar9485_1_0_mac_core[][2] = {
+	/*  Addr      allmodes */
+	{0x00000008, 0x00000000},
+	{0x00000030, 0x00020085},
+	{0x00000034, 0x00000005},
+	{0x00000040, 0x00000000},
+	{0x00000044, 0x00000000},
+	{0x00000048, 0x00000008},
+	{0x0000004c, 0x00000010},
+	{0x00000050, 0x00000000},
+	{0x00001040, 0x002ffc0f},
+	{0x00001044, 0x002ffc0f},
+	{0x00001048, 0x002ffc0f},
+	{0x0000104c, 0x002ffc0f},
+	{0x00001050, 0x002ffc0f},
+	{0x00001054, 0x002ffc0f},
+	{0x00001058, 0x002ffc0f},
+	{0x0000105c, 0x002ffc0f},
+	{0x00001060, 0x002ffc0f},
+	{0x00001064, 0x002ffc0f},
+	{0x000010f0, 0x00000100},
+	{0x00001270, 0x00000000},
+	{0x000012b0, 0x00000000},
+	{0x000012f0, 0x00000000},
+	{0x0000143c, 0x00000000},
+	{0x0000147c, 0x00000000},
+	{0x00008000, 0x00000000},
+	{0x00008004, 0x00000000},
+	{0x00008008, 0x00000000},
+	{0x0000800c, 0x00000000},
+	{0x00008018, 0x00000000},
+	{0x00008020, 0x00000000},
+	{0x00008038, 0x00000000},
+	{0x0000803c, 0x00000000},
+	{0x00008040, 0x00000000},
+	{0x00008044, 0x00000000},
+	{0x00008048, 0x00000000},
+	{0x0000804c, 0xffffffff},
+	{0x00008054, 0x00000000},
+	{0x00008058, 0x00000000},
+	{0x0000805c, 0x000fc78f},
+	{0x00008060, 0x0000000f},
+	{0x00008064, 0x00000000},
+	{0x00008070, 0x00000310},
+	{0x00008074, 0x00000020},
+	{0x00008078, 0x00000000},
+	{0x0000809c, 0x0000000f},
+	{0x000080a0, 0x00000000},
+	{0x000080a4, 0x02ff0000},
+	{0x000080a8, 0x0e070605},
+	{0x000080ac, 0x0000000d},
+	{0x000080b0, 0x00000000},
+	{0x000080b4, 0x00000000},
+	{0x000080b8, 0x00000000},
+	{0x000080bc, 0x00000000},
+	{0x000080c0, 0x2a800000},
+	{0x000080c4, 0x06900168},
+	{0x000080c8, 0x13881c20},
+	{0x000080cc, 0x01f40000},
+	{0x000080d0, 0x00252500},
+	{0x000080d4, 0x00a00000},
+	{0x000080d8, 0x00400000},
+	{0x000080dc, 0x00000000},
+	{0x000080e0, 0xffffffff},
+	{0x000080e4, 0x0000ffff},
+	{0x000080e8, 0x3f3f3f3f},
+	{0x000080ec, 0x00000000},
+	{0x000080f0, 0x00000000},
+	{0x000080f4, 0x00000000},
+	{0x000080fc, 0x00020000},
+	{0x00008100, 0x00000000},
+	{0x00008108, 0x00000052},
+	{0x0000810c, 0x00000000},
+	{0x00008110, 0x00000000},
+	{0x00008114, 0x000007ff},
+	{0x00008118, 0x000000aa},
+	{0x0000811c, 0x00003210},
+	{0x00008124, 0x00000000},
+	{0x00008128, 0x00000000},
+	{0x0000812c, 0x00000000},
+	{0x00008130, 0x00000000},
+	{0x00008134, 0x00000000},
+	{0x00008138, 0x00000000},
+	{0x0000813c, 0x0000ffff},
+	{0x00008144, 0xffffffff},
+	{0x00008168, 0x00000000},
+	{0x0000816c, 0x00000000},
+	{0x00008170, 0x18486200},
+	{0x00008174, 0x33332210},
+	{0x00008178, 0x00000000},
+	{0x0000817c, 0x00020000},
+	{0x000081c0, 0x00000000},
+	{0x000081c4, 0x33332210},
+	{0x000081c8, 0x00000000},
+	{0x000081cc, 0x00000000},
+	{0x000081d4, 0x00000000},
+	{0x000081ec, 0x00000000},
+	{0x000081f0, 0x00000000},
+	{0x000081f4, 0x00000000},
+	{0x000081f8, 0x00000000},
+	{0x000081fc, 0x00000000},
+	{0x00008240, 0x00100000},
+	{0x00008244, 0x0010f400},
+	{0x00008248, 0x00000800},
+	{0x0000824c, 0x0001e800},
+	{0x00008250, 0x00000000},
+	{0x00008254, 0x00000000},
+	{0x00008258, 0x00000000},
+	{0x0000825c, 0x40000000},
+	{0x00008260, 0x00080922},
+	{0x00008264, 0x9ca00010},
+	{0x00008268, 0xffffffff},
+	{0x0000826c, 0x0000ffff},
+	{0x00008270, 0x00000000},
+	{0x00008274, 0x40000000},
+	{0x00008278, 0x003e4180},
+	{0x0000827c, 0x00000004},
+	{0x00008284, 0x0000002c},
+	{0x00008288, 0x0000002c},
+	{0x0000828c, 0x000000ff},
+	{0x00008294, 0x00000000},
+	{0x00008298, 0x00000000},
+	{0x0000829c, 0x00000000},
+	{0x00008300, 0x00000140},
+	{0x00008314, 0x00000000},
+	{0x0000831c, 0x0000010d},
+	{0x00008328, 0x00000000},
+	{0x0000832c, 0x00000007},
+	{0x00008330, 0x00000302},
+	{0x00008334, 0x00000700},
+	{0x00008338, 0x00ff0000},
+	{0x0000833c, 0x02400000},
+	{0x00008340, 0x000107ff},
+	{0x00008344, 0xa248105b},
+	{0x00008348, 0x008f0000},
+	{0x0000835c, 0x00000000},
+	{0x00008360, 0xffffffff},
+	{0x00008364, 0xffffffff},
+	{0x00008368, 0x00000000},
+	{0x00008370, 0x00000000},
+	{0x00008374, 0x000000ff},
+	{0x00008378, 0x00000000},
+	{0x0000837c, 0x00000000},
+	{0x00008380, 0xffffffff},
+	{0x00008384, 0xffffffff},
+	{0x00008390, 0xffffffff},
+	{0x00008394, 0xffffffff},
+	{0x00008398, 0x00000000},
+	{0x0000839c, 0x00000000},
+	{0x000083a0, 0x00000000},
+	{0x000083a4, 0x0000fa14},
+	{0x000083a8, 0x000f0c00},
+	{0x000083ac, 0x33332210},
+	{0x000083b0, 0x33332210},
+	{0x000083b4, 0x33332210},
+	{0x000083b8, 0x33332210},
+	{0x000083bc, 0x00000000},
+	{0x000083c0, 0x00000000},
+	{0x000083c4, 0x00000000},
+	{0x000083c8, 0x00000000},
+	{0x000083cc, 0x00000200},
+	{0x000083d0, 0x000301ff},
+};
+#endif
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/ath9k.h linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/ath9k.h
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/ath9k.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/ath9k.h	2011-03-14 21:20:32.000000000 -0400
@@ -21,7 +21,6 @@
 #include <linux/device.h>
 #include <linux/leds.h>
 #include <linux/completion.h>
-#include <linux/pm_qos_params.h>
 
 #include "debug.h"
 #include "common.h"
@@ -87,33 +86,19 @@ struct ath_config {
 /**
  * enum buffer_type - Buffer type flags
  *
- * @BUF_HT: Send this buffer using HT capabilities
  * @BUF_AMPDU: This buffer is an ampdu, as part of an aggregate (during TX)
  * @BUF_AGGR: Indicates whether the buffer can be aggregated
  *	(used in aggregation scheduling)
- * @BUF_RETRY: Indicates whether the buffer is retried
  * @BUF_XRETRY: To denote excessive retries of the buffer
  */
 enum buffer_type {
-	BUF_HT			= BIT(1),
 	BUF_AMPDU		= BIT(2),
 	BUF_AGGR		= BIT(3),
-	BUF_RETRY		= BIT(4),
 	BUF_XRETRY		= BIT(5),
 };
 
-#define bf_nframes      	bf_state.bfs_nframes
-#define bf_al           	bf_state.bfs_al
-#define bf_frmlen       	bf_state.bfs_frmlen
-#define bf_retries      	bf_state.bfs_retries
-#define bf_seqno        	bf_state.bfs_seqno
-#define bf_tidno        	bf_state.bfs_tidno
-#define bf_keyix                bf_state.bfs_keyix
-#define bf_keytype      	bf_state.bfs_keytype
-#define bf_isht(bf)		(bf->bf_state.bf_type & BUF_HT)
 #define bf_isampdu(bf)		(bf->bf_state.bf_type & BUF_AMPDU)
 #define bf_isaggr(bf)		(bf->bf_state.bf_type & BUF_AGGR)
-#define bf_isretried(bf)	(bf->bf_state.bf_type & BUF_RETRY)
 #define bf_isxretried(bf)	(bf->bf_state.bf_type & BUF_XRETRY)
 
 #define ATH_TXSTATUS_RING_SIZE 64
@@ -178,8 +163,8 @@ void ath_descdma_cleanup(struct ath_soft
 
 /* returns delimiter padding required given the packet length */
 #define ATH_AGGR_GET_NDELIM(_len)					\
-	(((((_len) + ATH_AGGR_DELIM_SZ) < ATH_AGGR_MINPLEN) ?           \
-	  (ATH_AGGR_MINPLEN - (_len) - ATH_AGGR_DELIM_SZ) : 0) >> 2)
+       (((_len) >= ATH_AGGR_MINPLEN) ? 0 :                             \
+        DIV_ROUND_UP(ATH_AGGR_MINPLEN - (_len), ATH_AGGR_DELIM_SZ))
 
 #define BAW_WITHIN(_start, _bawsz, _seqno) \
 	((((_seqno) - (_start)) & 4095) < (_bawsz))
@@ -196,12 +181,12 @@ enum ATH_AGGR_STATUS {
 
 #define ATH_TXFIFO_DEPTH 8
 struct ath_txq {
-	int axq_class;
 	u32 axq_qnum;
 	u32 *axq_link;
 	struct list_head axq_q;
 	spinlock_t axq_lock;
 	u32 axq_depth;
+	u32 axq_ampdu_depth;
 	bool stopped;
 	bool axq_tx_inprogress;
 	struct list_head axq_acq;
@@ -209,27 +194,29 @@ struct ath_txq {
 	struct list_head txq_fifo_pending;
 	u8 txq_headidx;
 	u8 txq_tailidx;
+	int pending_frames;
 };
 
 struct ath_atx_ac {
+	struct ath_txq *txq;
 	int sched;
-	int qnum;
 	struct list_head list;
 	struct list_head tid_q;
 };
 
+struct ath_frame_info {
+	int framelen;
+	u32 keyix;
+	enum ath9k_key_type keytype;
+	u8 retries;
+	u16 seqno;
+};
+
 struct ath_buf_state {
-	int bfs_nframes;
-	u16 bfs_al;
-	u16 bfs_frmlen;
-	int bfs_seqno;
-	int bfs_tidno;
-	int bfs_retries;
 	u8 bf_type;
 	u8 bfs_paprd;
 	unsigned long bfs_paprd_timestamp;
-	u32 bfs_keyix;
-	enum ath9k_key_type bfs_keytype;
+	enum ath9k_internal_frame_type bfs_ftype;
 };
 
 struct ath_buf {
@@ -242,7 +229,6 @@ struct ath_buf {
 	dma_addr_t bf_daddr;		/* physical addr of desc */
 	dma_addr_t bf_buf_addr;	/* physical addr of data buffer, for DMA */
 	bool bf_stale;
-	bool bf_tx_aborted;
 	u16 bf_flags;
 	struct ath_buf_state bf_state;
 	struct ath_wiphy *aphy;
@@ -271,7 +257,6 @@ struct ath_node {
 	struct ath_atx_ac ac[WME_NUM_AC];
 	u16 maxampdu;
 	u8 mpdudensity;
-	int last_rssi;
 };
 
 #define AGGR_CLEANUP         BIT(1)
@@ -280,6 +265,7 @@ struct ath_node {
 
 struct ath_tx_control {
 	struct ath_txq *txq;
+	struct ath_node *an;
 	int if_id;
 	enum ath9k_internal_frame_type frame_type;
 	u8 paprd;
@@ -292,12 +278,11 @@ struct ath_tx_control {
 struct ath_tx {
 	u16 seq_no;
 	u32 txqsetup;
-	int hwq_map[WME_NUM_AC];
 	spinlock_t txbuflock;
 	struct list_head txbuf;
 	struct ath_txq txq[ATH9K_NUM_TX_QUEUES];
 	struct ath_descdma txdma;
-	int pending_frames[WME_NUM_AC];
+	struct ath_txq *txq_map[WME_NUM_AC];
 };
 
 struct ath_rx_edma {
@@ -311,7 +296,6 @@ struct ath_rx {
 	u8 rxotherant;
 	u32 *rxlink;
 	unsigned int rxfilter;
-	spinlock_t pcu_lock;
 	spinlock_t rxbuflock;
 	struct list_head rxbuf;
 	struct ath_descdma rxdma;
@@ -328,7 +312,6 @@ void ath_rx_cleanup(struct ath_softc *sc
 int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp);
 struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype);
 void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq);
-int ath_tx_setup(struct ath_softc *sc, int haltype);
 bool ath_drain_all_txq(struct ath_softc *sc, bool retry_tx);
 void ath_draintxq(struct ath_softc *sc,
 		     struct ath_txq *txq, bool retry_tx);
@@ -343,7 +326,6 @@ int ath_tx_start(struct ieee80211_hw *hw
 		 struct ath_tx_control *txctl);
 void ath_tx_tasklet(struct ath_softc *sc);
 void ath_tx_edma_tasklet(struct ath_softc *sc);
-void ath_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb);
 int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
 		      u16 tid, u16 *ssn);
 void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid);
@@ -564,6 +546,7 @@ struct ath_ant_comb {
 #define SC_OP_BT_PRIORITY_DETECTED   BIT(12)
 #define SC_OP_BT_SCAN		     BIT(13)
 #define SC_OP_ANI_RUN		     BIT(14)
+#define SC_OP_ENABLE_APM	     BIT(15)
 
 /* Powersave flags */
 #define PS_WAIT_FOR_BEACON        BIT(0)
@@ -601,9 +584,9 @@ struct ath_softc {
 	struct ath_hw *sc_ah;
 	void __iomem *mem;
 	int irq;
-	spinlock_t sc_resetlock;
 	spinlock_t sc_serial_rw;
 	spinlock_t sc_pm_lock;
+	spinlock_t sc_pcu_lock;
 	struct mutex mutex;
 	struct work_struct paprd_work;
 	struct work_struct hw_check_work;
@@ -647,8 +630,6 @@ struct ath_softc {
 	struct ath_descdma txsdma;
 
 	struct ath_ant_comb ant_comb;
-
-	struct pm_qos_request_list pm_qos_req;
 };
 
 struct ath_wiphy {
@@ -665,11 +646,11 @@ struct ath_wiphy {
 	bool idle;
 	int chan_idx;
 	int chan_is_ht;
+	int last_rssi;
 };
 
 void ath9k_tasklet(unsigned long data);
 int ath_reset(struct ath_softc *sc, bool retry_tx);
-int ath_get_mac80211_qnum(u32 queue, struct ath_softc *sc);
 int ath_cabq_update(struct ath_softc *);
 
 static inline void ath_read_cachesize(struct ath_common *common, int *csz)
@@ -678,17 +659,18 @@ static inline void ath_read_cachesize(st
 }
 
 extern struct ieee80211_ops ath9k_ops;
-extern int modparam_nohwcrypt;
+extern int ath9k_modparam_nohwcrypt;
 extern int led_blink;
+extern bool is_ath9k_unloaded;
 
 irqreturn_t ath_isr(int irq, void *dev);
+void ath9k_init_crypto(struct ath_softc *sc);
 int ath9k_init_device(u16 devid, struct ath_softc *sc, u16 subsysid,
 		    const struct ath_bus_ops *bus_ops);
 void ath9k_deinit_device(struct ath_softc *sc);
 void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw);
 void ath9k_update_ichannel(struct ath_softc *sc, struct ieee80211_hw *hw,
 			   struct ath9k_channel *ichan);
-void ath_update_chainmask(struct ath_softc *sc, int is_ht);
 int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
 		    struct ath9k_channel *hchan);
 
@@ -715,10 +697,12 @@ static inline void ath_ahb_exit(void) {}
 void ath9k_ps_wakeup(struct ath_softc *sc);
 void ath9k_ps_restore(struct ath_softc *sc);
 
+u8 ath_txchainmask_reduction(struct ath_softc *sc, u8 chainmask, u32 rate);
+
 void ath9k_set_bssid_mask(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
 int ath9k_wiphy_add(struct ath_softc *sc);
 int ath9k_wiphy_del(struct ath_wiphy *aphy);
-void ath9k_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb);
+void ath9k_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb, int ftype);
 int ath9k_wiphy_pause(struct ath_wiphy *aphy);
 int ath9k_wiphy_unpause(struct ath_wiphy *aphy);
 int ath9k_wiphy_select(struct ath_wiphy *aphy);
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/beacon.c linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/beacon.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/beacon.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/beacon.c	2011-03-14 21:20:32.000000000 -0400
@@ -28,7 +28,7 @@ int ath_beaconq_config(struct ath_softc
 	struct ath_hw *ah = sc->sc_ah;
 	struct ath_common *common = ath9k_hw_common(ah);
 	struct ath9k_tx_queue_info qi, qi_be;
-	int qnum;
+	struct ath_txq *txq;
 
 	ath9k_hw_get_txq_props(ah, sc->beacon.beaconq, &qi);
 	if (sc->sc_ah->opmode == NL80211_IFTYPE_AP) {
@@ -38,16 +38,16 @@ int ath_beaconq_config(struct ath_softc
 		qi.tqi_cwmax = 0;
 	} else {
 		/* Adhoc mode; important thing is to use 2x cwmin. */
-		qnum = sc->tx.hwq_map[WME_AC_BE];
-		ath9k_hw_get_txq_props(ah, qnum, &qi_be);
+		txq = sc->tx.txq_map[WME_AC_BE];
+		ath9k_hw_get_txq_props(ah, txq->axq_qnum, &qi_be);
 		qi.tqi_aifs = qi_be.tqi_aifs;
 		qi.tqi_cwmin = 4*qi_be.tqi_cwmin;
 		qi.tqi_cwmax = qi_be.tqi_cwmax;
 	}
 
 	if (!ath9k_hw_set_txq_props(ah, sc->beacon.beaconq, &qi)) {
-		ath_print(common, ATH_DBG_FATAL,
-			  "Unable to update h/w beacon queue parameters\n");
+		ath_err(common,
+			"Unable to update h/w beacon queue parameters\n");
 		return 0;
 	} else {
 		ath9k_hw_resettxqueue(ah, sc->beacon.beaconq);
@@ -103,12 +103,32 @@ static void ath_beacon_setup(struct ath_
 	memset(series, 0, sizeof(struct ath9k_11n_rate_series) * 4);
 	series[0].Tries = 1;
 	series[0].Rate = rate;
-	series[0].ChSel = common->tx_chainmask;
+	series[0].ChSel = ath_txchainmask_reduction(sc,
+			common->tx_chainmask, series[0].Rate);
 	series[0].RateFlags = (ctsrate) ? ATH9K_RATESERIES_RTS_CTS : 0;
 	ath9k_hw_set11n_ratescenario(ah, ds, ds, 0, ctsrate, ctsduration,
 				     series, 4, 0);
 }
 
+static void ath_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb)
+{
+	struct ath_wiphy *aphy = hw->priv;
+	struct ath_softc *sc = aphy->sc;
+	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+	struct ath_tx_control txctl;
+
+	memset(&txctl, 0, sizeof(struct ath_tx_control));
+	txctl.txq = sc->beacon.cabq;
+
+	ath_dbg(common, ATH_DBG_XMIT,
+		"transmitting CABQ packet, skb: %p\n", skb);
+
+	if (ath_tx_start(hw, skb, &txctl) != 0) {
+		ath_dbg(common, ATH_DBG_XMIT, "CABQ TX failed\n");
+		dev_kfree_skb_any(skb);
+	}
+}
+
 static struct ath_buf *ath_beacon_generate(struct ieee80211_hw *hw,
 					   struct ieee80211_vif *vif)
 {
@@ -169,8 +189,7 @@ static struct ath_buf *ath_beacon_genera
 		dev_kfree_skb_any(skb);
 		bf->bf_mpdu = NULL;
 		bf->bf_buf_addr = 0;
-		ath_print(common, ATH_DBG_FATAL,
-			  "dma_mapping_error on beaconing\n");
+		ath_err(common, "dma_mapping_error on beaconing\n");
 		return NULL;
 	}
 
@@ -190,8 +209,8 @@ static struct ath_buf *ath_beacon_genera
 
 	if (skb && cabq_depth) {
 		if (sc->nvifs > 1) {
-			ath_print(common, ATH_DBG_BEACON,
-				  "Flushing previous cabq traffic\n");
+			ath_dbg(common, ATH_DBG_BEACON,
+				"Flushing previous cabq traffic\n");
 			ath_draintxq(sc, cabq, false);
 		}
 	}
@@ -263,7 +282,7 @@ int ath_beacon_alloc(struct ath_wiphy *a
 	/* NB: the beacon data buffer must be 32-bit aligned. */
 	skb = ieee80211_beacon_get(sc->hw, vif);
 	if (skb == NULL) {
-		ath_print(common, ATH_DBG_BEACON, "cannot get skb\n");
+		ath_dbg(common, ATH_DBG_BEACON, "cannot get skb\n");
 		return -ENOMEM;
 	}
 
@@ -287,10 +306,9 @@ int ath_beacon_alloc(struct ath_wiphy *a
 		tsfadjust = intval * avp->av_bslot / ATH_BCBUF;
 		avp->tsf_adjust = cpu_to_le64(TU_TO_USEC(tsfadjust));
 
-		ath_print(common, ATH_DBG_BEACON,
-			  "stagger beacons, bslot %d intval "
-			  "%u tsfadjust %llu\n",
-			  avp->av_bslot, intval, (unsigned long long)tsfadjust);
+		ath_dbg(common, ATH_DBG_BEACON,
+			"stagger beacons, bslot %d intval %u tsfadjust %llu\n",
+			avp->av_bslot, intval, (unsigned long long)tsfadjust);
 
 		((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp =
 			avp->tsf_adjust;
@@ -304,8 +322,7 @@ int ath_beacon_alloc(struct ath_wiphy *a
 		dev_kfree_skb_any(skb);
 		bf->bf_mpdu = NULL;
 		bf->bf_buf_addr = 0;
-		ath_print(common, ATH_DBG_FATAL,
-			  "dma_mapping_error on beacon alloc\n");
+		ath_err(common, "dma_mapping_error on beacon alloc\n");
 		return -ENOMEM;
 	}
 
@@ -362,13 +379,13 @@ void ath_beacon_tasklet(unsigned long da
 		sc->beacon.bmisscnt++;
 
 		if (sc->beacon.bmisscnt < BSTUCK_THRESH) {
-			ath_print(common, ATH_DBG_BSTUCK,
-				  "missed %u consecutive beacons\n",
-				  sc->beacon.bmisscnt);
+			ath_dbg(common, ATH_DBG_BSTUCK,
+				"missed %u consecutive beacons\n",
+				sc->beacon.bmisscnt);
 			ath9k_hw_bstuck_nfcal(ah);
 		} else if (sc->beacon.bmisscnt >= BSTUCK_THRESH) {
-			ath_print(common, ATH_DBG_BSTUCK,
-				  "beacon is officially stuck\n");
+			ath_dbg(common, ATH_DBG_BSTUCK,
+				"beacon is officially stuck\n");
 			sc->sc_flags |= SC_OP_TSF_RESET;
 			ath_reset(sc, true);
 		}
@@ -377,9 +394,9 @@ void ath_beacon_tasklet(unsigned long da
 	}
 
 	if (sc->beacon.bmisscnt != 0) {
-		ath_print(common, ATH_DBG_BSTUCK,
-			  "resume beacon xmit after %u misses\n",
-			  sc->beacon.bmisscnt);
+		ath_dbg(common, ATH_DBG_BSTUCK,
+			"resume beacon xmit after %u misses\n",
+			sc->beacon.bmisscnt);
 		sc->beacon.bmisscnt = 0;
 	}
 
@@ -405,9 +422,9 @@ void ath_beacon_tasklet(unsigned long da
 	vif = sc->beacon.bslot[slot];
 	aphy = sc->beacon.bslot_aphy[slot];
 
-	ath_print(common, ATH_DBG_BEACON,
-		  "slot %d [tsf %llu tsftu %u intval %u] vif %p\n",
-		  slot, tsf, tsftu, intval, vif);
+	ath_dbg(common, ATH_DBG_BEACON,
+		"slot %d [tsf %llu tsftu %u intval %u] vif %p\n",
+		slot, tsf, tsftu, intval, vif);
 
 	bfaddr = 0;
 	if (vif) {
@@ -449,8 +466,8 @@ void ath_beacon_tasklet(unsigned long da
 		 * are still pending on the queue.
 		 */
 		if (!ath9k_hw_stoptxdma(ah, sc->beacon.beaconq)) {
-			ath_print(common, ATH_DBG_FATAL,
-				"beacon queue %u did not stop?\n", sc->beacon.beaconq);
+			ath_err(common, "beacon queue %u did not stop?\n",
+				sc->beacon.beaconq);
 		}
 
 		/* NB: cabq traffic should already be queued and primed */
@@ -503,7 +520,7 @@ static void ath_beacon_config_ap(struct
 
 	/* Set the computed AP beacon timers */
 
-	ath9k_hw_set_interrupts(ah, 0);
+	ath9k_hw_disable_interrupts(ah);
 	ath9k_beacon_init(sc, nexttbtt, intval);
 	sc->beacon.bmisscnt = 0;
 	ath9k_hw_set_interrupts(ah, ah->imask);
@@ -536,8 +553,8 @@ static void ath_beacon_config_sta(struct
 
 	/* No need to configure beacon if we are not associated */
 	if (!common->curaid) {
-		ath_print(common, ATH_DBG_BEACON,
-			 "STA is not yet associated..skipping beacon config\n");
+		ath_dbg(common, ATH_DBG_BEACON,
+			"STA is not yet associated..skipping beacon config\n");
 		return;
 	}
 
@@ -549,8 +566,6 @@ static void ath_beacon_config_sta(struct
 	 * last beacon we received (which may be none).
 	 */
 	dtimperiod = conf->dtim_period;
-	if (dtimperiod <= 0)		/* NB: 0 if not known */
-		dtimperiod = 1;
 	dtimcount = conf->dtim_count;
 	if (dtimcount >= dtimperiod)	/* NB: sanity check */
 		dtimcount = 0;
@@ -558,8 +573,6 @@ static void ath_beacon_config_sta(struct
 	cfpcount = 0;
 
 	sleepduration = conf->listen_interval * intval;
-	if (sleepduration <= 0)
-		sleepduration = intval;
 
 	/*
 	 * Pull nexttbtt forward to reflect the current
@@ -630,23 +643,22 @@ static void ath_beacon_config_sta(struct
 	/* TSF out of range threshold fixed at 1 second */
 	bs.bs_tsfoor_threshold = ATH9K_TSFOOR_THRESHOLD;
 
-	ath_print(common, ATH_DBG_BEACON, "tsf: %llu tsftu: %u\n", tsf, tsftu);
-	ath_print(common, ATH_DBG_BEACON,
-		  "bmiss: %u sleep: %u cfp-period: %u maxdur: %u next: %u\n",
-		  bs.bs_bmissthreshold, bs.bs_sleepduration,
-		  bs.bs_cfpperiod, bs.bs_cfpmaxduration, bs.bs_cfpnext);
+	ath_dbg(common, ATH_DBG_BEACON, "tsf: %llu tsftu: %u\n", tsf, tsftu);
+	ath_dbg(common, ATH_DBG_BEACON,
+		"bmiss: %u sleep: %u cfp-period: %u maxdur: %u next: %u\n",
+		bs.bs_bmissthreshold, bs.bs_sleepduration,
+		bs.bs_cfpperiod, bs.bs_cfpmaxduration, bs.bs_cfpnext);
 
 	/* Set the computed STA beacon timers */
 
-	ath9k_hw_set_interrupts(ah, 0);
+	ath9k_hw_disable_interrupts(ah);
 	ath9k_hw_set_sta_beacon_timers(ah, &bs);
 	ah->imask |= ATH9K_INT_BMISS;
 	ath9k_hw_set_interrupts(ah, ah->imask);
 }
 
 static void ath_beacon_config_adhoc(struct ath_softc *sc,
-				    struct ath_beacon_config *conf,
-				    struct ieee80211_vif *vif)
+				    struct ath_beacon_config *conf)
 {
 	struct ath_hw *ah = sc->sc_ah;
 	struct ath_common *common = ath9k_hw_common(ah);
@@ -670,9 +682,9 @@ static void ath_beacon_config_adhoc(stru
 		nexttbtt += intval;
 	} while (nexttbtt < tsftu);
 
-	ath_print(common, ATH_DBG_BEACON,
-		  "IBSS nexttbtt %u intval %u (%u)\n",
-		  nexttbtt, intval, conf->beacon_interval);
+	ath_dbg(common, ATH_DBG_BEACON,
+		"IBSS nexttbtt %u intval %u (%u)\n",
+		nexttbtt, intval, conf->beacon_interval);
 
 	/*
 	 * In IBSS mode enable the beacon timers but only enable SWBA interrupts
@@ -686,7 +698,7 @@ static void ath_beacon_config_adhoc(stru
 
 	/* Set the computed ADHOC beacon timers */
 
-	ath9k_hw_set_interrupts(ah, 0);
+	ath9k_hw_disable_interrupts(ah);
 	ath9k_beacon_init(sc, nexttbtt, intval);
 	sc->beacon.bmisscnt = 0;
 	ath9k_hw_set_interrupts(ah, ah->imask);
@@ -701,18 +713,17 @@ void ath_beacon_config(struct ath_softc
 	/* Setup the beacon configuration parameters */
 	if (vif) {
 		struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
-
 		iftype = vif->type;
-
 		cur_conf->beacon_interval = bss_conf->beacon_int;
 		cur_conf->dtim_period = bss_conf->dtim_period;
+	} else {
+		iftype = sc->sc_ah->opmode;
+	}
+
 		cur_conf->listen_interval = 1;
 		cur_conf->dtim_count = 1;
 		cur_conf->bmiss_timeout =
 			ATH_DEFAULT_BMISS_LIMIT * cur_conf->beacon_interval;
-	} else {
-		iftype = sc->sc_ah->opmode;
-	}
 
 	/*
 	 * It looks like mac80211 may end up using beacon interval of zero in
@@ -723,20 +734,27 @@ void ath_beacon_config(struct ath_softc
 	if (cur_conf->beacon_interval == 0)
 		cur_conf->beacon_interval = 100;
 
+	/*
+	 * Some times we dont parse dtim period from mac80211, in that case
+	 * use a default value
+	 */
+	if (cur_conf->dtim_period == 0)
+		cur_conf->dtim_period = 1;
+
 	switch (iftype) {
 	case NL80211_IFTYPE_AP:
 		ath_beacon_config_ap(sc, cur_conf);
 		break;
 	case NL80211_IFTYPE_ADHOC:
 	case NL80211_IFTYPE_MESH_POINT:
-		ath_beacon_config_adhoc(sc, cur_conf, vif);
+		ath_beacon_config_adhoc(sc, cur_conf);
 		break;
 	case NL80211_IFTYPE_STATION:
 		ath_beacon_config_sta(sc, cur_conf);
 		break;
 	default:
-		ath_print(common, ATH_DBG_CONFIG,
-			  "Unsupported beaconing mode\n");
+		ath_dbg(common, ATH_DBG_CONFIG,
+			"Unsupported beaconing mode\n");
 		return;
 	}
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/btcoex.c linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/btcoex.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/btcoex.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/btcoex.c	2011-03-14 21:20:32.000000000 -0400
@@ -35,29 +35,6 @@ struct ath_btcoex_config {
 	bool bt_hold_rx_clear;
 };
 
-static const u16 ath_subsysid_tbl[] = {
-	AR9280_COEX2WIRE_SUBSYSID,
-	AT9285_COEX3WIRE_SA_SUBSYSID,
-	AT9285_COEX3WIRE_DA_SUBSYSID
-};
-
-/*
- * Checks the subsystem id of the device to see if it
- * supports btcoex
- */
-bool ath9k_hw_btcoex_supported(struct ath_hw *ah)
-{
-	int i;
-
-	if (!ah->hw_version.subsysid)
-		return false;
-
-	for (i = 0; i < ARRAY_SIZE(ath_subsysid_tbl); i++)
-		if (ah->hw_version.subsysid == ath_subsysid_tbl[i])
-			return true;
-
-	return false;
-}
 
 void ath9k_hw_init_btcoex_hw(struct ath_hw *ah, int qnum)
 {
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/btcoex.h linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/btcoex.h
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/btcoex.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/btcoex.h	2011-03-14 21:20:32.000000000 -0400
@@ -49,7 +49,6 @@ struct ath_btcoex_hw {
 	u32 bt_coex_mode2; 	/* Register setting for AR_BT_COEX_MODE2 */
 };
 
-bool ath9k_hw_btcoex_supported(struct ath_hw *ah);
 void ath9k_hw_btcoex_init_2wire(struct ath_hw *ah);
 void ath9k_hw_btcoex_init_3wire(struct ath_hw *ah);
 void ath9k_hw_init_btcoex_hw(struct ath_hw *ah, int qnum);
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/calib.c linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/calib.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/calib.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/calib.c	2011-03-14 21:20:32.000000000 -0400
@@ -97,12 +97,12 @@ static void ath9k_hw_update_nfcal_hist_b
 		if (h[i].privNF > limit->max) {
 			high_nf_mid = true;
 
-			ath_print(common, ATH_DBG_CALIBRATE,
-				  "NFmid[%d] (%d) > MAX (%d), %s\n",
-				  i, h[i].privNF, limit->max,
-				  (cal->nfcal_interference ?
-				   "not corrected (due to interference)" :
-				   "correcting to MAX"));
+			ath_dbg(common, ATH_DBG_CALIBRATE,
+				"NFmid[%d] (%d) > MAX (%d), %s\n",
+				i, h[i].privNF, limit->max,
+				(cal->nfcal_interference ?
+				 "not corrected (due to interference)" :
+				 "correcting to MAX"));
 
 			/*
 			 * Normally we limit the average noise floor by the
@@ -180,18 +180,18 @@ bool ath9k_hw_reset_calvalid(struct ath_
 		return true;
 
 	if (currCal->calState != CAL_DONE) {
-		ath_print(common, ATH_DBG_CALIBRATE,
-			  "Calibration state incorrect, %d\n",
-			  currCal->calState);
+		ath_dbg(common, ATH_DBG_CALIBRATE,
+			"Calibration state incorrect, %d\n",
+			currCal->calState);
 		return true;
 	}
 
 	if (!(ah->supp_cals & currCal->calData->calType))
 		return true;
 
-	ath_print(common, ATH_DBG_CALIBRATE,
-		  "Resetting Cal %d state for channel %u\n",
-		  currCal->calData->calType, conf->channel->center_freq);
+	ath_dbg(common, ATH_DBG_CALIBRATE,
+		"Resetting Cal %d state for channel %u\n",
+		currCal->calData->calType, conf->channel->center_freq);
 
 	ah->caldata->CalValid &= ~currCal->calData->calType;
 	currCal->calState = CAL_WAITING;
@@ -279,9 +279,9 @@ void ath9k_hw_loadnf(struct ath_hw *ah,
 	 * noisefloor until the next calibration timer.
 	 */
 	if (j == 1000) {
-		ath_print(common, ATH_DBG_ANY, "Timeout while waiting for nf "
-			  "to load: AR_PHY_AGC_CONTROL=0x%x\n",
-			  REG_READ(ah, AR_PHY_AGC_CONTROL));
+		ath_dbg(common, ATH_DBG_ANY,
+			"Timeout while waiting for nf to load: AR_PHY_AGC_CONTROL=0x%x\n",
+			REG_READ(ah, AR_PHY_AGC_CONTROL));
 		return;
 	}
 
@@ -318,19 +318,19 @@ static void ath9k_hw_nf_sanitize(struct
 		if (!nf[i])
 			continue;
 
-		ath_print(common, ATH_DBG_CALIBRATE,
-			  "NF calibrated [%s] [chain %d] is %d\n",
-			  (i >= 3 ? "ext" : "ctl"), i % 3, nf[i]);
+		ath_dbg(common, ATH_DBG_CALIBRATE,
+			"NF calibrated [%s] [chain %d] is %d\n",
+			(i >= 3 ? "ext" : "ctl"), i % 3, nf[i]);
 
 		if (nf[i] > ATH9K_NF_TOO_HIGH) {
-			ath_print(common, ATH_DBG_CALIBRATE,
-				  "NF[%d] (%d) > MAX (%d), correcting to MAX",
-				  i, nf[i], ATH9K_NF_TOO_HIGH);
+			ath_dbg(common, ATH_DBG_CALIBRATE,
+				"NF[%d] (%d) > MAX (%d), correcting to MAX\n",
+				i, nf[i], ATH9K_NF_TOO_HIGH);
 			nf[i] = limit->max;
 		} else if (nf[i] < limit->min) {
-			ath_print(common, ATH_DBG_CALIBRATE,
-				  "NF[%d] (%d) < MIN (%d), correcting to NOM",
-				  i, nf[i], limit->min);
+			ath_dbg(common, ATH_DBG_CALIBRATE,
+				"NF[%d] (%d) < MIN (%d), correcting to NOM\n",
+				i, nf[i], limit->min);
 			nf[i] = limit->nominal;
 		}
 	}
@@ -347,8 +347,8 @@ bool ath9k_hw_getnf(struct ath_hw *ah, s
 
 	chan->channelFlags &= (~CHANNEL_CW_INT);
 	if (REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) {
-		ath_print(common, ATH_DBG_CALIBRATE,
-			  "NF did not complete in calibration window\n");
+		ath_dbg(common, ATH_DBG_CALIBRATE,
+			"NF did not complete in calibration window\n");
 		return false;
 	}
 
@@ -357,10 +357,9 @@ bool ath9k_hw_getnf(struct ath_hw *ah, s
 	nf = nfarray[0];
 	if (ath9k_hw_get_nf_thresh(ah, c->band, &nfThresh)
 	    && nf > nfThresh) {
-		ath_print(common, ATH_DBG_CALIBRATE,
-			  "noise floor failed detected; "
-			  "detected %d, threshold %d\n",
-			  nf, nfThresh);
+		ath_dbg(common, ATH_DBG_CALIBRATE,
+			"noise floor failed detected; detected %d, threshold %d\n",
+			nf, nfThresh);
 		chan->channelFlags |= CHANNEL_CW_INT;
 	}
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/common.c linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/common.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/common.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/common.c	2011-03-14 21:20:32.000000000 -0400
@@ -107,12 +107,10 @@ static u32 ath9k_get_extchanmode(struct
 /*
  * Update internal channel flags.
  */
-void ath9k_cmn_update_ichannel(struct ieee80211_hw *hw,
-			       struct ath9k_channel *ichan)
+void ath9k_cmn_update_ichannel(struct ath9k_channel *ichan,
+			       struct ieee80211_channel *chan,
+			       enum nl80211_channel_type channel_type)
 {
-	struct ieee80211_channel *chan = hw->conf.channel;
-	struct ieee80211_conf *conf = &hw->conf;
-
 	ichan->channel = chan->center_freq;
 	ichan->chan = chan;
 
@@ -124,9 +122,8 @@ void ath9k_cmn_update_ichannel(struct ie
 		ichan->channelFlags = CHANNEL_5GHZ | CHANNEL_OFDM;
 	}
 
-	if (conf_is_ht(conf))
-		ichan->chanmode = ath9k_get_extchanmode(chan,
-							conf->channel_type);
+	if (channel_type != NL80211_CHAN_NO_HT)
+		ichan->chanmode = ath9k_get_extchanmode(chan, channel_type);
 }
 EXPORT_SYMBOL(ath9k_cmn_update_ichannel);
 
@@ -142,7 +139,7 @@ struct ath9k_channel *ath9k_cmn_get_curc
 
 	chan_idx = curchan->hw_value;
 	channel = &ah->channels[chan_idx];
-	ath9k_cmn_update_ichannel(hw, channel);
+	ath9k_cmn_update_ichannel(channel, curchan, hw->conf.channel_type);
 
 	return channel;
 }
@@ -183,8 +180,8 @@ void ath9k_cmn_btcoex_bt_stomp(struct at
 					   AR_STOMP_NONE_WLAN_WGHT);
 		break;
 	default:
-		ath_print(common, ATH_DBG_BTCOEX,
-			  "Invalid Stomptype\n");
+		ath_dbg(common, ATH_DBG_BTCOEX,
+			"Invalid Stomptype\n");
 		break;
 	}
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/common.h linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/common.h
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/common.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/common.h	2011-03-14 21:20:32.000000000 -0400
@@ -17,7 +17,6 @@
 #include <net/mac80211.h>
 
 #include "../ath.h"
-#include "../debug.h"
 
 #include "hw.h"
 #include "hw-ops.h"
@@ -31,10 +30,11 @@
 #define WME_MAX_BA              WME_BA_BMP_SIZE
 #define ATH_TID_MAX_BUFS        (2 * WME_MAX_BA)
 
-#define WME_AC_BE   0
-#define WME_AC_BK   1
-#define WME_AC_VI   2
-#define WME_AC_VO   3
+/* These must match mac80211 skb queue mapping numbers */
+#define WME_AC_VO   0
+#define WME_AC_VI   1
+#define WME_AC_BE   2
+#define WME_AC_BK   3
 #define WME_NUM_AC  4
 
 #define ATH_RSSI_DUMMY_MARKER   0x127
@@ -62,8 +62,9 @@ enum ath_stomp_type {
 
 int ath9k_cmn_padpos(__le16 frame_control);
 int ath9k_cmn_get_hw_crypto_keytype(struct sk_buff *skb);
-void ath9k_cmn_update_ichannel(struct ieee80211_hw *hw,
-			       struct ath9k_channel *ichan);
+void ath9k_cmn_update_ichannel(struct ath9k_channel *ichan,
+			       struct ieee80211_channel *chan,
+			       enum nl80211_channel_type channel_type);
 struct ath9k_channel *ath9k_cmn_get_curchannel(struct ieee80211_hw *hw,
 					       struct ath_hw *ah);
 int ath9k_cmn_count_streams(unsigned int chainmask, int max);
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/debug.c linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/debug.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/debug.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/debug.c	2011-03-14 21:20:32.000000000 -0400
@@ -24,8 +24,6 @@
 #define REG_READ_D(_ah, _reg) \
 	ath9k_hw_common(_ah)->ops->read((_ah), (_reg))
 
-static struct dentry *ath9k_debugfs_root;
-
 static int ath9k_debugfs_open(struct inode *inode, struct file *file)
 {
 	file->private_data = inode->i_private;
@@ -461,16 +459,16 @@ static ssize_t read_file_wiphy(struct fi
 
 	/* Put variable-length stuff down here, and check for overflows. */
 	for (i = 0; i < sc->num_sec_wiphy; i++) {
-		struct ath_wiphy *aphy = sc->sec_wiphy[i];
-		if (aphy == NULL)
+		struct ath_wiphy *aphy_tmp = sc->sec_wiphy[i];
+		if (aphy_tmp == NULL)
 			continue;
-		chan = aphy->hw->conf.channel;
+		chan = aphy_tmp->hw->conf.channel;
 		len += snprintf(buf + len, sizeof(buf) - len,
 			"secondary: %s (%s chan=%d ht=%d)\n",
-			wiphy_name(aphy->hw->wiphy),
-			ath_wiphy_state_str(aphy->state),
+			wiphy_name(aphy_tmp->hw->wiphy),
+			ath_wiphy_state_str(aphy_tmp->state),
 			ieee80211_frequency_to_channel(chan->center_freq),
-			aphy->chan_is_ht);
+						       aphy_tmp->chan_is_ht);
 	}
 	if (len > sizeof(buf))
 		len = sizeof(buf);
@@ -585,10 +583,10 @@ static const struct file_operations fops
 	do {								\
 		len += snprintf(buf + len, size - len,			\
 				"%s%13u%11u%10u%10u\n", str,		\
-		sc->debug.stats.txstats[sc->tx.hwq_map[WME_AC_BE]].elem, \
-		sc->debug.stats.txstats[sc->tx.hwq_map[WME_AC_BK]].elem, \
-		sc->debug.stats.txstats[sc->tx.hwq_map[WME_AC_VI]].elem, \
-		sc->debug.stats.txstats[sc->tx.hwq_map[WME_AC_VO]].elem); \
+		sc->debug.stats.txstats[WME_AC_BE].elem, \
+		sc->debug.stats.txstats[WME_AC_BK].elem, \
+		sc->debug.stats.txstats[WME_AC_VI].elem, \
+		sc->debug.stats.txstats[WME_AC_VO].elem); \
 } while(0)
 
 static ssize_t read_file_xmit(struct file *file, char __user *user_buf,
@@ -630,33 +628,35 @@ static ssize_t read_file_xmit(struct fil
 	return retval;
 }
 
-void ath_debug_stat_tx(struct ath_softc *sc, struct ath_txq *txq,
-		       struct ath_buf *bf, struct ath_tx_status *ts)
+void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf,
+		       struct ath_tx_status *ts)
 {
-	TX_STAT_INC(txq->axq_qnum, tx_pkts_all);
-	sc->debug.stats.txstats[txq->axq_qnum].tx_bytes_all += bf->bf_mpdu->len;
+	int qnum = skb_get_queue_mapping(bf->bf_mpdu);
+
+	TX_STAT_INC(qnum, tx_pkts_all);
+	sc->debug.stats.txstats[qnum].tx_bytes_all += bf->bf_mpdu->len;
 
 	if (bf_isampdu(bf)) {
 		if (bf_isxretried(bf))
-			TX_STAT_INC(txq->axq_qnum, a_xretries);
+			TX_STAT_INC(qnum, a_xretries);
 		else
-			TX_STAT_INC(txq->axq_qnum, a_completed);
+			TX_STAT_INC(qnum, a_completed);
 	} else {
-		TX_STAT_INC(txq->axq_qnum, completed);
+		TX_STAT_INC(qnum, completed);
 	}
 
 	if (ts->ts_status & ATH9K_TXERR_FIFO)
-		TX_STAT_INC(txq->axq_qnum, fifo_underrun);
+		TX_STAT_INC(qnum, fifo_underrun);
 	if (ts->ts_status & ATH9K_TXERR_XTXOP)
-		TX_STAT_INC(txq->axq_qnum, xtxop);
+		TX_STAT_INC(qnum, xtxop);
 	if (ts->ts_status & ATH9K_TXERR_TIMER_EXPIRED)
-		TX_STAT_INC(txq->axq_qnum, timer_exp);
+		TX_STAT_INC(qnum, timer_exp);
 	if (ts->ts_flags & ATH9K_TX_DESC_CFG_ERR)
-		TX_STAT_INC(txq->axq_qnum, desc_cfg_err);
+		TX_STAT_INC(qnum, desc_cfg_err);
 	if (ts->ts_flags & ATH9K_TX_DATA_UNDERRUN)
-		TX_STAT_INC(txq->axq_qnum, data_underrun);
+		TX_STAT_INC(qnum, data_underrun);
 	if (ts->ts_flags & ATH9K_TX_DELIM_UNDERRUN)
-		TX_STAT_INC(txq->axq_qnum, delim_underrun);
+		TX_STAT_INC(qnum, delim_underrun);
 }
 
 static const struct file_operations fops_xmit = {
@@ -876,11 +876,8 @@ int ath9k_init_debug(struct ath_hw *ah)
 	struct ath_common *common = ath9k_hw_common(ah);
 	struct ath_softc *sc = (struct ath_softc *) common->priv;
 
-	if (!ath9k_debugfs_root)
-		return -ENOENT;
-
-	sc->debug.debugfs_phy = debugfs_create_dir(wiphy_name(sc->hw->wiphy),
-						      ath9k_debugfs_root);
+	sc->debug.debugfs_phy = debugfs_create_dir("ath9k",
+						   sc->hw->wiphy->debugfsdir);
 	if (!sc->debug.debugfs_phy)
 		return -ENOMEM;
 
@@ -933,29 +930,7 @@ int ath9k_init_debug(struct ath_hw *ah)
 	sc->debug.regidx = 0;
 	return 0;
 err:
-	ath9k_exit_debug(ah);
-	return -ENOMEM;
-}
-
-void ath9k_exit_debug(struct ath_hw *ah)
-{
-	struct ath_common *common = ath9k_hw_common(ah);
-	struct ath_softc *sc = (struct ath_softc *) common->priv;
-
 	debugfs_remove_recursive(sc->debug.debugfs_phy);
-}
-
-int ath9k_debug_create_root(void)
-{
-	ath9k_debugfs_root = debugfs_create_dir(KBUILD_MODNAME, NULL);
-	if (!ath9k_debugfs_root)
-		return -ENOENT;
-
-	return 0;
-}
-
-void ath9k_debug_remove_root(void)
-{
-	debugfs_remove(ath9k_debugfs_root);
-	ath9k_debugfs_root = NULL;
+	sc->debug.debugfs_phy = NULL;
+	return -ENOMEM;
 }
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/debug.h linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/debug.h
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/debug.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/debug.h	2011-03-14 21:20:32.000000000 -0400
@@ -164,13 +164,10 @@ struct ath9k_debug {
 };
 
 int ath9k_init_debug(struct ath_hw *ah);
-void ath9k_exit_debug(struct ath_hw *ah);
 
-int ath9k_debug_create_root(void);
-void ath9k_debug_remove_root(void);
 void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status);
-void ath_debug_stat_tx(struct ath_softc *sc, struct ath_txq *txq,
-		       struct ath_buf *bf, struct ath_tx_status *ts);
+void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf,
+		       struct ath_tx_status *ts);
 void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs);
 
 #else
@@ -180,26 +177,12 @@ static inline int ath9k_init_debug(struc
 	return 0;
 }
 
-static inline void ath9k_exit_debug(struct ath_hw *ah)
-{
-}
-
-static inline int ath9k_debug_create_root(void)
-{
-	return 0;
-}
-
-static inline void ath9k_debug_remove_root(void)
-{
-}
-
 static inline void ath_debug_stat_interrupt(struct ath_softc *sc,
 					    enum ath9k_int status)
 {
 }
 
 static inline void ath_debug_stat_tx(struct ath_softc *sc,
-				     struct ath_txq *txq,
 				     struct ath_buf *bf,
 				     struct ath_tx_status *ts)
 {
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/eeprom_4k.c linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/eeprom_4k.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/eeprom_4k.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/eeprom_4k.c	2011-03-14 21:20:32.000000000 -0400
@@ -37,14 +37,14 @@ static bool ath9k_hw_4k_fill_eeprom(stru
 	eep_start_loc = 64;
 
 	if (!ath9k_hw_use_flash(ah)) {
-		ath_print(common, ATH_DBG_EEPROM,
-			  "Reading from EEPROM, not flash\n");
+		ath_dbg(common, ATH_DBG_EEPROM,
+			"Reading from EEPROM, not flash\n");
 	}
 
 	for (addr = 0; addr < SIZE_EEPROM_4K; addr++) {
 		if (!ath9k_hw_nvram_read(common, addr + eep_start_loc, eep_data)) {
-			ath_print(common, ATH_DBG_EEPROM,
-				  "Unable to read eeprom region\n");
+			ath_dbg(common, ATH_DBG_EEPROM,
+				"Unable to read eeprom region\n");
 			return false;
 		}
 		eep_data++;
@@ -69,13 +69,12 @@ static int ath9k_hw_4k_check_eeprom(stru
 	if (!ath9k_hw_use_flash(ah)) {
 		if (!ath9k_hw_nvram_read(common, AR5416_EEPROM_MAGIC_OFFSET,
 					 &magic)) {
-			ath_print(common, ATH_DBG_FATAL,
-				  "Reading Magic # failed\n");
+			ath_err(common, "Reading Magic # failed\n");
 			return false;
 		}
 
-		ath_print(common, ATH_DBG_EEPROM,
-			  "Read Magic = 0x%04X\n", magic);
+		ath_dbg(common, ATH_DBG_EEPROM,
+			"Read Magic = 0x%04X\n", magic);
 
 		if (magic != AR5416_EEPROM_MAGIC) {
 			magic2 = swab16(magic);
@@ -90,16 +89,15 @@ static int ath9k_hw_4k_check_eeprom(stru
 					eepdata++;
 				}
 			} else {
-				ath_print(common, ATH_DBG_FATAL,
-					  "Invalid EEPROM Magic. "
-					  "endianness mismatch.\n");
+				ath_err(common,
+					"Invalid EEPROM Magic. Endianness mismatch.\n");
 				return -EINVAL;
 			}
 		}
 	}
 
-	ath_print(common, ATH_DBG_EEPROM, "need_swap = %s.\n",
-		  need_swap ? "True" : "False");
+	ath_dbg(common, ATH_DBG_EEPROM, "need_swap = %s.\n",
+		need_swap ? "True" : "False");
 
 	if (need_swap)
 		el = swab16(ah->eeprom.map4k.baseEepHeader.length);
@@ -120,8 +118,8 @@ static int ath9k_hw_4k_check_eeprom(stru
 		u32 integer;
 		u16 word;
 
-		ath_print(common, ATH_DBG_EEPROM,
-			  "EEPROM Endianness is not native.. Changing\n");
+		ath_dbg(common, ATH_DBG_EEPROM,
+			"EEPROM Endianness is not native.. Changing\n");
 
 		word = swab16(eep->baseEepHeader.length);
 		eep->baseEepHeader.length = word;
@@ -155,7 +153,7 @@ static int ath9k_hw_4k_check_eeprom(stru
 			eep->modalHeader.antCtrlChain[i] = integer;
 		}
 
-		for (i = 0; i < AR5416_EEPROM_MODAL_SPURS; i++) {
+		for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) {
 			word = swab16(eep->modalHeader.spurChans[i].spurChan);
 			eep->modalHeader.spurChans[i].spurChan = word;
 		}
@@ -163,9 +161,8 @@ static int ath9k_hw_4k_check_eeprom(stru
 
 	if (sum != 0xffff || ah->eep_ops->get_eeprom_ver(ah) != AR5416_EEP_VER ||
 	    ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_NO_BACK_VER) {
-		ath_print(common, ATH_DBG_FATAL,
-			  "Bad EEPROM checksum 0x%x or revision 0x%04x\n",
-			  sum, ah->eep_ops->get_eeprom_ver(ah));
+		ath_err(common, "Bad EEPROM checksum 0x%x or revision 0x%04x\n",
+			sum, ah->eep_ops->get_eeprom_ver(ah));
 		return -EINVAL;
 	}
 
@@ -230,173 +227,6 @@ static u32 ath9k_hw_4k_get_eeprom(struct
 	}
 }
 
-static void ath9k_hw_get_4k_gain_boundaries_pdadcs(struct ath_hw *ah,
-				struct ath9k_channel *chan,
-				struct cal_data_per_freq_4k *pRawDataSet,
-				u8 *bChans, u16 availPiers,
-				u16 tPdGainOverlap,
-				u16 *pPdGainBoundaries, u8 *pPDADCValues,
-				u16 numXpdGains)
-{
-#define TMP_VAL_VPD_TABLE \
-	((vpdTableI[i][sizeCurrVpdTable - 1] + (ss - maxIndex + 1) * vpdStep));
-	int i, j, k;
-	int16_t ss;
-	u16 idxL = 0, idxR = 0, numPiers;
-	static u8 vpdTableL[AR5416_EEP4K_NUM_PD_GAINS]
-		[AR5416_MAX_PWR_RANGE_IN_HALF_DB];
-	static u8 vpdTableR[AR5416_EEP4K_NUM_PD_GAINS]
-		[AR5416_MAX_PWR_RANGE_IN_HALF_DB];
-	static u8 vpdTableI[AR5416_EEP4K_NUM_PD_GAINS]
-		[AR5416_MAX_PWR_RANGE_IN_HALF_DB];
-
-	u8 *pVpdL, *pVpdR, *pPwrL, *pPwrR;
-	u8 minPwrT4[AR5416_EEP4K_NUM_PD_GAINS];
-	u8 maxPwrT4[AR5416_EEP4K_NUM_PD_GAINS];
-	int16_t vpdStep;
-	int16_t tmpVal;
-	u16 sizeCurrVpdTable, maxIndex, tgtIndex;
-	bool match;
-	int16_t minDelta = 0;
-	struct chan_centers centers;
-#define PD_GAIN_BOUNDARY_DEFAULT 58;
-
-	memset(&minPwrT4, 0, AR9287_NUM_PD_GAINS);
-	ath9k_hw_get_channel_centers(ah, chan, &centers);
-
-	for (numPiers = 0; numPiers < availPiers; numPiers++) {
-		if (bChans[numPiers] == AR5416_BCHAN_UNUSED)
-			break;
-	}
-
-	match = ath9k_hw_get_lower_upper_index(
-					(u8)FREQ2FBIN(centers.synth_center,
-					IS_CHAN_2GHZ(chan)), bChans, numPiers,
-					&idxL, &idxR);
-
-	if (match) {
-		for (i = 0; i < numXpdGains; i++) {
-			minPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][0];
-			maxPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][4];
-			ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
-					pRawDataSet[idxL].pwrPdg[i],
-					pRawDataSet[idxL].vpdPdg[i],
-					AR5416_EEP4K_PD_GAIN_ICEPTS,
-					vpdTableI[i]);
-		}
-	} else {
-		for (i = 0; i < numXpdGains; i++) {
-			pVpdL = pRawDataSet[idxL].vpdPdg[i];
-			pPwrL = pRawDataSet[idxL].pwrPdg[i];
-			pVpdR = pRawDataSet[idxR].vpdPdg[i];
-			pPwrR = pRawDataSet[idxR].pwrPdg[i];
-
-			minPwrT4[i] = max(pPwrL[0], pPwrR[0]);
-
-			maxPwrT4[i] =
-				min(pPwrL[AR5416_EEP4K_PD_GAIN_ICEPTS - 1],
-				    pPwrR[AR5416_EEP4K_PD_GAIN_ICEPTS - 1]);
-
-
-			ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
-						pPwrL, pVpdL,
-						AR5416_EEP4K_PD_GAIN_ICEPTS,
-						vpdTableL[i]);
-			ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
-						pPwrR, pVpdR,
-						AR5416_EEP4K_PD_GAIN_ICEPTS,
-						vpdTableR[i]);
-
-			for (j = 0; j <= (maxPwrT4[i] - minPwrT4[i]) / 2; j++) {
-				vpdTableI[i][j] =
-					(u8)(ath9k_hw_interpolate((u16)
-					     FREQ2FBIN(centers.
-						       synth_center,
-						       IS_CHAN_2GHZ
-						       (chan)),
-					     bChans[idxL], bChans[idxR],
-					     vpdTableL[i][j], vpdTableR[i][j]));
-			}
-		}
-	}
-
-	k = 0;
-
-	for (i = 0; i < numXpdGains; i++) {
-		if (i == (numXpdGains - 1))
-			pPdGainBoundaries[i] =
-				(u16)(maxPwrT4[i] / 2);
-		else
-			pPdGainBoundaries[i] =
-				(u16)((maxPwrT4[i] + minPwrT4[i + 1]) / 4);
-
-		pPdGainBoundaries[i] =
-			min((u16)AR5416_MAX_RATE_POWER, pPdGainBoundaries[i]);
-
-		if ((i == 0) && !AR_SREV_5416_20_OR_LATER(ah)) {
-			minDelta = pPdGainBoundaries[0] - 23;
-			pPdGainBoundaries[0] = 23;
-		} else {
-			minDelta = 0;
-		}
-
-		if (i == 0) {
-			if (AR_SREV_9280_20_OR_LATER(ah))
-				ss = (int16_t)(0 - (minPwrT4[i] / 2));
-			else
-				ss = 0;
-		} else {
-			ss = (int16_t)((pPdGainBoundaries[i - 1] -
-					(minPwrT4[i] / 2)) -
-				       tPdGainOverlap + 1 + minDelta);
-		}
-		vpdStep = (int16_t)(vpdTableI[i][1] - vpdTableI[i][0]);
-		vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep);
-
-		while ((ss < 0) && (k < (AR5416_NUM_PDADC_VALUES - 1))) {
-			tmpVal = (int16_t)(vpdTableI[i][0] + ss * vpdStep);
-			pPDADCValues[k++] = (u8)((tmpVal < 0) ? 0 : tmpVal);
-			ss++;
-		}
-
-		sizeCurrVpdTable = (u8) ((maxPwrT4[i] - minPwrT4[i]) / 2 + 1);
-		tgtIndex = (u8)(pPdGainBoundaries[i] + tPdGainOverlap -
-				(minPwrT4[i] / 2));
-		maxIndex = (tgtIndex < sizeCurrVpdTable) ?
-			tgtIndex : sizeCurrVpdTable;
-
-		while ((ss < maxIndex) && (k < (AR5416_NUM_PDADC_VALUES - 1)))
-			pPDADCValues[k++] = vpdTableI[i][ss++];
-
-		vpdStep = (int16_t)(vpdTableI[i][sizeCurrVpdTable - 1] -
-				    vpdTableI[i][sizeCurrVpdTable - 2]);
-		vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep);
-
-		if (tgtIndex >= maxIndex) {
-			while ((ss <= tgtIndex) &&
-			       (k < (AR5416_NUM_PDADC_VALUES - 1))) {
-				tmpVal = (int16_t) TMP_VAL_VPD_TABLE;
-				pPDADCValues[k++] = (u8)((tmpVal > 255) ?
-							 255 : tmpVal);
-				ss++;
-			}
-		}
-	}
-
-	while (i < AR5416_EEP4K_PD_GAINS_IN_MASK) {
-		pPdGainBoundaries[i] = PD_GAIN_BOUNDARY_DEFAULT;
-		i++;
-	}
-
-	while (k < AR5416_NUM_PDADC_VALUES) {
-		pPDADCValues[k] = pPDADCValues[k - 1];
-		k++;
-	}
-
-	return;
-#undef TMP_VAL_VPD_TABLE
-}
-
 static void ath9k_hw_set_4k_power_cal_table(struct ath_hw *ah,
 				  struct ath9k_channel *chan,
 				  int16_t *pTxPowerIndexOffset)
@@ -407,7 +237,7 @@ static void ath9k_hw_set_4k_power_cal_ta
 	u8 *pCalBChans = NULL;
 	u16 pdGainOverlap_t2;
 	static u8 pdadcValues[AR5416_NUM_PDADC_VALUES];
-	u16 gainBoundaries[AR5416_EEP4K_PD_GAINS_IN_MASK];
+	u16 gainBoundaries[AR5416_PD_GAINS_IN_MASK];
 	u16 numPiers, i, j;
 	u16 numXpdGain, xpdMask;
 	u16 xpdGainValues[AR5416_EEP4K_NUM_PD_GAINS] = { 0, 0 };
@@ -429,12 +259,12 @@ static void ath9k_hw_set_4k_power_cal_ta
 
 	numXpdGain = 0;
 
-	for (i = 1; i <= AR5416_EEP4K_PD_GAINS_IN_MASK; i++) {
-		if ((xpdMask >> (AR5416_EEP4K_PD_GAINS_IN_MASK - i)) & 1) {
+	for (i = 1; i <= AR5416_PD_GAINS_IN_MASK; i++) {
+		if ((xpdMask >> (AR5416_PD_GAINS_IN_MASK - i)) & 1) {
 			if (numXpdGain >= AR5416_EEP4K_NUM_PD_GAINS)
 				break;
 			xpdGainValues[numXpdGain] =
-				(u16)(AR5416_EEP4K_PD_GAINS_IN_MASK - i);
+				(u16)(AR5416_PD_GAINS_IN_MASK - i);
 			numXpdGain++;
 		}
 	}
@@ -458,7 +288,7 @@ static void ath9k_hw_set_4k_power_cal_ta
 		if (pEepData->baseEepHeader.txMask & (1 << i)) {
 			pRawDataset = pEepData->calPierData2G[i];
 
-			ath9k_hw_get_4k_gain_boundaries_pdadcs(ah, chan,
+			ath9k_hw_get_gain_boundaries_pdadcs(ah, chan,
 					    pRawDataset, pCalBChans,
 					    numPiers, pdGainOverlap_t2,
 					    gainBoundaries,
@@ -488,21 +318,20 @@ static void ath9k_hw_set_4k_power_cal_ta
 					((pdadcValues[4 * j + 3] & 0xFF) << 24);
 				REG_WRITE(ah, regOffset, reg32);
 
-				ath_print(common, ATH_DBG_EEPROM,
-					  "PDADC (%d,%4x): %4.4x %8.8x\n",
-					  i, regChainOffset, regOffset,
-					  reg32);
-				ath_print(common, ATH_DBG_EEPROM,
-					  "PDADC: Chain %d | "
-					  "PDADC %3d Value %3d | "
-					  "PDADC %3d Value %3d | "
-					  "PDADC %3d Value %3d | "
-					  "PDADC %3d Value %3d |\n",
-					  i, 4 * j, pdadcValues[4 * j],
-					  4 * j + 1, pdadcValues[4 * j + 1],
-					  4 * j + 2, pdadcValues[4 * j + 2],
-					  4 * j + 3,
-					  pdadcValues[4 * j + 3]);
+				ath_dbg(common, ATH_DBG_EEPROM,
+					"PDADC (%d,%4x): %4.4x %8.8x\n",
+					i, regChainOffset, regOffset,
+					reg32);
+				ath_dbg(common, ATH_DBG_EEPROM,
+					"PDADC: Chain %d | "
+					"PDADC %3d Value %3d | "
+					"PDADC %3d Value %3d | "
+					"PDADC %3d Value %3d | "
+					"PDADC %3d Value %3d |\n",
+					i, 4 * j, pdadcValues[4 * j],
+					4 * j + 1, pdadcValues[4 * j + 1],
+					4 * j + 2, pdadcValues[4 * j + 2],
+					4 * j + 3, pdadcValues[4 * j + 3]);
 
 				regOffset += 4;
 			}
@@ -532,14 +361,16 @@ static void ath9k_hw_set_4k_power_per_ra
 	int i;
 	int16_t twiceLargestAntenna;
 	u16 twiceMinEdgePower;
-	u16 twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
+	u16 twiceMaxEdgePower = MAX_RATE_POWER;
 	u16 scaledPower = 0, minCtlPower, maxRegAllowedPower;
-	u16 numCtlModes, *pCtlMode, ctlMode, freq;
+	u16 numCtlModes;
+	const u16 *pCtlMode;
+	u16 ctlMode, freq;
 	struct chan_centers centers;
 	struct cal_ctl_data_4k *rep;
 	struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k;
 	static const u16 tpScaleReductionTable[5] =
-		{ 0, 3, 6, 9, AR5416_MAX_RATE_POWER };
+		{ 0, 3, 6, 9, MAX_RATE_POWER };
 	struct cal_target_power_leg targetPowerOfdm, targetPowerCck = {
 		0, { 0, 0, 0, 0}
 	};
@@ -550,10 +381,10 @@ static void ath9k_hw_set_4k_power_per_ra
 	struct cal_target_power_ht targetPowerHt20, targetPowerHt40 = {
 		0, {0, 0, 0, 0}
 	};
-	u16 ctlModesFor11g[] =
-		{ CTL_11B, CTL_11G, CTL_2GHT20, CTL_11B_EXT, CTL_11G_EXT,
-		  CTL_2GHT40
-		};
+	static const u16 ctlModesFor11g[] = {
+		CTL_11B, CTL_11G, CTL_2GHT20,
+		CTL_11B_EXT, CTL_11G_EXT, CTL_2GHT40
+	};
 
 	ath9k_hw_get_channel_centers(ah, chan, &centers);
 
@@ -615,7 +446,7 @@ static void ath9k_hw_set_4k_power_per_ra
 
 		if (ah->eep_ops->get_eeprom_ver(ah) == 14 &&
 		    ah->eep_ops->get_eeprom_rev(ah) <= 2)
-			twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
+			twiceMaxEdgePower = MAX_RATE_POWER;
 
 		for (i = 0; (i < AR5416_EEP4K_NUM_CTLS) &&
 			     pEepData->ctlIndex[i]; i++) {
@@ -726,7 +557,7 @@ static void ath9k_hw_4k_set_txpower(stru
 				    u16 cfgCtl,
 				    u8 twiceAntennaReduction,
 				    u8 twiceMaxRegulatoryPower,
-				    u8 powerLimit)
+				    u8 powerLimit, bool test)
 {
 	struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
 	struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k;
@@ -751,15 +582,20 @@ static void ath9k_hw_4k_set_txpower(stru
 
 	ath9k_hw_set_4k_power_cal_table(ah, chan, &txPowerIndexOffset);
 
+	regulatory->max_power_level = 0;
 	for (i = 0; i < ARRAY_SIZE(ratesArray); i++) {
 		ratesArray[i] =	(int16_t)(txPowerIndexOffset + ratesArray[i]);
-		if (ratesArray[i] > AR5416_MAX_RATE_POWER)
-			ratesArray[i] = AR5416_MAX_RATE_POWER;
+		if (ratesArray[i] > MAX_RATE_POWER)
+			ratesArray[i] = MAX_RATE_POWER;
+
+		if (ratesArray[i] > regulatory->max_power_level)
+			regulatory->max_power_level = ratesArray[i];
 	}
 
+	if (test)
+	    return;
 
 	/* Update regulatory */
-
 	i = rate6mb;
 	if (IS_CHAN_HT40(chan))
 		i = rateHt40_0;
@@ -934,8 +770,7 @@ static void ath9k_hw_4k_set_board_values
 	pModal = &eep->modalHeader;
 	txRxAttenLocal = 23;
 
-	REG_WRITE(ah, AR_PHY_SWITCH_COM,
-		  ah->eep_ops->get_eeprom_antenna_cfg(ah, chan));
+	REG_WRITE(ah, AR_PHY_SWITCH_COM, pModal->antCtrlCommon);
 
 	/* Single chain for 4K EEPROM*/
 	ath9k_hw_4k_set_gain(ah, pModal, eep, txRxAttenLocal);
@@ -1151,21 +986,6 @@ static void ath9k_hw_4k_set_board_values
 	}
 }
 
-static u32 ath9k_hw_4k_get_eeprom_antenna_cfg(struct ath_hw *ah,
-					      struct ath9k_channel *chan)
-{
-	struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k;
-	struct modal_eep_4k_header *pModal = &eep->modalHeader;
-
-	return pModal->antCtrlCommon;
-}
-
-static u8 ath9k_hw_4k_get_num_ant_config(struct ath_hw *ah,
-					 enum ath9k_hal_freq_band freq_band)
-{
-	return 1;
-}
-
 static u16 ath9k_hw_4k_get_spur_channel(struct ath_hw *ah, u16 i, bool is2GHz)
 {
 #define EEP_MAP4K_SPURCHAN \
@@ -1174,17 +994,17 @@ static u16 ath9k_hw_4k_get_spur_channel(
 
 	u16 spur_val = AR_NO_SPUR;
 
-	ath_print(common, ATH_DBG_ANI,
-		  "Getting spur idx %d is2Ghz. %d val %x\n",
-		  i, is2GHz, ah->config.spurchans[i][is2GHz]);
+	ath_dbg(common, ATH_DBG_ANI,
+		"Getting spur idx:%d is2Ghz:%d val:%x\n",
+		i, is2GHz, ah->config.spurchans[i][is2GHz]);
 
 	switch (ah->config.spurmode) {
 	case SPUR_DISABLE:
 		break;
 	case SPUR_ENABLE_IOCTL:
 		spur_val = ah->config.spurchans[i][is2GHz];
-		ath_print(common, ATH_DBG_ANI,
-			  "Getting spur val from new loc. %d\n", spur_val);
+		ath_dbg(common, ATH_DBG_ANI,
+			"Getting spur val from new loc. %d\n", spur_val);
 		break;
 	case SPUR_ENABLE_EEPROM:
 		spur_val = EEP_MAP4K_SPURCHAN;
@@ -1202,8 +1022,6 @@ const struct eeprom_ops eep_4k_ops = {
 	.fill_eeprom		= ath9k_hw_4k_fill_eeprom,
 	.get_eeprom_ver		= ath9k_hw_4k_get_eeprom_ver,
 	.get_eeprom_rev		= ath9k_hw_4k_get_eeprom_rev,
-	.get_num_ant_config	= ath9k_hw_4k_get_num_ant_config,
-	.get_eeprom_antenna_cfg	= ath9k_hw_4k_get_eeprom_antenna_cfg,
 	.set_board_values	= ath9k_hw_4k_set_board_values,
 	.set_addac		= ath9k_hw_4k_set_addac,
 	.set_txpower		= ath9k_hw_4k_set_txpower,
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/eeprom_9287.c linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/eeprom_9287.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/eeprom_9287.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/eeprom_9287.c	2011-03-14 21:20:32.000000000 -0400
@@ -37,21 +37,21 @@ static bool ath9k_hw_ar9287_fill_eeprom(
 	int addr, eep_start_loc;
 	eep_data = (u16 *)eep;
 
-	if (AR9287_HTC_DEVID(ah))
+	if (common->bus_ops->ath_bus_type == ATH_USB)
 		eep_start_loc = AR9287_HTC_EEP_START_LOC;
 	else
 		eep_start_loc = AR9287_EEP_START_LOC;
 
 	if (!ath9k_hw_use_flash(ah)) {
-		ath_print(common, ATH_DBG_EEPROM,
-			  "Reading from EEPROM, not flash\n");
+		ath_dbg(common, ATH_DBG_EEPROM,
+			"Reading from EEPROM, not flash\n");
 	}
 
 	for (addr = 0; addr < NUM_EEP_WORDS; addr++) {
 		if (!ath9k_hw_nvram_read(common, addr + eep_start_loc,
 					 eep_data)) {
-			ath_print(common, ATH_DBG_EEPROM,
-				  "Unable to read eeprom region\n");
+			ath_dbg(common, ATH_DBG_EEPROM,
+				"Unable to read eeprom region\n");
 			return false;
 		}
 		eep_data++;
@@ -72,13 +72,12 @@ static int ath9k_hw_ar9287_check_eeprom(
 	if (!ath9k_hw_use_flash(ah)) {
 		if (!ath9k_hw_nvram_read(common, AR5416_EEPROM_MAGIC_OFFSET,
 					 &magic)) {
-			ath_print(common, ATH_DBG_FATAL,
-				  "Reading Magic # failed\n");
+			ath_err(common, "Reading Magic # failed\n");
 			return false;
 		}
 
-		ath_print(common, ATH_DBG_EEPROM,
-			  "Read Magic = 0x%04X\n", magic);
+		ath_dbg(common, ATH_DBG_EEPROM,
+			"Read Magic = 0x%04X\n", magic);
 
 		if (magic != AR5416_EEPROM_MAGIC) {
 			magic2 = swab16(magic);
@@ -93,16 +92,15 @@ static int ath9k_hw_ar9287_check_eeprom(
 					eepdata++;
 				}
 			} else {
-				ath_print(common, ATH_DBG_FATAL,
-					  "Invalid EEPROM Magic. "
-					  "Endianness mismatch.\n");
+				ath_err(common,
+					"Invalid EEPROM Magic. Endianness mismatch.\n");
 				return -EINVAL;
 			}
 		}
 	}
 
-	ath_print(common, ATH_DBG_EEPROM, "need_swap = %s.\n",
-		  need_swap ? "True" : "False");
+	ath_dbg(common, ATH_DBG_EEPROM, "need_swap = %s.\n",
+		need_swap ? "True" : "False");
 
 	if (need_swap)
 		el = swab16(ah->eeprom.map9287.baseEepHeader.length);
@@ -152,7 +150,7 @@ static int ath9k_hw_ar9287_check_eeprom(
 			eep->modalHeader.antCtrlChain[i] = integer;
 		}
 
-		for (i = 0; i < AR9287_EEPROM_MODAL_SPURS; i++) {
+		for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) {
 			word = swab16(eep->modalHeader.spurChans[i].spurChan);
 			eep->modalHeader.spurChans[i].spurChan = word;
 		}
@@ -160,9 +158,8 @@ static int ath9k_hw_ar9287_check_eeprom(
 
 	if (sum != 0xffff || ah->eep_ops->get_eeprom_ver(ah) != AR9287_EEP_VER
 	    || ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_NO_BACK_VER) {
-		ath_print(common, ATH_DBG_FATAL,
-			  "Bad EEPROM checksum 0x%x or revision 0x%04x\n",
-			   sum, ah->eep_ops->get_eeprom_ver(ah));
+		ath_err(common, "Bad EEPROM checksum 0x%x or revision 0x%04x\n",
+			sum, ah->eep_ops->get_eeprom_ver(ah));
 		return -EINVAL;
 	}
 
@@ -223,163 +220,6 @@ static u32 ath9k_hw_ar9287_get_eeprom(st
 	}
 }
 
-static void ath9k_hw_get_ar9287_gain_boundaries_pdadcs(struct ath_hw *ah,
-			       struct ath9k_channel *chan,
-			       struct cal_data_per_freq_ar9287 *pRawDataSet,
-			       u8 *bChans, u16 availPiers,
-			       u16 tPdGainOverlap,
-			       u16 *pPdGainBoundaries,
-			       u8 *pPDADCValues,
-			       u16 numXpdGains)
-{
-#define TMP_VAL_VPD_TABLE						\
-	((vpdTableI[i][sizeCurrVpdTable - 1] + (ss - maxIndex + 1) * vpdStep));
-
-	int i, j, k;
-	int16_t ss;
-	u16 idxL = 0, idxR = 0, numPiers;
-	u8 *pVpdL, *pVpdR, *pPwrL, *pPwrR;
-	u8 minPwrT4[AR9287_NUM_PD_GAINS];
-	u8 maxPwrT4[AR9287_NUM_PD_GAINS];
-	int16_t vpdStep;
-	int16_t tmpVal;
-	u16 sizeCurrVpdTable, maxIndex, tgtIndex;
-	bool match;
-	int16_t minDelta = 0;
-	struct chan_centers centers;
-	static u8 vpdTableL[AR5416_EEP4K_NUM_PD_GAINS]
-		[AR5416_MAX_PWR_RANGE_IN_HALF_DB];
-	static u8 vpdTableR[AR5416_EEP4K_NUM_PD_GAINS]
-		[AR5416_MAX_PWR_RANGE_IN_HALF_DB];
-	static u8 vpdTableI[AR5416_EEP4K_NUM_PD_GAINS]
-		[AR5416_MAX_PWR_RANGE_IN_HALF_DB];
-
-	memset(&minPwrT4, 0, AR9287_NUM_PD_GAINS);
-	ath9k_hw_get_channel_centers(ah, chan, &centers);
-
-	for (numPiers = 0; numPiers < availPiers; numPiers++) {
-		if (bChans[numPiers] == AR9287_BCHAN_UNUSED)
-			break;
-	}
-
-	match = ath9k_hw_get_lower_upper_index(
-		(u8)FREQ2FBIN(centers.synth_center, IS_CHAN_2GHZ(chan)),
-		bChans, numPiers, &idxL, &idxR);
-
-	if (match) {
-		for (i = 0; i < numXpdGains; i++) {
-			minPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][0];
-			maxPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][4];
-			ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
-						pRawDataSet[idxL].pwrPdg[i],
-						pRawDataSet[idxL].vpdPdg[i],
-						AR9287_PD_GAIN_ICEPTS,
-						vpdTableI[i]);
-		}
-	} else {
-		for (i = 0; i < numXpdGains; i++) {
-			pVpdL = pRawDataSet[idxL].vpdPdg[i];
-			pPwrL = pRawDataSet[idxL].pwrPdg[i];
-			pVpdR = pRawDataSet[idxR].vpdPdg[i];
-			pPwrR = pRawDataSet[idxR].pwrPdg[i];
-
-			minPwrT4[i] = max(pPwrL[0], pPwrR[0]);
-
-			maxPwrT4[i] = min(pPwrL[AR9287_PD_GAIN_ICEPTS - 1],
-					  pPwrR[AR9287_PD_GAIN_ICEPTS - 1]);
-
-			ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
-						pPwrL, pVpdL,
-						AR9287_PD_GAIN_ICEPTS,
-						vpdTableL[i]);
-			ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
-						pPwrR, pVpdR,
-						AR9287_PD_GAIN_ICEPTS,
-						vpdTableR[i]);
-
-			for (j = 0; j <= (maxPwrT4[i] - minPwrT4[i]) / 2; j++) {
-				vpdTableI[i][j] = (u8)(ath9k_hw_interpolate(
-				       (u16)FREQ2FBIN(centers. synth_center,
-						      IS_CHAN_2GHZ(chan)),
-				       bChans[idxL], bChans[idxR],
-				       vpdTableL[i][j], vpdTableR[i][j]));
-			}
-		}
-	}
-
-	k = 0;
-
-	for (i = 0; i < numXpdGains; i++) {
-		if (i == (numXpdGains - 1))
-			pPdGainBoundaries[i] =
-				(u16)(maxPwrT4[i] / 2);
-		else
-			pPdGainBoundaries[i] =
-				(u16)((maxPwrT4[i] + minPwrT4[i+1]) / 4);
-
-		pPdGainBoundaries[i] = min((u16)AR5416_MAX_RATE_POWER,
-					   pPdGainBoundaries[i]);
-
-
-		minDelta = 0;
-
-		if (i == 0) {
-			if (AR_SREV_9280_20_OR_LATER(ah))
-				ss = (int16_t)(0 - (minPwrT4[i] / 2));
-			else
-				ss = 0;
-		} else {
-			ss = (int16_t)((pPdGainBoundaries[i-1] -
-					(minPwrT4[i] / 2)) -
-				       tPdGainOverlap + 1 + minDelta);
-		}
-
-		vpdStep = (int16_t)(vpdTableI[i][1] - vpdTableI[i][0]);
-		vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep);
-
-		while ((ss < 0) && (k < (AR9287_NUM_PDADC_VALUES - 1)))	{
-			tmpVal = (int16_t)(vpdTableI[i][0] + ss * vpdStep);
-			pPDADCValues[k++] = (u8)((tmpVal < 0) ? 0 : tmpVal);
-			ss++;
-		}
-
-		sizeCurrVpdTable = (u8)((maxPwrT4[i] - minPwrT4[i]) / 2 + 1);
-		tgtIndex = (u8)(pPdGainBoundaries[i] +
-				tPdGainOverlap - (minPwrT4[i] / 2));
-		maxIndex = (tgtIndex < sizeCurrVpdTable) ?
-			    tgtIndex : sizeCurrVpdTable;
-
-		while ((ss < maxIndex) && (k < (AR9287_NUM_PDADC_VALUES - 1)))
-			pPDADCValues[k++] = vpdTableI[i][ss++];
-
-		vpdStep = (int16_t)(vpdTableI[i][sizeCurrVpdTable - 1] -
-				    vpdTableI[i][sizeCurrVpdTable - 2]);
-		vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep);
-
-		if (tgtIndex > maxIndex) {
-			while ((ss <= tgtIndex) &&
-				(k < (AR9287_NUM_PDADC_VALUES - 1))) {
-				tmpVal = (int16_t) TMP_VAL_VPD_TABLE;
-				pPDADCValues[k++] =
-					(u8)((tmpVal > 255) ? 255 : tmpVal);
-				ss++;
-			}
-		}
-	}
-
-	while (i < AR9287_PD_GAINS_IN_MASK) {
-		pPdGainBoundaries[i] = pPdGainBoundaries[i-1];
-		i++;
-	}
-
-	while (k < AR9287_NUM_PDADC_VALUES) {
-		pPDADCValues[k] = pPDADCValues[k-1];
-		k++;
-	}
-
-#undef TMP_VAL_VPD_TABLE
-}
-
 static void ar9287_eeprom_get_tx_gain_index(struct ath_hw *ah,
 			    struct ath9k_channel *chan,
 			    struct cal_data_op_loop_ar9287 *pRawDatasetOpLoop,
@@ -392,7 +232,7 @@ static void ar9287_eeprom_get_tx_gain_in
 	ath9k_hw_get_channel_centers(ah, chan, &centers);
 
 	for (numPiers = 0; numPiers < availPiers; numPiers++) {
-		if (pCalChans[numPiers] == AR9287_BCHAN_UNUSED)
+		if (pCalChans[numPiers] == AR5416_BCHAN_UNUSED)
 			break;
 	}
 
@@ -458,11 +298,11 @@ static void ath9k_hw_set_ar9287_power_ca
 	struct cal_data_op_loop_ar9287 *pRawDatasetOpenLoop;
 	u8 *pCalBChans = NULL;
 	u16 pdGainOverlap_t2;
-	u8 pdadcValues[AR9287_NUM_PDADC_VALUES];
-	u16 gainBoundaries[AR9287_PD_GAINS_IN_MASK];
+	u8 pdadcValues[AR5416_NUM_PDADC_VALUES];
+	u16 gainBoundaries[AR5416_PD_GAINS_IN_MASK];
 	u16 numPiers = 0, i, j;
 	u16 numXpdGain, xpdMask;
-	u16 xpdGainValues[AR9287_NUM_PD_GAINS] = {0, 0, 0, 0};
+	u16 xpdGainValues[AR5416_NUM_PD_GAINS] = {0, 0, 0, 0};
 	u32 reg32, regOffset, regChainOffset, regval;
 	int16_t modalIdx, diff = 0;
 	struct ar9287_eeprom *pEepData = &ah->eeprom.map9287;
@@ -490,12 +330,12 @@ static void ath9k_hw_set_ar9287_power_ca
 	numXpdGain = 0;
 
 	/* Calculate the value of xpdgains from the xpdGain Mask */
-	for (i = 1; i <= AR9287_PD_GAINS_IN_MASK; i++) {
-		if ((xpdMask >> (AR9287_PD_GAINS_IN_MASK - i)) & 1) {
-			if (numXpdGain >= AR9287_NUM_PD_GAINS)
+	for (i = 1; i <= AR5416_PD_GAINS_IN_MASK; i++) {
+		if ((xpdMask >> (AR5416_PD_GAINS_IN_MASK - i)) & 1) {
+			if (numXpdGain >= AR5416_NUM_PD_GAINS)
 				break;
 			xpdGainValues[numXpdGain] =
-				(u16)(AR9287_PD_GAINS_IN_MASK-i);
+				(u16)(AR5416_PD_GAINS_IN_MASK-i);
 			numXpdGain++;
 		}
 	}
@@ -528,7 +368,7 @@ static void ath9k_hw_set_ar9287_power_ca
 					(struct cal_data_per_freq_ar9287 *)
 					pEepData->calPierData2G[i];
 
-				ath9k_hw_get_ar9287_gain_boundaries_pdadcs(ah, chan,
+				ath9k_hw_get_gain_boundaries_pdadcs(ah, chan,
 							   pRawDataset,
 							   pCalBChans, numPiers,
 							   pdGainOverlap_t2,
@@ -564,13 +404,13 @@ static void ath9k_hw_set_ar9287_power_ca
 					     (int32_t)AR9287_PWR_TABLE_OFFSET_DB);
 				diff *= 2;
 
-				for (j = 0; j < ((u16)AR9287_NUM_PDADC_VALUES-diff); j++)
+				for (j = 0; j < ((u16)AR5416_NUM_PDADC_VALUES-diff); j++)
 					pdadcValues[j] = pdadcValues[j+diff];
 
-				for (j = (u16)(AR9287_NUM_PDADC_VALUES-diff);
-				     j < AR9287_NUM_PDADC_VALUES; j++)
+				for (j = (u16)(AR5416_NUM_PDADC_VALUES-diff);
+				     j < AR5416_NUM_PDADC_VALUES; j++)
 					pdadcValues[j] =
-					  pdadcValues[AR9287_NUM_PDADC_VALUES-diff];
+					  pdadcValues[AR5416_NUM_PDADC_VALUES-diff];
 			}
 
 			if (!ath9k_hw_ar9287_get_eeprom(ah, EEP_OL_PWRCTRL)) {
@@ -613,9 +453,9 @@ static void ath9k_hw_set_ar9287_power_pe
 #define REDUCE_SCALED_POWER_BY_THREE_CHAIN   10
 
 	struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
-	u16 twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
+	u16 twiceMaxEdgePower = MAX_RATE_POWER;
 	static const u16 tpScaleReductionTable[5] =
-		{ 0, 3, 6, 9, AR5416_MAX_RATE_POWER };
+		{ 0, 3, 6, 9, MAX_RATE_POWER };
 	int i;
 	int16_t twiceLargestAntenna;
 	struct cal_ctl_data_ar9287 *rep;
@@ -626,13 +466,13 @@ static void ath9k_hw_set_ar9287_power_pe
 	struct cal_target_power_ht targetPowerHt20,
 				    targetPowerHt40 = {0, {0, 0, 0, 0} };
 	u16 scaledPower = 0, minCtlPower, maxRegAllowedPower;
-	u16 ctlModesFor11g[] = {CTL_11B,
-				CTL_11G,
-				CTL_2GHT20,
-				CTL_11B_EXT,
-				CTL_11G_EXT,
-				CTL_2GHT40};
-	u16 numCtlModes = 0, *pCtlMode = NULL, ctlMode, freq;
+	static const u16 ctlModesFor11g[] = {
+		CTL_11B, CTL_11G, CTL_2GHT20,
+		CTL_11B_EXT, CTL_11G_EXT, CTL_2GHT40
+	};
+	u16 numCtlModes = 0;
+	const u16 *pCtlMode = NULL;
+	u16 ctlMode, freq;
 	struct chan_centers centers;
 	int tx_chainmask;
 	u16 twiceMinEdgePower;
@@ -853,7 +693,7 @@ static void ath9k_hw_ar9287_set_txpower(
 					struct ath9k_channel *chan, u16 cfgCtl,
 					u8 twiceAntennaReduction,
 					u8 twiceMaxRegulatoryPower,
-					u8 powerLimit)
+					u8 powerLimit, bool test)
 {
 	struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
 	struct ar9287_eeprom *pEepData = &ah->eeprom.map9287;
@@ -877,12 +717,26 @@ static void ath9k_hw_ar9287_set_txpower(
 
 	ath9k_hw_set_ar9287_power_cal_table(ah, chan, &txPowerIndexOffset);
 
+	regulatory->max_power_level = 0;
 	for (i = 0; i < ARRAY_SIZE(ratesArray); i++) {
 		ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]);
-		if (ratesArray[i] > AR9287_MAX_RATE_POWER)
-			ratesArray[i] = AR9287_MAX_RATE_POWER;
+		if (ratesArray[i] > MAX_RATE_POWER)
+			ratesArray[i] = MAX_RATE_POWER;
+
+		if (ratesArray[i] > regulatory->max_power_level)
+			regulatory->max_power_level = ratesArray[i];
 	}
 
+	if (test)
+		return;
+
+	if (IS_CHAN_2GHZ(chan))
+		i = rate1l;
+	else
+		i = rate6mb;
+
+	regulatory->max_power_level = ratesArray[i];
+
 	if (AR_SREV_9280_20_OR_LATER(ah)) {
 		for (i = 0; i < Ar5416RateSize; i++)
 			ratesArray[i] -= AR9287_PWR_TABLE_OFFSET_DB * 2;
@@ -971,17 +825,6 @@ static void ath9k_hw_ar9287_set_txpower(
 			  | ATH9K_POW_SM(ratesArray[rateDupOfdm], 8)
 			  | ATH9K_POW_SM(ratesArray[rateDupCck], 0));
 	}
-
-	if (IS_CHAN_2GHZ(chan))
-		i = rate1l;
-	else
-		i = rate6mb;
-
-	if (AR_SREV_9280_20_OR_LATER(ah))
-		regulatory->max_power_level =
-			ratesArray[i] + AR9287_PWR_TABLE_OFFSET_DB * 2;
-	else
-		regulatory->max_power_level = ratesArray[i];
 }
 
 static void ath9k_hw_ar9287_set_addac(struct ath_hw *ah,
@@ -1023,8 +866,7 @@ static void ath9k_hw_ar9287_set_board_va
 		antWrites[j++] = (u16)(pModal->antCtrlChain[i] & 0x3);
 	}
 
-	REG_WRITE(ah, AR_PHY_SWITCH_COM,
-		  ah->eep_ops->get_eeprom_antenna_cfg(ah, chan));
+	REG_WRITE(ah, AR_PHY_SWITCH_COM, pModal->antCtrlCommon);
 
 	for (i = 0; i < AR9287_MAX_CHAINS; i++)	{
 		regChainOffset = i * 0x1000;
@@ -1125,21 +967,6 @@ static void ath9k_hw_ar9287_set_board_va
 				  pModal->xpaBiasLvl);
 }
 
-static u8 ath9k_hw_ar9287_get_num_ant_config(struct ath_hw *ah,
-					     enum ath9k_hal_freq_band freq_band)
-{
-	return 1;
-}
-
-static u32 ath9k_hw_ar9287_get_eeprom_antenna_cfg(struct ath_hw *ah,
-						  struct ath9k_channel *chan)
-{
-	struct ar9287_eeprom *eep = &ah->eeprom.map9287;
-	struct modal_eep_ar9287_header *pModal = &eep->modalHeader;
-
-	return pModal->antCtrlCommon;
-}
-
 static u16 ath9k_hw_ar9287_get_spur_channel(struct ath_hw *ah,
 					    u16 i, bool is2GHz)
 {
@@ -1149,17 +976,17 @@ static u16 ath9k_hw_ar9287_get_spur_chan
 	struct ath_common *common = ath9k_hw_common(ah);
 	u16 spur_val = AR_NO_SPUR;
 
-	ath_print(common, ATH_DBG_ANI,
-		  "Getting spur idx %d is2Ghz. %d val %x\n",
-		  i, is2GHz, ah->config.spurchans[i][is2GHz]);
+	ath_dbg(common, ATH_DBG_ANI,
+		"Getting spur idx:%d is2Ghz:%d val:%x\n",
+		i, is2GHz, ah->config.spurchans[i][is2GHz]);
 
 	switch (ah->config.spurmode) {
 	case SPUR_DISABLE:
 		break;
 	case SPUR_ENABLE_IOCTL:
 		spur_val = ah->config.spurchans[i][is2GHz];
-		ath_print(common, ATH_DBG_ANI,
-			  "Getting spur val from new loc. %d\n", spur_val);
+		ath_dbg(common, ATH_DBG_ANI,
+			"Getting spur val from new loc. %d\n", spur_val);
 		break;
 	case SPUR_ENABLE_EEPROM:
 		spur_val = EEP_MAP9287_SPURCHAN;
@@ -1177,8 +1004,6 @@ const struct eeprom_ops eep_ar9287_ops =
 	.fill_eeprom		= ath9k_hw_ar9287_fill_eeprom,
 	.get_eeprom_ver		= ath9k_hw_ar9287_get_eeprom_ver,
 	.get_eeprom_rev		= ath9k_hw_ar9287_get_eeprom_rev,
-	.get_num_ant_config	= ath9k_hw_ar9287_get_num_ant_config,
-	.get_eeprom_antenna_cfg	= ath9k_hw_ar9287_get_eeprom_antenna_cfg,
 	.set_board_values	= ath9k_hw_ar9287_set_board_values,
 	.set_addac		= ath9k_hw_ar9287_set_addac,
 	.set_txpower		= ath9k_hw_ar9287_set_txpower,
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/eeprom.c linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/eeprom.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/eeprom.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/eeprom.c	2011-03-14 21:20:32.000000000 -0400
@@ -234,7 +234,7 @@ void ath9k_hw_get_target_powers(struct a
 u16 ath9k_hw_get_max_edge_power(u16 freq, struct cal_ctl_edges *pRdEdgesPower,
 				bool is2GHz, int num_band_edges)
 {
-	u16 twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
+	u16 twiceMaxEdgePower = MAX_RATE_POWER;
 	int i;
 
 	for (i = 0; (i < num_band_edges) &&
@@ -273,12 +273,225 @@ void ath9k_hw_update_regulatory_maxpower
 		regulatory->max_power_level += INCREASE_MAXPOW_BY_THREE_CHAIN;
 		break;
 	default:
-		ath_print(common, ATH_DBG_EEPROM,
-			  "Invalid chainmask configuration\n");
+		ath_dbg(common, ATH_DBG_EEPROM,
+			"Invalid chainmask configuration\n");
 		break;
 	}
 }
 
+void ath9k_hw_get_gain_boundaries_pdadcs(struct ath_hw *ah,
+				struct ath9k_channel *chan,
+				void *pRawDataSet,
+				u8 *bChans, u16 availPiers,
+				u16 tPdGainOverlap,
+				u16 *pPdGainBoundaries, u8 *pPDADCValues,
+				u16 numXpdGains)
+{
+	int i, j, k;
+	int16_t ss;
+	u16 idxL = 0, idxR = 0, numPiers;
+	static u8 vpdTableL[AR5416_NUM_PD_GAINS]
+		[AR5416_MAX_PWR_RANGE_IN_HALF_DB];
+	static u8 vpdTableR[AR5416_NUM_PD_GAINS]
+		[AR5416_MAX_PWR_RANGE_IN_HALF_DB];
+	static u8 vpdTableI[AR5416_NUM_PD_GAINS]
+		[AR5416_MAX_PWR_RANGE_IN_HALF_DB];
+
+	u8 *pVpdL, *pVpdR, *pPwrL, *pPwrR;
+	u8 minPwrT4[AR5416_NUM_PD_GAINS];
+	u8 maxPwrT4[AR5416_NUM_PD_GAINS];
+	int16_t vpdStep;
+	int16_t tmpVal;
+	u16 sizeCurrVpdTable, maxIndex, tgtIndex;
+	bool match;
+	int16_t minDelta = 0;
+	struct chan_centers centers;
+	int pdgain_boundary_default;
+	struct cal_data_per_freq *data_def = pRawDataSet;
+	struct cal_data_per_freq_4k *data_4k = pRawDataSet;
+	struct cal_data_per_freq_ar9287 *data_9287 = pRawDataSet;
+	bool eeprom_4k = AR_SREV_9285(ah) || AR_SREV_9271(ah);
+	int intercepts;
+
+	if (AR_SREV_9287(ah))
+		intercepts = AR9287_PD_GAIN_ICEPTS;
+	else
+		intercepts = AR5416_PD_GAIN_ICEPTS;
+
+	memset(&minPwrT4, 0, AR5416_NUM_PD_GAINS);
+	ath9k_hw_get_channel_centers(ah, chan, &centers);
+
+	for (numPiers = 0; numPiers < availPiers; numPiers++) {
+		if (bChans[numPiers] == AR5416_BCHAN_UNUSED)
+			break;
+	}
+
+	match = ath9k_hw_get_lower_upper_index((u8)FREQ2FBIN(centers.synth_center,
+							     IS_CHAN_2GHZ(chan)),
+					       bChans, numPiers, &idxL, &idxR);
+
+	if (match) {
+		if (AR_SREV_9287(ah)) {
+			/* FIXME: array overrun? */
+			for (i = 0; i < numXpdGains; i++) {
+				minPwrT4[i] = data_9287[idxL].pwrPdg[i][0];
+				maxPwrT4[i] = data_9287[idxL].pwrPdg[i][4];
+				ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
+						data_9287[idxL].pwrPdg[i],
+						data_9287[idxL].vpdPdg[i],
+						intercepts,
+						vpdTableI[i]);
+			}
+		} else if (eeprom_4k) {
+			for (i = 0; i < numXpdGains; i++) {
+				minPwrT4[i] = data_4k[idxL].pwrPdg[i][0];
+				maxPwrT4[i] = data_4k[idxL].pwrPdg[i][4];
+				ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
+						data_4k[idxL].pwrPdg[i],
+						data_4k[idxL].vpdPdg[i],
+						intercepts,
+						vpdTableI[i]);
+			}
+		} else {
+			for (i = 0; i < numXpdGains; i++) {
+				minPwrT4[i] = data_def[idxL].pwrPdg[i][0];
+				maxPwrT4[i] = data_def[idxL].pwrPdg[i][4];
+				ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
+						data_def[idxL].pwrPdg[i],
+						data_def[idxL].vpdPdg[i],
+						intercepts,
+						vpdTableI[i]);
+			}
+		}
+	} else {
+		for (i = 0; i < numXpdGains; i++) {
+			if (AR_SREV_9287(ah)) {
+				pVpdL = data_9287[idxL].vpdPdg[i];
+				pPwrL = data_9287[idxL].pwrPdg[i];
+				pVpdR = data_9287[idxR].vpdPdg[i];
+				pPwrR = data_9287[idxR].pwrPdg[i];
+			} else if (eeprom_4k) {
+				pVpdL = data_4k[idxL].vpdPdg[i];
+				pPwrL = data_4k[idxL].pwrPdg[i];
+				pVpdR = data_4k[idxR].vpdPdg[i];
+				pPwrR = data_4k[idxR].pwrPdg[i];
+			} else {
+				pVpdL = data_def[idxL].vpdPdg[i];
+				pPwrL = data_def[idxL].pwrPdg[i];
+				pVpdR = data_def[idxR].vpdPdg[i];
+				pPwrR = data_def[idxR].pwrPdg[i];
+			}
+
+			minPwrT4[i] = max(pPwrL[0], pPwrR[0]);
+
+			maxPwrT4[i] =
+				min(pPwrL[intercepts - 1],
+				    pPwrR[intercepts - 1]);
+
+
+			ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
+						pPwrL, pVpdL,
+						intercepts,
+						vpdTableL[i]);
+			ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
+						pPwrR, pVpdR,
+						intercepts,
+						vpdTableR[i]);
+
+			for (j = 0; j <= (maxPwrT4[i] - minPwrT4[i]) / 2; j++) {
+				vpdTableI[i][j] =
+					(u8)(ath9k_hw_interpolate((u16)
+					     FREQ2FBIN(centers.
+						       synth_center,
+						       IS_CHAN_2GHZ
+						       (chan)),
+					     bChans[idxL], bChans[idxR],
+					     vpdTableL[i][j], vpdTableR[i][j]));
+			}
+		}
+	}
+
+	k = 0;
+
+	for (i = 0; i < numXpdGains; i++) {
+		if (i == (numXpdGains - 1))
+			pPdGainBoundaries[i] =
+				(u16)(maxPwrT4[i] / 2);
+		else
+			pPdGainBoundaries[i] =
+				(u16)((maxPwrT4[i] + minPwrT4[i + 1]) / 4);
+
+		pPdGainBoundaries[i] =
+			min((u16)MAX_RATE_POWER, pPdGainBoundaries[i]);
+
+		if ((i == 0) && !AR_SREV_5416_20_OR_LATER(ah)) {
+			minDelta = pPdGainBoundaries[0] - 23;
+			pPdGainBoundaries[0] = 23;
+		} else {
+			minDelta = 0;
+		}
+
+		if (i == 0) {
+			if (AR_SREV_9280_20_OR_LATER(ah))
+				ss = (int16_t)(0 - (minPwrT4[i] / 2));
+			else
+				ss = 0;
+		} else {
+			ss = (int16_t)((pPdGainBoundaries[i - 1] -
+					(minPwrT4[i] / 2)) -
+				       tPdGainOverlap + 1 + minDelta);
+		}
+		vpdStep = (int16_t)(vpdTableI[i][1] - vpdTableI[i][0]);
+		vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep);
+
+		while ((ss < 0) && (k < (AR5416_NUM_PDADC_VALUES - 1))) {
+			tmpVal = (int16_t)(vpdTableI[i][0] + ss * vpdStep);
+			pPDADCValues[k++] = (u8)((tmpVal < 0) ? 0 : tmpVal);
+			ss++;
+		}
+
+		sizeCurrVpdTable = (u8) ((maxPwrT4[i] - minPwrT4[i]) / 2 + 1);
+		tgtIndex = (u8)(pPdGainBoundaries[i] + tPdGainOverlap -
+				(minPwrT4[i] / 2));
+		maxIndex = (tgtIndex < sizeCurrVpdTable) ?
+			tgtIndex : sizeCurrVpdTable;
+
+		while ((ss < maxIndex) && (k < (AR5416_NUM_PDADC_VALUES - 1))) {
+			pPDADCValues[k++] = vpdTableI[i][ss++];
+		}
+
+		vpdStep = (int16_t)(vpdTableI[i][sizeCurrVpdTable - 1] -
+				    vpdTableI[i][sizeCurrVpdTable - 2]);
+		vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep);
+
+		if (tgtIndex >= maxIndex) {
+			while ((ss <= tgtIndex) &&
+			       (k < (AR5416_NUM_PDADC_VALUES - 1))) {
+				tmpVal = (int16_t)((vpdTableI[i][sizeCurrVpdTable - 1] +
+						    (ss - maxIndex + 1) * vpdStep));
+				pPDADCValues[k++] = (u8)((tmpVal > 255) ?
+							 255 : tmpVal);
+				ss++;
+			}
+		}
+	}
+
+	if (eeprom_4k)
+		pdgain_boundary_default = 58;
+	else
+		pdgain_boundary_default = pPdGainBoundaries[i - 1];
+
+	while (i < AR5416_PD_GAINS_IN_MASK) {
+		pPdGainBoundaries[i] = pdgain_boundary_default;
+		i++;
+	}
+
+	while (k < AR5416_NUM_PDADC_VALUES) {
+		pPDADCValues[k] = pPDADCValues[k - 1];
+		k++;
+	}
+}
+
 int ath9k_hw_eeprom_init(struct ath_hw *ah)
 {
 	int status;
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/eeprom_def.c linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/eeprom_def.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/eeprom_def.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/eeprom_def.c	2011-03-14 21:20:32.000000000 -0400
@@ -96,8 +96,8 @@ static bool ath9k_hw_def_fill_eeprom(str
 	for (addr = 0; addr < SIZE_EEPROM_DEF; addr++) {
 		if (!ath9k_hw_nvram_read(common, addr + ar5416_eep_start_loc,
 					 eep_data)) {
-			ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL,
-				  "Unable to read eeprom region\n");
+			ath_err(ath9k_hw_common(ah),
+				"Unable to read eeprom region\n");
 			return false;
 		}
 		eep_data++;
@@ -117,13 +117,13 @@ static int ath9k_hw_def_check_eeprom(str
 	int i, addr, size;
 
 	if (!ath9k_hw_nvram_read(common, AR5416_EEPROM_MAGIC_OFFSET, &magic)) {
-		ath_print(common, ATH_DBG_FATAL, "Reading Magic # failed\n");
+		ath_err(common, "Reading Magic # failed\n");
 		return false;
 	}
 
 	if (!ath9k_hw_use_flash(ah)) {
-		ath_print(common, ATH_DBG_EEPROM,
-			  "Read Magic = 0x%04X\n", magic);
+		ath_dbg(common, ATH_DBG_EEPROM,
+			"Read Magic = 0x%04X\n", magic);
 
 		if (magic != AR5416_EEPROM_MAGIC) {
 			magic2 = swab16(magic);
@@ -139,16 +139,15 @@ static int ath9k_hw_def_check_eeprom(str
 					eepdata++;
 				}
 			} else {
-				ath_print(common, ATH_DBG_FATAL,
-					  "Invalid EEPROM Magic. "
-					  "Endianness mismatch.\n");
+				ath_err(common,
+					"Invalid EEPROM Magic. Endianness mismatch.\n");
 				return -EINVAL;
 			}
 		}
 	}
 
-	ath_print(common, ATH_DBG_EEPROM, "need_swap = %s.\n",
-		  need_swap ? "True" : "False");
+	ath_dbg(common, ATH_DBG_EEPROM, "need_swap = %s.\n",
+		need_swap ? "True" : "False");
 
 	if (need_swap)
 		el = swab16(ah->eeprom.def.baseEepHeader.length);
@@ -169,8 +168,8 @@ static int ath9k_hw_def_check_eeprom(str
 		u32 integer, j;
 		u16 word;
 
-		ath_print(common, ATH_DBG_EEPROM,
-			  "EEPROM Endianness is not native.. Changing.\n");
+		ath_dbg(common, ATH_DBG_EEPROM,
+			"EEPROM Endianness is not native.. Changing.\n");
 
 		word = swab16(eep->baseEepHeader.length);
 		eep->baseEepHeader.length = word;
@@ -207,7 +206,7 @@ static int ath9k_hw_def_check_eeprom(str
 				pModal->antCtrlChain[i] = integer;
 			}
 
-			for (i = 0; i < AR5416_EEPROM_MODAL_SPURS; i++) {
+			for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) {
 				word = swab16(pModal->spurChans[i].spurChan);
 				pModal->spurChans[i].spurChan = word;
 			}
@@ -216,8 +215,7 @@ static int ath9k_hw_def_check_eeprom(str
 
 	if (sum != 0xffff || ah->eep_ops->get_eeprom_ver(ah) != AR5416_EEP_VER ||
 	    ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_NO_BACK_VER) {
-		ath_print(common, ATH_DBG_FATAL,
-			  "Bad EEPROM checksum 0x%x or revision 0x%04x\n",
+		ath_err(common, "Bad EEPROM checksum 0x%x or revision 0x%04x\n",
 			sum, ah->eep_ops->get_eeprom_ver(ah));
 		return -EINVAL;
 	}
@@ -228,6 +226,10 @@ static int ath9k_hw_def_check_eeprom(str
 	    eep->baseEepHeader.pwdclkind == 0)
 		ah->need_an_top2_fixup = 1;
 
+	if ((common->bus_ops->ath_bus_type == ATH_USB) &&
+	    (AR_SREV_9280(ah)))
+		eep->modalHeader[0].xpaBiasLvl = 0;
+
 	return 0;
 }
 
@@ -376,8 +378,7 @@ static void ath9k_hw_def_set_board_value
 	pModal = &(eep->modalHeader[IS_CHAN_2GHZ(chan)]);
 	txRxAttenLocal = IS_CHAN_2GHZ(chan) ? 23 : 44;
 
-	REG_WRITE(ah, AR_PHY_SWITCH_COM,
-		  ah->eep_ops->get_eeprom_antenna_cfg(ah, chan));
+	REG_WRITE(ah, AR_PHY_SWITCH_COM, pModal->antCtrlCommon & 0xffff);
 
 	for (i = 0; i < AR5416_MAX_CHAINS; i++) {
 		if (AR_SREV_9280(ah)) {
@@ -590,168 +591,6 @@ static void ath9k_hw_def_set_addac(struc
 #undef XPA_LVL_FREQ
 }
 
-static void ath9k_hw_get_def_gain_boundaries_pdadcs(struct ath_hw *ah,
-				struct ath9k_channel *chan,
-				struct cal_data_per_freq *pRawDataSet,
-				u8 *bChans, u16 availPiers,
-				u16 tPdGainOverlap,
-				u16 *pPdGainBoundaries, u8 *pPDADCValues,
-				u16 numXpdGains)
-{
-	int i, j, k;
-	int16_t ss;
-	u16 idxL = 0, idxR = 0, numPiers;
-	static u8 vpdTableL[AR5416_NUM_PD_GAINS]
-		[AR5416_MAX_PWR_RANGE_IN_HALF_DB];
-	static u8 vpdTableR[AR5416_NUM_PD_GAINS]
-		[AR5416_MAX_PWR_RANGE_IN_HALF_DB];
-	static u8 vpdTableI[AR5416_NUM_PD_GAINS]
-		[AR5416_MAX_PWR_RANGE_IN_HALF_DB];
-
-	u8 *pVpdL, *pVpdR, *pPwrL, *pPwrR;
-	u8 minPwrT4[AR5416_NUM_PD_GAINS];
-	u8 maxPwrT4[AR5416_NUM_PD_GAINS];
-	int16_t vpdStep;
-	int16_t tmpVal;
-	u16 sizeCurrVpdTable, maxIndex, tgtIndex;
-	bool match;
-	int16_t minDelta = 0;
-	struct chan_centers centers;
-
-	memset(&minPwrT4, 0, AR9287_NUM_PD_GAINS);
-	ath9k_hw_get_channel_centers(ah, chan, &centers);
-
-	for (numPiers = 0; numPiers < availPiers; numPiers++) {
-		if (bChans[numPiers] == AR5416_BCHAN_UNUSED)
-			break;
-	}
-
-	match = ath9k_hw_get_lower_upper_index((u8)FREQ2FBIN(centers.synth_center,
-							     IS_CHAN_2GHZ(chan)),
-					       bChans, numPiers, &idxL, &idxR);
-
-	if (match) {
-		for (i = 0; i < numXpdGains; i++) {
-			minPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][0];
-			maxPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][4];
-			ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
-					pRawDataSet[idxL].pwrPdg[i],
-					pRawDataSet[idxL].vpdPdg[i],
-					AR5416_PD_GAIN_ICEPTS,
-					vpdTableI[i]);
-		}
-	} else {
-		for (i = 0; i < numXpdGains; i++) {
-			pVpdL = pRawDataSet[idxL].vpdPdg[i];
-			pPwrL = pRawDataSet[idxL].pwrPdg[i];
-			pVpdR = pRawDataSet[idxR].vpdPdg[i];
-			pPwrR = pRawDataSet[idxR].pwrPdg[i];
-
-			minPwrT4[i] = max(pPwrL[0], pPwrR[0]);
-
-			maxPwrT4[i] =
-				min(pPwrL[AR5416_PD_GAIN_ICEPTS - 1],
-				    pPwrR[AR5416_PD_GAIN_ICEPTS - 1]);
-
-
-			ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
-						pPwrL, pVpdL,
-						AR5416_PD_GAIN_ICEPTS,
-						vpdTableL[i]);
-			ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
-						pPwrR, pVpdR,
-						AR5416_PD_GAIN_ICEPTS,
-						vpdTableR[i]);
-
-			for (j = 0; j <= (maxPwrT4[i] - minPwrT4[i]) / 2; j++) {
-				vpdTableI[i][j] =
-					(u8)(ath9k_hw_interpolate((u16)
-					     FREQ2FBIN(centers.
-						       synth_center,
-						       IS_CHAN_2GHZ
-						       (chan)),
-					     bChans[idxL], bChans[idxR],
-					     vpdTableL[i][j], vpdTableR[i][j]));
-			}
-		}
-	}
-
-	k = 0;
-
-	for (i = 0; i < numXpdGains; i++) {
-		if (i == (numXpdGains - 1))
-			pPdGainBoundaries[i] =
-				(u16)(maxPwrT4[i] / 2);
-		else
-			pPdGainBoundaries[i] =
-				(u16)((maxPwrT4[i] + minPwrT4[i + 1]) / 4);
-
-		pPdGainBoundaries[i] =
-			min((u16)AR5416_MAX_RATE_POWER, pPdGainBoundaries[i]);
-
-		if ((i == 0) && !AR_SREV_5416_20_OR_LATER(ah)) {
-			minDelta = pPdGainBoundaries[0] - 23;
-			pPdGainBoundaries[0] = 23;
-		} else {
-			minDelta = 0;
-		}
-
-		if (i == 0) {
-			if (AR_SREV_9280_20_OR_LATER(ah))
-				ss = (int16_t)(0 - (minPwrT4[i] / 2));
-			else
-				ss = 0;
-		} else {
-			ss = (int16_t)((pPdGainBoundaries[i - 1] -
-					(minPwrT4[i] / 2)) -
-				       tPdGainOverlap + 1 + minDelta);
-		}
-		vpdStep = (int16_t)(vpdTableI[i][1] - vpdTableI[i][0]);
-		vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep);
-
-		while ((ss < 0) && (k < (AR5416_NUM_PDADC_VALUES - 1))) {
-			tmpVal = (int16_t)(vpdTableI[i][0] + ss * vpdStep);
-			pPDADCValues[k++] = (u8)((tmpVal < 0) ? 0 : tmpVal);
-			ss++;
-		}
-
-		sizeCurrVpdTable = (u8) ((maxPwrT4[i] - minPwrT4[i]) / 2 + 1);
-		tgtIndex = (u8)(pPdGainBoundaries[i] + tPdGainOverlap -
-				(minPwrT4[i] / 2));
-		maxIndex = (tgtIndex < sizeCurrVpdTable) ?
-			tgtIndex : sizeCurrVpdTable;
-
-		while ((ss < maxIndex) && (k < (AR5416_NUM_PDADC_VALUES - 1))) {
-			pPDADCValues[k++] = vpdTableI[i][ss++];
-		}
-
-		vpdStep = (int16_t)(vpdTableI[i][sizeCurrVpdTable - 1] -
-				    vpdTableI[i][sizeCurrVpdTable - 2]);
-		vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep);
-
-		if (tgtIndex >= maxIndex) {
-			while ((ss <= tgtIndex) &&
-			       (k < (AR5416_NUM_PDADC_VALUES - 1))) {
-				tmpVal = (int16_t)((vpdTableI[i][sizeCurrVpdTable - 1] +
-						    (ss - maxIndex + 1) * vpdStep));
-				pPDADCValues[k++] = (u8)((tmpVal > 255) ?
-							 255 : tmpVal);
-				ss++;
-			}
-		}
-	}
-
-	while (i < AR5416_PD_GAINS_IN_MASK) {
-		pPdGainBoundaries[i] = pPdGainBoundaries[i - 1];
-		i++;
-	}
-
-	while (k < AR5416_NUM_PDADC_VALUES) {
-		pPDADCValues[k] = pPDADCValues[k - 1];
-		k++;
-	}
-}
-
 static int16_t ath9k_change_gain_boundary_setting(struct ath_hw *ah,
 				u16 *gb,
 				u16 numXpdGain,
@@ -784,7 +623,7 @@ static int16_t ath9k_change_gain_boundar
 		/* Because of a hardware limitation, ensure the gain boundary
 		 * is not larger than (63 - overlap)
 		 */
-		gb_limit = (u16)(AR5416_MAX_RATE_POWER - pdGainOverlap_t2);
+		gb_limit = (u16)(MAX_RATE_POWER - pdGainOverlap_t2);
 
 		for (k = 0; k < numXpdGain; k++)
 			gb[k] = (u16)min(gb_limit, gb[k]);
@@ -918,7 +757,7 @@ static void ath9k_hw_set_def_power_cal_t
 				ath9k_olc_get_pdadcs(ah, pcdacIdx,
 						     txPower/2, pdadcValues);
 			} else {
-				ath9k_hw_get_def_gain_boundaries_pdadcs(ah,
+				ath9k_hw_get_gain_boundaries_pdadcs(ah,
 							chan, pRawDataset,
 							pCalBChans, numPiers,
 							pdGainOverlap_t2,
@@ -966,20 +805,19 @@ static void ath9k_hw_set_def_power_cal_t
 					((pdadcValues[4 * j + 3] & 0xFF) << 24);
 				REG_WRITE(ah, regOffset, reg32);
 
-				ath_print(common, ATH_DBG_EEPROM,
-					  "PDADC (%d,%4x): %4.4x %8.8x\n",
-					  i, regChainOffset, regOffset,
-					  reg32);
-				ath_print(common, ATH_DBG_EEPROM,
-					  "PDADC: Chain %d | PDADC %3d "
-					  "Value %3d | PDADC %3d Value %3d | "
-					  "PDADC %3d Value %3d | PDADC %3d "
-					  "Value %3d |\n",
-					  i, 4 * j, pdadcValues[4 * j],
-					  4 * j + 1, pdadcValues[4 * j + 1],
-					  4 * j + 2, pdadcValues[4 * j + 2],
-					  4 * j + 3,
-					  pdadcValues[4 * j + 3]);
+				ath_dbg(common, ATH_DBG_EEPROM,
+					"PDADC (%d,%4x): %4.4x %8.8x\n",
+					i, regChainOffset, regOffset,
+					reg32);
+				ath_dbg(common, ATH_DBG_EEPROM,
+					"PDADC: Chain %d | PDADC %3d "
+					"Value %3d | PDADC %3d Value %3d | "
+					"PDADC %3d Value %3d | PDADC %3d "
+					"Value %3d |\n",
+					i, 4 * j, pdadcValues[4 * j],
+					4 * j + 1, pdadcValues[4 * j + 1],
+					4 * j + 2, pdadcValues[4 * j + 2],
+					4 * j + 3, pdadcValues[4 * j + 3]);
 
 				regOffset += 4;
 			}
@@ -1004,9 +842,9 @@ static void ath9k_hw_set_def_power_per_r
 
 	struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
 	struct ar5416_eeprom_def *pEepData = &ah->eeprom.def;
-	u16 twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
+	u16 twiceMaxEdgePower = MAX_RATE_POWER;
 	static const u16 tpScaleReductionTable[5] =
-		{ 0, 3, 6, 9, AR5416_MAX_RATE_POWER };
+		{ 0, 3, 6, 9, MAX_RATE_POWER };
 
 	int i;
 	int16_t twiceLargestAntenna;
@@ -1022,13 +860,16 @@ static void ath9k_hw_set_def_power_per_r
 		0, {0, 0, 0, 0}
 	};
 	u16 scaledPower = 0, minCtlPower, maxRegAllowedPower;
-	u16 ctlModesFor11a[] =
-		{ CTL_11A, CTL_5GHT20, CTL_11A_EXT, CTL_5GHT40 };
-	u16 ctlModesFor11g[] =
-		{ CTL_11B, CTL_11G, CTL_2GHT20, CTL_11B_EXT, CTL_11G_EXT,
-		  CTL_2GHT40
-		};
-	u16 numCtlModes, *pCtlMode, ctlMode, freq;
+	static const u16 ctlModesFor11a[] = {
+		CTL_11A, CTL_5GHT20, CTL_11A_EXT, CTL_5GHT40
+	};
+	static const u16 ctlModesFor11g[] = {
+		CTL_11B, CTL_11G, CTL_2GHT20,
+		CTL_11B_EXT, CTL_11G_EXT, CTL_2GHT40
+	};
+	u16 numCtlModes;
+	const u16 *pCtlMode;
+	u16 ctlMode, freq;
 	struct chan_centers centers;
 	int tx_chainmask;
 	u16 twiceMinEdgePower;
@@ -1148,7 +989,7 @@ static void ath9k_hw_set_def_power_per_r
 
 		if (ah->eep_ops->get_eeprom_ver(ah) == 14 &&
 		    ah->eep_ops->get_eeprom_rev(ah) <= 2)
-			twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
+			twiceMaxEdgePower = MAX_RATE_POWER;
 
 		for (i = 0; (i < AR5416_NUM_CTLS) && pEepData->ctlIndex[i]; i++) {
 			if ((((cfgCtl & ~CTL_MODE_M) |
@@ -1263,7 +1104,7 @@ static void ath9k_hw_def_set_txpower(str
 				    u16 cfgCtl,
 				    u8 twiceAntennaReduction,
 				    u8 twiceMaxRegulatoryPower,
-				    u8 powerLimit)
+				    u8 powerLimit, bool test)
 {
 #define RT_AR_DELTA(x) (ratesArray[x] - cck_ofdm_delta)
 	struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
@@ -1290,12 +1131,44 @@ static void ath9k_hw_def_set_txpower(str
 
 	ath9k_hw_set_def_power_cal_table(ah, chan, &txPowerIndexOffset);
 
+	regulatory->max_power_level = 0;
 	for (i = 0; i < ARRAY_SIZE(ratesArray); i++) {
 		ratesArray[i] =	(int16_t)(txPowerIndexOffset + ratesArray[i]);
-		if (ratesArray[i] > AR5416_MAX_RATE_POWER)
-			ratesArray[i] = AR5416_MAX_RATE_POWER;
+		if (ratesArray[i] > MAX_RATE_POWER)
+			ratesArray[i] = MAX_RATE_POWER;
+		if (ratesArray[i] > regulatory->max_power_level)
+			regulatory->max_power_level = ratesArray[i];
+	}
+
+	if (!test) {
+		i = rate6mb;
+
+		if (IS_CHAN_HT40(chan))
+			i = rateHt40_0;
+		else if (IS_CHAN_HT20(chan))
+			i = rateHt20_0;
+
+		regulatory->max_power_level = ratesArray[i];
 	}
 
+	switch(ar5416_get_ntxchains(ah->txchainmask)) {
+	case 1:
+		break;
+	case 2:
+		regulatory->max_power_level += INCREASE_MAXPOW_BY_TWO_CHAIN;
+		break;
+	case 3:
+		regulatory->max_power_level += INCREASE_MAXPOW_BY_THREE_CHAIN;
+		break;
+	default:
+		ath_dbg(ath9k_hw_common(ah), ATH_DBG_EEPROM,
+			"Invalid chainmask configuration\n");
+		break;
+	}
+
+	if (test)
+		return;
+
 	if (AR_SREV_9280_20_OR_LATER(ah)) {
 		for (i = 0; i < Ar5416RateSize; i++) {
 			int8_t pwr_table_offset;
@@ -1392,62 +1265,6 @@ static void ath9k_hw_def_set_txpower(str
 	REG_WRITE(ah, AR_PHY_POWER_TX_SUB,
 		  ATH9K_POW_SM(pModal->pwrDecreaseFor3Chain, 6)
 		  | ATH9K_POW_SM(pModal->pwrDecreaseFor2Chain, 0));
-
-	i = rate6mb;
-
-	if (IS_CHAN_HT40(chan))
-		i = rateHt40_0;
-	else if (IS_CHAN_HT20(chan))
-		i = rateHt20_0;
-
-	if (AR_SREV_9280_20_OR_LATER(ah))
-		regulatory->max_power_level =
-			ratesArray[i] + AR5416_PWR_TABLE_OFFSET_DB * 2;
-	else
-		regulatory->max_power_level = ratesArray[i];
-
-	switch(ar5416_get_ntxchains(ah->txchainmask)) {
-	case 1:
-		break;
-	case 2:
-		regulatory->max_power_level += INCREASE_MAXPOW_BY_TWO_CHAIN;
-		break;
-	case 3:
-		regulatory->max_power_level += INCREASE_MAXPOW_BY_THREE_CHAIN;
-		break;
-	default:
-		ath_print(ath9k_hw_common(ah), ATH_DBG_EEPROM,
-			  "Invalid chainmask configuration\n");
-		break;
-	}
-}
-
-static u8 ath9k_hw_def_get_num_ant_config(struct ath_hw *ah,
-					  enum ath9k_hal_freq_band freq_band)
-{
-	struct ar5416_eeprom_def *eep = &ah->eeprom.def;
-	struct modal_eep_header *pModal =
-		&(eep->modalHeader[freq_band]);
-	struct base_eep_header *pBase = &eep->baseEepHeader;
-	u8 num_ant_config;
-
-	num_ant_config = 1;
-
-	if (pBase->version >= 0x0E0D &&
-	    (pModal->lna_ctl & LNA_CTL_USE_ANT1))
-		num_ant_config += 1;
-
-	return num_ant_config;
-}
-
-static u32 ath9k_hw_def_get_eeprom_antenna_cfg(struct ath_hw *ah,
-					       struct ath9k_channel *chan)
-{
-	struct ar5416_eeprom_def *eep = &ah->eeprom.def;
-	struct modal_eep_header *pModal =
-		&(eep->modalHeader[IS_CHAN_2GHZ(chan)]);
-
-	return pModal->antCtrlCommon;
 }
 
 static u16 ath9k_hw_def_get_spur_channel(struct ath_hw *ah, u16 i, bool is2GHz)
@@ -1458,17 +1275,17 @@ static u16 ath9k_hw_def_get_spur_channel
 
 	u16 spur_val = AR_NO_SPUR;
 
-	ath_print(common, ATH_DBG_ANI,
-		  "Getting spur idx %d is2Ghz. %d val %x\n",
-		  i, is2GHz, ah->config.spurchans[i][is2GHz]);
+	ath_dbg(common, ATH_DBG_ANI,
+		"Getting spur idx:%d is2Ghz:%d val:%x\n",
+		i, is2GHz, ah->config.spurchans[i][is2GHz]);
 
 	switch (ah->config.spurmode) {
 	case SPUR_DISABLE:
 		break;
 	case SPUR_ENABLE_IOCTL:
 		spur_val = ah->config.spurchans[i][is2GHz];
-		ath_print(common, ATH_DBG_ANI,
-			  "Getting spur val from new loc. %d\n", spur_val);
+		ath_dbg(common, ATH_DBG_ANI,
+			"Getting spur val from new loc. %d\n", spur_val);
 		break;
 	case SPUR_ENABLE_EEPROM:
 		spur_val = EEP_DEF_SPURCHAN;
@@ -1486,8 +1303,6 @@ const struct eeprom_ops eep_def_ops = {
 	.fill_eeprom		= ath9k_hw_def_fill_eeprom,
 	.get_eeprom_ver		= ath9k_hw_def_get_eeprom_ver,
 	.get_eeprom_rev		= ath9k_hw_def_get_eeprom_rev,
-	.get_num_ant_config	= ath9k_hw_def_get_num_ant_config,
-	.get_eeprom_antenna_cfg	= ath9k_hw_def_get_eeprom_antenna_cfg,
 	.set_board_values	= ath9k_hw_def_set_board_values,
 	.set_addac		= ath9k_hw_def_set_addac,
 	.set_txpower		= ath9k_hw_def_set_txpower,
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/eeprom.h linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/eeprom.h
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/eeprom.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/eeprom.h	2011-03-14 21:20:32.000000000 -0400
@@ -17,12 +17,12 @@
 #ifndef EEPROM_H
 #define EEPROM_H
 
+#define AR_EEPROM_MODAL_SPURS   5
+
 #include "../ath.h"
 #include <net/cfg80211.h>
 #include "ar9003_eeprom.h"
 
-#define AH_USE_EEPROM   0x1
-
 #ifdef __BIG_ENDIAN
 #define AR5416_EEPROM_MAGIC 0x5aa5
 #else
@@ -149,8 +149,6 @@
 #define AR5416_NUM_PD_GAINS             4
 #define AR5416_PD_GAINS_IN_MASK         4
 #define AR5416_PD_GAIN_ICEPTS           5
-#define AR5416_EEPROM_MODAL_SPURS       5
-#define AR5416_MAX_RATE_POWER           63
 #define AR5416_NUM_PDADC_VALUES         128
 #define AR5416_BCHAN_UNUSED             0xFF
 #define AR5416_MAX_PWR_RANGE_IN_HALF_DB 64
@@ -175,8 +173,6 @@
 #define AR5416_EEP4K_NUM_CTLS                 12
 #define AR5416_EEP4K_NUM_BAND_EDGES           4
 #define AR5416_EEP4K_NUM_PD_GAINS             2
-#define AR5416_EEP4K_PD_GAINS_IN_MASK         4
-#define AR5416_EEP4K_PD_GAIN_ICEPTS           5
 #define AR5416_EEP4K_MAX_CHAINS               1
 
 #define AR9280_TX_GAIN_TABLE_SIZE 22
@@ -198,35 +194,12 @@
 #define AR9287_NUM_2G_40_TARGET_POWERS  3
 #define AR9287_NUM_CTLS              	12
 #define AR9287_NUM_BAND_EDGES        	4
-#define AR9287_NUM_PD_GAINS             4
-#define AR9287_PD_GAINS_IN_MASK         4
 #define AR9287_PD_GAIN_ICEPTS           1
-#define AR9287_EEPROM_MODAL_SPURS       5
-#define AR9287_MAX_RATE_POWER           63
-#define AR9287_NUM_PDADC_VALUES         128
-#define AR9287_NUM_RATES                16
-#define AR9287_BCHAN_UNUSED             0xFF
-#define AR9287_MAX_PWR_RANGE_IN_HALF_DB 64
-#define AR9287_OPFLAGS_11A              0x01
-#define AR9287_OPFLAGS_11G              0x02
-#define AR9287_OPFLAGS_2G_HT40          0x08
-#define AR9287_OPFLAGS_2G_HT20          0x20
-#define AR9287_OPFLAGS_5G_HT40          0x04
-#define AR9287_OPFLAGS_5G_HT20          0x10
 #define AR9287_EEPMISC_BIG_ENDIAN       0x01
 #define AR9287_EEPMISC_WOW              0x02
 #define AR9287_MAX_CHAINS               2
 #define AR9287_ANT_16S                  32
-#define AR9287_custdatasize             20
 
-#define AR9287_NUM_ANT_CHAIN_FIELDS     6
-#define AR9287_NUM_ANT_COMMON_FIELDS    4
-#define AR9287_SIZE_ANT_CHAIN_FIELD     2
-#define AR9287_SIZE_ANT_COMMON_FIELD    4
-#define AR9287_ANT_CHAIN_MASK           0x3
-#define AR9287_ANT_COMMON_MASK          0xf
-#define AR9287_CHAIN_0_IDX              0
-#define AR9287_CHAIN_1_IDX              1
 #define AR9287_DATA_SZ                  32
 
 #define AR9287_PWR_TABLE_OFFSET_DB  -5
@@ -280,6 +253,7 @@ enum eeprom_param {
 	EEP_PAPRD,
 	EEP_MODAL_VER,
 	EEP_ANT_DIV_CTL1,
+	EEP_CHAIN_MASK_REDUCE
 };
 
 enum ar5416_rates {
@@ -395,7 +369,7 @@ struct modal_eep_header {
 	u16 xpaBiasLvlFreq[3];
 	u8 futureModal[6];
 
-	struct spur_chan spurChans[AR5416_EEPROM_MODAL_SPURS];
+	struct spur_chan spurChans[AR_EEPROM_MODAL_SPURS];
 } __packed;
 
 struct calDataPerFreqOpLoop {
@@ -463,7 +437,7 @@ struct modal_eep_4k_header {
 	u8 db2_4:4, reserved:4;
 #endif
 	u8 futureModal[4];
-	struct spur_chan spurChans[AR5416_EEPROM_MODAL_SPURS];
+	struct spur_chan spurChans[AR_EEPROM_MODAL_SPURS];
 } __packed;
 
 struct base_eep_ar9287_header {
@@ -521,7 +495,7 @@ struct modal_eep_ar9287_header {
 	u8 ob_qam;
 	u8 ob_pal_off;
 	u8 futureModal[30];
-	struct spur_chan spurChans[AR9287_EEPROM_MODAL_SPURS];
+	struct spur_chan spurChans[AR_EEPROM_MODAL_SPURS];
 } __packed;
 
 struct cal_data_per_freq {
@@ -530,8 +504,8 @@ struct cal_data_per_freq {
 } __packed;
 
 struct cal_data_per_freq_4k {
-	u8 pwrPdg[AR5416_EEP4K_NUM_PD_GAINS][AR5416_EEP4K_PD_GAIN_ICEPTS];
-	u8 vpdPdg[AR5416_EEP4K_NUM_PD_GAINS][AR5416_EEP4K_PD_GAIN_ICEPTS];
+	u8 pwrPdg[AR5416_EEP4K_NUM_PD_GAINS][AR5416_PD_GAIN_ICEPTS];
+	u8 vpdPdg[AR5416_EEP4K_NUM_PD_GAINS][AR5416_PD_GAIN_ICEPTS];
 } __packed;
 
 struct cal_target_power_leg {
@@ -557,8 +531,8 @@ struct cal_data_op_loop_ar9287 {
 } __packed;
 
 struct cal_data_per_freq_ar9287 {
-	u8 pwrPdg[AR9287_NUM_PD_GAINS][AR9287_PD_GAIN_ICEPTS];
-	u8 vpdPdg[AR9287_NUM_PD_GAINS][AR9287_PD_GAIN_ICEPTS];
+	u8 pwrPdg[AR5416_NUM_PD_GAINS][AR9287_PD_GAIN_ICEPTS];
+	u8 vpdPdg[AR5416_NUM_PD_GAINS][AR9287_PD_GAIN_ICEPTS];
 } __packed;
 
 union cal_data_per_freq_ar9287_u {
@@ -673,15 +647,12 @@ struct eeprom_ops {
 	bool (*fill_eeprom)(struct ath_hw *hw);
 	int (*get_eeprom_ver)(struct ath_hw *hw);
 	int (*get_eeprom_rev)(struct ath_hw *hw);
-	u8 (*get_num_ant_config)(struct ath_hw *hw,
-				 enum ath9k_hal_freq_band band);
-	u32 (*get_eeprom_antenna_cfg)(struct ath_hw *hw,
-				      struct ath9k_channel *chan);
 	void (*set_board_values)(struct ath_hw *hw, struct ath9k_channel *chan);
 	void (*set_addac)(struct ath_hw *hw, struct ath9k_channel *chan);
 	void (*set_txpower)(struct ath_hw *hw, struct ath9k_channel *chan,
 			   u16 cfgCtl, u8 twiceAntennaReduction,
-			   u8 twiceMaxRegulatoryPower, u8 powerLimit);
+			   u8 twiceMaxRegulatoryPower, u8 powerLimit,
+			   bool test);
 	u16 (*get_spur_channel)(struct ath_hw *ah, u16 i, bool is2GHz);
 };
 
@@ -714,6 +685,14 @@ u16 ath9k_hw_get_max_edge_power(u16 freq
 void ath9k_hw_update_regulatory_maxpower(struct ath_hw *ah);
 int ath9k_hw_eeprom_init(struct ath_hw *ah);
 
+void ath9k_hw_get_gain_boundaries_pdadcs(struct ath_hw *ah,
+				struct ath9k_channel *chan,
+				void *pRawDataSet,
+				u8 *bChans, u16 availPiers,
+				u16 tPdGainOverlap,
+				u16 *pPdGainBoundaries, u8 *pPDADCValues,
+				u16 numXpdGains);
+
 #define ar5416_get_ntxchains(_txchainmask)			\
 	(((_txchainmask >> 2) & 1) +                            \
 	 ((_txchainmask >> 1) & 1) + (_txchainmask & 1))
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/gpio.c linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/gpio.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/gpio.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/gpio.c	2011-03-14 21:20:32.000000000 -0400
@@ -103,8 +103,8 @@ static int ath_register_led(struct ath_s
 
 	ret = led_classdev_register(wiphy_dev(sc->hw->wiphy), &led->led_cdev);
 	if (ret)
-		ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL,
-			  "Failed to register led:%s", led->name);
+		ath_err(ath9k_hw_common(sc->sc_ah),
+			"Failed to register led:%s", led->name);
 	else
 		led->registered = 1;
 	return ret;
@@ -236,13 +236,13 @@ static void ath_detect_bt_priority(struc
 		sc->sc_flags &= ~(SC_OP_BT_PRIORITY_DETECTED | SC_OP_BT_SCAN);
 		/* Detect if colocated bt started scanning */
 		if (btcoex->bt_priority_cnt >= ATH_BT_CNT_SCAN_THRESHOLD) {
-			ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_BTCOEX,
-				  "BT scan detected");
+			ath_dbg(ath9k_hw_common(sc->sc_ah), ATH_DBG_BTCOEX,
+				"BT scan detected\n");
 			sc->sc_flags |= (SC_OP_BT_SCAN |
 					 SC_OP_BT_PRIORITY_DETECTED);
 		} else if (btcoex->bt_priority_cnt >= ATH_BT_CNT_THRESHOLD) {
-			ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_BTCOEX,
-				  "BT priority traffic detected");
+			ath_dbg(ath9k_hw_common(sc->sc_ah), ATH_DBG_BTCOEX,
+				"BT priority traffic detected\n");
 			sc->sc_flags |= SC_OP_BT_PRIORITY_DETECTED;
 		}
 
@@ -259,7 +259,7 @@ static void ath9k_gen_timer_start(struct
 	ath9k_hw_gen_timer_start(ah, timer, timer_next, timer_period);
 
 	if ((ah->imask & ATH9K_INT_GENTIMER) == 0) {
-		ath9k_hw_set_interrupts(ah, 0);
+		ath9k_hw_disable_interrupts(ah);
 		ah->imask |= ATH9K_INT_GENTIMER;
 		ath9k_hw_set_interrupts(ah, ah->imask);
 	}
@@ -273,7 +273,7 @@ static void ath9k_gen_timer_stop(struct
 
 	/* if no timer is enabled, turn off interrupt mask */
 	if (timer_table->timer_mask.val == 0) {
-		ath9k_hw_set_interrupts(ah, 0);
+		ath9k_hw_disable_interrupts(ah);
 		ah->imask &= ~ATH9K_INT_GENTIMER;
 		ath9k_hw_set_interrupts(ah, ah->imask);
 	}
@@ -310,10 +310,8 @@ static void ath_btcoex_period_timer(unsi
 
 		timer_period = is_btscan ? btcoex->btscan_no_stomp :
 					   btcoex->btcoex_no_stomp;
-		ath9k_gen_timer_start(ah,
-				      btcoex->no_stomp_timer,
-				      (ath9k_hw_gettsf32(ah) +
-				       timer_period), timer_period * 10);
+		ath9k_gen_timer_start(ah, btcoex->no_stomp_timer, 0,
+				      timer_period * 10);
 		btcoex->hw_timer_enabled = true;
 	}
 
@@ -333,8 +331,8 @@ static void ath_btcoex_no_stomp_timer(vo
 	struct ath_common *common = ath9k_hw_common(ah);
 	bool is_btscan = sc->sc_flags & SC_OP_BT_SCAN;
 
-	ath_print(common, ATH_DBG_BTCOEX,
-		  "no stomp timer running\n");
+	ath_dbg(common, ATH_DBG_BTCOEX,
+		"no stomp timer running\n");
 
 	spin_lock_bh(&btcoex->btcoex_lock);
 
@@ -380,8 +378,8 @@ void ath9k_btcoex_timer_resume(struct at
 	struct ath_btcoex *btcoex = &sc->btcoex;
 	struct ath_hw *ah = sc->sc_ah;
 
-	ath_print(ath9k_hw_common(ah), ATH_DBG_BTCOEX,
-		  "Starting btcoex timers");
+	ath_dbg(ath9k_hw_common(ah), ATH_DBG_BTCOEX,
+		"Starting btcoex timers\n");
 
 	/* make sure duty cycle timer is also stopped when resuming */
 	if (btcoex->hw_timer_enabled)
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/hif_usb.c linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/hif_usb.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/hif_usb.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/hif_usb.c	2011-03-14 21:20:32.000000000 -0400
@@ -28,10 +28,7 @@ MODULE_FIRMWARE(FIRMWARE_AR9271);
 static struct usb_device_id ath9k_hif_usb_ids[] = {
 	{ USB_DEVICE(0x0cf3, 0x9271) }, /* Atheros */
 	{ USB_DEVICE(0x0cf3, 0x1006) }, /* Atheros */
-	{ USB_DEVICE(0x0cf3, 0x7010) }, /* Atheros */
-	{ USB_DEVICE(0x0cf3, 0x7015) }, /* Atheros */
 	{ USB_DEVICE(0x0846, 0x9030) }, /* Netgear N150 */
-	{ USB_DEVICE(0x0846, 0x9018) }, /* Netgear WNDA3200 */
 	{ USB_DEVICE(0x07D1, 0x3A10) }, /* Dlink Wireless 150 */
 	{ USB_DEVICE(0x13D3, 0x3327) }, /* Azurewave */
 	{ USB_DEVICE(0x13D3, 0x3328) }, /* Azurewave */
@@ -40,9 +37,21 @@ static struct usb_device_id ath9k_hif_us
 	{ USB_DEVICE(0x13D3, 0x3349) }, /* Azurewave */
 	{ USB_DEVICE(0x13D3, 0x3350) }, /* Azurewave */
 	{ USB_DEVICE(0x04CA, 0x4605) }, /* Liteon */
-	{ USB_DEVICE(0x083A, 0xA704) }, /* SMC Networks */
 	{ USB_DEVICE(0x040D, 0x3801) }, /* VIA */
-	{ USB_DEVICE(0x1668, 0x1200) }, /* Verizon */
+	{ USB_DEVICE(0x0cf3, 0xb003) }, /* Ubiquiti WifiStation Ext */
+
+	{ USB_DEVICE(0x0cf3, 0x7015),
+	  .driver_info = AR9287_USB },  /* Atheros */
+	{ USB_DEVICE(0x1668, 0x1200),
+	  .driver_info = AR9287_USB },  /* Verizon */
+
+	{ USB_DEVICE(0x0cf3, 0x7010),
+	  .driver_info = AR9280_USB },  /* Atheros */
+	{ USB_DEVICE(0x0846, 0x9018),
+	  .driver_info = AR9280_USB },  /* Netgear WNDA3200 */
+	{ USB_DEVICE(0x083A, 0xA704),
+	  .driver_info = AR9280_USB },  /* SMC Networks */
+
 	{ },
 };
 
@@ -144,16 +153,36 @@ static void hif_usb_tx_cb(struct urb *ur
 	case -ENODEV:
 	case -ESHUTDOWN:
 		/*
-		 * The URB has been killed, free the SKBs
-		 * and return.
+		 * The URB has been killed, free the SKBs.
 		 */
 		ath9k_skb_queue_purge(hif_dev, &tx_buf->skb_queue);
-		return;
+
+		/*
+		 * If the URBs are being flushed, no need to add this
+		 * URB to the free list.
+		 */
+		spin_lock(&hif_dev->tx.tx_lock);
+		if (hif_dev->tx.flags & HIF_USB_TX_FLUSH) {
+			spin_unlock(&hif_dev->tx.tx_lock);
+			return;
+		}
+		spin_unlock(&hif_dev->tx.tx_lock);
+
+		/*
+		 * In the stop() case, this URB has to be added to
+		 * the free list.
+		 */
+		goto add_free;
 	default:
 		break;
 	}
 
-	/* Check if TX has been stopped */
+	/*
+	 * Check if TX has been stopped, this is needed because
+	 * this CB could have been invoked just after the TX lock
+	 * was released in hif_stop() and kill_urb() hasn't been
+	 * called yet.
+	 */
 	spin_lock(&hif_dev->tx.tx_lock);
 	if (hif_dev->tx.flags & HIF_USB_TX_STOP) {
 		spin_unlock(&hif_dev->tx.tx_lock);
@@ -190,8 +219,9 @@ static int __hif_usb_tx(struct hif_devic
 	struct tx_buf *tx_buf = NULL;
 	struct sk_buff *nskb = NULL;
 	int ret = 0, i;
-	u16 *hdr, tx_skb_cnt = 0;
+	u16 tx_skb_cnt = 0;
 	u8 *buf;
+	__le16 *hdr;
 
 	if (hif_dev->tx.tx_skb_cnt == 0)
 		return 0;
@@ -216,9 +246,9 @@ static int __hif_usb_tx(struct hif_devic
 
 		buf = tx_buf->buf;
 		buf += tx_buf->offset;
-		hdr = (u16 *)buf;
-		*hdr++ = nskb->len;
-		*hdr++ = ATH_USB_TX_STREAM_MODE_TAG;
+		hdr = (__le16 *)buf;
+		*hdr++ = cpu_to_le16(nskb->len);
+		*hdr++ = cpu_to_le16(ATH_USB_TX_STREAM_MODE_TAG);
 		buf += 4;
 		memcpy(buf, nskb->data, nskb->len);
 		tx_buf->len = nskb->len + 4;
@@ -305,6 +335,7 @@ static void hif_usb_start(void *hif_hand
 static void hif_usb_stop(void *hif_handle, u8 pipe_id)
 {
 	struct hif_device_usb *hif_dev = (struct hif_device_usb *)hif_handle;
+	struct tx_buf *tx_buf = NULL, *tx_buf_tmp = NULL;
 	unsigned long flags;
 
 	spin_lock_irqsave(&hif_dev->tx.tx_lock, flags);
@@ -312,6 +343,12 @@ static void hif_usb_stop(void *hif_handl
 	hif_dev->tx.tx_skb_cnt = 0;
 	hif_dev->tx.flags |= HIF_USB_TX_STOP;
 	spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags);
+
+	/* The pending URBs have to be canceled. */
+	list_for_each_entry_safe(tx_buf, tx_buf_tmp,
+				 &hif_dev->tx.tx_pending, list) {
+		usb_kill_urb(tx_buf->urb);
+	}
 }
 
 static int hif_usb_send(void *hif_handle, u8 pipe_id, struct sk_buff *skb,
@@ -353,9 +390,9 @@ static void ath9k_hif_usb_rx_stream(stru
 				    struct sk_buff *skb)
 {
 	struct sk_buff *nskb, *skb_pool[MAX_PKT_NUM_IN_TRANSFER];
-	int index = 0, i = 0, chk_idx, len = skb->len;
-	int rx_remain_len = 0, rx_pkt_len = 0;
-	u16 pkt_len, pkt_tag, pool_index = 0;
+	int index = 0, i = 0, len = skb->len;
+	int rx_remain_len, rx_pkt_len;
+	u16 pool_index = 0;
 	u8 *ptr;
 
 	spin_lock(&hif_dev->rx_lock);
@@ -389,64 +426,64 @@ static void ath9k_hif_usb_rx_stream(stru
 	spin_unlock(&hif_dev->rx_lock);
 
 	while (index < len) {
+		u16 pkt_len;
+		u16 pkt_tag;
+		u16 pad_len;
+		int chk_idx;
+
 		ptr = (u8 *) skb->data;
 
 		pkt_len = ptr[index] + (ptr[index+1] << 8);
 		pkt_tag = ptr[index+2] + (ptr[index+3] << 8);
 
-		if (pkt_tag == ATH_USB_RX_STREAM_MODE_TAG) {
-			u16 pad_len;
-
-			pad_len = 4 - (pkt_len & 0x3);
-			if (pad_len == 4)
-				pad_len = 0;
-
-			chk_idx = index;
-			index = index + 4 + pkt_len + pad_len;
+		if (pkt_tag != ATH_USB_RX_STREAM_MODE_TAG) {
+			RX_STAT_INC(skb_dropped);
+			return;
+		}
 
-			if (index > MAX_RX_BUF_SIZE) {
-				spin_lock(&hif_dev->rx_lock);
-				hif_dev->rx_remain_len = index - MAX_RX_BUF_SIZE;
-				hif_dev->rx_transfer_len =
-					MAX_RX_BUF_SIZE - chk_idx - 4;
-				hif_dev->rx_pad_len = pad_len;
+		pad_len = 4 - (pkt_len & 0x3);
+		if (pad_len == 4)
+			pad_len = 0;
 
-				nskb = __dev_alloc_skb(pkt_len + 32,
-						       GFP_ATOMIC);
-				if (!nskb) {
-					dev_err(&hif_dev->udev->dev,
-					"ath9k_htc: RX memory allocation"
-					" error\n");
-					spin_unlock(&hif_dev->rx_lock);
-					goto err;
-				}
-				skb_reserve(nskb, 32);
-				RX_STAT_INC(skb_allocated);
+		chk_idx = index;
+		index = index + 4 + pkt_len + pad_len;
 
-				memcpy(nskb->data, &(skb->data[chk_idx+4]),
-				       hif_dev->rx_transfer_len);
+		if (index > MAX_RX_BUF_SIZE) {
+			spin_lock(&hif_dev->rx_lock);
+			hif_dev->rx_remain_len = index - MAX_RX_BUF_SIZE;
+			hif_dev->rx_transfer_len =
+				MAX_RX_BUF_SIZE - chk_idx - 4;
+			hif_dev->rx_pad_len = pad_len;
 
-				/* Record the buffer pointer */
-				hif_dev->remain_skb = nskb;
+			nskb = __dev_alloc_skb(pkt_len + 32, GFP_ATOMIC);
+			if (!nskb) {
+				dev_err(&hif_dev->udev->dev,
+					"ath9k_htc: RX memory allocation error\n");
 				spin_unlock(&hif_dev->rx_lock);
-			} else {
-				nskb = __dev_alloc_skb(pkt_len + 32, GFP_ATOMIC);
-				if (!nskb) {
-					dev_err(&hif_dev->udev->dev,
-					"ath9k_htc: RX memory allocation"
-					" error\n");
-					goto err;
-				}
-				skb_reserve(nskb, 32);
-				RX_STAT_INC(skb_allocated);
-
-				memcpy(nskb->data, &(skb->data[chk_idx+4]), pkt_len);
-				skb_put(nskb, pkt_len);
-				skb_pool[pool_index++] = nskb;
+				goto err;
 			}
+			skb_reserve(nskb, 32);
+			RX_STAT_INC(skb_allocated);
+
+			memcpy(nskb->data, &(skb->data[chk_idx+4]),
+			       hif_dev->rx_transfer_len);
+
+			/* Record the buffer pointer */
+			hif_dev->remain_skb = nskb;
+			spin_unlock(&hif_dev->rx_lock);
 		} else {
-			RX_STAT_INC(skb_dropped);
-			return;
+			nskb = __dev_alloc_skb(pkt_len + 32, GFP_ATOMIC);
+			if (!nskb) {
+				dev_err(&hif_dev->udev->dev,
+					"ath9k_htc: RX memory allocation error\n");
+				goto err;
+			}
+			skb_reserve(nskb, 32);
+			RX_STAT_INC(skb_allocated);
+
+			memcpy(nskb->data, &(skb->data[chk_idx+4]), pkt_len);
+			skb_put(nskb, pkt_len);
+			skb_pool[pool_index++] = nskb;
 		}
 	}
 
@@ -461,7 +498,7 @@ err:
 static void ath9k_hif_usb_rx_cb(struct urb *urb)
 {
 	struct sk_buff *skb = (struct sk_buff *) urb->context;
-	struct hif_device_usb *hif_dev = (struct hif_device_usb *)
+	struct hif_device_usb *hif_dev =
 		usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0));
 	int ret;
 
@@ -508,7 +545,7 @@ static void ath9k_hif_usb_reg_in_cb(stru
 {
 	struct sk_buff *skb = (struct sk_buff *) urb->context;
 	struct sk_buff *nskb;
-	struct hif_device_usb *hif_dev = (struct hif_device_usb *)
+	struct hif_device_usb *hif_dev =
 		usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0));
 	int ret;
 
@@ -578,6 +615,7 @@ free:
 static void ath9k_hif_usb_dealloc_tx_urbs(struct hif_device_usb *hif_dev)
 {
 	struct tx_buf *tx_buf = NULL, *tx_buf_tmp = NULL;
+	unsigned long flags;
 
 	list_for_each_entry_safe(tx_buf, tx_buf_tmp,
 				 &hif_dev->tx.tx_buf, list) {
@@ -588,6 +626,10 @@ static void ath9k_hif_usb_dealloc_tx_urb
 		kfree(tx_buf);
 	}
 
+	spin_lock_irqsave(&hif_dev->tx.tx_lock, flags);
+	hif_dev->tx.flags |= HIF_USB_TX_FLUSH;
+	spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags);
+
 	list_for_each_entry_safe(tx_buf, tx_buf_tmp,
 				 &hif_dev->tx.tx_pending, list) {
 		usb_kill_urb(tx_buf->urb);
@@ -776,7 +818,8 @@ static void ath9k_hif_usb_dealloc_urbs(s
 	ath9k_hif_usb_dealloc_rx_urbs(hif_dev);
 }
 
-static int ath9k_hif_usb_download_fw(struct hif_device_usb *hif_dev)
+static int ath9k_hif_usb_download_fw(struct hif_device_usb *hif_dev,
+				     u32 drv_info)
 {
 	int transfer, err;
 	const void *data = hif_dev->firmware->data;
@@ -807,18 +850,10 @@ static int ath9k_hif_usb_download_fw(str
 	}
 	kfree(buf);
 
-	switch (hif_dev->device_id) {
-	case 0x7010:
-	case 0x7015:
-	case 0x9018:
-	case 0xA704:
-	case 0x1200:
+	if (IS_AR7010_DEVICE(drv_info))
 		firm_offset = AR7010_FIRMWARE_TEXT;
-		break;
-	default:
+	else
 		firm_offset = AR9271_FIRMWARE_TEXT;
-		break;
-	}
 
 	/*
 	 * Issue FW download complete command to firmware.
@@ -836,7 +871,7 @@ static int ath9k_hif_usb_download_fw(str
 	return 0;
 }
 
-static int ath9k_hif_usb_dev_init(struct hif_device_usb *hif_dev)
+static int ath9k_hif_usb_dev_init(struct hif_device_usb *hif_dev, u32 drv_info)
 {
 	int ret, idx;
 	struct usb_host_interface *alt = &hif_dev->interface->altsetting[0];
@@ -852,7 +887,7 @@ static int ath9k_hif_usb_dev_init(struct
 	}
 
 	/* Download firmware */
-	ret = ath9k_hif_usb_download_fw(hif_dev);
+	ret = ath9k_hif_usb_download_fw(hif_dev, drv_info);
 	if (ret) {
 		dev_err(&hif_dev->udev->dev,
 			"ath9k_htc: Firmware - %s download failed\n",
@@ -884,9 +919,9 @@ static int ath9k_hif_usb_dev_init(struct
 
 	return 0;
 
-err_fw_download:
-	ath9k_hif_usb_dealloc_urbs(hif_dev);
 err_urb:
+	ath9k_hif_usb_dealloc_urbs(hif_dev);
+err_fw_download:
 	release_firmware(hif_dev->firmware);
 err_fw_req:
 	hif_dev->firmware = NULL;
@@ -931,23 +966,15 @@ static int ath9k_hif_usb_probe(struct us
 
 	/* Find out which firmware to load */
 
-	switch(hif_dev->device_id) {
-	case 0x7010:
-	case 0x7015:
-	case 0x9018:
-	case 0xA704:
-	case 0x1200:
+	if (IS_AR7010_DEVICE(id->driver_info))
 		if (le16_to_cpu(udev->descriptor.bcdDevice) == 0x0202)
 			hif_dev->fw_name = FIRMWARE_AR7010_1_1;
 		else
 			hif_dev->fw_name = FIRMWARE_AR7010;
-		break;
-	default:
+	else
 		hif_dev->fw_name = FIRMWARE_AR9271;
-		break;
-	}
 
-	ret = ath9k_hif_usb_dev_init(hif_dev);
+	ret = ath9k_hif_usb_dev_init(hif_dev, id->driver_info);
 	if (ret) {
 		ret = -EINVAL;
 		goto err_hif_init_usb;
@@ -955,7 +982,7 @@ static int ath9k_hif_usb_probe(struct us
 
 	ret = ath9k_htc_hw_init(hif_dev->htc_handle,
 				&hif_dev->udev->dev, hif_dev->device_id,
-				hif_dev->udev->product);
+				hif_dev->udev->product, id->driver_info);
 	if (ret) {
 		ret = -EINVAL;
 		goto err_htc_hw_init;
@@ -998,18 +1025,17 @@ static void ath9k_hif_usb_reboot(struct
 static void ath9k_hif_usb_disconnect(struct usb_interface *interface)
 {
 	struct usb_device *udev = interface_to_usbdev(interface);
-	struct hif_device_usb *hif_dev =
-		(struct hif_device_usb *) usb_get_intfdata(interface);
+	struct hif_device_usb *hif_dev = usb_get_intfdata(interface);
+	bool unplugged = (udev->state == USB_STATE_NOTATTACHED) ? true : false;
 
 	if (hif_dev) {
-		ath9k_htc_hw_deinit(hif_dev->htc_handle,
-		    (udev->state == USB_STATE_NOTATTACHED) ? true : false);
+		ath9k_htc_hw_deinit(hif_dev->htc_handle, unplugged);
 		ath9k_htc_hw_free(hif_dev->htc_handle);
 		ath9k_hif_usb_dev_deinit(hif_dev);
 		usb_set_intfdata(interface, NULL);
 	}
 
-	if (hif_dev->flags & HIF_USB_START)
+	if (!unplugged && (hif_dev->flags & HIF_USB_START))
 		ath9k_hif_usb_reboot(udev);
 
 	kfree(hif_dev);
@@ -1021,8 +1047,7 @@ static void ath9k_hif_usb_disconnect(str
 static int ath9k_hif_usb_suspend(struct usb_interface *interface,
 				 pm_message_t message)
 {
-	struct hif_device_usb *hif_dev =
-		(struct hif_device_usb *) usb_get_intfdata(interface);
+	struct hif_device_usb *hif_dev = usb_get_intfdata(interface);
 
 	/*
 	 * The device has to be set to FULLSLEEP mode in case no
@@ -1038,8 +1063,8 @@ static int ath9k_hif_usb_suspend(struct
 
 static int ath9k_hif_usb_resume(struct usb_interface *interface)
 {
-	struct hif_device_usb *hif_dev =
-		(struct hif_device_usb *) usb_get_intfdata(interface);
+	struct hif_device_usb *hif_dev = usb_get_intfdata(interface);
+	struct htc_target *htc_handle = hif_dev->htc_handle;
 	int ret;
 
 	ret = ath9k_hif_usb_alloc_urbs(hif_dev);
@@ -1047,7 +1072,8 @@ static int ath9k_hif_usb_resume(struct u
 		return ret;
 
 	if (hif_dev->firmware) {
-		ret = ath9k_hif_usb_download_fw(hif_dev);
+		ret = ath9k_hif_usb_download_fw(hif_dev,
+				htc_handle->drv_priv->ah->hw_version.usbdev);
 		if (ret)
 			goto fail_resume;
 	} else {
@@ -1057,7 +1083,7 @@ static int ath9k_hif_usb_resume(struct u
 
 	mdelay(100);
 
-	ret = ath9k_htc_resume(hif_dev->htc_handle);
+	ret = ath9k_htc_resume(htc_handle);
 
 	if (ret)
 		goto fail_resume;
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/hif_usb.h linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/hif_usb.h
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/hif_usb.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/hif_usb.h	2011-03-14 21:20:32.000000000 -0400
@@ -17,6 +17,8 @@
 #ifndef HTC_USB_H
 #define HTC_USB_H
 
+#define IS_AR7010_DEVICE(_v) (((_v) == AR9280_USB) || ((_v) == AR9287_USB))
+
 #define AR9271_FIRMWARE       0x501000
 #define AR9271_FIRMWARE_TEXT  0x903000
 #define AR7010_FIRMWARE_TEXT  0x906000
@@ -62,6 +64,7 @@ struct tx_buf {
 };
 
 #define HIF_USB_TX_STOP  BIT(0)
+#define HIF_USB_TX_FLUSH BIT(1)
 
 struct hif_usb_tx {
 	u8 flags;
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c	2011-03-14 21:20:32.000000000 -0400
@@ -123,11 +123,11 @@ static void ath9k_htc_beacon_config_sta(
 	/* TSF out of range threshold fixed at 1 second */
 	bs.bs_tsfoor_threshold = ATH9K_TSFOOR_THRESHOLD;
 
-	ath_print(common, ATH_DBG_BEACON, "tsf: %llu tsftu: %u\n", tsf, tsftu);
-	ath_print(common, ATH_DBG_BEACON,
-		  "bmiss: %u sleep: %u cfp-period: %u maxdur: %u next: %u\n",
-		  bs.bs_bmissthreshold, bs.bs_sleepduration,
-		  bs.bs_cfpperiod, bs.bs_cfpmaxduration, bs.bs_cfpnext);
+	ath_dbg(common, ATH_DBG_BEACON, "tsf: %llu tsftu: %u\n", tsf, tsftu);
+	ath_dbg(common, ATH_DBG_BEACON,
+		"bmiss: %u sleep: %u cfp-period: %u maxdur: %u next: %u\n",
+		bs.bs_bmissthreshold, bs.bs_sleepduration,
+		bs.bs_cfpperiod, bs.bs_cfpmaxduration, bs.bs_cfpnext);
 
 	/* Set the computed STA beacon timers */
 
@@ -154,9 +154,9 @@ static void ath9k_htc_beacon_config_adho
 	if (priv->op_flags & OP_ENABLE_BEACON)
 		imask |= ATH9K_INT_SWBA;
 
-	ath_print(common, ATH_DBG_BEACON,
-		  "IBSS Beacon config, intval: %d, imask: 0x%x\n",
-		  bss_conf->beacon_interval, imask);
+	ath_dbg(common, ATH_DBG_BEACON,
+		"IBSS Beacon config, intval: %d, imask: 0x%x\n",
+		bss_conf->beacon_interval, imask);
 
 	WMI_CMD(WMI_DISABLE_INTR_CMDID);
 	ath9k_hw_beaconinit(priv->ah, nexttbtt, intval);
@@ -246,8 +246,8 @@ void ath9k_htc_beaconq_config(struct ath
 	qi.tqi_cwmax = qi_be.tqi_cwmax;
 
 	if (!ath9k_hw_set_txq_props(ah, priv->beaconq, &qi)) {
-		ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL,
-			  "Unable to update beacon queue %u!\n", qnum);
+		ath_err(ath9k_hw_common(ah),
+			"Unable to update beacon queue %u!\n", qnum);
 	} else {
 		ath9k_hw_resettxqueue(ah, priv->beaconq);
 	}
@@ -278,8 +278,8 @@ void ath9k_htc_beacon_config(struct ath9
 		ath9k_htc_beacon_config_adhoc(priv, cur_conf);
 		break;
 	default:
-		ath_print(common, ATH_DBG_CONFIG,
-			  "Unsupported beaconing mode\n");
+		ath_dbg(common, ATH_DBG_CONFIG,
+			"Unsupported beaconing mode\n");
 		return;
 	}
 }
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c	2011-03-14 21:20:32.000000000 -0400
@@ -1,3 +1,19 @@
+/*
+ * Copyright (c) 2010 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
 #include "htc.h"
 
 /******************/
@@ -20,13 +36,13 @@ static void ath_detect_bt_priority(struc
 		priv->op_flags &= ~(OP_BT_PRIORITY_DETECTED | OP_BT_SCAN);
 		/* Detect if colocated bt started scanning */
 		if (btcoex->bt_priority_cnt >= ATH_BT_CNT_SCAN_THRESHOLD) {
-			ath_print(ath9k_hw_common(ah), ATH_DBG_BTCOEX,
-				  "BT scan detected");
+			ath_dbg(ath9k_hw_common(ah), ATH_DBG_BTCOEX,
+				"BT scan detected\n");
 			priv->op_flags |= (OP_BT_SCAN |
 					 OP_BT_PRIORITY_DETECTED);
 		} else if (btcoex->bt_priority_cnt >= ATH_BT_CNT_THRESHOLD) {
-			ath_print(ath9k_hw_common(ah), ATH_DBG_BTCOEX,
-				    "BT priority traffic detected");
+			ath_dbg(ath9k_hw_common(ah), ATH_DBG_BTCOEX,
+				"BT priority traffic detected\n");
 			priv->op_flags |= OP_BT_PRIORITY_DETECTED;
 		}
 
@@ -83,8 +99,8 @@ static void ath_btcoex_duty_cycle_work(s
 	struct ath_common *common = ath9k_hw_common(ah);
 	bool is_btscan = priv->op_flags & OP_BT_SCAN;
 
-	ath_print(common, ATH_DBG_BTCOEX,
-		  "time slice work for bt and wlan\n");
+	ath_dbg(common, ATH_DBG_BTCOEX,
+		"time slice work for bt and wlan\n");
 
 	if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_LOW || is_btscan)
 		ath9k_cmn_btcoex_bt_stomp(common, ATH_BTCOEX_STOMP_NONE);
@@ -114,8 +130,7 @@ void ath_htc_resume_btcoex_work(struct a
 	struct ath_btcoex *btcoex = &priv->btcoex;
 	struct ath_hw *ah = priv->ah;
 
-	ath_print(ath9k_hw_common(ah), ATH_DBG_BTCOEX,
-		  "Starting btcoex work");
+	ath_dbg(ath9k_hw_common(ah), ATH_DBG_BTCOEX, "Starting btcoex work\n");
 
 	btcoex->bt_priority_cnt = 0;
 	btcoex->bt_priority_time = jiffies;
@@ -132,3 +147,314 @@ void ath_htc_cancel_btcoex_work(struct a
 	cancel_delayed_work_sync(&priv->coex_period_work);
 	cancel_delayed_work_sync(&priv->duty_cycle_work);
 }
+
+/*******/
+/* LED */
+/*******/
+
+static void ath9k_led_blink_work(struct work_struct *work)
+{
+	struct ath9k_htc_priv *priv = container_of(work, struct ath9k_htc_priv,
+						   ath9k_led_blink_work.work);
+
+	if (!(priv->op_flags & OP_LED_ASSOCIATED))
+		return;
+
+	if ((priv->led_on_duration == ATH_LED_ON_DURATION_IDLE) ||
+	    (priv->led_off_duration == ATH_LED_OFF_DURATION_IDLE))
+		ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin, 0);
+	else
+		ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin,
+				  (priv->op_flags & OP_LED_ON) ? 1 : 0);
+
+	ieee80211_queue_delayed_work(priv->hw,
+				     &priv->ath9k_led_blink_work,
+				     (priv->op_flags & OP_LED_ON) ?
+				     msecs_to_jiffies(priv->led_off_duration) :
+				     msecs_to_jiffies(priv->led_on_duration));
+
+	priv->led_on_duration = priv->led_on_cnt ?
+		max((ATH_LED_ON_DURATION_IDLE - priv->led_on_cnt), 25) :
+		ATH_LED_ON_DURATION_IDLE;
+	priv->led_off_duration = priv->led_off_cnt ?
+		max((ATH_LED_OFF_DURATION_IDLE - priv->led_off_cnt), 10) :
+		ATH_LED_OFF_DURATION_IDLE;
+	priv->led_on_cnt = priv->led_off_cnt = 0;
+
+	if (priv->op_flags & OP_LED_ON)
+		priv->op_flags &= ~OP_LED_ON;
+	else
+		priv->op_flags |= OP_LED_ON;
+}
+
+static void ath9k_led_brightness_work(struct work_struct *work)
+{
+	struct ath_led *led = container_of(work, struct ath_led,
+					   brightness_work.work);
+	struct ath9k_htc_priv *priv = led->priv;
+
+	switch (led->brightness) {
+	case LED_OFF:
+		if (led->led_type == ATH_LED_ASSOC ||
+		    led->led_type == ATH_LED_RADIO) {
+			ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin,
+					  (led->led_type == ATH_LED_RADIO));
+			priv->op_flags &= ~OP_LED_ASSOCIATED;
+			if (led->led_type == ATH_LED_RADIO)
+				priv->op_flags &= ~OP_LED_ON;
+		} else {
+			priv->led_off_cnt++;
+		}
+		break;
+	case LED_FULL:
+		if (led->led_type == ATH_LED_ASSOC) {
+			priv->op_flags |= OP_LED_ASSOCIATED;
+			ieee80211_queue_delayed_work(priv->hw,
+					     &priv->ath9k_led_blink_work, 0);
+		} else if (led->led_type == ATH_LED_RADIO) {
+			ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin, 0);
+			priv->op_flags |= OP_LED_ON;
+		} else {
+			priv->led_on_cnt++;
+		}
+		break;
+	default:
+		break;
+	}
+}
+
+static void ath9k_led_brightness(struct led_classdev *led_cdev,
+				 enum led_brightness brightness)
+{
+	struct ath_led *led = container_of(led_cdev, struct ath_led, led_cdev);
+	struct ath9k_htc_priv *priv = led->priv;
+
+	led->brightness = brightness;
+	if (!(priv->op_flags & OP_LED_DEINIT))
+		ieee80211_queue_delayed_work(priv->hw,
+					     &led->brightness_work, 0);
+}
+
+void ath9k_led_stop_brightness(struct ath9k_htc_priv *priv)
+{
+	cancel_delayed_work_sync(&priv->radio_led.brightness_work);
+	cancel_delayed_work_sync(&priv->assoc_led.brightness_work);
+	cancel_delayed_work_sync(&priv->tx_led.brightness_work);
+	cancel_delayed_work_sync(&priv->rx_led.brightness_work);
+}
+
+static int ath9k_register_led(struct ath9k_htc_priv *priv, struct ath_led *led,
+			      char *trigger)
+{
+	int ret;
+
+	led->priv = priv;
+	led->led_cdev.name = led->name;
+	led->led_cdev.default_trigger = trigger;
+	led->led_cdev.brightness_set = ath9k_led_brightness;
+
+	ret = led_classdev_register(wiphy_dev(priv->hw->wiphy), &led->led_cdev);
+	if (ret)
+		ath_err(ath9k_hw_common(priv->ah),
+			"Failed to register led:%s", led->name);
+	else
+		led->registered = 1;
+
+	INIT_DELAYED_WORK(&led->brightness_work, ath9k_led_brightness_work);
+
+	return ret;
+}
+
+static void ath9k_unregister_led(struct ath_led *led)
+{
+	if (led->registered) {
+		led_classdev_unregister(&led->led_cdev);
+		led->registered = 0;
+	}
+}
+
+void ath9k_deinit_leds(struct ath9k_htc_priv *priv)
+{
+	priv->op_flags |= OP_LED_DEINIT;
+	ath9k_unregister_led(&priv->assoc_led);
+	priv->op_flags &= ~OP_LED_ASSOCIATED;
+	ath9k_unregister_led(&priv->tx_led);
+	ath9k_unregister_led(&priv->rx_led);
+	ath9k_unregister_led(&priv->radio_led);
+}
+
+void ath9k_init_leds(struct ath9k_htc_priv *priv)
+{
+	char *trigger;
+	int ret;
+
+	if (AR_SREV_9287(priv->ah))
+		priv->ah->led_pin = ATH_LED_PIN_9287;
+	else if (AR_SREV_9271(priv->ah))
+		priv->ah->led_pin = ATH_LED_PIN_9271;
+	else if (AR_DEVID_7010(priv->ah))
+		priv->ah->led_pin = ATH_LED_PIN_7010;
+	else
+		priv->ah->led_pin = ATH_LED_PIN_DEF;
+
+	/* Configure gpio 1 for output */
+	ath9k_hw_cfg_output(priv->ah, priv->ah->led_pin,
+			    AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
+	/* LED off, active low */
+	ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin, 1);
+
+	INIT_DELAYED_WORK(&priv->ath9k_led_blink_work, ath9k_led_blink_work);
+
+	trigger = ieee80211_get_radio_led_name(priv->hw);
+	snprintf(priv->radio_led.name, sizeof(priv->radio_led.name),
+		"ath9k-%s::radio", wiphy_name(priv->hw->wiphy));
+	ret = ath9k_register_led(priv, &priv->radio_led, trigger);
+	priv->radio_led.led_type = ATH_LED_RADIO;
+	if (ret)
+		goto fail;
+
+	trigger = ieee80211_get_assoc_led_name(priv->hw);
+	snprintf(priv->assoc_led.name, sizeof(priv->assoc_led.name),
+		"ath9k-%s::assoc", wiphy_name(priv->hw->wiphy));
+	ret = ath9k_register_led(priv, &priv->assoc_led, trigger);
+	priv->assoc_led.led_type = ATH_LED_ASSOC;
+	if (ret)
+		goto fail;
+
+	trigger = ieee80211_get_tx_led_name(priv->hw);
+	snprintf(priv->tx_led.name, sizeof(priv->tx_led.name),
+		"ath9k-%s::tx", wiphy_name(priv->hw->wiphy));
+	ret = ath9k_register_led(priv, &priv->tx_led, trigger);
+	priv->tx_led.led_type = ATH_LED_TX;
+	if (ret)
+		goto fail;
+
+	trigger = ieee80211_get_rx_led_name(priv->hw);
+	snprintf(priv->rx_led.name, sizeof(priv->rx_led.name),
+		"ath9k-%s::rx", wiphy_name(priv->hw->wiphy));
+	ret = ath9k_register_led(priv, &priv->rx_led, trigger);
+	priv->rx_led.led_type = ATH_LED_RX;
+	if (ret)
+		goto fail;
+
+	priv->op_flags &= ~OP_LED_DEINIT;
+
+	return;
+
+fail:
+	cancel_delayed_work_sync(&priv->ath9k_led_blink_work);
+	ath9k_deinit_leds(priv);
+}
+
+/*******************/
+/*	Rfkill	   */
+/*******************/
+
+static bool ath_is_rfkill_set(struct ath9k_htc_priv *priv)
+{
+	return ath9k_hw_gpio_get(priv->ah, priv->ah->rfkill_gpio) ==
+		priv->ah->rfkill_polarity;
+}
+
+void ath9k_htc_rfkill_poll_state(struct ieee80211_hw *hw)
+{
+	struct ath9k_htc_priv *priv = hw->priv;
+	bool blocked = !!ath_is_rfkill_set(priv);
+
+	wiphy_rfkill_set_hw_state(hw->wiphy, blocked);
+}
+
+void ath9k_start_rfkill_poll(struct ath9k_htc_priv *priv)
+{
+	if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT)
+		wiphy_rfkill_start_polling(priv->hw->wiphy);
+}
+
+void ath9k_htc_radio_enable(struct ieee80211_hw *hw)
+{
+	struct ath9k_htc_priv *priv = hw->priv;
+	struct ath_hw *ah = priv->ah;
+	struct ath_common *common = ath9k_hw_common(ah);
+	int ret;
+	u8 cmd_rsp;
+
+	if (!ah->curchan)
+		ah->curchan = ath9k_cmn_get_curchannel(hw, ah);
+
+	/* Reset the HW */
+	ret = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false);
+	if (ret) {
+		ath_err(common,
+			"Unable to reset hardware; reset status %d (freq %u MHz)\n",
+			ret, ah->curchan->channel);
+	}
+
+	ath_update_txpow(priv);
+
+	/* Start RX */
+	WMI_CMD(WMI_START_RECV_CMDID);
+	ath9k_host_rx_init(priv);
+
+	/* Start TX */
+	htc_start(priv->htc);
+	spin_lock_bh(&priv->tx_lock);
+	priv->tx_queues_stop = false;
+	spin_unlock_bh(&priv->tx_lock);
+	ieee80211_wake_queues(hw);
+
+	WMI_CMD(WMI_ENABLE_INTR_CMDID);
+
+	/* Enable LED */
+	ath9k_hw_cfg_output(ah, ah->led_pin,
+			    AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
+	ath9k_hw_set_gpio(ah, ah->led_pin, 0);
+}
+
+void ath9k_htc_radio_disable(struct ieee80211_hw *hw)
+{
+	struct ath9k_htc_priv *priv = hw->priv;
+	struct ath_hw *ah = priv->ah;
+	struct ath_common *common = ath9k_hw_common(ah);
+	int ret;
+	u8 cmd_rsp;
+
+	ath9k_htc_ps_wakeup(priv);
+
+	/* Disable LED */
+	ath9k_hw_set_gpio(ah, ah->led_pin, 1);
+	ath9k_hw_cfg_gpio_input(ah, ah->led_pin);
+
+	WMI_CMD(WMI_DISABLE_INTR_CMDID);
+
+	/* Stop TX */
+	ieee80211_stop_queues(hw);
+	htc_stop(priv->htc);
+	WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID);
+	skb_queue_purge(&priv->tx_queue);
+
+	/* Stop RX */
+	WMI_CMD(WMI_STOP_RECV_CMDID);
+
+	/*
+	 * The MIB counters have to be disabled here,
+	 * since the target doesn't do it.
+	 */
+	ath9k_hw_disable_mib_counters(ah);
+
+	if (!ah->curchan)
+		ah->curchan = ath9k_cmn_get_curchannel(hw, ah);
+
+	/* Reset the HW */
+	ret = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false);
+	if (ret) {
+		ath_err(common,
+			"Unable to reset hardware; reset status %d (freq %u MHz)\n",
+			ret, ah->curchan->channel);
+	}
+
+	/* Disable the PHY */
+	ath9k_hw_phy_disable(ah);
+
+	ath9k_htc_ps_restore(priv);
+	ath9k_htc_setpower(priv, ATH9K_PM_FULL_SLEEP);
+}
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/htc_drv_init.c linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/htc_drv_init.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/htc_drv_init.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/htc_drv_init.c	2011-03-14 21:20:32.000000000 -0400
@@ -142,9 +142,6 @@ static void ath9k_deinit_priv(struct ath
 {
 	ath9k_htc_exit_debug(priv->ah);
 	ath9k_hw_deinit(priv->ah);
-	tasklet_kill(&priv->wmi_tasklet);
-	tasklet_kill(&priv->rx_tasklet);
-	tasklet_kill(&priv->tx_tasklet);
 	kfree(priv->ah);
 	priv->ah = NULL;
 }
@@ -181,7 +178,8 @@ static inline int ath9k_htc_connect_svc(
 	return htc_connect_service(priv->htc, &req, ep_id);
 }
 
-static int ath9k_init_htc_services(struct ath9k_htc_priv *priv, u16 devid)
+static int ath9k_init_htc_services(struct ath9k_htc_priv *priv, u16 devid,
+				   u32 drv_info)
 {
 	int ret;
 
@@ -245,17 +243,10 @@ static int ath9k_init_htc_services(struc
 	 * the HIF layer, shouldn't matter much.
 	 */
 
-	switch(devid) {
-	case 0x7010:
-	case 0x7015:
-	case 0x9018:
-	case 0xA704:
-	case 0x1200:
+	if (IS_AR7010_DEVICE(drv_info))
 		priv->htc->credits = 45;
-		break;
-	default:
+	else
 		priv->htc->credits = 33;
-	}
 
 	ret = htc_init(priv->htc);
 	if (ret)
@@ -294,9 +285,9 @@ static unsigned int ath9k_regread(void *
 			  (u8 *) &val, sizeof(val),
 			  100);
 	if (unlikely(r)) {
-		ath_print(common, ATH_DBG_WMI,
-			  "REGISTER READ FAILED: (0x%04x, %d)\n",
-			   reg_offset, r);
+		ath_dbg(common, ATH_DBG_WMI,
+			"REGISTER READ FAILED: (0x%04x, %d)\n",
+			reg_offset, r);
 		return -EIO;
 	}
 
@@ -308,7 +299,7 @@ static void ath9k_regwrite_single(void *
 	struct ath_hw *ah = (struct ath_hw *) hw_priv;
 	struct ath_common *common = ath9k_hw_common(ah);
 	struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv;
-	__be32 buf[2] = {
+	const __be32 buf[2] = {
 		cpu_to_be32(reg_offset),
 		cpu_to_be32(val),
 	};
@@ -319,9 +310,9 @@ static void ath9k_regwrite_single(void *
 			  (u8 *) &val, sizeof(val),
 			  100);
 	if (unlikely(r)) {
-		ath_print(common, ATH_DBG_WMI,
-			  "REGISTER WRITE FAILED:(0x%04x, %d)\n",
-			  reg_offset, r);
+		ath_dbg(common, ATH_DBG_WMI,
+			"REGISTER WRITE FAILED:(0x%04x, %d)\n",
+			reg_offset, r);
 	}
 }
 
@@ -351,9 +342,9 @@ static void ath9k_regwrite_buffer(void *
 			  (u8 *) &rsp_status, sizeof(rsp_status),
 			  100);
 		if (unlikely(r)) {
-			ath_print(common, ATH_DBG_WMI,
-				  "REGISTER WRITE FAILED, multi len: %d\n",
-				  priv->wmi->multi_write_idx);
+			ath_dbg(common, ATH_DBG_WMI,
+				"REGISTER WRITE FAILED, multi len: %d\n",
+				priv->wmi->multi_write_idx);
 		}
 		priv->wmi->multi_write_idx = 0;
 	}
@@ -401,9 +392,9 @@ static void ath9k_regwrite_flush(void *h
 			  (u8 *) &rsp_status, sizeof(rsp_status),
 			  100);
 		if (unlikely(r)) {
-			ath_print(common, ATH_DBG_WMI,
-				  "REGISTER WRITE FAILED, multi len: %d\n",
-				  priv->wmi->multi_write_idx);
+			ath_dbg(common, ATH_DBG_WMI,
+				"REGISTER WRITE FAILED, multi len: %d\n",
+				priv->wmi->multi_write_idx);
 		}
 		priv->wmi->multi_write_idx = 0;
 	}
@@ -475,9 +466,9 @@ static void setup_ht_cap(struct ath9k_ht
 	tx_streams = ath9k_cmn_count_streams(common->tx_chainmask, 2);
 	rx_streams = ath9k_cmn_count_streams(common->rx_chainmask, 2);
 
-	ath_print(common, ATH_DBG_CONFIG,
-		  "TX streams %d, RX streams: %d\n",
-		  tx_streams, rx_streams);
+	ath_dbg(common, ATH_DBG_CONFIG,
+		"TX streams %d, RX streams: %d\n",
+		tx_streams, rx_streams);
 
 	if (tx_streams != rx_streams) {
 		ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_RX_DIFF;
@@ -501,37 +492,31 @@ static int ath9k_init_queues(struct ath9
 
 	priv->beaconq = ath9k_hw_beaconq_setup(priv->ah);
 	if (priv->beaconq == -1) {
-		ath_print(common, ATH_DBG_FATAL,
-			  "Unable to setup BEACON xmit queue\n");
+		ath_err(common, "Unable to setup BEACON xmit queue\n");
 		goto err;
 	}
 
 	priv->cabq = ath9k_htc_cabq_setup(priv);
 	if (priv->cabq == -1) {
-		ath_print(common, ATH_DBG_FATAL,
-			  "Unable to setup CAB xmit queue\n");
+		ath_err(common, "Unable to setup CAB xmit queue\n");
 		goto err;
 	}
 
 	if (!ath9k_htc_txq_setup(priv, WME_AC_BE)) {
-		ath_print(common, ATH_DBG_FATAL,
-			  "Unable to setup xmit queue for BE traffic\n");
+		ath_err(common, "Unable to setup xmit queue for BE traffic\n");
 		goto err;
 	}
 
 	if (!ath9k_htc_txq_setup(priv, WME_AC_BK)) {
-		ath_print(common, ATH_DBG_FATAL,
-			  "Unable to setup xmit queue for BK traffic\n");
+		ath_err(common, "Unable to setup xmit queue for BK traffic\n");
 		goto err;
 	}
 	if (!ath9k_htc_txq_setup(priv, WME_AC_VI)) {
-		ath_print(common, ATH_DBG_FATAL,
-			  "Unable to setup xmit queue for VI traffic\n");
+		ath_err(common, "Unable to setup xmit queue for VI traffic\n");
 		goto err;
 	}
 	if (!ath9k_htc_txq_setup(priv, WME_AC_VO)) {
-		ath_print(common, ATH_DBG_FATAL,
-			  "Unable to setup xmit queue for VO traffic\n");
+		ath_err(common, "Unable to setup xmit queue for VO traffic\n");
 		goto err;
 	}
 
@@ -549,9 +534,9 @@ static void ath9k_init_crypto(struct ath
 	/* Get the hardware key cache size. */
 	common->keymax = priv->ah->caps.keycache_size;
 	if (common->keymax > ATH_KEYMAX) {
-		ath_print(common, ATH_DBG_ANY,
-			  "Warning, using only %u entries in %u key cache\n",
-			  ATH_KEYMAX, common->keymax);
+		ath_dbg(common, ATH_DBG_ANY,
+			"Warning, using only %u entries in %u key cache\n",
+			ATH_KEYMAX, common->keymax);
 		common->keymax = ATH_KEYMAX;
 	}
 
@@ -627,7 +612,8 @@ static void ath9k_init_btcoex(struct ath
 }
 
 static int ath9k_init_priv(struct ath9k_htc_priv *priv,
-			   u16 devid, char *product)
+			   u16 devid, char *product,
+			   u32 drv_info)
 {
 	struct ath_hw *ah = NULL;
 	struct ath_common *common;
@@ -641,6 +627,8 @@ static int ath9k_init_priv(struct ath9k_
 
 	ah->hw_version.devid = devid;
 	ah->hw_version.subsysid = 0; /* FIXME */
+	ah->hw_version.usbdev = drv_info;
+	ah->ah_flags |= AH_USE_EEPROM;
 	priv->ah = ah;
 
 	common = ath9k_hw_common(ah);
@@ -656,13 +644,15 @@ static int ath9k_init_priv(struct ath9k_
 	spin_lock_init(&priv->tx_lock);
 	mutex_init(&priv->mutex);
 	mutex_init(&priv->htc_pm_lock);
-	tasklet_init(&priv->wmi_tasklet, ath9k_wmi_tasklet,
+	tasklet_init(&priv->swba_tasklet, ath9k_swba_tasklet,
 		     (unsigned long)priv);
 	tasklet_init(&priv->rx_tasklet, ath9k_rx_tasklet,
 		     (unsigned long)priv);
-	tasklet_init(&priv->tx_tasklet, ath9k_tx_tasklet, (unsigned long)priv);
+	tasklet_init(&priv->tx_tasklet, ath9k_tx_tasklet,
+		     (unsigned long)priv);
 	INIT_DELAYED_WORK(&priv->ath9k_ani_work, ath9k_ani_work);
 	INIT_WORK(&priv->ps_work, ath9k_ps_work);
+	INIT_WORK(&priv->fatal_work, ath9k_fatal_work);
 
 	/*
 	 * Cache line size is used to size and align various
@@ -673,16 +663,15 @@ static int ath9k_init_priv(struct ath9k_
 
 	ret = ath9k_hw_init(ah);
 	if (ret) {
-		ath_print(common, ATH_DBG_FATAL,
-			  "Unable to initialize hardware; "
-			  "initialization status: %d\n", ret);
+		ath_err(common,
+			"Unable to initialize hardware; initialization status: %d\n",
+			ret);
 		goto err_hw;
 	}
 
 	ret = ath9k_htc_init_debug(ah);
 	if (ret) {
-		ath_print(common, ATH_DBG_FATAL,
-			  "Unable to create debugfs files\n");
+		ath_err(common, "Unable to create debugfs files\n");
 		goto err_debug;
 	}
 
@@ -762,7 +751,7 @@ static void ath9k_set_hw_capab(struct at
 }
 
 static int ath9k_init_device(struct ath9k_htc_priv *priv,
-			     u16 devid, char *product)
+			     u16 devid, char *product, u32 drv_info)
 {
 	struct ieee80211_hw *hw = priv->hw;
 	struct ath_common *common;
@@ -771,7 +760,7 @@ static int ath9k_init_device(struct ath9
 	struct ath_regulatory *reg;
 
 	/* Bring up device */
-	error = ath9k_init_priv(priv, devid, product);
+	error = ath9k_init_priv(priv, devid, product, drv_info);
 	if (error != 0)
 		goto err_init;
 
@@ -829,7 +818,7 @@ err_init:
 }
 
 int ath9k_htc_probe_device(struct htc_target *htc_handle, struct device *dev,
-			   u16 devid, char *product)
+			   u16 devid, char *product, u32 drv_info)
 {
 	struct ieee80211_hw *hw;
 	struct ath9k_htc_priv *priv;
@@ -856,14 +845,11 @@ int ath9k_htc_probe_device(struct htc_ta
 		goto err_free;
 	}
 
-	ret = ath9k_init_htc_services(priv, devid);
+	ret = ath9k_init_htc_services(priv, devid, drv_info);
 	if (ret)
 		goto err_init;
 
-	/* The device may have been unplugged earlier. */
-	priv->op_flags &= ~OP_UNPLUGGED;
-
-	ret = ath9k_init_device(priv, devid, product);
+	ret = ath9k_init_device(priv, devid, product, drv_info);
 	if (ret)
 		goto err_init;
 
@@ -882,7 +868,7 @@ void ath9k_htc_disconnect_device(struct
 
 		/* Check if the device has been yanked out. */
 		if (hotunplug)
-			htc_handle->drv_priv->op_flags |= OP_UNPLUGGED;
+			htc_handle->drv_priv->ah->ah_flags |= AH_UNPLUGGED;
 
 		ath9k_deinit_device(htc_handle->drv_priv);
 		ath9k_deinit_wmi(htc_handle->drv_priv);
@@ -899,14 +885,15 @@ void ath9k_htc_suspend(struct htc_target
 
 int ath9k_htc_resume(struct htc_target *htc_handle)
 {
+	struct ath9k_htc_priv *priv = htc_handle->drv_priv;
 	int ret;
 
-	ret = ath9k_htc_wait_for_target(htc_handle->drv_priv);
+	ret = ath9k_htc_wait_for_target(priv);
 	if (ret)
 		return ret;
 
-	ret = ath9k_init_htc_services(htc_handle->drv_priv,
-			      htc_handle->drv_priv->ah->hw_version.devid);
+	ret = ath9k_init_htc_services(priv, priv->ah->hw_version.devid,
+				      priv->ah->hw_version.usbdev);
 	return ret;
 }
 #endif
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/htc_drv_main.c linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/htc_drv_main.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/htc_drv_main.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/htc_drv_main.c	2011-03-14 21:20:32.000000000 -0400
@@ -24,12 +24,12 @@ static struct dentry *ath9k_debugfs_root
 /* Utilities */
 /*************/
 
-static void ath_update_txpow(struct ath9k_htc_priv *priv)
+void ath_update_txpow(struct ath9k_htc_priv *priv)
 {
 	struct ath_hw *ah = priv->ah;
 
 	if (priv->curtxpow != priv->txpowlimit) {
-		ath9k_hw_set_txpowerlimit(ah, priv->txpowlimit);
+		ath9k_hw_set_txpowerlimit(ah, priv->txpowlimit, false);
 		/* read back in case value is clamped */
 		priv->curtxpow = ath9k_hw_regulatory(ah)->power_limit;
 	}
@@ -116,6 +116,60 @@ void ath9k_ps_work(struct work_struct *w
 	ath9k_htc_setpower(priv, ATH9K_PM_NETWORK_SLEEP);
 }
 
+void ath9k_htc_reset(struct ath9k_htc_priv *priv)
+{
+	struct ath_hw *ah = priv->ah;
+	struct ath_common *common = ath9k_hw_common(ah);
+	struct ieee80211_channel *channel = priv->hw->conf.channel;
+	struct ath9k_hw_cal_data *caldata;
+	enum htc_phymode mode;
+	__be16 htc_mode;
+	u8 cmd_rsp;
+	int ret;
+
+	mutex_lock(&priv->mutex);
+	ath9k_htc_ps_wakeup(priv);
+
+	if (priv->op_flags & OP_ASSOCIATED)
+		cancel_delayed_work_sync(&priv->ath9k_ani_work);
+
+	ieee80211_stop_queues(priv->hw);
+	htc_stop(priv->htc);
+	WMI_CMD(WMI_DISABLE_INTR_CMDID);
+	WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID);
+	WMI_CMD(WMI_STOP_RECV_CMDID);
+
+	caldata = &priv->caldata[channel->hw_value];
+	ret = ath9k_hw_reset(ah, ah->curchan, caldata, false);
+	if (ret) {
+		ath_err(common,
+			"Unable to reset device (%u Mhz) reset status %d\n",
+			channel->center_freq, ret);
+	}
+
+	ath_update_txpow(priv);
+
+	WMI_CMD(WMI_START_RECV_CMDID);
+	ath9k_host_rx_init(priv);
+
+	mode = ath9k_htc_get_curmode(priv, ah->curchan);
+	htc_mode = cpu_to_be16(mode);
+	WMI_CMD_BUF(WMI_SET_MODE_CMDID, &htc_mode);
+
+	WMI_CMD(WMI_ENABLE_INTR_CMDID);
+	htc_start(priv->htc);
+
+	if (priv->op_flags & OP_ASSOCIATED) {
+		ath9k_htc_beacon_config(priv, priv->vif);
+		ath_start_ani(priv);
+	}
+
+	ieee80211_wake_queues(priv->hw);
+
+	ath9k_htc_ps_restore(priv);
+	mutex_unlock(&priv->mutex);
+}
+
 static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv,
 				 struct ieee80211_hw *hw,
 				 struct ath9k_channel *hchan)
@@ -123,7 +177,7 @@ static int ath9k_htc_set_channel(struct
 	struct ath_hw *ah = priv->ah;
 	struct ath_common *common = ath9k_hw_common(ah);
 	struct ieee80211_conf *conf = &common->hw->conf;
-	bool fastcc = true;
+	bool fastcc;
 	struct ieee80211_channel *channel = hw->conf.channel;
 	struct ath9k_hw_cal_data *caldata;
 	enum htc_phymode mode;
@@ -134,8 +188,7 @@ static int ath9k_htc_set_channel(struct
 	if (priv->op_flags & OP_INVALID)
 		return -EIO;
 
-	if (priv->op_flags & OP_FULL_RESET)
-		fastcc = false;
+	fastcc = !!(hw->conf.flags & IEEE80211_CONF_OFFCHANNEL);
 
 	ath9k_htc_ps_wakeup(priv);
 	htc_stop(priv->htc);
@@ -143,18 +196,18 @@ static int ath9k_htc_set_channel(struct
 	WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID);
 	WMI_CMD(WMI_STOP_RECV_CMDID);
 
-	ath_print(common, ATH_DBG_CONFIG,
-		  "(%u MHz) -> (%u MHz), HT: %d, HT40: %d fastcc: %d\n",
-		  priv->ah->curchan->channel,
-		  channel->center_freq, conf_is_ht(conf), conf_is_ht40(conf),
-		  fastcc);
+	ath_dbg(common, ATH_DBG_CONFIG,
+		"(%u MHz) -> (%u MHz), HT: %d, HT40: %d fastcc: %d\n",
+		priv->ah->curchan->channel,
+		channel->center_freq, conf_is_ht(conf), conf_is_ht40(conf),
+		fastcc);
 
 	caldata = &priv->caldata[channel->hw_value];
 	ret = ath9k_hw_reset(ah, hchan, caldata, fastcc);
 	if (ret) {
-		ath_print(common, ATH_DBG_FATAL,
-			  "Unable to reset channel (%u Mhz) "
-			  "reset status %d\n", channel->center_freq, ret);
+		ath_err(common,
+			"Unable to reset channel (%u Mhz) reset status %d\n",
+			channel->center_freq, ret);
 		goto err;
 	}
 
@@ -177,23 +230,43 @@ static int ath9k_htc_set_channel(struct
 		goto err;
 
 	htc_start(priv->htc);
-
-	priv->op_flags &= ~OP_FULL_RESET;
 err:
 	ath9k_htc_ps_restore(priv);
 	return ret;
 }
 
+static void __ath9k_htc_remove_monitor_interface(struct ath9k_htc_priv *priv)
+{
+	struct ath_common *common = ath9k_hw_common(priv->ah);
+	struct ath9k_htc_target_vif hvif;
+	int ret = 0;
+	u8 cmd_rsp;
+
+	memset(&hvif, 0, sizeof(struct ath9k_htc_target_vif));
+	memcpy(&hvif.myaddr, common->macaddr, ETH_ALEN);
+	hvif.index = 0; /* Should do for now */
+	WMI_CMD_BUF(WMI_VAP_REMOVE_CMDID, &hvif);
+	priv->nvifs--;
+}
+
 static int ath9k_htc_add_monitor_interface(struct ath9k_htc_priv *priv)
 {
 	struct ath_common *common = ath9k_hw_common(priv->ah);
 	struct ath9k_htc_target_vif hvif;
+	struct ath9k_htc_target_sta tsta;
 	int ret = 0;
 	u8 cmd_rsp;
 
 	if (priv->nvifs > 0)
 		return -ENOBUFS;
 
+	if (priv->nstations >= ATH9K_HTC_MAX_STA)
+		return -ENOBUFS;
+
+	/*
+	 * Add an interface.
+	 */
+
 	memset(&hvif, 0, sizeof(struct ath9k_htc_target_vif));
 	memcpy(&hvif.myaddr, common->macaddr, ETH_ALEN);
 
@@ -206,23 +279,68 @@ static int ath9k_htc_add_monitor_interfa
 		return ret;
 
 	priv->nvifs++;
+
+	/*
+	 * Associate a station with the interface for packet injection.
+	 */
+
+	memset(&tsta, 0, sizeof(struct ath9k_htc_target_sta));
+
+	memcpy(&tsta.macaddr, common->macaddr, ETH_ALEN);
+
+	tsta.is_vif_sta = 1;
+	tsta.sta_index = priv->nstations;
+	tsta.vif_index = hvif.index;
+	tsta.maxampdu = 0xffff;
+
+	WMI_CMD_BUF(WMI_NODE_CREATE_CMDID, &tsta);
+	if (ret) {
+		ath_err(common, "Unable to add station entry for monitor mode\n");
+		goto err_vif;
+	}
+
+	priv->nstations++;
+
+	/*
+	 * Set chainmask etc. on the target.
+	 */
+	ret = ath9k_htc_update_cap_target(priv);
+	if (ret)
+		ath_dbg(common, ATH_DBG_CONFIG,
+			"Failed to update capability in target\n");
+
+	priv->ah->is_monitoring = true;
+
 	return 0;
+
+err_vif:
+	/*
+	 * Remove the interface from the target.
+	 */
+	__ath9k_htc_remove_monitor_interface(priv);
+	return ret;
 }
 
 static int ath9k_htc_remove_monitor_interface(struct ath9k_htc_priv *priv)
 {
 	struct ath_common *common = ath9k_hw_common(priv->ah);
-	struct ath9k_htc_target_vif hvif;
 	int ret = 0;
-	u8 cmd_rsp;
+	u8 cmd_rsp, sta_idx;
 
-	memset(&hvif, 0, sizeof(struct ath9k_htc_target_vif));
-	memcpy(&hvif.myaddr, common->macaddr, ETH_ALEN);
-	hvif.index = 0; /* Should do for now */
-	WMI_CMD_BUF(WMI_VAP_REMOVE_CMDID, &hvif);
-	priv->nvifs--;
+	__ath9k_htc_remove_monitor_interface(priv);
 
-	return ret;
+	sta_idx = 0; /* Only single interface, for now */
+
+	WMI_CMD_BUF(WMI_NODE_REMOVE_CMDID, &sta_idx);
+	if (ret) {
+		ath_err(common, "Unable to remove station entry for monitor mode\n");
+		return ret;
+	}
+
+	priv->nstations--;
+	priv->ah->is_monitoring = false;
+
+	return 0;
 }
 
 static int ath9k_htc_add_station(struct ath9k_htc_priv *priv,
@@ -263,15 +381,16 @@ static int ath9k_htc_add_station(struct
 	WMI_CMD_BUF(WMI_NODE_CREATE_CMDID, &tsta);
 	if (ret) {
 		if (sta)
-			ath_print(common, ATH_DBG_FATAL,
-			  "Unable to add station entry for: %pM\n", sta->addr);
+			ath_err(common,
+				"Unable to add station entry for: %pM\n",
+				sta->addr);
 		return ret;
 	}
 
 	if (sta)
-		ath_print(common, ATH_DBG_CONFIG,
-			  "Added a station entry for: %pM (idx: %d)\n",
-			  sta->addr, tsta.sta_index);
+		ath_dbg(common, ATH_DBG_CONFIG,
+			"Added a station entry for: %pM (idx: %d)\n",
+			sta->addr, tsta.sta_index);
 
 	priv->nstations++;
 	return 0;
@@ -296,22 +415,22 @@ static int ath9k_htc_remove_station(stru
 	WMI_CMD_BUF(WMI_NODE_REMOVE_CMDID, &sta_idx);
 	if (ret) {
 		if (sta)
-			ath_print(common, ATH_DBG_FATAL,
-			  "Unable to remove station entry for: %pM\n",
-			  sta->addr);
+			ath_err(common,
+				"Unable to remove station entry for: %pM\n",
+				sta->addr);
 		return ret;
 	}
 
 	if (sta)
-		ath_print(common, ATH_DBG_CONFIG,
-			  "Removed a station entry for: %pM (idx: %d)\n",
-			  sta->addr, sta_idx);
+		ath_dbg(common, ATH_DBG_CONFIG,
+			"Removed a station entry for: %pM (idx: %d)\n",
+			sta->addr, sta_idx);
 
 	priv->nstations--;
 	return 0;
 }
 
-static int ath9k_htc_update_cap_target(struct ath9k_htc_priv *priv)
+int ath9k_htc_update_cap_target(struct ath9k_htc_priv *priv)
 {
 	struct ath9k_htc_cap_target tcap;
 	int ret;
@@ -390,8 +509,8 @@ static int ath9k_htc_send_rate_cmd(struc
 
 	WMI_CMD_BUF(WMI_RC_RATE_UPDATE_CMDID, trate);
 	if (ret) {
-		ath_print(common, ATH_DBG_FATAL,
-			  "Unable to initialize Rate information on target\n");
+		ath_err(common,
+			"Unable to initialize Rate information on target\n");
 	}
 
 	return ret;
@@ -408,9 +527,9 @@ static void ath9k_htc_init_rate(struct a
 	ath9k_htc_setup_rate(priv, sta, &trate);
 	ret = ath9k_htc_send_rate_cmd(priv, &trate);
 	if (!ret)
-		ath_print(common, ATH_DBG_CONFIG,
-			  "Updated target sta: %pM, rate caps: 0x%X\n",
-			  sta->addr, be32_to_cpu(trate.capflags));
+		ath_dbg(common, ATH_DBG_CONFIG,
+			"Updated target sta: %pM, rate caps: 0x%X\n",
+			sta->addr, be32_to_cpu(trate.capflags));
 }
 
 static void ath9k_htc_update_rate(struct ath9k_htc_priv *priv,
@@ -435,9 +554,9 @@ static void ath9k_htc_update_rate(struct
 
 	ret = ath9k_htc_send_rate_cmd(priv, &trate);
 	if (!ret)
-		ath_print(common, ATH_DBG_CONFIG,
-			  "Updated target sta: %pM, rate caps: 0x%X\n",
-			  bss_conf->bssid, be32_to_cpu(trate.capflags));
+		ath_dbg(common, ATH_DBG_CONFIG,
+			"Updated target sta: %pM, rate caps: 0x%X\n",
+			bss_conf->bssid, be32_to_cpu(trate.capflags));
 }
 
 static int ath9k_htc_tx_aggr_oper(struct ath9k_htc_priv *priv,
@@ -464,14 +583,14 @@ static int ath9k_htc_tx_aggr_oper(struct
 
 	WMI_CMD_BUF(WMI_TX_AGGR_ENABLE_CMDID, &aggr);
 	if (ret)
-		ath_print(common, ATH_DBG_CONFIG,
-			  "Unable to %s TX aggregation for (%pM, %d)\n",
-			  (aggr.aggr_enable) ? "start" : "stop", sta->addr, tid);
+		ath_dbg(common, ATH_DBG_CONFIG,
+			"Unable to %s TX aggregation for (%pM, %d)\n",
+			(aggr.aggr_enable) ? "start" : "stop", sta->addr, tid);
 	else
-		ath_print(common, ATH_DBG_CONFIG,
-			  "%s TX aggregation for (%pM, %d)\n",
-			  (aggr.aggr_enable) ? "Starting" : "Stopping",
-			  sta->addr, tid);
+		ath_dbg(common, ATH_DBG_CONFIG,
+			"%s TX aggregation for (%pM, %d)\n",
+			(aggr.aggr_enable) ? "Starting" : "Stopping",
+			sta->addr, tid);
 
 	spin_lock_bh(&priv->tx_lock);
 	ista->tid_state[tid] = (aggr.aggr_enable && !ret) ? AGGR_START : AGGR_STOP;
@@ -689,7 +808,7 @@ void ath9k_htc_debug_remove_root(void)
 /* ANI */
 /*******/
 
-static void ath_start_ani(struct ath9k_htc_priv *priv)
+void ath_start_ani(struct ath9k_htc_priv *priv)
 {
 	struct ath_common *common = ath9k_hw_common(priv->ah);
 	unsigned long timestamp = jiffies_to_msecs(jiffies);
@@ -724,7 +843,7 @@ void ath9k_ani_work(struct work_struct *
 	/* Long calibration runs independently of short calibration. */
 	if ((timestamp - common->ani.longcal_timer) >= ATH_LONG_CALINTERVAL) {
 		longcal = true;
-		ath_print(common, ATH_DBG_ANI, "longcal @%lu\n", jiffies);
+		ath_dbg(common, ATH_DBG_ANI, "longcal @%lu\n", jiffies);
 		common->ani.longcal_timer = timestamp;
 	}
 
@@ -733,8 +852,8 @@ void ath9k_ani_work(struct work_struct *
 		if ((timestamp - common->ani.shortcal_timer) >=
 		    short_cal_interval) {
 			shortcal = true;
-			ath_print(common, ATH_DBG_ANI,
-				  "shortcal @%lu\n", jiffies);
+			ath_dbg(common, ATH_DBG_ANI,
+				"shortcal @%lu\n", jiffies);
 			common->ani.shortcal_timer = timestamp;
 			common->ani.resetcal_timer = timestamp;
 		}
@@ -788,317 +907,6 @@ set_timer:
 				     msecs_to_jiffies(cal_interval));
 }
 
-/*******/
-/* LED */
-/*******/
-
-static void ath9k_led_blink_work(struct work_struct *work)
-{
-	struct ath9k_htc_priv *priv = container_of(work, struct ath9k_htc_priv,
-						   ath9k_led_blink_work.work);
-
-	if (!(priv->op_flags & OP_LED_ASSOCIATED))
-		return;
-
-	if ((priv->led_on_duration == ATH_LED_ON_DURATION_IDLE) ||
-	    (priv->led_off_duration == ATH_LED_OFF_DURATION_IDLE))
-		ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin, 0);
-	else
-		ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin,
-				  (priv->op_flags & OP_LED_ON) ? 1 : 0);
-
-	ieee80211_queue_delayed_work(priv->hw,
-				     &priv->ath9k_led_blink_work,
-				     (priv->op_flags & OP_LED_ON) ?
-				     msecs_to_jiffies(priv->led_off_duration) :
-				     msecs_to_jiffies(priv->led_on_duration));
-
-	priv->led_on_duration = priv->led_on_cnt ?
-		max((ATH_LED_ON_DURATION_IDLE - priv->led_on_cnt), 25) :
-		ATH_LED_ON_DURATION_IDLE;
-	priv->led_off_duration = priv->led_off_cnt ?
-		max((ATH_LED_OFF_DURATION_IDLE - priv->led_off_cnt), 10) :
-		ATH_LED_OFF_DURATION_IDLE;
-	priv->led_on_cnt = priv->led_off_cnt = 0;
-
-	if (priv->op_flags & OP_LED_ON)
-		priv->op_flags &= ~OP_LED_ON;
-	else
-		priv->op_flags |= OP_LED_ON;
-}
-
-static void ath9k_led_brightness_work(struct work_struct *work)
-{
-	struct ath_led *led = container_of(work, struct ath_led,
-					   brightness_work.work);
-	struct ath9k_htc_priv *priv = led->priv;
-
-	switch (led->brightness) {
-	case LED_OFF:
-		if (led->led_type == ATH_LED_ASSOC ||
-		    led->led_type == ATH_LED_RADIO) {
-			ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin,
-					  (led->led_type == ATH_LED_RADIO));
-			priv->op_flags &= ~OP_LED_ASSOCIATED;
-			if (led->led_type == ATH_LED_RADIO)
-				priv->op_flags &= ~OP_LED_ON;
-		} else {
-			priv->led_off_cnt++;
-		}
-		break;
-	case LED_FULL:
-		if (led->led_type == ATH_LED_ASSOC) {
-			priv->op_flags |= OP_LED_ASSOCIATED;
-			ieee80211_queue_delayed_work(priv->hw,
-					     &priv->ath9k_led_blink_work, 0);
-		} else if (led->led_type == ATH_LED_RADIO) {
-			ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin, 0);
-			priv->op_flags |= OP_LED_ON;
-		} else {
-			priv->led_on_cnt++;
-		}
-		break;
-	default:
-		break;
-	}
-}
-
-static void ath9k_led_brightness(struct led_classdev *led_cdev,
-				 enum led_brightness brightness)
-{
-	struct ath_led *led = container_of(led_cdev, struct ath_led, led_cdev);
-	struct ath9k_htc_priv *priv = led->priv;
-
-	led->brightness = brightness;
-	if (!(priv->op_flags & OP_LED_DEINIT))
-		ieee80211_queue_delayed_work(priv->hw,
-					     &led->brightness_work, 0);
-}
-
-static void ath9k_led_stop_brightness(struct ath9k_htc_priv *priv)
-{
-	cancel_delayed_work_sync(&priv->radio_led.brightness_work);
-	cancel_delayed_work_sync(&priv->assoc_led.brightness_work);
-	cancel_delayed_work_sync(&priv->tx_led.brightness_work);
-	cancel_delayed_work_sync(&priv->rx_led.brightness_work);
-}
-
-static int ath9k_register_led(struct ath9k_htc_priv *priv, struct ath_led *led,
-			      char *trigger)
-{
-	int ret;
-
-	led->priv = priv;
-	led->led_cdev.name = led->name;
-	led->led_cdev.default_trigger = trigger;
-	led->led_cdev.brightness_set = ath9k_led_brightness;
-
-	ret = led_classdev_register(wiphy_dev(priv->hw->wiphy), &led->led_cdev);
-	if (ret)
-		ath_print(ath9k_hw_common(priv->ah), ATH_DBG_FATAL,
-			  "Failed to register led:%s", led->name);
-	else
-		led->registered = 1;
-
-	INIT_DELAYED_WORK(&led->brightness_work, ath9k_led_brightness_work);
-
-	return ret;
-}
-
-static void ath9k_unregister_led(struct ath_led *led)
-{
-	if (led->registered) {
-		led_classdev_unregister(&led->led_cdev);
-		led->registered = 0;
-	}
-}
-
-void ath9k_deinit_leds(struct ath9k_htc_priv *priv)
-{
-	priv->op_flags |= OP_LED_DEINIT;
-	ath9k_unregister_led(&priv->assoc_led);
-	priv->op_flags &= ~OP_LED_ASSOCIATED;
-	ath9k_unregister_led(&priv->tx_led);
-	ath9k_unregister_led(&priv->rx_led);
-	ath9k_unregister_led(&priv->radio_led);
-}
-
-void ath9k_init_leds(struct ath9k_htc_priv *priv)
-{
-	char *trigger;
-	int ret;
-
-	if (AR_SREV_9287(priv->ah))
-		priv->ah->led_pin = ATH_LED_PIN_9287;
-	else if (AR_SREV_9271(priv->ah))
-		priv->ah->led_pin = ATH_LED_PIN_9271;
-	else if (AR_DEVID_7010(priv->ah))
-		priv->ah->led_pin = ATH_LED_PIN_7010;
-	else
-		priv->ah->led_pin = ATH_LED_PIN_DEF;
-
-	/* Configure gpio 1 for output */
-	ath9k_hw_cfg_output(priv->ah, priv->ah->led_pin,
-			    AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
-	/* LED off, active low */
-	ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin, 1);
-
-	INIT_DELAYED_WORK(&priv->ath9k_led_blink_work, ath9k_led_blink_work);
-
-	trigger = ieee80211_get_radio_led_name(priv->hw);
-	snprintf(priv->radio_led.name, sizeof(priv->radio_led.name),
-		"ath9k-%s::radio", wiphy_name(priv->hw->wiphy));
-	ret = ath9k_register_led(priv, &priv->radio_led, trigger);
-	priv->radio_led.led_type = ATH_LED_RADIO;
-	if (ret)
-		goto fail;
-
-	trigger = ieee80211_get_assoc_led_name(priv->hw);
-	snprintf(priv->assoc_led.name, sizeof(priv->assoc_led.name),
-		"ath9k-%s::assoc", wiphy_name(priv->hw->wiphy));
-	ret = ath9k_register_led(priv, &priv->assoc_led, trigger);
-	priv->assoc_led.led_type = ATH_LED_ASSOC;
-	if (ret)
-		goto fail;
-
-	trigger = ieee80211_get_tx_led_name(priv->hw);
-	snprintf(priv->tx_led.name, sizeof(priv->tx_led.name),
-		"ath9k-%s::tx", wiphy_name(priv->hw->wiphy));
-	ret = ath9k_register_led(priv, &priv->tx_led, trigger);
-	priv->tx_led.led_type = ATH_LED_TX;
-	if (ret)
-		goto fail;
-
-	trigger = ieee80211_get_rx_led_name(priv->hw);
-	snprintf(priv->rx_led.name, sizeof(priv->rx_led.name),
-		"ath9k-%s::rx", wiphy_name(priv->hw->wiphy));
-	ret = ath9k_register_led(priv, &priv->rx_led, trigger);
-	priv->rx_led.led_type = ATH_LED_RX;
-	if (ret)
-		goto fail;
-
-	priv->op_flags &= ~OP_LED_DEINIT;
-
-	return;
-
-fail:
-	cancel_delayed_work_sync(&priv->ath9k_led_blink_work);
-	ath9k_deinit_leds(priv);
-}
-
-/*******************/
-/*	Rfkill	   */
-/*******************/
-
-static bool ath_is_rfkill_set(struct ath9k_htc_priv *priv)
-{
-	return ath9k_hw_gpio_get(priv->ah, priv->ah->rfkill_gpio) ==
-		priv->ah->rfkill_polarity;
-}
-
-static void ath9k_htc_rfkill_poll_state(struct ieee80211_hw *hw)
-{
-	struct ath9k_htc_priv *priv = hw->priv;
-	bool blocked = !!ath_is_rfkill_set(priv);
-
-	wiphy_rfkill_set_hw_state(hw->wiphy, blocked);
-}
-
-void ath9k_start_rfkill_poll(struct ath9k_htc_priv *priv)
-{
-	if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT)
-		wiphy_rfkill_start_polling(priv->hw->wiphy);
-}
-
-static void ath9k_htc_radio_enable(struct ieee80211_hw *hw)
-{
-	struct ath9k_htc_priv *priv = hw->priv;
-	struct ath_hw *ah = priv->ah;
-	struct ath_common *common = ath9k_hw_common(ah);
-	int ret;
-	u8 cmd_rsp;
-
-	if (!ah->curchan)
-		ah->curchan = ath9k_cmn_get_curchannel(hw, ah);
-
-	/* Reset the HW */
-	ret = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false);
-	if (ret) {
-		ath_print(common, ATH_DBG_FATAL,
-			  "Unable to reset hardware; reset status %d "
-			  "(freq %u MHz)\n", ret, ah->curchan->channel);
-	}
-
-	ath_update_txpow(priv);
-
-	/* Start RX */
-	WMI_CMD(WMI_START_RECV_CMDID);
-	ath9k_host_rx_init(priv);
-
-	/* Start TX */
-	htc_start(priv->htc);
-	spin_lock_bh(&priv->tx_lock);
-	priv->tx_queues_stop = false;
-	spin_unlock_bh(&priv->tx_lock);
-	ieee80211_wake_queues(hw);
-
-	WMI_CMD(WMI_ENABLE_INTR_CMDID);
-
-	/* Enable LED */
-	ath9k_hw_cfg_output(ah, ah->led_pin,
-			    AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
-	ath9k_hw_set_gpio(ah, ah->led_pin, 0);
-}
-
-static void ath9k_htc_radio_disable(struct ieee80211_hw *hw)
-{
-	struct ath9k_htc_priv *priv = hw->priv;
-	struct ath_hw *ah = priv->ah;
-	struct ath_common *common = ath9k_hw_common(ah);
-	int ret;
-	u8 cmd_rsp;
-
-	ath9k_htc_ps_wakeup(priv);
-
-	/* Disable LED */
-	ath9k_hw_set_gpio(ah, ah->led_pin, 1);
-	ath9k_hw_cfg_gpio_input(ah, ah->led_pin);
-
-	WMI_CMD(WMI_DISABLE_INTR_CMDID);
-
-	/* Stop TX */
-	ieee80211_stop_queues(hw);
-	htc_stop(priv->htc);
-	WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID);
-	skb_queue_purge(&priv->tx_queue);
-
-	/* Stop RX */
-	WMI_CMD(WMI_STOP_RECV_CMDID);
-
-	/*
-	 * The MIB counters have to be disabled here,
-	 * since the target doesn't do it.
-	 */
-	ath9k_hw_disable_mib_counters(ah);
-
-	if (!ah->curchan)
-		ah->curchan = ath9k_cmn_get_curchannel(hw, ah);
-
-	/* Reset the HW */
-	ret = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false);
-	if (ret) {
-		ath_print(common, ATH_DBG_FATAL,
-			  "Unable to reset hardware; reset status %d "
-			  "(freq %u MHz)\n", ret, ah->curchan->channel);
-	}
-
-	/* Disable the PHY */
-	ath9k_hw_phy_disable(ah);
-
-	ath9k_htc_ps_restore(priv);
-	ath9k_htc_setpower(priv, ATH9K_PM_FULL_SLEEP);
-}
-
 /**********************/
 /* mac80211 Callbacks */
 /**********************/
@@ -1124,15 +932,15 @@ static int ath9k_htc_tx(struct ieee80211
 	ret = ath9k_htc_tx_start(priv, skb);
 	if (ret != 0) {
 		if (ret == -ENOMEM) {
-			ath_print(ath9k_hw_common(priv->ah), ATH_DBG_XMIT,
-				  "Stopping TX queues\n");
+			ath_dbg(ath9k_hw_common(priv->ah), ATH_DBG_XMIT,
+				"Stopping TX queues\n");
 			ieee80211_stop_queues(hw);
 			spin_lock_bh(&priv->tx_lock);
 			priv->tx_queues_stop = true;
 			spin_unlock_bh(&priv->tx_lock);
 		} else {
-			ath_print(ath9k_hw_common(priv->ah), ATH_DBG_XMIT,
-				  "Tx failed");
+			ath_dbg(ath9k_hw_common(priv->ah), ATH_DBG_XMIT,
+				"Tx failed\n");
 		}
 		goto fail_tx;
 	}
@@ -1158,9 +966,9 @@ static int ath9k_htc_start(struct ieee80
 
 	mutex_lock(&priv->mutex);
 
-	ath_print(common, ATH_DBG_CONFIG,
-		  "Starting driver with initial channel: %d MHz\n",
-		  curchan->center_freq);
+	ath_dbg(common, ATH_DBG_CONFIG,
+		"Starting driver with initial channel: %d MHz\n",
+		curchan->center_freq);
 
 	/* Ensure that HW is awake before flushing RX */
 	ath9k_htc_setpower(priv, ATH9K_PM_AWAKE);
@@ -1169,15 +977,12 @@ static int ath9k_htc_start(struct ieee80
 	/* setup initial channel */
 	init_channel = ath9k_cmn_get_curchannel(hw, ah);
 
-	/* Reset SERDES registers */
-	ath9k_hw_configpcipowersave(ah, 0, 0);
-
 	ath9k_hw_htc_resetinit(ah);
 	ret = ath9k_hw_reset(ah, init_channel, ah->caldata, false);
 	if (ret) {
-		ath_print(common, ATH_DBG_FATAL,
-			  "Unable to reset hardware; reset status %d "
-			  "(freq %u MHz)\n", ret, curchan->center_freq);
+		ath_err(common,
+			"Unable to reset hardware; reset status %d (freq %u MHz)\n",
+			ret, curchan->center_freq);
 		mutex_unlock(&priv->mutex);
 		return ret;
 	}
@@ -1223,31 +1028,40 @@ static void ath9k_htc_stop(struct ieee80
 	mutex_lock(&priv->mutex);
 
 	if (priv->op_flags & OP_INVALID) {
-		ath_print(common, ATH_DBG_ANY, "Device not present\n");
+		ath_dbg(common, ATH_DBG_ANY, "Device not present\n");
 		mutex_unlock(&priv->mutex);
 		return;
 	}
 
-	/* Cancel all the running timers/work .. */
-	cancel_work_sync(&priv->ps_work);
-	cancel_delayed_work_sync(&priv->ath9k_led_blink_work);
-	ath9k_led_stop_brightness(priv);
-
 	ath9k_htc_ps_wakeup(priv);
 	htc_stop(priv->htc);
 	WMI_CMD(WMI_DISABLE_INTR_CMDID);
 	WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID);
 	WMI_CMD(WMI_STOP_RECV_CMDID);
+
+	tasklet_kill(&priv->swba_tasklet);
+	tasklet_kill(&priv->rx_tasklet);
+	tasklet_kill(&priv->tx_tasklet);
+
 	skb_queue_purge(&priv->tx_queue);
 
+	mutex_unlock(&priv->mutex);
+
+	/* Cancel all the running timers/work .. */
+	cancel_work_sync(&priv->fatal_work);
+	cancel_work_sync(&priv->ps_work);
+	cancel_delayed_work_sync(&priv->ath9k_led_blink_work);
+	ath9k_led_stop_brightness(priv);
+
+	mutex_lock(&priv->mutex);
+
 	/* Remove monitor interface here */
 	if (ah->opmode == NL80211_IFTYPE_MONITOR) {
 		if (ath9k_htc_remove_monitor_interface(priv))
-			ath_print(common, ATH_DBG_FATAL,
-				  "Unable to remove monitor interface\n");
+			ath_err(common, "Unable to remove monitor interface\n");
 		else
-			ath_print(common, ATH_DBG_CONFIG,
-				  "Monitor interface removed\n");
+			ath_dbg(common, ATH_DBG_CONFIG,
+				"Monitor interface removed\n");
 	}
 
 	if (ah->btcoex_hw.enabled) {
@@ -1258,13 +1072,12 @@ static void ath9k_htc_stop(struct ieee80
 
 	ath9k_hw_phy_disable(ah);
 	ath9k_hw_disable(ah);
-	ath9k_hw_configpcipowersave(ah, 1, 1);
 	ath9k_htc_ps_restore(priv);
 	ath9k_htc_setpower(priv, ATH9K_PM_FULL_SLEEP);
 
 	priv->op_flags |= OP_INVALID;
 
-	ath_print(common, ATH_DBG_CONFIG, "Driver halt\n");
+	ath_dbg(common, ATH_DBG_CONFIG, "Driver halt\n");
 	mutex_unlock(&priv->mutex);
 }
 
@@ -1298,14 +1111,14 @@ static int ath9k_htc_add_interface(struc
 		hvif.opmode = cpu_to_be32(HTC_M_IBSS);
 		break;
 	default:
-		ath_print(common, ATH_DBG_FATAL,
+		ath_err(common,
 			"Interface type %d not yet supported\n", vif->type);
 		ret = -EOPNOTSUPP;
 		goto out;
 	}
 
-	ath_print(common, ATH_DBG_CONFIG,
-		  "Attach a VIF of type: %d\n", vif->type);
+	ath_dbg(common, ATH_DBG_CONFIG,
+		"Attach a VIF of type: %d\n", vif->type);
 
 	priv->ah->opmode = vif->type;
 
@@ -1328,8 +1141,8 @@ static int ath9k_htc_add_interface(struc
 
 	ret = ath9k_htc_update_cap_target(priv);
 	if (ret)
-		ath_print(common, ATH_DBG_CONFIG, "Failed to update"
-			  " capability in target \n");
+		ath_dbg(common, ATH_DBG_CONFIG,
+			"Failed to update capability in target\n");
 
 	priv->vif = vif;
 out:
@@ -1349,7 +1162,7 @@ static void ath9k_htc_remove_interface(s
 	int ret = 0;
 	u8 cmd_rsp;
 
-	ath_print(common, ATH_DBG_CONFIG, "Detach Interface\n");
+	ath_dbg(common, ATH_DBG_CONFIG, "Detach Interface\n");
 
 	mutex_lock(&priv->mutex);
 	ath9k_htc_ps_wakeup(priv);
@@ -1386,30 +1199,46 @@ static int ath9k_htc_config(struct ieee8
 		mutex_unlock(&priv->htc_pm_lock);
 
 		if (enable_radio) {
-			ath_print(common, ATH_DBG_CONFIG,
-				  "not-idle: enabling radio\n");
+			ath_dbg(common, ATH_DBG_CONFIG,
+				"not-idle: enabling radio\n");
 			ath9k_htc_setpower(priv, ATH9K_PM_AWAKE);
 			ath9k_htc_radio_enable(hw);
 		}
 	}
 
+	/*
+	 * Monitor interface should be added before
+	 * IEEE80211_CONF_CHANGE_CHANNEL is handled.
+	 */
+	if (changed & IEEE80211_CONF_CHANGE_MONITOR) {
+		if (conf->flags & IEEE80211_CONF_MONITOR) {
+			if (ath9k_htc_add_monitor_interface(priv))
+				ath_err(common, "Failed to set monitor mode\n");
+			else
+				ath_dbg(common, ATH_DBG_CONFIG,
+					"HW opmode set to Monitor mode\n");
+		}
+	}
+
 	if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
 		struct ieee80211_channel *curchan = hw->conf.channel;
 		int pos = curchan->hw_value;
 
-		ath_print(common, ATH_DBG_CONFIG, "Set channel: %d MHz\n",
-			  curchan->center_freq);
+		ath_dbg(common, ATH_DBG_CONFIG, "Set channel: %d MHz\n",
+			curchan->center_freq);
 
-		ath9k_cmn_update_ichannel(hw, &priv->ah->channels[pos]);
+		ath9k_cmn_update_ichannel(&priv->ah->channels[pos],
+					  hw->conf.channel,
+					  hw->conf.channel_type);
 
 		if (ath9k_htc_set_channel(priv, hw, &priv->ah->channels[pos]) < 0) {
-			ath_print(common, ATH_DBG_FATAL,
-				  "Unable to set channel\n");
+			ath_err(common, "Unable to set channel\n");
 			mutex_unlock(&priv->mutex);
 			return -EINVAL;
 		}
 
 	}
+
 	if (changed & IEEE80211_CONF_CHANGE_PS) {
 		if (conf->flags & IEEE80211_CONF_PS) {
 			ath9k_htc_setpower(priv, ATH9K_PM_NETWORK_SLEEP);
@@ -1421,15 +1250,9 @@ static int ath9k_htc_config(struct ieee8
 		}
 	}
 
-	if (changed & IEEE80211_CONF_CHANGE_MONITOR) {
-		if (conf->flags & IEEE80211_CONF_MONITOR) {
-			if (ath9k_htc_add_monitor_interface(priv))
-				ath_print(common, ATH_DBG_FATAL,
-					  "Failed to set monitor mode\n");
-			else
-				ath_print(common, ATH_DBG_CONFIG,
-					  "HW opmode set to Monitor mode\n");
-		}
+	if (changed & IEEE80211_CONF_CHANGE_POWER) {
+		priv->txpowlimit = 2 * conf->power_level;
+		ath_update_txpow(priv);
 	}
 
 	if (changed & IEEE80211_CONF_CHANGE_IDLE) {
@@ -1440,8 +1263,8 @@ static int ath9k_htc_config(struct ieee8
 		}
 		mutex_unlock(&priv->htc_pm_lock);
 
-		ath_print(common, ATH_DBG_CONFIG,
-			  "idle: disabling radio\n");
+		ath_dbg(common, ATH_DBG_CONFIG,
+			"idle: disabling radio\n");
 		ath9k_htc_radio_disable(hw);
 	}
 
@@ -1478,8 +1301,8 @@ static void ath9k_htc_configure_filter(s
 	rfilt = ath9k_htc_calcrxfilter(priv);
 	ath9k_hw_setrxfilter(priv->ah, rfilt);
 
-	ath_print(ath9k_hw_common(priv->ah), ATH_DBG_CONFIG,
-		  "Set HW RX filter: 0x%x\n", rfilt);
+	ath_dbg(ath9k_hw_common(priv->ah), ATH_DBG_CONFIG,
+		"Set HW RX filter: 0x%x\n", rfilt);
 
 	ath9k_htc_ps_restore(priv);
 	mutex_unlock(&priv->mutex);
@@ -1542,15 +1365,14 @@ static int ath9k_htc_conf_tx(struct ieee
 
 	qnum = get_hw_qnum(queue, priv->hwq_map);
 
-	ath_print(common, ATH_DBG_CONFIG,
-		  "Configure tx [queue/hwq] [%d/%d],  "
-		  "aifs: %d, cw_min: %d, cw_max: %d, txop: %d\n",
-		  queue, qnum, params->aifs, params->cw_min,
-		  params->cw_max, params->txop);
+	ath_dbg(common, ATH_DBG_CONFIG,
+		"Configure tx [queue/hwq] [%d/%d],  aifs: %d, cw_min: %d, cw_max: %d, txop: %d\n",
+		queue, qnum, params->aifs, params->cw_min,
+		params->cw_max, params->txop);
 
 	ret = ath_htc_txq_update(priv, qnum, &qi);
 	if (ret) {
-		ath_print(common, ATH_DBG_FATAL, "TXQ Update failed\n");
+		ath_err(common, "TXQ Update failed\n");
 		goto out;
 	}
 
@@ -1578,7 +1400,7 @@ static int ath9k_htc_set_key(struct ieee
 		return -ENOSPC;
 
 	mutex_lock(&priv->mutex);
-	ath_print(common, ATH_DBG_CONFIG, "Set HW Key\n");
+	ath_dbg(common, ATH_DBG_CONFIG, "Set HW Key\n");
 	ath9k_htc_ps_wakeup(priv);
 
 	switch (cmd) {
@@ -1624,7 +1446,7 @@ static void ath9k_htc_bss_info_changed(s
 	if (changed & BSS_CHANGED_ASSOC) {
 		common->curaid = bss_conf->assoc ?
 				 bss_conf->aid : 0;
-		ath_print(common, ATH_DBG_CONFIG, "BSS Changed ASSOC %d\n",
+		ath_dbg(common, ATH_DBG_CONFIG, "BSS Changed ASSOC %d\n",
 			bss_conf->assoc);
 
 		if (bss_conf->assoc) {
@@ -1641,9 +1463,9 @@ static void ath9k_htc_bss_info_changed(s
 		memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN);
 		ath9k_hw_write_associd(ah);
 
-		ath_print(common, ATH_DBG_CONFIG,
-			  "BSSID: %pM aid: 0x%x\n",
-			  common->curbssid, common->curaid);
+		ath_dbg(common, ATH_DBG_CONFIG,
+			"BSSID: %pM aid: 0x%x\n",
+			common->curbssid, common->curaid);
 	}
 
 	if ((changed & BSS_CHANGED_BEACON_INT) ||
@@ -1661,8 +1483,8 @@ static void ath9k_htc_bss_info_changed(s
 	}
 
 	if (changed & BSS_CHANGED_ERP_PREAMBLE) {
-		ath_print(common, ATH_DBG_CONFIG, "BSS Changed PREAMBLE %d\n",
-			  bss_conf->use_short_preamble);
+		ath_dbg(common, ATH_DBG_CONFIG, "BSS Changed PREAMBLE %d\n",
+			bss_conf->use_short_preamble);
 		if (bss_conf->use_short_preamble)
 			priv->op_flags |= OP_PREAMBLE_SHORT;
 		else
@@ -1670,8 +1492,8 @@ static void ath9k_htc_bss_info_changed(s
 	}
 
 	if (changed & BSS_CHANGED_ERP_CTS_PROT) {
-		ath_print(common, ATH_DBG_CONFIG, "BSS Changed CTS PROT %d\n",
-			  bss_conf->use_cts_prot);
+		ath_dbg(common, ATH_DBG_CONFIG, "BSS Changed CTS PROT %d\n",
+			bss_conf->use_cts_prot);
 		if (bss_conf->use_cts_prot &&
 		    hw->conf.channel->band != IEEE80211_BAND_5GHZ)
 			priv->op_flags |= OP_PROTECT_ENABLE;
@@ -1762,8 +1584,7 @@ static int ath9k_htc_ampdu_action(struct
 		spin_unlock_bh(&priv->tx_lock);
 		break;
 	default:
-		ath_print(ath9k_hw_common(priv->ah), ATH_DBG_FATAL,
-			  "Unknown AMPDU action\n");
+		ath_err(ath9k_hw_common(priv->ah), "Unknown AMPDU action\n");
 	}
 
 	return ret;
@@ -1792,7 +1613,6 @@ static void ath9k_htc_sw_scan_complete(s
 	spin_lock_bh(&priv->beacon_lock);
 	priv->op_flags &= ~OP_SCANNING;
 	spin_unlock_bh(&priv->beacon_lock);
-	priv->op_flags |= OP_FULL_RESET;
 	if (priv->op_flags & OP_ASSOCIATED) {
 		ath9k_htc_beacon_config(priv, priv->vif);
 		ath_start_ani(priv);
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c	2011-03-14 21:20:32.000000000 -0400
@@ -20,8 +20,15 @@
 /* TX */
 /******/
 
+static const int subtype_txq_to_hwq[] = {
+	[WME_AC_BE] = ATH_TXQ_AC_BE,
+	[WME_AC_BK] = ATH_TXQ_AC_BK,
+	[WME_AC_VI] = ATH_TXQ_AC_VI,
+	[WME_AC_VO] = ATH_TXQ_AC_VO,
+};
+
 #define ATH9K_HTC_INIT_TXQ(subtype) do {			\
-		qi.tqi_subtype = subtype;			\
+		qi.tqi_subtype = subtype_txq_to_hwq[subtype];	\
 		qi.tqi_aifs = ATH9K_TXQ_USEDEFAULT;		\
 		qi.tqi_cwmin = ATH9K_TXQ_USEDEFAULT;		\
 		qi.tqi_cwmax = ATH9K_TXQ_USEDEFAULT;		\
@@ -62,8 +69,8 @@ int ath_htc_txq_update(struct ath9k_htc_
 	qi.tqi_readyTime = qinfo->tqi_readyTime;
 
 	if (!ath9k_hw_set_txq_props(ah, qnum, &qi)) {
-		ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL,
-			  "Unable to update hardware queue %u!\n", qnum);
+		ath_err(ath9k_hw_common(ah),
+			"Unable to update hardware queue %u!\n", qnum);
 		error = -EIO;
 	} else {
 		ath9k_hw_resettxqueue(ah, qnum);
@@ -106,6 +113,7 @@ int ath9k_htc_tx_start(struct ath9k_htc_
 
 	if (ieee80211_is_data(fc)) {
 		struct tx_frame_hdr tx_hdr;
+		u32 flags = 0;
 		u8 *qc;
 
 		memset(&tx_hdr, 0, sizeof(struct tx_frame_hdr));
@@ -129,13 +137,14 @@ int ath9k_htc_tx_start(struct ath9k_htc_
 		/* Check for RTS protection */
 		if (priv->hw->wiphy->rts_threshold != (u32) -1)
 			if (skb->len > priv->hw->wiphy->rts_threshold)
-				tx_hdr.flags |= ATH9K_HTC_TX_RTSCTS;
+				flags |= ATH9K_HTC_TX_RTSCTS;
 
 		/* CTS-to-self */
-		if (!(tx_hdr.flags & ATH9K_HTC_TX_RTSCTS) &&
+		if (!(flags & ATH9K_HTC_TX_RTSCTS) &&
 		    (priv->op_flags & OP_PROTECT_ENABLE))
-			tx_hdr.flags |= ATH9K_HTC_TX_CTSONLY;
+			flags |= ATH9K_HTC_TX_CTSONLY;
 
+		tx_hdr.flags = cpu_to_be32(flags);
 		tx_hdr.key_type = ath9k_cmn_get_hw_crypto_keytype(skb);
 		if (tx_hdr.key_type == ATH9K_KEY_TYPE_CLEAR)
 			tx_hdr.keyix = (u8) ATH9K_TXKEYIX_INVALID;
@@ -244,7 +253,7 @@ void ath9k_tx_tasklet(unsigned long data
 				ista = (struct ath9k_htc_sta *)sta->drv_priv;
 
 				if (ath9k_htc_check_tx_aggr(priv, ista, tid)) {
-					ieee80211_start_tx_ba_session(sta, tid);
+					ieee80211_start_tx_ba_session(sta, tid, 0);
 					spin_lock_bh(&priv->tx_lock);
 					ista->tid_state[tid] = AGGR_PROGRESS;
 					spin_unlock_bh(&priv->tx_lock);
@@ -263,8 +272,8 @@ void ath9k_tx_tasklet(unsigned long data
 	if (priv->tx_queues_stop) {
 		priv->tx_queues_stop = false;
 		spin_unlock_bh(&priv->tx_lock);
-		ath_print(ath9k_hw_common(priv->ah), ATH_DBG_XMIT,
-			  "Waking up TX queues\n");
+		ath_dbg(ath9k_hw_common(priv->ah), ATH_DBG_XMIT,
+			"Waking up TX queues\n");
 		ieee80211_wake_queues(priv->hw);
 		return;
 	}
@@ -289,8 +298,7 @@ void ath9k_htc_txep(void *drv_priv, stru
 		   (ep_id == priv->data_vo_ep)) {
 		skb_pull(skb, sizeof(struct tx_frame_hdr));
 	} else {
-		ath_print(common, ATH_DBG_FATAL,
-			  "Unsupported TX EPID: %d\n", ep_id);
+		ath_err(common, "Unsupported TX EPID: %d\n", ep_id);
 		dev_kfree_skb_any(skb);
 		return;
 	}
@@ -330,9 +338,8 @@ bool ath9k_htc_txq_setup(struct ath9k_ht
 		return false;
 
 	if (qnum >= ARRAY_SIZE(priv->hwq_map)) {
-		ath_print(common, ATH_DBG_FATAL,
-			  "qnum %u out of range, max %u!\n",
-			  qnum, (unsigned int)ARRAY_SIZE(priv->hwq_map));
+		ath_err(common, "qnum %u out of range, max %zu!\n",
+			qnum, ARRAY_SIZE(priv->hwq_map));
 		ath9k_hw_releasetxqueue(ah, qnum);
 		return false;
 	}
@@ -483,8 +490,7 @@ static bool ath9k_rx_prepare(struct ath9
 	__le16 fc;
 
 	if (skb->len <= HTC_RX_FRAME_HEADER_SIZE) {
-		ath_print(common, ATH_DBG_FATAL,
-			  "Corrupted RX frame, dropping\n");
+		ath_err(common, "Corrupted RX frame, dropping\n");
 		goto rx_next;
 	}
 
@@ -492,10 +498,9 @@ static bool ath9k_rx_prepare(struct ath9
 
 	if (be16_to_cpu(rxstatus->rs_datalen) -
 	    (skb->len - HTC_RX_FRAME_HEADER_SIZE) != 0) {
-		ath_print(common, ATH_DBG_FATAL,
-			  "Corrupted RX data len, dropping "
-			  "(dlen: %d, skblen: %d)\n",
-			  rxstatus->rs_datalen, skb->len);
+		ath_err(common,
+			"Corrupted RX data len, dropping (dlen: %d, skblen: %d)\n",
+			rxstatus->rs_datalen, skb->len);
 		goto rx_next;
 	}
 
@@ -678,8 +683,8 @@ void ath9k_htc_rxep(void *drv_priv, stru
 	spin_unlock(&priv->rx.rxbuflock);
 
 	if (rxbuf == NULL) {
-		ath_print(common, ATH_DBG_ANY,
-			  "No free RX buffer\n");
+		ath_dbg(common, ATH_DBG_ANY,
+			"No free RX buffer\n");
 		goto err;
 	}
 
@@ -721,8 +726,7 @@ int ath9k_rx_init(struct ath9k_htc_priv
 	for (i = 0; i < ATH9K_HTC_RXBUF; i++) {
 		rxbuf = kzalloc(sizeof(struct ath9k_htc_rxbuf), GFP_KERNEL);
 		if (rxbuf == NULL) {
-			ath_print(common, ATH_DBG_FATAL,
-				  "Unable to allocate RX buffers\n");
+			ath_err(common, "Unable to allocate RX buffers\n");
 			goto err;
 		}
 		list_add_tail(&rxbuf->list, &priv->rx.rxbuf);
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/htc.h linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/htc.h
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/htc.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/htc.h	2011-03-14 21:20:32.000000000 -0400
@@ -78,7 +78,7 @@ struct tx_frame_hdr {
 	u8 node_idx;
 	u8 vif_idx;
 	u8 tidno;
-	u32 flags; /* ATH9K_HTC_TX_* */
+	__be32 flags; /* ATH9K_HTC_TX_* */
 	u8 key_type;
 	u8 keyix;
 	u8 reserved[26];
@@ -331,17 +331,15 @@ void ath_htc_cancel_btcoex_work(struct a
 
 #define OP_INVALID		   BIT(0)
 #define OP_SCANNING		   BIT(1)
-#define OP_FULL_RESET		   BIT(2)
-#define OP_LED_ASSOCIATED	   BIT(3)
-#define OP_LED_ON		   BIT(4)
-#define OP_PREAMBLE_SHORT	   BIT(5)
-#define OP_PROTECT_ENABLE	   BIT(6)
-#define OP_ASSOCIATED		   BIT(7)
-#define OP_ENABLE_BEACON	   BIT(8)
-#define OP_LED_DEINIT		   BIT(9)
-#define OP_UNPLUGGED		   BIT(10)
-#define OP_BT_PRIORITY_DETECTED	   BIT(11)
-#define OP_BT_SCAN		   BIT(12)
+#define OP_LED_ASSOCIATED	   BIT(2)
+#define OP_LED_ON		   BIT(3)
+#define OP_PREAMBLE_SHORT	   BIT(4)
+#define OP_PROTECT_ENABLE	   BIT(5)
+#define OP_ASSOCIATED		   BIT(6)
+#define OP_ENABLE_BEACON	   BIT(7)
+#define OP_LED_DEINIT		   BIT(8)
+#define OP_BT_PRIORITY_DETECTED    BIT(9)
+#define OP_BT_SCAN                 BIT(10)
 
 struct ath9k_htc_priv {
 	struct device *dev;
@@ -368,7 +366,7 @@ struct ath9k_htc_priv {
 	u16 seq_no;
 	u32 bmiss_cnt;
 
-	struct ath9k_hw_cal_data caldata[38];
+	struct ath9k_hw_cal_data caldata[ATH9K_NUM_CHANNELS];
 
 	spinlock_t beacon_lock;
 
@@ -378,7 +376,7 @@ struct ath9k_htc_priv {
 	struct ieee80211_vif *vif;
 	struct htc_beacon_config cur_beacon_conf;
 	unsigned int rxfilter;
-	struct tasklet_struct wmi_tasklet;
+	struct tasklet_struct swba_tasklet;
 	struct tasklet_struct rx_tasklet;
 	struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS];
 	struct ath9k_htc_rx rx;
@@ -386,6 +384,7 @@ struct ath9k_htc_priv {
 	struct sk_buff_head tx_queue;
 	struct delayed_work ath9k_ani_work;
 	struct work_struct ps_work;
+	struct work_struct fatal_work;
 
 	struct mutex htc_pm_lock;
 	unsigned long ps_usecount;
@@ -420,6 +419,8 @@ static inline void ath_read_cachesize(st
 	common->bus_ops->read_cachesize(common, csz);
 }
 
+void ath9k_htc_reset(struct ath9k_htc_priv *priv);
+
 void ath9k_htc_beaconq_config(struct ath9k_htc_priv *priv);
 void ath9k_htc_beacon_config(struct ath9k_htc_priv *priv,
 			     struct ieee80211_vif *vif);
@@ -432,9 +433,11 @@ void ath9k_htc_txep(void *priv, struct s
 void ath9k_htc_beaconep(void *drv_priv, struct sk_buff *skb,
 			enum htc_endpoint_id ep_id, bool txok);
 
+int ath9k_htc_update_cap_target(struct ath9k_htc_priv *priv);
 void ath9k_htc_station_work(struct work_struct *work);
 void ath9k_htc_aggr_work(struct work_struct *work);
 void ath9k_ani_work(struct work_struct *work);;
+void ath_start_ani(struct ath9k_htc_priv *priv);
 
 int ath9k_tx_init(struct ath9k_htc_priv *priv);
 void ath9k_tx_tasklet(unsigned long data);
@@ -457,13 +460,18 @@ void ath9k_htc_ps_restore(struct ath9k_h
 void ath9k_ps_work(struct work_struct *work);
 bool ath9k_htc_setpower(struct ath9k_htc_priv *priv,
 			enum ath9k_power_mode mode);
+void ath_update_txpow(struct ath9k_htc_priv *priv);
 
 void ath9k_start_rfkill_poll(struct ath9k_htc_priv *priv);
+void ath9k_htc_rfkill_poll_state(struct ieee80211_hw *hw);
+void ath9k_htc_radio_enable(struct ieee80211_hw *hw);
+void ath9k_htc_radio_disable(struct ieee80211_hw *hw);
+void ath9k_led_stop_brightness(struct ath9k_htc_priv *priv);
 void ath9k_init_leds(struct ath9k_htc_priv *priv);
 void ath9k_deinit_leds(struct ath9k_htc_priv *priv);
 
 int ath9k_htc_probe_device(struct htc_target *htc_handle, struct device *dev,
-			   u16 devid, char *product);
+			   u16 devid, char *product, u32 drv_info);
 void ath9k_htc_disconnect_device(struct htc_target *htc_handle, bool hotunplug);
 #ifdef CONFIG_PM
 void ath9k_htc_suspend(struct htc_target *htc_handle);
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/htc_hst.c linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/htc_hst.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/htc_hst.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/htc_hst.c	2011-03-14 21:20:32.000000000 -0400
@@ -462,9 +462,10 @@ void ath9k_htc_hw_free(struct htc_target
 }
 
 int ath9k_htc_hw_init(struct htc_target *target,
-		      struct device *dev, u16 devid, char *product)
+		      struct device *dev, u16 devid,
+		      char *product, u32 drv_info)
 {
-	if (ath9k_htc_probe_device(target, dev, devid, product)) {
+	if (ath9k_htc_probe_device(target, dev, devid, product, drv_info)) {
 		printk(KERN_ERR "Failed to initialize the device\n");
 		return -ENODEV;
 	}
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/htc_hst.h linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/htc_hst.h
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/htc_hst.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/htc_hst.h	2011-03-14 21:20:32.000000000 -0400
@@ -77,20 +77,6 @@ struct htc_config_pipe_msg {
 	u8 credits;
 } __packed;
 
-struct htc_packet {
-	void *pktcontext;
-	u8 *buf;
-	u8 *buf_payload;
-	u32 buflen;
-	u32 payload_len;
-
-	int endpoint;
-	int status;
-
-	void *context;
-	u32 reserved;
-};
-
 struct htc_ep_callbacks {
 	void *priv;
 	void (*tx) (void *, struct sk_buff *, enum htc_endpoint_id, bool txok);
@@ -123,11 +109,6 @@ struct htc_endpoint {
 #define HTC_CONTROL_BUFFER_SIZE	\
 	(HTC_MAX_CONTROL_MESSAGE_LENGTH + sizeof(struct htc_frame_hdr))
 
-struct htc_control_buf {
-	struct htc_packet htc_pkt;
-	u8 buf[HTC_CONTROL_BUFFER_SIZE];
-};
-
 #define HTC_OP_START_WAIT           BIT(0)
 #define HTC_OP_CONFIG_PIPE_CREDITS  BIT(1)
 
@@ -239,7 +220,8 @@ struct htc_target *ath9k_htc_hw_alloc(vo
 				      struct device *dev);
 void ath9k_htc_hw_free(struct htc_target *htc);
 int ath9k_htc_hw_init(struct htc_target *target,
-		      struct device *dev, u16 devid, char *product);
+		      struct device *dev, u16 devid, char *product,
+		      u32 drv_info);
 void ath9k_htc_hw_deinit(struct htc_target *target, bool hot_unplug);
 
 #endif /* HTC_HST_H */
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/hw.c linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/hw.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/hw.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/hw.c	2011-03-14 21:20:32.000000000 -0400
@@ -54,13 +54,6 @@ static void ath9k_hw_init_mode_regs(stru
 	ath9k_hw_private_ops(ah)->init_mode_regs(ah);
 }
 
-static bool ath9k_hw_macversion_supported(struct ath_hw *ah)
-{
-	struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
-
-	return priv_ops->macversion_supported(ah->hw_version.macVersion);
-}
-
 static u32 ath9k_hw_compute_pll_control(struct ath_hw *ah,
 					struct ath9k_channel *chan)
 {
@@ -129,9 +122,9 @@ bool ath9k_hw_wait(struct ath_hw *ah, u3
 		udelay(AH_TIME_QUANTUM);
 	}
 
-	ath_print(ath9k_hw_common(ah), ATH_DBG_ANY,
-		  "timeout (%d us) on reg 0x%x: 0x%08x & 0x%08x != 0x%08x\n",
-		  timeout, reg, REG_READ(ah, reg), mask, val);
+	ath_dbg(ath9k_hw_common(ah), ATH_DBG_ANY,
+		"timeout (%d us) on reg 0x%x: 0x%08x & 0x%08x != 0x%08x\n",
+		timeout, reg, REG_READ(ah, reg), mask, val);
 
 	return false;
 }
@@ -211,8 +204,8 @@ u16 ath9k_hw_computetxtime(struct ath_hw
 		}
 		break;
 	default:
-		ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL,
-			  "Unknown phy %u (rate ix %u)\n", phy, rateix);
+		ath_err(ath9k_hw_common(ah),
+			"Unknown phy %u (rate ix %u)\n", phy, rateix);
 		txTime = 0;
 		break;
 	}
@@ -284,11 +277,9 @@ static void ath9k_hw_read_revisions(stru
 
 static void ath9k_hw_disablepcie(struct ath_hw *ah)
 {
-	if (AR_SREV_9100(ah))
+	if (!AR_SREV_5416(ah))
 		return;
 
-	ENABLE_REGWRITE_BUFFER(ah);
-
 	REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fc00);
 	REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924);
 	REG_WRITE(ah, AR_PCIE_SERDES, 0x28000029);
@@ -300,8 +291,6 @@ static void ath9k_hw_disablepcie(struct
 	REG_WRITE(ah, AR_PCIE_SERDES, 0x000e1007);
 
 	REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000);
-
-	REGWRITE_BUFFER_FLUSH(ah);
 }
 
 /* This should work for all families including legacy */
@@ -310,10 +299,9 @@ static bool ath9k_hw_chip_test(struct at
 	struct ath_common *common = ath9k_hw_common(ah);
 	u32 regAddr[2] = { AR_STA_ID0 };
 	u32 regHold[2];
-	u32 patternData[4] = { 0x55555555,
-			       0xaaaaaaaa,
-			       0x66666666,
-			       0x99999999 };
+	static const u32 patternData[4] = {
+		0x55555555, 0xaaaaaaaa, 0x66666666, 0x99999999
+	};
 	int i, j, loop_max;
 
 	if (!AR_SREV_9300_20_OR_LATER(ah)) {
@@ -332,11 +320,9 @@ static bool ath9k_hw_chip_test(struct at
 			REG_WRITE(ah, addr, wrData);
 			rdData = REG_READ(ah, addr);
 			if (rdData != wrData) {
-				ath_print(common, ATH_DBG_FATAL,
-					  "address test failed "
-					  "addr: 0x%08x - wr:0x%08x != "
-					  "rd:0x%08x\n",
-					  addr, wrData, rdData);
+				ath_err(common,
+					"address test failed addr: 0x%08x - wr:0x%08x != rd:0x%08x\n",
+					addr, wrData, rdData);
 				return false;
 			}
 		}
@@ -345,11 +331,9 @@ static bool ath9k_hw_chip_test(struct at
 			REG_WRITE(ah, addr, wrData);
 			rdData = REG_READ(ah, addr);
 			if (wrData != rdData) {
-				ath_print(common, ATH_DBG_FATAL,
-					  "address test failed "
-					  "addr: 0x%08x - wr:0x%08x != "
-					  "rd:0x%08x\n",
-					  addr, wrData, rdData);
+				ath_err(common,
+					"address test failed addr: 0x%08x - wr:0x%08x != rd:0x%08x\n",
+					addr, wrData, rdData);
 				return false;
 			}
 		}
@@ -385,6 +369,9 @@ static void ath9k_hw_init_config(struct
 	else
 		ah->config.ht_enable = 0;
 
+	/* PAPRD needs some more work to be enabled */
+	ah->config.paprd_disable = 1;
+
 	ah->config.rx_intr_mitigation = true;
 	ah->config.pcieSerDesWrite = true;
 
@@ -419,17 +406,12 @@ static void ath9k_hw_init_defaults(struc
 	ah->hw_version.magic = AR5416_MAGIC;
 	ah->hw_version.subvendorid = 0;
 
-	ah->ah_flags = 0;
-	if (!AR_SREV_9100(ah))
-		ah->ah_flags = AH_USE_EEPROM;
-
 	ah->atim_window = 0;
 	ah->sta_id1_defaults =
 		AR_STA_ID1_CRPT_MIC_ENABLE |
 		AR_STA_ID1_MCAST_KSRCH;
-	ah->beacon_interval = 100;
 	ah->enable_32kHz_clock = DONT_USE_32KHZ;
-	ah->slottime = (u32) -1;
+	ah->slottime = 20;
 	ah->globaltxtimeout = (u32) -1;
 	ah->power_mode = ATH9K_PM_UNDEFINED;
 }
@@ -440,7 +422,7 @@ static int ath9k_hw_init_macaddr(struct
 	u32 sum;
 	int i;
 	u16 eeval;
-	u32 EEP_MAC[] = { EEP_MAC_LSW, EEP_MAC_MID, EEP_MAC_MSW };
+	static const u32 EEP_MAC[] = { EEP_MAC_LSW, EEP_MAC_MID, EEP_MAC_MSW };
 
 	sum = 0;
 	for (i = 0; i < 3; i++) {
@@ -457,9 +439,10 @@ static int ath9k_hw_init_macaddr(struct
 
 static int ath9k_hw_post_init(struct ath_hw *ah)
 {
+	struct ath_common *common = ath9k_hw_common(ah);
 	int ecode;
 
-	if (!AR_SREV_9271(ah)) {
+	if (common->bus_ops->ath_bus_type != ATH_USB) {
 		if (!ath9k_hw_chip_test(ah))
 			return -ENODEV;
 	}
@@ -474,16 +457,15 @@ static int ath9k_hw_post_init(struct ath
 	if (ecode != 0)
 		return ecode;
 
-	ath_print(ath9k_hw_common(ah), ATH_DBG_CONFIG,
-		  "Eeprom VER: %d, REV: %d\n",
-		  ah->eep_ops->get_eeprom_ver(ah),
-		  ah->eep_ops->get_eeprom_rev(ah));
+	ath_dbg(ath9k_hw_common(ah), ATH_DBG_CONFIG,
+		"Eeprom VER: %d, REV: %d\n",
+		ah->eep_ops->get_eeprom_ver(ah),
+		ah->eep_ops->get_eeprom_rev(ah));
 
 	ecode = ath9k_hw_rf_alloc_ext_banks(ah);
 	if (ecode) {
-		ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL,
-			  "Failed allocating banks for "
-			  "external radio\n");
+		ath_err(ath9k_hw_common(ah),
+			"Failed allocating banks for external radio\n");
 		ath9k_hw_rf_free_ext_banks(ah);
 		return ecode;
 	}
@@ -514,8 +496,7 @@ static int __ath9k_hw_init(struct ath_hw
 		ah->hw_version.macVersion = AR_SREV_VERSION_9100;
 
 	if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_POWER_ON)) {
-		ath_print(common, ATH_DBG_FATAL,
-			  "Couldn't reset chip\n");
+		ath_err(common, "Couldn't reset chip\n");
 		return -EIO;
 	}
 
@@ -525,7 +506,7 @@ static int __ath9k_hw_init(struct ath_hw
 	ath9k_hw_attach_ops(ah);
 
 	if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) {
-		ath_print(common, ATH_DBG_FATAL, "Couldn't wakeup chip\n");
+		ath_err(common, "Couldn't wakeup chip\n");
 		return -EIO;
 	}
 
@@ -541,7 +522,7 @@ static int __ath9k_hw_init(struct ath_hw
 		}
 	}
 
-	ath_print(common, ATH_DBG_RESET, "serialize_regmode is %d\n",
+	ath_dbg(common, ATH_DBG_RESET, "serialize_regmode is %d\n",
 		ah->config.serialize_regmode);
 
 	if (AR_SREV_9285(ah) || AR_SREV_9271(ah))
@@ -549,11 +530,22 @@ static int __ath9k_hw_init(struct ath_hw
 	else
 		ah->config.max_txtrig_level = MAX_TX_FIFO_THRESHOLD;
 
-	if (!ath9k_hw_macversion_supported(ah)) {
-		ath_print(common, ATH_DBG_FATAL,
-			  "Mac Chip Rev 0x%02x.%x is not supported by "
-			  "this driver\n", ah->hw_version.macVersion,
-			  ah->hw_version.macRev);
+	switch (ah->hw_version.macVersion) {
+	case AR_SREV_VERSION_5416_PCI:
+	case AR_SREV_VERSION_5416_PCIE:
+	case AR_SREV_VERSION_9160:
+	case AR_SREV_VERSION_9100:
+	case AR_SREV_VERSION_9280:
+	case AR_SREV_VERSION_9285:
+	case AR_SREV_VERSION_9287:
+	case AR_SREV_VERSION_9271:
+	case AR_SREV_VERSION_9300:
+	case AR_SREV_VERSION_9485:
+		break;
+	default:
+		ath_err(common,
+			"Mac Chip Rev 0x%02x.%x is not supported by this driver\n",
+			ah->hw_version.macVersion, ah->hw_version.macRev);
 		return -EOPNOTSUPP;
 	}
 
@@ -599,8 +591,7 @@ static int __ath9k_hw_init(struct ath_hw
 
 	r = ath9k_hw_init_macaddr(ah);
 	if (r) {
-		ath_print(common, ATH_DBG_FATAL,
-			  "Failed to initialize MAC address\n");
+		ath_err(common, "Failed to initialize MAC address\n");
 		return r;
 	}
 
@@ -634,21 +625,21 @@ int ath9k_hw_init(struct ath_hw *ah)
 	case AR9287_DEVID_PCIE:
 	case AR2427_DEVID_PCIE:
 	case AR9300_DEVID_PCIE:
+	case AR9300_DEVID_AR9485_PCIE:
 		break;
 	default:
 		if (common->bus_ops->ath_bus_type == ATH_USB)
 			break;
-		ath_print(common, ATH_DBG_FATAL,
-			  "Hardware device ID 0x%04x not supported\n",
-			  ah->hw_version.devid);
+		ath_err(common, "Hardware device ID 0x%04x not supported\n",
+			ah->hw_version.devid);
 		return -EOPNOTSUPP;
 	}
 
 	ret = __ath9k_hw_init(ah);
 	if (ret) {
-		ath_print(common, ATH_DBG_FATAL,
-			  "Unable to initialize hardware; "
-			  "initialization status: %d\n", ret);
+		ath_err(common,
+			"Unable to initialize hardware; initialization status: %d\n",
+			ret);
 		return ret;
 	}
 
@@ -680,7 +671,12 @@ static void ath9k_hw_init_qos(struct ath
 static void ath9k_hw_init_pll(struct ath_hw *ah,
 			      struct ath9k_channel *chan)
 {
-	u32 pll = ath9k_hw_compute_pll_control(ah, chan);
+	u32 pll;
+
+	if (AR_SREV_9485(ah))
+		REG_WRITE(ah, AR_RTC_PLL_CONTROL2, 0x886666);
+
+	pll = ath9k_hw_compute_pll_control(ah, chan);
 
 	REG_WRITE(ah, AR_RTC_PLL_CONTROL, pll);
 
@@ -772,8 +768,8 @@ static void ath9k_hw_set_cts_timeout(str
 static bool ath9k_hw_set_global_txtimeout(struct ath_hw *ah, u32 tu)
 {
 	if (tu > 0xFFFF) {
-		ath_print(ath9k_hw_common(ah), ATH_DBG_XMIT,
-			  "bad global tx timeout %u\n", tu);
+		ath_dbg(ath9k_hw_common(ah), ATH_DBG_XMIT,
+			"bad global tx timeout %u\n", tu);
 		ah->globaltxtimeout = (u32) -1;
 		return false;
 	} else {
@@ -790,8 +786,8 @@ void ath9k_hw_init_global_settings(struc
 	int slottime;
 	int sifstime;
 
-	ath_print(ath9k_hw_common(ah), ATH_DBG_RESET, "ah->misc_mode 0x%x\n",
-		  ah->misc_mode);
+	ath_dbg(ath9k_hw_common(ah), ATH_DBG_RESET, "ah->misc_mode 0x%x\n",
+		ah->misc_mode);
 
 	if (ah->misc_mode != 0)
 		REG_WRITE(ah, AR_PCU_MISC,
@@ -816,7 +812,7 @@ void ath9k_hw_init_global_settings(struc
 	if (conf->channel && conf->channel->band == IEEE80211_BAND_2GHZ)
 		acktimeout += 64 - sifstime - ah->slottime;
 
-	ath9k_hw_setslottime(ah, slottime);
+	ath9k_hw_setslottime(ah, ah->slottime);
 	ath9k_hw_set_ack_timeout(ah, acktimeout);
 	ath9k_hw_set_cts_timeout(ah, acktimeout);
 	if (ah->globaltxtimeout != (u32) -1)
@@ -1034,8 +1030,8 @@ static bool ath9k_hw_set_reset(struct at
 
 	REG_WRITE(ah, AR_RTC_RC, 0);
 	if (!ath9k_hw_wait(ah, AR_RTC_RC, AR_RTC_RC_M, 0, AH_WAIT_TIMEOUT)) {
-		ath_print(ath9k_hw_common(ah), ATH_DBG_RESET,
-			  "RTC stuck in MAC reset\n");
+		ath_dbg(ath9k_hw_common(ah), ATH_DBG_RESET,
+			"RTC stuck in MAC reset\n");
 		return false;
 	}
 
@@ -1081,8 +1077,8 @@ static bool ath9k_hw_set_reset_power_on(
 			   AR_RTC_STATUS_M,
 			   AR_RTC_STATUS_ON,
 			   AH_WAIT_TIMEOUT)) {
-		ath_print(ath9k_hw_common(ah), ATH_DBG_RESET,
-			  "RTC not waking up\n");
+		ath_dbg(ath9k_hw_common(ah), ATH_DBG_RESET,
+			"RTC not waking up\n");
 		return false;
 	}
 
@@ -1142,16 +1138,14 @@ static bool ath9k_hw_channel_change(stru
 
 	for (qnum = 0; qnum < AR_NUM_QCU; qnum++) {
 		if (ath9k_hw_numtxpending(ah, qnum)) {
-			ath_print(common, ATH_DBG_QUEUE,
-				  "Transmit frames pending on "
-				  "queue %d\n", qnum);
+			ath_dbg(common, ATH_DBG_QUEUE,
+				"Transmit frames pending on queue %d\n", qnum);
 			return false;
 		}
 	}
 
 	if (!ath9k_hw_rfbus_req(ah)) {
-		ath_print(common, ATH_DBG_FATAL,
-			  "Could not kill baseband RX\n");
+		ath_err(common, "Could not kill baseband RX\n");
 		return false;
 	}
 
@@ -1159,8 +1153,7 @@ static bool ath9k_hw_channel_change(stru
 
 	r = ath9k_hw_rf_set_freq(ah, chan);
 	if (r) {
-		ath_print(common, ATH_DBG_FATAL,
-			  "Failed to set channel\n");
+		ath_err(common, "Failed to set channel\n");
 		return false;
 	}
 	ath9k_hw_set_clockrate(ah);
@@ -1170,7 +1163,7 @@ static bool ath9k_hw_channel_change(stru
 			     channel->max_antenna_gain * 2,
 			     channel->max_power * 2,
 			     min((u32) MAX_RATE_POWER,
-			     (u32) regulatory->power_limit));
+			     (u32) regulatory->power_limit), false);
 
 	ath9k_hw_rfbus_done(ah);
 
@@ -1224,10 +1217,10 @@ int ath9k_hw_reset(struct ath_hw *ah, st
 	ah->txchainmask = common->tx_chainmask;
 	ah->rxchainmask = common->rx_chainmask;
 
-	if (!ah->chip_fullsleep) {
+	if ((common->bus_ops->ath_bus_type != ATH_USB) && !ah->chip_fullsleep) {
 		ath9k_hw_abortpcurecv(ah);
 		if (!ath9k_hw_stopdmarecv(ah)) {
-			ath_print(common, ATH_DBG_XMIT,
+			ath_dbg(common, ATH_DBG_XMIT,
 				"Failed to stop receive dma\n");
 			bChannelChange = false;
 		}
@@ -1283,6 +1276,8 @@ int ath9k_hw_reset(struct ath_hw *ah, st
 
 	ath9k_hw_mark_phy_inactive(ah);
 
+	ah->paprd_table_write_done = false;
+
 	/* Only required on the first reset */
 	if (AR_SREV_9271(ah) && ah->htc_reset_init) {
 		REG_WRITE(ah,
@@ -1292,7 +1287,7 @@ int ath9k_hw_reset(struct ath_hw *ah, st
 	}
 
 	if (!ath9k_hw_chip_reset(ah, chan)) {
-		ath_print(common, ATH_DBG_FATAL, "Chip reset failed\n");
+		ath_err(common, "Chip reset failed\n");
 		return -EINVAL;
 	}
 
@@ -1394,7 +1389,7 @@ int ath9k_hw_reset(struct ath_hw *ah, st
 	ath9k_hw_init_qos(ah);
 
 	if (ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT)
-		ath9k_enable_rfkill(ah);
+		ath9k_hw_cfg_gpio_input(ah, ah->rfkill_gpio);
 
 	ath9k_hw_init_global_settings(ah);
 
@@ -1439,13 +1434,13 @@ int ath9k_hw_reset(struct ath_hw *ah, st
 		u32 mask;
 		mask = REG_READ(ah, AR_CFG);
 		if (mask & (AR_CFG_SWRB | AR_CFG_SWTB | AR_CFG_SWRG)) {
-			ath_print(common, ATH_DBG_RESET,
+			ath_dbg(common, ATH_DBG_RESET,
 				"CFG Byte Swap Set 0x%x\n", mask);
 		} else {
 			mask =
 				INIT_CONFIG_STATUS | AR_CFG_SWRB | AR_CFG_SWTB;
 			REG_WRITE(ah, AR_CFG, mask);
-			ath_print(common, ATH_DBG_RESET,
+			ath_dbg(common, ATH_DBG_RESET,
 				"Setting CFG 0x%x\n", REG_READ(ah, AR_CFG));
 		}
 	} else {
@@ -1573,9 +1568,9 @@ static bool ath9k_hw_set_power_awake(str
 				    AR_RTC_FORCE_WAKE_EN);
 		}
 		if (i == 0) {
-			ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL,
-				  "Failed to wakeup in %uus\n",
-				  POWER_UP_TIME / 20);
+			ath_err(ath9k_hw_common(ah),
+				"Failed to wakeup in %uus\n",
+				POWER_UP_TIME / 20);
 			return false;
 		}
 	}
@@ -1599,8 +1594,8 @@ bool ath9k_hw_setpower(struct ath_hw *ah
 	if (ah->power_mode == mode)
 		return status;
 
-	ath_print(common, ATH_DBG_RESET, "%s -> %s\n",
-		  modes[ah->power_mode], modes[mode]);
+	ath_dbg(common, ATH_DBG_RESET, "%s -> %s\n",
+		modes[ah->power_mode], modes[mode]);
 
 	switch (mode) {
 	case ATH9K_PM_AWAKE:
@@ -1614,12 +1609,20 @@ bool ath9k_hw_setpower(struct ath_hw *ah
 		ath9k_set_power_network_sleep(ah, setChip);
 		break;
 	default:
-		ath_print(common, ATH_DBG_FATAL,
-			  "Unknown power mode %u\n", mode);
+		ath_err(common, "Unknown power mode %u\n", mode);
 		return false;
 	}
 	ah->power_mode = mode;
 
+	/*
+	 * XXX: If this warning never comes up after a while then
+	 * simply keep the ATH_DBG_WARN_ON_ONCE() but make
+	 * ath9k_hw_setpower() return type void.
+	 */
+
+	if (!(ah->ah_flags & AH_UNPLUGGED))
+		ATH_DBG_WARN_ON_ONCE(!status);
+
 	return status;
 }
 EXPORT_SYMBOL(ath9k_hw_setpower);
@@ -1632,17 +1635,9 @@ void ath9k_hw_beaconinit(struct ath_hw *
 {
 	int flags = 0;
 
-	ah->beacon_interval = beacon_period;
-
 	ENABLE_REGWRITE_BUFFER(ah);
 
 	switch (ah->opmode) {
-	case NL80211_IFTYPE_STATION:
-		REG_WRITE(ah, AR_NEXT_TBTT_TIMER, TU_TO_USEC(next_beacon));
-		REG_WRITE(ah, AR_NEXT_DMA_BEACON_ALERT, 0xffff);
-		REG_WRITE(ah, AR_NEXT_SWBA, 0x7ffff);
-		flags |= AR_TBTT_TIMER_EN;
-		break;
 	case NL80211_IFTYPE_ADHOC:
 	case NL80211_IFTYPE_MESH_POINT:
 		REG_SET_BIT(ah, AR_TXCFG,
@@ -1666,17 +1661,9 @@ void ath9k_hw_beaconinit(struct ath_hw *
 			AR_TBTT_TIMER_EN | AR_DBA_TIMER_EN | AR_SWBA_TIMER_EN;
 		break;
 	default:
-		if (ah->is_monitoring) {
-			REG_WRITE(ah, AR_NEXT_TBTT_TIMER,
-					TU_TO_USEC(next_beacon));
-			REG_WRITE(ah, AR_NEXT_DMA_BEACON_ALERT, 0xffff);
-			REG_WRITE(ah, AR_NEXT_SWBA, 0x7ffff);
-			flags |= AR_TBTT_TIMER_EN;
-			break;
-		}
-		ath_print(ath9k_hw_common(ah), ATH_DBG_BEACON,
-			  "%s: unsupported opmode: %d\n",
-			  __func__, ah->opmode);
+		ath_dbg(ath9k_hw_common(ah), ATH_DBG_BEACON,
+			"%s: unsupported opmode: %d\n",
+			__func__, ah->opmode);
 		return;
 		break;
 	}
@@ -1732,10 +1719,10 @@ void ath9k_hw_set_sta_beacon_timers(stru
 	else
 		nextTbtt = bs->bs_nexttbtt;
 
-	ath_print(common, ATH_DBG_BEACON, "next DTIM %d\n", bs->bs_nextdtim);
-	ath_print(common, ATH_DBG_BEACON, "next beacon %d\n", nextTbtt);
-	ath_print(common, ATH_DBG_BEACON, "beacon period %d\n", beaconintval);
-	ath_print(common, ATH_DBG_BEACON, "DTIM period %d\n", dtimperiod);
+	ath_dbg(common, ATH_DBG_BEACON, "next DTIM %d\n", bs->bs_nextdtim);
+	ath_dbg(common, ATH_DBG_BEACON, "next beacon %d\n", nextTbtt);
+	ath_dbg(common, ATH_DBG_BEACON, "beacon period %d\n", beaconintval);
+	ath_dbg(common, ATH_DBG_BEACON, "DTIM period %d\n", dtimperiod);
 
 	ENABLE_REGWRITE_BUFFER(ah);
 
@@ -1781,7 +1768,7 @@ int ath9k_hw_fill_cap_info(struct ath_hw
 	struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw;
 
 	u16 capField = 0, eeval;
-	u8 ant_div_ctl1;
+	u8 ant_div_ctl1, tx_chainmask, rx_chainmask;
 
 	eeval = ah->eep_ops->get_eeprom(ah, EEP_REG_0);
 	regulatory->current_rd = eeval;
@@ -1800,14 +1787,14 @@ int ath9k_hw_fill_cap_info(struct ath_hw
 			regulatory->current_rd += 5;
 		else if (regulatory->current_rd == 0x41)
 			regulatory->current_rd = 0x43;
-		ath_print(common, ATH_DBG_REGULATORY,
-			  "regdomain mapped to 0x%x\n", regulatory->current_rd);
+		ath_dbg(common, ATH_DBG_REGULATORY,
+			"regdomain mapped to 0x%x\n", regulatory->current_rd);
 	}
 
 	eeval = ah->eep_ops->get_eeprom(ah, EEP_OP_MODE);
 	if ((eeval & (AR5416_OPFLAGS_11G | AR5416_OPFLAGS_11A)) == 0) {
-		ath_print(common, ATH_DBG_FATAL,
-			  "no band has been marked as supported in EEPROM.\n");
+		ath_err(common,
+			"no band has been marked as supported in EEPROM\n");
 		return -EINVAL;
 	}
 
@@ -1833,6 +1820,10 @@ int ath9k_hw_fill_cap_info(struct ath_hw
 
 	ah->misc_mode |= AR_PCU_MIC_NEW_LOC_ENA;
 
+	/* enable key search for every frame in an aggregate */
+	if (AR_SREV_9300_20_OR_LATER(ah))
+		ah->misc_mode |= AR_PCU_ALWAYS_PERFORM_KEYSEARCH;
+
 	pCap->low_2ghz_chan = 2312;
 	pCap->high_2ghz_chan = 2732;
 
@@ -1921,13 +1912,7 @@ int ath9k_hw_fill_cap_info(struct ath_hw
 	    AR_SREV_5416(ah))
 		pCap->reg_cap |= AR_EEPROM_EEREGCAP_EN_FCC_MIDBAND;
 
-	pCap->num_antcfg_5ghz =
-		ah->eep_ops->get_num_ant_config(ah, ATH9K_HAL_FREQ_BAND_5GHZ);
-	pCap->num_antcfg_2ghz =
-		ah->eep_ops->get_num_ant_config(ah, ATH9K_HAL_FREQ_BAND_2GHZ);
-
-	if (AR_SREV_9280_20_OR_LATER(ah) &&
-	    ath9k_hw_btcoex_supported(ah)) {
+	if (AR_SREV_9280_20_OR_LATER(ah) && common->btcoex_enabled) {
 		btcoex_hw->btactive_gpio = ATH_BTACTIVE_GPIO;
 		btcoex_hw->wlanactive_gpio = ATH_WLANACTIVE_GPIO;
 
@@ -1942,14 +1927,17 @@ int ath9k_hw_fill_cap_info(struct ath_hw
 	}
 
 	if (AR_SREV_9300_20_OR_LATER(ah)) {
-		pCap->hw_caps |= ATH9K_HW_CAP_EDMA | ATH9K_HW_CAP_LDPC |
-				 ATH9K_HW_CAP_FASTCLOCK;
+		pCap->hw_caps |= ATH9K_HW_CAP_EDMA | ATH9K_HW_CAP_FASTCLOCK;
+		if (!AR_SREV_9485(ah))
+			pCap->hw_caps |= ATH9K_HW_CAP_LDPC;
+
 		pCap->rx_hp_qdepth = ATH9K_HW_RX_HP_QDEPTH;
 		pCap->rx_lp_qdepth = ATH9K_HW_RX_LP_QDEPTH;
 		pCap->rx_status_len = sizeof(struct ar9003_rxs);
 		pCap->tx_desc_len = sizeof(struct ar9003_txc);
 		pCap->txs_len = sizeof(struct ar9003_txs);
-		if (ah->eep_ops->get_eeprom(ah, EEP_PAPRD))
+		if (!ah->config.paprd_disable &&
+		    ah->eep_ops->get_eeprom(ah, EEP_PAPRD))
 			pCap->hw_caps |= ATH9K_HW_CAP_PAPRD;
 	} else {
 		pCap->tx_desc_len = sizeof(struct ath_desc);
@@ -1963,6 +1951,9 @@ int ath9k_hw_fill_cap_info(struct ath_hw
 	if (AR_SREV_9300_20_OR_LATER(ah))
 		pCap->hw_caps |= ATH9K_HW_CAP_RAC_SUPPORTED;
 
+	if (AR_SREV_9300_20_OR_LATER(ah))
+		ah->ent_mode = REG_READ(ah, AR_ENT_OTP);
+
 	if (AR_SREV_9287_11_OR_LATER(ah) || AR_SREV_9271(ah))
 		pCap->hw_caps |= ATH9K_HW_CAP_SGI_20;
 
@@ -1973,6 +1964,29 @@ int ath9k_hw_fill_cap_info(struct ath_hw
 			if ((ant_div_ctl1 & 0x1) && ((ant_div_ctl1 >> 3) & 0x1))
 				pCap->hw_caps |= ATH9K_HW_CAP_ANT_DIV_COMB;
 		}
+	if (AR_SREV_9300_20_OR_LATER(ah)) {
+		if (ah->eep_ops->get_eeprom(ah, EEP_CHAIN_MASK_REDUCE))
+			pCap->hw_caps |= ATH9K_HW_CAP_APM;
+	}
+
+
+
+	if (AR_SREV_9485_10(ah)) {
+		pCap->pcie_lcr_extsync_en = true;
+		pCap->pcie_lcr_offset = 0x80;
+	}
+
+	tx_chainmask = pCap->tx_chainmask;
+	rx_chainmask = pCap->rx_chainmask;
+	while (tx_chainmask || rx_chainmask) {
+		if (tx_chainmask & BIT(0))
+			pCap->max_txchains++;
+		if (rx_chainmask & BIT(0))
+			pCap->max_rxchains++;
+
+		tx_chainmask >>= 1;
+		rx_chainmask >>= 1;
+	}
 
 	return 0;
 }
@@ -2177,7 +2191,7 @@ bool ath9k_hw_disable(struct ath_hw *ah)
 }
 EXPORT_SYMBOL(ath9k_hw_disable);
 
-void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit)
+void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit, bool test)
 {
 	struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
 	struct ath9k_channel *chan = ah->curchan;
@@ -2190,7 +2204,7 @@ void ath9k_hw_set_txpowerlimit(struct at
 				 channel->max_antenna_gain * 2,
 				 channel->max_power * 2,
 				 min((u32) MAX_RATE_POWER,
-				 (u32) regulatory->power_limit));
+				 (u32) regulatory->power_limit), test);
 }
 EXPORT_SYMBOL(ath9k_hw_set_txpowerlimit);
 
@@ -2250,8 +2264,8 @@ void ath9k_hw_reset_tsf(struct ath_hw *a
 {
 	if (!ath9k_hw_wait(ah, AR_SLP32_MODE, AR_SLP32_TSF_WRITE_STATUS, 0,
 			   AH_TSF_WRITE_TIMEOUT))
-		ath_print(ath9k_hw_common(ah), ATH_DBG_RESET,
-			  "AR_SLP32_TSF_WRITE_STATUS limit exceeded\n");
+		ath_dbg(ath9k_hw_common(ah), ATH_DBG_RESET,
+			"AR_SLP32_TSF_WRITE_STATUS limit exceeded\n");
 
 	REG_WRITE(ah, AR_RESET_TSF, AR_RESET_TSF_ONCE);
 }
@@ -2324,11 +2338,10 @@ static u32 rightmost_index(struct ath_ge
 	return timer_table->gen_timer_index[b];
 }
 
-u32 ath9k_hw_gettsf32(struct ath_hw *ah)
+static u32 ath9k_hw_gettsf32(struct ath_hw *ah)
 {
 	return REG_READ(ah, AR_TSF_L32);
 }
-EXPORT_SYMBOL(ath9k_hw_gettsf32);
 
 struct ath_gen_timer *ath_gen_timer_alloc(struct ath_hw *ah,
 					  void (*trigger)(void *),
@@ -2342,9 +2355,9 @@ struct ath_gen_timer *ath_gen_timer_allo
 	timer = kzalloc(sizeof(struct ath_gen_timer), GFP_KERNEL);
 
 	if (timer == NULL) {
-		ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL,
-			  "Failed to allocate memory"
-			  "for hw timer[%d]\n", timer_index);
+		ath_err(ath9k_hw_common(ah),
+			"Failed to allocate memory for hw timer[%d]\n",
+			timer_index);
 		return NULL;
 	}
 
@@ -2373,9 +2386,9 @@ void ath9k_hw_gen_timer_start(struct ath
 
 	tsf = ath9k_hw_gettsf32(ah);
 
-	ath_print(ath9k_hw_common(ah), ATH_DBG_HWTIMER,
-		  "curent tsf %x period %x"
-		  "timer_next %x\n", tsf, timer_period, timer_next);
+	ath_dbg(ath9k_hw_common(ah), ATH_DBG_HWTIMER,
+		"current tsf %x period %x timer_next %x\n",
+		tsf, timer_period, timer_next);
 
 	/*
 	 * Pull timer_next forward if the current TSF already passed it
@@ -2455,8 +2468,8 @@ void ath_gen_timer_isr(struct ath_hw *ah
 		index = rightmost_index(timer_table, &thresh_mask);
 		timer = timer_table->timers[index];
 		BUG_ON(!timer);
-		ath_print(common, ATH_DBG_HWTIMER,
-			  "TSF overflow for Gen timer %d\n", index);
+		ath_dbg(common, ATH_DBG_HWTIMER,
+			"TSF overflow for Gen timer %d\n", index);
 		timer->overflow(timer->arg);
 	}
 
@@ -2464,8 +2477,8 @@ void ath_gen_timer_isr(struct ath_hw *ah
 		index = rightmost_index(timer_table, &trigger_mask);
 		timer = timer_table->timers[index];
 		BUG_ON(!timer);
-		ath_print(common, ATH_DBG_HWTIMER,
-			  "Gen timer[%d] trigger\n", index);
+		ath_dbg(common, ATH_DBG_HWTIMER,
+			"Gen timer[%d] trigger\n", index);
 		timer->trigger(timer->arg);
 	}
 }
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/hw.h linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/hw.h
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/hw.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/hw.h	2011-03-14 21:20:32.000000000 -0400
@@ -30,7 +30,6 @@
 #include "btcoex.h"
 
 #include "../regd.h"
-#include "../debug.h"
 
 #define ATHEROS_VENDOR_ID	0x168c
 
@@ -44,6 +43,7 @@
 #define AR9287_DEVID_PCI	0x002d
 #define AR9287_DEVID_PCIE	0x002e
 #define AR9300_DEVID_PCIE	0x0030
+#define AR9300_DEVID_AR9485_PCIE 0x0032
 
 #define AR5416_AR9100_DEVID	0x000b
 
@@ -157,6 +157,13 @@
 #define PAPRD_GAIN_TABLE_ENTRIES    32
 #define PAPRD_TABLE_SZ              24
 
+enum ath_hw_txq_subtype {
+	ATH_TXQ_AC_BE = 0,
+	ATH_TXQ_AC_BK = 1,
+	ATH_TXQ_AC_VI = 2,
+	ATH_TXQ_AC_VO = 3,
+};
+
 enum ath_ini_subsys {
 	ATH_INI_PRE = 0,
 	ATH_INI_CORE,
@@ -180,6 +187,7 @@ enum ath9k_hw_caps {
 	ATH9K_HW_CAP_ANT_DIV_COMB		= BIT(12),
 	ATH9K_HW_CAP_2GHZ			= BIT(13),
 	ATH9K_HW_CAP_5GHZ			= BIT(14),
+	ATH9K_HW_CAP_APM			= BIT(15),
 };
 
 struct ath9k_hw_capabilities {
@@ -191,16 +199,18 @@ struct ath9k_hw_capabilities {
 	u16 rts_aggr_limit;
 	u8 tx_chainmask;
 	u8 rx_chainmask;
+	u8 max_txchains;
+	u8 max_rxchains;
 	u16 tx_triglevel_max;
 	u16 reg_cap;
 	u8 num_gpio_pins;
-	u8 num_antcfg_2ghz;
-	u8 num_antcfg_5ghz;
 	u8 rx_hp_qdepth;
 	u8 rx_lp_qdepth;
 	u8 rx_status_len;
 	u8 tx_desc_len;
 	u8 txs_len;
+	u16 pcie_lcr_offset;
+	bool pcie_lcr_extsync_en;
 };
 
 struct ath9k_ops_config {
@@ -215,6 +225,7 @@ struct ath9k_ops_config {
 	u32 pcie_waen;
 	u8 analog_shiftreg;
 	u8 ht_enable;
+	u8 paprd_disable;
 	u32 ofdm_trig_low;
 	u32 ofdm_trig_high;
 	u32 cck_trig_high;
@@ -226,7 +237,6 @@ struct ath9k_ops_config {
 #define SPUR_DISABLE        	0
 #define SPUR_ENABLE_IOCTL   	1
 #define SPUR_ENABLE_EEPROM  	2
-#define AR_EEPROM_MODAL_SPURS   5
 #define AR_SPUR_5413_1      	1640
 #define AR_SPUR_5413_2      	1200
 #define AR_NO_SPUR      	0x8000
@@ -434,6 +444,7 @@ struct ath9k_hw_version {
 	u16 analog5GhzRev;
 	u16 analog2GhzRev;
 	u16 subsysid;
+	enum ath_usb_dev usbdev;
 };
 
 /* Generic TSF timer definitions */
@@ -478,6 +489,40 @@ struct ath_hw_antcomb_conf {
 };
 
 /**
+ * struct ath_hw_radar_conf - radar detection initialization parameters
+ *
+ * @pulse_inband: threshold for checking the ratio of in-band power
+ *	to total power for short radar pulses (half dB steps)
+ * @pulse_inband_step: threshold for checking an in-band power to total
+ *	power ratio increase for short radar pulses (half dB steps)
+ * @pulse_height: threshold for detecting the beginning of a short
+ *	radar pulse (dB step)
+ * @pulse_rssi: threshold for detecting if a short radar pulse is
+ *	gone (dB step)
+ * @pulse_maxlen: maximum pulse length (0.8 us steps)
+ *
+ * @radar_rssi: RSSI threshold for starting long radar detection (dB steps)
+ * @radar_inband: threshold for checking the ratio of in-band power
+ *	to total power for long radar pulses (half dB steps)
+ * @fir_power: threshold for detecting the end of a long radar pulse (dB)
+ *
+ * @ext_channel: enable extension channel radar detection
+ */
+struct ath_hw_radar_conf {
+	unsigned int pulse_inband;
+	unsigned int pulse_inband_step;
+	unsigned int pulse_height;
+	unsigned int pulse_rssi;
+	unsigned int pulse_maxlen;
+
+	unsigned int radar_rssi;
+	unsigned int radar_inband;
+	int fir_power;
+
+	bool ext_channel;
+};
+
+/**
  * struct ath_hw_private_ops - callbacks used internally by hardware code
  *
  * This structure contains private callbacks designed to only be used internally
@@ -488,7 +533,6 @@ struct ath_hw_antcomb_conf {
  *
  * @init_mode_regs: Initializes mode registers
  * @init_mode_gain_regs: Initialize TX/RX gain registers
- * @macversion_supported: If this specific mac revision is supported
  *
  * @rf_set_freq: change frequency
  * @spur_mitigate_freq: spur mitigation
@@ -510,7 +554,6 @@ struct ath_hw_private_ops {
 
 	void (*init_mode_regs)(struct ath_hw *ah);
 	void (*init_mode_gain_regs)(struct ath_hw *ah);
-	bool (*macversion_supported)(u32 macversion);
 	void (*setup_calibration)(struct ath_hw *ah,
 				  struct ath9k_cal_list *currCal);
 
@@ -534,7 +577,6 @@ struct ath_hw_private_ops {
 	void (*set_delta_slope)(struct ath_hw *ah, struct ath9k_channel *chan);
 	bool (*rfbus_req)(struct ath_hw *ah);
 	void (*rfbus_done)(struct ath_hw *ah);
-	void (*enable_rfkill)(struct ath_hw *ah);
 	void (*restore_chainmask)(struct ath_hw *ah);
 	void (*set_diversity)(struct ath_hw *ah, bool value);
 	u32 (*compute_pll_control)(struct ath_hw *ah,
@@ -542,6 +584,8 @@ struct ath_hw_private_ops {
 	bool (*ani_control)(struct ath_hw *ah, enum ath9k_ani_cmd cmd,
 			    int param);
 	void (*do_getnf)(struct ath_hw *ah, int16_t nfarray[NUM_NF_READINGS]);
+	void (*set_radar_params)(struct ath_hw *ah,
+				 struct ath_hw_radar_conf *conf);
 
 	/* ANI */
 	void (*ani_cache_ini_regs)(struct ath_hw *ah);
@@ -603,6 +647,10 @@ struct ath_nf_limits {
 	s16 nominal;
 };
 
+/* ah_flags */
+#define AH_USE_EEPROM   0x1
+#define AH_UNPLUGGED    0x2 /* The card has been physically removed. */
+
 struct ath_hw {
 	struct ieee80211_hw *hw;
 	struct ath_common common;
@@ -718,9 +766,7 @@ struct ath_hw {
 	u32 *bank6Temp;
 
 	u8 txpower_limit;
-	int16_t txpower_indexoffset;
 	int coverage_class;
-	u32 beacon_interval;
 	u32 slottime;
 	u32 globaltxtimeout;
 
@@ -740,6 +786,8 @@ struct ath_hw {
 	u8 txchainmask;
 	u8 rxchainmask;
 
+	struct ath_hw_radar_conf radar_conf;
+
 	u32 originalGain[22];
 	int initPDADC;
 	int PDADCdelta;
@@ -789,6 +837,11 @@ struct ath_hw {
 	u32 bb_watchdog_last_status;
 	u32 bb_watchdog_timeout_ms; /* in ms, 0 to disable */
 
+	unsigned int paprd_target_power;
+	unsigned int paprd_training_power;
+	unsigned int paprd_ratemask;
+	unsigned int paprd_ratemask_ht40;
+	bool paprd_table_write_done;
 	u32 paprd_gain_table_entries[PAPRD_GAIN_TABLE_ENTRIES];
 	u8 paprd_gain_table_index[PAPRD_GAIN_TABLE_ENTRIES];
 	/*
@@ -797,6 +850,9 @@ struct ath_hw {
 	 * this register when in sleep states.
 	 */
 	u32 WARegVal;
+
+	/* Enterprise mode cap */
+	u32 ent_mode;
 };
 
 static inline struct ath_common *ath9k_hw_common(struct ath_hw *ah)
@@ -819,10 +875,9 @@ static inline struct ath_hw_ops *ath9k_h
 	return &ah->ops;
 }
 
-static inline int sign_extend(int val, const int nbits)
+static inline u8 get_streams(int mask)
 {
-	int order = BIT(nbits-1);
-	return (val ^ order) - order;
+	return !!(mask & BIT(0)) + !!(mask & BIT(1)) + !!(mask & BIT(2));
 }
 
 /* Initialization, Detach, Reset */
@@ -861,7 +916,7 @@ u32 ath9k_hw_getrxfilter(struct ath_hw *
 void ath9k_hw_setrxfilter(struct ath_hw *ah, u32 bits);
 bool ath9k_hw_phy_disable(struct ath_hw *ah);
 bool ath9k_hw_disable(struct ath_hw *ah);
-void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit);
+void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit, bool test);
 void ath9k_hw_setopmode(struct ath_hw *ah);
 void ath9k_hw_setmcastfilter(struct ath_hw *ah, u32 filter0, u32 filter1);
 void ath9k_hw_setbssidmask(struct ath_hw *ah);
@@ -893,7 +948,6 @@ void ath9k_hw_gen_timer_stop(struct ath_
 
 void ath_gen_timer_free(struct ath_hw *ah, struct ath_gen_timer *timer);
 void ath_gen_timer_isr(struct ath_hw *hw);
-u32 ath9k_hw_gettsf32(struct ath_hw *ah);
 
 void ath9k_hw_name(struct ath_hw *ah, char *hw_name, size_t len);
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/hw-ops.h linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/hw-ops.h
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/hw-ops.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/hw-ops.h	2011-03-14 21:20:32.000000000 -0400
@@ -223,11 +223,6 @@ static inline void ath9k_hw_rfbus_done(s
 	return ath9k_hw_private_ops(ah)->rfbus_done(ah);
 }
 
-static inline void ath9k_enable_rfkill(struct ath_hw *ah)
-{
-	return ath9k_hw_private_ops(ah)->enable_rfkill(ah);
-}
-
 static inline void ath9k_hw_restore_chainmask(struct ath_hw *ah)
 {
 	if (!ath9k_hw_private_ops(ah)->restore_chainmask)
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/init.c linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/init.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/init.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/init.c	2011-03-14 21:20:32.000000000 -0400
@@ -29,17 +29,23 @@ static unsigned int ath9k_debug = ATH_DB
 module_param_named(debug, ath9k_debug, uint, 0);
 MODULE_PARM_DESC(debug, "Debugging mask");
 
-int modparam_nohwcrypt;
-module_param_named(nohwcrypt, modparam_nohwcrypt, int, 0444);
+int ath9k_modparam_nohwcrypt;
+module_param_named(nohwcrypt, ath9k_modparam_nohwcrypt, int, 0444);
 MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption");
 
 int led_blink;
 module_param_named(blink, led_blink, int, 0444);
 MODULE_PARM_DESC(blink, "Enable LED blink on activity");
 
+static int ath9k_btcoex_enable;
+module_param_named(btcoex_enable, ath9k_btcoex_enable, int, 0444);
+MODULE_PARM_DESC(btcoex_enable, "Enable wifi-BT coexistence");
+
+bool is_ath9k_unloaded;
 /* We use the hw_value as an index into our private channel structure */
 
 #define CHAN2G(_freq, _idx)  { \
+	.band = IEEE80211_BAND_2GHZ, \
 	.center_freq = (_freq), \
 	.hw_value = (_idx), \
 	.max_power = 20, \
@@ -206,7 +212,9 @@ static void setup_ht_cap(struct ath_soft
 	ht_info->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
 	ht_info->ampdu_density = IEEE80211_HT_MPDU_DENSITY_8;
 
-	if (AR_SREV_9300_20_OR_LATER(ah))
+	if (AR_SREV_9485(ah))
+		max_streams = 1;
+	else if (AR_SREV_9300_20_OR_LATER(ah))
 		max_streams = 3;
 	else
 		max_streams = 2;
@@ -222,9 +230,9 @@ static void setup_ht_cap(struct ath_soft
 	tx_streams = ath9k_cmn_count_streams(common->tx_chainmask, max_streams);
 	rx_streams = ath9k_cmn_count_streams(common->rx_chainmask, max_streams);
 
-	ath_print(common, ATH_DBG_CONFIG,
-		  "TX streams %d, RX streams: %d\n",
-		  tx_streams, rx_streams);
+	ath_dbg(common, ATH_DBG_CONFIG,
+		"TX streams %d, RX streams: %d\n",
+		tx_streams, rx_streams);
 
 	if (tx_streams != rx_streams) {
 		ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_RX_DIFF;
@@ -267,8 +275,8 @@ int ath_descdma_setup(struct ath_softc *
 	struct ath_buf *bf;
 	int i, bsize, error, desc_len;
 
-	ath_print(common, ATH_DBG_CONFIG, "%s DMA: %u buffers %u desc/buf\n",
-		  name, nbuf, ndesc);
+	ath_dbg(common, ATH_DBG_CONFIG, "%s DMA: %u buffers %u desc/buf\n",
+		name, nbuf, ndesc);
 
 	INIT_LIST_HEAD(head);
 
@@ -279,8 +287,7 @@ int ath_descdma_setup(struct ath_softc *
 
 	/* ath_desc must be a multiple of DWORDs */
 	if ((desc_len % 4) != 0) {
-		ath_print(common, ATH_DBG_FATAL,
-			  "ath_desc not DWORD aligned\n");
+		ath_err(common, "ath_desc not DWORD aligned\n");
 		BUG_ON((desc_len % 4) != 0);
 		error = -ENOMEM;
 		goto fail;
@@ -314,9 +321,9 @@ int ath_descdma_setup(struct ath_softc *
 		goto fail;
 	}
 	ds = (u8 *) dd->dd_desc;
-	ath_print(common, ATH_DBG_CONFIG, "%s DMA map: %p (%u) -> %llx (%u)\n",
-		  name, ds, (u32) dd->dd_desc_len,
-		  ito64(dd->dd_desc_paddr), /*XXX*/(u32) dd->dd_desc_len);
+	ath_dbg(common, ATH_DBG_CONFIG, "%s DMA map: %p (%u) -> %llx (%u)\n",
+		name, ds, (u32) dd->dd_desc_len,
+		ito64(dd->dd_desc_paddr), /*XXX*/(u32) dd->dd_desc_len);
 
 	/* allocate buffers */
 	bsize = sizeof(struct ath_buf) * nbuf;
@@ -362,7 +369,7 @@ fail:
 #undef DS2PHYS
 }
 
-static void ath9k_init_crypto(struct ath_softc *sc)
+void ath9k_init_crypto(struct ath_softc *sc)
 {
 	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
 	int i = 0;
@@ -370,9 +377,9 @@ static void ath9k_init_crypto(struct ath
 	/* Get the hardware key cache size. */
 	common->keymax = sc->sc_ah->caps.keycache_size;
 	if (common->keymax > ATH_KEYMAX) {
-		ath_print(common, ATH_DBG_ANY,
-			  "Warning, using only %u entries in %u key cache\n",
-			  ATH_KEYMAX, common->keymax);
+		ath_dbg(common, ATH_DBG_ANY,
+			"Warning, using only %u entries in %u key cache\n",
+			ATH_KEYMAX, common->keymax);
 		common->keymax = ATH_KEYMAX;
 	}
 
@@ -395,7 +402,8 @@ static void ath9k_init_crypto(struct ath
 
 static int ath9k_init_btcoex(struct ath_softc *sc)
 {
-	int r, qnum;
+	struct ath_txq *txq;
+	int r;
 
 	switch (sc->sc_ah->btcoex_hw.scheme) {
 	case ATH_BTCOEX_CFG_NONE:
@@ -408,8 +416,8 @@ static int ath9k_init_btcoex(struct ath_
 		r = ath_init_btcoex_timer(sc);
 		if (r)
 			return -1;
-		qnum = sc->tx.hwq_map[WME_AC_BE];
-		ath9k_hw_init_btcoex_hw(sc->sc_ah, qnum);
+		txq = sc->tx.txq_map[WME_AC_BE];
+		ath9k_hw_init_btcoex_hw(sc->sc_ah, txq->axq_qnum);
 		sc->btcoex.bt_stomp_type = ATH_BTCOEX_STOMP_LOW;
 		break;
 	default:
@@ -422,59 +430,18 @@ static int ath9k_init_btcoex(struct ath_
 
 static int ath9k_init_queues(struct ath_softc *sc)
 {
-	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
 	int i = 0;
 
-	for (i = 0; i < ARRAY_SIZE(sc->tx.hwq_map); i++)
-		sc->tx.hwq_map[i] = -1;
-
 	sc->beacon.beaconq = ath9k_hw_beaconq_setup(sc->sc_ah);
-	if (sc->beacon.beaconq == -1) {
-		ath_print(common, ATH_DBG_FATAL,
-			  "Unable to setup a beacon xmit queue\n");
-		goto err;
-	}
-
 	sc->beacon.cabq = ath_txq_setup(sc, ATH9K_TX_QUEUE_CAB, 0);
-	if (sc->beacon.cabq == NULL) {
-		ath_print(common, ATH_DBG_FATAL,
-			  "Unable to setup CAB xmit queue\n");
-		goto err;
-	}
 
 	sc->config.cabqReadytime = ATH_CABQ_READY_TIME;
 	ath_cabq_update(sc);
 
-	if (!ath_tx_setup(sc, WME_AC_BK)) {
-		ath_print(common, ATH_DBG_FATAL,
-			  "Unable to setup xmit queue for BK traffic\n");
-		goto err;
-	}
-
-	if (!ath_tx_setup(sc, WME_AC_BE)) {
-		ath_print(common, ATH_DBG_FATAL,
-			  "Unable to setup xmit queue for BE traffic\n");
-		goto err;
-	}
-	if (!ath_tx_setup(sc, WME_AC_VI)) {
-		ath_print(common, ATH_DBG_FATAL,
-			  "Unable to setup xmit queue for VI traffic\n");
-		goto err;
-	}
-	if (!ath_tx_setup(sc, WME_AC_VO)) {
-		ath_print(common, ATH_DBG_FATAL,
-			  "Unable to setup xmit queue for VO traffic\n");
-		goto err;
-	}
+	for (i = 0; i < WME_NUM_AC; i++)
+		sc->tx.txq_map[i] = ath_txq_setup(sc, ATH9K_TX_QUEUE_DATA, i);
 
 	return 0;
-
-err:
-	for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++)
-		if (ATH_TXQ_SETUP(sc, i))
-			ath_tx_cleanupq(sc, &sc->tx.txq[i]);
-
-	return -EIO;
 }
 
 static int ath9k_init_channels_rates(struct ath_softc *sc)
@@ -570,6 +537,9 @@ static int ath9k_init_softc(u16 devid, s
 	ah->hw_version.subsysid = subsysid;
 	sc->sc_ah = ah;
 
+	if (!sc->dev->platform_data)
+		ah->ah_flags |= AH_USE_EEPROM;
+
 	common = ath9k_hw_common(ah);
 	common->ops = &ath9k_common_ops;
 	common->bus_ops = bus_ops;
@@ -577,10 +547,10 @@ static int ath9k_init_softc(u16 devid, s
 	common->hw = sc->hw;
 	common->priv = sc;
 	common->debug_mask = ath9k_debug;
+	common->btcoex_enabled = ath9k_btcoex_enable == 1;
 	spin_lock_init(&common->cc_lock);
 
 	spin_lock_init(&sc->wiphy_lock);
-	spin_lock_init(&sc->sc_resetlock);
 	spin_lock_init(&sc->sc_serial_rw);
 	spin_lock_init(&sc->sc_pm_lock);
 	mutex_init(&sc->mutex);
@@ -600,13 +570,6 @@ static int ath9k_init_softc(u16 devid, s
 	if (ret)
 		goto err_hw;
 
-	ret = ath9k_init_debug(ah);
-	if (ret) {
-		ath_print(common, ATH_DBG_FATAL,
-			  "Unable to create debugfs files\n");
-		goto err_debug;
-	}
-
 	ret = ath9k_init_queues(sc);
 	if (ret)
 		goto err_queues;
@@ -629,12 +592,8 @@ err_btcoex:
 		if (ATH_TXQ_SETUP(sc, i))
 			ath_tx_cleanupq(sc, &sc->tx.txq[i]);
 err_queues:
-	ath9k_exit_debug(ah);
-err_debug:
 	ath9k_hw_deinit(ah);
 err_hw:
-	tasklet_kill(&sc->intr_tq);
-	tasklet_kill(&sc->bcon_tasklet);
 
 	kfree(ah);
 	sc->sc_ah = NULL;
@@ -642,6 +601,37 @@ err_hw:
 	return ret;
 }
 
+static void ath9k_init_band_txpower(struct ath_softc *sc, int band)
+{
+	struct ieee80211_supported_band *sband;
+	struct ieee80211_channel *chan;
+	struct ath_hw *ah = sc->sc_ah;
+	struct ath_regulatory *reg = ath9k_hw_regulatory(ah);
+	int i;
+
+	sband = &sc->sbands[band];
+	for (i = 0; i < sband->n_channels; i++) {
+		chan = &sband->channels[i];
+		ah->curchan = &ah->channels[chan->hw_value];
+		ath9k_cmn_update_ichannel(ah->curchan, chan, NL80211_CHAN_HT20);
+		ath9k_hw_set_txpowerlimit(ah, MAX_RATE_POWER, true);
+		chan->max_power = reg->max_power_level / 2;
+	}
+}
+
+static void ath9k_init_txpower_limits(struct ath_softc *sc)
+{
+	struct ath_hw *ah = sc->sc_ah;
+	struct ath9k_channel *curchan = ah->curchan;
+
+	if (ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ)
+		ath9k_init_band_txpower(sc, IEEE80211_BAND_2GHZ);
+	if (ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ)
+		ath9k_init_band_txpower(sc, IEEE80211_BAND_5GHZ);
+
+	ah->curchan = curchan;
+}
+
 void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
 {
 	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
@@ -657,7 +647,7 @@ void ath9k_set_hw_capab(struct ath_softc
 	if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT)
 		 hw->flags |= IEEE80211_HW_AMPDU_AGGREGATION;
 
-	if (AR_SREV_9160_10_OR_LATER(sc->sc_ah) || modparam_nohwcrypt)
+	if (AR_SREV_9160_10_OR_LATER(sc->sc_ah) || ath9k_modparam_nohwcrypt)
 		hw->flags |= IEEE80211_HW_MFP_CAPABLE;
 
 	hw->wiphy->interface_modes =
@@ -705,6 +695,7 @@ int ath9k_init_device(u16 devid, struct
 		    const struct ath_bus_ops *bus_ops)
 {
 	struct ieee80211_hw *hw = sc->hw;
+	struct ath_wiphy *aphy = hw->priv;
 	struct ath_common *common;
 	struct ath_hw *ah;
 	int error = 0;
@@ -737,11 +728,19 @@ int ath9k_init_device(u16 devid, struct
 	if (error != 0)
 		goto error_rx;
 
+	ath9k_init_txpower_limits(sc);
+
 	/* Register with mac80211 */
 	error = ieee80211_register_hw(hw);
 	if (error)
 		goto error_register;
 
+	error = ath9k_init_debug(ah);
+	if (error) {
+		ath_err(common, "Unable to create debugfs files\n");
+		goto error_world;
+	}
+
 	/* Handle world regulatory */
 	if (!ath_is_world_regd(reg)) {
 		error = regulatory_hint(hw->wiphy, reg->alpha2);
@@ -754,13 +753,11 @@ int ath9k_init_device(u16 devid, struct
 	INIT_WORK(&sc->chan_work, ath9k_wiphy_chan_work);
 	INIT_DELAYED_WORK(&sc->wiphy_work, ath9k_wiphy_work);
 	sc->wiphy_scheduler_int = msecs_to_jiffies(500);
+	aphy->last_rssi = ATH_RSSI_DUMMY_MARKER;
 
 	ath_init_leds(sc);
 	ath_start_rfkill_poll(sc);
 
-	pm_qos_add_request(&sc->pm_qos_req, PM_QOS_CPU_DMA_LATENCY,
-			   PM_QOS_DEFAULT_VALUE);
-
 	return 0;
 
 error_world:
@@ -799,12 +796,8 @@ static void ath9k_deinit_softc(struct at
 		if (ATH_TXQ_SETUP(sc, i))
 			ath_tx_cleanupq(sc, &sc->tx.txq[i]);
 
-	ath9k_exit_debug(sc->sc_ah);
 	ath9k_hw_deinit(sc->sc_ah);
 
-	tasklet_kill(&sc->intr_tq);
-	tasklet_kill(&sc->bcon_tasklet);
-
 	kfree(sc->sc_ah);
 	sc->sc_ah = NULL;
 }
@@ -819,6 +812,8 @@ void ath9k_deinit_device(struct ath_soft
 	wiphy_rfkill_stop_polling(sc->hw->wiphy);
 	ath_deinit_leds(sc);
 
+	ath9k_ps_restore(sc);
+
 	for (i = 0; i < sc->num_sec_wiphy; i++) {
 		struct ath_wiphy *aphy = sc->sec_wiphy[i];
 		if (aphy == NULL)
@@ -829,7 +824,6 @@ void ath9k_deinit_device(struct ath_soft
 	}
 
 	ieee80211_unregister_hw(hw);
-	pm_qos_remove_request(&sc->pm_qos_req);
 	ath_rx_cleanup(sc);
 	ath_tx_cleanup(sc);
 	ath9k_deinit_softc(sc);
@@ -866,20 +860,12 @@ static int __init ath9k_init(void)
 		goto err_out;
 	}
 
-	error = ath9k_debug_create_root();
-	if (error) {
-		printk(KERN_ERR
-			"ath9k: Unable to create debugfs root: %d\n",
-			error);
-		goto err_rate_unregister;
-	}
-
 	error = ath_pci_init();
 	if (error < 0) {
 		printk(KERN_ERR
 			"ath9k: No PCI devices found, driver not installed.\n");
 		error = -ENODEV;
-		goto err_remove_root;
+		goto err_rate_unregister;
 	}
 
 	error = ath_ahb_init();
@@ -893,8 +879,6 @@ static int __init ath9k_init(void)
  err_pci_exit:
 	ath_pci_exit();
 
- err_remove_root:
-	ath9k_debug_remove_root();
  err_rate_unregister:
 	ath_rate_control_unregister();
  err_out:
@@ -904,9 +888,9 @@ module_init(ath9k_init);
 
 static void __exit ath9k_exit(void)
 {
+	is_ath9k_unloaded = true;
 	ath_ahb_exit();
 	ath_pci_exit();
-	ath9k_debug_remove_root();
 	ath_rate_control_unregister();
 	printk(KERN_INFO "%s: Driver unloaded\n", dev_info);
 }
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/mac.c linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/mac.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/mac.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/mac.c	2011-03-14 21:20:32.000000000 -0400
@@ -20,11 +20,11 @@
 static void ath9k_hw_set_txq_interrupts(struct ath_hw *ah,
 					struct ath9k_tx_queue_info *qi)
 {
-	ath_print(ath9k_hw_common(ah), ATH_DBG_INTERRUPT,
-		  "tx ok 0x%x err 0x%x desc 0x%x eol 0x%x urn 0x%x\n",
-		  ah->txok_interrupt_mask, ah->txerr_interrupt_mask,
-		  ah->txdesc_interrupt_mask, ah->txeol_interrupt_mask,
-		  ah->txurn_interrupt_mask);
+	ath_dbg(ath9k_hw_common(ah), ATH_DBG_INTERRUPT,
+		"tx ok 0x%x err 0x%x desc 0x%x eol 0x%x urn 0x%x\n",
+		ah->txok_interrupt_mask, ah->txerr_interrupt_mask,
+		ah->txdesc_interrupt_mask, ah->txeol_interrupt_mask,
+		ah->txurn_interrupt_mask);
 
 	ENABLE_REGWRITE_BUFFER(ah);
 
@@ -56,8 +56,8 @@ EXPORT_SYMBOL(ath9k_hw_puttxbuf);
 
 void ath9k_hw_txstart(struct ath_hw *ah, u32 q)
 {
-	ath_print(ath9k_hw_common(ah), ATH_DBG_QUEUE,
-		  "Enable TXE on queue: %u\n", q);
+	ath_dbg(ath9k_hw_common(ah), ATH_DBG_QUEUE,
+		"Enable TXE on queue: %u\n", q);
 	REG_WRITE(ah, AR_Q_TXE, 1 << q);
 }
 EXPORT_SYMBOL(ath9k_hw_txstart);
@@ -117,12 +117,11 @@ EXPORT_SYMBOL(ath9k_hw_numtxpending);
 bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel)
 {
 	u32 txcfg, curLevel, newLevel;
-	enum ath9k_int omask;
 
 	if (ah->tx_trig_level >= ah->config.max_txtrig_level)
 		return false;
 
-	omask = ath9k_hw_set_interrupts(ah, ah->imask & ~ATH9K_INT_GLOBAL);
+	ath9k_hw_disable_interrupts(ah);
 
 	txcfg = REG_READ(ah, AR_TXCFG);
 	curLevel = MS(txcfg, AR_FTRIG);
@@ -136,7 +135,7 @@ bool ath9k_hw_updatetxtriglevel(struct a
 		REG_WRITE(ah, AR_TXCFG,
 			  (txcfg & ~AR_FTRIG) | SM(newLevel, AR_FTRIG));
 
-	ath9k_hw_set_interrupts(ah, omask);
+	ath9k_hw_enable_interrupts(ah);
 
 	ah->tx_trig_level = newLevel;
 
@@ -155,15 +154,15 @@ bool ath9k_hw_stoptxdma(struct ath_hw *a
 	u32 wait_time = ATH9K_TX_STOP_DMA_TIMEOUT / ATH9K_TIME_QUANTUM;
 
 	if (q >= pCap->total_queues) {
-		ath_print(common, ATH_DBG_QUEUE, "Stopping TX DMA, "
-			  "invalid queue: %u\n", q);
+		ath_dbg(common, ATH_DBG_QUEUE,
+			"Stopping TX DMA, invalid queue: %u\n", q);
 		return false;
 	}
 
 	qi = &ah->txq[q];
 	if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
-		ath_print(common, ATH_DBG_QUEUE, "Stopping TX DMA, "
-			  "inactive queue: %u\n", q);
+		ath_dbg(common, ATH_DBG_QUEUE,
+			"Stopping TX DMA, inactive queue: %u\n", q);
 		return false;
 	}
 
@@ -176,9 +175,9 @@ bool ath9k_hw_stoptxdma(struct ath_hw *a
 	}
 
 	if (ath9k_hw_numtxpending(ah, q)) {
-		ath_print(common, ATH_DBG_QUEUE,
-			  "%s: Num of pending TX Frames %d on Q %d\n",
-			  __func__, ath9k_hw_numtxpending(ah, q), q);
+		ath_dbg(common, ATH_DBG_QUEUE,
+			"%s: Num of pending TX Frames %d on Q %d\n",
+			__func__, ath9k_hw_numtxpending(ah, q), q);
 
 		for (j = 0; j < 2; j++) {
 			tsfLow = REG_READ(ah, AR_TSF_L32);
@@ -192,9 +191,9 @@ bool ath9k_hw_stoptxdma(struct ath_hw *a
 			if ((REG_READ(ah, AR_TSF_L32) >> 10) == (tsfLow >> 10))
 				break;
 
-			ath_print(common, ATH_DBG_QUEUE,
-				  "TSF has moved while trying to set "
-				  "quiet time TSF: 0x%08x\n", tsfLow);
+			ath_dbg(common, ATH_DBG_QUEUE,
+				"TSF has moved while trying to set quiet time TSF: 0x%08x\n",
+				tsfLow);
 		}
 
 		REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH);
@@ -205,9 +204,8 @@ bool ath9k_hw_stoptxdma(struct ath_hw *a
 		wait = wait_time;
 		while (ath9k_hw_numtxpending(ah, q)) {
 			if ((--wait) == 0) {
-				ath_print(common, ATH_DBG_FATAL,
-					  "Failed to stop TX DMA in 100 "
-					  "msec after killing last frame\n");
+				ath_err(common,
+					"Failed to stop TX DMA in 100 msec after killing last frame\n");
 				break;
 			}
 			udelay(ATH9K_TIME_QUANTUM);
@@ -240,19 +238,19 @@ bool ath9k_hw_set_txq_props(struct ath_h
 	struct ath9k_tx_queue_info *qi;
 
 	if (q >= pCap->total_queues) {
-		ath_print(common, ATH_DBG_QUEUE, "Set TXQ properties, "
-			  "invalid queue: %u\n", q);
+		ath_dbg(common, ATH_DBG_QUEUE,
+			"Set TXQ properties, invalid queue: %u\n", q);
 		return false;
 	}
 
 	qi = &ah->txq[q];
 	if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
-		ath_print(common, ATH_DBG_QUEUE, "Set TXQ properties, "
-			  "inactive queue: %u\n", q);
+		ath_dbg(common, ATH_DBG_QUEUE,
+			"Set TXQ properties, inactive queue: %u\n", q);
 		return false;
 	}
 
-	ath_print(common, ATH_DBG_QUEUE, "Set queue properties for: %u\n", q);
+	ath_dbg(common, ATH_DBG_QUEUE, "Set queue properties for: %u\n", q);
 
 	qi->tqi_ver = qinfo->tqi_ver;
 	qi->tqi_subtype = qinfo->tqi_subtype;
@@ -311,15 +309,15 @@ bool ath9k_hw_get_txq_props(struct ath_h
 	struct ath9k_tx_queue_info *qi;
 
 	if (q >= pCap->total_queues) {
-		ath_print(common, ATH_DBG_QUEUE, "Get TXQ properties, "
-			  "invalid queue: %u\n", q);
+		ath_dbg(common, ATH_DBG_QUEUE,
+			"Get TXQ properties, invalid queue: %u\n", q);
 		return false;
 	}
 
 	qi = &ah->txq[q];
 	if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
-		ath_print(common, ATH_DBG_QUEUE, "Get TXQ properties, "
-			  "inactive queue: %u\n", q);
+		ath_dbg(common, ATH_DBG_QUEUE,
+			"Get TXQ properties, inactive queue: %u\n", q);
 		return false;
 	}
 
@@ -369,23 +367,20 @@ int ath9k_hw_setuptxqueue(struct ath_hw
 			    ATH9K_TX_QUEUE_INACTIVE)
 				break;
 		if (q == pCap->total_queues) {
-			ath_print(common, ATH_DBG_FATAL,
-				  "No available TX queue\n");
+			ath_err(common, "No available TX queue\n");
 			return -1;
 		}
 		break;
 	default:
-		ath_print(common, ATH_DBG_FATAL,
-			  "Invalid TX queue type: %u\n", type);
+		ath_err(common, "Invalid TX queue type: %u\n", type);
 		return -1;
 	}
 
-	ath_print(common, ATH_DBG_QUEUE, "Setup TX queue: %u\n", q);
+	ath_dbg(common, ATH_DBG_QUEUE, "Setup TX queue: %u\n", q);
 
 	qi = &ah->txq[q];
 	if (qi->tqi_type != ATH9K_TX_QUEUE_INACTIVE) {
-		ath_print(common, ATH_DBG_FATAL,
-			  "TX queue: %u already active\n", q);
+		ath_err(common, "TX queue: %u already active\n", q);
 		return -1;
 	}
 	memset(qi, 0, sizeof(struct ath9k_tx_queue_info));
@@ -417,18 +412,18 @@ bool ath9k_hw_releasetxqueue(struct ath_
 	struct ath9k_tx_queue_info *qi;
 
 	if (q >= pCap->total_queues) {
-		ath_print(common, ATH_DBG_QUEUE, "Release TXQ, "
-			  "invalid queue: %u\n", q);
+		ath_dbg(common, ATH_DBG_QUEUE,
+			"Release TXQ, invalid queue: %u\n", q);
 		return false;
 	}
 	qi = &ah->txq[q];
 	if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
-		ath_print(common, ATH_DBG_QUEUE, "Release TXQ, "
-			  "inactive queue: %u\n", q);
+		ath_dbg(common, ATH_DBG_QUEUE,
+			"Release TXQ, inactive queue: %u\n", q);
 		return false;
 	}
 
-	ath_print(common, ATH_DBG_QUEUE, "Release TX queue: %u\n", q);
+	ath_dbg(common, ATH_DBG_QUEUE, "Release TX queue: %u\n", q);
 
 	qi->tqi_type = ATH9K_TX_QUEUE_INACTIVE;
 	ah->txok_interrupt_mask &= ~(1 << q);
@@ -451,19 +446,19 @@ bool ath9k_hw_resettxqueue(struct ath_hw
 	u32 cwMin, chanCwMin, value;
 
 	if (q >= pCap->total_queues) {
-		ath_print(common, ATH_DBG_QUEUE, "Reset TXQ, "
-			  "invalid queue: %u\n", q);
+		ath_dbg(common, ATH_DBG_QUEUE,
+			"Reset TXQ, invalid queue: %u\n", q);
 		return false;
 	}
 
 	qi = &ah->txq[q];
 	if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
-		ath_print(common, ATH_DBG_QUEUE, "Reset TXQ, "
-			  "inactive queue: %u\n", q);
+		ath_dbg(common, ATH_DBG_QUEUE,
+			"Reset TXQ, inactive queue: %u\n", q);
 		return true;
 	}
 
-	ath_print(common, ATH_DBG_QUEUE, "Reset TX queue: %u\n", q);
+	ath_dbg(common, ATH_DBG_QUEUE, "Reset TX queue: %u\n", q);
 
 	if (qi->tqi_cwmin == ATH9K_TXQ_USEDEFAULT) {
 		if (chan && IS_CHAN_B(chan))
@@ -697,15 +692,16 @@ int ath9k_hw_rxprocdesc(struct ath_hw *a
 	if ((ads.ds_rxstatus8 & AR_RxFrameOK) == 0) {
 		if (ads.ds_rxstatus8 & AR_CRCErr)
 			rs->rs_status |= ATH9K_RXERR_CRC;
-		else if (ads.ds_rxstatus8 & AR_PHYErr) {
+		if (ads.ds_rxstatus8 & AR_PHYErr) {
 			rs->rs_status |= ATH9K_RXERR_PHY;
 			phyerr = MS(ads.ds_rxstatus8, AR_PHYErrCode);
 			rs->rs_phyerr = phyerr;
-		} else if (ads.ds_rxstatus8 & AR_DecryptCRCErr)
+		}
+		if (ads.ds_rxstatus8 & AR_DecryptCRCErr)
 			rs->rs_status |= ATH9K_RXERR_DECRYPT;
-		else if (ads.ds_rxstatus8 & AR_MichaelErr)
+		if (ads.ds_rxstatus8 & AR_MichaelErr)
 			rs->rs_status |= ATH9K_RXERR_MIC;
-		else if (ads.ds_rxstatus8 & AR_KeyMiss)
+		if (ads.ds_rxstatus8 & AR_KeyMiss)
 			rs->rs_status |= ATH9K_RXERR_DECRYPT;
 	}
 
@@ -735,9 +731,9 @@ bool ath9k_hw_setrxabort(struct ath_hw *
 				     AR_DIAG_RX_ABORT));
 
 			reg = REG_READ(ah, AR_OBS_BUS_1);
-			ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL,
-				  "RX failed to go idle in 10 ms RXSM=0x%x\n",
-				  reg);
+			ath_err(ath9k_hw_common(ah),
+				"RX failed to go idle in 10 ms RXSM=0x%x\n",
+				reg);
 
 			return false;
 		}
@@ -766,14 +762,6 @@ void ath9k_hw_startpcureceive(struct ath
 }
 EXPORT_SYMBOL(ath9k_hw_startpcureceive);
 
-void ath9k_hw_stoppcurecv(struct ath_hw *ah)
-{
-	REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_DIS);
-
-	ath9k_hw_disable_mib_counters(ah);
-}
-EXPORT_SYMBOL(ath9k_hw_stoppcurecv);
-
 void ath9k_hw_abortpcurecv(struct ath_hw *ah)
 {
 	REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_ABORT | AR_DIAG_RX_DIS);
@@ -799,12 +787,11 @@ bool ath9k_hw_stopdmarecv(struct ath_hw
 	}
 
 	if (i == 0) {
-		ath_print(common, ATH_DBG_FATAL,
-			  "DMA failed to stop in %d ms "
-			  "AR_CR=0x%08x AR_DIAG_SW=0x%08x\n",
-			  AH_RX_STOP_DMA_TIMEOUT / 1000,
-			  REG_READ(ah, AR_CR),
-			  REG_READ(ah, AR_DIAG_SW));
+		ath_err(common,
+			"DMA failed to stop in %d ms AR_CR=0x%08x AR_DIAG_SW=0x%08x\n",
+			AH_RX_STOP_DMA_TIMEOUT / 1000,
+			REG_READ(ah, AR_CR),
+			REG_READ(ah, AR_DIAG_SW));
 		return false;
 	} else {
 		return true;
@@ -848,28 +835,59 @@ bool ath9k_hw_intrpend(struct ath_hw *ah
 }
 EXPORT_SYMBOL(ath9k_hw_intrpend);
 
-enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah,
-					      enum ath9k_int ints)
+void ath9k_hw_disable_interrupts(struct ath_hw *ah)
+{
+	struct ath_common *common = ath9k_hw_common(ah);
+
+	ath_dbg(common, ATH_DBG_INTERRUPT, "disable IER\n");
+	REG_WRITE(ah, AR_IER, AR_IER_DISABLE);
+	(void) REG_READ(ah, AR_IER);
+	if (!AR_SREV_9100(ah)) {
+		REG_WRITE(ah, AR_INTR_ASYNC_ENABLE, 0);
+		(void) REG_READ(ah, AR_INTR_ASYNC_ENABLE);
+
+		REG_WRITE(ah, AR_INTR_SYNC_ENABLE, 0);
+		(void) REG_READ(ah, AR_INTR_SYNC_ENABLE);
+	}
+}
+EXPORT_SYMBOL(ath9k_hw_disable_interrupts);
+
+void ath9k_hw_enable_interrupts(struct ath_hw *ah)
+{
+	struct ath_common *common = ath9k_hw_common(ah);
+
+	if (!(ah->imask & ATH9K_INT_GLOBAL))
+		return;
+
+	ath_dbg(common, ATH_DBG_INTERRUPT, "enable IER\n");
+	REG_WRITE(ah, AR_IER, AR_IER_ENABLE);
+	if (!AR_SREV_9100(ah)) {
+		REG_WRITE(ah, AR_INTR_ASYNC_ENABLE,
+			  AR_INTR_MAC_IRQ);
+		REG_WRITE(ah, AR_INTR_ASYNC_MASK, AR_INTR_MAC_IRQ);
+
+
+		REG_WRITE(ah, AR_INTR_SYNC_ENABLE,
+			  AR_INTR_SYNC_DEFAULT);
+		REG_WRITE(ah, AR_INTR_SYNC_MASK,
+			  AR_INTR_SYNC_DEFAULT);
+	}
+	ath_dbg(common, ATH_DBG_INTERRUPT, "AR_IMR 0x%x IER 0x%x\n",
+		REG_READ(ah, AR_IMR), REG_READ(ah, AR_IER));
+}
+EXPORT_SYMBOL(ath9k_hw_enable_interrupts);
+
+void ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints)
 {
 	enum ath9k_int omask = ah->imask;
 	u32 mask, mask2;
 	struct ath9k_hw_capabilities *pCap = &ah->caps;
 	struct ath_common *common = ath9k_hw_common(ah);
 
-	ath_print(common, ATH_DBG_INTERRUPT, "0x%x => 0x%x\n", omask, ints);
-
-	if (omask & ATH9K_INT_GLOBAL) {
-		ath_print(common, ATH_DBG_INTERRUPT, "disable IER\n");
-		REG_WRITE(ah, AR_IER, AR_IER_DISABLE);
-		(void) REG_READ(ah, AR_IER);
-		if (!AR_SREV_9100(ah)) {
-			REG_WRITE(ah, AR_INTR_ASYNC_ENABLE, 0);
-			(void) REG_READ(ah, AR_INTR_ASYNC_ENABLE);
+	if (!(ints & ATH9K_INT_GLOBAL))
+		ath9k_hw_disable_interrupts(ah);
 
-			REG_WRITE(ah, AR_INTR_SYNC_ENABLE, 0);
-			(void) REG_READ(ah, AR_INTR_SYNC_ENABLE);
-		}
-	}
+	ath_dbg(common, ATH_DBG_INTERRUPT, "0x%x => 0x%x\n", omask, ints);
 
 	/* TODO: global int Ref count */
 	mask = ints & ATH9K_INT_COMMON;
@@ -930,7 +948,7 @@ enum ath9k_int ath9k_hw_set_interrupts(s
 			mask2 |= AR_IMR_S2_CST;
 	}
 
-	ath_print(common, ATH_DBG_INTERRUPT, "new IMR 0x%x\n", mask);
+	ath_dbg(common, ATH_DBG_INTERRUPT, "new IMR 0x%x\n", mask);
 	REG_WRITE(ah, AR_IMR, mask);
 	ah->imrs2_reg &= ~(AR_IMR_S2_TIM | AR_IMR_S2_DTIM | AR_IMR_S2_DTIMSYNC |
 			   AR_IMR_S2_CABEND | AR_IMR_S2_CABTO |
@@ -945,24 +963,9 @@ enum ath9k_int ath9k_hw_set_interrupts(s
 			REG_CLR_BIT(ah, AR_IMR_S5, AR_IMR_S5_TIM_TIMER);
 	}
 
-	if (ints & ATH9K_INT_GLOBAL) {
-		ath_print(common, ATH_DBG_INTERRUPT, "enable IER\n");
-		REG_WRITE(ah, AR_IER, AR_IER_ENABLE);
-		if (!AR_SREV_9100(ah)) {
-			REG_WRITE(ah, AR_INTR_ASYNC_ENABLE,
-				  AR_INTR_MAC_IRQ);
-			REG_WRITE(ah, AR_INTR_ASYNC_MASK, AR_INTR_MAC_IRQ);
-
-
-			REG_WRITE(ah, AR_INTR_SYNC_ENABLE,
-				  AR_INTR_SYNC_DEFAULT);
-			REG_WRITE(ah, AR_INTR_SYNC_MASK,
-				  AR_INTR_SYNC_DEFAULT);
-		}
-		ath_print(common, ATH_DBG_INTERRUPT, "AR_IMR 0x%x IER 0x%x\n",
-			  REG_READ(ah, AR_IMR), REG_READ(ah, AR_IER));
-	}
+	if (ints & ATH9K_INT_GLOBAL)
+		ath9k_hw_enable_interrupts(ah);
 
-	return omask;
+	return;
 }
 EXPORT_SYMBOL(ath9k_hw_set_interrupts);
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/mac.h linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/mac.h
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/mac.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/mac.h	2011-03-14 21:20:32.000000000 -0400
@@ -104,13 +104,11 @@ struct ath_tx_status {
 	u32 ts_tstamp;
 	u16 ts_seqnum;
 	u8 ts_status;
-	u8 ts_ratecode;
 	u8 ts_rateindex;
 	int8_t ts_rssi;
 	u8 ts_shortretry;
 	u8 ts_longretry;
 	u8 ts_virtcol;
-	u8 ts_antenna;
 	u8 ts_flags;
 	int8_t ts_rssi_ctl0;
 	int8_t ts_rssi_ctl1;
@@ -121,7 +119,6 @@ struct ath_tx_status {
 	u8 qid;
 	u16 desc_id;
 	u8 tid;
-	u8 pad[2];
 	u32 ba_low;
 	u32 ba_high;
 	u32 evm0;
@@ -240,7 +237,7 @@ struct ath_desc {
 	u32 ds_ctl1;
 	u32 ds_hw[20];
 	void *ds_vdata;
-} __packed;
+} __packed __aligned(4);
 
 #define ATH9K_TXDESC_CLRDMASK		0x0001
 #define ATH9K_TXDESC_NOACK		0x0002
@@ -310,7 +307,7 @@ struct ar5416_desc {
 			u32 status8;
 		} rx;
 	} u;
-} __packed;
+} __packed __aligned(4);
 
 #define AR5416DESC(_ds)         ((struct ar5416_desc *)(_ds))
 #define AR5416DESC_CONST(_ds)   ((const struct ar5416_desc *)(_ds))
@@ -669,6 +666,7 @@ enum ath9k_key_type {
 
 struct ath_hw;
 struct ath9k_channel;
+enum ath9k_int;
 
 u32 ath9k_hw_gettxbuf(struct ath_hw *ah, u32 q);
 void ath9k_hw_puttxbuf(struct ath_hw *ah, u32 q, u32 txdp);
@@ -693,15 +691,15 @@ void ath9k_hw_setuprxdesc(struct ath_hw
 bool ath9k_hw_setrxabort(struct ath_hw *ah, bool set);
 void ath9k_hw_putrxbuf(struct ath_hw *ah, u32 rxdp);
 void ath9k_hw_startpcureceive(struct ath_hw *ah, bool is_scanning);
-void ath9k_hw_stoppcurecv(struct ath_hw *ah);
 void ath9k_hw_abortpcurecv(struct ath_hw *ah);
 bool ath9k_hw_stopdmarecv(struct ath_hw *ah);
 int ath9k_hw_beaconq_setup(struct ath_hw *ah);
 
 /* Interrupt Handling */
 bool ath9k_hw_intrpend(struct ath_hw *ah);
-enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah,
-				       enum ath9k_int ints);
+void ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints);
+void ath9k_hw_enable_interrupts(struct ath_hw *ah);
+void ath9k_hw_disable_interrupts(struct ath_hw *ah);
 
 void ar9002_hw_attach_mac_ops(struct ath_hw *ah);
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/main.c linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/main.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/main.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/main.c	2011-03-14 21:20:32.000000000 -0400
@@ -23,7 +23,7 @@ static void ath_update_txpow(struct ath_
 	struct ath_hw *ah = sc->sc_ah;
 
 	if (sc->curtxpow != sc->config.txpowlimit) {
-		ath9k_hw_set_txpowerlimit(ah, sc->config.txpowlimit);
+		ath9k_hw_set_txpowerlimit(ah, sc->config.txpowlimit, false);
 		/* read back in case value is clamped */
 		sc->curtxpow = ath9k_hw_regulatory(ah)->power_limit;
 	}
@@ -234,6 +234,8 @@ int ath_set_channel(struct ath_softc *sc
 
 	ath9k_ps_wakeup(sc);
 
+	spin_lock_bh(&sc->sc_pcu_lock);
+
 	/*
 	 * This is only performed if the channel settings have
 	 * actually changed.
@@ -243,11 +245,9 @@ int ath_set_channel(struct ath_softc *sc
 	 * hardware at the new frequency, and then re-enable
 	 * the relevant bits of the h/w.
 	 */
-	ath9k_hw_set_interrupts(ah, 0);
+	ath9k_hw_disable_interrupts(ah);
 	stopped = ath_drain_all_txq(sc, false);
 
-	spin_lock_bh(&sc->rx.pcu_lock);
-
 	if (!ath_stoprecv(sc))
 		stopped = false;
 
@@ -261,46 +261,39 @@ int ath_set_channel(struct ath_softc *sc
 	if (!(sc->sc_flags & SC_OP_OFFCHANNEL))
 		caldata = &aphy->caldata;
 
-	ath_print(common, ATH_DBG_CONFIG,
-		  "(%u MHz) -> (%u MHz), conf_is_ht40: %d fastcc: %d\n",
-		  sc->sc_ah->curchan->channel,
-		  channel->center_freq, conf_is_ht40(conf),
-		  fastcc);
-
-	spin_lock_bh(&sc->sc_resetlock);
+	ath_dbg(common, ATH_DBG_CONFIG,
+		"(%u MHz) -> (%u MHz), conf_is_ht40: %d fastcc: %d\n",
+		sc->sc_ah->curchan->channel,
+		channel->center_freq, conf_is_ht40(conf),
+		fastcc);
 
 	r = ath9k_hw_reset(ah, hchan, caldata, fastcc);
 	if (r) {
-		ath_print(common, ATH_DBG_FATAL,
-			  "Unable to reset channel (%u MHz), "
-			  "reset status %d\n",
-			  channel->center_freq, r);
-		spin_unlock_bh(&sc->sc_resetlock);
-		spin_unlock_bh(&sc->rx.pcu_lock);
+		ath_err(common,
+			"Unable to reset channel (%u MHz), reset status %d\n",
+			channel->center_freq, r);
 		goto ps_restore;
 	}
-	spin_unlock_bh(&sc->sc_resetlock);
 
 	if (ath_startrecv(sc) != 0) {
-		ath_print(common, ATH_DBG_FATAL,
-			  "Unable to restart recv logic\n");
+		ath_err(common, "Unable to restart recv logic\n");
 		r = -EIO;
-		spin_unlock_bh(&sc->rx.pcu_lock);
 		goto ps_restore;
 	}
 
-	spin_unlock_bh(&sc->rx.pcu_lock);
-
 	ath_update_txpow(sc);
 	ath9k_hw_set_interrupts(ah, ah->imask);
 
 	if (!(sc->sc_flags & (SC_OP_OFFCHANNEL))) {
-		ath_beacon_config(sc, NULL);
+		if (sc->sc_flags & SC_OP_BEACONS)
+			ath_beacon_config(sc, NULL);
 		ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0);
 		ath_start_ani(common);
 	}
 
  ps_restore:
+	spin_unlock_bh(&sc->sc_pcu_lock);
+
 	ath9k_ps_restore(sc);
 	return r;
 }
@@ -328,6 +321,46 @@ static void ath_paprd_activate(struct at
 	ath9k_ps_restore(sc);
 }
 
+static bool ath_paprd_send_frame(struct ath_softc *sc, struct sk_buff *skb, int chain)
+{
+	struct ieee80211_hw *hw = sc->hw;
+	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
+	struct ath_hw *ah = sc->sc_ah;
+	struct ath_common *common = ath9k_hw_common(ah);
+	struct ath_tx_control txctl;
+	int time_left;
+
+	memset(&txctl, 0, sizeof(txctl));
+	txctl.txq = sc->tx.txq_map[WME_AC_BE];
+
+	memset(tx_info, 0, sizeof(*tx_info));
+	tx_info->band = hw->conf.channel->band;
+	tx_info->flags |= IEEE80211_TX_CTL_NO_ACK;
+	tx_info->control.rates[0].idx = 0;
+	tx_info->control.rates[0].count = 1;
+	tx_info->control.rates[0].flags = IEEE80211_TX_RC_MCS;
+	tx_info->control.rates[1].idx = -1;
+
+	init_completion(&sc->paprd_complete);
+	txctl.paprd = BIT(chain);
+
+	if (ath_tx_start(hw, skb, &txctl) != 0) {
+		ath_dbg(common, ATH_DBG_XMIT, "PAPRD TX failed\n");
+		dev_kfree_skb_any(skb);
+		return false;
+	}
+
+	time_left = wait_for_completion_timeout(&sc->paprd_complete,
+			msecs_to_jiffies(ATH_PAPRD_TIMEOUT));
+
+	if (!time_left)
+		ath_dbg(ath9k_hw_common(sc->sc_ah), ATH_DBG_CALIBRATE,
+			"Timeout waiting for paprd training on TX chain %d\n",
+			chain);
+
+	return !!time_left;
+}
+
 void ath_paprd_calibrate(struct work_struct *work)
 {
 	struct ath_softc *sc = container_of(work, struct ath_softc, paprd_work);
@@ -335,28 +368,23 @@ void ath_paprd_calibrate(struct work_str
 	struct ath_hw *ah = sc->sc_ah;
 	struct ieee80211_hdr *hdr;
 	struct sk_buff *skb = NULL;
-	struct ieee80211_tx_info *tx_info;
-	int band = hw->conf.channel->band;
-	struct ieee80211_supported_band *sband = &sc->sbands[band];
-	struct ath_tx_control txctl;
 	struct ath9k_hw_cal_data *caldata = ah->caldata;
 	struct ath_common *common = ath9k_hw_common(ah);
-	int qnum, ftype;
+	int ftype;
 	int chain_ok = 0;
 	int chain;
 	int len = 1800;
-	int time_left;
-	int i;
 
 	if (!caldata)
 		return;
 
+	if (ar9003_paprd_init_table(ah) < 0)
+		return;
+
 	skb = alloc_skb(len, GFP_KERNEL);
 	if (!skb)
 		return;
 
-	tx_info = IEEE80211_SKB_CB(skb);
-
 	skb_put(skb, len);
 	memset(skb->data, 0, len);
 	hdr = (struct ieee80211_hdr *)skb->data;
@@ -367,40 +395,25 @@ void ath_paprd_calibrate(struct work_str
 	memcpy(hdr->addr2, hw->wiphy->perm_addr, ETH_ALEN);
 	memcpy(hdr->addr3, hw->wiphy->perm_addr, ETH_ALEN);
 
-	memset(&txctl, 0, sizeof(txctl));
-	qnum = sc->tx.hwq_map[WME_AC_BE];
-	txctl.txq = &sc->tx.txq[qnum];
-
 	ath9k_ps_wakeup(sc);
-	ar9003_paprd_init_table(ah);
 	for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) {
 		if (!(common->tx_chainmask & BIT(chain)))
 			continue;
 
 		chain_ok = 0;
-		memset(tx_info, 0, sizeof(*tx_info));
-		tx_info->band = band;
 
-		for (i = 0; i < 4; i++) {
-			tx_info->control.rates[i].idx = sband->n_bitrates - 1;
-			tx_info->control.rates[i].count = 6;
-		}
+		ath_dbg(common, ATH_DBG_CALIBRATE,
+			"Sending PAPRD frame for thermal measurement "
+			"on chain %d\n", chain);
+		if (!ath_paprd_send_frame(sc, skb, chain))
+			goto fail_paprd;
 
-		init_completion(&sc->paprd_complete);
 		ar9003_paprd_setup_gain_table(ah, chain);
-		txctl.paprd = BIT(chain);
-		if (ath_tx_start(hw, skb, &txctl) != 0)
-			break;
 
-		time_left = wait_for_completion_timeout(&sc->paprd_complete,
-				msecs_to_jiffies(ATH_PAPRD_TIMEOUT));
-		if (!time_left) {
-			ath_print(ath9k_hw_common(ah), ATH_DBG_CALIBRATE,
-				  "Timeout waiting for paprd training on "
-				  "TX chain %d\n",
-				  chain);
+		ath_dbg(common, ATH_DBG_CALIBRATE,
+			"Sending PAPRD training frame on chain %d\n", chain);
+		if (!ath_paprd_send_frame(sc, skb, chain))
 			goto fail_paprd;
-		}
 
 		if (!ar9003_paprd_is_done(ah))
 			break;
@@ -457,7 +470,7 @@ void ath_ani_calibrate(unsigned long dat
 	/* Long calibration runs independently of short calibration. */
 	if ((timestamp - common->ani.longcal_timer) >= long_cal_interval) {
 		longcal = true;
-		ath_print(common, ATH_DBG_ANI, "longcal @%lu\n", jiffies);
+		ath_dbg(common, ATH_DBG_ANI, "longcal @%lu\n", jiffies);
 		common->ani.longcal_timer = timestamp;
 	}
 
@@ -465,8 +478,8 @@ void ath_ani_calibrate(unsigned long dat
 	if (!common->ani.caldone) {
 		if ((timestamp - common->ani.shortcal_timer) >= short_cal_interval) {
 			shortcal = true;
-			ath_print(common, ATH_DBG_ANI,
-				  "shortcal @%lu\n", jiffies);
+			ath_dbg(common, ATH_DBG_ANI,
+				"shortcal @%lu\n", jiffies);
 			common->ani.shortcal_timer = timestamp;
 			common->ani.resetcal_timer = timestamp;
 		}
@@ -525,49 +538,25 @@ set_timer:
 	if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_PAPRD) && ah->caldata) {
 		if (!ah->caldata->paprd_done)
 			ieee80211_queue_work(sc->hw, &sc->paprd_work);
-		else
+		else if (!ah->paprd_table_write_done)
 			ath_paprd_activate(sc);
 	}
 }
 
-/*
- * Update tx/rx chainmask. For legacy association,
- * hard code chainmask to 1x1, for 11n association, use
- * the chainmask configuration, for bt coexistence, use
- * the chainmask configuration even in legacy mode.
- */
-void ath_update_chainmask(struct ath_softc *sc, int is_ht)
-{
-	struct ath_hw *ah = sc->sc_ah;
-	struct ath_common *common = ath9k_hw_common(ah);
-
-	if ((sc->sc_flags & SC_OP_OFFCHANNEL) || is_ht ||
-	    (ah->btcoex_hw.scheme != ATH_BTCOEX_CFG_NONE)) {
-		common->tx_chainmask = ah->caps.tx_chainmask;
-		common->rx_chainmask = ah->caps.rx_chainmask;
-	} else {
-		common->tx_chainmask = 1;
-		common->rx_chainmask = 1;
-	}
-
-	ath_print(common, ATH_DBG_CONFIG,
-		  "tx chmask: %d, rx chmask: %d\n",
-		  common->tx_chainmask,
-		  common->rx_chainmask);
-}
-
 static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta)
 {
 	struct ath_node *an;
-
+	struct ath_hw *ah = sc->sc_ah;
 	an = (struct ath_node *)sta->drv_priv;
 
+	if ((ah->caps.hw_caps) & ATH9K_HW_CAP_APM)
+		sc->sc_flags |= SC_OP_ENABLE_APM;
+
 	if (sc->sc_flags & SC_OP_TXAGGR) {
 		ath_tx_node_init(sc, an);
 		an->maxampdu = 1 << (IEEE80211_HT_MAX_AMPDU_FACTOR +
 				     sta->ht_cap.ampdu_factor);
 		an->mpdudensity = parse_mpdudensity(sta->ht_cap.ampdu_density);
-		an->last_rssi = ATH_RSSI_DUMMY_MARKER;
 	}
 }
 
@@ -607,14 +596,14 @@ void ath9k_tasklet(unsigned long data)
 	u32 status = sc->intrstatus;
 	u32 rxmask;
 
-	ath9k_ps_wakeup(sc);
-
 	if (status & ATH9K_INT_FATAL) {
 		ath_reset(sc, true);
-		ath9k_ps_restore(sc);
 		return;
 	}
 
+	ath9k_ps_wakeup(sc);
+	spin_lock(&sc->sc_pcu_lock);
+
 	if (!ath9k_hw_check_alive(ah))
 		ieee80211_queue_work(sc->hw, &sc->hw_check_work);
 
@@ -625,15 +614,12 @@ void ath9k_tasklet(unsigned long data)
 		rxmask = (ATH9K_INT_RX | ATH9K_INT_RXEOL | ATH9K_INT_RXORN);
 
 	if (status & rxmask) {
-		spin_lock_bh(&sc->rx.pcu_lock);
-
 		/* Check for high priority Rx first */
 		if ((ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) &&
 		    (status & ATH9K_INT_RXHP))
 			ath_rx_tasklet(sc, 0, true);
 
 		ath_rx_tasklet(sc, 0, false);
-		spin_unlock_bh(&sc->rx.pcu_lock);
 	}
 
 	if (status & ATH9K_INT_TX) {
@@ -648,8 +634,8 @@ void ath9k_tasklet(unsigned long data)
 		 * TSF sync does not look correct; remain awake to sync with
 		 * the next Beacon.
 		 */
-		ath_print(common, ATH_DBG_PS,
-			  "TSFOOR - Sync with next Beacon\n");
+		ath_dbg(common, ATH_DBG_PS,
+			"TSFOOR - Sync with next Beacon\n");
 		sc->ps_flags |= PS_WAIT_FOR_BEACON | PS_BEACON_SYNC;
 	}
 
@@ -658,7 +644,9 @@ void ath9k_tasklet(unsigned long data)
 			ath_gen_timer_isr(sc->sc_ah);
 
 	/* re-enable hardware interrupt */
-	ath9k_hw_set_interrupts(ah, ah->imask);
+	ath9k_hw_enable_interrupts(ah);
+
+	spin_unlock(&sc->sc_pcu_lock);
 	ath9k_ps_restore(sc);
 }
 
@@ -757,7 +745,7 @@ irqreturn_t ath_isr(int irq, void *dev)
 		 * interrupt; otherwise it will continue to
 		 * fire.
 		 */
-		ath9k_hw_set_interrupts(ah, 0);
+		ath9k_hw_disable_interrupts(ah);
 		/*
 		 * Let the hal handle the event. We assume
 		 * it will clear whatever condition caused
@@ -766,11 +754,13 @@ irqreturn_t ath_isr(int irq, void *dev)
 		spin_lock(&common->cc_lock);
 		ath9k_hw_proc_mib_event(ah);
 		spin_unlock(&common->cc_lock);
-		ath9k_hw_set_interrupts(ah, ah->imask);
+		ath9k_hw_enable_interrupts(ah);
 	}
 
 	if (!(ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP))
 		if (status & ATH9K_INT_TIM_TIMER) {
+			if (ATH_DBG_WARN_ON_ONCE(sc->ps_idle))
+				goto chip_reset;
 			/* Clear RxAbort bit so that we can
 			 * receive frames */
 			ath9k_setpower(sc, ATH9K_PM_AWAKE);
@@ -783,8 +773,8 @@ chip_reset:
 	ath_debug_stat_interrupt(sc, status);
 
 	if (sched) {
-		/* turn off every interrupt except SWBA */
-		ath9k_hw_set_interrupts(ah, (ah->imask & ATH9K_INT_SWBA));
+		/* turn off every interrupt */
+		ath9k_hw_disable_interrupts(ah);
 		tasklet_schedule(&sc->intr_tq);
 	}
 
@@ -836,16 +826,18 @@ static u32 ath_get_extchanmode(struct at
 }
 
 static void ath9k_bss_assoc_info(struct ath_softc *sc,
+				 struct ieee80211_hw *hw,
 				 struct ieee80211_vif *vif,
 				 struct ieee80211_bss_conf *bss_conf)
 {
+	struct ath_wiphy *aphy = hw->priv;
 	struct ath_hw *ah = sc->sc_ah;
 	struct ath_common *common = ath9k_hw_common(ah);
 
 	if (bss_conf->assoc) {
-		ath_print(common, ATH_DBG_CONFIG,
-			  "Bss Info ASSOC %d, bssid: %pM\n",
-			   bss_conf->aid, common->curbssid);
+		ath_dbg(common, ATH_DBG_CONFIG,
+			"Bss Info ASSOC %d, bssid: %pM\n",
+			bss_conf->aid, common->curbssid);
 
 		/* New association, store aid */
 		common->curaid = bss_conf->aid;
@@ -862,12 +854,13 @@ static void ath9k_bss_assoc_info(struct
 		ath_beacon_config(sc, vif);
 
 		/* Reset rssi stats */
+		aphy->last_rssi = ATH_RSSI_DUMMY_MARKER;
 		sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER;
 
 		sc->sc_flags |= SC_OP_ANI_RUN;
 		ath_start_ani(common);
 	} else {
-		ath_print(common, ATH_DBG_CONFIG, "Bss Info DISASSOC\n");
+		ath_dbg(common, ATH_DBG_CONFIG, "Bss Info DISASSOC\n");
 		common->curaid = 0;
 		/* Stop ANI */
 		sc->sc_flags &= ~SC_OP_ANI_RUN;
@@ -883,31 +876,25 @@ void ath_radio_enable(struct ath_softc *
 	int r;
 
 	ath9k_ps_wakeup(sc);
+	spin_lock_bh(&sc->sc_pcu_lock);
+
 	ath9k_hw_configpcipowersave(ah, 0, 0);
 
 	if (!ah->curchan)
 		ah->curchan = ath_get_curchannel(sc, sc->hw);
 
-	spin_lock_bh(&sc->rx.pcu_lock);
-	spin_lock_bh(&sc->sc_resetlock);
 	r = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false);
 	if (r) {
-		ath_print(common, ATH_DBG_FATAL,
-			  "Unable to reset channel (%u MHz), "
-			  "reset status %d\n",
-			  channel->center_freq, r);
+		ath_err(common,
+			"Unable to reset channel (%u MHz), reset status %d\n",
+			channel->center_freq, r);
 	}
-	spin_unlock_bh(&sc->sc_resetlock);
 
 	ath_update_txpow(sc);
 	if (ath_startrecv(sc) != 0) {
-		ath_print(common, ATH_DBG_FATAL,
-			  "Unable to restart recv logic\n");
-		spin_unlock_bh(&sc->rx.pcu_lock);
-		return;
+		ath_err(common, "Unable to restart recv logic\n");
+		goto out;
 	}
-	spin_unlock_bh(&sc->rx.pcu_lock);
-
 	if (sc->sc_flags & SC_OP_BEACONS)
 		ath_beacon_config(sc, NULL);	/* restart beacons */
 
@@ -920,6 +907,9 @@ void ath_radio_enable(struct ath_softc *
 	ath9k_hw_set_gpio(ah, ah->led_pin, 0);
 
 	ieee80211_wake_queues(hw);
+out:
+	spin_unlock_bh(&sc->sc_pcu_lock);
+
 	ath9k_ps_restore(sc);
 }
 
@@ -930,6 +920,8 @@ void ath_radio_disable(struct ath_softc
 	int r;
 
 	ath9k_ps_wakeup(sc);
+	spin_lock_bh(&sc->sc_pcu_lock);
+
 	ieee80211_stop_queues(hw);
 
 	/*
@@ -942,35 +934,29 @@ void ath_radio_disable(struct ath_softc
 	}
 
 	/* Disable interrupts */
-	ath9k_hw_set_interrupts(ah, 0);
+	ath9k_hw_disable_interrupts(ah);
 
 	ath_drain_all_txq(sc, false);	/* clear pending tx frames */
 
-	spin_lock_bh(&sc->rx.pcu_lock);
-
 	ath_stoprecv(sc);		/* turn off frame recv */
 	ath_flushrecv(sc);		/* flush recv queue */
 
 	if (!ah->curchan)
 		ah->curchan = ath_get_curchannel(sc, hw);
 
-	spin_lock_bh(&sc->sc_resetlock);
 	r = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false);
 	if (r) {
-		ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL,
-			  "Unable to reset channel (%u MHz), "
-			  "reset status %d\n",
-			  channel->center_freq, r);
+		ath_err(ath9k_hw_common(sc->sc_ah),
+			"Unable to reset channel (%u MHz), reset status %d\n",
+			channel->center_freq, r);
 	}
-	spin_unlock_bh(&sc->sc_resetlock);
 
 	ath9k_hw_phy_disable(ah);
 
-	spin_unlock_bh(&sc->rx.pcu_lock);
-
 	ath9k_hw_configpcipowersave(ah, 1, 1);
+
+	spin_unlock_bh(&sc->sc_pcu_lock);
 	ath9k_ps_restore(sc);
-	ath9k_setpower(sc, ATH9K_PM_FULL_SLEEP);
 }
 
 int ath_reset(struct ath_softc *sc, bool retry_tx)
@@ -983,28 +969,24 @@ int ath_reset(struct ath_softc *sc, bool
 	/* Stop ANI */
 	del_timer_sync(&common->ani.timer);
 
+	ath9k_ps_wakeup(sc);
+	spin_lock_bh(&sc->sc_pcu_lock);
+
 	ieee80211_stop_queues(hw);
 
-	ath9k_hw_set_interrupts(ah, 0);
+	ath9k_hw_disable_interrupts(ah);
 	ath_drain_all_txq(sc, retry_tx);
 
-	spin_lock_bh(&sc->rx.pcu_lock);
-
 	ath_stoprecv(sc);
 	ath_flushrecv(sc);
 
-	spin_lock_bh(&sc->sc_resetlock);
 	r = ath9k_hw_reset(ah, sc->sc_ah->curchan, ah->caldata, false);
 	if (r)
-		ath_print(common, ATH_DBG_FATAL,
-			  "Unable to reset hardware; reset status %d\n", r);
-	spin_unlock_bh(&sc->sc_resetlock);
+		ath_err(common,
+			"Unable to reset hardware; reset status %d\n", r);
 
 	if (ath_startrecv(sc) != 0)
-		ath_print(common, ATH_DBG_FATAL,
-			  "Unable to start recv logic\n");
-
-	spin_unlock_bh(&sc->rx.pcu_lock);
+		ath_err(common, "Unable to start recv logic\n");
 
 	/*
 	 * We may be doing a reset in response to a request
@@ -1030,63 +1012,15 @@ int ath_reset(struct ath_softc *sc, bool
 	}
 
 	ieee80211_wake_queues(hw);
+	spin_unlock_bh(&sc->sc_pcu_lock);
 
 	/* Start ANI */
 	ath_start_ani(common);
+	ath9k_ps_restore(sc);
 
 	return r;
 }
 
-static int ath_get_hal_qnum(u16 queue, struct ath_softc *sc)
-{
-	int qnum;
-
-	switch (queue) {
-	case 0:
-		qnum = sc->tx.hwq_map[WME_AC_VO];
-		break;
-	case 1:
-		qnum = sc->tx.hwq_map[WME_AC_VI];
-		break;
-	case 2:
-		qnum = sc->tx.hwq_map[WME_AC_BE];
-		break;
-	case 3:
-		qnum = sc->tx.hwq_map[WME_AC_BK];
-		break;
-	default:
-		qnum = sc->tx.hwq_map[WME_AC_BE];
-		break;
-	}
-
-	return qnum;
-}
-
-int ath_get_mac80211_qnum(u32 queue, struct ath_softc *sc)
-{
-	int qnum;
-
-	switch (queue) {
-	case WME_AC_VO:
-		qnum = 0;
-		break;
-	case WME_AC_VI:
-		qnum = 1;
-		break;
-	case WME_AC_BE:
-		qnum = 2;
-		break;
-	case WME_AC_BK:
-		qnum = 3;
-		break;
-	default:
-		qnum = -1;
-		break;
-	}
-
-	return qnum;
-}
-
 /* XXX: Remove me once we don't depend on ath9k_channel for all
  * this redundant data */
 void ath9k_update_ichannel(struct ath_softc *sc, struct ieee80211_hw *hw,
@@ -1125,9 +1059,9 @@ static int ath9k_start(struct ieee80211_
 	struct ath9k_channel *init_channel;
 	int r;
 
-	ath_print(common, ATH_DBG_CONFIG,
-		  "Starting driver with initial channel: %d MHz\n",
-		  curchan->center_freq);
+	ath_dbg(common, ATH_DBG_CONFIG,
+		"Starting driver with initial channel: %d MHz\n",
+		curchan->center_freq);
 
 	mutex_lock(&sc->mutex);
 
@@ -1168,19 +1102,15 @@ static int ath9k_start(struct ieee80211_
 	 * be followed by initialization of the appropriate bits
 	 * and then setup of the interrupt mask.
 	 */
-	spin_lock_bh(&sc->rx.pcu_lock);
-	spin_lock_bh(&sc->sc_resetlock);
+	spin_lock_bh(&sc->sc_pcu_lock);
 	r = ath9k_hw_reset(ah, init_channel, ah->caldata, false);
 	if (r) {
-		ath_print(common, ATH_DBG_FATAL,
-			  "Unable to reset hardware; reset status %d "
-			  "(freq %u MHz)\n", r,
-			  curchan->center_freq);
-		spin_unlock_bh(&sc->sc_resetlock);
-		spin_unlock_bh(&sc->rx.pcu_lock);
+		ath_err(common,
+			"Unable to reset hardware; reset status %d (freq %u MHz)\n",
+			r, curchan->center_freq);
+		spin_unlock_bh(&sc->sc_pcu_lock);
 		goto mutex_unlock;
 	}
-	spin_unlock_bh(&sc->sc_resetlock);
 
 	/*
 	 * This is needed only to setup initial state
@@ -1196,13 +1126,12 @@ static int ath9k_start(struct ieee80211_
 	 * here except setup the interrupt mask.
 	 */
 	if (ath_startrecv(sc) != 0) {
-		ath_print(common, ATH_DBG_FATAL,
-			  "Unable to start recv logic\n");
+		ath_err(common, "Unable to start recv logic\n");
 		r = -EIO;
-		spin_unlock_bh(&sc->rx.pcu_lock);
+		spin_unlock_bh(&sc->sc_pcu_lock);
 		goto mutex_unlock;
 	}
-	spin_unlock_bh(&sc->rx.pcu_lock);
+	spin_unlock_bh(&sc->sc_pcu_lock);
 
 	/* Setup our intr mask. */
 	ah->imask = ATH9K_INT_TX | ATH9K_INT_RXEOL |
@@ -1244,7 +1173,8 @@ static int ath9k_start(struct ieee80211_
 			ath9k_btcoex_timer_resume(sc);
 	}
 
-	pm_qos_update_request(&sc->pm_qos_req, 55);
+	if (ah->caps.pcie_lcr_extsync_en && common->bus_ops->extn_synch_en)
+		common->bus_ops->extn_synch_en(common);
 
 mutex_unlock:
 	mutex_unlock(&sc->mutex);
@@ -1255,19 +1185,16 @@ mutex_unlock:
 static int ath9k_tx(struct ieee80211_hw *hw,
 		    struct sk_buff *skb)
 {
-	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
 	struct ath_wiphy *aphy = hw->priv;
 	struct ath_softc *sc = aphy->sc;
 	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
 	struct ath_tx_control txctl;
-	int padpos, padsize;
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
-	int qnum;
 
 	if (aphy->state != ATH_WIPHY_ACTIVE && aphy->state != ATH_WIPHY_SCAN) {
-		ath_print(common, ATH_DBG_XMIT,
-			  "ath9k: %s: TX in unexpected wiphy state "
-			  "%d\n", wiphy_name(hw->wiphy), aphy->state);
+		ath_dbg(common, ATH_DBG_XMIT,
+			"ath9k: %s: TX in unexpected wiphy state %d\n",
+			wiphy_name(hw->wiphy), aphy->state);
 		goto exit;
 	}
 
@@ -1279,8 +1206,8 @@ static int ath9k_tx(struct ieee80211_hw
 		if (ieee80211_is_data(hdr->frame_control) &&
 		    !ieee80211_is_nullfunc(hdr->frame_control) &&
 		    !ieee80211_has_pm(hdr->frame_control)) {
-			ath_print(common, ATH_DBG_PS, "Add PM=1 for a TX frame "
-				  "while in PS mode\n");
+			ath_dbg(common, ATH_DBG_PS,
+				"Add PM=1 for a TX frame while in PS mode\n");
 			hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM);
 		}
 	}
@@ -1295,12 +1222,12 @@ static int ath9k_tx(struct ieee80211_hw
 		if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP))
 			ath9k_hw_setrxabort(sc->sc_ah, 0);
 		if (ieee80211_is_pspoll(hdr->frame_control)) {
-			ath_print(common, ATH_DBG_PS,
-				  "Sending PS-Poll to pick a buffered frame\n");
+			ath_dbg(common, ATH_DBG_PS,
+				"Sending PS-Poll to pick a buffered frame\n");
 			sc->ps_flags |= PS_WAIT_FOR_PSPOLL_DATA;
 		} else {
-			ath_print(common, ATH_DBG_PS,
-				  "Wake up to complete TX\n");
+			ath_dbg(common, ATH_DBG_PS,
+				"Wake up to complete TX\n");
 			sc->ps_flags |= PS_WAIT_FOR_TX_ACK;
 		}
 		/*
@@ -1312,36 +1239,12 @@ static int ath9k_tx(struct ieee80211_hw
 	}
 
 	memset(&txctl, 0, sizeof(struct ath_tx_control));
+	txctl.txq = sc->tx.txq_map[skb_get_queue_mapping(skb)];
 
-	/*
-	 * As a temporary workaround, assign seq# here; this will likely need
-	 * to be cleaned up to work better with Beacon transmission and virtual
-	 * BSSes.
-	 */
-	if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
-		if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT)
-			sc->tx.seq_no += 0x10;
-		hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG);
-		hdr->seq_ctrl |= cpu_to_le16(sc->tx.seq_no);
-	}
-
-	/* Add the padding after the header if this is not already done */
-	padpos = ath9k_cmn_padpos(hdr->frame_control);
-	padsize = padpos & 3;
-	if (padsize && skb->len>padpos) {
-		if (skb_headroom(skb) < padsize)
-			return -1;
-		skb_push(skb, padsize);
-		memmove(skb->data, skb->data + padsize, padpos);
-	}
-
-	qnum = ath_get_hal_qnum(skb_get_queue_mapping(skb), sc);
-	txctl.txq = &sc->tx.txq[qnum];
-
-	ath_print(common, ATH_DBG_XMIT, "transmitting packet, skb: %p\n", skb);
+	ath_dbg(common, ATH_DBG_XMIT, "transmitting packet, skb: %p\n", skb);
 
 	if (ath_tx_start(hw, skb, &txctl) != 0) {
-		ath_print(common, ATH_DBG_XMIT, "TX failed\n");
+		ath_dbg(common, ATH_DBG_XMIT, "TX failed\n");
 		goto exit;
 	}
 
@@ -1381,7 +1284,7 @@ static void ath9k_stop(struct ieee80211_
 	}
 
 	if (sc->sc_flags & SC_OP_INVALID) {
-		ath_print(common, ATH_DBG_ANY, "Device not present\n");
+		ath_dbg(common, ATH_DBG_ANY, "Device not present\n");
 		mutex_unlock(&sc->mutex);
 		return;
 	}
@@ -1400,34 +1303,45 @@ static void ath9k_stop(struct ieee80211_
 			ath9k_btcoex_timer_pause(sc);
 	}
 
+	spin_lock_bh(&sc->sc_pcu_lock);
+
+	/* prevent tasklets to enable interrupts once we disable them */
+	ah->imask &= ~ATH9K_INT_GLOBAL;
+
 	/* make sure h/w will not generate any interrupt
 	 * before setting the invalid flag. */
-	ath9k_hw_set_interrupts(ah, 0);
+	ath9k_hw_disable_interrupts(ah);
 
-	spin_lock_bh(&sc->rx.pcu_lock);
 	if (!(sc->sc_flags & SC_OP_INVALID)) {
 		ath_drain_all_txq(sc, false);
 		ath_stoprecv(sc);
 		ath9k_hw_phy_disable(ah);
 	} else
 		sc->rx.rxlink = NULL;
-	spin_unlock_bh(&sc->rx.pcu_lock);
 
 	/* disable HAL and put h/w to sleep */
 	ath9k_hw_disable(ah);
 	ath9k_hw_configpcipowersave(ah, 1, 1);
+
+	spin_unlock_bh(&sc->sc_pcu_lock);
+
+	/* we can now sync irq and kill any running tasklets, since we already
+	 * disabled interrupts and not holding a spin lock */
+	synchronize_irq(sc->irq);
+	tasklet_kill(&sc->intr_tq);
+	tasklet_kill(&sc->bcon_tasklet);
+
 	ath9k_ps_restore(sc);
 
-	/* Finally, put the chip in FULL SLEEP mode */
-	ath9k_setpower(sc, ATH9K_PM_FULL_SLEEP);
+	sc->ps_idle = true;
+	ath9k_set_wiphy_idle(aphy, true);
+	ath_radio_disable(sc, hw);
 
 	sc->sc_flags |= SC_OP_INVALID;
 
-	pm_qos_update_request(&sc->pm_qos_req, PM_QOS_DEFAULT_VALUE);
-
 	mutex_unlock(&sc->mutex);
 
-	ath_print(common, ATH_DBG_CONFIG, "Driver halt\n");
+	ath_dbg(common, ATH_DBG_CONFIG, "Driver halt\n");
 }
 
 static int ath9k_add_interface(struct ieee80211_hw *hw,
@@ -1460,14 +1374,14 @@ static int ath9k_add_interface(struct ie
 		ic_opmode = vif->type;
 		break;
 	default:
-		ath_print(common, ATH_DBG_FATAL,
-			"Interface type %d not yet supported\n", vif->type);
+		ath_err(common, "Interface type %d not yet supported\n",
+			vif->type);
 		ret = -EOPNOTSUPP;
 		goto out;
 	}
 
-	ath_print(common, ATH_DBG_CONFIG,
-		  "Attach a VIF of type: %d\n", ic_opmode);
+	ath_dbg(common, ATH_DBG_CONFIG,
+		"Attach a VIF of type: %d\n", ic_opmode);
 
 	/* Set the VIF opmode */
 	avp->av_opmode = ic_opmode;
@@ -1513,15 +1427,83 @@ out:
 	return ret;
 }
 
+static void ath9k_reclaim_beacon(struct ath_softc *sc,
+				 struct ieee80211_vif *vif)
+{
+	struct ath_vif *avp = (void *)vif->drv_priv;
+
+	/* Disable SWBA interrupt */
+	sc->sc_ah->imask &= ~ATH9K_INT_SWBA;
+	ath9k_ps_wakeup(sc);
+	ath9k_hw_set_interrupts(sc->sc_ah, sc->sc_ah->imask);
+	ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq);
+	tasklet_kill(&sc->bcon_tasklet);
+	ath9k_ps_restore(sc);
+
+	ath_beacon_return(sc, avp);
+	sc->sc_flags &= ~SC_OP_BEACONS;
+
+	if (sc->nbcnvifs > 0) {
+		/* Re-enable beaconing */
+		sc->sc_ah->imask |= ATH9K_INT_SWBA;
+		ath9k_ps_wakeup(sc);
+		ath9k_hw_set_interrupts(sc->sc_ah, sc->sc_ah->imask);
+		ath9k_ps_restore(sc);
+	}
+}
+
+static int ath9k_change_interface(struct ieee80211_hw *hw,
+				  struct ieee80211_vif *vif,
+				  enum nl80211_iftype new_type,
+				  bool p2p)
+{
+	struct ath_wiphy *aphy = hw->priv;
+	struct ath_softc *sc = aphy->sc;
+	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+	int ret = 0;
+
+	ath_dbg(common, ATH_DBG_CONFIG, "Change Interface\n");
+	mutex_lock(&sc->mutex);
+
+	switch (new_type) {
+	case NL80211_IFTYPE_AP:
+	case NL80211_IFTYPE_ADHOC:
+		if (sc->nbcnvifs >= ATH_BCBUF) {
+			ath_err(common, "No beacon slot available\n");
+			ret = -ENOBUFS;
+			goto out;
+		}
+		break;
+	case NL80211_IFTYPE_STATION:
+		/* Stop ANI */
+		sc->sc_flags &= ~SC_OP_ANI_RUN;
+		del_timer_sync(&common->ani.timer);
+		if ((vif->type == NL80211_IFTYPE_AP) ||
+		    (vif->type == NL80211_IFTYPE_ADHOC))
+			ath9k_reclaim_beacon(sc, vif);
+		break;
+	default:
+		ath_err(common, "Interface type %d not yet supported\n",
+				vif->type);
+		ret = -ENOTSUPP;
+		goto out;
+	}
+	vif->type = new_type;
+	vif->p2p = p2p;
+
+out:
+	mutex_unlock(&sc->mutex);
+	return ret;
+}
+
 static void ath9k_remove_interface(struct ieee80211_hw *hw,
 				   struct ieee80211_vif *vif)
 {
 	struct ath_wiphy *aphy = hw->priv;
 	struct ath_softc *sc = aphy->sc;
 	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
-	struct ath_vif *avp = (void *)vif->drv_priv;
 
-	ath_print(common, ATH_DBG_CONFIG, "Detach Interface\n");
+	ath_dbg(common, ATH_DBG_CONFIG, "Detach Interface\n");
 
 	mutex_lock(&sc->mutex);
 
@@ -1532,26 +1514,8 @@ static void ath9k_remove_interface(struc
 	/* Reclaim beacon resources */
 	if ((sc->sc_ah->opmode == NL80211_IFTYPE_AP) ||
 	    (sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC) ||
-	    (sc->sc_ah->opmode == NL80211_IFTYPE_MESH_POINT)) {
-		/* Disable SWBA interrupt */
-		sc->sc_ah->imask &= ~ATH9K_INT_SWBA;
-		ath9k_ps_wakeup(sc);
-		ath9k_hw_set_interrupts(sc->sc_ah, sc->sc_ah->imask);
-		ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq);
-		ath9k_ps_restore(sc);
-		tasklet_kill(&sc->bcon_tasklet);
-	}
-
-	ath_beacon_return(sc, avp);
-	sc->sc_flags &= ~SC_OP_BEACONS;
-
-	if (sc->nbcnvifs) {
-		/* Re-enable SWBA interrupt */
-		sc->sc_ah->imask |= ATH9K_INT_SWBA;
-		ath9k_ps_wakeup(sc);
-		ath9k_hw_set_interrupts(sc->sc_ah, sc->sc_ah->imask);
-		ath9k_ps_restore(sc);
-	}
+	    (sc->sc_ah->opmode == NL80211_IFTYPE_MESH_POINT))
+		ath9k_reclaim_beacon(sc, vif);
 
 	sc->nvifs--;
 
@@ -1631,8 +1595,8 @@ static int ath9k_config(struct ieee80211
 		if (enable_radio) {
 			sc->ps_idle = false;
 			ath_radio_enable(sc, hw);
-			ath_print(common, ATH_DBG_CONFIG,
-				  "not-idle: enabling radio\n");
+			ath_dbg(common, ATH_DBG_CONFIG,
+				"not-idle: enabling radio\n");
 		}
 	}
 
@@ -1654,12 +1618,12 @@ static int ath9k_config(struct ieee80211
 
 	if (changed & IEEE80211_CONF_CHANGE_MONITOR) {
 		if (conf->flags & IEEE80211_CONF_MONITOR) {
-			ath_print(common, ATH_DBG_CONFIG,
-				  "Monitor mode is enabled\n");
+			ath_dbg(common, ATH_DBG_CONFIG,
+				"Monitor mode is enabled\n");
 			sc->sc_ah->is_monitoring = true;
 		} else {
-			ath_print(common, ATH_DBG_CONFIG,
-				  "Monitor mode is disabled\n");
+			ath_dbg(common, ATH_DBG_CONFIG,
+				"Monitor mode is disabled\n");
 			sc->sc_ah->is_monitoring = false;
 		}
 	}
@@ -1691,14 +1655,12 @@ static int ath9k_config(struct ieee80211
 			goto skip_chan_change;
 		}
 
-		ath_print(common, ATH_DBG_CONFIG, "Set channel: %d MHz\n",
-			  curchan->center_freq);
+		ath_dbg(common, ATH_DBG_CONFIG, "Set channel: %d MHz\n",
+			curchan->center_freq);
 
 		/* XXX: remove me eventualy */
 		ath9k_update_ichannel(sc, hw, &sc->sc_ah->channels[pos]);
 
-		ath_update_chainmask(sc, conf_is_ht(conf));
-
 		/* update survey stats for the old channel before switching */
 		spin_lock_irqsave(&common->cc_lock, flags);
 		ath_update_survey_stats(sc);
@@ -1725,8 +1687,7 @@ static int ath9k_config(struct ieee80211
 		}
 
 		if (ath_set_channel(sc, hw, &sc->sc_ah->channels[pos]) < 0) {
-			ath_print(common, ATH_DBG_FATAL,
-				  "Unable to set channel\n");
+			ath_err(common, "Unable to set channel\n");
 			mutex_unlock(&sc->mutex);
 			return -EINVAL;
 		}
@@ -1743,7 +1704,9 @@ static int ath9k_config(struct ieee80211
 skip_chan_change:
 	if (changed & IEEE80211_CONF_CHANGE_POWER) {
 		sc->config.txpowlimit = 2 * conf->power_level;
+		ath9k_ps_wakeup(sc);
 		ath_update_txpow(sc);
+		ath9k_ps_restore(sc);
 	}
 
 	spin_lock_bh(&sc->wiphy_lock);
@@ -1751,7 +1714,7 @@ skip_chan_change:
 	spin_unlock_bh(&sc->wiphy_lock);
 
 	if (disable_radio) {
-		ath_print(common, ATH_DBG_CONFIG, "idle: disabling radio\n");
+		ath_dbg(common, ATH_DBG_CONFIG, "idle: disabling radio\n");
 		sc->ps_idle = true;
 		ath_radio_disable(sc, hw);
 	}
@@ -1790,8 +1753,8 @@ static void ath9k_configure_filter(struc
 	ath9k_hw_setrxfilter(sc->sc_ah, rfilt);
 	ath9k_ps_restore(sc);
 
-	ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_CONFIG,
-		  "Set HW RX filter: 0x%x\n", rfilt);
+	ath_dbg(ath9k_hw_common(sc->sc_ah), ATH_DBG_CONFIG,
+		"Set HW RX filter: 0x%x\n", rfilt);
 }
 
 static int ath9k_sta_add(struct ieee80211_hw *hw,
@@ -1824,12 +1787,15 @@ static int ath9k_conf_tx(struct ieee8021
 	struct ath_wiphy *aphy = hw->priv;
 	struct ath_softc *sc = aphy->sc;
 	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+	struct ath_txq *txq;
 	struct ath9k_tx_queue_info qi;
-	int ret = 0, qnum;
+	int ret = 0;
 
 	if (queue >= WME_NUM_AC)
 		return 0;
 
+	txq = sc->tx.txq_map[queue];
+
 	mutex_lock(&sc->mutex);
 
 	memset(&qi, 0, sizeof(struct ath9k_tx_queue_info));
@@ -1838,20 +1804,18 @@ static int ath9k_conf_tx(struct ieee8021
 	qi.tqi_cwmin = params->cw_min;
 	qi.tqi_cwmax = params->cw_max;
 	qi.tqi_burstTime = params->txop;
-	qnum = ath_get_hal_qnum(queue, sc);
 
-	ath_print(common, ATH_DBG_CONFIG,
-		  "Configure tx [queue/halq] [%d/%d],  "
-		  "aifs: %d, cw_min: %d, cw_max: %d, txop: %d\n",
-		  queue, qnum, params->aifs, params->cw_min,
-		  params->cw_max, params->txop);
+	ath_dbg(common, ATH_DBG_CONFIG,
+		"Configure tx [queue/halq] [%d/%d], aifs: %d, cw_min: %d, cw_max: %d, txop: %d\n",
+		queue, txq->axq_qnum, params->aifs, params->cw_min,
+		params->cw_max, params->txop);
 
-	ret = ath_txq_update(sc, qnum, &qi);
+	ret = ath_txq_update(sc, txq->axq_qnum, &qi);
 	if (ret)
-		ath_print(common, ATH_DBG_FATAL, "TXQ Update failed\n");
+		ath_err(common, "TXQ Update failed\n");
 
 	if (sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC)
-		if ((qnum == sc->tx.hwq_map[WME_AC_BE]) && !ret)
+		if (queue == WME_AC_BE && !ret)
 			ath_beaconq_config(sc);
 
 	mutex_unlock(&sc->mutex);
@@ -1870,12 +1834,12 @@ static int ath9k_set_key(struct ieee8021
 	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
 	int ret = 0;
 
-	if (modparam_nohwcrypt)
+	if (ath9k_modparam_nohwcrypt)
 		return -ENOSPC;
 
 	mutex_lock(&sc->mutex);
 	ath9k_ps_wakeup(sc);
-	ath_print(common, ATH_DBG_CONFIG, "Set HW Key\n");
+	ath_dbg(common, ATH_DBG_CONFIG, "Set HW Key\n");
 
 	switch (cmd) {
 	case SET_KEY:
@@ -1930,13 +1894,8 @@ static void ath9k_bss_info_changed(struc
 		/* Set aggregation protection mode parameters */
 		sc->config.ath_aggr_prot = 0;
 
-		/* Only legacy IBSS for now */
-		if (vif->type == NL80211_IFTYPE_ADHOC)
-			ath_update_chainmask(sc, 0);
-
-		ath_print(common, ATH_DBG_CONFIG,
-			  "BSSID: %pM aid: 0x%x\n",
-			  common->curbssid, common->curaid);
+		ath_dbg(common, ATH_DBG_CONFIG, "BSSID: %pM aid: 0x%x\n",
+			common->curbssid, common->curaid);
 
 		/* need to reconfigure the beacon */
 		sc->sc_flags &= ~SC_OP_BEACONS ;
@@ -1992,8 +1951,8 @@ static void ath9k_bss_info_changed(struc
 	}
 
 	if (changed & BSS_CHANGED_ERP_PREAMBLE) {
-		ath_print(common, ATH_DBG_CONFIG, "BSS Changed PREAMBLE %d\n",
-			  bss_conf->use_short_preamble);
+		ath_dbg(common, ATH_DBG_CONFIG, "BSS Changed PREAMBLE %d\n",
+			bss_conf->use_short_preamble);
 		if (bss_conf->use_short_preamble)
 			sc->sc_flags |= SC_OP_PREAMBLE_SHORT;
 		else
@@ -2001,8 +1960,8 @@ static void ath9k_bss_info_changed(struc
 	}
 
 	if (changed & BSS_CHANGED_ERP_CTS_PROT) {
-		ath_print(common, ATH_DBG_CONFIG, "BSS Changed CTS PROT %d\n",
-			  bss_conf->use_cts_prot);
+		ath_dbg(common, ATH_DBG_CONFIG, "BSS Changed CTS PROT %d\n",
+			bss_conf->use_cts_prot);
 		if (bss_conf->use_cts_prot &&
 		    hw->conf.channel->band != IEEE80211_BAND_5GHZ)
 			sc->sc_flags |= SC_OP_PROTECT_ENABLE;
@@ -2011,9 +1970,9 @@ static void ath9k_bss_info_changed(struc
 	}
 
 	if (changed & BSS_CHANGED_ASSOC) {
-		ath_print(common, ATH_DBG_CONFIG, "BSS Changed ASSOC %d\n",
+		ath_dbg(common, ATH_DBG_CONFIG, "BSS Changed ASSOC %d\n",
 			bss_conf->assoc);
-		ath9k_bss_assoc_info(sc, vif, bss_conf);
+		ath9k_bss_assoc_info(sc, hw, vif, bss_conf);
 	}
 
 	mutex_unlock(&sc->mutex);
@@ -2026,7 +1985,9 @@ static u64 ath9k_get_tsf(struct ieee8021
 	struct ath_softc *sc = aphy->sc;
 
 	mutex_lock(&sc->mutex);
+	ath9k_ps_wakeup(sc);
 	tsf = ath9k_hw_gettsf64(sc->sc_ah);
+	ath9k_ps_restore(sc);
 	mutex_unlock(&sc->mutex);
 
 	return tsf;
@@ -2038,7 +1999,9 @@ static void ath9k_set_tsf(struct ieee802
 	struct ath_softc *sc = aphy->sc;
 
 	mutex_lock(&sc->mutex);
+	ath9k_ps_wakeup(sc);
 	ath9k_hw_settsf64(sc->sc_ah, tsf);
+	ath9k_ps_restore(sc);
 	mutex_unlock(&sc->mutex);
 }
 
@@ -2076,6 +2039,9 @@ static int ath9k_ampdu_action(struct iee
 	case IEEE80211_AMPDU_RX_STOP:
 		break;
 	case IEEE80211_AMPDU_TX_START:
+		if (!(sc->sc_flags & SC_OP_TXAGGR))
+			return -EOPNOTSUPP;
+
 		ath9k_ps_wakeup(sc);
 		ret = ath_tx_aggr_start(sc, sta, tid, ssn);
 		if (!ret)
@@ -2094,8 +2060,7 @@ static int ath9k_ampdu_action(struct iee
 		ath9k_ps_restore(sc);
 		break;
 	default:
-		ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL,
-			  "Unknown AMPDU action\n");
+		ath_err(ath9k_hw_common(sc->sc_ah), "Unknown AMPDU action\n");
 	}
 
 	local_bh_enable();
@@ -2195,6 +2160,7 @@ struct ieee80211_ops ath9k_ops = {
 	.start 		    = ath9k_start,
 	.stop 		    = ath9k_stop,
 	.add_interface 	    = ath9k_add_interface,
+	.change_interface   = ath9k_change_interface,
 	.remove_interface   = ath9k_remove_interface,
 	.config 	    = ath9k_config,
 	.configure_filter   = ath9k_configure_filter,
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/pci.c linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/pci.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/pci.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/pci.c	2011-03-14 21:20:32.000000000 -0400
@@ -16,6 +16,7 @@
 
 #include <linux/nl80211.h>
 #include <linux/pci.h>
+#include <linux/ath9k_platform.h>
 #include "ath9k.h"
 
 static DEFINE_PCI_DEVICE_TABLE(ath_pci_id_table) = {
@@ -29,6 +30,7 @@ static DEFINE_PCI_DEVICE_TABLE(ath_pci_i
 	{ PCI_VDEVICE(ATHEROS, 0x002D) }, /* PCI   */
 	{ PCI_VDEVICE(ATHEROS, 0x002E) }, /* PCI-E */
 	{ PCI_VDEVICE(ATHEROS, 0x0030) }, /* PCI-E  AR9300 */
+	{ PCI_VDEVICE(ATHEROS, 0x0032) }, /* PCI-E  AR9485 */
 	{ 0 }
 };
 
@@ -53,20 +55,34 @@ static void ath_pci_read_cachesize(struc
 
 static bool ath_pci_eeprom_read(struct ath_common *common, u32 off, u16 *data)
 {
-	struct ath_hw *ah = (struct ath_hw *) common->ah;
+	struct ath_softc *sc = (struct ath_softc *) common->priv;
+	struct ath9k_platform_data *pdata = sc->dev->platform_data;
 
-	common->ops->read(ah, AR5416_EEPROM_OFFSET + (off << AR5416_EEPROM_S));
+	if (pdata) {
+		if (off >= (ARRAY_SIZE(pdata->eeprom_data))) {
+			ath_err(common,
+				"%s: eeprom read failed, offset %08x is out of range\n",
+				__func__, off);
+		}
 
-	if (!ath9k_hw_wait(ah,
-			   AR_EEPROM_STATUS_DATA,
-			   AR_EEPROM_STATUS_DATA_BUSY |
-			   AR_EEPROM_STATUS_DATA_PROT_ACCESS, 0,
-			   AH_WAIT_TIMEOUT)) {
-		return false;
-	}
+		*data = pdata->eeprom_data[off];
+	} else {
+		struct ath_hw *ah = (struct ath_hw *) common->ah;
 
-	*data = MS(common->ops->read(ah, AR_EEPROM_STATUS_DATA),
-		   AR_EEPROM_STATUS_DATA_VAL);
+		common->ops->read(ah, AR5416_EEPROM_OFFSET +
+				      (off << AR5416_EEPROM_S));
+
+		if (!ath9k_hw_wait(ah,
+				   AR_EEPROM_STATUS_DATA,
+				   AR_EEPROM_STATUS_DATA_BUSY |
+				   AR_EEPROM_STATUS_DATA_PROT_ACCESS, 0,
+				   AH_WAIT_TIMEOUT)) {
+			return false;
+		}
+
+		*data = MS(common->ops->read(ah, AR_EEPROM_STATUS_DATA),
+			   AR_EEPROM_STATUS_DATA_VAL);
+	}
 
 	return true;
 }
@@ -80,7 +96,7 @@ static void ath_pci_bt_coex_prep(struct
 	struct pci_dev *pdev = to_pci_dev(sc->dev);
 	u8 aspm;
 
-	if (!pdev->is_pcie)
+	if (!pci_is_pcie(pdev))
 		return;
 
 	pci_read_config_byte(pdev, ATH_PCIE_CAP_LINK_CTRL, &aspm);
@@ -88,11 +104,23 @@ static void ath_pci_bt_coex_prep(struct
 	pci_write_config_byte(pdev, ATH_PCIE_CAP_LINK_CTRL, aspm);
 }
 
+static void ath_pci_extn_synch_enable(struct ath_common *common)
+{
+	struct ath_softc *sc = (struct ath_softc *) common->priv;
+	struct pci_dev *pdev = to_pci_dev(sc->dev);
+	u8 lnkctl;
+
+	pci_read_config_byte(pdev, sc->sc_ah->caps.pcie_lcr_offset, &lnkctl);
+	lnkctl |= PCI_EXP_LNKCTL_ES;
+	pci_write_config_byte(pdev, sc->sc_ah->caps.pcie_lcr_offset, lnkctl);
+}
+
 static const struct ath_bus_ops ath_pci_bus_ops = {
 	.ath_bus_type = ATH_PCI,
 	.read_cachesize = ath_pci_read_cachesize,
 	.eeprom_read = ath_pci_eeprom_read,
 	.bt_coex_prep = ath_pci_bt_coex_prep,
+	.extn_synch_en = ath_pci_extn_synch_enable,
 };
 
 static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
@@ -236,6 +264,8 @@ static void ath_pci_remove(struct pci_de
 	struct ath_softc *sc = aphy->sc;
 	void __iomem *mem = sc->mem;
 
+	if (!is_ath9k_unloaded)
+		sc->sc_ah->ah_flags |= AH_UNPLUGGED;
 	ath9k_deinit_device(sc);
 	free_irq(sc->irq, sc);
 	ieee80211_free_hw(sc->hw);
@@ -247,34 +277,25 @@ static void ath_pci_remove(struct pci_de
 
 #ifdef CONFIG_PM
 
-static int ath_pci_suspend(struct pci_dev *pdev, pm_message_t state)
+static int ath_pci_suspend(struct device *device)
 {
+	struct pci_dev *pdev = to_pci_dev(device);
 	struct ieee80211_hw *hw = pci_get_drvdata(pdev);
 	struct ath_wiphy *aphy = hw->priv;
 	struct ath_softc *sc = aphy->sc;
 
 	ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 1);
 
-	pci_save_state(pdev);
-	pci_disable_device(pdev);
-	pci_set_power_state(pdev, PCI_D3hot);
-
 	return 0;
 }
 
-static int ath_pci_resume(struct pci_dev *pdev)
+static int ath_pci_resume(struct device *device)
 {
+	struct pci_dev *pdev = to_pci_dev(device);
 	struct ieee80211_hw *hw = pci_get_drvdata(pdev);
 	struct ath_wiphy *aphy = hw->priv;
 	struct ath_softc *sc = aphy->sc;
 	u32 val;
-	int err;
-
-	pci_restore_state(pdev);
-
-	err = pci_enable_device(pdev);
-	if (err)
-		return err;
 
 	/*
 	 * Suspend/Resume resets the PCI configuration space, so we have to
@@ -290,10 +311,38 @@ static int ath_pci_resume(struct pci_dev
 			    AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
 	ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 1);
 
+	  /*
+	   * Reset key cache to sane defaults (all entries cleared) instead of
+	   * semi-random values after suspend/resume.
+	   */
+	ath9k_ps_wakeup(sc);
+	ath9k_init_crypto(sc);
+	ath9k_ps_restore(sc);
+
+	sc->ps_idle = true;
+	ath9k_set_wiphy_idle(aphy, true);
+	ath_radio_disable(sc, hw);
+
 	return 0;
 }
 
-#endif /* CONFIG_PM */
+static const struct dev_pm_ops ath9k_pm_ops = {
+	.suspend = ath_pci_suspend,
+	.resume = ath_pci_resume,
+	.freeze = ath_pci_suspend,
+	.thaw = ath_pci_resume,
+	.poweroff = ath_pci_suspend,
+	.restore = ath_pci_resume,
+};
+
+#define ATH9K_PM_OPS	(&ath9k_pm_ops)
+
+#else /* !CONFIG_PM */
+
+#define ATH9K_PM_OPS	NULL
+
+#endif /* !CONFIG_PM */
+
 
 MODULE_DEVICE_TABLE(pci, ath_pci_id_table);
 
@@ -302,10 +351,7 @@ static struct pci_driver ath_pci_driver
 	.id_table   = ath_pci_id_table,
 	.probe      = ath_pci_probe,
 	.remove     = ath_pci_remove,
-#ifdef CONFIG_PM
-	.suspend    = ath_pci_suspend,
-	.resume     = ath_pci_resume,
-#endif /* CONFIG_PM */
+	.driver.pm  = ATH9K_PM_OPS,
 };
 
 int ath_pci_init(void)
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/phy.h linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/phy.h
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/phy.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/phy.h	2011-03-14 21:20:32.000000000 -0400
@@ -19,6 +19,7 @@
 
 #define CHANSEL_DIV		15
 #define CHANSEL_2G(_freq)	(((_freq) * 0x10000) / CHANSEL_DIV)
+#define CHANSEL_2G_9485(_freq)	((((_freq) * 0x10000) - 215) / CHANSEL_DIV)
 #define CHANSEL_5G(_freq)	(((_freq) * 0x8000) / CHANSEL_DIV)
 
 #define AR_PHY_BASE     0x9800
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/rc.c linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/rc.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/rc.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/rc.c	2011-03-14 21:20:32.000000000 -0400
@@ -381,25 +381,6 @@ static const struct ath_rate_table ar541
 static int ath_rc_get_rateindex(const struct ath_rate_table *rate_table,
 				struct ieee80211_tx_rate *rate);
 
-static inline int8_t median(int8_t a, int8_t b, int8_t c)
-{
-	if (a >= b) {
-		if (b >= c)
-			return b;
-		else if (a > c)
-			return c;
-		else
-			return a;
-	} else {
-		if (a >= c)
-			return a;
-		else if (b >= c)
-			return c;
-		else
-			return b;
-	}
-}
-
 static void ath_rc_sort_validrates(const struct ath_rate_table *rate_table,
 				   struct ath_rate_priv *ath_rc_priv)
 {
@@ -419,7 +400,7 @@ static void ath_rc_sort_validrates(const
 	}
 }
 
-static void ath_rc_init_valid_txmask(struct ath_rate_priv *ath_rc_priv)
+static void ath_rc_init_valid_rate_idx(struct ath_rate_priv *ath_rc_priv)
 {
 	u8 i;
 
@@ -427,7 +408,7 @@ static void ath_rc_init_valid_txmask(str
 		ath_rc_priv->valid_rate_index[i] = 0;
 }
 
-static inline void ath_rc_set_valid_txmask(struct ath_rate_priv *ath_rc_priv,
+static inline void ath_rc_set_valid_rate_idx(struct ath_rate_priv *ath_rc_priv,
 					   u8 index, int valid_tx_rate)
 {
 	BUG_ON(index > ath_rc_priv->rate_table_size);
@@ -508,7 +489,7 @@ static u8 ath_rc_init_validrates(struct
 
 			ath_rc_priv->valid_phy_rateidx[phy][valid_rate_count] = i;
 			ath_rc_priv->valid_phy_ratecnt[phy] += 1;
-			ath_rc_set_valid_txmask(ath_rc_priv, i, 1);
+			ath_rc_set_valid_rate_idx(ath_rc_priv, i, 1);
 			hi = i;
 		}
 	}
@@ -551,7 +532,7 @@ static u8 ath_rc_setvalid_rates(struct a
 				ath_rc_priv->valid_phy_rateidx[phy]
 					[valid_rate_count] = j;
 				ath_rc_priv->valid_phy_ratecnt[phy] += 1;
-				ath_rc_set_valid_txmask(ath_rc_priv, j, 1);
+				ath_rc_set_valid_rate_idx(ath_rc_priv, j, 1);
 				hi = A_MAX(hi, j);
 			}
 		}
@@ -587,7 +568,7 @@ static u8 ath_rc_setvalid_htrates(struct
 			ath_rc_priv->valid_phy_rateidx[phy]
 				[ath_rc_priv->valid_phy_ratecnt[phy]] = j;
 			ath_rc_priv->valid_phy_ratecnt[phy] += 1;
-			ath_rc_set_valid_txmask(ath_rc_priv, j, 1);
+			ath_rc_set_valid_rate_idx(ath_rc_priv, j, 1);
 			hi = A_MAX(hi, j);
 		}
 	}
@@ -883,7 +864,7 @@ static bool ath_rc_update_per(struct ath
 	bool state_change = false;
 	int count, n_bad_frames;
 	u8 last_per;
-	static u32 nretry_to_per_lookup[10] = {
+	static const u32 nretry_to_per_lookup[10] = {
 		100 * 0 / 1,
 		100 * 1 / 4,
 		100 * 1 / 2,
@@ -1106,13 +1087,13 @@ static int ath_rc_get_rateindex(const st
 				struct ieee80211_tx_rate *rate)
 {
 	int rix = 0, i = 0;
-	int mcs_rix_off[] = { 7, 15, 20, 21, 22, 23 };
+	static const int mcs_rix_off[] = { 7, 15, 20, 21, 22, 23 };
 
 	if (!(rate->flags & IEEE80211_TX_RC_MCS))
 		return rate->idx;
 
 	while (rate->idx > mcs_rix_off[i] &&
-	      i < sizeof(mcs_rix_off)/sizeof(int)) {
+	       i < ARRAY_SIZE(mcs_rix_off)) {
 		rix++; i++;
 	}
 
@@ -1203,7 +1184,7 @@ struct ath_rate_table *ath_choose_rate_t
 			return &ar5416_11na_ratetable;
 		return &ar5416_11a_ratetable;
 	default:
-		ath_print(common, ATH_DBG_CONFIG, "Invalid band\n");
+		ath_dbg(common, ATH_DBG_CONFIG, "Invalid band\n");
 		return NULL;
 	}
 }
@@ -1229,7 +1210,7 @@ static void ath_rc_init(struct ath_softc
 	}
 
 	/* Determine the valid rates */
-	ath_rc_init_valid_txmask(ath_rc_priv);
+	ath_rc_init_valid_rate_idx(ath_rc_priv);
 
 	for (i = 0; i < WLAN_RC_PHY_MAX; i++) {
 		for (j = 0; j < MAX_TX_RATE_PHY; j++)
@@ -1278,9 +1259,9 @@ static void ath_rc_init(struct ath_softc
 	ath_rc_priv->rate_max_phy = ath_rc_priv->valid_rate_index[k-4];
 	ath_rc_priv->rate_table = rate_table;
 
-	ath_print(common, ATH_DBG_CONFIG,
-		  "RC Initialized with capabilities: 0x%x\n",
-		  ath_rc_priv->ht_cap);
+	ath_dbg(common, ATH_DBG_CONFIG,
+		"RC Initialized with capabilities: 0x%x\n",
+		ath_rc_priv->ht_cap);
 }
 
 static u8 ath_rc_build_ht_caps(struct ath_softc *sc, struct ieee80211_sta *sta,
@@ -1340,7 +1321,7 @@ static void ath_tx_status(void *priv, st
 	struct ath_rate_priv *ath_rc_priv = priv_sta;
 	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
 	struct ieee80211_hdr *hdr;
-	int final_ts_idx = 0, tx_status = 0, is_underrun = 0;
+	int final_ts_idx = 0, tx_status = 0;
 	int long_retry = 0;
 	__le16 fc;
 	int i;
@@ -1373,32 +1354,17 @@ static void ath_tx_status(void *priv, st
 		tx_info->status.ampdu_len = 1;
 	}
 
-	/*
-	 * If an underrun error is seen assume it as an excessive retry only
-	 * if max frame trigger level has been reached (2 KB for singel stream,
-	 * and 4 KB for dual stream). Adjust the long retry as if the frame was
-	 * tried hw->max_rate_tries times to affect how ratectrl updates PER for
-	 * the failed rate. In case of congestion on the bus penalizing these
-	 * type of underruns should help hardware actually transmit new frames
-	 * successfully by eventually preferring slower rates. This itself
-	 * should also alleviate congestion on the bus.
-	 */
-	if ((tx_info->pad[0] & ATH_TX_INFO_UNDERRUN) &&
-	    (sc->sc_ah->tx_trig_level >= ath_rc_priv->tx_triglevel_max)) {
-		tx_status = 1;
-		is_underrun = 1;
-	}
-
-	if (tx_info->pad[0] & ATH_TX_INFO_XRETRY)
+	if (!(tx_info->flags & IEEE80211_TX_STAT_ACK))
 		tx_status = 1;
 
 	ath_rc_tx_status(sc, ath_rc_priv, tx_info, final_ts_idx, tx_status,
-			 (is_underrun) ? sc->hw->max_rate_tries : long_retry);
+			 long_retry);
 
 	/* Check if aggregation has to be enabled for this tid */
 	if (conf_is_ht(&sc->hw->conf) &&
 	    !(skb->protocol == cpu_to_be16(ETH_P_PAE))) {
-		if (ieee80211_is_data_qos(fc)) {
+		if (ieee80211_is_data_qos(fc) &&
+		    skb_get_queue_mapping(skb) != IEEE80211_AC_VO) {
 			u8 *qc, tid;
 			struct ath_node *an;
 
@@ -1407,7 +1373,7 @@ static void ath_tx_status(void *priv, st
 			an = (struct ath_node *)sta->drv_priv;
 
 			if(ath_tx_aggr_check(sc, an, tid))
-				ieee80211_start_tx_ba_session(sta, tid);
+				ieee80211_start_tx_ba_session(sta, tid, 0);
 		}
 	}
 
@@ -1444,12 +1410,12 @@ static void ath_rate_init(void *priv, st
 		ath_rc_priv->neg_ht_rates.rs_nrates = j;
 	}
 
-	is_cw40 = sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40;
+	is_cw40 = !!(sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40);
 
 	if (is_cw40)
-		is_sgi = sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40;
+		is_sgi = !!(sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40);
 	else if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_SGI_20)
-		is_sgi = sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20;
+		is_sgi = !!(sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20);
 
 	/* Choose rate table first */
 
@@ -1468,10 +1434,8 @@ static void ath_rate_update(void *priv,
 	struct ath_rate_priv *ath_rc_priv = priv_sta;
 	const struct ath_rate_table *rate_table = NULL;
 	bool oper_cw40 = false, oper_sgi;
-	bool local_cw40 = (ath_rc_priv->ht_cap & WLAN_RC_40_FLAG) ?
-		true : false;
-	bool local_sgi = (ath_rc_priv->ht_cap & WLAN_RC_SGI_FLAG) ?
-		true : false;
+	bool local_cw40 = !!(ath_rc_priv->ht_cap & WLAN_RC_40_FLAG);
+	bool local_sgi = !!(ath_rc_priv->ht_cap & WLAN_RC_SGI_FLAG);
 
 	/* FIXME: Handle AP mode later when we support CWM */
 
@@ -1499,9 +1463,9 @@ static void ath_rate_update(void *priv,
 						   oper_cw40, oper_sgi);
 			ath_rc_init(sc, priv_sta, sband, sta, rate_table);
 
-			ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_CONFIG,
-				  "Operating HT Bandwidth changed to: %d\n",
-				  sc->hw->conf.channel_type);
+			ath_dbg(ath9k_hw_common(sc->sc_ah), ATH_DBG_CONFIG,
+				"Operating HT Bandwidth changed to: %d\n",
+				sc->hw->conf.channel_type);
 		}
 	}
 }
@@ -1612,13 +1576,11 @@ static void *ath_rate_alloc_sta(void *pr
 
 	rate_priv = kzalloc(sizeof(struct ath_rate_priv), gfp);
 	if (!rate_priv) {
-		ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL,
-			  "Unable to allocate private rc structure\n");
+		ath_err(ath9k_hw_common(sc->sc_ah),
+			"Unable to allocate private rc structure\n");
 		return NULL;
 	}
 
-	rate_priv->tx_triglevel_max = sc->sc_ah->caps.tx_triglevel_max;
-
 	return rate_priv;
 }
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/rc.h linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/rc.h
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/rc.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/rc.h	2011-03-14 21:20:32.000000000 -0400
@@ -195,7 +195,6 @@ struct ath_rc_stats {
  * @rate_max_phy: phy index for the max rate
  * @per: PER for every valid rate in %
  * @probe_interval: interval for ratectrl to probe for other rates
- * @prev_data_rix: rate idx of last data frame
  * @ht_cap: HT capabilities
  * @neg_rates: Negotatied rates
  * @neg_ht_rates: Negotiated HT rates
@@ -214,22 +213,14 @@ struct ath_rate_priv {
 	u32 probe_time;
 	u32 per_down_time;
 	u32 probe_interval;
-	u32 prev_data_rix;
-	u32 tx_triglevel_max;
 	struct ath_rateset neg_rates;
 	struct ath_rateset neg_ht_rates;
-	struct ath_rate_softc *asc;
 	const struct ath_rate_table *rate_table;
 
 	struct dentry *debugfs_rcstats;
 	struct ath_rc_stats rcstats[RATE_TABLE_SIZE];
 };
 
-#define ATH_TX_INFO_FRAME_TYPE_INTERNAL	(1 << 0)
-#define ATH_TX_INFO_FRAME_TYPE_PAUSE	(1 << 1)
-#define ATH_TX_INFO_XRETRY		(1 << 3)
-#define ATH_TX_INFO_UNDERRUN		(1 << 4)
-
 enum ath9k_internal_frame_type {
 	ATH9K_IFT_NOT_INTERNAL,
 	ATH9K_IFT_PAUSE,
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/recv.c linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/recv.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/recv.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/recv.c	2011-03-14 21:20:32.000000000 -0400
@@ -165,7 +165,7 @@ static void ath_rx_addbuffer_edma(struct
 	u32 nbuf = 0;
 
 	if (list_empty(&sc->rx.rxbuf)) {
-		ath_print(common, ATH_DBG_QUEUE, "No free rx buf available\n");
+		ath_dbg(common, ATH_DBG_QUEUE, "No free rx buf available\n");
 		return;
 	}
 
@@ -269,7 +269,7 @@ static int ath_rx_edma_init(struct ath_s
 				dev_kfree_skb_any(skb);
 				bf->bf_mpdu = NULL;
 				bf->bf_buf_addr = 0;
-				ath_print(common, ATH_DBG_FATAL,
+				ath_err(common,
 					"dma_mapping_error() on RX init\n");
 				error = -ENOMEM;
 				goto rx_init_fail;
@@ -317,7 +317,7 @@ int ath_rx_init(struct ath_softc *sc, in
 	struct ath_buf *bf;
 	int error = 0;
 
-	spin_lock_init(&sc->rx.pcu_lock);
+	spin_lock_init(&sc->sc_pcu_lock);
 	sc->sc_flags &= ~SC_OP_RXFLUSH;
 	spin_lock_init(&sc->rx.rxbuflock);
 
@@ -327,17 +327,17 @@ int ath_rx_init(struct ath_softc *sc, in
 		common->rx_bufsize = roundup(IEEE80211_MAX_MPDU_LEN,
 				min(common->cachelsz, (u16)64));
 
-		ath_print(common, ATH_DBG_CONFIG, "cachelsz %u rxbufsize %u\n",
-				common->cachelsz, common->rx_bufsize);
+		ath_dbg(common, ATH_DBG_CONFIG, "cachelsz %u rxbufsize %u\n",
+			common->cachelsz, common->rx_bufsize);
 
 		/* Initialize rx descriptors */
 
 		error = ath_descdma_setup(sc, &sc->rx.rxdma, &sc->rx.rxbuf,
 				"rx", nbufs, 1, 0);
 		if (error != 0) {
-			ath_print(common, ATH_DBG_FATAL,
-				  "failed to allocate rx descriptors: %d\n",
-				  error);
+			ath_err(common,
+				"failed to allocate rx descriptors: %d\n",
+				error);
 			goto err;
 		}
 
@@ -358,8 +358,8 @@ int ath_rx_init(struct ath_softc *sc, in
 				dev_kfree_skb_any(skb);
 				bf->bf_mpdu = NULL;
 				bf->bf_buf_addr = 0;
-				ath_print(common, ATH_DBG_FATAL,
-					  "dma_mapping_error() on RX init\n");
+				ath_err(common,
+					"dma_mapping_error() on RX init\n");
 				error = -ENOMEM;
 				goto err;
 			}
@@ -528,6 +528,13 @@ bool ath_stoprecv(struct ath_softc *sc)
 		sc->rx.rxlink = NULL;
 	spin_unlock_bh(&sc->rx.rxbuflock);
 
+	if (!(ah->ah_flags & AH_UNPLUGGED) &&
+	    unlikely(!stopped)) {
+		ath_err(ath9k_hw_common(sc->sc_ah),
+			"Could not stop RX, we could be "
+			"confusing the DMA engine when we start RX up\n");
+		ATH_DBG_WARN_ON_ONCE(!stopped);
+	}
 	return stopped;
 }
 
@@ -588,9 +595,8 @@ static void ath_rx_ps_beacon(struct ath_
 
 	if (sc->ps_flags & PS_BEACON_SYNC) {
 		sc->ps_flags &= ~PS_BEACON_SYNC;
-		ath_print(common, ATH_DBG_PS,
-			  "Reconfigure Beacon timers based on "
-			  "timestamp from the AP\n");
+		ath_dbg(common, ATH_DBG_PS,
+			"Reconfigure Beacon timers based on timestamp from the AP\n");
 		ath_beacon_config(sc, NULL);
 	}
 
@@ -602,8 +608,8 @@ static void ath_rx_ps_beacon(struct ath_
 		 * a backup trigger for returning into NETWORK SLEEP state,
 		 * so we are waiting for it as well.
 		 */
-		ath_print(common, ATH_DBG_PS, "Received DTIM beacon indicating "
-			  "buffered broadcast/multicast frame(s)\n");
+		ath_dbg(common, ATH_DBG_PS,
+			"Received DTIM beacon indicating buffered broadcast/multicast frame(s)\n");
 		sc->ps_flags |= PS_WAIT_FOR_CAB | PS_WAIT_FOR_BEACON;
 		return;
 	}
@@ -615,8 +621,8 @@ static void ath_rx_ps_beacon(struct ath_
 		 * been delivered.
 		 */
 		sc->ps_flags &= ~PS_WAIT_FOR_CAB;
-		ath_print(common, ATH_DBG_PS,
-			  "PS wait for CAB frames timed out\n");
+		ath_dbg(common, ATH_DBG_PS,
+			"PS wait for CAB frames timed out\n");
 	}
 }
 
@@ -641,15 +647,14 @@ static void ath_rx_ps(struct ath_softc *
 		 * point.
 		 */
 		sc->ps_flags &= ~(PS_WAIT_FOR_CAB | PS_WAIT_FOR_BEACON);
-		ath_print(common, ATH_DBG_PS,
-			  "All PS CAB frames received, back to sleep\n");
+		ath_dbg(common, ATH_DBG_PS,
+			"All PS CAB frames received, back to sleep\n");
 	} else if ((sc->ps_flags & PS_WAIT_FOR_PSPOLL_DATA) &&
 		   !is_multicast_ether_addr(hdr->addr1) &&
 		   !ieee80211_has_morefrags(hdr->frame_control)) {
 		sc->ps_flags &= ~PS_WAIT_FOR_PSPOLL_DATA;
-		ath_print(common, ATH_DBG_PS,
-			  "Going back to sleep after having received "
-			  "PS-Poll data (0x%lx)\n",
+		ath_dbg(common, ATH_DBG_PS,
+			"Going back to sleep after having received PS-Poll data (0x%lx)\n",
 			sc->ps_flags & (PS_WAIT_FOR_BEACON |
 					PS_WAIT_FOR_CAB |
 					PS_WAIT_FOR_PSPOLL_DATA |
@@ -658,8 +663,7 @@ static void ath_rx_ps(struct ath_softc *
 }
 
 static void ath_rx_send_to_mac80211(struct ieee80211_hw *hw,
-				    struct ath_softc *sc, struct sk_buff *skb,
-				    struct ieee80211_rx_status *rxs)
+				    struct ath_softc *sc, struct sk_buff *skb)
 {
 	struct ieee80211_hdr *hdr;
 
@@ -958,8 +962,9 @@ static int ath9k_process_rate(struct ath
 	 * No valid hardware bitrate found -- we should not get here
 	 * because hardware has already validated this frame as OK.
 	 */
-	ath_print(common, ATH_DBG_XMIT, "unsupported hw bitrate detected "
-		  "0x%02x using 1 Mbit\n", rx_stats->rs_rate);
+	ath_dbg(common, ATH_DBG_XMIT,
+		"unsupported hw bitrate detected 0x%02x using 1 Mbit\n",
+		rx_stats->rs_rate);
 
 	return -EINVAL;
 }
@@ -969,36 +974,23 @@ static void ath9k_process_rssi(struct at
 			       struct ieee80211_hdr *hdr,
 			       struct ath_rx_status *rx_stats)
 {
+	struct ath_wiphy *aphy = hw->priv;
 	struct ath_hw *ah = common->ah;
-	struct ieee80211_sta *sta;
-	struct ath_node *an;
-	int last_rssi = ATH_RSSI_DUMMY_MARKER;
+	int last_rssi;
 	__le16 fc;
 
-	fc = hdr->frame_control;
+	if (ah->opmode != NL80211_IFTYPE_STATION)
+		return;
 
-	rcu_read_lock();
-	/*
-	 * XXX: use ieee80211_find_sta! This requires quite a bit of work
-	 * under the current ath9k virtual wiphy implementation as we have
-	 * no way of tying a vif to wiphy. Typically vifs are attached to
-	 * at least one sdata of a wiphy on mac80211 but with ath9k virtual
-	 * wiphy you'd have to iterate over every wiphy and each sdata.
-	 */
-	if (is_multicast_ether_addr(hdr->addr1))
-		sta = ieee80211_find_sta_by_ifaddr(hw, hdr->addr2, NULL);
-	else
-		sta = ieee80211_find_sta_by_ifaddr(hw, hdr->addr2, hdr->addr1);
+	fc = hdr->frame_control;
+	if (!ieee80211_is_beacon(fc) ||
+	    compare_ether_addr(hdr->addr3, common->curbssid))
+		return;
 
-	if (sta) {
-		an = (struct ath_node *) sta->drv_priv;
-		if (rx_stats->rs_rssi != ATH9K_RSSI_BAD &&
-		   !rx_stats->rs_moreaggr)
-			ATH_RSSI_LPF(an->last_rssi, rx_stats->rs_rssi);
-		last_rssi = an->last_rssi;
-	}
-	rcu_read_unlock();
+	if (rx_stats->rs_rssi != ATH9K_RSSI_BAD && !rx_stats->rs_moreaggr)
+		ATH_RSSI_LPF(aphy->last_rssi, rx_stats->rs_rssi);
 
+	last_rssi = aphy->last_rssi;
 	if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER))
 		rx_stats->rs_rssi = ATH_EP_RND(last_rssi,
 					      ATH_RSSI_EP_MULTIPLIER);
@@ -1006,8 +998,7 @@ static void ath9k_process_rssi(struct at
 		rx_stats->rs_rssi = 0;
 
 	/* Update Beacon RSSI, this is used by ANI. */
-	if (ieee80211_is_beacon(fc))
-		ah->stats.avgbrssi = rx_stats->rs_rssi;
+	ah->stats.avgbrssi = rx_stats->rs_rssi;
 }
 
 /*
@@ -1637,7 +1628,7 @@ int ath_rx_tasklet(struct ath_softc *sc,
 	struct ath_hw *ah = sc->sc_ah;
 	struct ath_common *common = ath9k_hw_common(ah);
 	/*
-	 * The hw can techncically differ from common->hw when using ath9k
+	 * The hw can technically differ from common->hw when using ath9k
 	 * virtual wiphy so to account for that we iterate over the active
 	 * wiphys and find the appropriate wiphy and therefore hw.
 	 */
@@ -1744,9 +1735,8 @@ int ath_rx_tasklet(struct ath_softc *sc,
 			dev_kfree_skb_any(requeue_skb);
 			bf->bf_mpdu = NULL;
 			bf->bf_buf_addr = 0;
-			ath_print(common, ATH_DBG_FATAL,
-				  "dma_mapping_error() on RX\n");
-			ath_rx_send_to_mac80211(hw, sc, skb, rxs);
+			ath_err(common, "dma_mapping_error() on RX\n");
+			ath_rx_send_to_mac80211(hw, sc, skb);
 			break;
 		}
 
@@ -1762,17 +1752,18 @@ int ath_rx_tasklet(struct ath_softc *sc,
 		}
 
 		spin_lock_irqsave(&sc->sc_pm_lock, flags);
-		if (unlikely(ath9k_check_auto_sleep(sc) ||
-			     (sc->ps_flags & (PS_WAIT_FOR_BEACON |
+
+		if ((sc->ps_flags & (PS_WAIT_FOR_BEACON |
 					      PS_WAIT_FOR_CAB |
-					      PS_WAIT_FOR_PSPOLL_DATA))))
+					      PS_WAIT_FOR_PSPOLL_DATA)) ||
+					unlikely(ath9k_check_auto_sleep(sc)))
 			ath_rx_ps(sc, skb);
 		spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
 
 		if (ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB)
 			ath_ant_comb_scan(sc, &rs);
 
-		ath_rx_send_to_mac80211(hw, sc, skb, rxs);
+		ath_rx_send_to_mac80211(hw, sc, skb);
 
 requeue:
 		if (edma) {
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/reg.h linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/reg.h
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/reg.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/reg.h	2011-03-14 21:20:32.000000000 -0400
@@ -787,6 +787,8 @@
 #define AR_SREV_REVISION_9271_11	1
 #define AR_SREV_VERSION_9300		0x1c0
 #define AR_SREV_REVISION_9300_20	2 /* 2.0 and 2.1 */
+#define AR_SREV_VERSION_9485		0x240
+#define AR_SREV_REVISION_9485_10	0
 
 #define AR_SREV_5416(_ah) \
 	(((_ah)->hw_version.macVersion == AR_SREV_VERSION_5416_PCI) || \
@@ -859,20 +861,24 @@
 	 (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9300) && \
 	  ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9300_20)))
 
+#define AR_SREV_9485(_ah) \
+	(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9485))
+#define AR_SREV_9485_10(_ah) \
+	(AR_SREV_9485(_ah) && \
+	 ((_ah)->hw_version.macRev == AR_SREV_REVISION_9485_10))
+
 #define AR_SREV_9285E_20(_ah) \
     (AR_SREV_9285_12_OR_LATER(_ah) && \
      ((REG_READ(_ah, AR_AN_SYNTH9) & 0x7) == 0x1))
 
-#define AR_DEVID_7010(_ah) \
-	(((_ah)->hw_version.devid == 0x7010) || \
-	 ((_ah)->hw_version.devid == 0x7015) || \
-	 ((_ah)->hw_version.devid == 0x9018) || \
-	 ((_ah)->hw_version.devid == 0xA704) || \
-	 ((_ah)->hw_version.devid == 0x1200))
+enum ath_usb_dev {
+	AR9280_USB = 1, /* AR7010 + AR9280, UB94 */
+	AR9287_USB = 2, /* AR7010 + AR9287, UB95 */
+};
 
-#define AR9287_HTC_DEVID(_ah) \
-	(((_ah)->hw_version.devid == 0x7015) || \
-	 ((_ah)->hw_version.devid == 0x1200))
+#define AR_DEVID_7010(_ah) \
+	(((_ah)->hw_version.usbdev == AR9280_USB) || \
+	 ((_ah)->hw_version.usbdev == AR9287_USB))
 
 #define AR_RADIO_SREV_MAJOR                   0xf0
 #define AR_RAD5133_SREV_MAJOR                 0xc0
@@ -1074,6 +1080,9 @@ enum {
 #define AR_INTR_PRIO_ASYNC_MASK   0x40c8
 #define AR_INTR_PRIO_SYNC_MASK    0x40cc
 #define AR_INTR_PRIO_ASYNC_ENABLE 0x40d4
+#define AR_ENT_OTP		  0x40d8
+#define AR_ENT_OTP_CHAIN2_DISABLE               0x00020000
+#define AR_ENT_OTP_MPSD		0x00800000
 
 #define AR_RTC_9300_PLL_DIV          0x000003ff
 #define AR_RTC_9300_PLL_DIV_S        0
@@ -1111,6 +1120,8 @@ enum {
 #define AR_RTC_PLL_CONTROL \
 	((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0014) : 0x7014)
 
+#define AR_RTC_PLL_CONTROL2	0x703c
+
 #define AR_RTC_PLL_DIV          0x0000001f
 #define AR_RTC_PLL_DIV_S        0
 #define AR_RTC_PLL_DIV2         0x00000020
@@ -1574,6 +1585,7 @@ enum {
 #define AR_PCU_TBTT_PROTECT        0x00200000
 #define AR_PCU_CLEAR_VMF           0x01000000
 #define AR_PCU_CLEAR_BA_VALID      0x04000000
+#define AR_PCU_ALWAYS_PERFORM_KEYSEARCH 0x10000000
 
 #define AR_PCU_BT_ANT_PREVENT_RX   0x00100000
 #define AR_PCU_BT_ANT_PREVENT_RX_S 20
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/virtual.c linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/virtual.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/virtual.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/virtual.c	2011-03-14 21:20:32.000000000 -0400
@@ -107,6 +107,7 @@ int ath9k_wiphy_add(struct ath_softc *sc
 	aphy->sc = sc;
 	aphy->hw = hw;
 	sc->sec_wiphy[i] = aphy;
+	aphy->last_rssi = ATH_RSSI_DUMMY_MARKER;
 	spin_unlock_bh(&sc->wiphy_lock);
 
 	memcpy(addr, common->macaddr, ETH_ALEN);
@@ -186,7 +187,7 @@ static int ath9k_send_nullfunc(struct at
 	info->control.rates[1].idx = -1;
 
 	memset(&txctl, 0, sizeof(struct ath_tx_control));
-	txctl.txq = &sc->tx.txq[sc->tx.hwq_map[WME_AC_VO]];
+	txctl.txq = sc->tx.txq_map[WME_AC_VO];
 	txctl.frame_type = ps ? ATH9K_IFT_PAUSE : ATH9K_IFT_UNPAUSE;
 
 	if (ath_tx_start(aphy->hw, skb, &txctl) != 0)
@@ -287,7 +288,6 @@ void ath9k_wiphy_chan_work(struct work_s
 	/* sync hw configuration for hw code */
 	common->hw = aphy->hw;
 
-	ath_update_chainmask(sc, sc->chan_is_ht);
 	if (ath_set_channel(sc, aphy->hw,
 			    &sc->sc_ah->channels[sc->chan_idx]) < 0) {
 		printk(KERN_DEBUG "ath9k: Failed to set channel for new "
@@ -304,13 +304,12 @@ void ath9k_wiphy_chan_work(struct work_s
  * ath9k version of ieee80211_tx_status() for TX frames that are generated
  * internally in the driver.
  */
-void ath9k_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
+void ath9k_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb, int ftype)
 {
 	struct ath_wiphy *aphy = hw->priv;
 	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
 
-	if ((tx_info->pad[0] & ATH_TX_INFO_FRAME_TYPE_PAUSE) &&
-	    aphy->state == ATH_WIPHY_PAUSING) {
+	if (ftype == ATH9K_IFT_PAUSE && aphy->state == ATH_WIPHY_PAUSING) {
 		if (!(tx_info->flags & IEEE80211_TX_STAT_ACK)) {
 			printk(KERN_DEBUG "ath9k: %s: no ACK for pause "
 			       "frame\n", wiphy_name(hw->wiphy));
@@ -656,10 +655,9 @@ void ath9k_set_wiphy_idle(struct ath_wip
 	struct ath_softc *sc = aphy->sc;
 
 	aphy->idle = idle;
-	ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_CONFIG,
-		  "Marking %s as %s\n",
-		  wiphy_name(aphy->hw->wiphy),
-		  idle ? "idle" : "not-idle");
+	ath_dbg(ath9k_hw_common(sc->sc_ah), ATH_DBG_CONFIG,
+		"Marking %s as %sidle\n",
+		wiphy_name(aphy->hw->wiphy), idle ? "" : "not-");
 }
 /* Only bother starting a queue on an active virtual wiphy */
 bool ath_mac80211_start_queue(struct ath_softc *sc, u16 skb_queue)
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/wmi.c linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/wmi.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/wmi.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/wmi.c	2011-03-14 21:20:32.000000000 -0400
@@ -120,17 +120,27 @@ void ath9k_deinit_wmi(struct ath9k_htc_p
 	kfree(priv->wmi);
 }
 
-void ath9k_wmi_tasklet(unsigned long data)
+void ath9k_swba_tasklet(unsigned long data)
 {
 	struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *)data;
 	struct ath_common *common = ath9k_hw_common(priv->ah);
 
-	ath_print(common, ATH_DBG_WMI, "SWBA Event received\n");
+	ath_dbg(common, ATH_DBG_WMI, "SWBA Event received\n");
 
 	ath9k_htc_swba(priv, priv->wmi->beacon_pending);
 
 }
 
+void ath9k_fatal_work(struct work_struct *work)
+{
+	struct ath9k_htc_priv *priv = container_of(work, struct ath9k_htc_priv,
+						   fatal_work);
+	struct ath_common *common = ath9k_hw_common(priv->ah);
+
+	ath_dbg(common, ATH_DBG_FATAL, "FATAL Event received, resetting device\n");
+	ath9k_htc_reset(priv);
+}
+
 static void ath9k_wmi_rsp_callback(struct wmi *wmi, struct sk_buff *skb)
 {
 	skb_pull(skb, sizeof(struct wmi_cmd_hdr));
@@ -163,7 +173,11 @@ static void ath9k_wmi_ctrl_rx(void *priv
 		switch (cmd_id) {
 		case WMI_SWBA_EVENTID:
 			wmi->beacon_pending = *(u8 *)wmi_event;
-			tasklet_schedule(&wmi->drv_priv->wmi_tasklet);
+			tasklet_schedule(&wmi->drv_priv->swba_tasklet);
+			break;
+		case WMI_FATAL_EVENTID:
+			ieee80211_queue_work(wmi->drv_priv->hw,
+					     &wmi->drv_priv->fatal_work);
 			break;
 		case WMI_TXRATE_EVENTID:
 #ifdef CONFIG_ATH9K_HTC_DEBUGFS
@@ -250,7 +264,7 @@ int ath9k_wmi_cmd(struct wmi *wmi, enum
 	int time_left, ret = 0;
 	unsigned long flags;
 
-	if (wmi->drv_priv->op_flags & OP_UNPLUGGED)
+	if (ah->ah_flags & AH_UNPLUGGED)
 		return 0;
 
 	skb = alloc_skb(headroom + cmd_len, GFP_ATOMIC);
@@ -286,9 +300,9 @@ int ath9k_wmi_cmd(struct wmi *wmi, enum
 
 	time_left = wait_for_completion_timeout(&wmi->cmd_wait, timeout);
 	if (!time_left) {
-		ath_print(common, ATH_DBG_WMI,
-			  "Timeout waiting for WMI command: %s\n",
-			  wmi_cmd_to_name(cmd_id));
+		ath_dbg(common, ATH_DBG_WMI,
+			"Timeout waiting for WMI command: %s\n",
+			wmi_cmd_to_name(cmd_id));
 		mutex_unlock(&wmi->op_mutex);
 		return -ETIMEDOUT;
 	}
@@ -298,8 +312,8 @@ int ath9k_wmi_cmd(struct wmi *wmi, enum
 	return 0;
 
 out:
-	ath_print(common, ATH_DBG_WMI,
-		  "WMI failure for: %s\n", wmi_cmd_to_name(cmd_id));
+	ath_dbg(common, ATH_DBG_WMI,
+		"WMI failure for: %s\n", wmi_cmd_to_name(cmd_id));
 	mutex_unlock(&wmi->op_mutex);
 	kfree_skb(skb);
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/wmi.h linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/wmi.h
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/wmi.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/wmi.h	2011-03-14 21:20:32.000000000 -0400
@@ -117,7 +117,8 @@ int ath9k_wmi_cmd(struct wmi *wmi, enum
 		  u8 *cmd_buf, u32 cmd_len,
 		  u8 *rsp_buf, u32 rsp_len,
 		  u32 timeout);
-void ath9k_wmi_tasklet(unsigned long data);
+void ath9k_swba_tasklet(unsigned long data);
+void ath9k_fatal_work(struct work_struct *work);
 
 #define WMI_CMD(_wmi_cmd)						\
 	do {								\
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/xmit.c linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/xmit.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath9k/xmit.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath9k/xmit.c	2011-03-14 21:20:32.000000000 -0400
@@ -48,19 +48,17 @@ static u16 bits_per_symbol[][2] = {
 
 #define IS_HT_RATE(_rate)     ((_rate) & 0x80)
 
-static void ath_tx_send_ht_normal(struct ath_softc *sc, struct ath_txq *txq,
-				  struct ath_atx_tid *tid,
-				  struct list_head *bf_head);
+static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq,
+			       struct ath_atx_tid *tid,
+			       struct list_head *bf_head);
 static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
 				struct ath_txq *txq, struct list_head *bf_q,
 				struct ath_tx_status *ts, int txok, int sendbar);
 static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq,
 			     struct list_head *head);
-static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf);
-static int ath_tx_num_badfrms(struct ath_softc *sc, struct ath_buf *bf,
-			      struct ath_tx_status *ts, int txok);
+static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf, int len);
 static void ath_tx_rc_status(struct ath_buf *bf, struct ath_tx_status *ts,
-			     int nbad, int txok, bool update_rc);
+			     int nframes, int nbad, int txok, bool update_rc);
 static void ath_tx_update_baw(struct ath_softc *sc, struct ath_atx_tid *tid,
 			      int seqno);
 
@@ -124,7 +122,7 @@ static void ath_tx_queue_tid(struct ath_
 
 static void ath_tx_resume_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
 {
-	struct ath_txq *txq = &sc->tx.txq[tid->ac->qnum];
+	struct ath_txq *txq = tid->ac->txq;
 
 	WARN_ON(!tid->paused);
 
@@ -140,12 +138,21 @@ unlock:
 	spin_unlock_bh(&txq->axq_lock);
 }
 
+static struct ath_frame_info *get_frame_info(struct sk_buff *skb)
+{
+	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
+	BUILD_BUG_ON(sizeof(struct ath_frame_info) >
+		     sizeof(tx_info->rate_driver_data));
+	return (struct ath_frame_info *) &tx_info->rate_driver_data[0];
+}
+
 static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
 {
-	struct ath_txq *txq = &sc->tx.txq[tid->ac->qnum];
+	struct ath_txq *txq = tid->ac->txq;
 	struct ath_buf *bf;
 	struct list_head bf_head;
 	struct ath_tx_status ts;
+	struct ath_frame_info *fi;
 
 	INIT_LIST_HEAD(&bf_head);
 
@@ -156,12 +163,15 @@ static void ath_tx_flush_tid(struct ath_
 		bf = list_first_entry(&tid->buf_q, struct ath_buf, list);
 		list_move_tail(&bf->list, &bf_head);
 
-		if (bf_isretried(bf)) {
-			ath_tx_update_baw(sc, tid, bf->bf_seqno);
+		spin_unlock_bh(&txq->axq_lock);
+		fi = get_frame_info(bf->bf_mpdu);
+		if (fi->retries) {
+			ath_tx_update_baw(sc, tid, fi->seqno);
 			ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 0);
 		} else {
-			ath_tx_send_ht_normal(sc, txq, tid, &bf_head);
+			ath_tx_send_normal(sc, txq, tid, &bf_head);
 		}
+		spin_lock_bh(&txq->axq_lock);
 	}
 
 	spin_unlock_bh(&txq->axq_lock);
@@ -184,14 +194,11 @@ static void ath_tx_update_baw(struct ath
 }
 
 static void ath_tx_addto_baw(struct ath_softc *sc, struct ath_atx_tid *tid,
-			     struct ath_buf *bf)
+			     u16 seqno)
 {
 	int index, cindex;
 
-	if (bf_isretried(bf))
-		return;
-
-	index  = ATH_BA_INDEX(tid->seq_start, bf->bf_seqno);
+	index  = ATH_BA_INDEX(tid->seq_start, seqno);
 	cindex = (tid->baw_head + index) & (ATH_TID_MAX_BUFS - 1);
 	__set_bit(cindex, tid->tx_buf);
 
@@ -215,6 +222,7 @@ static void ath_tid_drain(struct ath_sof
 	struct ath_buf *bf;
 	struct list_head bf_head;
 	struct ath_tx_status ts;
+	struct ath_frame_info *fi;
 
 	memset(&ts, 0, sizeof(ts));
 	INIT_LIST_HEAD(&bf_head);
@@ -226,8 +234,9 @@ static void ath_tid_drain(struct ath_sof
 		bf = list_first_entry(&tid->buf_q, struct ath_buf, list);
 		list_move_tail(&bf->list, &bf_head);
 
-		if (bf_isretried(bf))
-			ath_tx_update_baw(sc, tid, bf->bf_seqno);
+		fi = get_frame_info(bf->bf_mpdu);
+		if (fi->retries)
+			ath_tx_update_baw(sc, tid, fi->seqno);
 
 		spin_unlock(&txq->axq_lock);
 		ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 0);
@@ -239,16 +248,15 @@ static void ath_tid_drain(struct ath_sof
 }
 
 static void ath_tx_set_retry(struct ath_softc *sc, struct ath_txq *txq,
-			     struct ath_buf *bf)
+			     struct sk_buff *skb)
 {
-	struct sk_buff *skb;
+	struct ath_frame_info *fi = get_frame_info(skb);
 	struct ieee80211_hdr *hdr;
 
-	bf->bf_state.bf_type |= BUF_RETRY;
-	bf->bf_retries++;
 	TX_STAT_INC(txq->axq_qnum, a_retries);
+	if (fi->retries++ > 0)
+		return;
 
-	skb = bf->bf_mpdu;
 	hdr = (struct ieee80211_hdr *)skb->data;
 	hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_RETRY);
 }
@@ -298,9 +306,41 @@ static struct ath_buf* ath_clone_txbuf(s
 	return tbf;
 }
 
+static void ath_tx_count_frames(struct ath_softc *sc, struct ath_buf *bf,
+			        struct ath_tx_status *ts, int txok,
+			        int *nframes, int *nbad)
+{
+	struct ath_frame_info *fi;
+	u16 seq_st = 0;
+	u32 ba[WME_BA_BMP_SIZE >> 5];
+	int ba_index;
+	int isaggr = 0;
+
+	*nbad = 0;
+	*nframes = 0;
+
+	isaggr = bf_isaggr(bf);
+	if (isaggr) {
+		seq_st = ts->ts_seqnum;
+		memcpy(ba, &ts->ba_low, WME_BA_BMP_SIZE >> 3);
+	}
+
+	while (bf) {
+		fi = get_frame_info(bf->bf_mpdu);
+		ba_index = ATH_BA_INDEX(seq_st, fi->seqno);
+
+		(*nframes)++;
+		if (!txok || (isaggr && !ATH_BA_ISSET(ba, ba_index)))
+			(*nbad)++;
+
+		bf = bf->bf_next;
+	}
+}
+
+
 static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
 				 struct ath_buf *bf, struct list_head *bf_q,
-				 struct ath_tx_status *ts, int txok)
+				 struct ath_tx_status *ts, int txok, bool retry)
 {
 	struct ath_node *an = NULL;
 	struct sk_buff *skb;
@@ -316,7 +356,9 @@ static void ath_tx_complete_aggr(struct
 	int isaggr, txfail, txpending, sendbar = 0, needreset = 0, nbad = 0;
 	bool rc_update = true;
 	struct ieee80211_tx_rate rates[4];
+	struct ath_frame_info *fi;
 	int nframes;
+	u8 tidno;
 
 	skb = bf->bf_mpdu;
 	hdr = (struct ieee80211_hdr *)skb->data;
@@ -325,7 +367,6 @@ static void ath_tx_complete_aggr(struct
 	hw = bf->aphy->hw;
 
 	memcpy(rates, tx_info->control.rates, sizeof(rates));
-	nframes = bf->bf_nframes;
 
 	rcu_read_lock();
 
@@ -342,7 +383,7 @@ static void ath_tx_complete_aggr(struct
 			    !bf->bf_stale || bf_next != NULL)
 				list_move_tail(&bf->list, &bf_head);
 
-			ath_tx_rc_status(bf, ts, 1, 0, false);
+			ath_tx_rc_status(bf, ts, 1, 1, 0, false);
 			ath_tx_complete_buf(sc, bf, txq, &bf_head, ts,
 				0, 0);
 
@@ -352,14 +393,15 @@ static void ath_tx_complete_aggr(struct
 	}
 
 	an = (struct ath_node *)sta->drv_priv;
-	tid = ATH_AN_2_TID(an, bf->bf_tidno);
+	tidno = ieee80211_get_qos_ctl(hdr)[0] & IEEE80211_QOS_CTL_TID_MASK;
+	tid = ATH_AN_2_TID(an, tidno);
 
 	/*
 	 * The hardware occasionally sends a tx status for the wrong TID.
 	 * In this case, the BA status cannot be considered valid and all
 	 * subframes need to be retransmitted
 	 */
-	if (bf->bf_tidno != ts->tid)
+	if (tidno != ts->tid)
 		txok = false;
 
 	isaggr = bf_isaggr(bf);
@@ -385,15 +427,16 @@ static void ath_tx_complete_aggr(struct
 	INIT_LIST_HEAD(&bf_pending);
 	INIT_LIST_HEAD(&bf_head);
 
-	nbad = ath_tx_num_badfrms(sc, bf, ts, txok);
+	ath_tx_count_frames(sc, bf, ts, txok, &nframes, &nbad);
 	while (bf) {
 		txfail = txpending = 0;
 		bf_next = bf->bf_next;
 
 		skb = bf->bf_mpdu;
 		tx_info = IEEE80211_SKB_CB(skb);
+		fi = get_frame_info(skb);
 
-		if (ATH_BA_ISSET(ba, ATH_BA_INDEX(seq_st, bf->bf_seqno))) {
+		if (ATH_BA_ISSET(ba, ATH_BA_INDEX(seq_st, fi->seqno))) {
 			/* transmit completion, subframe is
 			 * acked by block ack */
 			acked_cnt++;
@@ -401,10 +444,9 @@ static void ath_tx_complete_aggr(struct
 			/* transmit completion */
 			acked_cnt++;
 		} else {
-			if (!(tid->state & AGGR_CLEANUP) &&
-			    !bf_last->bf_tx_aborted) {
-				if (bf->bf_retries < ATH_MAX_SW_RETRIES) {
-					ath_tx_set_retry(sc, txq, bf);
+			if (!(tid->state & AGGR_CLEANUP) && retry) {
+				if (fi->retries < ATH_MAX_SW_RETRIES) {
+					ath_tx_set_retry(sc, txq, bf->bf_mpdu);
 					txpending = 1;
 				} else {
 					bf->bf_state.bf_type |= BUF_XRETRY;
@@ -442,16 +484,15 @@ static void ath_tx_complete_aggr(struct
 			 * block-ack window
 			 */
 			spin_lock_bh(&txq->axq_lock);
-			ath_tx_update_baw(sc, tid, bf->bf_seqno);
+			ath_tx_update_baw(sc, tid, fi->seqno);
 			spin_unlock_bh(&txq->axq_lock);
 
 			if (rc_update && (acked_cnt == 1 || txfail_cnt == 1)) {
 				memcpy(tx_info->control.rates, rates, sizeof(rates));
-				bf->bf_nframes = nframes;
-				ath_tx_rc_status(bf, ts, nbad, txok, true);
+				ath_tx_rc_status(bf, ts, nframes, nbad, txok, true);
 				rc_update = false;
 			} else {
-				ath_tx_rc_status(bf, ts, nbad, txok, false);
+				ath_tx_rc_status(bf, ts, nframes, nbad, txok, false);
 			}
 
 			ath_tx_complete_buf(sc, bf, txq, &bf_head, ts,
@@ -470,14 +511,13 @@ static void ath_tx_complete_aggr(struct
 					 */
 					if (!tbf) {
 						spin_lock_bh(&txq->axq_lock);
-						ath_tx_update_baw(sc, tid,
-								bf->bf_seqno);
+						ath_tx_update_baw(sc, tid, fi->seqno);
 						spin_unlock_bh(&txq->axq_lock);
 
 						bf->bf_state.bf_type |=
 							BUF_XRETRY;
-						ath_tx_rc_status(bf, ts, nbad,
-								0, false);
+						ath_tx_rc_status(bf, ts, nframes,
+								nbad, 0, false);
 						ath_tx_complete_buf(sc, bf, txq,
 								    &bf_head,
 								    ts, 0, 0);
@@ -611,6 +651,7 @@ static int ath_compute_num_delims(struct
 	u16 minlen;
 	u8 flags, rix;
 	int width, streams, half_gi, ndelim, mindelim;
+	struct ath_frame_info *fi = get_frame_info(bf->bf_mpdu);
 
 	/* Select standard number of delimiters based on frame length alone */
 	ndelim = ATH_AGGR_GET_NDELIM(frmlen);
@@ -621,7 +662,7 @@ static int ath_compute_num_delims(struct
 	 * TODO - this could be improved to be dependent on the rate.
 	 *      The hardware can keep up at lower rates, but not higher rates
 	 */
-	if (bf->bf_keytype != ATH9K_KEY_TYPE_CLEAR)
+	if (fi->keyix != ATH9K_TXKEYIX_INVALID)
 		ndelim += ATH_AGGR_ENCRYPTDELIM;
 
 	/*
@@ -665,7 +706,8 @@ static int ath_compute_num_delims(struct
 static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc,
 					     struct ath_txq *txq,
 					     struct ath_atx_tid *tid,
-					     struct list_head *bf_q)
+					     struct list_head *bf_q,
+					     int *aggr_len)
 {
 #define PADBYTES(_len) ((4 - ((_len) % 4)) % 4)
 	struct ath_buf *bf, *bf_first, *bf_prev = NULL;
@@ -674,14 +716,16 @@ static enum ATH_AGGR_STATUS ath_tx_form_
 		al_delta, h_baw = tid->baw_size / 2;
 	enum ATH_AGGR_STATUS status = ATH_AGGR_DONE;
 	struct ieee80211_tx_info *tx_info;
+	struct ath_frame_info *fi;
 
 	bf_first = list_first_entry(&tid->buf_q, struct ath_buf, list);
 
 	do {
 		bf = list_first_entry(&tid->buf_q, struct ath_buf, list);
+		fi = get_frame_info(bf->bf_mpdu);
 
 		/* do not step over block-ack window */
-		if (!BAW_WITHIN(tid->seq_start, tid->baw_size, bf->bf_seqno)) {
+		if (!BAW_WITHIN(tid->seq_start, tid->baw_size, fi->seqno)) {
 			status = ATH_AGGR_BAW_CLOSED;
 			break;
 		}
@@ -692,7 +736,7 @@ static enum ATH_AGGR_STATUS ath_tx_form_
 		}
 
 		/* do not exceed aggregation limit */
-		al_delta = ATH_AGGR_DELIM_SZ + bf->bf_frmlen;
+		al_delta = ATH_AGGR_DELIM_SZ + fi->framelen;
 
 		if (nframes &&
 		    (aggr_limit < (al + bpad + al_delta + prev_al))) {
@@ -719,14 +763,15 @@ static enum ATH_AGGR_STATUS ath_tx_form_
 		 * Get the delimiters needed to meet the MPDU
 		 * density for this node.
 		 */
-		ndelim = ath_compute_num_delims(sc, tid, bf_first, bf->bf_frmlen);
+		ndelim = ath_compute_num_delims(sc, tid, bf_first, fi->framelen);
 		bpad = PADBYTES(al_delta) + (ndelim << 2);
 
 		bf->bf_next = NULL;
 		ath9k_hw_set_desc_link(sc->sc_ah, bf->bf_desc, 0);
 
 		/* link buffers of this frame to the aggregate */
-		ath_tx_addto_baw(sc, tid, bf);
+		if (!fi->retries)
+			ath_tx_addto_baw(sc, tid, fi->seqno);
 		ath9k_hw_set11n_aggr_middle(sc->sc_ah, bf->bf_desc, ndelim);
 		list_move_tail(&bf->list, bf_q);
 		if (bf_prev) {
@@ -738,8 +783,7 @@ static enum ATH_AGGR_STATUS ath_tx_form_
 
 	} while (!list_empty(&tid->buf_q));
 
-	bf_first->bf_al = al;
-	bf_first->bf_nframes = nframes;
+	*aggr_len = al;
 
 	return status;
 #undef PADBYTES
@@ -750,7 +794,9 @@ static void ath_tx_sched_aggr(struct ath
 {
 	struct ath_buf *bf;
 	enum ATH_AGGR_STATUS status;
+	struct ath_frame_info *fi;
 	struct list_head bf_q;
+	int aggr_len;
 
 	do {
 		if (list_empty(&tid->buf_q))
@@ -758,7 +804,7 @@ static void ath_tx_sched_aggr(struct ath
 
 		INIT_LIST_HEAD(&bf_q);
 
-		status = ath_tx_form_aggr(sc, txq, tid, &bf_q);
+		status = ath_tx_form_aggr(sc, txq, tid, &bf_q, &aggr_len);
 
 		/*
 		 * no frames picked up to be aggregated;
@@ -771,18 +817,20 @@ static void ath_tx_sched_aggr(struct ath
 		bf->bf_lastbf = list_entry(bf_q.prev, struct ath_buf, list);
 
 		/* if only one frame, send as non-aggregate */
-		if (bf->bf_nframes == 1) {
+		if (bf == bf->bf_lastbf) {
+			fi = get_frame_info(bf->bf_mpdu);
+
 			bf->bf_state.bf_type &= ~BUF_AGGR;
 			ath9k_hw_clr11n_aggr(sc->sc_ah, bf->bf_desc);
-			ath_buf_set_rate(sc, bf);
+			ath_buf_set_rate(sc, bf, fi->framelen);
 			ath_tx_txqaddbuf(sc, txq, &bf_q);
 			continue;
 		}
 
 		/* setup first desc of aggregate */
 		bf->bf_state.bf_type |= BUF_AGGR;
-		ath_buf_set_rate(sc, bf);
-		ath9k_hw_set11n_aggr_first(sc->sc_ah, bf->bf_desc, bf->bf_al);
+		ath_buf_set_rate(sc, bf, aggr_len);
+		ath9k_hw_set11n_aggr_first(sc->sc_ah, bf->bf_desc, aggr_len);
 
 		/* anchor last desc of aggregate */
 		ath9k_hw_set11n_aggr_last(sc->sc_ah, bf->bf_lastbf->bf_desc);
@@ -790,7 +838,7 @@ static void ath_tx_sched_aggr(struct ath
 		ath_tx_txqaddbuf(sc, txq, &bf_q);
 		TX_STAT_INC(txq->axq_qnum, a_aggr);
 
-	} while (txq->axq_depth < ATH_AGGR_MIN_QDEPTH &&
+	} while (txq->axq_ampdu_depth < ATH_AGGR_MIN_QDEPTH &&
 		 status != ATH_AGGR_BAW_CLOSED);
 }
 
@@ -817,7 +865,7 @@ void ath_tx_aggr_stop(struct ath_softc *
 {
 	struct ath_node *an = (struct ath_node *)sta->drv_priv;
 	struct ath_atx_tid *txtid = ATH_AN_2_TID(an, tid);
-	struct ath_txq *txq = &sc->tx.txq[txtid->ac->qnum];
+	struct ath_txq *txq = txtid->ac->txq;
 
 	if (txtid->state & AGGR_CLEANUP)
 		return;
@@ -888,10 +936,16 @@ struct ath_txq *ath_txq_setup(struct ath
 	struct ath_hw *ah = sc->sc_ah;
 	struct ath_common *common = ath9k_hw_common(ah);
 	struct ath9k_tx_queue_info qi;
+	static const int subtype_txq_to_hwq[] = {
+		[WME_AC_BE] = ATH_TXQ_AC_BE,
+		[WME_AC_BK] = ATH_TXQ_AC_BK,
+		[WME_AC_VI] = ATH_TXQ_AC_VI,
+		[WME_AC_VO] = ATH_TXQ_AC_VO,
+	};
 	int qnum, i;
 
 	memset(&qi, 0, sizeof(qi));
-	qi.tqi_subtype = subtype;
+	qi.tqi_subtype = subtype_txq_to_hwq[subtype];
 	qi.tqi_aifs = ATH9K_TXQ_USEDEFAULT;
 	qi.tqi_cwmin = ATH9K_TXQ_USEDEFAULT;
 	qi.tqi_cwmax = ATH9K_TXQ_USEDEFAULT;
@@ -931,22 +985,21 @@ struct ath_txq *ath_txq_setup(struct ath
 		return NULL;
 	}
 	if (qnum >= ARRAY_SIZE(sc->tx.txq)) {
-		ath_print(common, ATH_DBG_FATAL,
-			  "qnum %u out of range, max %u!\n",
-			  qnum, (unsigned int)ARRAY_SIZE(sc->tx.txq));
+		ath_err(common, "qnum %u out of range, max %zu!\n",
+			qnum, ARRAY_SIZE(sc->tx.txq));
 		ath9k_hw_releasetxqueue(ah, qnum);
 		return NULL;
 	}
 	if (!ATH_TXQ_SETUP(sc, qnum)) {
 		struct ath_txq *txq = &sc->tx.txq[qnum];
 
-		txq->axq_class = subtype;
 		txq->axq_qnum = qnum;
 		txq->axq_link = NULL;
 		INIT_LIST_HEAD(&txq->axq_q);
 		INIT_LIST_HEAD(&txq->axq_acq);
 		spin_lock_init(&txq->axq_lock);
 		txq->axq_depth = 0;
+		txq->axq_ampdu_depth = 0;
 		txq->axq_tx_inprogress = false;
 		sc->tx.txqsetup |= 1<<qnum;
 
@@ -985,8 +1038,8 @@ int ath_txq_update(struct ath_softc *sc,
 	qi.tqi_readyTime = qinfo->tqi_readyTime;
 
 	if (!ath9k_hw_set_txq_props(ah, qnum, &qi)) {
-		ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL,
-			  "Unable to update hardware queue %u!\n", qnum);
+		ath_err(ath9k_hw_common(sc->sc_ah),
+			"Unable to update hardware queue %u!\n", qnum);
 		error = -EIO;
 	} else {
 		ath9k_hw_resettxqueue(ah, qnum);
@@ -1016,6 +1069,12 @@ int ath_cabq_update(struct ath_softc *sc
 	return 0;
 }
 
+static bool bf_is_ampdu_not_probing(struct ath_buf *bf)
+{
+    struct ieee80211_tx_info *info = IEEE80211_SKB_CB(bf->bf_mpdu);
+    return bf_isampdu(bf) && !(info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE);
+}
+
 /*
  * Drain a given TX queue (could be Beacon or Data)
  *
@@ -1062,8 +1121,6 @@ void ath_draintxq(struct ath_softc *sc,
 		}
 
 		lastbf = bf->bf_lastbf;
-		if (!retry_tx)
-			lastbf->bf_tx_aborted = true;
 
 		if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
 			list_cut_position(&bf_head,
@@ -1076,11 +1133,13 @@ void ath_draintxq(struct ath_softc *sc,
 		}
 
 		txq->axq_depth--;
-
+		if (bf_is_ampdu_not_probing(bf))
+			txq->axq_ampdu_depth--;
 		spin_unlock_bh(&txq->axq_lock);
 
 		if (bf_isampdu(bf))
-			ath_tx_complete_aggr(sc, txq, bf, &bf_head, &ts, 0);
+			ath_tx_complete_aggr(sc, txq, bf, &bf_head, &ts, 0,
+					     retry_tx);
 		else
 			ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 0);
 	}
@@ -1101,7 +1160,7 @@ void ath_draintxq(struct ath_softc *sc,
 
 			if (bf_isampdu(bf))
 				ath_tx_complete_aggr(sc, txq, bf, &bf_head,
-						     &ts, 0);
+						     &ts, 0, retry_tx);
 			else
 				ath_tx_complete_buf(sc, bf, txq, &bf_head,
 						    &ts, 0, 0);
@@ -1143,7 +1202,7 @@ bool ath_drain_all_txq(struct ath_softc
 	}
 
 	if (npend)
-		ath_print(common, ATH_DBG_FATAL, "Failed to stop TX DMA!\n");
+		ath_err(common, "Failed to stop TX DMA!\n");
 
 	for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
 		if (ATH_TXQ_SETUP(sc, i))
@@ -1202,24 +1261,6 @@ void ath_txq_schedule(struct ath_softc *
 	}
 }
 
-int ath_tx_setup(struct ath_softc *sc, int haltype)
-{
-	struct ath_txq *txq;
-
-	if (haltype >= ARRAY_SIZE(sc->tx.hwq_map)) {
-		ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL,
-			  "HAL AC %u out of range, max %zu!\n",
-			 haltype, ARRAY_SIZE(sc->tx.hwq_map));
-		return 0;
-	}
-	txq = ath_txq_setup(sc, ATH9K_TX_QUEUE_DATA, haltype);
-	if (txq != NULL) {
-		sc->tx.hwq_map[haltype] = txq->axq_qnum;
-		return 1;
-	} else
-		return 0;
-}
-
 /***********/
 /* TX, DMA */
 /***********/
@@ -1245,8 +1286,8 @@ static void ath_tx_txqaddbuf(struct ath_
 
 	bf = list_first_entry(head, struct ath_buf, list);
 
-	ath_print(common, ATH_DBG_QUEUE,
-		  "qnum: %d, txq depth: %d\n", txq->axq_qnum, txq->axq_depth);
+	ath_dbg(common, ATH_DBG_QUEUE,
+		"qnum: %d, txq depth: %d\n", txq->axq_qnum, txq->axq_depth);
 
 	if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
 		if (txq->axq_depth >= ATH_TXFIFO_DEPTH) {
@@ -1254,47 +1295,45 @@ static void ath_tx_txqaddbuf(struct ath_
 			return;
 		}
 		if (!list_empty(&txq->txq_fifo[txq->txq_headidx]))
-			ath_print(common, ATH_DBG_XMIT,
-				  "Initializing tx fifo %d which "
-				  "is non-empty\n",
-				  txq->txq_headidx);
+			ath_dbg(common, ATH_DBG_XMIT,
+				"Initializing tx fifo %d which is non-empty\n",
+				txq->txq_headidx);
 		INIT_LIST_HEAD(&txq->txq_fifo[txq->txq_headidx]);
 		list_splice_init(head, &txq->txq_fifo[txq->txq_headidx]);
 		INCR(txq->txq_headidx, ATH_TXFIFO_DEPTH);
 		ath9k_hw_puttxbuf(ah, txq->axq_qnum, bf->bf_daddr);
-		ath_print(common, ATH_DBG_XMIT,
-			  "TXDP[%u] = %llx (%p)\n",
-			  txq->axq_qnum, ito64(bf->bf_daddr), bf->bf_desc);
+		ath_dbg(common, ATH_DBG_XMIT, "TXDP[%u] = %llx (%p)\n",
+			txq->axq_qnum, ito64(bf->bf_daddr), bf->bf_desc);
 	} else {
 		list_splice_tail_init(head, &txq->axq_q);
 
 		if (txq->axq_link == NULL) {
 			ath9k_hw_puttxbuf(ah, txq->axq_qnum, bf->bf_daddr);
-			ath_print(common, ATH_DBG_XMIT,
-					"TXDP[%u] = %llx (%p)\n",
-					txq->axq_qnum, ito64(bf->bf_daddr),
-					bf->bf_desc);
+			ath_dbg(common, ATH_DBG_XMIT, "TXDP[%u] = %llx (%p)\n",
+				txq->axq_qnum, ito64(bf->bf_daddr),
+				bf->bf_desc);
 		} else {
 			*txq->axq_link = bf->bf_daddr;
-			ath_print(common, ATH_DBG_XMIT,
-					"link[%u] (%p)=%llx (%p)\n",
-					txq->axq_qnum, txq->axq_link,
-					ito64(bf->bf_daddr), bf->bf_desc);
+			ath_dbg(common, ATH_DBG_XMIT,
+				"link[%u] (%p)=%llx (%p)\n",
+				txq->axq_qnum, txq->axq_link,
+				ito64(bf->bf_daddr), bf->bf_desc);
 		}
 		ath9k_hw_get_desc_link(ah, bf->bf_lastbf->bf_desc,
 				       &txq->axq_link);
 		ath9k_hw_txstart(ah, txq->axq_qnum);
 	}
 	txq->axq_depth++;
+	if (bf_is_ampdu_not_probing(bf))
+		txq->axq_ampdu_depth++;
 }
 
 static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid,
-			      struct list_head *bf_head,
-			      struct ath_tx_control *txctl)
+			      struct ath_buf *bf, struct ath_tx_control *txctl)
 {
-	struct ath_buf *bf;
+	struct ath_frame_info *fi = get_frame_info(bf->bf_mpdu);
+	struct list_head bf_head;
 
-	bf = list_first_entry(bf_head, struct ath_buf, list);
 	bf->bf_state.bf_type |= BUF_AMPDU;
 	TX_STAT_INC(txctl->txq->axq_qnum, a_queued);
 
@@ -1306,56 +1345,47 @@ static void ath_tx_send_ampdu(struct ath
 	 * - h/w queue depth exceeds low water mark
 	 */
 	if (!list_empty(&tid->buf_q) || tid->paused ||
-	    !BAW_WITHIN(tid->seq_start, tid->baw_size, bf->bf_seqno) ||
-	    txctl->txq->axq_depth >= ATH_AGGR_MIN_QDEPTH) {
+	    !BAW_WITHIN(tid->seq_start, tid->baw_size, fi->seqno) ||
+	    txctl->txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH) {
 		/*
 		 * Add this frame to software queue for scheduling later
 		 * for aggregation.
 		 */
-		list_move_tail(&bf->list, &tid->buf_q);
+		list_add_tail(&bf->list, &tid->buf_q);
 		ath_tx_queue_tid(txctl->txq, tid);
 		return;
 	}
 
+	INIT_LIST_HEAD(&bf_head);
+	list_add(&bf->list, &bf_head);
+
 	/* Add sub-frame to BAW */
-	ath_tx_addto_baw(sc, tid, bf);
+	if (!fi->retries)
+		ath_tx_addto_baw(sc, tid, fi->seqno);
 
 	/* Queue to h/w without aggregation */
-	bf->bf_nframes = 1;
 	bf->bf_lastbf = bf;
-	ath_buf_set_rate(sc, bf);
-	ath_tx_txqaddbuf(sc, txctl->txq, bf_head);
+	ath_buf_set_rate(sc, bf, fi->framelen);
+	ath_tx_txqaddbuf(sc, txctl->txq, &bf_head);
 }
 
-static void ath_tx_send_ht_normal(struct ath_softc *sc, struct ath_txq *txq,
-				  struct ath_atx_tid *tid,
-				  struct list_head *bf_head)
+static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq,
+			       struct ath_atx_tid *tid,
+			       struct list_head *bf_head)
 {
+	struct ath_frame_info *fi;
 	struct ath_buf *bf;
 
 	bf = list_first_entry(bf_head, struct ath_buf, list);
 	bf->bf_state.bf_type &= ~BUF_AMPDU;
 
 	/* update starting sequence number for subsequent ADDBA request */
-	INCR(tid->seq_start, IEEE80211_SEQ_MAX);
-
-	bf->bf_nframes = 1;
-	bf->bf_lastbf = bf;
-	ath_buf_set_rate(sc, bf);
-	ath_tx_txqaddbuf(sc, txq, bf_head);
-	TX_STAT_INC(txq->axq_qnum, queued);
-}
-
-static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq,
-			       struct list_head *bf_head)
-{
-	struct ath_buf *bf;
-
-	bf = list_first_entry(bf_head, struct ath_buf, list);
+	if (tid)
+		INCR(tid->seq_start, IEEE80211_SEQ_MAX);
 
 	bf->bf_lastbf = bf;
-	bf->bf_nframes = 1;
-	ath_buf_set_rate(sc, bf);
+	fi = get_frame_info(bf->bf_mpdu);
+	ath_buf_set_rate(sc, bf, fi->framelen);
 	ath_tx_txqaddbuf(sc, txq, bf_head);
 	TX_STAT_INC(txq->axq_qnum, queued);
 }
@@ -1383,40 +1413,52 @@ static enum ath9k_pkt_type get_hw_packet
 	return htype;
 }
 
-static void assign_aggr_tid_seqno(struct sk_buff *skb,
-				  struct ath_buf *bf)
+static void setup_frame_info(struct ieee80211_hw *hw, struct sk_buff *skb,
+			     int framelen)
 {
+	struct ath_wiphy *aphy = hw->priv;
+	struct ath_softc *sc = aphy->sc;
 	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
+	struct ieee80211_sta *sta = tx_info->control.sta;
+	struct ieee80211_key_conf *hw_key = tx_info->control.hw_key;
 	struct ieee80211_hdr *hdr;
+	struct ath_frame_info *fi = get_frame_info(skb);
 	struct ath_node *an;
 	struct ath_atx_tid *tid;
-	__le16 fc;
-	u8 *qc;
+	enum ath9k_key_type keytype;
+	u16 seqno = 0;
+	u8 tidno;
 
-	if (!tx_info->control.sta)
-		return;
+	keytype = ath9k_cmn_get_hw_crypto_keytype(skb);
 
-	an = (struct ath_node *)tx_info->control.sta->drv_priv;
 	hdr = (struct ieee80211_hdr *)skb->data;
-	fc = hdr->frame_control;
+	if (sta && ieee80211_is_data_qos(hdr->frame_control) &&
+		conf_is_ht(&hw->conf) && (sc->sc_flags & SC_OP_TXAGGR)) {
 
-	if (ieee80211_is_data_qos(fc)) {
-		qc = ieee80211_get_qos_ctl(hdr);
-		bf->bf_tidno = qc[0] & 0xf;
+		an = (struct ath_node *) sta->drv_priv;
+		tidno = ieee80211_get_qos_ctl(hdr)[0] & IEEE80211_QOS_CTL_TID_MASK;
+
+		/*
+		 * Override seqno set by upper layer with the one
+		 * in tx aggregation state.
+		 */
+		tid = ATH_AN_2_TID(an, tidno);
+		seqno = tid->seq_next;
+		hdr->seq_ctrl = cpu_to_le16(seqno << IEEE80211_SEQ_SEQ_SHIFT);
+		INCR(tid->seq_next, IEEE80211_SEQ_MAX);
 	}
 
-	/*
-	 * For HT capable stations, we save tidno for later use.
-	 * We also override seqno set by upper layer with the one
-	 * in tx aggregation state.
-	 */
-	tid = ATH_AN_2_TID(an, bf->bf_tidno);
-	hdr->seq_ctrl = cpu_to_le16(tid->seq_next << IEEE80211_SEQ_SEQ_SHIFT);
-	bf->bf_seqno = tid->seq_next;
-	INCR(tid->seq_next, IEEE80211_SEQ_MAX);
+	memset(fi, 0, sizeof(*fi));
+	if (hw_key)
+		fi->keyix = hw_key->hw_key_idx;
+	else
+		fi->keyix = ATH9K_TXKEYIX_INVALID;
+	fi->keytype = keytype;
+	fi->framelen = framelen;
+	fi->seqno = seqno;
 }
 
-static int setup_tx_flags(struct sk_buff *skb, bool use_ldpc)
+static int setup_tx_flags(struct sk_buff *skb)
 {
 	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
 	int flags = 0;
@@ -1427,7 +1469,7 @@ static int setup_tx_flags(struct sk_buff
 	if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK)
 		flags |= ATH9K_TXDESC_NOACK;
 
-	if (use_ldpc)
+	if (tx_info->flags & IEEE80211_TX_CTL_LDPC)
 		flags |= ATH9K_TXDESC_LDPC;
 
 	return flags;
@@ -1439,13 +1481,11 @@ static int setup_tx_flags(struct sk_buff
  * width  - 0 for 20 MHz, 1 for 40 MHz
  * half_gi - to use 4us v/s 3.6 us for symbol time
  */
-static u32 ath_pkt_duration(struct ath_softc *sc, u8 rix, struct ath_buf *bf,
+static u32 ath_pkt_duration(struct ath_softc *sc, u8 rix, int pktlen,
 			    int width, int half_gi, bool shortPreamble)
 {
 	u32 nbits, nsymbits, duration, nsymbols;
-	int streams, pktlen;
-
-	pktlen = bf_isaggr(bf) ? bf->bf_al : bf->bf_frmlen;
+	int streams;
 
 	/* find number of symbols: PLCP + data */
 	streams = HT_RC_2_STREAMS(rix);
@@ -1464,7 +1504,19 @@ static u32 ath_pkt_duration(struct ath_s
 	return duration;
 }
 
-static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf)
+u8 ath_txchainmask_reduction(struct ath_softc *sc, u8 chainmask, u32 rate)
+{
+	struct ath_hw *ah = sc->sc_ah;
+	struct ath9k_channel *curchan = ah->curchan;
+	if ((sc->sc_flags & SC_OP_ENABLE_APM) &&
+			(curchan->channelFlags & CHANNEL_5GHZ) &&
+			(chainmask == 0x7) && (rate < 0x90))
+		return 0x3;
+	else
+		return chainmask;
+}
+
+static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf, int len)
 {
 	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
 	struct ath9k_11n_rate_series series[4];
@@ -1504,7 +1556,6 @@ static void ath_buf_set_rate(struct ath_
 
 		rix = rates[i].idx;
 		series[i].Tries = rates[i].count;
-		series[i].ChSel = common->tx_chainmask;
 
 		if ((sc->config.ath_aggr_prot && bf_isaggr(bf)) ||
 		    (rates[i].flags & IEEE80211_TX_RC_USE_RTS_CTS)) {
@@ -1527,14 +1578,16 @@ static void ath_buf_set_rate(struct ath_
 		if (rates[i].flags & IEEE80211_TX_RC_MCS) {
 			/* MCS rates */
 			series[i].Rate = rix | 0x80;
-			series[i].PktDuration = ath_pkt_duration(sc, rix, bf,
+			series[i].ChSel = ath_txchainmask_reduction(sc,
+					common->tx_chainmask, series[i].Rate);
+			series[i].PktDuration = ath_pkt_duration(sc, rix, len,
 				 is_40, is_sgi, is_sp);
 			if (rix < 8 && (tx_info->flags & IEEE80211_TX_CTL_STBC))
 				series[i].RateFlags |= ATH9K_RATESERIES_STBC;
 			continue;
 		}
 
-		/* legcay rates */
+		/* legacy rates */
 		if ((tx_info->band == IEEE80211_BAND_2GHZ) &&
 		    !(rate->flags & IEEE80211_RATE_ERP_G))
 			phy = WLAN_RC_PHY_CCK;
@@ -1550,12 +1603,18 @@ static void ath_buf_set_rate(struct ath_
 			is_sp = false;
 		}
 
+		if (bf->bf_state.bfs_paprd)
+			series[i].ChSel = common->tx_chainmask;
+		else
+			series[i].ChSel = ath_txchainmask_reduction(sc,
+					common->tx_chainmask, series[i].Rate);
+
 		series[i].PktDuration = ath9k_hw_computetxtime(sc->sc_ah,
-			phy, rate->bitrate * 100, bf->bf_frmlen, rix, is_sp);
+			phy, rate->bitrate * 100, len, rix, is_sp);
 	}
 
 	/* For AR5416 - RTS cannot be followed by a frame larger than 8K */
-	if (bf_isaggr(bf) && (bf->bf_al > sc->sc_ah->caps.rts_aggr_limit))
+	if (bf_isaggr(bf) && (len > sc->sc_ah->caps.rts_aggr_limit))
 		flags &= ~ATH9K_TXDESC_RTSENA;
 
 	/* ATH9K_TXDESC_RTSENA and ATH9K_TXDESC_CTSENA are mutually exclusive. */
@@ -1572,67 +1631,29 @@ static void ath_buf_set_rate(struct ath_
 		ath9k_hw_set11n_burstduration(sc->sc_ah, bf->bf_desc, 8192);
 }
 
-static int ath_tx_setup_buffer(struct ieee80211_hw *hw, struct ath_buf *bf,
-				struct sk_buff *skb,
-				struct ath_tx_control *txctl)
+static struct ath_buf *ath_tx_setup_buffer(struct ieee80211_hw *hw,
+					   struct ath_txq *txq,
+					   struct sk_buff *skb)
 {
 	struct ath_wiphy *aphy = hw->priv;
 	struct ath_softc *sc = aphy->sc;
-	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
-	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
-	int hdrlen;
-	__le16 fc;
-	int padpos, padsize;
-	bool use_ldpc = false;
+	struct ath_hw *ah = sc->sc_ah;
+	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+	struct ath_frame_info *fi = get_frame_info(skb);
+	struct ath_buf *bf;
+	struct ath_desc *ds;
+	int frm_type;
 
-	tx_info->pad[0] = 0;
-	switch (txctl->frame_type) {
-	case ATH9K_IFT_NOT_INTERNAL:
-		break;
-	case ATH9K_IFT_PAUSE:
-		tx_info->pad[0] |= ATH_TX_INFO_FRAME_TYPE_PAUSE;
-		/* fall through */
-	case ATH9K_IFT_UNPAUSE:
-		tx_info->pad[0] |= ATH_TX_INFO_FRAME_TYPE_INTERNAL;
-		break;
+	bf = ath_tx_get_buffer(sc);
+	if (!bf) {
+		ath_dbg(common, ATH_DBG_XMIT, "TX buffers are full\n");
+		return NULL;
 	}
-	hdrlen = ieee80211_get_hdrlen_from_skb(skb);
-	fc = hdr->frame_control;
 
 	ATH_TXBUF_RESET(bf);
 
 	bf->aphy = aphy;
-	bf->bf_frmlen = skb->len + FCS_LEN;
-	/* Remove the padding size from bf_frmlen, if any */
-	padpos = ath9k_cmn_padpos(hdr->frame_control);
-	padsize = padpos & 3;
-	if (padsize && skb->len>padpos+padsize) {
-		bf->bf_frmlen -= padsize;
-	}
-
-	if (!txctl->paprd && conf_is_ht(&hw->conf)) {
-		bf->bf_state.bf_type |= BUF_HT;
-		if (tx_info->flags & IEEE80211_TX_CTL_LDPC)
-			use_ldpc = true;
-	}
-
-	bf->bf_state.bfs_paprd = txctl->paprd;
-	if (txctl->paprd)
-		bf->bf_state.bfs_paprd_timestamp = jiffies;
-	bf->bf_flags = setup_tx_flags(skb, use_ldpc);
-
-	bf->bf_keytype = ath9k_cmn_get_hw_crypto_keytype(skb);
-	if (bf->bf_keytype != ATH9K_KEY_TYPE_CLEAR) {
-		bf->bf_frmlen += tx_info->control.hw_key->icv_len;
-		bf->bf_keyix = tx_info->control.hw_key->hw_key_idx;
-	} else {
-		bf->bf_keyix = ATH9K_TXKEYIX_INVALID;
-	}
-
-	if (ieee80211_is_data_qos(fc) && bf_isht(bf) &&
-	    (sc->sc_flags & SC_OP_TXAGGR))
-		assign_aggr_tid_seqno(skb, bf);
-
+	bf->bf_flags = setup_tx_flags(skb);
 	bf->bf_mpdu = skb;
 
 	bf->bf_buf_addr = dma_map_single(sc->dev, skb->data,
@@ -1640,42 +1661,19 @@ static int ath_tx_setup_buffer(struct ie
 	if (unlikely(dma_mapping_error(sc->dev, bf->bf_buf_addr))) {
 		bf->bf_mpdu = NULL;
 		bf->bf_buf_addr = 0;
-		ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL,
-			  "dma_mapping_error() on TX\n");
-		return -ENOMEM;
+		ath_err(ath9k_hw_common(sc->sc_ah),
+			"dma_mapping_error() on TX\n");
+		ath_tx_return_buffer(sc, bf);
+		return NULL;
 	}
 
-	bf->bf_tx_aborted = false;
-
-	return 0;
-}
-
-/* FIXME: tx power */
-static void ath_tx_start_dma(struct ath_softc *sc, struct ath_buf *bf,
-			     struct ath_tx_control *txctl)
-{
-	struct sk_buff *skb = bf->bf_mpdu;
-	struct ieee80211_tx_info *tx_info =  IEEE80211_SKB_CB(skb);
-	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
-	struct ath_node *an = NULL;
-	struct list_head bf_head;
-	struct ath_desc *ds;
-	struct ath_atx_tid *tid;
-	struct ath_hw *ah = sc->sc_ah;
-	int frm_type;
-	__le16 fc;
-
 	frm_type = get_hw_packet_type(skb);
-	fc = hdr->frame_control;
-
-	INIT_LIST_HEAD(&bf_head);
-	list_add_tail(&bf->list, &bf_head);
 
 	ds = bf->bf_desc;
 	ath9k_hw_set_desc_link(ah, ds, 0);
 
-	ath9k_hw_set11n_txdesc(ah, ds, bf->bf_frmlen, frm_type, MAX_RATE_POWER,
-			       bf->bf_keyix, bf->bf_keytype, bf->bf_flags);
+	ath9k_hw_set11n_txdesc(ah, ds, fi->framelen, frm_type, MAX_RATE_POWER,
+			       fi->keyix, fi->keytype, bf->bf_flags);
 
 	ath9k_hw_filltxdesc(ah, ds,
 			    skb->len,	/* segment length */
@@ -1683,42 +1681,56 @@ static void ath_tx_start_dma(struct ath_
 			    true,	/* last segment */
 			    ds,		/* first descriptor */
 			    bf->bf_buf_addr,
-			    txctl->txq->axq_qnum);
+			    txq->axq_qnum);
 
-	if (bf->bf_state.bfs_paprd)
-		ar9003_hw_set_paprd_txdesc(ah, ds, bf->bf_state.bfs_paprd);
+
+	return bf;
+}
+
+/* FIXME: tx power */
+static void ath_tx_start_dma(struct ath_softc *sc, struct ath_buf *bf,
+			     struct ath_tx_control *txctl)
+{
+	struct sk_buff *skb = bf->bf_mpdu;
+	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
+	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+	struct list_head bf_head;
+	struct ath_atx_tid *tid = NULL;
+	u8 tidno;
 
 	spin_lock_bh(&txctl->txq->axq_lock);
 
-	if (bf_isht(bf) && (sc->sc_flags & SC_OP_TXAGGR) &&
-	    tx_info->control.sta) {
-		an = (struct ath_node *)tx_info->control.sta->drv_priv;
-		tid = ATH_AN_2_TID(an, bf->bf_tidno);
+	if (ieee80211_is_data_qos(hdr->frame_control) && txctl->an) {
+		tidno = ieee80211_get_qos_ctl(hdr)[0] &
+			IEEE80211_QOS_CTL_TID_MASK;
+		tid = ATH_AN_2_TID(txctl->an, tidno);
 
-		if (!ieee80211_is_data_qos(fc)) {
-			ath_tx_send_normal(sc, txctl->txq, &bf_head);
-			goto tx_done;
-		}
+		WARN_ON(tid->ac->txq != txctl->txq);
+	}
 
-		if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) {
-			/*
-			 * Try aggregation if it's a unicast data frame
-			 * and the destination is HT capable.
-			 */
-			ath_tx_send_ampdu(sc, tid, &bf_head, txctl);
-		} else {
-			/*
-			 * Send this frame as regular when ADDBA
-			 * exchange is neither complete nor pending.
-			 */
-			ath_tx_send_ht_normal(sc, txctl->txq,
-					      tid, &bf_head);
-		}
+	if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) && tid) {
+		/*
+		 * Try aggregation if it's a unicast data frame
+		 * and the destination is HT capable.
+		 */
+		ath_tx_send_ampdu(sc, tid, bf, txctl);
 	} else {
-		ath_tx_send_normal(sc, txctl->txq, &bf_head);
+		INIT_LIST_HEAD(&bf_head);
+		list_add_tail(&bf->list, &bf_head);
+
+		bf->bf_state.bfs_ftype = txctl->frame_type;
+		bf->bf_state.bfs_paprd = txctl->paprd;
+
+		if (bf->bf_state.bfs_paprd)
+			ar9003_hw_set_paprd_txdesc(sc->sc_ah, bf->bf_desc,
+						   bf->bf_state.bfs_paprd);
+
+		if (txctl->paprd)
+			bf->bf_state.bfs_paprd_timestamp = jiffies;
+
+		ath_tx_send_normal(sc, txctl->txq, tid, &bf_head);
 	}
 
-tx_done:
 	spin_unlock_bh(&txctl->txq->axq_lock);
 }
 
@@ -1726,66 +1738,23 @@ tx_done:
 int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
 		 struct ath_tx_control *txctl)
 {
+	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+	struct ieee80211_sta *sta = info->control.sta;
 	struct ath_wiphy *aphy = hw->priv;
 	struct ath_softc *sc = aphy->sc;
-	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
 	struct ath_txq *txq = txctl->txq;
 	struct ath_buf *bf;
-	int q, r;
-
-	bf = ath_tx_get_buffer(sc);
-	if (!bf) {
-		ath_print(common, ATH_DBG_XMIT, "TX buffers are full\n");
-		return -1;
-	}
-
-	r = ath_tx_setup_buffer(hw, bf, skb, txctl);
-	if (unlikely(r)) {
-		ath_print(common, ATH_DBG_FATAL, "TX mem alloc failure\n");
-
-		/* upon ath_tx_processq() this TX queue will be resumed, we
-		 * guarantee this will happen by knowing beforehand that
-		 * we will at least have to run TX completionon one buffer
-		 * on the queue */
-		spin_lock_bh(&txq->axq_lock);
-		if (!txq->stopped && txq->axq_depth > 1) {
-			ath_mac80211_stop_queue(sc, skb_get_queue_mapping(skb));
-			txq->stopped = 1;
-		}
-		spin_unlock_bh(&txq->axq_lock);
-
-		ath_tx_return_buffer(sc, bf);
-
-		return r;
-	}
-
-	q = skb_get_queue_mapping(skb);
-	if (q >= 4)
-		q = 0;
-
-	spin_lock_bh(&txq->axq_lock);
-	if (++sc->tx.pending_frames[q] > ATH_MAX_QDEPTH && !txq->stopped) {
-		ath_mac80211_stop_queue(sc, skb_get_queue_mapping(skb));
-		txq->stopped = 1;
-	}
-	spin_unlock_bh(&txq->axq_lock);
-
-	ath_tx_start_dma(sc, bf, txctl);
-
-	return 0;
-}
-
-void ath_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb)
-{
-	struct ath_wiphy *aphy = hw->priv;
-	struct ath_softc *sc = aphy->sc;
-	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
-	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
 	int padpos, padsize;
-	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
-	struct ath_tx_control txctl;
+	int frmlen = skb->len + FCS_LEN;
+	int q;
 
-	memset(&txctl, 0, sizeof(struct ath_tx_control));
+	/* NOTE:  sta can be NULL according to net/mac80211.h */
+	if (sta)
+		txctl->an = (struct ath_node *)sta->drv_priv;
+
+	if (info->control.hw_key)
+		frmlen += info->control.hw_key->icv_len;
 
 	/*
 	 * As a temporary workaround, assign seq# here; this will likely need
@@ -1802,30 +1771,37 @@ void ath_tx_cabq(struct ieee80211_hw *hw
 	/* Add the padding after the header if this is not already done */
 	padpos = ath9k_cmn_padpos(hdr->frame_control);
 	padsize = padpos & 3;
-	if (padsize && skb->len>padpos) {
-		if (skb_headroom(skb) < padsize) {
-			ath_print(common, ATH_DBG_XMIT,
-				  "TX CABQ padding failed\n");
-			dev_kfree_skb_any(skb);
-			return;
-		}
+	if (padsize && skb->len > padpos) {
+		if (skb_headroom(skb) < padsize)
+			return -ENOMEM;
+
 		skb_push(skb, padsize);
 		memmove(skb->data, skb->data + padsize, padpos);
 	}
 
-	txctl.txq = sc->beacon.cabq;
+	setup_frame_info(hw, skb, frmlen);
 
-	ath_print(common, ATH_DBG_XMIT,
-		  "transmitting CABQ packet, skb: %p\n", skb);
+	/*
+	 * At this point, the vif, hw_key and sta pointers in the tx control
+	 * info are no longer valid (overwritten by the ath_frame_info data.
+	 */
 
-	if (ath_tx_start(hw, skb, &txctl) != 0) {
-		ath_print(common, ATH_DBG_XMIT, "CABQ TX failed\n");
-		goto exit;
+	bf = ath_tx_setup_buffer(hw, txctl->txq, skb);
+	if (unlikely(!bf))
+		return -ENOMEM;
+
+	q = skb_get_queue_mapping(skb);
+	spin_lock_bh(&txq->axq_lock);
+	if (txq == sc->tx.txq_map[q] &&
+	    ++txq->pending_frames > ATH_MAX_QDEPTH && !txq->stopped) {
+		ath_mac80211_stop_queue(sc, q);
+		txq->stopped = 1;
 	}
+	spin_unlock_bh(&txq->axq_lock);
 
-	return;
-exit:
-	dev_kfree_skb_any(skb);
+	ath_tx_start_dma(sc, bf, txctl);
+
+	return 0;
 }
 
 /*****************/
@@ -1833,7 +1809,8 @@ exit:
 /*****************/
 
 static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
-			    struct ath_wiphy *aphy, int tx_flags)
+			    struct ath_wiphy *aphy, int tx_flags, int ftype,
+			    struct ath_txq *txq)
 {
 	struct ieee80211_hw *hw = sc->hw;
 	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
@@ -1841,7 +1818,7 @@ static void ath_tx_complete(struct ath_s
 	struct ieee80211_hdr * hdr = (struct ieee80211_hdr *)skb->data;
 	int q, padpos, padsize;
 
-	ath_print(common, ATH_DBG_XMIT, "TX complete: skb: %p\n", skb);
+	ath_dbg(common, ATH_DBG_XMIT, "TX complete: skb: %p\n", skb);
 
 	if (aphy)
 		hw = aphy->hw;
@@ -1867,24 +1844,24 @@ static void ath_tx_complete(struct ath_s
 
 	if (sc->ps_flags & PS_WAIT_FOR_TX_ACK) {
 		sc->ps_flags &= ~PS_WAIT_FOR_TX_ACK;
-		ath_print(common, ATH_DBG_PS,
-			  "Going back to sleep after having "
-			  "received TX status (0x%lx)\n",
+		ath_dbg(common, ATH_DBG_PS,
+			"Going back to sleep after having received TX status (0x%lx)\n",
 			sc->ps_flags & (PS_WAIT_FOR_BEACON |
 					PS_WAIT_FOR_CAB |
 					PS_WAIT_FOR_PSPOLL_DATA |
 					PS_WAIT_FOR_TX_ACK));
 	}
 
-	if (unlikely(tx_info->pad[0] & ATH_TX_INFO_FRAME_TYPE_INTERNAL))
-		ath9k_tx_status(hw, skb);
+	if (unlikely(ftype))
+		ath9k_tx_status(hw, skb, ftype);
 	else {
 		q = skb_get_queue_mapping(skb);
-		if (q >= 4)
-			q = 0;
-
-		if (--sc->tx.pending_frames[q] < 0)
-			sc->tx.pending_frames[q] = 0;
+		if (txq == sc->tx.txq_map[q]) {
+			spin_lock_bh(&txq->axq_lock);
+			if (WARN_ON(--txq->pending_frames < 0))
+				txq->pending_frames = 0;
+			spin_unlock_bh(&txq->axq_lock);
+		}
 
 		ieee80211_tx_status(hw, skb);
 	}
@@ -1913,14 +1890,15 @@ static void ath_tx_complete_buf(struct a
 
 	if (bf->bf_state.bfs_paprd) {
 		if (time_after(jiffies,
-			       bf->bf_state.bfs_paprd_timestamp +
-			       msecs_to_jiffies(ATH_PAPRD_TIMEOUT)))
+				bf->bf_state.bfs_paprd_timestamp +
+				msecs_to_jiffies(ATH_PAPRD_TIMEOUT)))
 			dev_kfree_skb_any(skb);
 		else
 			complete(&sc->paprd_complete);
 	} else {
-		ath_debug_stat_tx(sc, txq, bf, ts);
-		ath_tx_complete(sc, skb, bf->aphy, tx_flags);
+		ath_debug_stat_tx(sc, bf, ts);
+		ath_tx_complete(sc, skb, bf->aphy, tx_flags,
+				bf->bf_state.bfs_ftype, txq);
 	}
 	/* At this point, skb (bf->bf_mpdu) is consumed...make sure we don't
 	 * accidentally reference it later.
@@ -1935,42 +1913,15 @@ static void ath_tx_complete_buf(struct a
 	spin_unlock_irqrestore(&sc->tx.txbuflock, flags);
 }
 
-static int ath_tx_num_badfrms(struct ath_softc *sc, struct ath_buf *bf,
-			      struct ath_tx_status *ts, int txok)
-{
-	u16 seq_st = 0;
-	u32 ba[WME_BA_BMP_SIZE >> 5];
-	int ba_index;
-	int nbad = 0;
-	int isaggr = 0;
-
-	if (bf->bf_lastbf->bf_tx_aborted)
-		return 0;
-
-	isaggr = bf_isaggr(bf);
-	if (isaggr) {
-		seq_st = ts->ts_seqnum;
-		memcpy(ba, &ts->ba_low, WME_BA_BMP_SIZE >> 3);
-	}
-
-	while (bf) {
-		ba_index = ATH_BA_INDEX(seq_st, bf->bf_seqno);
-		if (!txok || (isaggr && !ATH_BA_ISSET(ba, ba_index)))
-			nbad++;
-
-		bf = bf->bf_next;
-	}
-
-	return nbad;
-}
-
 static void ath_tx_rc_status(struct ath_buf *bf, struct ath_tx_status *ts,
-			     int nbad, int txok, bool update_rc)
+			     int nframes, int nbad, int txok, bool update_rc)
 {
 	struct sk_buff *skb = bf->bf_mpdu;
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
 	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
 	struct ieee80211_hw *hw = bf->aphy->hw;
+	struct ath_softc *sc = bf->aphy->sc;
+	struct ath_hw *ah = sc->sc_ah;
 	u8 i, tx_rateindex;
 
 	if (txok)
@@ -1984,22 +1935,32 @@ static void ath_tx_rc_status(struct ath_
 	if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) && update_rc) {
 		tx_info->flags |= IEEE80211_TX_STAT_AMPDU;
 
-		BUG_ON(nbad > bf->bf_nframes);
+		BUG_ON(nbad > nframes);
 
-		tx_info->status.ampdu_len = bf->bf_nframes;
-		tx_info->status.ampdu_ack_len = bf->bf_nframes - nbad;
+		tx_info->status.ampdu_len = nframes;
+		tx_info->status.ampdu_ack_len = nframes - nbad;
 	}
 
 	if ((ts->ts_status & ATH9K_TXERR_FILT) == 0 &&
 	    (bf->bf_flags & ATH9K_TXDESC_NOACK) == 0 && update_rc) {
-		if (ieee80211_is_data(hdr->frame_control)) {
-			if (ts->ts_flags &
-			    (ATH9K_TX_DATA_UNDERRUN | ATH9K_TX_DELIM_UNDERRUN))
-				tx_info->pad[0] |= ATH_TX_INFO_UNDERRUN;
-			if ((ts->ts_status & ATH9K_TXERR_XRETRY) ||
-			    (ts->ts_status & ATH9K_TXERR_FIFO))
-				tx_info->pad[0] |= ATH_TX_INFO_XRETRY;
-		}
+		/*
+		 * If an underrun error is seen assume it as an excessive
+		 * retry only if max frame trigger level has been reached
+		 * (2 KB for single stream, and 4 KB for dual stream).
+		 * Adjust the long retry as if the frame was tried
+		 * hw->max_rate_tries times to affect how rate control updates
+		 * PER for the failed rate.
+		 * In case of congestion on the bus penalizing this type of
+		 * underruns should help hardware actually transmit new frames
+		 * successfully by eventually preferring slower rates.
+		 * This itself should also alleviate congestion on the bus.
+		 */
+		if (ieee80211_is_data(hdr->frame_control) &&
+		    (ts->ts_flags & (ATH9K_TX_DATA_UNDERRUN |
+		                     ATH9K_TX_DELIM_UNDERRUN)) &&
+		    ah->tx_trig_level >= sc->sc_ah->caps.tx_triglevel_max)
+			tx_info->status.rates[tx_rateindex].count =
+				hw->max_rate_tries;
 	}
 
 	for (i = tx_rateindex + 1; i < hw->max_rates; i++) {
@@ -2010,16 +1971,13 @@ static void ath_tx_rc_status(struct ath_
 	tx_info->status.rates[tx_rateindex].count = ts->ts_longretry + 1;
 }
 
-static void ath_wake_mac80211_queue(struct ath_softc *sc, struct ath_txq *txq)
+static void ath_wake_mac80211_queue(struct ath_softc *sc, int qnum)
 {
-	int qnum;
-
-	qnum = ath_get_mac80211_qnum(txq->axq_class, sc);
-	if (qnum == -1)
-		return;
+	struct ath_txq *txq;
 
+	txq = sc->tx.txq_map[qnum];
 	spin_lock_bh(&txq->axq_lock);
-	if (txq->stopped && sc->tx.pending_frames[qnum] < ATH_MAX_QDEPTH) {
+	if (txq->stopped && txq->pending_frames < ATH_MAX_QDEPTH) {
 		if (ath_mac80211_start_queue(sc, qnum))
 			txq->stopped = 0;
 	}
@@ -2036,10 +1994,11 @@ static void ath_tx_processq(struct ath_s
 	struct ath_tx_status ts;
 	int txok;
 	int status;
+	int qnum;
 
-	ath_print(common, ATH_DBG_QUEUE, "tx queue %d (%x), link %p\n",
-		  txq->axq_qnum, ath9k_hw_gettxbuf(sc->sc_ah, txq->axq_qnum),
-		  txq->axq_link);
+	ath_dbg(common, ATH_DBG_QUEUE, "tx queue %d (%x), link %p\n",
+		txq->axq_qnum, ath9k_hw_gettxbuf(sc->sc_ah, txq->axq_qnum),
+		txq->axq_link);
 
 	for (;;) {
 		spin_lock_bh(&txq->axq_lock);
@@ -2096,6 +2055,9 @@ static void ath_tx_processq(struct ath_s
 		txq->axq_tx_inprogress = false;
 		if (bf_held)
 			list_del(&bf_held->list);
+
+		if (bf_is_ampdu_not_probing(bf))
+			txq->axq_ampdu_depth--;
 		spin_unlock_bh(&txq->axq_lock);
 
 		if (bf_held)
@@ -2108,15 +2070,19 @@ static void ath_tx_processq(struct ath_s
 			 */
 			if (ts.ts_status & ATH9K_TXERR_XRETRY)
 				bf->bf_state.bf_type |= BUF_XRETRY;
-			ath_tx_rc_status(bf, &ts, txok ? 0 : 1, txok, true);
+			ath_tx_rc_status(bf, &ts, 1, txok ? 0 : 1, txok, true);
 		}
 
+		qnum = skb_get_queue_mapping(bf->bf_mpdu);
+
 		if (bf_isampdu(bf))
-			ath_tx_complete_aggr(sc, txq, bf, &bf_head, &ts, txok);
+			ath_tx_complete_aggr(sc, txq, bf, &bf_head, &ts, txok,
+					     true);
 		else
 			ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, txok, 0);
 
-		ath_wake_mac80211_queue(sc, txq);
+		if (txq == sc->tx.txq_map[qnum])
+			ath_wake_mac80211_queue(sc, qnum);
 
 		spin_lock_bh(&txq->axq_lock);
 		if (sc->sc_flags & SC_OP_TXAGGR)
@@ -2150,11 +2116,9 @@ static void ath_tx_complete_poll_work(st
 		}
 
 	if (needreset) {
-		ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_RESET,
-			  "tx hung, resetting the chip\n");
-		ath9k_ps_wakeup(sc);
+		ath_dbg(ath9k_hw_common(sc->sc_ah), ATH_DBG_RESET,
+			"tx hung, resetting the chip\n");
 		ath_reset(sc, true);
-		ath9k_ps_restore(sc);
 	}
 
 	ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work,
@@ -2186,14 +2150,15 @@ void ath_tx_edma_tasklet(struct ath_soft
 	struct list_head bf_head;
 	int status;
 	int txok;
+	int qnum;
 
 	for (;;) {
 		status = ath9k_hw_txprocdesc(ah, NULL, (void *)&txs);
 		if (status == -EINPROGRESS)
 			break;
 		if (status == -EIO) {
-			ath_print(common, ATH_DBG_XMIT,
-				  "Error processing tx status\n");
+			ath_dbg(common, ATH_DBG_XMIT,
+				"Error processing tx status\n");
 			break;
 		}
 
@@ -2219,6 +2184,8 @@ void ath_tx_edma_tasklet(struct ath_soft
 		INCR(txq->txq_tailidx, ATH_TXFIFO_DEPTH);
 		txq->axq_depth--;
 		txq->axq_tx_inprogress = false;
+		if (bf_is_ampdu_not_probing(bf))
+			txq->axq_ampdu_depth--;
 		spin_unlock_bh(&txq->axq_lock);
 
 		txok = !(txs.ts_status & ATH9K_TXERR_MASK);
@@ -2226,16 +2193,20 @@ void ath_tx_edma_tasklet(struct ath_soft
 		if (!bf_isampdu(bf)) {
 			if (txs.ts_status & ATH9K_TXERR_XRETRY)
 				bf->bf_state.bf_type |= BUF_XRETRY;
-			ath_tx_rc_status(bf, &txs, txok ? 0 : 1, txok, true);
+			ath_tx_rc_status(bf, &txs, 1, txok ? 0 : 1, txok, true);
 		}
 
+		qnum = skb_get_queue_mapping(bf->bf_mpdu);
+
 		if (bf_isampdu(bf))
-			ath_tx_complete_aggr(sc, txq, bf, &bf_head, &txs, txok);
+			ath_tx_complete_aggr(sc, txq, bf, &bf_head, &txs,
+					     txok, true);
 		else
 			ath_tx_complete_buf(sc, bf, txq, &bf_head,
 					    &txs, txok, 0);
 
-		ath_wake_mac80211_queue(sc, txq);
+		if (txq == sc->tx.txq_map[qnum])
+			ath_wake_mac80211_queue(sc, qnum);
 
 		spin_lock_bh(&txq->axq_lock);
 		if (!list_empty(&txq->txq_fifo_pending)) {
@@ -2300,16 +2271,16 @@ int ath_tx_init(struct ath_softc *sc, in
 	error = ath_descdma_setup(sc, &sc->tx.txdma, &sc->tx.txbuf,
 				  "tx", nbufs, 1, 1);
 	if (error != 0) {
-		ath_print(common, ATH_DBG_FATAL,
-			  "Failed to allocate tx descriptors: %d\n", error);
+		ath_err(common,
+			"Failed to allocate tx descriptors: %d\n", error);
 		goto err;
 	}
 
 	error = ath_descdma_setup(sc, &sc->beacon.bdma, &sc->beacon.bbuf,
 				  "beacon", ATH_BCBUF, 1, 1);
 	if (error != 0) {
-		ath_print(common, ATH_DBG_FATAL,
-			  "Failed to allocate beacon descriptors: %d\n", error);
+		ath_err(common,
+			"Failed to allocate beacon descriptors: %d\n", error);
 		goto err;
 	}
 
@@ -2367,7 +2338,7 @@ void ath_tx_node_init(struct ath_softc *
 	for (acno = 0, ac = &an->ac[acno];
 	     acno < WME_NUM_AC; acno++, ac++) {
 		ac->sched    = false;
-		ac->qnum = sc->tx.hwq_map[acno];
+		ac->txq = sc->tx.txq_map[acno];
 		INIT_LIST_HEAD(&ac->tid_q);
 	}
 }
@@ -2377,17 +2348,13 @@ void ath_tx_node_cleanup(struct ath_soft
 	struct ath_atx_ac *ac;
 	struct ath_atx_tid *tid;
 	struct ath_txq *txq;
-	int i, tidno;
+	int tidno;
 
 	for (tidno = 0, tid = &an->tid[tidno];
 	     tidno < WME_NUM_TID; tidno++, tid++) {
-		i = tid->ac->qnum;
-
-		if (!ATH_TXQ_SETUP(sc, i))
-			continue;
 
-		txq = &sc->tx.txq[i];
 		ac = tid->ac;
+		txq = ac->txq;
 
 		spin_lock_bh(&txq->axq_lock);
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath.h linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath.h
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/ath.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/ath.h	2011-03-14 21:20:32.000000000 -0400
@@ -126,6 +126,7 @@ struct ath_bus_ops {
 	void (*read_cachesize)(struct ath_common *common, int *csz);
 	bool (*eeprom_read)(struct ath_common *common, u32 off, u16 *data);
 	void (*bt_coex_prep)(struct ath_common *common);
+	void (*extn_synch_en)(struct ath_common *common);
 };
 
 struct ath_common {
@@ -162,6 +163,8 @@ struct ath_common {
 	struct ath_regulatory regulatory;
 	const struct ath_ops *ops;
 	const struct ath_bus_ops *bus_ops;
+
+	bool btcoex_enabled;
 };
 
 struct sk_buff *ath_rxbuf_alloc(struct ath_common *common,
@@ -178,4 +181,112 @@ bool ath_hw_keyreset(struct ath_common *
 void ath_hw_cycle_counters_update(struct ath_common *common);
 int32_t ath_hw_get_listen_time(struct ath_common *common);
 
+extern __attribute__ ((format (printf, 3, 4))) int
+ath_printk(const char *level, struct ath_common *common, const char *fmt, ...);
+
+#define ath_emerg(common, fmt, ...)				\
+	ath_printk(KERN_EMERG, common, fmt, ##__VA_ARGS__)
+#define ath_alert(common, fmt, ...)				\
+	ath_printk(KERN_ALERT, common, fmt, ##__VA_ARGS__)
+#define ath_crit(common, fmt, ...)				\
+	ath_printk(KERN_CRIT, common, fmt, ##__VA_ARGS__)
+#define ath_err(common, fmt, ...)				\
+	ath_printk(KERN_ERR, common, fmt, ##__VA_ARGS__)
+#define ath_warn(common, fmt, ...)				\
+	ath_printk(KERN_WARNING, common, fmt, ##__VA_ARGS__)
+#define ath_notice(common, fmt, ...)				\
+	ath_printk(KERN_NOTICE, common, fmt, ##__VA_ARGS__)
+#define ath_info(common, fmt, ...)				\
+	ath_printk(KERN_INFO, common, fmt, ##__VA_ARGS__)
+
+/**
+ * enum ath_debug_level - atheros wireless debug level
+ *
+ * @ATH_DBG_RESET: reset processing
+ * @ATH_DBG_QUEUE: hardware queue management
+ * @ATH_DBG_EEPROM: eeprom processing
+ * @ATH_DBG_CALIBRATE: periodic calibration
+ * @ATH_DBG_INTERRUPT: interrupt processing
+ * @ATH_DBG_REGULATORY: regulatory processing
+ * @ATH_DBG_ANI: adaptive noise immunitive processing
+ * @ATH_DBG_XMIT: basic xmit operation
+ * @ATH_DBG_BEACON: beacon handling
+ * @ATH_DBG_CONFIG: configuration of the hardware
+ * @ATH_DBG_FATAL: fatal errors, this is the default, DBG_DEFAULT
+ * @ATH_DBG_PS: power save processing
+ * @ATH_DBG_HWTIMER: hardware timer handling
+ * @ATH_DBG_BTCOEX: bluetooth coexistance
+ * @ATH_DBG_BSTUCK: stuck beacons
+ * @ATH_DBG_ANY: enable all debugging
+ *
+ * The debug level is used to control the amount and type of debugging output
+ * we want to see. Each driver has its own method for enabling debugging and
+ * modifying debug level states -- but this is typically done through a
+ * module parameter 'debug' along with a respective 'debug' debugfs file
+ * entry.
+ */
+enum ATH_DEBUG {
+	ATH_DBG_RESET		= 0x00000001,
+	ATH_DBG_QUEUE		= 0x00000002,
+	ATH_DBG_EEPROM		= 0x00000004,
+	ATH_DBG_CALIBRATE	= 0x00000008,
+	ATH_DBG_INTERRUPT	= 0x00000010,
+	ATH_DBG_REGULATORY	= 0x00000020,
+	ATH_DBG_ANI		= 0x00000040,
+	ATH_DBG_XMIT		= 0x00000080,
+	ATH_DBG_BEACON		= 0x00000100,
+	ATH_DBG_CONFIG		= 0x00000200,
+	ATH_DBG_FATAL		= 0x00000400,
+	ATH_DBG_PS		= 0x00000800,
+	ATH_DBG_HWTIMER		= 0x00001000,
+	ATH_DBG_BTCOEX		= 0x00002000,
+	ATH_DBG_WMI		= 0x00004000,
+	ATH_DBG_BSTUCK		= 0x00008000,
+	ATH_DBG_ANY		= 0xffffffff
+};
+
+#define ATH_DBG_DEFAULT (ATH_DBG_FATAL)
+
+#ifdef CONFIG_ATH_DEBUG
+
+#define ath_dbg(common, dbg_mask, fmt, ...)			\
+({								\
+	int rtn;						\
+	if ((common)->debug_mask & dbg_mask)			\
+		rtn = ath_printk(KERN_DEBUG, common, fmt,	\
+				 ##__VA_ARGS__);		\
+	else							\
+		rtn = 0;					\
+								\
+	rtn;							\
+})
+#define ATH_DBG_WARN(foo, arg...) WARN(foo, arg)
+#define ATH_DBG_WARN_ON_ONCE(foo) WARN_ON_ONCE(foo)
+
+#else
+
+static inline  __attribute__ ((format (printf, 3, 4))) int
+ath_dbg(struct ath_common *common, enum ATH_DEBUG dbg_mask,
+	const char *fmt, ...)
+{
+	return 0;
+}
+#define ATH_DBG_WARN(foo, arg...) do {} while (0)
+#define ATH_DBG_WARN_ON_ONCE(foo) ({				\
+	int __ret_warn_once = !!(foo);				\
+	unlikely(__ret_warn_once);				\
+})
+
+#endif /* CONFIG_ATH_DEBUG */
+
+/** Returns string describing opmode, or NULL if unknown mode. */
+#ifdef CONFIG_ATH_DEBUG
+const char *ath_opmode_to_string(enum nl80211_iftype opmode);
+#else
+static inline const char *ath_opmode_to_string(enum nl80211_iftype opmode)
+{
+	return "UNKNOWN";
+}
+#endif
+
 #endif /* ATH_H */
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/carl9170/carl9170.h linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/carl9170/carl9170.h
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/carl9170/carl9170.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/carl9170/carl9170.h	2011-03-14 21:20:32.000000000 -0400
@@ -48,7 +48,7 @@
 #include <linux/usb.h>
 #ifdef CONFIG_CARL9170_LEDS
 #include <linux/leds.h>
-#endif /* CONFIG_CARL170_LEDS */
+#endif /* CONFIG_CARL9170_LEDS */
 #ifdef CONFIG_CARL9170_WPC
 #include <linux/input.h>
 #endif /* CONFIG_CARL9170_WPC */
@@ -215,7 +215,7 @@ enum carl9170_restart_reasons {
 	CARL9170_RR_TOO_MANY_FIRMWARE_ERRORS,
 	CARL9170_RR_WATCHDOG,
 	CARL9170_RR_STUCK_TX,
-	CARL9170_RR_SLOW_SYSTEM,
+	CARL9170_RR_UNRESPONSIVE_DEVICE,
 	CARL9170_RR_COMMAND_TIMEOUT,
 	CARL9170_RR_TOO_MANY_PHY_ERRORS,
 	CARL9170_RR_LOST_RSP,
@@ -287,6 +287,7 @@ struct ar9170 {
 
 	/* reset / stuck frames/queue detection */
 	struct work_struct restart_work;
+	struct work_struct ping_work;
 	unsigned int restart_counter;
 	unsigned long queue_stop_timeout[__AR9170_NUM_TXQ];
 	unsigned long max_queue_stop_timeout[__AR9170_NUM_TXQ];
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/carl9170/cmd.c linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/carl9170/cmd.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/carl9170/cmd.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/carl9170/cmd.c	2011-03-14 21:20:32.000000000 -0400
@@ -41,7 +41,7 @@
 
 int carl9170_write_reg(struct ar9170 *ar, const u32 reg, const u32 val)
 {
-	__le32 buf[2] = {
+	const __le32 buf[2] = {
 		cpu_to_le32(reg),
 		cpu_to_le32(val),
 	};
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/carl9170/fwcmd.h linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/carl9170/fwcmd.h
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/carl9170/fwcmd.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/carl9170/fwcmd.h	2011-03-14 21:20:32.000000000 -0400
@@ -97,13 +97,13 @@ struct carl9170_set_key_cmd {
 	__le16		type;
 	u8		macAddr[6];
 	u32		key[4];
-} __packed;
+} __packed __aligned(4);
 #define CARL9170_SET_KEY_CMD_SIZE		28
 
 struct carl9170_disable_key_cmd {
 	__le16		user;
 	__le16		padding;
-} __packed;
+} __packed __aligned(4);
 #define CARL9170_DISABLE_KEY_CMD_SIZE		4
 
 struct carl9170_u32_list {
@@ -206,7 +206,7 @@ struct carl9170_cmd {
 		struct carl9170_rx_filter_cmd	rx_filter;
 		u8 data[CARL9170_MAX_CMD_PAYLOAD_LEN];
 	} __packed;
-} __packed;
+} __packed __aligned(4);
 
 #define	CARL9170_TX_STATUS_QUEUE	3
 #define	CARL9170_TX_STATUS_QUEUE_S	0
@@ -216,6 +216,7 @@ struct carl9170_cmd {
 #define	CARL9170_TX_STATUS_TRIES	(7 << CARL9170_TX_STATUS_TRIES_S)
 #define	CARL9170_TX_STATUS_SUCCESS	0x80
 
+#ifdef __CARL9170FW__
 /*
  * NOTE:
  * Both structs [carl9170_tx_status and _carl9170_tx_status]
@@ -232,6 +233,8 @@ struct carl9170_tx_status {
 	u8 tries:3;
 	u8 success:1;
 } __packed;
+#endif /* __CARL9170FW__ */
+
 struct _carl9170_tx_status {
 	/*
 	 * This version should be immune to all alignment bugs.
@@ -272,13 +275,15 @@ struct carl9170_rsp {
 		struct carl9170_rf_init_result	rf_init_res;
 		struct carl9170_u32_list	rreg_res;
 		struct carl9170_u32_list	echo;
+#ifdef __CARL9170FW__
 		struct carl9170_tx_status	tx_status[0];
+#endif /* __CARL9170FW__ */
 		struct _carl9170_tx_status	_tx_status[0];
 		struct carl9170_gpio		gpio;
 		struct carl9170_tsf_rsp		tsf;
 		struct carl9170_psm		psm;
 		u8 data[CARL9170_MAX_CMD_PAYLOAD_LEN];
 	} __packed;
-} __packed;
+} __packed __aligned(4);
 
 #endif /* __CARL9170_SHARED_FWCMD_H */
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/carl9170/hw.h linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/carl9170/hw.h
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/carl9170/hw.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/carl9170/hw.h	2011-03-14 21:20:32.000000000 -0400
@@ -712,7 +712,8 @@ struct ar9170_stream {
 	__le16 tag;
 
 	u8 payload[0];
-};
+} __packed __aligned(4);
+#define AR9170_STREAM_LEN				4
 
 #define AR9170_MAX_ACKTABLE_ENTRIES			8
 #define AR9170_MAX_VIRTUAL_MAC				7
@@ -736,4 +737,8 @@ struct ar9170_stream {
 
 #define MOD_VAL(reg, value, newvalue)					\
 	(((value) & ~reg) | (((newvalue) << reg##_S) & reg))
+
+#define GET_VAL(reg, value)						\
+	(((value) & reg) >> reg##_S)
+
 #endif	/* __CARL9170_SHARED_HW_H */
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/carl9170/mac.c linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/carl9170/mac.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/carl9170/mac.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/carl9170/mac.c	2011-03-14 21:20:32.000000000 -0400
@@ -205,8 +205,8 @@ int carl9170_init_mac(struct ar9170 *ar)
 	carl9170_regwrite(AR9170_MAC_REG_BACKOFF_PROTECT, 0x105);
 
 	/* Aggregation MAX number and timeout */
-	carl9170_regwrite(AR9170_MAC_REG_AMPDU_FACTOR, 0xa);
-	carl9170_regwrite(AR9170_MAC_REG_AMPDU_DENSITY, 0x140a00);
+	carl9170_regwrite(AR9170_MAC_REG_AMPDU_FACTOR, 0x8000a);
+	carl9170_regwrite(AR9170_MAC_REG_AMPDU_DENSITY, 0x140a07);
 
 	carl9170_regwrite(AR9170_MAC_REG_FRAMETYPE_FILTER,
 			  AR9170_MAC_FTF_DEFAULTS);
@@ -457,8 +457,9 @@ int carl9170_set_beacon_timers(struct ar
 
 int carl9170_update_beacon(struct ar9170 *ar, const bool submit)
 {
-	struct sk_buff *skb;
+	struct sk_buff *skb = NULL;
 	struct carl9170_vif_info *cvif;
+	struct ieee80211_tx_info *txinfo;
 	__le32 *data, *old = NULL;
 	u32 word, off, addr, len;
 	int i = 0, err = 0;
@@ -487,7 +488,13 @@ found:
 
 	if (!skb) {
 		err = -ENOMEM;
-		goto out_unlock;
+		goto err_free;
+	}
+
+	txinfo = IEEE80211_SKB_CB(skb);
+	if (txinfo->control.rates[0].flags & IEEE80211_TX_RC_MCS) {
+		err = -EINVAL;
+		goto err_free;
 	}
 
 	spin_lock_bh(&ar->beacon_lock);
@@ -504,11 +511,8 @@ found:
 			wiphy_err(ar->hw->wiphy, "beacon does not "
 				  "fit into device memory!\n");
 		}
-
-		spin_unlock_bh(&ar->beacon_lock);
-		dev_kfree_skb_any(skb);
 		err = -EINVAL;
-		goto out_unlock;
+		goto err_unlock;
 	}
 
 	if (len > AR9170_MAC_BCN_LENGTH_MAX) {
@@ -518,22 +522,22 @@ found:
 				 AR9170_MAC_BCN_LENGTH_MAX, len);
 		}
 
-		spin_unlock_bh(&ar->beacon_lock);
-		dev_kfree_skb_any(skb);
 		err = -EMSGSIZE;
-		goto out_unlock;
+		goto err_unlock;
 	}
 
-	carl9170_async_regwrite_begin(ar);
+	i = txinfo->control.rates[0].idx;
+	if (txinfo->band != IEEE80211_BAND_2GHZ)
+		i += 4;
 
-	/* XXX: use skb->cb info */
-	if (ar->hw->conf.channel->band == IEEE80211_BAND_2GHZ) {
-		carl9170_async_regwrite(AR9170_MAC_REG_BCN_PLCP,
-				((skb->len + FCS_LEN) << (3 + 16)) + 0x0400);
-	} else {
-		carl9170_async_regwrite(AR9170_MAC_REG_BCN_PLCP,
-				((skb->len + FCS_LEN) << 16) + 0x001b);
-	}
+	word = __carl9170_ratetable[i].hw_value & 0xf;
+	if (i < 4)
+		word |= ((skb->len + FCS_LEN) << (3 + 16)) + 0x0400;
+	else
+		word |= ((skb->len + FCS_LEN) << 16) + 0x0010;
+
+	carl9170_async_regwrite_begin(ar);
+	carl9170_async_regwrite(AR9170_MAC_REG_BCN_PLCP, word);
 
 	for (i = 0; i < DIV_ROUND_UP(skb->len, 4); i++) {
 		/*
@@ -557,7 +561,7 @@ found:
 		cvif->beacon = skb;
 	spin_unlock_bh(&ar->beacon_lock);
 	if (err)
-		goto out_unlock;
+		goto err_free;
 
 	if (submit) {
 		err = carl9170_bcn_ctrl(ar, cvif->id,
@@ -565,10 +569,18 @@ found:
 					addr, skb->len + FCS_LEN);
 
 		if (err)
-			goto out_unlock;
+			goto err_free;
 	}
 out_unlock:
 	rcu_read_unlock();
+	return 0;
+
+err_unlock:
+	spin_unlock_bh(&ar->beacon_lock);
+
+err_free:
+	rcu_read_unlock();
+	dev_kfree_skb_any(skb);
 	return err;
 }
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/carl9170/main.c linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/carl9170/main.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/carl9170/main.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/carl9170/main.c	2011-03-14 21:20:32.000000000 -0400
@@ -428,6 +428,7 @@ static void carl9170_cancel_worker(struc
 	cancel_delayed_work_sync(&ar->led_work);
 #endif /* CONFIG_CARL9170_LEDS */
 	cancel_work_sync(&ar->ps_work);
+	cancel_work_sync(&ar->ping_work);
 	cancel_work_sync(&ar->ampdu_work);
 }
 
@@ -533,6 +534,21 @@ void carl9170_restart(struct ar9170 *ar,
 	 */
 }
 
+static void carl9170_ping_work(struct work_struct *work)
+{
+	struct ar9170 *ar = container_of(work, struct ar9170, ping_work);
+	int err;
+
+	if (!IS_STARTED(ar))
+		return;
+
+	mutex_lock(&ar->mutex);
+	err = carl9170_echo_test(ar, 0xdeadbeef);
+	if (err)
+		carl9170_restart(ar, CARL9170_RR_UNRESPONSIVE_DEVICE);
+	mutex_unlock(&ar->mutex);
+}
+
 static int carl9170_init_interface(struct ar9170 *ar,
 				   struct ieee80211_vif *vif)
 {
@@ -1614,6 +1630,7 @@ void *carl9170_alloc(size_t priv_size)
 		skb_queue_head_init(&ar->tx_pending[i]);
 	}
 	INIT_WORK(&ar->ps_work, carl9170_ps_work);
+	INIT_WORK(&ar->ping_work, carl9170_ping_work);
 	INIT_WORK(&ar->restart_work, carl9170_restart_work);
 	INIT_WORK(&ar->ampdu_work, carl9170_ampdu_work);
 	INIT_DELAYED_WORK(&ar->tx_janitor, carl9170_tx_janitor);
@@ -1829,7 +1846,7 @@ int carl9170_register(struct ar9170 *ar)
 	err = carl9170_led_register(ar);
 	if (err)
 		goto err_unreg;
-#endif /* CONFIG_CAR9L170_LEDS */
+#endif /* CONFIG_CARL9170_LEDS */
 
 #ifdef CONFIG_CARL9170_WPC
 	err = carl9170_register_wps_button(ar);
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/carl9170/phy.c linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/carl9170/phy.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/carl9170/phy.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/carl9170/phy.c	2011-03-14 21:20:32.000000000 -0400
@@ -1029,8 +1029,6 @@ static int carl9170_init_rf_bank4_pwr(st
 	if (err)
 		return err;
 
-	msleep(20);
-
 	return 0;
 }
 
@@ -1554,15 +1552,6 @@ static int carl9170_set_power_cal(struct
 	return carl9170_regwrite_result();
 }
 
-/* TODO: replace this with sign_extend32(noise, 8) */
-static int carl9170_calc_noise_dbm(u32 raw_noise)
-{
-	if (raw_noise & 0x100)
-		return ~0x1ff | raw_noise;
-	else
-		return raw_noise;
-}
-
 int carl9170_get_noisefloor(struct ar9170 *ar)
 {
 	static const u32 phy_regs[] = {
@@ -1578,11 +1567,11 @@ int carl9170_get_noisefloor(struct ar917
 		return err;
 
 	for (i = 0; i < 2; i++) {
-		ar->noise[i] = carl9170_calc_noise_dbm(
-			(phy_res[i] >> 19) & 0x1ff);
+		ar->noise[i] = sign_extend32(GET_VAL(
+			AR9170_PHY_CCA_MIN_PWR, phy_res[i]), 8);
 
-		ar->noise[i + 2] = carl9170_calc_noise_dbm(
-			(phy_res[i + 2] >> 23) & 0x1ff);
+		ar->noise[i + 2] = sign_extend32(GET_VAL(
+			AR9170_PHY_EXT_CCA_MIN_PWR, phy_res[i + 2]), 8);
 	}
 
 	return 0;
@@ -1669,12 +1658,6 @@ int carl9170_set_channel(struct ar9170 *
 			return err;
 
 		cmd = CARL9170_CMD_RF_INIT;
-
-		msleep(100);
-
-		err = carl9170_echo_test(ar, 0xaabbccdd);
-		if (err)
-			return err;
 	} else {
 		cmd = CARL9170_CMD_FREQUENCY;
 	}
@@ -1685,6 +1668,8 @@ int carl9170_set_channel(struct ar9170 *
 
 	err = carl9170_write_reg(ar, AR9170_PHY_REG_HEAVY_CLIP_ENABLE,
 				 0x200);
+	if (err)
+		return err;
 
 	err = carl9170_init_rf_bank4_pwr(ar,
 		channel->band == IEEE80211_BAND_5GHZ,
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/carl9170/phy.h linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/carl9170/phy.h
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/carl9170/phy.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/carl9170/phy.h	2011-03-14 21:20:32.000000000 -0400
@@ -139,8 +139,8 @@
 #define		AR9170_PHY_AGC_CONTROL_NO_UPDATE_NF	0x00020000
 
 #define	AR9170_PHY_REG_CCA			(AR9170_PHY_REG_BASE + 0x0064)
-#define		AR9170_PHY_CCA_MINCCA_PWR		0x0ff80000
-#define		AR9170_PHY_CCA_MINCCA_PWR_S		19
+#define		AR9170_PHY_CCA_MIN_PWR			0x0ff80000
+#define		AR9170_PHY_CCA_MIN_PWR_S		19
 #define		AR9170_PHY_CCA_THRESH62			0x0007f000
 #define		AR9170_PHY_CCA_THRESH62_S		12
 
@@ -338,8 +338,8 @@
 #define		AR9170_PHY_EXT_CCA_CYCPWR_THR1_S	9
 #define		AR9170_PHY_EXT_CCA_THRESH62		0x007f0000
 #define		AR9170_PHY_EXT_CCA_THRESH62_S		16
-#define		AR9170_PHY_EXT_MINCCA_PWR		0xff800000
-#define		AR9170_PHY_EXT_MINCCA_PWR_S		23
+#define		AR9170_PHY_EXT_CCA_MIN_PWR		0xff800000
+#define		AR9170_PHY_EXT_CCA_MIN_PWR_S		23
 
 #define	AR9170_PHY_REG_SFCORR_EXT		(AR9170_PHY_REG_BASE + 0x01c0)
 #define		AR9170_PHY_SFCORR_EXT_M1_THRESH		0x0000007f
@@ -546,19 +546,19 @@
 #define		AR9170_PHY_FORCE_XPA_CFG_S		0
 
 #define	AR9170_PHY_REG_CH1_CCA			(AR9170_PHY_REG_BASE + 0x1064)
-#define		AR9170_PHY_CH1_MINCCA_PWR		0x0ff80000
-#define		AR9170_PHY_CH1_MINCCA_PWR_S		19
+#define		AR9170_PHY_CH1_CCA_MIN_PWR		0x0ff80000
+#define		AR9170_PHY_CH1_CCA_MIN_PWR_S		19
 
 #define	AR9170_PHY_REG_CH2_CCA			(AR9170_PHY_REG_BASE + 0x2064)
-#define		AR9170_PHY_CH2_MINCCA_PWR		0x0ff80000
-#define		AR9170_PHY_CH2_MINCCA_PWR_S		19
+#define		AR9170_PHY_CH2_CCA_MIN_PWR		0x0ff80000
+#define		AR9170_PHY_CH2_CCA_MIN_PWR_S		19
 
 #define	AR9170_PHY_REG_CH1_EXT_CCA		(AR9170_PHY_REG_BASE + 0x11bc)
-#define		AR9170_PHY_CH1_EXT_MINCCA_PWR		0xff800000
-#define		AR9170_PHY_CH1_EXT_MINCCA_PWR_S		23
+#define		AR9170_PHY_CH1_EXT_CCA_MIN_PWR		0xff800000
+#define		AR9170_PHY_CH1_EXT_CCA_MIN_PWR_S	23
 
 #define	AR9170_PHY_REG_CH2_EXT_CCA		(AR9170_PHY_REG_BASE + 0x21bc)
-#define		AR9170_PHY_CH2_EXT_MINCCA_PWR		0xff800000
-#define		AR9170_PHY_CH2_EXT_MINCCA_PWR_S		23
+#define		AR9170_PHY_CH2_EXT_CCA_MIN_PWR		0xff800000
+#define		AR9170_PHY_CH2_EXT_CCA_MIN_PWR_S	23
 
 #endif	/* __CARL9170_SHARED_PHY_H */
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/carl9170/rx.c linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/carl9170/rx.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/carl9170/rx.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/carl9170/rx.c	2011-03-14 21:20:32.000000000 -0400
@@ -564,7 +564,7 @@ static void carl9170_ps_beacon(struct ar
 	cam = ieee80211_check_tim(tim_ie, tim_len, ar->common.curaid);
 
 	/* 2. Maybe the AP wants to send multicast/broadcast data? */
-	cam = !!(tim_ie->bitmap_ctrl & 0x01);
+	cam |= !!(tim_ie->bitmap_ctrl & 0x01);
 
 	if (!cam) {
 		/* back to low-power land. */
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/carl9170/tx.c linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/carl9170/tx.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/carl9170/tx.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/carl9170/tx.c	2011-03-14 21:20:32.000000000 -0400
@@ -242,9 +242,11 @@ static void carl9170_tx_release(struct k
 			ar->tx_ampdu_schedule = true;
 
 		if (txinfo->flags & IEEE80211_TX_STAT_AMPDU) {
-			txinfo->status.ampdu_len = txinfo->pad[0];
-			txinfo->status.ampdu_ack_len = txinfo->pad[1];
-			txinfo->pad[0] = txinfo->pad[1] = 0;
+			struct _carl9170_tx_superframe *super;
+
+			super = (void *)skb->data;
+			txinfo->status.ampdu_len = super->s.rix;
+			txinfo->status.ampdu_ack_len = super->s.cnt;
 		} else if (txinfo->flags & IEEE80211_TX_STAT_ACK) {
 			/*
 			 * drop redundant tx_status reports:
@@ -337,7 +339,8 @@ static void carl9170_tx_status_process_a
 	u8 tid;
 
 	if (!(txinfo->flags & IEEE80211_TX_CTL_AMPDU) ||
-	    txinfo->flags & IEEE80211_TX_CTL_INJECTED)
+	    txinfo->flags & IEEE80211_TX_CTL_INJECTED ||
+	   (!(super->f.mac_control & cpu_to_le16(AR9170_TX_MAC_AGGR))))
 		return;
 
 	tx_info = IEEE80211_SKB_CB(skb);
@@ -389,8 +392,8 @@ static void carl9170_tx_status_process_a
 		sta_info->stats[tid].ampdu_ack_len++;
 
 	if (super->f.mac_control & cpu_to_le16(AR9170_TX_MAC_IMM_BA)) {
-		txinfo->pad[0] = sta_info->stats[tid].ampdu_len;
-		txinfo->pad[1] = sta_info->stats[tid].ampdu_ack_len;
+		super->s.rix = sta_info->stats[tid].ampdu_len;
+		super->s.cnt = sta_info->stats[tid].ampdu_ack_len;
 		txinfo->flags |= IEEE80211_TX_STAT_AMPDU;
 		sta_info->stats[tid].clear = true;
 	}
@@ -524,6 +527,59 @@ next:
 	}
 }
 
+static void carl9170_tx_ampdu_timeout(struct ar9170 *ar)
+{
+	struct carl9170_sta_tid *iter;
+	struct sk_buff *skb;
+	struct ieee80211_tx_info *txinfo;
+	struct carl9170_tx_info *arinfo;
+	struct _carl9170_tx_superframe *super;
+	struct ieee80211_sta *sta;
+	struct ieee80211_vif *vif;
+	struct ieee80211_hdr *hdr;
+	unsigned int vif_id;
+
+	rcu_read_lock();
+	list_for_each_entry_rcu(iter, &ar->tx_ampdu_list, list) {
+		if (iter->state < CARL9170_TID_STATE_IDLE)
+			continue;
+
+		spin_lock_bh(&iter->lock);
+		skb = skb_peek(&iter->queue);
+		if (!skb)
+			goto unlock;
+
+		txinfo = IEEE80211_SKB_CB(skb);
+		arinfo = (void *)txinfo->rate_driver_data;
+		if (time_is_after_jiffies(arinfo->timeout +
+		    msecs_to_jiffies(CARL9170_QUEUE_TIMEOUT)))
+			goto unlock;
+
+		super = (void *) skb->data;
+		hdr = (void *) super->frame_data;
+
+		vif_id = (super->s.misc & CARL9170_TX_SUPER_MISC_VIF_ID) >>
+			 CARL9170_TX_SUPER_MISC_VIF_ID_S;
+
+		if (WARN_ON(vif_id >= AR9170_MAX_VIRTUAL_MAC))
+			goto unlock;
+
+		vif = rcu_dereference(ar->vif_priv[vif_id].vif);
+		if (WARN_ON(!vif))
+			goto unlock;
+
+		sta = ieee80211_find_sta(vif, hdr->addr1);
+		if (WARN_ON(!sta))
+			goto unlock;
+
+		ieee80211_stop_tx_ba_session(sta, iter->tid);
+unlock:
+		spin_unlock_bh(&iter->lock);
+
+	}
+	rcu_read_unlock();
+}
+
 void carl9170_tx_janitor(struct work_struct *work)
 {
 	struct ar9170 *ar = container_of(work, struct ar9170,
@@ -534,6 +590,7 @@ void carl9170_tx_janitor(struct work_str
 	ar->tx_janitor_last_run = jiffies;
 
 	carl9170_check_queue_stop_timeout(ar);
+	carl9170_tx_ampdu_timeout(ar);
 
 	if (!atomic_read(&ar->tx_total_queued))
 		return;
@@ -842,10 +899,8 @@ static int carl9170_tx_prepare(struct ar
 		if (unlikely(!sta || !cvif))
 			goto err_out;
 
-		factor = min_t(unsigned int, 1u,
-			 info->control.sta->ht_cap.ampdu_factor);
-
-		density = info->control.sta->ht_cap.ampdu_density;
+		factor = min_t(unsigned int, 1u, sta->ht_cap.ampdu_factor);
+		density = sta->ht_cap.ampdu_density;
 
 		if (density) {
 			/*
@@ -1206,6 +1261,7 @@ static void carl9170_tx(struct ar9170 *a
 static bool carl9170_tx_ampdu_queue(struct ar9170 *ar,
 	struct ieee80211_sta *sta, struct sk_buff *skb)
 {
+	struct _carl9170_tx_superframe *super = (void *) skb->data;
 	struct carl9170_sta_info *sta_info;
 	struct carl9170_sta_tid *agg;
 	struct sk_buff *iter;
@@ -1274,6 +1330,7 @@ err_unlock:
 
 err_unlock_rcu:
 	rcu_read_unlock();
+	super->f.mac_control &= ~cpu_to_le16(AR9170_TX_MAC_AGGR);
 	carl9170_tx_status(ar, skb, false);
 	ar->tx_dropped++;
 	return false;
@@ -1302,9 +1359,6 @@ int carl9170_op_tx(struct ieee80211_hw *
 	 */
 
 	if (info->flags & IEEE80211_TX_CTL_AMPDU) {
-		if (WARN_ON_ONCE(!sta))
-			goto err_free;
-
 		run = carl9170_tx_ampdu_queue(ar, sta, skb);
 		if (run)
 			carl9170_tx_ampdu(ar);
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/carl9170/usb.c linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/carl9170/usb.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/carl9170/usb.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/carl9170/usb.c	2011-03-14 21:20:32.000000000 -0400
@@ -118,6 +118,8 @@ static struct usb_device_id carl9170_usb
 	{ USB_DEVICE(0x057c, 0x8402) },
 	/* Qwest/Actiontec 802AIN Wireless N USB Network Adapter */
 	{ USB_DEVICE(0x1668, 0x1200) },
+	/* Airlive X.USB a/b/g/n */
+	{ USB_DEVICE(0x1b75, 0x9170) },
 
 	/* terminate */
 	{}
@@ -160,8 +162,7 @@ err_acc:
 
 static void carl9170_usb_tx_data_complete(struct urb *urb)
 {
-	struct ar9170 *ar = (struct ar9170 *)
-	      usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0));
+	struct ar9170 *ar = usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0));
 
 	if (WARN_ON_ONCE(!ar)) {
 		dev_kfree_skb_irq(urb->context);
@@ -433,7 +434,7 @@ static void carl9170_usb_rx_complete(str
 			 * device.
 			 */
 
-			carl9170_restart(ar, CARL9170_RR_SLOW_SYSTEM);
+			ieee80211_queue_work(ar->hw, &ar->ping_work);
 		}
 	} else {
 		/*
@@ -835,7 +836,7 @@ static int carl9170_usb_load_firmware(st
 	if (err)
 		goto err_out;
 
-	/* firmware restarts cmd counter */
+	/* now, start the command response counter */
 	ar->cmd_seq = -1;
 
 	return 0;
@@ -852,7 +853,12 @@ int carl9170_usb_restart(struct ar9170 *
 	if (ar->intf->condition != USB_INTERFACE_BOUND)
 		return 0;
 
-	/* Disable command response sequence counter. */
+	/*
+	 * Disable the command response sequence counter check.
+	 * We already know that the device/firmware is in a bad state.
+	 * So, no extra points are awarded to anyone who reminds the
+	 * driver about that.
+	 */
 	ar->cmd_seq = -2;
 
 	err = carl9170_reboot(ar);
@@ -904,6 +910,15 @@ static int carl9170_usb_init_device(stru
 {
 	int err;
 
+	/*
+	 * The carl9170 firmware let's the driver know when it's
+	 * ready for action. But we have to be prepared to gracefully
+	 * handle all spurious [flushed] messages after each (re-)boot.
+	 * Thus the command response counter remains disabled until it
+	 * can be safely synchronized.
+	 */
+	ar->cmd_seq = -2;
+
 	err = carl9170_usb_send_rx_irq_urb(ar);
 	if (err)
 		goto err_out;
@@ -912,14 +927,21 @@ static int carl9170_usb_init_device(stru
 	if (err)
 		goto err_unrx;
 
+	err = carl9170_usb_open(ar);
+	if (err)
+		goto err_unrx;
+
 	mutex_lock(&ar->mutex);
 	err = carl9170_usb_load_firmware(ar);
 	mutex_unlock(&ar->mutex);
 	if (err)
-		goto err_unrx;
+		goto err_stop;
 
 	return 0;
 
+err_stop:
+	carl9170_usb_stop(ar);
+
 err_unrx:
 	carl9170_usb_cancel_urbs(ar);
 
@@ -965,10 +987,6 @@ static void carl9170_usb_firmware_finish
 	if (err)
 		goto err_freefw;
 
-	err = carl9170_usb_open(ar);
-	if (err)
-		goto err_unrx;
-
 	err = carl9170_register(ar);
 
 	carl9170_usb_stop(ar);
@@ -1044,7 +1062,6 @@ static int carl9170_usb_probe(struct usb
 	atomic_set(&ar->rx_work_urbs, 0);
 	atomic_set(&ar->rx_anch_urbs, 0);
 	atomic_set(&ar->rx_pool_urbs, 0);
-	ar->cmd_seq = -2;
 
 	usb_get_dev(ar->udev);
 
@@ -1091,10 +1108,6 @@ static int carl9170_usb_suspend(struct u
 
 	carl9170_usb_cancel_urbs(ar);
 
-	/*
-	 * firmware automatically reboots for usb suspend.
-	 */
-
 	return 0;
 }
 
@@ -1107,12 +1120,20 @@ static int carl9170_usb_resume(struct us
 		return -ENODEV;
 
 	usb_unpoison_anchored_urbs(&ar->rx_anch);
+	carl9170_set_state(ar, CARL9170_STOPPED);
 
-	err = carl9170_usb_init_device(ar);
-	if (err)
-		goto err_unrx;
+	/*
+	 * The USB documentation demands that [for suspend] all traffic
+	 * to and from the device has to stop. This would be fine, but
+	 * there's a catch: the device[usb phy] does not come back.
+	 *
+	 * Upon resume the firmware will "kill" itself and the
+	 * boot-code sorts out the magic voodoo.
+	 * Not very nice, but there's not much what could go wrong.
+	 */
+	msleep(1100);
 
-	err = carl9170_usb_open(ar);
+	err = carl9170_usb_init_device(ar);
 	if (err)
 		goto err_unrx;
 
@@ -1134,6 +1155,7 @@ static struct usb_driver carl9170_driver
 #ifdef CONFIG_PM
 	.suspend = carl9170_usb_suspend,
 	.resume = carl9170_usb_resume,
+	.reset_resume = carl9170_usb_resume,
 #endif /* CONFIG_PM */
 };
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/carl9170/version.h linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/carl9170/version.h
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/carl9170/version.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/carl9170/version.h	2011-03-14 21:20:32.000000000 -0400
@@ -1,7 +1,7 @@
 #ifndef __CARL9170_SHARED_VERSION_H
 #define __CARL9170_SHARED_VERSION_H
 #define CARL9170FW_VERSION_YEAR 10
-#define CARL9170FW_VERSION_MONTH 9
-#define CARL9170FW_VERSION_DAY 28
-#define CARL9170FW_VERSION_GIT "1.8.8.3"
+#define CARL9170FW_VERSION_MONTH 10
+#define CARL9170FW_VERSION_DAY 29
+#define CARL9170FW_VERSION_GIT "1.9.0"
 #endif /* __CARL9170_SHARED_VERSION_H */
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/debug.c linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/debug.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/debug.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/debug.c	2011-03-14 21:20:32.000000000 -0400
@@ -15,21 +15,6 @@
  */
 
 #include "ath.h"
-#include "debug.h"
-
-void ath_print(struct ath_common *common, int dbg_mask, const char *fmt, ...)
-{
-	va_list args;
-
-	if (likely(!(common->debug_mask & dbg_mask)))
-		return;
-
-	va_start(args, fmt);
-	printk(KERN_DEBUG "ath: ");
-	vprintk(fmt, args);
-	va_end(args);
-}
-EXPORT_SYMBOL(ath_print);
 
 const char *ath_opmode_to_string(enum nl80211_iftype opmode)
 {
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/debug.h linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/debug.h
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/debug.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/debug.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,90 +0,0 @@
-/*
- * Copyright (c) 2008-2009 Atheros Communications Inc.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef ATH_DEBUG_H
-#define ATH_DEBUG_H
-
-#include "ath.h"
-
-/**
- * enum ath_debug_level - atheros wireless debug level
- *
- * @ATH_DBG_RESET: reset processing
- * @ATH_DBG_QUEUE: hardware queue management
- * @ATH_DBG_EEPROM: eeprom processing
- * @ATH_DBG_CALIBRATE: periodic calibration
- * @ATH_DBG_INTERRUPT: interrupt processing
- * @ATH_DBG_REGULATORY: regulatory processing
- * @ATH_DBG_ANI: adaptive noise immunitive processing
- * @ATH_DBG_XMIT: basic xmit operation
- * @ATH_DBG_BEACON: beacon handling
- * @ATH_DBG_CONFIG: configuration of the hardware
- * @ATH_DBG_FATAL: fatal errors, this is the default, DBG_DEFAULT
- * @ATH_DBG_PS: power save processing
- * @ATH_DBG_HWTIMER: hardware timer handling
- * @ATH_DBG_BTCOEX: bluetooth coexistance
- * @ATH_DBG_BSTUCK: stuck beacons
- * @ATH_DBG_ANY: enable all debugging
- *
- * The debug level is used to control the amount and type of debugging output
- * we want to see. Each driver has its own method for enabling debugging and
- * modifying debug level states -- but this is typically done through a
- * module parameter 'debug' along with a respective 'debug' debugfs file
- * entry.
- */
-enum ATH_DEBUG {
-	ATH_DBG_RESET		= 0x00000001,
-	ATH_DBG_QUEUE		= 0x00000002,
-	ATH_DBG_EEPROM		= 0x00000004,
-	ATH_DBG_CALIBRATE	= 0x00000008,
-	ATH_DBG_INTERRUPT	= 0x00000010,
-	ATH_DBG_REGULATORY	= 0x00000020,
-	ATH_DBG_ANI		= 0x00000040,
-	ATH_DBG_XMIT		= 0x00000080,
-	ATH_DBG_BEACON		= 0x00000100,
-	ATH_DBG_CONFIG		= 0x00000200,
-	ATH_DBG_FATAL		= 0x00000400,
-	ATH_DBG_PS		= 0x00000800,
-	ATH_DBG_HWTIMER		= 0x00001000,
-	ATH_DBG_BTCOEX		= 0x00002000,
-	ATH_DBG_WMI		= 0x00004000,
-	ATH_DBG_BSTUCK		= 0x00008000,
-	ATH_DBG_ANY		= 0xffffffff
-};
-
-#define ATH_DBG_DEFAULT (ATH_DBG_FATAL)
-
-#ifdef CONFIG_ATH_DEBUG
-void ath_print(struct ath_common *common, int dbg_mask, const char *fmt, ...)
-	__attribute__ ((format (printf, 3, 4)));
-#else
-static inline void __attribute__ ((format (printf, 3, 4)))
-ath_print(struct ath_common *common, int dbg_mask, const char *fmt, ...)
-{
-}
-#endif /* CONFIG_ATH_DEBUG */
-
-/** Returns string describing opmode, or NULL if unknown mode. */
-#ifdef CONFIG_ATH_DEBUG
-const char *ath_opmode_to_string(enum nl80211_iftype opmode);
-#else
-static inline const char *ath_opmode_to_string(enum nl80211_iftype opmode)
-{
-	return "UNKNOWN";
-}
-#endif
-
-#endif /* ATH_DEBUG_H */
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/key.c linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/key.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/key.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/key.c	2011-03-14 21:20:32.000000000 -0400
@@ -20,7 +20,6 @@
 
 #include "ath.h"
 #include "reg.h"
-#include "debug.h"
 
 #define REG_READ			(common->ops->read)
 #define REG_WRITE(_ah, _reg, _val)	(common->ops->write)(_ah, _val, _reg)
@@ -37,8 +36,7 @@ bool ath_hw_keyreset(struct ath_common *
 	void *ah = common->ah;
 
 	if (entry >= common->keymax) {
-		ath_print(common, ATH_DBG_FATAL,
-			  "keychache entry %u out of range\n", entry);
+		ath_err(common, "keycache entry %u out of range\n", entry);
 		return false;
 	}
 
@@ -60,6 +58,8 @@ bool ath_hw_keyreset(struct ath_common *
 		REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), 0);
 		REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), 0);
 		REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), 0);
+		if (common->crypt_caps & ATH_CRYPT_CAP_MIC_COMBINED)
+			REG_WRITE(ah, AR_KEYTABLE_KEY4(micentry), 0);
 
 	}
 
@@ -67,15 +67,15 @@ bool ath_hw_keyreset(struct ath_common *
 }
 EXPORT_SYMBOL(ath_hw_keyreset);
 
-bool ath_hw_keysetmac(struct ath_common *common, u16 entry, const u8 *mac)
+static bool ath_hw_keysetmac(struct ath_common *common,
+			     u16 entry, const u8 *mac)
 {
 	u32 macHi, macLo;
 	u32 unicast_flag = AR_KEYTABLE_VALID;
 	void *ah = common->ah;
 
 	if (entry >= common->keymax) {
-		ath_print(common, ATH_DBG_FATAL,
-			  "keychache entry %u out of range\n", entry);
+		ath_err(common, "keycache entry %u out of range\n", entry);
 		return false;
 	}
 
@@ -107,17 +107,16 @@ bool ath_hw_keysetmac(struct ath_common
 	return true;
 }
 
-bool ath_hw_set_keycache_entry(struct ath_common *common, u16 entry,
-				 const struct ath_keyval *k,
-				 const u8 *mac)
+static bool ath_hw_set_keycache_entry(struct ath_common *common, u16 entry,
+				      const struct ath_keyval *k,
+				      const u8 *mac)
 {
 	void *ah = common->ah;
 	u32 key0, key1, key2, key3, key4;
 	u32 keyType;
 
 	if (entry >= common->keymax) {
-		ath_print(common, ATH_DBG_FATAL,
-			  "keycache entry %u out of range\n", entry);
+		ath_err(common, "keycache entry %u out of range\n", entry);
 		return false;
 	}
 
@@ -127,8 +126,8 @@ bool ath_hw_set_keycache_entry(struct at
 		break;
 	case ATH_CIPHER_AES_CCM:
 		if (!(common->crypt_caps & ATH_CRYPT_CAP_CIPHER_AESCCM)) {
-			ath_print(common, ATH_DBG_ANY,
-				  "AES-CCM not supported by this mac rev\n");
+			ath_dbg(common, ATH_DBG_ANY,
+				"AES-CCM not supported by this mac rev\n");
 			return false;
 		}
 		keyType = AR_KEYTABLE_TYPE_CCM;
@@ -136,15 +135,15 @@ bool ath_hw_set_keycache_entry(struct at
 	case ATH_CIPHER_TKIP:
 		keyType = AR_KEYTABLE_TYPE_TKIP;
 		if (entry + 64 >= common->keymax) {
-			ath_print(common, ATH_DBG_ANY,
-				  "entry %u inappropriate for TKIP\n", entry);
+			ath_dbg(common, ATH_DBG_ANY,
+				"entry %u inappropriate for TKIP\n", entry);
 			return false;
 		}
 		break;
 	case ATH_CIPHER_WEP:
 		if (k->kv_len < WLAN_KEY_LEN_WEP40) {
-			ath_print(common, ATH_DBG_ANY,
-				  "WEP key length %u too small\n", k->kv_len);
+			ath_dbg(common, ATH_DBG_ANY,
+				"WEP key length %u too small\n", k->kv_len);
 			return false;
 		}
 		if (k->kv_len <= WLAN_KEY_LEN_WEP40)
@@ -158,8 +157,7 @@ bool ath_hw_set_keycache_entry(struct at
 		keyType = AR_KEYTABLE_TYPE_CLR;
 		break;
 	default:
-		ath_print(common, ATH_DBG_FATAL,
-			  "cipher %u not supported\n", k->kv_type);
+		ath_err(common, "cipher %u not supported\n", k->kv_type);
 		return false;
 	}
 
@@ -340,8 +338,7 @@ static int ath_setkey_tkip(struct ath_co
 	memcpy(hk->kv_mic, key_txmic, sizeof(hk->kv_mic));
 	if (!ath_hw_set_keycache_entry(common, keyix, hk, NULL)) {
 		/* TX MIC entry failed. No need to proceed further */
-		ath_print(common, ATH_DBG_FATAL,
-			  "Setting TX MIC Key Failed\n");
+		ath_err(common, "Setting TX MIC Key Failed\n");
 		return 0;
 	}
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/main.c linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/main.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/main.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/main.c	2011-03-14 21:20:32.000000000 -0400
@@ -56,3 +56,23 @@ struct sk_buff *ath_rxbuf_alloc(struct a
 	return skb;
 }
 EXPORT_SYMBOL(ath_rxbuf_alloc);
+
+int ath_printk(const char *level, struct ath_common *common,
+	       const char *fmt, ...)
+{
+	struct va_format vaf;
+	va_list args;
+	int rtn;
+
+	va_start(args, fmt);
+
+	vaf.fmt = fmt;
+	vaf.va = &args;
+
+	rtn = printk("%sath: %pV", level, &vaf);
+
+	va_end(args);
+
+	return rtn;
+}
+EXPORT_SYMBOL(ath_printk);
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/regd.c linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/regd.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ath/regd.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ath/regd.c	2011-03-14 21:20:32.000000000 -0400
@@ -342,6 +342,14 @@ int ath_reg_notifier_apply(struct wiphy
 	/* We always apply this */
 	ath_reg_apply_radar_flags(wiphy);
 
+	/*
+	 * This would happen when we have sent a custom regulatory request
+	 * a world regulatory domain and the scheduler hasn't yet processed
+	 * any pending requests in the queue.
+	 */
+	if (!request)
+		return 0;
+
 	switch (request->initiator) {
 	case NL80211_REGDOM_SET_BY_DRIVER:
 	case NL80211_REGDOM_SET_BY_CORE:
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/atmel.c linux-libre-2.6.38-gnu1/drivers/net/wireless/atmel.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/atmel.c	2013-05-03 03:59:48.000000000 -0400
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/atmel.c	2013-05-03 02:00:05.000000000 -0400
@@ -1146,7 +1146,7 @@ static irqreturn_t service_interrupt(int
 	struct atmel_private *priv = netdev_priv(dev);
 	u8 isr;
 	int i = -1;
-	static u8 irq_order[] = {
+	static const u8 irq_order[] = {
 		ISR_OUT_OF_RANGE,
 		ISR_RxCOMPLETE,
 		ISR_TxCOMPLETE,
@@ -3756,7 +3756,9 @@ static int probe_atmel_card(struct net_d
 
 	if (rc) {
 		if (dev->dev_addr[0] == 0xFF) {
-			u8 default_mac[] = {0x00, 0x04, 0x25, 0x00, 0x00, 0x00};
+			static const u8 default_mac[] = {
+				0x00, 0x04, 0x25, 0x00, 0x00, 0x00
+			};
 			printk(KERN_ALERT "%s: *** Invalid MAC address. UPGRADE Firmware ****\n", dev->name);
 			memcpy(dev->dev_addr, default_mac, 6);
 		}
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/b43/b43.h linux-libre-2.6.38-gnu1/drivers/net/wireless/b43/b43.h
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/b43/b43.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/b43/b43.h	2011-03-14 21:20:32.000000000 -0400
@@ -153,6 +153,19 @@
 #define B43_BFH_FEM_BT			0x0040	/* has FEM and switch to share antenna
 						 * with bluetooth */
 
+/* SPROM boardflags2_lo values */
+#define B43_BFL2_RXBB_INT_REG_DIS	0x0001	/* external RX BB regulator present */
+#define B43_BFL2_APLL_WAR		0x0002	/* alternative A-band PLL settings implemented */
+#define B43_BFL2_TXPWRCTRL_EN 		0x0004	/* permits enabling TX Power Control */
+#define B43_BFL2_2X4_DIV		0x0008	/* 2x4 diversity switch */
+#define B43_BFL2_5G_PWRGAIN		0x0010	/* supports 5G band power gain */
+#define B43_BFL2_PCIEWAR_OVR		0x0020	/* overrides ASPM and Clkreq settings */
+#define B43_BFL2_CAESERS_BRD		0x0040	/* is Caesers board (unused) */
+#define B43_BFL2_BTC3WIRE		0x0080	/* used 3-wire bluetooth coexist */
+#define B43_BFL2_SKWRKFEM_BRD		0x0100	/* 4321mcm93 uses Skyworks FEM */
+#define B43_BFL2_SPUR_WAR		0x0200	/* has a workaround for clock-harmonic spurs */
+#define B43_BFL2_GPLL_WAR		0x0400	/* altenative G-band PLL settings implemented */
+
 /* GPIO register offset, in both ChipCommon and PCI core. */
 #define B43_GPIO_CONTROL		0x6c
 
@@ -403,10 +416,10 @@ enum {
 
 /* 802.11 core specific TM State Low (SSB_TMSLOW) flags */
 #define B43_TMSLOW_GMODE		0x20000000	/* G Mode Enable */
-#define B43_TMSLOW_PHYCLKSPEED		0x00C00000	/* PHY clock speed mask (N-PHY only) */
-#define  B43_TMSLOW_PHYCLKSPEED_40MHZ	0x00000000	/* 40 MHz PHY */
-#define  B43_TMSLOW_PHYCLKSPEED_80MHZ	0x00400000	/* 80 MHz PHY */
-#define  B43_TMSLOW_PHYCLKSPEED_160MHZ	0x00800000	/* 160 MHz PHY */
+#define B43_TMSLOW_PHY_BANDWIDTH	0x00C00000	/* PHY band width and clock speed mask (N-PHY only) */
+#define  B43_TMSLOW_PHY_BANDWIDTH_10MHZ	0x00000000	/* 10 MHz bandwidth, 40 MHz PHY */
+#define  B43_TMSLOW_PHY_BANDWIDTH_20MHZ	0x00400000	/* 20 MHz bandwidth, 80 MHz PHY */
+#define  B43_TMSLOW_PHY_BANDWIDTH_40MHZ	0x00800000	/* 40 MHz bandwidth, 160 MHz PHY */
 #define B43_TMSLOW_PLLREFSEL		0x00200000	/* PLL Frequency Reference Select (rev >= 5) */
 #define B43_TMSLOW_MACPHYCLKEN		0x00100000	/* MAC PHY Clock Control Enable (rev >= 5) */
 #define B43_TMSLOW_PHYRESET		0x00080000	/* PHY Reset */
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/b43/dma.c linux-libre-2.6.38-gnu1/drivers/net/wireless/b43/dma.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/b43/dma.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/b43/dma.c	2011-03-14 21:20:32.000000000 -0400
@@ -415,11 +415,6 @@ static int alloc_ringmemory(struct b43_d
 
 static void free_ringmemory(struct b43_dmaring *ring)
 {
-	gfp_t flags = GFP_KERNEL;
-
-	if (ring->type == B43_DMA_64BIT)
-		flags |= GFP_DMA;
-
 	dma_free_coherent(ring->dev->dev->dma_dev, B43_DMA_RINGMEMSIZE,
 			  ring->descbase, ring->dmabase);
 }
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/b43/Kconfig linux-libre-2.6.38-gnu1/drivers/net/wireless/b43/Kconfig
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/b43/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/b43/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -86,15 +86,16 @@ config B43_PIO
 	select SSB_BLOCKIO
 	default y
 
-config B43_NPHY
-	bool "Pre IEEE 802.11n support (BROKEN)"
-	depends on B43 && EXPERIMENTAL && BROKEN
+config B43_PHY_N
+	bool "Support for 802.11n (N-PHY) devices (EXPERIMENTAL)"
+	depends on B43 && EXPERIMENTAL
 	---help---
-	  Support for the IEEE 802.11n draft.
+	  Support for the N-PHY.
 
-	  THIS IS BROKEN AND DOES NOT WORK YET.
+	  This enables support for devices with N-PHY revision up to 2.
 
-	  SAY N.
+	  Say N if you expect high stability and performance. Saying Y will not
+	  affect other devices support and may provide support for basic needs.
 
 config B43_PHY_LP
 	bool "Support for low-power (LP-PHY) devices (EXPERIMENTAL)"
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/b43/main.c linux-libre-2.6.38-gnu1/drivers/net/wireless/b43/main.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/b43/main.c	2013-05-03 03:59:55.000000000 -0400
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/b43/main.c	2013-05-03 02:00:13.000000000 -0400
@@ -316,59 +316,83 @@ static int b43_ratelimit(struct b43_wl *
 
 void b43info(struct b43_wl *wl, const char *fmt, ...)
 {
+	struct va_format vaf;
 	va_list args;
 
 	if (b43_modparam_verbose < B43_VERBOSITY_INFO)
 		return;
 	if (!b43_ratelimit(wl))
 		return;
+
 	va_start(args, fmt);
-	printk(KERN_INFO "b43-%s: ",
-	       (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan");
-	vprintk(fmt, args);
+
+	vaf.fmt = fmt;
+	vaf.va = &args;
+
+	printk(KERN_INFO "b43-%s: %pV",
+	       (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan", &vaf);
+
 	va_end(args);
 }
 
 void b43err(struct b43_wl *wl, const char *fmt, ...)
 {
+	struct va_format vaf;
 	va_list args;
 
 	if (b43_modparam_verbose < B43_VERBOSITY_ERROR)
 		return;
 	if (!b43_ratelimit(wl))
 		return;
+
 	va_start(args, fmt);
-	printk(KERN_ERR "b43-%s ERROR: ",
-	       (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan");
-	vprintk(fmt, args);
+
+	vaf.fmt = fmt;
+	vaf.va = &args;
+
+	printk(KERN_ERR "b43-%s ERROR: %pV",
+	       (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan", &vaf);
+
 	va_end(args);
 }
 
 void b43warn(struct b43_wl *wl, const char *fmt, ...)
 {
+	struct va_format vaf;
 	va_list args;
 
 	if (b43_modparam_verbose < B43_VERBOSITY_WARN)
 		return;
 	if (!b43_ratelimit(wl))
 		return;
+
 	va_start(args, fmt);
-	printk(KERN_WARNING "b43-%s warning: ",
-	       (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan");
-	vprintk(fmt, args);
+
+	vaf.fmt = fmt;
+	vaf.va = &args;
+
+	printk(KERN_WARNING "b43-%s warning: %pV",
+	       (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan", &vaf);
+
 	va_end(args);
 }
 
 void b43dbg(struct b43_wl *wl, const char *fmt, ...)
 {
+	struct va_format vaf;
 	va_list args;
 
 	if (b43_modparam_verbose < B43_VERBOSITY_DEBUG)
 		return;
+
 	va_start(args, fmt);
-	printk(KERN_DEBUG "b43-%s debug: ",
-	       (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan");
-	vprintk(fmt, args);
+
+	vaf.fmt = fmt;
+	vaf.va = &args;
+
+	printk(KERN_DEBUG "b43-%s debug: %pV",
+	       (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan", &vaf);
+
 	va_end(args);
 }
 
@@ -1120,6 +1144,8 @@ void b43_wireless_core_reset(struct b43_
 
 	flags |= B43_TMSLOW_PHYCLKEN;
 	flags |= B43_TMSLOW_PHYRESET;
+	if (dev->phy.type == B43_PHYTYPE_N)
+		flags |= B43_TMSLOW_PHY_BANDWIDTH_20MHZ; /* Make 20 MHz def */
 	ssb_device_enable(dev->dev, flags);
 	msleep(2);		/* Wait for the PLL to turn on. */
 
@@ -2086,8 +2112,10 @@ static int b43_try_request_fw(struct b43
 		filename = "ucode13";
 	else if (rev == 14)
 		filename = "ucode14";
-	else if (rev >= 15)
+	else if (rev == 15)
 		filename = "ucode15";
+	else if ((rev >= 16) && (rev <= 20))
+		filename = "ucode16_mimo";
 	else
 		goto err_no_ucode;
 	err = b43_do_request_fw(ctx, filename, &fw->ucode);
@@ -2130,7 +2158,9 @@ static int b43_try_request_fw(struct b43
 			goto err_no_initvals;
 		break;
 	case B43_PHYTYPE_N:
-		if ((rev >= 11) && (rev <= 12))
+		if (rev >= 16)
+			filename = "n0initvals16";
+		else if ((rev >= 11) && (rev <= 12))
 			filename = "n0initvals11";
 		else
 			goto err_no_initvals;
@@ -2174,7 +2204,9 @@ static int b43_try_request_fw(struct b43
 			goto err_no_initvals;
 		break;
 	case B43_PHYTYPE_N:
-		if ((rev >= 11) && (rev <= 12))
+		if (rev >= 16)
+			filename = "n0bsinitvals16";
+		else if ((rev >= 11) && (rev <= 12))
 			filename = "n0bsinitvals11";
 		else
 			goto err_no_initvals;
@@ -4018,9 +4050,9 @@ static int b43_phy_versioning(struct b43
 		if (phy_rev > 9)
 			unsupported = 1;
 		break;
-#ifdef CONFIG_B43_NPHY
+#ifdef CONFIG_B43_PHY_N
 	case B43_PHYTYPE_N:
-		if (phy_rev > 4)
+		if (phy_rev > 9)
 			unsupported = 1;
 		break;
 #endif
@@ -5063,7 +5095,7 @@ static void b43_print_driverinfo(void)
 #ifdef CONFIG_B43_PCMCIA
 	feat_pcmcia = "M";
 #endif
-#ifdef CONFIG_B43_NPHY
+#ifdef CONFIG_B43_PHY_N
 	feat_nphy = "N";
 #endif
 #ifdef CONFIG_B43_LEDS
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/b43/Makefile linux-libre-2.6.38-gnu1/drivers/net/wireless/b43/Makefile
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/b43/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/b43/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -1,12 +1,12 @@
 b43-y				+= main.o
 b43-y				+= tables.o
-b43-$(CONFIG_B43_NPHY)		+= tables_nphy.o
-b43-$(CONFIG_B43_NPHY)		+= radio_2055.o
-b43-$(CONFIG_B43_NPHY)		+= radio_2056.o
+b43-$(CONFIG_B43_PHY_N)		+= tables_nphy.o
+b43-$(CONFIG_B43_PHY_N)		+= radio_2055.o
+b43-$(CONFIG_B43_PHY_N)		+= radio_2056.o
 b43-y				+= phy_common.o
 b43-y				+= phy_g.o
 b43-y				+= phy_a.o
-b43-$(CONFIG_B43_NPHY)		+= phy_n.o
+b43-$(CONFIG_B43_PHY_N)		+= phy_n.o
 b43-$(CONFIG_B43_PHY_LP)	+= phy_lp.o
 b43-$(CONFIG_B43_PHY_LP)	+= tables_lpphy.o
 b43-y				+= sysfs.o
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/b43/phy_common.c linux-libre-2.6.38-gnu1/drivers/net/wireless/b43/phy_common.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/b43/phy_common.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/b43/phy_common.c	2011-03-14 21:20:32.000000000 -0400
@@ -50,7 +50,7 @@ int b43_phy_allocate(struct b43_wldev *d
 		phy->ops = &b43_phyops_g;
 		break;
 	case B43_PHYTYPE_N:
-#ifdef CONFIG_B43_NPHY
+#ifdef CONFIG_B43_PHY_N
 		phy->ops = &b43_phyops_n;
 #endif
 		break;
@@ -231,6 +231,7 @@ void b43_radio_maskset(struct b43_wldev
 u16 b43_phy_read(struct b43_wldev *dev, u16 reg)
 {
 	assert_mac_suspended(dev);
+	dev->phy.writes_counter = 0;
 	return dev->phy.ops->phy_read(dev, reg);
 }
 
@@ -238,6 +239,10 @@ void b43_phy_write(struct b43_wldev *dev
 {
 	assert_mac_suspended(dev);
 	dev->phy.ops->phy_write(dev, reg, value);
+	if (++dev->phy.writes_counter == B43_MAX_WRITES_IN_ROW) {
+		b43_read16(dev, B43_MMIO_PHY_VER);
+		dev->phy.writes_counter = 0;
+	}
 }
 
 void b43_phy_copy(struct b43_wldev *dev, u16 destreg, u16 srcreg)
@@ -424,12 +429,21 @@ void b43_phyop_switch_analog_generic(str
 	b43_write16(dev, B43_MMIO_PHY0, on ? 0 : 0xF4);
 }
 
+
+bool b43_channel_type_is_40mhz(enum nl80211_channel_type channel_type)
+{
+	return (channel_type == NL80211_CHAN_HT40MINUS ||
+		channel_type == NL80211_CHAN_HT40PLUS);
+}
+
 /* http://bcm-v4.sipsolutions.net/802.11/PHY/Cordic */
 struct b43_c32 b43_cordic(int theta)
 {
-	u32 arctg[] = { 2949120, 1740967, 919879, 466945, 234379, 117304,
-		      58666, 29335, 14668, 7334, 3667, 1833, 917, 458,
-		      229, 115, 57, 29, };
+	static const u32 arctg[] = {
+		2949120, 1740967, 919879, 466945, 234379, 117304,
+		  58666,   29335,  14668,   7334,   3667,   1833,
+		    917,     458,    229,    115,     57,     29,
+	};
 	u8 i;
 	s32 tmp;
 	s8 signx = 1;
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/b43/phy_common.h linux-libre-2.6.38-gnu1/drivers/net/wireless/b43/phy_common.h
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/b43/phy_common.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/b43/phy_common.h	2011-03-14 21:20:32.000000000 -0400
@@ -39,6 +39,9 @@ struct b43_c32 { s32 i, q; };
 #define B43_PHYVER_TYPE_SHIFT		8
 #define B43_PHYVER_VERSION		0x00FF
 
+/* PHY writes need to be flushed if we reach limit */
+#define B43_MAX_WRITES_IN_ROW		24
+
 /**
  * enum b43_interference_mitigation - Interference Mitigation mode
  *
@@ -232,6 +235,9 @@ struct b43_phy {
 	/* PHY revision number. */
 	u8 rev;
 
+	/* Count writes since last read */
+	u8 writes_counter;
+
 	/* Radio versioning */
 	u16 radio_manuf;	/* Radio manufacturer */
 	u16 radio_ver;		/* Radio version */
@@ -430,6 +436,8 @@ int b43_phy_shm_tssi_read(struct b43_wld
  */
 void b43_phyop_switch_analog_generic(struct b43_wldev *dev, bool on);
 
+bool b43_channel_type_is_40mhz(enum nl80211_channel_type channel_type);
+
 struct b43_c32 b43_cordic(int theta);
 
 #endif /* LINUX_B43_PHY_COMMON_H_ */
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/b43/phy_g.c linux-libre-2.6.38-gnu1/drivers/net/wireless/b43/phy_g.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/b43/phy_g.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/b43/phy_g.c	2011-03-14 21:20:32.000000000 -0400
@@ -1919,7 +1919,7 @@ static void b43_hardware_pctl_init_gphy(
 	b43_hf_write(dev, b43_hf_read(dev) | B43_HF_HWPCTL);
 }
 
-/* Intialize B/G PHY power control */
+/* Initialize B/G PHY power control */
 static void b43_phy_init_pctl(struct b43_wldev *dev)
 {
 	struct ssb_bus *bus = dev->dev->bus;
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/b43/phy_n.c linux-libre-2.6.38-gnu1/drivers/net/wireless/b43/phy_n.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/b43/phy_n.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/b43/phy_n.c	2011-03-14 21:20:32.000000000 -0400
@@ -67,6 +67,18 @@ enum b43_nphy_rf_sequence {
 	B43_RFSEQ_UPDATE_GAINU,
 };
 
+enum b43_nphy_rssi_type {
+	B43_NPHY_RSSI_X = 0,
+	B43_NPHY_RSSI_Y,
+	B43_NPHY_RSSI_Z,
+	B43_NPHY_RSSI_PWRDET,
+	B43_NPHY_RSSI_TSSI_I,
+	B43_NPHY_RSSI_TSSI_Q,
+	B43_NPHY_RSSI_TBD,
+};
+
+static void b43_nphy_stay_in_carrier_search(struct b43_wldev *dev,
+						bool enable);
 static void b43_nphy_set_rf_sequence(struct b43_wldev *dev, u8 cmd,
 					u8 *events, u8 *delays, u8 length);
 static void b43_nphy_force_rf_sequence(struct b43_wldev *dev,
@@ -76,13 +88,6 @@ static void b43_nphy_rf_control_override
 static void b43_nphy_rf_control_intc_override(struct b43_wldev *dev, u8 field,
 						u16 value, u8 core);
 
-static inline bool b43_channel_type_is_40mhz(
-					enum nl80211_channel_type channel_type)
-{
-	return (channel_type == NL80211_CHAN_HT40MINUS ||
-		channel_type == NL80211_CHAN_HT40PLUS);
-}
-
 void b43_nphy_set_rxantenna(struct b43_wldev *dev, int antenna)
 {//TODO
 }
@@ -134,6 +139,99 @@ static void b43_chantab_radio_upload(str
 	b43_radio_write(dev, B2055_C2_TX_MXBGTRIM, e->radio_c2_tx_mxbgtrim);
 }
 
+static void b43_chantab_radio_2056_upload(struct b43_wldev *dev,
+				const struct b43_nphy_channeltab_entry_rev3 *e)
+{
+	b43_radio_write(dev, B2056_SYN_PLL_VCOCAL1, e->radio_syn_pll_vcocal1);
+	b43_radio_write(dev, B2056_SYN_PLL_VCOCAL2, e->radio_syn_pll_vcocal2);
+	b43_radio_write(dev, B2056_SYN_PLL_REFDIV, e->radio_syn_pll_refdiv);
+	b43_radio_write(dev, B2056_SYN_PLL_MMD2, e->radio_syn_pll_mmd2);
+	b43_radio_write(dev, B2056_SYN_PLL_MMD1, e->radio_syn_pll_mmd1);
+	b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER1,
+					e->radio_syn_pll_loopfilter1);
+	b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER2,
+					e->radio_syn_pll_loopfilter2);
+	b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER3,
+					e->radio_syn_pll_loopfilter3);
+	b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER4,
+					e->radio_syn_pll_loopfilter4);
+	b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER5,
+					e->radio_syn_pll_loopfilter5);
+	b43_radio_write(dev, B2056_SYN_RESERVED_ADDR27,
+					e->radio_syn_reserved_addr27);
+	b43_radio_write(dev, B2056_SYN_RESERVED_ADDR28,
+					e->radio_syn_reserved_addr28);
+	b43_radio_write(dev, B2056_SYN_RESERVED_ADDR29,
+					e->radio_syn_reserved_addr29);
+	b43_radio_write(dev, B2056_SYN_LOGEN_VCOBUF1,
+					e->radio_syn_logen_vcobuf1);
+	b43_radio_write(dev, B2056_SYN_LOGEN_MIXER2, e->radio_syn_logen_mixer2);
+	b43_radio_write(dev, B2056_SYN_LOGEN_BUF3, e->radio_syn_logen_buf3);
+	b43_radio_write(dev, B2056_SYN_LOGEN_BUF4, e->radio_syn_logen_buf4);
+
+	b43_radio_write(dev, B2056_RX0 | B2056_RX_LNAA_TUNE,
+					e->radio_rx0_lnaa_tune);
+	b43_radio_write(dev, B2056_RX0 | B2056_RX_LNAG_TUNE,
+					e->radio_rx0_lnag_tune);
+
+	b43_radio_write(dev, B2056_TX0 | B2056_TX_INTPAA_BOOST_TUNE,
+					e->radio_tx0_intpaa_boost_tune);
+	b43_radio_write(dev, B2056_TX0 | B2056_TX_INTPAG_BOOST_TUNE,
+					e->radio_tx0_intpag_boost_tune);
+	b43_radio_write(dev, B2056_TX0 | B2056_TX_PADA_BOOST_TUNE,
+					e->radio_tx0_pada_boost_tune);
+	b43_radio_write(dev, B2056_TX0 | B2056_TX_PADG_BOOST_TUNE,
+					e->radio_tx0_padg_boost_tune);
+	b43_radio_write(dev, B2056_TX0 | B2056_TX_PGAA_BOOST_TUNE,
+					e->radio_tx0_pgaa_boost_tune);
+	b43_radio_write(dev, B2056_TX0 | B2056_TX_PGAG_BOOST_TUNE,
+					e->radio_tx0_pgag_boost_tune);
+	b43_radio_write(dev, B2056_TX0 | B2056_TX_MIXA_BOOST_TUNE,
+					e->radio_tx0_mixa_boost_tune);
+	b43_radio_write(dev, B2056_TX0 | B2056_TX_MIXG_BOOST_TUNE,
+					e->radio_tx0_mixg_boost_tune);
+
+	b43_radio_write(dev, B2056_RX1 | B2056_RX_LNAA_TUNE,
+					e->radio_rx1_lnaa_tune);
+	b43_radio_write(dev, B2056_RX1 | B2056_RX_LNAG_TUNE,
+					e->radio_rx1_lnag_tune);
+
+	b43_radio_write(dev, B2056_TX1 | B2056_TX_INTPAA_BOOST_TUNE,
+					e->radio_tx1_intpaa_boost_tune);
+	b43_radio_write(dev, B2056_TX1 | B2056_TX_INTPAG_BOOST_TUNE,
+					e->radio_tx1_intpag_boost_tune);
+	b43_radio_write(dev, B2056_TX1 | B2056_TX_PADA_BOOST_TUNE,
+					e->radio_tx1_pada_boost_tune);
+	b43_radio_write(dev, B2056_TX1 | B2056_TX_PADG_BOOST_TUNE,
+					e->radio_tx1_padg_boost_tune);
+	b43_radio_write(dev, B2056_TX1 | B2056_TX_PGAA_BOOST_TUNE,
+					e->radio_tx1_pgaa_boost_tune);
+	b43_radio_write(dev, B2056_TX1 | B2056_TX_PGAG_BOOST_TUNE,
+					e->radio_tx1_pgag_boost_tune);
+	b43_radio_write(dev, B2056_TX1 | B2056_TX_MIXA_BOOST_TUNE,
+					e->radio_tx1_mixa_boost_tune);
+	b43_radio_write(dev, B2056_TX1 | B2056_TX_MIXG_BOOST_TUNE,
+					e->radio_tx1_mixg_boost_tune);
+}
+
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/Radio/2056Setup */
+static void b43_radio_2056_setup(struct b43_wldev *dev,
+				const struct b43_nphy_channeltab_entry_rev3 *e)
+{
+	B43_WARN_ON(dev->phy.rev < 3);
+
+	b43_chantab_radio_2056_upload(dev, e);
+	/* TODO */
+	udelay(50);
+	/* VCO calibration */
+	b43_radio_write(dev, B2056_SYN_PLL_VCOCAL12, 0x00);
+	b43_radio_write(dev, B2056_TX_INTPAA_PA_MISC, 0x38);
+	b43_radio_write(dev, B2056_TX_INTPAA_PA_MISC, 0x18);
+	b43_radio_write(dev, B2056_TX_INTPAA_PA_MISC, 0x38);
+	b43_radio_write(dev, B2056_TX_INTPAA_PA_MISC, 0x39);
+	udelay(300);
+}
+
 static void b43_chantab_phy_upload(struct b43_wldev *dev,
 				   const struct b43_phy_n_sfo_cfg *e)
 {
@@ -145,9 +243,154 @@ static void b43_chantab_phy_upload(struc
 	b43_phy_write(dev, B43_NPHY_BW6, e->phy_bw6);
 }
 
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrCtrlEnable */
+static void b43_nphy_tx_power_ctrl(struct b43_wldev *dev, bool enable)
+{
+	struct b43_phy_n *nphy = dev->phy.n;
+	u8 i;
+	u16 tmp;
+
+	if (nphy->hang_avoid)
+		b43_nphy_stay_in_carrier_search(dev, 1);
+
+	nphy->txpwrctrl = enable;
+	if (!enable) {
+		if (dev->phy.rev >= 3)
+			; /* TODO */
+
+		b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x6840);
+		for (i = 0; i < 84; i++)
+			b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0);
+
+		b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x6C40);
+		for (i = 0; i < 84; i++)
+			b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0);
+
+		tmp = B43_NPHY_TXPCTL_CMD_COEFF | B43_NPHY_TXPCTL_CMD_HWPCTLEN;
+		if (dev->phy.rev >= 3)
+			tmp |= B43_NPHY_TXPCTL_CMD_PCTLEN;
+		b43_phy_mask(dev, B43_NPHY_TXPCTL_CMD, ~tmp);
+
+		if (dev->phy.rev >= 3) {
+			b43_phy_set(dev, B43_NPHY_AFECTL_OVER1, 0x0100);
+			b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x0100);
+		} else {
+			b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x4000);
+		}
+
+		if (dev->phy.rev == 2)
+			b43_phy_maskset(dev, B43_NPHY_BPHY_CTL3,
+				~B43_NPHY_BPHY_CTL3_SCALE, 0x53);
+		else if (dev->phy.rev < 2)
+			b43_phy_maskset(dev, B43_NPHY_BPHY_CTL3,
+				~B43_NPHY_BPHY_CTL3_SCALE, 0x5A);
+
+		if (dev->phy.rev < 2 && 0)
+			; /* TODO */
+	} else {
+		b43err(dev->wl, "enabling tx pwr ctrl not implemented yet\n");
+	}
+
+	if (nphy->hang_avoid)
+		b43_nphy_stay_in_carrier_search(dev, 0);
+}
+
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrFix */
 static void b43_nphy_tx_power_fix(struct b43_wldev *dev)
 {
-	//TODO
+	struct b43_phy_n *nphy = dev->phy.n;
+	struct ssb_sprom *sprom = &(dev->dev->bus->sprom);
+
+	u8 txpi[2], bbmult, i;
+	u16 tmp, radio_gain, dac_gain;
+	u16 freq = dev->phy.channel_freq;
+	u32 txgain;
+	/* u32 gaintbl; rev3+ */
+
+	if (nphy->hang_avoid)
+		b43_nphy_stay_in_carrier_search(dev, 1);
+
+	if (dev->phy.rev >= 3) {
+		txpi[0] = 40;
+		txpi[1] = 40;
+	} else if (sprom->revision < 4) {
+		txpi[0] = 72;
+		txpi[1] = 72;
+	} else {
+		if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
+			txpi[0] = sprom->txpid2g[0];
+			txpi[1] = sprom->txpid2g[1];
+		} else if (freq >= 4900 && freq < 5100) {
+			txpi[0] = sprom->txpid5gl[0];
+			txpi[1] = sprom->txpid5gl[1];
+		} else if (freq >= 5100 && freq < 5500) {
+			txpi[0] = sprom->txpid5g[0];
+			txpi[1] = sprom->txpid5g[1];
+		} else if (freq >= 5500) {
+			txpi[0] = sprom->txpid5gh[0];
+			txpi[1] = sprom->txpid5gh[1];
+		} else {
+			txpi[0] = 91;
+			txpi[1] = 91;
+		}
+	}
+
+	/*
+	for (i = 0; i < 2; i++) {
+		nphy->txpwrindex[i].index_internal = txpi[i];
+		nphy->txpwrindex[i].index_internal_save = txpi[i];
+	}
+	*/
+
+	for (i = 0; i < 2; i++) {
+		if (dev->phy.rev >= 3) {
+			/* FIXME: support 5GHz */
+			txgain = b43_ntab_tx_gain_rev3plus_2ghz[txpi[i]];
+			radio_gain = (txgain >> 16) & 0x1FFFF;
+		} else {
+			txgain = b43_ntab_tx_gain_rev0_1_2[txpi[i]];
+			radio_gain = (txgain >> 16) & 0x1FFF;
+		}
+
+		dac_gain = (txgain >> 8) & 0x3F;
+		bbmult = txgain & 0xFF;
+
+		if (dev->phy.rev >= 3) {
+			if (i == 0)
+				b43_phy_set(dev, B43_NPHY_AFECTL_OVER1, 0x0100);
+			else
+				b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x0100);
+		} else {
+			b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x4000);
+		}
+
+		if (i == 0)
+			b43_phy_write(dev, B43_NPHY_AFECTL_DACGAIN1, dac_gain);
+		else
+			b43_phy_write(dev, B43_NPHY_AFECTL_DACGAIN2, dac_gain);
+
+		b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x1D10 + i);
+		b43_phy_write(dev, B43_NPHY_TABLE_DATALO, radio_gain);
+
+		b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x3C57);
+		tmp = b43_phy_read(dev, B43_NPHY_TABLE_DATALO);
+
+		if (i == 0)
+			tmp = (tmp & 0x00FF) | (bbmult << 8);
+		else
+			tmp = (tmp & 0xFF00) | bbmult;
+
+		b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x3C57);
+		b43_phy_write(dev, B43_NPHY_TABLE_DATALO, tmp);
+
+		if (0)
+			; /* TODO */
+	}
+
+	b43_phy_mask(dev, B43_NPHY_BPHY_CTL2, ~B43_NPHY_BPHY_CTL2_LUT);
+
+	if (nphy->hang_avoid)
+		b43_nphy_stay_in_carrier_search(dev, 0);
 }
 
 
@@ -191,7 +434,8 @@ static void b43_radio_init2055_post(stru
 				binfo->type != 0x46D ||
 				binfo->rev < 0x41);
 	else
-		workaround = ((sprom->boardflags_hi & B43_BFH_NOPA) == 0);
+		workaround =
+			!(sprom->boardflags2_lo & B43_BFL2_RXBB_INT_REG_DIS);
 
 	b43_radio_mask(dev, B2055_MASTER1, 0xFFF3);
 	if (workaround) {
@@ -240,23 +484,55 @@ static void b43_radio_init2055_post(stru
 static void b43_radio_init2055(struct b43_wldev *dev)
 {
 	b43_radio_init2055_pre(dev);
-	if (b43_status(dev) < B43_STAT_INITIALIZED)
-		b2055_upload_inittab(dev, 0, 1);
-	else
-		b2055_upload_inittab(dev, 0/*FIXME on 5ghz band*/, 0);
+	if (b43_status(dev) < B43_STAT_INITIALIZED) {
+		/* Follow wl, not specs. Do not force uploading all regs */
+		b2055_upload_inittab(dev, 0, 0);
+	} else {
+		bool ghz5 = b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ;
+		b2055_upload_inittab(dev, ghz5, 0);
+	}
 	b43_radio_init2055_post(dev);
 }
 
+static void b43_radio_init2056_pre(struct b43_wldev *dev)
+{
+	b43_phy_mask(dev, B43_NPHY_RFCTL_CMD,
+		     ~B43_NPHY_RFCTL_CMD_CHIP0PU);
+	/* Maybe wl meant to reset and set (order?) RFCTL_CMD_OEPORFORCE? */
+	b43_phy_mask(dev, B43_NPHY_RFCTL_CMD,
+		     B43_NPHY_RFCTL_CMD_OEPORFORCE);
+	b43_phy_set(dev, B43_NPHY_RFCTL_CMD,
+		    ~B43_NPHY_RFCTL_CMD_OEPORFORCE);
+	b43_phy_set(dev, B43_NPHY_RFCTL_CMD,
+		    B43_NPHY_RFCTL_CMD_CHIP0PU);
+}
+
+static void b43_radio_init2056_post(struct b43_wldev *dev)
+{
+	b43_radio_set(dev, B2056_SYN_COM_CTRL, 0xB);
+	b43_radio_set(dev, B2056_SYN_COM_PU, 0x2);
+	b43_radio_set(dev, B2056_SYN_COM_RESET, 0x2);
+	msleep(1);
+	b43_radio_mask(dev, B2056_SYN_COM_RESET, ~0x2);
+	b43_radio_mask(dev, B2056_SYN_PLL_MAST2, ~0xFC);
+	b43_radio_mask(dev, B2056_SYN_RCCAL_CTRL0, ~0x1);
+	/*
+	if (nphy->init_por)
+		Call Radio 2056 Recalibrate
+	*/
+}
+
 /*
  * Initialize a Broadcom 2056 N-radio
  * http://bcm-v4.sipsolutions.net/802.11/Radio/2056/Init
  */
 static void b43_radio_init2056(struct b43_wldev *dev)
 {
-	/* TODO */
+	b43_radio_init2056_pre(dev);
+	b2056_upload_inittabs(dev, 0, 0);
+	b43_radio_init2056_post(dev);
 }
 
-
 /*
  * Upload the N-PHY tables.
  * http://bcm-v4.sipsolutions.net/802.11/PHY/N/InitTables
@@ -453,6 +729,8 @@ static void b43_nphy_rx_iq_coeffs(struct
 	}
 }
 
+#if 0
+/* Ready but not used anywhere */
 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxCalPhyCleanup */
 static void b43_nphy_rx_cal_phy_cleanup(struct b43_wldev *dev, u8 core)
 {
@@ -534,6 +812,7 @@ static void b43_nphy_rx_cal_phy_setup(st
 	b43_nphy_rf_control_intc_override(dev, 1, rxval, (core + 1));
 	b43_nphy_rf_control_intc_override(dev, 1, txval, (2 - core));
 }
+#endif
 
 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CalcRxIqComp */
 static void b43_nphy_calc_rx_iq_comp(struct b43_wldev *dev, u8 mask)
@@ -569,7 +848,6 @@ static void b43_nphy_calc_rx_iq_comp(str
 			ii = est.i1_pwr;
 			qq = est.q1_pwr;
 		} else {
-			B43_WARN_ON(1);
 			continue;
 		}
 
@@ -651,7 +929,8 @@ static void b43_nphy_tx_iq_workaround(st
 }
 
 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/clip-detection */
-static void b43_nphy_write_clip_detection(struct b43_wldev *dev, u16 *clip_st)
+static void b43_nphy_write_clip_detection(struct b43_wldev *dev,
+					  const u16 *clip_st)
 {
 	b43_phy_write(dev, B43_NPHY_C1_CLIP1THRES, clip_st[0]);
 	b43_phy_write(dev, B43_NPHY_C2_CLIP1THRES, clip_st[1]);
@@ -727,7 +1006,7 @@ static void b43_nphy_stay_in_carrier_sea
 	struct b43_phy_n *nphy = phy->n;
 
 	if (enable) {
-		u16 clip[] = { 0xFFFF, 0xFFFF };
+		static const u16 clip[] = { 0xFFFF, 0xFFFF };
 		if (nphy->deaf_count++ == 0) {
 			nphy->classifier_state = b43_nphy_classifier(dev, 0, 0);
 			b43_nphy_classifier(dev, 0x7, 0);
@@ -839,7 +1118,7 @@ static void b43_nphy_adjust_lna_gain_tab
 	u16 data[4];
 	s16 gain[2];
 	u16 minmax[2];
-	u16 lna_gain[4] = { -2, 10, 19, 25 };
+	static const u16 lna_gain[4] = { -2, 10, 19, 25 };
 
 	if (nphy->hang_avoid)
 		b43_nphy_stay_in_carrier_search(dev, 1);
@@ -871,7 +1150,7 @@ static void b43_nphy_adjust_lna_gain_tab
 			data[2] = lna_gain[2] + gain[i];
 			data[3] = lna_gain[3] + gain[i];
 		}
-		b43_ntab_write_bulk(dev, B43_NTAB16(10, 8), 4, data);
+		b43_ntab_write_bulk(dev, B43_NTAB16(i, 8), 4, data);
 
 		minmax[i] = 23 + gain[i];
 	}
@@ -891,6 +1170,7 @@ static void b43_nphy_gain_ctrl_workaroun
 	struct b43_phy_n *nphy = dev->phy.n;
 	u8 i, j;
 	u8 code;
+	u16 tmp;
 
 	/* TODO: for PHY >= 3
 	s8 *lna1_gain, *lna2_gain;
@@ -913,15 +1193,15 @@ static void b43_nphy_gain_ctrl_workaroun
 				B43_NPHY_C2_CGAINI_CL2DETECT);
 
 		/* Set narrowband clip threshold */
-		b43_phy_set(dev, B43_NPHY_C1_NBCLIPTHRES, 0x84);
-		b43_phy_set(dev, B43_NPHY_C2_NBCLIPTHRES, 0x84);
+		b43_phy_write(dev, B43_NPHY_C1_NBCLIPTHRES, 0x84);
+		b43_phy_write(dev, B43_NPHY_C2_NBCLIPTHRES, 0x84);
 
 		if (!dev->phy.is_40mhz) {
 			/* Set dwell lengths */
-			b43_phy_set(dev, B43_NPHY_CLIP1_NBDWELL_LEN, 0x002B);
-			b43_phy_set(dev, B43_NPHY_CLIP2_NBDWELL_LEN, 0x002B);
-			b43_phy_set(dev, B43_NPHY_W1CLIP1_DWELL_LEN, 0x0009);
-			b43_phy_set(dev, B43_NPHY_W1CLIP2_DWELL_LEN, 0x0009);
+			b43_phy_write(dev, B43_NPHY_CLIP1_NBDWELL_LEN, 0x002B);
+			b43_phy_write(dev, B43_NPHY_CLIP2_NBDWELL_LEN, 0x002B);
+			b43_phy_write(dev, B43_NPHY_W1CLIP1_DWELL_LEN, 0x0009);
+			b43_phy_write(dev, B43_NPHY_W1CLIP2_DWELL_LEN, 0x0009);
 		}
 
 		/* Set wideband clip 2 threshold */
@@ -943,7 +1223,7 @@ static void b43_nphy_gain_ctrl_workaroun
 				~B43_NPHY_C2_CCK_CGAINI_GAINBKOFF, 0x1);
 		}
 
-		b43_phy_set(dev, B43_NPHY_CCK_SHIFTB_REF, 0x809C);
+		b43_phy_write(dev, B43_NPHY_CCK_SHIFTB_REF, 0x809C);
 
 		if (nphy->gain_boost) {
 			if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ &&
@@ -964,10 +1244,10 @@ static void b43_nphy_gain_ctrl_workaroun
 				code << B43_NPHY_C2_INITGAIN_HPVGA2_SHIFT);
 
 		b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x1D06);
-		b43_phy_write(dev, B43_NPHY_TABLE_DATALO,
-					(code << 8 | 0x7C));
-		b43_phy_write(dev, B43_NPHY_TABLE_DATALO,
-					(code << 8 | 0x7C));
+		/* specs say about 2 loops, but wl does 4 */
+		for (i = 0; i < 4; i++)
+			b43_phy_write(dev, B43_NPHY_TABLE_DATALO,
+							(code << 8 | 0x7C));
 
 		b43_nphy_adjust_lna_gain_table(dev);
 
@@ -985,19 +1265,21 @@ static void b43_nphy_gain_ctrl_workaroun
 			b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x1);
 
 			b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x1D06);
-			b43_phy_write(dev, B43_NPHY_TABLE_DATALO,
-					(code << 8 | 0x74));
-			b43_phy_write(dev, B43_NPHY_TABLE_DATALO,
-					(code << 8 | 0x74));
+			/* specs say about 2 loops, but wl does 4 */
+			for (i = 0; i < 4; i++)
+				b43_phy_write(dev, B43_NPHY_TABLE_DATALO,
+							(code << 8 | 0x74));
 		}
 
 		if (dev->phy.rev == 2) {
 			for (i = 0; i < 4; i++) {
 				b43_phy_write(dev, B43_NPHY_TABLE_ADDR,
 						(0x0400 * i) + 0x0020);
-				for (j = 0; j < 21; j++)
+				for (j = 0; j < 21; j++) {
+					tmp = j * (i < 2 ? 3 : 1);
 					b43_phy_write(dev,
-						B43_NPHY_TABLE_DATALO, 3 * j);
+						B43_NPHY_TABLE_DATALO, tmp);
+				}
 			}
 
 			b43_nphy_set_rf_sequence(dev, 5,
@@ -1026,7 +1308,7 @@ static void b43_nphy_workarounds(struct
 	u8 events2[7] = { 0x0, 0x3, 0x5, 0x4, 0x2, 0x1, 0x8 };
 	u8 delays2[7] = { 0x8, 0x6, 0x2, 0x4, 0x4, 0x6, 0x1 };
 
-	if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
+	if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ)
 		b43_nphy_classifier(dev, 1, 0);
 	else
 		b43_nphy_classifier(dev, 1, 1);
@@ -1049,29 +1331,18 @@ static void b43_nphy_workarounds(struct
 			b43_radio_set(dev, B2055_C2_TX_RF_SPARE, 0x8);
 		}
 
-		/* TODO: convert to b43_ntab_write? */
-		b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x2000);
-		b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x000A);
-		b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x2010);
-		b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x000A);
-		b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x2002);
-		b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0xCDAA);
-		b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x2012);
-		b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0xCDAA);
+		b43_ntab_write(dev, B43_NTAB16(8, 0x00), 0x000A);
+		b43_ntab_write(dev, B43_NTAB16(8, 0x10), 0x000A);
+		b43_ntab_write(dev, B43_NTAB16(8, 0x02), 0xCDAA);
+		b43_ntab_write(dev, B43_NTAB16(8, 0x12), 0xCDAA);
 
 		if (dev->phy.rev < 2) {
-			b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x2008);
-			b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x0000);
-			b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x2018);
-			b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x0000);
-			b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x2007);
-			b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x7AAB);
-			b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x2017);
-			b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x7AAB);
-			b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x2006);
-			b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x0800);
-			b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x2016);
-			b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x0800);
+			b43_ntab_write(dev, B43_NTAB16(8, 0x08), 0x0000);
+			b43_ntab_write(dev, B43_NTAB16(8, 0x18), 0x0000);
+			b43_ntab_write(dev, B43_NTAB16(8, 0x07), 0x7AAB);
+			b43_ntab_write(dev, B43_NTAB16(8, 0x17), 0x7AAB);
+			b43_ntab_write(dev, B43_NTAB16(8, 0x06), 0x0800);
+			b43_ntab_write(dev, B43_NTAB16(8, 0x16), 0x0800);
 		}
 
 		b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO1, 0x2D8);
@@ -1565,19 +1836,20 @@ static void b43_nphy_rf_control_intc_ove
 	}
 }
 
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/BPHYInit */
 static void b43_nphy_bphy_init(struct b43_wldev *dev)
 {
 	unsigned int i;
 	u16 val;
 
 	val = 0x1E1F;
-	for (i = 0; i < 14; i++) {
+	for (i = 0; i < 16; i++) {
 		b43_phy_write(dev, B43_PHY_N_BMODE(0x88 + i), val);
 		val -= 0x202;
 	}
 	val = 0x3E3F;
 	for (i = 0; i < 16; i++) {
-		b43_phy_write(dev, B43_PHY_N_BMODE(0x97 + i), val);
+		b43_phy_write(dev, B43_PHY_N_BMODE(0x98 + i), val);
 		val -= 0x202;
 	}
 	b43_phy_write(dev, B43_PHY_N_BMODE(0x38), 0x668);
@@ -1585,7 +1857,8 @@ static void b43_nphy_bphy_init(struct b4
 
 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ScaleOffsetRssi */
 static void b43_nphy_scale_offset_rssi(struct b43_wldev *dev, u16 scale,
-				       s8 offset, u8 core, u8 rail, u8 type)
+					s8 offset, u8 core, u8 rail,
+					enum b43_nphy_rssi_type type)
 {
 	u16 tmp;
 	bool core1or5 = (core == 1) || (core == 5);
@@ -1594,53 +1867,59 @@ static void b43_nphy_scale_offset_rssi(s
 	offset = clamp_val(offset, -32, 31);
 	tmp = ((scale & 0x3F) << 8) | (offset & 0x3F);
 
-	if (core1or5 && (rail == 0) && (type == 2))
+	if (core1or5 && (rail == 0) && (type == B43_NPHY_RSSI_Z))
 		b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_Z, tmp);
-	if (core1or5 && (rail == 1) && (type == 2))
+	if (core1or5 && (rail == 1) && (type == B43_NPHY_RSSI_Z))
 		b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_Z, tmp);
-	if (core2or5 && (rail == 0) && (type == 2))
+	if (core2or5 && (rail == 0) && (type == B43_NPHY_RSSI_Z))
 		b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_Z, tmp);
-	if (core2or5 && (rail == 1) && (type == 2))
+	if (core2or5 && (rail == 1) && (type == B43_NPHY_RSSI_Z))
 		b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_Z, tmp);
-	if (core1or5 && (rail == 0) && (type == 0))
+
+	if (core1or5 && (rail == 0) && (type == B43_NPHY_RSSI_X))
 		b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_X, tmp);
-	if (core1or5 && (rail == 1) && (type == 0))
+	if (core1or5 && (rail == 1) && (type == B43_NPHY_RSSI_X))
 		b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_X, tmp);
-	if (core2or5 && (rail == 0) && (type == 0))
+	if (core2or5 && (rail == 0) && (type == B43_NPHY_RSSI_X))
 		b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_X, tmp);
-	if (core2or5 && (rail == 1) && (type == 0))
+	if (core2or5 && (rail == 1) && (type == B43_NPHY_RSSI_X))
 		b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_X, tmp);
-	if (core1or5 && (rail == 0) && (type == 1))
+
+	if (core1or5 && (rail == 0) && (type == B43_NPHY_RSSI_Y))
 		b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_Y, tmp);
-	if (core1or5 && (rail == 1) && (type == 1))
+	if (core1or5 && (rail == 1) && (type == B43_NPHY_RSSI_Y))
 		b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_Y, tmp);
-	if (core2or5 && (rail == 0) && (type == 1))
+	if (core2or5 && (rail == 0) && (type == B43_NPHY_RSSI_Y))
 		b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_Y, tmp);
-	if (core2or5 && (rail == 1) && (type == 1))
+	if (core2or5 && (rail == 1) && (type == B43_NPHY_RSSI_Y))
 		b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_Y, tmp);
-	if (core1or5 && (rail == 0) && (type == 6))
+
+	if (core1or5 && (rail == 0) && (type == B43_NPHY_RSSI_TBD))
 		b43_phy_write(dev, B43_NPHY_RSSIMC_0I_TBD, tmp);
-	if (core1or5 && (rail == 1) && (type == 6))
+	if (core1or5 && (rail == 1) && (type == B43_NPHY_RSSI_TBD))
 		b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_TBD, tmp);
-	if (core2or5 && (rail == 0) && (type == 6))
+	if (core2or5 && (rail == 0) && (type == B43_NPHY_RSSI_TBD))
 		b43_phy_write(dev, B43_NPHY_RSSIMC_1I_TBD, tmp);
-	if (core2or5 && (rail == 1) && (type == 6))
+	if (core2or5 && (rail == 1) && (type == B43_NPHY_RSSI_TBD))
 		b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_TBD, tmp);
-	if (core1or5 && (rail == 0) && (type == 3))
+
+	if (core1or5 && (rail == 0) && (type == B43_NPHY_RSSI_PWRDET))
 		b43_phy_write(dev, B43_NPHY_RSSIMC_0I_PWRDET, tmp);
-	if (core1or5 && (rail == 1) && (type == 3))
+	if (core1or5 && (rail == 1) && (type == B43_NPHY_RSSI_PWRDET))
 		b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_PWRDET, tmp);
-	if (core2or5 && (rail == 0) && (type == 3))
+	if (core2or5 && (rail == 0) && (type == B43_NPHY_RSSI_PWRDET))
 		b43_phy_write(dev, B43_NPHY_RSSIMC_1I_PWRDET, tmp);
-	if (core2or5 && (rail == 1) && (type == 3))
+	if (core2or5 && (rail == 1) && (type == B43_NPHY_RSSI_PWRDET))
 		b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_PWRDET, tmp);
-	if (core1or5 && (type == 4))
+
+	if (core1or5 && (type == B43_NPHY_RSSI_TSSI_I))
 		b43_phy_write(dev, B43_NPHY_RSSIMC_0I_TSSI, tmp);
-	if (core2or5 && (type == 4))
+	if (core2or5 && (type == B43_NPHY_RSSI_TSSI_I))
 		b43_phy_write(dev, B43_NPHY_RSSIMC_1I_TSSI, tmp);
-	if (core1or5 && (type == 5))
+
+	if (core1or5 && (type == B43_NPHY_RSSI_TSSI_Q))
 		b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_TSSI, tmp);
-	if (core2or5 && (type == 5))
+	if (core2or5 && (type == B43_NPHY_RSSI_TSSI_Q))
 		b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_TSSI, tmp);
 }
 
@@ -1668,27 +1947,39 @@ static void b43_nphy_rev2_rssi_select(st
 				(type + 1) << 4);
 	}
 
-	/* TODO use some definitions */
 	if (code == 0) {
-		b43_phy_maskset(dev, B43_NPHY_AFECTL_OVER, 0xCFFF, 0);
+		b43_phy_mask(dev, B43_NPHY_AFECTL_OVER, ~0x3000);
 		if (type < 3) {
-			b43_phy_maskset(dev, B43_NPHY_RFCTL_CMD, 0xFEC7, 0);
-			b43_phy_maskset(dev, B43_NPHY_RFCTL_OVER, 0xEFDC, 0);
-			b43_phy_maskset(dev, B43_NPHY_RFCTL_CMD, 0xFFFE, 0);
+			b43_phy_mask(dev, B43_NPHY_RFCTL_CMD,
+				~(B43_NPHY_RFCTL_CMD_RXEN |
+				  B43_NPHY_RFCTL_CMD_CORESEL));
+			b43_phy_mask(dev, B43_NPHY_RFCTL_OVER,
+				~(0x1 << 12 |
+				  0x1 << 5 |
+				  0x1 << 1 |
+				  0x1));
+			b43_phy_mask(dev, B43_NPHY_RFCTL_CMD,
+				~B43_NPHY_RFCTL_CMD_START);
 			udelay(20);
-			b43_phy_maskset(dev, B43_NPHY_RFCTL_OVER, 0xFFFE, 0);
+			b43_phy_mask(dev, B43_NPHY_RFCTL_OVER, ~0x1);
 		}
 	} else {
-		b43_phy_maskset(dev, B43_NPHY_AFECTL_OVER, 0xCFFF,
-				0x3000);
+		b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x3000);
 		if (type < 3) {
 			b43_phy_maskset(dev, B43_NPHY_RFCTL_CMD,
-					0xFEC7, 0x0180);
-			b43_phy_maskset(dev, B43_NPHY_RFCTL_OVER,
-					0xEFDC, (code << 1 | 0x1021));
-			b43_phy_maskset(dev, B43_NPHY_RFCTL_CMD, 0xFFFE, 0x1);
+				~(B43_NPHY_RFCTL_CMD_RXEN |
+				  B43_NPHY_RFCTL_CMD_CORESEL),
+				(B43_NPHY_RFCTL_CMD_RXEN |
+				 code << B43_NPHY_RFCTL_CMD_CORESEL_SHIFT));
+			b43_phy_set(dev, B43_NPHY_RFCTL_OVER,
+				(0x1 << 12 |
+				  0x1 << 5 |
+				  0x1 << 1 |
+				  0x1));
+			b43_phy_set(dev, B43_NPHY_RFCTL_CMD,
+				B43_NPHY_RFCTL_CMD_START);
 			udelay(20);
-			b43_phy_maskset(dev, B43_NPHY_RFCTL_OVER, 0xFFFE, 0);
+			b43_phy_mask(dev, B43_NPHY_RFCTL_OVER, ~0x1);
 		}
 	}
 }
@@ -1837,6 +2128,14 @@ static int b43_nphy_poll_rssi(struct b43
 		save_regs_phy[5] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER);
 		save_regs_phy[6] = b43_phy_read(dev, B43_NPHY_TXF_40CO_B1S0);
 		save_regs_phy[7] = b43_phy_read(dev, B43_NPHY_TXF_40CO_B32S1);
+	} else if (dev->phy.rev == 2) {
+		save_regs_phy[0] = b43_phy_read(dev, B43_NPHY_AFECTL_C1);
+		save_regs_phy[1] = b43_phy_read(dev, B43_NPHY_AFECTL_C2);
+		save_regs_phy[2] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER);
+		save_regs_phy[3] = b43_phy_read(dev, B43_NPHY_RFCTL_CMD);
+		save_regs_phy[4] = b43_phy_read(dev, B43_NPHY_RFCTL_OVER);
+		save_regs_phy[5] = b43_phy_read(dev, B43_NPHY_RFCTL_RSSIO1);
+		save_regs_phy[6] = b43_phy_read(dev, B43_NPHY_RFCTL_RSSIO2);
 	}
 
 	b43_nphy_rssi_select(dev, 5, type);
@@ -1880,6 +2179,14 @@ static int b43_nphy_poll_rssi(struct b43
 		b43_phy_write(dev, B43_NPHY_AFECTL_OVER, save_regs_phy[5]);
 		b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S0, save_regs_phy[6]);
 		b43_phy_write(dev, B43_NPHY_TXF_40CO_B32S1, save_regs_phy[7]);
+	} else if (dev->phy.rev == 2) {
+		b43_phy_write(dev, B43_NPHY_AFECTL_C1, save_regs_phy[0]);
+		b43_phy_write(dev, B43_NPHY_AFECTL_C2, save_regs_phy[1]);
+		b43_phy_write(dev, B43_NPHY_AFECTL_OVER, save_regs_phy[2]);
+		b43_phy_write(dev, B43_NPHY_RFCTL_CMD, save_regs_phy[3]);
+		b43_phy_write(dev, B43_NPHY_RFCTL_OVER, save_regs_phy[4]);
+		b43_phy_write(dev, B43_NPHY_RFCTL_RSSIO1, save_regs_phy[5]);
+		b43_phy_write(dev, B43_NPHY_RFCTL_RSSIO2, save_regs_phy[6]);
 	}
 
 	return out;
@@ -1894,7 +2201,10 @@ static void b43_nphy_rev2_rssi_cal(struc
 	u16 class, override;
 	u8 regs_save_radio[2];
 	u16 regs_save_phy[2];
+
 	s8 offset[4];
+	u8 core;
+	u8 rail;
 
 	u16 clip_state[2];
 	u16 clip_off[2] = { 0xFFFF, 0xFFFF };
@@ -1995,16 +2305,15 @@ static void b43_nphy_rev2_rssi_cal(struc
 		if (results_min[i] == 248)
 			offset[i] = code - 32;
 
-		if (i % 2 == 0)
-			b43_nphy_scale_offset_rssi(dev, 0, offset[i], 1, 0,
-							type);
-		else
-			b43_nphy_scale_offset_rssi(dev, 0, offset[i], 2, 1,
-							type);
+		core = (i / 2) ? 2 : 1;
+		rail = (i % 2) ? 1 : 0;
+
+		b43_nphy_scale_offset_rssi(dev, 0, offset[i], core, rail,
+						type);
 	}
 
 	b43_radio_maskset(dev, B2055_C1_PD_RSSIMISC, 0xF8, state[0]);
-	b43_radio_maskset(dev, B2055_C1_PD_RSSIMISC, 0xF8, state[1]);
+	b43_radio_maskset(dev, B2055_C2_PD_RSSIMISC, 0xF8, state[1]);
 
 	switch (state[2]) {
 	case 1:
@@ -2042,6 +2351,9 @@ static void b43_nphy_rev2_rssi_cal(struc
 
 	b43_nphy_classifier(dev, 7, class);
 	b43_nphy_write_clip_detection(dev, clip_state);
+	/* Specs don't say about reset here, but it makes wl and b43 dumps
+	   identical, it really seems wl performs this */
+	b43_nphy_reset_cca(dev);
 }
 
 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICalRev3 */
@@ -2059,9 +2371,9 @@ static void b43_nphy_rssi_cal(struct b43
 	if (dev->phy.rev >= 3) {
 		b43_nphy_rev3_rssi_cal(dev);
 	} else {
-		b43_nphy_rev2_rssi_cal(dev, 2);
-		b43_nphy_rev2_rssi_cal(dev, 0);
-		b43_nphy_rev2_rssi_cal(dev, 1);
+		b43_nphy_rev2_rssi_cal(dev, B43_NPHY_RSSI_Z);
+		b43_nphy_rev2_rssi_cal(dev, B43_NPHY_RSSI_X);
+		b43_nphy_rev2_rssi_cal(dev, B43_NPHY_RSSI_Y);
 	}
 }
 
@@ -2295,7 +2607,7 @@ static void b43_nphy_int_pa_set_tx_dig_f
 {
 	int i, j;
 	/* B43_NPHY_TXF_20CO_S0A1, B43_NPHY_TXF_40CO_S0A1, unknown */
-	u16 offset[] = { 0x186, 0x195, 0x2C5 };
+	static const u16 offset[] = { 0x186, 0x195, 0x2C5 };
 
 	for (i = 0; i < 3; i++)
 		for (j = 0; j < 15; j++)
@@ -2327,7 +2639,7 @@ static struct nphy_txgains b43_nphy_get_
 	struct nphy_txgains target;
 	const u32 *table = NULL;
 
-	if (nphy->txpwrctrl == 0) {
+	if (!nphy->txpwrctrl) {
 		int i;
 
 		if (nphy->hang_avoid)
@@ -2884,7 +3196,7 @@ static int b43_nphy_rev2_cal_rx_iq(struc
 	u8 rfctl[2];
 	u8 afectl_core;
 	u16 tmp[6];
-	u16 cur_hpf1, cur_hpf2, cur_lna;
+	u16 uninitialized_var(cur_hpf1), uninitialized_var(cur_hpf2), cur_lna;
 	u32 real, imag;
 	enum ieee80211_band band;
 
@@ -3077,9 +3389,9 @@ static void b43_nphy_mac_phy_clock_set(s
 {
 	u32 tmslow = ssb_read32(dev->dev, SSB_TMSLOW);
 	if (on)
-		tmslow |= SSB_TMSLOW_PHYCLK;
+		tmslow |= B43_TMSLOW_MACPHYCLKEN;
 	else
-		tmslow &= ~SSB_TMSLOW_PHYCLK;
+		tmslow &= ~B43_TMSLOW_MACPHYCLKEN;
 	ssb_write32(dev->dev, SSB_TMSLOW, tmslow);
 }
 
@@ -3088,7 +3400,7 @@ static void b43_nphy_set_rx_core_state(s
 {
 	struct b43_phy *phy = &dev->phy;
 	struct b43_phy_n *nphy = phy->n;
-	u16 buf[16];
+	/* u16 buf[16]; it's rev3+ */
 
 	nphy->phyrxchain = mask;
 
@@ -3232,10 +3544,12 @@ int b43_phy_initn(struct b43_wldev *dev)
 
 	b43_nphy_classifier(dev, 0, 0);
 	b43_nphy_read_clip_detection(dev, clip);
+	if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
+		b43_nphy_bphy_init(dev);
+
 	tx_pwr_state = nphy->txpwrctrl;
-	/* TODO N PHY TX power control with argument 0
-		(turning off power control) */
-	/* TODO Fix the TX Power Settings */
+	b43_nphy_tx_power_ctrl(dev, false);
+	b43_nphy_tx_power_fix(dev);
 	/* TODO N PHY TX Power Control Idle TSSI */
 	/* TODO N PHY TX Power Control Setup */
 
@@ -3292,21 +3606,18 @@ int b43_phy_initn(struct b43_wldev *dev)
 					/* TODO N PHY Pre Calibrate TX Gain */
 					target = b43_nphy_get_tx_gains(dev);
 				}
-			}
+				if (!b43_nphy_cal_tx_iq_lo(dev, target, true, false))
+					if (b43_nphy_cal_rx_iq(dev, target, 2, 0) == 0)
+						b43_nphy_save_cal(dev);
+			} else if (nphy->mphase_cal_phase_id == 0)
+				;/* N PHY Periodic Calibration with arg 3 */
+		} else {
+			b43_nphy_restore_cal(dev);
 		}
 	}
 
-	if (!b43_nphy_cal_tx_iq_lo(dev, target, true, false)) {
-		if (b43_nphy_cal_rx_iq(dev, target, 2, 0) == 0)
-			b43_nphy_save_cal(dev);
-		else if (nphy->mphase_cal_phase_id == 0)
-			;/* N PHY Periodic Calibration with argument 3 */
-	} else {
-		b43_nphy_restore_cal(dev);
-	}
-
 	b43_nphy_tx_pwr_ctrl_coef_setup(dev);
-	/* TODO N PHY TX Power Control Enable with argument tx_pwr_state */
+	b43_nphy_tx_power_ctrl(dev, tx_pwr_state);
 	b43_phy_write(dev, B43_NPHY_TXMACIF_HOLDOFF, 0x0015);
 	b43_phy_write(dev, B43_NPHY_TXMACDELAY, 0x0320);
 	if (phy->rev >= 3 && phy->rev <= 6)
@@ -3315,7 +3626,6 @@ int b43_phy_initn(struct b43_wldev *dev)
 	if (phy->rev >= 3)
 		b43_nphy_spur_workaround(dev);
 
-	b43err(dev->wl, "IEEE 802.11n devices are not supported, yet.\n");
 	return 0;
 }
 
@@ -3357,7 +3667,7 @@ static void b43_nphy_channel_setup(struc
 			b43_phy_mask(dev, B43_PHY_B_TEST, ~0x840);
 	}
 
-	if (nphy->txpwrctrl)
+	if (!nphy->txpwrctrl)
 		b43_nphy_tx_power_fix(dev);
 
 	if (dev->phy.rev < 3)
@@ -3381,7 +3691,6 @@ static int b43_nphy_set_channel(struct b
 				enum nl80211_channel_type channel_type)
 {
 	struct b43_phy *phy = &dev->phy;
-	struct b43_phy_n *nphy = dev->phy.n;
 
 	const struct b43_nphy_channeltab_entry_rev2 *tabent_r2;
 	const struct b43_nphy_channeltab_entry_rev3 *tabent_r3;
@@ -3391,7 +3700,6 @@ static int b43_nphy_set_channel(struct b
 	if (dev->phy.rev >= 3) {
 		tabent_r3 = b43_nphy_get_chantabent_rev3(dev,
 							channel->center_freq);
-		tabent_r3 = NULL;
 		if (!tabent_r3)
 			return -ESRCH;
 	} else {
@@ -3420,7 +3728,7 @@ static int b43_nphy_set_channel(struct b
 	if (dev->phy.rev >= 3) {
 		tmp = (channel->band == IEEE80211_BAND_5GHZ) ? 4 : 0;
 		b43_radio_maskset(dev, 0x08, 0xFFFB, tmp);
-		/* TODO: PHY Radio2056 Setup (dev, tabent_r3); */
+		b43_radio_2056_setup(dev, tabent_r3);
 		b43_nphy_channel_setup(dev, &(tabent_r3->phy_regs), channel);
 	} else {
 		tmp = (channel->band == IEEE80211_BAND_5GHZ) ? 0x0020 : 0x0050;
@@ -3451,7 +3759,11 @@ static void b43_nphy_op_prepare_structs(
 
 	memset(nphy, 0, sizeof(*nphy));
 
-	//TODO init struct b43_phy_n
+	nphy->hang_avoid = (phy->rev == 3 || phy->rev == 4);
+	nphy->gain_boost = true; /* this way we follow wl, assume it is true */
+	nphy->txrx_chain = 2; /* sth different than 0 and 1 for now */
+	nphy->phyrxchain = 3; /* to avoid b43_nphy_set_rx_core_state like wl */
+	nphy->perical = 2; /* avoid additional rssi cal on init (like wl) */
 }
 
 static void b43_nphy_op_free(struct b43_wldev *dev)
@@ -3500,6 +3812,15 @@ static void b43_nphy_op_write(struct b43
 	b43_write16(dev, B43_MMIO_PHY_DATA, value);
 }
 
+static void b43_nphy_op_maskset(struct b43_wldev *dev, u16 reg, u16 mask,
+				 u16 set)
+{
+	check_phyreg(dev, reg);
+	b43_write16(dev, B43_MMIO_PHY_CONTROL, reg);
+	b43_write16(dev, B43_MMIO_PHY_DATA,
+		    (b43_read16(dev, B43_MMIO_PHY_DATA) & mask) | set);
+}
+
 static u16 b43_nphy_op_radio_read(struct b43_wldev *dev, u16 reg)
 {
 	/* Register 1 is a 32-bit register. */
@@ -3524,8 +3845,6 @@ static void b43_nphy_op_radio_write(stru
 static void b43_nphy_op_software_rfkill(struct b43_wldev *dev,
 					bool blocked)
 {
-	struct b43_phy_n *nphy = dev->phy.n;
-
 	if (b43_read32(dev, B43_MMIO_MACCTL) & B43_MACCTL_ENABLED)
 		b43err(dev->wl, "MAC not suspended\n");
 
@@ -3596,6 +3915,7 @@ const struct b43_phy_operations b43_phyo
 	.init			= b43_nphy_op_init,
 	.phy_read		= b43_nphy_op_read,
 	.phy_write		= b43_nphy_op_write,
+	.phy_maskset		= b43_nphy_op_maskset,
 	.radio_read		= b43_nphy_op_radio_read,
 	.radio_write		= b43_nphy_op_radio_write,
 	.software_rfkill	= b43_nphy_op_software_rfkill,
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/b43/phy_n.h linux-libre-2.6.38-gnu1/drivers/net/wireless/b43/phy_n.h
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/b43/phy_n.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/b43/phy_n.h	2011-03-14 21:20:32.000000000 -0400
@@ -782,7 +782,7 @@ struct b43_phy_n {
 	u16 mphase_txcal_numcmds;
 	u16 mphase_txcal_bestcoeffs[11];
 
-	u8 txpwrctrl;
+	bool txpwrctrl;
 	u16 txcal_bbmult;
 	u16 txiqlocal_bestc[11];
 	bool txiqlocal_coeffsvalid;
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/b43/radio_2055.c linux-libre-2.6.38-gnu1/drivers/net/wireless/b43/radio_2055.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/b43/radio_2055.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/b43/radio_2055.c	2011-03-14 21:20:32.000000000 -0400
@@ -244,7 +244,7 @@ static const struct b2055_inittab_entry
   [0xCB]			= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
   [0xCC]			= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
   [B2055_C1_LNA_GAINBST]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
-  [0xCE]			= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [0xCE]			= { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
   [0xCF]			= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
   [0xD0]			= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
   [0xD1]			= { .ghz5 = 0x0018, .ghz2 = 0x0018, NOUPLOAD, },
@@ -256,7 +256,7 @@ static const struct b2055_inittab_entry
   [0xD7]			= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
   [0xD8]			= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
   [B2055_C2_LNA_GAINBST]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
-  [0xDA]			= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [0xDA]			= { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
   [0xDB]			= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
   [0xDC]			= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
   [0xDD]			= { .ghz5 = 0x0018, .ghz2 = 0x0018, NOUPLOAD, },
@@ -304,178 +304,178 @@ static const struct b43_nphy_channeltab_
   {	.channel		= 184,
 	.freq			= 4920, /* MHz */
 	.unk2			= 3280,
-	RADIOREGS(0x71, 0x01, 0xEC, 0x0F, 0xFF, 0x01, 0x04, 0x0A,
+	RADIOREGS(0x71, 0xEC, 0x01, 0x0F, 0xFF, 0x01, 0x04, 0x0A,
 		  0x00, 0x8F, 0xFF, 0xFF, 0xFF, 0x00, 0x0F, 0x0F,
 		  0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F),
-	PHYREGS(0xB407, 0xB007, 0xAC07, 0x1402, 0x1502, 0x1602),
+	PHYREGS(0x07B4, 0x07B0, 0x07AC, 0x0214, 0x0215, 0x0216),
   },
   {	.channel		= 186,
 	.freq			= 4930, /* MHz */
 	.unk2			= 3287,
-	RADIOREGS(0x71, 0x01, 0xED, 0x0F, 0xFF, 0x01, 0x04, 0x0A,
+	RADIOREGS(0x71, 0xED, 0x01, 0x0F, 0xFF, 0x01, 0x04, 0x0A,
 		  0x00, 0x8F, 0xFF, 0xFF, 0xFF, 0x00, 0x0F, 0x0F,
 		  0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F),
-	PHYREGS(0xB807, 0xB407, 0xB007, 0x1302, 0x1402, 0x1502),
+	PHYREGS(0x07B8, 0x07B4, 0x07B0, 0x0213, 0x0214, 0x0215),
   },
   {	.channel		= 188,
 	.freq			= 4940, /* MHz */
 	.unk2			= 3293,
-	RADIOREGS(0x71, 0x01, 0xEE, 0x0F, 0xFF, 0x01, 0x04, 0x0A,
+	RADIOREGS(0x71, 0xEE, 0x01, 0x0F, 0xFF, 0x01, 0x04, 0x0A,
 		  0x00, 0x8F, 0xEE, 0xEE, 0xFF, 0x00, 0x0F, 0x0F,
 		  0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F),
-	PHYREGS(0xBC07, 0xB807, 0xB407, 0x1202, 0x1302, 0x1402),
+	PHYREGS(0x07BC, 0x07B8, 0x07B4, 0x0212, 0x0213, 0x0214),
   },
   {	.channel		= 190,
 	.freq			= 4950, /* MHz */
 	.unk2			= 3300,
-	RADIOREGS(0x71, 0x01, 0xEF, 0x0F, 0xFF, 0x01, 0x04, 0x0A,
+	RADIOREGS(0x71, 0xEF, 0x01, 0x0F, 0xFF, 0x01, 0x04, 0x0A,
 		  0x00, 0x8F, 0xEE, 0xEE, 0xFF, 0x00, 0x0F, 0x0F,
 		  0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F),
-	PHYREGS(0xC007, 0xBC07, 0xB807, 0x1102, 0x1202, 0x1302),
+	PHYREGS(0x07C0, 0x07BC, 0x07B8, 0x0211, 0x0212, 0x0213),
   },
   {	.channel		= 192,
 	.freq			= 4960, /* MHz */
 	.unk2			= 3307,
-	RADIOREGS(0x71, 0x01, 0xF0, 0x0F, 0xFF, 0x01, 0x04, 0x0A,
+	RADIOREGS(0x71, 0xF0, 0x01, 0x0F, 0xFF, 0x01, 0x04, 0x0A,
 		  0x00, 0x8F, 0xEE, 0xEE, 0xFF, 0x00, 0x0F, 0x0F,
 		  0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F),
-	PHYREGS(0xC407, 0xC007, 0xBC07, 0x0F02, 0x1102, 0x1202),
+	PHYREGS(0x07C4, 0x07C0, 0x07BC, 0x020F, 0x0211, 0x0212),
   },
   {	.channel		= 194,
 	.freq			= 4970, /* MHz */
 	.unk2			= 3313,
-	RADIOREGS(0x71, 0x01, 0xF1, 0x0F, 0xFF, 0x01, 0x04, 0x0A,
+	RADIOREGS(0x71, 0xF1, 0x01, 0x0F, 0xFF, 0x01, 0x04, 0x0A,
 		  0x00, 0x8F, 0xEE, 0xEE, 0xFF, 0x00, 0x0F, 0x0F,
 		  0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F),
-	PHYREGS(0xC807, 0xC407, 0xC007, 0x0E02, 0x0F02, 0x1102),
+	PHYREGS(0x07C8, 0x07C4, 0x07C0, 0x020E, 0x020F, 0x0211),
   },
   {	.channel		= 196,
 	.freq			= 4980, /* MHz */
 	.unk2			= 3320,
-	RADIOREGS(0x71, 0x01, 0xF2, 0x0E, 0xFF, 0x01, 0x04, 0x0A,
+	RADIOREGS(0x71, 0xF2, 0x01, 0x0E, 0xFF, 0x01, 0x04, 0x0A,
 		  0x00, 0x8F, 0xDD, 0xDD, 0xFF, 0x00, 0x0F, 0x0F,
 		  0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F),
-	PHYREGS(0xCC07, 0xC807, 0xC407, 0x0D02, 0x0E02, 0x0F02),
+	PHYREGS(0x07CC, 0x07C8, 0x07C4, 0x020D, 0x020E, 0x020F),
   },
   {	.channel		= 198,
 	.freq			= 4990, /* MHz */
 	.unk2			= 3327,
-	RADIOREGS(0x71, 0x01, 0xF3, 0x0E, 0xFF, 0x01, 0x04, 0x0A,
+	RADIOREGS(0x71, 0xF3, 0x01, 0x0E, 0xFF, 0x01, 0x04, 0x0A,
 		  0x00, 0x8F, 0xDD, 0xDD, 0xFF, 0x00, 0x0F, 0x0F,
 		  0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F),
-	PHYREGS(0xD007, 0xCC07, 0xC807, 0x0C02, 0x0D02, 0x0E02),
+	PHYREGS(0x07D0, 0x07CC, 0x07C8, 0x020C, 0x020D, 0x020E),
   },
   {	.channel		= 200,
 	.freq			= 5000, /* MHz */
 	.unk2			= 3333,
-	RADIOREGS(0x71, 0x01, 0xF4, 0x0E, 0xFF, 0x01, 0x04, 0x0A,
+	RADIOREGS(0x71, 0xF4, 0x01, 0x0E, 0xFF, 0x01, 0x04, 0x0A,
 		  0x00, 0x8F, 0xDD, 0xDD, 0xFF, 0x00, 0x0F, 0x0F,
 		  0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F),
-	PHYREGS(0xD407, 0xD007, 0xCC07, 0x0B02, 0x0C02, 0x0D02),
+	PHYREGS(0x07D4, 0x07D0, 0x07CC, 0x020B, 0x020C, 0x020D),
   },
   {	.channel		= 202,
 	.freq			= 5010, /* MHz */
 	.unk2			= 3340,
-	RADIOREGS(0x71, 0x01, 0xF5, 0x0E, 0xFF, 0x01, 0x04, 0x0A,
+	RADIOREGS(0x71, 0xF5, 0x01, 0x0E, 0xFF, 0x01, 0x04, 0x0A,
 		  0x00, 0x8F, 0xDD, 0xDD, 0xFF, 0x00, 0x0F, 0x0F,
 		  0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F),
-	PHYREGS(0xD807, 0xD407, 0xD007, 0x0A02, 0x0B02, 0x0C02),
+	PHYREGS(0x07D8, 0x07D4, 0x07D0, 0x020A, 0x020B, 0x020C),
   },
   {	.channel		= 204,
 	.freq			= 5020, /* MHz */
 	.unk2			= 3347,
-	RADIOREGS(0x71, 0x01, 0xF6, 0x0E, 0xF7, 0x01, 0x04, 0x0A,
+	RADIOREGS(0x71, 0xF6, 0x01, 0x0E, 0xF7, 0x01, 0x04, 0x0A,
 		  0x00, 0x8F, 0xCC, 0xCC, 0xFF, 0x00, 0x0F, 0x0F,
 		  0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F),
-	PHYREGS(0xDC07, 0xD807, 0xD407, 0x0902, 0x0A02, 0x0B02),
+	PHYREGS(0x07DC, 0x07D8, 0x07D4, 0x0209, 0x020A, 0x020B),
   },
   {	.channel		= 206,
 	.freq			= 5030, /* MHz */
 	.unk2			= 3353,
-	RADIOREGS(0x71, 0x01, 0xF7, 0x0E, 0xF7, 0x01, 0x04, 0x0A,
+	RADIOREGS(0x71, 0xF7, 0x01, 0x0E, 0xF7, 0x01, 0x04, 0x0A,
 		  0x00, 0x8F, 0xCC, 0xCC, 0xFF, 0x00, 0x0F, 0x0F,
 		  0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F),
-	PHYREGS(0xE007, 0xDC07, 0xD807, 0x0802, 0x0902, 0x0A02),
+	PHYREGS(0x07E0, 0x07DC, 0x07D8, 0x0208, 0x0209, 0x020A),
   },
   {	.channel		= 208,
 	.freq			= 5040, /* MHz */
 	.unk2			= 3360,
-	RADIOREGS(0x71, 0x01, 0xF8, 0x0D, 0xEF, 0x01, 0x04, 0x0A,
+	RADIOREGS(0x71, 0xF8, 0x01, 0x0D, 0xEF, 0x01, 0x04, 0x0A,
 		  0x00, 0x8F, 0xCC, 0xCC, 0xFF, 0x00, 0x0F, 0x0F,
 		  0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F),
-	PHYREGS(0xE407, 0xE007, 0xDC07, 0x0702, 0x0802, 0x0902),
+	PHYREGS(0x07E4, 0x07E0, 0x07DC, 0x0207, 0x0208, 0x0209),
   },
   {	.channel		= 210,
 	.freq			= 5050, /* MHz */
 	.unk2			= 3367,
-	RADIOREGS(0x71, 0x01, 0xF9, 0x0D, 0xEF, 0x01, 0x04, 0x0A,
+	RADIOREGS(0x71, 0xF9, 0x01, 0x0D, 0xEF, 0x01, 0x04, 0x0A,
 		  0x00, 0x8F, 0xCC, 0xCC, 0xFF, 0x00, 0x0F, 0x0F,
 		  0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F),
-	PHYREGS(0xE807, 0xE407, 0xE007, 0x0602, 0x0702, 0x0802),
+	PHYREGS(0x07E8, 0x07E4, 0x07E0, 0x0206, 0x0207, 0x0208),
   },
   {	.channel		= 212,
 	.freq			= 5060, /* MHz */
 	.unk2			= 3373,
-	RADIOREGS(0x71, 0x01, 0xFA, 0x0D, 0xE6, 0x01, 0x04, 0x0A,
+	RADIOREGS(0x71, 0xFA, 0x01, 0x0D, 0xE6, 0x01, 0x04, 0x0A,
 		  0x00, 0x8F, 0xBB, 0xBB, 0xFF, 0x00, 0x0E, 0x0F,
 		  0x8E, 0xFF, 0x00, 0x0E, 0x0F, 0x8E),
-	PHYREGS(0xEC07, 0xE807, 0xE407, 0x0502, 0x0602, 0x0702),
+	PHYREGS(0x07EC, 0x07E8, 0x07E4, 0x0205, 0x0206, 0x0207),
   },
   {	.channel		= 214,
 	.freq			= 5070, /* MHz */
 	.unk2			= 3380,
-	RADIOREGS(0x71, 0x01, 0xFB, 0x0D, 0xE6, 0x01, 0x04, 0x0A,
+	RADIOREGS(0x71, 0xFB, 0x01, 0x0D, 0xE6, 0x01, 0x04, 0x0A,
 		  0x00, 0x8F, 0xBB, 0xBB, 0xFF, 0x00, 0x0E, 0x0F,
 		  0x8E, 0xFF, 0x00, 0x0E, 0x0F, 0x8E),
-	PHYREGS(0xF007, 0xEC07, 0xE807, 0x0402, 0x0502, 0x0602),
+	PHYREGS(0x07F0, 0x07EC, 0x07E8, 0x0204, 0x0205, 0x0206),
   },
   {	.channel		= 216,
 	.freq			= 5080, /* MHz */
 	.unk2			= 3387,
-	RADIOREGS(0x71, 0x01, 0xFC, 0x0D, 0xDE, 0x01, 0x04, 0x0A,
+	RADIOREGS(0x71, 0xFC, 0x01, 0x0D, 0xDE, 0x01, 0x04, 0x0A,
 		  0x00, 0x8E, 0xBB, 0xBB, 0xEE, 0x00, 0x0E, 0x0F,
 		  0x8D, 0xEE, 0x00, 0x0E, 0x0F, 0x8D),
-	PHYREGS(0xF407, 0xF007, 0xEC07, 0x0302, 0x0402, 0x0502),
+	PHYREGS(0x07F4, 0x07F0, 0x07EC, 0x0203, 0x0204, 0x0205),
   },
   {	.channel		= 218,
 	.freq			= 5090, /* MHz */
 	.unk2			= 3393,
-	RADIOREGS(0x71, 0x01, 0xFD, 0x0D, 0xDE, 0x01, 0x04, 0x0A,
+	RADIOREGS(0x71, 0xFD, 0x01, 0x0D, 0xDE, 0x01, 0x04, 0x0A,
 		  0x00, 0x8E, 0xBB, 0xBB, 0xEE, 0x00, 0x0E, 0x0F,
 		  0x8D, 0xEE, 0x00, 0x0E, 0x0F, 0x8D),
-	PHYREGS(0xF807, 0xF407, 0xF007, 0x0202, 0x0302, 0x0402),
+	PHYREGS(0x07F8, 0x07F4, 0x07F0, 0x0202, 0x0203, 0x0204),
   },
   {	.channel		= 220,
 	.freq			= 5100, /* MHz */
 	.unk2			= 3400,
-	RADIOREGS(0x71, 0x01, 0xFE, 0x0C, 0xD6, 0x01, 0x04, 0x0A,
+	RADIOREGS(0x71, 0xFE, 0x01, 0x0C, 0xD6, 0x01, 0x04, 0x0A,
 		  0x00, 0x8E, 0xAA, 0xAA, 0xEE, 0x00, 0x0D, 0x0F,
 		  0x8D, 0xEE, 0x00, 0x0D, 0x0F, 0x8D),
-	PHYREGS(0xFC07, 0xF807, 0xF407, 0x0102, 0x0202, 0x0302),
+	PHYREGS(0x07FC, 0x07F8, 0x07F4, 0x0201, 0x0202, 0x0203),
   },
   {	.channel		= 222,
 	.freq			= 5110, /* MHz */
 	.unk2			= 3407,
-	RADIOREGS(0x71, 0x01, 0xFF, 0x0C, 0xD6, 0x01, 0x04, 0x0A,
+	RADIOREGS(0x71, 0xFF, 0x01, 0x0C, 0xD6, 0x01, 0x04, 0x0A,
 		  0x00, 0x8E, 0xAA, 0xAA, 0xEE, 0x00, 0x0D, 0x0F,
 		  0x8D, 0xEE, 0x00, 0x0D, 0x0F, 0x8D),
-	PHYREGS(0x0008, 0xFC07, 0xF807, 0x0002, 0x0102, 0x0202),
+	PHYREGS(0x0800, 0x07FC, 0x07F8, 0x0200, 0x0201, 0x0202),
   },
   {	.channel		= 224,
 	.freq			= 5120, /* MHz */
 	.unk2			= 3413,
-	RADIOREGS(0x71, 0x02, 0x00, 0x0C, 0xCE, 0x01, 0x04, 0x0A,
+	RADIOREGS(0x71, 0x00, 0x02, 0x0C, 0xCE, 0x01, 0x04, 0x0A,
 		  0x00, 0x8D, 0xAA, 0xAA, 0xDD, 0x00, 0x0D, 0x0F,
 		  0x8C, 0xDD, 0x00, 0x0D, 0x0F, 0x8C),
-	PHYREGS(0x0408, 0x0008, 0xFC07, 0xFF01, 0x0002, 0x0102),
+	PHYREGS(0x0804, 0x0800, 0x07FC, 0x01FF, 0x0200, 0x0201),
   },
   {	.channel		= 226,
 	.freq			= 5130, /* MHz */
 	.unk2			= 3420,
-	RADIOREGS(0x71, 0x02, 0x01, 0x0C, 0xCE, 0x01, 0x04, 0x0A,
+	RADIOREGS(0x71, 0x01, 0x02, 0x0C, 0xCE, 0x01, 0x04, 0x0A,
 		  0x00, 0x8D, 0xAA, 0xAA, 0xDD, 0x00, 0x0D, 0x0F,
 		  0x8C, 0xDD, 0x00, 0x0D, 0x0F, 0x8C),
-	PHYREGS(0x0808, 0x0408, 0x0008, 0xFE01, 0xFF01, 0x0002),
+	PHYREGS(0x0808, 0x0804, 0x0800, 0x01FE, 0x01FF, 0x0200),
   },
   {	.channel		= 228,
 	.freq			= 5140, /* MHz */
@@ -483,815 +483,815 @@ static const struct b43_nphy_channeltab_
 	RADIOREGS(0x71, 0x02, 0x02, 0x0C, 0xC6, 0x01, 0x04, 0x0A,
 		  0x00, 0x8D, 0x99, 0x99, 0xDD, 0x00, 0x0C, 0x0E,
 		  0x8B, 0xDD, 0x00, 0x0C, 0x0E, 0x8B),
-	PHYREGS(0x0C08, 0x0808, 0x0408, 0xFD01, 0xFE01, 0xFF01),
+	PHYREGS(0x080C, 0x0808, 0x0804, 0x01FD, 0x01FE, 0x01FF),
   },
   {	.channel		= 32,
 	.freq			= 5160, /* MHz */
 	.unk2			= 3440,
-	RADIOREGS(0x71, 0x02, 0x04, 0x0B, 0xBE, 0x01, 0x04, 0x0A,
+	RADIOREGS(0x71, 0x04, 0x02, 0x0B, 0xBE, 0x01, 0x04, 0x0A,
 		  0x00, 0x8C, 0x99, 0x99, 0xCC, 0x00, 0x0B, 0x0D,
 		  0x8A, 0xCC, 0x00, 0x0B, 0x0D, 0x8A),
-	PHYREGS(0x1408, 0x1008, 0x0C08, 0xFB01, 0xFC01, 0xFD01),
+	PHYREGS(0x0814, 0x0810, 0x080C, 0x01FB, 0x01FC, 0x01FD),
   },
   {	.channel		= 34,
 	.freq			= 5170, /* MHz */
 	.unk2			= 3447,
-	RADIOREGS(0x71, 0x02, 0x05, 0x0B, 0xBE, 0x01, 0x04, 0x0A,
+	RADIOREGS(0x71, 0x05, 0x02, 0x0B, 0xBE, 0x01, 0x04, 0x0A,
 		  0x00, 0x8C, 0x99, 0x99, 0xCC, 0x00, 0x0B, 0x0D,
 		  0x8A, 0xCC, 0x00, 0x0B, 0x0D, 0x8A),
-	PHYREGS(0x1808, 0x1408, 0x1008, 0xFA01, 0xFB01, 0xFC01),
+	PHYREGS(0x0818, 0x0814, 0x0810, 0x01FA, 0x01FB, 0x01FC),
   },
   {	.channel		= 36,
 	.freq			= 5180, /* MHz */
 	.unk2			= 3453,
-	RADIOREGS(0x71, 0x02, 0x06, 0x0B, 0xB6, 0x01, 0x04, 0x0A,
+	RADIOREGS(0x71, 0x06, 0x02, 0x0B, 0xB6, 0x01, 0x04, 0x0A,
 		  0x00, 0x8C, 0x88, 0x88, 0xCC, 0x00, 0x0B, 0x0C,
 		  0x89, 0xCC, 0x00, 0x0B, 0x0C, 0x89),
-	PHYREGS(0x1C08, 0x1808, 0x1408, 0xF901, 0xFA01, 0xFB01),
+	PHYREGS(0x081C, 0x0818, 0x0814, 0x01F9, 0x01FA, 0x01FB),
   },
   {	.channel		= 38,
 	.freq			= 5190, /* MHz */
 	.unk2			= 3460,
-	RADIOREGS(0x71, 0x02, 0x07, 0x0B, 0xB6, 0x01, 0x04, 0x0A,
+	RADIOREGS(0x71, 0x07, 0x02, 0x0B, 0xB6, 0x01, 0x04, 0x0A,
 		  0x00, 0x8C, 0x88, 0x88, 0xCC, 0x00, 0x0B, 0x0C,
 		  0x89, 0xCC, 0x00, 0x0B, 0x0C, 0x89),
-	PHYREGS(0x2008, 0x1C08, 0x1808, 0xF801, 0xF901, 0xFA01),
+	PHYREGS(0x0820, 0x081C, 0x0818, 0x01F8, 0x01F9, 0x01FA),
   },
   {	.channel		= 40,
 	.freq			= 5200, /* MHz */
 	.unk2			= 3467,
-	RADIOREGS(0x71, 0x02, 0x08, 0x0B, 0xAF, 0x01, 0x04, 0x0A,
+	RADIOREGS(0x71, 0x08, 0x02, 0x0B, 0xAF, 0x01, 0x04, 0x0A,
 		  0x00, 0x8B, 0x88, 0x88, 0xBB, 0x00, 0x0A, 0x0B,
 		  0x89, 0xBB, 0x00, 0x0A, 0x0B, 0x89),
-	PHYREGS(0x2408, 0x2008, 0x1C08, 0xF701, 0xF801, 0xF901),
+	PHYREGS(0x0824, 0x0820, 0x081C, 0x01F7, 0x01F8, 0x01F9),
   },
   {	.channel		= 42,
 	.freq			= 5210, /* MHz */
 	.unk2			= 3473,
-	RADIOREGS(0x71, 0x02, 0x09, 0x0B, 0xAF, 0x01, 0x04, 0x0A,
+	RADIOREGS(0x71, 0x09, 0x02, 0x0B, 0xAF, 0x01, 0x04, 0x0A,
 		  0x00, 0x8B, 0x88, 0x88, 0xBB, 0x00, 0x0A, 0x0B,
 		  0x89, 0xBB, 0x00, 0x0A, 0x0B, 0x89),
-	PHYREGS(0x2808, 0x2408, 0x2008, 0xF601, 0xF701, 0xF801),
+	PHYREGS(0x0828, 0x0824, 0x0820, 0x01F6, 0x01F7, 0x01F8),
   },
   {	.channel		= 44,
 	.freq			= 5220, /* MHz */
 	.unk2			= 3480,
-	RADIOREGS(0x71, 0x02, 0x0A, 0x0A, 0xA7, 0x01, 0x04, 0x0A,
+	RADIOREGS(0x71, 0x0A, 0x02, 0x0A, 0xA7, 0x01, 0x04, 0x0A,
 		  0x00, 0x8B, 0x77, 0x77, 0xBB, 0x00, 0x09, 0x0A,
 		  0x88, 0xBB, 0x00, 0x09, 0x0A, 0x88),
-	PHYREGS(0x2C08, 0x2808, 0x2408, 0xF501, 0xF601, 0xF701),
+	PHYREGS(0x082C, 0x0828, 0x0824, 0x01F5, 0x01F6, 0x01F7),
   },
   {	.channel		= 46,
 	.freq			= 5230, /* MHz */
 	.unk2			= 3487,
-	RADIOREGS(0x71, 0x02, 0x0B, 0x0A, 0xA7, 0x01, 0x04, 0x0A,
+	RADIOREGS(0x71, 0x0B, 0x02, 0x0A, 0xA7, 0x01, 0x04, 0x0A,
 		  0x00, 0x8B, 0x77, 0x77, 0xBB, 0x00, 0x09, 0x0A,
 		  0x88, 0xBB, 0x00, 0x09, 0x0A, 0x88),
-	PHYREGS(0x3008, 0x2C08, 0x2808, 0xF401, 0xF501, 0xF601),
+	PHYREGS(0x0830, 0x082C, 0x0828, 0x01F4, 0x01F5, 0x01F6),
   },
   {	.channel		= 48,
 	.freq			= 5240, /* MHz */
 	.unk2			= 3493,
-	RADIOREGS(0x71, 0x02, 0x0C, 0x0A, 0xA0, 0x01, 0x04, 0x0A,
+	RADIOREGS(0x71, 0x0C, 0x02, 0x0A, 0xA0, 0x01, 0x04, 0x0A,
 		  0x00, 0x8A, 0x77, 0x77, 0xAA, 0x00, 0x09, 0x0A,
 		  0x87, 0xAA, 0x00, 0x09, 0x0A, 0x87),
-	PHYREGS(0x3408, 0x3008, 0x2C08, 0xF301, 0xF401, 0xF501),
+	PHYREGS(0x0834, 0x0830, 0x082C, 0x01F3, 0x01F4, 0x01F5),
   },
   {	.channel		= 50,
 	.freq			= 5250, /* MHz */
 	.unk2			= 3500,
-	RADIOREGS(0x71, 0x02, 0x0D, 0x0A, 0xA0, 0x01, 0x04, 0x0A,
+	RADIOREGS(0x71, 0x0D, 0x02, 0x0A, 0xA0, 0x01, 0x04, 0x0A,
 		  0x00, 0x8A, 0x77, 0x77, 0xAA, 0x00, 0x09, 0x0A,
 		  0x87, 0xAA, 0x00, 0x09, 0x0A, 0x87),
-	PHYREGS(0x3808, 0x3408, 0x3008, 0xF201, 0xF301, 0xF401),
+	PHYREGS(0x0838, 0x0834, 0x0830, 0x01F2, 0x01F3, 0x01F4),
   },
   {	.channel		= 52,
 	.freq			= 5260, /* MHz */
 	.unk2			= 3507,
-	RADIOREGS(0x71, 0x02, 0x0E, 0x0A, 0x98, 0x01, 0x04, 0x0A,
+	RADIOREGS(0x71, 0x0E, 0x02, 0x0A, 0x98, 0x01, 0x04, 0x0A,
 		  0x00, 0x8A, 0x66, 0x66, 0xAA, 0x00, 0x08, 0x09,
 		  0x87, 0xAA, 0x00, 0x08, 0x09, 0x87),
-	PHYREGS(0x3C08, 0x3808, 0x3408, 0xF101, 0xF201, 0xF301),
+	PHYREGS(0x083C, 0x0838, 0x0834, 0x01F1, 0x01F2, 0x01F3),
   },
   {	.channel		= 54,
 	.freq			= 5270, /* MHz */
 	.unk2			= 3513,
-	RADIOREGS(0x71, 0x02, 0x0F, 0x0A, 0x98, 0x01, 0x04, 0x0A,
+	RADIOREGS(0x71, 0x0F, 0x02, 0x0A, 0x98, 0x01, 0x04, 0x0A,
 		  0x00, 0x8A, 0x66, 0x66, 0xAA, 0x00, 0x08, 0x09,
 		  0x87, 0xAA, 0x00, 0x08, 0x09, 0x87),
-	PHYREGS(0x4008, 0x3C08, 0x3808, 0xF001, 0xF101, 0xF201),
+	PHYREGS(0x0840, 0x083C, 0x0838, 0x01F0, 0x01F1, 0x01F2),
   },
   {	.channel		= 56,
 	.freq			= 5280, /* MHz */
 	.unk2			= 3520,
-	RADIOREGS(0x71, 0x02, 0x10, 0x09, 0x91, 0x01, 0x04, 0x0A,
+	RADIOREGS(0x71, 0x10, 0x02, 0x09, 0x91, 0x01, 0x04, 0x0A,
 		  0x00, 0x89, 0x66, 0x66, 0x99, 0x00, 0x08, 0x08,
 		  0x86, 0x99, 0x00, 0x08, 0x08, 0x86),
-	PHYREGS(0x4408, 0x4008, 0x3C08, 0xF001, 0xF001, 0xF101),
+	PHYREGS(0x0844, 0x0840, 0x083C, 0x01F0, 0x01F0, 0x01F1),
   },
   {	.channel		= 58,
 	.freq			= 5290, /* MHz */
 	.unk2			= 3527,
-	RADIOREGS(0x71, 0x02, 0x11, 0x09, 0x91, 0x01, 0x04, 0x0A,
+	RADIOREGS(0x71, 0x11, 0x02, 0x09, 0x91, 0x01, 0x04, 0x0A,
 		  0x00, 0x89, 0x66, 0x66, 0x99, 0x00, 0x08, 0x08,
 		  0x86, 0x99, 0x00, 0x08, 0x08, 0x86),
-	PHYREGS(0x4808, 0x4408, 0x4008, 0xEF01, 0xF001, 0xF001),
+	PHYREGS(0x0848, 0x0844, 0x0840, 0x01EF, 0x01F0, 0x01F0),
   },
   {	.channel		= 60,
 	.freq			= 5300, /* MHz */
 	.unk2			= 3533,
-	RADIOREGS(0x71, 0x02, 0x12, 0x09, 0x8A, 0x01, 0x04, 0x0A,
+	RADIOREGS(0x71, 0x12, 0x02, 0x09, 0x8A, 0x01, 0x04, 0x0A,
 		  0x00, 0x89, 0x55, 0x55, 0x99, 0x00, 0x08, 0x07,
 		  0x85, 0x99, 0x00, 0x08, 0x07, 0x85),
-	PHYREGS(0x4C08, 0x4808, 0x4408, 0xEE01, 0xEF01, 0xF001),
+	PHYREGS(0x084C, 0x0848, 0x0844, 0x01EE, 0x01EF, 0x01F0),
   },
   {	.channel		= 62,
 	.freq			= 5310, /* MHz */
 	.unk2			= 3540,
-	RADIOREGS(0x71, 0x02, 0x13, 0x09, 0x8A, 0x01, 0x04, 0x0A,
+	RADIOREGS(0x71, 0x13, 0x02, 0x09, 0x8A, 0x01, 0x04, 0x0A,
 		  0x00, 0x89, 0x55, 0x55, 0x99, 0x00, 0x08, 0x07,
 		  0x85, 0x99, 0x00, 0x08, 0x07, 0x85),
-	PHYREGS(0x5008, 0x4C08, 0x4808, 0xED01, 0xEE01, 0xEF01),
+	PHYREGS(0x0850, 0x084C, 0x0848, 0x01ED, 0x01EE, 0x01EF),
   },
   {	.channel		= 64,
 	.freq			= 5320, /* MHz */
 	.unk2			= 3547,
-	RADIOREGS(0x71, 0x02, 0x14, 0x09, 0x83, 0x01, 0x04, 0x0A,
+	RADIOREGS(0x71, 0x14, 0x02, 0x09, 0x83, 0x01, 0x04, 0x0A,
 		  0x00, 0x88, 0x55, 0x55, 0x88, 0x00, 0x07, 0x07,
 		  0x84, 0x88, 0x00, 0x07, 0x07, 0x84),
-	PHYREGS(0x5408, 0x5008, 0x4C08, 0xEC01, 0xED01, 0xEE01),
+	PHYREGS(0x0854, 0x0850, 0x084C, 0x01EC, 0x01ED, 0x01EE),
   },
   {	.channel		= 66,
 	.freq			= 5330, /* MHz */
 	.unk2			= 3553,
-	RADIOREGS(0x71, 0x02, 0x15, 0x09, 0x83, 0x01, 0x04, 0x0A,
+	RADIOREGS(0x71, 0x15, 0x02, 0x09, 0x83, 0x01, 0x04, 0x0A,
 		  0x00, 0x88, 0x55, 0x55, 0x88, 0x00, 0x07, 0x07,
 		  0x84, 0x88, 0x00, 0x07, 0x07, 0x84),
-	PHYREGS(0x5808, 0x5408, 0x5008, 0xEB01, 0xEC01, 0xED01),
+	PHYREGS(0x0858, 0x0854, 0x0850, 0x01EB, 0x01EC, 0x01ED),
   },
   {	.channel		= 68,
 	.freq			= 5340, /* MHz */
 	.unk2			= 3560,
-	RADIOREGS(0x71, 0x02, 0x16, 0x08, 0x7C, 0x01, 0x04, 0x0A,
+	RADIOREGS(0x71, 0x16, 0x02, 0x08, 0x7C, 0x01, 0x04, 0x0A,
 		  0x00, 0x88, 0x44, 0x44, 0x88, 0x00, 0x07, 0x06,
 		  0x84, 0x88, 0x00, 0x07, 0x06, 0x84),
-	PHYREGS(0x5C08, 0x5808, 0x5408, 0xEA01, 0xEB01, 0xEC01),
+	PHYREGS(0x085C, 0x0858, 0x0854, 0x01EA, 0x01EB, 0x01EC),
   },
   {	.channel		= 70,
 	.freq			= 5350, /* MHz */
 	.unk2			= 3567,
-	RADIOREGS(0x71, 0x02, 0x17, 0x08, 0x7C, 0x01, 0x04, 0x0A,
+	RADIOREGS(0x71, 0x17, 0x02, 0x08, 0x7C, 0x01, 0x04, 0x0A,
 		  0x00, 0x88, 0x44, 0x44, 0x88, 0x00, 0x07, 0x06,
 		  0x84, 0x88, 0x00, 0x07, 0x06, 0x84),
-	PHYREGS(0x6008, 0x5C08, 0x5808, 0xE901, 0xEA01, 0xEB01),
+	PHYREGS(0x0860, 0x085C, 0x0858, 0x01E9, 0x01EA, 0x01EB),
   },
   {	.channel		= 72,
 	.freq			= 5360, /* MHz */
 	.unk2			= 3573,
-	RADIOREGS(0x71, 0x02, 0x18, 0x08, 0x75, 0x01, 0x04, 0x0A,
+	RADIOREGS(0x71, 0x18, 0x02, 0x08, 0x75, 0x01, 0x04, 0x0A,
 		  0x00, 0x87, 0x44, 0x44, 0x77, 0x00, 0x06, 0x05,
 		  0x83, 0x77, 0x00, 0x06, 0x05, 0x83),
-	PHYREGS(0x6408, 0x6008, 0x5C08, 0xE801, 0xE901, 0xEA01),
+	PHYREGS(0x0864, 0x0860, 0x085C, 0x01E8, 0x01E9, 0x01EA),
   },
   {	.channel		= 74,
 	.freq			= 5370, /* MHz */
 	.unk2			= 3580,
-	RADIOREGS(0x71, 0x02, 0x19, 0x08, 0x75, 0x01, 0x04, 0x0A,
+	RADIOREGS(0x71, 0x19, 0x02, 0x08, 0x75, 0x01, 0x04, 0x0A,
 		  0x00, 0x87, 0x44, 0x44, 0x77, 0x00, 0x06, 0x05,
 		  0x83, 0x77, 0x00, 0x06, 0x05, 0x83),
-	PHYREGS(0x6808, 0x6408, 0x6008, 0xE701, 0xE801, 0xE901),
+	PHYREGS(0x0868, 0x0864, 0x0860, 0x01E7, 0x01E8, 0x01E9),
   },
   {	.channel		= 76,
 	.freq			= 5380, /* MHz */
 	.unk2			= 3587,
-	RADIOREGS(0x71, 0x02, 0x1A, 0x08, 0x6E, 0x01, 0x04, 0x0A,
+	RADIOREGS(0x71, 0x1A, 0x02, 0x08, 0x6E, 0x01, 0x04, 0x0A,
 		  0x00, 0x87, 0x33, 0x33, 0x77, 0x00, 0x06, 0x04,
 		  0x82, 0x77, 0x00, 0x06, 0x04, 0x82),
-	PHYREGS(0x6C08, 0x6808, 0x6408, 0xE601, 0xE701, 0xE801),
+	PHYREGS(0x086C, 0x0868, 0x0864, 0x01E6, 0x01E7, 0x01E8),
   },
   {	.channel		= 78,
 	.freq			= 5390, /* MHz */
 	.unk2			= 3593,
-	RADIOREGS(0x71, 0x02, 0x1B, 0x08, 0x6E, 0x01, 0x04, 0x0A,
+	RADIOREGS(0x71, 0x1B, 0x02, 0x08, 0x6E, 0x01, 0x04, 0x0A,
 		  0x00, 0x87, 0x33, 0x33, 0x77, 0x00, 0x06, 0x04,
 		  0x82, 0x77, 0x00, 0x06, 0x04, 0x82),
-	PHYREGS(0x7008, 0x6C08, 0x6808, 0xE501, 0xE601, 0xE701),
+	PHYREGS(0x0870, 0x086C, 0x0868, 0x01E5, 0x01E6, 0x01E7),
   },
   {	.channel		= 80,
 	.freq			= 5400, /* MHz */
 	.unk2			= 3600,
-	RADIOREGS(0x71, 0x02, 0x1C, 0x07, 0x67, 0x01, 0x04, 0x0A,
+	RADIOREGS(0x71, 0x1C, 0x02, 0x07, 0x67, 0x01, 0x04, 0x0A,
 		  0x00, 0x86, 0x33, 0x33, 0x66, 0x00, 0x05, 0x04,
 		  0x81, 0x66, 0x00, 0x05, 0x04, 0x81),
-	PHYREGS(0x7408, 0x7008, 0x6C08, 0xE501, 0xE501, 0xE601),
+	PHYREGS(0x0874, 0x0870, 0x086C, 0x01E5, 0x01E5, 0x01E6),
   },
   {	.channel		= 82,
 	.freq			= 5410, /* MHz */
 	.unk2			= 3607,
-	RADIOREGS(0x71, 0x02, 0x1D, 0x07, 0x67, 0x01, 0x04, 0x0A,
+	RADIOREGS(0x71, 0x1D, 0x02, 0x07, 0x67, 0x01, 0x04, 0x0A,
 		  0x00, 0x86, 0x33, 0x33, 0x66, 0x00, 0x05, 0x04,
 		  0x81, 0x66, 0x00, 0x05, 0x04, 0x81),
-	PHYREGS(0x7808, 0x7408, 0x7008, 0xE401, 0xE501, 0xE501),
+	PHYREGS(0x0878, 0x0874, 0x0870, 0x01E4, 0x01E5, 0x01E5),
   },
   {	.channel		= 84,
 	.freq			= 5420, /* MHz */
 	.unk2			= 3613,
-	RADIOREGS(0x71, 0x02, 0x1E, 0x07, 0x61, 0x01, 0x04, 0x0A,
+	RADIOREGS(0x71, 0x1E, 0x02, 0x07, 0x61, 0x01, 0x04, 0x0A,
 		  0x00, 0x86, 0x22, 0x22, 0x66, 0x00, 0x05, 0x03,
 		  0x80, 0x66, 0x00, 0x05, 0x03, 0x80),
-	PHYREGS(0x7C08, 0x7808, 0x7408, 0xE301, 0xE401, 0xE501),
+	PHYREGS(0x087C, 0x0878, 0x0874, 0x01E3, 0x01E4, 0x01E5),
   },
   {	.channel		= 86,
 	.freq			= 5430, /* MHz */
 	.unk2			= 3620,
-	RADIOREGS(0x71, 0x02, 0x1F, 0x07, 0x61, 0x01, 0x04, 0x0A,
+	RADIOREGS(0x71, 0x1F, 0x02, 0x07, 0x61, 0x01, 0x04, 0x0A,
 		  0x00, 0x86, 0x22, 0x22, 0x66, 0x00, 0x05, 0x03,
 		  0x80, 0x66, 0x00, 0x05, 0x03, 0x80),
-	PHYREGS(0x8008, 0x7C08, 0x7808, 0xE201, 0xE301, 0xE401),
+	PHYREGS(0x0880, 0x087C, 0x0878, 0x01E2, 0x01E3, 0x01E4),
   },
   {	.channel		= 88,
 	.freq			= 5440, /* MHz */
 	.unk2			= 3627,
-	RADIOREGS(0x71, 0x02, 0x20, 0x07, 0x5A, 0x01, 0x04, 0x0A,
+	RADIOREGS(0x71, 0x20, 0x02, 0x07, 0x5A, 0x01, 0x04, 0x0A,
 		  0x00, 0x85, 0x22, 0x22, 0x55, 0x00, 0x04, 0x02,
 		  0x80, 0x55, 0x00, 0x04, 0x02, 0x80),
-	PHYREGS(0x8408, 0x8008, 0x7C08, 0xE101, 0xE201, 0xE301),
+	PHYREGS(0x0884, 0x0880, 0x087C, 0x01E1, 0x01E2, 0x01E3),
   },
   {	.channel		= 90,
 	.freq			= 5450, /* MHz */
 	.unk2			= 3633,
-	RADIOREGS(0x71, 0x02, 0x21, 0x07, 0x5A, 0x01, 0x04, 0x0A,
+	RADIOREGS(0x71, 0x21, 0x02, 0x07, 0x5A, 0x01, 0x04, 0x0A,
 		  0x00, 0x85, 0x22, 0x22, 0x55, 0x00, 0x04, 0x02,
 		  0x80, 0x55, 0x00, 0x04, 0x02, 0x80),
-	PHYREGS(0x8808, 0x8408, 0x8008, 0xE001, 0xE101, 0xE201),
+	PHYREGS(0x0888, 0x0884, 0x0880, 0x01E0, 0x01E1, 0x01E2),
   },
   {	.channel		= 92,
 	.freq			= 5460, /* MHz */
 	.unk2			= 3640,
-	RADIOREGS(0x71, 0x02, 0x22, 0x06, 0x53, 0x01, 0x04, 0x0A,
+	RADIOREGS(0x71, 0x22, 0x02, 0x06, 0x53, 0x01, 0x04, 0x0A,
 		  0x00, 0x85, 0x11, 0x11, 0x55, 0x00, 0x04, 0x01,
 		  0x80, 0x55, 0x00, 0x04, 0x01, 0x80),
-	PHYREGS(0x8C08, 0x8808, 0x8408, 0xDF01, 0xE001, 0xE101),
+	PHYREGS(0x088C, 0x0888, 0x0884, 0x01DF, 0x01E0, 0x01E1),
   },
   {	.channel		= 94,
 	.freq			= 5470, /* MHz */
 	.unk2			= 3647,
-	RADIOREGS(0x71, 0x02, 0x23, 0x06, 0x53, 0x01, 0x04, 0x0A,
+	RADIOREGS(0x71, 0x23, 0x02, 0x06, 0x53, 0x01, 0x04, 0x0A,
 		  0x00, 0x85, 0x11, 0x11, 0x55, 0x00, 0x04, 0x01,
 		  0x80, 0x55, 0x00, 0x04, 0x01, 0x80),
-	PHYREGS(0x9008, 0x8C08, 0x8808, 0xDE01, 0xDF01, 0xE001),
+	PHYREGS(0x0890, 0x088C, 0x0888, 0x01DE, 0x01DF, 0x01E0),
   },
   {	.channel		= 96,
 	.freq			= 5480, /* MHz */
 	.unk2			= 3653,
-	RADIOREGS(0x71, 0x02, 0x24, 0x06, 0x4D, 0x01, 0x04, 0x0A,
+	RADIOREGS(0x71, 0x24, 0x02, 0x06, 0x4D, 0x01, 0x04, 0x0A,
 		  0x00, 0x84, 0x11, 0x11, 0x44, 0x00, 0x03, 0x00,
 		  0x80, 0x44, 0x00, 0x03, 0x00, 0x80),
-	PHYREGS(0x9408, 0x9008, 0x8C08, 0xDD01, 0xDE01, 0xDF01),
+	PHYREGS(0x0894, 0x0890, 0x088C, 0x01DD, 0x01DE, 0x01DF),
   },
   {	.channel		= 98,
 	.freq			= 5490, /* MHz */
 	.unk2			= 3660,
-	RADIOREGS(0x71, 0x02, 0x25, 0x06, 0x4D, 0x01, 0x04, 0x0A,
+	RADIOREGS(0x71, 0x25, 0x02, 0x06, 0x4D, 0x01, 0x04, 0x0A,
 		  0x00, 0x84, 0x11, 0x11, 0x44, 0x00, 0x03, 0x00,
 		  0x80, 0x44, 0x00, 0x03, 0x00, 0x80),
-	PHYREGS(0x9808, 0x9408, 0x9008, 0xDD01, 0xDD01, 0xDE01),
+	PHYREGS(0x0898, 0x0894, 0x0890, 0x01DD, 0x01DD, 0x01DE),
   },
   {	.channel		= 100,
 	.freq			= 5500, /* MHz */
 	.unk2			= 3667,
-	RADIOREGS(0x71, 0x02, 0x26, 0x06, 0x47, 0x01, 0x04, 0x0A,
+	RADIOREGS(0x71, 0x26, 0x02, 0x06, 0x47, 0x01, 0x04, 0x0A,
 		  0x00, 0x84, 0x00, 0x00, 0x44, 0x00, 0x03, 0x00,
 		  0x80, 0x44, 0x00, 0x03, 0x00, 0x80),
-	PHYREGS(0x9C08, 0x9808, 0x9408, 0xDC01, 0xDD01, 0xDD01),
+	PHYREGS(0x089C, 0x0898, 0x0894, 0x01DC, 0x01DD, 0x01DD),
   },
   {	.channel		= 102,
 	.freq			= 5510, /* MHz */
 	.unk2			= 3673,
-	RADIOREGS(0x71, 0x02, 0x27, 0x06, 0x47, 0x01, 0x04, 0x0A,
+	RADIOREGS(0x71, 0x27, 0x02, 0x06, 0x47, 0x01, 0x04, 0x0A,
 		  0x00, 0x84, 0x00, 0x00, 0x44, 0x00, 0x03, 0x00,
 		  0x80, 0x44, 0x00, 0x03, 0x00, 0x80),
-	PHYREGS(0xA008, 0x9C08, 0x9808, 0xDB01, 0xDC01, 0xDD01),
+	PHYREGS(0x08A0, 0x089C, 0x0898, 0x01DB, 0x01DC, 0x01DD),
   },
   {	.channel		= 104,
 	.freq			= 5520, /* MHz */
 	.unk2			= 3680,
-	RADIOREGS(0x71, 0x02, 0x28, 0x05, 0x40, 0x01, 0x04, 0x0A,
+	RADIOREGS(0x71, 0x28, 0x02, 0x05, 0x40, 0x01, 0x04, 0x0A,
 		  0x00, 0x83, 0x00, 0x00, 0x33, 0x00, 0x02, 0x00,
 		  0x80, 0x33, 0x00, 0x02, 0x00, 0x80),
-	PHYREGS(0xA408, 0xA008, 0x9C08, 0xDA01, 0xDB01, 0xDC01),
+	PHYREGS(0x08A4, 0x08A0, 0x089C, 0x01DA, 0x01DB, 0x01DC),
   },
   {	.channel		= 106,
 	.freq			= 5530, /* MHz */
 	.unk2			= 3687,
-	RADIOREGS(0x71, 0x02, 0x29, 0x05, 0x40, 0x01, 0x04, 0x0A,
+	RADIOREGS(0x71, 0x29, 0x02, 0x05, 0x40, 0x01, 0x04, 0x0A,
 		  0x00, 0x83, 0x00, 0x00, 0x33, 0x00, 0x02, 0x00,
 		  0x80, 0x33, 0x00, 0x02, 0x00, 0x80),
-	PHYREGS(0xA808, 0xA408, 0xA008, 0xD901, 0xDA01, 0xDB01),
+	PHYREGS(0x08A8, 0x08A4, 0x08A0, 0x01D9, 0x01DA, 0x01DB),
   },
   {	.channel		= 108,
 	.freq			= 5540, /* MHz */
 	.unk2			= 3693,
-	RADIOREGS(0x71, 0x02, 0x2A, 0x05, 0x3A, 0x01, 0x04, 0x0A,
+	RADIOREGS(0x71, 0x2A, 0x02, 0x05, 0x3A, 0x01, 0x04, 0x0A,
 		  0x00, 0x83, 0x00, 0x00, 0x33, 0x00, 0x02, 0x00,
 		  0x80, 0x33, 0x00, 0x02, 0x00, 0x80),
-	PHYREGS(0xAC08, 0xA808, 0xA408, 0xD801, 0xD901, 0xDA01),
+	PHYREGS(0x08AC, 0x08A8, 0x08A4, 0x01D8, 0x01D9, 0x01DA),
   },
   {	.channel		= 110,
 	.freq			= 5550, /* MHz */
 	.unk2			= 3700,
-	RADIOREGS(0x71, 0x02, 0x2B, 0x05, 0x3A, 0x01, 0x04, 0x0A,
+	RADIOREGS(0x71, 0x2B, 0x02, 0x05, 0x3A, 0x01, 0x04, 0x0A,
 		  0x00, 0x83, 0x00, 0x00, 0x33, 0x00, 0x02, 0x00,
 		  0x80, 0x33, 0x00, 0x02, 0x00, 0x80),
-	PHYREGS(0xB008, 0xAC08, 0xA808, 0xD701, 0xD801, 0xD901),
+	PHYREGS(0x08B0, 0x08AC, 0x08A8, 0x01D7, 0x01D8, 0x01D9),
   },
   {	.channel		= 112,
 	.freq			= 5560, /* MHz */
 	.unk2			= 3707,
-	RADIOREGS(0x71, 0x02, 0x2C, 0x05, 0x34, 0x01, 0x04, 0x0A,
+	RADIOREGS(0x71, 0x2C, 0x02, 0x05, 0x34, 0x01, 0x04, 0x0A,
 		  0x00, 0x82, 0x00, 0x00, 0x22, 0x00, 0x01, 0x00,
 		  0x80, 0x22, 0x00, 0x01, 0x00, 0x80),
-	PHYREGS(0xB408, 0xB008, 0xAC08, 0xD701, 0xD701, 0xD801),
+	PHYREGS(0x08B4, 0x08B0, 0x08AC, 0x01D7, 0x01D7, 0x01D8),
   },
   {	.channel		= 114,
 	.freq			= 5570, /* MHz */
 	.unk2			= 3713,
-	RADIOREGS(0x71, 0x02, 0x2D, 0x05, 0x34, 0x01, 0x04, 0x0A,
+	RADIOREGS(0x71, 0x2D, 0x02, 0x05, 0x34, 0x01, 0x04, 0x0A,
 		  0x00, 0x82, 0x00, 0x00, 0x22, 0x00, 0x01, 0x00,
 		  0x80, 0x22, 0x00, 0x01, 0x00, 0x80),
-	PHYREGS(0xB808, 0xB408, 0xB008, 0xD601, 0xD701, 0xD701),
+	PHYREGS(0x08B8, 0x08B4, 0x08B0, 0x01D6, 0x01D7, 0x01D7),
   },
   {	.channel		= 116,
 	.freq			= 5580, /* MHz */
 	.unk2			= 3720,
-	RADIOREGS(0x71, 0x02, 0x2E, 0x04, 0x2E, 0x01, 0x04, 0x0A,
+	RADIOREGS(0x71, 0x2E, 0x02, 0x04, 0x2E, 0x01, 0x04, 0x0A,
 		  0x00, 0x82, 0x00, 0x00, 0x22, 0x00, 0x01, 0x00,
 		  0x80, 0x22, 0x00, 0x01, 0x00, 0x80),
-	PHYREGS(0xBC08, 0xB808, 0xB408, 0xD501, 0xD601, 0xD701),
+	PHYREGS(0x08BC, 0x08B8, 0x08B4, 0x01D5, 0x01D6, 0x01D7),
   },
   {	.channel		= 118,
 	.freq			= 5590, /* MHz */
 	.unk2			= 3727,
-	RADIOREGS(0x71, 0x02, 0x2F, 0x04, 0x2E, 0x01, 0x04, 0x0A,
+	RADIOREGS(0x71, 0x2F, 0x02, 0x04, 0x2E, 0x01, 0x04, 0x0A,
 		  0x00, 0x82, 0x00, 0x00, 0x22, 0x00, 0x01, 0x00,
 		  0x80, 0x22, 0x00, 0x01, 0x00, 0x80),
-	PHYREGS(0xC008, 0xBC08, 0xB808, 0xD401, 0xD501, 0xD601),
+	PHYREGS(0x08C0, 0x08BC, 0x08B8, 0x01D4, 0x01D5, 0x01D6),
   },
   {	.channel		= 120,
 	.freq			= 5600, /* MHz */
 	.unk2			= 3733,
-	RADIOREGS(0x71, 0x02, 0x30, 0x04, 0x28, 0x01, 0x04, 0x0A,
+	RADIOREGS(0x71, 0x30, 0x02, 0x04, 0x28, 0x01, 0x04, 0x0A,
 		  0x00, 0x81, 0x00, 0x00, 0x11, 0x00, 0x01, 0x00,
 		  0x80, 0x11, 0x00, 0x01, 0x00, 0x80),
-	PHYREGS(0xC408, 0xC008, 0xBC08, 0xD301, 0xD401, 0xD501),
+	PHYREGS(0x08C4, 0x08C0, 0x08BC, 0x01D3, 0x01D4, 0x01D5),
   },
   {	.channel		= 122,
 	.freq			= 5610, /* MHz */
 	.unk2			= 3740,
-	RADIOREGS(0x71, 0x02, 0x31, 0x04, 0x28, 0x01, 0x04, 0x0A,
+	RADIOREGS(0x71, 0x31, 0x02, 0x04, 0x28, 0x01, 0x04, 0x0A,
 		  0x00, 0x81, 0x00, 0x00, 0x11, 0x00, 0x01, 0x00,
 		  0x80, 0x11, 0x00, 0x01, 0x00, 0x80),
-	PHYREGS(0xC808, 0xC408, 0xC008, 0xD201, 0xD301, 0xD401),
+	PHYREGS(0x08C8, 0x08C4, 0x08C0, 0x01D2, 0x01D3, 0x01D4),
   },
   {	.channel		= 124,
 	.freq			= 5620, /* MHz */
 	.unk2			= 3747,
-	RADIOREGS(0x71, 0x02, 0x32, 0x04, 0x21, 0x01, 0x04, 0x0A,
+	RADIOREGS(0x71, 0x32, 0x02, 0x04, 0x21, 0x01, 0x04, 0x0A,
 		  0x00, 0x81, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
 		  0x80, 0x11, 0x00, 0x00, 0x00, 0x80),
-	PHYREGS(0xCC08, 0xC808, 0xC408, 0xD201, 0xD201, 0xD301),
+	PHYREGS(0x08CC, 0x08C8, 0x08C4, 0x01D2, 0x01D2, 0x01D3),
   },
   {	.channel		= 126,
 	.freq			= 5630, /* MHz */
 	.unk2			= 3753,
-	RADIOREGS(0x71, 0x02, 0x33, 0x04, 0x21, 0x01, 0x04, 0x0A,
+	RADIOREGS(0x71, 0x33, 0x02, 0x04, 0x21, 0x01, 0x04, 0x0A,
 		  0x00, 0x81, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
 		  0x80, 0x11, 0x00, 0x00, 0x00, 0x80),
-	PHYREGS(0xD008, 0xCC08, 0xC808, 0xD101, 0xD201, 0xD201),
+	PHYREGS(0x08D0, 0x08CC, 0x08C8, 0x01D1, 0x01D2, 0x01D2),
   },
   {	.channel		= 128,
 	.freq			= 5640, /* MHz */
 	.unk2			= 3760,
-	RADIOREGS(0x71, 0x02, 0x34, 0x03, 0x1C, 0x01, 0x04, 0x0A,
+	RADIOREGS(0x71, 0x34, 0x02, 0x03, 0x1C, 0x01, 0x04, 0x0A,
 		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
-	PHYREGS(0xD408, 0xD008, 0xCC08, 0xD001, 0xD101, 0xD201),
+	PHYREGS(0x08D4, 0x08D0, 0x08CC, 0x01D0, 0x01D1, 0x01D2),
   },
   {	.channel		= 130,
 	.freq			= 5650, /* MHz */
 	.unk2			= 3767,
-	RADIOREGS(0x71, 0x02, 0x35, 0x03, 0x1C, 0x01, 0x04, 0x0A,
+	RADIOREGS(0x71, 0x35, 0x02, 0x03, 0x1C, 0x01, 0x04, 0x0A,
 		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
-	PHYREGS(0xD808, 0xD408, 0xD008, 0xCF01, 0xD001, 0xD101),
+	PHYREGS(0x08D8, 0x08D4, 0x08D0, 0x01CF, 0x01D0, 0x01D1),
   },
   {	.channel		= 132,
 	.freq			= 5660, /* MHz */
 	.unk2			= 3773,
-	RADIOREGS(0x71, 0x02, 0x36, 0x03, 0x16, 0x01, 0x04, 0x0A,
+	RADIOREGS(0x71, 0x36, 0x02, 0x03, 0x16, 0x01, 0x04, 0x0A,
 		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
-	PHYREGS(0xDC08, 0xD808, 0xD408, 0xCE01, 0xCF01, 0xD001),
+	PHYREGS(0x08DC, 0x08D8, 0x08D4, 0x01CE, 0x01CF, 0x01D0),
   },
   {	.channel		= 134,
 	.freq			= 5670, /* MHz */
 	.unk2			= 3780,
-	RADIOREGS(0x71, 0x02, 0x37, 0x03, 0x16, 0x01, 0x04, 0x0A,
+	RADIOREGS(0x71, 0x37, 0x02, 0x03, 0x16, 0x01, 0x04, 0x0A,
 		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
-	PHYREGS(0xE008, 0xDC08, 0xD808, 0xCE01, 0xCE01, 0xCF01),
+	PHYREGS(0x08E0, 0x08DC, 0x08D8, 0x01CE, 0x01CE, 0x01CF),
   },
   {	.channel		= 136,
 	.freq			= 5680, /* MHz */
 	.unk2			= 3787,
-	RADIOREGS(0x71, 0x02, 0x38, 0x03, 0x10, 0x01, 0x04, 0x0A,
+	RADIOREGS(0x71, 0x38, 0x02, 0x03, 0x10, 0x01, 0x04, 0x0A,
 		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
-	PHYREGS(0xE408, 0xE008, 0xDC08, 0xCD01, 0xCE01, 0xCE01),
+	PHYREGS(0x08E4, 0x08E0, 0x08DC, 0x01CD, 0x01CE, 0x01CE),
   },
   {	.channel		= 138,
 	.freq			= 5690, /* MHz */
 	.unk2			= 3793,
-	RADIOREGS(0x71, 0x02, 0x39, 0x03, 0x10, 0x01, 0x04, 0x0A,
+	RADIOREGS(0x71, 0x39, 0x02, 0x03, 0x10, 0x01, 0x04, 0x0A,
 		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
-	PHYREGS(0xE808, 0xE408, 0xE008, 0xCC01, 0xCD01, 0xCE01),
+	PHYREGS(0x08E8, 0x08E4, 0x08E0, 0x01CC, 0x01CD, 0x01CE),
   },
   {	.channel		= 140,
 	.freq			= 5700, /* MHz */
 	.unk2			= 3800,
-	RADIOREGS(0x71, 0x02, 0x3A, 0x02, 0x0A, 0x01, 0x04, 0x0A,
+	RADIOREGS(0x71, 0x3A, 0x02, 0x02, 0x0A, 0x01, 0x04, 0x0A,
 		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
-	PHYREGS(0xEC08, 0xE808, 0xE408, 0xCB01, 0xCC01, 0xCD01),
+	PHYREGS(0x08EC, 0x08E8, 0x08E4, 0x01CB, 0x01CC, 0x01CD),
   },
   {	.channel		= 142,
 	.freq			= 5710, /* MHz */
 	.unk2			= 3807,
-	RADIOREGS(0x71, 0x02, 0x3B, 0x02, 0x0A, 0x01, 0x04, 0x0A,
+	RADIOREGS(0x71, 0x3B, 0x02, 0x02, 0x0A, 0x01, 0x04, 0x0A,
 		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
-	PHYREGS(0xF008, 0xEC08, 0xE808, 0xCA01, 0xCB01, 0xCC01),
+	PHYREGS(0x08F0, 0x08EC, 0x08E8, 0x01CA, 0x01CB, 0x01CC),
   },
   {	.channel		= 144,
 	.freq			= 5720, /* MHz */
 	.unk2			= 3813,
-	RADIOREGS(0x71, 0x02, 0x3C, 0x02, 0x0A, 0x01, 0x04, 0x0A,
+	RADIOREGS(0x71, 0x3C, 0x02, 0x02, 0x0A, 0x01, 0x04, 0x0A,
 		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
-	PHYREGS(0xF408, 0xF008, 0xEC08, 0xC901, 0xCA01, 0xCB01),
+	PHYREGS(0x08F4, 0x08F0, 0x08EC, 0x01C9, 0x01CA, 0x01CB),
   },
   {	.channel		= 145,
 	.freq			= 5725, /* MHz */
 	.unk2			= 3817,
-	RADIOREGS(0x72, 0x04, 0x79, 0x02, 0x03, 0x01, 0x03, 0x14,
+	RADIOREGS(0x72, 0x79, 0x04, 0x02, 0x03, 0x01, 0x03, 0x14,
 		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
-	PHYREGS(0xF608, 0xF208, 0xEE08, 0xC901, 0xCA01, 0xCB01),
+	PHYREGS(0x08F6, 0x08F2, 0x08EE, 0x01C9, 0x01CA, 0x01CB),
   },
   {	.channel		= 146,
 	.freq			= 5730, /* MHz */
 	.unk2			= 3820,
-	RADIOREGS(0x71, 0x02, 0x3D, 0x02, 0x0A, 0x01, 0x04, 0x0A,
+	RADIOREGS(0x71, 0x3D, 0x02, 0x02, 0x0A, 0x01, 0x04, 0x0A,
 		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
-	PHYREGS(0xF808, 0xF408, 0xF008, 0xC901, 0xC901, 0xCA01),
+	PHYREGS(0x08F8, 0x08F4, 0x08F0, 0x01C9, 0x01C9, 0x01CA),
   },
   {	.channel		= 147,
 	.freq			= 5735, /* MHz */
 	.unk2			= 3823,
-	RADIOREGS(0x72, 0x04, 0x7B, 0x02, 0x03, 0x01, 0x03, 0x14,
+	RADIOREGS(0x72, 0x7B, 0x04, 0x02, 0x03, 0x01, 0x03, 0x14,
 		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
-	PHYREGS(0xFA08, 0xF608, 0xF208, 0xC801, 0xC901, 0xCA01),
+	PHYREGS(0x08FA, 0x08F6, 0x08F2, 0x01C8, 0x01C9, 0x01CA),
   },
   {	.channel		= 148,
 	.freq			= 5740, /* MHz */
 	.unk2			= 3827,
-	RADIOREGS(0x71, 0x02, 0x3E, 0x02, 0x0A, 0x01, 0x04, 0x0A,
+	RADIOREGS(0x71, 0x3E, 0x02, 0x02, 0x0A, 0x01, 0x04, 0x0A,
 		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
-	PHYREGS(0xFC08, 0xF808, 0xF408, 0xC801, 0xC901, 0xC901),
+	PHYREGS(0x08FC, 0x08F8, 0x08F4, 0x01C8, 0x01C9, 0x01C9),
   },
   {	.channel		= 149,
 	.freq			= 5745, /* MHz */
 	.unk2			= 3830,
-	RADIOREGS(0x72, 0x04, 0x7D, 0x02, 0xFE, 0x00, 0x03, 0x14,
+	RADIOREGS(0x72, 0x7D, 0x04, 0x02, 0xFE, 0x00, 0x03, 0x14,
 		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
-	PHYREGS(0xFE08, 0xFA08, 0xF608, 0xC801, 0xC801, 0xC901),
+	PHYREGS(0x08FE, 0x08FA, 0x08F6, 0x01C8, 0x01C8, 0x01C9),
   },
   {	.channel		= 150,
 	.freq			= 5750, /* MHz */
 	.unk2			= 3833,
-	RADIOREGS(0x71, 0x02, 0x3F, 0x02, 0x0A, 0x01, 0x04, 0x0A,
+	RADIOREGS(0x71, 0x3F, 0x02, 0x02, 0x0A, 0x01, 0x04, 0x0A,
 		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
-	PHYREGS(0x0009, 0xFC08, 0xF808, 0xC701, 0xC801, 0xC901),
+	PHYREGS(0x0900, 0x08FC, 0x08F8, 0x01C7, 0x01C8, 0x01C9),
   },
   {	.channel		= 151,
 	.freq			= 5755, /* MHz */
 	.unk2			= 3837,
-	RADIOREGS(0x72, 0x04, 0x7F, 0x02, 0xFE, 0x00, 0x03, 0x14,
+	RADIOREGS(0x72, 0x7F, 0x04, 0x02, 0xFE, 0x00, 0x03, 0x14,
 		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
-	PHYREGS(0x0209, 0xFE08, 0xFA08, 0xC701, 0xC801, 0xC801),
+	PHYREGS(0x0902, 0x08FE, 0x08FA, 0x01C7, 0x01C8, 0x01C8),
   },
   {	.channel		= 152,
 	.freq			= 5760, /* MHz */
 	.unk2			= 3840,
-	RADIOREGS(0x71, 0x02, 0x40, 0x02, 0x0A, 0x01, 0x04, 0x0A,
+	RADIOREGS(0x71, 0x40, 0x02, 0x02, 0x0A, 0x01, 0x04, 0x0A,
 		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
-	PHYREGS(0x0409, 0x0009, 0xFC08, 0xC601, 0xC701, 0xC801),
+	PHYREGS(0x0904, 0x0900, 0x08FC, 0x01C6, 0x01C7, 0x01C8),
   },
   {	.channel		= 153,
 	.freq			= 5765, /* MHz */
 	.unk2			= 3843,
-	RADIOREGS(0x72, 0x04, 0x81, 0x02, 0xF8, 0x00, 0x03, 0x14,
+	RADIOREGS(0x72, 0x81, 0x04, 0x02, 0xF8, 0x00, 0x03, 0x14,
 		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
-	PHYREGS(0x0609, 0x0209, 0xFE08, 0xC601, 0xC701, 0xC801),
+	PHYREGS(0x0906, 0x0902, 0x08FE, 0x01C6, 0x01C7, 0x01C8),
   },
   {	.channel		= 154,
 	.freq			= 5770, /* MHz */
 	.unk2			= 3847,
-	RADIOREGS(0x71, 0x02, 0x41, 0x02, 0x0A, 0x01, 0x04, 0x0A,
+	RADIOREGS(0x71, 0x41, 0x02, 0x02, 0x0A, 0x01, 0x04, 0x0A,
 		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
-	PHYREGS(0x0809, 0x0409, 0x0009, 0xC601, 0xC601, 0xC701),
+	PHYREGS(0x0908, 0x0904, 0x0900, 0x01C6, 0x01C6, 0x01C7),
   },
   {	.channel		= 155,
 	.freq			= 5775, /* MHz */
 	.unk2			= 3850,
-	RADIOREGS(0x72, 0x04, 0x83, 0x02, 0xF8, 0x00, 0x03, 0x14,
+	RADIOREGS(0x72, 0x83, 0x04, 0x02, 0xF8, 0x00, 0x03, 0x14,
 		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
-	PHYREGS(0x0A09, 0x0609, 0x0209, 0xC501, 0xC601, 0xC701),
+	PHYREGS(0x090A, 0x0906, 0x0902, 0x01C5, 0x01C6, 0x01C7),
   },
   {	.channel		= 156,
 	.freq			= 5780, /* MHz */
 	.unk2			= 3853,
-	RADIOREGS(0x71, 0x02, 0x42, 0x02, 0x0A, 0x01, 0x04, 0x0A,
+	RADIOREGS(0x71, 0x42, 0x02, 0x02, 0x0A, 0x01, 0x04, 0x0A,
 		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
-	PHYREGS(0x0C09, 0x0809, 0x0409, 0xC501, 0xC601, 0xC601),
+	PHYREGS(0x090C, 0x0908, 0x0904, 0x01C5, 0x01C6, 0x01C6),
   },
   {	.channel		= 157,
 	.freq			= 5785, /* MHz */
 	.unk2			= 3857,
-	RADIOREGS(0x72, 0x04, 0x85, 0x02, 0xF2, 0x00, 0x03, 0x14,
+	RADIOREGS(0x72, 0x85, 0x04, 0x02, 0xF2, 0x00, 0x03, 0x14,
 		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
-	PHYREGS(0x0E09, 0x0A09, 0x0609, 0xC401, 0xC501, 0xC601),
+	PHYREGS(0x090E, 0x090A, 0x0906, 0x01C4, 0x01C5, 0x01C6),
   },
   {	.channel		= 158,
 	.freq			= 5790, /* MHz */
 	.unk2			= 3860,
-	RADIOREGS(0x71, 0x02, 0x43, 0x02, 0x0A, 0x01, 0x04, 0x0A,
+	RADIOREGS(0x71, 0x43, 0x02, 0x02, 0x0A, 0x01, 0x04, 0x0A,
 		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
-	PHYREGS(0x1009, 0x0C09, 0x0809, 0xC401, 0xC501, 0xC601),
+	PHYREGS(0x0910, 0x090C, 0x0908, 0x01C4, 0x01C5, 0x01C6),
   },
   {	.channel		= 159,
 	.freq			= 5795, /* MHz */
 	.unk2			= 3863,
-	RADIOREGS(0x72, 0x04, 0x87, 0x02, 0xF2, 0x00, 0x03, 0x14,
+	RADIOREGS(0x72, 0x87, 0x04, 0x02, 0xF2, 0x00, 0x03, 0x14,
 		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
-	PHYREGS(0x1209, 0x0E09, 0x0A09, 0xC401, 0xC401, 0xC501),
+	PHYREGS(0x0912, 0x090E, 0x090A, 0x01C4, 0x01C4, 0x01C5),
   },
   {	.channel		= 160,
 	.freq			= 5800, /* MHz */
 	.unk2			= 3867,
-	RADIOREGS(0x71, 0x02, 0x44, 0x01, 0x0A, 0x01, 0x04, 0x0A,
+	RADIOREGS(0x71, 0x44, 0x02, 0x01, 0x0A, 0x01, 0x04, 0x0A,
 		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
-	PHYREGS(0x1409, 0x1009, 0x0C09, 0xC301, 0xC401, 0xC501),
+	PHYREGS(0x0914, 0x0910, 0x090C, 0x01C3, 0x01C4, 0x01C5),
   },
   {	.channel		= 161,
 	.freq			= 5805, /* MHz */
 	.unk2			= 3870,
-	RADIOREGS(0x72, 0x04, 0x89, 0x01, 0xED, 0x00, 0x03, 0x14,
+	RADIOREGS(0x72, 0x89, 0x04, 0x01, 0xED, 0x00, 0x03, 0x14,
 		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
-	PHYREGS(0x1609, 0x1209, 0x0E09, 0xC301, 0xC401, 0xC401),
+	PHYREGS(0x0916, 0x0912, 0x090E, 0x01C3, 0x01C4, 0x01C4),
   },
   {	.channel		= 162,
 	.freq			= 5810, /* MHz */
 	.unk2			= 3873,
-	RADIOREGS(0x71, 0x02, 0x45, 0x01, 0x0A, 0x01, 0x04, 0x0A,
+	RADIOREGS(0x71, 0x45, 0x02, 0x01, 0x0A, 0x01, 0x04, 0x0A,
 		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
-	PHYREGS(0x1809, 0x1409, 0x1009, 0xC201, 0xC301, 0xC401),
+	PHYREGS(0x0918, 0x0914, 0x0910, 0x01C2, 0x01C3, 0x01C4),
   },
   {	.channel		= 163,
 	.freq			= 5815, /* MHz */
 	.unk2			= 3877,
-	RADIOREGS(0x72, 0x04, 0x8B, 0x01, 0xED, 0x00, 0x03, 0x14,
+	RADIOREGS(0x72, 0x8B, 0x04, 0x01, 0xED, 0x00, 0x03, 0x14,
 		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
-	PHYREGS(0x1A09, 0x1609, 0x1209, 0xC201, 0xC301, 0xC401),
+	PHYREGS(0x091A, 0x0916, 0x0912, 0x01C2, 0x01C3, 0x01C4),
   },
   {	.channel		= 164,
 	.freq			= 5820, /* MHz */
 	.unk2			= 3880,
-	RADIOREGS(0x71, 0x02, 0x46, 0x01, 0x0A, 0x01, 0x04, 0x0A,
+	RADIOREGS(0x71, 0x46, 0x02, 0x01, 0x0A, 0x01, 0x04, 0x0A,
 		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
-	PHYREGS(0x1C09, 0x1809, 0x1409, 0xC201, 0xC201, 0xC301),
+	PHYREGS(0x091C, 0x0918, 0x0914, 0x01C2, 0x01C2, 0x01C3),
   },
   {	.channel		= 165,
 	.freq			= 5825, /* MHz */
 	.unk2			= 3883,
-	RADIOREGS(0x72, 0x04, 0x8D, 0x01, 0xED, 0x00, 0x03, 0x14,
+	RADIOREGS(0x72, 0x8D, 0x04, 0x01, 0xED, 0x00, 0x03, 0x14,
 		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
-	PHYREGS(0x1E09, 0x1A09, 0x1609, 0xC101, 0xC201, 0xC301),
+	PHYREGS(0x091E, 0x091A, 0x0916, 0x01C1, 0x01C2, 0x01C3),
   },
   {	.channel		= 166,
 	.freq			= 5830, /* MHz */
 	.unk2			= 3887,
-	RADIOREGS(0x71, 0x02, 0x47, 0x01, 0x0A, 0x01, 0x04, 0x0A,
+	RADIOREGS(0x71, 0x47, 0x02, 0x01, 0x0A, 0x01, 0x04, 0x0A,
 		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
-	PHYREGS(0x2009, 0x1C09, 0x1809, 0xC101, 0xC201, 0xC201),
+	PHYREGS(0x0920, 0x091C, 0x0918, 0x01C1, 0x01C2, 0x01C2),
   },
   {	.channel		= 168,
 	.freq			= 5840, /* MHz */
 	.unk2			= 3893,
-	RADIOREGS(0x71, 0x02, 0x48, 0x01, 0x0A, 0x01, 0x04, 0x0A,
+	RADIOREGS(0x71, 0x48, 0x02, 0x01, 0x0A, 0x01, 0x04, 0x0A,
 		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
-	PHYREGS(0x2409, 0x2009, 0x1C09, 0xC001, 0xC101, 0xC201),
+	PHYREGS(0x0924, 0x0920, 0x091C, 0x01C0, 0x01C1, 0x01C2),
   },
   {	.channel		= 170,
 	.freq			= 5850, /* MHz */
 	.unk2			= 3900,
-	RADIOREGS(0x71, 0x02, 0x49, 0x01, 0xE0, 0x00, 0x04, 0x0A,
+	RADIOREGS(0x71, 0x49, 0x02, 0x01, 0xE0, 0x00, 0x04, 0x0A,
 		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
-	PHYREGS(0x2809, 0x2409, 0x2009, 0xBF01, 0xC001, 0xC101),
+	PHYREGS(0x0928, 0x0924, 0x0920, 0x01BF, 0x01C0, 0x01C1),
   },
   {	.channel		= 172,
 	.freq			= 5860, /* MHz */
 	.unk2			= 3907,
-	RADIOREGS(0x71, 0x02, 0x4A, 0x01, 0xDE, 0x00, 0x04, 0x0A,
+	RADIOREGS(0x71, 0x4A, 0x02, 0x01, 0xDE, 0x00, 0x04, 0x0A,
 		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
-	PHYREGS(0x2C09, 0x2809, 0x2409, 0xBF01, 0xBF01, 0xC001),
+	PHYREGS(0x092C, 0x0928, 0x0924, 0x01BF, 0x01BF, 0x01C0),
   },
   {	.channel		= 174,
 	.freq			= 5870, /* MHz */
 	.unk2			= 3913,
-	RADIOREGS(0x71, 0x02, 0x4B, 0x00, 0xDB, 0x00, 0x04, 0x0A,
+	RADIOREGS(0x71, 0x4B, 0x02, 0x00, 0xDB, 0x00, 0x04, 0x0A,
 		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
-	PHYREGS(0x3009, 0x2C09, 0x2809, 0xBE01, 0xBF01, 0xBF01),
+	PHYREGS(0x0930, 0x092C, 0x0928, 0x01BE, 0x01BF, 0x01BF),
   },
   {	.channel		= 176,
 	.freq			= 5880, /* MHz */
 	.unk2			= 3920,
-	RADIOREGS(0x71, 0x02, 0x4C, 0x00, 0xD8, 0x00, 0x04, 0x0A,
+	RADIOREGS(0x71, 0x4C, 0x02, 0x00, 0xD8, 0x00, 0x04, 0x0A,
 		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
-	PHYREGS(0x3409, 0x3009, 0x2C09, 0xBD01, 0xBE01, 0xBF01),
+	PHYREGS(0x0934, 0x0930, 0x092C, 0x01BD, 0x01BE, 0x01BF),
   },
   {	.channel		= 178,
 	.freq			= 5890, /* MHz */
 	.unk2			= 3927,
-	RADIOREGS(0x71, 0x02, 0x4D, 0x00, 0xD6, 0x00, 0x04, 0x0A,
+	RADIOREGS(0x71, 0x4D, 0x02, 0x00, 0xD6, 0x00, 0x04, 0x0A,
 		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
-	PHYREGS(0x3809, 0x3409, 0x3009, 0xBC01, 0xBD01, 0xBE01),
+	PHYREGS(0x0938, 0x0934, 0x0930, 0x01BC, 0x01BD, 0x01BE),
   },
   {	.channel		= 180,
 	.freq			= 5900, /* MHz */
 	.unk2			= 3933,
-	RADIOREGS(0x71, 0x02, 0x4E, 0x00, 0xD3, 0x00, 0x04, 0x0A,
+	RADIOREGS(0x71, 0x4E, 0x02, 0x00, 0xD3, 0x00, 0x04, 0x0A,
 		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
-	PHYREGS(0x3C09, 0x3809, 0x3409, 0xBC01, 0xBC01, 0xBD01),
+	PHYREGS(0x093C, 0x0938, 0x0934, 0x01BC, 0x01BC, 0x01BD),
   },
   {	.channel		= 182,
 	.freq			= 5910, /* MHz */
 	.unk2			= 3940,
-	RADIOREGS(0x71, 0x02, 0x4F, 0x00, 0xD6, 0x00, 0x04, 0x0A,
+	RADIOREGS(0x71, 0x4F, 0x02, 0x00, 0xD6, 0x00, 0x04, 0x0A,
 		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
-	PHYREGS(0x4009, 0x3C09, 0x3809, 0xBB01, 0xBC01, 0xBC01),
+	PHYREGS(0x0940, 0x093C, 0x0938, 0x01BB, 0x01BC, 0x01BC),
   },
   {	.channel		= 1,
 	.freq			= 2412, /* MHz */
 	.unk2			= 3216,
-	RADIOREGS(0x73, 0x09, 0x6C, 0x0F, 0x00, 0x01, 0x07, 0x15,
+	RADIOREGS(0x73, 0x6C, 0x09, 0x0F, 0x00, 0x01, 0x07, 0x15,
 		  0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0D, 0x0C,
 		  0x80, 0xFF, 0x88, 0x0D, 0x0C, 0x80),
-	PHYREGS(0xC903, 0xC503, 0xC103, 0x3A04, 0x3F04, 0x4304),
+	PHYREGS(0x03C9, 0x03C5, 0x03C1, 0x043A, 0x043F, 0x0443),
   },
   {	.channel		= 2,
 	.freq			= 2417, /* MHz */
 	.unk2			= 3223,
-	RADIOREGS(0x73, 0x09, 0x71, 0x0F, 0x00, 0x01, 0x07, 0x15,
+	RADIOREGS(0x73, 0x71, 0x09, 0x0F, 0x00, 0x01, 0x07, 0x15,
 		  0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0C, 0x0B,
 		  0x80, 0xFF, 0x88, 0x0C, 0x0B, 0x80),
-	PHYREGS(0xCB03, 0xC703, 0xC303, 0x3804, 0x3D04, 0x4104),
+	PHYREGS(0x03CB, 0x03C7, 0x03C3, 0x0438, 0x043D, 0x0441),
   },
   {	.channel		= 3,
 	.freq			= 2422, /* MHz */
 	.unk2			= 3229,
-	RADIOREGS(0x73, 0x09, 0x76, 0x0F, 0x00, 0x01, 0x07, 0x15,
+	RADIOREGS(0x73, 0x76, 0x09, 0x0F, 0x00, 0x01, 0x07, 0x15,
 		  0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0C, 0x0A,
 		  0x80, 0xFF, 0x88, 0x0C, 0x0A, 0x80),
-	PHYREGS(0xCD03, 0xC903, 0xC503, 0x3604, 0x3A04, 0x3F04),
+	PHYREGS(0x03CD, 0x03C9, 0x03C5, 0x0436, 0x043A, 0x043F),
   },
   {	.channel		= 4,
 	.freq			= 2427, /* MHz */
 	.unk2			= 3236,
-	RADIOREGS(0x73, 0x09, 0x7B, 0x0F, 0x00, 0x01, 0x07, 0x15,
+	RADIOREGS(0x73, 0x7B, 0x09, 0x0F, 0x00, 0x01, 0x07, 0x15,
 		  0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0C, 0x0A,
 		  0x80, 0xFF, 0x88, 0x0C, 0x0A, 0x80),
-	PHYREGS(0xCF03, 0xCB03, 0xC703, 0x3404, 0x3804, 0x3D04),
+	PHYREGS(0x03CF, 0x03CB, 0x03C7, 0x0434, 0x0438, 0x043D),
   },
   {	.channel		= 5,
 	.freq			= 2432, /* MHz */
 	.unk2			= 3243,
-	RADIOREGS(0x73, 0x09, 0x80, 0x0F, 0x00, 0x01, 0x07, 0x15,
+	RADIOREGS(0x73, 0x80, 0x09, 0x0F, 0x00, 0x01, 0x07, 0x15,
 		  0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0C, 0x09,
 		  0x80, 0xFF, 0x88, 0x0C, 0x09, 0x80),
-	PHYREGS(0xD103, 0xCD03, 0xC903, 0x3104, 0x3604, 0x3A04),
+	PHYREGS(0x03D1, 0x03CD, 0x03C9, 0x0431, 0x0436, 0x043A),
   },
   {	.channel		= 6,
 	.freq			= 2437, /* MHz */
 	.unk2			= 3249,
-	RADIOREGS(0x73, 0x09, 0x85, 0x0F, 0x00, 0x01, 0x07, 0x15,
+	RADIOREGS(0x73, 0x85, 0x09, 0x0F, 0x00, 0x01, 0x07, 0x15,
 		  0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0B, 0x08,
 		  0x80, 0xFF, 0x88, 0x0B, 0x08, 0x80),
-	PHYREGS(0xD303, 0xCF03, 0xCB03, 0x2F04, 0x3404, 0x3804),
+	PHYREGS(0x03D3, 0x03CF, 0x03CB, 0x042F, 0x0434, 0x0438),
   },
   {	.channel		= 7,
 	.freq			= 2442, /* MHz */
 	.unk2			= 3256,
-	RADIOREGS(0x73, 0x09, 0x8A, 0x0F, 0x00, 0x01, 0x07, 0x15,
+	RADIOREGS(0x73, 0x8A, 0x09, 0x0F, 0x00, 0x01, 0x07, 0x15,
 		  0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0A, 0x07,
 		  0x80, 0xFF, 0x88, 0x0A, 0x07, 0x80),
-	PHYREGS(0xD503, 0xD103, 0xCD03, 0x2D04, 0x3104, 0x3604),
+	PHYREGS(0x03D5, 0x03D1, 0x03CD, 0x042D, 0x0431, 0x0436),
   },
   {	.channel		= 8,
 	.freq			= 2447, /* MHz */
 	.unk2			= 3263,
-	RADIOREGS(0x73, 0x09, 0x8F, 0x0F, 0x00, 0x01, 0x07, 0x15,
+	RADIOREGS(0x73, 0x8F, 0x09, 0x0F, 0x00, 0x01, 0x07, 0x15,
 		  0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0A, 0x06,
 		  0x80, 0xFF, 0x88, 0x0A, 0x06, 0x80),
-	PHYREGS(0xD703, 0xD303, 0xCF03, 0x2B04, 0x2F04, 0x3404),
+	PHYREGS(0x03D7, 0x03D3, 0x03CF, 0x042B, 0x042F, 0x0434),
   },
   {	.channel		= 9,
 	.freq			= 2452, /* MHz */
 	.unk2			= 3269,
-	RADIOREGS(0x73, 0x09, 0x94, 0x0F, 0x00, 0x01, 0x07, 0x15,
+	RADIOREGS(0x73, 0x94, 0x09, 0x0F, 0x00, 0x01, 0x07, 0x15,
 		  0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x09, 0x06,
 		  0x80, 0xFF, 0x88, 0x09, 0x06, 0x80),
-	PHYREGS(0xD903, 0xD503, 0xD103, 0x2904, 0x2D04, 0x3104),
+	PHYREGS(0x03D9, 0x03D5, 0x03D1, 0x0429, 0x042D, 0x0431),
   },
   {	.channel		= 10,
 	.freq			= 2457, /* MHz */
 	.unk2			= 3276,
-	RADIOREGS(0x73, 0x09, 0x99, 0x0F, 0x00, 0x01, 0x07, 0x15,
+	RADIOREGS(0x73, 0x99, 0x09, 0x0F, 0x00, 0x01, 0x07, 0x15,
 		  0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x08, 0x05,
 		  0x80, 0xFF, 0x88, 0x08, 0x05, 0x80),
-	PHYREGS(0xDB03, 0xD703, 0xD303, 0x2704, 0x2B04, 0x2F04),
+	PHYREGS(0x03DB, 0x03D7, 0x03D3, 0x0427, 0x042B, 0x042F),
   },
   {	.channel		= 11,
 	.freq			= 2462, /* MHz */
 	.unk2			= 3283,
-	RADIOREGS(0x73, 0x09, 0x9E, 0x0F, 0x00, 0x01, 0x07, 0x15,
+	RADIOREGS(0x73, 0x9E, 0x09, 0x0F, 0x00, 0x01, 0x07, 0x15,
 		  0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x08, 0x04,
 		  0x80, 0xFF, 0x88, 0x08, 0x04, 0x80),
-	PHYREGS(0xDD03, 0xD903, 0xD503, 0x2404, 0x2904, 0x2D04),
+	PHYREGS(0x03DD, 0x03D9, 0x03D5, 0x0424, 0x0429, 0x042D),
   },
   {	.channel		= 12,
 	.freq			= 2467, /* MHz */
 	.unk2			= 3289,
-	RADIOREGS(0x73, 0x09, 0xA3, 0x0F, 0x00, 0x01, 0x07, 0x15,
+	RADIOREGS(0x73, 0xA3, 0x09, 0x0F, 0x00, 0x01, 0x07, 0x15,
 		  0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x08, 0x03,
 		  0x80, 0xFF, 0x88, 0x08, 0x03, 0x80),
-	PHYREGS(0xDF03, 0xDB03, 0xD703, 0x2204, 0x2704, 0x2B04),
+	PHYREGS(0x03DF, 0x03DB, 0x03D7, 0x0422, 0x0427, 0x042B),
   },
   {	.channel		= 13,
 	.freq			= 2472, /* MHz */
 	.unk2			= 3296,
-	RADIOREGS(0x73, 0x09, 0xA8, 0x0F, 0x00, 0x01, 0x07, 0x15,
+	RADIOREGS(0x73, 0xA8, 0x09, 0x0F, 0x00, 0x01, 0x07, 0x15,
 		  0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x07, 0x03,
 		  0x80, 0xFF, 0x88, 0x07, 0x03, 0x80),
-	PHYREGS(0xE103, 0xDD03, 0xD903, 0x2004, 0x2404, 0x2904),
+	PHYREGS(0x03E1, 0x03DD, 0x03D9, 0x0420, 0x0424, 0x0429),
   },
   {	.channel		= 14,
 	.freq			= 2484, /* MHz */
 	.unk2			= 3312,
-	RADIOREGS(0x73, 0x09, 0xB4, 0x0F, 0xFF, 0x01, 0x07, 0x15,
+	RADIOREGS(0x73, 0xB4, 0x09, 0x0F, 0xFF, 0x01, 0x07, 0x15,
 		  0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x07, 0x01,
 		  0x80, 0xFF, 0x88, 0x07, 0x01, 0x80),
-	PHYREGS(0xE603, 0xE203, 0xDE03, 0x1B04, 0x1F04, 0x2404),
+	PHYREGS(0x03E6, 0x03E2, 0x03DE, 0x041B, 0x041F, 0x0424),
   },
 };
 
@@ -1299,7 +1299,7 @@ void b2055_upload_inittab(struct b43_wld
 			  bool ghz5, bool ignore_uploadflag)
 {
 	const struct b2055_inittab_entry *e;
-	unsigned int i;
+	unsigned int i, writes = 0;
 	u16 value;
 
 	for (i = 0; i < ARRAY_SIZE(b2055_inittab); i++) {
@@ -1312,6 +1312,8 @@ void b2055_upload_inittab(struct b43_wld
 			else
 				value = e->ghz2;
 			b43_radio_write16(dev, i, value);
+			if (++writes % 4 == 0)
+				b43_read32(dev, B43_MMIO_MACCTL); /* flush */
 		}
 	}
 }
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/b43/radio_2056.c linux-libre-2.6.38-gnu1/drivers/net/wireless/b43/radio_2056.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/b43/radio_2056.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/b43/radio_2056.c	2011-03-14 21:20:32.000000000 -0400
@@ -24,17 +24,9073 @@
 #include "radio_2056.h"
 #include "phy_common.h"
 
+struct b2056_inittab_entry {
+	/* Value to write if we use the 5GHz band. */
+	u16 ghz5;
+	/* Value to write if we use the 2.4GHz band. */
+	u16 ghz2;
+	/* Flags */
+	u8 flags;
+};
+#define B2056_INITTAB_ENTRY_OK	0x01
+#define B2056_INITTAB_UPLOAD	0x02
+#define UPLOAD		.flags = B2056_INITTAB_ENTRY_OK | B2056_INITTAB_UPLOAD
+#define NOUPLOAD	.flags = B2056_INITTAB_ENTRY_OK
+
+struct b2056_inittabs_pts {
+	const struct b2056_inittab_entry *syn;
+	unsigned int syn_length;
+	const struct b2056_inittab_entry *tx;
+	unsigned int tx_length;
+	const struct b2056_inittab_entry *rx;
+	unsigned int rx_length;
+};
+
+static const struct b2056_inittab_entry b2056_inittab_rev3_syn[] = {
+	[B2056_SYN_RESERVED_ADDR2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR4]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR5]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR6]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR7]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_COM_CTRL]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_COM_PU]		= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_SYN_COM_OVR]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_COM_RESET]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_COM_RCAL]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_COM_RC_RXLPF]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_COM_RC_TXLPF]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_COM_RC_RXHPF]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR16]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR17]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR18]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR19]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR20]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR21]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR22]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR23]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR24]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR25]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR26]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR27]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR28]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR29]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR30]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR31]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_GPIO_MASTER1]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_GPIO_MASTER2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_TOPBIAS_MASTER]	= { .ghz5 = 0x0060, .ghz2 = 0x0060, NOUPLOAD, },
+	[B2056_SYN_TOPBIAS_RCAL]	= { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
+	[B2056_SYN_AFEREG]		= { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, },
+	[B2056_SYN_TEMPPROCSENSE]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_TEMPPROCSENSEIDAC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_TEMPPROCSENSERCAL]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LPO]			= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_SYN_VDDCAL_MASTER]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_VDDCAL_IDAC]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_VDDCAL_STATUS]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCAL_MASTER]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCAL_CODE_OUT]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL0]		= { .ghz5 = 0x000d, .ghz2 = 0x000d, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL1]		= { .ghz5 = 0x001f, .ghz2 = 0x001f, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL2]		= { .ghz5 = 0x0015, .ghz2 = 0x0015, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL3]		= { .ghz5 = 0x000f, .ghz2 = 0x000f, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL4]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL5]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL6]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL7]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL8]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL9]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL10]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL11]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_ZCAL_SPARE1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_ZCAL_SPARE2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_MAST1]		= { .ghz5 = 0x0013, .ghz2 = 0x0013, NOUPLOAD, },
+	[B2056_SYN_PLL_MAST2]		= { .ghz5 = 0x000f, .ghz2 = 0x000f, NOUPLOAD, },
+	[B2056_SYN_PLL_MAST3]		= { .ghz5 = 0x0018, .ghz2 = 0x0018, NOUPLOAD, },
+	[B2056_SYN_PLL_BIAS_RESET]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_XTAL0]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_XTAL1]		= { .ghz5 = 0x0020, .ghz2 = 0x0020, NOUPLOAD, },
+	[B2056_SYN_PLL_XTAL3]		= { .ghz5 = 0x0020, .ghz2 = 0x0020, NOUPLOAD, },
+	[B2056_SYN_PLL_XTAL4]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_XTAL5]		= { .ghz5 = 0x0077, .ghz2 = 0x0077, NOUPLOAD, },
+	[B2056_SYN_PLL_XTAL6]		= { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+	[B2056_SYN_PLL_REFDIV]		= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_SYN_PLL_PFD]		= { .ghz5 = 0x0004, .ghz2 = 0x0004, NOUPLOAD, },
+	[B2056_SYN_PLL_CP1]		= { .ghz5 = 0x000f, .ghz2 = 0x000f, NOUPLOAD, },
+	[B2056_SYN_PLL_CP2]		= { .ghz5 = 0x0030, .ghz2 = 0x0030, NOUPLOAD, },
+	[B2056_SYN_PLL_CP3]		= { .ghz5 = 0x0032, .ghz2 = 0x0032, NOUPLOAD, },
+	[B2056_SYN_PLL_LOOPFILTER1]	= { .ghz5 = 0x000d, .ghz2 = 0x000d, NOUPLOAD, },
+	[B2056_SYN_PLL_LOOPFILTER2]	= { .ghz5 = 0x000d, .ghz2 = 0x000d, NOUPLOAD, },
+	[B2056_SYN_PLL_LOOPFILTER3]	= { .ghz5 = 0x0004, .ghz2 = 0x0004, NOUPLOAD, },
+	[B2056_SYN_PLL_LOOPFILTER4]	= { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
+	[B2056_SYN_PLL_LOOPFILTER5]	= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_SYN_PLL_MMD1]		= { .ghz5 = 0x001c, .ghz2 = 0x001c, NOUPLOAD, },
+	[B2056_SYN_PLL_MMD2]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_SYN_PLL_VCO1]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_SYN_PLL_VCO2]		= { .ghz5 = 0x00f7, .ghz2 = 0x00f7, UPLOAD, },
+	[B2056_SYN_PLL_MONITOR1]	= { .ghz5 = 0x00b4, .ghz2 = 0x00b4, NOUPLOAD, },
+	[B2056_SYN_PLL_MONITOR2]	= { .ghz5 = 0x00d2, .ghz2 = 0x00d2, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL4]		= { .ghz5 = 0x0004, .ghz2 = 0x0004, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL5]		= { .ghz5 = 0x0096, .ghz2 = 0x0096, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL6]		= { .ghz5 = 0x003e, .ghz2 = 0x003e, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL7]		= { .ghz5 = 0x003e, .ghz2 = 0x003e, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL8]		= { .ghz5 = 0x0013, .ghz2 = 0x0013, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL9]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL10]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL11]	= { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL12]	= { .ghz5 = 0x0007, .ghz2 = 0x0007, UPLOAD, },
+	[B2056_SYN_PLL_VCOCAL13]	= { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+	[B2056_SYN_PLL_VREG]		= { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, },
+	[B2056_SYN_PLL_STATUS1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_STATUS2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_STATUS3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PU0]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PU1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PU2]		= { .ghz5 = 0x0040, .ghz2 = 0x0040, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PU3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PU5]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PU6]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PU7]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PU8]		= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_SYN_LOGEN_BIAS_RESET]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_RCCR1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_VCOBUF1]	= { .ghz5 = 0x0060, .ghz2 = 0x0060, NOUPLOAD, },
+	[B2056_SYN_LOGEN_MIXER1]	= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_MIXER2]	= { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, },
+	[B2056_SYN_LOGEN_BUF1]		= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGENBUF2]		= { .ghz5 = 0x008f, .ghz2 = 0x008f, UPLOAD, },
+	[B2056_SYN_LOGEN_BUF3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_BUF4]		= { .ghz5 = 0x00cc, .ghz2 = 0x00cc, NOUPLOAD, },
+	[B2056_SYN_LOGEN_DIV1]		= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_SYN_LOGEN_DIV2]		= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_DIV3]		= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACL1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACL2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACL3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACL4]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACL5]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACL6]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACLOUT]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACLCAL1]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACLCAL2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACLCAL3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_CALEN]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PEAKDET1]	= { .ghz5 = 0x00ff, .ghz2 = 0x00ff, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CORE_ACL_OVR]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_RX_DIFF_ACL_OVR]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_TX_DIFF_ACL_OVR]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_RX_CMOS_ACL_OVR]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_TX_CMOS_ACL_OVR]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_VCOBUF2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_MIXER3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_BUF5]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_BUF6]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFRX1]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFRX2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFRX3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFRX4]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFTX1]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFTX2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFTX3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFTX4]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSRX1]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSRX2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSRX3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSRX4]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSTX1]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSTX2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSTX3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSTX4]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_VCOBUF2_OVRVAL]= { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
+	[B2056_SYN_LOGEN_MIXER3_OVRVAL]	= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_BUF5_OVRVAL]	= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_BUF6_OVRVAL]	= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFRX1_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFRX2_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFRX3_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFRX4_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFTX1_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFTX2_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFTX3_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFTX4_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSRX1_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSRX2_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSRX3_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSRX4_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSTX1_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSTX2_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSTX3_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSTX4_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACL_WAITCNT]	= { .ghz5 = 0x000a, .ghz2 = 0x000a, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CORE_CALVALID]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_RX_CMOS_CALVALID]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_TX_CMOS_VALID]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+};
+
+static const struct b2056_inittab_entry b2056_inittab_rev3_tx[] = {
+	[B2056_TX_RESERVED_ADDR2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR4]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR5]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR6]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR7]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_COM_CTRL]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_COM_PU]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_COM_OVR]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_COM_RESET]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_COM_RCAL]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_COM_RC_RXLPF]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_COM_RC_TXLPF]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_COM_RC_RXHPF]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR16]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR17]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR18]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR19]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR20]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR21]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR22]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR23]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR24]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR25]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR26]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR27]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR28]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR29]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR30]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR31]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_IQCAL_GAIN_BW]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_LOFT_FINE_I]		= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+	[B2056_TX_LOFT_FINE_Q]		= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+	[B2056_TX_LOFT_COARSE_I]	= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+	[B2056_TX_LOFT_COARSE_Q]	= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+	[B2056_TX_TX_COM_MASTER1]	= { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, },
+	[B2056_TX_TX_COM_MASTER2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RXIQCAL_TXMUX]	= { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, },
+	[B2056_TX_TX_SSI_MASTER]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_IQCAL_VCM_HG]		= { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, },
+	[B2056_TX_IQCAL_IDAC]		= { .ghz5 = 0x0037, .ghz2 = 0x0037, NOUPLOAD, },
+	[B2056_TX_TSSI_VCM]		= { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, },
+	[B2056_TX_TX_AMP_DET]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TX_SSI_MUX]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TSSIA]		= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_TX_TSSIG]		= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_TX_TSSI_MISC1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TSSI_MISC2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TSSI_MISC3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_PA_SPARE1]		= { .ghz5 = 0x0011, .ghz2 = 0x0011, NOUPLOAD, },
+	[B2056_TX_PA_SPARE2]		= { .ghz5 = 0x0011, .ghz2 = 0x0011, NOUPLOAD, },
+	[B2056_TX_INTPAA_MASTER]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAA_GAIN]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAA_BOOST_TUNE]	= { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, },
+	[B2056_TX_INTPAA_IAUX_STAT]	= { .ghz5 = 0x000f, .ghz2 = 0x000f, NOUPLOAD, },
+	[B2056_TX_INTPAA_IAUX_DYN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAA_IMAIN_STAT]	= { .ghz5 = 0x002d, .ghz2 = 0x002d, NOUPLOAD, },
+	[B2056_TX_INTPAA_IMAIN_DYN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAA_CASCBIAS]	= { .ghz5 = 0x006e, .ghz2 = 0x006e, NOUPLOAD, },
+	[B2056_TX_INTPAA_PASLOPE]	= { .ghz5 = 0x00f0, .ghz2 = 0x00f0, UPLOAD, },
+	[B2056_TX_INTPAA_PA_MISC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAG_MASTER]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAG_GAIN]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAG_BOOST_TUNE]	= { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, },
+	[B2056_TX_INTPAG_IAUX_STAT]	= { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, },
+	[B2056_TX_INTPAG_IAUX_DYN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAG_IMAIN_STAT]	= { .ghz5 = 0x001e, .ghz2 = 0x001e, NOUPLOAD, },
+	[B2056_TX_INTPAG_IMAIN_DYN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAG_CASCBIAS]	= { .ghz5 = 0x006e, .ghz2 = 0x006e, NOUPLOAD, },
+	[B2056_TX_INTPAG_PASLOPE]	= { .ghz5 = 0x00f0, .ghz2 = 0x00f0, UPLOAD, },
+	[B2056_TX_INTPAG_PA_MISC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_PADA_MASTER]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_TX_PADA_IDAC]		= { .ghz5 = 0x00ff, .ghz2 = 0x00ff, UPLOAD, },
+	[B2056_TX_PADA_CASCBIAS]	= { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, },
+	[B2056_TX_PADA_GAIN]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_PADA_BOOST_TUNE]	= { .ghz5 = 0x0038, .ghz2 = 0x0038, NOUPLOAD, },
+	[B2056_TX_PADA_SLOPE]		= { .ghz5 = 0x0070, .ghz2 = 0x0070, UPLOAD, },
+	[B2056_TX_PADG_MASTER]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_TX_PADG_IDAC]		= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+	[B2056_TX_PADG_CASCBIAS]	= { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, },
+	[B2056_TX_PADG_GAIN]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_PADG_BOOST_TUNE]	= { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+	[B2056_TX_PADG_SLOPE]		= { .ghz5 = 0x0070, .ghz2 = 0x0070, UPLOAD, },
+	[B2056_TX_PGAA_MASTER]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_TX_PGAA_IDAC]		= { .ghz5 = 0x00ff, .ghz2 = 0x00ff, UPLOAD, },
+	[B2056_TX_PGAA_GAIN]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_PGAA_BOOST_TUNE]	= { .ghz5 = 0x0083, .ghz2 = 0x0083, NOUPLOAD, },
+	[B2056_TX_PGAA_SLOPE]		= { .ghz5 = 0x0077, .ghz2 = 0x0077, UPLOAD, },
+	[B2056_TX_PGAA_MISC]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_PGAG_MASTER]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_TX_PGAG_IDAC]		= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+	[B2056_TX_PGAG_GAIN]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_PGAG_BOOST_TUNE]	= { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+	[B2056_TX_PGAG_SLOPE]		= { .ghz5 = 0x0077, .ghz2 = 0x0077, UPLOAD, },
+	[B2056_TX_PGAG_MISC]		= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_TX_MIXA_MASTER]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_MIXA_BOOST_TUNE]	= { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+	[B2056_TX_MIXG]			= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_MIXG_BOOST_TUNE]	= { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+	[B2056_TX_BB_GM_MASTER]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_GMBB_GM]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_GMBB_IDAC]		= { .ghz5 = 0x0074, .ghz2 = 0x0074, UPLOAD, },
+	[B2056_TX_TXLPF_MASTER]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_RCCAL]		= { .ghz5 = 0x000a, .ghz2 = 0x000a, NOUPLOAD, },
+	[B2056_TX_TXLPF_RCCAL_OFF0]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_RCCAL_OFF1]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_RCCAL_OFF2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_RCCAL_OFF3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_RCCAL_OFF4]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_RCCAL_OFF5]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_RCCAL_OFF6]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_BW]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_TX_TXLPF_GAIN]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_IDAC]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_IDAC_0]		= { .ghz5 = 0x000e, .ghz2 = 0x000e, NOUPLOAD, },
+	[B2056_TX_TXLPF_IDAC_1]		= { .ghz5 = 0x000e, .ghz2 = 0x000e, NOUPLOAD, },
+	[B2056_TX_TXLPF_IDAC_2]		= { .ghz5 = 0x000e, .ghz2 = 0x000e, NOUPLOAD, },
+	[B2056_TX_TXLPF_IDAC_3]		= { .ghz5 = 0x0013, .ghz2 = 0x0013, NOUPLOAD, },
+	[B2056_TX_TXLPF_IDAC_4]		= { .ghz5 = 0x0013, .ghz2 = 0x0013, NOUPLOAD, },
+	[B2056_TX_TXLPF_IDAC_5]		= { .ghz5 = 0x001b, .ghz2 = 0x001b, NOUPLOAD, },
+	[B2056_TX_TXLPF_IDAC_6]		= { .ghz5 = 0x001b, .ghz2 = 0x001b, NOUPLOAD, },
+	[B2056_TX_TXLPF_OPAMP_IDAC]	= { .ghz5 = 0x0055, .ghz2 = 0x0055, NOUPLOAD, },
+	[B2056_TX_TXLPF_MISC]		= { .ghz5 = 0x005b, .ghz2 = 0x005b, NOUPLOAD, },
+	[B2056_TX_TXSPARE1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE4]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE5]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE6]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE7]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE8]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE9]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE10]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE11]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE12]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE13]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE14]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE15]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE16]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_STATUS_INTPA_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_STATUS_PAD_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_STATUS_PGA_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_STATUS_GM_TXLPF_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_STATUS_TXLPF_BW]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_STATUS_TXLPF_RC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+};
+
+static const struct b2056_inittab_entry b2056_inittab_rev3_rx[] = {
+	[B2056_RX_RESERVED_ADDR2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR4]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR5]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR6]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR7]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_COM_CTRL]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_COM_PU]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_COM_OVR]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_COM_RESET]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_COM_RCAL]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_COM_RC_RXLPF]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_COM_RC_TXLPF]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_COM_RC_RXHPF]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR16]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR17]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR18]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR19]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR20]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR21]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR22]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR23]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR24]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR25]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR26]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR27]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR28]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR29]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR30]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR31]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXIQCAL_RXMUX]	= { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, },
+	[B2056_RX_RSSI_PU]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RSSI_SEL]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RSSI_GAIN]		= { .ghz5 = 0x0090, .ghz2 = 0x0090, NOUPLOAD, },
+	[B2056_RX_RSSI_NB_IDAC]		= { .ghz5 = 0x0055, .ghz2 = 0x0055, NOUPLOAD, },
+	[B2056_RX_RSSI_WB2I_IDAC_1]	= { .ghz5 = 0x0015, .ghz2 = 0x0015, NOUPLOAD, },
+	[B2056_RX_RSSI_WB2I_IDAC_2]	= { .ghz5 = 0x0005, .ghz2 = 0x0005, NOUPLOAD, },
+	[B2056_RX_RSSI_WB2Q_IDAC_1]	= { .ghz5 = 0x0015, .ghz2 = 0x0015, NOUPLOAD, },
+	[B2056_RX_RSSI_WB2Q_IDAC_2]	= { .ghz5 = 0x0005, .ghz2 = 0x0005, NOUPLOAD, },
+	[B2056_RX_RSSI_POLE]		= { .ghz5 = 0x0020, .ghz2 = 0x0020, NOUPLOAD, },
+	[B2056_RX_RSSI_WB1_IDAC]	= { .ghz5 = 0x0011, .ghz2 = 0x0011, NOUPLOAD, },
+	[B2056_RX_RSSI_MISC]		= { .ghz5 = 0x0090, .ghz2 = 0x0090, NOUPLOAD, },
+	[B2056_RX_LNAA_MASTER]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_LNAA_TUNE]		= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+	[B2056_RX_LNAA_GAIN]		= { .ghz5 = 0x0032, .ghz2 = 0x0032, NOUPLOAD, },
+	[B2056_RX_LNA_A_SLOPE]		= { .ghz5 = 0x0077, .ghz2 = 0x0077, NOUPLOAD, },
+	[B2056_RX_BIASPOLE_LNAA1_IDAC]	= { .ghz5 = 0x0017, .ghz2 = 0x0017, UPLOAD, },
+	[B2056_RX_LNAA2_IDAC]		= { .ghz5 = 0x00ff, .ghz2 = 0x00ff, UPLOAD, },
+	[B2056_RX_LNA1A_MISC]		= { .ghz5 = 0x0020, .ghz2 = 0x0020, NOUPLOAD, },
+	[B2056_RX_LNAG_MASTER]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_LNAG_TUNE]		= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+	[B2056_RX_LNAG_GAIN]		= { .ghz5 = 0x0032, .ghz2 = 0x0032, NOUPLOAD, },
+	[B2056_RX_LNA_G_SLOPE]		= { .ghz5 = 0x0077, .ghz2 = 0x0077, NOUPLOAD, },
+	[B2056_RX_BIASPOLE_LNAG1_IDAC]	= { .ghz5 = 0x0017, .ghz2 = 0x0017, UPLOAD, },
+	[B2056_RX_LNAG2_IDAC]		= { .ghz5 = 0x00f0, .ghz2 = 0x00f0, UPLOAD, },
+	[B2056_RX_LNA1G_MISC]		= { .ghz5 = 0x0020, .ghz2 = 0x0020, NOUPLOAD, },
+	[B2056_RX_MIXA_MASTER]		= { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+	[B2056_RX_MIXA_VCM]		= { .ghz5 = 0x0099, .ghz2 = 0x0099, NOUPLOAD, },
+	[B2056_RX_MIXA_CTRLPTAT]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_MIXA_LOB_BIAS]	= { .ghz5 = 0x0044, .ghz2 = 0x0044, UPLOAD, },
+	[B2056_RX_MIXA_CORE_IDAC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_MIXA_CMFB_IDAC]	= { .ghz5 = 0x0044, .ghz2 = 0x0044, NOUPLOAD, },
+	[B2056_RX_MIXA_BIAS_AUX]	= { .ghz5 = 0x000f, .ghz2 = 0x000f, UPLOAD, },
+	[B2056_RX_MIXA_BIAS_MAIN]	= { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
+	[B2056_RX_MIXA_BIAS_MISC]	= { .ghz5 = 0x0004, .ghz2 = 0x0004, NOUPLOAD, },
+	[B2056_RX_MIXA_MAST_BIAS]	= { .ghz5 = 0x0050, .ghz2 = 0x0050, UPLOAD, },
+	[B2056_RX_MIXG_MASTER]		= { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+	[B2056_RX_MIXG_VCM]		= { .ghz5 = 0x0099, .ghz2 = 0x0099, NOUPLOAD, },
+	[B2056_RX_MIXG_CTRLPTAT]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_MIXG_LOB_BIAS]	= { .ghz5 = 0x0011, .ghz2 = 0x0011, NOUPLOAD, },
+	[B2056_RX_MIXG_CORE_IDAC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_MIXG_CMFB_IDAC]	= { .ghz5 = 0x0044, .ghz2 = 0x0044, NOUPLOAD, },
+	[B2056_RX_MIXG_BIAS_AUX]	= { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+	[B2056_RX_MIXG_BIAS_MAIN]	= { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
+	[B2056_RX_MIXG_BIAS_MISC]	= { .ghz5 = 0x0004, .ghz2 = 0x0004, NOUPLOAD, },
+	[B2056_RX_MIXG_MAST_BIAS]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_TIA_MASTER]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_TIA_IOPAMP]		= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_RX_TIA_QOPAMP]		= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_RX_TIA_IMISC]		= { .ghz5 = 0x0057, .ghz2 = 0x0057, NOUPLOAD, },
+	[B2056_RX_TIA_QMISC]		= { .ghz5 = 0x0057, .ghz2 = 0x0057, NOUPLOAD, },
+	[B2056_RX_TIA_GAIN]		= { .ghz5 = 0x0044, .ghz2 = 0x0044, NOUPLOAD, },
+	[B2056_RX_TIA_SPARE1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_TIA_SPARE2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_BB_LPF_MASTER]	= { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+	[B2056_RX_AACI_MASTER]		= { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+	[B2056_RX_RXLPF_IDAC]		= { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+	[B2056_RX_RXLPF_OPAMPBIAS_LOWQ]	= { .ghz5 = 0x0022, .ghz2 = 0x0022, NOUPLOAD, },
+	[B2056_RX_RXLPF_OPAMPBIAS_HIGHQ]= { .ghz5 = 0x0022, .ghz2 = 0x0022, NOUPLOAD, },
+	[B2056_RX_RXLPF_BIAS_DCCANCEL]	= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_RX_RXLPF_OUTVCM]		= { .ghz5 = 0x0023, .ghz2 = 0x0023, NOUPLOAD, },
+	[B2056_RX_RXLPF_INVCM_BODY]	= { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+	[B2056_RX_RXLPF_CC_OP]		= { .ghz5 = 0x0055, .ghz2 = 0x0055, NOUPLOAD, },
+	[B2056_RX_RXLPF_GAIN]		= { .ghz5 = 0x0023, .ghz2 = 0x0023, NOUPLOAD, },
+	[B2056_RX_RXLPF_Q_BW]		= { .ghz5 = 0x0041, .ghz2 = 0x0041, NOUPLOAD, },
+	[B2056_RX_RXLPF_HP_CORNER_BW]	= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_RX_RXLPF_RCCAL_HPC]	= { .ghz5 = 0x000a, .ghz2 = 0x000a, NOUPLOAD, },
+	[B2056_RX_RXHPF_OFF0]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXHPF_OFF1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXHPF_OFF2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXHPF_OFF3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXHPF_OFF4]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXHPF_OFF5]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXHPF_OFF6]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXHPF_OFF7]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXLPF_RCCAL_LPC]	= { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, },
+	[B2056_RX_RXLPF_OFF_0]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXLPF_OFF_1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXLPF_OFF_2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXLPF_OFF_3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXLPF_OFF_4]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_UNUSED]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_VGA_MASTER]		= { .ghz5 = 0x0022, .ghz2 = 0x0022, NOUPLOAD, },
+	[B2056_RX_VGA_BIAS]		= { .ghz5 = 0x0022, .ghz2 = 0x0022, NOUPLOAD, },
+	[B2056_RX_VGA_BIAS_DCCANCEL]	= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_RX_VGA_GAIN]		= { .ghz5 = 0x000a, .ghz2 = 0x000a, NOUPLOAD, },
+	[B2056_RX_VGA_HP_CORNER_BW]	= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_RX_VGABUF_BIAS]		= { .ghz5 = 0x0022, .ghz2 = 0x0022, NOUPLOAD, },
+	[B2056_RX_VGABUF_GAIN_BW]	= { .ghz5 = 0x0030, .ghz2 = 0x0030, NOUPLOAD, },
+	[B2056_RX_TXFBMIX_A]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_TXFBMIX_G]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE4]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE5]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE6]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE7]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE8]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE9]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE10]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE11]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE12]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE13]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE14]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE15]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE16]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_LNAA_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_LNAG_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_MIXTIA_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_RXLPF_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_VGA_BUF_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_RXLPF_Q]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_RXLPF_BUF_BW]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_RXLPF_VGA_HPC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_RXLPF_RC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_HPC_RC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+};
+
+static const struct b2056_inittab_entry b2056_inittab_rev4_syn[] = {
+	[B2056_SYN_RESERVED_ADDR2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR4]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR5]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR6]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR7]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_COM_CTRL]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_COM_PU]		= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_SYN_COM_OVR]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_COM_RESET]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_COM_RCAL]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_COM_RC_RXLPF]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_COM_RC_TXLPF]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_COM_RC_RXHPF]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR16]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR17]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR18]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR19]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR20]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR21]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR22]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR23]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR24]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR25]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR26]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR27]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR28]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR29]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR30]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR31]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_GPIO_MASTER1]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_GPIO_MASTER2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_TOPBIAS_MASTER]	= { .ghz5 = 0x0060, .ghz2 = 0x0060, NOUPLOAD, },
+	[B2056_SYN_TOPBIAS_RCAL]	= { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
+	[B2056_SYN_AFEREG]		= { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, },
+	[B2056_SYN_TEMPPROCSENSE]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_TEMPPROCSENSEIDAC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_TEMPPROCSENSERCAL]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LPO]			= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_SYN_VDDCAL_MASTER]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_VDDCAL_IDAC]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_VDDCAL_STATUS]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCAL_MASTER]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCAL_CODE_OUT]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL0]		= { .ghz5 = 0x000d, .ghz2 = 0x000d, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL1]		= { .ghz5 = 0x001f, .ghz2 = 0x001f, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL2]		= { .ghz5 = 0x0015, .ghz2 = 0x0015, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL3]		= { .ghz5 = 0x000f, .ghz2 = 0x000f, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL4]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL5]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL6]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL7]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL8]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL9]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL10]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL11]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_ZCAL_SPARE1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_ZCAL_SPARE2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_MAST1]		= { .ghz5 = 0x0013, .ghz2 = 0x0013, NOUPLOAD, },
+	[B2056_SYN_PLL_MAST2]		= { .ghz5 = 0x000f, .ghz2 = 0x000f, NOUPLOAD, },
+	[B2056_SYN_PLL_MAST3]		= { .ghz5 = 0x0018, .ghz2 = 0x0018, NOUPLOAD, },
+	[B2056_SYN_PLL_BIAS_RESET]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_XTAL0]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_XTAL1]		= { .ghz5 = 0x0020, .ghz2 = 0x0020, NOUPLOAD, },
+	[B2056_SYN_PLL_XTAL3]		= { .ghz5 = 0x0020, .ghz2 = 0x0020, NOUPLOAD, },
+	[B2056_SYN_PLL_XTAL4]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_XTAL5]		= { .ghz5 = 0x0077, .ghz2 = 0x0077, NOUPLOAD, },
+	[B2056_SYN_PLL_XTAL6]		= { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+	[B2056_SYN_PLL_REFDIV]		= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_SYN_PLL_PFD]		= { .ghz5 = 0x0004, .ghz2 = 0x0004, NOUPLOAD, },
+	[B2056_SYN_PLL_CP1]		= { .ghz5 = 0x000f, .ghz2 = 0x000f, NOUPLOAD, },
+	[B2056_SYN_PLL_CP2]		= { .ghz5 = 0x0030, .ghz2 = 0x0030, NOUPLOAD, },
+	[B2056_SYN_PLL_CP3]		= { .ghz5 = 0x0032, .ghz2 = 0x0032, NOUPLOAD, },
+	[B2056_SYN_PLL_LOOPFILTER1]	= { .ghz5 = 0x000d, .ghz2 = 0x000d, NOUPLOAD, },
+	[B2056_SYN_PLL_LOOPFILTER2]	= { .ghz5 = 0x000d, .ghz2 = 0x000d, NOUPLOAD, },
+	[B2056_SYN_PLL_LOOPFILTER3]	= { .ghz5 = 0x0004, .ghz2 = 0x0004, NOUPLOAD, },
+	[B2056_SYN_PLL_LOOPFILTER4]	= { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
+	[B2056_SYN_PLL_LOOPFILTER5]	= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_SYN_PLL_MMD1]		= { .ghz5 = 0x001c, .ghz2 = 0x001c, NOUPLOAD, },
+	[B2056_SYN_PLL_MMD2]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_SYN_PLL_VCO1]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_SYN_PLL_VCO2]		= { .ghz5 = 0x00f7, .ghz2 = 0x00f7, UPLOAD, },
+	[B2056_SYN_PLL_MONITOR1]	= { .ghz5 = 0x00b4, .ghz2 = 0x00b4, NOUPLOAD, },
+	[B2056_SYN_PLL_MONITOR2]	= { .ghz5 = 0x00d2, .ghz2 = 0x00d2, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL4]		= { .ghz5 = 0x0004, .ghz2 = 0x0004, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL5]		= { .ghz5 = 0x0096, .ghz2 = 0x0096, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL6]		= { .ghz5 = 0x003e, .ghz2 = 0x003e, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL7]		= { .ghz5 = 0x003e, .ghz2 = 0x003e, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL8]		= { .ghz5 = 0x0013, .ghz2 = 0x0013, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL9]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL10]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL11]	= { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL12]	= { .ghz5 = 0x0007, .ghz2 = 0x0007, UPLOAD, },
+	[B2056_SYN_PLL_VCOCAL13]	= { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+	[B2056_SYN_PLL_VREG]		= { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, },
+	[B2056_SYN_PLL_STATUS1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_STATUS2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_STATUS3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PU0]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PU1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PU2]		= { .ghz5 = 0x0040, .ghz2 = 0x0040, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PU3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PU5]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PU6]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PU7]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PU8]		= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_SYN_LOGEN_BIAS_RESET]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_RCCR1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_VCOBUF1]	= { .ghz5 = 0x0060, .ghz2 = 0x0060, NOUPLOAD, },
+	[B2056_SYN_LOGEN_MIXER1]	= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_MIXER2]	= { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, },
+	[B2056_SYN_LOGEN_BUF1]		= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGENBUF2]		= { .ghz5 = 0x008f, .ghz2 = 0x008f, UPLOAD, },
+	[B2056_SYN_LOGEN_BUF3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_BUF4]		= { .ghz5 = 0x00cc, .ghz2 = 0x00cc, NOUPLOAD, },
+	[B2056_SYN_LOGEN_DIV1]		= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_SYN_LOGEN_DIV2]		= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_DIV3]		= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACL1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACL2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACL3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACL4]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACL5]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACL6]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACLOUT]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACLCAL1]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACLCAL2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACLCAL3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_CALEN]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PEAKDET1]	= { .ghz5 = 0x00ff, .ghz2 = 0x00ff, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CORE_ACL_OVR]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_RX_DIFF_ACL_OVR]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_TX_DIFF_ACL_OVR]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_RX_CMOS_ACL_OVR]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_TX_CMOS_ACL_OVR]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_VCOBUF2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_MIXER3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_BUF5]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_BUF6]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFRX1]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFRX2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFRX3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFRX4]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFTX1]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFTX2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFTX3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFTX4]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSRX1]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSRX2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSRX3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSRX4]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSTX1]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSTX2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSTX3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSTX4]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_VCOBUF2_OVRVAL]= { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
+	[B2056_SYN_LOGEN_MIXER3_OVRVAL]	= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_BUF5_OVRVAL]	= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_BUF6_OVRVAL]	= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFRX1_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFRX2_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFRX3_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFRX4_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFTX1_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFTX2_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFTX3_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFTX4_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSRX1_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSRX2_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSRX3_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSRX4_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSTX1_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSTX2_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSTX3_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSTX4_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACL_WAITCNT]	= { .ghz5 = 0x000a, .ghz2 = 0x000a, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CORE_CALVALID]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_RX_CMOS_CALVALID]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_TX_CMOS_VALID]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+};
+
+static const struct b2056_inittab_entry b2056_inittab_rev4_tx[] = {
+	[B2056_TX_RESERVED_ADDR2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR4]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR5]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR6]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR7]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_COM_CTRL]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_COM_PU]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_COM_OVR]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_COM_RESET]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_COM_RCAL]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_COM_RC_RXLPF]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_COM_RC_TXLPF]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_COM_RC_RXHPF]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR16]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR17]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR18]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR19]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR20]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR21]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR22]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR23]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR24]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR25]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR26]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR27]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR28]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR29]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR30]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR31]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_IQCAL_GAIN_BW]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_LOFT_FINE_I]		= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+	[B2056_TX_LOFT_FINE_Q]		= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+	[B2056_TX_LOFT_COARSE_I]	= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+	[B2056_TX_LOFT_COARSE_Q]	= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+	[B2056_TX_TX_COM_MASTER1]	= { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, },
+	[B2056_TX_TX_COM_MASTER2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RXIQCAL_TXMUX]	= { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, },
+	[B2056_TX_TX_SSI_MASTER]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_IQCAL_VCM_HG]		= { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, },
+	[B2056_TX_IQCAL_IDAC]		= { .ghz5 = 0x0037, .ghz2 = 0x0037, NOUPLOAD, },
+	[B2056_TX_TSSI_VCM]		= { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, },
+	[B2056_TX_TX_AMP_DET]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TX_SSI_MUX]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TSSIA]		= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_TX_TSSIG]		= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_TX_TSSI_MISC1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TSSI_MISC2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TSSI_MISC3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_PA_SPARE1]		= { .ghz5 = 0x0011, .ghz2 = 0x0011, NOUPLOAD, },
+	[B2056_TX_PA_SPARE2]		= { .ghz5 = 0x0011, .ghz2 = 0x0011, NOUPLOAD, },
+	[B2056_TX_INTPAA_MASTER]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAA_GAIN]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAA_BOOST_TUNE]	= { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, },
+	[B2056_TX_INTPAA_IAUX_STAT]	= { .ghz5 = 0x000f, .ghz2 = 0x000f, NOUPLOAD, },
+	[B2056_TX_INTPAA_IAUX_DYN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAA_IMAIN_STAT]	= { .ghz5 = 0x002d, .ghz2 = 0x002d, NOUPLOAD, },
+	[B2056_TX_INTPAA_IMAIN_DYN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAA_CASCBIAS]	= { .ghz5 = 0x006e, .ghz2 = 0x006e, NOUPLOAD, },
+	[B2056_TX_INTPAA_PASLOPE]	= { .ghz5 = 0x00f0, .ghz2 = 0x00f0, UPLOAD, },
+	[B2056_TX_INTPAA_PA_MISC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAG_MASTER]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAG_GAIN]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAG_BOOST_TUNE]	= { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, },
+	[B2056_TX_INTPAG_IAUX_STAT]	= { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, },
+	[B2056_TX_INTPAG_IAUX_DYN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAG_IMAIN_STAT]	= { .ghz5 = 0x001e, .ghz2 = 0x001e, NOUPLOAD, },
+	[B2056_TX_INTPAG_IMAIN_DYN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAG_CASCBIAS]	= { .ghz5 = 0x006e, .ghz2 = 0x006e, NOUPLOAD, },
+	[B2056_TX_INTPAG_PASLOPE]	= { .ghz5 = 0x00f0, .ghz2 = 0x00f0, UPLOAD, },
+	[B2056_TX_INTPAG_PA_MISC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_PADA_MASTER]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_TX_PADA_IDAC]		= { .ghz5 = 0x00ff, .ghz2 = 0x00ff, UPLOAD, },
+	[B2056_TX_PADA_CASCBIAS]	= { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, },
+	[B2056_TX_PADA_GAIN]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_PADA_BOOST_TUNE]	= { .ghz5 = 0x0038, .ghz2 = 0x0038, NOUPLOAD, },
+	[B2056_TX_PADA_SLOPE]		= { .ghz5 = 0x0070, .ghz2 = 0x0070, UPLOAD, },
+	[B2056_TX_PADG_MASTER]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_TX_PADG_IDAC]		= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+	[B2056_TX_PADG_CASCBIAS]	= { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, },
+	[B2056_TX_PADG_GAIN]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_PADG_BOOST_TUNE]	= { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+	[B2056_TX_PADG_SLOPE]		= { .ghz5 = 0x0070, .ghz2 = 0x0070, UPLOAD, },
+	[B2056_TX_PGAA_MASTER]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_TX_PGAA_IDAC]		= { .ghz5 = 0x00ff, .ghz2 = 0x00ff, UPLOAD, },
+	[B2056_TX_PGAA_GAIN]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_PGAA_BOOST_TUNE]	= { .ghz5 = 0x0083, .ghz2 = 0x0083, NOUPLOAD, },
+	[B2056_TX_PGAA_SLOPE]		= { .ghz5 = 0x0077, .ghz2 = 0x0077, UPLOAD, },
+	[B2056_TX_PGAA_MISC]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_PGAG_MASTER]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_TX_PGAG_IDAC]		= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+	[B2056_TX_PGAG_GAIN]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_PGAG_BOOST_TUNE]	= { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+	[B2056_TX_PGAG_SLOPE]		= { .ghz5 = 0x0077, .ghz2 = 0x0077, UPLOAD, },
+	[B2056_TX_PGAG_MISC]		= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_TX_MIXA_MASTER]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_MIXA_BOOST_TUNE]	= { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+	[B2056_TX_MIXG]			= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_MIXG_BOOST_TUNE]	= { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+	[B2056_TX_BB_GM_MASTER]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_GMBB_GM]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_GMBB_IDAC]		= { .ghz5 = 0x0072, .ghz2 = 0x0072, UPLOAD, },
+	[B2056_TX_TXLPF_MASTER]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_RCCAL]		= { .ghz5 = 0x000a, .ghz2 = 0x000a, NOUPLOAD, },
+	[B2056_TX_TXLPF_RCCAL_OFF0]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_RCCAL_OFF1]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_RCCAL_OFF2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_RCCAL_OFF3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_RCCAL_OFF4]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_RCCAL_OFF5]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_RCCAL_OFF6]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_BW]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_TX_TXLPF_GAIN]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_IDAC]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_IDAC_0]		= { .ghz5 = 0x000e, .ghz2 = 0x000e, NOUPLOAD, },
+	[B2056_TX_TXLPF_IDAC_1]		= { .ghz5 = 0x000e, .ghz2 = 0x000e, NOUPLOAD, },
+	[B2056_TX_TXLPF_IDAC_2]		= { .ghz5 = 0x000e, .ghz2 = 0x000e, NOUPLOAD, },
+	[B2056_TX_TXLPF_IDAC_3]		= { .ghz5 = 0x0013, .ghz2 = 0x0013, NOUPLOAD, },
+	[B2056_TX_TXLPF_IDAC_4]		= { .ghz5 = 0x0013, .ghz2 = 0x0013, NOUPLOAD, },
+	[B2056_TX_TXLPF_IDAC_5]		= { .ghz5 = 0x001b, .ghz2 = 0x001b, NOUPLOAD, },
+	[B2056_TX_TXLPF_IDAC_6]		= { .ghz5 = 0x001b, .ghz2 = 0x001b, NOUPLOAD, },
+	[B2056_TX_TXLPF_OPAMP_IDAC]	= { .ghz5 = 0x0055, .ghz2 = 0x0055, NOUPLOAD, },
+	[B2056_TX_TXLPF_MISC]		= { .ghz5 = 0x005b, .ghz2 = 0x005b, NOUPLOAD, },
+	[B2056_TX_TXSPARE1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE4]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE5]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE6]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE7]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE8]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE9]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE10]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE11]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE12]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE13]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE14]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE15]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE16]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_STATUS_INTPA_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_STATUS_PAD_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_STATUS_PGA_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_STATUS_GM_TXLPF_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_STATUS_TXLPF_BW]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_STATUS_TXLPF_RC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+};
+
+static const struct b2056_inittab_entry b2056_inittab_rev4_rx[] = {
+	[B2056_RX_RESERVED_ADDR2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR4]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR5]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR6]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR7]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_COM_CTRL]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_COM_PU]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_COM_OVR]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_COM_RESET]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_COM_RCAL]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_COM_RC_RXLPF]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_COM_RC_TXLPF]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_COM_RC_RXHPF]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR16]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR17]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR18]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR19]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR20]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR21]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR22]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR23]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR24]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR25]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR26]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR27]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR28]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR29]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR30]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR31]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXIQCAL_RXMUX]	= { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, },
+	[B2056_RX_RSSI_PU]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RSSI_SEL]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RSSI_GAIN]		= { .ghz5 = 0x0090, .ghz2 = 0x0090, NOUPLOAD, },
+	[B2056_RX_RSSI_NB_IDAC]		= { .ghz5 = 0x0055, .ghz2 = 0x0055, NOUPLOAD, },
+	[B2056_RX_RSSI_WB2I_IDAC_1]	= { .ghz5 = 0x0015, .ghz2 = 0x0015, NOUPLOAD, },
+	[B2056_RX_RSSI_WB2I_IDAC_2]	= { .ghz5 = 0x0005, .ghz2 = 0x0005, NOUPLOAD, },
+	[B2056_RX_RSSI_WB2Q_IDAC_1]	= { .ghz5 = 0x0015, .ghz2 = 0x0015, NOUPLOAD, },
+	[B2056_RX_RSSI_WB2Q_IDAC_2]	= { .ghz5 = 0x0005, .ghz2 = 0x0005, NOUPLOAD, },
+	[B2056_RX_RSSI_POLE]		= { .ghz5 = 0x0020, .ghz2 = 0x0020, NOUPLOAD, },
+	[B2056_RX_RSSI_WB1_IDAC]	= { .ghz5 = 0x0011, .ghz2 = 0x0011, NOUPLOAD, },
+	[B2056_RX_RSSI_MISC]		= { .ghz5 = 0x0090, .ghz2 = 0x0090, NOUPLOAD, },
+	[B2056_RX_LNAA_MASTER]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_LNAA_TUNE]		= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+	[B2056_RX_LNAA_GAIN]		= { .ghz5 = 0x0032, .ghz2 = 0x0032, NOUPLOAD, },
+	[B2056_RX_LNA_A_SLOPE]		= { .ghz5 = 0x0077, .ghz2 = 0x0077, NOUPLOAD, },
+	[B2056_RX_BIASPOLE_LNAA1_IDAC]	= { .ghz5 = 0x0017, .ghz2 = 0x0017, UPLOAD, },
+	[B2056_RX_LNAA2_IDAC]		= { .ghz5 = 0x00ff, .ghz2 = 0x00ff, UPLOAD, },
+	[B2056_RX_LNA1A_MISC]		= { .ghz5 = 0x0020, .ghz2 = 0x0020, NOUPLOAD, },
+	[B2056_RX_LNAG_MASTER]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_LNAG_TUNE]		= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+	[B2056_RX_LNAG_GAIN]		= { .ghz5 = 0x0032, .ghz2 = 0x0032, NOUPLOAD, },
+	[B2056_RX_LNA_G_SLOPE]		= { .ghz5 = 0x0077, .ghz2 = 0x0077, NOUPLOAD, },
+	[B2056_RX_BIASPOLE_LNAG1_IDAC]	= { .ghz5 = 0x0017, .ghz2 = 0x0017, UPLOAD, },
+	[B2056_RX_LNAG2_IDAC]		= { .ghz5 = 0x00f0, .ghz2 = 0x00f0, UPLOAD, },
+	[B2056_RX_LNA1G_MISC]		= { .ghz5 = 0x0020, .ghz2 = 0x0020, NOUPLOAD, },
+	[B2056_RX_MIXA_MASTER]		= { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+	[B2056_RX_MIXA_VCM]		= { .ghz5 = 0x0055, .ghz2 = 0x0055, UPLOAD, },
+	[B2056_RX_MIXA_CTRLPTAT]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_MIXA_LOB_BIAS]	= { .ghz5 = 0x0044, .ghz2 = 0x0044, UPLOAD, },
+	[B2056_RX_MIXA_CORE_IDAC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_MIXA_CMFB_IDAC]	= { .ghz5 = 0x0044, .ghz2 = 0x0044, NOUPLOAD, },
+	[B2056_RX_MIXA_BIAS_AUX]	= { .ghz5 = 0x000f, .ghz2 = 0x000f, UPLOAD, },
+	[B2056_RX_MIXA_BIAS_MAIN]	= { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
+	[B2056_RX_MIXA_BIAS_MISC]	= { .ghz5 = 0x0004, .ghz2 = 0x0004, NOUPLOAD, },
+	[B2056_RX_MIXA_MAST_BIAS]	= { .ghz5 = 0x0050, .ghz2 = 0x0050, UPLOAD, },
+	[B2056_RX_MIXG_MASTER]		= { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+	[B2056_RX_MIXG_VCM]		= { .ghz5 = 0x0055, .ghz2 = 0x0055, UPLOAD, },
+	[B2056_RX_MIXG_CTRLPTAT]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_MIXG_LOB_BIAS]	= { .ghz5 = 0x0011, .ghz2 = 0x0011, NOUPLOAD, },
+	[B2056_RX_MIXG_CORE_IDAC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_MIXG_CMFB_IDAC]	= { .ghz5 = 0x0044, .ghz2 = 0x0044, NOUPLOAD, },
+	[B2056_RX_MIXG_BIAS_AUX]	= { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+	[B2056_RX_MIXG_BIAS_MAIN]	= { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
+	[B2056_RX_MIXG_BIAS_MISC]	= { .ghz5 = 0x0004, .ghz2 = 0x0004, NOUPLOAD, },
+	[B2056_RX_MIXG_MAST_BIAS]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_TIA_MASTER]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_TIA_IOPAMP]		= { .ghz5 = 0x0026, .ghz2 = 0x0026, UPLOAD, },
+	[B2056_RX_TIA_QOPAMP]		= { .ghz5 = 0x0026, .ghz2 = 0x0026, UPLOAD, },
+	[B2056_RX_TIA_IMISC]		= { .ghz5 = 0x000f, .ghz2 = 0x000f, UPLOAD, },
+	[B2056_RX_TIA_QMISC]		= { .ghz5 = 0x000f, .ghz2 = 0x000f, UPLOAD, },
+	[B2056_RX_TIA_GAIN]		= { .ghz5 = 0x0044, .ghz2 = 0x0044, NOUPLOAD, },
+	[B2056_RX_TIA_SPARE1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_TIA_SPARE2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_BB_LPF_MASTER]	= { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+	[B2056_RX_AACI_MASTER]		= { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+	[B2056_RX_RXLPF_IDAC]		= { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+	[B2056_RX_RXLPF_OPAMPBIAS_LOWQ]	= { .ghz5 = 0x0022, .ghz2 = 0x0022, NOUPLOAD, },
+	[B2056_RX_RXLPF_OPAMPBIAS_HIGHQ]= { .ghz5 = 0x0022, .ghz2 = 0x0022, NOUPLOAD, },
+	[B2056_RX_RXLPF_BIAS_DCCANCEL]	= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_RX_RXLPF_OUTVCM]		= { .ghz5 = 0x002f, .ghz2 = 0x002f, UPLOAD, },
+	[B2056_RX_RXLPF_INVCM_BODY]	= { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+	[B2056_RX_RXLPF_CC_OP]		= { .ghz5 = 0x0055, .ghz2 = 0x0055, NOUPLOAD, },
+	[B2056_RX_RXLPF_GAIN]		= { .ghz5 = 0x0023, .ghz2 = 0x0023, NOUPLOAD, },
+	[B2056_RX_RXLPF_Q_BW]		= { .ghz5 = 0x0041, .ghz2 = 0x0041, NOUPLOAD, },
+	[B2056_RX_RXLPF_HP_CORNER_BW]	= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_RX_RXLPF_RCCAL_HPC]	= { .ghz5 = 0x000a, .ghz2 = 0x000a, NOUPLOAD, },
+	[B2056_RX_RXHPF_OFF0]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXHPF_OFF1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXHPF_OFF2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXHPF_OFF3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXHPF_OFF4]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXHPF_OFF5]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXHPF_OFF6]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXHPF_OFF7]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXLPF_RCCAL_LPC]	= { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, },
+	[B2056_RX_RXLPF_OFF_0]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXLPF_OFF_1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXLPF_OFF_2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXLPF_OFF_3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXLPF_OFF_4]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_UNUSED]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_VGA_MASTER]		= { .ghz5 = 0x0022, .ghz2 = 0x0022, NOUPLOAD, },
+	[B2056_RX_VGA_BIAS]		= { .ghz5 = 0x0022, .ghz2 = 0x0022, NOUPLOAD, },
+	[B2056_RX_VGA_BIAS_DCCANCEL]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, UPLOAD, },
+	[B2056_RX_VGA_GAIN]		= { .ghz5 = 0x000a, .ghz2 = 0x000a, NOUPLOAD, },
+	[B2056_RX_VGA_HP_CORNER_BW]	= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_RX_VGABUF_BIAS]		= { .ghz5 = 0x0022, .ghz2 = 0x0022, NOUPLOAD, },
+	[B2056_RX_VGABUF_GAIN_BW]	= { .ghz5 = 0x0030, .ghz2 = 0x0030, NOUPLOAD, },
+	[B2056_RX_TXFBMIX_A]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_TXFBMIX_G]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE4]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE5]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE6]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE7]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE8]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE9]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE10]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE11]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE12]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE13]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE14]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE15]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE16]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_LNAA_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_LNAG_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_MIXTIA_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_RXLPF_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_VGA_BUF_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_RXLPF_Q]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_RXLPF_BUF_BW]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_RXLPF_VGA_HPC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_RXLPF_RC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_HPC_RC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+};
+
+static const struct b2056_inittab_entry b2056_inittab_rev5_syn[] = {
+	[B2056_SYN_RESERVED_ADDR2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR4]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR5]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR6]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR7]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_COM_CTRL]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_COM_PU]		= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_SYN_COM_OVR]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_COM_RESET]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_COM_RCAL]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_COM_RC_RXLPF]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_COM_RC_TXLPF]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_COM_RC_RXHPF]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR16]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR17]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR18]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR19]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR20]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR21]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR22]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR23]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR24]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR25]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR26]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR27]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR28]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR29]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR30]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR31]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_GPIO_MASTER1]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_GPIO_MASTER2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_TOPBIAS_MASTER]	= { .ghz5 = 0x0060, .ghz2 = 0x0060, NOUPLOAD, },
+	[B2056_SYN_TOPBIAS_RCAL]	= { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
+	[B2056_SYN_AFEREG]		= { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, },
+	[B2056_SYN_TEMPPROCSENSE]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_TEMPPROCSENSEIDAC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_TEMPPROCSENSERCAL]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LPO]			= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_SYN_VDDCAL_MASTER]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_VDDCAL_IDAC]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_VDDCAL_STATUS]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCAL_MASTER]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCAL_CODE_OUT]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL0]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL1]		= { .ghz5 = 0x001f, .ghz2 = 0x001f, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL2]		= { .ghz5 = 0x0015, .ghz2 = 0x0015, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL3]		= { .ghz5 = 0x000f, .ghz2 = 0x000f, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL4]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL5]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL6]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL7]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL8]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL9]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL10]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL11]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_ZCAL_SPARE1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_ZCAL_SPARE2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_MAST1]		= { .ghz5 = 0x0013, .ghz2 = 0x0013, NOUPLOAD, },
+	[B2056_SYN_PLL_MAST2]		= { .ghz5 = 0x000f, .ghz2 = 0x000f, NOUPLOAD, },
+	[B2056_SYN_PLL_MAST3]		= { .ghz5 = 0x0018, .ghz2 = 0x0018, NOUPLOAD, },
+	[B2056_SYN_PLL_BIAS_RESET]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_XTAL0]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_XTAL1]		= { .ghz5 = 0x0020, .ghz2 = 0x0020, NOUPLOAD, },
+	[B2056_SYN_PLL_XTAL3]		= { .ghz5 = 0x0020, .ghz2 = 0x0020, NOUPLOAD, },
+	[B2056_SYN_PLL_XTAL4]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_XTAL5]		= { .ghz5 = 0x0077, .ghz2 = 0x0077, NOUPLOAD, },
+	[B2056_SYN_PLL_XTAL6]		= { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+	[B2056_SYN_PLL_REFDIV]		= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_SYN_PLL_PFD]		= { .ghz5 = 0x0004, .ghz2 = 0x0004, NOUPLOAD, },
+	[B2056_SYN_PLL_CP1]		= { .ghz5 = 0x000f, .ghz2 = 0x000f, NOUPLOAD, },
+	[B2056_SYN_PLL_CP2]		= { .ghz5 = 0x0030, .ghz2 = 0x0030, NOUPLOAD, },
+	[B2056_SYN_PLL_CP3]		= { .ghz5 = 0x0032, .ghz2 = 0x0032, NOUPLOAD, },
+	[B2056_SYN_PLL_LOOPFILTER1]	= { .ghz5 = 0x000d, .ghz2 = 0x000d, NOUPLOAD, },
+	[B2056_SYN_PLL_LOOPFILTER2]	= { .ghz5 = 0x000d, .ghz2 = 0x000d, NOUPLOAD, },
+	[B2056_SYN_PLL_LOOPFILTER3]	= { .ghz5 = 0x0004, .ghz2 = 0x0004, NOUPLOAD, },
+	[B2056_SYN_PLL_LOOPFILTER4]	= { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
+	[B2056_SYN_PLL_LOOPFILTER5]	= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_SYN_PLL_MMD1]		= { .ghz5 = 0x001c, .ghz2 = 0x001c, NOUPLOAD, },
+	[B2056_SYN_PLL_MMD2]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_SYN_PLL_VCO1]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_SYN_PLL_VCO2]		= { .ghz5 = 0x00f7, .ghz2 = 0x00f7, UPLOAD, },
+	[B2056_SYN_PLL_MONITOR1]	= { .ghz5 = 0x00b4, .ghz2 = 0x00b4, NOUPLOAD, },
+	[B2056_SYN_PLL_MONITOR2]	= { .ghz5 = 0x00d2, .ghz2 = 0x00d2, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL4]		= { .ghz5 = 0x0004, .ghz2 = 0x0004, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL5]		= { .ghz5 = 0x0096, .ghz2 = 0x0096, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL6]		= { .ghz5 = 0x003e, .ghz2 = 0x003e, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL7]		= { .ghz5 = 0x003e, .ghz2 = 0x003e, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL8]		= { .ghz5 = 0x0013, .ghz2 = 0x0013, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL9]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL10]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL11]	= { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL12]	= { .ghz5 = 0x0007, .ghz2 = 0x0007, UPLOAD, },
+	[B2056_SYN_PLL_VCOCAL13]	= { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+	[B2056_SYN_PLL_VREG]		= { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, },
+	[B2056_SYN_PLL_STATUS1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_STATUS2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_STATUS3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PU0]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PU1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PU2]		= { .ghz5 = 0x0040, .ghz2 = 0x0040, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PU3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PU5]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PU6]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PU7]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PU8]		= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_SYN_LOGEN_BIAS_RESET]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_RCCR1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_VCOBUF1]	= { .ghz5 = 0x0060, .ghz2 = 0x0060, NOUPLOAD, },
+	[B2056_SYN_LOGEN_MIXER1]	= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_MIXER2]	= { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, },
+	[B2056_SYN_LOGEN_BUF1]		= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGENBUF2]		= { .ghz5 = 0x008f, .ghz2 = 0x008f, UPLOAD, },
+	[B2056_SYN_LOGEN_BUF3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_BUF4]		= { .ghz5 = 0x00cc, .ghz2 = 0x00cc, NOUPLOAD, },
+	[B2056_SYN_LOGEN_DIV1]		= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_SYN_LOGEN_DIV2]		= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_DIV3]		= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACL1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACL2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACL3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACL4]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACL5]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACL6]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACLOUT]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACLCAL1]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACLCAL2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACLCAL3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_CALEN]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PEAKDET1]	= { .ghz5 = 0x00ff, .ghz2 = 0x00ff, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CORE_ACL_OVR]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_RX_DIFF_ACL_OVR]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_TX_DIFF_ACL_OVR]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_RX_CMOS_ACL_OVR]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_TX_CMOS_ACL_OVR]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_VCOBUF2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_MIXER3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_BUF5]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_BUF6]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFRX1]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFRX2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFRX3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFRX4]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFTX1]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFTX2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFTX3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFTX4]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSRX1]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSRX2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSRX3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSRX4]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSTX1]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSTX2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSTX3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSTX4]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_VCOBUF2_OVRVAL]= { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
+	[B2056_SYN_LOGEN_MIXER3_OVRVAL]	= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_BUF5_OVRVAL]	= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_BUF6_OVRVAL]	= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFRX1_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFRX2_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFRX3_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFRX4_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFTX1_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFTX2_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFTX3_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFTX4_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSRX1_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSRX2_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSRX3_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSRX4_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSTX1_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSTX2_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSTX3_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSTX4_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACL_WAITCNT]	= { .ghz5 = 0x000a, .ghz2 = 0x000a, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CORE_CALVALID]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_RX_CMOS_CALVALID]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_TX_CMOS_VALID]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+};
+
+static const struct b2056_inittab_entry b2056_inittab_rev5_tx[] = {
+	[B2056_TX_RESERVED_ADDR2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR4]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR5]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR6]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR7]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_COM_CTRL]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_COM_PU]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_COM_OVR]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_COM_RESET]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_COM_RCAL]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_COM_RC_RXLPF]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_COM_RC_TXLPF]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_COM_RC_RXHPF]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR16]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR17]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR18]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR19]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR20]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR21]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR22]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR23]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR24]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR25]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR26]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR27]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR28]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR29]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR30]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR31]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_IQCAL_GAIN_BW]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_LOFT_FINE_I]		= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+	[B2056_TX_LOFT_FINE_Q]		= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+	[B2056_TX_LOFT_COARSE_I]	= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+	[B2056_TX_LOFT_COARSE_Q]	= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+	[B2056_TX_TX_COM_MASTER1]	= { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, },
+	[B2056_TX_TX_COM_MASTER2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RXIQCAL_TXMUX]	= { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, },
+	[B2056_TX_TX_SSI_MASTER]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_IQCAL_VCM_HG]		= { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, },
+	[B2056_TX_IQCAL_IDAC]		= { .ghz5 = 0x0037, .ghz2 = 0x0037, NOUPLOAD, },
+	[B2056_TX_TSSI_VCM]		= { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, },
+	[B2056_TX_TX_AMP_DET]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TX_SSI_MUX]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TSSIA]		= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_TX_TSSIG]		= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_TX_TSSI_MISC1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TSSI_MISC2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TSSI_MISC3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_PA_SPARE1]		= { .ghz5 = 0x0011, .ghz2 = 0x0011, NOUPLOAD, },
+	[B2056_TX_PA_SPARE2]		= { .ghz5 = 0x0011, .ghz2 = 0x0011, NOUPLOAD, },
+	[B2056_TX_INTPAA_MASTER]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAA_GAIN]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAA_BOOST_TUNE]	= { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, },
+	[B2056_TX_INTPAA_IAUX_STAT]	= { .ghz5 = 0x000f, .ghz2 = 0x000f, NOUPLOAD, },
+	[B2056_TX_INTPAA_IAUX_DYN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAA_IMAIN_STAT]	= { .ghz5 = 0x002d, .ghz2 = 0x002d, NOUPLOAD, },
+	[B2056_TX_INTPAA_IMAIN_DYN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAA_CASCBIAS]	= { .ghz5 = 0x006e, .ghz2 = 0x006e, NOUPLOAD, },
+	[B2056_TX_INTPAA_PASLOPE]	= { .ghz5 = 0x00f0, .ghz2 = 0x00f0, UPLOAD, },
+	[B2056_TX_INTPAA_PA_MISC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAG_MASTER]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAG_GAIN]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAG_BOOST_TUNE]	= { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, },
+	[B2056_TX_INTPAG_IAUX_STAT]	= { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, },
+	[B2056_TX_INTPAG_IAUX_DYN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAG_IMAIN_STAT]	= { .ghz5 = 0x001e, .ghz2 = 0x001e, NOUPLOAD, },
+	[B2056_TX_INTPAG_IMAIN_DYN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAG_CASCBIAS]	= { .ghz5 = 0x006e, .ghz2 = 0x006e, NOUPLOAD, },
+	[B2056_TX_INTPAG_PASLOPE]	= { .ghz5 = 0x00f0, .ghz2 = 0x00f0, UPLOAD, },
+	[B2056_TX_INTPAG_PA_MISC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_PADA_MASTER]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_TX_PADA_IDAC]		= { .ghz5 = 0x00ff, .ghz2 = 0x00ff, UPLOAD, },
+	[B2056_TX_PADA_CASCBIAS]	= { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, },
+	[B2056_TX_PADA_GAIN]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_PADA_BOOST_TUNE]	= { .ghz5 = 0x0038, .ghz2 = 0x0038, NOUPLOAD, },
+	[B2056_TX_PADA_SLOPE]		= { .ghz5 = 0x0070, .ghz2 = 0x0070, UPLOAD, },
+	[B2056_TX_PADG_MASTER]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_TX_PADG_IDAC]		= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+	[B2056_TX_PADG_CASCBIAS]	= { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, },
+	[B2056_TX_PADG_GAIN]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_PADG_BOOST_TUNE]	= { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+	[B2056_TX_PADG_SLOPE]		= { .ghz5 = 0x0070, .ghz2 = 0x0070, UPLOAD, },
+	[B2056_TX_PGAA_MASTER]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_TX_PGAA_IDAC]		= { .ghz5 = 0x00ff, .ghz2 = 0x00ff, UPLOAD, },
+	[B2056_TX_PGAA_GAIN]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_PGAA_BOOST_TUNE]	= { .ghz5 = 0x0083, .ghz2 = 0x0083, NOUPLOAD, },
+	[B2056_TX_PGAA_SLOPE]		= { .ghz5 = 0x0077, .ghz2 = 0x0077, UPLOAD, },
+	[B2056_TX_PGAA_MISC]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_PGAG_MASTER]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_TX_PGAG_IDAC]		= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+	[B2056_TX_PGAG_GAIN]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_PGAG_BOOST_TUNE]	= { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+	[B2056_TX_PGAG_SLOPE]		= { .ghz5 = 0x0077, .ghz2 = 0x0077, UPLOAD, },
+	[B2056_TX_PGAG_MISC]		= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_TX_MIXA_MASTER]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_MIXA_BOOST_TUNE]	= { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+	[B2056_TX_MIXG]			= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_MIXG_BOOST_TUNE]	= { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+	[B2056_TX_BB_GM_MASTER]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_GMBB_GM]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_GMBB_IDAC]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, UPLOAD, },
+	[B2056_TX_TXLPF_MASTER]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_RCCAL]		= { .ghz5 = 0x000a, .ghz2 = 0x000a, NOUPLOAD, },
+	[B2056_TX_TXLPF_RCCAL_OFF0]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_RCCAL_OFF1]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_RCCAL_OFF2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_RCCAL_OFF3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_RCCAL_OFF4]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_RCCAL_OFF5]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_RCCAL_OFF6]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_BW]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_TX_TXLPF_GAIN]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_IDAC]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_IDAC_0]		= { .ghz5 = 0x000e, .ghz2 = 0x000e, NOUPLOAD, },
+	[B2056_TX_TXLPF_IDAC_1]		= { .ghz5 = 0x000e, .ghz2 = 0x000e, NOUPLOAD, },
+	[B2056_TX_TXLPF_IDAC_2]		= { .ghz5 = 0x000e, .ghz2 = 0x000e, NOUPLOAD, },
+	[B2056_TX_TXLPF_IDAC_3]		= { .ghz5 = 0x0013, .ghz2 = 0x0013, NOUPLOAD, },
+	[B2056_TX_TXLPF_IDAC_4]		= { .ghz5 = 0x0013, .ghz2 = 0x0013, NOUPLOAD, },
+	[B2056_TX_TXLPF_IDAC_5]		= { .ghz5 = 0x001b, .ghz2 = 0x001b, NOUPLOAD, },
+	[B2056_TX_TXLPF_IDAC_6]		= { .ghz5 = 0x001b, .ghz2 = 0x001b, NOUPLOAD, },
+	[B2056_TX_TXLPF_OPAMP_IDAC]	= { .ghz5 = 0x0055, .ghz2 = 0x0055, NOUPLOAD, },
+	[B2056_TX_TXLPF_MISC]		= { .ghz5 = 0x005b, .ghz2 = 0x005b, NOUPLOAD, },
+	[B2056_TX_TXSPARE1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE4]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE5]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE6]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE7]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE8]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE9]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE10]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE11]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE12]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE13]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE14]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE15]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE16]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_STATUS_INTPA_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_STATUS_PAD_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_STATUS_PGA_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_STATUS_GM_TXLPF_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_STATUS_TXLPF_BW]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_STATUS_TXLPF_RC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_GMBB_IDAC0]		= { .ghz5 = 0x0070, .ghz2 = 0x0070, NOUPLOAD, },
+	[B2056_TX_GMBB_IDAC1]		= { .ghz5 = 0x0070, .ghz2 = 0x0070, NOUPLOAD, },
+	[B2056_TX_GMBB_IDAC2]		= { .ghz5 = 0x0071, .ghz2 = 0x0071, UPLOAD, },
+	[B2056_TX_GMBB_IDAC3]		= { .ghz5 = 0x0071, .ghz2 = 0x0071, UPLOAD, },
+	[B2056_TX_GMBB_IDAC4]		= { .ghz5 = 0x0072, .ghz2 = 0x0072, UPLOAD, },
+	[B2056_TX_GMBB_IDAC5]		= { .ghz5 = 0x0073, .ghz2 = 0x0073, UPLOAD, },
+	[B2056_TX_GMBB_IDAC6]		= { .ghz5 = 0x0074, .ghz2 = 0x0074, UPLOAD, },
+	[B2056_TX_GMBB_IDAC7]		= { .ghz5 = 0x0075, .ghz2 = 0x0075, UPLOAD, },
+};
+
+static const struct b2056_inittab_entry b2056_inittab_rev5_rx[] = {
+	[B2056_RX_RESERVED_ADDR2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR4]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR5]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR6]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR7]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_COM_CTRL]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_COM_PU]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_COM_OVR]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_COM_RESET]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_COM_RCAL]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_COM_RC_RXLPF]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_COM_RC_TXLPF]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_COM_RC_RXHPF]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR16]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR17]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR18]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR19]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR20]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR21]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR22]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR23]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR24]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR25]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR26]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR27]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR28]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR29]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR30]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR31]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXIQCAL_RXMUX]	= { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, },
+	[B2056_RX_RSSI_PU]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RSSI_SEL]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RSSI_GAIN]		= { .ghz5 = 0x0090, .ghz2 = 0x0090, NOUPLOAD, },
+	[B2056_RX_RSSI_NB_IDAC]		= { .ghz5 = 0x0055, .ghz2 = 0x0055, NOUPLOAD, },
+	[B2056_RX_RSSI_WB2I_IDAC_1]	= { .ghz5 = 0x0015, .ghz2 = 0x0015, NOUPLOAD, },
+	[B2056_RX_RSSI_WB2I_IDAC_2]	= { .ghz5 = 0x0005, .ghz2 = 0x0005, NOUPLOAD, },
+	[B2056_RX_RSSI_WB2Q_IDAC_1]	= { .ghz5 = 0x0015, .ghz2 = 0x0015, NOUPLOAD, },
+	[B2056_RX_RSSI_WB2Q_IDAC_2]	= { .ghz5 = 0x0005, .ghz2 = 0x0005, NOUPLOAD, },
+	[B2056_RX_RSSI_POLE]		= { .ghz5 = 0x0020, .ghz2 = 0x0020, NOUPLOAD, },
+	[B2056_RX_RSSI_WB1_IDAC]	= { .ghz5 = 0x0011, .ghz2 = 0x0011, NOUPLOAD, },
+	[B2056_RX_RSSI_MISC]		= { .ghz5 = 0x0090, .ghz2 = 0x0090, NOUPLOAD, },
+	[B2056_RX_LNAA_MASTER]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_LNAA_TUNE]		= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+	[B2056_RX_LNAA_GAIN]		= { .ghz5 = 0x0032, .ghz2 = 0x0032, NOUPLOAD, },
+	[B2056_RX_LNA_A_SLOPE]		= { .ghz5 = 0x0077, .ghz2 = 0x0077, NOUPLOAD, },
+	[B2056_RX_BIASPOLE_LNAA1_IDAC]	= { .ghz5 = 0x0017, .ghz2 = 0x0017, UPLOAD, },
+	[B2056_RX_LNAA2_IDAC]		= { .ghz5 = 0x00ff, .ghz2 = 0x00ff, UPLOAD, },
+	[B2056_RX_LNA1A_MISC]		= { .ghz5 = 0x0020, .ghz2 = 0x0020, NOUPLOAD, },
+	[B2056_RX_LNAG_MASTER]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_LNAG_TUNE]		= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+	[B2056_RX_LNAG_GAIN]		= { .ghz5 = 0x0032, .ghz2 = 0x0032, NOUPLOAD, },
+	[B2056_RX_LNA_G_SLOPE]		= { .ghz5 = 0x0077, .ghz2 = 0x0077, NOUPLOAD, },
+	[B2056_RX_BIASPOLE_LNAG1_IDAC]	= { .ghz5 = 0x0017, .ghz2 = 0x0017, UPLOAD, },
+	[B2056_RX_LNAG2_IDAC]		= { .ghz5 = 0x00f0, .ghz2 = 0x00f0, UPLOAD, },
+	[B2056_RX_LNA1G_MISC]		= { .ghz5 = 0x0020, .ghz2 = 0x0020, NOUPLOAD, },
+	[B2056_RX_MIXA_MASTER]		= { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+	[B2056_RX_MIXA_VCM]		= { .ghz5 = 0x0055, .ghz2 = 0x0055, UPLOAD, },
+	[B2056_RX_MIXA_CTRLPTAT]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_MIXA_LOB_BIAS]	= { .ghz5 = 0x0088, .ghz2 = 0x0088, UPLOAD, },
+	[B2056_RX_MIXA_CORE_IDAC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_MIXA_CMFB_IDAC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, UPLOAD, },
+	[B2056_RX_MIXA_BIAS_AUX]	= { .ghz5 = 0x0007, .ghz2 = 0x0007, UPLOAD, },
+	[B2056_RX_MIXA_BIAS_MAIN]	= { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
+	[B2056_RX_MIXA_BIAS_MISC]	= { .ghz5 = 0x0004, .ghz2 = 0x0004, NOUPLOAD, },
+	[B2056_RX_MIXA_MAST_BIAS]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_MIXG_MASTER]		= { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+	[B2056_RX_MIXG_VCM]		= { .ghz5 = 0x0055, .ghz2 = 0x0055, UPLOAD, },
+	[B2056_RX_MIXG_CTRLPTAT]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_MIXG_LOB_BIAS]	= { .ghz5 = 0x0011, .ghz2 = 0x0011, NOUPLOAD, },
+	[B2056_RX_MIXG_CORE_IDAC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_MIXG_CMFB_IDAC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, UPLOAD, },
+	[B2056_RX_MIXG_BIAS_AUX]	= { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+	[B2056_RX_MIXG_BIAS_MAIN]	= { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
+	[B2056_RX_MIXG_BIAS_MISC]	= { .ghz5 = 0x0004, .ghz2 = 0x0004, NOUPLOAD, },
+	[B2056_RX_MIXG_MAST_BIAS]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_TIA_MASTER]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_TIA_IOPAMP]		= { .ghz5 = 0x0026, .ghz2 = 0x0026, UPLOAD, },
+	[B2056_RX_TIA_QOPAMP]		= { .ghz5 = 0x0026, .ghz2 = 0x0026, UPLOAD, },
+	[B2056_RX_TIA_IMISC]		= { .ghz5 = 0x000f, .ghz2 = 0x000f, UPLOAD, },
+	[B2056_RX_TIA_QMISC]		= { .ghz5 = 0x000f, .ghz2 = 0x000f, UPLOAD, },
+	[B2056_RX_TIA_GAIN]		= { .ghz5 = 0x0044, .ghz2 = 0x0044, NOUPLOAD, },
+	[B2056_RX_TIA_SPARE1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_TIA_SPARE2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_BB_LPF_MASTER]	= { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+	[B2056_RX_AACI_MASTER]		= { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+	[B2056_RX_RXLPF_IDAC]		= { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+	[B2056_RX_RXLPF_OPAMPBIAS_LOWQ]	= { .ghz5 = 0x0022, .ghz2 = 0x0022, NOUPLOAD, },
+	[B2056_RX_RXLPF_OPAMPBIAS_HIGHQ]= { .ghz5 = 0x0022, .ghz2 = 0x0022, NOUPLOAD, },
+	[B2056_RX_RXLPF_BIAS_DCCANCEL]	= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_RX_RXLPF_OUTVCM]		= { .ghz5 = 0x0004, .ghz2 = 0x0004, UPLOAD, },
+	[B2056_RX_RXLPF_INVCM_BODY]	= { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+	[B2056_RX_RXLPF_CC_OP]		= { .ghz5 = 0x0055, .ghz2 = 0x0055, NOUPLOAD, },
+	[B2056_RX_RXLPF_GAIN]		= { .ghz5 = 0x0023, .ghz2 = 0x0023, NOUPLOAD, },
+	[B2056_RX_RXLPF_Q_BW]		= { .ghz5 = 0x0041, .ghz2 = 0x0041, NOUPLOAD, },
+	[B2056_RX_RXLPF_HP_CORNER_BW]	= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_RX_RXLPF_RCCAL_HPC]	= { .ghz5 = 0x000a, .ghz2 = 0x000a, NOUPLOAD, },
+	[B2056_RX_RXHPF_OFF0]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXHPF_OFF1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXHPF_OFF2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXHPF_OFF3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXHPF_OFF4]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXHPF_OFF5]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXHPF_OFF6]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXHPF_OFF7]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXLPF_RCCAL_LPC]	= { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, },
+	[B2056_RX_RXLPF_OFF_0]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXLPF_OFF_1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXLPF_OFF_2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXLPF_OFF_3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXLPF_OFF_4]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_UNUSED]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_VGA_MASTER]		= { .ghz5 = 0x0022, .ghz2 = 0x0022, NOUPLOAD, },
+	[B2056_RX_VGA_BIAS]		= { .ghz5 = 0x0022, .ghz2 = 0x0022, NOUPLOAD, },
+	[B2056_RX_VGA_BIAS_DCCANCEL]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, UPLOAD, },
+	[B2056_RX_VGA_GAIN]		= { .ghz5 = 0x000a, .ghz2 = 0x000a, NOUPLOAD, },
+	[B2056_RX_VGA_HP_CORNER_BW]	= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_RX_VGABUF_BIAS]		= { .ghz5 = 0x0022, .ghz2 = 0x0022, NOUPLOAD, },
+	[B2056_RX_VGABUF_GAIN_BW]	= { .ghz5 = 0x0030, .ghz2 = 0x0030, NOUPLOAD, },
+	[B2056_RX_TXFBMIX_A]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_TXFBMIX_G]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE4]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE5]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE6]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE7]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE8]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE9]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE10]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE11]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE12]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE13]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE14]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE15]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE16]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_LNAA_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_LNAG_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_MIXTIA_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_RXLPF_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_VGA_BUF_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_RXLPF_Q]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_RXLPF_BUF_BW]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_RXLPF_VGA_HPC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_RXLPF_RC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_HPC_RC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+};
+
+static const struct b2056_inittab_entry b2056_inittab_rev6_syn[] = {
+	[B2056_SYN_RESERVED_ADDR2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR4]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR5]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR6]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR7]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_COM_CTRL]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_COM_PU]		= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_SYN_COM_OVR]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_COM_RESET]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_COM_RCAL]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_COM_RC_RXLPF]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_COM_RC_TXLPF]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_COM_RC_RXHPF]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR16]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR17]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR18]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR19]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR20]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR21]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR22]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR23]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR24]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR25]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR26]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR27]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR28]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR29]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR30]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR31]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_GPIO_MASTER1]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_GPIO_MASTER2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_TOPBIAS_MASTER]	= { .ghz5 = 0x0060, .ghz2 = 0x0060, NOUPLOAD, },
+	[B2056_SYN_TOPBIAS_RCAL]	= { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
+	[B2056_SYN_AFEREG]		= { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, },
+	[B2056_SYN_TEMPPROCSENSE]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_TEMPPROCSENSEIDAC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_TEMPPROCSENSERCAL]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LPO]			= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_SYN_VDDCAL_MASTER]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_VDDCAL_IDAC]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_VDDCAL_STATUS]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCAL_MASTER]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCAL_CODE_OUT]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL0]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL1]		= { .ghz5 = 0x001f, .ghz2 = 0x001f, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL2]		= { .ghz5 = 0x0015, .ghz2 = 0x0015, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL3]		= { .ghz5 = 0x000f, .ghz2 = 0x000f, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL4]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL5]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL6]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL7]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL8]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL9]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL10]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL11]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_ZCAL_SPARE1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_ZCAL_SPARE2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_MAST1]		= { .ghz5 = 0x0013, .ghz2 = 0x0013, NOUPLOAD, },
+	[B2056_SYN_PLL_MAST2]		= { .ghz5 = 0x000f, .ghz2 = 0x000f, NOUPLOAD, },
+	[B2056_SYN_PLL_MAST3]		= { .ghz5 = 0x0018, .ghz2 = 0x0018, NOUPLOAD, },
+	[B2056_SYN_PLL_BIAS_RESET]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_XTAL0]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_XTAL1]		= { .ghz5 = 0x0020, .ghz2 = 0x0020, NOUPLOAD, },
+	[B2056_SYN_PLL_XTAL3]		= { .ghz5 = 0x0020, .ghz2 = 0x0020, NOUPLOAD, },
+	[B2056_SYN_PLL_XTAL4]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_XTAL5]		= { .ghz5 = 0x0077, .ghz2 = 0x0077, NOUPLOAD, },
+	[B2056_SYN_PLL_XTAL6]		= { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+	[B2056_SYN_PLL_REFDIV]		= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_SYN_PLL_PFD]		= { .ghz5 = 0x0004, .ghz2 = 0x0004, NOUPLOAD, },
+	[B2056_SYN_PLL_CP1]		= { .ghz5 = 0x000f, .ghz2 = 0x000f, NOUPLOAD, },
+	[B2056_SYN_PLL_CP2]		= { .ghz5 = 0x0030, .ghz2 = 0x0030, NOUPLOAD, },
+	[B2056_SYN_PLL_CP3]		= { .ghz5 = 0x0032, .ghz2 = 0x0032, NOUPLOAD, },
+	[B2056_SYN_PLL_LOOPFILTER1]	= { .ghz5 = 0x000d, .ghz2 = 0x000d, NOUPLOAD, },
+	[B2056_SYN_PLL_LOOPFILTER2]	= { .ghz5 = 0x000d, .ghz2 = 0x000d, NOUPLOAD, },
+	[B2056_SYN_PLL_LOOPFILTER3]	= { .ghz5 = 0x0004, .ghz2 = 0x0004, NOUPLOAD, },
+	[B2056_SYN_PLL_LOOPFILTER4]	= { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
+	[B2056_SYN_PLL_LOOPFILTER5]	= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_SYN_PLL_MMD1]		= { .ghz5 = 0x001c, .ghz2 = 0x001c, NOUPLOAD, },
+	[B2056_SYN_PLL_MMD2]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_SYN_PLL_VCO1]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_SYN_PLL_VCO2]		= { .ghz5 = 0x00f7, .ghz2 = 0x00f7, UPLOAD, },
+	[B2056_SYN_PLL_MONITOR1]	= { .ghz5 = 0x00b4, .ghz2 = 0x00b4, NOUPLOAD, },
+	[B2056_SYN_PLL_MONITOR2]	= { .ghz5 = 0x00d2, .ghz2 = 0x00d2, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL4]		= { .ghz5 = 0x0004, .ghz2 = 0x0004, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL5]		= { .ghz5 = 0x0096, .ghz2 = 0x0096, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL6]		= { .ghz5 = 0x003e, .ghz2 = 0x003e, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL7]		= { .ghz5 = 0x003e, .ghz2 = 0x003e, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL8]		= { .ghz5 = 0x0013, .ghz2 = 0x0013, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL9]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL10]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL11]	= { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL12]	= { .ghz5 = 0x0007, .ghz2 = 0x0007, UPLOAD, },
+	[B2056_SYN_PLL_VCOCAL13]	= { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+	[B2056_SYN_PLL_VREG]		= { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, },
+	[B2056_SYN_PLL_STATUS1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_STATUS2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_STATUS3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PU0]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PU1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PU2]		= { .ghz5 = 0x0040, .ghz2 = 0x0040, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PU3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PU5]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PU6]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PU7]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PU8]		= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_SYN_LOGEN_BIAS_RESET]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_RCCR1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_VCOBUF1]	= { .ghz5 = 0x0060, .ghz2 = 0x0060, NOUPLOAD, },
+	[B2056_SYN_LOGEN_MIXER1]	= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_MIXER2]	= { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, },
+	[B2056_SYN_LOGEN_BUF1]		= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGENBUF2]		= { .ghz5 = 0x008f, .ghz2 = 0x008f, UPLOAD, },
+	[B2056_SYN_LOGEN_BUF3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_BUF4]		= { .ghz5 = 0x00cc, .ghz2 = 0x00cc, NOUPLOAD, },
+	[B2056_SYN_LOGEN_DIV1]		= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_SYN_LOGEN_DIV2]		= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_DIV3]		= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACL1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACL2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACL3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACL4]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACL5]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACL6]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACLOUT]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACLCAL1]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACLCAL2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACLCAL3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_CALEN]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PEAKDET1]	= { .ghz5 = 0x00ff, .ghz2 = 0x00ff, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CORE_ACL_OVR]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_RX_DIFF_ACL_OVR]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_TX_DIFF_ACL_OVR]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_RX_CMOS_ACL_OVR]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_TX_CMOS_ACL_OVR]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_VCOBUF2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_MIXER3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_BUF5]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_BUF6]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFRX1]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFRX2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFRX3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFRX4]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFTX1]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFTX2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFTX3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFTX4]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSRX1]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSRX2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSRX3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSRX4]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSTX1]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSTX2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSTX3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSTX4]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_VCOBUF2_OVRVAL]= { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
+	[B2056_SYN_LOGEN_MIXER3_OVRVAL]	= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_BUF5_OVRVAL]	= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_BUF6_OVRVAL]	= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFRX1_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFRX2_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFRX3_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFRX4_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFTX1_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFTX2_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFTX3_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFTX4_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSRX1_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSRX2_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSRX3_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSRX4_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSTX1_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSTX2_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSTX3_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSTX4_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACL_WAITCNT]	= { .ghz5 = 0x000a, .ghz2 = 0x000a, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CORE_CALVALID]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_RX_CMOS_CALVALID]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_TX_CMOS_VALID]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+};
+
+static const struct b2056_inittab_entry b2056_inittab_rev6_tx[] = {
+	[B2056_TX_RESERVED_ADDR2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR4]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR5]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR6]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR7]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_COM_CTRL]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_COM_PU]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_COM_OVR]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_COM_RESET]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_COM_RCAL]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_COM_RC_RXLPF]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_COM_RC_TXLPF]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_COM_RC_RXHPF]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR16]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR17]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR18]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR19]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR20]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR21]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR22]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR23]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR24]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR25]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR26]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR27]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR28]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR29]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR30]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR31]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_IQCAL_GAIN_BW]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_LOFT_FINE_I]		= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+	[B2056_TX_LOFT_FINE_Q]		= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+	[B2056_TX_LOFT_COARSE_I]	= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+	[B2056_TX_LOFT_COARSE_Q]	= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+	[B2056_TX_TX_COM_MASTER1]	= { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, },
+	[B2056_TX_TX_COM_MASTER2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RXIQCAL_TXMUX]	= { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, },
+	[B2056_TX_TX_SSI_MASTER]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_IQCAL_VCM_HG]		= { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, },
+	[B2056_TX_IQCAL_IDAC]		= { .ghz5 = 0x0037, .ghz2 = 0x0037, NOUPLOAD, },
+	[B2056_TX_TSSI_VCM]		= { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, },
+	[B2056_TX_TX_AMP_DET]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TX_SSI_MUX]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TSSIA]		= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_TX_TSSIG]		= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_TX_TSSI_MISC1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TSSI_MISC2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TSSI_MISC3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_PA_SPARE1]		= { .ghz5 = 0x0011, .ghz2 = 0x0011, NOUPLOAD, },
+	[B2056_TX_PA_SPARE2]		= { .ghz5 = 0x00ee, .ghz2 = 0x00ee, UPLOAD, },
+	[B2056_TX_INTPAA_MASTER]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAA_GAIN]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAA_BOOST_TUNE]	= { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, },
+	[B2056_TX_INTPAA_IAUX_STAT]	= { .ghz5 = 0x0050, .ghz2 = 0x0050, UPLOAD, },
+	[B2056_TX_INTPAA_IAUX_DYN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAA_IMAIN_STAT]	= { .ghz5 = 0x0050, .ghz2 = 0x0050, UPLOAD, },
+	[B2056_TX_INTPAA_IMAIN_DYN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAA_CASCBIAS]	= { .ghz5 = 0x006e, .ghz2 = 0x006e, NOUPLOAD, },
+	[B2056_TX_INTPAA_PASLOPE]	= { .ghz5 = 0x00f0, .ghz2 = 0x00f0, UPLOAD, },
+	[B2056_TX_INTPAA_PA_MISC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAG_MASTER]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAG_GAIN]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAG_BOOST_TUNE]	= { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, },
+	[B2056_TX_INTPAG_IAUX_STAT]	= { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, },
+	[B2056_TX_INTPAG_IAUX_DYN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAG_IMAIN_STAT]	= { .ghz5 = 0x001e, .ghz2 = 0x001e, NOUPLOAD, },
+	[B2056_TX_INTPAG_IMAIN_DYN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAG_CASCBIAS]	= { .ghz5 = 0x006e, .ghz2 = 0x006e, NOUPLOAD, },
+	[B2056_TX_INTPAG_PASLOPE]	= { .ghz5 = 0x00f0, .ghz2 = 0x00f0, UPLOAD, },
+	[B2056_TX_INTPAG_PA_MISC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_PADA_MASTER]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_TX_PADA_IDAC]		= { .ghz5 = 0x00ff, .ghz2 = 0x00ff, UPLOAD, },
+	[B2056_TX_PADA_CASCBIAS]	= { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, },
+	[B2056_TX_PADA_GAIN]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_PADA_BOOST_TUNE]	= { .ghz5 = 0x0038, .ghz2 = 0x0038, NOUPLOAD, },
+	[B2056_TX_PADA_SLOPE]		= { .ghz5 = 0x0070, .ghz2 = 0x0070, UPLOAD, },
+	[B2056_TX_PADG_MASTER]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_TX_PADG_IDAC]		= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+	[B2056_TX_PADG_CASCBIAS]	= { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, },
+	[B2056_TX_PADG_GAIN]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_PADG_BOOST_TUNE]	= { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+	[B2056_TX_PADG_SLOPE]		= { .ghz5 = 0x0070, .ghz2 = 0x0070, UPLOAD, },
+	[B2056_TX_PGAA_MASTER]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_TX_PGAA_IDAC]		= { .ghz5 = 0x00ff, .ghz2 = 0x00ff, UPLOAD, },
+	[B2056_TX_PGAA_GAIN]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_PGAA_BOOST_TUNE]	= { .ghz5 = 0x0083, .ghz2 = 0x0083, NOUPLOAD, },
+	[B2056_TX_PGAA_SLOPE]		= { .ghz5 = 0x0077, .ghz2 = 0x0077, UPLOAD, },
+	[B2056_TX_PGAA_MISC]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_PGAG_MASTER]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_TX_PGAG_IDAC]		= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+	[B2056_TX_PGAG_GAIN]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_PGAG_BOOST_TUNE]	= { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+	[B2056_TX_PGAG_SLOPE]		= { .ghz5 = 0x0077, .ghz2 = 0x0077, UPLOAD, },
+	[B2056_TX_PGAG_MISC]		= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_TX_MIXA_MASTER]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_MIXA_BOOST_TUNE]	= { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+	[B2056_TX_MIXG]			= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_MIXG_BOOST_TUNE]	= { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+	[B2056_TX_BB_GM_MASTER]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_GMBB_GM]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_GMBB_IDAC]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, UPLOAD, },
+	[B2056_TX_TXLPF_MASTER]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_RCCAL]		= { .ghz5 = 0x000a, .ghz2 = 0x000a, NOUPLOAD, },
+	[B2056_TX_TXLPF_RCCAL_OFF0]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_RCCAL_OFF1]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_RCCAL_OFF2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_RCCAL_OFF3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_RCCAL_OFF4]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_RCCAL_OFF5]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_RCCAL_OFF6]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_BW]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_TX_TXLPF_GAIN]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_IDAC]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_IDAC_0]		= { .ghz5 = 0x000e, .ghz2 = 0x000e, NOUPLOAD, },
+	[B2056_TX_TXLPF_IDAC_1]		= { .ghz5 = 0x000e, .ghz2 = 0x000e, NOUPLOAD, },
+	[B2056_TX_TXLPF_IDAC_2]		= { .ghz5 = 0x000e, .ghz2 = 0x000e, NOUPLOAD, },
+	[B2056_TX_TXLPF_IDAC_3]		= { .ghz5 = 0x0013, .ghz2 = 0x0013, NOUPLOAD, },
+	[B2056_TX_TXLPF_IDAC_4]		= { .ghz5 = 0x0013, .ghz2 = 0x0013, NOUPLOAD, },
+	[B2056_TX_TXLPF_IDAC_5]		= { .ghz5 = 0x001b, .ghz2 = 0x001b, NOUPLOAD, },
+	[B2056_TX_TXLPF_IDAC_6]		= { .ghz5 = 0x001b, .ghz2 = 0x001b, NOUPLOAD, },
+	[B2056_TX_TXLPF_OPAMP_IDAC]	= { .ghz5 = 0x0055, .ghz2 = 0x0055, NOUPLOAD, },
+	[B2056_TX_TXLPF_MISC]		= { .ghz5 = 0x005b, .ghz2 = 0x005b, NOUPLOAD, },
+	[B2056_TX_TXSPARE1]		= { .ghz5 = 0x0030, .ghz2 = 0x0030, UPLOAD, },
+	[B2056_TX_TXSPARE2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE4]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE5]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE6]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE7]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE8]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE9]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE10]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE11]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE12]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE13]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE14]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE15]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE16]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_STATUS_INTPA_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_STATUS_PAD_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_STATUS_PGA_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_STATUS_GM_TXLPF_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_STATUS_TXLPF_BW]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_STATUS_TXLPF_RC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_GMBB_IDAC0]		= { .ghz5 = 0x0070, .ghz2 = 0x0070, NOUPLOAD, },
+	[B2056_TX_GMBB_IDAC1]		= { .ghz5 = 0x0070, .ghz2 = 0x0070, NOUPLOAD, },
+	[B2056_TX_GMBB_IDAC2]		= { .ghz5 = 0x0070, .ghz2 = 0x0070, NOUPLOAD, },
+	[B2056_TX_GMBB_IDAC3]		= { .ghz5 = 0x0070, .ghz2 = 0x0070, NOUPLOAD, },
+	[B2056_TX_GMBB_IDAC4]		= { .ghz5 = 0x0070, .ghz2 = 0x0070, NOUPLOAD, },
+	[B2056_TX_GMBB_IDAC5]		= { .ghz5 = 0x0070, .ghz2 = 0x0070, NOUPLOAD, },
+	[B2056_TX_GMBB_IDAC6]		= { .ghz5 = 0x0070, .ghz2 = 0x0070, NOUPLOAD, },
+	[B2056_TX_GMBB_IDAC7]		= { .ghz5 = 0x0070, .ghz2 = 0x0070, NOUPLOAD, },
+};
+
+static const struct b2056_inittab_entry b2056_inittab_rev6_rx[] = {
+	[B2056_RX_RESERVED_ADDR2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR4]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR5]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR6]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR7]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_COM_CTRL]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_COM_PU]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_COM_OVR]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_COM_RESET]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_COM_RCAL]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_COM_RC_RXLPF]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_COM_RC_TXLPF]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_COM_RC_RXHPF]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR16]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR17]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR18]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR19]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR20]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR21]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR22]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR23]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR24]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR25]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR26]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR27]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR28]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR29]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR30]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR31]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXIQCAL_RXMUX]	= { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, },
+	[B2056_RX_RSSI_PU]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RSSI_SEL]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RSSI_GAIN]		= { .ghz5 = 0x0090, .ghz2 = 0x0090, NOUPLOAD, },
+	[B2056_RX_RSSI_NB_IDAC]		= { .ghz5 = 0x0055, .ghz2 = 0x0055, NOUPLOAD, },
+	[B2056_RX_RSSI_WB2I_IDAC_1]	= { .ghz5 = 0x0015, .ghz2 = 0x0015, NOUPLOAD, },
+	[B2056_RX_RSSI_WB2I_IDAC_2]	= { .ghz5 = 0x0005, .ghz2 = 0x0005, NOUPLOAD, },
+	[B2056_RX_RSSI_WB2Q_IDAC_1]	= { .ghz5 = 0x0015, .ghz2 = 0x0015, NOUPLOAD, },
+	[B2056_RX_RSSI_WB2Q_IDAC_2]	= { .ghz5 = 0x0005, .ghz2 = 0x0005, NOUPLOAD, },
+	[B2056_RX_RSSI_POLE]		= { .ghz5 = 0x0020, .ghz2 = 0x0020, NOUPLOAD, },
+	[B2056_RX_RSSI_WB1_IDAC]	= { .ghz5 = 0x0011, .ghz2 = 0x0011, NOUPLOAD, },
+	[B2056_RX_RSSI_MISC]		= { .ghz5 = 0x0090, .ghz2 = 0x0090, NOUPLOAD, },
+	[B2056_RX_LNAA_MASTER]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_LNAA_TUNE]		= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+	[B2056_RX_LNAA_GAIN]		= { .ghz5 = 0x0032, .ghz2 = 0x0032, NOUPLOAD, },
+	[B2056_RX_LNA_A_SLOPE]		= { .ghz5 = 0x0077, .ghz2 = 0x0077, NOUPLOAD, },
+	[B2056_RX_BIASPOLE_LNAA1_IDAC]	= { .ghz5 = 0x0017, .ghz2 = 0x0017, UPLOAD, },
+	[B2056_RX_LNAA2_IDAC]		= { .ghz5 = 0x00ff, .ghz2 = 0x00ff, UPLOAD, },
+	[B2056_RX_LNA1A_MISC]		= { .ghz5 = 0x0020, .ghz2 = 0x0020, NOUPLOAD, },
+	[B2056_RX_LNAG_MASTER]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_LNAG_TUNE]		= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+	[B2056_RX_LNAG_GAIN]		= { .ghz5 = 0x0032, .ghz2 = 0x0032, NOUPLOAD, },
+	[B2056_RX_LNA_G_SLOPE]		= { .ghz5 = 0x0077, .ghz2 = 0x0077, NOUPLOAD, },
+	[B2056_RX_BIASPOLE_LNAG1_IDAC]	= { .ghz5 = 0x0017, .ghz2 = 0x0017, UPLOAD, },
+	[B2056_RX_LNAG2_IDAC]		= { .ghz5 = 0x00f0, .ghz2 = 0x00f0, UPLOAD, },
+	[B2056_RX_LNA1G_MISC]		= { .ghz5 = 0x0020, .ghz2 = 0x0020, NOUPLOAD, },
+	[B2056_RX_MIXA_MASTER]		= { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+	[B2056_RX_MIXA_VCM]		= { .ghz5 = 0x0055, .ghz2 = 0x0055, UPLOAD, },
+	[B2056_RX_MIXA_CTRLPTAT]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_MIXA_LOB_BIAS]	= { .ghz5 = 0x0088, .ghz2 = 0x0088, UPLOAD, },
+	[B2056_RX_MIXA_CORE_IDAC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_MIXA_CMFB_IDAC]	= { .ghz5 = 0x0044, .ghz2 = 0x0044, NOUPLOAD, },
+	[B2056_RX_MIXA_BIAS_AUX]	= { .ghz5 = 0x0007, .ghz2 = 0x0007, UPLOAD, },
+	[B2056_RX_MIXA_BIAS_MAIN]	= { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
+	[B2056_RX_MIXA_BIAS_MISC]	= { .ghz5 = 0x0004, .ghz2 = 0x0004, NOUPLOAD, },
+	[B2056_RX_MIXA_MAST_BIAS]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_MIXG_MASTER]		= { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+	[B2056_RX_MIXG_VCM]		= { .ghz5 = 0x0055, .ghz2 = 0x0055, UPLOAD, },
+	[B2056_RX_MIXG_CTRLPTAT]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_MIXG_LOB_BIAS]	= { .ghz5 = 0x0011, .ghz2 = 0x0011, NOUPLOAD, },
+	[B2056_RX_MIXG_CORE_IDAC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_MIXG_CMFB_IDAC]	= { .ghz5 = 0x0044, .ghz2 = 0x0044, NOUPLOAD, },
+	[B2056_RX_MIXG_BIAS_AUX]	= { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+	[B2056_RX_MIXG_BIAS_MAIN]	= { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
+	[B2056_RX_MIXG_BIAS_MISC]	= { .ghz5 = 0x0004, .ghz2 = 0x0004, NOUPLOAD, },
+	[B2056_RX_MIXG_MAST_BIAS]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_TIA_MASTER]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_TIA_IOPAMP]		= { .ghz5 = 0x0026, .ghz2 = 0x0026, UPLOAD, },
+	[B2056_RX_TIA_QOPAMP]		= { .ghz5 = 0x0026, .ghz2 = 0x0026, UPLOAD, },
+	[B2056_RX_TIA_IMISC]		= { .ghz5 = 0x000f, .ghz2 = 0x000f, UPLOAD, },
+	[B2056_RX_TIA_QMISC]		= { .ghz5 = 0x000f, .ghz2 = 0x000f, UPLOAD, },
+	[B2056_RX_TIA_GAIN]		= { .ghz5 = 0x0044, .ghz2 = 0x0044, NOUPLOAD, },
+	[B2056_RX_TIA_SPARE1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_TIA_SPARE2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_BB_LPF_MASTER]	= { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+	[B2056_RX_AACI_MASTER]		= { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+	[B2056_RX_RXLPF_IDAC]		= { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+	[B2056_RX_RXLPF_OPAMPBIAS_LOWQ]	= { .ghz5 = 0x0022, .ghz2 = 0x0022, NOUPLOAD, },
+	[B2056_RX_RXLPF_OPAMPBIAS_HIGHQ]= { .ghz5 = 0x0022, .ghz2 = 0x0022, NOUPLOAD, },
+	[B2056_RX_RXLPF_BIAS_DCCANCEL]	= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_RX_RXLPF_OUTVCM]		= { .ghz5 = 0x0004, .ghz2 = 0x0004, UPLOAD, },
+	[B2056_RX_RXLPF_INVCM_BODY]	= { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+	[B2056_RX_RXLPF_CC_OP]		= { .ghz5 = 0x0055, .ghz2 = 0x0055, NOUPLOAD, },
+	[B2056_RX_RXLPF_GAIN]		= { .ghz5 = 0x0023, .ghz2 = 0x0023, NOUPLOAD, },
+	[B2056_RX_RXLPF_Q_BW]		= { .ghz5 = 0x0041, .ghz2 = 0x0041, NOUPLOAD, },
+	[B2056_RX_RXLPF_HP_CORNER_BW]	= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_RX_RXLPF_RCCAL_HPC]	= { .ghz5 = 0x000a, .ghz2 = 0x000a, NOUPLOAD, },
+	[B2056_RX_RXHPF_OFF0]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXHPF_OFF1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXHPF_OFF2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXHPF_OFF3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXHPF_OFF4]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXHPF_OFF5]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXHPF_OFF6]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXHPF_OFF7]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXLPF_RCCAL_LPC]	= { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, },
+	[B2056_RX_RXLPF_OFF_0]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXLPF_OFF_1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXLPF_OFF_2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXLPF_OFF_3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXLPF_OFF_4]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_UNUSED]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_VGA_MASTER]		= { .ghz5 = 0x0022, .ghz2 = 0x0022, NOUPLOAD, },
+	[B2056_RX_VGA_BIAS]		= { .ghz5 = 0x0022, .ghz2 = 0x0022, NOUPLOAD, },
+	[B2056_RX_VGA_BIAS_DCCANCEL]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, UPLOAD, },
+	[B2056_RX_VGA_GAIN]		= { .ghz5 = 0x000a, .ghz2 = 0x000a, NOUPLOAD, },
+	[B2056_RX_VGA_HP_CORNER_BW]	= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_RX_VGABUF_BIAS]		= { .ghz5 = 0x0022, .ghz2 = 0x0022, NOUPLOAD, },
+	[B2056_RX_VGABUF_GAIN_BW]	= { .ghz5 = 0x0030, .ghz2 = 0x0030, NOUPLOAD, },
+	[B2056_RX_TXFBMIX_A]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_TXFBMIX_G]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE3]		= { .ghz5 = 0x0005, .ghz2 = 0x0005, UPLOAD, },
+	[B2056_RX_RXSPARE4]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE5]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE6]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE7]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE8]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE9]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE10]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE11]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE12]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE13]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE14]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE15]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE16]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_LNAA_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_LNAG_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_MIXTIA_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_RXLPF_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_VGA_BUF_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_RXLPF_Q]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_RXLPF_BUF_BW]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_RXLPF_VGA_HPC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_RXLPF_RC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_HPC_RC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+};
+
+static const struct b2056_inittab_entry b2056_inittab_rev7_syn[] = {
+	[B2056_SYN_RESERVED_ADDR2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR4]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR5]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR6]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR7]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_COM_CTRL]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_COM_PU]		= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_SYN_COM_OVR]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_COM_RESET]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_COM_RCAL]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_COM_RC_RXLPF]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_COM_RC_TXLPF]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_COM_RC_RXHPF]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR16]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR17]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR18]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR19]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR20]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR21]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR22]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR23]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR24]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR25]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR26]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR27]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR28]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR29]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR30]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR31]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_GPIO_MASTER1]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_GPIO_MASTER2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_TOPBIAS_MASTER]	= { .ghz5 = 0x0060, .ghz2 = 0x0060, NOUPLOAD, },
+	[B2056_SYN_TOPBIAS_RCAL]	= { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
+	[B2056_SYN_AFEREG]		= { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, },
+	[B2056_SYN_TEMPPROCSENSE]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_TEMPPROCSENSEIDAC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_TEMPPROCSENSERCAL]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LPO]			= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_SYN_VDDCAL_MASTER]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_VDDCAL_IDAC]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_VDDCAL_STATUS]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCAL_MASTER]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCAL_CODE_OUT]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL0]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL1]		= { .ghz5 = 0x001f, .ghz2 = 0x001f, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL2]		= { .ghz5 = 0x0015, .ghz2 = 0x0015, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL3]		= { .ghz5 = 0x000f, .ghz2 = 0x000f, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL4]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL5]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL6]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL7]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL8]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL9]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL10]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL11]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_ZCAL_SPARE1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_ZCAL_SPARE2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_MAST1]		= { .ghz5 = 0x0013, .ghz2 = 0x0013, NOUPLOAD, },
+	[B2056_SYN_PLL_MAST2]		= { .ghz5 = 0x000f, .ghz2 = 0x000f, NOUPLOAD, },
+	[B2056_SYN_PLL_MAST3]		= { .ghz5 = 0x0018, .ghz2 = 0x0018, NOUPLOAD, },
+	[B2056_SYN_PLL_BIAS_RESET]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_XTAL0]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_XTAL1]		= { .ghz5 = 0x0020, .ghz2 = 0x0020, NOUPLOAD, },
+	[B2056_SYN_PLL_XTAL3]		= { .ghz5 = 0x0020, .ghz2 = 0x0020, NOUPLOAD, },
+	[B2056_SYN_PLL_XTAL4]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_XTAL5]		= { .ghz5 = 0x0077, .ghz2 = 0x0077, NOUPLOAD, },
+	[B2056_SYN_PLL_XTAL6]		= { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+	[B2056_SYN_PLL_REFDIV]		= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_SYN_PLL_PFD]		= { .ghz5 = 0x0004, .ghz2 = 0x0004, NOUPLOAD, },
+	[B2056_SYN_PLL_CP1]		= { .ghz5 = 0x000f, .ghz2 = 0x000f, NOUPLOAD, },
+	[B2056_SYN_PLL_CP2]		= { .ghz5 = 0x0030, .ghz2 = 0x0030, NOUPLOAD, },
+	[B2056_SYN_PLL_CP3]		= { .ghz5 = 0x0032, .ghz2 = 0x0032, NOUPLOAD, },
+	[B2056_SYN_PLL_LOOPFILTER1]	= { .ghz5 = 0x000d, .ghz2 = 0x000d, NOUPLOAD, },
+	[B2056_SYN_PLL_LOOPFILTER2]	= { .ghz5 = 0x000d, .ghz2 = 0x000d, NOUPLOAD, },
+	[B2056_SYN_PLL_LOOPFILTER3]	= { .ghz5 = 0x0004, .ghz2 = 0x0004, NOUPLOAD, },
+	[B2056_SYN_PLL_LOOPFILTER4]	= { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
+	[B2056_SYN_PLL_LOOPFILTER5]	= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_SYN_PLL_MMD1]		= { .ghz5 = 0x001c, .ghz2 = 0x001c, NOUPLOAD, },
+	[B2056_SYN_PLL_MMD2]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_SYN_PLL_VCO1]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_SYN_PLL_VCO2]		= { .ghz5 = 0x00f7, .ghz2 = 0x00f7, UPLOAD, },
+	[B2056_SYN_PLL_MONITOR1]	= { .ghz5 = 0x00b4, .ghz2 = 0x00b4, NOUPLOAD, },
+	[B2056_SYN_PLL_MONITOR2]	= { .ghz5 = 0x00d2, .ghz2 = 0x00d2, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL4]		= { .ghz5 = 0x0004, .ghz2 = 0x0004, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL5]		= { .ghz5 = 0x0096, .ghz2 = 0x0096, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL6]		= { .ghz5 = 0x003e, .ghz2 = 0x003e, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL7]		= { .ghz5 = 0x003e, .ghz2 = 0x003e, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL8]		= { .ghz5 = 0x0013, .ghz2 = 0x0013, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL9]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL10]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL11]	= { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL12]	= { .ghz5 = 0x0007, .ghz2 = 0x0007, UPLOAD, },
+	[B2056_SYN_PLL_VCOCAL13]	= { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+	[B2056_SYN_PLL_VREG]		= { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, },
+	[B2056_SYN_PLL_STATUS1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_STATUS2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_STATUS3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PU0]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PU1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PU2]		= { .ghz5 = 0x0040, .ghz2 = 0x0040, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PU3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PU5]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PU6]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PU7]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PU8]		= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_SYN_LOGEN_BIAS_RESET]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_RCCR1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_VCOBUF1]	= { .ghz5 = 0x0060, .ghz2 = 0x0060, NOUPLOAD, },
+	[B2056_SYN_LOGEN_MIXER1]	= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_MIXER2]	= { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, },
+	[B2056_SYN_LOGEN_BUF1]		= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGENBUF2]		= { .ghz5 = 0x008f, .ghz2 = 0x008f, UPLOAD, },
+	[B2056_SYN_LOGEN_BUF3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_BUF4]		= { .ghz5 = 0x00cc, .ghz2 = 0x00cc, NOUPLOAD, },
+	[B2056_SYN_LOGEN_DIV1]		= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_SYN_LOGEN_DIV2]		= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_DIV3]		= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACL1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACL2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACL3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACL4]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACL5]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACL6]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACLOUT]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACLCAL1]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACLCAL2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACLCAL3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_CALEN]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PEAKDET1]	= { .ghz5 = 0x00ff, .ghz2 = 0x00ff, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CORE_ACL_OVR]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_RX_DIFF_ACL_OVR]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_TX_DIFF_ACL_OVR]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_RX_CMOS_ACL_OVR]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_TX_CMOS_ACL_OVR]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_VCOBUF2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_MIXER3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_BUF5]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_BUF6]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFRX1]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFRX2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFRX3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFRX4]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFTX1]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFTX2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFTX3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFTX4]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSRX1]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSRX2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSRX3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSRX4]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSTX1]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSTX2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSTX3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSTX4]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_VCOBUF2_OVRVAL]= { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
+	[B2056_SYN_LOGEN_MIXER3_OVRVAL]	= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_BUF5_OVRVAL]	= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_BUF6_OVRVAL]	= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFRX1_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFRX2_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFRX3_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFRX4_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFTX1_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFTX2_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFTX3_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFTX4_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSRX1_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSRX2_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSRX3_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSRX4_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSTX1_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSTX2_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSTX3_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSTX4_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACL_WAITCNT]	= { .ghz5 = 0x000a, .ghz2 = 0x000a, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CORE_CALVALID]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_RX_CMOS_CALVALID]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_TX_CMOS_VALID]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+};
+
+static const struct b2056_inittab_entry b2056_inittab_rev7_tx[] = {
+	[B2056_TX_RESERVED_ADDR2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR4]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR5]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR6]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR7]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_COM_CTRL]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_COM_PU]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_COM_OVR]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_COM_RESET]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_COM_RCAL]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_COM_RC_RXLPF]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_COM_RC_TXLPF]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_COM_RC_RXHPF]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR16]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR17]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR18]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR19]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR20]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR21]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR22]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR23]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR24]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR25]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR26]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR27]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR28]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR29]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR30]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR31]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_IQCAL_GAIN_BW]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_LOFT_FINE_I]		= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+	[B2056_TX_LOFT_FINE_Q]		= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+	[B2056_TX_LOFT_COARSE_I]	= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+	[B2056_TX_LOFT_COARSE_Q]	= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+	[B2056_TX_TX_COM_MASTER1]	= { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, },
+	[B2056_TX_TX_COM_MASTER2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RXIQCAL_TXMUX]	= { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, },
+	[B2056_TX_TX_SSI_MASTER]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_IQCAL_VCM_HG]		= { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, },
+	[B2056_TX_IQCAL_IDAC]		= { .ghz5 = 0x0037, .ghz2 = 0x0037, NOUPLOAD, },
+	[B2056_TX_TSSI_VCM]		= { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, },
+	[B2056_TX_TX_AMP_DET]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TX_SSI_MUX]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TSSIA]		= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_TX_TSSIG]		= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_TX_TSSI_MISC1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TSSI_MISC2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TSSI_MISC3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_PA_SPARE1]		= { .ghz5 = 0x0011, .ghz2 = 0x0011, NOUPLOAD, },
+	[B2056_TX_PA_SPARE2]		= { .ghz5 = 0x00ee, .ghz2 = 0x00ee, UPLOAD, },
+	[B2056_TX_INTPAA_MASTER]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAA_GAIN]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAA_BOOST_TUNE]	= { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, },
+	[B2056_TX_INTPAA_IAUX_STAT]	= { .ghz5 = 0x0050, .ghz2 = 0x0050, UPLOAD, },
+	[B2056_TX_INTPAA_IAUX_DYN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAA_IMAIN_STAT]	= { .ghz5 = 0x0050, .ghz2 = 0x0050, UPLOAD, },
+	[B2056_TX_INTPAA_IMAIN_DYN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAA_CASCBIAS]	= { .ghz5 = 0x006e, .ghz2 = 0x006e, NOUPLOAD, },
+	[B2056_TX_INTPAA_PASLOPE]	= { .ghz5 = 0x00f0, .ghz2 = 0x00f0, UPLOAD, },
+	[B2056_TX_INTPAA_PA_MISC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAG_MASTER]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAG_GAIN]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAG_BOOST_TUNE]	= { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, },
+	[B2056_TX_INTPAG_IAUX_STAT]	= { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, },
+	[B2056_TX_INTPAG_IAUX_DYN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAG_IMAIN_STAT]	= { .ghz5 = 0x001e, .ghz2 = 0x001e, NOUPLOAD, },
+	[B2056_TX_INTPAG_IMAIN_DYN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAG_CASCBIAS]	= { .ghz5 = 0x006e, .ghz2 = 0x006e, NOUPLOAD, },
+	[B2056_TX_INTPAG_PASLOPE]	= { .ghz5 = 0x00f0, .ghz2 = 0x00f0, UPLOAD, },
+	[B2056_TX_INTPAG_PA_MISC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_PADA_MASTER]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_TX_PADA_IDAC]		= { .ghz5 = 0x00ff, .ghz2 = 0x00ff, UPLOAD, },
+	[B2056_TX_PADA_CASCBIAS]	= { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, },
+	[B2056_TX_PADA_GAIN]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_PADA_BOOST_TUNE]	= { .ghz5 = 0x0038, .ghz2 = 0x0038, NOUPLOAD, },
+	[B2056_TX_PADA_SLOPE]		= { .ghz5 = 0x0070, .ghz2 = 0x0070, UPLOAD, },
+	[B2056_TX_PADG_MASTER]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_TX_PADG_IDAC]		= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+	[B2056_TX_PADG_CASCBIAS]	= { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, },
+	[B2056_TX_PADG_GAIN]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_PADG_BOOST_TUNE]	= { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+	[B2056_TX_PADG_SLOPE]		= { .ghz5 = 0x0070, .ghz2 = 0x0070, UPLOAD, },
+	[B2056_TX_PGAA_MASTER]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_TX_PGAA_IDAC]		= { .ghz5 = 0x00ff, .ghz2 = 0x00ff, UPLOAD, },
+	[B2056_TX_PGAA_GAIN]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_PGAA_BOOST_TUNE]	= { .ghz5 = 0x0083, .ghz2 = 0x0083, NOUPLOAD, },
+	[B2056_TX_PGAA_SLOPE]		= { .ghz5 = 0x0077, .ghz2 = 0x0077, UPLOAD, },
+	[B2056_TX_PGAA_MISC]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_PGAG_MASTER]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_TX_PGAG_IDAC]		= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+	[B2056_TX_PGAG_GAIN]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_PGAG_BOOST_TUNE]	= { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+	[B2056_TX_PGAG_SLOPE]		= { .ghz5 = 0x0077, .ghz2 = 0x0077, UPLOAD, },
+	[B2056_TX_PGAG_MISC]		= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_TX_MIXA_MASTER]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_MIXA_BOOST_TUNE]	= { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+	[B2056_TX_MIXG]			= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_MIXG_BOOST_TUNE]	= { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+	[B2056_TX_BB_GM_MASTER]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_GMBB_GM]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_GMBB_IDAC]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, UPLOAD, },
+	[B2056_TX_TXLPF_MASTER]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_RCCAL]		= { .ghz5 = 0x000a, .ghz2 = 0x000a, NOUPLOAD, },
+	[B2056_TX_TXLPF_RCCAL_OFF0]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_RCCAL_OFF1]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_RCCAL_OFF2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_RCCAL_OFF3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_RCCAL_OFF4]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_RCCAL_OFF5]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_RCCAL_OFF6]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_BW]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_TX_TXLPF_GAIN]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_IDAC]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_IDAC_0]		= { .ghz5 = 0x000e, .ghz2 = 0x000e, NOUPLOAD, },
+	[B2056_TX_TXLPF_IDAC_1]		= { .ghz5 = 0x000e, .ghz2 = 0x000e, NOUPLOAD, },
+	[B2056_TX_TXLPF_IDAC_2]		= { .ghz5 = 0x000e, .ghz2 = 0x000e, NOUPLOAD, },
+	[B2056_TX_TXLPF_IDAC_3]		= { .ghz5 = 0x0013, .ghz2 = 0x0013, NOUPLOAD, },
+	[B2056_TX_TXLPF_IDAC_4]		= { .ghz5 = 0x0013, .ghz2 = 0x0013, NOUPLOAD, },
+	[B2056_TX_TXLPF_IDAC_5]		= { .ghz5 = 0x001b, .ghz2 = 0x001b, NOUPLOAD, },
+	[B2056_TX_TXLPF_IDAC_6]		= { .ghz5 = 0x001b, .ghz2 = 0x001b, NOUPLOAD, },
+	[B2056_TX_TXLPF_OPAMP_IDAC]	= { .ghz5 = 0x0055, .ghz2 = 0x0055, NOUPLOAD, },
+	[B2056_TX_TXLPF_MISC]		= { .ghz5 = 0x005b, .ghz2 = 0x005b, NOUPLOAD, },
+	[B2056_TX_TXSPARE1]		= { .ghz5 = 0x0030, .ghz2 = 0x0030, UPLOAD, },
+	[B2056_TX_TXSPARE2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE4]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE5]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE6]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE7]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE8]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE9]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE10]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE11]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE12]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE13]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE14]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE15]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE16]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_STATUS_INTPA_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_STATUS_PAD_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_STATUS_PGA_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_STATUS_GM_TXLPF_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_STATUS_TXLPF_BW]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_STATUS_TXLPF_RC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_GMBB_IDAC0]		= { .ghz5 = 0x0070, .ghz2 = 0x0070, NOUPLOAD, },
+	[B2056_TX_GMBB_IDAC1]		= { .ghz5 = 0x0070, .ghz2 = 0x0070, NOUPLOAD, },
+	[B2056_TX_GMBB_IDAC2]		= { .ghz5 = 0x0071, .ghz2 = 0x0071, UPLOAD, },
+	[B2056_TX_GMBB_IDAC3]		= { .ghz5 = 0x0071, .ghz2 = 0x0071, UPLOAD, },
+	[B2056_TX_GMBB_IDAC4]		= { .ghz5 = 0x0072, .ghz2 = 0x0072, UPLOAD, },
+	[B2056_TX_GMBB_IDAC5]		= { .ghz5 = 0x0073, .ghz2 = 0x0073, UPLOAD, },
+	[B2056_TX_GMBB_IDAC6]		= { .ghz5 = 0x0074, .ghz2 = 0x0074, UPLOAD, },
+	[B2056_TX_GMBB_IDAC7]		= { .ghz5 = 0x0075, .ghz2 = 0x0075, UPLOAD, },
+};
+
+static const struct b2056_inittab_entry b2056_inittab_rev7_rx[] = {
+	[B2056_RX_RESERVED_ADDR2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR4]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR5]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR6]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR7]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_COM_CTRL]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_COM_PU]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_COM_OVR]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_COM_RESET]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_COM_RCAL]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_COM_RC_RXLPF]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_COM_RC_TXLPF]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_COM_RC_RXHPF]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR16]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR17]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR18]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR19]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR20]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR21]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR22]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR23]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR24]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR25]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR26]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR27]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR28]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR29]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR30]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR31]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXIQCAL_RXMUX]	= { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, },
+	[B2056_RX_RSSI_PU]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RSSI_SEL]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RSSI_GAIN]		= { .ghz5 = 0x0090, .ghz2 = 0x0090, NOUPLOAD, },
+	[B2056_RX_RSSI_NB_IDAC]		= { .ghz5 = 0x0055, .ghz2 = 0x0055, NOUPLOAD, },
+	[B2056_RX_RSSI_WB2I_IDAC_1]	= { .ghz5 = 0x0015, .ghz2 = 0x0015, NOUPLOAD, },
+	[B2056_RX_RSSI_WB2I_IDAC_2]	= { .ghz5 = 0x0005, .ghz2 = 0x0005, NOUPLOAD, },
+	[B2056_RX_RSSI_WB2Q_IDAC_1]	= { .ghz5 = 0x0015, .ghz2 = 0x0015, NOUPLOAD, },
+	[B2056_RX_RSSI_WB2Q_IDAC_2]	= { .ghz5 = 0x0005, .ghz2 = 0x0005, NOUPLOAD, },
+	[B2056_RX_RSSI_POLE]		= { .ghz5 = 0x0020, .ghz2 = 0x0020, NOUPLOAD, },
+	[B2056_RX_RSSI_WB1_IDAC]	= { .ghz5 = 0x0011, .ghz2 = 0x0011, NOUPLOAD, },
+	[B2056_RX_RSSI_MISC]		= { .ghz5 = 0x0090, .ghz2 = 0x0090, NOUPLOAD, },
+	[B2056_RX_LNAA_MASTER]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_LNAA_TUNE]		= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+	[B2056_RX_LNAA_GAIN]		= { .ghz5 = 0x0032, .ghz2 = 0x0032, NOUPLOAD, },
+	[B2056_RX_LNA_A_SLOPE]		= { .ghz5 = 0x0077, .ghz2 = 0x0077, NOUPLOAD, },
+	[B2056_RX_BIASPOLE_LNAA1_IDAC]	= { .ghz5 = 0x0017, .ghz2 = 0x0017, UPLOAD, },
+	[B2056_RX_LNAA2_IDAC]		= { .ghz5 = 0x00ff, .ghz2 = 0x00ff, UPLOAD, },
+	[B2056_RX_LNA1A_MISC]		= { .ghz5 = 0x0020, .ghz2 = 0x0020, NOUPLOAD, },
+	[B2056_RX_LNAG_MASTER]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_LNAG_TUNE]		= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+	[B2056_RX_LNAG_GAIN]		= { .ghz5 = 0x0032, .ghz2 = 0x0032, NOUPLOAD, },
+	[B2056_RX_LNA_G_SLOPE]		= { .ghz5 = 0x0077, .ghz2 = 0x0077, NOUPLOAD, },
+	[B2056_RX_BIASPOLE_LNAG1_IDAC]	= { .ghz5 = 0x0017, .ghz2 = 0x0017, UPLOAD, },
+	[B2056_RX_LNAG2_IDAC]		= { .ghz5 = 0x00f0, .ghz2 = 0x00f0, UPLOAD, },
+	[B2056_RX_LNA1G_MISC]		= { .ghz5 = 0x0020, .ghz2 = 0x0020, NOUPLOAD, },
+	[B2056_RX_MIXA_MASTER]		= { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+	[B2056_RX_MIXA_VCM]		= { .ghz5 = 0x0055, .ghz2 = 0x0055, UPLOAD, },
+	[B2056_RX_MIXA_CTRLPTAT]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_MIXA_LOB_BIAS]	= { .ghz5 = 0x0088, .ghz2 = 0x0088, UPLOAD, },
+	[B2056_RX_MIXA_CORE_IDAC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_MIXA_CMFB_IDAC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, UPLOAD, },
+	[B2056_RX_MIXA_BIAS_AUX]	= { .ghz5 = 0x0007, .ghz2 = 0x0007, UPLOAD, },
+	[B2056_RX_MIXA_BIAS_MAIN]	= { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
+	[B2056_RX_MIXA_BIAS_MISC]	= { .ghz5 = 0x0004, .ghz2 = 0x0004, NOUPLOAD, },
+	[B2056_RX_MIXA_MAST_BIAS]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_MIXG_MASTER]		= { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+	[B2056_RX_MIXG_VCM]		= { .ghz5 = 0x0055, .ghz2 = 0x0055, UPLOAD, },
+	[B2056_RX_MIXG_CTRLPTAT]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_MIXG_LOB_BIAS]	= { .ghz5 = 0x0011, .ghz2 = 0x0011, NOUPLOAD, },
+	[B2056_RX_MIXG_CORE_IDAC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_MIXG_CMFB_IDAC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, UPLOAD, },
+	[B2056_RX_MIXG_BIAS_AUX]	= { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+	[B2056_RX_MIXG_BIAS_MAIN]	= { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
+	[B2056_RX_MIXG_BIAS_MISC]	= { .ghz5 = 0x0004, .ghz2 = 0x0004, NOUPLOAD, },
+	[B2056_RX_MIXG_MAST_BIAS]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_TIA_MASTER]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_TIA_IOPAMP]		= { .ghz5 = 0x0026, .ghz2 = 0x0026, UPLOAD, },
+	[B2056_RX_TIA_QOPAMP]		= { .ghz5 = 0x0026, .ghz2 = 0x0026, UPLOAD, },
+	[B2056_RX_TIA_IMISC]		= { .ghz5 = 0x000f, .ghz2 = 0x000f, UPLOAD, },
+	[B2056_RX_TIA_QMISC]		= { .ghz5 = 0x000f, .ghz2 = 0x000f, UPLOAD, },
+	[B2056_RX_TIA_GAIN]		= { .ghz5 = 0x0044, .ghz2 = 0x0044, NOUPLOAD, },
+	[B2056_RX_TIA_SPARE1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_TIA_SPARE2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_BB_LPF_MASTER]	= { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+	[B2056_RX_AACI_MASTER]		= { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+	[B2056_RX_RXLPF_IDAC]		= { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+	[B2056_RX_RXLPF_OPAMPBIAS_LOWQ]	= { .ghz5 = 0x0022, .ghz2 = 0x0022, NOUPLOAD, },
+	[B2056_RX_RXLPF_OPAMPBIAS_HIGHQ]= { .ghz5 = 0x0022, .ghz2 = 0x0022, NOUPLOAD, },
+	[B2056_RX_RXLPF_BIAS_DCCANCEL]	= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_RX_RXLPF_OUTVCM]		= { .ghz5 = 0x0004, .ghz2 = 0x0004, UPLOAD, },
+	[B2056_RX_RXLPF_INVCM_BODY]	= { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+	[B2056_RX_RXLPF_CC_OP]		= { .ghz5 = 0x0055, .ghz2 = 0x0055, NOUPLOAD, },
+	[B2056_RX_RXLPF_GAIN]		= { .ghz5 = 0x0023, .ghz2 = 0x0023, NOUPLOAD, },
+	[B2056_RX_RXLPF_Q_BW]		= { .ghz5 = 0x0041, .ghz2 = 0x0041, NOUPLOAD, },
+	[B2056_RX_RXLPF_HP_CORNER_BW]	= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_RX_RXLPF_RCCAL_HPC]	= { .ghz5 = 0x000a, .ghz2 = 0x000a, NOUPLOAD, },
+	[B2056_RX_RXHPF_OFF0]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXHPF_OFF1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXHPF_OFF2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXHPF_OFF3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXHPF_OFF4]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXHPF_OFF5]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXHPF_OFF6]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXHPF_OFF7]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXLPF_RCCAL_LPC]	= { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, },
+	[B2056_RX_RXLPF_OFF_0]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXLPF_OFF_1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXLPF_OFF_2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXLPF_OFF_3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXLPF_OFF_4]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_UNUSED]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_VGA_MASTER]		= { .ghz5 = 0x0022, .ghz2 = 0x0022, NOUPLOAD, },
+	[B2056_RX_VGA_BIAS]		= { .ghz5 = 0x0022, .ghz2 = 0x0022, NOUPLOAD, },
+	[B2056_RX_VGA_BIAS_DCCANCEL]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, UPLOAD, },
+	[B2056_RX_VGA_GAIN]		= { .ghz5 = 0x000a, .ghz2 = 0x000a, NOUPLOAD, },
+	[B2056_RX_VGA_HP_CORNER_BW]	= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_RX_VGABUF_BIAS]		= { .ghz5 = 0x0022, .ghz2 = 0x0022, NOUPLOAD, },
+	[B2056_RX_VGABUF_GAIN_BW]	= { .ghz5 = 0x0030, .ghz2 = 0x0030, NOUPLOAD, },
+	[B2056_RX_TXFBMIX_A]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_TXFBMIX_G]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE4]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE5]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE6]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE7]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE8]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE9]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE10]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE11]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE12]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE13]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE14]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE15]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE16]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_LNAA_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_LNAG_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_MIXTIA_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_RXLPF_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_VGA_BUF_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_RXLPF_Q]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_RXLPF_BUF_BW]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_RXLPF_VGA_HPC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_RXLPF_RC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_HPC_RC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+};
+
+static const struct b2056_inittab_entry b2056_inittab_rev8_syn[] = {
+	[B2056_SYN_RESERVED_ADDR2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR4]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR5]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR6]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR7]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_COM_CTRL]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_COM_PU]		= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_SYN_COM_OVR]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_COM_RESET]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_COM_RCAL]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_COM_RC_RXLPF]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_COM_RC_TXLPF]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_COM_RC_RXHPF]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR16]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR17]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR18]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR19]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR20]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR21]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR22]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR23]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR24]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR25]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR26]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR27]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR28]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR29]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR30]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR31]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_GPIO_MASTER1]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_GPIO_MASTER2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_TOPBIAS_MASTER]	= { .ghz5 = 0x0060, .ghz2 = 0x0060, NOUPLOAD, },
+	[B2056_SYN_TOPBIAS_RCAL]	= { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
+	[B2056_SYN_AFEREG]		= { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, },
+	[B2056_SYN_TEMPPROCSENSE]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_TEMPPROCSENSEIDAC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_TEMPPROCSENSERCAL]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LPO]			= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_SYN_VDDCAL_MASTER]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_VDDCAL_IDAC]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_VDDCAL_STATUS]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCAL_MASTER]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCAL_CODE_OUT]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL0]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL1]		= { .ghz5 = 0x001f, .ghz2 = 0x001f, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL2]		= { .ghz5 = 0x0015, .ghz2 = 0x0015, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL3]		= { .ghz5 = 0x000f, .ghz2 = 0x000f, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL4]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL5]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL6]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL7]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL8]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL9]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL10]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL11]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_ZCAL_SPARE1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_ZCAL_SPARE2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_MAST1]		= { .ghz5 = 0x0013, .ghz2 = 0x0013, NOUPLOAD, },
+	[B2056_SYN_PLL_MAST2]		= { .ghz5 = 0x000f, .ghz2 = 0x000f, NOUPLOAD, },
+	[B2056_SYN_PLL_MAST3]		= { .ghz5 = 0x0018, .ghz2 = 0x0018, NOUPLOAD, },
+	[B2056_SYN_PLL_BIAS_RESET]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_XTAL0]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_XTAL1]		= { .ghz5 = 0x0020, .ghz2 = 0x0020, NOUPLOAD, },
+	[B2056_SYN_PLL_XTAL3]		= { .ghz5 = 0x0020, .ghz2 = 0x0020, NOUPLOAD, },
+	[B2056_SYN_PLL_XTAL4]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_XTAL5]		= { .ghz5 = 0x0077, .ghz2 = 0x0077, NOUPLOAD, },
+	[B2056_SYN_PLL_XTAL6]		= { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+	[B2056_SYN_PLL_REFDIV]		= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_SYN_PLL_PFD]		= { .ghz5 = 0x0004, .ghz2 = 0x0004, NOUPLOAD, },
+	[B2056_SYN_PLL_CP1]		= { .ghz5 = 0x000f, .ghz2 = 0x000f, NOUPLOAD, },
+	[B2056_SYN_PLL_CP2]		= { .ghz5 = 0x0030, .ghz2 = 0x0030, NOUPLOAD, },
+	[B2056_SYN_PLL_CP3]		= { .ghz5 = 0x0032, .ghz2 = 0x0032, NOUPLOAD, },
+	[B2056_SYN_PLL_LOOPFILTER1]	= { .ghz5 = 0x000d, .ghz2 = 0x000d, NOUPLOAD, },
+	[B2056_SYN_PLL_LOOPFILTER2]	= { .ghz5 = 0x000d, .ghz2 = 0x000d, NOUPLOAD, },
+	[B2056_SYN_PLL_LOOPFILTER3]	= { .ghz5 = 0x0004, .ghz2 = 0x0004, NOUPLOAD, },
+	[B2056_SYN_PLL_LOOPFILTER4]	= { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
+	[B2056_SYN_PLL_LOOPFILTER5]	= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_SYN_PLL_MMD1]		= { .ghz5 = 0x001c, .ghz2 = 0x001c, NOUPLOAD, },
+	[B2056_SYN_PLL_MMD2]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_SYN_PLL_VCO1]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_SYN_PLL_VCO2]		= { .ghz5 = 0x00f7, .ghz2 = 0x00f7, UPLOAD, },
+	[B2056_SYN_PLL_MONITOR1]	= { .ghz5 = 0x00b4, .ghz2 = 0x00b4, NOUPLOAD, },
+	[B2056_SYN_PLL_MONITOR2]	= { .ghz5 = 0x00d2, .ghz2 = 0x00d2, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL4]		= { .ghz5 = 0x0004, .ghz2 = 0x0004, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL5]		= { .ghz5 = 0x0096, .ghz2 = 0x0096, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL6]		= { .ghz5 = 0x003e, .ghz2 = 0x003e, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL7]		= { .ghz5 = 0x003e, .ghz2 = 0x003e, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL8]		= { .ghz5 = 0x0013, .ghz2 = 0x0013, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL9]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL10]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL11]	= { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL12]	= { .ghz5 = 0x0007, .ghz2 = 0x0007, UPLOAD, },
+	[B2056_SYN_PLL_VCOCAL13]	= { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+	[B2056_SYN_PLL_VREG]		= { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, },
+	[B2056_SYN_PLL_STATUS1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_STATUS2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_STATUS3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PU0]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PU1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PU2]		= { .ghz5 = 0x0040, .ghz2 = 0x0040, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PU3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PU5]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PU6]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PU7]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PU8]		= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_SYN_LOGEN_BIAS_RESET]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_RCCR1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_VCOBUF1]	= { .ghz5 = 0x0060, .ghz2 = 0x0060, NOUPLOAD, },
+	[B2056_SYN_LOGEN_MIXER1]	= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_MIXER2]	= { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, },
+	[B2056_SYN_LOGEN_BUF1]		= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGENBUF2]		= { .ghz5 = 0x008f, .ghz2 = 0x008f, UPLOAD, },
+	[B2056_SYN_LOGEN_BUF3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_BUF4]		= { .ghz5 = 0x00cc, .ghz2 = 0x00cc, NOUPLOAD, },
+	[B2056_SYN_LOGEN_DIV1]		= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_SYN_LOGEN_DIV2]		= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_DIV3]		= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACL1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACL2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACL3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACL4]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACL5]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACL6]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACLOUT]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACLCAL1]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACLCAL2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACLCAL3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_CALEN]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PEAKDET1]	= { .ghz5 = 0x00ff, .ghz2 = 0x00ff, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CORE_ACL_OVR]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_RX_DIFF_ACL_OVR]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_TX_DIFF_ACL_OVR]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_RX_CMOS_ACL_OVR]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_TX_CMOS_ACL_OVR]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_VCOBUF2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_MIXER3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_BUF5]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_BUF6]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFRX1]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFRX2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFRX3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFRX4]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFTX1]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFTX2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFTX3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFTX4]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSRX1]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSRX2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSRX3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSRX4]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSTX1]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSTX2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSTX3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSTX4]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_VCOBUF2_OVRVAL]= { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
+	[B2056_SYN_LOGEN_MIXER3_OVRVAL]	= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_BUF5_OVRVAL]	= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_BUF6_OVRVAL]	= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFRX1_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFRX2_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFRX3_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFRX4_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFTX1_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFTX2_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFTX3_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFTX4_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSRX1_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSRX2_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSRX3_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSRX4_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSTX1_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSTX2_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSTX3_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSTX4_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACL_WAITCNT]	= { .ghz5 = 0x000a, .ghz2 = 0x000a, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CORE_CALVALID]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_RX_CMOS_CALVALID]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_TX_CMOS_VALID]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+};
+
+static const struct b2056_inittab_entry b2056_inittab_rev8_tx[] = {
+	[B2056_TX_RESERVED_ADDR2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR4]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR5]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR6]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR7]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_COM_CTRL]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_COM_PU]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_COM_OVR]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_COM_RESET]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_COM_RCAL]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_COM_RC_RXLPF]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_COM_RC_TXLPF]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_COM_RC_RXHPF]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR16]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR17]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR18]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR19]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR20]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR21]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR22]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR23]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR24]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR25]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR26]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR27]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR28]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR29]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR30]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR31]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_IQCAL_GAIN_BW]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_LOFT_FINE_I]		= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+	[B2056_TX_LOFT_FINE_Q]		= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+	[B2056_TX_LOFT_COARSE_I]	= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+	[B2056_TX_LOFT_COARSE_Q]	= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+	[B2056_TX_TX_COM_MASTER1]	= { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, },
+	[B2056_TX_TX_COM_MASTER2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RXIQCAL_TXMUX]	= { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, },
+	[B2056_TX_TX_SSI_MASTER]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_IQCAL_VCM_HG]		= { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, },
+	[B2056_TX_IQCAL_IDAC]		= { .ghz5 = 0x0037, .ghz2 = 0x0037, NOUPLOAD, },
+	[B2056_TX_TSSI_VCM]		= { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, },
+	[B2056_TX_TX_AMP_DET]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TX_SSI_MUX]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TSSIA]		= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_TX_TSSIG]		= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_TX_TSSI_MISC1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TSSI_MISC2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TSSI_MISC3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_PA_SPARE1]		= { .ghz5 = 0x0011, .ghz2 = 0x0011, NOUPLOAD, },
+	[B2056_TX_PA_SPARE2]		= { .ghz5 = 0x00ee, .ghz2 = 0x00ee, UPLOAD, },
+	[B2056_TX_INTPAA_MASTER]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAA_GAIN]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAA_BOOST_TUNE]	= { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, },
+	[B2056_TX_INTPAA_IAUX_STAT]	= { .ghz5 = 0x0050, .ghz2 = 0x0050, UPLOAD, },
+	[B2056_TX_INTPAA_IAUX_DYN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAA_IMAIN_STAT]	= { .ghz5 = 0x0050, .ghz2 = 0x0050, UPLOAD, },
+	[B2056_TX_INTPAA_IMAIN_DYN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAA_CASCBIAS]	= { .ghz5 = 0x006e, .ghz2 = 0x006e, NOUPLOAD, },
+	[B2056_TX_INTPAA_PASLOPE]	= { .ghz5 = 0x00f0, .ghz2 = 0x00f0, UPLOAD, },
+	[B2056_TX_INTPAA_PA_MISC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAG_MASTER]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAG_GAIN]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAG_BOOST_TUNE]	= { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, },
+	[B2056_TX_INTPAG_IAUX_STAT]	= { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, },
+	[B2056_TX_INTPAG_IAUX_DYN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAG_IMAIN_STAT]	= { .ghz5 = 0x001e, .ghz2 = 0x001e, NOUPLOAD, },
+	[B2056_TX_INTPAG_IMAIN_DYN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAG_CASCBIAS]	= { .ghz5 = 0x006e, .ghz2 = 0x006e, NOUPLOAD, },
+	[B2056_TX_INTPAG_PASLOPE]	= { .ghz5 = 0x00f0, .ghz2 = 0x00f0, UPLOAD, },
+	[B2056_TX_INTPAG_PA_MISC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_PADA_MASTER]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_TX_PADA_IDAC]		= { .ghz5 = 0x00ff, .ghz2 = 0x00ff, UPLOAD, },
+	[B2056_TX_PADA_CASCBIAS]	= { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, },
+	[B2056_TX_PADA_GAIN]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_PADA_BOOST_TUNE]	= { .ghz5 = 0x0038, .ghz2 = 0x0038, NOUPLOAD, },
+	[B2056_TX_PADA_SLOPE]		= { .ghz5 = 0x0070, .ghz2 = 0x0070, UPLOAD, },
+	[B2056_TX_PADG_MASTER]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_TX_PADG_IDAC]		= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+	[B2056_TX_PADG_CASCBIAS]	= { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, },
+	[B2056_TX_PADG_GAIN]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_PADG_BOOST_TUNE]	= { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+	[B2056_TX_PADG_SLOPE]		= { .ghz5 = 0x0070, .ghz2 = 0x0070, UPLOAD, },
+	[B2056_TX_PGAA_MASTER]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_TX_PGAA_IDAC]		= { .ghz5 = 0x00ff, .ghz2 = 0x00ff, UPLOAD, },
+	[B2056_TX_PGAA_GAIN]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_PGAA_BOOST_TUNE]	= { .ghz5 = 0x0083, .ghz2 = 0x0083, NOUPLOAD, },
+	[B2056_TX_PGAA_SLOPE]		= { .ghz5 = 0x0077, .ghz2 = 0x0077, UPLOAD, },
+	[B2056_TX_PGAA_MISC]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_PGAG_MASTER]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_TX_PGAG_IDAC]		= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+	[B2056_TX_PGAG_GAIN]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_PGAG_BOOST_TUNE]	= { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+	[B2056_TX_PGAG_SLOPE]		= { .ghz5 = 0x0077, .ghz2 = 0x0077, UPLOAD, },
+	[B2056_TX_PGAG_MISC]		= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_TX_MIXA_MASTER]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_MIXA_BOOST_TUNE]	= { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+	[B2056_TX_MIXG]			= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_MIXG_BOOST_TUNE]	= { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+	[B2056_TX_BB_GM_MASTER]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_GMBB_GM]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_GMBB_IDAC]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, UPLOAD, },
+	[B2056_TX_TXLPF_MASTER]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_RCCAL]		= { .ghz5 = 0x000a, .ghz2 = 0x000a, NOUPLOAD, },
+	[B2056_TX_TXLPF_RCCAL_OFF0]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_RCCAL_OFF1]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_RCCAL_OFF2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_RCCAL_OFF3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_RCCAL_OFF4]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_RCCAL_OFF5]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_RCCAL_OFF6]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_BW]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_TX_TXLPF_GAIN]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_IDAC]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_IDAC_0]		= { .ghz5 = 0x000e, .ghz2 = 0x000e, NOUPLOAD, },
+	[B2056_TX_TXLPF_IDAC_1]		= { .ghz5 = 0x000e, .ghz2 = 0x000e, NOUPLOAD, },
+	[B2056_TX_TXLPF_IDAC_2]		= { .ghz5 = 0x000e, .ghz2 = 0x000e, NOUPLOAD, },
+	[B2056_TX_TXLPF_IDAC_3]		= { .ghz5 = 0x0013, .ghz2 = 0x0013, NOUPLOAD, },
+	[B2056_TX_TXLPF_IDAC_4]		= { .ghz5 = 0x0013, .ghz2 = 0x0013, NOUPLOAD, },
+	[B2056_TX_TXLPF_IDAC_5]		= { .ghz5 = 0x001b, .ghz2 = 0x001b, NOUPLOAD, },
+	[B2056_TX_TXLPF_IDAC_6]		= { .ghz5 = 0x001b, .ghz2 = 0x001b, NOUPLOAD, },
+	[B2056_TX_TXLPF_OPAMP_IDAC]	= { .ghz5 = 0x0055, .ghz2 = 0x0055, NOUPLOAD, },
+	[B2056_TX_TXLPF_MISC]		= { .ghz5 = 0x005b, .ghz2 = 0x005b, NOUPLOAD, },
+	[B2056_TX_TXSPARE1]		= { .ghz5 = 0x0030, .ghz2 = 0x0030, UPLOAD, },
+	[B2056_TX_TXSPARE2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE4]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE5]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE6]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE7]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE8]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE9]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE10]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE11]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE12]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE13]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE14]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE15]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE16]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_STATUS_INTPA_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_STATUS_PAD_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_STATUS_PGA_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_STATUS_GM_TXLPF_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_STATUS_TXLPF_BW]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_STATUS_TXLPF_RC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_GMBB_IDAC0]		= { .ghz5 = 0x0070, .ghz2 = 0x0070, NOUPLOAD, },
+	[B2056_TX_GMBB_IDAC1]		= { .ghz5 = 0x0070, .ghz2 = 0x0070, NOUPLOAD, },
+	[B2056_TX_GMBB_IDAC2]		= { .ghz5 = 0x0070, .ghz2 = 0x0070, NOUPLOAD, },
+	[B2056_TX_GMBB_IDAC3]		= { .ghz5 = 0x0070, .ghz2 = 0x0070, NOUPLOAD, },
+	[B2056_TX_GMBB_IDAC4]		= { .ghz5 = 0x0070, .ghz2 = 0x0070, NOUPLOAD, },
+	[B2056_TX_GMBB_IDAC5]		= { .ghz5 = 0x0070, .ghz2 = 0x0070, NOUPLOAD, },
+	[B2056_TX_GMBB_IDAC6]		= { .ghz5 = 0x0070, .ghz2 = 0x0070, NOUPLOAD, },
+	[B2056_TX_GMBB_IDAC7]		= { .ghz5 = 0x0070, .ghz2 = 0x0070, NOUPLOAD, },
+};
+
+static const struct b2056_inittab_entry b2056_inittab_rev8_rx[] = {
+	[B2056_RX_RESERVED_ADDR2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR4]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR5]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR6]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR7]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_COM_CTRL]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_COM_PU]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_COM_OVR]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_COM_RESET]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_COM_RCAL]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_COM_RC_RXLPF]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_COM_RC_TXLPF]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_COM_RC_RXHPF]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR16]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR17]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR18]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR19]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR20]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR21]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR22]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR23]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR24]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR25]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR26]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR27]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR28]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR29]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR30]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR31]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXIQCAL_RXMUX]	= { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, },
+	[B2056_RX_RSSI_PU]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RSSI_SEL]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RSSI_GAIN]		= { .ghz5 = 0x0090, .ghz2 = 0x0090, NOUPLOAD, },
+	[B2056_RX_RSSI_NB_IDAC]		= { .ghz5 = 0x0055, .ghz2 = 0x0055, NOUPLOAD, },
+	[B2056_RX_RSSI_WB2I_IDAC_1]	= { .ghz5 = 0x0015, .ghz2 = 0x0015, NOUPLOAD, },
+	[B2056_RX_RSSI_WB2I_IDAC_2]	= { .ghz5 = 0x0005, .ghz2 = 0x0005, NOUPLOAD, },
+	[B2056_RX_RSSI_WB2Q_IDAC_1]	= { .ghz5 = 0x0015, .ghz2 = 0x0015, NOUPLOAD, },
+	[B2056_RX_RSSI_WB2Q_IDAC_2]	= { .ghz5 = 0x0005, .ghz2 = 0x0005, NOUPLOAD, },
+	[B2056_RX_RSSI_POLE]		= { .ghz5 = 0x0020, .ghz2 = 0x0020, NOUPLOAD, },
+	[B2056_RX_RSSI_WB1_IDAC]	= { .ghz5 = 0x0011, .ghz2 = 0x0011, NOUPLOAD, },
+	[B2056_RX_RSSI_MISC]		= { .ghz5 = 0x0090, .ghz2 = 0x0090, NOUPLOAD, },
+	[B2056_RX_LNAA_MASTER]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_LNAA_TUNE]		= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+	[B2056_RX_LNAA_GAIN]		= { .ghz5 = 0x0032, .ghz2 = 0x0032, NOUPLOAD, },
+	[B2056_RX_LNA_A_SLOPE]		= { .ghz5 = 0x0077, .ghz2 = 0x0077, NOUPLOAD, },
+	[B2056_RX_BIASPOLE_LNAA1_IDAC]	= { .ghz5 = 0x0017, .ghz2 = 0x0017, UPLOAD, },
+	[B2056_RX_LNAA2_IDAC]		= { .ghz5 = 0x00ff, .ghz2 = 0x00ff, UPLOAD, },
+	[B2056_RX_LNA1A_MISC]		= { .ghz5 = 0x0020, .ghz2 = 0x0020, NOUPLOAD, },
+	[B2056_RX_LNAG_MASTER]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_LNAG_TUNE]		= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+	[B2056_RX_LNAG_GAIN]		= { .ghz5 = 0x0032, .ghz2 = 0x0032, NOUPLOAD, },
+	[B2056_RX_LNA_G_SLOPE]		= { .ghz5 = 0x0077, .ghz2 = 0x0077, NOUPLOAD, },
+	[B2056_RX_BIASPOLE_LNAG1_IDAC]	= { .ghz5 = 0x0017, .ghz2 = 0x0017, UPLOAD, },
+	[B2056_RX_LNAG2_IDAC]		= { .ghz5 = 0x00f0, .ghz2 = 0x00f0, UPLOAD, },
+	[B2056_RX_LNA1G_MISC]		= { .ghz5 = 0x0020, .ghz2 = 0x0020, NOUPLOAD, },
+	[B2056_RX_MIXA_MASTER]		= { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+	[B2056_RX_MIXA_VCM]		= { .ghz5 = 0x0055, .ghz2 = 0x0055, UPLOAD, },
+	[B2056_RX_MIXA_CTRLPTAT]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_MIXA_LOB_BIAS]	= { .ghz5 = 0x0088, .ghz2 = 0x0088, UPLOAD, },
+	[B2056_RX_MIXA_CORE_IDAC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_MIXA_CMFB_IDAC]	= { .ghz5 = 0x0044, .ghz2 = 0x0044, NOUPLOAD, },
+	[B2056_RX_MIXA_BIAS_AUX]	= { .ghz5 = 0x0007, .ghz2 = 0x0007, UPLOAD, },
+	[B2056_RX_MIXA_BIAS_MAIN]	= { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
+	[B2056_RX_MIXA_BIAS_MISC]	= { .ghz5 = 0x0004, .ghz2 = 0x0004, NOUPLOAD, },
+	[B2056_RX_MIXA_MAST_BIAS]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_MIXG_MASTER]		= { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+	[B2056_RX_MIXG_VCM]		= { .ghz5 = 0x0055, .ghz2 = 0x0055, UPLOAD, },
+	[B2056_RX_MIXG_CTRLPTAT]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_MIXG_LOB_BIAS]	= { .ghz5 = 0x0011, .ghz2 = 0x0011, NOUPLOAD, },
+	[B2056_RX_MIXG_CORE_IDAC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_MIXG_CMFB_IDAC]	= { .ghz5 = 0x0044, .ghz2 = 0x0044, NOUPLOAD, },
+	[B2056_RX_MIXG_BIAS_AUX]	= { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+	[B2056_RX_MIXG_BIAS_MAIN]	= { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
+	[B2056_RX_MIXG_BIAS_MISC]	= { .ghz5 = 0x0004, .ghz2 = 0x0004, NOUPLOAD, },
+	[B2056_RX_MIXG_MAST_BIAS]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_TIA_MASTER]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_TIA_IOPAMP]		= { .ghz5 = 0x0026, .ghz2 = 0x0026, UPLOAD, },
+	[B2056_RX_TIA_QOPAMP]		= { .ghz5 = 0x0026, .ghz2 = 0x0026, UPLOAD, },
+	[B2056_RX_TIA_IMISC]		= { .ghz5 = 0x000f, .ghz2 = 0x000f, UPLOAD, },
+	[B2056_RX_TIA_QMISC]		= { .ghz5 = 0x000f, .ghz2 = 0x000f, UPLOAD, },
+	[B2056_RX_TIA_GAIN]		= { .ghz5 = 0x0044, .ghz2 = 0x0044, NOUPLOAD, },
+	[B2056_RX_TIA_SPARE1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_TIA_SPARE2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_BB_LPF_MASTER]	= { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+	[B2056_RX_AACI_MASTER]		= { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+	[B2056_RX_RXLPF_IDAC]		= { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+	[B2056_RX_RXLPF_OPAMPBIAS_LOWQ]	= { .ghz5 = 0x0022, .ghz2 = 0x0022, NOUPLOAD, },
+	[B2056_RX_RXLPF_OPAMPBIAS_HIGHQ]= { .ghz5 = 0x0022, .ghz2 = 0x0022, NOUPLOAD, },
+	[B2056_RX_RXLPF_BIAS_DCCANCEL]	= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_RX_RXLPF_OUTVCM]		= { .ghz5 = 0x0004, .ghz2 = 0x0004, UPLOAD, },
+	[B2056_RX_RXLPF_INVCM_BODY]	= { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+	[B2056_RX_RXLPF_CC_OP]		= { .ghz5 = 0x0055, .ghz2 = 0x0055, NOUPLOAD, },
+	[B2056_RX_RXLPF_GAIN]		= { .ghz5 = 0x0023, .ghz2 = 0x0023, NOUPLOAD, },
+	[B2056_RX_RXLPF_Q_BW]		= { .ghz5 = 0x0041, .ghz2 = 0x0041, NOUPLOAD, },
+	[B2056_RX_RXLPF_HP_CORNER_BW]	= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_RX_RXLPF_RCCAL_HPC]	= { .ghz5 = 0x000a, .ghz2 = 0x000a, NOUPLOAD, },
+	[B2056_RX_RXHPF_OFF0]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXHPF_OFF1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXHPF_OFF2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXHPF_OFF3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXHPF_OFF4]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXHPF_OFF5]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXHPF_OFF6]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXHPF_OFF7]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXLPF_RCCAL_LPC]	= { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, },
+	[B2056_RX_RXLPF_OFF_0]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXLPF_OFF_1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXLPF_OFF_2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXLPF_OFF_3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXLPF_OFF_4]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_UNUSED]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_VGA_MASTER]		= { .ghz5 = 0x0022, .ghz2 = 0x0022, NOUPLOAD, },
+	[B2056_RX_VGA_BIAS]		= { .ghz5 = 0x0022, .ghz2 = 0x0022, NOUPLOAD, },
+	[B2056_RX_VGA_BIAS_DCCANCEL]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, UPLOAD, },
+	[B2056_RX_VGA_GAIN]		= { .ghz5 = 0x000a, .ghz2 = 0x000a, NOUPLOAD, },
+	[B2056_RX_VGA_HP_CORNER_BW]	= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_RX_VGABUF_BIAS]		= { .ghz5 = 0x0022, .ghz2 = 0x0022, NOUPLOAD, },
+	[B2056_RX_VGABUF_GAIN_BW]	= { .ghz5 = 0x0030, .ghz2 = 0x0030, NOUPLOAD, },
+	[B2056_RX_TXFBMIX_A]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_TXFBMIX_G]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE3]		= { .ghz5 = 0x0005, .ghz2 = 0x0005, UPLOAD, },
+	[B2056_RX_RXSPARE4]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE5]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE6]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE7]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE8]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE9]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE10]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE11]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE12]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE13]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE14]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE15]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE16]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_LNAA_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_LNAG_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_MIXTIA_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_RXLPF_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_VGA_BUF_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_RXLPF_Q]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_RXLPF_BUF_BW]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_RXLPF_VGA_HPC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_RXLPF_RC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_HPC_RC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+};
+
+#define INITTABSPTS(prefix) \
+	.syn		= prefix##_syn,			\
+	.syn_length	= ARRAY_SIZE(prefix##_syn),	\
+	.tx		= prefix##_tx,			\
+	.tx_length	= ARRAY_SIZE(prefix##_tx),	\
+	.rx		= prefix##_rx,			\
+	.rx_length	= ARRAY_SIZE(prefix##_rx)
+
+struct b2056_inittabs_pts b2056_inittabs[] = {
+	[3] = { INITTABSPTS(b2056_inittab_rev3) },
+	[4] = { INITTABSPTS(b2056_inittab_rev4) },
+	[5] = { INITTABSPTS(b2056_inittab_rev5) },
+	[6] = { INITTABSPTS(b2056_inittab_rev6) },
+	[7] = { INITTABSPTS(b2056_inittab_rev7) },
+	[8] = { INITTABSPTS(b2056_inittab_rev8) },
+	[9] = { INITTABSPTS(b2056_inittab_rev7) },
+};
+
+#define RADIOREGS3(r00, r01, r02, r03, r04, r05, r06, r07, r08, r09, \
+		   r10, r11, r12, r13, r14, r15, r16, r17, r18, r19, \
+		   r20, r21, r22, r23, r24, r25, r26, r27, r28, r29, \
+		   r30, r31, r32, r33, r34, r35, r36) \
+	.radio_syn_pll_vcocal1		= r00,	\
+	.radio_syn_pll_vcocal2		= r01,	\
+	.radio_syn_pll_refdiv		= r02,	\
+	.radio_syn_pll_mmd2		= r03,	\
+	.radio_syn_pll_mmd1		= r04,	\
+	.radio_syn_pll_loopfilter1	= r05,	\
+	.radio_syn_pll_loopfilter2	= r06,	\
+	.radio_syn_pll_loopfilter3	= r07,	\
+	.radio_syn_pll_loopfilter4	= r08,	\
+	.radio_syn_pll_loopfilter5	= r09,	\
+	.radio_syn_reserved_addr27	= r10,	\
+	.radio_syn_reserved_addr28	= r11,	\
+	.radio_syn_reserved_addr29	= r12,	\
+	.radio_syn_logen_vcobuf1	= r13,	\
+	.radio_syn_logen_mixer2		= r14,	\
+	.radio_syn_logen_buf3		= r15,	\
+	.radio_syn_logen_buf4		= r16,	\
+	.radio_rx0_lnaa_tune		= r17,	\
+	.radio_rx0_lnag_tune		= r18,	\
+	.radio_tx0_intpaa_boost_tune	= r19,	\
+	.radio_tx0_intpag_boost_tune	= r20,	\
+	.radio_tx0_pada_boost_tune	= r21,	\
+	.radio_tx0_padg_boost_tune	= r22,	\
+	.radio_tx0_pgaa_boost_tune	= r23,	\
+	.radio_tx0_pgag_boost_tune	= r24,	\
+	.radio_tx0_mixa_boost_tune	= r25,	\
+	.radio_tx0_mixg_boost_tune	= r26,	\
+	.radio_rx1_lnaa_tune		= r27,	\
+	.radio_rx1_lnag_tune		= r28,	\
+	.radio_tx1_intpaa_boost_tune	= r29,	\
+	.radio_tx1_intpag_boost_tune	= r30,	\
+	.radio_tx1_pada_boost_tune	= r31,	\
+	.radio_tx1_padg_boost_tune	= r32,	\
+	.radio_tx1_pgaa_boost_tune	= r33,	\
+	.radio_tx1_pgag_boost_tune	= r34,	\
+	.radio_tx1_mixa_boost_tune	= r35,	\
+	.radio_tx1_mixg_boost_tune	= r36
+
+#define PHYREGS(r0, r1, r2, r3, r4, r5)	\
+	.phy_regs.phy_bw1a	= r0,	\
+	.phy_regs.phy_bw2	= r1,	\
+	.phy_regs.phy_bw3	= r2,	\
+	.phy_regs.phy_bw4	= r3,	\
+	.phy_regs.phy_bw5	= r4,	\
+	.phy_regs.phy_bw6	= r5
+
+/* http://bcm-v4.sipsolutions.net/802.11/Radio/2056/ChannelTable */
 static const struct b43_nphy_channeltab_entry_rev3 b43_nphy_channeltab_rev3[] = {
+  {	.freq			= 4920,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b,
+		   0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f,
+		   0x00, 0x0b, 0x00, 0xff, 0x00),
+	PHYREGS(0x07b4, 0x07b0, 0x07ac, 0x0214, 0x0215, 0x0216),
+  },
+  {	.freq			= 4930,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xed, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b,
+		   0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f,
+		   0x00, 0x0b, 0x00, 0xff, 0x00),
+	PHYREGS(0x07b8, 0x07b4, 0x07b0, 0x0213, 0x0214, 0x0215),
+  },
+  {	.freq			= 4940,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xee, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b,
+		   0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f,
+		   0x00, 0x0b, 0x00, 0xff, 0x00),
+	PHYREGS(0x07bc, 0x07b8, 0x07b4, 0x0212, 0x0213, 0x0214),
+  },
+  {	.freq			= 4950,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xef, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b,
+		   0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f,
+		   0x00, 0x0b, 0x00, 0xff, 0x00),
+	PHYREGS(0x07c0, 0x07bc, 0x07b8, 0x0211, 0x0212, 0x0213),
+  },
+  {	.freq			= 4960,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf0, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b,
+		   0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f,
+		   0x00, 0x0b, 0x00, 0xff, 0x00),
+	PHYREGS(0x07c4, 0x07c0, 0x07bc, 0x020f, 0x0211, 0x0212),
+  },
+  {	.freq			= 4970,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf1, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b,
+		   0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f,
+		   0x00, 0x0b, 0x00, 0xff, 0x00),
+	PHYREGS(0x07c8, 0x07c4, 0x07c0, 0x020e, 0x020f, 0x0211),
+  },
+  {	.freq			= 4980,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf2, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b,
+		   0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f,
+		   0x00, 0x0b, 0x00, 0xff, 0x00),
+	PHYREGS(0x07cc, 0x07c8, 0x07c4, 0x020d, 0x020e, 0x020f),
+  },
+  {	.freq			= 4990,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf3, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b,
+		   0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f,
+		   0x00, 0x0b, 0x00, 0xff, 0x00),
+	PHYREGS(0x07d0, 0x07cc, 0x07c8, 0x020c, 0x020d, 0x020e),
+  },
+  {	.freq			= 5000,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf4, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+		   0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f,
+		   0x00, 0x0b, 0x00, 0xff, 0x00),
+	PHYREGS(0x07d4, 0x07d0, 0x07cc, 0x020b, 0x020c, 0x020d),
+  },
+  {	.freq			= 5010,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf5, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+		   0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f,
+		   0x00, 0x0b, 0x00, 0xff, 0x00),
+	PHYREGS(0x07d8, 0x07d4, 0x07d0, 0x020a, 0x020b, 0x020c),
+  },
+  {	.freq			= 5020,
+	RADIOREGS3(0xf7, 0x01, 0x01, 0x01, 0xf6, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+		   0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f,
+		   0x00, 0x0b, 0x00, 0xff, 0x00),
+	PHYREGS(0x07dc, 0x07d8, 0x07d4, 0x0209, 0x020a, 0x020b),
+  },
+  {	.freq			= 5030,
+	RADIOREGS3(0xf7, 0x01, 0x01, 0x01, 0xf7, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+		   0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f,
+		   0x00, 0x0b, 0x00, 0xff, 0x00),
+	PHYREGS(0x07e0, 0x07dc, 0x07d8, 0x0208, 0x0209, 0x020a),
+  },
+  {	.freq			= 5040,
+	RADIOREGS3(0xef, 0x01, 0x01, 0x01, 0xf8, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+		   0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f,
+		   0x00, 0x0b, 0x00, 0xff, 0x00),
+	PHYREGS(0x07e4, 0x07e0, 0x07dc, 0x0207, 0x0208, 0x0209),
+  },
+  {	.freq			= 5050,
+	RADIOREGS3(0xef, 0x01, 0x01, 0x01, 0xf9, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+		   0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f,
+		   0x00, 0x0b, 0x00, 0xff, 0x00),
+	PHYREGS(0x07e8, 0x07e4, 0x07e0, 0x0206, 0x0207, 0x0208),
+  },
+  {	.freq			= 5060,
+	RADIOREGS3(0xe6, 0x01, 0x01, 0x01, 0xfa, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+		   0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f,
+		   0x00, 0x0b, 0x00, 0xff, 0x00),
+	PHYREGS(0x07ec, 0x07e8, 0x07e4, 0x0205, 0x0206, 0x0207),
+  },
+  {	.freq			= 5070,
+	RADIOREGS3(0xe6, 0x01, 0x01, 0x01, 0xfb, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+		   0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f,
+		   0x00, 0x0b, 0x00, 0xff, 0x00),
+	PHYREGS(0x07f0, 0x07ec, 0x07e8, 0x0204, 0x0205, 0x0206),
+  },
+  {	.freq			= 5080,
+	RADIOREGS3(0xde, 0x01, 0x01, 0x01, 0xfc, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+		   0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f,
+		   0x00, 0x0b, 0x00, 0xff, 0x00),
+	PHYREGS(0x07f4, 0x07f0, 0x07ec, 0x0203, 0x0204, 0x0205),
+  },
+  {	.freq			= 5090,
+	RADIOREGS3(0xde, 0x01, 0x01, 0x01, 0xfd, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+		   0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f,
+		   0x00, 0x0b, 0x00, 0xff, 0x00),
+	PHYREGS(0x07f8, 0x07f4, 0x07f0, 0x0202, 0x0203, 0x0204),
+  },
+  {	.freq			= 5100,
+	RADIOREGS3(0xd6, 0x01, 0x01, 0x01, 0xfe, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+		   0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f,
+		   0x00, 0x0b, 0x00, 0xff, 0x00),
+	PHYREGS(0x07fc, 0x07f8, 0x07f4, 0x0201, 0x0202, 0x0203),
+  },
+  {	.freq			= 5110,
+	RADIOREGS3(0xd6, 0x01, 0x01, 0x01, 0xff, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+		   0x00, 0xfc, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f,
+		   0x00, 0x0b, 0x00, 0xfc, 0x00),
+	PHYREGS(0x0800, 0x07fc, 0x07f8, 0x0200, 0x0201, 0x0202),
+  },
+  {	.freq			= 5120,
+	RADIOREGS3(0xce, 0x01, 0x01, 0x02, 0x00, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+		   0x00, 0xfc, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f,
+		   0x00, 0x0b, 0x00, 0xfc, 0x00),
+	PHYREGS(0x0804, 0x0800, 0x07fc, 0x01ff, 0x0200, 0x0201),
+  },
+  {	.freq			= 5130,
+	RADIOREGS3(0xce, 0x01, 0x01, 0x02, 0x01, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+		   0x00, 0xfc, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f,
+		   0x00, 0x0b, 0x00, 0xfc, 0x00),
+	PHYREGS(0x0808, 0x0804, 0x0800, 0x01fe, 0x01ff, 0x0200),
+  },
+  {	.freq			= 5140,
+	RADIOREGS3(0xc6, 0x01, 0x01, 0x02, 0x02, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+		   0x00, 0xfc, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f,
+		   0x00, 0x0b, 0x00, 0xfc, 0x00),
+	PHYREGS(0x080c, 0x0808, 0x0804, 0x01fd, 0x01fe, 0x01ff),
+  },
+  {	.freq			= 5160,
+	RADIOREGS3(0xbe, 0x01, 0x01, 0x02, 0x04, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+		   0x00, 0xfc, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f,
+		   0x00, 0x0b, 0x00, 0xfc, 0x00),
+	PHYREGS(0x0814, 0x0810, 0x080c, 0x01fb, 0x01fc, 0x01fd),
+  },
+  {	.freq			= 5170,
+	RADIOREGS3(0xbe, 0x01, 0x01, 0x02, 0x05, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+		   0x00, 0xfc, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f,
+		   0x00, 0x0b, 0x00, 0xfc, 0x00),
+	PHYREGS(0x0818, 0x0814, 0x0810, 0x01fa, 0x01fb, 0x01fc),
+  },
+  {	.freq			= 5180,
+	RADIOREGS3(0xb6, 0x01, 0x01, 0x02, 0x06, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xef, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+		   0x00, 0xfc, 0x00, 0xef, 0x00, 0x07, 0x00, 0x7f,
+		   0x00, 0x0b, 0x00, 0xfc, 0x00),
+	PHYREGS(0x081c, 0x0818, 0x0814, 0x01f9, 0x01fa, 0x01fb),
+  },
+  {	.freq			= 5190,
+	RADIOREGS3(0xb6, 0x01, 0x01, 0x02, 0x07, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xef, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+		   0x00, 0xfc, 0x00, 0xef, 0x00, 0x07, 0x00, 0x7f,
+		   0x00, 0x0b, 0x00, 0xfc, 0x00),
+	PHYREGS(0x0820, 0x081c, 0x0818, 0x01f8, 0x01f9, 0x01fa),
+  },
+  {	.freq			= 5200,
+	RADIOREGS3(0xaf, 0x01, 0x01, 0x02, 0x08, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xef, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a,
+		   0x00, 0xfc, 0x00, 0xef, 0x00, 0x06, 0x00, 0x7f,
+		   0x00, 0x0a, 0x00, 0xfc, 0x00),
+	PHYREGS(0x0824, 0x0820, 0x081c, 0x01f7, 0x01f8, 0x01f9),
+  },
+  {	.freq			= 5210,
+	RADIOREGS3(0xaf, 0x01, 0x01, 0x02, 0x09, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xdf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a,
+		   0x00, 0xfc, 0x00, 0xdf, 0x00, 0x06, 0x00, 0x7f,
+		   0x00, 0x0a, 0x00, 0xfc, 0x00),
+	PHYREGS(0x0828, 0x0824, 0x0820, 0x01f6, 0x01f7, 0x01f8),
+  },
+  {	.freq			= 5220,
+	RADIOREGS3(0xa7, 0x01, 0x01, 0x02, 0x0a, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xdf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a,
+		   0x00, 0xfc, 0x00, 0xdf, 0x00, 0x06, 0x00, 0x7f,
+		   0x00, 0x0a, 0x00, 0xfc, 0x00),
+	PHYREGS(0x082c, 0x0828, 0x0824, 0x01f5, 0x01f6, 0x01f7),
+  },
+  {	.freq			= 5230,
+	RADIOREGS3(0xa7, 0x01, 0x01, 0x02, 0x0b, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xdf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a,
+		   0x00, 0xfc, 0x00, 0xdf, 0x00, 0x06, 0x00, 0x7f,
+		   0x00, 0x0a, 0x00, 0xfc, 0x00),
+	PHYREGS(0x0830, 0x082c, 0x0828, 0x01f4, 0x01f5, 0x01f6),
+  },
+  {	.freq			= 5240,
+	RADIOREGS3(0xa0, 0x01, 0x01, 0x02, 0x0c, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xcf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a,
+		   0x00, 0xfc, 0x00, 0xcf, 0x00, 0x06, 0x00, 0x7f,
+		   0x00, 0x0a, 0x00, 0xfc, 0x00),
+	PHYREGS(0x0834, 0x0830, 0x082c, 0x01f3, 0x01f4, 0x01f5),
+  },
+  {	.freq			= 5250,
+	RADIOREGS3(0xa0, 0x01, 0x01, 0x02, 0x0d, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xcf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a,
+		   0x00, 0xfc, 0x00, 0xcf, 0x00, 0x06, 0x00, 0x7f,
+		   0x00, 0x0a, 0x00, 0xfc, 0x00),
+	PHYREGS(0x0838, 0x0834, 0x0830, 0x01f2, 0x01f3, 0x01f4),
+  },
+  {	.freq			= 5260,
+	RADIOREGS3(0x98, 0x01, 0x01, 0x02, 0x0e, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xcf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a,
+		   0x00, 0xfc, 0x00, 0xcf, 0x00, 0x06, 0x00, 0x7f,
+		   0x00, 0x0a, 0x00, 0xfc, 0x00),
+	PHYREGS(0x083c, 0x0838, 0x0834, 0x01f1, 0x01f2, 0x01f3),
+  },
+  {	.freq			= 5270,
+	RADIOREGS3(0x98, 0x01, 0x01, 0x02, 0x0f, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00,
+		   0xff, 0xcf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a,
+		   0x00, 0xfc, 0x00, 0xcf, 0x00, 0x06, 0x00, 0x7f,
+		   0x00, 0x0a, 0x00, 0xfc, 0x00),
+	PHYREGS(0x0840, 0x083c, 0x0838, 0x01f0, 0x01f1, 0x01f2),
+  },
+  {	.freq			= 5280,
+	RADIOREGS3(0x91, 0x01, 0x01, 0x02, 0x10, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00,
+		   0xff, 0xbf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a,
+		   0x00, 0xfc, 0x00, 0xbf, 0x00, 0x06, 0x00, 0x7f,
+		   0x00, 0x0a, 0x00, 0xfc, 0x00),
+	PHYREGS(0x0844, 0x0840, 0x083c, 0x01f0, 0x01f0, 0x01f1),
+  },
+  {	.freq			= 5290,
+	RADIOREGS3(0x91, 0x01, 0x01, 0x02, 0x11, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00,
+		   0xff, 0xbf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a,
+		   0x00, 0xfc, 0x00, 0xbf, 0x00, 0x06, 0x00, 0x7f,
+		   0x00, 0x0a, 0x00, 0xfc, 0x00),
+	PHYREGS(0x0848, 0x0844, 0x0840, 0x01ef, 0x01f0, 0x01f0),
+  },
+  {	.freq			= 5300,
+	RADIOREGS3(0x8a, 0x01, 0x01, 0x02, 0x12, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00,
+		   0xff, 0xbf, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09,
+		   0x00, 0xfc, 0x00, 0xbf, 0x00, 0x05, 0x00, 0x7f,
+		   0x00, 0x09, 0x00, 0xfc, 0x00),
+	PHYREGS(0x084c, 0x0848, 0x0844, 0x01ee, 0x01ef, 0x01f0),
+  },
+  {	.freq			= 5310,
+	RADIOREGS3(0x8a, 0x01, 0x01, 0x02, 0x13, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00,
+		   0xff, 0xbf, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09,
+		   0x00, 0xfa, 0x00, 0xbf, 0x00, 0x05, 0x00, 0x7f,
+		   0x00, 0x09, 0x00, 0xfa, 0x00),
+	PHYREGS(0x0850, 0x084c, 0x0848, 0x01ed, 0x01ee, 0x01ef),
+  },
+  {	.freq			= 5320,
+	RADIOREGS3(0x83, 0x01, 0x01, 0x02, 0x14, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00,
+		   0xff, 0xbf, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09,
+		   0x00, 0xfa, 0x00, 0xbf, 0x00, 0x05, 0x00, 0x7f,
+		   0x00, 0x09, 0x00, 0xfa, 0x00),
+	PHYREGS(0x0854, 0x0850, 0x084c, 0x01ec, 0x01ed, 0x01ee),
+  },
+  {	.freq			= 5330,
+	RADIOREGS3(0x83, 0x01, 0x01, 0x02, 0x15, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00,
+		   0xff, 0xaf, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09,
+		   0x00, 0xfa, 0x00, 0xaf, 0x00, 0x05, 0x00, 0x7f,
+		   0x00, 0x09, 0x00, 0xfa, 0x00),
+	PHYREGS(0x0858, 0x0854, 0x0850, 0x01eb, 0x01ec, 0x01ed),
+  },
+  {	.freq			= 5340,
+	RADIOREGS3(0x7c, 0x01, 0x01, 0x02, 0x16, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00,
+		   0xff, 0xaf, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09,
+		   0x00, 0xfa, 0x00, 0xaf, 0x00, 0x05, 0x00, 0x7f,
+		   0x00, 0x09, 0x00, 0xfa, 0x00),
+	PHYREGS(0x085c, 0x0858, 0x0854, 0x01ea, 0x01eb, 0x01ec),
+  },
+  {	.freq			= 5350,
+	RADIOREGS3(0x7c, 0x01, 0x01, 0x02, 0x17, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00,
+		   0xff, 0x9f, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09,
+		   0x00, 0xfa, 0x00, 0x9f, 0x00, 0x05, 0x00, 0x7f,
+		   0x00, 0x09, 0x00, 0xfa, 0x00),
+	PHYREGS(0x0860, 0x085c, 0x0858, 0x01e9, 0x01ea, 0x01eb),
+  },
+  {	.freq			= 5360,
+	RADIOREGS3(0x75, 0x01, 0x01, 0x02, 0x18, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00,
+		   0xff, 0x9f, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09,
+		   0x00, 0xfa, 0x00, 0x9f, 0x00, 0x05, 0x00, 0x7f,
+		   0x00, 0x09, 0x00, 0xfa, 0x00),
+	PHYREGS(0x0864, 0x0860, 0x085c, 0x01e8, 0x01e9, 0x01ea),
+  },
+  {	.freq			= 5370,
+	RADIOREGS3(0x75, 0x01, 0x01, 0x02, 0x19, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00,
+		   0xff, 0x9f, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09,
+		   0x00, 0xfa, 0x00, 0x9f, 0x00, 0x05, 0x00, 0x7f,
+		   0x00, 0x09, 0x00, 0xfa, 0x00),
+	PHYREGS(0x0868, 0x0864, 0x0860, 0x01e7, 0x01e8, 0x01e9),
+  },
+  {	.freq			= 5380,
+	RADIOREGS3(0x6e, 0x01, 0x01, 0x02, 0x1a, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00,
+		   0xff, 0x9f, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09,
+		   0x00, 0xfa, 0x00, 0x9f, 0x00, 0x05, 0x00, 0x7f,
+		   0x00, 0x09, 0x00, 0xfa, 0x00),
+	PHYREGS(0x086c, 0x0868, 0x0864, 0x01e6, 0x01e7, 0x01e8),
+  },
+  {	.freq			= 5390,
+	RADIOREGS3(0x6e, 0x01, 0x01, 0x02, 0x1b, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00,
+		   0xff, 0x8f, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09,
+		   0x00, 0xfa, 0x00, 0x8f, 0x00, 0x05, 0x00, 0x7f,
+		   0x00, 0x09, 0x00, 0xfa, 0x00),
+	PHYREGS(0x0870, 0x086c, 0x0868, 0x01e5, 0x01e6, 0x01e7),
+  },
+  {	.freq			= 5400,
+	RADIOREGS3(0x67, 0x01, 0x01, 0x02, 0x1c, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00,
+		   0xc8, 0x8f, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08,
+		   0x00, 0xfa, 0x00, 0x8f, 0x00, 0x04, 0x00, 0x7f,
+		   0x00, 0x08, 0x00, 0xfa, 0x00),
+	PHYREGS(0x0874, 0x0870, 0x086c, 0x01e5, 0x01e5, 0x01e6),
+  },
+  {	.freq			= 5410,
+	RADIOREGS3(0x67, 0x01, 0x01, 0x02, 0x1d, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00,
+		   0xc8, 0x8f, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08,
+		   0x00, 0xfa, 0x00, 0x8f, 0x00, 0x04, 0x00, 0x7f,
+		   0x00, 0x08, 0x00, 0xfa, 0x00),
+	PHYREGS(0x0878, 0x0874, 0x0870, 0x01e4, 0x01e5, 0x01e5),
+  },
+  {	.freq			= 5420,
+	RADIOREGS3(0x61, 0x01, 0x01, 0x02, 0x1e, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00,
+		   0xc8, 0x8e, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08,
+		   0x00, 0xfa, 0x00, 0x8e, 0x00, 0x04, 0x00, 0x7f,
+		   0x00, 0x08, 0x00, 0xfa, 0x00),
+	PHYREGS(0x087c, 0x0878, 0x0874, 0x01e3, 0x01e4, 0x01e5),
+  },
+  {	.freq			= 5430,
+	RADIOREGS3(0x61, 0x01, 0x01, 0x02, 0x1f, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00,
+		   0xc8, 0x8e, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08,
+		   0x00, 0xfa, 0x00, 0x8e, 0x00, 0x04, 0x00, 0x7f,
+		   0x00, 0x08, 0x00, 0xfa, 0x00),
+	PHYREGS(0x0880, 0x087c, 0x0878, 0x01e2, 0x01e3, 0x01e4),
+  },
+  {	.freq			= 5440,
+	RADIOREGS3(0x5a, 0x01, 0x01, 0x02, 0x20, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00,
+		   0xc8, 0x7e, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08,
+		   0x00, 0xfa, 0x00, 0x7e, 0x00, 0x04, 0x00, 0x7f,
+		   0x00, 0x08, 0x00, 0xfa, 0x00),
+	PHYREGS(0x0884, 0x0880, 0x087c, 0x01e1, 0x01e2, 0x01e3),
+  },
+  {	.freq			= 5450,
+	RADIOREGS3(0x5a, 0x01, 0x01, 0x02, 0x21, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00,
+		   0xc8, 0x7d, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08,
+		   0x00, 0xfa, 0x00, 0x7d, 0x00, 0x04, 0x00, 0x7f,
+		   0x00, 0x08, 0x00, 0xfa, 0x00),
+	PHYREGS(0x0888, 0x0884, 0x0880, 0x01e0, 0x01e1, 0x01e2),
+  },
+  {	.freq			= 5460,
+	RADIOREGS3(0x53, 0x01, 0x01, 0x02, 0x22, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00,
+		   0xc8, 0x6d, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08,
+		   0x00, 0xf8, 0x00, 0x6d, 0x00, 0x04, 0x00, 0x7f,
+		   0x00, 0x08, 0x00, 0xf8, 0x00),
+	PHYREGS(0x088c, 0x0888, 0x0884, 0x01df, 0x01e0, 0x01e1),
+  },
+  {	.freq			= 5470,
+	RADIOREGS3(0x53, 0x01, 0x01, 0x02, 0x23, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00,
+		   0xc8, 0x6d, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08,
+		   0x00, 0xf8, 0x00, 0x6d, 0x00, 0x04, 0x00, 0x7f,
+		   0x00, 0x08, 0x00, 0xf8, 0x00),
+	PHYREGS(0x0890, 0x088c, 0x0888, 0x01de, 0x01df, 0x01e0),
+  },
+  {	.freq			= 5480,
+	RADIOREGS3(0x4d, 0x01, 0x01, 0x02, 0x24, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00,
+		   0xc8, 0x5d, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08,
+		   0x00, 0xf8, 0x00, 0x5d, 0x00, 0x04, 0x00, 0x7f,
+		   0x00, 0x08, 0x00, 0xf8, 0x00),
+	PHYREGS(0x0894, 0x0890, 0x088c, 0x01dd, 0x01de, 0x01df),
+  },
+  {	.freq			= 5490,
+	RADIOREGS3(0x4d, 0x01, 0x01, 0x02, 0x25, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00,
+		   0xc8, 0x5c, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08,
+		   0x00, 0xf8, 0x00, 0x5c, 0x00, 0x04, 0x00, 0x7f,
+		   0x00, 0x08, 0x00, 0xf8, 0x00),
+	PHYREGS(0x0898, 0x0894, 0x0890, 0x01dd, 0x01dd, 0x01de),
+  },
+  {	.freq			= 5500,
+	RADIOREGS3(0x47, 0x01, 0x01, 0x02, 0x26, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00,
+		   0x84, 0x5c, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+		   0x00, 0xf8, 0x00, 0x5c, 0x00, 0x03, 0x00, 0x7f,
+		   0x00, 0x07, 0x00, 0xf8, 0x00),
+	PHYREGS(0x089c, 0x0898, 0x0894, 0x01dc, 0x01dd, 0x01dd),
+  },
+  {	.freq			= 5510,
+	RADIOREGS3(0x47, 0x01, 0x01, 0x02, 0x27, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00,
+		   0x84, 0x4c, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+		   0x00, 0xf8, 0x00, 0x4c, 0x00, 0x03, 0x00, 0x7f,
+		   0x00, 0x07, 0x00, 0xf8, 0x00),
+	PHYREGS(0x08a0, 0x089c, 0x0898, 0x01db, 0x01dc, 0x01dd),
+  },
+  {	.freq			= 5520,
+	RADIOREGS3(0x40, 0x01, 0x01, 0x02, 0x28, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00,
+		   0x84, 0x4c, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+		   0x00, 0xf8, 0x00, 0x4c, 0x00, 0x03, 0x00, 0x7f,
+		   0x00, 0x07, 0x00, 0xf8, 0x00),
+	PHYREGS(0x08a4, 0x08a0, 0x089c, 0x01da, 0x01db, 0x01dc),
+  },
+  {	.freq			= 5530,
+	RADIOREGS3(0x40, 0x01, 0x01, 0x02, 0x29, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00,
+		   0x84, 0x3b, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+		   0x00, 0xf8, 0x00, 0x3b, 0x00, 0x03, 0x00, 0x7f,
+		   0x00, 0x07, 0x00, 0xf8, 0x00),
+	PHYREGS(0x08a8, 0x08a4, 0x08a0, 0x01d9, 0x01da, 0x01db),
+  },
+  {	.freq			= 5540,
+	RADIOREGS3(0x3a, 0x01, 0x01, 0x02, 0x2a, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00,
+		   0x84, 0x3b, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+		   0x00, 0xf8, 0x00, 0x3b, 0x00, 0x03, 0x00, 0x7f,
+		   0x00, 0x07, 0x00, 0xf8, 0x00),
+	PHYREGS(0x08ac, 0x08a8, 0x08a4, 0x01d8, 0x01d9, 0x01da),
+  },
+  {	.freq			= 5550,
+	RADIOREGS3(0x3a, 0x01, 0x01, 0x02, 0x2b, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00,
+		   0x84, 0x3b, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+		   0x00, 0xf8, 0x00, 0x3b, 0x00, 0x03, 0x00, 0x7f,
+		   0x00, 0x07, 0x00, 0xf8, 0x00),
+	PHYREGS(0x08b0, 0x08ac, 0x08a8, 0x01d7, 0x01d8, 0x01d9),
+  },
+  {	.freq			= 5560,
+	RADIOREGS3(0x34, 0x01, 0x01, 0x02, 0x2c, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00,
+		   0x84, 0x2b, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+		   0x00, 0xf8, 0x00, 0x2b, 0x00, 0x03, 0x00, 0x7f,
+		   0x00, 0x07, 0x00, 0xf8, 0x00),
+	PHYREGS(0x08b4, 0x08b0, 0x08ac, 0x01d7, 0x01d7, 0x01d8),
+  },
+  {	.freq			= 5570,
+	RADIOREGS3(0x34, 0x01, 0x01, 0x02, 0x2d, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00,
+		   0x84, 0x2a, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+		   0x00, 0xf8, 0x00, 0x2a, 0x00, 0x03, 0x00, 0x7f,
+		   0x00, 0x07, 0x00, 0xf8, 0x00),
+	PHYREGS(0x08b8, 0x08b4, 0x08b0, 0x01d6, 0x01d7, 0x01d7),
+  },
+  {	.freq			= 5580,
+	RADIOREGS3(0x2e, 0x01, 0x01, 0x02, 0x2e, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00,
+		   0x84, 0x1a, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+		   0x00, 0xf8, 0x00, 0x1a, 0x00, 0x03, 0x00, 0x7f,
+		   0x00, 0x07, 0x00, 0xf8, 0x00),
+	PHYREGS(0x08bc, 0x08b8, 0x08b4, 0x01d5, 0x01d6, 0x01d7),
+  },
+  {	.freq			= 5590,
+	RADIOREGS3(0x2e, 0x01, 0x01, 0x02, 0x2f, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00,
+		   0x84, 0x1a, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+		   0x00, 0xf8, 0x00, 0x1a, 0x00, 0x03, 0x00, 0x7f,
+		   0x00, 0x07, 0x00, 0xf8, 0x00),
+	PHYREGS(0x08c0, 0x08bc, 0x08b8, 0x01d4, 0x01d5, 0x01d6),
+  },
+  {	.freq			= 5600,
+	RADIOREGS3(0x28, 0x01, 0x01, 0x02, 0x30, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00,
+		   0x70, 0x1a, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+		   0x00, 0xf8, 0x00, 0x1a, 0x00, 0x03, 0x00, 0x7f,
+		   0x00, 0x07, 0x00, 0xf8, 0x00),
+	PHYREGS(0x08c4, 0x08c0, 0x08bc, 0x01d3, 0x01d4, 0x01d5),
+  },
+  {	.freq			= 5610,
+	RADIOREGS3(0x28, 0x01, 0x01, 0x02, 0x31, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00,
+		   0x70, 0x19, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+		   0x00, 0xf8, 0x00, 0x19, 0x00, 0x03, 0x00, 0x7f,
+		   0x00, 0x07, 0x00, 0xf8, 0x00),
+	PHYREGS(0x08c8, 0x08c4, 0x08c0, 0x01d2, 0x01d3, 0x01d4),
+  },
+  {	.freq			= 5620,
+	RADIOREGS3(0x21, 0x01, 0x01, 0x02, 0x32, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00,
+		   0x70, 0x19, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+		   0x00, 0xf8, 0x00, 0x19, 0x00, 0x03, 0x00, 0x7f,
+		   0x00, 0x07, 0x00, 0xf8, 0x00),
+	PHYREGS(0x08cc, 0x08c8, 0x08c4, 0x01d2, 0x01d2, 0x01d3),
+  },
+  {	.freq			= 5630,
+	RADIOREGS3(0x21, 0x01, 0x01, 0x02, 0x33, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00,
+		   0x70, 0x09, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+		   0x00, 0xf8, 0x00, 0x09, 0x00, 0x03, 0x00, 0x7f,
+		   0x00, 0x07, 0x00, 0xf8, 0x00),
+	PHYREGS(0x08d0, 0x08cc, 0x08c8, 0x01d1, 0x01d2, 0x01d2),
+  },
+  {	.freq			= 5640,
+	RADIOREGS3(0x1c, 0x01, 0x01, 0x02, 0x34, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00,
+		   0x70, 0x09, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+		   0x00, 0xf8, 0x00, 0x09, 0x00, 0x03, 0x00, 0x7f,
+		   0x00, 0x07, 0x00, 0xf8, 0x00),
+	PHYREGS(0x08d4, 0x08d0, 0x08cc, 0x01d0, 0x01d1, 0x01d2),
+  },
+  {	.freq			= 5650,
+	RADIOREGS3(0x1c, 0x01, 0x01, 0x02, 0x35, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00,
+		   0x70, 0x08, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+		   0x00, 0xf8, 0x00, 0x08, 0x00, 0x03, 0x00, 0x7f,
+		   0x00, 0x07, 0x00, 0xf8, 0x00),
+	PHYREGS(0x08d8, 0x08d4, 0x08d0, 0x01cf, 0x01d0, 0x01d1),
+  },
+  {	.freq			= 5660,
+	RADIOREGS3(0x16, 0x01, 0x01, 0x02, 0x36, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00,
+		   0x70, 0x08, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+		   0x00, 0xf6, 0x00, 0x08, 0x00, 0x03, 0x00, 0x7f,
+		   0x00, 0x07, 0x00, 0xf6, 0x00),
+	PHYREGS(0x08dc, 0x08d8, 0x08d4, 0x01ce, 0x01cf, 0x01d0),
+  },
+  {	.freq			= 5670,
+	RADIOREGS3(0x16, 0x01, 0x01, 0x02, 0x37, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00,
+		   0x70, 0x08, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+		   0x00, 0xf6, 0x00, 0x08, 0x00, 0x03, 0x00, 0x7f,
+		   0x00, 0x07, 0x00, 0xf6, 0x00),
+	PHYREGS(0x08e0, 0x08dc, 0x08d8, 0x01ce, 0x01ce, 0x01cf),
+  },
+  {	.freq			= 5680,
+	RADIOREGS3(0x10, 0x01, 0x01, 0x02, 0x38, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00,
+		   0x70, 0x08, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+		   0x00, 0xf6, 0x00, 0x08, 0x00, 0x03, 0x00, 0x7f,
+		   0x00, 0x07, 0x00, 0xf6, 0x00),
+	PHYREGS(0x08e4, 0x08e0, 0x08dc, 0x01cd, 0x01ce, 0x01ce),
+  },
+  {	.freq			= 5690,
+	RADIOREGS3(0x10, 0x01, 0x01, 0x02, 0x39, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00,
+		   0x70, 0x07, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+		   0x00, 0xf6, 0x00, 0x07, 0x00, 0x03, 0x00, 0x7f,
+		   0x00, 0x07, 0x00, 0xf6, 0x00),
+	PHYREGS(0x08e8, 0x08e4, 0x08e0, 0x01cc, 0x01cd, 0x01ce),
+  },
+  {	.freq			= 5700,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3a, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00,
+		   0x40, 0x07, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+		   0x00, 0xf6, 0x00, 0x07, 0x00, 0x02, 0x00, 0x7f,
+		   0x00, 0x06, 0x00, 0xf6, 0x00),
+	PHYREGS(0x08ec, 0x08e8, 0x08e4, 0x01cb, 0x01cc, 0x01cd),
+  },
+  {	.freq			= 5710,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3b, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00,
+		   0x40, 0x07, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+		   0x00, 0xf4, 0x00, 0x07, 0x00, 0x02, 0x00, 0x7f,
+		   0x00, 0x06, 0x00, 0xf4, 0x00),
+	PHYREGS(0x08f0, 0x08ec, 0x08e8, 0x01ca, 0x01cb, 0x01cc),
+  },
+  {	.freq			= 5720,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3c, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00,
+		   0x40, 0x07, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+		   0x00, 0xf4, 0x00, 0x07, 0x00, 0x02, 0x00, 0x7f,
+		   0x00, 0x06, 0x00, 0xf4, 0x00),
+	PHYREGS(0x08f4, 0x08f0, 0x08ec, 0x01c9, 0x01ca, 0x01cb),
+  },
+  {	.freq			= 5725,
+	RADIOREGS3(0x03, 0x01, 0x02, 0x04, 0x79, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00,
+		   0x40, 0x06, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+		   0x00, 0xf4, 0x00, 0x06, 0x00, 0x02, 0x00, 0x7f,
+		   0x00, 0x06, 0x00, 0xf4, 0x00),
+	PHYREGS(0x08f6, 0x08f2, 0x08ee, 0x01c9, 0x01ca, 0x01cb),
+  },
+  {	.freq			= 5730,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3d, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00,
+		   0x40, 0x06, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+		   0x00, 0xf4, 0x00, 0x06, 0x00, 0x02, 0x00, 0x7f,
+		   0x00, 0x06, 0x00, 0xf4, 0x00),
+	PHYREGS(0x08f8, 0x08f4, 0x08f0, 0x01c9, 0x01c9, 0x01ca),
+  },
+  {	.freq			= 5735,
+	RADIOREGS3(0x03, 0x01, 0x02, 0x04, 0x7b, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00,
+		   0x40, 0x06, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+		   0x00, 0xf4, 0x00, 0x06, 0x00, 0x02, 0x00, 0x7f,
+		   0x00, 0x06, 0x00, 0xf4, 0x00),
+	PHYREGS(0x08fa, 0x08f6, 0x08f2, 0x01c8, 0x01c9, 0x01ca),
+  },
+  {	.freq			= 5740,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3e, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00,
+		   0x40, 0x06, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+		   0x00, 0xf4, 0x00, 0x06, 0x00, 0x02, 0x00, 0x7f,
+		   0x00, 0x06, 0x00, 0xf4, 0x00),
+	PHYREGS(0x08fc, 0x08f8, 0x08f4, 0x01c8, 0x01c9, 0x01c9),
+  },
+  {	.freq			= 5745,
+	RADIOREGS3(0xfe, 0x00, 0x02, 0x04, 0x7d, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00,
+		   0x40, 0x06, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+		   0x00, 0xf4, 0x00, 0x06, 0x00, 0x02, 0x00, 0x7f,
+		   0x00, 0x06, 0x00, 0xf4, 0x00),
+	PHYREGS(0x08fe, 0x08fa, 0x08f6, 0x01c8, 0x01c8, 0x01c9),
+  },
+  {	.freq			= 5750,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3f, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00,
+		   0x40, 0x06, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+		   0x00, 0xf4, 0x00, 0x06, 0x00, 0x02, 0x00, 0x7f,
+		   0x00, 0x06, 0x00, 0xf4, 0x00),
+	PHYREGS(0x0900, 0x08fc, 0x08f8, 0x01c7, 0x01c8, 0x01c9),
+  },
+  {	.freq			= 5755,
+	RADIOREGS3(0xfe, 0x00, 0x02, 0x04, 0x7f, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00,
+		   0x40, 0x05, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+		   0x00, 0xf4, 0x00, 0x05, 0x00, 0x02, 0x00, 0x7f,
+		   0x00, 0x06, 0x00, 0xf4, 0x00),
+	PHYREGS(0x0902, 0x08fe, 0x08fa, 0x01c7, 0x01c8, 0x01c8),
+  },
+  {	.freq			= 5760,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x40, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00,
+		   0x40, 0x05, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+		   0x00, 0xf4, 0x00, 0x05, 0x00, 0x02, 0x00, 0x7f,
+		   0x00, 0x06, 0x00, 0xf4, 0x00),
+	PHYREGS(0x0904, 0x0900, 0x08fc, 0x01c6, 0x01c7, 0x01c8),
+  },
+  {	.freq			= 5765,
+	RADIOREGS3(0xf8, 0x00, 0x02, 0x04, 0x81, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00,
+		   0x40, 0x05, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+		   0x00, 0xf4, 0x00, 0x05, 0x00, 0x02, 0x00, 0x7f,
+		   0x00, 0x06, 0x00, 0xf4, 0x00),
+	PHYREGS(0x0906, 0x0902, 0x08fe, 0x01c6, 0x01c7, 0x01c8),
+  },
+  {	.freq			= 5770,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x41, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00,
+		   0x40, 0x05, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+		   0x00, 0xf4, 0x00, 0x05, 0x00, 0x02, 0x00, 0x7f,
+		   0x00, 0x06, 0x00, 0xf4, 0x00),
+	PHYREGS(0x0908, 0x0904, 0x0900, 0x01c6, 0x01c6, 0x01c7),
+  },
+  {	.freq			= 5775,
+	RADIOREGS3(0xf8, 0x00, 0x02, 0x04, 0x83, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00,
+		   0x40, 0x05, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+		   0x00, 0xf4, 0x00, 0x05, 0x00, 0x02, 0x00, 0x7f,
+		   0x00, 0x06, 0x00, 0xf4, 0x00),
+	PHYREGS(0x090a, 0x0906, 0x0902, 0x01c5, 0x01c6, 0x01c7),
+  },
+  {	.freq			= 5780,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x42, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00,
+		   0x40, 0x05, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+		   0x00, 0xf4, 0x00, 0x05, 0x00, 0x02, 0x00, 0x7f,
+		   0x00, 0x06, 0x00, 0xf4, 0x00),
+	PHYREGS(0x090c, 0x0908, 0x0904, 0x01c5, 0x01c6, 0x01c6),
+  },
+  {	.freq			= 5785,
+	RADIOREGS3(0xf2, 0x00, 0x02, 0x04, 0x85, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00,
+		   0x40, 0x04, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+		   0x00, 0xf4, 0x00, 0x04, 0x00, 0x02, 0x00, 0x7f,
+		   0x00, 0x06, 0x00, 0xf4, 0x00),
+	PHYREGS(0x090e, 0x090a, 0x0906, 0x01c4, 0x01c5, 0x01c6),
+  },
+  {	.freq			= 5790,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x43, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00,
+		   0x40, 0x04, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+		   0x00, 0xf4, 0x00, 0x04, 0x00, 0x02, 0x00, 0x7f,
+		   0x00, 0x06, 0x00, 0xf4, 0x00),
+	PHYREGS(0x0910, 0x090c, 0x0908, 0x01c4, 0x01c5, 0x01c6),
+  },
+  {	.freq			= 5795,
+	RADIOREGS3(0xf2, 0x00, 0x02, 0x04, 0x87, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00,
+		   0x40, 0x04, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+		   0x00, 0xf4, 0x00, 0x04, 0x00, 0x02, 0x00, 0x7f,
+		   0x00, 0x06, 0x00, 0xf4, 0x00),
+	PHYREGS(0x0912, 0x090e, 0x090a, 0x01c4, 0x01c4, 0x01c5),
+  },
+  {	.freq			= 5800,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x44, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00,
+		   0x20, 0x04, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
+		   0x00, 0xf4, 0x00, 0x04, 0x00, 0x00, 0x00, 0x7f,
+		   0x00, 0x06, 0x00, 0xf4, 0x00),
+	PHYREGS(0x0914, 0x0910, 0x090c, 0x01c3, 0x01c4, 0x01c5),
+  },
+  {	.freq			= 5805,
+	RADIOREGS3(0xed, 0x00, 0x02, 0x04, 0x89, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00,
+		   0x20, 0x04, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
+		   0x00, 0xf4, 0x00, 0x04, 0x00, 0x00, 0x00, 0x7f,
+		   0x00, 0x06, 0x00, 0xf4, 0x00),
+	PHYREGS(0x0916, 0x0912, 0x090e, 0x01c3, 0x01c4, 0x01c4),
+  },
+  {	.freq			= 5810,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x45, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00,
+		   0x20, 0x04, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
+		   0x00, 0xf4, 0x00, 0x04, 0x00, 0x00, 0x00, 0x7f,
+		   0x00, 0x06, 0x00, 0xf4, 0x00),
+	PHYREGS(0x0918, 0x0914, 0x0910, 0x01c2, 0x01c3, 0x01c4),
+  },
+  {	.freq			= 5815,
+	RADIOREGS3(0xed, 0x00, 0x02, 0x04, 0x8b, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00,
+		   0x20, 0x04, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
+		   0x00, 0xf4, 0x00, 0x04, 0x00, 0x00, 0x00, 0x7f,
+		   0x00, 0x06, 0x00, 0xf4, 0x00),
+	PHYREGS(0x091a, 0x0916, 0x0912, 0x01c2, 0x01c3, 0x01c4),
+  },
+  {	.freq			= 5820,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x46, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00,
+		   0x20, 0x03, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
+		   0x00, 0xf4, 0x00, 0x03, 0x00, 0x00, 0x00, 0x7f,
+		   0x00, 0x06, 0x00, 0xf4, 0x00),
+	PHYREGS(0x091c, 0x0918, 0x0914, 0x01c2, 0x01c2, 0x01c3),
+  },
+  {	.freq			= 5825,
+	RADIOREGS3(0xed, 0x00, 0x02, 0x04, 0x8d, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00,
+		   0x20, 0x03, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
+		   0x00, 0xf4, 0x00, 0x03, 0x00, 0x00, 0x00, 0x7f,
+		   0x00, 0x06, 0x00, 0xf4, 0x00),
+	PHYREGS(0x091e, 0x091a, 0x0916, 0x01c1, 0x01c2, 0x01c3),
+  },
+  {	.freq			= 5830,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x47, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00,
+		   0x20, 0x03, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
+		   0x00, 0xf4, 0x00, 0x03, 0x00, 0x00, 0x00, 0x7f,
+		   0x00, 0x06, 0x00, 0xf4, 0x00),
+	PHYREGS(0x0920, 0x091c, 0x0918, 0x01c1, 0x01c2, 0x01c2),
+  },
+  {	.freq			= 5840,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x48, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00,
+		   0x20, 0x03, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
+		   0x00, 0xf4, 0x00, 0x03, 0x00, 0x00, 0x00, 0x7f,
+		   0x00, 0x06, 0x00, 0xf4, 0x00),
+	PHYREGS(0x0924, 0x0920, 0x091c, 0x01c0, 0x01c1, 0x01c2),
+  },
+  {	.freq			= 5850,
+	RADIOREGS3(0xe0, 0x00, 0x01, 0x02, 0x49, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00,
+		   0x20, 0x03, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
+		   0x00, 0xf4, 0x00, 0x03, 0x00, 0x00, 0x00, 0x7f,
+		   0x00, 0x06, 0x00, 0xf4, 0x00),
+	PHYREGS(0x0928, 0x0924, 0x0920, 0x01bf, 0x01c0, 0x01c1),
+  },
+  {	.freq			= 5860,
+	RADIOREGS3(0xde, 0x00, 0x01, 0x02, 0x4a, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00,
+		   0x20, 0x03, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
+		   0x00, 0xf2, 0x00, 0x03, 0x00, 0x00, 0x00, 0x7f,
+		   0x00, 0x06, 0x00, 0xf2, 0x00),
+	PHYREGS(0x092c, 0x0928, 0x0924, 0x01bf, 0x01bf, 0x01c0),
+  },
+  {	.freq			= 5870,
+	RADIOREGS3(0xdb, 0x00, 0x01, 0x02, 0x4b, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00,
+		   0x20, 0x02, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
+		   0x00, 0xf2, 0x00, 0x02, 0x00, 0x00, 0x00, 0x7f,
+		   0x00, 0x06, 0x00, 0xf2, 0x00),
+	PHYREGS(0x0930, 0x092c, 0x0928, 0x01be, 0x01bf, 0x01bf),
+  },
+  {	.freq			= 5880,
+	RADIOREGS3(0xd8, 0x00, 0x01, 0x02, 0x4c, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00,
+		   0x20, 0x02, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
+		   0x00, 0xf2, 0x00, 0x02, 0x00, 0x00, 0x00, 0x7f,
+		   0x00, 0x06, 0x00, 0xf2, 0x00),
+	PHYREGS(0x0934, 0x0930, 0x092c, 0x01bd, 0x01be, 0x01bf),
+  },
+  {	.freq			= 5890,
+	RADIOREGS3(0xd6, 0x00, 0x01, 0x02, 0x4d, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00,
+		   0x20, 0x02, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
+		   0x00, 0xf2, 0x00, 0x02, 0x00, 0x00, 0x00, 0x7f,
+		   0x00, 0x06, 0x00, 0xf2, 0x00),
+	PHYREGS(0x0938, 0x0934, 0x0930, 0x01bc, 0x01bd, 0x01be),
+  },
+  {	.freq			= 5900,
+	RADIOREGS3(0xd3, 0x00, 0x01, 0x02, 0x4e, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x87, 0x03, 0x00,
+		   0x00, 0x02, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x05,
+		   0x00, 0xf2, 0x00, 0x02, 0x00, 0x00, 0x00, 0x7f,
+		   0x00, 0x05, 0x00, 0xf2, 0x00),
+	PHYREGS(0x093c, 0x0938, 0x0934, 0x01bc, 0x01bc, 0x01bd),
+  },
+  {	.freq			= 5910,
+	RADIOREGS3(0xd6, 0x00, 0x01, 0x02, 0x4f, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x87, 0x03, 0x00,
+		   0x00, 0x01, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x05,
+		   0x00, 0xf2, 0x00, 0x01, 0x00, 0x00, 0x00, 0x7f,
+		   0x00, 0x05, 0x00, 0xf2, 0x00),
+	PHYREGS(0x0940, 0x093c, 0x0938, 0x01bb, 0x01bc, 0x01bc),
+  },
+  {	.freq			= 2412,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x6c, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x04, 0x04, 0x04, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0xff, 0x00, 0x05, 0x00, 0x70, 0x00,
+		   0x0f, 0x00, 0x0f, 0x00, 0xff, 0x00, 0x05, 0x00,
+		   0x70, 0x00, 0x0f, 0x00, 0x0f),
+	PHYREGS(0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443),
+  },
+  {	.freq			= 2417,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x71, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0xff, 0x00, 0x05, 0x00, 0x70, 0x00,
+		   0x0f, 0x00, 0x0f, 0x00, 0xff, 0x00, 0x05, 0x00,
+		   0x70, 0x00, 0x0f, 0x00, 0x0f),
+	PHYREGS(0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441),
+  },
+  {	.freq			= 2422,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x76, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0xff, 0x00, 0x05, 0x00, 0x70, 0x00,
+		   0x0f, 0x00, 0x0f, 0x00, 0xff, 0x00, 0x05, 0x00,
+		   0x70, 0x00, 0x0f, 0x00, 0x0f),
+	PHYREGS(0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f),
+  },
+  {	.freq			= 2427,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x7b, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0xfd, 0x00, 0x05, 0x00, 0x70, 0x00,
+		   0x0f, 0x00, 0x0f, 0x00, 0xfd, 0x00, 0x05, 0x00,
+		   0x70, 0x00, 0x0f, 0x00, 0x0f),
+	PHYREGS(0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d),
+  },
+  {	.freq			= 2432,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x80, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0xfb, 0x00, 0x05, 0x00, 0x70, 0x00,
+		   0x0f, 0x00, 0x0f, 0x00, 0xfb, 0x00, 0x05, 0x00,
+		   0x70, 0x00, 0x0f, 0x00, 0x0f),
+	PHYREGS(0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a),
+  },
+  {	.freq			= 2437,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x85, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0xfa, 0x00, 0x05, 0x00, 0x70, 0x00,
+		   0x0f, 0x00, 0x0f, 0x00, 0xfa, 0x00, 0x05, 0x00,
+		   0x70, 0x00, 0x0f, 0x00, 0x0f),
+	PHYREGS(0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438),
+  },
+  {	.freq			= 2442,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x8a, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0xf8, 0x00, 0x05, 0x00, 0x70, 0x00,
+		   0x0f, 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x05, 0x00,
+		   0x70, 0x00, 0x0f, 0x00, 0x0f),
+	PHYREGS(0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436),
+  },
+  {	.freq			= 2447,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x8f, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0xf7, 0x00, 0x05, 0x00, 0x70, 0x00,
+		   0x0f, 0x00, 0x0f, 0x00, 0xf7, 0x00, 0x05, 0x00,
+		   0x70, 0x00, 0x0f, 0x00, 0x0f),
+	PHYREGS(0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434),
+  },
+  {	.freq			= 2452,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x94, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0xf6, 0x00, 0x05, 0x00, 0x70, 0x00,
+		   0x0f, 0x00, 0x0f, 0x00, 0xf6, 0x00, 0x05, 0x00,
+		   0x70, 0x00, 0x0f, 0x00, 0x0f),
+	PHYREGS(0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431),
+  },
+  {	.freq			= 2457,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x99, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0xf5, 0x00, 0x05, 0x00, 0x70, 0x00,
+		   0x0f, 0x00, 0x0d, 0x00, 0xf5, 0x00, 0x05, 0x00,
+		   0x70, 0x00, 0x0f, 0x00, 0x0d),
+	PHYREGS(0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f),
+  },
+  {	.freq			= 2462,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x9e, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0xf4, 0x00, 0x05, 0x00, 0x70, 0x00,
+		   0x0f, 0x00, 0x0d, 0x00, 0xf4, 0x00, 0x05, 0x00,
+		   0x70, 0x00, 0x0f, 0x00, 0x0d),
+	PHYREGS(0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d),
+  },
+  {	.freq			= 2467,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0xa3, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0xf3, 0x00, 0x05, 0x00, 0x70, 0x00,
+		   0x0f, 0x00, 0x0d, 0x00, 0xf3, 0x00, 0x05, 0x00,
+		   0x70, 0x00, 0x0f, 0x00, 0x0d),
+	PHYREGS(0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b),
+  },
+  {	.freq			= 2472,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0xa8, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0xf2, 0x00, 0x05, 0x00, 0x70, 0x00,
+		   0x0f, 0x00, 0x0d, 0x00, 0xf2, 0x00, 0x05, 0x00,
+		   0x70, 0x00, 0x0f, 0x00, 0x0d),
+	PHYREGS(0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429),
+  },
+  {	.freq			= 2484,
+	RADIOREGS3(0xff, 0x01, 0x03, 0x09, 0xb4, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0xf0, 0x00, 0x05, 0x00, 0x70, 0x00,
+		   0x0f, 0x00, 0x0d, 0x00, 0xf0, 0x00, 0x05, 0x00,
+		   0x70, 0x00, 0x0f, 0x00, 0x0d),
+	PHYREGS(0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424),
+  },
+};
+
+static const struct b43_nphy_channeltab_entry_rev3 b43_nphy_channeltab_rev4[] = {
+  {	.freq			= 4920,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xff, 0x00),
+	PHYREGS(0x07b4, 0x07b0, 0x07ac, 0x0214, 0x0215, 0x0216),
+  },
+  {	.freq			= 4930,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xed, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xff, 0x00),
+	PHYREGS(0x07b8, 0x07b4, 0x07b0, 0x0213, 0x0214, 0x0215),
+  },
+  {	.freq			= 4940,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xee, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xff, 0x00),
+	PHYREGS(0x07bc, 0x07b8, 0x07b4, 0x0212, 0x0213, 0x0214),
+  },
+  {	.freq			= 4950,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xef, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xff, 0x00),
+	PHYREGS(0x07c0, 0x07bc, 0x07b8, 0x0211, 0x0212, 0x0213),
+  },
+  {	.freq			= 4960,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf0, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xff, 0x00),
+	PHYREGS(0x07c4, 0x07c0, 0x07bc, 0x020f, 0x0211, 0x0212),
+  },
+  {	.freq			= 4970,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf1, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xff, 0x00),
+	PHYREGS(0x07c8, 0x07c4, 0x07c0, 0x020e, 0x020f, 0x0211),
+  },
+  {	.freq			= 4980,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf2, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xff, 0x00),
+	PHYREGS(0x07cc, 0x07c8, 0x07c4, 0x020d, 0x020e, 0x020f),
+  },
+  {	.freq			= 4990,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf3, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xff, 0x00),
+	PHYREGS(0x07d0, 0x07cc, 0x07c8, 0x020c, 0x020d, 0x020e),
+  },
+  {	.freq			= 5000,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf4, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xff, 0x00),
+	PHYREGS(0x07d4, 0x07d0, 0x07cc, 0x020b, 0x020c, 0x020d),
+  },
+  {	.freq			= 5010,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf5, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xff, 0x00),
+	PHYREGS(0x07d8, 0x07d4, 0x07d0, 0x020a, 0x020b, 0x020c),
+  },
+  {	.freq			= 5020,
+	RADIOREGS3(0xf7, 0x01, 0x01, 0x01, 0xf6, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xff, 0x00),
+	PHYREGS(0x07dc, 0x07d8, 0x07d4, 0x0209, 0x020a, 0x020b),
+  },
+  {	.freq			= 5030,
+	RADIOREGS3(0xf7, 0x01, 0x01, 0x01, 0xf7, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xff, 0x00),
+	PHYREGS(0x07e0, 0x07dc, 0x07d8, 0x0208, 0x0209, 0x020a),
+  },
+  {	.freq			= 5040,
+	RADIOREGS3(0xef, 0x01, 0x01, 0x01, 0xf8, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xff, 0x00),
+	PHYREGS(0x07e4, 0x07e0, 0x07dc, 0x0207, 0x0208, 0x0209),
+  },
+  {	.freq			= 5050,
+	RADIOREGS3(0xef, 0x01, 0x01, 0x01, 0xf9, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xff, 0x00),
+	PHYREGS(0x07e8, 0x07e4, 0x07e0, 0x0206, 0x0207, 0x0208),
+  },
+  {	.freq			= 5060,
+	RADIOREGS3(0xe6, 0x01, 0x01, 0x01, 0xfa, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xff, 0x00),
+	PHYREGS(0x07ec, 0x07e8, 0x07e4, 0x0205, 0x0206, 0x0207),
+  },
+  {	.freq			= 5070,
+	RADIOREGS3(0xe6, 0x01, 0x01, 0x01, 0xfb, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xff, 0x00),
+	PHYREGS(0x07f0, 0x07ec, 0x07e8, 0x0204, 0x0205, 0x0206),
+  },
+  {	.freq			= 5080,
+	RADIOREGS3(0xde, 0x01, 0x01, 0x01, 0xfc, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xff, 0x00),
+	PHYREGS(0x07f4, 0x07f0, 0x07ec, 0x0203, 0x0204, 0x0205),
+  },
+  {	.freq			= 5090,
+	RADIOREGS3(0xde, 0x01, 0x01, 0x01, 0xfd, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xff, 0x00),
+	PHYREGS(0x07f8, 0x07f4, 0x07f0, 0x0202, 0x0203, 0x0204),
+  },
+  {	.freq			= 5100,
+	RADIOREGS3(0xd6, 0x01, 0x01, 0x01, 0xfe, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xfe, 0x00, 0xff, 0x00, 0x0c, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xfe, 0x00),
+	PHYREGS(0x07fc, 0x07f8, 0x07f4, 0x0201, 0x0202, 0x0203),
+  },
+  {	.freq			= 5110,
+	RADIOREGS3(0xd6, 0x01, 0x01, 0x01, 0xff, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xfe, 0x00, 0xff, 0x00, 0x0c, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xfe, 0x00),
+	PHYREGS(0x0800, 0x07fc, 0x07f8, 0x0200, 0x0201, 0x0202),
+  },
+  {	.freq			= 5120,
+	RADIOREGS3(0xce, 0x01, 0x01, 0x02, 0x00, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xfe, 0x00, 0xff, 0x00, 0x0c, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xfe, 0x00),
+	PHYREGS(0x0804, 0x0800, 0x07fc, 0x01ff, 0x0200, 0x0201),
+  },
+  {	.freq			= 5130,
+	RADIOREGS3(0xce, 0x01, 0x01, 0x02, 0x01, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xfe, 0x00, 0xff, 0x00, 0x0c, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xfe, 0x00),
+	PHYREGS(0x0808, 0x0804, 0x0800, 0x01fe, 0x01ff, 0x0200),
+  },
+  {	.freq			= 5140,
+	RADIOREGS3(0xc6, 0x01, 0x01, 0x02, 0x02, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xfe, 0x00, 0xff, 0x00, 0x0c, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xfe, 0x00),
+	PHYREGS(0x080c, 0x0808, 0x0804, 0x01fd, 0x01fe, 0x01ff),
+  },
+  {	.freq			= 5160,
+	RADIOREGS3(0xbe, 0x01, 0x01, 0x02, 0x04, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xfe, 0x00, 0xff, 0x00, 0x0c, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xfe, 0x00),
+	PHYREGS(0x0814, 0x0810, 0x080c, 0x01fb, 0x01fc, 0x01fd),
+  },
+  {	.freq			= 5170,
+	RADIOREGS3(0xbe, 0x01, 0x01, 0x02, 0x05, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xfe, 0x00, 0xff, 0x00, 0x0c, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xfe, 0x00),
+	PHYREGS(0x0818, 0x0814, 0x0810, 0x01fa, 0x01fb, 0x01fc),
+  },
+  {	.freq			= 5180,
+	RADIOREGS3(0xb6, 0x01, 0x01, 0x02, 0x06, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xef, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xfe, 0x00, 0xef, 0x00, 0x0c, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xfe, 0x00),
+	PHYREGS(0x081c, 0x0818, 0x0814, 0x01f9, 0x01fa, 0x01fb),
+  },
+  {	.freq			= 5190,
+	RADIOREGS3(0xb6, 0x01, 0x01, 0x02, 0x07, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xef, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xfe, 0x00, 0xef, 0x00, 0x0c, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xfe, 0x00),
+	PHYREGS(0x0820, 0x081c, 0x0818, 0x01f8, 0x01f9, 0x01fa),
+  },
+  {	.freq			= 5200,
+	RADIOREGS3(0xaf, 0x01, 0x01, 0x02, 0x08, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xef, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xfc, 0x00, 0xef, 0x00, 0x0a, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xfc, 0x00),
+	PHYREGS(0x0824, 0x0820, 0x081c, 0x01f7, 0x01f8, 0x01f9),
+  },
+  {	.freq			= 5210,
+	RADIOREGS3(0xaf, 0x01, 0x01, 0x02, 0x09, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xdf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xfc, 0x00, 0xdf, 0x00, 0x0a, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xfc, 0x00),
+	PHYREGS(0x0828, 0x0824, 0x0820, 0x01f6, 0x01f7, 0x01f8),
+  },
+  {	.freq			= 5220,
+	RADIOREGS3(0xa7, 0x01, 0x01, 0x02, 0x0a, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xdf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xfc, 0x00, 0xdf, 0x00, 0x0a, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xfc, 0x00),
+	PHYREGS(0x082c, 0x0828, 0x0824, 0x01f5, 0x01f6, 0x01f7),
+  },
+  {	.freq			= 5230,
+	RADIOREGS3(0xa7, 0x01, 0x01, 0x02, 0x0b, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xdf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xfc, 0x00, 0xdf, 0x00, 0x0a, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xfc, 0x00),
+	PHYREGS(0x0830, 0x082c, 0x0828, 0x01f4, 0x01f5, 0x01f6),
+  },
+  {	.freq			= 5240,
+	RADIOREGS3(0xa0, 0x01, 0x01, 0x02, 0x0c, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xcf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xfc, 0x00, 0xcf, 0x00, 0x0a, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xfc, 0x00),
+	PHYREGS(0x0834, 0x0830, 0x082c, 0x01f3, 0x01f4, 0x01f5),
+  },
+  {	.freq			= 5250,
+	RADIOREGS3(0xa0, 0x01, 0x01, 0x02, 0x0d, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xcf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xfc, 0x00, 0xcf, 0x00, 0x0a, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xfc, 0x00),
+	PHYREGS(0x0838, 0x0834, 0x0830, 0x01f2, 0x01f3, 0x01f4),
+  },
+  {	.freq			= 5260,
+	RADIOREGS3(0x98, 0x01, 0x01, 0x02, 0x0e, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xcf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xfc, 0x00, 0xcf, 0x00, 0x0a, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xfc, 0x00),
+	PHYREGS(0x083c, 0x0838, 0x0834, 0x01f1, 0x01f2, 0x01f3),
+  },
+  {	.freq			= 5270,
+	RADIOREGS3(0x98, 0x01, 0x01, 0x02, 0x0f, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00,
+		   0xff, 0xcf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xfc, 0x00, 0xcf, 0x00, 0x0a, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xfc, 0x00),
+	PHYREGS(0x0840, 0x083c, 0x0838, 0x01f0, 0x01f1, 0x01f2),
+  },
+  {	.freq			= 5280,
+	RADIOREGS3(0x91, 0x01, 0x01, 0x02, 0x10, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00,
+		   0xff, 0xbf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xfc, 0x00, 0xbf, 0x00, 0x0a, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xfc, 0x00),
+	PHYREGS(0x0844, 0x0840, 0x083c, 0x01f0, 0x01f0, 0x01f1),
+  },
+  {	.freq			= 5290,
+	RADIOREGS3(0x91, 0x01, 0x01, 0x02, 0x11, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00,
+		   0xff, 0xbf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xfc, 0x00, 0xbf, 0x00, 0x0a, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xfc, 0x00),
+	PHYREGS(0x0848, 0x0844, 0x0840, 0x01ef, 0x01f0, 0x01f0),
+  },
+  {	.freq			= 5300,
+	RADIOREGS3(0x8a, 0x01, 0x01, 0x02, 0x12, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00,
+		   0xff, 0xbf, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xfa, 0x00, 0xbf, 0x00, 0x08, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xfa, 0x00),
+	PHYREGS(0x084c, 0x0848, 0x0844, 0x01ee, 0x01ef, 0x01f0),
+  },
+  {	.freq			= 5310,
+	RADIOREGS3(0x8a, 0x01, 0x01, 0x02, 0x13, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00,
+		   0xff, 0xbf, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xfa, 0x00, 0xbf, 0x00, 0x08, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xfa, 0x00),
+	PHYREGS(0x0850, 0x084c, 0x0848, 0x01ed, 0x01ee, 0x01ef),
+  },
+  {	.freq			= 5320,
+	RADIOREGS3(0x83, 0x01, 0x01, 0x02, 0x14, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00,
+		   0xff, 0xbf, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xfa, 0x00, 0xbf, 0x00, 0x08, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xfa, 0x00),
+	PHYREGS(0x0854, 0x0850, 0x084c, 0x01ec, 0x01ed, 0x01ee),
+  },
+  {	.freq			= 5330,
+	RADIOREGS3(0x83, 0x01, 0x01, 0x02, 0x15, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00,
+		   0xff, 0xaf, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xfa, 0x00, 0xaf, 0x00, 0x08, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xfa, 0x00),
+	PHYREGS(0x0858, 0x0854, 0x0850, 0x01eb, 0x01ec, 0x01ed),
+  },
+  {	.freq			= 5340,
+	RADIOREGS3(0x7c, 0x01, 0x01, 0x02, 0x16, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00,
+		   0xff, 0xaf, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xfa, 0x00, 0xaf, 0x00, 0x08, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xfa, 0x00),
+	PHYREGS(0x085c, 0x0858, 0x0854, 0x01ea, 0x01eb, 0x01ec),
+  },
+  {	.freq			= 5350,
+	RADIOREGS3(0x7c, 0x01, 0x01, 0x02, 0x17, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00,
+		   0xff, 0x9f, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xfa, 0x00, 0x9f, 0x00, 0x08, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xfa, 0x00),
+	PHYREGS(0x0860, 0x085c, 0x0858, 0x01e9, 0x01ea, 0x01eb),
+  },
+  {	.freq			= 5360,
+	RADIOREGS3(0x75, 0x01, 0x01, 0x02, 0x18, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00,
+		   0xff, 0x9f, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xfa, 0x00, 0x9f, 0x00, 0x08, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xfa, 0x00),
+	PHYREGS(0x0864, 0x0860, 0x085c, 0x01e8, 0x01e9, 0x01ea),
+  },
+  {	.freq			= 5370,
+	RADIOREGS3(0x75, 0x01, 0x01, 0x02, 0x19, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00,
+		   0xff, 0x9f, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xfa, 0x00, 0x9f, 0x00, 0x08, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xfa, 0x00),
+	PHYREGS(0x0868, 0x0864, 0x0860, 0x01e7, 0x01e8, 0x01e9),
+  },
+  {	.freq			= 5380,
+	RADIOREGS3(0x6e, 0x01, 0x01, 0x02, 0x1a, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00,
+		   0xff, 0x9f, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xfa, 0x00, 0x9f, 0x00, 0x08, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xfa, 0x00),
+	PHYREGS(0x086c, 0x0868, 0x0864, 0x01e6, 0x01e7, 0x01e8),
+  },
+  {	.freq			= 5390,
+	RADIOREGS3(0x6e, 0x01, 0x01, 0x02, 0x1b, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00,
+		   0xff, 0x8f, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xfa, 0x00, 0x8f, 0x00, 0x08, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xfa, 0x00),
+	PHYREGS(0x0870, 0x086c, 0x0868, 0x01e5, 0x01e6, 0x01e7),
+  },
+  {	.freq			= 5400,
+	RADIOREGS3(0x67, 0x01, 0x01, 0x02, 0x1c, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00,
+		   0xc8, 0x8f, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xf8, 0x00, 0x8f, 0x00, 0x07, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xf8, 0x00),
+	PHYREGS(0x0874, 0x0870, 0x086c, 0x01e5, 0x01e5, 0x01e6),
+  },
+  {	.freq			= 5410,
+	RADIOREGS3(0x67, 0x01, 0x01, 0x02, 0x1d, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00,
+		   0xc8, 0x8f, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xf8, 0x00, 0x8f, 0x00, 0x07, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xf8, 0x00),
+	PHYREGS(0x0878, 0x0874, 0x0870, 0x01e4, 0x01e5, 0x01e5),
+  },
+  {	.freq			= 5420,
+	RADIOREGS3(0x61, 0x01, 0x01, 0x02, 0x1e, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00,
+		   0xc8, 0x8e, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xf8, 0x00, 0x8e, 0x00, 0x07, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xf8, 0x00),
+	PHYREGS(0x087c, 0x0878, 0x0874, 0x01e3, 0x01e4, 0x01e5),
+  },
+  {	.freq			= 5430,
+	RADIOREGS3(0x61, 0x01, 0x01, 0x02, 0x1f, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00,
+		   0xc8, 0x8e, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xf8, 0x00, 0x8e, 0x00, 0x07, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xf8, 0x00),
+	PHYREGS(0x0880, 0x087c, 0x0878, 0x01e2, 0x01e3, 0x01e4),
+  },
+  {	.freq			= 5440,
+	RADIOREGS3(0x5a, 0x01, 0x01, 0x02, 0x20, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00,
+		   0xc8, 0x7e, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xf8, 0x00, 0x7e, 0x00, 0x07, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xf8, 0x00),
+	PHYREGS(0x0884, 0x0880, 0x087c, 0x01e1, 0x01e2, 0x01e3),
+  },
+  {	.freq			= 5450,
+	RADIOREGS3(0x5a, 0x01, 0x01, 0x02, 0x21, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00,
+		   0xc8, 0x7d, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xf8, 0x00, 0x7d, 0x00, 0x07, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xf8, 0x00),
+	PHYREGS(0x0888, 0x0884, 0x0880, 0x01e0, 0x01e1, 0x01e2),
+  },
+  {	.freq			= 5460,
+	RADIOREGS3(0x53, 0x01, 0x01, 0x02, 0x22, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00,
+		   0xc8, 0x6d, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xf8, 0x00, 0x6d, 0x00, 0x07, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xf8, 0x00),
+	PHYREGS(0x088c, 0x0888, 0x0884, 0x01df, 0x01e0, 0x01e1),
+  },
+  {	.freq			= 5470,
+	RADIOREGS3(0x53, 0x01, 0x01, 0x02, 0x23, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00,
+		   0xc8, 0x6d, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xf8, 0x00, 0x6d, 0x00, 0x07, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xf8, 0x00),
+	PHYREGS(0x0890, 0x088c, 0x0888, 0x01de, 0x01df, 0x01e0),
+  },
+  {	.freq			= 5480,
+	RADIOREGS3(0x4d, 0x01, 0x01, 0x02, 0x24, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00,
+		   0xc8, 0x5d, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xf8, 0x00, 0x5d, 0x00, 0x07, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xf8, 0x00),
+	PHYREGS(0x0894, 0x0890, 0x088c, 0x01dd, 0x01de, 0x01df),
+  },
+  {	.freq			= 5490,
+	RADIOREGS3(0x4d, 0x01, 0x01, 0x02, 0x25, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00,
+		   0xc8, 0x5c, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xf8, 0x00, 0x5c, 0x00, 0x07, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xf8, 0x00),
+	PHYREGS(0x0898, 0x0894, 0x0890, 0x01dd, 0x01dd, 0x01de),
+  },
+  {	.freq			= 5500,
+	RADIOREGS3(0x47, 0x01, 0x01, 0x02, 0x26, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00,
+		   0x84, 0x5c, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d,
+		   0x00, 0xf6, 0x00, 0x5c, 0x00, 0x06, 0x00, 0x7f,
+		   0x00, 0x0d, 0x00, 0xf6, 0x00),
+	PHYREGS(0x089c, 0x0898, 0x0894, 0x01dc, 0x01dd, 0x01dd),
+  },
+  {	.freq			= 5510,
+	RADIOREGS3(0x47, 0x01, 0x01, 0x02, 0x27, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00,
+		   0x84, 0x4c, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d,
+		   0x00, 0xf6, 0x00, 0x4c, 0x00, 0x06, 0x00, 0x7f,
+		   0x00, 0x0d, 0x00, 0xf6, 0x00),
+	PHYREGS(0x08a0, 0x089c, 0x0898, 0x01db, 0x01dc, 0x01dd),
+  },
+  {	.freq			= 5520,
+	RADIOREGS3(0x40, 0x01, 0x01, 0x02, 0x28, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00,
+		   0x84, 0x4c, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d,
+		   0x00, 0xf6, 0x00, 0x4c, 0x00, 0x06, 0x00, 0x7f,
+		   0x00, 0x0d, 0x00, 0xf6, 0x00),
+	PHYREGS(0x08a4, 0x08a0, 0x089c, 0x01da, 0x01db, 0x01dc),
+  },
+  {	.freq			= 5530,
+	RADIOREGS3(0x40, 0x01, 0x01, 0x02, 0x29, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00,
+		   0x84, 0x3b, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d,
+		   0x00, 0xf6, 0x00, 0x3b, 0x00, 0x06, 0x00, 0x7f,
+		   0x00, 0x0d, 0x00, 0xf6, 0x00),
+	PHYREGS(0x08a8, 0x08a4, 0x08a0, 0x01d9, 0x01da, 0x01db),
+  },
+  {	.freq			= 5540,
+	RADIOREGS3(0x3a, 0x01, 0x01, 0x02, 0x2a, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00,
+		   0x84, 0x3b, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d,
+		   0x00, 0xf6, 0x00, 0x3b, 0x00, 0x06, 0x00, 0x7f,
+		   0x00, 0x0d, 0x00, 0xf6, 0x00),
+	PHYREGS(0x08ac, 0x08a8, 0x08a4, 0x01d8, 0x01d9, 0x01da),
+  },
+  {	.freq			= 5550,
+	RADIOREGS3(0x3a, 0x01, 0x01, 0x02, 0x2b, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00,
+		   0x84, 0x3b, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d,
+		   0x00, 0xf6, 0x00, 0x3b, 0x00, 0x06, 0x00, 0x7f,
+		   0x00, 0x0d, 0x00, 0xf6, 0x00),
+	PHYREGS(0x08b0, 0x08ac, 0x08a8, 0x01d7, 0x01d8, 0x01d9),
+  },
+  {	.freq			= 5560,
+	RADIOREGS3(0x34, 0x01, 0x01, 0x02, 0x2c, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00,
+		   0x84, 0x2b, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d,
+		   0x00, 0xf6, 0x00, 0x2b, 0x00, 0x06, 0x00, 0x7f,
+		   0x00, 0x0d, 0x00, 0xf6, 0x00),
+	PHYREGS(0x08b4, 0x08b0, 0x08ac, 0x01d7, 0x01d7, 0x01d8),
+  },
+  {	.freq			= 5570,
+	RADIOREGS3(0x34, 0x01, 0x01, 0x02, 0x2d, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00,
+		   0x84, 0x2a, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d,
+		   0x00, 0xf6, 0x00, 0x2a, 0x00, 0x06, 0x00, 0x7f,
+		   0x00, 0x0d, 0x00, 0xf6, 0x00),
+	PHYREGS(0x08b8, 0x08b4, 0x08b0, 0x01d6, 0x01d7, 0x01d7),
+  },
+  {	.freq			= 5580,
+	RADIOREGS3(0x2e, 0x01, 0x01, 0x02, 0x2e, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00,
+		   0x84, 0x1a, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d,
+		   0x00, 0xf6, 0x00, 0x1a, 0x00, 0x06, 0x00, 0x7f,
+		   0x00, 0x0d, 0x00, 0xf6, 0x00),
+	PHYREGS(0x08bc, 0x08b8, 0x08b4, 0x01d5, 0x01d6, 0x01d7),
+  },
+  {	.freq			= 5590,
+	RADIOREGS3(0x2e, 0x01, 0x01, 0x02, 0x2f, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00,
+		   0x84, 0x1a, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d,
+		   0x00, 0xf6, 0x00, 0x1a, 0x00, 0x06, 0x00, 0x7f,
+		   0x00, 0x0d, 0x00, 0xf6, 0x00),
+	PHYREGS(0x08c0, 0x08bc, 0x08b8, 0x01d4, 0x01d5, 0x01d6),
+  },
+  {	.freq			= 5600,
+	RADIOREGS3(0x28, 0x01, 0x01, 0x02, 0x30, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00,
+		   0x70, 0x1a, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b,
+		   0x00, 0xf4, 0x00, 0x1a, 0x00, 0x04, 0x00, 0x7f,
+		   0x00, 0x0b, 0x00, 0xf4, 0x00),
+	PHYREGS(0x08c4, 0x08c0, 0x08bc, 0x01d3, 0x01d4, 0x01d5),
+  },
+  {	.freq			= 5610,
+	RADIOREGS3(0x28, 0x01, 0x01, 0x02, 0x31, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00,
+		   0x70, 0x19, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b,
+		   0x00, 0xf4, 0x00, 0x19, 0x00, 0x04, 0x00, 0x7f,
+		   0x00, 0x0b, 0x00, 0xf4, 0x00),
+	PHYREGS(0x08c8, 0x08c4, 0x08c0, 0x01d2, 0x01d3, 0x01d4),
+  },
+  {	.freq			= 5620,
+	RADIOREGS3(0x21, 0x01, 0x01, 0x02, 0x32, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00,
+		   0x70, 0x19, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b,
+		   0x00, 0xf4, 0x00, 0x19, 0x00, 0x04, 0x00, 0x7f,
+		   0x00, 0x0b, 0x00, 0xf4, 0x00),
+	PHYREGS(0x08cc, 0x08c8, 0x08c4, 0x01d2, 0x01d2, 0x01d3),
+  },
+  {	.freq			= 5630,
+	RADIOREGS3(0x21, 0x01, 0x01, 0x02, 0x33, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00,
+		   0x70, 0x09, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b,
+		   0x00, 0xf4, 0x00, 0x09, 0x00, 0x04, 0x00, 0x7f,
+		   0x00, 0x0b, 0x00, 0xf4, 0x00),
+	PHYREGS(0x08d0, 0x08cc, 0x08c8, 0x01d1, 0x01d2, 0x01d2),
+  },
+  {	.freq			= 5640,
+	RADIOREGS3(0x1c, 0x01, 0x01, 0x02, 0x34, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00,
+		   0x70, 0x09, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b,
+		   0x00, 0xf4, 0x00, 0x09, 0x00, 0x04, 0x00, 0x7f,
+		   0x00, 0x0b, 0x00, 0xf4, 0x00),
+	PHYREGS(0x08d4, 0x08d0, 0x08cc, 0x01d0, 0x01d1, 0x01d2),
+  },
+  {	.freq			= 5650,
+	RADIOREGS3(0x1c, 0x01, 0x01, 0x02, 0x35, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00,
+		   0x70, 0x08, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b,
+		   0x00, 0xf4, 0x00, 0x08, 0x00, 0x04, 0x00, 0x7f,
+		   0x00, 0x0b, 0x00, 0xf4, 0x00),
+	PHYREGS(0x08d8, 0x08d4, 0x08d0, 0x01cf, 0x01d0, 0x01d1),
+  },
+  {	.freq			= 5660,
+	RADIOREGS3(0x16, 0x01, 0x01, 0x02, 0x36, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00,
+		   0x70, 0x08, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b,
+		   0x00, 0xf4, 0x00, 0x08, 0x00, 0x04, 0x00, 0x7f,
+		   0x00, 0x0b, 0x00, 0xf4, 0x00),
+	PHYREGS(0x08dc, 0x08d8, 0x08d4, 0x01ce, 0x01cf, 0x01d0),
+  },
+  {	.freq			= 5670,
+	RADIOREGS3(0x16, 0x01, 0x01, 0x02, 0x37, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00,
+		   0x70, 0x08, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b,
+		   0x00, 0xf4, 0x00, 0x08, 0x00, 0x04, 0x00, 0x7f,
+		   0x00, 0x0b, 0x00, 0xf4, 0x00),
+	PHYREGS(0x08e0, 0x08dc, 0x08d8, 0x01ce, 0x01ce, 0x01cf),
+  },
+  {	.freq			= 5680,
+	RADIOREGS3(0x10, 0x01, 0x01, 0x02, 0x38, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00,
+		   0x70, 0x08, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b,
+		   0x00, 0xf4, 0x00, 0x08, 0x00, 0x04, 0x00, 0x7f,
+		   0x00, 0x0b, 0x00, 0xf4, 0x00),
+	PHYREGS(0x08e4, 0x08e0, 0x08dc, 0x01cd, 0x01ce, 0x01ce),
+  },
+  {	.freq			= 5690,
+	RADIOREGS3(0x10, 0x01, 0x01, 0x02, 0x39, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00,
+		   0x70, 0x07, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b,
+		   0x00, 0xf4, 0x00, 0x07, 0x00, 0x04, 0x00, 0x7f,
+		   0x00, 0x0b, 0x00, 0xf4, 0x00),
+	PHYREGS(0x08e8, 0x08e4, 0x08e0, 0x01cc, 0x01cd, 0x01ce),
+  },
+  {	.freq			= 5700,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3a, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00,
+		   0x40, 0x07, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+		   0x00, 0xf2, 0x00, 0x07, 0x00, 0x03, 0x00, 0x7f,
+		   0x00, 0x0a, 0x00, 0xf2, 0x00),
+	PHYREGS(0x08ec, 0x08e8, 0x08e4, 0x01cb, 0x01cc, 0x01cd),
+  },
+  {	.freq			= 5710,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3b, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00,
+		   0x40, 0x07, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+		   0x00, 0xf2, 0x00, 0x07, 0x00, 0x03, 0x00, 0x7f,
+		   0x00, 0x0a, 0x00, 0xf2, 0x00),
+	PHYREGS(0x08f0, 0x08ec, 0x08e8, 0x01ca, 0x01cb, 0x01cc),
+  },
+  {	.freq			= 5720,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3c, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00,
+		   0x40, 0x07, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+		   0x00, 0xf2, 0x00, 0x07, 0x00, 0x03, 0x00, 0x7f,
+		   0x00, 0x0a, 0x00, 0xf2, 0x00),
+	PHYREGS(0x08f4, 0x08f0, 0x08ec, 0x01c9, 0x01ca, 0x01cb),
+  },
+  {	.freq			= 5725,
+	RADIOREGS3(0x03, 0x01, 0x02, 0x04, 0x79, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00,
+		   0x40, 0x06, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+		   0x00, 0xf2, 0x00, 0x06, 0x00, 0x03, 0x00, 0x7f,
+		   0x00, 0x0a, 0x00, 0xf2, 0x00),
+	PHYREGS(0x08f6, 0x08f2, 0x08ee, 0x01c9, 0x01ca, 0x01cb),
+  },
+  {	.freq			= 5730,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3d, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00,
+		   0x40, 0x06, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+		   0x00, 0xf2, 0x00, 0x06, 0x00, 0x03, 0x00, 0x7f,
+		   0x00, 0x0a, 0x00, 0xf2, 0x00),
+	PHYREGS(0x08f8, 0x08f4, 0x08f0, 0x01c9, 0x01c9, 0x01ca),
+  },
+  {	.freq			= 5735,
+	RADIOREGS3(0x03, 0x01, 0x02, 0x04, 0x7b, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00,
+		   0x40, 0x06, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+		   0x00, 0xf2, 0x00, 0x06, 0x00, 0x03, 0x00, 0x7f,
+		   0x00, 0x0a, 0x00, 0xf2, 0x00),
+	PHYREGS(0x08fa, 0x08f6, 0x08f2, 0x01c8, 0x01c9, 0x01ca),
+  },
+  {	.freq			= 5740,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3e, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00,
+		   0x40, 0x06, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+		   0x00, 0xf2, 0x00, 0x06, 0x00, 0x03, 0x00, 0x7f,
+		   0x00, 0x0a, 0x00, 0xf2, 0x00),
+	PHYREGS(0x08fc, 0x08f8, 0x08f4, 0x01c8, 0x01c9, 0x01c9),
+  },
+  {	.freq			= 5745,
+	RADIOREGS3(0xfe, 0x00, 0x02, 0x04, 0x7d, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00,
+		   0x40, 0x06, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+		   0x00, 0xf2, 0x00, 0x06, 0x00, 0x03, 0x00, 0x7f,
+		   0x00, 0x0a, 0x00, 0xf2, 0x00),
+	PHYREGS(0x08fe, 0x08fa, 0x08f6, 0x01c8, 0x01c8, 0x01c9),
+  },
+  {	.freq			= 5750,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3f, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00,
+		   0x40, 0x06, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+		   0x00, 0xf2, 0x00, 0x06, 0x00, 0x03, 0x00, 0x7f,
+		   0x00, 0x0a, 0x00, 0xf2, 0x00),
+	PHYREGS(0x0900, 0x08fc, 0x08f8, 0x01c7, 0x01c8, 0x01c9),
+  },
+  {	.freq			= 5755,
+	RADIOREGS3(0xfe, 0x00, 0x02, 0x04, 0x7f, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00,
+		   0x40, 0x05, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+		   0x00, 0xf2, 0x00, 0x05, 0x00, 0x03, 0x00, 0x7f,
+		   0x00, 0x0a, 0x00, 0xf2, 0x00),
+	PHYREGS(0x0902, 0x08fe, 0x08fa, 0x01c7, 0x01c8, 0x01c8),
+  },
+  {	.freq			= 5760,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x40, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00,
+		   0x40, 0x05, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+		   0x00, 0xf2, 0x00, 0x05, 0x00, 0x03, 0x00, 0x7f,
+		   0x00, 0x0a, 0x00, 0xf2, 0x00),
+	PHYREGS(0x0904, 0x0900, 0x08fc, 0x01c6, 0x01c7, 0x01c8),
+  },
+  {	.freq			= 5765,
+	RADIOREGS3(0xf8, 0x00, 0x02, 0x04, 0x81, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00,
+		   0x40, 0x05, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+		   0x00, 0xf2, 0x00, 0x05, 0x00, 0x03, 0x00, 0x7f,
+		   0x00, 0x0a, 0x00, 0xf2, 0x00),
+	PHYREGS(0x0906, 0x0902, 0x08fe, 0x01c6, 0x01c7, 0x01c8),
+  },
+  {	.freq			= 5770,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x41, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00,
+		   0x40, 0x05, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+		   0x00, 0xf2, 0x00, 0x05, 0x00, 0x03, 0x00, 0x7f,
+		   0x00, 0x0a, 0x00, 0xf2, 0x00),
+	PHYREGS(0x0908, 0x0904, 0x0900, 0x01c6, 0x01c6, 0x01c7),
+  },
+  {	.freq			= 5775,
+	RADIOREGS3(0xf8, 0x00, 0x02, 0x04, 0x83, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00,
+		   0x40, 0x05, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+		   0x00, 0xf2, 0x00, 0x05, 0x00, 0x03, 0x00, 0x7f,
+		   0x00, 0x0a, 0x00, 0xf2, 0x00),
+	PHYREGS(0x090a, 0x0906, 0x0902, 0x01c5, 0x01c6, 0x01c7),
+  },
+  {	.freq			= 5780,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x42, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00,
+		   0x40, 0x05, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+		   0x00, 0xf2, 0x00, 0x05, 0x00, 0x03, 0x00, 0x7f,
+		   0x00, 0x0a, 0x00, 0xf2, 0x00),
+	PHYREGS(0x090c, 0x0908, 0x0904, 0x01c5, 0x01c6, 0x01c6),
+  },
+  {	.freq			= 5785,
+	RADIOREGS3(0xf2, 0x00, 0x02, 0x04, 0x85, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00,
+		   0x40, 0x04, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+		   0x00, 0xf2, 0x00, 0x04, 0x00, 0x03, 0x00, 0x7f,
+		   0x00, 0x0a, 0x00, 0xf2, 0x00),
+	PHYREGS(0x090e, 0x090a, 0x0906, 0x01c4, 0x01c5, 0x01c6),
+  },
+  {	.freq			= 5790,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x43, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00,
+		   0x40, 0x04, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+		   0x00, 0xf2, 0x00, 0x04, 0x00, 0x03, 0x00, 0x7f,
+		   0x00, 0x0a, 0x00, 0xf2, 0x00),
+	PHYREGS(0x0910, 0x090c, 0x0908, 0x01c4, 0x01c5, 0x01c6),
+  },
+  {	.freq			= 5795,
+	RADIOREGS3(0xf2, 0x00, 0x02, 0x04, 0x87, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00,
+		   0x40, 0x04, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+		   0x00, 0xf2, 0x00, 0x04, 0x00, 0x03, 0x00, 0x7f,
+		   0x00, 0x0a, 0x00, 0xf2, 0x00),
+	PHYREGS(0x0912, 0x090e, 0x090a, 0x01c4, 0x01c4, 0x01c5),
+  },
+  {	.freq			= 5800,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x44, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00,
+		   0x20, 0x04, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
+		   0x00, 0xf0, 0x00, 0x04, 0x00, 0x02, 0x00, 0x7f,
+		   0x00, 0x09, 0x00, 0xf0, 0x00),
+	PHYREGS(0x0914, 0x0910, 0x090c, 0x01c3, 0x01c4, 0x01c5),
+  },
+  {	.freq			= 5805,
+	RADIOREGS3(0xed, 0x00, 0x02, 0x04, 0x89, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00,
+		   0x20, 0x04, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
+		   0x00, 0xf0, 0x00, 0x04, 0x00, 0x02, 0x00, 0x7f,
+		   0x00, 0x09, 0x00, 0xf0, 0x00),
+	PHYREGS(0x0916, 0x0912, 0x090e, 0x01c3, 0x01c4, 0x01c4),
+  },
+  {	.freq			= 5810,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x45, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00,
+		   0x20, 0x04, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
+		   0x00, 0xf0, 0x00, 0x04, 0x00, 0x02, 0x00, 0x7f,
+		   0x00, 0x09, 0x00, 0xf0, 0x00),
+	PHYREGS(0x0918, 0x0914, 0x0910, 0x01c2, 0x01c3, 0x01c4),
+  },
+  {	.freq			= 5815,
+	RADIOREGS3(0xed, 0x00, 0x02, 0x04, 0x8b, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00,
+		   0x20, 0x04, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
+		   0x00, 0xf0, 0x00, 0x04, 0x00, 0x02, 0x00, 0x7f,
+		   0x00, 0x09, 0x00, 0xf0, 0x00),
+	PHYREGS(0x091a, 0x0916, 0x0912, 0x01c2, 0x01c3, 0x01c4),
+  },
+  {	.freq			= 5820,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x46, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00,
+		   0x20, 0x03, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
+		   0x00, 0xf0, 0x00, 0x03, 0x00, 0x02, 0x00, 0x7f,
+		   0x00, 0x09, 0x00, 0xf0, 0x00),
+	PHYREGS(0x091c, 0x0918, 0x0914, 0x01c2, 0x01c2, 0x01c3),
+  },
+  {	.freq			= 5825,
+	RADIOREGS3(0xed, 0x00, 0x02, 0x04, 0x8d, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00,
+		   0x20, 0x03, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
+		   0x00, 0xf0, 0x00, 0x03, 0x00, 0x02, 0x00, 0x7f,
+		   0x00, 0x09, 0x00, 0xf0, 0x00),
+	PHYREGS(0x091e, 0x091a, 0x0916, 0x01c1, 0x01c2, 0x01c3),
+  },
+  {	.freq			= 5830,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x47, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00,
+		   0x20, 0x03, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
+		   0x00, 0xf0, 0x00, 0x03, 0x00, 0x02, 0x00, 0x7f,
+		   0x00, 0x09, 0x00, 0xf0, 0x00),
+	PHYREGS(0x0920, 0x091c, 0x0918, 0x01c1, 0x01c2, 0x01c2),
+  },
+  {	.freq			= 5840,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x48, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00,
+		   0x20, 0x03, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
+		   0x00, 0xf0, 0x00, 0x03, 0x00, 0x02, 0x00, 0x7f,
+		   0x00, 0x09, 0x00, 0xf0, 0x00),
+	PHYREGS(0x0924, 0x0920, 0x091c, 0x01c0, 0x01c1, 0x01c2),
+  },
+  {	.freq			= 5850,
+	RADIOREGS3(0xe0, 0x00, 0x01, 0x02, 0x49, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00,
+		   0x20, 0x03, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
+		   0x00, 0xf0, 0x00, 0x03, 0x00, 0x02, 0x00, 0x7f,
+		   0x00, 0x09, 0x00, 0xf0, 0x00),
+	PHYREGS(0x0928, 0x0924, 0x0920, 0x01bf, 0x01c0, 0x01c1),
+  },
+  {	.freq			= 5860,
+	RADIOREGS3(0xde, 0x00, 0x01, 0x02, 0x4a, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00,
+		   0x20, 0x03, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
+		   0x00, 0xf0, 0x00, 0x03, 0x00, 0x02, 0x00, 0x7f,
+		   0x00, 0x09, 0x00, 0xf0, 0x00),
+	PHYREGS(0x092c, 0x0928, 0x0924, 0x01bf, 0x01bf, 0x01c0),
+  },
+  {	.freq			= 5870,
+	RADIOREGS3(0xdb, 0x00, 0x01, 0x02, 0x4b, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00,
+		   0x20, 0x02, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
+		   0x00, 0xf0, 0x00, 0x02, 0x00, 0x02, 0x00, 0x7f,
+		   0x00, 0x09, 0x00, 0xf0, 0x00),
+	PHYREGS(0x0930, 0x092c, 0x0928, 0x01be, 0x01bf, 0x01bf),
+  },
+  {	.freq			= 5880,
+	RADIOREGS3(0xd8, 0x00, 0x01, 0x02, 0x4c, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00,
+		   0x20, 0x02, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
+		   0x00, 0xf0, 0x00, 0x02, 0x00, 0x02, 0x00, 0x7f,
+		   0x00, 0x09, 0x00, 0xf0, 0x00),
+	PHYREGS(0x0934, 0x0930, 0x092c, 0x01bd, 0x01be, 0x01bf),
+  },
+  {	.freq			= 5890,
+	RADIOREGS3(0xd6, 0x00, 0x01, 0x02, 0x4d, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00,
+		   0x20, 0x02, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
+		   0x00, 0xf0, 0x00, 0x02, 0x00, 0x02, 0x00, 0x7f,
+		   0x00, 0x09, 0x00, 0xf0, 0x00),
+	PHYREGS(0x0938, 0x0934, 0x0930, 0x01bc, 0x01bd, 0x01be),
+  },
+  {	.freq			= 5900,
+	RADIOREGS3(0xd3, 0x00, 0x01, 0x02, 0x4e, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x87, 0x03, 0x00,
+		   0x00, 0x02, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x07,
+		   0x00, 0xf0, 0x00, 0x02, 0x00, 0x00, 0x00, 0x7f,
+		   0x00, 0x07, 0x00, 0xf0, 0x00),
+	PHYREGS(0x093c, 0x0938, 0x0934, 0x01bc, 0x01bc, 0x01bd),
+  },
+  {	.freq			= 5910,
+	RADIOREGS3(0xd6, 0x00, 0x01, 0x02, 0x4f, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x87, 0x03, 0x00,
+		   0x00, 0x01, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x07,
+		   0x00, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x00, 0x7f,
+		   0x00, 0x07, 0x00, 0xf0, 0x00),
+	PHYREGS(0x0940, 0x093c, 0x0938, 0x01bb, 0x01bc, 0x01bc),
+  },
+  {	.freq			= 2412,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x6c, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x04, 0x04, 0x04, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0xff, 0x00, 0x04, 0x00, 0x70, 0x00,
+		   0x0f, 0x00, 0x0e, 0x00, 0xff, 0x00, 0x04, 0x00,
+		   0x70, 0x00, 0x0f, 0x00, 0x0e),
+	PHYREGS(0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443),
+  },
+  {	.freq			= 2417,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x71, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0xff, 0x00, 0x04, 0x00, 0x70, 0x00,
+		   0x0f, 0x00, 0x0e, 0x00, 0xff, 0x00, 0x04, 0x00,
+		   0x70, 0x00, 0x0f, 0x00, 0x0e),
+	PHYREGS(0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441),
+  },
+  {	.freq			= 2422,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x76, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0xff, 0x00, 0x04, 0x00, 0x70, 0x00,
+		   0x0f, 0x00, 0x0e, 0x00, 0xff, 0x00, 0x04, 0x00,
+		   0x70, 0x00, 0x0f, 0x00, 0x0e),
+	PHYREGS(0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f),
+  },
+  {	.freq			= 2427,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x7b, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0xfd, 0x00, 0x04, 0x00, 0x70, 0x00,
+		   0x0f, 0x00, 0x0e, 0x00, 0xfd, 0x00, 0x04, 0x00,
+		   0x70, 0x00, 0x0f, 0x00, 0x0e),
+	PHYREGS(0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d),
+  },
+  {	.freq			= 2432,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x80, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0xfb, 0x00, 0x04, 0x00, 0x70, 0x00,
+		   0x0f, 0x00, 0x0e, 0x00, 0xfb, 0x00, 0x04, 0x00,
+		   0x70, 0x00, 0x0f, 0x00, 0x0e),
+	PHYREGS(0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a),
+  },
+  {	.freq			= 2437,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x85, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0xfa, 0x00, 0x04, 0x00, 0x70, 0x00,
+		   0x0f, 0x00, 0x0e, 0x00, 0xfa, 0x00, 0x04, 0x00,
+		   0x70, 0x00, 0x0f, 0x00, 0x0e),
+	PHYREGS(0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438),
+  },
+  {	.freq			= 2442,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x8a, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0xf8, 0x00, 0x04, 0x00, 0x70, 0x00,
+		   0x0f, 0x00, 0x0e, 0x00, 0xf8, 0x00, 0x04, 0x00,
+		   0x70, 0x00, 0x0f, 0x00, 0x0e),
+	PHYREGS(0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436),
+  },
+  {	.freq			= 2447,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x8f, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0xf7, 0x00, 0x04, 0x00, 0x70, 0x00,
+		   0x0f, 0x00, 0x0e, 0x00, 0xf7, 0x00, 0x04, 0x00,
+		   0x70, 0x00, 0x0f, 0x00, 0x0e),
+	PHYREGS(0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434),
+  },
+  {	.freq			= 2452,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x94, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0xf6, 0x00, 0x04, 0x00, 0x70, 0x00,
+		   0x0f, 0x00, 0x0e, 0x00, 0xf6, 0x00, 0x04, 0x00,
+		   0x70, 0x00, 0x0f, 0x00, 0x0e),
+	PHYREGS(0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431),
+  },
+  {	.freq			= 2457,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x99, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0xf5, 0x00, 0x04, 0x00, 0x70, 0x00,
+		   0x0f, 0x00, 0x0e, 0x00, 0xf5, 0x00, 0x04, 0x00,
+		   0x70, 0x00, 0x0f, 0x00, 0x0e),
+	PHYREGS(0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f),
+  },
+  {	.freq			= 2462,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x9e, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0xf4, 0x00, 0x04, 0x00, 0x70, 0x00,
+		   0x0f, 0x00, 0x0e, 0x00, 0xf4, 0x00, 0x04, 0x00,
+		   0x70, 0x00, 0x0f, 0x00, 0x0e),
+	PHYREGS(0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d),
+  },
+  {	.freq			= 2467,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0xa3, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0xf3, 0x00, 0x04, 0x00, 0x70, 0x00,
+		   0x0f, 0x00, 0x0e, 0x00, 0xf3, 0x00, 0x04, 0x00,
+		   0x70, 0x00, 0x0f, 0x00, 0x0e),
+	PHYREGS(0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b),
+  },
+  {	.freq			= 2472,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0xa8, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0xf2, 0x00, 0x04, 0x00, 0x70, 0x00,
+		   0x0f, 0x00, 0x0e, 0x00, 0xf2, 0x00, 0x04, 0x00,
+		   0x70, 0x00, 0x0f, 0x00, 0x0e),
+	PHYREGS(0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429),
+  },
+  {	.freq			= 2484,
+	RADIOREGS3(0xff, 0x01, 0x03, 0x09, 0xb4, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0xf0, 0x00, 0x04, 0x00, 0x70, 0x00,
+		   0x0f, 0x00, 0x0e, 0x00, 0xf0, 0x00, 0x04, 0x00,
+		   0x70, 0x00, 0x0f, 0x00, 0x0e),
+	PHYREGS(0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424),
+  },
+};
+
+static const struct b43_nphy_channeltab_entry_rev3 b43_nphy_channeltab_rev5[] = {
+  {	.freq			= 4920,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0f,
+		   0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70,
+		   0x00, 0x0f, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07b4, 0x07b0, 0x07ac, 0x0214, 0x0215, 0x0216),
+  },
+  {	.freq			= 4930,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xed, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0e,
+		   0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70,
+		   0x00, 0x0e, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07b8, 0x07b4, 0x07b0, 0x0213, 0x0214, 0x0215),
+  },
+  {	.freq			= 4940,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xee, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0e,
+		   0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70,
+		   0x00, 0x0e, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07bc, 0x07b8, 0x07b4, 0x0212, 0x0213, 0x0214),
+  },
+  {	.freq			= 4950,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xef, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0e,
+		   0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70,
+		   0x00, 0x0e, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07c0, 0x07bc, 0x07b8, 0x0211, 0x0212, 0x0213),
+  },
+  {	.freq			= 4960,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf0, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0e,
+		   0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70,
+		   0x00, 0x0e, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07c4, 0x07c0, 0x07bc, 0x020f, 0x0211, 0x0212),
+  },
+  {	.freq			= 4970,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf1, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d,
+		   0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70,
+		   0x00, 0x0d, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07c8, 0x07c4, 0x07c0, 0x020e, 0x020f, 0x0211),
+  },
+  {	.freq			= 4980,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf2, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d,
+		   0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70,
+		   0x00, 0x0d, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07cc, 0x07c8, 0x07c4, 0x020d, 0x020e, 0x020f),
+  },
+  {	.freq			= 4990,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf3, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d,
+		   0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70,
+		   0x00, 0x0d, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07d0, 0x07cc, 0x07c8, 0x020c, 0x020d, 0x020e),
+  },
+  {	.freq			= 5000,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf4, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d,
+		   0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70,
+		   0x00, 0x0d, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07d4, 0x07d0, 0x07cc, 0x020b, 0x020c, 0x020d),
+  },
+  {	.freq			= 5010,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf5, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d,
+		   0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70,
+		   0x00, 0x0d, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07d8, 0x07d4, 0x07d0, 0x020a, 0x020b, 0x020c),
+  },
+  {	.freq			= 5020,
+	RADIOREGS3(0xf7, 0x01, 0x01, 0x01, 0xf6, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0d,
+		   0x00, 0x9f, 0x00, 0xff, 0x00, 0x09, 0x00, 0x70,
+		   0x00, 0x0d, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07dc, 0x07d8, 0x07d4, 0x0209, 0x020a, 0x020b),
+  },
+  {	.freq			= 5030,
+	RADIOREGS3(0xf7, 0x01, 0x01, 0x01, 0xf7, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c,
+		   0x00, 0x9f, 0x00, 0xff, 0x00, 0x09, 0x00, 0x70,
+		   0x00, 0x0c, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07e0, 0x07dc, 0x07d8, 0x0208, 0x0209, 0x020a),
+  },
+  {	.freq			= 5040,
+	RADIOREGS3(0xef, 0x01, 0x01, 0x01, 0xf8, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfe, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c,
+		   0x00, 0x9f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x70,
+		   0x00, 0x0c, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07e4, 0x07e0, 0x07dc, 0x0207, 0x0208, 0x0209),
+  },
+  {	.freq			= 5050,
+	RADIOREGS3(0xef, 0x01, 0x01, 0x01, 0xf9, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfe, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c,
+		   0x00, 0x9f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x70,
+		   0x00, 0x0c, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07e8, 0x07e4, 0x07e0, 0x0206, 0x0207, 0x0208),
+  },
+  {	.freq			= 5060,
+	RADIOREGS3(0xe6, 0x01, 0x01, 0x01, 0xfa, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfd, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c,
+		   0x00, 0x9f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x70,
+		   0x00, 0x0c, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07ec, 0x07e8, 0x07e4, 0x0205, 0x0206, 0x0207),
+  },
+  {	.freq			= 5070,
+	RADIOREGS3(0xe6, 0x01, 0x01, 0x01, 0xfb, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfd, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b,
+		   0x00, 0x9f, 0x00, 0xfd, 0x00, 0x08, 0x00, 0x70,
+		   0x00, 0x0b, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07f0, 0x07ec, 0x07e8, 0x0204, 0x0205, 0x0206),
+  },
+  {	.freq			= 5080,
+	RADIOREGS3(0xde, 0x01, 0x01, 0x01, 0xfc, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b,
+		   0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70,
+		   0x00, 0x0b, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07f4, 0x07f0, 0x07ec, 0x0203, 0x0204, 0x0205),
+  },
+  {	.freq			= 5090,
+	RADIOREGS3(0xde, 0x01, 0x01, 0x01, 0xfd, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b,
+		   0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70,
+		   0x00, 0x0b, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07f8, 0x07f4, 0x07f0, 0x0202, 0x0203, 0x0204),
+  },
+  {	.freq			= 5100,
+	RADIOREGS3(0xd6, 0x01, 0x01, 0x01, 0xfe, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b,
+		   0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70,
+		   0x00, 0x0b, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07fc, 0x07f8, 0x07f4, 0x0201, 0x0202, 0x0203),
+  },
+  {	.freq			= 5110,
+	RADIOREGS3(0xd6, 0x01, 0x01, 0x01, 0xff, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b,
+		   0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70,
+		   0x00, 0x0b, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0800, 0x07fc, 0x07f8, 0x0200, 0x0201, 0x0202),
+  },
+  {	.freq			= 5120,
+	RADIOREGS3(0xce, 0x01, 0x01, 0x02, 0x00, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b,
+		   0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70,
+		   0x00, 0x0b, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0804, 0x0800, 0x07fc, 0x01ff, 0x0200, 0x0201),
+  },
+  {	.freq			= 5130,
+	RADIOREGS3(0xce, 0x01, 0x01, 0x02, 0x01, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfb, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0a,
+		   0x00, 0x9f, 0x00, 0xfb, 0x00, 0x08, 0x00, 0x70,
+		   0x00, 0x0a, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0808, 0x0804, 0x0800, 0x01fe, 0x01ff, 0x0200),
+  },
+  {	.freq			= 5140,
+	RADIOREGS3(0xc6, 0x01, 0x01, 0x02, 0x02, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfb, 0x00, 0x07, 0x00, 0x70, 0x00, 0x0a,
+		   0x00, 0x9f, 0x00, 0xfb, 0x00, 0x07, 0x00, 0x70,
+		   0x00, 0x0a, 0x00, 0x6f, 0x00),
+	PHYREGS(0x080c, 0x0808, 0x0804, 0x01fd, 0x01fe, 0x01ff),
+  },
+  {	.freq			= 5160,
+	RADIOREGS3(0xbe, 0x01, 0x01, 0x02, 0x04, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfb, 0x00, 0x07, 0x00, 0x70, 0x00, 0x09,
+		   0x00, 0x9e, 0x00, 0xfb, 0x00, 0x07, 0x00, 0x70,
+		   0x00, 0x09, 0x00, 0x6e, 0x00),
+	PHYREGS(0x0814, 0x0810, 0x080c, 0x01fb, 0x01fc, 0x01fd),
+  },
+  {	.freq			= 5170,
+	RADIOREGS3(0xbe, 0x01, 0x01, 0x02, 0x05, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfb, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09,
+		   0x00, 0x9e, 0x00, 0xfb, 0x00, 0x06, 0x00, 0x70,
+		   0x00, 0x09, 0x00, 0x6e, 0x00),
+	PHYREGS(0x0818, 0x0814, 0x0810, 0x01fa, 0x01fb, 0x01fc),
+  },
+  {	.freq			= 5180,
+	RADIOREGS3(0xb6, 0x01, 0x01, 0x02, 0x06, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09,
+		   0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70,
+		   0x00, 0x09, 0x00, 0x6e, 0x00),
+	PHYREGS(0x081c, 0x0818, 0x0814, 0x01f9, 0x01fa, 0x01fb),
+  },
+  {	.freq			= 5190,
+	RADIOREGS3(0xb6, 0x01, 0x01, 0x02, 0x07, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09,
+		   0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70,
+		   0x00, 0x09, 0x00, 0x6e, 0x00),
+	PHYREGS(0x0820, 0x081c, 0x0818, 0x01f8, 0x01f9, 0x01fa),
+  },
+  {	.freq			= 5200,
+	RADIOREGS3(0xaf, 0x01, 0x01, 0x02, 0x08, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09,
+		   0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70,
+		   0x00, 0x09, 0x00, 0x6e, 0x00),
+	PHYREGS(0x0824, 0x0820, 0x081c, 0x01f7, 0x01f8, 0x01f9),
+  },
+  {	.freq			= 5210,
+	RADIOREGS3(0xaf, 0x01, 0x01, 0x02, 0x09, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09,
+		   0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70,
+		   0x00, 0x09, 0x00, 0x6e, 0x00),
+	PHYREGS(0x0828, 0x0824, 0x0820, 0x01f6, 0x01f7, 0x01f8),
+  },
+  {	.freq			= 5220,
+	RADIOREGS3(0xa7, 0x01, 0x01, 0x02, 0x0a, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09,
+		   0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70,
+		   0x00, 0x09, 0x00, 0x6e, 0x00),
+	PHYREGS(0x082c, 0x0828, 0x0824, 0x01f5, 0x01f6, 0x01f7),
+  },
+  {	.freq			= 5230,
+	RADIOREGS3(0xa7, 0x01, 0x01, 0x02, 0x0b, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xea, 0x00, 0x06, 0x00, 0x70, 0x00, 0x08,
+		   0x00, 0x9e, 0x00, 0xea, 0x00, 0x06, 0x00, 0x70,
+		   0x00, 0x08, 0x00, 0x6e, 0x00),
+	PHYREGS(0x0830, 0x082c, 0x0828, 0x01f4, 0x01f5, 0x01f6),
+  },
+  {	.freq			= 5240,
+	RADIOREGS3(0xa0, 0x01, 0x01, 0x02, 0x0c, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xe9, 0x00, 0x05, 0x00, 0x70, 0x00, 0x08,
+		   0x00, 0x9d, 0x00, 0xe9, 0x00, 0x05, 0x00, 0x70,
+		   0x00, 0x08, 0x00, 0x6d, 0x00),
+	PHYREGS(0x0834, 0x0830, 0x082c, 0x01f3, 0x01f4, 0x01f5),
+  },
+  {	.freq			= 5250,
+	RADIOREGS3(0xa0, 0x01, 0x01, 0x02, 0x0d, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xe9, 0x00, 0x05, 0x00, 0x70, 0x00, 0x08,
+		   0x00, 0x9d, 0x00, 0xe9, 0x00, 0x05, 0x00, 0x70,
+		   0x00, 0x08, 0x00, 0x6d, 0x00),
+	PHYREGS(0x0838, 0x0834, 0x0830, 0x01f2, 0x01f3, 0x01f4),
+  },
+  {	.freq			= 5260,
+	RADIOREGS3(0x98, 0x01, 0x01, 0x02, 0x0e, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xd9, 0x00, 0x05, 0x00, 0x70, 0x00, 0x08,
+		   0x00, 0x9d, 0x00, 0xd9, 0x00, 0x05, 0x00, 0x70,
+		   0x00, 0x08, 0x00, 0x6d, 0x00),
+	PHYREGS(0x083c, 0x0838, 0x0834, 0x01f1, 0x01f2, 0x01f3),
+  },
+  {	.freq			= 5270,
+	RADIOREGS3(0x98, 0x01, 0x01, 0x02, 0x0f, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00,
+		   0xff, 0xd8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
+		   0x00, 0x9c, 0x00, 0xd8, 0x00, 0x04, 0x00, 0x70,
+		   0x00, 0x07, 0x00, 0x6c, 0x00),
+	PHYREGS(0x0840, 0x083c, 0x0838, 0x01f0, 0x01f1, 0x01f2),
+  },
+  {	.freq			= 5280,
+	RADIOREGS3(0x91, 0x01, 0x01, 0x02, 0x10, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00,
+		   0xff, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
+		   0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70,
+		   0x00, 0x07, 0x00, 0x6c, 0x00),
+	PHYREGS(0x0844, 0x0840, 0x083c, 0x01f0, 0x01f0, 0x01f1),
+  },
+  {	.freq			= 5290,
+	RADIOREGS3(0x91, 0x01, 0x01, 0x02, 0x11, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00,
+		   0xff, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
+		   0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70,
+		   0x00, 0x07, 0x00, 0x6c, 0x00),
+	PHYREGS(0x0848, 0x0844, 0x0840, 0x01ef, 0x01f0, 0x01f0),
+  },
+  {	.freq			= 5300,
+	RADIOREGS3(0x8a, 0x01, 0x01, 0x02, 0x12, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00,
+		   0xff, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
+		   0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70,
+		   0x00, 0x07, 0x00, 0x6c, 0x00),
+	PHYREGS(0x084c, 0x0848, 0x0844, 0x01ee, 0x01ef, 0x01f0),
+  },
+  {	.freq			= 5310,
+	RADIOREGS3(0x8a, 0x01, 0x01, 0x02, 0x13, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00,
+		   0xff, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
+		   0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70,
+		   0x00, 0x07, 0x00, 0x6c, 0x00),
+	PHYREGS(0x0850, 0x084c, 0x0848, 0x01ed, 0x01ee, 0x01ef),
+  },
+  {	.freq			= 5320,
+	RADIOREGS3(0x83, 0x01, 0x01, 0x02, 0x14, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00,
+		   0xff, 0xb8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
+		   0x00, 0x9c, 0x00, 0xb8, 0x00, 0x04, 0x00, 0x70,
+		   0x00, 0x07, 0x00, 0x6c, 0x00),
+	PHYREGS(0x0854, 0x0850, 0x084c, 0x01ec, 0x01ed, 0x01ee),
+  },
+  {	.freq			= 5330,
+	RADIOREGS3(0x83, 0x01, 0x01, 0x02, 0x15, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00,
+		   0xff, 0xb7, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
+		   0x00, 0x9b, 0x00, 0xb7, 0x00, 0x04, 0x00, 0x70,
+		   0x00, 0x07, 0x00, 0x6b, 0x00),
+	PHYREGS(0x0858, 0x0854, 0x0850, 0x01eb, 0x01ec, 0x01ed),
+  },
+  {	.freq			= 5340,
+	RADIOREGS3(0x7c, 0x01, 0x01, 0x02, 0x16, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00,
+		   0xff, 0xb7, 0x00, 0x03, 0x00, 0x70, 0x00, 0x07,
+		   0x00, 0x9b, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x70,
+		   0x00, 0x07, 0x00, 0x6b, 0x00),
+	PHYREGS(0x085c, 0x0858, 0x0854, 0x01ea, 0x01eb, 0x01ec),
+  },
+  {	.freq			= 5350,
+	RADIOREGS3(0x7c, 0x01, 0x01, 0x02, 0x17, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00,
+		   0xff, 0xa7, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06,
+		   0x00, 0x9b, 0x00, 0xa7, 0x00, 0x03, 0x00, 0x70,
+		   0x00, 0x06, 0x00, 0x6b, 0x00),
+	PHYREGS(0x0860, 0x085c, 0x0858, 0x01e9, 0x01ea, 0x01eb),
+  },
+  {	.freq			= 5360,
+	RADIOREGS3(0x75, 0x01, 0x01, 0x02, 0x18, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00,
+		   0xff, 0xa6, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06,
+		   0x00, 0x9b, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x70,
+		   0x00, 0x06, 0x00, 0x6b, 0x00),
+	PHYREGS(0x0864, 0x0860, 0x085c, 0x01e8, 0x01e9, 0x01ea),
+  },
+  {	.freq			= 5370,
+	RADIOREGS3(0x75, 0x01, 0x01, 0x02, 0x19, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00,
+		   0xff, 0xa6, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06,
+		   0x00, 0x9b, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x70,
+		   0x00, 0x06, 0x00, 0x5b, 0x00),
+	PHYREGS(0x0868, 0x0864, 0x0860, 0x01e7, 0x01e8, 0x01e9),
+  },
+  {	.freq			= 5380,
+	RADIOREGS3(0x6e, 0x01, 0x01, 0x02, 0x1a, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00,
+		   0xff, 0x96, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06,
+		   0x00, 0x9a, 0x00, 0x96, 0x00, 0x03, 0x00, 0x70,
+		   0x00, 0x06, 0x00, 0x5a, 0x00),
+	PHYREGS(0x086c, 0x0868, 0x0864, 0x01e6, 0x01e7, 0x01e8),
+  },
+  {	.freq			= 5390,
+	RADIOREGS3(0x6e, 0x01, 0x01, 0x02, 0x1b, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00,
+		   0xff, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06,
+		   0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70,
+		   0x00, 0x06, 0x00, 0x5a, 0x00),
+	PHYREGS(0x0870, 0x086c, 0x0868, 0x01e5, 0x01e6, 0x01e7),
+  },
+  {	.freq			= 5400,
+	RADIOREGS3(0x67, 0x01, 0x01, 0x02, 0x1c, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00,
+		   0xc8, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06,
+		   0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70,
+		   0x00, 0x06, 0x00, 0x5a, 0x00),
+	PHYREGS(0x0874, 0x0870, 0x086c, 0x01e5, 0x01e5, 0x01e6),
+  },
+  {	.freq			= 5410,
+	RADIOREGS3(0x67, 0x01, 0x01, 0x02, 0x1d, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00,
+		   0xc8, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x05,
+		   0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70,
+		   0x00, 0x05, 0x00, 0x5a, 0x00),
+	PHYREGS(0x0878, 0x0874, 0x0870, 0x01e4, 0x01e5, 0x01e5),
+  },
+  {	.freq			= 5420,
+	RADIOREGS3(0x61, 0x01, 0x01, 0x02, 0x1e, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00,
+		   0xc8, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x05,
+		   0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70,
+		   0x00, 0x05, 0x00, 0x5a, 0x00),
+	PHYREGS(0x087c, 0x0878, 0x0874, 0x01e3, 0x01e4, 0x01e5),
+  },
+  {	.freq			= 5430,
+	RADIOREGS3(0x61, 0x01, 0x01, 0x02, 0x1f, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00,
+		   0xc8, 0x85, 0x00, 0x02, 0x00, 0x70, 0x00, 0x05,
+		   0x00, 0x99, 0x00, 0x85, 0x00, 0x02, 0x00, 0x70,
+		   0x00, 0x05, 0x00, 0x59, 0x00),
+	PHYREGS(0x0880, 0x087c, 0x0878, 0x01e2, 0x01e3, 0x01e4),
+  },
+  {	.freq			= 5440,
+	RADIOREGS3(0x5a, 0x01, 0x01, 0x02, 0x20, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00,
+		   0xc8, 0x84, 0x00, 0x02, 0x00, 0x70, 0x00, 0x05,
+		   0x00, 0x99, 0x00, 0x84, 0x00, 0x02, 0x00, 0x70,
+		   0x00, 0x05, 0x00, 0x59, 0x00),
+	PHYREGS(0x0884, 0x0880, 0x087c, 0x01e1, 0x01e2, 0x01e3),
+  },
+  {	.freq			= 5450,
+	RADIOREGS3(0x5a, 0x01, 0x01, 0x02, 0x21, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00,
+		   0xc8, 0x84, 0x00, 0x02, 0x00, 0x70, 0x00, 0x05,
+		   0x00, 0x99, 0x00, 0x84, 0x00, 0x02, 0x00, 0x70,
+		   0x00, 0x05, 0x00, 0x59, 0x00),
+	PHYREGS(0x0888, 0x0884, 0x0880, 0x01e0, 0x01e1, 0x01e2),
+  },
+  {	.freq			= 5460,
+	RADIOREGS3(0x53, 0x01, 0x01, 0x02, 0x22, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00,
+		   0xc8, 0x84, 0x00, 0x02, 0x00, 0x70, 0x00, 0x04,
+		   0x00, 0x99, 0x00, 0x84, 0x00, 0x02, 0x00, 0x70,
+		   0x00, 0x04, 0x00, 0x69, 0x00),
+	PHYREGS(0x088c, 0x0888, 0x0884, 0x01df, 0x01e0, 0x01e1),
+  },
+  {	.freq			= 5470,
+	RADIOREGS3(0x53, 0x01, 0x01, 0x02, 0x23, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00,
+		   0xc8, 0x74, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04,
+		   0x00, 0x99, 0x00, 0x74, 0x00, 0x01, 0x00, 0x70,
+		   0x00, 0x04, 0x00, 0x69, 0x00),
+	PHYREGS(0x0890, 0x088c, 0x0888, 0x01de, 0x01df, 0x01e0),
+  },
+  {	.freq			= 5480,
+	RADIOREGS3(0x4d, 0x01, 0x01, 0x02, 0x24, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00,
+		   0xc8, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04,
+		   0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70,
+		   0x00, 0x04, 0x00, 0x68, 0x00),
+	PHYREGS(0x0894, 0x0890, 0x088c, 0x01dd, 0x01de, 0x01df),
+  },
+  {	.freq			= 5490,
+	RADIOREGS3(0x4d, 0x01, 0x01, 0x02, 0x25, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00,
+		   0xc8, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04,
+		   0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70,
+		   0x00, 0x04, 0x00, 0x68, 0x00),
+	PHYREGS(0x0898, 0x0894, 0x0890, 0x01dd, 0x01dd, 0x01de),
+  },
+  {	.freq			= 5500,
+	RADIOREGS3(0x47, 0x01, 0x01, 0x02, 0x26, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00,
+		   0x84, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04,
+		   0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70,
+		   0x00, 0x04, 0x00, 0x78, 0x00),
+	PHYREGS(0x089c, 0x0898, 0x0894, 0x01dc, 0x01dd, 0x01dd),
+  },
+  {	.freq			= 5510,
+	RADIOREGS3(0x47, 0x01, 0x01, 0x02, 0x27, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00,
+		   0x84, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04,
+		   0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70,
+		   0x00, 0x04, 0x00, 0x78, 0x00),
+	PHYREGS(0x08a0, 0x089c, 0x0898, 0x01db, 0x01dc, 0x01dd),
+  },
+  {	.freq			= 5520,
+	RADIOREGS3(0x40, 0x01, 0x01, 0x02, 0x28, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00,
+		   0x84, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04,
+		   0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70,
+		   0x00, 0x04, 0x00, 0x78, 0x00),
+	PHYREGS(0x08a4, 0x08a0, 0x089c, 0x01da, 0x01db, 0x01dc),
+  },
+  {	.freq			= 5530,
+	RADIOREGS3(0x40, 0x01, 0x01, 0x02, 0x29, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00,
+		   0x84, 0x63, 0x00, 0x01, 0x00, 0x70, 0x00, 0x03,
+		   0x00, 0x98, 0x00, 0x63, 0x00, 0x01, 0x00, 0x70,
+		   0x00, 0x03, 0x00, 0x78, 0x00),
+	PHYREGS(0x08a8, 0x08a4, 0x08a0, 0x01d9, 0x01da, 0x01db),
+  },
+  {	.freq			= 5540,
+	RADIOREGS3(0x3a, 0x01, 0x01, 0x02, 0x2a, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00,
+		   0x84, 0x62, 0x00, 0x00, 0x00, 0x70, 0x00, 0x03,
+		   0x00, 0x97, 0x00, 0x62, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x03, 0x00, 0x77, 0x00),
+	PHYREGS(0x08ac, 0x08a8, 0x08a4, 0x01d8, 0x01d9, 0x01da),
+  },
+  {	.freq			= 5550,
+	RADIOREGS3(0x3a, 0x01, 0x01, 0x02, 0x2b, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00,
+		   0x84, 0x62, 0x00, 0x00, 0x00, 0x70, 0x00, 0x03,
+		   0x00, 0x97, 0x00, 0x62, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x03, 0x00, 0x77, 0x00),
+	PHYREGS(0x08b0, 0x08ac, 0x08a8, 0x01d7, 0x01d8, 0x01d9),
+  },
+  {	.freq			= 5560,
+	RADIOREGS3(0x34, 0x01, 0x01, 0x02, 0x2c, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00,
+		   0x84, 0x62, 0x00, 0x00, 0x00, 0x70, 0x00, 0x03,
+		   0x00, 0x97, 0x00, 0x62, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x03, 0x00, 0x77, 0x00),
+	PHYREGS(0x08b4, 0x08b0, 0x08ac, 0x01d7, 0x01d7, 0x01d8),
+  },
+  {	.freq			= 5570,
+	RADIOREGS3(0x34, 0x01, 0x01, 0x02, 0x2d, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00,
+		   0x84, 0x52, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
+		   0x00, 0x96, 0x00, 0x52, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x02, 0x00, 0x76, 0x00),
+	PHYREGS(0x08b8, 0x08b4, 0x08b0, 0x01d6, 0x01d7, 0x01d7),
+  },
+  {	.freq			= 5580,
+	RADIOREGS3(0x2e, 0x01, 0x01, 0x02, 0x2e, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00,
+		   0x84, 0x52, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
+		   0x00, 0x96, 0x00, 0x52, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x02, 0x00, 0x76, 0x00),
+	PHYREGS(0x08bc, 0x08b8, 0x08b4, 0x01d5, 0x01d6, 0x01d7),
+  },
+  {	.freq			= 5590,
+	RADIOREGS3(0x2e, 0x01, 0x01, 0x02, 0x2f, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00,
+		   0x84, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
+		   0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x02, 0x00, 0x76, 0x00),
+	PHYREGS(0x08c0, 0x08bc, 0x08b8, 0x01d4, 0x01d5, 0x01d6),
+  },
+  {	.freq			= 5600,
+	RADIOREGS3(0x28, 0x01, 0x01, 0x02, 0x30, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00,
+		   0x70, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
+		   0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x02, 0x00, 0x76, 0x00),
+	PHYREGS(0x08c4, 0x08c0, 0x08bc, 0x01d3, 0x01d4, 0x01d5),
+  },
+  {	.freq			= 5610,
+	RADIOREGS3(0x28, 0x01, 0x01, 0x02, 0x31, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00,
+		   0x70, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
+		   0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x02, 0x00, 0x76, 0x00),
+	PHYREGS(0x08c8, 0x08c4, 0x08c0, 0x01d2, 0x01d3, 0x01d4),
+  },
+  {	.freq			= 5620,
+	RADIOREGS3(0x21, 0x01, 0x01, 0x02, 0x32, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00,
+		   0x70, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
+		   0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x02, 0x00, 0x76, 0x00),
+	PHYREGS(0x08cc, 0x08c8, 0x08c4, 0x01d2, 0x01d2, 0x01d3),
+  },
+  {	.freq			= 5630,
+	RADIOREGS3(0x21, 0x01, 0x01, 0x02, 0x33, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00,
+		   0x70, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
+		   0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x02, 0x00, 0x76, 0x00),
+	PHYREGS(0x08d0, 0x08cc, 0x08c8, 0x01d1, 0x01d2, 0x01d2),
+  },
+  {	.freq			= 5640,
+	RADIOREGS3(0x1c, 0x01, 0x01, 0x02, 0x34, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00,
+		   0x70, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
+		   0x00, 0x95, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x02, 0x00, 0x75, 0x00),
+	PHYREGS(0x08d4, 0x08d0, 0x08cc, 0x01d0, 0x01d1, 0x01d2),
+  },
+  {	.freq			= 5650,
+	RADIOREGS3(0x1c, 0x01, 0x01, 0x02, 0x35, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00,
+		   0x70, 0x50, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+		   0x00, 0x95, 0x00, 0x50, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x01, 0x00, 0x75, 0x00),
+	PHYREGS(0x08d8, 0x08d4, 0x08d0, 0x01cf, 0x01d0, 0x01d1),
+  },
+  {	.freq			= 5660,
+	RADIOREGS3(0x16, 0x01, 0x01, 0x02, 0x36, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00,
+		   0x70, 0x50, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+		   0x00, 0x95, 0x00, 0x50, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x01, 0x00, 0x75, 0x00),
+	PHYREGS(0x08dc, 0x08d8, 0x08d4, 0x01ce, 0x01cf, 0x01d0),
+  },
+  {	.freq			= 5670,
+	RADIOREGS3(0x16, 0x01, 0x01, 0x02, 0x37, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00,
+		   0x70, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+		   0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x01, 0x00, 0x74, 0x00),
+	PHYREGS(0x08e0, 0x08dc, 0x08d8, 0x01ce, 0x01ce, 0x01cf),
+  },
+  {	.freq			= 5680,
+	RADIOREGS3(0x10, 0x01, 0x01, 0x02, 0x38, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00,
+		   0x70, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+		   0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x01, 0x00, 0x74, 0x00),
+	PHYREGS(0x08e4, 0x08e0, 0x08dc, 0x01cd, 0x01ce, 0x01ce),
+  },
+  {	.freq			= 5690,
+	RADIOREGS3(0x10, 0x01, 0x01, 0x02, 0x39, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00,
+		   0x70, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+		   0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x01, 0x00, 0x74, 0x00),
+	PHYREGS(0x08e8, 0x08e4, 0x08e0, 0x01cc, 0x01cd, 0x01ce),
+  },
+  {	.freq			= 5700,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3a, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00,
+		   0x40, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+		   0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x01, 0x00, 0x74, 0x00),
+	PHYREGS(0x08ec, 0x08e8, 0x08e4, 0x01cb, 0x01cc, 0x01cd),
+  },
+  {	.freq			= 5710,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3b, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00,
+		   0x40, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+		   0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x01, 0x00, 0x74, 0x00),
+	PHYREGS(0x08f0, 0x08ec, 0x08e8, 0x01ca, 0x01cb, 0x01cc),
+  },
+  {	.freq			= 5720,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3c, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00,
+		   0x40, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+		   0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x01, 0x00, 0x74, 0x00),
+	PHYREGS(0x08f4, 0x08f0, 0x08ec, 0x01c9, 0x01ca, 0x01cb),
+  },
+  {	.freq			= 5725,
+	RADIOREGS3(0x03, 0x01, 0x02, 0x04, 0x79, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00,
+		   0x40, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+		   0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x01, 0x00, 0x74, 0x00),
+	PHYREGS(0x08f6, 0x08f2, 0x08ee, 0x01c9, 0x01ca, 0x01cb),
+  },
+  {	.freq			= 5730,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3d, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00,
+		   0x40, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+		   0x00, 0x94, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x01, 0x00, 0x84, 0x00),
+	PHYREGS(0x08f8, 0x08f4, 0x08f0, 0x01c9, 0x01c9, 0x01ca),
+  },
+  {	.freq			= 5735,
+	RADIOREGS3(0x03, 0x01, 0x02, 0x04, 0x7b, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00,
+		   0x40, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x83, 0x00),
+	PHYREGS(0x08fa, 0x08f6, 0x08f2, 0x01c8, 0x01c9, 0x01ca),
+  },
+  {	.freq			= 5740,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3e, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00,
+		   0x40, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x83, 0x00),
+	PHYREGS(0x08fc, 0x08f8, 0x08f4, 0x01c8, 0x01c9, 0x01c9),
+  },
+  {	.freq			= 5745,
+	RADIOREGS3(0xfe, 0x00, 0x02, 0x04, 0x7d, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00,
+		   0x40, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x83, 0x00),
+	PHYREGS(0x08fe, 0x08fa, 0x08f6, 0x01c8, 0x01c8, 0x01c9),
+  },
+  {	.freq			= 5750,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3f, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00,
+		   0x40, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x83, 0x00),
+	PHYREGS(0x0900, 0x08fc, 0x08f8, 0x01c7, 0x01c8, 0x01c9),
+  },
+  {	.freq			= 5755,
+	RADIOREGS3(0xfe, 0x00, 0x02, 0x04, 0x7f, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00,
+		   0x40, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x83, 0x00),
+	PHYREGS(0x0902, 0x08fe, 0x08fa, 0x01c7, 0x01c8, 0x01c8),
+  },
+  {	.freq			= 5760,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x40, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00,
+		   0x40, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x93, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x83, 0x00),
+	PHYREGS(0x0904, 0x0900, 0x08fc, 0x01c6, 0x01c7, 0x01c8),
+  },
+  {	.freq			= 5765,
+	RADIOREGS3(0xf8, 0x00, 0x02, 0x04, 0x81, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00,
+		   0x40, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x92, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x82, 0x00),
+	PHYREGS(0x0906, 0x0902, 0x08fe, 0x01c6, 0x01c7, 0x01c8),
+  },
+  {	.freq			= 5770,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x41, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00,
+		   0x40, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x92, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x82, 0x00),
+	PHYREGS(0x0908, 0x0904, 0x0900, 0x01c6, 0x01c6, 0x01c7),
+  },
+  {	.freq			= 5775,
+	RADIOREGS3(0xf8, 0x00, 0x02, 0x04, 0x83, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00,
+		   0x40, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x92, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x82, 0x00),
+	PHYREGS(0x090a, 0x0906, 0x0902, 0x01c5, 0x01c6, 0x01c7),
+  },
+  {	.freq			= 5780,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x42, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00,
+		   0x40, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x82, 0x00),
+	PHYREGS(0x090c, 0x0908, 0x0904, 0x01c5, 0x01c6, 0x01c6),
+  },
+  {	.freq			= 5785,
+	RADIOREGS3(0xf2, 0x00, 0x02, 0x04, 0x85, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00,
+		   0x40, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x82, 0x00),
+	PHYREGS(0x090e, 0x090a, 0x0906, 0x01c4, 0x01c5, 0x01c6),
+  },
+  {	.freq			= 5790,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x43, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00,
+		   0x40, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x82, 0x00),
+	PHYREGS(0x0910, 0x090c, 0x0908, 0x01c4, 0x01c5, 0x01c6),
+  },
+  {	.freq			= 5795,
+	RADIOREGS3(0xf2, 0x00, 0x02, 0x04, 0x87, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00,
+		   0x40, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x82, 0x00),
+	PHYREGS(0x0912, 0x090e, 0x090a, 0x01c4, 0x01c4, 0x01c5),
+  },
+  {	.freq			= 5800,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x44, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00,
+		   0x20, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x82, 0x00),
+	PHYREGS(0x0914, 0x0910, 0x090c, 0x01c3, 0x01c4, 0x01c5),
+  },
+  {	.freq			= 5805,
+	RADIOREGS3(0xed, 0x00, 0x02, 0x04, 0x89, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00,
+		   0x20, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x82, 0x00),
+	PHYREGS(0x0916, 0x0912, 0x090e, 0x01c3, 0x01c4, 0x01c4),
+  },
+  {	.freq			= 5810,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x45, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00,
+		   0x20, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x82, 0x00),
+	PHYREGS(0x0918, 0x0914, 0x0910, 0x01c2, 0x01c3, 0x01c4),
+  },
+  {	.freq			= 5815,
+	RADIOREGS3(0xed, 0x00, 0x02, 0x04, 0x8b, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00,
+		   0x20, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x82, 0x00),
+	PHYREGS(0x091a, 0x0916, 0x0912, 0x01c2, 0x01c3, 0x01c4),
+  },
+  {	.freq			= 5820,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x46, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00,
+		   0x20, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x82, 0x00),
+	PHYREGS(0x091c, 0x0918, 0x0914, 0x01c2, 0x01c2, 0x01c3),
+  },
+  {	.freq			= 5825,
+	RADIOREGS3(0xed, 0x00, 0x02, 0x04, 0x8d, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00,
+		   0x20, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x82, 0x00),
+	PHYREGS(0x091e, 0x091a, 0x0916, 0x01c1, 0x01c2, 0x01c3),
+  },
+  {	.freq			= 5830,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x47, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00,
+		   0x20, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x72, 0x00),
+	PHYREGS(0x0920, 0x091c, 0x0918, 0x01c1, 0x01c2, 0x01c2),
+  },
+  {	.freq			= 5840,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x48, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00,
+		   0x20, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x72, 0x00),
+	PHYREGS(0x0924, 0x0920, 0x091c, 0x01c0, 0x01c1, 0x01c2),
+  },
+  {	.freq			= 5850,
+	RADIOREGS3(0xe0, 0x00, 0x01, 0x02, 0x49, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00,
+		   0x20, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x72, 0x00),
+	PHYREGS(0x0928, 0x0924, 0x0920, 0x01bf, 0x01c0, 0x01c1),
+  },
+  {	.freq			= 5860,
+	RADIOREGS3(0xde, 0x00, 0x01, 0x02, 0x4a, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00,
+		   0x20, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x72, 0x00),
+	PHYREGS(0x092c, 0x0928, 0x0924, 0x01bf, 0x01bf, 0x01c0),
+  },
+  {	.freq			= 5870,
+	RADIOREGS3(0xdb, 0x00, 0x01, 0x02, 0x4b, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00,
+		   0x20, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x71, 0x00),
+	PHYREGS(0x0930, 0x092c, 0x0928, 0x01be, 0x01bf, 0x01bf),
+  },
+  {	.freq			= 5880,
+	RADIOREGS3(0xd8, 0x00, 0x01, 0x02, 0x4c, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00,
+		   0x20, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x71, 0x00),
+	PHYREGS(0x0934, 0x0930, 0x092c, 0x01bd, 0x01be, 0x01bf),
+  },
+  {	.freq			= 5890,
+	RADIOREGS3(0xd6, 0x00, 0x01, 0x02, 0x4d, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00,
+		   0x20, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x71, 0x00),
+	PHYREGS(0x0938, 0x0934, 0x0930, 0x01bc, 0x01bd, 0x01be),
+  },
+  {	.freq			= 5900,
+	RADIOREGS3(0xd3, 0x00, 0x01, 0x02, 0x4e, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x87, 0x03, 0x00,
+		   0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x71, 0x00),
+	PHYREGS(0x093c, 0x0938, 0x0934, 0x01bc, 0x01bc, 0x01bd),
+  },
+  {	.freq			= 5910,
+	RADIOREGS3(0xd6, 0x00, 0x01, 0x02, 0x4f, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x87, 0x03, 0x00,
+		   0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x71, 0x00),
+	PHYREGS(0x0940, 0x093c, 0x0938, 0x01bb, 0x01bc, 0x01bc),
+  },
+  {	.freq			= 2412,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x6c, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x04, 0x04, 0x04, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x1f, 0x00, 0x03, 0x00, 0x70, 0x00,
+		   0x0f, 0x00, 0x0b, 0x00, 0x1f, 0x00, 0x03, 0x00,
+		   0x70, 0x00, 0x0f, 0x00, 0x0b),
+	PHYREGS(0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443),
+  },
+  {	.freq			= 2417,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x71, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x1f, 0x00, 0x03, 0x00, 0x70, 0x00,
+		   0x0f, 0x00, 0x0a, 0x00, 0x1f, 0x00, 0x03, 0x00,
+		   0x70, 0x00, 0x0f, 0x00, 0x0a),
+	PHYREGS(0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441),
+  },
+  {	.freq			= 2422,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x76, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x0e, 0x00, 0x03, 0x00, 0x70, 0x00,
+		   0x0f, 0x00, 0x0a, 0x00, 0x0e, 0x00, 0x03, 0x00,
+		   0x70, 0x00, 0x0f, 0x00, 0x0a),
+	PHYREGS(0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f),
+  },
+  {	.freq			= 2427,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x7b, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x0d, 0x00, 0x03, 0x00, 0x70, 0x00,
+		   0x0e, 0x00, 0x0a, 0x00, 0x0d, 0x00, 0x03, 0x00,
+		   0x70, 0x00, 0x0e, 0x00, 0x0a),
+	PHYREGS(0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d),
+  },
+  {	.freq			= 2432,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x80, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x0c, 0x00, 0x03, 0x00, 0x70, 0x00,
+		   0x0e, 0x00, 0x0a, 0x00, 0x0c, 0x00, 0x03, 0x00,
+		   0x70, 0x00, 0x0e, 0x00, 0x0a),
+	PHYREGS(0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a),
+  },
+  {	.freq			= 2437,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x85, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x0b, 0x00, 0x03, 0x00, 0x70, 0x00,
+		   0x0e, 0x00, 0x0a, 0x00, 0x0b, 0x00, 0x03, 0x00,
+		   0x70, 0x00, 0x0e, 0x00, 0x0a),
+	PHYREGS(0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438),
+  },
+  {	.freq			= 2442,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x8a, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x09, 0x00, 0x03, 0x00, 0x70, 0x00,
+		   0x0e, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x03, 0x00,
+		   0x70, 0x00, 0x0e, 0x00, 0x0a),
+	PHYREGS(0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436),
+  },
+  {	.freq			= 2447,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x8f, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x08, 0x00, 0x02, 0x00, 0x70, 0x00,
+		   0x0e, 0x00, 0x09, 0x00, 0x08, 0x00, 0x02, 0x00,
+		   0x70, 0x00, 0x0e, 0x00, 0x09),
+	PHYREGS(0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434),
+  },
+  {	.freq			= 2452,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x94, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x07, 0x00, 0x02, 0x00, 0x70, 0x00,
+		   0x0e, 0x00, 0x09, 0x00, 0x07, 0x00, 0x02, 0x00,
+		   0x70, 0x00, 0x0e, 0x00, 0x09),
+	PHYREGS(0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431),
+  },
+  {	.freq			= 2457,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x99, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x06, 0x00, 0x02, 0x00, 0x70, 0x00,
+		   0x0d, 0x00, 0x09, 0x00, 0x06, 0x00, 0x02, 0x00,
+		   0x70, 0x00, 0x0d, 0x00, 0x09),
+	PHYREGS(0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f),
+  },
+  {	.freq			= 2462,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x9e, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x05, 0x00, 0x02, 0x00, 0x70, 0x00,
+		   0x0d, 0x00, 0x09, 0x00, 0x05, 0x00, 0x02, 0x00,
+		   0x70, 0x00, 0x0d, 0x00, 0x09),
+	PHYREGS(0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d),
+  },
+  {	.freq			= 2467,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0xa3, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x70, 0x00,
+		   0x0d, 0x00, 0x08, 0x00, 0x04, 0x00, 0x02, 0x00,
+		   0x70, 0x00, 0x0d, 0x00, 0x08),
+	PHYREGS(0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b),
+  },
+  {	.freq			= 2472,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0xa8, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x03, 0x00, 0x02, 0x00, 0x70, 0x00,
+		   0x0d, 0x00, 0x08, 0x00, 0x03, 0x00, 0x02, 0x00,
+		   0x70, 0x00, 0x0d, 0x00, 0x08),
+	PHYREGS(0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429),
+  },
+  {	.freq			= 2484,
+	RADIOREGS3(0xff, 0x01, 0x03, 0x09, 0xb4, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x70, 0x00,
+		   0x0d, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00,
+		   0x70, 0x00, 0x0d, 0x00, 0x08),
+	PHYREGS(0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424),
+  },
 };
 
+static const struct b43_nphy_channeltab_entry_rev3 b43_nphy_channeltab_rev6[] = {
+  {	.freq			= 4920,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+		   0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77,
+		   0x00, 0x0f, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07b4, 0x07b0, 0x07ac, 0x0214, 0x0215, 0x0216),
+  },
+  {	.freq			= 4930,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xed, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+		   0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77,
+		   0x00, 0x0f, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07b8, 0x07b4, 0x07b0, 0x0213, 0x0214, 0x0215),
+  },
+  {	.freq			= 4940,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xee, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+		   0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77,
+		   0x00, 0x0f, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07bc, 0x07b8, 0x07b4, 0x0212, 0x0213, 0x0214),
+  },
+  {	.freq			= 4950,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xef, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+		   0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77,
+		   0x00, 0x0f, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07c0, 0x07bc, 0x07b8, 0x0211, 0x0212, 0x0213),
+  },
+  {	.freq			= 4960,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf0, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+		   0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77,
+		   0x00, 0x0f, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07c4, 0x07c0, 0x07bc, 0x020f, 0x0211, 0x0212),
+  },
+  {	.freq			= 4970,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf1, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+		   0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77,
+		   0x00, 0x0f, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07c8, 0x07c4, 0x07c0, 0x020e, 0x020f, 0x0211),
+  },
+  {	.freq			= 4980,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf2, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+		   0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77,
+		   0x00, 0x0f, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07cc, 0x07c8, 0x07c4, 0x020d, 0x020e, 0x020f),
+  },
+  {	.freq			= 4990,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf3, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+		   0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77,
+		   0x00, 0x0f, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07d0, 0x07cc, 0x07c8, 0x020c, 0x020d, 0x020e),
+  },
+  {	.freq			= 5000,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf4, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+		   0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77,
+		   0x00, 0x0f, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07d4, 0x07d0, 0x07cc, 0x020b, 0x020c, 0x020d),
+  },
+  {	.freq			= 5010,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf5, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+		   0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77,
+		   0x00, 0x0f, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07d8, 0x07d4, 0x07d0, 0x020a, 0x020b, 0x020c),
+  },
+  {	.freq			= 5020,
+	RADIOREGS3(0xf7, 0x01, 0x01, 0x01, 0xf6, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+		   0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77,
+		   0x00, 0x0f, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07dc, 0x07d8, 0x07d4, 0x0209, 0x020a, 0x020b),
+  },
+  {	.freq			= 5030,
+	RADIOREGS3(0xf7, 0x01, 0x01, 0x01, 0xf7, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+		   0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77,
+		   0x00, 0x0f, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07e0, 0x07dc, 0x07d8, 0x0208, 0x0209, 0x020a),
+  },
+  {	.freq			= 5040,
+	RADIOREGS3(0xef, 0x01, 0x01, 0x01, 0xf8, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+		   0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77,
+		   0x00, 0x0f, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07e4, 0x07e0, 0x07dc, 0x0207, 0x0208, 0x0209),
+  },
+  {	.freq			= 5050,
+	RADIOREGS3(0xef, 0x01, 0x01, 0x01, 0xf9, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+		   0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77,
+		   0x00, 0x0f, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07e8, 0x07e4, 0x07e0, 0x0206, 0x0207, 0x0208),
+  },
+  {	.freq			= 5060,
+	RADIOREGS3(0xe6, 0x01, 0x01, 0x01, 0xfa, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+		   0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77,
+		   0x00, 0x0f, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07ec, 0x07e8, 0x07e4, 0x0205, 0x0206, 0x0207),
+  },
+  {	.freq			= 5070,
+	RADIOREGS3(0xe6, 0x01, 0x01, 0x01, 0xfb, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+		   0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77,
+		   0x00, 0x0f, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07f0, 0x07ec, 0x07e8, 0x0204, 0x0205, 0x0206),
+  },
+  {	.freq			= 5080,
+	RADIOREGS3(0xde, 0x01, 0x01, 0x01, 0xfc, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+		   0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77,
+		   0x00, 0x0f, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07f4, 0x07f0, 0x07ec, 0x0203, 0x0204, 0x0205),
+  },
+  {	.freq			= 5090,
+	RADIOREGS3(0xde, 0x01, 0x01, 0x01, 0xfd, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+		   0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77,
+		   0x00, 0x0f, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07f8, 0x07f4, 0x07f0, 0x0202, 0x0203, 0x0204),
+  },
+  {	.freq			= 5100,
+	RADIOREGS3(0xd6, 0x01, 0x01, 0x01, 0xfe, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfd, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
+		   0x00, 0x6f, 0x00, 0xfd, 0x00, 0x08, 0x00, 0x77,
+		   0x00, 0x0f, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07fc, 0x07f8, 0x07f4, 0x0201, 0x0202, 0x0203),
+  },
+  {	.freq			= 5110,
+	RADIOREGS3(0xd6, 0x01, 0x01, 0x01, 0xff, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
+		   0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77,
+		   0x00, 0x0f, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0800, 0x07fc, 0x07f8, 0x0200, 0x0201, 0x0202),
+  },
+  {	.freq			= 5120,
+	RADIOREGS3(0xce, 0x01, 0x01, 0x02, 0x00, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
+		   0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77,
+		   0x00, 0x0f, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0804, 0x0800, 0x07fc, 0x01ff, 0x0200, 0x0201),
+  },
+  {	.freq			= 5130,
+	RADIOREGS3(0xce, 0x01, 0x01, 0x02, 0x01, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
+		   0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77,
+		   0x00, 0x0f, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0808, 0x0804, 0x0800, 0x01fe, 0x01ff, 0x0200),
+  },
+  {	.freq			= 5140,
+	RADIOREGS3(0xc6, 0x01, 0x01, 0x02, 0x02, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfb, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
+		   0x00, 0x6f, 0x00, 0xfb, 0x00, 0x08, 0x00, 0x77,
+		   0x00, 0x0f, 0x00, 0x6f, 0x00),
+	PHYREGS(0x080c, 0x0808, 0x0804, 0x01fd, 0x01fe, 0x01ff),
+  },
+  {	.freq			= 5160,
+	RADIOREGS3(0xbe, 0x01, 0x01, 0x02, 0x04, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfa, 0x00, 0x07, 0x00, 0x77, 0x00, 0x0e,
+		   0x00, 0x6f, 0x00, 0xfa, 0x00, 0x07, 0x00, 0x77,
+		   0x00, 0x0e, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0814, 0x0810, 0x080c, 0x01fb, 0x01fc, 0x01fd),
+  },
+  {	.freq			= 5170,
+	RADIOREGS3(0xbe, 0x01, 0x01, 0x02, 0x05, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfa, 0x00, 0x07, 0x00, 0x77, 0x00, 0x0e,
+		   0x00, 0x6f, 0x00, 0xfa, 0x00, 0x07, 0x00, 0x77,
+		   0x00, 0x0e, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0818, 0x0814, 0x0810, 0x01fa, 0x01fb, 0x01fc),
+  },
+  {	.freq			= 5180,
+	RADIOREGS3(0xb6, 0x01, 0x01, 0x02, 0x06, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xf9, 0x00, 0x06, 0x00, 0x77, 0x00, 0x0e,
+		   0x00, 0x6f, 0x00, 0xf9, 0x00, 0x06, 0x00, 0x77,
+		   0x00, 0x0e, 0x00, 0x6f, 0x00),
+	PHYREGS(0x081c, 0x0818, 0x0814, 0x01f9, 0x01fa, 0x01fb),
+  },
+  {	.freq			= 5190,
+	RADIOREGS3(0xb6, 0x01, 0x01, 0x02, 0x07, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xf9, 0x00, 0x06, 0x00, 0x77, 0x00, 0x0d,
+		   0x00, 0x6f, 0x00, 0xf9, 0x00, 0x06, 0x00, 0x77,
+		   0x00, 0x0d, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0820, 0x081c, 0x0818, 0x01f8, 0x01f9, 0x01fa),
+  },
+  {	.freq			= 5200,
+	RADIOREGS3(0xaf, 0x01, 0x01, 0x02, 0x08, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xf9, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+		   0x00, 0x6f, 0x00, 0xf9, 0x00, 0x05, 0x00, 0x77,
+		   0x00, 0x0d, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0824, 0x0820, 0x081c, 0x01f7, 0x01f8, 0x01f9),
+  },
+  {	.freq			= 5210,
+	RADIOREGS3(0xaf, 0x01, 0x01, 0x02, 0x09, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xf9, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+		   0x00, 0x6f, 0x00, 0xf9, 0x00, 0x05, 0x00, 0x77,
+		   0x00, 0x0d, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0828, 0x0824, 0x0820, 0x01f6, 0x01f7, 0x01f8),
+  },
+  {	.freq			= 5220,
+	RADIOREGS3(0xa7, 0x01, 0x01, 0x02, 0x0a, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00,
+		   0xfe, 0xd8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+		   0x00, 0x6f, 0x00, 0xd8, 0x00, 0x05, 0x00, 0x77,
+		   0x00, 0x0d, 0x00, 0x6f, 0x00),
+	PHYREGS(0x082c, 0x0828, 0x0824, 0x01f5, 0x01f6, 0x01f7),
+  },
+  {	.freq			= 5230,
+	RADIOREGS3(0xa7, 0x01, 0x01, 0x02, 0x0b, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00,
+		   0xee, 0xd8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+		   0x00, 0x6f, 0x00, 0xd8, 0x00, 0x05, 0x00, 0x77,
+		   0x00, 0x0d, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0830, 0x082c, 0x0828, 0x01f4, 0x01f5, 0x01f6),
+  },
+  {	.freq			= 5240,
+	RADIOREGS3(0xa0, 0x01, 0x01, 0x02, 0x0c, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00,
+		   0xee, 0xc8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+		   0x00, 0x6f, 0x00, 0xc8, 0x00, 0x05, 0x00, 0x77,
+		   0x00, 0x0d, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0834, 0x0830, 0x082c, 0x01f3, 0x01f4, 0x01f5),
+  },
+  {	.freq			= 5250,
+	RADIOREGS3(0xa0, 0x01, 0x01, 0x02, 0x0d, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00,
+		   0xed, 0xc7, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+		   0x00, 0x6f, 0x00, 0xc7, 0x00, 0x05, 0x00, 0x77,
+		   0x00, 0x0d, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0838, 0x0834, 0x0830, 0x01f2, 0x01f3, 0x01f4),
+  },
+  {	.freq			= 5260,
+	RADIOREGS3(0x98, 0x01, 0x01, 0x02, 0x0e, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8e, 0x0e, 0x00,
+		   0xed, 0xc7, 0x00, 0x04, 0x00, 0x77, 0x00, 0x0d,
+		   0x00, 0x6f, 0x00, 0xc7, 0x00, 0x04, 0x00, 0x77,
+		   0x00, 0x0d, 0x00, 0x6f, 0x00),
+	PHYREGS(0x083c, 0x0838, 0x0834, 0x01f1, 0x01f2, 0x01f3),
+  },
+  {	.freq			= 5270,
+	RADIOREGS3(0x98, 0x01, 0x01, 0x02, 0x0f, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8e, 0x0e, 0x00,
+		   0xed, 0xc7, 0x00, 0x04, 0x00, 0x77, 0x00, 0x0c,
+		   0x00, 0x6f, 0x00, 0xc7, 0x00, 0x04, 0x00, 0x77,
+		   0x00, 0x0c, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0840, 0x083c, 0x0838, 0x01f0, 0x01f1, 0x01f2),
+  },
+  {	.freq			= 5280,
+	RADIOREGS3(0x91, 0x01, 0x01, 0x02, 0x10, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00,
+		   0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
+		   0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77,
+		   0x00, 0x0c, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0844, 0x0840, 0x083c, 0x01f0, 0x01f0, 0x01f1),
+  },
+  {	.freq			= 5290,
+	RADIOREGS3(0x91, 0x01, 0x01, 0x02, 0x11, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00,
+		   0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
+		   0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77,
+		   0x00, 0x0c, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0848, 0x0844, 0x0840, 0x01ef, 0x01f0, 0x01f0),
+  },
+  {	.freq			= 5300,
+	RADIOREGS3(0x8a, 0x01, 0x01, 0x02, 0x12, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00,
+		   0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
+		   0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77,
+		   0x00, 0x0c, 0x00, 0x6f, 0x00),
+	PHYREGS(0x084c, 0x0848, 0x0844, 0x01ee, 0x01ef, 0x01f0),
+  },
+  {	.freq			= 5310,
+	RADIOREGS3(0x8a, 0x01, 0x01, 0x02, 0x13, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00,
+		   0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
+		   0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77,
+		   0x00, 0x0c, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0850, 0x084c, 0x0848, 0x01ed, 0x01ee, 0x01ef),
+  },
+  {	.freq			= 5320,
+	RADIOREGS3(0x83, 0x01, 0x01, 0x02, 0x14, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00,
+		   0xdb, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
+		   0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77,
+		   0x00, 0x0c, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0854, 0x0850, 0x084c, 0x01ec, 0x01ed, 0x01ee),
+  },
+  {	.freq			= 5330,
+	RADIOREGS3(0x83, 0x01, 0x01, 0x02, 0x15, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00,
+		   0xcb, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b,
+		   0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77,
+		   0x00, 0x0b, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0858, 0x0854, 0x0850, 0x01eb, 0x01ec, 0x01ed),
+  },
+  {	.freq			= 5340,
+	RADIOREGS3(0x7c, 0x01, 0x01, 0x02, 0x16, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00,
+		   0xca, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b,
+		   0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77,
+		   0x00, 0x0b, 0x00, 0x6f, 0x00),
+	PHYREGS(0x085c, 0x0858, 0x0854, 0x01ea, 0x01eb, 0x01ec),
+  },
+  {	.freq			= 5350,
+	RADIOREGS3(0x7c, 0x01, 0x01, 0x02, 0x17, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00,
+		   0xca, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b,
+		   0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77,
+		   0x00, 0x0b, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0860, 0x085c, 0x0858, 0x01e9, 0x01ea, 0x01eb),
+  },
+  {	.freq			= 5360,
+	RADIOREGS3(0x75, 0x01, 0x01, 0x02, 0x18, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00,
+		   0xc9, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
+		   0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77,
+		   0x00, 0x0a, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0864, 0x0860, 0x085c, 0x01e8, 0x01e9, 0x01ea),
+  },
+  {	.freq			= 5370,
+	RADIOREGS3(0x75, 0x01, 0x01, 0x02, 0x19, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00,
+		   0xc9, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
+		   0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77,
+		   0x00, 0x0a, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0868, 0x0864, 0x0860, 0x01e7, 0x01e8, 0x01e9),
+  },
+  {	.freq			= 5380,
+	RADIOREGS3(0x6e, 0x01, 0x01, 0x02, 0x1a, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00,
+		   0xb8, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
+		   0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77,
+		   0x00, 0x0a, 0x00, 0x6f, 0x00),
+	PHYREGS(0x086c, 0x0868, 0x0864, 0x01e6, 0x01e7, 0x01e8),
+  },
+  {	.freq			= 5390,
+	RADIOREGS3(0x6e, 0x01, 0x01, 0x02, 0x1b, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00,
+		   0xb8, 0x84, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
+		   0x00, 0x6f, 0x00, 0x84, 0x00, 0x03, 0x00, 0x77,
+		   0x00, 0x0a, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0870, 0x086c, 0x0868, 0x01e5, 0x01e6, 0x01e7),
+  },
+  {	.freq			= 5400,
+	RADIOREGS3(0x67, 0x01, 0x01, 0x02, 0x1c, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00,
+		   0xb8, 0x84, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
+		   0x00, 0x6f, 0x00, 0x84, 0x00, 0x03, 0x00, 0x77,
+		   0x00, 0x0a, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0874, 0x0870, 0x086c, 0x01e5, 0x01e5, 0x01e6),
+  },
+  {	.freq			= 5410,
+	RADIOREGS3(0x67, 0x01, 0x01, 0x02, 0x1d, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00,
+		   0xb7, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a,
+		   0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77,
+		   0x00, 0x0a, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0878, 0x0874, 0x0870, 0x01e4, 0x01e5, 0x01e5),
+  },
+  {	.freq			= 5420,
+	RADIOREGS3(0x61, 0x01, 0x01, 0x02, 0x1e, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00,
+		   0xa7, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a,
+		   0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77,
+		   0x00, 0x0a, 0x00, 0x6f, 0x00),
+	PHYREGS(0x087c, 0x0878, 0x0874, 0x01e3, 0x01e4, 0x01e5),
+  },
+  {	.freq			= 5430,
+	RADIOREGS3(0x61, 0x01, 0x01, 0x02, 0x1f, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0b, 0x00,
+		   0xa6, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a,
+		   0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77,
+		   0x00, 0x0a, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0880, 0x087c, 0x0878, 0x01e2, 0x01e3, 0x01e4),
+  },
+  {	.freq			= 5440,
+	RADIOREGS3(0x5a, 0x01, 0x01, 0x02, 0x20, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00,
+		   0xa6, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x09,
+		   0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77,
+		   0x00, 0x09, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0884, 0x0880, 0x087c, 0x01e1, 0x01e2, 0x01e3),
+  },
+  {	.freq			= 5450,
+	RADIOREGS3(0x5a, 0x01, 0x01, 0x02, 0x21, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00,
+		   0x95, 0x84, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09,
+		   0x00, 0x6f, 0x00, 0x84, 0x00, 0x01, 0x00, 0x77,
+		   0x00, 0x09, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0888, 0x0884, 0x0880, 0x01e0, 0x01e1, 0x01e2),
+  },
+  {	.freq			= 5460,
+	RADIOREGS3(0x53, 0x01, 0x01, 0x02, 0x22, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00,
+		   0x95, 0x84, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09,
+		   0x00, 0x6f, 0x00, 0x84, 0x00, 0x01, 0x00, 0x77,
+		   0x00, 0x09, 0x00, 0x6f, 0x00),
+	PHYREGS(0x088c, 0x0888, 0x0884, 0x01df, 0x01e0, 0x01e1),
+  },
+  {	.freq			= 5470,
+	RADIOREGS3(0x53, 0x01, 0x01, 0x02, 0x23, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00,
+		   0x94, 0x73, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09,
+		   0x00, 0x6f, 0x00, 0x73, 0x00, 0x01, 0x00, 0x77,
+		   0x00, 0x09, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0890, 0x088c, 0x0888, 0x01de, 0x01df, 0x01e0),
+  },
+  {	.freq			= 5480,
+	RADIOREGS3(0x4d, 0x01, 0x01, 0x02, 0x24, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00,
+		   0x84, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+		   0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x09, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0894, 0x0890, 0x088c, 0x01dd, 0x01de, 0x01df),
+  },
+  {	.freq			= 5490,
+	RADIOREGS3(0x4d, 0x01, 0x01, 0x02, 0x25, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00,
+		   0x83, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+		   0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x09, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0898, 0x0894, 0x0890, 0x01dd, 0x01dd, 0x01de),
+  },
+  {	.freq			= 5500,
+	RADIOREGS3(0x47, 0x01, 0x01, 0x02, 0x26, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00,
+		   0x82, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+		   0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x09, 0x00, 0x6f, 0x00),
+	PHYREGS(0x089c, 0x0898, 0x0894, 0x01dc, 0x01dd, 0x01dd),
+  },
+  {	.freq			= 5510,
+	RADIOREGS3(0x47, 0x01, 0x01, 0x02, 0x27, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00,
+		   0x82, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+		   0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x09, 0x00, 0x6f, 0x00),
+	PHYREGS(0x08a0, 0x089c, 0x0898, 0x01db, 0x01dc, 0x01dd),
+  },
+  {	.freq			= 5520,
+	RADIOREGS3(0x40, 0x01, 0x01, 0x02, 0x28, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00,
+		   0x72, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+		   0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x09, 0x00, 0x6f, 0x00),
+	PHYREGS(0x08a4, 0x08a0, 0x089c, 0x01da, 0x01db, 0x01dc),
+  },
+  {	.freq			= 5530,
+	RADIOREGS3(0x40, 0x01, 0x01, 0x02, 0x29, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x09, 0x00,
+		   0x72, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+		   0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x09, 0x00, 0x6f, 0x00),
+	PHYREGS(0x08a8, 0x08a4, 0x08a0, 0x01d9, 0x01da, 0x01db),
+  },
+  {	.freq			= 5540,
+	RADIOREGS3(0x3a, 0x01, 0x01, 0x02, 0x2a, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x09, 0x00,
+		   0x71, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+		   0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x09, 0x00, 0x6f, 0x00),
+	PHYREGS(0x08ac, 0x08a8, 0x08a4, 0x01d8, 0x01d9, 0x01da),
+  },
+  {	.freq			= 5550,
+	RADIOREGS3(0x3a, 0x01, 0x01, 0x02, 0x2b, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x89, 0x09, 0x00,
+		   0x61, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+		   0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x09, 0x00, 0x6f, 0x00),
+	PHYREGS(0x08b0, 0x08ac, 0x08a8, 0x01d7, 0x01d8, 0x01d9),
+  },
+  {	.freq			= 5560,
+	RADIOREGS3(0x34, 0x01, 0x01, 0x02, 0x2c, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x89, 0x09, 0x00,
+		   0x61, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+		   0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x09, 0x00, 0x6f, 0x00),
+	PHYREGS(0x08b4, 0x08b0, 0x08ac, 0x01d7, 0x01d7, 0x01d8),
+  },
+  {	.freq			= 5570,
+	RADIOREGS3(0x34, 0x01, 0x01, 0x02, 0x2d, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x89, 0x09, 0x00,
+		   0x61, 0x62, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+		   0x00, 0x6f, 0x00, 0x62, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x09, 0x00, 0x6f, 0x00),
+	PHYREGS(0x08b8, 0x08b4, 0x08b0, 0x01d6, 0x01d7, 0x01d7),
+  },
+  {	.freq			= 5580,
+	RADIOREGS3(0x2e, 0x01, 0x01, 0x02, 0x2e, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x89, 0x08, 0x00,
+		   0x60, 0x62, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08,
+		   0x00, 0x6f, 0x00, 0x62, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x08, 0x00, 0x6f, 0x00),
+	PHYREGS(0x08bc, 0x08b8, 0x08b4, 0x01d5, 0x01d6, 0x01d7),
+  },
+  {	.freq			= 5590,
+	RADIOREGS3(0x2e, 0x01, 0x01, 0x02, 0x2f, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x89, 0x08, 0x00,
+		   0x50, 0x61, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08,
+		   0x00, 0x6f, 0x00, 0x61, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x08, 0x00, 0x6f, 0x00),
+	PHYREGS(0x08c0, 0x08bc, 0x08b8, 0x01d4, 0x01d5, 0x01d6),
+  },
+  {	.freq			= 5600,
+	RADIOREGS3(0x28, 0x01, 0x01, 0x02, 0x30, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x89, 0x08, 0x00,
+		   0x50, 0x51, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08,
+		   0x00, 0x6f, 0x00, 0x51, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x08, 0x00, 0x6f, 0x00),
+	PHYREGS(0x08c4, 0x08c0, 0x08bc, 0x01d3, 0x01d4, 0x01d5),
+  },
+  {	.freq			= 5610,
+	RADIOREGS3(0x28, 0x01, 0x01, 0x02, 0x31, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x89, 0x08, 0x00,
+		   0x50, 0x51, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08,
+		   0x00, 0x6f, 0x00, 0x51, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x08, 0x00, 0x6f, 0x00),
+	PHYREGS(0x08c8, 0x08c4, 0x08c0, 0x01d2, 0x01d3, 0x01d4),
+  },
+  {	.freq			= 5620,
+	RADIOREGS3(0x21, 0x01, 0x01, 0x02, 0x32, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x89, 0x08, 0x00,
+		   0x50, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07,
+		   0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x07, 0x00, 0x6f, 0x00),
+	PHYREGS(0x08cc, 0x08c8, 0x08c4, 0x01d2, 0x01d2, 0x01d3),
+  },
+  {	.freq			= 5630,
+	RADIOREGS3(0x21, 0x01, 0x01, 0x02, 0x33, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x88, 0x07, 0x00,
+		   0x50, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07,
+		   0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x07, 0x00, 0x6f, 0x00),
+	PHYREGS(0x08d0, 0x08cc, 0x08c8, 0x01d1, 0x01d2, 0x01d2),
+  },
+  {	.freq			= 5640,
+	RADIOREGS3(0x1c, 0x01, 0x01, 0x02, 0x34, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x88, 0x07, 0x00,
+		   0x40, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07,
+		   0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x07, 0x00, 0x6f, 0x00),
+	PHYREGS(0x08d4, 0x08d0, 0x08cc, 0x01d0, 0x01d1, 0x01d2),
+  },
+  {	.freq			= 5650,
+	RADIOREGS3(0x1c, 0x01, 0x01, 0x02, 0x35, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x88, 0x07, 0x00,
+		   0x40, 0x40, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07,
+		   0x00, 0x6f, 0x00, 0x40, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x07, 0x00, 0x6f, 0x00),
+	PHYREGS(0x08d8, 0x08d4, 0x08d0, 0x01cf, 0x01d0, 0x01d1),
+  },
+  {	.freq			= 5660,
+	RADIOREGS3(0x16, 0x01, 0x01, 0x02, 0x36, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x88, 0x07, 0x00,
+		   0x40, 0x40, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+		   0x00, 0x6f, 0x00, 0x40, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x06, 0x00, 0x6f, 0x00),
+	PHYREGS(0x08dc, 0x08d8, 0x08d4, 0x01ce, 0x01cf, 0x01d0),
+  },
+  {	.freq			= 5670,
+	RADIOREGS3(0x16, 0x01, 0x01, 0x02, 0x37, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x88, 0x07, 0x00,
+		   0x40, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+		   0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x06, 0x00, 0x6f, 0x00),
+	PHYREGS(0x08e0, 0x08dc, 0x08d8, 0x01ce, 0x01ce, 0x01cf),
+  },
+  {	.freq			= 5680,
+	RADIOREGS3(0x10, 0x01, 0x01, 0x02, 0x38, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x06, 0x00,
+		   0x30, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+		   0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x06, 0x00, 0x6f, 0x00),
+	PHYREGS(0x08e4, 0x08e0, 0x08dc, 0x01cd, 0x01ce, 0x01ce),
+  },
+  {	.freq			= 5690,
+	RADIOREGS3(0x10, 0x01, 0x01, 0x02, 0x39, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x06, 0x00,
+		   0x30, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+		   0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x06, 0x00, 0x6f, 0x00),
+	PHYREGS(0x08e8, 0x08e4, 0x08e0, 0x01cc, 0x01cd, 0x01ce),
+  },
+  {	.freq			= 5700,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3a, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x06, 0x00,
+		   0x30, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+		   0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x06, 0x00, 0x6e, 0x00),
+	PHYREGS(0x08ec, 0x08e8, 0x08e4, 0x01cb, 0x01cc, 0x01cd),
+  },
+  {	.freq			= 5710,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3b, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x06, 0x00,
+		   0x30, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+		   0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x06, 0x00, 0x6e, 0x00),
+	PHYREGS(0x08f0, 0x08ec, 0x08e8, 0x01ca, 0x01cb, 0x01cc),
+  },
+  {	.freq			= 5720,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3c, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x06, 0x00,
+		   0x30, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+		   0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x06, 0x00, 0x6e, 0x00),
+	PHYREGS(0x08f4, 0x08f0, 0x08ec, 0x01c9, 0x01ca, 0x01cb),
+  },
+  {	.freq			= 5725,
+	RADIOREGS3(0x03, 0x01, 0x02, 0x04, 0x79, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x05, 0x05, 0x05, 0x87, 0x06, 0x00,
+		   0x30, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+		   0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x06, 0x00, 0x6e, 0x00),
+	PHYREGS(0x08f6, 0x08f2, 0x08ee, 0x01c9, 0x01ca, 0x01cb),
+  },
+  {	.freq			= 5730,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3d, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x05, 0x00,
+		   0x20, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+		   0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x06, 0x00, 0x6e, 0x00),
+	PHYREGS(0x08f8, 0x08f4, 0x08f0, 0x01c9, 0x01c9, 0x01ca),
+  },
+  {	.freq			= 5735,
+	RADIOREGS3(0x03, 0x01, 0x02, 0x04, 0x7b, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x05, 0x05, 0x05, 0x87, 0x05, 0x00,
+		   0x20, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+		   0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x06, 0x00, 0x6d, 0x00),
+	PHYREGS(0x08fa, 0x08f6, 0x08f2, 0x01c8, 0x01c9, 0x01ca),
+  },
+  {	.freq			= 5740,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3e, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x05, 0x00,
+		   0x20, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+		   0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x06, 0x00, 0x6d, 0x00),
+	PHYREGS(0x08fc, 0x08f8, 0x08f4, 0x01c8, 0x01c9, 0x01c9),
+  },
+  {	.freq			= 5745,
+	RADIOREGS3(0xfe, 0x00, 0x02, 0x04, 0x7d, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x05, 0x05, 0x05, 0x87, 0x05, 0x00,
+		   0x20, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+		   0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x06, 0x00, 0x6d, 0x00),
+	PHYREGS(0x08fe, 0x08fa, 0x08f6, 0x01c8, 0x01c8, 0x01c9),
+  },
+  {	.freq			= 5750,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3f, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x05, 0x00,
+		   0x20, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+		   0x00, 0x6d, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x05, 0x00, 0x6d, 0x00),
+	PHYREGS(0x0900, 0x08fc, 0x08f8, 0x01c7, 0x01c8, 0x01c9),
+  },
+  {	.freq			= 5755,
+	RADIOREGS3(0xfe, 0x00, 0x02, 0x04, 0x7f, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x05, 0x05, 0x05, 0x87, 0x05, 0x00,
+		   0x10, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+		   0x00, 0x6c, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x05, 0x00, 0x6c, 0x00),
+	PHYREGS(0x0902, 0x08fe, 0x08fa, 0x01c7, 0x01c8, 0x01c8),
+  },
+  {	.freq			= 5760,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x40, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x86, 0x05, 0x00,
+		   0x10, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+		   0x00, 0x6c, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x05, 0x00, 0x6c, 0x00),
+	PHYREGS(0x0904, 0x0900, 0x08fc, 0x01c6, 0x01c7, 0x01c8),
+  },
+  {	.freq			= 5765,
+	RADIOREGS3(0xf8, 0x00, 0x02, 0x04, 0x81, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x05, 0x05, 0x05, 0x86, 0x05, 0x00,
+		   0x10, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+		   0x00, 0x6c, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x05, 0x00, 0x6c, 0x00),
+	PHYREGS(0x0906, 0x0902, 0x08fe, 0x01c6, 0x01c7, 0x01c8),
+  },
+  {	.freq			= 5770,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x41, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x86, 0x04, 0x00,
+		   0x10, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+		   0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x05, 0x00, 0x6b, 0x00),
+	PHYREGS(0x0908, 0x0904, 0x0900, 0x01c6, 0x01c6, 0x01c7),
+  },
+  {	.freq			= 5775,
+	RADIOREGS3(0xf8, 0x00, 0x02, 0x04, 0x83, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x05, 0x05, 0x05, 0x86, 0x04, 0x00,
+		   0x10, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+		   0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x05, 0x00, 0x6b, 0x00),
+	PHYREGS(0x090a, 0x0906, 0x0902, 0x01c5, 0x01c6, 0x01c7),
+  },
+  {	.freq			= 5780,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x42, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x86, 0x04, 0x00,
+		   0x10, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+		   0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x05, 0x00, 0x6b, 0x00),
+	PHYREGS(0x090c, 0x0908, 0x0904, 0x01c5, 0x01c6, 0x01c6),
+  },
+  {	.freq			= 5785,
+	RADIOREGS3(0xf2, 0x00, 0x02, 0x04, 0x85, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00,
+		   0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+		   0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x05, 0x00, 0x6b, 0x00),
+	PHYREGS(0x090e, 0x090a, 0x0906, 0x01c4, 0x01c5, 0x01c6),
+  },
+  {	.freq			= 5790,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x43, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00,
+		   0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+		   0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x05, 0x00, 0x6b, 0x00),
+	PHYREGS(0x0910, 0x090c, 0x0908, 0x01c4, 0x01c5, 0x01c6),
+  },
+  {	.freq			= 5795,
+	RADIOREGS3(0xf2, 0x00, 0x02, 0x04, 0x87, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00,
+		   0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+		   0x00, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x05, 0x00, 0x6b, 0x00),
+	PHYREGS(0x0912, 0x090e, 0x090a, 0x01c4, 0x01c4, 0x01c5),
+  },
+  {	.freq			= 5800,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x44, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00,
+		   0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+		   0x00, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x05, 0x00, 0x6b, 0x00),
+	PHYREGS(0x0914, 0x0910, 0x090c, 0x01c3, 0x01c4, 0x01c5),
+  },
+  {	.freq			= 5805,
+	RADIOREGS3(0xed, 0x00, 0x02, 0x04, 0x89, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00,
+		   0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+		   0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x05, 0x00, 0x6a, 0x00),
+	PHYREGS(0x0916, 0x0912, 0x090e, 0x01c3, 0x01c4, 0x01c4),
+  },
+  {	.freq			= 5810,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x45, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00,
+		   0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+		   0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x05, 0x00, 0x6a, 0x00),
+	PHYREGS(0x0918, 0x0914, 0x0910, 0x01c2, 0x01c3, 0x01c4),
+  },
+  {	.freq			= 5815,
+	RADIOREGS3(0xed, 0x00, 0x02, 0x04, 0x8b, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00,
+		   0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+		   0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x05, 0x00, 0x6a, 0x00),
+	PHYREGS(0x091a, 0x0916, 0x0912, 0x01c2, 0x01c3, 0x01c4),
+  },
+  {	.freq			= 5820,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x46, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00,
+		   0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+		   0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x05, 0x00, 0x6a, 0x00),
+	PHYREGS(0x091c, 0x0918, 0x0914, 0x01c2, 0x01c2, 0x01c3),
+  },
+  {	.freq			= 5825,
+	RADIOREGS3(0xed, 0x00, 0x02, 0x04, 0x8d, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00,
+		   0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+		   0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x05, 0x00, 0x69, 0x00),
+	PHYREGS(0x091e, 0x091a, 0x0916, 0x01c1, 0x01c2, 0x01c3),
+  },
+  {	.freq			= 5830,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x47, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00,
+		   0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+		   0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x05, 0x00, 0x69, 0x00),
+	PHYREGS(0x0920, 0x091c, 0x0918, 0x01c1, 0x01c2, 0x01c2),
+  },
+  {	.freq			= 5840,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x48, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00,
+		   0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+		   0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x04, 0x00, 0x69, 0x00),
+	PHYREGS(0x0924, 0x0920, 0x091c, 0x01c0, 0x01c1, 0x01c2),
+  },
+  {	.freq			= 5850,
+	RADIOREGS3(0xe0, 0x00, 0x01, 0x02, 0x49, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00,
+		   0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+		   0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x04, 0x00, 0x69, 0x00),
+	PHYREGS(0x0928, 0x0924, 0x0920, 0x01bf, 0x01c0, 0x01c1),
+  },
+  {	.freq			= 5860,
+	RADIOREGS3(0xde, 0x00, 0x01, 0x02, 0x4a, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00,
+		   0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+		   0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x04, 0x00, 0x69, 0x00),
+	PHYREGS(0x092c, 0x0928, 0x0924, 0x01bf, 0x01bf, 0x01c0),
+  },
+  {	.freq			= 5870,
+	RADIOREGS3(0xdb, 0x00, 0x01, 0x02, 0x4b, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00,
+		   0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+		   0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x04, 0x00, 0x68, 0x00),
+	PHYREGS(0x0930, 0x092c, 0x0928, 0x01be, 0x01bf, 0x01bf),
+  },
+  {	.freq			= 5880,
+	RADIOREGS3(0xd8, 0x00, 0x01, 0x02, 0x4c, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00,
+		   0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+		   0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x04, 0x00, 0x68, 0x00),
+	PHYREGS(0x0934, 0x0930, 0x092c, 0x01bd, 0x01be, 0x01bf),
+  },
+  {	.freq			= 5890,
+	RADIOREGS3(0xd6, 0x00, 0x01, 0x02, 0x4d, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00,
+		   0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+		   0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x04, 0x00, 0x68, 0x00),
+	PHYREGS(0x0938, 0x0934, 0x0930, 0x01bc, 0x01bd, 0x01be),
+  },
+  {	.freq			= 5900,
+	RADIOREGS3(0xd3, 0x00, 0x01, 0x02, 0x4e, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00,
+		   0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+		   0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x04, 0x00, 0x68, 0x00),
+	PHYREGS(0x093c, 0x0938, 0x0934, 0x01bc, 0x01bc, 0x01bd),
+  },
+  {	.freq			= 5910,
+	RADIOREGS3(0xd6, 0x00, 0x01, 0x02, 0x4f, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00,
+		   0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+		   0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x04, 0x00, 0x68, 0x00),
+	PHYREGS(0x0940, 0x093c, 0x0938, 0x01bb, 0x01bc, 0x01bc),
+  },
+  {	.freq			= 2412,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x6c, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x04, 0x04, 0x04, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x78, 0x00, 0x03, 0x00, 0x70, 0x00,
+		   0x0b, 0x00, 0x0a, 0x00, 0x78, 0x00, 0x03, 0x00,
+		   0x70, 0x00, 0x0b, 0x00, 0x0a),
+	PHYREGS(0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443),
+  },
+  {	.freq			= 2417,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x71, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x78, 0x00, 0x03, 0x00, 0x70, 0x00,
+		   0x0b, 0x00, 0x0a, 0x00, 0x78, 0x00, 0x03, 0x00,
+		   0x70, 0x00, 0x0b, 0x00, 0x0a),
+	PHYREGS(0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441),
+  },
+  {	.freq			= 2422,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x76, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x67, 0x00, 0x03, 0x00, 0x70, 0x00,
+		   0x0b, 0x00, 0x0a, 0x00, 0x67, 0x00, 0x03, 0x00,
+		   0x70, 0x00, 0x0b, 0x00, 0x0a),
+	PHYREGS(0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f),
+  },
+  {	.freq			= 2427,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x7b, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x57, 0x00, 0x03, 0x00, 0x70, 0x00,
+		   0x0a, 0x00, 0x0a, 0x00, 0x57, 0x00, 0x03, 0x00,
+		   0x70, 0x00, 0x0a, 0x00, 0x0a),
+	PHYREGS(0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d),
+  },
+  {	.freq			= 2432,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x80, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x56, 0x00, 0x03, 0x00, 0x70, 0x00,
+		   0x0a, 0x00, 0x0a, 0x00, 0x56, 0x00, 0x03, 0x00,
+		   0x70, 0x00, 0x0a, 0x00, 0x0a),
+	PHYREGS(0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a),
+  },
+  {	.freq			= 2437,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x85, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x46, 0x00, 0x03, 0x00, 0x70, 0x00,
+		   0x0a, 0x00, 0x0a, 0x00, 0x46, 0x00, 0x03, 0x00,
+		   0x70, 0x00, 0x0a, 0x00, 0x0a),
+	PHYREGS(0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438),
+  },
+  {	.freq			= 2442,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x8a, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x45, 0x00, 0x02, 0x00, 0x70, 0x00,
+		   0x0a, 0x00, 0x0a, 0x00, 0x45, 0x00, 0x02, 0x00,
+		   0x70, 0x00, 0x0a, 0x00, 0x0a),
+	PHYREGS(0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436),
+  },
+  {	.freq			= 2447,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x8f, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x34, 0x00, 0x02, 0x00, 0x70, 0x00,
+		   0x0a, 0x00, 0x09, 0x00, 0x34, 0x00, 0x02, 0x00,
+		   0x70, 0x00, 0x0a, 0x00, 0x09),
+	PHYREGS(0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434),
+  },
+  {	.freq			= 2452,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x94, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x23, 0x00, 0x02, 0x00, 0x70, 0x00,
+		   0x0a, 0x00, 0x09, 0x00, 0x23, 0x00, 0x02, 0x00,
+		   0x70, 0x00, 0x0a, 0x00, 0x09),
+	PHYREGS(0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431),
+  },
+  {	.freq			= 2457,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x99, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x12, 0x00, 0x02, 0x00, 0x70, 0x00,
+		   0x0a, 0x00, 0x09, 0x00, 0x12, 0x00, 0x02, 0x00,
+		   0x70, 0x00, 0x0a, 0x00, 0x09),
+	PHYREGS(0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f),
+  },
+  {	.freq			= 2462,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x9e, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x70, 0x00,
+		   0x09, 0x00, 0x09, 0x00, 0x02, 0x00, 0x02, 0x00,
+		   0x70, 0x00, 0x09, 0x00, 0x09),
+	PHYREGS(0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d),
+  },
+  {	.freq			= 2467,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0xa3, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x70, 0x00,
+		   0x09, 0x00, 0x09, 0x00, 0x01, 0x00, 0x02, 0x00,
+		   0x70, 0x00, 0x09, 0x00, 0x09),
+	PHYREGS(0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b),
+  },
+  {	.freq			= 2472,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0xa8, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x70, 0x00,
+		   0x09, 0x00, 0x09, 0x00, 0x01, 0x00, 0x02, 0x00,
+		   0x70, 0x00, 0x09, 0x00, 0x09),
+	PHYREGS(0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429),
+  },
+  {	.freq			= 2484,
+	RADIOREGS3(0xff, 0x01, 0x03, 0x09, 0xb4, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x07, 0x07, 0x07, 0x8f, 0x20, 0x00,
+		   0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x70, 0x00,
+		   0x09, 0x00, 0x09, 0x00, 0x00, 0x00, 0x02, 0x00,
+		   0x70, 0x00, 0x09, 0x00, 0x09),
+	PHYREGS(0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424),
+  },
+};
+
+static const struct b43_nphy_channeltab_entry_rev3 b43_nphy_channeltab_rev7_9[] = {
+  {	.freq			= 4920,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0f,
+		   0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70,
+		   0x00, 0x0f, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07b4, 0x07b0, 0x07ac, 0x0214, 0x0215, 0x0216),
+  },
+  {	.freq			= 4930,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xed, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0e,
+		   0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70,
+		   0x00, 0x0e, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07b8, 0x07b4, 0x07b0, 0x0213, 0x0214, 0x0215),
+  },
+  {	.freq			= 4940,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xee, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0e,
+		   0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70,
+		   0x00, 0x0e, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07bc, 0x07b8, 0x07b4, 0x0212, 0x0213, 0x0214),
+  },
+  {	.freq			= 4950,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xef, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0e,
+		   0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70,
+		   0x00, 0x0e, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07c0, 0x07bc, 0x07b8, 0x0211, 0x0212, 0x0213),
+  },
+  {	.freq			= 4960,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf0, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0e,
+		   0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70,
+		   0x00, 0x0e, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07c4, 0x07c0, 0x07bc, 0x020f, 0x0211, 0x0212),
+  },
+  {	.freq			= 4970,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf1, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d,
+		   0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70,
+		   0x00, 0x0d, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07c8, 0x07c4, 0x07c0, 0x020e, 0x020f, 0x0211),
+  },
+  {	.freq			= 4980,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf2, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d,
+		   0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70,
+		   0x00, 0x0d, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07cc, 0x07c8, 0x07c4, 0x020d, 0x020e, 0x020f),
+  },
+  {	.freq			= 4990,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf3, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d,
+		   0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70,
+		   0x00, 0x0d, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07d0, 0x07cc, 0x07c8, 0x020c, 0x020d, 0x020e),
+  },
+  {	.freq			= 5000,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf4, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d,
+		   0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70,
+		   0x00, 0x0d, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07d4, 0x07d0, 0x07cc, 0x020b, 0x020c, 0x020d),
+  },
+  {	.freq			= 5010,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf5, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d,
+		   0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70,
+		   0x00, 0x0d, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07d8, 0x07d4, 0x07d0, 0x020a, 0x020b, 0x020c),
+  },
+  {	.freq			= 5020,
+	RADIOREGS3(0xf7, 0x01, 0x01, 0x01, 0xf6, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0d,
+		   0x00, 0x9f, 0x00, 0xff, 0x00, 0x09, 0x00, 0x70,
+		   0x00, 0x0d, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07dc, 0x07d8, 0x07d4, 0x0209, 0x020a, 0x020b),
+  },
+  {	.freq			= 5030,
+	RADIOREGS3(0xf7, 0x01, 0x01, 0x01, 0xf7, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c,
+		   0x00, 0x9f, 0x00, 0xff, 0x00, 0x09, 0x00, 0x70,
+		   0x00, 0x0c, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07e0, 0x07dc, 0x07d8, 0x0208, 0x0209, 0x020a),
+  },
+  {	.freq			= 5040,
+	RADIOREGS3(0xef, 0x01, 0x01, 0x01, 0xf8, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfe, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c,
+		   0x00, 0x9f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x70,
+		   0x00, 0x0c, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07e4, 0x07e0, 0x07dc, 0x0207, 0x0208, 0x0209),
+  },
+  {	.freq			= 5050,
+	RADIOREGS3(0xef, 0x01, 0x01, 0x01, 0xf9, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfe, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c,
+		   0x00, 0x9f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x70,
+		   0x00, 0x0c, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07e8, 0x07e4, 0x07e0, 0x0206, 0x0207, 0x0208),
+  },
+  {	.freq			= 5060,
+	RADIOREGS3(0xe6, 0x01, 0x01, 0x01, 0xfa, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfd, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c,
+		   0x00, 0x9f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x70,
+		   0x00, 0x0c, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07ec, 0x07e8, 0x07e4, 0x0205, 0x0206, 0x0207),
+  },
+  {	.freq			= 5070,
+	RADIOREGS3(0xe6, 0x01, 0x01, 0x01, 0xfb, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfd, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b,
+		   0x00, 0x9f, 0x00, 0xfd, 0x00, 0x08, 0x00, 0x70,
+		   0x00, 0x0b, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07f0, 0x07ec, 0x07e8, 0x0204, 0x0205, 0x0206),
+  },
+  {	.freq			= 5080,
+	RADIOREGS3(0xde, 0x01, 0x01, 0x01, 0xfc, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b,
+		   0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70,
+		   0x00, 0x0b, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07f4, 0x07f0, 0x07ec, 0x0203, 0x0204, 0x0205),
+  },
+  {	.freq			= 5090,
+	RADIOREGS3(0xde, 0x01, 0x01, 0x01, 0xfd, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b,
+		   0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70,
+		   0x00, 0x0b, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07f8, 0x07f4, 0x07f0, 0x0202, 0x0203, 0x0204),
+  },
+  {	.freq			= 5100,
+	RADIOREGS3(0xd6, 0x01, 0x01, 0x01, 0xfe, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b,
+		   0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70,
+		   0x00, 0x0b, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07fc, 0x07f8, 0x07f4, 0x0201, 0x0202, 0x0203),
+  },
+  {	.freq			= 5110,
+	RADIOREGS3(0xd6, 0x01, 0x01, 0x01, 0xff, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b,
+		   0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70,
+		   0x00, 0x0b, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0800, 0x07fc, 0x07f8, 0x0200, 0x0201, 0x0202),
+  },
+  {	.freq			= 5120,
+	RADIOREGS3(0xce, 0x01, 0x01, 0x02, 0x00, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b,
+		   0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70,
+		   0x00, 0x0b, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0804, 0x0800, 0x07fc, 0x01ff, 0x0200, 0x0201),
+  },
+  {	.freq			= 5130,
+	RADIOREGS3(0xce, 0x01, 0x01, 0x02, 0x01, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfb, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0a,
+		   0x00, 0x9f, 0x00, 0xfb, 0x00, 0x08, 0x00, 0x70,
+		   0x00, 0x0a, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0808, 0x0804, 0x0800, 0x01fe, 0x01ff, 0x0200),
+  },
+  {	.freq			= 5140,
+	RADIOREGS3(0xc6, 0x01, 0x01, 0x02, 0x02, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfb, 0x00, 0x07, 0x00, 0x70, 0x00, 0x0a,
+		   0x00, 0x9f, 0x00, 0xfb, 0x00, 0x07, 0x00, 0x70,
+		   0x00, 0x0a, 0x00, 0x6f, 0x00),
+	PHYREGS(0x080c, 0x0808, 0x0804, 0x01fd, 0x01fe, 0x01ff),
+  },
+  {	.freq			= 5160,
+	RADIOREGS3(0xbe, 0x01, 0x01, 0x02, 0x04, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfb, 0x00, 0x07, 0x00, 0x70, 0x00, 0x09,
+		   0x00, 0x9e, 0x00, 0xfb, 0x00, 0x07, 0x00, 0x70,
+		   0x00, 0x09, 0x00, 0x6e, 0x00),
+	PHYREGS(0x0814, 0x0810, 0x080c, 0x01fb, 0x01fc, 0x01fd),
+  },
+  {	.freq			= 5170,
+	RADIOREGS3(0xbe, 0x01, 0x01, 0x02, 0x05, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfb, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09,
+		   0x00, 0x9e, 0x00, 0xfb, 0x00, 0x06, 0x00, 0x70,
+		   0x00, 0x09, 0x00, 0x6e, 0x00),
+	PHYREGS(0x0818, 0x0814, 0x0810, 0x01fa, 0x01fb, 0x01fc),
+  },
+  {	.freq			= 5180,
+	RADIOREGS3(0xb6, 0x01, 0x01, 0x02, 0x06, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09,
+		   0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70,
+		   0x00, 0x09, 0x00, 0x6e, 0x00),
+	PHYREGS(0x081c, 0x0818, 0x0814, 0x01f9, 0x01fa, 0x01fb),
+  },
+  {	.freq			= 5190,
+	RADIOREGS3(0xb6, 0x01, 0x01, 0x02, 0x07, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09,
+		   0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70,
+		   0x00, 0x09, 0x00, 0x6e, 0x00),
+	PHYREGS(0x0820, 0x081c, 0x0818, 0x01f8, 0x01f9, 0x01fa),
+  },
+  {	.freq			= 5200,
+	RADIOREGS3(0xaf, 0x01, 0x01, 0x02, 0x08, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09,
+		   0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70,
+		   0x00, 0x09, 0x00, 0x6e, 0x00),
+	PHYREGS(0x0824, 0x0820, 0x081c, 0x01f7, 0x01f8, 0x01f9),
+  },
+  {	.freq			= 5210,
+	RADIOREGS3(0xaf, 0x01, 0x01, 0x02, 0x09, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09,
+		   0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70,
+		   0x00, 0x09, 0x00, 0x6e, 0x00),
+	PHYREGS(0x0828, 0x0824, 0x0820, 0x01f6, 0x01f7, 0x01f8),
+  },
+  {	.freq			= 5220,
+	RADIOREGS3(0xa7, 0x01, 0x01, 0x02, 0x0a, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00,
+		   0xfe, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09,
+		   0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70,
+		   0x00, 0x09, 0x00, 0x6e, 0x00),
+	PHYREGS(0x082c, 0x0828, 0x0824, 0x01f5, 0x01f6, 0x01f7),
+  },
+  {	.freq			= 5230,
+	RADIOREGS3(0xa7, 0x01, 0x01, 0x02, 0x0b, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00,
+		   0xee, 0xea, 0x00, 0x06, 0x00, 0x70, 0x00, 0x08,
+		   0x00, 0x9e, 0x00, 0xea, 0x00, 0x06, 0x00, 0x70,
+		   0x00, 0x08, 0x00, 0x6e, 0x00),
+	PHYREGS(0x0830, 0x082c, 0x0828, 0x01f4, 0x01f5, 0x01f6),
+  },
+  {	.freq			= 5240,
+	RADIOREGS3(0xa0, 0x01, 0x01, 0x02, 0x0c, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00,
+		   0xee, 0xe9, 0x00, 0x05, 0x00, 0x70, 0x00, 0x08,
+		   0x00, 0x9d, 0x00, 0xe9, 0x00, 0x05, 0x00, 0x70,
+		   0x00, 0x08, 0x00, 0x6d, 0x00),
+	PHYREGS(0x0834, 0x0830, 0x082c, 0x01f3, 0x01f4, 0x01f5),
+  },
+  {	.freq			= 5250,
+	RADIOREGS3(0xa0, 0x01, 0x01, 0x02, 0x0d, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00,
+		   0xed, 0xe9, 0x00, 0x05, 0x00, 0x70, 0x00, 0x08,
+		   0x00, 0x9d, 0x00, 0xe9, 0x00, 0x05, 0x00, 0x70,
+		   0x00, 0x08, 0x00, 0x6d, 0x00),
+	PHYREGS(0x0838, 0x0834, 0x0830, 0x01f2, 0x01f3, 0x01f4),
+  },
+  {	.freq			= 5260,
+	RADIOREGS3(0x98, 0x01, 0x01, 0x02, 0x0e, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8e, 0x0e, 0x00,
+		   0xed, 0xd9, 0x00, 0x05, 0x00, 0x70, 0x00, 0x08,
+		   0x00, 0x9d, 0x00, 0xd9, 0x00, 0x05, 0x00, 0x70,
+		   0x00, 0x08, 0x00, 0x6d, 0x00),
+	PHYREGS(0x083c, 0x0838, 0x0834, 0x01f1, 0x01f2, 0x01f3),
+  },
+  {	.freq			= 5270,
+	RADIOREGS3(0x98, 0x01, 0x01, 0x02, 0x0f, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8e, 0x0e, 0x00,
+		   0xed, 0xd8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
+		   0x00, 0x9c, 0x00, 0xd8, 0x00, 0x04, 0x00, 0x70,
+		   0x00, 0x07, 0x00, 0x6c, 0x00),
+	PHYREGS(0x0840, 0x083c, 0x0838, 0x01f0, 0x01f1, 0x01f2),
+  },
+  {	.freq			= 5280,
+	RADIOREGS3(0x91, 0x01, 0x01, 0x02, 0x10, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00,
+		   0xdc, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
+		   0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70,
+		   0x00, 0x07, 0x00, 0x6c, 0x00),
+	PHYREGS(0x0844, 0x0840, 0x083c, 0x01f0, 0x01f0, 0x01f1),
+  },
+  {	.freq			= 5290,
+	RADIOREGS3(0x91, 0x01, 0x01, 0x02, 0x11, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00,
+		   0xdc, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
+		   0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70,
+		   0x00, 0x07, 0x00, 0x6c, 0x00),
+	PHYREGS(0x0848, 0x0844, 0x0840, 0x01ef, 0x01f0, 0x01f0),
+  },
+  {	.freq			= 5300,
+	RADIOREGS3(0x8a, 0x01, 0x01, 0x02, 0x12, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00,
+		   0xdc, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
+		   0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70,
+		   0x00, 0x07, 0x00, 0x6c, 0x00),
+	PHYREGS(0x084c, 0x0848, 0x0844, 0x01ee, 0x01ef, 0x01f0),
+  },
+  {	.freq			= 5310,
+	RADIOREGS3(0x8a, 0x01, 0x01, 0x02, 0x13, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00,
+		   0xdc, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
+		   0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70,
+		   0x00, 0x07, 0x00, 0x6c, 0x00),
+	PHYREGS(0x0850, 0x084c, 0x0848, 0x01ed, 0x01ee, 0x01ef),
+  },
+  {	.freq			= 5320,
+	RADIOREGS3(0x83, 0x01, 0x01, 0x02, 0x14, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00,
+		   0xdb, 0xb8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
+		   0x00, 0x9c, 0x00, 0xb8, 0x00, 0x04, 0x00, 0x70,
+		   0x00, 0x07, 0x00, 0x6c, 0x00),
+	PHYREGS(0x0854, 0x0850, 0x084c, 0x01ec, 0x01ed, 0x01ee),
+  },
+  {	.freq			= 5330,
+	RADIOREGS3(0x83, 0x01, 0x01, 0x02, 0x15, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00,
+		   0xcb, 0xb7, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
+		   0x00, 0x9b, 0x00, 0xb7, 0x00, 0x04, 0x00, 0x70,
+		   0x00, 0x07, 0x00, 0x6b, 0x00),
+	PHYREGS(0x0858, 0x0854, 0x0850, 0x01eb, 0x01ec, 0x01ed),
+  },
+  {	.freq			= 5340,
+	RADIOREGS3(0x7c, 0x01, 0x01, 0x02, 0x16, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00,
+		   0xca, 0xb7, 0x00, 0x03, 0x00, 0x70, 0x00, 0x07,
+		   0x00, 0x9b, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x70,
+		   0x00, 0x07, 0x00, 0x6b, 0x00),
+	PHYREGS(0x085c, 0x0858, 0x0854, 0x01ea, 0x01eb, 0x01ec),
+  },
+  {	.freq			= 5350,
+	RADIOREGS3(0x7c, 0x01, 0x01, 0x02, 0x17, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00,
+		   0xca, 0xa7, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06,
+		   0x00, 0x9b, 0x00, 0xa7, 0x00, 0x03, 0x00, 0x70,
+		   0x00, 0x06, 0x00, 0x6b, 0x00),
+	PHYREGS(0x0860, 0x085c, 0x0858, 0x01e9, 0x01ea, 0x01eb),
+  },
+  {	.freq			= 5360,
+	RADIOREGS3(0x75, 0x01, 0x01, 0x02, 0x18, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00,
+		   0xc9, 0xa6, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06,
+		   0x00, 0x9b, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x70,
+		   0x00, 0x06, 0x00, 0x6b, 0x00),
+	PHYREGS(0x0864, 0x0860, 0x085c, 0x01e8, 0x01e9, 0x01ea),
+  },
+  {	.freq			= 5370,
+	RADIOREGS3(0x75, 0x01, 0x01, 0x02, 0x19, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00,
+		   0xc9, 0xa6, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06,
+		   0x00, 0x9b, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x70,
+		   0x00, 0x06, 0x00, 0x7b, 0x00),
+	PHYREGS(0x0868, 0x0864, 0x0860, 0x01e7, 0x01e8, 0x01e9),
+  },
+  {	.freq			= 5380,
+	RADIOREGS3(0x6e, 0x01, 0x01, 0x02, 0x1a, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00,
+		   0xb8, 0x96, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06,
+		   0x00, 0x9a, 0x00, 0x96, 0x00, 0x03, 0x00, 0x70,
+		   0x00, 0x06, 0x00, 0x7a, 0x00),
+	PHYREGS(0x086c, 0x0868, 0x0864, 0x01e6, 0x01e7, 0x01e8),
+  },
+  {	.freq			= 5390,
+	RADIOREGS3(0x6e, 0x01, 0x01, 0x02, 0x1b, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00,
+		   0xb8, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06,
+		   0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70,
+		   0x00, 0x06, 0x00, 0x7a, 0x00),
+	PHYREGS(0x0870, 0x086c, 0x0868, 0x01e5, 0x01e6, 0x01e7),
+  },
+  {	.freq			= 5400,
+	RADIOREGS3(0x67, 0x01, 0x01, 0x02, 0x1c, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00,
+		   0xb8, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06,
+		   0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70,
+		   0x00, 0x06, 0x00, 0x7a, 0x00),
+	PHYREGS(0x0874, 0x0870, 0x086c, 0x01e5, 0x01e5, 0x01e6),
+  },
+  {	.freq			= 5410,
+	RADIOREGS3(0x67, 0x01, 0x01, 0x02, 0x1d, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00,
+		   0xb7, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x05,
+		   0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70,
+		   0x00, 0x05, 0x00, 0x7a, 0x00),
+	PHYREGS(0x0878, 0x0874, 0x0870, 0x01e4, 0x01e5, 0x01e5),
+  },
+  {	.freq			= 5420,
+	RADIOREGS3(0x61, 0x01, 0x01, 0x02, 0x1e, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00,
+		   0xa7, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x05,
+		   0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70,
+		   0x00, 0x05, 0x00, 0x7a, 0x00),
+	PHYREGS(0x087c, 0x0878, 0x0874, 0x01e3, 0x01e4, 0x01e5),
+  },
+  {	.freq			= 5430,
+	RADIOREGS3(0x61, 0x01, 0x01, 0x02, 0x1f, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0b, 0x00,
+		   0xa6, 0x85, 0x00, 0x02, 0x00, 0x70, 0x00, 0x05,
+		   0x00, 0x99, 0x00, 0x85, 0x00, 0x02, 0x00, 0x70,
+		   0x00, 0x05, 0x00, 0x79, 0x00),
+	PHYREGS(0x0880, 0x087c, 0x0878, 0x01e2, 0x01e3, 0x01e4),
+  },
+  {	.freq			= 5440,
+	RADIOREGS3(0x5a, 0x01, 0x01, 0x02, 0x20, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00,
+		   0xa6, 0x84, 0x00, 0x02, 0x00, 0x70, 0x00, 0x05,
+		   0x00, 0x99, 0x00, 0x84, 0x00, 0x02, 0x00, 0x70,
+		   0x00, 0x05, 0x00, 0x79, 0x00),
+	PHYREGS(0x0884, 0x0880, 0x087c, 0x01e1, 0x01e2, 0x01e3),
+  },
+  {	.freq			= 5450,
+	RADIOREGS3(0x5a, 0x01, 0x01, 0x02, 0x21, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00,
+		   0x95, 0x84, 0x00, 0x02, 0x00, 0x70, 0x00, 0x05,
+		   0x00, 0x99, 0x00, 0x84, 0x00, 0x02, 0x00, 0x70,
+		   0x00, 0x05, 0x00, 0x79, 0x00),
+	PHYREGS(0x0888, 0x0884, 0x0880, 0x01e0, 0x01e1, 0x01e2),
+  },
+  {	.freq			= 5460,
+	RADIOREGS3(0x53, 0x01, 0x01, 0x02, 0x22, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00,
+		   0x95, 0x84, 0x00, 0x02, 0x00, 0x70, 0x00, 0x04,
+		   0x00, 0x99, 0x00, 0x84, 0x00, 0x02, 0x00, 0x70,
+		   0x00, 0x04, 0x00, 0x79, 0x00),
+	PHYREGS(0x088c, 0x0888, 0x0884, 0x01df, 0x01e0, 0x01e1),
+  },
+  {	.freq			= 5470,
+	RADIOREGS3(0x53, 0x01, 0x01, 0x02, 0x23, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00,
+		   0x94, 0x74, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04,
+		   0x00, 0x99, 0x00, 0x74, 0x00, 0x01, 0x00, 0x70,
+		   0x00, 0x04, 0x00, 0x79, 0x00),
+	PHYREGS(0x0890, 0x088c, 0x0888, 0x01de, 0x01df, 0x01e0),
+  },
+  {	.freq			= 5480,
+	RADIOREGS3(0x4d, 0x01, 0x01, 0x02, 0x24, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00,
+		   0x84, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04,
+		   0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70,
+		   0x00, 0x04, 0x00, 0x78, 0x00),
+	PHYREGS(0x0894, 0x0890, 0x088c, 0x01dd, 0x01de, 0x01df),
+  },
+  {	.freq			= 5490,
+	RADIOREGS3(0x4d, 0x01, 0x01, 0x02, 0x25, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00,
+		   0x83, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04,
+		   0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70,
+		   0x00, 0x04, 0x00, 0x78, 0x00),
+	PHYREGS(0x0898, 0x0894, 0x0890, 0x01dd, 0x01dd, 0x01de),
+  },
+  {	.freq			= 5500,
+	RADIOREGS3(0x47, 0x01, 0x01, 0x02, 0x26, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00,
+		   0x82, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04,
+		   0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70,
+		   0x00, 0x04, 0x00, 0x78, 0x00),
+	PHYREGS(0x089c, 0x0898, 0x0894, 0x01dc, 0x01dd, 0x01dd),
+  },
+  {	.freq			= 5510,
+	RADIOREGS3(0x47, 0x01, 0x01, 0x02, 0x27, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00,
+		   0x82, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04,
+		   0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70,
+		   0x00, 0x04, 0x00, 0x78, 0x00),
+	PHYREGS(0x08a0, 0x089c, 0x0898, 0x01db, 0x01dc, 0x01dd),
+  },
+  {	.freq			= 5520,
+	RADIOREGS3(0x40, 0x01, 0x01, 0x02, 0x28, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00,
+		   0x72, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04,
+		   0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70,
+		   0x00, 0x04, 0x00, 0x78, 0x00),
+	PHYREGS(0x08a4, 0x08a0, 0x089c, 0x01da, 0x01db, 0x01dc),
+  },
+  {	.freq			= 5530,
+	RADIOREGS3(0x40, 0x01, 0x01, 0x02, 0x29, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x09, 0x00,
+		   0x72, 0x63, 0x00, 0x01, 0x00, 0x70, 0x00, 0x03,
+		   0x00, 0x98, 0x00, 0x63, 0x00, 0x01, 0x00, 0x70,
+		   0x00, 0x03, 0x00, 0x78, 0x00),
+	PHYREGS(0x08a8, 0x08a4, 0x08a0, 0x01d9, 0x01da, 0x01db),
+  },
+  {	.freq			= 5540,
+	RADIOREGS3(0x3a, 0x01, 0x01, 0x02, 0x2a, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x09, 0x00,
+		   0x71, 0x62, 0x00, 0x00, 0x00, 0x70, 0x00, 0x03,
+		   0x00, 0x97, 0x00, 0x62, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x03, 0x00, 0x77, 0x00),
+	PHYREGS(0x08ac, 0x08a8, 0x08a4, 0x01d8, 0x01d9, 0x01da),
+  },
+  {	.freq			= 5550,
+	RADIOREGS3(0x3a, 0x01, 0x01, 0x02, 0x2b, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x89, 0x09, 0x00,
+		   0x61, 0x62, 0x00, 0x00, 0x00, 0x70, 0x00, 0x03,
+		   0x00, 0x97, 0x00, 0x62, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x03, 0x00, 0x77, 0x00),
+	PHYREGS(0x08b0, 0x08ac, 0x08a8, 0x01d7, 0x01d8, 0x01d9),
+  },
+  {	.freq			= 5560,
+	RADIOREGS3(0x34, 0x01, 0x01, 0x02, 0x2c, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x89, 0x09, 0x00,
+		   0x61, 0x62, 0x00, 0x00, 0x00, 0x70, 0x00, 0x03,
+		   0x00, 0x97, 0x00, 0x62, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x03, 0x00, 0x77, 0x00),
+	PHYREGS(0x08b4, 0x08b0, 0x08ac, 0x01d7, 0x01d7, 0x01d8),
+  },
+  {	.freq			= 5570,
+	RADIOREGS3(0x34, 0x01, 0x01, 0x02, 0x2d, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x89, 0x09, 0x00,
+		   0x61, 0x52, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
+		   0x00, 0x96, 0x00, 0x52, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x02, 0x00, 0x76, 0x00),
+	PHYREGS(0x08b8, 0x08b4, 0x08b0, 0x01d6, 0x01d7, 0x01d7),
+  },
+  {	.freq			= 5580,
+	RADIOREGS3(0x2e, 0x01, 0x01, 0x02, 0x2e, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x89, 0x08, 0x00,
+		   0x60, 0x52, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
+		   0x00, 0x96, 0x00, 0x52, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x02, 0x00, 0x86, 0x00),
+	PHYREGS(0x08bc, 0x08b8, 0x08b4, 0x01d5, 0x01d6, 0x01d7),
+  },
+  {	.freq			= 5590,
+	RADIOREGS3(0x2e, 0x01, 0x01, 0x02, 0x2f, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x89, 0x08, 0x00,
+		   0x50, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
+		   0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x02, 0x00, 0x86, 0x00),
+	PHYREGS(0x08c0, 0x08bc, 0x08b8, 0x01d4, 0x01d5, 0x01d6),
+  },
+  {	.freq			= 5600,
+	RADIOREGS3(0x28, 0x01, 0x01, 0x02, 0x30, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x89, 0x08, 0x00,
+		   0x50, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
+		   0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x02, 0x00, 0x86, 0x00),
+	PHYREGS(0x08c4, 0x08c0, 0x08bc, 0x01d3, 0x01d4, 0x01d5),
+  },
+  {	.freq			= 5610,
+	RADIOREGS3(0x28, 0x01, 0x01, 0x02, 0x31, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x89, 0x08, 0x00,
+		   0x50, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
+		   0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x02, 0x00, 0x86, 0x00),
+	PHYREGS(0x08c8, 0x08c4, 0x08c0, 0x01d2, 0x01d3, 0x01d4),
+  },
+  {	.freq			= 5620,
+	RADIOREGS3(0x21, 0x01, 0x01, 0x02, 0x32, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x89, 0x08, 0x00,
+		   0x50, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
+		   0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x02, 0x00, 0x86, 0x00),
+	PHYREGS(0x08cc, 0x08c8, 0x08c4, 0x01d2, 0x01d2, 0x01d3),
+  },
+  {	.freq			= 5630,
+	RADIOREGS3(0x21, 0x01, 0x01, 0x02, 0x33, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x88, 0x07, 0x00,
+		   0x50, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
+		   0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x02, 0x00, 0x86, 0x00),
+	PHYREGS(0x08d0, 0x08cc, 0x08c8, 0x01d1, 0x01d2, 0x01d2),
+  },
+  {	.freq			= 5640,
+	RADIOREGS3(0x1c, 0x01, 0x01, 0x02, 0x34, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x88, 0x07, 0x00,
+		   0x40, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
+		   0x00, 0x95, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x02, 0x00, 0x85, 0x00),
+	PHYREGS(0x08d4, 0x08d0, 0x08cc, 0x01d0, 0x01d1, 0x01d2),
+  },
+  {	.freq			= 5650,
+	RADIOREGS3(0x1c, 0x01, 0x01, 0x02, 0x35, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x88, 0x07, 0x00,
+		   0x40, 0x50, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+		   0x00, 0x95, 0x00, 0x50, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x01, 0x00, 0x85, 0x00),
+	PHYREGS(0x08d8, 0x08d4, 0x08d0, 0x01cf, 0x01d0, 0x01d1),
+  },
+  {	.freq			= 5660,
+	RADIOREGS3(0x16, 0x01, 0x01, 0x02, 0x36, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x88, 0x07, 0x00,
+		   0x40, 0x50, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+		   0x00, 0x95, 0x00, 0x50, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x01, 0x00, 0x85, 0x00),
+	PHYREGS(0x08dc, 0x08d8, 0x08d4, 0x01ce, 0x01cf, 0x01d0),
+  },
+  {	.freq			= 5670,
+	RADIOREGS3(0x16, 0x01, 0x01, 0x02, 0x37, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x88, 0x07, 0x00,
+		   0x40, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+		   0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x01, 0x00, 0x84, 0x00),
+	PHYREGS(0x08e0, 0x08dc, 0x08d8, 0x01ce, 0x01ce, 0x01cf),
+  },
+  {	.freq			= 5680,
+	RADIOREGS3(0x10, 0x01, 0x01, 0x02, 0x38, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x06, 0x00,
+		   0x30, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+		   0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x01, 0x00, 0x84, 0x00),
+	PHYREGS(0x08e4, 0x08e0, 0x08dc, 0x01cd, 0x01ce, 0x01ce),
+  },
+  {	.freq			= 5690,
+	RADIOREGS3(0x10, 0x01, 0x01, 0x02, 0x39, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x06, 0x00,
+		   0x30, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+		   0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x01, 0x00, 0x94, 0x00),
+	PHYREGS(0x08e8, 0x08e4, 0x08e0, 0x01cc, 0x01cd, 0x01ce),
+  },
+  {	.freq			= 5700,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3a, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x06, 0x00,
+		   0x30, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+		   0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x01, 0x00, 0x94, 0x00),
+	PHYREGS(0x08ec, 0x08e8, 0x08e4, 0x01cb, 0x01cc, 0x01cd),
+  },
+  {	.freq			= 5710,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3b, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x06, 0x00,
+		   0x30, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+		   0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x01, 0x00, 0x94, 0x00),
+	PHYREGS(0x08f0, 0x08ec, 0x08e8, 0x01ca, 0x01cb, 0x01cc),
+  },
+  {	.freq			= 5720,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3c, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x06, 0x00,
+		   0x30, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+		   0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x01, 0x00, 0x94, 0x00),
+	PHYREGS(0x08f4, 0x08f0, 0x08ec, 0x01c9, 0x01ca, 0x01cb),
+  },
+  {	.freq			= 5725,
+	RADIOREGS3(0x03, 0x01, 0x02, 0x04, 0x79, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x05, 0x05, 0x05, 0x87, 0x06, 0x00,
+		   0x30, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+		   0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x01, 0x00, 0x94, 0x00),
+	PHYREGS(0x08f6, 0x08f2, 0x08ee, 0x01c9, 0x01ca, 0x01cb),
+  },
+  {	.freq			= 5730,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3d, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x05, 0x00,
+		   0x20, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+		   0x00, 0x94, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x01, 0x00, 0x94, 0x00),
+	PHYREGS(0x08f8, 0x08f4, 0x08f0, 0x01c9, 0x01c9, 0x01ca),
+  },
+  {	.freq			= 5735,
+	RADIOREGS3(0x03, 0x01, 0x02, 0x04, 0x7b, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x05, 0x05, 0x05, 0x87, 0x05, 0x00,
+		   0x20, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x93, 0x00),
+	PHYREGS(0x08fa, 0x08f6, 0x08f2, 0x01c8, 0x01c9, 0x01ca),
+  },
+  {	.freq			= 5740,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3e, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x05, 0x00,
+		   0x20, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x93, 0x00),
+	PHYREGS(0x08fc, 0x08f8, 0x08f4, 0x01c8, 0x01c9, 0x01c9),
+  },
+  {	.freq			= 5745,
+	RADIOREGS3(0xfe, 0x00, 0x02, 0x04, 0x7d, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x05, 0x05, 0x05, 0x87, 0x05, 0x00,
+		   0x20, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x93, 0x00),
+	PHYREGS(0x08fe, 0x08fa, 0x08f6, 0x01c8, 0x01c8, 0x01c9),
+  },
+  {	.freq			= 5750,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3f, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x05, 0x00,
+		   0x20, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x93, 0x00),
+	PHYREGS(0x0900, 0x08fc, 0x08f8, 0x01c7, 0x01c8, 0x01c9),
+  },
+  {	.freq			= 5755,
+	RADIOREGS3(0xfe, 0x00, 0x02, 0x04, 0x7f, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x05, 0x05, 0x05, 0x87, 0x05, 0x00,
+		   0x10, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x93, 0x00),
+	PHYREGS(0x0902, 0x08fe, 0x08fa, 0x01c7, 0x01c8, 0x01c8),
+  },
+  {	.freq			= 5760,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x40, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x86, 0x05, 0x00,
+		   0x10, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x93, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x93, 0x00),
+	PHYREGS(0x0904, 0x0900, 0x08fc, 0x01c6, 0x01c7, 0x01c8),
+  },
+  {	.freq			= 5765,
+	RADIOREGS3(0xf8, 0x00, 0x02, 0x04, 0x81, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x05, 0x05, 0x05, 0x86, 0x05, 0x00,
+		   0x10, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x92, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x92, 0x00),
+	PHYREGS(0x0906, 0x0902, 0x08fe, 0x01c6, 0x01c7, 0x01c8),
+  },
+  {	.freq			= 5770,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x41, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x86, 0x04, 0x00,
+		   0x10, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x92, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x92, 0x00),
+	PHYREGS(0x0908, 0x0904, 0x0900, 0x01c6, 0x01c6, 0x01c7),
+  },
+  {	.freq			= 5775,
+	RADIOREGS3(0xf8, 0x00, 0x02, 0x04, 0x83, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x05, 0x05, 0x05, 0x86, 0x04, 0x00,
+		   0x10, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x92, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x92, 0x00),
+	PHYREGS(0x090a, 0x0906, 0x0902, 0x01c5, 0x01c6, 0x01c7),
+  },
+  {	.freq			= 5780,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x42, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x86, 0x04, 0x00,
+		   0x10, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x92, 0x00),
+	PHYREGS(0x090c, 0x0908, 0x0904, 0x01c5, 0x01c6, 0x01c6),
+  },
+  {	.freq			= 5785,
+	RADIOREGS3(0xf2, 0x00, 0x02, 0x04, 0x85, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00,
+		   0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x92, 0x00),
+	PHYREGS(0x090e, 0x090a, 0x0906, 0x01c4, 0x01c5, 0x01c6),
+  },
+  {	.freq			= 5790,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x43, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00,
+		   0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x92, 0x00),
+	PHYREGS(0x0910, 0x090c, 0x0908, 0x01c4, 0x01c5, 0x01c6),
+  },
+  {	.freq			= 5795,
+	RADIOREGS3(0xf2, 0x00, 0x02, 0x04, 0x87, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00,
+		   0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x92, 0x00),
+	PHYREGS(0x0912, 0x090e, 0x090a, 0x01c4, 0x01c4, 0x01c5),
+  },
+  {	.freq			= 5800,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x44, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00,
+		   0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x92, 0x00),
+	PHYREGS(0x0914, 0x0910, 0x090c, 0x01c3, 0x01c4, 0x01c5),
+  },
+  {	.freq			= 5805,
+	RADIOREGS3(0xed, 0x00, 0x02, 0x04, 0x89, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00,
+		   0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x92, 0x00),
+	PHYREGS(0x0916, 0x0912, 0x090e, 0x01c3, 0x01c4, 0x01c4),
+  },
+  {	.freq			= 5810,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x45, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00,
+		   0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x92, 0x00),
+	PHYREGS(0x0918, 0x0914, 0x0910, 0x01c2, 0x01c3, 0x01c4),
+  },
+  {	.freq			= 5815,
+	RADIOREGS3(0xed, 0x00, 0x02, 0x04, 0x8b, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00,
+		   0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x92, 0x00),
+	PHYREGS(0x091a, 0x0916, 0x0912, 0x01c2, 0x01c3, 0x01c4),
+  },
+  {	.freq			= 5820,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x46, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00,
+		   0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x92, 0x00),
+	PHYREGS(0x091c, 0x0918, 0x0914, 0x01c2, 0x01c2, 0x01c3),
+  },
+  {	.freq			= 5825,
+	RADIOREGS3(0xed, 0x00, 0x02, 0x04, 0x8d, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00,
+		   0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x92, 0x00),
+	PHYREGS(0x091e, 0x091a, 0x0916, 0x01c1, 0x01c2, 0x01c3),
+  },
+  {	.freq			= 5830,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x47, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00,
+		   0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x92, 0x00),
+	PHYREGS(0x0920, 0x091c, 0x0918, 0x01c1, 0x01c2, 0x01c2),
+  },
+  {	.freq			= 5840,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x48, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00,
+		   0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x92, 0x00),
+	PHYREGS(0x0924, 0x0920, 0x091c, 0x01c0, 0x01c1, 0x01c2),
+  },
+  {	.freq			= 5850,
+	RADIOREGS3(0xe0, 0x00, 0x01, 0x02, 0x49, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00,
+		   0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x92, 0x00),
+	PHYREGS(0x0928, 0x0924, 0x0920, 0x01bf, 0x01c0, 0x01c1),
+  },
+  {	.freq			= 5860,
+	RADIOREGS3(0xde, 0x00, 0x01, 0x02, 0x4a, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00,
+		   0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x92, 0x00),
+	PHYREGS(0x092c, 0x0928, 0x0924, 0x01bf, 0x01bf, 0x01c0),
+  },
+  {	.freq			= 5870,
+	RADIOREGS3(0xdb, 0x00, 0x01, 0x02, 0x4b, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00,
+		   0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x91, 0x00),
+	PHYREGS(0x0930, 0x092c, 0x0928, 0x01be, 0x01bf, 0x01bf),
+  },
+  {	.freq			= 5880,
+	RADIOREGS3(0xd8, 0x00, 0x01, 0x02, 0x4c, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00,
+		   0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x91, 0x00),
+	PHYREGS(0x0934, 0x0930, 0x092c, 0x01bd, 0x01be, 0x01bf),
+  },
+  {	.freq			= 5890,
+	RADIOREGS3(0xd6, 0x00, 0x01, 0x02, 0x4d, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00,
+		   0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x91, 0x00),
+	PHYREGS(0x0938, 0x0934, 0x0930, 0x01bc, 0x01bd, 0x01be),
+  },
+  {	.freq			= 5900,
+	RADIOREGS3(0xd3, 0x00, 0x01, 0x02, 0x4e, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00,
+		   0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x91, 0x00),
+	PHYREGS(0x093c, 0x0938, 0x0934, 0x01bc, 0x01bc, 0x01bd),
+  },
+  {	.freq			= 5910,
+	RADIOREGS3(0xd6, 0x00, 0x01, 0x02, 0x4f, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00,
+		   0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x91, 0x00),
+	PHYREGS(0x0940, 0x093c, 0x0938, 0x01bb, 0x01bc, 0x01bc),
+  },
+  {	.freq			= 2412,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x6c, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x04, 0x04, 0x04, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x89, 0x00, 0x03, 0x00, 0x70, 0x00,
+		   0x0f, 0x00, 0x0b, 0x00, 0x89, 0x00, 0x03, 0x00,
+		   0x70, 0x00, 0x0f, 0x00, 0x0b),
+	PHYREGS(0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443),
+  },
+  {	.freq			= 2417,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x71, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x89, 0x00, 0x03, 0x00, 0x70, 0x00,
+		   0x0f, 0x00, 0x0a, 0x00, 0x89, 0x00, 0x03, 0x00,
+		   0x70, 0x00, 0x0f, 0x00, 0x0a),
+	PHYREGS(0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441),
+  },
+  {	.freq			= 2422,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x76, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x89, 0x00, 0x03, 0x00, 0x70, 0x00,
+		   0x0f, 0x00, 0x0a, 0x00, 0x89, 0x00, 0x03, 0x00,
+		   0x70, 0x00, 0x0f, 0x00, 0x0a),
+	PHYREGS(0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f),
+  },
+  {	.freq			= 2427,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x7b, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x78, 0x00, 0x03, 0x00, 0x70, 0x00,
+		   0x0e, 0x00, 0x0a, 0x00, 0x78, 0x00, 0x03, 0x00,
+		   0x70, 0x00, 0x0e, 0x00, 0x0a),
+	PHYREGS(0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d),
+  },
+  {	.freq			= 2432,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x80, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x77, 0x00, 0x03, 0x00, 0x70, 0x00,
+		   0x0e, 0x00, 0x0a, 0x00, 0x77, 0x00, 0x03, 0x00,
+		   0x70, 0x00, 0x0e, 0x00, 0x0a),
+	PHYREGS(0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a),
+  },
+  {	.freq			= 2437,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x85, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x76, 0x00, 0x03, 0x00, 0x70, 0x00,
+		   0x0e, 0x00, 0x0a, 0x00, 0x76, 0x00, 0x03, 0x00,
+		   0x70, 0x00, 0x0e, 0x00, 0x0a),
+	PHYREGS(0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438),
+  },
+  {	.freq			= 2442,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x8a, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x66, 0x00, 0x03, 0x00, 0x70, 0x00,
+		   0x0e, 0x00, 0x0a, 0x00, 0x66, 0x00, 0x03, 0x00,
+		   0x70, 0x00, 0x0e, 0x00, 0x0a),
+	PHYREGS(0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436),
+  },
+  {	.freq			= 2447,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x8f, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x55, 0x00, 0x02, 0x00, 0x70, 0x00,
+		   0x0e, 0x00, 0x09, 0x00, 0x55, 0x00, 0x02, 0x00,
+		   0x70, 0x00, 0x0e, 0x00, 0x09),
+	PHYREGS(0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434),
+  },
+  {	.freq			= 2452,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x94, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x45, 0x00, 0x02, 0x00, 0x70, 0x00,
+		   0x0e, 0x00, 0x09, 0x00, 0x45, 0x00, 0x02, 0x00,
+		   0x70, 0x00, 0x0e, 0x00, 0x09),
+	PHYREGS(0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431),
+  },
+  {	.freq			= 2457,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x99, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x34, 0x00, 0x02, 0x00, 0x70, 0x00,
+		   0x0d, 0x00, 0x09, 0x00, 0x34, 0x00, 0x02, 0x00,
+		   0x70, 0x00, 0x0d, 0x00, 0x09),
+	PHYREGS(0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f),
+  },
+  {	.freq			= 2462,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x9e, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x33, 0x00, 0x02, 0x00, 0x70, 0x00,
+		   0x0d, 0x00, 0x09, 0x00, 0x33, 0x00, 0x02, 0x00,
+		   0x70, 0x00, 0x0d, 0x00, 0x09),
+	PHYREGS(0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d),
+  },
+  {	.freq			= 2467,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0xa3, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x22, 0x00, 0x02, 0x00, 0x70, 0x00,
+		   0x0d, 0x00, 0x08, 0x00, 0x22, 0x00, 0x02, 0x00,
+		   0x70, 0x00, 0x0d, 0x00, 0x08),
+	PHYREGS(0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b),
+  },
+  {	.freq			= 2472,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0xa8, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x11, 0x00, 0x02, 0x00, 0x70, 0x00,
+		   0x0d, 0x00, 0x08, 0x00, 0x11, 0x00, 0x02, 0x00,
+		   0x70, 0x00, 0x0d, 0x00, 0x08),
+	PHYREGS(0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429),
+  },
+  {	.freq			= 2484,
+	RADIOREGS3(0xff, 0x01, 0x03, 0x09, 0xb4, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x07, 0x07, 0x07, 0x8f, 0x20, 0x00,
+		   0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x70, 0x00,
+		   0x0d, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00,
+		   0x70, 0x00, 0x0d, 0x00, 0x08),
+	PHYREGS(0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424),
+  },
+};
+
+static const struct b43_nphy_channeltab_entry_rev3 b43_nphy_channeltab_rev8[] = {
+  {	.freq			= 4920,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+		   0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77,
+		   0x00, 0x0f, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07b4, 0x07b0, 0x07ac, 0x0214, 0x0215, 0x0216),
+  },
+  {	.freq			= 4930,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xed, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+		   0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77,
+		   0x00, 0x0f, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07b8, 0x07b4, 0x07b0, 0x0213, 0x0214, 0x0215),
+  },
+  {	.freq			= 4940,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xee, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+		   0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77,
+		   0x00, 0x0f, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07bc, 0x07b8, 0x07b4, 0x0212, 0x0213, 0x0214),
+  },
+  {	.freq			= 4950,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xef, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+		   0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77,
+		   0x00, 0x0f, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07c0, 0x07bc, 0x07b8, 0x0211, 0x0212, 0x0213),
+  },
+  {	.freq			= 4960,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf0, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+		   0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77,
+		   0x00, 0x0f, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07c4, 0x07c0, 0x07bc, 0x020f, 0x0211, 0x0212),
+  },
+  {	.freq			= 4970,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf1, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+		   0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77,
+		   0x00, 0x0f, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07c8, 0x07c4, 0x07c0, 0x020e, 0x020f, 0x0211),
+  },
+  {	.freq			= 4980,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf2, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+		   0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77,
+		   0x00, 0x0f, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07cc, 0x07c8, 0x07c4, 0x020d, 0x020e, 0x020f),
+  },
+  {	.freq			= 4990,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf3, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+		   0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77,
+		   0x00, 0x0f, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07d0, 0x07cc, 0x07c8, 0x020c, 0x020d, 0x020e),
+  },
+  {	.freq			= 5000,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf4, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+		   0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77,
+		   0x00, 0x0f, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07d4, 0x07d0, 0x07cc, 0x020b, 0x020c, 0x020d),
+  },
+  {	.freq			= 5010,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf5, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+		   0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77,
+		   0x00, 0x0f, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07d8, 0x07d4, 0x07d0, 0x020a, 0x020b, 0x020c),
+  },
+  {	.freq			= 5020,
+	RADIOREGS3(0xf7, 0x01, 0x01, 0x01, 0xf6, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+		   0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77,
+		   0x00, 0x0f, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07dc, 0x07d8, 0x07d4, 0x0209, 0x020a, 0x020b),
+  },
+  {	.freq			= 5030,
+	RADIOREGS3(0xf7, 0x01, 0x01, 0x01, 0xf7, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+		   0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77,
+		   0x00, 0x0f, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07e0, 0x07dc, 0x07d8, 0x0208, 0x0209, 0x020a),
+  },
+  {	.freq			= 5040,
+	RADIOREGS3(0xef, 0x01, 0x01, 0x01, 0xf8, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+		   0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77,
+		   0x00, 0x0f, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07e4, 0x07e0, 0x07dc, 0x0207, 0x0208, 0x0209),
+  },
+  {	.freq			= 5050,
+	RADIOREGS3(0xef, 0x01, 0x01, 0x01, 0xf9, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+		   0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77,
+		   0x00, 0x0f, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07e8, 0x07e4, 0x07e0, 0x0206, 0x0207, 0x0208),
+  },
+  {	.freq			= 5060,
+	RADIOREGS3(0xe6, 0x01, 0x01, 0x01, 0xfa, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+		   0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77,
+		   0x00, 0x0f, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07ec, 0x07e8, 0x07e4, 0x0205, 0x0206, 0x0207),
+  },
+  {	.freq			= 5070,
+	RADIOREGS3(0xe6, 0x01, 0x01, 0x01, 0xfb, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+		   0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77,
+		   0x00, 0x0f, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07f0, 0x07ec, 0x07e8, 0x0204, 0x0205, 0x0206),
+  },
+  {	.freq			= 5080,
+	RADIOREGS3(0xde, 0x01, 0x01, 0x01, 0xfc, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+		   0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77,
+		   0x00, 0x0f, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07f4, 0x07f0, 0x07ec, 0x0203, 0x0204, 0x0205),
+  },
+  {	.freq			= 5090,
+	RADIOREGS3(0xde, 0x01, 0x01, 0x01, 0xfd, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+		   0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77,
+		   0x00, 0x0f, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07f8, 0x07f4, 0x07f0, 0x0202, 0x0203, 0x0204),
+  },
+  {	.freq			= 5100,
+	RADIOREGS3(0xd6, 0x01, 0x01, 0x01, 0xfe, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfd, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
+		   0x00, 0x6f, 0x00, 0xfd, 0x00, 0x08, 0x00, 0x77,
+		   0x00, 0x0f, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07fc, 0x07f8, 0x07f4, 0x0201, 0x0202, 0x0203),
+  },
+  {	.freq			= 5110,
+	RADIOREGS3(0xd6, 0x01, 0x01, 0x01, 0xff, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
+		   0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77,
+		   0x00, 0x0f, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0800, 0x07fc, 0x07f8, 0x0200, 0x0201, 0x0202),
+  },
+  {	.freq			= 5120,
+	RADIOREGS3(0xce, 0x01, 0x01, 0x02, 0x00, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
+		   0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77,
+		   0x00, 0x0f, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0804, 0x0800, 0x07fc, 0x01ff, 0x0200, 0x0201),
+  },
+  {	.freq			= 5130,
+	RADIOREGS3(0xce, 0x01, 0x01, 0x02, 0x01, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
+		   0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77,
+		   0x00, 0x0f, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0808, 0x0804, 0x0800, 0x01fe, 0x01ff, 0x0200),
+  },
+  {	.freq			= 5140,
+	RADIOREGS3(0xc6, 0x01, 0x01, 0x02, 0x02, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfb, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
+		   0x00, 0x6f, 0x00, 0xfb, 0x00, 0x08, 0x00, 0x77,
+		   0x00, 0x0f, 0x00, 0x6f, 0x00),
+	PHYREGS(0x080c, 0x0808, 0x0804, 0x01fd, 0x01fe, 0x01ff),
+  },
+  {	.freq			= 5160,
+	RADIOREGS3(0xbe, 0x01, 0x01, 0x02, 0x04, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfa, 0x00, 0x07, 0x00, 0x77, 0x00, 0x0e,
+		   0x00, 0x6f, 0x00, 0xfa, 0x00, 0x07, 0x00, 0x77,
+		   0x00, 0x0e, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0814, 0x0810, 0x080c, 0x01fb, 0x01fc, 0x01fd),
+  },
+  {	.freq			= 5170,
+	RADIOREGS3(0xbe, 0x01, 0x01, 0x02, 0x05, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfa, 0x00, 0x07, 0x00, 0x77, 0x00, 0x0e,
+		   0x00, 0x6f, 0x00, 0xfa, 0x00, 0x07, 0x00, 0x77,
+		   0x00, 0x0e, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0818, 0x0814, 0x0810, 0x01fa, 0x01fb, 0x01fc),
+  },
+  {	.freq			= 5180,
+	RADIOREGS3(0xb6, 0x01, 0x01, 0x02, 0x06, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xf9, 0x00, 0x06, 0x00, 0x77, 0x00, 0x0e,
+		   0x00, 0x6f, 0x00, 0xf9, 0x00, 0x06, 0x00, 0x77,
+		   0x00, 0x0e, 0x00, 0x6f, 0x00),
+	PHYREGS(0x081c, 0x0818, 0x0814, 0x01f9, 0x01fa, 0x01fb),
+  },
+  {	.freq			= 5190,
+	RADIOREGS3(0xb6, 0x01, 0x01, 0x02, 0x07, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xf9, 0x00, 0x06, 0x00, 0x77, 0x00, 0x0d,
+		   0x00, 0x6f, 0x00, 0xf9, 0x00, 0x06, 0x00, 0x77,
+		   0x00, 0x0d, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0820, 0x081c, 0x0818, 0x01f8, 0x01f9, 0x01fa),
+  },
+  {	.freq			= 5200,
+	RADIOREGS3(0xaf, 0x01, 0x01, 0x02, 0x08, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xf9, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+		   0x00, 0x6f, 0x00, 0xf9, 0x00, 0x05, 0x00, 0x77,
+		   0x00, 0x0d, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0824, 0x0820, 0x081c, 0x01f7, 0x01f8, 0x01f9),
+  },
+  {	.freq			= 5210,
+	RADIOREGS3(0xaf, 0x01, 0x01, 0x02, 0x09, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xf9, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+		   0x00, 0x6f, 0x00, 0xf9, 0x00, 0x05, 0x00, 0x77,
+		   0x00, 0x0d, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0828, 0x0824, 0x0820, 0x01f6, 0x01f7, 0x01f8),
+  },
+  {	.freq			= 5220,
+	RADIOREGS3(0xa7, 0x01, 0x01, 0x02, 0x0a, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00,
+		   0xfe, 0xd8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+		   0x00, 0x6f, 0x00, 0xd8, 0x00, 0x05, 0x00, 0x77,
+		   0x00, 0x0d, 0x00, 0x6f, 0x00),
+	PHYREGS(0x082c, 0x0828, 0x0824, 0x01f5, 0x01f6, 0x01f7),
+  },
+  {	.freq			= 5230,
+	RADIOREGS3(0xa7, 0x01, 0x01, 0x02, 0x0b, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00,
+		   0xee, 0xd8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+		   0x00, 0x6f, 0x00, 0xd8, 0x00, 0x05, 0x00, 0x77,
+		   0x00, 0x0d, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0830, 0x082c, 0x0828, 0x01f4, 0x01f5, 0x01f6),
+  },
+  {	.freq			= 5240,
+	RADIOREGS3(0xa0, 0x01, 0x01, 0x02, 0x0c, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00,
+		   0xee, 0xc8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+		   0x00, 0x6f, 0x00, 0xc8, 0x00, 0x05, 0x00, 0x77,
+		   0x00, 0x0d, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0834, 0x0830, 0x082c, 0x01f3, 0x01f4, 0x01f5),
+  },
+  {	.freq			= 5250,
+	RADIOREGS3(0xa0, 0x01, 0x01, 0x02, 0x0d, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00,
+		   0xed, 0xc7, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+		   0x00, 0x6f, 0x00, 0xc7, 0x00, 0x05, 0x00, 0x77,
+		   0x00, 0x0d, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0838, 0x0834, 0x0830, 0x01f2, 0x01f3, 0x01f4),
+  },
+  {	.freq			= 5260,
+	RADIOREGS3(0x98, 0x01, 0x01, 0x02, 0x0e, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8e, 0x0e, 0x00,
+		   0xed, 0xc7, 0x00, 0x04, 0x00, 0x77, 0x00, 0x0d,
+		   0x00, 0x6f, 0x00, 0xc7, 0x00, 0x04, 0x00, 0x77,
+		   0x00, 0x0d, 0x00, 0x6f, 0x00),
+	PHYREGS(0x083c, 0x0838, 0x0834, 0x01f1, 0x01f2, 0x01f3),
+  },
+  {	.freq			= 5270,
+	RADIOREGS3(0x98, 0x01, 0x01, 0x02, 0x0f, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8e, 0x0e, 0x00,
+		   0xed, 0xc7, 0x00, 0x04, 0x00, 0x77, 0x00, 0x0c,
+		   0x00, 0x6f, 0x00, 0xc7, 0x00, 0x04, 0x00, 0x77,
+		   0x00, 0x0c, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0840, 0x083c, 0x0838, 0x01f0, 0x01f1, 0x01f2),
+  },
+  {	.freq			= 5280,
+	RADIOREGS3(0x91, 0x01, 0x01, 0x02, 0x10, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00,
+		   0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
+		   0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77,
+		   0x00, 0x0c, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0844, 0x0840, 0x083c, 0x01f0, 0x01f0, 0x01f1),
+  },
+  {	.freq			= 5290,
+	RADIOREGS3(0x91, 0x01, 0x01, 0x02, 0x11, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00,
+		   0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
+		   0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77,
+		   0x00, 0x0c, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0848, 0x0844, 0x0840, 0x01ef, 0x01f0, 0x01f0),
+  },
+  {	.freq			= 5300,
+	RADIOREGS3(0x8a, 0x01, 0x01, 0x02, 0x12, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00,
+		   0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
+		   0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77,
+		   0x00, 0x0c, 0x00, 0x6f, 0x00),
+	PHYREGS(0x084c, 0x0848, 0x0844, 0x01ee, 0x01ef, 0x01f0),
+  },
+  {	.freq			= 5310,
+	RADIOREGS3(0x8a, 0x01, 0x01, 0x02, 0x13, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00,
+		   0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
+		   0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77,
+		   0x00, 0x0c, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0850, 0x084c, 0x0848, 0x01ed, 0x01ee, 0x01ef),
+  },
+  {	.freq			= 5320,
+	RADIOREGS3(0x83, 0x01, 0x01, 0x02, 0x14, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00,
+		   0xdb, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
+		   0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77,
+		   0x00, 0x0c, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0854, 0x0850, 0x084c, 0x01ec, 0x01ed, 0x01ee),
+  },
+  {	.freq			= 5330,
+	RADIOREGS3(0x83, 0x01, 0x01, 0x02, 0x15, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00,
+		   0xcb, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b,
+		   0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77,
+		   0x00, 0x0b, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0858, 0x0854, 0x0850, 0x01eb, 0x01ec, 0x01ed),
+  },
+  {	.freq			= 5340,
+	RADIOREGS3(0x7c, 0x01, 0x01, 0x02, 0x16, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00,
+		   0xca, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b,
+		   0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77,
+		   0x00, 0x0b, 0x00, 0x6f, 0x00),
+	PHYREGS(0x085c, 0x0858, 0x0854, 0x01ea, 0x01eb, 0x01ec),
+  },
+  {	.freq			= 5350,
+	RADIOREGS3(0x7c, 0x01, 0x01, 0x02, 0x17, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00,
+		   0xca, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b,
+		   0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77,
+		   0x00, 0x0b, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0860, 0x085c, 0x0858, 0x01e9, 0x01ea, 0x01eb),
+  },
+  {	.freq			= 5360,
+	RADIOREGS3(0x75, 0x01, 0x01, 0x02, 0x18, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00,
+		   0xc9, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
+		   0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77,
+		   0x00, 0x0a, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0864, 0x0860, 0x085c, 0x01e8, 0x01e9, 0x01ea),
+  },
+  {	.freq			= 5370,
+	RADIOREGS3(0x75, 0x01, 0x01, 0x02, 0x19, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00,
+		   0xc9, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
+		   0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77,
+		   0x00, 0x0a, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0868, 0x0864, 0x0860, 0x01e7, 0x01e8, 0x01e9),
+  },
+  {	.freq			= 5380,
+	RADIOREGS3(0x6e, 0x01, 0x01, 0x02, 0x1a, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00,
+		   0xb8, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
+		   0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77,
+		   0x00, 0x0a, 0x00, 0x6f, 0x00),
+	PHYREGS(0x086c, 0x0868, 0x0864, 0x01e6, 0x01e7, 0x01e8),
+  },
+  {	.freq			= 5390,
+	RADIOREGS3(0x6e, 0x01, 0x01, 0x02, 0x1b, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00,
+		   0xb8, 0x84, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
+		   0x00, 0x6f, 0x00, 0x84, 0x00, 0x03, 0x00, 0x77,
+		   0x00, 0x0a, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0870, 0x086c, 0x0868, 0x01e5, 0x01e6, 0x01e7),
+  },
+  {	.freq			= 5400,
+	RADIOREGS3(0x67, 0x01, 0x01, 0x02, 0x1c, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00,
+		   0xb8, 0x84, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
+		   0x00, 0x6f, 0x00, 0x84, 0x00, 0x03, 0x00, 0x77,
+		   0x00, 0x0a, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0874, 0x0870, 0x086c, 0x01e5, 0x01e5, 0x01e6),
+  },
+  {	.freq			= 5410,
+	RADIOREGS3(0x67, 0x01, 0x01, 0x02, 0x1d, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00,
+		   0xb7, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a,
+		   0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77,
+		   0x00, 0x0a, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0878, 0x0874, 0x0870, 0x01e4, 0x01e5, 0x01e5),
+  },
+  {	.freq			= 5420,
+	RADIOREGS3(0x61, 0x01, 0x01, 0x02, 0x1e, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00,
+		   0xa7, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a,
+		   0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77,
+		   0x00, 0x0a, 0x00, 0x6f, 0x00),
+	PHYREGS(0x087c, 0x0878, 0x0874, 0x01e3, 0x01e4, 0x01e5),
+  },
+  {	.freq			= 5430,
+	RADIOREGS3(0x61, 0x01, 0x01, 0x02, 0x1f, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0b, 0x00,
+		   0xa6, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a,
+		   0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77,
+		   0x00, 0x0a, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0880, 0x087c, 0x0878, 0x01e2, 0x01e3, 0x01e4),
+  },
+  {	.freq			= 5440,
+	RADIOREGS3(0x5a, 0x01, 0x01, 0x02, 0x20, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00,
+		   0xa6, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x09,
+		   0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77,
+		   0x00, 0x09, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0884, 0x0880, 0x087c, 0x01e1, 0x01e2, 0x01e3),
+  },
+  {	.freq			= 5450,
+	RADIOREGS3(0x5a, 0x01, 0x01, 0x02, 0x21, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00,
+		   0x95, 0x84, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09,
+		   0x00, 0x6f, 0x00, 0x84, 0x00, 0x01, 0x00, 0x77,
+		   0x00, 0x09, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0888, 0x0884, 0x0880, 0x01e0, 0x01e1, 0x01e2),
+  },
+  {	.freq			= 5460,
+	RADIOREGS3(0x53, 0x01, 0x01, 0x02, 0x22, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00,
+		   0x95, 0x84, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09,
+		   0x00, 0x6f, 0x00, 0x84, 0x00, 0x01, 0x00, 0x77,
+		   0x00, 0x09, 0x00, 0x6f, 0x00),
+	PHYREGS(0x088c, 0x0888, 0x0884, 0x01df, 0x01e0, 0x01e1),
+  },
+  {	.freq			= 5470,
+	RADIOREGS3(0x53, 0x01, 0x01, 0x02, 0x23, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00,
+		   0x94, 0x73, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09,
+		   0x00, 0x6f, 0x00, 0x73, 0x00, 0x01, 0x00, 0x77,
+		   0x00, 0x09, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0890, 0x088c, 0x0888, 0x01de, 0x01df, 0x01e0),
+  },
+  {	.freq			= 5480,
+	RADIOREGS3(0x4d, 0x01, 0x01, 0x02, 0x24, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00,
+		   0x84, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+		   0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x09, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0894, 0x0890, 0x088c, 0x01dd, 0x01de, 0x01df),
+  },
+  {	.freq			= 5490,
+	RADIOREGS3(0x4d, 0x01, 0x01, 0x02, 0x25, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00,
+		   0x83, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+		   0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x09, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0898, 0x0894, 0x0890, 0x01dd, 0x01dd, 0x01de),
+  },
+  {	.freq			= 5500,
+	RADIOREGS3(0x47, 0x01, 0x01, 0x02, 0x26, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00,
+		   0x82, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+		   0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x09, 0x00, 0x6f, 0x00),
+	PHYREGS(0x089c, 0x0898, 0x0894, 0x01dc, 0x01dd, 0x01dd),
+  },
+  {	.freq			= 5510,
+	RADIOREGS3(0x47, 0x01, 0x01, 0x02, 0x27, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00,
+		   0x82, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+		   0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x09, 0x00, 0x6f, 0x00),
+	PHYREGS(0x08a0, 0x089c, 0x0898, 0x01db, 0x01dc, 0x01dd),
+  },
+  {	.freq			= 5520,
+	RADIOREGS3(0x40, 0x01, 0x01, 0x02, 0x28, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00,
+		   0x72, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+		   0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x09, 0x00, 0x6f, 0x00),
+	PHYREGS(0x08a4, 0x08a0, 0x089c, 0x01da, 0x01db, 0x01dc),
+  },
+  {	.freq			= 5530,
+	RADIOREGS3(0x40, 0x01, 0x01, 0x02, 0x29, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x09, 0x00,
+		   0x72, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+		   0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x09, 0x00, 0x6f, 0x00),
+	PHYREGS(0x08a8, 0x08a4, 0x08a0, 0x01d9, 0x01da, 0x01db),
+  },
+  {	.freq			= 5540,
+	RADIOREGS3(0x3a, 0x01, 0x01, 0x02, 0x2a, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x09, 0x00,
+		   0x71, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+		   0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x09, 0x00, 0x6f, 0x00),
+	PHYREGS(0x08ac, 0x08a8, 0x08a4, 0x01d8, 0x01d9, 0x01da),
+  },
+  {	.freq			= 5550,
+	RADIOREGS3(0x3a, 0x01, 0x01, 0x02, 0x2b, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x89, 0x09, 0x00,
+		   0x61, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+		   0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x09, 0x00, 0x6f, 0x00),
+	PHYREGS(0x08b0, 0x08ac, 0x08a8, 0x01d7, 0x01d8, 0x01d9),
+  },
+  {	.freq			= 5560,
+	RADIOREGS3(0x34, 0x01, 0x01, 0x02, 0x2c, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x89, 0x09, 0x00,
+		   0x61, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+		   0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x09, 0x00, 0x6f, 0x00),
+	PHYREGS(0x08b4, 0x08b0, 0x08ac, 0x01d7, 0x01d7, 0x01d8),
+  },
+  {	.freq			= 5570,
+	RADIOREGS3(0x34, 0x01, 0x01, 0x02, 0x2d, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x89, 0x09, 0x00,
+		   0x61, 0x62, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+		   0x00, 0x6f, 0x00, 0x62, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x09, 0x00, 0x6f, 0x00),
+	PHYREGS(0x08b8, 0x08b4, 0x08b0, 0x01d6, 0x01d7, 0x01d7),
+  },
+  {	.freq			= 5580,
+	RADIOREGS3(0x2e, 0x01, 0x01, 0x02, 0x2e, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x89, 0x08, 0x00,
+		   0x60, 0x62, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08,
+		   0x00, 0x6f, 0x00, 0x62, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x08, 0x00, 0x6f, 0x00),
+	PHYREGS(0x08bc, 0x08b8, 0x08b4, 0x01d5, 0x01d6, 0x01d7),
+  },
+  {	.freq			= 5590,
+	RADIOREGS3(0x2e, 0x01, 0x01, 0x02, 0x2f, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x89, 0x08, 0x00,
+		   0x50, 0x61, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08,
+		   0x00, 0x6f, 0x00, 0x61, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x08, 0x00, 0x6f, 0x00),
+	PHYREGS(0x08c0, 0x08bc, 0x08b8, 0x01d4, 0x01d5, 0x01d6),
+  },
+  {	.freq			= 5600,
+	RADIOREGS3(0x28, 0x01, 0x01, 0x02, 0x30, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x89, 0x08, 0x00,
+		   0x50, 0x51, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08,
+		   0x00, 0x6f, 0x00, 0x51, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x08, 0x00, 0x6f, 0x00),
+	PHYREGS(0x08c4, 0x08c0, 0x08bc, 0x01d3, 0x01d4, 0x01d5),
+  },
+  {	.freq			= 5610,
+	RADIOREGS3(0x28, 0x01, 0x01, 0x02, 0x31, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x89, 0x08, 0x00,
+		   0x50, 0x51, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08,
+		   0x00, 0x6f, 0x00, 0x51, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x08, 0x00, 0x6f, 0x00),
+	PHYREGS(0x08c8, 0x08c4, 0x08c0, 0x01d2, 0x01d3, 0x01d4),
+  },
+  {	.freq			= 5620,
+	RADIOREGS3(0x21, 0x01, 0x01, 0x02, 0x32, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x89, 0x08, 0x00,
+		   0x50, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07,
+		   0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x07, 0x00, 0x6f, 0x00),
+	PHYREGS(0x08cc, 0x08c8, 0x08c4, 0x01d2, 0x01d2, 0x01d3),
+  },
+  {	.freq			= 5630,
+	RADIOREGS3(0x21, 0x01, 0x01, 0x02, 0x33, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x88, 0x07, 0x00,
+		   0x50, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07,
+		   0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x07, 0x00, 0x6f, 0x00),
+	PHYREGS(0x08d0, 0x08cc, 0x08c8, 0x01d1, 0x01d2, 0x01d2),
+  },
+  {	.freq			= 5640,
+	RADIOREGS3(0x1c, 0x01, 0x01, 0x02, 0x34, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x88, 0x07, 0x00,
+		   0x40, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07,
+		   0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x07, 0x00, 0x6f, 0x00),
+	PHYREGS(0x08d4, 0x08d0, 0x08cc, 0x01d0, 0x01d1, 0x01d2),
+  },
+  {	.freq			= 5650,
+	RADIOREGS3(0x1c, 0x01, 0x01, 0x02, 0x35, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x88, 0x07, 0x00,
+		   0x40, 0x40, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07,
+		   0x00, 0x6f, 0x00, 0x40, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x07, 0x00, 0x6f, 0x00),
+	PHYREGS(0x08d8, 0x08d4, 0x08d0, 0x01cf, 0x01d0, 0x01d1),
+  },
+  {	.freq			= 5660,
+	RADIOREGS3(0x16, 0x01, 0x01, 0x02, 0x36, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x88, 0x07, 0x00,
+		   0x40, 0x40, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+		   0x00, 0x6f, 0x00, 0x40, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x06, 0x00, 0x6f, 0x00),
+	PHYREGS(0x08dc, 0x08d8, 0x08d4, 0x01ce, 0x01cf, 0x01d0),
+  },
+  {	.freq			= 5670,
+	RADIOREGS3(0x16, 0x01, 0x01, 0x02, 0x37, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x88, 0x07, 0x00,
+		   0x40, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+		   0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x06, 0x00, 0x6f, 0x00),
+	PHYREGS(0x08e0, 0x08dc, 0x08d8, 0x01ce, 0x01ce, 0x01cf),
+  },
+  {	.freq			= 5680,
+	RADIOREGS3(0x10, 0x01, 0x01, 0x02, 0x38, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x06, 0x00,
+		   0x30, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+		   0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x06, 0x00, 0x6f, 0x00),
+	PHYREGS(0x08e4, 0x08e0, 0x08dc, 0x01cd, 0x01ce, 0x01ce),
+  },
+  {	.freq			= 5690,
+	RADIOREGS3(0x10, 0x01, 0x01, 0x02, 0x39, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x06, 0x00,
+		   0x30, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+		   0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x06, 0x00, 0x6f, 0x00),
+	PHYREGS(0x08e8, 0x08e4, 0x08e0, 0x01cc, 0x01cd, 0x01ce),
+  },
+  {	.freq			= 5700,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3a, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x06, 0x00,
+		   0x30, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+		   0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x06, 0x00, 0x6e, 0x00),
+	PHYREGS(0x08ec, 0x08e8, 0x08e4, 0x01cb, 0x01cc, 0x01cd),
+  },
+  {	.freq			= 5710,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3b, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x06, 0x00,
+		   0x30, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+		   0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x06, 0x00, 0x6e, 0x00),
+	PHYREGS(0x08f0, 0x08ec, 0x08e8, 0x01ca, 0x01cb, 0x01cc),
+  },
+  {	.freq			= 5720,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3c, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x06, 0x00,
+		   0x30, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+		   0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x06, 0x00, 0x6e, 0x00),
+	PHYREGS(0x08f4, 0x08f0, 0x08ec, 0x01c9, 0x01ca, 0x01cb),
+  },
+  {	.freq			= 5725,
+	RADIOREGS3(0x03, 0x01, 0x02, 0x04, 0x79, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x05, 0x05, 0x05, 0x87, 0x06, 0x00,
+		   0x30, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+		   0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x06, 0x00, 0x6e, 0x00),
+	PHYREGS(0x08f6, 0x08f2, 0x08ee, 0x01c9, 0x01ca, 0x01cb),
+  },
+  {	.freq			= 5730,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3d, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x05, 0x00,
+		   0x20, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+		   0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x06, 0x00, 0x6e, 0x00),
+	PHYREGS(0x08f8, 0x08f4, 0x08f0, 0x01c9, 0x01c9, 0x01ca),
+  },
+  {	.freq			= 5735,
+	RADIOREGS3(0x03, 0x01, 0x02, 0x04, 0x7b, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x05, 0x05, 0x05, 0x87, 0x05, 0x00,
+		   0x20, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+		   0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x06, 0x00, 0x6d, 0x00),
+	PHYREGS(0x08fa, 0x08f6, 0x08f2, 0x01c8, 0x01c9, 0x01ca),
+  },
+  {	.freq			= 5740,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3e, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x05, 0x00,
+		   0x20, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+		   0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x06, 0x00, 0x6d, 0x00),
+	PHYREGS(0x08fc, 0x08f8, 0x08f4, 0x01c8, 0x01c9, 0x01c9),
+  },
+  {	.freq			= 5745,
+	RADIOREGS3(0xfe, 0x00, 0x02, 0x04, 0x7d, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x05, 0x05, 0x05, 0x87, 0x05, 0x00,
+		   0x20, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+		   0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x06, 0x00, 0x6d, 0x00),
+	PHYREGS(0x08fe, 0x08fa, 0x08f6, 0x01c8, 0x01c8, 0x01c9),
+  },
+  {	.freq			= 5750,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3f, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x05, 0x00,
+		   0x20, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+		   0x00, 0x6d, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x05, 0x00, 0x6d, 0x00),
+	PHYREGS(0x0900, 0x08fc, 0x08f8, 0x01c7, 0x01c8, 0x01c9),
+  },
+  {	.freq			= 5755,
+	RADIOREGS3(0xfe, 0x00, 0x02, 0x04, 0x7f, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x05, 0x05, 0x05, 0x87, 0x05, 0x00,
+		   0x10, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+		   0x00, 0x6c, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x05, 0x00, 0x6c, 0x00),
+	PHYREGS(0x0902, 0x08fe, 0x08fa, 0x01c7, 0x01c8, 0x01c8),
+  },
+  {	.freq			= 5760,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x40, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x86, 0x05, 0x00,
+		   0x10, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+		   0x00, 0x6c, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x05, 0x00, 0x6c, 0x00),
+	PHYREGS(0x0904, 0x0900, 0x08fc, 0x01c6, 0x01c7, 0x01c8),
+  },
+  {	.freq			= 5765,
+	RADIOREGS3(0xf8, 0x00, 0x02, 0x04, 0x81, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x05, 0x05, 0x05, 0x86, 0x05, 0x00,
+		   0x10, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+		   0x00, 0x6c, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x05, 0x00, 0x6c, 0x00),
+	PHYREGS(0x0906, 0x0902, 0x08fe, 0x01c6, 0x01c7, 0x01c8),
+  },
+  {	.freq			= 5770,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x41, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x86, 0x04, 0x00,
+		   0x10, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+		   0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x05, 0x00, 0x6b, 0x00),
+	PHYREGS(0x0908, 0x0904, 0x0900, 0x01c6, 0x01c6, 0x01c7),
+  },
+  {	.freq			= 5775,
+	RADIOREGS3(0xf8, 0x00, 0x02, 0x04, 0x83, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x05, 0x05, 0x05, 0x86, 0x04, 0x00,
+		   0x10, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+		   0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x05, 0x00, 0x6b, 0x00),
+	PHYREGS(0x090a, 0x0906, 0x0902, 0x01c5, 0x01c6, 0x01c7),
+  },
+  {	.freq			= 5780,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x42, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x86, 0x04, 0x00,
+		   0x10, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+		   0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x05, 0x00, 0x6b, 0x00),
+	PHYREGS(0x090c, 0x0908, 0x0904, 0x01c5, 0x01c6, 0x01c6),
+  },
+  {	.freq			= 5785,
+	RADIOREGS3(0xf2, 0x00, 0x02, 0x04, 0x85, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00,
+		   0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+		   0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x05, 0x00, 0x6b, 0x00),
+	PHYREGS(0x090e, 0x090a, 0x0906, 0x01c4, 0x01c5, 0x01c6),
+  },
+  {	.freq			= 5790,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x43, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00,
+		   0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+		   0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x05, 0x00, 0x6b, 0x00),
+	PHYREGS(0x0910, 0x090c, 0x0908, 0x01c4, 0x01c5, 0x01c6),
+  },
+  {	.freq			= 5795,
+	RADIOREGS3(0xf2, 0x00, 0x02, 0x04, 0x87, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00,
+		   0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+		   0x00, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x05, 0x00, 0x6b, 0x00),
+	PHYREGS(0x0912, 0x090e, 0x090a, 0x01c4, 0x01c4, 0x01c5),
+  },
+  {	.freq			= 5800,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x44, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00,
+		   0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+		   0x00, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x05, 0x00, 0x6b, 0x00),
+	PHYREGS(0x0914, 0x0910, 0x090c, 0x01c3, 0x01c4, 0x01c5),
+  },
+  {	.freq			= 5805,
+	RADIOREGS3(0xed, 0x00, 0x02, 0x04, 0x89, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00,
+		   0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+		   0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x05, 0x00, 0x6a, 0x00),
+	PHYREGS(0x0916, 0x0912, 0x090e, 0x01c3, 0x01c4, 0x01c4),
+  },
+  {	.freq			= 5810,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x45, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00,
+		   0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+		   0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x05, 0x00, 0x6a, 0x00),
+	PHYREGS(0x0918, 0x0914, 0x0910, 0x01c2, 0x01c3, 0x01c4),
+  },
+  {	.freq			= 5815,
+	RADIOREGS3(0xed, 0x00, 0x02, 0x04, 0x8b, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00,
+		   0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+		   0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x05, 0x00, 0x6a, 0x00),
+	PHYREGS(0x091a, 0x0916, 0x0912, 0x01c2, 0x01c3, 0x01c4),
+  },
+  {	.freq			= 5820,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x46, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00,
+		   0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+		   0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x05, 0x00, 0x6a, 0x00),
+	PHYREGS(0x091c, 0x0918, 0x0914, 0x01c2, 0x01c2, 0x01c3),
+  },
+  {	.freq			= 5825,
+	RADIOREGS3(0xed, 0x00, 0x02, 0x04, 0x8d, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00,
+		   0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+		   0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x05, 0x00, 0x69, 0x00),
+	PHYREGS(0x091e, 0x091a, 0x0916, 0x01c1, 0x01c2, 0x01c3),
+  },
+  {	.freq			= 5830,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x47, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00,
+		   0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+		   0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x05, 0x00, 0x69, 0x00),
+	PHYREGS(0x0920, 0x091c, 0x0918, 0x01c1, 0x01c2, 0x01c2),
+  },
+  {	.freq			= 5840,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x48, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00,
+		   0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+		   0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x04, 0x00, 0x69, 0x00),
+	PHYREGS(0x0924, 0x0920, 0x091c, 0x01c0, 0x01c1, 0x01c2),
+  },
+  {	.freq			= 5850,
+	RADIOREGS3(0xe0, 0x00, 0x01, 0x02, 0x49, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00,
+		   0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+		   0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x04, 0x00, 0x69, 0x00),
+	PHYREGS(0x0928, 0x0924, 0x0920, 0x01bf, 0x01c0, 0x01c1),
+  },
+  {	.freq			= 5860,
+	RADIOREGS3(0xde, 0x00, 0x01, 0x02, 0x4a, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00,
+		   0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+		   0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x04, 0x00, 0x69, 0x00),
+	PHYREGS(0x092c, 0x0928, 0x0924, 0x01bf, 0x01bf, 0x01c0),
+  },
+  {	.freq			= 5870,
+	RADIOREGS3(0xdb, 0x00, 0x01, 0x02, 0x4b, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00,
+		   0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+		   0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x04, 0x00, 0x68, 0x00),
+	PHYREGS(0x0930, 0x092c, 0x0928, 0x01be, 0x01bf, 0x01bf),
+  },
+  {	.freq			= 5880,
+	RADIOREGS3(0xd8, 0x00, 0x01, 0x02, 0x4c, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00,
+		   0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+		   0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x04, 0x00, 0x68, 0x00),
+	PHYREGS(0x0934, 0x0930, 0x092c, 0x01bd, 0x01be, 0x01bf),
+  },
+  {	.freq			= 5890,
+	RADIOREGS3(0xd6, 0x00, 0x01, 0x02, 0x4d, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00,
+		   0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+		   0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x04, 0x00, 0x68, 0x00),
+	PHYREGS(0x0938, 0x0934, 0x0930, 0x01bc, 0x01bd, 0x01be),
+  },
+  {	.freq			= 5900,
+	RADIOREGS3(0xd3, 0x00, 0x01, 0x02, 0x4e, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00,
+		   0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+		   0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x04, 0x00, 0x68, 0x00),
+	PHYREGS(0x093c, 0x0938, 0x0934, 0x01bc, 0x01bc, 0x01bd),
+  },
+  {	.freq			= 5910,
+	RADIOREGS3(0xd6, 0x00, 0x01, 0x02, 0x4f, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00,
+		   0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+		   0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x04, 0x00, 0x68, 0x00),
+	PHYREGS(0x0940, 0x093c, 0x0938, 0x01bb, 0x01bc, 0x01bc),
+  },
+  {	.freq			= 2412,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x6c, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x04, 0x04, 0x04, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x78, 0x00, 0x03, 0x00, 0x70, 0x00,
+		   0x0b, 0x00, 0x0a, 0x00, 0x89, 0x00, 0x03, 0x00,
+		   0x70, 0x00, 0x0b, 0x00, 0x0a),
+	PHYREGS(0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443),
+  },
+  {	.freq			= 2417,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x71, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x78, 0x00, 0x03, 0x00, 0x70, 0x00,
+		   0x0b, 0x00, 0x0a, 0x00, 0x89, 0x00, 0x03, 0x00,
+		   0x70, 0x00, 0x0b, 0x00, 0x0a),
+	PHYREGS(0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441),
+  },
+  {	.freq			= 2422,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x76, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x67, 0x00, 0x03, 0x00, 0x70, 0x00,
+		   0x0b, 0x00, 0x0a, 0x00, 0x89, 0x00, 0x03, 0x00,
+		   0x70, 0x00, 0x0b, 0x00, 0x0a),
+	PHYREGS(0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f),
+  },
+  {	.freq			= 2427,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x7b, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x57, 0x00, 0x03, 0x00, 0x70, 0x00,
+		   0x0a, 0x00, 0x0a, 0x00, 0x78, 0x00, 0x03, 0x00,
+		   0x70, 0x00, 0x0a, 0x00, 0x0a),
+	PHYREGS(0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d),
+  },
+  {	.freq			= 2432,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x80, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x56, 0x00, 0x03, 0x00, 0x70, 0x00,
+		   0x0a, 0x00, 0x0a, 0x00, 0x77, 0x00, 0x03, 0x00,
+		   0x70, 0x00, 0x0a, 0x00, 0x0a),
+	PHYREGS(0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a),
+  },
+  {	.freq			= 2437,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x85, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x46, 0x00, 0x03, 0x00, 0x70, 0x00,
+		   0x0a, 0x00, 0x0a, 0x00, 0x76, 0x00, 0x03, 0x00,
+		   0x70, 0x00, 0x0a, 0x00, 0x0a),
+	PHYREGS(0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438),
+  },
+  {	.freq			= 2442,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x8a, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x45, 0x00, 0x02, 0x00, 0x70, 0x00,
+		   0x0a, 0x00, 0x0a, 0x00, 0x66, 0x00, 0x02, 0x00,
+		   0x70, 0x00, 0x0a, 0x00, 0x0a),
+	PHYREGS(0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436),
+  },
+  {	.freq			= 2447,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x8f, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x34, 0x00, 0x02, 0x00, 0x70, 0x00,
+		   0x0a, 0x00, 0x09, 0x00, 0x55, 0x00, 0x02, 0x00,
+		   0x70, 0x00, 0x0a, 0x00, 0x09),
+	PHYREGS(0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434),
+  },
+  {	.freq			= 2452,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x94, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x23, 0x00, 0x02, 0x00, 0x70, 0x00,
+		   0x0a, 0x00, 0x09, 0x00, 0x45, 0x00, 0x02, 0x00,
+		   0x70, 0x00, 0x0a, 0x00, 0x09),
+	PHYREGS(0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431),
+  },
+  {	.freq			= 2457,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x99, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x12, 0x00, 0x02, 0x00, 0x70, 0x00,
+		   0x0a, 0x00, 0x09, 0x00, 0x34, 0x00, 0x02, 0x00,
+		   0x70, 0x00, 0x0a, 0x00, 0x09),
+	PHYREGS(0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f),
+  },
+  {	.freq			= 2462,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x9e, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x70, 0x00,
+		   0x09, 0x00, 0x09, 0x00, 0x33, 0x00, 0x02, 0x00,
+		   0x70, 0x00, 0x09, 0x00, 0x09),
+	PHYREGS(0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d),
+  },
+  {	.freq			= 2467,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0xa3, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x70, 0x00,
+		   0x09, 0x00, 0x09, 0x00, 0x22, 0x00, 0x02, 0x00,
+		   0x70, 0x00, 0x09, 0x00, 0x09),
+	PHYREGS(0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b),
+  },
+  {	.freq			= 2472,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0xa8, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x70, 0x00,
+		   0x09, 0x00, 0x09, 0x00, 0x11, 0x00, 0x02, 0x00,
+		   0x70, 0x00, 0x09, 0x00, 0x09),
+	PHYREGS(0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429),
+  },
+  {	.freq			= 2484,
+	RADIOREGS3(0xff, 0x01, 0x03, 0x09, 0xb4, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x07, 0x07, 0x07, 0x8f, 0x20, 0x00,
+		   0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x70, 0x00,
+		   0x09, 0x00, 0x09, 0x00, 0x00, 0x00, 0x02, 0x00,
+		   0x70, 0x00, 0x09, 0x00, 0x09),
+	PHYREGS(0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424),
+  },
+};
+
+static void b2056_upload_inittab(struct b43_wldev *dev, bool ghz5,
+				 bool ignore_uploadflag, u16 routing,
+				 const struct b2056_inittab_entry *e,
+				 unsigned int length)
+{
+	unsigned int i;
+	u16 value;
+
+	for (i = 0; i < length; i++, e++) {
+		if (!(e->flags & B2056_INITTAB_ENTRY_OK))
+			continue;
+		if ((e->flags & B2056_INITTAB_UPLOAD) || ignore_uploadflag) {
+			if (ghz5)
+				value = e->ghz5;
+			else
+				value = e->ghz2;
+			b43_radio_write(dev, routing | i, value);
+		}
+	}
+}
+
+void b2056_upload_inittabs(struct b43_wldev *dev,
+			   bool ghz5, bool ignore_uploadflag)
+{
+	struct b2056_inittabs_pts *pts;
+
+	if (dev->phy.rev >= ARRAY_SIZE(b2056_inittabs)) {
+		B43_WARN_ON(1);
+		return;
+	}
+	pts = &b2056_inittabs[dev->phy.rev];
+
+	b2056_upload_inittab(dev, ghz5, ignore_uploadflag,
+				B2056_SYN, pts->syn, pts->syn_length);
+	b2056_upload_inittab(dev, ghz5, ignore_uploadflag,
+				B2056_TX0, pts->tx, pts->tx_length);
+	b2056_upload_inittab(dev, ghz5, ignore_uploadflag,
+				B2056_TX1, pts->tx, pts->tx_length);
+	b2056_upload_inittab(dev, ghz5, ignore_uploadflag,
+				B2056_RX0, pts->rx, pts->rx_length);
+	b2056_upload_inittab(dev, ghz5, ignore_uploadflag,
+				B2056_RX1, pts->rx, pts->rx_length);
+}
+
 const struct b43_nphy_channeltab_entry_rev3 *
 b43_nphy_get_chantabent_rev3(struct b43_wldev *dev, u16 freq)
 {
 	const struct b43_nphy_channeltab_entry_rev3 *e;
-	unsigned int i;
+	unsigned int length, i;
 
-	for (i = 0; i < ARRAY_SIZE(b43_nphy_channeltab_rev3); i++) {
-		e = &(b43_nphy_channeltab_rev3[i]);
+	switch (dev->phy.rev) {
+	case 3:
+		e = b43_nphy_channeltab_rev3;
+		length = ARRAY_SIZE(b43_nphy_channeltab_rev3);
+		break;
+	case 4:
+		e = b43_nphy_channeltab_rev4;
+		length = ARRAY_SIZE(b43_nphy_channeltab_rev4);
+		break;
+	case 5:
+		e = b43_nphy_channeltab_rev5;
+		length = ARRAY_SIZE(b43_nphy_channeltab_rev5);
+		break;
+	case 6:
+		e = b43_nphy_channeltab_rev6;
+		length = ARRAY_SIZE(b43_nphy_channeltab_rev6);
+		break;
+	case 7:
+	case 9:
+		e = b43_nphy_channeltab_rev7_9;
+		length = ARRAY_SIZE(b43_nphy_channeltab_rev7_9);
+		break;
+	case 8:
+		e = b43_nphy_channeltab_rev8;
+		length = ARRAY_SIZE(b43_nphy_channeltab_rev8);
+		break;
+	default:
+		B43_WARN_ON(1);
+		return NULL;
+	}
+
+	for (i = 0; i < length; i++, e++) {
 		if (e->freq == freq)
 			return e;
 	}
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/b43/radio_2056.h linux-libre-2.6.38-gnu1/drivers/net/wireless/b43/radio_2056.h
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/b43/radio_2056.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/b43/radio_2056.h	2011-03-14 21:20:32.000000000 -0400
@@ -4,6 +4,9 @@
 
   Copyright (c) 2010 Rafał Miłecki <zajec5@gmail.com>
 
+  Some parts of the code in this file are derived from the brcm80211
+  driver  Copyright (c) 2010 Broadcom 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
@@ -28,15 +31,1090 @@
 
 #include "tables_nphy.h"
 
+#define B2056_SYN			(0x0 << 12)
+#define B2056_TX0			(0x2 << 12)
+#define B2056_TX1			(0x3 << 12)
+#define B2056_RX0			(0x6 << 12)
+#define B2056_RX1			(0x7 << 12)
+#define B2056_ALLTX			(0xE << 12)
+#define B2056_ALLRX			(0xF << 12)
+
+#define B2056_SYN_RESERVED_ADDR0	0x00
+#define B2056_SYN_IDCODE		0x01
+#define B2056_SYN_RESERVED_ADDR2	0x02
+#define B2056_SYN_RESERVED_ADDR3	0x03
+#define B2056_SYN_RESERVED_ADDR4	0x04
+#define B2056_SYN_RESERVED_ADDR5	0x05
+#define B2056_SYN_RESERVED_ADDR6	0x06
+#define B2056_SYN_RESERVED_ADDR7	0x07
+#define B2056_SYN_COM_CTRL		0x08
+#define B2056_SYN_COM_PU		0x09
+#define B2056_SYN_COM_OVR		0x0A
+#define B2056_SYN_COM_RESET		0x0B
+#define B2056_SYN_COM_RCAL		0x0C
+#define B2056_SYN_COM_RC_RXLPF		0x0D
+#define B2056_SYN_COM_RC_TXLPF		0x0E
+#define B2056_SYN_COM_RC_RXHPF		0x0F
+#define B2056_SYN_RESERVED_ADDR16	0x10
+#define B2056_SYN_RESERVED_ADDR17	0x11
+#define B2056_SYN_RESERVED_ADDR18	0x12
+#define B2056_SYN_RESERVED_ADDR19	0x13
+#define B2056_SYN_RESERVED_ADDR20	0x14
+#define B2056_SYN_RESERVED_ADDR21	0x15
+#define B2056_SYN_RESERVED_ADDR22	0x16
+#define B2056_SYN_RESERVED_ADDR23	0x17
+#define B2056_SYN_RESERVED_ADDR24	0x18
+#define B2056_SYN_RESERVED_ADDR25	0x19
+#define B2056_SYN_RESERVED_ADDR26	0x1A
+#define B2056_SYN_RESERVED_ADDR27	0x1B
+#define B2056_SYN_RESERVED_ADDR28	0x1C
+#define B2056_SYN_RESERVED_ADDR29	0x1D
+#define B2056_SYN_RESERVED_ADDR30	0x1E
+#define B2056_SYN_RESERVED_ADDR31	0x1F
+#define B2056_SYN_GPIO_MASTER1		0x20
+#define B2056_SYN_GPIO_MASTER2		0x21
+#define B2056_SYN_TOPBIAS_MASTER	0x22
+#define B2056_SYN_TOPBIAS_RCAL		0x23
+#define B2056_SYN_AFEREG		0x24
+#define B2056_SYN_TEMPPROCSENSE		0x25
+#define B2056_SYN_TEMPPROCSENSEIDAC	0x26
+#define B2056_SYN_TEMPPROCSENSERCAL	0x27
+#define B2056_SYN_LPO			0x28
+#define B2056_SYN_VDDCAL_MASTER		0x29
+#define B2056_SYN_VDDCAL_IDAC		0x2A
+#define B2056_SYN_VDDCAL_STATUS		0x2B
+#define B2056_SYN_RCAL_MASTER		0x2C
+#define B2056_SYN_RCAL_CODE_OUT		0x2D
+#define B2056_SYN_RCCAL_CTRL0		0x2E
+#define B2056_SYN_RCCAL_CTRL1		0x2F
+#define B2056_SYN_RCCAL_CTRL2		0x30
+#define B2056_SYN_RCCAL_CTRL3		0x31
+#define B2056_SYN_RCCAL_CTRL4		0x32
+#define B2056_SYN_RCCAL_CTRL5		0x33
+#define B2056_SYN_RCCAL_CTRL6		0x34
+#define B2056_SYN_RCCAL_CTRL7		0x35
+#define B2056_SYN_RCCAL_CTRL8		0x36
+#define B2056_SYN_RCCAL_CTRL9		0x37
+#define B2056_SYN_RCCAL_CTRL10		0x38
+#define B2056_SYN_RCCAL_CTRL11		0x39
+#define B2056_SYN_ZCAL_SPARE1		0x3A
+#define B2056_SYN_ZCAL_SPARE2		0x3B
+#define B2056_SYN_PLL_MAST1		0x3C
+#define B2056_SYN_PLL_MAST2		0x3D
+#define B2056_SYN_PLL_MAST3		0x3E
+#define B2056_SYN_PLL_BIAS_RESET	0x3F
+#define B2056_SYN_PLL_XTAL0		0x40
+#define B2056_SYN_PLL_XTAL1		0x41
+#define B2056_SYN_PLL_XTAL3		0x42
+#define B2056_SYN_PLL_XTAL4		0x43
+#define B2056_SYN_PLL_XTAL5		0x44
+#define B2056_SYN_PLL_XTAL6		0x45
+#define B2056_SYN_PLL_REFDIV		0x46
+#define B2056_SYN_PLL_PFD		0x47
+#define B2056_SYN_PLL_CP1		0x48
+#define B2056_SYN_PLL_CP2		0x49
+#define B2056_SYN_PLL_CP3		0x4A
+#define B2056_SYN_PLL_LOOPFILTER1	0x4B
+#define B2056_SYN_PLL_LOOPFILTER2	0x4C
+#define B2056_SYN_PLL_LOOPFILTER3	0x4D
+#define B2056_SYN_PLL_LOOPFILTER4	0x4E
+#define B2056_SYN_PLL_LOOPFILTER5	0x4F
+#define B2056_SYN_PLL_MMD1		0x50
+#define B2056_SYN_PLL_MMD2		0x51
+#define B2056_SYN_PLL_VCO1		0x52
+#define B2056_SYN_PLL_VCO2		0x53
+#define B2056_SYN_PLL_MONITOR1		0x54
+#define B2056_SYN_PLL_MONITOR2		0x55
+#define B2056_SYN_PLL_VCOCAL1		0x56
+#define B2056_SYN_PLL_VCOCAL2		0x57
+#define B2056_SYN_PLL_VCOCAL4		0x58
+#define B2056_SYN_PLL_VCOCAL5		0x59
+#define B2056_SYN_PLL_VCOCAL6		0x5A
+#define B2056_SYN_PLL_VCOCAL7		0x5B
+#define B2056_SYN_PLL_VCOCAL8		0x5C
+#define B2056_SYN_PLL_VCOCAL9		0x5D
+#define B2056_SYN_PLL_VCOCAL10		0x5E
+#define B2056_SYN_PLL_VCOCAL11		0x5F
+#define B2056_SYN_PLL_VCOCAL12		0x60
+#define B2056_SYN_PLL_VCOCAL13		0x61
+#define B2056_SYN_PLL_VREG		0x62
+#define B2056_SYN_PLL_STATUS1		0x63
+#define B2056_SYN_PLL_STATUS2		0x64
+#define B2056_SYN_PLL_STATUS3		0x65
+#define B2056_SYN_LOGEN_PU0		0x66
+#define B2056_SYN_LOGEN_PU1		0x67
+#define B2056_SYN_LOGEN_PU2		0x68
+#define B2056_SYN_LOGEN_PU3		0x69
+#define B2056_SYN_LOGEN_PU5		0x6A
+#define B2056_SYN_LOGEN_PU6		0x6B
+#define B2056_SYN_LOGEN_PU7		0x6C
+#define B2056_SYN_LOGEN_PU8		0x6D
+#define B2056_SYN_LOGEN_BIAS_RESET	0x6E
+#define B2056_SYN_LOGEN_RCCR1		0x6F
+#define B2056_SYN_LOGEN_VCOBUF1		0x70
+#define B2056_SYN_LOGEN_MIXER1		0x71
+#define B2056_SYN_LOGEN_MIXER2		0x72
+#define B2056_SYN_LOGEN_BUF1		0x73
+#define B2056_SYN_LOGENBUF2		0x74
+#define B2056_SYN_LOGEN_BUF3		0x75
+#define B2056_SYN_LOGEN_BUF4		0x76
+#define B2056_SYN_LOGEN_DIV1		0x77
+#define B2056_SYN_LOGEN_DIV2		0x78
+#define B2056_SYN_LOGEN_DIV3		0x79
+#define B2056_SYN_LOGEN_ACL1		0x7A
+#define B2056_SYN_LOGEN_ACL2		0x7B
+#define B2056_SYN_LOGEN_ACL3		0x7C
+#define B2056_SYN_LOGEN_ACL4		0x7D
+#define B2056_SYN_LOGEN_ACL5		0x7E
+#define B2056_SYN_LOGEN_ACL6		0x7F
+#define B2056_SYN_LOGEN_ACLOUT		0x80
+#define B2056_SYN_LOGEN_ACLCAL1		0x81
+#define B2056_SYN_LOGEN_ACLCAL2		0x82
+#define B2056_SYN_LOGEN_ACLCAL3		0x83
+#define B2056_SYN_CALEN			0x84
+#define B2056_SYN_LOGEN_PEAKDET1	0x85
+#define B2056_SYN_LOGEN_CORE_ACL_OVR	0x86
+#define B2056_SYN_LOGEN_RX_DIFF_ACL_OVR	0x87
+#define B2056_SYN_LOGEN_TX_DIFF_ACL_OVR	0x88
+#define B2056_SYN_LOGEN_RX_CMOS_ACL_OVR	0x89
+#define B2056_SYN_LOGEN_TX_CMOS_ACL_OVR	0x8A
+#define B2056_SYN_LOGEN_VCOBUF2		0x8B
+#define B2056_SYN_LOGEN_MIXER3		0x8C
+#define B2056_SYN_LOGEN_BUF5		0x8D
+#define B2056_SYN_LOGEN_BUF6		0x8E
+#define B2056_SYN_LOGEN_CBUFRX1		0x8F
+#define B2056_SYN_LOGEN_CBUFRX2		0x90
+#define B2056_SYN_LOGEN_CBUFRX3		0x91
+#define B2056_SYN_LOGEN_CBUFRX4		0x92
+#define B2056_SYN_LOGEN_CBUFTX1		0x93
+#define B2056_SYN_LOGEN_CBUFTX2		0x94
+#define B2056_SYN_LOGEN_CBUFTX3		0x95
+#define B2056_SYN_LOGEN_CBUFTX4		0x96
+#define B2056_SYN_LOGEN_CMOSRX1		0x97
+#define B2056_SYN_LOGEN_CMOSRX2		0x98
+#define B2056_SYN_LOGEN_CMOSRX3		0x99
+#define B2056_SYN_LOGEN_CMOSRX4		0x9A
+#define B2056_SYN_LOGEN_CMOSTX1		0x9B
+#define B2056_SYN_LOGEN_CMOSTX2		0x9C
+#define B2056_SYN_LOGEN_CMOSTX3		0x9D
+#define B2056_SYN_LOGEN_CMOSTX4		0x9E
+#define B2056_SYN_LOGEN_VCOBUF2_OVRVAL	0x9F
+#define B2056_SYN_LOGEN_MIXER3_OVRVAL	0xA0
+#define B2056_SYN_LOGEN_BUF5_OVRVAL	0xA1
+#define B2056_SYN_LOGEN_BUF6_OVRVAL	0xA2
+#define B2056_SYN_LOGEN_CBUFRX1_OVRVAL	0xA3
+#define B2056_SYN_LOGEN_CBUFRX2_OVRVAL	0xA4
+#define B2056_SYN_LOGEN_CBUFRX3_OVRVAL	0xA5
+#define B2056_SYN_LOGEN_CBUFRX4_OVRVAL	0xA6
+#define B2056_SYN_LOGEN_CBUFTX1_OVRVAL	0xA7
+#define B2056_SYN_LOGEN_CBUFTX2_OVRVAL	0xA8
+#define B2056_SYN_LOGEN_CBUFTX3_OVRVAL	0xA9
+#define B2056_SYN_LOGEN_CBUFTX4_OVRVAL	0xAA
+#define B2056_SYN_LOGEN_CMOSRX1_OVRVAL	0xAB
+#define B2056_SYN_LOGEN_CMOSRX2_OVRVAL	0xAC
+#define B2056_SYN_LOGEN_CMOSRX3_OVRVAL	0xAD
+#define B2056_SYN_LOGEN_CMOSRX4_OVRVAL	0xAE
+#define B2056_SYN_LOGEN_CMOSTX1_OVRVAL	0xAF
+#define B2056_SYN_LOGEN_CMOSTX2_OVRVAL	0xB0
+#define B2056_SYN_LOGEN_CMOSTX3_OVRVAL	0xB1
+#define B2056_SYN_LOGEN_CMOSTX4_OVRVAL	0xB2
+#define B2056_SYN_LOGEN_ACL_WAITCNT	0xB3
+#define B2056_SYN_LOGEN_CORE_CALVALID	0xB4
+#define B2056_SYN_LOGEN_RX_CMOS_CALVALID	0xB5
+#define B2056_SYN_LOGEN_TX_CMOS_VALID	0xB6
+
+#define B2056_TX_RESERVED_ADDR0		0x00
+#define B2056_TX_IDCODE			0x01
+#define B2056_TX_RESERVED_ADDR2		0x02
+#define B2056_TX_RESERVED_ADDR3		0x03
+#define B2056_TX_RESERVED_ADDR4		0x04
+#define B2056_TX_RESERVED_ADDR5		0x05
+#define B2056_TX_RESERVED_ADDR6		0x06
+#define B2056_TX_RESERVED_ADDR7		0x07
+#define B2056_TX_COM_CTRL		0x08
+#define B2056_TX_COM_PU			0x09
+#define B2056_TX_COM_OVR		0x0A
+#define B2056_TX_COM_RESET		0x0B
+#define B2056_TX_COM_RCAL		0x0C
+#define B2056_TX_COM_RC_RXLPF		0x0D
+#define B2056_TX_COM_RC_TXLPF		0x0E
+#define B2056_TX_COM_RC_RXHPF		0x0F
+#define B2056_TX_RESERVED_ADDR16	0x10
+#define B2056_TX_RESERVED_ADDR17	0x11
+#define B2056_TX_RESERVED_ADDR18	0x12
+#define B2056_TX_RESERVED_ADDR19	0x13
+#define B2056_TX_RESERVED_ADDR20	0x14
+#define B2056_TX_RESERVED_ADDR21	0x15
+#define B2056_TX_RESERVED_ADDR22	0x16
+#define B2056_TX_RESERVED_ADDR23	0x17
+#define B2056_TX_RESERVED_ADDR24	0x18
+#define B2056_TX_RESERVED_ADDR25	0x19
+#define B2056_TX_RESERVED_ADDR26	0x1A
+#define B2056_TX_RESERVED_ADDR27	0x1B
+#define B2056_TX_RESERVED_ADDR28	0x1C
+#define B2056_TX_RESERVED_ADDR29	0x1D
+#define B2056_TX_RESERVED_ADDR30	0x1E
+#define B2056_TX_RESERVED_ADDR31	0x1F
+#define B2056_TX_IQCAL_GAIN_BW		0x20
+#define B2056_TX_LOFT_FINE_I		0x21
+#define B2056_TX_LOFT_FINE_Q		0x22
+#define B2056_TX_LOFT_COARSE_I		0x23
+#define B2056_TX_LOFT_COARSE_Q		0x24
+#define B2056_TX_TX_COM_MASTER1		0x25
+#define B2056_TX_TX_COM_MASTER2		0x26
+#define B2056_TX_RXIQCAL_TXMUX		0x27
+#define B2056_TX_TX_SSI_MASTER		0x28
+#define B2056_TX_IQCAL_VCM_HG		0x29
+#define B2056_TX_IQCAL_IDAC		0x2A
+#define B2056_TX_TSSI_VCM		0x2B
+#define B2056_TX_TX_AMP_DET		0x2C
+#define B2056_TX_TX_SSI_MUX		0x2D
+#define B2056_TX_TSSIA			0x2E
+#define B2056_TX_TSSIG			0x2F
+#define B2056_TX_TSSI_MISC1		0x30
+#define B2056_TX_TSSI_MISC2		0x31
+#define B2056_TX_TSSI_MISC3		0x32
+#define B2056_TX_PA_SPARE1		0x33
+#define B2056_TX_PA_SPARE2		0x34
+#define B2056_TX_INTPAA_MASTER		0x35
+#define B2056_TX_INTPAA_GAIN		0x36
+#define B2056_TX_INTPAA_BOOST_TUNE	0x37
+#define B2056_TX_INTPAA_IAUX_STAT	0x38
+#define B2056_TX_INTPAA_IAUX_DYN	0x39
+#define B2056_TX_INTPAA_IMAIN_STAT	0x3A
+#define B2056_TX_INTPAA_IMAIN_DYN	0x3B
+#define B2056_TX_INTPAA_CASCBIAS	0x3C
+#define B2056_TX_INTPAA_PASLOPE		0x3D
+#define B2056_TX_INTPAA_PA_MISC		0x3E
+#define B2056_TX_INTPAG_MASTER		0x3F
+#define B2056_TX_INTPAG_GAIN		0x40
+#define B2056_TX_INTPAG_BOOST_TUNE	0x41
+#define B2056_TX_INTPAG_IAUX_STAT	0x42
+#define B2056_TX_INTPAG_IAUX_DYN	0x43
+#define B2056_TX_INTPAG_IMAIN_STAT	0x44
+#define B2056_TX_INTPAG_IMAIN_DYN	0x45
+#define B2056_TX_INTPAG_CASCBIAS	0x46
+#define B2056_TX_INTPAG_PASLOPE		0x47
+#define B2056_TX_INTPAG_PA_MISC		0x48
+#define B2056_TX_PADA_MASTER		0x49
+#define B2056_TX_PADA_IDAC		0x4A
+#define B2056_TX_PADA_CASCBIAS		0x4B
+#define B2056_TX_PADA_GAIN		0x4C
+#define B2056_TX_PADA_BOOST_TUNE	0x4D
+#define B2056_TX_PADA_SLOPE		0x4E
+#define B2056_TX_PADG_MASTER		0x4F
+#define B2056_TX_PADG_IDAC		0x50
+#define B2056_TX_PADG_CASCBIAS		0x51
+#define B2056_TX_PADG_GAIN		0x52
+#define B2056_TX_PADG_BOOST_TUNE	0x53
+#define B2056_TX_PADG_SLOPE		0x54
+#define B2056_TX_PGAA_MASTER		0x55
+#define B2056_TX_PGAA_IDAC		0x56
+#define B2056_TX_PGAA_GAIN		0x57
+#define B2056_TX_PGAA_BOOST_TUNE	0x58
+#define B2056_TX_PGAA_SLOPE		0x59
+#define B2056_TX_PGAA_MISC		0x5A
+#define B2056_TX_PGAG_MASTER		0x5B
+#define B2056_TX_PGAG_IDAC		0x5C
+#define B2056_TX_PGAG_GAIN		0x5D
+#define B2056_TX_PGAG_BOOST_TUNE	0x5E
+#define B2056_TX_PGAG_SLOPE		0x5F
+#define B2056_TX_PGAG_MISC		0x60
+#define B2056_TX_MIXA_MASTER		0x61
+#define B2056_TX_MIXA_BOOST_TUNE	0x62
+#define B2056_TX_MIXG			0x63
+#define B2056_TX_MIXG_BOOST_TUNE	0x64
+#define B2056_TX_BB_GM_MASTER		0x65
+#define B2056_TX_GMBB_GM		0x66
+#define B2056_TX_GMBB_IDAC		0x67
+#define B2056_TX_TXLPF_MASTER		0x68
+#define B2056_TX_TXLPF_RCCAL		0x69
+#define B2056_TX_TXLPF_RCCAL_OFF0	0x6A
+#define B2056_TX_TXLPF_RCCAL_OFF1	0x6B
+#define B2056_TX_TXLPF_RCCAL_OFF2	0x6C
+#define B2056_TX_TXLPF_RCCAL_OFF3	0x6D
+#define B2056_TX_TXLPF_RCCAL_OFF4	0x6E
+#define B2056_TX_TXLPF_RCCAL_OFF5	0x6F
+#define B2056_TX_TXLPF_RCCAL_OFF6	0x70
+#define B2056_TX_TXLPF_BW		0x71
+#define B2056_TX_TXLPF_GAIN		0x72
+#define B2056_TX_TXLPF_IDAC		0x73
+#define B2056_TX_TXLPF_IDAC_0		0x74
+#define B2056_TX_TXLPF_IDAC_1		0x75
+#define B2056_TX_TXLPF_IDAC_2		0x76
+#define B2056_TX_TXLPF_IDAC_3		0x77
+#define B2056_TX_TXLPF_IDAC_4		0x78
+#define B2056_TX_TXLPF_IDAC_5		0x79
+#define B2056_TX_TXLPF_IDAC_6		0x7A
+#define B2056_TX_TXLPF_OPAMP_IDAC	0x7B
+#define B2056_TX_TXLPF_MISC		0x7C
+#define B2056_TX_TXSPARE1		0x7D
+#define B2056_TX_TXSPARE2		0x7E
+#define B2056_TX_TXSPARE3		0x7F
+#define B2056_TX_TXSPARE4		0x80
+#define B2056_TX_TXSPARE5		0x81
+#define B2056_TX_TXSPARE6		0x82
+#define B2056_TX_TXSPARE7		0x83
+#define B2056_TX_TXSPARE8		0x84
+#define B2056_TX_TXSPARE9		0x85
+#define B2056_TX_TXSPARE10		0x86
+#define B2056_TX_TXSPARE11		0x87
+#define B2056_TX_TXSPARE12		0x88
+#define B2056_TX_TXSPARE13		0x89
+#define B2056_TX_TXSPARE14		0x8A
+#define B2056_TX_TXSPARE15		0x8B
+#define B2056_TX_TXSPARE16		0x8C
+#define B2056_TX_STATUS_INTPA_GAIN	0x8D
+#define B2056_TX_STATUS_PAD_GAIN	0x8E
+#define B2056_TX_STATUS_PGA_GAIN	0x8F
+#define B2056_TX_STATUS_GM_TXLPF_GAIN	0x90
+#define B2056_TX_STATUS_TXLPF_BW	0x91
+#define B2056_TX_STATUS_TXLPF_RC	0x92
+#define B2056_TX_GMBB_IDAC0		0x93
+#define B2056_TX_GMBB_IDAC1		0x94
+#define B2056_TX_GMBB_IDAC2		0x95
+#define B2056_TX_GMBB_IDAC3		0x96
+#define B2056_TX_GMBB_IDAC4		0x97
+#define B2056_TX_GMBB_IDAC5		0x98
+#define B2056_TX_GMBB_IDAC6		0x99
+#define B2056_TX_GMBB_IDAC7		0x9A
+
+#define B2056_RX_RESERVED_ADDR0		0x00
+#define B2056_RX_IDCODE			0x01
+#define B2056_RX_RESERVED_ADDR2		0x02
+#define B2056_RX_RESERVED_ADDR3		0x03
+#define B2056_RX_RESERVED_ADDR4		0x04
+#define B2056_RX_RESERVED_ADDR5		0x05
+#define B2056_RX_RESERVED_ADDR6		0x06
+#define B2056_RX_RESERVED_ADDR7		0x07
+#define B2056_RX_COM_CTRL		0x08
+#define B2056_RX_COM_PU			0x09
+#define B2056_RX_COM_OVR		0x0A
+#define B2056_RX_COM_RESET		0x0B
+#define B2056_RX_COM_RCAL		0x0C
+#define B2056_RX_COM_RC_RXLPF		0x0D
+#define B2056_RX_COM_RC_TXLPF		0x0E
+#define B2056_RX_COM_RC_RXHPF		0x0F
+#define B2056_RX_RESERVED_ADDR16	0x10
+#define B2056_RX_RESERVED_ADDR17	0x11
+#define B2056_RX_RESERVED_ADDR18	0x12
+#define B2056_RX_RESERVED_ADDR19	0x13
+#define B2056_RX_RESERVED_ADDR20	0x14
+#define B2056_RX_RESERVED_ADDR21	0x15
+#define B2056_RX_RESERVED_ADDR22	0x16
+#define B2056_RX_RESERVED_ADDR23	0x17
+#define B2056_RX_RESERVED_ADDR24	0x18
+#define B2056_RX_RESERVED_ADDR25	0x19
+#define B2056_RX_RESERVED_ADDR26	0x1A
+#define B2056_RX_RESERVED_ADDR27	0x1B
+#define B2056_RX_RESERVED_ADDR28	0x1C
+#define B2056_RX_RESERVED_ADDR29	0x1D
+#define B2056_RX_RESERVED_ADDR30	0x1E
+#define B2056_RX_RESERVED_ADDR31	0x1F
+#define B2056_RX_RXIQCAL_RXMUX		0x20
+#define B2056_RX_RSSI_PU		0x21
+#define B2056_RX_RSSI_SEL		0x22
+#define B2056_RX_RSSI_GAIN		0x23
+#define B2056_RX_RSSI_NB_IDAC		0x24
+#define B2056_RX_RSSI_WB2I_IDAC_1	0x25
+#define B2056_RX_RSSI_WB2I_IDAC_2	0x26
+#define B2056_RX_RSSI_WB2Q_IDAC_1	0x27
+#define B2056_RX_RSSI_WB2Q_IDAC_2	0x28
+#define B2056_RX_RSSI_POLE		0x29
+#define B2056_RX_RSSI_WB1_IDAC		0x2A
+#define B2056_RX_RSSI_MISC		0x2B
+#define B2056_RX_LNAA_MASTER		0x2C
+#define B2056_RX_LNAA_TUNE		0x2D
+#define B2056_RX_LNAA_GAIN		0x2E
+#define B2056_RX_LNA_A_SLOPE		0x2F
+#define B2056_RX_BIASPOLE_LNAA1_IDAC	0x30
+#define B2056_RX_LNAA2_IDAC		0x31
+#define B2056_RX_LNA1A_MISC		0x32
+#define B2056_RX_LNAG_MASTER		0x33
+#define B2056_RX_LNAG_TUNE		0x34
+#define B2056_RX_LNAG_GAIN		0x35
+#define B2056_RX_LNA_G_SLOPE		0x36
+#define B2056_RX_BIASPOLE_LNAG1_IDAC	0x37
+#define B2056_RX_LNAG2_IDAC		0x38
+#define B2056_RX_LNA1G_MISC		0x39
+#define B2056_RX_MIXA_MASTER		0x3A
+#define B2056_RX_MIXA_VCM		0x3B
+#define B2056_RX_MIXA_CTRLPTAT		0x3C
+#define B2056_RX_MIXA_LOB_BIAS		0x3D
+#define B2056_RX_MIXA_CORE_IDAC		0x3E
+#define B2056_RX_MIXA_CMFB_IDAC		0x3F
+#define B2056_RX_MIXA_BIAS_AUX		0x40
+#define B2056_RX_MIXA_BIAS_MAIN		0x41
+#define B2056_RX_MIXA_BIAS_MISC		0x42
+#define B2056_RX_MIXA_MAST_BIAS		0x43
+#define B2056_RX_MIXG_MASTER		0x44
+#define B2056_RX_MIXG_VCM		0x45
+#define B2056_RX_MIXG_CTRLPTAT		0x46
+#define B2056_RX_MIXG_LOB_BIAS		0x47
+#define B2056_RX_MIXG_CORE_IDAC		0x48
+#define B2056_RX_MIXG_CMFB_IDAC		0x49
+#define B2056_RX_MIXG_BIAS_AUX		0x4A
+#define B2056_RX_MIXG_BIAS_MAIN		0x4B
+#define B2056_RX_MIXG_BIAS_MISC		0x4C
+#define B2056_RX_MIXG_MAST_BIAS		0x4D
+#define B2056_RX_TIA_MASTER		0x4E
+#define B2056_RX_TIA_IOPAMP		0x4F
+#define B2056_RX_TIA_QOPAMP		0x50
+#define B2056_RX_TIA_IMISC		0x51
+#define B2056_RX_TIA_QMISC		0x52
+#define B2056_RX_TIA_GAIN		0x53
+#define B2056_RX_TIA_SPARE1		0x54
+#define B2056_RX_TIA_SPARE2		0x55
+#define B2056_RX_BB_LPF_MASTER		0x56
+#define B2056_RX_AACI_MASTER		0x57
+#define B2056_RX_RXLPF_IDAC		0x58
+#define B2056_RX_RXLPF_OPAMPBIAS_LOWQ	0x59
+#define B2056_RX_RXLPF_OPAMPBIAS_HIGHQ	0x5A
+#define B2056_RX_RXLPF_BIAS_DCCANCEL	0x5B
+#define B2056_RX_RXLPF_OUTVCM		0x5C
+#define B2056_RX_RXLPF_INVCM_BODY	0x5D
+#define B2056_RX_RXLPF_CC_OP		0x5E
+#define B2056_RX_RXLPF_GAIN		0x5F
+#define B2056_RX_RXLPF_Q_BW		0x60
+#define B2056_RX_RXLPF_HP_CORNER_BW	0x61
+#define B2056_RX_RXLPF_RCCAL_HPC	0x62
+#define B2056_RX_RXHPF_OFF0		0x63
+#define B2056_RX_RXHPF_OFF1		0x64
+#define B2056_RX_RXHPF_OFF2		0x65
+#define B2056_RX_RXHPF_OFF3		0x66
+#define B2056_RX_RXHPF_OFF4		0x67
+#define B2056_RX_RXHPF_OFF5		0x68
+#define B2056_RX_RXHPF_OFF6		0x69
+#define B2056_RX_RXHPF_OFF7		0x6A
+#define B2056_RX_RXLPF_RCCAL_LPC	0x6B
+#define B2056_RX_RXLPF_OFF_0		0x6C
+#define B2056_RX_RXLPF_OFF_1		0x6D
+#define B2056_RX_RXLPF_OFF_2		0x6E
+#define B2056_RX_RXLPF_OFF_3		0x6F
+#define B2056_RX_RXLPF_OFF_4		0x70
+#define B2056_RX_UNUSED			0x71
+#define B2056_RX_VGA_MASTER		0x72
+#define B2056_RX_VGA_BIAS		0x73
+#define B2056_RX_VGA_BIAS_DCCANCEL	0x74
+#define B2056_RX_VGA_GAIN		0x75
+#define B2056_RX_VGA_HP_CORNER_BW	0x76
+#define B2056_RX_VGABUF_BIAS		0x77
+#define B2056_RX_VGABUF_GAIN_BW		0x78
+#define B2056_RX_TXFBMIX_A		0x79
+#define B2056_RX_TXFBMIX_G		0x7A
+#define B2056_RX_RXSPARE1		0x7B
+#define B2056_RX_RXSPARE2		0x7C
+#define B2056_RX_RXSPARE3		0x7D
+#define B2056_RX_RXSPARE4		0x7E
+#define B2056_RX_RXSPARE5		0x7F
+#define B2056_RX_RXSPARE6		0x80
+#define B2056_RX_RXSPARE7		0x81
+#define B2056_RX_RXSPARE8		0x82
+#define B2056_RX_RXSPARE9		0x83
+#define B2056_RX_RXSPARE10		0x84
+#define B2056_RX_RXSPARE11		0x85
+#define B2056_RX_RXSPARE12		0x86
+#define B2056_RX_RXSPARE13		0x87
+#define B2056_RX_RXSPARE14		0x88
+#define B2056_RX_RXSPARE15		0x89
+#define B2056_RX_RXSPARE16		0x8A
+#define B2056_RX_STATUS_LNAA_GAIN	0x8B
+#define B2056_RX_STATUS_LNAG_GAIN	0x8C
+#define B2056_RX_STATUS_MIXTIA_GAIN	0x8D
+#define B2056_RX_STATUS_RXLPF_GAIN	0x8E
+#define B2056_RX_STATUS_VGA_BUF_GAIN	0x8F
+#define B2056_RX_STATUS_RXLPF_Q		0x90
+#define B2056_RX_STATUS_RXLPF_BUF_BW	0x91
+#define B2056_RX_STATUS_RXLPF_VGA_HPC	0x92
+#define B2056_RX_STATUS_RXLPF_RC	0x93
+#define B2056_RX_STATUS_HPC_RC		0x94
+
+#define B2056_LNA1_A_PU			0x01
+#define B2056_LNA2_A_PU			0x02
+#define B2056_LNA1_G_PU			0x01
+#define B2056_LNA2_G_PU			0x02
+#define B2056_MIXA_PU_I			0x01
+#define B2056_MIXA_PU_Q			0x02
+#define B2056_MIXA_PU_GM		0x10
+#define B2056_MIXG_PU_I			0x01
+#define B2056_MIXG_PU_Q			0x02
+#define B2056_MIXG_PU_GM		0x10
+#define B2056_TIA_PU			0x01
+#define B2056_BB_LPF_PU			0x20
+#define B2056_W1_PU			0x02
+#define B2056_W2_PU			0x04
+#define B2056_NB_PU			0x08
+#define B2056_RSSI_W1_SEL		0x02
+#define B2056_RSSI_W2_SEL		0x04
+#define B2056_RSSI_NB_SEL		0x08
+#define B2056_VCM_MASK			0x1C
+#define B2056_RSSI_VCM_SHIFT		0x02
+
+#define B2056_SYN			(0x0 << 12)
+#define B2056_TX0			(0x2 << 12)
+#define B2056_TX1			(0x3 << 12)
+#define B2056_RX0			(0x6 << 12)
+#define B2056_RX1			(0x7 << 12)
+#define B2056_ALLTX			(0xE << 12)
+#define B2056_ALLRX			(0xF << 12)
+
+#define B2056_SYN_RESERVED_ADDR0	0x00
+#define B2056_SYN_IDCODE		0x01
+#define B2056_SYN_RESERVED_ADDR2	0x02
+#define B2056_SYN_RESERVED_ADDR3	0x03
+#define B2056_SYN_RESERVED_ADDR4	0x04
+#define B2056_SYN_RESERVED_ADDR5	0x05
+#define B2056_SYN_RESERVED_ADDR6	0x06
+#define B2056_SYN_RESERVED_ADDR7	0x07
+#define B2056_SYN_COM_CTRL		0x08
+#define B2056_SYN_COM_PU		0x09
+#define B2056_SYN_COM_OVR		0x0A
+#define B2056_SYN_COM_RESET		0x0B
+#define B2056_SYN_COM_RCAL		0x0C
+#define B2056_SYN_COM_RC_RXLPF		0x0D
+#define B2056_SYN_COM_RC_TXLPF		0x0E
+#define B2056_SYN_COM_RC_RXHPF		0x0F
+#define B2056_SYN_RESERVED_ADDR16	0x10
+#define B2056_SYN_RESERVED_ADDR17	0x11
+#define B2056_SYN_RESERVED_ADDR18	0x12
+#define B2056_SYN_RESERVED_ADDR19	0x13
+#define B2056_SYN_RESERVED_ADDR20	0x14
+#define B2056_SYN_RESERVED_ADDR21	0x15
+#define B2056_SYN_RESERVED_ADDR22	0x16
+#define B2056_SYN_RESERVED_ADDR23	0x17
+#define B2056_SYN_RESERVED_ADDR24	0x18
+#define B2056_SYN_RESERVED_ADDR25	0x19
+#define B2056_SYN_RESERVED_ADDR26	0x1A
+#define B2056_SYN_RESERVED_ADDR27	0x1B
+#define B2056_SYN_RESERVED_ADDR28	0x1C
+#define B2056_SYN_RESERVED_ADDR29	0x1D
+#define B2056_SYN_RESERVED_ADDR30	0x1E
+#define B2056_SYN_RESERVED_ADDR31	0x1F
+#define B2056_SYN_GPIO_MASTER1		0x20
+#define B2056_SYN_GPIO_MASTER2		0x21
+#define B2056_SYN_TOPBIAS_MASTER	0x22
+#define B2056_SYN_TOPBIAS_RCAL		0x23
+#define B2056_SYN_AFEREG		0x24
+#define B2056_SYN_TEMPPROCSENSE		0x25
+#define B2056_SYN_TEMPPROCSENSEIDAC	0x26
+#define B2056_SYN_TEMPPROCSENSERCAL	0x27
+#define B2056_SYN_LPO			0x28
+#define B2056_SYN_VDDCAL_MASTER		0x29
+#define B2056_SYN_VDDCAL_IDAC		0x2A
+#define B2056_SYN_VDDCAL_STATUS		0x2B
+#define B2056_SYN_RCAL_MASTER		0x2C
+#define B2056_SYN_RCAL_CODE_OUT		0x2D
+#define B2056_SYN_RCCAL_CTRL0		0x2E
+#define B2056_SYN_RCCAL_CTRL1		0x2F
+#define B2056_SYN_RCCAL_CTRL2		0x30
+#define B2056_SYN_RCCAL_CTRL3		0x31
+#define B2056_SYN_RCCAL_CTRL4		0x32
+#define B2056_SYN_RCCAL_CTRL5		0x33
+#define B2056_SYN_RCCAL_CTRL6		0x34
+#define B2056_SYN_RCCAL_CTRL7		0x35
+#define B2056_SYN_RCCAL_CTRL8		0x36
+#define B2056_SYN_RCCAL_CTRL9		0x37
+#define B2056_SYN_RCCAL_CTRL10		0x38
+#define B2056_SYN_RCCAL_CTRL11		0x39
+#define B2056_SYN_ZCAL_SPARE1		0x3A
+#define B2056_SYN_ZCAL_SPARE2		0x3B
+#define B2056_SYN_PLL_MAST1		0x3C
+#define B2056_SYN_PLL_MAST2		0x3D
+#define B2056_SYN_PLL_MAST3		0x3E
+#define B2056_SYN_PLL_BIAS_RESET	0x3F
+#define B2056_SYN_PLL_XTAL0		0x40
+#define B2056_SYN_PLL_XTAL1		0x41
+#define B2056_SYN_PLL_XTAL3		0x42
+#define B2056_SYN_PLL_XTAL4		0x43
+#define B2056_SYN_PLL_XTAL5		0x44
+#define B2056_SYN_PLL_XTAL6		0x45
+#define B2056_SYN_PLL_REFDIV		0x46
+#define B2056_SYN_PLL_PFD		0x47
+#define B2056_SYN_PLL_CP1		0x48
+#define B2056_SYN_PLL_CP2		0x49
+#define B2056_SYN_PLL_CP3		0x4A
+#define B2056_SYN_PLL_LOOPFILTER1	0x4B
+#define B2056_SYN_PLL_LOOPFILTER2	0x4C
+#define B2056_SYN_PLL_LOOPFILTER3	0x4D
+#define B2056_SYN_PLL_LOOPFILTER4	0x4E
+#define B2056_SYN_PLL_LOOPFILTER5	0x4F
+#define B2056_SYN_PLL_MMD1		0x50
+#define B2056_SYN_PLL_MMD2		0x51
+#define B2056_SYN_PLL_VCO1		0x52
+#define B2056_SYN_PLL_VCO2		0x53
+#define B2056_SYN_PLL_MONITOR1		0x54
+#define B2056_SYN_PLL_MONITOR2		0x55
+#define B2056_SYN_PLL_VCOCAL1		0x56
+#define B2056_SYN_PLL_VCOCAL2		0x57
+#define B2056_SYN_PLL_VCOCAL4		0x58
+#define B2056_SYN_PLL_VCOCAL5		0x59
+#define B2056_SYN_PLL_VCOCAL6		0x5A
+#define B2056_SYN_PLL_VCOCAL7		0x5B
+#define B2056_SYN_PLL_VCOCAL8		0x5C
+#define B2056_SYN_PLL_VCOCAL9		0x5D
+#define B2056_SYN_PLL_VCOCAL10		0x5E
+#define B2056_SYN_PLL_VCOCAL11		0x5F
+#define B2056_SYN_PLL_VCOCAL12		0x60
+#define B2056_SYN_PLL_VCOCAL13		0x61
+#define B2056_SYN_PLL_VREG		0x62
+#define B2056_SYN_PLL_STATUS1		0x63
+#define B2056_SYN_PLL_STATUS2		0x64
+#define B2056_SYN_PLL_STATUS3		0x65
+#define B2056_SYN_LOGEN_PU0		0x66
+#define B2056_SYN_LOGEN_PU1		0x67
+#define B2056_SYN_LOGEN_PU2		0x68
+#define B2056_SYN_LOGEN_PU3		0x69
+#define B2056_SYN_LOGEN_PU5		0x6A
+#define B2056_SYN_LOGEN_PU6		0x6B
+#define B2056_SYN_LOGEN_PU7		0x6C
+#define B2056_SYN_LOGEN_PU8		0x6D
+#define B2056_SYN_LOGEN_BIAS_RESET	0x6E
+#define B2056_SYN_LOGEN_RCCR1		0x6F
+#define B2056_SYN_LOGEN_VCOBUF1		0x70
+#define B2056_SYN_LOGEN_MIXER1		0x71
+#define B2056_SYN_LOGEN_MIXER2		0x72
+#define B2056_SYN_LOGEN_BUF1		0x73
+#define B2056_SYN_LOGENBUF2		0x74
+#define B2056_SYN_LOGEN_BUF3		0x75
+#define B2056_SYN_LOGEN_BUF4		0x76
+#define B2056_SYN_LOGEN_DIV1		0x77
+#define B2056_SYN_LOGEN_DIV2		0x78
+#define B2056_SYN_LOGEN_DIV3		0x79
+#define B2056_SYN_LOGEN_ACL1		0x7A
+#define B2056_SYN_LOGEN_ACL2		0x7B
+#define B2056_SYN_LOGEN_ACL3		0x7C
+#define B2056_SYN_LOGEN_ACL4		0x7D
+#define B2056_SYN_LOGEN_ACL5		0x7E
+#define B2056_SYN_LOGEN_ACL6		0x7F
+#define B2056_SYN_LOGEN_ACLOUT		0x80
+#define B2056_SYN_LOGEN_ACLCAL1		0x81
+#define B2056_SYN_LOGEN_ACLCAL2		0x82
+#define B2056_SYN_LOGEN_ACLCAL3		0x83
+#define B2056_SYN_CALEN			0x84
+#define B2056_SYN_LOGEN_PEAKDET1	0x85
+#define B2056_SYN_LOGEN_CORE_ACL_OVR	0x86
+#define B2056_SYN_LOGEN_RX_DIFF_ACL_OVR	0x87
+#define B2056_SYN_LOGEN_TX_DIFF_ACL_OVR	0x88
+#define B2056_SYN_LOGEN_RX_CMOS_ACL_OVR	0x89
+#define B2056_SYN_LOGEN_TX_CMOS_ACL_OVR	0x8A
+#define B2056_SYN_LOGEN_VCOBUF2		0x8B
+#define B2056_SYN_LOGEN_MIXER3		0x8C
+#define B2056_SYN_LOGEN_BUF5		0x8D
+#define B2056_SYN_LOGEN_BUF6		0x8E
+#define B2056_SYN_LOGEN_CBUFRX1		0x8F
+#define B2056_SYN_LOGEN_CBUFRX2		0x90
+#define B2056_SYN_LOGEN_CBUFRX3		0x91
+#define B2056_SYN_LOGEN_CBUFRX4		0x92
+#define B2056_SYN_LOGEN_CBUFTX1		0x93
+#define B2056_SYN_LOGEN_CBUFTX2		0x94
+#define B2056_SYN_LOGEN_CBUFTX3		0x95
+#define B2056_SYN_LOGEN_CBUFTX4		0x96
+#define B2056_SYN_LOGEN_CMOSRX1		0x97
+#define B2056_SYN_LOGEN_CMOSRX2		0x98
+#define B2056_SYN_LOGEN_CMOSRX3		0x99
+#define B2056_SYN_LOGEN_CMOSRX4		0x9A
+#define B2056_SYN_LOGEN_CMOSTX1		0x9B
+#define B2056_SYN_LOGEN_CMOSTX2		0x9C
+#define B2056_SYN_LOGEN_CMOSTX3		0x9D
+#define B2056_SYN_LOGEN_CMOSTX4		0x9E
+#define B2056_SYN_LOGEN_VCOBUF2_OVRVAL	0x9F
+#define B2056_SYN_LOGEN_MIXER3_OVRVAL	0xA0
+#define B2056_SYN_LOGEN_BUF5_OVRVAL	0xA1
+#define B2056_SYN_LOGEN_BUF6_OVRVAL	0xA2
+#define B2056_SYN_LOGEN_CBUFRX1_OVRVAL	0xA3
+#define B2056_SYN_LOGEN_CBUFRX2_OVRVAL	0xA4
+#define B2056_SYN_LOGEN_CBUFRX3_OVRVAL	0xA5
+#define B2056_SYN_LOGEN_CBUFRX4_OVRVAL	0xA6
+#define B2056_SYN_LOGEN_CBUFTX1_OVRVAL	0xA7
+#define B2056_SYN_LOGEN_CBUFTX2_OVRVAL	0xA8
+#define B2056_SYN_LOGEN_CBUFTX3_OVRVAL	0xA9
+#define B2056_SYN_LOGEN_CBUFTX4_OVRVAL	0xAA
+#define B2056_SYN_LOGEN_CMOSRX1_OVRVAL	0xAB
+#define B2056_SYN_LOGEN_CMOSRX2_OVRVAL	0xAC
+#define B2056_SYN_LOGEN_CMOSRX3_OVRVAL	0xAD
+#define B2056_SYN_LOGEN_CMOSRX4_OVRVAL	0xAE
+#define B2056_SYN_LOGEN_CMOSTX1_OVRVAL	0xAF
+#define B2056_SYN_LOGEN_CMOSTX2_OVRVAL	0xB0
+#define B2056_SYN_LOGEN_CMOSTX3_OVRVAL	0xB1
+#define B2056_SYN_LOGEN_CMOSTX4_OVRVAL	0xB2
+#define B2056_SYN_LOGEN_ACL_WAITCNT	0xB3
+#define B2056_SYN_LOGEN_CORE_CALVALID	0xB4
+#define B2056_SYN_LOGEN_RX_CMOS_CALVALID	0xB5
+#define B2056_SYN_LOGEN_TX_CMOS_VALID	0xB6
+
+#define B2056_TX_RESERVED_ADDR0		0x00
+#define B2056_TX_IDCODE			0x01
+#define B2056_TX_RESERVED_ADDR2		0x02
+#define B2056_TX_RESERVED_ADDR3		0x03
+#define B2056_TX_RESERVED_ADDR4		0x04
+#define B2056_TX_RESERVED_ADDR5		0x05
+#define B2056_TX_RESERVED_ADDR6		0x06
+#define B2056_TX_RESERVED_ADDR7		0x07
+#define B2056_TX_COM_CTRL		0x08
+#define B2056_TX_COM_PU			0x09
+#define B2056_TX_COM_OVR		0x0A
+#define B2056_TX_COM_RESET		0x0B
+#define B2056_TX_COM_RCAL		0x0C
+#define B2056_TX_COM_RC_RXLPF		0x0D
+#define B2056_TX_COM_RC_TXLPF		0x0E
+#define B2056_TX_COM_RC_RXHPF		0x0F
+#define B2056_TX_RESERVED_ADDR16	0x10
+#define B2056_TX_RESERVED_ADDR17	0x11
+#define B2056_TX_RESERVED_ADDR18	0x12
+#define B2056_TX_RESERVED_ADDR19	0x13
+#define B2056_TX_RESERVED_ADDR20	0x14
+#define B2056_TX_RESERVED_ADDR21	0x15
+#define B2056_TX_RESERVED_ADDR22	0x16
+#define B2056_TX_RESERVED_ADDR23	0x17
+#define B2056_TX_RESERVED_ADDR24	0x18
+#define B2056_TX_RESERVED_ADDR25	0x19
+#define B2056_TX_RESERVED_ADDR26	0x1A
+#define B2056_TX_RESERVED_ADDR27	0x1B
+#define B2056_TX_RESERVED_ADDR28	0x1C
+#define B2056_TX_RESERVED_ADDR29	0x1D
+#define B2056_TX_RESERVED_ADDR30	0x1E
+#define B2056_TX_RESERVED_ADDR31	0x1F
+#define B2056_TX_IQCAL_GAIN_BW		0x20
+#define B2056_TX_LOFT_FINE_I		0x21
+#define B2056_TX_LOFT_FINE_Q		0x22
+#define B2056_TX_LOFT_COARSE_I		0x23
+#define B2056_TX_LOFT_COARSE_Q		0x24
+#define B2056_TX_TX_COM_MASTER1		0x25
+#define B2056_TX_TX_COM_MASTER2		0x26
+#define B2056_TX_RXIQCAL_TXMUX		0x27
+#define B2056_TX_TX_SSI_MASTER		0x28
+#define B2056_TX_IQCAL_VCM_HG		0x29
+#define B2056_TX_IQCAL_IDAC		0x2A
+#define B2056_TX_TSSI_VCM		0x2B
+#define B2056_TX_TX_AMP_DET		0x2C
+#define B2056_TX_TX_SSI_MUX		0x2D
+#define B2056_TX_TSSIA			0x2E
+#define B2056_TX_TSSIG			0x2F
+#define B2056_TX_TSSI_MISC1		0x30
+#define B2056_TX_TSSI_MISC2		0x31
+#define B2056_TX_TSSI_MISC3		0x32
+#define B2056_TX_PA_SPARE1		0x33
+#define B2056_TX_PA_SPARE2		0x34
+#define B2056_TX_INTPAA_MASTER		0x35
+#define B2056_TX_INTPAA_GAIN		0x36
+#define B2056_TX_INTPAA_BOOST_TUNE	0x37
+#define B2056_TX_INTPAA_IAUX_STAT	0x38
+#define B2056_TX_INTPAA_IAUX_DYN	0x39
+#define B2056_TX_INTPAA_IMAIN_STAT	0x3A
+#define B2056_TX_INTPAA_IMAIN_DYN	0x3B
+#define B2056_TX_INTPAA_CASCBIAS	0x3C
+#define B2056_TX_INTPAA_PASLOPE		0x3D
+#define B2056_TX_INTPAA_PA_MISC		0x3E
+#define B2056_TX_INTPAG_MASTER		0x3F
+#define B2056_TX_INTPAG_GAIN		0x40
+#define B2056_TX_INTPAG_BOOST_TUNE	0x41
+#define B2056_TX_INTPAG_IAUX_STAT	0x42
+#define B2056_TX_INTPAG_IAUX_DYN	0x43
+#define B2056_TX_INTPAG_IMAIN_STAT	0x44
+#define B2056_TX_INTPAG_IMAIN_DYN	0x45
+#define B2056_TX_INTPAG_CASCBIAS	0x46
+#define B2056_TX_INTPAG_PASLOPE		0x47
+#define B2056_TX_INTPAG_PA_MISC		0x48
+#define B2056_TX_PADA_MASTER		0x49
+#define B2056_TX_PADA_IDAC		0x4A
+#define B2056_TX_PADA_CASCBIAS		0x4B
+#define B2056_TX_PADA_GAIN		0x4C
+#define B2056_TX_PADA_BOOST_TUNE	0x4D
+#define B2056_TX_PADA_SLOPE		0x4E
+#define B2056_TX_PADG_MASTER		0x4F
+#define B2056_TX_PADG_IDAC		0x50
+#define B2056_TX_PADG_CASCBIAS		0x51
+#define B2056_TX_PADG_GAIN		0x52
+#define B2056_TX_PADG_BOOST_TUNE	0x53
+#define B2056_TX_PADG_SLOPE		0x54
+#define B2056_TX_PGAA_MASTER		0x55
+#define B2056_TX_PGAA_IDAC		0x56
+#define B2056_TX_PGAA_GAIN		0x57
+#define B2056_TX_PGAA_BOOST_TUNE	0x58
+#define B2056_TX_PGAA_SLOPE		0x59
+#define B2056_TX_PGAA_MISC		0x5A
+#define B2056_TX_PGAG_MASTER		0x5B
+#define B2056_TX_PGAG_IDAC		0x5C
+#define B2056_TX_PGAG_GAIN		0x5D
+#define B2056_TX_PGAG_BOOST_TUNE	0x5E
+#define B2056_TX_PGAG_SLOPE		0x5F
+#define B2056_TX_PGAG_MISC		0x60
+#define B2056_TX_MIXA_MASTER		0x61
+#define B2056_TX_MIXA_BOOST_TUNE	0x62
+#define B2056_TX_MIXG			0x63
+#define B2056_TX_MIXG_BOOST_TUNE	0x64
+#define B2056_TX_BB_GM_MASTER		0x65
+#define B2056_TX_GMBB_GM		0x66
+#define B2056_TX_GMBB_IDAC		0x67
+#define B2056_TX_TXLPF_MASTER		0x68
+#define B2056_TX_TXLPF_RCCAL		0x69
+#define B2056_TX_TXLPF_RCCAL_OFF0	0x6A
+#define B2056_TX_TXLPF_RCCAL_OFF1	0x6B
+#define B2056_TX_TXLPF_RCCAL_OFF2	0x6C
+#define B2056_TX_TXLPF_RCCAL_OFF3	0x6D
+#define B2056_TX_TXLPF_RCCAL_OFF4	0x6E
+#define B2056_TX_TXLPF_RCCAL_OFF5	0x6F
+#define B2056_TX_TXLPF_RCCAL_OFF6	0x70
+#define B2056_TX_TXLPF_BW		0x71
+#define B2056_TX_TXLPF_GAIN		0x72
+#define B2056_TX_TXLPF_IDAC		0x73
+#define B2056_TX_TXLPF_IDAC_0		0x74
+#define B2056_TX_TXLPF_IDAC_1		0x75
+#define B2056_TX_TXLPF_IDAC_2		0x76
+#define B2056_TX_TXLPF_IDAC_3		0x77
+#define B2056_TX_TXLPF_IDAC_4		0x78
+#define B2056_TX_TXLPF_IDAC_5		0x79
+#define B2056_TX_TXLPF_IDAC_6		0x7A
+#define B2056_TX_TXLPF_OPAMP_IDAC	0x7B
+#define B2056_TX_TXLPF_MISC		0x7C
+#define B2056_TX_TXSPARE1		0x7D
+#define B2056_TX_TXSPARE2		0x7E
+#define B2056_TX_TXSPARE3		0x7F
+#define B2056_TX_TXSPARE4		0x80
+#define B2056_TX_TXSPARE5		0x81
+#define B2056_TX_TXSPARE6		0x82
+#define B2056_TX_TXSPARE7		0x83
+#define B2056_TX_TXSPARE8		0x84
+#define B2056_TX_TXSPARE9		0x85
+#define B2056_TX_TXSPARE10		0x86
+#define B2056_TX_TXSPARE11		0x87
+#define B2056_TX_TXSPARE12		0x88
+#define B2056_TX_TXSPARE13		0x89
+#define B2056_TX_TXSPARE14		0x8A
+#define B2056_TX_TXSPARE15		0x8B
+#define B2056_TX_TXSPARE16		0x8C
+#define B2056_TX_STATUS_INTPA_GAIN	0x8D
+#define B2056_TX_STATUS_PAD_GAIN	0x8E
+#define B2056_TX_STATUS_PGA_GAIN	0x8F
+#define B2056_TX_STATUS_GM_TXLPF_GAIN	0x90
+#define B2056_TX_STATUS_TXLPF_BW	0x91
+#define B2056_TX_STATUS_TXLPF_RC	0x92
+#define B2056_TX_GMBB_IDAC0		0x93
+#define B2056_TX_GMBB_IDAC1		0x94
+#define B2056_TX_GMBB_IDAC2		0x95
+#define B2056_TX_GMBB_IDAC3		0x96
+#define B2056_TX_GMBB_IDAC4		0x97
+#define B2056_TX_GMBB_IDAC5		0x98
+#define B2056_TX_GMBB_IDAC6		0x99
+#define B2056_TX_GMBB_IDAC7		0x9A
+
+#define B2056_RX_RESERVED_ADDR0		0x00
+#define B2056_RX_IDCODE			0x01
+#define B2056_RX_RESERVED_ADDR2		0x02
+#define B2056_RX_RESERVED_ADDR3		0x03
+#define B2056_RX_RESERVED_ADDR4		0x04
+#define B2056_RX_RESERVED_ADDR5		0x05
+#define B2056_RX_RESERVED_ADDR6		0x06
+#define B2056_RX_RESERVED_ADDR7		0x07
+#define B2056_RX_COM_CTRL		0x08
+#define B2056_RX_COM_PU			0x09
+#define B2056_RX_COM_OVR		0x0A
+#define B2056_RX_COM_RESET		0x0B
+#define B2056_RX_COM_RCAL		0x0C
+#define B2056_RX_COM_RC_RXLPF		0x0D
+#define B2056_RX_COM_RC_TXLPF		0x0E
+#define B2056_RX_COM_RC_RXHPF		0x0F
+#define B2056_RX_RESERVED_ADDR16	0x10
+#define B2056_RX_RESERVED_ADDR17	0x11
+#define B2056_RX_RESERVED_ADDR18	0x12
+#define B2056_RX_RESERVED_ADDR19	0x13
+#define B2056_RX_RESERVED_ADDR20	0x14
+#define B2056_RX_RESERVED_ADDR21	0x15
+#define B2056_RX_RESERVED_ADDR22	0x16
+#define B2056_RX_RESERVED_ADDR23	0x17
+#define B2056_RX_RESERVED_ADDR24	0x18
+#define B2056_RX_RESERVED_ADDR25	0x19
+#define B2056_RX_RESERVED_ADDR26	0x1A
+#define B2056_RX_RESERVED_ADDR27	0x1B
+#define B2056_RX_RESERVED_ADDR28	0x1C
+#define B2056_RX_RESERVED_ADDR29	0x1D
+#define B2056_RX_RESERVED_ADDR30	0x1E
+#define B2056_RX_RESERVED_ADDR31	0x1F
+#define B2056_RX_RXIQCAL_RXMUX		0x20
+#define B2056_RX_RSSI_PU		0x21
+#define B2056_RX_RSSI_SEL		0x22
+#define B2056_RX_RSSI_GAIN		0x23
+#define B2056_RX_RSSI_NB_IDAC		0x24
+#define B2056_RX_RSSI_WB2I_IDAC_1	0x25
+#define B2056_RX_RSSI_WB2I_IDAC_2	0x26
+#define B2056_RX_RSSI_WB2Q_IDAC_1	0x27
+#define B2056_RX_RSSI_WB2Q_IDAC_2	0x28
+#define B2056_RX_RSSI_POLE		0x29
+#define B2056_RX_RSSI_WB1_IDAC		0x2A
+#define B2056_RX_RSSI_MISC		0x2B
+#define B2056_RX_LNAA_MASTER		0x2C
+#define B2056_RX_LNAA_TUNE		0x2D
+#define B2056_RX_LNAA_GAIN		0x2E
+#define B2056_RX_LNA_A_SLOPE		0x2F
+#define B2056_RX_BIASPOLE_LNAA1_IDAC	0x30
+#define B2056_RX_LNAA2_IDAC		0x31
+#define B2056_RX_LNA1A_MISC		0x32
+#define B2056_RX_LNAG_MASTER		0x33
+#define B2056_RX_LNAG_TUNE		0x34
+#define B2056_RX_LNAG_GAIN		0x35
+#define B2056_RX_LNA_G_SLOPE		0x36
+#define B2056_RX_BIASPOLE_LNAG1_IDAC	0x37
+#define B2056_RX_LNAG2_IDAC		0x38
+#define B2056_RX_LNA1G_MISC		0x39
+#define B2056_RX_MIXA_MASTER		0x3A
+#define B2056_RX_MIXA_VCM		0x3B
+#define B2056_RX_MIXA_CTRLPTAT		0x3C
+#define B2056_RX_MIXA_LOB_BIAS		0x3D
+#define B2056_RX_MIXA_CORE_IDAC		0x3E
+#define B2056_RX_MIXA_CMFB_IDAC		0x3F
+#define B2056_RX_MIXA_BIAS_AUX		0x40
+#define B2056_RX_MIXA_BIAS_MAIN		0x41
+#define B2056_RX_MIXA_BIAS_MISC		0x42
+#define B2056_RX_MIXA_MAST_BIAS		0x43
+#define B2056_RX_MIXG_MASTER		0x44
+#define B2056_RX_MIXG_VCM		0x45
+#define B2056_RX_MIXG_CTRLPTAT		0x46
+#define B2056_RX_MIXG_LOB_BIAS		0x47
+#define B2056_RX_MIXG_CORE_IDAC		0x48
+#define B2056_RX_MIXG_CMFB_IDAC		0x49
+#define B2056_RX_MIXG_BIAS_AUX		0x4A
+#define B2056_RX_MIXG_BIAS_MAIN		0x4B
+#define B2056_RX_MIXG_BIAS_MISC		0x4C
+#define B2056_RX_MIXG_MAST_BIAS		0x4D
+#define B2056_RX_TIA_MASTER		0x4E
+#define B2056_RX_TIA_IOPAMP		0x4F
+#define B2056_RX_TIA_QOPAMP		0x50
+#define B2056_RX_TIA_IMISC		0x51
+#define B2056_RX_TIA_QMISC		0x52
+#define B2056_RX_TIA_GAIN		0x53
+#define B2056_RX_TIA_SPARE1		0x54
+#define B2056_RX_TIA_SPARE2		0x55
+#define B2056_RX_BB_LPF_MASTER		0x56
+#define B2056_RX_AACI_MASTER		0x57
+#define B2056_RX_RXLPF_IDAC		0x58
+#define B2056_RX_RXLPF_OPAMPBIAS_LOWQ	0x59
+#define B2056_RX_RXLPF_OPAMPBIAS_HIGHQ	0x5A
+#define B2056_RX_RXLPF_BIAS_DCCANCEL	0x5B
+#define B2056_RX_RXLPF_OUTVCM		0x5C
+#define B2056_RX_RXLPF_INVCM_BODY	0x5D
+#define B2056_RX_RXLPF_CC_OP		0x5E
+#define B2056_RX_RXLPF_GAIN		0x5F
+#define B2056_RX_RXLPF_Q_BW		0x60
+#define B2056_RX_RXLPF_HP_CORNER_BW	0x61
+#define B2056_RX_RXLPF_RCCAL_HPC	0x62
+#define B2056_RX_RXHPF_OFF0		0x63
+#define B2056_RX_RXHPF_OFF1		0x64
+#define B2056_RX_RXHPF_OFF2		0x65
+#define B2056_RX_RXHPF_OFF3		0x66
+#define B2056_RX_RXHPF_OFF4		0x67
+#define B2056_RX_RXHPF_OFF5		0x68
+#define B2056_RX_RXHPF_OFF6		0x69
+#define B2056_RX_RXHPF_OFF7		0x6A
+#define B2056_RX_RXLPF_RCCAL_LPC	0x6B
+#define B2056_RX_RXLPF_OFF_0		0x6C
+#define B2056_RX_RXLPF_OFF_1		0x6D
+#define B2056_RX_RXLPF_OFF_2		0x6E
+#define B2056_RX_RXLPF_OFF_3		0x6F
+#define B2056_RX_RXLPF_OFF_4		0x70
+#define B2056_RX_UNUSED			0x71
+#define B2056_RX_VGA_MASTER		0x72
+#define B2056_RX_VGA_BIAS		0x73
+#define B2056_RX_VGA_BIAS_DCCANCEL	0x74
+#define B2056_RX_VGA_GAIN		0x75
+#define B2056_RX_VGA_HP_CORNER_BW	0x76
+#define B2056_RX_VGABUF_BIAS		0x77
+#define B2056_RX_VGABUF_GAIN_BW		0x78
+#define B2056_RX_TXFBMIX_A		0x79
+#define B2056_RX_TXFBMIX_G		0x7A
+#define B2056_RX_RXSPARE1		0x7B
+#define B2056_RX_RXSPARE2		0x7C
+#define B2056_RX_RXSPARE3		0x7D
+#define B2056_RX_RXSPARE4		0x7E
+#define B2056_RX_RXSPARE5		0x7F
+#define B2056_RX_RXSPARE6		0x80
+#define B2056_RX_RXSPARE7		0x81
+#define B2056_RX_RXSPARE8		0x82
+#define B2056_RX_RXSPARE9		0x83
+#define B2056_RX_RXSPARE10		0x84
+#define B2056_RX_RXSPARE11		0x85
+#define B2056_RX_RXSPARE12		0x86
+#define B2056_RX_RXSPARE13		0x87
+#define B2056_RX_RXSPARE14		0x88
+#define B2056_RX_RXSPARE15		0x89
+#define B2056_RX_RXSPARE16		0x8A
+#define B2056_RX_STATUS_LNAA_GAIN	0x8B
+#define B2056_RX_STATUS_LNAG_GAIN	0x8C
+#define B2056_RX_STATUS_MIXTIA_GAIN	0x8D
+#define B2056_RX_STATUS_RXLPF_GAIN	0x8E
+#define B2056_RX_STATUS_VGA_BUF_GAIN	0x8F
+#define B2056_RX_STATUS_RXLPF_Q		0x90
+#define B2056_RX_STATUS_RXLPF_BUF_BW	0x91
+#define B2056_RX_STATUS_RXLPF_VGA_HPC	0x92
+#define B2056_RX_STATUS_RXLPF_RC	0x93
+#define B2056_RX_STATUS_HPC_RC		0x94
+
+#define B2056_LNA1_A_PU			0x01
+#define B2056_LNA2_A_PU			0x02
+#define B2056_LNA1_G_PU			0x01
+#define B2056_LNA2_G_PU			0x02
+#define B2056_MIXA_PU_I			0x01
+#define B2056_MIXA_PU_Q			0x02
+#define B2056_MIXA_PU_GM		0x10
+#define B2056_MIXG_PU_I			0x01
+#define B2056_MIXG_PU_Q			0x02
+#define B2056_MIXG_PU_GM		0x10
+#define B2056_TIA_PU			0x01
+#define B2056_BB_LPF_PU			0x20
+#define B2056_W1_PU			0x02
+#define B2056_W2_PU			0x04
+#define B2056_NB_PU			0x08
+#define B2056_RSSI_W1_SEL		0x02
+#define B2056_RSSI_W2_SEL		0x04
+#define B2056_RSSI_NB_SEL		0x08
+#define B2056_VCM_MASK			0x1C
+#define B2056_RSSI_VCM_SHIFT		0x02
+
 struct b43_nphy_channeltab_entry_rev3 {
-	/* The channel number */
-	u8 channel;
 	/* The channel frequency in MHz */
 	u16 freq;
 	/* Radio register values on channelswitch */
-	/* TODO */
+	u8 radio_syn_pll_vcocal1;
+	u8 radio_syn_pll_vcocal2;
+	u8 radio_syn_pll_refdiv;
+	u8 radio_syn_pll_mmd2;
+	u8 radio_syn_pll_mmd1;
+	u8 radio_syn_pll_loopfilter1;
+	u8 radio_syn_pll_loopfilter2;
+	u8 radio_syn_pll_loopfilter3;
+	u8 radio_syn_pll_loopfilter4;
+	u8 radio_syn_pll_loopfilter5;
+	u8 radio_syn_reserved_addr27;
+	u8 radio_syn_reserved_addr28;
+	u8 radio_syn_reserved_addr29;
+	u8 radio_syn_logen_vcobuf1;
+	u8 radio_syn_logen_mixer2;
+	u8 radio_syn_logen_buf3;
+	u8 radio_syn_logen_buf4;
+	u8 radio_rx0_lnaa_tune;
+	u8 radio_rx0_lnag_tune;
+	u8 radio_tx0_intpaa_boost_tune;
+	u8 radio_tx0_intpag_boost_tune;
+	u8 radio_tx0_pada_boost_tune;
+	u8 radio_tx0_padg_boost_tune;
+	u8 radio_tx0_pgaa_boost_tune;
+	u8 radio_tx0_pgag_boost_tune;
+	u8 radio_tx0_mixa_boost_tune;
+	u8 radio_tx0_mixg_boost_tune;
+	u8 radio_rx1_lnaa_tune;
+	u8 radio_rx1_lnag_tune;
+	u8 radio_tx1_intpaa_boost_tune;
+	u8 radio_tx1_intpag_boost_tune;
+	u8 radio_tx1_pada_boost_tune;
+	u8 radio_tx1_padg_boost_tune;
+	u8 radio_tx1_pgaa_boost_tune;
+	u8 radio_tx1_pgag_boost_tune;
+	u8 radio_tx1_mixa_boost_tune;
+	u8 radio_tx1_mixg_boost_tune;
 	/* PHY register values on channelswitch */
 	struct b43_phy_n_sfo_cfg phy_regs;
 };
 
+void b2056_upload_inittabs(struct b43_wldev *dev,
+			   bool ghz5, bool ignore_uploadflag);
+
 #endif /* B43_RADIO_2056_H_ */
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/b43/rfkill.c linux-libre-2.6.38-gnu1/drivers/net/wireless/b43/rfkill.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/b43/rfkill.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/b43/rfkill.c	2011-03-14 21:20:32.000000000 -0400
@@ -28,23 +28,8 @@
 /* Returns TRUE, if the radio is enabled in hardware. */
 bool b43_is_hw_radio_enabled(struct b43_wldev *dev)
 {
-	if (dev->phy.rev >= 3 || dev->phy.type == B43_PHYTYPE_LP) {
-		if (!(b43_read32(dev, B43_MMIO_RADIO_HWENABLED_HI)
-		      & B43_MMIO_RADIO_HWENABLED_HI_MASK))
-			return 1;
-	} else {
-		/* To prevent CPU fault on PPC, do not read a register
-		 * unless the interface is started; however, on resume
-		 * for hibernation, this routine is entered early. When
-		 * that happens, unconditionally return TRUE.
-		 */
-		if (b43_status(dev) < B43_STAT_STARTED)
-			return 1;
-		if (b43_read16(dev, B43_MMIO_RADIO_HWENABLED_LO)
-		    & B43_MMIO_RADIO_HWENABLED_LO_MASK)
-			return 1;
-	}
-	return 0;
+	return !(b43_read32(dev, B43_MMIO_RADIO_HWENABLED_HI)
+		& B43_MMIO_RADIO_HWENABLED_HI_MASK);
 }
 
 /* The poll callback for the hardware button. */
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/b43/tables_nphy.c linux-libre-2.6.38-gnu1/drivers/net/wireless/b43/tables_nphy.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/b43/tables_nphy.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/b43/tables_nphy.c	2011-03-14 21:20:32.000000000 -0400
@@ -28,41 +28,41 @@
 #include "phy_n.h"
 
 static const u8 b43_ntab_adjustpower0[] = {
-	0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01,
-	0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03,
-	0x04, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05,
-	0x06, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07, 0x07,
-	0x08, 0x08, 0x08, 0x08, 0x09, 0x09, 0x09, 0x09,
-	0x0A, 0x0A, 0x0A, 0x0A, 0x0B, 0x0B, 0x0B, 0x0B,
-	0x0C, 0x0C, 0x0C, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D,
-	0x0E, 0x0E, 0x0E, 0x0E, 0x0F, 0x0F, 0x0F, 0x0F,
-	0x10, 0x10, 0x10, 0x10, 0x11, 0x11, 0x11, 0x11,
-	0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13,
-	0x14, 0x14, 0x14, 0x14, 0x15, 0x15, 0x15, 0x15,
-	0x16, 0x16, 0x16, 0x16, 0x17, 0x17, 0x17, 0x17,
-	0x18, 0x18, 0x18, 0x18, 0x19, 0x19, 0x19, 0x19,
-	0x1A, 0x1A, 0x1A, 0x1A, 0x1B, 0x1B, 0x1B, 0x1B,
-	0x1C, 0x1C, 0x1C, 0x1C, 0x1D, 0x1D, 0x1D, 0x1D,
-	0x1E, 0x1E, 0x1E, 0x1E, 0x1F, 0x1F, 0x1F, 0x1F,
+	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, 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, 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, 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,
 };
 
 static const u8 b43_ntab_adjustpower1[] = {
-	0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01,
-	0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03,
-	0x04, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05,
-	0x06, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07, 0x07,
-	0x08, 0x08, 0x08, 0x08, 0x09, 0x09, 0x09, 0x09,
-	0x0A, 0x0A, 0x0A, 0x0A, 0x0B, 0x0B, 0x0B, 0x0B,
-	0x0C, 0x0C, 0x0C, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D,
-	0x0E, 0x0E, 0x0E, 0x0E, 0x0F, 0x0F, 0x0F, 0x0F,
-	0x10, 0x10, 0x10, 0x10, 0x11, 0x11, 0x11, 0x11,
-	0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13,
-	0x14, 0x14, 0x14, 0x14, 0x15, 0x15, 0x15, 0x15,
-	0x16, 0x16, 0x16, 0x16, 0x17, 0x17, 0x17, 0x17,
-	0x18, 0x18, 0x18, 0x18, 0x19, 0x19, 0x19, 0x19,
-	0x1A, 0x1A, 0x1A, 0x1A, 0x1B, 0x1B, 0x1B, 0x1B,
-	0x1C, 0x1C, 0x1C, 0x1C, 0x1D, 0x1D, 0x1D, 0x1D,
-	0x1E, 0x1E, 0x1E, 0x1E, 0x1F, 0x1F, 0x1F, 0x1F,
+	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, 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, 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, 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,
 };
 
 static const u16 b43_ntab_bdi[] = {
@@ -130,8 +130,8 @@ static const u32 b43_ntab_framestruct[]
 	0x09804506, 0x00100030, 0x09804507, 0x00100030,
 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x08004A0C, 0x00100008, 0x01000A0D, 0x00100028,
-	0x0980450E, 0x00100038, 0x0980450F, 0x00100038,
+	0x08004A0C, 0x00100004, 0x01000A0D, 0x00100024,
+	0x0980450E, 0x00100034, 0x0980450F, 0x00100034,
 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 	0x00000A04, 0x00100000, 0x11008A05, 0x00100020,
@@ -202,13 +202,13 @@ static const u32 b43_ntab_framestruct[]
 	0x53028A06, 0x01900060, 0x53028A07, 0x01900060,
 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x4002140C, 0x000F4810, 0x6203140D, 0x00100050,
-	0x53028A0E, 0x01900070, 0x53028A0F, 0x01900070,
+	0x4002140C, 0x000F4808, 0x6203140D, 0x00100048,
+	0x53028A0E, 0x01900068, 0x53028A0F, 0x01900068,
 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000A0C, 0x00100008, 0x11008A0D, 0x00100028,
-	0x1980C50E, 0x00100038, 0x2181050E, 0x00100038,
-	0x2181050E, 0x00100038, 0x0180050C, 0x00100038,
+	0x00000A0C, 0x00100004, 0x11008A0D, 0x00100024,
+	0x1980C50E, 0x00100034, 0x2181050E, 0x00100034,
+	0x2181050E, 0x00100034, 0x0180050C, 0x00100038,
 	0x1180850D, 0x00100038, 0x1181850D, 0x00100038,
 	0x2981450F, 0x01100038, 0x00000000, 0x00000000,
 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
@@ -238,9 +238,9 @@ static const u32 b43_ntab_framestruct[]
 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x4002140C, 0x00100010, 0x0200140D, 0x00100050,
-	0x0B004A0E, 0x01900070, 0x13008A0E, 0x01900070,
-	0x13008A0E, 0x01900070, 0x43020A0C, 0x00100070,
+	0x4002140C, 0x00100008, 0x0200140D, 0x00100048,
+	0x0B004A0E, 0x01900068, 0x13008A0E, 0x01900068,
+	0x13008A0E, 0x01900068, 0x43020A0C, 0x00100070,
 	0x1B00CA0D, 0x00100070, 0x1B014A0D, 0x00100070,
 	0x23010A0F, 0x01500070, 0x00000000, 0x00000000,
 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
@@ -337,73 +337,73 @@ static const u32 b43_ntab_framestruct[]
 };
 
 static const u32 b43_ntab_gainctl0[] = {
-	0x007F003F, 0x007E013F, 0x007D023E, 0x007C033E,
-	0x007B043D, 0x007A053D, 0x0079063C, 0x0078073C,
-	0x0077083B, 0x0076093B, 0x00750A3A, 0x00740B3A,
-	0x00730C39, 0x00720D39, 0x00710E38, 0x00700F38,
-	0x006F0037, 0x006E0137, 0x006D0236, 0x006C0336,
-	0x006B0435, 0x006A0535, 0x00690634, 0x00680734,
-	0x00670833, 0x00660933, 0x00650A32, 0x00640B32,
-	0x00630C31, 0x00620D31, 0x00610E30, 0x00600F30,
-	0x005F002F, 0x005E012F, 0x005D022E, 0x005C032E,
-	0x005B042D, 0x005A052D, 0x0059062C, 0x0058072C,
-	0x0057082B, 0x0056092B, 0x00550A2A, 0x00540B2A,
-	0x00530C29, 0x00520D29, 0x00510E28, 0x00500F28,
-	0x004F0027, 0x004E0127, 0x004D0226, 0x004C0326,
-	0x004B0425, 0x004A0525, 0x00490624, 0x00480724,
-	0x00470823, 0x00460923, 0x00450A22, 0x00440B22,
-	0x00430C21, 0x00420D21, 0x00410E20, 0x00400F20,
-	0x003F001F, 0x003E011F, 0x003D021E, 0x003C031E,
-	0x003B041D, 0x003A051D, 0x0039061C, 0x0038071C,
-	0x0037081B, 0x0036091B, 0x00350A1A, 0x00340B1A,
-	0x00330C19, 0x00320D19, 0x00310E18, 0x00300F18,
-	0x002F0017, 0x002E0117, 0x002D0216, 0x002C0316,
-	0x002B0415, 0x002A0515, 0x00290614, 0x00280714,
-	0x00270813, 0x00260913, 0x00250A12, 0x00240B12,
-	0x00230C11, 0x00220D11, 0x00210E10, 0x00200F10,
-	0x001F000F, 0x001E010F, 0x001D020E, 0x001C030E,
-	0x001B040D, 0x001A050D, 0x0019060C, 0x0018070C,
-	0x0017080B, 0x0016090B, 0x00150A0A, 0x00140B0A,
-	0x00130C09, 0x00120D09, 0x00110E08, 0x00100F08,
-	0x000F0007, 0x000E0107, 0x000D0206, 0x000C0306,
-	0x000B0405, 0x000A0505, 0x00090604, 0x00080704,
-	0x00070803, 0x00060903, 0x00050A02, 0x00040B02,
-	0x00030C01, 0x00020D01, 0x00010E00, 0x00000F00,
+	0x03CC2B44, 0x03CC2B42, 0x03CC2B40, 0x03CC2B3E,
+	0x03CC2B3D, 0x03CC2B3B, 0x03C82B44, 0x03C82B42,
+	0x03C82B40, 0x03C82B3E, 0x03C82B3D, 0x03C82B3B,
+	0x03C82B39, 0x03C82B38, 0x03C82B36, 0x03C82B34,
+	0x03C42B44, 0x03C42B42, 0x03C42B40, 0x03C42B3E,
+	0x03C42B3D, 0x03C42B3B, 0x03C42B39, 0x03C42B38,
+	0x03C42B36, 0x03C42B34, 0x03C42B33, 0x03C42B32,
+	0x03C42B30, 0x03C42B2F, 0x03C42B2D, 0x03C02B44,
+	0x03C02B42, 0x03C02B40, 0x03C02B3E, 0x03C02B3D,
+	0x03C02B3B, 0x03C02B39, 0x03C02B38, 0x03C02B36,
+	0x03C02B34, 0x03B02B44, 0x03B02B42, 0x03B02B40,
+	0x03B02B3E, 0x03B02B3D, 0x03B02B3B, 0x03B02B39,
+	0x03B02B38, 0x03B02B36, 0x03B02B34, 0x03B02B33,
+	0x03B02B32, 0x03B02B30, 0x03B02B2F, 0x03B02B2D,
+	0x03A02B44, 0x03A02B42, 0x03A02B40, 0x03A02B3E,
+	0x03A02B3D, 0x03A02B3B, 0x03A02B39, 0x03A02B38,
+	0x03A02B36, 0x03A02B34, 0x03902B44, 0x03902B42,
+	0x03902B40, 0x03902B3E, 0x03902B3D, 0x03902B3B,
+	0x03902B39, 0x03902B38, 0x03902B36, 0x03902B34,
+	0x03902B33, 0x03902B32, 0x03902B30, 0x03802B44,
+	0x03802B42, 0x03802B40, 0x03802B3E, 0x03802B3D,
+	0x03802B3B, 0x03802B39, 0x03802B38, 0x03802B36,
+	0x03802B34, 0x03802B33, 0x03802B32, 0x03802B30,
+	0x03802B2F, 0x03802B2D, 0x03802B2C, 0x03802B2B,
+	0x03802B2A, 0x03802B29, 0x03802B27, 0x03802B26,
+	0x03802B25, 0x03802B24, 0x03802B23, 0x03802B22,
+	0x03802B21, 0x03802B20, 0x03802B1F, 0x03802B1E,
+	0x03802B1E, 0x03802B1D, 0x03802B1C, 0x03802B1B,
+	0x03802B1A, 0x03802B1A, 0x03802B19, 0x03802B18,
+	0x03802B18, 0x03802B18, 0x03802B18, 0x03802B18,
+	0x03802B18, 0x03802B18, 0x03802B18, 0x03802B18,
+	0x03802B18, 0x03802B18, 0x03802B18, 0x00002B00,
 };
 
 static const u32 b43_ntab_gainctl1[] = {
-	0x007F003F, 0x007E013F, 0x007D023E, 0x007C033E,
-	0x007B043D, 0x007A053D, 0x0079063C, 0x0078073C,
-	0x0077083B, 0x0076093B, 0x00750A3A, 0x00740B3A,
-	0x00730C39, 0x00720D39, 0x00710E38, 0x00700F38,
-	0x006F0037, 0x006E0137, 0x006D0236, 0x006C0336,
-	0x006B0435, 0x006A0535, 0x00690634, 0x00680734,
-	0x00670833, 0x00660933, 0x00650A32, 0x00640B32,
-	0x00630C31, 0x00620D31, 0x00610E30, 0x00600F30,
-	0x005F002F, 0x005E012F, 0x005D022E, 0x005C032E,
-	0x005B042D, 0x005A052D, 0x0059062C, 0x0058072C,
-	0x0057082B, 0x0056092B, 0x00550A2A, 0x00540B2A,
-	0x00530C29, 0x00520D29, 0x00510E28, 0x00500F28,
-	0x004F0027, 0x004E0127, 0x004D0226, 0x004C0326,
-	0x004B0425, 0x004A0525, 0x00490624, 0x00480724,
-	0x00470823, 0x00460923, 0x00450A22, 0x00440B22,
-	0x00430C21, 0x00420D21, 0x00410E20, 0x00400F20,
-	0x003F001F, 0x003E011F, 0x003D021E, 0x003C031E,
-	0x003B041D, 0x003A051D, 0x0039061C, 0x0038071C,
-	0x0037081B, 0x0036091B, 0x00350A1A, 0x00340B1A,
-	0x00330C19, 0x00320D19, 0x00310E18, 0x00300F18,
-	0x002F0017, 0x002E0117, 0x002D0216, 0x002C0316,
-	0x002B0415, 0x002A0515, 0x00290614, 0x00280714,
-	0x00270813, 0x00260913, 0x00250A12, 0x00240B12,
-	0x00230C11, 0x00220D11, 0x00210E10, 0x00200F10,
-	0x001F000F, 0x001E010F, 0x001D020E, 0x001C030E,
-	0x001B040D, 0x001A050D, 0x0019060C, 0x0018070C,
-	0x0017080B, 0x0016090B, 0x00150A0A, 0x00140B0A,
-	0x00130C09, 0x00120D09, 0x00110E08, 0x00100F08,
-	0x000F0007, 0x000E0107, 0x000D0206, 0x000C0306,
-	0x000B0405, 0x000A0505, 0x00090604, 0x00080704,
-	0x00070803, 0x00060903, 0x00050A02, 0x00040B02,
-	0x00030C01, 0x00020D01, 0x00010E00, 0x00000F00,
+	0x03CC2B44, 0x03CC2B42, 0x03CC2B40, 0x03CC2B3E,
+	0x03CC2B3D, 0x03CC2B3B, 0x03C82B44, 0x03C82B42,
+	0x03C82B40, 0x03C82B3E, 0x03C82B3D, 0x03C82B3B,
+	0x03C82B39, 0x03C82B38, 0x03C82B36, 0x03C82B34,
+	0x03C42B44, 0x03C42B42, 0x03C42B40, 0x03C42B3E,
+	0x03C42B3D, 0x03C42B3B, 0x03C42B39, 0x03C42B38,
+	0x03C42B36, 0x03C42B34, 0x03C42B33, 0x03C42B32,
+	0x03C42B30, 0x03C42B2F, 0x03C42B2D, 0x03C02B44,
+	0x03C02B42, 0x03C02B40, 0x03C02B3E, 0x03C02B3D,
+	0x03C02B3B, 0x03C02B39, 0x03C02B38, 0x03C02B36,
+	0x03C02B34, 0x03B02B44, 0x03B02B42, 0x03B02B40,
+	0x03B02B3E, 0x03B02B3D, 0x03B02B3B, 0x03B02B39,
+	0x03B02B38, 0x03B02B36, 0x03B02B34, 0x03B02B33,
+	0x03B02B32, 0x03B02B30, 0x03B02B2F, 0x03B02B2D,
+	0x03A02B44, 0x03A02B42, 0x03A02B40, 0x03A02B3E,
+	0x03A02B3D, 0x03A02B3B, 0x03A02B39, 0x03A02B38,
+	0x03A02B36, 0x03A02B34, 0x03902B44, 0x03902B42,
+	0x03902B40, 0x03902B3E, 0x03902B3D, 0x03902B3B,
+	0x03902B39, 0x03902B38, 0x03902B36, 0x03902B34,
+	0x03902B33, 0x03902B32, 0x03902B30, 0x03802B44,
+	0x03802B42, 0x03802B40, 0x03802B3E, 0x03802B3D,
+	0x03802B3B, 0x03802B39, 0x03802B38, 0x03802B36,
+	0x03802B34, 0x03802B33, 0x03802B32, 0x03802B30,
+	0x03802B2F, 0x03802B2D, 0x03802B2C, 0x03802B2B,
+	0x03802B2A, 0x03802B29, 0x03802B27, 0x03802B26,
+	0x03802B25, 0x03802B24, 0x03802B23, 0x03802B22,
+	0x03802B21, 0x03802B20, 0x03802B1F, 0x03802B1E,
+	0x03802B1E, 0x03802B1D, 0x03802B1C, 0x03802B1B,
+	0x03802B1A, 0x03802B1A, 0x03802B19, 0x03802B18,
+	0x03802B18, 0x03802B18, 0x03802B18, 0x03802B18,
+	0x03802B18, 0x03802B18, 0x03802B18, 0x03802B18,
+	0x03802B18, 0x03802B18, 0x03802B18, 0x00002B00,
 };
 
 static const u32 b43_ntab_intlevel[] = {
@@ -1811,9 +1811,7 @@ void b43_ntab_write_bulk(struct b43_wlde
 }
 
 #define ntab_upload(dev, offset, data) do { \
-		unsigned int i;						\
-		for (i = 0; i < (offset##_SIZE); i++)			\
-			b43_ntab_write(dev, (offset) + i, (data)[i]);	\
+		b43_ntab_write_bulk(dev, offset, offset##_SIZE, data);	\
 	} while (0)
 
 void b43_nphy_rev0_1_2_tables_init(struct b43_wldev *dev)
@@ -1825,24 +1823,24 @@ void b43_nphy_rev0_1_2_tables_init(struc
 	ntab_upload(dev, B43_NTAB_TDTRN, b43_ntab_tdtrn);
 	ntab_upload(dev, B43_NTAB_INTLEVEL, b43_ntab_intlevel);
 	ntab_upload(dev, B43_NTAB_PILOT, b43_ntab_pilot);
-	ntab_upload(dev, B43_NTAB_PILOTLT, b43_ntab_pilotlt);
 	ntab_upload(dev, B43_NTAB_TDI20A0, b43_ntab_tdi20a0);
 	ntab_upload(dev, B43_NTAB_TDI20A1, b43_ntab_tdi20a1);
 	ntab_upload(dev, B43_NTAB_TDI40A0, b43_ntab_tdi40a0);
 	ntab_upload(dev, B43_NTAB_TDI40A1, b43_ntab_tdi40a1);
-	ntab_upload(dev, B43_NTAB_BDI, b43_ntab_bdi);
 	ntab_upload(dev, B43_NTAB_CHANEST, b43_ntab_channelest);
 	ntab_upload(dev, B43_NTAB_MCS, b43_ntab_mcs);
-
-	/* Volatile tables */
 	ntab_upload(dev, B43_NTAB_NOISEVAR10, b43_ntab_noisevar10);
 	ntab_upload(dev, B43_NTAB_NOISEVAR11, b43_ntab_noisevar11);
+
+	/* Volatile tables */
+	ntab_upload(dev, B43_NTAB_BDI, b43_ntab_bdi);
+	ntab_upload(dev, B43_NTAB_PILOTLT, b43_ntab_pilotlt);
+	ntab_upload(dev, B43_NTAB_C0_GAINCTL, b43_ntab_gainctl0);
+	ntab_upload(dev, B43_NTAB_C1_GAINCTL, b43_ntab_gainctl1);
 	ntab_upload(dev, B43_NTAB_C0_ESTPLT, b43_ntab_estimatepowerlt0);
 	ntab_upload(dev, B43_NTAB_C1_ESTPLT, b43_ntab_estimatepowerlt1);
 	ntab_upload(dev, B43_NTAB_C0_ADJPLT, b43_ntab_adjustpower0);
 	ntab_upload(dev, B43_NTAB_C1_ADJPLT, b43_ntab_adjustpower1);
-	ntab_upload(dev, B43_NTAB_C0_GAINCTL, b43_ntab_gainctl0);
-	ntab_upload(dev, B43_NTAB_C1_GAINCTL, b43_ntab_gainctl1);
 	ntab_upload(dev, B43_NTAB_C0_IQLT, b43_ntab_iqlt0);
 	ntab_upload(dev, B43_NTAB_C1_IQLT, b43_ntab_iqlt1);
 	ntab_upload(dev, B43_NTAB_C0_LOFEEDTH, b43_ntab_loftlt0);
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/b43legacy/main.c linux-libre-2.6.38-gnu1/drivers/net/wireless/b43legacy/main.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/b43legacy/main.c	2013-05-03 03:59:59.000000000 -0400
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/b43legacy/main.c	2013-05-03 02:00:18.000000000 -0400
@@ -179,52 +179,75 @@ static int b43legacy_ratelimit(struct b4
 
 void b43legacyinfo(struct b43legacy_wl *wl, const char *fmt, ...)
 {
+	struct va_format vaf;
 	va_list args;
 
 	if (!b43legacy_ratelimit(wl))
 		return;
+
 	va_start(args, fmt);
-	printk(KERN_INFO "b43legacy-%s: ",
-	       (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan");
-	vprintk(fmt, args);
+
+	vaf.fmt = fmt;
+	vaf.va = &args;
+
+	printk(KERN_INFO "b43legacy-%s: %pV",
+	       (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan", &vaf);
+
 	va_end(args);
 }
 
 void b43legacyerr(struct b43legacy_wl *wl, const char *fmt, ...)
 {
+	struct va_format vaf;
 	va_list args;
 
 	if (!b43legacy_ratelimit(wl))
 		return;
+
 	va_start(args, fmt);
-	printk(KERN_ERR "b43legacy-%s ERROR: ",
-	       (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan");
-	vprintk(fmt, args);
+
+	vaf.fmt = fmt;
+	vaf.va = &args;
+
+	printk(KERN_ERR "b43legacy-%s ERROR: %pV",
+	       (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan", &vaf);
+
 	va_end(args);
 }
 
 void b43legacywarn(struct b43legacy_wl *wl, const char *fmt, ...)
 {
+	struct va_format vaf;
 	va_list args;
 
 	if (!b43legacy_ratelimit(wl))
 		return;
+
 	va_start(args, fmt);
-	printk(KERN_WARNING "b43legacy-%s warning: ",
-	       (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan");
-	vprintk(fmt, args);
+
+	vaf.fmt = fmt;
+	vaf.va = &args;
+
+	printk(KERN_WARNING "b43legacy-%s warning: %pV",
+	       (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan", &vaf);
+
 	va_end(args);
 }
 
 #if B43legacy_DEBUG
 void b43legacydbg(struct b43legacy_wl *wl, const char *fmt, ...)
 {
+	struct va_format vaf;
 	va_list args;
 
 	va_start(args, fmt);
-	printk(KERN_DEBUG "b43legacy-%s debug: ",
-	       (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan");
-	vprintk(fmt, args);
+
+	vaf.fmt = fmt;
+	vaf.va = &args;
+
+	printk(KERN_DEBUG "b43legacy-%s debug: %pV",
+	       (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan", &vaf);
+
 	va_end(args);
 }
 #endif /* DEBUG */
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/b43legacy/phy.c linux-libre-2.6.38-gnu1/drivers/net/wireless/b43legacy/phy.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/b43legacy/phy.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/b43legacy/phy.c	2011-03-14 21:20:32.000000000 -0400
@@ -153,7 +153,7 @@ void b43legacy_phy_calibrate(struct b43l
 	phy->calibrated = 1;
 }
 
-/* intialize B PHY power control
+/* initialize B PHY power control
  * as described in http://bcm-specs.sipsolutions.net/InitPowerControl
  */
 static void b43legacy_phy_init_pctl(struct b43legacy_wldev *dev)
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/b43legacy/rfkill.c linux-libre-2.6.38-gnu1/drivers/net/wireless/b43legacy/rfkill.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/b43legacy/rfkill.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/b43legacy/rfkill.c	2011-03-14 21:20:32.000000000 -0400
@@ -29,7 +29,7 @@
 /* Returns TRUE, if the radio is enabled in hardware. */
 bool b43legacy_is_hw_radio_enabled(struct b43legacy_wldev *dev)
 {
-	if (dev->phy.rev >= 3) {
+	if (dev->dev->id.revision >= 3) {
 		if (!(b43legacy_read32(dev, B43legacy_MMIO_RADIO_HWENABLED_HI)
 		      & B43legacy_MMIO_RADIO_HWENABLED_HI_MASK))
 			return 1;
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/hostap/hostap_ap.c linux-libre-2.6.38-gnu1/drivers/net/wireless/hostap/hostap_ap.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/hostap/hostap_ap.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/hostap/hostap_ap.c	2011-03-14 21:20:32.000000000 -0400
@@ -858,7 +858,10 @@ void hostap_free_data(struct ap_data *ap
 		return;
 	}
 
+	flush_work_sync(&ap->add_sta_proc_queue);
+
 #ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT
+	flush_work_sync(&ap->wds_oper_queue);
 	if (ap->crypt)
 		ap->crypt->deinit(ap->crypt_priv);
 	ap->crypt = ap->crypt_priv = NULL;
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/hostap/hostap_cs.c linux-libre-2.6.38-gnu1/drivers/net/wireless/hostap/hostap_cs.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/hostap/hostap_cs.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/hostap/hostap_cs.c	2011-03-14 21:20:32.000000000 -0400
@@ -518,22 +518,21 @@ static int prism2_config(struct pcmcia_d
 	hw_priv->link = link;
 
 	/*
-	 * Make sure the IRQ handler cannot proceed until at least
-	 * dev->base_addr is initialized.
+	 * We enable IRQ here, but IRQ handler will not proceed
+	 * until dev->base_addr is set below. This protect us from
+	 * receive interrupts when driver is not initialized.
 	 */
-	spin_lock_irqsave(&local->irq_init_lock, flags);
-
 	ret = pcmcia_request_irq(link, prism2_interrupt);
 	if (ret)
-		goto failed_unlock;
+		goto failed;
 
 	ret = pcmcia_enable_device(link);
 	if (ret)
-		goto failed_unlock;
+		goto failed;
 
+	spin_lock_irqsave(&local->irq_init_lock, flags);
 	dev->irq = link->irq;
 	dev->base_addr = link->resource[0]->start;
-
 	spin_unlock_irqrestore(&local->irq_init_lock, flags);
 
 	local->shutdown = 0;
@@ -546,8 +545,6 @@ static int prism2_config(struct pcmcia_d
 
 	return ret;
 
- failed_unlock:
-	spin_unlock_irqrestore(&local->irq_init_lock, flags);
  failed:
 	kfree(hw_priv);
 	prism2_release((u_long)link);
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/hostap/hostap_hw.c linux-libre-2.6.38-gnu1/drivers/net/wireless/hostap/hostap_hw.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/hostap/hostap_hw.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/hostap/hostap_hw.c	2011-03-14 21:20:32.000000000 -0400
@@ -3317,7 +3317,13 @@ static void prism2_free_local_data(struc
 
 	unregister_netdev(local->dev);
 
-	flush_scheduled_work();
+	flush_work_sync(&local->reset_queue);
+	flush_work_sync(&local->set_multicast_list_queue);
+	flush_work_sync(&local->set_tim_queue);
+#ifndef PRISM2_NO_STATION_MODES
+	flush_work_sync(&local->info_queue);
+#endif
+	flush_work_sync(&local->comms_qual_update);
 
 	lib80211_crypt_info_free(&local->crypt_info);
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ipw2x00/ipw2200.c linux-libre-2.6.38-gnu1/drivers/net/wireless/ipw2x00/ipw2200.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ipw2x00/ipw2200.c	2013-05-03 04:00:41.000000000 -0400
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ipw2x00/ipw2200.c	2013-05-03 02:01:03.000000000 -0400
@@ -1973,6 +1973,13 @@ static void ipw_irq_tasklet(struct ipw_p
 
 	inta = ipw_read32(priv, IPW_INTA_RW);
 	inta_mask = ipw_read32(priv, IPW_INTA_MASK_R);
+
+	if (inta == 0xFFFFFFFF) {
+		/* Hardware disappeared */
+		IPW_WARNING("TASKLET INTA == 0xFFFFFFFF\n");
+		/* Only handle the cached INTA values */
+		inta = 0;
+	}
 	inta &= (IPW_INTA_MASK_ALL & inta_mask);
 
 	/* Add any cached INTA values that need to be handled */
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/iwlwifi/iwl-1000.c linux-libre-2.6.38-gnu1/drivers/net/wireless/iwlwifi/iwl-1000.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/iwlwifi/iwl-1000.c	2013-05-03 04:01:00.000000000 -0400
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/iwlwifi/iwl-1000.c	2013-05-03 02:01:25.000000000 -0400
@@ -147,7 +147,11 @@ static int iwl1000_hw_set_hw_params(stru
 	priv->hw_params.rx_wrt_ptr_reg = FH_RSCSR_CHNL0_WPTR;
 
 	priv->hw_params.tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant);
-	priv->hw_params.rx_chains_num = num_of_ant(priv->cfg->valid_rx_ant);
+	if (priv->cfg->rx_with_siso_diversity)
+		priv->hw_params.rx_chains_num = 1;
+	else
+		priv->hw_params.rx_chains_num =
+			num_of_ant(priv->cfg->valid_rx_ant);
 	priv->hw_params.valid_tx_ant = priv->cfg->valid_tx_ant;
 	priv->hw_params.valid_rx_ant = priv->cfg->valid_rx_ant;
 
@@ -211,14 +215,16 @@ static struct iwl_lib_ops iwl1000_lib =
 		.calib_version	= iwlagn_eeprom_calib_version,
 		.query_addr = iwlagn_eeprom_query_addr,
 	},
-	.post_associate = iwl_post_associate,
-	.isr = iwl_isr_ict,
-	.config_ap = iwl_config_ap,
+	.isr_ops = {
+		.isr = iwl_isr_ict,
+		.free = iwl_free_isr_ict,
+		.alloc = iwl_alloc_isr_ict,
+		.reset = iwl_reset_ict,
+		.disable = iwl_disable_ict,
+	},
 	.temp_ops = {
 		.temperature = iwlagn_temperature,
 	 },
-	.manage_ibss_station = iwlagn_manage_ibss_station,
-	.update_bcast_stations = iwl_update_bcast_stations,
 	.debugfs_ops = {
 		.rx_stats_read = iwl_ucode_rx_stats_read,
 		.tx_stats_read = iwl_ucode_tx_stats_read,
@@ -226,7 +232,6 @@ static struct iwl_lib_ops iwl1000_lib =
 		.bt_stats_read = iwl_ucode_bt_stats_read,
 		.reply_tx_error = iwl_reply_tx_error_read,
 	},
-	.recover_from_tx_stall = iwl_bg_monitor_recover,
 	.check_plcp_health = iwl_good_plcp_health,
 	.check_ack_health = iwl_good_ack_health,
 	.txfifo_flush = iwlagn_txfifo_flush,
@@ -243,6 +248,7 @@ static const struct iwl_ops iwl1000_ops
 	.hcmd = &iwlagn_hcmd,
 	.utils = &iwlagn_hcmd_utils,
 	.led = &iwlagn_led_ops,
+	.ieee80211_ops = &iwlagn_hw_ops,
 };
 
 static struct iwl_base_params iwl1000_base_params = {
@@ -259,7 +265,7 @@ static struct iwl_base_params iwl1000_ba
 	.support_ct_kill_exit = true,
 	.plcp_delta_threshold = IWL_MAX_PLCP_ERR_EXT_LONG_THRESHOLD_DEF,
 	.chain_noise_scale = 1000,
-	.monitor_recover_period = IWL_DEF_MONITORING_PERIOD,
+	.wd_timeout = IWL_DEF_WD_TIMEOUT,
 	.max_event_log_size = 128,
 	.ucode_tracing = true,
 	.sensitivity_calib_by_driver = true,
@@ -270,68 +276,49 @@ static struct iwl_ht_params iwl1000_ht_p
 	.use_rts_for_aggregation = true, /* use rts/cts protection */
 };
 
+#define IWL_DEVICE_1000						\
+	.fw_name_pre = IWL1000_FW_PRE,				\
+	.ucode_api_max = IWL1000_UCODE_API_MAX,			\
+	.ucode_api_min = IWL1000_UCODE_API_MIN,			\
+	.eeprom_ver = EEPROM_1000_EEPROM_VERSION,		\
+	.eeprom_calib_ver = EEPROM_1000_TX_POWER_VERSION,	\
+	.ops = &iwl1000_ops,					\
+	.mod_params = &iwlagn_mod_params,			\
+	.base_params = &iwl1000_base_params,			\
+	.led_mode = IWL_LED_BLINK
+
 struct iwl_cfg iwl1000_bgn_cfg = {
 	.name = "Intel(R) Centrino(R) Wireless-N 1000 BGN",
-	.fw_name_pre = IWL1000_FW_PRE,
-	.ucode_api_max = IWL1000_UCODE_API_MAX,
-	.ucode_api_min = IWL1000_UCODE_API_MIN,
-	.sku = IWL_SKU_G|IWL_SKU_N,
-	.valid_tx_ant = ANT_A,
-	.valid_rx_ant = ANT_AB,
-	.eeprom_ver = EEPROM_1000_EEPROM_VERSION,
-	.eeprom_calib_ver = EEPROM_1000_TX_POWER_VERSION,
-	.ops = &iwl1000_ops,
-	.mod_params = &iwlagn_mod_params,
-	.base_params = &iwl1000_base_params,
+	IWL_DEVICE_1000,
 	.ht_params = &iwl1000_ht_params,
 };
 
 struct iwl_cfg iwl1000_bg_cfg = {
 	.name = "Intel(R) Centrino(R) Wireless-N 1000 BG",
-	.fw_name_pre = IWL1000_FW_PRE,
-	.ucode_api_max = IWL1000_UCODE_API_MAX,
-	.ucode_api_min = IWL1000_UCODE_API_MIN,
-	.sku = IWL_SKU_G,
-	.valid_tx_ant = ANT_A,
-	.valid_rx_ant = ANT_AB,
-	.eeprom_ver = EEPROM_1000_EEPROM_VERSION,
-	.eeprom_calib_ver = EEPROM_1000_TX_POWER_VERSION,
-	.ops = &iwl1000_ops,
-	.mod_params = &iwlagn_mod_params,
-	.base_params = &iwl1000_base_params,
+	IWL_DEVICE_1000,
 };
 
+#define IWL_DEVICE_100						\
+	.fw_name_pre = IWL100_FW_PRE,				\
+	.ucode_api_max = IWL100_UCODE_API_MAX,			\
+	.ucode_api_min = IWL100_UCODE_API_MIN,			\
+	.eeprom_ver = EEPROM_1000_EEPROM_VERSION,		\
+	.eeprom_calib_ver = EEPROM_1000_TX_POWER_VERSION,	\
+	.ops = &iwl1000_ops,					\
+	.mod_params = &iwlagn_mod_params,			\
+	.base_params = &iwl1000_base_params,			\
+	.led_mode = IWL_LED_RF_STATE,				\
+	.rx_with_siso_diversity = true
+
 struct iwl_cfg iwl100_bgn_cfg = {
-	.name = "Intel(R) 100 Series 1x1 BGN",
-	.fw_name_pre = IWL100_FW_PRE,
-	.ucode_api_max = IWL100_UCODE_API_MAX,
-	.ucode_api_min = IWL100_UCODE_API_MIN,
-	.sku = IWL_SKU_G|IWL_SKU_N,
-	.valid_tx_ant = ANT_A,
-	.valid_rx_ant = ANT_A,
-	.eeprom_ver = EEPROM_1000_EEPROM_VERSION,
-	.eeprom_calib_ver = EEPROM_1000_TX_POWER_VERSION,
-	.ops = &iwl1000_ops,
-	.mod_params = &iwlagn_mod_params,
-	.base_params = &iwl1000_base_params,
+	.name = "Intel(R) Centrino(R) Wireless-N 100 BGN",
+	IWL_DEVICE_100,
 	.ht_params = &iwl1000_ht_params,
-	.use_new_eeprom_reading = true,
 };
 
 struct iwl_cfg iwl100_bg_cfg = {
-	.name = "Intel(R) 100 Series 1x1 BG",
-	.fw_name_pre = IWL100_FW_PRE,
-	.ucode_api_max = IWL100_UCODE_API_MAX,
-	.ucode_api_min = IWL100_UCODE_API_MIN,
-	.sku = IWL_SKU_G,
-	.valid_tx_ant = ANT_A,
-	.valid_rx_ant = ANT_A,
-	.eeprom_ver = EEPROM_1000_EEPROM_VERSION,
-	.eeprom_calib_ver = EEPROM_1000_TX_POWER_VERSION,
-	.ops = &iwl1000_ops,
-	.mod_params = &iwlagn_mod_params,
-	.base_params = &iwl1000_base_params,
-	.use_new_eeprom_reading = true,
+	.name = "Intel(R) Centrino(R) Wireless-N 100 BG",
+	IWL_DEVICE_100,
 };
 
 /*(DEBLOBBED)*/
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/iwlwifi/iwl3945-base.c linux-libre-2.6.38-gnu1/drivers/net/wireless/iwlwifi/iwl3945-base.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/iwlwifi/iwl3945-base.c	2013-05-03 04:00:44.000000000 -0400
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/iwlwifi/iwl3945-base.c	2013-05-03 02:01:07.000000000 -0400
@@ -61,6 +61,7 @@
 #include "iwl-helpers.h"
 #include "iwl-dev.h"
 #include "iwl-spectrum.h"
+#include "iwl-legacy.h"
 
 /*
  * module name, copyright, version, etc.
@@ -474,7 +475,7 @@ static int iwl3945_tx_skb(struct iwl_pri
 	dma_addr_t phys_addr;
 	dma_addr_t txcmd_phys;
 	int txq_id = skb_get_queue_mapping(skb);
-	u16 len, idx, len_org, hdr_len; /* TODO: len_org is not used */
+	u16 len, idx, hdr_len;
 	u8 id;
 	u8 unicast;
 	u8 sta_id;
@@ -611,15 +612,8 @@ static int iwl3945_tx_skb(struct iwl_pri
 	 */
 	len = sizeof(struct iwl3945_tx_cmd) +
 			sizeof(struct iwl_cmd_header) + hdr_len;
-
-	len_org = len;
 	len = (len + 3) & ~3;
 
-	if (len_org != len)
-		len_org = 1;
-	else
-		len_org = 0;
-
 	/* Physical address of this Tx command's header (not MAC header!),
 	 * within command buffer array. */
 	txcmd_phys = pci_map_single(priv->pci_dev, &out_cmd->hdr,
@@ -661,7 +655,7 @@ static int iwl3945_tx_skb(struct iwl_pri
 			spin_unlock_irqrestore(&priv->lock, flags);
 		}
 
-		iwl_stop_queue(priv, skb_get_queue_mapping(skb));
+		iwl_stop_queue(priv, txq);
 	}
 
 	return 0;
@@ -2515,13 +2509,8 @@ static void iwl3945_alive_start(struct i
 	/* After the ALIVE response, we can send commands to 3945 uCode */
 	set_bit(STATUS_ALIVE, &priv->status);
 
-	if (priv->cfg->ops->lib->recover_from_tx_stall) {
-		/* Enable timer to monitor the driver queues */
-		mod_timer(&priv->monitor_recover,
-			jiffies +
-			msecs_to_jiffies(
-			  priv->cfg->base_params->monitor_recover_period));
-	}
+	/* Enable watchdog to monitor the driver tx queues */
+	iwl_setup_watchdog(priv);
 
 	if (iwl_is_rfkill(priv))
 		return;
@@ -2578,8 +2567,7 @@ static void __iwl3945_down(struct iwl_pr
 
 	/* Stop TX queues watchdog. We need to have STATUS_EXIT_PENDING bit set
 	 * to prevent rearm timer */
-	if (priv->cfg->ops->lib->recover_from_tx_stall)
-		del_timer_sync(&priv->monitor_recover);
+	del_timer_sync(&priv->watchdog);
 
 	/* Station information will now be cleared in device */
 	iwl_clear_ucode_stations(priv, NULL);
@@ -3057,22 +3045,22 @@ static void iwl3945_bg_rx_replenish(stru
 	mutex_unlock(&priv->mutex);
 }
 
-void iwl3945_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif)
+void iwl3945_post_associate(struct iwl_priv *priv)
 {
 	int rc = 0;
 	struct ieee80211_conf *conf = NULL;
 	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
 
-	if (!vif || !priv->is_open)
+	if (!ctx->vif || !priv->is_open)
 		return;
 
-	if (vif->type == NL80211_IFTYPE_AP) {
+	if (ctx->vif->type == NL80211_IFTYPE_AP) {
 		IWL_ERR(priv, "%s Should not be called in AP mode\n", __func__);
 		return;
 	}
 
 	IWL_DEBUG_ASSOC(priv, "Associated as %d to: %pM\n",
-			vif->bss_conf.aid, ctx->active.bssid_addr);
+			ctx->vif->bss_conf.aid, ctx->active.bssid_addr);
 
 	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
 		return;
@@ -3091,18 +3079,18 @@ void iwl3945_post_associate(struct iwl_p
 
 	ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
 
-	ctx->staging.assoc_id = cpu_to_le16(vif->bss_conf.aid);
+	ctx->staging.assoc_id = cpu_to_le16(ctx->vif->bss_conf.aid);
 
 	IWL_DEBUG_ASSOC(priv, "assoc id %d beacon interval %d\n",
-			vif->bss_conf.aid, vif->bss_conf.beacon_int);
+			ctx->vif->bss_conf.aid, ctx->vif->bss_conf.beacon_int);
 
-	if (vif->bss_conf.use_short_preamble)
+	if (ctx->vif->bss_conf.use_short_preamble)
 		ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
 	else
 		ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
 
 	if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK) {
-		if (vif->bss_conf.use_short_slot)
+		if (ctx->vif->bss_conf.use_short_slot)
 			ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK;
 		else
 			ctx->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
@@ -3110,7 +3098,7 @@ void iwl3945_post_associate(struct iwl_p
 
 	iwl3945_commit_rxon(priv, ctx);
 
-	switch (vif->type) {
+	switch (ctx->vif->type) {
 	case NL80211_IFTYPE_STATION:
 		iwl3945_rate_scale_init(priv->hw, IWL_AP_ID);
 		break;
@@ -3119,7 +3107,7 @@ void iwl3945_post_associate(struct iwl_p
 		break;
 	default:
 		IWL_ERR(priv, "%s Should not be called in %d mode\n",
-			__func__, vif->type);
+			__func__, ctx->vif->type);
 		break;
 	}
 }
@@ -3234,9 +3222,10 @@ static int iwl3945_mac_tx(struct ieee802
 	return NETDEV_TX_OK;
 }
 
-void iwl3945_config_ap(struct iwl_priv *priv, struct ieee80211_vif *vif)
+void iwl3945_config_ap(struct iwl_priv *priv)
 {
 	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
+	struct ieee80211_vif *vif = ctx->vif;
 	int rc = 0;
 
 	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
@@ -3407,9 +3396,9 @@ static void iwl3945_configure_filter(str
 	ctx->staging.filter_flags |= filter_or;
 
 	/*
-	 * Committing directly here breaks for some reason,
-	 * but we'll eventually commit the filter flags
-	 * change anyway.
+	 * Not committing directly because hardware can perform a scan,
+	 * but even if hw is ready, committing here breaks for some reason,
+	 * we'll eventually commit the filter flags change anyway.
 	 */
 
 	mutex_unlock(&priv->mutex);
@@ -3780,12 +3769,9 @@ static void iwl3945_setup_deferred_work(
 
 	iwl3945_hw_setup_deferred_work(priv);
 
-	if (priv->cfg->ops->lib->recover_from_tx_stall) {
-		init_timer(&priv->monitor_recover);
-		priv->monitor_recover.data = (unsigned long)priv;
-		priv->monitor_recover.function =
-			priv->cfg->ops->lib->recover_from_tx_stall;
-	}
+	init_timer(&priv->watchdog);
+	priv->watchdog.data = (unsigned long)priv;
+	priv->watchdog.function = iwl_bg_watchdog;
 
 	tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long))
 		     iwl3945_irq_tasklet, (unsigned long)priv);
@@ -3824,18 +3810,19 @@ static struct attribute_group iwl3945_at
 	.attrs = iwl3945_sysfs_entries,
 };
 
-static struct ieee80211_ops iwl3945_hw_ops = {
+struct ieee80211_ops iwl3945_hw_ops = {
 	.tx = iwl3945_mac_tx,
 	.start = iwl3945_mac_start,
 	.stop = iwl3945_mac_stop,
 	.add_interface = iwl_mac_add_interface,
 	.remove_interface = iwl_mac_remove_interface,
-	.config = iwl_mac_config,
+	.change_interface = iwl_mac_change_interface,
+	.config = iwl_legacy_mac_config,
 	.configure_filter = iwl3945_configure_filter,
 	.set_key = iwl3945_mac_set_key,
 	.conf_tx = iwl_mac_conf_tx,
-	.reset_tsf = iwl_mac_reset_tsf,
-	.bss_info_changed = iwl_bss_info_changed,
+	.reset_tsf = iwl_legacy_mac_reset_tsf,
+	.bss_info_changed = iwl_legacy_mac_bss_info_changed,
 	.hw_scan = iwl_mac_hw_scan,
 	.sta_add = iwl3945_mac_sta_add,
 	.sta_remove = iwl_mac_sta_remove,
@@ -3865,7 +3852,15 @@ static int iwl3945_init_drv(struct iwl_p
 	priv->iw_mode = NL80211_IFTYPE_STATION;
 	priv->missed_beacon_threshold = IWL_MISSED_BEACON_THRESHOLD_DEF;
 
+	/* initialize force reset */
+	priv->force_reset[IWL_RF_RESET].reset_duration =
+		IWL_DELAY_NEXT_FORCE_RF_RESET;
+	priv->force_reset[IWL_FW_RESET].reset_duration =
+		IWL_DELAY_NEXT_FORCE_FW_RELOAD;
+
+
 	priv->tx_power_user_lmt = IWL_DEFAULT_TX_POWER;
+	priv->tx_power_next = IWL_DEFAULT_TX_POWER;
 
 	if (eeprom->version < EEPROM_3945_EEPROM_VERSION) {
 		IWL_WARN(priv, "Unsupported EEPROM version: 0x%04X\n",
@@ -3965,7 +3960,7 @@ static int iwl3945_pci_probe(struct pci_
 
 	/* mac80211 allocates memory for this device instance, including
 	 *   space for this driver's private structure */
-	hw = iwl_alloc_all(cfg, &iwl3945_hw_ops);
+	hw = iwl_alloc_all(cfg);
 	if (hw == NULL) {
 		pr_err("Can not allocate network device\n");
 		err = -ENOMEM;
@@ -4117,7 +4112,7 @@ static int iwl3945_pci_probe(struct pci_
 
 	pci_enable_msi(priv->pci_dev);
 
-	err = request_irq(priv->pci_dev->irq, priv->cfg->ops->lib->isr,
+	err = request_irq(priv->pci_dev->irq, priv->cfg->ops->lib->isr_ops.isr,
 			  IRQF_SHARED, DRV_NAME, priv);
 	if (err) {
 		IWL_ERR(priv, "Error allocating IRQ %d\n", priv->pci_dev->irq);
@@ -4275,10 +4270,7 @@ static struct pci_driver iwl3945_driver
 	.id_table = iwl3945_hw_card_ids,
 	.probe = iwl3945_pci_probe,
 	.remove = __devexit_p(iwl3945_pci_remove),
-#ifdef CONFIG_PM
-	.suspend = iwl_pci_suspend,
-	.resume = iwl_pci_resume,
-#endif
+	.driver.pm = IWL_PM_OPS,
 };
 
 static int __init iwl3945_init(void)
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/iwlwifi/iwl-3945.c linux-libre-2.6.38-gnu1/drivers/net/wireless/iwlwifi/iwl-3945.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/iwlwifi/iwl-3945.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/iwlwifi/iwl-3945.c	2011-03-14 21:20:32.000000000 -0400
@@ -51,6 +51,7 @@
 #include "iwl-led.h"
 #include "iwl-3945-led.h"
 #include "iwl-3945-debugfs.h"
+#include "iwl-legacy.h"
 
 #define IWL_DECLARE_RATE_INFO(r, ip, in, rp, rn, pp, np)    \
 	[IWL_RATE_##r##M_INDEX] = { IWL_RATE_##r##M_PLCP,   \
@@ -115,7 +116,7 @@ void iwl3945_disable_events(struct iwl_p
 	u32 base;		/* SRAM address of event log header */
 	u32 disable_ptr;	/* SRAM address of event-disable bitmap array */
 	u32 array_size;		/* # of u32 entries in array */
-	u32 evt_disable[IWL_EVT_DISABLE_SIZE] = {
+	static const u32 evt_disable[IWL_EVT_DISABLE_SIZE] = {
 		0x00000000,	/*   31 -    0  Event id numbers */
 		0x00000000,	/*   63 -   32 */
 		0x00000000,	/*   95 -   64 */
@@ -296,7 +297,7 @@ static void iwl3945_tx_queue_reclaim(str
 	if (iwl_queue_space(q) > q->low_mark && (txq_id >= 0) &&
 			(txq_id != IWL39_CMD_QUEUE_NUM) &&
 			priv->mac80211_registered)
-		iwl_wake_queue(priv, txq_id);
+		iwl_wake_queue(priv, txq);
 }
 
 /**
@@ -324,6 +325,7 @@ static void iwl3945_rx_reply_tx(struct i
 		return;
 	}
 
+	txq->time_stamp = jiffies;
 	info = IEEE80211_SKB_CB(txq->txb[txq->q.read_ptr].skb);
 	ieee80211_tx_info_clear_status(info);
 
@@ -400,72 +402,6 @@ static void iwl3945_accumulative_statist
 }
 #endif
 
-/**
- * iwl3945_good_plcp_health - checks for plcp error.
- *
- * When the plcp error is exceeding the thresholds, reset the radio
- * to improve the throughput.
- */
-static bool iwl3945_good_plcp_health(struct iwl_priv *priv,
-				struct iwl_rx_packet *pkt)
-{
-	bool rc = true;
-	struct iwl3945_notif_statistics current_stat;
-	int combined_plcp_delta;
-	unsigned int plcp_msec;
-	unsigned long plcp_received_jiffies;
-
-	if (priv->cfg->base_params->plcp_delta_threshold ==
-	    IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE) {
-		IWL_DEBUG_RADIO(priv, "plcp_err check disabled\n");
-		return rc;
-	}
-	memcpy(&current_stat, pkt->u.raw, sizeof(struct
-			iwl3945_notif_statistics));
-	/*
-	 * check for plcp_err and trigger radio reset if it exceeds
-	 * the plcp error threshold plcp_delta.
-	 */
-	plcp_received_jiffies = jiffies;
-	plcp_msec = jiffies_to_msecs((long) plcp_received_jiffies -
-					(long) priv->plcp_jiffies);
-	priv->plcp_jiffies = plcp_received_jiffies;
-	/*
-	 * check to make sure plcp_msec is not 0 to prevent division
-	 * by zero.
-	 */
-	if (plcp_msec) {
-		combined_plcp_delta =
-			(le32_to_cpu(current_stat.rx.ofdm.plcp_err) -
-			le32_to_cpu(priv->_3945.statistics.rx.ofdm.plcp_err));
-
-		if ((combined_plcp_delta > 0) &&
-			((combined_plcp_delta * 100) / plcp_msec) >
-			priv->cfg->base_params->plcp_delta_threshold) {
-			/*
-			 * if plcp_err exceed the threshold, the following
-			 * data is printed in csv format:
-			 *    Text: plcp_err exceeded %d,
-			 *    Received ofdm.plcp_err,
-			 *    Current ofdm.plcp_err,
-			 *    combined_plcp_delta,
-			 *    plcp_msec
-			 */
-			IWL_DEBUG_RADIO(priv, "plcp_err exceeded %u, "
-				"%u, %d, %u mSecs\n",
-				priv->cfg->base_params->plcp_delta_threshold,
-				le32_to_cpu(current_stat.rx.ofdm.plcp_err),
-				combined_plcp_delta, plcp_msec);
-			/*
-			 * Reset the RF radio due to the high plcp
-			 * error rate
-			 */
-			rc = false;
-		}
-	}
-	return rc;
-}
-
 void iwl3945_hw_rx_statistics(struct iwl_priv *priv,
 		struct iwl_rx_mem_buffer *rxb)
 {
@@ -1451,6 +1387,10 @@ static int iwl3945_send_tx_power(struct
 	};
 	u16 chan;
 
+	if (WARN_ONCE(test_bit(STATUS_SCAN_HW, &priv->status),
+		      "TX Power requested while scanning!\n"))
+		return -EAGAIN;
+
 	chan = le16_to_cpu(priv->contexts[IWL_RXON_CTX_BSS].active.channel);
 
 	txpower.band = (priv->band == IEEE80211_BAND_5GHZ) ? 0 : 1;
@@ -1779,6 +1719,9 @@ int iwl3945_commit_rxon(struct iwl_priv
 	int rc = 0;
 	bool new_assoc = !!(staging_rxon->filter_flags & RXON_FILTER_ASSOC_MSK);
 
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+		return -EINVAL;
+
 	if (!iwl_is_alive(priv))
 		return -1;
 
@@ -2722,12 +2665,9 @@ static struct iwl_lib_ops iwl3945_lib =
 	},
 	.send_tx_power	= iwl3945_send_tx_power,
 	.is_valid_rtc_data_addr = iwl3945_hw_valid_rtc_data_addr,
-	.post_associate = iwl3945_post_associate,
-	.isr = iwl_isr_legacy,
-	.config_ap = iwl3945_config_ap,
-	.manage_ibss_station = iwl3945_manage_ibss_station,
-	.recover_from_tx_stall = iwl_bg_monitor_recover,
-	.check_plcp_health = iwl3945_good_plcp_health,
+	.isr_ops = {
+		.isr = iwl_isr_legacy,
+	},
 
 	.debugfs_ops = {
 		.rx_stats_read = iwl3945_ucode_rx_stats_read,
@@ -2736,10 +2676,16 @@ static struct iwl_lib_ops iwl3945_lib =
 	},
 };
 
+static const struct iwl_legacy_ops iwl3945_legacy_ops = {
+	.post_associate = iwl3945_post_associate,
+	.config_ap = iwl3945_config_ap,
+	.manage_ibss_station = iwl3945_manage_ibss_station,
+};
+
 static struct iwl_hcmd_utils_ops iwl3945_hcmd_utils = {
 	.get_hcmd_size = iwl3945_get_hcmd_size,
 	.build_addsta_hcmd = iwl3945_build_addsta_hcmd,
-	.tx_cmd_protection = iwlcore_tx_cmd_protection,
+	.tx_cmd_protection = iwl_legacy_tx_cmd_protection,
 	.request_scan = iwl3945_request_scan,
 	.post_scan = iwl3945_post_scan,
 };
@@ -2749,6 +2695,8 @@ static const struct iwl_ops iwl3945_ops
 	.hcmd = &iwl3945_hcmd,
 	.utils = &iwl3945_hcmd_utils,
 	.led = &iwl3945_led_ops,
+	.legacy = &iwl3945_legacy_ops,
+	.ieee80211_ops = &iwl3945_hw_ops,
 };
 
 static struct iwl_base_params iwl3945_base_params = {
@@ -2761,7 +2709,7 @@ static struct iwl_base_params iwl3945_ba
 	.led_compensation = 64,
 	.broken_powersave = true,
 	.plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF,
-	.monitor_recover_period = IWL_DEF_MONITORING_PERIOD,
+	.wd_timeout = IWL_DEF_WD_TIMEOUT,
 	.max_event_log_size = 512,
 	.tx_power_by_driver = true,
 };
@@ -2776,6 +2724,7 @@ static struct iwl_cfg iwl3945_bg_cfg = {
 	.ops = &iwl3945_ops,
 	.mod_params = &iwl3945_mod_params,
 	.base_params = &iwl3945_base_params,
+	.led_mode = IWL_LED_BLINK,
 };
 
 static struct iwl_cfg iwl3945_abg_cfg = {
@@ -2788,6 +2737,7 @@ static struct iwl_cfg iwl3945_abg_cfg =
 	.ops = &iwl3945_ops,
 	.mod_params = &iwl3945_mod_params,
 	.base_params = &iwl3945_base_params,
+	.led_mode = IWL_LED_BLINK,
 };
 
 DEFINE_PCI_DEVICE_TABLE(iwl3945_hw_card_ids) = {
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/iwlwifi/iwl-3945.h linux-libre-2.6.38-gnu1/drivers/net/wireless/iwlwifi/iwl-3945.h
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/iwlwifi/iwl-3945.h	2013-05-03 04:00:46.000000000 -0400
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/iwlwifi/iwl-3945.h	2013-05-03 02:01:10.000000000 -0400
@@ -264,10 +264,8 @@ void iwl3945_reply_statistics(struct iwl
 			      struct iwl_rx_mem_buffer *rxb);
 extern void iwl3945_disable_events(struct iwl_priv *priv);
 extern int iwl4965_get_temperature(const struct iwl_priv *priv);
-extern void iwl3945_post_associate(struct iwl_priv *priv,
-				   struct ieee80211_vif *vif);
-extern void iwl3945_config_ap(struct iwl_priv *priv,
-			      struct ieee80211_vif *vif);
+extern void iwl3945_post_associate(struct iwl_priv *priv);
+extern void iwl3945_config_ap(struct iwl_priv *priv);
 
 extern int iwl3945_commit_rxon(struct iwl_priv *priv,
 			       struct iwl_rxon_context *ctx);
@@ -282,6 +280,8 @@ extern int iwl3945_commit_rxon(struct iw
  */
 extern u8 iwl3945_hw_find_station(struct iwl_priv *priv, const u8 *bssid);
 
+extern struct ieee80211_ops iwl3945_hw_ops;
+
 /*
  * Forward declare iwl-3945.c functions for iwl-base.c
  */
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/iwlwifi/iwl-4965.c linux-libre-2.6.38-gnu1/drivers/net/wireless/iwlwifi/iwl-4965.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/iwlwifi/iwl-4965.c	2013-05-03 04:00:53.000000000 -0400
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/iwlwifi/iwl-4965.c	2013-05-03 02:01:18.000000000 -0400
@@ -48,6 +48,7 @@
 #include "iwl-agn-led.h"
 #include "iwl-agn.h"
 #include "iwl-agn-debugfs.h"
+#include "iwl-legacy.h"
 
 static int iwl4965_send_tx_power(struct iwl_priv *priv);
 static int iwl4965_hw_get_temperature(struct iwl_priv *priv);
@@ -1377,13 +1378,9 @@ static int iwl4965_send_tx_power(struct
 	u8 ctrl_chan_high = 0;
 	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
 
-	if (test_bit(STATUS_SCANNING, &priv->status)) {
-		/* If this gets hit a lot, switch it to a BUG() and catch
-		 * the stack trace to find out who is calling this during
-		 * a scan. */
-		IWL_WARN(priv, "TX Power requested while scanning!\n");
+	if (WARN_ONCE(test_bit(STATUS_SCAN_HW, &priv->status),
+		      "TX Power requested while scanning!\n"))
 		return -EAGAIN;
-	}
 
 	band = priv->band == IEEE80211_BAND_2GHZ;
 
@@ -1447,6 +1444,142 @@ static int iwl4965_send_rxon_assoc(struc
 	return ret;
 }
 
+static int iwl4965_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
+{
+	/* cast away the const for active_rxon in this function */
+	struct iwl_rxon_cmd *active_rxon = (void *)&ctx->active;
+	int ret;
+	bool new_assoc =
+		!!(ctx->staging.filter_flags & RXON_FILTER_ASSOC_MSK);
+
+	if (!iwl_is_alive(priv))
+		return -EBUSY;
+
+	if (!ctx->is_active)
+		return 0;
+
+	/* always get timestamp with Rx frame */
+	ctx->staging.flags |= RXON_FLG_TSF2HOST_MSK;
+
+	ret = iwl_check_rxon_cmd(priv, ctx);
+	if (ret) {
+		IWL_ERR(priv, "Invalid RXON configuration.  Not committing.\n");
+		return -EINVAL;
+	}
+
+	/*
+	 * receive commit_rxon request
+	 * abort any previous channel switch if still in process
+	 */
+	if (priv->switch_rxon.switch_in_progress &&
+	    (priv->switch_rxon.channel != ctx->staging.channel)) {
+		IWL_DEBUG_11H(priv, "abort channel switch on %d\n",
+		      le16_to_cpu(priv->switch_rxon.channel));
+		iwl_chswitch_done(priv, false);
+	}
+
+	/* If we don't need to send a full RXON, we can use
+	 * iwl_rxon_assoc_cmd which is used to reconfigure filter
+	 * and other flags for the current radio configuration. */
+	if (!iwl_full_rxon_required(priv, ctx)) {
+		ret = iwl_send_rxon_assoc(priv, ctx);
+		if (ret) {
+			IWL_ERR(priv, "Error setting RXON_ASSOC (%d)\n", ret);
+			return ret;
+		}
+
+		memcpy(active_rxon, &ctx->staging, sizeof(*active_rxon));
+		iwl_print_rx_config_cmd(priv, ctx);
+		return 0;
+	}
+
+	/* If we are currently associated and the new config requires
+	 * an RXON_ASSOC and the new config wants the associated mask enabled,
+	 * we must clear the associated from the active configuration
+	 * before we apply the new config */
+	if (iwl_is_associated_ctx(ctx) && new_assoc) {
+		IWL_DEBUG_INFO(priv, "Toggling associated bit on current RXON\n");
+		active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
+
+		ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd,
+				       sizeof(struct iwl_rxon_cmd),
+				       active_rxon);
+
+		/* If the mask clearing failed then we set
+		 * active_rxon back to what it was previously */
+		if (ret) {
+			active_rxon->filter_flags |= RXON_FILTER_ASSOC_MSK;
+			IWL_ERR(priv, "Error clearing ASSOC_MSK (%d)\n", ret);
+			return ret;
+		}
+		iwl_clear_ucode_stations(priv, ctx);
+		iwl_restore_stations(priv, ctx);
+		ret = iwl_restore_default_wep_keys(priv, ctx);
+		if (ret) {
+			IWL_ERR(priv, "Failed to restore WEP keys (%d)\n", ret);
+			return ret;
+		}
+	}
+
+	IWL_DEBUG_INFO(priv, "Sending RXON\n"
+		       "* with%s RXON_FILTER_ASSOC_MSK\n"
+		       "* channel = %d\n"
+		       "* bssid = %pM\n",
+		       (new_assoc ? "" : "out"),
+		       le16_to_cpu(ctx->staging.channel),
+		       ctx->staging.bssid_addr);
+
+	iwl_set_rxon_hwcrypto(priv, ctx, !priv->cfg->mod_params->sw_crypto);
+
+	/* Apply the new configuration
+	 * RXON unassoc clears the station table in uCode so restoration of
+	 * stations is needed after it (the RXON command) completes
+	 */
+	if (!new_assoc) {
+		ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd,
+			      sizeof(struct iwl_rxon_cmd), &ctx->staging);
+		if (ret) {
+			IWL_ERR(priv, "Error setting new RXON (%d)\n", ret);
+			return ret;
+		}
+		IWL_DEBUG_INFO(priv, "Return from !new_assoc RXON.\n");
+		memcpy(active_rxon, &ctx->staging, sizeof(*active_rxon));
+		iwl_clear_ucode_stations(priv, ctx);
+		iwl_restore_stations(priv, ctx);
+		ret = iwl_restore_default_wep_keys(priv, ctx);
+		if (ret) {
+			IWL_ERR(priv, "Failed to restore WEP keys (%d)\n", ret);
+			return ret;
+		}
+	}
+	if (new_assoc) {
+		priv->start_calib = 0;
+		/* Apply the new configuration
+		 * RXON assoc doesn't clear the station table in uCode,
+		 */
+		ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd,
+			      sizeof(struct iwl_rxon_cmd), &ctx->staging);
+		if (ret) {
+			IWL_ERR(priv, "Error setting new RXON (%d)\n", ret);
+			return ret;
+		}
+		memcpy(active_rxon, &ctx->staging, sizeof(*active_rxon));
+	}
+	iwl_print_rx_config_cmd(priv, ctx);
+
+	iwl_init_sensitivity(priv);
+
+	/* If we issue a new RXON command which required a tune then we must
+	 * send a new TXPOWER command or we won't be able to Tx any frames */
+	ret = iwl_set_tx_power(priv, priv->tx_power_user_lmt, true);
+	if (ret) {
+		IWL_ERR(priv, "Error sending TX power (%d)\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
 static int iwl4965_hw_channel_switch(struct iwl_priv *priv,
 				     struct ieee80211_channel_switch *ch_switch)
 {
@@ -1554,22 +1687,6 @@ static void iwl4965_txq_update_byte_cnt_
 }
 
 /**
- * sign_extend - Sign extend a value using specified bit as sign-bit
- *
- * Example: sign_extend(9, 3) would return -7 as bit3 of 1001b is 1
- * and bit0..2 is 001b which when sign extended to 1111111111111001b is -7.
- *
- * @param oper value to sign extend
- * @param index 0 based bit index (0<=index<32) to sign bit
- */
-static s32 sign_extend(u32 oper, int index)
-{
-	u8 shift = 31 - index;
-
-	return (s32)(oper << shift) >> shift;
-}
-
-/**
  * iwl4965_hw_get_temperature - return the calibrated temperature (in Kelvin)
  * @statistics: Provides the temperature reading from the uCode
  *
@@ -1606,9 +1723,9 @@ static int iwl4965_hw_get_temperature(st
 	 * "initialize" ALIVE response.
 	 */
 	if (!test_bit(STATUS_TEMPERATURE, &priv->status))
-		vt = sign_extend(R4, 23);
+		vt = sign_extend32(R4, 23);
 	else
-		vt = sign_extend(le32_to_cpu(priv->_agn.statistics.
+		vt = sign_extend32(le32_to_cpu(priv->_agn.statistics.
 				 general.common.temperature), 23);
 
 	IWL_DEBUG_TEMP(priv, "Calib values R[1-3]: %d %d %d R4: %d\n", R1, R2, R3, vt);
@@ -2081,6 +2198,7 @@ static void iwl4965_rx_reply_tx(struct i
 		return;
 	}
 
+	txq->time_stamp = jiffies;
 	info = IEEE80211_SKB_CB(txq->txb[txq->q.read_ptr].skb);
 	memset(&info->status, 0, sizeof(info->status));
 
@@ -2121,12 +2239,8 @@ static void iwl4965_rx_reply_tx(struct i
 
 			if (priv->mac80211_registered &&
 			    (iwl_queue_space(&txq->q) > txq->q.low_mark) &&
-			    (agg->state != IWL_EMPTYING_HW_QUEUE_DELBA)) {
-				if (agg->state == IWL_AGG_OFF)
-					iwl_wake_queue(priv, txq_id);
-				else
-					iwl_wake_queue(priv, txq->swq_id);
-			}
+			    (agg->state != IWL_EMPTYING_HW_QUEUE_DELBA))
+				iwl_wake_queue(priv, txq);
 		}
 	} else {
 		info->status.rates[0].count = tx_resp->failure_frame + 1;
@@ -2150,7 +2264,7 @@ static void iwl4965_rx_reply_tx(struct i
 
 		if (priv->mac80211_registered &&
 		    (iwl_queue_space(&txq->q) > txq->q.low_mark))
-			iwl_wake_queue(priv, txq_id);
+			iwl_wake_queue(priv, txq);
 	}
 	if (qc && likely(sta_id != IWL_INVALID_STATION))
 		iwlagn_txq_check_empty(priv, sta_id, tid, txq_id);
@@ -2216,7 +2330,7 @@ static void iwl4965_cancel_deferred_work
 
 static struct iwl_hcmd_ops iwl4965_hcmd = {
 	.rxon_assoc = iwl4965_send_rxon_assoc,
-	.commit_rxon = iwlagn_commit_rxon,
+	.commit_rxon = iwl4965_commit_rxon,
 	.set_rxon_chain = iwlagn_set_rxon_chain,
 	.send_bt_config = iwl_send_bt_config,
 };
@@ -2233,12 +2347,155 @@ static void iwl4965_post_scan(struct iwl
 		iwlcore_commit_rxon(priv, ctx);
 }
 
+static void iwl4965_post_associate(struct iwl_priv *priv)
+{
+	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
+	struct ieee80211_vif *vif = ctx->vif;
+	struct ieee80211_conf *conf = NULL;
+	int ret = 0;
+
+	if (!vif || !priv->is_open)
+		return;
+
+	if (vif->type == NL80211_IFTYPE_AP) {
+		IWL_ERR(priv, "%s Should not be called in AP mode\n", __func__);
+		return;
+	}
+
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+		return;
+
+	iwl_scan_cancel_timeout(priv, 200);
+
+	conf = ieee80211_get_hw_conf(priv->hw);
+
+	ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
+	iwlcore_commit_rxon(priv, ctx);
+
+	ret = iwl_send_rxon_timing(priv, ctx);
+	if (ret)
+		IWL_WARN(priv, "RXON timing - "
+			    "Attempting to continue.\n");
+
+	ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
+
+	iwl_set_rxon_ht(priv, &priv->current_ht_config);
+
+	if (priv->cfg->ops->hcmd->set_rxon_chain)
+		priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
+
+	ctx->staging.assoc_id = cpu_to_le16(vif->bss_conf.aid);
+
+	IWL_DEBUG_ASSOC(priv, "assoc id %d beacon interval %d\n",
+			vif->bss_conf.aid, vif->bss_conf.beacon_int);
+
+	if (vif->bss_conf.use_short_preamble)
+		ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
+	else
+		ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
+
+	if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK) {
+		if (vif->bss_conf.use_short_slot)
+			ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK;
+		else
+			ctx->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
+	}
+
+	iwlcore_commit_rxon(priv, ctx);
+
+	IWL_DEBUG_ASSOC(priv, "Associated as %d to: %pM\n",
+			vif->bss_conf.aid, ctx->active.bssid_addr);
+
+	switch (vif->type) {
+	case NL80211_IFTYPE_STATION:
+		break;
+	case NL80211_IFTYPE_ADHOC:
+		iwlagn_send_beacon_cmd(priv);
+		break;
+	default:
+		IWL_ERR(priv, "%s Should not be called in %d mode\n",
+			  __func__, vif->type);
+		break;
+	}
+
+	/* the chain noise calibration will enabled PM upon completion
+	 * If chain noise has already been run, then we need to enable
+	 * power management here */
+	if (priv->chain_noise_data.state == IWL_CHAIN_NOISE_DONE)
+		iwl_power_update_mode(priv, false);
+
+	/* Enable Rx differential gain and sensitivity calibrations */
+	iwl_chain_noise_reset(priv);
+	priv->start_calib = 1;
+}
+
+static void iwl4965_config_ap(struct iwl_priv *priv)
+{
+	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
+	struct ieee80211_vif *vif = ctx->vif;
+	int ret = 0;
+
+	lockdep_assert_held(&priv->mutex);
+
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+		return;
+
+	/* The following should be done only at AP bring up */
+	if (!iwl_is_associated_ctx(ctx)) {
+
+		/* RXON - unassoc (to set timing command) */
+		ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
+		iwlcore_commit_rxon(priv, ctx);
+
+		/* RXON Timing */
+		ret = iwl_send_rxon_timing(priv, ctx);
+		if (ret)
+			IWL_WARN(priv, "RXON timing failed - "
+					"Attempting to continue.\n");
+
+		/* AP has all antennas */
+		priv->chain_noise_data.active_chains =
+			priv->hw_params.valid_rx_ant;
+		iwl_set_rxon_ht(priv, &priv->current_ht_config);
+		if (priv->cfg->ops->hcmd->set_rxon_chain)
+			priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
+
+		ctx->staging.assoc_id = 0;
+
+		if (vif->bss_conf.use_short_preamble)
+			ctx->staging.flags |=
+				RXON_FLG_SHORT_PREAMBLE_MSK;
+		else
+			ctx->staging.flags &=
+				~RXON_FLG_SHORT_PREAMBLE_MSK;
+
+		if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK) {
+			if (vif->bss_conf.use_short_slot)
+				ctx->staging.flags |=
+					RXON_FLG_SHORT_SLOT_MSK;
+			else
+				ctx->staging.flags &=
+					~RXON_FLG_SHORT_SLOT_MSK;
+		}
+		/* need to send beacon cmd before committing assoc RXON! */
+		iwlagn_send_beacon_cmd(priv);
+		/* restore RXON assoc */
+		ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
+		iwlcore_commit_rxon(priv, ctx);
+	}
+	iwlagn_send_beacon_cmd(priv);
+
+	/* FIXME - we need to add code here to detect a totally new
+	 * configuration, reset the AP, unassoc, rxon timing, assoc,
+	 * clear sta table, add BCAST sta... */
+}
+
 static struct iwl_hcmd_utils_ops iwl4965_hcmd_utils = {
 	.get_hcmd_size = iwl4965_get_hcmd_size,
 	.build_addsta_hcmd = iwl4965_build_addsta_hcmd,
 	.chain_noise_reset = iwl4965_chain_noise_reset,
 	.gain_computation = iwl4965_gain_computation,
-	.tx_cmd_protection = iwlcore_tx_cmd_protection,
+	.tx_cmd_protection = iwl_legacy_tx_cmd_protection,
 	.calc_rssi = iwl4965_calc_rssi,
 	.request_scan = iwlagn_request_scan,
 	.post_scan = iwl4965_post_scan,
@@ -2285,14 +2542,12 @@ static struct iwl_lib_ops iwl4965_lib =
 	},
 	.send_tx_power	= iwl4965_send_tx_power,
 	.update_chain_flags = iwl_update_chain_flags,
-	.post_associate = iwl_post_associate,
-	.config_ap = iwl_config_ap,
-	.isr = iwl_isr_legacy,
+	.isr_ops = {
+		.isr = iwl_isr_legacy,
+	},
 	.temp_ops = {
 		.temperature = iwl4965_temperature_calib,
 	},
-	.manage_ibss_station = iwlagn_manage_ibss_station,
-	.update_bcast_stations = iwl_update_bcast_stations,
 	.debugfs_ops = {
 		.rx_stats_read = iwl_ucode_rx_stats_read,
 		.tx_stats_read = iwl_ucode_tx_stats_read,
@@ -2300,15 +2555,46 @@ static struct iwl_lib_ops iwl4965_lib =
 		.bt_stats_read = iwl_ucode_bt_stats_read,
 		.reply_tx_error = iwl_reply_tx_error_read,
 	},
-	.recover_from_tx_stall = iwl_bg_monitor_recover,
 	.check_plcp_health = iwl_good_plcp_health,
 };
 
+static const struct iwl_legacy_ops iwl4965_legacy_ops = {
+	.post_associate = iwl4965_post_associate,
+	.config_ap = iwl4965_config_ap,
+	.manage_ibss_station = iwlagn_manage_ibss_station,
+	.update_bcast_stations = iwl_update_bcast_stations,
+};
+
+struct ieee80211_ops iwl4965_hw_ops = {
+	.tx = iwlagn_mac_tx,
+	.start = iwlagn_mac_start,
+	.stop = iwlagn_mac_stop,
+	.add_interface = iwl_mac_add_interface,
+	.remove_interface = iwl_mac_remove_interface,
+	.change_interface = iwl_mac_change_interface,
+	.config = iwl_legacy_mac_config,
+	.configure_filter = iwlagn_configure_filter,
+	.set_key = iwlagn_mac_set_key,
+	.update_tkip_key = iwlagn_mac_update_tkip_key,
+	.conf_tx = iwl_mac_conf_tx,
+	.reset_tsf = iwl_legacy_mac_reset_tsf,
+	.bss_info_changed = iwl_legacy_mac_bss_info_changed,
+	.ampdu_action = iwlagn_mac_ampdu_action,
+	.hw_scan = iwl_mac_hw_scan,
+	.sta_add = iwlagn_mac_sta_add,
+	.sta_remove = iwl_mac_sta_remove,
+	.channel_switch = iwlagn_mac_channel_switch,
+	.flush = iwlagn_mac_flush,
+	.tx_last_beacon = iwl_mac_tx_last_beacon,
+};
+
 static const struct iwl_ops iwl4965_ops = {
 	.lib = &iwl4965_lib,
 	.hcmd = &iwl4965_hcmd,
 	.utils = &iwl4965_hcmd_utils,
 	.led = &iwlagn_led_ops,
+	.legacy = &iwl4965_legacy_ops,
+	.ieee80211_ops = &iwl4965_hw_ops,
 };
 
 static struct iwl_base_params iwl4965_base_params = {
@@ -2323,13 +2609,14 @@ static struct iwl_base_params iwl4965_ba
 	.led_compensation = 61,
 	.chain_noise_num_beacons = IWL4965_CAL_NUM_BEACONS,
 	.plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
-	.monitor_recover_period = IWL_DEF_MONITORING_PERIOD,
+	.wd_timeout = IWL_DEF_WD_TIMEOUT,
 	.temperature_kelvin = true,
 	.max_event_log_size = 512,
 	.tx_power_by_driver = true,
 	.ucode_tracing = true,
 	.sensitivity_calib_by_driver = true,
 	.chain_noise_calib_by_driver = true,
+	.no_agg_framecnt_info = true,
 };
 
 struct iwl_cfg iwl4965_agn_cfg = {
@@ -2345,6 +2632,7 @@ struct iwl_cfg iwl4965_agn_cfg = {
 	.ops = &iwl4965_ops,
 	.mod_params = &iwlagn_mod_params,
 	.base_params = &iwl4965_base_params,
+	.led_mode = IWL_LED_BLINK,
 	/*
 	 * Force use of chains B and C for scan RX on 5 GHz band
 	 * because the device has off-channel reception on chain A.
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/iwlwifi/iwl-5000.c linux-libre-2.6.38-gnu1/drivers/net/wireless/iwlwifi/iwl-5000.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/iwlwifi/iwl-5000.c	2013-05-03 04:00:55.000000000 -0400
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/iwlwifi/iwl-5000.c	2013-05-03 02:01:21.000000000 -0400
@@ -51,7 +51,7 @@
 #include "iwl-agn-debugfs.h"
 
 /* Highest firmware API version supported */
-#define IWL5000_UCODE_API_MAX 2
+#define IWL5000_UCODE_API_MAX 5
 #define IWL5150_UCODE_API_MAX 2
 
 /* Lowest firmware API version supported */
@@ -385,14 +385,16 @@ static struct iwl_lib_ops iwl5000_lib =
 		.calib_version	= iwlagn_eeprom_calib_version,
 		.query_addr = iwlagn_eeprom_query_addr,
 	},
-	.post_associate = iwl_post_associate,
-	.isr = iwl_isr_ict,
-	.config_ap = iwl_config_ap,
+	.isr_ops = {
+		.isr = iwl_isr_ict,
+		.free = iwl_free_isr_ict,
+		.alloc = iwl_alloc_isr_ict,
+		.reset = iwl_reset_ict,
+		.disable = iwl_disable_ict,
+	},
 	.temp_ops = {
 		.temperature = iwlagn_temperature,
 	 },
-	.manage_ibss_station = iwlagn_manage_ibss_station,
-	.update_bcast_stations = iwl_update_bcast_stations,
 	.debugfs_ops = {
 		.rx_stats_read = iwl_ucode_rx_stats_read,
 		.tx_stats_read = iwl_ucode_tx_stats_read,
@@ -400,7 +402,6 @@ static struct iwl_lib_ops iwl5000_lib =
 		.bt_stats_read = iwl_ucode_bt_stats_read,
 		.reply_tx_error = iwl_reply_tx_error_read,
 	},
-	.recover_from_tx_stall = iwl_bg_monitor_recover,
 	.check_plcp_health = iwl_good_plcp_health,
 	.check_ack_health = iwl_good_ack_health,
 	.txfifo_flush = iwlagn_txfifo_flush,
@@ -453,14 +454,16 @@ static struct iwl_lib_ops iwl5150_lib =
 		.calib_version	= iwlagn_eeprom_calib_version,
 		.query_addr = iwlagn_eeprom_query_addr,
 	},
-	.post_associate = iwl_post_associate,
-	.isr = iwl_isr_ict,
-	.config_ap = iwl_config_ap,
+	.isr_ops = {
+		.isr = iwl_isr_ict,
+		.free = iwl_free_isr_ict,
+		.alloc = iwl_alloc_isr_ict,
+		.reset = iwl_reset_ict,
+		.disable = iwl_disable_ict,
+	},
 	.temp_ops = {
 		.temperature = iwl5150_temperature,
 	 },
-	.manage_ibss_station = iwlagn_manage_ibss_station,
-	.update_bcast_stations = iwl_update_bcast_stations,
 	.debugfs_ops = {
 		.rx_stats_read = iwl_ucode_rx_stats_read,
 		.tx_stats_read = iwl_ucode_tx_stats_read,
@@ -468,7 +471,6 @@ static struct iwl_lib_ops iwl5150_lib =
 		.bt_stats_read = iwl_ucode_bt_stats_read,
 		.reply_tx_error = iwl_reply_tx_error_read,
 	},
-	.recover_from_tx_stall = iwl_bg_monitor_recover,
 	.check_plcp_health = iwl_good_plcp_health,
 	.check_ack_health = iwl_good_ack_health,
 	.txfifo_flush = iwlagn_txfifo_flush,
@@ -485,6 +487,7 @@ static const struct iwl_ops iwl5000_ops
 	.hcmd = &iwlagn_hcmd,
 	.utils = &iwlagn_hcmd_utils,
 	.led = &iwlagn_led_ops,
+	.ieee80211_ops = &iwlagn_hw_ops,
 };
 
 static const struct iwl_ops iwl5150_ops = {
@@ -492,6 +495,7 @@ static const struct iwl_ops iwl5150_ops
 	.hcmd = &iwlagn_hcmd,
 	.utils = &iwlagn_hcmd_utils,
 	.led = &iwlagn_led_ops,
+	.ieee80211_ops = &iwlagn_hw_ops,
 };
 
 static struct iwl_base_params iwl5000_base_params = {
@@ -505,7 +509,7 @@ static struct iwl_base_params iwl5000_ba
 	.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
 	.plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF,
 	.chain_noise_scale = 1000,
-	.monitor_recover_period = IWL_LONG_MONITORING_PERIOD,
+	.wd_timeout = IWL_LONG_WD_TIMEOUT,
 	.max_event_log_size = 512,
 	.ucode_tracing = true,
 	.sensitivity_calib_by_driver = true,
@@ -516,66 +520,43 @@ static struct iwl_ht_params iwl5000_ht_p
 	.use_rts_for_aggregation = true, /* use rts/cts protection */
 };
 
+#define IWL_DEVICE_5000						\
+	.fw_name_pre = IWL5000_FW_PRE,				\
+	.ucode_api_max = IWL5000_UCODE_API_MAX,			\
+	.ucode_api_min = IWL5000_UCODE_API_MIN,			\
+	.eeprom_ver = EEPROM_5000_EEPROM_VERSION,		\
+	.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,	\
+	.ops = &iwl5000_ops,					\
+	.mod_params = &iwlagn_mod_params,			\
+	.base_params = &iwl5000_base_params,			\
+	.led_mode = IWL_LED_BLINK
+
 struct iwl_cfg iwl5300_agn_cfg = {
 	.name = "Intel(R) Ultimate N WiFi Link 5300 AGN",
-	.fw_name_pre = IWL5000_FW_PRE,
-	.ucode_api_max = IWL5000_UCODE_API_MAX,
-	.ucode_api_min = IWL5000_UCODE_API_MIN,
-	.sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
-	.valid_tx_ant = ANT_ABC,
-	.valid_rx_ant = ANT_ABC,
-	.eeprom_ver = EEPROM_5000_EEPROM_VERSION,
-	.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
-	.ops = &iwl5000_ops,
-	.mod_params = &iwlagn_mod_params,
-	.base_params = &iwl5000_base_params,
+	IWL_DEVICE_5000,
 	.ht_params = &iwl5000_ht_params,
 };
 
 struct iwl_cfg iwl5100_bgn_cfg = {
 	.name = "Intel(R) WiFi Link 5100 BGN",
-	.fw_name_pre = IWL5000_FW_PRE,
-	.ucode_api_max = IWL5000_UCODE_API_MAX,
-	.ucode_api_min = IWL5000_UCODE_API_MIN,
-	.sku = IWL_SKU_G|IWL_SKU_N,
-	.valid_tx_ant = ANT_B,
-	.valid_rx_ant = ANT_AB,
-	.eeprom_ver = EEPROM_5000_EEPROM_VERSION,
-	.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
-	.ops = &iwl5000_ops,
-	.mod_params = &iwlagn_mod_params,
-	.base_params = &iwl5000_base_params,
+	IWL_DEVICE_5000,
+	.valid_tx_ant = ANT_B,		/* .cfg overwrite */
+	.valid_rx_ant = ANT_AB,		/* .cfg overwrite */
 	.ht_params = &iwl5000_ht_params,
 };
 
 struct iwl_cfg iwl5100_abg_cfg = {
 	.name = "Intel(R) WiFi Link 5100 ABG",
-	.fw_name_pre = IWL5000_FW_PRE,
-	.ucode_api_max = IWL5000_UCODE_API_MAX,
-	.ucode_api_min = IWL5000_UCODE_API_MIN,
-	.sku = IWL_SKU_A|IWL_SKU_G,
-	.valid_tx_ant = ANT_B,
-	.valid_rx_ant = ANT_AB,
-	.eeprom_ver = EEPROM_5000_EEPROM_VERSION,
-	.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
-	.ops = &iwl5000_ops,
-	.mod_params = &iwlagn_mod_params,
-	.base_params = &iwl5000_base_params,
+	IWL_DEVICE_5000,
+	.valid_tx_ant = ANT_B,		/* .cfg overwrite */
+	.valid_rx_ant = ANT_AB,		/* .cfg overwrite */
 };
 
 struct iwl_cfg iwl5100_agn_cfg = {
 	.name = "Intel(R) WiFi Link 5100 AGN",
-	.fw_name_pre = IWL5000_FW_PRE,
-	.ucode_api_max = IWL5000_UCODE_API_MAX,
-	.ucode_api_min = IWL5000_UCODE_API_MIN,
-	.sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
-	.valid_tx_ant = ANT_B,
-	.valid_rx_ant = ANT_AB,
-	.eeprom_ver = EEPROM_5000_EEPROM_VERSION,
-	.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
-	.ops = &iwl5000_ops,
-	.mod_params = &iwlagn_mod_params,
-	.base_params = &iwl5000_base_params,
+	IWL_DEVICE_5000,
+	.valid_tx_ant = ANT_B,		/* .cfg overwrite */
+	.valid_rx_ant = ANT_AB,		/* .cfg overwrite */
 	.ht_params = &iwl5000_ht_params,
 };
 
@@ -584,48 +565,39 @@ struct iwl_cfg iwl5350_agn_cfg = {
 	.fw_name_pre = IWL5000_FW_PRE,
 	.ucode_api_max = IWL5000_UCODE_API_MAX,
 	.ucode_api_min = IWL5000_UCODE_API_MIN,
-	.sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
-	.valid_tx_ant = ANT_ABC,
-	.valid_rx_ant = ANT_ABC,
 	.eeprom_ver = EEPROM_5050_EEPROM_VERSION,
 	.eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION,
 	.ops = &iwl5000_ops,
 	.mod_params = &iwlagn_mod_params,
 	.base_params = &iwl5000_base_params,
 	.ht_params = &iwl5000_ht_params,
+	.led_mode = IWL_LED_BLINK,
+	.internal_wimax_coex = true,
 };
 
+#define IWL_DEVICE_5150						\
+	.fw_name_pre = IWL5150_FW_PRE,				\
+	.ucode_api_max = IWL5150_UCODE_API_MAX,			\
+	.ucode_api_min = IWL5150_UCODE_API_MIN,			\
+	.eeprom_ver = EEPROM_5050_EEPROM_VERSION,		\
+	.eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION,	\
+	.ops = &iwl5150_ops,					\
+	.mod_params = &iwlagn_mod_params,			\
+	.base_params = &iwl5000_base_params,			\
+	.need_dc_calib = true,					\
+	.led_mode = IWL_LED_BLINK,				\
+	.internal_wimax_coex = true
+
 struct iwl_cfg iwl5150_agn_cfg = {
 	.name = "Intel(R) WiMAX/WiFi Link 5150 AGN",
-	.fw_name_pre = IWL5150_FW_PRE,
-	.ucode_api_max = IWL5150_UCODE_API_MAX,
-	.ucode_api_min = IWL5150_UCODE_API_MIN,
-	.sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
-	.valid_tx_ant = ANT_A,
-	.valid_rx_ant = ANT_AB,
-	.eeprom_ver = EEPROM_5050_EEPROM_VERSION,
-	.eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION,
-	.ops = &iwl5150_ops,
-	.mod_params = &iwlagn_mod_params,
-	.base_params = &iwl5000_base_params,
+	IWL_DEVICE_5150,
 	.ht_params = &iwl5000_ht_params,
-	.need_dc_calib = true,
+
 };
 
 struct iwl_cfg iwl5150_abg_cfg = {
 	.name = "Intel(R) WiMAX/WiFi Link 5150 ABG",
-	.fw_name_pre = IWL5150_FW_PRE,
-	.ucode_api_max = IWL5150_UCODE_API_MAX,
-	.ucode_api_min = IWL5150_UCODE_API_MIN,
-	.sku = IWL_SKU_A|IWL_SKU_G,
-	.valid_tx_ant = ANT_A,
-	.valid_rx_ant = ANT_AB,
-	.eeprom_ver = EEPROM_5050_EEPROM_VERSION,
-	.eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION,
-	.ops = &iwl5150_ops,
-	.mod_params = &iwlagn_mod_params,
-	.base_params = &iwl5000_base_params,
-	.need_dc_calib = true,
+	IWL_DEVICE_5150,
 };
 
 /*(DEBLOBBED)*/
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/iwlwifi/iwl-6000.c linux-libre-2.6.38-gnu1/drivers/net/wireless/iwlwifi/iwl-6000.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/iwlwifi/iwl-6000.c	2013-05-03 04:00:58.000000000 -0400
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/iwlwifi/iwl-6000.c	2013-05-03 02:01:23.000000000 -0400
@@ -53,13 +53,11 @@
 #define IWL6000_UCODE_API_MAX 4
 #define IWL6050_UCODE_API_MAX 5
 #define IWL6000G2_UCODE_API_MAX 5
-#define IWL130_UCODE_API_MAX 5
 
 /* Lowest firmware API version supported */
 #define IWL6000_UCODE_API_MIN 4
 #define IWL6050_UCODE_API_MIN 4
 #define IWL6000G2_UCODE_API_MIN 4
-#define IWL130_UCODE_API_MIN 5
 
 #define IWL6000_FW_PRE "/*(DEBLOBBED)*/"
 #define _IWL6000_MODULE_FIRMWARE(api) IWL6000_FW_PRE /*(DEBLOBBED)*/
@@ -77,10 +75,6 @@
 #define _IWL6000G2B_MODULE_FIRMWARE(api) IWL6000G2B_FW_PRE /*(DEBLOBBED)*/
 #define IWL6000G2B_MODULE_FIRMWARE(api) _IWL6000G2B_MODULE_FIRMWARE(api)
 
-#define IWL130_FW_PRE "/*(DEBLOBBED)*/"
-#define _IWL130_MODULE_FIRMWARE(api) IWL130_FW_PRE /*(DEBLOBBED)*/
-#define IWL130_MODULE_FIRMWARE(api) _IWL130_MODULE_FIRMWARE(api)
-
 static void iwl6000_set_ct_threshold(struct iwl_priv *priv)
 {
 	/* want Celsius */
@@ -188,7 +182,11 @@ static int iwl6000_hw_set_hw_params(stru
 	priv->hw_params.rx_wrt_ptr_reg = FH_RSCSR_CHNL0_WPTR;
 
 	priv->hw_params.tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant);
-	priv->hw_params.rx_chains_num = num_of_ant(priv->cfg->valid_rx_ant);
+	if (priv->cfg->rx_with_siso_diversity)
+		priv->hw_params.rx_chains_num = 1;
+	else
+		priv->hw_params.rx_chains_num =
+			num_of_ant(priv->cfg->valid_rx_ant);
 	priv->hw_params.valid_tx_ant = priv->cfg->valid_tx_ant;
 	priv->hw_params.valid_rx_ant = priv->cfg->valid_rx_ant;
 
@@ -328,14 +326,16 @@ static struct iwl_lib_ops iwl6000_lib =
 		.query_addr = iwlagn_eeprom_query_addr,
 		.update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower,
 	},
-	.post_associate = iwl_post_associate,
-	.isr = iwl_isr_ict,
-	.config_ap = iwl_config_ap,
+	.isr_ops = {
+		.isr = iwl_isr_ict,
+		.free = iwl_free_isr_ict,
+		.alloc = iwl_alloc_isr_ict,
+		.reset = iwl_reset_ict,
+		.disable = iwl_disable_ict,
+	},
 	.temp_ops = {
 		.temperature = iwlagn_temperature,
 	 },
-	.manage_ibss_station = iwlagn_manage_ibss_station,
-	.update_bcast_stations = iwl_update_bcast_stations,
 	.debugfs_ops = {
 		.rx_stats_read = iwl_ucode_rx_stats_read,
 		.tx_stats_read = iwl_ucode_tx_stats_read,
@@ -343,7 +343,6 @@ static struct iwl_lib_ops iwl6000_lib =
 		.bt_stats_read = iwl_ucode_bt_stats_read,
 		.reply_tx_error = iwl_reply_tx_error_read,
 	},
-	.recover_from_tx_stall = iwl_bg_monitor_recover,
 	.check_plcp_health = iwl_good_plcp_health,
 	.check_ack_health = iwl_good_ack_health,
 	.txfifo_flush = iwlagn_txfifo_flush,
@@ -399,14 +398,16 @@ static struct iwl_lib_ops iwl6000g2b_lib
 		.query_addr = iwlagn_eeprom_query_addr,
 		.update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower,
 	},
-	.post_associate = iwl_post_associate,
-	.isr = iwl_isr_ict,
-	.config_ap = iwl_config_ap,
+	.isr_ops = {
+		.isr = iwl_isr_ict,
+		.free = iwl_free_isr_ict,
+		.alloc = iwl_alloc_isr_ict,
+		.reset = iwl_reset_ict,
+		.disable = iwl_disable_ict,
+	},
 	.temp_ops = {
 		.temperature = iwlagn_temperature,
 	 },
-	.manage_ibss_station = iwlagn_manage_ibss_station,
-	.update_bcast_stations = iwl_update_bcast_stations,
 	.debugfs_ops = {
 		.rx_stats_read = iwl_ucode_rx_stats_read,
 		.tx_stats_read = iwl_ucode_tx_stats_read,
@@ -414,7 +415,6 @@ static struct iwl_lib_ops iwl6000g2b_lib
 		.bt_stats_read = iwl_ucode_bt_stats_read,
 		.reply_tx_error = iwl_reply_tx_error_read,
 	},
-	.recover_from_tx_stall = iwl_bg_monitor_recover,
 	.check_plcp_health = iwl_good_plcp_health,
 	.check_ack_health = iwl_good_ack_health,
 	.txfifo_flush = iwlagn_txfifo_flush,
@@ -439,6 +439,7 @@ static const struct iwl_ops iwl6000_ops
 	.hcmd = &iwlagn_hcmd,
 	.utils = &iwlagn_hcmd_utils,
 	.led = &iwlagn_led_ops,
+	.ieee80211_ops = &iwlagn_hw_ops,
 };
 
 static const struct iwl_ops iwl6050_ops = {
@@ -447,6 +448,7 @@ static const struct iwl_ops iwl6050_ops
 	.utils = &iwlagn_hcmd_utils,
 	.led = &iwlagn_led_ops,
 	.nic = &iwl6050_nic_ops,
+	.ieee80211_ops = &iwlagn_hw_ops,
 };
 
 static const struct iwl_ops iwl6050g2_ops = {
@@ -455,6 +457,7 @@ static const struct iwl_ops iwl6050g2_op
 	.utils = &iwlagn_hcmd_utils,
 	.led = &iwlagn_led_ops,
 	.nic = &iwl6050g2_nic_ops,
+	.ieee80211_ops = &iwlagn_hw_ops,
 };
 
 static const struct iwl_ops iwl6000g2b_ops = {
@@ -462,6 +465,7 @@ static const struct iwl_ops iwl6000g2b_o
 	.hcmd = &iwlagn_bt_hcmd,
 	.utils = &iwlagn_hcmd_utils,
 	.led = &iwlagn_led_ops,
+	.ieee80211_ops = &iwlagn_hw_ops,
 };
 
 static struct iwl_base_params iwl6000_base_params = {
@@ -480,11 +484,12 @@ static struct iwl_base_params iwl6000_ba
 	.support_ct_kill_exit = true,
 	.plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
 	.chain_noise_scale = 1000,
-	.monitor_recover_period = IWL_DEF_MONITORING_PERIOD,
+	.wd_timeout = IWL_DEF_WD_TIMEOUT,
 	.max_event_log_size = 512,
 	.ucode_tracing = true,
 	.sensitivity_calib_by_driver = true,
 	.chain_noise_calib_by_driver = true,
+	.shadow_reg_enable = true,
 };
 
 static struct iwl_base_params iwl6050_base_params = {
@@ -503,13 +508,14 @@ static struct iwl_base_params iwl6050_ba
 	.support_ct_kill_exit = true,
 	.plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
 	.chain_noise_scale = 1500,
-	.monitor_recover_period = IWL_DEF_MONITORING_PERIOD,
+	.wd_timeout = IWL_DEF_WD_TIMEOUT,
 	.max_event_log_size = 1024,
 	.ucode_tracing = true,
 	.sensitivity_calib_by_driver = true,
 	.chain_noise_calib_by_driver = true,
+	.shadow_reg_enable = true,
 };
-static struct iwl_base_params iwl6000_coex_base_params = {
+static struct iwl_base_params iwl6000_g2_base_params = {
 	.eeprom_size = OTP_LOW_IMAGE_SIZE,
 	.num_of_queues = IWLAGN_NUM_QUEUES,
 	.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
@@ -518,18 +524,19 @@ static struct iwl_base_params iwl6000_co
 	.use_bsm = false,
 	.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
 	.shadow_ram_support = true,
-	.led_compensation = 51,
+	.led_compensation = 57,
 	.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
 	.supports_idle = true,
 	.adv_thermal_throttle = true,
 	.support_ct_kill_exit = true,
 	.plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
 	.chain_noise_scale = 1000,
-	.monitor_recover_period = IWL_LONG_MONITORING_PERIOD,
+	.wd_timeout = IWL_LONG_WD_TIMEOUT,
 	.max_event_log_size = 512,
 	.ucode_tracing = true,
 	.sensitivity_calib_by_driver = true,
 	.chain_noise_calib_by_driver = true,
+	.shadow_reg_enable = true,
 };
 
 static struct iwl_ht_params iwl6000_ht_params = {
@@ -541,271 +548,166 @@ static struct iwl_bt_params iwl6000_bt_p
 	.bt_statistics = true,
 	/* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */
 	.advanced_bt_coexist = true,
+	.agg_time_limit = BT_AGG_THRESHOLD_DEF,
 	.bt_init_traffic_load = IWL_BT_COEX_TRAFFIC_LOAD_NONE,
 	.bt_prio_boost = IWLAGN_BT_PRIO_BOOST_DEFAULT,
+	.bt_sco_disable = true,
 };
 
-struct iwl_cfg iwl6000g2a_2agn_cfg = {
-	.name = "6000 Series 2x2 AGN Gen2a",
-	.fw_name_pre = IWL6000G2A_FW_PRE,
-	.ucode_api_max = IWL6000G2_UCODE_API_MAX,
-	.ucode_api_min = IWL6000G2_UCODE_API_MIN,
-	.sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
-	.valid_tx_ant = ANT_AB,
-	.valid_rx_ant = ANT_AB,
-	.eeprom_ver = EEPROM_6000G2_EEPROM_VERSION,
-	.eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION,
-	.ops = &iwl6000_ops,
-	.mod_params = &iwlagn_mod_params,
-	.base_params = &iwl6000_base_params,
+#define IWL_DEVICE_6005						\
+	.fw_name_pre = IWL6000G2A_FW_PRE,			\
+	.ucode_api_max = IWL6000G2_UCODE_API_MAX,		\
+	.ucode_api_min = IWL6000G2_UCODE_API_MIN,		\
+	.eeprom_ver = EEPROM_6000G2_EEPROM_VERSION,		\
+	.eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION,	\
+	.ops = &iwl6000_ops,					\
+	.mod_params = &iwlagn_mod_params,			\
+	.base_params = &iwl6000_g2_base_params,			\
+	.need_dc_calib = true,					\
+	.need_temp_offset_calib = true,				\
+	.led_mode = IWL_LED_RF_STATE
+
+struct iwl_cfg iwl6005_2agn_cfg = {
+	.name = "Intel(R) Centrino(R) Advanced-N 6205 AGN",
+	IWL_DEVICE_6005,
 	.ht_params = &iwl6000_ht_params,
-	.need_dc_calib = true,
-	.need_temp_offset_calib = true,
-	.use_new_eeprom_reading = true,
 };
 
-struct iwl_cfg iwl6000g2a_2abg_cfg = {
-	.name = "6000 Series 2x2 ABG Gen2a",
-	.fw_name_pre = IWL6000G2A_FW_PRE,
-	.ucode_api_max = IWL6000G2_UCODE_API_MAX,
-	.ucode_api_min = IWL6000G2_UCODE_API_MIN,
-	.sku = IWL_SKU_A|IWL_SKU_G,
-	.valid_tx_ant = ANT_AB,
-	.valid_rx_ant = ANT_AB,
-	.eeprom_ver = EEPROM_6000G2_EEPROM_VERSION,
-	.eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION,
-	.ops = &iwl6000_ops,
-	.mod_params = &iwlagn_mod_params,
-	.base_params = &iwl6000_base_params,
-	.need_dc_calib = true,
-	.need_temp_offset_calib = true,
-	.use_new_eeprom_reading = true,
+struct iwl_cfg iwl6005_2abg_cfg = {
+	.name = "Intel(R) Centrino(R) Advanced-N 6205 ABG",
+	IWL_DEVICE_6005,
 };
 
-struct iwl_cfg iwl6000g2a_2bg_cfg = {
-	.name = "6000 Series 2x2 BG Gen2a",
-	.fw_name_pre = IWL6000G2A_FW_PRE,
-	.ucode_api_max = IWL6000G2_UCODE_API_MAX,
-	.ucode_api_min = IWL6000G2_UCODE_API_MIN,
-	.sku = IWL_SKU_G,
-	.valid_tx_ant = ANT_AB,
-	.valid_rx_ant = ANT_AB,
-	.eeprom_ver = EEPROM_6000G2_EEPROM_VERSION,
-	.eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION,
-	.ops = &iwl6000_ops,
-	.mod_params = &iwlagn_mod_params,
-	.base_params = &iwl6000_base_params,
-	.need_dc_calib = true,
-	.need_temp_offset_calib = true,
-	.use_new_eeprom_reading = true,
+struct iwl_cfg iwl6005_2bg_cfg = {
+	.name = "Intel(R) Centrino(R) Advanced-N 6205 BG",
+	IWL_DEVICE_6005,
 };
 
-struct iwl_cfg iwl6000g2b_2agn_cfg = {
-	.name = "6000 Series 2x2 AGN Gen2b",
-	.fw_name_pre = IWL6000G2B_FW_PRE,
-	.ucode_api_max = IWL6000G2_UCODE_API_MAX,
-	.ucode_api_min = IWL6000G2_UCODE_API_MIN,
-	.sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
-	.valid_tx_ant = ANT_AB,
-	.valid_rx_ant = ANT_AB,
-	.eeprom_ver = EEPROM_6000G2_EEPROM_VERSION,
-	.eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION,
-	.ops = &iwl6000g2b_ops,
-	.mod_params = &iwlagn_mod_params,
-	.base_params = &iwl6000_coex_base_params,
-	.bt_params = &iwl6000_bt_params,
+#define IWL_DEVICE_6030						\
+	.fw_name_pre = IWL6000G2B_FW_PRE,			\
+	.ucode_api_max = IWL6000G2_UCODE_API_MAX,		\
+	.ucode_api_min = IWL6000G2_UCODE_API_MIN,		\
+	.eeprom_ver = EEPROM_6000G2_EEPROM_VERSION,		\
+	.eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION,	\
+	.ops = &iwl6000g2b_ops,					\
+	.mod_params = &iwlagn_mod_params,			\
+	.base_params = &iwl6000_g2_base_params,			\
+	.bt_params = &iwl6000_bt_params,			\
+	.need_dc_calib = true,					\
+	.need_temp_offset_calib = true,				\
+	.led_mode = IWL_LED_RF_STATE,				\
+	.adv_pm = true						\
+
+struct iwl_cfg iwl6030_2agn_cfg = {
+	.name = "Intel(R) Centrino(R) Advanced-N 6230 AGN",
+	IWL_DEVICE_6030,
 	.ht_params = &iwl6000_ht_params,
-	.need_dc_calib = true,
-	.need_temp_offset_calib = true,
-	/* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */
-	.scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A,
-	.use_new_eeprom_reading = true,
 };
 
-struct iwl_cfg iwl6000g2b_2abg_cfg = {
-	.name = "6000 Series 2x2 ABG Gen2b",
-	.fw_name_pre = IWL6000G2B_FW_PRE,
-	.ucode_api_max = IWL6000G2_UCODE_API_MAX,
-	.ucode_api_min = IWL6000G2_UCODE_API_MIN,
-	.sku = IWL_SKU_A|IWL_SKU_G,
-	.valid_tx_ant = ANT_AB,
-	.valid_rx_ant = ANT_AB,
-	.eeprom_ver = EEPROM_6000G2_EEPROM_VERSION,
-	.eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION,
-	.ops = &iwl6000g2b_ops,
-	.mod_params = &iwlagn_mod_params,
-	.base_params = &iwl6000_coex_base_params,
-	.bt_params = &iwl6000_bt_params,
-	.need_dc_calib = true,
-	.need_temp_offset_calib = true,
-	/* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */
-	.scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A,
-	.use_new_eeprom_reading = true,
+struct iwl_cfg iwl6030_2abg_cfg = {
+	.name = "Intel(R) Centrino(R) Advanced-N 6230 ABG",
+	IWL_DEVICE_6030,
 };
 
-struct iwl_cfg iwl6000g2b_2bgn_cfg = {
-	.name = "6000 Series 2x2 BGN Gen2b",
-	.fw_name_pre = IWL6000G2B_FW_PRE,
-	.ucode_api_max = IWL6000G2_UCODE_API_MAX,
-	.ucode_api_min = IWL6000G2_UCODE_API_MIN,
-	.sku = IWL_SKU_G|IWL_SKU_N,
-	.valid_tx_ant = ANT_AB,
-	.valid_rx_ant = ANT_AB,
-	.eeprom_ver = EEPROM_6000G2_EEPROM_VERSION,
-	.eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION,
-	.ops = &iwl6000g2b_ops,
-	.mod_params = &iwlagn_mod_params,
-	.base_params = &iwl6000_coex_base_params,
-	.bt_params = &iwl6000_bt_params,
+struct iwl_cfg iwl6030_2bgn_cfg = {
+	.name = "Intel(R) Centrino(R) Advanced-N 6230 BGN",
+	IWL_DEVICE_6030,
 	.ht_params = &iwl6000_ht_params,
-	.need_dc_calib = true,
-	.need_temp_offset_calib = true,
-	/* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */
-	.scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A,
-	.use_new_eeprom_reading = true,
 };
 
-struct iwl_cfg iwl6000g2b_2bg_cfg = {
-	.name = "6000 Series 2x2 BG Gen2b",
-	.fw_name_pre = IWL6000G2B_FW_PRE,
-	.ucode_api_max = IWL6000G2_UCODE_API_MAX,
-	.ucode_api_min = IWL6000G2_UCODE_API_MIN,
-	.sku = IWL_SKU_G,
-	.valid_tx_ant = ANT_AB,
-	.valid_rx_ant = ANT_AB,
-	.eeprom_ver = EEPROM_6000G2_EEPROM_VERSION,
-	.eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION,
-	.ops = &iwl6000g2b_ops,
-	.mod_params = &iwlagn_mod_params,
-	.base_params = &iwl6000_coex_base_params,
-	.bt_params = &iwl6000_bt_params,
-	.need_dc_calib = true,
-	.need_temp_offset_calib = true,
-	/* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */
-	.scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A,
-	.use_new_eeprom_reading = true,
+struct iwl_cfg iwl6030_2bg_cfg = {
+	.name = "Intel(R) Centrino(R) Advanced-N 6230 BG",
+	IWL_DEVICE_6030,
 };
 
-struct iwl_cfg iwl6000g2b_bgn_cfg = {
-	.name = "6000 Series 1x2 BGN Gen2b",
-	.fw_name_pre = IWL6000G2B_FW_PRE,
-	.ucode_api_max = IWL6000G2_UCODE_API_MAX,
-	.ucode_api_min = IWL6000G2_UCODE_API_MIN,
-	.sku = IWL_SKU_G|IWL_SKU_N,
-	.valid_tx_ant = ANT_A,
-	.valid_rx_ant = ANT_AB,
-	.eeprom_ver = EEPROM_6000G2_EEPROM_VERSION,
-	.eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION,
-	.ops = &iwl6000g2b_ops,
-	.mod_params = &iwlagn_mod_params,
-	.base_params = &iwl6000_coex_base_params,
-	.bt_params = &iwl6000_bt_params,
+struct iwl_cfg iwl1030_bgn_cfg = {
+	.name = "Intel(R) Centrino(R) Wireless-N 1030 BGN",
+	IWL_DEVICE_6030,
 	.ht_params = &iwl6000_ht_params,
-	.need_dc_calib = true,
-	.need_temp_offset_calib = true,
-	/* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */
-	.scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A,
-	.use_new_eeprom_reading = true,
 };
 
-struct iwl_cfg iwl6000g2b_bg_cfg = {
-	.name = "6000 Series 1x2 BG Gen2b",
-	.fw_name_pre = IWL6000G2B_FW_PRE,
-	.ucode_api_max = IWL6000G2_UCODE_API_MAX,
-	.ucode_api_min = IWL6000G2_UCODE_API_MIN,
-	.sku = IWL_SKU_G,
-	.valid_tx_ant = ANT_A,
-	.valid_rx_ant = ANT_AB,
-	.eeprom_ver = EEPROM_6000G2_EEPROM_VERSION,
-	.eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION,
-	.ops = &iwl6000g2b_ops,
-	.mod_params = &iwlagn_mod_params,
-	.base_params = &iwl6000_coex_base_params,
-	.bt_params = &iwl6000_bt_params,
-	.need_dc_calib = true,
-	.need_temp_offset_calib = true,
-	/* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */
-	.scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A,
-	.use_new_eeprom_reading = true,
+struct iwl_cfg iwl1030_bg_cfg = {
+	.name = "Intel(R) Centrino(R) Wireless-N 1030 BG",
+	IWL_DEVICE_6030,
+};
+
+struct iwl_cfg iwl130_bgn_cfg = {
+	.name = "Intel(R) Centrino(R) Wireless-N 130 BGN",
+	IWL_DEVICE_6030,
+	.ht_params = &iwl6000_ht_params,
+	.rx_with_siso_diversity = true,
+};
+
+struct iwl_cfg iwl130_bg_cfg = {
+	.name = "Intel(R) Centrino(R) Wireless-N 130 BG",
+	IWL_DEVICE_6030,
+	.rx_with_siso_diversity = true,
 };
 
 /*
  * "i": Internal configuration, use internal Power Amplifier
  */
+#define IWL_DEVICE_6000i					\
+	.fw_name_pre = IWL6000_FW_PRE,				\
+	.ucode_api_max = IWL6000_UCODE_API_MAX,			\
+	.ucode_api_min = IWL6000_UCODE_API_MIN,			\
+	.valid_tx_ant = ANT_BC,		/* .cfg overwrite */	\
+	.valid_rx_ant = ANT_BC,		/* .cfg overwrite */	\
+	.eeprom_ver = EEPROM_6000_EEPROM_VERSION,		\
+	.eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION,	\
+	.ops = &iwl6000_ops,					\
+	.mod_params = &iwlagn_mod_params,			\
+	.base_params = &iwl6000_base_params,			\
+	.pa_type = IWL_PA_INTERNAL,				\
+	.led_mode = IWL_LED_BLINK
+
 struct iwl_cfg iwl6000i_2agn_cfg = {
 	.name = "Intel(R) Centrino(R) Advanced-N 6200 AGN",
-	.fw_name_pre = IWL6000_FW_PRE,
-	.ucode_api_max = IWL6000_UCODE_API_MAX,
-	.ucode_api_min = IWL6000_UCODE_API_MIN,
-	.sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
-	.valid_tx_ant = ANT_BC,
-	.valid_rx_ant = ANT_BC,
-	.eeprom_ver = EEPROM_6000_EEPROM_VERSION,
-	.eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION,
-	.ops = &iwl6000_ops,
-	.mod_params = &iwlagn_mod_params,
-	.base_params = &iwl6000_base_params,
+	IWL_DEVICE_6000i,
 	.ht_params = &iwl6000_ht_params,
-	.pa_type = IWL_PA_INTERNAL,
 };
 
 struct iwl_cfg iwl6000i_2abg_cfg = {
 	.name = "Intel(R) Centrino(R) Advanced-N 6200 ABG",
-	.fw_name_pre = IWL6000_FW_PRE,
-	.ucode_api_max = IWL6000_UCODE_API_MAX,
-	.ucode_api_min = IWL6000_UCODE_API_MIN,
-	.sku = IWL_SKU_A|IWL_SKU_G,
-	.valid_tx_ant = ANT_BC,
-	.valid_rx_ant = ANT_BC,
-	.eeprom_ver = EEPROM_6000_EEPROM_VERSION,
-	.eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION,
-	.ops = &iwl6000_ops,
-	.mod_params = &iwlagn_mod_params,
-	.base_params = &iwl6000_base_params,
-	.pa_type = IWL_PA_INTERNAL,
+	IWL_DEVICE_6000i,
 };
 
 struct iwl_cfg iwl6000i_2bg_cfg = {
 	.name = "Intel(R) Centrino(R) Advanced-N 6200 BG",
-	.fw_name_pre = IWL6000_FW_PRE,
-	.ucode_api_max = IWL6000_UCODE_API_MAX,
-	.ucode_api_min = IWL6000_UCODE_API_MIN,
-	.sku = IWL_SKU_G,
-	.valid_tx_ant = ANT_BC,
-	.valid_rx_ant = ANT_BC,
-	.eeprom_ver = EEPROM_6000_EEPROM_VERSION,
-	.eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION,
-	.ops = &iwl6000_ops,
-	.mod_params = &iwlagn_mod_params,
-	.base_params = &iwl6000_base_params,
-	.pa_type = IWL_PA_INTERNAL,
+	IWL_DEVICE_6000i,
 };
 
+#define IWL_DEVICE_6050						\
+	.fw_name_pre = IWL6050_FW_PRE,				\
+	.ucode_api_max = IWL6050_UCODE_API_MAX,			\
+	.ucode_api_min = IWL6050_UCODE_API_MIN,			\
+	.valid_tx_ant = ANT_AB,		/* .cfg overwrite */	\
+	.valid_rx_ant = ANT_AB,		/* .cfg overwrite */	\
+	.ops = &iwl6050_ops,					\
+	.eeprom_ver = EEPROM_6050_EEPROM_VERSION,		\
+	.eeprom_calib_ver = EEPROM_6050_TX_POWER_VERSION,	\
+	.mod_params = &iwlagn_mod_params,			\
+	.base_params = &iwl6050_base_params,			\
+	.need_dc_calib = true,					\
+	.led_mode = IWL_LED_BLINK,				\
+	.internal_wimax_coex = true
+
 struct iwl_cfg iwl6050_2agn_cfg = {
 	.name = "Intel(R) Centrino(R) Advanced-N + WiMAX 6250 AGN",
-	.fw_name_pre = IWL6050_FW_PRE,
-	.ucode_api_max = IWL6050_UCODE_API_MAX,
-	.ucode_api_min = IWL6050_UCODE_API_MIN,
-	.sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
-	.valid_tx_ant = ANT_AB,
-	.valid_rx_ant = ANT_AB,
-	.ops = &iwl6050_ops,
-	.eeprom_ver = EEPROM_6050_EEPROM_VERSION,
-	.eeprom_calib_ver = EEPROM_6050_TX_POWER_VERSION,
-	.mod_params = &iwlagn_mod_params,
-	.base_params = &iwl6050_base_params,
+	IWL_DEVICE_6050,
 	.ht_params = &iwl6000_ht_params,
-	.need_dc_calib = true,
 };
 
-struct iwl_cfg iwl6050g2_bgn_cfg = {
-	.name = "6050 Series 1x2 BGN Gen2",
+struct iwl_cfg iwl6050_2abg_cfg = {
+	.name = "Intel(R) Centrino(R) Advanced-N + WiMAX 6250 ABG",
+	IWL_DEVICE_6050,
+};
+
+struct iwl_cfg iwl6150_bgn_cfg = {
+	.name = "Intel(R) Centrino(R) Wireless-N + WiMAX 6150 BGN",
 	.fw_name_pre = IWL6050_FW_PRE,
 	.ucode_api_max = IWL6050_UCODE_API_MAX,
 	.ucode_api_min = IWL6050_UCODE_API_MIN,
-	.sku = IWL_SKU_G|IWL_SKU_N,
-	.valid_tx_ant = ANT_A,
-	.valid_rx_ant = ANT_AB,
 	.eeprom_ver = EEPROM_6050G2_EEPROM_VERSION,
 	.eeprom_calib_ver = EEPROM_6050G2_TX_POWER_VERSION,
 	.ops = &iwl6050g2_ops,
@@ -813,23 +715,8 @@ struct iwl_cfg iwl6050g2_bgn_cfg = {
 	.base_params = &iwl6050_base_params,
 	.ht_params = &iwl6000_ht_params,
 	.need_dc_calib = true,
-	.use_new_eeprom_reading = true,
-};
-
-struct iwl_cfg iwl6050_2abg_cfg = {
-	.name = "Intel(R) Centrino(R) Advanced-N + WiMAX 6250 ABG",
-	.fw_name_pre = IWL6050_FW_PRE,
-	.ucode_api_max = IWL6050_UCODE_API_MAX,
-	.ucode_api_min = IWL6050_UCODE_API_MIN,
-	.sku = IWL_SKU_A|IWL_SKU_G,
-	.valid_tx_ant = ANT_AB,
-	.valid_rx_ant = ANT_AB,
-	.eeprom_ver = EEPROM_6050_EEPROM_VERSION,
-	.eeprom_calib_ver = EEPROM_6050_TX_POWER_VERSION,
-	.ops = &iwl6050_ops,
-	.mod_params = &iwlagn_mod_params,
-	.base_params = &iwl6050_base_params,
-	.need_dc_calib = true,
+	.led_mode = IWL_LED_RF_STATE,
+	.internal_wimax_coex = true,
 };
 
 struct iwl_cfg iwl6000_3agn_cfg = {
@@ -837,9 +724,6 @@ struct iwl_cfg iwl6000_3agn_cfg = {
 	.fw_name_pre = IWL6000_FW_PRE,
 	.ucode_api_max = IWL6000_UCODE_API_MAX,
 	.ucode_api_min = IWL6000_UCODE_API_MIN,
-	.sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
-	.valid_tx_ant = ANT_ABC,
-	.valid_rx_ant = ANT_ABC,
 	.eeprom_ver = EEPROM_6000_EEPROM_VERSION,
 	.eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION,
 	.ops = &iwl6000_ops,
@@ -847,47 +731,7 @@ struct iwl_cfg iwl6000_3agn_cfg = {
 	.base_params = &iwl6000_base_params,
 	.ht_params = &iwl6000_ht_params,
 	.need_dc_calib = true,
-};
-
-struct iwl_cfg iwl130_bgn_cfg = {
-	.name = "Intel(R) 130 Series 1x1 BGN",
-	.fw_name_pre = IWL6000G2B_FW_PRE,
-	.ucode_api_max = IWL130_UCODE_API_MAX,
-	.ucode_api_min = IWL130_UCODE_API_MIN,
-	.sku = IWL_SKU_G|IWL_SKU_N,
-	.valid_tx_ant = ANT_A,
-	.valid_rx_ant = ANT_A,
-	.eeprom_ver = EEPROM_6000G2_EEPROM_VERSION,
-	.eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION,
-	.ops = &iwl6000g2b_ops,
-	.mod_params = &iwlagn_mod_params,
-	.base_params = &iwl6000_coex_base_params,
-	.bt_params = &iwl6000_bt_params,
-	.ht_params = &iwl6000_ht_params,
-	.need_dc_calib = true,
-	/* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */
-	.scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A,
-	.use_new_eeprom_reading = true,
-};
-
-struct iwl_cfg iwl130_bg_cfg = {
-	.name = "Intel(R) 130 Series 1x2 BG",
-	.fw_name_pre = IWL6000G2B_FW_PRE,
-	.ucode_api_max = IWL130_UCODE_API_MAX,
-	.ucode_api_min = IWL130_UCODE_API_MIN,
-	.sku = IWL_SKU_G,
-	.valid_tx_ant = ANT_A,
-	.valid_rx_ant = ANT_A,
-	.eeprom_ver = EEPROM_6000G2_EEPROM_VERSION,
-	.eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION,
-	.ops = &iwl6000g2b_ops,
-	.mod_params = &iwlagn_mod_params,
-	.base_params = &iwl6000_coex_base_params,
-	.bt_params = &iwl6000_bt_params,
-	.need_dc_calib = true,
-	/* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */
-	.scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A,
-	.use_new_eeprom_reading = true,
+	.led_mode = IWL_LED_BLINK,
 };
 
 /*(DEBLOBBED)*/
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/iwlwifi/iwl-agn.c linux-libre-2.6.38-gnu1/drivers/net/wireless/iwlwifi/iwl-agn.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/iwlwifi/iwl-agn.c	2013-05-03 04:00:50.000000000 -0400
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/iwlwifi/iwl-agn.c	2013-05-03 02:01:14.000000000 -0400
@@ -90,170 +90,6 @@ MODULE_ALIAS("iwl4965");
 static int iwlagn_ant_coupling;
 static bool iwlagn_bt_ch_announce = 1;
 
-/**
- * iwlagn_commit_rxon - commit staging_rxon to hardware
- *
- * The RXON command in staging_rxon is committed to the hardware and
- * the active_rxon structure is updated with the new data.  This
- * function correctly transitions out of the RXON_ASSOC_MSK state if
- * a HW tune is required based on the RXON structure changes.
- */
-int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
-{
-	/* cast away the const for active_rxon in this function */
-	struct iwl_rxon_cmd *active_rxon = (void *)&ctx->active;
-	int ret;
-	bool new_assoc =
-		!!(ctx->staging.filter_flags & RXON_FILTER_ASSOC_MSK);
-	bool old_assoc = !!(ctx->active.filter_flags & RXON_FILTER_ASSOC_MSK);
-
-	if (!iwl_is_alive(priv))
-		return -EBUSY;
-
-	if (!ctx->is_active)
-		return 0;
-
-	/* always get timestamp with Rx frame */
-	ctx->staging.flags |= RXON_FLG_TSF2HOST_MSK;
-
-	ret = iwl_check_rxon_cmd(priv, ctx);
-	if (ret) {
-		IWL_ERR(priv, "Invalid RXON configuration.  Not committing.\n");
-		return -EINVAL;
-	}
-
-	/*
-	 * receive commit_rxon request
-	 * abort any previous channel switch if still in process
-	 */
-	if (priv->switch_rxon.switch_in_progress &&
-	    (priv->switch_rxon.channel != ctx->staging.channel)) {
-		IWL_DEBUG_11H(priv, "abort channel switch on %d\n",
-		      le16_to_cpu(priv->switch_rxon.channel));
-		iwl_chswitch_done(priv, false);
-	}
-
-	/* If we don't need to send a full RXON, we can use
-	 * iwl_rxon_assoc_cmd which is used to reconfigure filter
-	 * and other flags for the current radio configuration. */
-	if (!iwl_full_rxon_required(priv, ctx)) {
-		ret = iwl_send_rxon_assoc(priv, ctx);
-		if (ret) {
-			IWL_ERR(priv, "Error setting RXON_ASSOC (%d)\n", ret);
-			return ret;
-		}
-
-		memcpy(active_rxon, &ctx->staging, sizeof(*active_rxon));
-		iwl_print_rx_config_cmd(priv, ctx);
-		return 0;
-	}
-
-	/* If we are currently associated and the new config requires
-	 * an RXON_ASSOC and the new config wants the associated mask enabled,
-	 * we must clear the associated from the active configuration
-	 * before we apply the new config */
-	if (iwl_is_associated_ctx(ctx) && new_assoc) {
-		IWL_DEBUG_INFO(priv, "Toggling associated bit on current RXON\n");
-		active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
-
-		ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd,
-				       sizeof(struct iwl_rxon_cmd),
-				       active_rxon);
-
-		/* If the mask clearing failed then we set
-		 * active_rxon back to what it was previously */
-		if (ret) {
-			active_rxon->filter_flags |= RXON_FILTER_ASSOC_MSK;
-			IWL_ERR(priv, "Error clearing ASSOC_MSK (%d)\n", ret);
-			return ret;
-		}
-		iwl_clear_ucode_stations(priv, ctx);
-		iwl_restore_stations(priv, ctx);
-		ret = iwl_restore_default_wep_keys(priv, ctx);
-		if (ret) {
-			IWL_ERR(priv, "Failed to restore WEP keys (%d)\n", ret);
-			return ret;
-		}
-	}
-
-	IWL_DEBUG_INFO(priv, "Sending RXON\n"
-		       "* with%s RXON_FILTER_ASSOC_MSK\n"
-		       "* channel = %d\n"
-		       "* bssid = %pM\n",
-		       (new_assoc ? "" : "out"),
-		       le16_to_cpu(ctx->staging.channel),
-		       ctx->staging.bssid_addr);
-
-	iwl_set_rxon_hwcrypto(priv, ctx, !priv->cfg->mod_params->sw_crypto);
-
-	if (!old_assoc) {
-		/*
-		 * First of all, before setting associated, we need to
-		 * send RXON timing so the device knows about the DTIM
-		 * period and other timing values
-		 */
-		ret = iwl_send_rxon_timing(priv, ctx);
-		if (ret) {
-			IWL_ERR(priv, "Error setting RXON timing!\n");
-			return ret;
-		}
-	}
-
-	if (priv->cfg->ops->hcmd->set_pan_params) {
-		ret = priv->cfg->ops->hcmd->set_pan_params(priv);
-		if (ret)
-			return ret;
-	}
-
-	/* Apply the new configuration
-	 * RXON unassoc clears the station table in uCode so restoration of
-	 * stations is needed after it (the RXON command) completes
-	 */
-	if (!new_assoc) {
-		ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd,
-			      sizeof(struct iwl_rxon_cmd), &ctx->staging);
-		if (ret) {
-			IWL_ERR(priv, "Error setting new RXON (%d)\n", ret);
-			return ret;
-		}
-		IWL_DEBUG_INFO(priv, "Return from !new_assoc RXON.\n");
-		memcpy(active_rxon, &ctx->staging, sizeof(*active_rxon));
-		iwl_clear_ucode_stations(priv, ctx);
-		iwl_restore_stations(priv, ctx);
-		ret = iwl_restore_default_wep_keys(priv, ctx);
-		if (ret) {
-			IWL_ERR(priv, "Failed to restore WEP keys (%d)\n", ret);
-			return ret;
-		}
-	}
-	if (new_assoc) {
-		priv->start_calib = 0;
-		/* Apply the new configuration
-		 * RXON assoc doesn't clear the station table in uCode,
-		 */
-		ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd,
-			      sizeof(struct iwl_rxon_cmd), &ctx->staging);
-		if (ret) {
-			IWL_ERR(priv, "Error setting new RXON (%d)\n", ret);
-			return ret;
-		}
-		memcpy(active_rxon, &ctx->staging, sizeof(*active_rxon));
-	}
-	iwl_print_rx_config_cmd(priv, ctx);
-
-	iwl_init_sensitivity(priv);
-
-	/* If we issue a new RXON command which required a tune then we must
-	 * send a new TXPOWER command or we won't be able to Tx any frames */
-	ret = iwl_set_tx_power(priv, priv->tx_power_user_lmt, true);
-	if (ret) {
-		IWL_ERR(priv, "Error sending TX power (%d)\n", ret);
-		return ret;
-	}
-
-	return 0;
-}
-
 void iwl_update_chain_flags(struct iwl_priv *priv)
 {
 	struct iwl_rxon_context *ctx;
@@ -261,7 +97,8 @@ void iwl_update_chain_flags(struct iwl_p
 	if (priv->cfg->ops->hcmd->set_rxon_chain) {
 		for_each_context(priv, ctx) {
 			priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
-			iwlcore_commit_rxon(priv, ctx);
+			if (ctx->active.rx_chain != ctx->staging.rx_chain)
+				iwlcore_commit_rxon(priv, ctx);
 		}
 	}
 }
@@ -411,7 +248,8 @@ static unsigned int iwl_hw_get_beacon_cm
 
 	return sizeof(*tx_beacon_cmd) + frame_size;
 }
-static int iwl_send_beacon_cmd(struct iwl_priv *priv)
+
+int iwlagn_send_beacon_cmd(struct iwl_priv *priv)
 {
 	struct iwl_frame *frame;
 	unsigned int frame_size;
@@ -661,7 +499,7 @@ static void iwl_bg_beacon_update(struct
 
 	priv->beacon_skb = beacon;
 
-	iwl_send_beacon_cmd(priv);
+	iwlagn_send_beacon_cmd(priv);
  out:
 	mutex_unlock(&priv->mutex);
 }
@@ -1316,9 +1154,12 @@ static void iwl_irq_tasklet_legacy(struc
 	}
 
 	/* Re-enable all interrupts */
-	/* only Re-enable if diabled by irq */
+	/* only Re-enable if disabled by irq */
 	if (test_bit(STATUS_INT_ENABLED, &priv->status))
 		iwl_enable_interrupts(priv);
+	/* Re-enable RF_KILL if it occurred */
+	else if (handled & CSR_INT_BIT_RF_KILL)
+		iwl_enable_rfkill_int(priv);
 
 #ifdef CONFIG_IWLWIFI_DEBUG
 	if (iwl_get_debug_level(priv) & (IWL_DL_ISR)) {
@@ -1530,9 +1371,12 @@ static void iwl_irq_tasklet(struct iwl_p
 	}
 
 	/* Re-enable all interrupts */
-	/* only Re-enable if diabled by irq */
+	/* only Re-enable if disabled by irq */
 	if (test_bit(STATUS_INT_ENABLED, &priv->status))
 		iwl_enable_interrupts(priv);
+	/* Re-enable RF_KILL if it occurred */
+	else if (handled & CSR_INT_BIT_RF_KILL)
+		iwl_enable_rfkill_int(priv);
 }
 
 /* the threshold ratio of actual_ack_cnt to expected_ack_cnt in percent */
@@ -2664,7 +2508,7 @@ int iwl_dump_nic_event_log(struct iwl_pr
 		return pos;
 	}
 
-	/* enable/disable bt channel announcement */
+	/* enable/disable bt channel inhibition */
 	priv->bt_ch_announce = iwlagn_bt_ch_announce;
 
 #ifdef CONFIG_IWLWIFI_DEBUG
@@ -2816,13 +2660,8 @@ static void iwl_alive_start(struct iwl_p
 	/* After the ALIVE response, we can send host commands to the uCode */
 	set_bit(STATUS_ALIVE, &priv->status);
 
-	if (priv->cfg->ops->lib->recover_from_tx_stall) {
-		/* Enable timer to monitor the driver queues */
-		mod_timer(&priv->monitor_recover,
-			jiffies +
-			msecs_to_jiffies(
-			  priv->cfg->base_params->monitor_recover_period));
-	}
+	/* Enable watchdog to monitor the driver tx queues */
+	iwl_setup_watchdog(priv);
 
 	if (iwl_is_rfkill(priv))
 		return;
@@ -2879,6 +2718,8 @@ static void iwl_alive_start(struct iwl_p
 
 	iwl_reset_run_time_calib(priv);
 
+	set_bit(STATUS_READY, &priv->status);
+
 	/* Configure the adapter for unassociated operation */
 	iwlcore_commit_rxon(priv, ctx);
 
@@ -2888,7 +2729,6 @@ static void iwl_alive_start(struct iwl_p
 	iwl_leds_init(priv);
 
 	IWL_DEBUG_INFO(priv, "ALIVE processing complete.\n");
-	set_bit(STATUS_READY, &priv->status);
 	wake_up_interruptible(&priv->wait_command_queue);
 
 	iwl_power_update_mode(priv, true);
@@ -2916,8 +2756,7 @@ static void __iwl_down(struct iwl_priv *
 
 	/* Stop TX queues watchdog. We need to have STATUS_EXIT_PENDING bit set
 	 * to prevent rearm timer */
-	if (priv->cfg->ops->lib->recover_from_tx_stall)
-		del_timer_sync(&priv->monitor_recover);
+	del_timer_sync(&priv->watchdog);
 
 	iwl_clear_ucode_stations(priv, NULL);
 	iwl_dealloc_bcast_stations(priv);
@@ -2978,7 +2817,8 @@ static void __iwl_down(struct iwl_priv *
 				STATUS_EXIT_PENDING;
 
 	/* device going down, Stop using ICT table */
-	iwl_disable_ict(priv);
+	if (priv->cfg->ops->lib->isr_ops.disable)
+		priv->cfg->ops->lib->isr_ops.disable(priv);
 
 	iwlagn_txq_ctx_stop(priv);
 	iwlagn_rxq_stop(priv);
@@ -3201,7 +3041,8 @@ static void iwl_bg_alive_start(struct wo
 		return;
 
 	/* enable dram interrupt */
-	iwl_reset_ict(priv);
+	if (priv->cfg->ops->lib->isr_ops.reset)
+		priv->cfg->ops->lib->isr_ops.reset(priv);
 
 	mutex_lock(&priv->mutex);
 	iwl_alive_start(priv);
@@ -3309,92 +3150,6 @@ static void iwl_bg_rx_replenish(struct w
 	mutex_unlock(&priv->mutex);
 }
 
-#define IWL_DELAY_NEXT_SCAN (HZ*2)
-
-void iwl_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif)
-{
-	struct iwl_rxon_context *ctx;
-	struct ieee80211_conf *conf = NULL;
-	int ret = 0;
-
-	if (!vif || !priv->is_open)
-		return;
-
-	ctx = iwl_rxon_ctx_from_vif(vif);
-
-	if (vif->type == NL80211_IFTYPE_AP) {
-		IWL_ERR(priv, "%s Should not be called in AP mode\n", __func__);
-		return;
-	}
-
-	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-		return;
-
-	iwl_scan_cancel_timeout(priv, 200);
-
-	conf = ieee80211_get_hw_conf(priv->hw);
-
-	ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
-	iwlcore_commit_rxon(priv, ctx);
-
-	ret = iwl_send_rxon_timing(priv, ctx);
-	if (ret)
-		IWL_WARN(priv, "RXON timing - "
-			    "Attempting to continue.\n");
-
-	ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
-
-	iwl_set_rxon_ht(priv, &priv->current_ht_config);
-
-	if (priv->cfg->ops->hcmd->set_rxon_chain)
-		priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
-
-	ctx->staging.assoc_id = cpu_to_le16(vif->bss_conf.aid);
-
-	IWL_DEBUG_ASSOC(priv, "assoc id %d beacon interval %d\n",
-			vif->bss_conf.aid, vif->bss_conf.beacon_int);
-
-	if (vif->bss_conf.use_short_preamble)
-		ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
-	else
-		ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
-
-	if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK) {
-		if (vif->bss_conf.use_short_slot)
-			ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK;
-		else
-			ctx->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
-	}
-
-	iwlcore_commit_rxon(priv, ctx);
-
-	IWL_DEBUG_ASSOC(priv, "Associated as %d to: %pM\n",
-			vif->bss_conf.aid, ctx->active.bssid_addr);
-
-	switch (vif->type) {
-	case NL80211_IFTYPE_STATION:
-		break;
-	case NL80211_IFTYPE_ADHOC:
-		iwl_send_beacon_cmd(priv);
-		break;
-	default:
-		IWL_ERR(priv, "%s Should not be called in %d mode\n",
-			  __func__, vif->type);
-		break;
-	}
-
-	/* the chain noise calibration will enabled PM upon completion
-	 * If chain noise has already been run, then we need to enable
-	 * power management here */
-	if (priv->chain_noise_data.state == IWL_CHAIN_NOISE_DONE)
-		iwl_power_update_mode(priv, false);
-
-	/* Enable Rx differential gain and sensitivity calibrations */
-	iwl_chain_noise_reset(priv);
-	priv->start_calib = 1;
-
-}
-
 /*****************************************************************************
  *
  * mac80211 entry point functions
@@ -3420,7 +3175,8 @@ static int iwl_mac_setup_register(struct
 	hw->flags = IEEE80211_HW_SIGNAL_DBM |
 		    IEEE80211_HW_AMPDU_AGGREGATION |
 		    IEEE80211_HW_NEED_DTIM_PERIOD |
-		    IEEE80211_HW_SPECTRUM_MGMT;
+		    IEEE80211_HW_SPECTRUM_MGMT |
+		    IEEE80211_HW_REPORTS_TX_ACK_STATUS;
 
 	if (!priv->cfg->base_params->broken_powersave)
 		hw->flags |= IEEE80211_HW_SUPPORTS_PS |
@@ -3474,7 +3230,7 @@ static int iwl_mac_setup_register(struct
 }
 
 
-static int iwl_mac_start(struct ieee80211_hw *hw)
+int iwlagn_mac_start(struct ieee80211_hw *hw)
 {
 	struct iwl_priv *priv = hw->priv;
 	int ret;
@@ -3515,7 +3271,7 @@ out:
 	return 0;
 }
 
-static void iwl_mac_stop(struct ieee80211_hw *hw)
+void iwlagn_mac_stop(struct ieee80211_hw *hw)
 {
 	struct iwl_priv *priv = hw->priv;
 
@@ -3530,14 +3286,15 @@ static void iwl_mac_stop(struct ieee8021
 
 	flush_workqueue(priv->workqueue);
 
-	/* enable interrupts again in order to receive rfkill changes */
+	/* User space software may expect getting rfkill changes
+	 * even if interface is down */
 	iwl_write32(priv, CSR_INT, 0xFFFFFFFF);
-	iwl_enable_interrupts(priv);
+	iwl_enable_rfkill_int(priv);
 
 	IWL_DEBUG_MAC80211(priv, "leave\n");
 }
 
-static int iwl_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
+int iwlagn_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 {
 	struct iwl_priv *priv = hw->priv;
 
@@ -3553,73 +3310,12 @@ static int iwl_mac_tx(struct ieee80211_h
 	return NETDEV_TX_OK;
 }
 
-void iwl_config_ap(struct iwl_priv *priv, struct ieee80211_vif *vif)
-{
-	struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);
-	int ret = 0;
-
-	lockdep_assert_held(&priv->mutex);
-
-	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-		return;
-
-	/* The following should be done only at AP bring up */
-	if (!iwl_is_associated_ctx(ctx)) {
-
-		/* RXON - unassoc (to set timing command) */
-		ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
-		iwlcore_commit_rxon(priv, ctx);
-
-		/* RXON Timing */
-		ret = iwl_send_rxon_timing(priv, ctx);
-		if (ret)
-			IWL_WARN(priv, "RXON timing failed - "
-					"Attempting to continue.\n");
-
-		/* AP has all antennas */
-		priv->chain_noise_data.active_chains =
-			priv->hw_params.valid_rx_ant;
-		iwl_set_rxon_ht(priv, &priv->current_ht_config);
-		if (priv->cfg->ops->hcmd->set_rxon_chain)
-			priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
-
-		ctx->staging.assoc_id = 0;
-
-		if (vif->bss_conf.use_short_preamble)
-			ctx->staging.flags |=
-				RXON_FLG_SHORT_PREAMBLE_MSK;
-		else
-			ctx->staging.flags &=
-				~RXON_FLG_SHORT_PREAMBLE_MSK;
-
-		if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK) {
-			if (vif->bss_conf.use_short_slot)
-				ctx->staging.flags |=
-					RXON_FLG_SHORT_SLOT_MSK;
-			else
-				ctx->staging.flags &=
-					~RXON_FLG_SHORT_SLOT_MSK;
-		}
-		/* need to send beacon cmd before committing assoc RXON! */
-		iwl_send_beacon_cmd(priv);
-		/* restore RXON assoc */
-		ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
-		iwlcore_commit_rxon(priv, ctx);
-	}
-	iwl_send_beacon_cmd(priv);
-
-	/* FIXME - we need to add code here to detect a totally new
-	 * configuration, reset the AP, unassoc, rxon timing, assoc,
-	 * clear sta table, add BCAST sta... */
-}
-
-static void iwl_mac_update_tkip_key(struct ieee80211_hw *hw,
-				    struct ieee80211_vif *vif,
-				    struct ieee80211_key_conf *keyconf,
-				    struct ieee80211_sta *sta,
-				    u32 iv32, u16 *phase1key)
+void iwlagn_mac_update_tkip_key(struct ieee80211_hw *hw,
+				struct ieee80211_vif *vif,
+				struct ieee80211_key_conf *keyconf,
+				struct ieee80211_sta *sta,
+				u32 iv32, u16 *phase1key)
 {
-
 	struct iwl_priv *priv = hw->priv;
 	struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
 
@@ -3631,10 +3327,9 @@ static void iwl_mac_update_tkip_key(stru
 	IWL_DEBUG_MAC80211(priv, "leave\n");
 }
 
-static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
-			   struct ieee80211_vif *vif,
-			   struct ieee80211_sta *sta,
-			   struct ieee80211_key_conf *key)
+int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
+		       struct ieee80211_vif *vif, struct ieee80211_sta *sta,
+		       struct ieee80211_key_conf *key)
 {
 	struct iwl_priv *priv = hw->priv;
 	struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
@@ -3701,10 +3396,10 @@ static int iwl_mac_set_key(struct ieee80
 	return ret;
 }
 
-static int iwl_mac_ampdu_action(struct ieee80211_hw *hw,
-				struct ieee80211_vif *vif,
-				enum ieee80211_ampdu_mlme_action action,
-				struct ieee80211_sta *sta, u16 tid, u16 *ssn)
+int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw,
+			    struct ieee80211_vif *vif,
+			    enum ieee80211_ampdu_mlme_action action,
+			    struct ieee80211_sta *sta, u16 tid, u16 *ssn)
 {
 	struct iwl_priv *priv = hw->priv;
 	int ret = -EINVAL;
@@ -3785,39 +3480,9 @@ static int iwl_mac_ampdu_action(struct i
 	return ret;
 }
 
-static void iwl_mac_sta_notify(struct ieee80211_hw *hw,
-			       struct ieee80211_vif *vif,
-			       enum sta_notify_cmd cmd,
-			       struct ieee80211_sta *sta)
-{
-	struct iwl_priv *priv = hw->priv;
-	struct iwl_station_priv *sta_priv = (void *)sta->drv_priv;
-	int sta_id;
-
-	switch (cmd) {
-	case STA_NOTIFY_SLEEP:
-		WARN_ON(!sta_priv->client);
-		sta_priv->asleep = true;
-		if (atomic_read(&sta_priv->pending_frames) > 0)
-			ieee80211_sta_block_awake(hw, sta, true);
-		break;
-	case STA_NOTIFY_AWAKE:
-		WARN_ON(!sta_priv->client);
-		if (!sta_priv->asleep)
-			break;
-		sta_priv->asleep = false;
-		sta_id = iwl_sta_id(sta);
-		if (sta_id != IWL_INVALID_STATION)
-			iwl_sta_modify_ps_wake(priv, sta_id);
-		break;
-	default:
-		break;
-	}
-}
-
-static int iwlagn_mac_sta_add(struct ieee80211_hw *hw,
-			      struct ieee80211_vif *vif,
-			      struct ieee80211_sta *sta)
+int iwlagn_mac_sta_add(struct ieee80211_hw *hw,
+		       struct ieee80211_vif *vif,
+		       struct ieee80211_sta *sta)
 {
 	struct iwl_priv *priv = hw->priv;
 	struct iwl_station_priv *sta_priv = (void *)sta->drv_priv;
@@ -3858,8 +3523,8 @@ static int iwlagn_mac_sta_add(struct iee
 	return 0;
 }
 
-static void iwl_mac_channel_switch(struct ieee80211_hw *hw,
-				   struct ieee80211_channel_switch *ch_switch)
+void iwlagn_mac_channel_switch(struct ieee80211_hw *hw,
+			       struct ieee80211_channel_switch *ch_switch)
 {
 	struct iwl_priv *priv = hw->priv;
 	const struct iwl_channel_info *ch_info;
@@ -3956,10 +3621,10 @@ out_exit:
 	IWL_DEBUG_MAC80211(priv, "leave\n");
 }
 
-static void iwlagn_configure_filter(struct ieee80211_hw *hw,
-				    unsigned int changed_flags,
-				    unsigned int *total_flags,
-				    u64 multicast)
+void iwlagn_configure_filter(struct ieee80211_hw *hw,
+			     unsigned int changed_flags,
+			     unsigned int *total_flags,
+			     u64 multicast)
 {
 	struct iwl_priv *priv = hw->priv;
 	__le32 filter_or = 0, filter_nand = 0;
@@ -3976,7 +3641,8 @@ static void iwlagn_configure_filter(stru
 			changed_flags, *total_flags);
 
 	CHK(FIF_OTHER_BSS | FIF_PROMISC_IN_BSS, RXON_FILTER_PROMISC_MSK);
-	CHK(FIF_CONTROL, RXON_FILTER_CTL2HOST_MSK);
+	/* Setting _just_ RXON_FILTER_CTL2HOST_MSK causes FH errors */
+	CHK(FIF_CONTROL, RXON_FILTER_CTL2HOST_MSK | RXON_FILTER_PROMISC_MSK);
 	CHK(FIF_BCN_PRBRESP_PROMISC, RXON_FILTER_BCON_AWARE_MSK);
 
 #undef CHK
@@ -3986,7 +3652,11 @@ static void iwlagn_configure_filter(stru
 	for_each_context(priv, ctx) {
 		ctx->staging.filter_flags &= ~filter_nand;
 		ctx->staging.filter_flags |= filter_or;
-		iwlcore_commit_rxon(priv, ctx);
+
+		/*
+		 * Not committing directly because hardware can perform a scan,
+		 * but we'll eventually commit the filter flags change anyway.
+		 */
 	}
 
 	mutex_unlock(&priv->mutex);
@@ -4001,7 +3671,7 @@ static void iwlagn_configure_filter(stru
 			FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL;
 }
 
-static void iwl_mac_flush(struct ieee80211_hw *hw, bool drop)
+void iwlagn_mac_flush(struct ieee80211_hw *hw, bool drop)
 {
 	struct iwl_priv *priv = hw->priv;
 
@@ -4074,12 +3744,9 @@ static void iwl_setup_deferred_work(stru
 	priv->ucode_trace.data = (unsigned long)priv;
 	priv->ucode_trace.function = iwl_bg_ucode_trace;
 
-	if (priv->cfg->ops->lib->recover_from_tx_stall) {
-		init_timer(&priv->monitor_recover);
-		priv->monitor_recover.data = (unsigned long)priv;
-		priv->monitor_recover.function =
-			priv->cfg->ops->lib->recover_from_tx_stall;
-	}
+	init_timer(&priv->watchdog);
+	priv->watchdog.data = (unsigned long)priv;
+	priv->watchdog.function = iwl_bg_watchdog;
 
 	if (!priv->cfg->base_params->use_isr_legacy)
 		tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long))
@@ -4172,13 +3839,13 @@ static int iwl_init_drv(struct iwl_priv
 		priv->bt_on_thresh = BT_ON_THRESHOLD_DEF;
 		priv->bt_duration = BT_DURATION_LIMIT_DEF;
 		priv->dynamic_frag_thresh = BT_FRAG_THRESHOLD_DEF;
-		priv->dynamic_agg_thresh = BT_AGG_THRESHOLD_DEF;
 	}
 
 	/* Set the tx_power_user_lmt to the lowest power level
 	 * this value will get overwritten by channel max power avg
 	 * from eeprom */
 	priv->tx_power_user_lmt = IWLAGN_TX_POWER_TARGET_POWER_MIN;
+	priv->tx_power_next = IWLAGN_TX_POWER_TARGET_POWER_MIN;
 
 	ret = iwl_init_channel_map(priv);
 	if (ret) {
@@ -4209,28 +3876,30 @@ static void iwl_uninit_drv(struct iwl_pr
 	kfree(priv->scan_cmd);
 }
 
-static struct ieee80211_ops iwl_hw_ops = {
-	.tx = iwl_mac_tx,
-	.start = iwl_mac_start,
-	.stop = iwl_mac_stop,
+#ifdef CONFIG_IWL5000
+struct ieee80211_ops iwlagn_hw_ops = {
+	.tx = iwlagn_mac_tx,
+	.start = iwlagn_mac_start,
+	.stop = iwlagn_mac_stop,
 	.add_interface = iwl_mac_add_interface,
 	.remove_interface = iwl_mac_remove_interface,
-	.config = iwl_mac_config,
+	.change_interface = iwl_mac_change_interface,
+	.config = iwlagn_mac_config,
 	.configure_filter = iwlagn_configure_filter,
-	.set_key = iwl_mac_set_key,
-	.update_tkip_key = iwl_mac_update_tkip_key,
+	.set_key = iwlagn_mac_set_key,
+	.update_tkip_key = iwlagn_mac_update_tkip_key,
 	.conf_tx = iwl_mac_conf_tx,
-	.reset_tsf = iwl_mac_reset_tsf,
-	.bss_info_changed = iwl_bss_info_changed,
-	.ampdu_action = iwl_mac_ampdu_action,
+	.bss_info_changed = iwlagn_bss_info_changed,
+	.ampdu_action = iwlagn_mac_ampdu_action,
 	.hw_scan = iwl_mac_hw_scan,
-	.sta_notify = iwl_mac_sta_notify,
+	.sta_notify = iwlagn_mac_sta_notify,
 	.sta_add = iwlagn_mac_sta_add,
 	.sta_remove = iwl_mac_sta_remove,
-	.channel_switch = iwl_mac_channel_switch,
-	.flush = iwl_mac_flush,
+	.channel_switch = iwlagn_mac_channel_switch,
+	.flush = iwlagn_mac_flush,
 	.tx_last_beacon = iwl_mac_tx_last_beacon,
 };
+#endif
 
 static void iwl_hw_detect(struct iwl_priv *priv)
 {
@@ -4298,10 +3967,15 @@ static int iwl_pci_probe(struct pci_dev
 	if (cfg->mod_params->disable_hw_scan) {
 		dev_printk(KERN_DEBUG, &(pdev->dev),
 			"sw scan support is deprecated\n");
-		iwl_hw_ops.hw_scan = NULL;
+#ifdef CONFIG_IWL5000
+		iwlagn_hw_ops.hw_scan = NULL;
+#endif
+#ifdef CONFIG_IWL4965
+		iwl4965_hw_ops.hw_scan = NULL;
+#endif
 	}
 
-	hw = iwl_alloc_all(cfg, &iwl_hw_ops);
+	hw = iwl_alloc_all(cfg);
 	if (!hw) {
 		err = -ENOMEM;
 		goto out;
@@ -4333,6 +4007,7 @@ static int iwl_pci_probe(struct pci_dev
 		BIT(NL80211_IFTYPE_ADHOC);
 	priv->contexts[IWL_RXON_CTX_BSS].interface_modes =
 		BIT(NL80211_IFTYPE_STATION);
+	priv->contexts[IWL_RXON_CTX_BSS].ap_devtype = RXON_DEV_TYPE_AP;
 	priv->contexts[IWL_RXON_CTX_BSS].ibss_devtype = RXON_DEV_TYPE_IBSS;
 	priv->contexts[IWL_RXON_CTX_BSS].station_devtype = RXON_DEV_TYPE_ESS;
 	priv->contexts[IWL_RXON_CTX_BSS].unused_devtype = RXON_DEV_TYPE_ESS;
@@ -4368,8 +4043,10 @@ static int iwl_pci_probe(struct pci_dev
 		(iwlagn_ant_coupling > IWL_BT_ANTENNA_COUPLING_THRESHOLD) ?
 		true : false;
 
-	/* enable/disable bt channel announcement */
+	/* enable/disable bt channel inhibition */
 	priv->bt_ch_announce = iwlagn_bt_ch_announce;
+	IWL_DEBUG_INFO(priv, "BT channel inhibition is %s\n",
+		       (priv->bt_ch_announce) ? "On" : "Off");
 
 	if (iwl_alloc_traffic_mem(priv))
 		IWL_ERR(priv, "Not enough memory to generate traffic log\n");
@@ -4461,6 +4138,10 @@ static int iwl_pci_probe(struct pci_dev
 	if (err)
 		goto out_free_eeprom;
 
+	err = iwl_eeprom_check_sku(priv);
+	if (err)
+		goto out_free_eeprom;
+
 	/* extract MAC Address */
 	iwl_eeprom_get_mac(priv, priv->addresses[0].addr);
 	IWL_DEBUG_INFO(priv, "MAC address: %pM\n", priv->addresses[0].addr);
@@ -4500,8 +4181,10 @@ static int iwl_pci_probe(struct pci_dev
 
 	pci_enable_msi(priv->pci_dev);
 
-	iwl_alloc_isr_ict(priv);
-	err = request_irq(priv->pci_dev->irq, priv->cfg->ops->lib->isr,
+	if (priv->cfg->ops->lib->isr_ops.alloc)
+		priv->cfg->ops->lib->isr_ops.alloc(priv);
+
+	err = request_irq(priv->pci_dev->irq, priv->cfg->ops->lib->isr_ops.isr,
 			  IRQF_SHARED, DRV_NAME, priv);
 	if (err) {
 		IWL_ERR(priv, "Error allocating IRQ %d\n", priv->pci_dev->irq);
@@ -4515,14 +4198,14 @@ static int iwl_pci_probe(struct pci_dev
 	 * 8. Enable interrupts and read RFKILL state
 	 *********************************************/
 
-	/* enable interrupts if needed: hw bug w/a */
+	/* enable rfkill interrupt: hw bug w/a */
 	pci_read_config_word(priv->pci_dev, PCI_COMMAND, &pci_cmd);
 	if (pci_cmd & PCI_COMMAND_INTX_DISABLE) {
 		pci_cmd &= ~PCI_COMMAND_INTX_DISABLE;
 		pci_write_config_word(priv->pci_dev, PCI_COMMAND, pci_cmd);
 	}
 
-	iwl_enable_interrupts(priv);
+	iwl_enable_rfkill_int(priv);
 
 	/* If platform's RF_KILL switch is NOT set to KILL */
 	if (iwl_read32(priv, CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)
@@ -4548,7 +4231,8 @@ static int iwl_pci_probe(struct pci_dev
 	destroy_workqueue(priv->workqueue);
 	priv->workqueue = NULL;
 	free_irq(priv->pci_dev->irq, priv);
-	iwl_free_isr_ict(priv);
+	if (priv->cfg->ops->lib->isr_ops.free)
+		priv->cfg->ops->lib->isr_ops.free(priv);
  out_disable_msi:
 	pci_disable_msi(priv->pci_dev);
 	iwl_uninit_drv(priv);
@@ -4643,7 +4327,8 @@ static void __devexit iwl_pci_remove(str
 
 	iwl_uninit_drv(priv);
 
-	iwl_free_isr_ict(priv);
+	if (priv->cfg->ops->lib->isr_ops.free)
+		priv->cfg->ops->lib->isr_ops.free(priv);
 
 	dev_kfree_skb(priv->beacon_skb);
 
@@ -4734,51 +4419,32 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_ca
 	{IWL_PCI_DEVICE(0x4239, 0x1311, iwl6000i_2agn_cfg)},
 	{IWL_PCI_DEVICE(0x4239, 0x1316, iwl6000i_2abg_cfg)},
 
-/* 6x00 Series Gen2a */
-	{IWL_PCI_DEVICE(0x0082, 0x1201, iwl6000g2a_2agn_cfg)},
-	{IWL_PCI_DEVICE(0x0085, 0x1211, iwl6000g2a_2agn_cfg)},
-	{IWL_PCI_DEVICE(0x0082, 0x1221, iwl6000g2a_2agn_cfg)},
-	{IWL_PCI_DEVICE(0x0082, 0x1206, iwl6000g2a_2abg_cfg)},
-	{IWL_PCI_DEVICE(0x0085, 0x1216, iwl6000g2a_2abg_cfg)},
-	{IWL_PCI_DEVICE(0x0082, 0x1226, iwl6000g2a_2abg_cfg)},
-	{IWL_PCI_DEVICE(0x0082, 0x1207, iwl6000g2a_2bg_cfg)},
-	{IWL_PCI_DEVICE(0x0082, 0x1301, iwl6000g2a_2agn_cfg)},
-	{IWL_PCI_DEVICE(0x0082, 0x1306, iwl6000g2a_2abg_cfg)},
-	{IWL_PCI_DEVICE(0x0082, 0x1307, iwl6000g2a_2bg_cfg)},
-	{IWL_PCI_DEVICE(0x0082, 0x1321, iwl6000g2a_2agn_cfg)},
-	{IWL_PCI_DEVICE(0x0082, 0x1326, iwl6000g2a_2abg_cfg)},
-	{IWL_PCI_DEVICE(0x0085, 0x1311, iwl6000g2a_2agn_cfg)},
-	{IWL_PCI_DEVICE(0x0085, 0x1316, iwl6000g2a_2abg_cfg)},
+/* 6x05 Series */
+	{IWL_PCI_DEVICE(0x0082, 0x1301, iwl6005_2agn_cfg)},
+	{IWL_PCI_DEVICE(0x0082, 0x1306, iwl6005_2abg_cfg)},
+	{IWL_PCI_DEVICE(0x0082, 0x1307, iwl6005_2bg_cfg)},
+	{IWL_PCI_DEVICE(0x0082, 0x1321, iwl6005_2agn_cfg)},
+	{IWL_PCI_DEVICE(0x0082, 0x1326, iwl6005_2abg_cfg)},
+	{IWL_PCI_DEVICE(0x0085, 0x1311, iwl6005_2agn_cfg)},
+	{IWL_PCI_DEVICE(0x0085, 0x1316, iwl6005_2abg_cfg)},
 
-/* 6x00 Series Gen2b */
-	{IWL_PCI_DEVICE(0x008F, 0x5105, iwl6000g2b_bgn_cfg)},
-	{IWL_PCI_DEVICE(0x0090, 0x5115, iwl6000g2b_bgn_cfg)},
-	{IWL_PCI_DEVICE(0x008F, 0x5125, iwl6000g2b_bgn_cfg)},
-	{IWL_PCI_DEVICE(0x008F, 0x5107, iwl6000g2b_bg_cfg)},
-	{IWL_PCI_DEVICE(0x008F, 0x5201, iwl6000g2b_2agn_cfg)},
-	{IWL_PCI_DEVICE(0x0090, 0x5211, iwl6000g2b_2agn_cfg)},
-	{IWL_PCI_DEVICE(0x008F, 0x5221, iwl6000g2b_2agn_cfg)},
-	{IWL_PCI_DEVICE(0x008F, 0x5206, iwl6000g2b_2abg_cfg)},
-	{IWL_PCI_DEVICE(0x0090, 0x5216, iwl6000g2b_2abg_cfg)},
-	{IWL_PCI_DEVICE(0x008F, 0x5226, iwl6000g2b_2abg_cfg)},
-	{IWL_PCI_DEVICE(0x008F, 0x5207, iwl6000g2b_2bg_cfg)},
-	{IWL_PCI_DEVICE(0x008A, 0x5301, iwl6000g2b_bgn_cfg)},
-	{IWL_PCI_DEVICE(0x008A, 0x5305, iwl6000g2b_bgn_cfg)},
-	{IWL_PCI_DEVICE(0x008A, 0x5307, iwl6000g2b_bg_cfg)},
-	{IWL_PCI_DEVICE(0x008A, 0x5321, iwl6000g2b_bgn_cfg)},
-	{IWL_PCI_DEVICE(0x008A, 0x5325, iwl6000g2b_bgn_cfg)},
-	{IWL_PCI_DEVICE(0x008B, 0x5311, iwl6000g2b_bgn_cfg)},
-	{IWL_PCI_DEVICE(0x008B, 0x5315, iwl6000g2b_bgn_cfg)},
-	{IWL_PCI_DEVICE(0x0090, 0x5211, iwl6000g2b_2agn_cfg)},
-	{IWL_PCI_DEVICE(0x0090, 0x5215, iwl6000g2b_2bgn_cfg)},
-	{IWL_PCI_DEVICE(0x0090, 0x5216, iwl6000g2b_2abg_cfg)},
-	{IWL_PCI_DEVICE(0x0091, 0x5201, iwl6000g2b_2agn_cfg)},
-	{IWL_PCI_DEVICE(0x0091, 0x5205, iwl6000g2b_2bgn_cfg)},
-	{IWL_PCI_DEVICE(0x0091, 0x5206, iwl6000g2b_2abg_cfg)},
-	{IWL_PCI_DEVICE(0x0091, 0x5207, iwl6000g2b_2bg_cfg)},
-	{IWL_PCI_DEVICE(0x0091, 0x5221, iwl6000g2b_2agn_cfg)},
-	{IWL_PCI_DEVICE(0x0091, 0x5225, iwl6000g2b_2bgn_cfg)},
-	{IWL_PCI_DEVICE(0x0091, 0x5226, iwl6000g2b_2abg_cfg)},
+/* 6x30 Series */
+	{IWL_PCI_DEVICE(0x008A, 0x5305, iwl1030_bgn_cfg)},
+	{IWL_PCI_DEVICE(0x008A, 0x5307, iwl1030_bg_cfg)},
+	{IWL_PCI_DEVICE(0x008A, 0x5325, iwl1030_bgn_cfg)},
+	{IWL_PCI_DEVICE(0x008A, 0x5327, iwl1030_bg_cfg)},
+	{IWL_PCI_DEVICE(0x008B, 0x5315, iwl1030_bgn_cfg)},
+	{IWL_PCI_DEVICE(0x008B, 0x5317, iwl1030_bg_cfg)},
+	{IWL_PCI_DEVICE(0x0090, 0x5211, iwl6030_2agn_cfg)},
+	{IWL_PCI_DEVICE(0x0090, 0x5215, iwl6030_2bgn_cfg)},
+	{IWL_PCI_DEVICE(0x0090, 0x5216, iwl6030_2abg_cfg)},
+	{IWL_PCI_DEVICE(0x0091, 0x5201, iwl6030_2agn_cfg)},
+	{IWL_PCI_DEVICE(0x0091, 0x5205, iwl6030_2bgn_cfg)},
+	{IWL_PCI_DEVICE(0x0091, 0x5206, iwl6030_2abg_cfg)},
+	{IWL_PCI_DEVICE(0x0091, 0x5207, iwl6030_2bg_cfg)},
+	{IWL_PCI_DEVICE(0x0091, 0x5221, iwl6030_2agn_cfg)},
+	{IWL_PCI_DEVICE(0x0091, 0x5225, iwl6030_2bgn_cfg)},
+	{IWL_PCI_DEVICE(0x0091, 0x5226, iwl6030_2abg_cfg)},
 
 /* 6x50 WiFi/WiMax Series */
 	{IWL_PCI_DEVICE(0x0087, 0x1301, iwl6050_2agn_cfg)},
@@ -4788,13 +4454,13 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_ca
 	{IWL_PCI_DEVICE(0x0089, 0x1311, iwl6050_2agn_cfg)},
 	{IWL_PCI_DEVICE(0x0089, 0x1316, iwl6050_2abg_cfg)},
 
-/* 6x50 WiFi/WiMax Series Gen2 */
-	{IWL_PCI_DEVICE(0x0885, 0x1305, iwl6050g2_bgn_cfg)},
-	{IWL_PCI_DEVICE(0x0885, 0x1306, iwl6050g2_bgn_cfg)},
-	{IWL_PCI_DEVICE(0x0885, 0x1325, iwl6050g2_bgn_cfg)},
-	{IWL_PCI_DEVICE(0x0885, 0x1326, iwl6050g2_bgn_cfg)},
-	{IWL_PCI_DEVICE(0x0886, 0x1315, iwl6050g2_bgn_cfg)},
-	{IWL_PCI_DEVICE(0x0886, 0x1316, iwl6050g2_bgn_cfg)},
+/* 6150 WiFi/WiMax Series */
+	{IWL_PCI_DEVICE(0x0885, 0x1305, iwl6150_bgn_cfg)},
+	{IWL_PCI_DEVICE(0x0885, 0x1306, iwl6150_bgn_cfg)},
+	{IWL_PCI_DEVICE(0x0885, 0x1325, iwl6150_bgn_cfg)},
+	{IWL_PCI_DEVICE(0x0885, 0x1326, iwl6150_bgn_cfg)},
+	{IWL_PCI_DEVICE(0x0886, 0x1315, iwl6150_bgn_cfg)},
+	{IWL_PCI_DEVICE(0x0886, 0x1316, iwl6150_bgn_cfg)},
 
 /* 1000 Series WiFi */
 	{IWL_PCI_DEVICE(0x0083, 0x1205, iwl1000_bgn_cfg)},
@@ -4812,10 +4478,11 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_ca
 
 /* 100 Series WiFi */
 	{IWL_PCI_DEVICE(0x08AE, 0x1005, iwl100_bgn_cfg)},
+	{IWL_PCI_DEVICE(0x08AE, 0x1007, iwl100_bg_cfg)},
 	{IWL_PCI_DEVICE(0x08AF, 0x1015, iwl100_bgn_cfg)},
+	{IWL_PCI_DEVICE(0x08AF, 0x1017, iwl100_bg_cfg)},
 	{IWL_PCI_DEVICE(0x08AE, 0x1025, iwl100_bgn_cfg)},
-	{IWL_PCI_DEVICE(0x08AE, 0x1007, iwl100_bg_cfg)},
-	{IWL_PCI_DEVICE(0x08AE, 0x1017, iwl100_bg_cfg)},
+	{IWL_PCI_DEVICE(0x08AE, 0x1027, iwl100_bg_cfg)},
 
 /* 130 Series WiFi */
 	{IWL_PCI_DEVICE(0x0896, 0x5005, iwl130_bgn_cfg)},
@@ -4836,10 +4503,7 @@ static struct pci_driver iwl_driver = {
 	.id_table = iwl_hw_card_ids,
 	.probe = iwl_pci_probe,
 	.remove = __devexit_p(iwl_pci_remove),
-#ifdef CONFIG_PM
-	.suspend = iwl_pci_suspend,
-	.resume = iwl_pci_resume,
-#endif
+	.driver.pm = IWL_PM_OPS,
 };
 
 static int __init iwl_init(void)
@@ -4925,6 +4589,6 @@ module_param_named(antenna_coupling, iwl
 MODULE_PARM_DESC(antenna_coupling,
 		 "specify antenna coupling in dB (defualt: 0 dB)");
 
-module_param_named(bt_ch_announce, iwlagn_bt_ch_announce, bool, S_IRUGO);
-MODULE_PARM_DESC(bt_ch_announce,
-		 "Enable BT channel announcement mode (default: enable)");
+module_param_named(bt_ch_inhibition, iwlagn_bt_ch_announce, bool, S_IRUGO);
+MODULE_PARM_DESC(bt_ch_inhibition,
+		 "Disable BT channel inhibition (default: enable)");
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/iwlwifi/iwl-agn-calib.c linux-libre-2.6.38-gnu1/drivers/net/wireless/iwlwifi/iwl-agn-calib.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/iwlwifi/iwl-agn-calib.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/iwlwifi/iwl-agn-calib.c	2011-03-14 21:20:32.000000000 -0400
@@ -732,8 +732,122 @@ static inline u8 find_first_chain(u8 mas
 	return CHAIN_C;
 }
 
+/**
+ * Run disconnected antenna algorithm to find out which antennas are
+ * disconnected.
+ */
+static void iwl_find_disconn_antenna(struct iwl_priv *priv, u32* average_sig,
+				     struct iwl_chain_noise_data *data)
+{
+	u32 active_chains = 0;
+	u32 max_average_sig;
+	u16 max_average_sig_antenna_i;
+	u8 num_tx_chains;
+	u8 first_chain;
+	u16 i = 0;
+
+	average_sig[0] = data->chain_signal_a /
+			 priv->cfg->base_params->chain_noise_num_beacons;
+	average_sig[1] = data->chain_signal_b /
+			 priv->cfg->base_params->chain_noise_num_beacons;
+	average_sig[2] = data->chain_signal_c /
+			 priv->cfg->base_params->chain_noise_num_beacons;
+
+	if (average_sig[0] >= average_sig[1]) {
+		max_average_sig = average_sig[0];
+		max_average_sig_antenna_i = 0;
+		active_chains = (1 << max_average_sig_antenna_i);
+	} else {
+		max_average_sig = average_sig[1];
+		max_average_sig_antenna_i = 1;
+		active_chains = (1 << max_average_sig_antenna_i);
+	}
+
+	if (average_sig[2] >= max_average_sig) {
+		max_average_sig = average_sig[2];
+		max_average_sig_antenna_i = 2;
+		active_chains = (1 << max_average_sig_antenna_i);
+	}
+
+	IWL_DEBUG_CALIB(priv, "average_sig: a %d b %d c %d\n",
+		     average_sig[0], average_sig[1], average_sig[2]);
+	IWL_DEBUG_CALIB(priv, "max_average_sig = %d, antenna %d\n",
+		     max_average_sig, max_average_sig_antenna_i);
+
+	/* Compare signal strengths for all 3 receivers. */
+	for (i = 0; i < NUM_RX_CHAINS; i++) {
+		if (i != max_average_sig_antenna_i) {
+			s32 rssi_delta = (max_average_sig - average_sig[i]);
+
+			/* If signal is very weak, compared with
+			 * strongest, mark it as disconnected. */
+			if (rssi_delta > MAXIMUM_ALLOWED_PATHLOSS)
+				data->disconn_array[i] = 1;
+			else
+				active_chains |= (1 << i);
+			IWL_DEBUG_CALIB(priv, "i = %d  rssiDelta = %d  "
+			     "disconn_array[i] = %d\n",
+			     i, rssi_delta, data->disconn_array[i]);
+		}
+	}
+
+	/*
+	 * The above algorithm sometimes fails when the ucode
+	 * reports 0 for all chains. It's not clear why that
+	 * happens to start with, but it is then causing trouble
+	 * because this can make us enable more chains than the
+	 * hardware really has.
+	 *
+	 * To be safe, simply mask out any chains that we know
+	 * are not on the device.
+	 */
+	active_chains &= priv->hw_params.valid_rx_ant;
+
+	num_tx_chains = 0;
+	for (i = 0; i < NUM_RX_CHAINS; i++) {
+		/* loops on all the bits of
+		 * priv->hw_setting.valid_tx_ant */
+		u8 ant_msk = (1 << i);
+		if (!(priv->hw_params.valid_tx_ant & ant_msk))
+			continue;
+
+		num_tx_chains++;
+		if (data->disconn_array[i] == 0)
+			/* there is a Tx antenna connected */
+			break;
+		if (num_tx_chains == priv->hw_params.tx_chains_num &&
+		    data->disconn_array[i]) {
+			/*
+			 * If all chains are disconnected
+			 * connect the first valid tx chain
+			 */
+			first_chain =
+				find_first_chain(priv->cfg->valid_tx_ant);
+			data->disconn_array[first_chain] = 0;
+			active_chains |= BIT(first_chain);
+			IWL_DEBUG_CALIB(priv, "All Tx chains are disconnected \
+					W/A - declare %d as connected\n",
+					first_chain);
+			break;
+		}
+	}
+
+	if (active_chains != priv->hw_params.valid_rx_ant &&
+	    active_chains != priv->chain_noise_data.active_chains)
+		IWL_DEBUG_CALIB(priv,
+				"Detected that not all antennas are connected! "
+				"Connected: %#x, valid: %#x.\n",
+				active_chains, priv->hw_params.valid_rx_ant);
+
+	/* Save for use within RXON, TX, SCAN commands, etc. */
+	data->active_chains = active_chains;
+	IWL_DEBUG_CALIB(priv, "active_chains (bitwise) = 0x%x\n",
+			active_chains);
+}
+
+
 /*
- * Accumulate 20 beacons of signal and noise statistics for each of
+ * Accumulate 16 beacons of signal and noise statistics for each of
  *   3 receivers/antennas/rx-chains, then figure out:
  * 1)  Which antennas are connected.
  * 2)  Differential rx gain settings to balance the 3 receivers.
@@ -750,8 +864,6 @@ void iwl_chain_noise_calibration(struct
 	u32 chain_sig_c;
 	u32 average_sig[NUM_RX_CHAINS] = {INITIALIZATION_VALUE};
 	u32 average_noise[NUM_RX_CHAINS] = {INITIALIZATION_VALUE};
-	u32 max_average_sig;
-	u16 max_average_sig_antenna_i;
 	u32 min_average_noise = MIN_AVERAGE_NOISE_MAX_VALUE;
 	u16 min_average_noise_antenna_i = INITIALIZATION_VALUE;
 	u16 i = 0;
@@ -759,11 +871,9 @@ void iwl_chain_noise_calibration(struct
 	u16 stat_chnum = INITIALIZATION_VALUE;
 	u8 rxon_band24;
 	u8 stat_band24;
-	u32 active_chains = 0;
-	u8 num_tx_chains;
 	unsigned long flags;
 	struct statistics_rx_non_phy *rx_info;
-	u8 first_chain;
+
 	/*
 	 * MULTI-FIXME:
 	 * When we support multiple interfaces on different channels,
@@ -869,108 +979,16 @@ void iwl_chain_noise_calibration(struct
 		return;
 
 	/* Analyze signal for disconnected antenna */
-	average_sig[0] = data->chain_signal_a /
-			 priv->cfg->base_params->chain_noise_num_beacons;
-	average_sig[1] = data->chain_signal_b /
-			 priv->cfg->base_params->chain_noise_num_beacons;
-	average_sig[2] = data->chain_signal_c /
-			 priv->cfg->base_params->chain_noise_num_beacons;
-
-	if (average_sig[0] >= average_sig[1]) {
-		max_average_sig = average_sig[0];
-		max_average_sig_antenna_i = 0;
-		active_chains = (1 << max_average_sig_antenna_i);
-	} else {
-		max_average_sig = average_sig[1];
-		max_average_sig_antenna_i = 1;
-		active_chains = (1 << max_average_sig_antenna_i);
-	}
-
-	if (average_sig[2] >= max_average_sig) {
-		max_average_sig = average_sig[2];
-		max_average_sig_antenna_i = 2;
-		active_chains = (1 << max_average_sig_antenna_i);
-	}
-
-	IWL_DEBUG_CALIB(priv, "average_sig: a %d b %d c %d\n",
-		     average_sig[0], average_sig[1], average_sig[2]);
-	IWL_DEBUG_CALIB(priv, "max_average_sig = %d, antenna %d\n",
-		     max_average_sig, max_average_sig_antenna_i);
-
-	/* Compare signal strengths for all 3 receivers. */
-	for (i = 0; i < NUM_RX_CHAINS; i++) {
-		if (i != max_average_sig_antenna_i) {
-			s32 rssi_delta = (max_average_sig - average_sig[i]);
-
-			/* If signal is very weak, compared with
-			 * strongest, mark it as disconnected. */
-			if (rssi_delta > MAXIMUM_ALLOWED_PATHLOSS)
-				data->disconn_array[i] = 1;
-			else
-				active_chains |= (1 << i);
-			IWL_DEBUG_CALIB(priv, "i = %d  rssiDelta = %d  "
-			     "disconn_array[i] = %d\n",
-			     i, rssi_delta, data->disconn_array[i]);
-		}
-	}
-
-	/*
-	 * The above algorithm sometimes fails when the ucode
-	 * reports 0 for all chains. It's not clear why that
-	 * happens to start with, but it is then causing trouble
-	 * because this can make us enable more chains than the
-	 * hardware really has.
-	 *
-	 * To be safe, simply mask out any chains that we know
-	 * are not on the device.
-	 */
 	if (priv->cfg->bt_params &&
-	    priv->cfg->bt_params->advanced_bt_coexist &&
-	    priv->bt_full_concurrent) {
-		/* operated as 1x1 in full concurrency mode */
-		active_chains &= first_antenna(priv->hw_params.valid_rx_ant);
+	    priv->cfg->bt_params->advanced_bt_coexist) {
+		/* Disable disconnected antenna algorithm for advanced
+		   bt coex, assuming valid antennas are connected */
+		data->active_chains = priv->hw_params.valid_rx_ant;
+		for (i = 0; i < NUM_RX_CHAINS; i++)
+			if (!(data->active_chains & (1<<i)))
+				data->disconn_array[i] = 1;
 	} else
-		active_chains &= priv->hw_params.valid_rx_ant;
-
-	num_tx_chains = 0;
-	for (i = 0; i < NUM_RX_CHAINS; i++) {
-		/* loops on all the bits of
-		 * priv->hw_setting.valid_tx_ant */
-		u8 ant_msk = (1 << i);
-		if (!(priv->hw_params.valid_tx_ant & ant_msk))
-			continue;
-
-		num_tx_chains++;
-		if (data->disconn_array[i] == 0)
-			/* there is a Tx antenna connected */
-			break;
-		if (num_tx_chains == priv->hw_params.tx_chains_num &&
-		    data->disconn_array[i]) {
-			/*
-			 * If all chains are disconnected
-			 * connect the first valid tx chain
-			 */
-			first_chain =
-				find_first_chain(priv->cfg->valid_tx_ant);
-			data->disconn_array[first_chain] = 0;
-			active_chains |= BIT(first_chain);
-			IWL_DEBUG_CALIB(priv, "All Tx chains are disconnected W/A - declare %d as connected\n",
-					first_chain);
-			break;
-		}
-	}
-
-	if (active_chains != priv->hw_params.valid_rx_ant &&
-	    active_chains != priv->chain_noise_data.active_chains)
-		IWL_DEBUG_CALIB(priv,
-				"Detected that not all antennas are connected! "
-				"Connected: %#x, valid: %#x.\n",
-				active_chains, priv->hw_params.valid_rx_ant);
-
-	/* Save for use within RXON, TX, SCAN commands, etc. */
-	priv->chain_noise_data.active_chains = active_chains;
-	IWL_DEBUG_CALIB(priv, "active_chains (bitwise) = 0x%x\n",
-			active_chains);
+		iwl_find_disconn_antenna(priv, average_sig, data);
 
 	/* Analyze noise for rx balance */
 	average_noise[0] = data->chain_noise_a /
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c linux-libre-2.6.38-gnu1/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c	2011-03-14 21:20:32.000000000 -0400
@@ -856,6 +856,9 @@ ssize_t iwl_ucode_bt_stats_read(struct f
 	if (!iwl_is_alive(priv))
 		return -EAGAIN;
 
+	if (!priv->bt_enable_flag)
+		return -EINVAL;
+
 	/* make request to uCode to retrieve statistics information */
 	mutex_lock(&priv->mutex);
 	ret = iwl_send_statistics_request(priv, CMD_SYNC, false);
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c linux-libre-2.6.38-gnu1/drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c	2011-03-14 21:20:32.000000000 -0400
@@ -75,109 +75,6 @@
 #include "iwl-agn.h"
 #include "iwl-io.h"
 
-/************************** EEPROM BANDS ****************************
- *
- * The iwl_eeprom_band definitions below provide the mapping from the
- * EEPROM contents to the specific channel number supported for each
- * band.
- *
- * For example, iwl_priv->eeprom.band_3_channels[4] from the band_3
- * definition below maps to physical channel 42 in the 5.2GHz spectrum.
- * The specific geography and calibration information for that channel
- * is contained in the eeprom map itself.
- *
- * During init, we copy the eeprom information and channel map
- * information into priv->channel_info_24/52 and priv->channel_map_24/52
- *
- * channel_map_24/52 provides the index in the channel_info array for a
- * given channel.  We have to have two separate maps as there is channel
- * overlap with the 2.4GHz and 5.2GHz spectrum as seen in band_1 and
- * band_2
- *
- * A value of 0xff stored in the channel_map indicates that the channel
- * is not supported by the hardware at all.
- *
- * A value of 0xfe in the channel_map indicates that the channel is not
- * valid for Tx with the current hardware.  This means that
- * while the system can tune and receive on a given channel, it may not
- * be able to associate or transmit any frames on that
- * channel.  There is no corresponding channel information for that
- * entry.
- *
- *********************************************************************/
-
-/**
- * struct iwl_txpwr_section: eeprom section information
- * @offset: indirect address into eeprom image
- * @count: number of "struct iwl_eeprom_enhanced_txpwr" in this section
- * @band: band type for the section
- * @is_common - true: common section, false: channel section
- * @is_cck - true: cck section, false: not cck section
- * @is_ht_40 - true: all channel in the section are HT40 channel,
- *	       false: legacy or HT 20 MHz
- *	       ignore if it is common section
- * @iwl_eeprom_section_channel: channel array in the section,
- *	       ignore if common section
- */
-struct iwl_txpwr_section {
-	u32 offset;
-	u8 count;
-	enum ieee80211_band band;
-	bool is_common;
-	bool is_cck;
-	bool is_ht40;
-	u8 iwl_eeprom_section_channel[EEPROM_MAX_TXPOWER_SECTION_ELEMENTS];
-};
-
-/**
- * section 1 - 3 are regulatory tx power apply to all channels based on
- *    modulation: CCK, OFDM
- *    Band: 2.4GHz, 5.2GHz
- * section 4 - 10 are regulatory tx power apply to specified channels
- *    For example:
- *	1L - Channel 1 Legacy
- *	1HT - Channel 1 HT
- *	(1,+1) - Channel 1 HT40 "_above_"
- *
- * Section 1: all CCK channels
- * Section 2: all 2.4 GHz OFDM (Legacy, HT and HT40) channels
- * Section 3: all 5.2 GHz OFDM (Legacy, HT and HT40) channels
- * Section 4: 2.4 GHz 20MHz channels: 1L, 1HT, 2L, 2HT, 10L, 10HT, 11L, 11HT
- * Section 5: 2.4 GHz 40MHz channels: (1,+1) (2,+1) (6,+1) (7,+1) (9,+1)
- * Section 6: 5.2 GHz 20MHz channels: 36L, 64L, 100L, 36HT, 64HT, 100HT
- * Section 7: 5.2 GHz 40MHz channels: (36,+1) (60,+1) (100,+1)
- * Section 8: 2.4 GHz channel: 13L, 13HT
- * Section 9: 2.4 GHz channel: 140L, 140HT
- * Section 10: 2.4 GHz 40MHz channels: (132,+1)  (44,+1)
- *
- */
-static const struct iwl_txpwr_section enhinfo[] = {
-	{ EEPROM_LB_CCK_20_COMMON, 1, IEEE80211_BAND_2GHZ, true, true, false },
-	{ EEPROM_LB_OFDM_COMMON, 3, IEEE80211_BAND_2GHZ, true, false, false },
-	{ EEPROM_HB_OFDM_COMMON, 3, IEEE80211_BAND_5GHZ, true, false, false },
-	{ EEPROM_LB_OFDM_20_BAND, 8, IEEE80211_BAND_2GHZ,
-		false, false, false,
-		{1, 1, 2, 2, 10, 10, 11, 11 } },
-	{ EEPROM_LB_OFDM_HT40_BAND, 5, IEEE80211_BAND_2GHZ,
-		false, false, true,
-		{ 1, 2, 6, 7, 9 } },
-	{ EEPROM_HB_OFDM_20_BAND, 6, IEEE80211_BAND_5GHZ,
-		false, false, false,
-		{ 36, 64, 100, 36, 64, 100 } },
-	{ EEPROM_HB_OFDM_HT40_BAND, 3, IEEE80211_BAND_5GHZ,
-		false, false, true,
-		{ 36, 60, 100 } },
-	{ EEPROM_LB_OFDM_20_CHANNEL_13, 2, IEEE80211_BAND_2GHZ,
-		false, false, false,
-		{ 13, 13 } },
-	{ EEPROM_HB_OFDM_20_CHANNEL_140, 2, IEEE80211_BAND_5GHZ,
-		false, false, false,
-		{ 140, 140 } },
-	{ EEPROM_HB_OFDM_HT40_BAND_1, 2, IEEE80211_BAND_5GHZ,
-		false, false, true,
-		{ 132, 44 } },
-};
-
 /******************************************************************************
  *
  * EEPROM related functions
@@ -248,6 +145,50 @@ err:
 
 }
 
+int iwl_eeprom_check_sku(struct iwl_priv *priv)
+{
+	u16 eeprom_sku;
+	u16 radio_cfg;
+
+	eeprom_sku = iwl_eeprom_query16(priv, EEPROM_SKU_CAP);
+
+	if (!priv->cfg->sku) {
+		/* not using sku overwrite */
+		priv->cfg->sku =
+			((eeprom_sku & EEPROM_SKU_CAP_BAND_SELECTION) >>
+			EEPROM_SKU_CAP_BAND_POS);
+		if (eeprom_sku & EEPROM_SKU_CAP_11N_ENABLE)
+			priv->cfg->sku |= IWL_SKU_N;
+	}
+	if (!priv->cfg->sku) {
+		IWL_ERR(priv, "Invalid device sku\n");
+		return -EINVAL;
+	}
+
+	IWL_INFO(priv, "Device SKU: 0X%x\n", priv->cfg->sku);
+
+	if (!priv->cfg->valid_tx_ant && !priv->cfg->valid_rx_ant) {
+		/* not using .cfg overwrite */
+		radio_cfg = iwl_eeprom_query16(priv, EEPROM_RADIO_CONFIG);
+		priv->cfg->valid_tx_ant = EEPROM_RF_CFG_TX_ANT_MSK(radio_cfg);
+		priv->cfg->valid_rx_ant = EEPROM_RF_CFG_RX_ANT_MSK(radio_cfg);
+		if (!priv->cfg->valid_tx_ant || !priv->cfg->valid_rx_ant) {
+			IWL_ERR(priv, "Invalid chain (0X%x, 0X%x)\n",
+				priv->cfg->valid_tx_ant,
+				priv->cfg->valid_rx_ant);
+			return -EINVAL;
+		}
+		IWL_INFO(priv, "Valid Tx ant: 0X%x, Valid Rx ant: 0X%x\n",
+			 priv->cfg->valid_tx_ant, priv->cfg->valid_rx_ant);
+	}
+	/*
+	 * for some special cases,
+	 * EEPROM did not reflect the correct antenna setting
+	 * so overwrite the valid tx/rx antenna from .cfg
+	 */
+	return 0;
+}
+
 void iwl_eeprom_get_mac(const struct iwl_priv *priv, u8 *mac)
 {
 	const u8 *addr = priv->cfg->ops->lib->eeprom_ops.query_addr(priv,
@@ -265,15 +206,6 @@ static s8 iwl_get_max_txpower_avg(struct
 {
 	s8 max_txpower_avg = 0; /* (dBm) */
 
-	IWL_DEBUG_INFO(priv, "%d - "
-			"chain_a: %d dB chain_b: %d dB "
-			"chain_c: %d dB mimo2: %d dB mimo3: %d dB\n",
-			element,
-			enhanced_txpower[element].chain_a_max >> 1,
-			enhanced_txpower[element].chain_b_max >> 1,
-			enhanced_txpower[element].chain_c_max >> 1,
-			enhanced_txpower[element].mimo2_max >> 1,
-			enhanced_txpower[element].mimo3_max >> 1);
 	/* Take the highest tx power from any valid chains */
 	if ((priv->cfg->valid_tx_ant & ANT_A) &&
 	    (enhanced_txpower[element].chain_a_max > max_txpower_avg))
@@ -303,157 +235,6 @@ static s8 iwl_get_max_txpower_avg(struct
 	return (max_txpower_avg & 0x01) + (max_txpower_avg >> 1);
 }
 
-/**
- * iwl_update_common_txpower: update channel tx power
- *     update tx power per band based on EEPROM enhanced tx power info.
- */
-static s8 iwl_update_common_txpower(struct iwl_priv *priv,
-		struct iwl_eeprom_enhanced_txpwr *enhanced_txpower,
-		int section, int element, s8 *max_txpower_in_half_dbm)
-{
-	struct iwl_channel_info *ch_info;
-	int ch;
-	bool is_ht40 = false;
-	s8 max_txpower_avg; /* (dBm) */
-
-	/* it is common section, contain all type (Legacy, HT and HT40)
-	 * based on the element in the section to determine
-	 * is it HT 40 or not
-	 */
-	if (element == EEPROM_TXPOWER_COMMON_HT40_INDEX)
-		is_ht40 = true;
-	max_txpower_avg =
-		iwl_get_max_txpower_avg(priv, enhanced_txpower,
-					element, max_txpower_in_half_dbm);
-
-	ch_info = priv->channel_info;
-
-	for (ch = 0; ch < priv->channel_count; ch++) {
-		/* find matching band and update tx power if needed */
-		if ((ch_info->band == enhinfo[section].band) &&
-		    (ch_info->max_power_avg < max_txpower_avg) &&
-		    (!is_ht40)) {
-			/* Update regulatory-based run-time data */
-			ch_info->max_power_avg = ch_info->curr_txpow =
-				max_txpower_avg;
-			ch_info->scan_power = max_txpower_avg;
-		}
-		if ((ch_info->band == enhinfo[section].band) && is_ht40 &&
-		    (ch_info->ht40_max_power_avg < max_txpower_avg)) {
-			/* Update regulatory-based run-time data */
-			ch_info->ht40_max_power_avg = max_txpower_avg;
-		}
-		ch_info++;
-	}
-	return max_txpower_avg;
-}
-
-/**
- * iwl_update_channel_txpower: update channel tx power
- *      update channel tx power based on EEPROM enhanced tx power info.
- */
-static s8 iwl_update_channel_txpower(struct iwl_priv *priv,
-		struct iwl_eeprom_enhanced_txpwr *enhanced_txpower,
-		int section, int element, s8 *max_txpower_in_half_dbm)
-{
-	struct iwl_channel_info *ch_info;
-	int ch;
-	u8 channel;
-	s8 max_txpower_avg; /* (dBm) */
-
-	channel = enhinfo[section].iwl_eeprom_section_channel[element];
-	max_txpower_avg =
-		iwl_get_max_txpower_avg(priv, enhanced_txpower,
-					element, max_txpower_in_half_dbm);
-
-	ch_info = priv->channel_info;
-	for (ch = 0; ch < priv->channel_count; ch++) {
-		/* find matching channel and update tx power if needed */
-		if (ch_info->channel == channel) {
-			if ((ch_info->max_power_avg < max_txpower_avg) &&
-			    (!enhinfo[section].is_ht40)) {
-				/* Update regulatory-based run-time data */
-				ch_info->max_power_avg = max_txpower_avg;
-				ch_info->curr_txpow = max_txpower_avg;
-				ch_info->scan_power = max_txpower_avg;
-			}
-			if ((enhinfo[section].is_ht40) &&
-			    (ch_info->ht40_max_power_avg < max_txpower_avg)) {
-				/* Update regulatory-based run-time data */
-				ch_info->ht40_max_power_avg = max_txpower_avg;
-			}
-			break;
-		}
-		ch_info++;
-	}
-	return max_txpower_avg;
-}
-
-/**
- * iwlcore_eeprom_enhanced_txpower: process enhanced tx power info
- */
-static void iwlcore_eeprom_enhanced_txpower_old(struct iwl_priv *priv)
-{
-	int eeprom_section_count = 0;
-	int section, element;
-	struct iwl_eeprom_enhanced_txpwr *enhanced_txpower;
-	u32 offset;
-	s8 max_txpower_avg; /* (dBm) */
-	s8 max_txpower_in_half_dbm; /* (half-dBm) */
-
-	/* Loop through all the sections
-	 * adjust bands and channel's max tx power
-	 * Set the tx_power_user_lmt to the highest power
-	 * supported by any channels and chains
-	 */
-	for (section = 0; section < ARRAY_SIZE(enhinfo); section++) {
-		eeprom_section_count = enhinfo[section].count;
-		offset = enhinfo[section].offset;
-		enhanced_txpower = (struct iwl_eeprom_enhanced_txpwr *)
-				iwl_eeprom_query_addr(priv, offset);
-
-		/*
-		 * check for valid entry -
-		 * different version of EEPROM might contain different set
-		 * of enhanced tx power table
-		 * always check for valid entry before process
-		 * the information
-		 */
-		if (!(enhanced_txpower->flags || enhanced_txpower->channel) ||
-		    enhanced_txpower->delta_20_in_40)
-			continue;
-
-		for (element = 0; element < eeprom_section_count; element++) {
-			if (enhinfo[section].is_common)
-				max_txpower_avg =
-					iwl_update_common_txpower(priv,
-						enhanced_txpower, section,
-						element,
-						&max_txpower_in_half_dbm);
-			else
-				max_txpower_avg =
-					iwl_update_channel_txpower(priv,
-						enhanced_txpower, section,
-						element,
-						&max_txpower_in_half_dbm);
-
-			/* Update the tx_power_user_lmt to the highest power
-			 * supported by any channel */
-			if (max_txpower_avg > priv->tx_power_user_lmt)
-				priv->tx_power_user_lmt = max_txpower_avg;
-
-			/*
-			 * Update the tx_power_lmt_in_half_dbm to
-			 * the highest power supported by any channel
-			 */
-			if (max_txpower_in_half_dbm >
-			    priv->tx_power_lmt_in_half_dbm)
-				priv->tx_power_lmt_in_half_dbm =
-					max_txpower_in_half_dbm;
-		}
-	}
-}
-
 static void
 iwlcore_eeprom_enh_txp_read_element(struct iwl_priv *priv,
 				    struct iwl_eeprom_enhanced_txpwr *txp,
@@ -492,7 +273,10 @@ iwlcore_eeprom_enh_txp_read_element(stru
 #define EEPROM_TXP_ENTRY_LEN sizeof(struct iwl_eeprom_enhanced_txpwr)
 #define EEPROM_TXP_SZ_OFFS (0x00 | INDIRECT_ADDRESS | INDIRECT_TXP_LIMIT_SIZE)
 
-static void iwlcore_eeprom_enhanced_txpower_new(struct iwl_priv *priv)
+#define TXP_CHECK_AND_PRINT(x) ((txp->flags & IWL_EEPROM_ENH_TXP_FL_##x) \
+			    ? # x " " : "")
+
+void iwlcore_eeprom_enhanced_txpower(struct iwl_priv *priv)
 {
 	struct iwl_eeprom_enhanced_txpwr *txp_array, *txp;
 	int idx, entries;
@@ -506,13 +290,39 @@ static void iwlcore_eeprom_enhanced_txpo
 	entries = le16_to_cpup(txp_len) * 2 / EEPROM_TXP_ENTRY_LEN;
 
 	txp_array = (void *) iwlagn_eeprom_query_addr(priv, EEPROM_TXP_OFFS);
+
 	for (idx = 0; idx < entries; idx++) {
 		txp = &txp_array[idx];
-
 		/* skip invalid entries */
 		if (!(txp->flags & IWL_EEPROM_ENH_TXP_FL_VALID))
 			continue;
 
+		IWL_DEBUG_EEPROM(priv, "%s %d:\t %s%s%s%s%s%s%s%s (0x%02x)\n",
+				 (txp->channel && (txp->flags &
+					IWL_EEPROM_ENH_TXP_FL_COMMON_TYPE)) ?
+					"Common " : (txp->channel) ?
+					"Channel" : "Common",
+				 (txp->channel),
+				 TXP_CHECK_AND_PRINT(VALID),
+				 TXP_CHECK_AND_PRINT(BAND_52G),
+				 TXP_CHECK_AND_PRINT(OFDM),
+				 TXP_CHECK_AND_PRINT(40MHZ),
+				 TXP_CHECK_AND_PRINT(HT_AP),
+				 TXP_CHECK_AND_PRINT(RES1),
+				 TXP_CHECK_AND_PRINT(RES2),
+				 TXP_CHECK_AND_PRINT(COMMON_TYPE),
+				 txp->flags);
+		IWL_DEBUG_EEPROM(priv, "\t\t chain_A: 0x%02x "
+				 "chain_B: 0X%02x chain_C: 0X%02x\n",
+				 txp->chain_a_max, txp->chain_b_max,
+				 txp->chain_c_max);
+		IWL_DEBUG_EEPROM(priv, "\t\t MIMO2: 0x%02x "
+				 "MIMO3: 0x%02x High 20_on_40: 0x%02x "
+				 "Low 20_on_40: 0x%02x\n",
+				 txp->mimo2_max, txp->mimo3_max,
+				 ((txp->delta_20_in_40 & 0xf0) >> 4),
+				 (txp->delta_20_in_40 & 0x0f));
+
 		max_txp_avg = iwl_get_max_txpower_avg(priv, txp_array, idx,
 						      &max_txp_avg_halfdbm);
 
@@ -528,11 +338,3 @@ static void iwlcore_eeprom_enhanced_txpo
 		iwlcore_eeprom_enh_txp_read_element(priv, txp, max_txp_avg);
 	}
 }
-
-void iwlcore_eeprom_enhanced_txpower(struct iwl_priv *priv)
-{
-	if (priv->cfg->use_new_eeprom_reading)
-		iwlcore_eeprom_enhanced_txpower_new(priv);
-	else
-		iwlcore_eeprom_enhanced_txpower_old(priv);
-}
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/iwlwifi/iwl-agn.h linux-libre-2.6.38-gnu1/drivers/net/wireless/iwlwifi/iwl-agn.h
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/iwlwifi/iwl-agn.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/iwlwifi/iwl-agn.h	2011-03-14 21:20:32.000000000 -0400
@@ -74,22 +74,22 @@ extern struct iwl_cfg iwl5100_bgn_cfg;
 extern struct iwl_cfg iwl5100_abg_cfg;
 extern struct iwl_cfg iwl5150_agn_cfg;
 extern struct iwl_cfg iwl5150_abg_cfg;
-extern struct iwl_cfg iwl6000g2a_2agn_cfg;
-extern struct iwl_cfg iwl6000g2a_2abg_cfg;
-extern struct iwl_cfg iwl6000g2a_2bg_cfg;
-extern struct iwl_cfg iwl6000g2b_bgn_cfg;
-extern struct iwl_cfg iwl6000g2b_bg_cfg;
-extern struct iwl_cfg iwl6000g2b_2agn_cfg;
-extern struct iwl_cfg iwl6000g2b_2abg_cfg;
-extern struct iwl_cfg iwl6000g2b_2bgn_cfg;
-extern struct iwl_cfg iwl6000g2b_2bg_cfg;
+extern struct iwl_cfg iwl6005_2agn_cfg;
+extern struct iwl_cfg iwl6005_2abg_cfg;
+extern struct iwl_cfg iwl6005_2bg_cfg;
+extern struct iwl_cfg iwl1030_bgn_cfg;
+extern struct iwl_cfg iwl1030_bg_cfg;
+extern struct iwl_cfg iwl6030_2agn_cfg;
+extern struct iwl_cfg iwl6030_2abg_cfg;
+extern struct iwl_cfg iwl6030_2bgn_cfg;
+extern struct iwl_cfg iwl6030_2bg_cfg;
 extern struct iwl_cfg iwl6000i_2agn_cfg;
 extern struct iwl_cfg iwl6000i_2abg_cfg;
 extern struct iwl_cfg iwl6000i_2bg_cfg;
 extern struct iwl_cfg iwl6000_3agn_cfg;
 extern struct iwl_cfg iwl6050_2agn_cfg;
 extern struct iwl_cfg iwl6050_2abg_cfg;
-extern struct iwl_cfg iwl6050g2_bgn_cfg;
+extern struct iwl_cfg iwl6150_bgn_cfg;
 extern struct iwl_cfg iwl1000_bgn_cfg;
 extern struct iwl_cfg iwl1000_bg_cfg;
 extern struct iwl_cfg iwl100_bgn_cfg;
@@ -102,6 +102,9 @@ extern struct iwl_hcmd_ops iwlagn_hcmd;
 extern struct iwl_hcmd_ops iwlagn_bt_hcmd;
 extern struct iwl_hcmd_utils_ops iwlagn_hcmd_utils;
 
+extern struct ieee80211_ops iwlagn_hw_ops;
+extern struct ieee80211_ops iwl4965_hw_ops;
+
 int iwl_reset_ict(struct iwl_priv *priv);
 void iwl_disable_ict(struct iwl_priv *priv);
 int iwl_alloc_isr_ict(struct iwl_priv *priv);
@@ -132,6 +135,11 @@ void iwl_free_tfds_in_queue(struct iwl_p
 /* RXON */
 int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx);
 void iwlagn_set_rxon_chain(struct iwl_priv *priv, struct iwl_rxon_context *ctx);
+int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed);
+void iwlagn_bss_info_changed(struct ieee80211_hw *hw,
+			     struct ieee80211_vif *vif,
+			     struct ieee80211_bss_conf *bss_conf,
+			     u32 changes);
 
 /* uCode */
 int iwlagn_load_ucode(struct iwl_priv *priv);
@@ -249,6 +257,7 @@ int iwlagn_manage_ibss_station(struct iw
 int iwlagn_send_rxon_assoc(struct iwl_priv *priv,
 			   struct iwl_rxon_context *ctx);
 int iwlagn_send_tx_ant_config(struct iwl_priv *priv, u8 valid_tx_ant);
+int iwlagn_send_beacon_cmd(struct iwl_priv *priv);
 
 /* bt coex */
 void iwlagn_send_advance_bt_config(struct iwl_priv *priv);
@@ -292,9 +301,12 @@ int iwl_sta_rx_agg_start(struct iwl_priv
 			 int tid, u16 ssn);
 int iwl_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta,
 			int tid);
-void iwl_sta_modify_ps_wake(struct iwl_priv *priv, int sta_id);
 void iwl_sta_modify_sleep_tx_count(struct iwl_priv *priv, int sta_id, int cnt);
 int iwl_update_bcast_stations(struct iwl_priv *priv);
+void iwlagn_mac_sta_notify(struct ieee80211_hw *hw,
+			   struct ieee80211_vif *vif,
+			   enum sta_notify_cmd cmd,
+			   struct ieee80211_sta *sta);
 
 /* rate */
 static inline u32 iwl_ant_idx_to_flags(u8 ant_idx)
@@ -318,4 +330,31 @@ void iwl_eeprom_get_mac(const struct iwl
 int iwlcore_eeprom_acquire_semaphore(struct iwl_priv *priv);
 void iwlcore_eeprom_release_semaphore(struct iwl_priv *priv);
 
+/* mac80211 handlers (for 4965) */
+int iwlagn_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb);
+int iwlagn_mac_start(struct ieee80211_hw *hw);
+void iwlagn_mac_stop(struct ieee80211_hw *hw);
+void iwlagn_configure_filter(struct ieee80211_hw *hw,
+			     unsigned int changed_flags,
+			     unsigned int *total_flags,
+			     u64 multicast);
+int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
+		       struct ieee80211_vif *vif, struct ieee80211_sta *sta,
+		       struct ieee80211_key_conf *key);
+void iwlagn_mac_update_tkip_key(struct ieee80211_hw *hw,
+				struct ieee80211_vif *vif,
+				struct ieee80211_key_conf *keyconf,
+				struct ieee80211_sta *sta,
+				u32 iv32, u16 *phase1key);
+int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw,
+			    struct ieee80211_vif *vif,
+			    enum ieee80211_ampdu_mlme_action action,
+			    struct ieee80211_sta *sta, u16 tid, u16 *ssn);
+int iwlagn_mac_sta_add(struct ieee80211_hw *hw,
+		       struct ieee80211_vif *vif,
+		       struct ieee80211_sta *sta);
+void iwlagn_mac_channel_switch(struct ieee80211_hw *hw,
+			       struct ieee80211_channel_switch *ch_switch);
+void iwlagn_mac_flush(struct ieee80211_hw *hw, bool drop);
+
 #endif /* __iwl_agn_h__ */
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c linux-libre-2.6.38-gnu1/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c	2011-03-14 21:20:32.000000000 -0400
@@ -307,6 +307,7 @@ static int iwlagn_set_pan_params(struct
 
 	if (ctx_bss->vif && ctx_pan->vif) {
 		int bcnint = ctx_pan->vif->bss_conf.beacon_int;
+		int dtim = ctx_pan->vif->bss_conf.dtim_period ?: 1;
 
 		/* should be set, but seems unused?? */
 		cmd.flags |= cpu_to_le16(IWL_WIPAN_PARAMS_FLG_SLOTTED_MODE);
@@ -329,10 +330,10 @@ static int iwlagn_set_pan_params(struct
 		if (test_bit(STATUS_SCAN_HW, &priv->status) ||
 		    (!ctx_bss->vif->bss_conf.idle &&
 		     !ctx_bss->vif->bss_conf.assoc)) {
-			slot0 = bcnint * 3 - 20;
+			slot0 = dtim * bcnint * 3 - 20;
 			slot1 = 20;
 		} else if (!ctx_pan->vif->bss_conf.idle &&
-                           !ctx_pan->vif->bss_conf.assoc) {
+			   !ctx_pan->vif->bss_conf.assoc) {
 			slot1 = bcnint * 3 - 20;
 			slot0 = 20;
 		}
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/iwlwifi/iwl-agn-ict.c linux-libre-2.6.38-gnu1/drivers/net/wireless/iwlwifi/iwl-agn-ict.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/iwlwifi/iwl-agn-ict.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/iwlwifi/iwl-agn-ict.c	2011-03-14 21:20:32.000000000 -0400
@@ -197,7 +197,7 @@ static irqreturn_t iwl_isr(int irq, void
 
  none:
 	/* re-enable interrupts here since we don't have anything to service. */
-	/* only Re-enable if diabled by irq  and no schedules tasklet. */
+	/* only Re-enable if disabled by irq  and no schedules tasklet. */
 	if (test_bit(STATUS_INT_ENABLED, &priv->status) && !priv->_agn.inta)
 		iwl_enable_interrupts(priv);
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/iwlwifi/iwl-agn-lib.c linux-libre-2.6.38-gnu1/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/iwlwifi/iwl-agn-lib.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/iwlwifi/iwl-agn-lib.c	2011-03-14 21:20:32.000000000 -0400
@@ -405,6 +405,7 @@ static void iwlagn_rx_reply_tx(struct iw
 		return;
 	}
 
+	txq->time_stamp = jiffies;
 	info = IEEE80211_SKB_CB(txq->txb[txq->q.read_ptr].skb);
 	memset(&info->status, 0, sizeof(info->status));
 
@@ -445,22 +446,17 @@ static void iwlagn_rx_reply_tx(struct iw
 
 			if (priv->mac80211_registered &&
 			    (iwl_queue_space(&txq->q) > txq->q.low_mark) &&
-			    (agg->state != IWL_EMPTYING_HW_QUEUE_DELBA)) {
-				if (agg->state == IWL_AGG_OFF)
-					iwl_wake_queue(priv, txq_id);
-				else
-					iwl_wake_queue(priv, txq->swq_id);
-			}
+			    (agg->state != IWL_EMPTYING_HW_QUEUE_DELBA))
+				iwl_wake_queue(priv, txq);
 		}
 	} else {
-		BUG_ON(txq_id != txq->swq_id);
 		iwlagn_set_tx_status(priv, info, tx_resp, txq_id, false);
 		freed = iwlagn_tx_queue_reclaim(priv, txq_id, index);
 		iwl_free_tfds_in_queue(priv, sta_id, tid, freed);
 
 		if (priv->mac80211_registered &&
 		    (iwl_queue_space(&txq->q) > txq->q.low_mark))
-			iwl_wake_queue(priv, txq_id);
+			iwl_wake_queue(priv, txq);
 	}
 
 	iwlagn_txq_check_empty(priv, sta_id, tid, txq_id);
@@ -496,6 +492,10 @@ int iwlagn_send_tx_power(struct iwl_priv
 	struct iwlagn_tx_power_dbm_cmd tx_power_cmd;
 	u8 tx_ant_cfg_cmd;
 
+	if (WARN_ONCE(test_bit(STATUS_SCAN_HW, &priv->status),
+		      "TX Power requested while scanning!\n"))
+		return -EAGAIN;
+
 	/* half dBm need to multiply */
 	tx_power_cmd.global_lmt = (s8)(2 * priv->tx_power_user_lmt);
 
@@ -522,9 +522,8 @@ int iwlagn_send_tx_power(struct iwl_priv
 	else
 		tx_ant_cfg_cmd = REPLY_TX_POWER_DBM_CMD;
 
-	return  iwl_send_cmd_pdu_async(priv, tx_ant_cfg_cmd,
-				       sizeof(tx_power_cmd), &tx_power_cmd,
-				       NULL);
+	return iwl_send_cmd_pdu(priv, tx_ant_cfg_cmd, sizeof(tx_power_cmd),
+				&tx_power_cmd);
 }
 
 void iwlagn_temperature(struct iwl_priv *priv)
@@ -756,6 +755,12 @@ int iwlagn_hw_nic_init(struct iwl_priv *
 	} else
 		iwlagn_txq_ctx_reset(priv);
 
+	if (priv->cfg->base_params->shadow_reg_enable) {
+		/* enable shadow regs in HW */
+		iwl_set_bit(priv, CSR_MAC_SHADOW_REG_CTRL,
+			0x800FFFFF);
+	}
+
 	set_bit(STATUS_INIT, &priv->status);
 
 	return 0;
@@ -1487,15 +1492,11 @@ int iwlagn_request_scan(struct iwl_priv
 	if (priv->cfg->scan_rx_antennas[band])
 		rx_ant = priv->cfg->scan_rx_antennas[band];
 
-	if (priv->cfg->scan_tx_antennas[band])
-		scan_tx_antennas = priv->cfg->scan_tx_antennas[band];
-
-	if (priv->cfg->bt_params &&
-	    priv->cfg->bt_params->advanced_bt_coexist &&
-	    priv->bt_full_concurrent) {
-		/* operated as 1x1 in full concurrency mode */
-		scan_tx_antennas = first_antenna(
-			priv->cfg->scan_tx_antennas[band]);
+	if (band == IEEE80211_BAND_2GHZ &&
+	    priv->cfg->bt_params &&
+	    priv->cfg->bt_params->advanced_bt_coexist) {
+		/* transmit 2.4 GHz probes only on first antenna */
+		scan_tx_antennas = first_antenna(scan_tx_antennas);
 	}
 
 	priv->scan_tx_ant[band] = iwl_toggle_tx_ant(priv, priv->scan_tx_ant[band],
@@ -1590,22 +1591,6 @@ int iwlagn_request_scan(struct iwl_priv
 	return ret;
 }
 
-void iwlagn_post_scan(struct iwl_priv *priv)
-{
-	struct iwl_rxon_context *ctx;
-
-	/*
-	 * Since setting the RXON may have been deferred while
-	 * performing the scan, fire one off if needed
-	 */
-	for_each_context(priv, ctx)
-		if (memcmp(&ctx->staging, &ctx->active, sizeof(ctx->staging)))
-			iwlagn_commit_rxon(priv, ctx);
-
-	if (priv->cfg->ops->hcmd->set_pan_params)
-		priv->cfg->ops->hcmd->set_pan_params(priv);
-}
-
 int iwlagn_manage_ibss_station(struct iwl_priv *priv,
 			       struct ieee80211_vif *vif, bool add)
 {
@@ -1796,7 +1781,7 @@ static const __le32 iwlagn_def_3w_lookup
 	cpu_to_le32(0xc0004000),
 	cpu_to_le32(0x00004000),
 	cpu_to_le32(0xf0005000),
-	cpu_to_le32(0xf0004000),
+	cpu_to_le32(0xf0005000),
 };
 
 static const __le32 iwlagn_concurrent_lookup[12] = {
@@ -1832,6 +1817,7 @@ void iwlagn_send_advance_bt_config(struc
 		bt_cmd.prio_boost = 0;
 	bt_cmd.kill_ack_mask = priv->kill_ack_mask;
 	bt_cmd.kill_cts_mask = priv->kill_cts_mask;
+
 	bt_cmd.valid = priv->bt_valid;
 	bt_cmd.tx_prio_boost = 0;
 	bt_cmd.rx_prio_boost = 0;
@@ -1847,10 +1833,15 @@ void iwlagn_send_advance_bt_config(struc
 	} else {
 		bt_cmd.flags = IWLAGN_BT_FLAG_COEX_MODE_3W <<
 					IWLAGN_BT_FLAG_COEX_MODE_SHIFT;
+		if (priv->cfg->bt_params &&
+		    priv->cfg->bt_params->bt_sco_disable)
+			bt_cmd.flags |= IWLAGN_BT_FLAG_SYNC_2_BT_DISABLE;
+
 		if (priv->bt_ch_announce)
 			bt_cmd.flags |= IWLAGN_BT_FLAG_CHANNEL_INHIBITION;
 		IWL_DEBUG_INFO(priv, "BT coex flag: 0X%x\n", bt_cmd.flags);
 	}
+	priv->bt_enable_flag = bt_cmd.flags;
 	if (priv->bt_full_concurrent)
 		memcpy(bt_cmd.bt3_lookup_table, iwlagn_concurrent_lookup,
 			sizeof(iwlagn_concurrent_lookup));
@@ -1890,12 +1881,20 @@ static void iwlagn_bt_traffic_change_wor
 	struct iwl_rxon_context *ctx;
 	int smps_request = -1;
 
+	/*
+	 * Note: bt_traffic_load can be overridden by scan complete and
+	 * coex profile notifications. Ignore that since only bad consequence
+	 * can be not matching debug print with actual state.
+	 */
 	IWL_DEBUG_INFO(priv, "BT traffic load changes: %d\n",
 		       priv->bt_traffic_load);
 
 	switch (priv->bt_traffic_load) {
 	case IWL_BT_COEX_TRAFFIC_LOAD_NONE:
-		smps_request = IEEE80211_SMPS_AUTOMATIC;
+		if (priv->bt_status)
+			smps_request = IEEE80211_SMPS_DYNAMIC;
+		else
+			smps_request = IEEE80211_SMPS_AUTOMATIC;
 		break;
 	case IWL_BT_COEX_TRAFFIC_LOAD_LOW:
 		smps_request = IEEE80211_SMPS_DYNAMIC;
@@ -1912,6 +1911,16 @@ static void iwlagn_bt_traffic_change_wor
 
 	mutex_lock(&priv->mutex);
 
+	/*
+	 * We can not send command to firmware while scanning. When the scan
+	 * complete we will schedule this work again. We do check with mutex
+	 * locked to prevent new scan request to arrive. We do not check
+	 * STATUS_SCANNING to avoid race when queue_work two times from
+	 * different notifications, but quit and not perform any work at all.
+	 */
+	if (test_bit(STATUS_SCAN_HW, &priv->status))
+		goto out;
+
 	if (priv->cfg->ops->lib->update_chain_flags)
 		priv->cfg->ops->lib->update_chain_flags(priv);
 
@@ -1921,7 +1930,7 @@ static void iwlagn_bt_traffic_change_wor
 				ieee80211_request_smps(ctx->vif, smps_request);
 		}
 	}
-
+out:
 	mutex_unlock(&priv->mutex);
 }
 
@@ -1992,24 +2001,29 @@ static void iwlagn_print_uartmsg(struct
 			BT_UART_MSG_FRAME7CONNECTABLE_POS);
 }
 
-static void iwlagn_set_kill_ack_msk(struct iwl_priv *priv,
-				     struct iwl_bt_uart_msg *uart_msg)
+static void iwlagn_set_kill_msk(struct iwl_priv *priv,
+				struct iwl_bt_uart_msg *uart_msg)
 {
-	u8 kill_ack_msk;
-	__le32 bt_kill_ack_msg[2] = {
-			cpu_to_le32(0xFFFFFFF), cpu_to_le32(0xFFFFFC00) };
+	u8 kill_msk;
+	static const __le32 bt_kill_ack_msg[2] = {
+		IWLAGN_BT_KILL_ACK_MASK_DEFAULT,
+		IWLAGN_BT_KILL_ACK_CTS_MASK_SCO };
+	static const __le32 bt_kill_cts_msg[2] = {
+		IWLAGN_BT_KILL_CTS_MASK_DEFAULT,
+		IWLAGN_BT_KILL_ACK_CTS_MASK_SCO };
 
-	kill_ack_msk = (((BT_UART_MSG_FRAME3A2DP_MSK |
-			BT_UART_MSG_FRAME3SNIFF_MSK |
-			BT_UART_MSG_FRAME3SCOESCO_MSK) &
-			uart_msg->frame3) == 0) ? 1 : 0;
-	if (priv->kill_ack_mask != bt_kill_ack_msg[kill_ack_msk]) {
+	kill_msk = (BT_UART_MSG_FRAME3SCOESCO_MSK & uart_msg->frame3)
+		? 1 : 0;
+	if (priv->kill_ack_mask != bt_kill_ack_msg[kill_msk] ||
+	    priv->kill_cts_mask != bt_kill_cts_msg[kill_msk]) {
 		priv->bt_valid |= IWLAGN_BT_VALID_KILL_ACK_MASK;
-		priv->kill_ack_mask = bt_kill_ack_msg[kill_ack_msk];
+		priv->kill_ack_mask = bt_kill_ack_msg[kill_msk];
+		priv->bt_valid |= IWLAGN_BT_VALID_KILL_CTS_MASK;
+		priv->kill_cts_mask = bt_kill_cts_msg[kill_msk];
+
 		/* schedule to send runtime bt_config */
 		queue_work(priv->workqueue, &priv->bt_runtime_config);
 	}
-
 }
 
 void iwlagn_bt_coex_profile_notif(struct iwl_priv *priv,
@@ -2020,7 +2034,6 @@ void iwlagn_bt_coex_profile_notif(struct
 	struct iwl_bt_coex_profile_notif *coex = &pkt->u.bt_coex_profile_notif;
 	struct iwlagn_bt_sco_cmd sco_cmd = { .flags = 0 };
 	struct iwl_bt_uart_msg *uart_msg = &coex->last_bt_uart_msg;
-	u8 last_traffic_load;
 
 	IWL_DEBUG_NOTIF(priv, "BT Coex notification:\n");
 	IWL_DEBUG_NOTIF(priv, "    status: %d\n", coex->bt_status);
@@ -2029,11 +2042,10 @@ void iwlagn_bt_coex_profile_notif(struct
 			coex->bt_ci_compliance);
 	iwlagn_print_uartmsg(priv, uart_msg);
 
-	last_traffic_load = priv->notif_bt_traffic_load;
-	priv->notif_bt_traffic_load = coex->bt_traffic_load;
+	priv->last_bt_traffic_load = priv->bt_traffic_load;
 	if (priv->iw_mode != NL80211_IFTYPE_ADHOC) {
 		if (priv->bt_status != coex->bt_status ||
-		    last_traffic_load != coex->bt_traffic_load) {
+		    priv->last_bt_traffic_load != coex->bt_traffic_load) {
 			if (coex->bt_status) {
 				/* BT on */
 				if (!priv->bt_ch_announce)
@@ -2062,7 +2074,7 @@ void iwlagn_bt_coex_profile_notif(struct
 		}
 	}
 
-	iwlagn_set_kill_ack_msk(priv, uart_msg);
+	iwlagn_set_kill_msk(priv, uart_msg);
 
 	/* FIXME: based on notification, adjust the prio_boost */
 
@@ -2282,7 +2294,7 @@ static const char *get_csr_string(int cm
 void iwl_dump_csr(struct iwl_priv *priv)
 {
 	int i;
-	u32 csr_tbl[] = {
+	static const u32 csr_tbl[] = {
 		CSR_HW_IF_CONFIG_REG,
 		CSR_INT_COALESCING,
 		CSR_INT,
@@ -2341,7 +2353,7 @@ int iwl_dump_fh(struct iwl_priv *priv, c
 	int pos = 0;
 	size_t bufsz = 0;
 #endif
-	u32 fh_tbl[] = {
+	static const u32 fh_tbl[] = {
 		FH_RSCSR_CHNL0_STTS_WPTR_REG,
 		FH_RSCSR_CHNL0_RBDCB_BASE_REG,
 		FH_RSCSR_CHNL0_WPTR,
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/iwlwifi/iwl-agn-rs.c linux-libre-2.6.38-gnu1/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/iwlwifi/iwl-agn-rs.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/iwlwifi/iwl-agn-rs.c	2011-03-14 21:20:32.000000000 -0400
@@ -387,7 +387,7 @@ static int rs_tl_turn_on_agg_for_tid(str
 	if (load > IWL_AGG_LOAD_THRESHOLD) {
 		IWL_DEBUG_HT(priv, "Starting Tx agg: STA: %pM tid: %d\n",
 				sta->addr, tid);
-		ret = ieee80211_start_tx_ba_session(sta, tid);
+		ret = ieee80211_start_tx_ba_session(sta, tid, 5000);
 		if (ret == -EAGAIN) {
 			/*
 			 * driver and mac80211 is out of sync
@@ -833,17 +833,23 @@ static void rs_bt_update_lq(struct iwl_p
 			    struct iwl_lq_sta *lq_sta)
 {
 	struct iwl_scale_tbl_info *tbl;
-	bool full_concurrent;
+	bool full_concurrent = priv->bt_full_concurrent;
 	unsigned long flags;
 
-	spin_lock_irqsave(&priv->lock, flags);
-	if (priv->bt_ci_compliance && priv->bt_ant_couple_ok)
-		full_concurrent = true;
-	else
-		full_concurrent = false;
-	spin_unlock_irqrestore(&priv->lock, flags);
-
-	if (priv->bt_full_concurrent != full_concurrent) {
+	if (priv->bt_ant_couple_ok) {
+		/*
+		 * Is there a need to switch between
+		 * full concurrency and 3-wire?
+		 */
+		spin_lock_irqsave(&priv->lock, flags);
+		if (priv->bt_ci_compliance && priv->bt_ant_couple_ok)
+			full_concurrent = true;
+		else
+			full_concurrent = false;
+		spin_unlock_irqrestore(&priv->lock, flags);
+	}
+	if ((priv->bt_traffic_load != priv->last_bt_traffic_load) ||
+	    (priv->bt_full_concurrent != full_concurrent)) {
 		priv->bt_full_concurrent = full_concurrent;
 
 		/* Update uCode's rate table. */
@@ -1040,8 +1046,7 @@ done:
 	if (sta && sta->supp_rates[sband->band])
 		rs_rate_scale_perform(priv, skb, sta, lq_sta);
 
-	/* Is there a need to switch between full concurrency and 3-wire? */
-	if (priv->bt_ant_couple_ok)
+	if (priv->cfg->bt_params && priv->cfg->bt_params->advanced_bt_coexist)
 		rs_bt_update_lq(priv, ctx, lq_sta);
 }
 
@@ -2868,6 +2873,10 @@ void iwl_rs_rate_init(struct iwl_priv *p
 		lq_sta->last_txrate_idx += IWL_FIRST_OFDM_RATE;
 	lq_sta->is_agg = 0;
 
+#ifdef CONFIG_MAC80211_DEBUGFS
+	lq_sta->dbg_fixed_rate = 0;
+#endif
+
 	rs_initialize_lq(priv, conf, sta, lq_sta);
 }
 
@@ -3010,10 +3019,7 @@ static void rs_fill_link_cmd(struct iwl_
 	 */
 	if (priv && priv->cfg->bt_params &&
 	    priv->cfg->bt_params->agg_time_limit &&
-	    priv->cfg->bt_params->agg_time_limit >=
-		LINK_QUAL_AGG_TIME_LIMIT_MIN &&
-	    priv->cfg->bt_params->agg_time_limit <=
-		 LINK_QUAL_AGG_TIME_LIMIT_MAX)
+	    priv->bt_traffic_load >= IWL_BT_COEX_TRAFFIC_LOAD_HIGH)
 		lq_cmd->agg_params.agg_time_limit =
 			cpu_to_le16(priv->cfg->bt_params->agg_time_limit);
 }
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c linux-libre-2.6.38-gnu1/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,642 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License 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, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ *****************************************************************************/
+
+#include "iwl-dev.h"
+#include "iwl-agn.h"
+#include "iwl-sta.h"
+#include "iwl-core.h"
+#include "iwl-agn-calib.h"
+
+static int iwlagn_disable_bss(struct iwl_priv *priv,
+			      struct iwl_rxon_context *ctx,
+			      struct iwl_rxon_cmd *send)
+{
+	__le32 old_filter = send->filter_flags;
+	int ret;
+
+	send->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
+	ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd, sizeof(*send), send);
+
+	send->filter_flags = old_filter;
+
+	if (ret)
+		IWL_ERR(priv, "Error clearing ASSOC_MSK on BSS (%d)\n", ret);
+
+	return ret;
+}
+
+static int iwlagn_disable_pan(struct iwl_priv *priv,
+			      struct iwl_rxon_context *ctx,
+			      struct iwl_rxon_cmd *send)
+{
+	__le32 old_filter = send->filter_flags;
+	u8 old_dev_type = send->dev_type;
+	int ret;
+
+	send->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
+	send->dev_type = RXON_DEV_TYPE_P2P;
+	ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd, sizeof(*send), send);
+
+	send->filter_flags = old_filter;
+	send->dev_type = old_dev_type;
+
+	if (ret)
+		IWL_ERR(priv, "Error disabling PAN (%d)\n", ret);
+
+	/* FIXME: WAIT FOR PAN DISABLE */
+	msleep(300);
+
+	return ret;
+}
+
+static void iwlagn_update_qos(struct iwl_priv *priv,
+			      struct iwl_rxon_context *ctx)
+{
+	int ret;
+
+	if (!ctx->is_active)
+		return;
+
+	ctx->qos_data.def_qos_parm.qos_flags = 0;
+
+	if (ctx->qos_data.qos_active)
+		ctx->qos_data.def_qos_parm.qos_flags |=
+			QOS_PARAM_FLG_UPDATE_EDCA_MSK;
+
+	if (ctx->ht.enabled)
+		ctx->qos_data.def_qos_parm.qos_flags |= QOS_PARAM_FLG_TGN_MSK;
+
+	IWL_DEBUG_QOS(priv, "send QoS cmd with Qos active=%d FLAGS=0x%X\n",
+		      ctx->qos_data.qos_active,
+		      ctx->qos_data.def_qos_parm.qos_flags);
+
+	ret = iwl_send_cmd_pdu(priv, ctx->qos_cmd,
+			       sizeof(struct iwl_qosparam_cmd),
+			       &ctx->qos_data.def_qos_parm);
+	if (ret)
+		IWL_ERR(priv, "Failed to update QoS\n");
+}
+
+static int iwlagn_update_beacon(struct iwl_priv *priv,
+				struct ieee80211_vif *vif)
+{
+	lockdep_assert_held(&priv->mutex);
+
+	dev_kfree_skb(priv->beacon_skb);
+	priv->beacon_skb = ieee80211_beacon_get(priv->hw, vif);
+	if (!priv->beacon_skb)
+		return -ENOMEM;
+	return iwlagn_send_beacon_cmd(priv);
+}
+
+/**
+ * iwlagn_commit_rxon - commit staging_rxon to hardware
+ *
+ * The RXON command in staging_rxon is committed to the hardware and
+ * the active_rxon structure is updated with the new data.  This
+ * function correctly transitions out of the RXON_ASSOC_MSK state if
+ * a HW tune is required based on the RXON structure changes.
+ */
+int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
+{
+	/* cast away the const for active_rxon in this function */
+	struct iwl_rxon_cmd *active = (void *)&ctx->active;
+	bool new_assoc = !!(ctx->staging.filter_flags & RXON_FILTER_ASSOC_MSK);
+	bool old_assoc = !!(ctx->active.filter_flags & RXON_FILTER_ASSOC_MSK);
+	int ret;
+
+	lockdep_assert_held(&priv->mutex);
+
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+		return -EINVAL;
+
+	if (!iwl_is_alive(priv))
+		return -EBUSY;
+
+	/* This function hardcodes a bunch of dual-mode assumptions */
+	BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2);
+
+	if (!ctx->is_active)
+		return 0;
+
+	/* always get timestamp with Rx frame */
+	ctx->staging.flags |= RXON_FLG_TSF2HOST_MSK;
+
+	if ((ctx->vif && ctx->vif->bss_conf.use_short_slot) ||
+	    !(ctx->staging.flags & RXON_FLG_BAND_24G_MSK))
+		ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK;
+	else
+		ctx->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
+
+	ret = iwl_check_rxon_cmd(priv, ctx);
+	if (ret) {
+		IWL_ERR(priv, "Invalid RXON configuration. Not committing.\n");
+		return -EINVAL;
+	}
+
+	/*
+	 * receive commit_rxon request
+	 * abort any previous channel switch if still in process
+	 */
+	if (priv->switch_rxon.switch_in_progress &&
+	    (priv->switch_rxon.channel != ctx->staging.channel)) {
+		IWL_DEBUG_11H(priv, "abort channel switch on %d\n",
+		      le16_to_cpu(priv->switch_rxon.channel));
+		iwl_chswitch_done(priv, false);
+	}
+
+	/*
+	 * If we don't need to send a full RXON, we can use
+	 * iwl_rxon_assoc_cmd which is used to reconfigure filter
+	 * and other flags for the current radio configuration.
+	 */
+	if (!iwl_full_rxon_required(priv, ctx)) {
+		ret = iwl_send_rxon_assoc(priv, ctx);
+		if (ret) {
+			IWL_ERR(priv, "Error setting RXON_ASSOC (%d)\n", ret);
+			return ret;
+		}
+
+		memcpy(active, &ctx->staging, sizeof(*active));
+		iwl_print_rx_config_cmd(priv, ctx);
+		return 0;
+	}
+
+	if (priv->cfg->ops->hcmd->set_pan_params) {
+		ret = priv->cfg->ops->hcmd->set_pan_params(priv);
+		if (ret)
+			return ret;
+	}
+
+	iwl_set_rxon_hwcrypto(priv, ctx, !priv->cfg->mod_params->sw_crypto);
+
+	IWL_DEBUG_INFO(priv,
+		       "Going to commit RXON\n"
+		       "  * with%s RXON_FILTER_ASSOC_MSK\n"
+		       "  * channel = %d\n"
+		       "  * bssid = %pM\n",
+		       (new_assoc ? "" : "out"),
+		       le16_to_cpu(ctx->staging.channel),
+		       ctx->staging.bssid_addr);
+
+	/*
+	 * Always clear associated first, but with the correct config.
+	 * This is required as for example station addition for the
+	 * AP station must be done after the BSSID is set to correctly
+	 * set up filters in the device.
+	 */
+	if ((old_assoc && new_assoc) || !new_assoc) {
+		if (ctx->ctxid == IWL_RXON_CTX_BSS)
+			ret = iwlagn_disable_bss(priv, ctx, &ctx->staging);
+		else
+			ret = iwlagn_disable_pan(priv, ctx, &ctx->staging);
+		if (ret)
+			return ret;
+
+		memcpy(active, &ctx->staging, sizeof(*active));
+
+		/*
+		 * Un-assoc RXON clears the station table and WEP
+		 * keys, so we have to restore those afterwards.
+		 */
+		iwl_clear_ucode_stations(priv, ctx);
+		iwl_restore_stations(priv, ctx);
+		ret = iwl_restore_default_wep_keys(priv, ctx);
+		if (ret) {
+			IWL_ERR(priv, "Failed to restore WEP keys (%d)\n", ret);
+			return ret;
+		}
+	}
+
+	/* RXON timing must be before associated RXON */
+	ret = iwl_send_rxon_timing(priv, ctx);
+	if (ret) {
+		IWL_ERR(priv, "Failed to send timing (%d)!\n", ret);
+		return ret;
+	}
+
+	if (new_assoc) {
+		/* QoS info may be cleared by previous un-assoc RXON */
+		iwlagn_update_qos(priv, ctx);
+
+		/*
+		 * We'll run into this code path when beaconing is
+		 * enabled, but then we also need to send the beacon
+		 * to the device.
+		 */
+		if (ctx->vif && (ctx->vif->type == NL80211_IFTYPE_AP)) {
+			ret = iwlagn_update_beacon(priv, ctx->vif);
+			if (ret) {
+				IWL_ERR(priv,
+					"Error sending required beacon (%d)!\n",
+					ret);
+				return ret;
+			}
+		}
+
+		priv->start_calib = 0;
+		/*
+		 * Apply the new configuration.
+		 *
+		 * Associated RXON doesn't clear the station table in uCode,
+		 * so we don't need to restore stations etc. after this.
+		 */
+		ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd,
+			      sizeof(struct iwl_rxon_cmd), &ctx->staging);
+		if (ret) {
+			IWL_ERR(priv, "Error setting new RXON (%d)\n", ret);
+			return ret;
+		}
+		memcpy(active, &ctx->staging, sizeof(*active));
+
+		iwl_reprogram_ap_sta(priv, ctx);
+
+		/* IBSS beacon needs to be sent after setting assoc */
+		if (ctx->vif && (ctx->vif->type == NL80211_IFTYPE_ADHOC))
+			if (iwlagn_update_beacon(priv, ctx->vif))
+				IWL_ERR(priv, "Error sending IBSS beacon\n");
+	}
+
+	iwl_print_rx_config_cmd(priv, ctx);
+
+	iwl_init_sensitivity(priv);
+
+	/*
+	 * If we issue a new RXON command which required a tune then we must
+	 * send a new TXPOWER command or we won't be able to Tx any frames.
+	 *
+	 * FIXME: which RXON requires a tune? Can we optimise this out in
+	 *        some cases?
+	 */
+	ret = iwl_set_tx_power(priv, priv->tx_power_user_lmt, true);
+	if (ret) {
+		IWL_ERR(priv, "Error sending TX power (%d)\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed)
+{
+	struct iwl_priv *priv = hw->priv;
+	struct iwl_rxon_context *ctx;
+	struct ieee80211_conf *conf = &hw->conf;
+	struct ieee80211_channel *channel = conf->channel;
+	const struct iwl_channel_info *ch_info;
+	int ret = 0;
+	bool ht_changed[NUM_IWL_RXON_CTX] = {};
+
+	IWL_DEBUG_MAC80211(priv, "changed %#x", changed);
+
+	mutex_lock(&priv->mutex);
+
+	if (unlikely(test_bit(STATUS_SCANNING, &priv->status))) {
+		IWL_DEBUG_MAC80211(priv, "leave - scanning\n");
+		goto out;
+	}
+
+	if (!iwl_is_ready(priv)) {
+		IWL_DEBUG_MAC80211(priv, "leave - not ready\n");
+		goto out;
+	}
+
+	if (changed & (IEEE80211_CONF_CHANGE_SMPS |
+		       IEEE80211_CONF_CHANGE_CHANNEL)) {
+		/* mac80211 uses static for non-HT which is what we want */
+		priv->current_ht_config.smps = conf->smps_mode;
+
+		/*
+		 * Recalculate chain counts.
+		 *
+		 * If monitor mode is enabled then mac80211 will
+		 * set up the SM PS mode to OFF if an HT channel is
+		 * configured.
+		 */
+		if (priv->cfg->ops->hcmd->set_rxon_chain)
+			for_each_context(priv, ctx)
+				priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
+	}
+
+	if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
+		unsigned long flags;
+
+		ch_info = iwl_get_channel_info(priv, channel->band,
+					       channel->hw_value);
+		if (!is_channel_valid(ch_info)) {
+			IWL_DEBUG_MAC80211(priv, "leave - invalid channel\n");
+			ret = -EINVAL;
+			goto out;
+		}
+
+		spin_lock_irqsave(&priv->lock, flags);
+
+		for_each_context(priv, ctx) {
+			/* Configure HT40 channels */
+			if (ctx->ht.enabled != conf_is_ht(conf)) {
+				ctx->ht.enabled = conf_is_ht(conf);
+				ht_changed[ctx->ctxid] = true;
+			}
+
+			if (ctx->ht.enabled) {
+				if (conf_is_ht40_minus(conf)) {
+					ctx->ht.extension_chan_offset =
+						IEEE80211_HT_PARAM_CHA_SEC_BELOW;
+					ctx->ht.is_40mhz = true;
+				} else if (conf_is_ht40_plus(conf)) {
+					ctx->ht.extension_chan_offset =
+						IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
+					ctx->ht.is_40mhz = true;
+				} else {
+					ctx->ht.extension_chan_offset =
+						IEEE80211_HT_PARAM_CHA_SEC_NONE;
+					ctx->ht.is_40mhz = false;
+				}
+			} else
+				ctx->ht.is_40mhz = false;
+
+			/*
+			 * Default to no protection. Protection mode will
+			 * later be set from BSS config in iwl_ht_conf
+			 */
+			ctx->ht.protection = IEEE80211_HT_OP_MODE_PROTECTION_NONE;
+
+			/* if we are switching from ht to 2.4 clear flags
+			 * from any ht related info since 2.4 does not
+			 * support ht */
+			if (le16_to_cpu(ctx->staging.channel) !=
+			    channel->hw_value)
+				ctx->staging.flags = 0;
+
+			iwl_set_rxon_channel(priv, channel, ctx);
+			iwl_set_rxon_ht(priv, &priv->current_ht_config);
+
+			iwl_set_flags_for_band(priv, ctx, channel->band,
+					       ctx->vif);
+		}
+
+		spin_unlock_irqrestore(&priv->lock, flags);
+
+		iwl_update_bcast_stations(priv);
+
+		/*
+		 * The list of supported rates and rate mask can be different
+		 * for each band; since the band may have changed, reset
+		 * the rate mask to what mac80211 lists.
+		 */
+		iwl_set_rate(priv);
+	}
+
+	if (changed & (IEEE80211_CONF_CHANGE_PS |
+			IEEE80211_CONF_CHANGE_IDLE)) {
+		ret = iwl_power_update_mode(priv, false);
+		if (ret)
+			IWL_DEBUG_MAC80211(priv, "Error setting sleep level\n");
+	}
+
+	if (changed & IEEE80211_CONF_CHANGE_POWER) {
+		IWL_DEBUG_MAC80211(priv, "TX Power old=%d new=%d\n",
+			priv->tx_power_user_lmt, conf->power_level);
+
+		iwl_set_tx_power(priv, conf->power_level, false);
+	}
+
+	for_each_context(priv, ctx) {
+		if (!memcmp(&ctx->staging, &ctx->active, sizeof(ctx->staging)))
+			continue;
+		iwlagn_commit_rxon(priv, ctx);
+		if (ht_changed[ctx->ctxid])
+			iwlagn_update_qos(priv, ctx);
+	}
+ out:
+	mutex_unlock(&priv->mutex);
+	return ret;
+}
+
+static void iwlagn_check_needed_chains(struct iwl_priv *priv,
+				       struct iwl_rxon_context *ctx,
+				       struct ieee80211_bss_conf *bss_conf)
+{
+	struct ieee80211_vif *vif = ctx->vif;
+	struct iwl_rxon_context *tmp;
+	struct ieee80211_sta *sta;
+	struct iwl_ht_config *ht_conf = &priv->current_ht_config;
+	bool need_multiple;
+
+	lockdep_assert_held(&priv->mutex);
+
+	switch (vif->type) {
+	case NL80211_IFTYPE_STATION:
+		rcu_read_lock();
+		sta = ieee80211_find_sta(vif, bss_conf->bssid);
+		if (sta) {
+			struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap;
+			int maxstreams;
+
+			maxstreams = (ht_cap->mcs.tx_params &
+				      IEEE80211_HT_MCS_TX_MAX_STREAMS_MASK)
+					>> IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT;
+			maxstreams += 1;
+
+			need_multiple = true;
+
+			if ((ht_cap->mcs.rx_mask[1] == 0) &&
+			    (ht_cap->mcs.rx_mask[2] == 0))
+				need_multiple = false;
+			if (maxstreams <= 1)
+				need_multiple = false;
+		} else {
+			/*
+			 * If at all, this can only happen through a race
+			 * when the AP disconnects us while we're still
+			 * setting up the connection, in that case mac80211
+			 * will soon tell us about that.
+			 */
+			need_multiple = false;
+		}
+		rcu_read_unlock();
+		break;
+	case NL80211_IFTYPE_ADHOC:
+		/* currently */
+		need_multiple = false;
+		break;
+	default:
+		/* only AP really */
+		need_multiple = true;
+		break;
+	}
+
+	ctx->ht_need_multiple_chains = need_multiple;
+
+	if (!need_multiple) {
+		/* check all contexts */
+		for_each_context(priv, tmp) {
+			if (!tmp->vif)
+				continue;
+			if (tmp->ht_need_multiple_chains) {
+				need_multiple = true;
+				break;
+			}
+		}
+	}
+
+	ht_conf->single_chain_sufficient = !need_multiple;
+}
+
+void iwlagn_bss_info_changed(struct ieee80211_hw *hw,
+			     struct ieee80211_vif *vif,
+			     struct ieee80211_bss_conf *bss_conf,
+			     u32 changes)
+{
+	struct iwl_priv *priv = hw->priv;
+	struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);
+	int ret;
+	bool force = false;
+
+	mutex_lock(&priv->mutex);
+
+	if (unlikely(!iwl_is_ready(priv))) {
+		IWL_DEBUG_MAC80211(priv, "leave - not ready\n");
+		mutex_unlock(&priv->mutex);
+		return;
+        }
+
+	if (unlikely(!ctx->vif)) {
+		IWL_DEBUG_MAC80211(priv, "leave - vif is NULL\n");
+		mutex_unlock(&priv->mutex);
+		return;
+	}
+
+	if (changes & BSS_CHANGED_BEACON_INT)
+		force = true;
+
+	if (changes & BSS_CHANGED_QOS) {
+		ctx->qos_data.qos_active = bss_conf->qos;
+		iwlagn_update_qos(priv, ctx);
+	}
+
+	ctx->staging.assoc_id = cpu_to_le16(vif->bss_conf.aid);
+	if (vif->bss_conf.use_short_preamble)
+		ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
+	else
+		ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
+
+	if (changes & BSS_CHANGED_ASSOC) {
+		if (bss_conf->assoc) {
+			iwl_led_associate(priv);
+			priv->timestamp = bss_conf->timestamp;
+			ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
+		} else {
+			ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
+			iwl_led_disassociate(priv);
+		}
+	}
+
+	if (ctx->ht.enabled) {
+		ctx->ht.protection = bss_conf->ht_operation_mode &
+					IEEE80211_HT_OP_MODE_PROTECTION;
+		ctx->ht.non_gf_sta_present = !!(bss_conf->ht_operation_mode &
+					IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT);
+		iwlagn_check_needed_chains(priv, ctx, bss_conf);
+		iwl_set_rxon_ht(priv, &priv->current_ht_config);
+	}
+
+	if (priv->cfg->ops->hcmd->set_rxon_chain)
+		priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
+
+	if (bss_conf->use_cts_prot && (priv->band != IEEE80211_BAND_5GHZ))
+		ctx->staging.flags |= RXON_FLG_TGG_PROTECT_MSK;
+	else
+		ctx->staging.flags &= ~RXON_FLG_TGG_PROTECT_MSK;
+
+	if (bss_conf->use_cts_prot)
+		ctx->staging.flags |= RXON_FLG_SELF_CTS_EN;
+	else
+		ctx->staging.flags &= ~RXON_FLG_SELF_CTS_EN;
+
+	memcpy(ctx->staging.bssid_addr, bss_conf->bssid, ETH_ALEN);
+
+	if (vif->type == NL80211_IFTYPE_AP ||
+	    vif->type == NL80211_IFTYPE_ADHOC) {
+		if (vif->bss_conf.enable_beacon) {
+			ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
+			priv->beacon_ctx = ctx;
+		} else {
+			ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
+			priv->beacon_ctx = NULL;
+		}
+	}
+
+	if (force || memcmp(&ctx->staging, &ctx->active, sizeof(ctx->staging)))
+		iwlagn_commit_rxon(priv, ctx);
+
+	if (changes & BSS_CHANGED_ASSOC && bss_conf->assoc) {
+		/*
+		 * The chain noise calibration will enable PM upon
+		 * completion. If calibration has already been run
+		 * then we need to enable power management here.
+		 */
+		if (priv->chain_noise_data.state == IWL_CHAIN_NOISE_DONE)
+			iwl_power_update_mode(priv, false);
+
+		/* Enable RX differential gain and sensitivity calibrations */
+		iwl_chain_noise_reset(priv);
+		priv->start_calib = 1;
+	}
+
+	if (changes & BSS_CHANGED_IBSS) {
+		ret = iwlagn_manage_ibss_station(priv, vif,
+						 bss_conf->ibss_joined);
+		if (ret)
+			IWL_ERR(priv, "failed to %s IBSS station %pM\n",
+				bss_conf->ibss_joined ? "add" : "remove",
+				bss_conf->bssid);
+	}
+
+	if (changes & BSS_CHANGED_BEACON && vif->type == NL80211_IFTYPE_ADHOC &&
+	    priv->beacon_ctx) {
+		if (iwlagn_update_beacon(priv, vif))
+			IWL_ERR(priv, "Error sending IBSS beacon\n");
+	}
+
+	mutex_unlock(&priv->mutex);
+}
+
+void iwlagn_post_scan(struct iwl_priv *priv)
+{
+	struct iwl_rxon_context *ctx;
+
+	/*
+	 * Since setting the RXON may have been deferred while
+	 * performing the scan, fire one off if needed
+	 */
+	for_each_context(priv, ctx)
+		if (memcmp(&ctx->staging, &ctx->active, sizeof(ctx->staging)))
+			iwlagn_commit_rxon(priv, ctx);
+
+	if (priv->cfg->ops->hcmd->set_pan_params)
+		priv->cfg->ops->hcmd->set_pan_params(priv);
+}
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/iwlwifi/iwl-agn-sta.c linux-libre-2.6.38-gnu1/drivers/net/wireless/iwlwifi/iwl-agn-sta.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/iwlwifi/iwl-agn-sta.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/iwlwifi/iwl-agn-sta.c	2011-03-14 21:20:32.000000000 -0400
@@ -684,7 +684,7 @@ int iwl_sta_rx_agg_stop(struct iwl_priv
 	return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
 }
 
-void iwl_sta_modify_ps_wake(struct iwl_priv *priv, int sta_id)
+static void iwl_sta_modify_ps_wake(struct iwl_priv *priv, int sta_id)
 {
 	unsigned long flags;
 
@@ -714,3 +714,33 @@ void iwl_sta_modify_sleep_tx_count(struc
 	spin_unlock_irqrestore(&priv->sta_lock, flags);
 
 }
+
+void iwlagn_mac_sta_notify(struct ieee80211_hw *hw,
+			   struct ieee80211_vif *vif,
+			   enum sta_notify_cmd cmd,
+			   struct ieee80211_sta *sta)
+{
+	struct iwl_priv *priv = hw->priv;
+	struct iwl_station_priv *sta_priv = (void *)sta->drv_priv;
+	int sta_id;
+
+	switch (cmd) {
+	case STA_NOTIFY_SLEEP:
+		WARN_ON(!sta_priv->client);
+		sta_priv->asleep = true;
+		if (atomic_read(&sta_priv->pending_frames) > 0)
+			ieee80211_sta_block_awake(hw, sta, true);
+		break;
+	case STA_NOTIFY_AWAKE:
+		WARN_ON(!sta_priv->client);
+		if (!sta_priv->asleep)
+			break;
+		sta_priv->asleep = false;
+		sta_id = iwl_sta_id(sta);
+		if (sta_id != IWL_INVALID_STATION)
+			iwl_sta_modify_ps_wake(priv, sta_id);
+		break;
+	default:
+		break;
+	}
+}
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/iwlwifi/iwl-agn-tx.c linux-libre-2.6.38-gnu1/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/iwlwifi/iwl-agn-tx.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/iwlwifi/iwl-agn-tx.c	2011-03-14 21:20:32.000000000 -0400
@@ -67,8 +67,14 @@
  */
 
 static const u8 tid_to_ac[] = {
-	/* this matches the mac80211 numbers */
-	2, 3, 3, 2, 1, 1, 0, 0
+	IEEE80211_AC_BE,
+	IEEE80211_AC_BK,
+	IEEE80211_AC_BK,
+	IEEE80211_AC_BE,
+	IEEE80211_AC_VI,
+	IEEE80211_AC_VI,
+	IEEE80211_AC_VO,
+	IEEE80211_AC_VO
 };
 
 static inline int get_ac_from_tid(u16 tid)
@@ -518,11 +524,11 @@ int iwlagn_tx_skb(struct iwl_priv *priv,
 	struct iwl_cmd_meta *out_meta;
 	struct iwl_tx_cmd *tx_cmd;
 	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
-	int swq_id, txq_id;
+	int txq_id;
 	dma_addr_t phys_addr;
 	dma_addr_t txcmd_phys;
 	dma_addr_t scratch_phys;
-	u16 len, len_org, firstlen, secondlen;
+	u16 len, firstlen, secondlen;
 	u16 seq_number = 0;
 	__le16 fc;
 	u8 hdr_len;
@@ -531,6 +537,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv,
 	u8 tid = 0;
 	u8 *qc = NULL;
 	unsigned long flags;
+	bool is_agg = false;
 
 	if (info->control.vif)
 		ctx = iwl_rxon_ctx_from_vif(info->control.vif);
@@ -567,8 +574,8 @@ int iwlagn_tx_skb(struct iwl_priv *priv,
 	if (sta)
 		sta_priv = (void *)sta->drv_priv;
 
-	if (sta_priv && sta_priv->asleep) {
-		WARN_ON(!(info->flags & IEEE80211_TX_CTL_PSPOLL_RESPONSE));
+	if (sta_priv && sta_priv->asleep &&
+	    (info->flags & IEEE80211_TX_CTL_PSPOLL_RESPONSE)) {
 		/*
 		 * This sends an asynchronous command to the device,
 		 * but we can rely on it being processed before the
@@ -616,11 +623,11 @@ int iwlagn_tx_skb(struct iwl_priv *priv,
 		if (info->flags & IEEE80211_TX_CTL_AMPDU &&
 		    priv->stations[sta_id].tid[tid].agg.state == IWL_AGG_ON) {
 			txq_id = priv->stations[sta_id].tid[tid].agg.txq_id;
+			is_agg = true;
 		}
 	}
 
 	txq = &priv->txq[txq_id];
-	swq_id = txq->swq_id;
 	q = &txq->q;
 
 	if (unlikely(iwl_queue_space(q) < q->high_mark)) {
@@ -687,30 +694,23 @@ int iwlagn_tx_skb(struct iwl_priv *priv,
 	 */
 	len = sizeof(struct iwl_tx_cmd) +
 		sizeof(struct iwl_cmd_header) + hdr_len;
-
-	len_org = len;
-	firstlen = len = (len + 3) & ~3;
-
-	if (len_org != len)
-		len_org = 1;
-	else
-		len_org = 0;
+	firstlen = (len + 3) & ~3;
 
 	/* Tell NIC about any 2-byte padding after MAC header */
-	if (len_org)
+	if (firstlen != len)
 		tx_cmd->tx_flags |= TX_CMD_FLG_MH_PAD_MSK;
 
 	/* Physical address of this Tx command's header (not MAC header!),
 	 * within command buffer array. */
 	txcmd_phys = pci_map_single(priv->pci_dev,
-				    &out_cmd->hdr, len,
+				    &out_cmd->hdr, firstlen,
 				    PCI_DMA_BIDIRECTIONAL);
 	dma_unmap_addr_set(out_meta, mapping, txcmd_phys);
-	dma_unmap_len_set(out_meta, len, len);
+	dma_unmap_len_set(out_meta, len, firstlen);
 	/* Add buffer containing Tx command and MAC(!) header to TFD's
 	 * first entry */
 	priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq,
-						   txcmd_phys, len, 1, 0);
+						   txcmd_phys, firstlen, 1, 0);
 
 	if (!ieee80211_has_morefrags(hdr->frame_control)) {
 		txq->need_update = 1;
@@ -721,23 +721,21 @@ int iwlagn_tx_skb(struct iwl_priv *priv,
 
 	/* Set up TFD's 2nd entry to point directly to remainder of skb,
 	 * if any (802.11 null frames have no payload). */
-	secondlen = len = skb->len - hdr_len;
-	if (len) {
+	secondlen = skb->len - hdr_len;
+	if (secondlen > 0) {
 		phys_addr = pci_map_single(priv->pci_dev, skb->data + hdr_len,
-					   len, PCI_DMA_TODEVICE);
+					   secondlen, PCI_DMA_TODEVICE);
 		priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq,
-							   phys_addr, len,
+							   phys_addr, secondlen,
 							   0, 0);
 	}
 
 	scratch_phys = txcmd_phys + sizeof(struct iwl_cmd_header) +
 				offsetof(struct iwl_tx_cmd, scratch);
 
-	len = sizeof(struct iwl_tx_cmd) +
-		sizeof(struct iwl_cmd_header) + hdr_len;
 	/* take back ownership of DMA buffer to enable update */
 	pci_dma_sync_single_for_cpu(priv->pci_dev, txcmd_phys,
-				    len, PCI_DMA_BIDIRECTIONAL);
+				    firstlen, PCI_DMA_BIDIRECTIONAL);
 	tx_cmd->dram_lsb_ptr = cpu_to_le32(scratch_phys);
 	tx_cmd->dram_msb_ptr = iwl_get_dma_hi_addr(scratch_phys);
 
@@ -753,7 +751,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv,
 						     le16_to_cpu(tx_cmd->len));
 
 	pci_dma_sync_single_for_device(priv->pci_dev, txcmd_phys,
-				       len, PCI_DMA_BIDIRECTIONAL);
+				       firstlen, PCI_DMA_BIDIRECTIONAL);
 
 	trace_iwlwifi_dev_tx(priv,
 			     &((struct iwl_tfd *)txq->tfds)[txq->q.write_ptr],
@@ -773,8 +771,14 @@ int iwlagn_tx_skb(struct iwl_priv *priv,
 	 * whether or not we should update the write pointer.
 	 */
 
-	/* avoid atomic ops if it isn't an associated client */
-	if (sta_priv && sta_priv->client)
+	/*
+	 * Avoid atomic ops if it isn't an associated client.
+	 * Also, if this is a packet for aggregation, don't
+	 * increase the counter because the ucode will stop
+	 * aggregation queues when their respective station
+	 * goes to sleep.
+	 */
+	if (sta_priv && sta_priv->client && !is_agg)
 		atomic_inc(&sta_priv->pending_frames);
 
 	if ((iwl_queue_space(q) < q->high_mark) && priv->mac80211_registered) {
@@ -784,7 +788,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv,
 			iwl_txq_update_write_ptr(priv, txq);
 			spin_unlock_irqrestore(&priv->lock, flags);
 		} else {
-			iwl_stop_queue(priv, txq->swq_id);
+			iwl_stop_queue(priv, txq);
 		}
 	}
 
@@ -1013,7 +1017,7 @@ int iwlagn_tx_agg_start(struct iwl_priv
 	tid_data = &priv->stations[sta_id].tid[tid];
 	*ssn = SEQ_TO_SN(tid_data->seq_number);
 	tid_data->agg.txq_id = txq_id;
-	priv->txq[txq_id].swq_id = iwl_virtual_agg_queue_num(get_ac_from_tid(tid), txq_id);
+	iwl_set_swq_id(&priv->txq[txq_id], get_ac_from_tid(tid), txq_id);
 	spin_unlock_irqrestore(&priv->sta_lock, flags);
 
 	ret = priv->cfg->ops->lib->txq_agg_enable(priv, txq_id, tx_fifo,
@@ -1153,14 +1157,15 @@ int iwlagn_txq_check_empty(struct iwl_pr
 	return 0;
 }
 
-static void iwlagn_tx_status(struct iwl_priv *priv, struct iwl_tx_info *tx_info)
+static void iwlagn_non_agg_tx_status(struct iwl_priv *priv,
+				     struct iwl_rxon_context *ctx,
+				     const u8 *addr1)
 {
-	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) tx_info->skb->data;
 	struct ieee80211_sta *sta;
 	struct iwl_station_priv *sta_priv;
 
 	rcu_read_lock();
-	sta = ieee80211_find_sta(tx_info->ctx->vif, hdr->addr1);
+	sta = ieee80211_find_sta(ctx->vif, addr1);
 	if (sta) {
 		sta_priv = (void *)sta->drv_priv;
 		/* avoid atomic ops if this isn't a client */
@@ -1169,6 +1174,15 @@ static void iwlagn_tx_status(struct iwl_
 			ieee80211_sta_block_awake(priv->hw, sta, false);
 	}
 	rcu_read_unlock();
+}
+
+static void iwlagn_tx_status(struct iwl_priv *priv, struct iwl_tx_info *tx_info,
+			     bool is_agg)
+{
+	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) tx_info->skb->data;
+
+	if (!is_agg)
+		iwlagn_non_agg_tx_status(priv, tx_info->ctx, hdr->addr1);
 
 	ieee80211_tx_status_irqsafe(priv->hw, tx_info->skb);
 }
@@ -1193,7 +1207,8 @@ int iwlagn_tx_queue_reclaim(struct iwl_p
 	     q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) {
 
 		tx_info = &txq->txb[txq->q.read_ptr];
-		iwlagn_tx_status(priv, tx_info);
+		iwlagn_tx_status(priv, tx_info,
+				 txq_id >= IWLAGN_FIRST_AMPDU_QUEUE);
 
 		hdr = (struct ieee80211_hdr *)tx_info->skb->data;
 		if (hdr && ieee80211_is_data_qos(hdr->frame_control))
@@ -1222,7 +1237,6 @@ static int iwlagn_tx_status_reply_compre
 	int i, sh, ack;
 	u16 seq_ctl = le16_to_cpu(ba_resp->seq_ctl);
 	u16 scd_flow = le16_to_cpu(ba_resp->scd_flow);
-	u64 bitmap, sent_bitmap;
 	int successes = 0;
 	struct ieee80211_tx_info *info;
 
@@ -1241,40 +1255,68 @@ static int iwlagn_tx_status_reply_compre
 	if (sh < 0) /* tbw something is wrong with indices */
 		sh += 0x100;
 
-	/* don't use 64-bit values for now */
-	bitmap = le64_to_cpu(ba_resp->bitmap) >> sh;
-
 	if (agg->frame_count > (64 - sh)) {
 		IWL_DEBUG_TX_REPLY(priv, "more frames than bitmap size");
 		return -1;
 	}
+	if (!priv->cfg->base_params->no_agg_framecnt_info && ba_resp->txed) {
+		/*
+		 * sent and ack information provided by uCode
+		 * use it instead of figure out ourself
+		 */
+		if (ba_resp->txed_2_done > ba_resp->txed) {
+			IWL_DEBUG_TX_REPLY(priv,
+				"bogus sent(%d) and ack(%d) count\n",
+				ba_resp->txed, ba_resp->txed_2_done);
+			/*
+			 * set txed_2_done = txed,
+			 * so it won't impact rate scale
+			 */
+			ba_resp->txed = ba_resp->txed_2_done;
+		}
+		IWL_DEBUG_HT(priv, "agg frames sent:%d, acked:%d\n",
+				ba_resp->txed, ba_resp->txed_2_done);
+	} else {
+		u64 bitmap, sent_bitmap;
 
-	/* check for success or failure according to the
-	 * transmitted bitmap and block-ack bitmap */
-	sent_bitmap = bitmap & agg->bitmap;
+		/* don't use 64-bit values for now */
+		bitmap = le64_to_cpu(ba_resp->bitmap) >> sh;
 
-	/* For each frame attempted in aggregation,
-	 * update driver's record of tx frame's status. */
-	i = 0;
-	while (sent_bitmap) {
-		ack = sent_bitmap & 1ULL;
-		successes += ack;
-		IWL_DEBUG_TX_REPLY(priv, "%s ON i=%d idx=%d raw=%d\n",
-			ack ? "ACK" : "NACK", i, (agg->start_idx + i) & 0xff,
-			agg->start_idx + i);
-		sent_bitmap >>= 1;
-		++i;
+		/* check for success or failure according to the
+		 * transmitted bitmap and block-ack bitmap */
+		sent_bitmap = bitmap & agg->bitmap;
+
+		/* For each frame attempted in aggregation,
+		 * update driver's record of tx frame's status. */
+		i = 0;
+		while (sent_bitmap) {
+			ack = sent_bitmap & 1ULL;
+			successes += ack;
+			IWL_DEBUG_TX_REPLY(priv, "%s ON i=%d idx=%d raw=%d\n",
+				ack ? "ACK" : "NACK", i,
+				(agg->start_idx + i) & 0xff,
+				agg->start_idx + i);
+			sent_bitmap >>= 1;
+			++i;
+		}
+
+		IWL_DEBUG_TX_REPLY(priv, "Bitmap %llx\n",
+				   (unsigned long long)bitmap);
 	}
 
 	info = IEEE80211_SKB_CB(priv->txq[scd_flow].txb[agg->start_idx].skb);
 	memset(&info->status, 0, sizeof(info->status));
 	info->flags |= IEEE80211_TX_STAT_ACK;
 	info->flags |= IEEE80211_TX_STAT_AMPDU;
-	info->status.ampdu_ack_len = successes;
-	info->status.ampdu_len = agg->frame_count;
-	iwlagn_hwrate_to_tx_control(priv, agg->rate_n_flags, info);
+	if (!priv->cfg->base_params->no_agg_framecnt_info && ba_resp->txed) {
+		info->status.ampdu_ack_len = ba_resp->txed_2_done;
+		info->status.ampdu_len = ba_resp->txed;
 
-	IWL_DEBUG_TX_REPLY(priv, "Bitmap %llx\n", (unsigned long long)bitmap);
+	} else {
+		info->status.ampdu_ack_len = successes;
+		info->status.ampdu_len = agg->frame_count;
+	}
+	iwlagn_hwrate_to_tx_control(priv, agg->rate_n_flags, info);
 
 	return 0;
 }
@@ -1385,7 +1427,7 @@ void iwlagn_rx_reply_compressed_ba(struc
 		if ((iwl_queue_space(&txq->q) > txq->q.low_mark) &&
 		    priv->mac80211_registered &&
 		    (agg->state != IWL_EMPTYING_HW_QUEUE_DELBA))
-			iwl_wake_queue(priv, txq->swq_id);
+			iwl_wake_queue(priv, txq);
 
 		iwlagn_txq_check_empty(priv, sta_id, tid, scd_flow);
 	}
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c linux-libre-2.6.38-gnu1/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c	2011-03-14 21:20:32.000000000 -0400
@@ -40,30 +40,36 @@
 #include "iwl-agn.h"
 #include "iwl-agn-calib.h"
 
-static const s8 iwlagn_default_queue_to_tx_fifo[] = {
-	IWL_TX_FIFO_VO,
-	IWL_TX_FIFO_VI,
-	IWL_TX_FIFO_BE,
-	IWL_TX_FIFO_BK,
-	IWLAGN_CMD_FIFO_NUM,
-	IWL_TX_FIFO_UNUSED,
-	IWL_TX_FIFO_UNUSED,
-	IWL_TX_FIFO_UNUSED,
-	IWL_TX_FIFO_UNUSED,
-	IWL_TX_FIFO_UNUSED,
+#define IWL_AC_UNSET -1
+
+struct queue_to_fifo_ac {
+	s8 fifo, ac;
 };
 
-static const s8 iwlagn_ipan_queue_to_tx_fifo[] = {
-	IWL_TX_FIFO_VO,
-	IWL_TX_FIFO_VI,
-	IWL_TX_FIFO_BE,
-	IWL_TX_FIFO_BK,
-	IWL_TX_FIFO_BK_IPAN,
-	IWL_TX_FIFO_BE_IPAN,
-	IWL_TX_FIFO_VI_IPAN,
-	IWL_TX_FIFO_VO_IPAN,
-	IWL_TX_FIFO_BE_IPAN,
-	IWLAGN_CMD_FIFO_NUM,
+static const struct queue_to_fifo_ac iwlagn_default_queue_to_tx_fifo[] = {
+	{ IWL_TX_FIFO_VO, IEEE80211_AC_VO, },
+	{ IWL_TX_FIFO_VI, IEEE80211_AC_VI, },
+	{ IWL_TX_FIFO_BE, IEEE80211_AC_BE, },
+	{ IWL_TX_FIFO_BK, IEEE80211_AC_BK, },
+	{ IWLAGN_CMD_FIFO_NUM, IWL_AC_UNSET, },
+	{ IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, },
+	{ IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, },
+	{ IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, },
+	{ IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, },
+	{ IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, },
+};
+
+static const struct queue_to_fifo_ac iwlagn_ipan_queue_to_tx_fifo[] = {
+	{ IWL_TX_FIFO_VO, IEEE80211_AC_VO, },
+	{ IWL_TX_FIFO_VI, IEEE80211_AC_VI, },
+	{ IWL_TX_FIFO_BE, IEEE80211_AC_BE, },
+	{ IWL_TX_FIFO_BK, IEEE80211_AC_BK, },
+	{ IWL_TX_FIFO_BK_IPAN, IEEE80211_AC_BK, },
+	{ IWL_TX_FIFO_BE_IPAN, IEEE80211_AC_BE, },
+	{ IWL_TX_FIFO_VI_IPAN, IEEE80211_AC_VI, },
+	{ IWL_TX_FIFO_VO_IPAN, IEEE80211_AC_VO, },
+	{ IWL_TX_FIFO_BE_IPAN, 2, },
+	{ IWLAGN_CMD_FIFO_NUM, IWL_AC_UNSET, },
 };
 
 static struct iwl_wimax_coex_event_entry cu_priorities[COEX_NUM_OF_EVENTS] = {
@@ -429,7 +435,7 @@ void iwlagn_send_bt_env(struct iwl_priv
 
 int iwlagn_alive_notify(struct iwl_priv *priv)
 {
-	const s8 *queues;
+	const struct queue_to_fifo_ac *queue_to_fifo;
 	u32 a;
 	unsigned long flags;
 	int i, chan;
@@ -492,9 +498,9 @@ int iwlagn_alive_notify(struct iwl_priv
 
 	/* map queues to FIFOs */
 	if (priv->valid_contexts != BIT(IWL_RXON_CTX_BSS))
-		queues = iwlagn_ipan_queue_to_tx_fifo;
+		queue_to_fifo = iwlagn_ipan_queue_to_tx_fifo;
 	else
-		queues = iwlagn_default_queue_to_tx_fifo;
+		queue_to_fifo = iwlagn_default_queue_to_tx_fifo;
 
 	iwlagn_set_wr_ptrs(priv, priv->cmd_queue, 0);
 
@@ -510,18 +516,25 @@ int iwlagn_alive_notify(struct iwl_priv
 	BUILD_BUG_ON(ARRAY_SIZE(iwlagn_ipan_queue_to_tx_fifo) != 10);
 
 	for (i = 0; i < 10; i++) {
-		int ac = queues[i];
+		int fifo = queue_to_fifo[i].fifo;
+		int ac = queue_to_fifo[i].ac;
 
 		iwl_txq_ctx_activate(priv, i);
 
-		if (ac == IWL_TX_FIFO_UNUSED)
+		if (fifo == IWL_TX_FIFO_UNUSED)
 			continue;
 
-		iwlagn_tx_queue_set_status(priv, &priv->txq[i], ac, 0);
+		if (ac != IWL_AC_UNSET)
+			iwl_set_swq_id(&priv->txq[i], ac, i);
+		iwlagn_tx_queue_set_status(priv, &priv->txq[i], fifo, 0);
 	}
 
 	spin_unlock_irqrestore(&priv->lock, flags);
 
+	/* Enable L1-Active */
+	iwl_clear_bits_prph(priv, APMG_PCIDEV_STT_REG,
+			  APMG_PCIDEV_STT_VAL_L1_ACT_DIS);
+
 	iwlagn_send_wimax_coex(priv);
 
 	iwlagn_set_Xtal_calib(priv);
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/iwlwifi/iwl-commands.h linux-libre-2.6.38-gnu1/drivers/net/wireless/iwlwifi/iwl-commands.h
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/iwlwifi/iwl-commands.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/iwlwifi/iwl-commands.h	2011-03-14 21:20:32.000000000 -0400
@@ -2022,6 +2022,9 @@ struct iwl_compressed_ba_resp {
 	__le64 bitmap;
 	__le16 scd_flow;
 	__le16 scd_ssn;
+	/* following only for 5000 series and up */
+	u8 txed;	/* number of frames sent */
+	u8 txed_2_done; /* number of frames acked */
 } __packed;
 
 /*
@@ -2407,9 +2410,9 @@ struct iwl_link_quality_cmd {
 #define BT_FRAG_THRESHOLD_MAX	0
 #define BT_FRAG_THRESHOLD_MIN	0
 
-#define BT_AGG_THRESHOLD_DEF	0
-#define BT_AGG_THRESHOLD_MAX	0
-#define BT_AGG_THRESHOLD_MIN	0
+#define BT_AGG_THRESHOLD_DEF	1200
+#define BT_AGG_THRESHOLD_MAX	8000
+#define BT_AGG_THRESHOLD_MIN	400
 
 /*
  * REPLY_BT_CONFIG = 0x9b (command, has simple generic response)
@@ -2436,8 +2439,9 @@ struct iwl_bt_cmd {
 #define IWLAGN_BT_FLAG_COEX_MODE_3W		2
 #define IWLAGN_BT_FLAG_COEX_MODE_4W		3
 
-#define IWLAGN_BT_FLAG_UCODE_DEFAULT	BIT(6)
-#define IWLAGN_BT_FLAG_NOCOEX_NOTIF	BIT(7)
+#define IWLAGN_BT_FLAG_UCODE_DEFAULT		BIT(6)
+/* Disable Sync PSPoll on SCO/eSCO */
+#define IWLAGN_BT_FLAG_SYNC_2_BT_DISABLE	BIT(7)
 
 #define IWLAGN_BT_PRIO_BOOST_MAX	0xFF
 #define IWLAGN_BT_PRIO_BOOST_MIN	0x00
@@ -2447,8 +2451,9 @@ struct iwl_bt_cmd {
 
 #define IWLAGN_BT3_T7_DEFAULT		1
 
-#define IWLAGN_BT_KILL_ACK_MASK_DEFAULT	cpu_to_le32(0xffffffff)
-#define IWLAGN_BT_KILL_CTS_MASK_DEFAULT	cpu_to_le32(0xffffffff)
+#define IWLAGN_BT_KILL_ACK_MASK_DEFAULT	cpu_to_le32(0xffff0000)
+#define IWLAGN_BT_KILL_CTS_MASK_DEFAULT	cpu_to_le32(0xffff0000)
+#define IWLAGN_BT_KILL_ACK_CTS_MASK_SCO	cpu_to_le32(0xffffffff)
 
 #define IWLAGN_BT3_PRIO_SAMPLE_DEFAULT	2
 
@@ -2664,9 +2669,16 @@ struct iwl_spectrum_notification {
 #define IWL_POWER_VEC_SIZE 5
 
 #define IWL_POWER_DRIVER_ALLOW_SLEEP_MSK	cpu_to_le16(BIT(0))
+#define IWL_POWER_POWER_SAVE_ENA_MSK		cpu_to_le16(BIT(0))
+#define IWL_POWER_POWER_MANAGEMENT_ENA_MSK	cpu_to_le16(BIT(1))
 #define IWL_POWER_SLEEP_OVER_DTIM_MSK		cpu_to_le16(BIT(2))
 #define IWL_POWER_PCI_PM_MSK			cpu_to_le16(BIT(3))
 #define IWL_POWER_FAST_PD			cpu_to_le16(BIT(4))
+#define IWL_POWER_BEACON_FILTERING		cpu_to_le16(BIT(5))
+#define IWL_POWER_SHADOW_REG_ENA		cpu_to_le16(BIT(6))
+#define IWL_POWER_CT_KILL_SET			cpu_to_le16(BIT(7))
+#define IWL_POWER_BT_SCO_ENA			cpu_to_le16(BIT(8))
+#define IWL_POWER_ADVANCE_PM_ENA_MSK		cpu_to_le16(BIT(9))
 
 struct iwl3945_powertable_cmd {
 	__le16 flags;
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/iwlwifi/iwl-core.c linux-libre-2.6.38-gnu1/drivers/net/wireless/iwlwifi/iwl-core.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/iwlwifi/iwl-core.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/iwlwifi/iwl-core.c	2011-03-14 21:20:32.000000000 -0400
@@ -77,15 +77,15 @@ EXPORT_SYMBOL(iwl_bcast_addr);
 
 
 /* This function both allocates and initializes hw and priv. */
-struct ieee80211_hw *iwl_alloc_all(struct iwl_cfg *cfg,
-		struct ieee80211_ops *hw_ops)
+struct ieee80211_hw *iwl_alloc_all(struct iwl_cfg *cfg)
 {
 	struct iwl_priv *priv;
-
 	/* mac80211 allocates memory for this device instance, including
 	 *   space for this driver's private structure */
-	struct ieee80211_hw *hw =
-		ieee80211_alloc_hw(sizeof(struct iwl_priv), hw_ops);
+	struct ieee80211_hw *hw;
+
+	hw = ieee80211_alloc_hw(sizeof(struct iwl_priv),
+				cfg->ops->ieee80211_ops);
 	if (hw == NULL) {
 		pr_err("%s: Can not allocate network device\n",
 		       cfg->name);
@@ -100,35 +100,6 @@ out:
 }
 EXPORT_SYMBOL(iwl_alloc_all);
 
-/*
- * QoS  support
-*/
-static void iwl_update_qos(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
-{
-	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-		return;
-
-	if (!ctx->is_active)
-		return;
-
-	ctx->qos_data.def_qos_parm.qos_flags = 0;
-
-	if (ctx->qos_data.qos_active)
-		ctx->qos_data.def_qos_parm.qos_flags |=
-			QOS_PARAM_FLG_UPDATE_EDCA_MSK;
-
-	if (ctx->ht.enabled)
-		ctx->qos_data.def_qos_parm.qos_flags |= QOS_PARAM_FLG_TGN_MSK;
-
-	IWL_DEBUG_QOS(priv, "send QoS cmd with Qos active=%d FLAGS=0x%X\n",
-		      ctx->qos_data.qos_active,
-		      ctx->qos_data.def_qos_parm.qos_flags);
-
-	iwl_send_cmd_pdu_async(priv, ctx->qos_cmd,
-			       sizeof(struct iwl_qosparam_cmd),
-			       &ctx->qos_data.def_qos_parm, NULL);
-}
-
 #define MAX_BIT_RATE_40_MHZ 150 /* Mbps */
 #define MAX_BIT_RATE_20_MHZ 72 /* Mbps */
 static void iwlcore_init_ht_hw_capab(const struct iwl_priv *priv,
@@ -317,40 +288,6 @@ void iwlcore_free_geos(struct iwl_priv *
 }
 EXPORT_SYMBOL(iwlcore_free_geos);
 
-/*
- *  iwlcore_tx_cmd_protection: Set rts/cts. 3945 and 4965 only share this
- *  function.
- */
-void iwlcore_tx_cmd_protection(struct iwl_priv *priv,
-			       struct ieee80211_tx_info *info,
-			       __le16 fc, __le32 *tx_flags)
-{
-	if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) {
-		*tx_flags |= TX_CMD_FLG_RTS_MSK;
-		*tx_flags &= ~TX_CMD_FLG_CTS_MSK;
-		*tx_flags |= TX_CMD_FLG_FULL_TXOP_PROT_MSK;
-
-		if (!ieee80211_is_mgmt(fc))
-			return;
-
-		switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) {
-		case cpu_to_le16(IEEE80211_STYPE_AUTH):
-		case cpu_to_le16(IEEE80211_STYPE_DEAUTH):
-		case cpu_to_le16(IEEE80211_STYPE_ASSOC_REQ):
-		case cpu_to_le16(IEEE80211_STYPE_REASSOC_REQ):
-			*tx_flags &= ~TX_CMD_FLG_RTS_MSK;
-			*tx_flags |= TX_CMD_FLG_CTS_MSK;
-			break;
-		}
-	} else if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) {
-		*tx_flags &= ~TX_CMD_FLG_RTS_MSK;
-		*tx_flags |= TX_CMD_FLG_CTS_MSK;
-		*tx_flags |= TX_CMD_FLG_FULL_TXOP_PROT_MSK;
-	}
-}
-EXPORT_SYMBOL(iwlcore_tx_cmd_protection);
-
-
 static bool iwl_is_channel_extension(struct iwl_priv *priv,
 				     enum ieee80211_band band,
 				     u16 channel, u8 extension_chan_offset)
@@ -1020,6 +957,22 @@ void iwl_irq_handle_error(struct iwl_pri
 	/* Cancel currently queued command. */
 	clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
 
+	/* W/A for WiFi/WiMAX coex and WiMAX own the RF */
+	if (priv->cfg->internal_wimax_coex &&
+	    (!(iwl_read_prph(priv, APMG_CLK_CTRL_REG) &
+			APMS_CLK_VAL_MRB_FUNC_MODE) ||
+	     (iwl_read_prph(priv, APMG_PS_CTRL_REG) &
+			APMG_PS_CTRL_VAL_RESET_REQ))) {
+		wake_up_interruptible(&priv->wait_command_queue);
+		/*
+		 *Keep the restart process from trying to send host
+		 * commands by clearing the INIT status bit
+		 */
+		clear_bit(STATUS_READY, &priv->status);
+		IWL_ERR(priv, "RF is used by WiMAX\n");
+		return;
+	}
+
 	IWL_ERR(priv, "Loaded firmware version: %s\n",
 		priv->hw->wiphy->fw_version);
 
@@ -1206,8 +1159,16 @@ EXPORT_SYMBOL(iwl_apm_init);
 
 int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force)
 {
-	int ret = 0;
-	s8 prev_tx_power = priv->tx_power_user_lmt;
+	int ret;
+	s8 prev_tx_power;
+
+	lockdep_assert_held(&priv->mutex);
+
+	if (priv->tx_power_user_lmt == tx_power && !force)
+		return 0;
+
+	if (!priv->cfg->ops->lib->send_tx_power)
+		return -EOPNOTSUPP;
 
 	if (tx_power < IWLAGN_TX_POWER_TARGET_POWER_MIN) {
 		IWL_WARN(priv,
@@ -1224,93 +1185,29 @@ int iwl_set_tx_power(struct iwl_priv *pr
 		return -EINVAL;
 	}
 
-	if (priv->tx_power_user_lmt != tx_power)
-		force = true;
+	if (!iwl_is_ready_rf(priv))
+		return -EIO;
 
-	/* if nic is not up don't send command */
-	if (iwl_is_ready_rf(priv)) {
-		priv->tx_power_user_lmt = tx_power;
-		if (force && priv->cfg->ops->lib->send_tx_power)
-			ret = priv->cfg->ops->lib->send_tx_power(priv);
-		else if (!priv->cfg->ops->lib->send_tx_power)
-			ret = -EOPNOTSUPP;
-		/*
-		 * if fail to set tx_power, restore the orig. tx power
-		 */
-		if (ret)
-			priv->tx_power_user_lmt = prev_tx_power;
+	/* scan complete use tx_power_next, need to be updated */
+	priv->tx_power_next = tx_power;
+	if (test_bit(STATUS_SCANNING, &priv->status) && !force) {
+		IWL_DEBUG_INFO(priv, "Deferring tx power set while scanning\n");
+		return 0;
 	}
 
-	/*
-	 * Even this is an async host command, the command
-	 * will always report success from uCode
-	 * So once driver can placing the command into the queue
-	 * successfully, driver can use priv->tx_power_user_lmt
-	 * to reflect the current tx power
-	 */
-	return ret;
-}
-EXPORT_SYMBOL(iwl_set_tx_power);
-
-irqreturn_t iwl_isr_legacy(int irq, void *data)
-{
-	struct iwl_priv *priv = data;
-	u32 inta, inta_mask;
-	u32 inta_fh;
-	unsigned long flags;
-	if (!priv)
-		return IRQ_NONE;
-
-	spin_lock_irqsave(&priv->lock, flags);
-
-	/* Disable (but don't clear!) interrupts here to avoid
-	 *    back-to-back ISRs and sporadic interrupts from our NIC.
-	 * If we have something to service, the tasklet will re-enable ints.
-	 * If we *don't* have something, we'll re-enable before leaving here. */
-	inta_mask = iwl_read32(priv, CSR_INT_MASK);  /* just for debug */
-	iwl_write32(priv, CSR_INT_MASK, 0x00000000);
-
-	/* Discover which interrupts are active/pending */
-	inta = iwl_read32(priv, CSR_INT);
-	inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS);
+	prev_tx_power = priv->tx_power_user_lmt;
+	priv->tx_power_user_lmt = tx_power;
 
-	/* Ignore interrupt if there's nothing in NIC to service.
-	 * This may be due to IRQ shared with another device,
-	 * or due to sporadic interrupts thrown from our NIC. */
-	if (!inta && !inta_fh) {
-		IWL_DEBUG_ISR(priv, "Ignore interrupt, inta == 0, inta_fh == 0\n");
-		goto none;
-	}
+	ret = priv->cfg->ops->lib->send_tx_power(priv);
 
-	if ((inta == 0xFFFFFFFF) || ((inta & 0xFFFFFFF0) == 0xa5a5a5a0)) {
-		/* Hardware disappeared. It might have already raised
-		 * an interrupt */
-		IWL_WARN(priv, "HARDWARE GONE?? INTA == 0x%08x\n", inta);
-		goto unplugged;
+	/* if fail to set tx_power, restore the orig. tx power */
+	if (ret) {
+		priv->tx_power_user_lmt = prev_tx_power;
+		priv->tx_power_next = prev_tx_power;
 	}
-
-	IWL_DEBUG_ISR(priv, "ISR inta 0x%08x, enabled 0x%08x, fh 0x%08x\n",
-		      inta, inta_mask, inta_fh);
-
-	inta &= ~CSR_INT_BIT_SCD;
-
-	/* iwl_irq_tasklet() will service interrupts and re-enable them */
-	if (likely(inta || inta_fh))
-		tasklet_schedule(&priv->irq_tasklet);
-
- unplugged:
-	spin_unlock_irqrestore(&priv->lock, flags);
-	return IRQ_HANDLED;
-
- none:
-	/* re-enable interrupts here since we don't have anything to service. */
-	/* only Re-enable if diabled by irq */
-	if (test_bit(STATUS_INT_ENABLED, &priv->status))
-		iwl_enable_interrupts(priv);
-	spin_unlock_irqrestore(&priv->lock, flags);
-	return IRQ_NONE;
+	return ret;
 }
-EXPORT_SYMBOL(iwl_isr_legacy);
+EXPORT_SYMBOL(iwl_set_tx_power);
 
 void iwl_send_bt_config(struct iwl_priv *priv)
 {
@@ -1326,6 +1223,7 @@ void iwl_send_bt_config(struct iwl_priv
 	else
 		bt_cmd.flags = BT_COEX_ENABLE;
 
+	priv->bt_enable_flag = bt_cmd.flags;
 	IWL_DEBUG_INFO(priv, "BT coex %s\n",
 		(bt_cmd.flags == BT_COEX_DISABLE) ? "disable" : "active");
 
@@ -1452,318 +1350,51 @@ int iwl_mac_tx_last_beacon(struct ieee80
 }
 EXPORT_SYMBOL_GPL(iwl_mac_tx_last_beacon);
 
-static void iwl_ht_conf(struct iwl_priv *priv,
-			struct ieee80211_vif *vif)
+static int iwl_set_mode(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
 {
-	struct iwl_ht_config *ht_conf = &priv->current_ht_config;
-	struct ieee80211_sta *sta;
-	struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
-	struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);
-
-	IWL_DEBUG_MAC80211(priv, "enter:\n");
-
-	if (!ctx->ht.enabled)
-		return;
-
-	ctx->ht.protection =
-		bss_conf->ht_operation_mode & IEEE80211_HT_OP_MODE_PROTECTION;
-	ctx->ht.non_gf_sta_present =
-		!!(bss_conf->ht_operation_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT);
-
-	ht_conf->single_chain_sufficient = false;
-
-	switch (vif->type) {
-	case NL80211_IFTYPE_STATION:
-		rcu_read_lock();
-		sta = ieee80211_find_sta(vif, bss_conf->bssid);
-		if (sta) {
-			struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap;
-			int maxstreams;
-
-			maxstreams = (ht_cap->mcs.tx_params &
-				      IEEE80211_HT_MCS_TX_MAX_STREAMS_MASK)
-					>> IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT;
-			maxstreams += 1;
-
-			if ((ht_cap->mcs.rx_mask[1] == 0) &&
-			    (ht_cap->mcs.rx_mask[2] == 0))
-				ht_conf->single_chain_sufficient = true;
-			if (maxstreams <= 1)
-				ht_conf->single_chain_sufficient = true;
-		} else {
-			/*
-			 * If at all, this can only happen through a race
-			 * when the AP disconnects us while we're still
-			 * setting up the connection, in that case mac80211
-			 * will soon tell us about that.
-			 */
-			ht_conf->single_chain_sufficient = true;
-		}
-		rcu_read_unlock();
-		break;
-	case NL80211_IFTYPE_ADHOC:
-		ht_conf->single_chain_sufficient = true;
-		break;
-	default:
-		break;
-	}
-
-	IWL_DEBUG_MAC80211(priv, "leave\n");
-}
+	iwl_connection_init_rx_config(priv, ctx);
 
-static inline void iwl_set_no_assoc(struct iwl_priv *priv,
-				    struct ieee80211_vif *vif)
-{
-	struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);
+	if (priv->cfg->ops->hcmd->set_rxon_chain)
+		priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
 
-	iwl_led_disassociate(priv);
-	/*
-	 * inform the ucode that there is no longer an
-	 * association and that no more packets should be
-	 * sent
-	 */
-	ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
-	ctx->staging.assoc_id = 0;
-	iwlcore_commit_rxon(priv, ctx);
+	return iwlcore_commit_rxon(priv, ctx);
 }
 
-static void iwlcore_beacon_update(struct ieee80211_hw *hw,
-				  struct ieee80211_vif *vif)
+static int iwl_setup_interface(struct iwl_priv *priv,
+			       struct iwl_rxon_context *ctx)
 {
-	struct iwl_priv *priv = hw->priv;
-	unsigned long flags;
-	__le64 timestamp;
-	struct sk_buff *skb = ieee80211_beacon_get(hw, vif);
-
-	if (!skb)
-		return;
-
-	IWL_DEBUG_ASSOC(priv, "enter\n");
+	struct ieee80211_vif *vif = ctx->vif;
+	int err;
 
 	lockdep_assert_held(&priv->mutex);
 
-	if (!priv->beacon_ctx) {
-		IWL_ERR(priv, "update beacon but no beacon context!\n");
-		dev_kfree_skb(skb);
-		return;
-	}
-
-	spin_lock_irqsave(&priv->lock, flags);
-
-	if (priv->beacon_skb)
-		dev_kfree_skb(priv->beacon_skb);
-
-	priv->beacon_skb = skb;
-
-	timestamp = ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp;
-	priv->timestamp = le64_to_cpu(timestamp);
-
-	IWL_DEBUG_ASSOC(priv, "leave\n");
-
-	spin_unlock_irqrestore(&priv->lock, flags);
-
-	if (!iwl_is_ready_rf(priv)) {
-		IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n");
-		return;
-	}
-
-	priv->cfg->ops->lib->post_associate(priv, priv->beacon_ctx->vif);
-}
-
-void iwl_bss_info_changed(struct ieee80211_hw *hw,
-			  struct ieee80211_vif *vif,
-			  struct ieee80211_bss_conf *bss_conf,
-			  u32 changes)
-{
-	struct iwl_priv *priv = hw->priv;
-	struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);
-	int ret;
-
-	IWL_DEBUG_MAC80211(priv, "changes = 0x%X\n", changes);
-
-	if (!iwl_is_alive(priv))
-		return;
-
-	mutex_lock(&priv->mutex);
-
-	if (changes & BSS_CHANGED_QOS) {
-		unsigned long flags;
-
-		spin_lock_irqsave(&priv->lock, flags);
-		ctx->qos_data.qos_active = bss_conf->qos;
-		iwl_update_qos(priv, ctx);
-		spin_unlock_irqrestore(&priv->lock, flags);
-	}
-
-	if (changes & BSS_CHANGED_BEACON_ENABLED) {
-		/*
-		 * the add_interface code must make sure we only ever
-		 * have a single interface that could be beaconing at
-		 * any time.
-		 */
-		if (vif->bss_conf.enable_beacon)
-			priv->beacon_ctx = ctx;
-		else
-			priv->beacon_ctx = NULL;
-	}
-
-	if (changes & BSS_CHANGED_BEACON && vif->type == NL80211_IFTYPE_AP) {
-		dev_kfree_skb(priv->beacon_skb);
-		priv->beacon_skb = ieee80211_beacon_get(hw, vif);
-	}
-
-	if (changes & BSS_CHANGED_BEACON_INT && vif->type == NL80211_IFTYPE_AP)
-		iwl_send_rxon_timing(priv, ctx);
-
-	if (changes & BSS_CHANGED_BSSID) {
-		IWL_DEBUG_MAC80211(priv, "BSSID %pM\n", bss_conf->bssid);
-
-		/*
-		 * If there is currently a HW scan going on in the
-		 * background then we need to cancel it else the RXON
-		 * below/in post_associate will fail.
-		 */
-		if (iwl_scan_cancel_timeout(priv, 100)) {
-			IWL_WARN(priv, "Aborted scan still in progress after 100ms\n");
-			IWL_DEBUG_MAC80211(priv, "leaving - scan abort failed.\n");
-			mutex_unlock(&priv->mutex);
-			return;
-		}
-
-		/* mac80211 only sets assoc when in STATION mode */
-		if (vif->type == NL80211_IFTYPE_ADHOC || bss_conf->assoc) {
-			memcpy(ctx->staging.bssid_addr,
-			       bss_conf->bssid, ETH_ALEN);
-
-			/* currently needed in a few places */
-			memcpy(priv->bssid, bss_conf->bssid, ETH_ALEN);
-		} else {
-			ctx->staging.filter_flags &=
-				~RXON_FILTER_ASSOC_MSK;
-		}
-
-	}
-
 	/*
-	 * This needs to be after setting the BSSID in case
-	 * mac80211 decides to do both changes at once because
-	 * it will invoke post_associate.
+	 * This variable will be correct only when there's just
+	 * a single context, but all code using it is for hardware
+	 * that supports only one context.
 	 */
-	if (vif->type == NL80211_IFTYPE_ADHOC && changes & BSS_CHANGED_BEACON)
-		iwlcore_beacon_update(hw, vif);
+	priv->iw_mode = vif->type;
 
-	if (changes & BSS_CHANGED_ERP_PREAMBLE) {
-		IWL_DEBUG_MAC80211(priv, "ERP_PREAMBLE %d\n",
-				   bss_conf->use_short_preamble);
-		if (bss_conf->use_short_preamble)
-			ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
-		else
-			ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
-	}
+	ctx->is_active = true;
 
-	if (changes & BSS_CHANGED_ERP_CTS_PROT) {
-		IWL_DEBUG_MAC80211(priv, "ERP_CTS %d\n", bss_conf->use_cts_prot);
-		if (bss_conf->use_cts_prot && (priv->band != IEEE80211_BAND_5GHZ))
-			ctx->staging.flags |= RXON_FLG_TGG_PROTECT_MSK;
-		else
-			ctx->staging.flags &= ~RXON_FLG_TGG_PROTECT_MSK;
-		if (bss_conf->use_cts_prot)
-			ctx->staging.flags |= RXON_FLG_SELF_CTS_EN;
-		else
-			ctx->staging.flags &= ~RXON_FLG_SELF_CTS_EN;
+	err = iwl_set_mode(priv, ctx);
+	if (err) {
+		if (!ctx->always_active)
+			ctx->is_active = false;
+		return err;
 	}
 
-	if (changes & BSS_CHANGED_BASIC_RATES) {
-		/* XXX use this information
-		 *
-		 * To do that, remove code from iwl_set_rate() and put something
-		 * like this here:
-		 *
-		if (A-band)
-			ctx->staging.ofdm_basic_rates =
-				bss_conf->basic_rates;
-		else
-			ctx->staging.ofdm_basic_rates =
-				bss_conf->basic_rates >> 4;
-			ctx->staging.cck_basic_rates =
-				bss_conf->basic_rates & 0xF;
+	if (priv->cfg->bt_params && priv->cfg->bt_params->advanced_bt_coexist &&
+	    vif->type == NL80211_IFTYPE_ADHOC) {
+		/*
+		 * pretend to have high BT traffic as long as we
+		 * are operating in IBSS mode, as this will cause
+		 * the rate scaling etc. to behave as intended.
 		 */
+		priv->bt_traffic_load = IWL_BT_COEX_TRAFFIC_LOAD_HIGH;
 	}
 
-	if (changes & BSS_CHANGED_HT) {
-		iwl_ht_conf(priv, vif);
-
-		if (priv->cfg->ops->hcmd->set_rxon_chain)
-			priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
-	}
-
-	if (changes & BSS_CHANGED_ASSOC) {
-		IWL_DEBUG_MAC80211(priv, "ASSOC %d\n", bss_conf->assoc);
-		if (bss_conf->assoc) {
-			priv->timestamp = bss_conf->timestamp;
-
-			iwl_led_associate(priv);
-
-			if (!iwl_is_rfkill(priv))
-				priv->cfg->ops->lib->post_associate(priv, vif);
-		} else
-			iwl_set_no_assoc(priv, vif);
-	}
-
-	if (changes && iwl_is_associated_ctx(ctx) && bss_conf->aid) {
-		IWL_DEBUG_MAC80211(priv, "Changes (%#x) while associated\n",
-				   changes);
-		ret = iwl_send_rxon_assoc(priv, ctx);
-		if (!ret) {
-			/* Sync active_rxon with latest change. */
-			memcpy((void *)&ctx->active,
-				&ctx->staging,
-				sizeof(struct iwl_rxon_cmd));
-		}
-	}
-
-	if (changes & BSS_CHANGED_BEACON_ENABLED) {
-		if (vif->bss_conf.enable_beacon) {
-			memcpy(ctx->staging.bssid_addr,
-			       bss_conf->bssid, ETH_ALEN);
-			memcpy(priv->bssid, bss_conf->bssid, ETH_ALEN);
-			iwl_led_associate(priv);
-			iwlcore_config_ap(priv, vif);
-		} else
-			iwl_set_no_assoc(priv, vif);
-	}
-
-	if (changes & BSS_CHANGED_IBSS) {
-		ret = priv->cfg->ops->lib->manage_ibss_station(priv, vif,
-							bss_conf->ibss_joined);
-		if (ret)
-			IWL_ERR(priv, "failed to %s IBSS station %pM\n",
-				bss_conf->ibss_joined ? "add" : "remove",
-				bss_conf->bssid);
-	}
-
-	if (changes & BSS_CHANGED_IDLE &&
-	    priv->cfg->ops->hcmd->set_pan_params) {
-		if (priv->cfg->ops->hcmd->set_pan_params(priv))
-			IWL_ERR(priv, "failed to update PAN params\n");
-	}
-
-	mutex_unlock(&priv->mutex);
-
-	IWL_DEBUG_MAC80211(priv, "leave\n");
-}
-EXPORT_SYMBOL(iwl_bss_info_changed);
-
-static int iwl_set_mode(struct iwl_priv *priv, struct ieee80211_vif *vif)
-{
-	struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);
-
-	iwl_connection_init_rx_config(priv, ctx);
-
-	if (priv->cfg->ops->hcmd->set_rxon_chain)
-		priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
-
-	return iwlcore_commit_rxon(priv, ctx);
+	return 0;
 }
 
 int iwl_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
@@ -1771,7 +1402,7 @@ int iwl_mac_add_interface(struct ieee802
 	struct iwl_priv *priv = hw->priv;
 	struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
 	struct iwl_rxon_context *tmp, *ctx = NULL;
-	int err = 0;
+	int err;
 
 	IWL_DEBUG_MAC80211(priv, "enter: type %d, addr %pM\n",
 			   vif->type, vif->addr);
@@ -1813,36 +1444,11 @@ int iwl_mac_add_interface(struct ieee802
 
 	vif_priv->ctx = ctx;
 	ctx->vif = vif;
-	/*
-	 * This variable will be correct only when there's just
-	 * a single context, but all code using it is for hardware
-	 * that supports only one context.
-	 */
-	priv->iw_mode = vif->type;
-
-	ctx->is_active = true;
-
-	err = iwl_set_mode(priv, vif);
-	if (err) {
-		if (!ctx->always_active)
-			ctx->is_active = false;
-		goto out_err;
-	}
 
-	if (priv->cfg->bt_params &&
-	    priv->cfg->bt_params->advanced_bt_coexist &&
-	    vif->type == NL80211_IFTYPE_ADHOC) {
-		/*
-		 * pretend to have high BT traffic as long as we
-		 * are operating in IBSS mode, as this will cause
-		 * the rate scaling etc. to behave as intended.
-		 */
-		priv->bt_traffic_load = IWL_BT_COEX_TRAFFIC_LOAD_HIGH;
-	}
-
-	goto out;
+	err = iwl_setup_interface(priv, ctx);
+	if (!err)
+		goto out;
 
- out_err:
 	ctx->vif = NULL;
 	priv->iw_mode = NL80211_IFTYPE_STATION;
  out:
@@ -1853,27 +1459,24 @@ int iwl_mac_add_interface(struct ieee802
 }
 EXPORT_SYMBOL(iwl_mac_add_interface);
 
-void iwl_mac_remove_interface(struct ieee80211_hw *hw,
-			      struct ieee80211_vif *vif)
+static void iwl_teardown_interface(struct iwl_priv *priv,
+				   struct ieee80211_vif *vif,
+				   bool mode_change)
 {
-	struct iwl_priv *priv = hw->priv;
 	struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);
 
-	IWL_DEBUG_MAC80211(priv, "enter\n");
-
-	mutex_lock(&priv->mutex);
-
-	WARN_ON(ctx->vif != vif);
-	ctx->vif = NULL;
+	lockdep_assert_held(&priv->mutex);
 
 	if (priv->scan_vif == vif) {
 		iwl_scan_cancel_timeout(priv, 200);
 		iwl_force_scan_end(priv);
 	}
-	iwl_set_mode(priv, vif);
 
-	if (!ctx->always_active)
-		ctx->is_active = false;
+	if (!mode_change) {
+		iwl_set_mode(priv, ctx);
+		if (!ctx->always_active)
+			ctx->is_active = false;
+	}
 
 	/*
 	 * When removing the IBSS interface, overwrite the
@@ -1883,211 +1486,31 @@ void iwl_mac_remove_interface(struct iee
 	 * both values are the same and zero.
 	 */
 	if (vif->type == NL80211_IFTYPE_ADHOC)
-		priv->bt_traffic_load = priv->notif_bt_traffic_load;
-
-	memset(priv->bssid, 0, ETH_ALEN);
-	mutex_unlock(&priv->mutex);
-
-	IWL_DEBUG_MAC80211(priv, "leave\n");
-
-}
-EXPORT_SYMBOL(iwl_mac_remove_interface);
-
-/**
- * iwl_mac_config - mac80211 config callback
- */
-int iwl_mac_config(struct ieee80211_hw *hw, u32 changed)
-{
-	struct iwl_priv *priv = hw->priv;
-	const struct iwl_channel_info *ch_info;
-	struct ieee80211_conf *conf = &hw->conf;
-	struct ieee80211_channel *channel = conf->channel;
-	struct iwl_ht_config *ht_conf = &priv->current_ht_config;
-	struct iwl_rxon_context *ctx;
-	unsigned long flags = 0;
-	int ret = 0;
-	u16 ch;
-	int scan_active = 0;
-
-	mutex_lock(&priv->mutex);
-
-	IWL_DEBUG_MAC80211(priv, "enter to channel %d changed 0x%X\n",
-					channel->hw_value, changed);
-
-	if (unlikely(!priv->cfg->mod_params->disable_hw_scan &&
-			test_bit(STATUS_SCANNING, &priv->status))) {
-		scan_active = 1;
-		IWL_DEBUG_MAC80211(priv, "leave - scanning\n");
-	}
-
-	if (changed & (IEEE80211_CONF_CHANGE_SMPS |
-		       IEEE80211_CONF_CHANGE_CHANNEL)) {
-		/* mac80211 uses static for non-HT which is what we want */
-		priv->current_ht_config.smps = conf->smps_mode;
-
-		/*
-		 * Recalculate chain counts.
-		 *
-		 * If monitor mode is enabled then mac80211 will
-		 * set up the SM PS mode to OFF if an HT channel is
-		 * configured.
-		 */
-		if (priv->cfg->ops->hcmd->set_rxon_chain)
-			for_each_context(priv, ctx)
-				priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
-	}
-
-	/* during scanning mac80211 will delay channel setting until
-	 * scan finish with changed = 0
-	 */
-	if (!changed || (changed & IEEE80211_CONF_CHANGE_CHANNEL)) {
-		if (scan_active)
-			goto set_ch_out;
-
-		ch = channel->hw_value;
-		ch_info = iwl_get_channel_info(priv, channel->band, ch);
-		if (!is_channel_valid(ch_info)) {
-			IWL_DEBUG_MAC80211(priv, "leave - invalid channel\n");
-			ret = -EINVAL;
-			goto set_ch_out;
-		}
-
-		spin_lock_irqsave(&priv->lock, flags);
-
-		for_each_context(priv, ctx) {
-			/* Configure HT40 channels */
-			ctx->ht.enabled = conf_is_ht(conf);
-			if (ctx->ht.enabled) {
-				if (conf_is_ht40_minus(conf)) {
-					ctx->ht.extension_chan_offset =
-						IEEE80211_HT_PARAM_CHA_SEC_BELOW;
-					ctx->ht.is_40mhz = true;
-				} else if (conf_is_ht40_plus(conf)) {
-					ctx->ht.extension_chan_offset =
-						IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
-					ctx->ht.is_40mhz = true;
-				} else {
-					ctx->ht.extension_chan_offset =
-						IEEE80211_HT_PARAM_CHA_SEC_NONE;
-					ctx->ht.is_40mhz = false;
-				}
-			} else
-				ctx->ht.is_40mhz = false;
-
-			/*
-			 * Default to no protection. Protection mode will
-			 * later be set from BSS config in iwl_ht_conf
-			 */
-			ctx->ht.protection = IEEE80211_HT_OP_MODE_PROTECTION_NONE;
-
-			/* if we are switching from ht to 2.4 clear flags
-			 * from any ht related info since 2.4 does not
-			 * support ht */
-			if ((le16_to_cpu(ctx->staging.channel) != ch))
-				ctx->staging.flags = 0;
-
-			iwl_set_rxon_channel(priv, channel, ctx);
-			iwl_set_rxon_ht(priv, ht_conf);
-
-			iwl_set_flags_for_band(priv, ctx, channel->band,
-					       ctx->vif);
-		}
-
-		spin_unlock_irqrestore(&priv->lock, flags);
-
-		if (priv->cfg->ops->lib->update_bcast_stations)
-			ret = priv->cfg->ops->lib->update_bcast_stations(priv);
-
- set_ch_out:
-		/* The list of supported rates and rate mask can be different
-		 * for each band; since the band may have changed, reset
-		 * the rate mask to what mac80211 lists */
-		iwl_set_rate(priv);
-	}
-
-	if (changed & (IEEE80211_CONF_CHANGE_PS |
-			IEEE80211_CONF_CHANGE_IDLE)) {
-		ret = iwl_power_update_mode(priv, false);
-		if (ret)
-			IWL_DEBUG_MAC80211(priv, "Error setting sleep level\n");
-	}
-
-	if (changed & IEEE80211_CONF_CHANGE_POWER) {
-		IWL_DEBUG_MAC80211(priv, "TX Power old=%d new=%d\n",
-			priv->tx_power_user_lmt, conf->power_level);
-
-		iwl_set_tx_power(priv, conf->power_level, false);
-	}
-
-	if (!iwl_is_ready(priv)) {
-		IWL_DEBUG_MAC80211(priv, "leave - not ready\n");
-		goto out;
-	}
-
-	if (scan_active)
-		goto out;
-
-	for_each_context(priv, ctx) {
-		if (memcmp(&ctx->active, &ctx->staging, sizeof(ctx->staging)))
-			iwlcore_commit_rxon(priv, ctx);
-		else
-			IWL_DEBUG_INFO(priv,
-				"Not re-sending same RXON configuration.\n");
-	}
-
-out:
-	IWL_DEBUG_MAC80211(priv, "leave\n");
-	mutex_unlock(&priv->mutex);
-	return ret;
+		priv->bt_traffic_load = priv->last_bt_traffic_load;
 }
-EXPORT_SYMBOL(iwl_mac_config);
 
-void iwl_mac_reset_tsf(struct ieee80211_hw *hw)
+void iwl_mac_remove_interface(struct ieee80211_hw *hw,
+			      struct ieee80211_vif *vif)
 {
 	struct iwl_priv *priv = hw->priv;
-	unsigned long flags;
-	/* IBSS can only be the IWL_RXON_CTX_BSS context */
-	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
+	struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);
 
-	mutex_lock(&priv->mutex);
 	IWL_DEBUG_MAC80211(priv, "enter\n");
 
-	spin_lock_irqsave(&priv->lock, flags);
-	memset(&priv->current_ht_config, 0, sizeof(struct iwl_ht_config));
-	spin_unlock_irqrestore(&priv->lock, flags);
-
-	spin_lock_irqsave(&priv->lock, flags);
-
-	/* new association get rid of ibss beacon skb */
-	if (priv->beacon_skb)
-		dev_kfree_skb(priv->beacon_skb);
-
-	priv->beacon_skb = NULL;
-
-	priv->timestamp = 0;
-
-	spin_unlock_irqrestore(&priv->lock, flags);
-
-	iwl_scan_cancel_timeout(priv, 100);
-	if (!iwl_is_ready_rf(priv)) {
-		IWL_DEBUG_MAC80211(priv, "leave - not ready\n");
-		mutex_unlock(&priv->mutex);
-		return;
-	}
+	mutex_lock(&priv->mutex);
 
-	/* we are restarting association process
-	 * clear RXON_FILTER_ASSOC_MSK bit
-	 */
-	ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
-	iwlcore_commit_rxon(priv, ctx);
+	WARN_ON(ctx->vif != vif);
+	ctx->vif = NULL;
 
-	iwl_set_rate(priv);
+	iwl_teardown_interface(priv, vif, false);
 
+	memset(priv->bssid, 0, ETH_ALEN);
 	mutex_unlock(&priv->mutex);
 
 	IWL_DEBUG_MAC80211(priv, "leave\n");
+
 }
-EXPORT_SYMBOL(iwl_mac_reset_tsf);
+EXPORT_SYMBOL(iwl_mac_remove_interface);
 
 int iwl_alloc_txq_mem(struct iwl_priv *priv)
 {
@@ -2431,77 +1854,115 @@ int iwl_force_reset(struct iwl_priv *pri
 	return 0;
 }
 
-/**
- * iwl_bg_monitor_recover - Timer callback to check for stuck queue and recover
- *
- * During normal condition (no queue is stuck), the timer is continually set to
- * execute every monitor_recover_period milliseconds after the last timer
- * expired.  When the queue read_ptr is at the same place, the timer is
- * shorten to 100mSecs.  This is
- *      1) to reduce the chance that the read_ptr may wrap around (not stuck)
- *      2) to detect the stuck queues quicker before the station and AP can
- *      disassociate each other.
- *
- * This function monitors all the tx queues and recover from it if any
- * of the queues are stuck.
- * 1. It first check the cmd queue for stuck conditions.  If it is stuck,
- *      it will recover by resetting the firmware and return.
- * 2. Then, it checks for station association.  If it associates it will check
- *      other queues.  If any queue is stuck, it will recover by resetting
- *      the firmware.
- * Note: It the number of times the queue read_ptr to be at the same place to
- *      be MAX_REPEAT+1 in order to consider to be stuck.
- */
+int iwl_mac_change_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+			     enum nl80211_iftype newtype, bool newp2p)
+{
+	struct iwl_priv *priv = hw->priv;
+	struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);
+	struct iwl_rxon_context *tmp;
+	u32 interface_modes;
+	int err;
+
+	newtype = ieee80211_iftype_p2p(newtype, newp2p);
+
+	mutex_lock(&priv->mutex);
+
+	interface_modes = ctx->interface_modes | ctx->exclusive_interface_modes;
+
+	if (!(interface_modes & BIT(newtype))) {
+		err = -EBUSY;
+		goto out;
+	}
+
+	if (ctx->exclusive_interface_modes & BIT(newtype)) {
+		for_each_context(priv, tmp) {
+			if (ctx == tmp)
+				continue;
+
+			if (!tmp->vif)
+				continue;
+
+			/*
+			 * The current mode switch would be exclusive, but
+			 * another context is active ... refuse the switch.
+			 */
+			err = -EBUSY;
+			goto out;
+		}
+	}
+
+	/* success */
+	iwl_teardown_interface(priv, vif, true);
+	vif->type = newtype;
+	err = iwl_setup_interface(priv, ctx);
+	WARN_ON(err);
+	/*
+	 * We've switched internally, but submitting to the
+	 * device may have failed for some reason. Mask this
+	 * error, because otherwise mac80211 will not switch
+	 * (and set the interface type back) and we'll be
+	 * out of sync with it.
+	 */
+	err = 0;
+
+ out:
+	mutex_unlock(&priv->mutex);
+	return err;
+}
+EXPORT_SYMBOL(iwl_mac_change_interface);
+
 /*
- * The maximum number of times the read pointer of the tx queue at the
- * same place without considering to be stuck.
+ * On every watchdog tick we check (latest) time stamp. If it does not
+ * change during timeout period and queue is not empty we reset firmware.
  */
-#define MAX_REPEAT      (2)
 static int iwl_check_stuck_queue(struct iwl_priv *priv, int cnt)
 {
-	struct iwl_tx_queue *txq;
-	struct iwl_queue *q;
+	struct iwl_tx_queue *txq = &priv->txq[cnt];
+	struct iwl_queue *q = &txq->q;
+	unsigned long timeout;
+	int ret;
 
-	txq = &priv->txq[cnt];
-	q = &txq->q;
-	/* queue is empty, skip */
-	if (q->read_ptr == q->write_ptr)
+	if (q->read_ptr == q->write_ptr) {
+		txq->time_stamp = jiffies;
 		return 0;
+	}
 
-	if (q->read_ptr == q->last_read_ptr) {
-		/* a queue has not been read from last time */
-		if (q->repeat_same_read_ptr > MAX_REPEAT) {
-			IWL_ERR(priv,
-				"queue %d stuck %d time. Fw reload.\n",
-				q->id, q->repeat_same_read_ptr);
-			q->repeat_same_read_ptr = 0;
-			iwl_force_reset(priv, IWL_FW_RESET, false);
-		} else {
-			q->repeat_same_read_ptr++;
-			IWL_DEBUG_RADIO(priv,
-					"queue %d, not read %d time\n",
-					q->id,
-					q->repeat_same_read_ptr);
-			mod_timer(&priv->monitor_recover,
-				jiffies + msecs_to_jiffies(
-				IWL_ONE_HUNDRED_MSECS));
-			return 1;
-		}
-	} else {
-		q->last_read_ptr = q->read_ptr;
-		q->repeat_same_read_ptr = 0;
+	timeout = txq->time_stamp +
+		  msecs_to_jiffies(priv->cfg->base_params->wd_timeout);
+
+	if (time_after(jiffies, timeout)) {
+		IWL_ERR(priv, "Queue %d stuck for %u ms.\n",
+				q->id, priv->cfg->base_params->wd_timeout);
+		ret = iwl_force_reset(priv, IWL_FW_RESET, false);
+		return (ret == -EAGAIN) ? 0 : 1;
 	}
+
 	return 0;
 }
 
-void iwl_bg_monitor_recover(unsigned long data)
+/*
+ * Making watchdog tick be a quarter of timeout assure we will
+ * discover the queue hung between timeout and 1.25*timeout
+ */
+#define IWL_WD_TICK(timeout) ((timeout) / 4)
+
+/*
+ * Watchdog timer callback, we check each tx queue for stuck, if if hung
+ * we reset the firmware. If everything is fine just rearm the timer.
+ */
+void iwl_bg_watchdog(unsigned long data)
 {
 	struct iwl_priv *priv = (struct iwl_priv *)data;
 	int cnt;
+	unsigned long timeout;
 
 	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
 		return;
 
+	timeout = priv->cfg->base_params->wd_timeout;
+	if (timeout == 0)
+		return;
+
 	/* monitor and check for stuck cmd queue */
 	if (iwl_check_stuck_queue(priv, priv->cmd_queue))
 		return;
@@ -2516,17 +1977,23 @@ void iwl_bg_monitor_recover(unsigned lon
 				return;
 		}
 	}
-	if (priv->cfg->base_params->monitor_recover_period) {
-		/*
-		 * Reschedule the timer to occur in
-		 * priv->cfg->base_params->monitor_recover_period
-		 */
-		mod_timer(&priv->monitor_recover, jiffies + msecs_to_jiffies(
-			  priv->cfg->base_params->monitor_recover_period));
-	}
+
+	mod_timer(&priv->watchdog, jiffies +
+		  msecs_to_jiffies(IWL_WD_TICK(timeout)));
 }
-EXPORT_SYMBOL(iwl_bg_monitor_recover);
+EXPORT_SYMBOL(iwl_bg_watchdog);
 
+void iwl_setup_watchdog(struct iwl_priv *priv)
+{
+	unsigned int timeout = priv->cfg->base_params->wd_timeout;
+
+	if (timeout)
+		mod_timer(&priv->watchdog,
+			  jiffies + msecs_to_jiffies(IWL_WD_TICK(timeout)));
+	else
+		del_timer(&priv->watchdog);
+}
+EXPORT_SYMBOL(iwl_setup_watchdog);
 
 /*
  * extended beacon time format
@@ -2584,8 +2051,9 @@ EXPORT_SYMBOL(iwl_add_beacon_time);
 
 #ifdef CONFIG_PM
 
-int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state)
+int iwl_pci_suspend(struct device *device)
 {
+	struct pci_dev *pdev = to_pci_dev(device);
 	struct iwl_priv *priv = pci_get_drvdata(pdev);
 
 	/*
@@ -2597,18 +2065,14 @@ int iwl_pci_suspend(struct pci_dev *pdev
 	 */
 	iwl_apm_stop(priv);
 
-	pci_save_state(pdev);
-	pci_disable_device(pdev);
-	pci_set_power_state(pdev, PCI_D3hot);
-
 	return 0;
 }
 EXPORT_SYMBOL(iwl_pci_suspend);
 
-int iwl_pci_resume(struct pci_dev *pdev)
+int iwl_pci_resume(struct device *device)
 {
+	struct pci_dev *pdev = to_pci_dev(device);
 	struct iwl_priv *priv = pci_get_drvdata(pdev);
-	int ret;
 	bool hw_rfkill = false;
 
 	/*
@@ -2617,11 +2081,6 @@ int iwl_pci_resume(struct pci_dev *pdev)
 	 */
 	pci_write_config_byte(pdev, PCI_CFG_RETRY_TIMEOUT, 0x00);
 
-	pci_set_power_state(pdev, PCI_D0);
-	ret = pci_enable_device(pdev);
-	if (ret)
-		return ret;
-	pci_restore_state(pdev);
 	iwl_enable_interrupts(priv);
 
 	if (!(iwl_read32(priv, CSR_GP_CNTRL) &
@@ -2639,4 +2098,14 @@ int iwl_pci_resume(struct pci_dev *pdev)
 }
 EXPORT_SYMBOL(iwl_pci_resume);
 
+const struct dev_pm_ops iwl_pm_ops = {
+	.suspend = iwl_pci_suspend,
+	.resume = iwl_pci_resume,
+	.freeze = iwl_pci_suspend,
+	.thaw = iwl_pci_resume,
+	.poweroff = iwl_pci_suspend,
+	.restore = iwl_pci_resume,
+};
+EXPORT_SYMBOL(iwl_pm_ops);
+
 #endif /* CONFIG_PM */
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/iwlwifi/iwl-core.h linux-libre-2.6.38-gnu1/drivers/net/wireless/iwlwifi/iwl-core.h
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/iwlwifi/iwl-core.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/iwlwifi/iwl-core.h	2011-03-14 21:20:32.000000000 -0400
@@ -120,6 +120,14 @@ struct iwl_apm_ops {
 	void (*config)(struct iwl_priv *priv);
 };
 
+struct iwl_isr_ops {
+	irqreturn_t (*isr) (int irq, void *data);
+	void (*free)(struct iwl_priv *priv);
+	int (*alloc)(struct iwl_priv *priv);
+	int (*reset)(struct iwl_priv *priv);
+	void (*disable)(struct iwl_priv *priv);
+};
+
 struct iwl_debugfs_ops {
 	ssize_t (*rx_stats_read)(struct file *file, char __user *user_buf,
 				 size_t count, loff_t *ppos);
@@ -193,22 +201,15 @@ struct iwl_lib_ops {
 	/* power */
 	int (*send_tx_power) (struct iwl_priv *priv);
 	void (*update_chain_flags)(struct iwl_priv *priv);
-	void (*post_associate)(struct iwl_priv *priv,
-			       struct ieee80211_vif *vif);
-	void (*config_ap)(struct iwl_priv *priv, struct ieee80211_vif *vif);
-	irqreturn_t (*isr) (int irq, void *data);
+
+	/* isr */
+	struct iwl_isr_ops isr_ops;
 
 	/* eeprom operations (as defined in iwl-eeprom.h) */
 	struct iwl_eeprom_ops eeprom_ops;
 
 	/* temperature */
 	struct iwl_temp_ops temp_ops;
-	/* station management */
-	int (*manage_ibss_station)(struct iwl_priv *priv,
-				   struct ieee80211_vif *vif, bool add);
-	int (*update_bcast_stations)(struct iwl_priv *priv);
-	/* recover from tx queue stall */
-	void (*recover_from_tx_stall)(unsigned long data);
 	/* check for plcp health */
 	bool (*check_plcp_health)(struct iwl_priv *priv,
 					struct iwl_rx_packet *pkt);
@@ -235,12 +236,23 @@ struct iwl_nic_ops {
 	void (*additional_nic_config)(struct iwl_priv *priv);
 };
 
+struct iwl_legacy_ops {
+	void (*post_associate)(struct iwl_priv *priv);
+	void (*config_ap)(struct iwl_priv *priv);
+	/* station management */
+	int (*update_bcast_stations)(struct iwl_priv *priv);
+	int (*manage_ibss_station)(struct iwl_priv *priv,
+				   struct ieee80211_vif *vif, bool add);
+};
+
 struct iwl_ops {
 	const struct iwl_lib_ops *lib;
 	const struct iwl_hcmd_ops *hcmd;
 	const struct iwl_hcmd_utils_ops *utils;
 	const struct iwl_led_ops *led;
 	const struct iwl_nic_ops *nic;
+	const struct iwl_legacy_ops *legacy;
+	const struct ieee80211_ops *ieee80211_ops;
 };
 
 struct iwl_mod_params {
@@ -266,7 +278,7 @@ struct iwl_mod_params {
  * @plcp_delta_threshold: plcp error rate threshold used to trigger
  *	radio tuning when there is a high receiving plcp error rate
  * @chain_noise_scale: default chain noise scale used for gain computation
- * @monitor_recover_period: default timer used to check stuck queues
+ * @wd_timeout: TX queues watchdog timeout
  * @temperature_kelvin: temperature report by uCode in kelvin
  * @max_event_log_size: size of event log buffer size for ucode event logging
  * @tx_power_by_driver: tx power calibration performed by driver
@@ -276,7 +288,10 @@ struct iwl_mod_params {
  *	sensitivity calibration operation
  * @chain_noise_calib_by_driver: driver has the capability to perform
  *	chain noise calibration operation
-*/
+ * @shadow_reg_enable: HW shadhow register bit
+ * @no_agg_framecnt_info: uCode do not provide aggregation frame count
+ *	information
+ */
 struct iwl_base_params {
 	int eeprom_size;
 	int num_of_queues;	/* def: HW dependent */
@@ -298,14 +313,15 @@ struct iwl_base_params {
 	const bool support_wimax_coexist;
 	u8 plcp_delta_threshold;
 	s32 chain_noise_scale;
-	/* timer period for monitor the driver queues */
-	u32 monitor_recover_period;
+	unsigned int wd_timeout;
 	bool temperature_kelvin;
 	u32 max_event_log_size;
 	const bool tx_power_by_driver;
 	const bool ucode_tracing;
 	const bool sensitivity_calib_by_driver;
 	const bool chain_noise_calib_by_driver;
+	const bool shadow_reg_enable;
+	const bool no_agg_framecnt_info;
 };
 /*
  * @advanced_bt_coexist: support advanced bt coexist
@@ -315,6 +331,7 @@ struct iwl_base_params {
  * @agg_time_limit: maximum number of uSec in aggregation
  * @ampdu_factor: Maximum A-MPDU length factor
  * @ampdu_density: Minimum A-MPDU spacing
+ * @bt_sco_disable: uCode should not response to BT in SCO/ESCO mode
 */
 struct iwl_bt_params {
 	bool advanced_bt_coexist;
@@ -324,6 +341,7 @@ struct iwl_bt_params {
 	u16 agg_time_limit;
 	u8 ampdu_factor;
 	u8 ampdu_density;
+	bool bt_sco_disable;
 };
 /*
  * @use_rts_for_aggregation: use rts/cts protection for HT traffic
@@ -344,6 +362,10 @@ struct iwl_ht_params {
  * @need_dc_calib: need to perform init dc calibration
  * @need_temp_offset_calib: need to perform temperature offset calibration
  * @scan_antennas: available antenna for scan operation
+ * @led_mode: 0=blinking, 1=On(RF On)/Off(RF Off)
+ * @adv_pm: advance power management
+ * @rx_with_siso_diversity: 1x1 device with rx antenna diversity
+ * @internal_wimax_coex: internal wifi/wimax combo device
  *
  * We enable the driver to be backward compatible wrt API version. The
  * driver specifies which APIs it supports (with @ucode_api_max being the
@@ -389,16 +411,17 @@ struct iwl_cfg {
 	const bool need_dc_calib;	  /* if used set to true */
 	const bool need_temp_offset_calib; /* if used set to true */
 	u8 scan_rx_antennas[IEEE80211_NUM_BANDS];
-	u8 scan_tx_antennas[IEEE80211_NUM_BANDS];
-	const bool use_new_eeprom_reading; /* temporary, remove later */
+	enum iwl_led_mode led_mode;
+	const bool adv_pm;
+	const bool rx_with_siso_diversity;
+	const bool internal_wimax_coex;
 };
 
 /***************************
  *   L i b                 *
  ***************************/
 
-struct ieee80211_hw *iwl_alloc_all(struct iwl_cfg *cfg,
-		struct ieee80211_ops *hw_ops);
+struct ieee80211_hw *iwl_alloc_all(struct iwl_cfg *cfg);
 int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue,
 		    const struct ieee80211_tx_queue_params *params);
 int iwl_mac_tx_last_beacon(struct ieee80211_hw *hw);
@@ -426,23 +449,16 @@ int iwl_set_decrypted_flag(struct iwl_pr
 			   u32 decrypt_res,
 			   struct ieee80211_rx_status *stats);
 void iwl_irq_handle_error(struct iwl_priv *priv);
-void iwl_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif);
-void iwl_bss_info_changed(struct ieee80211_hw *hw,
-				     struct ieee80211_vif *vif,
-				     struct ieee80211_bss_conf *bss_conf,
-				     u32 changes);
 int iwl_mac_add_interface(struct ieee80211_hw *hw,
 			  struct ieee80211_vif *vif);
 void iwl_mac_remove_interface(struct ieee80211_hw *hw,
 			      struct ieee80211_vif *vif);
-int iwl_mac_config(struct ieee80211_hw *hw, u32 changed);
-void iwl_config_ap(struct iwl_priv *priv, struct ieee80211_vif *vif);
-void iwl_mac_reset_tsf(struct ieee80211_hw *hw);
+int iwl_mac_change_interface(struct ieee80211_hw *hw,
+			     struct ieee80211_vif *vif,
+			     enum nl80211_iftype newtype, bool newp2p);
 int iwl_alloc_txq_mem(struct iwl_priv *priv);
 void iwl_free_txq_mem(struct iwl_priv *priv);
-void iwlcore_tx_cmd_protection(struct iwl_priv *priv,
-			       struct ieee80211_tx_info *info,
-			       __le16 fc, __le32 *tx_flags);
+
 #ifdef CONFIG_IWLWIFI_DEBUGFS
 int iwl_alloc_traffic_mem(struct iwl_priv *priv);
 void iwl_free_traffic_mem(struct iwl_priv *priv);
@@ -530,6 +546,7 @@ int iwl_tx_queue_init(struct iwl_priv *p
 void iwl_tx_queue_reset(struct iwl_priv *priv, struct iwl_tx_queue *txq,
 			int slots_num, u32 txq_id);
 void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id);
+void iwl_setup_watchdog(struct iwl_priv *priv);
 /*****************************************************
  * TX power
  ****************************************************/
@@ -599,7 +616,6 @@ int iwl_enqueue_hcmd(struct iwl_priv *pr
 /*****************************************************
  * PCI						     *
  *****************************************************/
-irqreturn_t iwl_isr_legacy(int irq, void *data);
 
 static inline u16 iwl_pcie_link_ctl(struct iwl_priv *priv)
 {
@@ -610,15 +626,23 @@ static inline u16 iwl_pcie_link_ctl(stru
 	return pci_lnk_ctl;
 }
 
-void iwl_bg_monitor_recover(unsigned long data);
+void iwl_bg_watchdog(unsigned long data);
 u32 iwl_usecs_to_beacons(struct iwl_priv *priv, u32 usec, u32 beacon_interval);
 __le32 iwl_add_beacon_time(struct iwl_priv *priv, u32 base,
 			   u32 addon, u32 beacon_interval);
 
 #ifdef CONFIG_PM
-int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state);
-int iwl_pci_resume(struct pci_dev *pdev);
-#endif /* CONFIG_PM */
+int iwl_pci_suspend(struct device *device);
+int iwl_pci_resume(struct device *device);
+extern const struct dev_pm_ops iwl_pm_ops;
+
+#define IWL_PM_OPS	(&iwl_pm_ops)
+
+#else /* !CONFIG_PM */
+
+#define IWL_PM_OPS	NULL
+
+#endif /* !CONFIG_PM */
 
 /*****************************************************
 *  Error Handling Debugging
@@ -725,11 +749,6 @@ static inline int iwlcore_commit_rxon(st
 {
 	return priv->cfg->ops->hcmd->commit_rxon(priv, ctx);
 }
-static inline void iwlcore_config_ap(struct iwl_priv *priv,
-				     struct ieee80211_vif *vif)
-{
-	priv->cfg->ops->lib->config_ap(priv, vif);
-}
 static inline const struct ieee80211_supported_band *iwl_get_hw_mode(
 			struct iwl_priv *priv, enum ieee80211_band band)
 {
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/iwlwifi/iwl-csr.h linux-libre-2.6.38-gnu1/drivers/net/wireless/iwlwifi/iwl-csr.h
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/iwlwifi/iwl-csr.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/iwlwifi/iwl-csr.h	2011-03-14 21:20:32.000000000 -0400
@@ -132,6 +132,8 @@
 
 #define CSR_LED_REG             (CSR_BASE+0x094)
 #define CSR_DRAM_INT_TBL_REG	(CSR_BASE+0x0A0)
+#define CSR_MAC_SHADOW_REG_CTRL	(CSR_BASE+0x0A8) /* 6000 and up */
+
 
 /* GIO Chicken Bits (PCI Express bus link power management) */
 #define CSR_GIO_CHICKEN_BITS    (CSR_BASE+0x100)
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/iwlwifi/iwl-debugfs.c linux-libre-2.6.38-gnu1/drivers/net/wireless/iwlwifi/iwl-debugfs.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/iwlwifi/iwl-debugfs.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/iwlwifi/iwl-debugfs.c	2011-03-14 21:20:32.000000000 -0400
@@ -992,11 +992,8 @@ static ssize_t iwl_dbgfs_tx_queue_read(s
 				" swq_id=%#.2x (ac %d/hwq %d)\n",
 				cnt, q->read_ptr, q->write_ptr,
 				!!test_bit(cnt, priv->queue_stopped),
-				txq->swq_id,
-				txq->swq_id & 0x80 ? txq->swq_id & 3 :
-				txq->swq_id,
-				txq->swq_id & 0x80 ? (txq->swq_id >> 2) &
-				0x1f : txq->swq_id);
+				txq->swq_id, txq->swq_id & 3,
+				(txq->swq_id >> 2) & 0x1f);
 		if (cnt >= 4)
 			continue;
 		/* for the ACs, display the stop count too */
@@ -1537,32 +1534,26 @@ static ssize_t iwl_dbgfs_ucode_bt_stats_
 			user_buf, count, ppos);
 }
 
-static ssize_t iwl_dbgfs_monitor_period_write(struct file *file,
+static ssize_t iwl_dbgfs_wd_timeout_write(struct file *file,
 					const char __user *user_buf,
 					size_t count, loff_t *ppos) {
 
 	struct iwl_priv *priv = file->private_data;
 	char buf[8];
 	int buf_size;
-	int period;
+	int timeout;
 
 	memset(buf, 0, sizeof(buf));
 	buf_size = min(count, sizeof(buf) -  1);
 	if (copy_from_user(buf, user_buf, buf_size))
 		return -EFAULT;
-	if (sscanf(buf, "%d", &period) != 1)
+	if (sscanf(buf, "%d", &timeout) != 1)
 		return -EINVAL;
-	if (period < 0 || period > IWL_MAX_MONITORING_PERIOD)
-		priv->cfg->base_params->monitor_recover_period =
-			IWL_DEF_MONITORING_PERIOD;
-	else
-		priv->cfg->base_params->monitor_recover_period = period;
+	if (timeout < 0 || timeout > IWL_MAX_WD_TIMEOUT)
+		timeout = IWL_DEF_WD_TIMEOUT;
 
-	if (priv->cfg->base_params->monitor_recover_period)
-		mod_timer(&priv->monitor_recover, jiffies + msecs_to_jiffies(
-			  priv->cfg->base_params->monitor_recover_period));
-	else
-		del_timer_sync(&priv->monitor_recover);
+	priv->cfg->base_params->wd_timeout = timeout;
+	iwl_setup_watchdog(priv);
 	return count;
 }
 
@@ -1576,11 +1567,18 @@ static ssize_t iwl_dbgfs_bt_traffic_read
 	const size_t bufsz = sizeof(buf);
 	ssize_t ret;
 
+	if (!priv->bt_enable_flag) {
+		pos += scnprintf(buf + pos, bufsz - pos, "BT coex disabled\n");
+		ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+		return ret;
+	}
+	pos += scnprintf(buf + pos, bufsz - pos, "BT enable flag: 0x%x\n",
+		priv->bt_enable_flag);
 	pos += scnprintf(buf + pos, bufsz - pos, "BT in %s mode\n",
 		priv->bt_full_concurrent ? "full concurrency" : "3-wire");
 	pos += scnprintf(buf + pos, bufsz - pos, "BT status: %s, "
 			 "last traffic notif: %d\n",
-		priv->bt_status ? "On" : "Off", priv->notif_bt_traffic_load);
+		priv->bt_status ? "On" : "Off", priv->last_bt_traffic_load);
 	pos += scnprintf(buf + pos, bufsz - pos, "ch_announcement: %d, "
 			 "sco_active: %d, kill_ack_mask: %x, "
 			 "kill_cts_mask: %x\n",
@@ -1689,7 +1687,7 @@ DEBUGFS_READ_FILE_OPS(rxon_flags);
 DEBUGFS_READ_FILE_OPS(rxon_filter_flags);
 DEBUGFS_WRITE_FILE_OPS(txfifo_flush);
 DEBUGFS_READ_FILE_OPS(ucode_bt_stats);
-DEBUGFS_WRITE_FILE_OPS(monitor_period);
+DEBUGFS_WRITE_FILE_OPS(wd_timeout);
 DEBUGFS_READ_FILE_OPS(bt_traffic);
 DEBUGFS_READ_WRITE_FILE_OPS(protection_mode);
 DEBUGFS_READ_FILE_OPS(reply_tx_error);
@@ -1766,7 +1764,7 @@ int iwl_dbgfs_register(struct iwl_priv *
 	DEBUGFS_ADD_FILE(reply_tx_error, dir_debug, S_IRUSR);
 	DEBUGFS_ADD_FILE(rxon_flags, dir_debug, S_IWUSR);
 	DEBUGFS_ADD_FILE(rxon_filter_flags, dir_debug, S_IWUSR);
-	DEBUGFS_ADD_FILE(monitor_period, dir_debug, S_IWUSR);
+	DEBUGFS_ADD_FILE(wd_timeout, dir_debug, S_IWUSR);
 	if (priv->cfg->bt_params && priv->cfg->bt_params->advanced_bt_coexist)
 		DEBUGFS_ADD_FILE(bt_traffic, dir_debug, S_IRUSR);
 	if (priv->cfg->base_params->sensitivity_calib_by_driver)
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/iwlwifi/iwl-debug.h linux-libre-2.6.38-gnu1/drivers/net/wireless/iwlwifi/iwl-debug.h
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/iwlwifi/iwl-debug.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/iwlwifi/iwl-debug.h	2011-03-14 21:20:32.000000000 -0400
@@ -120,6 +120,7 @@ static inline void iwl_dbgfs_unregister(
 /* 0x000000F0 - 0x00000010 */
 #define IWL_DL_MACDUMP		(1 << 4)
 #define IWL_DL_HCMD_DUMP	(1 << 5)
+#define IWL_DL_EEPROM		(1 << 6)
 #define IWL_DL_RADIO		(1 << 7)
 /* 0x00000F00 - 0x00000100 */
 #define IWL_DL_POWER		(1 << 8)
@@ -164,6 +165,7 @@ static inline void iwl_dbgfs_unregister(
 #define IWL_DEBUG_WEP(p, f, a...)	IWL_DEBUG(p, IWL_DL_WEP, f, ## a)
 #define IWL_DEBUG_HC(p, f, a...)	IWL_DEBUG(p, IWL_DL_HCMD, f, ## a)
 #define IWL_DEBUG_HC_DUMP(p, f, a...)	IWL_DEBUG(p, IWL_DL_HCMD_DUMP, f, ## a)
+#define IWL_DEBUG_EEPROM(p, f, a...)	IWL_DEBUG(p, IWL_DL_EEPROM, f, ## a)
 #define IWL_DEBUG_CALIB(p, f, a...)	IWL_DEBUG(p, IWL_DL_CALIB, f, ## a)
 #define IWL_DEBUG_FW(p, f, a...)	IWL_DEBUG(p, IWL_DL_FW, f, ## a)
 #define IWL_DEBUG_RF_KILL(p, f, a...)	IWL_DEBUG(p, IWL_DL_RF_KILL, f, ## a)
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/iwlwifi/iwl-dev.h linux-libre-2.6.38-gnu1/drivers/net/wireless/iwlwifi/iwl-dev.h
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/iwlwifi/iwl-dev.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/iwlwifi/iwl-dev.h	2011-03-14 21:20:32.000000000 -0400
@@ -129,9 +129,6 @@ struct iwl_queue {
 	int write_ptr;       /* 1-st empty entry (index) host_w*/
 	int read_ptr;         /* last used entry (index) host_r*/
 	/* use for monitoring and recovering the stuck queue */
-	int last_read_ptr;      /* storing the last read_ptr */
-	/* number of time read_ptr and last_read_ptr are the same */
-	u8 repeat_same_read_ptr;
 	dma_addr_t dma_addr;   /* physical addr for BD's */
 	int n_window;	       /* safe queue window */
 	u32 id;
@@ -155,6 +152,7 @@ struct iwl_tx_info {
  * @meta: array of meta data for each command/tx buffer
  * @dma_addr_cmd: physical address of cmd/tx buffer array
  * @txb: array of per-TFD driver data
+ * @time_stamp: time (in jiffies) of last read_ptr change
  * @need_update: indicates need to update read/write index
  * @sched_retry: indicates queue is high-throughput aggregation (HT AGG) enabled
  *
@@ -170,6 +168,7 @@ struct iwl_tx_queue {
 	struct iwl_device_cmd **cmd;
 	struct iwl_cmd_meta *meta;
 	struct iwl_tx_info *txb;
+	unsigned long time_stamp;
 	u8 need_update;
 	u8 sched_retry;
 	u8 active;
@@ -1104,11 +1103,10 @@ struct iwl_event_log {
 #define IWL_DELAY_NEXT_FORCE_RF_RESET  (HZ*3)
 #define IWL_DELAY_NEXT_FORCE_FW_RELOAD (HZ*5)
 
-/* timer constants use to monitor and recover stuck tx queues in mSecs */
-#define IWL_DEF_MONITORING_PERIOD	(1000)
-#define IWL_LONG_MONITORING_PERIOD	(5000)
-#define IWL_ONE_HUNDRED_MSECS   (100)
-#define IWL_MAX_MONITORING_PERIOD	(60000)
+/* TX queue watchdog timeouts in mSecs */
+#define IWL_DEF_WD_TIMEOUT	(2000)
+#define IWL_LONG_WD_TIMEOUT	(10000)
+#define IWL_MAX_WD_TIMEOUT	(120000)
 
 /* BT Antenna Coupling Threshold (dB) */
 #define IWL_BT_ANTENNA_COUPLING_THRESHOLD	(35)
@@ -1162,6 +1160,8 @@ struct iwl_rxon_context {
 	 */
 	bool always_active, is_active;
 
+	bool ht_need_multiple_chains;
+
 	enum iwl_rxon_context_id ctxid;
 
 	u32 interface_modes, exclusive_interface_modes;
@@ -1468,8 +1468,9 @@ struct iwl_priv {
 	};
 
 	/* bt coex */
+	u8 bt_enable_flag;
 	u8 bt_status;
-	u8 bt_traffic_load, notif_bt_traffic_load;
+	u8 bt_traffic_load, last_bt_traffic_load;
 	bool bt_ch_announce;
 	bool bt_sco_active;
 	bool bt_full_concurrent;
@@ -1480,7 +1481,6 @@ struct iwl_priv {
 	u16 bt_on_thresh;
 	u16 bt_duration;
 	u16 dynamic_frag_thresh;
-	u16 dynamic_agg_thresh;
 	u8 bt_ci_compliance;
 	struct work_struct bt_traffic_change_work;
 
@@ -1517,6 +1517,7 @@ struct iwl_priv {
 	s8 tx_power_user_lmt;
 	s8 tx_power_device_lmt;
 	s8 tx_power_lmt_in_half_dbm; /* max tx power in half-dBm format */
+	s8 tx_power_next;
 
 
 #ifdef CONFIG_IWLWIFI_DEBUG
@@ -1542,7 +1543,7 @@ struct iwl_priv {
 	struct work_struct run_time_calib_work;
 	struct timer_list statistics_periodic;
 	struct timer_list ucode_trace;
-	struct timer_list monitor_recover;
+	struct timer_list watchdog;
 	bool hw_ready;
 
 	struct iwl_event_log event_log;
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/iwlwifi/iwl-eeprom.c linux-libre-2.6.38-gnu1/drivers/net/wireless/iwlwifi/iwl-eeprom.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/iwlwifi/iwl-eeprom.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/iwlwifi/iwl-eeprom.c	2011-03-14 21:20:32.000000000 -0400
@@ -147,7 +147,7 @@ static int iwl_eeprom_verify_signature(s
 	u32 gp = iwl_read32(priv, CSR_EEPROM_GP) & CSR_EEPROM_GP_VALID_MSK;
 	int ret = 0;
 
-	IWL_DEBUG_INFO(priv, "EEPROM signature=0x%08x\n", gp);
+	IWL_DEBUG_EEPROM(priv, "EEPROM signature=0x%08x\n", gp);
 	switch (gp) {
 	case CSR_EEPROM_GP_BAD_SIG_EEP_GOOD_SIG_OTP:
 		if (priv->nvm_device_type != NVM_DEVICE_TYPE_OTP) {
@@ -354,7 +354,7 @@ static int iwl_find_otp_image(struct iwl
 		 */
 		valid_addr = next_link_addr;
 		next_link_addr = le16_to_cpu(link_value) * sizeof(u16);
-		IWL_DEBUG_INFO(priv, "OTP blocks %d addr 0x%x\n",
+		IWL_DEBUG_EEPROM(priv, "OTP blocks %d addr 0x%x\n",
 			       usedblocks, next_link_addr);
 		if (iwl_read_otp_word(priv, next_link_addr, &link_value))
 			return -EINVAL;
@@ -374,7 +374,7 @@ static int iwl_find_otp_image(struct iwl
 	} while (usedblocks <= priv->cfg->base_params->max_ll_items);
 
 	/* OTP has no valid blocks */
-	IWL_DEBUG_INFO(priv, "OTP has no valid blocks\n");
+	IWL_DEBUG_EEPROM(priv, "OTP has no valid blocks\n");
 	return -EINVAL;
 }
 
@@ -414,7 +414,7 @@ int iwl_eeprom_init(struct iwl_priv *pri
 		return -ENOENT;
 	/* allocate eeprom */
 	sz = priv->cfg->base_params->eeprom_size;
-	IWL_DEBUG_INFO(priv, "NVM size = %d\n", sz);
+	IWL_DEBUG_EEPROM(priv, "NVM size = %d\n", sz);
 	priv->eeprom = kzalloc(sz, GFP_KERNEL);
 	if (!priv->eeprom) {
 		ret = -ENOMEM;
@@ -492,7 +492,7 @@ int iwl_eeprom_init(struct iwl_priv *pri
 		}
 	}
 
-	IWL_DEBUG_INFO(priv, "NVM Type: %s, version: 0x%x\n",
+	IWL_DEBUG_EEPROM(priv, "NVM Type: %s, version: 0x%x\n",
 		       (priv->nvm_device_type == NVM_DEVICE_TYPE_OTP)
 		       ? "OTP" : "EEPROM",
 		       iwl_eeprom_query16(priv, EEPROM_VERSION));
@@ -594,7 +594,7 @@ static int iwl_mod_ht40_chan_info(struct
 	if (!is_channel_valid(ch_info))
 		return -1;
 
-	IWL_DEBUG_INFO(priv, "HT40 Ch. %d [%sGHz] %s%s%s%s%s(0x%02x %ddBm):"
+	IWL_DEBUG_EEPROM(priv, "HT40 Ch. %d [%sGHz] %s%s%s%s%s(0x%02x %ddBm):"
 			" Ad-Hoc %ssupported\n",
 			ch_info->channel,
 			is_channel_a_band(ch_info) ?
@@ -634,11 +634,11 @@ int iwl_init_channel_map(struct iwl_priv
 	struct iwl_channel_info *ch_info;
 
 	if (priv->channel_count) {
-		IWL_DEBUG_INFO(priv, "Channel map already initialized.\n");
+		IWL_DEBUG_EEPROM(priv, "Channel map already initialized.\n");
 		return 0;
 	}
 
-	IWL_DEBUG_INFO(priv, "Initializing regulatory info from EEPROM\n");
+	IWL_DEBUG_EEPROM(priv, "Initializing regulatory info from EEPROM\n");
 
 	priv->channel_count =
 	    ARRAY_SIZE(iwl_eeprom_band_1) +
@@ -647,7 +647,8 @@ int iwl_init_channel_map(struct iwl_priv
 	    ARRAY_SIZE(iwl_eeprom_band_4) +
 	    ARRAY_SIZE(iwl_eeprom_band_5);
 
-	IWL_DEBUG_INFO(priv, "Parsing data for %d channels.\n", priv->channel_count);
+	IWL_DEBUG_EEPROM(priv, "Parsing data for %d channels.\n",
+			priv->channel_count);
 
 	priv->channel_info = kzalloc(sizeof(struct iwl_channel_info) *
 				     priv->channel_count, GFP_KERNEL);
@@ -686,7 +687,8 @@ int iwl_init_channel_map(struct iwl_priv
 					IEEE80211_CHAN_NO_HT40;
 
 			if (!(is_channel_valid(ch_info))) {
-				IWL_DEBUG_INFO(priv, "Ch. %d Flags %x [%sGHz] - "
+				IWL_DEBUG_EEPROM(priv,
+					       "Ch. %d Flags %x [%sGHz] - "
 					       "No traffic\n",
 					       ch_info->channel,
 					       ch_info->flags,
@@ -702,7 +704,8 @@ int iwl_init_channel_map(struct iwl_priv
 			ch_info->scan_power = eeprom_ch_info[ch].max_power_avg;
 			ch_info->min_power = 0;
 
-			IWL_DEBUG_INFO(priv, "Ch. %d [%sGHz] %s%s%s%s%s%s(0x%02x %ddBm):"
+			IWL_DEBUG_EEPROM(priv, "Ch. %d [%sGHz] "
+				       "%s%s%s%s%s%s(0x%02x %ddBm):"
 				       " Ad-Hoc %ssupported\n",
 				       ch_info->channel,
 				       is_channel_a_band(ch_info) ?
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/iwlwifi/iwl-eeprom.h linux-libre-2.6.38-gnu1/drivers/net/wireless/iwlwifi/iwl-eeprom.h
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/iwlwifi/iwl-eeprom.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/iwlwifi/iwl-eeprom.h	2011-03-14 21:20:32.000000000 -0400
@@ -110,9 +110,18 @@ enum {
 };
 
 /* SKU Capabilities */
+/* 3945 only */
 #define EEPROM_SKU_CAP_SW_RF_KILL_ENABLE                (1 << 0)
 #define EEPROM_SKU_CAP_HW_RF_KILL_ENABLE                (1 << 1)
 
+/* 5000 and up */
+#define EEPROM_SKU_CAP_BAND_POS				(4)
+#define EEPROM_SKU_CAP_BAND_SELECTION	                \
+		(3 << EEPROM_SKU_CAP_BAND_POS)
+#define EEPROM_SKU_CAP_11N_ENABLE	                (1 << 6)
+#define EEPROM_SKU_CAP_AMT_ENABLE	                (1 << 7)
+#define EEPROM_SKU_CAP_IPAN_ENABLE	                (1 << 8)
+
 /* *regulatory* channel data format in eeprom, one for each channel.
  * There are separate entries for HT40 (40 MHz) vs. normal (20 MHz) channels. */
 struct iwl_eeprom_channel {
@@ -222,59 +231,6 @@ struct iwl_eeprom_enhanced_txpwr {
 #define EEPROM_6000_REG_BAND_24_HT40_CHANNELS  ((0x80)\
 		| INDIRECT_ADDRESS | INDIRECT_REGULATORY)   /* 14  bytes */
 
-/* 6000 and up regulatory tx power - indirect access */
-/* max. elements per section */
-#define EEPROM_MAX_TXPOWER_SECTION_ELEMENTS	(8)
-#define EEPROM_TXPOWER_COMMON_HT40_INDEX	(2)
-
-/**
- * Partition the enhanced tx power portion of eeprom image into
- * 10 sections based on band, modulation, frequency and channel
- *
- * Section 1: all CCK channels
- * Section 2: all 2.4 GHz OFDM (Legacy, HT and HT40 ) channels
- * Section 3: all 5.2 GHz OFDM (Legacy, HT and HT40) channels
- * Section 4: 2.4 GHz 20MHz channels: 1, 2, 10, 11. Both Legacy and HT
- * Section 5: 2.4 GHz 40MHz channels: 1, 2, 6, 7, 9, (_above_)
- * Section 6: 5.2 GHz 20MHz channels: 36, 64, 100, both Legacy and HT
- * Section 7: 5.2 GHz 40MHz channels: 36, 60, 100 (_above_)
- * Section 8: 2.4 GHz channel 13, Both Legacy and HT
- * Section 9: 2.4 GHz channel 140, Both Legacy and HT
- * Section 10: 2.4 GHz 40MHz channels: 132, 44 (_above_)
- */
-/* 2.4 GHz band: CCK */
-#define EEPROM_LB_CCK_20_COMMON       ((0xA8)\
-		| INDIRECT_ADDRESS | INDIRECT_REGULATORY)   /* 8 bytes */
-/* 2.4 GHz band: 20MHz-Legacy, 20MHz-HT, 40MHz-HT */
-#define EEPROM_LB_OFDM_COMMON       ((0xB0)\
-		| INDIRECT_ADDRESS | INDIRECT_REGULATORY)   /* 24 bytes */
-/* 5.2 GHz band: 20MHz-Legacy, 20MHz-HT, 40MHz-HT */
-#define EEPROM_HB_OFDM_COMMON       ((0xC8)\
-		| INDIRECT_ADDRESS | INDIRECT_REGULATORY)   /* 24 bytes */
-/* 2.4GHz band channels:
- *	1Legacy, 1HT, 2Legacy, 2HT, 10Legacy, 10HT, 11Legacy, 11HT */
-#define EEPROM_LB_OFDM_20_BAND       ((0xE0)\
-		| INDIRECT_ADDRESS | INDIRECT_REGULATORY)   /* 64 bytes */
-/* 2.4 GHz band HT40 channels: (1,+1) (2,+1) (6,+1) (7,+1) (9,+1) */
-#define EEPROM_LB_OFDM_HT40_BAND       ((0x120)\
-		| INDIRECT_ADDRESS | INDIRECT_REGULATORY)   /* 40 bytes */
-/* 5.2GHz band channels: 36Legacy, 36HT, 64Legacy, 64HT, 100Legacy, 100HT */
-#define EEPROM_HB_OFDM_20_BAND       ((0x148)\
-		| INDIRECT_ADDRESS | INDIRECT_REGULATORY)   /* 48 bytes */
-/* 5.2 GHz band HT40 channels: (36,+1) (60,+1) (100,+1) */
-#define EEPROM_HB_OFDM_HT40_BAND       ((0x178)\
-		| INDIRECT_ADDRESS | INDIRECT_REGULATORY)   /* 24 bytes */
-/* 2.4 GHz band, channnel 13: Legacy, HT */
-#define EEPROM_LB_OFDM_20_CHANNEL_13       ((0x190)\
-		| INDIRECT_ADDRESS | INDIRECT_REGULATORY)   /* 16 bytes */
-/* 5.2 GHz band, channnel 140: Legacy, HT */
-#define EEPROM_HB_OFDM_20_CHANNEL_140       ((0x1A0)\
-		| INDIRECT_ADDRESS | INDIRECT_REGULATORY)   /* 16 bytes */
-/* 5.2 GHz band, HT40 channnels (132,+1) (44,+1) */
-#define EEPROM_HB_OFDM_HT40_BAND_1       ((0x1B0)\
-		| INDIRECT_ADDRESS | INDIRECT_REGULATORY)   /* 16 bytes */
-
-
 /* 5050 Specific */
 #define EEPROM_5050_TX_POWER_VERSION    (4)
 #define EEPROM_5050_EEPROM_VERSION	(0x21E)
@@ -414,11 +370,10 @@ struct iwl_eeprom_calib_info {
 #define EEPROM_BOARD_REVISION               (2*0x35)	/* 2  bytes */
 #define EEPROM_BOARD_PBA_NUMBER             (2*0x3B+1)	/* 9  bytes */
 #define EEPROM_VERSION                      (2*0x44)	/* 2  bytes */
-#define EEPROM_SKU_CAP                      (2*0x45)	/* 1  bytes */
+#define EEPROM_SKU_CAP                      (2*0x45)	/* 2  bytes */
 #define EEPROM_OEM_MODE                     (2*0x46)	/* 2  bytes */
 #define EEPROM_WOWLAN_MODE                  (2*0x47)	/* 2  bytes */
 #define EEPROM_RADIO_CONFIG                 (2*0x48)	/* 2  bytes */
-#define EEPROM_3945_M_VERSION               (2*0x4A)	/* 1  bytes */
 #define EEPROM_NUM_MAC_ADDRESS              (2*0x4C)	/* 2  bytes */
 
 /* The following masks are to be applied on EEPROM_RADIO_CONFIG */
@@ -521,6 +476,7 @@ struct iwl_eeprom_ops {
 int iwl_eeprom_init(struct iwl_priv *priv);
 void iwl_eeprom_free(struct iwl_priv *priv);
 int  iwl_eeprom_check_version(struct iwl_priv *priv);
+int  iwl_eeprom_check_sku(struct iwl_priv *priv);
 const u8 *iwl_eeprom_query_addr(const struct iwl_priv *priv, size_t offset);
 int iwlcore_eeprom_verify_signature(struct iwl_priv *priv);
 u16 iwl_eeprom_query16(const struct iwl_priv *priv, size_t offset);
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/iwlwifi/iwl-helpers.h linux-libre-2.6.38-gnu1/drivers/net/wireless/iwlwifi/iwl-helpers.h
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/iwlwifi/iwl-helpers.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/iwlwifi/iwl-helpers.h	2011-03-14 21:20:32.000000000 -0400
@@ -44,15 +44,6 @@ static inline struct ieee80211_conf *iee
 	return &hw->conf;
 }
 
-static inline unsigned long elapsed_jiffies(unsigned long start,
-					    unsigned long end)
-{
-	if (end >= start)
-		return end - start;
-
-	return end + (MAX_JIFFY_OFFSET - start) + 1;
-}
-
 /**
  * iwl_queue_inc_wrap - increment queue index, wrap back to beginning
  * @index -- current index
@@ -104,42 +95,36 @@ static inline int iwl_alloc_fw_desc(stru
  * | | | | | | | |
  * | | | | | | +-+-------- AC queue (0-3)
  * | | | | | |
- * | +-+-+-+-+------------ HW A-MPDU queue
+ * | +-+-+-+-+------------ HW queue ID
  * |
- * +---------------------- indicates agg queue
+ * +---------------------- unused
  */
-static inline u8 iwl_virtual_agg_queue_num(u8 ac, u8 hwq)
+static inline void iwl_set_swq_id(struct iwl_tx_queue *txq, u8 ac, u8 hwq)
 {
 	BUG_ON(ac > 3);   /* only have 2 bits */
-	BUG_ON(hwq > 31); /* only have 5 bits */
+	BUG_ON(hwq > 31); /* only use 5 bits */
 
-	return 0x80 | (hwq << 2) | ac;
+	txq->swq_id = (hwq << 2) | ac;
 }
 
-static inline void iwl_wake_queue(struct iwl_priv *priv, u8 queue)
+static inline void iwl_wake_queue(struct iwl_priv *priv,
+				  struct iwl_tx_queue *txq)
 {
-	u8 ac = queue;
-	u8 hwq = queue;
-
-	if (queue & 0x80) {
-		ac = queue & 3;
-		hwq = (queue >> 2) & 0x1f;
-	}
+	u8 queue = txq->swq_id;
+	u8 ac = queue & 3;
+	u8 hwq = (queue >> 2) & 0x1f;
 
 	if (test_and_clear_bit(hwq, priv->queue_stopped))
 		if (atomic_dec_return(&priv->queue_stop_count[ac]) <= 0)
 			ieee80211_wake_queue(priv->hw, ac);
 }
 
-static inline void iwl_stop_queue(struct iwl_priv *priv, u8 queue)
+static inline void iwl_stop_queue(struct iwl_priv *priv,
+				  struct iwl_tx_queue *txq)
 {
-	u8 ac = queue;
-	u8 hwq = queue;
-
-	if (queue & 0x80) {
-		ac = queue & 3;
-		hwq = (queue >> 2) & 0x1f;
-	}
+	u8 queue = txq->swq_id;
+	u8 ac = queue & 3;
+	u8 hwq = (queue >> 2) & 0x1f;
 
 	if (!test_and_set_bit(hwq, priv->queue_stopped))
 		if (atomic_inc_return(&priv->queue_stop_count[ac]) > 0)
@@ -163,6 +148,12 @@ static inline void iwl_disable_interrupt
 	IWL_DEBUG_ISR(priv, "Disabled interrupts\n");
 }
 
+static inline void iwl_enable_rfkill_int(struct iwl_priv *priv)
+{
+	IWL_DEBUG_ISR(priv, "Enabling rfkill interrupt\n");
+	iwl_write32(priv, CSR_INT_MASK, CSR_INT_BIT_RF_KILL);
+}
+
 static inline void iwl_enable_interrupts(struct iwl_priv *priv)
 {
 	IWL_DEBUG_ISR(priv, "Enabling interrupts\n");
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/iwlwifi/iwl-led.c linux-libre-2.6.38-gnu1/drivers/net/wireless/iwlwifi/iwl-led.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/iwlwifi/iwl-led.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/iwlwifi/iwl-led.c	2011-03-14 21:20:32.000000000 -0400
@@ -45,9 +45,8 @@
 /* default: IWL_LED_BLINK(0) using blinking index table */
 static int led_mode;
 module_param(led_mode, int, S_IRUGO);
-MODULE_PARM_DESC(led_mode, "led mode: 0=blinking, 1=On(RF On)/Off(RF Off), "
-			   "(default 0)");
-
+MODULE_PARM_DESC(led_mode, "0=system default, "
+		"1=On(RF On)/Off(RF Off), 2=blinking");
 
 static const struct {
 	u16 tpt;	/* Mb/s */
@@ -128,12 +127,13 @@ EXPORT_SYMBOL(iwl_led_start);
 int iwl_led_associate(struct iwl_priv *priv)
 {
 	IWL_DEBUG_LED(priv, "Associated\n");
-	if (led_mode == IWL_LED_BLINK)
+	if (priv->cfg->led_mode == IWL_LED_BLINK)
 		priv->allow_blinking = 1;
 	priv->last_blink_time = jiffies;
 
 	return 0;
 }
+EXPORT_SYMBOL(iwl_led_associate);
 
 int iwl_led_disassociate(struct iwl_priv *priv)
 {
@@ -141,6 +141,7 @@ int iwl_led_disassociate(struct iwl_priv
 
 	return 0;
 }
+EXPORT_SYMBOL(iwl_led_disassociate);
 
 /*
  * calculate blink rate according to last second Tx/Rx activities
@@ -221,5 +222,8 @@ void iwl_leds_init(struct iwl_priv *priv
 	priv->last_blink_rate = 0;
 	priv->last_blink_time = 0;
 	priv->allow_blinking = 0;
+	if (led_mode != IWL_LED_DEFAULT &&
+	    led_mode != priv->cfg->led_mode)
+		priv->cfg->led_mode = led_mode;
 }
 EXPORT_SYMBOL(iwl_leds_init);
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/iwlwifi/iwl-led.h linux-libre-2.6.38-gnu1/drivers/net/wireless/iwlwifi/iwl-led.h
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/iwlwifi/iwl-led.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/iwlwifi/iwl-led.h	2011-03-14 21:20:32.000000000 -0400
@@ -47,14 +47,16 @@ enum led_type {
 
 /*
  * LED mode
- *    IWL_LED_BLINK:    adjust led blink rate based on blink table
+ *    IWL_LED_DEFAULT:  use system default
  *    IWL_LED_RF_STATE: turn LED on/off based on RF state
  *			LED ON  = RF ON
  *			LED OFF = RF OFF
+ *    IWL_LED_BLINK:    adjust led blink rate based on blink table
  */
 enum iwl_led_mode {
-	IWL_LED_BLINK,
+	IWL_LED_DEFAULT,
 	IWL_LED_RF_STATE,
+	IWL_LED_BLINK,
 };
 
 void iwl_leds_init(struct iwl_priv *priv);
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/iwlwifi/iwl-legacy.c linux-libre-2.6.38-gnu1/drivers/net/wireless/iwlwifi/iwl-legacy.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/iwlwifi/iwl-legacy.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/iwlwifi/iwl-legacy.c	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,662 @@
+/******************************************************************************
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License 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,
+ * USA
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *****************************************************************************/
+
+#include <linux/kernel.h>
+#include <net/mac80211.h>
+
+#include "iwl-dev.h"
+#include "iwl-core.h"
+#include "iwl-helpers.h"
+#include "iwl-legacy.h"
+
+static void iwl_update_qos(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
+{
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+		return;
+
+	if (!ctx->is_active)
+		return;
+
+	ctx->qos_data.def_qos_parm.qos_flags = 0;
+
+	if (ctx->qos_data.qos_active)
+		ctx->qos_data.def_qos_parm.qos_flags |=
+			QOS_PARAM_FLG_UPDATE_EDCA_MSK;
+
+	if (ctx->ht.enabled)
+		ctx->qos_data.def_qos_parm.qos_flags |= QOS_PARAM_FLG_TGN_MSK;
+
+	IWL_DEBUG_QOS(priv, "send QoS cmd with Qos active=%d FLAGS=0x%X\n",
+		      ctx->qos_data.qos_active,
+		      ctx->qos_data.def_qos_parm.qos_flags);
+
+	iwl_send_cmd_pdu_async(priv, ctx->qos_cmd,
+			       sizeof(struct iwl_qosparam_cmd),
+			       &ctx->qos_data.def_qos_parm, NULL);
+}
+
+/**
+ * iwl_legacy_mac_config - mac80211 config callback
+ */
+int iwl_legacy_mac_config(struct ieee80211_hw *hw, u32 changed)
+{
+	struct iwl_priv *priv = hw->priv;
+	const struct iwl_channel_info *ch_info;
+	struct ieee80211_conf *conf = &hw->conf;
+	struct ieee80211_channel *channel = conf->channel;
+	struct iwl_ht_config *ht_conf = &priv->current_ht_config;
+	struct iwl_rxon_context *ctx;
+	unsigned long flags = 0;
+	int ret = 0;
+	u16 ch;
+	int scan_active = 0;
+	bool ht_changed[NUM_IWL_RXON_CTX] = {};
+
+	if (WARN_ON(!priv->cfg->ops->legacy))
+		return -EOPNOTSUPP;
+
+	mutex_lock(&priv->mutex);
+
+	IWL_DEBUG_MAC80211(priv, "enter to channel %d changed 0x%X\n",
+					channel->hw_value, changed);
+
+	if (unlikely(!priv->cfg->mod_params->disable_hw_scan &&
+			test_bit(STATUS_SCANNING, &priv->status))) {
+		scan_active = 1;
+		IWL_DEBUG_MAC80211(priv, "leave - scanning\n");
+	}
+
+	if (changed & (IEEE80211_CONF_CHANGE_SMPS |
+		       IEEE80211_CONF_CHANGE_CHANNEL)) {
+		/* mac80211 uses static for non-HT which is what we want */
+		priv->current_ht_config.smps = conf->smps_mode;
+
+		/*
+		 * Recalculate chain counts.
+		 *
+		 * If monitor mode is enabled then mac80211 will
+		 * set up the SM PS mode to OFF if an HT channel is
+		 * configured.
+		 */
+		if (priv->cfg->ops->hcmd->set_rxon_chain)
+			for_each_context(priv, ctx)
+				priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
+	}
+
+	/* during scanning mac80211 will delay channel setting until
+	 * scan finish with changed = 0
+	 */
+	if (!changed || (changed & IEEE80211_CONF_CHANGE_CHANNEL)) {
+		if (scan_active)
+			goto set_ch_out;
+
+		ch = channel->hw_value;
+		ch_info = iwl_get_channel_info(priv, channel->band, ch);
+		if (!is_channel_valid(ch_info)) {
+			IWL_DEBUG_MAC80211(priv, "leave - invalid channel\n");
+			ret = -EINVAL;
+			goto set_ch_out;
+		}
+
+		spin_lock_irqsave(&priv->lock, flags);
+
+		for_each_context(priv, ctx) {
+			/* Configure HT40 channels */
+			if (ctx->ht.enabled != conf_is_ht(conf)) {
+				ctx->ht.enabled = conf_is_ht(conf);
+				ht_changed[ctx->ctxid] = true;
+			}
+			if (ctx->ht.enabled) {
+				if (conf_is_ht40_minus(conf)) {
+					ctx->ht.extension_chan_offset =
+						IEEE80211_HT_PARAM_CHA_SEC_BELOW;
+					ctx->ht.is_40mhz = true;
+				} else if (conf_is_ht40_plus(conf)) {
+					ctx->ht.extension_chan_offset =
+						IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
+					ctx->ht.is_40mhz = true;
+				} else {
+					ctx->ht.extension_chan_offset =
+						IEEE80211_HT_PARAM_CHA_SEC_NONE;
+					ctx->ht.is_40mhz = false;
+				}
+			} else
+				ctx->ht.is_40mhz = false;
+
+			/*
+			 * Default to no protection. Protection mode will
+			 * later be set from BSS config in iwl_ht_conf
+			 */
+			ctx->ht.protection = IEEE80211_HT_OP_MODE_PROTECTION_NONE;
+
+			/* if we are switching from ht to 2.4 clear flags
+			 * from any ht related info since 2.4 does not
+			 * support ht */
+			if ((le16_to_cpu(ctx->staging.channel) != ch))
+				ctx->staging.flags = 0;
+
+			iwl_set_rxon_channel(priv, channel, ctx);
+			iwl_set_rxon_ht(priv, ht_conf);
+
+			iwl_set_flags_for_band(priv, ctx, channel->band,
+					       ctx->vif);
+		}
+
+		spin_unlock_irqrestore(&priv->lock, flags);
+
+		if (priv->cfg->ops->legacy->update_bcast_stations)
+			ret = priv->cfg->ops->legacy->update_bcast_stations(priv);
+
+ set_ch_out:
+		/* The list of supported rates and rate mask can be different
+		 * for each band; since the band may have changed, reset
+		 * the rate mask to what mac80211 lists */
+		iwl_set_rate(priv);
+	}
+
+	if (changed & (IEEE80211_CONF_CHANGE_PS |
+			IEEE80211_CONF_CHANGE_IDLE)) {
+		ret = iwl_power_update_mode(priv, false);
+		if (ret)
+			IWL_DEBUG_MAC80211(priv, "Error setting sleep level\n");
+	}
+
+	if (changed & IEEE80211_CONF_CHANGE_POWER) {
+		IWL_DEBUG_MAC80211(priv, "TX Power old=%d new=%d\n",
+			priv->tx_power_user_lmt, conf->power_level);
+
+		iwl_set_tx_power(priv, conf->power_level, false);
+	}
+
+	if (!iwl_is_ready(priv)) {
+		IWL_DEBUG_MAC80211(priv, "leave - not ready\n");
+		goto out;
+	}
+
+	if (scan_active)
+		goto out;
+
+	for_each_context(priv, ctx) {
+		if (memcmp(&ctx->active, &ctx->staging, sizeof(ctx->staging)))
+			iwlcore_commit_rxon(priv, ctx);
+		else
+			IWL_DEBUG_INFO(priv,
+				"Not re-sending same RXON configuration.\n");
+		if (ht_changed[ctx->ctxid])
+			iwl_update_qos(priv, ctx);
+	}
+
+out:
+	IWL_DEBUG_MAC80211(priv, "leave\n");
+	mutex_unlock(&priv->mutex);
+	return ret;
+}
+EXPORT_SYMBOL(iwl_legacy_mac_config);
+
+void iwl_legacy_mac_reset_tsf(struct ieee80211_hw *hw)
+{
+	struct iwl_priv *priv = hw->priv;
+	unsigned long flags;
+	/* IBSS can only be the IWL_RXON_CTX_BSS context */
+	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
+
+	if (WARN_ON(!priv->cfg->ops->legacy))
+		return;
+
+	mutex_lock(&priv->mutex);
+	IWL_DEBUG_MAC80211(priv, "enter\n");
+
+	spin_lock_irqsave(&priv->lock, flags);
+	memset(&priv->current_ht_config, 0, sizeof(struct iwl_ht_config));
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	spin_lock_irqsave(&priv->lock, flags);
+
+	/* new association get rid of ibss beacon skb */
+	if (priv->beacon_skb)
+		dev_kfree_skb(priv->beacon_skb);
+
+	priv->beacon_skb = NULL;
+
+	priv->timestamp = 0;
+
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	iwl_scan_cancel_timeout(priv, 100);
+	if (!iwl_is_ready_rf(priv)) {
+		IWL_DEBUG_MAC80211(priv, "leave - not ready\n");
+		mutex_unlock(&priv->mutex);
+		return;
+	}
+
+	/* we are restarting association process
+	 * clear RXON_FILTER_ASSOC_MSK bit
+	 */
+	ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
+	iwlcore_commit_rxon(priv, ctx);
+
+	iwl_set_rate(priv);
+
+	mutex_unlock(&priv->mutex);
+
+	IWL_DEBUG_MAC80211(priv, "leave\n");
+}
+EXPORT_SYMBOL(iwl_legacy_mac_reset_tsf);
+
+static void iwl_ht_conf(struct iwl_priv *priv,
+			struct ieee80211_vif *vif)
+{
+	struct iwl_ht_config *ht_conf = &priv->current_ht_config;
+	struct ieee80211_sta *sta;
+	struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
+	struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);
+
+	IWL_DEBUG_ASSOC(priv, "enter:\n");
+
+	if (!ctx->ht.enabled)
+		return;
+
+	ctx->ht.protection =
+		bss_conf->ht_operation_mode & IEEE80211_HT_OP_MODE_PROTECTION;
+	ctx->ht.non_gf_sta_present =
+		!!(bss_conf->ht_operation_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT);
+
+	ht_conf->single_chain_sufficient = false;
+
+	switch (vif->type) {
+	case NL80211_IFTYPE_STATION:
+		rcu_read_lock();
+		sta = ieee80211_find_sta(vif, bss_conf->bssid);
+		if (sta) {
+			struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap;
+			int maxstreams;
+
+			maxstreams = (ht_cap->mcs.tx_params &
+				      IEEE80211_HT_MCS_TX_MAX_STREAMS_MASK)
+					>> IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT;
+			maxstreams += 1;
+
+			if ((ht_cap->mcs.rx_mask[1] == 0) &&
+			    (ht_cap->mcs.rx_mask[2] == 0))
+				ht_conf->single_chain_sufficient = true;
+			if (maxstreams <= 1)
+				ht_conf->single_chain_sufficient = true;
+		} else {
+			/*
+			 * If at all, this can only happen through a race
+			 * when the AP disconnects us while we're still
+			 * setting up the connection, in that case mac80211
+			 * will soon tell us about that.
+			 */
+			ht_conf->single_chain_sufficient = true;
+		}
+		rcu_read_unlock();
+		break;
+	case NL80211_IFTYPE_ADHOC:
+		ht_conf->single_chain_sufficient = true;
+		break;
+	default:
+		break;
+	}
+
+	IWL_DEBUG_ASSOC(priv, "leave\n");
+}
+
+static inline void iwl_set_no_assoc(struct iwl_priv *priv,
+				    struct ieee80211_vif *vif)
+{
+	struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);
+
+	iwl_led_disassociate(priv);
+	/*
+	 * inform the ucode that there is no longer an
+	 * association and that no more packets should be
+	 * sent
+	 */
+	ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
+	ctx->staging.assoc_id = 0;
+	iwlcore_commit_rxon(priv, ctx);
+}
+
+static void iwlcore_beacon_update(struct ieee80211_hw *hw,
+				  struct ieee80211_vif *vif)
+{
+	struct iwl_priv *priv = hw->priv;
+	unsigned long flags;
+	__le64 timestamp;
+	struct sk_buff *skb = ieee80211_beacon_get(hw, vif);
+
+	if (!skb)
+		return;
+
+	IWL_DEBUG_MAC80211(priv, "enter\n");
+
+	lockdep_assert_held(&priv->mutex);
+
+	if (!priv->beacon_ctx) {
+		IWL_ERR(priv, "update beacon but no beacon context!\n");
+		dev_kfree_skb(skb);
+		return;
+	}
+
+	spin_lock_irqsave(&priv->lock, flags);
+
+	if (priv->beacon_skb)
+		dev_kfree_skb(priv->beacon_skb);
+
+	priv->beacon_skb = skb;
+
+	timestamp = ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp;
+	priv->timestamp = le64_to_cpu(timestamp);
+
+	IWL_DEBUG_MAC80211(priv, "leave\n");
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	if (!iwl_is_ready_rf(priv)) {
+		IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n");
+		return;
+	}
+
+	priv->cfg->ops->legacy->post_associate(priv);
+}
+
+void iwl_legacy_mac_bss_info_changed(struct ieee80211_hw *hw,
+				     struct ieee80211_vif *vif,
+				     struct ieee80211_bss_conf *bss_conf,
+				     u32 changes)
+{
+	struct iwl_priv *priv = hw->priv;
+	struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);
+	int ret;
+
+	if (WARN_ON(!priv->cfg->ops->legacy))
+		return;
+
+	IWL_DEBUG_MAC80211(priv, "changes = 0x%X\n", changes);
+
+	if (!iwl_is_alive(priv))
+		return;
+
+	mutex_lock(&priv->mutex);
+
+	if (changes & BSS_CHANGED_QOS) {
+		unsigned long flags;
+
+		spin_lock_irqsave(&priv->lock, flags);
+		ctx->qos_data.qos_active = bss_conf->qos;
+		iwl_update_qos(priv, ctx);
+		spin_unlock_irqrestore(&priv->lock, flags);
+	}
+
+	if (changes & BSS_CHANGED_BEACON_ENABLED) {
+		/*
+		 * the add_interface code must make sure we only ever
+		 * have a single interface that could be beaconing at
+		 * any time.
+		 */
+		if (vif->bss_conf.enable_beacon)
+			priv->beacon_ctx = ctx;
+		else
+			priv->beacon_ctx = NULL;
+	}
+
+	if (changes & BSS_CHANGED_BEACON && vif->type == NL80211_IFTYPE_AP) {
+		dev_kfree_skb(priv->beacon_skb);
+		priv->beacon_skb = ieee80211_beacon_get(hw, vif);
+	}
+
+	if (changes & BSS_CHANGED_BEACON_INT && vif->type == NL80211_IFTYPE_AP)
+		iwl_send_rxon_timing(priv, ctx);
+
+	if (changes & BSS_CHANGED_BSSID) {
+		IWL_DEBUG_MAC80211(priv, "BSSID %pM\n", bss_conf->bssid);
+
+		/*
+		 * If there is currently a HW scan going on in the
+		 * background then we need to cancel it else the RXON
+		 * below/in post_associate will fail.
+		 */
+		if (iwl_scan_cancel_timeout(priv, 100)) {
+			IWL_WARN(priv, "Aborted scan still in progress after 100ms\n");
+			IWL_DEBUG_MAC80211(priv, "leaving - scan abort failed.\n");
+			mutex_unlock(&priv->mutex);
+			return;
+		}
+
+		/* mac80211 only sets assoc when in STATION mode */
+		if (vif->type == NL80211_IFTYPE_ADHOC || bss_conf->assoc) {
+			memcpy(ctx->staging.bssid_addr,
+			       bss_conf->bssid, ETH_ALEN);
+
+			/* currently needed in a few places */
+			memcpy(priv->bssid, bss_conf->bssid, ETH_ALEN);
+		} else {
+			ctx->staging.filter_flags &=
+				~RXON_FILTER_ASSOC_MSK;
+		}
+
+	}
+
+	/*
+	 * This needs to be after setting the BSSID in case
+	 * mac80211 decides to do both changes at once because
+	 * it will invoke post_associate.
+	 */
+	if (vif->type == NL80211_IFTYPE_ADHOC && changes & BSS_CHANGED_BEACON)
+		iwlcore_beacon_update(hw, vif);
+
+	if (changes & BSS_CHANGED_ERP_PREAMBLE) {
+		IWL_DEBUG_MAC80211(priv, "ERP_PREAMBLE %d\n",
+				   bss_conf->use_short_preamble);
+		if (bss_conf->use_short_preamble)
+			ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
+		else
+			ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
+	}
+
+	if (changes & BSS_CHANGED_ERP_CTS_PROT) {
+		IWL_DEBUG_MAC80211(priv, "ERP_CTS %d\n", bss_conf->use_cts_prot);
+		if (bss_conf->use_cts_prot && (priv->band != IEEE80211_BAND_5GHZ))
+			ctx->staging.flags |= RXON_FLG_TGG_PROTECT_MSK;
+		else
+			ctx->staging.flags &= ~RXON_FLG_TGG_PROTECT_MSK;
+		if (bss_conf->use_cts_prot)
+			ctx->staging.flags |= RXON_FLG_SELF_CTS_EN;
+		else
+			ctx->staging.flags &= ~RXON_FLG_SELF_CTS_EN;
+	}
+
+	if (changes & BSS_CHANGED_BASIC_RATES) {
+		/* XXX use this information
+		 *
+		 * To do that, remove code from iwl_set_rate() and put something
+		 * like this here:
+		 *
+		if (A-band)
+			ctx->staging.ofdm_basic_rates =
+				bss_conf->basic_rates;
+		else
+			ctx->staging.ofdm_basic_rates =
+				bss_conf->basic_rates >> 4;
+			ctx->staging.cck_basic_rates =
+				bss_conf->basic_rates & 0xF;
+		 */
+	}
+
+	if (changes & BSS_CHANGED_HT) {
+		iwl_ht_conf(priv, vif);
+
+		if (priv->cfg->ops->hcmd->set_rxon_chain)
+			priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
+	}
+
+	if (changes & BSS_CHANGED_ASSOC) {
+		IWL_DEBUG_MAC80211(priv, "ASSOC %d\n", bss_conf->assoc);
+		if (bss_conf->assoc) {
+			priv->timestamp = bss_conf->timestamp;
+
+			iwl_led_associate(priv);
+
+			if (!iwl_is_rfkill(priv))
+				priv->cfg->ops->legacy->post_associate(priv);
+		} else
+			iwl_set_no_assoc(priv, vif);
+	}
+
+	if (changes && iwl_is_associated_ctx(ctx) && bss_conf->aid) {
+		IWL_DEBUG_MAC80211(priv, "Changes (%#x) while associated\n",
+				   changes);
+		ret = iwl_send_rxon_assoc(priv, ctx);
+		if (!ret) {
+			/* Sync active_rxon with latest change. */
+			memcpy((void *)&ctx->active,
+				&ctx->staging,
+				sizeof(struct iwl_rxon_cmd));
+		}
+	}
+
+	if (changes & BSS_CHANGED_BEACON_ENABLED) {
+		if (vif->bss_conf.enable_beacon) {
+			memcpy(ctx->staging.bssid_addr,
+			       bss_conf->bssid, ETH_ALEN);
+			memcpy(priv->bssid, bss_conf->bssid, ETH_ALEN);
+			iwl_led_associate(priv);
+			priv->cfg->ops->legacy->config_ap(priv);
+		} else
+			iwl_set_no_assoc(priv, vif);
+	}
+
+	if (changes & BSS_CHANGED_IBSS) {
+		ret = priv->cfg->ops->legacy->manage_ibss_station(priv, vif,
+							bss_conf->ibss_joined);
+		if (ret)
+			IWL_ERR(priv, "failed to %s IBSS station %pM\n",
+				bss_conf->ibss_joined ? "add" : "remove",
+				bss_conf->bssid);
+	}
+
+	mutex_unlock(&priv->mutex);
+
+	IWL_DEBUG_MAC80211(priv, "leave\n");
+}
+EXPORT_SYMBOL(iwl_legacy_mac_bss_info_changed);
+
+irqreturn_t iwl_isr_legacy(int irq, void *data)
+{
+	struct iwl_priv *priv = data;
+	u32 inta, inta_mask;
+	u32 inta_fh;
+	unsigned long flags;
+	if (!priv)
+		return IRQ_NONE;
+
+	spin_lock_irqsave(&priv->lock, flags);
+
+	/* Disable (but don't clear!) interrupts here to avoid
+	 *    back-to-back ISRs and sporadic interrupts from our NIC.
+	 * If we have something to service, the tasklet will re-enable ints.
+	 * If we *don't* have something, we'll re-enable before leaving here. */
+	inta_mask = iwl_read32(priv, CSR_INT_MASK);  /* just for debug */
+	iwl_write32(priv, CSR_INT_MASK, 0x00000000);
+
+	/* Discover which interrupts are active/pending */
+	inta = iwl_read32(priv, CSR_INT);
+	inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS);
+
+	/* Ignore interrupt if there's nothing in NIC to service.
+	 * This may be due to IRQ shared with another device,
+	 * or due to sporadic interrupts thrown from our NIC. */
+	if (!inta && !inta_fh) {
+		IWL_DEBUG_ISR(priv,
+			"Ignore interrupt, inta == 0, inta_fh == 0\n");
+		goto none;
+	}
+
+	if ((inta == 0xFFFFFFFF) || ((inta & 0xFFFFFFF0) == 0xa5a5a5a0)) {
+		/* Hardware disappeared. It might have already raised
+		 * an interrupt */
+		IWL_WARN(priv, "HARDWARE GONE?? INTA == 0x%08x\n", inta);
+		goto unplugged;
+	}
+
+	IWL_DEBUG_ISR(priv, "ISR inta 0x%08x, enabled 0x%08x, fh 0x%08x\n",
+		      inta, inta_mask, inta_fh);
+
+	inta &= ~CSR_INT_BIT_SCD;
+
+	/* iwl_irq_tasklet() will service interrupts and re-enable them */
+	if (likely(inta || inta_fh))
+		tasklet_schedule(&priv->irq_tasklet);
+
+unplugged:
+	spin_unlock_irqrestore(&priv->lock, flags);
+	return IRQ_HANDLED;
+
+none:
+	/* re-enable interrupts here since we don't have anything to service. */
+	/* only Re-enable if disabled by irq */
+	if (test_bit(STATUS_INT_ENABLED, &priv->status))
+		iwl_enable_interrupts(priv);
+	spin_unlock_irqrestore(&priv->lock, flags);
+	return IRQ_NONE;
+}
+EXPORT_SYMBOL(iwl_isr_legacy);
+
+/*
+ *  iwl_legacy_tx_cmd_protection: Set rts/cts. 3945 and 4965 only share this
+ *  function.
+ */
+void iwl_legacy_tx_cmd_protection(struct iwl_priv *priv,
+			       struct ieee80211_tx_info *info,
+			       __le16 fc, __le32 *tx_flags)
+{
+	if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) {
+		*tx_flags |= TX_CMD_FLG_RTS_MSK;
+		*tx_flags &= ~TX_CMD_FLG_CTS_MSK;
+		*tx_flags |= TX_CMD_FLG_FULL_TXOP_PROT_MSK;
+
+		if (!ieee80211_is_mgmt(fc))
+			return;
+
+		switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) {
+		case cpu_to_le16(IEEE80211_STYPE_AUTH):
+		case cpu_to_le16(IEEE80211_STYPE_DEAUTH):
+		case cpu_to_le16(IEEE80211_STYPE_ASSOC_REQ):
+		case cpu_to_le16(IEEE80211_STYPE_REASSOC_REQ):
+			*tx_flags &= ~TX_CMD_FLG_RTS_MSK;
+			*tx_flags |= TX_CMD_FLG_CTS_MSK;
+			break;
+		}
+	} else if (info->control.rates[0].flags &
+		   IEEE80211_TX_RC_USE_CTS_PROTECT) {
+		*tx_flags &= ~TX_CMD_FLG_RTS_MSK;
+		*tx_flags |= TX_CMD_FLG_CTS_MSK;
+		*tx_flags |= TX_CMD_FLG_FULL_TXOP_PROT_MSK;
+	}
+}
+EXPORT_SYMBOL(iwl_legacy_tx_cmd_protection);
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/iwlwifi/iwl-legacy.h linux-libre-2.6.38-gnu1/drivers/net/wireless/iwlwifi/iwl-legacy.h
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/iwlwifi/iwl-legacy.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/iwlwifi/iwl-legacy.h	2011-03-14 21:20:32.000000000 -0400
@@ -0,0 +1,79 @@
+/******************************************************************************
+ *
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License 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,
+ * USA
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * 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 Intel Corporation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "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 COPYRIGHT
+ * OWNER OR CONTRIBUTORS 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.
+ *****************************************************************************/
+
+#ifndef __iwl_legacy_h__
+#define __iwl_legacy_h__
+
+/* mac80211 handlers */
+int iwl_legacy_mac_config(struct ieee80211_hw *hw, u32 changed);
+void iwl_legacy_mac_reset_tsf(struct ieee80211_hw *hw);
+void iwl_legacy_mac_bss_info_changed(struct ieee80211_hw *hw,
+				     struct ieee80211_vif *vif,
+				     struct ieee80211_bss_conf *bss_conf,
+				     u32 changes);
+void iwl_legacy_tx_cmd_protection(struct iwl_priv *priv,
+				struct ieee80211_tx_info *info,
+				__le16 fc, __le32 *tx_flags);
+
+irqreturn_t iwl_isr_legacy(int irq, void *data);
+
+#endif /* __iwl_legacy_h__ */
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/iwlwifi/iwl-power.c linux-libre-2.6.38-gnu1/drivers/net/wireless/iwlwifi/iwl-power.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/iwlwifi/iwl-power.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/iwlwifi/iwl-power.c	2011-03-14 21:20:32.000000000 -0400
@@ -75,6 +75,10 @@ struct iwl_power_vec_entry {
 
 #define NOSLP cpu_to_le16(0), 0, 0
 #define SLP IWL_POWER_DRIVER_ALLOW_SLEEP_MSK, 0, 0
+#define ASLP (IWL_POWER_POWER_SAVE_ENA_MSK |	\
+		IWL_POWER_POWER_MANAGEMENT_ENA_MSK | \
+		IWL_POWER_ADVANCE_PM_ENA_MSK)
+#define ASLP_TOUT(T) cpu_to_le32(T)
 #define TU_TO_USEC 1024
 #define SLP_TOUT(T) cpu_to_le32((T) * TU_TO_USEC)
 #define SLP_VEC(X0, X1, X2, X3, X4) {cpu_to_le32(X0), \
@@ -114,6 +118,52 @@ static const struct iwl_power_vec_entry
 	{{SLP, SLP_TOUT(25), SLP_TOUT(25), SLP_VEC(4, 7, 10, 10, 0xFF)}, 0}
 };
 
+/* advance power management */
+/* DTIM 0 - 2 */
+static const struct iwl_power_vec_entry apm_range_0[IWL_POWER_NUM] = {
+	{{ASLP, 0, 0, ASLP_TOUT(50), ASLP_TOUT(50),
+		SLP_VEC(1, 2, 4, 6, 0xFF), 0}, 0},
+	{{ASLP, 0, 0, ASLP_TOUT(50), ASLP_TOUT(50),
+		SLP_VEC(1, 2, 4, 6, 0xFF), 0}, 0},
+	{{ASLP, 0, 0, ASLP_TOUT(50), ASLP_TOUT(50),
+		SLP_VEC(1, 2, 4, 6, 0xFF), 0}, 0},
+	{{ASLP, 0, 0, ASLP_TOUT(50), ASLP_TOUT(50),
+		SLP_VEC(1, 2, 4, 6, 0xFF), 0}, 0},
+	{{ASLP, 0, 0, ASLP_TOUT(50), ASLP_TOUT(50),
+		SLP_VEC(1, 2, 6, 8, 0xFF), ASLP_TOUT(2)}, 2}
+};
+
+
+/* for DTIM period IWL_DTIM_RANGE_0_MAX + 1 through IWL_DTIM_RANGE_1_MAX */
+/* DTIM 3 - 10 */
+static const struct iwl_power_vec_entry apm_range_1[IWL_POWER_NUM] = {
+	{{ASLP, 0, 0, ASLP_TOUT(50), ASLP_TOUT(50),
+		SLP_VEC(1, 2, 4, 6, 0xFF), 0}, 0},
+	{{ASLP, 0, 0, ASLP_TOUT(50), ASLP_TOUT(50),
+		SLP_VEC(1, 2, 4, 6, 0xFF), 0}, 0},
+	{{ASLP, 0, 0, ASLP_TOUT(50), ASLP_TOUT(50),
+		SLP_VEC(1, 2, 4, 6, 0xFF), 0}, 0},
+	{{ASLP, 0, 0, ASLP_TOUT(50), ASLP_TOUT(50),
+		SLP_VEC(1, 2, 4, 6, 0xFF), 0}, 0},
+	{{ASLP, 0, 0, ASLP_TOUT(50), ASLP_TOUT(50),
+		SLP_VEC(1, 2, 6, 8, 0xFF), 0}, 2}
+};
+
+/* for DTIM period > IWL_DTIM_RANGE_1_MAX */
+/* DTIM 11 - */
+static const struct iwl_power_vec_entry apm_range_2[IWL_POWER_NUM] = {
+	{{ASLP, 0, 0, ASLP_TOUT(50), ASLP_TOUT(50),
+		SLP_VEC(1, 2, 4, 6, 0xFF), 0}, 0},
+	{{ASLP, 0, 0, ASLP_TOUT(50), ASLP_TOUT(50),
+		SLP_VEC(1, 2, 4, 6, 0xFF), 0}, 0},
+	{{ASLP, 0, 0, ASLP_TOUT(50), ASLP_TOUT(50),
+		SLP_VEC(1, 2, 4, 6, 0xFF), 0}, 0},
+	{{ASLP, 0, 0, ASLP_TOUT(50), ASLP_TOUT(50),
+		SLP_VEC(1, 2, 4, 6, 0xFF), 0}, 0},
+	{{ASLP, 0, 0, ASLP_TOUT(50), ASLP_TOUT(50),
+		SLP_VEC(1, 2, 6, 8, 0xFF), ASLP_TOUT(2)}, 2}
+};
+
 static void iwl_static_sleep_cmd(struct iwl_priv *priv,
 				 struct iwl_powertable_cmd *cmd,
 				 enum iwl_power_level lvl, int period)
@@ -124,11 +174,19 @@ static void iwl_static_sleep_cmd(struct
 	u8 skip;
 	u32 slp_itrvl;
 
-	table = range_2;
-	if (period <= IWL_DTIM_RANGE_1_MAX)
-		table = range_1;
-	if (period <= IWL_DTIM_RANGE_0_MAX)
-		table = range_0;
+	if (priv->cfg->adv_pm) {
+		table = apm_range_2;
+		if (period <= IWL_DTIM_RANGE_1_MAX)
+			table = apm_range_1;
+		if (period <= IWL_DTIM_RANGE_0_MAX)
+			table = apm_range_0;
+	} else {
+		table = range_2;
+		if (period <= IWL_DTIM_RANGE_1_MAX)
+			table = range_1;
+		if (period <= IWL_DTIM_RANGE_0_MAX)
+			table = range_0;
+	}
 
 	BUG_ON(lvl < 0 || lvl >= IWL_POWER_NUM);
 
@@ -163,6 +221,20 @@ static void iwl_static_sleep_cmd(struct
 	else
 		cmd->flags &= ~IWL_POWER_SLEEP_OVER_DTIM_MSK;
 
+	if (priv->cfg->base_params->shadow_reg_enable)
+		cmd->flags |= IWL_POWER_SHADOW_REG_ENA;
+	else
+		cmd->flags &= ~IWL_POWER_SHADOW_REG_ENA;
+
+	if (priv->cfg->bt_params &&
+	    priv->cfg->bt_params->advanced_bt_coexist) {
+		if (!priv->cfg->bt_params->bt_sco_disable)
+			cmd->flags |= IWL_POWER_BT_SCO_ENA;
+		else
+			cmd->flags &= ~IWL_POWER_BT_SCO_ENA;
+	}
+
+
 	slp_itrvl = le32_to_cpu(cmd->sleep_interval[IWL_POWER_VEC_SIZE - 1]);
 	if (slp_itrvl > IWL_CONN_MAX_LISTEN_INTERVAL)
 		cmd->sleep_interval[IWL_POWER_VEC_SIZE - 1] =
@@ -236,6 +308,19 @@ static void iwl_power_fill_sleep_cmd(str
 	if (priv->power_data.pci_pm)
 		cmd->flags |= IWL_POWER_PCI_PM_MSK;
 
+	if (priv->cfg->base_params->shadow_reg_enable)
+		cmd->flags |= IWL_POWER_SHADOW_REG_ENA;
+	else
+		cmd->flags &= ~IWL_POWER_SHADOW_REG_ENA;
+
+	if (priv->cfg->bt_params &&
+	    priv->cfg->bt_params->advanced_bt_coexist) {
+		if (!priv->cfg->bt_params->bt_sco_disable)
+			cmd->flags |= IWL_POWER_BT_SCO_ENA;
+		else
+			cmd->flags &= ~IWL_POWER_BT_SCO_ENA;
+	}
+
 	cmd->rx_data_timeout = cpu_to_le32(1000 * dynps_ms);
 	cmd->tx_data_timeout = cpu_to_le32(1000 * dynps_ms);
 
@@ -263,70 +348,95 @@ static int iwl_set_power(struct iwl_priv
 				sizeof(struct iwl_powertable_cmd), cmd);
 }
 
-/* priv->mutex must be held */
-int iwl_power_update_mode(struct iwl_priv *priv, bool force)
+static void iwl_power_build_cmd(struct iwl_priv *priv,
+				struct iwl_powertable_cmd *cmd)
 {
-	int ret = 0;
 	bool enabled = priv->hw->conf.flags & IEEE80211_CONF_PS;
-	bool update_chains;
-	struct iwl_powertable_cmd cmd;
 	int dtimper;
 
-	/* Don't update the RX chain when chain noise calibration is running */
-	update_chains = priv->chain_noise_data.state == IWL_CHAIN_NOISE_DONE ||
-			priv->chain_noise_data.state == IWL_CHAIN_NOISE_ALIVE;
-
 	dtimper = priv->hw->conf.ps_dtim_period ?: 1;
 
 	if (priv->cfg->base_params->broken_powersave)
-		iwl_power_sleep_cam_cmd(priv, &cmd);
+		iwl_power_sleep_cam_cmd(priv, cmd);
 	else if (priv->cfg->base_params->supports_idle &&
 		 priv->hw->conf.flags & IEEE80211_CONF_IDLE)
-		iwl_static_sleep_cmd(priv, &cmd, IWL_POWER_INDEX_5, 20);
+		iwl_static_sleep_cmd(priv, cmd, IWL_POWER_INDEX_5, 20);
 	else if (priv->cfg->ops->lib->tt_ops.lower_power_detection &&
 		 priv->cfg->ops->lib->tt_ops.tt_power_mode &&
 		 priv->cfg->ops->lib->tt_ops.lower_power_detection(priv)) {
 		/* in thermal throttling low power state */
-		iwl_static_sleep_cmd(priv, &cmd,
+		iwl_static_sleep_cmd(priv, cmd,
 		    priv->cfg->ops->lib->tt_ops.tt_power_mode(priv), dtimper);
 	} else if (!enabled)
-		iwl_power_sleep_cam_cmd(priv, &cmd);
+		iwl_power_sleep_cam_cmd(priv, cmd);
 	else if (priv->power_data.debug_sleep_level_override >= 0)
-		iwl_static_sleep_cmd(priv, &cmd,
+		iwl_static_sleep_cmd(priv, cmd,
 				     priv->power_data.debug_sleep_level_override,
 				     dtimper);
 	else if (no_sleep_autoadjust)
-		iwl_static_sleep_cmd(priv, &cmd, IWL_POWER_INDEX_1, dtimper);
+		iwl_static_sleep_cmd(priv, cmd, IWL_POWER_INDEX_1, dtimper);
 	else
-		iwl_power_fill_sleep_cmd(priv, &cmd,
+		iwl_power_fill_sleep_cmd(priv, cmd,
 					 priv->hw->conf.dynamic_ps_timeout,
 					 priv->hw->conf.max_sleep_period);
+}
 
-	if (iwl_is_ready_rf(priv) &&
-	    (memcmp(&priv->power_data.sleep_cmd, &cmd, sizeof(cmd)) || force)) {
-		if (cmd.flags & IWL_POWER_DRIVER_ALLOW_SLEEP_MSK)
-			set_bit(STATUS_POWER_PMI, &priv->status);
+int iwl_power_set_mode(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd,
+		       bool force)
+{
+	int ret;
+	bool update_chains;
 
-		ret = iwl_set_power(priv, &cmd);
-		if (!ret) {
-			if (!(cmd.flags & IWL_POWER_DRIVER_ALLOW_SLEEP_MSK))
-				clear_bit(STATUS_POWER_PMI, &priv->status);
+	lockdep_assert_held(&priv->mutex);
 
-			if (priv->cfg->ops->lib->update_chain_flags &&
-			    update_chains)
-				priv->cfg->ops->lib->update_chain_flags(priv);
-			else if (priv->cfg->ops->lib->update_chain_flags)
-				IWL_DEBUG_POWER(priv,
+	/* Don't update the RX chain when chain noise calibration is running */
+	update_chains = priv->chain_noise_data.state == IWL_CHAIN_NOISE_DONE ||
+			priv->chain_noise_data.state == IWL_CHAIN_NOISE_ALIVE;
+
+	if (!memcmp(&priv->power_data.sleep_cmd, cmd, sizeof(*cmd)) && !force)
+		return 0;
+
+	if (!iwl_is_ready_rf(priv))
+		return -EIO;
+
+	/* scan complete use sleep_power_next, need to be updated */
+	memcpy(&priv->power_data.sleep_cmd_next, cmd, sizeof(*cmd));
+	if (test_bit(STATUS_SCANNING, &priv->status) && !force) {
+		IWL_DEBUG_INFO(priv, "Defer power set mode while scanning\n");
+		return 0;
+	}
+
+	if (cmd->flags & IWL_POWER_DRIVER_ALLOW_SLEEP_MSK)
+		set_bit(STATUS_POWER_PMI, &priv->status);
+
+	ret = iwl_set_power(priv, cmd);
+	if (!ret) {
+		if (!(cmd->flags & IWL_POWER_DRIVER_ALLOW_SLEEP_MSK))
+			clear_bit(STATUS_POWER_PMI, &priv->status);
+
+		if (priv->cfg->ops->lib->update_chain_flags && update_chains)
+			priv->cfg->ops->lib->update_chain_flags(priv);
+		else if (priv->cfg->ops->lib->update_chain_flags)
+			IWL_DEBUG_POWER(priv,
 					"Cannot update the power, chain noise "
 					"calibration running: %d\n",
 					priv->chain_noise_data.state);
-			memcpy(&priv->power_data.sleep_cmd, &cmd, sizeof(cmd));
-		} else
-			IWL_ERR(priv, "set power fail, ret = %d", ret);
-	}
+
+		memcpy(&priv->power_data.sleep_cmd, cmd, sizeof(*cmd));
+	} else
+		IWL_ERR(priv, "set power fail, ret = %d", ret);
 
 	return ret;
 }
+EXPORT_SYMBOL(iwl_power_set_mode);
+
+int iwl_power_update_mode(struct iwl_priv *priv, bool force)
+{
+	struct iwl_powertable_cmd cmd;
+
+	iwl_power_build_cmd(priv, &cmd);
+	return iwl_power_set_mode(priv, &cmd, force);
+}
 EXPORT_SYMBOL(iwl_power_update_mode);
 
 /* initialize to default */
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/iwlwifi/iwl-power.h linux-libre-2.6.38-gnu1/drivers/net/wireless/iwlwifi/iwl-power.h
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/iwlwifi/iwl-power.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/iwlwifi/iwl-power.h	2011-03-14 21:20:32.000000000 -0400
@@ -41,10 +41,13 @@ enum iwl_power_level {
 
 struct iwl_power_mgr {
 	struct iwl_powertable_cmd sleep_cmd;
+	struct iwl_powertable_cmd sleep_cmd_next;
 	int debug_sleep_level_override;
 	bool pci_pm;
 };
 
+int iwl_power_set_mode(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd,
+		       bool force);
 int iwl_power_update_mode(struct iwl_priv *priv, bool force);
 void iwl_power_initialize(struct iwl_priv *priv);
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/iwlwifi/iwl-prph.h linux-libre-2.6.38-gnu1/drivers/net/wireless/iwlwifi/iwl-prph.h
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/iwlwifi/iwl-prph.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/iwlwifi/iwl-prph.h	2011-03-14 21:20:32.000000000 -0400
@@ -83,10 +83,10 @@
 #define APMG_DIGITAL_SVR_REG		(APMG_BASE + 0x0058)
 #define APMG_ANALOG_SVR_REG		(APMG_BASE + 0x006C)
 
+#define APMS_CLK_VAL_MRB_FUNC_MODE	(0x00000001)
 #define APMG_CLK_VAL_DMA_CLK_RQT	(0x00000200)
 #define APMG_CLK_VAL_BSM_CLK_RQT	(0x00000800)
 
-
 #define APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS	(0x00400000)
 #define APMG_PS_CTRL_VAL_RESET_REQ		(0x04000000)
 #define APMG_PS_CTRL_MSK_PWR_SRC		(0x03000000)
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/iwlwifi/iwl-rx.c linux-libre-2.6.38-gnu1/drivers/net/wireless/iwlwifi/iwl-rx.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/iwlwifi/iwl-rx.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/iwlwifi/iwl-rx.c	2011-03-14 21:20:32.000000000 -0400
@@ -134,28 +134,37 @@ void iwl_rx_queue_update_write_ptr(struc
 	if (q->need_update == 0)
 		goto exit_unlock;
 
-	/* If power-saving is in use, make sure device is awake */
-	if (test_bit(STATUS_POWER_PMI, &priv->status)) {
-		reg = iwl_read32(priv, CSR_UCODE_DRV_GP1);
+	if (priv->cfg->base_params->shadow_reg_enable) {
+		/* shadow register enabled */
+		/* Device expects a multiple of 8 */
+		q->write_actual = (q->write & ~0x7);
+		iwl_write32(priv, rx_wrt_ptr_reg, q->write_actual);
+	} else {
+		/* If power-saving is in use, make sure device is awake */
+		if (test_bit(STATUS_POWER_PMI, &priv->status)) {
+			reg = iwl_read32(priv, CSR_UCODE_DRV_GP1);
 
-		if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) {
-			IWL_DEBUG_INFO(priv, "Rx queue requesting wakeup, GP1 = 0x%x\n",
-				      reg);
-			iwl_set_bit(priv, CSR_GP_CNTRL,
-				    CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
-			goto exit_unlock;
-		}
+			if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) {
+				IWL_DEBUG_INFO(priv,
+					"Rx queue requesting wakeup,"
+					" GP1 = 0x%x\n", reg);
+				iwl_set_bit(priv, CSR_GP_CNTRL,
+					CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
+				goto exit_unlock;
+			}
 
-		q->write_actual = (q->write & ~0x7);
-		iwl_write_direct32(priv, rx_wrt_ptr_reg, q->write_actual);
+			q->write_actual = (q->write & ~0x7);
+			iwl_write_direct32(priv, rx_wrt_ptr_reg,
+					q->write_actual);
 
-	/* Else device is assumed to be awake */
-	} else {
-		/* Device expects a multiple of 8 */
-		q->write_actual = (q->write & ~0x7);
-		iwl_write_direct32(priv, rx_wrt_ptr_reg, q->write_actual);
+		/* Else device is assumed to be awake */
+		} else {
+			/* Device expects a multiple of 8 */
+			q->write_actual = (q->write & ~0x7);
+			iwl_write_direct32(priv, rx_wrt_ptr_reg,
+				q->write_actual);
+		}
 	}
-
 	q->need_update = 0;
 
  exit_unlock:
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/iwlwifi/iwl-scan.c linux-libre-2.6.38-gnu1/drivers/net/wireless/iwlwifi/iwl-scan.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/iwlwifi/iwl-scan.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/iwlwifi/iwl-scan.c	2011-03-14 21:20:32.000000000 -0400
@@ -252,8 +252,7 @@ static void iwl_rx_scan_complete_notif(s
 
 	IWL_DEBUG_SCAN(priv, "Scan on %sGHz took %dms\n",
 		       (priv->scan_band == IEEE80211_BAND_2GHZ) ? "2.4" : "5.2",
-		       jiffies_to_msecs(elapsed_jiffies
-					(priv->scan_start, jiffies)));
+		       jiffies_to_msecs(jiffies - priv->scan_start));
 
 	queue_work(priv->workqueue, &priv->scan_completed);
 
@@ -603,13 +602,16 @@ out_settings:
 	if (!iwl_is_ready_rf(priv))
 		goto out;
 
-	/* Since setting the TXPOWER may have been deferred while
-	 * performing the scan, fire one off */
-	iwl_set_tx_power(priv, priv->tx_power_user_lmt, true);
+	/*
+	 * We do not commit power settings while scan is pending,
+	 * do it now if the settings changed.
+	 */
+	iwl_power_set_mode(priv, &priv->power_data.sleep_cmd_next, false);
+	iwl_set_tx_power(priv, priv->tx_power_next, false);
 
 	priv->cfg->ops->utils->post_scan(priv);
 
- out:
+out:
 	mutex_unlock(&priv->mutex);
 }
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/iwlwifi/iwl-sta.c linux-libre-2.6.38-gnu1/drivers/net/wireless/iwlwifi/iwl-sta.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/iwlwifi/iwl-sta.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/iwlwifi/iwl-sta.c	2011-03-14 21:20:32.000000000 -0400
@@ -107,7 +107,7 @@ static int iwl_process_add_sta_resp(stru
 	/*
 	 * XXX: The MAC address in the command buffer is often changed from
 	 * the original sent to the device. That is, the MAC address
-	 * written to the command buffer often is not the same MAC adress
+	 * written to the command buffer often is not the same MAC address
 	 * read from the command buffer when the command returns. This
 	 * issue has not yet been resolved and this debugging is left to
 	 * observe the problem.
@@ -400,7 +400,8 @@ static void iwl_sta_ucode_deactivate(str
 }
 
 static int iwl_send_remove_station(struct iwl_priv *priv,
-				   const u8 *addr, int sta_id)
+				   const u8 *addr, int sta_id,
+				   bool temporary)
 {
 	struct iwl_rx_packet *pkt;
 	int ret;
@@ -436,9 +437,11 @@ static int iwl_send_remove_station(struc
 	if (!ret) {
 		switch (pkt->u.rem_sta.status) {
 		case REM_STA_SUCCESS_MSK:
-			spin_lock_irqsave(&priv->sta_lock, flags_spin);
-			iwl_sta_ucode_deactivate(priv, sta_id);
-			spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
+			if (!temporary) {
+				spin_lock_irqsave(&priv->sta_lock, flags_spin);
+				iwl_sta_ucode_deactivate(priv, sta_id);
+				spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
+			}
 			IWL_DEBUG_ASSOC(priv, "REPLY_REMOVE_STA PASSED\n");
 			break;
 		default:
@@ -505,7 +508,7 @@ int iwl_remove_station(struct iwl_priv *
 
 	spin_unlock_irqrestore(&priv->sta_lock, flags);
 
-	return iwl_send_remove_station(priv, addr, sta_id);
+	return iwl_send_remove_station(priv, addr, sta_id, false);
 out_err:
 	spin_unlock_irqrestore(&priv->sta_lock, flags);
 	return -EINVAL;
@@ -624,6 +627,49 @@ void iwl_restore_stations(struct iwl_pri
 }
 EXPORT_SYMBOL(iwl_restore_stations);
 
+void iwl_reprogram_ap_sta(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
+{
+	unsigned long flags;
+	int sta_id = ctx->ap_sta_id;
+	int ret;
+	struct iwl_addsta_cmd sta_cmd;
+	struct iwl_link_quality_cmd lq;
+	bool active;
+
+	spin_lock_irqsave(&priv->sta_lock, flags);
+	if (!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE)) {
+		spin_unlock_irqrestore(&priv->sta_lock, flags);
+		return;
+	}
+
+	memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(sta_cmd));
+	sta_cmd.mode = 0;
+	memcpy(&lq, priv->stations[sta_id].lq, sizeof(lq));
+
+	active = priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE;
+	priv->stations[sta_id].used &= ~IWL_STA_DRIVER_ACTIVE;
+	spin_unlock_irqrestore(&priv->sta_lock, flags);
+
+	if (active) {
+		ret = iwl_send_remove_station(
+			priv, priv->stations[sta_id].sta.sta.addr,
+			sta_id, true);
+		if (ret)
+			IWL_ERR(priv, "failed to remove STA %pM (%d)\n",
+				priv->stations[sta_id].sta.sta.addr, ret);
+	}
+	spin_lock_irqsave(&priv->sta_lock, flags);
+	priv->stations[sta_id].used |= IWL_STA_DRIVER_ACTIVE;
+	spin_unlock_irqrestore(&priv->sta_lock, flags);
+
+	ret = iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
+	if (ret)
+		IWL_ERR(priv, "failed to re-add STA %pM (%d)\n",
+			priv->stations[sta_id].sta.sta.addr, ret);
+	iwl_send_lq_cmd(priv, ctx, &lq, CMD_SYNC, true);
+}
+EXPORT_SYMBOL(iwl_reprogram_ap_sta);
+
 int iwl_get_free_ucode_key_index(struct iwl_priv *priv)
 {
 	int i;
@@ -736,6 +782,14 @@ int iwl_send_lq_cmd(struct iwl_priv *pri
 	if (WARN_ON(lq->sta_id == IWL_INVALID_STATION))
 		return -EINVAL;
 
+
+	spin_lock_irqsave(&priv->sta_lock, flags_spin);
+	if (!(priv->stations[lq->sta_id].used & IWL_STA_DRIVER_ACTIVE)) {
+		spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
+		return -EINVAL;
+	}
+	spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
+
 	iwl_dump_lq_cmd(priv, lq);
 	BUG_ON(init && (cmd.flags & CMD_ASYNC));
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/iwlwifi/iwl-sta.h linux-libre-2.6.38-gnu1/drivers/net/wireless/iwlwifi/iwl-sta.h
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/iwlwifi/iwl-sta.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/iwlwifi/iwl-sta.h	2011-03-14 21:20:32.000000000 -0400
@@ -63,6 +63,7 @@ u8 iwl_prep_station(struct iwl_priv *pri
 
 int iwl_send_lq_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
 		    struct iwl_link_quality_cmd *lq, u8 flags, bool init);
+void iwl_reprogram_ap_sta(struct iwl_priv *priv, struct iwl_rxon_context *ctx);
 
 /**
  * iwl_clear_driver_stations - clear knowledge of all stations from driver
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/iwlwifi/iwl-tx.c linux-libre-2.6.38-gnu1/drivers/net/wireless/iwlwifi/iwl-tx.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/iwlwifi/iwl-tx.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/iwlwifi/iwl-tx.c	2011-03-14 21:20:32.000000000 -0400
@@ -49,30 +49,39 @@ void iwl_txq_update_write_ptr(struct iwl
 	if (txq->need_update == 0)
 		return;
 
-	/* if we're trying to save power */
-	if (test_bit(STATUS_POWER_PMI, &priv->status)) {
-		/* wake up nic if it's powered down ...
-		 * uCode will wake up, and interrupt us again, so next
-		 * time we'll skip this part. */
-		reg = iwl_read32(priv, CSR_UCODE_DRV_GP1);
+	if (priv->cfg->base_params->shadow_reg_enable) {
+		/* shadow register enabled */
+		iwl_write32(priv, HBUS_TARG_WRPTR,
+			    txq->q.write_ptr | (txq_id << 8));
+	} else {
+		/* if we're trying to save power */
+		if (test_bit(STATUS_POWER_PMI, &priv->status)) {
+			/* wake up nic if it's powered down ...
+			 * uCode will wake up, and interrupt us again, so next
+			 * time we'll skip this part. */
+			reg = iwl_read32(priv, CSR_UCODE_DRV_GP1);
 
-		if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) {
-			IWL_DEBUG_INFO(priv, "Tx queue %d requesting wakeup, GP1 = 0x%x\n",
-				      txq_id, reg);
-			iwl_set_bit(priv, CSR_GP_CNTRL,
-				    CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
-			return;
-		}
+			if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) {
+				IWL_DEBUG_INFO(priv,
+					"Tx queue %d requesting wakeup,"
+					" GP1 = 0x%x\n", txq_id, reg);
+				iwl_set_bit(priv, CSR_GP_CNTRL,
+					CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
+				return;
+			}
 
-		iwl_write_direct32(priv, HBUS_TARG_WRPTR,
+			iwl_write_direct32(priv, HBUS_TARG_WRPTR,
 				     txq->q.write_ptr | (txq_id << 8));
 
-	/* else not in power-save mode, uCode will never sleep when we're
-	 * trying to tx (during RFKILL, we're not trying to tx). */
-	} else
-		iwl_write32(priv, HBUS_TARG_WRPTR,
-			    txq->q.write_ptr | (txq_id << 8));
-
+		/*
+		 * else not in power-save mode,
+		 * uCode will never sleep when we're
+		 * trying to tx (during RFKILL, we're not trying to tx).
+		 */
+		} else
+			iwl_write32(priv, HBUS_TARG_WRPTR,
+				    txq->q.write_ptr | (txq_id << 8));
+	}
 	txq->need_update = 0;
 }
 EXPORT_SYMBOL(iwl_txq_update_write_ptr);
@@ -254,8 +263,6 @@ static int iwl_queue_init(struct iwl_pri
 		q->high_mark = 2;
 
 	q->write_ptr = q->read_ptr = 0;
-	q->last_read_ptr = 0;
-	q->repeat_same_read_ptr = 0;
 
 	return 0;
 }
@@ -350,13 +357,12 @@ int iwl_tx_queue_init(struct iwl_priv *p
 	txq->need_update = 0;
 
 	/*
-	 * Aggregation TX queues will get their ID when aggregation begins;
-	 * they overwrite the setting done here. The command FIFO doesn't
-	 * need an swq_id so don't set one to catch errors, all others can
-	 * be set up to the identity mapping.
+	 * For the default queues 0-3, set up the swq_id
+	 * already -- all others need to get one later
+	 * (if they need one at all).
 	 */
-	if (txq_id != priv->cmd_queue)
-		txq->swq_id = txq_id;
+	if (txq_id < 4)
+		iwl_set_swq_id(txq, txq_id, txq_id);
 
 	/* TFD_QUEUE_SIZE_MAX must be power-of-two size, otherwise
 	 * iwl_queue_inc_wrap and iwl_queue_dec_wrap are broken. */
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/iwlwifi/Kconfig linux-libre-2.6.38-gnu1/drivers/net/wireless/iwlwifi/Kconfig
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/iwlwifi/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/iwlwifi/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -106,6 +106,9 @@ config IWL5000
 		Intel WiFi Link 1000BGN
 		Intel Wireless WiFi 5150AGN
 		Intel Wireless WiFi 5100AGN, 5300AGN, and 5350AGN
+		Intel 6000 Gen 2 Series Wi-Fi Adapters (6000G2A and 6000G2B)
+		Intel WIreless WiFi Link 6050BGN Gen 2 Adapter
+		Intel 100 Series Wi-Fi Adapters (100BGN and 130BGN)
 
 config IWL3945
 	tristate "Intel PRO/Wireless 3945ABG/BG Network Connection (iwl3945)"
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/iwlwifi/Makefile linux-libre-2.6.38-gnu1/drivers/net/wireless/iwlwifi/Makefile
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/iwlwifi/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/iwlwifi/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -2,20 +2,27 @@ obj-$(CONFIG_IWLWIFI)	+= iwlcore.o
 iwlcore-objs 		:= iwl-core.o iwl-eeprom.o iwl-hcmd.o iwl-power.o
 iwlcore-objs 		+= iwl-rx.o iwl-tx.o iwl-sta.o
 iwlcore-objs 		+= iwl-scan.o iwl-led.o
+iwlcore-$(CONFIG_IWL3945) += iwl-legacy.o
+iwlcore-$(CONFIG_IWL4965) += iwl-legacy.o
 iwlcore-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o
 iwlcore-$(CONFIG_IWLWIFI_DEVICE_TRACING) += iwl-devtrace.o
 
+# If 3945 is selected only, iwl-legacy.o will be added
+# to iwlcore-m above, but it needs to be built in.
+iwlcore-objs += $(iwlcore-m)
+
 CFLAGS_iwl-devtrace.o := -I$(src)
 
 # AGN
 obj-$(CONFIG_IWLAGN)	+= iwlagn.o
-iwlagn-objs		:= iwl-agn.o iwl-agn-rs.o iwl-agn-led.o iwl-agn-ict.o
-iwlagn-objs		+= iwl-agn-ucode.o iwl-agn-hcmd.o iwl-agn-tx.o
+iwlagn-objs		:= iwl-agn.o iwl-agn-rs.o iwl-agn-led.o
+iwlagn-objs		+= iwl-agn-ucode.o iwl-agn-tx.o
 iwlagn-objs		+= iwl-agn-lib.o iwl-agn-rx.o iwl-agn-calib.o
 iwlagn-objs		+= iwl-agn-tt.o iwl-agn-sta.o iwl-agn-eeprom.o
 iwlagn-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-agn-debugfs.o
 
 iwlagn-$(CONFIG_IWL4965) += iwl-4965.o
+iwlagn-$(CONFIG_IWL5000) += iwl-agn-rxon.o iwl-agn-hcmd.o iwl-agn-ict.o
 iwlagn-$(CONFIG_IWL5000) += iwl-5000.o
 iwlagn-$(CONFIG_IWL5000) += iwl-6000.o
 iwlagn-$(CONFIG_IWL5000) += iwl-1000.o
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/iwmc3200wifi/cfg80211.c linux-libre-2.6.38-gnu1/drivers/net/wireless/iwmc3200wifi/cfg80211.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/iwmc3200wifi/cfg80211.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/iwmc3200wifi/cfg80211.c	2011-03-14 21:20:32.000000000 -0400
@@ -225,7 +225,8 @@ static int iwm_cfg80211_del_key(struct w
 
 static int iwm_cfg80211_set_default_key(struct wiphy *wiphy,
 					struct net_device *ndev,
-					u8 key_index)
+					u8 key_index, bool unicast,
+					bool multicast)
 {
 	struct iwm_priv *iwm = ndev_to_iwm(ndev);
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/iwmc3200wifi/commands.c linux-libre-2.6.38-gnu1/drivers/net/wireless/iwmc3200wifi/commands.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/iwmc3200wifi/commands.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/iwmc3200wifi/commands.c	2011-03-14 21:20:32.000000000 -0400
@@ -908,7 +908,7 @@ int iwm_scan_ssids(struct iwm_priv *iwm,
 		return ret;
 	}
 
-	iwm->scan_id = iwm->scan_id++ % IWM_SCAN_ID_MAX;
+	iwm->scan_id = (iwm->scan_id + 1) % IWM_SCAN_ID_MAX;
 
 	return 0;
 }
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/iwmc3200wifi/netdev.c linux-libre-2.6.38-gnu1/drivers/net/wireless/iwmc3200wifi/netdev.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/iwmc3200wifi/netdev.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/iwmc3200wifi/netdev.c	2011-03-14 21:20:32.000000000 -0400
@@ -126,6 +126,7 @@ void *iwm_if_alloc(int sizeof_bus, struc
 	ndev = alloc_netdev_mq(0, "wlan%d", ether_setup, IWM_TX_QUEUES);
 	if (!ndev) {
 		dev_err(dev, "no memory for network device instance\n");
+		ret = -ENOMEM;
 		goto out_priv;
 	}
 
@@ -138,6 +139,7 @@ void *iwm_if_alloc(int sizeof_bus, struc
 				    GFP_KERNEL);
 	if (!iwm->umac_profile) {
 		dev_err(dev, "Couldn't alloc memory for profile\n");
+		ret = -ENOMEM;
 		goto out_profile;
 	}
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/Kconfig linux-libre-2.6.38-gnu1/drivers/net/wireless/Kconfig
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -279,6 +279,7 @@ source "drivers/net/wireless/libertas/Kc
 source "drivers/net/wireless/orinoco/Kconfig"
 source "drivers/net/wireless/p54/Kconfig"
 source "drivers/net/wireless/rt2x00/Kconfig"
+source "drivers/net/wireless/rtlwifi/Kconfig"
 source "drivers/net/wireless/wl1251/Kconfig"
 source "drivers/net/wireless/wl12xx/Kconfig"
 source "drivers/net/wireless/zd1211rw/Kconfig"
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/libertas/cfg.c linux-libre-2.6.38-gnu1/drivers/net/wireless/libertas/cfg.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/libertas/cfg.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/libertas/cfg.c	2011-03-14 21:20:32.000000000 -0400
@@ -9,8 +9,6 @@
 #include <linux/sched.h>
 #include <linux/wait.h>
 #include <linux/slab.h>
-#include <linux/sched.h>
-#include <linux/wait.h>
 #include <linux/ieee80211.h>
 #include <net/cfg80211.h>
 #include <asm/unaligned.h>
@@ -1424,7 +1422,8 @@ static int lbs_cfg_disconnect(struct wip
 
 static int lbs_cfg_set_default_key(struct wiphy *wiphy,
 				   struct net_device *netdev,
-				   u8 key_index)
+				   u8 key_index, bool unicast,
+				   bool multicast)
 {
 	struct lbs_private *priv = wiphy_priv(wiphy);
 
@@ -2062,7 +2061,7 @@ static void lbs_cfg_set_regulatory_hint(
 	};
 
 	/* Section 5.17.2 */
-	static struct region_code_mapping regmap[] = {
+	static const struct region_code_mapping regmap[] = {
 		{"US ", 0x10}, /* US FCC */
 		{"CA ", 0x20}, /* Canada */
 		{"EU ", 0x30}, /* ETSI   */
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/libertas/cmd.c linux-libre-2.6.38-gnu1/drivers/net/wireless/libertas/cmd.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/libertas/cmd.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/libertas/cmd.c	2011-03-14 21:20:32.000000000 -0400
@@ -177,6 +177,14 @@ int lbs_host_sleep_cfg(struct lbs_privat
 	struct cmd_ds_host_sleep cmd_config;
 	int ret;
 
+	/*
+	 * Certain firmware versions do not support EHS_REMOVE_WAKEUP command
+	 * and the card will return a failure.  Since we need to be
+	 * able to reset the mask, in those cases we set a 0 mask instead.
+	 */
+	if (criteria == EHS_REMOVE_WAKEUP && !priv->ehs_remove_supported)
+		criteria = 0;
+
 	cmd_config.hdr.size = cpu_to_le16(sizeof(cmd_config));
 	cmd_config.criteria = cpu_to_le32(criteria);
 	cmd_config.gpio = priv->wol_gpio;
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/libertas/dev.h linux-libre-2.6.38-gnu1/drivers/net/wireless/libertas/dev.h
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/libertas/dev.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/libertas/dev.h	2011-03-14 21:20:32.000000000 -0400
@@ -138,6 +138,7 @@ struct lbs_private {
 	uint32_t wol_criteria;
 	uint8_t wol_gpio;
 	uint8_t wol_gap;
+	bool ehs_remove_supported;
 
 	/* Transmitting */
 	int tx_pending_len;		/* -1 while building packet */
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/libertas/if_spi.c linux-libre-2.6.38-gnu1/drivers/net/wireless/libertas/if_spi.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/libertas/if_spi.c	2013-05-03 04:01:13.000000000 -0400
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/libertas/if_spi.c	2013-05-03 02:01:37.000000000 -0400
@@ -776,7 +776,7 @@ static int lbs_spi_thread(void *data)
 				up(&card->spi_thread_terminated);
 				do_exit(0);
 			}
-		} while (err == EINTR);
+		} while (err == -EINTR);
 
 		/* Read the host interrupt status register to see what we
 		 * can do. */
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/libertas/if_usb.c linux-libre-2.6.38-gnu1/drivers/net/wireless/libertas/if_usb.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/libertas/if_usb.c	2013-05-03 04:01:16.000000000 -0400
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/libertas/if_usb.c	2013-05-03 02:01:40.000000000 -0400
@@ -331,6 +331,13 @@ static int if_usb_probe(struct usb_inter
 	if (device_create_file(&priv->dev->dev, &dev_attr_lbs_flash_boot2))
 		lbs_pr_err("cannot register lbs_flash_boot2 attribute\n");
 
+	/*
+	 * EHS_REMOVE_WAKEUP is not supported on all versions of the firmware.
+	 */
+	priv->wol_criteria = EHS_REMOVE_WAKEUP;
+	if (lbs_host_sleep_cfg(priv, priv->wol_criteria, NULL))
+		priv->ehs_remove_supported = false;
+
 	return 0;
 
 err_start_card:
@@ -1076,12 +1083,6 @@ static int if_usb_suspend(struct usb_int
 	if (priv->psstate != PS_STATE_FULL_POWER)
 		return -1;
 
-	if (priv->wol_criteria == EHS_REMOVE_WAKEUP) {
-		lbs_pr_info("Suspend attempt without "
-						"configuring wake params!\n");
-		return -ENOSYS;
-	}
-
 	ret = lbs_suspend(priv);
 	if (ret)
 		goto out;
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/libertas/main.c linux-libre-2.6.38-gnu1/drivers/net/wireless/libertas/main.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/libertas/main.c	2013-05-03 04:01:05.000000000 -0400
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/libertas/main.c	2013-05-03 02:01:30.000000000 -0400
@@ -851,9 +851,10 @@ struct lbs_private *lbs_add_card(void *c
 	priv->work_thread = create_singlethread_workqueue("lbs_worker");
 	INIT_WORK(&priv->mcast_work, lbs_set_mcast_worker);
 
-	priv->wol_criteria = 0xffffffff;
+	priv->wol_criteria = EHS_REMOVE_WAKEUP;
 	priv->wol_gpio = 0xff;
 	priv->wol_gap = 20;
+	priv->ehs_remove_supported = true;
 
 	goto done;
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/libertas/rx.c linux-libre-2.6.38-gnu1/drivers/net/wireless/libertas/rx.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/libertas/rx.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/libertas/rx.c	2011-03-14 21:20:32.000000000 -0400
@@ -55,7 +55,9 @@ int lbs_process_rxed_packet(struct lbs_p
 	struct rxpd *p_rx_pd;
 	int hdrchop;
 	struct ethhdr *p_ethhdr;
-	const u8 rfc1042_eth_hdr[] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
+	static const u8 rfc1042_eth_hdr[] = {
+		0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00
+	};
 
 	lbs_deb_enter(LBS_DEB_RX);
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/mac80211_hwsim.c linux-libre-2.6.38-gnu1/drivers/net/wireless/mac80211_hwsim.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/mac80211_hwsim.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/mac80211_hwsim.c	2011-03-14 21:20:32.000000000 -0400
@@ -309,6 +309,8 @@ struct mac80211_hwsim_data {
 	 */
 	u64 group;
 	struct dentry *debugfs_group;
+
+	int power_level;
 };
 
 
@@ -497,7 +499,7 @@ static bool mac80211_hwsim_tx_frame(stru
 	rx_status.band = data->channel->band;
 	rx_status.rate_idx = info->control.rates[0].idx;
 	/* TODO: simulate real signal strength (and optional packet loss) */
-	rx_status.signal = -50;
+	rx_status.signal = data->power_level - 50;
 
 	if (data->ps != PS_DISABLED)
 		hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM);
@@ -698,6 +700,7 @@ static int mac80211_hwsim_config(struct
 	data->idle = !!(conf->flags & IEEE80211_CONF_IDLE);
 
 	data->channel = conf->channel;
+	data->power_level = conf->power_level;
 	if (!data->started || !data->beacon_int)
 		del_timer(&data->beacon_timer);
 	else
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/Makefile linux-libre-2.6.38-gnu1/drivers/net/wireless/Makefile
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/Makefile	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/Makefile	2011-03-14 21:20:32.000000000 -0400
@@ -24,6 +24,7 @@ obj-$(CONFIG_B43LEGACY)		+= b43legacy/
 obj-$(CONFIG_ZD1211RW)		+= zd1211rw/
 obj-$(CONFIG_RTL8180)		+= rtl818x/
 obj-$(CONFIG_RTL8187)		+= rtl818x/
+obj-$(CONFIG_RTL8192CE)		+= rtlwifi/
 
 # 16-bit wireless PCMCIA client drivers
 obj-$(CONFIG_PCMCIA_RAYCS)	+= ray_cs.o
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/mwl8k.c linux-libre-2.6.38-gnu1/drivers/net/wireless/mwl8k.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/mwl8k.c	2013-05-03 04:01:24.000000000 -0400
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/mwl8k.c	2013-05-03 02:01:48.000000000 -0400
@@ -29,6 +29,12 @@
 #define MWL8K_NAME	KBUILD_MODNAME
 #define MWL8K_VERSION	"0.12"
 
+/* Module parameters */
+static unsigned ap_mode_default;
+module_param(ap_mode_default, bool, 0);
+MODULE_PARM_DESC(ap_mode_default,
+		 "Set to 1 to make ap mode the default instead of sta mode");
+
 /* Register definitions */
 #define MWL8K_HIU_GEN_PTR			0x00000c10
 #define  MWL8K_MODE_STA				 0x0000005a
@@ -92,8 +98,10 @@ struct rxd_ops {
 struct mwl8k_device_info {
 	char *part_name;
 	char *helper_image;
-	char *fw_image;
+	char *fw_image_sta;
+	char *fw_image_ap;
 	struct rxd_ops *ap_rxd_ops;
+	u32 fw_api_ap;
 };
 
 struct mwl8k_rx_queue {
@@ -136,8 +144,8 @@ struct mwl8k_priv {
 	void __iomem *regs;
 
 	/* firmware */
-	struct firmware *fw_helper;
-	struct firmware *fw_ucode;
+	const struct firmware *fw_helper;
+	const struct firmware *fw_ucode;
 
 	/* hardware/firmware parameters */
 	bool ap_fw;
@@ -210,6 +218,18 @@ struct mwl8k_priv {
 
 	/* Most recently reported noise in dBm */
 	s8 noise;
+
+	/*
+	 * preserve the queue configurations so they can be restored if/when
+	 * the firmware image is swapped.
+	 */
+	struct ieee80211_tx_queue_params wmm_params[MWL8K_TX_QUEUES];
+
+	/* async firmware loading state */
+	unsigned fw_state;
+	char *fw_pref;
+	char *fw_alt;
+	struct completion firmware_loading_complete;
 };
 
 /* Per interface specific private data */
@@ -285,8 +305,9 @@ static const struct ieee80211_rate mwl8k
 };
 
 /* Set or get info from Firmware */
-#define MWL8K_CMD_SET			0x0001
 #define MWL8K_CMD_GET			0x0000
+#define MWL8K_CMD_SET			0x0001
+#define MWL8K_CMD_SET_LIST		0x0002
 
 /* Firmware command codes */
 #define MWL8K_CMD_CODE_DNLD		0x0001
@@ -296,6 +317,7 @@ static const struct ieee80211_rate mwl8k
 #define MWL8K_CMD_GET_STAT		0x0014
 #define MWL8K_CMD_RADIO_CONTROL		0x001c
 #define MWL8K_CMD_RF_TX_POWER		0x001e
+#define MWL8K_CMD_TX_POWER		0x001f
 #define MWL8K_CMD_RF_ANTENNA		0x0020
 #define MWL8K_CMD_SET_BEACON		0x0100		/* per-vif */
 #define MWL8K_CMD_SET_PRE_SCAN		0x0107
@@ -333,6 +355,7 @@ static const char *mwl8k_cmd_name(__le16
 		MWL8K_CMDNAME(GET_STAT);
 		MWL8K_CMDNAME(RADIO_CONTROL);
 		MWL8K_CMDNAME(RF_TX_POWER);
+		MWL8K_CMDNAME(TX_POWER);
 		MWL8K_CMDNAME(RF_ANTENNA);
 		MWL8K_CMDNAME(SET_BEACON);
 		MWL8K_CMDNAME(SET_PRE_SCAN);
@@ -372,7 +395,7 @@ static void mwl8k_hw_reset(struct mwl8k_
 }
 
 /* Release fw image */
-static void mwl8k_release_fw(struct firmware **fw)
+static void mwl8k_release_fw(const struct firmware **fw)
 {
 	if (*fw == NULL)
 		return;
@@ -386,37 +409,68 @@ static void mwl8k_release_firmware(struc
 	mwl8k_release_fw(&priv->fw_helper);
 }
 
+/* states for asynchronous f/w loading */
+static void mwl8k_fw_state_machine(const struct firmware *fw, void *context);
+enum {
+	FW_STATE_INIT = 0,
+	FW_STATE_LOADING_PREF,
+	FW_STATE_LOADING_ALT,
+	FW_STATE_ERROR,
+};
+
 /* Request fw image */
 static int mwl8k_request_fw(struct mwl8k_priv *priv,
-			    const char *fname, struct firmware **fw)
+			    const char *fname, const struct firmware **fw,
+			    bool nowait)
 {
 	/* release current image */
 	if (*fw != NULL)
 		mwl8k_release_fw(fw);
 
-	return reject_firmware((const struct firmware **)fw,
-				fname, &priv->pdev->dev);
+	if (nowait)
+		return reject_firmware_nowait(THIS_MODULE, 1, fname,
+					       &priv->pdev->dev, GFP_KERNEL,
+					       priv, mwl8k_fw_state_machine);
+	else
+		return reject_firmware(fw, fname, &priv->pdev->dev);
 }
 
-static int mwl8k_reject_firmware(struct mwl8k_priv *priv)
+static int mwl8k_reject_firmware(struct mwl8k_priv *priv, char *fw_image,
+				  bool nowait)
 {
 	struct mwl8k_device_info *di = priv->device_info;
 	int rc;
 
 	if (di->helper_image != NULL) {
-		rc = mwl8k_request_fw(priv, di->helper_image, &priv->fw_helper);
-		if (rc) {
-			printk(KERN_ERR "%s: Error requesting helper "
-			       "firmware file %s\n", pci_name(priv->pdev),
-			       di->helper_image);
+		if (nowait)
+			rc = mwl8k_request_fw(priv, di->helper_image,
+					      &priv->fw_helper, true);
+		else
+			rc = mwl8k_request_fw(priv, di->helper_image,
+					      &priv->fw_helper, false);
+		if (rc)
+			printk(KERN_ERR "%s: Error requesting helper fw %s\n",
+			       pci_name(priv->pdev), di->helper_image);
+
+		if (rc || nowait)
 			return rc;
-		}
 	}
 
-	rc = mwl8k_request_fw(priv, di->fw_image, &priv->fw_ucode);
+	if (nowait) {
+		/*
+		 * if we get here, no helper image is needed.  Skip the
+		 * FW_STATE_INIT state.
+		 */
+		priv->fw_state = FW_STATE_LOADING_PREF;
+		rc = mwl8k_request_fw(priv, fw_image,
+				      &priv->fw_ucode,
+				      true);
+	} else
+		rc = mwl8k_request_fw(priv, fw_image,
+				      &priv->fw_ucode, false);
 	if (rc) {
 		printk(KERN_ERR "%s: Error requesting firmware file %s\n",
-		       pci_name(priv->pdev), di->fw_image);
+		       pci_name(priv->pdev), fw_image);
 		mwl8k_release_fw(&priv->fw_helper);
 		return rc;
 	}
@@ -577,12 +631,12 @@ static int mwl8k_feed_fw_image(struct mw
 static int mwl8k_load_firmware(struct ieee80211_hw *hw)
 {
 	struct mwl8k_priv *priv = hw->priv;
-	struct firmware *fw = priv->fw_ucode;
+	const struct firmware *fw = priv->fw_ucode;
 	int rc;
 	int loops;
 
 	if (!memcmp(fw->data, "\x01\x00\x00\x00", 4)) {
-		struct firmware *helper = priv->fw_helper;
+		const struct firmware *helper = priv->fw_helper;
 
 		if (helper == NULL) {
 			printk(KERN_ERR "%s: helper image needed but none "
@@ -1811,6 +1865,7 @@ struct mwl8k_cmd_get_hw_spec_ap {
 	__le32 wcbbase1;
 	__le32 wcbbase2;
 	__le32 wcbbase3;
+	__le32 fw_api_version;
 } __packed;
 
 static int mwl8k_cmd_get_hw_spec_ap(struct ieee80211_hw *hw)
@@ -1818,6 +1873,7 @@ static int mwl8k_cmd_get_hw_spec_ap(stru
 	struct mwl8k_priv *priv = hw->priv;
 	struct mwl8k_cmd_get_hw_spec_ap *cmd;
 	int rc;
+	u32 api_version;
 
 	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
 	if (cmd == NULL)
@@ -1834,6 +1890,16 @@ static int mwl8k_cmd_get_hw_spec_ap(stru
 	if (!rc) {
 		int off;
 
+		api_version = le32_to_cpu(cmd->fw_api_version);
+		if (priv->device_info->fw_api_ap != api_version) {
+			printk(KERN_ERR "%s: Unsupported fw API version for %s."
+			       "  Expected %d got %d.\n", MWL8K_NAME,
+			       priv->device_info->part_name,
+			       priv->device_info->fw_api_ap,
+			       api_version);
+			rc = -EINVAL;
+			goto done;
+		}
 		SET_IEEE80211_PERM_ADDR(hw, cmd->perm_addr);
 		priv->num_mcaddrs = le16_to_cpu(cmd->num_mcaddrs);
 		priv->fw_rev = le32_to_cpu(cmd->fw_rev);
@@ -1861,6 +1927,7 @@ static int mwl8k_cmd_get_hw_spec_ap(stru
 		iowrite32(priv->txq[3].txd_dma, priv->sram + off);
 	}
 
+done:
 	kfree(cmd);
 	return rc;
 }
@@ -2084,7 +2151,7 @@ mwl8k_set_radio_preamble(struct ieee8021
 /*
  * CMD_RF_TX_POWER.
  */
-#define MWL8K_TX_POWER_LEVEL_TOTAL	8
+#define MWL8K_RF_TX_POWER_LEVEL_TOTAL	8
 
 struct mwl8k_cmd_rf_tx_power {
 	struct mwl8k_cmd_pkt header;
@@ -2092,7 +2159,7 @@ struct mwl8k_cmd_rf_tx_power {
 	__le16 support_level;
 	__le16 current_level;
 	__le16 reserved;
-	__le16 power_level_list[MWL8K_TX_POWER_LEVEL_TOTAL];
+	__le16 power_level_list[MWL8K_RF_TX_POWER_LEVEL_TOTAL];
 } __packed;
 
 static int mwl8k_cmd_rf_tx_power(struct ieee80211_hw *hw, int dBm)
@@ -2116,6 +2183,65 @@ static int mwl8k_cmd_rf_tx_power(struct
 }
 
 /*
+ * CMD_TX_POWER.
+ */
+#define MWL8K_TX_POWER_LEVEL_TOTAL      12
+
+struct mwl8k_cmd_tx_power {
+	struct mwl8k_cmd_pkt header;
+	__le16 action;
+	__le16 band;
+	__le16 channel;
+	__le16 bw;
+	__le16 sub_ch;
+	__le16 power_level_list[MWL8K_TX_POWER_LEVEL_TOTAL];
+} __attribute__((packed));
+
+static int mwl8k_cmd_tx_power(struct ieee80211_hw *hw,
+				     struct ieee80211_conf *conf,
+				     unsigned short pwr)
+{
+	struct ieee80211_channel *channel = conf->channel;
+	struct mwl8k_cmd_tx_power *cmd;
+	int rc;
+	int i;
+
+	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+	if (cmd == NULL)
+		return -ENOMEM;
+
+	cmd->header.code = cpu_to_le16(MWL8K_CMD_TX_POWER);
+	cmd->header.length = cpu_to_le16(sizeof(*cmd));
+	cmd->action = cpu_to_le16(MWL8K_CMD_SET_LIST);
+
+	if (channel->band == IEEE80211_BAND_2GHZ)
+		cmd->band = cpu_to_le16(0x1);
+	else if (channel->band == IEEE80211_BAND_5GHZ)
+		cmd->band = cpu_to_le16(0x4);
+
+	cmd->channel = channel->hw_value;
+
+	if (conf->channel_type == NL80211_CHAN_NO_HT ||
+	    conf->channel_type == NL80211_CHAN_HT20) {
+		cmd->bw = cpu_to_le16(0x2);
+	} else {
+		cmd->bw = cpu_to_le16(0x4);
+		if (conf->channel_type == NL80211_CHAN_HT40MINUS)
+			cmd->sub_ch = cpu_to_le16(0x3);
+		else if (conf->channel_type == NL80211_CHAN_HT40PLUS)
+			cmd->sub_ch = cpu_to_le16(0x1);
+	}
+
+	for (i = 0; i < MWL8K_TX_POWER_LEVEL_TOTAL; i++)
+		cmd->power_level_list[i] = cpu_to_le16(pwr);
+
+	rc = mwl8k_post_cmd(hw, &cmd->header);
+	kfree(cmd);
+
+	return rc;
+}
+
+/*
  * CMD_RF_ANTENNA.
  */
 struct mwl8k_cmd_rf_antenna {
@@ -3283,13 +3409,16 @@ static void mwl8k_stop(struct ieee80211_
 		mwl8k_txq_reclaim(hw, i, INT_MAX, 1);
 }
 
+static int mwl8k_reload_firmware(struct ieee80211_hw *hw, char *fw_image);
+
 static int mwl8k_add_interface(struct ieee80211_hw *hw,
 			       struct ieee80211_vif *vif)
 {
 	struct mwl8k_priv *priv = hw->priv;
 	struct mwl8k_vif *mwl8k_vif;
 	u32 macids_supported;
-	int macid;
+	int macid, rc;
+	struct mwl8k_device_info *di;
 
 	/*
 	 * Reject interface creation if sniffer mode is active, as
@@ -3302,12 +3431,28 @@ static int mwl8k_add_interface(struct ie
 		return -EINVAL;
 	}
 
-
+	di = priv->device_info;
 	switch (vif->type) {
 	case NL80211_IFTYPE_AP:
+		if (!priv->ap_fw && di->fw_image_ap) {
+			/* we must load the ap fw to meet this request */
+			if (!list_empty(&priv->vif_list))
+				return -EBUSY;
+			rc = mwl8k_reload_firmware(hw, di->fw_image_ap);
+			if (rc)
+				return rc;
+		}
 		macids_supported = priv->ap_macids_supported;
 		break;
 	case NL80211_IFTYPE_STATION:
+		if (priv->ap_fw && di->fw_image_sta) {
+			/* we must load the sta fw to meet this request */
+			if (!list_empty(&priv->vif_list))
+				return -EBUSY;
+			rc = mwl8k_reload_firmware(hw, di->fw_image_sta);
+			if (rc)
+				return rc;
+		}
 		macids_supported = priv->sta_macids_supported;
 		break;
 	default:
@@ -3377,15 +3522,19 @@ static int mwl8k_config(struct ieee80211
 
 	if (conf->power_level > 18)
 		conf->power_level = 18;
-	rc = mwl8k_cmd_rf_tx_power(hw, conf->power_level);
-	if (rc)
-		goto out;
 
 	if (priv->ap_fw) {
+		rc = mwl8k_cmd_tx_power(hw, conf, conf->power_level);
+		if (rc)
+			goto out;
+
 		rc = mwl8k_cmd_rf_antenna(hw, MWL8K_RF_ANTENNA_RX, 0x7);
 		if (!rc)
 			rc = mwl8k_cmd_rf_antenna(hw, MWL8K_RF_ANTENNA_TX, 0x7);
 	} else {
+		rc = mwl8k_cmd_rf_tx_power(hw, conf->power_level);
+		if (rc)
+			goto out;
 		rc = mwl8k_cmd_mimo_config(hw, 0x7, 0x7);
 	}
 
@@ -3739,6 +3888,9 @@ static int mwl8k_conf_tx(struct ieee8021
 
 	rc = mwl8k_fw_lock(hw);
 	if (!rc) {
+		BUG_ON(queue > MWL8K_TX_QUEUES - 1);
+		memcpy(&priv->wmm_params[queue], params, sizeof(*params));
+
 		if (!priv->wmm_enabled)
 			rc = mwl8k_cmd_set_wmm_mode(hw, 1);
 
@@ -3838,21 +3990,27 @@ enum {
 	MWL8366,
 };
 
+#define MWL8K_8366_AP_FW_API 1
+#define _MWL8K_8366_AP_FW(api) "/*(DEBLOBBED)*/"
+#define MWL8K_8366_AP_FW(api) _MWL8K_8366_AP_FW(api)
+
 static struct mwl8k_device_info mwl8k_info_tbl[] __devinitdata = {
 	[MWL8363] = {
 		.part_name	= "88w8363",
 		.helper_image	= "/*(DEBLOBBED)*/",
-		.fw_image	= "/*(DEBLOBBED)*/",
+		.fw_image_sta	= "/*(DEBLOBBED)*/",
 	},
 	[MWL8687] = {
 		.part_name	= "88w8687",
 		.helper_image	= "/*(DEBLOBBED)*/",
-		.fw_image	= "/*(DEBLOBBED)*/",
+		.fw_image_sta	= "/*(DEBLOBBED)*/",
 	},
 	[MWL8366] = {
 		.part_name	= "88w8366",
 		.helper_image	= "/*(DEBLOBBED)*/",
-		.fw_image	= "/*(DEBLOBBED)*/",
+		.fw_image_sta	= "/*(DEBLOBBED)*/",
+		.fw_image_ap	= MWL8K_8366_AP_FW(MWL8K_8366_AP_FW_API),
+		.fw_api_ap	= MWL8K_8366_AP_FW_API,
 		.ap_rxd_ops	= &rxd_8366_ap_ops,
 	},
 };
@@ -3871,94 +4029,133 @@ static DEFINE_PCI_DEVICE_TABLE(mwl8k_pci
 };
 MODULE_DEVICE_TABLE(pci, mwl8k_pci_id_table);
 
-static int __devinit mwl8k_probe(struct pci_dev *pdev,
-				 const struct pci_device_id *id)
+static int mwl8k_request_alt_fw(struct mwl8k_priv *priv)
 {
-	static int printed_version = 0;
-	struct ieee80211_hw *hw;
-	struct mwl8k_priv *priv;
 	int rc;
-	int i;
-
-	if (!printed_version) {
-		printk(KERN_INFO "%s version %s\n", MWL8K_DESC, MWL8K_VERSION);
-		printed_version = 1;
-	}
-
-
-	rc = pci_enable_device(pdev);
+	printk(KERN_ERR "%s: Error requesting preferred fw %s.\n"
+	       "Trying alternative firmware %s\n", pci_name(priv->pdev),
+	       priv->fw_pref, priv->fw_alt);
+	rc = mwl8k_request_fw(priv, priv->fw_alt, &priv->fw_ucode, true);
 	if (rc) {
-		printk(KERN_ERR "%s: Cannot enable new PCI device\n",
-		       MWL8K_NAME);
+		printk(KERN_ERR "%s: Error requesting alt fw %s\n",
+		       pci_name(priv->pdev), priv->fw_alt);
 		return rc;
 	}
+	return 0;
+}
 
-	rc = pci_request_regions(pdev, MWL8K_NAME);
-	if (rc) {
-		printk(KERN_ERR "%s: Cannot obtain PCI resources\n",
-		       MWL8K_NAME);
-		goto err_disable_device;
-	}
-
-	pci_set_master(pdev);
-
-
-	hw = ieee80211_alloc_hw(sizeof(*priv), &mwl8k_ops);
-	if (hw == NULL) {
-		printk(KERN_ERR "%s: ieee80211 alloc failed\n", MWL8K_NAME);
-		rc = -ENOMEM;
-		goto err_free_reg;
-	}
+static int mwl8k_firmware_load_success(struct mwl8k_priv *priv);
+static void mwl8k_fw_state_machine(const struct firmware *fw, void *context)
+{
+	struct mwl8k_priv *priv = context;
+	struct mwl8k_device_info *di = priv->device_info;
+	int rc;
 
-	SET_IEEE80211_DEV(hw, &pdev->dev);
-	pci_set_drvdata(pdev, hw);
+	switch (priv->fw_state) {
+	case FW_STATE_INIT:
+		if (!fw) {
+			printk(KERN_ERR "%s: Error requesting helper fw %s\n",
+			       pci_name(priv->pdev), di->helper_image);
+			goto fail;
+		}
+		priv->fw_helper = fw;
+		rc = mwl8k_request_fw(priv, priv->fw_pref, &priv->fw_ucode,
+				      true);
+		if (rc && priv->fw_alt) {
+			rc = mwl8k_request_alt_fw(priv);
+			if (rc)
+				goto fail;
+			priv->fw_state = FW_STATE_LOADING_ALT;
+		} else if (rc)
+			goto fail;
+		else
+			priv->fw_state = FW_STATE_LOADING_PREF;
+		break;
 
-	priv = hw->priv;
-	priv->hw = hw;
-	priv->pdev = pdev;
-	priv->device_info = &mwl8k_info_tbl[id->driver_data];
+	case FW_STATE_LOADING_PREF:
+		if (!fw) {
+			if (priv->fw_alt) {
+				rc = mwl8k_request_alt_fw(priv);
+				if (rc)
+					goto fail;
+				priv->fw_state = FW_STATE_LOADING_ALT;
+			} else
+				goto fail;
+		} else {
+			priv->fw_ucode = fw;
+			rc = mwl8k_firmware_load_success(priv);
+			if (rc)
+				goto fail;
+			else
+				complete(&priv->firmware_loading_complete);
+		}
+		break;
 
+	case FW_STATE_LOADING_ALT:
+		if (!fw) {
+			printk(KERN_ERR "%s: Error requesting alt fw %s\n",
+			       pci_name(priv->pdev), di->helper_image);
+			goto fail;
+		}
+		priv->fw_ucode = fw;
+		rc = mwl8k_firmware_load_success(priv);
+		if (rc)
+			goto fail;
+		else
+			complete(&priv->firmware_loading_complete);
+		break;
 
-	priv->sram = pci_iomap(pdev, 0, 0x10000);
-	if (priv->sram == NULL) {
-		wiphy_err(hw->wiphy, "Cannot map device SRAM\n");
-		goto err_iounmap;
+	default:
+		printk(KERN_ERR "%s: Unexpected firmware loading state: %d\n",
+		       MWL8K_NAME, priv->fw_state);
+		BUG_ON(1);
 	}
 
-	/*
-	 * If BAR0 is a 32 bit BAR, the register BAR will be BAR1.
-	 * If BAR0 is a 64 bit BAR, the register BAR will be BAR2.
-	 */
-	priv->regs = pci_iomap(pdev, 1, 0x10000);
-	if (priv->regs == NULL) {
-		priv->regs = pci_iomap(pdev, 2, 0x10000);
-		if (priv->regs == NULL) {
-			wiphy_err(hw->wiphy, "Cannot map device registers\n");
-			goto err_iounmap;
-		}
-	}
+	return;
 
+fail:
+	priv->fw_state = FW_STATE_ERROR;
+	complete(&priv->firmware_loading_complete);
+	device_release_driver(&priv->pdev->dev);
+	mwl8k_release_firmware(priv);
+}
+
+static int mwl8k_init_firmware(struct ieee80211_hw *hw, char *fw_image,
+			       bool nowait)
+{
+	struct mwl8k_priv *priv = hw->priv;
+	int rc;
 
 	/* Reset firmware and hardware */
 	mwl8k_hw_reset(priv);
 
 	/* Ask userland hotplug daemon for the device firmware */
-	rc = mwl8k_reject_firmware(priv);
+	rc = mwl8k_reject_firmware(priv, fw_image, nowait);
 	if (rc) {
 		wiphy_err(hw->wiphy, "Firmware files not found\n");
-		goto err_stop_firmware;
+		return rc;
 	}
 
+	if (nowait)
+		return rc;
+
 	/* Load firmware into hardware */
 	rc = mwl8k_load_firmware(hw);
-	if (rc) {
+	if (rc)
 		wiphy_err(hw->wiphy, "Cannot start firmware\n");
-		goto err_stop_firmware;
-	}
 
 	/* Reclaim memory once firmware is successfully loaded */
 	mwl8k_release_firmware(priv);
 
+	return rc;
+}
+
+/* initialize hw after successfully loading a firmware image */
+static int mwl8k_probe_hw(struct ieee80211_hw *hw)
+{
+	struct mwl8k_priv *priv = hw->priv;
+	int rc = 0;
+	int i;
 
 	if (priv->ap_fw) {
 		priv->rxd_ops = priv->device_info->ap_rxd_ops;
@@ -3975,58 +4172,11 @@ static int __devinit mwl8k_probe(struct
 	priv->wmm_enabled = false;
 	priv->pending_tx_pkts = 0;
 
-
-	/*
-	 * Extra headroom is the size of the required DMA header
-	 * minus the size of the smallest 802.11 frame (CTS frame).
-	 */
-	hw->extra_tx_headroom =
-		sizeof(struct mwl8k_dma_data) - sizeof(struct ieee80211_cts);
-
-	hw->channel_change_time = 10;
-
-	hw->queues = MWL8K_TX_QUEUES;
-
-	/* Set rssi values to dBm */
-	hw->flags |= IEEE80211_HW_SIGNAL_DBM;
-	hw->vif_data_size = sizeof(struct mwl8k_vif);
-	hw->sta_data_size = sizeof(struct mwl8k_sta);
-
-	priv->macids_used = 0;
-	INIT_LIST_HEAD(&priv->vif_list);
-
-	/* Set default radio state and preamble */
-	priv->radio_on = 0;
-	priv->radio_short_preamble = 0;
-
-	/* Finalize join worker */
-	INIT_WORK(&priv->finalize_join_worker, mwl8k_finalize_join_worker);
-
-	/* TX reclaim and RX tasklets.  */
-	tasklet_init(&priv->poll_tx_task, mwl8k_tx_poll, (unsigned long)hw);
-	tasklet_disable(&priv->poll_tx_task);
-	tasklet_init(&priv->poll_rx_task, mwl8k_rx_poll, (unsigned long)hw);
-	tasklet_disable(&priv->poll_rx_task);
-
-	/* Power management cookie */
-	priv->cookie = pci_alloc_consistent(priv->pdev, 4, &priv->cookie_dma);
-	if (priv->cookie == NULL)
-		goto err_stop_firmware;
-
 	rc = mwl8k_rxq_init(hw, 0);
 	if (rc)
-		goto err_free_cookie;
+		goto err_stop_firmware;
 	rxq_refill(hw, 0, INT_MAX);
 
-	mutex_init(&priv->fw_mutex);
-	priv->fw_mutex_owner = NULL;
-	priv->fw_mutex_depth = 0;
-	priv->hostcmd_wait = NULL;
-
-	spin_lock_init(&priv->tx_lock);
-
-	priv->tx_wait = NULL;
-
 	for (i = 0; i < MWL8K_TX_QUEUES; i++) {
 		rc = mwl8k_txq_init(hw, i);
 		if (rc)
@@ -4066,13 +4216,6 @@ static int __devinit mwl8k_probe(struct
 		goto err_free_irq;
 	}
 
-	hw->wiphy->interface_modes = 0;
-	if (priv->ap_macids_supported)
-		hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_AP);
-	if (priv->sta_macids_supported)
-		hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_STATION);
-
-
 	/* Turn radio off */
 	rc = mwl8k_cmd_radio_disable(hw);
 	if (rc) {
@@ -4091,12 +4234,6 @@ static int __devinit mwl8k_probe(struct
 	iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK);
 	free_irq(priv->pdev->irq, hw);
 
-	rc = ieee80211_register_hw(hw);
-	if (rc) {
-		wiphy_err(hw->wiphy, "Cannot register device\n");
-		goto err_free_queues;
-	}
-
 	wiphy_info(hw->wiphy, "%s v%d, %pm, %s firmware %u.%u.%u.%u\n",
 		   priv->device_info->part_name,
 		   priv->hw_rev, hw->wiphy->perm_addr,
@@ -4115,14 +4252,238 @@ err_free_queues:
 		mwl8k_txq_deinit(hw, i);
 	mwl8k_rxq_deinit(hw, 0);
 
+err_stop_firmware:
+	mwl8k_hw_reset(priv);
+
+	return rc;
+}
+
+/*
+ * invoke mwl8k_reload_firmware to change the firmware image after the device
+ * has already been registered
+ */
+static int mwl8k_reload_firmware(struct ieee80211_hw *hw, char *fw_image)
+{
+	int i, rc = 0;
+	struct mwl8k_priv *priv = hw->priv;
+
+	mwl8k_stop(hw);
+	mwl8k_rxq_deinit(hw, 0);
+
+	for (i = 0; i < MWL8K_TX_QUEUES; i++)
+		mwl8k_txq_deinit(hw, i);
+
+	rc = mwl8k_init_firmware(hw, fw_image, false);
+	if (rc)
+		goto fail;
+
+	rc = mwl8k_probe_hw(hw);
+	if (rc)
+		goto fail;
+
+	rc = mwl8k_start(hw);
+	if (rc)
+		goto fail;
+
+	rc = mwl8k_config(hw, ~0);
+	if (rc)
+		goto fail;
+
+	for (i = 0; i < MWL8K_TX_QUEUES; i++) {
+		rc = mwl8k_conf_tx(hw, i, &priv->wmm_params[i]);
+		if (rc)
+			goto fail;
+	}
+
+	return rc;
+
+fail:
+	printk(KERN_WARNING "mwl8k: Failed to reload firmware image.\n");
+	return rc;
+}
+
+static int mwl8k_firmware_load_success(struct mwl8k_priv *priv)
+{
+	struct ieee80211_hw *hw = priv->hw;
+	int i, rc;
+
+	rc = mwl8k_load_firmware(hw);
+	mwl8k_release_firmware(priv);
+	if (rc) {
+		wiphy_err(hw->wiphy, "Cannot start firmware\n");
+		return rc;
+	}
+
+	/*
+	 * Extra headroom is the size of the required DMA header
+	 * minus the size of the smallest 802.11 frame (CTS frame).
+	 */
+	hw->extra_tx_headroom =
+		sizeof(struct mwl8k_dma_data) - sizeof(struct ieee80211_cts);
+
+	hw->channel_change_time = 10;
+
+	hw->queues = MWL8K_TX_QUEUES;
+
+	/* Set rssi values to dBm */
+	hw->flags |= IEEE80211_HW_SIGNAL_DBM;
+	hw->vif_data_size = sizeof(struct mwl8k_vif);
+	hw->sta_data_size = sizeof(struct mwl8k_sta);
+
+	priv->macids_used = 0;
+	INIT_LIST_HEAD(&priv->vif_list);
+
+	/* Set default radio state and preamble */
+	priv->radio_on = 0;
+	priv->radio_short_preamble = 0;
+
+	/* Finalize join worker */
+	INIT_WORK(&priv->finalize_join_worker, mwl8k_finalize_join_worker);
+
+	/* TX reclaim and RX tasklets.  */
+	tasklet_init(&priv->poll_tx_task, mwl8k_tx_poll, (unsigned long)hw);
+	tasklet_disable(&priv->poll_tx_task);
+	tasklet_init(&priv->poll_rx_task, mwl8k_rx_poll, (unsigned long)hw);
+	tasklet_disable(&priv->poll_rx_task);
+
+	/* Power management cookie */
+	priv->cookie = pci_alloc_consistent(priv->pdev, 4, &priv->cookie_dma);
+	if (priv->cookie == NULL)
+		return -ENOMEM;
+
+	mutex_init(&priv->fw_mutex);
+	priv->fw_mutex_owner = NULL;
+	priv->fw_mutex_depth = 0;
+	priv->hostcmd_wait = NULL;
+
+	spin_lock_init(&priv->tx_lock);
+
+	priv->tx_wait = NULL;
+
+	rc = mwl8k_probe_hw(hw);
+	if (rc)
+		goto err_free_cookie;
+
+	hw->wiphy->interface_modes = 0;
+	if (priv->ap_macids_supported || priv->device_info->fw_image_ap)
+		hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_AP);
+	if (priv->sta_macids_supported || priv->device_info->fw_image_sta)
+		hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_STATION);
+
+	rc = ieee80211_register_hw(hw);
+	if (rc) {
+		wiphy_err(hw->wiphy, "Cannot register device\n");
+		goto err_unprobe_hw;
+	}
+
+	return 0;
+
+err_unprobe_hw:
+	for (i = 0; i < MWL8K_TX_QUEUES; i++)
+		mwl8k_txq_deinit(hw, i);
+	mwl8k_rxq_deinit(hw, 0);
+
 err_free_cookie:
 	if (priv->cookie != NULL)
 		pci_free_consistent(priv->pdev, 4,
 				priv->cookie, priv->cookie_dma);
 
+	return rc;
+}
+static int __devinit mwl8k_probe(struct pci_dev *pdev,
+				 const struct pci_device_id *id)
+{
+	static int printed_version;
+	struct ieee80211_hw *hw;
+	struct mwl8k_priv *priv;
+	struct mwl8k_device_info *di;
+	int rc;
+
+	if (!printed_version) {
+		printk(KERN_INFO "%s version %s\n", MWL8K_DESC, MWL8K_VERSION);
+		printed_version = 1;
+	}
+
+
+	rc = pci_enable_device(pdev);
+	if (rc) {
+		printk(KERN_ERR "%s: Cannot enable new PCI device\n",
+		       MWL8K_NAME);
+		return rc;
+	}
+
+	rc = pci_request_regions(pdev, MWL8K_NAME);
+	if (rc) {
+		printk(KERN_ERR "%s: Cannot obtain PCI resources\n",
+		       MWL8K_NAME);
+		goto err_disable_device;
+	}
+
+	pci_set_master(pdev);
+
+
+	hw = ieee80211_alloc_hw(sizeof(*priv), &mwl8k_ops);
+	if (hw == NULL) {
+		printk(KERN_ERR "%s: ieee80211 alloc failed\n", MWL8K_NAME);
+		rc = -ENOMEM;
+		goto err_free_reg;
+	}
+
+	SET_IEEE80211_DEV(hw, &pdev->dev);
+	pci_set_drvdata(pdev, hw);
+
+	priv = hw->priv;
+	priv->hw = hw;
+	priv->pdev = pdev;
+	priv->device_info = &mwl8k_info_tbl[id->driver_data];
+
+
+	priv->sram = pci_iomap(pdev, 0, 0x10000);
+	if (priv->sram == NULL) {
+		wiphy_err(hw->wiphy, "Cannot map device SRAM\n");
+		goto err_iounmap;
+	}
+
+	/*
+	 * If BAR0 is a 32 bit BAR, the register BAR will be BAR1.
+	 * If BAR0 is a 64 bit BAR, the register BAR will be BAR2.
+	 */
+	priv->regs = pci_iomap(pdev, 1, 0x10000);
+	if (priv->regs == NULL) {
+		priv->regs = pci_iomap(pdev, 2, 0x10000);
+		if (priv->regs == NULL) {
+			wiphy_err(hw->wiphy, "Cannot map device registers\n");
+			goto err_iounmap;
+		}
+	}
+
+	/*
+	 * Choose the initial fw image depending on user input.  If a second
+	 * image is available, make it the alternative image that will be
+	 * loaded if the first one fails.
+	 */
+	init_completion(&priv->firmware_loading_complete);
+	di = priv->device_info;
+	if (ap_mode_default && di->fw_image_ap) {
+		priv->fw_pref = di->fw_image_ap;
+		priv->fw_alt = di->fw_image_sta;
+	} else if (!ap_mode_default && di->fw_image_sta) {
+		priv->fw_pref = di->fw_image_sta;
+		priv->fw_alt = di->fw_image_ap;
+	} else if (ap_mode_default && !di->fw_image_ap && di->fw_image_sta) {
+		printk(KERN_WARNING "AP fw is unavailable.  Using STA fw.");
+		priv->fw_pref = di->fw_image_sta;
+	} else if (!ap_mode_default && !di->fw_image_sta && di->fw_image_ap) {
+		printk(KERN_WARNING "STA fw is unavailable.  Using AP fw.");
+		priv->fw_pref = di->fw_image_ap;
+	}
+	rc = mwl8k_init_firmware(hw, priv->fw_pref, true);
+	if (rc)
+		goto err_stop_firmware;
+	return rc;
+
 err_stop_firmware:
 	mwl8k_hw_reset(priv);
-	mwl8k_release_firmware(priv);
 
 err_iounmap:
 	if (priv->regs != NULL)
@@ -4158,6 +4519,13 @@ static void __devexit mwl8k_remove(struc
 		return;
 	priv = hw->priv;
 
+	wait_for_completion(&priv->firmware_loading_complete);
+
+	if (priv->fw_state == FW_STATE_ERROR) {
+		mwl8k_hw_reset(priv);
+		goto unmap;
+	}
+
 	ieee80211_stop_queues(hw);
 
 	ieee80211_unregister_hw(hw);
@@ -4180,6 +4548,7 @@ static void __devexit mwl8k_remove(struc
 
 	pci_free_consistent(priv->pdev, 4, priv->cookie, priv->cookie_dma);
 
+unmap:
 	pci_iounmap(pdev, priv->regs);
 	pci_iounmap(pdev, priv->sram);
 	pci_set_drvdata(pdev, NULL);
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/orinoco/wext.c linux-libre-2.6.38-gnu1/drivers/net/wireless/orinoco/wext.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/orinoco/wext.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/orinoco/wext.c	2011-03-14 21:20:32.000000000 -0400
@@ -893,6 +893,14 @@ static int orinoco_ioctl_set_auth(struct
 		 */
 		break;
 
+	case IW_AUTH_MFP:
+		/* Management Frame Protection not supported.
+		 * Only fail if set to required.
+		 */
+		if (param->value == IW_AUTH_MFP_REQUIRED)
+			ret = -EINVAL;
+		break;
+
 	case IW_AUTH_KEY_MGMT:
 		/* wl_lkm implies value 2 == PSK for Hermes I
 		 * which ties in with WEXT
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/p54/p54pci.c linux-libre-2.6.38-gnu1/drivers/net/wireless/p54/p54pci.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/p54/p54pci.c	2013-05-03 04:01:31.000000000 -0400
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/p54/p54pci.c	2013-05-03 02:01:56.000000000 -0400
@@ -199,6 +199,7 @@ static void p54p_check_rx_ring(struct ie
 	while (i != idx) {
 		u16 len;
 		struct sk_buff *skb;
+		dma_addr_t dma_addr;
 		desc = &ring[i];
 		len = le16_to_cpu(desc->len);
 		skb = rx_buf[i];
@@ -216,17 +217,20 @@ static void p54p_check_rx_ring(struct ie
 
 			len = priv->common.rx_mtu;
 		}
+		dma_addr = le32_to_cpu(desc->host_addr);
+		pci_dma_sync_single_for_cpu(priv->pdev, dma_addr,
+			priv->common.rx_mtu + 32, PCI_DMA_FROMDEVICE);
 		skb_put(skb, len);
 
 		if (p54_rx(dev, skb)) {
-			pci_unmap_single(priv->pdev,
-					 le32_to_cpu(desc->host_addr),
-					 priv->common.rx_mtu + 32,
-					 PCI_DMA_FROMDEVICE);
+			pci_unmap_single(priv->pdev, dma_addr,
+				priv->common.rx_mtu + 32, PCI_DMA_FROMDEVICE);
 			rx_buf[i] = NULL;
-			desc->host_addr = 0;
+			desc->host_addr = cpu_to_le32(0);
 		} else {
 			skb_trim(skb, 0);
+			pci_dma_sync_single_for_device(priv->pdev, dma_addr,
+				priv->common.rx_mtu + 32, PCI_DMA_FROMDEVICE);
 			desc->len = cpu_to_le16(priv->common.rx_mtu + 32);
 		}
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/p54/p54usb.c linux-libre-2.6.38-gnu1/drivers/net/wireless/p54/p54usb.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/p54/p54usb.c	2013-05-03 04:01:36.000000000 -0400
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/p54/p54usb.c	2013-05-03 02:02:01.000000000 -0400
@@ -97,6 +97,7 @@ static struct usb_device_id p54u_table[]
 	{USB_DEVICE(0x1413, 0x5400)},   /* Telsey 802.11g USB2.0 Adapter */
 	{USB_DEVICE(0x1435, 0x0427)},	/* Inventel UR054G */
 	{USB_DEVICE(0x1668, 0x1050)},	/* Actiontec 802UIG-1 */
+	{USB_DEVICE(0x1740, 0x1000)},	/* Senao NUB-350 */
 	{USB_DEVICE(0x2001, 0x3704)},	/* DLink DWL-G122 rev A2 */
 	{USB_DEVICE(0x2001, 0x3705)},	/* D-Link DWL-G120 rev C1 */
 	{USB_DEVICE(0x413c, 0x5513)},	/* Dell WLA3310 USB Wireless Adapter */
@@ -188,7 +189,7 @@ static void p54u_rx_cb(struct urb *urb)
 static void p54u_tx_cb(struct urb *urb)
 {
 	struct sk_buff *skb = urb->context;
-	struct ieee80211_hw *dev = (struct ieee80211_hw *)
+	struct ieee80211_hw *dev =
 		usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0));
 
 	p54_free_skb(dev, skb);
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/p54/txrx.c linux-libre-2.6.38-gnu1/drivers/net/wireless/p54/txrx.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/p54/txrx.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/p54/txrx.c	2011-03-14 21:20:32.000000000 -0400
@@ -618,7 +618,7 @@ static void p54_tx_80211_header(struct p
 	else
 		*burst_possible = false;
 
-	if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ)
+	if (!(info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ))
 		*flags |= P54_HDR_FLAG_DATA_OUT_SEQNR;
 
 	if (info->flags & IEEE80211_TX_CTL_PSPOLL_RESPONSE)
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/prism54/islpci_dev.c linux-libre-2.6.38-gnu1/drivers/net/wireless/prism54/islpci_dev.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/prism54/islpci_dev.c	2013-05-03 04:01:40.000000000 -0400
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/prism54/islpci_dev.c	2013-05-03 02:02:05.000000000 -0400
@@ -628,7 +628,7 @@ islpci_alloc_memory(islpci_private *priv
 	printk(KERN_DEBUG "islpci_alloc_memory\n");
 #endif
 
-	/* remap the PCI device base address to accessable */
+	/* remap the PCI device base address to accessible */
 	if (!(priv->device_base =
 	      ioremap(pci_resource_start(priv->pdev, 0),
 		      ISL38XX_PCI_MEM_SIZE))) {
@@ -707,7 +707,7 @@ islpci_alloc_memory(islpci_private *priv
 				   PCI_DMA_FROMDEVICE);
 		if (!priv->pci_map_rx_address[counter]) {
 			/* error mapping the buffer to device
-			   accessable memory address */
+			   accessible memory address */
 			printk(KERN_ERR "failed to map skb DMA'able\n");
 			goto out_free;
 		}
@@ -771,7 +771,7 @@ islpci_free_memory(islpci_private *priv)
 		priv->data_low_rx[counter] = NULL;
 	}
 
-	/* Free the acces control list and the WPA list */
+	/* Free the access control list and the WPA list */
 	prism54_acl_clean(&priv->acl);
 	prism54_wpa_bss_ie_clean(priv);
 	mgt_clean(priv);
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/prism54/islpci_eth.c linux-libre-2.6.38-gnu1/drivers/net/wireless/prism54/islpci_eth.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/prism54/islpci_eth.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/prism54/islpci_eth.c	2011-03-14 21:20:32.000000000 -0400
@@ -450,7 +450,7 @@ islpci_eth_receive(islpci_private *priv)
 				   MAX_FRAGMENT_SIZE_RX + 2,
 				   PCI_DMA_FROMDEVICE);
 		if (unlikely(!priv->pci_map_rx_address[index])) {
-			/* error mapping the buffer to device accessable memory address */
+			/* error mapping the buffer to device accessible memory address */
 			DEBUG(SHOW_ERROR_MESSAGES,
 			      "Error mapping DMA address\n");
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/ray_cs.c linux-libre-2.6.38-gnu1/drivers/net/wireless/ray_cs.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/ray_cs.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/ray_cs.c	2011-03-14 21:20:32.000000000 -0400
@@ -1776,11 +1776,8 @@ static void ray_update_multi_list(struct
 		/* Copy the kernel's list of MC addresses to card */
 		netdev_for_each_mc_addr(ha, dev) {
 			memcpy_toio(p, ha->addr, ETH_ALEN);
-			dev_dbg(&link->dev,
-			      "ray_update_multi add addr %02x%02x%02x%02x%02x%02x\n",
-			      ha->addr[0], ha->addr[1],
-			      ha->addr[2], ha->addr[3],
-			      ha->addr[4], ha->addr[5]);
+			dev_dbg(&link->dev, "ray_update_multi add addr %pm\n",
+				ha->addr);
 			p += ETH_ALEN;
 			i++;
 		}
@@ -2015,11 +2012,8 @@ static irqreturn_t ray_interrupt(int irq
 				memcpy_fromio(&local->bss_id,
 					      prcs->var.rejoin_net_complete.
 					      bssid, ADDRLEN);
-				dev_dbg(&link->dev,
-				      "ray_cs new BSSID = %02x%02x%02x%02x%02x%02x\n",
-				      local->bss_id[0], local->bss_id[1],
-				      local->bss_id[2], local->bss_id[3],
-				      local->bss_id[4], local->bss_id[5]);
+				dev_dbg(&link->dev, "ray_cs new BSSID = %pm\n",
+					local->bss_id);
 				if (!sniffer)
 					authenticate(local);
 			}
@@ -2286,8 +2280,8 @@ static void untranslate(ray_dev_t *local
 	struct ethhdr *peth;
 	UCHAR srcaddr[ADDRLEN];
 	UCHAR destaddr[ADDRLEN];
-	static UCHAR org_bridge[3] = { 0, 0, 0xf8 };
-	static UCHAR org_1042[3] = { 0, 0, 0 };
+	static const UCHAR org_bridge[3] = { 0, 0, 0xf8 };
+	static const UCHAR org_1042[3] = { 0, 0, 0 };
 
 	memcpy(destaddr, ieee80211_get_DA(pmac), ADDRLEN);
 	memcpy(srcaddr, ieee80211_get_SA(pmac), ADDRLEN);
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/rndis_wlan.c linux-libre-2.6.38-gnu1/drivers/net/wireless/rndis_wlan.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/rndis_wlan.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/rndis_wlan.c	2011-03-14 21:20:32.000000000 -0400
@@ -129,6 +129,7 @@ MODULE_PARM_DESC(workaround_interval,
 #define OID_802_11_RTS_THRESHOLD		cpu_to_le32(0x0d01020a)
 #define OID_802_11_SUPPORTED_RATES		cpu_to_le32(0x0d01020e)
 #define OID_802_11_CONFIGURATION		cpu_to_le32(0x0d010211)
+#define OID_802_11_POWER_MODE			cpu_to_le32(0x0d010216)
 #define OID_802_11_BSSID_LIST			cpu_to_le32(0x0d010217)
 
 
@@ -156,6 +157,12 @@ MODULE_PARM_DESC(workaround_interval,
 #define RNDIS_STATUS_ADAPTER_NOT_OPEN		cpu_to_le32(0xc0010012)
 
 
+/* Known device types */
+#define RNDIS_UNKNOWN	0
+#define RNDIS_BCM4320A	1
+#define RNDIS_BCM4320B	2
+
+
 /* NDIS data structures. Taken from wpa_supplicant driver_ndis.c
  * slightly modified for datatype endianess, etc
  */
@@ -233,6 +240,12 @@ enum ndis_80211_addwep_bits {
 	NDIS_80211_ADDWEP_TRANSMIT_KEY = cpu_to_le32(1 << 31)
 };
 
+enum ndis_80211_power_mode {
+	NDIS_80211_POWER_MODE_CAM,
+	NDIS_80211_POWER_MODE_MAX_PSP,
+	NDIS_80211_POWER_MODE_FAST_PSP,
+};
+
 struct ndis_80211_auth_request {
 	__le32 length;
 	u8 bssid[6];
@@ -472,12 +485,16 @@ struct rndis_wlan_private {
 	struct mutex command_lock;
 	unsigned long work_pending;
 	int last_qual;
+	s32 cqm_rssi_thold;
+	u32 cqm_rssi_hyst;
+	int last_cqm_event_rssi;
 
 	struct ieee80211_supported_band band;
 	struct ieee80211_channel channels[ARRAY_SIZE(rndis_channels)];
 	struct ieee80211_rate rates[ARRAY_SIZE(rndis_rates)];
 	u32 cipher_suites[ARRAY_SIZE(rndis_cipher_suites)];
 
+	int device_type;
 	int caps;
 	int multicast_size;
 
@@ -493,10 +510,10 @@ struct rndis_wlan_private {
 
 	/* hardware state */
 	bool radio_on;
+	int power_mode;
 	int infra_mode;
 	bool connected;
 	u8 bssid[ETH_ALEN];
-	struct ndis_80211_ssid essid;
 	__le32 current_command_oid;
 
 	/* encryption stuff */
@@ -547,7 +564,7 @@ static int rndis_del_key(struct wiphy *w
 			 u8 key_index, bool pairwise, const u8 *mac_addr);
 
 static int rndis_set_default_key(struct wiphy *wiphy, struct net_device *netdev,
-								u8 key_index);
+				 u8 key_index, bool unicast, bool multicast);
 
 static int rndis_get_station(struct wiphy *wiphy, struct net_device *dev,
 					u8 *mac, struct station_info *sinfo);
@@ -563,7 +580,14 @@ static int rndis_del_pmksa(struct wiphy
 
 static int rndis_flush_pmksa(struct wiphy *wiphy, struct net_device *netdev);
 
-static struct cfg80211_ops rndis_config_ops = {
+static int rndis_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
+				bool enabled, int timeout);
+
+static int rndis_set_cqm_rssi_config(struct wiphy *wiphy,
+					struct net_device *dev,
+					s32 rssi_thold, u32 rssi_hyst);
+
+static const struct cfg80211_ops rndis_config_ops = {
 	.change_virtual_intf = rndis_change_virtual_intf,
 	.scan = rndis_scan,
 	.set_wiphy_params = rndis_set_wiphy_params,
@@ -582,6 +606,8 @@ static struct cfg80211_ops rndis_config_
 	.set_pmksa = rndis_set_pmksa,
 	.del_pmksa = rndis_del_pmksa,
 	.flush_pmksa = rndis_flush_pmksa,
+	.set_power_mgmt = rndis_set_power_mgmt,
+	.set_cqm_rssi_config = rndis_set_cqm_rssi_config,
 };
 
 static void *rndis_wiphy_privid = &rndis_wiphy_privid;
@@ -680,6 +706,7 @@ static const char *oid_to_string(__le32
 		OID_STR(OID_802_11_ADD_KEY);
 		OID_STR(OID_802_11_REMOVE_KEY);
 		OID_STR(OID_802_11_ASSOCIATION_INFORMATION);
+		OID_STR(OID_802_11_CAPABILITY);
 		OID_STR(OID_802_11_PMKID);
 		OID_STR(OID_802_11_NETWORK_TYPES_SUPPORTED);
 		OID_STR(OID_802_11_NETWORK_TYPE_IN_USE);
@@ -690,6 +717,7 @@ static const char *oid_to_string(__le32
 		OID_STR(OID_802_11_RTS_THRESHOLD);
 		OID_STR(OID_802_11_SUPPORTED_RATES);
 		OID_STR(OID_802_11_CONFIGURATION);
+		OID_STR(OID_802_11_POWER_MODE);
 		OID_STR(OID_802_11_BSSID_LIST);
 #undef OID_STR
 	}
@@ -810,7 +838,8 @@ exit_unlock:
 	return ret;
 }
 
-static int rndis_set_oid(struct usbnet *dev, __le32 oid, void *data, int len)
+static int rndis_set_oid(struct usbnet *dev, __le32 oid, const void *data,
+			 int len)
 {
 	struct rndis_wlan_private *priv = get_rndis_wlan_priv(dev);
 	union {
@@ -994,7 +1023,18 @@ static int level_to_qual(int level)
  */
 static int set_infra_mode(struct usbnet *usbdev, int mode);
 static void restore_keys(struct usbnet *usbdev);
-static int rndis_check_bssid_list(struct usbnet *usbdev);
+static int rndis_check_bssid_list(struct usbnet *usbdev, u8 *match_bssid,
+					bool *matched);
+
+static int rndis_start_bssid_list_scan(struct usbnet *usbdev)
+{
+	__le32 tmp;
+
+	/* Note: OID_802_11_BSSID_LIST_SCAN clears internal BSS list. */
+	tmp = cpu_to_le32(1);
+	return rndis_set_oid(usbdev, OID_802_11_BSSID_LIST_SCAN, &tmp,
+							sizeof(tmp));
+}
 
 static int set_essid(struct usbnet *usbdev, struct ndis_80211_ssid *ssid)
 {
@@ -1007,7 +1047,6 @@ static int set_essid(struct usbnet *usbd
 		return ret;
 	}
 	if (ret == 0) {
-		memcpy(&priv->essid, ssid, sizeof(priv->essid));
 		priv->radio_on = true;
 		netdev_dbg(usbdev->net, "%s(): radio_on = true\n", __func__);
 	}
@@ -1015,7 +1054,7 @@ static int set_essid(struct usbnet *usbd
 	return ret;
 }
 
-static int set_bssid(struct usbnet *usbdev, u8 bssid[ETH_ALEN])
+static int set_bssid(struct usbnet *usbdev, const u8 *bssid)
 {
 	int ret;
 
@@ -1031,7 +1070,9 @@ static int set_bssid(struct usbnet *usbd
 
 static int clear_bssid(struct usbnet *usbdev)
 {
-	u8 broadcast_mac[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+	static const u8 broadcast_mac[ETH_ALEN] = {
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff
+	};
 
 	return set_bssid(usbdev, broadcast_mac);
 }
@@ -1904,14 +1945,14 @@ static int rndis_scan(struct wiphy *wiph
 	struct usbnet *usbdev = netdev_priv(dev);
 	struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
 	int ret;
-	__le32 tmp;
+	int delay = SCAN_DELAY_JIFFIES;
 
 	netdev_dbg(usbdev->net, "cfg80211.scan\n");
 
 	/* Get current bssid list from device before new scan, as new scan
 	 * clears internal bssid list.
 	 */
-	rndis_check_bssid_list(usbdev);
+	rndis_check_bssid_list(usbdev, NULL, NULL);
 
 	if (!request)
 		return -EINVAL;
@@ -1921,13 +1962,13 @@ static int rndis_scan(struct wiphy *wiph
 
 	priv->scan_request = request;
 
-	tmp = cpu_to_le32(1);
-	ret = rndis_set_oid(usbdev, OID_802_11_BSSID_LIST_SCAN, &tmp,
-							sizeof(tmp));
+	ret = rndis_start_bssid_list_scan(usbdev);
 	if (ret == 0) {
+		if (priv->device_type == RNDIS_BCM4320A)
+			delay = HZ;
+
 		/* Wait before retrieving scan results from device */
-		queue_delayed_work(priv->workqueue, &priv->scan_work,
-			SCAN_DELAY_JIFFIES);
+		queue_delayed_work(priv->workqueue, &priv->scan_work, delay);
 	}
 
 	return ret;
@@ -1946,8 +1987,8 @@ static struct cfg80211_bss *rndis_bss_in
 	int ie_len, bssid_len;
 	u8 *ie;
 
-	netdev_dbg(usbdev->net, " found bssid: '%.32s' [%pM]\n",
-		   bssid->ssid.essid, bssid->mac);
+	netdev_dbg(usbdev->net, " found bssid: '%.32s' [%pM], len: %d\n",
+		   bssid->ssid.essid, bssid->mac, le32_to_cpu(bssid->length));
 
 	/* parse bssid structure */
 	bssid_len = le32_to_cpu(bssid->length);
@@ -1981,49 +2022,98 @@ static struct cfg80211_bss *rndis_bss_in
 		GFP_KERNEL);
 }
 
-static int rndis_check_bssid_list(struct usbnet *usbdev)
+static struct ndis_80211_bssid_ex *next_bssid_list_item(
+					struct ndis_80211_bssid_ex *bssid,
+					int *bssid_len, void *buf, int len)
+{
+	void *buf_end, *bssid_end;
+
+	buf_end = (char *)buf + len;
+	bssid_end = (char *)bssid + *bssid_len;
+
+	if ((int)(buf_end - bssid_end) < sizeof(bssid->length)) {
+		*bssid_len = 0;
+		return NULL;
+	} else {
+		bssid = (void *)((char *)bssid + *bssid_len);
+		*bssid_len = le32_to_cpu(bssid->length);
+		return bssid;
+	}
+}
+
+static bool check_bssid_list_item(struct ndis_80211_bssid_ex *bssid,
+				  int bssid_len, void *buf, int len)
+{
+	void *buf_end, *bssid_end;
+
+	if (!bssid || bssid_len <= 0 || bssid_len > len)
+		return false;
+
+	buf_end = (char *)buf + len;
+	bssid_end = (char *)bssid + bssid_len;
+
+	return (int)(buf_end - bssid_end) >= 0 && (int)(bssid_end - buf) >= 0;
+}
+
+static int rndis_check_bssid_list(struct usbnet *usbdev, u8 *match_bssid,
+					bool *matched)
 {
 	void *buf = NULL;
 	struct ndis_80211_bssid_list_ex *bssid_list;
 	struct ndis_80211_bssid_ex *bssid;
-	int ret = -EINVAL, len, count, bssid_len;
-	bool resized = false;
+	int ret = -EINVAL, len, count, bssid_len, real_count, new_len;
 
-	netdev_dbg(usbdev->net, "check_bssid_list\n");
+	netdev_dbg(usbdev->net, "%s()\n", __func__);
 
 	len = CONTROL_BUFFER_SIZE;
 resize_buf:
-	buf = kmalloc(len, GFP_KERNEL);
+	buf = kzalloc(len, GFP_KERNEL);
 	if (!buf) {
 		ret = -ENOMEM;
 		goto out;
 	}
 
-	ret = rndis_query_oid(usbdev, OID_802_11_BSSID_LIST, buf, &len);
-	if (ret != 0)
+	/* BSSID-list might have got bigger last time we checked, keep
+	 * resizing until it won't get any bigger.
+	 */
+	new_len = len;
+	ret = rndis_query_oid(usbdev, OID_802_11_BSSID_LIST, buf, &new_len);
+	if (ret != 0 || new_len < sizeof(struct ndis_80211_bssid_list_ex))
 		goto out;
 
-	if (!resized && len > CONTROL_BUFFER_SIZE) {
-		resized = true;
+	if (new_len > len) {
+		len = new_len;
 		kfree(buf);
 		goto resize_buf;
 	}
 
+	len = new_len;
+
 	bssid_list = buf;
-	bssid = bssid_list->bssid;
-	bssid_len = le32_to_cpu(bssid->length);
 	count = le32_to_cpu(bssid_list->num_items);
-	netdev_dbg(usbdev->net, "check_bssid_list: %d BSSIDs found (buflen: %d)\n",
-		   count, len);
+	real_count = 0;
+	netdev_dbg(usbdev->net, "%s(): buflen: %d\n", __func__, len);
 
-	while (count && ((void *)bssid + bssid_len) <= (buf + len)) {
-		rndis_bss_info_update(usbdev, bssid);
+	bssid_len = 0;
+	bssid = next_bssid_list_item(bssid_list->bssid, &bssid_len, buf, len);
 
-		bssid = (void *)bssid + bssid_len;
-		bssid_len = le32_to_cpu(bssid->length);
-		count--;
+	/* Device returns incorrect 'num_items'. Workaround by ignoring the
+	 * received 'num_items' and walking through full bssid buffer instead.
+	 */
+	while (check_bssid_list_item(bssid, bssid_len, buf, len)) {
+		if (rndis_bss_info_update(usbdev, bssid) && match_bssid &&
+		    matched) {
+			if (compare_ether_addr(bssid->mac, match_bssid))
+				*matched = true;
+		}
+
+		real_count++;
+		bssid = next_bssid_list_item(bssid, &bssid_len, buf, len);
 	}
 
+	netdev_dbg(usbdev->net, "%s(): num_items from device: %d, really found:"
+				" %d\n", __func__, count, real_count);
+
 out:
 	kfree(buf);
 	return ret;
@@ -2041,7 +2131,7 @@ static void rndis_get_scan_results(struc
 	if (!priv->scan_request)
 		return;
 
-	ret = rndis_check_bssid_list(usbdev);
+	ret = rndis_check_bssid_list(usbdev, NULL, NULL);
 
 	cfg80211_scan_done(priv->scan_request, ret < 0);
 
@@ -2355,7 +2445,7 @@ static int rndis_del_key(struct wiphy *w
 }
 
 static int rndis_set_default_key(struct wiphy *wiphy, struct net_device *netdev,
-								u8 key_index)
+				 u8 key_index, bool unicast, bool multicast)
 {
 	struct rndis_wlan_private *priv = wiphy_priv(wiphy);
 	struct usbnet *usbdev = priv->usbdev;
@@ -2365,6 +2455,9 @@ static int rndis_set_default_key(struct
 
 	priv->encr_tx_key_index = key_index;
 
+	if (is_wpa_key(priv, key_index))
+		return 0;
+
 	key = priv->encr_keys[key_index];
 
 	return add_wep_key(usbdev, key.material, key.len, key_index);
@@ -2495,6 +2588,139 @@ static int rndis_flush_pmksa(struct wiph
 	return rndis_set_oid(usbdev, OID_802_11_PMKID, &pmkid, sizeof(pmkid));
 }
 
+static int rndis_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
+				bool enabled, int timeout)
+{
+	struct rndis_wlan_private *priv = wiphy_priv(wiphy);
+	struct usbnet *usbdev = priv->usbdev;
+	int power_mode;
+	__le32 mode;
+	int ret;
+
+	if (priv->device_type != RNDIS_BCM4320B)
+		return -ENOTSUPP;
+
+	netdev_dbg(usbdev->net, "%s(): %s, %d\n", __func__,
+				enabled ? "enabled" : "disabled",
+				timeout);
+
+	if (enabled)
+		power_mode = NDIS_80211_POWER_MODE_FAST_PSP;
+	else
+		power_mode = NDIS_80211_POWER_MODE_CAM;
+
+	if (power_mode == priv->power_mode)
+		return 0;
+
+	priv->power_mode = power_mode;
+
+	mode = cpu_to_le32(power_mode);
+	ret = rndis_set_oid(usbdev, OID_802_11_POWER_MODE, &mode, sizeof(mode));
+
+	netdev_dbg(usbdev->net, "%s(): OID_802_11_POWER_MODE -> %d\n",
+				__func__, ret);
+
+	return ret;
+}
+
+static int rndis_set_cqm_rssi_config(struct wiphy *wiphy,
+					struct net_device *dev,
+					s32 rssi_thold, u32 rssi_hyst)
+{
+	struct rndis_wlan_private *priv = wiphy_priv(wiphy);
+
+	priv->cqm_rssi_thold = rssi_thold;
+	priv->cqm_rssi_hyst = rssi_hyst;
+	priv->last_cqm_event_rssi = 0;
+
+	return 0;
+}
+
+static void rndis_wlan_craft_connected_bss(struct usbnet *usbdev, u8 *bssid,
+					   struct ndis_80211_assoc_info *info)
+{
+	struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
+	struct ieee80211_channel *channel;
+	struct ndis_80211_conf config;
+	struct ndis_80211_ssid ssid;
+	s32 signal;
+	u64 timestamp;
+	u16 capability;
+	u16 beacon_interval;
+	__le32 rssi;
+	u8 ie_buf[34];
+	int len, ret, ie_len;
+
+	/* Get signal quality, in case of error use rssi=0 and ignore error. */
+	len = sizeof(rssi);
+	rssi = 0;
+	ret = rndis_query_oid(usbdev, OID_802_11_RSSI, &rssi, &len);
+	signal = level_to_qual(le32_to_cpu(rssi));
+
+	netdev_dbg(usbdev->net, "%s(): OID_802_11_RSSI -> %d, "
+		   "rssi:%d, qual: %d\n", __func__, ret, le32_to_cpu(rssi),
+		   level_to_qual(le32_to_cpu(rssi)));
+
+	/* Get AP capabilities */
+	if (info) {
+		capability = le16_to_cpu(info->resp_ie.capa);
+	} else {
+		/* Set atleast ESS/IBSS capability */
+		capability = (priv->infra_mode == NDIS_80211_INFRA_INFRA) ?
+				WLAN_CAPABILITY_ESS : WLAN_CAPABILITY_IBSS;
+	}
+
+	/* Get channel and beacon interval */
+	len = sizeof(config);
+	ret = rndis_query_oid(usbdev, OID_802_11_CONFIGURATION, &config, &len);
+	netdev_dbg(usbdev->net, "%s(): OID_802_11_CONFIGURATION -> %d\n",
+				__func__, ret);
+	if (ret >= 0) {
+		beacon_interval = le16_to_cpu(config.beacon_period);
+		channel = ieee80211_get_channel(priv->wdev.wiphy,
+				KHZ_TO_MHZ(le32_to_cpu(config.ds_config)));
+		if (!channel) {
+			netdev_warn(usbdev->net, "%s(): could not get channel."
+						 "\n", __func__);
+			return;
+		}
+	} else {
+		netdev_warn(usbdev->net, "%s(): could not get configuration.\n",
+					 __func__);
+		return;
+	}
+
+	/* Get SSID, in case of error, use zero length SSID and ignore error. */
+	len = sizeof(ssid);
+	memset(&ssid, 0, sizeof(ssid));
+	ret = rndis_query_oid(usbdev, OID_802_11_SSID, &ssid, &len);
+	netdev_dbg(usbdev->net, "%s(): OID_802_11_SSID -> %d, len: %d, ssid: "
+				"'%.32s'\n", __func__, ret,
+				le32_to_cpu(ssid.length), ssid.essid);
+
+	if (le32_to_cpu(ssid.length) > 32)
+		ssid.length = cpu_to_le32(32);
+
+	ie_buf[0] = WLAN_EID_SSID;
+	ie_buf[1] = le32_to_cpu(ssid.length);
+	memcpy(&ie_buf[2], ssid.essid, le32_to_cpu(ssid.length));
+
+	ie_len = le32_to_cpu(ssid.length) + 2;
+
+	/* no tsf */
+	timestamp = 0;
+
+	netdev_dbg(usbdev->net, "%s(): channel:%d(freq), bssid:[%pM], tsf:%d, "
+		"capa:%x, beacon int:%d, resp_ie(len:%d, essid:'%.32s'), "
+		"signal:%d\n", __func__, (channel ? channel->center_freq : -1),
+		bssid, (u32)timestamp, capability, beacon_interval, ie_len,
+		ssid.essid, signal);
+
+	cfg80211_inform_bss(priv->wdev.wiphy, channel, bssid,
+		timestamp, capability, beacon_interval, ie_buf, ie_len,
+		signal, GFP_KERNEL);
+}
+
 /*
  * workers, indication handlers, device poller
  */
@@ -2507,6 +2733,7 @@ static void rndis_wlan_do_link_up_work(s
 	u8 *req_ie, *resp_ie;
 	int ret, offset;
 	bool roamed = false;
+	bool match_bss;
 
 	if (priv->infra_mode == NDIS_80211_INFRA_INFRA && priv->connected) {
 		/* received media connect indication while connected, either
@@ -2558,6 +2785,13 @@ static void rndis_wlan_do_link_up_work(s
 					resp_ie_len =
 						CONTROL_BUFFER_SIZE - offset;
 			}
+		} else {
+			/* Since rndis_wlan_craft_connected_bss() might use info
+			 * later and expects info to contain valid data if
+			 * non-null, free info and set NULL here.
+			 */
+			kfree(info);
+			info = NULL;
 		}
 	} else if (WARN_ON(priv->infra_mode != NDIS_80211_INFRA_ADHOC))
 		return;
@@ -2569,13 +2803,26 @@ static void rndis_wlan_do_link_up_work(s
 	netdev_dbg(usbdev->net, "link up work: [%pM]%s\n",
 		   bssid, roamed ? " roamed" : "");
 
-	/* Internal bss list in device always contains at least the currently
+	/* Internal bss list in device should contain at least the currently
 	 * connected bss and we can get it to cfg80211 with
 	 * rndis_check_bssid_list().
-	 * NOTE: This is true for Broadcom chip, but not mentioned in RNDIS
-	 * spec.
+	 *
+	 * NDIS spec says: "If the device is associated, but the associated
+	 *  BSSID is not in its BSSID scan list, then the driver must add an
+	 *  entry for the BSSID at the end of the data that it returns in
+	 *  response to query of OID_802_11_BSSID_LIST."
+	 *
+	 * NOTE: Seems to be true for BCM4320b variant, but not BCM4320a.
 	 */
-	rndis_check_bssid_list(usbdev);
+	match_bss = false;
+	rndis_check_bssid_list(usbdev, bssid, &match_bss);
+
+	if (!is_zero_ether_addr(bssid) && !match_bss) {
+		/* Couldn't get bss from device, we need to manually craft bss
+		 * for cfg80211.
+		 */
+		rndis_wlan_craft_connected_bss(usbdev, bssid, info);
+	}
 
 	if (priv->infra_mode == NDIS_80211_INFRA_INFRA) {
 		if (!roamed)
@@ -2918,6 +3165,32 @@ static int rndis_wlan_get_caps(struct us
 	return retval;
 }
 
+static void rndis_do_cqm(struct usbnet *usbdev, s32 rssi)
+{
+	struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
+	enum nl80211_cqm_rssi_threshold_event event;
+	int thold, hyst, last_event;
+
+	if (priv->cqm_rssi_thold >= 0 || rssi >= 0)
+		return;
+	if (priv->infra_mode != NDIS_80211_INFRA_INFRA)
+		return;
+
+	last_event = priv->last_cqm_event_rssi;
+	thold = priv->cqm_rssi_thold;
+	hyst = priv->cqm_rssi_hyst;
+
+	if (rssi < thold && (last_event == 0 || rssi < last_event - hyst))
+		event = NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW;
+	else if (rssi > thold && (last_event == 0 || rssi > last_event + hyst))
+		event = NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH;
+	else
+		return;
+
+	priv->last_cqm_event_rssi = rssi;
+	cfg80211_cqm_rssi_notify(usbdev->net, event, GFP_KERNEL);
+}
+
 #define DEVICE_POLLER_JIFFIES (HZ)
 static void rndis_device_poller(struct work_struct *work)
 {
@@ -2934,13 +3207,28 @@ static void rndis_device_poller(struct w
 	 * also polls device with rndis_command() and catches for media link
 	 * indications.
 	 */
-	if (!is_associated(usbdev))
+	if (!is_associated(usbdev)) {
+		/* Workaround bad scanning in BCM4320a devices with active
+		 * background scanning when not associated.
+		 */
+		if (priv->device_type == RNDIS_BCM4320A && priv->radio_on &&
+		    !priv->scan_request) {
+			/* Get previous scan results */
+			rndis_check_bssid_list(usbdev, NULL, NULL);
+
+			/* Initiate new scan */
+			rndis_start_bssid_list_scan(usbdev);
+		}
+
 		goto end;
+	}
 
 	len = sizeof(rssi);
 	ret = rndis_query_oid(usbdev, OID_802_11_RSSI, &rssi, &len);
-	if (ret == 0)
+	if (ret == 0) {
 		priv->last_qual = level_to_qual(le32_to_cpu(rssi));
+		rndis_do_cqm(usbdev, le32_to_cpu(rssi));
+	}
 
 	netdev_dbg(usbdev->net, "dev-poller: OID_802_11_RSSI -> %d, rssi:%d, qual: %d\n",
 		   ret, le32_to_cpu(rssi), level_to_qual(le32_to_cpu(rssi)));
@@ -2992,10 +3280,12 @@ end:
 /*
  * driver/device initialization
  */
-static void rndis_copy_module_params(struct usbnet *usbdev)
+static void rndis_copy_module_params(struct usbnet *usbdev, int device_type)
 {
 	struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
 
+	priv->device_type = device_type;
+
 	priv->param_country[0] = modparam_country[0];
 	priv->param_country[1] = modparam_country[1];
 	priv->param_country[2] = 0;
@@ -3038,12 +3328,25 @@ static void rndis_copy_module_params(str
 		priv->param_workaround_interval = modparam_workaround_interval;
 }
 
+static int unknown_early_init(struct usbnet *usbdev)
+{
+	/* copy module parameters for unknown so that iwconfig reports txpower
+	 * and workaround parameter is copied to private structure correctly.
+	 */
+	rndis_copy_module_params(usbdev, RNDIS_UNKNOWN);
+
+	/* This is unknown device, so do not try set configuration parameters.
+	 */
+
+	return 0;
+}
+
 static int bcm4320a_early_init(struct usbnet *usbdev)
 {
 	/* copy module parameters for bcm4320a so that iwconfig reports txpower
 	 * and workaround parameter is copied to private structure correctly.
 	 */
-	rndis_copy_module_params(usbdev);
+	rndis_copy_module_params(usbdev, RNDIS_BCM4320A);
 
 	/* bcm4320a doesn't handle configuration parameters well. Try
 	 * set any and you get partially zeroed mac and broken device.
@@ -3057,7 +3360,7 @@ static int bcm4320b_early_init(struct us
 	struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
 	char buf[8];
 
-	rndis_copy_module_params(usbdev);
+	rndis_copy_module_params(usbdev, RNDIS_BCM4320B);
 
 	/* Early initialization settings, setting these won't have effect
 	 * if called after generic_rndis_bind().
@@ -3187,13 +3490,15 @@ static int rndis_wlan_bind(struct usbnet
 
 	set_default_iw_params(usbdev);
 
+	priv->power_mode = -1;
+
 	/* set default rts/frag */
 	rndis_set_wiphy_params(wiphy,
 			WIPHY_PARAM_FRAG_THRESHOLD | WIPHY_PARAM_RTS_THRESHOLD);
 
-	/* turn radio on */
-	priv->radio_on = true;
-	disassociate(usbdev, true);
+	/* turn radio off on init */
+	priv->radio_on = false;
+	disassociate(usbdev, false);
 	netif_carrier_off(usbdev->net);
 
 	return 0;
@@ -3320,7 +3625,7 @@ static const struct driver_info rndis_wl
 	.tx_fixup =	rndis_tx_fixup,
 	.reset =	rndis_wlan_reset,
 	.stop =		rndis_wlan_stop,
-	.early_init =	bcm4320a_early_init,
+	.early_init =	unknown_early_init,
 	.indication =	rndis_wlan_indication,
 };
 
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/rt2x00/Kconfig linux-libre-2.6.38-gnu1/drivers/net/wireless/rt2x00/Kconfig
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/rt2x00/Kconfig	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/rt2x00/Kconfig	2011-03-14 21:20:32.000000000 -0400
@@ -53,51 +53,41 @@ config RT61PCI
 
 	  When compiled as a module, this driver will be called rt61pci.
 
-config RT2800PCI_PCI
-	boolean
-	depends on PCI
-	default y
-
-config RT2800PCI_SOC
-	boolean
-	depends on RALINK_RT288X || RALINK_RT305X
-	default y
-
 config RT2800PCI
-	tristate "Ralink rt28xx/rt30xx/rt35xx (PCI/PCIe/PCMCIA) support (EXPERIMENTAL)"
-	depends on (RT2800PCI_PCI || RT2800PCI_SOC) && EXPERIMENTAL
+	tristate "Ralink rt27xx/rt28xx/rt30xx (PCI/PCIe/PCMCIA) support"
+	depends on PCI || RALINK_RT288X || RALINK_RT305X
 	select RT2800_LIB
-	select RT2X00_LIB_PCI if RT2800PCI_PCI
-	select RT2X00_LIB_SOC if RT2800PCI_SOC
+	select RT2X00_LIB_PCI if PCI
+	select RT2X00_LIB_SOC if RALINK_RT288X || RALINK_RT305X
 	select RT2X00_LIB_HT
 	select RT2X00_LIB_FIRMWARE
 	select RT2X00_LIB_CRYPTO
 	select CRC_CCITT
 	select EEPROM_93CX6
 	---help---
-	  This adds support for rt2800/rt3000/rt3500 wireless chipset family.
-	  Supported chips: RT2760, RT2790, RT2860, RT2880, RT2890 & RT3052
-
-	  This driver is non-functional at the moment and is intended for
-	  developers.
+	  This adds support for rt27xx/rt28xx/rt30xx wireless chipset family.
+	  Supported chips: RT2760, RT2790, RT2860, RT2880, RT2890, RT3052,
+			   RT3090, RT3091 & RT3092
 
 	  When compiled as a module, this driver will be called "rt2800pci.ko".
 
 if RT2800PCI
 
-config RT2800PCI_RT30XX
-	bool "rt2800pci - Include support for rt30xx (PCI/PCIe/PCMCIA) devices"
-	default y
+config RT2800PCI_RT33XX
+	bool "rt2800pci - Include support for rt33xx devices (EXPERIMENTAL)"
+	depends on EXPERIMENTAL
+	default n
 	---help---
-	  This adds support for rt30xx wireless chipset family to the
+	  This adds support for rt33xx wireless chipset family to the
 	  rt2800pci driver.
-	  Supported chips: RT3090, RT3091 & RT3092
+	  Supported chips: RT3390
 
 	  Support for these devices is non-functional at the moment and is
 	  intended for testers and developers.
 
 config RT2800PCI_RT35XX
-	bool "rt2800pci - Include support for rt35xx (PCI/PCIe/PCMCIA) devices"
+	bool "rt2800pci - Include support for rt35xx devices (EXPERIMENTAL)"
+	depends on EXPERIMENTAL
 	default n
 	---help---
 	  This adds support for rt35xx wireless chipset family to the
@@ -134,8 +124,8 @@ config RT73USB
 	  When compiled as a module, this driver will be called rt73usb.
 
 config RT2800USB
-	tristate "Ralink rt2800 (USB) support (EXPERIMENTAL)"
-	depends on USB && EXPERIMENTAL
+	tristate "Ralink rt27xx/rt28xx/rt30xx (USB) support"
+	depends on USB
 	select RT2800_LIB
 	select RT2X00_LIB_USB
 	select RT2X00_LIB_HT
@@ -143,30 +133,28 @@ config RT2800USB
 	select RT2X00_LIB_CRYPTO
 	select CRC_CCITT
 	---help---
-	  This adds experimental support for rt2800 wireless chipset family.
-	  Supported chips: RT2770, RT2870 & RT3070.
-
-	  Known issues:
-	  - support for RT2870 chips doesn't work with 802.11n APs yet
-	  - support for RT3070 chips is non-functional at the moment
+	  This adds support for rt27xx/rt28xx/rt30xx wireless chipset family.
+	  Supported chips: RT2770, RT2870 & RT3070, RT3071 & RT3072
 
 	  When compiled as a module, this driver will be called "rt2800usb.ko".
 
 if RT2800USB
 
-config RT2800USB_RT30XX
-	bool "rt2800usb - Include support for rt30xx (USB) devices"
-	default y
+config RT2800USB_RT33XX
+	bool "rt2800usb - Include support for rt33xx devices (EXPERIMENTAL)"
+	depends on EXPERIMENTAL
+	default n
 	---help---
-	  This adds support for rt30xx wireless chipset family to the
+	  This adds support for rt33xx wireless chipset family to the
 	  rt2800usb driver.
-	  Supported chips: RT3070, RT3071 & RT3072
+	  Supported chips: RT3370
 
 	  Support for these devices is non-functional at the moment and is
 	  intended for testers and developers.
 
 config RT2800USB_RT35XX
-	bool "rt2800usb - Include support for rt35xx (USB) devices"
+	bool "rt2800usb - Include support for rt35xx devices (EXPERIMENTAL)"
+	depends on EXPERIMENTAL
 	default n
 	---help---
 	  This adds support for rt35xx wireless chipset family to the
@@ -180,9 +168,9 @@ config RT2800USB_UNKNOWN
 	bool "rt2800usb - Include support for unknown (USB) devices"
 	default n
 	---help---
-	  This adds support for rt2800 family devices that are known to
-	  have a rt2800 family chipset, but for which the exact chipset
-	  is unknown.
+	  This adds support for rt2800usb devices that are known to
+	  have a rt28xx family compatible chipset, but for which the exact
+	  chipset is unknown.
 
 	  Support status for these devices is unknown, and enabling these
 	  devices may or may not work.
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/rt2x00/rt2400pci.c linux-libre-2.6.38-gnu1/drivers/net/wireless/rt2x00/rt2400pci.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/rt2x00/rt2400pci.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/rt2x00/rt2400pci.c	2011-03-14 21:20:32.000000000 -0400
@@ -633,6 +633,88 @@ static void rt2400pci_link_tuner(struct
 }
 
 /*
+ * Queue handlers.
+ */
+static void rt2400pci_start_queue(struct data_queue *queue)
+{
+	struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
+	u32 reg;
+
+	switch (queue->qid) {
+	case QID_RX:
+		rt2x00pci_register_read(rt2x00dev, RXCSR0, &reg);
+		rt2x00_set_field32(&reg, RXCSR0_DISABLE_RX, 0);
+		rt2x00pci_register_write(rt2x00dev, RXCSR0, reg);
+		break;
+	case QID_BEACON:
+		rt2x00pci_register_read(rt2x00dev, CSR14, &reg);
+		rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 1);
+		rt2x00_set_field32(&reg, CSR14_TBCN, 1);
+		rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 1);
+		rt2x00pci_register_write(rt2x00dev, CSR14, reg);
+		break;
+	default:
+		break;
+	}
+}
+
+static void rt2400pci_kick_queue(struct data_queue *queue)
+{
+	struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
+	u32 reg;
+
+	switch (queue->qid) {
+	case QID_AC_VO:
+		rt2x00pci_register_read(rt2x00dev, TXCSR0, &reg);
+		rt2x00_set_field32(&reg, TXCSR0_KICK_PRIO, 1);
+		rt2x00pci_register_write(rt2x00dev, TXCSR0, reg);
+		break;
+	case QID_AC_VI:
+		rt2x00pci_register_read(rt2x00dev, TXCSR0, &reg);
+		rt2x00_set_field32(&reg, TXCSR0_KICK_TX, 1);
+		rt2x00pci_register_write(rt2x00dev, TXCSR0, reg);
+		break;
+	case QID_ATIM:
+		rt2x00pci_register_read(rt2x00dev, TXCSR0, &reg);
+		rt2x00_set_field32(&reg, TXCSR0_KICK_ATIM, 1);
+		rt2x00pci_register_write(rt2x00dev, TXCSR0, reg);
+		break;
+	default:
+		break;
+	}
+}
+
+static void rt2400pci_stop_queue(struct data_queue *queue)
+{
+	struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
+	u32 reg;
+
+	switch (queue->qid) {
+	case QID_AC_VO:
+	case QID_AC_VI:
+	case QID_ATIM:
+		rt2x00pci_register_read(rt2x00dev, TXCSR0, &reg);
+		rt2x00_set_field32(&reg, TXCSR0_ABORT, 1);
+		rt2x00pci_register_write(rt2x00dev, TXCSR0, reg);
+		break;
+	case QID_RX:
+		rt2x00pci_register_read(rt2x00dev, RXCSR0, &reg);
+		rt2x00_set_field32(&reg, RXCSR0_DISABLE_RX, 1);
+		rt2x00pci_register_write(rt2x00dev, RXCSR0, reg);
+		break;
+	case QID_BEACON:
+		rt2x00pci_register_read(rt2x00dev, CSR14, &reg);
+		rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 0);
+		rt2x00_set_field32(&reg, CSR14_TBCN, 0);
+		rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 0);
+		rt2x00pci_register_write(rt2x00dev, CSR14, reg);
+		break;
+	default:
+		break;
+	}
+}
+
+/*
  * Initialization functions.
  */
 static bool rt2400pci_get_entry_state(struct queue_entry *entry)
@@ -878,18 +960,6 @@ static int rt2400pci_init_bbp(struct rt2
 /*
  * Device state switch handlers.
  */
-static void rt2400pci_toggle_rx(struct rt2x00_dev *rt2x00dev,
-				enum dev_state state)
-{
-	u32 reg;
-
-	rt2x00pci_register_read(rt2x00dev, RXCSR0, &reg);
-	rt2x00_set_field32(&reg, RXCSR0_DISABLE_RX,
-			   (state == STATE_RADIO_RX_OFF) ||
-			   (state == STATE_RADIO_RX_OFF_LINK));
-	rt2x00pci_register_write(rt2x00dev, RXCSR0, reg);
-}
-
 static void rt2400pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
 				 enum dev_state state)
 {
@@ -988,12 +1058,6 @@ static int rt2400pci_set_device_state(st
 	case STATE_RADIO_OFF:
 		rt2400pci_disable_radio(rt2x00dev);
 		break;
-	case STATE_RADIO_RX_ON:
-	case STATE_RADIO_RX_ON_LINK:
-	case STATE_RADIO_RX_OFF:
-	case STATE_RADIO_RX_OFF_LINK:
-		rt2400pci_toggle_rx(rt2x00dev, state);
-		break;
 	case STATE_RADIO_IRQ_ON:
 	case STATE_RADIO_IRQ_ON_ISR:
 	case STATE_RADIO_IRQ_OFF:
@@ -1125,32 +1189,6 @@ static void rt2400pci_write_beacon(struc
 	rt2x00pci_register_write(rt2x00dev, CSR14, reg);
 }
 
-static void rt2400pci_kick_tx_queue(struct data_queue *queue)
-{
-	struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
-	u32 reg;
-
-	rt2x00pci_register_read(rt2x00dev, TXCSR0, &reg);
-	rt2x00_set_field32(&reg, TXCSR0_KICK_PRIO, (queue->qid == QID_AC_BE));
-	rt2x00_set_field32(&reg, TXCSR0_KICK_TX, (queue->qid == QID_AC_BK));
-	rt2x00_set_field32(&reg, TXCSR0_KICK_ATIM, (queue->qid == QID_ATIM));
-	rt2x00pci_register_write(rt2x00dev, TXCSR0, reg);
-}
-
-static void rt2400pci_kill_tx_queue(struct data_queue *queue)
-{
-	struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
-	u32 reg;
-
-	if (queue->qid == QID_BEACON) {
-		rt2x00pci_register_write(rt2x00dev, CSR14, 0);
-	} else {
-		rt2x00pci_register_read(rt2x00dev, TXCSR0, &reg);
-		rt2x00_set_field32(&reg, TXCSR0_ABORT, 1);
-		rt2x00pci_register_write(rt2x00dev, TXCSR0, reg);
-	}
-}
-
 /*
  * RX control handlers
  */
@@ -1284,13 +1322,13 @@ static irqreturn_t rt2400pci_interrupt_t
 	 * 4 - Priority ring transmit done interrupt.
 	 */
 	if (rt2x00_get_field32(reg, CSR7_TXDONE_PRIORING))
-		rt2400pci_txdone(rt2x00dev, QID_AC_BE);
+		rt2400pci_txdone(rt2x00dev, QID_AC_VO);
 
 	/*
 	 * 5 - Tx ring transmit done interrupt.
 	 */
 	if (rt2x00_get_field32(reg, CSR7_TXDONE_TXRING))
-		rt2400pci_txdone(rt2x00dev, QID_AC_BK);
+		rt2400pci_txdone(rt2x00dev, QID_AC_VI);
 
 	/* Enable interrupts again. */
 	rt2x00dev->ops->lib->set_device_state(rt2x00dev,
@@ -1612,6 +1650,7 @@ static const struct ieee80211_ops rt2400
 	.get_tsf		= rt2400pci_get_tsf,
 	.tx_last_beacon		= rt2400pci_tx_last_beacon,
 	.rfkill_poll		= rt2x00mac_rfkill_poll,
+	.flush			= rt2x00mac_flush,
 };
 
 static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = {
@@ -1627,10 +1666,11 @@ static const struct rt2x00lib_ops rt2400
 	.link_stats		= rt2400pci_link_stats,
 	.reset_tuner		= rt2400pci_reset_tuner,
 	.link_tuner		= rt2400pci_link_tuner,
+	.start_queue		= rt2400pci_start_queue,
+	.kick_queue		= rt2400pci_kick_queue,
+	.stop_queue		= rt2400pci_stop_queue,
 	.write_tx_desc		= rt2400pci_write_tx_desc,
 	.write_beacon		= rt2400pci_write_beacon,
-	.kick_tx_queue		= rt2400pci_kick_tx_queue,
-	.kill_tx_queue		= rt2400pci_kill_tx_queue,
 	.fill_rxdone		= rt2400pci_fill_rxdone,
 	.config_filter		= rt2400pci_config_filter,
 	.config_intf		= rt2400pci_config_intf,
@@ -1640,28 +1680,28 @@ static const struct rt2x00lib_ops rt2400
 };
 
 static const struct data_queue_desc rt2400pci_queue_rx = {
-	.entry_num		= RX_ENTRIES,
+	.entry_num		= 24,
 	.data_size		= DATA_FRAME_SIZE,
 	.desc_size		= RXD_DESC_SIZE,
 	.priv_size		= sizeof(struct queue_entry_priv_pci),
 };
 
 static const struct data_queue_desc rt2400pci_queue_tx = {
-	.entry_num		= TX_ENTRIES,
+	.entry_num		= 24,
 	.data_size		= DATA_FRAME_SIZE,
 	.desc_size		= TXD_DESC_SIZE,
 	.priv_size		= sizeof(struct queue_entry_priv_pci),
 };
 
 static const struct data_queue_desc rt2400pci_queue_bcn = {
-	.entry_num		= BEACON_ENTRIES,
+	.entry_num		= 1,
 	.data_size		= MGMT_FRAME_SIZE,
 	.desc_size		= TXD_DESC_SIZE,
 	.priv_size		= sizeof(struct queue_entry_priv_pci),
 };
 
 static const struct data_queue_desc rt2400pci_queue_atim = {
-	.entry_num		= ATIM_ENTRIES,
+	.entry_num		= 8,
 	.data_size		= DATA_FRAME_SIZE,
 	.desc_size		= TXD_DESC_SIZE,
 	.priv_size		= sizeof(struct queue_entry_priv_pci),
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/rt2x00/rt2400pci.h linux-libre-2.6.38-gnu1/drivers/net/wireless/rt2x00/rt2400pci.h
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/rt2x00/rt2400pci.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/rt2x00/rt2400pci.h	2011-03-14 21:20:32.000000000 -0400
@@ -809,8 +809,8 @@
 /*
  * DMA descriptor defines.
  */
-#define TXD_DESC_SIZE			( 8 * sizeof(__le32) )
-#define RXD_DESC_SIZE			( 8 * sizeof(__le32) )
+#define TXD_DESC_SIZE			(8 * sizeof(__le32))
+#define RXD_DESC_SIZE			(8 * sizeof(__le32))
 
 /*
  * TX descriptor format for TX, PRIO, ATIM and Beacon Ring.
@@ -948,6 +948,6 @@
 	((__CLAMP_TX(__txpower) - MAX_TXPOWER) + MIN_TXPOWER)
 
 #define TXPOWER_TO_DEV(__txpower) \
-	MAX_TXPOWER - (__CLAMP_TX(__txpower) - MIN_TXPOWER)
+	(MAX_TXPOWER - (__CLAMP_TX(__txpower) - MIN_TXPOWER))
 
 #endif /* RT2400PCI_H */
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/rt2x00/rt2500pci.c linux-libre-2.6.38-gnu1/drivers/net/wireless/rt2x00/rt2500pci.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/rt2x00/rt2500pci.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/rt2x00/rt2500pci.c	2011-03-14 21:20:32.000000000 -0400
@@ -723,6 +723,88 @@ dynamic_cca_tune:
 }
 
 /*
+ * Queue handlers.
+ */
+static void rt2500pci_start_queue(struct data_queue *queue)
+{
+	struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
+	u32 reg;
+
+	switch (queue->qid) {
+	case QID_RX:
+		rt2x00pci_register_read(rt2x00dev, RXCSR0, &reg);
+		rt2x00_set_field32(&reg, RXCSR0_DISABLE_RX, 0);
+		rt2x00pci_register_write(rt2x00dev, RXCSR0, reg);
+		break;
+	case QID_BEACON:
+		rt2x00pci_register_read(rt2x00dev, CSR14, &reg);
+		rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 1);
+		rt2x00_set_field32(&reg, CSR14_TBCN, 1);
+		rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 1);
+		rt2x00pci_register_write(rt2x00dev, CSR14, reg);
+		break;
+	default:
+		break;
+	}
+}
+
+static void rt2500pci_kick_queue(struct data_queue *queue)
+{
+	struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
+	u32 reg;
+
+	switch (queue->qid) {
+	case QID_AC_VO:
+		rt2x00pci_register_read(rt2x00dev, TXCSR0, &reg);
+		rt2x00_set_field32(&reg, TXCSR0_KICK_PRIO, 1);
+		rt2x00pci_register_write(rt2x00dev, TXCSR0, reg);
+		break;
+	case QID_AC_VI:
+		rt2x00pci_register_read(rt2x00dev, TXCSR0, &reg);
+		rt2x00_set_field32(&reg, TXCSR0_KICK_TX, 1);
+		rt2x00pci_register_write(rt2x00dev, TXCSR0, reg);
+		break;
+	case QID_ATIM:
+		rt2x00pci_register_read(rt2x00dev, TXCSR0, &reg);
+		rt2x00_set_field32(&reg, TXCSR0_KICK_ATIM, 1);
+		rt2x00pci_register_write(rt2x00dev, TXCSR0, reg);
+		break;
+	default:
+		break;
+	}
+}
+
+static void rt2500pci_stop_queue(struct data_queue *queue)
+{
+	struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
+	u32 reg;
+
+	switch (queue->qid) {
+	case QID_AC_VO:
+	case QID_AC_VI:
+	case QID_ATIM:
+		rt2x00pci_register_read(rt2x00dev, TXCSR0, &reg);
+		rt2x00_set_field32(&reg, TXCSR0_ABORT, 1);
+		rt2x00pci_register_write(rt2x00dev, TXCSR0, reg);
+		break;
+	case QID_RX:
+		rt2x00pci_register_read(rt2x00dev, RXCSR0, &reg);
+		rt2x00_set_field32(&reg, RXCSR0_DISABLE_RX, 1);
+		rt2x00pci_register_write(rt2x00dev, RXCSR0, reg);
+		break;
+	case QID_BEACON:
+		rt2x00pci_register_read(rt2x00dev, CSR14, &reg);
+		rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 0);
+		rt2x00_set_field32(&reg, CSR14_TBCN, 0);
+		rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 0);
+		rt2x00pci_register_write(rt2x00dev, CSR14, reg);
+		break;
+	default:
+		break;
+	}
+}
+
+/*
  * Initialization functions.
  */
 static bool rt2500pci_get_entry_state(struct queue_entry *entry)
@@ -1033,18 +1115,6 @@ static int rt2500pci_init_bbp(struct rt2
 /*
  * Device state switch handlers.
  */
-static void rt2500pci_toggle_rx(struct rt2x00_dev *rt2x00dev,
-				enum dev_state state)
-{
-	u32 reg;
-
-	rt2x00pci_register_read(rt2x00dev, RXCSR0, &reg);
-	rt2x00_set_field32(&reg, RXCSR0_DISABLE_RX,
-			   (state == STATE_RADIO_RX_OFF) ||
-			   (state == STATE_RADIO_RX_OFF_LINK));
-	rt2x00pci_register_write(rt2x00dev, RXCSR0, reg);
-}
-
 static void rt2500pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
 				 enum dev_state state)
 {
@@ -1143,12 +1213,6 @@ static int rt2500pci_set_device_state(st
 	case STATE_RADIO_OFF:
 		rt2500pci_disable_radio(rt2x00dev);
 		break;
-	case STATE_RADIO_RX_ON:
-	case STATE_RADIO_RX_ON_LINK:
-	case STATE_RADIO_RX_OFF:
-	case STATE_RADIO_RX_OFF_LINK:
-		rt2500pci_toggle_rx(rt2x00dev, state);
-		break;
 	case STATE_RADIO_IRQ_ON:
 	case STATE_RADIO_IRQ_ON_ISR:
 	case STATE_RADIO_IRQ_OFF:
@@ -1193,9 +1257,9 @@ static void rt2500pci_write_tx_desc(stru
 
 	rt2x00_desc_read(txd, 2, &word);
 	rt2x00_set_field32(&word, TXD_W2_IV_OFFSET, IEEE80211_HEADER);
-	rt2x00_set_field32(&word, TXD_W2_AIFS, txdesc->aifs);
-	rt2x00_set_field32(&word, TXD_W2_CWMIN, txdesc->cw_min);
-	rt2x00_set_field32(&word, TXD_W2_CWMAX, txdesc->cw_max);
+	rt2x00_set_field32(&word, TXD_W2_AIFS, entry->queue->aifs);
+	rt2x00_set_field32(&word, TXD_W2_CWMIN, entry->queue->cw_min);
+	rt2x00_set_field32(&word, TXD_W2_CWMAX, entry->queue->cw_max);
 	rt2x00_desc_write(txd, 2, word);
 
 	rt2x00_desc_read(txd, 3, &word);
@@ -1279,32 +1343,6 @@ static void rt2500pci_write_beacon(struc
 	rt2x00pci_register_write(rt2x00dev, CSR14, reg);
 }
 
-static void rt2500pci_kick_tx_queue(struct data_queue *queue)
-{
-	struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
-	u32 reg;
-
-	rt2x00pci_register_read(rt2x00dev, TXCSR0, &reg);
-	rt2x00_set_field32(&reg, TXCSR0_KICK_PRIO, (queue->qid == QID_AC_BE));
-	rt2x00_set_field32(&reg, TXCSR0_KICK_TX, (queue->qid == QID_AC_BK));
-	rt2x00_set_field32(&reg, TXCSR0_KICK_ATIM, (queue->qid == QID_ATIM));
-	rt2x00pci_register_write(rt2x00dev, TXCSR0, reg);
-}
-
-static void rt2500pci_kill_tx_queue(struct data_queue *queue)
-{
-	struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
-	u32 reg;
-
-	if (queue->qid == QID_BEACON) {
-		rt2x00pci_register_write(rt2x00dev, CSR14, 0);
-	} else {
-		rt2x00pci_register_read(rt2x00dev, TXCSR0, &reg);
-		rt2x00_set_field32(&reg, TXCSR0_ABORT, 1);
-		rt2x00pci_register_write(rt2x00dev, TXCSR0, reg);
-	}
-}
-
 /*
  * RX control handlers
  */
@@ -1417,13 +1455,13 @@ static irqreturn_t rt2500pci_interrupt_t
 	 * 4 - Priority ring transmit done interrupt.
 	 */
 	if (rt2x00_get_field32(reg, CSR7_TXDONE_PRIORING))
-		rt2500pci_txdone(rt2x00dev, QID_AC_BE);
+		rt2500pci_txdone(rt2x00dev, QID_AC_VO);
 
 	/*
 	 * 5 - Tx ring transmit done interrupt.
 	 */
 	if (rt2x00_get_field32(reg, CSR7_TXDONE_TXRING))
-		rt2500pci_txdone(rt2x00dev, QID_AC_BK);
+		rt2500pci_txdone(rt2x00dev, QID_AC_VI);
 
 	/* Enable interrupts again. */
 	rt2x00dev->ops->lib->set_device_state(rt2x00dev,
@@ -1909,6 +1947,7 @@ static const struct ieee80211_ops rt2500
 	.get_tsf		= rt2500pci_get_tsf,
 	.tx_last_beacon		= rt2500pci_tx_last_beacon,
 	.rfkill_poll		= rt2x00mac_rfkill_poll,
+	.flush			= rt2x00mac_flush,
 };
 
 static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = {
@@ -1924,10 +1963,11 @@ static const struct rt2x00lib_ops rt2500
 	.link_stats		= rt2500pci_link_stats,
 	.reset_tuner		= rt2500pci_reset_tuner,
 	.link_tuner		= rt2500pci_link_tuner,
+	.start_queue		= rt2500pci_start_queue,
+	.kick_queue		= rt2500pci_kick_queue,
+	.stop_queue		= rt2500pci_stop_queue,
 	.write_tx_desc		= rt2500pci_write_tx_desc,
 	.write_beacon		= rt2500pci_write_beacon,
-	.kick_tx_queue		= rt2500pci_kick_tx_queue,
-	.kill_tx_queue		= rt2500pci_kill_tx_queue,
 	.fill_rxdone		= rt2500pci_fill_rxdone,
 	.config_filter		= rt2500pci_config_filter,
 	.config_intf		= rt2500pci_config_intf,
@@ -1937,28 +1977,28 @@ static const struct rt2x00lib_ops rt2500
 };
 
 static const struct data_queue_desc rt2500pci_queue_rx = {
-	.entry_num		= RX_ENTRIES,
+	.entry_num		= 32,
 	.data_size		= DATA_FRAME_SIZE,
 	.desc_size		= RXD_DESC_SIZE,
 	.priv_size		= sizeof(struct queue_entry_priv_pci),
 };
 
 static const struct data_queue_desc rt2500pci_queue_tx = {
-	.entry_num		= TX_ENTRIES,
+	.entry_num		= 32,
 	.data_size		= DATA_FRAME_SIZE,
 	.desc_size		= TXD_DESC_SIZE,
 	.priv_size		= sizeof(struct queue_entry_priv_pci),
 };
 
 static const struct data_queue_desc rt2500pci_queue_bcn = {
-	.entry_num		= BEACON_ENTRIES,
+	.entry_num		= 1,
 	.data_size		= MGMT_FRAME_SIZE,
 	.desc_size		= TXD_DESC_SIZE,
 	.priv_size		= sizeof(struct queue_entry_priv_pci),
 };
 
 static const struct data_queue_desc rt2500pci_queue_atim = {
-	.entry_num		= ATIM_ENTRIES,
+	.entry_num		= 8,
 	.data_size		= DATA_FRAME_SIZE,
 	.desc_size		= TXD_DESC_SIZE,
 	.priv_size		= sizeof(struct queue_entry_priv_pci),
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/rt2x00/rt2500pci.h linux-libre-2.6.38-gnu1/drivers/net/wireless/rt2x00/rt2500pci.h
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/rt2x00/rt2500pci.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/rt2x00/rt2500pci.h	2011-03-14 21:20:32.000000000 -0400
@@ -1088,8 +1088,8 @@
 /*
  * DMA descriptor defines.
  */
-#define TXD_DESC_SIZE			( 11 * sizeof(__le32) )
-#define RXD_DESC_SIZE			( 11 * sizeof(__le32) )
+#define TXD_DESC_SIZE			(11 * sizeof(__le32))
+#define RXD_DESC_SIZE			(11 * sizeof(__le32))
 
 /*
  * TX descriptor format for TX, PRIO, ATIM and Beacon Ring.
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/rt2x00/rt2500usb.c linux-libre-2.6.38-gnu1/drivers/net/wireless/rt2x00/rt2500usb.c
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/rt2x00/rt2500usb.c	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/rt2x00/rt2500usb.c	2011-03-14 21:20:32.000000000 -0400
@@ -39,7 +39,7 @@
 /*
  * Allow hardware encryption to be disabled.
  */
-static int modparam_nohwcrypt = 0;
+static int modparam_nohwcrypt;
 module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO);
 MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption.");
 
@@ -739,6 +739,55 @@ static void rt2500usb_reset_tuner(struct
 }
 
 /*
+ * Queue handlers.
+ */
+static void rt2500usb_start_queue(struct data_queue *queue)
+{
+	struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
+	u16 reg;
+
+	switch (queue->qid) {
+	case QID_RX:
+		rt2500usb_register_read(rt2x00dev, TXRX_CSR2, &reg);
+		rt2x00_set_field16(&reg, TXRX_CSR2_DISABLE_RX, 0);
+		rt2500usb_register_write(rt2x00dev, TXRX_CSR2, reg);
+		break;
+	case QID_BEACON:
+		rt2500usb_register_read(rt2x00dev, TXRX_CSR19, &reg);
+		rt2x00_set_field16(&reg, TXRX_CSR19_TSF_COUNT, 1);
+		rt2x00_set_field16(&reg, TXRX_CSR19_TBCN, 1);
+		rt2x00_set_field16(&reg, TXRX_CSR19_BEACON_GEN, 1);
+		rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg);
+		break;
+	default:
+		break;
+	}
+}
+
+static void rt2500usb_stop_queue(struct data_queue *queue)
+{
+	struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
+	u16 reg;
+
+	switch (queue->qid) {
+	case QID_RX:
+		rt2500usb_register_read(rt2x00dev, TXRX_CSR2, &reg);
+		rt2x00_set_field16(&reg, TXRX_CSR2_DISABLE_RX, 1);
+		rt2500usb_register_write(rt2x00dev, TXRX_CSR2, reg);
+		break;
+	case QID_BEACON:
+		rt2500usb_register_read(rt2x00dev, TXRX_CSR19, &reg);
+		rt2x00_set_field16(&reg, TXRX_CSR19_TSF_COUNT, 0);
+		rt2x00_set_field16(&reg, TXRX_CSR19_TBCN, 0);
+		rt2x00_set_field16(&reg, TXRX_CSR19_BEACON_GEN, 0);
+		rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg);
+		break;
+	default:
+		break;
+	}
+}
+
+/*
  * Initialization functions.
  */
 static int rt2500usb_init_registers(struct rt2x00_dev *rt2x00dev)
@@ -931,18 +980,6 @@ static int rt2500usb_init_bbp(struct rt2
 /*
  * Device state switch handlers.
  */
-static void rt2500usb_toggle_rx(struct rt2x00_dev *rt2x00dev,
-				enum dev_state state)
-{
-	u16 reg;
-
-	rt2500usb_register_read(rt2x00dev, TXRX_CSR2, &reg);
-	rt2x00_set_field16(&reg, TXRX_CSR2_DISABLE_RX,
-			   (state == STATE_RADIO_RX_OFF) ||
-			   (state == STATE_RADIO_RX_OFF_LINK));
-	rt2500usb_register_write(rt2x00dev, TXRX_CSR2, reg);
-}
-
 static int rt2500usb_enable_radio(struct rt2x00_dev *rt2x00dev)
 {
 	/*
@@ -1018,12 +1055,6 @@ static int rt2500usb_set_device_state(st
 	case STATE_RADIO_OFF:
 		rt2500usb_disable_radio(rt2x00dev);
 		break;
-	case STATE_RADIO_RX_ON:
-	case STATE_RADIO_RX_ON_LINK:
-	case STATE_RADIO_RX_OFF:
-	case STATE_RADIO_RX_OFF_LINK:
-		rt2500usb_toggle_rx(rt2x00dev, state);
-		break;
 	case STATE_RADIO_IRQ_ON:
 	case STATE_RADIO_IRQ_ON_ISR:
 	case STATE_RADIO_IRQ_OFF:
@@ -1081,9 +1112,9 @@ static void rt2500usb_write_tx_desc(stru
 
 	rt2x00_desc_read(txd, 1, &word);
 	rt2x00_set_field32(&word, TXD_W1_IV_OFFSET, txdesc->iv_offset);
-	rt2x00_set_field32(&word, TXD_W1_AIFS, txdesc->aifs);
-	rt2x00_set_field32(&word, TXD_W1_CWMIN, txdesc->cw_min);
-	rt2x00_set_field32(&word, TXD_W1_CWMAX, txdesc->cw_max);
+	rt2x00_set_field32(&word, TXD_W1_AIFS, entry->queue->aifs);
+	rt2x00_set_field32(&word, TXD_W1_CWMIN, entry->queue->cw_min);
+	rt2x00_set_field32(&word, TXD_W1_CWMAX, entry->queue->cw_max);
 	rt2x00_desc_write(txd, 1, word);
 
 	rt2x00_desc_read(txd, 2, &word);
@@ -1206,14 +1237,6 @@ static int rt2500usb_get_tx_data_len(str
 	return length;
 }
 
-static void rt2500usb_kill_tx_queue(struct data_queue *queue)
-{
-	if (queue->qid == QID_BEACON)
-		rt2500usb_register_write(queue->rt2x00dev, TXRX_CSR19, 0);
-
-	rt2x00usb_kill_tx_queue(queue);
-}
-
 /*
  * RX control handlers
  */
@@ -1801,6 +1824,7 @@ static const struct ieee80211_ops rt2500
 	.bss_info_changed	= rt2x00mac_bss_info_changed,
 	.conf_tx		= rt2x00mac_conf_tx,
 	.rfkill_poll		= rt2x00mac_rfkill_poll,
+	.flush			= rt2x00mac_flush,
 };
 
 static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = {
@@ -1813,11 +1837,13 @@ static const struct rt2x00lib_ops rt2500
 	.link_stats		= rt2500usb_link_stats,
 	.reset_tuner		= rt2500usb_reset_tuner,
 	.watchdog		= rt2x00usb_watchdog,
+	.start_queue		= rt2500usb_start_queue,
+	.kick_queue		= rt2x00usb_kick_queue,
+	.stop_queue		= rt2500usb_stop_queue,
+	.flush_queue		= rt2x00usb_flush_queue,
 	.write_tx_desc		= rt2500usb_write_tx_desc,
 	.write_beacon		= rt2500usb_write_beacon,
 	.get_tx_data_len	= rt2500usb_get_tx_data_len,
-	.kick_tx_queue		= rt2x00usb_kick_tx_queue,
-	.kill_tx_queue		= rt2500usb_kill_tx_queue,
 	.fill_rxdone		= rt2500usb_fill_rxdone,
 	.config_shared_key	= rt2500usb_config_key,
 	.config_pairwise_key	= rt2500usb_config_key,
@@ -1829,28 +1855,28 @@ static const struct rt2x00lib_ops rt2500
 };
 
 static const struct data_queue_desc rt2500usb_queue_rx = {
-	.entry_num		= RX_ENTRIES,
+	.entry_num		= 32,
 	.data_size		= DATA_FRAME_SIZE,
 	.desc_size		= RXD_DESC_SIZE,
 	.priv_size		= sizeof(struct queue_entry_priv_usb),
 };
 
 static const struct data_queue_desc rt2500usb_queue_tx = {
-	.entry_num		= TX_ENTRIES,
+	.entry_num		= 32,
 	.data_size		= DATA_FRAME_SIZE,
 	.desc_size		= TXD_DESC_SIZE,
 	.priv_size		= sizeof(struct queue_entry_priv_usb),
 };
 
 static const struct data_queue_desc rt2500usb_queue_bcn = {
-	.entry_num		= BEACON_ENTRIES,
+	.entry_num		= 1,
 	.data_size		= MGMT_FRAME_SIZE,
 	.desc_size		= TXD_DESC_SIZE,
 	.priv_size		= sizeof(struct queue_entry_priv_usb_bcn),
 };
 
 static const struct data_queue_desc rt2500usb_queue_atim = {
-	.entry_num		= ATIM_ENTRIES,
+	.entry_num		= 8,
 	.data_size		= DATA_FRAME_SIZE,
 	.desc_size		= TXD_DESC_SIZE,
 	.priv_size		= sizeof(struct queue_entry_priv_usb),
diff -druNp linux-libre-2.6.37-gnu1/drivers/net/wireless/rt2x00/rt2800.h linux-libre-2.6.38-gnu1/drivers/net/wireless/rt2x00/rt2800.h
--- linux-libre-2.6.37-gnu1/drivers/net/wireless/rt2x00/rt2800.h	2011-01-04 19:50:19.000000000 -0500
+++ linux-libre-2.6.38-gnu1/drivers/net/wireless/rt2x00/rt2800.h	2011-03-14 21:20:32.000000000 -0400
@@ -46,7 +46,11 @@
  * RF2020 2.4G B/G
  * RF3021 2.4G 1T2R
  * RF3022 2.4G 2T2R
- * RF3052 2.4G 2T2R
+ * RF3052 2.4G/5G 2T2R
+ * RF2853 2.4G/5G 3T3R
+ * RF3320 2.4G 1T1R(RT3350/RT3370/RT3390)
+ * RF3322 2.4G 2T2R(RT3352/RT3371/RT3372/RT3391/RT3392)
+ * RF3853 2.4G/5G 3T3R(RT3883/RT3563/RT3573/RT3593/RT3662)
  */
 #define RF2820				0x0001
 #define RF2850				0x0002
@@ -57,7 +61,10 @@
 #define RF3021				0x0007
 #define RF3022				0x0008
 #define RF3052				0x0009
+#define RF2853				0x000a
 #define RF3320				0x000b
+#define RF3322				0x000c
+#define RF3853				0x000d
 
 /*
  * Chipset revisions.
@@ -206,10 +213,10 @@
 
 /*
  * WMM_AIFSN_CFG: Aifsn for each EDCA AC
- * AIFSN0: AC_BE
- * AIFSN1: AC_BK
- * AIFSN2: AC_VI
- * AIFSN3: AC_VO
+ * AIFSN0: AC_VO
+ * AIFSN1: AC_VI
+ * AIFSN2: AC_BE
+ * AIFSN3: AC_BK
  */
 #define WMM_AIFSN_CFG			0x0214
 #define WMM_AIFSN_CFG_AIFSN0		FIELD32(0x0000000f)
@@ -219,10 +226,10 @@
 
 /*
  * WMM_CWMIN_CSR: CWmin for each EDCA AC
- * CWMIN0: AC_BE
- * CWMIN1: AC_BK
- * CWMIN2: AC_VI
- * CWMIN3: AC_VO
+ * CWMIN0: AC_VO
+ * CWMIN1: AC_VI
+ * CWMIN2: AC_BE
+ * CWMIN3: AC_BK
  */
 #define WMM_CWMIN_CFG			0x0218
 #define WMM_CWMIN_CFG_CWMIN0		FIELD32(0x0000000f)
@@ -232,10 +239,10 @@
 
 /*
  * WMM_CWMAX_CSR: CWmax for each EDCA AC
- * CWMAX0: AC_BE
- * CWMAX1: AC_BK
- * CWMAX2: AC_VI
- * CWMAX3: AC_VO
+ * CWMAX0: AC_VO
+ * CWMAX1: AC_VI
+ * CWMAX2: AC_BE
+ * CWMAX3: AC_BK
  */
 #define WMM_CWMAX_CFG			0x021c
 #define WMM_CWMAX_CFG_CWMAX0		FIELD32(0x0000000f)
@@ -244,18 +251,18 @@
 #define WMM_CWMAX_CFG_CWMAX3		FIELD32(0x0000f000)
 
 /*
- * AC_TXOP0: AC_BK/AC_BE TXOP register
- * AC0TXOP: AC_BK in unit of 32us
- * AC1TXOP: AC_BE in unit of 32us
+ * AC_TXOP0: AC_VO/AC_VI TXOP register
+ * AC0TXOP: AC_VO in unit of 32us
+ * AC1TXOP: AC_VI in unit of 32us
  */
 #define WMM_TXOP0_CFG			0x0220
 #define WMM_TXOP0_CFG_AC0TXOP		FIELD32(0x0000ffff)
 #define WMM_TXOP0_CFG_AC1TXOP		FIELD32(0xffff0000)
 
 /*
- * AC_TXOP1: AC_VO/AC_VI TXOP register
- * AC2TXOP: AC_VI in unit of 32us
- * AC3TXOP: AC_VO in unit of 32us
+ * AC_TXOP1: AC_BE/AC_BK TXOP register
+ * AC2TXOP: AC_BE in unit of 32us
+ * AC3TXOP: AC_BK in unit of 32us
  */
 #define WMM_TXOP1_CFG			0x0224
 #define WMM_TXOP1_CFG_AC2TXOP		FIELD32(0x0000ffff)
@@ -281,7 +288,7 @@
 #define MCU_CMD_CFG			0x022c
 
 /*
- * AC_BK 